aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors')
-rw-r--r--epan/dissectors/Makefile.am117
-rw-r--r--epan/dissectors/Makefile.common699
-rw-r--r--epan/dissectors/Makefile.nmake33
-rwxr-xr-xepan/dissectors/make-reg-dotc79
-rwxr-xr-xepan/dissectors/make-reg-dotc.py118
-rwxr-xr-xepan/dissectors/ncp2222.py14808
-rw-r--r--epan/dissectors/packet-3g-a11.c1135
-rw-r--r--epan/dissectors/packet-aarp.c362
-rw-r--r--epan/dissectors/packet-acap.c193
-rw-r--r--epan/dissectors/packet-acse.c1767
-rw-r--r--epan/dissectors/packet-acse.h191
-rw-r--r--epan/dissectors/packet-afp.c4740
-rw-r--r--epan/dissectors/packet-afp.h122
-rw-r--r--epan/dissectors/packet-afs-defs.h783
-rw-r--r--epan/dissectors/packet-afs-macros.h538
-rw-r--r--epan/dissectors/packet-afs-register-info.h585
-rw-r--r--epan/dissectors/packet-afs.c1779
-rw-r--r--epan/dissectors/packet-afs.h142
-rw-r--r--epan/dissectors/packet-aim-admin.c170
-rw-r--r--epan/dissectors/packet-aim-adverts.c121
-rw-r--r--epan/dissectors/packet-aim-bos.c175
-rw-r--r--epan/dissectors/packet-aim-buddylist.c235
-rw-r--r--epan/dissectors/packet-aim-chat.c193
-rw-r--r--epan/dissectors/packet-aim-chatnav.c139
-rw-r--r--epan/dissectors/packet-aim-directory.c124
-rw-r--r--epan/dissectors/packet-aim-generic.c561
-rw-r--r--epan/dissectors/packet-aim-icq.c130
-rw-r--r--epan/dissectors/packet-aim-invitation.c116
-rw-r--r--epan/dissectors/packet-aim-location.c259
-rw-r--r--epan/dissectors/packet-aim-messaging.c323
-rw-r--r--epan/dissectors/packet-aim-oft.c77
-rw-r--r--epan/dissectors/packet-aim-popup.c125
-rw-r--r--epan/dissectors/packet-aim-signon.c234
-rw-r--r--epan/dissectors/packet-aim-ssi.c331
-rw-r--r--epan/dissectors/packet-aim-stats.c97
-rw-r--r--epan/dissectors/packet-aim-translate.c99
-rw-r--r--epan/dissectors/packet-aim-userlookup.c127
-rw-r--r--epan/dissectors/packet-aim.c1152
-rw-r--r--epan/dissectors/packet-aim.h74
-rw-r--r--epan/dissectors/packet-ajp13.c877
-rw-r--r--epan/dissectors/packet-alcap.c1774
-rw-r--r--epan/dissectors/packet-ans.c153
-rw-r--r--epan/dissectors/packet-ansi_637.c1937
-rw-r--r--epan/dissectors/packet-ansi_683.c2093
-rw-r--r--epan/dissectors/packet-ansi_801.c956
-rw-r--r--epan/dissectors/packet-ansi_a.c8465
-rw-r--r--epan/dissectors/packet-ansi_a.h57
-rw-r--r--epan/dissectors/packet-ansi_map.c13242
-rw-r--r--epan/dissectors/packet-ansi_map.h41
-rw-r--r--epan/dissectors/packet-aodv.c979
-rw-r--r--epan/dissectors/packet-ap1394.c125
-rw-r--r--epan/dissectors/packet-ap1394.h29
-rw-r--r--epan/dissectors/packet-arcnet.c389
-rw-r--r--epan/dissectors/packet-arcnet.h29
-rw-r--r--epan/dissectors/packet-arp.c1043
-rw-r--r--epan/dissectors/packet-arp.h35
-rw-r--r--epan/dissectors/packet-asap.c665
-rw-r--r--epan/dissectors/packet-ascend.c169
-rw-r--r--epan/dissectors/packet-asf.c146
-rw-r--r--epan/dissectors/packet-atalk.c2303
-rw-r--r--epan/dissectors/packet-atalk.h53
-rw-r--r--epan/dissectors/packet-atm.c1640
-rw-r--r--epan/dissectors/packet-atm.h30
-rw-r--r--epan/dissectors/packet-auto_rp.c295
-rw-r--r--epan/dissectors/packet-bacapp.c122
-rw-r--r--epan/dissectors/packet-bacnet.c595
-rw-r--r--epan/dissectors/packet-beep.c1121
-rw-r--r--epan/dissectors/packet-ber.c1054
-rw-r--r--epan/dissectors/packet-ber.h161
-rw-r--r--epan/dissectors/packet-bfd.c273
-rw-r--r--epan/dissectors/packet-bgp.c2802
-rw-r--r--epan/dissectors/packet-bgp.h200
-rw-r--r--epan/dissectors/packet-bofl.c140
-rw-r--r--epan/dissectors/packet-bootp.c1823
-rw-r--r--epan/dissectors/packet-bootparams.c201
-rw-r--r--epan/dissectors/packet-bootparams.h13
-rw-r--r--epan/dissectors/packet-bpdu.c828
-rw-r--r--epan/dissectors/packet-brdwlk.c404
-rw-r--r--epan/dissectors/packet-bssap.c480
-rw-r--r--epan/dissectors/packet-bssap.h34
-rw-r--r--epan/dissectors/packet-bssgp.c1686
-rw-r--r--epan/dissectors/packet-bvlc.c401
-rw-r--r--epan/dissectors/packet-cast.c1776
-rw-r--r--epan/dissectors/packet-ccsds.c259
-rw-r--r--epan/dissectors/packet-cdp.c832
-rw-r--r--epan/dissectors/packet-cgmp.c143
-rw-r--r--epan/dissectors/packet-chdlc.c374
-rw-r--r--epan/dissectors/packet-chdlc.h45
-rw-r--r--epan/dissectors/packet-cisco-oui.c73
-rw-r--r--epan/dissectors/packet-clearcase.c79
-rw-r--r--epan/dissectors/packet-clearcase.h32
-rw-r--r--epan/dissectors/packet-clip.c120
-rw-r--r--epan/dissectors/packet-clip.h29
-rw-r--r--epan/dissectors/packet-clnp.c2396
-rw-r--r--epan/dissectors/packet-cops.c2637
-rw-r--r--epan/dissectors/packet-cosine.c193
-rw-r--r--epan/dissectors/packet-cpfi.c527
-rw-r--r--epan/dissectors/packet-cpha.c567
-rw-r--r--epan/dissectors/packet-cups.c391
-rw-r--r--epan/dissectors/packet-data.c71
-rw-r--r--epan/dissectors/packet-data.h29
-rw-r--r--epan/dissectors/packet-dccp.c564
-rw-r--r--epan/dissectors/packet-dccp.h415
-rw-r--r--epan/dissectors/packet-dcerpc-afs4int.c4658
-rw-r--r--epan/dissectors/packet-dcerpc-atsvc.c682
-rw-r--r--epan/dissectors/packet-dcerpc-atsvc.h39
-rw-r--r--epan/dissectors/packet-dcerpc-bossvr.c116
-rw-r--r--epan/dissectors/packet-dcerpc-browser.c1181
-rw-r--r--epan/dissectors/packet-dcerpc-browser.h42
-rw-r--r--epan/dissectors/packet-dcerpc-budb.c107
-rw-r--r--epan/dissectors/packet-dcerpc-butc.c121
-rw-r--r--epan/dissectors/packet-dcerpc-cds_clerkserver.c111
-rw-r--r--epan/dissectors/packet-dcerpc-cds_solicit.c83
-rw-r--r--epan/dissectors/packet-dcerpc-conv.c214
-rw-r--r--epan/dissectors/packet-dcerpc-cprpc_server.c82
-rw-r--r--epan/dissectors/packet-dcerpc-dce122.c4428
-rw-r--r--epan/dissectors/packet-dcerpc-dce122.h32
-rw-r--r--epan/dissectors/packet-dcerpc-dcom.h82
-rw-r--r--epan/dissectors/packet-dcerpc-dfs.c102
-rw-r--r--epan/dissectors/packet-dcerpc-dfs.h55
-rw-r--r--epan/dissectors/packet-dcerpc-dnsserver.c113
-rw-r--r--epan/dissectors/packet-dcerpc-dnsserver.h42
-rw-r--r--epan/dissectors/packet-dcerpc-drsuapi.c122
-rw-r--r--epan/dissectors/packet-dcerpc-drsuapi.h60
-rw-r--r--epan/dissectors/packet-dcerpc-dtsprovider.c87
-rw-r--r--epan/dissectors/packet-dcerpc-dtsstime_req.c82
-rw-r--r--epan/dissectors/packet-dcerpc-efs.c698
-rw-r--r--epan/dissectors/packet-dcerpc-efs.h46
-rw-r--r--epan/dissectors/packet-dcerpc-epm.c735
-rw-r--r--epan/dissectors/packet-dcerpc-epm4.c735
-rw-r--r--epan/dissectors/packet-dcerpc-eventlog.c859
-rw-r--r--epan/dissectors/packet-dcerpc-eventlog.h57
-rw-r--r--epan/dissectors/packet-dcerpc-fldb.c2142
-rw-r--r--epan/dissectors/packet-dcerpc-frsapi.c106
-rw-r--r--epan/dissectors/packet-dcerpc-frsapi.h42
-rw-r--r--epan/dissectors/packet-dcerpc-frsrpc.c114
-rw-r--r--epan/dissectors/packet-dcerpc-frsrpc.h43
-rw-r--r--epan/dissectors/packet-dcerpc-ftserver.c104
-rw-r--r--epan/dissectors/packet-dcerpc-icl_rpc.c86
-rw-r--r--epan/dissectors/packet-dcerpc-initshutdown.c212
-rw-r--r--epan/dissectors/packet-dcerpc-initshutdown.h37
-rw-r--r--epan/dissectors/packet-dcerpc-krb5rpc.c211
-rw-r--r--epan/dissectors/packet-dcerpc-llb.c90
-rw-r--r--epan/dissectors/packet-dcerpc-lsa-ds.c378
-rw-r--r--epan/dissectors/packet-dcerpc-lsa.c4541
-rw-r--r--epan/dissectors/packet-dcerpc-lsa.h145
-rw-r--r--epan/dissectors/packet-dcerpc-mapi.c476
-rw-r--r--epan/dissectors/packet-dcerpc-mapi.h41
-rw-r--r--epan/dissectors/packet-dcerpc-messenger.c147
-rw-r--r--epan/dissectors/packet-dcerpc-mgmt.c80
-rw-r--r--epan/dissectors/packet-dcerpc-ndr.c273
-rw-r--r--epan/dissectors/packet-dcerpc-netlogon.c7666
-rw-r--r--epan/dissectors/packet-dcerpc-netlogon.h90
-rw-r--r--epan/dissectors/packet-dcerpc-nspi.c116
-rw-r--r--epan/dissectors/packet-dcerpc-nt.c1509
-rw-r--r--epan/dissectors/packet-dcerpc-nt.h210
-rw-r--r--epan/dissectors/packet-dcerpc-oxid.c282
-rw-r--r--epan/dissectors/packet-dcerpc-rdaclif.c94
-rw-r--r--epan/dissectors/packet-dcerpc-reg.c926
-rw-r--r--epan/dissectors/packet-dcerpc-reg.h84
-rw-r--r--epan/dissectors/packet-dcerpc-remact.c77
-rw-r--r--epan/dissectors/packet-dcerpc-rep_proc.c93
-rw-r--r--epan/dissectors/packet-dcerpc-roverride.c88
-rw-r--r--epan/dissectors/packet-dcerpc-rpriv.c152
-rw-r--r--epan/dissectors/packet-dcerpc-rs_acct.c168
-rw-r--r--epan/dissectors/packet-dcerpc-rs_attr.c90
-rw-r--r--epan/dissectors/packet-dcerpc-rs_attr_schema.c95
-rw-r--r--epan/dissectors/packet-dcerpc-rs_bind.c89
-rw-r--r--epan/dissectors/packet-dcerpc-rs_misc.c131
-rw-r--r--epan/dissectors/packet-dcerpc-rs_pgo.c1900
-rw-r--r--epan/dissectors/packet-dcerpc-rs_plcy.c99
-rw-r--r--epan/dissectors/packet-dcerpc-rs_prop_acct.c83
-rw-r--r--epan/dissectors/packet-dcerpc-rs_prop_acl.c88
-rw-r--r--epan/dissectors/packet-dcerpc-rs_prop_attr.c88
-rw-r--r--epan/dissectors/packet-dcerpc-rs_prop_pgo.c93
-rw-r--r--epan/dissectors/packet-dcerpc-rs_prop_plcy.c91
-rw-r--r--epan/dissectors/packet-dcerpc-rs_pwd_mgmt.c95
-rw-r--r--epan/dissectors/packet-dcerpc-rs_repadm.c96
-rw-r--r--epan/dissectors/packet-dcerpc-rs_replist.c92
-rw-r--r--epan/dissectors/packet-dcerpc-rs_repmgr.c95
-rw-r--r--epan/dissectors/packet-dcerpc-rs_unix.c82
-rw-r--r--epan/dissectors/packet-dcerpc-rsec_login.c81
-rw-r--r--epan/dissectors/packet-dcerpc-samr.c5636
-rw-r--r--epan/dissectors/packet-dcerpc-samr.h145
-rw-r--r--epan/dissectors/packet-dcerpc-secidmap.c88
-rw-r--r--epan/dissectors/packet-dcerpc-spoolss.c8226
-rw-r--r--epan/dissectors/packet-dcerpc-spoolss.h574
-rw-r--r--epan/dissectors/packet-dcerpc-srvsvc.c7485
-rw-r--r--epan/dissectors/packet-dcerpc-srvsvc.h89
-rw-r--r--epan/dissectors/packet-dcerpc-svcctl.c618
-rw-r--r--epan/dissectors/packet-dcerpc-svcctl.h74
-rw-r--r--epan/dissectors/packet-dcerpc-tapi.c248
-rw-r--r--epan/dissectors/packet-dcerpc-tapi.h33
-rw-r--r--epan/dissectors/packet-dcerpc-tkn4int.c92
-rw-r--r--epan/dissectors/packet-dcerpc-trksvr.c99
-rw-r--r--epan/dissectors/packet-dcerpc-ubikdisk.c95
-rw-r--r--epan/dissectors/packet-dcerpc-ubikvote.c90
-rw-r--r--epan/dissectors/packet-dcerpc-update.c91
-rw-r--r--epan/dissectors/packet-dcerpc-wkssvc.c1796
-rw-r--r--epan/dissectors/packet-dcerpc-wkssvc.h66
-rw-r--r--epan/dissectors/packet-dcerpc.c4779
-rw-r--r--epan/dissectors/packet-dcerpc.h346
-rw-r--r--epan/dissectors/packet-dcm.c1234
-rw-r--r--epan/dissectors/packet-ddtp.c220
-rw-r--r--epan/dissectors/packet-ddtp.h56
-rw-r--r--epan/dissectors/packet-dec-bpdu.c300
-rw-r--r--epan/dissectors/packet-dhcpv6.c795
-rw-r--r--epan/dissectors/packet-diameter-defs.h807
-rw-r--r--epan/dissectors/packet-diameter.c1965
-rw-r--r--epan/dissectors/packet-diffserv-mpls-common.c114
-rw-r--r--epan/dissectors/packet-diffserv-mpls-common.h52
-rw-r--r--epan/dissectors/packet-distcc.c440
-rw-r--r--epan/dissectors/packet-dlsw.c435
-rw-r--r--epan/dissectors/packet-dnp.c775
-rw-r--r--epan/dissectors/packet-dns.c2513
-rw-r--r--epan/dissectors/packet-dns.h40
-rw-r--r--epan/dissectors/packet-dsi.c846
-rw-r--r--epan/dissectors/packet-dvmrp.c801
-rw-r--r--epan/dissectors/packet-dvmrp.h31
-rw-r--r--epan/dissectors/packet-e164.c433
-rw-r--r--epan/dissectors/packet-e164.h50
-rw-r--r--epan/dissectors/packet-eap.c1166
-rw-r--r--epan/dissectors/packet-eapol.c431
-rw-r--r--epan/dissectors/packet-echo.c128
-rw-r--r--epan/dissectors/packet-edonkey.c1435
-rw-r--r--epan/dissectors/packet-edonkey.h209
-rw-r--r--epan/dissectors/packet-eigrp.c509
-rw-r--r--epan/dissectors/packet-enc.c206
-rw-r--r--epan/dissectors/packet-enip.c2678
-rw-r--r--epan/dissectors/packet-enrp.c904
-rw-r--r--epan/dissectors/packet-esis.c452
-rw-r--r--epan/dissectors/packet-esis.h60
-rw-r--r--epan/dissectors/packet-eth.c471
-rw-r--r--epan/dissectors/packet-eth.h38
-rw-r--r--epan/dissectors/packet-etherip.c126
-rw-r--r--epan/dissectors/packet-ethertype.c300
-rw-r--r--epan/dissectors/packet-fc.c1454
-rw-r--r--epan/dissectors/packet-fc.h152
-rw-r--r--epan/dissectors/packet-fcbls.h77
-rw-r--r--epan/dissectors/packet-fcct.c307
-rw-r--r--epan/dissectors/packet-fcct.h97
-rw-r--r--epan/dissectors/packet-fcdns.c1939
-rw-r--r--epan/dissectors/packet-fcdns.h229
-rw-r--r--epan/dissectors/packet-fcels.c2003
-rw-r--r--epan/dissectors/packet-fcels.h326
-rw-r--r--epan/dissectors/packet-fcfcs.c1184
-rw-r--r--epan/dissectors/packet-fcfcs.h256
-rw-r--r--epan/dissectors/packet-fcfzs.c924
-rw-r--r--epan/dissectors/packet-fcfzs.h121
-rw-r--r--epan/dissectors/packet-fcip.c680
-rw-r--r--epan/dissectors/packet-fclctl.c176
-rw-r--r--epan/dissectors/packet-fclctl.h96
-rw-r--r--epan/dissectors/packet-fcp.c690
-rw-r--r--epan/dissectors/packet-fcp.h69
-rw-r--r--epan/dissectors/packet-fcsb3.c1001
-rw-r--r--epan/dissectors/packet-fcsb3.h74
-rw-r--r--epan/dissectors/packet-fcsp.c574
-rw-r--r--epan/dissectors/packet-fcsp.h57
-rw-r--r--epan/dissectors/packet-fcswils.c1923
-rw-r--r--epan/dissectors/packet-fcswils.h181
-rw-r--r--epan/dissectors/packet-fddi.c498
-rw-r--r--epan/dissectors/packet-fddi.h35
-rw-r--r--epan/dissectors/packet-fix.c6265
-rw-r--r--epan/dissectors/packet-fr.c740
-rw-r--r--epan/dissectors/packet-frame.c342
-rw-r--r--epan/dissectors/packet-frame.h49
-rw-r--r--epan/dissectors/packet-ftam.c3671
-rw-r--r--epan/dissectors/packet-ftam.h430
-rw-r--r--epan/dissectors/packet-ftp.c644
-rw-r--r--epan/dissectors/packet-fw1.c300
-rw-r--r--epan/dissectors/packet-gift.c160
-rw-r--r--epan/dissectors/packet-giop.c5654
-rw-r--r--epan/dissectors/packet-giop.h603
-rw-r--r--epan/dissectors/packet-gmrp.c399
-rw-r--r--epan/dissectors/packet-gnutella.c761
-rw-r--r--epan/dissectors/packet-gnutella.h80
-rw-r--r--epan/dissectors/packet-gprs-llc.c388
-rw-r--r--epan/dissectors/packet-gprs-ns.c366
-rw-r--r--epan/dissectors/packet-gre.c388
-rw-r--r--epan/dissectors/packet-gsm_a.c11377
-rw-r--r--epan/dissectors/packet-gsm_a.h77
-rw-r--r--epan/dissectors/packet-gsm_map.c3150
-rw-r--r--epan/dissectors/packet-gsm_map.h42
-rw-r--r--epan/dissectors/packet-gsm_sms.c2628
-rw-r--r--epan/dissectors/packet-gsm_sms.h29
-rw-r--r--epan/dissectors/packet-gsm_sms_ud.c639
-rw-r--r--epan/dissectors/packet-gsm_ss.c2490
-rw-r--r--epan/dissectors/packet-gsm_ss.h40
-rw-r--r--epan/dissectors/packet-gssapi.c479
-rw-r--r--epan/dissectors/packet-gssapi.h52
-rw-r--r--epan/dissectors/packet-gtp.c4600
-rw-r--r--epan/dissectors/packet-gtp.h34
-rw-r--r--epan/dissectors/packet-gvrp.c349
-rw-r--r--epan/dissectors/packet-h1.c320
-rw-r--r--epan/dissectors/packet-h225.c10748
-rw-r--r--epan/dissectors/packet-h225.h70
-rw-r--r--epan/dissectors/packet-h235.c1232
-rw-r--r--epan/dissectors/packet-h235.h59
-rw-r--r--epan/dissectors/packet-h245.c22458
-rw-r--r--epan/dissectors/packet-h245.h36
-rw-r--r--epan/dissectors/packet-h261.c263
-rw-r--r--epan/dissectors/packet-h263.c541
-rw-r--r--epan/dissectors/packet-h450.c1369
-rw-r--r--epan/dissectors/packet-hclnfsd.c879
-rw-r--r--epan/dissectors/packet-hclnfsd.h48
-rw-r--r--epan/dissectors/packet-hpext.c132
-rw-r--r--epan/dissectors/packet-hpext.h28
-rw-r--r--epan/dissectors/packet-hsrp.c239
-rw-r--r--epan/dissectors/packet-http.c1759
-rw-r--r--epan/dissectors/packet-http.h37
-rw-r--r--epan/dissectors/packet-hyperscsi.c223
-rw-r--r--epan/dissectors/packet-iapp.c554
-rw-r--r--epan/dissectors/packet-iax2.c1855
-rw-r--r--epan/dissectors/packet-iax2.h133
-rw-r--r--epan/dissectors/packet-ib.c239
-rw-r--r--epan/dissectors/packet-icap.c340
-rw-r--r--epan/dissectors/packet-icmpv6.c1661
-rw-r--r--epan/dissectors/packet-icp.c254
-rw-r--r--epan/dissectors/packet-icq.c2222
-rw-r--r--epan/dissectors/packet-ieee80211.c3445
-rw-r--r--epan/dissectors/packet-ieee80211.h34
-rw-r--r--epan/dissectors/packet-ieee8023.c121
-rw-r--r--epan/dissectors/packet-ieee8023.h34
-rw-r--r--epan/dissectors/packet-igap.c330
-rw-r--r--epan/dissectors/packet-igap.h35
-rw-r--r--epan/dissectors/packet-igmp.c1097
-rw-r--r--epan/dissectors/packet-igmp.h32
-rw-r--r--epan/dissectors/packet-igrp.c249
-rw-r--r--epan/dissectors/packet-image-gif.c711
-rw-r--r--epan/dissectors/packet-image-jfif.c1198
-rw-r--r--epan/dissectors/packet-imap.c192
-rw-r--r--epan/dissectors/packet-ip.c1897
-rw-r--r--epan/dissectors/packet-ip.h48
-rw-r--r--epan/dissectors/packet-ipdc.c442
-rw-r--r--epan/dissectors/packet-ipdc.h652
-rw-r--r--epan/dissectors/packet-ipfc.c140
-rw-r--r--epan/dissectors/packet-ipfc.h29
-rw-r--r--epan/dissectors/packet-ipmi.c656
-rw-r--r--epan/dissectors/packet-ipp.c628
-rw-r--r--epan/dissectors/packet-ipsec-udp.c107
-rw-r--r--epan/dissectors/packet-ipsec.c359
-rw-r--r--epan/dissectors/packet-ipsec.h31
-rw-r--r--epan/dissectors/packet-ipv6.c960
-rw-r--r--epan/dissectors/packet-ipv6.h540
-rw-r--r--epan/dissectors/packet-ipvs-syncd.c353
-rw-r--r--epan/dissectors/packet-ipx.c1580
-rw-r--r--epan/dissectors/packet-ipx.h178
-rw-r--r--epan/dissectors/packet-ipxwan.c465
-rw-r--r--epan/dissectors/packet-irc.c162
-rw-r--r--epan/dissectors/packet-isakmp.c1720
-rw-r--r--epan/dissectors/packet-iscsi.c2511
-rw-r--r--epan/dissectors/packet-isdn.c216
-rw-r--r--epan/dissectors/packet-isis-clv.c590
-rw-r--r--epan/dissectors/packet-isis-clv.h114
-rw-r--r--epan/dissectors/packet-isis-hello.c928
-rw-r--r--epan/dissectors/packet-isis-hello.h57
-rw-r--r--epan/dissectors/packet-isis-lsp.c2008
-rw-r--r--epan/dissectors/packet-isis-lsp.h88
-rw-r--r--epan/dissectors/packet-isis-snp.c595
-rw-r--r--epan/dissectors/packet-isis-snp.h40
-rw-r--r--epan/dissectors/packet-isis.c329
-rw-r--r--epan/dissectors/packet-isis.h60
-rw-r--r--epan/dissectors/packet-isl.c341
-rw-r--r--epan/dissectors/packet-isl.h29
-rw-r--r--epan/dissectors/packet-ismp.c874
-rw-r--r--epan/dissectors/packet-isns.c1922
-rw-r--r--epan/dissectors/packet-isup.c6352
-rw-r--r--epan/dissectors/packet-isup.h41
-rw-r--r--epan/dissectors/packet-iua.c909
-rw-r--r--epan/dissectors/packet-jabber.c143
-rw-r--r--epan/dissectors/packet-kadm5.c146
-rw-r--r--epan/dissectors/packet-kerberos.c4173
-rw-r--r--epan/dissectors/packet-kerberos.h46
-rw-r--r--epan/dissectors/packet-klm.c267
-rw-r--r--epan/dissectors/packet-klm.h34
-rw-r--r--epan/dissectors/packet-kpasswd.c167
-rw-r--r--epan/dissectors/packet-l2tp.c1082
-rw-r--r--epan/dissectors/packet-lapb.c250
-rw-r--r--epan/dissectors/packet-lapbether.c109
-rw-r--r--epan/dissectors/packet-lapd.c296
-rw-r--r--epan/dissectors/packet-laplink.c261
-rw-r--r--epan/dissectors/packet-ldap.c3006
-rw-r--r--epan/dissectors/packet-ldap.h90
-rw-r--r--epan/dissectors/packet-ldp.c3140
-rw-r--r--epan/dissectors/packet-ldp.h34
-rw-r--r--epan/dissectors/packet-llc.c750
-rw-r--r--epan/dissectors/packet-llc.h39
-rw-r--r--epan/dissectors/packet-lmi.c256
-rw-r--r--epan/dissectors/packet-lmp.c2306
-rw-r--r--epan/dissectors/packet-lpd.c196
-rw-r--r--epan/dissectors/packet-lwapp.c589
-rw-r--r--epan/dissectors/packet-m2pa.c465
-rw-r--r--epan/dissectors/packet-m2tp.c677
-rw-r--r--epan/dissectors/packet-m2ua.c1160
-rw-r--r--epan/dissectors/packet-m3ua.c2008
-rw-r--r--epan/dissectors/packet-mbtcp.c692
-rw-r--r--epan/dissectors/packet-mdshdr.c387
-rw-r--r--epan/dissectors/packet-media.c88
-rw-r--r--epan/dissectors/packet-mip.c519
-rw-r--r--epan/dissectors/packet-mip6.c692
-rw-r--r--epan/dissectors/packet-mip6.h211
-rw-r--r--epan/dissectors/packet-mmse.c1670
-rw-r--r--epan/dissectors/packet-mount.c1109
-rw-r--r--epan/dissectors/packet-mount.h21
-rw-r--r--epan/dissectors/packet-mpeg1.c394
-rw-r--r--epan/dissectors/packet-mpls-echo.c526
-rw-r--r--epan/dissectors/packet-mpls.c284
-rw-r--r--epan/dissectors/packet-mq-pcf.c318
-rw-r--r--epan/dissectors/packet-mq.c3285
-rw-r--r--epan/dissectors/packet-mq.h36
-rw-r--r--epan/dissectors/packet-mrdisc.c293
-rw-r--r--epan/dissectors/packet-mrdisc.h31
-rw-r--r--epan/dissectors/packet-msdp.c585
-rw-r--r--epan/dissectors/packet-msn-messenger.c153
-rw-r--r--epan/dissectors/packet-msnip.c334
-rw-r--r--epan/dissectors/packet-msnip.h31
-rw-r--r--epan/dissectors/packet-msproxy.c1291
-rw-r--r--epan/dissectors/packet-mtp2.c219
-rw-r--r--epan/dissectors/packet-mtp3.c694
-rw-r--r--epan/dissectors/packet-mtp3.h83
-rw-r--r--epan/dissectors/packet-mtp3mg.c1244
-rw-r--r--epan/dissectors/packet-multipart.c933
-rw-r--r--epan/dissectors/packet-mysql.c819
-rw-r--r--epan/dissectors/packet-nbipx.c802
-rw-r--r--epan/dissectors/packet-nbns.c1926
-rw-r--r--epan/dissectors/packet-ncp-int.h142
-rw-r--r--epan/dissectors/packet-ncp-nmas.c734
-rw-r--r--epan/dissectors/packet-ncp-nmas.h36
-rw-r--r--epan/dissectors/packet-ncp.c1052
-rw-r--r--epan/dissectors/packet-ncp2222.inc8650
-rw-r--r--epan/dissectors/packet-ndmp.c3493
-rw-r--r--epan/dissectors/packet-ndps.c8886
-rw-r--r--epan/dissectors/packet-ndps.h1852
-rw-r--r--epan/dissectors/packet-netbios.c1430
-rw-r--r--epan/dissectors/packet-netbios.h46
-rw-r--r--epan/dissectors/packet-netflow.c1767
-rw-r--r--epan/dissectors/packet-nfs.c8794
-rw-r--r--epan/dissectors/packet-nfs.h132
-rw-r--r--epan/dissectors/packet-nfsacl.c638
-rw-r--r--epan/dissectors/packet-nfsauth.c85
-rw-r--r--epan/dissectors/packet-nisplus.c1959
-rw-r--r--epan/dissectors/packet-nisplus.h64
-rw-r--r--epan/dissectors/packet-nlm.c1237
-rw-r--r--epan/dissectors/packet-nlm.h40
-rw-r--r--epan/dissectors/packet-nlsp.c1659
-rw-r--r--epan/dissectors/packet-nntp.c148
-rw-r--r--epan/dissectors/packet-nt-oui.c54
-rw-r--r--epan/dissectors/packet-nt-sonmp.c337
-rw-r--r--epan/dissectors/packet-nt-tpcp.c257
-rw-r--r--epan/dissectors/packet-ntlmssp.c1612
-rw-r--r--epan/dissectors/packet-ntp.c954
-rw-r--r--epan/dissectors/packet-ntp.h38
-rw-r--r--epan/dissectors/packet-null.c487
-rw-r--r--epan/dissectors/packet-null.h29
-rw-r--r--epan/dissectors/packet-olsr.c683
-rw-r--r--epan/dissectors/packet-osi-options.c460
-rw-r--r--epan/dissectors/packet-osi-options.h36
-rw-r--r--epan/dissectors/packet-osi.c305
-rw-r--r--epan/dissectors/packet-osi.h91
-rw-r--r--epan/dissectors/packet-ospf.c2145
-rw-r--r--epan/dissectors/packet-pcnfsd.c442
-rw-r--r--epan/dissectors/packet-pcnfsd.h31
-rw-r--r--epan/dissectors/packet-per.c1544
-rw-r--r--epan/dissectors/packet-per.h103
-rw-r--r--epan/dissectors/packet-pflog.c475
-rw-r--r--epan/dissectors/packet-pflog.h79
-rw-r--r--epan/dissectors/packet-pgm.c1934
-rw-r--r--epan/dissectors/packet-pim.c1210
-rw-r--r--epan/dissectors/packet-pim.h30
-rw-r--r--epan/dissectors/packet-pktc.c784
-rw-r--r--epan/dissectors/packet-pktc.h31
-rw-r--r--epan/dissectors/packet-pop.c234
-rw-r--r--epan/dissectors/packet-portmap.c626
-rw-r--r--epan/dissectors/packet-portmap.h62
-rw-r--r--epan/dissectors/packet-postgresql.c221
-rw-r--r--epan/dissectors/packet-ppp.c3767
-rw-r--r--epan/dissectors/packet-ppp.h44
-rw-r--r--epan/dissectors/packet-pppoe.c309
-rw-r--r--epan/dissectors/packet-pptp.c839
-rw-r--r--epan/dissectors/packet-pres.c1820
-rw-r--r--epan/dissectors/packet-pres.h172
-rw-r--r--epan/dissectors/packet-prism.c313
-rw-r--r--epan/dissectors/packet-prism.h37
-rw-r--r--epan/dissectors/packet-ptp.c2126
-rw-r--r--epan/dissectors/packet-q2931.c2189
-rw-r--r--epan/dissectors/packet-q931.c3166
-rw-r--r--epan/dissectors/packet-q931.h49
-rw-r--r--epan/dissectors/packet-q933.c2150
-rw-r--r--epan/dissectors/packet-qllc.c196
-rw-r--r--epan/dissectors/packet-quake.c667
-rw-r--r--epan/dissectors/packet-quake2.c932
-rw-r--r--epan/dissectors/packet-quake3.c665
-rw-r--r--epan/dissectors/packet-quakeworld.c913
-rw-r--r--epan/dissectors/packet-radiotap.c459
-rw-r--r--epan/dissectors/packet-radiotap.h30
-rw-r--r--epan/dissectors/packet-radius.c3427
-rw-r--r--epan/dissectors/packet-ranap.c4872
-rw-r--r--epan/dissectors/packet-raw.c204
-rw-r--r--epan/dissectors/packet-raw.h29
-rw-r--r--epan/dissectors/packet-rip.c405
-rw-r--r--epan/dissectors/packet-ripng.c155
-rw-r--r--epan/dissectors/packet-ripng.h116
-rw-r--r--epan/dissectors/packet-rlogin.c481
-rw-r--r--epan/dissectors/packet-rmcp.c191
-rw-r--r--epan/dissectors/packet-rmi.c384
-rw-r--r--epan/dissectors/packet-rmi.h69
-rw-r--r--epan/dissectors/packet-rmp.c270
-rw-r--r--epan/dissectors/packet-rpc.c3560
-rw-r--r--epan/dissectors/packet-rpc.h196
-rw-r--r--epan/dissectors/packet-rpl.c415
-rw-r--r--epan/dissectors/packet-rquota.c253
-rw-r--r--epan/dissectors/packet-rquota.h34
-rw-r--r--epan/dissectors/packet-rsh.c133
-rw-r--r--epan/dissectors/packet-rstat.c152
-rw-r--r--epan/dissectors/packet-rsvp.c4609
-rw-r--r--epan/dissectors/packet-rsvp.h32
-rw-r--r--epan/dissectors/packet-rsync.c338
-rw-r--r--epan/dissectors/packet-rtcp.c1655
-rw-r--r--epan/dissectors/packet-rtcp.h44
-rw-r--r--epan/dissectors/packet-rtp-events.c240
-rw-r--r--epan/dissectors/packet-rtp-events.h253
-rw-r--r--epan/dissectors/packet-rtp.c979
-rw-r--r--epan/dissectors/packet-rtp.h65
-rw-r--r--epan/dissectors/packet-rtps.c1993
-rw-r--r--epan/dissectors/packet-rtps.h250
-rw-r--r--epan/dissectors/packet-rtsp.c1217
-rw-r--r--epan/dissectors/packet-rwall.c89
-rw-r--r--epan/dissectors/packet-rwall.h32
-rw-r--r--epan/dissectors/packet-rx.c781
-rw-r--r--epan/dissectors/packet-rx.h82
-rw-r--r--epan/dissectors/packet-sadmind.c111
-rw-r--r--epan/dissectors/packet-sap.c362
-rw-r--r--epan/dissectors/packet-sccp.c2366
-rw-r--r--epan/dissectors/packet-sccpmg.c388
-rw-r--r--epan/dissectors/packet-scsi.c5337
-rw-r--r--epan/dissectors/packet-scsi.h83
-rw-r--r--epan/dissectors/packet-sctp.c2292
-rw-r--r--epan/dissectors/packet-sctp.h43
-rw-r--r--epan/dissectors/packet-sdlc.c222
-rw-r--r--epan/dissectors/packet-sdp.c1154
-rw-r--r--epan/dissectors/packet-sebek.c210
-rw-r--r--epan/dissectors/packet-ses.c1786
-rw-r--r--epan/dissectors/packet-ses.h198
-rw-r--r--epan/dissectors/packet-sflow.c1068
-rw-r--r--epan/dissectors/packet-sigcomp.c1975
-rw-r--r--epan/dissectors/packet-sip.c2063
-rw-r--r--epan/dissectors/packet-sip.h39
-rw-r--r--epan/dissectors/packet-sipfrag.c140
-rw-r--r--epan/dissectors/packet-skinny.c4402
-rw-r--r--epan/dissectors/packet-slimp3.c731
-rw-r--r--epan/dissectors/packet-sll.c307
-rw-r--r--epan/dissectors/packet-sll.h29
-rw-r--r--epan/dissectors/packet-slowprotocols.c819
-rw-r--r--epan/dissectors/packet-slsk.c2480
-rw-r--r--epan/dissectors/packet-smb-browse.c1166
-rw-r--r--epan/dissectors/packet-smb-browse.h34
-rw-r--r--epan/dissectors/packet-smb-common.c490
-rw-r--r--epan/dissectors/packet-smb-common.h121
-rw-r--r--epan/dissectors/packet-smb-logon.c1032
-rw-r--r--epan/dissectors/packet-smb-mailslot.c265
-rw-r--r--epan/dissectors/packet-smb-mailslot.h34
-rw-r--r--epan/dissectors/packet-smb-pipe.c3931
-rw-r--r--epan/dissectors/packet-smb-pipe.h37
-rw-r--r--epan/dissectors/packet-smb-sidsnooping.c457
-rw-r--r--epan/dissectors/packet-smb-sidsnooping.h41
-rw-r--r--epan/dissectors/packet-smb.c19418
-rw-r--r--epan/dissectors/packet-smpp.c2765
-rw-r--r--epan/dissectors/packet-smtp.c597
-rw-r--r--epan/dissectors/packet-sna.c3597
-rw-r--r--epan/dissectors/packet-sna.h35
-rw-r--r--epan/dissectors/packet-snaeth.c113
-rw-r--r--epan/dissectors/packet-sndcp.c577
-rw-r--r--epan/dissectors/packet-snmp.c2569
-rw-r--r--epan/dissectors/packet-snmp.h36
-rw-r--r--epan/dissectors/packet-socks.c1225
-rw-r--r--epan/dissectors/packet-spnego.c1694
-rw-r--r--epan/dissectors/packet-spray.c147
-rw-r--r--epan/dissectors/packet-spray.h35
-rw-r--r--epan/dissectors/packet-srvloc.c1699
-rw-r--r--epan/dissectors/packet-sscop.c332
-rw-r--r--epan/dissectors/packet-ssh.c940
-rw-r--r--epan/dissectors/packet-ssl.c3468
-rw-r--r--epan/dissectors/packet-stat-notify.c108
-rw-r--r--epan/dissectors/packet-stat-notify.h34
-rw-r--r--epan/dissectors/packet-stat.c351
-rw-r--r--epan/dissectors/packet-stat.h38
-rw-r--r--epan/dissectors/packet-stun.c410
-rw-r--r--epan/dissectors/packet-sua.c1763
-rw-r--r--epan/dissectors/packet-symantec.c103
-rw-r--r--epan/dissectors/packet-syslog.c253
-rw-r--r--epan/dissectors/packet-t38.c929
-rw-r--r--epan/dissectors/packet-tacacs.c1137
-rw-r--r--epan/dissectors/packet-tacacs.h431
-rw-r--r--epan/dissectors/packet-tcap.c2900
-rw-r--r--epan/dissectors/packet-tcap.h64
-rw-r--r--epan/dissectors/packet-tcp.c3247
-rw-r--r--epan/dissectors/packet-tcp.h96
-rw-r--r--epan/dissectors/packet-tds.c1805
-rw-r--r--epan/dissectors/packet-teimanagement.c146
-rw-r--r--epan/dissectors/packet-telnet.c1601
-rw-r--r--epan/dissectors/packet-teredo.c267
-rw-r--r--epan/dissectors/packet-text-media.c164
-rw-r--r--epan/dissectors/packet-tftp.c352
-rw-r--r--epan/dissectors/packet-time.c99
-rw-r--r--epan/dissectors/packet-tns.c1341
-rw-r--r--epan/dissectors/packet-tns.h43
-rw-r--r--epan/dissectors/packet-tpkt.c395
-rw-r--r--epan/dissectors/packet-tpkt.h45
-rw-r--r--epan/dissectors/packet-tr.c749
-rw-r--r--epan/dissectors/packet-tr.h36
-rw-r--r--epan/dissectors/packet-trmac.c415
-rw-r--r--epan/dissectors/packet-tsp.c227
-rw-r--r--epan/dissectors/packet-tuxedo.c199
-rw-r--r--epan/dissectors/packet-tzsp.c521
-rw-r--r--epan/dissectors/packet-ucp.c2595
-rw-r--r--epan/dissectors/packet-udp.c356
-rw-r--r--epan/dissectors/packet-udp.h42
-rw-r--r--epan/dissectors/packet-v120.c305
-rw-r--r--epan/dissectors/packet-vines.c1661
-rw-r--r--epan/dissectors/packet-vines.h135
-rw-r--r--epan/dissectors/packet-vj.c900
-rw-r--r--epan/dissectors/packet-vlan.c165
-rw-r--r--epan/dissectors/packet-vlan.h29
-rw-r--r--epan/dissectors/packet-vrrp.c302
-rw-r--r--epan/dissectors/packet-vtp.c698
-rw-r--r--epan/dissectors/packet-wap.c327
-rw-r--r--epan/dissectors/packet-wap.h100
-rw-r--r--epan/dissectors/packet-wbxml.c6731
-rw-r--r--epan/dissectors/packet-wccp.c1323
-rw-r--r--epan/dissectors/packet-wccp.h29
-rw-r--r--epan/dissectors/packet-wcp.c750
-rw-r--r--epan/dissectors/packet-wfleet-hdlc.c127
-rw-r--r--epan/dissectors/packet-who.c308
-rw-r--r--epan/dissectors/packet-wlancap.c302
-rw-r--r--epan/dissectors/packet-wlancap.h33
-rw-r--r--epan/dissectors/packet-wsp.c7410
-rw-r--r--epan/dissectors/packet-wsp.h60
-rw-r--r--epan/dissectors/packet-wtls.c1627
-rw-r--r--epan/dissectors/packet-wtls.h40
-rw-r--r--epan/dissectors/packet-wtp.c1095
-rw-r--r--epan/dissectors/packet-wtp.h63
-rw-r--r--epan/dissectors/packet-x11-keysym.h349
-rw-r--r--epan/dissectors/packet-x11-keysymdef.h2063
-rw-r--r--epan/dissectors/packet-x11.c5382
-rw-r--r--epan/dissectors/packet-x25.c2518
-rw-r--r--epan/dissectors/packet-x29.c281
-rw-r--r--epan/dissectors/packet-xdmcp.c520
-rw-r--r--epan/dissectors/packet-xot.c174
-rw-r--r--epan/dissectors/packet-xyplex.c215
-rw-r--r--epan/dissectors/packet-yhoo.c298
-rw-r--r--epan/dissectors/packet-ymsg.c433
-rw-r--r--epan/dissectors/packet-ypbind.c222
-rw-r--r--epan/dissectors/packet-ypbind.h34
-rw-r--r--epan/dissectors/packet-yppasswd.c173
-rw-r--r--epan/dissectors/packet-yppasswd.h32
-rw-r--r--epan/dissectors/packet-ypserv.c494
-rw-r--r--epan/dissectors/packet-ypserv.h43
-rw-r--r--epan/dissectors/packet-ypxfr.c81
-rw-r--r--epan/dissectors/packet-ypxfr.h33
-rw-r--r--epan/dissectors/packet-zebra.c617
-rw-r--r--epan/dissectors/process-x11-fields.pl131
-rw-r--r--epan/dissectors/x11-fields520
662 files changed, 618818 insertions, 0 deletions
diff --git a/epan/dissectors/Makefile.am b/epan/dissectors/Makefile.am
new file mode 100644
index 0000000000..a105149c62
--- /dev/null
+++ b/epan/dissectors/Makefile.am
@@ -0,0 +1,117 @@
+# Makefile.am
+#
+# $Id$
+#
+# Ethereal - Network traffic analyzer
+# By Gerald Combs <gerald@zing.org>
+# Copyright 2004 Gerald Combs
+#
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+noinst_LTLIBRARIES = libdissectors.la
+
+CLEANFILES = \
+ libdissectors.a \
+ libdissectors.la \
+ *~
+
+INCLUDES = -I$(srcdir)/../.. -I$(srcdir)/..
+
+include Makefile.common
+
+libdissectors_la_SOURCES = \
+ $(DISSECTOR_SRC) \
+ $(DISSECTOR_SUPPORT_SRC)
+
+EXTRA_DIST = \
+ Makefile.nmake
+
+packet-ncp2222.c : $(srcdir)/ncp2222.py
+ $(PYTHON) $< -o $@
+
+#
+# Build various header files for the X11 dissector.
+#
+PROC_X11_FIELDS := $(srcdir)/process-x11-fields.pl
+X11_FIELDS := $(srcdir)/x11-fields
+
+x11-declarations.h x11-register-info.h: $(PROC_X11_FIELDS) $(X11_FIELDS)
+ $(PERL) $(PROC_X11_FIELDS) < $(X11_FIELDS)
+
+#
+# Build "register.c", which contains a function "register_all_protocols()"
+# that calls the register routines for all protocols.
+#
+# We do this by grepping through sources. If that turns out to be too slow,
+# maybe we could just require every .o file to have an register routine
+# of a given name (packet-aarp.o -> proto_register_aarp, etc.).
+#
+# Formatting conventions: The name of the proto_register_* routines must
+# start in column zero, or must be preceded only by "void " starting in
+# column zero, and must not be inside #if.
+#
+# We assume that all dissector routines are in "packet-XXX.c" files.
+#
+# For some unknown reason, having a big "for" loop in the Makefile
+# to scan all the "packet-XXX.c" files doesn't work with some "make"s;
+# they seem to pass only the first few names in the list to the shell,
+# for some reason.
+#
+# Therefore, we have a script to generate the "register.c" file.
+#
+# The first argument is the name of the file to write.
+# The second argument is the directory in which the source files live.
+# All subsequent arguments are the files to scan.
+#
+register.c: $(plugin_src) $(DISSECTOR_SRC) $(srcdir)/make-reg-dotc $(srcdir)/make-reg-dotc.py
+ @if test -n $(PYTHON); then \
+ echo Making register.c with python ; \
+ $(PYTHON) $(srcdir)/make-reg-dotc.py $(srcdir) $(DISSECTOR_SRC) ; \
+ else \
+ echo Making register.c with shell script ; \
+ $(srcdir)/make-reg-dotc register.c $(srcdir) \
+ $(plugin_src) $(DISSECTOR_SRC) ; \
+ fi
+
+#
+# Currently register.c can be included in the distribution because
+# we always build all protocol dissectors. We used to have to check
+# whether or not to build the snmp dissector. If we again need to
+# variably build something, making register.c non-portable, uncomment
+# the dist-hook line below.
+#
+# Oh, yuk. We don't want to include "register.c" in the distribution, as
+# its contents depend on the configuration, and therefore we want it
+# to be built when the first "make" is done; however, Automake insists
+# on putting *all* source into the distribution.
+#
+# We work around this by having a "dist-hook" rule that deletes
+# "register.c", so that "dist" won't pick it up.
+#
+#dist-hook:
+# @rm -f $(distdir)/register.c
+
+
+MAINTAINERCLEANFILES = \
+ register.c \
+ packet-ncp2222.c
+
+CLEANFILES = \
+ libdissectors.a \
+ libdissectors.la \
+ x11-declarations.h \
+ x11-register-info.h \
+ *~
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
new file mode 100644
index 0000000000..7a614d1bdf
--- /dev/null
+++ b/epan/dissectors/Makefile.common
@@ -0,0 +1,699 @@
+# Makefile.common
+# Contains the stuff from Makefile.am and Makefile.nmake that is
+# a) common to both files and
+# b) portable between both files
+#
+# $Id: Makefile.common 11400 2004-07-18 00:24:25Z guy $
+#
+# Ethereal - Network traffic analyzer
+# By Gerald Combs <gerald@ethereal.com>
+# Copyright 1998 Gerald Combs
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+# the dissector sources (without any helpers)
+DISSECTOR_SRC = \
+ packet-3g-a11.c \
+ packet-aarp.c \
+ packet-acap.c \
+ packet-acse.c \
+ packet-afp.c \
+ packet-afs.c \
+ packet-aim.c \
+ packet-aim-adverts.c \
+ packet-aim-admin.c \
+ packet-aim-bos.c \
+ packet-aim-buddylist.c \
+ packet-aim-chat.c \
+ packet-aim-chatnav.c \
+ packet-aim-directory.c \
+ packet-aim-generic.c \
+ packet-aim-icq.c \
+ packet-aim-invitation.c \
+ packet-aim-location.c \
+ packet-aim-messaging.c \
+ packet-aim-oft.c \
+ packet-aim-popup.c \
+ packet-aim-signon.c \
+ packet-aim-ssi.c \
+ packet-aim-stats.c \
+ packet-aim-translate.c \
+ packet-aim-userlookup.c \
+ packet-ajp13.c \
+ packet-alcap.c \
+ packet-ans.c \
+ packet-ansi_637.c \
+ packet-ansi_683.c \
+ packet-ansi_801.c \
+ packet-ansi_a.c \
+ packet-ansi_map.c \
+ packet-aodv.c \
+ packet-ap1394.c \
+ packet-arcnet.c \
+ packet-arp.c \
+ packet-asap.c \
+ packet-ascend.c \
+ packet-asf.c \
+ packet-atalk.c \
+ packet-atm.c \
+ packet-auto_rp.c \
+ packet-bacapp.c \
+ packet-bacnet.c \
+ packet-beep.c \
+ packet-ber.c \
+ packet-bfd.c \
+ packet-bgp.c \
+ packet-bofl.c \
+ packet-bootp.c \
+ packet-bootparams.c \
+ packet-bpdu.c \
+ packet-brdwlk.c \
+ packet-bssap.c \
+ packet-bssgp.c \
+ packet-bvlc.c \
+ packet-cast.c \
+ packet-ccsds.c \
+ packet-cdp.c \
+ packet-cgmp.c \
+ packet-chdlc.c \
+ packet-cisco-oui.c \
+ packet-clearcase.c \
+ packet-clip.c \
+ packet-clnp.c \
+ packet-cops.c \
+ packet-cosine.c \
+ packet-cpfi.c \
+ packet-cpha.c \
+ packet-cups.c \
+ packet-data.c \
+ packet-dccp.c \
+ packet-dcerpc-afs4int.c \
+ packet-dcerpc-atsvc.c \
+ packet-dcerpc-bossvr.c \
+ packet-dcerpc-browser.c \
+ packet-dcerpc-budb.c \
+ packet-dcerpc-butc.c \
+ packet-dcerpc-cds_clerkserver.c \
+ packet-dcerpc-cds_solicit.c \
+ packet-dcerpc-conv.c \
+ packet-dcerpc-cprpc_server.c \
+ packet-dcerpc-dce122.c \
+ packet-dcerpc-dfs.c \
+ packet-dcerpc-dnsserver.c \
+ packet-dcerpc-drsuapi.c \
+ packet-dcerpc-dtsprovider.c \
+ packet-dcerpc-dtsstime_req.c \
+ packet-dcerpc-efs.c \
+ packet-dcerpc-epm.c \
+ packet-dcerpc-epm4.c \
+ packet-dcerpc-eventlog.c \
+ packet-dcerpc-fldb.c \
+ packet-dcerpc-frsapi.c \
+ packet-dcerpc-frsrpc.c \
+ packet-dcerpc-ftserver.c \
+ packet-dcerpc-icl_rpc.c \
+ packet-dcerpc-initshutdown.c \
+ packet-dcerpc-krb5rpc.c \
+ packet-dcerpc-llb.c \
+ packet-dcerpc-lsa-ds.c \
+ packet-dcerpc-lsa.c \
+ packet-dcerpc-mapi.c \
+ packet-dcerpc-messenger.c \
+ packet-dcerpc-mgmt.c \
+ packet-dcerpc-ndr.c \
+ packet-dcerpc-netlogon.c \
+ packet-dcerpc-nspi.c \
+ packet-dcerpc-oxid.c \
+ packet-dcerpc-rdaclif.c \
+ packet-dcerpc-reg.c \
+ packet-dcerpc-remact.c \
+ packet-dcerpc-rep_proc.c \
+ packet-dcerpc-roverride.c \
+ packet-dcerpc-rpriv.c \
+ packet-dcerpc-rs_acct.c \
+ packet-dcerpc-rs_attr.c \
+ packet-dcerpc-rs_attr_schema.c \
+ packet-dcerpc-rs_bind.c \
+ packet-dcerpc-rs_misc.c \
+ packet-dcerpc-rs_pgo.c \
+ packet-dcerpc-rs_plcy.c \
+ packet-dcerpc-rs_prop_acct.c \
+ packet-dcerpc-rs_prop_acl.c \
+ packet-dcerpc-rs_prop_attr.c \
+ packet-dcerpc-rs_prop_pgo.c \
+ packet-dcerpc-rs_prop_plcy.c \
+ packet-dcerpc-rs_pwd_mgmt.c \
+ packet-dcerpc-rs_repadm.c \
+ packet-dcerpc-rs_replist.c \
+ packet-dcerpc-rs_repmgr.c \
+ packet-dcerpc-rs_unix.c \
+ packet-dcerpc-rsec_login.c \
+ packet-dcerpc-samr.c \
+ packet-dcerpc-secidmap.c \
+ packet-dcerpc-spoolss.c \
+ packet-dcerpc-srvsvc.c \
+ packet-dcerpc-svcctl.c \
+ packet-dcerpc-tapi.c \
+ packet-dcerpc-tkn4int.c \
+ packet-dcerpc-trksvr.c \
+ packet-dcerpc-ubikdisk.c \
+ packet-dcerpc-ubikvote.c \
+ packet-dcerpc-update.c \
+ packet-dcerpc-wkssvc.c \
+ packet-dcerpc.c \
+ packet-dcm.c \
+ packet-ddtp.c \
+ packet-dec-bpdu.c \
+ packet-dhcpv6.c \
+ packet-diameter.c \
+ packet-diffserv-mpls-common.c \
+ packet-distcc.c \
+ packet-dlsw.c \
+ packet-dnp.c \
+ packet-dns.c \
+ packet-dsi.c \
+ packet-dvmrp.c \
+ packet-e164.c \
+ packet-eap.c \
+ packet-eapol.c \
+ packet-echo.c \
+ packet-edonkey.c \
+ packet-eigrp.c \
+ packet-enc.c \
+ packet-enip.c \
+ packet-enrp.c \
+ packet-esis.c \
+ packet-eth.c \
+ packet-etherip.c \
+ packet-ethertype.c \
+ packet-fc.c \
+ packet-fcct.c \
+ packet-fcdns.c \
+ packet-fcels.c \
+ packet-fcfcs.c \
+ packet-fcfzs.c \
+ packet-fcip.c \
+ packet-fclctl.c \
+ packet-fcp.c \
+ packet-fcsb3.c \
+ packet-fcsp.c \
+ packet-fcswils.c \
+ packet-fddi.c \
+ packet-fix.c \
+ packet-fr.c \
+ packet-frame.c \
+ packet-ftam.c \
+ packet-ftp.c \
+ packet-fw1.c \
+ packet-gift.c \
+ packet-giop.c \
+ packet-gmrp.c \
+ packet-gnutella.c \
+ packet-gprs-llc.c \
+ packet-gprs-ns.c \
+ packet-gre.c \
+ packet-gsm_a.c \
+ packet-gsm_map.c \
+ packet-gsm_sms.c \
+ packet-gsm_sms_ud.c \
+ packet-gsm_ss.c \
+ packet-gssapi.c \
+ packet-gtp.c \
+ packet-gvrp.c \
+ packet-h1.c \
+ packet-h225.c \
+ packet-h235.c \
+ packet-h245.c \
+ packet-h261.c \
+ packet-h263.c \
+ packet-h450.c \
+ packet-hclnfsd.c \
+ packet-hpext.c \
+ packet-hsrp.c \
+ packet-http.c \
+ packet-hyperscsi.c \
+ packet-iapp.c \
+ packet-iax2.c \
+ packet-ib.c \
+ packet-icap.c \
+ packet-icmpv6.c \
+ packet-icp.c \
+ packet-icq.c \
+ packet-ieee80211.c \
+ packet-ieee8023.c \
+ packet-igap.c \
+ packet-igmp.c \
+ packet-igrp.c \
+ packet-image-gif.c \
+ packet-image-jfif.c \
+ packet-imap.c \
+ packet-ip.c \
+ packet-ipdc.c \
+ packet-ipfc.c \
+ packet-ipmi.c \
+ packet-ipp.c \
+ packet-ipsec-udp.c \
+ packet-ipsec.c \
+ packet-ipv6.c \
+ packet-ipvs-syncd.c \
+ packet-ipx.c \
+ packet-ipxwan.c \
+ packet-irc.c \
+ packet-isakmp.c \
+ packet-iscsi.c \
+ packet-isdn.c \
+ packet-isis-clv.c \
+ packet-isis-hello.c \
+ packet-isis-lsp.c \
+ packet-isis-snp.c \
+ packet-isis.c \
+ packet-isl.c \
+ packet-ismp.c \
+ packet-isns.c \
+ packet-isup.c \
+ packet-iua.c \
+ packet-jabber.c \
+ packet-kadm5.c \
+ packet-kerberos.c \
+ packet-klm.c \
+ packet-kpasswd.c \
+ packet-l2tp.c \
+ packet-lapb.c \
+ packet-lapbether.c \
+ packet-lapd.c \
+ packet-laplink.c \
+ packet-ldap.c \
+ packet-ldp.c \
+ packet-llc.c \
+ packet-lmi.c \
+ packet-lmp.c \
+ packet-lpd.c \
+ packet-lwapp.c \
+ packet-m2pa.c \
+ packet-m2tp.c \
+ packet-m2ua.c \
+ packet-m3ua.c \
+ packet-mbtcp.c \
+ packet-mdshdr.c \
+ packet-media.c \
+ packet-mip.c \
+ packet-mip6.c \
+ packet-mmse.c \
+ packet-mount.c \
+ packet-mpeg1.c \
+ packet-mpls.c \
+ packet-mpls-echo.c \
+ packet-mq.c \
+ packet-mq-pcf.c \
+ packet-mrdisc.c \
+ packet-msdp.c \
+ packet-msn-messenger.c \
+ packet-msnip.c \
+ packet-msproxy.c \
+ packet-mtp2.c \
+ packet-mtp3.c \
+ packet-mtp3mg.c \
+ packet-multipart.c \
+ packet-mysql.c \
+ packet-nbipx.c \
+ packet-nbns.c \
+ packet-ncp.c \
+ packet-ncp2222.c \
+ packet-ncp-nmas.c \
+ packet-ndmp.c \
+ packet-ndps.c \
+ packet-netbios.c \
+ packet-netflow.c \
+ packet-nfs.c \
+ packet-nfsacl.c \
+ packet-nfsauth.c \
+ packet-nisplus.c \
+ packet-nlm.c \
+ packet-nlsp.c \
+ packet-nntp.c \
+ packet-nt-oui.c \
+ packet-nt-sonmp.c \
+ packet-nt-tpcp.c \
+ packet-ntlmssp.c \
+ packet-ntp.c \
+ packet-null.c \
+ packet-olsr.c \
+ packet-osi-options.c \
+ packet-osi.c \
+ packet-ospf.c \
+ packet-pcnfsd.c \
+ packet-per.c \
+ packet-pflog.c \
+ packet-pgm.c \
+ packet-pim.c \
+ packet-pktc.c \
+ packet-pop.c \
+ packet-portmap.c \
+ packet-postgresql.c \
+ packet-ppp.c \
+ packet-pppoe.c \
+ packet-pptp.c \
+ packet-pres.c \
+ packet-prism.c \
+ packet-ptp.c \
+ packet-q2931.c \
+ packet-q931.c \
+ packet-q933.c \
+ packet-qllc.c \
+ packet-quake.c \
+ packet-quake2.c \
+ packet-quake3.c \
+ packet-quakeworld.c \
+ packet-radius.c \
+ packet-radiotap.c \
+ packet-ranap.c \
+ packet-raw.c \
+ packet-rip.c \
+ packet-ripng.c \
+ packet-rlogin.c \
+ packet-rmcp.c \
+ packet-rmi.c \
+ packet-rmp.c \
+ packet-rpc.c \
+ packet-rpl.c \
+ packet-rquota.c \
+ packet-rsh.c \
+ packet-rstat.c \
+ packet-rsvp.c \
+ packet-rsync.c \
+ packet-rtcp.c \
+ packet-rtp-events.c \
+ packet-rtp.c \
+ packet-rtps.c \
+ packet-rtsp.c \
+ packet-rwall.c \
+ packet-rx.c \
+ packet-sadmind.c \
+ packet-sap.c \
+ packet-sccp.c \
+ packet-sccpmg.c \
+ packet-scsi.c \
+ packet-sctp.c \
+ packet-sdlc.c \
+ packet-sdp.c \
+ packet-sebek.c \
+ packet-ses.c \
+ packet-sflow.c \
+ packet-sip.c \
+ packet-sigcomp.c \
+ packet-sipfrag.c \
+ packet-skinny.c \
+ packet-slimp3.c \
+ packet-sll.c \
+ packet-slowprotocols.c \
+ packet-slsk.c \
+ packet-smb-browse.c \
+ packet-smb-common.c \
+ packet-smb-logon.c \
+ packet-smb-mailslot.c \
+ packet-smb-pipe.c \
+ packet-smb-sidsnooping.c \
+ packet-smb.c \
+ packet-smpp.c \
+ packet-smtp.c \
+ packet-sna.c \
+ packet-snaeth.c \
+ packet-sndcp.c \
+ packet-snmp.c \
+ packet-socks.c \
+ packet-spnego.c \
+ packet-spray.c \
+ packet-srvloc.c \
+ packet-sscop.c \
+ packet-ssh.c \
+ packet-ssl.c \
+ packet-stat-notify.c \
+ packet-stat.c \
+ packet-stun.c \
+ packet-sua.c \
+ packet-symantec.c \
+ packet-syslog.c \
+ packet-t38.c \
+ packet-tacacs.c \
+ packet-tcap.c \
+ packet-tcp.c \
+ packet-tds.c \
+ packet-teimanagement.c \
+ packet-telnet.c \
+ packet-teredo.c \
+ packet-text-media.c \
+ packet-tftp.c \
+ packet-time.c \
+ packet-tns.c \
+ packet-tpkt.c \
+ packet-tr.c \
+ packet-trmac.c \
+ packet-tsp.c \
+ packet-tuxedo.c \
+ packet-tzsp.c \
+ packet-ucp.c \
+ packet-udp.c \
+ packet-v120.c \
+ packet-vines.c \
+ packet-vj.c \
+ packet-vlan.c \
+ packet-vrrp.c \
+ packet-vtp.c \
+ packet-wap.c \
+ packet-wbxml.c \
+ packet-wccp.c \
+ packet-wcp.c \
+ packet-wfleet-hdlc.c \
+ packet-who.c \
+ packet-wlancap.c \
+ packet-wsp.c \
+ packet-wtls.c \
+ packet-wtp.c \
+ packet-x11.c \
+ packet-x25.c \
+ packet-x29.c \
+ packet-xdmcp.c \
+ packet-xot.c \
+ packet-xyplex.c \
+ packet-yhoo.c \
+ packet-ymsg.c \
+ packet-ypbind.c \
+ packet-yppasswd.c \
+ packet-ypserv.c \
+ packet-ypxfr.c \
+ packet-zebra.c
+
+# corresponding headers
+DISSECTOR_INCLUDES = \
+ packet-acse.h \
+ packet-afp.h \
+ packet-afs-defs.h \
+ packet-afs-macros.h \
+ packet-afs-register-info.h \
+ packet-afs.h \
+ packet-aim.h \
+ packet-ansi_a.h \
+ packet-ansi_map.h \
+ packet-ap1394.h \
+ packet-arcnet.h \
+ packet-arp.h \
+ packet-atalk.h \
+ packet-atm.h \
+ packet-ber.h \
+ packet-bgp.h \
+ packet-bootparams.h \
+ packet-bssap.h \
+ packet-chdlc.h \
+ packet-clearcase.h \
+ packet-clip.h \
+ packet-data.h \
+ packet-dccp.h \
+ packet-dcerpc-atsvc.h \
+ packet-dcerpc-browser.h \
+ packet-dcerpc-dce122.h \
+ packet-dcerpc-dcom.h \
+ packet-dcerpc-dfs.h \
+ packet-dcerpc-dnsserver.h \
+ packet-dcerpc-drsuapi.h \
+ packet-dcerpc-efs.h \
+ packet-dcerpc-eventlog.h \
+ packet-dcerpc-frsapi.h \
+ packet-dcerpc-frsrpc.h \
+ packet-dcerpc-initshutdown.h \
+ packet-dcerpc-lsa.h \
+ packet-dcerpc-mapi.h \
+ packet-dcerpc-netlogon.h \
+ packet-dcerpc-nt.h \
+ packet-dcerpc-reg.h \
+ packet-dcerpc-samr.h \
+ packet-dcerpc-spoolss.h \
+ packet-dcerpc-srvsvc.h \
+ packet-dcerpc-svcctl.h \
+ packet-dcerpc-tapi.h \
+ packet-dcerpc-wkssvc.h \
+ packet-dcerpc.h \
+ packet-ddtp.h \
+ packet-diameter-defs.h \
+ packet-diffserv-mpls-common.h \
+ packet-dns.h \
+ packet-dvmrp.h \
+ packet-e164.h \
+ packet-edonkey.h \
+ packet-esis.h \
+ packet-eth.h \
+ packet-fc.h \
+ packet-fcbls.h \
+ packet-fcct.h \
+ packet-fcdns.h \
+ packet-fcels.h \
+ packet-fcfcs.h \
+ packet-fcfzs.h \
+ packet-fclctl.h \
+ packet-fcp.h \
+ packet-fcsb3.h \
+ packet-fcsp.h \
+ packet-fcswils.h \
+ packet-fddi.h \
+ packet-frame.h \
+ packet-ftam.h \
+ packet-giop.h \
+ packet-gnutella.h \
+ packet-gsm_a.h \
+ packet-gsm_map.h \
+ packet-gsm_sms.h \
+ packet-gsm_ss.h \
+ packet-gssapi.h \
+ packet-gtp.h \
+ packet-h225.h \
+ packet-h235.h \
+ packet-h245.h \
+ packet-hclnfsd.h \
+ packet-hpext.h \
+ packet-http.h \
+ packet-iax2.h \
+ packet-ieee80211.h \
+ packet-ieee8023.h \
+ packet-igap.h \
+ packet-igmp.h \
+ packet-ip.h \
+ packet-ipdc.h \
+ packet-ipfc.h \
+ packet-ipsec.h \
+ packet-ipv6.h \
+ packet-ipx.h \
+ packet-isis-clv.h \
+ packet-isis-hello.h \
+ packet-isis-lsp.h \
+ packet-isis-snp.h \
+ packet-isis.h \
+ packet-isl.h \
+ packet-isup.h \
+ packet-kerberos.h \
+ packet-klm.h \
+ packet-ldap.h \
+ packet-ldp.h \
+ packet-llc.h \
+ packet-mip6.h \
+ packet-mount.h \
+ packet-mq.h \
+ packet-mrdisc.h \
+ packet-msnip.h \
+ packet-mtp3.h \
+ packet-ncp-int.h \
+ packet-ncp-nmas.h \
+ packet-ndps.h \
+ packet-netbios.h \
+ packet-nfs.h \
+ packet-nisplus.h \
+ packet-nlm.h \
+ packet-ntp.h \
+ packet-null.h \
+ packet-osi-options.h \
+ packet-osi.h \
+ packet-pcnfsd.h \
+ packet-per.h \
+ packet-pflog.h \
+ packet-pim.h \
+ packet-pktc.h \
+ packet-portmap.h \
+ packet-ppp.h \
+ packet-pres.h \
+ packet-prism.h \
+ packet-q931.h \
+ packet-radiotap.h \
+ packet-raw.h \
+ packet-ripng.h \
+ packet-rmi.h \
+ packet-rpc.h \
+ packet-rquota.h \
+ packet-rsvp.h \
+ packet-rtcp.h \
+ packet-rtp.h \
+ packet-rtps.h \
+ packet-rtp-events.h \
+ packet-rwall.h \
+ packet-rx.h \
+ packet-scsi.h \
+ packet-sctp.h \
+ packet-ses.h \
+ packet-sip.h \
+ packet-sll.h \
+ packet-smb-browse.h \
+ packet-smb-common.h \
+ packet-smb-mailslot.h \
+ packet-smb-pipe.h \
+ packet-smb-sidsnooping.h \
+ packet-sna.h \
+ packet-snmp.h \
+ packet-spray.h \
+ packet-stat-notify.h \
+ packet-stat.h \
+ packet-tacacs.h \
+ packet-tcap.h \
+ packet-tcp.h \
+ packet-tns.h \
+ packet-tpkt.h \
+ packet-tr.h \
+ packet-udp.h \
+ packet-vines.h \
+ packet-vlan.h \
+ packet-wap.h \
+ packet-wccp.h \
+ packet-wlancap.h \
+ packet-wsp.h \
+ packet-wtls.h \
+ packet-wtp.h \
+ packet-x11-keysym.h \
+ packet-x11-keysymdef.h \
+ packet-ypbind.h \
+ packet-yppasswd.h \
+ packet-ypserv.h \
+ packet-ypxfr.h
+
+# dissector helpers (needed from the dissectors, but not a dissector itself)
+DISSECTOR_SUPPORT_SRC = \
+ packet-dcerpc-nt.c \
+ register.c
+
+# "BUILT_SOURCES" are built before any "make all" or "make check" targets.
+BUILT_SOURCES = \
+ register.c \
+ x11-declarations.h \
+ x11-register-info.h
+
+# this target needed for distribution only
+noinst_HEADERS = \
+ $(DISSECTOR_INCLUDES)
diff --git a/epan/dissectors/Makefile.nmake b/epan/dissectors/Makefile.nmake
new file mode 100644
index 0000000000..587843048d
--- /dev/null
+++ b/epan/dissectors/Makefile.nmake
@@ -0,0 +1,33 @@
+## Makefile for building ethereal.exe with Microsoft C and nmake
+## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
+#
+# $Id: Makefile.nmake 11400 2004-07-18 00:24:25Z guy $
+
+include ..\..\config.nmake
+
+############### no need to modify below this line #########
+
+CFLAGS=-DHAVE_CONFIG_H /I. /I.. /I../.. $(GLIB_CFLAGS) \
+ $(PCRE_CFLAGS) /I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS)
+
+CVARSDLL=-DWIN32 -DNULL=0 -D_MT -D_DLL
+
+.c.obj::
+ $(CC) $(CVARSDLL) $(CFLAGS) -Fd.\ -c $<
+
+DISSECTOR_SRC = $(DISSECTOR_SRC:../=)
+DISSECTOR_OBJECTS = $(DISSECTOR_SRC:.c=.obj)
+
+DISSECTOR_SUPPORT_SRC = $(DISSECTOR_SUPPORT_SRC:../=)
+DISSECTOR_SUPPORT_OBJECTS = $(DISSECTOR_SUPPORT_SRC:.c=.obj)
+
+#dissectors.lib: ../../config.h $(DISSECTOR_OBJECTS) $(DISSECTOR_SUPPORT_OBJECTS) $(EXTRA_OBJECTS)
+dissectors.lib: ../../config.h $(DISSECTOR_OBJECTS) $(DISSECTOR_SUPPORT_OBJECTS)
+ link /lib /out:dissectors.lib $(DISSECTOR_OBJECTS) $(DISSECTOR_SUPPORT_OBJECTS)
+
+
+clean:
+ rm -f dissectors.lib $(PDB_FILE) \
+ $(DISSECTOR_OBJECTS) $(DISSECTOR_SUPPORT_OBJECTS)
+
+distclean: clean
diff --git a/epan/dissectors/make-reg-dotc b/epan/dissectors/make-reg-dotc
new file mode 100755
index 0000000000..a90019af05
--- /dev/null
+++ b/epan/dissectors/make-reg-dotc
@@ -0,0 +1,79 @@
+#! /bin/sh
+
+#
+# $Id$
+#
+
+#
+# The first argument is the output filename.
+#
+
+outfile="$1"
+shift
+
+#
+# The second argument is the directory in which the source files live.
+#
+srcdir="$1"
+shift
+
+#
+# All subsequent arguments are the files to scan.
+#
+rm -f ${outfile}-tmp
+echo '/* Do not modify this file. */' >${outfile}-tmp
+echo '/* It is created automatically by the Makefile. */'>>${outfile}-tmp
+echo '#include "register.h"' >>${outfile}-tmp
+
+#
+# Build code to call all the protocol registration routines.
+#
+echo 'void register_all_protocols(void) {' >>${outfile}-tmp
+for f in "$@"
+do
+ if [ -f $f ]
+ then
+ srcfile=$f
+ else
+ srcfile=$srcdir/$f
+ fi
+ grep '^proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
+done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
+for f in "$@"
+do
+ if [ -f $f ]
+ then
+ srcfile=$f
+ else
+ srcfile=$srcdir/$f
+ fi
+ grep '^void proto_register_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
+done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
+echo '}' >>${outfile}-tmp
+
+#
+# Build code to call all the protocol handoff registration routines.
+#
+echo 'void register_all_protocol_handoffs(void) {' >>${outfile}-tmp
+for f in "$@"
+do
+ if [ -f $f ]
+ then
+ srcfile=$f
+ else
+ srcfile=$srcdir/$f
+ fi
+ grep '^proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
+done | sed -e 's/^.*://' -e 's/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
+for f in "$@"
+do
+ if [ -f $f ]
+ then
+ srcfile=$f
+ else
+ srcfile=$srcdir/$f
+ fi
+ grep '^void proto_reg_handoff_[a-z_0-9A-Z]* *(' $srcfile 2>/dev/null | grep -v ';'
+done | sed -e 's/^.*://' -e 's/^void \([a-z_0-9A-Z]*\).*/ {extern void \1 (void); \1 ();}/' >>${outfile}-tmp
+echo '}' >>${outfile}-tmp
+mv ${outfile}-tmp ${outfile}
diff --git a/epan/dissectors/make-reg-dotc.py b/epan/dissectors/make-reg-dotc.py
new file mode 100755
index 0000000000..5c1411cb9c
--- /dev/null
+++ b/epan/dissectors/make-reg-dotc.py
@@ -0,0 +1,118 @@
+#!/usr/bin/python
+#
+# Looks for registration routines in the protocol dissectors,
+# and assembles C code to call all the routines.
+#
+# This is a Python version of the make-reg-dotc shell script.
+# Running the shell script on Win32 is very very slow because of
+# all the process-launching that goes on --- multiple greps and
+# seds for each input file. I wrote this python version so that
+# less processes would have to be started.
+#
+# $Id$
+
+import os
+import sys
+import re
+
+tmp_filename = "register.c-tmp"
+final_filename = "register.c"
+
+#
+# The first argument is the directory in which the source files live.
+#
+srcdir = sys.argv[1]
+
+#
+# All subsequent arguments are the files to scan.
+#
+files = sys.argv[2:]
+
+reg_code = open(tmp_filename, "w")
+
+reg_code.write("/* Do not modify this file. */\n")
+reg_code.write("/* It is created automatically by the Makefile. */\n")
+reg_code.write('#include "register.h"\n')
+
+# Create the proper list of filenames
+filenames = []
+for file in files:
+ if os.path.isfile(file):
+ filenames.append(file)
+ else:
+ filenames.append("%s/%s" % (srcdir, file))
+
+
+# Look through all files, applying the regex to each line.
+# If the pattern matches, save the "symbol" section to the
+# appropriate array.
+proto_reg = []
+handoff_reg = []
+
+# For those that don't know Python, r"" indicates a raw string,
+# devoid of Python escapes.
+proto_regex0 = r"^(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
+proto_regex1 = r"void\s+(?P<symbol>proto_register_[_A-Za-z0-9]+)\s*\([^;]+$"
+
+handoff_regex0 = r"^(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
+handoff_regex1 = r"void\s+(?P<symbol>proto_reg_handoff_[_A-Za-z0-9]+)\s*\([^;]+$"
+
+# This table drives the pattern-matching and symbol-harvesting
+patterns = [
+ ( proto_reg, re.compile(proto_regex0) ),
+ ( proto_reg, re.compile(proto_regex1) ),
+ ( handoff_reg, re.compile(handoff_regex0) ),
+ ( handoff_reg, re.compile(handoff_regex1) ),
+ ]
+
+# Grep
+for filename in filenames:
+ file = open(filename)
+# print "Searching %s" % (filename)
+ for line in file.readlines():
+ for action in patterns:
+ regex = action[1]
+ match = regex.search(line)
+ if match:
+ symbol = match.group("symbol")
+ list = action[0]
+ list.append(symbol)
+ file.close()
+
+# Sort the lists to make them pretty
+proto_reg.sort()
+handoff_reg.sort()
+
+# Make register_all_protocols()
+reg_code.write("void register_all_protocols(void) {\n")
+
+for symbol in proto_reg:
+ line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
+ reg_code.write(line)
+
+reg_code.write("}\n")
+
+
+# Make register_all_protocol_handoffs()
+reg_code.write("void register_all_protocol_handoffs(void) {\n")
+
+for symbol in handoff_reg:
+ line = " {extern void %s (void); %s ();}\n" % (symbol, symbol)
+ reg_code.write(line)
+
+reg_code.write("}\n")
+
+# Close the file
+reg_code.close()
+
+# Remove the old final_file if it exists.
+try:
+ os.stat(final_filename)
+ os.remove(final_filename)
+except OSError:
+ pass
+
+# Move from tmp file to final file
+os.rename(tmp_filename, final_filename)
+
+
diff --git a/epan/dissectors/ncp2222.py b/epan/dissectors/ncp2222.py
new file mode 100755
index 0000000000..b341510745
--- /dev/null
+++ b/epan/dissectors/ncp2222.py
@@ -0,0 +1,14808 @@
+#!/usr/bin/env python
+
+"""
+Creates C code from a table of NCP type 0x2222 packet types.
+(And 0x3333, which are the replies, but the packets are more commonly
+refered to as type 0x2222; the 0x3333 replies are understood to be
+part of the 0x2222 "family")
+
+The data-munging code was written by Gilbert Ramirez.
+The NCP data comes from Greg Morris <GMORRIS@novell.com>.
+Many thanks to Novell for letting him work on this.
+
+Additional data sources:
+"Programmer's Guide to the NetWare Core Protocol" by Steve Conner and Dianne Conner.
+
+Novell provides info at:
+
+http://developer.novell.com/ndk/ncp.htm (where you can download an
+*.exe file which installs a PDF, although you may have to create a login
+to do this)
+
+or
+
+http://developer.novell.com/ndk/doc/ncp/
+for a badly-formatted HTML version of the same PDF.
+
+
+$Id$
+
+
+Portions Copyright (c) 2000-2002 by Gilbert Ramirez <gram@alumni.rice.edu>.
+Portions Copyright (c) Novell, Inc. 2000-2003.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+"""
+
+import os
+import sys
+import string
+import getopt
+import traceback
+
+errors = {}
+groups = {}
+packets = []
+compcode_lists = None
+ptvc_lists = None
+msg = None
+
+REC_START = 0
+REC_LENGTH = 1
+REC_FIELD = 2
+REC_ENDIANNESS = 3
+REC_VAR = 4
+REC_REPEAT = 5
+REC_REQ_COND = 6
+
+NO_VAR = -1
+NO_REPEAT = -1
+NO_REQ_COND = -1
+NO_LENGTH_CHECK = -2
+
+
+PROTO_LENGTH_UNKNOWN = -1
+
+global_highest_var = -1
+global_req_cond = {}
+
+
+REQ_COND_SIZE_VARIABLE = "REQ_COND_SIZE_VARIABLE"
+REQ_COND_SIZE_CONSTANT = "REQ_COND_SIZE_CONSTANT"
+
+##############################################################################
+# Global containers
+##############################################################################
+
+class UniqueCollection:
+ """The UniqueCollection class stores objects which can be compared to other
+ objects of the same class. If two objects in the collection are equivalent,
+ only one is stored."""
+
+ def __init__(self, name):
+ "Constructor"
+ self.name = name
+ self.members = []
+ self.member_reprs = {}
+
+ def Add(self, object):
+ """Add an object to the members lists, if a comparable object
+ doesn't already exist. The object that is in the member list, that is
+ either the object that was added or the comparable object that was
+ already in the member list, is returned."""
+
+ r = repr(object)
+ # Is 'object' a duplicate of some other member?
+ if self.member_reprs.has_key(r):
+ return self.member_reprs[r]
+ else:
+ self.member_reprs[r] = object
+ self.members.append(object)
+ return object
+
+ def Members(self):
+ "Returns the list of members."
+ return self.members
+
+ def HasMember(self, object):
+ "Does the list of members contain the object?"
+ if self.members_reprs.has_key(repr(object)):
+ return 1
+ else:
+ return 0
+
+# This list needs to be defined before the NCP types are defined,
+# because the NCP types are defined in the global scope, not inside
+# a function's scope.
+ptvc_lists = UniqueCollection('PTVC Lists')
+
+##############################################################################
+
+class NamedList:
+ "NamedList's keep track of PTVC's and Completion Codes"
+ def __init__(self, name, list):
+ "Constructor"
+ self.name = name
+ self.list = list
+
+ def __cmp__(self, other):
+ "Compare this NamedList to another"
+
+ if isinstance(other, NamedList):
+ return cmp(self.list, other.list)
+ else:
+ return 0
+
+
+ def Name(self, new_name = None):
+ "Get/Set name of list"
+ if new_name != None:
+ self.name = new_name
+ return self.name
+
+ def Records(self):
+ "Returns record lists"
+ return self.list
+
+ def Null(self):
+ "Is there no list (different from an empty list)?"
+ return self.list == None
+
+ def Empty(self):
+ "It the list empty (different from a null list)?"
+ assert(not self.Null())
+
+ if self.list:
+ return 0
+ else:
+ return 1
+
+ def __repr__(self):
+ return repr(self.list)
+
+class PTVC(NamedList):
+ """ProtoTree TVBuff Cursor List ("PTVC List") Class"""
+
+ def __init__(self, name, records):
+ "Constructor"
+ NamedList.__init__(self, name, [])
+
+ global global_highest_var
+
+ expected_offset = None
+ highest_var = -1
+
+ named_vars = {}
+
+ # Make a PTVCRecord object for each list in 'records'
+ for record in records:
+ offset = record[REC_START]
+ length = record[REC_LENGTH]
+ field = record[REC_FIELD]
+ endianness = record[REC_ENDIANNESS]
+
+ # Variable
+ var_name = record[REC_VAR]
+ if var_name:
+ # Did we already define this var?
+ if named_vars.has_key(var_name):
+ sys.exit("%s has multiple %s vars." % \
+ (name, var_name))
+
+ highest_var = highest_var + 1
+ var = highest_var
+ if highest_var > global_highest_var:
+ global_highest_var = highest_var
+ named_vars[var_name] = var
+ else:
+ var = NO_VAR
+
+ # Repeat
+ repeat_name = record[REC_REPEAT]
+ if repeat_name:
+ # Do we have this var?
+ if not named_vars.has_key(repeat_name):
+ sys.exit("%s does not have %s var defined." % \
+ (name, var_name))
+ repeat = named_vars[repeat_name]
+ else:
+ repeat = NO_REPEAT
+
+ # Request Condition
+ req_cond = record[REC_REQ_COND]
+ if req_cond != NO_REQ_COND:
+ global_req_cond[req_cond] = None
+
+ ptvc_rec = PTVCRecord(field, length, endianness, var, repeat, req_cond)
+
+ if expected_offset == None:
+ expected_offset = offset
+
+ elif expected_offset == -1:
+ pass
+
+ elif expected_offset != offset and offset != -1:
+ msg.write("Expected offset in %s for %s to be %d\n" % \
+ (name, field.HFName(), expected_offset))
+ sys.exit(1)
+
+ # We can't make a PTVC list from a variable-length
+ # packet, unless the fields can tell us at run time
+ # how long the packet is. That is, nstring8 is fine, since
+ # the field has an integer telling us how long the string is.
+ # Fields that don't have a length determinable at run-time
+ # cannot be variable-length.
+ if type(ptvc_rec.Length()) == type(()):
+ if isinstance(ptvc_rec.Field(), nstring):
+ expected_offset = -1
+ pass
+ elif isinstance(ptvc_rec.Field(), nbytes):
+ expected_offset = -1
+ pass
+ elif isinstance(ptvc_rec.Field(), struct):
+ expected_offset = -1
+ pass
+ else:
+ field = ptvc_rec.Field()
+ assert 0, "Cannot make PTVC from %s, type %s" % \
+ (field.HFName(), field)
+
+ elif expected_offset > -1:
+ if ptvc_rec.Length() < 0:
+ expected_offset = -1
+ else:
+ expected_offset = expected_offset + ptvc_rec.Length()
+
+
+ self.list.append(ptvc_rec)
+
+ def ETTName(self):
+ return "ett_%s" % (self.Name(),)
+
+
+ def Code(self):
+ x = "static const ptvc_record %s[] = {\n" % (self.Name())
+ for ptvc_rec in self.list:
+ x = x + "\t%s,\n" % (ptvc_rec.Code())
+ x = x + "\t{ NULL, 0, NULL, NO_ENDIANNESS, NO_VAR, NO_REPEAT, NO_REQ_COND, NCP_FMT_NONE }\n"
+ x = x + "};\n"
+ return x
+
+ def __repr__(self):
+ x = ""
+ for ptvc_rec in self.list:
+ x = x + repr(ptvc_rec)
+ return x
+
+
+class PTVCBitfield(PTVC):
+ def __init__(self, name, vars):
+ NamedList.__init__(self, name, [])
+
+ for var in vars:
+ ptvc_rec = PTVCRecord(var, var.Length(), var.Endianness(),
+ NO_VAR, NO_REPEAT, NO_REQ_COND)
+ self.list.append(ptvc_rec)
+
+ def Code(self):
+ ett_name = self.ETTName()
+ x = "static gint %s;\n" % (ett_name,)
+
+ x = x + "static const ptvc_record ptvc_%s[] = {\n" % (self.Name())
+ for ptvc_rec in self.list:
+ x = x + "\t%s,\n" % (ptvc_rec.Code())
+ x = x + "\t{ NULL, 0, NULL, NO_ENDIANNESS, NO_VAR, NO_REPEAT, NO_REQ_COND, NCP_FMT_NONE }\n"
+ x = x + "};\n"
+
+ x = x + "static const sub_ptvc_record %s = {\n" % (self.Name(),)
+ x = x + "\t&%s,\n" % (ett_name,)
+ x = x + "\tNULL,\n"
+ x = x + "\tptvc_%s,\n" % (self.Name(),)
+ x = x + "};\n"
+ return x
+
+
+class PTVCRecord:
+ def __init__(self, field, length, endianness, var, repeat, req_cond):
+ "Constructor"
+ self.field = field
+ self.length = length
+ self.endianness = endianness
+ self.var = var
+ self.repeat = repeat
+ self.req_cond = req_cond
+
+ def __cmp__(self, other):
+ "Comparison operator"
+ if self.field != other.field:
+ return 1
+ elif self.length < other.length:
+ return -1
+ elif self.length > other.length:
+ return 1
+ elif self.endianness != other.endianness:
+ return 1
+ else:
+ return 0
+
+ def Code(self):
+ # Nice textual representations
+ if self.var == NO_VAR:
+ var = "NO_VAR"
+ else:
+ var = self.var
+
+ if self.repeat == NO_REPEAT:
+ repeat = "NO_REPEAT"
+ else:
+ repeat = self.repeat
+
+ if self.req_cond == NO_REQ_COND:
+ req_cond = "NO_REQ_COND"
+ else:
+ req_cond = global_req_cond[self.req_cond]
+ assert req_cond != None
+
+ if isinstance(self.field, struct):
+ return self.field.ReferenceString(var, repeat, req_cond)
+ else:
+ return self.RegularCode(var, repeat, req_cond)
+
+ def RegularCode(self, var, repeat, req_cond):
+ "String representation"
+ endianness = 'BE'
+ if self.endianness == LE:
+ endianness = 'LE'
+
+ length = None
+
+ if type(self.length) == type(0):
+ length = self.length
+ else:
+ # This is for cases where a length is needed
+ # in order to determine a following variable-length,
+ # like nstring8, where 1 byte is needed in order
+ # to determine the variable length.
+ var_length = self.field.Length()
+ if var_length > 0:
+ length = var_length
+
+ if length == PROTO_LENGTH_UNKNOWN:
+ # XXX length = "PROTO_LENGTH_UNKNOWN"
+ pass
+
+ assert length, "Length not handled for %s" % (self.field.HFName(),)
+
+ sub_ptvc_name = self.field.PTVCName()
+ if sub_ptvc_name != "NULL":
+ sub_ptvc_name = "&%s" % (sub_ptvc_name,)
+
+
+ return "{ &%s, %s, %s, %s, %s, %s, %s, %s }" % \
+ (self.field.HFName(), length, sub_ptvc_name,
+ endianness, var, repeat, req_cond,
+ self.field.SpecialFmt())
+
+ def Offset(self):
+ return self.offset
+
+ def Length(self):
+ return self.length
+
+ def Field(self):
+ return self.field
+
+ def __repr__(self):
+ return "{%s len=%s end=%s var=%s rpt=%s rqc=%s}" % \
+ (self.field.HFName(), self.length,
+ self.endianness, self.var, self.repeat, self.req_cond)
+
+##############################################################################
+
+class NCP:
+ "NCP Packet class"
+ def __init__(self, func_code, description, group, has_length=1):
+ "Constructor"
+ self.func_code = func_code
+ self.description = description
+ self.group = group
+ self.codes = None
+ self.request_records = None
+ self.reply_records = None
+ self.has_length = has_length
+ self.req_cond_size = None
+ self.req_info_str = None
+
+ if not groups.has_key(group):
+ msg.write("NCP 0x%x has invalid group '%s'\n" % \
+ (self.func_code, group))
+ sys.exit(1)
+
+ if self.HasSubFunction():
+ # NCP Function with SubFunction
+ self.start_offset = 10
+ else:
+ # Simple NCP Function
+ self.start_offset = 7
+
+ def ReqCondSize(self):
+ return self.req_cond_size
+
+ def ReqCondSizeVariable(self):
+ self.req_cond_size = REQ_COND_SIZE_VARIABLE
+
+ def ReqCondSizeConstant(self):
+ self.req_cond_size = REQ_COND_SIZE_CONSTANT
+
+ def FunctionCode(self, part=None):
+ "Returns the function code for this NCP packet."
+ if part == None:
+ return self.func_code
+ elif part == 'high':
+ if self.HasSubFunction():
+ return (self.func_code & 0xff00) >> 8
+ else:
+ return self.func_code
+ elif part == 'low':
+ if self.HasSubFunction():
+ return self.func_code & 0x00ff
+ else:
+ return 0x00
+ else:
+ msg.write("Unknown directive '%s' for function_code()\n" % (part))
+ sys.exit(1)
+
+ def HasSubFunction(self):
+ "Does this NPC packet require a subfunction field?"
+ if self.func_code <= 0xff:
+ return 0
+ else:
+ return 1
+
+ def HasLength(self):
+ return self.has_length
+
+ def Description(self):
+ return self.description
+
+ def Group(self):
+ return self.group
+
+ def PTVCRequest(self):
+ return self.ptvc_request
+
+ def PTVCReply(self):
+ return self.ptvc_reply
+
+ def Request(self, size, records=[], **kwargs):
+ self.request_size = size
+ self.request_records = records
+ if self.HasSubFunction():
+ if self.HasLength():
+ self.CheckRecords(size, records, "Request", 10)
+ else:
+ self.CheckRecords(size, records, "Request", 8)
+ else:
+ self.CheckRecords(size, records, "Request", 7)
+ self.ptvc_request = self.MakePTVC(records, "request")
+
+ if kwargs.has_key("info_str"):
+ self.req_info_str = kwargs["info_str"]
+
+ def Reply(self, size, records=[]):
+ self.reply_size = size
+ self.reply_records = records
+ self.CheckRecords(size, records, "Reply", 8)
+ self.ptvc_reply = self.MakePTVC(records, "reply")
+
+ def CheckRecords(self, size, records, descr, min_hdr_length):
+ "Simple sanity check"
+ if size == NO_LENGTH_CHECK:
+ return
+ min = size
+ max = size
+ if type(size) == type(()):
+ min = size[0]
+ max = size[1]
+
+ lower = min_hdr_length
+ upper = min_hdr_length
+
+ for record in records:
+ rec_size = record[REC_LENGTH]
+ rec_lower = rec_size
+ rec_upper = rec_size
+ if type(rec_size) == type(()):
+ rec_lower = rec_size[0]
+ rec_upper = rec_size[1]
+
+ lower = lower + rec_lower
+ upper = upper + rec_upper
+
+ error = 0
+ if min != lower:
+ msg.write("%s records for 2222/0x%x sum to %d bytes minimum, but param1 shows %d\n" \
+ % (descr, self.FunctionCode(), lower, min))
+ error = 1
+ if max != upper:
+ msg.write("%s records for 2222/0x%x sum to %d bytes maximum, but param1 shows %d\n" \
+ % (descr, self.FunctionCode(), upper, max))
+ error = 1
+
+ if error == 1:
+ sys.exit(1)
+
+
+ def MakePTVC(self, records, name_suffix):
+ """Makes a PTVC out of a request or reply record list. Possibly adds
+ it to the global list of PTVCs (the global list is a UniqueCollection,
+ so an equivalent PTVC may already be in the global list)."""
+
+ name = "%s_%s" % (self.CName(), name_suffix)
+ ptvc = PTVC(name, records)
+ return ptvc_lists.Add(ptvc)
+
+ def CName(self):
+ "Returns a C symbol based on the NCP function code"
+ return "ncp_0x%x" % (self.func_code)
+
+ def InfoStrName(self):
+ "Returns a C symbol based on the NCP function code, for the info_str"
+ return "info_str_0x%x" % (self.func_code)
+
+ def Variables(self):
+ """Returns a list of variables used in the request and reply records.
+ A variable is listed only once, even if it is used twice (once in
+ the request, once in the reply)."""
+
+ variables = {}
+ if self.request_records:
+ for record in self.request_records:
+ var = record[REC_FIELD]
+ variables[var.HFName()] = var
+
+ sub_vars = var.SubVariables()
+ for sv in sub_vars:
+ variables[sv.HFName()] = sv
+
+ if self.reply_records:
+ for record in self.reply_records:
+ var = record[REC_FIELD]
+ variables[var.HFName()] = var
+
+ sub_vars = var.SubVariables()
+ for sv in sub_vars:
+ variables[sv.HFName()] = sv
+
+ return variables.values()
+
+ def CalculateReqConds(self):
+ """Returns a list of request conditions (dfilter text) used
+ in the reply records. A request condition is listed only once,
+ even it it used twice. """
+ texts = {}
+ if self.reply_records:
+ for record in self.reply_records:
+ text = record[REC_REQ_COND]
+ if text != NO_REQ_COND:
+ texts[text] = None
+
+ if len(texts) == 0:
+ self.req_conds = None
+ return None
+
+ dfilter_texts = texts.keys()
+ dfilter_texts.sort()
+ name = "%s_req_cond_indexes" % (self.CName(),)
+ return NamedList(name, dfilter_texts)
+
+ def GetReqConds(self):
+ return self.req_conds
+
+ def SetReqConds(self, new_val):
+ self.req_conds = new_val
+
+
+ def CompletionCodes(self, codes=None):
+ """Sets or returns the list of completion
+ codes. Internally, a NamedList is used to store the
+ completion codes, but the caller of this function never
+ realizes that because Python lists are the input and
+ output."""
+
+ if codes == None:
+ return self.codes
+
+ # Sanity check
+ okay = 1
+ for code in codes:
+ if not errors.has_key(code):
+ msg.write("Errors table does not have key 0x%04x for NCP=0x%x\n" % (code,
+ self.func_code))
+ okay = 0
+
+ # Delay the exit until here so that the programmer can get
+ # the complete list of missing error codes
+ if not okay:
+ sys.exit(1)
+
+ # Create CompletionCode (NamedList) object and possible
+ # add it to the global list of completion code lists.
+ name = "%s_errors" % (self.CName(),)
+ codes.sort()
+ codes_list = NamedList(name, codes)
+ self.codes = compcode_lists.Add(codes_list)
+
+ self.Finalize()
+
+ def Finalize(self):
+ """Adds the NCP object to the global collection of NCP
+ objects. This is done automatically after setting the
+ CompletionCode list. Yes, this is a shortcut, but it makes
+ our list of NCP packet definitions look neater, since an
+ explicit "add to global list of packets" is not needed."""
+
+ # Add packet to global collection of packets
+ packets.append(self)
+
+def rec(start, length, field, endianness=None, **kw):
+ return _rec(start, length, field, endianness, kw)
+
+def srec(field, endianness=None, **kw):
+ return _rec(-1, -1, field, endianness, kw)
+
+def _rec(start, length, field, endianness, kw):
+ # If endianness not explicitly given, use the field's
+ # default endiannes.
+ if endianness == None:
+ endianness = field.Endianness()
+
+ # Setting a var?
+ if kw.has_key("var"):
+ # Is the field an INT ?
+ if not isinstance(field, CountingNumber):
+ sys.exit("Field %s used as count variable, but not integer." \
+ % (field.HFName()))
+ var = kw["var"]
+ else:
+ var = None
+
+ # If 'var' not used, 'repeat' can be used.
+ if not var and kw.has_key("repeat"):
+ repeat = kw["repeat"]
+ else:
+ repeat = None
+
+ # Request-condition ?
+ if kw.has_key("req_cond"):
+ req_cond = kw["req_cond"]
+ else:
+ req_cond = NO_REQ_COND
+
+ return [start, length, field, endianness, var, repeat, req_cond]
+
+
+
+
+##############################################################################
+
+LE = 1 # Little-Endian
+BE = 0 # Big-Endian
+NA = -1 # Not Applicable
+
+class Type:
+ " Virtual class for NCP field types"
+ type = "Type"
+ ftype = None
+ disp = "BASE_DEC"
+ endianness = NA
+ values = []
+
+ def __init__(self, abbrev, descr, bytes, endianness = NA):
+ self.abbrev = abbrev
+ self.descr = descr
+ self.bytes = bytes
+ self.endianness = endianness
+ self.hfname = "hf_ncp_" + self.abbrev
+ self.special_fmt = "NCP_FMT_NONE"
+
+ def Length(self):
+ return self.bytes
+
+ def Abbreviation(self):
+ return self.abbrev
+
+ def Description(self):
+ return self.descr
+
+ def HFName(self):
+ return self.hfname
+
+ def DFilter(self):
+ return "ncp." + self.abbrev
+
+ def EtherealFType(self):
+ return self.ftype
+
+ def Display(self, newval=None):
+ if newval != None:
+ self.disp = newval
+ return self.disp
+
+ def ValuesName(self):
+ return "NULL"
+
+ def Mask(self):
+ return 0
+
+ def Endianness(self):
+ return self.endianness
+
+ def SubVariables(self):
+ return []
+
+ def PTVCName(self):
+ return "NULL"
+
+ def NWDate(self):
+ self.special_fmt = "NCP_FMT_NW_DATE"
+
+ def NWTime(self):
+ self.special_fmt = "NCP_FMT_NW_TIME"
+
+ def NWUnicode(self):
+ self.special_fmt = "NCP_FMT_UNICODE"
+
+ def SpecialFmt(self):
+ return self.special_fmt
+
+ def __cmp__(self, other):
+ return cmp(self.hfname, other.hfname)
+
+class struct(PTVC, Type):
+ def __init__(self, name, items, descr=None):
+ name = "struct_%s" % (name,)
+ NamedList.__init__(self, name, [])
+
+ self.bytes = 0
+ self.descr = descr
+ for item in items:
+ if isinstance(item, Type):
+ field = item
+ length = field.Length()
+ endianness = field.Endianness()
+ var = NO_VAR
+ repeat = NO_REPEAT
+ req_cond = NO_REQ_COND
+ elif type(item) == type([]):
+ field = item[REC_FIELD]
+ length = item[REC_LENGTH]
+ endianness = item[REC_ENDIANNESS]
+ var = item[REC_VAR]
+ repeat = item[REC_REPEAT]
+ req_cond = item[REC_REQ_COND]
+ else:
+ assert 0, "Item %s item not handled." % (item,)
+
+ ptvc_rec = PTVCRecord(field, length, endianness, var,
+ repeat, req_cond)
+ self.list.append(ptvc_rec)
+ self.bytes = self.bytes + field.Length()
+
+ self.hfname = self.name
+
+ def Variables(self):
+ vars = []
+ for ptvc_rec in self.list:
+ vars.append(ptvc_rec.Field())
+ return vars
+
+ def ReferenceString(self, var, repeat, req_cond):
+ return "{ PTVC_STRUCT, NO_LENGTH, &%s, NO_ENDIANNESS, %s, %s, %s, NCP_FMT_NONE }" % \
+ (self.name, var, repeat, req_cond)
+
+ def Code(self):
+ ett_name = self.ETTName()
+ x = "static gint %s;\n" % (ett_name,)
+ x = x + "static const ptvc_record ptvc_%s[] = {\n" % (self.name,)
+ for ptvc_rec in self.list:
+ x = x + "\t%s,\n" % (ptvc_rec.Code())
+ x = x + "\t{ NULL, NO_LENGTH, NULL, NO_ENDIANNESS, NO_VAR, NO_REPEAT, NO_REQ_COND, NCP_FMT_NONE }\n"
+ x = x + "};\n"
+
+ x = x + "static const sub_ptvc_record %s = {\n" % (self.name,)
+ x = x + "\t&%s,\n" % (ett_name,)
+ if self.descr:
+ x = x + '\t"%s",\n' % (self.descr,)
+ else:
+ x = x + "\tNULL,\n"
+ x = x + "\tptvc_%s,\n" % (self.Name(),)
+ x = x + "};\n"
+ return x
+
+ def __cmp__(self, other):
+ return cmp(self.HFName(), other.HFName())
+
+
+class byte(Type):
+ type = "byte"
+ ftype = "FT_UINT8"
+ def __init__(self, abbrev, descr):
+ Type.__init__(self, abbrev, descr, 1)
+
+class CountingNumber:
+ pass
+
+# Same as above. Both are provided for convenience
+class uint8(Type, CountingNumber):
+ type = "uint8"
+ ftype = "FT_UINT8"
+ bytes = 1
+ def __init__(self, abbrev, descr):
+ Type.__init__(self, abbrev, descr, 1)
+
+class uint16(Type, CountingNumber):
+ type = "uint16"
+ ftype = "FT_UINT16"
+ def __init__(self, abbrev, descr, endianness = LE):
+ Type.__init__(self, abbrev, descr, 2, endianness)
+
+class uint24(Type, CountingNumber):
+ type = "uint24"
+ ftype = "FT_UINT24"
+ def __init__(self, abbrev, descr, endianness = LE):
+ Type.__init__(self, abbrev, descr, 3, endianness)
+
+class uint32(Type, CountingNumber):
+ type = "uint32"
+ ftype = "FT_UINT32"
+ def __init__(self, abbrev, descr, endianness = LE):
+ Type.__init__(self, abbrev, descr, 4, endianness)
+
+class boolean8(uint8):
+ type = "boolean8"
+ ftype = "FT_BOOLEAN"
+
+class boolean16(uint16):
+ type = "boolean16"
+ ftype = "FT_BOOLEAN"
+
+class boolean24(uint24):
+ type = "boolean24"
+ ftype = "FT_BOOLEAN"
+
+class boolean32(uint32):
+ type = "boolean32"
+ ftype = "FT_BOOLEAN"
+
+class nstring:
+ pass
+
+class nstring8(Type, nstring):
+ """A string of up to (2^8)-1 characters. The first byte
+ gives the string length."""
+
+ type = "nstring8"
+ ftype = "FT_UINT_STRING"
+ def __init__(self, abbrev, descr):
+ Type.__init__(self, abbrev, descr, 1)
+
+class nstring16(Type, nstring):
+ """A string of up to (2^16)-2 characters. The first 2 bytes
+ gives the string length."""
+
+ type = "nstring16"
+ ftype = "FT_UINT_STRING"
+ def __init__(self, abbrev, descr, endianness = LE):
+ Type.__init__(self, abbrev, descr, 2, endianness)
+
+class nstring32(Type, nstring):
+ """A string of up to (2^32)-4 characters. The first 4 bytes
+ gives the string length."""
+
+ type = "nstring32"
+ ftype = "FT_UINT_STRING"
+ def __init__(self, abbrev, descr, endianness = LE):
+ Type.__init__(self, abbrev, descr, 4, endianness)
+
+class fw_string(Type):
+ """A fixed-width string of n bytes."""
+
+ type = "fw_string"
+ ftype = "FT_STRING"
+
+ def __init__(self, abbrev, descr, bytes):
+ Type.__init__(self, abbrev, descr, bytes)
+
+
+class stringz(Type):
+ "NUL-terminated string, with a maximum length"
+
+ type = "stringz"
+ ftype = "FT_STRINGZ"
+ def __init__(self, abbrev, descr):
+ Type.__init__(self, abbrev, descr, PROTO_LENGTH_UNKNOWN)
+
+class val_string(Type):
+ """Abstract class for val_stringN, where N is number
+ of bits that key takes up."""
+
+ type = "val_string"
+ disp = 'BASE_HEX'
+
+ def __init__(self, abbrev, descr, val_string_array, endianness = LE):
+ Type.__init__(self, abbrev, descr, self.bytes, endianness)
+ self.values = val_string_array
+
+ def Code(self):
+ result = "static const value_string %s[] = {\n" \
+ % (self.ValuesCName())
+ for val_record in self.values:
+ value = val_record[0]
+ text = val_record[1]
+ value_repr = self.value_format % value
+ result = result + '\t{ %s,\t"%s" },\n' \
+ % (value_repr, text)
+
+ value_repr = self.value_format % 0
+ result = result + "\t{ %s,\tNULL },\n" % (value_repr)
+ result = result + "};\n"
+ REC_VAL_STRING_RES = self.value_format % value
+ return result
+
+ def ValuesCName(self):
+ return "ncp_%s_vals" % (self.abbrev)
+
+ def ValuesName(self):
+ return "VALS(%s)" % (self.ValuesCName())
+
+class val_string8(val_string):
+ type = "val_string8"
+ ftype = "FT_UINT8"
+ bytes = 1
+ value_format = "0x%02x"
+
+class val_string16(val_string):
+ type = "val_string16"
+ ftype = "FT_UINT16"
+ bytes = 2
+ value_format = "0x%04x"
+
+class val_string32(val_string):
+ type = "val_string32"
+ ftype = "FT_UINT32"
+ bytes = 4
+ value_format = "0x%08x"
+
+class bytes(Type):
+ type = 'bytes'
+ ftype = 'FT_BYTES'
+
+ def __init__(self, abbrev, descr, bytes):
+ Type.__init__(self, abbrev, descr, bytes, NA)
+
+class nbytes:
+ pass
+
+class nbytes8(Type, nbytes):
+ """A series of up to (2^8)-1 bytes. The first byte
+ gives the byte-string length."""
+
+ type = "nbytes8"
+ ftype = "FT_UINT_BYTES"
+ def __init__(self, abbrev, descr, endianness = LE):
+ Type.__init__(self, abbrev, descr, 1, endianness)
+
+class nbytes16(Type, nbytes):
+ """A series of up to (2^16)-2 bytes. The first 2 bytes
+ gives the byte-string length."""
+
+ type = "nbytes16"
+ ftype = "FT_UINT_BYTES"
+ def __init__(self, abbrev, descr, endianness = LE):
+ Type.__init__(self, abbrev, descr, 2, endianness)
+
+class nbytes32(Type, nbytes):
+ """A series of up to (2^32)-4 bytes. The first 4 bytes
+ gives the byte-string length."""
+
+ type = "nbytes32"
+ ftype = "FT_UINT_BYTES"
+ def __init__(self, abbrev, descr, endianness = LE):
+ Type.__init__(self, abbrev, descr, 4, endianness)
+
+class bf_uint(Type):
+ type = "bf_uint"
+ disp = None
+
+ def __init__(self, bitmask, abbrev, descr, endianness=LE):
+ Type.__init__(self, abbrev, descr, self.bytes, endianness)
+ self.bitmask = bitmask
+
+ def Mask(self):
+ return self.bitmask
+
+class bf_val_str(bf_uint):
+ type = "bf_uint"
+ disp = None
+
+ def __init__(self, bitmask, abbrev, descr, val_string_array, endiannes=LE):
+ bf_uint.__init__(self, bitmask, abbrev, descr, endiannes)
+ self.values = val_string_array
+
+ def ValuesName(self):
+ return "VALS(%s)" % (self.ValuesCName())
+
+class bf_val_str8(bf_val_str, val_string8):
+ type = "bf_val_str8"
+ ftype = "FT_UINT8"
+ disp = "BASE_HEX"
+ bytes = 1
+
+class bf_val_str16(bf_val_str, val_string16):
+ type = "bf_val_str16"
+ ftype = "FT_UINT16"
+ disp = "BASE_HEX"
+ bytes = 2
+
+class bf_val_str32(bf_val_str, val_string32):
+ type = "bf_val_str32"
+ ftype = "FT_UINT32"
+ disp = "BASE_HEX"
+ bytes = 4
+
+class bf_boolean:
+ pass
+
+class bf_boolean8(bf_uint, boolean8, bf_boolean):
+ type = "bf_boolean8"
+ ftype = "FT_BOOLEAN"
+ disp = "8"
+ bytes = 1
+
+class bf_boolean16(bf_uint, boolean16, bf_boolean):
+ type = "bf_boolean16"
+ ftype = "FT_BOOLEAN"
+ disp = "16"
+ bytes = 2
+
+class bf_boolean24(bf_uint, boolean24, bf_boolean):
+ type = "bf_boolean24"
+ ftype = "FT_BOOLEAN"
+ disp = "24"
+ bytes = 3
+
+class bf_boolean32(bf_uint, boolean32, bf_boolean):
+ type = "bf_boolean32"
+ ftype = "FT_BOOLEAN"
+ disp = "32"
+ bytes = 4
+
+class bitfield(Type):
+ type = "bitfield"
+ disp = 'BASE_HEX'
+
+ def __init__(self, vars):
+ var_hash = {}
+ for var in vars:
+ if isinstance(var, bf_boolean):
+ if not isinstance(var, self.bf_type):
+ print "%s must be of type %s" % \
+ (var.Abbreviation(),
+ self.bf_type)
+ sys.exit(1)
+ var_hash[var.bitmask] = var
+
+ bitmasks = var_hash.keys()
+ bitmasks.sort()
+ bitmasks.reverse()
+
+ ordered_vars = []
+ for bitmask in bitmasks:
+ var = var_hash[bitmask]
+ ordered_vars.append(var)
+
+ self.vars = ordered_vars
+ self.ptvcname = "ncp_%s_bitfield" % (self.abbrev,)
+ self.hfname = "hf_ncp_%s" % (self.abbrev,)
+ self.sub_ptvc = PTVCBitfield(self.PTVCName(), self.vars)
+
+ def SubVariables(self):
+ return self.vars
+
+ def SubVariablesPTVC(self):
+ return self.sub_ptvc
+
+ def PTVCName(self):
+ return self.ptvcname
+
+
+class bitfield8(bitfield, uint8):
+ type = "bitfield8"
+ ftype = "FT_UINT8"
+ bf_type = bf_boolean8
+
+ def __init__(self, abbrev, descr, vars):
+ uint8.__init__(self, abbrev, descr)
+ bitfield.__init__(self, vars)
+
+class bitfield16(bitfield, uint16):
+ type = "bitfield16"
+ ftype = "FT_UINT16"
+ bf_type = bf_boolean16
+
+ def __init__(self, abbrev, descr, vars, endianness=LE):
+ uint16.__init__(self, abbrev, descr, endianness)
+ bitfield.__init__(self, vars)
+
+class bitfield24(bitfield, uint24):
+ type = "bitfield24"
+ ftype = "FT_UINT24"
+ bf_type = bf_boolean24
+
+ def __init__(self, abbrev, descr, vars, endianness=LE):
+ uint24.__init__(self, abbrev, descr, endianness)
+ bitfield.__init__(self, vars)
+
+class bitfield32(bitfield, uint32):
+ type = "bitfield32"
+ ftype = "FT_UINT32"
+ bf_type = bf_boolean32
+
+ def __init__(self, abbrev, descr, vars, endianness=LE):
+ uint32.__init__(self, abbrev, descr, endianness)
+ bitfield.__init__(self, vars)
+
+#
+# Force the endianness of a field to a non-default value; used in
+# the list of fields of a structure.
+#
+def endian(field, endianness):
+ return [-1, field.Length(), field, endianness, NO_VAR, NO_REPEAT, NO_REQ_COND]
+
+##############################################################################
+# NCP Field Types. Defined in Appendix A of "Programmer's Guide..."
+##############################################################################
+
+AbortQueueFlag = val_string8("abort_q_flag", "Abort Queue Flag", [
+ [ 0x00, "Place at End of Queue" ],
+ [ 0x01, "Do Not Place Spool File, Examine Flags" ],
+])
+AcceptedMaxSize = uint16("accepted_max_size", "Accepted Max Size")
+AccessControl = val_string8("access_control", "Access Control", [
+ [ 0x00, "Open for read by this client" ],
+ [ 0x01, "Open for write by this client" ],
+ [ 0x02, "Deny read requests from other stations" ],
+ [ 0x03, "Deny write requests from other stations" ],
+ [ 0x04, "File detached" ],
+ [ 0x05, "TTS holding detach" ],
+ [ 0x06, "TTS holding open" ],
+])
+AccessDate = uint16("access_date", "Access Date")
+AccessDate.NWDate()
+AccessMode = bitfield8("access_mode", "Access Mode", [
+ bf_boolean8(0x01, "acc_mode_read", "Read Access"),
+ bf_boolean8(0x02, "acc_mode_write", "Write Access"),
+ bf_boolean8(0x04, "acc_mode_deny_read", "Deny Read Access"),
+ bf_boolean8(0x08, "acc_mode_deny_write", "Deny Write Access"),
+ bf_boolean8(0x10, "acc_mode_comp", "Compatibility Mode"),
+])
+AccessPrivileges = bitfield8("access_privileges", "Access Privileges", [
+ bf_boolean8(0x01, "acc_priv_read", "Read Privileges (files only)"),
+ bf_boolean8(0x02, "acc_priv_write", "Write Privileges (files only)"),
+ bf_boolean8(0x04, "acc_priv_open", "Open Privileges (files only)"),
+ bf_boolean8(0x08, "acc_priv_create", "Create Privileges (files only)"),
+ bf_boolean8(0x10, "acc_priv_delete", "Delete Privileges (files only)"),
+ bf_boolean8(0x20, "acc_priv_parent", "Parental Privileges (directories only for creating, deleting, and renaming)"),
+ bf_boolean8(0x40, "acc_priv_search", "Search Privileges (directories only)"),
+ bf_boolean8(0x80, "acc_priv_modify", "Modify File Status Flags Privileges (files and directories)"),
+])
+AccessRightsMask = bitfield8("access_rights_mask", "Access Rights", [
+ bf_boolean8(0x0001, "acc_rights_read", "Read Rights"),
+ bf_boolean8(0x0002, "acc_rights_write", "Write Rights"),
+ bf_boolean8(0x0004, "acc_rights_open", "Open Rights"),
+ bf_boolean8(0x0008, "acc_rights_create", "Create Rights"),
+ bf_boolean8(0x0010, "acc_rights_delete", "Delete Rights"),
+ bf_boolean8(0x0020, "acc_rights_parent", "Parental Rights"),
+ bf_boolean8(0x0040, "acc_rights_search", "Search Rights"),
+ bf_boolean8(0x0080, "acc_rights_modify", "Modify Rights"),
+])
+AccessRightsMaskWord = bitfield16("access_rights_mask_word", "Access Rights", [
+ bf_boolean16(0x0001, "acc_rights1_read", "Read Rights"),
+ bf_boolean16(0x0002, "acc_rights1_write", "Write Rights"),
+ bf_boolean16(0x0004, "acc_rights1_open", "Open Rights"),
+ bf_boolean16(0x0008, "acc_rights1_create", "Create Rights"),
+ bf_boolean16(0x0010, "acc_rights1_delete", "Delete Rights"),
+ bf_boolean16(0x0020, "acc_rights1_parent", "Parental Rights"),
+ bf_boolean16(0x0040, "acc_rights1_search", "Search Rights"),
+ bf_boolean16(0x0080, "acc_rights1_modify", "Modify Rights"),
+ bf_boolean16(0x0100, "acc_rights1_supervisor", "Supervisor Access Rights"),
+])
+AccountBalance = uint32("account_balance", "Account Balance")
+AccountVersion = uint8("acct_version", "Acct Version")
+ActionFlag = bitfield8("action_flag", "Action Flag", [
+ bf_boolean8(0x01, "act_flag_open", "Open"),
+ bf_boolean8(0x02, "act_flag_replace", "Replace"),
+ bf_boolean8(0x10, "act_flag_create", "Create"),
+])
+ActiveConnBitList = fw_string("active_conn_bit_list", "Active Connection List", 512)
+ActiveIndexedFiles = uint16("active_indexed_files", "Active Indexed Files")
+ActualMaxBinderyObjects = uint16("actual_max_bindery_objects", "Actual Max Bindery Objects")
+ActualMaxIndexedFiles = uint16("actual_max_indexed_files", "Actual Max Indexed Files")
+ActualMaxOpenFiles = uint16("actual_max_open_files", "Actual Max Open Files")
+ActualMaxSimultaneousTransactions = uint16("actual_max_sim_trans", "Actual Max Simultaneous Transactions")
+ActualMaxUsedDirectoryEntries = uint16("actual_max_used_directory_entries", "Actual Max Used Directory Entries")
+ActualMaxUsedRoutingBuffers = uint16("actual_max_used_routing_buffers", "Actual Max Used Routing Buffers")
+ActualResponseCount = uint16("actual_response_count", "Actual Response Count")
+AddNameSpaceAndVol = stringz("add_nm_spc_and_vol", "Add Name Space and Volume")
+AFPEntryID = uint32("afp_entry_id", "AFP Entry ID", BE)
+AFPEntryID.Display("BASE_HEX")
+AllocAvailByte = uint32("alloc_avail_byte", "Bytes Available for Allocation")
+AllocateMode = val_string16("allocate_mode", "Allocate Mode", [
+ [ 0x0000, "Permanent Directory Handle" ],
+ [ 0x0001, "Temporary Directory Handle" ],
+ [ 0x0002, "Special Temporary Directory Handle" ],
+])
+AllocationBlockSize = uint32("allocation_block_size", "Allocation Block Size")
+AllocFreeCount = uint32("alloc_free_count", "Reclaimable Free Bytes")
+ApplicationNumber = uint16("application_number", "Application Number")
+ArchivedTime = uint16("archived_time", "Archived Time")
+ArchivedTime.NWTime()
+ArchivedDate = uint16("archived_date", "Archived Date")
+ArchivedDate.NWDate()
+ArchiverID = uint32("archiver_id", "Archiver ID", BE)
+ArchiverID.Display("BASE_HEX")
+AssociatedNameSpace = uint8("associated_name_space", "Associated Name Space")
+AttachDuringProcessing = uint16("attach_during_processing", "Attach During Processing")
+AttachedIndexedFiles = uint8("attached_indexed_files", "Attached Indexed Files")
+AttachWhileProcessingAttach = uint16("attach_while_processing_attach", "Attach While Processing Attach")
+Attributes = uint32("attributes", "Attributes")
+AttributesDef = bitfield8("attr_def", "Attributes", [
+ bf_boolean8(0x01, "att_def_ro", "Read Only"),
+ bf_boolean8(0x02, "att_def_hidden", "Hidden"),
+ bf_boolean8(0x04, "att_def_system", "System"),
+ bf_boolean8(0x08, "att_def_execute", "Execute"),
+ bf_boolean8(0x10, "att_def_sub_only", "Subdirectory"),
+ bf_boolean8(0x20, "att_def_archive", "Archive"),
+ bf_boolean8(0x80, "att_def_shareable", "Shareable"),
+])
+AttributesDef16 = bitfield16("attr_def_16", "Attributes", [
+ bf_boolean16(0x0001, "att_def16_ro", "Read Only"),
+ bf_boolean16(0x0002, "att_def16_hidden", "Hidden"),
+ bf_boolean16(0x0004, "att_def16_system", "System"),
+ bf_boolean16(0x0008, "att_def16_execute", "Execute"),
+ bf_boolean16(0x0010, "att_def16_sub_only", "Subdirectory"),
+ bf_boolean16(0x0020, "att_def16_archive", "Archive"),
+ bf_boolean16(0x0080, "att_def16_shareable", "Shareable"),
+ bf_boolean16(0x1000, "att_def16_transaction", "Transactional"),
+ bf_boolean16(0x4000, "att_def16_read_audit", "Read Audit"),
+ bf_boolean16(0x8000, "att_def16_write_audit", "Write Audit"),
+])
+AttributesDef32 = bitfield32("attr_def_32", "Attributes", [
+ bf_boolean32(0x00000001, "att_def32_ro", "Read Only"),
+ bf_boolean32(0x00000002, "att_def32_hidden", "Hidden"),
+ bf_boolean32(0x00000004, "att_def32_system", "System"),
+ bf_boolean32(0x00000008, "att_def32_execute", "Execute"),
+ bf_boolean32(0x00000010, "att_def32_sub_only", "Subdirectory"),
+ bf_boolean32(0x00000020, "att_def32_archive", "Archive"),
+ bf_boolean32(0x00000080, "att_def32_shareable", "Shareable"),
+ bf_boolean32(0x00001000, "att_def32_transaction", "Transactional"),
+ bf_boolean32(0x00004000, "att_def32_read_audit", "Read Audit"),
+ bf_boolean32(0x00008000, "att_def32_write_audit", "Write Audit"),
+ bf_boolean32(0x00010000, "att_def_purge", "Purge"),
+ bf_boolean32(0x00020000, "att_def_reninhibit", "Rename Inhibit"),
+ bf_boolean32(0x00040000, "att_def_delinhibit", "Delete Inhibit"),
+ bf_boolean32(0x00080000, "att_def_cpyinhibit", "Copy Inhibit"),
+ bf_boolean32(0x02000000, "att_def_im_comp", "Immediate Compress"),
+ bf_boolean32(0x04000000, "att_def_comp", "Compressed"),
+])
+AttributeValidFlag = uint32("attribute_valid_flag", "Attribute Valid Flag")
+AuditFileVersionDate = uint16("audit_file_ver_date", "Audit File Version Date")
+AuditFileVersionDate.NWDate()
+AuditFlag = val_string8("audit_flag", "Audit Flag", [
+ [ 0x00, "Do NOT audit object" ],
+ [ 0x01, "Audit object" ],
+])
+AuditHandle = uint32("audit_handle", "Audit File Handle")
+AuditHandle.Display("BASE_HEX")
+AuditID = uint32("audit_id", "Audit ID", BE)
+AuditID.Display("BASE_HEX")
+AuditIDType = val_string16("audit_id_type", "Audit ID Type", [
+ [ 0x0000, "Volume" ],
+ [ 0x0001, "Container" ],
+])
+AuditVersionDate = uint16("audit_ver_date", "Auditing Version Date")
+AuditVersionDate.NWDate()
+AvailableBlocks = uint32("available_blocks", "Available Blocks")
+AvailableClusters = uint16("available_clusters", "Available Clusters")
+AvailableDirectorySlots = uint16("available_directory_slots", "Available Directory Slots")
+AvailableDirEntries = uint32("available_dir_entries", "Available Directory Entries")
+AvailableIndexedFiles = uint16("available_indexed_files", "Available Indexed Files")
+
+BackgroundAgedWrites = uint32("background_aged_writes", "Background Aged Writes")
+BackgroundDirtyWrites = uint32("background_dirty_writes", "Background Dirty Writes")
+BadLogicalConnectionCount = uint16("bad_logical_connection_count", "Bad Logical Connection Count")
+BannerName = fw_string("banner_name", "Banner Name", 14)
+BaseDirectoryID = uint32("base_directory_id", "Base Directory ID", BE)
+BaseDirectoryID.Display("BASE_HEX")
+binderyContext = nstring8("bindery_context", "Bindery Context")
+BitMap = bytes("bit_map", "Bit Map", 512)
+BlockNumber = uint32("block_number", "Block Number")
+BlockSize = uint16("block_size", "Block Size")
+BlockSizeInSectors = uint32("block_size_in_sectors", "Block Size in Sectors")
+BoardInstalled = uint8("board_installed", "Board Installed")
+BoardNumber = uint32("board_number", "Board Number")
+BoardNumbers = uint32("board_numbers", "Board Numbers")
+BufferSize = uint16("buffer_size", "Buffer Size")
+BusString = stringz("bus_string", "Bus String")
+BusType = val_string8("bus_type", "Bus Type", [
+ [0x00, "ISA"],
+ [0x01, "Micro Channel" ],
+ [0x02, "EISA"],
+ [0x04, "PCI"],
+ [0x08, "PCMCIA"],
+ [0x10, "ISA"],
+ [0x14, "ISA"],
+])
+BytesActuallyTransferred = uint32("bytes_actually_transferred", "Bytes Actually Transferred")
+BytesRead = fw_string("bytes_read", "Bytes Read", 6)
+BytesToCopy = uint32("bytes_to_copy", "Bytes to Copy")
+BytesWritten = fw_string("bytes_written", "Bytes Written", 6)
+
+CacheAllocations = uint32("cache_allocations", "Cache Allocations")
+CacheBlockScrapped = uint16("cache_block_scrapped", "Cache Block Scrapped")
+CacheBufferCount = uint16("cache_buffer_count", "Cache Buffer Count")
+CacheBufferSize = uint16("cache_buffer_size", "Cache Buffer Size")
+CacheFullWriteRequests = uint32("cache_full_write_requests", "Cache Full Write Requests")
+CacheGetRequests = uint32("cache_get_requests", "Cache Get Requests")
+CacheHitOnUnavailableBlock = uint16("cache_hit_on_unavailable_block", "Cache Hit On Unavailable Block")
+CacheHits = uint32("cache_hits", "Cache Hits")
+CacheMisses = uint32("cache_misses", "Cache Misses")
+CachePartialWriteRequests = uint32("cache_partial_write_requests", "Cache Partial Write Requests")
+CacheReadRequests = uint32("cache_read_requests", "Cache Read Requests")
+CacheWriteRequests = uint32("cache_write_requests", "Cache Write Requests")
+CategoryName = stringz("category_name", "Category Name")
+CCFileHandle = uint32("cc_file_handle", "File Handle")
+CCFileHandle.Display("BASE_HEX")
+CCFunction = val_string8("cc_function", "OP-Lock Flag", [
+ [ 0x01, "Clear OP-Lock" ],
+ [ 0x02, "Acknowledge Callback" ],
+ [ 0x03, "Decline Callback" ],
+ [ 0x04, "Level 2" ],
+])
+ChangeBits = bitfield16("change_bits", "Change Bits", [
+ bf_boolean16(0x0001, "change_bits_modify", "Modify Name"),
+ bf_boolean16(0x0002, "change_bits_fatt", "File Attributes"),
+ bf_boolean16(0x0004, "change_bits_cdate", "Creation Date"),
+ bf_boolean16(0x0008, "change_bits_ctime", "Creation Time"),
+ bf_boolean16(0x0010, "change_bits_owner", "Owner ID"),
+ bf_boolean16(0x0020, "change_bits_adate", "Archive Date"),
+ bf_boolean16(0x0040, "change_bits_atime", "Archive Time"),
+ bf_boolean16(0x0080, "change_bits_aid", "Archiver ID"),
+ bf_boolean16(0x0100, "change_bits_udate", "Update Date"),
+ bf_boolean16(0x0200, "change_bits_utime", "Update Time"),
+ bf_boolean16(0x0400, "change_bits_uid", "Update ID"),
+ bf_boolean16(0x0800, "change_bits_acc_date", "Access Date"),
+ bf_boolean16(0x1000, "change_bits_max_acc_mask", "Maximum Access Mask"),
+ bf_boolean16(0x2000, "change_bits_max_space", "Maximum Space"),
+])
+ChannelState = val_string8("channel_state", "Channel State", [
+ [ 0x00, "Channel is running" ],
+ [ 0x01, "Channel is stopping" ],
+ [ 0x02, "Channel is stopped" ],
+ [ 0x03, "Channel is not functional" ],
+])
+ChannelSynchronizationState = val_string8("channel_synchronization_state", "Channel Synchronization State", [
+ [ 0x00, "Channel is not being used" ],
+ [ 0x02, "NetWare is using the channel; no one else wants it" ],
+ [ 0x04, "NetWare is using the channel; someone else wants it" ],
+ [ 0x06, "Someone else is using the channel; NetWare does not need it" ],
+ [ 0x08, "Someone else is using the channel; NetWare needs it" ],
+ [ 0x0A, "Someone else has released the channel; NetWare should use it" ],
+])
+ChargeAmount = uint32("charge_amount", "Charge Amount")
+ChargeInformation = uint32("charge_information", "Charge Information")
+ClientCompFlag = val_string16("client_comp_flag", "Completion Flag", [
+ [ 0x0000, "Successful" ],
+ [ 0x0001, "Illegal Station Number" ],
+ [ 0x0002, "Client Not Logged In" ],
+ [ 0x0003, "Client Not Accepting Messages" ],
+ [ 0x0004, "Client Already has a Message" ],
+ [ 0x0096, "No Alloc Space for the Message" ],
+ [ 0x00fd, "Bad Station Number" ],
+ [ 0x00ff, "Failure" ],
+])
+ClientIDNumber = uint32("client_id_number", "Client ID Number", BE)
+ClientIDNumber.Display("BASE_HEX")
+ClientList = uint32("client_list", "Client List")
+ClientListCount = uint16("client_list_cnt", "Client List Count")
+ClientListLen = uint8("client_list_len", "Client List Length")
+ClientName = nstring8("client_name", "Client Name")
+ClientRecordArea = fw_string("client_record_area", "Client Record Area", 152)
+ClientStation = uint8("client_station", "Client Station")
+ClientStationLong = uint32("client_station_long", "Client Station")
+ClientTaskNumber = uint8("client_task_number", "Client Task Number")
+ClientTaskNumberLong = uint32("client_task_number_long", "Client Task Number")
+ClusterCount = uint16("cluster_count", "Cluster Count")
+ClustersUsedByDirectories = uint32("clusters_used_by_directories", "Clusters Used by Directories")
+ClustersUsedByExtendedDirectories = uint32("clusters_used_by_extended_dirs", "Clusters Used by Extended Directories")
+ClustersUsedByFAT = uint32("clusters_used_by_fat", "Clusters Used by FAT")
+ComCnts = uint16("com_cnts", "Communication Counters")
+Comment = nstring8("comment", "Comment")
+CommentType = uint16("comment_type", "Comment Type")
+CompletionCode = uint32("ncompletion_code", "Completion Code")
+CompressedDataStreamsCount = uint32("compressed_data_streams_count", "Compressed Data Streams Count")
+CompressedLimboDataStreamsCount = uint32("compressed_limbo_data_streams_count", "Compressed Limbo Data Streams Count")
+CompressedSectors = uint32("compressed_sectors", "Compressed Sectors")
+compressionStage = uint32("compression_stage", "Compression Stage")
+compressVolume = uint32("compress_volume", "Volume Compression")
+ConfigMajorVN = uint8("config_major_vn", "Configuration Major Version Number")
+ConfigMinorVN = uint8("config_minor_vn", "Configuration Minor Version Number")
+ConfigurationDescription = fw_string("configuration_description", "Configuration Description", 80)
+ConfigurationText = fw_string("configuration_text", "Configuration Text", 160)
+ConfiguredMaxBinderyObjects = uint16("configured_max_bindery_objects", "Configured Max Bindery Objects")
+ConfiguredMaxOpenFiles = uint16("configured_max_open_files", "Configured Max Open Files")
+ConfiguredMaxRoutingBuffers = uint16("configured_max_routing_buffers", "Configured Max Routing Buffers")
+ConfiguredMaxSimultaneousTransactions = uint16("cfg_max_simultaneous_transactions", "Configured Max Simultaneous Transactions")
+ConnectedLAN = uint32("connected_lan", "LAN Adapter")
+ConnectionControlBits = bitfield8("conn_ctrl_bits", "Connection Control", [
+ bf_boolean8(0x01, "enable_brdcasts", "Enable Broadcasts"),
+ bf_boolean8(0x02, "enable_personal_brdcasts", "Enable Personal Broadcasts"),
+ bf_boolean8(0x04, "enable_wdog_messages", "Enable Watchdog Message"),
+ bf_boolean8(0x10, "disable_brdcasts", "Disable Broadcasts"),
+ bf_boolean8(0x20, "disable_personal_brdcasts", "Disable Personal Broadcasts"),
+ bf_boolean8(0x40, "disable_wdog_messages", "Disable Watchdog Message"),
+])
+ConnectionListCount = uint32("conn_list_count", "Connection List Count")
+ConnectionList = uint32("connection_list", "Connection List")
+ConnectionNumber = uint32("connection_number", "Connection Number", BE)
+ConnectionNumberList = nstring8("connection_number_list", "Connection Number List")
+ConnectionNumberWord = uint16("conn_number_word", "Connection Number")
+ConnectionNumberByte = uint8("conn_number_byte", "Connection Number")
+ConnectionServiceType = val_string8("connection_service_type","Connection Service Type",[
+ [ 0x01, "CLIB backward Compatibility" ],
+ [ 0x02, "NCP Connection" ],
+ [ 0x03, "NLM Connection" ],
+ [ 0x04, "AFP Connection" ],
+ [ 0x05, "FTAM Connection" ],
+ [ 0x06, "ANCP Connection" ],
+ [ 0x07, "ACP Connection" ],
+ [ 0x08, "SMB Connection" ],
+ [ 0x09, "Winsock Connection" ],
+])
+ConnectionsInUse = uint16("connections_in_use", "Connections In Use")
+ConnectionsMaxUsed = uint16("connections_max_used", "Connections Max Used")
+ConnectionsSupportedMax = uint16("connections_supported_max", "Connections Supported Max")
+ConnectionType = val_string8("connection_type", "Connection Type", [
+ [ 0x00, "Not in use" ],
+ [ 0x02, "NCP" ],
+ [ 0x11, "UDP (for IP)" ],
+])
+ConnListLen = uint8("conn_list_len", "Connection List Length")
+Copyright = nstring8("copyright", "Copyright")
+connList = uint32("conn_list", "Connection List")
+ControlFlags = val_string8("control_flags", "Control Flags", [
+ [ 0x00, "Forced Record Locking is Off" ],
+ [ 0x01, "Forced Record Locking is On" ],
+])
+ControllerDriveNumber = uint8("controller_drive_number", "Controller Drive Number")
+ControllerNumber = uint8("controller_number", "Controller Number")
+ControllerType = uint8("controller_type", "Controller Type")
+Cookie1 = uint32("cookie_1", "Cookie 1")
+Cookie2 = uint32("cookie_2", "Cookie 2")
+Copies = uint8( "copies", "Copies" )
+CoprocessorFlag = uint32("co_processor_flag", "CoProcessor Present Flag")
+CoProcessorString = stringz("co_proc_string", "CoProcessor String")
+CounterMask = val_string8("counter_mask", "Counter Mask", [
+ [ 0x00, "Counter is Valid" ],
+ [ 0x01, "Counter is not Valid" ],
+])
+CPUNumber = uint32("cpu_number", "CPU Number")
+CPUString = stringz("cpu_string", "CPU String")
+CPUType = val_string8("cpu_type", "CPU Type", [
+ [ 0x00, "80386" ],
+ [ 0x01, "80486" ],
+ [ 0x02, "Pentium" ],
+ [ 0x03, "Pentium Pro" ],
+])
+CreationDate = uint16("creation_date", "Creation Date")
+CreationDate.NWDate()
+CreationTime = uint16("creation_time", "Creation Time")
+CreationTime.NWTime()
+CreatorID = uint32("creator_id", "Creator ID", BE)
+CreatorID.Display("BASE_HEX")
+CreatorNameSpaceNumber = val_string8("creator_name_space_number", "Creator Name Space Number", [
+ [ 0x00, "DOS Name Space" ],
+ [ 0x01, "MAC Name Space" ],
+ [ 0x02, "NFS Name Space" ],
+ [ 0x04, "Long Name Space" ],
+])
+CreditLimit = uint32("credit_limit", "Credit Limit")
+CtrlFlags = val_string16("ctrl_flags", "Control Flags", [
+ [ 0x0000, "Do Not Return File Name" ],
+ [ 0x0001, "Return File Name" ],
+])
+curCompBlks = uint32("cur_comp_blks", "Current Compression Blocks")
+curInitialBlks = uint32("cur_initial_blks", "Current Initial Blocks")
+curIntermediateBlks = uint32("cur_inter_blks", "Current Intermediate Blocks")
+CurNumOfRTags = uint32("cur_num_of_r_tags", "Current Number of Resource Tags")
+CurrentBlockBeingDecompressed = uint32("cur_blk_being_dcompress", "Current Block Being Decompressed")
+CurrentChangedFATs = uint16("current_changed_fats", "Current Changed FAT Entries")
+CurrentEntries = uint32("current_entries", "Current Entries")
+CurrentFormType = uint8( "current_form_type", "Current Form Type" )
+CurrentLFSCounters = uint32("current_lfs_counters", "Current LFS Counters")
+CurrentlyUsedRoutingBuffers = uint16("currently_used_routing_buffers", "Currently Used Routing Buffers")
+CurrentOpenFiles = uint16("current_open_files", "Current Open Files")
+CurrentReferenceID = uint16("curr_ref_id", "Current Reference ID")
+CurrentServers = uint32("current_servers", "Current Servers")
+CurrentServerTime = uint32("current_server_time", "Time Elapsed Since Server Was Brought Up")
+CurrentSpace = uint32("current_space", "Current Space")
+CurrentTransactionCount = uint32("current_trans_count", "Current Transaction Count")
+CurrentUsedBinderyObjects = uint16("current_used_bindery_objects", "Current Used Bindery Objects")
+CurrentUsedDynamicSpace = uint32("current_used_dynamic_space", "Current Used Dynamic Space")
+CustomCnts = uint32("custom_cnts", "Custom Counters")
+CustomCount = uint32("custom_count", "Custom Count")
+CustomCounters = uint32("custom_counters", "Custom Counters")
+CustomString = nstring8("custom_string", "Custom String")
+CustomVariableValue = uint32("custom_var_value", "Custom Variable Value")
+
+Data = nstring8("data", "Data")
+DataForkFirstFAT = uint32("data_fork_first_fat", "Data Fork First FAT Entry")
+DataForkLen = uint32("data_fork_len", "Data Fork Len")
+DataForkSize = uint32("data_fork_size", "Data Fork Size")
+DataSize = uint32("data_size", "Data Size")
+DataStream = val_string8("data_stream", "Data Stream", [
+ [ 0x00, "Resource Fork or DOS" ],
+ [ 0x01, "Data Fork" ],
+])
+DataStreamName = nstring8("data_stream_name", "Data Stream Name")
+DataStreamNumber = uint8("data_stream_number", "Data Stream Number")
+DataStreamsCount = uint32("data_streams_count", "Data Streams Count")
+DataStreamSize = uint32("data_stream_size", "Size")
+DataStreamSpaceAlloc = uint32( "data_stream_space_alloc", "Space Allocated for Data Stream" )
+Day = uint8("s_day", "Day")
+DayOfWeek = val_string8("s_day_of_week", "Day of Week", [
+ [ 0x00, "Sunday" ],
+ [ 0x01, "Monday" ],
+ [ 0x02, "Tuesday" ],
+ [ 0x03, "Wednesday" ],
+ [ 0x04, "Thursday" ],
+ [ 0x05, "Friday" ],
+ [ 0x06, "Saturday" ],
+])
+DeadMirrorTable = bytes("dead_mirror_table", "Dead Mirror Table", 32)
+DefinedDataStreams = uint8("defined_data_streams", "Defined Data Streams")
+DefinedNameSpaces = uint8("defined_name_spaces", "Defined Name Spaces")
+DeletedDate = uint16("deleted_date", "Deleted Date")
+DeletedDate.NWDate()
+DeletedFileTime = uint32( "deleted_file_time", "Deleted File Time")
+DeletedFileTime.Display("BASE_HEX")
+DeletedTime = uint16("deleted_time", "Deleted Time")
+DeletedTime.NWTime()
+DeletedID = uint32( "delete_id", "Deleted ID", BE)
+DeletedID.Display("BASE_HEX")
+DeleteExistingFileFlag = val_string8("delete_existing_file_flag", "Delete Existing File Flag", [
+ [ 0x00, "Do Not Delete Existing File" ],
+ [ 0x01, "Delete Existing File" ],
+])
+DenyReadCount = uint16("deny_read_count", "Deny Read Count")
+DenyWriteCount = uint16("deny_write_count", "Deny Write Count")
+DescriptionStrings = fw_string("description_string", "Description", 100)
+DesiredAccessRights = bitfield16("desired_access_rights", "Desired Access Rights", [
+ bf_boolean16(0x0001, "dsired_acc_rights_read_o", "Read Only"),
+ bf_boolean16(0x0002, "dsired_acc_rights_write_o", "Write Only"),
+ bf_boolean16(0x0004, "dsired_acc_rights_deny_r", "Deny Read"),
+ bf_boolean16(0x0008, "dsired_acc_rights_deny_w", "Deny Write"),
+ bf_boolean16(0x0010, "dsired_acc_rights_compat", "Compatibility"),
+ bf_boolean16(0x0040, "dsired_acc_rights_w_thru", "File Write Through"),
+ bf_boolean16(0x0400, "dsired_acc_rights_del_file_cls", "Delete File Close"),
+])
+DesiredResponseCount = uint16("desired_response_count", "Desired Response Count")
+DestDirHandle = uint8("dest_dir_handle", "Destination Directory Handle")
+DestNameSpace = val_string8("dest_name_space", "Destination Name Space", [
+ [ 0x00, "DOS Name Space" ],
+ [ 0x01, "MAC Name Space" ],
+ [ 0x02, "NFS Name Space" ],
+ [ 0x04, "Long Name Space" ],
+])
+DestPathComponentCount = uint8("dest_component_count", "Destination Path Component Count")
+DestPath = nstring8("dest_path", "Destination Path")
+DetachDuringProcessing = uint16("detach_during_processing", "Detach During Processing")
+DetachForBadConnectionNumber = uint16("detach_for_bad_connection_number", "Detach For Bad Connection Number")
+DirHandle = uint8("dir_handle", "Directory Handle")
+DirHandleName = uint8("dir_handle_name", "Handle Name")
+DirHandleLong = uint32("dir_handle_long", "Directory Handle")
+DirectoryAccessRights = uint8("directory_access_rights", "Directory Access Rights")
+#
+# XXX - what do the bits mean here?
+#
+DirectoryAttributes = uint8("directory_attributes", "Directory Attributes")
+DirectoryBase = uint32("dir_base", "Directory Base")
+DirectoryBase.Display("BASE_HEX")
+DirectoryCount = uint16("dir_count", "Directory Count")
+DirectoryEntryNumber = uint32("directory_entry_number", "Directory Entry Number")
+DirectoryEntryNumber.Display('BASE_HEX')
+DirectoryEntryNumberWord = uint16("directory_entry_number_word", "Directory Entry Number")
+DirectoryID = uint16("directory_id", "Directory ID", BE)
+DirectoryID.Display("BASE_HEX")
+DirectoryName = fw_string("directory_name", "Directory Name",12)
+DirectoryName14 = fw_string("directory_name_14", "Directory Name", 14)
+DirectoryNameLen = uint8("directory_name_len", "Directory Name Length")
+DirectoryNumber = uint32("directory_number", "Directory Number")
+DirectoryNumber.Display("BASE_HEX")
+DirectoryPath = fw_string("directory_path", "Directory Path", 16)
+DirectoryServicesObjectID = uint32("directory_services_object_id", "Directory Services Object ID")
+DirectoryServicesObjectID.Display("BASE_HEX")
+DirectoryStamp = uint16("directory_stamp", "Directory Stamp (0xD1D1)")
+DirtyCacheBuffers = uint16("dirty_cache_buffers", "Dirty Cache Buffers")
+DiskChannelNumber = uint8("disk_channel_number", "Disk Channel Number")
+DiskChannelTable = val_string8("disk_channel_table", "Disk Channel Table", [
+ [ 0x01, "XT" ],
+ [ 0x02, "AT" ],
+ [ 0x03, "SCSI" ],
+ [ 0x04, "Disk Coprocessor" ],
+])
+DiskSpaceLimit = uint32("disk_space_limit", "Disk Space Limit")
+DMAChannelsUsed = uint32("dma_channels_used", "DMA Channels Used")
+DMInfoEntries = uint32("dm_info_entries", "DM Info Entries")
+DMInfoLevel = val_string8("dm_info_level", "DM Info Level", [
+ [ 0x00, "Return Detailed DM Support Module Information" ],
+ [ 0x01, "Return Number of DM Support Modules" ],
+ [ 0x02, "Return DM Support Modules Names" ],
+])
+DMFlags = val_string8("dm_flags", "DM Flags", [
+ [ 0x00, "OnLine Media" ],
+ [ 0x01, "OffLine Media" ],
+])
+DMmajorVersion = uint32("dm_major_version", "DM Major Version")
+DMminorVersion = uint32("dm_minor_version", "DM Minor Version")
+DMPresentFlag = val_string8("dm_present_flag", "Data Migration Present Flag", [
+ [ 0x00, "Data Migration NLM is not loaded" ],
+ [ 0x01, "Data Migration NLM has been loaded and is running" ],
+])
+DOSDirectoryBase = uint32("dos_directory_base", "DOS Directory Base")
+DOSDirectoryBase.Display("BASE_HEX")
+DOSDirectoryEntry = uint32("dos_directory_entry", "DOS Directory Entry")
+DOSDirectoryEntry.Display("BASE_HEX")
+DOSDirectoryEntryNumber = uint32("dos_directory_entry_number", "DOS Directory Entry Number")
+DOSDirectoryEntryNumber.Display('BASE_HEX')
+DOSFileAttributes = uint8("dos_file_attributes", "DOS File Attributes")
+DOSParentDirectoryEntry = uint32("dos_parent_directory_entry", "DOS Parent Directory Entry")
+DOSParentDirectoryEntry.Display('BASE_HEX')
+DOSSequence = uint32("dos_sequence", "DOS Sequence")
+DriveCylinders = uint16("drive_cylinders", "Drive Cylinders")
+DriveDefinitionString = fw_string("drive_definition_string", "Drive Definition", 64)
+DriveHeads = uint8("drive_heads", "Drive Heads")
+DriveMappingTable = bytes("drive_mapping_table", "Drive Mapping Table", 32)
+DriveMirrorTable = bytes("drive_mirror_table", "Drive Mirror Table", 32)
+DriverBoardName = stringz("driver_board_name", "Driver Board Name")
+DriveRemovableFlag = val_string8("drive_removable_flag", "Drive Removable Flag", [
+ [ 0x00, "Nonremovable" ],
+ [ 0xff, "Removable" ],
+])
+DriverLogicalName = stringz("driver_log_name", "Driver Logical Name")
+DriverShortName = stringz("driver_short_name", "Driver Short Name")
+DriveSize = uint32("drive_size", "Drive Size")
+DstEAFlags = val_string16("dst_ea_flags", "Destination EA Flags", [
+ [ 0x0000, "Return EAHandle,Information Level 0" ],
+ [ 0x0001, "Return NetWareHandle,Information Level 0" ],
+ [ 0x0002, "Return Volume/Directory Number,Information Level 0" ],
+ [ 0x0004, "Return EAHandle,Close Handle on Error,Information Level 0" ],
+ [ 0x0005, "Return NetWareHandle,Close Handle on Error,Information Level 0" ],
+ [ 0x0006, "Return Volume/Directory Number,Close Handle on Error,Information Level 0" ],
+ [ 0x0010, "Return EAHandle,Information Level 1" ],
+ [ 0x0011, "Return NetWareHandle,Information Level 1" ],
+ [ 0x0012, "Return Volume/Directory Number,Information Level 1" ],
+ [ 0x0014, "Return EAHandle,Close Handle on Error,Information Level 1" ],
+ [ 0x0015, "Return NetWareHandle,Close Handle on Error,Information Level 1" ],
+ [ 0x0016, "Return Volume/Directory Number,Close Handle on Error,Information Level 1" ],
+ [ 0x0020, "Return EAHandle,Information Level 2" ],
+ [ 0x0021, "Return NetWareHandle,Information Level 2" ],
+ [ 0x0022, "Return Volume/Directory Number,Information Level 2" ],
+ [ 0x0024, "Return EAHandle,Close Handle on Error,Information Level 2" ],
+ [ 0x0025, "Return NetWareHandle,Close Handle on Error,Information Level 2" ],
+ [ 0x0026, "Return Volume/Directory Number,Close Handle on Error,Information Level 2" ],
+ [ 0x0030, "Return EAHandle,Information Level 3" ],
+ [ 0x0031, "Return NetWareHandle,Information Level 3" ],
+ [ 0x0032, "Return Volume/Directory Number,Information Level 3" ],
+ [ 0x0034, "Return EAHandle,Close Handle on Error,Information Level 3" ],
+ [ 0x0035, "Return NetWareHandle,Close Handle on Error,Information Level 3" ],
+ [ 0x0036, "Return Volume/Directory Number,Close Handle on Error,Information Level 3" ],
+ [ 0x0040, "Return EAHandle,Information Level 4" ],
+ [ 0x0041, "Return NetWareHandle,Information Level 4" ],
+ [ 0x0042, "Return Volume/Directory Number,Information Level 4" ],
+ [ 0x0044, "Return EAHandle,Close Handle on Error,Information Level 4" ],
+ [ 0x0045, "Return NetWareHandle,Close Handle on Error,Information Level 4" ],
+ [ 0x0046, "Return Volume/Directory Number,Close Handle on Error,Information Level 4" ],
+ [ 0x0050, "Return EAHandle,Information Level 5" ],
+ [ 0x0051, "Return NetWareHandle,Information Level 5" ],
+ [ 0x0052, "Return Volume/Directory Number,Information Level 5" ],
+ [ 0x0054, "Return EAHandle,Close Handle on Error,Information Level 5" ],
+ [ 0x0055, "Return NetWareHandle,Close Handle on Error,Information Level 5" ],
+ [ 0x0056, "Return Volume/Directory Number,Close Handle on Error,Information Level 5" ],
+ [ 0x0060, "Return EAHandle,Information Level 6" ],
+ [ 0x0061, "Return NetWareHandle,Information Level 6" ],
+ [ 0x0062, "Return Volume/Directory Number,Information Level 6" ],
+ [ 0x0064, "Return EAHandle,Close Handle on Error,Information Level 6" ],
+ [ 0x0065, "Return NetWareHandle,Close Handle on Error,Information Level 6" ],
+ [ 0x0066, "Return Volume/Directory Number,Close Handle on Error,Information Level 6" ],
+ [ 0x0070, "Return EAHandle,Information Level 7" ],
+ [ 0x0071, "Return NetWareHandle,Information Level 7" ],
+ [ 0x0072, "Return Volume/Directory Number,Information Level 7" ],
+ [ 0x0074, "Return EAHandle,Close Handle on Error,Information Level 7" ],
+ [ 0x0075, "Return NetWareHandle,Close Handle on Error,Information Level 7" ],
+ [ 0x0076, "Return Volume/Directory Number,Close Handle on Error,Information Level 7" ],
+ [ 0x0080, "Return EAHandle,Information Level 0,Immediate Close Handle" ],
+ [ 0x0081, "Return NetWareHandle,Information Level 0,Immediate Close Handle" ],
+ [ 0x0082, "Return Volume/Directory Number,Information Level 0,Immediate Close Handle" ],
+ [ 0x0084, "Return EAHandle,Close Handle on Error,Information Level 0,Immediate Close Handle" ],
+ [ 0x0085, "Return NetWareHandle,Close Handle on Error,Information Level 0,Immediate Close Handle" ],
+ [ 0x0086, "Return Volume/Directory Number,Close Handle on Error,Information Level 0,Immediate Close Handle" ],
+ [ 0x0090, "Return EAHandle,Information Level 1,Immediate Close Handle" ],
+ [ 0x0091, "Return NetWareHandle,Information Level 1,Immediate Close Handle" ],
+ [ 0x0092, "Return Volume/Directory Number,Information Level 1,Immediate Close Handle" ],
+ [ 0x0094, "Return EAHandle,Close Handle on Error,Information Level 1,Immediate Close Handle" ],
+ [ 0x0095, "Return NetWareHandle,Close Handle on Error,Information Level 1,Immediate Close Handle" ],
+ [ 0x0096, "Return Volume/Directory Number,Close Handle on Error,Information Level 1,Immediate Close Handle" ],
+ [ 0x00a0, "Return EAHandle,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a1, "Return NetWareHandle,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a2, "Return Volume/Directory Number,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a4, "Return EAHandle,Close Handle on Error,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a5, "Return NetWareHandle,Close Handle on Error,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a6, "Return Volume/Directory Number,Close Handle on Error,Information Level 2,Immediate Close Handle" ],
+ [ 0x00b0, "Return EAHandle,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b1, "Return NetWareHandle,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b2, "Return Volume/Directory Number,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b4, "Return EAHandle,Close Handle on Error,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b5, "Return NetWareHandle,Close Handle on Error,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b6, "Return Volume/Directory Number,Close Handle on Error,Information Level 3,Immediate Close Handle" ],
+ [ 0x00c0, "Return EAHandle,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c1, "Return NetWareHandle,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c2, "Return Volume/Directory Number,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c4, "Return EAHandle,Close Handle on Error,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c5, "Return NetWareHandle,Close Handle on Error,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c6, "Return Volume/Directory Number,Close Handle on Error,Information Level 4,Immediate Close Handle" ],
+ [ 0x00d0, "Return EAHandle,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d1, "Return NetWareHandle,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d2, "Return Volume/Directory Number,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d4, "Return EAHandle,Close Handle on Error,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d5, "Return NetWareHandle,Close Handle on Error,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d6, "Return Volume/Directory Number,Close Handle on Error,Information Level 5,Immediate Close Handle" ],
+ [ 0x00e0, "Return EAHandle,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e1, "Return NetWareHandle,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e2, "Return Volume/Directory Number,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e4, "Return EAHandle,Close Handle on Error,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e5, "Return NetWareHandle,Close Handle on Error,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e6, "Return Volume/Directory Number,Close Handle on Error,Information Level 6,Immediate Close Handle" ],
+ [ 0x00f0, "Return EAHandle,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f1, "Return NetWareHandle,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f2, "Return Volume/Directory Number,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f4, "Return EAHandle,Close Handle on Error,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f5, "Return NetWareHandle,Close Handle on Error,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f6, "Return Volume/Directory Number,Close Handle on Error,Information Level 7,Immediate Close Handle" ],
+])
+dstNSIndicator = val_string16("dst_ns_indicator", "Destination Name Space Indicator", [
+ [ 0x0000, "Return Source Name Space Information" ],
+ [ 0x0001, "Return Destination Name Space Information" ],
+])
+DstQueueID = uint32("dst_queue_id", "Destination Queue ID")
+DuplicateRepliesSent = uint16("duplicate_replies_sent", "Duplicate Replies Sent")
+
+EAAccessFlag = bitfield16("ea_access_flag", "EA Access Flag", [
+ bf_boolean16(0x0001, "ea_permanent_memory", "Permanent Memory"),
+ bf_boolean16(0x0002, "ea_deep_freeze", "Deep Freeze"),
+ bf_boolean16(0x0004, "ea_in_progress", "In Progress"),
+ bf_boolean16(0x0008, "ea_header_being_enlarged", "Header Being Enlarged"),
+ bf_boolean16(0x0010, "ea_new_tally_used", "New Tally Used"),
+ bf_boolean16(0x0020, "ea_tally_need_update", "Tally Need Update"),
+ bf_boolean16(0x0040, "ea_score_card_present", "Score Card Present"),
+ bf_boolean16(0x0080, "ea_need_bit_flag", "EA Need Bit Flag"),
+ bf_boolean16(0x0100, "ea_write_privileges", "Write Privileges"),
+ bf_boolean16(0x0200, "ea_read_privileges", "Read Privileges"),
+ bf_boolean16(0x0400, "ea_delete_privileges", "Delete Privileges"),
+ bf_boolean16(0x0800, "ea_system_ea_only", "System EA Only"),
+ bf_boolean16(0x1000, "ea_write_in_progress", "Write In Progress"),
+])
+EABytesWritten = uint32("ea_bytes_written", "Bytes Written")
+EACount = uint32("ea_count", "Count")
+EADataSize = uint32("ea_data_size", "Data Size")
+EADataSizeDuplicated = uint32("ea_data_size_duplicated", "Data Size Duplicated")
+EADuplicateCount = uint32("ea_duplicate_count", "Duplicate Count")
+EAErrorCodes = val_string16("ea_error_codes", "EA Error Codes", [
+ [ 0x0000, "SUCCESSFUL" ],
+ [ 0x00c8, "ERR_MISSING_EA_KEY" ],
+ [ 0x00c9, "ERR_EA_NOT_FOUND" ],
+ [ 0x00ca, "ERR_INVALID_EA_HANDLE_TYPE" ],
+ [ 0x00cb, "ERR_EA_NO_KEY_NO_DATA" ],
+ [ 0x00cc, "ERR_EA_NUMBER_MISMATCH" ],
+ [ 0x00cd, "ERR_EXTENT_NUMBER_OUT_OF_RANGE" ],
+ [ 0x00ce, "ERR_EA_BAD_DIR_NUM" ],
+ [ 0x00cf, "ERR_INVALID_EA_HANDLE" ],
+ [ 0x00d0, "ERR_EA_POSITION_OUT_OF_RANGE" ],
+ [ 0x00d1, "ERR_EA_ACCESS_DENIED" ],
+ [ 0x00d2, "ERR_DATA_PAGE_ODD_SIZE" ],
+ [ 0x00d3, "ERR_EA_VOLUME_NOT_MOUNTED" ],
+ [ 0x00d4, "ERR_BAD_PAGE_BOUNDARY" ],
+ [ 0x00d5, "ERR_INSPECT_FAILURE" ],
+ [ 0x00d6, "ERR_EA_ALREADY_CLAIMED" ],
+ [ 0x00d7, "ERR_ODD_BUFFER_SIZE" ],
+ [ 0x00d8, "ERR_NO_SCORECARDS" ],
+ [ 0x00d9, "ERR_BAD_EDS_SIGNATURE" ],
+ [ 0x00da, "ERR_EA_SPACE_LIMIT" ],
+ [ 0x00db, "ERR_EA_KEY_CORRUPT" ],
+ [ 0x00dc, "ERR_EA_KEY_LIMIT" ],
+ [ 0x00dd, "ERR_TALLY_CORRUPT" ],
+])
+EAFlags = val_string16("ea_flags", "EA Flags", [
+ [ 0x0000, "Return EAHandle,Information Level 0" ],
+ [ 0x0001, "Return NetWareHandle,Information Level 0" ],
+ [ 0x0002, "Return Volume/Directory Number,Information Level 0" ],
+ [ 0x0004, "Return EAHandle,Close Handle on Error,Information Level 0" ],
+ [ 0x0005, "Return NetWareHandle,Close Handle on Error,Information Level 0" ],
+ [ 0x0006, "Return Volume/Directory Number,Close Handle on Error,Information Level 0" ],
+ [ 0x0010, "Return EAHandle,Information Level 1" ],
+ [ 0x0011, "Return NetWareHandle,Information Level 1" ],
+ [ 0x0012, "Return Volume/Directory Number,Information Level 1" ],
+ [ 0x0014, "Return EAHandle,Close Handle on Error,Information Level 1" ],
+ [ 0x0015, "Return NetWareHandle,Close Handle on Error,Information Level 1" ],
+ [ 0x0016, "Return Volume/Directory Number,Close Handle on Error,Information Level 1" ],
+ [ 0x0020, "Return EAHandle,Information Level 2" ],
+ [ 0x0021, "Return NetWareHandle,Information Level 2" ],
+ [ 0x0022, "Return Volume/Directory Number,Information Level 2" ],
+ [ 0x0024, "Return EAHandle,Close Handle on Error,Information Level 2" ],
+ [ 0x0025, "Return NetWareHandle,Close Handle on Error,Information Level 2" ],
+ [ 0x0026, "Return Volume/Directory Number,Close Handle on Error,Information Level 2" ],
+ [ 0x0030, "Return EAHandle,Information Level 3" ],
+ [ 0x0031, "Return NetWareHandle,Information Level 3" ],
+ [ 0x0032, "Return Volume/Directory Number,Information Level 3" ],
+ [ 0x0034, "Return EAHandle,Close Handle on Error,Information Level 3" ],
+ [ 0x0035, "Return NetWareHandle,Close Handle on Error,Information Level 3" ],
+ [ 0x0036, "Return Volume/Directory Number,Close Handle on Error,Information Level 3" ],
+ [ 0x0040, "Return EAHandle,Information Level 4" ],
+ [ 0x0041, "Return NetWareHandle,Information Level 4" ],
+ [ 0x0042, "Return Volume/Directory Number,Information Level 4" ],
+ [ 0x0044, "Return EAHandle,Close Handle on Error,Information Level 4" ],
+ [ 0x0045, "Return NetWareHandle,Close Handle on Error,Information Level 4" ],
+ [ 0x0046, "Return Volume/Directory Number,Close Handle on Error,Information Level 4" ],
+ [ 0x0050, "Return EAHandle,Information Level 5" ],
+ [ 0x0051, "Return NetWareHandle,Information Level 5" ],
+ [ 0x0052, "Return Volume/Directory Number,Information Level 5" ],
+ [ 0x0054, "Return EAHandle,Close Handle on Error,Information Level 5" ],
+ [ 0x0055, "Return NetWareHandle,Close Handle on Error,Information Level 5" ],
+ [ 0x0056, "Return Volume/Directory Number,Close Handle on Error,Information Level 5" ],
+ [ 0x0060, "Return EAHandle,Information Level 6" ],
+ [ 0x0061, "Return NetWareHandle,Information Level 6" ],
+ [ 0x0062, "Return Volume/Directory Number,Information Level 6" ],
+ [ 0x0064, "Return EAHandle,Close Handle on Error,Information Level 6" ],
+ [ 0x0065, "Return NetWareHandle,Close Handle on Error,Information Level 6" ],
+ [ 0x0066, "Return Volume/Directory Number,Close Handle on Error,Information Level 6" ],
+ [ 0x0070, "Return EAHandle,Information Level 7" ],
+ [ 0x0071, "Return NetWareHandle,Information Level 7" ],
+ [ 0x0072, "Return Volume/Directory Number,Information Level 7" ],
+ [ 0x0074, "Return EAHandle,Close Handle on Error,Information Level 7" ],
+ [ 0x0075, "Return NetWareHandle,Close Handle on Error,Information Level 7" ],
+ [ 0x0076, "Return Volume/Directory Number,Close Handle on Error,Information Level 7" ],
+ [ 0x0080, "Return EAHandle,Information Level 0,Immediate Close Handle" ],
+ [ 0x0081, "Return NetWareHandle,Information Level 0,Immediate Close Handle" ],
+ [ 0x0082, "Return Volume/Directory Number,Information Level 0,Immediate Close Handle" ],
+ [ 0x0084, "Return EAHandle,Close Handle on Error,Information Level 0,Immediate Close Handle" ],
+ [ 0x0085, "Return NetWareHandle,Close Handle on Error,Information Level 0,Immediate Close Handle" ],
+ [ 0x0086, "Return Volume/Directory Number,Close Handle on Error,Information Level 0,Immediate Close Handle" ],
+ [ 0x0090, "Return EAHandle,Information Level 1,Immediate Close Handle" ],
+ [ 0x0091, "Return NetWareHandle,Information Level 1,Immediate Close Handle" ],
+ [ 0x0092, "Return Volume/Directory Number,Information Level 1,Immediate Close Handle" ],
+ [ 0x0094, "Return EAHandle,Close Handle on Error,Information Level 1,Immediate Close Handle" ],
+ [ 0x0095, "Return NetWareHandle,Close Handle on Error,Information Level 1,Immediate Close Handle" ],
+ [ 0x0096, "Return Volume/Directory Number,Close Handle on Error,Information Level 1,Immediate Close Handle" ],
+ [ 0x00a0, "Return EAHandle,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a1, "Return NetWareHandle,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a2, "Return Volume/Directory Number,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a4, "Return EAHandle,Close Handle on Error,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a5, "Return NetWareHandle,Close Handle on Error,Information Level 2,Immediate Close Handle" ],
+ [ 0x00a6, "Return Volume/Directory Number,Close Handle on Error,Information Level 2,Immediate Close Handle" ],
+ [ 0x00b0, "Return EAHandle,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b1, "Return NetWareHandle,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b2, "Return Volume/Directory Number,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b4, "Return EAHandle,Close Handle on Error,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b5, "Return NetWareHandle,Close Handle on Error,Information Level 3,Immediate Close Handle" ],
+ [ 0x00b6, "Return Volume/Directory Number,Close Handle on Error,Information Level 3,Immediate Close Handle" ],
+ [ 0x00c0, "Return EAHandle,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c1, "Return NetWareHandle,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c2, "Return Volume/Directory Number,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c4, "Return EAHandle,Close Handle on Error,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c5, "Return NetWareHandle,Close Handle on Error,Information Level 4,Immediate Close Handle" ],
+ [ 0x00c6, "Return Volume/Directory Number,Close Handle on Error,Information Level 4,Immediate Close Handle" ],
+ [ 0x00d0, "Return EAHandle,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d1, "Return NetWareHandle,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d2, "Return Volume/Directory Number,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d4, "Return EAHandle,Close Handle on Error,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d5, "Return NetWareHandle,Close Handle on Error,Information Level 5,Immediate Close Handle" ],
+ [ 0x00d6, "Return Volume/Directory Number,Close Handle on Error,Information Level 5,Immediate Close Handle" ],
+ [ 0x00e0, "Return EAHandle,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e1, "Return NetWareHandle,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e2, "Return Volume/Directory Number,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e4, "Return EAHandle,Close Handle on Error,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e5, "Return NetWareHandle,Close Handle on Error,Information Level 6,Immediate Close Handle" ],
+ [ 0x00e6, "Return Volume/Directory Number,Close Handle on Error,Information Level 6,Immediate Close Handle" ],
+ [ 0x00f0, "Return EAHandle,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f1, "Return NetWareHandle,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f2, "Return Volume/Directory Number,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f4, "Return EAHandle,Close Handle on Error,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f5, "Return NetWareHandle,Close Handle on Error,Information Level 7,Immediate Close Handle" ],
+ [ 0x00f6, "Return Volume/Directory Number,Close Handle on Error,Information Level 7,Immediate Close Handle" ],
+])
+EAHandle = uint32("ea_handle", "EA Handle")
+EAHandle.Display("BASE_HEX")
+EAHandleOrNetWareHandleOrVolume = uint32("ea_handle_or_netware_handle_or_volume", "EAHandle or NetWare Handle or Volume (see EAFlags)")
+EAHandleOrNetWareHandleOrVolume.Display("BASE_HEX")
+EAKey = nstring16("ea_key", "EA Key")
+EAKeySize = uint32("ea_key_size", "Key Size")
+EAKeySizeDuplicated = uint32("ea_key_size_duplicated", "Key Size Duplicated")
+EAValue = nstring16("ea_value", "EA Value")
+EAValueRep = fw_string("ea_value_rep", "EA Value", 1)
+EAValueLength = uint16("ea_value_length", "Value Length")
+EchoSocket = uint16("echo_socket", "Echo Socket")
+EchoSocket.Display('BASE_HEX')
+EffectiveRights = bitfield8("effective_rights", "Effective Rights", [
+ bf_boolean8(0x01, "effective_rights_read", "Read Rights"),
+ bf_boolean8(0x02, "effective_rights_write", "Write Rights"),
+ bf_boolean8(0x04, "effective_rights_open", "Open Rights"),
+ bf_boolean8(0x08, "effective_rights_create", "Create Rights"),
+ bf_boolean8(0x10, "effective_rights_delete", "Delete Rights"),
+ bf_boolean8(0x20, "effective_rights_parental", "Parental Rights"),
+ bf_boolean8(0x40, "effective_rights_search", "Search Rights"),
+ bf_boolean8(0x80, "effective_rights_modify", "Modify Rights"),
+])
+EnumInfoMask = bitfield8("enum_info_mask", "Return Information Mask", [
+ bf_boolean8(0x01, "enum_info_transport", "Transport Information"),
+ bf_boolean8(0x02, "enum_info_time", "Time Information"),
+ bf_boolean8(0x04, "enum_info_name", "Name Information"),
+ bf_boolean8(0x08, "enum_info_lock", "Lock Information"),
+ bf_boolean8(0x10, "enum_info_print", "Print Information"),
+ bf_boolean8(0x20, "enum_info_stats", "Statistical Information"),
+ bf_boolean8(0x40, "enum_info_account", "Accounting Information"),
+ bf_boolean8(0x80, "enum_info_auth", "Authentication Information"),
+])
+
+eventOffset = bytes("event_offset", "Event Offset", 8)
+eventOffset.Display("BASE_HEX")
+eventTime = uint32("event_time", "Event Time")
+eventTime.Display("BASE_HEX")
+ExpirationTime = uint32("expiration_time", "Expiration Time")
+ExpirationTime.Display('BASE_HEX')
+ExtAttrDataSize = uint32("ext_attr_data_size", "Extended Attributes Data Size")
+ExtAttrCount = uint32("ext_attr_count", "Extended Attributes Count")
+ExtAttrKeySize = uint32("ext_attr_key_size", "Extended Attributes Key Size")
+ExtendedAttributesDefined = uint32("extended_attributes_defined", "Extended Attributes Defined")
+ExtendedAttributeExtantsUsed = uint32("extended_attribute_extants_used", "Extended Attribute Extants Used")
+ExtendedInfo = bitfield16("ext_info", "Extended Return Information", [
+ bf_boolean16(0x0001, "ext_info_update", "Update"),
+ bf_boolean16(0x0002, "ext_info_dos_name", "DOS Name"),
+ bf_boolean16(0x0004, "ext_info_flush", "Flush"),
+ bf_boolean16(0x0008, "ext_info_parental", "Parental"),
+ bf_boolean16(0x0010, "ext_info_mac_finder", "MAC Finder"),
+ bf_boolean16(0x0020, "ext_info_sibling", "Sibling"),
+ bf_boolean16(0x0040, "ext_info_effective", "Effective"),
+ bf_boolean16(0x0080, "ext_info_mac_date", "MAC Date"),
+ bf_boolean16(0x0100, "ext_info_access", "Last Access"),
+ bf_boolean16(0x0400, "ext_info_64_bit_fs", "64 Bit File Sizes"),
+ bf_boolean16(0x8000, "ext_info_newstyle", "New Style"),
+])
+ExtRouterActiveFlag = boolean8("ext_router_active_flag", "External Router Active Flag")
+
+FailedAllocReqCnt = uint32("failed_alloc_req", "Failed Alloc Request Count")
+FatalFATWriteErrors = uint16("fatal_fat_write_errors", "Fatal FAT Write Errors")
+FATScanErrors = uint16("fat_scan_errors", "FAT Scan Errors")
+FATWriteErrors = uint16("fat_write_errors", "FAT Write Errors")
+FieldsLenTable = bytes("fields_len_table", "Fields Len Table", 32)
+FileCount = uint16("file_count", "File Count")
+FileDate = uint16("file_date", "File Date")
+FileDate.NWDate()
+FileDirWindow = uint16("file_dir_win", "File/Dir Window")
+FileDirWindow.Display("BASE_HEX")
+FileExecuteType = uint8("file_execute_type", "File Execute Type")
+FileExtendedAttributes = val_string8("file_ext_attr", "File Extended Attributes", [
+ [ 0x00, "Search On All Read Only Opens" ],
+ [ 0x01, "Search On Read Only Opens With No Path" ],
+ [ 0x02, "Shell Default Search Mode" ],
+ [ 0x03, "Search On All Opens With No Path" ],
+ [ 0x04, "Do Not Search" ],
+ [ 0x05, "Reserved" ],
+ [ 0x06, "Search On All Opens" ],
+ [ 0x07, "Reserved" ],
+ [ 0x08, "Search On All Read Only Opens/Indexed" ],
+ [ 0x09, "Search On Read Only Opens With No Path/Indexed" ],
+ [ 0x0a, "Shell Default Search Mode/Indexed" ],
+ [ 0x0b, "Search On All Opens With No Path/Indexed" ],
+ [ 0x0c, "Do Not Search/Indexed" ],
+ [ 0x0d, "Indexed" ],
+ [ 0x0e, "Search On All Opens/Indexed" ],
+ [ 0x0f, "Indexed" ],
+ [ 0x10, "Search On All Read Only Opens/Transactional" ],
+ [ 0x11, "Search On Read Only Opens With No Path/Transactional" ],
+ [ 0x12, "Shell Default Search Mode/Transactional" ],
+ [ 0x13, "Search On All Opens With No Path/Transactional" ],
+ [ 0x14, "Do Not Search/Transactional" ],
+ [ 0x15, "Transactional" ],
+ [ 0x16, "Search On All Opens/Transactional" ],
+ [ 0x17, "Transactional" ],
+ [ 0x18, "Search On All Read Only Opens/Indexed/Transactional" ],
+ [ 0x19, "Search On Read Only Opens With No Path/Indexed/Transactional" ],
+ [ 0x1a, "Shell Default Search Mode/Indexed/Transactional" ],
+ [ 0x1b, "Search On All Opens With No Path/Indexed/Transactional" ],
+ [ 0x1c, "Do Not Search/Indexed/Transactional" ],
+ [ 0x1d, "Indexed/Transactional" ],
+ [ 0x1e, "Search On All Opens/Indexed/Transactional" ],
+ [ 0x1f, "Indexed/Transactional" ],
+ [ 0x40, "Search On All Read Only Opens/Read Audit" ],
+ [ 0x41, "Search On Read Only Opens With No Path/Read Audit" ],
+ [ 0x42, "Shell Default Search Mode/Read Audit" ],
+ [ 0x43, "Search On All Opens With No Path/Read Audit" ],
+ [ 0x44, "Do Not Search/Read Audit" ],
+ [ 0x45, "Read Audit" ],
+ [ 0x46, "Search On All Opens/Read Audit" ],
+ [ 0x47, "Read Audit" ],
+ [ 0x48, "Search On All Read Only Opens/Indexed/Read Audit" ],
+ [ 0x49, "Search On Read Only Opens With No Path/Indexed/Read Audit" ],
+ [ 0x4a, "Shell Default Search Mode/Indexed/Read Audit" ],
+ [ 0x4b, "Search On All Opens With No Path/Indexed/Read Audit" ],
+ [ 0x4c, "Do Not Search/Indexed/Read Audit" ],
+ [ 0x4d, "Indexed/Read Audit" ],
+ [ 0x4e, "Search On All Opens/Indexed/Read Audit" ],
+ [ 0x4f, "Indexed/Read Audit" ],
+ [ 0x50, "Search On All Read Only Opens/Transactional/Read Audit" ],
+ [ 0x51, "Search On Read Only Opens With No Path/Transactional/Read Audit" ],
+ [ 0x52, "Shell Default Search Mode/Transactional/Read Audit" ],
+ [ 0x53, "Search On All Opens With No Path/Transactional/Read Audit" ],
+ [ 0x54, "Do Not Search/Transactional/Read Audit" ],
+ [ 0x55, "Transactional/Read Audit" ],
+ [ 0x56, "Search On All Opens/Transactional/Read Audit" ],
+ [ 0x57, "Transactional/Read Audit" ],
+ [ 0x58, "Search On All Read Only Opens/Indexed/Transactional/Read Audit" ],
+ [ 0x59, "Search On Read Only Opens With No Path/Indexed/Transactional/Read Audit" ],
+ [ 0x5a, "Shell Default Search Mode/Indexed/Transactional/Read Audit" ],
+ [ 0x5b, "Search On All Opens With No Path/Indexed/Transactional/Read Audit" ],
+ [ 0x5c, "Do Not Search/Indexed/Transactional/Read Audit" ],
+ [ 0x5d, "Indexed/Transactional/Read Audit" ],
+ [ 0x5e, "Search On All Opens/Indexed/Transactional/Read Audit" ],
+ [ 0x5f, "Indexed/Transactional/Read Audit" ],
+ [ 0x80, "Search On All Read Only Opens/Write Audit" ],
+ [ 0x81, "Search On Read Only Opens With No Path/Write Audit" ],
+ [ 0x82, "Shell Default Search Mode/Write Audit" ],
+ [ 0x83, "Search On All Opens With No Path/Write Audit" ],
+ [ 0x84, "Do Not Search/Write Audit" ],
+ [ 0x85, "Write Audit" ],
+ [ 0x86, "Search On All Opens/Write Audit" ],
+ [ 0x87, "Write Audit" ],
+ [ 0x88, "Search On All Read Only Opens/Indexed/Write Audit" ],
+ [ 0x89, "Search On Read Only Opens With No Path/Indexed/Write Audit" ],
+ [ 0x8a, "Shell Default Search Mode/Indexed/Write Audit" ],
+ [ 0x8b, "Search On All Opens With No Path/Indexed/Write Audit" ],
+ [ 0x8c, "Do Not Search/Indexed/Write Audit" ],
+ [ 0x8d, "Indexed/Write Audit" ],
+ [ 0x8e, "Search On All Opens/Indexed/Write Audit" ],
+ [ 0x8f, "Indexed/Write Audit" ],
+ [ 0x90, "Search On All Read Only Opens/Transactional/Write Audit" ],
+ [ 0x91, "Search On Read Only Opens With No Path/Transactional/Write Audit" ],
+ [ 0x92, "Shell Default Search Mode/Transactional/Write Audit" ],
+ [ 0x93, "Search On All Opens With No Path/Transactional/Write Audit" ],
+ [ 0x94, "Do Not Search/Transactional/Write Audit" ],
+ [ 0x95, "Transactional/Write Audit" ],
+ [ 0x96, "Search On All Opens/Transactional/Write Audit" ],
+ [ 0x97, "Transactional/Write Audit" ],
+ [ 0x98, "Search On All Read Only Opens/Indexed/Transactional/Write Audit" ],
+ [ 0x99, "Search On Read Only Opens With No Path/Indexed/Transactional/Write Audit" ],
+ [ 0x9a, "Shell Default Search Mode/Indexed/Transactional/Write Audit" ],
+ [ 0x9b, "Search On All Opens With No Path/Indexed/Transactional/Write Audit" ],
+ [ 0x9c, "Do Not Search/Indexed/Transactional/Write Audit" ],
+ [ 0x9d, "Indexed/Transactional/Write Audit" ],
+ [ 0x9e, "Search On All Opens/Indexed/Transactional/Write Audit" ],
+ [ 0x9f, "Indexed/Transactional/Write Audit" ],
+ [ 0xa0, "Search On All Read Only Opens/Read Audit/Write Audit" ],
+ [ 0xa1, "Search On Read Only Opens With No Path/Read Audit/Write Audit" ],
+ [ 0xa2, "Shell Default Search Mode/Read Audit/Write Audit" ],
+ [ 0xa3, "Search On All Opens With No Path/Read Audit/Write Audit" ],
+ [ 0xa4, "Do Not Search/Read Audit/Write Audit" ],
+ [ 0xa5, "Read Audit/Write Audit" ],
+ [ 0xa6, "Search On All Opens/Read Audit/Write Audit" ],
+ [ 0xa7, "Read Audit/Write Audit" ],
+ [ 0xa8, "Search On All Read Only Opens/Indexed/Read Audit/Write Audit" ],
+ [ 0xa9, "Search On Read Only Opens With No Path/Indexed/Read Audit/Write Audit" ],
+ [ 0xaa, "Shell Default Search Mode/Indexed/Read Audit/Write Audit" ],
+ [ 0xab, "Search On All Opens With No Path/Indexed/Read Audit/Write Audit" ],
+ [ 0xac, "Do Not Search/Indexed/Read Audit/Write Audit" ],
+ [ 0xad, "Indexed/Read Audit/Write Audit" ],
+ [ 0xae, "Search On All Opens/Indexed/Read Audit/Write Audit" ],
+ [ 0xaf, "Indexed/Read Audit/Write Audit" ],
+ [ 0xb0, "Search On All Read Only Opens/Transactional/Read Audit/Write Audit" ],
+ [ 0xb1, "Search On Read Only Opens With No Path/Transactional/Read Audit/Write Audit" ],
+ [ 0xb2, "Shell Default Search Mode/Transactional/Read Audit/Write Audit" ],
+ [ 0xb3, "Search On All Opens With No Path/Transactional/Read Audit/Write Audit" ],
+ [ 0xb4, "Do Not Search/Transactional/Read Audit/Write Audit" ],
+ [ 0xb5, "Transactional/Read Audit/Write Audit" ],
+ [ 0xb6, "Search On All Opens/Transactional/Read Audit/Write Audit" ],
+ [ 0xb7, "Transactional/Read Audit/Write Audit" ],
+ [ 0xb8, "Search On All Read Only Opens/Indexed/Transactional/Read Audit/Write Audit" ],
+ [ 0xb9, "Search On Read Only Opens With No Path/Indexed/Transactional/Read Audit/Write Audit" ],
+ [ 0xba, "Shell Default Search Mode/Indexed/Transactional/Read Audit/Write Audit" ],
+ [ 0xbb, "Search On All Opens With No Path/Indexed/Transactional/Read Audit/Write Audit" ],
+ [ 0xbc, "Do Not Search/Indexed/Transactional/Read Audit/Write Audit" ],
+ [ 0xbd, "Indexed/Transactional/Read Audit/Write Audit" ],
+ [ 0xbe, "Search On All Opens/Indexed/Transactional/Read Audit/Write Audit" ],
+ [ 0xbf, "Indexed/Transactional/Read Audit/Write Audit" ],
+])
+fileFlags = uint32("file_flags", "File Flags")
+FileHandle = bytes("file_handle", "File Handle", 6)
+FileLimbo = uint32("file_limbo", "File Limbo")
+FileListCount = uint32("file_list_count", "File List Count")
+FileLock = val_string8("file_lock", "File Lock", [
+ [ 0x00, "Not Locked" ],
+ [ 0xfe, "Locked by file lock" ],
+ [ 0xff, "Unknown" ],
+])
+FileLockCount = uint16("file_lock_count", "File Lock Count")
+FileMode = uint8("file_mode", "File Mode")
+FileName = nstring8("file_name", "Filename")
+FileName12 = fw_string("file_name_12", "Filename", 12)
+FileName14 = fw_string("file_name_14", "Filename", 14)
+FileNameLen = uint8("file_name_len", "Filename Length")
+FileOffset = uint32("file_offset", "File Offset")
+FilePath = nstring8("file_path", "File Path")
+FileSize = uint32("file_size", "File Size", BE)
+FileSize64bit = bytes("f_size_64bit", "64bit File Size", 64)
+FileSystemID = uint8("file_system_id", "File System ID")
+FileTime = uint16("file_time", "File Time")
+FileTime.NWTime()
+FileWriteFlags = val_string8("file_write_flags", "File Write Flags", [
+ [ 0x01, "Writing" ],
+ [ 0x02, "Write aborted" ],
+])
+FileWriteState = val_string8("file_write_state", "File Write State", [
+ [ 0x00, "Not Writing" ],
+ [ 0x01, "Write in Progress" ],
+ [ 0x02, "Write Being Stopped" ],
+])
+Filler = uint8("filler", "Filler")
+FinderAttr = bitfield16("finder_attr", "Finder Info Attributes", [
+ bf_boolean16(0x0001, "finder_attr_desktop", "Object on Desktop"),
+ bf_boolean16(0x2000, "finder_attr_invisible", "Object is Invisible"),
+ bf_boolean16(0x4000, "finder_attr_bundle", "Object Has Bundle"),
+])
+FixedBitMask = uint32("fixed_bit_mask", "Fixed Bit Mask")
+FixedBitsDefined = uint16("fixed_bits_defined", "Fixed Bits Defined")
+FlagBits = uint8("flag_bits", "Flag Bits")
+Flags = uint8("flags", "Flags")
+FlagsDef = uint16("flags_def", "Flags")
+FlushTime = uint32("flush_time", "Flush Time")
+FolderFlag = val_string8("folder_flag", "Folder Flag", [
+ [ 0x00, "Not a Folder" ],
+ [ 0x01, "Folder" ],
+])
+ForkCount = uint8("fork_count", "Fork Count")
+ForkIndicator = val_string8("fork_indicator", "Fork Indicator", [
+ [ 0x00, "Data Fork" ],
+ [ 0x01, "Resource Fork" ],
+])
+ForceFlag = val_string8("force_flag", "Force Server Down Flag", [
+ [ 0x00, "Down Server if No Files Are Open" ],
+ [ 0xff, "Down Server Immediately, Auto-Close Open Files" ],
+])
+ForgedDetachedRequests = uint16("forged_detached_requests", "Forged Detached Requests")
+FormType = uint16( "form_type", "Form Type" )
+FormTypeCnt = uint32("form_type_count", "Form Types Count")
+FoundSomeMem = uint32("found_some_mem", "Found Some Memory")
+FractionalSeconds = uint32("fractional_time", "Fractional Time in Seconds")
+FraggerHandle = uint32("fragger_handle", "Fragment Handle")
+FraggerHandle.Display('BASE_HEX')
+FragmentWriteOccurred = uint16("fragment_write_occurred", "Fragment Write Occurred")
+FragSize = uint32("frag_size", "Fragment Size")
+FreeableLimboSectors = uint32("freeable_limbo_sectors", "Freeable Limbo Sectors")
+FreeBlocks = uint32("free_blocks", "Free Blocks")
+FreedClusters = uint32("freed_clusters", "Freed Clusters")
+FreeDirectoryEntries = uint16("free_directory_entries", "Free Directory Entries")
+FSEngineFlag = boolean8("fs_engine_flag", "FS Engine Flag")
+FullName = fw_string("full_name", "Full Name", 39)
+
+GetSetFlag = val_string8("get_set_flag", "Get Set Flag", [
+ [ 0x00, "Get the default support module ID" ],
+ [ 0x01, "Set the default support module ID" ],
+])
+GUID = bytes("guid", "GUID", 16)
+GUID.Display("BASE_HEX")
+
+HandleFlag = val_string8("handle_flag", "Handle Flag", [
+ [ 0x00, "Short Directory Handle" ],
+ [ 0x01, "Directory Base" ],
+ [ 0xFF, "No Handle Present" ],
+])
+HandleInfoLevel = val_string8("handle_info_level", "Handle Info Level", [
+ [ 0x00, "Get Limited Information from a File Handle" ],
+ [ 0x01, "Get Limited Information from a File Handle Using a Name Space" ],
+ [ 0x02, "Get Information from a File Handle" ],
+ [ 0x03, "Get Information from a Directory Handle" ],
+ [ 0x04, "Get Complete Information from a Directory Handle" ],
+ [ 0x05, "Get Complete Information from a File Handle" ],
+])
+HeldBytesRead = bytes("held_bytes_read", "Held Bytes Read", 6)
+HeldBytesWritten = bytes("held_bytes_write", "Held Bytes Written", 6)
+HeldConnectTimeInMinutes = uint32("held_conn_time", "Held Connect Time in Minutes")
+HeldRequests = uint32("user_info_held_req", "Held Requests")
+HoldAmount = uint32("hold_amount", "Hold Amount")
+HoldCancelAmount = uint32("hold_cancel_amount", "Hold Cancel Amount")
+HolderID = uint32("holder_id", "Holder ID")
+HolderID.Display("BASE_HEX")
+HoldTime = uint32("hold_time", "Hold Time")
+HopsToNet = uint16("hops_to_net", "Hop Count")
+HorizLocation = uint16("horiz_location", "Horizontal Location")
+HostAddress = bytes("host_address", "Host Address", 6)
+HotFixBlocksAvailable = uint16("hot_fix_blocks_available", "Hot Fix Blocks Available")
+HotFixDisabled = val_string8("hot_fix_disabled", "Hot Fix Disabled", [
+ [ 0x00, "Enabled" ],
+ [ 0x01, "Disabled" ],
+])
+HotFixTableSize = uint16("hot_fix_table_size", "Hot Fix Table Size")
+HotFixTableStart = uint32("hot_fix_table_start", "Hot Fix Table Start")
+Hour = uint8("s_hour", "Hour")
+HugeBitMask = uint32("huge_bit_mask", "Huge Bit Mask")
+HugeBitsDefined = uint16("huge_bits_defined", "Huge Bits Defined")
+HugeData = nstring8("huge_data", "Huge Data")
+HugeDataUsed = uint32("huge_data_used", "Huge Data Used")
+HugeStateInfo = bytes("huge_state_info", "Huge State Info", 16)
+
+IdentificationNumber = uint32("identification_number", "Identification Number")
+IgnoredRxPkts = uint32("ignored_rx_pkts", "Ignored Receive Packets")
+IncomingPacketDiscardedNoDGroup = uint16("incoming_packet_discarded_no_dgroup", "Incoming Packet Discarded No DGroup")
+IndexNumber = uint8("index_number", "Index Number")
+InfoCount = uint16("info_count", "Info Count")
+InfoFlags = bitfield32("info_flags", "Info Flags", [
+ bf_boolean32(0x10000000, "info_flags_security", "Return Object Security"),
+ bf_boolean32(0x20000000, "info_flags_flags", "Return Object Flags"),
+ bf_boolean32(0x40000000, "info_flags_type", "Return Object Type"),
+ bf_boolean32(0x80000000, "info_flags_name", "Return Object Name"),
+])
+InfoLevelNumber = val_string8("info_level_num", "Information Level Number", [
+ [ 0x01, "Volume Information Definition" ],
+ [ 0x02, "Volume Information 2 Definition" ],
+])
+InfoMask = bitfield32("info_mask", "Information Mask", [
+ bf_boolean32(0x00000001, "info_flags_dos_time", "DOS Time"),
+ bf_boolean32(0x00000002, "info_flags_ref_count", "Reference Count"),
+ bf_boolean32(0x00000004, "info_flags_dos_attr", "DOS Attributes"),
+ bf_boolean32(0x00000008, "info_flags_ids", "ID's"),
+ bf_boolean32(0x00000010, "info_flags_ds_sizes", "Data Stream Sizes"),
+ bf_boolean32(0x00000020, "info_flags_ns_attr", "Name Space Attributes"),
+ bf_boolean32(0x00000040, "info_flags_ea_present", "EA Present Flag"),
+ bf_boolean32(0x00000080, "info_flags_all_attr", "All Attributes"),
+ bf_boolean32(0x00000100, "info_flags_all_dirbase_num", "All Directory Base Numbers"),
+ bf_boolean32(0x00000200, "info_flags_max_access_mask", "Maximum Access Mask"),
+ bf_boolean32(0x00000400, "info_flags_flush_time", "Flush Time"),
+ bf_boolean32(0x00000800, "info_flags_prnt_base_id", "Parent Base ID"),
+ bf_boolean32(0x00001000, "info_flags_mac_finder", "Mac Finder Information"),
+ bf_boolean32(0x00002000, "info_flags_sibling_cnt", "Sibling Count"),
+ bf_boolean32(0x00004000, "info_flags_effect_rights", "Effective Rights"),
+ bf_boolean32(0x00008000, "info_flags_mac_time", "Mac Time"),
+ bf_boolean32(0x20000000, "info_mask_dosname", "DOS Name"),
+ bf_boolean32(0x40000000, "info_mask_c_name_space", "Creator Name Space & Name"),
+ bf_boolean32(0x80000000, "info_mask_name", "Name"),
+])
+InheritedRightsMask = bitfield16("inherited_rights_mask", "Inherited Rights Mask", [
+ bf_boolean16(0x0001, "inh_rights_read", "Read Rights"),
+ bf_boolean16(0x0002, "inh_rights_write", "Write Rights"),
+ bf_boolean16(0x0004, "inh_rights_open", "Open Rights"),
+ bf_boolean16(0x0008, "inh_rights_create", "Create Rights"),
+ bf_boolean16(0x0010, "inh_rights_delete", "Delete Rights"),
+ bf_boolean16(0x0020, "inh_rights_parent", "Change Access"),
+ bf_boolean16(0x0040, "inh_rights_search", "See Files Flag"),
+ bf_boolean16(0x0080, "inh_rights_modify", "Modify Rights"),
+ bf_boolean16(0x0100, "inh_rights_supervisor", "Supervisor"),
+])
+InheritanceRevokeMask = bitfield16("inheritance_revoke_mask", "Revoke Rights Mask", [
+ bf_boolean16(0x0001, "inh_revoke_read", "Read Rights"),
+ bf_boolean16(0x0002, "inh_revoke_write", "Write Rights"),
+ bf_boolean16(0x0004, "inh_revoke_open", "Open Rights"),
+ bf_boolean16(0x0008, "inh_revoke_create", "Create Rights"),
+ bf_boolean16(0x0010, "inh_revoke_delete", "Delete Rights"),
+ bf_boolean16(0x0020, "inh_revoke_parent", "Change Access"),
+ bf_boolean16(0x0040, "inh_revoke_search", "See Files Flag"),
+ bf_boolean16(0x0080, "inh_revoke_modify", "Modify Rights"),
+ bf_boolean16(0x0100, "inh_revoke_supervisor", "Supervisor"),
+])
+InitialSemaphoreValue = uint8("initial_semaphore_value", "Initial Semaphore Value")
+InspectSize = uint32("inspect_size", "Inspect Size")
+InternetBridgeVersion = uint8("internet_bridge_version", "Internet Bridge Version")
+InterruptNumbersUsed = uint32("interrupt_numbers_used", "Interrupt Numbers Used")
+InUse = uint32("in_use", "Bytes in Use")
+IOAddressesUsed = bytes("io_addresses_used", "IO Addresses Used", 8)
+IOErrorCount = uint16("io_error_count", "IO Error Count")
+IOEngineFlag = boolean8("io_engine_flag", "IO Engine Flag")
+IPXNotMyNetwork = uint16("ipx_not_my_network", "IPX Not My Network")
+ItemsChanged = uint32("items_changed", "Items Changed")
+ItemsChecked = uint32("items_checked", "Items Checked")
+ItemsCount = uint32("items_count", "Items Count")
+itemsInList = uint32("items_in_list", "Items in List")
+ItemsInPacket = uint32("items_in_packet", "Items in Packet")
+
+JobControlFlags = bitfield8("job_control_flags", "Job Control Flags", [
+ bf_boolean8(0x08, "job_control_job_recovery", "Job Recovery"),
+ bf_boolean8(0x10, "job_control_reservice", "ReService Job"),
+ bf_boolean8(0x20, "job_control_file_open", "File Open"),
+ bf_boolean8(0x40, "job_control_user_hold", "User Hold"),
+ bf_boolean8(0x80, "job_control_operator_hold", "Operator Hold"),
+
+])
+JobControlFlagsWord = bitfield16("job_control_flags_word", "Job Control Flags", [
+ bf_boolean16(0x0008, "job_control1_job_recovery", "Job Recovery"),
+ bf_boolean16(0x0010, "job_control1_reservice", "ReService Job"),
+ bf_boolean16(0x0020, "job_control1_file_open", "File Open"),
+ bf_boolean16(0x0040, "job_control1_user_hold", "User Hold"),
+ bf_boolean16(0x0080, "job_control1_operator_hold", "Operator Hold"),
+
+])
+JobCount = uint32("job_count", "Job Count")
+JobFileHandle = bytes("job_file_handle", "Job File Handle", 6)
+JobFileHandleLong = uint32("job_file_handle_long", "Job File Handle", BE)
+JobFileHandleLong.Display("BASE_HEX")
+JobFileName = fw_string("job_file_name", "Job File Name", 14)
+JobPosition = uint8("job_position", "Job Position")
+JobPositionWord = uint16("job_position_word", "Job Position")
+JobNumber = uint16("job_number", "Job Number", BE )
+JobNumberLong = uint32("job_number_long", "Job Number", BE )
+JobNumberLong.Display("BASE_HEX")
+JobType = uint16("job_type", "Job Type", BE )
+
+LANCustomVariablesCount = uint32("lan_cust_var_count", "LAN Custom Variables Count")
+LANdriverBoardInstance = uint16("lan_drv_bd_inst", "LAN Driver Board Instance")
+LANdriverBoardNumber = uint16("lan_drv_bd_num", "LAN Driver Board Number")
+LANdriverCardID = uint16("lan_drv_card_id", "LAN Driver Card ID")
+LANdriverCardName = fw_string("lan_drv_card_name", "LAN Driver Card Name", 28)
+LANdriverCFG_MajorVersion = uint8("lan_dvr_cfg_major_vrs", "LAN Driver Config - Major Version")
+LANdriverCFG_MinorVersion = uint8("lan_dvr_cfg_minor_vrs", "LAN Driver Config - Minor Version")
+LANdriverDMAUsage1 = uint8("lan_drv_dma_usage1", "Primary DMA Channel")
+LANdriverDMAUsage2 = uint8("lan_drv_dma_usage2", "Secondary DMA Channel")
+LANdriverFlags = uint16("lan_drv_flags", "LAN Driver Flags")
+LANdriverFlags.Display("BASE_HEX")
+LANdriverInterrupt1 = uint8("lan_drv_interrupt1", "Primary Interrupt Vector")
+LANdriverInterrupt2 = uint8("lan_drv_interrupt2", "Secondary Interrupt Vector")
+LANdriverIOPortsAndRanges1 = uint16("lan_drv_io_ports_and_ranges_1", "Primary Base I/O Port")
+LANdriverIOPortsAndRanges2 = uint16("lan_drv_io_ports_and_ranges_2", "Number of I/O Ports")
+LANdriverIOPortsAndRanges3 = uint16("lan_drv_io_ports_and_ranges_3", "Secondary Base I/O Port")
+LANdriverIOPortsAndRanges4 = uint16("lan_drv_io_ports_and_ranges_4", "Number of I/O Ports")
+LANdriverIOReserved = bytes("lan_drv_io_reserved", "LAN Driver IO Reserved", 14)
+LANdriverLineSpeed = uint16("lan_drv_line_speed", "LAN Driver Line Speed")
+LANdriverLink = uint32("lan_drv_link", "LAN Driver Link")
+LANdriverLogicalName = bytes("lan_drv_log_name", "LAN Driver Logical Name", 18)
+LANdriverMajorVersion = uint8("lan_drv_major_ver", "LAN Driver Major Version")
+LANdriverMaximumSize = uint32("lan_drv_max_size", "LAN Driver Maximum Size")
+LANdriverMaxRecvSize = uint32("lan_drv_max_rcv_size", "LAN Driver Maximum Receive Size")
+LANdriverMediaID = uint16("lan_drv_media_id", "LAN Driver Media ID")
+LANdriverMediaType = fw_string("lan_drv_media_type", "LAN Driver Media Type", 40)
+LANdriverMemoryDecode0 = uint32("lan_drv_mem_decode_0", "LAN Driver Memory Decode 0")
+LANdriverMemoryDecode1 = uint32("lan_drv_mem_decode_1", "LAN Driver Memory Decode 1")
+LANdriverMemoryLength0 = uint16("lan_drv_mem_length_0", "LAN Driver Memory Length 0")
+LANdriverMemoryLength1 = uint16("lan_drv_mem_length_1", "LAN Driver Memory Length 1")
+LANdriverMinorVersion = uint8("lan_drv_minor_ver", "LAN Driver Minor Version")
+LANdriverModeFlags = val_string8("lan_dvr_mode_flags", "LAN Driver Mode Flags", [
+ [0x80, "Canonical Address" ],
+ [0x81, "Canonical Address" ],
+ [0x82, "Canonical Address" ],
+ [0x83, "Canonical Address" ],
+ [0x84, "Canonical Address" ],
+ [0x85, "Canonical Address" ],
+ [0x86, "Canonical Address" ],
+ [0x87, "Canonical Address" ],
+ [0x88, "Canonical Address" ],
+ [0x89, "Canonical Address" ],
+ [0x8a, "Canonical Address" ],
+ [0x8b, "Canonical Address" ],
+ [0x8c, "Canonical Address" ],
+ [0x8d, "Canonical Address" ],
+ [0x8e, "Canonical Address" ],
+ [0x8f, "Canonical Address" ],
+ [0x90, "Canonical Address" ],
+ [0x91, "Canonical Address" ],
+ [0x92, "Canonical Address" ],
+ [0x93, "Canonical Address" ],
+ [0x94, "Canonical Address" ],
+ [0x95, "Canonical Address" ],
+ [0x96, "Canonical Address" ],
+ [0x97, "Canonical Address" ],
+ [0x98, "Canonical Address" ],
+ [0x99, "Canonical Address" ],
+ [0x9a, "Canonical Address" ],
+ [0x9b, "Canonical Address" ],
+ [0x9c, "Canonical Address" ],
+ [0x9d, "Canonical Address" ],
+ [0x9e, "Canonical Address" ],
+ [0x9f, "Canonical Address" ],
+ [0xa0, "Canonical Address" ],
+ [0xa1, "Canonical Address" ],
+ [0xa2, "Canonical Address" ],
+ [0xa3, "Canonical Address" ],
+ [0xa4, "Canonical Address" ],
+ [0xa5, "Canonical Address" ],
+ [0xa6, "Canonical Address" ],
+ [0xa7, "Canonical Address" ],
+ [0xa8, "Canonical Address" ],
+ [0xa9, "Canonical Address" ],
+ [0xaa, "Canonical Address" ],
+ [0xab, "Canonical Address" ],
+ [0xac, "Canonical Address" ],
+ [0xad, "Canonical Address" ],
+ [0xae, "Canonical Address" ],
+ [0xaf, "Canonical Address" ],
+ [0xb0, "Canonical Address" ],
+ [0xb1, "Canonical Address" ],
+ [0xb2, "Canonical Address" ],
+ [0xb3, "Canonical Address" ],
+ [0xb4, "Canonical Address" ],
+ [0xb5, "Canonical Address" ],
+ [0xb6, "Canonical Address" ],
+ [0xb7, "Canonical Address" ],
+ [0xb8, "Canonical Address" ],
+ [0xb9, "Canonical Address" ],
+ [0xba, "Canonical Address" ],
+ [0xbb, "Canonical Address" ],
+ [0xbc, "Canonical Address" ],
+ [0xbd, "Canonical Address" ],
+ [0xbe, "Canonical Address" ],
+ [0xbf, "Canonical Address" ],
+ [0xc0, "Non-Canonical Address" ],
+ [0xc1, "Non-Canonical Address" ],
+ [0xc2, "Non-Canonical Address" ],
+ [0xc3, "Non-Canonical Address" ],
+ [0xc4, "Non-Canonical Address" ],
+ [0xc5, "Non-Canonical Address" ],
+ [0xc6, "Non-Canonical Address" ],
+ [0xc7, "Non-Canonical Address" ],
+ [0xc8, "Non-Canonical Address" ],
+ [0xc9, "Non-Canonical Address" ],
+ [0xca, "Non-Canonical Address" ],
+ [0xcb, "Non-Canonical Address" ],
+ [0xcc, "Non-Canonical Address" ],
+ [0xcd, "Non-Canonical Address" ],
+ [0xce, "Non-Canonical Address" ],
+ [0xcf, "Non-Canonical Address" ],
+ [0xd0, "Non-Canonical Address" ],
+ [0xd1, "Non-Canonical Address" ],
+ [0xd2, "Non-Canonical Address" ],
+ [0xd3, "Non-Canonical Address" ],
+ [0xd4, "Non-Canonical Address" ],
+ [0xd5, "Non-Canonical Address" ],
+ [0xd6, "Non-Canonical Address" ],
+ [0xd7, "Non-Canonical Address" ],
+ [0xd8, "Non-Canonical Address" ],
+ [0xd9, "Non-Canonical Address" ],
+ [0xda, "Non-Canonical Address" ],
+ [0xdb, "Non-Canonical Address" ],
+ [0xdc, "Non-Canonical Address" ],
+ [0xdd, "Non-Canonical Address" ],
+ [0xde, "Non-Canonical Address" ],
+ [0xdf, "Non-Canonical Address" ],
+ [0xe0, "Non-Canonical Address" ],
+ [0xe1, "Non-Canonical Address" ],
+ [0xe2, "Non-Canonical Address" ],
+ [0xe3, "Non-Canonical Address" ],
+ [0xe4, "Non-Canonical Address" ],
+ [0xe5, "Non-Canonical Address" ],
+ [0xe6, "Non-Canonical Address" ],
+ [0xe7, "Non-Canonical Address" ],
+ [0xe8, "Non-Canonical Address" ],
+ [0xe9, "Non-Canonical Address" ],
+ [0xea, "Non-Canonical Address" ],
+ [0xeb, "Non-Canonical Address" ],
+ [0xec, "Non-Canonical Address" ],
+ [0xed, "Non-Canonical Address" ],
+ [0xee, "Non-Canonical Address" ],
+ [0xef, "Non-Canonical Address" ],
+ [0xf0, "Non-Canonical Address" ],
+ [0xf1, "Non-Canonical Address" ],
+ [0xf2, "Non-Canonical Address" ],
+ [0xf3, "Non-Canonical Address" ],
+ [0xf4, "Non-Canonical Address" ],
+ [0xf5, "Non-Canonical Address" ],
+ [0xf6, "Non-Canonical Address" ],
+ [0xf7, "Non-Canonical Address" ],
+ [0xf8, "Non-Canonical Address" ],
+ [0xf9, "Non-Canonical Address" ],
+ [0xfa, "Non-Canonical Address" ],
+ [0xfb, "Non-Canonical Address" ],
+ [0xfc, "Non-Canonical Address" ],
+ [0xfd, "Non-Canonical Address" ],
+ [0xfe, "Non-Canonical Address" ],
+ [0xff, "Non-Canonical Address" ],
+])
+LANDriverNumber = uint8("lan_driver_number", "LAN Driver Number")
+LANdriverNodeAddress = bytes("lan_dvr_node_addr", "LAN Driver Node Address", 6)
+LANdriverRecvSize = uint32("lan_drv_rcv_size", "LAN Driver Receive Size")
+LANdriverReserved = uint16("lan_drv_reserved", "LAN Driver Reserved")
+LANdriverSendRetries = uint16("lan_drv_snd_retries", "LAN Driver Send Retries")
+LANdriverSharingFlags = uint16("lan_drv_share", "LAN Driver Sharing Flags")
+LANdriverShortName = fw_string("lan_drv_short_name", "LAN Driver Short Name", 40)
+LANdriverSlot = uint16("lan_drv_slot", "LAN Driver Slot")
+LANdriverSrcRouting = uint32("lan_drv_src_route", "LAN Driver Source Routing")
+LANdriverTransportTime = uint16("lan_drv_trans_time", "LAN Driver Transport Time")
+LastAccessedDate = uint16("last_access_date", "Last Accessed Date")
+LastAccessedDate.NWDate()
+LastAccessedTime = uint16("last_access_time", "Last Accessed Time")
+LastAccessedTime.NWTime()
+LastGarbCollect = uint32("last_garbage_collect", "Last Garbage Collection")
+LastInstance = uint32("last_instance", "Last Instance")
+LastRecordSeen = uint16("last_record_seen", "Last Record Seen")
+LastSearchIndex = uint16("last_search_index", "Search Index")
+LastSeen = uint32("last_seen", "Last Seen")
+LastSequenceNumber = uint16("last_sequence_number", "Sequence Number")
+Length64bit = bytes("length_64bit", "64bit Length", 64)
+Level = uint8("level", "Level")
+LFSCounters = uint32("lfs_counters", "LFS Counters")
+LimboDataStreamsCount = uint32("limbo_data_streams_count", "Limbo Data Streams Count")
+limbCount = uint32("limb_count", "Limb Count")
+LimboUsed = uint32("limbo_used", "Limbo Used")
+LoadedNameSpaces = uint8("loaded_name_spaces", "Loaded Name Spaces")
+LocalConnectionID = uint32("local_connection_id", "Local Connection ID")
+LocalConnectionID.Display("BASE_HEX")
+LocalMaxPacketSize = uint32("local_max_packet_size", "Local Max Packet Size")
+LocalMaxSendSize = uint32("local_max_send_size", "Local Max Send Size")
+LocalMaxRecvSize = uint32("local_max_recv_size", "Local Max Recv Size")
+LocalLoginInfoCcode = uint8("local_login_info_ccode", "Local Login Info C Code")
+LocalTargetSocket = uint32("local_target_socket", "Local Target Socket")
+LocalTargetSocket.Display("BASE_HEX")
+LockAreaLen = uint32("lock_area_len", "Lock Area Length")
+LockAreasStartOffset = uint32("lock_areas_start_offset", "Lock Areas Start Offset")
+LockTimeout = uint16("lock_timeout", "Lock Timeout")
+Locked = val_string8("locked", "Locked Flag", [
+ [ 0x00, "Not Locked Exclusively" ],
+ [ 0x01, "Locked Exclusively" ],
+])
+LockFlag = val_string8("lock_flag", "Lock Flag", [
+ [ 0x00, "Not Locked, Log for Future Exclusive Lock" ],
+ [ 0x01, "Exclusive Lock (Read/Write)" ],
+ [ 0x02, "Log for Future Shared Lock"],
+ [ 0x03, "Shareable Lock (Read-Only)" ],
+ [ 0xfe, "Locked by a File Lock" ],
+ [ 0xff, "Locked by Begin Share File Set" ],
+])
+LockName = nstring8("lock_name", "Lock Name")
+LockStatus = val_string8("lock_status", "Lock Status", [
+ [ 0x00, "Locked Exclusive" ],
+ [ 0x01, "Locked Shareable" ],
+ [ 0x02, "Logged" ],
+ [ 0x06, "Lock is Held by TTS"],
+])
+LockType = val_string8("lock_type", "Lock Type", [
+ [ 0x00, "Locked" ],
+ [ 0x01, "Open Shareable" ],
+ [ 0x02, "Logged" ],
+ [ 0x03, "Open Normal" ],
+ [ 0x06, "TTS Holding Lock" ],
+ [ 0x07, "Transaction Flag Set on This File" ],
+])
+LogFileFlagHigh = bitfield8("log_file_flag_high", "Log File Flag (byte 2)", [
+ bf_boolean8(0x80, "log_flag_call_back", "Call Back Requested" ),
+])
+LogFileFlagLow = bitfield8("log_file_flag_low", "Log File Flag", [
+ bf_boolean8(0x01, "log_flag_lock_file", "Lock File Immediately" ),
+])
+LoggedObjectID = uint32("logged_object_id", "Logged in Object ID")
+LoggedObjectID.Display("BASE_HEX")
+LoggedCount = uint16("logged_count", "Logged Count")
+LogicalConnectionNumber = uint16("logical_connection_number", "Logical Connection Number", BE)
+LogicalDriveCount = uint8("logical_drive_count", "Logical Drive Count")
+LogicalDriveNumber = uint8("logical_drive_number", "Logical Drive Number")
+LogicalLockThreshold = uint8("logical_lock_threshold", "LogicalLockThreshold")
+LogicalRecordName = nstring8("logical_record_name", "Logical Record Name")
+LoginKey = bytes("login_key", "Login Key", 8)
+LogLockType = uint8("log_lock_type", "Log Lock Type")
+LogTtlRxPkts = uint32("log_ttl_rx_pkts", "Total Received Packets")
+LogTtlTxPkts = uint32("log_ttl_tx_pkts", "Total Transmitted Packets")
+LongName = fw_string("long_name", "Long Name", 32)
+LRUBlockWasDirty = uint16("lru_block_was_dirty", "LRU Block Was Dirty")
+
+MacAttr = bitfield16("mac_attr", "Attributes", [
+ bf_boolean16(0x0001, "mac_attr_smode1", "Search Mode"),
+ bf_boolean16(0x0002, "mac_attr_smode2", "Search Mode"),
+ bf_boolean16(0x0004, "mac_attr_smode3", "Search Mode"),
+ bf_boolean16(0x0010, "mac_attr_transaction", "Transaction"),
+ bf_boolean16(0x0020, "mac_attr_index", "Index"),
+ bf_boolean16(0x0040, "mac_attr_r_audit", "Read Audit"),
+ bf_boolean16(0x0080, "mac_attr_w_audit", "Write Audit"),
+ bf_boolean16(0x0100, "mac_attr_r_only", "Read Only"),
+ bf_boolean16(0x0200, "mac_attr_hidden", "Hidden"),
+ bf_boolean16(0x0400, "mac_attr_system", "System"),
+ bf_boolean16(0x0800, "mac_attr_execute_only", "Execute Only"),
+ bf_boolean16(0x1000, "mac_attr_subdirectory", "Subdirectory"),
+ bf_boolean16(0x2000, "mac_attr_archive", "Archive"),
+ bf_boolean16(0x8000, "mac_attr_share", "Shareable File"),
+])
+MACBackupDate = uint16("mac_backup_date", "Mac Backup Date")
+MACBackupDate.NWDate()
+MACBackupTime = uint16("mac_backup_time", "Mac Backup Time")
+MACBackupTime.NWTime()
+MacBaseDirectoryID = uint32("mac_base_directory_id", "Mac Base Directory ID", BE)
+MacBaseDirectoryID.Display("BASE_HEX")
+MACCreateDate = uint16("mac_create_date", "Mac Create Date")
+MACCreateDate.NWDate()
+MACCreateTime = uint16("mac_create_time", "Mac Create Time")
+MACCreateTime.NWTime()
+MacDestinationBaseID = uint32("mac_destination_base_id", "Mac Destination Base ID")
+MacDestinationBaseID.Display("BASE_HEX")
+MacFinderInfo = bytes("mac_finder_info", "Mac Finder Information", 32)
+MacLastSeenID = uint32("mac_last_seen_id", "Mac Last Seen ID")
+MacLastSeenID.Display("BASE_HEX")
+MacSourceBaseID = uint32("mac_source_base_id", "Mac Source Base ID")
+MacSourceBaseID.Display("BASE_HEX")
+MajorVersion = uint32("major_version", "Major Version")
+MaxBytes = uint16("max_bytes", "Maximum Number of Bytes")
+MaxDataStreams = uint32("max_data_streams", "Maximum Data Streams")
+MaxDirDepth = uint32("max_dir_depth", "Maximum Directory Depth")
+MaximumSpace = uint16("max_space", "Maximum Space")
+MaxNumOfConn = uint32("max_num_of_conn", "Maximum Number of Connections")
+MaxNumOfLANS = uint32("max_num_of_lans", "Maximum Number Of LAN's")
+MaxNumOfMedias = uint32("max_num_of_medias", "Maximum Number Of Media's")
+MaxNumOfNmeSps = uint32("max_num_of_nme_sps", "Maximum Number Of Name Spaces")
+MaxNumOfSpoolPr = uint32("max_num_of_spool_pr", "Maximum Number Of Spool Printers")
+MaxNumOfStacks = uint32("max_num_of_stacks", "Maximum Number Of Stacks")
+MaxNumOfUsers = uint32("max_num_of_users", "Maximum Number Of Users")
+MaxNumOfVol = uint32("max_num_of_vol", "Maximum Number of Volumes")
+MaxSpace = uint32("maxspace", "Maximum Space")
+MaxUsedDynamicSpace = uint32("max_used_dynamic_space", "Max Used Dynamic Space")
+MediaList = uint32("media_list", "Media List")
+MediaListCount = uint32("media_list_count", "Media List Count")
+MediaName = nstring8("media_name", "Media Name")
+MediaNumber = uint32("media_number", "Media Number")
+MediaObjectType = val_string8("media_object_type", "Object Type", [
+ [ 0x00, "Adapter" ],
+ [ 0x01, "Changer" ],
+ [ 0x02, "Removable Device" ],
+ [ 0x03, "Device" ],
+ [ 0x04, "Removable Media" ],
+ [ 0x05, "Partition" ],
+ [ 0x06, "Slot" ],
+ [ 0x07, "Hotfix" ],
+ [ 0x08, "Mirror" ],
+ [ 0x09, "Parity" ],
+ [ 0x0a, "Volume Segment" ],
+ [ 0x0b, "Volume" ],
+ [ 0x0c, "Clone" ],
+ [ 0x0d, "Fixed Media" ],
+ [ 0x0e, "Unknown" ],
+])
+MemberName = nstring8("member_name", "Member Name")
+MemberType = val_string16("member_type", "Member Type", [
+ [ 0x0000, "Unknown" ],
+ [ 0x0001, "User" ],
+ [ 0x0002, "User group" ],
+ [ 0x0003, "Print queue" ],
+ [ 0x0004, "NetWare file server" ],
+ [ 0x0005, "Job server" ],
+ [ 0x0006, "Gateway" ],
+ [ 0x0007, "Print server" ],
+ [ 0x0008, "Archive queue" ],
+ [ 0x0009, "Archive server" ],
+ [ 0x000a, "Job queue" ],
+ [ 0x000b, "Administration" ],
+ [ 0x0021, "NAS SNA gateway" ],
+ [ 0x0026, "Remote bridge server" ],
+ [ 0x0027, "TCP/IP gateway" ],
+])
+MessageLanguage = uint32("message_language", "NLM Language")
+MigratedFiles = uint32("migrated_files", "Migrated Files")
+MigratedSectors = uint32("migrated_sectors", "Migrated Sectors")
+MinorVersion = uint32("minor_version", "Minor Version")
+Minute = uint8("s_minute", "Minutes")
+MixedModePathFlag = val_string8("mixed_mode_path_flag", "Mixed Mode Path Flag", [
+ [ 0x00, "Mixed mode path handling is not available"],
+ [ 0x01, "Mixed mode path handling is available"],
+])
+ModifiedDate = uint16("modified_date", "Modified Date")
+ModifiedDate.NWDate()
+ModifiedTime = uint16("modified_time", "Modified Time")
+ModifiedTime.NWTime()
+ModifierID = uint32("modifier_id", "Modifier ID", BE)
+ModifierID.Display("BASE_HEX")
+ModifyDOSInfoMask = bitfield16("modify_dos_info_mask", "Modify DOS Info Mask", [
+ bf_boolean16(0x0002, "modify_dos_read", "Attributes"),
+ bf_boolean16(0x0004, "modify_dos_write", "Creation Date"),
+ bf_boolean16(0x0008, "modify_dos_open", "Creation Time"),
+ bf_boolean16(0x0010, "modify_dos_create", "Creator ID"),
+ bf_boolean16(0x0020, "modify_dos_delete", "Archive Date"),
+ bf_boolean16(0x0040, "modify_dos_parent", "Archive Time"),
+ bf_boolean16(0x0080, "modify_dos_search", "Archiver ID"),
+ bf_boolean16(0x0100, "modify_dos_mdate", "Modify Date"),
+ bf_boolean16(0x0200, "modify_dos_mtime", "Modify Time"),
+ bf_boolean16(0x0400, "modify_dos_mid", "Modifier ID"),
+ bf_boolean16(0x0800, "modify_dos_laccess", "Last Access"),
+ bf_boolean16(0x1000, "modify_dos_inheritance", "Inheritance"),
+ bf_boolean16(0x2000, "modify_dos_max_space", "Maximum Space"),
+])
+Month = val_string8("s_month", "Month", [
+ [ 0x01, "January"],
+ [ 0x02, "Febuary"],
+ [ 0x03, "March"],
+ [ 0x04, "April"],
+ [ 0x05, "May"],
+ [ 0x06, "June"],
+ [ 0x07, "July"],
+ [ 0x08, "August"],
+ [ 0x09, "September"],
+ [ 0x0a, "October"],
+ [ 0x0b, "November"],
+ [ 0x0c, "December"],
+])
+
+MoreFlag = val_string8("more_flag", "More Flag", [
+ [ 0x00, "No More Segments/Entries Available" ],
+ [ 0x01, "More Segments/Entries Available" ],
+ [ 0xff, "More Segments/Entries Available" ],
+])
+MoreProperties = val_string8("more_properties", "More Properties", [
+ [ 0x00, "No More Properties Available" ],
+ [ 0x01, "No More Properties Available" ],
+ [ 0xff, "More Properties Available" ],
+])
+
+Name = nstring8("name", "Name")
+Name12 = fw_string("name12", "Name", 12)
+NameLen = uint8("name_len", "Name Space Length")
+NameLength = uint8("name_length", "Name Length")
+NameList = uint32("name_list", "Name List")
+#
+# XXX - should this value be used to interpret the characters in names,
+# search patterns, and the like?
+#
+# We need to handle character sets better, e.g. translating strings
+# from whatever character set they are in the packet (DOS/Windows code
+# pages, ISO character sets, UNIX EUC character sets, UTF-8, UCS-2/Unicode,
+# Mac character sets, etc.) into UCS-4 or UTF-8 and storing them as such
+# in the protocol tree, and displaying them as best we can.
+#
+NameSpace = val_string8("name_space", "Name Space", [
+ [ 0x00, "DOS" ],
+ [ 0x01, "MAC" ],
+ [ 0x02, "NFS" ],
+ [ 0x03, "FTAM" ],
+ [ 0x04, "OS/2, Long" ],
+])
+NamesSpaceInfoMask = bitfield16("ns_info_mask", "Names Space Info Mask", [
+ bf_boolean16(0x0001, "ns_info_mask_modify", "Modify Name"),
+ bf_boolean16(0x0002, "ns_info_mask_fatt", "File Attributes"),
+ bf_boolean16(0x0004, "ns_info_mask_cdate", "Creation Date"),
+ bf_boolean16(0x0008, "ns_info_mask_ctime", "Creation Time"),
+ bf_boolean16(0x0010, "ns_info_mask_owner", "Owner ID"),
+ bf_boolean16(0x0020, "ns_info_mask_adate", "Archive Date"),
+ bf_boolean16(0x0040, "ns_info_mask_atime", "Archive Time"),
+ bf_boolean16(0x0080, "ns_info_mask_aid", "Archiver ID"),
+ bf_boolean16(0x0100, "ns_info_mask_udate", "Update Date"),
+ bf_boolean16(0x0200, "ns_info_mask_utime", "Update Time"),
+ bf_boolean16(0x0400, "ns_info_mask_uid", "Update ID"),
+ bf_boolean16(0x0800, "ns_info_mask_acc_date", "Access Date"),
+ bf_boolean16(0x1000, "ns_info_mask_max_acc_mask", "Inheritance"),
+ bf_boolean16(0x2000, "ns_info_mask_max_space", "Maximum Space"),
+])
+NameSpaceName = nstring8("name_space_name", "Name Space Name")
+nameType = uint32("name_type", "nameType")
+NCPdataSize = uint32("ncp_data_size", "NCP Data Size")
+NCPextensionMajorVersion = uint8("ncp_extension_major_version", "NCP Extension Major Version")
+NCPextensionMinorVersion = uint8("ncp_extension_minor_version", "NCP Extension Minor Version")
+NCPextensionName = nstring8("ncp_extension_name", "NCP Extension Name")
+NCPextensionNumber = uint32("ncp_extension_number", "NCP Extension Number")
+NCPextensionNumber.Display("BASE_HEX")
+NCPExtensionNumbers = uint32("ncp_extension_numbers", "NCP Extension Numbers")
+NCPextensionRevisionNumber = uint8("ncp_extension_revision_number", "NCP Extension Revision Number")
+NCPPeakStaInUse = uint32("ncp_peak_sta_in_use", "Peak Number of Connections since Server was brought up")
+NCPStaInUseCnt = uint32("ncp_sta_in_use", "Number of Workstations Connected to Server")
+NDSRequestFlags = bitfield16("nds_request_flags", "NDS Request Flags", [
+ bf_boolean16(0x0001, "nds_request_flags_output", "Output Fields"),
+ bf_boolean16(0x0002, "nds_request_flags_no_such_entry", "No Such Entry"),
+ bf_boolean16(0x0004, "nds_request_flags_local_entry", "Local Entry"),
+ bf_boolean16(0x0008, "nds_request_flags_type_ref", "Type Referral"),
+ bf_boolean16(0x0010, "nds_request_flags_alias_ref", "Alias Referral"),
+ bf_boolean16(0x0020, "nds_request_flags_req_cnt", "Request Count"),
+ bf_boolean16(0x0040, "nds_request_flags_req_data_size", "Request Data Size"),
+ bf_boolean16(0x0080, "nds_request_flags_reply_data_size", "Reply Data Size"),
+ bf_boolean16(0x0100, "nds_request_flags_trans_ref", "Transport Referral"),
+ bf_boolean16(0x0200, "nds_request_flags_trans_ref2", "Transport Referral"),
+ bf_boolean16(0x0400, "nds_request_flags_up_ref", "Up Referral"),
+ bf_boolean16(0x0800, "nds_request_flags_dn_ref", "Down Referral"),
+])
+NDSStatus = uint32("nds_status", "NDS Status")
+NetBIOSBroadcastWasPropogated = uint32("netbios_broadcast_was_propogated", "NetBIOS Broadcast Was Propogated")
+NetIDNumber = uint32("net_id_number", "Net ID Number")
+NetIDNumber.Display("BASE_HEX")
+NetAddress = nbytes32("address", "Address")
+NetStatus = uint16("net_status", "Network Status")
+NetWareAccessHandle = bytes("netware_access_handle", "NetWare Access Handle", 6)
+NetworkAddress = uint32("network_address", "Network Address")
+NetworkAddress.Display("BASE_HEX")
+NetworkNodeAddress = bytes("network_node_address", "Network Node Address", 6)
+NetworkNumber = uint32("network_number", "Network Number")
+NetworkNumber.Display("BASE_HEX")
+#
+# XXX - this should have the "ipx_socket_vals" value_string table
+# from "packet-ipx.c".
+#
+NetworkSocket = uint16("network_socket", "Network Socket")
+NetworkSocket.Display("BASE_HEX")
+NewAccessRights = bitfield16("new_access_rights_mask", "New Access Rights", [
+ bf_boolean16(0x0001, "new_access_rights_read", "Read"),
+ bf_boolean16(0x0002, "new_access_rights_write", "Write"),
+ bf_boolean16(0x0004, "new_access_rights_open", "Open"),
+ bf_boolean16(0x0008, "new_access_rights_create", "Create"),
+ bf_boolean16(0x0010, "new_access_rights_delete", "Delete"),
+ bf_boolean16(0x0020, "new_access_rights_parental", "Parental"),
+ bf_boolean16(0x0040, "new_access_rights_search", "Search"),
+ bf_boolean16(0x0080, "new_access_rights_modify", "Modify"),
+ bf_boolean16(0x0100, "new_access_rights_supervisor", "Supervisor"),
+])
+NewDirectoryID = uint32("new_directory_id", "New Directory ID", BE)
+NewDirectoryID.Display("BASE_HEX")
+NewEAHandle = uint32("new_ea_handle", "New EA Handle")
+NewEAHandle.Display("BASE_HEX")
+NewFileName = fw_string("new_file_name", "New File Name", 14)
+NewFileNameLen = nstring8("new_file_name_len", "New File Name")
+NewFileSize = uint32("new_file_size", "New File Size")
+NewPassword = nstring8("new_password", "New Password")
+NewPath = nstring8("new_path", "New Path")
+NewPosition = uint8("new_position", "New Position")
+NewObjectName = nstring8("new_object_name", "New Object Name")
+NextCntBlock = uint32("next_cnt_block", "Next Count Block")
+NextHugeStateInfo = bytes("next_huge_state_info", "Next Huge State Info", 16)
+nextLimbScanNum = uint32("next_limb_scan_num", "Next Limb Scan Number")
+NextObjectID = uint32("next_object_id", "Next Object ID", BE)
+NextObjectID.Display("BASE_HEX")
+NextRecord = uint32("next_record", "Next Record")
+NextRequestRecord = uint16("next_request_record", "Next Request Record")
+NextSearchIndex = uint16("next_search_index", "Next Search Index")
+NextSearchNumber = uint16("next_search_number", "Next Search Number")
+NextSearchNum = uint32("nxt_search_num", "Next Search Number")
+nextStartingNumber = uint32("next_starting_number", "Next Starting Number")
+NextTrusteeEntry = uint32("next_trustee_entry", "Next Trustee Entry")
+NextVolumeNumber = uint32("next_volume_number", "Next Volume Number")
+NLMBuffer = nstring8("nlm_buffer", "Buffer")
+NLMcount = uint32("nlm_count", "NLM Count")
+NLMFlags = bitfield8("nlm_flags", "Flags", [
+ bf_boolean8(0x01, "nlm_flags_reentrant", "ReEntrant"),
+ bf_boolean8(0x02, "nlm_flags_multiple", "Can Load Multiple Times"),
+ bf_boolean8(0x04, "nlm_flags_synchronize", "Synchronize Start"),
+ bf_boolean8(0x08, "nlm_flags_pseudo", "PseudoPreemption"),
+])
+NLMLoadOptions = uint32("nlm_load_options", "NLM Load Options")
+NLMName = stringz("nlm_name_stringz", "NLM Name")
+NLMNumber = uint32("nlm_number", "NLM Number")
+NLMNumbers = uint32("nlm_numbers", "NLM Numbers")
+NLMsInList = uint32("nlms_in_list", "NLM's in List")
+NLMStartNumber = uint32("nlm_start_num", "NLM Start Number")
+NLMType = val_string8("nlm_type", "NLM Type", [
+ [ 0x00, "Generic NLM (.NLM)" ],
+ [ 0x01, "LAN Driver (.LAN)" ],
+ [ 0x02, "Disk Driver (.DSK)" ],
+ [ 0x03, "Name Space Support Module (.NAM)" ],
+ [ 0x04, "Utility or Support Program (.NLM)" ],
+ [ 0x05, "Mirrored Server Link (.MSL)" ],
+ [ 0x06, "OS NLM (.NLM)" ],
+ [ 0x07, "Paged High OS NLM (.NLM)" ],
+ [ 0x08, "Host Adapter Module (.HAM)" ],
+ [ 0x09, "Custom Device Module (.CDM)" ],
+ [ 0x0a, "File System Engine (.NLM)" ],
+ [ 0x0b, "Real Mode NLM (.NLM)" ],
+ [ 0x0c, "Hidden NLM (.NLM)" ],
+ [ 0x15, "NICI Support (.NLM)" ],
+ [ 0x16, "NICI Support (.NLM)" ],
+ [ 0x17, "Cryptography (.NLM)" ],
+ [ 0x18, "Encryption (.NLM)" ],
+ [ 0x19, "NICI Support (.NLM)" ],
+ [ 0x1c, "NICI Support (.NLM)" ],
+])
+nodeFlags = uint32("node_flags", "Node Flags")
+nodeFlags.Display("BASE_HEX")
+NoMoreMemAvlCnt = uint32("no_more_mem_avail", "No More Memory Available Count")
+NonDedFlag = boolean8("non_ded_flag", "Non Dedicated Flag")
+NonFreeableAvailableSubAllocSectors = uint32("non_freeable_avail_sub_alloc_sectors", "Non Freeable Available Sub Alloc Sectors")
+NonFreeableLimboSectors = uint32("non_freeable_limbo_sectors", "Non Freeable Limbo Sectors")
+NotUsableSubAllocSectors = uint32("not_usable_sub_alloc_sectors", "Not Usable Sub Alloc Sectors")
+NotYetPurgeableBlocks = uint32("not_yet_purgeable_blocks", "Not Yet Purgeable Blocks")
+NSInfoBitMask = uint32("ns_info_bit_mask", "Name Space Info Bit Mask")
+NSSOAllInFlags = bitfield32("nsso_all_in_flags", "SecretStore All Input Flags",[
+ bf_boolean32(0x00000010, "nsso_all_unicode", "Unicode Data"),
+ bf_boolean32(0x00000080, "nsso_set_tree", "Set Tree"),
+ bf_boolean32(0x00000200, "nsso_destroy_ctx", "Destroy Context"),
+])
+NSSOGetServiceInFlags = bitfield32("nsso_get_svc_in_flags", "SecretStore Get Service Flags",[
+ bf_boolean32(0x00000100, "nsso_get_ctx", "Get Context"),
+])
+NSSOReadInFlags = bitfield32("nsso_read_in_flags", "SecretStore Read Flags",[
+ bf_boolean32(0x00000001, "nsso_rw_enh_prot", "Read/Write Enhanced Protection"),
+ bf_boolean32(0x00000008, "nsso_repair", "Repair SecretStore"),
+])
+NSSOReadOrUnlockInFlags = bitfield32("nsso_read_or_unlock_in_flags", "SecretStore Read or Unlock Flags",[
+ bf_boolean32(0x00000004, "nsso_ep_master_pwd", "Master Password used instead of ENH Password"),
+])
+NSSOUnlockInFlags = bitfield32("nsso_unlock_in_flags", "SecretStore Unlock Flags",[
+ bf_boolean32(0x00000004, "nsso_rmv_lock", "Remove Lock from Store"),
+])
+NSSOWriteInFlags = bitfield32("nsso_write_in_flags", "SecretStore Write Flags",[
+ bf_boolean32(0x00000001, "nsso_enh_prot", "Enhanced Protection"),
+ bf_boolean32(0x00000002, "nsso_create_id", "Create ID"),
+ bf_boolean32(0x00000040, "nsso_ep_pwd_used", "Enhanced Protection Password Used"),
+])
+NSSOContextOutFlags = bitfield32("nsso_cts_out_flags", "Type of Context",[
+ bf_boolean32(0x00000001, "nsso_ds_ctx", "DSAPI Context"),
+ bf_boolean32(0x00000080, "nsso_ldap_ctx", "LDAP Context"),
+ bf_boolean32(0x00000200, "nsso_dc_ctx", "Reserved"),
+])
+NSSOGetServiceOutFlags = bitfield32("nsso_get_svc_out_flags", "SecretStore Status Flags",[
+ bf_boolean32(0x00400000, "nsso_mstr_pwd", "Master Password Present"),
+])
+NSSOGetServiceReadOutFlags = bitfield32("nsso_get_svc_read_out_flags", "SecretStore Status Flags",[
+ bf_boolean32(0x00800000, "nsso_mp_disabled", "Master Password Disabled"),
+])
+NSSOReadOutFlags = bitfield32("nsso_read_out_flags", "SecretStore Read Flags",[
+ bf_boolean32(0x00010000, "nsso_secret_locked", "Enhanced Protection Lock on Secret"),
+ bf_boolean32(0x00020000, "nsso_secret_not_init", "Secret Not Yet Initialized"),
+ bf_boolean32(0x00040000, "nsso_secret_marked", "Secret Marked for Enhanced Protection"),
+ bf_boolean32(0x00080000, "nsso_secret_not_sync", "Secret Not Yet Synchronized in NDS"),
+ bf_boolean32(0x00200000, "nsso_secret_enh_pwd", "Enhanced Protection Password on Secret"),
+])
+NSSOReadOutStatFlags = bitfield32("nsso_read_out_stat_flags", "SecretStore Read Status Flags",[
+ bf_boolean32(0x00100000, "nsso_admin_mod", "Admin Modified Secret Last"),
+])
+NSSOVerb = val_string8("nsso_verb", "SecretStore Verb", [
+ [ 0x00, "Query Server" ],
+ [ 0x01, "Read App Secrets" ],
+ [ 0x02, "Write App Secrets" ],
+ [ 0x03, "Add Secret ID" ],
+ [ 0x04, "Remove Secret ID" ],
+ [ 0x05, "Remove SecretStore" ],
+ [ 0x06, "Enumerate SecretID's" ],
+ [ 0x07, "Unlock Store" ],
+ [ 0x08, "Set Master Password" ],
+ [ 0x09, "Get Service Information" ],
+])
+NSSpecificInfo = fw_string("ns_specific_info", "Name Space Specific Info", 512)
+NumberOfAllocs = uint32("num_of_allocs", "Number of Allocations")
+NumberOfAttributes = uint32("number_of_attributes", "Number of Attributes")
+NumberOfCPUs = uint32("number_of_cpus", "Number of CPU's")
+NumberOfDataStreams = uint16("number_of_data_streams", "Number of Data Streams")
+NumberOfDynamicMemoryAreas = uint16("number_of_dynamic_memory_areas", "Number Of Dynamic Memory Areas")
+NumberOfEntries = uint8("number_of_entries", "Number of Entries")
+NumberOfLocks = uint8("number_of_locks", "Number of Locks")
+NumberOfMinutesToDelay = uint32("number_of_minutes_to_delay", "Number of Minutes to Delay")
+NumberOfNCPExtensions = uint32("number_of_ncp_extensions", "Number Of NCP Extensions")
+NumberOfNSLoaded = uint16("number_of_ns_loaded", "Number Of Name Spaces Loaded")
+NumberOfProtocols = uint8("number_of_protocols", "Number of Protocols")
+NumberOfRecords = uint16("number_of_records", "Number of Records")
+NumberOfReferencedPublics = uint32("num_of_ref_publics", "Number of Referenced Public Symbols")
+NumberOfSemaphores = uint16("number_of_semaphores", "Number Of Semaphores")
+NumberOfServiceProcesses = uint8("number_of_service_processes", "Number Of Service Processes")
+NumberOfSetCategories = uint32("number_of_set_categories", "Number Of Set Categories")
+NumberOfSMs = uint32("number_of_sms", "Number Of Storage Medias")
+NumberOfStations = uint8("number_of_stations", "Number of Stations")
+NumBytes = uint16("num_bytes", "Number of Bytes")
+NumOfCCinPkt = uint32("num_of_cc_in_pkt", "Number of Custom Counters in Packet")
+NumOfChecks = uint32("num_of_checks", "Number of Checks")
+NumOfEntries = uint32("num_of_entries", "Number of Entries")
+NumOfFilesMigrated = uint32("num_of_files_migrated", "Number Of Files Migrated")
+NumOfGarbageColl = uint32("num_of_garb_coll", "Number of Garbage Collections")
+NumOfNCPReqs = uint32("num_of_ncp_reqs", "Number of NCP Requests since Server was brought up")
+NumOfSegments = uint32("num_of_segments", "Number of Segments")
+
+ObjectCount = uint32("object_count", "Object Count")
+ObjectFlags = val_string8("object_flags", "Object Flags", [
+ [ 0x00, "Dynamic object" ],
+ [ 0x01, "Static object" ],
+])
+ObjectHasProperties = val_string8("object_has_properites", "Object Has Properties", [
+ [ 0x00, "No properties" ],
+ [ 0xff, "One or more properties" ],
+])
+ObjectID = uint32("object_id", "Object ID", BE)
+ObjectID.Display('BASE_HEX')
+ObjectIDCount = uint16("object_id_count", "Object ID Count")
+ObjectIDInfo = uint32("object_id_info", "Object Information")
+ObjectInfoReturnCount = uint32("object_info_rtn_count", "Object Information Count")
+ObjectName = nstring8("object_name", "Object Name")
+ObjectNameLen = fw_string("object_name_len", "Object Name", 48)
+ObjectNameStringz = stringz("object_name_stringz", "Object Name")
+ObjectNumber = uint32("object_number", "Object Number")
+ObjectSecurity = val_string8("object_security", "Object Security", [
+ [ 0x00, "Object Read (Anyone) / Object Write (Anyone)" ],
+ [ 0x01, "Object Read (Logged in) / Object Write (Anyone)" ],
+ [ 0x02, "Object Read (Logged in as Object) / Object Write (Anyone)" ],
+ [ 0x03, "Object Read (Supervisor) / Object Write (Anyone)" ],
+ [ 0x04, "Object Read (Operating System Only) / Object Write (Anyone)" ],
+ [ 0x10, "Object Read (Anyone) / Object Write (Logged in)" ],
+ [ 0x11, "Object Read (Logged in) / Object Write (Logged in)" ],
+ [ 0x12, "Object Read (Logged in as Object) / Object Write (Logged in)" ],
+ [ 0x13, "Object Read (Supervisor) / Object Write (Logged in)" ],
+ [ 0x14, "Object Read (Operating System Only) / Object Write (Logged in)" ],
+ [ 0x20, "Object Read (Anyone) / Object Write (Logged in as Object)" ],
+ [ 0x21, "Object Read (Logged in) / Object Write (Logged in as Object)" ],
+ [ 0x22, "Object Read (Logged in as Object) / Object Write (Logged in as Object)" ],
+ [ 0x23, "Object Read (Supervisor) / Object Write (Logged in as Object)" ],
+ [ 0x24, "Object Read (Operating System Only) / Object Write (Logged in as Object)" ],
+ [ 0x30, "Object Read (Anyone) / Object Write (Supervisor)" ],
+ [ 0x31, "Object Read (Logged in) / Object Write (Supervisor)" ],
+ [ 0x32, "Object Read (Logged in as Object) / Object Write (Supervisor)" ],
+ [ 0x33, "Object Read (Supervisor) / Object Write (Supervisor)" ],
+ [ 0x34, "Object Read (Operating System Only) / Object Write (Supervisor)" ],
+ [ 0x40, "Object Read (Anyone) / Object Write (Operating System Only)" ],
+ [ 0x41, "Object Read (Logged in) / Object Write (Operating System Only)" ],
+ [ 0x42, "Object Read (Logged in as Object) / Object Write (Operating System Only)" ],
+ [ 0x43, "Object Read (Supervisor) / Object Write (Operating System Only)" ],
+ [ 0x44, "Object Read (Operating System Only) / Object Write (Operating System Only)" ],
+])
+#
+# XXX - should this use the "server_vals[]" value_string array from
+# "packet-ipx.c"?
+#
+# XXX - should this list be merged with that list? There are some
+# oddities, e.g. this list has 0x03f5 for "Microsoft SQL Server", but
+# the list from "packet-ipx.c" has 0xf503 for that - is that just
+# byte-order confusion?
+#
+ObjectType = val_string16("object_type", "Object Type", [
+ [ 0x0000, "Unknown" ],
+ [ 0x0001, "User" ],
+ [ 0x0002, "User group" ],
+ [ 0x0003, "Print queue" ],
+ [ 0x0004, "NetWare file server" ],
+ [ 0x0005, "Job server" ],
+ [ 0x0006, "Gateway" ],
+ [ 0x0007, "Print server" ],
+ [ 0x0008, "Archive queue" ],
+ [ 0x0009, "Archive server" ],
+ [ 0x000a, "Job queue" ],
+ [ 0x000b, "Administration" ],
+ [ 0x0021, "NAS SNA gateway" ],
+ [ 0x0026, "Remote bridge server" ],
+ [ 0x0027, "TCP/IP gateway" ],
+ [ 0x0047, "Novell Print Server" ],
+ [ 0x004b, "Btrieve Server" ],
+ [ 0x004c, "NetWare SQL Server" ],
+ [ 0x0064, "ARCserve" ],
+ [ 0x0066, "ARCserve 3.0" ],
+ [ 0x0076, "NetWare SQL" ],
+ [ 0x00a0, "Gupta SQL Base Server" ],
+ [ 0x00a1, "Powerchute" ],
+ [ 0x0107, "NetWare Remote Console" ],
+ [ 0x01cb, "Shiva NetModem/E" ],
+ [ 0x01cc, "Shiva LanRover/E" ],
+ [ 0x01cd, "Shiva LanRover/T" ],
+ [ 0x01d8, "Castelle FAXPress Server" ],
+ [ 0x01da, "Castelle Print Server" ],
+ [ 0x01dc, "Castelle Fax Server" ],
+ [ 0x0200, "Novell SQL Server" ],
+ [ 0x023a, "NetWare Lanalyzer Agent" ],
+ [ 0x023c, "DOS Target Service Agent" ],
+ [ 0x023f, "NetWare Server Target Service Agent" ],
+ [ 0x024f, "Appletalk Remote Access Service" ],
+ [ 0x0263, "NetWare Management Agent" ],
+ [ 0x0264, "Global MHS" ],
+ [ 0x0265, "SNMP" ],
+ [ 0x026a, "NetWare Management/NMS Console" ],
+ [ 0x026b, "NetWare Time Synchronization" ],
+ [ 0x0273, "Nest Device" ],
+ [ 0x0274, "GroupWise Message Multiple Servers" ],
+ [ 0x0278, "NDS Replica Server" ],
+ [ 0x0282, "NDPS Service Registry Service" ],
+ [ 0x028a, "MPR/IPX Address Mapping Gateway" ],
+ [ 0x028b, "ManageWise" ],
+ [ 0x0293, "NetWare 6" ],
+ [ 0x030c, "HP JetDirect" ],
+ [ 0x0328, "Watcom SQL Server" ],
+ [ 0x0355, "Backup Exec" ],
+ [ 0x039b, "Lotus Notes" ],
+ [ 0x03e1, "Univel Server" ],
+ [ 0x03f5, "Microsoft SQL Server" ],
+ [ 0x055e, "Lexmark Print Server" ],
+ [ 0x0640, "Microsoft Gateway Services for NetWare" ],
+ [ 0x064e, "Microsoft Internet Information Server" ],
+ [ 0x077b, "Advantage Database Server" ],
+ [ 0x07a7, "Backup Exec Job Queue" ],
+ [ 0x07a8, "Backup Exec Job Manager" ],
+ [ 0x07a9, "Backup Exec Job Service" ],
+ [ 0x5555, "Site Lock" ],
+ [ 0x8202, "NDPS Broker" ],
+])
+OCRetFlags = val_string8("o_c_ret_flags", "Open Create Return Flags", [
+ [ 0x00, "No CallBack has been registered (No Op-Lock)" ],
+ [ 0x01, "Request has been registered for CallBack (Op-Lock)" ],
+])
+OldestDeletedFileAgeInTicks = uint32("oldest_deleted_file_age_in_ticks", "Oldest Deleted File Age in Ticks")
+OldFileName = bytes("old_file_name", "Old File Name", 15)
+OldFileSize = uint32("old_file_size", "Old File Size")
+OpenCount = uint16("open_count", "Open Count")
+OpenCreateAction = bitfield8("open_create_action", "Open Create Action", [
+ bf_boolean8(0x01, "open_create_action_opened", "Opened"),
+ bf_boolean8(0x02, "open_create_action_created", "Created"),
+ bf_boolean8(0x04, "open_create_action_replaced", "Replaced"),
+ bf_boolean8(0x08, "open_create_action_compressed", "Compressed"),
+ bf_boolean8(0x80, "open_create_action_read_only", "Read Only"),
+])
+OpenCreateMode = bitfield8("open_create_mode", "Open Create Mode", [
+ bf_boolean8(0x01, "open_create_mode_open", "Open existing file (file must exist)"),
+ bf_boolean8(0x02, "open_create_mode_replace", "Replace existing file"),
+ bf_boolean8(0x08, "open_create_mode_create", "Create new file or subdirectory (file or subdirectory cannot exist)"),
+ bf_boolean8(0x80, "open_create_mode_oplock", "Open Callback (Op-Lock)"),
+])
+OpenForReadCount = uint16("open_for_read_count", "Open For Read Count")
+OpenForWriteCount = uint16("open_for_write_count", "Open For Write Count")
+OpenRights = bitfield8("open_rights", "Open Rights", [
+ bf_boolean8(0x01, "open_rights_read_only", "Read Only"),
+ bf_boolean8(0x02, "open_rights_write_only", "Write Only"),
+ bf_boolean8(0x04, "open_rights_deny_read", "Deny Read"),
+ bf_boolean8(0x08, "open_rights_deny_write", "Deny Write"),
+ bf_boolean8(0x10, "open_rights_compat", "Compatibility"),
+ bf_boolean8(0x40, "open_rights_write_thru", "Write Through"),
+])
+OptionNumber = uint8("option_number", "Option Number")
+originalSize = uint32("original_size", "Original Size")
+OSLanguageID = uint8("os_language_id", "OS Language ID")
+OSMajorVersion = uint8("os_major_version", "OS Major Version")
+OSMinorVersion = uint8("os_minor_version", "OS Minor Version")
+OSRevision = uint8("os_revision", "OS Revision")
+OtherFileForkSize = uint32("other_file_fork_size", "Other File Fork Size")
+OtherFileForkFAT = uint32("other_file_fork_fat", "Other File Fork FAT Entry")
+OutgoingPacketDiscardedNoTurboBuffer = uint16("outgoing_packet_discarded_no_turbo_buffer", "Outgoing Packet Discarded No Turbo Buffer")
+
+PacketsDiscardedByHopCount = uint16("packets_discarded_by_hop_count", "Packets Discarded By Hop Count")
+PacketsDiscardedUnknownNet = uint16("packets_discarded_unknown_net", "Packets Discarded Unknown Net")
+PacketsFromInvalidConnection = uint16("packets_from_invalid_connection", "Packets From Invalid Connection")
+PacketsReceivedDuringProcessing = uint16("packets_received_during_processing", "Packets Received During Processing")
+PacketsWithBadRequestType = uint16("packets_with_bad_request_type", "Packets With Bad Request Type")
+PacketsWithBadSequenceNumber = uint16("packets_with_bad_sequence_number", "Packets With Bad Sequence Number")
+PageTableOwnerFlag = uint32("page_table_owner_flag", "Page Table Owner")
+ParentID = uint32("parent_id", "Parent ID")
+ParentID.Display("BASE_HEX")
+ParentBaseID = uint32("parent_base_id", "Parent Base ID")
+ParentBaseID.Display("BASE_HEX")
+ParentDirectoryBase = uint32("parent_directory_base", "Parent Directory Base")
+ParentDOSDirectoryBase = uint32("parent_dos_directory_base", "Parent DOS Directory Base")
+ParentObjectNumber = uint32("parent_object_number", "Parent Object Number")
+ParentObjectNumber.Display("BASE_HEX")
+Password = nstring8("password", "Password")
+PathBase = uint8("path_base", "Path Base")
+PathComponentCount = uint16("path_component_count", "Path Component Count")
+PathComponentSize = uint16("path_component_size", "Path Component Size")
+PathCookieFlags = val_string16("path_cookie_flags", "Path Cookie Flags", [
+ [ 0x0000, "Last component is Not a File Name" ],
+ [ 0x0001, "Last component is a File Name" ],
+])
+PathCount = uint8("path_count", "Path Count")
+Path = nstring8("path", "Path")
+PathAndName = stringz("path_and_name", "Path and Name")
+PendingIOCommands = uint16("pending_io_commands", "Pending IO Commands")
+PhysicalDiskNumber = uint8("physical_disk_number", "Physical Disk Number")
+PhysicalDriveCount = uint8("physical_drive_count", "Physical Drive Count")
+PhysicalLockThreshold = uint8("physical_lock_threshold", "Physical Lock Threshold")
+PingVersion = uint16("ping_version", "Ping Version")
+PositiveAcknowledgesSent = uint16("positive_acknowledges_sent", "Positive Acknowledges Sent")
+PreCompressedSectors = uint32("pre_compressed_sectors", "Precompressed Sectors")
+PreviousRecord = uint32("previous_record", "Previous Record")
+PrimaryEntry = uint32("primary_entry", "Primary Entry")
+PrintFlags = bitfield8("print_flags", "Print Flags", [
+ bf_boolean8(0x08, "print_flags_ff", "Suppress Form Feeds"),
+ bf_boolean8(0x10, "print_flags_cr", "Create"),
+ bf_boolean8(0x20, "print_flags_del_spool", "Delete Spool File after Printing"),
+ bf_boolean8(0x40, "print_flags_exp_tabs", "Expand Tabs in the File"),
+ bf_boolean8(0x80, "print_flags_banner", "Print Banner Page"),
+])
+PrinterHalted = val_string8("printer_halted", "Printer Halted", [
+ [ 0x00, "Printer is not Halted" ],
+ [ 0xff, "Printer is Halted" ],
+])
+PrinterOffLine = val_string8( "printer_offline", "Printer Off-Line", [
+ [ 0x00, "Printer is On-Line" ],
+ [ 0xff, "Printer is Off-Line" ],
+])
+PrintServerVersion = uint8("print_server_version", "Print Server Version")
+Priority = uint32("priority", "Priority")
+Privileges = uint32("privileges", "Login Privileges")
+ProcessorType = val_string8("processor_type", "Processor Type", [
+ [ 0x00, "Motorola 68000" ],
+ [ 0x01, "Intel 8088 or 8086" ],
+ [ 0x02, "Intel 80286" ],
+])
+ProDOSInfo = bytes("pro_dos_info", "Pro DOS Info", 6)
+ProductMajorVersion = uint16("product_major_version", "Product Major Version")
+ProductMinorVersion = uint16("product_minor_version", "Product Minor Version")
+ProductRevisionVersion = uint8("product_revision_version", "Product Revision Version")
+projectedCompSize = uint32("projected_comp_size", "Projected Compression Size")
+PropertyHasMoreSegments = val_string8("property_has_more_segments",
+ "Property Has More Segments", [
+ [ 0x00, "Is last segment" ],
+ [ 0xff, "More segments are available" ],
+])
+PropertyName = nstring8("property_name", "Property Name")
+PropertyName16 = fw_string("property_name_16", "Property Name", 16)
+PropertyData = bytes("property_data", "Property Data", 128)
+PropertySegment = uint8("property_segment", "Property Segment")
+PropertyType = val_string8("property_type", "Property Type", [
+ [ 0x00, "Display Static property" ],
+ [ 0x01, "Display Dynamic property" ],
+ [ 0x02, "Set Static property" ],
+ [ 0x03, "Set Dynamic property" ],
+])
+PropertyValue = fw_string("property_value", "Property Value", 128)
+ProposedMaxSize = uint16("proposed_max_size", "Proposed Max Size")
+protocolFlags = uint32("protocol_flags", "Protocol Flags")
+protocolFlags.Display("BASE_HEX")
+PurgeableBlocks = uint32("purgeable_blocks", "Purgeable Blocks")
+PurgeCcode = uint32("purge_c_code", "Purge Completion Code")
+PurgeCount = uint32("purge_count", "Purge Count")
+PurgeFlags = val_string16("purge_flags", "Purge Flags", [
+ [ 0x0000, "Do not Purge All" ],
+ [ 0x0001, "Purge All" ],
+ [ 0xffff, "Do not Purge All" ],
+])
+PurgeList = uint32("purge_list", "Purge List")
+PhysicalDiskChannel = uint8("physical_disk_channel", "Physical Disk Channel")
+PhysicalDriveType = val_string8("physical_drive_type", "Physical Drive Type", [
+ [ 0x01, "XT" ],
+ [ 0x02, "AT" ],
+ [ 0x03, "SCSI" ],
+ [ 0x04, "Disk Coprocessor" ],
+ [ 0x05, "PS/2 with MFM Controller" ],
+ [ 0x06, "PS/2 with ESDI Controller" ],
+ [ 0x07, "Convergent Technology SBIC" ],
+])
+PhysicalReadErrors = uint16("physical_read_errors", "Physical Read Errors")
+PhysicalReadRequests = uint32("physical_read_requests", "Physical Read Requests")
+PhysicalWriteErrors = uint16("physical_write_errors", "Physical Write Errors")
+PhysicalWriteRequests = uint32("physical_write_requests", "Physical Write Requests")
+PrintToFileFlag = boolean8("print_to_file_flag", "Print to File Flag")
+
+QueueID = uint32("queue_id", "Queue ID")
+QueueID.Display("BASE_HEX")
+QueueName = nstring8("queue_name", "Queue Name")
+QueueStartPosition = uint32("queue_start_position", "Queue Start Position")
+QueueStatus = bitfield8("queue_status", "Queue Status", [
+ bf_boolean8(0x01, "queue_status_new_jobs", "Operator does not want to add jobs to the queue"),
+ bf_boolean8(0x02, "queue_status_pserver", "Operator does not want additional servers attaching"),
+ bf_boolean8(0x04, "queue_status_svc_jobs", "Operator does not want servers to service jobs"),
+])
+QueueType = uint16("queue_type", "Queue Type")
+QueueingVersion = uint8("qms_version", "QMS Version")
+
+ReadBeyondWrite = uint16("read_beyond_write", "Read Beyond Write")
+RecordLockCount = uint16("rec_lock_count", "Record Lock Count")
+RecordStart = uint32("record_start", "Record Start")
+RecordEnd = uint32("record_end", "Record End")
+RecordInUseFlag = val_string16("record_in_use", "Record in Use", [
+ [ 0x0000, "Record In Use" ],
+ [ 0xffff, "Record Not In Use" ],
+])
+RedirectedPrinter = uint8( "redirected_printer", "Redirected Printer" )
+ReferenceCount = uint32("reference_count", "Reference Count")
+RelationsCount = uint16("relations_count", "Relations Count")
+ReMirrorCurrentOffset = uint32("re_mirror_current_offset", "ReMirror Current Offset")
+ReMirrorDriveNumber = uint8("re_mirror_drive_number", "ReMirror Drive Number")
+RemoteMaxPacketSize = uint32("remote_max_packet_size", "Remote Max Packet Size")
+RemoteTargetID = uint32("remote_target_id", "Remote Target ID")
+RemoteTargetID.Display("BASE_HEX")
+RemovableFlag = uint16("removable_flag", "Removable Flag")
+RemoveOpenRights = bitfield8("remove_open_rights", "Remove Open Rights", [
+ bf_boolean8(0x01, "remove_open_rights_ro", "Read Only"),
+ bf_boolean8(0x02, "remove_open_rights_wo", "Write Only"),
+ bf_boolean8(0x04, "remove_open_rights_dr", "Deny Read"),
+ bf_boolean8(0x08, "remove_open_rights_dw", "Deny Write"),
+ bf_boolean8(0x10, "remove_open_rights_comp", "Compatibility"),
+ bf_boolean8(0x40, "remove_open_rights_write_thru", "Write Through"),
+])
+RenameFlag = bitfield8("rename_flag", "Rename Flag", [
+ bf_boolean8(0x01, "rename_flag_ren", "Rename to Myself allows file to be renamed to it's original name"),
+ bf_boolean8(0x02, "rename_flag_comp", "Compatability allows files that are marked read only to be opened with read/write access"),
+ bf_boolean8(0x04, "rename_flag_no", "Name Only renames only the specified name space entry name"),
+])
+RepliesCancelled = uint16("replies_cancelled", "Replies Cancelled")
+ReplyBuffer = nstring8("reply_buffer", "Reply Buffer")
+ReplyBufferSize = uint32("reply_buffer_size", "Reply Buffer Size")
+ReplyQueueJobNumbers = uint32("reply_queue_job_numbers", "Reply Queue Job Numbers")
+RequestBitMap = bitfield16("request_bit_map", "Request Bit Map", [
+ bf_boolean16(0x0001, "request_bit_map_ret_afp_ent", "AFP Entry ID"),
+ bf_boolean16(0x0002, "request_bit_map_ret_data_fork", "Data Fork Length"),
+ bf_boolean16(0x0004, "request_bit_map_ret_res_fork", "Resource Fork Length"),
+ bf_boolean16(0x0008, "request_bit_map_ret_num_off", "Number of Offspring"),
+ bf_boolean16(0x0010, "request_bit_map_ret_owner", "Owner ID"),
+ bf_boolean16(0x0020, "request_bit_map_ret_short", "Short Name"),
+ bf_boolean16(0x0040, "request_bit_map_ret_acc_priv", "Access Privileges"),
+ bf_boolean16(0x0100, "request_bit_map_ratt", "Return Attributes"),
+ bf_boolean16(0x0200, "request_bit_map_ret_afp_parent", "AFP Parent Entry ID"),
+ bf_boolean16(0x0400, "request_bit_map_ret_cr_date", "Creation Date"),
+ bf_boolean16(0x0800, "request_bit_map_ret_acc_date", "Access Date"),
+ bf_boolean16(0x1000, "request_bit_map_ret_mod_date", "Modify Date&Time"),
+ bf_boolean16(0x2000, "request_bit_map_ret_bak_date", "Backup Date&Time"),
+ bf_boolean16(0x4000, "request_bit_map_ret_finder", "Finder Info"),
+ bf_boolean16(0x8000, "request_bit_map_ret_long_nm", "Long Name"),
+])
+ResourceForkLen = uint32("resource_fork_len", "Resource Fork Len")
+RequestCode = val_string8("request_code", "Request Code", [
+ [ 0x00, "Change Logged in to Temporary Authenticated" ],
+ [ 0x01, "Change Temporary Authenticated to Logged in" ],
+])
+RequestData = nstring8("request_data", "Request Data")
+RequestsReprocessed = uint16("requests_reprocessed", "Requests Reprocessed")
+Reserved = uint8( "reserved", "Reserved" )
+Reserved2 = bytes("reserved2", "Reserved", 2)
+Reserved3 = bytes("reserved3", "Reserved", 3)
+Reserved4 = bytes("reserved4", "Reserved", 4)
+Reserved6 = bytes("reserved6", "Reserved", 6)
+Reserved8 = bytes("reserved8", "Reserved", 8)
+Reserved10 = bytes("reserved10", "Reserved", 10)
+Reserved12 = bytes("reserved12", "Reserved", 12)
+Reserved16 = bytes("reserved16", "Reserved", 16)
+Reserved20 = bytes("reserved20", "Reserved", 20)
+Reserved28 = bytes("reserved28", "Reserved", 28)
+Reserved36 = bytes("reserved36", "Reserved", 36)
+Reserved44 = bytes("reserved44", "Reserved", 44)
+Reserved48 = bytes("reserved48", "Reserved", 48)
+Reserved50 = bytes("reserved50", "Reserved", 50)
+Reserved56 = bytes("reserved56", "Reserved", 56)
+Reserved64 = bytes("reserved64", "Reserved", 64)
+Reserved120 = bytes("reserved120", "Reserved", 120)
+ReservedOrDirectoryNumber = uint32("reserved_or_directory_number", "Reserved or Directory Number (see EAFlags)")
+ResourceCount = uint32("resource_count", "Resource Count")
+ResourceForkSize = uint32("resource_fork_size", "Resource Fork Size")
+ResourceName = stringz("resource_name", "Resource Name")
+ResourceSignature = fw_string("resource_sig", "Resource Signature", 4)
+RestoreTime = uint32("restore_time", "Restore Time")
+Restriction = uint32("restriction", "Disk Space Restriction")
+RestrictionsEnforced = val_string8("restrictions_enforced", "Disk Restrictions Enforce Flag", [
+ [ 0x00, "Enforced" ],
+ [ 0xff, "Not Enforced" ],
+])
+ReturnInfoCount = uint32("return_info_count", "Return Information Count")
+ReturnInfoMask = bitfield16("ret_info_mask", "Return Information", [
+ bf_boolean16(0x0001, "ret_info_mask_fname", "Return File Name Information"),
+ bf_boolean16(0x0002, "ret_info_mask_alloc", "Return Allocation Space Information"),
+ bf_boolean16(0x0004, "ret_info_mask_attr", "Return Attribute Information"),
+ bf_boolean16(0x0008, "ret_info_mask_size", "Return Size Information"),
+ bf_boolean16(0x0010, "ret_info_mask_tspace", "Return Total Space Information"),
+ bf_boolean16(0x0020, "ret_info_mask_eattr", "Return Extended Attributes Information"),
+ bf_boolean16(0x0040, "ret_info_mask_arch", "Return Archive Information"),
+ bf_boolean16(0x0080, "ret_info_mask_mod", "Return Modify Information"),
+ bf_boolean16(0x0100, "ret_info_mask_create", "Return Creation Information"),
+ bf_boolean16(0x0200, "ret_info_mask_ns", "Return Name Space Information"),
+ bf_boolean16(0x0400, "ret_info_mask_dir", "Return Directory Information"),
+ bf_boolean16(0x0800, "ret_info_mask_rights", "Return Rights Information"),
+ bf_boolean16(0x1000, "ret_info_mask_id", "Return ID Information"),
+ bf_boolean16(0x2000, "ret_info_mask_ns_attr", "Return Name Space Attributes Information"),
+ bf_boolean16(0x4000, "ret_info_mask_actual", "Return Actual Information"),
+ bf_boolean16(0x8000, "ret_info_mask_logical", "Return Logical Information"),
+])
+ReturnedListCount = uint32("returned_list_count", "Returned List Count")
+Revision = uint32("revision", "Revision")
+RevisionNumber = uint8("revision_number", "Revision")
+RevQueryFlag = val_string8("rev_query_flag", "Revoke Rights Query Flag", [
+ [ 0x00, "Do not query the locks engine for access rights" ],
+ [ 0x01, "Query the locks engine and return the access rights" ],
+])
+RightsGrantMask = bitfield8("rights_grant_mask", "Grant Rights", [
+ bf_boolean8(0x01, "rights_grant_mask_read", "Read"),
+ bf_boolean8(0x02, "rights_grant_mask_write", "Write"),
+ bf_boolean8(0x04, "rights_grant_mask_open", "Open"),
+ bf_boolean8(0x08, "rights_grant_mask_create", "Create"),
+ bf_boolean8(0x10, "rights_grant_mask_del", "Delete"),
+ bf_boolean8(0x20, "rights_grant_mask_parent", "Parental"),
+ bf_boolean8(0x40, "rights_grant_mask_search", "Search"),
+ bf_boolean8(0x80, "rights_grant_mask_mod", "Modify"),
+])
+RightsRevokeMask = bitfield8("rights_revoke_mask", "Revoke Rights", [
+ bf_boolean8(0x01, "rights_revoke_mask_read", "Read"),
+ bf_boolean8(0x02, "rights_revoke_mask_write", "Write"),
+ bf_boolean8(0x04, "rights_revoke_mask_open", "Open"),
+ bf_boolean8(0x08, "rights_revoke_mask_create", "Create"),
+ bf_boolean8(0x10, "rights_revoke_mask_del", "Delete"),
+ bf_boolean8(0x20, "rights_revoke_mask_parent", "Parental"),
+ bf_boolean8(0x40, "rights_revoke_mask_search", "Search"),
+ bf_boolean8(0x80, "rights_revoke_mask_mod", "Modify"),
+])
+RIPSocketNumber = uint16("rip_socket_num", "RIP Socket Number")
+RIPSocketNumber.Display("BASE_HEX")
+RouterDownFlag = boolean8("router_dn_flag", "Router Down Flag")
+RPCccode = val_string16("rpc_c_code", "RPC Completion Code", [
+ [ 0x0000, "Successful" ],
+])
+RTagNumber = uint32("r_tag_num", "Resource Tag Number")
+RTagNumber.Display("BASE_HEX")
+RpyNearestSrvFlag = boolean8("rpy_nearest_srv_flag", "Reply to Nearest Server Flag")
+
+SalvageableFileEntryNumber = uint32("salvageable_file_entry_number", "Salvageable File Entry Number")
+SalvageableFileEntryNumber.Display("BASE_HEX")
+SAPSocketNumber = uint16("sap_socket_number", "SAP Socket Number")
+SAPSocketNumber.Display("BASE_HEX")
+ScanItems = uint32("scan_items", "Number of Items returned from Scan")
+SearchAttributes = bitfield8("sattr", "Search Attributes", [
+ bf_boolean8(0x01, "sattr_ronly", "Read-Only Files Allowed"),
+ bf_boolean8(0x02, "sattr_hid", "Hidden Files Allowed"),
+ bf_boolean8(0x04, "sattr_sys", "System Files Allowed"),
+ bf_boolean8(0x08, "sattr_exonly", "Execute-Only Files Allowed"),
+ bf_boolean8(0x10, "sattr_sub", "Subdirectories Only"),
+ bf_boolean8(0x20, "sattr_archive", "Archive"),
+ bf_boolean8(0x40, "sattr_execute_confirm", "Execute Confirm"),
+ bf_boolean8(0x80, "sattr_shareable", "Shareable"),
+])
+SearchAttributesLow = bitfield16("search_att_low", "Search Attributes", [
+ bf_boolean16(0x0001, "search_att_read_only", "Read-Only"),
+ bf_boolean16(0x0002, "search_att_hidden", "Hidden Files Allowed"),
+ bf_boolean16(0x0004, "search_att_system", "System"),
+ bf_boolean16(0x0008, "search_att_execute_only", "Execute-Only"),
+ bf_boolean16(0x0010, "search_att_sub", "Subdirectories Only"),
+ bf_boolean16(0x0020, "search_att_archive", "Archive"),
+ bf_boolean16(0x0040, "search_att_execute_confirm", "Execute Confirm"),
+ bf_boolean16(0x0080, "search_att_shareable", "Shareable"),
+ bf_boolean16(0x8000, "search_attr_all_files", "All Files and Directories"),
+])
+SearchBitMap = bitfield8("search_bit_map", "Search Bit Map", [
+ bf_boolean8(0x01, "search_bit_map_hidden", "Hidden"),
+ bf_boolean8(0x02, "search_bit_map_sys", "System"),
+ bf_boolean8(0x04, "search_bit_map_sub", "Subdirectory"),
+ bf_boolean8(0x08, "search_bit_map_files", "Files"),
+])
+SearchConnNumber = uint32("search_conn_number", "Search Connection Number")
+SearchInstance = uint32("search_instance", "Search Instance")
+SearchNumber = uint32("search_number", "Search Number")
+SearchPattern = nstring8("search_pattern", "Search Pattern")
+SearchSequence = bytes("search_sequence", "Search Sequence", 9)
+SearchSequenceWord = uint16("search_sequence_word", "Search Sequence", BE)
+Second = uint8("s_second", "Seconds")
+SecondsRelativeToTheYear2000 = uint32("sec_rel_to_y2k", "Seconds Relative to the Year 2000")
+SecretStoreVerb = val_string8("ss_verb", "Secret Store Verb",[
+ [ 0x00, "Query Server" ],
+ [ 0x01, "Read App Secrets" ],
+ [ 0x02, "Write App Secrets" ],
+ [ 0x03, "Add Secret ID" ],
+ [ 0x04, "Remove Secret ID" ],
+ [ 0x05, "Remove SecretStore" ],
+ [ 0x06, "Enumerate Secret IDs" ],
+ [ 0x07, "Unlock Store" ],
+ [ 0x08, "Set Master Password" ],
+ [ 0x09, "Get Service Information" ],
+])
+SecurityEquivalentList = fw_string("security_equiv_list", "Security Equivalent List", 128)
+SecurityFlag = bitfield8("security_flag", "Security Flag", [
+ bf_boolean8(0x01, "checksuming", "Checksumming"),
+ bf_boolean8(0x02, "signature", "Signature"),
+ bf_boolean8(0x04, "complete_signatures", "Complete Signatures"),
+ bf_boolean8(0x08, "encryption", "Encryption"),
+ bf_boolean8(0x80, "large_internet_packets", "Large Internet Packets (LIP) Disabled"),
+])
+SecurityRestrictionVersion = uint8("security_restriction_version", "Security Restriction Version")
+SectorsPerBlock = uint8("sectors_per_block", "Sectors Per Block")
+SectorsPerCluster = uint16("sectors_per_cluster", "Sectors Per Cluster" )
+SectorsPerClusterLong = uint32("sectors_per_cluster_long", "Sectors Per Cluster" )
+SectorsPerTrack = uint8("sectors_per_track", "Sectors Per Track")
+SectorSize = uint32("sector_size", "Sector Size")
+SemaphoreHandle = uint32("semaphore_handle", "Semaphore Handle")
+SemaphoreName = nstring8("semaphore_name", "Semaphore Name")
+SemaphoreNameLen = uint8("semaphore_name_len", "Semaphore Name Len")
+SemaphoreOpenCount = uint8("semaphore_open_count", "Semaphore Open Count")
+SemaphoreShareCount = uint8("semaphore_share_count", "Semaphore Share Count")
+SemaphoreTimeOut = uint16("semaphore_time_out", "Semaphore Time Out")
+SemaphoreValue = uint16("semaphore_value", "Semaphore Value")
+SendStatus = val_string8("send_status", "Send Status", [
+ [ 0x00, "Successful" ],
+ [ 0x01, "Illegal Station Number" ],
+ [ 0x02, "Client Not Logged In" ],
+ [ 0x03, "Client Not Accepting Messages" ],
+ [ 0x04, "Client Already has a Message" ],
+ [ 0x96, "No Alloc Space for the Message" ],
+ [ 0xfd, "Bad Station Number" ],
+ [ 0xff, "Failure" ],
+])
+SequenceByte = uint8("sequence_byte", "Sequence")
+SequenceNumber = uint32("sequence_number", "Sequence Number")
+SequenceNumber.Display("BASE_HEX")
+ServerAddress = bytes("server_address", "Server Address", 12)
+ServerAppNumber = uint16("server_app_num", "Server App Number")
+#ServerIDList = uint32("server_id_list", "Server ID List")
+ServerID = uint32("server_id_number", "Server ID", BE )
+ServerID.Display("BASE_HEX")
+ServerInfoFlags = val_string16("server_info_flags", "Server Information Flags", [
+ [ 0x0000, "This server is not a member of a Cluster" ],
+ [ 0x0001, "This server is a member of a Cluster" ],
+])
+serverListFlags = uint32("server_list_flags", "Server List Flags")
+ServerName = fw_string("server_name", "Server Name", 48)
+serverName50 = fw_string("server_name50", "Server Name", 50)
+ServerNameLen = nstring8("server_name_len", "Server Name")
+ServerNameStringz = stringz("server_name_stringz", "Server Name")
+ServerNetworkAddress = bytes("server_network_address", "Server Network Address", 10)
+ServerNode = bytes("server_node", "Server Node", 6)
+ServerSerialNumber = uint32("server_serial_number", "Server Serial Number")
+ServerStation = uint8("server_station", "Server Station")
+ServerStationLong = uint32("server_station_long", "Server Station")
+ServerStationList = uint8("server_station_list", "Server Station List")
+ServerStatusRecord = fw_string("server_status_record", "Server Status Record", 64)
+ServerTaskNumber = uint8("server_task_number", "Server Task Number")
+ServerTaskNumberLong = uint32("server_task_number_long", "Server Task Number")
+ServerType = uint16("server_type", "Server Type")
+ServerType.Display("BASE_HEX")
+ServerUtilization = uint32("server_utilization", "Server Utilization")
+ServerUtilizationPercentage = uint8("server_utilization_percentage", "Server Utilization Percentage")
+ServiceType = val_string16("Service_type", "Service Type", [
+ [ 0x0000, "Unknown" ],
+ [ 0x0001, "User" ],
+ [ 0x0002, "User group" ],
+ [ 0x0003, "Print queue" ],
+ [ 0x0004, "NetWare file server" ],
+ [ 0x0005, "Job server" ],
+ [ 0x0006, "Gateway" ],
+ [ 0x0007, "Print server" ],
+ [ 0x0008, "Archive queue" ],
+ [ 0x0009, "Archive server" ],
+ [ 0x000a, "Job queue" ],
+ [ 0x000b, "Administration" ],
+ [ 0x0021, "NAS SNA gateway" ],
+ [ 0x0026, "Remote bridge server" ],
+ [ 0x0027, "TCP/IP gateway" ],
+])
+SetCmdCategory = val_string8("set_cmd_category", "Set Command Category", [
+ [ 0x00, "Communications" ],
+ [ 0x01, "Memory" ],
+ [ 0x02, "File Cache" ],
+ [ 0x03, "Directory Cache" ],
+ [ 0x04, "File System" ],
+ [ 0x05, "Locks" ],
+ [ 0x06, "Transaction Tracking" ],
+ [ 0x07, "Disk" ],
+ [ 0x08, "Time" ],
+ [ 0x09, "NCP" ],
+ [ 0x0a, "Miscellaneous" ],
+ [ 0x0b, "Error Handling" ],
+ [ 0x0c, "Directory Services" ],
+ [ 0x0d, "MultiProcessor" ],
+ [ 0x0e, "Service Location Protocol" ],
+ [ 0x0f, "Licensing Services" ],
+])
+SetCmdFlags = bitfield8("set_cmd_flags", "Set Command Flags", [
+ bf_boolean8(0x01, "cmd_flags_startup_only", "Startup.ncf Only"),
+ bf_boolean8(0x02, "cmd_flags_hidden", "Hidden"),
+ bf_boolean8(0x04, "cmd_flags_advanced", "Advanced"),
+ bf_boolean8(0x08, "cmd_flags_later", "Restart Server Required to Take Effect"),
+ bf_boolean8(0x80, "cmd_flags_secure", "Console Secured"),
+])
+SetCmdName = stringz("set_cmd_name", "Set Command Name")
+SetCmdType = val_string8("set_cmd_type", "Set Command Type", [
+ [ 0x00, "Numeric Value" ],
+ [ 0x01, "Boolean Value" ],
+ [ 0x02, "Ticks Value" ],
+ [ 0x04, "Time Value" ],
+ [ 0x05, "String Value" ],
+ [ 0x06, "Trigger Value" ],
+ [ 0x07, "Numeric Value" ],
+])
+SetCmdValueNum = uint32("set_cmd_value_num", "Set Command Value")
+SetCmdValueString = stringz("set_cmd_value_string", "Set Command Value")
+SetParmName = stringz("set_parm_name", "Set Parameter Name")
+SFTErrorTable = bytes("sft_error_table", "SFT Error Table", 60)
+SFTSupportLevel = val_string8("sft_support_level", "SFT Support Level", [
+ [ 0x01, "Server Offers Hot Disk Error Fixing" ],
+ [ 0x02, "Server Offers Disk Mirroring and Transaction Tracking" ],
+ [ 0x03, "Server Offers Physical Server Mirroring" ],
+])
+ShareableLockCount = uint16("shareable_lock_count", "Shareable Lock Count")
+SharedMemoryAddresses = bytes("shared_memory_addresses", "Shared Memory Addresses", 10)
+ShortName = fw_string("short_name", "Short Name", 12)
+ShortStkName = fw_string("short_stack_name", "Short Stack Name", 16)
+SiblingCount = uint32("sibling_count", "Sibling Count")
+SixtyFourBitOffsetsSupportedFlag = val_string8("64_bit_flag", "64 Bit Support", [
+ [ 0x00, "No support for 64 bit offsets" ],
+ [ 0x01, "64 bit offsets supported" ],
+])
+SMIDs = uint32("smids", "Storage Media ID's")
+SoftwareDescription = fw_string("software_description", "Software Description", 65)
+SoftwareDriverType = uint8("software_driver_type", "Software Driver Type")
+SoftwareMajorVersionNumber = uint8("software_major_version_number", "Software Major Version Number")
+SoftwareMinorVersionNumber = uint8("software_minor_version_number", "Software Minor Version Number")
+SourceDirHandle = uint8("source_dir_handle", "Source Directory Handle")
+sourceOriginateTime = bytes("source_originate_time", "Source Originate Time", 8)
+sourceOriginateTime.Display("BASE_HEX")
+SourcePath = nstring8("source_path", "Source Path")
+SourcePathComponentCount = uint8("source_component_count", "Source Path Component Count")
+sourceReturnTime = bytes("source_return_time", "Source Return Time", 8)
+sourceReturnTime.Display("BASE_HEX")
+SpaceUsed = uint32("space_used", "Space Used")
+SpaceMigrated = uint32("space_migrated", "Space Migrated")
+SrcNameSpace = val_string8("src_name_space", "Source Name Space", [
+ [ 0x00, "DOS Name Space" ],
+ [ 0x01, "MAC Name Space" ],
+ [ 0x02, "NFS Name Space" ],
+ [ 0x04, "Long Name Space" ],
+])
+SupModID = uint32("sup_mod_id", "Sup Mod ID")
+StackCount = uint32("stack_count", "Stack Count")
+StackFullNameStr = nstring8("stack_full_name_str", "Stack Full Name")
+StackMajorVN = uint8("stack_major_vn", "Stack Major Version Number")
+StackMinorVN = uint8("stack_minor_vn", "Stack Minor Version Number")
+StackNumber = uint32("stack_number", "Stack Number")
+StartConnNumber = uint32("start_conn_num", "Starting Connection Number")
+StartingBlock = uint16("starting_block", "Starting Block")
+StartingNumber = uint32("starting_number", "Starting Number")
+StartingSearchNumber = uint16("start_search_number", "Start Search Number")
+StartNumber = uint32("start_number", "Start Number")
+startNumberFlag = uint16("start_number_flag", "Start Number Flag")
+StartOffset64bit = bytes("s_offset_64bit", "64bit Starting Offset", 64)
+StartVolumeNumber = uint32("start_volume_number", "Starting Volume Number")
+StationList = uint32("station_list", "Station List")
+StationNumber = bytes("station_number", "Station Number", 3)
+StatMajorVersion = uint8("stat_major_version", "Statistics Table Major Version")
+StatMinorVersion = uint8("stat_minor_version", "Statistics Table Minor Version")
+Status = bitfield16("status", "Status", [
+ bf_boolean16(0x0001, "user_info_logged_in", "Logged In"),
+ bf_boolean16(0x0002, "user_info_being_abort", "Being Aborted"),
+ bf_boolean16(0x0004, "user_info_audited", "Audited"),
+ bf_boolean16(0x0008, "user_info_need_sec", "Needs Security Change"),
+ bf_boolean16(0x0010, "user_info_mac_station", "MAC Station"),
+ bf_boolean16(0x0020, "user_info_temp_authen", "Temporary Authenticated"),
+ bf_boolean16(0x0040, "user_info_audit_conn", "Audit Connection Recorded"),
+ bf_boolean16(0x0080, "user_info_dsaudit_conn", "DS Audit Connection Recorded"),
+ bf_boolean16(0x0100, "user_info_logout", "Logout in Progress"),
+ bf_boolean16(0x0200, "user_info_int_login", "Internal Login"),
+ bf_boolean16(0x0400, "user_info_bindery", "Bindery Connection"),
+])
+StatusFlagBits = bitfield32("status_flag_bits", "Status Flag", [
+ bf_boolean32(0x00000001, "status_flag_bits_suballoc", "Sub Allocation"),
+ bf_boolean32(0x00000002, "status_flag_bits_comp", "Compression"),
+ bf_boolean32(0x00000004, "status_flag_bits_migrate", "Migration"),
+ bf_boolean32(0x00000008, "status_flag_bits_audit", "Audit"),
+ bf_boolean32(0x00000010, "status_flag_bits_ro", "Read Only"),
+ bf_boolean32(0x00000020, "status_flag_bits_im_purge", "Immediate Purge"),
+ bf_boolean32(0x80000000, "status_flag_bits_nss", "NSS Volume"),
+])
+SubAllocClusters = uint32("sub_alloc_clusters", "Sub Alloc Clusters")
+SubAllocFreeableClusters = uint32("sub_alloc_freeable_clusters", "Sub Alloc Freeable Clusters")
+Subdirectory = uint32("sub_directory", "Subdirectory")
+Subdirectory.Display("BASE_HEX")
+SuggestedFileSize = uint32("suggested_file_size", "Suggested File Size")
+SupportModuleID = uint32("support_module_id", "Support Module ID")
+SynchName = nstring8("synch_name", "Synch Name")
+SystemIntervalMarker = uint32("system_interval_marker", "System Interval Marker")
+
+TabSize = uint8( "tab_size", "Tab Size" )
+TargetClientList = uint8("target_client_list", "Target Client List")
+TargetConnectionNumber = uint16("target_connection_number", "Target Connection Number")
+TargetDirectoryBase = uint32("target_directory_base", "Target Directory Base")
+TargetDirHandle = uint8("target_dir_handle", "Target Directory Handle")
+TargetEntryID = uint32("target_entry_id", "Target Entry ID")
+TargetEntryID.Display("BASE_HEX")
+TargetExecutionTime = bytes("target_execution_time", "Target Execution Time", 6)
+TargetFileHandle = bytes("target_file_handle", "Target File Handle", 6)
+TargetFileOffset = uint32("target_file_offset", "Target File Offset")
+TargetMessage = nstring8("target_message", "Message")
+TargetPrinter = uint8( "target_ptr", "Target Printer" )
+targetReceiveTime = bytes("target_receive_time", "Target Receive Time", 8)
+targetReceiveTime.Display("BASE_HEX")
+TargetServerIDNumber = uint32("target_server_id_number", "Target Server ID Number", BE )
+TargetServerIDNumber.Display("BASE_HEX")
+targetTransmitTime = bytes("target_transmit_time", "Target Transmit Time", 8)
+targetTransmitTime.Display("BASE_HEX")
+TaskNumByte = uint8("task_num_byte", "Task Number")
+TaskNumber = uint32("task_number", "Task Number")
+TaskNumberWord = uint16("task_number_word", "Task Number")
+TextJobDescription = fw_string("text_job_description", "Text Job Description", 50)
+ThrashingCount = uint16("thrashing_count", "Thrashing Count")
+TimeoutLimit = uint16("timeout_limit", "Timeout Limit")
+TimesyncStatus = bitfield32("timesync_status_flags", "Timesync Status", [
+ bf_boolean32(0x00000001, "timesync_status_sync", "Time is Synchronized"),
+ bf_boolean32(0x00000002, "timesync_status_net_sync", "Time is Synchronized to the Network"),
+ bf_boolean32(0x00000004, "timesync_status_active", "Time Synchronization is Active"),
+ bf_boolean32(0x00000008, "timesync_status_external", "External Time Synchronization Active"),
+ bf_val_str32(0x00000700, "timesync_status_server_type", "Time Server Type", [
+ [ 0x01, "Client Time Server" ],
+ [ 0x02, "Secondary Time Server" ],
+ [ 0x03, "Primary Time Server" ],
+ [ 0x04, "Reference Time Server" ],
+ [ 0x05, "Single Reference Time Server" ],
+ ]),
+ bf_boolean32(0x000f0000, "timesync_status_ext_sync", "External Clock Status"),
+])
+TimeToNet = uint16("time_to_net", "Time To Net")
+TotalBlocks = uint32("total_blocks", "Total Blocks")
+TotalBlocksToDecompress = uint32("total_blks_to_dcompress", "Total Blocks To Decompress")
+TotalBytesRead = bytes("user_info_ttl_bytes_rd", "Total Bytes Read", 6)
+TotalBytesWritten = bytes("user_info_ttl_bytes_wrt", "Total Bytes Written", 6)
+TotalCacheWrites = uint32("total_cache_writes", "Total Cache Writes")
+TotalChangedFATs = uint32("total_changed_fats", "Total Changed FAT Entries")
+TotalCommonCnts = uint32("total_common_cnts", "Total Common Counts")
+TotalCntBlocks = uint32("total_cnt_blocks", "Total Count Blocks")
+TotalDataStreamDiskSpaceAlloc = uint32("total_stream_size_struct_space_alloc", "Total Data Stream Disk Space Alloc")
+TotalDirectorySlots = uint16("total_directory_slots", "Total Directory Slots")
+TotalDirectoryEntries = uint32("total_dir_entries", "Total Directory Entries")
+TotalDynamicSpace = uint32("total_dynamic_space", "Total Dynamic Space")
+TotalExtendedDirectoryExtants = uint32("total_extended_directory_extants", "Total Extended Directory Extants")
+TotalFileServicePackets = uint32("total_file_service_packets", "Total File Service Packets")
+TotalFilesOpened = uint32("total_files_opened", "Total Files Opened")
+TotalLFSCounters = uint32("total_lfs_counters", "Total LFS Counters")
+TotalOffspring = uint16("total_offspring", "Total Offspring")
+TotalOtherPackets = uint32("total_other_packets", "Total Other Packets")
+TotalQueueJobs = uint32("total_queue_jobs", "Total Queue Jobs")
+TotalReadRequests = uint32("total_read_requests", "Total Read Requests")
+TotalRequest = uint32("total_request", "Total Requests")
+TotalRequestPackets = uint32("total_request_packets", "Total Request Packets")
+TotalRoutedPackets = uint32("total_routed_packets", "Total Routed Packets")
+TotalRxPkts = uint32("total_rx_pkts", "Total Receive Packets")
+TotalServerMemory = uint16("total_server_memory", "Total Server Memory", BE)
+TotalTransactionsBackedOut = uint32("total_trans_backed_out", "Total Transactions Backed Out")
+TotalTransactionsPerformed = uint32("total_trans_performed", "Total Transactions Performed")
+TotalTxPkts = uint32("total_tx_pkts", "Total Transmit Packets")
+TotalUnfilledBackoutRequests = uint16("total_unfilled_backout_requests", "Total Unfilled Backout Requests")
+TotalVolumeClusters = uint16("total_volume_clusters", "Total Volume Clusters")
+TotalWriteRequests = uint32("total_write_requests", "Total Write Requests")
+TotalWriteTransactionsPerformed = uint32("total_write_trans_performed", "Total Write Transactions Performed")
+TrackOnFlag = boolean8("track_on_flag", "Track On Flag")
+TransactionDiskSpace = uint16("transaction_disk_space", "Transaction Disk Space")
+TransactionFATAllocations = uint32("transaction_fat_allocations", "Transaction FAT Allocations")
+TransactionFileSizeChanges = uint32("transaction_file_size_changes", "Transaction File Size Changes")
+TransactionFilesTruncated = uint32("transaction_files_truncated", "Transaction Files Truncated")
+TransactionNumber = uint32("transaction_number", "Transaction Number")
+TransactionTrackingEnabled = uint8("transaction_tracking_enabled", "Transaction Tracking Enabled")
+TransactionTrackingFlag = uint16("tts_flag", "Transaction Tracking Flag")
+TransactionTrackingSupported = uint8("transaction_tracking_supported", "Transaction Tracking Supported")
+TransactionVolumeNumber = uint16("transaction_volume_number", "Transaction Volume Number")
+TransportType = val_string8("transport_type", "Communications Type", [
+ [ 0x01, "Internet Packet Exchange (IPX)" ],
+ [ 0x05, "User Datagram Protocol (UDP)" ],
+ [ 0x06, "Transmission Control Protocol (TCP)" ],
+])
+TreeLength = uint32("tree_length", "Tree Length")
+TreeName = nstring32("tree_name", "Tree Name")
+TreeName.NWUnicode()
+TrusteeRights = bitfield16("trustee_rights_low", "Trustee Rights", [
+ bf_boolean16(0x0001, "trustee_rights_read", "Read"),
+ bf_boolean16(0x0002, "trustee_rights_write", "Write"),
+ bf_boolean16(0x0004, "trustee_rights_open", "Open"),
+ bf_boolean16(0x0008, "trustee_rights_create", "Create"),
+ bf_boolean16(0x0010, "trustee_rights_del", "Delete"),
+ bf_boolean16(0x0020, "trustee_rights_parent", "Parental"),
+ bf_boolean16(0x0040, "trustee_rights_search", "Search"),
+ bf_boolean16(0x0080, "trustee_rights_modify", "Modify"),
+ bf_boolean16(0x0100, "trustee_rights_super", "Supervisor"),
+])
+TTSLevel = uint8("tts_level", "TTS Level")
+TrusteeSetNumber = uint8("trustee_set_number", "Trustee Set Number")
+TrusteeID = uint32("trustee_id_set", "Trustee ID")
+TrusteeID.Display("BASE_HEX")
+ttlCompBlks = uint32("ttl_comp_blks", "Total Compression Blocks")
+TtlDSDskSpaceAlloc = uint32("ttl_ds_disk_space_alloc", "Total Streams Space Allocated")
+TtlEAs = uint32("ttl_eas", "Total EA's")
+TtlEAsDataSize = uint32("ttl_eas_data_size", "Total EA's Data Size")
+TtlEAsKeySize = uint32("ttl_eas_key_size", "Total EA's Key Size")
+ttlIntermediateBlks = uint32("ttl_inter_blks", "Total Intermediate Blocks")
+TtlMigratedSize = uint32("ttl_migrated_size", "Total Migrated Size")
+TtlNumOfRTags = uint32("ttl_num_of_r_tags", "Total Number of Resource Tags")
+TtlNumOfSetCmds = uint32("ttl_num_of_set_cmds", "Total Number of Set Commands")
+TtlValuesLength = uint32("ttl_values_length", "Total Values Length")
+TtlWriteDataSize = uint32("ttl_write_data_size", "Total Write Data Size")
+TurboUsedForFileService = uint16("turbo_used_for_file_service", "Turbo Used For File Service")
+
+UnclaimedPkts = uint32("un_claimed_packets", "Unclaimed Packets")
+UnCompressableDataStreamsCount = uint32("un_compressable_data_streams_count", "Uncompressable Data Streams Count")
+Undefined8 = bytes("undefined_8", "Undefined", 8)
+Undefined28 = bytes("undefined_28", "Undefined", 28)
+UndefinedWord = uint16("undefined_word", "Undefined")
+UniqueID = uint8("unique_id", "Unique ID")
+UnknownByte = uint8("unknown_byte", "Unknown Byte")
+Unused = uint8("un_used", "Unused")
+UnusedBlocks = uint32("unused_blocks", "Unused Blocks")
+UnUsedDirectoryEntries = uint32("un_used_directory_entries", "Unused Directory Entries")
+UnusedDiskBlocks = uint32("unused_disk_blocks", "Unused Disk Blocks")
+UnUsedExtendedDirectoryExtants = uint32("un_used_extended_directory_extants", "Unused Extended Directory Extants")
+UpdateDate = uint16("update_date", "Update Date")
+UpdateDate.NWDate()
+UpdateID = uint32("update_id", "Update ID", BE)
+UpdateID.Display("BASE_HEX")
+UpdateTime = uint16("update_time", "Update Time")
+UpdateTime.NWTime()
+UseCount = val_string16("user_info_use_count", "Use Count", [
+ [ 0x0000, "Connection is not in use" ],
+ [ 0x0001, "Connection is in use" ],
+])
+UsedBlocks = uint32("used_blocks", "Used Blocks")
+UserID = uint32("user_id", "User ID", BE)
+UserID.Display("BASE_HEX")
+UserLoginAllowed = val_string8("user_login_allowed", "Login Status", [
+ [ 0x00, "Client Login Disabled" ],
+ [ 0x01, "Client Login Enabled" ],
+])
+
+UserName = nstring8("user_name", "User Name")
+UserName16 = fw_string("user_name_16", "User Name", 16)
+UserName48 = fw_string("user_name_48", "User Name", 48)
+UserType = uint16("user_type", "User Type")
+UTCTimeInSeconds = uint32("uts_time_in_seconds", "UTC Time in Seconds")
+
+ValueAvailable = val_string8("value_available", "Value Available", [
+ [ 0x00, "Has No Value" ],
+ [ 0xff, "Has Value" ],
+])
+VAPVersion = uint8("vap_version", "VAP Version")
+VariableBitMask = uint32("variable_bit_mask", "Variable Bit Mask")
+VariableBitsDefined = uint16("variable_bits_defined", "Variable Bits Defined")
+VConsoleRevision = uint8("vconsole_rev", "Console Revision")
+VConsoleVersion = uint8("vconsole_ver", "Console Version")
+Verb = uint32("verb", "Verb")
+VerbData = uint8("verb_data", "Verb Data")
+version = uint32("version", "Version")
+VersionNumber = uint8("version_number", "Version")
+VertLocation = uint16("vert_location", "Vertical Location")
+VirtualConsoleVersion = uint8("virtual_console_version", "Virtual Console Version")
+VolumeID = uint32("volume_id", "Volume ID")
+VolumeID.Display("BASE_HEX")
+VolInfoReplyLen = uint16("vol_info_reply_len", "Volume Information Reply Length")
+VolumeCachedFlag = val_string8("volume_cached_flag", "Volume Cached Flag", [
+ [ 0x00, "Volume is Not Cached" ],
+ [ 0xff, "Volume is Cached" ],
+])
+VolumeDataStreams = uint8("volume_data_streams", "Volume Data Streams")
+VolumeHashedFlag = val_string8("volume_hashed_flag", "Volume Hashed Flag", [
+ [ 0x00, "Volume is Not Hashed" ],
+ [ 0xff, "Volume is Hashed" ],
+])
+VolumeLastModifiedDate = uint16("volume_last_modified_date", "Volume Last Modified Date")
+VolumeLastModifiedDate.NWDate()
+VolumeLastModifiedTime = uint16("volume_last_modified_time", "Volume Last Modified Time")
+VolumeLastModifiedTime.NWTime()
+VolumeMountedFlag = val_string8("volume_mounted_flag", "Volume Mounted Flag", [
+ [ 0x00, "Volume is Not Mounted" ],
+ [ 0xff, "Volume is Mounted" ],
+])
+VolumeName = fw_string("volume_name", "Volume Name", 16)
+VolumeNameLen = nstring8("volume_name_len", "Volume Name")
+VolumeNameSpaces = uint8("volume_name_spaces", "Volume Name Spaces")
+VolumeNameStringz = stringz("volume_name_stringz", "Volume Name")
+VolumeNumber = uint8("volume_number", "Volume Number")
+VolumeNumberLong = uint32("volume_number_long", "Volume Number")
+VolumeRemovableFlag = val_string8("volume_removable_flag", "Volume Removable Flag", [
+ [ 0x00, "Disk Cannot be Removed from Server" ],
+ [ 0xff, "Disk Can be Removed from Server" ],
+])
+VolumeRequestFlags = val_string16("volume_request_flags", "Volume Request Flags", [
+ [ 0x0000, "Return name with volume number" ],
+ [ 0x0001, "Do not return name with volume number" ],
+])
+VolumeSizeInClusters = uint32("volume_size_in_clusters", "Volume Size in Clusters")
+VolumesSupportedMax = uint16("volumes_supported_max", "Volumes Supported Max")
+VolumeType = val_string16("volume_type", "Volume Type", [
+ [ 0x0000, "NetWare 386" ],
+ [ 0x0001, "NetWare 286" ],
+ [ 0x0002, "NetWare 386 Version 30" ],
+ [ 0x0003, "NetWare 386 Version 31" ],
+])
+WastedServerMemory = uint16("wasted_server_memory", "Wasted Server Memory", BE)
+WaitTime = uint32("wait_time", "Wait Time")
+
+Year = val_string8("year", "Year",[
+ [ 0x50, "1980" ],
+ [ 0x51, "1981" ],
+ [ 0x52, "1982" ],
+ [ 0x53, "1983" ],
+ [ 0x54, "1984" ],
+ [ 0x55, "1985" ],
+ [ 0x56, "1986" ],
+ [ 0x57, "1987" ],
+ [ 0x58, "1988" ],
+ [ 0x59, "1989" ],
+ [ 0x5a, "1990" ],
+ [ 0x5b, "1991" ],
+ [ 0x5c, "1992" ],
+ [ 0x5d, "1993" ],
+ [ 0x5e, "1994" ],
+ [ 0x5f, "1995" ],
+ [ 0x60, "1996" ],
+ [ 0x61, "1997" ],
+ [ 0x62, "1998" ],
+ [ 0x63, "1999" ],
+ [ 0x64, "2000" ],
+ [ 0x65, "2001" ],
+ [ 0x66, "2002" ],
+ [ 0x67, "2003" ],
+ [ 0x68, "2004" ],
+ [ 0x69, "2005" ],
+ [ 0x6a, "2006" ],
+ [ 0x6b, "2007" ],
+ [ 0x6c, "2008" ],
+ [ 0x6d, "2009" ],
+ [ 0x6e, "2010" ],
+ [ 0x6f, "2011" ],
+ [ 0x70, "2012" ],
+ [ 0x71, "2013" ],
+ [ 0x72, "2014" ],
+ [ 0x73, "2015" ],
+ [ 0x74, "2016" ],
+ [ 0x75, "2017" ],
+ [ 0x76, "2018" ],
+ [ 0x77, "2019" ],
+ [ 0x78, "2020" ],
+ [ 0x79, "2021" ],
+ [ 0x7a, "2022" ],
+ [ 0x7b, "2023" ],
+ [ 0x7c, "2024" ],
+ [ 0x7d, "2025" ],
+ [ 0x7e, "2026" ],
+ [ 0x7f, "2027" ],
+ [ 0xc0, "1984" ],
+ [ 0xc1, "1985" ],
+ [ 0xc2, "1986" ],
+ [ 0xc3, "1987" ],
+ [ 0xc4, "1988" ],
+ [ 0xc5, "1989" ],
+ [ 0xc6, "1990" ],
+ [ 0xc7, "1991" ],
+ [ 0xc8, "1992" ],
+ [ 0xc9, "1993" ],
+ [ 0xca, "1994" ],
+ [ 0xcb, "1995" ],
+ [ 0xcc, "1996" ],
+ [ 0xcd, "1997" ],
+ [ 0xce, "1998" ],
+ [ 0xcf, "1999" ],
+ [ 0xd0, "2000" ],
+ [ 0xd1, "2001" ],
+ [ 0xd2, "2002" ],
+ [ 0xd3, "2003" ],
+ [ 0xd4, "2004" ],
+ [ 0xd5, "2005" ],
+ [ 0xd6, "2006" ],
+ [ 0xd7, "2007" ],
+ [ 0xd8, "2008" ],
+ [ 0xd9, "2009" ],
+ [ 0xda, "2010" ],
+ [ 0xdb, "2011" ],
+ [ 0xdc, "2012" ],
+ [ 0xdd, "2013" ],
+ [ 0xde, "2014" ],
+ [ 0xdf, "2015" ],
+])
+##############################################################################
+# Structs
+##############################################################################
+
+
+acctngInfo = struct("acctng_info_struct", [
+ HoldTime,
+ HoldAmount,
+ ChargeAmount,
+ HeldConnectTimeInMinutes,
+ HeldRequests,
+ HeldBytesRead,
+ HeldBytesWritten,
+],"Accounting Information")
+AFP10Struct = struct("afp_10_struct", [
+ AFPEntryID,
+ ParentID,
+ AttributesDef16,
+ DataForkLen,
+ ResourceForkLen,
+ TotalOffspring,
+ CreationDate,
+ LastAccessedDate,
+ ModifiedDate,
+ ModifiedTime,
+ ArchivedDate,
+ ArchivedTime,
+ CreatorID,
+ Reserved4,
+ FinderAttr,
+ HorizLocation,
+ VertLocation,
+ FileDirWindow,
+ Reserved16,
+ LongName,
+ CreatorID,
+ ShortName,
+ AccessPrivileges,
+], "AFP Information" )
+AFP20Struct = struct("afp_20_struct", [
+ AFPEntryID,
+ ParentID,
+ AttributesDef16,
+ DataForkLen,
+ ResourceForkLen,
+ TotalOffspring,
+ CreationDate,
+ LastAccessedDate,
+ ModifiedDate,
+ ModifiedTime,
+ ArchivedDate,
+ ArchivedTime,
+ CreatorID,
+ Reserved4,
+ FinderAttr,
+ HorizLocation,
+ VertLocation,
+ FileDirWindow,
+ Reserved16,
+ LongName,
+ CreatorID,
+ ShortName,
+ AccessPrivileges,
+ Reserved,
+ ProDOSInfo,
+], "AFP Information" )
+ArchiveDateStruct = struct("archive_date_struct", [
+ ArchivedDate,
+])
+ArchiveIdStruct = struct("archive_id_struct", [
+ ArchiverID,
+])
+ArchiveInfoStruct = struct("archive_info_struct", [
+ ArchivedTime,
+ ArchivedDate,
+ ArchiverID,
+], "Archive Information")
+ArchiveTimeStruct = struct("archive_time_struct", [
+ ArchivedTime,
+])
+AttributesStruct = struct("attributes_struct", [
+ AttributesDef32,
+ FlagsDef,
+], "Attributes")
+authInfo = struct("auth_info_struct", [
+ Status,
+ Reserved2,
+ Privileges,
+])
+BoardNameStruct = struct("board_name_struct", [
+ DriverBoardName,
+ DriverShortName,
+ DriverLogicalName,
+], "Board Name")
+CacheInfo = struct("cache_info", [
+ uint32("max_byte_cnt", "Maximum Byte Count"),
+ uint32("min_num_of_cache_buff", "Minimum Number Of Cache Buffers"),
+ uint32("min_cache_report_thresh", "Minimum Cache Report Threshold"),
+ uint32("alloc_waiting", "Allocate Waiting Count"),
+ uint32("ndirty_blocks", "Number of Dirty Blocks"),
+ uint32("cache_dirty_wait_time", "Cache Dirty Wait Time"),
+ uint32("cache_max_concur_writes", "Cache Maximum Concurrent Writes"),
+ uint32("max_dirty_time", "Maximum Dirty Time"),
+ uint32("num_dir_cache_buff", "Number Of Directory Cache Buffers"),
+ uint32("cache_byte_to_block", "Cache Byte To Block Shift Factor"),
+], "Cache Information")
+CommonLanStruc = struct("common_lan_struct", [
+ boolean8("not_supported_mask", "Bit Counter Supported"),
+ Reserved3,
+ uint32("total_tx_packet_count", "Total Transmit Packet Count"),
+ uint32("total_rx_packet_count", "Total Receive Packet Count"),
+ uint32("no_ecb_available_count", "No ECB Available Count"),
+ uint32("packet_tx_too_big_count", "Transmit Packet Too Big Count"),
+ uint32("packet_tx_too_small_count", "Transmit Packet Too Small Count"),
+ uint32("packet_rx_overflow_count", "Receive Packet Overflow Count"),
+ uint32("packet_rx_too_big_count", "Receive Packet Too Big Count"),
+ uint32("packet_rs_too_small_count", "Receive Packet Too Small Count"),
+ uint32("packet_tx_misc_error_count", "Transmit Packet Misc Error Count"),
+ uint32("packet_rx_misc_error_count", "Receive Packet Misc Error Count"),
+ uint32("retry_tx_count", "Transmit Retry Count"),
+ uint32("checksum_error_count", "Checksum Error Count"),
+ uint32("hardware_rx_mismatch_count", "Hardware Receive Mismatch Count"),
+], "Common LAN Information")
+CompDeCompStat = struct("comp_d_comp_stat", [
+ uint32("cmphitickhigh", "Compress High Tick"),
+ uint32("cmphitickcnt", "Compress High Tick Count"),
+ uint32("cmpbyteincount", "Compress Byte In Count"),
+ uint32("cmpbyteoutcnt", "Compress Byte Out Count"),
+ uint32("cmphibyteincnt", "Compress High Byte In Count"),
+ uint32("cmphibyteoutcnt", "Compress High Byte Out Count"),
+ uint32("decphitickhigh", "DeCompress High Tick"),
+ uint32("decphitickcnt", "DeCompress High Tick Count"),
+ uint32("decpbyteincount", "DeCompress Byte In Count"),
+ uint32("decpbyteoutcnt", "DeCompress Byte Out Count"),
+ uint32("decphibyteincnt", "DeCompress High Byte In Count"),
+ uint32("decphibyteoutcnt", "DeCompress High Byte Out Count"),
+], "Compression/Decompression Information")
+ConnFileStruct = struct("conn_file_struct", [
+ ConnectionNumberWord,
+ TaskNumByte,
+ LockType,
+ AccessControl,
+ LockFlag,
+], "File Connection Information")
+ConnStruct = struct("conn_struct", [
+ TaskNumByte,
+ LockType,
+ AccessControl,
+ LockFlag,
+ VolumeNumber,
+ DirectoryEntryNumberWord,
+ FileName14,
+], "Connection Information")
+ConnTaskStruct = struct("conn_task_struct", [
+ ConnectionNumberByte,
+ TaskNumByte,
+], "Task Information")
+Counters = struct("counters_struct", [
+ uint32("read_exist_blck", "Read Existing Block Count"),
+ uint32("read_exist_write_wait", "Read Existing Write Wait Count"),
+ uint32("read_exist_part_read", "Read Existing Partial Read Count"),
+ uint32("read_exist_read_err", "Read Existing Read Error Count"),
+ uint32("wrt_blck_cnt", "Write Block Count"),
+ uint32("wrt_entire_blck", "Write Entire Block Count"),
+ uint32("internl_dsk_get", "Internal Disk Get Count"),
+ uint32("internl_dsk_get_need_to_alloc", "Internal Disk Get Need To Allocate Count"),
+ uint32("internl_dsk_get_someone_beat", "Internal Disk Get Someone Beat My Count"),
+ uint32("internl_dsk_get_part_read", "Internal Disk Get Partial Read Count"),
+ uint32("internl_dsk_get_read_err", "Internal Disk Get Read Error Count"),
+ uint32("async_internl_dsk_get", "Async Internal Disk Get Count"),
+ uint32("async_internl_dsk_get_need_to_alloc", "Async Internal Disk Get Need To Alloc"),
+ uint32("async_internl_dsk_get_someone_beat", "Async Internal Disk Get Someone Beat Me"),
+ uint32("err_doing_async_read", "Error Doing Async Read Count"),
+ uint32("internl_dsk_get_no_read", "Internal Disk Get No Read Count"),
+ uint32("internl_dsk_get_no_read_alloc", "Internal Disk Get No Read Allocate Count"),
+ uint32("internl_dsk_get_no_read_someone_beat", "Internal Disk Get No Read Someone Beat Me Count"),
+ uint32("internl_dsk_write", "Internal Disk Write Count"),
+ uint32("internl_dsk_write_alloc", "Internal Disk Write Allocate Count"),
+ uint32("internl_dsk_write_someone_beat", "Internal Disk Write Someone Beat Me Count"),
+ uint32("write_err", "Write Error Count"),
+ uint32("wait_on_sema", "Wait On Semaphore Count"),
+ uint32("alloc_blck_i_had_to_wait_for", "Allocate Block I Had To Wait For Someone Count"),
+ uint32("alloc_blck", "Allocate Block Count"),
+ uint32("alloc_blck_i_had_to_wait", "Allocate Block I Had To Wait Count"),
+], "Disk Counter Information")
+CPUInformation = struct("cpu_information", [
+ PageTableOwnerFlag,
+ CPUType,
+ Reserved3,
+ CoprocessorFlag,
+ BusType,
+ Reserved3,
+ IOEngineFlag,
+ Reserved3,
+ FSEngineFlag,
+ Reserved3,
+ NonDedFlag,
+ Reserved3,
+ CPUString,
+ CoProcessorString,
+ BusString,
+], "CPU Information")
+CreationDateStruct = struct("creation_date_struct", [
+ CreationDate,
+])
+CreationInfoStruct = struct("creation_info_struct", [
+ CreationTime,
+ CreationDate,
+ CreatorID,
+], "Creation Information")
+CreationTimeStruct = struct("creation_time_struct", [
+ CreationTime,
+])
+CustomCntsInfo = struct("custom_cnts_info", [
+ CustomVariableValue,
+ CustomString,
+], "Custom Counters" )
+DataStreamInfo = struct("data_stream_info", [
+ AssociatedNameSpace,
+ DataStreamName
+])
+DataStreamSizeStruct = struct("data_stream_size_struct", [
+ DataStreamSize,
+])
+DirCacheInfo = struct("dir_cache_info", [
+ uint32("min_time_since_file_delete", "Minimum Time Since File Delete"),
+ uint32("abs_min_time_since_file_delete", "Absolute Minimum Time Since File Delete"),
+ uint32("min_num_of_dir_cache_buff", "Minimum Number Of Directory Cache Buffers"),
+ uint32("max_num_of_dir_cache_buff", "Maximum Number Of Directory Cache Buffers"),
+ uint32("num_of_dir_cache_buff", "Number Of Directory Cache Buffers"),
+ uint32("dc_min_non_ref_time", "DC Minimum Non-Referenced Time"),
+ uint32("dc_wait_time_before_new_buff", "DC Wait Time Before New Buffer"),
+ uint32("dc_max_concurrent_writes", "DC Maximum Concurrent Writes"),
+ uint32("dc_dirty_wait_time", "DC Dirty Wait Time"),
+ uint32("dc_double_read_flag", "DC Double Read Flag"),
+ uint32("map_hash_node_count", "Map Hash Node Count"),
+ uint32("space_restriction_node_count", "Space Restriction Node Count"),
+ uint32("trustee_list_node_count", "Trustee List Node Count"),
+ uint32("percent_of_vol_used_by_dirs", "Percent Of Volume Used By Directories"),
+], "Directory Cache Information")
+DirEntryStruct = struct("dir_entry_struct", [
+ DirectoryEntryNumber,
+ DOSDirectoryEntryNumber,
+ VolumeNumberLong,
+], "Directory Entry Information")
+DirectoryInstance = struct("directory_instance", [
+ SearchSequenceWord,
+ DirectoryID,
+ DirectoryName14,
+ DirectoryAttributes,
+ DirectoryAccessRights,
+ endian(CreationDate, BE),
+ endian(AccessDate, BE),
+ CreatorID,
+ Reserved2,
+ DirectoryStamp,
+], "Directory Information")
+DMInfoLevel0 = struct("dm_info_level_0", [
+ uint32("io_flag", "IO Flag"),
+ uint32("sm_info_size", "Storage Module Information Size"),
+ uint32("avail_space", "Available Space"),
+ uint32("used_space", "Used Space"),
+ stringz("s_module_name", "Storage Module Name"),
+ uint8("s_m_info", "Storage Media Information"),
+])
+DMInfoLevel1 = struct("dm_info_level_1", [
+ NumberOfSMs,
+ SMIDs,
+])
+DMInfoLevel2 = struct("dm_info_level_2", [
+ Name,
+])
+DOSDirectoryEntryStruct = struct("dos_directory_entry_struct", [
+ AttributesDef32,
+ UniqueID,
+ PurgeFlags,
+ DestNameSpace,
+ DirectoryNameLen,
+ DirectoryName,
+ CreationTime,
+ CreationDate,
+ CreatorID,
+ ArchivedTime,
+ ArchivedDate,
+ ArchiverID,
+ UpdateTime,
+ UpdateDate,
+ NextTrusteeEntry,
+ Reserved48,
+ InheritedRightsMask,
+], "DOS Directory Information")
+DOSFileEntryStruct = struct("dos_file_entry_struct", [
+ AttributesDef32,
+ UniqueID,
+ PurgeFlags,
+ DestNameSpace,
+ NameLen,
+ Name12,
+ CreationTime,
+ CreationDate,
+ CreatorID,
+ ArchivedTime,
+ ArchivedDate,
+ ArchiverID,
+ UpdateTime,
+ UpdateDate,
+ UpdateID,
+ FileSize,
+ DataForkFirstFAT,
+ NextTrusteeEntry,
+ Reserved36,
+ InheritedRightsMask,
+ LastAccessedDate,
+ Reserved28,
+ PrimaryEntry,
+ NameList,
+], "DOS File Information")
+DSSpaceAllocateStruct = struct("ds_space_alloc_struct", [
+ DataStreamSpaceAlloc,
+])
+DynMemStruct = struct("dyn_mem_struct", [
+ uint32("dyn_mem_struct_total", "Total Dynamic Space" ),
+ uint32("dyn_mem_struct_max", "Max Used Dynamic Space" ),
+ uint32("dyn_mem_struct_cur", "Current Used Dynamic Space" ),
+], "Dynamic Memory Information")
+EAInfoStruct = struct("ea_info_struct", [
+ EADataSize,
+ EACount,
+ EAKeySize,
+], "Extended Attribute Information")
+ExtraCacheCntrs = struct("extra_cache_cntrs", [
+ uint32("internl_dsk_get_no_wait", "Internal Disk Get No Wait Count"),
+ uint32("internl_dsk_get_no_wait_need", "Internal Disk Get No Wait Need To Allocate Count"),
+ uint32("internl_dsk_get_no_wait_no_blk", "Internal Disk Get No Wait No Block Count"),
+ uint32("id_get_no_read_no_wait", "ID Get No Read No Wait Count"),
+ uint32("id_get_no_read_no_wait_sema", "ID Get No Read No Wait Semaphored Count"),
+ uint32("id_get_no_read_no_wait_buffer", "ID Get No Read No Wait No Buffer Count"),
+ uint32("id_get_no_read_no_wait_alloc", "ID Get No Read No Wait Allocate Count"),
+ uint32("id_get_no_read_no_wait_no_alloc", "ID Get No Read No Wait No Alloc Count"),
+ uint32("id_get_no_read_no_wait_no_alloc_sema", "ID Get No Read No Wait No Alloc Semaphored Count"),
+ uint32("id_get_no_read_no_wait_no_alloc_alloc", "ID Get No Read No Wait No Alloc Allocate Count"),
+], "Extra Cache Counters Information")
+
+
+ReferenceIDStruct = struct("ref_id_struct", [
+ CurrentReferenceID,
+])
+NSAttributeStruct = struct("ns_attrib_struct", [
+ AttributesDef32,
+])
+DStreamActual = struct("d_stream_actual", [
+ Reserved12,
+ # Need to look into how to format this correctly
+])
+DStreamLogical = struct("d_string_logical", [
+ Reserved12,
+ # Need to look into how to format this correctly
+])
+LastUpdatedInSecondsStruct = struct("last_update_in_seconds_struct", [
+ SecondsRelativeToTheYear2000,
+])
+DOSNameStruct = struct("dos_name_struct", [
+ FileName,
+], "DOS File Name")
+FlushTimeStruct = struct("flush_time_struct", [
+ FlushTime,
+])
+ParentBaseIDStruct = struct("parent_base_id_struct", [
+ ParentBaseID,
+])
+MacFinderInfoStruct = struct("mac_finder_info_struct", [
+ MacFinderInfo,
+])
+SiblingCountStruct = struct("sibling_count_struct", [
+ SiblingCount,
+])
+EffectiveRightsStruct = struct("eff_rights_struct", [
+ EffectiveRights,
+ Reserved3,
+])
+MacTimeStruct = struct("mac_time_struct", [
+ MACCreateDate,
+ MACCreateTime,
+ MACBackupDate,
+ MACBackupTime,
+])
+LastAccessedTimeStruct = struct("last_access_time_struct", [
+ LastAccessedTime,
+])
+
+
+
+FileAttributesStruct = struct("file_attributes_struct", [
+ AttributesDef32,
+])
+FileInfoStruct = struct("file_info_struct", [
+ ParentID,
+ DirectoryEntryNumber,
+ TotalBlocksToDecompress,
+ CurrentBlockBeingDecompressed,
+], "File Information")
+FileInstance = struct("file_instance", [
+ SearchSequenceWord,
+ DirectoryID,
+ FileName14,
+ AttributesDef,
+ FileMode,
+ FileSize,
+ endian(CreationDate, BE),
+ endian(AccessDate, BE),
+ endian(UpdateDate, BE),
+ endian(UpdateTime, BE),
+], "File Instance")
+FileNameStruct = struct("file_name_struct", [
+ FileName,
+], "File Name")
+FileServerCounters = struct("file_server_counters", [
+ uint16("too_many_hops", "Too Many Hops"),
+ uint16("unknown_network", "Unknown Network"),
+ uint16("no_space_for_service", "No Space For Service"),
+ uint16("no_receive_buff", "No Receive Buffers"),
+ uint16("not_my_network", "Not My Network"),
+ uint32("netbios_progated", "NetBIOS Propagated Count"),
+ uint32("ttl_pckts_srvcd", "Total Packets Serviced"),
+ uint32("ttl_pckts_routed", "Total Packets Routed"),
+], "File Server Counters")
+FileSystemInfo = struct("file_system_info", [
+ uint32("fat_moved", "Number of times the OS has move the location of FAT"),
+ uint32("fat_write_err", "Number of write errors in both original and mirrored copies of FAT"),
+ uint32("someone_else_did_it_0", "Someone Else Did It Count 0"),
+ uint32("someone_else_did_it_1", "Someone Else Did It Count 1"),
+ uint32("someone_else_did_it_2", "Someone Else Did It Count 2"),
+ uint32("i_ran_out_someone_else_did_it_0", "I Ran Out Someone Else Did It Count 0"),
+ uint32("i_ran_out_someone_else_did_it_1", "I Ran Out Someone Else Did It Count 1"),
+ uint32("i_ran_out_someone_else_did_it_2", "I Ran Out Someone Else Did It Count 2"),
+ uint32("turbo_fat_build_failed", "Turbo FAT Build Failed Count"),
+ uint32("extra_use_count_node_count", "Errors allocating a use count node for TTS"),
+ uint32("extra_extra_use_count_node_count", "Errors allocating an additional use count node for TTS"),
+ uint32("error_read_last_fat", "Error Reading Last FAT Count"),
+ uint32("someone_else_using_this_file", "Someone Else Using This File Count"),
+], "File System Information")
+GenericInfoDef = struct("generic_info_def", [
+ fw_string("generic_label", "Label", 64),
+ uint32("generic_ident_type", "Identification Type"),
+ uint32("generic_ident_time", "Identification Time"),
+ uint32("generic_media_type", "Media Type"),
+ uint32("generic_cartridge_type", "Cartridge Type"),
+ uint32("generic_unit_size", "Unit Size"),
+ uint32("generic_block_size", "Block Size"),
+ uint32("generic_capacity", "Capacity"),
+ uint32("generic_pref_unit_size", "Preferred Unit Size"),
+ fw_string("generic_name", "Name",64),
+ uint32("generic_type", "Type"),
+ uint32("generic_status", "Status"),
+ uint32("generic_func_mask", "Function Mask"),
+ uint32("generic_ctl_mask", "Control Mask"),
+ uint32("generic_parent_count", "Parent Count"),
+ uint32("generic_sib_count", "Sibling Count"),
+ uint32("generic_child_count", "Child Count"),
+ uint32("generic_spec_info_sz", "Specific Information Size"),
+ uint32("generic_object_uniq_id", "Unique Object ID"),
+ uint32("generic_media_slot", "Media Slot"),
+], "Generic Information")
+HandleInfoLevel0 = struct("handle_info_level_0", [
+# DataStream,
+])
+HandleInfoLevel1 = struct("handle_info_level_1", [
+ DataStream,
+])
+HandleInfoLevel2 = struct("handle_info_level_2", [
+ DOSDirectoryBase,
+ NameSpace,
+ DataStream,
+])
+HandleInfoLevel3 = struct("handle_info_level_3", [
+ DOSDirectoryBase,
+ NameSpace,
+])
+HandleInfoLevel4 = struct("handle_info_level_4", [
+ DOSDirectoryBase,
+ NameSpace,
+ ParentDirectoryBase,
+ ParentDOSDirectoryBase,
+])
+HandleInfoLevel5 = struct("handle_info_level_5", [
+ DOSDirectoryBase,
+ NameSpace,
+ DataStream,
+ ParentDirectoryBase,
+ ParentDOSDirectoryBase,
+])
+IPXInformation = struct("ipx_information", [
+ uint32("ipx_send_pkt", "IPX Send Packet Count"),
+ uint16("ipx_malform_pkt", "IPX Malformed Packet Count"),
+ uint32("ipx_get_ecb_req", "IPX Get ECB Request Count"),
+ uint32("ipx_get_ecb_fail", "IPX Get ECB Fail Count"),
+ uint32("ipx_aes_event", "IPX AES Event Count"),
+ uint16("ipx_postponed_aes", "IPX Postponed AES Count"),
+ uint16("ipx_max_conf_sock", "IPX Max Configured Socket Count"),
+ uint16("ipx_max_open_sock", "IPX Max Open Socket Count"),
+ uint16("ipx_open_sock_fail", "IPX Open Socket Fail Count"),
+ uint32("ipx_listen_ecb", "IPX Listen ECB Count"),
+ uint16("ipx_ecb_cancel_fail", "IPX ECB Cancel Fail Count"),
+ uint16("ipx_get_lcl_targ_fail", "IPX Get Local Target Fail Count"),
+], "IPX Information")
+JobEntryTime = struct("job_entry_time", [
+ Year,
+ Month,
+ Day,
+ Hour,
+ Minute,
+ Second,
+], "Job Entry Time")
+JobStruct3x = struct("job_struct_3x", [
+ RecordInUseFlag,
+ PreviousRecord,
+ NextRecord,
+ ClientStationLong,
+ ClientTaskNumberLong,
+ ClientIDNumber,
+ TargetServerIDNumber,
+ TargetExecutionTime,
+ JobEntryTime,
+ JobNumberLong,
+ JobType,
+ JobPositionWord,
+ JobControlFlagsWord,
+ JobFileName,
+ JobFileHandleLong,
+ ServerStationLong,
+ ServerTaskNumberLong,
+ ServerID,
+ TextJobDescription,
+ ClientRecordArea,
+], "Job Information")
+JobStruct = struct("job_struct", [
+ ClientStation,
+ ClientTaskNumber,
+ ClientIDNumber,
+ TargetServerIDNumber,
+ TargetExecutionTime,
+ JobEntryTime,
+ JobNumber,
+ JobType,
+ JobPosition,
+ JobControlFlags,
+ JobFileName,
+ JobFileHandle,
+ ServerStation,
+ ServerTaskNumber,
+ ServerID,
+ TextJobDescription,
+ ClientRecordArea,
+], "Job Information")
+JobStructNew = struct("job_struct_new", [
+ RecordInUseFlag,
+ PreviousRecord,
+ NextRecord,
+ ClientStationLong,
+ ClientTaskNumberLong,
+ ClientIDNumber,
+ TargetServerIDNumber,
+ TargetExecutionTime,
+ JobEntryTime,
+ JobNumberLong,
+ JobType,
+ JobPositionWord,
+ JobControlFlagsWord,
+ JobFileName,
+ JobFileHandleLong,
+ ServerStationLong,
+ ServerTaskNumberLong,
+ ServerID,
+], "Job Information")
+KnownRoutes = struct("known_routes", [
+ NetIDNumber,
+ HopsToNet,
+ NetStatus,
+ TimeToNet,
+], "Known Routes")
+KnownServStruc = struct("known_server_struct", [
+ ServerAddress,
+ HopsToNet,
+ ServerNameStringz,
+], "Known Servers")
+LANConfigInfo = struct("lan_cfg_info", [
+ LANdriverCFG_MajorVersion,
+ LANdriverCFG_MinorVersion,
+ LANdriverNodeAddress,
+ Reserved,
+ LANdriverModeFlags,
+ LANdriverBoardNumber,
+ LANdriverBoardInstance,
+ LANdriverMaximumSize,
+ LANdriverMaxRecvSize,
+ LANdriverRecvSize,
+ LANdriverCardID,
+ LANdriverMediaID,
+ LANdriverTransportTime,
+ LANdriverSrcRouting,
+ LANdriverLineSpeed,
+ LANdriverReserved,
+ LANdriverMajorVersion,
+ LANdriverMinorVersion,
+ LANdriverFlags,
+ LANdriverSendRetries,
+ LANdriverLink,
+ LANdriverSharingFlags,
+ LANdriverSlot,
+ LANdriverIOPortsAndRanges1,
+ LANdriverIOPortsAndRanges2,
+ LANdriverIOPortsAndRanges3,
+ LANdriverIOPortsAndRanges4,
+ LANdriverMemoryDecode0,
+ LANdriverMemoryLength0,
+ LANdriverMemoryDecode1,
+ LANdriverMemoryLength1,
+ LANdriverInterrupt1,
+ LANdriverInterrupt2,
+ LANdriverDMAUsage1,
+ LANdriverDMAUsage2,
+ LANdriverLogicalName,
+ LANdriverIOReserved,
+ LANdriverCardName,
+], "LAN Configuration Information")
+LastAccessStruct = struct("last_access_struct", [
+ LastAccessedDate,
+])
+lockInfo = struct("lock_info_struct", [
+ LogicalLockThreshold,
+ PhysicalLockThreshold,
+ FileLockCount,
+ RecordLockCount,
+], "Lock Information")
+LockStruct = struct("lock_struct", [
+ TaskNumByte,
+ LockType,
+ RecordStart,
+ RecordEnd,
+], "Locks")
+LoginTime = struct("login_time", [
+ Year,
+ Month,
+ Day,
+ Hour,
+ Minute,
+ Second,
+ DayOfWeek,
+], "Login Time")
+LogLockStruct = struct("log_lock_struct", [
+ TaskNumByte,
+ LockStatus,
+ LockName,
+], "Logical Locks")
+LogRecStruct = struct("log_rec_struct", [
+ ConnectionNumberWord,
+ TaskNumByte,
+ LockStatus,
+], "Logical Record Locks")
+LSLInformation = struct("lsl_information", [
+ uint32("rx_buffers", "Receive Buffers"),
+ uint32("rx_buffers_75", "Receive Buffers Warning Level"),
+ uint32("rx_buffers_checked_out", "Receive Buffers Checked Out Count"),
+ uint32("rx_buffer_size", "Receive Buffer Size"),
+ uint32("max_phy_packet_size", "Maximum Physical Packet Size"),
+ uint32("last_time_rx_buff_was_alloc", "Last Time a Receive Buffer was Allocated"),
+ uint32("max_num_of_protocols", "Maximum Number of Protocols"),
+ uint32("max_num_of_media_types", "Maximum Number of Media Types"),
+ uint32("total_tx_packets", "Total Transmit Packets"),
+ uint32("get_ecb_buf", "Get ECB Buffers"),
+ uint32("get_ecb_fails", "Get ECB Failures"),
+ uint32("aes_event_count", "AES Event Count"),
+ uint32("post_poned_events", "Postponed Events"),
+ uint32("ecb_cxl_fails", "ECB Cancel Failures"),
+ uint32("valid_bfrs_reused", "Valid Buffers Reused"),
+ uint32("enqueued_send_cnt", "Enqueued Send Count"),
+ uint32("total_rx_packets", "Total Receive Packets"),
+ uint32("unclaimed_packets", "Unclaimed Packets"),
+ uint8("stat_table_major_version", "Statistics Table Major Version"),
+ uint8("stat_table_minor_version", "Statistics Table Minor Version"),
+], "LSL Information")
+MaximumSpaceStruct = struct("max_space_struct", [
+ MaxSpace,
+])
+MemoryCounters = struct("memory_counters", [
+ uint32("orig_num_cache_buff", "Original Number Of Cache Buffers"),
+ uint32("curr_num_cache_buff", "Current Number Of Cache Buffers"),
+ uint32("cache_dirty_block_thresh", "Cache Dirty Block Threshold"),
+ uint32("wait_node", "Wait Node Count"),
+ uint32("wait_node_alloc_fail", "Wait Node Alloc Failure Count"),
+ uint32("move_cache_node", "Move Cache Node Count"),
+ uint32("move_cache_node_from_avai", "Move Cache Node From Avail Count"),
+ uint32("accel_cache_node_write", "Accelerate Cache Node Write Count"),
+ uint32("rem_cache_node", "Remove Cache Node Count"),
+ uint32("rem_cache_node_from_avail", "Remove Cache Node From Avail Count"),
+], "Memory Counters")
+MLIDBoardInfo = struct("mlid_board_info", [
+ uint32("protocol_board_num", "Protocol Board Number"),
+ uint16("protocol_number", "Protocol Number"),
+ bytes("protocol_id", "Protocol ID", 6),
+ nstring8("protocol_name", "Protocol Name"),
+], "MLID Board Information")
+ModifyInfoStruct = struct("modify_info_struct", [
+ ModifiedTime,
+ ModifiedDate,
+ ModifierID,
+ LastAccessedDate,
+], "Modification Information")
+nameInfo = struct("name_info_struct", [
+ ObjectType,
+ nstring8("login_name", "Login Name"),
+], "Name Information")
+NCPNetworkAddress = struct("ncp_network_address_struct", [
+ TransportType,
+ Reserved3,
+ NetAddress,
+], "Network Address")
+
+netAddr = struct("net_addr_struct", [
+ TransportType,
+ nbytes32("transport_addr", "Transport Address"),
+], "Network Address")
+
+NetWareInformationStruct = struct("netware_information_struct", [
+ DataStreamSpaceAlloc, # (Data Stream Alloc Bit)
+ AttributesDef32, # (Attributes Bit)
+ FlagsDef,
+ DataStreamSize, # (Data Stream Size Bit)
+ TotalDataStreamDiskSpaceAlloc, # (Total Stream Size Bit)
+ NumberOfDataStreams,
+ CreationTime, # (Creation Bit)
+ CreationDate,
+ CreatorID,
+ ModifiedTime, # (Modify Bit)
+ ModifiedDate,
+ ModifierID,
+ LastAccessedDate,
+ ArchivedTime, # (Archive Bit)
+ ArchivedDate,
+ ArchiverID,
+ InheritedRightsMask, # (Rights Bit)
+ DirectoryEntryNumber, # (Directory Entry Bit)
+ DOSDirectoryEntryNumber,
+ VolumeNumberLong,
+ EADataSize, # (Extended Attribute Bit)
+ EACount,
+ EAKeySize,
+ CreatorNameSpaceNumber, # (Name Space Bit)
+ Reserved3,
+], "NetWare Information")
+NLMInformation = struct("nlm_information", [
+ IdentificationNumber,
+ NLMFlags,
+ Reserved3,
+ NLMType,
+ Reserved3,
+ ParentID,
+ MajorVersion,
+ MinorVersion,
+ Revision,
+ Year,
+ Reserved3,
+ Month,
+ Reserved3,
+ Day,
+ Reserved3,
+ AllocAvailByte,
+ AllocFreeCount,
+ LastGarbCollect,
+ MessageLanguage,
+ NumberOfReferencedPublics,
+], "NLM Information")
+NSInfoStruct = struct("ns_info_struct", [
+ NameSpace,
+ Reserved3,
+])
+NWAuditStatus = struct("nw_audit_status", [
+ AuditVersionDate,
+ AuditFileVersionDate,
+ val_string16("audit_enable_flag", "Auditing Enabled Flag", [
+ [ 0x0000, "Auditing Disabled" ],
+ [ 0x0100, "Auditing Enabled" ],
+ ]),
+ Reserved2,
+ uint32("audit_file_size", "Audit File Size"),
+ uint32("modified_counter", "Modified Counter"),
+ uint32("audit_file_max_size", "Audit File Maximum Size"),
+ uint32("audit_file_size_threshold", "Audit File Size Threshold"),
+ uint32("audit_record_count", "Audit Record Count"),
+ uint32("auditing_flags", "Auditing Flags"),
+], "NetWare Audit Status")
+ObjectSecurityStruct = struct("object_security_struct", [
+ ObjectSecurity,
+])
+ObjectFlagsStruct = struct("object_flags_struct", [
+ ObjectFlags,
+])
+ObjectTypeStruct = struct("object_type_struct", [
+ ObjectType,
+ Reserved2,
+])
+ObjectNameStruct = struct("object_name_struct", [
+ ObjectNameStringz,
+])
+ObjectIDStruct = struct("object_id_struct", [
+ ObjectID,
+ Restriction,
+])
+OpnFilesStruct = struct("opn_files_struct", [
+ TaskNumberWord,
+ LockType,
+ AccessControl,
+ LockFlag,
+ VolumeNumber,
+ DOSParentDirectoryEntry,
+ DOSDirectoryEntry,
+ ForkCount,
+ NameSpace,
+ FileName,
+], "Open Files Information")
+OwnerIDStruct = struct("owner_id_struct", [
+ CreatorID,
+])
+PacketBurstInformation = struct("packet_burst_information", [
+ uint32("big_invalid_slot", "Big Invalid Slot Count"),
+ uint32("big_forged_packet", "Big Forged Packet Count"),
+ uint32("big_invalid_packet", "Big Invalid Packet Count"),
+ uint32("big_still_transmitting", "Big Still Transmitting Count"),
+ uint32("still_doing_the_last_req", "Still Doing The Last Request Count"),
+ uint32("invalid_control_req", "Invalid Control Request Count"),
+ uint32("control_invalid_message_number", "Control Invalid Message Number Count"),
+ uint32("control_being_torn_down", "Control Being Torn Down Count"),
+ uint32("big_repeat_the_file_read", "Big Repeat the File Read Count"),
+ uint32("big_send_extra_cc_count", "Big Send Extra CC Count"),
+ uint32("big_return_abort_mess", "Big Return Abort Message Count"),
+ uint32("big_read_invalid_mess", "Big Read Invalid Message Number Count"),
+ uint32("big_read_do_it_over", "Big Read Do It Over Count"),
+ uint32("big_read_being_torn_down", "Big Read Being Torn Down Count"),
+ uint32("previous_control_packet", "Previous Control Packet Count"),
+ uint32("send_hold_off_message", "Send Hold Off Message Count"),
+ uint32("big_read_no_data_avail", "Big Read No Data Available Count"),
+ uint32("big_read_trying_to_read", "Big Read Trying To Read Too Much Count"),
+ uint32("async_read_error", "Async Read Error Count"),
+ uint32("big_read_phy_read_err", "Big Read Physical Read Error Count"),
+ uint32("ctl_bad_ack_frag_list", "Control Bad ACK Fragment List Count"),
+ uint32("ctl_no_data_read", "Control No Data Read Count"),
+ uint32("write_dup_req", "Write Duplicate Request Count"),
+ uint32("shouldnt_be_ack_here", "Shouldn't Be ACKing Here Count"),
+ uint32("write_incon_packet_len", "Write Inconsistent Packet Lengths Count"),
+ uint32("first_packet_isnt_a_write", "First Packet Isn't A Write Count"),
+ uint32("write_trash_dup_req", "Write Trashed Duplicate Request Count"),
+ uint32("big_write_inv_message_num", "Big Write Invalid Message Number Count"),
+ uint32("big_write_being_torn_down", "Big Write Being Torn Down Count"),
+ uint32("big_write_being_abort", "Big Write Being Aborted Count"),
+ uint32("zero_ack_frag", "Zero ACK Fragment Count"),
+ uint32("write_curr_trans", "Write Currently Transmitting Count"),
+ uint32("try_to_write_too_much", "Trying To Write Too Much Count"),
+ uint32("write_out_of_mem_for_ctl_nodes", "Write Out Of Memory For Control Nodes Count"),
+ uint32("write_didnt_need_this_frag", "Write Didn't Need This Fragment Count"),
+ uint32("write_too_many_buf_check", "Write Too Many Buffers Checked Out Count"),
+ uint32("write_timeout", "Write Time Out Count"),
+ uint32("write_got_an_ack0", "Write Got An ACK Count 0"),
+ uint32("write_got_an_ack1", "Write Got An ACK Count 1"),
+ uint32("poll_abort_conn", "Poller Aborted The Connnection Count"),
+ uint32("may_had_out_of_order", "Maybe Had Out Of Order Writes Count"),
+ uint32("had_an_out_of_order", "Had An Out Of Order Write Count"),
+ uint32("moved_the_ack_bit_dn", "Moved The ACK Bit Down Count"),
+ uint32("bumped_out_of_order", "Bumped Out Of Order Write Count"),
+ uint32("poll_rem_old_out_of_order", "Poller Removed Old Out Of Order Count"),
+ uint32("write_didnt_need_but_req_ack", "Write Didn't Need But Requested ACK Count"),
+ uint32("write_trash_packet", "Write Trashed Packet Count"),
+ uint32("too_many_ack_frag", "Too Many ACK Fragments Count"),
+ uint32("saved_an_out_of_order_packet", "Saved An Out Of Order Packet Count"),
+ uint32("conn_being_aborted", "Connection Being Aborted Count"),
+], "Packet Burst Information")
+
+PadDSSpaceAllocate = struct("pad_ds_space_alloc", [
+ Reserved4,
+])
+PadAttributes = struct("pad_attributes", [
+ Reserved6,
+])
+PadDataStreamSize = struct("pad_data_stream_size", [
+ Reserved4,
+])
+PadTotalStreamSize = struct("pad_total_stream_size", [
+ Reserved6,
+])
+PadCreationInfo = struct("pad_creation_info", [
+ Reserved8,
+])
+PadModifyInfo = struct("pad_modify_info", [
+ Reserved10,
+])
+PadArchiveInfo = struct("pad_archive_info", [
+ Reserved8,
+])
+PadRightsInfo = struct("pad_rights_info", [
+ Reserved2,
+])
+PadDirEntry = struct("pad_dir_entry", [
+ Reserved12,
+])
+PadEAInfo = struct("pad_ea_info", [
+ Reserved12,
+])
+PadNSInfo = struct("pad_ns_info", [
+ Reserved4,
+])
+PhyLockStruct = struct("phy_lock_struct", [
+ LoggedCount,
+ ShareableLockCount,
+ RecordStart,
+ RecordEnd,
+ LogicalConnectionNumber,
+ TaskNumByte,
+ LockType,
+], "Physical Locks")
+printInfo = struct("print_info_struct", [
+ PrintFlags,
+ TabSize,
+ Copies,
+ PrintToFileFlag,
+ BannerName,
+ TargetPrinter,
+ FormType,
+], "Print Information")
+RightsInfoStruct = struct("rights_info_struct", [
+ InheritedRightsMask,
+])
+RoutersInfo = struct("routers_info", [
+ bytes("node", "Node", 6),
+ ConnectedLAN,
+ uint16("route_hops", "Hop Count"),
+ uint16("route_time", "Route Time"),
+], "Router Information")
+RTagStructure = struct("r_tag_struct", [
+ RTagNumber,
+ ResourceSignature,
+ ResourceCount,
+ ResourceName,
+], "Resource Tag")
+ScanInfoFileName = struct("scan_info_file_name", [
+ SalvageableFileEntryNumber,
+ FileName,
+])
+ScanInfoFileNoName = struct("scan_info_file_no_name", [
+ SalvageableFileEntryNumber,
+])
+Segments = struct("segments", [
+ uint32("volume_segment_dev_num", "Volume Segment Device Number"),
+ uint32("volume_segment_offset", "Volume Segment Offset"),
+ uint32("volume_segment_size", "Volume Segment Size"),
+], "Volume Segment Information")
+SemaInfoStruct = struct("sema_info_struct", [
+ LogicalConnectionNumber,
+ TaskNumByte,
+])
+SemaStruct = struct("sema_struct", [
+ OpenCount,
+ SemaphoreValue,
+ TaskNumByte,
+ SemaphoreName,
+], "Semaphore Information")
+ServerInfo = struct("server_info", [
+ uint32("reply_canceled", "Reply Canceled Count"),
+ uint32("write_held_off", "Write Held Off Count"),
+ uint32("write_held_off_with_dup", "Write Held Off With Duplicate Request"),
+ uint32("invalid_req_type", "Invalid Request Type Count"),
+ uint32("being_aborted", "Being Aborted Count"),
+ uint32("already_doing_realloc", "Already Doing Re-Allocate Count"),
+ uint32("dealloc_invalid_slot", "De-Allocate Invalid Slot Count"),
+ uint32("dealloc_being_proc", "De-Allocate Being Processed Count"),
+ uint32("dealloc_forged_packet", "De-Allocate Forged Packet Count"),
+ uint32("dealloc_still_transmit", "De-Allocate Still Transmitting Count"),
+ uint32("start_station_error", "Start Station Error Count"),
+ uint32("invalid_slot", "Invalid Slot Count"),
+ uint32("being_processed", "Being Processed Count"),
+ uint32("forged_packet", "Forged Packet Count"),
+ uint32("still_transmitting", "Still Transmitting Count"),
+ uint32("reexecute_request", "Re-Execute Request Count"),
+ uint32("invalid_sequence_number", "Invalid Sequence Number Count"),
+ uint32("dup_is_being_sent", "Duplicate Is Being Sent Already Count"),
+ uint32("sent_pos_ack", "Sent Positive Acknowledge Count"),
+ uint32("sent_a_dup_reply", "Sent A Duplicate Reply Count"),
+ uint32("no_mem_for_station", "No Memory For Station Control Count"),
+ uint32("no_avail_conns", "No Available Connections Count"),
+ uint32("realloc_slot", "Re-Allocate Slot Count"),
+ uint32("realloc_slot_came_too_soon", "Re-Allocate Slot Came Too Soon Count"),
+], "Server Information")
+ServersSrcInfo = struct("servers_src_info", [
+ ServerNode,
+ ConnectedLAN,
+ HopsToNet,
+], "Source Server Information")
+SpaceStruct = struct("space_struct", [
+ Level,
+ MaxSpace,
+ CurrentSpace,
+], "Space Information")
+SPXInformation = struct("spx_information", [
+ uint16("spx_max_conn", "SPX Max Connections Count"),
+ uint16("spx_max_used_conn", "SPX Max Used Connections"),
+ uint16("spx_est_conn_req", "SPX Establish Connection Requests"),
+ uint16("spx_est_conn_fail", "SPX Establish Connection Fail"),
+ uint16("spx_listen_con_req", "SPX Listen Connect Request"),
+ uint16("spx_listen_con_fail", "SPX Listen Connect Fail"),
+ uint32("spx_send", "SPX Send Count"),
+ uint32("spx_window_choke", "SPX Window Choke Count"),
+ uint16("spx_bad_send", "SPX Bad Send Count"),
+ uint16("spx_send_fail", "SPX Send Fail Count"),
+ uint16("spx_abort_conn", "SPX Aborted Connection"),
+ uint32("spx_listen_pkt", "SPX Listen Packet Count"),
+ uint16("spx_bad_listen", "SPX Bad Listen Count"),
+ uint32("spx_incoming_pkt", "SPX Incoming Packet Count"),
+ uint16("spx_bad_in_pkt", "SPX Bad In Packet Count"),
+ uint16("spx_supp_pkt", "SPX Suppressed Packet Count"),
+ uint16("spx_no_ses_listen", "SPX No Session Listen ECB Count"),
+ uint16("spx_watch_dog", "SPX Watch Dog Destination Session Count"),
+], "SPX Information")
+StackInfo = struct("stack_info", [
+ StackNumber,
+ fw_string("stack_short_name", "Stack Short Name", 16),
+], "Stack Information")
+statsInfo = struct("stats_info_struct", [
+ TotalBytesRead,
+ TotalBytesWritten,
+ TotalRequest,
+], "Statistics")
+theTimeStruct = struct("the_time_struct", [
+ UTCTimeInSeconds,
+ FractionalSeconds,
+ TimesyncStatus,
+])
+timeInfo = struct("time_info", [
+ Year,
+ Month,
+ Day,
+ Hour,
+ Minute,
+ Second,
+ DayOfWeek,
+ uint32("login_expiration_time", "Login Expiration Time"),
+])
+TotalStreamSizeStruct = struct("total_stream_size_struct", [
+ TotalDataStreamDiskSpaceAlloc,
+ NumberOfDataStreams,
+])
+TrendCounters = struct("trend_counters", [
+ uint32("num_of_cache_checks", "Number Of Cache Checks"),
+ uint32("num_of_cache_hits", "Number Of Cache Hits"),
+ uint32("num_of_dirty_cache_checks", "Number Of Dirty Cache Checks"),
+ uint32("num_of_cache_dirty_checks", "Number Of Cache Dirty Checks"),
+ uint32("cache_used_while_check", "Cache Used While Checking"),
+ uint32("wait_till_dirty_blcks_dec", "Wait Till Dirty Blocks Decrease Count"),
+ uint32("alloc_blck_frm_avail", "Allocate Block From Available Count"),
+ uint32("alloc_blck_frm_lru", "Allocate Block From LRU Count"),
+ uint32("alloc_blck_already_wait", "Allocate Block Already Waiting"),
+ uint32("lru_sit_time", "LRU Sitting Time"),
+ uint32("num_of_cache_check_no_wait", "Number Of Cache Check No Wait"),
+ uint32("num_of_cache_hits_no_wait", "Number Of Cache Hits No Wait"),
+], "Trend Counters")
+TrusteeStruct = struct("trustee_struct", [
+ endian(ObjectID, LE),
+ AccessRightsMaskWord,
+])
+UpdateDateStruct = struct("update_date_struct", [
+ UpdateDate,
+])
+UpdateIDStruct = struct("update_id_struct", [
+ UpdateID,
+])
+UpdateTimeStruct = struct("update_time_struct", [
+ UpdateTime,
+])
+UserInformation = struct("user_info", [
+ ConnectionNumber,
+ UseCount,
+ Reserved2,
+ ConnectionServiceType,
+ Year,
+ Month,
+ Day,
+ Hour,
+ Minute,
+ Second,
+ DayOfWeek,
+ Status,
+ Reserved2,
+ ExpirationTime,
+ ObjectType,
+ Reserved2,
+ TransactionTrackingFlag,
+ LogicalLockThreshold,
+ FileWriteFlags,
+ FileWriteState,
+ Reserved,
+ FileLockCount,
+ RecordLockCount,
+ TotalBytesRead,
+ TotalBytesWritten,
+ TotalRequest,
+ HeldRequests,
+ HeldBytesRead,
+ HeldBytesWritten,
+], "User Information")
+VolInfoStructure = struct("vol_info_struct", [
+ VolumeType,
+ Reserved2,
+ StatusFlagBits,
+ SectorSize,
+ SectorsPerClusterLong,
+ VolumeSizeInClusters,
+ FreedClusters,
+ SubAllocFreeableClusters,
+ FreeableLimboSectors,
+ NonFreeableLimboSectors,
+ NonFreeableAvailableSubAllocSectors,
+ NotUsableSubAllocSectors,
+ SubAllocClusters,
+ DataStreamsCount,
+ LimboDataStreamsCount,
+ OldestDeletedFileAgeInTicks,
+ CompressedDataStreamsCount,
+ CompressedLimboDataStreamsCount,
+ UnCompressableDataStreamsCount,
+ PreCompressedSectors,
+ CompressedSectors,
+ MigratedFiles,
+ MigratedSectors,
+ ClustersUsedByFAT,
+ ClustersUsedByDirectories,
+ ClustersUsedByExtendedDirectories,
+ TotalDirectoryEntries,
+ UnUsedDirectoryEntries,
+ TotalExtendedDirectoryExtants,
+ UnUsedExtendedDirectoryExtants,
+ ExtendedAttributesDefined,
+ ExtendedAttributeExtantsUsed,
+ DirectoryServicesObjectID,
+ VolumeLastModifiedTime,
+ VolumeLastModifiedDate,
+], "Volume Information")
+VolInfo2Struct = struct("vol_info_struct_2", [
+ uint32("volume_active_count", "Volume Active Count"),
+ uint32("volume_use_count", "Volume Use Count"),
+ uint32("mac_root_ids", "MAC Root IDs"),
+ VolumeLastModifiedTime,
+ VolumeLastModifiedDate,
+ uint32("volume_reference_count", "Volume Reference Count"),
+ uint32("compression_lower_limit", "Compression Lower Limit"),
+ uint32("outstanding_ios", "Outstanding IOs"),
+ uint32("outstanding_compression_ios", "Outstanding Compression IOs"),
+ uint32("compression_ios_limit", "Compression IOs Limit"),
+], "Extended Volume Information")
+VolumeStruct = struct("volume_struct", [
+ VolumeNumberLong,
+ VolumeNameLen,
+])
+
+
+##############################################################################
+# NCP Groups
+##############################################################################
+def define_groups():
+ groups['accounting'] = "Accounting"
+ groups['afp'] = "AFP"
+ groups['auditing'] = "Auditing"
+ groups['bindery'] = "Bindery"
+ groups['comm'] = "Communication"
+ groups['connection'] = "Connection"
+ groups['directory'] = "Directory"
+ groups['extended'] = "Extended Attribute"
+ groups['file'] = "File"
+ groups['fileserver'] = "File Server"
+ groups['message'] = "Message"
+ groups['migration'] = "Data Migration"
+ groups['misc'] = "Miscellaneous"
+ groups['name'] = "Name Space"
+ groups['nds'] = "NetWare Directory"
+ groups['print'] = "Print"
+ groups['queue'] = "Queue"
+ groups['sync'] = "Synchronization"
+ groups['tts'] = "Transaction Tracking"
+ groups['qms'] = "Queue Management System (QMS)"
+ groups['stats'] = "Server Statistics"
+ groups['nmas'] = "Novell Modular Authentication Service"
+ groups['sss'] = "SecretStore Services"
+ groups['unknown'] = "Unknown"
+
+##############################################################################
+# NCP Errors
+##############################################################################
+def define_errors():
+ errors[0x0000] = "Ok"
+ errors[0x0001] = "Transaction tracking is available"
+ errors[0x0002] = "Ok. The data has been written"
+ errors[0x0003] = "Calling Station is a Manager"
+
+ errors[0x0100] = "One or more of the Connection Numbers in the send list are invalid"
+ errors[0x0101] = "Invalid space limit"
+ errors[0x0102] = "Insufficient disk space"
+ errors[0x0103] = "Queue server cannot add jobs"
+ errors[0x0104] = "Out of disk space"
+ errors[0x0105] = "Semaphore overflow"
+ errors[0x0106] = "Invalid Parameter"
+ errors[0x0107] = "Invalid Number of Minutes to Delay"
+ errors[0x0108] = "Invalid Start or Network Number"
+ errors[0x0109] = "Cannot Obtain License"
+
+ errors[0x0200] = "One or more clients in the send list are not logged in"
+ errors[0x0201] = "Queue server cannot attach"
+
+ errors[0x0300] = "One or more clients in the send list are not accepting messages"
+
+ errors[0x0400] = "Client already has message"
+ errors[0x0401] = "Queue server cannot service job"
+
+ errors[0x7300] = "Revoke Handle Rights Not Found"
+ errors[0x7900] = "Invalid Parameter in Request Packet"
+ errors[0x7901] = "Nothing being Compressed"
+ errors[0x7a00] = "Connection Already Temporary"
+ errors[0x7b00] = "Connection Already Logged in"
+ errors[0x7c00] = "Connection Not Authenticated"
+
+ errors[0x7e00] = "NCP failed boundary check"
+ errors[0x7e01] = "Invalid Length"
+
+ errors[0x7f00] = "Lock Waiting"
+ errors[0x8000] = "Lock fail"
+ errors[0x8001] = "File in Use"
+
+ errors[0x8100] = "A file handle could not be allocated by the file server"
+ errors[0x8101] = "Out of File Handles"
+
+ errors[0x8200] = "Unauthorized to open the file"
+ errors[0x8300] = "Unable to read/write the volume. Possible bad sector on the file server"
+ errors[0x8301] = "Hard I/O Error"
+
+ errors[0x8400] = "Unauthorized to create the directory"
+ errors[0x8401] = "Unauthorized to create the file"
+
+ errors[0x8500] = "Unauthorized to delete the specified file"
+ errors[0x8501] = "Unauthorized to overwrite an existing file in this directory"
+
+ errors[0x8700] = "An unexpected character was encountered in the filename"
+ errors[0x8701] = "Create Filename Error"
+
+ errors[0x8800] = "Invalid file handle"
+ errors[0x8900] = "Unauthorized to search this file/directory"
+ errors[0x8a00] = "Unauthorized to delete this file/directory"
+ errors[0x8b00] = "Unauthorized to rename a file in this directory"
+
+ errors[0x8c00] = "No set privileges"
+ errors[0x8c01] = "Unauthorized to modify a file in this directory"
+ errors[0x8c02] = "Unauthorized to change the restriction on this volume"
+
+ errors[0x8d00] = "Some of the affected files are in use by another client"
+ errors[0x8d01] = "The affected file is in use"
+
+ errors[0x8e00] = "All of the affected files are in use by another client"
+ errors[0x8f00] = "Some of the affected files are read-only"
+
+ errors[0x9000] = "An attempt to modify a read-only volume occurred"
+ errors[0x9001] = "All of the affected files are read-only"
+ errors[0x9002] = "Read Only Access to Volume"
+
+ errors[0x9100] = "Some of the affected files already exist"
+ errors[0x9101] = "Some Names Exist"
+
+ errors[0x9200] = "Directory with the new name already exists"
+ errors[0x9201] = "All of the affected files already exist"
+
+ errors[0x9300] = "Unauthorized to read from this file"
+ errors[0x9400] = "Unauthorized to write to this file"
+ errors[0x9500] = "The affected file is detached"
+
+ errors[0x9600] = "The file server has run out of memory to service this request"
+ errors[0x9601] = "No alloc space for message"
+ errors[0x9602] = "Server Out of Space"
+
+ errors[0x9800] = "The affected volume is not mounted"
+ errors[0x9801] = "The volume associated with Volume Number is not mounted"
+ errors[0x9802] = "The resulting volume does not exist"
+ errors[0x9803] = "The destination volume is not mounted"
+ errors[0x9804] = "Disk Map Error"
+
+ errors[0x9900] = "The file server has run out of directory space on the affected volume"
+ errors[0x9a00] = "Invalid request to rename the affected file to another volume"
+
+ errors[0x9b00] = "DirHandle is not associated with a valid directory path"
+ errors[0x9b01] = "A resulting directory handle is not associated with a valid directory path"
+ errors[0x9b02] = "The directory associated with DirHandle does not exist"
+ errors[0x9b03] = "Bad directory handle"
+
+ errors[0x9c00] = "The resulting path is not valid"
+ errors[0x9c01] = "The resulting file path is not valid"
+ errors[0x9c02] = "The resulting directory path is not valid"
+ errors[0x9c03] = "Invalid path"
+
+ errors[0x9d00] = "A directory handle was not available for allocation"
+
+ errors[0x9e00] = "The name of the directory does not conform to a legal name for this name space"
+ errors[0x9e01] = "The new directory name does not conform to a legal name for this name space"
+ errors[0x9e02] = "Bad File Name"
+
+ errors[0x9f00] = "The request attempted to delete a directory that is in use by another client"
+
+ errors[0xa000] = "The request attempted to delete a directory that is not empty"
+ errors[0xa100] = "An unrecoverable error occured on the affected directory"
+
+ errors[0xa200] = "The request attempted to read from a file region that is physically locked"
+ errors[0xa201] = "I/O Lock Error"
+
+ errors[0xa400] = "Invalid directory rename attempted"
+ errors[0xa500] = "Invalid open create mode"
+ errors[0xa600] = "Auditor Access has been Removed"
+ errors[0xa700] = "Error Auditing Version"
+
+ errors[0xa800] = "Invalid Support Module ID"
+ errors[0xa801] = "No Auditing Access Rights"
+ errors[0xa802] = "No Access Rights"
+
+ errors[0xbe00] = "Invalid Data Stream"
+ errors[0xbf00] = "Requests for this name space are not valid on this volume"
+
+ errors[0xc000] = "Unauthorized to retrieve accounting data"
+
+ errors[0xc100] = "The ACCOUNT_BALANCE property does not exist"
+ errors[0xc101] = "No Account Balance"
+
+ errors[0xc200] = "The object has exceeded its credit limit"
+ errors[0xc300] = "Too many holds have been placed against this account"
+ errors[0xc400] = "The client account has been disabled"
+
+ errors[0xc500] = "Access to the account has been denied because of intruder detection"
+ errors[0xc501] = "Login lockout"
+ errors[0xc502] = "Server Login Locked"
+
+ errors[0xc600] = "The caller does not have operator priviliges"
+ errors[0xc601] = "The client does not have operator priviliges"
+
+ errors[0xc800] = "Missing EA Key"
+ errors[0xc900] = "EA Not Found"
+ errors[0xca00] = "Invalid EA Handle Type"
+ errors[0xcb00] = "EA No Key No Data"
+ errors[0xcc00] = "EA Number Mismatch"
+ errors[0xcd00] = "Extent Number Out of Range"
+ errors[0xce00] = "EA Bad Directory Number"
+ errors[0xcf00] = "Invalid EA Handle"
+
+ errors[0xd000] = "Queue error"
+ errors[0xd001] = "EA Position Out of Range"
+
+ errors[0xd100] = "The queue does not exist"
+ errors[0xd101] = "EA Access Denied"
+
+ errors[0xd200] = "A queue server is not associated with this queue"
+ errors[0xd201] = "A queue server is not associated with the selected queue"
+ errors[0xd202] = "No queue server"
+ errors[0xd203] = "Data Page Odd Size"
+
+ errors[0xd300] = "No queue rights"
+ errors[0xd301] = "EA Volume Not Mounted"
+
+ errors[0xd400] = "The queue is full and cannot accept another request"
+ errors[0xd401] = "The queue associated with ObjectId is full and cannot accept another request"
+ errors[0xd402] = "Bad Page Boundary"
+
+ errors[0xd500] = "A job does not exist in this queue"
+ errors[0xd501] = "No queue job"
+ errors[0xd502] = "The job associated with JobNumber does not exist in this queue"
+ errors[0xd503] = "Inspect Failure"
+ errors[0xd504] = "Unknown NCP Extension Number"
+
+ errors[0xd600] = "The file server does not allow unencrypted passwords"
+ errors[0xd601] = "No job right"
+ errors[0xd602] = "EA Already Claimed"
+
+ errors[0xd700] = "Bad account"
+ errors[0xd701] = "The old and new password strings are identical"
+ errors[0xd702] = "The job is currently being serviced"
+ errors[0xd703] = "The queue is currently servicing a job"
+ errors[0xd704] = "Queue servicing"
+ errors[0xd705] = "Odd Buffer Size"
+
+ errors[0xd800] = "Queue not active"
+ errors[0xd801] = "No Scorecards"
+
+ errors[0xd900] = "The file server cannot accept another connection as it has reached its limit"
+ errors[0xd901] = "The client is not security equivalent to one of the objects in the Q_SERVERS group property of the target queue"
+ errors[0xd902] = "Station is not a server"
+ errors[0xd903] = "Bad EDS Signature"
+ errors[0xd904] = "Attempt to log in using an account which has limits on the number of concurrent connections and that number has been reached."
+
+ errors[0xda00] = "Attempted to login to the file server during a restricted time period"
+ errors[0xda01] = "Queue halted"
+ errors[0xda02] = "EA Space Limit"
+
+ errors[0xdb00] = "Attempted to login to the file server from an unauthorized workstation or network"
+ errors[0xdb01] = "The queue cannot attach another queue server"
+ errors[0xdb02] = "Maximum queue servers"
+ errors[0xdb03] = "EA Key Corrupt"
+
+ errors[0xdc00] = "Account Expired"
+ errors[0xdc01] = "EA Key Limit"
+
+ errors[0xdd00] = "Tally Corrupt"
+ errors[0xde00] = "Attempted to login to the file server with an incorrect password"
+ errors[0xdf00] = "Attempted to login to the file server with a password that has expired"
+
+ errors[0xe000] = "No Login Connections Available"
+ errors[0xe700] = "No disk track"
+ errors[0xe800] = "Write to group"
+ errors[0xe900] = "The object is already a member of the group property"
+
+ errors[0xea00] = "No such member"
+ errors[0xea01] = "The bindery object is not a member of the set"
+ errors[0xea02] = "Non-existent member"
+
+ errors[0xeb00] = "The property is not a set property"
+
+ errors[0xec00] = "No such set"
+ errors[0xec01] = "The set property does not exist"
+
+ errors[0xed00] = "Property exists"
+ errors[0xed01] = "The property already exists"
+ errors[0xed02] = "An attempt was made to create a bindery object property that already exists"
+
+ errors[0xee00] = "The object already exists"
+ errors[0xee01] = "The bindery object already exists"
+
+ errors[0xef00] = "Illegal name"
+ errors[0xef01] = "Illegal characters in ObjectName field"
+ errors[0xef02] = "Invalid name"
+
+ errors[0xf000] = "A wildcard was detected in a field that does not support wildcards"
+ errors[0xf001] = "An illegal wildcard was detected in ObjectName"
+
+ errors[0xf100] = "The client does not have the rights to access this bindery object"
+ errors[0xf101] = "Bindery security"
+ errors[0xf102] = "Invalid bindery security"
+
+ errors[0xf200] = "Unauthorized to read from this object"
+ errors[0xf300] = "Unauthorized to rename this object"
+
+ errors[0xf400] = "Unauthorized to delete this object"
+ errors[0xf401] = "No object delete privileges"
+ errors[0xf402] = "Unauthorized to delete this queue"
+
+ errors[0xf500] = "Unauthorized to create this object"
+ errors[0xf501] = "No object create"
+
+ errors[0xf600] = "No property delete"
+ errors[0xf601] = "Unauthorized to delete the property of this object"
+ errors[0xf602] = "Unauthorized to delete this property"
+
+ errors[0xf700] = "Unauthorized to create this property"
+ errors[0xf701] = "No property create privilege"
+
+ errors[0xf800] = "Unauthorized to write to this property"
+ errors[0xf900] = "Unauthorized to read this property"
+ errors[0xfa00] = "Temporary remap error"
+
+ errors[0xfb00] = "No such property"
+ errors[0xfb01] = "The file server does not support this request"
+ errors[0xfb02] = "The specified property does not exist"
+ errors[0xfb03] = "The PASSWORD property does not exist for this bindery object"
+ errors[0xfb04] = "NDS NCP not available"
+ errors[0xfb05] = "Bad Directory Handle"
+ errors[0xfb06] = "Unknown Request"
+ errors[0xfb07] = "Invalid Subfunction Request"
+ errors[0xfb08] = "Attempt to use an invalid parameter (drive number, path, or flag value) during a set drive path call"
+ errors[0xfb09] = "NMAS not running on this server, NCP NOT Supported"
+ errors[0xfb0a] = "Station Not Logged In"
+ errors[0xfb0b] = "Secret Store not running on this server, NCP Not supported"
+
+ errors[0xfc00] = "The message queue cannot accept another message"
+ errors[0xfc01] = "The trustee associated with ObjectId does not exist"
+ errors[0xfc02] = "The specified bindery object does not exist"
+ errors[0xfc03] = "The bindery object associated with ObjectID does not exist"
+ errors[0xfc04] = "A bindery object does not exist that matches"
+ errors[0xfc05] = "The specified queue does not exist"
+ errors[0xfc06] = "No such object"
+ errors[0xfc07] = "The queue associated with ObjectID does not exist"
+
+ errors[0xfd00] = "Bad station number"
+ errors[0xfd01] = "The connection associated with ConnectionNumber is not active"
+ errors[0xfd02] = "Lock collision"
+ errors[0xfd03] = "Transaction tracking is disabled"
+
+ errors[0xfe00] = "I/O failure"
+ errors[0xfe01] = "The files containing the bindery on the file server are locked"
+ errors[0xfe02] = "A file with the specified name already exists in this directory"
+ errors[0xfe03] = "No more restrictions were found"
+ errors[0xfe04] = "The file server was unable to lock the file within the specified time limit"
+ errors[0xfe05] = "The file server was unable to lock all files within the specified time limit"
+ errors[0xfe06] = "The bindery object associated with ObjectID is not a valid trustee"
+ errors[0xfe07] = "Directory locked"
+ errors[0xfe08] = "Bindery locked"
+ errors[0xfe09] = "Invalid semaphore name length"
+ errors[0xfe0a] = "The file server was unable to complete the operation within the specified time limit"
+ errors[0xfe0b] = "Transaction restart"
+ errors[0xfe0c] = "Bad packet"
+ errors[0xfe0d] = "Timeout"
+ errors[0xfe0e] = "User Not Found"
+ errors[0xfe0f] = "Trustee Not Found"
+
+ errors[0xff00] = "Failure"
+ errors[0xff01] = "Lock error"
+ errors[0xff02] = "File not found"
+ errors[0xff03] = "The file not found or cannot be unlocked"
+ errors[0xff04] = "Record not found"
+ errors[0xff05] = "The logical record was not found"
+ errors[0xff06] = "The printer associated with Printer Number does not exist"
+ errors[0xff07] = "No such printer"
+ errors[0xff08] = "Unable to complete the request"
+ errors[0xff09] = "Unauthorized to change privileges of this trustee"
+ errors[0xff0a] = "No files matching the search criteria were found"
+ errors[0xff0b] = "A file matching the search criteria was not found"
+ errors[0xff0c] = "Verification failed"
+ errors[0xff0d] = "Object associated with ObjectID is not a manager"
+ errors[0xff0e] = "Invalid initial semaphore value"
+ errors[0xff0f] = "The semaphore handle is not valid"
+ errors[0xff10] = "SemaphoreHandle is not associated with a valid sempahore"
+ errors[0xff11] = "Invalid semaphore handle"
+ errors[0xff12] = "Transaction tracking is not available"
+ errors[0xff13] = "The transaction has not yet been written to disk"
+ errors[0xff14] = "Directory already exists"
+ errors[0xff15] = "The file already exists and the deletion flag was not set"
+ errors[0xff16] = "No matching files or directories were found"
+ errors[0xff17] = "A file or directory matching the search criteria was not found"
+ errors[0xff18] = "The file already exists"
+ errors[0xff19] = "Failure, No files found"
+ errors[0xff1a] = "Unlock Error"
+ errors[0xff1b] = "I/O Bound Error"
+ errors[0xff1c] = "Not Accepting Messages"
+ errors[0xff1d] = "No More Salvageable Files in Directory"
+ errors[0xff1e] = "Calling Station is Not a Manager"
+ errors[0xff1f] = "Bindery Failure"
+ errors[0xff20] = "NCP Extension Not Found"
+
+##############################################################################
+# Produce C code
+##############################################################################
+def ExamineVars(vars, structs_hash, vars_hash):
+ for var in vars:
+ if isinstance(var, struct):
+ structs_hash[var.HFName()] = var
+ struct_vars = var.Variables()
+ ExamineVars(struct_vars, structs_hash, vars_hash)
+ else:
+ vars_hash[repr(var)] = var
+ if isinstance(var, bitfield):
+ sub_vars = var.SubVariables()
+ ExamineVars(sub_vars, structs_hash, vars_hash)
+
+def produce_code():
+
+ global errors
+
+ print "/*"
+ print " * Generated automatically from %s" % (sys.argv[0])
+ print " * Do not edit this file manually, as all changes will be lost."
+ print " */\n"
+
+ print """
+/*
+ * Portions Copyright (c) Gilbert Ramirez 2000-2002
+ * Portions Copyright (c) Novell, Inc. 2000-2003
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "ptvcursor.h"
+#include "packet-ncp-int.h"
+#include "packet-ncp-nmas.h"
+#include <epan/strutil.h>
+#include "reassemble.h"
+
+/* Function declarations for functions used in proto_register_ncp2222() */
+static void ncp_init_protocol(void);
+static void ncp_postseq_cleanup(void);
+
+/* Endianness macros */
+#define BE 0
+#define LE 1
+#define NO_ENDIANNESS 0
+
+#define NO_LENGTH -1
+
+/* We use this int-pointer as a special flag in ptvc_record's */
+static int ptvc_struct_int_storage;
+#define PTVC_STRUCT (&ptvc_struct_int_storage)
+
+/* Values used in the count-variable ("var"/"repeat") logic. */"""
+
+
+ if global_highest_var > -1:
+ print "#define NUM_REPEAT_VARS\t%d" % (global_highest_var + 1)
+ print "guint repeat_vars[NUM_REPEAT_VARS];",
+ else:
+ print "#define NUM_REPEAT_VARS\t0"
+ print "guint *repeat_vars = NULL;",
+
+ print """
+#define NO_VAR NUM_REPEAT_VARS
+#define NO_REPEAT NUM_REPEAT_VARS
+
+#define REQ_COND_SIZE_CONSTANT 0
+#define REQ_COND_SIZE_VARIABLE 1
+#define NO_REQ_COND_SIZE 0
+
+
+#define NTREE 0x00020000
+#define NDEPTH 0x00000002
+#define NREV 0x00000004
+#define NFLAGS 0x00000008
+
+
+static int hf_ncp_func = -1;
+static int hf_ncp_length = -1;
+static int hf_ncp_subfunc = -1;
+static int hf_ncp_fragment_handle = -1;
+static int hf_ncp_completion_code = -1;
+static int hf_ncp_connection_status = -1;
+static int hf_ncp_req_frame_num = -1;
+static int hf_ncp_req_frame_time = -1;
+static int hf_ncp_fragment_size = -1;
+static int hf_ncp_message_size = -1;
+static int hf_ncp_nds_flag = -1;
+static int hf_ncp_nds_verb = -1;
+static int hf_ping_version = -1;
+static int hf_nds_version = -1;
+static int hf_nds_flags = -1;
+static int hf_nds_reply_depth = -1;
+static int hf_nds_reply_rev = -1;
+static int hf_nds_reply_flags = -1;
+static int hf_nds_p1type = -1;
+static int hf_nds_uint32value = -1;
+static int hf_nds_bit1 = -1;
+static int hf_nds_bit2 = -1;
+static int hf_nds_bit3 = -1;
+static int hf_nds_bit4 = -1;
+static int hf_nds_bit5 = -1;
+static int hf_nds_bit6 = -1;
+static int hf_nds_bit7 = -1;
+static int hf_nds_bit8 = -1;
+static int hf_nds_bit9 = -1;
+static int hf_nds_bit10 = -1;
+static int hf_nds_bit11 = -1;
+static int hf_nds_bit12 = -1;
+static int hf_nds_bit13 = -1;
+static int hf_nds_bit14 = -1;
+static int hf_nds_bit15 = -1;
+static int hf_nds_bit16 = -1;
+static int hf_bit1outflags = -1;
+static int hf_bit2outflags = -1;
+static int hf_bit3outflags = -1;
+static int hf_bit4outflags = -1;
+static int hf_bit5outflags = -1;
+static int hf_bit6outflags = -1;
+static int hf_bit7outflags = -1;
+static int hf_bit8outflags = -1;
+static int hf_bit9outflags = -1;
+static int hf_bit10outflags = -1;
+static int hf_bit11outflags = -1;
+static int hf_bit12outflags = -1;
+static int hf_bit13outflags = -1;
+static int hf_bit14outflags = -1;
+static int hf_bit15outflags = -1;
+static int hf_bit16outflags = -1;
+static int hf_bit1nflags = -1;
+static int hf_bit2nflags = -1;
+static int hf_bit3nflags = -1;
+static int hf_bit4nflags = -1;
+static int hf_bit5nflags = -1;
+static int hf_bit6nflags = -1;
+static int hf_bit7nflags = -1;
+static int hf_bit8nflags = -1;
+static int hf_bit9nflags = -1;
+static int hf_bit10nflags = -1;
+static int hf_bit11nflags = -1;
+static int hf_bit12nflags = -1;
+static int hf_bit13nflags = -1;
+static int hf_bit14nflags = -1;
+static int hf_bit15nflags = -1;
+static int hf_bit16nflags = -1;
+static int hf_bit1rflags = -1;
+static int hf_bit2rflags = -1;
+static int hf_bit3rflags = -1;
+static int hf_bit4rflags = -1;
+static int hf_bit5rflags = -1;
+static int hf_bit6rflags = -1;
+static int hf_bit7rflags = -1;
+static int hf_bit8rflags = -1;
+static int hf_bit9rflags = -1;
+static int hf_bit10rflags = -1;
+static int hf_bit11rflags = -1;
+static int hf_bit12rflags = -1;
+static int hf_bit13rflags = -1;
+static int hf_bit14rflags = -1;
+static int hf_bit15rflags = -1;
+static int hf_bit16rflags = -1;
+static int hf_bit1cflags = -1;
+static int hf_bit2cflags = -1;
+static int hf_bit3cflags = -1;
+static int hf_bit4cflags = -1;
+static int hf_bit5cflags = -1;
+static int hf_bit6cflags = -1;
+static int hf_bit7cflags = -1;
+static int hf_bit8cflags = -1;
+static int hf_bit9cflags = -1;
+static int hf_bit10cflags = -1;
+static int hf_bit11cflags = -1;
+static int hf_bit12cflags = -1;
+static int hf_bit13cflags = -1;
+static int hf_bit14cflags = -1;
+static int hf_bit15cflags = -1;
+static int hf_bit16cflags = -1;
+static int hf_bit1acflags = -1;
+static int hf_bit2acflags = -1;
+static int hf_bit3acflags = -1;
+static int hf_bit4acflags = -1;
+static int hf_bit5acflags = -1;
+static int hf_bit6acflags = -1;
+static int hf_bit7acflags = -1;
+static int hf_bit8acflags = -1;
+static int hf_bit9acflags = -1;
+static int hf_bit10acflags = -1;
+static int hf_bit11acflags = -1;
+static int hf_bit12acflags = -1;
+static int hf_bit13acflags = -1;
+static int hf_bit14acflags = -1;
+static int hf_bit15acflags = -1;
+static int hf_bit16acflags = -1;
+static int hf_bit1vflags = -1;
+static int hf_bit2vflags = -1;
+static int hf_bit3vflags = -1;
+static int hf_bit4vflags = -1;
+static int hf_bit5vflags = -1;
+static int hf_bit6vflags = -1;
+static int hf_bit7vflags = -1;
+static int hf_bit8vflags = -1;
+static int hf_bit9vflags = -1;
+static int hf_bit10vflags = -1;
+static int hf_bit11vflags = -1;
+static int hf_bit12vflags = -1;
+static int hf_bit13vflags = -1;
+static int hf_bit14vflags = -1;
+static int hf_bit15vflags = -1;
+static int hf_bit16vflags = -1;
+static int hf_bit1eflags = -1;
+static int hf_bit2eflags = -1;
+static int hf_bit3eflags = -1;
+static int hf_bit4eflags = -1;
+static int hf_bit5eflags = -1;
+static int hf_bit6eflags = -1;
+static int hf_bit7eflags = -1;
+static int hf_bit8eflags = -1;
+static int hf_bit9eflags = -1;
+static int hf_bit10eflags = -1;
+static int hf_bit11eflags = -1;
+static int hf_bit12eflags = -1;
+static int hf_bit13eflags = -1;
+static int hf_bit14eflags = -1;
+static int hf_bit15eflags = -1;
+static int hf_bit16eflags = -1;
+static int hf_bit1infoflagsl = -1;
+static int hf_bit2infoflagsl = -1;
+static int hf_bit3infoflagsl = -1;
+static int hf_bit4infoflagsl = -1;
+static int hf_bit5infoflagsl = -1;
+static int hf_bit6infoflagsl = -1;
+static int hf_bit7infoflagsl = -1;
+static int hf_bit8infoflagsl = -1;
+static int hf_bit9infoflagsl = -1;
+static int hf_bit10infoflagsl = -1;
+static int hf_bit11infoflagsl = -1;
+static int hf_bit12infoflagsl = -1;
+static int hf_bit13infoflagsl = -1;
+static int hf_bit14infoflagsl = -1;
+static int hf_bit15infoflagsl = -1;
+static int hf_bit16infoflagsl = -1;
+static int hf_bit1infoflagsh = -1;
+static int hf_bit2infoflagsh = -1;
+static int hf_bit3infoflagsh = -1;
+static int hf_bit4infoflagsh = -1;
+static int hf_bit5infoflagsh = -1;
+static int hf_bit6infoflagsh = -1;
+static int hf_bit7infoflagsh = -1;
+static int hf_bit8infoflagsh = -1;
+static int hf_bit9infoflagsh = -1;
+static int hf_bit10infoflagsh = -1;
+static int hf_bit11infoflagsh = -1;
+static int hf_bit12infoflagsh = -1;
+static int hf_bit13infoflagsh = -1;
+static int hf_bit14infoflagsh = -1;
+static int hf_bit15infoflagsh = -1;
+static int hf_bit16infoflagsh = -1;
+static int hf_bit1lflags = -1;
+static int hf_bit2lflags = -1;
+static int hf_bit3lflags = -1;
+static int hf_bit4lflags = -1;
+static int hf_bit5lflags = -1;
+static int hf_bit6lflags = -1;
+static int hf_bit7lflags = -1;
+static int hf_bit8lflags = -1;
+static int hf_bit9lflags = -1;
+static int hf_bit10lflags = -1;
+static int hf_bit11lflags = -1;
+static int hf_bit12lflags = -1;
+static int hf_bit13lflags = -1;
+static int hf_bit14lflags = -1;
+static int hf_bit15lflags = -1;
+static int hf_bit16lflags = -1;
+static int hf_bit1l1flagsl = -1;
+static int hf_bit2l1flagsl = -1;
+static int hf_bit3l1flagsl = -1;
+static int hf_bit4l1flagsl = -1;
+static int hf_bit5l1flagsl = -1;
+static int hf_bit6l1flagsl = -1;
+static int hf_bit7l1flagsl = -1;
+static int hf_bit8l1flagsl = -1;
+static int hf_bit9l1flagsl = -1;
+static int hf_bit10l1flagsl = -1;
+static int hf_bit11l1flagsl = -1;
+static int hf_bit12l1flagsl = -1;
+static int hf_bit13l1flagsl = -1;
+static int hf_bit14l1flagsl = -1;
+static int hf_bit15l1flagsl = -1;
+static int hf_bit16l1flagsl = -1;
+static int hf_bit1l1flagsh = -1;
+static int hf_bit2l1flagsh = -1;
+static int hf_bit3l1flagsh = -1;
+static int hf_bit4l1flagsh = -1;
+static int hf_bit5l1flagsh = -1;
+static int hf_bit6l1flagsh = -1;
+static int hf_bit7l1flagsh = -1;
+static int hf_bit8l1flagsh = -1;
+static int hf_bit9l1flagsh = -1;
+static int hf_bit10l1flagsh = -1;
+static int hf_bit11l1flagsh = -1;
+static int hf_bit12l1flagsh = -1;
+static int hf_bit13l1flagsh = -1;
+static int hf_bit14l1flagsh = -1;
+static int hf_bit15l1flagsh = -1;
+static int hf_bit16l1flagsh = -1;
+static int hf_nds_tree_name = -1;
+static int hf_nds_reply_error = -1;
+static int hf_nds_net = -1;
+static int hf_nds_node = -1;
+static int hf_nds_socket = -1;
+static int hf_add_ref_ip = -1;
+static int hf_add_ref_udp = -1;
+static int hf_add_ref_tcp = -1;
+static int hf_referral_record = -1;
+static int hf_referral_addcount = -1;
+static int hf_nds_port = -1;
+static int hf_mv_string = -1;
+static int hf_nds_syntax = -1;
+static int hf_value_string = -1;
+static int hf_nds_buffer_size = -1;
+static int hf_nds_ver = -1;
+static int hf_nds_nflags = -1;
+static int hf_nds_scope = -1;
+static int hf_nds_name = -1;
+static int hf_nds_comm_trans = -1;
+static int hf_nds_tree_trans = -1;
+static int hf_nds_iteration = -1;
+static int hf_nds_eid = -1;
+static int hf_nds_info_type = -1;
+static int hf_nds_all_attr = -1;
+static int hf_nds_req_flags = -1;
+static int hf_nds_attr = -1;
+static int hf_nds_crc = -1;
+static int hf_nds_referrals = -1;
+static int hf_nds_result_flags = -1;
+static int hf_nds_tag_string = -1;
+static int hf_value_bytes = -1;
+static int hf_replica_type = -1;
+static int hf_replica_state = -1;
+static int hf_replica_number = -1;
+static int hf_min_nds_ver = -1;
+static int hf_nds_ver_include = -1;
+static int hf_nds_ver_exclude = -1;
+static int hf_nds_es = -1;
+static int hf_es_type = -1;
+static int hf_delim_string = -1;
+static int hf_rdn_string = -1;
+static int hf_nds_revent = -1;
+static int hf_nds_rnum = -1;
+static int hf_nds_name_type = -1;
+static int hf_nds_rflags = -1;
+static int hf_nds_eflags = -1;
+static int hf_nds_depth = -1;
+static int hf_nds_class_def_type = -1;
+static int hf_nds_classes = -1;
+static int hf_nds_return_all_classes = -1;
+static int hf_nds_stream_flags = -1;
+static int hf_nds_stream_name = -1;
+static int hf_nds_file_handle = -1;
+static int hf_nds_file_size = -1;
+static int hf_nds_dn_output_type = -1;
+static int hf_nds_nested_output_type = -1;
+static int hf_nds_output_delimiter = -1;
+static int hf_nds_output_entry_specifier = -1;
+static int hf_es_value = -1;
+static int hf_es_rdn_count = -1;
+static int hf_nds_replica_num = -1;
+static int hf_nds_event_num = -1;
+static int hf_es_seconds = -1;
+static int hf_nds_compare_results = -1;
+static int hf_nds_parent = -1;
+static int hf_nds_name_filter = -1;
+static int hf_nds_class_filter = -1;
+static int hf_nds_time_filter = -1;
+static int hf_nds_partition_root_id = -1;
+static int hf_nds_replicas = -1;
+static int hf_nds_purge = -1;
+static int hf_nds_local_partition = -1;
+static int hf_partition_busy = -1;
+static int hf_nds_number_of_changes = -1;
+static int hf_sub_count = -1;
+static int hf_nds_revision = -1;
+static int hf_nds_base_class = -1;
+static int hf_nds_relative_dn = -1;
+static int hf_nds_root_dn = -1;
+static int hf_nds_parent_dn = -1;
+static int hf_deref_base = -1;
+static int hf_nds_entry_info = -1;
+static int hf_nds_base = -1;
+static int hf_nds_privileges = -1;
+static int hf_nds_vflags = -1;
+static int hf_nds_value_len = -1;
+static int hf_nds_cflags = -1;
+static int hf_nds_acflags = -1;
+static int hf_nds_asn1 = -1;
+static int hf_nds_upper = -1;
+static int hf_nds_lower = -1;
+static int hf_nds_trustee_dn = -1;
+static int hf_nds_attribute_dn = -1;
+static int hf_nds_acl_add = -1;
+static int hf_nds_acl_del = -1;
+static int hf_nds_att_add = -1;
+static int hf_nds_att_del = -1;
+static int hf_nds_keep = -1;
+static int hf_nds_new_rdn = -1;
+static int hf_nds_time_delay = -1;
+static int hf_nds_root_name = -1;
+static int hf_nds_new_part_id = -1;
+static int hf_nds_child_part_id = -1;
+static int hf_nds_master_part_id = -1;
+static int hf_nds_target_name = -1;
+static int hf_nds_super = -1;
+static int hf_bit1pingflags2 = -1;
+static int hf_bit2pingflags2 = -1;
+static int hf_bit3pingflags2 = -1;
+static int hf_bit4pingflags2 = -1;
+static int hf_bit5pingflags2 = -1;
+static int hf_bit6pingflags2 = -1;
+static int hf_bit7pingflags2 = -1;
+static int hf_bit8pingflags2 = -1;
+static int hf_bit9pingflags2 = -1;
+static int hf_bit10pingflags2 = -1;
+static int hf_bit11pingflags2 = -1;
+static int hf_bit12pingflags2 = -1;
+static int hf_bit13pingflags2 = -1;
+static int hf_bit14pingflags2 = -1;
+static int hf_bit15pingflags2 = -1;
+static int hf_bit16pingflags2 = -1;
+static int hf_bit1pingflags1 = -1;
+static int hf_bit2pingflags1 = -1;
+static int hf_bit3pingflags1 = -1;
+static int hf_bit4pingflags1 = -1;
+static int hf_bit5pingflags1 = -1;
+static int hf_bit6pingflags1 = -1;
+static int hf_bit7pingflags1 = -1;
+static int hf_bit8pingflags1 = -1;
+static int hf_bit9pingflags1 = -1;
+static int hf_bit10pingflags1 = -1;
+static int hf_bit11pingflags1 = -1;
+static int hf_bit12pingflags1 = -1;
+static int hf_bit13pingflags1 = -1;
+static int hf_bit14pingflags1 = -1;
+static int hf_bit15pingflags1 = -1;
+static int hf_bit16pingflags1 = -1;
+static int hf_bit1pingpflags1 = -1;
+static int hf_bit2pingpflags1 = -1;
+static int hf_bit3pingpflags1 = -1;
+static int hf_bit4pingpflags1 = -1;
+static int hf_bit5pingpflags1 = -1;
+static int hf_bit6pingpflags1 = -1;
+static int hf_bit7pingpflags1 = -1;
+static int hf_bit8pingpflags1 = -1;
+static int hf_bit9pingpflags1 = -1;
+static int hf_bit10pingpflags1 = -1;
+static int hf_bit11pingpflags1 = -1;
+static int hf_bit12pingpflags1 = -1;
+static int hf_bit13pingpflags1 = -1;
+static int hf_bit14pingpflags1 = -1;
+static int hf_bit15pingpflags1 = -1;
+static int hf_bit16pingpflags1 = -1;
+static int hf_bit1pingvflags1 = -1;
+static int hf_bit2pingvflags1 = -1;
+static int hf_bit3pingvflags1 = -1;
+static int hf_bit4pingvflags1 = -1;
+static int hf_bit5pingvflags1 = -1;
+static int hf_bit6pingvflags1 = -1;
+static int hf_bit7pingvflags1 = -1;
+static int hf_bit8pingvflags1 = -1;
+static int hf_bit9pingvflags1 = -1;
+static int hf_bit10pingvflags1 = -1;
+static int hf_bit11pingvflags1 = -1;
+static int hf_bit12pingvflags1 = -1;
+static int hf_bit13pingvflags1 = -1;
+static int hf_bit14pingvflags1 = -1;
+static int hf_bit15pingvflags1 = -1;
+static int hf_bit16pingvflags1 = -1;
+static int hf_nds_letter_ver = -1;
+static int hf_nds_os_ver = -1;
+static int hf_nds_lic_flags = -1;
+static int hf_nds_ds_time = -1;
+static int hf_nds_ping_version = -1;
+static int hf_nds_search_scope = -1;
+static int hf_nds_num_objects = -1;
+static int hf_bit1siflags = -1;
+static int hf_bit2siflags = -1;
+static int hf_bit3siflags = -1;
+static int hf_bit4siflags = -1;
+static int hf_bit5siflags = -1;
+static int hf_bit6siflags = -1;
+static int hf_bit7siflags = -1;
+static int hf_bit8siflags = -1;
+static int hf_bit9siflags = -1;
+static int hf_bit10siflags = -1;
+static int hf_bit11siflags = -1;
+static int hf_bit12siflags = -1;
+static int hf_bit13siflags = -1;
+static int hf_bit14siflags = -1;
+static int hf_bit15siflags = -1;
+static int hf_bit16siflags = -1;
+static int hf_nds_segments = -1;
+static int hf_nds_segment = -1;
+static int hf_nds_segment_overlap = -1;
+static int hf_nds_segment_overlap_conflict = -1;
+static int hf_nds_segment_multiple_tails = -1;
+static int hf_nds_segment_too_long_segment = -1;
+static int hf_nds_segment_error = -1;
+
+
+ """
+
+ # Look at all packet types in the packets collection, and cull information
+ # from them.
+ errors_used_list = []
+ errors_used_hash = {}
+ groups_used_list = []
+ groups_used_hash = {}
+ variables_used_hash = {}
+ structs_used_hash = {}
+
+ for pkt in packets:
+ # Determine which error codes are used.
+ codes = pkt.CompletionCodes()
+ for code in codes.Records():
+ if not errors_used_hash.has_key(code):
+ errors_used_hash[code] = len(errors_used_list)
+ errors_used_list.append(code)
+
+ # Determine which groups are used.
+ group = pkt.Group()
+ if not groups_used_hash.has_key(group):
+ groups_used_hash[group] = len(groups_used_list)
+ groups_used_list.append(group)
+
+ # Determine which variables are used.
+ vars = pkt.Variables()
+ ExamineVars(vars, structs_used_hash, variables_used_hash)
+
+
+ # Print the hf variable declarations
+ sorted_vars = variables_used_hash.values()
+ sorted_vars.sort()
+ for var in sorted_vars:
+ print "static int " + var.HFName() + " = -1;"
+
+
+ # Print the value_string's
+ for var in sorted_vars:
+ if isinstance(var, val_string):
+ print ""
+ print var.Code()
+
+ # Determine which error codes are not used
+ errors_not_used = {}
+ # Copy the keys from the error list...
+ for code in errors.keys():
+ errors_not_used[code] = 1
+ # ... and remove the ones that *were* used.
+ for code in errors_used_list:
+ del errors_not_used[code]
+
+ # Print a remark showing errors not used
+ list_errors_not_used = errors_not_used.keys()
+ list_errors_not_used.sort()
+ for code in list_errors_not_used:
+ print "/* Error 0x%04x not used: %s */" % (code, errors[code])
+ print "\n"
+
+ # Print the errors table
+ print "/* Error strings. */"
+ print "static const char *ncp_errors[] = {"
+ for code in errors_used_list:
+ print '\t/* %02d (0x%04x) */ "%s",' % (errors_used_hash[code], code, errors[code])
+ print "};\n"
+
+
+
+
+ # Determine which groups are not used
+ groups_not_used = {}
+ # Copy the keys from the group list...
+ for group in groups.keys():
+ groups_not_used[group] = 1
+ # ... and remove the ones that *were* used.
+ for group in groups_used_list:
+ del groups_not_used[group]
+
+ # Print a remark showing groups not used
+ list_groups_not_used = groups_not_used.keys()
+ list_groups_not_used.sort()
+ for group in list_groups_not_used:
+ print "/* Group not used: %s = %s */" % (group, groups[group])
+ print "\n"
+
+ # Print the groups table
+ print "/* Group strings. */"
+ print "static const char *ncp_groups[] = {"
+ for group in groups_used_list:
+ print '\t/* %02d (%s) */ "%s",' % (groups_used_hash[group], group, groups[group])
+ print "};\n"
+
+ # Print the group macros
+ for group in groups_used_list:
+ name = string.upper(group)
+ print "#define NCP_GROUP_%s\t%d" % (name, groups_used_hash[group])
+ print "\n"
+
+
+ # Print the conditional_records for all Request Conditions.
+ num = 0
+ print "/* Request-Condition dfilter records. The NULL pointer"
+ print " is replaced by a pointer to the created dfilter_t. */"
+ if len(global_req_cond) == 0:
+ print "static conditional_record req_conds = NULL;"
+ else:
+ print "static conditional_record req_conds[] = {"
+ for req_cond in global_req_cond.keys():
+ print "\t{ \"%s\", NULL }," % (req_cond,)
+ global_req_cond[req_cond] = num
+ num = num + 1
+ print "};"
+ print "#define NUM_REQ_CONDS %d" % (num,)
+ print "#define NO_REQ_COND NUM_REQ_CONDS\n\n"
+
+
+
+ # Print PTVC's for bitfields
+ ett_list = []
+ print "/* PTVC records for bit-fields. */"
+ for var in sorted_vars:
+ if isinstance(var, bitfield):
+ sub_vars_ptvc = var.SubVariablesPTVC()
+ print "/* %s */" % (sub_vars_ptvc.Name())
+ print sub_vars_ptvc.Code()
+ ett_list.append(sub_vars_ptvc.ETTName())
+
+
+ # Print the PTVC's for structures
+ print "/* PTVC records for structs. */"
+ # Sort them
+ svhash = {}
+ for svar in structs_used_hash.values():
+ svhash[svar.HFName()] = svar
+ if svar.descr:
+ ett_list.append(svar.ETTName())
+
+ struct_vars = svhash.keys()
+ struct_vars.sort()
+ for varname in struct_vars:
+ var = svhash[varname]
+ print var.Code()
+
+ ett_list.sort()
+
+ # Print regular PTVC's
+ print "/* PTVC records. These are re-used to save space. */"
+ for ptvc in ptvc_lists.Members():
+ if not ptvc.Null() and not ptvc.Empty():
+ print ptvc.Code()
+
+ # Print error_equivalency tables
+ print "/* Error-Equivalency Tables. These are re-used to save space. */"
+ for compcodes in compcode_lists.Members():
+ errors = compcodes.Records()
+ # Make sure the record for error = 0x00 comes last.
+ print "static const error_equivalency %s[] = {" % (compcodes.Name())
+ for error in errors:
+ error_in_packet = error >> 8;
+ ncp_error_index = errors_used_hash[error]
+ print "\t{ 0x%02x, %d }, /* 0x%04x */" % (error_in_packet,
+ ncp_error_index, error)
+ print "\t{ 0x00, -1 }\n};\n"
+
+
+
+ # Print integer arrays for all ncp_records that need
+ # a list of req_cond_indexes. Do it "uniquely" to save space;
+ # if multiple packets share the same set of req_cond's,
+ # then they'll share the same integer array
+ print "/* Request Condition Indexes */"
+ # First, make them unique
+ req_cond_collection = UniqueCollection("req_cond_collection")
+ for pkt in packets:
+ req_conds = pkt.CalculateReqConds()
+ if req_conds:
+ unique_list = req_cond_collection.Add(req_conds)
+ pkt.SetReqConds(unique_list)
+ else:
+ pkt.SetReqConds(None)
+
+ # Print them
+ for req_cond in req_cond_collection.Members():
+ print "static const int %s[] = {" % (req_cond.Name(),)
+ print "\t",
+ vals = []
+ for text in req_cond.Records():
+ vals.append(global_req_cond[text])
+ vals.sort()
+ for val in vals:
+ print "%s, " % (val,),
+
+ print "-1 };"
+ print ""
+
+
+
+ # Functions without length parameter
+ funcs_without_length = {}
+
+ # Print info string structures
+ print "/* Info Strings */"
+ for pkt in packets:
+ if pkt.req_info_str:
+ name = pkt.InfoStrName() + "_req"
+ var = pkt.req_info_str[0]
+ print "static const info_string_t %s = {" % (name,)
+ print "\t&%s," % (var.HFName(),)
+ print '\t"%s",' % (pkt.req_info_str[1],)
+ print '\t"%s"' % (pkt.req_info_str[2],)
+ print "};\n"
+
+
+
+ # Print ncp_record packet records
+ print "#define SUBFUNC_WITH_LENGTH 0x02"
+ print "#define SUBFUNC_NO_LENGTH 0x01"
+ print "#define NO_SUBFUNC 0x00"
+
+ print "/* ncp_record structs for packets */"
+ print "static const ncp_record ncp_packets[] = {"
+ for pkt in packets:
+ if pkt.HasSubFunction():
+ func = pkt.FunctionCode('high')
+ if pkt.HasLength():
+ subfunc_string = "SUBFUNC_WITH_LENGTH"
+ # Ensure that the function either has a length param or not
+ if funcs_without_length.has_key(func):
+ sys.exit("Function 0x%04x sometimes has length param, sometimes not." \
+ % (pkt.FunctionCode(),))
+ else:
+ subfunc_string = "SUBFUNC_NO_LENGTH"
+ funcs_without_length[func] = 1
+ else:
+ subfunc_string = "NO_SUBFUNC"
+ print '\t{ 0x%02x, 0x%02x, %s, "%s",' % (pkt.FunctionCode('high'),
+ pkt.FunctionCode('low'), subfunc_string, pkt.Description()),
+
+ print '\t%d /* %s */,' % (groups_used_hash[pkt.Group()], pkt.Group())
+
+ ptvc = pkt.PTVCRequest()
+ if not ptvc.Null() and not ptvc.Empty():
+ ptvc_request = ptvc.Name()
+ else:
+ ptvc_request = 'NULL'
+
+ ptvc = pkt.PTVCReply()
+ if not ptvc.Null() and not ptvc.Empty():
+ ptvc_reply = ptvc.Name()
+ else:
+ ptvc_reply = 'NULL'
+
+ errors = pkt.CompletionCodes()
+
+ req_conds_obj = pkt.GetReqConds()
+ if req_conds_obj:
+ req_conds = req_conds_obj.Name()
+ else:
+ req_conds = "NULL"
+
+ if not req_conds_obj:
+ req_cond_size = "NO_REQ_COND_SIZE"
+ else:
+ req_cond_size = pkt.ReqCondSize()
+ if req_cond_size == None:
+ msg.write("NCP packet %s nees a ReqCondSize*() call\n" \
+ % (pkt.CName(),))
+ sys.exit(1)
+
+ if pkt.req_info_str:
+ req_info_str = "&" + pkt.InfoStrName() + "_req"
+ else:
+ req_info_str = "NULL"
+
+ print '\t\t%s, %s, %s, %s, %s, %s },\n' % \
+ (ptvc_request, ptvc_reply, errors.Name(), req_conds,
+ req_cond_size, req_info_str)
+
+ print '\t{ 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NO_REQ_COND_SIZE, NULL }'
+ print "};\n"
+
+ print "/* ncp funcs that require a subfunc */"
+ print "static const guint8 ncp_func_requires_subfunc[] = {"
+ hi_seen = {}
+ for pkt in packets:
+ if pkt.HasSubFunction():
+ hi_func = pkt.FunctionCode('high')
+ if not hi_seen.has_key(hi_func):
+ print "\t0x%02x," % (hi_func)
+ hi_seen[hi_func] = 1
+ print "\t0"
+ print "};\n"
+
+
+ print "/* ncp funcs that have no length parameter */"
+ print "static const guint8 ncp_func_has_no_length_parameter[] = {"
+ funcs = funcs_without_length.keys()
+ funcs.sort()
+ for func in funcs:
+ print "\t0x%02x," % (func,)
+ print "\t0"
+ print "};\n"
+
+ # final_registration_ncp2222()
+ print """
+void
+final_registration_ncp2222(void)
+{
+ int i;
+ """
+
+ # Create dfilter_t's for conditional_record's
+ print """
+ for (i = 0; i < NUM_REQ_CONDS; i++) {
+ if (!dfilter_compile((const gchar*)req_conds[i].dfilter_text,
+ &req_conds[i].dfilter)) {
+ g_message("NCP dissector failed to compiler dfilter: %s\\n",
+ req_conds[i].dfilter_text);
+ g_assert_not_reached();
+ }
+ }
+}
+ """
+
+ # proto_register_ncp2222()
+ print """
+static const value_string ncp_nds_verb_vals[] = {
+ { 1, "Resolve Name" },
+ { 2, "Read Entry Information" },
+ { 3, "Read" },
+ { 4, "Compare" },
+ { 5, "List" },
+ { 6, "Search Entries" },
+ { 7, "Add Entry" },
+ { 8, "Remove Entry" },
+ { 9, "Modify Entry" },
+ { 10, "Modify RDN" },
+ { 11, "Create Attribute" },
+ { 12, "Read Attribute Definition" },
+ { 13, "Remove Attribute Definition" },
+ { 14, "Define Class" },
+ { 15, "Read Class Definition" },
+ { 16, "Modify Class Definition" },
+ { 17, "Remove Class Definition" },
+ { 18, "List Containable Classes" },
+ { 19, "Get Effective Rights" },
+ { 20, "Add Partition" },
+ { 21, "Remove Partition" },
+ { 22, "List Partitions" },
+ { 23, "Split Partition" },
+ { 24, "Join Partitions" },
+ { 25, "Add Replica" },
+ { 26, "Remove Replica" },
+ { 27, "Open Stream" },
+ { 28, "Search Filter" },
+ { 29, "Create Subordinate Reference" },
+ { 30, "Link Replica" },
+ { 31, "Change Replica Type" },
+ { 32, "Start Update Schema" },
+ { 33, "End Update Schema" },
+ { 34, "Update Schema" },
+ { 35, "Start Update Replica" },
+ { 36, "End Update Replica" },
+ { 37, "Update Replica" },
+ { 38, "Synchronize Partition" },
+ { 39, "Synchronize Schema" },
+ { 40, "Read Syntaxes" },
+ { 41, "Get Replica Root ID" },
+ { 42, "Begin Move Entry" },
+ { 43, "Finish Move Entry" },
+ { 44, "Release Moved Entry" },
+ { 45, "Backup Entry" },
+ { 46, "Restore Entry" },
+ { 47, "Save DIB" },
+ { 48, "Control" },
+ { 49, "Remove Backlink" },
+ { 50, "Close Iteration" },
+ { 51, "Unused" },
+ { 52, "Audit Skulking" },
+ { 53, "Get Server Address" },
+ { 54, "Set Keys" },
+ { 55, "Change Password" },
+ { 56, "Verify Password" },
+ { 57, "Begin Login" },
+ { 58, "Finish Login" },
+ { 59, "Begin Authentication" },
+ { 60, "Finish Authentication" },
+ { 61, "Logout" },
+ { 62, "Repair Ring" },
+ { 63, "Repair Timestamps" },
+ { 64, "Create Back Link" },
+ { 65, "Delete External Reference" },
+ { 66, "Rename External Reference" },
+ { 67, "Create Directory Entry" },
+ { 68, "Remove Directory Entry" },
+ { 69, "Designate New Master" },
+ { 70, "Change Tree Name" },
+ { 71, "Partition Entry Count" },
+ { 72, "Check Login Restrictions" },
+ { 73, "Start Join" },
+ { 74, "Low Level Split" },
+ { 75, "Low Level Join" },
+ { 76, "Abort Low Level Join" },
+ { 77, "Get All Servers" },
+ { 255, "EDirectory Call" },
+ { 0, NULL }
+};
+
+void
+proto_register_ncp2222(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_ncp_func,
+ { "Function", "ncp.func", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_length,
+ { "Packet Length", "ncp.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_subfunc,
+ { "SubFunction", "ncp.subfunc", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_completion_code,
+ { "Completion Code", "ncp.completion_code", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_fragment_handle,
+ { "NDS Fragment Handle", "ncp.ndsfrag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_fragment_size,
+ { "NDS Fragment Size", "ncp.ndsfragsize", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_message_size,
+ { "Message Size", "ncp.ndsmessagesize", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_nds_flag,
+ { "Flags", "ncp.ndsflag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_nds_verb,
+ { "NDS Verb", "ncp.ndsverb", FT_UINT8, BASE_HEX, VALS(ncp_nds_verb_vals), 0x0, "", HFILL }},
+
+ { &hf_ping_version,
+ { "NDS Version", "ncp.ping_version", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_version,
+ { "NDS Version", "ncp.nds_version", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_tree_name,
+ { "Tree Name", "ncp.nds_tree_name", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ /*
+ * XXX - the page at
+ *
+ * http://www.odyssea.com/whats_new/tcpipnet/tcpipnet.html
+ *
+ * says of the connection status "The Connection Code field may
+ * contain values that indicate the status of the client host to
+ * server connection. A value of 1 in the fourth bit of this data
+ * byte indicates that the server is unavailable (server was
+ * downed).
+ *
+ * The page at
+ *
+ * http://www.unm.edu/~network/presentations/course/appendix/appendix_f/tsld088.htm
+ *
+ * says that bit 0 is "bad service", bit 2 is "no connection
+ * available", bit 4 is "service down", and bit 6 is "server
+ * has a broadcast message waiting for the client".
+ *
+ * Should it be displayed in hex, and should those bits (and any
+ * other bits with significance) be displayed as bitfields
+ * underneath it?
+ */
+ { &hf_ncp_connection_status,
+ { "Connection Status", "ncp.connection_status", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_req_frame_num,
+ { "Response to Request in Frame Number", "ncp.req_frame_num", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_ncp_req_frame_time,
+ { "Time from Request", "ncp.time", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0x0, "Time between request and response in seconds", HFILL }},
+
+ { &hf_nds_flags,
+ { "NDS Return Flags", "ncp.nds_flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+
+ { &hf_nds_reply_depth,
+ { "Distance from Root", "ncp.ndsdepth", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_reply_rev,
+ { "NDS Revision", "ncp.ndsrev", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_reply_flags,
+ { "Flags", "ncp.ndsflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_p1type,
+ { "NDS Parameter Type", "ncp.p1type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_uint32value,
+ { "NDS Value", "ncp.uint32value", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_bit1,
+ { "Typeless", "ncp.nds_bit1", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_nds_bit2,
+ { "All Containers", "ncp.nds_bit2", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_nds_bit3,
+ { "Slashed", "ncp.nds_bit3", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_nds_bit4,
+ { "Dotted", "ncp.nds_bit4", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_nds_bit5,
+ { "Tuned", "ncp.nds_bit5", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_nds_bit6,
+ { "Not Defined", "ncp.nds_bit6", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_nds_bit7,
+ { "Not Defined", "ncp.nds_bit7", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_nds_bit8,
+ { "Not Defined", "ncp.nds_bit8", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_nds_bit9,
+ { "Not Defined", "ncp.nds_bit9", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_nds_bit10,
+ { "Not Defined", "ncp.nds_bit10", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_nds_bit11,
+ { "Not Defined", "ncp.nds_bit11", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_nds_bit12,
+ { "Not Defined", "ncp.nds_bit12", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_nds_bit13,
+ { "Not Defined", "ncp.nds_bit13", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_nds_bit14,
+ { "Not Defined", "ncp.nds_bit14", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_nds_bit15,
+ { "Not Defined", "ncp.nds_bit15", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_nds_bit16,
+ { "Not Defined", "ncp.nds_bit16", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1outflags,
+ { "Output Flags", "ncp.bit1outflags", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2outflags,
+ { "Entry ID", "ncp.bit2outflags", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3outflags,
+ { "Replica State", "ncp.bit3outflags", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4outflags,
+ { "Modification Timestamp", "ncp.bit4outflags", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5outflags,
+ { "Purge Time", "ncp.bit5outflags", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6outflags,
+ { "Local Partition ID", "ncp.bit6outflags", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7outflags,
+ { "Distinguished Name", "ncp.bit7outflags", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8outflags,
+ { "Replica Type", "ncp.bit8outflags", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9outflags,
+ { "Partition Busy", "ncp.bit9outflags", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10outflags,
+ { "Not Defined", "ncp.bit10outflags", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11outflags,
+ { "Not Defined", "ncp.bit11outflags", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12outflags,
+ { "Not Defined", "ncp.bit12outflags", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13outflags,
+ { "Not Defined", "ncp.bit13outflags", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14outflags,
+ { "Not Defined", "ncp.bit14outflags", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15outflags,
+ { "Not Defined", "ncp.bit15outflags", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16outflags,
+ { "Not Defined", "ncp.bit16outflags", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1nflags,
+ { "Entry ID", "ncp.bit1nflags", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2nflags,
+ { "Readable", "ncp.bit2nflags", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3nflags,
+ { "Writeable", "ncp.bit3nflags", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4nflags,
+ { "Master", "ncp.bit4nflags", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5nflags,
+ { "Create ID", "ncp.bit5nflags", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6nflags,
+ { "Walk Tree", "ncp.bit6nflags", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7nflags,
+ { "Dereference Alias", "ncp.bit7nflags", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8nflags,
+ { "Not Defined", "ncp.bit8nflags", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9nflags,
+ { "Not Defined", "ncp.bit9nflags", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10nflags,
+ { "Not Defined", "ncp.bit10nflags", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11nflags,
+ { "Not Defined", "ncp.bit11nflags", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12nflags,
+ { "Not Defined", "ncp.bit12nflags", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13nflags,
+ { "Not Defined", "ncp.bit13nflags", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14nflags,
+ { "Prefer Referrals", "ncp.bit14nflags", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15nflags,
+ { "Prefer Only Referrals", "ncp.bit15nflags", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16nflags,
+ { "Not Defined", "ncp.bit16nflags", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1rflags,
+ { "Typeless", "ncp.bit1rflags", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2rflags,
+ { "Slashed", "ncp.bit2rflags", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3rflags,
+ { "Dotted", "ncp.bit3rflags", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4rflags,
+ { "Tuned", "ncp.bit4rflags", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5rflags,
+ { "Not Defined", "ncp.bit5rflags", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6rflags,
+ { "Not Defined", "ncp.bit6rflags", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7rflags,
+ { "Not Defined", "ncp.bit7rflags", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8rflags,
+ { "Not Defined", "ncp.bit8rflags", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9rflags,
+ { "Not Defined", "ncp.bit9rflags", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10rflags,
+ { "Not Defined", "ncp.bit10rflags", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11rflags,
+ { "Not Defined", "ncp.bit11rflags", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12rflags,
+ { "Not Defined", "ncp.bit12rflags", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13rflags,
+ { "Not Defined", "ncp.bit13rflags", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14rflags,
+ { "Not Defined", "ncp.bit14rflags", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15rflags,
+ { "Not Defined", "ncp.bit15rflags", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16rflags,
+ { "Not Defined", "ncp.bit16rflags", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1eflags,
+ { "Alias Entry", "ncp.bit1eflags", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2eflags,
+ { "Partition Root", "ncp.bit2eflags", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3eflags,
+ { "Container Entry", "ncp.bit3eflags", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4eflags,
+ { "Container Alias", "ncp.bit4eflags", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5eflags,
+ { "Matches List Filter", "ncp.bit5eflags", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6eflags,
+ { "Reference Entry", "ncp.bit6eflags", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7eflags,
+ { "40x Reference Entry", "ncp.bit7eflags", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8eflags,
+ { "Back Linked", "ncp.bit8eflags", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9eflags,
+ { "New Entry", "ncp.bit9eflags", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10eflags,
+ { "Temporary Reference", "ncp.bit10eflags", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11eflags,
+ { "Audited", "ncp.bit11eflags", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12eflags,
+ { "Entry Not Present", "ncp.bit12eflags", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13eflags,
+ { "Entry Verify CTS", "ncp.bit13eflags", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14eflags,
+ { "Entry Damaged", "ncp.bit14eflags", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15eflags,
+ { "Not Defined", "ncp.bit15rflags", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16eflags,
+ { "Not Defined", "ncp.bit16rflags", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1infoflagsl,
+ { "Output Flags", "ncp.bit1infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2infoflagsl,
+ { "Entry ID", "ncp.bit2infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3infoflagsl,
+ { "Entry Flags", "ncp.bit3infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4infoflagsl,
+ { "Subordinate Count", "ncp.bit4infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5infoflagsl,
+ { "Modification Time", "ncp.bit5infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6infoflagsl,
+ { "Modification Timestamp", "ncp.bit6infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7infoflagsl,
+ { "Creation Timestamp", "ncp.bit7infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8infoflagsl,
+ { "Partition Root ID", "ncp.bit8infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9infoflagsl,
+ { "Parent ID", "ncp.bit9infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10infoflagsl,
+ { "Revision Count", "ncp.bit10infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11infoflagsl,
+ { "Replica Type", "ncp.bit11infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12infoflagsl,
+ { "Base Class", "ncp.bit12infoflagsl", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13infoflagsl,
+ { "Relative Distinguished Name", "ncp.bit13infoflagsl", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14infoflagsl,
+ { "Distinguished Name", "ncp.bit14infoflagsl", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15infoflagsl,
+ { "Root Distinguished Name", "ncp.bit15infoflagsl", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16infoflagsl,
+ { "Parent Distinguished Name", "ncp.bit16infoflagsl", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1infoflagsh,
+ { "Purge Time", "ncp.bit1infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2infoflagsh,
+ { "Dereference Base Class", "ncp.bit2infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3infoflagsh,
+ { "Not Defined", "ncp.bit3infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4infoflagsh,
+ { "Not Defined", "ncp.bit4infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5infoflagsh,
+ { "Not Defined", "ncp.bit5infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6infoflagsh,
+ { "Not Defined", "ncp.bit6infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7infoflagsh,
+ { "Not Defined", "ncp.bit7infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8infoflagsh,
+ { "Not Defined", "ncp.bit8infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9infoflagsh,
+ { "Not Defined", "ncp.bit9infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10infoflagsh,
+ { "Not Defined", "ncp.bit10infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11infoflagsh,
+ { "Not Defined", "ncp.bit11infoflagsh", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12infoflagsh,
+ { "Not Defined", "ncp.bit12infoflagshs", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13infoflagsh,
+ { "Not Defined", "ncp.bit13infoflagsh", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14infoflagsh,
+ { "Not Defined", "ncp.bit14infoflagsh", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15infoflagsh,
+ { "Not Defined", "ncp.bit15infoflagsh", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16infoflagsh,
+ { "Not Defined", "ncp.bit16infoflagsh", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1lflags,
+ { "List Typeless", "ncp.bit1lflags", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2lflags,
+ { "List Containers", "ncp.bit2lflags", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3lflags,
+ { "List Slashed", "ncp.bit3lflags", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4lflags,
+ { "List Dotted", "ncp.bit4lflags", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5lflags,
+ { "Dereference Alias", "ncp.bit5lflags", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6lflags,
+ { "List All Containers", "ncp.bit6lflags", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7lflags,
+ { "List Obsolete", "ncp.bit7lflags", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8lflags,
+ { "List Tuned Output", "ncp.bit8lflags", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9lflags,
+ { "List External Reference", "ncp.bit9lflags", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10lflags,
+ { "Not Defined", "ncp.bit10lflags", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11lflags,
+ { "Not Defined", "ncp.bit11lflags", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12lflags,
+ { "Not Defined", "ncp.bit12lflags", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13lflags,
+ { "Not Defined", "ncp.bit13lflags", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14lflags,
+ { "Not Defined", "ncp.bit14lflags", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15lflags,
+ { "Not Defined", "ncp.bit15lflags", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16lflags,
+ { "Not Defined", "ncp.bit16lflags", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1l1flagsl,
+ { "Output Flags", "ncp.bit1l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2l1flagsl,
+ { "Entry ID", "ncp.bit2l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3l1flagsl,
+ { "Replica State", "ncp.bit3l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4l1flagsl,
+ { "Modification Timestamp", "ncp.bit4l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5l1flagsl,
+ { "Purge Time", "ncp.bit5l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6l1flagsl,
+ { "Local Partition ID", "ncp.bit6l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7l1flagsl,
+ { "Distinguished Name", "ncp.bit7l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8l1flagsl,
+ { "Replica Type", "ncp.bit8l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9l1flagsl,
+ { "Partition Busy", "ncp.bit9l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10l1flagsl,
+ { "Not Defined", "ncp.bit10l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11l1flagsl,
+ { "Not Defined", "ncp.bit11l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12l1flagsl,
+ { "Not Defined", "ncp.bit12l1flagsl", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13l1flagsl,
+ { "Not Defined", "ncp.bit13l1flagsl", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14l1flagsl,
+ { "Not Defined", "ncp.bit14l1flagsl", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15l1flagsl,
+ { "Not Defined", "ncp.bit15l1flagsl", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16l1flagsl,
+ { "Not Defined", "ncp.bit16l1flagsl", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1l1flagsh,
+ { "Not Defined", "ncp.bit1l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2l1flagsh,
+ { "Not Defined", "ncp.bit2l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3l1flagsh,
+ { "Not Defined", "ncp.bit3l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4l1flagsh,
+ { "Not Defined", "ncp.bit4l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5l1flagsh,
+ { "Not Defined", "ncp.bit5l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6l1flagsh,
+ { "Not Defined", "ncp.bit6l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7l1flagsh,
+ { "Not Defined", "ncp.bit7l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8l1flagsh,
+ { "Not Defined", "ncp.bit8l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9l1flagsh,
+ { "Not Defined", "ncp.bit9l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10l1flagsh,
+ { "Not Defined", "ncp.bit10l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11l1flagsh,
+ { "Not Defined", "ncp.bit11l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12l1flagsh,
+ { "Not Defined", "ncp.bit12l1flagsh", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13l1flagsh,
+ { "Not Defined", "ncp.bit13l1flagsh", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14l1flagsh,
+ { "Not Defined", "ncp.bit14l1flagsh", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15l1flagsh,
+ { "Not Defined", "ncp.bit15l1flagsh", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16l1flagsh,
+ { "Not Defined", "ncp.bit16l1flagsh", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1vflags,
+ { "Naming", "ncp.bit1vflags", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2vflags,
+ { "Base Class", "ncp.bit2vflags", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3vflags,
+ { "Present", "ncp.bit3vflags", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4vflags,
+ { "Value Damaged", "ncp.bit4vflags", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5vflags,
+ { "Not Defined", "ncp.bit5vflags", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6vflags,
+ { "Not Defined", "ncp.bit6vflags", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7vflags,
+ { "Not Defined", "ncp.bit7vflags", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8vflags,
+ { "Not Defined", "ncp.bit8vflags", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9vflags,
+ { "Not Defined", "ncp.bit9vflags", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10vflags,
+ { "Not Defined", "ncp.bit10vflags", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11vflags,
+ { "Not Defined", "ncp.bit11vflags", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12vflags,
+ { "Not Defined", "ncp.bit12vflags", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13vflags,
+ { "Not Defined", "ncp.bit13vflags", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14vflags,
+ { "Not Defined", "ncp.bit14vflags", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15vflags,
+ { "Not Defined", "ncp.bit15vflags", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16vflags,
+ { "Not Defined", "ncp.bit16vflags", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1cflags,
+ { "Ambiguous Containment", "ncp.bit1cflags", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2cflags,
+ { "Ambiguous Naming", "ncp.bit2cflags", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3cflags,
+ { "Class Definition Cannot be Removed", "ncp.bit3cflags", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4cflags,
+ { "Effective Class", "ncp.bit4cflags", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5cflags,
+ { "Container Class", "ncp.bit5cflags", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6cflags,
+ { "Not Defined", "ncp.bit6cflags", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7cflags,
+ { "Not Defined", "ncp.bit7cflags", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8cflags,
+ { "Not Defined", "ncp.bit8cflags", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9cflags,
+ { "Not Defined", "ncp.bit9cflags", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10cflags,
+ { "Not Defined", "ncp.bit10cflags", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11cflags,
+ { "Not Defined", "ncp.bit11cflags", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12cflags,
+ { "Not Defined", "ncp.bit12cflags", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13cflags,
+ { "Not Defined", "ncp.bit13cflags", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14cflags,
+ { "Not Defined", "ncp.bit14cflags", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15cflags,
+ { "Not Defined", "ncp.bit15cflags", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16cflags,
+ { "Not Defined", "ncp.bit16cflags", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1acflags,
+ { "Single Valued", "ncp.bit1acflags", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2acflags,
+ { "Sized", "ncp.bit2acflags", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3acflags,
+ { "Non-Removable", "ncp.bit3acflags", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4acflags,
+ { "Read Only", "ncp.bit4acflags", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5acflags,
+ { "Hidden", "ncp.bit5acflags", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6acflags,
+ { "String", "ncp.bit6acflags", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7acflags,
+ { "Synchronize Immediate", "ncp.bit7acflags", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8acflags,
+ { "Public Read", "ncp.bit8acflags", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9acflags,
+ { "Server Read", "ncp.bit9acflags", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10acflags,
+ { "Write Managed", "ncp.bit10acflags", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11acflags,
+ { "Per Replica", "ncp.bit11acflags", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12acflags,
+ { "Never Schedule Synchronization", "ncp.bit12acflags", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13acflags,
+ { "Operational", "ncp.bit13acflags", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14acflags,
+ { "Not Defined", "ncp.bit14acflags", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15acflags,
+ { "Not Defined", "ncp.bit15acflags", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16acflags,
+ { "Not Defined", "ncp.bit16acflags", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+
+ { &hf_nds_reply_error,
+ { "NDS Error", "ncp.ndsreplyerror", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_net,
+ { "Network","ncp.ndsnet", FT_IPXNET, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_node,
+ { "Node", "ncp.ndsnode", FT_ETHER, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_socket,
+ { "Socket", "ncp.ndssocket", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_add_ref_ip,
+ { "Address Referral", "ncp.ipref", FT_IPv4, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_add_ref_udp,
+ { "Address Referral", "ncp.udpref", FT_IPv4, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_add_ref_tcp,
+ { "Address Referral", "ncp.tcpref", FT_IPv4, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_referral_record,
+ { "Referral Record", "ncp.ref_rec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_referral_addcount,
+ { "Address Count", "ncp.ref_addcount", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_port,
+ { "Port", "ncp.ndsport", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_mv_string,
+ { "Attribute Name ", "ncp.mv_string", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_syntax,
+ { "Attribute Syntax ", "ncp.nds_syntax", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_value_string,
+ { "Value ", "ncp.value_string", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_stream_name,
+ { "Stream Name ", "ncp.nds_stream_name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_buffer_size,
+ { "NDS Reply Buffer Size", "ncp.nds_reply_buf", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_ver,
+ { "NDS Version", "ncp.nds_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_nflags,
+ { "Flags", "ncp.nds_nflags", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_rflags,
+ { "Request Flags", "ncp.nds_rflags", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_eflags,
+ { "Entry Flags", "ncp.nds_eflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_scope,
+ { "Scope", "ncp.nds_scope", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_name,
+ { "Name", "ncp.nds_name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_name_type,
+ { "Name Type", "ncp.nds_name_type", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_comm_trans,
+ { "Communications Transport", "ncp.nds_comm_trans", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_tree_trans,
+ { "Tree Walker Transport", "ncp.nds_tree_trans", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_iteration,
+ { "Iteration Handle", "ncp.nds_iteration", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_file_handle,
+ { "File Handle", "ncp.nds_file_handle", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_file_size,
+ { "File Size", "ncp.nds_file_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_eid,
+ { "NDS EID", "ncp.nds_eid", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_depth,
+ { "Distance object is from Root", "ncp.nds_depth", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_info_type,
+ { "Info Type", "ncp.nds_info_type", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_class_def_type,
+ { "Class Definition Type", "ncp.nds_class_def_type", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_all_attr,
+ { "All Attributes", "ncp.nds_all_attr", FT_UINT32, BASE_DEC, NULL, 0x0, "Return all Attributes?", HFILL }},
+
+ { &hf_nds_return_all_classes,
+ { "All Classes", "ncp.nds_return_all_classes", FT_STRING, BASE_NONE, NULL, 0x0, "Return all Classes?", HFILL }},
+
+ { &hf_nds_req_flags,
+ { "Request Flags", "ncp.nds_req_flags", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_attr,
+ { "Attributes", "ncp.nds_attributes", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_classes,
+ { "Classes", "ncp.nds_classes", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_crc,
+ { "CRC", "ncp.nds_crc", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_referrals,
+ { "Referrals", "ncp.nds_referrals", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_result_flags,
+ { "Result Flags", "ncp.nds_result_flags", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_stream_flags,
+ { "Streams Flags", "ncp.nds_stream_flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_tag_string,
+ { "Tags", "ncp.nds_tags", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_value_bytes,
+ { "Bytes", "ncp.value_bytes", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_replica_type,
+ { "Replica Type", "ncp.rtype", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_replica_state,
+ { "Replica State", "ncp.rstate", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_rnum,
+ { "Replica Number", "ncp.rnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_revent,
+ { "Event", "ncp.revent", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_replica_number,
+ { "Replica Number", "ncp.rnum", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_min_nds_ver,
+ { "Minimum NDS Version", "ncp.min_nds_version", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_ver_include,
+ { "Include NDS Version", "ncp.inc_nds_ver", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_ver_exclude,
+ { "Exclude NDS Version", "ncp.exc_nds_ver", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_es,
+ { "Input Entry Specifier", "ncp.nds_es", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_es_type,
+ { "Entry Specifier Type", "ncp.nds_es_type", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_rdn_string,
+ { "RDN", "ncp.nds_rdn", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_delim_string,
+ { "Delimeter", "ncp.nds_delim", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_dn_output_type,
+ { "Output Entry Specifier Type", "ncp.nds_out_es_type", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_nested_output_type,
+ { "Nested Output Entry Specifier Type", "ncp.nds_nested_out_es", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_output_delimiter,
+ { "Output Delimiter", "ncp.nds_out_delimiter", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_output_entry_specifier,
+ { "Output Entry Specifier", "ncp.nds_out_es", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_es_value,
+ { "Entry Specifier Value", "ncp.nds_es_value", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_es_rdn_count,
+ { "RDN Count", "ncp.nds_es_rdn_count", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_replica_num,
+ { "Replica Number", "ncp.nds_replica_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_es_seconds,
+ { "Seconds", "ncp.nds_es_seconds", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_event_num,
+ { "Event Number", "ncp.nds_event_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_compare_results,
+ { "Compare Results", "ncp.nds_compare_results", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_parent,
+ { "Parent ID", "ncp.nds_parent", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_name_filter,
+ { "Name Filter", "ncp.nds_name_filter", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_class_filter,
+ { "Class Filter", "ncp.nds_class_filter", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_time_filter,
+ { "Time Filter", "ncp.nds_time_filter", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_partition_root_id,
+ { "Partition Root ID", "ncp.nds_partition_root_id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_replicas,
+ { "Replicas", "ncp.nds_replicas", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_purge,
+ { "Purge Time", "ncp.nds_purge", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_local_partition,
+ { "Local Partition ID", "ncp.nds_local_partition", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_partition_busy,
+ { "Partition Busy", "ncp.nds_partition_busy", FT_BOOLEAN, 16, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_number_of_changes,
+ { "Number of Attribute Changes", "ncp.nds_number_of_changes", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sub_count,
+ { "Subordinate Count", "ncp.sub_count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_revision,
+ { "Revision Count", "ncp.nds_rev_count", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_base_class,
+ { "Base Class", "ncp.nds_base_class", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_relative_dn,
+ { "Relative Distinguished Name", "ncp.nds_relative_dn", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_root_dn,
+ { "Root Distinguished Name", "ncp.nds_root_dn", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_parent_dn,
+ { "Parent Distinguished Name", "ncp.nds_parent_dn", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_deref_base,
+ { "Dereference Base Class", "ncp.nds_deref_base", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_base,
+ { "Base Class", "ncp.nds_base", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_super,
+ { "Super Class", "ncp.nds_super", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_entry_info,
+ { "Entry Information", "ncp.nds_entry_info", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_privileges,
+ { "Privileges", "ncp.nds_privileges", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_vflags,
+ { "Value Flags", "ncp.nds_vflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_value_len,
+ { "Value Length", "ncp.nds_vlength", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_cflags,
+ { "Class Flags", "ncp.nds_cflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_asn1,
+ { "ASN.1 ID", "ncp.nds_asn1", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_acflags,
+ { "Attribute Constraint Flags", "ncp.nds_acflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_upper,
+ { "Upper Limit Value", "ncp.nds_upper", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_lower,
+ { "Lower Limit Value", "ncp.nds_lower", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_trustee_dn,
+ { "Trustee Distinguished Name", "ncp.nds_trustee_dn", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_attribute_dn,
+ { "Attribute Name", "ncp.nds_attribute_dn", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_acl_add,
+ { "Access Control Lists to Add", "ncp.nds_acl_add", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_acl_del,
+ { "Access Control Lists to Delete", "ncp.nds_acl_del", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_att_add,
+ { "Attribute to Add", "ncp.nds_att_add", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_att_del,
+ { "Attribute to Delete", "ncp.nds_att_del", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_keep,
+ { "Delete Original RDN", "ncp.nds_keep", FT_BOOLEAN, 32, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_new_rdn,
+ { "New Relative Distinguished Name", "ncp.nds_new_rdn", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_time_delay,
+ { "Time Delay", "ncp.nds_time_delay", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_root_name,
+ { "Root Most Object Name", "ncp.nds_root_name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_new_part_id,
+ { "New Partition Root ID", "ncp.nds_new_part_id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_child_part_id,
+ { "Child Partition Root ID", "ncp.nds_child_part_id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_master_part_id,
+ { "Master Partition Root ID", "ncp.nds_master_part_id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_target_name,
+ { "Target Server Name", "ncp.nds_target_dn", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+
+ { &hf_bit1pingflags1,
+ { "Supported Fields", "ncp.bit1pingflags1", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2pingflags1,
+ { "Depth", "ncp.bit2pingflags1", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3pingflags1,
+ { "Revision", "ncp.bit3pingflags1", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4pingflags1,
+ { "Flags", "ncp.bit4pingflags1", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5pingflags1,
+ { "Verification Flags", "ncp.bit5pingflags1", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6pingflags1,
+ { "Letter Version", "ncp.bit6pingflags1", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7pingflags1,
+ { "OS Version", "ncp.bit7pingflags1", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8pingflags1,
+ { "License Flags", "ncp.bit8pingflags1", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9pingflags1,
+ { "DS Time", "ncp.bit9pingflags1", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10pingflags1,
+ { "Not Defined", "ncp.bit10pingflags1", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11pingflags1,
+ { "Not Defined", "ncp.bit11pingflags1", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12pingflags1,
+ { "Not Defined", "ncp.bit12pingflags1", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13pingflags1,
+ { "Not Defined", "ncp.bit13pingflags1", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14pingflags1,
+ { "Not Defined", "ncp.bit14pingflags1", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15pingflags1,
+ { "Not Defined", "ncp.bit15pingflags1", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16pingflags1,
+ { "Not Defined", "ncp.bit16pingflags1", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1pingflags2,
+ { "Sap Name", "ncp.bit1pingflags2", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2pingflags2,
+ { "Tree Name", "ncp.bit2pingflags2", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3pingflags2,
+ { "OS Name", "ncp.bit3pingflags2", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4pingflags2,
+ { "Hardware Name", "ncp.bit4pingflags2", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5pingflags2,
+ { "Vendor Name", "ncp.bit5pingflags2", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6pingflags2,
+ { "Not Defined", "ncp.bit6pingflags2", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7pingflags2,
+ { "Not Defined", "ncp.bit7pingflags2", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8pingflags2,
+ { "Not Defined", "ncp.bit8pingflags2", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9pingflags2,
+ { "Not Defined", "ncp.bit9pingflags2", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10pingflags2,
+ { "Not Defined", "ncp.bit10pingflags2", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11pingflags2,
+ { "Not Defined", "ncp.bit11pingflags2", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12pingflags2,
+ { "Not Defined", "ncp.bit12pingflags2", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13pingflags2,
+ { "Not Defined", "ncp.bit13pingflags2", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14pingflags2,
+ { "Not Defined", "ncp.bit14pingflags2", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15pingflags2,
+ { "Not Defined", "ncp.bit15pingflags2", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16pingflags2,
+ { "Not Defined", "ncp.bit16pingflags2", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1pingpflags1,
+ { "Root Most Master Replica", "ncp.bit1pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2pingpflags1,
+ { "Time Synchronized", "ncp.bit2pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3pingpflags1,
+ { "Not Defined", "ncp.bit3pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4pingpflags1,
+ { "Not Defined", "ncp.bit4pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5pingpflags1,
+ { "Not Defined", "ncp.bit5pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6pingpflags1,
+ { "Not Defined", "ncp.bit6pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7pingpflags1,
+ { "Not Defined", "ncp.bit7pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8pingpflags1,
+ { "Not Defined", "ncp.bit8pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9pingpflags1,
+ { "Not Defined", "ncp.bit9pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10pingpflags1,
+ { "Not Defined", "ncp.bit10pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11pingpflags1,
+ { "Not Defined", "ncp.bit11pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12pingpflags1,
+ { "Not Defined", "ncp.bit12pingpflags1", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13pingpflags1,
+ { "Not Defined", "ncp.bit13pingpflags1", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14pingpflags1,
+ { "Not Defined", "ncp.bit14pingpflags1", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15pingpflags1,
+ { "Not Defined", "ncp.bit15pingpflags1", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16pingpflags1,
+ { "Not Defined", "ncp.bit16pingpflags1", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_bit1pingvflags1,
+ { "Checksum", "ncp.bit1pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2pingvflags1,
+ { "CRC32", "ncp.bit2pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3pingvflags1,
+ { "Not Defined", "ncp.bit3pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4pingvflags1,
+ { "Not Defined", "ncp.bit4pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5pingvflags1,
+ { "Not Defined", "ncp.bit5pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6pingvflags1,
+ { "Not Defined", "ncp.bit6pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7pingvflags1,
+ { "Not Defined", "ncp.bit7pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8pingvflags1,
+ { "Not Defined", "ncp.bit8pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9pingvflags1,
+ { "Not Defined", "ncp.bit9pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10pingvflags1,
+ { "Not Defined", "ncp.bit10pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11pingvflags1,
+ { "Not Defined", "ncp.bit11pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12pingvflags1,
+ { "Not Defined", "ncp.bit12pingvflags1", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13pingvflags1,
+ { "Not Defined", "ncp.bit13pingvflags1", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14pingvflags1,
+ { "Not Defined", "ncp.bit14pingvflags1", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15pingvflags1,
+ { "Not Defined", "ncp.bit15pingvflags1", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16pingvflags1,
+ { "Not Defined", "ncp.bit16pingvflags1", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_nds_letter_ver,
+ { "Letter Version", "ncp.nds_letter_ver", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_os_ver,
+ { "OS Version", "ncp.nds_os_ver", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_lic_flags,
+ { "License Flags", "ncp.nds_lic_flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_ds_time,
+ { "DS Time", "ncp.nds_ds_time", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_ping_version,
+ { "Ping Version", "ncp.nds_ping_version", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_search_scope,
+ { "Search Scope", "ncp.nds_search_scope", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_nds_num_objects,
+ { "Number of Objects to Search", "ncp.nds_num_objects", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+
+ { &hf_bit1siflags,
+ { "Names", "ncp.bit1siflags", FT_BOOLEAN, 16, NULL, 0x00000001, "", HFILL }},
+
+ { &hf_bit2siflags,
+ { "Names and Values", "ncp.bit2siflags", FT_BOOLEAN, 16, NULL, 0x00000002, "", HFILL }},
+
+ { &hf_bit3siflags,
+ { "Effective Privileges", "ncp.bit3siflags", FT_BOOLEAN, 16, NULL, 0x00000004, "", HFILL }},
+
+ { &hf_bit4siflags,
+ { "Value Info", "ncp.bit4siflags", FT_BOOLEAN, 16, NULL, 0x00000008, "", HFILL }},
+
+ { &hf_bit5siflags,
+ { "Abbreviated Value", "ncp.bit5siflags", FT_BOOLEAN, 16, NULL, 0x00000010, "", HFILL }},
+
+ { &hf_bit6siflags,
+ { "Not Defined", "ncp.bit6siflags", FT_BOOLEAN, 16, NULL, 0x00000020, "", HFILL }},
+
+ { &hf_bit7siflags,
+ { "Not Defined", "ncp.bit7siflags", FT_BOOLEAN, 16, NULL, 0x00000040, "", HFILL }},
+
+ { &hf_bit8siflags,
+ { "Not Defined", "ncp.bit8siflags", FT_BOOLEAN, 16, NULL, 0x00000080, "", HFILL }},
+
+ { &hf_bit9siflags,
+ { "Expanded Class", "ncp.bit9siflags", FT_BOOLEAN, 16, NULL, 0x00000100, "", HFILL }},
+
+ { &hf_bit10siflags,
+ { "Not Defined", "ncp.bit10siflags", FT_BOOLEAN, 16, NULL, 0x00000200, "", HFILL }},
+
+ { &hf_bit11siflags,
+ { "Not Defined", "ncp.bit11siflags", FT_BOOLEAN, 16, NULL, 0x00000400, "", HFILL }},
+
+ { &hf_bit12siflags,
+ { "Not Defined", "ncp.bit12siflags", FT_BOOLEAN, 16, NULL, 0x00000800, "", HFILL }},
+
+ { &hf_bit13siflags,
+ { "Not Defined", "ncp.bit13siflags", FT_BOOLEAN, 16, NULL, 0x00001000, "", HFILL }},
+
+ { &hf_bit14siflags,
+ { "Not Defined", "ncp.bit14siflags", FT_BOOLEAN, 16, NULL, 0x00002000, "", HFILL }},
+
+ { &hf_bit15siflags,
+ { "Not Defined", "ncp.bit15siflags", FT_BOOLEAN, 16, NULL, 0x00004000, "", HFILL }},
+
+ { &hf_bit16siflags,
+ { "Not Defined", "ncp.bit16siflags", FT_BOOLEAN, 16, NULL, 0x00008000, "", HFILL }},
+
+ { &hf_nds_segment_overlap,
+ { "Segment overlap", "nds.segment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Segment overlaps with other segments", HFILL }},
+
+ { &hf_nds_segment_overlap_conflict,
+ { "Conflicting data in segment overlap", "nds.segment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Overlapping segments contained conflicting data", HFILL }},
+
+ { &hf_nds_segment_multiple_tails,
+ { "Multiple tail segments found", "nds.segment.multipletails",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Several tails were found when desegmenting the packet", HFILL }},
+
+ { &hf_nds_segment_too_long_segment,
+ { "Segment too long", "nds.segment.toolongsegment", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Segment contained data past end of packet", HFILL }},
+
+ { &hf_nds_segment_error,
+ {"Desegmentation error", "nds.segment.error", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "Desegmentation error due to illegal segments", HFILL }},
+
+ { &hf_nds_segment,
+ { "NDS Fragment", "nds.fragment", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "NDPS Fragment", HFILL }},
+
+ { &hf_nds_segments,
+ { "NDS Fragments", "nds.fragments", FT_NONE, BASE_NONE,
+ NULL, 0x0, "NDPS Fragments", HFILL }},
+
+
+
+ """
+ # Print the registration code for the hf variables
+ for var in sorted_vars:
+ print "\t{ &%s," % (var.HFName())
+ print "\t{ \"%s\", \"%s\", %s, %s, %s, 0x%x, \"\", HFILL }},\n" % \
+ (var.Description(), var.DFilter(),
+ var.EtherealFType(), var.Display(), var.ValuesName(),
+ var.Mask())
+
+ print "\t};\n"
+
+ if ett_list:
+ print "\tstatic gint *ett[] = {"
+
+ for ett in ett_list:
+ print "\t\t&%s," % (ett,)
+
+ print "\t};\n"
+
+ print """
+ proto_register_field_array(proto_ncp, hf, array_length(hf));
+ """
+
+ if ett_list:
+ print """
+ proto_register_subtree_array(ett, array_length(ett));
+ """
+
+ print """
+ register_init_routine(&ncp_init_protocol);
+ register_postseq_cleanup_routine(&ncp_postseq_cleanup);
+ register_final_registration_routine(final_registration_ncp2222);
+ """
+
+
+ # End of proto_register_ncp2222()
+ print "}"
+ print ""
+ print '#include "packet-ncp2222.inc"'
+
+def usage():
+ print "Usage: ncp2222.py -o output_file"
+ sys.exit(1)
+
+def main():
+ global compcode_lists
+ global ptvc_lists
+ global msg
+
+ optstring = "o:"
+ out_filename = None
+
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], optstring)
+ except getopt.error:
+ usage()
+
+ for opt, arg in opts:
+ if opt == "-o":
+ out_filename = arg
+ else:
+ usage()
+
+ if len(args) != 0:
+ usage()
+
+ if not out_filename:
+ usage()
+
+ # Create the output file
+ try:
+ out_file = open(out_filename, "w")
+ except IOError, err:
+ sys.exit("Could not open %s for writing: %s" % (out_filename,
+ err))
+
+ # Set msg to current stdout
+ msg = sys.stdout
+
+ # Set stdout to the output file
+ sys.stdout = out_file
+
+ msg.write("Processing NCP definitions...\n")
+ # Run the code, and if we catch any exception,
+ # erase the output file.
+ try:
+ compcode_lists = UniqueCollection('Completion Code Lists')
+ ptvc_lists = UniqueCollection('PTVC Lists')
+
+ define_errors()
+ define_groups()
+
+ define_ncp2222()
+
+ msg.write("Defined %d NCP types.\n" % (len(packets),))
+ produce_code()
+ except:
+ traceback.print_exc(20, msg)
+ try:
+ out_file.close()
+ except IOError, err:
+ msg.write("Could not close %s: %s\n" % (out_filename, err))
+
+ try:
+ if os.path.exists(out_filename):
+ os.remove(out_filename)
+ except OSError, err:
+ msg.write("Could not remove %s: %s\n" % (out_filename, err))
+
+ sys.exit(1)
+
+
+
+def define_ncp2222():
+ ##############################################################################
+ # NCP Packets. Here I list functions and subfunctions in hexadecimal like the
+ # NCP book (and I believe LanAlyzer does this too).
+ # However, Novell lists these in decimal in their on-line documentation.
+ ##############################################################################
+ # 2222/01
+ pkt = NCP(0x01, "File Set Lock", 'file')
+ pkt.Request(7)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/02
+ pkt = NCP(0x02, "File Release Lock", 'file')
+ pkt.Request(7)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xff00])
+ # 2222/03
+ pkt = NCP(0x03, "Log File Exclusive", 'file')
+ pkt.Request( (12, 267), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, 1, LockFlag ),
+ rec( 9, 2, TimeoutLimit, BE ),
+ rec( 11, (1, 256), FilePath ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8200, 0x9600, 0xfe0d, 0xff01])
+ # 2222/04
+ pkt = NCP(0x04, "Lock File Set", 'file')
+ pkt.Request( 9, [
+ rec( 7, 2, TimeoutLimit ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xfe0d, 0xff01])
+ ## 2222/05
+ pkt = NCP(0x05, "Release File", 'file')
+ pkt.Request( (9, 264), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, (1, 256), FilePath ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9b00, 0x9c03, 0xff1a])
+ # 2222/06
+ pkt = NCP(0x06, "Release File Set", 'file')
+ pkt.Request( 8, [
+ rec( 7, 1, LockFlag ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/07
+ pkt = NCP(0x07, "Clear File", 'file')
+ pkt.Request( (9, 264), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, (1, 256), FilePath ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9b03, 0x9c03,
+ 0xa100, 0xfd00, 0xff1a])
+ # 2222/08
+ pkt = NCP(0x08, "Clear File Set", 'file')
+ pkt.Request( 8, [
+ rec( 7, 1, LockFlag ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/09
+ pkt = NCP(0x09, "Log Logical Record", 'file')
+ pkt.Request( (11, 138), [
+ rec( 7, 1, LockFlag ),
+ rec( 8, 2, TimeoutLimit, BE ),
+ rec( 10, (1, 128), LogicalRecordName ),
+ ], info_str=(LogicalRecordName, "Log Logical Record: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xfe0d, 0xff1a])
+ # 2222/0A, 10
+ pkt = NCP(0x0A, "Lock Logical Record Set", 'file')
+ pkt.Request( 10, [
+ rec( 7, 1, LockFlag ),
+ rec( 8, 2, TimeoutLimit ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xfe0d, 0xff1a])
+ # 2222/0B, 11
+ pkt = NCP(0x0B, "Clear Logical Record", 'file')
+ pkt.Request( (8, 135), [
+ rec( 7, (1, 128), LogicalRecordName ),
+ ], info_str=(LogicalRecordName, "Clear Logical Record: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xff1a])
+ # 2222/0C, 12
+ pkt = NCP(0x0C, "Release Logical Record", 'file')
+ pkt.Request( (8, 135), [
+ rec( 7, (1, 128), LogicalRecordName ),
+ ], info_str=(LogicalRecordName, "Release Logical Record: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xff1a])
+ # 2222/0D, 13
+ pkt = NCP(0x0D, "Release Logical Record Set", 'file')
+ pkt.Request( 8, [
+ rec( 7, 1, LockFlag ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/0E, 14
+ pkt = NCP(0x0E, "Clear Logical Record Set", 'file')
+ pkt.Request( 8, [
+ rec( 7, 1, LockFlag ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/1100, 17/00
+ pkt = NCP(0x1100, "Write to Spool File", 'qms')
+ pkt.Request( (11, 16), [
+ rec( 10, ( 1, 6 ), Data ),
+ ], info_str=(Data, "Write to Spool File: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0104, 0x8000, 0x8101, 0x8701, 0x8800,
+ 0x8d00, 0x8e00, 0x8f00, 0x9001, 0x9400, 0x9500,
+ 0x9600, 0x9804, 0x9900, 0xa100, 0xa201, 0xff19])
+ # 2222/1101, 17/01
+ pkt = NCP(0x1101, "Close Spool File", 'qms')
+ pkt.Request( 11, [
+ rec( 10, 1, AbortQueueFlag ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8701, 0x8800, 0x8d00,
+ 0x8e00, 0x8f00, 0x9001, 0x9300, 0x9400, 0x9500,
+ 0x9600, 0x9804, 0x9900, 0x9b03, 0x9c03, 0x9d00,
+ 0xa100, 0xd000, 0xd100, 0xd202, 0xd300, 0xd400,
+ 0xda01, 0xe800, 0xea00, 0xeb00, 0xec00, 0xfc06,
+ 0xfd00, 0xfe07, 0xff06])
+ # 2222/1102, 17/02
+ pkt = NCP(0x1102, "Set Spool File Flags", 'qms')
+ pkt.Request( 30, [
+ rec( 10, 1, PrintFlags ),
+ rec( 11, 1, TabSize ),
+ rec( 12, 1, TargetPrinter ),
+ rec( 13, 1, Copies ),
+ rec( 14, 1, FormType ),
+ rec( 15, 1, Reserved ),
+ rec( 16, 14, BannerName ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xd202, 0xd300, 0xe800, 0xea00,
+ 0xeb00, 0xec00, 0xfc06, 0xfe07, 0xff06])
+
+ # 2222/1103, 17/03
+ pkt = NCP(0x1103, "Spool A Disk File", 'qms')
+ pkt.Request( (12, 23), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, (1, 12), Data ),
+ ], info_str=(Data, "Spool a Disk File: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8701, 0x8800, 0x8d00,
+ 0x8e00, 0x8f00, 0x9001, 0x9300, 0x9400, 0x9500,
+ 0x9600, 0x9804, 0x9900, 0x9b03, 0x9c03, 0x9d00,
+ 0xa100, 0xd000, 0xd100, 0xd202, 0xd300, 0xd400,
+ 0xda01, 0xe800, 0xea00, 0xeb00, 0xec00, 0xfc06,
+ 0xfd00, 0xfe07, 0xff06])
+
+ # 2222/1106, 17/06
+ pkt = NCP(0x1106, "Get Printer Status", 'qms')
+ pkt.Request( 11, [
+ rec( 10, 1, TargetPrinter ),
+ ])
+ pkt.Reply(12, [
+ rec( 8, 1, PrinterHalted ),
+ rec( 9, 1, PrinterOffLine ),
+ rec( 10, 1, CurrentFormType ),
+ rec( 11, 1, RedirectedPrinter ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xfb05, 0xfd00, 0xff06])
+
+ # 2222/1109, 17/09
+ pkt = NCP(0x1109, "Create Spool File", 'qms')
+ pkt.Request( (12, 23), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, (1, 12), Data ),
+ ], info_str=(Data, "Create Spool File: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8400, 0x8701, 0x8d00,
+ 0x8f00, 0x9001, 0x9400, 0x9600, 0x9804, 0x9900,
+ 0x9b03, 0x9c03, 0xa100, 0xd000, 0xd100, 0xd202,
+ 0xd300, 0xd400, 0xda01, 0xe800, 0xea00, 0xeb00,
+ 0xec00, 0xfc06, 0xfd00, 0xfe07, 0xff06])
+
+ # 2222/110A, 17/10
+ pkt = NCP(0x110A, "Get Printer's Queue", 'qms')
+ pkt.Request( 11, [
+ rec( 10, 1, TargetPrinter ),
+ ])
+ pkt.Reply( 12, [
+ rec( 8, 4, ObjectID, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xff06])
+
+ # 2222/12, 18
+ pkt = NCP(0x12, "Get Volume Info with Number", 'file')
+ pkt.Request( 8, [
+ rec( 7, 1, VolumeNumber )
+ ],info_str=(VolumeNumber, "Get Volume Information for Volume %d", ", %d"))
+ pkt.Reply( 36, [
+ rec( 8, 2, SectorsPerCluster, BE ),
+ rec( 10, 2, TotalVolumeClusters, BE ),
+ rec( 12, 2, AvailableClusters, BE ),
+ rec( 14, 2, TotalDirectorySlots, BE ),
+ rec( 16, 2, AvailableDirectorySlots, BE ),
+ rec( 18, 16, VolumeName ),
+ rec( 34, 2, RemovableFlag, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9804])
+
+ # 2222/13, 19
+ pkt = NCP(0x13, "Get Station Number", 'connection')
+ pkt.Request(7)
+ pkt.Reply(11, [
+ rec( 8, 3, StationNumber )
+ ])
+ pkt.CompletionCodes([0x0000, 0xff00])
+
+ # 2222/14, 20
+ pkt = NCP(0x14, "Get File Server Date And Time", 'fileserver')
+ pkt.Request(7)
+ pkt.Reply(15, [
+ rec( 8, 1, Year ),
+ rec( 9, 1, Month ),
+ rec( 10, 1, Day ),
+ rec( 11, 1, Hour ),
+ rec( 12, 1, Minute ),
+ rec( 13, 1, Second ),
+ rec( 14, 1, DayOfWeek ),
+ ])
+ pkt.CompletionCodes([0x0000])
+
+ # 2222/1500, 21/00
+ pkt = NCP(0x1500, "Send Broadcast Message", 'message')
+ pkt.Request((13, 70), [
+ rec( 10, 1, ClientListLen, var="x" ),
+ rec( 11, 1, TargetClientList, repeat="x" ),
+ rec( 12, (1, 58), TargetMessage ),
+ ], info_str=(TargetMessage, "Send Broadcast Message: %s", ", %s"))
+ pkt.Reply(10, [
+ rec( 8, 1, ClientListLen, var="x" ),
+ rec( 9, 1, SendStatus, repeat="x" )
+ ])
+ pkt.CompletionCodes([0x0000, 0xfd00])
+
+ # 2222/1501, 21/01
+ pkt = NCP(0x1501, "Get Broadcast Message", 'message')
+ pkt.Request(10)
+ pkt.Reply((9,66), [
+ rec( 8, (1, 58), TargetMessage )
+ ])
+ pkt.CompletionCodes([0x0000, 0xfd00])
+
+ # 2222/1502, 21/02
+ pkt = NCP(0x1502, "Disable Broadcasts", 'message')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xfb0a])
+
+ # 2222/1503, 21/03
+ pkt = NCP(0x1503, "Enable Broadcasts", 'message')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+
+ # 2222/1509, 21/09
+ pkt = NCP(0x1509, "Broadcast To Console", 'message')
+ pkt.Request((11, 68), [
+ rec( 10, (1, 58), TargetMessage )
+ ], info_str=(TargetMessage, "Broadcast to Console: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/150A, 21/10
+ pkt = NCP(0x150A, "Send Broadcast Message", 'message')
+ pkt.Request((17, 74), [
+ rec( 10, 2, ClientListCount, LE, var="x" ),
+ rec( 12, 4, ClientList, LE, repeat="x" ),
+ rec( 16, (1, 58), TargetMessage ),
+ ], info_str=(TargetMessage, "Send Broadcast Message: %s", ", %s"))
+ pkt.Reply(14, [
+ rec( 8, 2, ClientListCount, LE, var="x" ),
+ rec( 10, 4, ClientCompFlag, LE, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfd00])
+
+ # 2222/150B, 21/11
+ pkt = NCP(0x150B, "Get Broadcast Message", 'message')
+ pkt.Request(10)
+ pkt.Reply((9,66), [
+ rec( 8, (1, 58), TargetMessage )
+ ])
+ pkt.CompletionCodes([0x0000, 0xfd00])
+
+ # 2222/150C, 21/12
+ pkt = NCP(0x150C, "Connection Message Control", 'message')
+ pkt.Request(22, [
+ rec( 10, 1, ConnectionControlBits ),
+ rec( 11, 3, Reserved3 ),
+ rec( 14, 4, ConnectionListCount, LE, var="x" ),
+ rec( 18, 4, ConnectionList, LE, repeat="x" ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xff00])
+
+ # 2222/1600, 22/0
+ pkt = NCP(0x1600, "Set Directory Handle", 'fileserver')
+ pkt.Request((13,267), [
+ rec( 10, 1, TargetDirHandle ),
+ rec( 11, 1, DirHandle ),
+ rec( 12, (1, 255), Path ),
+ ], info_str=(Path, "Set Directory Handle to: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9b03, 0x9c03, 0xa100, 0xfa00,
+ 0xfd00, 0xff00])
+
+
+ # 2222/1601, 22/1
+ pkt = NCP(0x1601, "Get Directory Path", 'fileserver')
+ pkt.Request(11, [
+ rec( 10, 1, DirHandle ),
+ ],info_str=(DirHandle, "Get Directory Path for Directory Handle %d", ", %d"))
+ pkt.Reply((9,263), [
+ rec( 8, (1,255), Path ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9b00, 0x9c00, 0xa100])
+
+ # 2222/1602, 22/2
+ pkt = NCP(0x1602, "Scan Directory Information", 'fileserver')
+ pkt.Request((14,268), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 2, StartingSearchNumber, BE ),
+ rec( 13, (1, 255), Path ),
+ ], info_str=(Path, "Scan Directory Information: %s", ", %s"))
+ pkt.Reply(36, [
+ rec( 8, 16, DirectoryPath ),
+ rec( 24, 2, CreationDate, BE ),
+ rec( 26, 2, CreationTime, BE ),
+ rec( 28, 4, CreatorID, BE ),
+ rec( 32, 1, AccessRightsMask ),
+ rec( 33, 1, Reserved ),
+ rec( 34, 2, NextSearchNumber, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9b03, 0x9c03, 0xa100, 0xfa00,
+ 0xfd00, 0xff00])
+
+ # 2222/1603, 22/3
+ pkt = NCP(0x1603, "Get Effective Directory Rights", 'fileserver')
+ pkt.Request((14,268), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 2, StartingSearchNumber ),
+ rec( 13, (1, 255), Path ),
+ ], info_str=(Path, "Get Effective Directory Rights: %s", ", %s"))
+ pkt.Reply(9, [
+ rec( 8, 1, AccessRightsMask ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9b03, 0x9c03, 0xa100, 0xfa00,
+ 0xfd00, 0xff00])
+
+ # 2222/1604, 22/4
+ pkt = NCP(0x1604, "Modify Maximum Rights Mask", 'fileserver')
+ pkt.Request((14,268), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, RightsGrantMask ),
+ rec( 12, 1, RightsRevokeMask ),
+ rec( 13, (1, 255), Path ),
+ ], info_str=(Path, "Modify Maximum Rights Mask: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8c00, 0x9600, 0x9804, 0x9b03, 0x9c03, 0xa100, 0xfa00,
+ 0xfd00, 0xff00])
+
+ # 2222/1605, 22/5
+ pkt = NCP(0x1605, "Get Volume Number", 'fileserver')
+ pkt.Request((11, 265), [
+ rec( 10, (1,255), VolumeNameLen ),
+ ], info_str=(VolumeNameLen, "Get Volume Number for: %s", ", %s"))
+ pkt.Reply(9, [
+ rec( 8, 1, VolumeNumber ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804])
+
+ # 2222/1606, 22/6
+ pkt = NCP(0x1606, "Get Volume Name", 'fileserver')
+ pkt.Request(11, [
+ rec( 10, 1, VolumeNumber ),
+ ],info_str=(VolumeNumber, "Get Name for Volume %d", ", %d"))
+ pkt.Reply((9, 263), [
+ rec( 8, (1,255), VolumeNameLen ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0xff00])
+
+ # 2222/160A, 22/10
+ pkt = NCP(0x160A, "Create Directory", 'fileserver')
+ pkt.Request((13,267), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, AccessRightsMask ),
+ rec( 12, (1, 255), Path ),
+ ], info_str=(Path, "Create Directory: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8400, 0x9600, 0x9804, 0x9900, 0x9b03, 0x9c03,
+ 0x9e00, 0xa100, 0xfd00, 0xff00])
+
+ # 2222/160B, 22/11
+ pkt = NCP(0x160B, "Delete Directory", 'fileserver')
+ pkt.Request((13,267), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, Reserved ),
+ rec( 12, (1, 255), Path ),
+ ], info_str=(Path, "Delete Directory: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8a00, 0x9600, 0x9804, 0x9b03, 0x9c03,
+ 0x9f00, 0xa000, 0xa100, 0xfd00, 0xff00])
+
+ # 2222/160C, 22/12
+ pkt = NCP(0x160C, "Scan Directory for Trustees", 'fileserver')
+ pkt.Request((13,267), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, TrusteeSetNumber ),
+ rec( 12, (1, 255), Path ),
+ ], info_str=(Path, "Scan Directory for Trustees: %s", ", %s"))
+ pkt.Reply(57, [
+ rec( 8, 16, DirectoryPath ),
+ rec( 24, 2, CreationDate, BE ),
+ rec( 26, 2, CreationTime, BE ),
+ rec( 28, 4, CreatorID ),
+ rec( 32, 4, TrusteeID, BE ),
+ rec( 36, 4, TrusteeID, BE ),
+ rec( 40, 4, TrusteeID, BE ),
+ rec( 44, 4, TrusteeID, BE ),
+ rec( 48, 4, TrusteeID, BE ),
+ rec( 52, 1, AccessRightsMask ),
+ rec( 53, 1, AccessRightsMask ),
+ rec( 54, 1, AccessRightsMask ),
+ rec( 55, 1, AccessRightsMask ),
+ rec( 56, 1, AccessRightsMask ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8c00, 0x9600, 0x9804, 0x9b03, 0x9c03,
+ 0xa100, 0xfd00, 0xff00])
+
+ # 2222/160D, 22/13
+ pkt = NCP(0x160D, "Add Trustee to Directory", 'fileserver')
+ pkt.Request((17,271), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 4, TrusteeID, BE ),
+ rec( 15, 1, AccessRightsMask ),
+ rec( 16, (1, 255), Path ),
+ ], info_str=(Path, "Add Trustee to Directory: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8c00, 0x9600, 0x9804, 0x9900, 0x9b03, 0x9c03,
+ 0xa100, 0xfc06, 0xfd00, 0xff00])
+
+ # 2222/160E, 22/14
+ pkt = NCP(0x160E, "Delete Trustee from Directory", 'fileserver')
+ pkt.Request((17,271), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 4, TrusteeID, BE ),
+ rec( 15, 1, Reserved ),
+ rec( 16, (1, 255), Path ),
+ ], info_str=(Path, "Delete Trustee from Directory: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8c00, 0x9600, 0x9804, 0x9900, 0x9b03, 0x9c03,
+ 0xa100, 0xfc06, 0xfd00, 0xfe07, 0xff00])
+
+ # 2222/160F, 22/15
+ pkt = NCP(0x160F, "Rename Directory", 'fileserver')
+ pkt.Request((13, 521), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, (1, 255), Path ),
+ rec( -1, (1, 255), NewPath ),
+ ], info_str=(Path, "Rename Directory: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8b00, 0x9200, 0x9600, 0x9804, 0x9b03, 0x9c03,
+ 0x9e00, 0xa100, 0xef00, 0xfd00, 0xff00])
+
+ # 2222/1610, 22/16
+ pkt = NCP(0x1610, "Purge Erased Files", 'file')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8100, 0x9600, 0x9804, 0xa100, 0xff00])
+
+ # 2222/1611, 22/17
+ pkt = NCP(0x1611, "Recover Erased File", 'fileserver')
+ pkt.Request(11, [
+ rec( 10, 1, DirHandle ),
+ ],info_str=(DirHandle, "Recover Erased File from Directory Handle %d", ", %d"))
+ pkt.Reply(38, [
+ rec( 8, 15, OldFileName ),
+ rec( 23, 15, NewFileName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9b03, 0x9c03,
+ 0xa100, 0xfd00, 0xff00])
+ # 2222/1612, 22/18
+ pkt = NCP(0x1612, "Alloc Permanent Directory Handle", 'fileserver')
+ pkt.Request((13, 267), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, DirHandleName ),
+ rec( 12, (1,255), Path ),
+ ], info_str=(Path, "Allocate Permanent Directory Handle: %s", ", %s"))
+ pkt.Reply(10, [
+ rec( 8, 1, DirHandle ),
+ rec( 9, 1, AccessRightsMask ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9900, 0x9b00, 0x9c03, 0x9d00,
+ 0xa100, 0xfd00, 0xff00])
+ # 2222/1613, 22/19
+ pkt = NCP(0x1613, "Alloc Temporary Directory Handle", 'fileserver')
+ pkt.Request((13, 267), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, DirHandleName ),
+ rec( 12, (1,255), Path ),
+ ], info_str=(Path, "Allocate Temporary Directory Handle: %s", ", %s"))
+ pkt.Reply(10, [
+ rec( 8, 1, DirHandle ),
+ rec( 9, 1, AccessRightsMask ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9900, 0x9c03, 0x9d00,
+ 0xa100, 0xfd00, 0xff00])
+ # 2222/1614, 22/20
+ pkt = NCP(0x1614, "Deallocate Directory Handle", 'fileserver')
+ pkt.Request(11, [
+ rec( 10, 1, DirHandle ),
+ ],info_str=(DirHandle, "Deallocate Directory Handle %d", ", %d"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9b03])
+ # 2222/1615, 22/21
+ pkt = NCP(0x1615, "Get Volume Info with Handle", 'file')
+ pkt.Request( 11, [
+ rec( 10, 1, DirHandle )
+ ],info_str=(DirHandle, "Get Volume Information with Handle %d", ", %d"))
+ pkt.Reply( 36, [
+ rec( 8, 2, SectorsPerCluster, BE ),
+ rec( 10, 2, TotalVolumeClusters, BE ),
+ rec( 12, 2, AvailableClusters, BE ),
+ rec( 14, 2, TotalDirectorySlots, BE ),
+ rec( 16, 2, AvailableDirectorySlots, BE ),
+ rec( 18, 16, VolumeName ),
+ rec( 34, 2, RemovableFlag, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xff00])
+ # 2222/1616, 22/22
+ pkt = NCP(0x1616, "Alloc Special Temporary Directory Handle", 'fileserver')
+ pkt.Request((13, 267), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, DirHandleName ),
+ rec( 12, (1,255), Path ),
+ ], info_str=(Path, "Allocate Special Temporary Directory Handle: %s", ", %s"))
+ pkt.Reply(10, [
+ rec( 8, 1, DirHandle ),
+ rec( 9, 1, AccessRightsMask ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9900, 0x9c03, 0x9d00,
+ 0xa100, 0xfd00, 0xff00])
+ # 2222/1617, 22/23
+ pkt = NCP(0x1617, "Extract a Base Handle", 'fileserver')
+ pkt.Request(11, [
+ rec( 10, 1, DirHandle ),
+ ],info_str=(DirHandle, "Extract a Base Handle from Directory Handle %d", ", %d"))
+ pkt.Reply(22, [
+ rec( 8, 10, ServerNetworkAddress ),
+ rec( 18, 4, DirHandleLong ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9b03])
+ # 2222/1618, 22/24
+ pkt = NCP(0x1618, "Restore an Extracted Base Handle", 'fileserver')
+ pkt.Request(24, [
+ rec( 10, 10, ServerNetworkAddress ),
+ rec( 20, 4, DirHandleLong ),
+ ])
+ pkt.Reply(10, [
+ rec( 8, 1, DirHandle ),
+ rec( 9, 1, AccessRightsMask ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9b03, 0x9c00, 0x9d00, 0xa100,
+ 0xfd00, 0xff00])
+ # 2222/1619, 22/25
+ pkt = NCP(0x1619, "Set Directory Information", 'fileserver')
+ pkt.Request((21, 275), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 2, CreationDate ),
+ rec( 13, 2, CreationTime ),
+ rec( 15, 4, CreatorID, BE ),
+ rec( 19, 1, AccessRightsMask ),
+ rec( 20, (1,255), Path ),
+ ], info_str=(Path, "Set Directory Information: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8c00, 0x9600, 0x9804, 0x9b03, 0x9c00, 0xa100,
+ 0xff16])
+ # 2222/161A, 22/26
+ pkt = NCP(0x161A, "Get Path Name of a Volume-Directory Number Pair", 'fileserver')
+ pkt.Request(13, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 2, DirectoryEntryNumberWord ),
+ ])
+ pkt.Reply((9,263), [
+ rec( 8, (1,255), Path ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9804, 0x9c00, 0xa100])
+ # 2222/161B, 22/27
+ pkt = NCP(0x161B, "Scan Salvageable Files", 'fileserver')
+ pkt.Request(15, [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 4, SequenceNumber ),
+ ])
+ pkt.Reply(140, [
+ rec( 8, 4, SequenceNumber ),
+ rec( 12, 2, Subdirectory ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 4, AttributesDef32 ),
+ rec( 20, 1, UniqueID ),
+ rec( 21, 1, FlagsDef ),
+ rec( 22, 1, DestNameSpace ),
+ rec( 23, 1, FileNameLen ),
+ rec( 24, 12, FileName12 ),
+ rec( 36, 2, CreationTime ),
+ rec( 38, 2, CreationDate ),
+ rec( 40, 4, CreatorID, BE ),
+ rec( 44, 2, ArchivedTime ),
+ rec( 46, 2, ArchivedDate ),
+ rec( 48, 4, ArchiverID, BE ),
+ rec( 52, 2, UpdateTime ),
+ rec( 54, 2, UpdateDate ),
+ rec( 56, 4, UpdateID, BE ),
+ rec( 60, 4, FileSize, BE ),
+ rec( 64, 44, Reserved44 ),
+ rec( 108, 2, InheritedRightsMask ),
+ rec( 110, 2, LastAccessedDate ),
+ rec( 112, 4, DeletedFileTime ),
+ rec( 116, 2, DeletedTime ),
+ rec( 118, 2, DeletedDate ),
+ rec( 120, 4, DeletedID, BE ),
+ rec( 124, 16, Reserved16 ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfb01, 0xff1d])
+ # 2222/161C, 22/28
+ pkt = NCP(0x161C, "Recover Salvageable File", 'fileserver')
+ pkt.Request((17,525), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 4, SequenceNumber ),
+ rec( 15, (1, 255), FileName ),
+ rec( -1, (1, 255), NewFileNameLen ),
+ ], info_str=(FileName, "Recover File: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8401, 0x9c03, 0xfe02])
+ # 2222/161D, 22/29
+ pkt = NCP(0x161D, "Purge Salvageable File", 'fileserver')
+ pkt.Request(15, [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 4, SequenceNumber ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8500, 0x9c03])
+ # 2222/161E, 22/30
+ pkt = NCP(0x161E, "Scan a Directory", 'fileserver')
+ pkt.Request((17, 271), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, DOSFileAttributes ),
+ rec( 12, 4, SequenceNumber ),
+ rec( 16, (1, 255), SearchPattern ),
+ ], info_str=(SearchPattern, "Scan a Directory: %s", ", %s"))
+ pkt.Reply(140, [
+ rec( 8, 4, SequenceNumber ),
+ rec( 12, 4, Subdirectory ),
+ rec( 16, 4, AttributesDef32 ),
+ rec( 20, 1, UniqueID, LE ),
+ rec( 21, 1, PurgeFlags ),
+ rec( 22, 1, DestNameSpace ),
+ rec( 23, 1, NameLen ),
+ rec( 24, 12, Name12 ),
+ rec( 36, 2, CreationTime ),
+ rec( 38, 2, CreationDate ),
+ rec( 40, 4, CreatorID, BE ),
+ rec( 44, 2, ArchivedTime ),
+ rec( 46, 2, ArchivedDate ),
+ rec( 48, 4, ArchiverID, BE ),
+ rec( 52, 2, UpdateTime ),
+ rec( 54, 2, UpdateDate ),
+ rec( 56, 4, UpdateID, BE ),
+ rec( 60, 4, FileSize, BE ),
+ rec( 64, 44, Reserved44 ),
+ rec( 108, 2, InheritedRightsMask ),
+ rec( 110, 2, LastAccessedDate ),
+ rec( 112, 28, Reserved28 ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8500, 0x9c03])
+ # 2222/161F, 22/31
+ pkt = NCP(0x161F, "Get Directory Entry", 'fileserver')
+ pkt.Request(11, [
+ rec( 10, 1, DirHandle ),
+ ])
+ pkt.Reply(136, [
+ rec( 8, 4, Subdirectory ),
+ rec( 12, 4, AttributesDef32 ),
+ rec( 16, 1, UniqueID, LE ),
+ rec( 17, 1, PurgeFlags ),
+ rec( 18, 1, DestNameSpace ),
+ rec( 19, 1, NameLen ),
+ rec( 20, 12, Name12 ),
+ rec( 32, 2, CreationTime ),
+ rec( 34, 2, CreationDate ),
+ rec( 36, 4, CreatorID, BE ),
+ rec( 40, 2, ArchivedTime ),
+ rec( 42, 2, ArchivedDate ),
+ rec( 44, 4, ArchiverID, BE ),
+ rec( 48, 2, UpdateTime ),
+ rec( 50, 2, UpdateDate ),
+ rec( 52, 4, NextTrusteeEntry, BE ),
+ rec( 56, 48, Reserved48 ),
+ rec( 104, 2, MaximumSpace ),
+ rec( 106, 2, InheritedRightsMask ),
+ rec( 108, 28, Undefined28 ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8900, 0xbf00, 0xfb00])
+ # 2222/1620, 22/32
+ pkt = NCP(0x1620, "Scan Volume's User Disk Restrictions", 'fileserver')
+ pkt.Request(15, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, SequenceNumber ),
+ ])
+ pkt.Reply(17, [
+ rec( 8, 1, NumberOfEntries, var="x" ),
+ rec( 9, 8, ObjectIDStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9800])
+ # 2222/1621, 22/33
+ pkt = NCP(0x1621, "Add User Disk Space Restriction", 'fileserver')
+ pkt.Request(19, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, ObjectID ),
+ rec( 15, 4, DiskSpaceLimit ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8c00, 0x9600, 0x9800])
+ # 2222/1622, 22/34
+ pkt = NCP(0x1622, "Remove User Disk Space Restrictions", 'fileserver')
+ pkt.Request(15, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, ObjectID ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8c00, 0xfe0e])
+ # 2222/1623, 22/35
+ pkt = NCP(0x1623, "Get Directory Disk Space Restriction", 'fileserver')
+ pkt.Request(11, [
+ rec( 10, 1, DirHandle ),
+ ])
+ pkt.Reply(18, [
+ rec( 8, 1, NumberOfEntries ),
+ rec( 9, 1, Level ),
+ rec( 10, 4, MaxSpace ),
+ rec( 14, 4, CurrentSpace ),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/1624, 22/36
+ pkt = NCP(0x1624, "Set Directory Disk Space Restriction", 'fileserver')
+ pkt.Request(15, [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 4, DiskSpaceLimit ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0101, 0x8c00, 0xbf00])
+ # 2222/1625, 22/37
+ pkt = NCP(0x1625, "Set Directory Entry Information", 'fileserver')
+ pkt.Request(NO_LENGTH_CHECK, [
+ #
+ # XXX - this didn't match what was in the spec for 22/37
+ # on the Novell Web site.
+ #
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, SearchAttributes ),
+ rec( 12, 4, SequenceNumber ),
+ rec( 16, 2, ChangeBits ),
+ rec( 18, 2, Reserved2 ),
+ rec( 20, 4, Subdirectory ),
+ srec(DOSDirectoryEntryStruct, req_cond="ncp.search_att_sub == TRUE"),
+ srec(DOSFileEntryStruct, req_cond="ncp.search_att_sub == FALSE"),
+ ])
+ pkt.Reply(8)
+ pkt.ReqCondSizeConstant()
+ pkt.CompletionCodes([0x0000, 0x0106, 0x8c00, 0xbf00])
+ # 2222/1626, 22/38
+ pkt = NCP(0x1626, "Scan File or Directory for Extended Trustees", 'fileserver')
+ pkt.Request((13,267), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, SequenceByte ),
+ rec( 12, (1, 255), Path ),
+ ], info_str=(Path, "Scan for Extended Trustees: %s", ", %s"))
+ pkt.Reply(91, [
+ rec( 8, 1, NumberOfEntries, var="x" ),
+ rec( 9, 4, ObjectID ),
+ rec( 13, 4, ObjectID ),
+ rec( 17, 4, ObjectID ),
+ rec( 21, 4, ObjectID ),
+ rec( 25, 4, ObjectID ),
+ rec( 29, 4, ObjectID ),
+ rec( 33, 4, ObjectID ),
+ rec( 37, 4, ObjectID ),
+ rec( 41, 4, ObjectID ),
+ rec( 45, 4, ObjectID ),
+ rec( 49, 4, ObjectID ),
+ rec( 53, 4, ObjectID ),
+ rec( 57, 4, ObjectID ),
+ rec( 61, 4, ObjectID ),
+ rec( 65, 4, ObjectID ),
+ rec( 69, 4, ObjectID ),
+ rec( 73, 4, ObjectID ),
+ rec( 77, 4, ObjectID ),
+ rec( 81, 4, ObjectID ),
+ rec( 85, 4, ObjectID ),
+ rec( 89, 2, AccessRightsMaskWord, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9800, 0x9b00, 0x9c00])
+ # 2222/1627, 22/39
+ pkt = NCP(0x1627, "Add Extended Trustee to Directory or File", 'fileserver')
+ pkt.Request((18,272), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 4, ObjectID, BE ),
+ rec( 15, 2, TrusteeRights ),
+ rec( 17, (1, 255), Path ),
+ ], info_str=(Path, "Add Extended Trustee: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9000])
+ # 2222/1628, 22/40
+ pkt = NCP(0x1628, "Scan Directory Disk Space", 'fileserver')
+ pkt.Request((17,271), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 1, SearchAttributes ),
+ rec( 12, 4, SequenceNumber ),
+ rec( 16, (1, 255), SearchPattern ),
+ ], info_str=(SearchPattern, "Scan Directory Disk Space: %s", ", %s"))
+ pkt.Reply((148), [
+ rec( 8, 4, SequenceNumber ),
+ rec( 12, 4, Subdirectory ),
+ rec( 16, 4, AttributesDef32 ),
+ rec( 20, 1, UniqueID ),
+ rec( 21, 1, PurgeFlags ),
+ rec( 22, 1, DestNameSpace ),
+ rec( 23, 1, NameLen ),
+ rec( 24, 12, Name12 ),
+ rec( 36, 2, CreationTime ),
+ rec( 38, 2, CreationDate ),
+ rec( 40, 4, CreatorID, BE ),
+ rec( 44, 2, ArchivedTime ),
+ rec( 46, 2, ArchivedDate ),
+ rec( 48, 4, ArchiverID, BE ),
+ rec( 52, 2, UpdateTime ),
+ rec( 54, 2, UpdateDate ),
+ rec( 56, 4, UpdateID, BE ),
+ rec( 60, 4, DataForkSize, BE ),
+ rec( 64, 4, DataForkFirstFAT, BE ),
+ rec( 68, 4, NextTrusteeEntry, BE ),
+ rec( 72, 36, Reserved36 ),
+ rec( 108, 2, InheritedRightsMask ),
+ rec( 110, 2, LastAccessedDate ),
+ rec( 112, 4, DeletedFileTime ),
+ rec( 116, 2, DeletedTime ),
+ rec( 118, 2, DeletedDate ),
+ rec( 120, 4, DeletedID, BE ),
+ rec( 124, 8, Undefined8 ),
+ rec( 132, 4, PrimaryEntry, LE ),
+ rec( 136, 4, NameList, LE ),
+ rec( 140, 4, OtherFileForkSize, BE ),
+ rec( 144, 4, OtherFileForkFAT, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8900, 0x9c03, 0xfb01, 0xff00])
+ # 2222/1629, 22/41
+ pkt = NCP(0x1629, "Get Object Disk Usage and Restrictions", 'fileserver')
+ pkt.Request(15, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, ObjectID, BE ),
+ ])
+ pkt.Reply(16, [
+ rec( 8, 4, Restriction ),
+ rec( 12, 4, InUse ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9802])
+ # 2222/162A, 22/42
+ pkt = NCP(0x162A, "Get Effective Rights for Directory Entry", 'fileserver')
+ pkt.Request((12,266), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, (1, 255), Path ),
+ ], info_str=(Path, "Get Effective Rights: %s", ", %s"))
+ pkt.Reply(10, [
+ rec( 8, 2, AccessRightsMaskWord ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9804, 0x9c03])
+ # 2222/162B, 22/43
+ pkt = NCP(0x162B, "Remove Extended Trustee from Dir or File", 'fileserver')
+ pkt.Request((17,271), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, 4, ObjectID, BE ),
+ rec( 15, 1, Unused ),
+ rec( 16, (1, 255), Path ),
+ ], info_str=(Path, "Remove Extended Trustee from %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9002, 0x9c03, 0xfe0f, 0xff09])
+ # 2222/162C, 22/44
+ pkt = NCP(0x162C, "Get Volume and Purge Information", 'file')
+ pkt.Request( 11, [
+ rec( 10, 1, VolumeNumber )
+ ],info_str=(VolumeNumber, "Get Volume and Purge Information for Volume %d", ", %d"))
+ pkt.Reply( (38,53), [
+ rec( 8, 4, TotalBlocks ),
+ rec( 12, 4, FreeBlocks ),
+ rec( 16, 4, PurgeableBlocks ),
+ rec( 20, 4, NotYetPurgeableBlocks ),
+ rec( 24, 4, TotalDirectoryEntries ),
+ rec( 28, 4, AvailableDirEntries ),
+ rec( 32, 4, Reserved4 ),
+ rec( 36, 1, SectorsPerBlock ),
+ rec( 37, (1,16), VolumeNameLen ),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/162D, 22/45
+ pkt = NCP(0x162D, "Get Directory Information", 'file')
+ pkt.Request( 11, [
+ rec( 10, 1, DirHandle )
+ ])
+ pkt.Reply( (30, 45), [
+ rec( 8, 4, TotalBlocks ),
+ rec( 12, 4, AvailableBlocks ),
+ rec( 16, 4, TotalDirectoryEntries ),
+ rec( 20, 4, AvailableDirEntries ),
+ rec( 24, 4, Reserved4 ),
+ rec( 28, 1, SectorsPerBlock ),
+ rec( 29, (1,16), VolumeNameLen ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9b03])
+ # 2222/162E, 22/46
+ pkt = NCP(0x162E, "Rename Or Move", 'file')
+ pkt.Request( (17,525), [
+ rec( 10, 1, SourceDirHandle ),
+ rec( 11, 1, SearchAttributes ),
+ rec( 12, 1, SourcePathComponentCount ),
+ rec( 13, (1,255), SourcePath ),
+ rec( -1, 1, DestDirHandle ),
+ rec( -1, 1, DestPathComponentCount ),
+ rec( -1, (1,255), DestPath ),
+ ], info_str=(SourcePath, "Rename or Move: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0102, 0x8701, 0x8b00, 0x8d00, 0x8e00,
+ 0x8f00, 0x9001, 0x9101, 0x9201, 0x9a00, 0x9b03,
+ 0x9c03, 0xa400, 0xff17])
+ # 2222/162F, 22/47
+ pkt = NCP(0x162F, "Get Name Space Information", 'file')
+ pkt.Request( 11, [
+ rec( 10, 1, VolumeNumber )
+ ],info_str=(VolumeNumber, "Get Name Space Information for Volume %d", ", %d"))
+ pkt.Reply( (15,523), [
+ #
+ # XXX - why does this not display anything at all
+ # if the stuff after the first IndexNumber is
+ # un-commented? That stuff really is there....
+ #
+ rec( 8, 1, DefinedNameSpaces, var="v" ),
+ rec( 9, (1,255), NameSpaceName, repeat="v" ),
+ rec( -1, 1, DefinedDataStreams, var="w" ),
+ rec( -1, (2,256), DataStreamInfo, repeat="w" ),
+ rec( -1, 1, LoadedNameSpaces, var="x" ),
+ rec( -1, 1, IndexNumber, repeat="x" ),
+# rec( -1, 1, VolumeNameSpaces, var="y" ),
+# rec( -1, 1, IndexNumber, repeat="y" ),
+# rec( -1, 1, VolumeDataStreams, var="z" ),
+# rec( -1, 1, IndexNumber, repeat="z" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9802, 0xff00])
+ # 2222/1630, 22/48
+ pkt = NCP(0x1630, "Get Name Space Directory Entry", 'file')
+ pkt.Request( 16, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, DOSSequence ),
+ rec( 15, 1, SrcNameSpace ),
+ ])
+ pkt.Reply( 112, [
+ rec( 8, 4, SequenceNumber ),
+ rec( 12, 4, Subdirectory ),
+ rec( 16, 4, AttributesDef32 ),
+ rec( 20, 1, UniqueID ),
+ rec( 21, 1, Flags ),
+ rec( 22, 1, SrcNameSpace ),
+ rec( 23, 1, NameLength ),
+ rec( 24, 12, Name12 ),
+ rec( 36, 2, CreationTime ),
+ rec( 38, 2, CreationDate ),
+ rec( 40, 4, CreatorID, BE ),
+ rec( 44, 2, ArchivedTime ),
+ rec( 46, 2, ArchivedDate ),
+ rec( 48, 4, ArchiverID ),
+ rec( 52, 2, UpdateTime ),
+ rec( 54, 2, UpdateDate ),
+ rec( 56, 4, UpdateID ),
+ rec( 60, 4, FileSize ),
+ rec( 64, 44, Reserved44 ),
+ rec( 108, 2, InheritedRightsMask ),
+ rec( 110, 2, LastAccessedDate ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8900, 0x9802, 0xbf00])
+ # 2222/1631, 22/49
+ pkt = NCP(0x1631, "Open Data Stream", 'file')
+ pkt.Request( (15,269), [
+ rec( 10, 1, DataStream ),
+ rec( 11, 1, DirHandle ),
+ rec( 12, 1, AttributesDef ),
+ rec( 13, 1, OpenRights ),
+ rec( 14, (1, 255), FileName ),
+ ], info_str=(FileName, "Open Data Stream: %s", ", %s"))
+ pkt.Reply( 12, [
+ rec( 8, 4, CCFileHandle, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8200, 0x9002, 0xbe00, 0xff00])
+ # 2222/1632, 22/50
+ pkt = NCP(0x1632, "Get Object Effective Rights for Directory Entry", 'file')
+ pkt.Request( (16,270), [
+ rec( 10, 4, ObjectID, BE ),
+ rec( 14, 1, DirHandle ),
+ rec( 15, (1, 255), Path ),
+ ], info_str=(Path, "Get Object Effective Rights: %s", ", %s"))
+ pkt.Reply( 10, [
+ rec( 8, 2, TrusteeRights ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x9b00, 0x9c03])
+ # 2222/1633, 22/51
+ pkt = NCP(0x1633, "Get Extended Volume Information", 'file')
+ pkt.Request( 11, [
+ rec( 10, 1, VolumeNumber ),
+ ],info_str=(VolumeNumber, "Get Extended Volume Information for Volume %d", ", %d"))
+ pkt.Reply( (139,266), [
+ rec( 8, 2, VolInfoReplyLen ),
+ rec( 10, 128, VolInfoStructure),
+ rec( 138, (1,128), VolumeNameLen ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x9804, 0xfb08, 0xff00])
+ # 2222/1634, 22/52
+ pkt = NCP(0x1634, "Get Mount Volume List", 'file')
+ pkt.Request( 22, [
+ rec( 10, 4, StartVolumeNumber ),
+ rec( 14, 4, VolumeRequestFlags, LE ),
+ rec( 18, 4, SrcNameSpace ),
+ ])
+ pkt.Reply( 34, [
+ rec( 8, 4, ItemsInPacket, var="x" ),
+ rec( 12, 4, NextVolumeNumber ),
+ rec( 16, 18, VolumeStruct, repeat="x"),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/1700, 23/00
+ pkt = NCP(0x1700, "Login User", 'file')
+ pkt.Request( (12, 58), [
+ rec( 10, (1,16), UserName ),
+ rec( -1, (1,32), Password ),
+ ], info_str=(UserName, "Login User: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9602, 0xc101, 0xc200, 0xc501, 0xd700,
+ 0xd900, 0xda00, 0xdb00, 0xde00, 0xdf00, 0xe800,
+ 0xec00, 0xed00, 0xef00, 0xf001, 0xf100, 0xf200,
+ 0xf600, 0xfb00, 0xfc06, 0xfe07, 0xff00])
+ # 2222/1701, 23/01
+ pkt = NCP(0x1701, "Change User Password", 'file')
+ pkt.Request( (13, 90), [
+ rec( 10, (1,16), UserName ),
+ rec( -1, (1,32), Password ),
+ rec( -1, (1,32), NewPassword ),
+ ], info_str=(UserName, "Change Password for User: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xd600, 0xf001, 0xf101, 0xf501,
+ 0xfc06, 0xfe07, 0xff00])
+ # 2222/1702, 23/02
+ pkt = NCP(0x1702, "Get User Connection List", 'file')
+ pkt.Request( (11, 26), [
+ rec( 10, (1,16), UserName ),
+ ], info_str=(UserName, "Get User Connection: %s", ", %s"))
+ pkt.Reply( (9, 136), [
+ rec( 8, (1, 128), ConnectionNumberList ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf001, 0xfc06, 0xfe07, 0xff00])
+ # 2222/1703, 23/03
+ pkt = NCP(0x1703, "Get User Number", 'file')
+ pkt.Request( (11, 26), [
+ rec( 10, (1,16), UserName ),
+ ], info_str=(UserName, "Get User Number: %s", ", %s"))
+ pkt.Reply( 12, [
+ rec( 8, 4, ObjectID, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf001, 0xfc06, 0xfe07, 0xff00])
+ # 2222/1705, 23/05
+ pkt = NCP(0x1705, "Get Station's Logged Info", 'file')
+ pkt.Request( 11, [
+ rec( 10, 1, TargetConnectionNumber ),
+ ],info_str=(TargetConnectionNumber, "Get Station's Logged Information on Connection %d", ", %d"))
+ pkt.Reply( 266, [
+ rec( 8, 16, UserName16 ),
+ rec( 24, 7, LoginTime ),
+ rec( 31, 39, FullName ),
+ rec( 70, 4, UserID, BE ),
+ rec( 74, 128, SecurityEquivalentList ),
+ rec( 202, 64, Reserved64 ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9602, 0xfc06, 0xfd00, 0xfe07, 0xff00])
+ # 2222/1707, 23/07
+ pkt = NCP(0x1707, "Get Group Number", 'file')
+ pkt.Request( 14, [
+ rec( 10, 4, ObjectID, BE ),
+ ])
+ pkt.Reply( 62, [
+ rec( 8, 4, ObjectID, BE ),
+ rec( 12, 2, ObjectType, BE ),
+ rec( 14, 48, ObjectNameLen ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9602, 0xf101, 0xfc06, 0xfe07, 0xff00])
+ # 2222/170C, 23/12
+ pkt = NCP(0x170C, "Verify Serialization", 'file')
+ pkt.Request( 14, [
+ rec( 10, 4, ServerSerialNumber ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xff00])
+ # 2222/170D, 23/13
+ pkt = NCP(0x170D, "Log Network Message", 'file')
+ pkt.Request( (11, 68), [
+ rec( 10, (1, 58), TargetMessage ),
+ ], info_str=(TargetMessage, "Log Network Message: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8100, 0x8800, 0x8d00, 0x8e00, 0x8f00,
+ 0x9001, 0x9400, 0x9600, 0x9804, 0x9900, 0x9b00, 0xa100,
+ 0xa201, 0xff00])
+ # 2222/170E, 23/14
+ pkt = NCP(0x170E, "Get Disk Utilization", 'file')
+ pkt.Request( 15, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, TrusteeID, BE ),
+ ])
+ pkt.Reply( 19, [
+ rec( 8, 1, VolumeNumber ),
+ rec( 9, 4, TrusteeID, BE ),
+ rec( 13, 2, DirectoryCount, BE ),
+ rec( 15, 2, FileCount, BE ),
+ rec( 17, 2, ClusterCount, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0xa100, 0xf200])
+ # 2222/170F, 23/15
+ pkt = NCP(0x170F, "Scan File Information", 'file')
+ pkt.Request((15,269), [
+ rec( 10, 2, LastSearchIndex ),
+ rec( 12, 1, DirHandle ),
+ rec( 13, 1, SearchAttributes ),
+ rec( 14, (1, 255), FileName ),
+ ], info_str=(FileName, "Scan File Information: %s", ", %s"))
+ pkt.Reply( 102, [
+ rec( 8, 2, NextSearchIndex ),
+ rec( 10, 14, FileName14 ),
+ rec( 24, 2, AttributesDef16 ),
+ rec( 26, 4, FileSize, BE ),
+ rec( 30, 2, CreationDate, BE ),
+ rec( 32, 2, LastAccessedDate, BE ),
+ rec( 34, 2, ModifiedDate, BE ),
+ rec( 36, 2, ModifiedTime, BE ),
+ rec( 38, 4, CreatorID, BE ),
+ rec( 42, 2, ArchivedDate, BE ),
+ rec( 44, 2, ArchivedTime, BE ),
+ rec( 46, 56, Reserved56 ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8800, 0x8900, 0x9300, 0x9400, 0x9804, 0x9b00, 0x9c00,
+ 0xa100, 0xfd00, 0xff17])
+ # 2222/1710, 23/16
+ pkt = NCP(0x1710, "Set File Information", 'file')
+ pkt.Request((91,345), [
+ rec( 10, 2, AttributesDef16 ),
+ rec( 12, 4, FileSize, BE ),
+ rec( 16, 2, CreationDate, BE ),
+ rec( 18, 2, LastAccessedDate, BE ),
+ rec( 20, 2, ModifiedDate, BE ),
+ rec( 22, 2, ModifiedTime, BE ),
+ rec( 24, 4, CreatorID, BE ),
+ rec( 28, 2, ArchivedDate, BE ),
+ rec( 30, 2, ArchivedTime, BE ),
+ rec( 32, 56, Reserved56 ),
+ rec( 88, 1, DirHandle ),
+ rec( 89, 1, SearchAttributes ),
+ rec( 90, (1, 255), FileName ),
+ ], info_str=(FileName, "Set Information for File: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0x8c00, 0x8e00, 0x9400, 0x9600, 0x9804,
+ 0x9b03, 0x9c00, 0xa100, 0xa201, 0xfc06, 0xfd00, 0xfe07,
+ 0xff17])
+ # 2222/1711, 23/17
+ pkt = NCP(0x1711, "Get File Server Information", 'fileserver')
+ pkt.Request(10)
+ pkt.Reply(136, [
+ rec( 8, 48, ServerName ),
+ rec( 56, 1, OSMajorVersion ),
+ rec( 57, 1, OSMinorVersion ),
+ rec( 58, 2, ConnectionsSupportedMax, BE ),
+ rec( 60, 2, ConnectionsInUse, BE ),
+ rec( 62, 2, VolumesSupportedMax, BE ),
+ rec( 64, 1, OSRevision ),
+ rec( 65, 1, SFTSupportLevel ),
+ rec( 66, 1, TTSLevel ),
+ rec( 67, 2, ConnectionsMaxUsed, BE ),
+ rec( 69, 1, AccountVersion ),
+ rec( 70, 1, VAPVersion ),
+ rec( 71, 1, QueueingVersion ),
+ rec( 72, 1, PrintServerVersion ),
+ rec( 73, 1, VirtualConsoleVersion ),
+ rec( 74, 1, SecurityRestrictionVersion ),
+ rec( 75, 1, InternetBridgeVersion ),
+ rec( 76, 1, MixedModePathFlag ),
+ rec( 77, 1, LocalLoginInfoCcode ),
+ rec( 78, 2, ProductMajorVersion, BE ),
+ rec( 80, 2, ProductMinorVersion, BE ),
+ rec( 82, 2, ProductRevisionVersion, BE ),
+ rec( 84, 1, OSLanguageID, LE ),
+ rec( 85, 1, SixtyFourBitOffsetsSupportedFlag ),
+ rec( 86, 50, Reserved50 ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600])
+ # 2222/1712, 23/18
+ pkt = NCP(0x1712, "Get Network Serial Number", 'fileserver')
+ pkt.Request(10)
+ pkt.Reply(14, [
+ rec( 8, 4, ServerSerialNumber ),
+ rec( 12, 2, ApplicationNumber ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600])
+ # 2222/1713, 23/19
+ pkt = NCP(0x1713, "Get Internet Address", 'fileserver')
+ pkt.Request(11, [
+ rec( 10, 1, TargetConnectionNumber ),
+ ],info_str=(TargetConnectionNumber, "Get Internet Address for Connection %d", ", %d"))
+ pkt.Reply(20, [
+ rec( 8, 4, NetworkAddress, BE ),
+ rec( 12, 6, NetworkNodeAddress ),
+ rec( 18, 2, NetworkSocket, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xff00])
+ # 2222/1714, 23/20
+ pkt = NCP(0x1714, "Login Object", 'bindery')
+ pkt.Request( (14, 60), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,16), ClientName ),
+ rec( -1, (1,32), Password ),
+ ], info_str=(UserName, "Login Object: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9602, 0xc101, 0xc200, 0xc501, 0xd600, 0xd700,
+ 0xd900, 0xda00, 0xdb00, 0xde00, 0xdf00, 0xe800, 0xec00,
+ 0xed00, 0xef00, 0xf001, 0xf100, 0xf200, 0xf600, 0xfb00,
+ 0xfc06, 0xfe07, 0xff00])
+ # 2222/1715, 23/21
+ pkt = NCP(0x1715, "Get Object Connection List", 'bindery')
+ pkt.Request( (13, 28), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,16), ObjectName ),
+ ], info_str=(UserName, "Get Object Connection List: %s", ", %s"))
+ pkt.Reply( (9, 136), [
+ rec( 8, (1, 128), ConnectionNumberList ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf001, 0xfc06, 0xfe07, 0xff00])
+ # 2222/1716, 23/22
+ pkt = NCP(0x1716, "Get Station's Logged Info", 'bindery')
+ pkt.Request( 11, [
+ rec( 10, 1, TargetConnectionNumber ),
+ ])
+ pkt.Reply( 70, [
+ rec( 8, 4, UserID, BE ),
+ rec( 12, 2, ObjectType, BE ),
+ rec( 14, 48, ObjectNameLen ),
+ rec( 62, 7, LoginTime ),
+ rec( 69, 1, Reserved ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9602, 0xfb0a, 0xfc06, 0xfd00, 0xfe07, 0xff00])
+ # 2222/1717, 23/23
+ pkt = NCP(0x1717, "Get Login Key", 'bindery')
+ pkt.Request(10)
+ pkt.Reply( 16, [
+ rec( 8, 8, LoginKey ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9602])
+ # 2222/1718, 23/24
+ pkt = NCP(0x1718, "Keyed Object Login", 'bindery')
+ pkt.Request( (21, 68), [
+ rec( 10, 8, LoginKey ),
+ rec( 18, 2, ObjectType, BE ),
+ rec( 20, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Keyed Object Login: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9602, 0xc101, 0xc200, 0xc500, 0xd904, 0xda00,
+ 0xdb00, 0xdc00, 0xde00, 0xff00])
+ # 2222/171A, 23/26
+ #
+ # XXX - for NCP-over-IP, the NetworkAddress field appears to be
+ # an IP address, rather than an IPX network address, and should
+ # be dissected as an FT_IPv4 value; the NetworkNodeAddress and
+ # NetworkSocket are 0.
+ #
+ # For NCP-over-IPX, it should probably be dissected as an
+ # FT_IPXNET value.
+ #
+ pkt = NCP(0x171A, "Get Internet Address", 'fileserver')
+ pkt.Request(11, [
+ rec( 10, 1, TargetConnectionNumber ),
+ ])
+ pkt.Reply(21, [
+ rec( 8, 4, NetworkAddress, BE ),
+ rec( 12, 6, NetworkNodeAddress ),
+ rec( 18, 2, NetworkSocket, BE ),
+ rec( 20, 1, ConnectionType ),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/171B, 23/27
+ pkt = NCP(0x171B, "Get Object Connection List", 'bindery')
+ pkt.Request( (17,64), [
+ rec( 10, 4, SearchConnNumber ),
+ rec( 14, 2, ObjectType, BE ),
+ rec( 16, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Get Object Connection List: %s", ", %s"))
+ pkt.Reply( (10,137), [
+ rec( 8, 1, ConnListLen, var="x" ),
+ rec( 9, (1,128), ConnectionNumberList, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf001, 0xfc06, 0xfe07, 0xff00])
+ # 2222/171C, 23/28
+ pkt = NCP(0x171C, "Get Station's Logged Info", 'connection')
+ pkt.Request( 14, [
+ rec( 10, 4, TargetConnectionNumber ),
+ ])
+ pkt.Reply( 70, [
+ rec( 8, 4, UserID, BE ),
+ rec( 12, 2, ObjectType, BE ),
+ rec( 14, 48, ObjectNameLen ),
+ rec( 62, 7, LoginTime ),
+ rec( 69, 1, Reserved ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9602, 0xfb02, 0xfc06, 0xfd00, 0xfe07, 0xff00])
+ # 2222/171D, 23/29
+ pkt = NCP(0x171D, "Change Connection State", 'connection')
+ pkt.Request( 11, [
+ rec( 10, 1, RequestCode ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0109, 0x7a00, 0x7b00, 0x7c00, 0xe000, 0xfb06, 0xfd00])
+ # 2222/171E, 23/30
+ pkt = NCP(0x171E, "Set Watchdog Delay Interval", 'connection')
+ pkt.Request( 14, [
+ rec( 10, 4, NumberOfMinutesToDelay ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0107])
+ # 2222/171F, 23/31
+ pkt = NCP(0x171F, "Get Connection List From Object", 'bindery')
+ pkt.Request( 18, [
+ rec( 10, 4, ObjectID, BE ),
+ rec( 14, 4, ConnectionNumber ),
+ ])
+ pkt.Reply( (9, 136), [
+ rec( 8, (1, 128), ConnectionNumberList ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf001, 0xfc06, 0xfe07, 0xff00])
+ # 2222/1720, 23/32
+ pkt = NCP(0x1720, "Scan Bindery Object (List)", 'bindery')
+ pkt.Request((23,70), [
+ rec( 10, 4, NextObjectID, BE ),
+ rec( 14, 4, ObjectType, BE ),
+ rec( 18, 4, InfoFlags ),
+ rec( 22, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Scan Bindery Object: %s", ", %s"))
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec( 8, 4, ObjectInfoReturnCount ),
+ rec( 12, 4, NextObjectID, BE ),
+ rec( 16, 4, ObjectIDInfo ),
+ srec(ObjectTypeStruct, req_cond="ncp.info_flags_type == TRUE"),
+ srec(ObjectSecurityStruct, req_cond="ncp.info_flags_security == TRUE"),
+ srec(ObjectFlagsStruct, req_cond="ncp.info_flags_flags == TRUE"),
+ srec(ObjectNameStruct, req_cond="ncp.info_flags_name == TRUE"),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x9600, 0xef01, 0xfc02, 0xfe01, 0xff00])
+ # 2222/1721, 23/33
+ pkt = NCP(0x1721, "Generate GUIDs", 'nds')
+ pkt.Request( 14, [
+ rec( 10, 4, ReturnInfoCount ),
+ ])
+ pkt.Reply(28, [
+ rec( 8, 4, ReturnInfoCount, var="x" ),
+ rec( 12, 16, GUID, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/1732, 23/50
+ pkt = NCP(0x1732, "Create Bindery Object", 'bindery')
+ pkt.Request( (15,62), [
+ rec( 10, 1, ObjectFlags ),
+ rec( 11, 1, ObjectSecurity ),
+ rec( 12, 2, ObjectType, BE ),
+ rec( 14, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Create Bindery Object: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xe700, 0xee00, 0xef00, 0xf101, 0xf501,
+ 0xfc06, 0xfe07, 0xff00])
+ # 2222/1733, 23/51
+ pkt = NCP(0x1733, "Delete Bindery Object", 'bindery')
+ pkt.Request( (13,60), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Delete Bindery Object: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf000, 0xf200, 0xf400, 0xf600, 0xfb00,
+ 0xfc06, 0xfe07, 0xff00])
+ # 2222/1734, 23/52
+ pkt = NCP(0x1734, "Rename Bindery Object", 'bindery')
+ pkt.Request( (14,108), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, (1,48), NewObjectName ),
+ ], info_str=(ObjectName, "Rename Bindery Object: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xee00, 0xf000, 0xf300, 0xfc06, 0xfe07, 0xff00])
+ # 2222/1735, 23/53
+ pkt = NCP(0x1735, "Get Bindery Object ID", 'bindery')
+ pkt.Request((13,60), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Get Bindery Object: %s", ", %s"))
+ pkt.Reply(62, [
+ rec( 8, 4, ObjectID, BE ),
+ rec( 12, 2, ObjectType, BE ),
+ rec( 14, 48, ObjectNameLen ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xef01, 0xf000, 0xfc02, 0xfe01, 0xff00])
+ # 2222/1736, 23/54
+ pkt = NCP(0x1736, "Get Bindery Object Name", 'bindery')
+ pkt.Request( 14, [
+ rec( 10, 4, ObjectID, BE ),
+ ])
+ pkt.Reply( 62, [
+ rec( 8, 4, ObjectID, BE ),
+ rec( 12, 2, ObjectType, BE ),
+ rec( 14, 48, ObjectNameLen ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf101, 0xfc02, 0xfe01, 0xff00])
+ # 2222/1737, 23/55
+ pkt = NCP(0x1737, "Scan Bindery Object", 'bindery')
+ pkt.Request((17,64), [
+ rec( 10, 4, ObjectID, BE ),
+ rec( 14, 2, ObjectType, BE ),
+ rec( 16, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Scan Bindery Object: %s", ", %s"))
+ pkt.Reply(65, [
+ rec( 8, 4, ObjectID, BE ),
+ rec( 12, 2, ObjectType, BE ),
+ rec( 14, 48, ObjectNameLen ),
+ rec( 62, 1, ObjectFlags ),
+ rec( 63, 1, ObjectSecurity ),
+ rec( 64, 1, ObjectHasProperties ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xef01, 0xfc02,
+ 0xfe01, 0xff00])
+ # 2222/1738, 23/56
+ pkt = NCP(0x1738, "Change Bindery Object Security", 'bindery')
+ pkt.Request((14,61), [
+ rec( 10, 1, ObjectSecurity ),
+ rec( 11, 2, ObjectType, BE ),
+ rec( 13, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Change Bindery Object Security: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf000, 0xf101, 0xf501, 0xfc02, 0xfe01, 0xff00])
+ # 2222/1739, 23/57
+ pkt = NCP(0x1739, "Create Property", 'bindery')
+ pkt.Request((16,78), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, 1, PropertyType ),
+ rec( -1, 1, ObjectSecurity ),
+ rec( -1, (1,16), PropertyName ),
+ ], info_str=(PropertyName, "Create Property: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xed00, 0xef00, 0xf000, 0xf101,
+ 0xf200, 0xf600, 0xf700, 0xfb00, 0xfc02, 0xfe01,
+ 0xff00])
+ # 2222/173A, 23/58
+ pkt = NCP(0x173A, "Delete Property", 'bindery')
+ pkt.Request((14,76), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, (1,16), PropertyName ),
+ ], info_str=(PropertyName, "Delete Property: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf000, 0xf101, 0xf600, 0xfb00, 0xfc02,
+ 0xfe01, 0xff00])
+ # 2222/173B, 23/59
+ pkt = NCP(0x173B, "Change Property Security", 'bindery')
+ pkt.Request((15,77), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, 1, ObjectSecurity ),
+ rec( -1, (1,16), PropertyName ),
+ ], info_str=(PropertyName, "Change Property Security: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf000, 0xf101, 0xf200, 0xf600, 0xfb00,
+ 0xfc02, 0xfe01, 0xff00])
+ # 2222/173C, 23/60
+ pkt = NCP(0x173C, "Scan Property", 'bindery')
+ pkt.Request((18,80), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, 4, LastInstance, BE ),
+ rec( -1, (1,16), PropertyName ),
+ ], info_str=(PropertyName, "Scan Property: %s", ", %s"))
+ pkt.Reply( 32, [
+ rec( 8, 16, PropertyName16 ),
+ rec( 24, 1, ObjectFlags ),
+ rec( 25, 1, ObjectSecurity ),
+ rec( 26, 4, SearchInstance, BE ),
+ rec( 30, 1, ValueAvailable ),
+ rec( 31, 1, MoreProperties ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xf000, 0xf101, 0xf200, 0xf600, 0xfb00,
+ 0xfc02, 0xfe01, 0xff00])
+ # 2222/173D, 23/61
+ pkt = NCP(0x173D, "Read Property Value", 'bindery')
+ pkt.Request((15,77), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, 1, PropertySegment ),
+ rec( -1, (1,16), PropertyName ),
+ ], info_str=(PropertyName, "Read Property Value: %s", ", %s"))
+ pkt.Reply(138, [
+ rec( 8, 128, PropertyData ),
+ rec( 136, 1, PropertyHasMoreSegments ),
+ rec( 137, 1, PropertyType ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8800, 0x9300, 0x9600, 0xec01,
+ 0xf000, 0xf100, 0xf900, 0xfb02, 0xfc02,
+ 0xfe01, 0xff00])
+ # 2222/173E, 23/62
+ pkt = NCP(0x173E, "Write Property Value", 'bindery')
+ pkt.Request((144,206), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, 1, PropertySegment ),
+ rec( -1, 1, MoreFlag ),
+ rec( -1, (1,16), PropertyName ),
+ #
+ # XXX - don't show this if MoreFlag isn't set?
+ # In at least some packages where it's not set,
+ # PropertyValue appears to be garbage.
+ #
+ rec( -1, 128, PropertyValue ),
+ ], info_str=(PropertyName, "Write Property Value: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xe800, 0xec01, 0xf000, 0xf800,
+ 0xfb02, 0xfc03, 0xfe01, 0xff00 ])
+ # 2222/173F, 23/63
+ pkt = NCP(0x173F, "Verify Bindery Object Password", 'bindery')
+ pkt.Request((14,92), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, (1,32), Password ),
+ ], info_str=(ObjectName, "Verify Bindery Object Password: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xe800, 0xec01, 0xf000, 0xf101,
+ 0xfb02, 0xfc03, 0xfe01, 0xff00 ])
+ # 2222/1740, 23/64
+ pkt = NCP(0x1740, "Change Bindery Object Password", 'bindery')
+ pkt.Request((15,124), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, (1,32), Password ),
+ rec( -1, (1,32), NewPassword ),
+ ], info_str=(ObjectName, "Change Bindery Object Password: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc501, 0xd701, 0xe800, 0xec01, 0xf001,
+ 0xf100, 0xf800, 0xfb02, 0xfc03, 0xfe01, 0xff00])
+ # 2222/1741, 23/65
+ pkt = NCP(0x1741, "Add Bindery Object To Set", 'bindery')
+ pkt.Request((17,126), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, (1,16), PropertyName ),
+ rec( -1, 2, MemberType, BE ),
+ rec( -1, (1,48), MemberName ),
+ ], info_str=(MemberName, "Add Bindery Object to Set: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xe800, 0xe900, 0xea00, 0xeb00,
+ 0xec01, 0xf000, 0xf800, 0xfb02, 0xfc03, 0xfe01,
+ 0xff00])
+ # 2222/1742, 23/66
+ pkt = NCP(0x1742, "Delete Bindery Object From Set", 'bindery')
+ pkt.Request((17,126), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, (1,16), PropertyName ),
+ rec( -1, 2, MemberType, BE ),
+ rec( -1, (1,48), MemberName ),
+ ], info_str=(MemberName, "Delete Bindery Object from Set: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xeb00, 0xf000, 0xf800, 0xfb02,
+ 0xfc03, 0xfe01, 0xff00])
+ # 2222/1743, 23/67
+ pkt = NCP(0x1743, "Is Bindery Object In Set", 'bindery')
+ pkt.Request((17,126), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ rec( -1, (1,16), PropertyName ),
+ rec( -1, 2, MemberType, BE ),
+ rec( -1, (1,48), MemberName ),
+ ], info_str=(MemberName, "Is Bindery Object in Set: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xea00, 0xeb00, 0xec01, 0xf000,
+ 0xfb02, 0xfc03, 0xfe01, 0xff00])
+ # 2222/1744, 23/68
+ pkt = NCP(0x1744, "Close Bindery", 'bindery')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xff00])
+ # 2222/1745, 23/69
+ pkt = NCP(0x1745, "Open Bindery", 'bindery')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xff00])
+ # 2222/1746, 23/70
+ pkt = NCP(0x1746, "Get Bindery Access Level", 'bindery')
+ pkt.Request(10)
+ pkt.Reply(13, [
+ rec( 8, 1, ObjectSecurity ),
+ rec( 9, 4, LoggedObjectID, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600])
+ # 2222/1747, 23/71
+ pkt = NCP(0x1747, "Scan Bindery Object Trustee Paths", 'bindery')
+ pkt.Request(17, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 2, LastSequenceNumber, BE ),
+ rec( 13, 4, ObjectID, BE ),
+ ])
+ pkt.Reply((16,270), [
+ rec( 8, 2, LastSequenceNumber, BE),
+ rec( 10, 4, ObjectID, BE ),
+ rec( 14, 1, ObjectSecurity ),
+ rec( 15, (1,255), Path ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9300, 0x9600, 0xa100, 0xf000, 0xf100,
+ 0xf200, 0xfc02, 0xfe01, 0xff00])
+ # 2222/1748, 23/72
+ pkt = NCP(0x1748, "Get Bindery Object Access Level", 'bindery')
+ pkt.Request(14, [
+ rec( 10, 4, ObjectID, BE ),
+ ])
+ pkt.Reply(9, [
+ rec( 8, 1, ObjectSecurity ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600])
+ # 2222/1749, 23/73
+ pkt = NCP(0x1749, "Is Calling Station a Manager", 'bindery')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0003, 0xff1e])
+ # 2222/174A, 23/74
+ pkt = NCP(0x174A, "Keyed Verify Password", 'bindery')
+ pkt.Request((21,68), [
+ rec( 10, 8, LoginKey ),
+ rec( 18, 2, ObjectType, BE ),
+ rec( 20, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Keyed Verify Password: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc500, 0xfe01, 0xff0c])
+ # 2222/174B, 23/75
+ pkt = NCP(0x174B, "Keyed Change Password", 'bindery')
+ pkt.Request((22,100), [
+ rec( 10, 8, LoginKey ),
+ rec( 18, 2, ObjectType, BE ),
+ rec( 20, (1,48), ObjectName ),
+ rec( -1, (1,32), Password ),
+ ], info_str=(ObjectName, "Keyed Change Password: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc500, 0xfe01, 0xff0c])
+ # 2222/174C, 23/76
+ pkt = NCP(0x174C, "List Relations Of an Object", 'bindery')
+ pkt.Request((18,80), [
+ rec( 10, 4, LastSeen, BE ),
+ rec( 14, 2, ObjectType, BE ),
+ rec( 16, (1,48), ObjectName ),
+ rec( -1, (1,16), PropertyName ),
+ ], info_str=(ObjectName, "List Relations of an Object: %s", ", %s"))
+ pkt.Reply(14, [
+ rec( 8, 2, RelationsCount, BE, var="x" ),
+ rec( 10, 4, ObjectID, BE, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xf000, 0xf200, 0xfe01, 0xff00])
+ # 2222/1764, 23/100
+ pkt = NCP(0x1764, "Create Queue", 'qms')
+ pkt.Request((15,316), [
+ rec( 10, 2, QueueType, BE ),
+ rec( 12, (1,48), QueueName ),
+ rec( -1, 1, PathBase ),
+ rec( -1, (1,255), Path ),
+ ], info_str=(QueueName, "Create Queue: %s", ", %s"))
+ pkt.Reply(12, [
+ rec( 8, 4, QueueID ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9900, 0xd000, 0xd100,
+ 0xd200, 0xd300, 0xd400, 0xd500, 0xd601,
+ 0xd703, 0xd800, 0xd902, 0xda01, 0xdb02,
+ 0xee00, 0xff00])
+ # 2222/1765, 23/101
+ pkt = NCP(0x1765, "Destroy Queue", 'qms')
+ pkt.Request(14, [
+ rec( 10, 4, QueueID ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1766, 23/102
+ pkt = NCP(0x1766, "Read Queue Current Status", 'qms')
+ pkt.Request(14, [
+ rec( 10, 4, QueueID ),
+ ])
+ pkt.Reply(20, [
+ rec( 8, 4, QueueID ),
+ rec( 12, 1, QueueStatus ),
+ rec( 13, 1, CurrentEntries ),
+ rec( 14, 1, CurrentServers, var="x" ),
+ rec( 15, 4, ServerID, repeat="x" ),
+ rec( 19, 1, ServerStationList, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1767, 23/103
+ pkt = NCP(0x1767, "Set Queue Current Status", 'qms')
+ pkt.Request(15, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 1, QueueStatus ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xfc07,
+ 0xff00])
+ # 2222/1768, 23/104
+ pkt = NCP(0x1768, "Create Queue Job And File", 'qms')
+ pkt.Request(264, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 250, JobStruct ),
+ ])
+ pkt.Reply(62, [
+ rec( 8, 1, ClientStation ),
+ rec( 9, 1, ClientTaskNumber ),
+ rec( 10, 4, ClientIDNumber, BE ),
+ rec( 14, 4, TargetServerIDNumber, BE ),
+ rec( 18, 6, TargetExecutionTime ),
+ rec( 24, 6, JobEntryTime ),
+ rec( 30, 2, JobNumber, BE ),
+ rec( 32, 2, JobType, BE ),
+ rec( 34, 1, JobPosition ),
+ rec( 35, 1, JobControlFlags ),
+ rec( 36, 14, JobFileName ),
+ rec( 50, 6, JobFileHandle ),
+ rec( 56, 1, ServerStation ),
+ rec( 57, 1, ServerTaskNumber ),
+ rec( 58, 4, ServerID, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xfc07,
+ 0xff00])
+ # 2222/1769, 23/105
+ pkt = NCP(0x1769, "Close File And Start Queue Job", 'qms')
+ pkt.Request(16, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, JobNumber, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/176A, 23/106
+ pkt = NCP(0x176A, "Remove Job From Queue", 'qms')
+ pkt.Request(16, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, JobNumber, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/176B, 23/107
+ pkt = NCP(0x176B, "Get Queue Job List", 'qms')
+ pkt.Request(14, [
+ rec( 10, 4, QueueID ),
+ ])
+ pkt.Reply(12, [
+ rec( 8, 2, JobCount, BE, var="x" ),
+ rec( 10, 2, JobNumber, BE, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/176C, 23/108
+ pkt = NCP(0x176C, "Read Queue Job Entry", 'qms')
+ pkt.Request(16, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, JobNumber, BE ),
+ ])
+ pkt.Reply(258, [
+ rec( 8, 250, JobStruct ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/176D, 23/109
+ pkt = NCP(0x176D, "Change Queue Job Entry", 'qms')
+ pkt.Request(260, [
+ rec( 14, 250, JobStruct ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff18])
+ # 2222/176E, 23/110
+ pkt = NCP(0x176E, "Change Queue Job Position", 'qms')
+ pkt.Request(17, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, JobNumber, BE ),
+ rec( 16, 1, NewPosition ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xd000, 0xd100, 0xd500,
+ 0xd601, 0xfe07, 0xff1f])
+ # 2222/176F, 23/111
+ pkt = NCP(0x176F, "Attach Queue Server To Queue", 'qms')
+ pkt.Request(14, [
+ rec( 10, 4, QueueID ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xea00,
+ 0xfc06, 0xff00])
+ # 2222/1770, 23/112
+ pkt = NCP(0x1770, "Detach Queue Server From Queue", 'qms')
+ pkt.Request(14, [
+ rec( 10, 4, QueueID ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1771, 23/113
+ pkt = NCP(0x1771, "Service Queue Job", 'qms')
+ pkt.Request(16, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, ServiceType, BE ),
+ ])
+ pkt.Reply(62, [
+ rec( 8, 1, ClientStation ),
+ rec( 9, 1, ClientTaskNumber ),
+ rec( 10, 4, ClientIDNumber, BE ),
+ rec( 14, 4, TargetServerIDNumber, BE ),
+ rec( 18, 6, TargetExecutionTime ),
+ rec( 24, 6, JobEntryTime ),
+ rec( 30, 2, JobNumber, BE ),
+ rec( 32, 2, JobType, BE ),
+ rec( 34, 1, JobPosition ),
+ rec( 35, 1, JobControlFlags ),
+ rec( 36, 14, JobFileName ),
+ rec( 50, 6, JobFileHandle ),
+ rec( 56, 1, ServerStation ),
+ rec( 57, 1, ServerTaskNumber ),
+ rec( 58, 4, ServerID, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1772, 23/114
+ pkt = NCP(0x1772, "Finish Servicing Queue Job", 'qms')
+ pkt.Request(20, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, JobNumber, BE ),
+ rec( 16, 4, ChargeInformation, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1773, 23/115
+ pkt = NCP(0x1773, "Abort Servicing Queue Job", 'qms')
+ pkt.Request(16, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, JobNumber, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff18])
+ # 2222/1774, 23/116
+ pkt = NCP(0x1774, "Change To Client Rights", 'qms')
+ pkt.Request(16, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, JobNumber, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff18])
+ # 2222/1775, 23/117
+ pkt = NCP(0x1775, "Restore Queue Server Rights", 'qms')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1776, 23/118
+ pkt = NCP(0x1776, "Read Queue Server Current Status", 'qms')
+ pkt.Request(19, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, ServerID, BE ),
+ rec( 18, 1, ServerStation ),
+ ])
+ pkt.Reply(72, [
+ rec( 8, 64, ServerStatusRecord ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1777, 23/119
+ pkt = NCP(0x1777, "Set Queue Server Current Status", 'qms')
+ pkt.Request(78, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 64, ServerStatusRecord ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1778, 23/120
+ pkt = NCP(0x1778, "Get Queue Job File Size", 'qms')
+ pkt.Request(16, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, JobNumber, BE ),
+ ])
+ pkt.Reply(20, [
+ rec( 8, 4, QueueID ),
+ rec( 12, 4, JobNumberLong ),
+ rec( 16, 4, FileSize, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1779, 23/121
+ pkt = NCP(0x1779, "Create Queue Job And File", 'qms')
+ pkt.Request(264, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 250, JobStruct3x ),
+ ])
+ pkt.Reply(94, [
+ rec( 8, 86, JobStructNew ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xfc07, 0xff00])
+ # 2222/177A, 23/122
+ pkt = NCP(0x177A, "Read Queue Job Entry", 'qms')
+ pkt.Request(18, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ ])
+ pkt.Reply(258, [
+ rec( 8, 250, JobStruct3x ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/177B, 23/123
+ pkt = NCP(0x177B, "Change Queue Job Entry", 'qms')
+ pkt.Request(264, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 250, JobStruct ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xfc07, 0xff00])
+ # 2222/177C, 23/124
+ pkt = NCP(0x177C, "Service Queue Job", 'qms')
+ pkt.Request(16, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 2, ServiceType ),
+ ])
+ pkt.Reply(94, [
+ rec( 8, 86, JobStructNew ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/177D, 23/125
+ pkt = NCP(0x177D, "Read Queue Current Status", 'qms')
+ pkt.Request(14, [
+ rec( 10, 4, QueueID ),
+ ])
+ pkt.Reply(32, [
+ rec( 8, 4, QueueID ),
+ rec( 12, 1, QueueStatus ),
+ rec( 13, 3, Reserved3 ),
+ rec( 16, 4, CurrentEntries ),
+ rec( 20, 4, CurrentServers, var="x" ),
+ rec( 24, 4, ServerID, repeat="x" ),
+ rec( 28, 4, ServerStationLong, LE, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/177E, 23/126
+ pkt = NCP(0x177E, "Set Queue Current Status", 'qms')
+ pkt.Request(15, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 1, QueueStatus ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/177F, 23/127
+ pkt = NCP(0x177F, "Close File And Start Queue Job", 'qms')
+ pkt.Request(18, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xfc07, 0xff00])
+ # 2222/1780, 23/128
+ pkt = NCP(0x1780, "Remove Job From Queue", 'qms')
+ pkt.Request(18, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1781, 23/129
+ pkt = NCP(0x1781, "Get Queue Job List", 'qms')
+ pkt.Request(18, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ ])
+ pkt.Reply(20, [
+ rec( 8, 4, TotalQueueJobs ),
+ rec( 12, 4, ReplyQueueJobNumbers, var="x" ),
+ rec( 16, 4, JobNumberLong, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1782, 23/130
+ pkt = NCP(0x1782, "Change Job Priority", 'qms')
+ pkt.Request(22, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ rec( 18, 4, Priority ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1783, 23/131
+ pkt = NCP(0x1783, "Finish Servicing Queue Job", 'qms')
+ pkt.Request(22, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ rec( 18, 4, ChargeInformation ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1784, 23/132
+ pkt = NCP(0x1784, "Abort Servicing Queue Job", 'qms')
+ pkt.Request(18, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff18])
+ # 2222/1785, 23/133
+ pkt = NCP(0x1785, "Change To Client Rights", 'qms')
+ pkt.Request(18, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff18])
+ # 2222/1786, 23/134
+ pkt = NCP(0x1786, "Read Queue Server Current Status", 'qms')
+ pkt.Request(22, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, ServerID, BE ),
+ rec( 18, 4, ServerStation ),
+ ])
+ pkt.Reply(72, [
+ rec( 8, 64, ServerStatusRecord ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1787, 23/135
+ pkt = NCP(0x1787, "Get Queue Job File Size", 'qms')
+ pkt.Request(18, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ ])
+ pkt.Reply(20, [
+ rec( 8, 4, QueueID ),
+ rec( 12, 4, JobNumberLong ),
+ rec( 16, 4, FileSize, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9900, 0xd000, 0xd100, 0xd200,
+ 0xd300, 0xd400, 0xd500, 0xd601, 0xd703,
+ 0xd800, 0xd902, 0xda01, 0xdb02, 0xff00])
+ # 2222/1788, 23/136
+ pkt = NCP(0x1788, "Move Queue Job From Src Q to Dst Q", 'qms')
+ pkt.Request(22, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, JobNumberLong ),
+ rec( 18, 4, DstQueueID ),
+ ])
+ pkt.Reply(12, [
+ rec( 8, 4, JobNumberLong ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfc06])
+ # 2222/1789, 23/137
+ pkt = NCP(0x1789, "Get Queue Jobs From Form List", 'qms')
+ pkt.Request(24, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, QueueStartPosition ),
+ rec( 18, 4, FormTypeCnt, var="x" ),
+ rec( 22, 2, FormType, repeat="x" ),
+ ])
+ pkt.Reply(20, [
+ rec( 8, 4, TotalQueueJobs ),
+ rec( 12, 4, JobCount, var="x" ),
+ rec( 16, 4, JobNumberLong, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfc06])
+ # 2222/178A, 23/138
+ pkt = NCP(0x178A, "Service Queue Job By Form List", 'qms')
+ pkt.Request(24, [
+ rec( 10, 4, QueueID ),
+ rec( 14, 4, QueueStartPosition ),
+ rec( 18, 4, FormTypeCnt, var= "x" ),
+ rec( 22, 2, FormType, repeat="x" ),
+ ])
+ pkt.Reply(94, [
+ rec( 8, 86, JobStructNew ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfc06])
+ # 2222/1796, 23/150
+ pkt = NCP(0x1796, "Get Current Account Status", 'accounting')
+ pkt.Request((13,60), [
+ rec( 10, 2, ObjectType, BE ),
+ rec( 12, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Get Current Account Status: %s", ", %s"))
+ pkt.Reply(264, [
+ rec( 8, 4, AccountBalance, BE ),
+ rec( 12, 4, CreditLimit, BE ),
+ rec( 16, 120, Reserved120 ),
+ rec( 136, 4, HolderID, BE ),
+ rec( 140, 4, HoldAmount, BE ),
+ rec( 144, 4, HolderID, BE ),
+ rec( 148, 4, HoldAmount, BE ),
+ rec( 152, 4, HolderID, BE ),
+ rec( 156, 4, HoldAmount, BE ),
+ rec( 160, 4, HolderID, BE ),
+ rec( 164, 4, HoldAmount, BE ),
+ rec( 168, 4, HolderID, BE ),
+ rec( 172, 4, HoldAmount, BE ),
+ rec( 176, 4, HolderID, BE ),
+ rec( 180, 4, HoldAmount, BE ),
+ rec( 184, 4, HolderID, BE ),
+ rec( 188, 4, HoldAmount, BE ),
+ rec( 192, 4, HolderID, BE ),
+ rec( 196, 4, HoldAmount, BE ),
+ rec( 200, 4, HolderID, BE ),
+ rec( 204, 4, HoldAmount, BE ),
+ rec( 208, 4, HolderID, BE ),
+ rec( 212, 4, HoldAmount, BE ),
+ rec( 216, 4, HolderID, BE ),
+ rec( 220, 4, HoldAmount, BE ),
+ rec( 224, 4, HolderID, BE ),
+ rec( 228, 4, HoldAmount, BE ),
+ rec( 232, 4, HolderID, BE ),
+ rec( 236, 4, HoldAmount, BE ),
+ rec( 240, 4, HolderID, BE ),
+ rec( 244, 4, HoldAmount, BE ),
+ rec( 248, 4, HolderID, BE ),
+ rec( 252, 4, HoldAmount, BE ),
+ rec( 256, 4, HolderID, BE ),
+ rec( 260, 4, HoldAmount, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc000, 0xc101, 0xc400, 0xe800,
+ 0xea00, 0xeb00, 0xec00, 0xfc06, 0xfe07, 0xff00])
+ # 2222/1797, 23/151
+ pkt = NCP(0x1797, "Submit Account Charge", 'accounting')
+ pkt.Request((26,327), [
+ rec( 10, 2, ServiceType, BE ),
+ rec( 12, 4, ChargeAmount, BE ),
+ rec( 16, 4, HoldCancelAmount, BE ),
+ rec( 20, 2, ObjectType, BE ),
+ rec( 22, 2, CommentType, BE ),
+ rec( 24, (1,48), ObjectName ),
+ rec( -1, (1,255), Comment ),
+ ], info_str=(ObjectName, "Submit Account Charge: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0102, 0x8800, 0x9400, 0x9600, 0xa201,
+ 0xc000, 0xc101, 0xc200, 0xc400, 0xe800, 0xea00,
+ 0xeb00, 0xec00, 0xfe07, 0xff00])
+ # 2222/1798, 23/152
+ pkt = NCP(0x1798, "Submit Account Hold", 'accounting')
+ pkt.Request((17,64), [
+ rec( 10, 4, HoldCancelAmount, BE ),
+ rec( 14, 2, ObjectType, BE ),
+ rec( 16, (1,48), ObjectName ),
+ ], info_str=(ObjectName, "Submit Account Hold: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0102, 0x8800, 0x9400, 0x9600, 0xa201,
+ 0xc000, 0xc101, 0xc200, 0xc400, 0xe800, 0xea00,
+ 0xeb00, 0xec00, 0xfe07, 0xff00])
+ # 2222/1799, 23/153
+ pkt = NCP(0x1799, "Submit Account Note", 'accounting')
+ pkt.Request((18,319), [
+ rec( 10, 2, ServiceType, BE ),
+ rec( 12, 2, ObjectType, BE ),
+ rec( 14, 2, CommentType, BE ),
+ rec( 16, (1,48), ObjectName ),
+ rec( -1, (1,255), Comment ),
+ ], info_str=(ObjectName, "Submit Account Note: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0102, 0x9600, 0xc000, 0xc101, 0xc400,
+ 0xe800, 0xea00, 0xeb00, 0xec00, 0xf000, 0xfc06,
+ 0xff00])
+ # 2222/17c8, 23/200
+ pkt = NCP(0x17c8, "Check Console Privileges", 'stats')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601])
+ # 2222/17c9, 23/201
+ pkt = NCP(0x17c9, "Get File Server Description Strings", 'stats')
+ pkt.Request(10)
+ pkt.Reply(108, [
+ rec( 8, 100, DescriptionStrings ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600])
+ # 2222/17CA, 23/202
+ pkt = NCP(0x17CA, "Set File Server Date And Time", 'stats')
+ pkt.Request(16, [
+ rec( 10, 1, Year ),
+ rec( 11, 1, Month ),
+ rec( 12, 1, Day ),
+ rec( 13, 1, Hour ),
+ rec( 14, 1, Minute ),
+ rec( 15, 1, Second ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601])
+ # 2222/17CB, 23/203
+ pkt = NCP(0x17CB, "Disable File Server Login", 'stats')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601])
+ # 2222/17CC, 23/204
+ pkt = NCP(0x17CC, "Enable File Server Login", 'stats')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601])
+ # 2222/17CD, 23/205
+ pkt = NCP(0x17CD, "Get File Server Login Status", 'stats')
+ pkt.Request(10)
+ pkt.Reply(12, [
+ rec( 8, 4, UserLoginAllowed ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xfb01])
+ # 2222/17CF, 23/207
+ pkt = NCP(0x17CF, "Disable Transaction Tracking", 'stats')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601])
+ # 2222/17D0, 23/208
+ pkt = NCP(0x17D0, "Enable Transaction Tracking", 'stats')
+ pkt.Request(10)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601])
+ # 2222/17D1, 23/209
+ pkt = NCP(0x17D1, "Send Console Broadcast", 'stats')
+ pkt.Request((13,267), [
+ rec( 10, 1, NumberOfStations, var="x" ),
+ rec( 11, 1, StationList, repeat="x" ),
+ rec( 12, (1, 255), TargetMessage ),
+ ], info_str=(TargetMessage, "Send Console Broadcast: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601, 0xfd00])
+ # 2222/17D2, 23/210
+ pkt = NCP(0x17D2, "Clear Connection Number", 'stats')
+ pkt.Request(11, [
+ rec( 10, 1, ConnectionNumber ),
+ ],info_str=(ConnectionNumber, "Clear Connection Number %d", ", %d"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601, 0xfd00])
+ # 2222/17D3, 23/211
+ pkt = NCP(0x17D3, "Down File Server", 'stats')
+ pkt.Request(11, [
+ rec( 10, 1, ForceFlag ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601, 0xff00])
+ # 2222/17D4, 23/212
+ pkt = NCP(0x17D4, "Get File System Statistics", 'stats')
+ pkt.Request(10)
+ pkt.Reply(50, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 2, ConfiguredMaxOpenFiles ),
+ rec( 14, 2, ActualMaxOpenFiles ),
+ rec( 16, 2, CurrentOpenFiles ),
+ rec( 18, 4, TotalFilesOpened ),
+ rec( 22, 4, TotalReadRequests ),
+ rec( 26, 4, TotalWriteRequests ),
+ rec( 30, 2, CurrentChangedFATs ),
+ rec( 32, 4, TotalChangedFATs ),
+ rec( 36, 2, FATWriteErrors ),
+ rec( 38, 2, FatalFATWriteErrors ),
+ rec( 40, 2, FATScanErrors ),
+ rec( 42, 2, ActualMaxIndexedFiles ),
+ rec( 44, 2, ActiveIndexedFiles ),
+ rec( 46, 2, AttachedIndexedFiles ),
+ rec( 48, 2, AvailableIndexedFiles ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17D5, 23/213
+ pkt = NCP(0x17D5, "Get Transaction Tracking Statistics", 'stats')
+ pkt.Request((13,267), [
+ rec( 10, 2, LastRecordSeen ),
+ rec( 12, (1,255), SemaphoreName ),
+ ])
+ pkt.Reply(53, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 1, TransactionTrackingSupported ),
+ rec( 13, 1, TransactionTrackingEnabled ),
+ rec( 14, 2, TransactionVolumeNumber ),
+ rec( 16, 2, ConfiguredMaxSimultaneousTransactions ),
+ rec( 18, 2, ActualMaxSimultaneousTransactions ),
+ rec( 20, 2, CurrentTransactionCount ),
+ rec( 22, 4, TotalTransactionsPerformed ),
+ rec( 26, 4, TotalWriteTransactionsPerformed ),
+ rec( 30, 4, TotalTransactionsBackedOut ),
+ rec( 34, 2, TotalUnfilledBackoutRequests ),
+ rec( 36, 2, TransactionDiskSpace ),
+ rec( 38, 4, TransactionFATAllocations ),
+ rec( 42, 4, TransactionFileSizeChanges ),
+ rec( 46, 4, TransactionFilesTruncated ),
+ rec( 50, 1, NumberOfEntries, var="x" ),
+ rec( 51, 2, ConnTaskStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17D6, 23/214
+ pkt = NCP(0x17D6, "Read Disk Cache Statistics", 'stats')
+ pkt.Request(10)
+ pkt.Reply(86, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 2, CacheBufferCount ),
+ rec( 14, 2, CacheBufferSize ),
+ rec( 16, 2, DirtyCacheBuffers ),
+ rec( 18, 4, CacheReadRequests ),
+ rec( 22, 4, CacheWriteRequests ),
+ rec( 26, 4, CacheHits ),
+ rec( 30, 4, CacheMisses ),
+ rec( 34, 4, PhysicalReadRequests ),
+ rec( 38, 4, PhysicalWriteRequests ),
+ rec( 42, 2, PhysicalReadErrors ),
+ rec( 44, 2, PhysicalWriteErrors ),
+ rec( 46, 4, CacheGetRequests ),
+ rec( 50, 4, CacheFullWriteRequests ),
+ rec( 54, 4, CachePartialWriteRequests ),
+ rec( 58, 4, BackgroundDirtyWrites ),
+ rec( 62, 4, BackgroundAgedWrites ),
+ rec( 66, 4, TotalCacheWrites ),
+ rec( 70, 4, CacheAllocations ),
+ rec( 74, 2, ThrashingCount ),
+ rec( 76, 2, LRUBlockWasDirty ),
+ rec( 78, 2, ReadBeyondWrite ),
+ rec( 80, 2, FragmentWriteOccurred ),
+ rec( 82, 2, CacheHitOnUnavailableBlock ),
+ rec( 84, 2, CacheBlockScrapped ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17D7, 23/215
+ pkt = NCP(0x17D7, "Get Drive Mapping Table", 'stats')
+ pkt.Request(10)
+ pkt.Reply(184, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 1, SFTSupportLevel ),
+ rec( 13, 1, LogicalDriveCount ),
+ rec( 14, 1, PhysicalDriveCount ),
+ rec( 15, 1, DiskChannelTable ),
+ rec( 16, 4, Reserved4 ),
+ rec( 20, 2, PendingIOCommands, BE ),
+ rec( 22, 32, DriveMappingTable ),
+ rec( 54, 32, DriveMirrorTable ),
+ rec( 86, 32, DeadMirrorTable ),
+ rec( 118, 1, ReMirrorDriveNumber ),
+ rec( 119, 1, Filler ),
+ rec( 120, 4, ReMirrorCurrentOffset, BE ),
+ rec( 124, 60, SFTErrorTable ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17D8, 23/216
+ pkt = NCP(0x17D8, "Read Physical Disk Statistics", 'stats')
+ pkt.Request(11, [
+ rec( 10, 1, PhysicalDiskNumber ),
+ ])
+ pkt.Reply(101, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 1, PhysicalDiskChannel ),
+ rec( 13, 1, DriveRemovableFlag ),
+ rec( 14, 1, PhysicalDriveType ),
+ rec( 15, 1, ControllerDriveNumber ),
+ rec( 16, 1, ControllerNumber ),
+ rec( 17, 1, ControllerType ),
+ rec( 18, 4, DriveSize ),
+ rec( 22, 2, DriveCylinders ),
+ rec( 24, 1, DriveHeads ),
+ rec( 25, 1, SectorsPerTrack ),
+ rec( 26, 64, DriveDefinitionString ),
+ rec( 90, 2, IOErrorCount ),
+ rec( 92, 4, HotFixTableStart ),
+ rec( 96, 2, HotFixTableSize ),
+ rec( 98, 2, HotFixBlocksAvailable ),
+ rec( 100, 1, HotFixDisabled ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17D9, 23/217
+ pkt = NCP(0x17D9, "Get Disk Channel Statistics", 'stats')
+ pkt.Request(11, [
+ rec( 10, 1, DiskChannelNumber ),
+ ])
+ pkt.Reply(192, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 2, ChannelState, BE ),
+ rec( 14, 2, ChannelSynchronizationState, BE ),
+ rec( 16, 1, SoftwareDriverType ),
+ rec( 17, 1, SoftwareMajorVersionNumber ),
+ rec( 18, 1, SoftwareMinorVersionNumber ),
+ rec( 19, 65, SoftwareDescription ),
+ rec( 84, 8, IOAddressesUsed ),
+ rec( 92, 10, SharedMemoryAddresses ),
+ rec( 102, 4, InterruptNumbersUsed ),
+ rec( 106, 4, DMAChannelsUsed ),
+ rec( 110, 1, FlagBits ),
+ rec( 111, 1, Reserved ),
+ rec( 112, 80, ConfigurationDescription ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17DB, 23/219
+ pkt = NCP(0x17DB, "Get Connection's Open Files", 'file')
+ pkt.Request(14, [
+ rec( 10, 2, ConnectionNumber ),
+ rec( 12, 2, LastRecordSeen, BE ),
+ ])
+ pkt.Reply(32, [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 1, NumberOfRecords, var="x" ),
+ rec( 11, 21, ConnStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17DC, 23/220
+ pkt = NCP(0x17DC, "Get Connection Using A File", 'file')
+ pkt.Request((14,268), [
+ rec( 10, 2, LastRecordSeen, BE ),
+ rec( 12, 1, DirHandle ),
+ rec( 13, (1,255), Path ),
+ ], info_str=(Path, "Get Connection Using File: %s", ", %s"))
+ pkt.Reply(30, [
+ rec( 8, 2, UseCount, BE ),
+ rec( 10, 2, OpenCount, BE ),
+ rec( 12, 2, OpenForReadCount, BE ),
+ rec( 14, 2, OpenForWriteCount, BE ),
+ rec( 16, 2, DenyReadCount, BE ),
+ rec( 18, 2, DenyWriteCount, BE ),
+ rec( 20, 2, NextRequestRecord, BE ),
+ rec( 22, 1, Locked ),
+ rec( 23, 1, NumberOfRecords, var="x" ),
+ rec( 24, 6, ConnFileStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17DD, 23/221
+ pkt = NCP(0x17DD, "Get Physical Record Locks By Connection And File", 'file')
+ pkt.Request(31, [
+ rec( 10, 2, TargetConnectionNumber ),
+ rec( 12, 2, LastRecordSeen, BE ),
+ rec( 14, 1, VolumeNumber ),
+ rec( 15, 2, DirectoryID ),
+ rec( 17, 14, FileName14 ),
+ ], info_str=(FileName14, "Get Physical Record Locks by Connection and File: %s", ", %s"))
+ pkt.Reply(22, [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 1, NumberOfLocks, var="x" ),
+ rec( 11, 1, Reserved ),
+ rec( 12, 10, LockStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17DE, 23/222
+ pkt = NCP(0x17DE, "Get Physical Record Locks By File", 'file')
+ pkt.Request((14,268), [
+ rec( 10, 2, TargetConnectionNumber ),
+ rec( 12, 1, DirHandle ),
+ rec( 13, (1,255), Path ),
+ ], info_str=(Path, "Get Physical Record Locks by File: %s", ", %s"))
+ pkt.Reply(28, [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 1, NumberOfLocks, var="x" ),
+ rec( 11, 1, Reserved ),
+ rec( 12, 16, PhyLockStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17DF, 23/223
+ pkt = NCP(0x17DF, "Get Logical Records By Connection", 'file')
+ pkt.Request(14, [
+ rec( 10, 2, TargetConnectionNumber ),
+ rec( 12, 2, LastRecordSeen, BE ),
+ ])
+ pkt.Reply((14,268), [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 1, NumberOfRecords, var="x" ),
+ rec( 11, (3, 257), LogLockStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17E0, 23/224
+ pkt = NCP(0x17E0, "Get Logical Record Information", 'file')
+ pkt.Request((13,267), [
+ rec( 10, 2, LastRecordSeen ),
+ rec( 12, (1,255), LogicalRecordName ),
+ ], info_str=(LogicalRecordName, "Get Logical Record Information: %s", ", %s"))
+ pkt.Reply(20, [
+ rec( 8, 2, UseCount, BE ),
+ rec( 10, 2, ShareableLockCount, BE ),
+ rec( 12, 2, NextRequestRecord ),
+ rec( 14, 1, Locked ),
+ rec( 15, 1, NumberOfRecords, var="x" ),
+ rec( 16, 4, LogRecStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17E1, 23/225
+ pkt = NCP(0x17E1, "Get Connection's Semaphores", 'file')
+ pkt.Request(14, [
+ rec( 10, 2, ConnectionNumber ),
+ rec( 12, 2, LastRecordSeen ),
+ ])
+ pkt.Reply((18,272), [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 2, NumberOfSemaphores, var="x" ),
+ rec( 12, (6,260), SemaStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17E2, 23/226
+ pkt = NCP(0x17E2, "Get Semaphore Information", 'file')
+ pkt.Request((13,267), [
+ rec( 10, 2, LastRecordSeen ),
+ rec( 12, (1,255), SemaphoreName ),
+ ], info_str=(SemaphoreName, "Get Semaphore Information: %s", ", %s"))
+ pkt.Reply(17, [
+ rec( 8, 2, NextRequestRecord, BE ),
+ rec( 10, 2, OpenCount, BE ),
+ rec( 12, 1, SemaphoreValue ),
+ rec( 13, 1, NumberOfRecords, var="x" ),
+ rec( 14, 3, SemaInfoStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17E3, 23/227
+ pkt = NCP(0x17E3, "Get LAN Driver Configuration Information", 'stats')
+ pkt.Request(11, [
+ rec( 10, 1, LANDriverNumber ),
+ ])
+ pkt.Reply(180, [
+ rec( 8, 4, NetworkAddress, BE ),
+ rec( 12, 6, HostAddress ),
+ rec( 18, 1, BoardInstalled ),
+ rec( 19, 1, OptionNumber ),
+ rec( 20, 160, ConfigurationText ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17E5, 23/229
+ pkt = NCP(0x17E5, "Get Connection Usage Statistics", 'stats')
+ pkt.Request(12, [
+ rec( 10, 2, ConnectionNumber ),
+ ])
+ pkt.Reply(26, [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 6, BytesRead ),
+ rec( 16, 6, BytesWritten ),
+ rec( 22, 4, TotalRequestPackets ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17E6, 23/230
+ pkt = NCP(0x17E6, "Get Object's Remaining Disk Space", 'stats')
+ pkt.Request(14, [
+ rec( 10, 4, ObjectID, BE ),
+ ])
+ pkt.Reply(21, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 4, ObjectID ),
+ rec( 16, 4, UnusedDiskBlocks, BE ),
+ rec( 20, 1, RestrictionsEnforced ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17E7, 23/231
+ pkt = NCP(0x17E7, "Get File Server LAN I/O Statistics", 'stats')
+ pkt.Request(10)
+ pkt.Reply(74, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 2, ConfiguredMaxRoutingBuffers ),
+ rec( 14, 2, ActualMaxUsedRoutingBuffers ),
+ rec( 16, 2, CurrentlyUsedRoutingBuffers ),
+ rec( 18, 4, TotalFileServicePackets ),
+ rec( 22, 2, TurboUsedForFileService ),
+ rec( 24, 2, PacketsFromInvalidConnection ),
+ rec( 26, 2, BadLogicalConnectionCount ),
+ rec( 28, 2, PacketsReceivedDuringProcessing ),
+ rec( 30, 2, RequestsReprocessed ),
+ rec( 32, 2, PacketsWithBadSequenceNumber ),
+ rec( 34, 2, DuplicateRepliesSent ),
+ rec( 36, 2, PositiveAcknowledgesSent ),
+ rec( 38, 2, PacketsWithBadRequestType ),
+ rec( 40, 2, AttachDuringProcessing ),
+ rec( 42, 2, AttachWhileProcessingAttach ),
+ rec( 44, 2, ForgedDetachedRequests ),
+ rec( 46, 2, DetachForBadConnectionNumber ),
+ rec( 48, 2, DetachDuringProcessing ),
+ rec( 50, 2, RepliesCancelled ),
+ rec( 52, 2, PacketsDiscardedByHopCount ),
+ rec( 54, 2, PacketsDiscardedUnknownNet ),
+ rec( 56, 2, IncomingPacketDiscardedNoDGroup ),
+ rec( 58, 2, OutgoingPacketDiscardedNoTurboBuffer ),
+ rec( 60, 2, IPXNotMyNetwork ),
+ rec( 62, 4, NetBIOSBroadcastWasPropogated ),
+ rec( 66, 4, TotalOtherPackets ),
+ rec( 70, 4, TotalRoutedPackets ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17E8, 23/232
+ pkt = NCP(0x17E8, "Get File Server Misc Information", 'stats')
+ pkt.Request(10)
+ pkt.Reply(40, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 1, ProcessorType ),
+ rec( 13, 1, Reserved ),
+ rec( 14, 1, NumberOfServiceProcesses ),
+ rec( 15, 1, ServerUtilizationPercentage ),
+ rec( 16, 2, ConfiguredMaxBinderyObjects ),
+ rec( 18, 2, ActualMaxBinderyObjects ),
+ rec( 20, 2, CurrentUsedBinderyObjects ),
+ rec( 22, 2, TotalServerMemory ),
+ rec( 24, 2, WastedServerMemory ),
+ rec( 26, 2, NumberOfDynamicMemoryAreas, var="x" ),
+ rec( 28, 12, DynMemStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17E9, 23/233
+ pkt = NCP(0x17E9, "Get Volume Information", 'stats')
+ pkt.Request(11, [
+ rec( 10, 1, VolumeNumber ),
+ ],info_str=(VolumeNumber, "Get Information on Volume %d", ", %d"))
+ pkt.Reply(48, [
+ rec( 8, 4, SystemIntervalMarker, BE ),
+ rec( 12, 1, VolumeNumber ),
+ rec( 13, 1, LogicalDriveNumber ),
+ rec( 14, 2, BlockSize ),
+ rec( 16, 2, StartingBlock ),
+ rec( 18, 2, TotalBlocks ),
+ rec( 20, 2, FreeBlocks ),
+ rec( 22, 2, TotalDirectoryEntries ),
+ rec( 24, 2, FreeDirectoryEntries ),
+ rec( 26, 2, ActualMaxUsedDirectoryEntries ),
+ rec( 28, 1, VolumeHashedFlag ),
+ rec( 29, 1, VolumeCachedFlag ),
+ rec( 30, 1, VolumeRemovableFlag ),
+ rec( 31, 1, VolumeMountedFlag ),
+ rec( 32, 16, VolumeName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17EA, 23/234
+ pkt = NCP(0x17EA, "Get Connection's Task Information", 'stats')
+ pkt.Request(12, [
+ rec( 10, 2, ConnectionNumber ),
+ ])
+ pkt.Reply(18, [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 4, NumberOfAttributes, var="x" ),
+ rec( 14, 4, Attributes, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17EB, 23/235
+ pkt = NCP(0x17EB, "Get Connection's Open Files", 'file')
+ pkt.Request(14, [
+ rec( 10, 2, ConnectionNumber ),
+ rec( 12, 2, LastRecordSeen ),
+ ])
+ pkt.Reply((29,283), [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 2, NumberOfRecords, var="x" ),
+ rec( 12, (17, 271), OpnFilesStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17EC, 23/236
+ pkt = NCP(0x17EC, "Get Connection Using A File", 'file')
+ pkt.Request(18, [
+ rec( 10, 1, DataStreamNumber ),
+ rec( 11, 1, VolumeNumber ),
+ rec( 12, 4, DirectoryBase, LE ),
+ rec( 16, 2, LastRecordSeen ),
+ ])
+ pkt.Reply(33, [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 2, UseCount ),
+ rec( 12, 2, OpenCount ),
+ rec( 14, 2, OpenForReadCount ),
+ rec( 16, 2, OpenForWriteCount ),
+ rec( 18, 2, DenyReadCount ),
+ rec( 20, 2, DenyWriteCount ),
+ rec( 22, 1, Locked ),
+ rec( 23, 1, ForkCount ),
+ rec( 24, 2, NumberOfRecords, var="x" ),
+ rec( 26, 7, ConnStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xff00])
+ # 2222/17ED, 23/237
+ pkt = NCP(0x17ED, "Get Physical Record Locks By Connection And File", 'file')
+ pkt.Request(20, [
+ rec( 10, 2, TargetConnectionNumber ),
+ rec( 12, 1, DataStreamNumber ),
+ rec( 13, 1, VolumeNumber ),
+ rec( 14, 4, DirectoryBase, LE ),
+ rec( 18, 2, LastRecordSeen ),
+ ])
+ pkt.Reply(23, [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 2, NumberOfLocks, var="x" ),
+ rec( 12, 11, LockStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17EE, 23/238
+ pkt = NCP(0x17EE, "Get Physical Record Locks By File", 'file')
+ pkt.Request(18, [
+ rec( 10, 1, DataStreamNumber ),
+ rec( 11, 1, VolumeNumber ),
+ rec( 12, 4, DirectoryBase ),
+ rec( 16, 2, LastRecordSeen ),
+ ])
+ pkt.Reply(30, [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 2, NumberOfLocks, var="x" ),
+ rec( 12, 18, PhyLockStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17EF, 23/239
+ pkt = NCP(0x17EF, "Get Logical Records By Connection", 'file')
+ pkt.Request(14, [
+ rec( 10, 2, TargetConnectionNumber ),
+ rec( 12, 2, LastRecordSeen ),
+ ])
+ pkt.Reply((16,270), [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 2, NumberOfRecords, var="x" ),
+ rec( 12, (4, 258), LogLockStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17F0, 23/240
+ pkt = NCP(0x17F0, "Get Logical Record Information (old)", 'file')
+ pkt.Request((13,267), [
+ rec( 10, 2, LastRecordSeen ),
+ rec( 12, (1,255), LogicalRecordName ),
+ ])
+ pkt.Reply(22, [
+ rec( 8, 2, ShareableLockCount ),
+ rec( 10, 2, UseCount ),
+ rec( 12, 1, Locked ),
+ rec( 13, 2, NextRequestRecord ),
+ rec( 15, 2, NumberOfRecords, var="x" ),
+ rec( 17, 5, LogRecStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17F1, 23/241
+ pkt = NCP(0x17F1, "Get Connection's Semaphores", 'file')
+ pkt.Request(14, [
+ rec( 10, 2, ConnectionNumber ),
+ rec( 12, 2, LastRecordSeen ),
+ ])
+ pkt.Reply((19,273), [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 2, NumberOfSemaphores, var="x" ),
+ rec( 12, (7, 261), SemaStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17F2, 23/242
+ pkt = NCP(0x17F2, "Get Semaphore Information", 'file')
+ pkt.Request((13,267), [
+ rec( 10, 2, LastRecordSeen ),
+ rec( 12, (1,255), SemaphoreName ),
+ ], info_str=(SemaphoreName, "Get Semaphore Information: %s", ", %s"))
+ pkt.Reply(20, [
+ rec( 8, 2, NextRequestRecord ),
+ rec( 10, 2, OpenCount ),
+ rec( 12, 2, SemaphoreValue ),
+ rec( 14, 2, NumberOfRecords, var="x" ),
+ rec( 16, 4, SemaInfoStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17F3, 23/243
+ pkt = NCP(0x17F3, "Map Directory Number to Path", 'file')
+ pkt.Request(16, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, DirectoryNumber ),
+ rec( 15, 1, NameSpace ),
+ ])
+ pkt.Reply((9,263), [
+ rec( 8, (1,255), Path ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9c00, 0xc601, 0xfd00, 0xff00])
+ # 2222/17F4, 23/244
+ pkt = NCP(0x17F4, "Convert Path to Dir Entry", 'file')
+ pkt.Request((12,266), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, (1,255), Path ),
+ ], info_str=(Path, "Convert Path to Directory Entry: %s", ", %s"))
+ pkt.Reply(13, [
+ rec( 8, 1, VolumeNumber ),
+ rec( 9, 4, DirectoryNumber ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xc601, 0xfd00, 0xff00])
+ # 2222/17FD, 23/253
+ pkt = NCP(0x17FD, "Send Console Broadcast", 'stats')
+ pkt.Request((16, 270), [
+ rec( 10, 1, NumberOfStations, var="x" ),
+ rec( 11, 4, StationList, repeat="x" ),
+ rec( 15, (1, 255), TargetMessage ),
+ ], info_str=(TargetMessage, "Send Console Broadcast: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601, 0xfd00])
+ # 2222/17FE, 23/254
+ pkt = NCP(0x17FE, "Clear Connection Number", 'stats')
+ pkt.Request(14, [
+ rec( 10, 4, ConnectionNumber ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xc601, 0xfd00])
+ # 2222/18, 24
+ pkt = NCP(0x18, "End of Job", 'connection')
+ pkt.Request(7)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/19, 25
+ pkt = NCP(0x19, "Logout", 'connection')
+ pkt.Request(7)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/1A, 26
+ pkt = NCP(0x1A, "Log Physical Record", 'file')
+ pkt.Request(24, [
+ rec( 7, 1, LockFlag ),
+ rec( 8, 6, FileHandle ),
+ rec( 14, 4, LockAreasStartOffset, BE ),
+ rec( 18, 4, LockAreaLen, BE ),
+ rec( 22, 2, LockTimeout ),
+ ], info_str=(LockAreaLen, "Lock Record - Length of %d", "%d"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0x9600, 0xfd02, 0xfe04, 0xff01])
+ # 2222/1B, 27
+ pkt = NCP(0x1B, "Lock Physical Record Set", 'file')
+ pkt.Request(10, [
+ rec( 7, 1, LockFlag ),
+ rec( 8, 2, LockTimeout ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0x9600, 0xfd02, 0xfe04, 0xff01])
+ # 2222/1C, 28
+ pkt = NCP(0x1C, "Release Physical Record", 'file')
+ pkt.Request(22, [
+ rec( 7, 1, Reserved ),
+ rec( 8, 6, FileHandle ),
+ rec( 14, 4, LockAreasStartOffset ),
+ rec( 18, 4, LockAreaLen ),
+ ], info_str=(LockAreaLen, "Release Lock Record - Length of %d", "%d"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0x9600, 0xfd02, 0xfe04, 0xff03])
+ # 2222/1D, 29
+ pkt = NCP(0x1D, "Release Physical Record Set", 'file')
+ pkt.Request(8, [
+ rec( 7, 1, LockFlag ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0x9600, 0xfd02, 0xfe04, 0xff03])
+ # 2222/1E, 30 #Tested and fixed 6-14-02 GM
+ pkt = NCP(0x1E, "Clear Physical Record", 'file')
+ pkt.Request(22, [
+ rec( 7, 1, Reserved ),
+ rec( 8, 6, FileHandle ),
+ rec( 14, 4, LockAreasStartOffset, BE ),
+ rec( 18, 4, LockAreaLen, BE ),
+ ], info_str=(LockAreaLen, "Clear Lock Record - Length of %d", "%d"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0x9600, 0xfd02, 0xfe04, 0xff03])
+ # 2222/1F, 31
+ pkt = NCP(0x1F, "Clear Physical Record Set", 'file')
+ pkt.Request(8, [
+ rec( 7, 1, LockFlag ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0x9600, 0xfd02, 0xfe04, 0xff03])
+ # 2222/2000, 32/00
+ pkt = NCP(0x2000, "Open Semaphore", 'file', has_length=0)
+ pkt.Request(10, [
+ rec( 8, 1, InitialSemaphoreValue ),
+ rec( 9, 1, SemaphoreNameLen ),
+ ])
+ pkt.Reply(13, [
+ rec( 8, 4, SemaphoreHandle, BE ),
+ rec( 12, 1, SemaphoreOpenCount ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xff01])
+ # 2222/2001, 32/01
+ pkt = NCP(0x2001, "Examine Semaphore", 'file', has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, SemaphoreHandle, BE ),
+ ])
+ pkt.Reply(10, [
+ rec( 8, 1, SemaphoreValue ),
+ rec( 9, 1, SemaphoreOpenCount ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xff01])
+ # 2222/2002, 32/02
+ pkt = NCP(0x2002, "Wait On Semaphore", 'file', has_length=0)
+ pkt.Request(14, [
+ rec( 8, 4, SemaphoreHandle, BE ),
+ rec( 12, 2, SemaphoreTimeOut, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xff01])
+ # 2222/2003, 32/03
+ pkt = NCP(0x2003, "Signal Semaphore", 'file', has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, SemaphoreHandle, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xff01])
+ # 2222/2004, 32/04
+ pkt = NCP(0x2004, "Close Semaphore", 'file', has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, SemaphoreHandle, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xff01])
+ # 2222/21, 33
+ pkt = NCP(0x21, "Negotiate Buffer Size", 'connection')
+ pkt.Request(9, [
+ rec( 7, 2, BufferSize, BE ),
+ ])
+ pkt.Reply(10, [
+ rec( 8, 2, BufferSize, BE ),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/2200, 34/00
+ pkt = NCP(0x2200, "TTS Is Available", 'tts', has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0001, 0xfd03, 0xff12])
+ # 2222/2201, 34/01
+ pkt = NCP(0x2201, "TTS Begin Transaction", 'tts', has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/2202, 34/02
+ pkt = NCP(0x2202, "TTS End Transaction", 'tts', has_length=0)
+ pkt.Request(8)
+ pkt.Reply(12, [
+ rec( 8, 4, TransactionNumber, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xff01])
+ # 2222/2203, 34/03
+ pkt = NCP(0x2203, "TTS Abort Transaction", 'tts', has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xfd03, 0xfe0b, 0xff01])
+ # 2222/2204, 34/04
+ pkt = NCP(0x2204, "TTS Transaction Status", 'tts', has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, TransactionNumber, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/2205, 34/05
+ pkt = NCP(0x2205, "TTS Get Application Thresholds", 'tts', has_length=0)
+ pkt.Request(8)
+ pkt.Reply(10, [
+ rec( 8, 1, LogicalLockThreshold ),
+ rec( 9, 1, PhysicalLockThreshold ),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/2206, 34/06
+ pkt = NCP(0x2206, "TTS Set Application Thresholds", 'tts', has_length=0)
+ pkt.Request(10, [
+ rec( 8, 1, LogicalLockThreshold ),
+ rec( 9, 1, PhysicalLockThreshold ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600])
+ # 2222/2207, 34/07
+ pkt = NCP(0x2207, "TTS Get Workstation Thresholds", 'tts', has_length=0)
+ pkt.Request(10, [
+ rec( 8, 1, LogicalLockThreshold ),
+ rec( 9, 1, PhysicalLockThreshold ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/2208, 34/08
+ pkt = NCP(0x2208, "TTS Set Workstation Thresholds", 'tts', has_length=0)
+ pkt.Request(10, [
+ rec( 8, 1, LogicalLockThreshold ),
+ rec( 9, 1, PhysicalLockThreshold ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/2209, 34/09
+ pkt = NCP(0x2209, "TTS Get Transaction Bits", 'tts', has_length=0)
+ pkt.Request(8)
+ pkt.Reply(9, [
+ rec( 8, 1, ControlFlags ),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/220A, 34/10
+ pkt = NCP(0x220A, "TTS Set Transaction Bits", 'tts', has_length=0)
+ pkt.Request(9, [
+ rec( 8, 1, ControlFlags ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/2301, 35/01
+ pkt = NCP(0x2301, "AFP Create Directory", 'afp')
+ pkt.Request((49, 303), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, BaseDirectoryID ),
+ rec( 15, 1, Reserved ),
+ rec( 16, 4, CreatorID ),
+ rec( 20, 4, Reserved4 ),
+ rec( 24, 2, FinderAttr ),
+ rec( 26, 2, HorizLocation ),
+ rec( 28, 2, VertLocation ),
+ rec( 30, 2, FileDirWindow ),
+ rec( 32, 16, Reserved16 ),
+ rec( 48, (1,255), Path ),
+ ], info_str=(Path, "AFP Create Directory: %s", ", %s"))
+ pkt.Reply(12, [
+ rec( 8, 4, NewDirectoryID ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8400, 0x8800, 0x9300, 0x9600, 0x9804,
+ 0x9900, 0x9c03, 0x9e02, 0xa100, 0xa201, 0xfd00, 0xff18])
+ # 2222/2302, 35/02
+ pkt = NCP(0x2302, "AFP Create File", 'afp')
+ pkt.Request((49, 303), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, BaseDirectoryID ),
+ rec( 15, 1, DeleteExistingFileFlag ),
+ rec( 16, 4, CreatorID, BE ),
+ rec( 20, 4, Reserved4 ),
+ rec( 24, 2, FinderAttr ),
+ rec( 26, 2, HorizLocation, BE ),
+ rec( 28, 2, VertLocation, BE ),
+ rec( 30, 2, FileDirWindow, BE ),
+ rec( 32, 16, Reserved16 ),
+ rec( 48, (1,255), Path ),
+ ], info_str=(Path, "AFP Create File: %s", ", %s"))
+ pkt.Reply(12, [
+ rec( 8, 4, NewDirectoryID ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8301, 0x8400, 0x8701, 0x8800,
+ 0x8a00, 0x8d00, 0x8e00, 0x8f00, 0x9300, 0x9600, 0x9804,
+ 0x9900, 0x9b03, 0x9c03, 0x9e02, 0xa100, 0xa201, 0xfd00,
+ 0xff18])
+ # 2222/2303, 35/03
+ pkt = NCP(0x2303, "AFP Delete", 'afp')
+ pkt.Request((16,270), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, BaseDirectoryID ),
+ rec( 15, (1,255), Path ),
+ ], info_str=(Path, "AFP Delete: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8800, 0x8a00, 0x8d00, 0x8e00, 0x8f00,
+ 0x9000, 0x9300, 0x9600, 0x9804, 0x9b03, 0x9c03, 0x9e02,
+ 0xa000, 0xa100, 0xa201, 0xfd00, 0xff19])
+ # 2222/2304, 35/04
+ pkt = NCP(0x2304, "AFP Get Entry ID From Name", 'afp')
+ pkt.Request((16,270), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, BaseDirectoryID ),
+ rec( 15, (1,255), Path ),
+ ], info_str=(Path, "AFP Get Entry from Name: %s", ", %s"))
+ pkt.Reply(12, [
+ rec( 8, 4, TargetEntryID, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8800, 0x9300, 0x9600, 0x9804, 0x9c03,
+ 0xa100, 0xa201, 0xfd00, 0xff19])
+ # 2222/2305, 35/05
+ pkt = NCP(0x2305, "AFP Get File Information", 'afp')
+ pkt.Request((18,272), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, BaseDirectoryID ),
+ rec( 15, 2, RequestBitMap, BE ),
+ rec( 17, (1,255), Path ),
+ ], info_str=(Path, "AFP Get File Information: %s", ", %s"))
+ pkt.Reply(121, [
+ rec( 8, 4, AFPEntryID, BE ),
+ rec( 12, 4, ParentID, BE ),
+ rec( 16, 2, AttributesDef16, LE ),
+ rec( 18, 4, DataForkLen, BE ),
+ rec( 22, 4, ResourceForkLen, BE ),
+ rec( 26, 2, TotalOffspring, BE ),
+ rec( 28, 2, CreationDate, BE ),
+ rec( 30, 2, LastAccessedDate, BE ),
+ rec( 32, 2, ModifiedDate, BE ),
+ rec( 34, 2, ModifiedTime, BE ),
+ rec( 36, 2, ArchivedDate, BE ),
+ rec( 38, 2, ArchivedTime, BE ),
+ rec( 40, 4, CreatorID, BE ),
+ rec( 44, 4, Reserved4 ),
+ rec( 48, 2, FinderAttr ),
+ rec( 50, 2, HorizLocation ),
+ rec( 52, 2, VertLocation ),
+ rec( 54, 2, FileDirWindow ),
+ rec( 56, 16, Reserved16 ),
+ rec( 72, 32, LongName ),
+ rec( 104, 4, CreatorID, BE ),
+ rec( 108, 12, ShortName ),
+ rec( 120, 1, AccessPrivileges ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8800, 0x9300, 0x9600, 0x9804, 0x9c03,
+ 0xa100, 0xa201, 0xfd00, 0xff19])
+ # 2222/2306, 35/06
+ pkt = NCP(0x2306, "AFP Get Entry ID From NetWare Handle", 'afp')
+ pkt.Request(16, [
+ rec( 10, 6, FileHandle ),
+ ])
+ pkt.Reply(14, [
+ rec( 8, 1, VolumeID ),
+ rec( 9, 4, TargetEntryID, BE ),
+ rec( 13, 1, ForkIndicator ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8800, 0x9300, 0x9600, 0xa201])
+ # 2222/2307, 35/07
+ pkt = NCP(0x2307, "AFP Rename", 'afp')
+ pkt.Request((21, 529), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, MacSourceBaseID, BE ),
+ rec( 15, 4, MacDestinationBaseID, BE ),
+ rec( 19, (1,255), Path ),
+ rec( -1, (1,255), NewFileNameLen ),
+ ], info_str=(Path, "AFP Rename: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8401, 0x8800, 0x8b00, 0x8e00,
+ 0x9001, 0x9201, 0x9300, 0x9600, 0x9804, 0x9900,
+ 0x9c03, 0x9e00, 0xa100, 0xa201, 0xfd00, 0xff0a])
+ # 2222/2308, 35/08
+ pkt = NCP(0x2308, "AFP Open File Fork", 'afp')
+ pkt.Request((18, 272), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, MacBaseDirectoryID ),
+ rec( 15, 1, ForkIndicator ),
+ rec( 16, 1, AccessMode ),
+ rec( 17, (1,255), Path ),
+ ], info_str=(Path, "AFP Open File Fork: %s", ", %s"))
+ pkt.Reply(22, [
+ rec( 8, 4, AFPEntryID, BE ),
+ rec( 12, 4, DataForkLen, BE ),
+ rec( 16, 6, NetWareAccessHandle ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8301, 0x8800, 0x9300,
+ 0x9400, 0x9600, 0x9804, 0x9900, 0x9c03, 0xa100,
+ 0xa201, 0xfd00, 0xff16])
+ # 2222/2309, 35/09
+ pkt = NCP(0x2309, "AFP Set File Information", 'afp')
+ pkt.Request((64, 318), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, MacBaseDirectoryID ),
+ rec( 15, 2, RequestBitMap, BE ),
+ rec( 17, 2, MacAttr, BE ),
+ rec( 19, 2, CreationDate, BE ),
+ rec( 21, 2, LastAccessedDate, BE ),
+ rec( 23, 2, ModifiedDate, BE ),
+ rec( 25, 2, ModifiedTime, BE ),
+ rec( 27, 2, ArchivedDate, BE ),
+ rec( 29, 2, ArchivedTime, BE ),
+ rec( 31, 4, CreatorID, BE ),
+ rec( 35, 4, Reserved4 ),
+ rec( 39, 2, FinderAttr ),
+ rec( 41, 2, HorizLocation ),
+ rec( 43, 2, VertLocation ),
+ rec( 45, 2, FileDirWindow ),
+ rec( 47, 16, Reserved16 ),
+ rec( 63, (1,255), Path ),
+ ], info_str=(Path, "AFP Set File Information: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0104, 0x8301, 0x8800, 0x9300, 0x9400,
+ 0x9500, 0x9600, 0x9804, 0x9c03, 0xa100, 0xa201,
+ 0xfd00, 0xff16])
+ # 2222/230A, 35/10
+ pkt = NCP(0x230A, "AFP Scan File Information", 'afp')
+ pkt.Request((26, 280), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, MacBaseDirectoryID ),
+ rec( 15, 4, MacLastSeenID, BE ),
+ rec( 19, 2, DesiredResponseCount, BE ),
+ rec( 21, 2, SearchBitMap, BE ),
+ rec( 23, 2, RequestBitMap, BE ),
+ rec( 25, (1,255), Path ),
+ ], info_str=(Path, "AFP Scan File Information: %s", ", %s"))
+ pkt.Reply(123, [
+ rec( 8, 2, ActualResponseCount, BE, var="x" ),
+ rec( 10, 113, AFP10Struct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8800, 0x9300, 0x9600, 0x9804,
+ 0x9c03, 0xa100, 0xa201, 0xfd00, 0xff16])
+ # 2222/230B, 35/11
+ pkt = NCP(0x230B, "AFP Alloc Temporary Directory Handle", 'afp')
+ pkt.Request((16,270), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, MacBaseDirectoryID ),
+ rec( 15, (1,255), Path ),
+ ], info_str=(Path, "AFP Allocate Temporary Directory Handle: %s", ", %s"))
+ pkt.Reply(10, [
+ rec( 8, 1, DirHandle ),
+ rec( 9, 1, AccessRightsMask ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8800, 0x9300, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0x9d00, 0xa100,
+ 0xa201, 0xfd00, 0xff00])
+ # 2222/230C, 35/12
+ pkt = NCP(0x230C, "AFP Get Entry ID From Path Name", 'afp')
+ pkt.Request((12,266), [
+ rec( 10, 1, DirHandle ),
+ rec( 11, (1,255), Path ),
+ ], info_str=(Path, "AFP Get Entry ID from Path Name: %s", ", %s"))
+ pkt.Reply(12, [
+ rec( 8, 4, AFPEntryID, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8800, 0x9300, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa100, 0xa201,
+ 0xfd00, 0xff00])
+ # 2222/230D, 35/13
+ pkt = NCP(0x230D, "AFP 2.0 Create Directory", 'afp')
+ pkt.Request((55,309), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, BaseDirectoryID ),
+ rec( 15, 1, Reserved ),
+ rec( 16, 4, CreatorID, BE ),
+ rec( 20, 4, Reserved4 ),
+ rec( 24, 2, FinderAttr ),
+ rec( 26, 2, HorizLocation ),
+ rec( 28, 2, VertLocation ),
+ rec( 30, 2, FileDirWindow ),
+ rec( 32, 16, Reserved16 ),
+ rec( 48, 6, ProDOSInfo ),
+ rec( 54, (1,255), Path ),
+ ], info_str=(Path, "AFP 2.0 Create Directory: %s", ", %s"))
+ pkt.Reply(12, [
+ rec( 8, 4, NewDirectoryID ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8400, 0x8800, 0x9300,
+ 0x9600, 0x9804, 0x9900, 0x9c03, 0x9e00,
+ 0xa100, 0xa201, 0xfd00, 0xff00])
+ # 2222/230E, 35/14
+ pkt = NCP(0x230E, "AFP 2.0 Create File", 'afp')
+ pkt.Request((55,309), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, BaseDirectoryID ),
+ rec( 15, 1, DeleteExistingFileFlag ),
+ rec( 16, 4, CreatorID, BE ),
+ rec( 20, 4, Reserved4 ),
+ rec( 24, 2, FinderAttr ),
+ rec( 26, 2, HorizLocation ),
+ rec( 28, 2, VertLocation ),
+ rec( 30, 2, FileDirWindow ),
+ rec( 32, 16, Reserved16 ),
+ rec( 48, 6, ProDOSInfo ),
+ rec( 54, (1,255), Path ),
+ ], info_str=(Path, "AFP 2.0 Create File: %s", ", %s"))
+ pkt.Reply(12, [
+ rec( 8, 4, NewDirectoryID ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8301, 0x8400,
+ 0x8701, 0x8800, 0x8a00, 0x8d00, 0x8e00,
+ 0x8f00, 0x9001, 0x9300, 0x9600, 0x9804,
+ 0x9900, 0x9b03, 0x9c03, 0x9e00, 0xa100,
+ 0xa201, 0xfd00, 0xff00])
+ # 2222/230F, 35/15
+ pkt = NCP(0x230F, "AFP 2.0 Get File Or Directory Information", 'afp')
+ pkt.Request((18,272), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, BaseDirectoryID ),
+ rec( 15, 2, RequestBitMap, BE ),
+ rec( 17, (1,255), Path ),
+ ], info_str=(Path, "AFP 2.0 Get Information: %s", ", %s"))
+ pkt.Reply(128, [
+ rec( 8, 4, AFPEntryID, BE ),
+ rec( 12, 4, ParentID, BE ),
+ rec( 16, 2, AttributesDef16 ),
+ rec( 18, 4, DataForkLen, BE ),
+ rec( 22, 4, ResourceForkLen, BE ),
+ rec( 26, 2, TotalOffspring, BE ),
+ rec( 28, 2, CreationDate, BE ),
+ rec( 30, 2, LastAccessedDate, BE ),
+ rec( 32, 2, ModifiedDate, BE ),
+ rec( 34, 2, ModifiedTime, BE ),
+ rec( 36, 2, ArchivedDate, BE ),
+ rec( 38, 2, ArchivedTime, BE ),
+ rec( 40, 4, CreatorID, BE ),
+ rec( 44, 4, Reserved4 ),
+ rec( 48, 2, FinderAttr ),
+ rec( 50, 2, HorizLocation ),
+ rec( 52, 2, VertLocation ),
+ rec( 54, 2, FileDirWindow ),
+ rec( 56, 16, Reserved16 ),
+ rec( 72, 32, LongName ),
+ rec( 104, 4, CreatorID, BE ),
+ rec( 108, 12, ShortName ),
+ rec( 120, 1, AccessPrivileges ),
+ rec( 121, 1, Reserved ),
+ rec( 122, 6, ProDOSInfo ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8800, 0x9300, 0x9600, 0x9804, 0x9c03,
+ 0xa100, 0xa201, 0xfd00, 0xff19])
+ # 2222/2310, 35/16
+ pkt = NCP(0x2310, "AFP 2.0 Set File Information", 'afp')
+ pkt.Request((70, 324), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, MacBaseDirectoryID ),
+ rec( 15, 2, RequestBitMap, BE ),
+ rec( 17, 2, AttributesDef16 ),
+ rec( 19, 2, CreationDate, BE ),
+ rec( 21, 2, LastAccessedDate, BE ),
+ rec( 23, 2, ModifiedDate, BE ),
+ rec( 25, 2, ModifiedTime, BE ),
+ rec( 27, 2, ArchivedDate, BE ),
+ rec( 29, 2, ArchivedTime, BE ),
+ rec( 31, 4, CreatorID, BE ),
+ rec( 35, 4, Reserved4 ),
+ rec( 39, 2, FinderAttr ),
+ rec( 41, 2, HorizLocation ),
+ rec( 43, 2, VertLocation ),
+ rec( 45, 2, FileDirWindow ),
+ rec( 47, 16, Reserved16 ),
+ rec( 63, 6, ProDOSInfo ),
+ rec( 69, (1,255), Path ),
+ ], info_str=(Path, "AFP 2.0 Set File Information: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0104, 0x8301, 0x8800, 0x9300, 0x9400,
+ 0x9500, 0x9600, 0x9804, 0x9c03, 0xa100, 0xa201,
+ 0xfd00, 0xff16])
+ # 2222/2311, 35/17
+ pkt = NCP(0x2311, "AFP 2.0 Scan File Information", 'afp')
+ pkt.Request((26, 280), [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, MacBaseDirectoryID ),
+ rec( 15, 4, MacLastSeenID, BE ),
+ rec( 19, 2, DesiredResponseCount, BE ),
+ rec( 21, 2, SearchBitMap, BE ),
+ rec( 23, 2, RequestBitMap, BE ),
+ rec( 25, (1,255), Path ),
+ ], info_str=(Path, "AFP 2.0 Scan File Information: %s", ", %s"))
+ pkt.Reply(14, [
+ rec( 8, 2, ActualResponseCount, var="x" ),
+ rec( 10, 4, AFP20Struct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8301, 0x8800, 0x9300, 0x9600, 0x9804,
+ 0x9c03, 0xa100, 0xa201, 0xfd00, 0xff16])
+ # 2222/2312, 35/18
+ pkt = NCP(0x2312, "AFP Get DOS Name From Entry ID", 'afp')
+ pkt.Request(15, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, AFPEntryID, BE ),
+ ])
+ pkt.Reply((9,263), [
+ rec( 8, (1,255), Path ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8900, 0x9600, 0xbf00])
+ # 2222/2313, 35/19
+ pkt = NCP(0x2313, "AFP Get Macintosh Info On Deleted File", 'afp')
+ pkt.Request(15, [
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, DirectoryNumber, BE ),
+ ])
+ pkt.Reply((51,305), [
+ rec( 8, 4, CreatorID, BE ),
+ rec( 12, 4, Reserved4 ),
+ rec( 16, 2, FinderAttr ),
+ rec( 18, 2, HorizLocation ),
+ rec( 20, 2, VertLocation ),
+ rec( 22, 2, FileDirWindow ),
+ rec( 24, 16, Reserved16 ),
+ rec( 40, 6, ProDOSInfo ),
+ rec( 46, 4, ResourceForkSize, BE ),
+ rec( 50, (1,255), FileName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9c03, 0xbf00])
+ # 2222/2400, 36/00
+ pkt = NCP(0x2400, "Get NCP Extension Information", 'fileserver')
+ pkt.Request(14, [
+ rec( 10, 4, NCPextensionNumber, LE ),
+ ])
+ pkt.Reply((16,270), [
+ rec( 8, 4, NCPextensionNumber ),
+ rec( 12, 1, NCPextensionMajorVersion ),
+ rec( 13, 1, NCPextensionMinorVersion ),
+ rec( 14, 1, NCPextensionRevisionNumber ),
+ rec( 15, (1, 255), NCPextensionName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfe00])
+ # 2222/2401, 36/01
+ pkt = NCP(0x2401, "Get NCP Extension Maximum Data Size", 'fileserver')
+ pkt.Request(10)
+ pkt.Reply(10, [
+ rec( 8, 2, NCPdataSize ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfe00])
+ # 2222/2402, 36/02
+ pkt = NCP(0x2402, "Get NCP Extension Information by Name", 'fileserver')
+ pkt.Request((11, 265), [
+ rec( 10, (1,255), NCPextensionName ),
+ ], info_str=(NCPextensionName, "Get NCP Extension Information by Name: %s", ", %s"))
+ pkt.Reply((16,270), [
+ rec( 8, 4, NCPextensionNumber ),
+ rec( 12, 1, NCPextensionMajorVersion ),
+ rec( 13, 1, NCPextensionMinorVersion ),
+ rec( 14, 1, NCPextensionRevisionNumber ),
+ rec( 15, (1, 255), NCPextensionName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfe00, 0xff20])
+ # 2222/2403, 36/03
+ pkt = NCP(0x2403, "Get Number of Registered NCP Extensions", 'fileserver')
+ pkt.Request(10)
+ pkt.Reply(12, [
+ rec( 8, 4, NumberOfNCPExtensions ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfe00])
+ # 2222/2404, 36/04
+ pkt = NCP(0x2404, "Get NCP Extension Registered Verbs List", 'fileserver')
+ pkt.Request(14, [
+ rec( 10, 4, StartingNumber ),
+ ])
+ pkt.Reply(20, [
+ rec( 8, 4, ReturnedListCount, var="x" ),
+ rec( 12, 4, nextStartingNumber ),
+ rec( 16, 4, NCPExtensionNumbers, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfe00])
+ # 2222/2405, 36/05
+ pkt = NCP(0x2405, "Return NCP Extension Information", 'fileserver')
+ pkt.Request(14, [
+ rec( 10, 4, NCPextensionNumber ),
+ ])
+ pkt.Reply((16,270), [
+ rec( 8, 4, NCPextensionNumber ),
+ rec( 12, 1, NCPextensionMajorVersion ),
+ rec( 13, 1, NCPextensionMinorVersion ),
+ rec( 14, 1, NCPextensionRevisionNumber ),
+ rec( 15, (1, 255), NCPextensionName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfe00])
+ # 2222/2406, 36/06
+ pkt = NCP(0x2406, "Return NCP Extension Maximum Data Size", 'fileserver')
+ pkt.Request(10)
+ pkt.Reply(12, [
+ rec( 8, 4, NCPdataSize ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfe00])
+ # 2222/25, 37
+ pkt = NCP(0x25, "Execute NCP Extension", 'fileserver')
+ pkt.Request(11, [
+ rec( 7, 4, NCPextensionNumber ),
+ # The following value is Unicode
+ #rec[ 13, (1,255), RequestData ],
+ ])
+ pkt.Reply(8)
+ # The following value is Unicode
+ #[ 8, (1, 255), ReplyBuffer ],
+ pkt.CompletionCodes([0x0000, 0xd504, 0xee00, 0xfe00])
+ # 2222/3B, 59
+ pkt = NCP(0x3B, "Commit File", 'file', has_length=0 )
+ pkt.Request(14, [
+ rec( 7, 1, Reserved ),
+ rec( 8, 6, FileHandle ),
+ ], info_str=(FileHandle, "Commit File - 0x%s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0x9804, 0xff00])
+ # 2222/3E, 62
+ pkt = NCP(0x3E, "File Search Initialize", 'file', has_length=0 )
+ pkt.Request((9, 263), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, (1,255), Path ),
+ ], info_str=(Path, "Initialize File Search: %s", ", %s"))
+ pkt.Reply(14, [
+ rec( 8, 1, VolumeNumber ),
+ rec( 9, 2, DirectoryID ),
+ rec( 11, 2, SequenceNumber, BE ),
+ rec( 13, 1, AccessRightsMask ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0x9804, 0x9b03, 0x9c03, 0xa100,
+ 0xfd00, 0xff16])
+ # 2222/3F, 63
+ pkt = NCP(0x3F, "File Search Continue", 'file', has_length=0 )
+ pkt.Request((14, 268), [
+ rec( 7, 1, VolumeNumber ),
+ rec( 8, 2, DirectoryID ),
+ rec( 10, 2, SequenceNumber, BE ),
+ rec( 12, 1, SearchAttributes ),
+ rec( 13, (1,255), Path ),
+ ], info_str=(Path, "File Search Continue: %s", ", %s"))
+ pkt.Reply( NO_LENGTH_CHECK, [
+ #
+ # XXX - don't show this if we got back a non-zero
+ # completion code? For example, 255 means "No
+ # matching files or directories were found", so
+ # presumably it can't show you a matching file or
+ # directory instance - it appears to just leave crap
+ # there.
+ #
+ srec( DirectoryInstance, req_cond="ncp.sattr_sub==TRUE"),
+ srec( FileInstance, req_cond="ncp.sattr_sub!=TRUE"),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0xff16])
+ # 2222/40, 64
+ pkt = NCP(0x40, "Search for a File", 'file')
+ pkt.Request((12, 266), [
+ rec( 7, 2, SequenceNumber, BE ),
+ rec( 9, 1, DirHandle ),
+ rec( 10, 1, SearchAttributes ),
+ rec( 11, (1,255), FileName ),
+ ], info_str=(FileName, "Search for File: %s", ", %s"))
+ pkt.Reply(40, [
+ rec( 8, 2, SequenceNumber, BE ),
+ rec( 10, 2, Reserved2 ),
+ rec( 12, 14, FileName14 ),
+ rec( 26, 1, AttributesDef ),
+ rec( 27, 1, FileExecuteType ),
+ rec( 28, 4, FileSize ),
+ rec( 32, 2, CreationDate, BE ),
+ rec( 34, 2, LastAccessedDate, BE ),
+ rec( 36, 2, ModifiedDate, BE ),
+ rec( 38, 2, ModifiedTime, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8900, 0x9600, 0x9804, 0x9b03,
+ 0x9c03, 0xa100, 0xfd00, 0xff16])
+ # 2222/41, 65
+ pkt = NCP(0x41, "Open File", 'file')
+ pkt.Request((10, 264), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, 1, SearchAttributes ),
+ rec( 9, (1,255), FileName ),
+ ], info_str=(FileName, "Open File: %s", ", %s"))
+ pkt.Reply(44, [
+ rec( 8, 6, FileHandle ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 14, FileName14 ),
+ rec( 30, 1, AttributesDef ),
+ rec( 31, 1, FileExecuteType ),
+ rec( 32, 4, FileSize, BE ),
+ rec( 36, 2, CreationDate, BE ),
+ rec( 38, 2, LastAccessedDate, BE ),
+ rec( 40, 2, ModifiedDate, BE ),
+ rec( 42, 2, ModifiedTime, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8200, 0x9400,
+ 0x9600, 0x9804, 0x9c03, 0xa100, 0xfd00,
+ 0xff16])
+ # 2222/42, 66
+ pkt = NCP(0x42, "Close File", 'file')
+ pkt.Request(14, [
+ rec( 7, 1, Reserved ),
+ rec( 8, 6, FileHandle ),
+ ], info_str=(FileHandle, "Close File - 0x%s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0xff1a])
+ # 2222/43, 67
+ pkt = NCP(0x43, "Create File", 'file')
+ pkt.Request((10, 264), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, 1, AttributesDef ),
+ rec( 9, (1,255), FileName ),
+ ], info_str=(FileName, "Create File: %s", ", %s"))
+ pkt.Reply(44, [
+ rec( 8, 6, FileHandle ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 14, FileName14 ),
+ rec( 30, 1, AttributesDef ),
+ rec( 31, 1, FileExecuteType ),
+ rec( 32, 4, FileSize, BE ),
+ rec( 36, 2, CreationDate, BE ),
+ rec( 38, 2, LastAccessedDate, BE ),
+ rec( 40, 2, ModifiedDate, BE ),
+ rec( 42, 2, ModifiedTime, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9900, 0x9b03, 0x9c03, 0xfd00,
+ 0xff00])
+ # 2222/44, 68
+ pkt = NCP(0x44, "Erase File", 'file')
+ pkt.Request((10, 264), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, 1, SearchAttributes ),
+ rec( 9, (1,255), FileName ),
+ ], info_str=(FileName, "Erase File: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8a00, 0x8d00, 0x8e00, 0x8f00,
+ 0x9001, 0x9600, 0x9804, 0x9b03, 0x9c03,
+ 0xa100, 0xfd00, 0xff00])
+ # 2222/45, 69
+ pkt = NCP(0x45, "Rename File", 'file')
+ pkt.Request((12, 520), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, 1, SearchAttributes ),
+ rec( 9, (1,255), FileName ),
+ rec( -1, 1, TargetDirHandle ),
+ rec( -1, (1, 255), NewFileNameLen ),
+ ], info_str=(FileName, "Rename File: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8701, 0x8b00, 0x8d00, 0x8e00,
+ 0x8f00, 0x9001, 0x9101, 0x9201, 0x9600,
+ 0x9804, 0x9a00, 0x9b03, 0x9c03, 0xa100,
+ 0xfd00, 0xff16])
+ # 2222/46, 70
+ pkt = NCP(0x46, "Set File Attributes", 'file')
+ pkt.Request((11, 265), [
+ rec( 7, 1, AttributesDef ),
+ rec( 8, 1, DirHandle ),
+ rec( 9, 1, SearchAttributes ),
+ rec( 10, (1,255), FileName ),
+ ], info_str=(FileName, "Set File Attributes: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8c00, 0x8d00, 0x8e00, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa100, 0xfd00,
+ 0xff16])
+ # 2222/47, 71
+ pkt = NCP(0x47, "Get Current Size of File", 'file')
+ pkt.Request(14, [
+ rec(7, 1, Reserved ),
+ rec( 8, 6, FileHandle ),
+ ], info_str=(FileHandle, "Get Current Size of File - 0x%s", ", %s"))
+ pkt.Reply(12, [
+ rec( 8, 4, FileSize, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8800])
+ # 2222/48, 72
+ pkt = NCP(0x48, "Read From A File", 'file')
+ pkt.Request(20, [
+ rec( 7, 1, Reserved ),
+ rec( 8, 6, FileHandle ),
+ rec( 14, 4, FileOffset, BE ),
+ rec( 18, 2, MaxBytes, BE ),
+ ], info_str=(FileHandle, "Read From File - 0x%s", ", %s"))
+ pkt.Reply(10, [
+ rec( 8, 2, NumBytes, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8300, 0x8800, 0x9300, 0xff1b])
+ # 2222/49, 73
+ pkt = NCP(0x49, "Write to a File", 'file')
+ pkt.Request(20, [
+ rec( 7, 1, Reserved ),
+ rec( 8, 6, FileHandle ),
+ rec( 14, 4, FileOffset, BE ),
+ rec( 18, 2, MaxBytes, BE ),
+ ], info_str=(FileHandle, "Write to a File - 0x%s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x0104, 0x8300, 0x8800, 0x9400, 0x9500, 0xa201, 0xff1b])
+ # 2222/4A, 74
+ pkt = NCP(0x4A, "Copy from One File to Another", 'file')
+ pkt.Request(30, [
+ rec( 7, 1, Reserved ),
+ rec( 8, 6, FileHandle ),
+ rec( 14, 6, TargetFileHandle ),
+ rec( 20, 4, FileOffset, BE ),
+ rec( 24, 4, TargetFileOffset, BE ),
+ rec( 28, 2, BytesToCopy, BE ),
+ ])
+ pkt.Reply(12, [
+ rec( 8, 4, BytesActuallyTransferred, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x0104, 0x8300, 0x8800, 0x9300, 0x9400,
+ 0x9500, 0x9600, 0xa201, 0xff1b])
+ # 2222/4B, 75
+ pkt = NCP(0x4B, "Set File Time Date Stamp", 'file')
+ pkt.Request(18, [
+ rec( 7, 1, Reserved ),
+ rec( 8, 6, FileHandle ),
+ rec( 14, 2, FileTime, BE ),
+ rec( 16, 2, FileDate, BE ),
+ ], info_str=(FileHandle, "Set Time and Date Stamp for File - 0x%s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0x9400, 0x9600, 0xfb08])
+ # 2222/4C, 76
+ pkt = NCP(0x4C, "Open File", 'file')
+ pkt.Request((11, 265), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, 1, SearchAttributes ),
+ rec( 9, 1, AccessRightsMask ),
+ rec( 10, (1,255), FileName ),
+ ], info_str=(FileName, "Open File: %s", ", %s"))
+ pkt.Reply(44, [
+ rec( 8, 6, FileHandle ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 14, FileName14 ),
+ rec( 30, 1, AttributesDef ),
+ rec( 31, 1, FileExecuteType ),
+ rec( 32, 4, FileSize, BE ),
+ rec( 36, 2, CreationDate, BE ),
+ rec( 38, 2, LastAccessedDate, BE ),
+ rec( 40, 2, ModifiedDate, BE ),
+ rec( 42, 2, ModifiedTime, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8200, 0x9400,
+ 0x9600, 0x9804, 0x9c03, 0xa100, 0xfd00,
+ 0xff16])
+ # 2222/4D, 77
+ pkt = NCP(0x4D, "Create File", 'file')
+ pkt.Request((10, 264), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, 1, AttributesDef ),
+ rec( 9, (1,255), FileName ),
+ ], info_str=(FileName, "Create File: %s", ", %s"))
+ pkt.Reply(44, [
+ rec( 8, 6, FileHandle ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 14, FileName14 ),
+ rec( 30, 1, AttributesDef ),
+ rec( 31, 1, FileExecuteType ),
+ rec( 32, 4, FileSize, BE ),
+ rec( 36, 2, CreationDate, BE ),
+ rec( 38, 2, LastAccessedDate, BE ),
+ rec( 40, 2, ModifiedDate, BE ),
+ rec( 42, 2, ModifiedTime, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9900, 0x9b03, 0x9c03, 0xfd00,
+ 0xff00])
+ # 2222/4F, 79
+ pkt = NCP(0x4F, "Set File Extended Attributes", 'file')
+ pkt.Request((11, 265), [
+ rec( 7, 1, AttributesDef ),
+ rec( 8, 1, DirHandle ),
+ rec( 9, 1, AccessRightsMask ),
+ rec( 10, (1,255), FileName ),
+ ], info_str=(FileName, "Set File Extended Attributes: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8c00, 0x8d00, 0x8e00, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa100, 0xfd00,
+ 0xff16])
+ # 2222/54, 84
+ pkt = NCP(0x54, "Open/Create File", 'file')
+ pkt.Request((12, 266), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, 1, AttributesDef ),
+ rec( 9, 1, AccessRightsMask ),
+ rec( 10, 1, ActionFlag ),
+ rec( 11, (1,255), FileName ),
+ ], info_str=(FileName, "Open/Create File: %s", ", %s"))
+ pkt.Reply(44, [
+ rec( 8, 6, FileHandle ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 14, FileName14 ),
+ rec( 30, 1, AttributesDef ),
+ rec( 31, 1, FileExecuteType ),
+ rec( 32, 4, FileSize, BE ),
+ rec( 36, 2, CreationDate, BE ),
+ rec( 38, 2, LastAccessedDate, BE ),
+ rec( 40, 2, ModifiedDate, BE ),
+ rec( 42, 2, ModifiedTime, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xfd00, 0xff16])
+ # 2222/55, 85
+ pkt = NCP(0x55, "Get Sparse File Data Block Bit Map", 'file')
+ pkt.Request(17, [
+ rec( 7, 6, FileHandle ),
+ rec( 13, 4, FileOffset ),
+ ], info_str=(FileHandle, "Get Sparse File Data Block Bitmap for File - 0x%s", ", %s"))
+ pkt.Reply(528, [
+ rec( 8, 4, AllocationBlockSize ),
+ rec( 12, 4, Reserved4 ),
+ rec( 16, 512, BitMap ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8800])
+ # 2222/5601, 86/01
+ pkt = NCP(0x5601, "Close Extended Attribute Handle", 'file', has_length=0 )
+ pkt.Request(14, [
+ rec( 8, 2, Reserved2 ),
+ rec( 10, 4, EAHandle ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xcf00, 0xd301])
+ # 2222/5602, 86/02
+ pkt = NCP(0x5602, "Write Extended Attribute", 'file', has_length=0 )
+ pkt.Request((35,97), [
+ rec( 8, 2, EAFlags ),
+ rec( 10, 4, EAHandleOrNetWareHandleOrVolume ),
+ rec( 14, 4, ReservedOrDirectoryNumber ),
+ rec( 18, 4, TtlWriteDataSize ),
+ rec( 22, 4, FileOffset ),
+ rec( 26, 4, EAAccessFlag ),
+ rec( 30, 2, EAValueLength, var='x' ),
+ rec( 32, (2,64), EAKey ),
+ rec( -1, 1, EAValueRep, repeat='x' ),
+ ], info_str=(EAKey, "Write Extended Attribute: %s", ", %s"))
+ pkt.Reply(20, [
+ rec( 8, 4, EAErrorCodes ),
+ rec( 12, 4, EABytesWritten ),
+ rec( 16, 4, NewEAHandle ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xc800, 0xc900, 0xcb00, 0xce00, 0xcf00, 0xd101,
+ 0xd203, 0xd301, 0xd402])
+ # 2222/5603, 86/03
+ pkt = NCP(0x5603, "Read Extended Attribute", 'file', has_length=0 )
+ pkt.Request((28,538), [
+ rec( 8, 2, EAFlags ),
+ rec( 10, 4, EAHandleOrNetWareHandleOrVolume ),
+ rec( 14, 4, ReservedOrDirectoryNumber ),
+ rec( 18, 4, FileOffset ),
+ rec( 22, 4, InspectSize ),
+ rec( 26, (2,512), EAKey ),
+ ], info_str=(EAKey, "Read Extended Attribute: %s", ", %s"))
+ pkt.Reply((26,536), [
+ rec( 8, 4, EAErrorCodes ),
+ rec( 12, 4, TtlValuesLength ),
+ rec( 16, 4, NewEAHandle ),
+ rec( 20, 4, EAAccessFlag ),
+ rec( 24, (2,512), EAValue ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xc900, 0xce00, 0xcf00, 0xd101,
+ 0xd301])
+ # 2222/5604, 86/04
+ pkt = NCP(0x5604, "Enumerate Extended Attribute", 'file', has_length=0 )
+ pkt.Request((26,536), [
+ rec( 8, 2, EAFlags ),
+ rec( 10, 4, EAHandleOrNetWareHandleOrVolume ),
+ rec( 14, 4, ReservedOrDirectoryNumber ),
+ rec( 18, 4, InspectSize ),
+ rec( 22, 2, SequenceNumber ),
+ rec( 24, (2,512), EAKey ),
+ ], info_str=(EAKey, "Enumerate Extended Attribute: %s", ", %s"))
+ pkt.Reply(28, [
+ rec( 8, 4, EAErrorCodes ),
+ rec( 12, 4, TtlEAs ),
+ rec( 16, 4, TtlEAsDataSize ),
+ rec( 20, 4, TtlEAsKeySize ),
+ rec( 24, 4, NewEAHandle ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8800, 0xc900, 0xce00, 0xcf00, 0xd101,
+ 0xd301])
+ # 2222/5605, 86/05
+ pkt = NCP(0x5605, "Duplicate Extended Attributes", 'file', has_length=0 )
+ pkt.Request(28, [
+ rec( 8, 2, EAFlags ),
+ rec( 10, 2, DstEAFlags ),
+ rec( 12, 4, EAHandleOrNetWareHandleOrVolume ),
+ rec( 16, 4, ReservedOrDirectoryNumber ),
+ rec( 20, 4, EAHandleOrNetWareHandleOrVolume ),
+ rec( 24, 4, ReservedOrDirectoryNumber ),
+ ])
+ pkt.Reply(20, [
+ rec( 8, 4, EADuplicateCount ),
+ rec( 12, 4, EADataSizeDuplicated ),
+ rec( 16, 4, EAKeySizeDuplicated ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xd101])
+ # 2222/5701, 87/01
+ pkt = NCP(0x5701, "Open/Create File or Subdirectory", 'file', has_length=0)
+ pkt.Request((30, 284), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, OpenCreateMode ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 2, ReturnInfoMask ),
+ rec( 14, 2, ExtendedInfo ),
+ rec( 16, 4, AttributesDef32 ),
+ rec( 20, 2, DesiredAccessRights ),
+ rec( 22, 1, VolumeNumber ),
+ rec( 23, 4, DirectoryBase ),
+ rec( 27, 1, HandleFlag ),
+ rec( 28, 1, PathCount, var="x" ),
+ rec( 29, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Open or Create: %s", "/%s"))
+ pkt.Reply( NO_LENGTH_CHECK, [
+ rec( 8, 4, FileHandle ),
+ rec( 12, 1, OpenCreateAction ),
+ rec( 13, 1, Reserved ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( PadDSSpaceAllocate, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 0)" ),
+ srec( AttributesStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( PadAttributes, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 0)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 1)" ),
+ srec( PadDataStreamSize, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 0)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( PadTotalStreamSize, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 0)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 1)" ),
+ srec( PadCreationInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 0)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( PadModifyInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 0)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( PadArchiveInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 0)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( PadRightsInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 0)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( PadDirEntry, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 0)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( PadEAInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 0)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( PadNSInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 0)" ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_size == 1)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_create == 1)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( ReferenceIDStruct, req_cond="ncp.ret_info_mask_id == 1" ),
+ srec( NSAttributeStruct, req_cond="ncp.ret_info_mask_ns_attr == 1" ),
+ srec( DStreamActual, req_cond="ncp.ret_info_mask_actual == 1" ),
+ srec( DStreamLogical, req_cond="ncp.ret_info_mask_logical == 1" ),
+ srec( LastUpdatedInSecondsStruct, req_cond="ncp.ext_info_update == 1" ),
+ srec( DOSNameStruct, req_cond="ncp.ext_info_dos_name == 1" ),
+ srec( FlushTimeStruct, req_cond="ncp.ext_info_flush == 1" ),
+ srec( ParentBaseIDStruct, req_cond="ncp.ext_info_parental == 1" ),
+ srec( MacFinderInfoStruct, req_cond="ncp.ext_info_mac_finder == 1" ),
+ srec( SiblingCountStruct, req_cond="ncp.ext_info_sibling == 1" ),
+ srec( EffectiveRightsStruct, req_cond="ncp.ext_info_effective == 1" ),
+ srec( MacTimeStruct, req_cond="ncp.ext_info_mac_date == 1" ),
+ srec( LastAccessedTimeStruct, req_cond="ncp.ext_info_access == 1" ),
+ srec( FileNameStruct, req_cond="ncp.ret_info_mask_fname == 1" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x8001, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8900, 0x8d00, 0x8f00, 0x9001, 0x9400, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa500, 0xa802, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5702, 87/02
+ pkt = NCP(0x5702, "Initialize Search", 'file', has_length=0)
+ pkt.Request( (18,272), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, DirectoryBase ),
+ rec( 15, 1, HandleFlag ),
+ rec( 16, 1, PathCount, var="x" ),
+ rec( 17, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Set Search Pointer to: %s", "/%s"))
+ pkt.Reply(17, [
+ rec( 8, 1, VolumeNumber ),
+ rec( 9, 4, DirectoryNumber ),
+ rec( 13, 4, DirectoryEntryNumber ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5703, 87/03
+ pkt = NCP(0x5703, "Search for File or Subdirectory", 'file', has_length=0)
+ pkt.Request((26, 280), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, DataStream ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 2, ReturnInfoMask ),
+ rec( 14, 2, ExtendedInfo ),
+ rec( 16, 9, SearchSequence ),
+ rec( 25, (1,255), SearchPattern ),
+ ], info_str=(SearchPattern, "Search for: %s", "/%s"))
+ pkt.Reply( NO_LENGTH_CHECK, [
+ rec( 8, 9, SearchSequence ),
+ rec( 17, 1, Reserved ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( PadDSSpaceAllocate, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 0)" ),
+ srec( AttributesStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( PadAttributes, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 0)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 1)" ),
+ srec( PadDataStreamSize, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 0)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( PadTotalStreamSize, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 0)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 1)" ),
+ srec( PadCreationInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 0)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( PadModifyInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 0)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( PadArchiveInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 0)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( PadRightsInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 0)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( PadDirEntry, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 0)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( PadEAInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 0)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( PadNSInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 0)" ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_size == 1)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_create == 1)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( ReferenceIDStruct, req_cond="ncp.ret_info_mask_id == 1" ),
+ srec( NSAttributeStruct, req_cond="ncp.ret_info_mask_ns_attr == 1" ),
+ srec( DStreamActual, req_cond="ncp.ret_info_mask_actual == 1" ),
+ srec( DStreamLogical, req_cond="ncp.ret_info_mask_logical == 1" ),
+ srec( LastUpdatedInSecondsStruct, req_cond="ncp.ext_info_update == 1" ),
+ srec( DOSNameStruct, req_cond="ncp.ext_info_dos_name == 1" ),
+ srec( FlushTimeStruct, req_cond="ncp.ext_info_flush == 1" ),
+ srec( ParentBaseIDStruct, req_cond="ncp.ext_info_parental == 1" ),
+ srec( MacFinderInfoStruct, req_cond="ncp.ext_info_mac_finder == 1" ),
+ srec( SiblingCountStruct, req_cond="ncp.ext_info_sibling == 1" ),
+ srec( EffectiveRightsStruct, req_cond="ncp.ext_info_effective == 1" ),
+ srec( MacTimeStruct, req_cond="ncp.ext_info_mac_date == 1" ),
+ srec( LastAccessedTimeStruct, req_cond="ncp.ext_info_access == 1" ),
+ srec( FileNameStruct, req_cond="ncp.ret_info_mask_fname == 1" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5704, 87/04
+ pkt = NCP(0x5704, "Rename Or Move a File or Subdirectory", 'file', has_length=0)
+ pkt.Request((28, 536), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, RenameFlag ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 1, VolumeNumber ),
+ rec( 13, 4, DirectoryBase ),
+ rec( 17, 1, HandleFlag ),
+ rec( 18, 1, PathCount, var="x" ),
+ rec( 19, 1, VolumeNumber ),
+ rec( 20, 4, DirectoryBase ),
+ rec( 24, 1, HandleFlag ),
+ rec( 25, 1, PathCount, var="y" ),
+ rec( 26, (1, 255), Path, repeat="x" ),
+ rec( -1, (1,255), Path, repeat="y" ),
+ ], info_str=(Path, "Rename or Move: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8e00, 0x8f00, 0x9001, 0x9200, 0x9600,
+ 0x9804, 0x9a00, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5705, 87/05
+ pkt = NCP(0x5705, "Scan File or Subdirectory for Trustees", 'file', has_length=0)
+ pkt.Request((24, 278), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 4, SequenceNumber ),
+ rec( 16, 1, VolumeNumber ),
+ rec( 17, 4, DirectoryBase ),
+ rec( 21, 1, HandleFlag ),
+ rec( 22, 1, PathCount, var="x" ),
+ rec( 23, (1, 255), Path, repeat="x" ),
+ ], info_str=(Path, "Scan Trustees for: %s", "/%s"))
+ pkt.Reply(20, [
+ rec( 8, 4, SequenceNumber ),
+ rec( 12, 2, ObjectIDCount, var="x" ),
+ rec( 14, 6, TrusteeStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5706, 87/06
+ pkt = NCP(0x5706, "Obtain File or SubDirectory Information", 'file', has_length=0)
+ pkt.Request((24,278), [
+ rec( 10, 1, SrcNameSpace ),
+ rec( 11, 1, DestNameSpace ),
+ rec( 12, 2, SearchAttributesLow ),
+ rec( 14, 2, ReturnInfoMask, LE ),
+ rec( 16, 2, ExtendedInfo ),
+ rec( 18, 1, VolumeNumber ),
+ rec( 19, 4, DirectoryBase ),
+ rec( 23, 1, HandleFlag ),
+ rec( 24, 1, PathCount, var="x" ),
+ rec( 25, (1,255), Path, repeat="x",),
+ ], info_str=(Path, "Obtain Info for: %s", "/%s"))
+ pkt.Reply(NO_LENGTH_CHECK, [
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( PadDSSpaceAllocate, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 0)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( PadAttributes, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 0)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 1)" ),
+ srec( PadDataStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 0)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( PadTotalStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 0)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 1)" ),
+ srec( PadCreationInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 0)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( PadModifyInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 0)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( PadArchiveInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 0)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( PadRightsInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 0)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( PadDirEntry, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 0)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( PadEAInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 0)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( PadNSInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 0)" ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_size == 1)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_create == 1)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( ReferenceIDStruct, req_cond="ncp.ret_info_mask_id == 1" ),
+ srec( NSAttributeStruct, req_cond="ncp.ret_info_mask_ns_attr == 1" ),
+ srec( DStreamActual, req_cond="ncp.ret_info_mask_actual == 1" ),
+ srec( DStreamLogical, req_cond="ncp.ret_info_mask_logical == 1" ),
+ srec( LastUpdatedInSecondsStruct, req_cond="ncp.ext_info_update == 1" ),
+ srec( DOSNameStruct, req_cond="ncp.ext_info_dos_name == 1" ),
+ srec( FlushTimeStruct, req_cond="ncp.ext_info_flush == 1" ),
+ srec( ParentBaseIDStruct, req_cond="ncp.ext_info_parental == 1" ),
+ srec( MacFinderInfoStruct, req_cond="ncp.ext_info_mac_finder == 1" ),
+ srec( SiblingCountStruct, req_cond="ncp.ext_info_sibling == 1" ),
+ srec( EffectiveRightsStruct, req_cond="ncp.ext_info_effective == 1" ),
+ srec( MacTimeStruct, req_cond="ncp.ext_info_mac_date == 1" ),
+ srec( LastAccessedTimeStruct, req_cond="ncp.ext_info_access == 1" ),
+ srec( FileNameStruct, req_cond="ncp.ret_info_mask_fname == 1" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8700, 0x8900, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa802, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5707, 87/07
+ pkt = NCP(0x5707, "Modify File or Subdirectory DOS Information", 'file', has_length=0)
+ pkt.Request((62,316), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 2, ModifyDOSInfoMask ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 2, AttributesDef16 ),
+ rec( 18, 1, FileMode ),
+ rec( 19, 1, FileExtendedAttributes ),
+ rec( 20, 2, CreationDate ),
+ rec( 22, 2, CreationTime ),
+ rec( 24, 4, CreatorID, BE ),
+ rec( 28, 2, ModifiedDate ),
+ rec( 30, 2, ModifiedTime ),
+ rec( 32, 4, ModifierID, BE ),
+ rec( 36, 2, ArchivedDate ),
+ rec( 38, 2, ArchivedTime ),
+ rec( 40, 4, ArchiverID, BE ),
+ rec( 44, 2, LastAccessedDate ),
+ rec( 46, 2, InheritedRightsMask ),
+ rec( 48, 2, InheritanceRevokeMask ),
+ rec( 50, 4, MaxSpace ),
+ rec( 54, 1, VolumeNumber ),
+ rec( 55, 4, DirectoryBase ),
+ rec( 59, 1, HandleFlag ),
+ rec( 60, 1, PathCount, var="x" ),
+ rec( 61, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Modify DOS Information for: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8c01, 0x8d00, 0x8e00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5708, 87/08
+ pkt = NCP(0x5708, "Delete a File or Subdirectory", 'file', has_length=0)
+ pkt.Request((20,274), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 1, VolumeNumber ),
+ rec( 13, 4, DirectoryBase ),
+ rec( 17, 1, HandleFlag ),
+ rec( 18, 1, PathCount, var="x" ),
+ rec( 19, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Delete a File or Subdirectory: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8900, 0x8a00, 0x8d00, 0x8e00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5709, 87/09
+ pkt = NCP(0x5709, "Set Short Directory Handle", 'file', has_length=0)
+ pkt.Request((20,274), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, DataStream ),
+ rec( 10, 1, DestDirHandle ),
+ rec( 11, 1, Reserved ),
+ rec( 12, 1, VolumeNumber ),
+ rec( 13, 4, DirectoryBase ),
+ rec( 17, 1, HandleFlag ),
+ rec( 18, 1, PathCount, var="x" ),
+ rec( 19, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Set Short Directory Handle to: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/570A, 87/10
+ pkt = NCP(0x570A, "Add Trustee Set to File or Subdirectory", 'file', has_length=0)
+ pkt.Request((31,285), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 2, AccessRightsMaskWord ),
+ rec( 14, 2, ObjectIDCount, var="y" ),
+ rec( 16, 1, VolumeNumber ),
+ rec( 17, 4, DirectoryBase ),
+ rec( 21, 1, HandleFlag ),
+ rec( 22, 1, PathCount, var="x" ),
+ rec( 23, (1,255), Path, repeat="x" ),
+ rec( -1, 7, TrusteeStruct, repeat="y" ),
+ ], info_str=(Path, "Add Trustee Set to: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfc01, 0xfd00, 0xff16])
+ # 2222/570B, 87/11
+ pkt = NCP(0x570B, "Delete Trustee Set from File or SubDirectory", 'file', has_length=0)
+ pkt.Request((27,281), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, ObjectIDCount, var="y" ),
+ rec( 12, 1, VolumeNumber ),
+ rec( 13, 4, DirectoryBase ),
+ rec( 17, 1, HandleFlag ),
+ rec( 18, 1, PathCount, var="x" ),
+ rec( 19, (1,255), Path, repeat="x" ),
+ rec( -1, 7, TrusteeStruct, repeat="y" ),
+ ], info_str=(Path, "Delete Trustee Set from: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/570C, 87/12
+ pkt = NCP(0x570C, "Allocate Short Directory Handle", 'file', has_length=0)
+ pkt.Request((20,274), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, AllocateMode ),
+ rec( 12, 1, VolumeNumber ),
+ rec( 13, 4, DirectoryBase ),
+ rec( 17, 1, HandleFlag ),
+ rec( 18, 1, PathCount, var="x" ),
+ rec( 19, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Allocate Short Directory Handle to: %s", "/%s"))
+ pkt.Reply(14, [
+ rec( 8, 1, DirHandle ),
+ rec( 9, 1, VolumeNumber ),
+ rec( 10, 4, Reserved4 ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5710, 87/16
+ pkt = NCP(0x5710, "Scan Salvageable Files", 'file', has_length=0)
+ pkt.Request((26,280), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, DataStream ),
+ rec( 10, 2, ReturnInfoMask ),
+ rec( 12, 2, ExtendedInfo ),
+ rec( 14, 4, SequenceNumber ),
+ rec( 18, 1, VolumeNumber ),
+ rec( 19, 4, DirectoryBase ),
+ rec( 23, 1, HandleFlag ),
+ rec( 24, 1, PathCount, var="x" ),
+ rec( 25, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Scan for Deleted Files in: %s", "/%s"))
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec( 8, 4, SequenceNumber ),
+ rec( 12, 2, DeletedTime ),
+ rec( 14, 2, DeletedDate ),
+ rec( 16, 4, DeletedID, BE ),
+ rec( 20, 4, VolumeID ),
+ rec( 24, 4, DirectoryBase ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( PadDSSpaceAllocate, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 0)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( PadAttributes, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 0)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 1)" ),
+ srec( PadDataStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 0)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( PadTotalStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 0)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 1)" ),
+ srec( PadCreationInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 0)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( PadModifyInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 0)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( PadArchiveInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 0)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( PadRightsInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 0)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( PadDirEntry, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 0)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( PadEAInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 0)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( PadNSInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 0)" ),
+ srec( FileNameStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_fname == 1)" ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_size == 1)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_create == 1)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( FileNameStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_fname == 1)" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5711, 87/17
+ pkt = NCP(0x5711, "Recover Salvageable File", 'file', has_length=0)
+ pkt.Request((23,277), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 4, SequenceNumber ),
+ rec( 14, 4, VolumeID ),
+ rec( 18, 4, DirectoryBase ),
+ rec( 22, (1,255), FileName ),
+ ], info_str=(FileName, "Recover Deleted File: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5712, 87/18
+ pkt = NCP(0x5712, "Purge Salvageable Files", 'file', has_length=0)
+ pkt.Request(22, [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 4, SequenceNumber ),
+ rec( 14, 4, VolumeID ),
+ rec( 18, 4, DirectoryBase ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5713, 87/19
+ pkt = NCP(0x5713, "Get Name Space Information", 'file', has_length=0)
+ pkt.Request(18, [
+ rec( 8, 1, SrcNameSpace ),
+ rec( 9, 1, DestNameSpace ),
+ rec( 10, 1, Reserved ),
+ rec( 11, 1, VolumeNumber ),
+ rec( 12, 4, DirectoryBase ),
+ rec( 16, 2, NamesSpaceInfoMask ),
+ ])
+ pkt.Reply(NO_LENGTH_CHECK, [
+ srec( FileNameStruct, req_cond="ncp.ns_info_mask_modify == TRUE" ),
+ srec( FileAttributesStruct, req_cond="ncp.ns_info_mask_fatt == TRUE" ),
+ srec( CreationDateStruct, req_cond="ncp.ns_info_mask_cdate == TRUE" ),
+ srec( CreationTimeStruct, req_cond="ncp.ns_info_mask_ctime == TRUE" ),
+ srec( OwnerIDStruct, req_cond="ncp.ns_info_mask_owner == TRUE" ),
+ srec( ArchiveDateStruct, req_cond="ncp.ns_info_mask_adate == TRUE" ),
+ srec( ArchiveTimeStruct, req_cond="ncp.ns_info_mask_atime == TRUE" ),
+ srec( ArchiveIdStruct, req_cond="ncp.ns_info_mask_aid == TRUE" ),
+ srec( UpdateDateStruct, req_cond="ncp.ns_info_mask_udate == TRUE" ),
+ srec( UpdateTimeStruct, req_cond="ncp.ns_info_mask_utime == TRUE" ),
+ srec( UpdateIDStruct, req_cond="ncp.ns_info_mask_uid == TRUE" ),
+ srec( LastAccessStruct, req_cond="ncp.ns_info_mask_acc_date == TRUE" ),
+ srec( RightsInfoStruct, req_cond="ncp.ns_info_mask_max_acc_mask == TRUE" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5714, 87/20
+ pkt = NCP(0x5714, "Search for File or Subdirectory Set", 'file', has_length=0)
+ pkt.Request((28, 282), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, DataStream ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 2, ReturnInfoMask ),
+ rec( 14, 2, ExtendedInfo ),
+ rec( 16, 2, ReturnInfoCount ),
+ rec( 18, 9, SearchSequence ),
+ rec( 27, (1,255), SearchPattern ),
+ ])
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec( 8, 9, SearchSequence ),
+ rec( 17, 1, MoreFlag ),
+ rec( 18, 2, InfoCount ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( PadDSSpaceAllocate, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 0)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( PadAttributes, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 0)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 1)" ),
+ srec( PadDataStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 0)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( PadTotalStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 0)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 1)" ),
+ srec( PadCreationInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 0)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( PadModifyInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 0)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( PadArchiveInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 0)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( PadRightsInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 0)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( PadDirEntry, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 0)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( PadEAInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 0)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( PadNSInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 0)" ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_size == 1)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_create == 1)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( ReferenceIDStruct, req_cond="ncp.ret_info_mask_id == 1" ),
+ srec( NSAttributeStruct, req_cond="ncp.ret_info_mask_ns_attr == 1" ),
+ srec( DStreamActual, req_cond="ncp.ret_info_mask_actual == 1" ),
+ srec( DStreamLogical, req_cond="ncp.ret_info_mask_logical == 1" ),
+ srec( LastUpdatedInSecondsStruct, req_cond="ncp.ext_info_update == 1" ),
+ srec( DOSNameStruct, req_cond="ncp.ext_info_dos_name == 1" ),
+ srec( FlushTimeStruct, req_cond="ncp.ext_info_flush == 1" ),
+ srec( ParentBaseIDStruct, req_cond="ncp.ext_info_parental == 1" ),
+ srec( MacFinderInfoStruct, req_cond="ncp.ext_info_mac_finder == 1" ),
+ srec( SiblingCountStruct, req_cond="ncp.ext_info_sibling == 1" ),
+ srec( EffectiveRightsStruct, req_cond="ncp.ext_info_effective == 1" ),
+ srec( MacTimeStruct, req_cond="ncp.ext_info_mac_date == 1" ),
+ srec( LastAccessedTimeStruct, req_cond="ncp.ext_info_access == 1" ),
+ srec( FileNameStruct, req_cond="ncp.ret_info_mask_fname == 1" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5715, 87/21
+ pkt = NCP(0x5715, "Get Path String from Short Directory Handle", 'file', has_length=0)
+ pkt.Request(10, [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, DirHandle ),
+ ])
+ pkt.Reply((9,263), [
+ rec( 8, (1,255), Path ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xfd00, 0xff16])
+ # 2222/5716, 87/22
+ pkt = NCP(0x5716, "Generate Directory Base and Volume Number", 'file', has_length=0)
+ pkt.Request((20,274), [
+ rec( 8, 1, SrcNameSpace ),
+ rec( 9, 1, DestNameSpace ),
+ rec( 10, 2, dstNSIndicator ),
+ rec( 12, 1, VolumeNumber ),
+ rec( 13, 4, DirectoryBase ),
+ rec( 17, 1, HandleFlag ),
+ rec( 18, 1, PathCount, var="x" ),
+ rec( 19, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Get Volume and Directory Base from: %s", "/%s"))
+ pkt.Reply(17, [
+ rec( 8, 4, DirectoryBase ),
+ rec( 12, 4, DOSDirectoryBase ),
+ rec( 16, 1, VolumeNumber ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5717, 87/23
+ pkt = NCP(0x5717, "Query Name Space Information Format", 'file', has_length=0)
+ pkt.Request(10, [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, VolumeNumber ),
+ ])
+ pkt.Reply(58, [
+ rec( 8, 4, FixedBitMask ),
+ rec( 12, 4, VariableBitMask ),
+ rec( 16, 4, HugeBitMask ),
+ rec( 20, 2, FixedBitsDefined ),
+ rec( 22, 2, VariableBitsDefined ),
+ rec( 24, 2, HugeBitsDefined ),
+ rec( 26, 32, FieldsLenTable ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5718, 87/24
+ pkt = NCP(0x5718, "Get Name Spaces Loaded List from Volume Number", 'file', has_length=0)
+ pkt.Request(10, [
+ rec( 8, 1, Reserved ),
+ rec( 9, 1, VolumeNumber ),
+ ])
+ pkt.Reply(11, [
+ rec( 8, 2, NumberOfNSLoaded, var="x" ),
+ rec( 10, 1, NameSpace, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5719, 87/25
+ pkt = NCP(0x5719, "Set Name Space Information", 'file', has_length=0)
+ pkt.Request(531, [
+ rec( 8, 1, SrcNameSpace ),
+ rec( 9, 1, DestNameSpace ),
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 4, DirectoryBase ),
+ rec( 15, 2, NamesSpaceInfoMask ),
+ rec( 17, 2, Reserved2 ),
+ rec( 19, 512, NSSpecificInfo ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8b00, 0x8d00, 0x8f00, 0x9001,
+ 0x9600, 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00,
+ 0xff16])
+ # 2222/571A, 87/26
+ pkt = NCP(0x571A, "Get Huge Name Space Information", 'file', has_length=0)
+ pkt.Request(34, [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, VolumeNumber ),
+ rec( 10, 4, DirectoryBase ),
+ rec( 14, 4, HugeBitMask ),
+ rec( 18, 16, HugeStateInfo ),
+ ])
+ pkt.Reply((25,279), [
+ rec( 8, 16, NextHugeStateInfo ),
+ rec( 24, (1,255), HugeData ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8b00, 0x8d00, 0x8f00, 0x9001,
+ 0x9600, 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00,
+ 0xff16])
+ # 2222/571B, 87/27
+ pkt = NCP(0x571B, "Set Huge Name Space Information", 'file', has_length=0)
+ pkt.Request((35,289), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, VolumeNumber ),
+ rec( 10, 4, DirectoryBase ),
+ rec( 14, 4, HugeBitMask ),
+ rec( 18, 16, HugeStateInfo ),
+ rec( 34, (1,255), HugeData ),
+ ])
+ pkt.Reply(28, [
+ rec( 8, 16, NextHugeStateInfo ),
+ rec( 24, 4, HugeDataUsed ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8b00, 0x8d00, 0x8f00, 0x9001,
+ 0x9600, 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00,
+ 0xff16])
+ # 2222/571C, 87/28
+ pkt = NCP(0x571C, "Get Full Path String", 'file', has_length=0)
+ pkt.Request((28,282), [
+ rec( 8, 1, SrcNameSpace ),
+ rec( 9, 1, DestNameSpace ),
+ rec( 10, 2, PathCookieFlags ),
+ rec( 12, 4, Cookie1 ),
+ rec( 16, 4, Cookie2 ),
+ rec( 20, 1, VolumeNumber ),
+ rec( 21, 4, DirectoryBase ),
+ rec( 25, 1, HandleFlag ),
+ rec( 26, 1, PathCount, var="x" ),
+ rec( 27, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Get Full Path from: %s", "/%s"))
+ pkt.Reply((23,277), [
+ rec( 8, 2, PathCookieFlags ),
+ rec( 10, 4, Cookie1 ),
+ rec( 14, 4, Cookie2 ),
+ rec( 18, 2, PathComponentSize ),
+ rec( 20, 2, PathComponentCount, var='x' ),
+ rec( 22, (1,255), Path, repeat='x' ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8b00, 0x8d00, 0x8f00, 0x9001,
+ 0x9600, 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00,
+ 0xff16])
+ # 2222/571D, 87/29
+ pkt = NCP(0x571D, "Get Effective Directory Rights", 'file', has_length=0)
+ pkt.Request((24, 278), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, DestNameSpace ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 2, ReturnInfoMask ),
+ rec( 14, 2, ExtendedInfo ),
+ rec( 16, 1, VolumeNumber ),
+ rec( 17, 4, DirectoryBase ),
+ rec( 21, 1, HandleFlag ),
+ rec( 22, 1, PathCount, var="x" ),
+ rec( 23, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Get Effective Rights for: %s", "/%s"))
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec( 8, 2, EffectiveRights ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( PadDSSpaceAllocate, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 0)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( PadAttributes, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 0)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 1)" ),
+ srec( PadDataStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 0)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( PadTotalStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 0)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 1)" ),
+ srec( PadCreationInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 0)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( PadModifyInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 0)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( PadArchiveInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 0)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( PadRightsInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 0)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( PadDirEntry, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 0)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( PadEAInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 0)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( PadNSInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 0)" ),
+ srec( FileNameStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_fname == 1)" ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_size == 1)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_create == 1)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( FileNameStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_fname == 1)" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/571E, 87/30
+ pkt = NCP(0x571E, "Open/Create File or Subdirectory", 'file', has_length=0)
+ pkt.Request((34, 288), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, DataStream ),
+ rec( 10, 1, OpenCreateMode ),
+ rec( 11, 1, Reserved ),
+ rec( 12, 2, SearchAttributesLow ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 2, ReturnInfoMask ),
+ rec( 18, 2, ExtendedInfo ),
+ rec( 20, 4, AttributesDef32 ),
+ rec( 24, 2, DesiredAccessRights ),
+ rec( 26, 1, VolumeNumber ),
+ rec( 27, 4, DirectoryBase ),
+ rec( 31, 1, HandleFlag ),
+ rec( 32, 1, PathCount, var="x" ),
+ rec( 33, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Open or Create File: %s", "/%s"))
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec( 8, 4, FileHandle, BE ),
+ rec( 12, 1, OpenCreateAction ),
+ rec( 13, 1, Reserved ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( PadDSSpaceAllocate, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 0)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( PadAttributes, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 0)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 1)" ),
+ srec( PadDataStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 0)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( PadTotalStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 0)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 1)" ),
+ srec( PadCreationInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 0)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( PadModifyInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 0)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( PadArchiveInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 0)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( PadRightsInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 0)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( PadDirEntry, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 0)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( PadEAInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 0)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( PadNSInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 0)" ),
+ srec( FileNameStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_fname == 1)" ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_size == 1)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_create == 1)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( FileNameStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_fname == 1)" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/571F, 87/31
+ pkt = NCP(0x571F, "Get File Information", 'file', has_length=0)
+ pkt.Request(15, [
+ rec( 8, 6, FileHandle ),
+ rec( 14, 1, HandleInfoLevel ),
+ #rec( 15, 1, NameSpace ),
+ ], info_str=(FileHandle, "Get File Information - 0x%s", ", %s"))
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec( 8, 4, VolumeNumberLong ),
+ rec( 12, 4, DirectoryBase ),
+ srec(HandleInfoLevel0, req_cond="ncp.handle_info_level==0x00" ),
+ srec(HandleInfoLevel1, req_cond="ncp.handle_info_level==0x01" ),
+ srec(HandleInfoLevel2, req_cond="ncp.handle_info_level==0x02" ),
+ srec(HandleInfoLevel3, req_cond="ncp.handle_info_level==0x03" ),
+ srec(HandleInfoLevel4, req_cond="ncp.handle_info_level==0x04" ),
+ srec(HandleInfoLevel5, req_cond="ncp.handle_info_level==0x05" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5720, 87/32
+ pkt = NCP(0x5720, "Open/Create File or Subdirectory with Callback", 'file', has_length=0)
+ pkt.Request((30, 284), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, OpenCreateMode ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 2, ReturnInfoMask ),
+ rec( 14, 2, ExtendedInfo ),
+ rec( 16, 4, AttributesDef32 ),
+ rec( 20, 2, DesiredAccessRights ),
+ rec( 22, 1, VolumeNumber ),
+ rec( 23, 4, DirectoryBase ),
+ rec( 27, 1, HandleFlag ),
+ rec( 28, 1, PathCount, var="x" ),
+ rec( 29, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Open or Create with Op-Lock: %s", "/%s"))
+ pkt.Reply( NO_LENGTH_CHECK, [
+ rec( 8, 4, FileHandle, BE ),
+ rec( 12, 1, OpenCreateAction ),
+ rec( 13, 1, OCRetFlags ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( PadDSSpaceAllocate, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 0)" ),
+ srec( AttributesStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( PadAttributes, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 0)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 1)" ),
+ srec( PadDataStreamSize, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 0)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( PadTotalStreamSize, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 0)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 1)" ),
+ srec( PadCreationInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 0)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( PadModifyInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 0)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( PadArchiveInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 0)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( PadRightsInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 0)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( PadDirEntry, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 0)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( PadEAInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 0)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( PadNSInfo, req_cond="(ncp.ret_info_mask != 0x0000) && (ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 0)" ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_size == 1)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_create == 1)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( ReferenceIDStruct, req_cond="ncp.ret_info_mask_id == 1" ),
+ srec( NSAttributeStruct, req_cond="ncp.ret_info_mask_ns_attr == 1" ),
+ srec( DStreamActual, req_cond="ncp.ret_info_mask_actual == 1" ),
+ srec( DStreamLogical, req_cond="ncp.ret_info_mask_logical == 1" ),
+ srec( LastUpdatedInSecondsStruct, req_cond="ncp.ext_info_update == 1" ),
+ srec( DOSNameStruct, req_cond="ncp.ext_info_dos_name == 1" ),
+ srec( FlushTimeStruct, req_cond="ncp.ext_info_flush == 1" ),
+ srec( ParentBaseIDStruct, req_cond="ncp.ext_info_parental == 1" ),
+ srec( MacFinderInfoStruct, req_cond="ncp.ext_info_mac_finder == 1" ),
+ srec( SiblingCountStruct, req_cond="ncp.ext_info_sibling == 1" ),
+ srec( EffectiveRightsStruct, req_cond="ncp.ext_info_effective == 1" ),
+ srec( MacTimeStruct, req_cond="ncp.ext_info_mac_date == 1" ),
+ srec( LastAccessedTimeStruct, req_cond="ncp.ext_info_access == 1" ),
+ srec( FileNameStruct, req_cond="ncp.ret_info_mask_fname == 1" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5721, 87/33
+ pkt = NCP(0x5721, "Open/Create File or Subdirectory II with Callback", 'file', has_length=0)
+ pkt.Request((34, 288), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, DataStream ),
+ rec( 10, 1, OpenCreateMode ),
+ rec( 11, 1, Reserved ),
+ rec( 12, 2, SearchAttributesLow ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 2, ReturnInfoMask ),
+ rec( 18, 2, ExtendedInfo ),
+ rec( 20, 4, AttributesDef32 ),
+ rec( 24, 2, DesiredAccessRights ),
+ rec( 26, 1, VolumeNumber ),
+ rec( 27, 4, DirectoryBase ),
+ rec( 31, 1, HandleFlag ),
+ rec( 32, 1, PathCount, var="x" ),
+ rec( 33, (1,255), Path, repeat="x" ),
+ ], info_str=(FilePath, "Open or Create II with Op-Lock: %s", "/%s"))
+ pkt.Reply((91,345), [
+ rec( 8, 4, FileHandle ),
+ rec( 12, 1, OpenCreateAction ),
+ rec( 13, 1, OCRetFlags ),
+ rec( 14, 4, DataStreamSpaceAlloc ),
+ rec( 18, 6, AttributesStruct ),
+ rec( 24, 4, DataStreamSize ),
+ rec( 28, 4, TtlDSDskSpaceAlloc ),
+ rec( 32, 2, NumberOfDataStreams ),
+ rec( 34, 2, CreationTime ),
+ rec( 36, 2, CreationDate ),
+ rec( 38, 4, CreatorID, BE ),
+ rec( 42, 2, ModifiedTime ),
+ rec( 44, 2, ModifiedDate ),
+ rec( 46, 4, ModifierID, BE ),
+ rec( 50, 2, LastAccessedDate ),
+ rec( 52, 2, ArchivedTime ),
+ rec( 54, 2, ArchivedDate ),
+ rec( 56, 4, ArchiverID, BE ),
+ rec( 60, 2, InheritedRightsMask ),
+ rec( 62, 4, DirectoryEntryNumber ),
+ rec( 66, 4, DOSDirectoryEntryNumber ),
+ rec( 70, 4, VolumeNumberLong ),
+ rec( 74, 4, EADataSize ),
+ rec( 78, 4, EACount ),
+ rec( 82, 4, EAKeySize ),
+ rec( 86, 1, CreatorNameSpaceNumber ),
+ rec( 87, 3, Reserved3 ),
+ rec( 90, (1,255), FileName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5722, 87/34
+ pkt = NCP(0x5722, "Open CallBack Control (Op-Lock)", 'file', has_length=0)
+ pkt.Request(13, [
+ rec( 10, 4, CCFileHandle, BE ),
+ rec( 14, 1, CCFunction ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8800, 0xff16])
+ # 2222/5723, 87/35
+ pkt = NCP(0x5723, "Modify DOS Attributes on a File or Subdirectory", 'file', has_length=0)
+ pkt.Request((28, 282), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Flags ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 2, ReturnInfoMask ),
+ rec( 14, 2, ExtendedInfo ),
+ rec( 16, 4, AttributesDef32 ),
+ rec( 20, 1, VolumeNumber ),
+ rec( 21, 4, DirectoryBase ),
+ rec( 25, 1, HandleFlag ),
+ rec( 26, 1, PathCount, var="x" ),
+ rec( 27, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Modify DOS Attributes for: %s", "/%s"))
+ pkt.Reply(24, [
+ rec( 8, 4, ItemsChecked ),
+ rec( 12, 4, ItemsChanged ),
+ rec( 16, 4, AttributeValidFlag ),
+ rec( 20, 4, AttributesDef32 ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5724, 87/36
+ pkt = NCP(0x5724, "Log File", 'file', has_length=0)
+ pkt.Request((28, 282), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, Reserved2 ),
+ rec( 12, 1, LogFileFlagLow ),
+ rec( 13, 1, LogFileFlagHigh ),
+ rec( 14, 2, Reserved2 ),
+ rec( 16, 4, WaitTime ),
+ rec( 20, 1, VolumeNumber ),
+ rec( 21, 4, DirectoryBase ),
+ rec( 25, 1, HandleFlag ),
+ rec( 26, 1, PathCount, var="x" ),
+ rec( 27, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Lock File: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5725, 87/37
+ pkt = NCP(0x5725, "Release File", 'file', has_length=0)
+ pkt.Request((20, 274), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, Reserved2 ),
+ rec( 12, 1, VolumeNumber ),
+ rec( 13, 4, DirectoryBase ),
+ rec( 17, 1, HandleFlag ),
+ rec( 18, 1, PathCount, var="x" ),
+ rec( 19, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Release Lock on: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5726, 87/38
+ pkt = NCP(0x5726, "Clear File", 'file', has_length=0)
+ pkt.Request((20, 274), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, Reserved2 ),
+ rec( 12, 1, VolumeNumber ),
+ rec( 13, 4, DirectoryBase ),
+ rec( 17, 1, HandleFlag ),
+ rec( 18, 1, PathCount, var="x" ),
+ rec( 19, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Clear File: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5727, 87/39
+ pkt = NCP(0x5727, "Get Directory Disk Space Restriction", 'file', has_length=0)
+ pkt.Request((19, 273), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 2, Reserved2 ),
+ rec( 11, 1, VolumeNumber ),
+ rec( 12, 4, DirectoryBase ),
+ rec( 16, 1, HandleFlag ),
+ rec( 17, 1, PathCount, var="x" ),
+ rec( 18, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Get Disk Space Restriction for: %s", "/%s"))
+ pkt.Reply(18, [
+ rec( 8, 1, NumberOfEntries, var="x" ),
+ rec( 9, 9, SpaceStruct, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00,
+ 0xff16])
+ # 2222/5728, 87/40
+ pkt = NCP(0x5728, "Search for File or Subdirectory Set (Extended Errors)", 'file', has_length=0)
+ pkt.Request((28, 282), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, DataStream ),
+ rec( 10, 2, SearchAttributesLow ),
+ rec( 12, 2, ReturnInfoMask ),
+ rec( 14, 2, ExtendedInfo ),
+ rec( 16, 2, ReturnInfoCount ),
+ rec( 18, 9, SearchSequence ),
+ rec( 27, (1,255), SearchPattern ),
+ ], info_str=(SearchPattern, "Search for: %s", ", %s"))
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec( 8, 9, SearchSequence ),
+ rec( 17, 1, MoreFlag ),
+ rec( 18, 2, InfoCount ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( PadDSSpaceAllocate, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_alloc == 0)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( PadAttributes, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_attr == 0)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 1)" ),
+ srec( PadDataStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_size == 0)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( PadTotalStreamSize, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_tspace == 0)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 1)" ),
+ srec( PadCreationInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_create == 0)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( PadModifyInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_mod == 0)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( PadArchiveInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_arch == 0)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( PadRightsInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_rights == 0)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( PadDirEntry, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_dir == 0)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( PadEAInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_eattr == 0)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( PadNSInfo, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_ns == 0)" ),
+ srec( FileNameStruct, req_cond="(ncp.ext_info_newstyle == 0) && (ncp.ret_info_mask_fname == 1)" ),
+ srec( DSSpaceAllocateStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_alloc == 1)" ),
+ srec( AttributesStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_attr == 1)" ),
+ srec( DataStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_size == 1)" ),
+ srec( TotalStreamSizeStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_tspace == 1)" ),
+ srec( CreationInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_create == 1)" ),
+ srec( ModifyInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_mod == 1)" ),
+ srec( ArchiveInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_arch == 1)" ),
+ srec( RightsInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_rights == 1)" ),
+ srec( DirEntryStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_dir == 1)" ),
+ srec( EAInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_eattr == 1)" ),
+ srec( NSInfoStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_ns == 1)" ),
+ srec( FileNameStruct, req_cond="(ncp.ext_info_newstyle == 1) && (ncp.ret_info_mask_fname == 1)" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5729, 87/41
+ pkt = NCP(0x5729, "Scan Salvageable Files", 'file', has_length=0)
+ pkt.Request((24,278), [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, CtrlFlags, LE ),
+ rec( 12, 4, SequenceNumber ),
+ rec( 16, 1, VolumeNumber ),
+ rec( 17, 4, DirectoryBase ),
+ rec( 21, 1, HandleFlag ),
+ rec( 22, 1, PathCount, var="x" ),
+ rec( 23, (1,255), Path, repeat="x" ),
+ ], info_str=(Path, "Scan Deleted Files: %s", "/%s"))
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec( 8, 4, SequenceNumber ),
+ rec( 12, 4, DirectoryBase ),
+ rec( 16, 4, ScanItems, var="x" ),
+ srec(ScanInfoFileName, req_cond="ncp.ctrl_flags==0x0001", repeat="x" ),
+ srec(ScanInfoFileNoName, req_cond="ncp.ctrl_flags==0x0000", repeat="x" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/572A, 87/42
+ pkt = NCP(0x572A, "Purge Salvageable File List", 'file', has_length=0)
+ pkt.Request(28, [
+ rec( 8, 1, NameSpace ),
+ rec( 9, 1, Reserved ),
+ rec( 10, 2, PurgeFlags ),
+ rec( 12, 4, VolumeNumberLong ),
+ rec( 16, 4, DirectoryBase ),
+ rec( 20, 4, PurgeCount, var="x" ),
+ rec( 24, 4, PurgeList, repeat="x" ),
+ ])
+ pkt.Reply(16, [
+ rec( 8, 4, PurgeCount, var="x" ),
+ rec( 12, 4, PurgeCcode, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/572B, 87/43
+ pkt = NCP(0x572B, "Revoke File Handle Rights", 'file', has_length=0)
+ pkt.Request(17, [
+ rec( 8, 3, Reserved3 ),
+ rec( 11, 1, RevQueryFlag ),
+ rec( 12, 4, FileHandle ),
+ rec( 16, 1, RemoveOpenRights ),
+ ])
+ pkt.Reply(13, [
+ rec( 8, 4, FileHandle ),
+ rec( 12, 1, OpenRights ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/572C, 87/44
+ pkt = NCP(0x572C, "Update File Handle Rights", 'file', has_length=0)
+ pkt.Request(24, [
+ rec( 8, 2, Reserved2 ),
+ rec( 10, 1, VolumeNumber ),
+ rec( 11, 1, NameSpace ),
+ rec( 12, 4, DirectoryNumber ),
+ rec( 16, 2, AccessRightsMaskWord ),
+ rec( 18, 2, NewAccessRights ),
+ rec( 20, 4, FileHandle, BE ),
+ ])
+ pkt.Reply(16, [
+ rec( 8, 4, FileHandle, BE ),
+ rec( 12, 4, EffectiveRights ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff16])
+ # 2222/5740, 87/64
+ pkt = NCP(0x5740, "Read from File", 'file', has_length=0)
+ pkt.Request(22, [
+ rec( 8, 4, FileHandle, BE ),
+ rec( 12, 8, StartOffset64bit, BE ),
+ rec( 20, 2, NumBytes, BE ),
+ ])
+ pkt.Reply(10, [
+ rec( 8, 2, NumBytes, BE),
+ ])
+ pkt.CompletionCodes([0x0000, 0x8300, 0x8800, 0x9300, 0x9500, 0xa201, 0xfd00, 0xff1b])
+ # 2222/5741, 87/65
+ pkt = NCP(0x5741, "Write to File", 'file', has_length=0)
+ pkt.Request(22, [
+ rec( 8, 4, FileHandle, BE ),
+ rec( 12, 8, StartOffset64bit, BE ),
+ rec( 20, 2, NumBytes, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x8300, 0x8800, 0x9400, 0x9500, 0xa201, 0xfd00, 0xff1b])
+ # 2222/5742, 87/66
+ pkt = NCP(0x5742, "Get Current Size of File", 'file', has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, FileHandle, BE ),
+ ])
+ pkt.Reply(16, [
+ rec( 8, 8, FileSize64bit, BE ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x8800, 0x9600, 0xfd02, 0xff01])
+ # 2222/5743, 87/67
+ pkt = NCP(0x5743, "Log Physical Record", 'file', has_length=0)
+ pkt.Request(36, [
+ rec( 8, 4, LockFlag, BE ),
+ rec(12, 4, FileHandle, BE ),
+ rec(16, 8, StartOffset64bit, BE ),
+ rec(24, 8, Length64bit, BE ),
+ rec(32, 4, LockTimeout, BE),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x8800, 0x9600, 0xfb08, 0xfd02, 0xff01])
+ # 2222/5744, 87/68
+ pkt = NCP(0x5744, "Release Physical Record", 'file', has_length=0)
+ pkt.Request(28, [
+ rec(8, 4, FileHandle, BE ),
+ rec(12, 8, StartOffset64bit, BE ),
+ rec(20, 8, Length64bit, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff1a])
+ # 2222/5745, 87/69
+ pkt = NCP(0x5745, "Clear Physical Record", 'file', has_length=0)
+ pkt.Request(28, [
+ rec(8, 4, FileHandle, BE ),
+ rec(12, 8, StartOffset64bit, BE ),
+ rec(20, 8, Length64bit, BE ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xbf00, 0xfd00, 0xff1a])
+ # 2222/5801, 8801
+ pkt = NCP(0x5801, "Query Volume Audit Status", "auditing", has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, ConnectionNumber ),
+ ])
+ pkt.Reply(40, [
+ rec(8, 32, NWAuditStatus ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5802, 8802
+ pkt = NCP(0x5802, "Add User Audit Property", "auditing", has_length=0)
+ pkt.Request(25, [
+ rec(8, 4, AuditIDType ),
+ rec(12, 4, AuditID ),
+ rec(16, 4, AuditHandle ),
+ rec(20, 4, ObjectID ),
+ rec(24, 1, AuditFlag ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5803, 8803
+ pkt = NCP(0x5803, "Add Auditor Access", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5804, 8804
+ pkt = NCP(0x5804, "Change Auditor Volume Password", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5805, 8805
+ pkt = NCP(0x5805, "Check Auditor Access", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5806, 8806
+ pkt = NCP(0x5806, "Delete User Audit Property", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5807, 8807
+ pkt = NCP(0x5807, "Disable Auditing On A Volume", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5808, 8808
+ pkt = NCP(0x5808, "Enable Auditing On A Volume", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5809, 8809
+ pkt = NCP(0x5809, "Query User Being Audited", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/580A, 88,10
+ pkt = NCP(0x580A, "Read Audit Bit Map", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/580B, 88,11
+ pkt = NCP(0x580B, "Read Audit File Configuration Header", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/580D, 88,13
+ pkt = NCP(0x580D, "Remove Auditor Access", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/580E, 88,14
+ pkt = NCP(0x580E, "Reset Audit File", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+
+ # 2222/580F, 88,15
+ pkt = NCP(0x580F, "Auditing NCP", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5810, 88,16
+ pkt = NCP(0x5810, "Write Audit Bit Map", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5811, 88,17
+ pkt = NCP(0x5811, "Write Audit File Configuration Header", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5812, 88,18
+ pkt = NCP(0x5812, "Change Auditor Volume Password2", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5813, 88,19
+ pkt = NCP(0x5813, "Return Audit Flags", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5814, 88,20
+ pkt = NCP(0x5814, "Close Old Audit File", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5816, 88,22
+ pkt = NCP(0x5816, "Check Level Two Access", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5817, 88,23
+ pkt = NCP(0x5817, "Return Old Audit File List", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5818, 88,24
+ pkt = NCP(0x5818, "Init Audit File Reads", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5819, 88,25
+ pkt = NCP(0x5819, "Read Auditing File", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/581A, 88,26
+ pkt = NCP(0x581A, "Delete Old Audit File", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/581E, 88,30
+ pkt = NCP(0x581E, "Restart Volume auditing", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/581F, 88,31
+ pkt = NCP(0x581F, "Set Volume Password", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7300, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa600, 0xa801, 0xfd00, 0xff16])
+ # 2222/5A01, 90/00
+ pkt = NCP(0x5A01, "Parse Tree", 'file')
+ pkt.Request(26, [
+ rec( 10, 4, InfoMask ),
+ rec( 14, 4, Reserved4 ),
+ rec( 18, 4, Reserved4 ),
+ rec( 22, 4, limbCount ),
+ ])
+ pkt.Reply(32, [
+ rec( 8, 4, limbCount ),
+ rec( 12, 4, ItemsCount ),
+ rec( 16, 4, nextLimbScanNum ),
+ rec( 20, 4, CompletionCode ),
+ rec( 24, 1, FolderFlag ),
+ rec( 25, 3, Reserved ),
+ rec( 28, 4, DirectoryBase ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xfd00, 0xff16])
+ # 2222/5A0A, 90/10
+ pkt = NCP(0x5A0A, "Get Reference Count from Dir Entry Number", 'file')
+ pkt.Request(19, [
+ rec( 10, 4, VolumeNumberLong ),
+ rec( 14, 4, DirectoryBase ),
+ rec( 18, 1, NameSpace ),
+ ])
+ pkt.Reply(12, [
+ rec( 8, 4, ReferenceCount ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xfd00, 0xff16])
+ # 2222/5A0B, 90/11
+ pkt = NCP(0x5A0B, "Get Reference Count from Dir Handle", 'file')
+ pkt.Request(14, [
+ rec( 10, 4, DirHandle ),
+ ])
+ pkt.Reply(12, [
+ rec( 8, 4, ReferenceCount ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xfd00, 0xff16])
+ # 2222/5A0C, 90/12
+ pkt = NCP(0x5A0C, "Set Compressed File Size", 'file')
+ pkt.Request(20, [
+ rec( 10, 6, FileHandle ),
+ rec( 16, 4, SuggestedFileSize ),
+ ])
+ pkt.Reply(16, [
+ rec( 8, 4, OldFileSize ),
+ rec( 12, 4, NewFileSize ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xfd00, 0xff16])
+ # 2222/5A80, 90/128
+ pkt = NCP(0x5A80, "Move File Data To Data Migration", 'file')
+ pkt.Request(27, [
+ rec( 10, 4, VolumeNumberLong ),
+ rec( 14, 4, DirectoryEntryNumber ),
+ rec( 18, 1, NameSpace ),
+ rec( 19, 3, Reserved ),
+ rec( 22, 4, SupportModuleID ),
+ rec( 26, 1, DMFlags ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5A81, 90/129
+ pkt = NCP(0x5A81, "Data Migration File Information", 'file')
+ pkt.Request(19, [
+ rec( 10, 4, VolumeNumberLong ),
+ rec( 14, 4, DirectoryEntryNumber ),
+ rec( 18, 1, NameSpace ),
+ ])
+ pkt.Reply(24, [
+ rec( 8, 4, SupportModuleID ),
+ rec( 12, 4, RestoreTime ),
+ rec( 16, 4, DMInfoEntries, var="x" ),
+ rec( 20, 4, DataSize, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5A82, 90/130
+ pkt = NCP(0x5A82, "Volume Data Migration Status", 'file')
+ pkt.Request(18, [
+ rec( 10, 4, VolumeNumberLong ),
+ rec( 14, 4, SupportModuleID ),
+ ])
+ pkt.Reply(32, [
+ rec( 8, 4, NumOfFilesMigrated ),
+ rec( 12, 4, TtlMigratedSize ),
+ rec( 16, 4, SpaceUsed ),
+ rec( 20, 4, LimboUsed ),
+ rec( 24, 4, SpaceMigrated ),
+ rec( 28, 4, FileLimbo ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5A83, 90/131
+ pkt = NCP(0x5A83, "Migrator Status Info", 'file')
+ pkt.Request(10)
+ pkt.Reply(20, [
+ rec( 8, 1, DMPresentFlag ),
+ rec( 9, 3, Reserved3 ),
+ rec( 12, 4, DMmajorVersion ),
+ rec( 16, 4, DMminorVersion ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5A84, 90/132
+ pkt = NCP(0x5A84, "Data Migration Support Module Information", 'file')
+ pkt.Request(18, [
+ rec( 10, 1, DMInfoLevel ),
+ rec( 11, 3, Reserved3),
+ rec( 14, 4, SupportModuleID ),
+ ])
+ pkt.Reply(NO_LENGTH_CHECK, [
+ srec( DMInfoLevel0, req_cond="ncp.dm_info_level == 0x00" ),
+ srec( DMInfoLevel1, req_cond="ncp.dm_info_level == 0x01" ),
+ srec( DMInfoLevel2, req_cond="ncp.dm_info_level == 0x02" ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5A85, 90/133
+ pkt = NCP(0x5A85, "Move File Data From Data Migration", 'file')
+ pkt.Request(19, [
+ rec( 10, 4, VolumeNumberLong ),
+ rec( 14, 4, DirectoryEntryNumber ),
+ rec( 18, 1, NameSpace ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5A86, 90/134
+ pkt = NCP(0x5A86, "Get/Set Default Read-Write Support Module ID", 'file')
+ pkt.Request(18, [
+ rec( 10, 1, GetSetFlag ),
+ rec( 11, 3, Reserved3 ),
+ rec( 14, 4, SupportModuleID ),
+ ])
+ pkt.Reply(12, [
+ rec( 8, 4, SupportModuleID ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5A87, 90/135
+ pkt = NCP(0x5A87, "Data Migration Support Module Capacity Request", 'file')
+ pkt.Request(22, [
+ rec( 10, 4, SupportModuleID ),
+ rec( 14, 4, VolumeNumberLong ),
+ rec( 18, 4, DirectoryBase ),
+ ])
+ pkt.Reply(20, [
+ rec( 8, 4, BlockSizeInSectors ),
+ rec( 12, 4, TotalBlocks ),
+ rec( 16, 4, UsedBlocks ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5A88, 90/136
+ pkt = NCP(0x5A88, "RTDM Request", 'file')
+ pkt.Request(15, [
+ rec( 10, 4, Verb ),
+ rec( 14, 1, VerbData ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C, 91
+ pkt = NCP(0x5B, "NMAS Graded Authentication", 'nmas')
+ #Need info on this packet structure
+ pkt.Request(7)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C00, 9201
+ pkt = NCP(0x5C01, "SecretStore Services (Ping Server)", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C01, 9202
+ pkt = NCP(0x5C02, "SecretStore Services", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C02, 9203
+ pkt = NCP(0x5C03, "SecretStore Services", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C03, 9204
+ pkt = NCP(0x5C04, "SecretStore Services", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C04, 9205
+ pkt = NCP(0x5C05, "SecretStore Services", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C05, 9206
+ pkt = NCP(0x5C06, "SecretStore Services", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C06, 9207
+ pkt = NCP(0x5C07, "SecretStore Services", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C07, 9208
+ pkt = NCP(0x5C08, "SecretStore Services", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C08, 9209
+ pkt = NCP(0x5C09, "SecretStore Services", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5C09, 920a
+ pkt = NCP(0x5C0a, "SecretStore Services", 'sss', 0)
+ #Need info on this packet structure and SecretStore Verbs
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7e01, 0x8000, 0x8101, 0x8401, 0x8501,
+ 0x8701, 0x8800, 0x8d00, 0x8f00, 0x9001, 0x9600, 0xfb0b,
+ 0x9804, 0x9b03, 0x9c03, 0xa800, 0xfd00, 0xff16])
+ # 2222/5E, 9401
+ pkt = NCP(0x5E01, "NMAS Communications Packet", 'nmas', 0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xfb09])
+ # 2222/5E, 9402
+ pkt = NCP(0x5E02, "NMAS Communications Packet", 'nmas', 0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xfb09])
+ # 2222/5E, 9403
+ pkt = NCP(0x5E03, "NMAS Communications Packet", 'nmas', 0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xfb09])
+ # 2222/61, 97
+ pkt = NCP(0x61, "Get Big Packet NCP Max Packet Size", 'comm')
+ pkt.Request(10, [
+ rec( 7, 2, ProposedMaxSize, BE ),
+ rec( 9, 1, SecurityFlag ),
+ ],info_str=(ProposedMaxSize, "Get Big Max Packet Size - %d", ", %d"))
+ pkt.Reply(13, [
+ rec( 8, 2, AcceptedMaxSize, BE ),
+ rec( 10, 2, EchoSocket, BE ),
+ rec( 12, 1, SecurityFlag ),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/63, 99
+ pkt = NCP(0x63, "Undocumented Packet Burst", 'comm')
+ pkt.Request(7)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/64, 100
+ pkt = NCP(0x64, "Undocumented Packet Burst", 'comm')
+ pkt.Request(7)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/65, 101
+ pkt = NCP(0x65, "Packet Burst Connection Request", 'comm')
+ pkt.Request(25, [
+ rec( 7, 4, LocalConnectionID, BE ),
+ rec( 11, 4, LocalMaxPacketSize, BE ),
+ rec( 15, 2, LocalTargetSocket, BE ),
+ rec( 17, 4, LocalMaxSendSize, BE ),
+ rec( 21, 4, LocalMaxRecvSize, BE ),
+ ])
+ pkt.Reply(16, [
+ rec( 8, 4, RemoteTargetID, BE ),
+ rec( 12, 4, RemoteMaxPacketSize, BE ),
+ ])
+ pkt.CompletionCodes([0x0000])
+ # 2222/66, 102
+ pkt = NCP(0x66, "Undocumented Packet Burst", 'comm')
+ pkt.Request(7)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/67, 103
+ pkt = NCP(0x67, "Undocumented Packet Burst", 'comm')
+ pkt.Request(7)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000])
+ # 2222/6801, 104/01
+ pkt = NCP(0x6801, "Ping for NDS NCP", "nds", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x8100, 0xfb04, 0xfe0c])
+ # 2222/6802, 104/02
+ #
+ # XXX - if FraggerHandle is not 0xffffffff, this is not the
+ # first fragment, so we can only dissect this by reassembling;
+ # the fields after "Fragment Handle" are bogus for non-0xffffffff
+ # fragments, so we shouldn't dissect them.
+ #
+ # XXX - are there TotalRequest requests in the packet, and
+ # does each of them have NDSFlags and NDSVerb fields, or
+ # does only the first one have it?
+ #
+ pkt = NCP(0x6802, "Send NDS Fragmented Request/Reply", "nds", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0xfd01])
+ # 2222/6803, 104/03
+ pkt = NCP(0x6803, "Fragment Close", "nds", has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, FraggerHandle ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xff00])
+ # 2222/6804, 104/04
+ pkt = NCP(0x6804, "Return Bindery Context", "nds", has_length=0)
+ pkt.Request(8)
+ pkt.Reply((9, 263), [
+ rec( 8, (1,255), binderyContext ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfe0c, 0xff00])
+ # 2222/6805, 104/05
+ pkt = NCP(0x6805, "Monitor NDS Connection", "nds", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/6806, 104/06
+ pkt = NCP(0x6806, "Return NDS Statistics", "nds", has_length=0)
+ pkt.Request(10, [
+ rec( 8, 2, NDSRequestFlags ),
+ ])
+ pkt.Reply(8)
+ #Need to investigate how to decode Statistics Return Value
+ pkt.CompletionCodes([0x0000, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/6807, 104/07
+ pkt = NCP(0x6807, "Clear NDS Statistics", "nds", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/6808, 104/08
+ pkt = NCP(0x6808, "Reload NDS Software", "nds", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(12, [
+ rec( 8, 4, NDSStatus ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68C8, 104/200
+ pkt = NCP(0x68C8, "Query Container Audit Status", "auditing", has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, ConnectionNumber ),
+# rec( 12, 4, AuditIDType, LE ),
+# rec( 16, 4, AuditID ),
+# rec( 20, 2, BufferSize ),
+ ])
+ pkt.Reply(40, [
+ rec(8, 32, NWAuditStatus ),
+ ])
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68CA, 104/202
+ pkt = NCP(0x68CA, "Add Auditor Access", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68CB, 104/203
+ pkt = NCP(0x68CB, "Change Auditor Container Password", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68CC, 104/204
+ pkt = NCP(0x68CC, "Check Auditor Access", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68CE, 104/206
+ pkt = NCP(0x680CE, "Disable Container Auditing", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68CF, 104/207
+ pkt = NCP(0x68CF, "Enable Container Auditing", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68D1, 104/209
+ pkt = NCP(0x68D1, "Read Audit File Header", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68D3, 104/211
+ pkt = NCP(0x68D3, "Remove Auditor Access", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68D4, 104/212
+ pkt = NCP(0x68D4, "Reset Audit File", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68D6, 104/214
+ pkt = NCP(0x68D6, "Write Audit File Configuration Header", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68D7, 104/215
+ pkt = NCP(0x68D7, "Change Auditor Container Password2", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68D8, 104/216
+ pkt = NCP(0x68D8, "Return Audit Flags", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68D9, 104/217
+ pkt = NCP(0x68D9, "Close Old Audit File", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68DB, 104/219
+ pkt = NCP(0x68DB, "Check Level Two Access", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68DC, 104/220
+ pkt = NCP(0x68DC, "Check Object Audited", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68DD, 104/221
+ pkt = NCP(0x68DD, "Change Object Audited", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68DE, 104/222
+ pkt = NCP(0x68DE, "Return Old Audit File List", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68DF, 104/223
+ pkt = NCP(0x68DF, "Init Audit File Reads", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68E0, 104/224
+ pkt = NCP(0x68E0, "Read Auditing File", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68E1, 104/225
+ pkt = NCP(0x68E1, "Delete Old Audit File", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68E5, 104/229
+ pkt = NCP(0x68E5, "Set Audit Password", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/68E7, 104/231
+ pkt = NCP(0x68E7, "External Audit Append To File", "auditing", has_length=0)
+ pkt.Request(8)
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0xa700, 0xfb00, 0xfe0c, 0xff00])
+ # 2222/69, 105
+ pkt = NCP(0x69, "Log File", 'file')
+ pkt.Request( (12, 267), [
+ rec( 7, 1, DirHandle ),
+ rec( 8, 1, LockFlag ),
+ rec( 9, 2, TimeoutLimit ),
+ rec( 11, (1, 256), FilePath ),
+ ], info_str=(FilePath, "Log File: %s", "/%s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x8200, 0x9600, 0xfe0d, 0xff01])
+ # 2222/6A, 106
+ pkt = NCP(0x6A, "Lock File Set", 'file')
+ pkt.Request( 9, [
+ rec( 7, 2, TimeoutLimit ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x8200, 0x9600, 0xfe0d, 0xff01])
+ # 2222/6B, 107
+ pkt = NCP(0x6B, "Log Logical Record", 'file')
+ pkt.Request( (11, 266), [
+ rec( 7, 1, LockFlag ),
+ rec( 8, 2, TimeoutLimit ),
+ rec( 10, (1, 256), SynchName ),
+ ], info_str=(SynchName, "Log Logical Record: %s", ", %s"))
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x9600, 0xfe0d, 0xff01])
+ # 2222/6C, 108
+ pkt = NCP(0x6C, "Log Logical Record", 'file')
+ pkt.Request( 10, [
+ rec( 7, 1, LockFlag ),
+ rec( 8, 2, TimeoutLimit ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x9600, 0xfe0d, 0xff01])
+ # 2222/6D, 109
+ pkt = NCP(0x6D, "Log Physical Record", 'file')
+ pkt.Request(24, [
+ rec( 7, 1, LockFlag ),
+ rec( 8, 6, FileHandle ),
+ rec( 14, 4, LockAreasStartOffset ),
+ rec( 18, 4, LockAreaLen ),
+ rec( 22, 2, LockTimeout ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x8200, 0x8800, 0x9600, 0xfd02, 0xfe04, 0xff01])
+ # 2222/6E, 110
+ pkt = NCP(0x6E, "Lock Physical Record Set", 'file')
+ pkt.Request(10, [
+ rec( 7, 1, LockFlag ),
+ rec( 8, 2, LockTimeout ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x7f00, 0x8200, 0x8800, 0x9600, 0xfd02, 0xfe04, 0xff01])
+ # 2222/6F00, 111/00
+ pkt = NCP(0x6F00, "Open/Create a Semaphore", 'file', has_length=0)
+ pkt.Request((10,521), [
+ rec( 8, 1, InitialSemaphoreValue ),
+ rec( 9, (1, 512), SemaphoreName ),
+ ], info_str=(SemaphoreName, "Open/Create Semaphore: %s", ", %s"))
+ pkt.Reply(13, [
+ rec( 8, 4, SemaphoreHandle ),
+ rec( 12, 1, SemaphoreOpenCount ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xff01])
+ # 2222/6F01, 111/01
+ pkt = NCP(0x6F01, "Examine Semaphore", 'file', has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, SemaphoreHandle ),
+ ])
+ pkt.Reply(10, [
+ rec( 8, 1, SemaphoreValue ),
+ rec( 9, 1, SemaphoreOpenCount ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xff01])
+ # 2222/6F02, 111/02
+ pkt = NCP(0x6F02, "Wait On (P) Semaphore", 'file', has_length=0)
+ pkt.Request(14, [
+ rec( 8, 4, SemaphoreHandle ),
+ rec( 12, 2, LockTimeout ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xfe04, 0xff01])
+ # 2222/6F03, 111/03
+ pkt = NCP(0x6F03, "Signal (V) Semaphore", 'file', has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, SemaphoreHandle ),
+ ])
+ pkt.Reply(8)
+ pkt.CompletionCodes([0x0000, 0x9600, 0xfe04, 0xff01])
+ # 2222/6F04, 111/04
+ pkt = NCP(0x6F04, "Close Semaphore", 'file', has_length=0)
+ pkt.Request(12, [
+ rec( 8, 4, SemaphoreHandle ),
+ ])
+ pkt.Reply(10, [
+ rec( 8, 1, SemaphoreOpenCount ),
+ rec( 9, 1, SemaphoreShareCount ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x9600, 0xfe04, 0xff01])
+ # 2222/7201, 114/01
+ pkt = NCP(0x7201, "Timesync Get Time", 'file')
+ pkt.Request(10)
+ pkt.Reply(32,[
+ rec( 8, 12, theTimeStruct ),
+ rec(20, 8, eventOffset ),
+ rec(28, 4, eventTime ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb06, 0xff00])
+ # 2222/7202, 114/02
+ pkt = NCP(0x7202, "Timesync Exchange Time", 'file')
+ pkt.Request((63,112), [
+ rec( 10, 4, protocolFlags ),
+ rec( 14, 4, nodeFlags ),
+ rec( 18, 8, sourceOriginateTime ),
+ rec( 26, 8, targetReceiveTime ),
+ rec( 34, 8, targetTransmitTime ),
+ rec( 42, 8, sourceReturnTime ),
+ rec( 50, 8, eventOffset ),
+ rec( 58, 4, eventTime ),
+ rec( 62, (1,50), ServerNameLen ),
+ ], info_str=(ServerNameLen, "Timesync Exchange Time: %s", ", %s"))
+ pkt.Reply((64,113), [
+ rec( 8, 3, Reserved3 ),
+ rec( 11, 4, protocolFlags ),
+ rec( 15, 4, nodeFlags ),
+ rec( 19, 8, sourceOriginateTime ),
+ rec( 27, 8, targetReceiveTime ),
+ rec( 35, 8, targetTransmitTime ),
+ rec( 43, 8, sourceReturnTime ),
+ rec( 51, 8, eventOffset ),
+ rec( 59, 4, eventTime ),
+ rec( 63, (1,50), ServerNameLen ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb06, 0xff00])
+ # 2222/7205, 114/05
+ pkt = NCP(0x7205, "Timesync Get Server List", 'file')
+ pkt.Request(14, [
+ rec( 10, 4, StartNumber ),
+ ])
+ pkt.Reply(66, [
+ rec( 8, 4, nameType ),
+ rec( 12, 48, ServerName ),
+ rec( 60, 4, serverListFlags ),
+ rec( 64, 2, startNumberFlag ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb06, 0xff00])
+ # 2222/7206, 114/06
+ pkt = NCP(0x7206, "Timesync Set Server List", 'file')
+ pkt.Request(14, [
+ rec( 10, 4, StartNumber ),
+ ])
+ pkt.Reply(66, [
+ rec( 8, 4, nameType ),
+ rec( 12, 48, ServerName ),
+ rec( 60, 4, serverListFlags ),
+ rec( 64, 2, startNumberFlag ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb06, 0xff00])
+ # 2222/720C, 114/12
+ pkt = NCP(0x720C, "Timesync Get Version", 'file')
+ pkt.Request(10)
+ pkt.Reply(12, [
+ rec( 8, 4, version ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb06, 0xff00])
+ # 2222/7B01, 123/01
+ pkt = NCP(0x7B01, "Get Cache Information", 'stats')
+ pkt.Request(12, [
+ rec(10, 1, VersionNumber),
+ rec(11, 1, RevisionNumber),
+ ])
+ pkt.Reply(288, [
+ rec(8, 4, CurrentServerTime, LE),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 104, Counters ),
+ rec(120, 40, ExtraCacheCntrs ),
+ rec(160, 40, MemoryCounters ),
+ rec(200, 48, TrendCounters ),
+ rec(248, 40, CacheInfo ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xff00])
+ # 2222/7B02, 123/02
+ pkt = NCP(0x7B02, "Get File Server Information", 'stats')
+ pkt.Request(10)
+ pkt.Reply(150, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NCPStaInUseCnt ),
+ rec(20, 4, NCPPeakStaInUse ),
+ rec(24, 4, NumOfNCPReqs ),
+ rec(28, 4, ServerUtilization ),
+ rec(32, 96, ServerInfo ),
+ rec(128, 22, FileServerCounters ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B03, 123/03
+ pkt = NCP(0x7B03, "NetWare File System Information", 'stats')
+ pkt.Request(11, [
+ rec(10, 1, FileSystemID ),
+ ])
+ pkt.Reply(68, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 52, FileSystemInfo ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B04, 123/04
+ pkt = NCP(0x7B04, "User Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, ConnectionNumber ),
+ ])
+ pkt.Reply((85, 132), [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 68, UserInformation ),
+ rec(84, (1, 48), UserName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B05, 123/05
+ pkt = NCP(0x7B05, "Packet Burst Information", 'stats')
+ pkt.Request(10)
+ pkt.Reply(216, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 200, PacketBurstInformation ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B06, 123/06
+ pkt = NCP(0x7B06, "IPX SPX Information", 'stats')
+ pkt.Request(10)
+ pkt.Reply(94, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 34, IPXInformation ),
+ rec(50, 44, SPXInformation ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B07, 123/07
+ pkt = NCP(0x7B07, "Garbage Collection Information", 'stats')
+ pkt.Request(10)
+ pkt.Reply(40, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, FailedAllocReqCnt ),
+ rec(20, 4, NumberOfAllocs ),
+ rec(24, 4, NoMoreMemAvlCnt ),
+ rec(28, 4, NumOfGarbageColl ),
+ rec(32, 4, FoundSomeMem ),
+ rec(36, 4, NumOfChecks ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B08, 123/08
+ pkt = NCP(0x7B08, "CPU Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, CPUNumber ),
+ ])
+ pkt.Reply(51, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NumberOfCPUs ),
+ rec(20, 31, CPUInformation ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B09, 123/09
+ pkt = NCP(0x7B09, "Volume Switch Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, StartNumber )
+ ])
+ pkt.Reply(28, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, TotalLFSCounters ),
+ rec(20, 4, CurrentLFSCounters, var="x"),
+ rec(24, 4, LFSCounters, repeat="x"),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B0A, 123/10
+ pkt = NCP(0x7B0A, "Get NLM Loaded List", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, StartNumber )
+ ])
+ pkt.Reply(28, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NLMcount ),
+ rec(20, 4, NLMsInList, var="x" ),
+ rec(24, 4, NLMNumbers, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B0B, 123/11
+ pkt = NCP(0x7B0B, "NLM Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, NLMNumber ),
+ ])
+ pkt.Reply((79,841), [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 60, NLMInformation ),
+ rec(76, (1,255), FileName ),
+ rec(-1, (1,255), Name ),
+ rec(-1, (1,255), Copyright ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B0C, 123/12
+ pkt = NCP(0x7B0C, "Get Directory Cache Information", 'stats')
+ pkt.Request(10)
+ pkt.Reply(72, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 56, DirCacheInfo ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B0D, 123/13
+ pkt = NCP(0x7B0D, "Get Operating System Version Information", 'stats')
+ pkt.Request(10)
+ pkt.Reply(70, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 1, OSMajorVersion ),
+ rec(17, 1, OSMinorVersion ),
+ rec(18, 1, OSRevision ),
+ rec(19, 1, AccountVersion ),
+ rec(20, 1, VAPVersion ),
+ rec(21, 1, QueueingVersion ),
+ rec(22, 1, SecurityRestrictionVersion ),
+ rec(23, 1, InternetBridgeVersion ),
+ rec(24, 4, MaxNumOfVol ),
+ rec(28, 4, MaxNumOfConn ),
+ rec(32, 4, MaxNumOfUsers ),
+ rec(36, 4, MaxNumOfNmeSps ),
+ rec(40, 4, MaxNumOfLANS ),
+ rec(44, 4, MaxNumOfMedias ),
+ rec(48, 4, MaxNumOfStacks ),
+ rec(52, 4, MaxDirDepth ),
+ rec(56, 4, MaxDataStreams ),
+ rec(60, 4, MaxNumOfSpoolPr ),
+ rec(64, 4, ServerSerialNumber ),
+ rec(68, 2, ServerAppNumber ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B0E, 123/14
+ pkt = NCP(0x7B0E, "Get Active Connection List by Type", 'stats')
+ pkt.Request(15, [
+ rec(10, 4, StartConnNumber ),
+ rec(14, 1, ConnectionType ),
+ ])
+ pkt.Reply(528, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 512, ActiveConnBitList ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfd01, 0xff00])
+ # 2222/7B0F, 123/15
+ pkt = NCP(0x7B0F, "Get NLM Resource Tag List", 'stats')
+ pkt.Request(18, [
+ rec(10, 4, NLMNumber ),
+ rec(14, 4, NLMStartNumber ),
+ ])
+ pkt.Reply(37, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, TtlNumOfRTags ),
+ rec(20, 4, CurNumOfRTags ),
+ rec(24, 13, RTagStructure ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B10, 123/16
+ pkt = NCP(0x7B10, "Enumerate Connection Information from Connection List", 'stats')
+ pkt.Request(22, [
+ rec(10, 1, EnumInfoMask),
+ rec(11, 3, Reserved3),
+ rec(14, 4, itemsInList, var="x"),
+ rec(18, 4, connList, repeat="x"),
+ ])
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, ItemsInPacket ),
+ srec(netAddr, req_cond="ncp.enum_info_transport==TRUE"),
+ srec(timeInfo, req_cond="ncp.enum_info_time==TRUE"),
+ srec(nameInfo, req_cond="ncp.enum_info_name==TRUE"),
+ srec(lockInfo, req_cond="ncp.enum_info_lock==TRUE"),
+ srec(printInfo, req_cond="ncp.enum_info_print==TRUE"),
+ srec(statsInfo, req_cond="ncp.enum_info_stats==TRUE"),
+ srec(acctngInfo, req_cond="ncp.enum_info_account==TRUE"),
+ srec(authInfo, req_cond="ncp.enum_info_auth==TRUE"),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B11, 123/17
+ pkt = NCP(0x7B11, "Enumerate NCP Service Network Addresses", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, SearchNumber ),
+ ])
+ pkt.Reply(60, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, ServerInfoFlags ),
+ rec(16, 16, GUID ),
+ rec(32, 4, NextSearchNum ),
+ rec(36, 4, ItemsInPacket, var="x"),
+ rec(40, 20, NCPNetworkAddress, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb01, 0xff00])
+ # 2222/7B14, 123/20
+ pkt = NCP(0x7B14, "Active LAN Board List", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, StartNumber ),
+ ])
+ pkt.Reply(28, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, MaxNumOfLANS ),
+ rec(20, 4, ItemsInPacket, var="x"),
+ rec(24, 4, BoardNumbers, repeat="x"),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B15, 123/21
+ pkt = NCP(0x7B15, "LAN Configuration Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, BoardNumber ),
+ ])
+ pkt.Reply(152, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16,136, LANConfigInfo ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B16, 123/22
+ pkt = NCP(0x7B16, "LAN Common Counters Information", 'stats')
+ pkt.Request(18, [
+ rec(10, 4, BoardNumber ),
+ rec(14, 4, BlockNumber ),
+ ])
+ pkt.Reply(86, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 1, StatMajorVersion ),
+ rec(15, 1, StatMinorVersion ),
+ rec(16, 4, TotalCommonCnts ),
+ rec(20, 4, TotalCntBlocks ),
+ rec(24, 4, CustomCounters ),
+ rec(28, 4, NextCntBlock ),
+ rec(32, 54, CommonLanStruc ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B17, 123/23
+ pkt = NCP(0x7B17, "LAN Custom Counters Information", 'stats')
+ pkt.Request(18, [
+ rec(10, 4, BoardNumber ),
+ rec(14, 4, StartNumber ),
+ ])
+ pkt.Reply(25, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NumOfCCinPkt, var="x"),
+ rec(20, 5, CustomCntsInfo, repeat="x"),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B18, 123/24
+ pkt = NCP(0x7B18, "LAN Name Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, BoardNumber ),
+ ])
+ pkt.Reply(19, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 3, BoardNameStruct ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B19, 123/25
+ pkt = NCP(0x7B19, "LSL Information", 'stats')
+ pkt.Request(10)
+ pkt.Reply(90, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 74, LSLInformation ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B1A, 123/26
+ pkt = NCP(0x7B1A, "LSL Logical Board Statistics", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, BoardNumber ),
+ ])
+ pkt.Reply(28, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, LogTtlTxPkts ),
+ rec(20, 4, LogTtlRxPkts ),
+ rec(24, 4, UnclaimedPkts ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B1B, 123/27
+ pkt = NCP(0x7B1B, "MLID Board Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, BoardNumber ),
+ ])
+ pkt.Reply(44, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 1, Reserved ),
+ rec(15, 1, NumberOfProtocols ),
+ rec(16, 28, MLIDBoardInfo ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B1E, 123/30
+ pkt = NCP(0x7B1E, "Get Media Manager Object Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, ObjectNumber ),
+ ])
+ pkt.Reply(212, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 196, GenericInfoDef ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B1F, 123/31
+ pkt = NCP(0x7B1F, "Get Media Manager Objects List", 'stats')
+ pkt.Request(15, [
+ rec(10, 4, StartNumber ),
+ rec(14, 1, MediaObjectType ),
+ ])
+ pkt.Reply(28, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, nextStartingNumber ),
+ rec(20, 4, ObjectCount, var="x"),
+ rec(24, 4, ObjectID, repeat="x"),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B20, 123/32
+ pkt = NCP(0x7B20, "Get Media Manager Object Childrens List", 'stats')
+ pkt.Request(22, [
+ rec(10, 4, StartNumber ),
+ rec(14, 1, MediaObjectType ),
+ rec(15, 3, Reserved3 ),
+ rec(18, 4, ParentObjectNumber ),
+ ])
+ pkt.Reply(28, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, nextStartingNumber ),
+ rec(20, 4, ObjectCount, var="x" ),
+ rec(24, 4, ObjectID, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B21, 123/33
+ pkt = NCP(0x7B21, "Get Volume Segment List", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, VolumeNumberLong ),
+ ])
+ pkt.Reply(32, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NumOfSegments, var="x" ),
+ rec(20, 12, Segments, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B22, 123/34
+ pkt = NCP(0x7B22, "Get Volume Information by Level", 'stats')
+ pkt.Request(15, [
+ rec(10, 4, VolumeNumberLong ),
+ rec(14, 1, InfoLevelNumber ),
+ ])
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 1, InfoLevelNumber ),
+ rec(17, 3, Reserved3 ),
+ srec(VolInfoStructure, req_cond="ncp.info_level_num==0x01"),
+ srec(VolInfo2Struct, req_cond="ncp.info_level_num==0x02"),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B28, 123/40
+ pkt = NCP(0x7B28, "Active Protocol Stacks", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, StartNumber ),
+ ])
+ pkt.Reply(48, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, MaxNumOfLANS ),
+ rec(20, 4, StackCount, var="x" ),
+ rec(24, 4, nextStartingNumber ),
+ rec(28, 20, StackInfo, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B29, 123/41
+ pkt = NCP(0x7B29, "Get Protocol Stack Configuration Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, StackNumber ),
+ ])
+ pkt.Reply((37,164), [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 1, ConfigMajorVN ),
+ rec(17, 1, ConfigMinorVN ),
+ rec(18, 1, StackMajorVN ),
+ rec(19, 1, StackMinorVN ),
+ rec(20, 16, ShortStkName ),
+ rec(36, (1,128), StackFullNameStr ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B2A, 123/42
+ pkt = NCP(0x7B2A, "Get Protocol Stack Statistics Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, StackNumber ),
+ ])
+ pkt.Reply(38, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 1, StatMajorVersion ),
+ rec(17, 1, StatMinorVersion ),
+ rec(18, 2, ComCnts ),
+ rec(20, 4, CounterMask ),
+ rec(24, 4, TotalTxPkts ),
+ rec(28, 4, TotalRxPkts ),
+ rec(32, 4, IgnoredRxPkts ),
+ rec(36, 2, CustomCnts ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B2B, 123/43
+ pkt = NCP(0x7B2B, "Get Protocol Stack Custom Information", 'stats')
+ pkt.Request(18, [
+ rec(10, 4, StackNumber ),
+ rec(14, 4, StartNumber ),
+ ])
+ pkt.Reply(25, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, CustomCount, var="x" ),
+ rec(20, 5, CustomCntsInfo, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B2C, 123/44
+ pkt = NCP(0x7B2C, "Get Protocol Stack Numbers by Media Number", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, MediaNumber ),
+ ])
+ pkt.Reply(24, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, StackCount, var="x" ),
+ rec(20, 4, StackNumber, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B2D, 123/45
+ pkt = NCP(0x7B2D, "Get Protocol Stack Numbers by LAN Board Number", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, BoardNumber ),
+ ])
+ pkt.Reply(24, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, StackCount, var="x" ),
+ rec(20, 4, StackNumber, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B2E, 123/46
+ pkt = NCP(0x7B2E, "Get Media Name by Media Number", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, MediaNumber ),
+ ])
+ pkt.Reply((17,144), [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, (1,128), MediaName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7900, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B2F, 123/47
+ pkt = NCP(0x7B2F, "Get Loaded Media Number", 'stats')
+ pkt.Request(10)
+ pkt.Reply(28, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, MaxNumOfMedias ),
+ rec(20, 4, MediaListCount, var="x" ),
+ rec(24, 4, MediaList, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B32, 123/50
+ pkt = NCP(0x7B32, "Get General Router and SAP Information", 'stats')
+ pkt.Request(10)
+ pkt.Reply(37, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 2, RIPSocketNumber ),
+ rec(18, 2, Reserved2 ),
+ rec(20, 1, RouterDownFlag ),
+ rec(21, 3, Reserved3 ),
+ rec(24, 1, TrackOnFlag ),
+ rec(25, 3, Reserved3 ),
+ rec(28, 1, ExtRouterActiveFlag ),
+ rec(29, 3, Reserved3 ),
+ rec(32, 2, SAPSocketNumber ),
+ rec(34, 2, Reserved2 ),
+ rec(36, 1, RpyNearestSrvFlag ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B33, 123/51
+ pkt = NCP(0x7B33, "Get Network Router Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, NetworkNumber ),
+ ])
+ pkt.Reply(26, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 10, KnownRoutes ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x0108, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B34, 123/52
+ pkt = NCP(0x7B34, "Get Network Routers Information", 'stats')
+ pkt.Request(18, [
+ rec(10, 4, NetworkNumber),
+ rec(14, 4, StartNumber ),
+ ])
+ pkt.Reply(34, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NumOfEntries, var="x" ),
+ rec(20, 14, RoutersInfo, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x0108, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B35, 123/53
+ pkt = NCP(0x7B35, "Get Known Networks Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, StartNumber ),
+ ])
+ pkt.Reply(30, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NumOfEntries, var="x" ),
+ rec(20, 10, KnownRoutes, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B36, 123/54
+ pkt = NCP(0x7B36, "Get Server Information", 'stats')
+ pkt.Request((15,64), [
+ rec(10, 2, ServerType ),
+ rec(12, 2, Reserved2 ),
+ rec(14, (1,50), ServerNameLen ),
+ ], info_str=(ServerNameLen, "Get Server Information: %s", ", %s"))
+ pkt.Reply(30, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 12, ServerAddress ),
+ rec(28, 2, HopsToNet ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B37, 123/55
+ pkt = NCP(0x7B37, "Get Server Sources Information", 'stats')
+ pkt.Request((19,68), [
+ rec(10, 4, StartNumber ),
+ rec(14, 2, ServerType ),
+ rec(16, 2, Reserved2 ),
+ rec(18, (1,50), ServerNameLen ),
+ ], info_str=(ServerNameLen, "Get Server Sources Info: %s", ", %s"))
+ pkt.Reply(32, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NumOfEntries, var="x" ),
+ rec(20, 12, ServersSrcInfo, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x0108, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B38, 123/56
+ pkt = NCP(0x7B38, "Get Known Servers Information", 'stats')
+ pkt.Request(16, [
+ rec(10, 4, StartNumber ),
+ rec(14, 2, ServerType ),
+ ])
+ pkt.Reply(35, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NumOfEntries, var="x" ),
+ rec(20, 15, KnownServStruc, repeat="x" ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x0108, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B3C, 123/60
+ pkt = NCP(0x7B3C, "Get Server Set Commands Information", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, StartNumber ),
+ ])
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, TtlNumOfSetCmds ),
+ rec(20, 4, nextStartingNumber ),
+ rec(24, 1, SetCmdType ),
+ rec(25, 3, Reserved3 ),
+ rec(28, 1, SetCmdCategory ),
+ rec(29, 3, Reserved3 ),
+ rec(32, 1, SetCmdFlags ),
+ rec(33, 3, Reserved3 ),
+ rec(36, 100, SetCmdName ),
+ rec(136, 4, SetCmdValueNum ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B3D, 123/61
+ pkt = NCP(0x7B3D, "Get Server Set Categories", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, StartNumber ),
+ ])
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, NumberOfSetCategories ),
+ rec(20, 4, nextStartingNumber ),
+ rec(24, PROTO_LENGTH_UNKNOWN, CategoryName ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B3E, 123/62
+ pkt = NCP(0x7B3E, "Get Server Set Commands Information By Name", 'stats')
+ pkt.Request(NO_LENGTH_CHECK, [
+ rec(10, PROTO_LENGTH_UNKNOWN, SetParmName ),
+ ], info_str=(SetParmName, "Get Server Set Command Info for: %s", ", %s"))
+ pkt.Reply(NO_LENGTH_CHECK, [
+ rec(8, 4, CurrentServerTime ),
+ rec(12, 1, VConsoleVersion ),
+ rec(13, 1, VConsoleRevision ),
+ rec(14, 2, Reserved2 ),
+ rec(16, 4, TtlNumOfSetCmds ),
+ rec(20, 4, nextStartingNumber ),
+ rec(24, 1, SetCmdType ),
+ rec(25, 3, Reserved3 ),
+ rec(28, 1, SetCmdCategory ),
+ rec(29, 3, Reserved3 ),
+ rec(32, 1, SetCmdFlags ),
+ rec(33, 3, Reserved3 ),
+ rec(36, PROTO_LENGTH_UNKNOWN, SetCmdName ),
+ #rec(136, 4, SetCmdValueNum ),
+ ])
+ pkt.ReqCondSizeVariable()
+ pkt.CompletionCodes([0x0000, 0x7e01, 0xfb06, 0xff00])
+ # 2222/7B46, 123/70
+ pkt = NCP(0x7B46, "Get Current Compressing File", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, VolumeNumberLong ),
+ ])
+ pkt.Reply(56, [
+ rec(8, 4, ParentID ),
+ rec(12, 4, DirectoryEntryNumber ),
+ rec(16, 4, compressionStage ),
+ rec(20, 4, ttlIntermediateBlks ),
+ rec(24, 4, ttlCompBlks ),
+ rec(28, 4, curIntermediateBlks ),
+ rec(32, 4, curCompBlks ),
+ rec(36, 4, curInitialBlks ),
+ rec(40, 4, fileFlags ),
+ rec(44, 4, projectedCompSize ),
+ rec(48, 4, originalSize ),
+ rec(52, 4, compressVolume ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0x7901, 0xfb06, 0xff00])
+ # 2222/7B47, 123/71
+ pkt = NCP(0x7B47, "Get Current DeCompressing File Info List", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, VolumeNumberLong ),
+ ])
+ pkt.Reply(28, [
+ rec(8, 4, FileListCount ),
+ rec(12, 16, FileInfoStruct ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb06, 0xff00])
+ # 2222/7B48, 123/72
+ pkt = NCP(0x7B48, "Get Compression and Decompression Time and Counts", 'stats')
+ pkt.Request(14, [
+ rec(10, 4, VolumeNumberLong ),
+ ])
+ pkt.Reply(64, [
+ rec(8, 56, CompDeCompStat ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb06, 0xff00])
+ # 2222/8301, 131/01
+ pkt = NCP(0x8301, "RPC Load an NLM", 'fileserver')
+ pkt.Request(NO_LENGTH_CHECK, [
+ rec(10, 4, NLMLoadOptions ),
+ rec(14, 16, Reserved16 ),
+ rec(30, PROTO_LENGTH_UNKNOWN, PathAndName ),
+ ], info_str=(PathAndName, "RPC Load NLM: %s", ", %s"))
+ pkt.Reply(12, [
+ rec(8, 4, RPCccode ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb07, 0xff00])
+ # 2222/8302, 131/02
+ pkt = NCP(0x8302, "RPC Unload an NLM", 'fileserver')
+ pkt.Request(NO_LENGTH_CHECK, [
+ rec(10, 20, Reserved20 ),
+ rec(30, PROTO_LENGTH_UNKNOWN, NLMName ),
+ ], info_str=(NLMName, "RPC Unload NLM: %s", ", %s"))
+ pkt.Reply(12, [
+ rec(8, 4, RPCccode ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb07, 0xff00])
+ # 2222/8303, 131/03
+ pkt = NCP(0x8303, "RPC Mount Volume", 'fileserver')
+ pkt.Request(NO_LENGTH_CHECK, [
+ rec(10, 20, Reserved20 ),
+ rec(30, PROTO_LENGTH_UNKNOWN, VolumeNameStringz ),
+ ], info_str=(VolumeNameStringz, "RPC Mount Volume: %s", ", %s"))
+ pkt.Reply(32, [
+ rec(8, 4, RPCccode),
+ rec(12, 16, Reserved16 ),
+ rec(28, 4, VolumeNumberLong ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb07, 0xff00])
+ # 2222/8304, 131/04
+ pkt = NCP(0x8304, "RPC Dismount Volume", 'fileserver')
+ pkt.Request(NO_LENGTH_CHECK, [
+ rec(10, 20, Reserved20 ),
+ rec(30, PROTO_LENGTH_UNKNOWN, VolumeNameStringz ),
+ ], info_str=(VolumeNameStringz, "RPC Dismount Volume: %s", ", %s"))
+ pkt.Reply(12, [
+ rec(8, 4, RPCccode ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb07, 0xff00])
+ # 2222/8305, 131/05
+ pkt = NCP(0x8305, "RPC Add Name Space To Volume", 'fileserver')
+ pkt.Request(NO_LENGTH_CHECK, [
+ rec(10, 20, Reserved20 ),
+ rec(30, PROTO_LENGTH_UNKNOWN, AddNameSpaceAndVol ),
+ ], info_str=(AddNameSpaceAndVol, "RPC Add Name Space to Volume: %s", ", %s"))
+ pkt.Reply(12, [
+ rec(8, 4, RPCccode ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb07, 0xff00])
+ # 2222/8306, 131/06
+ pkt = NCP(0x8306, "RPC Set Command Value", 'fileserver')
+ pkt.Request(NO_LENGTH_CHECK, [
+ rec(10, 1, SetCmdType ),
+ rec(11, 3, Reserved3 ),
+ rec(14, 4, SetCmdValueNum ),
+ rec(18, 12, Reserved12 ),
+ rec(30, PROTO_LENGTH_UNKNOWN, SetCmdName ),
+ #
+ # XXX - optional string, if SetCmdType is 0
+ #
+ ], info_str=(SetCmdName, "RPC Set Command Value: %s", ", %s"))
+ pkt.Reply(12, [
+ rec(8, 4, RPCccode ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb07, 0xff00])
+ # 2222/8307, 131/07
+ pkt = NCP(0x8307, "RPC Execute NCF File", 'fileserver')
+ pkt.Request(NO_LENGTH_CHECK, [
+ rec(10, 20, Reserved20 ),
+ rec(30, PROTO_LENGTH_UNKNOWN, PathAndName ),
+ ], info_str=(PathAndName, "RPC Execute NCF File: %s", ", %s"))
+ pkt.Reply(12, [
+ rec(8, 4, RPCccode ),
+ ])
+ pkt.CompletionCodes([0x0000, 0x7e00, 0xfb07, 0xff00])
+if __name__ == '__main__':
+# import profile
+# filename = "ncp.pstats"
+# profile.run("main()", filename)
+#
+# import pstats
+# sys.stdout = msg
+# p = pstats.Stats(filename)
+#
+# print "Stats sorted by cumulative time"
+# p.strip_dirs().sort_stats('cumulative').print_stats()
+#
+# print "Function callees"
+# p.print_callees()
+ main()
diff --git a/epan/dissectors/packet-3g-a11.c b/epan/dissectors/packet-3g-a11.c
new file mode 100644
index 0000000000..b6730088ef
--- /dev/null
+++ b/epan/dissectors/packet-3g-a11.c
@@ -0,0 +1,1135 @@
+/*
+ * packet-3g-a11.c
+ * Routines for CDMA2000 A11 packet trace
+ * Copyright 2002, Ryuji Somegawa <somegawa@wide.ad.jp>
+ * packet-3g-a11.c was written based on 'packet-mip.c'.
+ *
+ * packet-mip.c
+ * Routines for Mobile IP dissection
+ * Copyright 2000, Stefan Raab <sraab@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <glib.h>
+#include <time.h>
+
+#include <epan/packet.h>
+
+/* Initialize the protocol and registered fields */
+static int proto_a11 = -1;
+static int hf_a11_type = -1;
+static int hf_a11_flags = -1;
+static int hf_a11_s = -1;
+static int hf_a11_b = -1;
+static int hf_a11_d = -1;
+static int hf_a11_m = -1;
+static int hf_a11_g = -1;
+static int hf_a11_v = -1;
+static int hf_a11_t = -1;
+static int hf_a11_code = -1;
+static int hf_a11_status = -1;
+static int hf_a11_life = -1;
+static int hf_a11_homeaddr = -1;
+static int hf_a11_haaddr = -1;
+static int hf_a11_coa = -1;
+static int hf_a11_ident = -1;
+static int hf_a11_ext_type = -1;
+static int hf_a11_ext_stype = -1;
+static int hf_a11_ext_len = -1;
+static int hf_a11_ext = -1;
+static int hf_a11_aext_spi = -1;
+static int hf_a11_aext_auth = -1;
+static int hf_a11_next_nai = -1;
+
+static int hf_a11_ses_key = -1;
+static int hf_a11_ses_mnsrid = -1;
+static int hf_a11_ses_sidver = -1;
+static int hf_a11_ses_msid_type = -1;
+static int hf_a11_ses_msid_len = -1;
+static int hf_a11_ses_msid = -1;
+static int hf_a11_ses_ptype = -1;
+
+static int hf_a11_vse_vid = -1;
+static int hf_a11_vse_apptype = -1;
+static int hf_a11_vse_canid = -1;
+static int hf_a11_vse_panid = -1;
+static int hf_a11_vse_srvopt = -1;
+static int hf_a11_vse_pdit = -1;
+static int hf_a11_vse_code = -1;
+static int hf_a11_vse_dormant = -1;
+static int hf_a11_vse_ppaddr = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_a11 = -1;
+static gint ett_a11_flags = -1;
+static gint ett_a11_ext = -1;
+static gint ett_a11_exts = -1;
+static gint ett_a11_radius = -1;
+static gint ett_a11_radiuses = -1;
+
+/* Port used for Mobile IP based Tunneling Protocol (A11) */
+#define UDP_PORT_3GA11 699
+#define NTP_BASETIME 2208988800ul
+#define THE3GPP2_VENDOR_ID 0x159f
+
+typedef enum {
+ REGISTRATION_REQUEST = 1,
+ REGISTRATION_REPLY = 3,
+ REGISTRATION_UPDATE = 20,
+ REGISTRATION_ACK =21,
+ SESSION_UPDATE = 22,
+ SESSION_ACK = 23
+} a11MessageTypes;
+
+static const value_string a11_types[] = {
+ {REGISTRATION_REQUEST, "Registration Request"},
+ {REGISTRATION_REPLY, "Registration Reply"},
+ {REGISTRATION_UPDATE, "Registration Update"},
+ {REGISTRATION_ACK, "Registration Ack"},
+ {SESSION_UPDATE, "Session Update"},
+ {SESSION_ACK, "Session Update Ack"},
+ {0, NULL},
+};
+
+static const value_string a11_reply_codes[]= {
+ {0, "Reg Accepted"},
+ {9, "Connection Update"},
+#if 0
+ {1, "Reg Accepted, but Simultaneous Bindings Unsupported."},
+ {64, "Reg Deny (FA)- Unspecified Reason"},
+ {65, "Reg Deny (FA)- Administratively Prohibited"},
+ {66, "Reg Deny (FA)- Insufficient Resources"},
+ {67, "Reg Deny (FA)- MN failed Authentication"},
+ {68, "Reg Deny (FA)- HA failed Authentication"},
+ {69, "Reg Deny (FA)- Requested Lifetime too Long"},
+ {70, "Reg Deny (FA)- Poorly Formed Request"},
+ {71, "Reg Deny (FA)- Poorly Formed Reply"},
+ {72, "Reg Deny (FA)- Requested Encapsulation Unavailable"},
+ {73, "Reg Deny (FA)- VJ Compression Unavailable"},
+ {74, "Reg Deny (FA)- Requested Reverse Tunnel Unavailable"},
+ {75, "Reg Deny (FA)- Reverse Tunnel is Mandatory and 'T' Bit Not Set"},
+ {76, "Reg Deny (FA)- Mobile Node Too Distant"},
+ {79, "Reg Deny (FA)- Delivery Style Not Supported"},
+ {80, "Reg Deny (FA)- Home Network Unreachable"},
+ {81, "Reg Deny (FA)- HA Host Unreachable"},
+ {82, "Reg Deny (FA)- HA Port Unreachable"},
+ {88, "Reg Deny (FA)- HA Unreachable"},
+ {96, "Reg Deny (FA)(NAI) - Non Zero Home Address Required"},
+ {97, "Reg Deny (FA)(NAI) - Missing NAI"},
+ {98, "Reg Deny (FA)(NAI) - Missing Home Agent"},
+ {99, "Reg Deny (FA)(NAI) - Missing Home Address"},
+#endif
+ {128, "Reg Deny (HA)- Unspecified"},
+ {129, "Reg Deny (HA)- Administratively Prohibited"},
+ {130, "Reg Deny (HA)- Insufficient Resources"},
+ {131, "Reg Deny (HA)- PCF Failed Authentication"},
+ /* {132, "Reg Deny (HA)- FA Failed Authentication"}, */
+ {133, "Reg Deny (HA)- Identification Mismatch"},
+ {134, "Reg Deny (HA)- Poorly Formed Request"},
+ /* {135, "Reg Deny (HA)- Too Many Simultaneous Bindings"}, */
+ {136, "Reg Deny (HA)- Unknown PDSN Address"},
+ {137, "Reg Deny (HA)- Requested Reverse Tunnel Unavailable"},
+ {138, "Reg Deny (HA)- Reverse Tunnel is Mandatory and 'T' Bit Not Set"},
+ {139, "Reg Deny (HA)- Requested Encapsulation Unavailable"},
+ {141, "Reg Deny (HA)- unsupported Vendor ID / Application Type in CVSE"},
+};
+
+
+static const value_string a11_ack_status[]= {
+ {0, "Update Accepted"},
+ {128, "Update Deny - Unspecified"},
+ {131, "Update Deny - Sending Node Failed Authentication"},
+ {133, "Update Deny - Registration ID Mismatch"},
+ {134, "Update Deny - Poorly Formed Request"},
+ {201, "Update Deny - Session Parameter Not Updated"},
+};
+
+typedef enum {
+ MH_AUTH_EXT = 32,
+ MF_AUTH_EXT = 33,
+ FH_AUTH_EXT = 34,
+ GEN_AUTH_EXT = 36, /* RFC 3012 */
+ OLD_CVSE_EXT = 37, /* RFC 3115 */
+ CVSE_EXT = 38, /* RFC 3115 */
+ SS_EXT = 39, /* 3GPP2 IOS4.2 */
+ RU_AUTH_EXT = 40, /* 3GPP2 IOS4.2 */
+ MN_NAI_EXT = 131,
+ MF_CHALLENGE_EXT = 132, /* RFC 3012 */
+ OLD_NVSE_EXT = 133, /* RFC 3115 */
+ NVSE_EXT = 134 /* RFC 3115 */
+} MIP_EXTS;
+
+
+static const value_string a11_ext_types[]= {
+ {MH_AUTH_EXT, "Mobile-Home Authentication Extension"},
+ {MF_AUTH_EXT, "Mobile-Foreign Authentication Extension"},
+ {FH_AUTH_EXT, "Foreign-Home Authentication Extension"},
+ {MN_NAI_EXT, "Mobile Node NAI Extension"},
+ {GEN_AUTH_EXT, "Generalized Mobile-IP Authentication Extension"},
+ {MF_CHALLENGE_EXT, "MN-FA Challenge Extension"},
+ {CVSE_EXT, "Critical Vendor/Organization Specific Extension"},
+ {SS_EXT, "Session Specific Extension"},
+ {RU_AUTH_EXT, "Registration Update Authentication Extension"},
+ {OLD_CVSE_EXT, "Critical Vendor/Organization Specific Extension (OLD)"},
+ {NVSE_EXT, "Normal Vendor/Organization Specific Extension"},
+ {OLD_NVSE_EXT, "Normal Vendor/Organization Specific Extension (OLD)"},
+ {0, NULL},
+};
+
+static const value_string a11_ext_stypes[]= {
+ {1, "MN AAA Extension"},
+ {0, NULL},
+};
+
+static const value_string a11_ext_nvose_srvopt[]= {
+ {0x0021, "3G High Speed Packet Data"},
+ {0x003C, "Link Layer Assisted Header Removal"},
+ {0x003D, "Link Layer Assisted Robust Header Compression"},
+ {0, NULL},
+};
+
+static const value_string a11_ext_nvose_pdsn_code[]= {
+ {0xc1, "Connection Release - reason unspecified"},
+ {0xc2, "Connection Release - PPP time-out"},
+ {0xc3, "Connection Release - registration time-out"},
+ {0xc4, "Connection Release - PDSN error"},
+ {0xc5, "Connection Release - inter-PCF handoff"},
+ {0xc6, "Connection Release - inter-PDSN handoff"},
+ {0xc7, "Connection Release - PDSN OAM&P intervention"},
+ {0xc8, "Connection Release - accounting error"},
+ {0xca, "Connection Release - user (NAI) failed authentication"},
+ {0x00, NULL},
+};
+
+static const value_string a11_ext_dormant[]= {
+ {0x0000, "all MS packet data service instances are dormant"},
+ {0, NULL},
+};
+
+static const value_string a11_ext_app[]= {
+ {0x0101, "Accounting (RADIUS)"},
+ {0x0102, "Accounting (DIAMETER)"},
+ {0x0201, "Mobility Event Indicator (Mobility)"},
+ {0x0301, "Data Available Indicator (Data Ready to Send)"},
+ {0x0401, "Access Network Identifiers (ANID)"},
+ {0x0501, "PDSN Identifiers (Anchor P-P Address)"},
+ {0x0601, "Indicators (All Dormant Indicator)"},
+ {0x0701, "PDSN Code (PDSN Code)"},
+ {0x0801, "Session Parameter (RN-PDIT:Radio Network Packet Data Inactivity Timer)"},
+ {0x0901, "Service Option (Service Option Value)"},
+ {0, NULL},
+};
+
+static const value_string a11_airlink_types[]= {
+ {1, "Session Setup (Y=1)"},
+ {2, "Active Start (Y=2)"},
+ {3, "Active Stop (Y=3)"},
+ {4, "Short Data Burst (Y=4)"},
+ {0, NULL},
+};
+
+#define ATTRIBUTE_NAME_LEN_MAX 128
+#define ATTR_TYPE_NULL 0
+#define ATTR_TYPE_INT 1
+#define ATTR_TYPE_STR 2
+#define ATTR_TYPE_IPV4 3
+#define ATTR_TYPE_TYPE 4
+#define ATTR_TYPE_MSID 5
+
+struct radius_attribute {
+ char attrname[ATTRIBUTE_NAME_LEN_MAX];
+ int type;
+ int subtype;
+ int bytes;
+ int data_type;
+};
+
+static const struct radius_attribute attrs[]={
+ {"Airlink Record", 26, 40, 4, ATTR_TYPE_TYPE},
+ {"R-P Session ID", 26, 41, 4, ATTR_TYPE_INT},
+ {"Airlink Sequence Number", 26, 42, 4, ATTR_TYPE_INT},
+#if 0
+ {"MSID", 31, -1, 15, ATTR_TYPE_MSID},
+#endif
+ {"Serving PCF", 26, 9, 4, ATTR_TYPE_IPV4},
+ {"BSID", 26, 10, 12, ATTR_TYPE_STR},
+ {"ESN", 26, 52, 15, ATTR_TYPE_STR},
+ {"User Zone", 26, 11, 4, ATTR_TYPE_INT},
+ {"Forward FCH Mux Option", 26, 12, 4, ATTR_TYPE_INT},
+ {"Reverse FCH Mux Option", 26, 13, 4, ATTR_TYPE_INT},
+ {"Forward Fundamental Rate (IOS 4.1)",26, 14, 4, ATTR_TYPE_INT},
+ {"Reverse Fundamental Rate (IOS 4.1)",26, 15, 4, ATTR_TYPE_INT},
+ {"Service Option", 26, 16, 4, ATTR_TYPE_INT},
+ {"Forward Traffic Type", 26, 17, 4, ATTR_TYPE_INT},
+ {"Reverse Traffic Type", 26, 18, 4, ATTR_TYPE_INT},
+ {"FCH Frame Size", 26, 19, 4, ATTR_TYPE_INT},
+ {"Forward FCH RC", 26, 20, 4, ATTR_TYPE_INT},
+ {"Reverse FCH RC", 26, 21, 4, ATTR_TYPE_INT},
+ {"DCCH Frame Size 0/5/20", 26, 50, 4, ATTR_TYPE_INT},
+ {"Forward DCCH Mux Option", 26, 84, 4, ATTR_TYPE_INT},
+ {"Reverse DCCH Mux Option", 26, 85, 4, ATTR_TYPE_INT},
+ {"Forward DCCH RC", 26, 86, 4, ATTR_TYPE_INT},
+ {"Reverse DCCH RC", 26, 87, 4, ATTR_TYPE_INT},
+ {"Airlink Priority", 26, 39, 4, ATTR_TYPE_INT},
+ {"Active Connection Time", 26, 49, 4, ATTR_TYPE_INT},
+ {"Mobile Orig/Term Ind.", 26, 45, 4, ATTR_TYPE_INT},
+ {"SDB Octet Count (Term.)", 26, 31, 4, ATTR_TYPE_INT},
+ {"SDB Octet Count (Orig.)", 26, 32, 4, ATTR_TYPE_INT},
+ {"Unknown", -1, -1, -1, ATTR_TYPE_NULL},
+};
+#define NUM_ATTR (sizeof(attrs)/sizeof(struct radius_attribute))
+
+#define MAX_STRVAL 16
+
+#define RADIUS_VENDOR_SPECIFIC 26
+#define SKIP_HDR_LEN 6
+
+static void dissect_a11_radius( tvbuff_t *, int, proto_tree *, int);
+
+/* RADIUS attributed */
+static void
+dissect_a11_radius( tvbuff_t *tvb, int offset, proto_tree *tree, int app_len)
+{
+ proto_item *ti;
+ proto_tree *radius_tree=NULL;
+ size_t radius_len;
+ guint8 radius_type;
+ guint8 radius_subtype;
+ int attribute_type;
+ guint attribute_len;
+ guint offset0;
+ guint radius_offset;
+ guint i;
+ guchar str_val[MAX_STRVAL];
+ guint radius_vendor_id = 0;
+
+ /* None of this really matters if we don't have a tree */
+ if (!tree) return;
+
+ offset0 = offset;
+
+ /* return if length of extension is not valid */
+ if (tvb_reported_length_remaining(tvb, offset) < 12) {
+ return;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset - 2, app_len, "Airlink Record");
+
+ radius_tree = proto_item_add_subtree(ti, ett_a11_radiuses);
+
+ /* And, handle each record */
+ while (tvb_reported_length_remaining(tvb, offset) > 0
+ && ((int)offset-(int)offset0) <app_len-2)
+ {
+
+ radius_type = tvb_get_guint8(tvb, offset);
+ radius_len = tvb_get_guint8(tvb, offset + 1);
+
+ if (radius_type == RADIUS_VENDOR_SPECIFIC)
+ {
+ radius_vendor_id = tvb_get_ntohl(tvb, offset +2);
+
+ if(radius_vendor_id != THE3GPP2_VENDOR_ID)
+ {
+ ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
+ "Unknown Vendor-specific Attribute (Vendor Id: %x)", radius_vendor_id);
+ offset += radius_len;
+ continue;
+ }
+ }
+ else
+ {
+
+ /**** ad-hoc ***/
+ if(radius_type == 31)
+ {
+ strncpy(str_val, tvb_get_ptr(tvb,offset+2,radius_len-2),
+ radius_len-2);
+ if(radius_len-2 < MAX_STRVAL) {
+ str_val[radius_len-2] = '\0';
+ }
+ else {
+ str_val[MAX_STRVAL-1] = '\0';
+ }
+ ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
+ "MSID: %s", str_val);
+ }
+ else if (radius_type == 46)
+ {
+ ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
+ "Acct Session Time: %d",tvb_get_ntohl(tvb,offset+2));
+ }
+ else
+ {
+ ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
+ "Unknown RADIUS Attributes (Type: %d)", radius_type);
+ }
+
+ offset += radius_len;
+ continue;
+ }
+
+ radius_len = tvb_get_guint8(tvb, offset + 1);
+
+ offset += SKIP_HDR_LEN;
+ radius_offset = 0;
+
+ /* Detect Airlink Record Type */
+
+ while (radius_len - 6 > radius_offset)
+ {
+
+ radius_subtype = tvb_get_guint8(tvb, offset + radius_offset);
+ attribute_len = tvb_get_guint8(tvb, offset + radius_offset + 1);
+
+ attribute_type = -1;
+ for(i = 0; i < NUM_ATTR; i++) {
+ if (attrs[i].subtype == radius_subtype) {
+ attribute_type = i;
+ break;
+ }
+ }
+
+ if(attribute_type >= 0) {
+ switch(attrs[attribute_type].data_type) {
+ case ATTR_TYPE_INT:
+ ti = proto_tree_add_text(radius_tree, tvb, offset + radius_offset,
+ attribute_len, "3GPP2: %s (%04x)", attrs[attribute_type].attrname,
+ tvb_get_ntohl(tvb,offset + radius_offset + 2));
+ break;
+ case ATTR_TYPE_IPV4:
+ ti = proto_tree_add_text(radius_tree, tvb, offset + radius_offset,
+ attribute_len, "3GPP2: %s (%s)", attrs[attribute_type].attrname,
+ ip_to_str(tvb_get_ptr(tvb,offset + radius_offset + 2,4)));
+ break;
+ case ATTR_TYPE_TYPE:
+ ti = proto_tree_add_text(radius_tree, tvb, offset + radius_offset,
+ attribute_len, "3GPP2: %s (%s)", attrs[attribute_type].attrname,
+ val_to_str(tvb_get_ntohl(tvb,offset+radius_offset+2),
+ a11_airlink_types,"Unknown"));
+ break;
+ case ATTR_TYPE_STR:
+ strncpy(str_val, tvb_get_ptr(tvb,offset+radius_offset+2,attribute_len - 2),
+ attribute_len - 2);
+ if(attribute_len - 2 < MAX_STRVAL) {
+ str_val[attribute_len - 2] = '\0';
+ }
+ else {
+ str_val[MAX_STRVAL-1] = '\0';
+ }
+ ti = proto_tree_add_text(radius_tree, tvb, offset+radius_offset,
+ attribute_len,
+ "3GPP2: %s (%s)", attrs[attribute_type].attrname, str_val);
+ break;
+ case ATTR_TYPE_NULL:
+ break;
+ default:
+ ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
+ "RADIUS: %s", attrs[attribute_type].attrname);
+ break;
+ }
+ }
+ else {
+ ti = proto_tree_add_text(radius_tree, tvb, offset, radius_len,
+ "RADIUS: Unknown 3GPP2 Attribute (Type:%d, SubType:%d)",
+ radius_type,radius_subtype);
+ }
+
+ radius_offset += attribute_len;
+ }
+ offset += radius_len - 6;
+
+ }
+
+}
+
+/* Code to dissect extensions */
+static void
+dissect_a11_extensions( tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *exts_tree=NULL;
+ proto_tree *ext_tree;
+ size_t ext_len;
+ guint8 ext_type;
+ guint8 ext_subtype=0;
+ size_t hdrLen;
+
+ gint16 apptype = -1;
+
+ /* None of this really matters if we don't have a tree */
+ if (!tree) return;
+
+ /* Add our tree, if we have extensions */
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "Extensions");
+ exts_tree = proto_item_add_subtree(ti, ett_a11_exts);
+
+ /* And, handle each extension */
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+
+ /* Get our extension info */
+ ext_type = tvb_get_guint8(tvb, offset);
+ if (ext_type == GEN_AUTH_EXT) {
+ /*
+ * Very nasty . . breaks normal extensions, since the length is
+ * in the wrong place :(
+ */
+ ext_subtype = tvb_get_guint8(tvb, offset + 1);
+ ext_len = tvb_get_ntohs(tvb, offset + 2);
+ hdrLen = 4;
+ } else if (ext_type == CVSE_EXT || ext_type == OLD_CVSE_EXT) {
+ ext_len = tvb_get_ntohs(tvb, offset + 2);
+ ext_subtype = tvb_get_guint8(tvb, offset + 8);
+ hdrLen = 4;
+ } else {
+ ext_len = tvb_get_guint8(tvb, offset + 1);
+ hdrLen = 2;
+ }
+
+ ti = proto_tree_add_text(exts_tree, tvb, offset, ext_len + hdrLen,
+ "Extension: %s",
+ val_to_str(ext_type, a11_ext_types,
+ "Unknown Extension %u"));
+ ext_tree = proto_item_add_subtree(ti, ett_a11_ext);
+
+ proto_tree_add_item(ext_tree, hf_a11_ext_type, tvb, offset, 1, ext_type);
+ offset++;
+
+ if (ext_type == SS_EXT) {
+ proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 1, ext_len);
+ offset++;
+ }
+ else if(ext_type == CVSE_EXT || ext_type == OLD_CVSE_EXT) {
+ offset++;
+ proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 2, ext_len);
+ offset+=2;
+ }
+ else if (ext_type != GEN_AUTH_EXT) {
+ /* Another nasty hack since GEN_AUTH_EXT broke everything */
+ proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 1, ext_len);
+ offset++;
+ }
+
+ switch(ext_type) {
+ case SS_EXT:
+ proto_tree_add_item(ext_tree, hf_a11_ses_ptype, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_ses_key, tvb, offset+2, 4, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_ses_sidver, tvb, offset+7, 1, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_ses_mnsrid, tvb, offset+8, 2, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_ses_msid_type, tvb, offset+10, 2, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_ses_msid_len, tvb, offset+12, 1, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_ses_msid, tvb, offset+13, ext_len-13, FALSE);
+ break;
+ case MH_AUTH_EXT:
+ case MF_AUTH_EXT:
+ case FH_AUTH_EXT:
+ /* All these extensions look the same. 4 byte SPI followed by a key */
+ proto_tree_add_item(ext_tree, hf_a11_aext_spi, tvb, offset, 4, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_aext_auth, tvb, offset+4, ext_len-4,
+ FALSE);
+ break;
+ case MN_NAI_EXT:
+ proto_tree_add_item(ext_tree, hf_a11_next_nai, tvb, offset,
+ ext_len, FALSE);
+ break;
+
+ case GEN_AUTH_EXT: /* RFC 3012 */
+ /*
+ * Very nasty . . breaks normal extensions, since the length is
+ * in the wrong place :(
+ */
+ proto_tree_add_uint(ext_tree, hf_a11_ext_stype, tvb, offset, 1, ext_subtype);
+ offset++;
+ proto_tree_add_uint(ext_tree, hf_a11_ext_len, tvb, offset, 2, ext_len);
+ offset+=2;
+ /* SPI */
+ proto_tree_add_item(ext_tree, hf_a11_aext_spi, tvb, offset, 4, FALSE);
+ /* Key */
+ proto_tree_add_item(ext_tree, hf_a11_aext_auth, tvb, offset + 4,
+ ext_len - 4, FALSE);
+
+ break;
+ case OLD_CVSE_EXT: /* RFC 3115 */
+ case CVSE_EXT: /* RFC 3115 */
+ proto_tree_add_item(ext_tree, hf_a11_vse_vid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_vse_apptype, tvb, offset+4, 2, FALSE);
+ apptype = tvb_get_ntohs(tvb, offset+4);
+ if(apptype == 0x0101) {
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ dissect_a11_radius(tvb, offset+6, ext_tree, ext_len + hdrLen - 8);
+ }
+ }
+ break;
+ case OLD_NVSE_EXT: /* RFC 3115 */
+ case NVSE_EXT: /* RFC 3115 */
+ proto_tree_add_item(ext_tree, hf_a11_vse_vid, tvb, offset+2, 4, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_vse_apptype, tvb, offset+6, 2, FALSE);
+
+ apptype = tvb_get_ntohs(tvb, offset+6);
+ switch(apptype) {
+ case 0x0401:
+ proto_tree_add_item(ext_tree, hf_a11_vse_panid, tvb, offset+8, 5, FALSE);
+ proto_tree_add_item(ext_tree, hf_a11_vse_canid, tvb, offset+13, 5, FALSE);
+ break;
+ case 0x0501:
+ proto_tree_add_item(ext_tree, hf_a11_vse_ppaddr, tvb, offset+8, 4, FALSE);
+ break;
+ case 0x0601:
+ proto_tree_add_item(ext_tree, hf_a11_vse_dormant, tvb, offset+8, 2, FALSE);
+ break;
+ case 0x0701:
+ proto_tree_add_item(ext_tree, hf_a11_vse_code, tvb, offset+8, 1, FALSE);
+ break;
+ case 0x0801:
+ proto_tree_add_item(ext_tree, hf_a11_vse_pdit, tvb, offset+8, 1, FALSE);
+ break;
+ case 0x0802:
+ proto_tree_add_text(ext_tree, tvb, offset+8, -1, "Session Parameter - Always On");
+ break;
+ case 0x0901:
+ proto_tree_add_item(ext_tree, hf_a11_vse_srvopt, tvb, offset+8, 2, FALSE);
+ break;
+ }
+
+ break;
+ case MF_CHALLENGE_EXT: /* RFC 3012 */
+ /* The default dissector is good here. The challenge is all hex anyway. */
+ default:
+ proto_tree_add_item(ext_tree, hf_a11_ext, tvb, offset, ext_len, FALSE);
+ break;
+ } /* ext type */
+
+ offset += ext_len;
+ } /* while data remaining */
+
+} /* dissect_a11_extensions */
+
+/* Code to actually dissect the packets */
+static int
+dissect_a11( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures we will need to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *a11_tree=NULL;
+ proto_item *tf;
+ proto_tree *flags_tree;
+ guint8 type;
+ guint8 flags;
+ nstime_t ident_time;
+ size_t offset=0;
+
+ if (!tvb_bytes_exist(tvb, offset, 1))
+ return 0; /* not enough data to check message type */
+
+ type = tvb_get_guint8(tvb, offset);
+ if (match_strval(type, a11_types) == NULL)
+ return 0; /* not a known message type */
+
+ /* Make entries in Protocol column and Info column on summary display */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "3GPP2 A11");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ switch (type) {
+ case REGISTRATION_REQUEST:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Request: PDSN=%s PCF=%s",
+ ip_to_str(tvb_get_ptr(tvb, 8, 4)),
+ ip_to_str(tvb_get_ptr(tvb,12,4)));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
+ a11_tree = proto_item_add_subtree(ti, ett_a11);
+
+ /* type */
+ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
+ offset++;
+
+ /* flags */
+ flags = tvb_get_guint8(tvb, offset);
+ tf = proto_tree_add_uint(a11_tree, hf_a11_flags, tvb,
+ offset, 1, flags);
+ flags_tree = proto_item_add_subtree(tf, ett_a11_flags);
+ proto_tree_add_boolean(flags_tree, hf_a11_s, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_a11_b, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_a11_d, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_a11_m, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_a11_g, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_a11_v, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_a11_t, tvb, offset, 1, flags);
+ offset++;
+
+ /* lifetime */
+ proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, FALSE);
+ offset +=2;
+
+ /* home address */
+ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* home agent address */
+ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Care of Address */
+ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Identifier */
+ ident_time.secs = tvb_get_ntohl(tvb,16)-(guint32) NTP_BASETIME;
+ ident_time.nsecs = tvb_get_ntohl(tvb,20)*1000;
+ proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
+ offset += 8;
+
+ } /* if tree */
+ break;
+ case REGISTRATION_REPLY:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Reply: PDSN=%s, Code=%u",
+ ip_to_str(tvb_get_ptr(tvb,8,4)), tvb_get_guint8(tvb,1));
+
+ if (tree) {
+ /* Add Subtree */
+ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
+ a11_tree = proto_item_add_subtree(ti, ett_a11);
+
+ /* Type */
+ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
+ offset++;
+
+ /* Reply Code */
+ proto_tree_add_item(a11_tree, hf_a11_code, tvb, offset, 1, FALSE);
+ offset++;
+
+ /* Registration Lifetime */
+ proto_tree_add_item(a11_tree, hf_a11_life, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* Home address */
+ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Home Agent Address */
+ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Identifier */
+ ident_time.secs = tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
+ ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
+ proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
+ offset += 8;
+ } /* if tree */
+
+ break;
+ case REGISTRATION_UPDATE:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO,"Reg Update: PDSN=%s",
+ ip_to_str(tvb_get_ptr(tvb,8,4)));
+ if (tree) {
+ /* Add Subtree */
+ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
+ a11_tree = proto_item_add_subtree(ti, ett_a11);
+
+ /* Type */
+ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
+ offset++;
+
+ /* Reserved */
+ offset+=3;
+
+ /* Home address */
+ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Home Agent Address */
+ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Identifier */
+ ident_time.secs = tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
+ ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
+ proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
+ offset += 8;
+
+ } /* if tree */
+ break;
+ case REGISTRATION_ACK:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Ack: PCF=%s Status=%u",
+ ip_to_str(tvb_get_ptr(tvb, 8, 4)),
+ tvb_get_guint8(tvb,3));
+ if (tree) {
+ /* Add Subtree */
+ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
+ a11_tree = proto_item_add_subtree(ti, ett_a11);
+
+ /* Type */
+ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
+ offset++;
+
+ /* Reserved */
+ offset+=2;
+
+ /* Ack Status */
+ proto_tree_add_item(a11_tree, hf_a11_status, tvb, offset, 1, FALSE);
+ offset++;
+
+ /* Home address */
+ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Care of Address */
+ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Identifier */
+ ident_time.secs = tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
+ ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
+ proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
+ offset += 8;
+
+ } /* if tree */
+ break;
+ case SESSION_UPDATE: /* IOS4.3 */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO,"Ses Update: PDSN=%s",
+ ip_to_str(tvb_get_ptr(tvb,8,4)));
+ if (tree) {
+ /* Add Subtree */
+ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
+ a11_tree = proto_item_add_subtree(ti, ett_a11);
+
+ /* Type */
+ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
+ offset++;
+
+ /* Reserved */
+ offset+=3;
+
+ /* Home address */
+ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Home Agent Address */
+ proto_tree_add_item(a11_tree, hf_a11_haaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Identifier */
+ ident_time.secs = tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
+ ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
+ proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
+ offset += 8;
+
+ } /* if tree */
+ break;
+ case SESSION_ACK: /* IOS4.3 */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Ses Upd Ack: PCF=%s, Status=%u",
+ ip_to_str(tvb_get_ptr(tvb, 8, 4)),
+ tvb_get_guint8(tvb,3));
+ if (tree) {
+ /* Add Subtree */
+ ti = proto_tree_add_item(tree, proto_a11, tvb, offset, -1, FALSE);
+ a11_tree = proto_item_add_subtree(ti, ett_a11);
+
+ /* Type */
+ proto_tree_add_uint(a11_tree, hf_a11_type, tvb, offset, 1, type);
+ offset++;
+
+ /* Reserved */
+ offset+=2;
+
+ /* Ack Status */
+ proto_tree_add_item(a11_tree, hf_a11_status, tvb, offset, 1, FALSE);
+ offset++;
+
+ /* Home address */
+ proto_tree_add_item(a11_tree, hf_a11_homeaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Care of Address */
+ proto_tree_add_item(a11_tree, hf_a11_coa, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Identifier */
+ ident_time.secs = tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
+ ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
+ proto_tree_add_time(a11_tree, hf_a11_ident, tvb, offset, 8, &ident_time);
+ offset += 8;
+
+ } /* if tree */
+ break;
+ } /* End switch */
+
+ if (tree) {
+ if (tvb_reported_length_remaining(tvb, offset) > 0)
+ dissect_a11_extensions(tvb, offset, a11_tree);
+ }
+ return tvb_length(tvb);
+} /* dissect_a11 */
+
+/* Register the protocol with Ethereal */
+void proto_register_a11(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_a11_type,
+ { "Message Type", "a11.type",
+ FT_UINT8, BASE_DEC, VALS(a11_types), 0,
+ "A11 Message type.", HFILL }
+ },
+ { &hf_a11_flags,
+ {"Flags", "a11.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_a11_s,
+ {"Simultaneous Bindings", "a11.s",
+
+ FT_BOOLEAN, 8, NULL, 128,
+ "Simultaneous Bindings Allowed", HFILL }
+ },
+ { &hf_a11_b,
+ {"Broadcast Datagrams", "a11.b",
+ FT_BOOLEAN, 8, NULL, 64,
+ "Broadcast Datagrams requested", HFILL }
+ },
+ { &hf_a11_d,
+ { "Co-lcated Care-of Address", "a11.d",
+ FT_BOOLEAN, 8, NULL, 32,
+ "MN using Co-located Care-of address", HFILL }
+ },
+ { &hf_a11_m,
+ {"Minimal Encapsulation", "a11.m",
+ FT_BOOLEAN, 8, NULL, 16,
+ "MN wants Minimal encapsulation", HFILL }
+ },
+ { &hf_a11_g,
+ {"GRE", "a11.g",
+ FT_BOOLEAN, 8, NULL, 8,
+ "MN wants GRE encapsulation", HFILL }
+ },
+ { &hf_a11_v,
+ { "Van Jacobson", "a11.v",
+ FT_BOOLEAN, 8, NULL, 4,
+ "Van Jacobson", HFILL }
+ },
+ { &hf_a11_t,
+ { "Reverse Tunneling", "a11.t",
+ FT_BOOLEAN, 8, NULL, 2,
+ "Reverse tunneling requested", HFILL }
+ },
+ { &hf_a11_code,
+ { "Reply Code", "a11.code",
+ FT_UINT8, BASE_DEC, VALS(a11_reply_codes), 0,
+ "A11 Registration Reply code.", HFILL }
+ },
+ { &hf_a11_status,
+ { "Reply Status", "a11.ackstat",
+ FT_UINT8, BASE_DEC, VALS(a11_ack_status), 0,
+ "A11 Registration Ack Status.", HFILL }
+ },
+ { &hf_a11_life,
+ { "Lifetime", "a11.life",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "A11 Registration Lifetime.", HFILL }
+ },
+ { &hf_a11_homeaddr,
+ { "Home Address", "a11.homeaddr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Mobile Node's home address.", HFILL }
+ },
+
+ { &hf_a11_haaddr,
+ { "Home Agent", "a11.haaddr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Home agent IP Address.", HFILL }
+ },
+ { &hf_a11_coa,
+ { "Care of Address", "a11.coa",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Care of Address.", HFILL }
+ },
+ { &hf_a11_ident,
+ { "Identification", "a11.ident",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0,
+ "MN Identification.", HFILL }
+ },
+ { &hf_a11_ext_type,
+ { "Extension Type", "a11.ext.type",
+ FT_UINT8, BASE_DEC, VALS(a11_ext_types), 0,
+ "Mobile IP Extension Type.", HFILL }
+ },
+ { &hf_a11_ext_stype,
+ { "Gen Auth Ext SubType", "a11.ext.auth.subtype",
+ FT_UINT8, BASE_DEC, VALS(a11_ext_stypes), 0,
+ "Mobile IP Auth Extension Sub Type.", HFILL }
+ },
+ { &hf_a11_ext_len,
+ { "Extension Length", "a11.ext.len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Mobile IP Extension Length.", HFILL }
+ },
+ { &hf_a11_ext,
+ { "Extension", "a11.extension",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Extension", HFILL }
+ },
+ { &hf_a11_aext_spi,
+ { "SPI", "a11.auth.spi",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Authentication Header Security Parameter Index.", HFILL }
+ },
+ { &hf_a11_aext_auth,
+ { "Authenticator", "a11.auth.auth",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "Authenticator.", HFILL }
+ },
+ { &hf_a11_next_nai,
+ { "NAI", "a11.nai",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "NAI", HFILL }
+ },
+ { &hf_a11_ses_key,
+ { "Key", "a11.ext.key",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Session Key.", HFILL }
+ },
+ { &hf_a11_ses_sidver,
+ { "Session ID Version", "a11.ext.sidver",
+ FT_UINT8, BASE_DEC, NULL, 3,
+ "Session ID Version", HFILL}
+ },
+ { &hf_a11_ses_mnsrid,
+ { "MNSR-ID", "a11.ext.mnsrid",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "MNSR-ID", HFILL }
+ },
+ { &hf_a11_ses_msid_type,
+ { "MSID Type", "a11.ext.msid_type",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "MSID Type.", HFILL }
+ },
+ { &hf_a11_ses_msid_len,
+ { "MSID Length", "a11.ext.msid_len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "MSID Length.", HFILL }
+ },
+ { &hf_a11_ses_msid,
+ { "MSID(BCD)", "a11.ext.msid",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "MSID(BCD).", HFILL }
+ },
+ { &hf_a11_ses_ptype,
+ { "Protocol Type", "a11.ext.ptype",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Protocol Type.", HFILL }
+ },
+ { &hf_a11_vse_vid,
+ { "Vendor ID", "a11.ext.vid",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Vendor ID.", HFILL }
+ },
+ { &hf_a11_vse_apptype,
+ { "Application Type", "a11.ext.apptype",
+ FT_UINT8, BASE_HEX, VALS(a11_ext_app), 0,
+ "Application Type.", HFILL }
+ },
+ { &hf_a11_vse_ppaddr,
+ { "Anchor P-P Address", "a11.ext.ppaddr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Anchor P-P Address.", HFILL }
+ },
+ { &hf_a11_vse_dormant,
+ { "All Dormant Indicator", "a11.ext.dormant",
+ FT_UINT16, BASE_HEX, VALS(a11_ext_dormant), 0,
+ "All Dormant Indicator.", HFILL }
+ },
+ { &hf_a11_vse_code,
+ { "Reply Code", "a11.ext.code",
+ FT_UINT8, BASE_DEC, VALS(a11_reply_codes), 0,
+ "PDSN Code.", HFILL }
+ },
+ { &hf_a11_vse_pdit,
+ { "PDSN Code", "a11.ext.code",
+ FT_UINT8, BASE_HEX, VALS(a11_ext_nvose_pdsn_code), 0,
+ "PDSN Code.", HFILL }
+ },
+ { &hf_a11_vse_srvopt,
+ { "Service Option", "a11.ext.srvopt",
+ FT_UINT16, BASE_HEX, VALS(a11_ext_nvose_srvopt), 0,
+ "Service Option.", HFILL }
+ },
+ { &hf_a11_vse_panid,
+ { "PANID", "a11.ext.panid",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "PANID", HFILL }
+ },
+ { &hf_a11_vse_canid,
+ { "CANID", "a11.ext.canid",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "CANID", HFILL }
+ },
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_a11,
+ &ett_a11_flags,
+ &ett_a11_ext,
+ &ett_a11_exts,
+ &ett_a11_radius,
+ &ett_a11_radiuses,
+ };
+
+ /* Register the protocol name and description */
+ proto_a11 = proto_register_protocol("3GPP2 A11", "3GPP2 A11", "a11");
+
+ /* Register the dissector by name */
+ new_register_dissector("a11", dissect_a11, proto_a11);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_a11, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_a11(void)
+{
+ dissector_handle_t a11_handle;
+
+ a11_handle = find_dissector("a11");
+ dissector_add("udp.port", UDP_PORT_3GA11, a11_handle);
+}
+
diff --git a/epan/dissectors/packet-aarp.c b/epan/dissectors/packet-aarp.c
new file mode 100644
index 0000000000..9c68873009
--- /dev/null
+++ b/epan/dissectors/packet-aarp.c
@@ -0,0 +1,362 @@
+/* packet-aarp.c
+ * Routines for Appletalk ARP packet disassembly
+ *
+ * $Id$
+ *
+ * Simon Wilkinson <sxw@dcs.ed.ac.uk>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "etypes.h"
+
+static int proto_aarp = -1;
+static int hf_aarp_hard_type = -1;
+static int hf_aarp_proto_type = -1;
+static int hf_aarp_hard_size = -1;
+static int hf_aarp_proto_size = -1;
+static int hf_aarp_opcode = -1;
+static int hf_aarp_src_hw = -1;
+static int hf_aarp_src_hw_mac = -1;
+static int hf_aarp_src_proto = -1;
+static int hf_aarp_src_proto_id = -1;
+static int hf_aarp_dst_hw = -1;
+static int hf_aarp_dst_hw_mac = -1;
+static int hf_aarp_dst_proto = -1;
+static int hf_aarp_dst_proto_id = -1;
+
+static gint ett_aarp = -1;
+
+#ifndef AARP_REQUEST
+#define AARP_REQUEST 0x0001
+#endif
+#ifndef AARP_REPLY
+#define AARP_REPLY 0x0002
+#endif
+#ifndef AARP_PROBE
+#define AARP_PROBE 0x0003
+#endif
+
+/* The following is screwed up shit to deal with the fact that
+ the linux kernel edits the packet inline. */
+#define AARP_REQUEST_SWAPPED 0x0100
+#define AARP_REPLY_SWAPPED 0x0200
+#define AARP_PROBE_SWAPPED 0x0300
+
+static const value_string op_vals[] = {
+ {AARP_REQUEST, "request" },
+ {AARP_REPLY, "reply" },
+ {AARP_PROBE, "probe" },
+ {AARP_REQUEST_SWAPPED, "request" },
+ {AARP_REPLY_SWAPPED, "reply" },
+ {AARP_PROBE_SWAPPED, "probe" },
+ {0, NULL } };
+
+/* AARP protocol HARDWARE identifiers. */
+#define AARPHRD_ETHER 1 /* Ethernet 10Mbps */
+#define AARPHRD_TR 2 /* Token Ring */
+
+static const value_string hrd_vals[] = {
+ {AARPHRD_ETHER, "Ethernet" },
+ {AARPHRD_TR, "Token Ring" },
+ {0, NULL } };
+
+/*
+ * Given the hardware address type and length, check whether an address
+ * is an Ethernet address - the address must be of type "Ethernet" or
+ * "Token Ring", and the length must be 6 bytes.
+ */
+#define AARP_HW_IS_ETHER(ar_hrd, ar_hln) \
+ (((ar_hrd) == AARPHRD_ETHER || (ar_hrd) == AARPHRD_TR) \
+ && (ar_hln) == 6)
+
+/*
+ * Given the protocol address type and length, check whether an address
+ * is an Appletalk address - the address must be of type "Appletalk",
+ * and the length must be 4 bytes.
+ */
+#define AARP_PRO_IS_ATALK(ar_pro, ar_pln) \
+ ((ar_pro) == ETHERTYPE_ATALK && (ar_pln) == 4)
+
+static gchar *
+atalkid_to_str(const guint8 *ad) {
+ gint node;
+ static gchar str[3][16];
+ static gchar *cur;
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+ node=ad[1]<<8|ad[2];
+ sprintf(cur, "%d.%d",node,ad[3]);
+ return cur;
+}
+
+static gchar *
+aarphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type) {
+ if (AARP_HW_IS_ETHER(type, ad_len)) {
+ /* Ethernet address (or Token Ring address, which is the same type
+ of address). */
+ return ether_to_str(ad);
+ }
+ return bytes_to_str(ad, ad_len);
+}
+
+static gchar *
+aarpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type) {
+ if (AARP_PRO_IS_ATALK(type, ad_len)) {
+ /* Appletalk address. */
+ return atalkid_to_str(ad);
+ }
+ return bytes_to_str(ad, ad_len);
+}
+
+/* Offsets of fields within an AARP packet. */
+#define AR_HRD 0
+#define AR_PRO 2
+#define AR_HLN 4
+#define AR_PLN 5
+#define AR_OP 6
+#define MIN_AARP_HEADER_SIZE 8
+
+static void
+dissect_aarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ guint16 ar_hrd;
+ guint16 ar_pro;
+ guint8 ar_hln;
+ guint8 ar_pln;
+ guint16 ar_op;
+ proto_tree *aarp_tree;
+ proto_item *ti;
+ gchar *op_str;
+ int sha_offset, spa_offset, tha_offset, tpa_offset;
+ const guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
+ gchar *sha_str, *spa_str, *tha_str, *tpa_str;
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AARP");
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
+ ar_pro = tvb_get_ntohs(tvb, AR_PRO);
+ ar_hln = tvb_get_guint8(tvb, AR_HLN);
+ ar_pln = tvb_get_guint8(tvb, AR_PLN);
+ ar_op = tvb_get_ntohs(tvb, AR_OP);
+
+ /* Get the offsets of the addresses. */
+ sha_offset = MIN_AARP_HEADER_SIZE;
+ spa_offset = sha_offset + ar_hln;
+ tha_offset = spa_offset + ar_pln;
+ tpa_offset = tha_offset + ar_hln;
+
+ /* Extract the addresses. */
+ sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
+ sha_str = aarphrdaddr_to_str(sha_val, ar_hln, ar_hrd);
+
+ spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
+ spa_str = aarpproaddr_to_str(spa_val, ar_pln, ar_pro);
+
+ tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
+ tha_str = aarphrdaddr_to_str(tha_val, ar_hln, ar_hrd);
+
+ tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
+ tpa_str = aarpproaddr_to_str(tpa_val, ar_pln, ar_pro);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ switch (ar_op) {
+ case AARP_REQUEST:
+ case AARP_REQUEST_SWAPPED:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s", tpa_str, spa_str);
+ break;
+ case AARP_REPLY:
+ case AARP_REPLY_SWAPPED:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", spa_str, sha_str);
+ break;
+ case AARP_PROBE:
+ case AARP_PROBE_SWAPPED:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Is there a %s", tpa_str);
+ break;
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown AARP opcode 0x%04x", ar_op);
+ break;
+ }
+ }
+
+ if (tree) {
+ if ((op_str = match_strval(ar_op, op_vals)))
+ ti = proto_tree_add_protocol_format(tree, proto_aarp, tvb, 0,
+ MIN_AARP_HEADER_SIZE + 2*ar_hln +
+ 2*ar_pln, "AppleTalk Address Resolution Protocol (%s)", op_str);
+ else
+ ti = proto_tree_add_protocol_format(tree, proto_aarp, tvb, 0,
+ MIN_AARP_HEADER_SIZE + 2*ar_hln +
+ 2*ar_pln,
+ "AppleTalk Address Resolution Protocol (opcode 0x%04x)", ar_op);
+ aarp_tree = proto_item_add_subtree(ti, ett_aarp);
+ proto_tree_add_uint(aarp_tree, hf_aarp_hard_type, tvb, AR_HRD, 2,
+ ar_hrd);
+ proto_tree_add_uint(aarp_tree, hf_aarp_proto_type, tvb, AR_PRO, 2,
+ ar_pro);
+ proto_tree_add_uint(aarp_tree, hf_aarp_hard_size, tvb, AR_HLN, 1,
+ ar_hln);
+ proto_tree_add_uint(aarp_tree, hf_aarp_proto_size, tvb, AR_PLN, 1,
+ ar_pln);
+ proto_tree_add_uint(aarp_tree, hf_aarp_opcode, tvb, AR_OP, 2,
+ ar_op);
+ if (ar_hln != 0) {
+ proto_tree_add_item(aarp_tree,
+ AARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_aarp_src_hw_mac : hf_aarp_src_hw,
+ tvb, sha_offset, ar_hln, FALSE);
+ }
+
+ if (ar_pln != 0) {
+ if (AARP_PRO_IS_ATALK(ar_pro, ar_pln)) {
+ proto_tree_add_bytes_format(aarp_tree, hf_aarp_src_proto_id, tvb, spa_offset, ar_pln,
+ spa_val,
+ "Sender ID: %s", spa_str);
+ } else {
+ proto_tree_add_bytes_format(aarp_tree, hf_aarp_src_proto, tvb, spa_offset, ar_pln,
+ spa_val,
+ "Sender protocol address: %s", spa_str);
+ }
+ }
+
+ if (ar_hln != 0) {
+ proto_tree_add_item(aarp_tree,
+ AARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_aarp_dst_hw_mac : hf_aarp_dst_hw,
+ tvb, tha_offset, ar_hln, FALSE);
+ }
+
+ if (ar_pln != 0) {
+ if (AARP_PRO_IS_ATALK(ar_pro, ar_pln)) {
+ proto_tree_add_bytes_format(aarp_tree, hf_aarp_dst_proto_id, tvb, tpa_offset, ar_pln,
+ tpa_val,
+ "Target ID: %s", tpa_str);
+ } else {
+ proto_tree_add_bytes_format(aarp_tree, hf_aarp_dst_proto, tvb, tpa_offset, ar_pln,
+ tpa_val,
+ "Target protocol address: %s", tpa_str);
+ }
+ }
+ }
+}
+
+void
+proto_register_aarp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_aarp_hard_type,
+ { "Hardware type", "aarp.hard.type",
+ FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_proto_type,
+ { "Protocol type", "aarp.proto.type",
+ FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_hard_size,
+ { "Hardware size", "aarp.hard.size",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_proto_size,
+ { "Protocol size", "aarp.proto.size",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_opcode,
+ { "Opcode", "aarp.opcode",
+ FT_UINT16, BASE_DEC, VALS(op_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_src_hw,
+ { "Sender hardware address", "aarp.src.hw",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_src_hw_mac,
+ { "Sender MAC address", "aarp.src.hw_mac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_src_proto,
+ { "Sender protocol address", "aarp.src.proto",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_src_proto_id,
+ { "Sender ID", "aarp.src.proto_id",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_dst_hw,
+ { "Target hardware address", "aarp.dst.hw",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_dst_hw_mac,
+ { "Target MAC address", "aarp.dst.hw_mac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_dst_proto,
+ { "Target protocol address", "aarp.dst.proto",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_aarp_dst_proto_id,
+ { "Target ID", "aarp.dst.proto_id",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_aarp,
+ };
+
+ proto_aarp = proto_register_protocol("Appletalk Address Resolution Protocol",
+ "AARP",
+ "aarp");
+ proto_register_field_array(proto_aarp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aarp(void)
+{
+ dissector_handle_t aarp_handle;
+
+ aarp_handle = create_dissector_handle(dissect_aarp, proto_aarp);
+ dissector_add("ethertype", ETHERTYPE_AARP, aarp_handle);
+ dissector_add("chdlctype", ETHERTYPE_AARP, aarp_handle);
+}
diff --git a/epan/dissectors/packet-acap.c b/epan/dissectors/packet-acap.c
new file mode 100644
index 0000000000..aee315dd2c
--- /dev/null
+++ b/epan/dissectors/packet-acap.c
@@ -0,0 +1,193 @@
+/* packet-acap.c
+ * Routines for ACAP packet dissection
+ * Copyright 2003, Brad Hards <bradh@frogmouth.net>
+ * Heavily based in packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-imap.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+static int proto_acap = -1;
+static int hf_acap_response = -1;
+static int hf_acap_request = -1;
+
+static gint ett_acap = -1;
+static gint ett_acap_reqresp = -1;
+
+#define TCP_PORT_ACAP 674
+
+static void
+dissect_acap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gboolean is_request;
+ proto_tree *acap_tree, *reqresp_tree;
+ proto_item *ti;
+ gint offset = 0;
+ const guchar *line;
+ gint next_offset;
+ int linelen;
+ int tokenlen;
+ const guchar *next_token;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACAP");
+
+ /*
+ * Find the end of the first line.
+ *
+ * Note that "tvb_find_line_end()" will return a value that is
+ * not longer than what's in the buffer, so the "tvb_get_ptr()"
+ * call won't throw an exception.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ line = tvb_get_ptr(tvb, offset, linelen);
+
+ if (pinfo->match_port == pinfo->destport)
+ is_request = TRUE;
+ else
+ is_request = FALSE;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary
+ * (but leave out the line terminator).
+ */
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
+ is_request ? "Request" : "Response",
+ format_text(line, linelen));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_acap, tvb, offset, -1,
+ FALSE);
+ acap_tree = proto_item_add_subtree(ti, ett_acap);
+
+ if (is_request) {
+ proto_tree_add_boolean_hidden(acap_tree,
+ hf_acap_request, tvb, 0, 0, TRUE);
+ } else {
+ proto_tree_add_boolean_hidden(acap_tree,
+ hf_acap_response, tvb, 0, 0, TRUE);
+ }
+
+ /*
+ * Put the line into the protocol tree.
+ */
+ ti = proto_tree_add_text(acap_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ reqresp_tree = proto_item_add_subtree(ti, ett_acap_reqresp);
+
+ /*
+ * Show the first line as tags + requests or replies.
+ */
+
+ /*
+ * Extract the first token, and, if there is a first
+ * token, add it as the request or reply tag.
+ */
+ tokenlen = get_token_len(line, line + linelen, &next_token);
+ if (tokenlen != 0) {
+ if (is_request) {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ tokenlen, "Request Tag: %s",
+ format_text(line, tokenlen));
+ } else {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ tokenlen, "Response Tag: %s",
+ format_text(line, tokenlen));
+ }
+ offset += next_token - line;
+ linelen -= next_token - line;
+ line = next_token;
+ }
+
+ /*
+ * Add the rest of the line as request or reply data.
+ */
+ if (linelen != 0) {
+ if (is_request) {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ linelen, "Request: %s",
+ format_text(line, linelen));
+ } else {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ linelen, "Response: %s",
+ format_text(line, linelen));
+ }
+ }
+
+ /*
+ * XXX - show the rest of the frame; this requires that
+ * we handle literals, quoted strings, continuation
+ * responses, etc..
+ *
+ * This involves a state machine, and attaching
+ * state information to the packets.
+ */
+ }
+}
+
+void
+proto_register_acap(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_acap_response,
+ { "Response", "acap.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if ACAP response", HFILL }},
+
+ { &hf_acap_request,
+ { "Request", "acap.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if ACAP request", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_acap,
+ &ett_acap_reqresp,
+ };
+
+ proto_acap = proto_register_protocol("Application Configuration Access Protocol",
+ "ACAP", "acap");
+ proto_register_field_array(proto_acap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_acap(void)
+{
+ dissector_handle_t acap_handle;
+
+ acap_handle = create_dissector_handle(dissect_acap, proto_acap);
+ dissector_add("tcp.port", TCP_PORT_ACAP, acap_handle);
+}
diff --git a/epan/dissectors/packet-acse.c b/epan/dissectors/packet-acse.c
new file mode 100644
index 0000000000..f7a4ed7e2e
--- /dev/null
+++ b/epan/dissectors/packet-acse.c
@@ -0,0 +1,1767 @@
+/* packet-acse.c
+*
+* Routine to dissect OSI ACSE Protocol packets
+*
+* $Id$
+*
+* Yuriy Sidelnikov <YSidelnikov@hotmail.com>
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-acse.h"
+#include "packet-frame.h"
+#include "prefs.h"
+
+#include <epan/strutil.h>
+
+#include "asn1.h"
+#include "format-oid.h"
+
+#include "packet-ses.h"
+extern const value_string ses_vals[];
+
+/* acse header fields */
+static int proto_acse = -1;
+/* type of session envelop */
+static struct SESSION_DATA_STRUCTURE* session = NULL;
+/* acse fields defining a sub tree */
+static gint ett_acse = -1;
+static gint ett_acse_param = -1;
+static gint ett_acse_rc = -1;
+static gint ett_acse_ms = -1;
+static gint ett_acse_itm = -1;
+
+/*
+----------------------------------------------------------------------------------------------------------*/
+/* Subdissector tables */
+static dissector_table_t application_dissector_table;
+static dissector_handle_t app_handle = NULL;
+static int hf_acse_type = -1;
+static int hf_cp_type_message_length = -1;
+static int hf_protocol_version = -1;
+
+
+
+static const value_string acse_vals[] =
+{
+ {ACSE_AARQ, "A-associate request" },
+ {ACSE_AARE, "A-associate response" },
+ {ACSE_RLRQ, "A-reliase request" },
+ {ACSE_RLRE, "A-reliase response" },
+ {ACSE_ABRT, "A-abort" },
+ {0, NULL }
+};
+
+static const value_string cr_vals[] =
+{
+ {MODE_SELECTOR, "Mode Selector"},
+ {SEQUENCE_TOP, "Sequence"},
+ {SET_TOP, "Set"},
+ {0, NULL}
+};
+
+static const value_string request_sequence_top_vals[] =
+{
+ {PROTOCOL_VERSION, "Protocol version"},
+ {APPLICATION_CONTEXT_NAME, "Application context name"},
+ {CALLED_AP_TITLE, "Called AP title"},
+ {CALLED_AE_QUALIFIER, "Called AE qualifier"},
+ {CALLED_AP_INVOKATION_ID, "Called AP invokation id"},
+ {CALLED_AE_INVOKATION_ID, "Called AE invokation id"},
+ {CALLING_AP_TITLE, "Calling AP title"},
+ {CALLING_AE_QUALIFIER, "Calling AE qualifier"},
+ {CALLING_AP_INVOKATION_ID, "Calling AP invokation id"},
+ {CALLING_AE_INVOKATION_ID, "Calling AE invokation id"},
+ {IMPLEMENTATION_INFORMATION,"Implementation information"},
+ {USER_INFORMATION,"User information"},
+ {0, NULL}
+};
+static const value_string response_sequence_top_vals[] =
+{
+ {PROTOCOL_VERSION, "Protocol version"},
+ {APPLICATION_CONTEXT_NAME, "Application context name"},
+ {ACSE_RESULT, "Result"},
+ {ACSE_RESULT_SOURCE_DIAGNOSTIC, "Result source diagnostic"},
+ {RESPONDING_AP_TITLE, "Responding AP title"},
+ {RESPONDING_AE_QUALIFIER, "Responding AE qualifier"},
+ {RESPONDING_AP_INVOKATION_ID, "Responding AP invokation id"},
+ {RESPONDING_AE_INVOKATION_ID, "Responding AE invokation id"},
+ {IMPLEMENTATION_INFORMATION,"Implementation information"},
+ {USER_INFORMATION,"User information"},
+ {0, NULL}
+};
+static const value_string associate_result_values_vals[] =
+{
+ {PRESENTATION_RESULT_ACCEPTANCE,"Accepted"},
+ {PRESENTATION_RESULT_USER_REJECTION,"Rejected permanent"},
+ {PRESENTATION_RESULT_PROVIDER_REJECTION,"Rejected transient"},
+ {0, NULL}
+};
+
+static const value_string acse_associate_source_diagnostic_vals[] =
+{
+ {ACSE_SERVICE_USER,"Acse service user"},
+ {ACSE_SERVICE_PROVIDER,"Acse service provider"},
+ {0, NULL}
+};
+static const value_string acse_service_user_values_vals[] =
+{
+ {ACSE_NULL,"null"},
+ {ACSE_NO_REASON_GIVEN,"No reason given"},
+ {ACSE_APPLICATION_CONTEXT_NAME_NOT_SUPPORTED,"Application context name not supported"},
+ {ACSE_CALLING_AP_TITLE_NOT_RECOGNIZED,"Calling AP title not recognized"},
+ {ACSE_CALLING_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Calling AP invokation identifier not recognized"},
+ {ACSE_CALLING_AE_QUALIFIER_NOT_RECOGNIZED,"Calling AE qualifier not recognized"},
+ {ACSE_CALLING_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Calling AE invokation identifier not recognized"},
+ {ACSE_CALLED_AP_TITLE_NOT_RECOGNIZED,"Called AP title not recognized"},
+ {ACSE_CALLED_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Called AP invokation identifier not recognized"},
+ {ACSE_CALLED_AE_QUALIFIER_NOT_RECOGNIZED,"Called AE qualifier not recognized"},
+ {ACSE_CALLED_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,"Called AE invokation identifier not recognized"},
+ {0, NULL}
+};
+static const value_string acse_service_provider_values_vals[] =
+{
+ {ACSE_NULL,"Null"},
+ {ACSE_NO_REASON_GIVEN,"No reason given"},
+ {ACSE_NO_COMMON_ACSE_VERSION,"no_common_acse_version"},
+ {0, NULL}
+};
+
+static const value_string acse_user_information_vals[] =
+{
+ {ACSE_EXTERNAL_USER,"External"},
+ {0, NULL}
+};
+static const value_string sequence_list_vals[] =
+{
+ {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
+ {ABSTRACT_SYNTAX_NAME,"Abstract syntax name"},
+ {TRANSFER_SYNTAX_NAMES,"Transfer syntax names"},
+ {0, NULL}
+};
+static const value_string presentation_context_definition_vals[] =
+{
+ {SEQUENCE, "Sequence"},
+ {0, NULL}
+};
+static const value_string user_data_values_vals[] =
+{
+ {SIMPLY_ENCODED_DATA,"Simply encoded data"},
+ {FULLY_ENCODED_DATA,"Fully encoded data "},
+ {0, NULL}
+};
+static const value_string presentation_data_values[] =
+{
+ {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
+ {SINGLE_ASN1_TYPE,"Single ASN.1 type"},
+ {OCTET_ALIGNED,"Octet aligned"},
+ {ARBITRARY,"Arbitrary"},
+ {ABSTRACT_SYNTAX_NAME,"Abstract syntax name"},
+ {0, NULL}
+};
+static const value_string release_request_reason[] =
+{
+ {RRR_NORMAL,"Normal"},
+ {RRR_URGENT,"Urgent"},
+ {RRR_USER_DEFINED,"User defined"},
+ {0, NULL}
+};
+static const value_string release_response_reason[] =
+{
+ {RRPR_NORMAL,"Normal"},
+ {RRPR_URGENT,"Not finished"},
+ {RRPR_USER_DEFINED,"User defined"},
+ {0, NULL}
+};
+
+static const value_string abort_reason[] =
+{
+ {ABRT_ACSE_SERVICE_USER,"Acse service user"},
+ {ABRT_ACSE_SERVICE_PROVIDER,"Acse service provider"},
+ {0, NULL}
+};
+
+static const value_string type_app[] =
+{
+ {0,""}, /* for unknown dissector */
+ {FTAM_APP,"FTAM"},
+ {CMIP_APP,"CMIP"},
+ {0, NULL}
+};
+
+/* pointers for acse dissector */
+static proto_tree *global_tree = NULL;
+static packet_info *global_pinfo = NULL;
+/* dissector for data */
+static dissector_handle_t data_handle;
+static void
+call_app_dissector(tvbuff_t *tvb, gint offset, gint param_len,
+ packet_info *pinfo, proto_tree *tree, proto_tree *param_tree)
+{
+ /* do we have OSI app packet dissector ? */
+ if(!app_handle )
+ {
+
+ /* No - display as data */
+ if (tree)
+ {
+ proto_tree_add_text(param_tree, tvb, offset, param_len,
+ "dissector is not available");
+ }
+ }
+ else
+ {
+ /* Yes - call application dissector */
+ tvbuff_t *next_tvb;
+
+ next_tvb = tvb_new_subset(tvb, offset, param_len,
+ param_len);
+ TRY
+ {
+ call_dissector(app_handle, next_tvb, pinfo,
+ tree);
+ }
+ CATCH_ALL
+ {
+ show_exception(tvb, pinfo, tree, EXCEPT_CODE);
+ }
+ ENDTRY;
+ }
+}
+static char*
+string_to_hex(const unsigned char * in,char * out,int len)
+{
+ char ascii[MAXSTRING];
+ int i;
+ memset(&ascii,0x00,sizeof(ascii));
+for(i=0;i<len;i++)
+ {
+ unsigned char o_out = *(in+i);
+ sprintf(out+(i<<1),"%.2x",* (in+i));
+ if( ( (o_out) >= 'a') & ( (o_out) <='z') ||
+ ( (o_out) >= 'A') & ( (o_out) <='Z') ||
+ ( (o_out) >= '0') & ( (o_out) <='9')
+ )
+ {
+ ascii[i] = o_out;
+ }
+ else
+ {
+ ascii[i] = '.';
+ }
+
+ }
+ strcat(out," ");
+ strcat(out,ascii);
+ return out;
+}
+
+static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
+{
+ guint length = 0;
+ gboolean def = FALSE;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_length_decode(a, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse length: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (len)
+ *len = length;
+
+ if (tree && hf_id)
+ proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start,
+length);
+
+ return ASN1_ERR_NOERROR;
+}
+static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i, int start, guint length)
+{
+ guint integer = 0;
+ proto_item *temp_item = NULL;
+ int ret;
+
+ ret = asn1_uint32_value_decode(a, length, &integer);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse value: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (i)
+ *i = integer;
+
+ if (tree && hf_id)
+ temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start,
+a->offset-start, integer);
+
+ if (new_item)
+ *new_item = temp_item;
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint length;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
+ asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ return read_integer_value(a, tree, hf_id, new_item, i, start, length);
+}
+/* display asn.1 Integer type */
+static void
+show_integer(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,guint item_len)
+{
+ proto_tree *acse_tree_itm = NULL;
+ proto_item *itm;
+ int ret;
+ int save_len = item_len;
+ int off = *offset;
+ itm = proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Integer");
+ acse_tree_itm = proto_item_add_subtree(itm, ett_acse_itm);
+ ret = read_integer(asn,acse_tree_itm,0,NULL,&item_len);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ itm = proto_tree_add_text(acse_tree_itm, tvb, (*offset)-item_len,
+ item_len,
+ "Integer value: %u",item_len);
+ }
+ else
+ {
+ /* can't dissect item. Skip it. */
+ *offset = off+ save_len;
+ }
+
+}
+static void
+show_protocol_version(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *acse_tree_itm = NULL;
+ proto_item *itm;
+ guint16 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+
+ itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ acse_tree_itm = proto_item_add_subtree(itm, ett_acse_itm);
+ *offset = asn->offset;
+ flags = tvb_get_ntohs(tvb, *offset);
+ proto_tree_add_boolean(acse_tree_itm,hf_protocol_version, tvb, *offset,
+ 2, flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+print_oid_value(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ guint ret;
+ subid_t *oid;
+ guint len;
+ gchar *display_string;
+ guint length;
+ guint start=*offset;
+
+ ret = asn1_oid_value_decode (asn, item_len, &oid, &len);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ return ;
+ }
+ length = asn->offset - start;
+ display_string = format_oid(oid, len);
+ proto_tree_add_text(acse_tree, tvb, *offset,length,"Value:%s",
+ display_string);
+ g_free(display_string);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+static void
+print_oid(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int *offset,int
+item_len,gchar* d_s)
+{
+ guint ret;
+ subid_t *oid;
+ guint len;
+ guint nbytes;
+ gchar *display_string;
+ guint length;
+ guint start=*offset;
+
+ ret = asn1_oid_decode ( asn, &oid, &len, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ return ;
+ }
+ length = asn->offset - start;
+ display_string = format_oid(oid, len);
+ proto_tree_add_text(acse_tree, tvb, *offset,length,"Value:%s",
+ display_string);
+ if(d_s)
+ {
+ /* copy OID */
+ strcpy(d_s,display_string);
+ }
+ g_free(display_string);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+print_value(proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ char tmp[MAXSTRING];
+ string_to_hex(tvb_get_ptr(tvb,*offset,item_len),tmp,item_len);
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len, tmp);
+}
+static int
+get_integer_value(ASN1_SCK *asn,int length,int *offset)
+{
+ int off = *offset;
+ int asn_off = asn->offset;
+ int item_len = -1;
+ int ret;
+ /* align pointers */
+ *offset=asn->offset;
+ ret = asn1_uint32_value_decode(asn, length, &item_len);
+ /* return to present position */
+ *offset = off;
+ asn->offset = asn_off;
+
+ if (ret != ASN1_ERR_NOERROR )
+ {
+ return -1;
+ }
+ else
+ {
+ return item_len;
+ }
+
+}
+static void
+show_fully_encoded_seq(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = *offset;
+ guint header_len;
+ guint acse = 0; /* no acse id */
+ int old_offset;
+ /* print seq */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ old_offset = *offset ;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, presentation_data_values,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+ case PRESENTATION_CONTEXT_IDENTIFIER:
+ {
+ acse = get_integer_value(asn,new_item_len,offset);
+ print_value(acse_tree_ms,tvb,offset,new_item_len);
+ }
+ break;
+ case ABSTRACT_SYNTAX_NAME:
+ print_oid_value(asn,acse_tree_ms,tvb,offset,new_item_len);
+ break;
+
+ case OCTET_ALIGNED:
+ break;
+ case SINGLE_ASN1_TYPE:
+ {
+ proto_item *acse_ms;
+ /* yes, we have to call ACSE dissector */
+ acse_ms = proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ "user data");
+ /* call acse dissector */
+ call_app_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,acse_tree_ms);
+ }
+ break;
+ case ARBITRARY:
+ print_value(acse_tree_ms,tvb,offset,new_item_len);
+ break;
+ default:
+ proto_tree_add_text(acse_tree, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ }
+ *offset = old_offset+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ }
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+
+}
+
+static void
+show_acse_user_information(ASN1_SCK *asn,proto_tree
+*acse_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ proto_tree *acse_tree_ab = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ proto_item *ab;
+ guint new_item_len;
+ guint code_item_len;
+ guint start = *offset;
+ guint header_len;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type,response_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* do we have user or provider abort ? */
+ ab = proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ val_to_str(type,acse_user_information_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ab = proto_item_add_subtree(ab, ett_acse_ms);
+
+ if(type!= ACSE_EXTERNAL)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* skip type of item*/
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree_ab, 0, &code_item_len) !=
+ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ code_item_len )
+ {
+ proto_tree_add_text(acse_tree_ab, tvb, *offset, code_item_len,
+ "Wrong item.Need %u bytes but have %u", code_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+
+ show_fully_encoded_seq(asn,acse_tree_ab,tvb,offset,code_item_len);
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+show_acse_result_source_diagnostic(ASN1_SCK *asn,proto_tree
+*acse_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ proto_tree *acse_tree_ab = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ proto_item *ab;
+ guint new_item_len;
+ guint code_item_len;
+ guint start = *offset;
+ guint header_len;
+ proto_tree *acse_tree_pr = NULL;
+ proto_item *pr;
+ int value;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type,response_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* do we have user or provider abort ? */
+ ab = proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ val_to_str(type,acse_associate_source_diagnostic_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ab = proto_item_add_subtree(ab, ett_acse_ms);
+
+ /* skip type of abort*/
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &code_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ code_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, code_item_len,
+ "Wrong item.Need %u bytes but have %u", code_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* skip type of constant*/
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree_ab, 0, &code_item_len) !=
+ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ code_item_len )
+ {
+ proto_tree_add_text(acse_tree_ab, tvb, *offset, code_item_len,
+ "Wrong item.Need %u bytes but have %u", code_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+ value = get_integer_value(asn,code_item_len,offset);
+ if(type == ACSE_SERVICE_USER )
+ {
+ pr = proto_tree_add_text(acse_tree_ab, tvb, *offset,
+ code_item_len+(asn->offset-*offset),
+ val_to_str(value , acse_service_user_values_vals,
+ "Unknown item (0x%02x)"));
+ }
+ else
+ {
+ pr = proto_tree_add_text(acse_tree_ab, tvb, *offset,
+ code_item_len+(asn->offset-*offset),
+ val_to_str(value , acse_service_provider_values_vals,
+ "Unknown item (0x%02x)"));
+ }
+
+ acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
+ print_value(acse_tree_pr,tvb,offset,code_item_len);
+
+ *offset = start+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+
+}
+static void
+show_acse_result(ASN1_SCK *asn,proto_tree
+*acse_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint code_item_len;
+ guint start = *offset;
+ guint header_len;
+ proto_tree *acse_tree_pr = NULL;
+ proto_item *pr;
+ int value;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type,response_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &code_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ code_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, code_item_len,
+ "Wrong item.Need %u bytes but have %u", code_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+ value = get_integer_value(asn,code_item_len,offset);
+ pr = proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ code_item_len+(asn->offset-*offset),
+ val_to_str(value , associate_result_values_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
+ print_value(acse_tree_pr,tvb,offset,code_item_len);
+
+ *offset = start+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+show_oid(ASN1_SCK *asn,proto_tree
+*acse_tree,tvbuff_t *tvb,int *offset,int item_len,const value_string*
+v_s,gchar* oid)
+{
+ proto_tree *acse_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = *offset;
+ guint header_len;
+ int old_offset;
+ old_offset = *offset ;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset) & 0x1f;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(acse_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, v_s,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+ print_oid(asn,acse_tree_ms,tvb,offset,new_item_len,oid);
+ *offset = old_offset+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+static void
+show_fully_encoded_data(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ proto_tree *acse_tree_ms = NULL;
+ proto_tree *acse_tree_pc = NULL;
+ guint length;
+ guint type;
+ guint header_len;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = asn->offset;
+ guint item_length = item_len;
+ acse_tree_pc = acse_tree;
+
+/* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < (guint)item_len )
+ {
+ proto_tree_add_text(acse_tree_pc, tvb, *offset, item_len,
+ "Wrong item.Need %u bytes but have %u", item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset =asn->offset;
+ start = *offset;
+ /* read the rest */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ int old_offset = *offset;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
+ ASN1_ERR_NOERROR)
+ {
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(acse_tree_pc, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ ms = proto_tree_add_text(acse_tree_pc, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, presentation_context_definition_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+
+ case SEQUENCE:
+ show_fully_encoded_seq(asn,acse_tree_ms,tvb,offset,new_item_len);
+ *offset = old_offset+(new_item_len+header_len);
+ break;
+
+ default:
+ proto_tree_add_text(acse_tree_ms, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ *offset = old_offset+(new_item_len+header_len);
+ }
+ item_len = item_len - (new_item_len+header_len);
+
+ }
+
+
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+}
+static void
+show_abort_reason(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ gint length;
+ gint value;
+ proto_tree *acse_tree_pc = NULL;
+ proto_item *itu;
+ guint new_item_len;
+ guint start = *offset;
+ int save_len = item_len;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ *offset = asn->offset;
+ return;
+ }
+
+ if(item_len <= 0)
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Reason not specified");
+ *offset = asn->offset;
+ return;
+ }
+ itu = proto_tree_add_text(acse_tree, tvb, *offset,ABORT_REASON_LEN,
+ "Reason");
+ acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
+ (*offset)++; /* skip type */
+ asn->offset = *offset;
+ item_len--;
+ /* get length */
+ if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
+ ASN1_ERR_NOERROR)
+ {
+ *offset = asn->offset;
+ return;
+ }
+ /* try to get reason */
+ value = get_integer_value(asn,new_item_len,offset);
+
+ proto_tree_add_text(acse_tree_pc, tvb, *offset+1,new_item_len,
+ val_to_str(value,abort_reason,"Unknown item (0x%02x)"));
+ item_len-=(asn->offset-*offset)+new_item_len;
+ *offset = asn->offset+new_item_len;
+ asn->offset = *offset;
+ /* do we have User information field ? */
+ if(item_len > 0)
+ {
+ show_acse_user_information(asn,acse_tree,tvb,offset,item_len);
+ }
+ /* align the pointer */
+ (*offset)=start+save_len;
+ asn->offset = (*offset);
+}
+
+static void
+show_disconnect_pdu(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ gint length;
+ gint value;
+ proto_tree *acse_tree_pc = NULL;
+ proto_item *itu;
+ guint new_item_len;
+ guint start = *offset;
+ int save_len = item_len;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ *offset = asn->offset;
+ return;
+ }
+
+ if(item_len <= 0)
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Reason not specified");
+ *offset = asn->offset;
+ return;
+ }
+ itu = proto_tree_add_text(acse_tree, tvb, *offset,ABORT_REASON_LEN,
+ "Reason");
+ acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
+ (*offset)++; /* skip type */
+ asn->offset = *offset;
+ item_len--;
+ /* get length */
+ if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
+ ASN1_ERR_NOERROR)
+ {
+ *offset = asn->offset;
+ return;
+ }
+ /* try to get reason */
+ value = get_integer_value(asn,new_item_len,offset);
+
+ proto_tree_add_text(acse_tree_pc, tvb, *offset+1,new_item_len,
+ val_to_str(value,release_response_reason,"Unknown item (0x%02x)"));
+ item_len-=(asn->offset-*offset)+new_item_len;
+ *offset = asn->offset+new_item_len;
+ asn->offset = *offset;
+ /* do we have User information field ? */
+ if(item_len > 0)
+ {
+ show_acse_user_information(asn,acse_tree,tvb,offset,item_len);
+ }
+ /* align the pointer */
+ (*offset)=start+save_len;
+ asn->offset = (*offset);
+}
+
+static void
+show_finish_pdu(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ gint length;
+ gint value;
+ proto_tree *acse_tree_pc = NULL;
+ proto_item *itu;
+ guint new_item_len;
+ guint start = *offset;
+ int save_len = item_len;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ *offset = asn->offset;
+ return;
+ }
+
+ if(item_len <= 0)
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Reason not specified");
+ *offset = asn->offset;
+ return;
+ }
+ itu = proto_tree_add_text(acse_tree, tvb, *offset,ABORT_REASON_LEN,
+ "Reason");
+ acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
+ (*offset)++; /* skip type */
+ asn->offset = *offset;
+ item_len--;
+ /* get length */
+ if (read_length(asn, acse_tree_pc, 0, &new_item_len) !=
+ ASN1_ERR_NOERROR)
+ {
+ *offset = asn->offset;
+ return;
+ }
+ /* try to get reason */
+ value = get_integer_value(asn,new_item_len,offset);
+
+ proto_tree_add_text(acse_tree_pc, tvb, *offset+1,new_item_len,
+ val_to_str(value,release_request_reason,"Unknown item (0x%02x)"));
+ item_len-=(asn->offset-*offset)+new_item_len;
+ *offset = asn->offset+new_item_len;
+ asn->offset = *offset;
+ /* do we have User information field ? */
+ if(item_len > 0)
+ {
+ show_acse_user_information(asn,acse_tree,tvb,offset,item_len);
+ }
+ /* align the pointer */
+ (*offset)=start+save_len;
+ asn->offset = (*offset);
+}
+static void
+show_user_data(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *acse_tree_ud = NULL;
+ proto_tree *acse_tree_pc = NULL;
+ proto_item *itm;
+ proto_item *itu;
+ guint start = asn->offset;
+ guint item_length = item_len;
+
+ itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len, "User data");
+ acse_tree_ud = proto_item_add_subtree(itm, ett_acse_ms);
+ itu = proto_tree_add_text(acse_tree_ud, tvb,
+ *offset,item_len+(asn->offset-*offset),
+ val_to_str(tag, user_data_values_vals,"Unknown item (0x%02x)"));
+ acse_tree_pc = proto_item_add_subtree(itu, ett_acse_ms);
+ switch(tag)
+ {
+ case SIMPLY_ENCODED_DATA:
+ break;
+ case FULLY_ENCODED_DATA:
+ show_fully_encoded_data(asn,acse_tree_pc,tvb,offset,item_len);
+ break;
+ default:
+ break;
+ }
+
+
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+
+}
+
+/* if we can't dissect */
+static void
+dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const char *field_name, int ret)
+{
+ char *errstr;
+ errstr = asn1_err_to_str(ret);
+
+ if (tree != NULL)
+ {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "ERROR: Couldn't parse %s: %s", field_name, errstr);
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+}
+
+/* display request top sequence */
+static void
+show_request_sequence_top(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, acse_tree,
+ "sequence error", ret);
+ break;
+ }
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case USER_INFORMATION:
+ show_acse_user_information(asn,acse_tree,tvb,offset,len1);
+ break;
+ case CALLED_AE_QUALIFIER:
+ case CALLING_AE_QUALIFIER:
+ {
+ proto_tree *acse_tree_pr = NULL;
+ proto_item *pr;
+ pr = proto_tree_add_text(acse_tree,tvb,*offset,
+ len1+(asn->offset-*offset),
+ val_to_str(tag ,request_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
+ show_integer(asn,acse_tree_pr,tvb,offset,len1);
+ }
+ break;
+ case APPLICATION_CONTEXT_NAME:
+ case CALLED_AP_TITLE:
+ case CALLING_AP_TITLE:
+ case CALLED_AP_INVOKATION_ID:
+ case CALLED_AE_INVOKATION_ID:
+ case CALLING_AP_INVOKATION_ID:
+ case CALLING_AE_INVOKATION_ID:
+ {
+ gchar oid_string[MAXSTRING];
+ show_oid(asn,acse_tree,tvb,offset,len1,(const
+value_string*)&request_sequence_top_vals,
+ (gchar*)&oid_string);
+ if(tag == APPLICATION_CONTEXT_NAME )
+ {
+ guint pos_in_string;
+ /* try to find real OID string from given */
+ /* function could return "1.0.8571.1.1" or "1.0.8571.1.1 iso.0.8571.1.1" */
+ /* so try to find first blank and strip string */
+ for(pos_in_string=0;pos_in_string<strlen(oid_string);pos_in_string++)
+ {
+ if( oid_string[pos_in_string] == ' ' )
+ {
+ oid_string[pos_in_string] = 0x00;
+ break;
+ }
+ }
+ /* try to get subdissector handler using given OID */
+ if(pos_in_string )
+ {
+ if( !(app_handle = dissector_get_string_handle(application_dissector_table, oid_string) ))
+ {
+ proto_tree_add_text(acse_tree,tvb,*offset,len1,"Unknown OID");
+ }
+ }
+ }
+ }
+ break;
+ case PROTOCOL_VERSION:
+ show_protocol_version(asn,acse_tree,tvb,offset,len1,tag);
+ break;
+ default:
+ itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset
+ -*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;;
+ }
+}
+/* display response top sequence */
+static void
+show_response_sequence_top(ASN1_SCK *asn,proto_tree *acse_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(acse_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, acse_tree,
+ "sequence error", ret);
+ break;
+ }
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case ACSE_RESULT:
+ show_acse_result(asn,acse_tree,tvb,offset,len1);
+ break;
+ case ACSE_RESULT_SOURCE_DIAGNOSTIC:
+ show_acse_result_source_diagnostic(asn,acse_tree,tvb,offset,len1);
+ break;
+ case USER_INFORMATION:
+ show_acse_user_information(asn,acse_tree,tvb,offset,len1);
+ break;
+
+ case RESPONDING_AE_QUALIFIER:
+ {
+ proto_tree *acse_tree_pr = NULL;
+ proto_item *pr;
+ pr = proto_tree_add_text(acse_tree,tvb,*offset,
+ len1+(asn->offset-*offset),
+ val_to_str(tag ,response_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ acse_tree_pr = proto_item_add_subtree(pr, ett_acse_ms);
+ show_integer(asn,acse_tree_pr,tvb,offset,len1);
+ }
+ break;
+ case APPLICATION_CONTEXT_NAME:
+ case RESPONDING_AP_TITLE:
+ case RESPONDING_AP_INVOKATION_ID:
+ case RESPONDING_AE_INVOKATION_ID:
+ show_oid(asn,acse_tree,tvb,offset,len1,(const
+value_string*)&response_sequence_top_vals,NULL);
+ break;
+ case PROTOCOL_VERSION:
+ show_protocol_version(asn,acse_tree,tvb,offset,len1,tag);
+ break;
+ default:
+ itm = proto_tree_add_text(acse_tree, tvb, *offset,(asn->offset
+ -*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+/*
+* Dissect a pdu.
+*/
+static int
+dissect_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree
+ *tree)
+{
+ proto_item *ti;
+ proto_tree *acse_tree = NULL;
+ guint length;
+ guint rest_len;
+ guint s_type;
+ ASN1_SCK asn;
+ guint cp_type_len;
+/* get type of tag */
+ s_type = tvb_get_guint8(tvb, offset);
+ /* set up type of pdu */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(session->spdu_type, ses_vals, "Unknown pdu type (0x%02x)"));
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_acse, tvb, offset, -1,
+ FALSE);
+ acse_tree = proto_item_add_subtree(ti, ett_acse);
+ }
+ offset++;
+/* open asn.1 stream */
+ asn1_open(&asn, tvb, offset);
+
+ switch(session->spdu_type)
+ {
+ case SES_REFUSE:
+ case SES_CONNECTION_REQUEST:
+ case SES_CONNECTION_ACCEPT:
+ proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
+
+ if (read_length(&asn, acse_tree, hf_cp_type_message_length, &cp_type_len)
+ != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
+ )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(acse_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", cp_type_len,length);
+ }
+ return FALSE;
+ }
+ if(tree)
+ {
+ if(session->spdu_type == SES_CONNECTION_REQUEST)
+ {
+ show_request_sequence_top(&asn,acse_tree,tvb,pinfo,&offset,cp_type_len);
+ }
+ else
+ {
+ show_response_sequence_top(&asn,acse_tree,tvb,pinfo,&offset,cp_type_len);
+ }
+
+ }
+ break;
+ case SES_FINISH:
+ proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
+ /* get length */
+ if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(acse_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", rest_len,length);
+ }
+ return FALSE;
+ }
+ show_finish_pdu(&asn,acse_tree,tvb,&offset,rest_len);
+ break;
+ case SES_DISCONNECT:
+ proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
+ /* get length */
+ if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(acse_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", rest_len,length);
+ }
+ return FALSE;
+ }
+ show_disconnect_pdu(&asn,acse_tree,tvb,&offset,rest_len);
+ break;
+ case SES_ABORT:
+ proto_tree_add_uint(acse_tree, hf_acse_type, tvb, offset-1, 1, s_type);
+ /* get length */
+ if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(acse_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", rest_len,length);
+ }
+ return FALSE;
+ }
+ show_abort_reason(&asn,acse_tree,tvb,&offset,rest_len);
+ break;
+ default:
+ {
+ proto_item *ms;
+ proto_tree *acse_tree_ms = NULL;
+ /* back to length */
+ offset--;
+ /* get length */
+ if (read_length(&asn, acse_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ ms = proto_tree_add_text(acse_tree, tvb, offset, rest_len,
+ val_to_str(session->spdu_type, ses_vals, "Unknown pdu type (0x%02x)"));
+ acse_tree_ms = proto_item_add_subtree(ms, ett_acse_ms);
+ show_user_data(&asn,acse_tree_ms,tvb,&offset,rest_len,s_type);
+ }
+ }
+/* close asn.1 stream */
+ asn1_close(&asn, &offset);
+
+ return offset;
+}
+
+/*
+* Dissect ACSE PDUs inside a PPDU.
+*/
+static void
+dissect_acse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+/* first, try to check length */
+/* do we have at least 2 bytes */
+ if (!tvb_bytes_exist(tvb, 0, 2))
+ {
+ proto_tree_add_text(tree, tvb, offset,
+tvb_reported_length_remaining(tvb,offset),
+ "User data");
+ return; /* no, it isn't a ACSE PDU */
+ }
+/* do we have spdu type from the session dissector? */
+ if( !pinfo->private_data )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Internal error:can't get spdu type from session dissector.");
+ return ;
+ }
+ }
+ else
+ {
+ session = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
+ if(session->spdu_type == 0 )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
+ return ;
+ }
+ }
+ }
+/* ACSE has only AARQ,AARE,RLRQ,RLRE,ABRT type of pdu */
+/* reject everything else */
+/* data pdu is not ACSE pdu and has to go directly to app dissector */
+ switch(session->spdu_type)
+ {
+ case SES_REFUSE: /* RLRE */
+ case SES_CONNECTION_REQUEST: /* AARQ */
+ case SES_CONNECTION_ACCEPT: /* AARE */
+ case SES_DISCONNECT: /* RLRQ */
+ case SES_FINISH: /* RLRE */
+ case SES_ABORT: /* ABRT */
+ break;
+ case SES_DATA_TRANSFER:
+ call_app_dissector(tvb,offset,tvb_reported_length_remaining(tvb, offset)
+,pinfo,tree,tree);
+ return;
+ default:
+ return;
+ }
+
+ /* we can't make any additional checking here */
+ /* postpone it before dissector will have more information */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACSE");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+ /* save pointers for calling the app dissector */
+ global_tree = tree;
+ global_pinfo = pinfo;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0)
+ {
+ offset = dissect_pdu(tvb, offset, pinfo, tree);
+ if(offset == FALSE )
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,"Internal error");
+ offset = tvb_length(tvb);
+ break;
+ }
+ }
+}
+
+void
+proto_register_acse(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_acse_type,
+ {
+ "PDU Type",
+ "acse.type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(acse_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_cp_type_message_length,
+ {
+ "Message Length",
+ "cp_type.message_length",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "CP type Message Length",
+ HFILL
+ }
+ },
+ {
+ &hf_protocol_version,
+ {
+ "Protocol version 1",
+ "acse.protocol.version",
+ FT_BOOLEAN, 16,
+ NULL,
+ ACSE_PROTOCOL_VERGION,
+ "Protocol version 1",
+ HFILL
+ }
+ },
+ };
+
+ static gint *ett[] =
+ {
+ &ett_acse,
+ &ett_acse_param,
+ &ett_acse_rc,
+ &ett_acse_ms,
+ &ett_acse_itm,
+ };
+ module_t *acse_module;
+
+
+ proto_acse = proto_register_protocol(PROTO_STRING_ACSE, "ACSE", "acse");
+ proto_register_field_array(proto_acse, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ acse_module = prefs_register_protocol(proto_acse, NULL);
+
+ /*
+ * Register the dissector by name, so other dissectors can
+ * grab it by name rather than just referring to it directly
+ */
+ register_dissector("acse", dissect_acse, proto_acse);
+ application_dissector_table = register_dissector_table("acse.application_context", "Application context OID", FT_STRING, BASE_NONE);
+}
+
+void
+proto_reg_handoff_acse(void)
+{
+ /* find data dissector */
+ data_handle = find_dissector("data");
+
+}
+
+
diff --git a/epan/dissectors/packet-acse.h b/epan/dissectors/packet-acse.h
new file mode 100644
index 0000000000..d5cb006b67
--- /dev/null
+++ b/epan/dissectors/packet-acse.h
@@ -0,0 +1,191 @@
+/* packet-acse.h
+*
+* Routine to dissect OSI ISO/IEC 10035-1 ACSE Protocol packets
+*
+* $Id$
+*
+* Yuriy Sidelnikov <YSidelnikov@hotmail.com>
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define PROTO_STRING_ACSE "OSI ISO/IEC 10035-1 ACSE Protocol"
+#define PROTO_STRING_ACSE_INFO "OSI ISO/IEC 10035-1 ACSE Protocol"
+
+/* asn.1 definitions */
+#define ASN1_CLASS_UNIVERSAL 0x00
+#define ASN1_CLASS_APPLICATION 0x40
+#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80
+#define ASN1_CLASS_Private 0xc0
+#define ASN1_CLASS_PC 0x20
+
+#define INTEGER_ITEM 0x01
+#define BOOLEAN_ITEM 0x01
+
+/* type of parameters */
+#define MODE_SELECTOR 0
+#define SET_TOP 1
+#define SEQUENCE_TOP 2
+
+
+#define SEQUENCE 0x30
+
+/* sequence top */
+#define TAG_00 0
+#define TAG_01 1
+
+enum
+{
+ACSE_AARQ = 0x60,
+ACSE_AARE,
+ACSE_RLRQ,
+ACSE_RLRE,
+ACSE_ABRT
+};
+
+
+enum
+{
+PROTOCOL_VERSION,
+APPLICATION_CONTEXT_NAME,
+CALLED_AP_TITLE,
+CALLED_AE_QUALIFIER,
+CALLED_AP_INVOKATION_ID,
+CALLED_AE_INVOKATION_ID,
+CALLING_AP_TITLE,
+CALLING_AE_QUALIFIER,
+CALLING_AP_INVOKATION_ID,
+CALLING_AE_INVOKATION_ID
+};
+
+#define IMPLEMENTATION_INFORMATION 29
+#define USER_INFORMATION 30
+#define ACSE_EXTERNAL 8
+
+enum
+{
+PROTOCOL_VERSION_2,
+APPLICATION_CONTEXT_NAME_2,
+ACSE_RESULT,
+ACSE_RESULT_SOURCE_DIAGNOSTIC,
+RESPONDING_AP_TITLE,
+RESPONDING_AE_QUALIFIER,
+RESPONDING_AP_INVOKATION_ID,
+RESPONDING_AE_INVOKATION_ID
+};
+
+enum
+{
+ACSE_NULL,
+ACSE_NO_REASON_GIVEN,
+ACSE_APPLICATION_CONTEXT_NAME_NOT_SUPPORTED,
+ACSE_CALLING_AP_TITLE_NOT_RECOGNIZED,
+ACSE_CALLING_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,
+ACSE_CALLING_AE_QUALIFIER_NOT_RECOGNIZED,
+ACSE_CALLING_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,
+ACSE_CALLED_AP_TITLE_NOT_RECOGNIZED,
+ACSE_CALLED_AP_INVOKATION_IDENTIFIER_NOT_RECOGNIZED,
+ACSE_CALLED_AE_QUALIFIER_NOT_RECOGNIZED,
+ACSE_CALLED_AE_INVOKATION_IDENTIFIER_NOT_RECOGNIZED
+};
+
+#define ACSE_NO_COMMON_ACSE_VERSION 2
+
+
+#define ACSE_SERVICE_USER 1
+#define ACSE_SERVICE_PROVIDER 2
+#define ACSE_EXTERNAL_USER 8
+
+/*//////////////////////////////////////////////////
+//enum
+//{
+//PROTOCOL_VERSION_1,
+//CALLING_PRESENTATION_SELECTOR,
+//CALLED_PRESENTATION_SELECTOR,
+//RESPONDING_PRESENTATION_SELECTOR,
+//PRESENTATION_CONTEXT_DEFINITION_LIST,
+//PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST,
+//DEFAULT_CONTEXT_NAME,
+//DEFAULT_CONTEXT_RESULT,
+//PRESENTATION_REQUIREMENTS,
+//USER_SESSION_REQUIREMENTS,
+//PROVIDER_REASON
+//};
+*************************************************/
+
+
+
+
+
+
+/* definition list **/
+#define PRESENTATION_CONTEXT_IDENTIFIER 2
+#define ABSTRACT_SYNTAX_NAME 6
+#define TRANSFER_SYNTAX_NAMES 0x30
+/* result list */
+#define PRESENTATION_RESULT 0x80
+#define PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME 0x81
+#define PRESENTATION_RESULT_INTEGER 0x82
+
+/* result values */
+#define PRESENTATION_RESULT_ACCEPTANCE 0
+#define PRESENTATION_RESULT_USER_REJECTION 1
+#define PRESENTATION_RESULT_PROVIDER_REJECTION 2
+
+enum
+{
+RRR_NORMAL,
+RRR_URGENT,
+RRR_USER_DEFINED
+};
+enum
+{
+RRPR_NORMAL,
+RRPR_URGENT,
+RRPR_USER_DEFINED
+};
+enum
+{
+ABRT_ACSE_SERVICE_USER,
+ABRT_ACSE_SERVICE_PROVIDER
+};
+/* user data */
+#define SIMPLY_ENCODED_DATA 0x60
+#define FULLY_ENCODED_DATA 0x61
+
+/* PDV */
+#define SINGLE_ASN1_TYPE 0xa0
+#define OCTET_ALIGNED 0xa1
+#define ARBITRARY 0xa2
+
+
+
+#define ACSE_PROTOCOL_VERGION 0x0080
+#define MAXSTRING 256
+#define ABORT_REASON_LEN 3
+
+
+#define FTAM_APP 1
+#define CMIP_APP 2
+
+
+
+
+
+
diff --git a/epan/dissectors/packet-afp.c b/epan/dissectors/packet-afp.c
new file mode 100644
index 0000000000..e0e50c48b4
--- /dev/null
+++ b/epan/dissectors/packet-afp.c
@@ -0,0 +1,4740 @@
+/* packet-afp.c
+ * Routines for afp packet dissection
+ * Copyright 2002, Didier Gautheron <dgautheron@magic.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ * Copied from packet-dsi.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/conversation.h>
+
+#include "packet-afp.h"
+
+/* The information in this module (AFP) comes from:
+
+ AFP 2.1 & 2.2.pdf contained in AppleShare_IP_6.3_SDK
+ available from http://www.apple.com
+
+ AFP3.0.pdf from http://www.apple.com (still available?)
+ AFP3.1.pdf from
+
+ http://developer.apple.com/documentation/Networking/Conceptual/AFP/AFP3_1.pdf
+
+ AFP 3.1 in HTML from
+
+http://developer.apple.com/documentation/Networking/Conceptual/AFP/index.html
+
+ The netatalk source code by Wesley Craig & Adrian Sun
+ http://netatalk.sf.net
+*/
+/* from netatalk/include/afp.h */
+#define AFPTRANS_NONE 0
+#define AFPTRANS_DDP (1 << 0)
+#define AFPTRANS_TCP (1 << 1)
+#define AFPTRANS_ALL (AFPTRANS_DDP | AFPTRANS_TCP)
+
+/* AFP Attention Codes -- 4 bits */
+#define AFPATTN_SHUTDOWN (1 << 15) /* shutdown/disconnect */
+#define AFPATTN_CRASH (1 << 14) /* server crashed */
+#define AFPATTN_MESG (1 << 13) /* server has message */
+#define AFPATTN_NORECONNECT (1 << 12) /* don't reconnect */
+/* server notification */
+#define AFPATTN_NOTIFY (AFPATTN_MESG | AFPATTN_NORECONNECT)
+
+/* extended bitmap -- 12 bits. volchanged is only useful w/ a server
+ * notification, and time is only useful for shutdown. */
+#define AFPATTN_VOLCHANGED (1 << 0) /* volume has changed */
+#define AFPATTN_TIME(x) ((x) & 0xfff) /* time in minutes */
+
+/* AFP functions */
+#define AFP_BYTELOCK 1
+#define AFP_CLOSEVOL 2
+#define AFP_CLOSEDIR 3
+#define AFP_CLOSEFORK 4
+#define AFP_COPYFILE 5
+#define AFP_CREATEDIR 6
+#define AFP_CREATEFILE 7
+#define AFP_DELETE 8
+#define AFP_ENUMERATE 9
+#define AFP_FLUSH 10
+#define AFP_FLUSHFORK 11
+#define AFP_GETFORKPARAM 14
+#define AFP_GETSRVINFO 15
+#define AFP_GETSRVPARAM 16
+#define AFP_GETVOLPARAM 17
+#define AFP_LOGIN 18
+#define AFP_LOGINCONT 19
+#define AFP_LOGOUT 20
+#define AFP_MAPID 21
+#define AFP_MAPNAME 22
+#define AFP_MOVE 23
+#define AFP_OPENVOL 24
+#define AFP_OPENDIR 25
+#define AFP_OPENFORK 26
+#define AFP_READ 27
+#define AFP_RENAME 28
+#define AFP_SETDIRPARAM 29
+#define AFP_SETFILEPARAM 30
+#define AFP_SETFORKPARAM 31
+#define AFP_SETVOLPARAM 32
+#define AFP_WRITE 33
+#define AFP_GETFLDRPARAM 34
+#define AFP_SETFLDRPARAM 35
+#define AFP_CHANGEPW 36
+#define AFP_GETUSERINFO 37
+#define AFP_GETSRVRMSG 38
+#define AFP_CREATEID 39
+#define AFP_DELETEID 40
+#define AFP_RESOLVEID 41
+#define AFP_EXCHANGEFILE 42
+#define AFP_CATSEARCH 43
+#define AFP_OPENDT 48
+#define AFP_CLOSEDT 49
+#define AFP_GETICON 51
+#define AFP_GTICNINFO 52
+#define AFP_ADDAPPL 53
+#define AFP_RMVAPPL 54
+#define AFP_GETAPPL 55
+#define AFP_ADDCMT 56
+#define AFP_RMVCMT 57
+#define AFP_GETCMT 58
+#define AFP_ZZZ 122
+#define AFP_ADDICON 192
+
+/* AFP 3.0 new calls */
+#define AFP_BYTELOCK_EXT 59
+#define AFP_CATSEARCH_EXT 67
+#define AFP_ENUMERATE_EXT 66
+#define AFP_READ_EXT 60
+#define AFP_WRITE_EXT 61
+#define AFP_LOGIN_EXT 63
+#define AFP_GETSESSTOKEN 64
+#define AFP_DISCTOLDSESS 65
+
+/* AFP 3.1 new calls */
+#define AFP_ENUMERATE_EXT2 68
+
+/* ----------------------------- */
+static int proto_afp = -1;
+static int hf_afp_reserved = -1;
+
+static int hf_afp_command = -1; /* CommandCode */
+static int hf_afp_AFPVersion = -1;
+static int hf_afp_UAM = -1;
+static int hf_afp_user = -1;
+static int hf_afp_passwd = -1;
+static int hf_afp_random = -1;
+
+static int hf_afp_login_flags = -1;
+static int hf_afp_pad = -1;
+
+static int hf_afp_user_type = -1;
+static int hf_afp_user_len = -1;
+static int hf_afp_user_name = -1;
+
+static int hf_afp_vol_flag_passwd = -1;
+static int hf_afp_vol_flag_unix_priv = -1;
+static int hf_afp_server_time = -1;
+
+static int hf_afp_vol_bitmap = -1;
+static int hf_afp_vol_name_offset = -1;
+static int hf_afp_vol_id = -1;
+static int hf_afp_vol_attribute = -1;
+static int hf_afp_vol_name = -1;
+static int hf_afp_vol_signature = -1;
+static int hf_afp_vol_creation_date = -1;
+static int hf_afp_vol_modification_date = -1;
+static int hf_afp_vol_backup_date = -1;
+static int hf_afp_vol_bytes_free = -1;
+static int hf_afp_vol_bytes_total = -1;
+static int hf_afp_vol_ex_bytes_free = -1;
+static int hf_afp_vol_ex_bytes_total = -1;
+static int hf_afp_vol_block_size = -1;
+
+/* desktop stuff */
+static int hf_afp_comment = -1;
+static int hf_afp_file_creator = -1;
+static int hf_afp_file_type = -1;
+static int hf_afp_icon_type = -1;
+static int hf_afp_icon_length = -1;
+static int hf_afp_icon_tag = -1;
+static int hf_afp_icon_index = -1;
+static int hf_afp_appl_index = -1;
+static int hf_afp_appl_tag = -1;
+
+static int hf_afp_did = -1;
+static int hf_afp_file_id = -1;
+static int hf_afp_file_DataForkLen = -1;
+static int hf_afp_file_RsrcForkLen = -1;
+static int hf_afp_file_ExtDataForkLen = -1;
+static int hf_afp_file_ExtRsrcForkLen = -1;
+
+static int hf_afp_dir_bitmap = -1;
+static int hf_afp_dir_offspring = -1;
+static int hf_afp_dir_OwnerID = -1;
+static int hf_afp_dir_GroupID = -1;
+
+static int hf_afp_file_bitmap = -1;
+static int hf_afp_req_count = -1;
+static int hf_afp_start_index = -1;
+static int hf_afp_start_index32 = -1;
+static int hf_afp_max_reply_size = -1;
+static int hf_afp_max_reply_size32 = -1;
+static int hf_afp_file_flag = -1;
+static int hf_afp_create_flag = -1;
+static int hf_afp_struct_size = -1;
+static int hf_afp_struct_size16 = -1;
+
+static int hf_afp_request_bitmap = -1;
+
+static int hf_afp_cat_count = -1;
+static int hf_afp_cat_req_matches = -1;
+static int hf_afp_cat_position = -1;
+
+static int hf_afp_creation_date = -1;
+static int hf_afp_modification_date = -1;
+static int hf_afp_backup_date = -1;
+static int hf_afp_finder_info = -1;
+static int hf_afp_long_name_offset = -1;
+static int hf_afp_short_name_offset = -1;
+static int hf_afp_unicode_name_offset = -1;
+static int hf_afp_unix_privs_uid = -1;
+static int hf_afp_unix_privs_gid = -1;
+static int hf_afp_unix_privs_permissions = -1;
+static int hf_afp_unix_privs_ua_permissions = -1;
+
+static int hf_afp_path_type = -1;
+static int hf_afp_path_len = -1;
+static int hf_afp_path_name = -1;
+static int hf_afp_path_unicode_hint = -1;
+static int hf_afp_path_unicode_len = -1;
+
+static int hf_afp_flag = -1;
+static int hf_afp_dt_ref = -1;
+static int hf_afp_ofork = -1;
+static int hf_afp_ofork_len = -1;
+static int hf_afp_offset = -1;
+static int hf_afp_rw_count = -1;
+static int hf_afp_newline_mask = -1;
+static int hf_afp_newline_char = -1;
+static int hf_afp_last_written = -1;
+static int hf_afp_actual_count = -1;
+
+static int hf_afp_fork_type = -1;
+static int hf_afp_access_mode = -1;
+static int hf_afp_access_read = -1;
+static int hf_afp_access_write = -1;
+static int hf_afp_access_deny_read = -1;
+static int hf_afp_access_deny_write = -1;
+
+static gint hf_afp_lock_op = -1;
+static gint hf_afp_lock_from = -1;
+static gint hf_afp_lock_offset = -1;
+static gint hf_afp_lock_len = -1;
+static gint hf_afp_lock_range_start = -1;
+
+static gint ett_afp = -1;
+
+static gint ett_afp_vol_attribute = -1;
+static gint ett_afp_enumerate = -1;
+static gint ett_afp_enumerate_line = -1;
+static gint ett_afp_access_mode = -1;
+
+static gint ett_afp_vol_bitmap = -1;
+static gint ett_afp_dir_bitmap = -1;
+static gint ett_afp_dir_attribute = -1;
+static gint ett_afp_file_attribute = -1;
+static gint ett_afp_file_bitmap = -1;
+static gint ett_afp_unix_privs = -1;
+static gint ett_afp_path_name = -1;
+static gint ett_afp_lock_flags = -1;
+static gint ett_afp_dir_ar = -1;
+
+static gint ett_afp_server_vol = -1;
+static gint ett_afp_vol_list = -1;
+static gint ett_afp_vol_flag = -1;
+static gint ett_afp_cat_search = -1;
+static gint ett_afp_cat_r_bitmap = -1;
+static gint ett_afp_cat_spec = -1;
+static gint ett_afp_vol_did = -1;
+
+/* AFP 3.0 parameters */
+static gint hf_afp_lock_offset64 = -1;
+static gint hf_afp_lock_len64 = -1;
+static gint hf_afp_lock_range_start64 = -1;
+
+static int hf_afp_offset64 = -1;
+static int hf_afp_rw_count64 = -1;
+
+static int hf_afp_last_written64 = -1;
+
+static int hf_afp_ofork_len64 = -1;
+static int hf_afp_session_token_type = -1;
+static int hf_afp_session_token_len = -1;
+static int hf_afp_session_token = -1;
+static int hf_afp_session_token_timestamp = -1;
+
+static dissector_handle_t data_handle;
+
+static const value_string vol_signature_vals[] = {
+ {1, "Flat"},
+ {2, "Fixed Directory ID"},
+ {3, "Variable Directory ID (deprecated)"},
+ {0, NULL }
+};
+
+static const value_string CommandCode_vals[] = {
+ {AFP_BYTELOCK, "FPByteRangeLock" },
+ {AFP_CLOSEVOL, "FPCloseVol" },
+ {AFP_CLOSEDIR, "FPCloseDir" },
+ {AFP_CLOSEFORK, "FPCloseFork" },
+ {AFP_COPYFILE, "FPCopyFile" },
+ {AFP_CREATEDIR, "FPCreateDir" },
+ {AFP_CREATEFILE, "FPCreateFile" },
+ {AFP_DELETE, "FPDelete" },
+ {AFP_ENUMERATE, "FPEnumerate" },
+ {AFP_FLUSH, "FPFlush" },
+ {AFP_FLUSHFORK, "FPFlushFork" },
+ {AFP_GETFORKPARAM, "FPGetForkParms" },
+ {AFP_GETSRVINFO, "FPGetSrvrInfo" },
+ {AFP_GETSRVPARAM, "FPGetSrvrParms" },
+ {AFP_GETVOLPARAM, "FPGetVolParms" },
+ {AFP_LOGIN, "FPLogin" },
+ {AFP_LOGINCONT, "FPLoginCont" },
+ {AFP_LOGOUT, "FPLogout" },
+ {AFP_MAPID, "FPMapID" },
+ {AFP_MAPNAME, "FPMapName" },
+ {AFP_MOVE, "FPMoveAndRename" },
+ {AFP_OPENVOL, "FPOpenVol" },
+ {AFP_OPENDIR, "FPOpenDir" },
+ {AFP_OPENFORK, "FPOpenFork" },
+ {AFP_READ, "FPRead" },
+ {AFP_RENAME, "FPRename" },
+ {AFP_SETDIRPARAM, "FPSetDirParms" },
+ {AFP_SETFILEPARAM, "FPSetFileParms" },
+ {AFP_SETFORKPARAM, "FPSetForkParms" },
+ {AFP_SETVOLPARAM, "FPSetVolParms" },
+ {AFP_WRITE, "FPWrite" },
+ {AFP_GETFLDRPARAM, "FPGetFileDirParms" },
+ {AFP_SETFLDRPARAM, "FPSetFileDirParms" },
+ {AFP_CHANGEPW, "FPChangePassword" },
+ {AFP_GETUSERINFO, "FPGetUserInfo" },
+ {AFP_GETSRVRMSG, "FPGetSrvrMsg" },
+ {AFP_CREATEID, "FPCreateID" },
+ {AFP_DELETEID, "FPDeleteID" },
+ {AFP_RESOLVEID, "FPResolveID" },
+ {AFP_EXCHANGEFILE, "FPExchangeFiles" },
+ {AFP_CATSEARCH, "FPCatSearch" },
+ {AFP_OPENDT, "FPOpenDT" },
+ {AFP_CLOSEDT, "FPCloseDT" },
+ {AFP_GETICON, "FPGetIcon" },
+ {AFP_GTICNINFO, "FPGetIconInfo" },
+ {AFP_ADDAPPL, "FPAddAPPL" },
+ {AFP_RMVAPPL, "FPRemoveAPPL" },
+ {AFP_GETAPPL, "FPGetAPPL" },
+ {AFP_ADDCMT, "FPAddComment" },
+ {AFP_RMVCMT, "FPRemoveComment" },
+ {AFP_GETCMT, "FPGetComment" },
+ {AFP_BYTELOCK_EXT, "FPByteRangeLockExt" },
+ {AFP_CATSEARCH_EXT, "FPCatSearchExt" },
+ {AFP_ENUMERATE_EXT, "FPEnumerateExt" },
+ {AFP_ENUMERATE_EXT2, "FPEnumerateExt2" },
+ {AFP_READ_EXT, "FPReadExt" },
+ {AFP_WRITE_EXT, "FPWriteExt" },
+ {AFP_LOGIN_EXT, "FPLoginExt" },
+ {AFP_GETSESSTOKEN, "FPGetSessionToken" },
+ {AFP_DISCTOLDSESS, "FPDisconnectOldSession" },
+ {AFP_ZZZ, "FPzzz" },
+ {AFP_ADDICON, "FPAddIcon" },
+ {0, NULL }
+};
+
+static const value_string unicode_hint_vals[] = {
+ { 0, "MacRoman" },
+ { 1, "MacJapanese" },
+ { 2, "MacChineseTrad" },
+ { 3, "MacKorean" },
+ { 4, "MacArabic" },
+ { 5, "MacHebrew" },
+ { 6, "MacGreek" },
+ { 7, "MacCyrillic" },
+ { 9, "MacDevanagari" },
+ { 10, "MacGurmukhi" },
+ { 11, "MacGujarati" },
+ { 12, "MacOriya" },
+ { 13, "MacBengali" },
+ { 14, "MacTamil" },
+ { 15, "MacTelugu" },
+ { 16, "MacKannada" },
+ { 17, "MacMalayalam" },
+ { 18, "MacSinhalese" },
+ { 19, "MacBurmese" },
+ { 20, "MacKhmer" },
+ { 21, "MacThai" },
+ { 22, "MacLaotian" },
+ { 23, "MacGeorgian" },
+ { 24, "MacArmenian" },
+ { 25, "MacChineseSimp" },
+ { 26, "MacTibetan" },
+ { 27, "MacMongolian" },
+ { 28, "MacEthiopic" },
+ { 29, "MacCentralEurRoman" },
+ { 30, "MacVietnamese" },
+ { 31, "MacExtArabic" },
+ { 33, "MacSymbol" },
+ { 34, "MacDingbats" },
+ { 35, "MacTurkish" },
+ { 36, "MacCroatian" },
+ { 37, "MacIcelandic" },
+ { 38, "MacRomanian" },
+ { 39, "MacCeltic" },
+ { 40, "MacGaelic" },
+ { 41, "MacKeyboardGlyphs" },
+ { 126, "MacUnicode" },
+ { 140, "MacFarsi" },
+ { 152, "MacUkrainian" },
+ { 236, "MacInuit" },
+ { 252, "MacVT100" },
+ { 255, "MacHFS" },
+ { 256, "UnicodeDefault" },
+/* { 257, "UnicodeV1_1" }, */
+ { 257, "ISO10646_1993" },
+ { 259, "UnicodeV2_0" },
+ { 259, "UnicodeV2_1" },
+ { 260, "UnicodeV3_0" },
+ { 513, "ISOLatin1" },
+ { 514, "ISOLatin2" },
+ { 515, "ISOLatin3" },
+ { 516, "ISOLatin4" },
+ { 517, "ISOLatinCyrillic" },
+ { 518, "ISOLatinArabic" },
+ { 519, "ISOLatinGreek" },
+ { 520, "ISOLatinHebrew" },
+ { 521, "ISOLatin5" },
+ { 522, "ISOLatin6" },
+ { 525, "ISOLatin7" },
+ { 526, "ISOLatin8" },
+ { 527, "ISOLatin9" },
+ { 1024, "DOSLatinUS" },
+ { 1029, "DOSGreek" },
+ { 1030, "DOSBalticRim" },
+ { 1040, "DOSLatin1" },
+ { 1041, "DOSGreek1" },
+ { 1042, "DOSLatin2" },
+ { 1043, "DOSCyrillic" },
+ { 1044, "DOSTurkish" },
+ { 1045, "DOSPortuguese" },
+ { 1046, "DOSIcelandic" },
+ { 1047, "DOSHebrew" },
+ { 1048, "DOSCanadianFrench" },
+ { 1049, "DOSArabic" },
+ { 1050, "DOSNordic" },
+ { 1051, "DOSRussian" },
+ { 1052, "DOSGreek2" },
+ { 1053, "DOSThai" },
+ { 1056, "DOSJapanese" },
+ { 1057, "DOSChineseSimplif" },
+ { 1058, "DOSKorean" },
+ { 1059, "DOSChineseTrad" },
+ { 1280, "WindowsLatin1" },
+/* { 1280, "WindowsANSI" }, */
+ { 1281, "WindowsLatin2" },
+ { 1282, "WindowsCyrillic" },
+ { 1283, "WindowsGreek" },
+ { 1284, "WindowsLatin5" },
+ { 1285, "WindowsHebrew" },
+ { 1286, "WindowsArabic" },
+ { 1287, "WindowsBalticRim" },
+ { 1288, "WindowsVietnamese" },
+ { 1296, "WindowsKoreanJohab" },
+ { 1536, "US_ASCII" },
+ { 1568, "JIS_X0201_76" },
+ { 1569, "JIS_X0208_83" },
+ { 1570, "JIS_X0208_90" },
+ { 0, NULL }
+};
+
+/* volume bitmap
+ from Apple AFP3.0.pdf
+ Table 1-2 p. 20
+*/
+#define kFPVolAttributeBit (1 << 0)
+#define kFPVolSignatureBit (1 << 1)
+#define kFPVolCreateDateBit (1 << 2)
+#define kFPVolModDateBit (1 << 3)
+#define kFPVolBackupDateBit (1 << 4)
+#define kFPVolIDBit (1 << 5)
+#define kFPVolBytesFreeBit (1 << 6)
+#define kFPVolBytesTotalBit (1 << 7)
+#define kFPVolNameBit (1 << 8)
+#define kFPVolExtBytesFreeBit (1 << 9)
+#define kFPVolExtBytesTotalBit (1 << 10)
+#define kFPVolBlockSizeBit (1 << 11)
+
+static int hf_afp_vol_bitmap_Attributes = -1;
+static int hf_afp_vol_bitmap_Signature = -1;
+static int hf_afp_vol_bitmap_CreateDate = -1;
+static int hf_afp_vol_bitmap_ModDate = -1;
+static int hf_afp_vol_bitmap_BackupDate = -1;
+static int hf_afp_vol_bitmap_ID = -1;
+static int hf_afp_vol_bitmap_BytesFree = -1;
+static int hf_afp_vol_bitmap_BytesTotal = -1;
+static int hf_afp_vol_bitmap_Name = -1;
+static int hf_afp_vol_bitmap_ExtBytesFree = -1;
+static int hf_afp_vol_bitmap_ExtBytesTotal = -1;
+static int hf_afp_vol_bitmap_BlockSize = -1;
+
+static int hf_afp_vol_attribute_ReadOnly = -1;
+static int hf_afp_vol_attribute_HasVolumePassword = -1;
+static int hf_afp_vol_attribute_SupportsFileIDs = -1;
+static int hf_afp_vol_attribute_SupportsCatSearch = -1;
+static int hf_afp_vol_attribute_SupportsBlankAccessPrivs = -1;
+static int hf_afp_vol_attribute_SupportsUnixPrivs = -1;
+static int hf_afp_vol_attribute_SupportsUTF8Names = -1;
+
+static int hf_afp_dir_bitmap_Attributes = -1;
+static int hf_afp_dir_bitmap_ParentDirID = -1;
+static int hf_afp_dir_bitmap_CreateDate = -1;
+static int hf_afp_dir_bitmap_ModDate = -1;
+static int hf_afp_dir_bitmap_BackupDate = -1;
+static int hf_afp_dir_bitmap_FinderInfo = -1;
+static int hf_afp_dir_bitmap_LongName = -1;
+static int hf_afp_dir_bitmap_ShortName = -1;
+static int hf_afp_dir_bitmap_NodeID = -1;
+static int hf_afp_dir_bitmap_OffspringCount = -1;
+static int hf_afp_dir_bitmap_OwnerID = -1;
+static int hf_afp_dir_bitmap_GroupID = -1;
+static int hf_afp_dir_bitmap_AccessRights = -1;
+static int hf_afp_dir_bitmap_UTF8Name = -1;
+static int hf_afp_dir_bitmap_UnixPrivs = -1;
+
+static int hf_afp_dir_attribute_Invisible = -1;
+static int hf_afp_dir_attribute_IsExpFolder = -1;
+
+static int hf_afp_dir_attribute_System = -1;
+static int hf_afp_dir_attribute_Mounted = -1;
+static int hf_afp_dir_attribute_InExpFolder = -1;
+
+static int hf_afp_dir_attribute_BackUpNeeded = -1;
+static int hf_afp_dir_attribute_RenameInhibit = -1;
+static int hf_afp_dir_attribute_DeleteInhibit = -1;
+static int hf_afp_dir_attribute_SetClear = -1;
+
+static int hf_afp_file_bitmap_Attributes = -1;
+static int hf_afp_file_bitmap_ParentDirID = -1;
+static int hf_afp_file_bitmap_CreateDate = -1;
+static int hf_afp_file_bitmap_ModDate = -1;
+static int hf_afp_file_bitmap_BackupDate = -1;
+static int hf_afp_file_bitmap_FinderInfo = -1;
+static int hf_afp_file_bitmap_LongName = -1;
+static int hf_afp_file_bitmap_ShortName = -1;
+static int hf_afp_file_bitmap_NodeID = -1;
+static int hf_afp_file_bitmap_DataForkLen = -1;
+static int hf_afp_file_bitmap_RsrcForkLen = -1;
+static int hf_afp_file_bitmap_ExtDataForkLen = -1;
+static int hf_afp_file_bitmap_LaunchLimit = -1;
+
+static int hf_afp_file_bitmap_UTF8Name = -1;
+static int hf_afp_file_bitmap_ExtRsrcForkLen = -1;
+static int hf_afp_file_bitmap_UnixPrivs = -1;
+
+static int hf_afp_file_attribute_Invisible = -1;
+static int hf_afp_file_attribute_MultiUser = -1;
+static int hf_afp_file_attribute_System = -1;
+static int hf_afp_file_attribute_DAlreadyOpen = -1;
+static int hf_afp_file_attribute_RAlreadyOpen = -1;
+static int hf_afp_file_attribute_WriteInhibit = -1;
+static int hf_afp_file_attribute_BackUpNeeded = -1;
+static int hf_afp_file_attribute_RenameInhibit = -1;
+static int hf_afp_file_attribute_DeleteInhibit = -1;
+static int hf_afp_file_attribute_CopyProtect = -1;
+static int hf_afp_file_attribute_SetClear = -1;
+
+static int hf_afp_map_name_type = -1;
+static int hf_afp_map_name = -1;
+static int hf_afp_map_id = -1;
+static int hf_afp_map_id_type = -1;
+
+static int hf_afp_request_bitmap_Attributes = -1;
+static int hf_afp_request_bitmap_ParentDirID = -1;
+static int hf_afp_request_bitmap_CreateDate = -1;
+static int hf_afp_request_bitmap_ModDate = -1;
+static int hf_afp_request_bitmap_BackupDate = -1;
+static int hf_afp_request_bitmap_FinderInfo = -1;
+static int hf_afp_request_bitmap_LongName = -1;
+static int hf_afp_request_bitmap_DataForkLen = -1;
+static int hf_afp_request_bitmap_OffspringCount = -1;
+static int hf_afp_request_bitmap_RsrcForkLen = -1;
+static int hf_afp_request_bitmap_ExtDataForkLen = -1;
+static int hf_afp_request_bitmap_UTF8Name = -1;
+static int hf_afp_request_bitmap_ExtRsrcForkLen = -1;
+static int hf_afp_request_bitmap_PartialNames = -1;
+
+static const value_string flag_vals[] = {
+ {0, "Start" },
+ {1, "End" },
+ {0, NULL } };
+
+static const value_string path_type_vals[] = {
+ {1, "Short names" },
+ {2, "Long names" },
+ {3, "Unicode names" },
+ {0, NULL } };
+
+static const value_string map_name_type_vals[] = {
+ {1, "Unicode user name to a user ID" },
+ {2, "Unicode group name to a group ID" },
+ {3, "Macintosh roman user name to a user ID" },
+ {4, "Macintosh roman group name to a group ID" },
+ {0, NULL } };
+
+static const value_string map_id_type_vals[] = {
+ {1, "User ID to a Macintosh roman user name" },
+ {2, "Group ID to a Macintosh roman group name" },
+ {3, "User ID to a unicode user name" },
+ {4, "Group ID to a unicode group name" },
+ {0, NULL } };
+
+/*
+ volume attribute from Apple AFP3.0.pdf
+ Table 1-3 p. 22
+*/
+#define kReadOnly (1 << 0)
+#define kHasVolumePassword (1 << 1)
+#define kSupportsFileIDs (1 << 2)
+#define kSupportsCatSearch (1 << 3)
+#define kSupportsBlankAccessPrivs (1 << 4)
+#define kSupportsUnixPrivs (1 << 5)
+#define kSupportsUTF8Names (1 << 6)
+/* AFP3.1 */
+#define kNoNetworkUserIDs (1 << 7)
+
+/*
+ directory bitmap from Apple AFP3.1.pdf
+ Table 1-5 pp. 25-26
+*/
+#define kFPAttributeBit (1 << 0)
+#define kFPParentDirIDBit (1 << 1)
+#define kFPCreateDateBit (1 << 2)
+#define kFPModDateBit (1 << 3)
+#define kFPBackupDateBit (1 << 4)
+#define kFPFinderInfoBit (1 << 5)
+#define kFPLongNameBit (1 << 6)
+#define kFPShortNameBit (1 << 7)
+#define kFPNodeIDBit (1 << 8)
+#define kFPOffspringCountBit (1 << 9)
+#define kFPOwnerIDBit (1 << 10)
+#define kFPGroupIDBit (1 << 11)
+#define kFPAccessRightsBit (1 << 12)
+#define kFPUTF8NameBit (1 << 13)
+
+/* FIXME AFP3.0 bit 14, AFP3.1 bit 15 */
+
+#define kFPUnixPrivsBit (1 << 15)
+
+/*
+ directory Access Rights parameter AFP3.1.pdf
+ table 1-7 p. 28
+*/
+
+#define AR_O_SEARCH (1 << 0) /* owner has search access */
+#define AR_O_READ (1 << 1) /* owner has read access */
+#define AR_O_WRITE (1 << 2) /* owner has write access */
+
+#define AR_G_SEARCH (1 << 8) /* group has search access */
+#define AR_G_READ (1 << 9) /* group has read access */
+#define AR_G_WRITE (1 << 10) /* group has write access */
+
+#define AR_E_SEARCH (1 << 16) /* everyone has search access */
+#define AR_E_READ (1 << 17) /* everyone has read access */
+#define AR_E_WRITE (1 << 18) /* everyone has write access */
+
+#define AR_U_SEARCH (1 << 24) /* user has search access */
+#define AR_U_READ (1 << 25) /* user has read access */
+#define AR_U_WRITE (1 << 26) /* user has write access */
+
+#define AR_BLANK (1 << 28) /* Blank Access Privileges (use parent dir privileges) */
+#define AR_U_OWN (1 << 31) /* user is the owner */
+
+static int hf_afp_dir_ar = -1;
+static int hf_afp_dir_ar_o_search = -1;
+static int hf_afp_dir_ar_o_read = -1;
+static int hf_afp_dir_ar_o_write = -1;
+static int hf_afp_dir_ar_g_search = -1;
+static int hf_afp_dir_ar_g_read = -1;
+static int hf_afp_dir_ar_g_write = -1;
+static int hf_afp_dir_ar_e_search = -1;
+static int hf_afp_dir_ar_e_read = -1;
+static int hf_afp_dir_ar_e_write = -1;
+static int hf_afp_dir_ar_u_search = -1;
+static int hf_afp_dir_ar_u_read = -1;
+static int hf_afp_dir_ar_u_write = -1;
+static int hf_afp_dir_ar_blank = -1;
+static int hf_afp_dir_ar_u_own = -1;
+
+static int hf_afp_user_flag = -1;
+static int hf_afp_user_ID = -1;
+static int hf_afp_group_ID = -1;
+static int hf_afp_user_bitmap = -1;
+static int hf_afp_user_bitmap_UID = -1;
+static int hf_afp_user_bitmap_GID = -1;
+
+static gint ett_afp_user_bitmap = -1;
+
+static const value_string user_flag_vals[] = {
+ {0, "Use user ID" },
+ {1, "Default user" },
+ {0, NULL } };
+
+/*
+ file bitmap AFP3.1.pdf
+ Table 1-8 p. 29
+same as dir
+kFPAttributeBit (bit 0)
+kFPParentDirIDBit (bit 1)
+kFPCreateDateBit (bit 2)
+kFPModDateBit (bit 3)
+kFPBackupDateBit (bit 4)
+kFPFinderInfoBit (bit 5)
+kFPLongNameBit (bit 6)
+kFPShortNameBit (bit 7)
+kFPNodeIDBit (bit 8)
+
+kFPUTF8NameBit (bit 13)
+*/
+
+#define kFPDataForkLenBit (1 << 9)
+#define kFPRsrcForkLenBit (1 << 10)
+#define kFPExtDataForkLenBit (1 << 11)
+#define kFPLaunchLimitBit (1 << 12)
+
+#define kFPExtRsrcForkLenBit (1 << 14)
+
+/*
+ file attribute AFP3.1.pdf
+ Table 1-9 pp. 29-31
+*/
+#define kFPInvisibleBit (1 << 0)
+#define kFPMultiUserBit (1 << 1)
+#define kFPSystemBit (1 << 2)
+#define kFPDAlreadyOpenBit (1 << 3)
+#define kFPRAlreadyOpenBit (1 << 4)
+#define kFPWriteInhibitBit (1 << 5)
+#define kFPBackUpNeededBit (1 << 6)
+#define kFPRenameInhibitBit (1 << 7)
+#define kFPDeleteInhibitBit (1 << 8)
+#define kFPCopyProtectBit (1 << 10)
+#define kFPSetClearBit (1 << 15)
+
+/* dir attribute */
+#define kIsExpFolder (1 << 1)
+#define kMounted (1 << 3)
+#define kInExpFolder (1 << 4)
+
+/* AFP 3.1 getsession token type */
+#define kLoginWithoutID 0
+#define kLoginWithID 1
+#define kReconnWithID 2
+#define kLoginWithTimeAndID 3
+#define kReconnWithTimeAndID 4
+
+static const value_string token_type_vals[] = {
+ {kLoginWithoutID, "LoginWithoutID"},
+ {kLoginWithID, "LoginWithID"},
+ {kReconnWithID, "ReconnWithID"},
+ {kLoginWithTimeAndID, "LoginWithTimeAndID"},
+ {kReconnWithTimeAndID, "ReconnWithTimeAndID"},
+ {0, NULL } };
+
+#define hash_init_count 20
+
+/* Hash functions */
+static gint afp_equal (gconstpointer v, gconstpointer v2);
+static guint afp_hash (gconstpointer v);
+
+static guint afp_packet_init_count = 200;
+
+typedef struct {
+ guint32 conversation;
+ guint16 seq;
+} afp_request_key;
+
+typedef struct {
+ guint8 command;
+} afp_request_val;
+
+static GHashTable *afp_request_hash = NULL;
+static GMemChunk *afp_request_keys = NULL;
+static GMemChunk *afp_request_vals = NULL;
+
+static guint Vol; /* volume */
+static guint Did; /* parent directory ID */
+
+/* Hash Functions */
+static gint afp_equal (gconstpointer v, gconstpointer v2)
+{
+ const afp_request_key *val1 = (const afp_request_key*)v;
+ const afp_request_key *val2 = (const afp_request_key*)v2;
+
+ if (val1->conversation == val2->conversation &&
+ val1->seq == val2->seq) {
+ return 1;
+ }
+ return 0;
+}
+
+static guint afp_hash (gconstpointer v)
+{
+ const afp_request_key *afp_key = (const afp_request_key*)v;
+ return afp_key->seq;
+}
+
+/* --------------------------
+*/
+#define PAD(x) { proto_tree_add_item(tree, hf_afp_pad, tvb, offset, x, FALSE); offset += x; }
+
+static guint16
+decode_vol_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint16 bitmap;
+
+ bitmap = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_item(tree, hf_afp_vol_bitmap, tvb, offset, 2,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_vol_bitmap);
+ }
+
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Attributes, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Signature, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_CreateDate, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ModDate, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BackupDate, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ID, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BytesFree, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BytesTotal, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_Name, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ExtBytesFree, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_ExtBytesTotal, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_bitmap_BlockSize , tvb, offset, 2,FALSE);
+
+ return bitmap;
+}
+
+/* -------------------------- */
+static guint16
+decode_vol_attribute (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint16 bitmap;
+
+ bitmap = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_item(tree, hf_afp_vol_attribute, tvb, offset, 2,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_vol_attribute);
+ }
+ proto_tree_add_item(sub_tree, hf_afp_vol_attribute_ReadOnly ,tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_attribute_HasVolumePassword ,tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsFileIDs ,tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsCatSearch ,tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsBlankAccessPrivs,tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsUnixPrivs ,tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_vol_attribute_SupportsUTF8Names ,tvb, offset, 2,FALSE);
+
+ return bitmap;
+}
+
+/* --------------------------
+ cf AFP3.0.pdf page 38
+ date are number of seconds from 12:00am on 01.01.2000 GMT
+ backup : 0x8000000 not set
+ from netatalk adouble.h
+*/
+#define DATE_NOT_SET 0x80000000
+#define AD_DATE_DELTA 946684800
+#define AD_DATE_TO_UNIX(x) (x + AD_DATE_DELTA)
+static guint32
+print_date(proto_tree *tree,int id, tvbuff_t *tvb, gint offset)
+{
+ time_t date = tvb_get_ntohl(tvb, offset);
+ nstime_t tv;
+
+ tv.secs = AD_DATE_TO_UNIX(date);
+ tv.nsecs = 0;
+ proto_tree_add_time(tree, id, tvb, offset, 4, &tv);
+
+ return date;
+}
+
+/* -------------------------- */
+static gint
+parse_vol_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
+{
+ guint16 nameoff = 0;
+
+ if ((bitmap & kFPVolAttributeBit)) {
+ decode_vol_attribute(tree,tvb,offset);
+ offset += 2;
+ }
+ if ((bitmap & kFPVolSignatureBit)) {
+ proto_tree_add_item(tree, hf_afp_vol_signature,tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ if ((bitmap & kFPVolCreateDateBit)) {
+ print_date(tree, hf_afp_vol_creation_date,tvb, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPVolModDateBit)) {
+ print_date(tree, hf_afp_vol_modification_date,tvb, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPVolBackupDateBit)) {
+ print_date(tree, hf_afp_vol_backup_date,tvb, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPVolIDBit)) {
+ proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+ offset += 2;
+ }
+ if ((bitmap & kFPVolBytesFreeBit)) {
+ proto_tree_add_item(tree, hf_afp_vol_bytes_free,tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ if ((bitmap & kFPVolBytesTotalBit)) {
+ proto_tree_add_item(tree, hf_afp_vol_bytes_total,tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ if ((bitmap & kFPVolNameBit)) {
+ nameoff = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_vol_name_offset,tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ if ((bitmap & kFPVolExtBytesFreeBit)) {
+ proto_tree_add_item(tree, hf_afp_vol_ex_bytes_free,tvb, offset, 8, FALSE);
+ offset += 8;
+ }
+ if ((bitmap & kFPVolExtBytesTotalBit)) {
+ proto_tree_add_item(tree, hf_afp_vol_ex_bytes_total,tvb, offset, 8, FALSE);
+ offset += 8;
+ }
+ if ((bitmap & kFPVolBlockSizeBit)) {
+ proto_tree_add_item(tree, hf_afp_vol_block_size,tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ if (nameoff) {
+ guint8 len;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
+ offset += len +1;
+
+ }
+ return offset;
+}
+
+/* -------------------------- */
+static guint16
+decode_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint16 bitmap;
+
+ bitmap = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_item(tree, hf_afp_file_bitmap, tvb, offset, 2,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_file_bitmap);
+ }
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_Attributes , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ParentDirID , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_CreateDate , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ModDate , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_BackupDate , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_FinderInfo , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_LongName , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ShortName , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_NodeID , tvb, offset, 2,FALSE);
+
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_DataForkLen , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_RsrcForkLen , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ExtDataForkLen , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_LaunchLimit , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_UTF8Name , tvb, offset, 2,FALSE);
+
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_ExtRsrcForkLen , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_bitmap_UnixPrivs , tvb, offset, 2,FALSE);
+
+ return bitmap;
+}
+
+/* -------------------------- */
+static guint16
+decode_file_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset, int shared)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint16 attribute;
+
+ attribute = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, 2,
+ "File Attributes: 0x%04x", attribute);
+ sub_tree = proto_item_add_subtree(item, ett_afp_file_attribute);
+ }
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_Invisible , tvb, offset, 2,FALSE);
+ if (!shared)
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_MultiUser , tvb, offset, 2,FALSE);
+
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_System , tvb, offset, 2,FALSE);
+
+ if (!shared) {
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_DAlreadyOpen , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_RAlreadyOpen , tvb, offset, 2,FALSE);
+ }
+ /* writeinhibit is file only but Macs are setting it with FPSetFileDirParms too */
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_WriteInhibit , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_BackUpNeeded , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_RenameInhibit, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_DeleteInhibit, tvb, offset, 2,FALSE);
+
+ if (!shared)
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_CopyProtect , tvb, offset, 2,FALSE);
+
+ proto_tree_add_item(sub_tree, hf_afp_file_attribute_SetClear , tvb, offset, 2,FALSE);
+
+ return(attribute);
+}
+
+static void
+decode_access_rights (proto_tree *tree, tvbuff_t *tvb, int hf, gint offset)
+{
+ proto_tree *sub_tree;
+ proto_item *item;
+
+ if (tree) {
+ item = proto_tree_add_item(tree, hf, tvb, offset, 4, FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_dir_ar);
+
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_search, tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_read , tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_o_write , tvb, offset, 4, FALSE);
+
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_search, tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_read , tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_g_write , tvb, offset, 4, FALSE);
+
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_search, tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_read , tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_e_write , tvb, offset, 4, FALSE);
+
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_search, tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_read , tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_write , tvb, offset, 4, FALSE);
+
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_blank , tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_ar_u_own , tvb, offset, 4, FALSE);
+ }
+}
+
+static void
+decode_unix_privs (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ proto_tree *sub_tree;
+ proto_item *item;
+
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, 16,
+ "UNIX privileges");
+ sub_tree = proto_item_add_subtree(item, ett_afp_unix_privs);
+
+ proto_tree_add_item(sub_tree, hf_afp_unix_privs_uid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_unix_privs_gid, tvb, offset+4, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_unix_privs_permissions, tvb, offset+8, 4, FALSE);
+ decode_access_rights(sub_tree, tvb, hf_afp_unix_privs_ua_permissions, offset+12);
+ }
+}
+
+/* -------------------------- */
+static gint
+parse_long_filename(proto_tree *tree, tvbuff_t *tvb, gint offset, gint org_offset)
+{
+ guint16 lnameoff;
+ gint tp_ofs = 0;
+ guint8 len;
+
+ lnameoff = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_long_name_offset,tvb, offset, 2, FALSE);
+ if (lnameoff) {
+ tp_ofs = lnameoff +org_offset;
+ len = tvb_get_guint8(tvb, tp_ofs);
+ proto_tree_add_item(tree, hf_afp_path_len, tvb, tp_ofs, 1,FALSE);
+ tp_ofs++;
+ proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
+ tp_ofs += len;
+ }
+ return tp_ofs;
+}
+
+/* -------------------------- */
+static gint
+parse_UTF8_filename(proto_tree *tree, tvbuff_t *tvb, gint offset, gint org_offset)
+{
+ guint16 unameoff;
+ gint tp_ofs = 0;
+ guint16 len;
+
+ unameoff = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_unicode_name_offset,tvb, offset, 2, FALSE);
+ offset += 2;
+ if (unameoff) {
+ /* FIXME AFP3.x reuses PDINFO bit for UTF8.
+ * In enumerate_ext it's pad with 4 bytes, PDINFO was 6 bytes,
+ * but not in catsearch_ext.
+ * Last but not least there's a bug in OSX catsearch_ext for spec2
+ * offset is off by 2 bytes.
+ */
+
+ tp_ofs = unameoff +org_offset;
+ if (tp_ofs > offset) {
+ PAD(4);
+ }
+ else if (tp_ofs < offset) {
+ tp_ofs = offset;
+ }
+ proto_tree_add_item( tree, hf_afp_path_unicode_hint, tvb, tp_ofs, 4,FALSE);
+ tp_ofs += 4;
+
+ len = tvb_get_ntohs(tvb, tp_ofs);
+ proto_tree_add_item( tree, hf_afp_path_unicode_len, tvb, tp_ofs, 2,FALSE);
+ tp_ofs += 2;
+
+ proto_tree_add_item(tree, hf_afp_path_name, tvb, tp_ofs, len,FALSE);
+ tp_ofs += len;
+ }
+ return tp_ofs;
+}
+
+/* -------------------------- */
+static gint
+parse_file_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap, int shared)
+{
+ guint16 snameoff = 0;
+ gint max_offset = 0;
+
+ gint org_offset = offset;
+
+ if ((bitmap & kFPAttributeBit)) {
+ decode_file_attribute(tree, tvb, offset, shared);
+ offset += 2;
+ }
+ if ((bitmap & kFPParentDirIDBit)) {
+ proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+ if ((bitmap & kFPCreateDateBit)) {
+ print_date(tree, hf_afp_creation_date,tvb, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPModDateBit)) {
+ print_date(tree, hf_afp_modification_date,tvb, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPBackupDateBit)) {
+ print_date(tree, hf_afp_backup_date,tvb, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPFinderInfoBit)) {
+ proto_tree_add_item(tree, hf_afp_finder_info,tvb, offset, 32, FALSE);
+ offset += 32;
+ }
+ if ((bitmap & kFPLongNameBit)) {
+ gint tp_ofs;
+
+ tp_ofs = parse_long_filename(tree, tvb, offset, org_offset);
+ max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+
+ offset += 2;
+
+ }
+ if ((bitmap & kFPShortNameBit)) {
+ snameoff = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_short_name_offset,tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ if ((bitmap & kFPNodeIDBit)) {
+ proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+
+ if ((bitmap & kFPDataForkLenBit)) {
+ proto_tree_add_item(tree, hf_afp_file_DataForkLen, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+
+ if ((bitmap & kFPRsrcForkLenBit)) {
+ proto_tree_add_item(tree, hf_afp_file_RsrcForkLen, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+
+ if ((bitmap & kFPExtDataForkLenBit)) {
+ proto_tree_add_item(tree, hf_afp_file_ExtDataForkLen, tvb, offset, 8,FALSE);
+ offset += 8;
+ }
+
+ if ((bitmap & kFPLaunchLimitBit)) {
+ offset += 2; /* ? */
+ }
+
+ if ((bitmap & kFPUTF8NameBit)) {
+ gint tp_ofs;
+
+ tp_ofs = parse_UTF8_filename(tree, tvb, offset, org_offset);
+ max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+ offset += 6;
+ }
+
+ if ((bitmap & kFPExtRsrcForkLenBit)) {
+ proto_tree_add_item(tree, hf_afp_file_ExtRsrcForkLen, tvb, offset, 8,FALSE);
+ offset += 8;
+ }
+
+ if ((bitmap & kFPUnixPrivsBit)) {
+ /*
+ * XXX - the AFP 3.0 spec says this is "Four bytes", but
+ * also says the privileges are "stored in an FPUnixPrivs
+ * structure", which is 16 bytes long.
+ *
+ * We assume, for now, that the latter is true.
+ */
+ decode_unix_privs(tree, tvb, offset);
+ offset += 16;
+ }
+
+ return (max_offset)?max_offset:offset;
+}
+
+/* -------------------------- */
+static guint16
+decode_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint16 bitmap;
+
+ bitmap = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_item(tree, hf_afp_dir_bitmap, tvb, offset, 2,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_dir_bitmap);
+ }
+
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_Attributes , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ParentDirID , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_CreateDate , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ModDate , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_BackupDate , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_FinderInfo , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_LongName , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_ShortName , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_NodeID , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_OffspringCount , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_OwnerID , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_GroupID , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_AccessRights , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_UTF8Name , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_bitmap_UnixPrivs , tvb, offset, 2,FALSE);
+
+ return bitmap;
+}
+
+/* -------------------------- */
+static guint16
+decode_dir_attribute(proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint16 attribute;
+
+ attribute = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, 2,
+ "Directory Attributes: 0x%04x", attribute);
+ sub_tree = proto_item_add_subtree(item, ett_afp_dir_attribute);
+ }
+ proto_tree_add_item(sub_tree, hf_afp_dir_attribute_Invisible , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_attribute_IsExpFolder , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_attribute_System , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_attribute_Mounted , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_attribute_InExpFolder , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_attribute_BackUpNeeded , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_attribute_RenameInhibit, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_dir_attribute_DeleteInhibit, tvb, offset, 2,FALSE);
+
+ return(attribute);
+}
+
+/* -------------------------- */
+static gint
+parse_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset, guint16 bitmap)
+{
+ guint16 snameoff = 0;
+ gint max_offset = 0;
+
+ gint org_offset = offset;
+
+ if ((bitmap & kFPAttributeBit)) {
+ decode_dir_attribute(tree, tvb, offset);
+ offset += 2;
+ }
+ if ((bitmap & kFPParentDirIDBit)) {
+ proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+ if ((bitmap & kFPCreateDateBit)) {
+ print_date(tree, hf_afp_creation_date,tvb, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPModDateBit)) {
+ print_date(tree, hf_afp_modification_date,tvb, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPBackupDateBit)) {
+ print_date(tree, hf_afp_backup_date,tvb, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPFinderInfoBit)) {
+ proto_tree_add_item(tree, hf_afp_finder_info,tvb, offset, 32, FALSE);
+ offset += 32;
+ }
+ if ((bitmap & kFPLongNameBit)) {
+ gint tp_ofs;
+
+ tp_ofs = parse_long_filename(tree, tvb, offset, org_offset);
+ max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+
+ offset += 2;
+ }
+ if ((bitmap & kFPShortNameBit)) {
+ snameoff = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_short_name_offset,tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ if ((bitmap & kFPNodeIDBit)) {
+ proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+ if ((bitmap & kFPOffspringCountBit)) {
+ proto_tree_add_item(tree, hf_afp_dir_offspring, tvb, offset, 2,FALSE);
+ offset += 2; /* error in AFP3.0.pdf */
+ }
+ if ((bitmap & kFPOwnerIDBit)) {
+ proto_tree_add_item(tree, hf_afp_dir_OwnerID, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ if ((bitmap & kFPGroupIDBit)) {
+ proto_tree_add_item(tree, hf_afp_dir_GroupID, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ if ((bitmap & kFPAccessRightsBit)) {
+ decode_access_rights(tree, tvb, hf_afp_dir_ar, offset);
+ offset += 4;
+ }
+ if ((bitmap & kFPUTF8NameBit)) {
+ gint tp_ofs;
+
+ tp_ofs = parse_UTF8_filename(tree, tvb, offset, org_offset);
+ max_offset = (tp_ofs >max_offset)?tp_ofs:max_offset;
+ offset += 6;
+ }
+ if ((bitmap & kFPUnixPrivsBit)) {
+ /*
+ * XXX - the AFP 3.0 spec says this is "Four bytes", but
+ * also says the privileges are "stored in an FPUnixPrivs
+ * structure", which is 16 bytes long.
+ *
+ * We assume, for now, that the latter is true.
+ */
+ decode_unix_privs(tree, tvb, offset);
+ offset += 16;
+ }
+ return (max_offset)?max_offset:offset;
+}
+
+/* -------------------------- */
+static gchar *
+name_in_bitmap(tvbuff_t *tvb, gint offset, guint16 bitmap, int isdir)
+{
+ gchar *name;
+ gint org_offset = offset;
+ guint16 nameoff;
+ guint8 len;
+ guint16 len16;
+ gint tp_ofs;
+
+ if ((bitmap & kFPAttributeBit)) /* 0 */
+ offset += 2;
+ if ((bitmap & kFPParentDirIDBit)) /* 1 */
+ offset += 4;
+ if ((bitmap & kFPCreateDateBit)) /* 2 */
+ offset += 4;
+ if ((bitmap & kFPModDateBit)) /* 3 */
+ offset += 4;
+ if ((bitmap & kFPBackupDateBit)) /* 4 */
+ offset += 4;
+ if ((bitmap & kFPFinderInfoBit)) /* 5 */
+ offset += 32;
+
+ if ((bitmap & kFPLongNameBit)) { /* 6 */
+ nameoff = tvb_get_ntohs(tvb, offset);
+ if (nameoff) {
+ tp_ofs = nameoff +org_offset;
+ len = tvb_get_guint8(tvb, tp_ofs);
+ tp_ofs++;
+ name = tvb_get_string(tvb, tp_ofs, len);
+ return name;
+ }
+ offset += 2;
+ }
+
+ if ((bitmap & kFPShortNameBit)) /* 7 */
+ offset += 2;
+ if ((bitmap & kFPNodeIDBit)) /* 8 */
+ offset += 4;
+
+ if (isdir) {
+ if ((bitmap & kFPOffspringCountBit)) /* 9 */
+ offset += 2;
+ if ((bitmap & kFPOwnerIDBit)) /* 10*/
+ offset += 4;
+ if ((bitmap & kFPGroupIDBit)) /* 11*/
+ offset += 4;
+ if ((bitmap & kFPAccessRightsBit)) /* 12*/
+ offset += 4;
+ }
+ else {
+ if ((bitmap & kFPDataForkLenBit)) /* 9 */
+ offset += 4;
+ if ((bitmap & kFPRsrcForkLenBit)) /* 10*/
+ offset += 4;
+ if ((bitmap & kFPExtDataForkLenBit)) /* 11*/
+ offset += 8;
+ if ((bitmap & kFPLaunchLimitBit)) /* 12*/
+ offset += 2; /* FIXME ? */
+ }
+
+ if ((bitmap & kFPUTF8NameBit)) { /* 13 */
+ nameoff = tvb_get_ntohs(tvb, offset);
+ if (nameoff) {
+ tp_ofs = nameoff +org_offset +4;
+ len16 = tvb_get_ntohs(tvb, tp_ofs);
+ tp_ofs += 2;
+ name = tvb_get_string(tvb, tp_ofs, len16);
+ return name;
+ }
+ }
+ return NULL;
+}
+
+/* -------------------------- */
+static gchar *
+name_in_dbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
+{
+ gchar *name;
+
+ name = name_in_bitmap(tvb, offset, bitmap, 1);
+ if (name != NULL)
+ return name;
+ /*
+ check UTF8 name
+ */
+
+ return name;
+}
+
+/* -------------------------- */
+static gchar *
+name_in_fbitmap(tvbuff_t *tvb, gint offset, guint16 bitmap)
+{
+ gchar *name;
+
+ name = name_in_bitmap(tvb, offset, bitmap, 0);
+ if (name != NULL)
+ return name;
+ /*
+ check UTF8 name
+ */
+
+ return name;
+}
+
+/* -------------------------- */
+static gint
+decode_vol_did(proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ Vol = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ Did = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+ offset += 4;
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+decode_vol_did_file_dir_bitmap (proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ offset = decode_vol_did(tree, tvb, offset);
+
+ decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ decode_dir_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ return offset;
+}
+
+/* ------------------------ */
+static gchar *
+get_name(tvbuff_t *tvb, int offset, int type)
+{
+ int len;
+ gchar *string;
+
+ switch (type) {
+ case 1:
+ case 2:
+ len = tvb_get_guint8(tvb, offset);
+ offset++;
+ string = tvb_format_text(tvb,offset, len);
+ break;
+ case 3:
+ len = tvb_get_ntohs(tvb, offset +4);
+ offset += 6;
+ string = tvb_format_text(tvb,offset, len);
+ break;
+ default:
+ string = "unknow type";
+ break;
+ }
+ return string;
+}
+/* -------------------------- */
+static gint
+decode_name_label (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset, const gchar *label)
+{
+ int len;
+ int header;
+ gchar *name;
+ guint8 type;
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+
+ type = tvb_get_guint8(tvb, offset);
+ if (type == 3) {
+ header = 7;
+ len = tvb_get_ntohs(tvb, offset +5);
+ }
+ else {
+ header = 2;
+ len = tvb_get_guint8(tvb, offset +1);
+ }
+ name = get_name(tvb, offset +1, type);
+
+ if (pinfo && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": Vol=%u Did=%u", Vol, Did);
+ if (len) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Name=%s", name);
+ }
+ }
+
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, len +header, label, name);
+ sub_tree = proto_item_add_subtree(item, ett_afp_path_name);
+
+ proto_tree_add_item( sub_tree, hf_afp_path_type, tvb, offset, 1,FALSE);
+ offset++;
+ if (type == 3) {
+ proto_tree_add_item( sub_tree, hf_afp_path_unicode_hint, tvb, offset, 4,FALSE);
+ offset += 4;
+ proto_tree_add_item( sub_tree, hf_afp_path_unicode_len, tvb, offset, 2,FALSE);
+ offset += 2;
+ }
+ else {
+ proto_tree_add_item( sub_tree, hf_afp_path_len, tvb, offset, 1,FALSE);
+ offset++;
+ }
+
+ proto_tree_add_string(sub_tree, hf_afp_path_name, tvb, offset, len,name);
+ }
+ else
+ offset += header;
+
+ return offset +len;
+}
+
+/* -------------------------- */
+static gint
+decode_name (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, gint offset)
+{
+ return decode_name_label(tree, pinfo, tvb, offset, "Path: %s");
+}
+
+/* -------------------------- */
+static void
+add_info_fork(tvbuff_t *tvb, packet_info *pinfo, gint offset)
+{
+ guint16 ofork;
+
+ ofork = tvb_get_ntohs(tvb, offset);
+ if (ofork && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": Fork=%u", ofork);
+ }
+}
+
+/* -------------------------- */
+static void
+add_info_vol(tvbuff_t *tvb, packet_info *pinfo, gint offset)
+{
+ guint16 vol;
+
+ vol = tvb_get_ntohs(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": Vol=%u", vol);
+ }
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ int len;
+
+ PAD(1);
+
+ decode_vol_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ len = tvb_get_guint8(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ const gchar *rep;
+ rep = get_name(tvb, offset, 2);
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", rep);
+ }
+
+ if (!tree)
+ return offset;
+
+ proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
+ offset += len +1;
+
+ len = tvb_reported_length_remaining(tvb,offset);
+ if (len >= 8) {
+ /* optionnal password */
+ proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, 8,FALSE);
+ offset += 8;
+ }
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_open_vol(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ guint16 bitmap;
+
+ if (!tree)
+ return offset;
+ bitmap = decode_vol_bitmap(tree, tvb, offset);
+ offset += 2;
+ offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_reply_afp_get_server_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ guint8 num;
+ guint8 len;
+ guint8 flag;
+ guint8 i;
+ proto_tree *sub_tree = NULL;
+ proto_tree *flag_tree;
+ proto_item *item;
+ proto_item *ti;
+
+ if (!tree)
+ return offset;
+
+ print_date(tree, hf_afp_server_time,tvb, offset);
+ offset += 4;
+
+ num = tvb_get_guint8(tvb, offset);
+ item = proto_tree_add_text(tree, tvb, offset, 1, "Volumes : %d", num);
+ sub_tree = proto_item_add_subtree(item, ett_afp_server_vol);
+ offset++;
+
+ for (i = 0; i < num; i++) {
+ const gchar *rep;
+
+ item = proto_tree_add_text(sub_tree, tvb, offset, -1,"Volume");
+ tree = proto_item_add_subtree(item, ett_afp_vol_list);
+
+ flag = tvb_get_guint8(tvb, offset);
+
+ ti = proto_tree_add_text(tree, tvb, offset , 1,"Flags : 0x%02x", flag);
+ flag_tree = proto_item_add_subtree(ti, ett_afp_vol_flag);
+ proto_tree_add_item(flag_tree, hf_afp_vol_flag_passwd, tvb, offset, 1,FALSE);
+ proto_tree_add_item(flag_tree, hf_afp_vol_flag_unix_priv ,tvb, offset, 1,FALSE);
+ offset++;
+
+ len = tvb_get_guint8(tvb, offset) +1;
+ rep = get_name(tvb, offset, 2);
+ proto_item_set_text(item, rep);
+ proto_item_set_len(item, len +1);
+
+ proto_tree_add_item(tree, hf_afp_vol_name, tvb, offset, 1,FALSE);
+
+ offset += len;
+ }
+ return offset;
+}
+
+/* **************************
+ next calls use the same format :
+ 1 pad byte
+ volume id
+ AFP_FLUSH
+ AFP_CLOSEVOL
+ AFP_OPENDT
+*/
+static gint
+dissect_query_afp_with_vol_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+
+ if (!tree)
+ return offset;
+ PAD(1);
+
+ proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+ offset += 2;
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+
+ proto_tree_add_item(tree, hf_afp_fork_type, tvb, offset, 1,FALSE);
+ offset++;
+
+ offset = decode_vol_did(tree, tvb, offset);
+
+ decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+ if (tree) {
+ item = proto_tree_add_item(tree, hf_afp_access_mode, tvb, offset, 2,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_access_mode);
+
+ proto_tree_add_item(sub_tree, hf_afp_access_read , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_access_write , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_access_deny_read , tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_access_deny_write, tvb, offset, 2,FALSE);
+ }
+ offset += 2;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_open_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ guint16 f_bitmap;
+
+ f_bitmap = decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ add_info_fork(tvb, pinfo, offset);
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_enumerate_ext2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ offset = decode_vol_did_file_dir_bitmap(tree, tvb, offset);
+
+ proto_tree_add_item(tree, hf_afp_req_count, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_start_index32, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_max_reply_size32, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ offset = decode_vol_did_file_dir_bitmap(tree, tvb, offset);
+
+ proto_tree_add_item(tree, hf_afp_req_count, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_start_index, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_max_reply_size, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ return offset;
+}
+
+/* -------------------------- */
+static int
+loop_record(tvbuff_t *tvb, proto_tree *ptree, gint offset,
+ int count, guint16 d_bitmap, guint16 f_bitmap, int add, int ext)
+{
+ proto_tree *tree = NULL;
+ proto_item *item;
+ gchar *name;
+ guint8 flags;
+ guint size;
+ gint org;
+ int i;
+ int decal;
+
+ for (i = 0; i < count; i++) {
+ org = offset;
+ if (ext) {
+ size = tvb_get_ntohs(tvb, offset) +add *2;
+ decal = 2;
+ }
+ else {
+ size = tvb_get_guint8(tvb, offset) +add;
+ decal = 1;
+ }
+ if (!size)
+ return offset; /* packet is malformed */
+ flags = tvb_get_guint8(tvb, offset +decal);
+
+ decal += (ext)?2:1;
+
+ if (ptree) {
+ if (flags) {
+ name = name_in_dbitmap(tvb, offset +decal, d_bitmap);
+ }
+ else {
+ name = name_in_fbitmap(tvb, offset +decal, f_bitmap);
+ }
+ if (name) {
+ item = proto_tree_add_text(ptree, tvb, offset, size, "%s", name);
+ g_free(name);
+ }
+ else {
+ item = proto_tree_add_text(ptree, tvb, offset, size, "line %d", i+1);
+ }
+ tree = proto_item_add_subtree(item, ett_afp_enumerate_line);
+ }
+ if (ext) {
+ proto_tree_add_item(tree, hf_afp_struct_size16, tvb, offset, 2,FALSE);
+ offset += 2;
+ }
+ else {
+ proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
+ offset++;
+ }
+
+ proto_tree_add_item(tree, hf_afp_file_flag, tvb, offset, 1,FALSE);
+ offset++;
+ if (ext) {
+ PAD(1);
+ }
+ if (flags) {
+ offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
+ }
+ else {
+ offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
+ }
+ if ((offset & 1))
+ PAD(1);
+ offset = org +size; /* play safe */
+ }
+ return offset;
+}
+/* ------------------------- */
+static gint
+reply_enumerate(tvbuff_t *tvb, proto_tree *tree, gint offset, int ext)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ int count;
+ guint16 f_bitmap;
+ guint16 d_bitmap;
+
+ f_bitmap = decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ d_bitmap = decode_dir_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ count = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_item(tree, hf_afp_req_count, tvb, offset, 2,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_enumerate);
+ }
+ offset += 2;
+
+ return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap,0, ext);
+}
+
+/* ------------------------- */
+static gint
+dissect_reply_afp_enumerate(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ return reply_enumerate(tvb, tree, offset, 0);
+}
+
+/* **************************/
+static gint
+dissect_reply_afp_enumerate_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ return reply_enumerate(tvb, tree, offset, 1);
+}
+
+/* **************************/
+static gint
+catsearch_spec(tvbuff_t *tvb, proto_tree *ptree, gint offset, int ext, guint32 bitmap, const gchar *label)
+{
+ proto_tree *tree = NULL;
+ proto_item *item;
+ guint16 size;
+ gint org;
+
+ org = offset;
+
+ if (ext) {
+ size = tvb_get_ntohs(tvb, offset) +2;
+ }
+ else {
+ size = tvb_get_guint8(tvb, offset) +2;
+ }
+
+ item = proto_tree_add_text(ptree, tvb, offset, size, label);
+ tree = proto_item_add_subtree(item, ett_afp_cat_spec);
+
+ if (ext) {
+ proto_tree_add_item(tree, hf_afp_struct_size16, tvb, offset, 2,FALSE);
+ offset += 2;
+ }
+ else {
+ proto_tree_add_item(tree, hf_afp_struct_size, tvb, offset, 1,FALSE);
+ offset++;
+ PAD(1);
+ }
+
+ offset = parse_file_bitmap(tree, tvb, offset, (guint16) bitmap,0);
+ offset = org +size;
+
+ return offset;
+}
+
+/* ------------------------- */
+static gint
+query_catsearch(tvbuff_t *tvb, proto_tree *ptree, gint offset, int ext)
+{
+ proto_tree *tree = NULL, *sub_tree;
+ proto_item *item;
+ guint16 f_bitmap;
+ guint16 d_bitmap;
+ guint32 r_bitmap;
+
+ if (!ptree)
+ return offset;
+ PAD(1);
+
+ proto_tree_add_item(ptree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(ptree, hf_afp_cat_req_matches, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ptree, hf_afp_reserved, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ptree, hf_afp_cat_position, tvb, offset, 16,FALSE);
+ offset += 16;
+
+ f_bitmap = decode_file_bitmap(ptree, tvb, offset);
+ offset += 2;
+
+ d_bitmap = decode_dir_bitmap(ptree, tvb, offset);
+ offset += 2;
+
+ r_bitmap = tvb_get_ntohl(tvb, offset);
+ if (ptree) {
+ item = proto_tree_add_item(ptree, hf_afp_file_bitmap, tvb, offset, 4,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_cat_r_bitmap);
+
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_Attributes , tvb, offset, 4,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_ParentDirID , tvb, offset, 4,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_CreateDate , tvb, offset, 4,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_ModDate , tvb, offset, 4,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_BackupDate , tvb, offset, 4,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_FinderInfo , tvb, offset, 4,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_LongName , tvb, offset, 4,FALSE);
+
+ if (d_bitmap == 0) {
+ /* Only for file-only searches */
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_DataForkLen , tvb, offset, 4,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_RsrcForkLen , tvb, offset, 4,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_ExtDataForkLen , tvb, offset, 4,FALSE);
+ }
+ if (f_bitmap == 0) {
+ /* Only for directory-only searches */
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_OffspringCount , tvb, offset, 4,FALSE);
+ }
+
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_UTF8Name , tvb, offset, 4,FALSE);
+
+ if (d_bitmap == 0) {
+ /* Only for file-only searches */
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_ExtRsrcForkLen , tvb, offset, 4,FALSE);
+ }
+ proto_tree_add_item(sub_tree, hf_afp_request_bitmap_PartialNames , tvb, offset, 4,FALSE);
+ }
+ offset += 4;
+
+ /* spec 1 */
+ offset = catsearch_spec(tvb, ptree, offset, ext, r_bitmap, "Spec 1");
+
+ /* spec 2 */
+ offset = catsearch_spec(tvb, ptree, offset, ext, r_bitmap, "Spec 2");
+
+ return offset;
+}
+
+/* ------------------------- */
+static gint
+dissect_query_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ptree, gint offset)
+{
+ return query_catsearch(tvb, ptree, offset, 0);
+
+}
+/* **************************/
+static gint
+dissect_query_afp_cat_search_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *ptree, gint offset)
+{
+ return query_catsearch(tvb, ptree, offset, 1);
+
+}
+
+/* **************************/
+static gint
+reply_catsearch(tvbuff_t *tvb, proto_tree *tree, gint offset, int ext)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint16 f_bitmap;
+ guint16 d_bitmap;
+ int count;
+
+ proto_tree_add_item(tree, hf_afp_cat_position, tvb, offset, 16,FALSE);
+ offset += 16;
+
+ f_bitmap = decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ d_bitmap = decode_dir_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ count = tvb_get_ntohl(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_item(tree, hf_afp_cat_count, tvb, offset, 4,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_cat_search);
+ }
+ offset += 4;
+
+ return loop_record(tvb,sub_tree, offset, count, d_bitmap, f_bitmap, 2, ext);
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_cat_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ return reply_catsearch(tvb, tree, offset, 0);
+}
+
+/* **************************/
+static gint
+dissect_reply_afp_cat_search_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ return reply_catsearch(tvb, tree, offset, 1);
+}
+
+/* **************************/
+static gint
+dissect_query_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1)
+ add_info_vol(tvb, pinfo, offset);
+
+ proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ decode_vol_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ return offset;
+}
+
+/* ------------------------ */
+static gint
+dissect_reply_afp_get_vol_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ guint16 bitmap;
+
+ bitmap = decode_vol_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
+
+ return offset;
+}
+
+/* **************************/
+static gint
+dissect_query_afp_set_vol_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ guint16 bitmap;
+
+ PAD(1)
+
+ add_info_vol(tvb, pinfo, offset);
+ proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ bitmap = decode_vol_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ offset = parse_vol_bitmap(tree, tvb, offset, bitmap);
+
+ return offset;
+}
+
+/* ***************************/
+static gint
+decode_uam_parameters(const char *uam, int len_uam, tvbuff_t *tvb, proto_tree *tree, gint offset)
+{
+ int len;
+
+ if (!strncasecmp(uam, "Cleartxt passwrd", len_uam)) {
+ if ((offset & 1))
+ PAD(1);
+
+ len = 8; /* tvb_strsize(tvb, offset);*/
+ proto_tree_add_item(tree, hf_afp_passwd, tvb, offset, len,FALSE);
+ offset += len;
+ }
+ else if (!strncasecmp(uam, "DHCAST128", len_uam)) {
+ if ((offset & 1))
+ PAD(1);
+
+ len = 16;
+ proto_tree_add_item(tree, hf_afp_random, tvb, offset, len,FALSE);
+ offset += len;
+ }
+ else if (!strncasecmp(uam, "2-Way Randnum exchange", len_uam)) {
+ /* nothing */
+ return offset;
+ }
+ return offset;
+}
+
+/* ---------------- */
+static gint
+dissect_query_afp_login(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ int len;
+ int len_uam;
+ const char *uam;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_AFPVersion, tvb, offset, 1,FALSE);
+ offset += len +1;
+ len_uam = tvb_get_guint8(tvb, offset);
+ uam = tvb_get_ptr(tvb, offset +1, len_uam);
+ proto_tree_add_item(tree, hf_afp_UAM, tvb, offset, 1,FALSE);
+ offset += len_uam +1;
+
+ if (!strncasecmp(uam, "No User Authent", len_uam)) {
+ return offset;
+ }
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_user, tvb, offset, 1,FALSE);
+ offset += len +1;
+
+ return decode_uam_parameters(uam, len_uam, tvb, tree, offset);
+}
+
+/* ***************************/
+static gint
+dissect_query_afp_login_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ int len;
+ int len_uam;
+ const char *uam;
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_login_flags, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_AFPVersion, tvb, offset, 1,FALSE);
+ offset += len +1;
+
+ len_uam = tvb_get_guint8(tvb, offset);
+ uam = tvb_get_ptr(tvb, offset +1, len_uam);
+ proto_tree_add_item(tree, hf_afp_UAM, tvb, offset, 1,FALSE);
+ offset += len_uam +1;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_user_type, tvb, offset, 1,FALSE);
+ offset++;
+ /* only type 3 */
+ len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_user_len, tvb, offset, 2,FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_afp_user_name, tvb, offset, len,FALSE);
+ offset += len;
+
+ /* directory service */
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_path_type, tvb, offset, 1,FALSE);
+ offset++;
+ /* FIXME use 16 bit len + unicode from smb dissector */
+ switch (type) {
+ case 1:
+ case 2:
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_path_len, tvb, offset, 1,FALSE);
+ offset++;
+ proto_tree_add_item(tree, hf_afp_path_name, tvb, offset, len,FALSE);
+ offset += len;
+ break;
+ case 3:
+ len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item( tree, hf_afp_path_unicode_len, tvb, offset, 2,FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_afp_path_name, tvb, offset, len,FALSE);
+ offset += len;
+ break;
+ default:
+ break;
+ }
+
+ return decode_uam_parameters(uam, len_uam, tvb, tree, offset);
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_write(tvbuff_t *tvb, packet_info *pinfo , proto_tree *tree, gint offset)
+{
+ int param;
+ gint col_info = check_col(pinfo->cinfo, COL_INFO);
+
+
+ proto_tree_add_item(tree, hf_afp_flag, tvb, offset, 1,FALSE);
+ offset += 1;
+
+ add_info_fork(tvb, pinfo, offset);
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_offset, tvb, offset, 4,FALSE);
+ if (col_info) {
+ param = tvb_get_ntohl(tvb, offset);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Offset=%d", param);
+ }
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_rw_count, tvb, offset, 4,FALSE);
+ if (col_info) {
+ param = tvb_get_ntohl(tvb, offset);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Size=%d", param);
+ }
+ offset += 4;
+
+ return offset;
+}
+
+static gint
+dissect_reply_afp_write(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_last_written, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_write_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_flag, tvb, offset, 1,FALSE);
+ offset += 1;
+
+ add_info_fork(tvb, pinfo, offset);
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_offset64, tvb, offset, 8,FALSE);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_afp_rw_count64, tvb, offset, 8,FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+static gint
+dissect_reply_afp_write_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_last_written64, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_read(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ int param;
+ gint col_info = check_col(pinfo->cinfo, COL_INFO);
+
+ PAD(1);
+
+ add_info_fork(tvb, pinfo, offset);
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_offset, tvb, offset, 4,FALSE);
+ if (col_info) {
+ param = tvb_get_ntohl(tvb, offset);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Offset=%d", param);
+ }
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_rw_count, tvb, offset, 4,FALSE);
+ if (col_info) {
+ param = tvb_get_ntohl(tvb, offset);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Size=%d", param);
+ }
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_newline_mask, tvb, offset, 1,FALSE);
+ offset++;
+
+ proto_tree_add_item(tree, hf_afp_newline_char, tvb, offset, 1,FALSE);
+ offset++;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_read_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ PAD(1);
+
+ add_info_fork(tvb, pinfo, offset);
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_offset64, tvb, offset, 8,FALSE);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_afp_rw_count64, tvb, offset, 8,FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+/* **************************
+ Open desktop call
+ query is the same than AFP_FLUSH, AFP_CLOSEVOL
+
+*/
+static gint
+dissect_reply_afp_open_dt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+/* **************************
+ no reply
+*/
+static gint
+dissect_query_afp_close_dt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+/* **************************
+ calls using the same format :
+ 1 pad byte
+ fork number
+ AFP_FLUSHFORK
+ AFP_CLOSEFORK
+*/
+static gint
+dissect_query_afp_with_fork(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ PAD(1);
+ add_info_fork(tvb, pinfo, offset);
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ PAD(1);
+ offset = decode_vol_did_file_dir_bitmap(tree, tvb, offset);
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_fldr_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ guint8 flags;
+ guint16 f_bitmap, d_bitmap;
+
+ f_bitmap = decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ d_bitmap = decode_dir_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ flags = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_file_flag, tvb, offset, 1,FALSE);
+ offset++;
+ PAD(1);
+ if (flags) {
+ offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
+ }
+ else {
+ offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
+ }
+ return offset;
+}
+
+/* **************************
+ no reply
+*/
+static gint
+dissect_query_afp_set_fldr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ guint16 f_bitmap;
+
+ PAD(1);
+ offset = decode_vol_did(tree, tvb, offset);
+
+ f_bitmap = decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ if ((offset & 1))
+ PAD(1);
+ /* did:name can be a file or a folder but only the intersection between
+ * file bitmap and dir bitmap can be set.
+ * Well it's in afp spec, but clients (Mac) are setting 'file only' bits with this call
+ * (WriteInhibit for example).
+ */
+ offset = parse_file_bitmap(tree, tvb, offset, f_bitmap, 1);
+
+ return offset;
+}
+
+/* **************************
+ no reply
+*/
+static gint
+dissect_query_afp_set_file_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ guint16 f_bitmap;
+
+ PAD(1);
+ offset = decode_vol_did(tree, tvb, offset);
+
+ f_bitmap = decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ if ((offset & 1))
+ PAD(1);
+ offset = parse_file_bitmap(tree, tvb, offset, f_bitmap, 0);
+
+ return offset;
+}
+
+/* **************************
+ no reply
+*/
+static gint
+dissect_query_afp_set_dir_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ guint16 d_bitmap;
+
+ PAD(1);
+ offset = decode_vol_did(tree, tvb, offset);
+
+ d_bitmap = decode_dir_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ if ((offset & 1))
+ PAD(1);
+ offset = parse_dir_bitmap(tree, tvb, offset, d_bitmap);
+
+ offset += 4;
+ return offset;
+}
+
+/* **************************
+ AFP_DELETE
+ AFP_CREATE_DIR
+ */
+static gint
+dissect_query_afp_create_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ PAD(1);
+ offset = decode_vol_did(tree, tvb, offset);
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+ return offset;
+}
+
+/* --------------------------
+ AFP_MOVE
+*/
+static gint
+dissect_reply_afp_create_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_create_dir(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+/* **************************
+ no reply
+*/
+static gint
+dissect_query_afp_delete_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+/* **************************
+ same reply as get_fork_param
+*/
+static gint
+dissect_query_afp_resolve_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_vol_id, tvb, offset, 2,FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_afp_file_id, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_fork_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ add_info_fork(tvb, pinfo, offset);
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_fork_param(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ guint16 f_bitmap;
+
+ f_bitmap = decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ offset = parse_file_bitmap(tree, tvb, offset, f_bitmap,0);
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_set_fork_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ guint16 bitmap;
+ int param;
+
+ PAD(1);
+ add_info_fork(tvb, pinfo, offset);
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ bitmap = decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ if ((bitmap & kFPExtDataForkLenBit) || (bitmap & kFPExtRsrcForkLenBit)) {
+ proto_tree_add_item(tree, hf_afp_ofork_len64, tvb, offset, 8, FALSE);
+ offset += 8;
+ }
+ else {
+ proto_tree_add_item(tree, hf_afp_ofork_len, tvb, offset, 4,FALSE);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ param = tvb_get_ntohl(tvb, offset);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Size=%d", param);
+ }
+ offset += 4;
+ }
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_move(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ offset = decode_vol_did(tree, tvb, offset);
+
+ proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ offset = decode_name_label(tree, pinfo, tvb, offset, "Source path: %s");
+ offset = decode_name_label(tree, NULL, tvb, offset, "Dest dir: %s");
+ offset = decode_name_label(tree, NULL, tvb, offset, "New name: %s");
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_exchange_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ offset = decode_vol_did(tree, tvb, offset);
+
+ proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ offset = decode_name_label(tree, pinfo, tvb, offset, "Source path: %s");
+ offset = decode_name_label(tree, NULL, tvb, offset, "Dest path: %s");
+
+ return offset;
+}
+/* ************************** */
+static gint
+dissect_query_afp_copy_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+
+ PAD(1);
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, 6,"Source volume");
+ sub_tree = proto_item_add_subtree(item, ett_afp_vol_did);
+ }
+ offset = decode_vol_did(sub_tree, tvb, offset);
+
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, 6,"Dest volume");
+ sub_tree = proto_item_add_subtree(item, ett_afp_vol_did);
+ }
+ offset = decode_vol_did(sub_tree, tvb, offset);
+
+ offset = decode_name_label(tree, pinfo, tvb, offset, "Source path: %s");
+ offset = decode_name_label(tree, NULL, tvb, offset, "Dest dir: %s");
+ offset = decode_name_label(tree, NULL, tvb, offset, "New name: %s");
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_rename(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ offset = decode_vol_did(tree, tvb, offset);
+
+ offset = decode_name_label(tree, pinfo, tvb, offset, "Old name: %s");
+ offset = decode_name_label(tree, NULL, tvb, offset, "New name: %s");
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_byte_lock(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint8 flag;
+
+ flag = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, 1, "Flags: 0x%02x", flag);
+ sub_tree = proto_item_add_subtree(item, ett_afp_lock_flags);
+ }
+
+ proto_tree_add_item(sub_tree, hf_afp_lock_op, tvb, offset, 1,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_lock_from, tvb, offset, 1,FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_lock_offset, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_lock_len, tvb, offset, 4,FALSE);
+ offset += 4;
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_byte_lock(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_lock_range_start, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_byte_lock_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint8 flag;
+
+ flag = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, 1, "Flags: 0x%02x", flag);
+ sub_tree = proto_item_add_subtree(item, ett_afp_lock_flags);
+ }
+
+ proto_tree_add_item(sub_tree, hf_afp_lock_op, tvb, offset, 1,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_lock_from, tvb, offset, 1,FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_afp_ofork, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_lock_offset64, tvb, offset, 8,FALSE);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_afp_lock_len64, tvb, offset, 8,FALSE);
+ offset += 8;
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_byte_lock_ext(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_lock_range_start64, tvb, offset, 8,FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_add_cmt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ guint8 len;
+
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ if ((offset & 1))
+ PAD(1);
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_comment, tvb, offset, 1,FALSE);
+ offset += len +1;
+
+ return offset;
+}
+
+
+/* ************************** */
+static gint
+dissect_query_afp_get_cmt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_cmt(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ guint8 len;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_comment, tvb, offset, 1,FALSE);
+ offset += len +1;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_icon(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
+ offset += 1;
+ PAD(1);
+
+ proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_icon_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_icon_index, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_icon_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+
+ proto_tree_add_item(tree, hf_afp_icon_tag, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
+ offset += 1;
+
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_add_icon(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_file_type, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_icon_type, tvb, offset, 1,FALSE);
+ offset += 1;
+
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_icon_tag, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_icon_length, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+/* **************************
+ no reply
+*/
+static gint
+decode_dt_did(proto_tree *tree, tvbuff_t *tvb, gint offset)
+{
+ /* FIXME it's not volume but dt cf decode_name*/
+ Vol = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ Did = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_did, tvb, offset, 4,FALSE);
+ offset += 4;
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_query_afp_add_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ offset = decode_dt_did(tree, tvb, offset);
+
+ proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_appl_tag, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ return offset;
+}
+
+/* **************************
+ no reply
+*/
+static gint
+dissect_query_afp_rmv_appl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ offset = decode_dt_did(tree, tvb, offset);
+
+ proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_appl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+
+ PAD(1);
+ proto_tree_add_item(tree, hf_afp_dt_ref, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_afp_file_creator, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_appl_index, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ decode_file_bitmap(tree, tvb, offset);
+ offset += 2;
+
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_appl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_appl_tag, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_create_file(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_create_flag, tvb, offset, 1,FALSE);
+ offset++;
+
+ offset = decode_vol_did(tree, tvb, offset);
+
+ offset = decode_name(tree, pinfo, tvb, offset);
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_map_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree_add_item(tree, hf_afp_map_id_type, tvb, offset, 1,FALSE);
+ offset++;
+
+ proto_tree_add_item(tree, hf_afp_map_id, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_map_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+int len;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_map_name, tvb, offset, 1,FALSE);
+ offset += len +1;
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_map_name(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+int len;
+ proto_tree_add_item(tree, hf_afp_map_name_type, tvb, offset, 1,FALSE);
+ offset++;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_map_name, tvb, offset, 1,FALSE);
+ offset += len +1;
+
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_map_name(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+
+ proto_tree_add_item(tree, hf_afp_map_id, tvb, offset, 4,FALSE);
+ offset += 4;
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_disconnect_old_session(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+int len;
+
+ PAD(1);
+
+ proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
+ offset += 2;
+
+ len = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_session_token_len, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_afp_session_token, tvb, offset, len,FALSE);
+ offset += len;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_session_token(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+guint16 token;
+int len;
+
+ PAD(1);
+ token = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
+ offset += 2;
+ if (token == kLoginWithoutID) /* 0 */
+ return offset;
+
+ len = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_session_token_len, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ switch (token) {
+ case kLoginWithTimeAndID:
+ case kReconnWithTimeAndID:
+ proto_tree_add_item(tree, hf_afp_session_token_timestamp, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+
+ proto_tree_add_item(tree, hf_afp_session_token, tvb, offset, len,FALSE);
+ offset += len;
+
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_session_token(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+int len;
+int size;
+
+ /* FIXME spec and capture disagree : or it's 4 bytes with no token type, or it's 2 bytes */
+ size = 4;
+ if (size == 2) {
+ proto_tree_add_item(tree, hf_afp_session_token_type, tvb, offset, 2,FALSE);
+ offset += 2;
+ }
+ len = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_afp_session_token_len, tvb, offset, size,FALSE);
+ offset += size;
+
+ proto_tree_add_item(tree, hf_afp_session_token, tvb, offset, len,FALSE);
+ offset += len;
+
+ return offset;
+}
+
+/* ************************** */
+static gint
+dissect_query_afp_get_user_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint16 bitmap;
+
+
+ proto_tree_add_item(tree, hf_afp_user_flag, tvb, offset, 1,FALSE);
+ offset++;
+
+ proto_tree_add_item(tree, hf_afp_user_ID, tvb, offset, 4,FALSE);
+ offset += 4;
+
+ bitmap = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_item(tree, hf_afp_user_bitmap, tvb, offset, 2,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_user_bitmap);
+ proto_tree_add_item(sub_tree, hf_afp_user_bitmap_UID, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_user_bitmap_GID, tvb, offset, 2,FALSE);
+ }
+ offset += 2;
+
+ return offset;
+}
+
+/* -------------------------- */
+static gint
+dissect_reply_afp_get_user_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree *sub_tree = NULL;
+ proto_item *item;
+ guint16 bitmap;
+
+ bitmap = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ item = proto_tree_add_item(tree, hf_afp_user_bitmap, tvb, offset, 2,FALSE);
+ sub_tree = proto_item_add_subtree(item, ett_afp_user_bitmap);
+ proto_tree_add_item(sub_tree, hf_afp_user_bitmap_UID, tvb, offset, 2,FALSE);
+ proto_tree_add_item(sub_tree, hf_afp_user_bitmap_GID, tvb, offset, 2,FALSE);
+ }
+
+ offset += 2;
+ if ((bitmap & 1)) {
+ proto_tree_add_item(tree, hf_afp_user_ID, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+
+ if ((bitmap & 2)) {
+ proto_tree_add_item(tree, hf_afp_group_ID, tvb, offset, 4,FALSE);
+ offset += 4;
+ }
+ return offset;
+}
+
+/* ************************** */
+static void
+dissect_afp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct aspinfo *aspinfo = pinfo->private_data;
+ proto_tree *afp_tree = NULL;
+ proto_item *ti;
+ conversation_t *conversation;
+ gint offset = 0;
+ afp_request_key request_key, *new_request_key;
+ afp_request_val *request_val;
+ guint8 afp_command;
+
+ int len = tvb_reported_length_remaining(tvb,0);
+ gint col_info = check_col(pinfo->cinfo, COL_INFO);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AFP");
+ if (col_info)
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if (conversation == NULL)
+ {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+
+ request_key.conversation = conversation->index;
+ request_key.seq = aspinfo->seq;
+
+ request_val = (afp_request_val *) g_hash_table_lookup(
+ afp_request_hash, &request_key);
+
+ if (!request_val && !aspinfo->reply) {
+ afp_command = tvb_get_guint8(tvb, offset);
+ new_request_key = g_mem_chunk_alloc(afp_request_keys);
+ *new_request_key = request_key;
+
+ request_val = g_mem_chunk_alloc(afp_request_vals);
+ request_val->command = tvb_get_guint8(tvb, offset);
+
+ g_hash_table_insert(afp_request_hash, new_request_key,
+ request_val);
+ }
+
+ if (!request_val) { /* missing request */
+ if (col_info)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "[Reply without query?]");
+ return;
+ }
+
+ afp_command = request_val->command;
+ if (col_info) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ val_to_str(afp_command, CommandCode_vals,
+ "Unknown command (%u)"),
+ aspinfo->reply ? "reply" : "request");
+ if (aspinfo->reply && aspinfo->code != 0) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s (%d)",
+ val_to_str(aspinfo->code, asp_error_vals,
+ "Unknown error (%u)"), aspinfo->code);
+ }
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_afp, tvb, offset, -1,FALSE);
+ afp_tree = proto_item_add_subtree(ti, ett_afp);
+ }
+ if (!aspinfo->reply) {
+
+ proto_tree_add_uint(afp_tree, hf_afp_command, tvb,offset, 1, afp_command);
+ if (afp_command != tvb_get_guint8(tvb, offset))
+ {
+ /* we have the same conversation for different connections eg:
+ * ip1:2048 --> ip2:548
+ * ip1:2048 --> ip2:548 <RST>
+ * ....
+ * ip1:2048 --> ip2:548 <SYN> use the same port but it's a new session!
+ */
+ if (col_info) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "[Error!IP port reused, you need to split the capture file]");
+ return;
+ }
+ }
+ offset++;
+ switch(afp_command) {
+ case AFP_BYTELOCK:
+ offset = dissect_query_afp_byte_lock(tvb, pinfo, afp_tree, offset);break;
+ case AFP_BYTELOCK_EXT:
+ offset = dissect_query_afp_byte_lock_ext(tvb, pinfo, afp_tree, offset);break;
+ case AFP_OPENDT: /* same as close vol */
+ case AFP_FLUSH:
+ case AFP_CLOSEVOL:
+ offset = dissect_query_afp_with_vol_id(tvb, pinfo, afp_tree, offset);break;
+ case AFP_CLOSEDIR:
+ /* offset = dissect_query_afp_close_dir(tvb, pinfo, afp_tree, offset);break; */
+ break;
+ case AFP_CLOSEDT:
+ offset = dissect_query_afp_close_dt(tvb, pinfo, afp_tree, offset);break;
+ case AFP_FLUSHFORK: /* same packet as closefork */
+ case AFP_CLOSEFORK:
+ offset = dissect_query_afp_with_fork(tvb, pinfo, afp_tree, offset);break;
+ case AFP_COPYFILE:
+ offset = dissect_query_afp_copy_file(tvb, pinfo, afp_tree, offset);break;
+ case AFP_CREATEFILE:
+ offset = dissect_query_afp_create_file(tvb, pinfo, afp_tree, offset);break;
+ case AFP_DISCTOLDSESS:
+ offset = dissect_query_afp_disconnect_old_session(tvb, pinfo, afp_tree, offset);break;
+ case AFP_ENUMERATE_EXT2:
+ offset = dissect_query_afp_enumerate_ext2(tvb, pinfo, afp_tree, offset);break;
+ case AFP_ENUMERATE_EXT:
+ case AFP_ENUMERATE:
+ offset = dissect_query_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETFORKPARAM:
+ offset = dissect_query_afp_get_fork_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETSESSTOKEN:
+ offset = dissect_query_afp_get_session_token(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETUSERINFO:
+ offset = dissect_query_afp_get_user_info(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETSRVINFO:
+ /* offset = dissect_query_afp_get_server_info(tvb, pinfo, afp_tree, offset);break; */
+ case AFP_GETSRVPARAM:
+ break; /* no parameters */
+ case AFP_GETVOLPARAM:
+ offset = dissect_query_afp_get_vol_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_LOGIN_EXT:
+ offset = dissect_query_afp_login_ext(tvb, pinfo, afp_tree, offset);break;
+ case AFP_LOGIN:
+ offset = dissect_query_afp_login(tvb, pinfo, afp_tree, offset);break;
+ case AFP_LOGINCONT:
+ case AFP_LOGOUT:
+ break;
+ case AFP_MAPID:
+ offset = dissect_query_afp_map_id(tvb, pinfo, afp_tree, offset);break;
+ case AFP_MAPNAME:
+ offset = dissect_query_afp_map_name(tvb, pinfo, afp_tree, offset);break;
+ case AFP_MOVE:
+ offset = dissect_query_afp_move(tvb, pinfo, afp_tree, offset);break;
+ case AFP_OPENVOL:
+ offset = dissect_query_afp_open_vol(tvb, pinfo, afp_tree, offset);break;
+ case AFP_OPENDIR:
+ break;
+ case AFP_OPENFORK:
+ offset = dissect_query_afp_open_fork(tvb, pinfo, afp_tree, offset);break;
+ case AFP_READ:
+ offset = dissect_query_afp_read(tvb, pinfo, afp_tree, offset);break;
+ case AFP_READ_EXT:
+ offset = dissect_query_afp_read_ext(tvb, pinfo, afp_tree, offset);break;
+ case AFP_RENAME:
+ offset = dissect_query_afp_rename(tvb, pinfo, afp_tree, offset);break;
+ case AFP_SETDIRPARAM:
+ offset = dissect_query_afp_set_dir_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_SETFILEPARAM:
+ offset = dissect_query_afp_set_file_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_SETFORKPARAM:
+ offset = dissect_query_afp_set_fork_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_SETVOLPARAM:
+ offset = dissect_query_afp_set_vol_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_WRITE:
+ offset = dissect_query_afp_write(tvb, pinfo, afp_tree, offset);break;
+ case AFP_WRITE_EXT:
+ offset = dissect_query_afp_write_ext(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETFLDRPARAM:
+ offset = dissect_query_afp_get_fldr_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_SETFLDRPARAM:
+ offset = dissect_query_afp_set_fldr_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_CHANGEPW:
+ case AFP_GETSRVRMSG:
+ break;
+ case AFP_DELETE: /* same as create_id */
+ case AFP_CREATEDIR:
+ case AFP_CREATEID:
+ offset = dissect_query_afp_create_id(tvb, pinfo, afp_tree, offset);break;
+ case AFP_DELETEID:
+ offset = dissect_query_afp_delete_id(tvb, pinfo, afp_tree, offset);break;
+ case AFP_RESOLVEID:
+ offset = dissect_query_afp_resolve_id(tvb, pinfo, afp_tree, offset);break;
+ case AFP_EXCHANGEFILE:
+ offset = dissect_query_afp_exchange_file(tvb, pinfo, afp_tree, offset);break;
+ case AFP_CATSEARCH_EXT:
+ offset = dissect_query_afp_cat_search_ext(tvb, pinfo, afp_tree, offset);break;
+ case AFP_CATSEARCH:
+ offset = dissect_query_afp_cat_search(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETICON:
+ offset = dissect_query_afp_get_icon(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GTICNINFO:
+ offset = dissect_query_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break;
+ case AFP_ADDAPPL:
+ offset = dissect_query_afp_add_appl(tvb, pinfo, afp_tree, offset);break;
+ case AFP_RMVAPPL:
+ offset = dissect_query_afp_rmv_appl(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETAPPL:
+ offset = dissect_query_afp_get_appl(tvb, pinfo, afp_tree, offset);break;
+ case AFP_ADDCMT:
+ offset = dissect_query_afp_add_cmt(tvb, pinfo, afp_tree, offset);break;
+ case AFP_RMVCMT: /* same as get_cmt */
+ case AFP_GETCMT:
+ offset = dissect_query_afp_get_cmt(tvb, pinfo, afp_tree, offset);break;
+ case AFP_ADDICON:
+ offset = dissect_query_afp_add_icon(tvb, pinfo, afp_tree, offset);break;
+ break;
+ }
+ }
+ else {
+ proto_tree_add_uint(afp_tree, hf_afp_command, tvb, 0, 0, afp_command);
+ if (!len) {
+ /* for some calls if the reply is an error there's no data
+ */
+ return;
+ }
+ switch(afp_command) {
+ case AFP_BYTELOCK:
+ offset = dissect_reply_afp_byte_lock(tvb, pinfo, afp_tree, offset);break;
+ case AFP_BYTELOCK_EXT:
+ offset = dissect_reply_afp_byte_lock_ext(tvb, pinfo, afp_tree, offset);break;
+ case AFP_ENUMERATE_EXT2:
+ case AFP_ENUMERATE_EXT:
+ offset = dissect_reply_afp_enumerate_ext(tvb, pinfo, afp_tree, offset);break;
+ case AFP_ENUMERATE:
+ offset = dissect_reply_afp_enumerate(tvb, pinfo, afp_tree, offset);break;
+ case AFP_OPENVOL:
+ offset = dissect_reply_afp_open_vol(tvb, pinfo, afp_tree, offset);break;
+ case AFP_OPENFORK:
+ offset = dissect_reply_afp_open_fork(tvb, pinfo, afp_tree, offset);break;
+ case AFP_RESOLVEID:
+ case AFP_GETFORKPARAM:
+ offset =dissect_reply_afp_get_fork_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETUSERINFO:
+ offset = dissect_reply_afp_get_user_info(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETSRVPARAM:
+ offset = dissect_reply_afp_get_server_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_CREATEDIR:
+ offset = dissect_reply_afp_create_dir(tvb, pinfo, afp_tree, offset);break;
+ case AFP_MAPID:
+ offset = dissect_reply_afp_map_id(tvb, pinfo, afp_tree, offset);break;
+ case AFP_MAPNAME:
+ offset = dissect_reply_afp_map_name(tvb, pinfo, afp_tree, offset);break;
+ case AFP_MOVE: /* same as create_id */
+ case AFP_CREATEID:
+ offset = dissect_reply_afp_create_id(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETSESSTOKEN:
+ offset = dissect_reply_afp_get_session_token(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETVOLPARAM:
+ offset = dissect_reply_afp_get_vol_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETFLDRPARAM:
+ offset = dissect_reply_afp_get_fldr_param(tvb, pinfo, afp_tree, offset);break;
+ case AFP_OPENDT:
+ offset = dissect_reply_afp_open_dt(tvb, pinfo, afp_tree, offset);break;
+ case AFP_CATSEARCH_EXT:
+ offset = dissect_reply_afp_cat_search_ext(tvb, pinfo, afp_tree, offset);break;
+ case AFP_CATSEARCH:
+ offset = dissect_reply_afp_cat_search(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GTICNINFO:
+ offset = dissect_reply_afp_get_icon_info(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETAPPL:
+ offset = dissect_reply_afp_get_appl(tvb, pinfo, afp_tree, offset);break;
+ case AFP_GETCMT:
+ offset = dissect_reply_afp_get_cmt(tvb, pinfo, afp_tree, offset);break;
+ case AFP_WRITE:
+ offset = dissect_reply_afp_write(tvb, pinfo, afp_tree, offset);break;
+ case AFP_WRITE_EXT:
+ offset = dissect_reply_afp_write_ext(tvb, pinfo, afp_tree, offset);break;
+ }
+ }
+ if (tree && offset < len) {
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, afp_tree);
+ }
+}
+
+static void afp_reinit( void)
+{
+
+ if (afp_request_hash)
+ g_hash_table_destroy(afp_request_hash);
+ if (afp_request_keys)
+ g_mem_chunk_destroy(afp_request_keys);
+ if (afp_request_vals)
+ g_mem_chunk_destroy(afp_request_vals);
+
+ afp_request_hash = g_hash_table_new(afp_hash, afp_equal);
+
+ afp_request_keys = g_mem_chunk_new("afp_request_keys",
+ sizeof(afp_request_key),
+ afp_packet_init_count * sizeof(afp_request_key),
+ G_ALLOC_AND_FREE);
+ afp_request_vals = g_mem_chunk_new("afp_request_vals",
+ sizeof(afp_request_val),
+ afp_packet_init_count * sizeof(afp_request_val),
+ G_ALLOC_AND_FREE);
+
+}
+
+void
+proto_register_afp(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_afp_command,
+ { "Command", "afp.command",
+ FT_UINT8, BASE_DEC, VALS(CommandCode_vals), 0x0,
+ "AFP function", HFILL }},
+
+ { &hf_afp_pad,
+ { "Pad", "afp.pad",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "Pad Byte", HFILL }},
+
+ { &hf_afp_AFPVersion,
+ { "AFP Version", "afp.AFPVersion",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "Client AFP version", HFILL }},
+
+ { &hf_afp_UAM,
+ { "UAM", "afp.UAM",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "User Authentication Method", HFILL }},
+
+ { &hf_afp_user,
+ { "User", "afp.user",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "User", HFILL }},
+
+ { &hf_afp_user_type,
+ { "Type", "afp.user_type",
+ FT_UINT8, BASE_HEX, VALS(path_type_vals), 0,
+ "Type of user name", HFILL }},
+ { &hf_afp_user_len,
+ { "Len", "afp.user_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "User name length (unicode)", HFILL }},
+ { &hf_afp_user_name,
+ { "User", "afp.user_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "User name (unicode)", HFILL }},
+
+ { &hf_afp_passwd,
+ { "Password", "afp.passwd",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Password", HFILL }},
+
+ { &hf_afp_random,
+ { "Random number", "afp.random",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "UAM random number", HFILL }},
+
+ { &hf_afp_login_flags,
+ { "Flags", "afp.afp_login_flags",
+ FT_UINT16, BASE_HEX, NULL, 0 /* 0x0FFF*/,
+ "Login flags", HFILL }},
+
+ { &hf_afp_vol_bitmap,
+ { "Bitmap", "afp.vol_bitmap",
+ FT_UINT16, BASE_HEX, NULL, 0 /* 0x0FFF*/,
+ "Volume bitmap", HFILL }},
+
+ { &hf_afp_vol_bitmap_Attributes,
+ { "Attributes", "afp.vol_bitmap.attributes",
+ FT_BOOLEAN, 16, NULL, kFPVolAttributeBit,
+ "Volume attributes", HFILL }},
+
+ { &hf_afp_vol_attribute,
+ { "Attributes", "afp.vol_attributes",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Volume attributes", HFILL }},
+
+ { &hf_afp_vol_attribute_ReadOnly,
+ { "Read only", "afp.vol_attribute.read_only",
+ FT_BOOLEAN, 16, NULL, kReadOnly,
+ "Read only volume", HFILL }},
+
+ { &hf_afp_vol_attribute_HasVolumePassword,
+ { "Volume password", "afp.vol_attribute.passwd",
+ FT_BOOLEAN, 16, NULL, kHasVolumePassword,
+ "Has a volume password", HFILL }},
+
+ { &hf_afp_vol_attribute_SupportsFileIDs,
+ { "File IDs", "afp.vol_attribute.fileIDs",
+ FT_BOOLEAN, 16, NULL, kSupportsFileIDs,
+ "Supports file IDs", HFILL }},
+
+ { &hf_afp_vol_attribute_SupportsCatSearch,
+ { "Catalog search", "afp.vol_attribute.cat_search",
+ FT_BOOLEAN, 16, NULL, kSupportsCatSearch,
+ "Supports catalog search operations", HFILL }},
+
+ { &hf_afp_vol_attribute_SupportsBlankAccessPrivs,
+ { "Blank access privileges", "afp.vol_attribute.blank_access_privs",
+ FT_BOOLEAN, 16, NULL, kSupportsBlankAccessPrivs,
+ "Supports blank access privileges", HFILL }},
+
+ { &hf_afp_vol_attribute_SupportsUnixPrivs,
+ { "UNIX access privileges", "afp.vol_attribute.unix_privs",
+ FT_BOOLEAN, 16, NULL, kSupportsUnixPrivs,
+ "Supports UNIX access privileges", HFILL }},
+
+ { &hf_afp_vol_attribute_SupportsUTF8Names,
+ { "UTF-8 names", "afp.vol_attribute.utf8_names",
+ FT_BOOLEAN, 16, NULL, kSupportsUTF8Names,
+ "Supports UTF-8 names", HFILL }},
+
+ { &hf_afp_vol_bitmap_Signature,
+ { "Signature", "afp.vol_bitmap.signature",
+ FT_BOOLEAN, 16, NULL, kFPVolSignatureBit,
+ "Volume signature", HFILL }},
+
+ { &hf_afp_vol_bitmap_CreateDate,
+ { "Creation date", "afp.vol_bitmap.create_date",
+ FT_BOOLEAN, 16, NULL, kFPVolCreateDateBit,
+ "Volume creation date", HFILL }},
+
+ { &hf_afp_vol_bitmap_ModDate,
+ { "Modification date", "afp.vol_bitmap.mod_date",
+ FT_BOOLEAN, 16, NULL, kFPVolModDateBit,
+ "Volume modification date", HFILL }},
+
+ { &hf_afp_vol_bitmap_BackupDate,
+ { "Backup date", "afp.vol_bitmap.backup_date",
+ FT_BOOLEAN, 16, NULL, kFPVolBackupDateBit,
+ "Volume backup date", HFILL }},
+
+ { &hf_afp_vol_bitmap_ID,
+ { "ID", "afp.vol_bitmap.id",
+ FT_BOOLEAN, 16, NULL, kFPVolIDBit,
+ "Volume ID", HFILL }},
+
+ { &hf_afp_vol_bitmap_BytesFree,
+ { "Bytes free", "afp.vol_bitmap.bytes_free",
+ FT_BOOLEAN, 16, NULL, kFPVolBytesFreeBit,
+ "Volume free bytes", HFILL }},
+
+ { &hf_afp_vol_bitmap_BytesTotal,
+ { "Bytes total", "afp.vol_bitmap.bytes_total",
+ FT_BOOLEAN, 16, NULL, kFPVolBytesTotalBit,
+ "Volume total bytes", HFILL }},
+
+ { &hf_afp_vol_bitmap_Name,
+ { "Name", "afp.vol_bitmap.name",
+ FT_BOOLEAN, 16, NULL, kFPVolNameBit,
+ "Volume name", HFILL }},
+
+ { &hf_afp_vol_bitmap_ExtBytesFree,
+ { "Extended bytes free", "afp.vol_bitmap.ex_bytes_free",
+ FT_BOOLEAN, 16, NULL, kFPVolExtBytesFreeBit,
+ "Volume extended (>2GB) free bytes", HFILL }},
+
+ { &hf_afp_vol_bitmap_ExtBytesTotal,
+ { "Extended bytes total", "afp.vol_bitmap.ex_bytes_total",
+ FT_BOOLEAN, 16, NULL, kFPVolExtBytesTotalBit,
+ "Volume extended (>2GB) total bytes", HFILL }},
+
+ { &hf_afp_vol_bitmap_BlockSize,
+ { "Block size", "afp.vol_bitmap.block_size",
+ FT_BOOLEAN, 16, NULL, kFPVolBlockSizeBit,
+ "Volume block size", HFILL }},
+
+ { &hf_afp_dir_bitmap_Attributes,
+ { "Attributes", "afp.dir_bitmap.attributes",
+ FT_BOOLEAN, 16, NULL, kFPAttributeBit,
+ "Return attributes if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_ParentDirID,
+ { "DID", "afp.dir_bitmap.did",
+ FT_BOOLEAN, 16, NULL, kFPParentDirIDBit,
+ "Return parent directory ID if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_CreateDate,
+ { "Creation date", "afp.dir_bitmap.create_date",
+ FT_BOOLEAN, 16, NULL, kFPCreateDateBit,
+ "Return creation date if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_ModDate,
+ { "Modification date", "afp.dir_bitmap.mod_date",
+ FT_BOOLEAN, 16, NULL, kFPModDateBit,
+ "Return modification date if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_BackupDate,
+ { "Backup date", "afp.dir_bitmap.backup_date",
+ FT_BOOLEAN, 16, NULL, kFPBackupDateBit,
+ "Return backup date if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_FinderInfo,
+ { "Finder info", "afp.dir_bitmap.finder_info",
+ FT_BOOLEAN, 16, NULL, kFPFinderInfoBit,
+ "Return finder info if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_LongName,
+ { "Long name", "afp.dir_bitmap.long_name",
+ FT_BOOLEAN, 16, NULL, kFPLongNameBit,
+ "Return long name if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_ShortName,
+ { "Short name", "afp.dir_bitmap.short_name",
+ FT_BOOLEAN, 16, NULL, kFPShortNameBit,
+ "Return short name if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_NodeID,
+ { "File ID", "afp.dir_bitmap.fid",
+ FT_BOOLEAN, 16, NULL, kFPNodeIDBit,
+ "Return file ID if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_OffspringCount,
+ { "Offspring count", "afp.dir_bitmap.offspring_count",
+ FT_BOOLEAN, 16, NULL, kFPOffspringCountBit,
+ "Return offspring count if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_OwnerID,
+ { "Owner id", "afp.dir_bitmap.owner_id",
+ FT_BOOLEAN, 16, NULL, kFPOwnerIDBit,
+ "Return owner id if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_GroupID,
+ { "Group id", "afp.dir_bitmap.group_id",
+ FT_BOOLEAN, 16, NULL, kFPGroupIDBit,
+ "Return group id if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_AccessRights,
+ { "Access rights", "afp.dir_bitmap.access_rights",
+ FT_BOOLEAN, 16, NULL, kFPAccessRightsBit,
+ "Return access rights if directory", HFILL }},
+
+ { &hf_afp_dir_bitmap_UTF8Name,
+ { "UTF-8 name", "afp.dir_bitmap.UTF8_name",
+ FT_BOOLEAN, 16, NULL, kFPUTF8NameBit,
+ "Return UTF-8 name if diectory", HFILL }},
+
+ { &hf_afp_dir_bitmap_UnixPrivs,
+ { "UNIX privileges", "afp.dir_bitmap.unix_privs",
+ FT_BOOLEAN, 16, NULL, kFPUnixPrivsBit,
+ "Return UNIX privileges if directory", HFILL }},
+
+ { &hf_afp_dir_attribute_Invisible,
+ { "Invisible", "afp.dir_attribute.invisible",
+ FT_BOOLEAN, 16, NULL, kFPInvisibleBit,
+ "Directory is not visible", HFILL }},
+
+ { &hf_afp_dir_attribute_IsExpFolder,
+ { "Share point", "afp.dir_attribute.share",
+ FT_BOOLEAN, 16, NULL, kFPMultiUserBit,
+ "Directory is a share point", HFILL }},
+
+ { &hf_afp_dir_attribute_System,
+ { "System", "afp.dir_attribute.system",
+ FT_BOOLEAN, 16, NULL, kFPSystemBit,
+ "Directory is a system directory", HFILL }},
+
+ { &hf_afp_dir_attribute_Mounted,
+ { "Mounted", "afp.dir_attribute.mounted",
+ FT_BOOLEAN, 16, NULL, kFPDAlreadyOpenBit,
+ "Directory is mounted", HFILL }},
+
+ { &hf_afp_dir_attribute_InExpFolder,
+ { "Shared area", "afp.dir_attribute.in_exported_folder",
+ FT_BOOLEAN, 16, NULL, kFPRAlreadyOpenBit,
+ "Directory is in a shared area", HFILL }},
+
+ { &hf_afp_dir_attribute_BackUpNeeded,
+ { "Backup needed", "afp.dir_attribute.backup_needed",
+ FT_BOOLEAN, 16, NULL, kFPBackUpNeededBit,
+ "Directory needs to be backed up", HFILL }},
+
+ { &hf_afp_dir_attribute_RenameInhibit,
+ { "Rename inhibit", "afp.dir_attribute.rename_inhibit",
+ FT_BOOLEAN, 16, NULL, kFPRenameInhibitBit,
+ "Rename inhibit", HFILL }},
+
+ { &hf_afp_dir_attribute_DeleteInhibit,
+ { "Delete inhibit", "afp.dir_attribute.delete_inhibit",
+ FT_BOOLEAN, 16, NULL, kFPDeleteInhibitBit,
+ "Delete inhibit", HFILL }},
+
+ { &hf_afp_dir_attribute_SetClear,
+ { "Set", "afp.dir_attribute.set_clear",
+ FT_BOOLEAN, 16, NULL, kFPSetClearBit,
+ "Clear/set attribute", HFILL }},
+
+ { &hf_afp_file_bitmap_Attributes,
+ { "Attributes", "afp.file_bitmap.attributes",
+ FT_BOOLEAN, 16, NULL, kFPAttributeBit,
+ "Return attributes if file", HFILL }},
+
+ { &hf_afp_file_bitmap_ParentDirID,
+ { "DID", "afp.file_bitmap.did",
+ FT_BOOLEAN, 16, NULL, kFPParentDirIDBit,
+ "Return parent directory ID if file", HFILL }},
+
+ { &hf_afp_file_bitmap_CreateDate,
+ { "Creation date", "afp.file_bitmap.create_date",
+ FT_BOOLEAN, 16, NULL, kFPCreateDateBit,
+ "Return creation date if file", HFILL }},
+
+ { &hf_afp_file_bitmap_ModDate,
+ { "Modification date", "afp.file_bitmap.mod_date",
+ FT_BOOLEAN, 16, NULL, kFPModDateBit,
+ "Return modification date if file", HFILL }},
+
+ { &hf_afp_file_bitmap_BackupDate,
+ { "Backup date", "afp.file_bitmap.backup_date",
+ FT_BOOLEAN, 16, NULL, kFPBackupDateBit,
+ "Return backup date if file", HFILL }},
+
+ { &hf_afp_file_bitmap_FinderInfo,
+ { "Finder info", "afp.file_bitmap.finder_info",
+ FT_BOOLEAN, 16, NULL, kFPFinderInfoBit,
+ "Return finder info if file", HFILL }},
+
+ { &hf_afp_file_bitmap_LongName,
+ { "Long name", "afp.file_bitmap.long_name",
+ FT_BOOLEAN, 16, NULL, kFPLongNameBit,
+ "Return long name if file", HFILL }},
+
+ { &hf_afp_file_bitmap_ShortName,
+ { "Short name", "afp.file_bitmap.short_name",
+ FT_BOOLEAN, 16, NULL, kFPShortNameBit,
+ "Return short name if file", HFILL }},
+
+ { &hf_afp_file_bitmap_NodeID,
+ { "File ID", "afp.file_bitmap.fid",
+ FT_BOOLEAN, 16, NULL, kFPNodeIDBit,
+ "Return file ID if file", HFILL }},
+
+ { &hf_afp_file_bitmap_DataForkLen,
+ { "Data fork size", "afp.file_bitmap.data_fork_len",
+ FT_BOOLEAN, 16, NULL, kFPDataForkLenBit,
+ "Return data fork size if file", HFILL }},
+
+ { &hf_afp_file_bitmap_RsrcForkLen,
+ { "Resource fork size", "afp.file_bitmap.resource_fork_len",
+ FT_BOOLEAN, 16, NULL, kFPRsrcForkLenBit,
+ "Return resource fork size if file", HFILL }},
+
+ { &hf_afp_file_bitmap_ExtDataForkLen,
+ { "Extended data fork size", "afp.file_bitmap.ex_data_fork_len",
+ FT_BOOLEAN, 16, NULL, kFPExtDataForkLenBit,
+ "Return extended (>2GB) data fork size if file", HFILL }},
+
+ { &hf_afp_file_bitmap_LaunchLimit,
+ { "Launch limit", "afp.file_bitmap.launch_limit",
+ FT_BOOLEAN, 16, NULL, kFPLaunchLimitBit,
+ "Return launch limit if file", HFILL }},
+
+ { &hf_afp_file_bitmap_UTF8Name,
+ { "UTF-8 name", "afp.file_bitmap.UTF8_name",
+ FT_BOOLEAN, 16, NULL, kFPUTF8NameBit,
+ "Return UTF-8 name if file", HFILL }},
+
+ { &hf_afp_file_bitmap_ExtRsrcForkLen,
+ { "Extended resource fork size", "afp.file_bitmap.ex_resource_fork_len",
+ FT_BOOLEAN, 16, NULL, kFPExtRsrcForkLenBit,
+ "Return extended (>2GB) resource fork size if file", HFILL }},
+
+ { &hf_afp_file_bitmap_UnixPrivs,
+ { "UNIX privileges", "afp.file_bitmap.unix_privs",
+ FT_BOOLEAN, 16, NULL, kFPUnixPrivsBit,
+ "Return UNIX privileges if file", HFILL }},
+
+ /* ---------- */
+ { &hf_afp_file_attribute_Invisible,
+ { "Invisible", "afp.file_attribute.invisible",
+ FT_BOOLEAN, 16, NULL, kFPInvisibleBit,
+ "File is not visible", HFILL }},
+
+ { &hf_afp_file_attribute_MultiUser,
+ { "Multi user", "afp.file_attribute.multi_user",
+ FT_BOOLEAN, 16, NULL, kFPMultiUserBit,
+ "multi user", HFILL }},
+
+ { &hf_afp_file_attribute_System,
+ { "System", "afp.file_attribute.system",
+ FT_BOOLEAN, 16, NULL, kFPSystemBit,
+ "File is a system file", HFILL }},
+
+ { &hf_afp_file_attribute_DAlreadyOpen,
+ { "Data fork open", "afp.file_attribute.df_open",
+ FT_BOOLEAN, 16, NULL, kFPDAlreadyOpenBit,
+ "Data fork already open", HFILL }},
+
+ { &hf_afp_file_attribute_RAlreadyOpen,
+ { "Resource fork open", "afp.file_attribute.rf_open",
+ FT_BOOLEAN, 16, NULL, kFPRAlreadyOpenBit,
+ "Resource fork already open", HFILL }},
+
+ { &hf_afp_file_attribute_WriteInhibit,
+ { "Write inhibit", "afp.file_attribute.write_inhibit",
+ FT_BOOLEAN, 16, NULL, kFPWriteInhibitBit,
+ "Write inhibit", HFILL }},
+
+ { &hf_afp_file_attribute_BackUpNeeded,
+ { "Backup needed", "afp.file_attribute.backup_needed",
+ FT_BOOLEAN, 16, NULL, kFPBackUpNeededBit,
+ "File needs to be backed up", HFILL }},
+
+ { &hf_afp_file_attribute_RenameInhibit,
+ { "Rename inhibit", "afp.file_attribute.rename_inhibit",
+ FT_BOOLEAN, 16, NULL, kFPRenameInhibitBit,
+ "rename inhibit", HFILL }},
+
+ { &hf_afp_file_attribute_DeleteInhibit,
+ { "Delete inhibit", "afp.file_attribute.delete_inhibit",
+ FT_BOOLEAN, 16, NULL, kFPDeleteInhibitBit,
+ "delete inhibit", HFILL }},
+
+ { &hf_afp_file_attribute_CopyProtect,
+ { "Copy protect", "afp.file_attribute.copy_protect",
+ FT_BOOLEAN, 16, NULL, kFPCopyProtectBit,
+ "copy protect", HFILL }},
+
+ { &hf_afp_file_attribute_SetClear,
+ { "Set", "afp.file_attribute.set_clear",
+ FT_BOOLEAN, 16, NULL, kFPSetClearBit,
+ "Clear/set attribute", HFILL }},
+ /* ---------- */
+
+ { &hf_afp_vol_name,
+ { "Volume", "afp.vol_name",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "Volume name", HFILL }},
+
+ { &hf_afp_vol_flag_passwd,
+ { "Password", "afp.vol_flag_passwd",
+ FT_BOOLEAN, 8, NULL, 1,
+ "Volume is password-protected", HFILL }},
+
+ { &hf_afp_vol_flag_unix_priv,
+ { "Unix privs", "afp.vol_flag_unix_priv",
+ FT_BOOLEAN, 8, NULL, 2,
+ "Volume has unix privileges", HFILL }},
+
+ { &hf_afp_vol_id,
+ { "Volume id", "afp.vol_id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Volume id", HFILL }},
+
+ { &hf_afp_vol_signature,
+ { "Signature", "afp.vol_signature",
+ FT_UINT16, BASE_DEC, VALS(vol_signature_vals), 0x0,
+ "Volume signature", HFILL }},
+
+ { &hf_afp_vol_name_offset,
+ { "Volume name offset","afp.vol_name_offset",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Volume name offset in packet", HFILL }},
+
+ { &hf_afp_vol_creation_date,
+ { "Creation date", "afp.vol_creation_date",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Volume creation date", HFILL }},
+
+ { &hf_afp_vol_modification_date,
+ { "Modification date", "afp.vol_modification_date",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Volume modification date", HFILL }},
+
+ { &hf_afp_vol_backup_date,
+ { "Backup date", "afp.vol_backup_date",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Volume backup date", HFILL }},
+
+ { &hf_afp_vol_bytes_free,
+ { "Bytes free", "afp.vol_bytes_free",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Free space", HFILL }},
+
+ { &hf_afp_vol_bytes_total,
+ { "Bytes total", "afp.vol_bytes_total",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Volume size", HFILL }},
+
+ { &hf_afp_vol_ex_bytes_free,
+ { "Extended bytes free", "afp.vol_ex_bytes_free",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Extended (>2GB) free space", HFILL }},
+
+ { &hf_afp_vol_ex_bytes_total,
+ { "Extended bytes total", "afp.vol_ex_bytes_total",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Extended (>2GB) volume size", HFILL }},
+
+ { &hf_afp_vol_block_size,
+ { "Block size", "afp.vol_block_size",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Volume block size", HFILL }},
+
+ { &hf_afp_did,
+ { "DID", "afp.did",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Parent directory ID", HFILL }},
+
+ { &hf_afp_dir_bitmap,
+ { "Directory bitmap", "afp.dir_bitmap",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Directory bitmap", HFILL }},
+
+ { &hf_afp_dir_offspring,
+ { "Offspring", "afp.dir_offspring",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Directory offspring", HFILL }},
+
+ { &hf_afp_dir_OwnerID,
+ { "Owner ID", "afp.dir_owner_id",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Directory owner ID", HFILL }},
+
+ { &hf_afp_dir_GroupID,
+ { "Group ID", "afp.dir_group_id",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Directory group ID", HFILL }},
+
+ { &hf_afp_creation_date,
+ { "Creation date", "afp.creation_date",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Creation date", HFILL }},
+
+ { &hf_afp_modification_date,
+ { "Modification date", "afp.modification_date",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Modification date", HFILL }},
+
+ { &hf_afp_backup_date,
+ { "Backup date", "afp.backup_date",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Backup date", HFILL }},
+
+ { &hf_afp_finder_info,
+ { "Finder info", "afp.finder_info",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Finder info", HFILL }},
+
+ { &hf_afp_long_name_offset,
+ { "Long name offset", "afp.long_name_offset",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Long name offset in packet", HFILL }},
+
+ { &hf_afp_short_name_offset,
+ { "Short name offset", "afp.short_name_offset",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Short name offset in packet", HFILL }},
+
+ { &hf_afp_unicode_name_offset,
+ { "Unicode name offset", "afp.unicode_name_offset",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Unicode name offset in packet", HFILL }},
+
+ { &hf_afp_unix_privs_uid,
+ { "UID", "afp.unix_privs.uid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "User ID", HFILL }},
+
+ { &hf_afp_unix_privs_gid,
+ { "GID", "afp.unix_privs.gid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Group ID", HFILL }},
+
+ { &hf_afp_unix_privs_permissions,
+ { "Permissions", "afp.unix_privs.permissions",
+ FT_UINT32, BASE_OCT, NULL, 0x0,
+ "Permissions", HFILL }},
+
+ { &hf_afp_unix_privs_ua_permissions,
+ { "User's access rights", "afp.unix_privs.ua_permissions",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "User's access rights", HFILL }},
+
+ { &hf_afp_file_id,
+ { "File ID", "afp.file_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "File/directory ID", HFILL }},
+
+ { &hf_afp_file_DataForkLen,
+ { "Data fork size", "afp.data_fork_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Data fork size", HFILL }},
+
+ { &hf_afp_file_RsrcForkLen,
+ { "Resource fork size", "afp.resource_fork_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Resource fork size", HFILL }},
+
+ { &hf_afp_file_ExtDataForkLen,
+ { "Extended data fork size", "afp.ext_data_fork_len",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Extended (>2GB) data fork length", HFILL }},
+
+ { &hf_afp_file_ExtRsrcForkLen,
+ { "Extended resource fork size", "afp.ext_resource_fork_len",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Extended (>2GB) resource fork length", HFILL }},
+
+ { &hf_afp_file_bitmap,
+ { "File bitmap", "afp.file_bitmap",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "File bitmap", HFILL }},
+
+ { &hf_afp_req_count,
+ { "Req count", "afp.req_count",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Maximum number of structures returned", HFILL }},
+
+ { &hf_afp_start_index,
+ { "Start index", "afp.start_index",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "First structure returned", HFILL }},
+
+ { &hf_afp_max_reply_size,
+ { "Reply size", "afp.reply_size",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Reply size", HFILL }},
+
+ { &hf_afp_start_index32,
+ { "Start index", "afp.start_index32",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "First structure returned", HFILL }},
+
+ { &hf_afp_max_reply_size32,
+ { "Reply size", "afp.reply_size32",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Reply size", HFILL }},
+
+ { &hf_afp_file_flag,
+ { "Dir", "afp.file_flag",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ "Is a dir", HFILL }},
+
+ { &hf_afp_create_flag,
+ { "Hard create", "afp.create_flag",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ "Soft/hard create file", HFILL }},
+
+ { &hf_afp_request_bitmap_Attributes,
+ { "Attributes", "afp.request_bitmap.attributes",
+ FT_BOOLEAN, 32, NULL, kFPAttributeBit,
+ "Search attributes", HFILL }},
+
+ { &hf_afp_request_bitmap_ParentDirID,
+ { "DID", "afp.request_bitmap.did",
+ FT_BOOLEAN, 32, NULL, kFPParentDirIDBit,
+ "Search parent directory ID", HFILL }},
+
+ { &hf_afp_request_bitmap_CreateDate,
+ { "Creation date", "afp.request_bitmap.create_date",
+ FT_BOOLEAN, 32, NULL, kFPCreateDateBit,
+ "Search creation date", HFILL }},
+
+ { &hf_afp_request_bitmap_ModDate,
+ { "Modification date", "afp.request_bitmap.mod_date",
+ FT_BOOLEAN, 32, NULL, kFPModDateBit,
+ "Search modification date", HFILL }},
+
+ { &hf_afp_request_bitmap_BackupDate,
+ { "Backup date", "afp.request_bitmap.backup_date",
+ FT_BOOLEAN, 32, NULL, kFPBackupDateBit,
+ "Search backup date", HFILL }},
+
+ { &hf_afp_request_bitmap_FinderInfo,
+ { "Finder info", "afp.request_bitmap.finder_info",
+ FT_BOOLEAN, 32, NULL, kFPFinderInfoBit,
+ "Search finder info", HFILL }},
+
+ { &hf_afp_request_bitmap_LongName,
+ { "Long name", "afp.request_bitmap.long_name",
+ FT_BOOLEAN, 32, NULL, kFPLongNameBit,
+ "Search long name", HFILL }},
+
+ { &hf_afp_request_bitmap_DataForkLen,
+ { "Data fork size", "afp.request_bitmap.data_fork_len",
+ FT_BOOLEAN, 32, NULL, kFPDataForkLenBit,
+ "Search data fork size", HFILL }},
+
+ { &hf_afp_request_bitmap_OffspringCount,
+ { "Offspring count", "afp.request_bitmap.offspring_count",
+ FT_BOOLEAN, 32, NULL, kFPOffspringCountBit,
+ "Search offspring count", HFILL }},
+
+ { &hf_afp_request_bitmap_RsrcForkLen,
+ { "Resource fork size", "afp.request_bitmap.resource_fork_len",
+ FT_BOOLEAN, 32, NULL, kFPRsrcForkLenBit,
+ "Search resource fork size", HFILL }},
+
+ { &hf_afp_request_bitmap_ExtDataForkLen,
+ { "Extended data fork size", "afp.request_bitmap.ex_data_fork_len",
+ FT_BOOLEAN, 32, NULL, kFPExtDataForkLenBit,
+ "Search extended (>2GB) data fork size", HFILL }},
+
+ { &hf_afp_request_bitmap_UTF8Name,
+ { "UTF-8 name", "afp.request_bitmap.UTF8_name",
+ FT_BOOLEAN, 32, NULL, kFPUTF8NameBit,
+ "Search UTF-8 name", HFILL }},
+
+ { &hf_afp_request_bitmap_ExtRsrcForkLen,
+ { "Extended resource fork size", "afp.request_bitmap.ex_resource_fork_len",
+ FT_BOOLEAN, 32, NULL, kFPExtRsrcForkLenBit,
+ "Search extended (>2GB) resource fork size", HFILL }},
+
+ { &hf_afp_request_bitmap_PartialNames,
+ { "Match on partial names", "afp.request_bitmap.partial_names",
+ FT_BOOLEAN, 32, NULL, 0x80000000,
+ "Match on partial names", HFILL }},
+
+ { &hf_afp_request_bitmap,
+ { "Request bitmap", "afp.request_bitmap",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Request bitmap", HFILL }},
+
+ { &hf_afp_struct_size,
+ { "Struct size", "afp.struct_size",
+ FT_UINT8, BASE_DEC, NULL,0,
+ "Sizeof of struct", HFILL }},
+
+ { &hf_afp_struct_size16,
+ { "Struct size", "afp.struct_size16",
+ FT_UINT16, BASE_DEC, NULL,0,
+ "Sizeof of struct", HFILL }},
+
+ { &hf_afp_flag,
+ { "From", "afp.flag",
+ FT_UINT8, BASE_HEX, VALS(flag_vals), 0x80,
+ "Offset is relative to start/end of the fork", HFILL }},
+
+ { &hf_afp_dt_ref,
+ { "DT ref", "afp.dt_ref",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Desktop database reference num", HFILL }},
+
+ { &hf_afp_ofork,
+ { "Fork", "afp.ofork",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Open fork reference number", HFILL }},
+
+ { &hf_afp_offset,
+ { "Offset", "afp.offset",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Offset", HFILL }},
+
+ { &hf_afp_rw_count,
+ { "Count", "afp.rw_count",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Number of bytes to be read/written", HFILL }},
+
+ { &hf_afp_newline_mask,
+ { "Newline mask", "afp.newline_mask",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Value to AND bytes with when looking for newline", HFILL }},
+
+ { &hf_afp_newline_char,
+ { "Newline char", "afp.newline_char",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Value to compare ANDed bytes with when looking for newline", HFILL }},
+
+ { &hf_afp_last_written,
+ { "Last written", "afp.last_written",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Offset of the last byte written", HFILL }},
+
+ { &hf_afp_actual_count,
+ { "Count", "afp.actual_count",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Number of bytes returned by read/write", HFILL }},
+
+ { &hf_afp_ofork_len,
+ { "New length", "afp.ofork_len",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "New length", HFILL }},
+
+ { &hf_afp_path_type,
+ { "Type", "afp.path_type",
+ FT_UINT8, BASE_HEX, VALS(path_type_vals), 0,
+ "Type of names", HFILL }},
+
+ { &hf_afp_path_len,
+ { "Len", "afp.path_len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Path length", HFILL }},
+
+ { &hf_afp_path_unicode_len,
+ { "Len", "afp.path_unicode_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Path length (unicode)", HFILL }},
+
+ { &hf_afp_path_unicode_hint,
+ { "Unicode hint", "afp.path_unicode_hint",
+ FT_UINT32, BASE_HEX, VALS(unicode_hint_vals), 0x0,
+ "Unicode hint", HFILL }},
+
+ { &hf_afp_path_name,
+ { "Name", "afp.path_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Path name", HFILL }},
+
+ { &hf_afp_fork_type,
+ { "Resource fork", "afp.fork_type",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ "Data/resource fork", HFILL }},
+
+ { &hf_afp_access_mode,
+ { "Access mode", "afp.access",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Fork access mode", HFILL }},
+
+ { &hf_afp_access_read,
+ { "Read", "afp.access.read",
+ FT_BOOLEAN, 8, NULL, 1,
+ "Open for reading", HFILL }},
+
+ { &hf_afp_access_write,
+ { "Write", "afp.access.write",
+ FT_BOOLEAN, 8, NULL, 2,
+ "Open for writing", HFILL }},
+
+ { &hf_afp_access_deny_read,
+ { "Deny read", "afp.access.deny_read",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ "Deny read", HFILL }},
+
+ { &hf_afp_access_deny_write,
+ { "Deny write", "afp.access.deny_write",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ "Deny write", HFILL }},
+
+ { &hf_afp_comment,
+ { "Comment", "afp.comment",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "File/folder comment", HFILL }},
+
+ { &hf_afp_file_creator,
+ { "File creator", "afp.file_creator",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "File creator", HFILL }},
+
+ { &hf_afp_file_type,
+ { "File type", "afp.file_type",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "File type", HFILL }},
+
+ { &hf_afp_icon_type,
+ { "Icon type", "afp.icon_type",
+ FT_UINT8, BASE_HEX, NULL , 0,
+ "Icon type", HFILL }},
+
+ { &hf_afp_icon_length,
+ { "Size", "afp.icon_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Size for icon bitmap", HFILL }},
+
+ { &hf_afp_icon_index,
+ { "Index", "afp.icon_index",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Icon index in desktop database", HFILL }},
+
+ { &hf_afp_icon_tag,
+ { "Tag", "afp.icon_tag",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Icon tag", HFILL }},
+
+ { &hf_afp_appl_index,
+ { "Index", "afp.appl_index",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Application index", HFILL }},
+
+ { &hf_afp_appl_tag,
+ { "Tag", "afp.appl_tag",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Application tag", HFILL }},
+
+ { &hf_afp_lock_op,
+ { "unlock", "afp.lock_op",
+ FT_BOOLEAN, 8, NULL, 0x1,
+ "Lock/unlock op", HFILL }},
+
+ { &hf_afp_lock_from,
+ { "End", "afp.lock_from",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ "Offset is relative to the end of the fork", HFILL }},
+
+ { &hf_afp_lock_offset,
+ { "Offset", "afp.lock_offset",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "First byte to be locked", HFILL }},
+
+ { &hf_afp_lock_len,
+ { "Length", "afp.lock_len",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Number of bytes to be locked/unlocked", HFILL }},
+
+ { &hf_afp_lock_range_start,
+ { "Start", "afp.lock_range_start",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "First byte locked/unlocked", HFILL }},
+
+ { &hf_afp_dir_ar,
+ { "Access rights", "afp.dir_ar",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Directory access rights", HFILL }},
+
+ { &hf_afp_dir_ar_o_search,
+ { "Owner has search access", "afp.dir_ar.o_search",
+ FT_BOOLEAN, 32, NULL, AR_O_SEARCH,
+ "Owner has search access", HFILL }},
+
+ { &hf_afp_dir_ar_o_read,
+ { "Owner has read access", "afp.dir_ar.o_read",
+ FT_BOOLEAN, 32, NULL, AR_O_READ,
+ "Owner has read access", HFILL }},
+
+ { &hf_afp_dir_ar_o_write,
+ { "Owner has write access", "afp.dir_ar.o_write",
+ FT_BOOLEAN, 32, NULL, AR_O_WRITE,
+ "Gwner has write access", HFILL }},
+
+ { &hf_afp_dir_ar_g_search,
+ { "Group has search access", "afp.dir_ar.g_search",
+ FT_BOOLEAN, 32, NULL, AR_G_SEARCH,
+ "Group has search access", HFILL }},
+
+ { &hf_afp_dir_ar_g_read,
+ { "Group has read access", "afp.dir_ar.g_read",
+ FT_BOOLEAN, 32, NULL, AR_G_READ,
+ "Group has read access", HFILL }},
+
+ { &hf_afp_dir_ar_g_write,
+ { "Group has write access", "afp.dir_ar.g_write",
+ FT_BOOLEAN, 32, NULL, AR_G_WRITE,
+ "Group has write access", HFILL }},
+
+ { &hf_afp_dir_ar_e_search,
+ { "Everyone has search access", "afp.dir_ar.e_search",
+ FT_BOOLEAN, 32, NULL, AR_E_SEARCH,
+ "Everyone has search access", HFILL }},
+
+ { &hf_afp_dir_ar_e_read,
+ { "Everyone has read access", "afp.dir_ar.e_read",
+ FT_BOOLEAN, 32, NULL, AR_E_READ,
+ "Everyone has read access", HFILL }},
+
+ { &hf_afp_dir_ar_e_write,
+ { "Everyone has write access", "afp.dir_ar.e_write",
+ FT_BOOLEAN, 32, NULL, AR_E_WRITE,
+ "Everyone has write access", HFILL }},
+
+ { &hf_afp_dir_ar_u_search,
+ { "User has search access", "afp.dir_ar.u_search",
+ FT_BOOLEAN, 32, NULL, AR_U_SEARCH,
+ "User has search access", HFILL }},
+
+ { &hf_afp_dir_ar_u_read,
+ { "User has read access", "afp.dir_ar.u_read",
+ FT_BOOLEAN, 32, NULL, AR_U_READ,
+ "User has read access", HFILL }},
+
+ { &hf_afp_dir_ar_u_write,
+ { "User has write access", "afp.dir_ar.u_write",
+ FT_BOOLEAN, 32, NULL, AR_U_WRITE,
+ "User has write access", HFILL }},
+
+ { &hf_afp_dir_ar_blank,
+ { "Blank access right", "afp.dir_ar.blank",
+ FT_BOOLEAN, 32, NULL, AR_BLANK,
+ "Blank access right", HFILL }},
+
+ { &hf_afp_dir_ar_u_own,
+ { "User is the owner", "afp.dir_ar.u_owner",
+ FT_BOOLEAN, 32, NULL, AR_U_OWN,
+ "Current user is the directory owner", HFILL }},
+
+ { &hf_afp_server_time,
+ { "Server time", "afp.server_time",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Server time", HFILL }},
+
+ { &hf_afp_cat_req_matches,
+ { "Max answers", "afp.cat_req_matches",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Maximum number of matches to return.", HFILL }},
+
+ { &hf_afp_reserved,
+ { "Reserved", "afp.reserved",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Reserved", HFILL }},
+
+ { &hf_afp_cat_count,
+ { "Cat count", "afp.cat_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of structures returned", HFILL }},
+
+ { &hf_afp_cat_position,
+ { "Position", "afp.cat_position",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Reserved", HFILL }},
+
+
+ { &hf_afp_map_name_type,
+ { "Type", "afp.map_name_type",
+ FT_UINT8, BASE_DEC, VALS(map_name_type_vals), 0x0,
+ "Map name type", HFILL }},
+
+ { &hf_afp_map_id_type,
+ { "Type", "afp.map_id_type",
+ FT_UINT8, BASE_DEC, VALS(map_id_type_vals), 0x0,
+ "Map ID type", HFILL }},
+
+ { &hf_afp_map_id,
+ { "ID", "afp.map_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "User/Group ID", HFILL }},
+
+ { &hf_afp_map_name,
+ { "Name", "afp.map_name",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "User/Group name", HFILL }},
+
+ /* AFP 3.0 */
+ { &hf_afp_lock_offset64,
+ { "Offset", "afp.lock_offset64",
+ FT_INT64, BASE_DEC, NULL, 0x0,
+ "First byte to be locked (64 bits)", HFILL }},
+
+ { &hf_afp_lock_len64,
+ { "Length", "afp.lock_len64",
+ FT_INT64, BASE_DEC, NULL, 0x0,
+ "Number of bytes to be locked/unlocked (64 bits)", HFILL }},
+
+ { &hf_afp_lock_range_start64,
+ { "Start", "afp.lock_range_start64",
+ FT_INT64, BASE_DEC, NULL, 0x0,
+ "First byte locked/unlocked (64 bits)", HFILL }},
+
+ { &hf_afp_offset64,
+ { "Offset", "afp.offset64",
+ FT_INT64, BASE_DEC, NULL, 0x0,
+ "Offset (64 bits)", HFILL }},
+
+ { &hf_afp_rw_count64,
+ { "Count", "afp.rw_count64",
+ FT_INT64, BASE_DEC, NULL, 0x0,
+ "Number of bytes to be read/written (64 bits)", HFILL }},
+
+ { &hf_afp_last_written64,
+ { "Last written", "afp.last_written64",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Offset of the last byte written (64 bits)", HFILL }},
+
+ { &hf_afp_ofork_len64,
+ { "New length", "afp.ofork_len64",
+ FT_INT64, BASE_DEC, NULL, 0x0,
+ "New length (64 bits)", HFILL }},
+
+ { &hf_afp_session_token_type,
+ { "Type", "afp.session_token_type",
+ FT_UINT16, BASE_HEX, VALS(token_type_vals), 0x0,
+ "Session token type", HFILL }},
+
+ /* FIXME FT_UINT32 in specs */
+ { &hf_afp_session_token_len,
+ { "Len", "afp.session_token_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Session token length", HFILL }},
+
+ { &hf_afp_session_token_timestamp,
+ { "Time stamp", "afp.session_token_timestamp",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Session time stamp", HFILL }},
+
+ { &hf_afp_session_token,
+ { "Token", "afp.session_token",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Session token", HFILL }},
+
+ { &hf_afp_user_flag,
+ { "Flag", "afp.user_flag",
+ FT_UINT8, BASE_HEX, VALS(user_flag_vals), 0x01,
+ "User Info flag", HFILL }},
+
+ { &hf_afp_user_ID,
+ { "User ID", "afp.user_ID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "User ID", HFILL }},
+
+ { &hf_afp_group_ID,
+ { "Group ID", "afp.group_ID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Group ID", HFILL }},
+
+ { &hf_afp_user_bitmap,
+ { "Bitmap", "afp.user_bitmap",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "User Info bitmap", HFILL }},
+
+ { &hf_afp_user_bitmap_UID,
+ { "User ID", "afp.user_bitmap.UID",
+ FT_BOOLEAN, 16, NULL, 0x01,
+ "User ID", HFILL }},
+
+ { &hf_afp_user_bitmap_GID,
+ { "Primary group ID", "afp.user_bitmap.GID",
+ FT_BOOLEAN, 16, NULL, 0x02,
+ "Primary group ID", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_afp,
+ &ett_afp_server_vol,
+ &ett_afp_vol_list,
+ &ett_afp_vol_flag,
+ &ett_afp_vol_bitmap,
+ &ett_afp_vol_attribute,
+ &ett_afp_dir_bitmap,
+ &ett_afp_file_bitmap,
+ &ett_afp_unix_privs,
+ &ett_afp_enumerate,
+ &ett_afp_enumerate_line,
+ &ett_afp_access_mode,
+ &ett_afp_dir_attribute,
+ &ett_afp_file_attribute,
+ &ett_afp_path_name,
+ &ett_afp_lock_flags,
+ &ett_afp_dir_ar,
+ &ett_afp_cat_search,
+ &ett_afp_cat_r_bitmap,
+ &ett_afp_cat_spec,
+ &ett_afp_vol_did,
+ &ett_afp_user_bitmap,
+ };
+
+ proto_afp = proto_register_protocol("AppleTalk Filing Protocol", "AFP", "afp");
+ proto_register_field_array(proto_afp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine( &afp_reinit);
+
+ register_dissector("afp", dissect_afp, proto_afp);
+ data_handle = find_dissector("data");
+}
+
+void
+proto_reg_handoff_afp(void)
+{
+ data_handle = find_dissector("data");
+}
+
+/* -------------------------------
+ end
+*/
diff --git a/epan/dissectors/packet-afp.h b/epan/dissectors/packet-afp.h
new file mode 100644
index 0000000000..1ab90f5992
--- /dev/null
+++ b/epan/dissectors/packet-afp.h
@@ -0,0 +1,122 @@
+/* packet-afp.h
+ * Definitions for packet disassembly structures and routines
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_AFP_H
+#define PACKET_AFP_H
+
+#define AFP_OK 0
+#define AFPERR_ACCESS -5000 /* permission denied */
+#define AFPERR_AUTHCONT -5001 /* logincont */
+#define AFPERR_BADUAM -5002 /* uam doesn't exist */
+#define AFPERR_BADVERS -5003 /* bad afp version number */
+#define AFPERR_BITMAP -5004 /* invalid bitmap */
+#define AFPERR_CANTMOVE -5005 /* can't move file */
+#define AFPERR_DENYCONF -5006 /* file synchronization locks conflict */
+#define AFPERR_DIRNEMPT -5007 /* directory not empty */
+#define AFPERR_DFULL -5008 /* disk full */
+#define AFPERR_EOF -5009 /* end of file -- catsearch and afp_read */
+#define AFPERR_BUSY -5010 /* FileBusy */
+#define AFPERR_FLATVOL -5011 /* volume doesn't support directories */
+#define AFPERR_NOITEM -5012 /* ItemNotFound */
+#define AFPERR_LOCK -5013 /* LockErr */
+#define AFPERR_MISC -5014 /* misc. err */
+#define AFPERR_NLOCK -5015 /* no more locks */
+#define AFPERR_NOSRVR -5016 /* no response by server at that address */
+#define AFPERR_EXIST -5017 /* object already exists */
+#define AFPERR_NOOBJ -5018 /* object not found */
+#define AFPERR_PARAM -5019 /* parameter error */
+#define AFPERR_NORANGE -5020 /* no range lock */
+#define AFPERR_RANGEOVR -5021 /* range overlap */
+#define AFPERR_SESSCLOS -5022 /* session closed */
+#define AFPERR_NOTAUTH -5023 /* user not authenticated */
+#define AFPERR_NOOP -5024 /* command not supported */
+#define AFPERR_BADTYPE -5025 /* object is the wrong type */
+#define AFPERR_NFILE -5026 /* too many files open */
+#define AFPERR_SHUTDOWN -5027 /* server is going down */
+#define AFPERR_NORENAME -5028 /* can't rename */
+#define AFPERR_NODIR -5029 /* couldn't find directory */
+#define AFPERR_ITYPE -5030 /* wrong icon type */
+#define AFPERR_VLOCK -5031 /* volume locked */
+#define AFPERR_OLOCK -5032 /* object locked */
+#define AFPERR_CTNSHRD -5033 /* share point contains a share point */
+#define AFPERR_NOID -5034 /* file thread not found */
+#define AFPERR_EXISTID -5035 /* file already has an id */
+#define AFPERR_DIFFVOL -5036 /* different volume */
+#define AFPERR_CATCHNG -5037 /* catalog has changed */
+#define AFPERR_SAMEOBJ -5038 /* source file == destination file */
+#define AFPERR_BADID -5039 /* non-existent file id */
+#define AFPERR_PWDSAME -5040 /* same password/can't change password */
+#define AFPERR_PWDSHORT -5041 /* password too short */
+#define AFPERR_PWDEXPR -5042 /* password expired */
+#define AFPERR_INSHRD -5043 /* folder being shared is inside a shared folder. may be returned by
+ afpMoveAndRename. */
+#define AFPERR_INTRASH -5044 /* shared folder in trash. */
+#define AFPERR_PWDCHNG -5045 /* password needs to be changed */
+#define AFPERR_PWDPOLCY -5046 /* password fails policy check */
+#define AFPERR_USRLOGIN -5047 /* user already logged on */
+
+extern const value_string asp_error_vals[];
+extern const value_string afp_server_addr_type_vals[];
+
+/* server flags */
+#define AFPSRVRINFO_COPY (1<<0) /* supports copyfile */
+#define AFPSRVRINFO_PASSWD (1<<1) /* supports change password */
+#define AFPSRVRINFO_NOSAVEPASSWD (1<<2) /* don't allow save password */
+#define AFPSRVRINFO_SRVMSGS (1<<3) /* supports server messages */
+#define AFPSRVRINFO_SRVSIGNATURE (1<<4) /* supports server signature */
+#define AFPSRVRINFO_TCPIP (1<<5) /* supports tcpip */
+#define AFPSRVRINFO_SRVNOTIFY (1<<6) /* supports server notifications */
+#define AFPSRVRINFO_SRVRECONNECT (1<<7) /* supports reconnect */
+#define AFPSRVRINFO_SRVDIRECTORY (1<<8) /* supports directory services */
+#define AFPSRVRINFO_SRVUTF8 (1<<9) /* supports UTF8 names AFP 3.1 */
+#define AFPSRVRINFO_FASTBOZO (1<<15) /* fast copying */
+
+
+#define AFPSTATUS_MACHOFF 0
+#define AFPSTATUS_VERSOFF 2
+#define AFPSTATUS_UAMSOFF 4
+#define AFPSTATUS_ICONOFF 6
+#define AFPSTATUS_FLAGOFF 8
+#define AFPSTATUS_PRELEN 10
+#define AFPSTATUS_POSTLEN 4
+#define AFPSTATUS_LEN (AFPSTATUS_PRELEN + AFPSTATUS_POSTLEN)
+
+/*
+ * Private data passed from DSI,DDP dissectors to AFP dissector.
+ * DSI DDP
+ * aspinfo.reply dsi.flags atp.function == 0x80
+ * release atp.function == 0xc0
+ * command command asp.function
+ * seq requestid atp.tid
+ * code code
+ */
+struct aspinfo {
+ guint8 reply; /* 0 query 1 reply */
+ guint8 release;
+ guint16 command; /* 2 6 write */
+ guint16 seq; /* sequence number */
+ gint32 code; /* error code/ offset NU */
+};
+
+#endif
diff --git a/epan/dissectors/packet-afs-defs.h b/epan/dissectors/packet-afs-defs.h
new file mode 100644
index 0000000000..913b43839e
--- /dev/null
+++ b/epan/dissectors/packet-afs-defs.h
@@ -0,0 +1,783 @@
+/* packet-afs-defs.h
+ * Routines for AFS packet dissection
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ * Based on routines from tcpdump patches by
+ * Ken Hornstein <kenh@cmf.nrl.navy.mil>
+ * Portions based on information retrieved from the RX definitions
+ * in Arla, the free AFS client at http://www.stacken.kth.se/project/arla/
+ * Portions based on information/specs retrieved from the OpenAFS sources at
+ * www.openafs.org, Copyright IBM.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+static const value_string fs_req[] = {
+ { 130, "fetch-data" },
+ { 131, "fetch-acl" },
+ { 132, "fetch-status" },
+ { 133, "store-data" },
+ { 134, "store-acl" },
+ { 135, "store-status" },
+ { 136, "remove-file" },
+ { 137, "create-file" },
+ { 138, "rename" },
+ { 139, "symlink" },
+ { 140, "link" },
+ { 141, "makedir" },
+ { 142, "rmdir" },
+ { 143, "old-set-lock" },
+ { 144, "old-extend-lock" },
+ { 145, "old-release-lock" },
+ { 146, "get-stats" },
+ { 147, "give-up-callbacks" },
+ { 148, "get-volume-info" },
+ { 149, "get-volume-status" },
+ { 150, "set-volume-status" },
+ { 151, "get-root-volume" },
+ { 152, "check-token" },
+ { 153, "get-time" },
+ { 154, "nget-volume-info" },
+ { 155, "bulk-status" },
+ { 156, "set-lock" },
+ { 157, "extend-lock" },
+ { 158, "release-lock" },
+ { 159, "xstats-version" },
+ { 160, "get-xstats" },
+ { 161, "dfs-lookup" },
+ { 162, "dfs-flushcps" },
+ { 163, "dfs-symlink" },
+ { 220, "residency" },
+ { 65536, "inline-bulk-status" },
+ { 65537, "fetch-data-64" },
+ { 65538, "store-data-64" },
+ { 65539, "give-up-all-callbacks" },
+ { 65540, "get-capabilities" },
+ { 0, NULL },
+};
+
+static const value_string cb_req[] = {
+ { 204, "callback" },
+ { 205, "init-callback-state" },
+ { 206, "probe" },
+ { 207, "get-lock" },
+ { 208, "get-ce" },
+ { 209, "xstats-version" },
+ { 210, "get-xstats" },
+ { 211, "init-callback-state2" },
+ { 212, "who-are-you" },
+ { 213, "init-callback-state3" },
+ { 214, "probeuuid" },
+ { 215, "get-server-prefs" },
+ { 216, "get-cellservdb" },
+ { 217, "get-local-cell" },
+ { 218, "get-cache-config" },
+ { 65536, "get-ce-64" },
+ { 65537, "get-cell-by-num" },
+ { 65538, "get-capabilities" },
+ { 0, NULL },
+};
+
+static const value_string prot_req[] = {
+ { 500, "new-user" },
+ { 501, "where-is-it" },
+ { 502, "dump-entry" },
+ { 503, "add-to-group" },
+ { 504, "name-to-id" },
+ { 505, "id-to-name" },
+ { 506, "delete" },
+ { 507, "remove-from-group" },
+ { 508, "get-cps" },
+ { 509, "new-entry" },
+ { 510, "list-max" },
+ { 511, "set-max" },
+ { 512, "list-entry" },
+ { 513, "change-entry" },
+ { 514, "list-elements" },
+ { 515, "is-member-of" },
+ { 516, "set-fld-sentry" },
+ { 517, "list-owned" },
+ { 518, "get-cps2" },
+ { 519, "get-host-cps" },
+ { 520, "update-entry" },
+ { 521, "list-entries" },
+ { 0, NULL },
+};
+
+static const value_string vldb_req[] = {
+ { 501, "create-entry" },
+ { 502, "delete-entry" },
+ { 503, "get-entry-by-id" },
+ { 504, "get-entry-by-name" },
+ { 505, "get-new-volume-id" },
+ { 506, "replace-entry" },
+ { 507, "update-entry" },
+ { 508, "set-lock" },
+ { 509, "release-lock" },
+ { 510, "list-entry" },
+ { 511, "list-attributes" },
+ { 512, "linked-list" },
+ { 513, "get-stats" },
+ { 514, "probe" },
+ { 515, "get-addrs" },
+ { 516, "change-addr" },
+ { 517, "create-entry-n" },
+ { 518, "get-entry-by-id-n" },
+ { 519, "get-entry-by-name-n" },
+ { 520, "replace-entry-n" },
+ { 521, "list-entry-n" },
+ { 522, "list-attrib-n" },
+ { 523, "linked-list-n" },
+ { 524, "update-entry-by-name" },
+ { 525, "create-entry-u" },
+ { 526, "get-entry-by-id-u" },
+ { 527, "get-entry-by-name-u" },
+ { 528, "replace-entry-u" },
+ { 529, "list-entry-u" },
+ { 530, "list-attrib-u" },
+ { 531, "linked-list-u" },
+ { 532, "regaddr" },
+ { 533, "get-addrs-u" },
+ { 534, "list-attrib-n2" },
+ { 0, NULL },
+};
+
+static const value_string kauth_req[] = {
+ { 1, "auth-old" },
+ { 21, "authenticate" },
+ { 22, "authenticate-v2" },
+ { 2, "change-pw" },
+ { 3, "get-ticket-old" },
+ { 23, "get-ticket" },
+ { 4, "set-pw" },
+ { 5, "set-fields" },
+ { 6, "create-user" },
+ { 7, "delete-user" },
+ { 8, "get-entry" },
+ { 9, "list-entry" },
+ { 10, "get-stats" },
+ { 11, "debug" },
+ { 12, "get-pw" },
+ { 13, "get-random-key" },
+ { 14, "unlock" },
+ { 15, "lock-status" },
+ { 0, NULL },
+};
+
+static const value_string vol_req[] = {
+ { 100, "create-volume" },
+ { 101, "delete-volume" },
+ { 102, "restore" },
+ { 103, "forward" },
+ { 104, "end-trans" },
+ { 105, "clone" },
+ { 106, "set-flags" },
+ { 107, "get-flags" },
+ { 108, "trans-create" },
+ { 109, "dump" },
+ { 110, "get-nth-volume" },
+ { 111, "set-forwarding" },
+ { 112, "get-name" },
+ { 113, "get-status" },
+ { 114, "sig-restore" },
+ { 115, "list-partitions" },
+ { 116, "list-volumes" },
+ { 117, "set-id-types" },
+ { 118, "monitor" },
+ { 119, "partition-info" },
+ { 120, "reclone" },
+ { 121, "list-one-volume" },
+ { 122, "nuke" },
+ { 123, "set-date" },
+ { 124, "x-list-volumes" },
+ { 125, "x-list-one-volume" },
+ { 126, "set-info" },
+ { 127, "x-list-partitions" },
+ { 128, "forward-multiple" },
+ { 65536, "convert-ro" },
+ { 65537, "getsize" },
+ { 0, NULL },
+};
+
+static const value_string bos_req[] = {
+ { 80, "create-bnode" },
+ { 81, "delete-bnode" },
+ { 82, "set-status" },
+ { 83, "get-status" },
+ { 84, "enumerate-instance" },
+ { 85, "get-instance-info" },
+ { 86, "get-instance-parm" },
+ { 87, "add-superuser" },
+ { 88, "delete-superuser" },
+ { 89, "list-superusers" },
+ { 90, "list-keys" },
+ { 91, "add-key" },
+ { 92, "delete-key" },
+ { 93, "set-cell-name" },
+ { 94, "get-cell-name" },
+ { 95, "get-cell-host" },
+ { 96, "add-cell-host" },
+ { 97, "delete-cell-host" },
+ { 98, "set-t-status" },
+ { 99, "shutdown-all" },
+ { 100, "restart-all" },
+ { 101, "startup-all" },
+ { 102, "set-noauth-flag" },
+ { 103, "re-bozo" },
+ { 104, "restart" },
+ { 105, "install" },
+ { 106, "uninstall" },
+ { 107, "get-dates" },
+ { 108, "exec" },
+ { 109, "prune" },
+ { 110, "set-restart-time" },
+ { 111, "get-restart-time" },
+ { 112, "get-log" },
+ { 113, "wait-all" },
+ { 114, "get-instance-strings" },
+ { 115, "get-restricted" },
+ { 116, "set restricted" },
+ { 0, NULL },
+};
+
+static const value_string update_req[] = {
+ { 1, "fetch-file" },
+ { 2, "fetch-info" },
+ { 0, NULL },
+};
+
+static const value_string rmtsys_req[] = {
+ { 1, "setpag" },
+ { 2, "pioctl" },
+ { 0, NULL },
+};
+
+static const value_string backup_req[] = {
+ { 100, "perform-dump" },
+ { 101, "perform-restore" },
+ { 102, "check-dump" },
+ { 103, "abort-dump" },
+ { 104, "wait-for-dump" },
+ { 105, "end-dump" },
+ { 106, "get-tm-info" },
+ { 107, "label-tape" },
+ { 108, "scan-nodes" },
+ { 109, "read-label" },
+ { 110, "scan-dumps" },
+ { 111, "get-tc-info" },
+ { 112, "save-database" },
+ { 113, "restore-database" },
+ { 114, "get-status" },
+ { 115, "request-abort" },
+ { 116, "end-status" },
+ { 117, "scan-status" },
+ { 118, "delete-dump" },
+ { 0, NULL },
+};
+
+static const value_string ubik_req[] = {
+ { 10000, "vote-beacon" },
+ { 10001, "vote-debug-old" },
+ { 10002, "vote-sdebug-old" },
+ { 10003, "vote-getsyncsite" },
+ { 10004, "vote-debug" },
+ { 10005, "vote-sdebug" },
+ { 10006, "vote-xdebug" },
+ { 10007, "vote-xsdebug" },
+ { 20000, "disk-begin" },
+ { 20001, "disk-commit" },
+ { 20002, "disk-lock" },
+ { 20003, "disk-write" },
+ { 20004, "disk-getversion" },
+ { 20005, "disk-getfile" },
+ { 20006, "disk-sendfile" },
+ { 20007, "disk-abort" },
+ { 20008, "disk-releaselocks" },
+ { 20009, "disk-truncate" },
+ { 20010, "disk-probe" },
+ { 20011, "disk-writev" },
+ { 20012, "disk-interfaceaddr" },
+ { 20013, "disk-setversion" },
+ { 0, NULL },
+};
+
+static const value_string cb_types[] = {
+ { CB_TYPE_EXCLUSIVE, "exclusive" },
+ { CB_TYPE_SHARED, "shared" },
+ { CB_TYPE_DROPPED, "dropped" },
+ { 0, NULL },
+};
+
+static const value_string afs_errors[] = {
+ /* VOL Errors */
+ { 363520, "ID Exists"},
+ { 363521, "IO Error"},
+ { 363522, "Name Exists"},
+ { 363523, "Create Failed"},
+ { 363524, "Entry Not Found"},
+ { 363525, "Empty"},
+ { 363526, "Entry Deleted"},
+ { 363527, "Bad Name"},
+ { 363528, "Bad Index"},
+ { 363529, "Bad Volume Type"},
+ { 363530, "Bad Partition"},
+ { 363531, "Bad Server"},
+ { 363532, "Bad Replicate Server"},
+ { 363533, "No Replicate Server"},
+ { 363534, "Duplicate Replicate Server"},
+ { 363535, "ReadWrite Volume Not Found"},
+ { 363536, "Bad Reference Count"},
+ { 363537, "Size Exceeded"},
+ { 363538, "Bad Entry"},
+ { 363539, "Bad Volume ID Bump"},
+ { 363540, "Already has edit"},
+ { 363541, "Entry Locked"},
+ { 363542, "Bad Volume Operation"},
+ { 363543, "Bad Rel Lock Type"},
+ { 363544, "Rerelease"},
+ { 363545, "Bad Server"},
+ { 363546, "Permission Denied"},
+ { 363547, "Out of Memory"},
+
+ /* KAUTH Errors */
+ { 180480, "Database Inconsistent"},
+ { 180481, "Exists"},
+ { 180482, "IO"},
+ { 180483, "Create Failed"},
+ { 180484, "noent"},
+ { 180485, "Empty"},
+ { 180486, "Bad Name"},
+ { 180487, "Bad Index"},
+ { 180488, "No auth"},
+ { 180489, "Answer too long"},
+ { 180490, "Bad Request"},
+ { 180491, "Old Interface"},
+ { 180492, "Bad Argument"},
+ { 180493, "Bad Command"},
+ { 180494, "No keys"},
+ { 180495, "Read PW"},
+ { 180496, "Bad key"},
+ { 180497, "Ubik Init"},
+ { 180498, "Ubik Call"},
+ { 180499, "Bad Protocol"},
+ { 180500, "No cells"},
+ { 180501, "No cell"},
+ { 180502, "Too many ubiks"},
+ { 180503, "Too many keys"},
+ { 180504, "Bad ticket"},
+ { 180505, "Unknown Key"},
+ { 180506, "Key Cache Invalid"},
+ { 180507, "Bad Server"},
+ { 180508, "Bad User"},
+ { 180509, "Bad CPW"},
+ { 180510, "Bad Create"},
+ { 180511, "No ticket"},
+ { 180512, "Assoc user"},
+ { 180513, "Not special"},
+ { 180514, "Clock skew too great"},
+ { 180515, "No recursion"},
+ { 180516, "RX failed"},
+ { 180517, "Null password"},
+ { 180518, "Internal error"},
+ { 180519, "Password expired"},
+ { 180520, "Reused"},
+ { 180521, "Too soon"},
+ { 180522, "Locked"},
+
+ /* PT Errors */
+ { 267264, "Exists"},
+ { 267265, "ID Exists"},
+ { 267266, "No IDs"},
+ { 267267, "DB Failed"},
+ { 267268, "No such entry"},
+ { 267269, "Permission denied"},
+ { 267270, "Not group"},
+ { 267271, "Not user"},
+ { 267272, "Bad name"},
+ { 267273, "Bad argument"},
+ { 267274, "No more"},
+ { 267275, "Bad DB"},
+ { 267276, "Group empty"},
+ { 267277, "Inconsistent"},
+ { 267278, "DB Address"},
+ { 267279, "Too many"},
+ { 267280, "No memory"},
+
+ /* Volume server errors */
+ { 1492325120, "Release error"},
+ { 1492325121, "No op"},
+ { 1492325122, "Read dump error"},
+ { 1492325123, "Dump error"},
+ { 1492325124, "Attach error"},
+ { 1492325125, "Illegal partition"},
+ { 1492325126, "Detach error"},
+ { 1492325127, "Bad access"},
+ { 1492325128, "VLDB error"},
+ { 1492325129, "Bad Name"},
+ { 1492325130, "Volume moved"},
+ { 1492325131, "Bad operation"},
+ { 1492325132, "Bad release"},
+ { 1492325133, "Volume busy"},
+ { 1492325134, "No memory"},
+ { 1492325135, "No volume"},
+ { 1492325136, "Multiple RW volumes"},
+ { 1492325137, "Failed operation"},
+
+ /* add more of these errors to decode the errcode responses */
+ { 0, NULL },
+};
+
+static const value_string port_types[] = {
+ { AFS_PORT_FS, "File Server" },
+ { AFS_PORT_CB, "Callback Server" },
+ { AFS_PORT_BOS, "BOS Server" },
+ { AFS_PORT_PROT, "Protection Server" },
+ { AFS_PORT_VLDB, "Volume Location Database Server" },
+ { AFS_PORT_KAUTH, "Kerberos Authentication Server" },
+ { AFS_PORT_ERROR, "Error Server" },
+ { AFS_PORT_VOL, "Volume Server" },
+ { AFS_PORT_RMTSYS, "Rmtsys? Server" },
+ { AFS_PORT_UPDATE, "Update? Server" },
+ { AFS_PORT_BACKUP, "Backup Server" },
+ { 0, NULL }
+};
+
+static const value_string port_types_short[] = {
+ { AFS_PORT_FS, "FS" },
+ { AFS_PORT_CB, "CB" },
+ { AFS_PORT_BOS, "BOS" },
+ { AFS_PORT_PROT, "PROT" },
+ { AFS_PORT_VLDB, "VLDB" },
+ { AFS_PORT_KAUTH, "KAUTH" },
+ { AFS_PORT_ERROR, "ERR" },
+ { AFS_PORT_VOL, "VOL" },
+ { AFS_PORT_RMTSYS, "RMT" },
+ { AFS_PORT_UPDATE, "UPD" },
+ { AFS_PORT_BACKUP, "BKUP" },
+ { 0, NULL }
+};
+
+static const value_string ubik_lock_types[] = {
+ { 1, "read" },
+ { 2, "write" },
+ { 3, "wait" },
+ { 0, NULL },
+};
+
+static const value_string xstat_collections[] = {
+ { 0, "call counting & info" },
+ { 1, "performance info" },
+ { 2, "full performance info" },
+ { 0, NULL },
+};
+
+static const value_string vice_lock_types[] = {
+ { 0, "read" },
+ { 1, "write" },
+ { 2, "extend" },
+ { 3, "release" },
+ { 0, NULL },
+};
+
+static const value_string volume_types[] = {
+ { 0, "read-write" },
+ { 1, "read-only" },
+ { 2, "backup" },
+ { 0xffffffff, "any" },
+ { 0, NULL },
+};
+
+static int proto_afs = -1;
+static int hf_afs_fs = -1;
+static int hf_afs_cb = -1;
+static int hf_afs_prot = -1;
+static int hf_afs_vldb = -1;
+static int hf_afs_kauth = -1;
+static int hf_afs_vol = -1;
+static int hf_afs_error = -1;
+static int hf_afs_bos = -1;
+static int hf_afs_update = -1;
+static int hf_afs_rmtsys = -1;
+static int hf_afs_ubik = -1;
+static int hf_afs_backup = -1;
+
+static int hf_afs_fs_opcode = -1;
+static int hf_afs_cb_opcode = -1;
+static int hf_afs_prot_opcode = -1;
+static int hf_afs_vldb_opcode = -1;
+static int hf_afs_kauth_opcode = -1;
+static int hf_afs_vol_opcode = -1;
+static int hf_afs_error_opcode = -1;
+static int hf_afs_bos_opcode = -1;
+static int hf_afs_update_opcode = -1;
+static int hf_afs_rmtsys_opcode = -1;
+static int hf_afs_ubik_opcode = -1;
+static int hf_afs_backup_opcode = -1;
+
+static int hf_afs_fs_fid_volume = -1;
+static int hf_afs_fs_fid_vnode = -1;
+static int hf_afs_fs_fid_uniqifier = -1;
+static int hf_afs_fs_offset = -1;
+static int hf_afs_fs_length = -1;
+static int hf_afs_fs_flength = -1;
+static int hf_afs_fs_offset64 = -1;
+static int hf_afs_fs_length64 = -1;
+static int hf_afs_fs_flength64 = -1;
+static int hf_afs_fs_errcode = -1;
+static int hf_afs_fs_data = -1;
+static int hf_afs_fs_name = -1;
+static int hf_afs_fs_oldname = -1;
+static int hf_afs_fs_newname = -1;
+static int hf_afs_fs_symlink_name = -1;
+static int hf_afs_fs_symlink_content = -1;
+static int hf_afs_fs_volid = -1;
+static int hf_afs_fs_volname = -1;
+static int hf_afs_fs_timestamp = -1;
+static int hf_afs_fs_offlinemsg = -1;
+static int hf_afs_fs_motd = -1;
+static int hf_afs_fs_xstats_version = -1;
+static int hf_afs_fs_xstats_timestamp = -1;
+static int hf_afs_fs_xstats_clientversion = -1;
+static int hf_afs_fs_xstats_collnumber = -1;
+static int hf_afs_fs_cps_spare1 = -1;
+static int hf_afs_fs_cps_spare2 = -1;
+static int hf_afs_fs_cps_spare3 = -1;
+static int hf_afs_fs_vicelocktype = -1;
+static int hf_afs_fs_viceid = -1;
+static int hf_afs_fs_ipaddr = -1;
+static int hf_afs_fs_token = -1;
+
+static int hf_afs_fs_status_anonymousaccess = -1;
+static int hf_afs_fs_status_author = -1;
+static int hf_afs_fs_status_calleraccess = -1;
+static int hf_afs_fs_status_clientmodtime = -1;
+static int hf_afs_fs_status_dataversion = -1;
+static int hf_afs_fs_status_dataversionhigh = -1;
+static int hf_afs_fs_status_filetype = -1;
+static int hf_afs_fs_status_group = -1;
+static int hf_afs_fs_status_interfaceversion = -1;
+static int hf_afs_fs_status_length = -1;
+static int hf_afs_fs_status_linkcount = -1;
+static int hf_afs_fs_status_mask = -1;
+static int hf_afs_fs_status_mask_fsync = -1;
+static int hf_afs_fs_status_mask_setgroup = -1;
+static int hf_afs_fs_status_mask_setmode = -1;
+static int hf_afs_fs_status_mask_setmodtime = -1;
+static int hf_afs_fs_status_mask_setowner = -1;
+static int hf_afs_fs_status_mask_setsegsize = -1;
+static int hf_afs_fs_status_mode = -1;
+static int hf_afs_fs_status_owner = -1;
+static int hf_afs_fs_status_parentunique = -1;
+static int hf_afs_fs_status_parentvnode = -1;
+static int hf_afs_fs_status_segsize = -1;
+static int hf_afs_fs_status_servermodtime = -1;
+static int hf_afs_fs_status_spare2 = -1;
+static int hf_afs_fs_status_spare3 = -1;
+static int hf_afs_fs_status_spare4 = -1;
+static int hf_afs_fs_status_synccounter = -1;
+
+static int hf_afs_fs_volsync_spare1 = -1;
+static int hf_afs_fs_volsync_spare2 = -1;
+static int hf_afs_fs_volsync_spare3 = -1;
+static int hf_afs_fs_volsync_spare4 = -1;
+static int hf_afs_fs_volsync_spare5 = -1;
+static int hf_afs_fs_volsync_spare6 = -1;
+
+static int hf_afs_fs_acl_datasize = -1;
+static int hf_afs_fs_acl_count_negative = -1;
+static int hf_afs_fs_acl_count_positive = -1;
+static int hf_afs_fs_acl_entity = -1;
+static int hf_afs_fs_acl_r = -1;
+static int hf_afs_fs_acl_l = -1;
+static int hf_afs_fs_acl_i = -1;
+static int hf_afs_fs_acl_d = -1;
+static int hf_afs_fs_acl_w = -1;
+static int hf_afs_fs_acl_k = -1;
+static int hf_afs_fs_acl_a = -1;
+
+static int hf_afs_fs_callback_version = -1;
+static int hf_afs_fs_callback_expires = -1;
+static int hf_afs_fs_callback_type = -1;
+
+static int hf_afs_bos_errcode = -1;
+static int hf_afs_bos_type = -1;
+static int hf_afs_bos_instance = -1;
+static int hf_afs_bos_status = -1;
+static int hf_afs_bos_statusdesc = -1;
+static int hf_afs_bos_num = -1;
+static int hf_afs_bos_size = -1;
+static int hf_afs_bos_flags = -1;
+static int hf_afs_bos_date = -1;
+static int hf_afs_bos_content = -1;
+static int hf_afs_bos_user = -1;
+static int hf_afs_bos_key = -1;
+static int hf_afs_bos_path = -1;
+static int hf_afs_bos_file = -1;
+static int hf_afs_bos_cmd = -1;
+static int hf_afs_bos_error = -1;
+static int hf_afs_bos_spare1 = -1;
+static int hf_afs_bos_spare2 = -1;
+static int hf_afs_bos_spare3 = -1;
+static int hf_afs_bos_parm = -1;
+static int hf_afs_bos_kvno = -1;
+static int hf_afs_bos_cell = -1;
+static int hf_afs_bos_host = -1;
+static int hf_afs_bos_newtime = -1;
+static int hf_afs_bos_baktime = -1;
+static int hf_afs_bos_oldtime = -1;
+static int hf_afs_bos_data = -1;
+static int hf_afs_bos_keymodtime = -1;
+static int hf_afs_bos_keychecksum = -1;
+static int hf_afs_bos_keyspare2 = -1;
+
+static int hf_afs_vldb_errcode = -1;
+static int hf_afs_vldb_name = -1;
+static int hf_afs_vldb_id = -1;
+static int hf_afs_vldb_type = -1;
+static int hf_afs_vldb_bump = -1;
+static int hf_afs_vldb_index = -1;
+static int hf_afs_vldb_nextindex = -1;
+static int hf_afs_vldb_count = -1;
+static int hf_afs_vldb_numservers = -1;
+static int hf_afs_vldb_server = -1;
+static int hf_afs_vldb_serveruuid = -1;
+static int hf_afs_vldb_serveruniq = -1;
+static int hf_afs_vldb_serverflags = -1;
+static int hf_afs_vldb_serverip = -1;
+static int hf_afs_vldb_partition = -1;
+static int hf_afs_vldb_rovol = -1;
+static int hf_afs_vldb_rwvol = -1;
+static int hf_afs_vldb_bkvol = -1;
+static int hf_afs_vldb_clonevol = -1;
+static int hf_afs_vldb_flags = -1;
+static int hf_afs_vldb_flags_rwexists = -1;
+static int hf_afs_vldb_flags_roexists = -1;
+static int hf_afs_vldb_flags_bkexists = -1;
+static int hf_afs_vldb_flags_dfsfileset = -1;
+
+static int hf_afs_vldb_spare1 = -1;
+static int hf_afs_vldb_spare2 = -1;
+static int hf_afs_vldb_spare3 = -1;
+static int hf_afs_vldb_spare4 = -1;
+static int hf_afs_vldb_spare5 = -1;
+static int hf_afs_vldb_spare6 = -1;
+static int hf_afs_vldb_spare7 = -1;
+static int hf_afs_vldb_spare8 = -1;
+static int hf_afs_vldb_spare9 = -1;
+
+static int hf_afs_kauth_errcode = -1;
+static int hf_afs_kauth_princ = -1;
+static int hf_afs_kauth_realm = -1;
+static int hf_afs_kauth_domain = -1;
+static int hf_afs_kauth_kvno = -1;
+static int hf_afs_kauth_name = -1;
+static int hf_afs_kauth_data = -1;
+
+static int hf_afs_vol_errcode = -1;
+static int hf_afs_vol_count = -1;
+static int hf_afs_vol_id = -1;
+static int hf_afs_vol_name = -1;
+
+static int hf_afs_cb_errcode = -1;
+static int hf_afs_cb_callback_version = -1;
+static int hf_afs_cb_callback_type = -1;
+static int hf_afs_cb_callback_expires = -1;
+static int hf_afs_cb_fid_volume = -1;
+static int hf_afs_cb_fid_vnode = -1;
+static int hf_afs_cb_fid_uniqifier = -1;
+
+static int hf_afs_prot_errcode = -1;
+static int hf_afs_prot_name = -1;
+static int hf_afs_prot_id = -1;
+static int hf_afs_prot_count = -1;
+static int hf_afs_prot_oldid = -1;
+static int hf_afs_prot_newid = -1;
+static int hf_afs_prot_pos = -1;
+static int hf_afs_prot_flag = -1;
+static int hf_afs_prot_uid = -1;
+static int hf_afs_prot_gid = -1;
+static int hf_afs_prot_maxuid = -1;
+static int hf_afs_prot_maxgid = -1;
+
+static int hf_afs_backup_errcode = -1;
+
+static int hf_afs_ubik_errcode = -1;
+static int hf_afs_ubik_version_epoch = -1;
+static int hf_afs_ubik_version_counter = -1;
+static int hf_afs_ubik_votestart = -1;
+static int hf_afs_ubik_state = -1;
+static int hf_afs_ubik_site = -1;
+static int hf_afs_ubik_interface = -1;
+static int hf_afs_ubik_file = -1;
+static int hf_afs_ubik_pos = -1;
+static int hf_afs_ubik_length = -1;
+static int hf_afs_ubik_locktype = -1;
+static int hf_afs_ubik_voteend = -1;
+static int hf_afs_ubik_votetype = -1;
+
+static int hf_afs_ubik_now = -1;
+static int hf_afs_ubik_lastyestime = -1;
+static int hf_afs_ubik_lastyeshost = -1;
+static int hf_afs_ubik_lastyesstate = -1;
+static int hf_afs_ubik_lastyesclaim = -1;
+static int hf_afs_ubik_lowesthost = -1;
+static int hf_afs_ubik_lowesttime = -1;
+static int hf_afs_ubik_synchost = -1;
+static int hf_afs_ubik_synctime = -1;
+static int hf_afs_ubik_amsyncsite = -1;
+static int hf_afs_ubik_syncsiteuntil = -1;
+static int hf_afs_ubik_nservers = -1;
+static int hf_afs_ubik_lockedpages = -1;
+static int hf_afs_ubik_writelockedpages = -1;
+static int hf_afs_ubik_activewrite = -1;
+static int hf_afs_ubik_tidcounter = -1;
+static int hf_afs_ubik_anyreadlocks = -1;
+static int hf_afs_ubik_anywritelocks = -1;
+static int hf_afs_ubik_recoverystate = -1;
+static int hf_afs_ubik_currenttrans = -1;
+static int hf_afs_ubik_writetrans = -1;
+static int hf_afs_ubik_epochtime = -1;
+static int hf_afs_ubik_isclone = -1;
+static int hf_afs_ubik_addr = -1;
+static int hf_afs_ubik_lastvotetime = -1;
+static int hf_afs_ubik_lastbeaconsent = -1;
+static int hf_afs_ubik_lastvote = -1;
+static int hf_afs_ubik_currentdb = -1;
+static int hf_afs_ubik_beaconsincedown = -1;
+static int hf_afs_ubik_up = -1;
+static int hf_afs_repframe = -1;
+static int hf_afs_reqframe = -1;
+static int hf_afs_time = -1;
+
+static gint ett_afs = -1;
+static gint ett_afs_op = -1;
+static gint ett_afs_acl = -1;
+static gint ett_afs_fid = -1;
+static gint ett_afs_callback = -1;
+static gint ett_afs_ubikver = -1;
+static gint ett_afs_status = -1;
+static gint ett_afs_status_mask = -1;
+static gint ett_afs_volsync = -1;
+static gint ett_afs_volumeinfo = -1;
+static gint ett_afs_vicestat = -1;
+static gint ett_afs_vldb_flags = -1;
diff --git a/epan/dissectors/packet-afs-macros.h b/epan/dissectors/packet-afs-macros.h
new file mode 100644
index 0000000000..0f84032b4b
--- /dev/null
+++ b/epan/dissectors/packet-afs-macros.h
@@ -0,0 +1,538 @@
+/* packet-afs-macros.h
+ * Helper macros for AFS packet dissection
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ * Based on routines from tcpdump patches by
+ * Ken Hornstein <kenh@cmf.nrl.navy.mil>
+ * Portions based on information retrieved from the RX definitions
+ * in Arla, the free AFS client at http://www.stacken.kth.se/project/arla/
+ * Portions based on information/specs retrieved from the OpenAFS sources at
+ * www.openafs.org, Copyright IBM.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/*
+ * Macros for helper dissection routines
+ *
+ * The macros are here to save on coding. They assume that
+ * the current offset is in 'offset', and that the offset
+ * should be incremented after performing the macro's operation.
+ */
+
+
+/* Output a unsigned integer, stored into field 'field'
+ Assumes it is in network byte order, converts to host before using */
+#define OUT_UINT(field) \
+ proto_tree_add_uint(tree, field, tvb, offset, sizeof(guint32), tvb_get_ntohl(tvb, offset)); \
+ offset += 4;
+
+/* Output a unsigned integer, stored into field 'field'
+ Assumes it is in network byte order, converts to host before using */
+#define OUT_INT(field) \
+ proto_tree_add_int(tree, field, tvb, offset, sizeof(gint32), tvb_get_ntohl(tvb, offset)); \
+ offset += 4;
+
+/* Output a unsigned integer, stored into field 'field'
+ Assumes it is in network byte order, converts to host before using */
+#define OUT_UINT64(field) \
+ proto_tree_add_item(tree, field, tvb, offset, 8, FALSE); \
+ offset += 8;
+
+/* Output a unsigned integer, stored into field 'field'
+ Assumes it is in network byte order, converts to host before using */
+#define OUT_INT64(field) \
+ proto_tree_add_item(tree, field, tvb, offset, 8, FALSE); \
+ offset += 8;
+
+/* Output a unsigned integer, stored into field 'field'
+ Assumes it is in network byte order, converts to host before using,
+ Note - does not increment offset, so can be used repeatedly for bitfields */
+#define DISP_UINT(field) \
+ proto_tree_add_uint(tree,field,tvb,offset,sizeof(guint32),tvb_get_ntohl(tvb, offset));
+
+/* Output an IPv4 address, stored into field 'field' */
+#define OUT_IP(field) \
+ proto_tree_add_ipv4(tree,field,tvb,offset,sizeof(gint32),\
+ tvb_get_letohl(tvb, offset));\
+ offset += 4;
+
+/* Output a simple rx array */
+#define OUT_RXArray8(func) \
+ { \
+ unsigned int j,i; \
+ j = tvb_get_guint8(tvb, offset); \
+ offset += 1; \
+ for (i=0; i<j; i++) { \
+ func; \
+ } \
+ }
+
+/* Output a simple rx array */
+#define OUT_RXArray32(func) \
+ { \
+ unsigned int j,i; \
+ j = tvb_get_ntohl(tvb, offset); \
+ offset += sizeof(guint32); \
+ for (i=0; i<j; i++) { \
+ func; \
+ } \
+ }
+
+/* Output a UNIX seconds/microseconds timestamp, after converting to an
+ nstime_t */
+#define OUT_TIMESTAMP(field) \
+ { nstime_t ts; \
+ ts.secs = tvb_get_ntohl(tvb, offset); \
+ ts.nsecs = tvb_get_ntohl(tvb, offset)*1000; \
+ proto_tree_add_time(tree,field, tvb,offset,2*sizeof(guint32),&ts); \
+ offset += 8; \
+ }
+
+/* Output a seconds-only time value, after converting to an nstime_t;
+ this can be an absolute time as a UNIX time-since-epoch, or a
+ relative time in seconds */
+#define OUT_TIMESECS(field) \
+ { nstime_t ts; \
+ ts.secs = tvb_get_ntohl(tvb, offset); \
+ ts.nsecs = 0; \
+ proto_tree_add_time(tree,field, tvb,offset,sizeof(guint32),&ts); \
+ offset += 4; \
+ }
+
+/* Output a rx style string, up to a maximum length first
+ 4 bytes - length, then char data */
+#define OUT_RXString(field) \
+ { guint32 i,len; \
+ char *tmp; \
+ const guint8 *p; \
+ i = tvb_get_ntohl(tvb, offset); \
+ offset += 4; \
+ p = tvb_get_ptr(tvb,offset,i); \
+ len = ((i+4-1)/4)*4; \
+ tmp = g_malloc(i+1); \
+ memcpy(tmp, p, i); \
+ tmp[i] = '\0'; \
+ proto_tree_add_string(tree, field, tvb, offset-4, len+4, \
+ (void *)tmp); \
+ g_free(tmp); \
+ offset += len; \
+ }
+
+/* Output a fixed length vectorized string (each char is a 32 bit int) */
+#define OUT_RXStringV(field, length) \
+ { char tmp[length+1]; \
+ int i,soff; \
+ soff = offset;\
+ for (i=0; i<length; i++)\
+ {\
+ tmp[i] = (char) tvb_get_ntohl(tvb, offset);\
+ offset += sizeof(guint32);\
+ }\
+ tmp[length] = '\0';\
+ proto_tree_add_string(tree, field, tvb, soff, length*sizeof(guint32), tmp);\
+ }
+
+
+/* Output a callback */
+#define OUT_FS_AFSCallBack() \
+ { proto_tree *save, *ti; \
+ ti = proto_tree_add_text(tree, tvb, offset, 3*4, "Callback"); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_callback); \
+ OUT_UINT(hf_afs_fs_callback_version); \
+ OUT_TIMESECS(hf_afs_fs_callback_expires); \
+ OUT_UINT(hf_afs_fs_callback_type); \
+ tree = save; \
+ }
+
+/* Output a callback */
+#define OUT_CB_AFSCallBack() \
+ { proto_tree *save, *ti; \
+ ti = proto_tree_add_text(tree, tvb, offset, 3*4, "Callback"); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_callback); \
+ OUT_UINT(hf_afs_cb_callback_version); \
+ OUT_TIMESECS(hf_afs_cb_callback_expires); \
+ OUT_UINT(hf_afs_cb_callback_type); \
+ tree = save; \
+ }
+
+/* Output a File ID */
+#define OUT_FS_AFSFid(label) \
+ { proto_tree *save, *ti; \
+ ti = proto_tree_add_text(tree, tvb, offset, 3*4, \
+ "FileID (%s)", label); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_fid); \
+ OUT_UINT(hf_afs_fs_fid_volume); \
+ OUT_UINT(hf_afs_fs_fid_vnode); \
+ OUT_UINT(hf_afs_fs_fid_uniqifier); \
+ tree = save; \
+ }
+
+/* Output a Status mask */
+#define OUT_FS_STATUSMASK() \
+ { proto_tree *save, *ti; \
+ guint32 mask; \
+ mask = tvb_get_ntohl(tvb, offset); \
+ ti = proto_tree_add_uint(tree, hf_afs_fs_status_mask, tvb, offset, \
+ sizeof(guint32), mask); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_status_mask); \
+ proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setmodtime, \
+ tvb,offset,sizeof(guint32), mask); \
+ proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setowner, \
+ tvb,offset,sizeof(guint32), mask); \
+ proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setgroup, \
+ tvb,offset,sizeof(guint32), mask); \
+ proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setmode, \
+ tvb,offset,sizeof(guint32), mask); \
+ proto_tree_add_boolean(tree, hf_afs_fs_status_mask_setsegsize, \
+ tvb,offset,sizeof(guint32), mask); \
+ proto_tree_add_boolean(tree, hf_afs_fs_status_mask_fsync, \
+ tvb,offset,sizeof(guint32), mask); \
+ offset += 4; \
+ tree = save; \
+ }
+
+/* Output vldb flags */
+#define OUT_VLDB_Flags() \
+ { proto_tree *save, *ti; \
+ guint32 flags; \
+ flags = tvb_get_ntohl(tvb, offset); \
+ ti = proto_tree_add_uint(tree, hf_afs_vldb_flags, tvb, offset, \
+ sizeof(guint32), flags); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_vldb_flags); \
+ proto_tree_add_boolean(tree, hf_afs_vldb_flags_rwexists, \
+ tvb,offset,sizeof(guint32), flags); \
+ proto_tree_add_boolean(tree, hf_afs_vldb_flags_roexists, \
+ tvb,offset,sizeof(guint32), flags); \
+ proto_tree_add_boolean(tree, hf_afs_vldb_flags_bkexists, \
+ tvb,offset,sizeof(guint32), flags); \
+ proto_tree_add_boolean(tree, hf_afs_vldb_flags_dfsfileset, \
+ tvb,offset,sizeof(guint32), flags); \
+ offset += 4; \
+ tree = save; \
+ }
+
+
+
+/* Output a File ID */
+#define OUT_CB_AFSFid(label) \
+ { proto_tree *save, *ti; \
+ ti = proto_tree_add_text(tree, tvb, offset, 3*4, \
+ "FileID (%s)", label); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_fid); \
+ OUT_UINT(hf_afs_cb_fid_volume); \
+ OUT_UINT(hf_afs_cb_fid_vnode); \
+ OUT_UINT(hf_afs_cb_fid_uniqifier); \
+ tree = save; \
+ }
+
+/* Output a StoreStatus */
+#define OUT_FS_AFSStoreStatus(label) \
+ { proto_tree *save, *ti; \
+ ti = proto_tree_add_text(tree, tvb, offset, 6*4, \
+ label); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_status); \
+ OUT_FS_STATUSMASK(); \
+ OUT_TIMESECS(hf_afs_fs_status_clientmodtime); \
+ OUT_UINT(hf_afs_fs_status_owner); \
+ OUT_UINT(hf_afs_fs_status_group); \
+ OUT_UINT(hf_afs_fs_status_mode); \
+ OUT_UINT(hf_afs_fs_status_segsize); \
+ tree = save; \
+ }
+
+/* Output a FetchStatus */
+#define OUT_FS_AFSFetchStatus(label) \
+ { proto_tree *save, *ti; \
+ ti = proto_tree_add_text(tree, tvb, offset, 21*4, \
+ label); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_status); \
+ OUT_UINT(hf_afs_fs_status_interfaceversion); \
+ OUT_UINT(hf_afs_fs_status_filetype); \
+ OUT_UINT(hf_afs_fs_status_linkcount); \
+ OUT_UINT(hf_afs_fs_status_length); \
+ OUT_UINT(hf_afs_fs_status_dataversion); \
+ OUT_UINT(hf_afs_fs_status_author); \
+ OUT_UINT(hf_afs_fs_status_owner); \
+ OUT_UINT(hf_afs_fs_status_calleraccess); \
+ OUT_UINT(hf_afs_fs_status_anonymousaccess); \
+ OUT_UINT(hf_afs_fs_status_mode); \
+ OUT_UINT(hf_afs_fs_status_parentvnode); \
+ OUT_UINT(hf_afs_fs_status_parentunique); \
+ OUT_UINT(hf_afs_fs_status_segsize); \
+ OUT_TIMESECS(hf_afs_fs_status_clientmodtime); \
+ OUT_TIMESECS(hf_afs_fs_status_servermodtime); \
+ OUT_UINT(hf_afs_fs_status_group); \
+ OUT_UINT(hf_afs_fs_status_synccounter); \
+ OUT_UINT(hf_afs_fs_status_dataversionhigh); \
+ OUT_UINT(hf_afs_fs_status_spare2); \
+ OUT_UINT(hf_afs_fs_status_spare3); \
+ OUT_UINT(hf_afs_fs_status_spare4); \
+ tree = save; \
+ }
+
+/* Output a VolSync */
+#define OUT_FS_AFSVolSync() \
+ { proto_tree *save, *ti; \
+ ti = proto_tree_add_text(tree, tvb, offset, 6*4, \
+ "VolSync"); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_volsync); \
+ OUT_TIMESECS(hf_afs_fs_volsync_spare1); \
+ OUT_UINT(hf_afs_fs_volsync_spare2); \
+ OUT_UINT(hf_afs_fs_volsync_spare3); \
+ OUT_UINT(hf_afs_fs_volsync_spare4); \
+ OUT_UINT(hf_afs_fs_volsync_spare5); \
+ OUT_UINT(hf_afs_fs_volsync_spare6); \
+ tree = save; \
+ }
+
+/* Output a AFSCBFids */
+#define OUT_FS_AFSCBFids() \
+ OUT_RXArray32(OUT_FS_AFSFid("Target"));
+
+/* Output a ViceIds */
+#define OUT_FS_ViceIds() \
+ OUT_RXArray8(OUT_UINT(hf_afs_fs_viceid));
+
+/* Output a IPAddrs */
+#define OUT_FS_IPAddrs() \
+ OUT_RXArray8(OUT_IP(hf_afs_fs_ipaddr));
+
+/* Output a AFSCBs */
+#define OUT_FS_AFSCBs() \
+ OUT_RXArray32(OUT_FS_AFSCallBack());
+
+/* Output a AFSBulkStats */
+#define OUT_FS_AFSBulkStats() \
+ OUT_RXArray32(OUT_FS_AFSFetchStatus("Status"));
+
+/* Output a AFSFetchVolumeStatus */
+#define OUT_FS_AFSFetchVolumeStatus()
+
+/* Output a AFSStoreVolumeStatus */
+#define OUT_FS_AFSStoreVolumeStatus()
+
+/* Output a ViceStatistics structure */
+#define OUT_FS_ViceStatistics()
+
+/* Output a AFS_CollData structure */
+#define OUT_FS_AFS_CollData()
+
+/* Output a VolumeInfo structure */
+#define OUT_FS_VolumeInfo()
+
+/* Output an AFS Token - might just be bytes though */
+#define OUT_FS_AFSTOKEN() OUT_RXStringV(hf_afs_fs_token, 1024)
+
+/* Output a AFS acl */
+#define ACLOUT(who, positive, acl, bytes) \
+ { proto_tree *save, *ti; \
+ int tmpoffset; \
+ int acllen; \
+ char tmp[10]; \
+ tmp[0] = 0; \
+ if ( acl & PRSFS_READ ) strcat(tmp, "r"); \
+ if ( acl & PRSFS_LOOKUP ) strcat(tmp, "l"); \
+ if ( acl & PRSFS_INSERT ) strcat(tmp, "i"); \
+ if ( acl & PRSFS_DELETE ) strcat(tmp, "d"); \
+ if ( acl & PRSFS_WRITE ) strcat(tmp, "w"); \
+ if ( acl & PRSFS_LOCK ) strcat(tmp, "k"); \
+ if ( acl & PRSFS_ADMINISTER ) strcat(tmp, "a"); \
+ ti = proto_tree_add_text(tree, tvb, offset, bytes, \
+ "ACL: %s %s%s", \
+ who, tmp, positive ? "" : " (negative)"); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_acl); \
+ proto_tree_add_string(tree,hf_afs_fs_acl_entity, tvb,offset,strlen(who), who);\
+ tmpoffset = offset + strlen(who) + 1; \
+ acllen = bytes - strlen(who) - 1; \
+ proto_tree_add_boolean(tree,hf_afs_fs_acl_r, tvb,tmpoffset,acllen,acl);\
+ proto_tree_add_boolean(tree,hf_afs_fs_acl_l, tvb,tmpoffset,acllen,acl);\
+ proto_tree_add_boolean(tree,hf_afs_fs_acl_i, tvb,tmpoffset,acllen,acl);\
+ proto_tree_add_boolean(tree,hf_afs_fs_acl_d, tvb,tmpoffset,acllen,acl);\
+ proto_tree_add_boolean(tree,hf_afs_fs_acl_w, tvb,tmpoffset,acllen,acl);\
+ proto_tree_add_boolean(tree,hf_afs_fs_acl_k, tvb,tmpoffset,acllen,acl);\
+ proto_tree_add_boolean(tree,hf_afs_fs_acl_a, tvb,tmpoffset,acllen,acl);\
+ tree = save; \
+ }
+
+/* Output a UUID */
+#define OUT_UUID(x) \
+ OUT_BYTES(x, 11*sizeof(guint32));
+#define SKIP_UUID() \
+ SKIP(11*sizeof(guint32));
+
+
+/* Output a bulkaddr */
+#define OUT_VLDB_BulkAddr() \
+ OUT_RXArray32(OUT_IP(hf_afs_vldb_serverip));
+
+/* output a bozo_key */
+#define OUT_BOS_KEY() \
+ OUT_BYTES(hf_afs_bos_key, 8);
+
+/* output a bozo_key */
+#define OUT_BOS_KEYINFO() \
+ OUT_TIMESTAMP(hf_afs_bos_keymodtime); \
+ OUT_UINT(hf_afs_bos_keychecksum); \
+ OUT_UINT(hf_afs_bos_keyspare2);
+
+/* output a bozo_netKTime */
+#define OUT_BOS_TIME() \
+ SKIP(4); SKIP(2); SKIP(2); SKIP(2); SKIP(2);
+
+/* output a bozo_status */
+#define OUT_BOS_STATUS() \
+ SKIP(10 * 4);
+
+/* output a ubik interface addr array */
+#define OUT_UBIK_InterfaceAddrs() \
+ { \
+ unsigned int i,j,seen_null=0; \
+ for (i=0; i<255; i++) { \
+ j = tvb_get_ntohl(tvb, offset); \
+ if ( j != 0 ) { \
+ OUT_IP(hf_afs_ubik_interface); \
+ seen_null = 0; \
+ } else { \
+ if ( ! seen_null ) { \
+ proto_tree_add_text(tree, tvb, offset, \
+ tvb_length_remaining(tvb, offset), \
+ "Null Interface Addresses"); \
+ seen_null = 1; \
+ } \
+ offset += 4; \
+ }\
+ } \
+ }
+
+#define OUT_UBIK_DebugOld() \
+ { \
+ OUT_TIMESECS(hf_afs_ubik_now); \
+ OUT_TIMESECS(hf_afs_ubik_lastyestime); \
+ OUT_IP(hf_afs_ubik_lastyeshost); \
+ OUT_UINT(hf_afs_ubik_lastyesstate); \
+ OUT_TIMESECS(hf_afs_ubik_lastyesclaim); \
+ OUT_IP(hf_afs_ubik_lowesthost); \
+ OUT_TIMESECS(hf_afs_ubik_lowesttime); \
+ OUT_IP(hf_afs_ubik_synchost); \
+ OUT_TIMESECS(hf_afs_ubik_synctime); \
+ OUT_UBIKVERSION("Sync Version"); \
+ OUT_UBIKVERSION("Sync TID"); \
+ OUT_UINT(hf_afs_ubik_amsyncsite); \
+ OUT_TIMESECS(hf_afs_ubik_syncsiteuntil); \
+ OUT_UINT(hf_afs_ubik_nservers); \
+ OUT_UINT(hf_afs_ubik_lockedpages); \
+ OUT_UINT(hf_afs_ubik_writelockedpages); \
+ OUT_UBIKVERSION("Local Version"); \
+ OUT_UINT(hf_afs_ubik_activewrite); \
+ OUT_UINT(hf_afs_ubik_tidcounter); \
+ OUT_UINT(hf_afs_ubik_anyreadlocks); \
+ OUT_UINT(hf_afs_ubik_anywritelocks); \
+ OUT_UINT(hf_afs_ubik_recoverystate); \
+ OUT_UINT(hf_afs_ubik_currenttrans); \
+ OUT_UINT(hf_afs_ubik_writetrans); \
+ OUT_TIMESECS(hf_afs_ubik_epochtime); \
+ }
+
+#define OUT_UBIK_SDebugOld() \
+ { \
+ OUT_IP(hf_afs_ubik_addr); \
+ OUT_TIMESECS(hf_afs_ubik_lastvotetime); \
+ OUT_TIMESECS(hf_afs_ubik_lastbeaconsent); \
+ OUT_UINT(hf_afs_ubik_lastvote); \
+ OUT_UBIKVERSION("Remote Version"); \
+ OUT_UINT(hf_afs_ubik_currentdb); \
+ OUT_UINT(hf_afs_ubik_beaconsincedown); \
+ OUT_UINT(hf_afs_ubik_up); \
+ }
+
+/* Skip a certain number of bytes */
+#define SKIP(bytes) \
+ offset += bytes;
+
+/* Raw data - to end of frame */
+#define OUT_BYTES_ALL(field) OUT_BYTES(field, tvb_length_remaining(tvb,offset))
+
+/* Raw data */
+#define OUT_BYTES(field, bytes) \
+ proto_tree_add_item(tree, field, tvb, offset, bytes, FALSE);\
+ offset += bytes;
+
+
+
+/* Skip the opcode */
+#define SKIP_OPCODE() \
+ { \
+ SKIP(sizeof(guint32)); \
+ }
+
+/* Output a UBIK version code */
+#define OUT_UBIKVERSION(label) \
+ { proto_tree *save, *ti; \
+ unsigned int epoch,counter; \
+ nstime_t ts; \
+ epoch = tvb_get_ntohl(tvb, offset); \
+ offset += 4; \
+ counter = tvb_get_ntohl(tvb, offset); \
+ offset += 4; \
+ ts.secs = epoch; \
+ ts.nsecs = 0; \
+ ti = proto_tree_add_text(tree, tvb, offset-8, 8, \
+ "UBIK Version (%s): %u.%u", label, epoch, counter ); \
+ save = tree; \
+ tree = proto_item_add_subtree(ti, ett_afs_ubikver); \
+ if ( epoch != 0 ) \
+ proto_tree_add_time(tree,hf_afs_ubik_version_epoch, tvb,offset-8, \
+ sizeof(guint32),&ts); \
+ else \
+ proto_tree_add_text(tree, tvb, offset-8, \
+ sizeof(guint32),"Epoch: 0"); \
+ proto_tree_add_uint(tree,hf_afs_ubik_version_counter, tvb,offset-4, \
+ sizeof(guint32),counter); \
+ tree = save; \
+ }
+
+/* Output a kauth getticket request */
+#define OUT_KAUTH_GetTicket() \
+ { \
+ int len = 0; \
+ OUT_UINT(hf_afs_kauth_kvno); \
+ OUT_RXString(hf_afs_kauth_domain); \
+ len = tvb_get_ntohl(tvb, offset); \
+ offset += 4; \
+ OUT_BYTES(hf_afs_kauth_data, len); \
+ OUT_RXString(hf_afs_kauth_princ); \
+ OUT_RXString(hf_afs_kauth_realm); \
+ }
+
diff --git a/epan/dissectors/packet-afs-register-info.h b/epan/dissectors/packet-afs-register-info.h
new file mode 100644
index 0000000000..7b3d116c52
--- /dev/null
+++ b/epan/dissectors/packet-afs-register-info.h
@@ -0,0 +1,585 @@
+/* packet-afs-register-info.h
+ * Routines for AFS packet dissection
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ * Based on routines from tcpdump patches by
+ * Ken Hornstein <kenh@cmf.nrl.navy.mil>
+ * Portions based on information retrieved from the RX definitions
+ * in Arla, the free AFS client at http://www.stacken.kth.se/project/arla/
+ * Portions based on information/specs retrieved from the OpenAFS sources at
+ * www.openafs.org, Copyright IBM.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+{ &hf_afs_fs, { "File Server", "afs.fs",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "File Server", HFILL }},
+{ &hf_afs_cb, { "Callback", "afs.cb",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Callback", HFILL }},
+{ &hf_afs_prot, { "Protection", "afs.prot",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Protection Server", HFILL }},
+{ &hf_afs_vldb, { "VLDB", "afs.vldb",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Volume Location Database Server", HFILL }},
+{ &hf_afs_kauth, { "KAuth", "afs.kauth",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Kerberos Auth Server", HFILL }},
+{ &hf_afs_vol, { "Volume Server", "afs.vol",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Volume Server", HFILL }},
+{ &hf_afs_error, { "Error", "afs.error",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Error", HFILL }},
+{ &hf_afs_bos, { "BOS", "afs.bos",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Basic Oversee Server", HFILL }},
+{ &hf_afs_update, { "Update", "afs.update",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Update Server", HFILL }},
+{ &hf_afs_rmtsys, { "Rmtsys", "afs.rmtsys",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Rmtsys", HFILL }},
+{ &hf_afs_ubik, { "Ubik", "afs.ubik",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Ubik", HFILL }},
+{ &hf_afs_backup, { "Backup", "afs.backup",
+ FT_BOOLEAN, BASE_NONE, 0, 0, "Backup Server", HFILL }},
+
+{ &hf_afs_fs_opcode, { "Operation", "afs.fs.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(fs_req), 0, "Operation", HFILL }},
+{ &hf_afs_cb_opcode, { "Operation", "afs.cb.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(cb_req), 0, "Operation", HFILL }},
+{ &hf_afs_prot_opcode, { "Operation", "afs.prot.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(prot_req), 0, "Operation", HFILL }},
+{ &hf_afs_vldb_opcode, { "Operation", "afs.vldb.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(vldb_req), 0, "Operation", HFILL }},
+{ &hf_afs_kauth_opcode, { "Operation", "afs.kauth.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(kauth_req), 0, "Operation", HFILL }},
+{ &hf_afs_vol_opcode, { "Operation", "afs.vol.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(vol_req), 0, "Operation", HFILL }},
+{ &hf_afs_bos_opcode, { "Operation", "afs.bos.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(bos_req), 0, "Operation", HFILL }},
+{ &hf_afs_update_opcode, { "Operation", "afs.update.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(update_req), 0, "Operation", HFILL }},
+{ &hf_afs_rmtsys_opcode, { "Operation", "afs.rmtsys.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(rmtsys_req), 0, "Operation", HFILL }},
+{ &hf_afs_error_opcode, { "Operation", "afs.error.opcode",
+ FT_UINT32, BASE_DEC,
+ 0, 0, "Operation", HFILL }},
+{ &hf_afs_backup_opcode, {
+ "Operation", "afs.backup.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(backup_req), 0, "Operation", HFILL }},
+{ &hf_afs_ubik_opcode, {
+ "Operation", "afs.ubik.opcode",
+ FT_UINT32, BASE_DEC,
+ VALS(ubik_req), 0, "Operation", HFILL }},
+
+
+/* File Server Fields */
+{ &hf_afs_fs_fid_volume, { "FileID (Volume)", "afs.fs.fid.volume",
+ FT_UINT32, BASE_DEC,
+ 0, 0, "File ID (Volume)", HFILL }},
+{ &hf_afs_fs_fid_vnode, { "FileID (VNode)", "afs.fs.fid.vnode",
+ FT_UINT32, BASE_DEC,
+ 0, 0, "File ID (VNode)", HFILL }},
+{ &hf_afs_fs_fid_uniqifier, { "FileID (Uniqifier)", "afs.fs.fid.uniq",
+ FT_UINT32, BASE_DEC,
+ 0, 0, "File ID (Uniqifier)", HFILL }},
+{ &hf_afs_fs_offset, { "Offset", "afs.fs.offset",
+ FT_UINT32, BASE_DEC,
+ 0, 0, "Offset", HFILL }},
+{ &hf_afs_fs_length, { "Length", "afs.fs.length",
+ FT_UINT32, BASE_DEC, 0, 0, "Length", HFILL }},
+{ &hf_afs_fs_flength, { "FLength", "afs.fs.flength",
+ FT_UINT32, BASE_DEC, 0, 0, "FLength", HFILL }},
+{ &hf_afs_fs_offset64, { "Offset64", "afs.fs.offset64",
+ FT_UINT64, BASE_DEC,
+ 0, 0, "Offset64", HFILL }},
+{ &hf_afs_fs_length64, { "Length64", "afs.fs.length64",
+ FT_UINT64, BASE_DEC, 0, 0, "Length64", HFILL }},
+{ &hf_afs_fs_flength64, { "FLength64", "afs.fs.flength64",
+ FT_UINT64, BASE_DEC, 0, 0, "FLength64", HFILL }},
+{ &hf_afs_fs_errcode, { "Error Code", "afs.fs.errcode",
+ FT_UINT32, BASE_DEC, VALS(afs_errors), 0, "Error Code", HFILL }},
+{ &hf_afs_fs_data, { "Data", "afs.fs.data",
+ FT_BYTES, BASE_HEX, 0, 0, "Data", HFILL }},
+{ &hf_afs_fs_token, { "Token", "afs.fs.token",
+ FT_BYTES, BASE_HEX, 0, 0, "Token", HFILL }},
+{ &hf_afs_fs_oldname, { "Old Name", "afs.fs.oldname",
+ FT_STRING, BASE_HEX, 0, 0, "Old Name", HFILL }},
+{ &hf_afs_fs_newname, { "New Name", "afs.fs.newname",
+ FT_STRING, BASE_HEX, 0, 0, "New Name", HFILL }},
+{ &hf_afs_fs_name, { "Name", "afs.fs.name",
+ FT_STRING, BASE_HEX, 0, 0, "Name", HFILL }},
+{ &hf_afs_fs_symlink_name, { "Symlink Name", "afs.fs.symlink.name",
+ FT_STRING, BASE_HEX, 0, 0, "Symlink Name", HFILL }},
+{ &hf_afs_fs_symlink_content, { "Symlink Content", "afs.fs.symlink.content",
+ FT_STRING, BASE_HEX, 0, 0, "Symlink Content", HFILL }},
+{ &hf_afs_fs_volid, { "Volume ID", "afs.fs.volid",
+ FT_UINT32, BASE_DEC, 0, 0, "Volume ID", HFILL }},
+{ &hf_afs_fs_volname, { "Volume Name", "afs.fs.volname",
+ FT_STRING, BASE_HEX, 0, 0, "Volume Name", HFILL }},
+{ &hf_afs_fs_timestamp, { "Timestamp", "afs.fs.timestamp",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Timestamp", HFILL }},
+{ &hf_afs_fs_offlinemsg, { "Offline Message", "afs.fs.offlinemsg",
+ FT_STRING, BASE_HEX, 0, 0, "Volume Name", HFILL }},
+{ &hf_afs_fs_motd, { "Message of the Day", "afs.fs.motd",
+ FT_STRING, BASE_HEX, 0, 0, "Message of the Day", HFILL }},
+{ &hf_afs_fs_xstats_version, { "XStats Version", "afs.fs.xstats.version",
+ FT_UINT32, BASE_DEC, 0, 0, "XStats Version", HFILL }},
+{ &hf_afs_fs_xstats_clientversion, { "Client Version", "afs.fs.xstats.clientversion",
+ FT_UINT32, BASE_DEC, 0, 0, "Client Version", HFILL }},
+{ &hf_afs_fs_xstats_collnumber, { "Collection Number", "afs.fs.xstats.collnumber",
+ FT_UINT32, BASE_DEC, VALS(xstat_collections), 0, "Collection Number", HFILL }},
+{ &hf_afs_fs_xstats_timestamp, { "XStats Timestamp", "afs.fs.xstats.timestamp",
+ FT_UINT32, BASE_DEC, 0, 0, "XStats Timestamp", HFILL }},
+{ &hf_afs_fs_cps_spare1, { "CPS Spare1", "afs.fs.cps.spare1",
+ FT_UINT32, BASE_DEC, 0, 0, "CPS Spare1", HFILL }},
+{ &hf_afs_fs_cps_spare2, { "CPS Spare2", "afs.fs.cps.spare2",
+ FT_UINT32, BASE_DEC, 0, 0, "CPS Spare2", HFILL }},
+{ &hf_afs_fs_cps_spare3, { "CPS Spare3", "afs.fs.cps.spare3",
+ FT_UINT32, BASE_DEC, 0, 0, "CPS Spare3", HFILL }},
+{ &hf_afs_fs_vicelocktype, { "Vice Lock Type", "afs.fs.vicelocktype",
+ FT_UINT32, BASE_DEC, VALS(vice_lock_types), 0, "Vice Lock Type", HFILL }},
+/* XXX - is this an IP address? */
+{ &hf_afs_fs_viceid, { "Vice ID", "afs.fs.viceid",
+ FT_UINT32, BASE_DEC, 0, 0, "Vice ID", HFILL }},
+
+{ &hf_afs_fs_status_mask, { "Mask", "afs.fs.status.mask",
+ FT_UINT32, BASE_HEX, 0, 0, "Mask", HFILL }},
+{ &hf_afs_fs_status_mask_setmodtime, { "Set Modification Time", "afs.fs.status.mask.setmodtime",
+ FT_BOOLEAN, 32, 0, 0x00000001, "Set Modification Time", HFILL }},
+{ &hf_afs_fs_status_mask_setowner, { "Set Owner", "afs.fs.status.mask.setowner",
+ FT_BOOLEAN, 32, 0, 0x00000002, "Set Owner", HFILL }},
+{ &hf_afs_fs_status_mask_setgroup, { "Set Group", "afs.fs.status.mask.setgroup",
+ FT_BOOLEAN, 32, 0, 0x00000004, "Set Group", HFILL }},
+{ &hf_afs_fs_status_mask_setmode, { "Set Mode", "afs.fs.status.mask.setmode",
+ FT_BOOLEAN, 32, 0, 0x00000008, "Set Mode", HFILL }},
+{ &hf_afs_fs_status_mask_setsegsize, { "Set Segment Size", "afs.fs.status.mask.setsegsize",
+ FT_BOOLEAN, 32, 0, 0x00000010, "Set Segment Size", HFILL }},
+{ &hf_afs_fs_status_mask_fsync, { "FSync", "afs.fs.status.mask.fsync",
+ FT_BOOLEAN, 32, 0, 0x00000400, "FSync", HFILL }},
+
+{ &hf_afs_fs_status_clientmodtime, { "Client Modification Time", "afs.fs.status.clientmodtime",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Client Modification Time", HFILL }},
+{ &hf_afs_fs_status_servermodtime, { "Server Modification Time", "afs.fs.status.servermodtime",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Server Modification Time", HFILL }},
+{ &hf_afs_fs_status_owner, { "Owner", "afs.fs.status.owner",
+ FT_UINT32, BASE_DEC, 0, 0, "Owner", HFILL }},
+{ &hf_afs_fs_status_group, { "Group", "afs.fs.status.group",
+ FT_UINT32, BASE_DEC, 0, 0, "Group", HFILL }},
+{ &hf_afs_fs_status_mode, { "Unix Mode", "afs.fs.status.mode",
+ FT_UINT32, BASE_OCT, 0, 0, "Unix Mode", HFILL }},
+{ &hf_afs_fs_status_segsize, { "Segment Size", "afs.fs.status.segsize",
+ FT_UINT32, BASE_DEC, 0, 0, "Segment Size", HFILL }},
+{ &hf_afs_fs_status_interfaceversion, { "Interface Version", "afs.fs.status.interfaceversion",
+ FT_UINT32, BASE_DEC, 0, 0, "Interface Version", HFILL }},
+{ &hf_afs_fs_status_filetype, { "File Type", "afs.fs.status.filetype",
+ FT_UINT32, BASE_DEC, 0, 0, "File Type", HFILL }},
+{ &hf_afs_fs_status_author, { "Author", "afs.fs.status.author",
+ FT_UINT32, BASE_DEC, 0, 0, "Author", HFILL }},
+{ &hf_afs_fs_status_calleraccess, { "Caller Access", "afs.fs.status.calleraccess",
+ FT_UINT32, BASE_DEC, 0, 0, "Caller Access", HFILL }},
+{ &hf_afs_fs_status_anonymousaccess, { "Anonymous Access", "afs.fs.status.anonymousaccess",
+ FT_UINT32, BASE_DEC, 0, 0, "Anonymous Access", HFILL }},
+{ &hf_afs_fs_status_parentvnode, { "Parent VNode", "afs.fs.status.parentvnode",
+ FT_UINT32, BASE_DEC, 0, 0, "Parent VNode", HFILL }},
+{ &hf_afs_fs_status_parentunique, { "Parent Unique", "afs.fs.status.parentunique",
+ FT_UINT32, BASE_DEC, 0, 0, "Parent Unique", HFILL }},
+{ &hf_afs_fs_status_dataversion, { "Data Version", "afs.fs.status.dataversion",
+ FT_UINT32, BASE_DEC, 0, 0, "Data Version", HFILL }},
+{ &hf_afs_fs_status_dataversionhigh, { "Data Version (High)", "afs.fs.status.dataversionhigh",
+ FT_UINT32, BASE_DEC, 0, 0, "Data Version (High)", HFILL }},
+{ &hf_afs_fs_status_linkcount, { "Link Count", "afs.fs.status.linkcount",
+ FT_UINT32, BASE_DEC, 0, 0, "Link Count", HFILL }},
+{ &hf_afs_fs_status_spare2, { "Spare 2", "afs.fs.status.spare2",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 2", HFILL }},
+{ &hf_afs_fs_status_spare3, { "Spare 3", "afs.fs.status.spare3",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 3", HFILL }},
+{ &hf_afs_fs_status_spare4, { "Spare 4", "afs.fs.status.spare4",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 4", HFILL }},
+{ &hf_afs_fs_status_synccounter, { "Sync Counter", "afs.fs.status.synccounter",
+ FT_UINT32, BASE_DEC, 0, 0, "Sync Counter", HFILL }},
+{ &hf_afs_fs_status_length, { "Length", "afs.fs.status.length",
+ FT_UINT32, BASE_DEC, 0, 0, "Length", HFILL }},
+
+
+{ &hf_afs_fs_volsync_spare1, { "Volume Creation Timestamp", "afs.fs.volsync.spare1",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Volume Creation Timestamp", HFILL }},
+{ &hf_afs_fs_volsync_spare2, { "Spare 2", "afs.fs.volsync.spare2",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 2", HFILL }},
+{ &hf_afs_fs_volsync_spare3, { "Spare 3", "afs.fs.volsync.spare3",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 3", HFILL }},
+{ &hf_afs_fs_volsync_spare4, { "Spare 4", "afs.fs.volsync.spare4",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 4", HFILL }},
+{ &hf_afs_fs_volsync_spare5, { "Spare 5", "afs.fs.volsync.spare5",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 5", HFILL }},
+{ &hf_afs_fs_volsync_spare6, { "Spare 6", "afs.fs.volsync.spare6",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 6", HFILL }},
+
+
+{ &hf_afs_fs_acl_count_positive, {
+ "ACL Count (Positive)", "afs.fs.acl.count.positive",
+ FT_UINT32, BASE_DEC, 0, 0, "Number of Positive ACLs", HFILL }},
+{ &hf_afs_fs_acl_count_negative, {
+ "ACL Count (Negative)", "afs.fs.acl.count.negative",
+ FT_UINT32, BASE_DEC, 0, 0, "Number of Negative ACLs", HFILL }},
+{ &hf_afs_fs_acl_datasize, {
+ "ACL Size", "afs.fs.acl.datasize",
+ FT_UINT32, BASE_DEC, 0, 0, "ACL Data Size", HFILL }},
+{ &hf_afs_fs_acl_entity, {
+ "Entity (User/Group)", "afs.fs.acl.entity",
+ FT_STRING, BASE_HEX, 0, 0, "ACL Entity (User/Group)", HFILL }},
+{ &hf_afs_fs_acl_r, {
+ "_R_ead", "afs.fs.acl.r",
+ FT_BOOLEAN, 8, 0, PRSFS_READ, "Read", HFILL }},
+{ &hf_afs_fs_acl_l, {
+ "_L_ookup", "afs.fs.acl.l",
+ FT_BOOLEAN, 8, 0, PRSFS_LOOKUP, "Lookup", HFILL }},
+{ &hf_afs_fs_acl_i, {
+ "_I_nsert", "afs.fs.acl.i",
+ FT_BOOLEAN, 8, 0, PRSFS_INSERT, "Insert", HFILL }},
+{ &hf_afs_fs_acl_d, { "_D_elete", "afs.fs.acl.d",
+ FT_BOOLEAN, 8, 0, PRSFS_DELETE, "Delete", HFILL }},
+{ &hf_afs_fs_acl_w, { "_W_rite", "afs.fs.acl.w",
+ FT_BOOLEAN, 8, 0, PRSFS_WRITE, "Write", HFILL }},
+{ &hf_afs_fs_acl_k, { "_L_ock", "afs.fs.acl.k",
+ FT_BOOLEAN, 8, 0, PRSFS_LOCK, "Lock", HFILL }},
+{ &hf_afs_fs_acl_a, { "_A_dminister", "afs.fs.acl.a",
+ FT_BOOLEAN, 8, 0, PRSFS_ADMINISTER, "Administer", HFILL }},
+
+{ &hf_afs_fs_callback_version, { "Version", "afs.fs.callback.version",
+ FT_UINT32, BASE_DEC, 0, 0, "Version", HFILL }},
+{ &hf_afs_fs_callback_expires, { "Expires", "afs.fs.callback.expires",
+ FT_RELATIVE_TIME, BASE_NONE, 0, 0, "Expires", HFILL }},
+{ &hf_afs_fs_callback_type, { "Type", "afs.fs.callback.type",
+ FT_UINT32, BASE_DEC, VALS(cb_types), 0, "Type", HFILL }},
+
+/* BOS Server Fields */
+{ &hf_afs_bos_errcode, { "Error Code", "afs.bos.errcode",
+ FT_UINT32, BASE_DEC, VALS(afs_errors), 0, "Error Code", HFILL }},
+{ &hf_afs_bos_type, { "Type", "afs.bos.type",
+ FT_STRING, BASE_HEX, 0, 0, "Type", HFILL }},
+{ &hf_afs_bos_content, { "Content", "afs.bos.content",
+ FT_STRING, BASE_HEX, 0, 0, "Content", HFILL }},
+{ &hf_afs_bos_data, { "Data", "afs.bos.data",
+ FT_BYTES, BASE_HEX, 0, 0, "Data", HFILL }},
+{ &hf_afs_bos_path, { "Path", "afs.bos.path",
+ FT_STRING, BASE_HEX, 0, 0, "Path", HFILL }},
+{ &hf_afs_bos_parm, { "Parm", "afs.bos.parm",
+ FT_STRING, BASE_HEX, 0, 0, "Parm", HFILL }},
+{ &hf_afs_bos_error, { "Error", "afs.bos.error",
+ FT_STRING, BASE_HEX, 0, 0, "Error", HFILL }},
+{ &hf_afs_bos_spare1, { "Spare1", "afs.bos.spare1",
+ FT_STRING, BASE_HEX, 0, 0, "Spare1", HFILL }},
+{ &hf_afs_bos_spare2, { "Spare2", "afs.bos.spare2",
+ FT_STRING, BASE_HEX, 0, 0, "Spare2", HFILL }},
+{ &hf_afs_bos_spare3, { "Spare3", "afs.bos.spare3",
+ FT_STRING, BASE_HEX, 0, 0, "Spare3", HFILL }},
+{ &hf_afs_bos_file, { "File", "afs.bos.file",
+ FT_STRING, BASE_HEX, 0, 0, "File", HFILL }},
+{ &hf_afs_bos_cmd, { "Command", "afs.bos.cmd",
+ FT_STRING, BASE_HEX, 0, 0, "Command", HFILL }},
+{ &hf_afs_bos_key, { "Key", "afs.bos.key",
+ FT_BYTES, BASE_HEX, 0, 0, "key", HFILL }},
+{ &hf_afs_bos_user, { "User", "afs.bos.user",
+ FT_STRING, BASE_HEX, 0, 0, "User", HFILL }},
+{ &hf_afs_bos_instance, { "Instance", "afs.bos.instance",
+ FT_STRING, BASE_HEX, 0, 0, "Instance", HFILL }},
+{ &hf_afs_bos_status, { "Status", "afs.bos.status",
+ FT_INT32, BASE_DEC, 0, 0, "Status", HFILL }},
+{ &hf_afs_bos_statusdesc, { "Status Description", "afs.bos.statusdesc",
+ FT_STRING, BASE_DEC, 0, 0, "Status Description", HFILL }},
+{ &hf_afs_bos_num, { "Number", "afs.bos.number",
+ FT_UINT32, BASE_DEC, 0, 0, "Number", HFILL }},
+{ &hf_afs_bos_size, { "Size", "afs.bos.size",
+ FT_UINT32, BASE_DEC, 0, 0, "Size", HFILL }},
+{ &hf_afs_bos_flags, { "Flags", "afs.bos.flags",
+ FT_UINT32, BASE_DEC, 0, 0, "Flags", HFILL }},
+{ &hf_afs_bos_date, { "Date", "afs.bos.date",
+ FT_UINT32, BASE_DEC, 0, 0, "Date", HFILL }},
+{ &hf_afs_bos_kvno, { "Key Version Number", "afs.bos.kvno",
+ FT_UINT32, BASE_DEC, 0, 0, "Key Version Number", HFILL }},
+{ &hf_afs_bos_cell, { "Cell", "afs.bos.cell",
+ FT_STRING, BASE_HEX, 0, 0, "Cell", HFILL }},
+{ &hf_afs_bos_host, { "Host", "afs.bos.host",
+ FT_STRING, BASE_HEX, 0, 0, "Host", HFILL }},
+{ &hf_afs_bos_newtime, { "New Time", "afs.bos.newtime",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "New Time", HFILL }},
+{ &hf_afs_bos_baktime, { "Backup Time", "afs.bos.baktime",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Backup Time", HFILL }},
+{ &hf_afs_bos_oldtime, { "Old Time", "afs.bos.oldtime",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Old Time", HFILL }},
+{ &hf_afs_bos_keymodtime, { "Key Modification Time", "afs.bos.keymodtime",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Key Modification Time", HFILL }},
+{ &hf_afs_bos_keychecksum, { "Key Checksum", "afs.bos.keychecksum",
+ FT_UINT32, BASE_DEC, 0, 0, "Key Checksum", HFILL }},
+{ &hf_afs_bos_keyspare2, { "Key Spare 2", "afs.bos.keyspare2",
+ FT_UINT32, BASE_DEC, 0, 0, "Key Spare 2", HFILL }},
+
+
+/* KAUTH Server Fields */
+{ &hf_afs_kauth_errcode, { "Error Code", "afs.kauth.errcode",
+ FT_UINT32, BASE_DEC, VALS(afs_errors), 0, "Error Code", HFILL }},
+{ &hf_afs_kauth_princ, { "Principal", "afs.kauth.princ",
+ FT_STRING, BASE_HEX, 0, 0, "Principal", HFILL }},
+{ &hf_afs_kauth_realm, { "Realm", "afs.kauth.realm",
+ FT_STRING, BASE_HEX, 0, 0, "Realm", HFILL }},
+{ &hf_afs_kauth_domain, { "Domain", "afs.kauth.domain",
+ FT_STRING, BASE_HEX, 0, 0, "Domain", HFILL }},
+{ &hf_afs_kauth_name, { "Name", "afs.kauth.name",
+ FT_STRING, BASE_HEX, 0, 0, "Name", HFILL }},
+{ &hf_afs_kauth_data, { "Data", "afs.kauth.data",
+ FT_BYTES, BASE_HEX, 0, 0, "Data", HFILL }},
+{ &hf_afs_kauth_kvno, { "Key Version Number", "afs.kauth.kvno",
+ FT_UINT32, BASE_DEC, 0, 0, "Key Version Number", HFILL }},
+
+/* VOL Server Fields */
+{ &hf_afs_vol_errcode, { "Error Code", "afs.vol.errcode",
+ FT_UINT32, BASE_DEC, VALS(afs_errors), 0, "Error Code", HFILL }},
+{ &hf_afs_vol_id, { "Volume ID", "afs.vol.id",
+ FT_UINT32, BASE_DEC, 0, 0, "Volume ID", HFILL }},
+{ &hf_afs_vol_count, { "Volume Count", "afs.vol.count",
+ FT_UINT32, BASE_DEC, 0, 0, "Volume Count", HFILL }},
+{ &hf_afs_vol_name, { "Volume Name", "afs.vol.name",
+ FT_STRING, BASE_HEX, 0, 0, "Volume Name", HFILL }},
+
+/* VLDB Server Fields */
+{ &hf_afs_vldb_errcode, { "Error Code", "afs.vldb.errcode",
+ FT_UINT32, BASE_DEC, VALS(afs_errors), 0, "Error Code", HFILL }},
+{ &hf_afs_vldb_type, { "Volume Type", "afs.vldb.type",
+ FT_UINT32, BASE_HEX, VALS(volume_types), 0, "Volume Type", HFILL }},
+{ &hf_afs_vldb_id, { "Volume ID", "afs.vldb.id",
+ FT_UINT32, BASE_DEC, 0, 0, "Volume ID", HFILL }},
+{ &hf_afs_vldb_bump, { "Bumped Volume ID", "afs.vldb.bump",
+ FT_UINT32, BASE_DEC, 0, 0, "Bumped Volume ID", HFILL }},
+{ &hf_afs_vldb_index, { "Volume Index", "afs.vldb.index",
+ FT_UINT32, BASE_DEC, 0, 0, "Volume Index", HFILL }},
+{ &hf_afs_vldb_count, { "Volume Count", "afs.vldb.count",
+ FT_UINT32, BASE_DEC, 0, 0, "Volume Count", HFILL }},
+{ &hf_afs_vldb_numservers, { "Number of Servers", "afs.vldb.numservers",
+ FT_UINT32, BASE_DEC, 0, 0, "Number of Servers", HFILL }},
+{ &hf_afs_vldb_nextindex, { "Next Volume Index", "afs.vldb.nextindex",
+ FT_UINT32, BASE_DEC, 0, 0, "Next Volume Index", HFILL }},
+{ &hf_afs_vldb_rovol, { "Read-Only Volume ID", "afs.vldb.rovol",
+ FT_UINT32, BASE_DEC, 0, 0, "Read-Only Volume ID", HFILL }},
+{ &hf_afs_vldb_rwvol, { "Read-Write Volume ID", "afs.vldb.rwvol",
+ FT_UINT32, BASE_DEC, 0, 0, "Read-Only Volume ID", HFILL }},
+{ &hf_afs_vldb_bkvol, { "Backup Volume ID", "afs.vldb.bkvol",
+ FT_UINT32, BASE_DEC, 0, 0, "Read-Only Volume ID", HFILL }},
+{ &hf_afs_vldb_clonevol, { "Clone Volume ID", "afs.vldb.clonevol",
+ FT_UINT32, BASE_DEC, 0, 0, "Clone Volume ID", HFILL }},
+{ &hf_afs_vldb_name, { "Volume Name", "afs.vldb.name",
+ FT_STRING, BASE_HEX, 0, 0, "Volume Name", HFILL }},
+{ &hf_afs_vldb_partition, { "Partition", "afs.vldb.partition",
+ FT_STRING, BASE_HEX, 0, 0, "Partition", HFILL }},
+{ &hf_afs_vldb_server, { "Server", "afs.vldb.server",
+ FT_IPv4, BASE_HEX, 0, 0, "Server", HFILL }},
+{ &hf_afs_vldb_serveruuid, { "Server UUID", "afs.vldb.serveruuid",
+ FT_BYTES, BASE_HEX, 0, 0, "Server UUID", HFILL }},
+{ &hf_afs_vldb_serveruniq, { "Server Unique Address", "afs.vldb.serveruniq",
+ FT_UINT32, BASE_HEX, 0, 0, "Server Unique Address", HFILL }},
+{ &hf_afs_vldb_serverflags, { "Server Flags", "afs.vldb.serverflags",
+ FT_UINT32, BASE_HEX, 0, 0, "Server Flags", HFILL }},
+{ &hf_afs_vldb_serverip, { "Server IP", "afs.vldb.serverip",
+ FT_IPv4, BASE_HEX, 0, 0, "Server IP", HFILL }},
+{ &hf_afs_vldb_flags, { "Flags", "afs.vldb.flags",
+ FT_UINT32, BASE_HEX, 0, 0, "Flags", HFILL }},
+
+{ &hf_afs_vldb_flags_rwexists, { "Read/Write Exists", "afs.vldb.flags.rwexists",
+ FT_BOOLEAN, 32, 0, 0x1000, "Read/Write Exists", HFILL }},
+{ &hf_afs_vldb_flags_roexists, { "Read-Only Exists", "afs.vldb.flags.roexists",
+ FT_BOOLEAN, 32, 0, 0x2000, "Read-Only Exists", HFILL }},
+{ &hf_afs_vldb_flags_bkexists, { "Backup Exists", "afs.vldb.flags.bkexists",
+ FT_BOOLEAN, 32, 0, 0x4000, "Backup Exists", HFILL }},
+{ &hf_afs_vldb_flags_dfsfileset, { "DFS Fileset", "afs.vldb.flags.dfsfileset",
+ FT_BOOLEAN, 32, 0, 0x8000, "DFS Fileset", HFILL }},
+
+{ &hf_afs_vldb_spare1, { "Spare 1", "afs.vldb.spare1",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 1", HFILL }},
+{ &hf_afs_vldb_spare2, { "Spare 2", "afs.vldb.spare2",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 2", HFILL }},
+{ &hf_afs_vldb_spare3, { "Spare 3", "afs.vldb.spare3",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 3", HFILL }},
+{ &hf_afs_vldb_spare4, { "Spare 4", "afs.vldb.spare4",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 4", HFILL }},
+{ &hf_afs_vldb_spare5, { "Spare 5", "afs.vldb.spare5",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 5", HFILL }},
+{ &hf_afs_vldb_spare6, { "Spare 6", "afs.vldb.spare6",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 6", HFILL }},
+{ &hf_afs_vldb_spare7, { "Spare 7", "afs.vldb.spare7",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 7", HFILL }},
+{ &hf_afs_vldb_spare8, { "Spare 8", "afs.vldb.spare8",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 8", HFILL }},
+{ &hf_afs_vldb_spare9, { "Spare 9", "afs.vldb.spare9",
+ FT_UINT32, BASE_DEC, 0, 0, "Spare 9", HFILL }},
+
+/* BACKUP Server Fields */
+{ &hf_afs_backup_errcode, { "Error Code", "afs.backup.errcode",
+ FT_UINT32, BASE_DEC, VALS(afs_errors), 0, "Error Code", HFILL }},
+
+/* CB Server Fields */
+{ &hf_afs_cb_errcode, { "Error Code", "afs.cb.errcode",
+ FT_UINT32, BASE_DEC, VALS(afs_errors), 0, "Error Code", HFILL }},
+{ &hf_afs_cb_callback_version, { "Version", "afs.cb.callback.version",
+ FT_UINT32, BASE_DEC, 0, 0, "Version", HFILL }},
+{ &hf_afs_cb_callback_expires, { "Expires", "afs.cb.callback.expires",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Expires", HFILL }},
+{ &hf_afs_cb_callback_type, { "Type", "afs.cb.callback.type",
+ FT_UINT32, BASE_DEC, VALS(cb_types), 0, "Type", HFILL }},
+{ &hf_afs_cb_fid_volume, { "FileID (Volume)", "afs.cb.fid.volume",
+ FT_UINT32, BASE_DEC, 0, 0, "File ID (Volume)", HFILL }},
+{ &hf_afs_cb_fid_vnode, { "FileID (VNode)", "afs.cb.fid.vnode",
+ FT_UINT32, BASE_DEC, 0, 0, "File ID (VNode)", HFILL }},
+{ &hf_afs_cb_fid_uniqifier, { "FileID (Uniqifier)", "afs.cb.fid.uniq",
+ FT_UINT32, BASE_DEC, 0, 0, "File ID (Uniqifier)", HFILL }},
+
+/* PROT Server Fields */
+{ &hf_afs_prot_errcode, { "Error Code", "afs.prot.errcode",
+ FT_UINT32, BASE_DEC, VALS(afs_errors), 0, "Error Code", HFILL }},
+{ &hf_afs_prot_name, { "Name", "afs.prot.name",
+ FT_STRING, BASE_HEX, 0, 0, "Name", HFILL }},
+{ &hf_afs_prot_id, { "ID", "afs.prot.id",
+ FT_UINT32, BASE_DEC, 0, 0, "ID", HFILL }},
+{ &hf_afs_prot_oldid, { "Old ID", "afs.prot.oldid",
+ FT_UINT32, BASE_DEC, 0, 0, "Old ID", HFILL }},
+{ &hf_afs_prot_newid, { "New ID", "afs.prot.newid",
+ FT_UINT32, BASE_DEC, 0, 0, "New ID", HFILL }},
+{ &hf_afs_prot_gid, { "Group ID", "afs.prot.gid",
+ FT_UINT32, BASE_DEC, 0, 0, "Group ID", HFILL }},
+{ &hf_afs_prot_uid, { "User ID", "afs.prot.uid",
+ FT_UINT32, BASE_DEC, 0, 0, "User ID", HFILL }},
+{ &hf_afs_prot_count, { "Count", "afs.prot.count",
+ FT_UINT32, BASE_DEC, 0, 0, "Count", HFILL }},
+{ &hf_afs_prot_maxgid, { "Maximum Group ID", "afs.prot.maxgid",
+ FT_UINT32, BASE_DEC, 0, 0, "Maximum Group ID", HFILL }},
+{ &hf_afs_prot_maxuid, { "Maximum User ID", "afs.prot.maxuid",
+ FT_UINT32, BASE_DEC, 0, 0, "Maximum User ID", HFILL }},
+{ &hf_afs_prot_pos, { "Position", "afs.prot.pos",
+ FT_UINT32, BASE_DEC, 0, 0, "Position", HFILL }},
+{ &hf_afs_prot_flag, { "Flag", "afs.prot.flag",
+ FT_UINT32, BASE_HEX, 0, 0, "Flag", HFILL }},
+
+/* UBIK Fields */
+{ &hf_afs_ubik_errcode, { "Error Code", "afs.ubik.errcode",
+ FT_UINT32, BASE_DEC, VALS(afs_errors), 0, "Error Code", HFILL }},
+{ &hf_afs_ubik_state, { "State", "afs.ubik.state",
+ FT_UINT32, BASE_HEX, 0, 0, "State", HFILL }},
+{ &hf_afs_ubik_version_epoch, { "Epoch", "afs.ubik.version.epoch",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Epoch", HFILL }},
+{ &hf_afs_ubik_version_counter, { "Counter", "afs.ubik.version.counter",
+ FT_UINT32, BASE_DEC, 0, 0, "Counter", HFILL }},
+{ &hf_afs_ubik_votestart, { "Vote Started", "afs.ubik.votestart",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Vote Started", HFILL }},
+{ &hf_afs_ubik_voteend, { "Vote Ends", "afs.ubik.voteend",
+ FT_ABSOLUTE_TIME, BASE_NONE, 0, 0, "Vote Ends", HFILL }},
+{ &hf_afs_ubik_file, { "File", "afs.ubik.file",
+ FT_UINT32, BASE_DEC, 0, 0, "File", HFILL }},
+{ &hf_afs_ubik_pos, { "Position", "afs.ubik.position",
+ FT_UINT32, BASE_DEC, 0, 0, "Position", HFILL }},
+{ &hf_afs_ubik_length, { "Length", "afs.ubik.length",
+ FT_UINT32, BASE_DEC, 0, 0, "Length", HFILL }},
+{ &hf_afs_ubik_locktype, { "Lock Type", "afs.ubik.locktype",
+ FT_UINT32, BASE_DEC, VALS(ubik_lock_types), 0, "Lock Type", HFILL }},
+{ &hf_afs_ubik_votetype, { "Vote Type", "afs.ubik.votetype",
+ FT_UINT32, BASE_HEX, 0, 0, "Vote Type", HFILL }},
+{ &hf_afs_ubik_site, { "Site", "afs.ubik.site",
+ FT_IPv4, BASE_HEX, 0, 0, "Site", HFILL }},
+{ &hf_afs_ubik_interface, { "Interface Address", "afs.ubik.interface",
+ FT_IPv4, BASE_HEX, 0, 0, "Interface Address", HFILL }},
+
+{ &hf_afs_ubik_now, { "Now", "afs.ubik.now",
+ FT_ABSOLUTE_TIME, BASE_HEX, 0, 0, "Now", HFILL }},
+{ &hf_afs_ubik_lastyestime, { "Last Yes Time", "afs.ubik.lastyesttime",
+ FT_ABSOLUTE_TIME, BASE_HEX, 0, 0, "Last Yes Time", HFILL }},
+{ &hf_afs_ubik_lastyeshost, { "Last Yes Host", "afs.ubik.lastyeshost",
+ FT_IPv4, BASE_HEX, 0, 0, "Last Yes Host", HFILL }},
+{ &hf_afs_ubik_lastyesstate, { "Last Yes State", "afs.ubik.lastyesstate",
+ FT_UINT32, BASE_HEX, 0, 0, "Last Yes State", HFILL }},
+{ &hf_afs_ubik_lastyesclaim, { "Last Yes Claim", "afs.ubik.lastyesclaim",
+ FT_ABSOLUTE_TIME, BASE_HEX, 0, 0, "Last Yes Claim", HFILL }},
+{ &hf_afs_ubik_lowesthost, { "Lowest Host", "afs.ubik.lowesthost",
+ FT_IPv4, BASE_HEX, 0, 0, "Lowest Host", HFILL }},
+{ &hf_afs_ubik_lowesttime, { "Lowest Time", "afs.ubik.lowesttime",
+ FT_ABSOLUTE_TIME, BASE_HEX, 0, 0, "Lowest Time", HFILL }},
+{ &hf_afs_ubik_synchost, { "Sync Host", "afs.ubik.synchost",
+ FT_IPv4, BASE_HEX, 0, 0, "Sync Host", HFILL }},
+{ &hf_afs_ubik_addr, { "Address", "afs.ubik.addr",
+ FT_IPv4, BASE_HEX, 0, 0, "Address", HFILL }},
+{ &hf_afs_ubik_synctime, { "Sync Time", "afs.ubik.synctime",
+ FT_ABSOLUTE_TIME, BASE_HEX, 0, 0, "Sync Time", HFILL }},
+{ &hf_afs_ubik_lastvotetime, { "Last Vote Time", "afs.ubik.lastvotetime",
+ FT_ABSOLUTE_TIME, BASE_HEX, 0, 0, "Last Vote Time", HFILL }},
+{ &hf_afs_ubik_lastbeaconsent, { "Last Beacon Sent", "afs.ubik.lastbeaconsent",
+ FT_ABSOLUTE_TIME, BASE_HEX, 0, 0, "Last Beacon Sent", HFILL }},
+{ &hf_afs_ubik_lastvote, { "Last Vote", "afs.ubik.lastvote",
+ FT_UINT32, BASE_HEX, 0, 0, "Last Vote", HFILL }},
+{ &hf_afs_ubik_currentdb, { "Current DB", "afs.ubik.currentdb",
+ FT_UINT32, BASE_HEX, 0, 0, "Current DB", HFILL }},
+{ &hf_afs_ubik_up, { "Up", "afs.ubik.up",
+ FT_UINT32, BASE_HEX, 0, 0, "Up", HFILL }},
+{ &hf_afs_ubik_beaconsincedown, { "Beacon Since Down", "afs.ubik.beaconsincedown",
+ FT_UINT32, BASE_HEX, 0, 0, "Beacon Since Down", HFILL }},
+{ &hf_afs_ubik_amsyncsite, { "Am Sync Site", "afs.ubik.amsyncsite",
+ FT_UINT32, BASE_HEX, 0, 0, "Am Sync Site", HFILL }},
+{ &hf_afs_ubik_syncsiteuntil, { "Sync Site Until", "afs.ubik.syncsiteuntil",
+ FT_ABSOLUTE_TIME, BASE_HEX, 0, 0, "Sync Site Until", HFILL }},
+{ &hf_afs_ubik_nservers, { "Number of Servers", "afs.ubik.nservers",
+ FT_UINT32, BASE_HEX, 0, 0, "Number of Servers", HFILL }},
+{ &hf_afs_ubik_lockedpages, { "Locked Pages", "afs.ubik.lockedpages",
+ FT_UINT32, BASE_HEX, 0, 0, "Locked Pages", HFILL }},
+{ &hf_afs_ubik_writelockedpages, { "Write Locked Pages", "afs.ubik.writelockedpages",
+ FT_UINT32, BASE_HEX, 0, 0, "Write Locked Pages", HFILL }},
+{ &hf_afs_ubik_activewrite, { "Active Write", "afs.ubik.activewrite",
+ FT_UINT32, BASE_HEX, 0, 0, "Active Write", HFILL }},
+{ &hf_afs_ubik_tidcounter, { "TID Counter", "afs.ubik.tidcounter",
+ FT_UINT32, BASE_HEX, 0, 0, "TID Counter", HFILL }},
+{ &hf_afs_ubik_anyreadlocks, { "Any Read Locks", "afs.ubik.anyreadlocks",
+ FT_UINT32, BASE_HEX, 0, 0, "Any Read Locks", HFILL }},
+{ &hf_afs_ubik_anywritelocks, { "Any Write Locks", "afs.ubik.anywritelocks",
+ FT_UINT32, BASE_HEX, 0, 0, "Any Write Locks", HFILL }},
+{ &hf_afs_ubik_recoverystate, { "Recovery State", "afs.ubik.recoverystate",
+ FT_UINT32, BASE_HEX, 0, 0, "Recovery State", HFILL }},
+{ &hf_afs_ubik_currenttrans, { "Current Transaction", "afs.ubik.currenttran",
+ FT_UINT32, BASE_HEX, 0, 0, "Current Transaction", HFILL }},
+{ &hf_afs_ubik_writetrans, { "Write Transaction", "afs.ubik.writetran",
+ FT_UINT32, BASE_HEX, 0, 0, "Write Transaction", HFILL }},
+{ &hf_afs_ubik_epochtime, { "Epoch Time", "afs.ubik.epochtime",
+ FT_ABSOLUTE_TIME, BASE_HEX, 0, 0, "Epoch Time", HFILL }},
+{ &hf_afs_ubik_isclone, { "Is Clone", "afs.ubik.isclone",
+ FT_UINT32, BASE_HEX, 0, 0, "Is Clone", HFILL }},
+{ &hf_afs_reqframe, { "Request Frame", "afs.reqframe",
+ FT_FRAMENUM, BASE_NONE, NULL, 0, "Request Frame", HFILL }},
+{ &hf_afs_repframe, { "Reply Frame", "afs.repframe",
+ FT_FRAMENUM, BASE_NONE, NULL, 0, "Reply Frame", HFILL }},
+{ &hf_afs_time, { "Time from request", "afs.time",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0, "Time between Request and Reply for AFS calls", HFILL }},
+
+
+
+
+
+
+
+
diff --git a/epan/dissectors/packet-afs.c b/epan/dissectors/packet-afs.c
new file mode 100644
index 0000000000..2292e45bc2
--- /dev/null
+++ b/epan/dissectors/packet-afs.c
@@ -0,0 +1,1779 @@
+/* packet-afs.c
+ * Routines for AFS packet dissection
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ * Based on routines from tcpdump patches by
+ * Ken Hornstein <kenh@cmf.nrl.navy.mil>
+ * Portions based on information retrieved from the RX definitions
+ * in Arla, the free AFS client at http://www.stacken.kth.se/project/arla/
+ * Portions based on information/specs retrieved from the OpenAFS sources at
+ * www.openafs.org, Copyright IBM.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include <epan/resolv.h>
+
+#include "packet-rx.h"
+#include "packet-afs.h"
+#include "packet-afs-defs.h"
+#include "packet-afs-macros.h"
+
+#define GETSTR ((const char *)tvb_get_ptr(tvb,offset,tvb_ensure_length_remaining(tvb,offset)))
+
+#define VALID_OPCODE(opcode) ((opcode >= OPCODE_LOW && opcode <= OPCODE_HIGH) || \
+ (opcode >= VOTE_LOW && opcode <= VOTE_HIGH) || \
+ (opcode >= DISK_LOW && opcode <= DISK_HIGH))
+
+static int afs_packet_init_count = 100;
+
+struct afs_request_key {
+ guint32 conversation, callnumber;
+ guint16 service;
+};
+
+struct afs_request_val {
+ guint32 opcode;
+ guint req_num;
+ guint rep_num;
+ nstime_t req_time;
+};
+
+static GHashTable *afs_request_hash = NULL;
+static GMemChunk *afs_request_keys = NULL;
+static GMemChunk *afs_request_vals = NULL;
+
+
+
+/*
+ * Dissector prototypes
+ */
+static int dissect_acl(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset);
+static void dissect_fs_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_fs_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_bos_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_bos_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_vol_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_vol_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_kauth_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_kauth_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_cb_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_cb_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_prot_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_prot_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_vldb_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_vldb_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_ubik_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_ubik_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_backup_reply(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+static void dissect_backup_request(tvbuff_t *tvb, struct rxinfo *rxinfo,
+ proto_tree *tree, int offset, int opcode);
+
+/*
+ * Hash Functions
+ */
+static gint
+afs_equal(gconstpointer v, gconstpointer w)
+{
+ const struct afs_request_key *v1 = (const struct afs_request_key *)v;
+ const struct afs_request_key *v2 = (const struct afs_request_key *)w;
+
+ if (v1 -> conversation == v2 -> conversation &&
+ v1 -> service == v2 -> service &&
+ v1 -> callnumber == v2 -> callnumber ) {
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static guint
+afs_hash (gconstpointer v)
+{
+ const struct afs_request_key *key = (const struct afs_request_key *)v;
+ guint val;
+
+ val = key -> conversation + key -> service + key -> callnumber;
+
+ return val;
+}
+
+/*
+ * Protocol initialization
+ */
+static void
+afs_init_protocol(void)
+{
+ if (afs_request_hash)
+ g_hash_table_destroy(afs_request_hash);
+ if (afs_request_keys)
+ g_mem_chunk_destroy(afs_request_keys);
+ if (afs_request_vals)
+ g_mem_chunk_destroy(afs_request_vals);
+
+ afs_request_hash = g_hash_table_new(afs_hash, afs_equal);
+ afs_request_keys = g_mem_chunk_new("afs_request_keys",
+ sizeof(struct afs_request_key),
+ afs_packet_init_count * sizeof(struct afs_request_key),
+ G_ALLOC_AND_FREE);
+ afs_request_vals = g_mem_chunk_new("afs_request_vals",
+ sizeof(struct afs_request_val),
+ afs_packet_init_count * sizeof(struct afs_request_val),
+ G_ALLOC_AND_FREE);
+}
+
+
+
+/*
+ * Dissection routines
+ */
+
+static void
+dissect_afs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct rxinfo *rxinfo = pinfo->private_data;
+ int reply = 0;
+ conversation_t *conversation;
+ struct afs_request_key request_key, *new_request_key;
+ struct afs_request_val *request_val=NULL;
+ proto_tree *afs_tree, *afs_op_tree, *ti;
+ int port, node, typenode, opcode;
+ value_string const *vals;
+ int offset = 0;
+ nstime_t ns;
+
+ void (*dissector)(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode);
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AFS (RX)");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ reply = (rxinfo->flags & RX_CLIENT_INITIATED) == 0;
+ port = ((reply == 0) ? pinfo->destport : pinfo->srcport );
+
+ /*
+ * Find out what conversation this packet is part of.
+ * XXX - this should really be done by the transport-layer protocol,
+ * although for connectionless transports, we may not want to do that
+ * unless we know some higher-level protocol will want it - or we
+ * may want to do it, so you can say e.g. "show only the packets in
+ * this UDP 'connection'".
+ *
+ * Note that we don't have to worry about the direction this packet
+ * was going - the conversation code handles that for us, treating
+ * packets from A:X to B:Y as being part of the same conversation as
+ * packets from B:Y to A:X.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL) {
+ /* It's not part of any conversation - create a new one. */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+
+ request_key.conversation = conversation->index;
+ request_key.service = rxinfo->serviceid;
+ request_key.callnumber = rxinfo->callnumber;
+
+ request_val = (struct afs_request_val *) g_hash_table_lookup(
+ afs_request_hash, &request_key);
+
+ /* only allocate a new hash element when it's a request */
+ opcode = 0;
+ if(!pinfo->fd->flags.visited){
+ if ( !request_val && !reply) {
+ new_request_key = g_mem_chunk_alloc(afs_request_keys);
+ *new_request_key = request_key;
+
+ request_val = g_mem_chunk_alloc(afs_request_vals);
+ request_val -> opcode = tvb_get_ntohl(tvb, offset);
+ request_val -> req_num = pinfo->fd->num;
+ request_val -> rep_num = 0;
+ request_val -> req_time.secs=pinfo->fd->abs_secs;
+ request_val -> req_time.nsecs=pinfo->fd->abs_usecs*1000;
+
+ g_hash_table_insert(afs_request_hash, new_request_key,
+ request_val);
+ }
+ if( request_val && reply ) {
+ request_val -> rep_num = pinfo->fd->num;
+ }
+ }
+
+ if ( request_val ) {
+ opcode = request_val->opcode;
+ }
+
+
+ node = 0;
+ typenode = 0;
+ vals = NULL;
+ dissector = NULL;
+ switch (port) {
+ case AFS_PORT_FS:
+ typenode = hf_afs_fs;
+ node = hf_afs_fs_opcode;
+ vals = fs_req;
+ dissector = reply ? dissect_fs_reply : dissect_fs_request;
+ break;
+ case AFS_PORT_CB:
+ typenode = hf_afs_cb;
+ node = hf_afs_cb_opcode;
+ vals = cb_req;
+ dissector = reply ? dissect_cb_reply : dissect_cb_request;
+ break;
+ case AFS_PORT_PROT:
+ typenode = hf_afs_prot;
+ node = hf_afs_prot_opcode;
+ vals = prot_req;
+ dissector = reply ? dissect_prot_reply : dissect_prot_request;
+ break;
+ case AFS_PORT_VLDB:
+ typenode = hf_afs_vldb;
+ node = hf_afs_vldb_opcode;
+ vals = vldb_req;
+ dissector = reply ? dissect_vldb_reply : dissect_vldb_request;
+ break;
+ case AFS_PORT_KAUTH:
+ typenode = hf_afs_kauth;
+ node = hf_afs_kauth_opcode;
+ vals = kauth_req;
+ dissector = reply ? dissect_kauth_reply : dissect_kauth_request;
+ break;
+ case AFS_PORT_VOL:
+ typenode = hf_afs_vol;
+ node = hf_afs_vol_opcode;
+ vals = vol_req;
+ dissector = reply ? dissect_vol_reply : dissect_vol_request;
+ break;
+ case AFS_PORT_ERROR:
+ typenode = hf_afs_error;
+ node = hf_afs_error_opcode;
+ /* dissector = reply ? dissect_error_reply : dissect_error_request; */
+ break;
+ case AFS_PORT_BOS:
+ typenode = hf_afs_bos;
+ node = hf_afs_bos_opcode;
+ vals = bos_req;
+ dissector = reply ? dissect_bos_reply : dissect_bos_request;
+ break;
+ case AFS_PORT_UPDATE:
+ typenode = hf_afs_update;
+ node = hf_afs_update_opcode;
+ vals = update_req;
+ /* dissector = reply ? dissect_update_reply : dissect_update_request; */
+ break;
+ case AFS_PORT_RMTSYS:
+ typenode = hf_afs_rmtsys;
+ node = hf_afs_rmtsys_opcode;
+ vals = rmtsys_req;
+ /* dissector = reply ? dissect_rmtsys_reply : dissect_rmtsys_request; */
+ break;
+ case AFS_PORT_BACKUP:
+ typenode = hf_afs_backup;
+ node = hf_afs_backup_opcode;
+ vals = backup_req;
+ dissector = reply ? dissect_backup_reply : dissect_backup_request;
+ break;
+ }
+
+ if ( (opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
+ (opcode >= DISK_LOW && opcode <= DISK_HIGH) ) {
+ typenode = hf_afs_ubik;
+ node = hf_afs_ubik_opcode;
+ vals = ubik_req;
+ dissector = reply ? dissect_ubik_reply : dissect_ubik_request;
+ }
+
+
+ if ( VALID_OPCODE(opcode) ) {
+ if ( vals ) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s %s: %s (%d)",
+ typenode == hf_afs_ubik ? "UBIK-" : "",
+ val_to_str(port, port_types_short, "Unknown(%d)"),
+ reply ? "Reply" : "Request",
+ val_to_str(opcode, vals, "Unknown(%d)"), opcode);
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s %s: Unknown(%d)",
+ typenode == hf_afs_ubik ? "UBIK-" : "",
+ val_to_str(port, port_types_short, "Unknown(%d)"),
+ reply ? "Reply" : "Request",
+ opcode);
+ }
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Encrypted %s %s",
+ val_to_str(port, port_types_short, "Unknown(%d)"),
+ reply ? "Reply" : "Request"
+ );
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_afs, tvb, offset, -1,
+ FALSE);
+ afs_tree = proto_item_add_subtree(ti, ett_afs);
+
+ proto_tree_add_text(afs_tree, tvb, 0, 0,
+ "Service: %s%s%s %s",
+ VALID_OPCODE(opcode) ? "" : "Encrypted ",
+ typenode == hf_afs_ubik ? "UBIK - " : "",
+ val_to_str(port, port_types, "Unknown(%d)"),
+ reply ? "Reply" : "Request");
+
+ if( request_val && !reply && request_val->rep_num) {
+ proto_tree_add_uint_format(afs_tree, hf_afs_repframe,
+ tvb, 0, 0, request_val->rep_num,
+ "The reply to this request is in frame %u",
+ request_val->rep_num);
+ }
+ if( request_val && reply && request_val->rep_num) {
+ proto_tree_add_uint_format(afs_tree, hf_afs_reqframe,
+ tvb, 0, 0, request_val->req_num,
+ "This is a reply to a request in frame %u",
+ request_val->req_num);
+ ns.secs= pinfo->fd->abs_secs-request_val->req_time.secs;
+ ns.nsecs=pinfo->fd->abs_usecs*1000-request_val->req_time.nsecs;
+ if(ns.nsecs<0){
+ ns.nsecs+=1000000000;
+ ns.secs--;
+ }
+ proto_tree_add_time(afs_tree, hf_afs_time, tvb, offset, 0,
+ &ns);
+ }
+
+
+ if ( VALID_OPCODE(opcode) ) {
+ /* until we do cache, can't handle replies */
+ ti = NULL;
+ if ( !reply && node != 0 ) {
+ if ( rxinfo->seq == 1 )
+ {
+ ti = proto_tree_add_uint(afs_tree,
+ node, tvb, offset, 4, opcode);
+ } else {
+ ti = proto_tree_add_uint(afs_tree,
+ node, tvb, 0, 0, opcode);
+ }
+ } else if ( reply && node != 0 ) {
+ /* the opcode isn't in this packet */
+ ti = proto_tree_add_uint(afs_tree,
+ node, tvb, 0, 0, opcode);
+ } else {
+ ti = proto_tree_add_text(afs_tree, tvb,
+ 0, 0, "Operation: Unknown");
+ }
+
+ /* Add the subtree for this particular service */
+ afs_op_tree = proto_item_add_subtree(ti, ett_afs_op);
+
+
+ if ( typenode != 0 ) {
+ /* indicate the type of request */
+ proto_tree_add_boolean_hidden(afs_tree, typenode, tvb, offset, 0, 1);
+ }
+
+ /* Process the packet according to what service it is */
+ if ( dissector ) {
+ (*dissector)(tvb, rxinfo, afs_op_tree, offset, opcode);
+ }
+ }
+ }
+
+ /* if it's the last packet, and it's a reply, remove opcode
+ from hash */
+ /* ignoring for now, I'm not sure how the chunk deallocation works */
+ if ( rxinfo->flags & RX_LAST_PACKET && reply ){
+
+ }
+}
+
+
+/*
+ * Here is a helper routine for adding an AFS acl to the proto tree
+ * This is to be used with FS packets only
+ *
+ * An AFS ACL is a string that has the following format:
+ *
+ * <positive> <negative>
+ * <uid1> <aclbits1>
+ * ....
+ *
+ * "positive" and "negative" are integers which contain the number of
+ * positive and negative ACL's in the string. The uid/aclbits pair are
+ * ASCII strings containing the UID/PTS record and and a ascii number
+ * representing a logical OR of all the ACL permission bits
+ */
+/*
+ * XXX - FIXME:
+ *
+ * sscanf is probably quite dangerous if we run outside the packet.
+ *
+ * "GETSTR" doesn't guarantee that the resulting string is
+ * null-terminated.
+ *
+ * Should this just scan the string itself, rather than using "sscanf()"?
+ */
+static int
+dissect_acl(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset)
+{
+ int old_offset;
+ gint32 bytes;
+ int i, n, pos, neg, acl;
+ char user[128]; /* Be sure to adjust sscanf()s below if length is changed... */
+
+ old_offset = offset;
+ bytes = tvb_get_ntohl(tvb, offset);
+ OUT_UINT(hf_afs_fs_acl_datasize);
+
+
+ if (sscanf(GETSTR, "%d %n", &pos, &n) != 1) {
+ /* does not matter what we return, if this fails,
+ * we cant dissect anything else in the packet either.
+ */
+ return offset;
+ }
+ proto_tree_add_uint(tree, hf_afs_fs_acl_count_positive, tvb,
+ offset, n, pos);
+ offset += n;
+
+
+ if (sscanf(GETSTR, "%d %n", &neg, &n) != 1) {
+ return offset;
+ }
+ proto_tree_add_uint(tree, hf_afs_fs_acl_count_negative, tvb,
+ offset, n, neg);
+ offset += n;
+
+ /*
+ * This wacky order preserves the order used by the "fs" command
+ */
+ for (i = 0; i < pos; i++) {
+ if (sscanf(GETSTR, "%127s %d %n", user, &acl, &n) != 2) {
+ return offset;
+ }
+ ACLOUT(user,1,acl,n);
+ offset += n;
+ }
+ for (i = 0; i < neg; i++) {
+ if (sscanf(GETSTR, "%127s %d %n", user, &acl, &n) != 2) {
+ return offset;
+ }
+ ACLOUT(user,0,acl,n);
+ offset += n;
+ if (offset >= old_offset+bytes ) {
+ return offset;
+ }
+ }
+
+ return offset;
+}
+
+/*
+ * Here are the helper dissection routines
+ */
+
+static void
+dissect_fs_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
+{
+ if ( rxinfo->type == RX_PACKET_TYPE_DATA )
+ {
+ switch ( opcode )
+ {
+ case 130: /* fetch data */
+ /* only on first packet */
+ if ( rxinfo->seq == 1 )
+ {
+ OUT_FS_AFSFetchStatus("Status");
+ OUT_FS_AFSCallBack();
+ OUT_FS_AFSVolSync();
+ }
+ OUT_BYTES_ALL(hf_afs_fs_data);
+ break;
+ case 131: /* fetch acl */
+ offset = dissect_acl(tvb, rxinfo, tree, offset);
+ OUT_FS_AFSFetchStatus("Status");
+ OUT_FS_AFSVolSync();
+ break;
+ case 132: /* Fetch status */
+ OUT_FS_AFSFetchStatus("Status");
+ OUT_FS_AFSCallBack();
+ OUT_FS_AFSVolSync();
+ break;
+ case 133: /* Store data */
+ case 134: /* Store ACL */
+ case 135: /* Store status */
+ case 136: /* Remove file */
+ OUT_FS_AFSFetchStatus("Status");
+ OUT_FS_AFSVolSync();
+ break;
+ case 137: /* create file */
+ case 141: /* make dir */
+ case 161: /* lookup */
+ case 163: /* dfs symlink */
+ OUT_FS_AFSFid((opcode == 137)? "New File" : ((opcode == 141)? "New Directory" : "File"));
+ OUT_FS_AFSFetchStatus("File Status");
+ OUT_FS_AFSFetchStatus("Directory Status");
+ OUT_FS_AFSCallBack();
+ OUT_FS_AFSVolSync();
+ break;
+ case 138: /* rename */
+ OUT_FS_AFSFetchStatus("Old Directory Status");
+ OUT_FS_AFSFetchStatus("New Directory Status");
+ OUT_FS_AFSVolSync();
+ break;
+ case 139: /* symlink */
+ OUT_FS_AFSFid("Symlink");
+ case 140: /* link */
+ OUT_FS_AFSFetchStatus("Symlink Status");
+ case 142: /* rmdir */
+ OUT_FS_AFSFetchStatus("Directory Status");
+ OUT_FS_AFSVolSync();
+ break;
+ case 143: /* old set lock */
+ case 144: /* old extend lock */
+ case 145: /* old release lock */
+ case 147: /* give up callbacks */
+ case 150: /* set volume status */
+ case 152: /* check token */
+ /* nothing returned */
+ break;
+ case 146: /* get statistics */
+ OUT_FS_ViceStatistics();
+ break;
+ case 148: /* get volume info */
+ case 154: /* n-get-volume-info */
+ OUT_FS_VolumeInfo();
+ break;
+ case 149: /* get volume status */
+ OUT_FS_AFSFetchVolumeStatus();
+ OUT_RXString(hf_afs_fs_volname);
+ OUT_RXString(hf_afs_fs_offlinemsg);
+ OUT_RXString(hf_afs_fs_motd);
+ break;
+ case 151: /* root volume */
+ OUT_RXString(hf_afs_fs_volname);
+ break;
+ case 153: /* get time */
+ OUT_TIMESTAMP(hf_afs_fs_timestamp);
+ break;
+ case 155: /* bulk status */
+ OUT_FS_AFSBulkStats();
+ SKIP(4);
+ OUT_FS_AFSCBs();
+ OUT_FS_AFSVolSync();
+ break;
+ case 156: /* set lock */
+ case 157: /* extend lock */
+ case 158: /* release lock */
+ OUT_FS_AFSVolSync();
+ break;
+ case 159: /* x-stats-version */
+ OUT_UINT(hf_afs_fs_xstats_version);
+ break;
+ case 160: /* get xstats */
+ OUT_UINT(hf_afs_fs_xstats_version);
+ OUT_TIMESECS(hf_afs_fs_xstats_timestamp);
+ OUT_FS_AFS_CollData();
+ break;
+ case 162: /* flush cps */
+ OUT_UINT(hf_afs_fs_cps_spare2);
+ OUT_UINT(hf_afs_fs_cps_spare3);
+ break;
+ }
+ }
+ else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
+ {
+ OUT_UINT(hf_afs_fs_errcode);
+ }
+}
+
+static void
+dissect_fs_request(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
+{
+ /* skip the opcode if this is the first packet in the stream */
+ if ( rxinfo->seq == 1 )
+ {
+ offset += 4; /* skip the opcode */
+ }
+
+ switch ( opcode )
+ {
+ case 130: /* Fetch data */
+ OUT_FS_AFSFid("Source");
+ OUT_UINT(hf_afs_fs_offset);
+ OUT_UINT(hf_afs_fs_length);
+ break;
+ case 131: /* Fetch ACL */
+ OUT_FS_AFSFid("Target");
+ break;
+ case 132: /* Fetch Status */
+ OUT_FS_AFSFid("Target");
+ break;
+ case 133: /* Store Data */
+ if ( rxinfo->seq == 1 )
+ {
+ OUT_FS_AFSFid("Destination");
+ OUT_FS_AFSStoreStatus("Status");
+ OUT_UINT(hf_afs_fs_offset);
+ OUT_UINT(hf_afs_fs_length);
+ OUT_UINT(hf_afs_fs_flength);
+ }
+ OUT_BYTES_ALL(hf_afs_fs_data);
+ break;
+ case 134: /* Store ACL */
+ OUT_FS_AFSFid("Target");
+ offset = dissect_acl(tvb, rxinfo, tree, offset);
+ break;
+ case 135: /* Store Status */
+ OUT_FS_AFSFid("Target");
+ OUT_FS_AFSStoreStatus("Status");
+ break;
+ case 136: /* Remove File */
+ OUT_FS_AFSFid("Remove File");
+ OUT_RXString(hf_afs_fs_name);
+ break;
+ case 137: /* Create File */
+ OUT_FS_AFSFid("Target");
+ OUT_RXString(hf_afs_fs_name);
+ OUT_FS_AFSStoreStatus("Status");
+ break;
+ case 138: /* Rename file */
+ OUT_FS_AFSFid("Old");
+ OUT_RXString(hf_afs_fs_oldname);
+ OUT_FS_AFSFid("New");
+ OUT_RXString(hf_afs_fs_newname);
+ break;
+ case 139: /* Symlink */
+ OUT_FS_AFSFid("File");
+ OUT_RXString(hf_afs_fs_symlink_name);
+ OUT_RXString(hf_afs_fs_symlink_content);
+ OUT_FS_AFSStoreStatus("Status");
+ break;
+ case 140: /* Link */
+ OUT_FS_AFSFid("Link To (New File)");
+ OUT_RXString(hf_afs_fs_name);
+ OUT_FS_AFSFid("Link From (Old File)");
+ break;
+ case 141: /* Make dir */
+ OUT_FS_AFSFid("Target");
+ OUT_RXString(hf_afs_fs_name);
+ OUT_FS_AFSStoreStatus("Status");
+ break;
+ case 142: /* Remove dir */
+ OUT_FS_AFSFid("Target");
+ OUT_RXString(hf_afs_fs_name);
+ break;
+ case 143: /* Old Set Lock */
+ OUT_FS_AFSFid("Target");
+ OUT_UINT(hf_afs_fs_vicelocktype);
+ OUT_FS_AFSVolSync();
+ break;
+ case 144: /* Old Extend Lock */
+ OUT_FS_AFSFid("Target");
+ OUT_FS_AFSVolSync();
+ break;
+ case 145: /* Old Release Lock */
+ OUT_FS_AFSFid("Target");
+ OUT_FS_AFSVolSync();
+ break;
+ case 146: /* Get statistics */
+ /* no params */
+ break;
+ case 147: /* Give up callbacks */
+ OUT_FS_AFSCBFids();
+ OUT_FS_AFSCBs();
+ break;
+ case 148: /* Get vol info */
+ OUT_RXString(hf_afs_fs_volname);
+ break;
+ case 149: /* Get vol stats */
+ OUT_UINT(hf_afs_fs_volid);
+ break;
+ case 150: /* Set vol stats */
+ OUT_UINT(hf_afs_fs_volid);
+ OUT_FS_AFSStoreVolumeStatus();
+ OUT_RXString(hf_afs_fs_volname);
+ OUT_RXString(hf_afs_fs_offlinemsg);
+ OUT_RXString(hf_afs_fs_motd);
+ break;
+ case 151: /* get root volume */
+ /* no params */
+ break;
+ case 152: /* check token */
+ OUT_UINT(hf_afs_fs_viceid);
+ OUT_FS_AFSTOKEN();
+ break;
+ case 153: /* get time */
+ /* no params */
+ break;
+ case 154: /* new get vol info */
+ OUT_RXString(hf_afs_fs_volname);
+ break;
+ case 155: /* bulk stat */
+ OUT_FS_AFSCBFids();
+ break;
+ case 156: /* Set Lock */
+ OUT_FS_AFSFid("Target");
+ OUT_UINT(hf_afs_fs_vicelocktype);
+ break;
+ case 157: /* Extend Lock */
+ OUT_FS_AFSFid("Target");
+ break;
+ case 158: /* Release Lock */
+ OUT_FS_AFSFid("Target");
+ break;
+ case 159: /* xstats version */
+ /* no params */
+ break;
+ case 160: /* get xstats */
+ OUT_UINT(hf_afs_fs_xstats_clientversion);
+ OUT_UINT(hf_afs_fs_xstats_collnumber);
+ break;
+ case 161: /* lookup */
+ OUT_FS_AFSFid("Target");
+ OUT_RXString(hf_afs_fs_name);
+ break;
+ case 162: /* flush cps */
+ OUT_FS_ViceIds();
+ OUT_FS_IPAddrs();
+ OUT_UINT(hf_afs_fs_cps_spare1);
+ break;
+ case 163: /* dfs symlink */
+ OUT_FS_AFSFid("Target");
+ OUT_RXString(hf_afs_fs_symlink_name);
+ OUT_RXString(hf_afs_fs_symlink_content);
+ OUT_FS_AFSStoreStatus("Symlink Status");
+ break;
+ case 220: /* residencycmd */
+ OUT_FS_AFSFid("Target");
+ /* need residency inputs here */
+ break;
+ case 65536: /* inline bulk status */
+ OUT_FS_AFSCBFids();
+ break;
+ case 65537: /* fetch-data-64 */
+ OUT_FS_AFSFid("Target");
+ OUT_INT64(hf_afs_fs_offset64);
+ OUT_INT64(hf_afs_fs_length64);
+ /* need more here */
+ break;
+ case 65538: /* store-data-64 */
+ OUT_FS_AFSFid("Target");
+ OUT_FS_AFSStoreStatus("Status");
+ OUT_INT64(hf_afs_fs_offset64);
+ OUT_INT64(hf_afs_fs_length64);
+ OUT_INT64(hf_afs_fs_flength64);
+ /* need residency inputs here */
+ break;
+ case 65539: /* give up all cbs */
+ break;
+ case 65540: /* get capabilities */
+ break;
+ }
+}
+
+/*
+ * BOS Helpers
+ */
+static void
+dissect_bos_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
+{
+ if ( rxinfo->type == RX_PACKET_TYPE_DATA )
+ {
+ switch ( opcode )
+ {
+ case 80: /* create bnode */
+ /* no output */
+ break;
+ case 81: /* delete bnode */
+ /* no output */
+ break;
+ case 82: /* set status */
+ /* no output */
+ break;
+ case 83: /* get status */
+ OUT_INT(hf_afs_bos_status);
+ OUT_RXString(hf_afs_bos_statusdesc);
+ break;
+ case 84: /* enumerate instance */
+ OUT_RXString(hf_afs_bos_instance);
+ break;
+ case 85: /* get instance info */
+ OUT_RXString(hf_afs_bos_type);
+ OUT_BOS_STATUS();
+ break;
+ case 86: /* get instance parm */
+ OUT_RXString(hf_afs_bos_parm);
+ break;
+ case 87: /* add siperuser */
+ /* no output */
+ break;
+ case 88: /* delete superuser */
+ /* no output */
+ break;
+ case 89: /* list superusers */
+ OUT_RXString(hf_afs_bos_user);
+ break;
+ case 90: /* list keys */
+ OUT_UINT(hf_afs_bos_kvno);
+ OUT_BOS_KEY();
+ OUT_BOS_KEYINFO();
+ break;
+ case 91: /* add key */
+ /* no output */
+ break;
+ case 92: /* delete key */
+ /* no output */
+ break;
+ case 93: /* set cell name */
+ /* no output */
+ break;
+ case 94: /* get cell name */
+ OUT_RXString(hf_afs_bos_cell);
+ break;
+ case 95: /* get cell host */
+ OUT_RXString(hf_afs_bos_host);
+ break;
+ case 96: /* add cell host */
+ /* no output */
+ break;
+ case 97: /* delete cell host */
+ /* no output */
+ break;
+ case 98: /* set tstatus */
+ /* no output */
+ break;
+ case 99: /* shutdown all */
+ /* no output */
+ break;
+ case 100: /* restart all */
+ /* no output */
+ break;
+ case 101: /* startup all */
+ /* no output */
+ break;
+ case 102: /* set noauth flag */
+ /* no output */
+ break;
+ case 103: /* rebozo */
+ /* no output */
+ break;
+ case 104: /* restart */
+ /* no output */
+ break;
+ case 105: /* install */
+ /* no output */
+ break;
+ case 106: /* uninstall */
+ /* no output */
+ break;
+ case 107: /* get dates */
+ OUT_TIMESECS(hf_afs_bos_newtime);
+ OUT_TIMESECS(hf_afs_bos_baktime);
+ OUT_TIMESECS(hf_afs_bos_oldtime);
+ break;
+ case 108: /* exec */
+ /* no output */
+ break;
+ case 109: /* prune */
+ /* no output */
+ break;
+ case 110: /* set restart time */
+ /* no output */
+ break;
+ case 111: /* get restart time */
+ OUT_BOS_TIME();
+ break;
+ case 112: /* get log */
+ /* need to make this dump a big string somehow */
+ OUT_BYTES_ALL(hf_afs_bos_data);
+ break;
+ case 113: /* wait all */
+ /* no output */
+ break;
+ case 114: /* get instance strings */
+ OUT_RXString(hf_afs_bos_error);
+ OUT_RXString(hf_afs_bos_spare1);
+ OUT_RXString(hf_afs_bos_spare2);
+ OUT_RXString(hf_afs_bos_spare3);
+ break;
+ }
+ }
+ else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
+ {
+ OUT_UINT(hf_afs_bos_errcode);
+ }
+}
+
+static void
+dissect_bos_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
+{
+ offset += 4; /* skip the opcode */
+
+ switch ( opcode )
+ {
+ case 80: /* create b node */
+ OUT_RXString(hf_afs_bos_type);
+ OUT_RXString(hf_afs_bos_instance);
+ OUT_RXString(hf_afs_bos_parm);
+ OUT_RXString(hf_afs_bos_parm);
+ OUT_RXString(hf_afs_bos_parm);
+ OUT_RXString(hf_afs_bos_parm);
+ OUT_RXString(hf_afs_bos_parm);
+ OUT_RXString(hf_afs_bos_parm);
+ break;
+ case 81: /* delete b node */
+ OUT_RXString(hf_afs_bos_instance);
+ break;
+ case 82: /* set status */
+ OUT_RXString(hf_afs_bos_instance);
+ OUT_INT(hf_afs_bos_status);
+ break;
+ case 83: /* get status */
+ OUT_RXString(hf_afs_bos_instance);
+ break;
+ case 84: /* enumerate instance */
+ OUT_UINT(hf_afs_bos_num);
+ break;
+ case 85: /* get instance info */
+ OUT_RXString(hf_afs_bos_instance);
+ break;
+ case 86: /* get instance parm */
+ OUT_RXString(hf_afs_bos_instance);
+ OUT_UINT(hf_afs_bos_num);
+ break;
+ case 87: /* add super user */
+ OUT_RXString(hf_afs_bos_user);
+ break;
+ case 88: /* delete super user */
+ OUT_RXString(hf_afs_bos_user);
+ break;
+ case 89: /* list super users */
+ OUT_UINT(hf_afs_bos_num);
+ break;
+ case 90: /* list keys */
+ OUT_UINT(hf_afs_bos_num);
+ break;
+ case 91: /* add key */
+ OUT_UINT(hf_afs_bos_num);
+ OUT_BOS_KEY();
+ break;
+ case 92: /* delete key */
+ OUT_UINT(hf_afs_bos_num);
+ break;
+ case 93: /* set cell name */
+ OUT_RXString(hf_afs_bos_content);
+ break;
+ case 95: /* set cell host */
+ OUT_UINT(hf_afs_bos_num);
+ break;
+ case 96: /* add cell host */
+ OUT_RXString(hf_afs_bos_content);
+ break;
+ case 97: /* delete cell host */
+ OUT_RXString(hf_afs_bos_content);
+ break;
+ case 98: /* set t status */
+ OUT_RXString(hf_afs_bos_content);
+ OUT_INT(hf_afs_bos_status);
+ break;
+ case 99: /* shutdown all */
+ /* no params */
+ break;
+ case 100: /* restart all */
+ /* no params */
+ break;
+ case 101: /* startup all */
+ /* no params */
+ break;
+ case 102: /* set no-auth flag */
+ OUT_UINT(hf_afs_bos_flags);
+ break;
+ case 103: /* re-bozo? */
+ /* no params */
+ break;
+ case 104: /* restart */
+ OUT_RXString(hf_afs_bos_instance);
+ break;
+ case 105: /* install */
+ OUT_RXString(hf_afs_bos_path);
+ OUT_UINT(hf_afs_bos_size);
+ OUT_UINT(hf_afs_bos_flags);
+ OUT_UINT(hf_afs_bos_date);
+ break;
+ case 106: /* uninstall */
+ OUT_RXString(hf_afs_bos_path);
+ break;
+ case 107: /* get dates */
+ OUT_RXString(hf_afs_bos_path);
+ break;
+ case 108: /* exec */
+ OUT_RXString(hf_afs_bos_cmd);
+ break;
+ case 109: /* prune */
+ OUT_UINT(hf_afs_bos_flags);
+ break;
+ case 110: /* set restart time */
+ OUT_UINT(hf_afs_bos_num);
+ OUT_BOS_TIME();
+ break;
+ case 111: /* get restart time */
+ OUT_UINT(hf_afs_bos_num);
+ break;
+ case 112: /* get log */
+ OUT_RXString(hf_afs_bos_file);
+ break;
+ case 113: /* wait all */
+ /* no params */
+ break;
+ case 114: /* get instance strings */
+ OUT_RXString(hf_afs_bos_content);
+ break;
+ }
+}
+
+/*
+ * VOL Helpers
+ */
+static void
+dissect_vol_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
+{
+ if ( rxinfo->type == RX_PACKET_TYPE_DATA )
+ {
+ switch ( opcode )
+ {
+ case 121:
+ /* should loop here maybe */
+ OUT_UINT(hf_afs_vol_count);
+ OUT_RXStringV(hf_afs_vol_name, 32); /* not sure on */
+ break;
+ }
+ }
+ else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
+ {
+ OUT_UINT(hf_afs_vol_errcode);
+ }
+}
+
+static void
+dissect_vol_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
+{
+ offset += 4; /* skip the opcode */
+
+ switch ( opcode )
+ {
+ case 121: /* list one vol */
+ OUT_UINT(hf_afs_vol_count);
+ OUT_UINT(hf_afs_vol_id);
+ break;
+ }
+}
+
+/*
+ * KAUTH Helpers
+ */
+static void
+dissect_kauth_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
+{
+ if ( rxinfo->type == RX_PACKET_TYPE_DATA )
+ {
+ switch ( opcode )
+ {
+ }
+ }
+ else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
+ {
+ OUT_UINT(hf_afs_kauth_errcode);
+ }
+}
+
+static void
+dissect_kauth_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
+{
+ offset += 4; /* skip the opcode */
+
+ switch ( opcode )
+ {
+ case 1: /* authenticate old */
+ case 21: /* authenticate */
+ case 22: /* authenticate v2 */
+ case 2: /* change pw */
+ case 5: /* set fields */
+ case 6: /* create user */
+ case 7: /* delete user */
+ case 8: /* get entry */
+ case 14: /* unlock */
+ case 15: /* lock status */
+ OUT_RXString(hf_afs_kauth_princ);
+ OUT_RXString(hf_afs_kauth_realm);
+ OUT_BYTES_ALL(hf_afs_kauth_data);
+ break;
+ case 3: /* getticket-old */
+ case 23: /* getticket */
+ OUT_KAUTH_GetTicket();
+ break;
+ case 4: /* set pass */
+ OUT_RXString(hf_afs_kauth_princ);
+ OUT_RXString(hf_afs_kauth_realm);
+ OUT_UINT(hf_afs_kauth_kvno);
+ break;
+ case 12: /* get pass */
+ OUT_RXString(hf_afs_kauth_name);
+ break;
+ }
+}
+
+/*
+ * CB Helpers
+ */
+static void
+dissect_cb_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
+{
+ if ( rxinfo->type == RX_PACKET_TYPE_DATA )
+ {
+ switch ( opcode )
+ {
+ }
+ }
+ else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
+ {
+ OUT_UINT(hf_afs_cb_errcode);
+ }
+}
+
+static void
+dissect_cb_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
+{
+ offset += 4; /* skip the opcode */
+
+ switch ( opcode )
+ {
+ case 204: /* callback */
+ {
+ unsigned int i,j;
+
+ j = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ for (i=0; i<j; i++)
+ {
+ OUT_CB_AFSFid("Target");
+ }
+
+ j = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ for (i=0; i<j; i++)
+ {
+ OUT_CB_AFSCallBack();
+ }
+ }
+ }
+}
+
+/*
+ * PROT Helpers
+ */
+static void
+dissect_prot_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
+{
+ if ( rxinfo->type == RX_PACKET_TYPE_DATA )
+ {
+ switch ( opcode )
+ {
+ case 504: /* name to id */
+ {
+ unsigned int i, j;
+
+ j = tvb_get_ntohl(tvb, offset);
+ OUT_UINT(hf_afs_prot_count);
+
+ for (i=0; i<j; i++)
+ {
+ OUT_UINT(hf_afs_prot_id);
+ }
+ }
+ break;
+ case 505: /* id to name */
+ {
+ unsigned int i, j;
+
+ j = tvb_get_ntohl(tvb, offset);
+ OUT_UINT(hf_afs_prot_count);
+
+ for (i=0; i<j; i++)
+ {
+ OUT_RXStringV(hf_afs_prot_name, PRNAMEMAX);
+ }
+ }
+ break;
+ case 508: /* get cps */
+ case 514: /* list elements */
+ case 517: /* list owned */
+ case 518: /* get cps2 */
+ case 519: /* get host cps */
+ {
+ unsigned int i, j;
+
+ j = tvb_get_ntohl(tvb, offset);
+ OUT_UINT(hf_afs_prot_count);
+
+ for (i=0; i<j; i++)
+ {
+ OUT_UINT(hf_afs_prot_id);
+ }
+ }
+ break;
+ case 510: /* list max */
+ OUT_UINT(hf_afs_prot_maxuid);
+ OUT_UINT(hf_afs_prot_maxgid);
+ break;
+ }
+ }
+ else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
+ {
+ OUT_UINT(hf_afs_prot_errcode);
+ }
+}
+
+static void
+dissect_prot_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
+{
+ offset += 4; /* skip the opcode */
+
+ switch ( opcode )
+ {
+ case 500: /* new user */
+ OUT_RXString(hf_afs_prot_name);
+ OUT_UINT(hf_afs_prot_id);
+ OUT_UINT(hf_afs_prot_oldid);
+ break;
+ case 501: /* where is it */
+ case 506: /* delete */
+ case 508: /* get cps */
+ case 512: /* list entry */
+ case 514: /* list elements */
+ case 517: /* list owned */
+ case 519: /* get host cps */
+ OUT_UINT(hf_afs_prot_id);
+ break;
+ case 502: /* dump entry */
+ OUT_UINT(hf_afs_prot_pos);
+ break;
+ case 503: /* add to group */
+ case 507: /* remove from group */
+ case 515: /* is a member of? */
+ OUT_UINT(hf_afs_prot_uid);
+ OUT_UINT(hf_afs_prot_gid);
+ break;
+ case 504: /* name to id */
+ {
+ unsigned int i, j;
+
+ j = tvb_get_ntohl(tvb, offset);
+ OUT_UINT(hf_afs_prot_count);
+
+ for (i=0; i<j; i++)
+ {
+ OUT_RXStringV(hf_afs_prot_name,PRNAMEMAX);
+ }
+ }
+ break;
+ case 505: /* id to name */
+ {
+ unsigned int i, j;
+
+ j = tvb_get_ntohl(tvb, offset);
+ OUT_UINT(hf_afs_prot_count);
+
+ for (i=0; i<j; i++)
+ {
+ OUT_UINT(hf_afs_prot_id);
+ }
+ }
+ break;
+ case 509: /* new entry */
+ OUT_RXString(hf_afs_prot_name);
+ OUT_UINT(hf_afs_prot_flag);
+ OUT_UINT(hf_afs_prot_oldid);
+ break;
+ case 511: /* set max */
+ OUT_UINT(hf_afs_prot_id);
+ OUT_UINT(hf_afs_prot_flag);
+ break;
+ case 513: /* change entry */
+ OUT_UINT(hf_afs_prot_id);
+ OUT_RXString(hf_afs_prot_name);
+ OUT_UINT(hf_afs_prot_oldid);
+ OUT_UINT(hf_afs_prot_newid);
+ break;
+ case 520: /* update entry */
+ OUT_UINT(hf_afs_prot_id);
+ OUT_RXString(hf_afs_prot_name);
+ break;
+ }
+}
+
+/*
+ * VLDB Helpers
+ */
+static void
+dissect_vldb_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
+{
+ if ( rxinfo->type == RX_PACKET_TYPE_DATA )
+ {
+ switch ( opcode )
+ {
+ case 510: /* list entry */
+ OUT_UINT(hf_afs_vldb_count);
+ OUT_UINT(hf_afs_vldb_nextindex);
+ break;
+ case 503: /* get entry by id */
+ case 504: /* get entry by name */
+ {
+ int nservers,i,j;
+ OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
+ SKIP(4);
+ nservers = tvb_get_ntohl(tvb, offset);
+ OUT_UINT(hf_afs_vldb_numservers);
+ for (i=0; i<8; i++)
+ {
+ if ( i<nservers )
+ {
+ OUT_IP(hf_afs_vldb_server);
+ }
+ else
+ {
+ SKIP(4);
+ }
+ }
+ for (i=0; i<8; i++)
+ {
+ char part[8];
+ j = tvb_get_ntohl(tvb, offset);
+ strcpy(part, "/vicepa");
+ if ( i<nservers && j<=25 )
+ {
+ part[6] = 'a' + (char) j;
+ proto_tree_add_string(tree, hf_afs_vldb_partition, tvb,
+ offset, 4, part);
+ }
+ SKIP(4);
+ }
+ SKIP(8 * sizeof(guint32));
+ OUT_UINT(hf_afs_vldb_rwvol);
+ OUT_UINT(hf_afs_vldb_rovol);
+ OUT_UINT(hf_afs_vldb_bkvol);
+ OUT_UINT(hf_afs_vldb_clonevol);
+ OUT_VLDB_Flags();
+ }
+ break;
+ case 505: /* get new volume id */
+ OUT_UINT(hf_afs_vldb_id);
+ break;
+ case 521: /* list entry */
+ case 529: /* list entry U */
+ OUT_UINT(hf_afs_vldb_count);
+ OUT_UINT(hf_afs_vldb_nextindex);
+ break;
+ case 518: /* get entry by id n */
+ case 519: /* get entry by name N */
+ {
+ int nservers,i,j;
+ OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
+ nservers = tvb_get_ntohl(tvb, offset);
+ OUT_UINT(hf_afs_vldb_numservers);
+ for (i=0; i<13; i++)
+ {
+ if ( i<nservers )
+ {
+ OUT_IP(hf_afs_vldb_server);
+ }
+ else
+ {
+ SKIP(4);
+ }
+ }
+ for (i=0; i<13; i++)
+ {
+ char part[8];
+ j = tvb_get_ntohl(tvb, offset);
+ strcpy(part, "/vicepa");
+ if ( i<nservers && j<=25 )
+ {
+ part[6] = 'a' + (char) j;
+ proto_tree_add_string(tree, hf_afs_vldb_partition, tvb,
+ offset, 4, part);
+ }
+ SKIP(4);
+ }
+ SKIP(13 * sizeof(guint32));
+ OUT_UINT(hf_afs_vldb_rwvol);
+ OUT_UINT(hf_afs_vldb_rovol);
+ OUT_UINT(hf_afs_vldb_bkvol);
+ }
+ break;
+ case 526: /* get entry by id u */
+ case 527: /* get entry by name u */
+ {
+ int nservers,i,j;
+ OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
+ nservers = tvb_get_ntohl(tvb, offset);
+ OUT_UINT(hf_afs_vldb_numservers);
+ for (i=0; i<13; i++)
+ {
+ if ( i<nservers )
+ {
+ OUT_UUID(hf_afs_vldb_serveruuid);
+ }
+ else
+ {
+ SKIP_UUID();
+ }
+ }
+ for (i=0; i<13; i++)
+ {
+ if ( i<nservers )
+ {
+ OUT_UINT(hf_afs_vldb_serveruniq);
+ }
+ else
+ {
+ SKIP(sizeof(guint32));
+ }
+ }
+ for (i=0; i<13; i++)
+ {
+ char part[8];
+ j = tvb_get_ntohl(tvb, offset);
+ strcpy(part, "/vicepa");
+ if ( i<nservers && j<=25 )
+ {
+ part[6] = 'a' + (char) j;
+ proto_tree_add_string(tree, hf_afs_vldb_partition, tvb,
+ offset, 4, part);
+ }
+ SKIP(4);
+ }
+ for (i=0; i<13; i++)
+ {
+ if ( i<nservers )
+ {
+ OUT_UINT(hf_afs_vldb_serverflags);
+ }
+ else
+ {
+ SKIP(sizeof(guint32));
+ }
+ }
+ OUT_UINT(hf_afs_vldb_rwvol);
+ OUT_UINT(hf_afs_vldb_rovol);
+ OUT_UINT(hf_afs_vldb_bkvol);
+ OUT_UINT(hf_afs_vldb_clonevol);
+ OUT_UINT(hf_afs_vldb_flags);
+ OUT_UINT(hf_afs_vldb_spare1);
+ OUT_UINT(hf_afs_vldb_spare2);
+ OUT_UINT(hf_afs_vldb_spare3);
+ OUT_UINT(hf_afs_vldb_spare4);
+ OUT_UINT(hf_afs_vldb_spare5);
+ OUT_UINT(hf_afs_vldb_spare6);
+ OUT_UINT(hf_afs_vldb_spare7);
+ OUT_UINT(hf_afs_vldb_spare8);
+ OUT_UINT(hf_afs_vldb_spare9);
+ }
+ break;
+ }
+ }
+ else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
+ {
+ OUT_UINT(hf_afs_vldb_errcode);
+ }
+}
+
+static void
+dissect_vldb_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
+{
+ offset += 4; /* skip the opcode */
+
+ switch ( opcode )
+ {
+ case 501: /* create new volume */
+ case 517: /* create entry N */
+ OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
+ break;
+ case 502: /* delete entry */
+ case 503: /* get entry by id */
+ case 507: /* update entry */
+ case 508: /* set lock */
+ case 509: /* release lock */
+ case 518: /* get entry by id */
+ OUT_UINT(hf_afs_vldb_id);
+ OUT_UINT(hf_afs_vldb_type);
+ break;
+ case 504: /* get entry by name */
+ case 519: /* get entry by name N */
+ case 524: /* update entry by name */
+ case 527: /* get entry by name U */
+ OUT_RXString(hf_afs_vldb_name);
+ break;
+ case 505: /* get new vol id */
+ OUT_UINT(hf_afs_vldb_bump);
+ break;
+ case 506: /* replace entry */
+ case 520: /* replace entry N */
+ OUT_UINT(hf_afs_vldb_id);
+ OUT_UINT(hf_afs_vldb_type);
+ OUT_RXStringV(hf_afs_vldb_name, VLNAMEMAX);
+ break;
+ case 510: /* list entry */
+ case 521: /* list entry N */
+ OUT_UINT(hf_afs_vldb_index);
+ break;
+ case 532: /* regaddr */
+ OUT_UUID(hf_afs_vldb_serveruuid);
+ OUT_UINT(hf_afs_vldb_spare1);
+ OUT_VLDB_BulkAddr();
+ break;
+ }
+}
+
+/*
+ * UBIK Helpers
+ */
+static void
+dissect_ubik_reply(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
+{
+ switch ( opcode )
+ {
+ case 10000: /* vote-beacon */
+ break;
+ case 10001: /* vote-debug-old */
+ OUT_UBIK_DebugOld();
+ break;
+ case 10002: /* vote-sdebug-old */
+ OUT_UBIK_SDebugOld();
+ break;
+ case 10003: /* vote-get syncsite */
+ break;
+ case 10004: /* vote-debug */
+ OUT_UBIK_DebugOld();
+ OUT_UBIK_InterfaceAddrs();
+ break;
+ case 10005: /* vote-sdebug */
+ OUT_UBIK_SDebugOld();
+ OUT_UBIK_InterfaceAddrs();
+ break;
+ case 10006: /* vote-xdebug */
+ OUT_UBIK_DebugOld();
+ OUT_UBIK_InterfaceAddrs();
+ OUT_UINT(hf_afs_ubik_isclone);
+ break;
+ case 10007: /* vote-xsdebug */
+ OUT_UBIK_SDebugOld();
+ OUT_UBIK_InterfaceAddrs();
+ OUT_UINT(hf_afs_ubik_isclone);
+ break;
+ case 20000: /* disk-begin */
+ break;
+ case 20004: /* get version */
+ OUT_UBIKVERSION("DB Version");
+ break;
+ case 20010: /* disk-probe */
+ break;
+ case 20012: /* disk-interfaceaddr */
+ OUT_UBIK_InterfaceAddrs();
+ break;
+ }
+}
+
+static void
+dissect_ubik_request(tvbuff_t *tvb, struct rxinfo *rxinfo _U_, proto_tree *tree, int offset, int opcode)
+{
+ offset += 4; /* skip the opcode */
+
+ switch ( opcode )
+ {
+ case 10000: /* vote-beacon */
+ OUT_UINT(hf_afs_ubik_state);
+ OUT_TIMESECS(hf_afs_ubik_votestart);
+ OUT_UBIKVERSION("DB Version");
+ OUT_UBIKVERSION("TID");
+ break;
+ case 10001: /* vote-debug-old */
+ break;
+ case 10002: /* vote-sdebug-old */
+ OUT_UINT(hf_afs_ubik_site);
+ break;
+ case 10003: /* vote-get sync site */
+ OUT_IP(hf_afs_ubik_site);
+ break;
+ case 10004: /* vote-debug */
+ case 10005: /* vote-sdebug */
+ OUT_IP(hf_afs_ubik_site);
+ break;
+ case 20000: /* disk-begin */
+ OUT_UBIKVERSION("TID");
+ break;
+ case 20001: /* disk-commit */
+ OUT_UBIKVERSION("TID");
+ break;
+ case 20002: /* disk-lock */
+ OUT_UBIKVERSION("TID");
+ OUT_UINT(hf_afs_ubik_file);
+ OUT_UINT(hf_afs_ubik_pos);
+ OUT_UINT(hf_afs_ubik_length);
+ OUT_UINT(hf_afs_ubik_locktype);
+ break;
+ case 20003: /* disk-write */
+ OUT_UBIKVERSION("TID");
+ OUT_UINT(hf_afs_ubik_file);
+ OUT_UINT(hf_afs_ubik_pos);
+ break;
+ case 20004: /* disk-get version */
+ break;
+ case 20005: /* disk-get file */
+ OUT_UINT(hf_afs_ubik_file);
+ break;
+ case 20006: /* disk-send file */
+ OUT_UINT(hf_afs_ubik_file);
+ OUT_UINT(hf_afs_ubik_length);
+ OUT_UBIKVERSION("DB Version");
+ break;
+ case 20007: /* disk-abort */
+ case 20008: /* disk-release locks */
+ case 20010: /* disk-probe */
+ break;
+ case 20009: /* disk-truncate */
+ OUT_UBIKVERSION("TID");
+ OUT_UINT(hf_afs_ubik_file);
+ OUT_UINT(hf_afs_ubik_length);
+ break;
+ case 20011: /* disk-writev */
+ OUT_UBIKVERSION("TID");
+ break;
+ case 20012: /* disk-interfaceaddr */
+ OUT_UBIK_InterfaceAddrs();
+ break;
+ case 20013: /* disk-set version */
+ OUT_UBIKVERSION("TID");
+ OUT_UBIKVERSION("Old DB Version");
+ OUT_UBIKVERSION("New DB Version");
+ break;
+ }
+}
+
+/*
+ * BACKUP Helpers
+ */
+static void
+dissect_backup_reply(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *tree, int offset, int opcode)
+{
+ if ( rxinfo->type == RX_PACKET_TYPE_DATA )
+ {
+ switch ( opcode )
+ {
+ }
+ }
+ else if ( rxinfo->type == RX_PACKET_TYPE_ABORT )
+ {
+ OUT_UINT(hf_afs_backup_errcode);
+ }
+}
+
+static void
+dissect_backup_request(tvbuff_t *tvb _U_, struct rxinfo *rxinfo _U_, proto_tree *tree _U_, int offset, int opcode)
+{
+ offset += 4; /* skip the opcode */
+
+ switch ( opcode )
+ {
+ }
+}
+
+/*
+ * Registration code for registering the protocol and fields
+ */
+
+void
+proto_register_afs(void)
+{
+ static hf_register_info hf[] = {
+#include "packet-afs-register-info.h"
+ };
+ static gint *ett[] = {
+ &ett_afs,
+ &ett_afs_op,
+ &ett_afs_acl,
+ &ett_afs_fid,
+ &ett_afs_callback,
+ &ett_afs_ubikver,
+ &ett_afs_status,
+ &ett_afs_status_mask,
+ &ett_afs_volsync,
+ &ett_afs_volumeinfo,
+ &ett_afs_vicestat,
+ &ett_afs_vldb_flags,
+ };
+
+ proto_afs = proto_register_protocol("Andrew File System (AFS)",
+ "AFS (RX)", "afs");
+ proto_register_field_array(proto_afs, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&afs_init_protocol);
+
+ register_dissector("afs", dissect_afs, proto_afs);
+}
diff --git a/epan/dissectors/packet-afs.h b/epan/dissectors/packet-afs.h
new file mode 100644
index 0000000000..6569b08c9b
--- /dev/null
+++ b/epan/dissectors/packet-afs.h
@@ -0,0 +1,142 @@
+/* packet-afs.h
+ * Definitions for packet disassembly structures and routines
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_AFS_H
+#define PACKET_AFS_H
+
+#define AFS_PORT_FS 7000
+#define AFS_PORT_CB 7001
+#define AFS_PORT_PROT 7002
+#define AFS_PORT_VLDB 7003
+#define AFS_PORT_KAUTH 7004
+#define AFS_PORT_VOL 7005
+#define AFS_PORT_ERROR 7006 /* Doesn't seem to be used */
+#define AFS_PORT_BOS 7007
+#define AFS_PORT_UPDATE 7008
+#define AFS_PORT_RMTSYS 7009
+#define AFS_PORT_BACKUP 7021
+
+#ifndef AFSNAMEMAX
+#define AFSNAMEMAX 256
+#endif
+
+#ifndef AFSOPAQUEMAX
+#define AFSOPAQUEMAX 1024
+#endif
+
+#define PRNAMEMAX 64
+#define VLNAMEMAX 65
+#define KANAMEMAX 64
+#define BOSNAMEMAX 256
+
+#define PRSFS_READ 1 /* Read files */
+#define PRSFS_WRITE 2 /* Write files */
+#define PRSFS_INSERT 4 /* Insert files into a directory */
+#define PRSFS_LOOKUP 8 /* Lookup files into a directory */
+#define PRSFS_DELETE 16 /* Delete files */
+#define PRSFS_LOCK 32 /* Lock files */
+#define PRSFS_ADMINISTER 64 /* Change ACL's */
+
+#define CB_TYPE_EXCLUSIVE 1
+#define CB_TYPE_SHARED 2
+#define CB_TYPE_DROPPED 3
+
+#define OPCODE_LOW 0
+#define OPCODE_HIGH 66000 /* arbitrary, is just a fuzzy check for encrypted traffic */
+#define VOTE_LOW 10000
+#define VOTE_HIGH 10007
+#define DISK_LOW 20000
+#define DISK_HIGH 20013
+
+#define FILE_TYPE_FILE 1
+#define FILE_TYPE_DIR 2
+#define FILE_TYPE_LINK 3
+
+struct afs_header {
+ guint32 opcode;
+};
+
+struct afs_volsync {
+ guint32 spare1;
+ guint32 spare2;
+ guint32 spare3;
+ guint32 spare4;
+ guint32 spare5;
+ guint32 spare6;
+};
+
+struct afs_status {
+ guint32 InterfaceVersion;
+ guint32 FileType;
+ guint32 LinkCount;
+ guint32 Length;
+ guint32 DataVersion;
+ guint32 Author;
+ guint32 Owner;
+ guint32 CallerAccess;
+ guint32 AnonymousAccess;
+ guint32 UnixModeBits;
+ guint32 ParentVnode;
+ guint32 ParentUnique;
+ guint32 SegSize;
+ guint32 ClientModTime;
+ guint32 ServerModTime;
+ guint32 Group;
+ guint32 SyncCount;
+ guint32 spare1;
+ guint32 spare2;
+ guint32 spare3;
+ guint32 spare4;
+};
+
+struct afs_volumeinfo {
+ guint32 Vid;
+ guint32 Type;
+ guint32 Type0;
+ guint32 Type1;
+ guint32 Type2;
+ guint32 Type3;
+ guint32 Type4;
+ guint32 ServerCount;
+ guint32 Server0;
+ guint32 Server1;
+ guint32 Server2;
+ guint32 Server3;
+ guint32 Server4;
+ guint32 Server5;
+ guint32 Server6;
+ guint32 Server7;
+ guint16 Part0;
+ guint16 Part1;
+ guint16 Part2;
+ guint16 Part3;
+ guint16 Part4;
+ guint16 Part5;
+ guint16 Part6;
+ guint16 Part7;
+};
+
+
+#endif
diff --git a/epan/dissectors/packet-aim-admin.c b/epan/dissectors/packet-aim-admin.c
new file mode 100644
index 0000000000..5a347bff5d
--- /dev/null
+++ b/epan/dissectors/packet-aim-admin.c
@@ -0,0 +1,170 @@
+/* packet-aim-admin.c
+ * Routines for AIM (OSCAR) dissection, Administration Service
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_ADMIN 0x0007
+
+/* Family Admin */
+#define FAMILY_ADMIN_ERROR 0x0001
+#define FAMILY_ADMIN_ACCNT_INFO_REQ 0x0002
+#define FAMILY_ADMIN_ACCNT_INFO_REPL 0x0003
+#define FAMILY_ADMIN_INFOCHANGEREQ 0x0004
+#define FAMILY_ADMIN_INFOCHANGEREPLY 0x0005
+#define FAMILY_ADMIN_ACCT_CFRM_REQ 0x0006
+#define FAMILY_ADMIN_ACCT_CFRM_REPL 0x0007
+#define FAMILY_ADMIN_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_admin[] = {
+ { FAMILY_ADMIN_ERROR, "Error" },
+ { FAMILY_ADMIN_ACCNT_INFO_REQ, "Request Account Information" },
+ { FAMILY_ADMIN_ACCNT_INFO_REPL, "Requested Account Information" },
+ { FAMILY_ADMIN_INFOCHANGEREQ, "Infochange Request" },
+ { FAMILY_ADMIN_INFOCHANGEREPLY, "Infochange Reply" },
+ { FAMILY_ADMIN_ACCT_CFRM_REQ, "Account Confirm Request" },
+ { FAMILY_ADMIN_ACCT_CFRM_REPL, "Account Confirm Reply" },
+ { FAMILY_ADMIN_DEFAULT, "Adminstrative Default" },
+ { 0, NULL }
+};
+
+#define CONFIRM_STATUS_EMAIL_SENT 0x00
+#define CONFIRM_STATUS_ALREADY_CONFIRMED 0x1E
+#define CONFIRM_STATUS_SERVER_ERROR 0x23
+
+static const value_string confirm_statusses[] = {
+ { CONFIRM_STATUS_EMAIL_SENT, "A confirmation email has been sent" },
+ { CONFIRM_STATUS_ALREADY_CONFIRMED, "Account was already confirmed" },
+ { CONFIRM_STATUS_SERVER_ERROR, "Server couldn't start confirmation process" },
+ { 0, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_admin = -1;
+static int hf_admin_acctinfo_code = -1;
+static int hf_admin_acctinfo_permissions = -1;
+static int hf_admin_confirm_status = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_admin = -1;
+
+static int dissect_aim_admin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ struct aiminfo *aiminfo = pinfo->private_data;
+ proto_item *ti = NULL;
+ proto_tree *admin_tree = NULL;
+ int offset = 0;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Administration Service");
+ admin_tree = proto_item_add_subtree(ti, ett_aim_admin);
+ }
+
+ switch(aiminfo->subtype) {
+ case FAMILY_ADMIN_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, 0, admin_tree);
+ case FAMILY_ADMIN_ACCNT_INFO_REQ:
+ proto_tree_add_item(admin_tree, hf_admin_acctinfo_code, tvb, 0, 2, tvb_get_ntohs(tvb, 0));
+ proto_tree_add_text(admin_tree, tvb, 2, 2, "Unknown");
+ return 4;
+
+ case FAMILY_ADMIN_INFOCHANGEREPLY:
+ case FAMILY_ADMIN_ACCNT_INFO_REPL:
+ {
+ proto_tree_add_uint(admin_tree, hf_admin_acctinfo_permissions, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ return dissect_aim_tlv_list(tvb, pinfo, offset, admin_tree, client_tlvs);
+ }
+ case FAMILY_ADMIN_INFOCHANGEREQ:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, admin_tree, client_tlvs);
+ }
+ return offset;
+ case FAMILY_ADMIN_ACCT_CFRM_REQ:
+ /* No data */
+ return 0;
+ case FAMILY_ADMIN_ACCT_CFRM_REPL:
+ proto_tree_add_uint(admin_tree, hf_admin_confirm_status, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, admin_tree, client_tlvs);
+ }
+ return offset;
+
+ default: return 0;
+ }
+ return 0;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_admin(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_admin_acctinfo_code,
+ { "Account Information Request Code", "aim.acctinfo.code", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_admin_acctinfo_permissions,
+ { "Account Permissions", "aim.acctinfo.permissions", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_admin_confirm_status,
+ { "Confirmation status", "admin.confirm_status", FT_UINT16, BASE_HEX, VALS(confirm_statusses), 0x0, "", HFILL },
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_admin,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_admin = proto_register_protocol("AIM Administrative", "AIM Administration", "aim_admin");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim_admin, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_admin(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim_admin, proto_aim_admin);
+ dissector_add("aim.family", FAMILY_ADMIN, aim_handle);
+ aim_init_family(FAMILY_ADMIN, "Administration", aim_fnac_family_admin);
+}
diff --git a/epan/dissectors/packet-aim-adverts.c b/epan/dissectors/packet-aim-adverts.c
new file mode 100644
index 0000000000..a0fc9a4663
--- /dev/null
+++ b/epan/dissectors/packet-aim-adverts.c
@@ -0,0 +1,121 @@
+/* packet-aim-adverts.c
+ * Routines for AIM (OSCAR) dissection, SNAC Advertisements
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_ADVERTS 0x0005
+
+/* Family Advertising */
+#define FAMILY_ADVERTS_ERROR 0x0001
+#define FAMILY_ADVERTS_REQUEST 0x0002
+#define FAMILY_ADVERTS_DATA 0x0003
+#define FAMILY_ADVERTS_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_adverts[] = {
+ { FAMILY_ADVERTS_ERROR, "Error" },
+ { FAMILY_ADVERTS_REQUEST, "Request" },
+ { FAMILY_ADVERTS_DATA, "Data (GIF)" },
+ { FAMILY_ADVERTS_DEFAULT, "Adverts Default" },
+ { 0, NULL }
+};
+
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_adverts = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_adverts = -1;
+
+static int dissect_aim_adverts(tvbuff_t *tvb _U_,
+ packet_info *pinfo _U_,
+ proto_tree *tree _U_)
+{
+ struct aiminfo *aiminfo = pinfo->private_data;
+ int offset = 0;
+
+ switch(aiminfo->subtype) {
+ case FAMILY_ADVERTS_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, tree);
+ break;
+ case FAMILY_ADVERTS_REQUEST:
+ /* FIXME */
+ return 0;
+ case FAMILY_ADVERTS_DATA:
+ /* FIXME: */
+ /* From other sources, I understand this response contains
+ * a GIF file, haven't actually seen one though. And this
+ * family appears to be deprecated, so we might never find out.. */
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_adverts(void)
+{
+
+/* Setup list of header fields */
+/*FIXME
+ static hf_register_info hf[] = {
+ };*/
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_adverts,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_adverts = proto_register_protocol("AIM Advertisements", "AIM Advertisements", "aim_adverts");
+
+/* Required function calls to register the header fields and subtrees used */
+/*FIXME
+ proto_register_field_array(proto_aim_adverts, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_adverts(void)
+{
+ dissector_handle_t aim_handle;
+ aim_handle = new_create_dissector_handle(dissect_aim_adverts, proto_aim_adverts);
+ dissector_add("aim.family", FAMILY_ADVERTS, aim_handle);
+ aim_init_family(FAMILY_ADVERTS, "Advertisements", aim_fnac_family_adverts);
+}
diff --git a/epan/dissectors/packet-aim-bos.c b/epan/dissectors/packet-aim-bos.c
new file mode 100644
index 0000000000..69db5c4fb5
--- /dev/null
+++ b/epan/dissectors/packet-aim-bos.c
@@ -0,0 +1,175 @@
+/* packet-aim-bos.c
+ * Routines for AIM (OSCAR) dissection, SNAC BOS
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_BOS 0x0009
+
+/* Family BOS (Misc) */
+#define FAMILY_BOS_ERROR 0x0001
+#define FAMILY_BOS_RIGHTSQUERY 0x0002
+#define FAMILY_BOS_RIGHTS 0x0003
+#define FAMILY_BOS_SET_GROUP_PERM 0x0004
+#define FAMILY_BOS_ADD_TO_VISIBLE 0x0005
+#define FAMILY_BOS_DEL_FROM_VISIBLE 0x0006
+#define FAMILY_BOS_ADD_TO_INVISIBLE 0x0007
+#define FAMILY_BOS_DEL_FROM_INVISIBLE 0x0008
+#define FAMILY_BOS_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_bos[] = {
+ { FAMILY_BOS_ERROR, "Error" },
+ { FAMILY_BOS_RIGHTSQUERY, "Rights Query" },
+ { FAMILY_BOS_RIGHTS, "Rights" },
+ { FAMILY_BOS_SET_GROUP_PERM, "Set Group Permissions Mask" },
+ { FAMILY_BOS_ADD_TO_VISIBLE, "Add To Visible List" },
+ { FAMILY_BOS_DEL_FROM_VISIBLE, "Delete From Visible List" },
+ { FAMILY_BOS_ADD_TO_INVISIBLE, "Add To Invisible List" },
+ { FAMILY_BOS_DEL_FROM_INVISIBLE, "Delete From Invisible List" },
+ { FAMILY_BOS_DEFAULT, "BOS Default" },
+ { 0, NULL }
+};
+
+#define CLASS_UNCONFIRMED 0x0001
+#define CLASS_ADMINISTRATOR 0x0002
+#define CLASS_AOL 0x0004
+#define CLASS_COMMERCIAL 0x0008
+#define CLASS_FREE 0x0010
+#define CLASS_AWAY 0x0020
+#define CLASS_ICQ 0x0040
+#define CLASS_WIRELESS 0x0080
+#define CLASS_UNKNOWN100 0x0100
+#define CLASS_UNKNOWN200 0x0200
+#define CLASS_UNKNOWN400 0x0400
+#define CLASS_UNKNOWN800 0x0800
+
+#define AIM_PRIVACY_TLV_MAX_VISIB_LIST_SIZE 0x001
+#define AIM_PRIVACY_TLV_MAX_INVISIB_LIST_SIZE 0x002
+
+static const aim_tlv privacy_tlvs[] = {
+ { AIM_PRIVACY_TLV_MAX_VISIB_LIST_SIZE, "Max visible list size", dissect_aim_tlv_value_uint16 },
+ { AIM_PRIVACY_TLV_MAX_INVISIB_LIST_SIZE, "Max invisible list size", dissect_aim_tlv_value_uint16 },
+ { 0, "Unknown", NULL },
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_bos = -1;
+static int hf_aim_bos_data = -1;
+static int hf_aim_bos_class = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_bos = -1;
+
+static int dissect_aim_bos(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ struct aiminfo *aiminfo = pinfo->private_data;
+ int offset = 0;
+ proto_item *ti;
+ proto_tree *bos_tree = NULL;
+ guint32 userclass;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Privacy Management Service");
+ bos_tree = proto_item_add_subtree(ti, ett_aim_bos);
+ }
+
+ switch(aiminfo->subtype) {
+ case FAMILY_BOS_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, bos_tree);
+ case FAMILY_BOS_RIGHTSQUERY:
+ /* No data */
+ return 0;
+ case FAMILY_BOS_SET_GROUP_PERM:
+ userclass = tvb_get_ntohl(tvb, offset);
+ ti = proto_tree_add_uint(bos_tree, hf_aim_bos_class, tvb, offset, 4, userclass);
+ return dissect_aim_userclass(tvb, offset, 4, ti, userclass);
+ case FAMILY_BOS_RIGHTS:
+ while(tvb_reported_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, bos_tree, privacy_tlvs);
+ }
+ return offset;
+ case FAMILY_BOS_ADD_TO_VISIBLE:
+ case FAMILY_BOS_DEL_FROM_VISIBLE:
+ case FAMILY_BOS_ADD_TO_INVISIBLE:
+ case FAMILY_BOS_DEL_FROM_INVISIBLE:
+ while(tvb_reported_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_buddyname(tvb, pinfo, offset, bos_tree);
+ }
+ return offset;
+
+ default:
+ return 0;
+ }
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_bos(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_aim_bos_data,
+ { "Data", "aim.data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_bos_class,
+ { "User class", "aim.bos.userclass", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_bos,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_bos = proto_register_protocol("AIM Privacy Management Service", "AIM BOS", "aim_bos");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim_bos, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_bos(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim_bos, proto_aim_bos);
+ dissector_add("aim.family", FAMILY_BOS, aim_handle);
+ aim_init_family(FAMILY_BOS, "Privacy Management Service", aim_fnac_family_bos);
+}
diff --git a/epan/dissectors/packet-aim-buddylist.c b/epan/dissectors/packet-aim-buddylist.c
new file mode 100644
index 0000000000..2a2cbe2bda
--- /dev/null
+++ b/epan/dissectors/packet-aim-buddylist.c
@@ -0,0 +1,235 @@
+/* packet-aim-buddylist.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Buddylist
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+#include "prefs.h"
+
+#define FAMILY_BUDDYLIST 0x0003
+
+/* Family Buddy List */
+#define FAMILY_BUDDYLIST_ERROR 0x0001
+#define FAMILY_BUDDYLIST_REQRIGHTS 0x0002
+#define FAMILY_BUDDYLIST_RIGHTSINFO 0x0003
+#define FAMILY_BUDDYLIST_ADDBUDDY 0x0004
+#define FAMILY_BUDDYLIST_REMBUDDY 0x0005
+#define FAMILY_BUDDYLIST_WATCHERS_REQ 0x0006
+#define FAMILY_BUDDYLIST_WATCHERS_REP 0x0007
+#define FAMILY_BUDDYLIST_REJECT 0x000a
+#define FAMILY_BUDDYLIST_ONCOMING 0x000b
+#define FAMILY_BUDDYLIST_OFFGOING 0x000c
+#define FAMILY_BUDDYLIST_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_buddylist[] = {
+ { FAMILY_BUDDYLIST_ERROR, "Error" },
+ { FAMILY_BUDDYLIST_REQRIGHTS, "Request Rights" },
+ { FAMILY_BUDDYLIST_RIGHTSINFO, "Rights Info" },
+ { FAMILY_BUDDYLIST_ADDBUDDY, "Add Buddy" },
+ { FAMILY_BUDDYLIST_REMBUDDY, "Remove Buddy" },
+ { FAMILY_BUDDYLIST_REJECT, "Reject Buddy" },
+ { FAMILY_BUDDYLIST_ONCOMING, "Oncoming Buddy" },
+ { FAMILY_BUDDYLIST_OFFGOING, "Offgoing Buddy" },
+ { FAMILY_BUDDYLIST_DEFAULT, "Buddy Default" },
+ { 0, NULL }
+};
+
+#define AIM_BUDDYLIST_TLV_MAX_CONTACT_ENTRIES 0x0001
+#define AIM_BUDDYLIST_TLV_MAX_WATCHER_ENTRIES 0x0002
+#define AIM_BUDDYLIST_TLV_MAX_ONLINE_NOTIFICATIONS 0x0003
+
+const aim_tlv buddylist_tlvs[] = {
+ { AIM_BUDDYLIST_TLV_MAX_CONTACT_ENTRIES, "Max number of contact list entries", dissect_aim_tlv_value_uint16 },
+ { AIM_BUDDYLIST_TLV_MAX_WATCHER_ENTRIES, "Max number of watcher list entries", dissect_aim_tlv_value_uint16 },
+ { AIM_BUDDYLIST_TLV_MAX_ONLINE_NOTIFICATIONS, "Max online notifications", dissect_aim_tlv_value_uint16 },
+ {0, NULL, NULL }
+};
+
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_buddylist = -1;
+static int hf_aim_buddyname_len = -1;
+static int hf_aim_buddyname = -1;
+static int hf_aim_userinfo_warninglevel = -1;
+static int hf_aim_userinfo_tlvcount = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_buddylist = -1;
+
+static int dissect_aim_snac_buddylist(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint8 buddyname_length = 0;
+ char buddyname[MAX_BUDDYNAME_LENGTH + 1];
+ guint16 tlv_count = 0;
+ struct aiminfo *aiminfo = pinfo->private_data;
+ int offset = 0;
+ proto_item *ti;
+ proto_tree *buddy_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1, "Buddy List Service");
+ buddy_tree = proto_item_add_subtree(ti, ett_aim_buddylist);
+ }
+
+
+ switch(aiminfo->subtype)
+ {
+ case FAMILY_BUDDYLIST_REQRIGHTS:
+ case FAMILY_BUDDYLIST_WATCHERS_REQ:
+ /* No data */
+ return 0;
+ case FAMILY_BUDDYLIST_REMBUDDY:
+ case FAMILY_BUDDYLIST_ADDBUDDY:
+ case FAMILY_BUDDYLIST_WATCHERS_REP:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_buddyname( tvb, pinfo, offset, buddy_tree);
+ }
+ return offset;
+ case FAMILY_BUDDYLIST_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, buddy_tree);
+ case FAMILY_BUDDYLIST_RIGHTSINFO:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv( tvb, pinfo, offset, buddy_tree, buddylist_tlvs);
+ }
+ return offset;
+ case FAMILY_BUDDYLIST_REJECT:
+ return dissect_aim_buddyname(tvb, pinfo, offset, buddy_tree);
+ case FAMILY_BUDDYLIST_ONCOMING:
+ buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Oncoming Buddy");
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
+ format_text(buddyname, buddyname_length));
+ }
+
+ if (buddy_tree) {
+ proto_tree_add_text(buddy_tree, tvb, offset + 1, buddyname_length,
+ "Screen Name: %s",
+ format_text(buddyname, buddyname_length));
+ }
+ offset += buddyname_length + 1;
+
+ /* Warning level */
+ proto_tree_add_item(buddy_tree, hf_aim_userinfo_warninglevel, tvb, offset,
+ 2, FALSE);
+ offset += 2;
+
+ /* TLV Count */
+ tlv_count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(buddy_tree, hf_aim_userinfo_tlvcount, tvb, offset,
+ 2, FALSE);
+ offset += 2;
+
+ while (tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, buddy_tree, onlinebuddy_tlvs);
+ }
+
+ return offset;
+
+ case FAMILY_BUDDYLIST_OFFGOING:
+ buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Offgoing Buddy");
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
+ format_text(buddyname, buddyname_length));
+ }
+
+ if (buddy_tree) {
+ proto_tree_add_text(buddy_tree, tvb, offset + 1, buddyname_length,
+ "Screen Name: %s",
+ format_text(buddyname, buddyname_length));
+ }
+ offset += buddyname_length + 1;
+
+ /* Warning level */
+ proto_tree_add_item(buddy_tree, hf_aim_userinfo_warninglevel, tvb, offset,
+ 2, FALSE);
+ offset += 2;
+
+ return dissect_aim_tlv_list(tvb, pinfo, offset, buddy_tree, onlinebuddy_tlvs);
+ default:
+ return 0;
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_buddylist(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_aim_buddyname_len,
+ { "Buddyname len", "aim.buddynamelen", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_buddyname,
+ { "Buddy Name", "aim.buddyname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_userinfo_warninglevel,
+ { "Warning Level", "aim.userinfo.warninglevel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_userinfo_tlvcount,
+ { "TLV Count", "aim.userinfo.tlvcount", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_buddylist,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_buddylist = proto_register_protocol("AIM Buddylist Service", "AIM Buddylist", "aim_buddylist");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim_buddylist, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_buddylist(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim_snac_buddylist, proto_aim_buddylist);
+ dissector_add("aim.family", FAMILY_BUDDYLIST, aim_handle);
+ aim_init_family(FAMILY_BUDDYLIST, "Buddylist", aim_fnac_family_buddylist);
+}
diff --git a/epan/dissectors/packet-aim-chat.c b/epan/dissectors/packet-aim-chat.c
new file mode 100644
index 0000000000..31905827c2
--- /dev/null
+++ b/epan/dissectors/packet-aim-chat.c
@@ -0,0 +1,193 @@
+/* packet-aim-chat.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Chat
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ * Copyright 2000, Ralf Hoelzer <ralf@well.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-tcp.h"
+#include "packet-aim.h"
+#include "prefs.h"
+
+/* SNAC families */
+#define FAMILY_CHAT 0x000E
+
+/* Family Chat */
+#define FAMILY_CHAT_ERROR 0x0001
+#define FAMILY_CHAT_ROOMINFOUPDATE 0x0002
+#define FAMILY_CHAT_USERJOIN 0x0003
+#define FAMILY_CHAT_USERLEAVE 0x0004
+#define FAMILY_CHAT_OUTGOINGMSG 0x0005
+#define FAMILY_CHAT_INCOMINGMSG 0x0006
+#define FAMILY_CHAT_EVIL_REQ 0x0007
+#define FAMILY_CHAT_EVIL_REPLY 0x0008
+#define FAMILY_CHAT_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_chat[] = {
+ { FAMILY_CHAT_ERROR, "Error" },
+ { FAMILY_CHAT_ROOMINFOUPDATE, "Room Info Update" },
+ { FAMILY_CHAT_USERJOIN, "User Join" },
+ { FAMILY_CHAT_USERLEAVE, "User Leave" },
+ { FAMILY_CHAT_OUTGOINGMSG, "Outgoing Message" },
+ { FAMILY_CHAT_INCOMINGMSG, "Incoming Message" },
+ { FAMILY_CHAT_EVIL_REQ, "Evil Request" },
+ { FAMILY_CHAT_EVIL_REPLY, "Evil Reply" },
+ { FAMILY_CHAT_DEFAULT, "Chat Default" },
+ { 0, NULL }
+};
+
+#define AIM_CHAT_TLV_BROWSABLE_TREE 0x001
+#define AIM_CHAT_TLV_CLASS_EXCLUSIVE 0x002
+#define AIM_CHAT_TLV_MAX_CONCURRENT_ROOMS 0x003
+#define AIM_CHAT_TLV_MAX_ROOM_NAME_LEN 0x004
+#define AIM_CHAT_TLV_ROOT_ROOMS 0x005
+#define AIM_CHAT_TLV_SEARCH_TAGS 0x006
+#define AIM_CHAT_TLV_CHILD_ROOMS 0x065
+#define AIM_CHAT_TLV_CONTAINS_USER_CLASS 0x066
+#define AIM_CHAT_TLV_CONTAINS_USER_ARRAY 0x067
+
+static const aim_tlv chat_tlvs[] = {
+ { AIM_CHAT_TLV_BROWSABLE_TREE, "Browsable tree", dissect_aim_tlv_value_bytes },
+ { AIM_CHAT_TLV_CLASS_EXCLUSIVE, "Exclusively for class", dissect_aim_tlv_value_userclass },
+ { AIM_CHAT_TLV_MAX_CONCURRENT_ROOMS, "Max. number of concurrent rooms", dissect_aim_tlv_value_uint8 },
+ { AIM_CHAT_TLV_MAX_ROOM_NAME_LEN, "Max. length of room name", dissect_aim_tlv_value_uint8 },
+ { AIM_CHAT_TLV_ROOT_ROOMS, "Root Rooms", dissect_aim_tlv_value_bytes },
+ { AIM_CHAT_TLV_SEARCH_TAGS, "Search Tags", dissect_aim_tlv_value_bytes },
+ { AIM_CHAT_TLV_CHILD_ROOMS, "Child Rooms", dissect_aim_tlv_value_bytes },
+ { AIM_CHAT_TLV_CONTAINS_USER_CLASS, "Contains User Class", dissect_aim_tlv_value_bytes },
+ { AIM_CHAT_TLV_CONTAINS_USER_ARRAY, "Contains User Array", dissect_aim_tlv_value_bytes },
+ { 0, NULL, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_chat = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_chat = -1;
+
+static int dissect_aim_snac_chat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 buddyname_length = 0;
+ int offset = 0;
+ struct aiminfo *aiminfo = pinfo->private_data;
+ char buddyname[MAX_BUDDYNAME_LENGTH + 1];
+ guchar msg[1000];
+ proto_item *ti;
+ proto_tree *chat_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1, "Chat Service");
+ chat_tree = proto_item_add_subtree(ti, ett_aim_chat);
+ }
+
+ switch(aiminfo->subtype)
+ {
+ case FAMILY_CHAT_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, chat_tree);
+ case FAMILY_CHAT_USERLEAVE:
+ case FAMILY_CHAT_USERJOIN:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_userinfo(tvb, pinfo, offset, chat_tree);
+ }
+ return offset;
+ case FAMILY_CHAT_EVIL_REQ:
+ case FAMILY_CHAT_EVIL_REPLY:
+ case FAMILY_CHAT_ROOMINFOUPDATE:
+ /* FIXME */
+ return 0;
+ case FAMILY_CHAT_OUTGOINGMSG:
+ /* channel message from client */
+ aim_get_message( msg, tvb, 40 + buddyname_length, tvb_length(tvb)
+ - 40 - buddyname_length );
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", msg);
+ return tvb_length(tvb);
+
+ case FAMILY_CHAT_INCOMINGMSG:
+ /* channel message to client */
+ buddyname_length = aim_get_buddyname( buddyname, tvb, 30, 31 );
+ aim_get_message( msg, tvb, 36 + buddyname_length, tvb_length(tvb)
+ - 36 - buddyname_length );
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "from: %s", buddyname);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", msg);
+ }
+
+ if(chat_tree) {
+ proto_tree_add_text(chat_tree, tvb, 31, buddyname_length,
+ "Screen Name: %s",
+ format_text(buddyname, buddyname_length));
+ }
+ return tvb_length(tvb);
+ default:
+ return 0;
+ }
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_chat(void)
+{
+
+/* Setup list of header fields */
+/*FIXME
+ static hf_register_info hf[] = {
+ };*/
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_chat,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_chat = proto_register_protocol("AIM Chat Service", "AIM Chat", "aim_chat");
+
+/* Required function calls to register the header fields and subtrees used */
+/*FIXME
+ proto_register_field_array(proto_aim_chat, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_chat(void)
+{
+ dissector_handle_t aim_handle;
+ aim_handle = new_create_dissector_handle(dissect_aim_snac_chat, proto_aim_chat);
+ dissector_add("aim.family", FAMILY_CHAT, aim_handle);
+ aim_init_family(FAMILY_CHAT, "Chat", aim_fnac_family_chat);
+}
diff --git a/epan/dissectors/packet-aim-chatnav.c b/epan/dissectors/packet-aim-chatnav.c
new file mode 100644
index 0000000000..d7cb30704c
--- /dev/null
+++ b/epan/dissectors/packet-aim-chatnav.c
@@ -0,0 +1,139 @@
+/* packet-aim.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_CHAT_NAV 0x000D
+
+/* Family Chat Navigation */
+#define FAMILY_CHATNAV_ERROR 0x0001
+#define FAMILY_CHATNAV_LIMITS_REQ 0x0002
+#define FAMILY_CHATNAV_EXCHANGE_REQ 0x0003
+#define FAMILY_CHATNAV_ROOM_INFO_REQ 0x0004
+#define FAMILY_CHATNAV_ROOMIF_EXT_REQ 0x0005
+#define FAMILY_CHATNAV_MEMBERLIST_REQ 0x0006
+#define FAMILY_CHATNAV_SEARCH_ROOM 0x0007
+#define FAMILY_CHATNAV_CREATE_ROOM 0x0008
+#define FAMILY_CHATNAV_INFO_REPLY 0x0009
+#define FAMILY_CHATNAV_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_chatnav[] = {
+ { FAMILY_CHATNAV_ERROR, "Error" },
+ { FAMILY_CHATNAV_LIMITS_REQ, "Request Limits" },
+ { FAMILY_CHATNAV_EXCHANGE_REQ, "Request Exchange" },
+ { FAMILY_CHATNAV_ROOM_INFO_REQ, "Request Room Information" },
+ { FAMILY_CHATNAV_ROOMIF_EXT_REQ, "Request Extended Room Information" },
+ { FAMILY_CHATNAV_MEMBERLIST_REQ, "Request Member List" },
+ { FAMILY_CHATNAV_SEARCH_ROOM, "Search Room" },
+ { FAMILY_CHATNAV_CREATE_ROOM, "Create" },
+ { FAMILY_CHATNAV_INFO_REPLY, "Info" },
+ { FAMILY_CHATNAV_DEFAULT, "ChatNav Default" },
+ { 0, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_chatnav = -1;
+
+int ett_aim_chatnav = -1;
+
+static int dissect_aim_chatnav(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct aiminfo *aiminfo = pinfo->private_data;
+
+ proto_item *ti;
+ proto_tree *chatnav_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1, "Chat Navigation Service");
+ chatnav_tree = proto_item_add_subtree(ti, ett_aim_chatnav);
+ }
+
+ switch(aiminfo->subtype) {
+ case FAMILY_CHATNAV_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, 0, chatnav_tree);
+ case FAMILY_CHATNAV_LIMITS_REQ:
+ /* No data */
+ return 0;
+ case FAMILY_CHATNAV_EXCHANGE_REQ:
+ case FAMILY_CHATNAV_ROOM_INFO_REQ:
+ case FAMILY_CHATNAV_ROOMIF_EXT_REQ:
+ case FAMILY_CHATNAV_MEMBERLIST_REQ:
+ case FAMILY_CHATNAV_SEARCH_ROOM:
+ case FAMILY_CHATNAV_CREATE_ROOM:
+ case FAMILY_CHATNAV_INFO_REPLY:
+ case FAMILY_CHATNAV_DEFAULT:
+ /* FIXME */
+ return 0;
+ default: return 0;
+ }
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_chatnav(void)
+{
+
+/* Setup list of header fields */
+/*FIXME
+ static hf_register_info hf[] = {
+ };*/
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_chatnav,
+ };
+/* Register the protocol name and description */
+ proto_aim_chatnav = proto_register_protocol("AIM Chat Navigation", "AIM ChatNav", "aim_chatnav");
+
+/* Required function calls to register the header fields and subtrees used */
+/*FIXME
+ proto_register_field_array(proto_aim_chatnav, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_chatnav(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim_chatnav, proto_aim_chatnav);
+ dissector_add("aim.family", FAMILY_CHAT_NAV, aim_handle);
+
+ aim_init_family(FAMILY_CHAT_NAV, "Chat Navigation", aim_fnac_family_chatnav);
+}
diff --git a/epan/dissectors/packet-aim-directory.c b/epan/dissectors/packet-aim-directory.c
new file mode 100644
index 0000000000..ea9d064d9f
--- /dev/null
+++ b/epan/dissectors/packet-aim-directory.c
@@ -0,0 +1,124 @@
+/* packet-aim-directory.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Directory
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_DIRECTORY 0x000F
+
+#define FAMILY_DIRECTORY_ERROR 0x0001
+#define FAMILY_DIRECTORY_SEARCH_USER_REQ 0x0002
+#define FAMILY_DIRECTORY_SEARCH_USER_REPL 0x0003
+#define FAMILY_DIRECTORY_INTERESTS_LIST_REQ 0x0004
+#define FAMILY_DIRECTORY_INTERESTS_LIST_REP 0x0005
+
+static const value_string aim_fnac_family_directory[] = {
+ { FAMILY_DIRECTORY_ERROR, "Error" },
+ { FAMILY_DIRECTORY_SEARCH_USER_REQ, "Client search for user request" },
+ { FAMILY_DIRECTORY_SEARCH_USER_REPL, "Server reply for search request (found users)" },
+ { FAMILY_DIRECTORY_INTERESTS_LIST_REQ, "Request interests list from server" },
+ { FAMILY_DIRECTORY_INTERESTS_LIST_REP, "Interests list" },
+ { 0, NULL },
+};
+
+static int proto_aim_directory = -1;
+static int ett_aim_directory = -1;
+
+static int dissect_aim_directory(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct aiminfo *aiminfo = pinfo->private_data;
+ proto_item *ti;
+ int offset = 0;
+ proto_tree *directory_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1, "Directory Service");
+ directory_tree = proto_item_add_subtree(ti, ett_aim_directory);
+ }
+
+ switch(aiminfo->subtype) {
+ case FAMILY_DIRECTORY_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, 0, directory_tree);
+ case FAMILY_DIRECTORY_INTERESTS_LIST_REQ:
+ return 0;
+ case FAMILY_DIRECTORY_SEARCH_USER_REQ:
+ /* FIXME */
+ return 0;
+ case FAMILY_DIRECTORY_SEARCH_USER_REPL:
+ while (tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
+ }
+ return offset;
+ case FAMILY_DIRECTORY_INTERESTS_LIST_REP:
+ /* FIXME */
+ return 0;
+ }
+ return 0;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_directory(void)
+{
+
+/* Setup list of header fields */
+/*FIXME
+ static hf_register_info hf[] = {
+ };*/
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_directory
+ };
+/* Register the protocol name and description */
+ proto_aim_directory = proto_register_protocol("AIM Directory Search", "AIM Directory", "aim_dir");
+
+/* Required function calls to register the header fields and subtrees used */
+/*FIXME
+ proto_register_field_array(proto_aim_directory, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_directory(void)
+{
+ dissector_handle_t aim_handle;
+ aim_handle = new_create_dissector_handle(dissect_aim_directory, proto_aim_directory);
+ dissector_add("aim.family", FAMILY_DIRECTORY, aim_handle);
+ aim_init_family(FAMILY_DIRECTORY, "Directory", aim_fnac_family_directory);
+}
diff --git a/epan/dissectors/packet-aim-generic.c b/epan/dissectors/packet-aim-generic.c
new file mode 100644
index 0000000000..caefda6428
--- /dev/null
+++ b/epan/dissectors/packet-aim-generic.c
@@ -0,0 +1,561 @@
+/* packet-aim-generic.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Family Generic
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+#include "prefs.h"
+
+#define STRIP_TAGS 1
+
+/* SNAC families */
+#define FAMILY_GENERIC 0x0001
+
+/* Family Generic */
+#define FAMILY_GENERIC_ERROR 0x0001
+#define FAMILY_GENERIC_CLIENTREADY 0x0002
+#define FAMILY_GENERIC_SERVERREADY 0x0003
+#define FAMILY_GENERIC_SERVICEREQ 0x0004
+#define FAMILY_GENERIC_REDIRECT 0x0005
+#define FAMILY_GENERIC_RATEINFOREQ 0x0006
+#define FAMILY_GENERIC_RATEINFO 0x0007
+#define FAMILY_GENERIC_RATEINFOACK 0x0008
+#define FAMILY_GENERIC_RATECHANGE 0x000a
+#define FAMILY_GENERIC_SERVERPAUSE 0x000b
+#define FAMILY_GENERIC_CLIENTPAUSEACK 0x000c
+#define FAMILY_GENERIC_SERVERRESUME 0x000d
+#define FAMILY_GENERIC_REQSELFINFO 0x000e
+#define FAMILY_GENERIC_SELFINFO 0x000f
+#define FAMILY_GENERIC_EVIL 0x0010
+#define FAMILY_GENERIC_SETIDLE 0x0011
+#define FAMILY_GENERIC_MIGRATIONREQ 0x0012
+#define FAMILY_GENERIC_MOTD 0x0013
+#define FAMILY_GENERIC_SETPRIVFLAGS 0x0014
+#define FAMILY_GENERIC_WELLKNOWNURL 0x0015
+#define FAMILY_GENERIC_NOP 0x0016
+#define FAMILY_GENERIC_CAPABILITIES 0x0017
+#define FAMILY_GENERIC_CAPACK 0x0018
+#define FAMILY_GENERIC_SETSTATUS 0x001e
+#define FAMILY_GENERIC_CLIENTVERREQ 0x001f
+#define FAMILY_GENERIC_CLIENTVERREPL 0x0020
+#define FAMILY_GENERIC_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_generic[] = {
+ { FAMILY_GENERIC_ERROR, "Error" },
+ { FAMILY_GENERIC_CLIENTREADY , "Client Ready" },
+ { FAMILY_GENERIC_SERVERREADY, "Server Ready" },
+ { FAMILY_GENERIC_SERVICEREQ, "Service Request" },
+ { FAMILY_GENERIC_REDIRECT, "Redirect" },
+ { FAMILY_GENERIC_RATEINFOREQ, "Rate Info Request" },
+ { FAMILY_GENERIC_RATEINFO, "Rate Info" },
+ { FAMILY_GENERIC_RATEINFOACK, "Rate Info Ack" },
+ { FAMILY_GENERIC_RATECHANGE, "Rate Change" },
+ { FAMILY_GENERIC_SERVERPAUSE, "Server Pause" },
+ { FAMILY_GENERIC_CLIENTPAUSEACK, "Client Pause Ack" },
+ { FAMILY_GENERIC_SERVERRESUME, "Server Resume" },
+ { FAMILY_GENERIC_REQSELFINFO, "Self Info Request" },
+ { FAMILY_GENERIC_SELFINFO, "Self Info" },
+ { FAMILY_GENERIC_EVIL, "Evil" },
+ { FAMILY_GENERIC_SETIDLE, "Set Idle" },
+ { FAMILY_GENERIC_MIGRATIONREQ, "Migration Request" },
+ { FAMILY_GENERIC_MOTD, "Message Of The Day" },
+ { FAMILY_GENERIC_SETPRIVFLAGS, "Set Privilege Flags" },
+ { FAMILY_GENERIC_WELLKNOWNURL, "Well Known URL" },
+ { FAMILY_GENERIC_NOP, "noop" },
+ { FAMILY_GENERIC_CAPABILITIES, "Capabilities" },
+ { FAMILY_GENERIC_CAPACK, "Capabilities Ack" },
+ { FAMILY_GENERIC_SETSTATUS, "Set Status (ICQ specific)" },
+ { FAMILY_GENERIC_CLIENTVERREQ, "Client Verification Requst" },
+ { FAMILY_GENERIC_CLIENTVERREPL, "Client Verification Reply" },
+ { FAMILY_GENERIC_DEFAULT, "Generic Default" },
+ { 0, NULL }
+};
+
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_MDT_UPGRADE 0x0001
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_ADV_UPGRADE 0x0002
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_SYS_BULLETIN 0x0003
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_NORMAL 0x0004
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_NEWS 0x0006
+
+static const value_string aim_snac_generic_motd_motdtypes[] = {
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_MDT_UPGRADE, "Mandatory Upgrade Needed Notice" },
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_ADV_UPGRADE, "Advisable Upgrade Notice" },
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_SYS_BULLETIN, "AIM/ICQ Service System Announcements" },
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_NORMAL, "Standard Notice" },
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_NEWS, "News from AOL service" },
+ { 0, NULL }
+};
+
+#define RATEINFO_STATE_LIMITED 0x01
+#define RATEINFO_STATE_ALERT 0x02
+#define RATEINFO_STATE_CLEAR 0x03
+
+static const value_string rateinfo_states[] = {
+ { RATEINFO_STATE_LIMITED, "Limited" },
+ { RATEINFO_STATE_ALERT, "Alert" },
+ { RATEINFO_STATE_CLEAR, "Clear" },
+ { 0, NULL }
+};
+
+#define RATECHANGE_MSG_LIMIT_PARAMS_CHANGED 0x0001
+#define RATECHANGE_MSG_LIMIT_WARN 0x0002
+#define RATECHANGE_MSG_LIMIT_HIT 0x0003
+#define RATECHANGE_MSG_LIMIT_CLEAR 0x0004
+
+static const value_string ratechange_msgs[] = {
+ { RATECHANGE_MSG_LIMIT_PARAMS_CHANGED, "Rate limits parameters changed" },
+ { RATECHANGE_MSG_LIMIT_WARN, "Rate limits warning (current level < alert level)" },
+ { RATECHANGE_MSG_LIMIT_HIT, "Rate limit hit (current level < limit level)" },
+ { RATECHANGE_MSG_LIMIT_CLEAR, "Rate limit clear (current level now > clear level)" },
+ { 0, NULL },
+};
+
+static int dissect_aim_snac_generic(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree);
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_generic = -1;
+static int hf_generic_motd_motdtype = -1;
+static int hf_generic_servicereq_service = -1;
+static int hf_generic_rateinfo_numclasses = -1;
+static int hf_generic_rateinfo_windowsize = -1;
+static int hf_generic_rateinfo_clearlevel = -1;
+static int hf_generic_rateinfo_alertlevel = -1;
+static int hf_generic_rateinfo_limitlevel = -1;
+static int hf_generic_rateinfo_disconnectlevel = -1;
+static int hf_generic_rateinfo_currentlevel = -1;
+static int hf_generic_rateinfo_maxlevel = -1;
+static int hf_generic_rateinfo_lasttime = -1;
+static int hf_generic_rateinfo_curstate = -1;
+static int hf_generic_rateinfo_classid = -1;
+static int hf_generic_rateinfo_numpairs = -1;
+static int hf_generic_rateinfoack_group = -1;
+static int hf_generic_ratechange_msg = -1;
+static int hf_generic_migration_numfams = -1;
+static int hf_generic_priv_flags = -1;
+static int hf_generic_allow_idle_see = -1;
+static int hf_generic_allow_member_see = -1;
+static int hf_generic_selfinfo_warninglevel = -1;
+static int hf_generic_evil_new_warn_level = -1;
+static int hf_generic_idle_time = -1;
+static int hf_generic_client_ver_req_offset = -1;
+static int hf_generic_client_ver_req_length = -1;
+static int hf_generic_client_ver_req_hash = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_generic_clientready = -1;
+static gint ett_generic_migratefamilies = -1;
+static gint ett_generic_clientready_item = -1;
+static gint ett_generic_serverready = -1;
+static gint ett_generic = -1;
+static gint ett_generic_priv_flags = -1;
+static gint ett_generic_rateinfo_class = -1;
+static gint ett_generic_rateinfo_classes = -1;
+static gint ett_generic_rateinfo_groups = -1;
+static gint ett_generic_rateinfo_group = -1;
+
+static int dissect_rate_class(tvbuff_t *tvb, packet_info *pinfo _U_, int offset,
+ proto_tree *class_tree) {
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_classid, tvb, offset, 2, tvb_get_ntohs(tvb, offset));offset+=2;
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_windowsize, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_clearlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_alertlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_limitlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_disconnectlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_currentlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_maxlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_lasttime, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
+ proto_tree_add_uint(class_tree, hf_generic_rateinfo_curstate, tvb, offset, 1, tvb_get_guint8(tvb, offset));offset+=1;
+ return offset;
+}
+
+static int dissect_generic_rateinfo(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree) {
+ int offset = 0;
+ guint16 i;
+ proto_item *ti;
+ guint16 numclasses = tvb_get_ntohs(tvb, 0);
+ proto_tree *classes_tree = NULL, *groups_tree, *group_tree;
+ proto_tree_add_uint(tree, hf_generic_rateinfo_numclasses, tvb, 0, 2, numclasses );
+ offset+=2;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, 33*numclasses, "Available Rate Classes");
+ classes_tree = proto_item_add_subtree(ti, ett_generic_rateinfo_classes);
+ }
+
+ for(i = 0; i < numclasses; i++) {
+ guint16 myid = tvb_get_ntohs(tvb, offset);
+ proto_item *ti = proto_tree_add_text(classes_tree, tvb, offset, 33,"Rate Class 0x%02x", myid);
+ proto_tree *class_tree = proto_item_add_subtree(ti, ett_generic_rateinfo_class);
+ offset = dissect_rate_class(tvb, pinfo, offset, class_tree);
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "Rate Groups");
+ groups_tree = proto_item_add_subtree(ti, ett_generic_rateinfo_groups);
+
+ for(i = 0; i < numclasses; i++) {
+ guint16 myid = tvb_get_ntohs(tvb, offset);
+ guint16 j;
+ guint16 numpairs;
+
+ proto_item *ti = proto_tree_add_text(groups_tree, tvb, offset, 33,"Rate Group 0x%02x", myid);
+ group_tree = proto_item_add_subtree(ti, ett_generic_rateinfo_group);
+ proto_tree_add_uint(group_tree, hf_generic_rateinfo_classid, tvb, offset, 2, myid);offset+=2;
+ numpairs = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(group_tree, hf_generic_rateinfo_numpairs, tvb, offset, 2, numpairs); offset+=2;
+ for(j = 0; j < numpairs; j++) {
+ const char *fam_name, *subtype_name;
+ guint16 family;
+ guint16 subtype;
+ family = tvb_get_ntohs(tvb, offset); offset+=2;
+ subtype = tvb_get_ntohs(tvb, offset); offset+=2;
+
+ fam_name = aim_get_familyname(family);
+ subtype_name = aim_get_subtypename(family, subtype);
+
+ proto_tree_add_text(group_tree, tvb, offset-4, 4, "Family: %s (0x%04x), Subtype: %s (0x%04x)", fam_name?fam_name:"Unknown", family, subtype_name?subtype_name:"Unknown", subtype);
+ }
+ }
+
+ return offset;
+}
+
+static int dissect_aim_snac_generic(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ int offset = 0;
+ const char *name;
+ struct aiminfo *aiminfo = pinfo->private_data;
+ guint16 n, i;
+ proto_item *ti = NULL;
+ proto_tree *gen_tree = NULL;
+ proto_tree *entry = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Generic Service");
+ gen_tree = proto_item_add_subtree(ti, ett_generic);
+ }
+
+ if ((name = match_strval(aiminfo->subtype, aim_fnac_family_generic)) != NULL) {
+ if (ti) proto_item_append_text(ti, ", %s", name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, name);
+ }
+
+ switch(aiminfo->subtype)
+ {
+ case FAMILY_GENERIC_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, 0, gen_tree);
+ case FAMILY_GENERIC_CLIENTREADY:
+ ti = proto_tree_add_text(gen_tree, tvb, 0, tvb_length_remaining(tvb, 0), "Supported services");
+ entry = proto_item_add_subtree(ti, ett_generic_clientready);
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ guint16 famnum = tvb_get_ntohs(tvb, offset);
+ const char *famname = aim_get_familyname(famnum);
+ proto_tree *subentry;
+ ti = proto_tree_add_text(entry, tvb, offset, 2, "%s (0x%x)", famname?famname:"Unknown Family", famnum);
+ offset+=2;
+
+ subentry = proto_item_add_subtree(ti, ett_generic_clientready_item);
+
+ proto_tree_add_text(subentry, tvb, offset, 2, "Version: %d", tvb_get_ntohs(tvb, offset) ); offset += 2;
+ proto_tree_add_text(subentry, tvb, offset, 4, "DLL Version: %u", tvb_get_ntoh24(tvb, offset) ); offset += 4;
+ }
+ return offset;
+ case FAMILY_GENERIC_SERVERREADY:
+ ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Supported services");
+ entry = proto_item_add_subtree(ti, ett_generic_clientready);
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ guint16 famnum = tvb_get_ntohs(tvb, offset);
+ const char *famname = aim_get_familyname(famnum);
+ proto_tree_add_text(entry, tvb, offset, 2, "%s (0x%x)", famname?famname:"Unknown Family", famnum);
+ offset+=2;
+ }
+ return offset;
+ case FAMILY_GENERIC_SERVICEREQ:
+ name = aim_get_familyname( tvb_get_ntohs(tvb, offset) );
+ proto_tree_add_uint_format(gen_tree, hf_generic_servicereq_service, tvb, offset, 2, tvb_get_ntohs(tvb, offset), "%s (0x%04x)", name?name:"Unknown", tvb_get_ntohs(tvb, offset) );
+ offset+=2;
+ return offset;
+ case FAMILY_GENERIC_REDIRECT:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree, client_tlvs);
+ }
+ return offset;
+ case FAMILY_GENERIC_CAPABILITIES:
+ ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Requested services");
+ entry = proto_item_add_subtree(ti, ett_generic_clientready);
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ guint16 famnum = tvb_get_ntohs(tvb, offset);
+ const char *famname = aim_get_familyname(famnum);
+ ti = proto_tree_add_text(entry, tvb, offset, 4, "%s (0x%x), Version: %d", famname?famname:"Unknown Family", famnum, tvb_get_ntohs(tvb, offset+2));
+ offset += 4;
+ }
+ return offset;
+ case FAMILY_GENERIC_CAPACK:
+ ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Accepted requested services");
+ entry = proto_item_add_subtree(ti, ett_generic_clientready);
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ guint16 famnum = tvb_get_ntohs(tvb, offset);
+ const char *famname = aim_get_familyname(famnum);
+ ti = proto_tree_add_text(entry, tvb, offset, 4, "%s (0x%x), Version: %d", famname?famname:"Unknown Family", famnum, tvb_get_ntohs(tvb, offset+2));
+ offset += 4;
+ }
+ return offset;
+
+
+ case FAMILY_GENERIC_MOTD:
+ proto_tree_add_item(gen_tree, hf_generic_motd_motdtype, tvb, offset,
+ 2, tvb_get_ntohs(tvb, offset));
+ offset+=2;
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree, motd_tlvs);
+ }
+ return offset;
+
+ case FAMILY_GENERIC_RATEINFO:
+ return dissect_generic_rateinfo(tvb, pinfo, gen_tree);
+ case FAMILY_GENERIC_RATEINFOACK:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_uint(gen_tree, hf_generic_rateinfoack_group, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+ offset+=2;
+ }
+ return offset;
+ case FAMILY_GENERIC_RATECHANGE:
+ proto_tree_add_uint(gen_tree, hf_generic_ratechange_msg, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+ offset+=2;
+ offset = dissect_rate_class(tvb, pinfo, offset, gen_tree);
+ break;
+
+
+ case FAMILY_GENERIC_CLIENTPAUSEACK:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ guint16 famnum = tvb_get_ntohs(tvb, offset);
+ const char *famname = aim_get_familyname(famnum);
+ proto_tree_add_text(gen_tree, tvb, offset, 4, "Family: %s (0x%x)", famname?famname:"Unknown Family", famnum);
+ offset += 2;
+ }
+ return offset;
+ case FAMILY_GENERIC_SERVERRESUME:
+ case FAMILY_GENERIC_REQSELFINFO:
+ case FAMILY_GENERIC_NOP:
+ case FAMILY_GENERIC_SERVERPAUSE:
+ case FAMILY_GENERIC_RATEINFOREQ:
+ /* No data */
+ return offset;
+ case FAMILY_GENERIC_MIGRATIONREQ:
+ n = tvb_get_ntohs(tvb, offset);offset+=2;
+ proto_tree_add_uint(gen_tree, hf_generic_migration_numfams, tvb, offset, 2, n);
+ ti = proto_tree_add_text(gen_tree, tvb, offset, 2 * n, "Families to migrate");
+ entry = proto_item_add_subtree(ti, ett_generic_migratefamilies);
+ for(i = 0; i < n; i++) {
+ guint16 famnum = tvb_get_ntohs(tvb, offset);
+ const char *famname = aim_get_familyname(famnum);
+ proto_tree_add_text(gen_tree, tvb, offset, 4, "Family: %s (0x%x)", famname?famname:"Unknown Family", famnum);
+ offset += 2;
+ }
+
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree, client_tlvs);
+ }
+
+ return offset;
+ case FAMILY_GENERIC_SETPRIVFLAGS:
+ {
+ guint32 flags = tvb_get_ntoh24(tvb, offset);
+ ti = proto_tree_add_uint(gen_tree, hf_generic_priv_flags, tvb, offset, 4, flags);
+ entry = proto_item_add_subtree(ti, ett_generic_priv_flags);
+ proto_tree_add_boolean(entry, hf_generic_allow_idle_see, tvb, offset, 4, flags);
+ proto_tree_add_boolean(entry, hf_generic_allow_member_see, tvb, offset, 4, flags);
+ offset+=4;
+ }
+ return offset;
+ case FAMILY_GENERIC_SELFINFO:
+ offset = dissect_aim_buddyname(tvb, pinfo, offset, gen_tree);
+ proto_tree_add_item(gen_tree, hf_generic_selfinfo_warninglevel, tvb, offset, 2, FALSE);
+ offset += 2;
+ return dissect_aim_tlv_list(tvb, pinfo, offset, gen_tree, onlinebuddy_tlvs);
+ case FAMILY_GENERIC_EVIL:
+ proto_tree_add_item(gen_tree, hf_generic_evil_new_warn_level, tvb, offset, 2, FALSE);
+ while(tvb_length_remaining(tvb, offset)) {
+ offset = dissect_aim_userinfo(tvb, pinfo, offset, gen_tree);
+ }
+ return offset;
+ case FAMILY_GENERIC_SETIDLE:
+ proto_tree_add_item(gen_tree, hf_generic_idle_time, tvb, offset, 2, FALSE);
+ return 4;
+ case FAMILY_GENERIC_SETSTATUS:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree, onlinebuddy_tlvs);
+ }
+ return offset;
+ case FAMILY_GENERIC_CLIENTVERREQ:
+ proto_tree_add_item(gen_tree, hf_generic_client_ver_req_offset, tvb, offset, 4, FALSE);
+ offset+=4;
+ proto_tree_add_item(gen_tree, hf_generic_client_ver_req_length, tvb, offset, 4, FALSE);
+ return offset+4;
+ case FAMILY_GENERIC_CLIENTVERREPL:
+ proto_tree_add_item(gen_tree, hf_generic_client_ver_req_hash, tvb, offset, 16, FALSE);
+ return 16;
+ case FAMILY_GENERIC_WELLKNOWNURL:
+ /* FIXME */
+ return 0;
+ default: return 0;
+ }
+ return 0;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_generic(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_generic_servicereq_service,
+ { "Requested Service", "generic.servicereq.service", FT_UINT16,
+ BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_motd_motdtype,
+ { "MOTD Type", "generic.motd.motdtype", FT_UINT16,
+ BASE_HEX, VALS(aim_snac_generic_motd_motdtypes), 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_numclasses,
+ { "Number of Rateinfo Classes", "aim.rateinfo.numclasses", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_windowsize,
+ { "Window Size", "aim.rateinfo.class.window_size", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_clearlevel,
+ { "Clear Level", "aim.rateinfo.class.clearlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_alertlevel,
+ { "Alert Level", "aim.rateinfo.class.alertlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_limitlevel,
+ { "Limit Level", "aim.rateinfo.class.limitlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_disconnectlevel,
+ { "Disconnect Level", "aim.rateinfo.class.disconnectlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_currentlevel,
+ { "Current Level", "aim.rateinfo.class.currentlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_maxlevel,
+ { "Max Level", "aim.rateinfo.class.maxlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_lasttime,
+ { "Last Time", "aim.rateinfo.class.lasttime", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_curstate,
+ { "Current State", "aim.rateinfo.class.curstate", FT_UINT8, BASE_HEX, VALS(rateinfo_states), 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_classid,
+ { "Class ID", "aim.rateinfo.class.id", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfo_numpairs,
+ { "Number of Family/Subtype pairs", "aim.rateinfo.class.numpairs", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_rateinfoack_group,
+ { "Acknowledged Rate Class", "aim.rateinfoack.class", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_ratechange_msg,
+ { "Rate Change Message", "aim.ratechange.msg", FT_UINT16, BASE_HEX, VALS(ratechange_msgs), 0x0, "", HFILL },
+ },
+ { &hf_generic_migration_numfams,
+ { "Number of families to migrate", "aim.migrate.numfams", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_priv_flags,
+ { "Privilege flags", "aim.privilege_flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_allow_idle_see,
+ { "Allow other users to see idle time", "aim.privilege_flags.allow_idle", FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x0001, "", HFILL },
+ },
+ { &hf_generic_allow_member_see,
+ { "Allow other users to see how long account has been a member", "aim.privilege_flags.allow_member", FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x0002, "", HFILL },
+ },
+ { &hf_generic_selfinfo_warninglevel,
+ { "Warning level", "aim.selfinfo.warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_evil_new_warn_level,
+ { "New warning level", "aim.evil.new_warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_idle_time,
+ { "Idle time (seconds)", "aim.idle_time", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_client_ver_req_offset,
+ { "Client Verification Request Offset", "aim.client_verification.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_client_ver_req_length,
+ { "Client Verification Request Length", "aim.client_verification.length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_generic_client_ver_req_hash,
+ { "Client Verification MD5 Hash", "aim.client_verification.hash", FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_generic,
+ &ett_generic_migratefamilies,
+ &ett_generic_rateinfo_class,
+ &ett_generic_rateinfo_group,
+ &ett_generic_rateinfo_groups,
+ &ett_generic_rateinfo_classes,
+ &ett_generic_clientready,
+ &ett_generic_clientready_item,
+ &ett_generic_serverready,
+ &ett_generic_priv_flags,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_generic = proto_register_protocol("AIM Generic Service", "AIM Generic", "aim_generic");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim_generic, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_generic(void)
+{
+ dissector_handle_t aim_handle;
+ aim_handle = new_create_dissector_handle(dissect_aim_snac_generic, proto_aim_generic);
+ dissector_add("aim.family", FAMILY_GENERIC, aim_handle);
+ aim_init_family(FAMILY_GENERIC, "Generic", aim_fnac_family_generic);
+}
diff --git a/epan/dissectors/packet-aim-icq.c b/epan/dissectors/packet-aim-icq.c
new file mode 100644
index 0000000000..6fc357b2cd
--- /dev/null
+++ b/epan/dissectors/packet-aim-icq.c
@@ -0,0 +1,130 @@
+/* packet-aim-icq.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC ICQ
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_ICQ 0x0015
+
+/* Family ICQ */
+#define FAMILY_ICQ_ERROR 0x0001
+#define FAMILY_ICQ_LOGINREQUEST 0x0002
+#define FAMILY_ICQ_LOGINRESPONSE 0x0003
+#define FAMILY_ICQ_AUTHREQUEST 0x0006
+#define FAMILY_ICQ_AUTHRESPONSE 0x0007
+
+static const value_string aim_fnac_family_icq[] = {
+ { FAMILY_ICQ_ERROR, "Error" },
+ { FAMILY_ICQ_LOGINREQUEST, "Login Request" },
+ { FAMILY_ICQ_LOGINRESPONSE, "Login Response" },
+ { FAMILY_ICQ_AUTHREQUEST, "Auth Request" },
+ { FAMILY_ICQ_AUTHRESPONSE, "Auth Response" },
+ { 0, NULL }
+};
+
+int dissect_aim_tlv_value_icq(proto_item *ti, guint16, tvbuff_t *);
+
+#define TLV_ICQ_META_DATA 0x0001
+
+static const aim_tlv icq_tlv[] = {
+ { TLV_ICQ_META_DATA, "Encapsulated ICQ Meta Data", dissect_aim_tlv_value_icq },
+ { 0, "Unknown", NULL },
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_icq = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_icq = -1;
+
+int dissect_aim_tlv_value_icq(proto_item *ti _U_, guint16 subtype _U_, tvbuff_t *tvb _U_)
+{
+ /* FIXME */
+ return 0;
+}
+
+static int dissect_aim_icq(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ struct aiminfo *aiminfo = pinfo->private_data;
+ int offset = 0;
+ switch(aiminfo->subtype) {
+ case FAMILY_ICQ_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, tree);
+ case FAMILY_ICQ_LOGINREQUEST:
+ return dissect_aim_tlv(tvb, pinfo, offset, tree, icq_tlv);
+ case FAMILY_ICQ_LOGINRESPONSE:
+ case FAMILY_ICQ_AUTHREQUEST:
+ case FAMILY_ICQ_AUTHRESPONSE:
+ /* FIXME */
+ default:
+ return 0;
+ }
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_icq(void)
+{
+
+/* Setup list of header fields */
+/* static hf_register_info hf[] = {
+ };*/
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_icq,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_icq = proto_register_protocol("AIM ICQ", "AIM ICQ", "aim_icq");
+
+/* Required function calls to register the header fields and subtrees used */
+ /*proto_register_field_array(proto_aim_icq, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_icq(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim_icq, proto_aim_icq);
+ dissector_add("aim.family", FAMILY_ICQ, aim_handle);
+ aim_init_family(FAMILY_ICQ, "ICQ", aim_fnac_family_icq);
+}
diff --git a/epan/dissectors/packet-aim-invitation.c b/epan/dissectors/packet-aim-invitation.c
new file mode 100644
index 0000000000..26b468d317
--- /dev/null
+++ b/epan/dissectors/packet-aim-invitation.c
@@ -0,0 +1,116 @@
+/* packet-aim-invitation.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Invitation
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_INVITATION 0x0006
+
+/* Family Invitation */
+#define FAMILY_INVITATION_ERROR 0x0001
+#define FAMILY_INVITATION_FRIEND_REQ 0x0002
+#define FAMILY_INVITATION_FRIEND_REPL 0x0003
+#define FAMILY_INVITATION_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_invitation[] = {
+ { FAMILY_INVITATION_ERROR, "Error" },
+ { FAMILY_INVITATION_FRIEND_REQ, "Invite a friend to join AIM" },
+ { FAMILY_INVITATION_FRIEND_REPL, "Invitation Ack" },
+ { FAMILY_INVITATION_DEFAULT, "Invitation Default" },
+ { 0, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_invitation = -1;
+
+static int ett_aim_invitation = -1;
+
+static int dissect_aim_invitation(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ int offset = 0;
+ struct aiminfo *aiminfo = pinfo->private_data;
+ proto_item *ti = NULL;
+ proto_tree *invite_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Invite Service");
+ invite_tree = proto_item_add_subtree(ti, ett_aim_invitation);
+ }
+
+ switch(aiminfo->subtype) {
+ case FAMILY_INVITATION_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, invite_tree);
+ case FAMILY_INVITATION_FRIEND_REQ:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, invite_tree, onlinebuddy_tlvs);
+ }
+ return 0;
+ case FAMILY_INVITATION_FRIEND_REPL:
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_invitation(void)
+{
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_invitation,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_invitation = proto_register_protocol("AIM Invitation Service", "AIM Invitation", "aim_invitation");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_invitation(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim_invitation, proto_aim_invitation);
+ dissector_add("aim.family", FAMILY_INVITATION, aim_handle);
+ aim_init_family(FAMILY_INVITATION, "Invitation", aim_fnac_family_invitation);
+}
diff --git a/epan/dissectors/packet-aim-location.c b/epan/dissectors/packet-aim-location.c
new file mode 100644
index 0000000000..44da9d81a5
--- /dev/null
+++ b/epan/dissectors/packet-aim-location.c
@@ -0,0 +1,259 @@
+/* packet-aim-location.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Location
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ * Copyright 2000, Ralf Hoelzer <ralf@well.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+/* SNAC families */
+#define FAMILY_LOCATION 0x0002
+
+/* Family Location Services */
+#define FAMILY_LOCATION_ERROR 0x0001
+#define FAMILY_LOCATION_REQRIGHTS 0x0002
+#define FAMILY_LOCATION_RIGHTSINFO 0x0003
+#define FAMILY_LOCATION_SETUSERINFO 0x0004
+#define FAMILY_LOCATION_REQUSERINFO 0x0005
+#define FAMILY_LOCATION_USERINFO 0x0006
+#define FAMILY_LOCATION_WATCHERSUBREQ 0x0007
+#define FAMILY_LOCATION_WATCHERNOT 0x0008
+#define FAMILY_LOCATION_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_location[] = {
+ { FAMILY_LOCATION_ERROR, "Error" },
+ { FAMILY_LOCATION_REQRIGHTS, "Request Rights" },
+ { FAMILY_LOCATION_RIGHTSINFO, "Rights Info" },
+ { FAMILY_LOCATION_SETUSERINFO, "Set User Info" },
+ { FAMILY_LOCATION_REQUSERINFO, "Request User Info" },
+ { FAMILY_LOCATION_USERINFO, "User Info" },
+ { FAMILY_LOCATION_WATCHERSUBREQ, "Watcher Subrequest" },
+ { FAMILY_LOCATION_WATCHERNOT, "Watcher Notification" },
+ { FAMILY_LOCATION_DEFAULT, "Location Default" },
+ { 0, NULL }
+};
+
+#define FAMILY_LOCATION_USERINFO_INFOENCODING 0x0001
+#define FAMILY_LOCATION_USERINFO_INFOMSG 0x0002
+#define FAMILY_LOCATION_USERINFO_AWAYENCODING 0x0003
+#define FAMILY_LOCATION_USERINFO_AWAYMSG 0x0004
+#define FAMILY_LOCATION_USERINFO_CAPS 0x0005
+
+static const aim_tlv msg_tlv[] = {
+ { FAMILY_LOCATION_USERINFO_INFOENCODING, "Info Msg Encoding", dissect_aim_tlv_value_string},
+ { FAMILY_LOCATION_USERINFO_INFOMSG, "Info Message", dissect_aim_tlv_value_string },
+ { FAMILY_LOCATION_USERINFO_AWAYENCODING, "Away Msg Encoding", dissect_aim_tlv_value_string },
+ { FAMILY_LOCATION_USERINFO_AWAYMSG, "Away Message", dissect_aim_tlv_value_string },
+ { FAMILY_LOCATION_USERINFO_CAPS, "Capabilities", dissect_aim_tlv_value_bytes },
+ { 0, "Unknown", 0 }
+};
+
+#define AIM_LOCATION_RIGHTS_TLV_MAX_PROFILE_LENGTH 0x0001
+#define AIM_LOCATION_RIGHTS_TLV_MAX_CAPABILITIES 0x0002
+#define AIM_LOCATION_RIGHTS_TLV_CLIENT_CAPABILITIES 0x0005
+
+static const aim_tlv location_rights_tlvs[] = {
+ { AIM_LOCATION_RIGHTS_TLV_MAX_PROFILE_LENGTH, "Max Profile Length", dissect_aim_tlv_value_uint16 },
+ { AIM_LOCATION_RIGHTS_TLV_MAX_CAPABILITIES, "Max capabilities", dissect_aim_tlv_value_uint16 },
+ { AIM_LOCATION_RIGHTS_TLV_CLIENT_CAPABILITIES, "Client capabilities", dissect_aim_tlv_value_client_capabilities },
+ { 0, "Unknown", NULL }
+};
+
+#define FAMILY_LOCATION_USERINFO_INFOTYPE_GENERALINFO 0x0001
+#define FAMILY_LOCATION_USERINFO_INFOTYPE_AWAYMSG 0x0003
+#define FAMILY_LOCATION_USERINFO_INFOTYPE_CAPS 0x0005
+
+static const value_string aim_snac_location_request_user_info_infotypes[] = {
+ { FAMILY_LOCATION_USERINFO_INFOTYPE_GENERALINFO, "Request General Info" },
+ { FAMILY_LOCATION_USERINFO_INFOTYPE_AWAYMSG, "Request Away Message" },
+ { FAMILY_LOCATION_USERINFO_INFOTYPE_CAPS, "Request Capabilities" },
+ { 0, NULL }
+};
+
+static int dissect_aim_snac_location_request_user_information(tvbuff_t *tvb, int offset, proto_tree *tree);
+static int dissect_aim_snac_location_user_information(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_location = -1;
+static int hf_aim_snac_location_request_user_info_infotype = -1;
+static int hf_aim_userinfo_warninglevel = -1;
+static int hf_aim_buddyname_len = -1;
+static int hf_aim_buddyname = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_location = -1;
+
+static int dissect_aim_location(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree )
+{
+ struct aiminfo *aiminfo = pinfo->private_data;
+ int offset = 0;
+ proto_item *ti = NULL;
+ proto_tree *loc_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Location Service");
+ loc_tree = proto_item_add_subtree(ti, ett_aim_location);
+ }
+
+ switch(aiminfo->subtype)
+ {
+ case FAMILY_LOCATION_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, loc_tree);
+ case FAMILY_LOCATION_REQUSERINFO:
+ return dissect_aim_snac_location_request_user_information(tvb, offset, loc_tree);
+ case FAMILY_LOCATION_USERINFO:
+ return dissect_aim_snac_location_user_information(tvb, pinfo, offset, loc_tree);
+ case FAMILY_LOCATION_REQRIGHTS:
+ /* No data */
+ return 0;
+ case FAMILY_LOCATION_RIGHTSINFO:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, loc_tree, location_rights_tlvs);
+ }
+ return 0;
+ case FAMILY_LOCATION_SETUSERINFO:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, loc_tree, location_rights_tlvs);
+ }
+ return 0;
+ case FAMILY_LOCATION_WATCHERSUBREQ:
+ /* FIXME */
+ return 0;
+ case FAMILY_LOCATION_WATCHERNOT:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_buddyname(tvb, pinfo, offset, loc_tree);
+ }
+ return offset;
+ default:
+ return 0;
+ }
+}
+
+static int dissect_aim_snac_location_request_user_information(tvbuff_t *tvb,
+ int offset,
+ proto_tree *tree)
+{
+ guint8 buddyname_length = 0;
+
+ /* Info Type */
+ proto_tree_add_item(tree, hf_aim_snac_location_request_user_info_infotype,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* Buddy Name length */
+ buddyname_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_aim_buddyname_len, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* Buddy name */
+ proto_tree_add_item(tree, hf_aim_buddyname, tvb, offset, buddyname_length, FALSE);
+ offset += buddyname_length;
+
+ return offset;
+}
+
+static int dissect_aim_snac_location_user_information(tvbuff_t *tvb,
+ packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ guint8 buddyname_length = 0;
+
+ /* Buddy Name length */
+ buddyname_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_aim_buddyname_len, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* Buddy name */
+ proto_tree_add_item(tree, hf_aim_buddyname, tvb, offset, buddyname_length, FALSE);
+ offset += buddyname_length;
+
+ /* Warning level */
+ proto_tree_add_item(tree, hf_aim_userinfo_warninglevel, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ offset = dissect_aim_tlv_list(tvb, pinfo, offset, tree, onlinebuddy_tlvs);
+
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, tree, msg_tlv);
+ }
+
+ return offset;
+}
+
+void
+proto_register_aim_location(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_aim_buddyname_len,
+ { "Buddyname len", "aim.buddynamelen", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_buddyname,
+ { "Buddy Name", "aim.buddyname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_userinfo_warninglevel,
+ { "Warning Level", "aim.userinfo.warninglevel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_snac_location_request_user_info_infotype,
+ { "Infotype", "aim.snac.location.request_user_info.infotype", FT_UINT16, BASE_HEX, VALS(aim_snac_location_request_user_info_infotypes), 0x0,
+ "", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_location,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_location = proto_register_protocol("AIM Location", "AIM Location", "aim_location");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim_location, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_location(void)
+{
+ dissector_handle_t aim_handle;
+ aim_handle = new_create_dissector_handle(dissect_aim_location, proto_aim_location);
+ dissector_add("aim.family", FAMILY_LOCATION, aim_handle);
+ aim_init_family(FAMILY_LOCATION, "Location", aim_fnac_family_location);
+}
diff --git a/epan/dissectors/packet-aim-messaging.c b/epan/dissectors/packet-aim-messaging.c
new file mode 100644
index 0000000000..15522ea6c9
--- /dev/null
+++ b/epan/dissectors/packet-aim-messaging.c
@@ -0,0 +1,323 @@
+/* packet-aim-messaging.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Messaging
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ * Copyright 2000, Ralf Hoelzer <ralf@well.com>
+ * Copyright 2004, Devin Heitmueller <dheitmueller@netilla.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_MESSAGING 0x0004
+
+/* Family Messaging Service */
+#define FAMILY_MESSAGING_ERROR 0x0001
+#define FAMILY_MESSAGING_SETICBMPARAM 0x0002
+#define FAMILY_MESSAGING_RESETICBMPARAM 0x0003
+#define FAMILY_MESSAGING_REQPARAMINFO 0x0004
+#define FAMILY_MESSAGING_PARAMINFO 0x0005
+#define FAMILY_MESSAGING_OUTGOING 0x0006
+#define FAMILY_MESSAGING_INCOMING 0x0007
+#define FAMILY_MESSAGING_EVILREQ 0x0008
+#define FAMILY_MESSAGING_EVIL 0x0009
+#define FAMILY_MESSAGING_MISSEDCALL 0x000a
+#define FAMILY_MESSAGING_CLIENTAUTORESP 0x000b
+#define FAMILY_MESSAGING_ACK 0x000c
+#define FAMILY_MESSAGING_MINITYPING 0x0014
+#define FAMILY_MESSAGING_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_messaging[] = {
+ { FAMILY_MESSAGING_ERROR, "Error" },
+ { FAMILY_MESSAGING_SETICBMPARAM, "Set ICBM Parameter" },
+ { FAMILY_MESSAGING_RESETICBMPARAM, "Reset ICBM Parameter" },
+ { FAMILY_MESSAGING_REQPARAMINFO, "Request Parameter Info" },
+ { FAMILY_MESSAGING_PARAMINFO, "Parameter Info" },
+ { FAMILY_MESSAGING_INCOMING, "Incoming" },
+ { FAMILY_MESSAGING_OUTGOING, "Outgoing" },
+ { FAMILY_MESSAGING_EVILREQ, "Evil Request" },
+ { FAMILY_MESSAGING_EVIL, "Evil Response" },
+ { FAMILY_MESSAGING_MISSEDCALL, "Missed Call" },
+ { FAMILY_MESSAGING_CLIENTAUTORESP, "Client Auto Response" },
+ { FAMILY_MESSAGING_ACK, "Acknowledge" },
+ { FAMILY_MESSAGING_MINITYPING, "Mini Typing Notifications (MTN)" },
+ { FAMILY_MESSAGING_DEFAULT, "Messaging Default" },
+ { 0, NULL }
+};
+
+
+#define INCOMING_CH1_MESSAGE_BLOCK 0x0002
+#define INCOMING_CH1_SERVER_ACK_REQ 0x0003
+#define INCOMING_CH1_MESSAGE_AUTH_RESP 0x0004
+#define INCOMING_CH1_MESSAGE_OFFLINE 0x0006
+#define INCOMING_CH1_ICON_PRESENT 0x0008
+#define INCOMING_CH1_BUDDY_REQ 0x0009
+#define INCOMING_CH1_TYPING 0x000b
+
+static const aim_tlv messaging_incoming_ch1_tlvs[] = {
+ { INCOMING_CH1_MESSAGE_BLOCK, "Message Block", dissect_aim_tlv_value_messageblock },
+ { INCOMING_CH1_SERVER_ACK_REQ, "Server Ack Requested", dissect_aim_tlv_value_bytes },
+ { INCOMING_CH1_MESSAGE_AUTH_RESP, "Message is Auto Response", dissect_aim_tlv_value_bytes },
+ { INCOMING_CH1_MESSAGE_OFFLINE, "Message was received offline", dissect_aim_tlv_value_bytes },
+ { INCOMING_CH1_ICON_PRESENT, "Icon present", dissect_aim_tlv_value_bytes },
+ { INCOMING_CH1_BUDDY_REQ, "Buddy Req", dissect_aim_tlv_value_bytes },
+ { INCOMING_CH1_TYPING, "Non-direct connect typing notification", dissect_aim_tlv_value_bytes },
+ { 0, "Unknown", NULL }
+};
+
+#define MINITYPING_FINISHED_SIGN 0x0000
+#define MINITYPING_TEXT_TYPED_SIGN 0x0001
+#define MINITYPING_BEGUN_SIGN 0x0002
+
+static const value_string minityping_type[] = {
+ {MINITYPING_FINISHED_SIGN, "Typing finished sign" },
+ {MINITYPING_TEXT_TYPED_SIGN, "Text typed sign" },
+ {MINITYPING_BEGUN_SIGN, "Typing begun sign" },
+ {0, NULL }
+};
+
+#define EVIL_ORIGIN_ANONYMOUS 1
+#define EVIL_ORIGIN_NONANONYMOUS 2
+
+static const value_string evil_origins[] = {
+ {EVIL_ORIGIN_ANONYMOUS, "Anonymous"},
+ {EVIL_ORIGIN_NONANONYMOUS, "Non-Anonymous"},
+ {0, NULL },
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_messaging = -1;
+static int hf_aim_icbm_channel = -1;
+static int hf_aim_icbm_cookie = -1;
+static int hf_aim_icbm_msg_flags = -1;
+static int hf_aim_icbm_max_sender_warnlevel = -1;
+static int hf_aim_icbm_max_receiver_warnlevel = -1;
+static int hf_aim_icbm_max_snac_size = -1;
+static int hf_aim_icbm_min_msg_interval = -1;
+static int hf_aim_icbm_unknown = -1;
+static int hf_aim_icbm_notification_cookie = -1;
+static int hf_aim_icbm_notification_channel = -1;
+static int hf_aim_icbm_notification_type = -1;
+static int hf_aim_message_channel_id = -1;
+static int hf_aim_icbm_evil = -1;
+static int hf_aim_evil_warn_level = -1;
+static int hf_aim_evil_new_warn_level = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_messaging = -1;
+
+static int dissect_aim_messaging(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint8 buddyname_length = 0;
+ char buddyname[MAX_BUDDYNAME_LENGTH + 1];
+ int offset = 0;
+ struct aiminfo *aiminfo = pinfo->private_data;
+ proto_item *ti = NULL;
+ proto_tree *msg_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Messaging Service");
+ msg_tree = proto_item_add_subtree(ti, ett_aim_messaging);
+ }
+
+ switch(aiminfo->subtype)
+ {
+ case FAMILY_MESSAGING_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, msg_tree);
+ case FAMILY_MESSAGING_RESETICBMPARAM:
+ case FAMILY_MESSAGING_REQPARAMINFO:
+ /* No data */
+ return 0;
+ case FAMILY_MESSAGING_OUTGOING:
+
+ /* ICBM Cookie */
+ proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* Message Channel ID */
+ proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ /* Add the outgoing username to the info column */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ buddyname_length = aim_get_buddyname(buddyname, tvb, offset,
+ offset + 1);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " to: %s",
+ format_text(buddyname, buddyname_length));
+ }
+
+ offset = dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
+
+ while(tvb_reported_length_remaining(tvb, offset) > 0) {
+ /* djh - Note that we reuse the "incoming ch1 tlv" set even though this
+ is outgoing. We may need to split this to a separate TLV set, but
+ so far I haven't seen the need @@@@@@@@ */
+ offset = dissect_aim_tlv(tvb, pinfo, offset, msg_tree,
+ messaging_incoming_ch1_tlvs);
+ }
+
+ return offset;
+
+ case FAMILY_MESSAGING_INCOMING:
+
+ /* ICBM Cookie */
+ proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* Message Channel ID */
+ proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ offset = dissect_aim_userinfo(tvb, pinfo, offset, msg_tree);
+
+ while(tvb_reported_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, msg_tree,
+ messaging_incoming_ch1_tlvs);
+ }
+
+ return offset;
+ case FAMILY_MESSAGING_SETICBMPARAM:
+ case FAMILY_MESSAGING_PARAMINFO:
+ proto_tree_add_item(msg_tree, hf_aim_icbm_channel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ proto_tree_add_item(msg_tree, hf_aim_icbm_msg_flags, tvb, offset, 4, tvb_get_ntoh24(tvb, offset)); offset+=4;
+ proto_tree_add_item(msg_tree, hf_aim_icbm_max_snac_size, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ proto_tree_add_item(msg_tree, hf_aim_icbm_max_sender_warnlevel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ proto_tree_add_item(msg_tree, hf_aim_icbm_max_receiver_warnlevel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ proto_tree_add_item(msg_tree, hf_aim_icbm_min_msg_interval, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ proto_tree_add_item(msg_tree, hf_aim_icbm_unknown, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ return offset;
+ case FAMILY_MESSAGING_EVILREQ:
+ proto_tree_add_item(msg_tree, hf_aim_icbm_evil, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ return dissect_aim_buddyname(tvb, pinfo, offset, tree);
+ case FAMILY_MESSAGING_EVIL:
+ proto_tree_add_item(msg_tree, hf_aim_evil_warn_level, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ proto_tree_add_item(msg_tree, hf_aim_evil_new_warn_level, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ return offset;
+ case FAMILY_MESSAGING_MINITYPING:
+ proto_tree_add_item(msg_tree,hf_aim_icbm_notification_cookie, tvb, offset, 8, FALSE); offset+=8;
+ proto_tree_add_item(msg_tree,hf_aim_icbm_notification_channel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ offset = dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
+ proto_tree_add_item(msg_tree,hf_aim_icbm_notification_type, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+ return offset;
+ case FAMILY_MESSAGING_MISSEDCALL:
+ case FAMILY_MESSAGING_CLIENTAUTORESP:
+ case FAMILY_MESSAGING_ACK:
+ /*FIXME*/
+
+
+ default:
+ return 0;
+ }
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_messaging(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_aim_icbm_channel,
+ { "Channel to setup", "aim.icbm.channel", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_msg_flags,
+ { "Message Flags", "aim.icbm.flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_max_snac_size,
+ { "Max SNAC Size", "aim.icbm.max_snac", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_max_sender_warnlevel,
+ { "Max sender warn level", "aim.icbm.max_sender_warn-level", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_max_receiver_warnlevel,
+ { "max receiver warn level", "aim.icbm.max_receiver_warnlevel", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_min_msg_interval,
+ { "Minimum message interval (seconds)", "aim.icbm.min_msg_interval", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_unknown,
+ { "Unknown parameter", "aim.icbm.unknown", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_cookie,
+ { "ICBM Cookie", "aim.messaging.icbmcookie", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_message_channel_id,
+ { "Message Channel ID", "aim.messaging.channelid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_icbm_evil,
+ { "Send Evil Bit As", "aim.evilreq.origin", FT_UINT16, BASE_DEC, VALS(evil_origins), 0x0, "", HFILL },
+ },
+ { &hf_aim_evil_warn_level,
+ { "Old warning level", "aim.evil.warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_evil_new_warn_level,
+ { "New warning level", "aim.evil.new_warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_notification_cookie,
+ { "Notification Cookie", "aim.notification.cookie", FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_notification_channel,
+ { "Notification Channel", "aim.notification.channel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_icbm_notification_type,
+ { "Notification Type", "aim.notification.type", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_messaging,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_messaging = proto_register_protocol("AIM Messaging", "AIM Messaging", "aim_messaging");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim_messaging, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_messaging(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim_messaging, proto_aim_messaging);
+ dissector_add("aim.family", FAMILY_MESSAGING, aim_handle);
+ aim_init_family(FAMILY_MESSAGING, "Messaging", aim_fnac_family_messaging);
+}
diff --git a/epan/dissectors/packet-aim-oft.c b/epan/dissectors/packet-aim-oft.c
new file mode 100644
index 0000000000..a4c8ded9f0
--- /dev/null
+++ b/epan/dissectors/packet-aim-oft.c
@@ -0,0 +1,77 @@
+/* packet-aim.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+/* SNAC families */
+#define FAMILY_OFT 0xfffe
+
+static int proto_aim_oft = -1;
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_oft(void)
+{
+
+/* Setup list of header fields */
+/* static hf_register_info hf[] = {
+ };*/
+
+/* Setup protocol subtree array */
+/* static gint *ett[] = {
+ };*/
+
+/* Register the protocol name and description */
+ proto_aim_oft = proto_register_protocol("AIM OFT", "AIM OFT", "aim_oft");
+
+/* Required function calls to register the header fields and subtrees used */
+/* proto_register_field_array(proto_aim_oft, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));*/
+}
+
+void
+proto_reg_handoff_aim_oft(void)
+{
+/* dissector_handle_t aim_handle;*/
+
+ /* FIXME
+ aim_handle = new_create_dissector_handle(dissect_aim, proto_aim);
+ dissector_add("tcp.port", TCP_PORT_AIM, aim_handle);*/
+}
diff --git a/epan/dissectors/packet-aim-popup.c b/epan/dissectors/packet-aim-popup.c
new file mode 100644
index 0000000000..8aad38fd25
--- /dev/null
+++ b/epan/dissectors/packet-aim-popup.c
@@ -0,0 +1,125 @@
+/* packet-aim.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+/* SNAC families */
+#define FAMILY_POPUP 0x0008
+
+/* Family Popup */
+#define FAMILY_POPUP_ERROR 0x0001
+#define FAMILY_POPUP_COMMAND 0x0002
+#define FAMILY_POPUP_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_popup[] = {
+ { FAMILY_POPUP_ERROR, "Error" },
+ { FAMILY_POPUP_COMMAND, "Display Popup Message Server Command" },
+ { FAMILY_POPUP_DEFAULT, "Popup Default" },
+ { 0, NULL }
+};
+
+#define AIM_POPUP_TLV_MESSAGE_TEXT 0x001
+#define AIM_POPUP_TLV_URL_STRING 0x002
+#define AIM_POPUP_TLV_WINDOW_WIDTH 0x003
+#define AIM_POPUP_TLV_WINDOW_HEIGHT 0x004
+#define AIM_POPUP_TLV_AUTOHIDE_DELAY 0x005
+
+const aim_tlv popup_tlvs[] = {
+ { AIM_POPUP_TLV_MESSAGE_TEXT, "Message text (html)", dissect_aim_tlv_value_string },
+ { AIM_POPUP_TLV_URL_STRING, "URL string", dissect_aim_tlv_value_string },
+ { AIM_POPUP_TLV_WINDOW_WIDTH, "Window Width (pixels)", dissect_aim_tlv_value_uint16 },
+ { AIM_POPUP_TLV_WINDOW_HEIGHT, "Window Height (pixels)", dissect_aim_tlv_value_uint16 },
+ { AIM_POPUP_TLV_AUTOHIDE_DELAY, "Autohide delay (seconds)", dissect_aim_tlv_value_uint16 },
+ { 0, NULL, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_popup = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_popup = -1;
+
+static int dissect_aim_snac_popup(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ int offset = 0;
+ struct aiminfo *aiminfo = pinfo->private_data;
+ proto_item *ti = NULL;
+ proto_tree *popup_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Popup Service");
+ popup_tree = proto_item_add_subtree(ti, ett_aim_popup);
+ }
+
+ switch(aiminfo->subtype) {
+ case FAMILY_POPUP_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, 0, popup_tree);
+ case FAMILY_POPUP_COMMAND:
+ return dissect_aim_tlv(tvb, pinfo, offset, popup_tree, popup_tlvs);
+ }
+
+ return 0;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_popup(void)
+{
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_popup,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_popup = proto_register_protocol("AIM Popup", "AIM Popup", "aim_popup");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_popup(void)
+{
+ dissector_handle_t aim_handle;
+ aim_handle = new_create_dissector_handle(dissect_aim_snac_popup, proto_aim_popup);
+ dissector_add("aim.family", FAMILY_POPUP, aim_handle);
+ aim_init_family(FAMILY_POPUP, "Popup", aim_fnac_family_popup);
+}
diff --git a/epan/dissectors/packet-aim-signon.c b/epan/dissectors/packet-aim-signon.c
new file mode 100644
index 0000000000..e068de9e0f
--- /dev/null
+++ b/epan/dissectors/packet-aim-signon.c
@@ -0,0 +1,234 @@
+/* packet-aim-signon.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Signon
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ * Copyright 2000, Ralf Hoelzer <ralf@well.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_SIGNON 0x0017
+
+/* Family Signon */
+#define FAMILY_SIGNON_ERROR 0x0001
+#define FAMILY_SIGNON_LOGON 0x0002
+#define FAMILY_SIGNON_LOGON_REPLY 0x0003
+#define FAMILY_SIGNON_UIN_REQ 0x0004
+#define FAMILY_SIGNON_UIN_REPL 0x0005
+#define FAMILY_SIGNON_SIGNON 0x0006
+#define FAMILY_SIGNON_SIGNON_REPLY 0x0007
+#define FAMILY_SIGNON_S_SECUREID_REQ 0x000a
+#define FAMILY_SIGNON_C_SECUREID_REP 0x000b
+
+static const value_string aim_fnac_family_signon[] = {
+ { FAMILY_SIGNON_LOGON, "Logon" },
+ { FAMILY_SIGNON_LOGON_REPLY, "Logon Reply" },
+ { FAMILY_SIGNON_UIN_REQ, "Request UIN" },
+ { FAMILY_SIGNON_UIN_REPL, "New UIN response" },
+ { FAMILY_SIGNON_SIGNON, "Sign-on" },
+ { FAMILY_SIGNON_SIGNON_REPLY, "Sign-on Reply" },
+ { FAMILY_SIGNON_S_SECUREID_REQ, "Server SecureID Request" },
+ { FAMILY_SIGNON_C_SECUREID_REP, "Client SecureID Reply" },
+ { 0, NULL }
+};
+
+static int dissect_aim_snac_signon(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree);
+static int dissect_aim_snac_signon_logon(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
+static int dissect_aim_snac_signon_logon_reply(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
+static int dissect_aim_snac_signon_signon(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
+static int dissect_aim_snac_signon_signon_reply(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_signon = -1;
+static int hf_aim_infotype = -1;
+static int hf_aim_signon_challenge_len = -1;
+static int hf_aim_signon_challenge = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_aim_signon = -1;
+
+static int dissect_aim_snac_signon(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ struct aiminfo *aiminfo = pinfo->private_data;
+ int offset = 0;
+
+ proto_item *ti = NULL;
+ proto_tree *signon_tree = NULL;
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Signon");
+ signon_tree = proto_item_add_subtree(ti, ett_aim_signon);
+ }
+
+ switch(aiminfo->subtype)
+ {
+ case FAMILY_SIGNON_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, signon_tree);
+ case FAMILY_SIGNON_LOGON:
+ return dissect_aim_snac_signon_logon(tvb, pinfo, offset, signon_tree);
+ case FAMILY_SIGNON_LOGON_REPLY:
+ return dissect_aim_snac_signon_logon_reply(tvb, pinfo, offset, signon_tree);
+ case FAMILY_SIGNON_SIGNON:
+ return dissect_aim_snac_signon_signon(tvb, pinfo, offset, signon_tree);
+ case FAMILY_SIGNON_SIGNON_REPLY:
+ return dissect_aim_snac_signon_signon_reply(tvb, pinfo, offset, signon_tree);
+ case FAMILY_SIGNON_S_SECUREID_REQ:
+ /* No data */
+ return 0;
+ case FAMILY_SIGNON_UIN_REQ:
+ case FAMILY_SIGNON_UIN_REPL:
+ case FAMILY_SIGNON_C_SECUREID_REP:
+ /*FIXME*/
+ default:
+ return 0;
+ }
+}
+
+static int dissect_aim_snac_signon_logon(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ while (tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
+ }
+ return offset;
+}
+
+static int dissect_aim_snac_signon_logon_reply(tvbuff_t *tvb,
+ packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Login information reply");
+
+ while (tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
+ }
+ return offset;
+}
+
+static int dissect_aim_snac_signon_signon(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ guint8 buddyname_length = 0;
+ char buddyname[MAX_BUDDYNAME_LENGTH + 1];
+
+ /* Info Type */
+ proto_tree_add_item(tree, hf_aim_infotype, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* Unknown */
+ offset += 1;
+
+ /* Buddy Name */
+ buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Username: %s",
+ format_text(buddyname, buddyname_length));
+ }
+
+ if(tree) {
+ proto_tree_add_text(tree, tvb, offset + 1, buddyname_length,
+ "Screen Name: %s",
+ format_text(buddyname, buddyname_length));
+ }
+
+ offset += buddyname_length + 1;
+ return offset;
+}
+
+static int dissect_aim_snac_signon_signon_reply(tvbuff_t *tvb,
+ packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ guint16 challenge_length = 0;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Sign-on reply");
+
+ /* Logon Challenge Length */
+ challenge_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_aim_signon_challenge_len, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* Challenge */
+ proto_tree_add_item(tree, hf_aim_signon_challenge, tvb, offset, challenge_length, FALSE);
+ offset += challenge_length;
+ return offset;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_signon(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_aim_infotype,
+ { "Infotype", "aim.infotype", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_signon_challenge_len,
+ { "Signon challenge length", "aim.signon.challengelen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_signon_challenge,
+ { "Signon challenge", "aim.signon.challenge", FT_STRING, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_signon,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_signon = proto_register_protocol("AIM Signon", "AIM Signon", "aim_signon");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim_signon, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_signon(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim_snac_signon, proto_aim_signon);
+ dissector_add("aim.family", FAMILY_SIGNON, aim_handle);
+ aim_init_family(FAMILY_SIGNON, "Signon", aim_fnac_family_signon);
+}
diff --git a/epan/dissectors/packet-aim-ssi.c b/epan/dissectors/packet-aim-ssi.c
new file mode 100644
index 0000000000..18e0faa662
--- /dev/null
+++ b/epan/dissectors/packet-aim-ssi.c
@@ -0,0 +1,331 @@
+/* packet-aim-ssi.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC SSI
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ * Copyright 2000, Ralf Hoelzer <ralf@well.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_SSI 0x0013
+
+/* Family Server-Stored Buddy Lists */
+#define FAMILY_SSI_ERROR 0x0001
+#define FAMILY_SSI_REQRIGHTS 0x0002
+#define FAMILY_SSI_RIGHTSINFO 0x0003
+#define FAMILY_SSI_REQLIST_FIRSTTIME 0x0004
+#define FAMILY_SSI_REQLIST 0x0005
+#define FAMILY_SSI_LIST 0x0006
+#define FAMILY_SSI_ACTIVATE 0x0007
+#define FAMILY_SSI_ADD 0x0008
+#define FAMILY_SSI_MOD 0x0009
+#define FAMILY_SSI_DEL 0x000a
+#define FAMILY_SSI_SRVACK 0x000e
+#define FAMILY_SSI_NOLIST 0x000f
+#define FAMILY_SSI_EDITSTART 0x0011
+#define FAMILY_SSI_EDITSTOP 0x0012
+#define FAMILY_SSI_GRANT_FUTURE_AUTH 0x0014
+#define FAMILY_SSI_FUTUR_AUTH_GRANTED 0x0015
+#define FAMILY_SSI_SEND_AUTH_REQ 0x0018
+#define FAMILY_SSI_AUTH_REQ 0x0019
+#define FAMILY_SSI_SEND_AUTH_REPLY 0x001a
+#define FAMILY_SSI_AUTH_REPLY 0x001b
+#define FAMILY_SSI_WAS_ADDED 0x001c
+
+static const value_string aim_fnac_family_ssi[] = {
+ { FAMILY_SSI_ERROR, "Error" },
+ { FAMILY_SSI_REQRIGHTS, "Request Rights" },
+ { FAMILY_SSI_RIGHTSINFO, "Rights Info" },
+ { FAMILY_SSI_REQLIST_FIRSTTIME, "Request List (first time)" },
+ { FAMILY_SSI_REQLIST, "Request List" },
+ { FAMILY_SSI_LIST, "List" },
+ { FAMILY_SSI_ACTIVATE, "Activate" },
+ { FAMILY_SSI_ADD, "Add Buddy" },
+ { FAMILY_SSI_MOD, "Modify Buddy" },
+ { FAMILY_SSI_DEL, "Delete Buddy" },
+ { FAMILY_SSI_SRVACK, "Server Ack" },
+ { FAMILY_SSI_NOLIST, "No List" },
+ { FAMILY_SSI_EDITSTART, "Edit Start" },
+ { FAMILY_SSI_EDITSTOP, "Edit Stop" },
+ { FAMILY_SSI_GRANT_FUTURE_AUTH, "Grant Future Authorization to Client" },
+ { FAMILY_SSI_FUTUR_AUTH_GRANTED, "Future Authorization Granted" },
+ { FAMILY_SSI_SEND_AUTH_REQ, "Send Authentication Request" },
+ { FAMILY_SSI_AUTH_REQ, "Authentication Request" },
+ { FAMILY_SSI_SEND_AUTH_REPLY, "Send Authentication Reply" },
+ { FAMILY_SSI_AUTH_REPLY, "Authentication Reply" },
+ { FAMILY_SSI_WAS_ADDED, "Remote User Added Client To List" },
+ { 0, NULL }
+};
+
+#define FAMILY_SSI_TYPE_BUDDY 0x0000
+#define FAMILY_SSI_TYPE_GROUP 0x0001
+#define FAMILY_SSI_TYPE_PERMIT 0x0002
+#define FAMILY_SSI_TYPE_DENY 0x0003
+#define FAMILY_SSI_TYPE_PDINFO 0x0004
+#define FAMILY_SSI_TYPE_PRESENCEPREFS 0x0005
+#define FAMILY_SSI_TYPE_ICONINFO 0x0014
+
+static const value_string aim_fnac_family_ssi_types[] = {
+ { FAMILY_SSI_TYPE_BUDDY, "Buddy" },
+ { FAMILY_SSI_TYPE_GROUP, "Group" },
+ { FAMILY_SSI_TYPE_PERMIT, "Permit" },
+ { FAMILY_SSI_TYPE_DENY, "Deny" },
+ { FAMILY_SSI_TYPE_PDINFO, "PDINFO" },
+ { FAMILY_SSI_TYPE_PRESENCEPREFS, "Presence Preferences" },
+ { FAMILY_SSI_TYPE_ICONINFO, "Icon Info" },
+ { 0, NULL }
+};
+
+static const aim_tlv ssi_rights_tlvs[] = {
+ { 0, NULL, NULL }
+};
+
+static int dissect_aim_snac_ssi_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree, guint16 subtype _U_);
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_ssi = -1;
+static int hf_aim_fnac_subtype_ssi_version = -1;
+static int hf_aim_fnac_subtype_ssi_numitems = -1;
+static int hf_aim_fnac_subtype_ssi_last_change_time = -1;
+static int hf_aim_fnac_subtype_ssi_buddyname_len = -1;
+static int hf_aim_fnac_subtype_ssi_buddyname = -1;
+static int hf_aim_fnac_subtype_ssi_gid = -1;
+static int hf_aim_fnac_subtype_ssi_bid = -1;
+static int hf_aim_fnac_subtype_ssi_type = -1;
+static int hf_aim_fnac_subtype_ssi_tlvlen = -1;
+static int hf_aim_fnac_subtype_ssi_data = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_ssi = -1;
+static gint ett_ssi = -1;
+
+static int dissect_ssi_item(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *ssi_entry,
+ guint16 subtype _U_)
+{
+ guint16 buddyname_length = 0;
+ int endoffset;
+ guint16 tlv_len = 0;
+ /* Buddy Name Length */
+ buddyname_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_buddyname_len,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* Buddy Name */
+ if (buddyname_length > 0) {
+ proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_buddyname, tvb,
+ offset, buddyname_length, FALSE);
+ offset += buddyname_length;
+ }
+
+ /* Buddy group ID */
+ proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_gid, tvb, offset,
+ 2, FALSE);
+ offset += 2;
+
+ /* Buddy ID */
+ proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_bid, tvb, offset,
+ 2, FALSE);
+ offset += 2;
+
+ /* Buddy Type */
+ proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_type, tvb, offset,
+ 2, FALSE);
+ offset += 2;
+
+ /* Size of the following TLV in bytes (as opposed to the number of
+ TLV objects in the chain) */
+ tlv_len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_tlvlen, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ endoffset = offset;
+ /* For now, we just dump the TLV contents as-is, since there is not a
+ TLV dissection utility that works based on total chain length */
+ while(endoffset < offset+tlv_len) {
+ endoffset = dissect_aim_tlv(tvb, pinfo, endoffset, ssi_entry, client_tlvs);
+ }
+ return endoffset;
+}
+
+static int dissect_aim_snac_ssi(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ struct aiminfo *aiminfo = pinfo->private_data;
+ int offset = 0;
+ proto_item *ti = NULL;
+ proto_tree *ssi_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Server Side Information Service");
+ ssi_tree = proto_item_add_subtree(ti, ett_ssi);
+ }
+
+ switch(aiminfo->subtype)
+ {
+ case FAMILY_SSI_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, ssi_tree);
+ case FAMILY_SSI_LIST:
+ return dissect_aim_snac_ssi_list(tvb, pinfo, offset, ssi_tree, aiminfo->subtype);
+ case FAMILY_SSI_RIGHTSINFO:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, ssi_tree, ssi_rights_tlvs);
+ }
+ return offset;
+ case FAMILY_SSI_REQRIGHTS:
+ case FAMILY_SSI_ACTIVATE:
+ case FAMILY_SSI_EDITSTART:
+ case FAMILY_SSI_EDITSTOP:
+ case FAMILY_SSI_REQLIST_FIRSTTIME:
+ /* No data */
+ return 0;
+ case FAMILY_SSI_ADD:
+ case FAMILY_SSI_MOD:
+ case FAMILY_SSI_DEL:
+ return dissect_ssi_item(tvb, pinfo, offset, ssi_tree, aiminfo->subtype);
+ case FAMILY_SSI_WAS_ADDED:
+ return dissect_aim_buddyname(tvb, pinfo, offset, ssi_tree);
+ case FAMILY_SSI_REQLIST:
+ case FAMILY_SSI_SRVACK:
+ case FAMILY_SSI_NOLIST:
+ case FAMILY_SSI_GRANT_FUTURE_AUTH:
+ case FAMILY_SSI_FUTUR_AUTH_GRANTED:
+ case FAMILY_SSI_SEND_AUTH_REQ:
+ case FAMILY_SSI_AUTH_REQ:
+ case FAMILY_SSI_SEND_AUTH_REPLY:
+ case FAMILY_SSI_AUTH_REPLY:
+
+ /* FIXME */
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+static int dissect_aim_snac_ssi_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree,
+ guint16 subtype)
+{
+ proto_item *ti;
+ proto_tree *ssi_entry = NULL;
+ guint16 num_items, i;
+
+ /* SSI Version */
+ proto_tree_add_item(tree, hf_aim_fnac_subtype_ssi_version, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ /* Number of items */
+ proto_tree_add_item(tree, hf_aim_fnac_subtype_ssi_numitems, tvb, offset, 2,
+ FALSE);
+ num_items = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+
+ for(i = 0; i < num_items; i++) {
+ ti = proto_tree_add_text(tree, tvb, offset, tvb_get_ntohs(tvb, offset+10)+10, "SSI Entry");
+ ssi_entry = proto_item_add_subtree(ti, ett_aim_ssi);
+ offset = dissect_ssi_item(tvb, pinfo, offset, ssi_entry, subtype);
+ }
+ proto_tree_add_item(tree, hf_aim_fnac_subtype_ssi_last_change_time, tvb, offset, 4, FALSE);
+ return offset;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_ssi(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_aim_fnac_subtype_ssi_version,
+ { "SSI Version", "aim.fnac.ssi.version", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype_ssi_numitems,
+ { "SSI Object count", "aim.fnac.ssi.numitems", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype_ssi_last_change_time,
+ { "SSI Last Change Time", "aim.fnac.ssi.last_change_time", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype_ssi_buddyname_len,
+ { "SSI Buddy Name length", "aim.fnac.ssi.buddyname_len", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype_ssi_buddyname,
+ { "Buddy Name", "aim.fnac.ssi.buddyname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype_ssi_gid,
+ { "SSI Buddy Group ID", "aim.fnac.ssi.gid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype_ssi_bid,
+ { "SSI Buddy ID", "aim.fnac.ssi.bid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype_ssi_type,
+ { "SSI Buddy type", "aim.fnac.ssi.type", FT_UINT16, BASE_HEX, VALS(aim_fnac_family_ssi_types), 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype_ssi_tlvlen,
+ { "SSI TLV Len", "aim.fnac.ssi.tlvlen", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype_ssi_data,
+ { "SSI Buddy Data", "aim.fnac.ssi.data", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_ssi,
+ &ett_ssi,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_ssi = proto_register_protocol("AIM Server Side Info", "AIM SSI", "aim_ssi");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim_ssi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_ssi(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim_snac_ssi, proto_aim_ssi);
+ dissector_add("aim.family", FAMILY_SSI, aim_handle);
+ aim_init_family(FAMILY_SSI, "SSI", aim_fnac_family_ssi);
+}
diff --git a/epan/dissectors/packet-aim-stats.c b/epan/dissectors/packet-aim-stats.c
new file mode 100644
index 0000000000..2a5da29b2d
--- /dev/null
+++ b/epan/dissectors/packet-aim-stats.c
@@ -0,0 +1,97 @@
+/* packet-aim-stats.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Stats
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_STATS 0x000B
+
+/* Family User Stats */
+#define FAMILY_STATS_ERROR 0x0001
+#define FAMILY_STATS_SETREPORTINTERVAL 0x0002
+#define FAMILY_STATS_REPORTREQ 0x0003
+#define FAMILY_STATS_REPORTACK 0x0004
+#define FAMILY_STATS_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_stats[] = {
+ { FAMILY_STATS_ERROR, "Error" },
+ { FAMILY_STATS_SETREPORTINTERVAL, "Set Report Interval" },
+ { FAMILY_STATS_REPORTREQ, "Report Request" },
+ { FAMILY_STATS_REPORTACK, "Report Ack" },
+ { FAMILY_STATS_DEFAULT, "Stats Default" },
+ { 0, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_aim_stats = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_stats = -1;
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_stats(void)
+{
+
+/* Setup list of header fields */
+/*FIXME
+ static hf_register_info hf[] = {
+ };*/
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_stats,
+ };
+
+/* Register the protocol name and description */
+ proto_aim_stats = proto_register_protocol("AIM Statistics", "AIM Stats", "aim_stats");
+
+/* Required function calls to register the header fields and subtrees used */
+/*FIXME
+ proto_register_field_array(proto_aim_stats, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_stats(void)
+{
+ /*dissector_handle_t aim_handle;*/
+/*FIXME: aim_handle = new_create_dissector_handle(dissect_aim_snac_stats, proto_aim_stats);
+ dissector_add("aim.family", FAMILY_STATS, aim_handle);*/
+ aim_init_family(FAMILY_STATS, "Statistic", aim_fnac_family_stats);
+}
diff --git a/epan/dissectors/packet-aim-translate.c b/epan/dissectors/packet-aim-translate.c
new file mode 100644
index 0000000000..dbf1f193c8
--- /dev/null
+++ b/epan/dissectors/packet-aim-translate.c
@@ -0,0 +1,99 @@
+/* packet-aim-translate.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Translate
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_TRANSLATE 0x000C
+
+/* Family Translation */
+#define FAMILY_TRANSLATE_ERROR 0x0001
+#define FAMILY_TRANSLATE_REQ 0x0002
+#define FAMILY_TRANSLATE_REPL 0x0003
+#define FAMILY_TRANSLATE_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_translate[] = {
+ { FAMILY_TRANSLATE_ERROR, "Error" },
+ { FAMILY_TRANSLATE_REQ, "Translate Request" },
+ { FAMILY_TRANSLATE_REPL, "Translate Reply" },
+ { FAMILY_TRANSLATE_DEFAULT, "Translate Default" },
+ { 0, NULL }
+};
+
+static int proto_aim_translate = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_translate = -1;
+
+static int dissect_aim_translate(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {
+
+ /* FIXME */
+ return 0;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_translate(void)
+{
+
+/* Setup list of header fields */
+/*FIXME
+ static hf_register_info hf[] = {
+ };*/
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_translate,
+ };
+/* Register the protocol name and description */
+ proto_aim_translate = proto_register_protocol("AIM Translate", "AIM Translate", "aim_translate");
+
+/* Required function calls to register the header fields and subtrees used */
+/*FIXME
+ proto_register_field_array(proto_aim_translate, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_translate(void)
+{
+ dissector_handle_t aim_handle;
+ aim_handle = new_create_dissector_handle(dissect_aim_translate, proto_aim_translate);
+ dissector_add("aim.family", FAMILY_TRANSLATE, aim_handle);
+ aim_init_family(FAMILY_TRANSLATE, "Translate", aim_fnac_family_translate);
+}
diff --git a/epan/dissectors/packet-aim-userlookup.c b/epan/dissectors/packet-aim-userlookup.c
new file mode 100644
index 0000000000..ebf7c95531
--- /dev/null
+++ b/epan/dissectors/packet-aim-userlookup.c
@@ -0,0 +1,127 @@
+/* packet-aim-userlookup.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Userlookup
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-aim.h"
+
+#define FAMILY_USERLOOKUP 0x000A
+
+/* Family User Lookup */
+#define FAMILY_USERLOOKUP_ERROR 0x0001
+#define FAMILY_USERLOOKUP_SEARCHEMAIL 0x0002
+#define FAMILY_USERLOOKUP_SEARCHRESULT 0x0003
+#define FAMILY_USERLOOKUP_DEFAULT 0xffff
+
+static const value_string aim_fnac_family_userlookup[] = {
+ { FAMILY_USERLOOKUP_ERROR, "Error" },
+ { FAMILY_USERLOOKUP_SEARCHEMAIL, "Search for user by email address" },
+ { FAMILY_USERLOOKUP_SEARCHRESULT, "Search results" },
+ { FAMILY_USERLOOKUP_DEFAULT, "Userlookup Default" },
+ { 0, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int hf_aim_userlookup_email = -1;
+static int proto_aim_userlookup = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aim_userlookup = -1;
+
+static int dissect_aim_snac_userlookup(tvbuff_t *tvb _U_, packet_info *pinfo,
+ proto_tree *tree _U_)
+{
+ struct aiminfo *aiminfo = pinfo->private_data;
+ int offset = 0;
+
+ proto_item *ti = NULL;
+ proto_tree *lookup_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Lookup Service");
+ lookup_tree = proto_item_add_subtree(ti, ett_aim_userlookup);
+ }
+
+
+ switch(aiminfo->subtype) {
+ case FAMILY_USERLOOKUP_ERROR:
+ return dissect_aim_snac_error(tvb, pinfo, offset, tree);
+ case FAMILY_USERLOOKUP_SEARCHEMAIL:
+ proto_tree_add_item(lookup_tree, hf_aim_userlookup_email, tvb, 0, tvb_length(tvb), FALSE);
+ return tvb_length(tvb);
+ case FAMILY_USERLOOKUP_SEARCHRESULT:
+ while(tvb_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, lookup_tree, client_tlvs);
+ }
+ return offset;
+ }
+
+ return 0;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim_userlookup(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_aim_userlookup_email,
+ { "Email address looked for", "aim.userlookup.email", FT_STRING, BASE_NONE, NULL, 0, "Email address", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim_userlookup,
+ };
+/* Register the protocol name and description */
+ proto_aim_userlookup = proto_register_protocol("AIM User Lookup", "AIM User Lookup", "aim_lookup");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim_userlookup, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_aim_userlookup(void)
+{
+ dissector_handle_t aim_handle;
+ aim_handle = new_create_dissector_handle(dissect_aim_snac_userlookup, proto_aim_userlookup);
+ dissector_add("aim.family", FAMILY_USERLOOKUP, aim_handle);
+ aim_init_family(FAMILY_USERLOOKUP, "User Lookup", aim_fnac_family_userlookup);
+}
diff --git a/epan/dissectors/packet-aim.c b/epan/dissectors/packet-aim.c
new file mode 100644
index 0000000000..7a1d9b5e94
--- /dev/null
+++ b/epan/dissectors/packet-aim.c
@@ -0,0 +1,1152 @@
+/* packet-aim.c
+ * Routines for AIM Instant Messenger (OSCAR) dissection
+ * Copyright 2000, Ralf Hoelzer <ralf@well.com>
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ * Copyright 2004, Devin Heitmueller <dheitmueller@netilla.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include "isprint.h"
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-tcp.h"
+#include "packet-aim.h"
+#include "prefs.h"
+
+#define TCP_PORT_AIM 5190
+
+#define STRIP_TAGS 1
+
+/* channels */
+#define CHANNEL_NEW_CONN 0x01
+#define CHANNEL_SNAC_DATA 0x02
+#define CHANNEL_FLAP_ERR 0x03
+#define CHANNEL_CLOSE_CONN 0x04
+#define CHANNEL_KEEP_ALIVE 0x05
+
+#define CLI_COOKIE 0x01
+
+#define FAMILY_ALL_ERROR_INVALID_HEADER 0x0001
+#define FAMILY_ALL_ERROR_SERVER_RATE_LIMIT_EXCEEDED 0x0002
+#define FAMILY_ALL_ERROR_CLIENT_RATE_LIMIT_EXCEEDED 0x0003
+#define FAMILY_ALL_ERROR_RECIPIENT_NOT_LOGGED_IN 0x0004
+#define FAMILY_ALL_ERROR_REQUESTED_SERVICE_UNAVAILABLE 0x0005
+#define FAMILY_ALL_ERROR_REQUESTED_SERVICE_NOT_DEFINED 0x0006
+#define FAMILY_ALL_ERROR_OBSOLETE_SNAC 0x0007
+#define FAMILY_ALL_ERROR_NOT_SUPPORTED_BY_SERVER 0x0008
+#define FAMILY_ALL_ERROR_NOT_SUPPORTED_BY_CLIENT 0x0009
+#define FAMILY_ALL_ERROR_REFUSED_BY_CLIENT 0x000a
+#define FAMILY_ALL_ERROR_REPLY_TOO_BIG 0x000b
+#define FAMILY_ALL_ERROR_RESPONSES_LOST 0x000c
+#define FAMILY_ALL_ERROR_REQUEST_DENIED 0x000d
+#define FAMILY_ALL_ERROR_INCORRECT_SNAC_FORMAT 0x000e
+#define FAMILY_ALL_ERROR_INSUFFICIENT_RIGHTS 0x000f
+#define FAMILY_ALL_ERROR_RECIPIENT_BLOCKED 0x0010
+#define FAMILY_ALL_ERROR_SENDER_TOO_EVIL 0x0011
+#define FAMILY_ALL_ERROR_RECEIVER_TOO_EVIL 0x0012
+#define FAMILY_ALL_ERROR_USER_TEMP_UNAVAILABLE 0x0013
+#define FAMILY_ALL_ERROR_NO_MATCH 0x0014
+#define FAMILY_ALL_ERROR_LIST_OVERFLOW 0x0015
+#define FAMILY_ALL_ERROR_REQUEST_AMBIGUOUS 0x0016
+#define FAMILY_ALL_ERROR_SERVER_QUEUE_FULL 0x0017
+#define FAMILY_ALL_ERROR_NOT_WHILE_ON_AOL 0x0018
+
+static const value_string aim_flap_channels[] = {
+ { CHANNEL_NEW_CONN, "New Connection" },
+ { CHANNEL_SNAC_DATA, "SNAC Data" },
+ { CHANNEL_FLAP_ERR, "FLAP-Level Error" },
+ { CHANNEL_CLOSE_CONN, "Close Connection" },
+ { CHANNEL_KEEP_ALIVE, "Keep Alive" },
+ { 0, NULL }
+};
+
+static const value_string aim_snac_errors[] = {
+ { FAMILY_ALL_ERROR_INVALID_HEADER, "Invalid SNAC Header" },
+ { FAMILY_ALL_ERROR_SERVER_RATE_LIMIT_EXCEEDED, "Server rate limit exceeded" },
+ { FAMILY_ALL_ERROR_CLIENT_RATE_LIMIT_EXCEEDED, "Client rate limit exceeded" },
+ { FAMILY_ALL_ERROR_RECIPIENT_NOT_LOGGED_IN, "Recipient not logged in" },
+ { FAMILY_ALL_ERROR_REQUESTED_SERVICE_UNAVAILABLE, "Requested service unavailable" },
+ { FAMILY_ALL_ERROR_REQUESTED_SERVICE_NOT_DEFINED, "Requested service not defined" },
+ { FAMILY_ALL_ERROR_OBSOLETE_SNAC, "Obsolete SNAC issued" },
+ { FAMILY_ALL_ERROR_NOT_SUPPORTED_BY_SERVER, "Not supported by server" },
+ { FAMILY_ALL_ERROR_NOT_SUPPORTED_BY_CLIENT, "Not supported by client" },
+ { FAMILY_ALL_ERROR_REFUSED_BY_CLIENT, "Refused by client" },
+ { FAMILY_ALL_ERROR_REPLY_TOO_BIG, "Reply too big" },
+ { FAMILY_ALL_ERROR_RESPONSES_LOST, "Responses lost" },
+ { FAMILY_ALL_ERROR_REQUEST_DENIED, "Request denied" },
+ { FAMILY_ALL_ERROR_INCORRECT_SNAC_FORMAT, "Incorrect SNAC format" },
+ { FAMILY_ALL_ERROR_INSUFFICIENT_RIGHTS, "Insufficient rights" },
+ { FAMILY_ALL_ERROR_RECIPIENT_BLOCKED, "Recipient blocked" },
+ { FAMILY_ALL_ERROR_SENDER_TOO_EVIL, "Sender too evil" },
+ { FAMILY_ALL_ERROR_RECEIVER_TOO_EVIL, "Receiver too evil" },
+ { FAMILY_ALL_ERROR_USER_TEMP_UNAVAILABLE, "User temporarily unavailable" },
+ { FAMILY_ALL_ERROR_NO_MATCH, "No match" },
+ { FAMILY_ALL_ERROR_LIST_OVERFLOW, "List overflow" },
+ { FAMILY_ALL_ERROR_REQUEST_AMBIGUOUS, "Request ambiguous" },
+ { FAMILY_ALL_ERROR_SERVER_QUEUE_FULL, "Server queue full" },
+ { FAMILY_ALL_ERROR_NOT_WHILE_ON_AOL, "Not while on AOL" },
+ { 0, NULL }
+};
+
+#define AIM_CLIENT_TLV_SCREEN_NAME 0x0001
+#define AIM_CLIENT_TLV_ROASTED_PASSWORD 0x0002
+#define AIM_CLIENT_TLV_CLIENT_ID_STRING 0x0003
+#define AIM_CLIENT_TLV_ERRORURL 0x0004
+#define AIM_CLIENT_TLV_BOS_SERVER_STRING 0x0005
+#define AIM_CLIENT_TLV_AUTH_COOKIE 0x0006
+#define AIM_CLIENT_TLV_ERRORCODE 0x0008
+#define AIM_CLIENT_TLV_GENERIC_SERVICE_ID 0x000d
+#define AIM_CLIENT_TLV_CLIENT_COUNTRY 0x000e
+#define AIM_CLIENT_TLV_CLIENT_LANGUAGE 0x000f
+#define AIM_CLIENT_TLV_EMAILADDR 0x0011
+#define AIM_CLIENT_TLV_OLD_ROASTED_PASSWORD 0x0012
+#define AIM_CLIENT_TLV_REGSTATUS 0x0013
+#define AIM_CLIENT_TLV_CLIENT_DISTRIBUTION_NUM 0x0014
+#define AIM_CLIENT_TLV_INVITEMESSAGE 0x0015
+#define AIM_CLIENT_TLV_CLIENT_ID 0x0016
+#define AIM_CLIENT_TLV_CLIENT_MAJOR_VERSION 0x0017
+#define AIM_CLIENT_TLV_CLIENT_MINOR_VERSION 0x0018
+#define AIM_CLIENT_TLV_CLIENT_LESSER_VERSION 0x0019
+#define AIM_CLIENT_TLV_CLIENT_BUILD_NUMBER 0x001a
+#define AIM_CLIENT_TLV_PASSWORD 0x0025
+#define AIM_CLIENT_TLV_LATESTBETABUILD 0x0040
+#define AIM_CLIENT_TLV_LATESTBETAURL 0x0041
+#define AIM_CLIENT_TLV_LATESTBETAINFO 0x0042
+#define AIM_CLIENT_TLV_LATESTBETANAME 0x0043
+#define AIM_CLIENT_TLV_LATESTRELEASEBUILD 0x0044
+#define AIM_CLIENT_TLV_LATESTRELEASEURL 0x0045
+#define AIM_CLIENT_TLV_LATESTRELEASEINFO 0x0046
+#define AIM_CLIENT_TLV_LATESTRELEASENAME 0x0047
+#define AIM_CLIENT_TLV_CLIENTUSESSI 0x004a
+#define AIM_CLIENT_TLV_CHANGE_PASSWORD_URL 0x0054
+
+const aim_tlv client_tlvs[] = {
+ { AIM_CLIENT_TLV_SCREEN_NAME, "Screen name", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_ROASTED_PASSWORD, "Roasted password array", dissect_aim_tlv_value_bytes },
+ { AIM_CLIENT_TLV_OLD_ROASTED_PASSWORD, "Old roasted password array", dissect_aim_tlv_value_bytes },
+ { AIM_CLIENT_TLV_CLIENT_ID_STRING, "Client id string (name, version)", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_CLIENT_ID, "Client id number", dissect_aim_tlv_value_uint16 },
+ { AIM_CLIENT_TLV_CLIENT_MAJOR_VERSION, "Client major version", dissect_aim_tlv_value_uint16 },
+ { AIM_CLIENT_TLV_CLIENT_MINOR_VERSION, "Client minor version", dissect_aim_tlv_value_uint16 },
+ { AIM_CLIENT_TLV_CLIENT_LESSER_VERSION, "Client lesser version", dissect_aim_tlv_value_uint16 },
+ { AIM_CLIENT_TLV_CLIENT_BUILD_NUMBER, "Client build number", dissect_aim_tlv_value_uint16 },
+ { AIM_CLIENT_TLV_CLIENT_DISTRIBUTION_NUM, "Client distribution number", dissect_aim_tlv_value_uint16 },
+ { AIM_CLIENT_TLV_CLIENT_LANGUAGE, "Client language", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_CLIENT_COUNTRY, "Client country", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_BOS_SERVER_STRING, "BOS server string", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_AUTH_COOKIE, "Authorization cookie", dissect_aim_tlv_value_bytes },
+ { AIM_CLIENT_TLV_ERRORURL, "Error URL", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_ERRORCODE, "Error Code", dissect_aim_tlv_value_uint16 }, /* FIXME: Decode error codes too */
+ { AIM_CLIENT_TLV_EMAILADDR, "Account Email address", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_REGSTATUS, "Registration Status", dissect_aim_tlv_value_uint16 },
+ { AIM_CLIENT_TLV_LATESTBETABUILD, "Latest Beta Build", dissect_aim_tlv_value_uint32 },
+ { AIM_CLIENT_TLV_LATESTBETAURL, "Latest Beta URL", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_LATESTBETAINFO, "Latest Beta Info", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_LATESTBETANAME, "Latest Beta Name", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_LATESTRELEASEBUILD, "Latest Release Build", dissect_aim_tlv_value_uint32 },
+ { AIM_CLIENT_TLV_LATESTRELEASEURL, "Latest Release URL", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_LATESTRELEASEINFO, "Latest Release Info", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_LATESTRELEASENAME, "Latest Release Name", dissect_aim_tlv_value_string },
+ { AIM_CLIENT_TLV_CLIENTUSESSI, "Use SSI", dissect_aim_tlv_value_uint8 },
+ { AIM_CLIENT_TLV_GENERIC_SERVICE_ID, "Service (Family) ID", dissect_aim_tlv_value_uint16 },
+ { AIM_CLIENT_TLV_CHANGE_PASSWORD_URL, "Change password url", dissect_aim_tlv_value_string },
+ { 0, "Unknown", NULL },
+};
+
+
+static int dissect_aim_tlv_value_userstatus(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb);
+static int dissect_aim_tlv_value_dcinfo(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb);
+
+#define AIM_ONLINEBUDDY_USERCLASS 0x0001
+#define AIM_ONLINEBUDDY_ONSINCE 0x0003
+#define AIM_ONLINEBUDDY_IDLETIME 0x0004
+#define AIM_ONLINEBUDDY_MEMBERSINCE 0x0005
+#define AIM_ONLINEBUDDY_STATUS 0x0006
+#define AIM_ONLINEBUDDY_TIMEUPDATE 0x0011
+#define AIM_ONLINEBUDDY_IPADDR 0x000a
+#define AIM_ONLINEBUDDY_DCINFO 0x000c
+#define AIM_ONLINEBUDDY_CAPINFO 0x000d
+#define AIM_ONLINEBUDDY_UNKNOWN 0x000e
+#define AIM_ONLINEBUDDY_SESSIONLEN 0x000f
+#define AIM_ONLINEBUDDY_ICQSESSIONLEN 0x0010
+
+const aim_tlv onlinebuddy_tlvs[] = {
+ { AIM_ONLINEBUDDY_USERCLASS, "User class", dissect_aim_tlv_value_userclass },
+ { AIM_ONLINEBUDDY_ONSINCE, "Online since", dissect_aim_tlv_value_uint32 },
+ { AIM_ONLINEBUDDY_IDLETIME, "Idle time (sec)", dissect_aim_tlv_value_uint16 },
+ { AIM_ONLINEBUDDY_STATUS, "Online status", dissect_aim_tlv_value_userstatus },
+ { AIM_ONLINEBUDDY_IPADDR, "User IP Address", dissect_aim_tlv_value_ipv4 },
+ { AIM_ONLINEBUDDY_DCINFO, "DC Info", dissect_aim_tlv_value_dcinfo},
+ { AIM_ONLINEBUDDY_CAPINFO, "Capability Info", dissect_aim_tlv_value_bytes },
+ { AIM_ONLINEBUDDY_MEMBERSINCE, "Member since", dissect_aim_tlv_value_time },
+ { AIM_ONLINEBUDDY_UNKNOWN, "Unknown", dissect_aim_tlv_value_uint16 },
+ { AIM_ONLINEBUDDY_TIMEUPDATE, "Time update", dissect_aim_tlv_value_bytes },
+ { AIM_ONLINEBUDDY_SESSIONLEN, "Session Length (sec)", dissect_aim_tlv_value_uint32 },
+ { AIM_ONLINEBUDDY_ICQSESSIONLEN, "ICQ Session Length (sec)", dissect_aim_tlv_value_uint32 },
+ { 0, "Unknown", NULL }
+};
+
+struct aim_family {
+ guint16 family;
+ const char *name;
+ const value_string *subtypes;
+};
+
+static GList *families = NULL;
+
+#define AIM_MOTD_TLV_MOTD 0x000B
+
+const aim_tlv motd_tlvs[] = {
+ { AIM_MOTD_TLV_MOTD, "Message of the day message", dissect_aim_tlv_value_string },
+ { 0, "Unknown", NULL }
+};
+
+#define FAMILY_GENERIC_REDIRECT_SERVER_ADDRESS 0x0005
+#define FAMILY_GENERIC_REDIRECT_AUTH_COOKIE 0x0006
+#define FAMILY_GENERIC_REDIRECT_FAMILY_ID 0x000D
+
+static const aim_tlv aim_fnac_family_generic_redirect_tlv[] = {
+ { FAMILY_GENERIC_REDIRECT_SERVER_ADDRESS, "Server address and (optional) port", dissect_aim_tlv_value_string },
+ { FAMILY_GENERIC_REDIRECT_AUTH_COOKIE, "Authorization cookie", dissect_aim_tlv_value_string },
+ { FAMILY_GENERIC_REDIRECT_FAMILY_ID, "Family ID", dissect_aim_tlv_value_uint16 },
+ { 0, "Unknown", NULL }
+};
+
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_MDT_UPGRADE 0x0001
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_ADV_UPGRADE 0x0002
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_SYS_BULLETIN 0x0003
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_NORMAL 0x0004
+#define FAMILY_GENERIC_MOTD_MOTDTYPE_NEWS 0x0006
+
+static const value_string aim_snac_generic_motd_motdtypes[] = {
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_MDT_UPGRADE, "Mandatory Upgrade Needed Notice" },
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_ADV_UPGRADE, "Advisable Upgrade Notice" },
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_SYS_BULLETIN, "AIM/ICQ Service System Announcements" },
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_NORMAL, "Standard Notice" },
+ { FAMILY_GENERIC_MOTD_MOTDTYPE_NEWS, "News from AOL service" },
+ { 0, NULL }
+};
+
+#define CLASS_UNCONFIRMED 0x0001
+#define CLASS_ADMINISTRATOR 0x0002
+#define CLASS_AOL 0x0004
+#define CLASS_COMMERCIAL 0x0008
+#define CLASS_FREE 0x0010
+#define CLASS_AWAY 0x0020
+#define CLASS_ICQ 0x0040
+#define CLASS_WIRELESS 0x0080
+#define CLASS_UNKNOWN100 0x0100
+#define CLASS_UNKNOWN200 0x0200
+#define CLASS_UNKNOWN400 0x0400
+#define CLASS_UNKNOWN800 0x0800
+
+static int dissect_aim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static guint get_aim_pdu_len(tvbuff_t *tvb, int offset);
+static void dissect_aim_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static void dissect_aim_newconn(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
+static void dissect_aim_snac(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree, proto_tree *root_tree);
+static void dissect_aim_flap_err(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+static void dissect_aim_keep_alive(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+static void dissect_aim_close_conn(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+static void dissect_aim_unknown_channel(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+
+static dissector_table_t subdissector_table;
+
+/* Initialize the protocol and registered fields */
+static int proto_aim = -1;
+static int hf_aim_cmd_start = -1;
+static int hf_aim_channel = -1;
+static int hf_aim_seqno = -1;
+static int hf_aim_data = -1;
+static int hf_aim_data_len = -1;
+static int hf_aim_signon_challenge_len = -1;
+static int hf_aim_signon_challenge = -1;
+static int hf_aim_fnac_family = -1;
+static int hf_aim_fnac_subtype = -1;
+static int hf_aim_fnac_flags = -1;
+static int hf_aim_fnac_id = -1;
+static int hf_aim_infotype = -1;
+static int hf_aim_buddyname_len = -1;
+static int hf_aim_buddyname = -1;
+static int hf_aim_userinfo_warninglevel = -1;
+static int hf_aim_snac_error = -1;
+static int hf_aim_tlvcount = -1;
+static int hf_aim_authcookie = -1;
+static int hf_aim_userclass_unconfirmed = -1;
+static int hf_aim_userclass_administrator = -1;
+static int hf_aim_userclass_aol = -1;
+static int hf_aim_userclass_commercial = -1;
+static int hf_aim_userclass_free = -1;
+static int hf_aim_userclass_away = -1;
+static int hf_aim_userclass_icq = -1;
+static int hf_aim_userclass_wireless = -1;
+static int hf_aim_userclass_unknown100 = -1;
+static int hf_aim_userclass_unknown200 = -1;
+static int hf_aim_userclass_unknown400 = -1;
+static int hf_aim_userclass_unknown800 = -1;
+static int hf_aim_messageblock_featuresdes = -1;
+static int hf_aim_messageblock_featureslen = -1;
+static int hf_aim_messageblock_features = -1;
+static int hf_aim_messageblock_info = -1;
+static int hf_aim_messageblock_len = -1;
+static int hf_aim_messageblock_charset = -1;
+static int hf_aim_messageblock_charsubset = -1;
+static int hf_aim_messageblock_message = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_aim = -1;
+static gint ett_aim_buddyname= -1;
+static gint ett_aim_fnac = -1;
+static gint ett_aim_tlv = -1;
+static gint ett_aim_userclass = -1;
+static gint ett_aim_messageblock = -1;
+
+/* desegmentation of AIM over TCP */
+static gboolean aim_desegment = TRUE;
+
+/* Code to actually dissect the packets */
+static int dissect_aim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+/* check, if this is really an AIM packet, they start with 0x2a */
+/* XXX - I've seen some stuff starting with 0x5a followed by 0x2a */
+
+ if(tvb_bytes_exist(tvb, 0, 1) && tvb_get_guint8(tvb, 0) != 0x2a) {
+ /* Not an instant messenger packet, just happened to use the same port */
+ /* XXX - if desegmentation disabled, this might be a continuation
+ packet, not a non-AIM packet */
+ return 0;
+ }
+
+ tcp_dissect_pdus(tvb, pinfo, tree, aim_desegment, 6, get_aim_pdu_len,
+ dissect_aim_pdu);
+ return tvb_length(tvb);
+}
+
+static guint get_aim_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint16 plen;
+
+ /*
+ * Get the length of the AIM packet.
+ */
+ plen = tvb_get_ntohs(tvb, offset + 4);
+
+ /*
+ * That length doesn't include the length of the header itself; add that in.
+ */
+ return plen + 6;
+}
+
+static void dissect_aim_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Header fields */
+ unsigned char hdr_channel; /* channel ID */
+ unsigned short hdr_sequence_no; /* Internal frame sequence number, not needed */
+ unsigned short hdr_data_field_length; /* length of data within frame */
+
+ int offset=0;
+
+/* Set up structures we will need to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *aim_tree = NULL;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AIM");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "AOL Instant Messenger");
+
+ /* get relevant header information */
+ offset += 1; /* XXX - put the identifier into the tree? */
+ hdr_channel = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ hdr_sequence_no = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ hdr_data_field_length = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+
+/* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_aim, tvb, 0, -1, FALSE);
+ aim_tree = proto_item_add_subtree(ti, ett_aim);
+ proto_tree_add_uint(aim_tree, hf_aim_cmd_start, tvb, 0, 1, '*');
+ proto_tree_add_item(aim_tree, hf_aim_channel, tvb, 1, 1, FALSE);
+ proto_tree_add_uint(aim_tree, hf_aim_seqno, tvb, 2, 2, hdr_sequence_no);
+ proto_tree_add_uint(aim_tree, hf_aim_data_len, tvb, 4, 2, hdr_data_field_length);
+
+ }
+
+ switch(hdr_channel)
+ {
+ case CHANNEL_NEW_CONN:
+ dissect_aim_newconn(tvb, pinfo, offset, aim_tree);
+ break;
+ case CHANNEL_SNAC_DATA:
+ dissect_aim_snac(tvb, pinfo, offset, aim_tree, tree);
+ break;
+ case CHANNEL_FLAP_ERR:
+ dissect_aim_flap_err(tvb, pinfo, offset, aim_tree);
+ break;
+ case CHANNEL_CLOSE_CONN:
+ dissect_aim_close_conn(tvb, pinfo, offset, aim_tree);
+ break;
+ case CHANNEL_KEEP_ALIVE:
+ dissect_aim_keep_alive(tvb, pinfo, offset, aim_tree);
+ break;
+ default:
+ dissect_aim_unknown_channel(tvb, pinfo, offset, aim_tree);
+ break;
+ }
+
+}
+
+const char *aim_get_subtypename( guint16 famnum, guint16 subtype )
+{
+ GList *gl = families;
+ while(gl) {
+ struct aim_family *fam = gl->data;
+ if(fam->family == famnum) return match_strval(subtype, fam->subtypes);
+ gl = gl->next;
+ }
+
+ return NULL;
+
+}
+
+const char *aim_get_familyname( guint16 famnum )
+{
+ GList *gl = families;
+ while(gl) {
+ struct aim_family *fam = gl->data;
+ if(fam->family == famnum) return fam->name;
+ gl = gl->next;
+ }
+
+ return NULL;
+}
+
+int aim_get_buddyname( char *name, tvbuff_t *tvb, int len_offset, int name_offset)
+{
+ guint8 buddyname_length;
+
+ buddyname_length = tvb_get_guint8(tvb, len_offset);
+
+ if(buddyname_length > MAX_BUDDYNAME_LENGTH ) buddyname_length = MAX_BUDDYNAME_LENGTH;
+ tvb_get_nstringz0(tvb, name_offset, buddyname_length + 1, name);
+
+ return buddyname_length;
+}
+
+
+void aim_get_message( guchar *msg, tvbuff_t *tvb, int msg_offset, int msg_length)
+{
+ int i,j,c;
+ int bracket = FALSE;
+ int max, tagchars = 0;
+ int new_offset = msg_offset;
+ int new_length = msg_length;
+
+
+
+ /* make sure nothing bigger than 1000 bytes is printed */
+ if( msg_length > 999 ) return;
+
+ memset( msg, '\0', 1000);
+ i = 0;
+ c = 0;
+
+ /* loop until HTML tag is reached - quick&dirty way to find start of message
+ * (it is nearly impossible to find the correct start offset for all client versions) */
+ while( (tagchars < 6) && (new_length > 5) )
+ {
+ j = tvb_get_guint8(tvb, new_offset);
+ if( ( (j == '<') && (tagchars == 0) ) ||
+ ( (j == 'h') && (tagchars == 1) ) ||
+ ( (j == 'H') && (tagchars == 1) ) ||
+ ( (j == 't') && (tagchars == 2) ) ||
+ ( (j == 'T') && (tagchars == 2) ) ||
+ ( (j == 'm') && (tagchars == 3) ) ||
+ ( (j == 'M') && (tagchars == 3) ) ||
+ ( (j == 'l') && (tagchars == 4) ) ||
+ ( (j == 'L') && (tagchars == 4) ) ||
+ ( (j == '>') && (tagchars == 5) ) ) tagchars++;
+ new_offset++;
+ new_length--;
+ }
+
+ /* set offset and length of message to after the first HTML tag */
+ msg_offset = new_offset;
+ msg_length = new_length;
+ max = msg_length - 1;
+ tagchars = 0;
+
+ /* find the rest of the message until either a </html> is reached or the end of the frame.
+ * All other HTML tags are stripped to display only the raw message (printable characters) */
+ while( (c < max) && (tagchars < 7) )
+ {
+ j = tvb_get_guint8(tvb, msg_offset+c);
+
+
+ /* make sure this is an HTML tag by checking the order of the chars */
+ if( ( (j == '<') && (tagchars == 0) ) ||
+ ( (j == '/') && (tagchars == 1) ) ||
+ ( (j == 'h') && (tagchars == 2) ) ||
+ ( (j == 'H') && (tagchars == 2) ) ||
+ ( (j == 't') && (tagchars == 3) ) ||
+ ( (j == 'T') && (tagchars == 3) ) ||
+ ( (j == 'm') && (tagchars == 4) ) ||
+ ( (j == 'M') && (tagchars == 4) ) ||
+ ( (j == 'l') && (tagchars == 5) ) ||
+ ( (j == 'L') && (tagchars == 5) ) ||
+ ( (j == '>') && (tagchars == 6) ) ) tagchars++;
+
+#ifdef STRIP_TAGS
+ if( j == '<' ) bracket = TRUE;
+ if( j == '>' ) bracket = FALSE;
+ if( (isprint(j) ) && (bracket == FALSE) && (j != '>'))
+#else
+ if( isprint(j) )
+#endif
+ {
+ msg[i] = j;
+ i++;
+ }
+ c++;
+ }
+}
+
+void aim_init_family(guint16 family, const char *name, const value_string *subtypes)
+{
+ struct aim_family *fam = g_new(struct aim_family, 1);
+ fam->name = g_strdup(name);
+ fam->family = family;
+ fam->subtypes = subtypes;
+ families = g_list_append(families, fam);
+}
+
+static void dissect_aim_newconn(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "New Connection");
+
+ if (tvb_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_item(tree, hf_aim_authcookie, tvb, offset, 4, FALSE);
+ offset+=4;
+ while(tvb_reported_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
+ }
+ }
+
+ if (tvb_length_remaining(tvb, offset) > 0)
+ proto_tree_add_item(tree, hf_aim_data, tvb, offset, -1, FALSE);
+}
+
+
+int dissect_aim_snac_error(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *aim_tree)
+{
+ char *name;
+ if ((name = match_strval(tvb_get_ntohs(tvb, offset), aim_snac_errors)) != NULL) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, name);
+ }
+
+ proto_tree_add_item (aim_tree, hf_aim_snac_error,
+ tvb, offset, 2, FALSE);
+ return tvb_length_remaining(tvb, 2);
+}
+
+int dissect_aim_userinfo(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ offset = dissect_aim_buddyname(tvb, pinfo, offset, tree);
+
+ proto_tree_add_item(tree, hf_aim_userinfo_warninglevel, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ return dissect_aim_tlv_list(tvb, pinfo, offset, tree, onlinebuddy_tlvs);
+}
+
+static void dissect_aim_snac(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *aim_tree, proto_tree *root_tree)
+{
+ guint16 family;
+ guint16 subtype;
+ guint16 flags;
+ guint32 id;
+ proto_item *ti1;
+ struct aiminfo aiminfo;
+ const char *fam_name, *subtype_name;
+ proto_tree *aim_tree_fnac = NULL;
+ tvbuff_t *subtvb;
+ int orig_offset;
+
+ orig_offset = offset;
+ family = tvb_get_ntohs(tvb, offset);
+ fam_name = aim_get_familyname(family);
+ offset += 2;
+ subtype = tvb_get_ntohs(tvb, offset);
+ subtype_name = aim_get_subtypename(family, subtype);
+ offset += 2;
+ flags = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ id = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "SNAC data");
+ }
+
+ if( aim_tree )
+ {
+ offset = orig_offset;
+ ti1 = proto_tree_add_text(aim_tree, tvb, 6, 10, "FNAC");
+ aim_tree_fnac = proto_item_add_subtree(ti1, ett_aim_fnac);
+
+ proto_tree_add_text (aim_tree_fnac,
+ tvb, offset, 2, "Family: %s (0x%04x)", fam_name?fam_name:"Unknown", family);
+ offset += 2;
+
+ proto_tree_add_text (aim_tree_fnac,
+ tvb, offset, 2, "Subtype: %s (0x%04x)", subtype_name?subtype_name:"Unknown", subtype);
+ offset += 2;
+
+ proto_tree_add_uint(aim_tree_fnac, hf_aim_fnac_flags, tvb, offset,
+ 2, flags);
+ offset += 2;
+ proto_tree_add_uint(aim_tree_fnac, hf_aim_fnac_id, tvb, offset,
+ 4, id);
+ offset += 4;
+ }
+
+ subtvb = tvb_new_subset(tvb, offset, -1, -1);
+ aiminfo.tcpinfo = pinfo->private_data;
+ aiminfo.family = family;
+ aiminfo.subtype = subtype;
+ pinfo->private_data = &aiminfo;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if(fam_name) col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", fam_name);
+ else col_append_fstr(pinfo->cinfo, COL_INFO, ", Family: 0x%04x", family);
+ if(subtype_name) col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", subtype_name);
+ else col_append_fstr(pinfo->cinfo, COL_INFO, ", Subtype: 0x%04x", subtype);
+ }
+
+ if(tvb_length_remaining(tvb, offset) == 0 || !dissector_try_port(subdissector_table, family, subtvb, pinfo, root_tree)) {
+ /* Show the undissected payload */
+ if (tvb_length_remaining(tvb, offset) > 0)
+ proto_tree_add_item(aim_tree, hf_aim_data, tvb, offset, -1, FALSE);
+ }
+}
+
+static void dissect_aim_flap_err(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "FLAP error");
+ }
+
+ /* Show the undissected payload */
+ if (tvb_length_remaining(tvb, offset) > 0)
+ proto_tree_add_item(tree, hf_aim_data, tvb, offset, -1, FALSE);
+}
+
+static void dissect_aim_keep_alive(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Keep Alive");
+ }
+
+ /* Show the undissected payload */
+ if (tvb_length_remaining(tvb, offset) > 0)
+ proto_tree_add_item(tree, hf_aim_data, tvb, offset, -1, FALSE);
+}
+
+static void dissect_aim_close_conn(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Close Connection");
+ }
+
+ while(tvb_reported_length_remaining(tvb, offset) > 0) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
+ }
+}
+
+static void dissect_aim_unknown_channel(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown Channel");
+ }
+
+ /* Show the undissected payload */
+ if (tvb_length_remaining(tvb, offset) > 0)
+ proto_tree_add_item(tree, hf_aim_data, tvb, offset, -1, FALSE);
+}
+
+int dissect_aim_buddyname(tvbuff_t *tvb, packet_info *pinfo _U_, int offset,
+ proto_tree *tree)
+{
+ guint8 buddyname_length = 0;
+ char *buddyname;
+ proto_item *ti = NULL;
+ proto_tree *buddy_tree = NULL;
+
+ buddyname_length = tvb_get_guint8(tvb, offset);
+ offset++;
+ buddyname = tvb_get_string(tvb, offset, buddyname_length);
+
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, offset-1, 1+buddyname_length,
+ "Buddy: %s",
+ format_text(buddyname, buddyname_length));
+ buddy_tree = proto_item_add_subtree(ti, ett_aim_buddyname);
+ }
+
+ proto_tree_add_item(buddy_tree, hf_aim_buddyname_len, tvb, offset-1, 1, FALSE);
+ proto_tree_add_item(buddy_tree, hf_aim_buddyname, tvb, offset, buddyname_length, FALSE);
+ return offset+buddyname_length;
+}
+
+
+int dissect_aim_tlv_value_client_capabilities(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb)
+{
+ /* FIXME */
+ return tvb_length(tvb);
+}
+
+int dissect_aim_tlv_value_time(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb)
+{
+ /* FIXME */
+ return tvb_length(tvb);
+}
+
+int dissect_aim_userclass(tvbuff_t *tvb, int offset, int len, proto_item *ti, guint32 flags)
+{
+ proto_tree *entry;
+
+ entry = proto_item_add_subtree(ti, ett_aim_userclass);
+ proto_tree_add_boolean(entry, hf_aim_userclass_unconfirmed, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_administrator, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_aol, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_commercial, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_free, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_away, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_icq, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_wireless, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_unknown100, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_unknown200, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_unknown400, tvb, offset, len, flags);
+ proto_tree_add_boolean(entry, hf_aim_userclass_unknown800, tvb, offset, len, flags);
+ return offset+len;
+}
+
+int dissect_aim_tlv_value_userclass(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb)
+{
+ guint16 value16 = tvb_get_ntohs(tvb, 0);
+ proto_item_set_text(ti, "Value: 0x%04x", value16);
+ return dissect_aim_userclass(tvb, 0, 2, ti, value16);
+}
+
+static int dissect_aim_tlv_value_userstatus(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb)
+{
+ /* FIXME */
+ return tvb_length(tvb);
+}
+
+static int dissect_aim_tlv_value_dcinfo(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb)
+{
+ /* FIXME */
+ return tvb_length(tvb);
+}
+
+int dissect_aim_tlv_value_string (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb)
+{
+ guint8 *buf;
+ gint string_len;
+
+ string_len = tvb_length(tvb);
+ buf = tvb_get_string(tvb, 0, string_len);
+ proto_item_set_text(ti, "Value: %s", format_text(buf, string_len));
+ g_free(buf);
+ return string_len;
+}
+
+int dissect_aim_tlv_value_bytes (proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb _U_)
+{
+ return tvb_length(tvb);
+}
+
+int dissect_aim_tlv_value_uint8 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+ guint8 value8 = tvb_get_guint8(tvb, 0);
+ proto_item_set_text(ti, "Value: %d", value8);
+ return 1;
+}
+
+int dissect_aim_tlv_value_uint16 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+ guint16 value16 = tvb_get_ntohs(tvb, 0);
+ proto_item_set_text(ti, "Value: %d", value16);
+ return 2;
+}
+
+int dissect_aim_tlv_value_ipv4 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+ /* FIXME: Somewhat more readable format ? */
+ guint32 value32 = tvb_get_ntoh24(tvb, 0);
+ proto_item_set_text(ti, "Value: %d", value32);
+ return 4;
+}
+
+int dissect_aim_tlv_value_uint32 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+ guint32 value32 = tvb_get_ntoh24(tvb, 0);
+ proto_item_set_text(ti, "Value: %d", value32);
+ return 4;
+}
+
+int dissect_aim_tlv_value_messageblock (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+ proto_tree *entry;
+ guint8 *buf;
+ guint16 featurelen;
+ guint16 blocklen;
+ int offset=0;
+
+ /* Setup a new subtree */
+ entry = proto_item_add_subtree(ti, ett_aim_messageblock);
+
+ /* Features descriptor */
+ proto_tree_add_item(entry, hf_aim_messageblock_featuresdes, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ /* Features Length */
+ featurelen = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(entry, hf_aim_messageblock_featureslen, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ /* Features (should be expanded further @@@@@@@ ) */
+ proto_tree_add_item(entry, hf_aim_messageblock_features, tvb, offset,
+ featurelen, FALSE);
+ offset += featurelen;
+
+ /* There can be multiple messages in this message block */
+ while (tvb_length_remaining(tvb, offset) > 0) {
+ /* Info field */
+ proto_tree_add_item(entry, hf_aim_messageblock_info, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ /* Block length (includes charset and charsubset) */
+ blocklen = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(entry, hf_aim_messageblock_len, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ /* Character set */
+ proto_tree_add_item(entry, hf_aim_messageblock_charset, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ /* Character subset */
+ proto_tree_add_item(entry, hf_aim_messageblock_charsubset, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ /* The actual message */
+ buf = tvb_get_string(tvb, offset, blocklen - 4 );
+ proto_item_set_text(ti, "Message: %s",
+ format_text(buf, blocklen - 4));
+ proto_tree_add_item(entry, hf_aim_messageblock_message, tvb, offset,
+ blocklen-4,
+ FALSE);
+ offset += tvb_length_remaining(tvb, offset);
+ g_free(buf);
+ }
+
+ return offset;
+}
+
+/* Dissect a TLV value */
+int dissect_aim_tlv(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree, const aim_tlv *tlv)
+{
+ guint16 valueid;
+ guint16 length;
+ int i = 0;
+ const aim_tlv *tmp;
+ proto_item *ti1;
+ proto_tree *tlv_tree;
+ int orig_offset;
+
+ /* Record the starting offset so we can reuse it at the second pass */
+ orig_offset = offset;
+
+ /* Get the value ID */
+ valueid = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+
+ /* Figure out which entry applies from the tlv list */
+ tmp = tlv;
+ while (tmp[i].valueid) {
+ if (tmp[i].valueid == valueid) {
+ /* We found a match */
+ break;
+ }
+ i++;
+ }
+
+ /* At this point, we are either pointing at the correct record, or
+ we didn't find the record, and are pointing at the last item in the
+ list */
+
+ length = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ offset += length;
+
+ if (tree) {
+ offset = orig_offset;
+
+ ti1 = proto_tree_add_text(tree, tvb, offset, length + 4, "TLV: %s", tmp[i].desc);
+
+ tlv_tree = proto_item_add_subtree(ti1, ett_aim_tlv);
+
+ proto_tree_add_text(tlv_tree, tvb, offset, 2,
+ "Value ID: %s (0x%04x)", tmp[i].desc, valueid);
+ offset += 2;
+
+ proto_tree_add_text(tlv_tree, tvb, offset, 2,
+ "Length: %d", length);
+ offset += 2;
+
+ ti1 = proto_tree_add_text(tlv_tree, tvb, offset, length,
+ "Value");
+
+ if (tmp[i].dissector) {
+ tmp[i].dissector(ti1, valueid, tvb_new_subset(tvb, offset, length, length));
+ }
+
+ offset += length;
+ }
+
+ /* Return the new length */
+ return offset;
+}
+
+int dissect_aim_tlv_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree, const aim_tlv *tlv_table)
+{
+ guint16 i, tlv_count = tvb_get_ntohs(tvb, offset);
+
+ proto_tree_add_item(tree, hf_aim_tlvcount, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ for(i = 0; i < tlv_count; i++) {
+ offset = dissect_aim_tlv(tvb, pinfo, offset, tree, tlv_table);
+ }
+ return offset;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aim(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_aim_cmd_start,
+ { "Command Start", "aim.cmd_start", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_channel,
+ { "Channel ID", "aim.channel", FT_UINT8, BASE_HEX, VALS(aim_flap_channels), 0x0, "", HFILL }
+ },
+ { &hf_aim_seqno,
+ { "Sequence Number", "aim.seqno", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_authcookie,
+ { "Authentication Cookie", "aim.authcookie", FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_data_len,
+ { "Data Field Length", "aim.datalen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_data,
+ { "Data", "aim.data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_signon_challenge_len,
+ { "Signon challenge length", "aim.signon.challengelen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_signon_challenge,
+ { "Signon challenge", "aim.signon.challenge", FT_STRING, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_family,
+ { "FNAC Family ID", "aim.fnac.family", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_subtype,
+ { "FNAC Subtype ID", "aim.fnac.subtype", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_flags,
+ { "FNAC Flags", "aim.fnac.flags", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_fnac_id,
+ { "FNAC ID", "aim.fnac.id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_infotype,
+ { "Infotype", "aim.infotype", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_buddyname_len,
+ { "Buddyname len", "aim.buddynamelen", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_buddyname,
+ { "Buddy Name", "aim.buddyname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ { &hf_aim_tlvcount,
+ { "TLV Count", "aim.tlvcount", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_snac_error,
+ { "SNAC Error", "aim.snac.error", FT_UINT16,
+ BASE_HEX, VALS(aim_snac_errors), 0x0, "", HFILL },
+ },
+ { &hf_aim_userclass_unconfirmed,
+ { "AOL Unconfirmed user flag", "aim.userclass.unconfirmed", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_UNCONFIRMED, "", HFILL },
+ },
+ { &hf_aim_userclass_administrator,
+ { "AOL Administrator flag", "aim.userclass.administrator", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_ADMINISTRATOR, "", HFILL },
+ },
+ { &hf_aim_userclass_aol,
+ { "AOL Staff User Flag", "aim.userclass.staff", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_AOL, "", HFILL },
+ },
+ { &hf_aim_userclass_commercial,
+ { "AOL commercial account flag", "aim.userclass.commercial", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_COMMERCIAL, "", HFILL },
+ },
+ { &hf_aim_userclass_free,
+ { "ICQ non-commercial account flag", "aim.userclass.noncommercial", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_FREE, "", HFILL },
+ },
+ { &hf_aim_userclass_away,
+ { "AOL away status flag", "aim.userclass.away", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_AWAY, "", HFILL },
+ },
+ { &hf_aim_userclass_icq,
+ { "ICQ user sign", "aim.userclass.icq", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_ICQ, "", HFILL },
+ },
+ { &hf_aim_userclass_wireless,
+ { "AOL wireless user", "aim.userclass.wireless", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_WIRELESS, "", HFILL },
+ },
+ { &hf_aim_userclass_unknown100,
+ { "Unknown bit", "aim.userclass.unknown100", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_UNKNOWN100, "", HFILL },
+ },
+ { &hf_aim_userclass_unknown200,
+ { "Unknown bit", "aim.userclass.unknown200", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_UNKNOWN200, "", HFILL },
+ },
+ { &hf_aim_userclass_unknown400,
+ { "Unknown bit", "aim.userclass.unknown400", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_UNKNOWN400, "", HFILL },
+ },
+ { &hf_aim_userclass_unknown800,
+ { "Unknown bit", "aim.userclass.unknown800", FT_BOOLEAN, 32, TFS(&flags_set_truth), CLASS_UNKNOWN800, "", HFILL },
+ },
+ { &hf_aim_userinfo_warninglevel,
+ { "Warning Level", "aim.userinfo.warninglevel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_messageblock_featuresdes,
+ { "Features", "aim.messageblock.featuresdes", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_messageblock_featureslen,
+ { "Features Length", "aim.messageblock.featureslen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_messageblock_features,
+ { "Features", "aim.messageblock.features", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_messageblock_info,
+ { "Block info", "aim.messageblock.info", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_messageblock_len,
+ { "Block length", "aim.messageblock.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_messageblock_charset,
+ { "Block Character set", "aim.messageblock.charset", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_messageblock_charsubset,
+ { "Block Character subset", "aim.messageblock.charsubset", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+ },
+ { &hf_aim_messageblock_message,
+ { "Message", "aim.messageblock.message", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL },
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aim,
+ &ett_aim_fnac,
+ &ett_aim_tlv,
+ &ett_aim_buddyname,
+ &ett_aim_userclass,
+ &ett_aim_messageblock
+ };
+ module_t *aim_module;
+
+ /* Register the protocol name and description */
+ proto_aim = proto_register_protocol("AOL Instant Messenger", "AIM", "aim");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aim, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ aim_module = prefs_register_protocol(proto_aim, NULL);
+ prefs_register_bool_preference(aim_module, "desegment",
+ "Desegment all AIM messages spanning multiple TCP segments",
+ "Whether the AIM dissector should desegment all messages spanning multiple TCP segments",
+ &aim_desegment);
+
+ subdissector_table = register_dissector_table("aim.family",
+ "Family ID", FT_UINT16, BASE_HEX);
+}
+
+void
+proto_reg_handoff_aim(void)
+{
+ dissector_handle_t aim_handle;
+
+ aim_handle = new_create_dissector_handle(dissect_aim, proto_aim);
+ dissector_add("tcp.port", TCP_PORT_AIM, aim_handle);
+}
diff --git a/epan/dissectors/packet-aim.h b/epan/dissectors/packet-aim.h
new file mode 100644
index 0000000000..5848aba9c0
--- /dev/null
+++ b/epan/dissectors/packet-aim.h
@@ -0,0 +1,74 @@
+/* packet-tcp.h
+ * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_AIM_H__
+#define __PACKET_AIM_H__
+
+#define MAX_BUDDYNAME_LENGTH 30
+
+typedef struct _aim_tlv {
+ guint16 valueid;
+ char *desc;
+ int (*dissector) (proto_item *ti, guint16 value_id, tvbuff_t *tvb);
+} aim_tlv;
+
+struct aiminfo {
+ guint16 family;
+ guint16 subtype;
+ struct tcpinfo *tcpinfo;
+};
+
+void aim_init_family(guint16 family, const char *name, const value_string *subtypes);
+
+int dissect_aim_buddyname(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
+void aim_get_message( guchar *msg, tvbuff_t *tvb, int msg_offset, int msg_length);
+int aim_get_buddyname( char *name, tvbuff_t *tvb, int len_offset, int name_offset);
+int dissect_aim_userinfo(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
+
+int dissect_aim_snac_error(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *aim_tree);
+
+int dissect_aim_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree, const aim_tlv *);
+int dissect_aim_tlv_list(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree, const aim_tlv *);
+
+const char *aim_get_familyname( guint16 family );
+const char *aim_get_subtypename( guint16 family, guint16 subtype);
+
+int dissect_aim_tlv_value_string(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_tlv_value_uint8(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_tlv_value_uint16(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_tlv_value_uint32(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_tlv_value_bytes(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_tlv_value_ipv4(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_tlv_value_time(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_tlv_value_client_capabilities(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_userclass(tvbuff_t *tvb, int offset, int len, proto_item *ti, guint32 flags);
+int dissect_aim_tlv_value_userclass(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_tlv_value_messageblock (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb);
+
+extern const aim_tlv client_tlvs[];
+extern const aim_tlv onlinebuddy_tlvs[];
+extern const aim_tlv motd_tlvs[];
+
+#endif
diff --git a/epan/dissectors/packet-ajp13.c b/epan/dissectors/packet-ajp13.c
new file mode 100644
index 0000000000..3fe267b0da
--- /dev/null
+++ b/epan/dissectors/packet-ajp13.c
@@ -0,0 +1,877 @@
+/* packet-ajp13.c
+ * Routines for AJP13 dissection
+ * Copyright 2002, Christopher K. St. John <cks@distributopia.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "packet-tcp.h"
+
+
+
+/* IMPORTANT IMPLEMENTATION NOTES
+ *
+ * You need to be looking at: jk/doc/AJP13.html in the
+ * jakarta-tomcat-connectors repository.
+ *
+ * If you're an ethereal dissector guru, then you can skip the rest of
+ * this. I'm writing it all down because I've written 3 dissectors so
+ * far and every time I've forgotten it all and had to re-learn it
+ * from scratch. Not this time, damnit.
+ *
+ * Dissector routines get called in two phases:
+ *
+ * The first phase is an in-order traversal of every incoming
+ * frame. Since we know it's in-order, we can set up a "conversational
+ * state" that records context-sensitive stuff like "was there a
+ * content-length in the previous request". During this first pass
+ * through the data, the "tree" parameter might be null, or not. For
+ * the regular gui-based ethereal, it's null, which means we don't
+ * actually display the dissected data in the gui quite yet. For the
+ * text based interface, we might do the parsing and display both in
+ * this first pass.
+ *
+ * The second phase happens when the data is actually displayed. In
+ * this pase the "tree" param is non-null, so you've got a hook to
+ * hang the parsed-out display data on. Since there might be gigabytes
+ * worth of capture data, the display code only calls the dissector
+ * for the stuff the user actually clicks on. So you have to assume
+ * the dissector is getting called on random frames, you can't depend
+ * on ordering anymore.
+ *
+ * But some parts of the AJP13 capture stream are context sensitive.
+ * That's no big deal during the first in-order pass, but the second
+ * phase requires us to display any random frame correctly. So during
+ * the first in-order phase we create a per-frame user data structure
+ * and attach it to the frame using p_add_proto_data.
+ *
+ * Since AJP13 is a TCP/IP based protocol, writing a dissector for it
+ * requires addressing several other issues:
+ *
+ * 1) TCP/IP segments can get retransmitted or be sent out of
+ * order. Users don't normally care, because the low-level kernel
+ * networking code takes care of reassembling them properly. But we're
+ * looking at raw network packets, aren't we? The stuff on the
+ * wire. Ethereal has been getting better and better at helping
+ * dissectors with this. I'm a little fuzzy on the details, but my
+ * uderstanding is that ethereal now contains a fairly substantial
+ * user-space TCP/IP stack so it can re-assemble the data. But I might
+ * be wrong. Since AJP13 is going to be used either on the loopback
+ * interface or on a LAN, it isn't likely to be a big issues anyway.
+ *
+ * 2) AJP13 packets (PDU's or protocol data unit's in
+ * networking-speak) don't necessarily line up with TCP segments. That
+ * is, one TCP segment can have more than one AJP13 PDU, or one AJP13
+ * PDU can stretch across multiple TCP segments. Assembling them is
+ * obviously possible, but a royal pain. During the "phase one"
+ * in-order pass you have to keep track of a bunch of offsets and
+ * store which PDU goes with which TCP segment. Luckly, recent
+ * (0.9.4+) versions of ethereal provide the "tcp_dissect_pdus()"
+ * function that takes care of much of the work. See the comments in
+ * packet-tcp.c, the example code in packet-dns.c, or check the
+ * ethereal-dev archives for details.
+ *
+ * 3) Ethereal isn't guaranteed to see all the data. I'm a little
+ * unclear on all the possible failure modes, but it comes down to: a)
+ * Not your fault: it's an imperfect world, we're eavesdroppers, and
+ * stuff happens. We might totally miss packets or get garbled
+ * data. Or b) Totally your fault: you turn on the capture during the
+ * middle of an AJP13 conversation and the capture starts out with
+ * half an AJP13 PDU. This code doesn't currently handle either case
+ * very well, but you can get arbitrarily clever. Like: put in tests
+ * to see if this packet has reasonable field values, and if it
+ * doesn't, walk the offset ahead until we see a matching magic number
+ * field, then re-test. But we don't do that now, and since we're
+ * using tcp_dissect_pdu's, I'm not sure how to do it.
+ *
+ */
+
+
+/*
+ * Request/response header codes. Common headers are stored as ints in
+ * an effort to improve performance. Why can't we just have one big
+ * list?
+ */
+
+static const value_string req_header_codes[] = {
+ { 0x01, "accept" },
+ { 0x02, "accept-charset" },
+ { 0x03, "accept-encoding" },
+ { 0x04, "accept-language" },
+ { 0x05, "authorization" },
+ { 0x06, "connection" },
+ { 0x07, "content-type" },
+ { 0x08, "content-length" },
+ { 0x09, "cookie" },
+ { 0x0A, "cookie2" },
+ { 0x0B, "host" },
+ { 0x0C, "pragma" },
+ { 0x0D, "referer" },
+ { 0x0E, "user-agent" },
+};
+
+
+static const value_string rsp_header_codes[] = {
+ { 0x01, "Content-Type" },
+ { 0x02, "Content-Language" },
+ { 0x03, "Content-Length" },
+ { 0x04, "Date" },
+ { 0x05, "Last-Modified" },
+ { 0x06, "Location" },
+ { 0x07, "Set-Cookie" },
+ { 0x08, "Set-Cookie2" },
+ { 0x09, "Servlet-Engine" },
+ { 0x0A, "Status" },
+ { 0x0B, "WWW-Authenticate" },
+};
+
+
+static const value_string mtype_codes[] = {
+ { 0, "BAD" },
+ { 1, "BAD" },
+ { 2, "FORWARD REQUEST" },
+ { 3, "SEND BODY CHUNK" },
+ { 4, "SEND HEADERS" },
+ { 5, "END RESPONSE" },
+ { 6, "GET BODY CHUNK" },
+ { 7, "SHUTDOWN" },
+};
+
+
+static const value_string http_method_codes[] = {
+ { 1, "OPTIONS" },
+ { 2, "GET" },
+ { 3, "HEAD" },
+ { 4, "POST" },
+ { 5, "PUT" },
+ { 6, "DELETE" },
+ { 7, "TRACE" },
+ { 8, "PROPFIND" },
+ { 9, "PROPPATCH" },
+ { 10, "MKCOL" },
+ { 11, "COPY" },
+ { 12, "MOVE" },
+ { 13, "LOCK" },
+ { 14, "UNLOCK" },
+ { 15, "ACL" },
+ { 16, "REPORT" },
+ { 17, "VERSION-CONTROL" },
+ { 18, "CHECKIN" },
+ { 19, "CHECKOUT" },
+ { 20, "UNCHECKOUT" },
+ { 21, "SEARCH" },
+};
+
+
+
+static int proto_ajp13 = -1;
+static int hf_ajp13_magic = -1;
+static int hf_ajp13_len = -1;
+static int hf_ajp13_code = -1;
+static int hf_ajp13_method = -1;
+static int hf_ajp13_ver = -1;
+static int hf_ajp13_uri = -1;
+static int hf_ajp13_raddr = -1;
+static int hf_ajp13_rhost = -1;
+static int hf_ajp13_srv = -1;
+static int hf_ajp13_port = -1;
+static int hf_ajp13_sslp = -1;
+static int hf_ajp13_nhdr = -1;
+static int hf_ajp13_hname = -1;
+static int hf_ajp13_hval = -1;
+static int hf_ajp13_rlen = -1;
+static int hf_ajp13_reusep = -1;
+static int hf_ajp13_rstatus= -1;
+static int hf_ajp13_rsmsg = -1;
+static int hf_ajp13_data = -1;
+static gint ett_ajp13 = -1;
+
+
+typedef struct ajp13_conv_data {
+ int content_length;
+ gboolean was_get_body_chunk; /* XXX - not used */
+} ajp13_conv_data;
+
+static GMemChunk *ajp13_conv_data_chunk = NULL;
+
+typedef struct ajp13_frame_data {
+ gboolean is_request_body;
+} ajp13_frame_data;
+
+static GMemChunk *ajp13_frame_data_chunk = NULL;
+
+static int ajp13_packet_init_count = 100;
+
+/* ajp13, in sort of a belt-and-suspenders move, encodes strings with
+ * both a leading length field, and a trailing null. Mostly, see
+ * AJPv13.html. The returned length _includes_ the trailing null, if
+ * there is one.
+ *
+ * XXX - is there a tvbuff routine to handle this?
+ */
+static guint16
+get_nstring(tvbuff_t *tvb, gint offset, guint8* cbuf, size_t cbuflen)
+{
+ guint16 len;
+ guint16 copylen;
+
+ len = tvb_get_ntohs(tvb, offset);
+
+ if (len == 0xffff) {
+ cbuf[0] = '\0';
+ len = 0;
+ } else {
+ copylen = len;
+ if (copylen > cbuflen - 1)
+ copylen = cbuflen - 1;
+ tvb_memcpy(tvb, cbuf, offset+2, copylen);
+ cbuf[copylen] = '\0';
+ len++;
+ }
+ return len;
+}
+
+
+
+/* dissect a response. more work to do here.
+ */
+static void
+display_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ajp13_tree)
+{
+ gchar* msg_code = NULL;
+ int pos = 0;
+ guint8 mcode = 0;
+ char mcode_buf[1024];
+ int i;
+
+ /* MAGIC
+ */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, 0);
+ pos+=2;
+
+ /* PDU LENGTH
+ */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, 0);
+ pos+=2;
+
+ /* MESSAGE TYPE CODE
+ */
+ mcode = tvb_get_guint8(tvb, pos);
+ msg_code = val_to_str(mcode, mtype_codes, "UNKNOWN");
+ sprintf(mcode_buf, "(%d) %s", mcode, msg_code);
+ if (ajp13_tree)
+ proto_tree_add_string(ajp13_tree, hf_ajp13_code, tvb, pos, 1, mcode_buf);
+ pos+=1;
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, msg_code);
+
+ if (mcode == 5) {
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_reusep, tvb, pos, 1, 0);
+ pos+=1;
+
+ } else if (mcode == 4) {
+
+ guint8 rsmsg_bytes[8*1024]; /* DANGER WILL ROBINSON */
+ guint16 rsmsg_len;
+ guint16 nhdr;
+ guint16 rcode_num;
+
+ /* HTTP RESPONSE STATUS CODE
+ */
+ rcode_num = tvb_get_ntohs(tvb, pos);
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_rstatus, tvb, pos, 2, 0);
+ pos+=2;
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ":%d", rcode_num);
+
+ /* HTTP RESPONSE STATUS MESSAGE
+ */
+ rsmsg_len = get_nstring(tvb, pos, rsmsg_bytes, sizeof rsmsg_bytes);
+ pos+=2;
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_rsmsg, tvb, pos, rsmsg_len, 0);
+ pos+=rsmsg_len;
+ /* dangerous assumption that we can just %s out raw bytes */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", rsmsg_bytes);
+
+ /* NUMBER OF HEADERS
+ */
+ nhdr = tvb_get_ntohs(tvb, pos);
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, 0);
+ pos+=2;
+
+ /* HEADERS
+ */
+ for(i=0; i<nhdr; i++) {
+
+ guint8 hcd;
+ guint8 hid;
+ char hval[8192];
+ guint16 hval_len;
+ int orig_pos = pos;
+ gchar* hname = NULL;
+ int dp = 0;
+ int cl = 0;
+ guint8 hname_bytes[1024];
+ gchar hname_value[8*1024];
+
+ /* HEADER CODE/NAME
+ */
+ hcd = tvb_get_guint8(tvb, pos);
+
+ if (hcd == 0xA0) {
+ pos+=1;
+ hid = tvb_get_guint8(tvb, pos);
+ pos+=1;
+
+ hname = val_to_str(hid, rsp_header_codes, "UNKNOWN");
+ /* Content-Length header (encoded by 0x08) is special */
+ if (hid == 0x08)
+ cl = 1;
+ } else {
+ int hname_len = get_nstring(tvb, pos, hname_bytes, sizeof hname_bytes);
+
+ pos+=hname_len+2;
+ hname = (gchar*)hname_bytes; /* VERY EVIL */
+ }
+
+ dp = pos-orig_pos;
+
+ /* HEADER VALUE
+ */
+ orig_pos = pos;
+ hval_len = get_nstring(tvb, pos, hval, sizeof hval);
+
+ pos+=hval_len+2;
+ dp = pos - orig_pos;
+ if (ajp13_tree) {
+ sprintf(hname_value, "%s : %s", hname, hval);
+ proto_tree_add_string(ajp13_tree, hf_ajp13_hval, tvb, orig_pos, dp, hname_value);
+ }
+ }
+
+ } else if (mcode == 6) {
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_rlen, tvb, pos, 2, 0);
+ pos+=2;
+
+ } else {
+ /* MESSAGE DATA (COPOUT)
+ */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_data, tvb, pos+2, -1, 0);
+ }
+}
+
+
+
+/* dissect a request body. see AJPv13.html, but the idea is that these
+ * packets, unlike all other packets, have no type field. you just
+ * sort of have to know that they're coming based on the previous
+ * packets.
+ */
+static void
+display_req_body(tvbuff_t *tvb, proto_tree *ajp13_tree)
+{
+ /*printf("ajp13:display_req_body()\n");*/
+
+ if (ajp13_tree) {
+
+ guint8 body_bytes[128*1024]; /* DANGER WILL ROBINSON */
+ int pos = 0;
+ guint16 body_len;
+
+ /* MAGIC
+ */
+ proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, 0);
+ pos+=2;
+
+ /* PACKET LENGTH
+ */
+ proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, 0);
+ pos+=2;
+
+ /* BODY (AS STRING)
+ */
+ body_len = get_nstring(tvb, pos, body_bytes, sizeof body_bytes);
+ proto_tree_add_item(ajp13_tree, hf_ajp13_data, tvb, pos+2, body_len-1, 0);
+ }
+}
+
+
+
+/* note that even if ajp13_tree is null on the first pass, we still
+ * need to dissect the packet in order to determine if there is a
+ * content-length, and thus if there is a subsequent automatic
+ * request-body transmitted in the next request packet. if there is a
+ * content-length, we record the fact in the conversation context.
+ * ref the top of this file for comments explaining the multi-pass
+ * thing.
+*/
+static void
+display_req_forward(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *ajp13_tree,
+ ajp13_conv_data* cd)
+{
+ int pos = 0;
+ guint8 meth;
+ guint8 cod;
+ guint8 ver[1024];
+ guint16 ver_len;
+ guint8 uri[4096];
+ guint16 uri_len;
+ guint8 raddr[4096];
+ guint16 raddr_len;
+ guint8 rhost[4096];
+ guint16 rhost_len;
+ guint8 srv[4096];
+ guint16 srv_len;
+ guint nhdr;
+ guint i;
+
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, 0);
+ pos+=2;
+
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, 0);
+ pos+=2;
+
+ /* PACKET CODE
+ */
+ cod = tvb_get_guint8(tvb, 4);
+ if (ajp13_tree) {
+ gchar* msg_code = NULL;
+ char mcode_buf[1024];
+ msg_code = val_to_str(cod, mtype_codes, "UNKNOWN");
+ sprintf(mcode_buf, "(%d) %s", cod, msg_code);
+ proto_tree_add_string(ajp13_tree, hf_ajp13_code, tvb, pos, 1, mcode_buf);
+ }
+ pos+=1;
+
+ /* HTTP METHOD (ENCODED AS INTEGER)
+ */
+ {
+ gchar* meth_code = NULL;
+ meth = tvb_get_guint8(tvb, pos);
+ meth_code = val_to_str(meth, http_method_codes, "UNKNOWN");
+ if (ajp13_tree) {
+ char mcode_buf[1024];
+ sprintf(mcode_buf, "(%d) %s", meth, meth_code);
+ proto_tree_add_string(ajp13_tree, hf_ajp13_method, tvb, pos, 1, mcode_buf);
+ }
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, meth_code);
+ pos+=1;
+ }
+
+ /* HTTP VERSION STRING
+ */
+ ver_len = get_nstring(tvb, pos, ver, sizeof ver);
+ pos+=2; /* skip over size */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_ver, tvb, pos, ver_len, 0);
+ pos=pos+ver_len; /* skip over chars + trailing null */
+
+ /* URI
+ */
+ uri_len = get_nstring(tvb, pos, uri, sizeof uri);
+ pos+=2; /* skip over size */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_uri, tvb, pos, uri_len, 0);
+ pos=pos+uri_len; /* skip over chars + trailing null */
+
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s %s", uri, ver);
+
+
+ /* REMOTE ADDRESS
+ */
+ raddr_len = get_nstring(tvb, pos, raddr, sizeof raddr);
+ pos+=2; /* skip over size */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_raddr, tvb, pos, raddr_len, 0);
+ pos=pos+raddr_len; /* skip over chars + trailing null */
+
+ /* REMOTE HOST
+ */
+ rhost_len = get_nstring(tvb, pos, rhost, sizeof rhost);
+ pos+=2; /* skip over size */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_rhost, tvb, pos, rhost_len, 0);
+ pos=pos+rhost_len; /* skip over chars + trailing null */
+
+ /* SERVER NAME
+ */
+ srv_len = get_nstring(tvb, pos, srv, sizeof srv);
+ pos+=2; /* skip over size */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_srv, tvb, pos, srv_len, 0);
+ pos=pos+srv_len; /* skip over chars + trailing null */
+
+ /* SERVER PORT
+ */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_port, tvb, pos, 2, 0);
+ pos+=2;
+
+ /* IS SSL?
+ */
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_sslp, tvb, pos, 1, 0);
+ pos+=1;
+
+ /* NUM HEADERS
+ */
+ nhdr = tvb_get_ntohs(tvb, pos);
+
+ if (ajp13_tree)
+ proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, 0);
+ pos+=2;
+ cd->content_length = 0;
+
+ /* HEADERS
+ */
+ for(i=0; i<nhdr; i++) {
+
+ guint8 hcd;
+ guint8 hid;
+ char hval[8192];
+ guint16 hval_len;
+ int orig_pos = pos;
+ gchar* hname = NULL;
+ int dp = 0;
+ int cl = 0;
+ guint8 hname_bytes[1024];
+
+ /* HEADER CODE/NAME
+ */
+ hcd = tvb_get_guint8(tvb, pos);
+
+ if (hcd == 0xA0) {
+ pos+=1;
+ hid = tvb_get_guint8(tvb, pos);
+ pos+=1;
+
+ hname = val_to_str(hid, req_header_codes, "UNKNOWN");
+ if (hid == 0x08)
+ cl = 1;
+ } else {
+ int hname_len = get_nstring(tvb, pos, hname_bytes, sizeof hname_bytes);
+
+ pos+=hname_len+2;
+ hname = (gchar*)hname_bytes; /* VERY EVIL */
+ }
+
+ dp = pos-orig_pos;
+
+ /* HEADER VALUE
+ */
+ orig_pos = pos;
+ hval_len = get_nstring(tvb, pos, hval, sizeof hval);
+
+ pos+=hval_len+2;
+ dp = pos - orig_pos;
+ if (ajp13_tree) {
+ proto_tree_add_string_format(ajp13_tree, hf_ajp13_hval,
+ tvb, orig_pos, dp, hname,
+ "%s: %s", hname, hval);
+ }
+ if (cl) {
+ cl = atoi(hval);
+ cd->content_length = cl;
+ }
+ }
+}
+
+
+
+/* main dissector function. ethereal calls it for segments in both
+ * directions.
+ */
+static void
+dissect_ajp13_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 mag;
+ guint16 len;
+ conversation_t *conv = NULL;
+ ajp13_conv_data *cd = NULL;
+ proto_tree *ajp13_tree = NULL;
+ ajp13_frame_data* fd = NULL;
+
+ /* conversational state really only does us good during the first
+ * in-order traversal
+ */
+ conv = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (!conv) {
+ conv = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+ cd = (ajp13_conv_data*)conversation_get_proto_data(conv, proto_ajp13);
+ if (!cd) {
+ cd = (ajp13_conv_data*)g_mem_chunk_alloc(ajp13_conv_data_chunk);
+ cd->content_length = 0;
+ cd->was_get_body_chunk = FALSE;
+ conversation_add_proto_data(conv, proto_ajp13, cd);
+ }
+
+ /* we use the per segment user data to record the conversational
+ * state for use later on when we're called out of order (see
+ * comments at top of this file)
+ */
+ fd = (ajp13_frame_data*)p_get_proto_data(pinfo->fd, proto_ajp13);
+ if (!fd) {
+ /*printf("ajp13:dissect_ajp13_common():no frame data, adding");*/
+ /* since there's no per-packet user data, this must be the first
+ * time we've see the packet, and it must be the first "in order"
+ * pass through the data.
+ */
+ fd = (ajp13_frame_data*)g_mem_chunk_alloc(ajp13_frame_data_chunk);
+ p_add_proto_data(pinfo->fd, proto_ajp13, fd);
+ fd->is_request_body = FALSE;
+ if (cd->content_length) {
+ /* this is screwy, see AJPv13.html. the idea is that if the
+ * request has a body (as determined by the content-length
+ * header), then there's always an immediate follow-up PDU with
+ * no GET_BODY_CHUNK from the container.
+ */
+ fd->is_request_body = TRUE;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ mag = tvb_get_ntohs(tvb, 0);
+ len = tvb_get_ntohs(tvb, 2);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AJP13");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (mag == 0x1234 && !fd->is_request_body)
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%d:REQ:", conv->index);
+ else if (mag == 0x1234 && fd->is_request_body)
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%d:REQ:Body", conv->index);
+ else if (mag == 0x4142)
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%d:RSP:", conv->index);
+ else
+ col_set_str(pinfo->cinfo, COL_INFO, "AJP13 Error?");
+ }
+
+ if (tree) {
+ proto_item *ti;
+ ti = proto_tree_add_item(tree, proto_ajp13, tvb, 0, tvb_length(tvb), FALSE);
+ ajp13_tree = proto_item_add_subtree(ti, ett_ajp13);
+ }
+
+ if (mag == 0x1234) {
+
+ if (fd->is_request_body)
+ display_req_body(tvb, ajp13_tree);
+ else
+ display_req_forward(tvb, pinfo, ajp13_tree, cd);
+
+ } else if (mag == 0x4142) {
+
+ display_rsp(tvb, pinfo, ajp13_tree);
+
+ }
+}
+
+
+
+/* given the first chunk of the AJP13 pdu, extract out and return the
+ * packet length. see comments in packet-tcp.c:tcp_dissect_pdus().
+ */
+static guint
+get_ajp13_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint16 magic;
+ guint16 plen;
+ magic = tvb_get_ntohs(tvb, offset);
+ plen = tvb_get_ntohs(tvb, offset+2);
+ plen += 4;
+ return plen;
+}
+
+
+
+/* Code to actually dissect the packets.
+ */
+static void
+dissect_ajp13(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it
+ */
+ tcp_dissect_pdus(tvb, pinfo, tree,
+ TRUE, /* desegment or not */
+ 4, /* magic + length */
+ get_ajp13_pdu_len, /* use first 4, calc data len */
+ dissect_ajp13_tcp_pdu); /* the naive dissector */
+}
+
+
+
+static void
+ajp13_init_protocol(void)
+{
+ if (ajp13_conv_data_chunk)
+ g_mem_chunk_destroy(ajp13_conv_data_chunk);
+ if (ajp13_frame_data_chunk)
+ g_mem_chunk_destroy(ajp13_frame_data_chunk);
+
+ ajp13_conv_data_chunk = g_mem_chunk_new("ajp13_conv_data_chunk",
+ sizeof(ajp13_conv_data),
+ ajp13_packet_init_count * sizeof(ajp13_conv_data),
+ G_ALLOC_ONLY);
+
+ ajp13_frame_data_chunk = g_mem_chunk_new("ajp13_frame_data_chunk",
+ sizeof(ajp13_frame_data),
+ ajp13_packet_init_count * sizeof(ajp13_frame_data),
+ G_ALLOC_ONLY);
+}
+
+void
+proto_register_ajp13(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ajp13_magic,
+ { "Magic", "ajp13.magic", FT_BYTES, BASE_HEX, NULL, 0x0, "Magic Number",
+ HFILL }
+ },
+ { &hf_ajp13_len,
+ { "Length", "ajp13.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Data Length",
+ HFILL }
+ },
+ { &hf_ajp13_code,
+ { "Code", "ajp13.code", FT_STRING, BASE_DEC, NULL, 0x0, "Type Code",
+ HFILL }
+ },
+ { &hf_ajp13_method,
+ { "Method", "ajp13.method", FT_STRING, BASE_DEC, NULL, 0x0, "HTTP Method",
+ HFILL }
+ },
+ { &hf_ajp13_ver,
+ { "Version", "ajp13.ver", FT_STRING, BASE_DEC, NULL, 0x0, "HTTP Version",
+ HFILL }
+ },
+ { &hf_ajp13_uri,
+ { "URI", "ajp13.uri", FT_STRING, BASE_DEC, NULL, 0x0, "HTTP URI",
+ HFILL }
+ },
+ { &hf_ajp13_raddr,
+ { "RADDR", "ajp13.raddr", FT_STRING, BASE_DEC, NULL, 0x0, "Remote Address",
+ HFILL }
+ },
+ { &hf_ajp13_rhost,
+ { "RHOST", "ajp13.rhost", FT_STRING, BASE_DEC, NULL, 0x0, "Remote Host",
+ HFILL }
+ },
+ { &hf_ajp13_srv,
+ { "SRV", "ajp13.srv", FT_STRING, BASE_DEC, NULL, 0x0, "Server",
+ HFILL }
+ },
+ { &hf_ajp13_port,
+ { "PORT", "ajp13.port", FT_UINT16, BASE_DEC, NULL, 0x0, "Port",
+ HFILL }
+ },
+ { &hf_ajp13_sslp,
+ { "SSLP", "ajp13.sslp", FT_UINT8, BASE_DEC, NULL, 0x0, "Is SSL?",
+ HFILL }
+ },
+ { &hf_ajp13_nhdr,
+ { "NHDR", "ajp13.nhdr", FT_UINT16, BASE_DEC, NULL, 0x0, "Num Headers",
+ HFILL }
+ },
+ { &hf_ajp13_hname,
+ { "HNAME", "ajp13.hname", FT_STRING, BASE_DEC, NULL, 0x0, "Header Name",
+ HFILL }
+ },
+ { &hf_ajp13_hval,
+ { "HVAL", "ajp13.hval", FT_STRING, BASE_DEC, NULL, 0x0, "Header Value",
+ HFILL }
+ },
+ { &hf_ajp13_rlen,
+ { "RLEN", "ajp13.rlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Requested Length",
+ HFILL }
+ },
+ { &hf_ajp13_reusep,
+ { "REUSEP", "ajp13.reusep", FT_UINT8, BASE_DEC, NULL, 0x0, "Reuse Connection?",
+ HFILL }
+ },
+ { &hf_ajp13_rstatus,
+ { "RSTATUS", "ajp13.rstatus", FT_UINT16, BASE_DEC, NULL, 0x0, "HTTP Status Code",
+ HFILL }
+ },
+ { &hf_ajp13_rsmsg,
+ { "RSMSG", "ajp13.rmsg", FT_STRING, BASE_DEC, NULL, 0x0, "HTTP Status Message",
+ HFILL }
+ },
+ { &hf_ajp13_data,
+ { "Data", "ajp13.data", FT_STRING, BASE_DEC, NULL, 0x0, "Data",
+ HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_ajp13,
+ };
+
+ /* Register the protocol name and description
+ */
+ proto_ajp13 = proto_register_protocol("Apache JServ Protocol v1.3", "AJP13", "ajp13");
+
+ proto_register_field_array(proto_ajp13, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine(&ajp13_init_protocol);
+}
+
+
+
+void
+proto_reg_handoff_ajp13(void)
+{
+ dissector_handle_t ajp13_handle;
+ ajp13_handle = create_dissector_handle(dissect_ajp13, proto_ajp13);
+ dissector_add("tcp.port", 8009, ajp13_handle);
+}
diff --git a/epan/dissectors/packet-alcap.c b/epan/dissectors/packet-alcap.c
new file mode 100644
index 0000000000..92a4eb11c1
--- /dev/null
+++ b/epan/dissectors/packet-alcap.c
@@ -0,0 +1,1774 @@
+/* packet-alcap.c
+ * Routines for ALCAP (Q.2630.1) dissection
+ * AAL type 2 signalling protocol - Capability set 1
+ * 12/1999
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gmodule.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <string.h>
+
+#include "epan/packet.h"
+
+
+#define ALCAP_MSG_HEADER_LEN 6
+#define ALCAP_PARM_HEADER_LEN 3
+
+#define ALCAP_SI 12
+
+#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
+ if ((edc_len) > (edc_max_len)) \
+ { \
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb, \
+ curr_offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
+ }
+
+#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
+ if ((sdc_len) < (sdc_min_len)) \
+ { \
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb, \
+ curr_offset, (sdc_len), "Short Data (?)"); \
+ return; \
+ }
+
+#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
+ if ((edc_len) != (edc_eq_len)) \
+ { \
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb, \
+ curr_offset, (edc_len), "Unexpected Data Length"); \
+ return; \
+ }
+
+static const value_string msg_parm_strings[] = {
+ { 1, "Cause (CAU)" },
+ { 2, "Connection element identifier (CEID)" },
+ { 3, "Destination E.164 service endpoint address (ESEA)" },
+ { 4, "Destination NSAP service endpoint address (NSEA)" },
+ { 5, "Link characteristics (ALC)" },
+ { 6, "Originating signalling association identifier (OSAID)" },
+ { 7, "Served user generated reference (SUGR)" },
+ { 8, "Served user transport (SUT)" },
+ { 9, "Service specific information (audio) (SSIA)" },
+ { 10, "Service specific information (multirate) (SSIM)" },
+ { 11, "Service specific information (SAR-assured) (SSISA)" },
+ { 12, "Service specific information (SAR-unassured) (SSISU)" },
+ { 13, "Test connection identifier (TCI)" },
+ { 0, NULL },
+};
+#define NUM_PARMS (sizeof(msg_parm_strings)/sizeof(value_string))
+
+static char *alcap_proto_name = "AAL type 2 signalling protocol - Capability set 1 (Q.2630.1)";
+static char *alcap_proto_name_short = "ALCAP";
+
+/* Initialize the subtree pointers */
+static gint ett_alcap = -1;
+static gint ett_parm = -1;
+
+/* Initialize the protocol and registered fields */
+static int proto_alcap = -1;
+static int hf_alcap_msg_type = -1;
+static int hf_alcap_length = -1;
+static int hf_alcap_parm_id = -1;
+static int hf_alcap_none = -1;
+static int hf_alcap_dsaid = -1;
+static int hf_alcap_osaid = -1;
+static int hf_alcap_aal2_path_id = -1;
+static int hf_alcap_channel_id = -1;
+static int hf_alcap_organizational_unique_id = -1;
+static int hf_alcap_served_user_gen_ref = -1;
+static int hf_alcap_nsap_address = -1;
+
+static char bigbuf[1024];
+static char bigbuf2[1024];
+static dissector_handle_t data_handle;
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
+
+#define FIELD_COMPATIBILITY 0
+#define FIELD_SIGNALLING_ASSOC_ID 1
+#define FIELD_AAL2_PATH_ID 2
+#define FIELD_CHANNEL_ID 3
+#define FIELD_ORGANIZATIONAL_UNIQUE_ID 4
+#define FIELD_AUDIO_SERVICE 5
+#define FIELD_MULTIRATE_SERVICE 6
+#define FIELD_SEG_REASSEMBLY_ASS 7
+#define FIELD_SEG_REASSEMBLY_UNASS 8
+#define FIELD_SERVED_USER_GEN_REF 9
+#define FIELD_MAX_CPS_SDU_BIT_RATE 10
+#define FIELD_AVG_CPS_SDU_BIT_RATE 11
+#define FIELD_MAX_CPS_SDU_SIZE 12
+#define FIELD_AVG_CPS_SDU_SIZE 13
+#define FIELD_NATURE_OF_ADDRESS 14
+#define FIELD_E164_ADDRESS 15
+#define FIELD_NSAP_ADDRESS 16
+#define FIELD_CAUSE_VALUE 17
+#define FIELD_DIAGNOSTICS 18
+#define FIELD_SERVED_USER_TRANSPORT 19
+static const char * field_strings[] = {
+ "Compatibility",
+ "Signalling association identifier",
+ "AAL type 2 path identifier",
+ "Channel identifier (CID)",
+ "Organizational unique identifier (OUI)",
+ "Audio service",
+ "Multirate service",
+ "Segmentation and reassembly (assured data transfer)",
+ "Segmentation and reassembly (unassured data transfer)",
+ "Served user generated reference",
+ "Maximum CPS-SDU bit rate",
+ "Average CPS-SDU bit rate",
+ "Maximum CPS-SDU size",
+ "Average CPS-SDU size",
+ "Nature of address",
+ "E.164 address",
+ "NSAP address",
+ "Cause value",
+ "Diagnostics",
+ "Served user transport"
+};
+#define NUM_FIELDS (sizeof(field_strings)/sizeof(char *))
+static gint ett_fields[NUM_FIELDS];
+
+static const value_string msg_type_strings[] = {
+ { 1, "Block confirm (BLC)" },
+ { 2, "Block request (BLO)" },
+ { 3, "Confusion (CFN)" },
+ { 4, "Establish confirm (ECF)" },
+ { 5, "Establish request (ERQ)" },
+ { 6, "Release confirm (RLC)" },
+ { 7, "Release request (REL)" },
+ { 8, "Reset confirm (RSC)" },
+ { 9, "Reset request (RES)" },
+ { 10, "Unblock confirm (UBC)" },
+ { 11, "Unblock request (UBL)" },
+ { 0, NULL },
+};
+
+/* FUNCTIONS */
+
+static gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr) {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.1
+ */
+static void
+dis_field_compatibility(tvbuff_t *tvb, proto_tree *tree, guint32 *offset, gboolean message)
+{
+ guint32 curr_offset;
+ guint8 compat;
+ proto_item *item;
+ proto_tree *subtree;
+ gchar *str = NULL;
+
+ curr_offset = *offset;
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, 1, "%s %s",
+ message ? "Message" : "Parameter",
+ field_strings[FIELD_COMPATIBILITY]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_COMPATIBILITY]);
+
+ compat = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(bigbuf, compat, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, compat, 0x40, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Pass-on not possible - %s",
+ bigbuf,
+ (compat & 0x40) ? "Send notification" : "Do not send notification");
+
+ switch ((compat & 0x30) >> 4)
+ {
+ case 0x00:
+ str = "Pass on message or parameter (Release connection)";
+ break;
+
+ case 0x01:
+ if (message)
+ {
+ str = "Discard parameter (Discard message)";
+ }
+ else
+ {
+ str = "Discard parameter";
+ }
+ break;
+
+ case 0x02:
+ str = "Discard message";
+ break;
+
+ case 0x03:
+ str = "Release connection";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, compat, 0x30, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Pass-on not possible, instruction - %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, compat, 0x08, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, compat, 0x04, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : General action - %s",
+ bigbuf,
+ (compat & 0x04) ? "Send notification" : "Do not send notification");
+
+ switch (compat & 0x03)
+ {
+ case 0x00:
+ str = "Pass on message or parameter";
+ break;
+
+ case 0x01:
+ if (message)
+ {
+ str = "Discard parameter (Discard message)";
+ }
+ else
+ {
+ str = "Discard parameter";
+ }
+ break;
+
+ case 0x02:
+ str = "Discard message";
+ break;
+
+ case 0x03:
+ str = "Release connection";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, compat, 0x03, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : General action, instruction - %s",
+ bigbuf,
+ str);
+
+ *offset += 1;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.2
+ */
+static void
+dis_field_signalling_assoc_id(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset, gboolean destination)
+{
+ guint32 curr_offset;
+ guint32 value;
+
+ curr_offset = *offset;
+
+#define FIELD_SIGNALLING_ASSOC_ID_LEN 4
+
+ SHORT_DATA_CHECK(*len, FIELD_SIGNALLING_ASSOC_ID_LEN);
+
+ value = tvb_get_ntohl(tvb, curr_offset);
+
+ if (destination)
+ {
+ proto_tree_add_uint_format(tree, hf_alcap_dsaid, tvb,
+ curr_offset, FIELD_SIGNALLING_ASSOC_ID_LEN, value,
+ "Destination signalling association identifier: %d%s",
+ value,
+ value ? "" : " (unknown)");
+ }
+ else
+ {
+ proto_tree_add_uint(tree, hf_alcap_osaid, tvb,
+ curr_offset, FIELD_SIGNALLING_ASSOC_ID_LEN, value);
+ }
+
+ curr_offset += FIELD_SIGNALLING_ASSOC_ID_LEN;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.3
+ */
+static void
+dis_field_aal2_path_id(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ guint32 value;
+
+ curr_offset = *offset;
+
+#define FIELD_AAL2_PATH_ID_LEN 4
+
+ SHORT_DATA_CHECK(*len, FIELD_AAL2_PATH_ID_LEN);
+
+ value = tvb_get_ntohl(tvb, curr_offset);
+
+ proto_tree_add_uint_format(tree, hf_alcap_aal2_path_id, tvb,
+ curr_offset, FIELD_AAL2_PATH_ID_LEN, value,
+ "AAL2 path identifier: %d%s",
+ value,
+ value ? "" : " (Null)");
+
+ curr_offset += FIELD_AAL2_PATH_ID_LEN;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.4
+ */
+static void
+dis_field_channel_id(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ guint8 oct;
+
+ curr_offset = *offset;
+
+ SHORT_DATA_CHECK(*len, 1);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_uint_format(tree, hf_alcap_channel_id, tvb,
+ curr_offset, 1, oct,
+ "Channel identifier (CID): %d%s",
+ oct,
+ oct ? "" : " (Null)");
+
+ curr_offset++;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.5
+ */
+static void
+dis_field_organizational_unique_id(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ guint32 octs;
+
+ curr_offset = *offset;
+
+#define FIELD_ORGANIZATIONAL_UNIQUE_ID_LEN 3
+
+ SHORT_DATA_CHECK(*len, FIELD_ORGANIZATIONAL_UNIQUE_ID_LEN);
+
+ octs = tvb_get_ntoh24(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_alcap_organizational_unique_id, tvb,
+ curr_offset, FIELD_ORGANIZATIONAL_UNIQUE_ID_LEN, octs);
+
+ curr_offset += FIELD_ORGANIZATIONAL_UNIQUE_ID_LEN;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.6
+ */
+static void
+dis_field_audio_service(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ guint32 value;
+ guint8 oct;
+ proto_item *item;
+ proto_tree *subtree;
+ gchar *str = NULL;
+
+ curr_offset = *offset;
+
+#define FIELD_AUDIO_SERVICE_LEN 5
+
+ SHORT_DATA_CHECK(*len, FIELD_AUDIO_SERVICE_LEN);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, FIELD_AUDIO_SERVICE_LEN, field_strings[FIELD_AUDIO_SERVICE]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_AUDIO_SERVICE]);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch ((oct & 0xc0) >> 6)
+ {
+ case 0x00: str = "Designates a profile specified by ITU-T Rec. I.366.2; ignore organizational unique identifier"; break;
+ case 0x01: str = "Designates a profile specified by organizational unique identifier"; break;
+ case 0x02: str = "Designates a custom profile; ignore organizational unique identifier"; break;
+ case 0x03: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Profile type, %s",
+ bigbuf, str);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "Profile identifier (%d)",
+ oct);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : FRM, transport of frame mode data %s",
+ bigbuf,
+ (oct & 0x80) ? "enabled" : "disabled");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : CMD, transport of circuit mode data (64 kbit/s) %s",
+ bigbuf,
+ (oct & 0x40) ? "enabled" : "disabled");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : MF-R2, transport of multi-frequency R2 dialled digits %s",
+ bigbuf,
+ (oct & 0x20) ? "enabled" : "disabled");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : MF-R1, transport of multi-frequency R1 dialled digits %s",
+ bigbuf,
+ (oct & 0x10) ? "enabled" : "disabled");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : DTMF, transport of dual tone multi-frequency dialled digits %s",
+ bigbuf,
+ (oct & 0x08) ? "enabled" : "disabled");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : CAS, transport of channel associated signalling %s",
+ bigbuf,
+ (oct & 0x04) ? "enabled" : "disabled");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : FAX, transport of demodulated facsimile data %s",
+ bigbuf,
+ (oct & 0x02) ? "enabled" : "disabled");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : A/mu-law, interpretation of generic PCM coding: %s-law",
+ bigbuf,
+ (oct & 0x01) ? "mu" : "A");
+
+ curr_offset++;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 2,
+ "Maximum length of frame mode data (%d)",
+ value);
+
+ curr_offset += 2;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.7
+ */
+static void
+dis_field_multirate_service(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ guint32 value;
+ guint8 oct;
+ proto_item *item;
+ proto_tree *subtree;
+
+ curr_offset = *offset;
+
+#define FIELD_MULTIRATE_SERVICE_LEN 3
+
+ SHORT_DATA_CHECK(*len, FIELD_MULTIRATE_SERVICE_LEN);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, FIELD_MULTIRATE_SERVICE_LEN, field_strings[FIELD_MULTIRATE_SERVICE]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_MULTIRATE_SERVICE]);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : FRM, transport of frame mode data %s",
+ bigbuf,
+ (oct & 0x80) ? "enabled" : "disabled");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Multiplier (%d) for n x 64 kbit/s",
+ bigbuf,
+ oct & 0x1f);
+
+ curr_offset++;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 2,
+ "Maximum length of frame mode data (%d)",
+ value);
+
+ curr_offset += 2;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.8
+ */
+static void
+dis_field_seg_reassembly_ass(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ guint32 value;
+ proto_item *item;
+ proto_tree *subtree;
+
+ curr_offset = *offset;
+
+#define FIELD_SEG_REASSEMBLY_ASS_LEN 14
+
+ SHORT_DATA_CHECK(*len, FIELD_SEG_REASSEMBLY_ASS_LEN);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, FIELD_SEG_REASSEMBLY_ASS_LEN, field_strings[FIELD_SEG_REASSEMBLY_ASS]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_SEG_REASSEMBLY_ASS]);
+
+ value = tvb_get_ntoh24(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 3,
+ "Maximum length of SSSAR-SDU in the forward direction (%d)",
+ value);
+
+ curr_offset += 3;
+
+ value = tvb_get_ntoh24(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 3,
+ "Maximum length of SSSAR-SDU in the backward direction (%d)",
+ value);
+
+ curr_offset += 3;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 2,
+ "Maximum length of SSCOP-SDU in the forward direction (%d)",
+ value);
+
+ curr_offset += 2;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 2,
+ "Maximum length of SSCOP-SDU in the backward direction (%d)",
+ value);
+
+ curr_offset += 2;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 2,
+ "Maximum length of SSCOP-UU in the forward direction (%d)",
+ value);
+
+ curr_offset += 2;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 2,
+ "Maximum length of SSCOP-UU in the backward direction (%d)",
+ value);
+
+ curr_offset += 2;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.9
+ */
+static void
+dis_field_seg_reassembly_unass(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ guint32 value;
+ guint8 oct;
+ proto_item *item;
+ proto_tree *subtree;
+
+ curr_offset = *offset;
+
+#define FIELD_SEG_REASSEMBLY_UNASS_LEN 7
+
+ SHORT_DATA_CHECK(*len, FIELD_SEG_REASSEMBLY_UNASS_LEN);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, FIELD_SEG_REASSEMBLY_UNASS_LEN, field_strings[FIELD_SEG_REASSEMBLY_UNASS]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_SEG_REASSEMBLY_UNASS]);
+
+ value = tvb_get_ntoh24(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 3,
+ "Maximum length of SSSAR-SDU in the forward direction (%d)",
+ value);
+
+ curr_offset += 3;
+
+ value = tvb_get_ntoh24(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 3,
+ "Maximum length of SSSAR-SDU in the backward direction (%d)",
+ value);
+
+ curr_offset += 3;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : TED, transmission error detection %s",
+ bigbuf,
+ oct & 0x80 ? "enabled" : "disabled");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ curr_offset++;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.10
+ */
+static void
+dis_field_served_user_gen_ref(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ guint32 value;
+
+ curr_offset = *offset;
+
+#define FIELD_SERVED_USER_GEN_REF_LEN 4
+
+ SHORT_DATA_CHECK(*len, FIELD_SERVED_USER_GEN_REF_LEN);
+
+ value = tvb_get_ntohl(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_alcap_served_user_gen_ref, tvb,
+ curr_offset, FIELD_SERVED_USER_GEN_REF_LEN, value);
+
+ curr_offset += FIELD_SERVED_USER_GEN_REF_LEN;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.11
+ */
+static void
+dis_field_cps_sdu_bit_rate(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset, gboolean maximum)
+{
+ guint32 curr_offset;
+ guint32 value;
+ proto_item *item;
+ proto_tree *subtree;
+
+ curr_offset = *offset;
+
+#define FIELD_CPS_SDU_BIT_RATE_LEN 4
+
+ SHORT_DATA_CHECK(*len, FIELD_CPS_SDU_BIT_RATE_LEN);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, FIELD_CPS_SDU_BIT_RATE_LEN, field_strings[FIELD_MAX_CPS_SDU_BIT_RATE + (maximum ? 0 : 1)]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_MAX_CPS_SDU_BIT_RATE + (maximum ? 0 : 1)]);
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 2,
+ "CPS-SDU bit rate in the forward direction (%d)",
+ value);
+
+ curr_offset += 2;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 2,
+ "CPS-SDU bit rate in the backward direction (%d)",
+ value);
+
+ curr_offset += 2;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.12
+ */
+static void
+dis_field_cps_sdu_size(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset, gboolean maximum)
+{
+ guint32 curr_offset;
+ guint8 oct;
+ proto_item *item;
+ proto_tree *subtree;
+
+ curr_offset = *offset;
+
+#define FIELD_CPS_SDU_SIZE_LEN 2
+
+ SHORT_DATA_CHECK(*len, FIELD_CPS_SDU_SIZE_LEN);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, FIELD_CPS_SDU_SIZE_LEN, field_strings[FIELD_MAX_CPS_SDU_SIZE + (maximum ? 0 : 1)]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_MAX_CPS_SDU_SIZE + (maximum ? 0 : 1)]);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 1,
+ "CPS-SDU size in the forward direction (%d)",
+ oct);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 1,
+ "CPS-SDU size in the backward direction (%d)",
+ oct);
+
+ curr_offset++;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.13
+ */
+static void
+dis_field_nature_of_address(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ guint32 value;
+ guint8 oct;
+ proto_item *item;
+ proto_tree *subtree;
+ gchar *str = NULL;
+
+ curr_offset = *offset;
+
+#define FIELD_NATURE_OF_ADDRESS_LEN 1
+
+ SHORT_DATA_CHECK(*len, FIELD_NATURE_OF_ADDRESS_LEN);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, FIELD_NATURE_OF_ADDRESS_LEN, field_strings[FIELD_NATURE_OF_ADDRESS]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_NATURE_OF_ADDRESS]);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ value = oct & 0x7f;
+
+ switch (value)
+ {
+ case 0x00: str = "spare"; break;
+ case 0x01: str = "subscriber number (national use)"; break;
+ case 0x02: str = "unknown (national use)"; break;
+ case 0x03: str = "national (significant) number"; break;
+ case 0x04: str = "international number"; break;
+ case 0x05: str = "network-specific number (national use)"; break;
+ default:
+ if ((value >= 0x06) && (value <= 0x6f)) { str = "spare"; break; }
+ else if ((value >= 0x70) && (value <= 0xfe)) { str = "reserved for national use"; break; }
+ else { str = "not given in spec. ???"; break; }
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Nature of address code, %s (%d)",
+ bigbuf,
+ str,
+ value);
+
+ curr_offset++;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.14
+ */
+static void
+dis_field_e164_address(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ proto_item *item;
+ proto_tree *subtree;
+ guint8 parm_len;
+ guint8 oct;
+ guint8 i;
+
+ curr_offset = *offset;
+
+ SHORT_DATA_CHECK(*len, 1);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, -1, field_strings[FIELD_E164_ADDRESS]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_E164_ADDRESS]);
+
+ parm_len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_item_set_len(item, parm_len + 1);
+
+ proto_tree_add_uint(subtree, hf_alcap_length, tvb, curr_offset, 1, parm_len);
+
+ curr_offset++;
+
+ if (parm_len > 0)
+ {
+ i=0;
+ while (i < parm_len)
+ {
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ bigbuf2[i] = (oct & 0x0f) + 0x30;
+
+ other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Digit %d of address (%d)",
+ bigbuf,
+ i+1,
+ oct & 0x0f);
+
+ curr_offset++;
+ i++;
+ }
+
+ bigbuf2[i] = '\0';
+
+ proto_item_append_text(item, " (%s)", bigbuf2);
+ }
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.15
+ */
+static void
+dis_field_nsap_address(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+
+ curr_offset = *offset;
+
+#define FIELD_NSAP_ADDRESS_LEN 20
+
+ SHORT_DATA_CHECK(*len, FIELD_NSAP_ADDRESS_LEN);
+
+ proto_tree_add_item(tree, hf_alcap_nsap_address, tvb,
+ curr_offset, FIELD_NSAP_ADDRESS_LEN, FALSE);
+
+ curr_offset += FIELD_NSAP_ADDRESS_LEN;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.16
+ */
+static void
+dis_field_cause_value(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset, gboolean *compat)
+{
+ guint32 curr_offset;
+ guint8 oct;
+ proto_item *item;
+ proto_tree *subtree;
+ gchar *str = NULL;
+
+ *compat = FALSE;
+ curr_offset = *offset;
+
+#define FIELD_CAUSE_VALUE_LEN 2
+
+ SHORT_DATA_CHECK(*len, FIELD_CAUSE_VALUE_LEN);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, FIELD_CAUSE_VALUE_LEN, field_strings[FIELD_CAUSE_VALUE]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_CAUSE_VALUE]);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (oct & 0x3)
+ {
+ case 0x00: str = "ITU-T standardized coding as described in ITU-T Rec. Q.850 and Q.2610"; break;
+ case 0x01: str = "ISO/IEC standard"; break;
+ case 0x02: str = "national standard"; break;
+ case 0x03: str = "standard defined for the network (either public or private) present on the network side of the interface"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Coding standard, %s",
+ bigbuf,
+ str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (oct & 0x7f)
+ {
+ case 1: str = "Unallocated (unassigned) number"; break;
+ case 3: str = "No route to destination"; break;
+ case 31: str = "Normal, unspecified"; break;
+ case 34: str = "No circuit/channel available"; break;
+ case 38: str = "Network out of order"; break;
+ case 41: str = "Temporary failure"; break;
+ case 42: str = "Switching equipment congestion"; break;
+ case 44: str = "Requested circuit/channel not available"; break;
+ case 47: str = "Resource unavailable, unspecified"; break;
+ case 93: str = "AAL parameters cannot be supported"; break;
+ case 95: str = "Invalid message, unspecified"; break;
+ case 96: str = "Mandatory information element is missing"; break;
+ case 97: str = "Message type non-existent or not implemented"; *compat = TRUE; break;
+ case 99: str = "Information element/parameter non-existent or not implemented"; *compat = TRUE; break;
+ case 100: str = "Invalid information element contents"; break;
+ case 102: str = "Recovery on timer expiry"; break;
+ case 110: str = "Message with unrecognized parameter, discarded"; *compat = TRUE; break;
+ default: str = "Unknown"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(subtree, tvb,
+ curr_offset, 1,
+ "%s : Cause (%d), %s",
+ bigbuf,
+ oct & 0x7f,
+ str);
+
+ curr_offset++;
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.17
+ */
+static void
+dis_field_diagnostics(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset, gboolean compat)
+{
+ guint32 curr_offset;
+ guint8 oct;
+ proto_item *item;
+ proto_tree *subtree;
+ guint8 parm_len;
+ gchar *str = NULL;
+ gint idx;
+ guint8 i;
+
+ curr_offset = *offset;
+
+ SHORT_DATA_CHECK(*len, 1);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, -1, field_strings[FIELD_DIAGNOSTICS]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_DIAGNOSTICS]);
+
+ parm_len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_item_set_len(item, parm_len + 1);
+
+ proto_tree_add_uint(subtree, hf_alcap_length, tvb, curr_offset, 1, parm_len);
+
+ curr_offset++;
+
+ if (parm_len > 0)
+ {
+ if (compat)
+ {
+ /*
+ * compatibility diagnostics
+ */
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ str = my_match_strval(oct, msg_type_strings, &idx);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 1, (str == NULL) ? "Unknown message identifier" : str);
+
+ curr_offset++;
+
+ i=1;
+ while ((i+2) <= parm_len)
+ {
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ str = my_match_strval(oct, msg_parm_strings, &idx);
+
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 1, (str == NULL) ? "Unknown parameter" : str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct == 0)
+ {
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 1, "Whole parameter");
+ }
+ else
+ {
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, 1, "Field number %d", oct);
+ }
+
+ curr_offset++;
+ i += 2;
+ }
+
+ if (i != parm_len)
+ {
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, parm_len - i, "Extraneous Data ???");
+
+ curr_offset += (parm_len - i);
+ }
+ }
+ else
+ {
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, parm_len, "Coded as per ITU-T Rec. Q.2610");
+
+ curr_offset += parm_len;
+ }
+ }
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.4.18
+ */
+static void
+dis_field_served_user_transport(tvbuff_t *tvb, proto_tree *tree, guint *len, guint32 *offset)
+{
+ guint32 curr_offset;
+ proto_item *item;
+ proto_tree *subtree;
+ guint8 parm_len;
+
+ curr_offset = *offset;
+
+ SHORT_DATA_CHECK(*len, 1);
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, -1, field_strings[FIELD_SERVED_USER_TRANSPORT]);
+
+ subtree = proto_item_add_subtree(item, ett_fields[FIELD_SERVED_USER_TRANSPORT]);
+
+ parm_len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_item_set_len(item, parm_len + 1);
+
+ proto_tree_add_uint(subtree, hf_alcap_length, tvb, curr_offset, 1, parm_len);
+
+ curr_offset++;
+
+ if (parm_len > 0)
+ {
+ proto_tree_add_none_format(subtree, hf_alcap_none, tvb,
+ curr_offset, parm_len, "Value");
+
+ curr_offset += parm_len;
+ }
+
+ *len -= (curr_offset - *offset);
+ *offset = curr_offset;
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.1
+ */
+static void
+dis_parm_cause(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+ gboolean compat;
+
+ dis_field_cause_value(tvb, tree, &len, &curr_offset, &compat);
+
+ dis_field_diagnostics(tvb, tree, &len, &curr_offset, compat);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.2
+ */
+static void
+dis_parm_conn_element_id(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_aal2_path_id(tvb, tree, &len, &curr_offset);
+
+ dis_field_channel_id(tvb, tree, &len, &curr_offset);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.3
+ */
+static void
+dis_parm_dest_e164_sea(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_nature_of_address(tvb, tree, &len, &curr_offset);
+
+ dis_field_e164_address(tvb, tree, &len, &curr_offset);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.4
+ */
+static void
+dis_parm_dest_nsap_sea(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_nsap_address(tvb, tree, &len, &curr_offset);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.5
+ */
+static void
+dis_parm_link_characteristics(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_cps_sdu_bit_rate(tvb, tree, &len, &curr_offset, TRUE);
+
+ dis_field_cps_sdu_bit_rate(tvb, tree, &len, &curr_offset, FALSE);
+
+ dis_field_cps_sdu_size(tvb, tree, &len, &curr_offset, TRUE);
+
+ dis_field_cps_sdu_size(tvb, tree, &len, &curr_offset, FALSE);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.6
+ */
+static void
+dis_parm_osai(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_signalling_assoc_id(tvb, tree, &len, &curr_offset, FALSE);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.7
+ */
+static void
+dis_parm_served_user_gen_ref(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_served_user_gen_ref(tvb, tree, &len, &curr_offset);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.8
+ */
+static void
+dis_parm_served_user_transport(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_served_user_transport(tvb, tree, &len, &curr_offset);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.9
+ */
+static void
+dis_parm_service_specific_info_audio(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_audio_service(tvb, tree, &len, &curr_offset);
+
+ dis_field_organizational_unique_id(tvb, tree, &len, &curr_offset);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.10
+ */
+static void
+dis_parm_service_specific_info_multirate(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_multirate_service(tvb, tree, &len, &curr_offset);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.11
+ */
+static void
+dis_parm_service_specific_info_ass(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_seg_reassembly_ass(tvb, tree, &len, &curr_offset);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+/*
+ * Ref. ITU-T Q.2630.1 (12/1999)
+ * Section 7.3.12
+ */
+static void
+dis_parm_service_specific_info_unass(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 curr_offset)
+{
+
+ dis_field_seg_reassembly_unass(tvb, tree, &len, &curr_offset);
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+static gint ett_parms[NUM_PARMS];
+static void (*alcap_parm_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
+ dis_parm_cause, /* Cause */
+ dis_parm_conn_element_id, /* Connection element identifier */
+ dis_parm_dest_e164_sea, /* Destination E.164 service endpoint address */
+ dis_parm_dest_nsap_sea, /* Destination NSAP service endpoint address */
+ dis_parm_link_characteristics, /* Link characteristics */
+ dis_parm_osai, /* Originating signalling association identifier */
+ dis_parm_served_user_gen_ref, /* Served user generated reference */
+ dis_parm_served_user_transport, /* Served user transport */
+ dis_parm_service_specific_info_audio, /* Service specific information (audio) */
+ dis_parm_service_specific_info_multirate, /* Service specific information (multirate) */
+ dis_parm_service_specific_info_ass, /* Service specific information (SAR-assured) */
+ dis_parm_service_specific_info_unass, /* Service specific information (SAR-unassured) */
+ NULL /* no parms */, /* Test connection identifier */
+ NULL, /* NONE */
+};
+
+/* GENERIC ALCAP DISSECTOR FUNCTIONS */
+
+static void
+dissect_alcap_parms(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 len)
+{
+ void (*parm_fcn)(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = NULL;
+ guint8 parm;
+ guint8 parm_len;
+ guint32 curr_offset, saved_offset;
+ gint idx;
+ gchar *str = NULL;
+ proto_item *item;
+ proto_tree *subtree;
+ gint ett_parm_idx;
+
+
+ curr_offset = offset;
+
+ while (len >= ALCAP_PARM_HEADER_LEN)
+ {
+ saved_offset = curr_offset;
+
+ parm = tvb_get_guint8(tvb, curr_offset);
+
+ str = my_match_strval(parm, msg_parm_strings, &idx);
+
+ if (str == NULL)
+ {
+ ett_parm_idx = ett_parm;
+ parm_fcn = NULL;
+ }
+ else
+ {
+ ett_parm_idx = ett_parms[idx];
+ parm_fcn = alcap_parm_fcn[idx];
+ }
+
+ item =
+ proto_tree_add_none_format(tree, hf_alcap_none, tvb,
+ curr_offset, -1, (str == NULL) ? "Unknown parameter" : str);
+
+ subtree = proto_item_add_subtree(item, ett_parm_idx);
+
+ proto_tree_add_uint(subtree, hf_alcap_parm_id, tvb,
+ curr_offset, 1, parm);
+
+ curr_offset++;
+
+ dis_field_compatibility(tvb, subtree, &curr_offset, FALSE);
+
+ parm_len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_uint(subtree, hf_alcap_length, tvb, curr_offset, 1, parm_len);
+
+ curr_offset++;
+
+ proto_item_set_len(item, (curr_offset - saved_offset) + parm_len);
+
+ if (parm_len > 0)
+ {
+ if (parm_fcn == NULL)
+ {
+ proto_tree_add_none_format(subtree, hf_alcap_none,
+ tvb, curr_offset, parm_len, "Parameter data");
+ }
+ else
+ {
+ (*parm_fcn)(tvb, subtree, parm_len, curr_offset);
+ }
+ }
+
+ len -= (ALCAP_PARM_HEADER_LEN + parm_len);
+ curr_offset += parm_len;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, 0);
+}
+
+static void
+dissect_alcap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *alcap_tree)
+{
+ guint32 temp_len;
+ guint32 len;
+ guint32 offset;
+ guint8 msg_type;
+ gint idx;
+ gchar *str = NULL;
+
+ offset = 0;
+
+ len = tvb_length(tvb);
+ temp_len = len;
+
+ if (len < ALCAP_MSG_HEADER_LEN)
+ {
+ proto_tree_add_none_format(alcap_tree, hf_alcap_none, tvb,
+ offset, len, "Message header too short");
+
+ return;
+ }
+
+ dis_field_signalling_assoc_id(tvb, alcap_tree, &temp_len, &offset, TRUE);
+
+ msg_type = tvb_get_guint8(tvb, offset);
+
+ str = my_match_strval(msg_type, msg_type_strings, &idx);
+
+ if (str == NULL)
+ {
+ proto_tree_add_none_format(alcap_tree, hf_alcap_none, tvb,
+ offset, 1, "Unknown message identifier");
+
+ return;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_set_str(pinfo->cinfo, COL_INFO, str);
+ }
+
+ proto_tree_add_uint(alcap_tree, hf_alcap_msg_type, tvb,
+ offset, 1, msg_type);
+
+ offset++;
+
+ dis_field_compatibility(tvb, alcap_tree, &offset, TRUE);
+
+ if (len > ALCAP_MSG_HEADER_LEN)
+ {
+ dissect_alcap_parms(tvb, alcap_tree, offset, len - ALCAP_MSG_HEADER_LEN);
+ }
+}
+
+static void
+dissect_alcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *alcap_item;
+ proto_tree *alcap_tree = NULL;
+
+ g_pinfo = pinfo;
+
+ /*
+ * Don't change the Protocol column on summary display
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, alcap_proto_name_short);
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree)
+ {
+ g_tree = tree;
+
+ /*
+ * create the ALCAP protocol tree
+ */
+ alcap_item =
+ proto_tree_add_protocol_format(tree, proto_alcap, tvb, 0, -1,
+ alcap_proto_name);
+
+ alcap_tree =
+ proto_item_add_subtree(alcap_item, ett_alcap);
+
+ dissect_alcap_message(tvb, pinfo, alcap_tree);
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_alcap(void)
+{
+ guint i;
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] =
+ {
+ { &hf_alcap_msg_type,
+ { "Message Type",
+ "alcap.msg_type",
+ FT_UINT8, BASE_DEC, VALS(msg_type_strings), 0,
+ "", HFILL }},
+ { &hf_alcap_dsaid,
+ { "Destination signalling association identifier",
+ "alcap.dsai",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_alcap_osaid,
+ { "Originating signalling association identifier",
+ "alcap.osai",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_alcap_aal2_path_id,
+ { "AAL2 path identifier",
+ "alcap.aal2_path_id",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_alcap_channel_id,
+ { "Channel identifier (CID)",
+ "alcap.channel_id",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_alcap_organizational_unique_id,
+ { "Organizational unique identifier (OUI)",
+ "alcap.organizational_unique_id",
+ FT_UINT24, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_alcap_served_user_gen_ref,
+ { "Served user generated reference",
+ "alcap.served_user_gen_ref",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_alcap_nsap_address,
+ { "NSAP address",
+ "alcap.nsap_address",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_alcap_parm_id,
+ { "Parameter identifier",
+ "alcap.param_id",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }},
+ { &hf_alcap_length,
+ { "Length", "alcap.len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_alcap_none,
+ { "Subtree", "alcap.none",
+ FT_NONE, 0, 0, 0,
+ "", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+#define NUM_INDIVIDUAL_PARMS 2
+ static gint *ett[NUM_INDIVIDUAL_PARMS+NUM_PARMS+NUM_FIELDS];
+
+ memset((void *) ett, 0, sizeof(ett));
+
+ ett[0] = &ett_alcap;
+ ett[1] = &ett_parm;
+
+ for (i=0; i < NUM_PARMS; i++)
+ {
+ ett_parms[i] = -1;
+ ett[NUM_INDIVIDUAL_PARMS+i] = &ett_parms[i];
+ }
+
+ for (i=0; i < NUM_FIELDS; i++)
+ {
+ ett_fields[i] = -1;
+ ett[NUM_INDIVIDUAL_PARMS+NUM_PARMS+i] = &ett_fields[i];
+ }
+
+ /* Register the protocol name and description */
+ proto_alcap =
+ proto_register_protocol(alcap_proto_name, alcap_proto_name_short, "alcap");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_alcap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_alcap(void)
+{
+ dissector_handle_t alcap_handle;
+
+ alcap_handle = create_dissector_handle(dissect_alcap, proto_alcap);
+
+ dissector_add("mtp3.service_indicator", ALCAP_SI, alcap_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ans.c b/epan/dissectors/packet-ans.c
new file mode 100644
index 0000000000..bd2c791d99
--- /dev/null
+++ b/epan/dissectors/packet-ans.c
@@ -0,0 +1,153 @@
+/* packet-ans.c
+ * Routines for Intel ANS probe dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2003 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The following information was graciously provided by Intel:
+ * Offset Size (bytes) Contents
+ * 0 6 Destination Broadcast probes: {FF,FF,FF,FF,FF,FF}
+ * Multicast probes: {01,AA,00,00,00,00}
+ * 6 6 Source Matches the CurrentMACAddress of the
+ * adapter sending the probe.
+ * 8 2 Type Network order is 0x886D, Intel's reserved
+ * packet type.
+ * 10 (0) 2 ApplicationID Network order is 0x0001, identifies
+ * it as fault tolerance probe.
+ * 12 (2) 2 RevID Network order, identifies the revision id
+ * of Teaming software.
+ * 16 (4) 4 ProbeSequenceNumber Ascending sequence number
+ * that identifies the current probing cycle.
+ * 20 (8) 2 SenderID Unique ID within a team identifying
+ * the member that originally sent the probe.
+ * 22 (10) 6 TeamID Unique ID identifying the team in charge
+ * of this probe.
+ * 28 Padding Reserved
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/proto.h>
+#include <etypes.h>
+
+/* Initialize the protocol and registered fields */
+static int proto_ans = -1;
+
+static int hf_ans_app_id = -1;
+static int hf_ans_rev_id = -1;
+static int hf_ans_seq_num = -1;
+static int hf_ans_sender_id = -1;
+static int hf_ans_team_id = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_ans = -1;
+
+/* Code to actually dissect the packets */
+static void
+dissect_ans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *ans_tree = NULL;
+ guint16 sender_id;
+ guint32 seq_num;
+ gchar team_id[6];
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Intel ANS probe");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ seq_num = tvb_get_ntohl(tvb, 4);
+ sender_id = tvb_get_ntohs(tvb, 8);
+ tvb_memcpy(tvb, team_id, 10, 6);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Sequence: %u, Sender ID %u, Team ID %s",
+ seq_num, sender_id, ether_to_str(team_id));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ans, tvb, 0, -1, FALSE);
+ ans_tree = proto_item_add_subtree(ti, ett_ans);
+
+ proto_tree_add_item(ans_tree, hf_ans_app_id, tvb, 0, 2, FALSE);
+ proto_tree_add_item(ans_tree, hf_ans_rev_id, tvb, 2, 2, FALSE);
+ proto_tree_add_item(ans_tree, hf_ans_seq_num, tvb, 4, 4, FALSE);
+ proto_tree_add_item(ans_tree, hf_ans_sender_id, tvb, 8, 2, FALSE);
+ proto_tree_add_item(ans_tree, hf_ans_team_id, tvb, 10, 6, FALSE);
+ }
+}
+
+
+void
+proto_register_ans(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ans_app_id,
+ { "Application ID", "ans.app_id",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Intel ANS Application ID", HFILL }
+ },
+ { &hf_ans_rev_id,
+ { "Revision ID", "ans.rev_id",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Intel ANS Revision ID", HFILL }
+ },
+ { &hf_ans_seq_num,
+ { "Sequence Number", "ans.seq_num",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Intel ANS Sequence Number", HFILL }
+ },
+ { &hf_ans_sender_id,
+ { "Sender ID", "ans.sender_id",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Intel ANS Sender ID", HFILL }
+ },
+ { &hf_ans_team_id,
+ { "Team ID", "ans.team_id",
+ FT_ETHER, BASE_HEX, NULL, 0,
+ "Intel ANS Team ID", HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_ans,
+ };
+
+ proto_ans = proto_register_protocol("Intel ANS probe", "ANS", "ans");
+ proto_register_field_array(proto_ans, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_ans(void)
+{
+ dissector_handle_t ans_handle;
+
+ ans_handle = create_dissector_handle(dissect_ans, proto_ans);
+ dissector_add("ethertype", ETHERTYPE_INTEL_ANS, ans_handle);
+}
diff --git a/epan/dissectors/packet-ansi_637.c b/epan/dissectors/packet-ansi_637.c
new file mode 100644
index 0000000000..8285ed698f
--- /dev/null
+++ b/epan/dissectors/packet-ansi_637.c
@@ -0,0 +1,1937 @@
+/* packet-ansi_637.c
+ * Routines for ANSI IS-637-A (SMS) dissection
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * Title 3GPP2 Other
+ *
+ * Short Message Service
+ * 3GPP2 C.S0015-0 TIA/EIA-637-A
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gmodule.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <string.h>
+
+#include "epan/packet.h"
+
+
+static char *ansi_proto_name_tele = "ANSI IS-637-A (SMS) Teleservice Layer";
+static char *ansi_proto_name_trans = "ANSI IS-637-A (SMS) Transport Layer";
+static char *ansi_proto_name_short = "IS-637-A";
+
+static const value_string ansi_srvc_cat_strings[] = {
+ { 0x0000, "Unknown or unspecified" },
+ { 0x0001, "Emergency Broadcasts" },
+ { 0x0002, "Administrative" },
+ { 0x0003, "Maintenance" },
+ { 0x0004, "General News - Local" },
+ { 0x0005, "General News - Regional" },
+ { 0x0006, "General News - National" },
+ { 0x0007, "General News - International" },
+ { 0x0008, "Business/Financial News - Local" },
+ { 0x0009, "Business/Financial News - Regional" },
+ { 0x000A, "Business/Financial News - National" },
+ { 0x000B, "Business/Financial News - International" },
+ { 0x000C, "Sports News - Local" },
+ { 0x000D, "Sports News - Regional" },
+ { 0x000E, "Sports News - National" },
+ { 0x000F, "Sports News - International" },
+ { 0x0010, "Entertainment News - Local" },
+ { 0x0011, "Entertainment News - Regional" },
+ { 0x0012, "Entertainment News - National" },
+ { 0x0013, "Entertainment News - International" },
+ { 0x0014, "Local Weather" },
+ { 0x0015, "Area Traffic Reports" },
+ { 0x0016, "Local Airport Flight Schedules" },
+ { 0x0017, "Restaurants" },
+ { 0x0018, "Lodgings" },
+ { 0x0019, "Retail Directory" },
+ { 0x001A, "Advertisements" },
+ { 0x001B, "Stock Quotes" },
+ { 0x001C, "Employment Opportunities" },
+ { 0x001D, "Medical/Health/Hospitals" },
+ { 0x001E, "Technology News" },
+ { 0x001F, "Multi-category" },
+ { 0, NULL },
+};
+
+static const value_string ansi_tele_msg_type_strings[] = {
+ { 1, "Deliver (mobile-terminated only)" },
+ { 2, "Submit (mobile-originated only)" },
+ { 3, "Cancellation (mobile-originated only)" },
+ { 4, "Delivery Acknowledgement (mobile-terminated only)" },
+ { 5, "User Acknowledgement (either direction)" },
+ { 0, NULL },
+};
+
+static const value_string ansi_tele_id_strings[] = {
+ { 1, "Reserved for maintenance" },
+ { 4096, "AMPS Extended Protocol Enhanced Services" },
+ { 4097, "CDMA Cellular Paging Teleservice" },
+ { 4098, "CDMA Cellular Messaging Teleservice" },
+ { 4099, "CDMA Voice Mail Notification" },
+ { 32513, "TDMA Cellular Messaging Teleservice" },
+ { 32520, "TDMA System Assisted Mobile Positioning through Satellite (SAMPS)" },
+ { 32584, "TDMA Segmented System Assisted Mobile Positioning Service" },
+ { 0, NULL },
+};
+
+static const value_string ansi_tele_param_strings[] = {
+ { 0x00, "Message Identifier" },
+ { 0x01, "User Data" },
+ { 0x02, "User Response Code" },
+ { 0x03, "Message Center Time Stamp" },
+ { 0x04, "Validity Period - Absolute" },
+ { 0x05, "Validity Period - Relative" },
+ { 0x06, "Deferred Delivery Time - Absolute" },
+ { 0x07, "Deferred Delivery Time - Relative" },
+ { 0x08, "Priority Indicator" },
+ { 0x09, "Privacy Indicator" },
+ { 0x0a, "Reply Option" },
+ { 0x0b, "Number of Messages" },
+ { 0x0c, "Alert on Message Delivery" },
+ { 0x0d, "Language Indicator" },
+ { 0x0e, "Call-Back Number" },
+ { 0x0f, "Message Display Mode" },
+ { 0x10, "Multiple Encoding User Data" },
+ { 0, NULL },
+};
+
+static const value_string ansi_trans_msg_type_strings[] = {
+ { 0, "Point-to-Point" },
+ { 1, "Broadcast" },
+ { 2, "Acknowledge" },
+ { 0, NULL },
+};
+
+static const value_string ansi_trans_param_strings[] = {
+ { 0x00, "Teleservice Identifier" },
+ { 0x01, "Service Category" },
+ { 0x02, "Originating Address" },
+ { 0x03, "Originating Subaddress" },
+ { 0x04, "Destination Address" },
+ { 0x05, "Destination Subaddress" },
+ { 0x06, "Bearer Reply Option" },
+ { 0x07, "Cause Codes" },
+ { 0x08, "Bearer Data" },
+ { 0, NULL },
+};
+
+/*
+ * from Table 2.7.1.3.2.4-4. Representation of DTMF Digits
+ * 3GPP2 C.S0005-C (IS-2000 aka cdma2000)
+ */
+static unsigned char air_digits[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '?','1','2','3','4','5','6','7','8','9','0','*','#','?','?'
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_ansi_637_tele = -1;
+static int proto_ansi_637_trans = -1;
+static int hf_ansi_637_none = -1;
+static int hf_ansi_637_length = -1;
+static int hf_ansi_637_bin_addr = -1;
+static int hf_ansi_637_tele_msg_type = -1;
+static int hf_ansi_637_tele_msg_id = -1;
+static int hf_ansi_637_tele_msg_rsvd = -1;
+static int hf_ansi_637_tele_subparam_id = -1;
+static int hf_ansi_637_trans_msg_type = -1;
+static int hf_ansi_637_trans_param_id = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_ansi_637_tele = -1;
+static gint ett_ansi_637_trans = -1;
+static gint ett_params = -1;
+
+static guint32 ansi_637_trans_tele_id;
+static char ansi_637_bigbuf[1024];
+static gchar ansi_637_add_string[1024];
+static dissector_handle_t data_handle;
+static dissector_table_t tele_dissector_table;
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
+
+/* FUNCTIONS */
+
+static void
+decode_7_bits(tvbuff_t *tvb, guint32 *offset, guint8 num_fields, guint8 *last_oct, guint8 *last_bit, gchar *buf)
+{
+ guint8 oct, oct2, bit;
+ guint32 saved_offset;
+ guint32 i;
+
+
+ if (num_fields == 0)
+ {
+ return;
+ }
+
+ saved_offset = *offset;
+ oct = oct2 = *last_oct;
+ bit = *last_bit;
+
+ if (bit == 1)
+ {
+ oct2 = tvb_get_guint8(tvb, *offset);
+ (*offset)++;
+ }
+
+ for (i=0; i < num_fields; i++)
+ {
+ if (bit != 1)
+ {
+ oct = oct2;
+
+ /*
+ * cannot grab an octet if we are getting
+ * the last field and bit is 7 or 8
+ * because there may not be another octet
+ */
+ if (((i + 1) != num_fields) ||
+ ((bit != 7) && (bit != 8)))
+ {
+ oct2 = tvb_get_guint8(tvb, *offset);
+ (*offset)++;
+ }
+ }
+
+ switch (bit)
+ {
+ case 1:
+ buf[i] = ((oct & 0x01) << 6) | ((oct2 & 0xfc) >> 2);
+ break;
+
+ case 2:
+ buf[i] = ((oct & 0x03) << 5) | ((oct2 & 0xf8) >> 3);
+ break;
+
+ case 3:
+ buf[i] = ((oct & 0x07) << 4) | ((oct2 & 0xf0) >> 4);
+ break;
+
+ case 4:
+ buf[i] = ((oct & 0x0f) << 3) | ((oct2 & 0xe0) >> 5);
+ break;
+
+ case 5:
+ buf[i] = ((oct & 0x1f) << 2) | ((oct2 & 0xc0) >> 6);
+ break;
+
+ case 6:
+ buf[i] = ((oct & 0x3f) << 1) | ((oct2 & 0x80) >> 7);
+ break;
+
+ case 7:
+ buf[i] = oct & 0x7f;
+ break;
+
+ case 8:
+ buf[i] = (oct & 0xfe) >> 1;
+ break;
+ }
+
+ bit = (bit % 8) + 1;
+ }
+
+ buf[i] = '\0';
+ *last_bit = bit;
+ *last_oct = (bit == 1) ? oct : oct2;
+}
+
+static gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr)
+ {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+
+/* PARAM FUNCTIONS */
+
+#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
+ if ((edc_len) > (edc_max_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, offset, \
+ (edc_len) - (edc_max_len), "Extraneous Data"); \
+ }
+
+#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
+ if ((sdc_len) < (sdc_min_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, offset, \
+ (sdc_len), "Short Data (?)"); \
+ return; \
+ }
+
+#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
+ if ((edc_len) != (edc_eq_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, offset, \
+ (edc_len), "Unexpected Data Length"); \
+ return; \
+ }
+
+static void
+tele_param_user_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, oct2;
+ guint8 encoding;
+ guint8 msg_type;
+ guint8 num_fields;
+ guint8 used;
+ guint8 bit;
+ guint32 required_octs;
+ guint32 saved_offset;
+ guint32 i;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ /*
+ * message encoding
+ */
+ oct = tvb_get_guint8(tvb, offset);
+ oct2 = 0;
+ msg_type = 0;
+ used = 0;
+
+ encoding = ((oct & 0xf8) >> 3);
+ switch (encoding)
+ {
+ case 0x00: str = "Octet, unspecified"; break;
+ case 0x01: str = "Extended Protocol Message";
+ oct2 = tvb_get_guint8(tvb, offset+1);
+ msg_type = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
+ break;
+ case 0x02: str = "7-bit ASCII"; break;
+ case 0x03: str = "IA5"; break;
+ case 0x04: str = "UNICODE"; break;
+ case 0x05: str = "Shift-JIS"; break;
+ case 0x06: str = "Korean"; break;
+ case 0x07: str = "Latin/Hebrew"; break;
+ case 0x08: str = "Latin"; break;
+ case 0x09: str = "GSM 7-bit default alphabet"; break;
+ default: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf8, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Encoding: %s",
+ ansi_637_bigbuf,
+ str);
+
+ if (encoding == 0x01)
+ {
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Message type: see TIA/EIA/IS-91 (%d)",
+ ansi_637_bigbuf,
+ msg_type);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
+ proto_tree_add_text(tree, tvb, offset+1, 1,
+ "%s : Message type",
+ ansi_637_bigbuf);
+
+ oct = oct2;
+ offset++;
+ used++;
+ }
+
+ offset++;
+ used++;
+
+ /*
+ * number of fields
+ */
+ oct2 = tvb_get_guint8(tvb, offset);
+ num_fields = ((oct & 0x07) << 5) | ((oct2 & 0xf8) >> 3);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, offset-1, 1,
+ "%s : Number of fields (MSB): %d",
+ ansi_637_bigbuf,
+ num_fields);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number of fields (LSB)",
+ ansi_637_bigbuf);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x07, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Most significant bits of first field",
+ ansi_637_bigbuf);
+
+ offset++;
+ used++;
+ oct = oct2;
+
+ /* NOTE: there are now 3 bits remaining in 'oct' */
+
+ if (len - used <= 0) return;
+
+ /*
+ * decode rest if 7-bit ASCII
+ */
+ if (encoding == 0x02)
+ {
+ /*
+ * magic numbers:
+ * 3 bits remaining from last octet
+ * 7 bit encoding
+ * 8 bits per octet
+ */
+ i = (num_fields * 7) - 3;
+ required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+
+ if (required_octs + used > len)
+ {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing %d octet(s) for number of fields",
+ (required_octs + used) - len);
+
+ return;
+ }
+
+ bit = 3;
+ saved_offset = offset;
+
+ decode_7_bits(tvb, &offset, num_fields, &oct, &bit, ansi_637_bigbuf);
+
+ proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
+ "Encoded user data: %s",
+ ansi_637_bigbuf);
+
+ switch (bit)
+ {
+ case 1: oct2 = 0x01; break;
+ case 2: oct2 = 0x03; break;
+ case 3: oct2 = 0x07; break;
+ case 4: oct2 = 0x0f; break;
+ case 5: oct2 = 0x1f; break;
+ case 6: oct2 = 0x3f; break;
+ case 7: oct2 = 0x7f; break;
+ }
+
+ if (bit != 8)
+ {
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, oct2, 8);
+ proto_tree_add_text(tree, tvb, offset - 1, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+ }
+ }
+ else
+ {
+ proto_tree_add_text(tree, tvb, offset, len - used,
+ "Encoded user data");
+ }
+}
+
+static void
+tele_param_rsp_code(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ /*
+ * response code
+ */
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Response code: %d",
+ oct);
+}
+
+static void
+tele_param_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, oct2, oct3;
+
+ EXACT_DATA_CHECK(len, 6);
+
+ oct = tvb_get_guint8(tvb, offset);
+ oct2 = tvb_get_guint8(tvb, offset+1);
+ oct3 = tvb_get_guint8(tvb, offset+2);
+
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Year %d%d, Month %d%d, Day %d%d",
+ (oct & 0xf0) >> 4,
+ oct & 0x0f,
+ (oct2 & 0xf0) >> 4,
+ oct2 & 0x0f,
+ (oct3 & 0xf0) >> 4,
+ oct3 & 0x0f);
+
+ offset += 3;
+
+ oct = tvb_get_guint8(tvb, offset);
+ oct2 = tvb_get_guint8(tvb, offset+1);
+ oct3 = tvb_get_guint8(tvb, offset+2);
+
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Hour %d%d, Minutes %d%d, Seconds %d%d",
+ (oct & 0xf0) >> 4,
+ oct & 0x0f,
+ (oct2 & 0xf0) >> 4,
+ oct2 & 0x0f,
+ (oct3 & 0xf0) >> 4,
+ oct3 & 0x0f);
+}
+
+static void
+tele_param_rel_timestamp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ guint32 value = 0;
+ gchar *str = NULL;
+ gchar *str2 = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch (oct)
+ {
+ case 245: str = "Indefinite"; break;
+ case 246: str = "Immediate"; break;
+ case 247: str = "Valid until mobile becomes inactive/Deliver when mobile next becomes active"; break;
+ case 248: str = "Valid until registration area changes, discard if not registered" ; break;
+ default:
+ if (oct <= 143) { value = (oct + 1) * 5; str2 = "Minutes"; break; }
+ else if ((oct >= 144) && (oct <= 167)) { value = (oct - 143) * 30; str2 = "Minutes + 12 Hours"; break; }
+ else if ((oct >= 168) && (oct <= 196)) { value = oct - 166; str2 = "Days"; break; }
+ else if ((oct >= 197) && (oct <= 244)) { value = oct - 192; str2 = "Weeks"; break; }
+ else { str = "Reserved"; break; }
+ }
+
+ if (str == NULL)
+ {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ str2);
+ }
+ else
+ {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%d %s",
+ value, str2);
+ }
+}
+
+static void
+tele_param_pri_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch ((oct & 0xc0) >> 6)
+ {
+ case 0: str = "Normal"; break;
+ case 1: str = "Interactive"; break;
+ case 2: str = "Urgent"; break;
+ case 3: str = "Emergency"; break;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : %s",
+ ansi_637_bigbuf,
+ str);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+}
+
+static void
+tele_param_priv_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch ((oct & 0xc0) >> 6)
+ {
+ case 0: str = "Not restricted (privacy level 0)"; break;
+ case 1: str = "Restricted (privacy level 1)"; break;
+ case 2: str = "Confidential (privacy level 2)"; break;
+ case 3: str = "Secret (privacy level 3)"; break;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : %s",
+ ansi_637_bigbuf,
+ str);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+}
+
+static void
+tele_param_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : %s (manual) acknowledgment is requested",
+ ansi_637_bigbuf,
+ (oct & 0x80) ? "User" : "No user");
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : %s acknowledgment requested",
+ ansi_637_bigbuf,
+ (oct & 0x40) ? "Delivery" : "No delivery");
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+}
+
+static void
+tele_param_num_messages(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Number of voice mail messages: %d%d",
+ (oct & 0xf0) >> 4,
+ oct & 0x0f);
+}
+
+static void
+tele_param_alert(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch ((oct & 0xc0) >> 6)
+ {
+ case 0: str = "Use Mobile default alert"; break;
+ case 1: str = "Use Low-priority alert"; break;
+ case 2: str = "Use Medium-priority alert"; break;
+ case 3: str = "Use High-priority alert"; break;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : %s",
+ ansi_637_bigbuf,
+ str);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+}
+
+static void
+tele_param_lang_ind(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch (oct)
+ {
+ case 0x00: str = "Unknown or unspecified"; break;
+ case 0x01: str = "English"; break;
+ case 0x02: str = "French"; break;
+ case 0x03: str = "Spanish"; break;
+ case 0x04: str = "Japanese"; break;
+ case 0x05: str = "Korean"; break;
+ case 0x06: str = "Chinese"; break;
+ case 0x07: str = "Hebrew"; break;
+ default: str = "Reserved"; break;
+ }
+
+ proto_tree_add_text(tree, tvb, offset, 1,
+ str);
+}
+
+static void
+tele_param_cb_num(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, oct2, num_fields, odd;
+ guint32 saved_offset;
+ guint32 required_octs;
+ guint32 i;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Digit mode: %s",
+ ansi_637_bigbuf,
+ (oct & 0x80) ? "8-bit ASCII" : "4-bit DTMF");
+
+ if (oct & 0x80)
+ {
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Type of number: (%d)",
+ ansi_637_bigbuf,
+ (oct & 0x70) >> 4);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Numbering plan: (%d)",
+ ansi_637_bigbuf,
+ oct & 0x0f);
+
+ offset++;
+ num_fields = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xff, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number of fields: (%d)",
+ ansi_637_bigbuf,
+ num_fields);
+
+ if (num_fields == 0) return;
+
+ if (num_fields > (len - 2))
+ {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing %d octet(s) for number of fields",
+ (num_fields + 2) - len);
+
+ return;
+ }
+
+ offset++;
+
+ i = 0;
+ while (i < num_fields)
+ {
+ ansi_637_bigbuf[i] = tvb_get_guint8(tvb, offset+i) & 0x7f;
+ i++;
+ }
+ ansi_637_bigbuf[i] = '\0';
+
+ proto_tree_add_text(tree, tvb, offset, num_fields,
+ "Number: %s",
+ ansi_637_bigbuf);
+ }
+ else
+ {
+ offset++;
+ num_fields = (oct & 0x7f) << 1;
+ oct2 = tvb_get_guint8(tvb, offset);
+ num_fields |= ((oct2 & 0x80) >> 7);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree, tvb, offset-1, 1,
+ "%s : Number of fields (MBS): (%d)",
+ ansi_637_bigbuf,
+ num_fields);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x80, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number of fields (LSB)",
+ ansi_637_bigbuf);
+
+ oct = oct2;
+ odd = FALSE;
+
+ if (num_fields > 0)
+ {
+ i = (num_fields - 1) * 4;
+ required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+
+ if (required_octs + 2 > len)
+ {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing %d octet(s) for number of fields",
+ (required_octs + 2) - len);
+
+ return;
+ }
+
+ odd = num_fields & 0x01;
+ memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
+ saved_offset = offset;
+ offset++;
+
+ i = 0;
+ while (i < num_fields)
+ {
+ ansi_637_bigbuf[i] =
+ air_digits[(oct & 0x78) >> 3];
+
+ i++;
+ if (i >= num_fields) break;
+
+ oct2 = tvb_get_guint8(tvb, offset);
+ offset++;
+
+ ansi_637_bigbuf[i] =
+ air_digits[((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7)];
+
+ oct = oct2;
+
+ i++;
+ }
+
+ proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
+ "Number: %s",
+ ansi_637_bigbuf);
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x07: 0x7f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+ }
+}
+
+static void
+tele_param_disp_mode(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch ((oct & 0xc0) >> 6)
+ {
+ case 0: str = "Immediate Display: The mobile station is to display the received message as soon as possible."; break;
+ case 1: str = "Mobile default setting: The mobile station is to display the received message based on a pre-defined mode in the mobile station."; break;
+ case 2: str = "User Invoke: The mobile station is to display the received message based on the mode selected by the user."; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : %s",
+ ansi_637_bigbuf,
+ str);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+}
+
+#define NUM_TELE_PARAM (sizeof(ansi_tele_param_strings)/sizeof(value_string))
+static gint ett_ansi_637_tele_param[NUM_TELE_PARAM];
+static void (*ansi_637_tele_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
+ NULL, /* Message Identifier */
+ tele_param_user_data, /* User Data */
+ tele_param_rsp_code, /* User Response Code */
+ tele_param_timestamp, /* Message Center Time Stamp */
+ tele_param_timestamp, /* Validity Period Absolute */
+ tele_param_rel_timestamp, /* Validity Period Relative */
+ tele_param_timestamp, /* Deferred Delivery Time - Absolute */
+ tele_param_rel_timestamp, /* Deferred Delivery Time - Relative */
+ tele_param_pri_ind, /* Priority Indicator */
+ tele_param_priv_ind, /* Privacy Indicator */
+ tele_param_reply_opt, /* Reply Option */
+ tele_param_num_messages, /* Number of Messages */
+ tele_param_alert, /* Alert on Message Delivery */
+ tele_param_lang_ind, /* Language Indicator */
+ tele_param_cb_num, /* Call-Back Number */
+ tele_param_disp_mode, /* Message Display Mode */
+ NULL, /* Multiple Encoding User Data */
+ NULL, /* NONE */
+};
+
+static void
+trans_param_tele_id(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+ guint32 value;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 2);
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ ansi_637_trans_tele_id = value;
+
+ str = match_strval(value, ansi_tele_id_strings);
+
+ if (NULL == str) str = "Unrecognized Teleservice ID";
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s (%d)",
+ str,
+ value);
+
+ sprintf(add_string, " - %s (%d)", str, value);
+}
+
+static void
+trans_param_srvc_cat(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+ guint32 value;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 2);
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ str = match_strval(value, ansi_srvc_cat_strings);
+
+ if (NULL == str) str = "Reserved";
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ str);
+
+ sprintf(add_string, " - %s (%d)", str, value);
+}
+
+static void
+trans_param_address(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+ guint8 oct, oct2, num_fields, odd;
+ gboolean email_addr;
+ guint32 saved_offset;
+ guint32 required_octs;
+ guint32 i;
+ gchar *str;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ email_addr = FALSE;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Digit mode: %s",
+ ansi_637_bigbuf,
+ (oct & 0x80) ? "8-bit ASCII" : "4-bit DTMF");
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number mode: %s",
+ ansi_637_bigbuf,
+ (oct & 0x40) ? "Data Network Address" : "ANSI T1.607");
+
+ if (oct & 0x80)
+ {
+ if (oct & 0x40)
+ {
+ switch ((oct & 0x38) >> 3)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "Internet Protocol (RFC 791)"; break;
+ case 2: str = "Internet Email Address (RFC 822)"; email_addr = TRUE; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x38, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Type of number: %s (%d)",
+ ansi_637_bigbuf,
+ str,
+ (oct & 0x38) >> 3);
+
+ offset++;
+ num_fields = (oct & 0x07) << 5;
+ oct2 = tvb_get_guint8(tvb, offset);
+ num_fields |= ((oct2 & 0xf8) >> 3);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, offset-1, 1,
+ "%s : Number of fields (MSB): (%d)",
+ ansi_637_bigbuf,
+ num_fields);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf8, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number of fields (LSB)",
+ ansi_637_bigbuf);
+
+ if (num_fields == 0) return;
+
+ if (num_fields > (len - 2))
+ {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing %d octet(s) for number of fields",
+ (num_fields + 2) - len);
+
+ return;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x07, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Most significant bits of first field",
+ ansi_637_bigbuf);
+
+ offset++;
+ oct = oct2;
+
+ i = 0;
+ while (i < num_fields)
+ {
+ ansi_637_bigbuf[i] = (oct & 0x07) << 5;
+ ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0xf8) >> 3;
+ i++;
+ }
+ ansi_637_bigbuf[i] = '\0';
+
+ if (email_addr)
+ {
+ proto_tree_add_text(tree, tvb, offset, num_fields - 1,
+ "Number: %s",
+ ansi_637_bigbuf);
+ }
+ else
+ {
+ proto_tree_add_bytes(tree, hf_ansi_637_bin_addr, tvb, offset, num_fields - 1,
+ ansi_637_bigbuf);
+ }
+
+ offset += (num_fields - 1);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf8, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Least significant bits of last field",
+ ansi_637_bigbuf);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+ }
+ else
+ {
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x38, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Type of number: (%d)",
+ ansi_637_bigbuf,
+ (oct & 0x38) >> 3);
+
+ oct2 = tvb_get_guint8(tvb, offset + 1);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Numbering plan (MSB): (%d)",
+ ansi_637_bigbuf,
+ ((oct & 0x07) << 1) | ((oct2 & 0x80) >> 7));
+
+ offset++;
+ oct = oct2;
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Numbering plan (LSB)",
+ ansi_637_bigbuf);
+
+ offset++;
+ num_fields = (oct & 0x7f) << 1;
+ oct2 = tvb_get_guint8(tvb, offset);
+ num_fields |= ((oct2 & 0x80) >> 7);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree, tvb, offset-1, 1,
+ "%s : Number of fields (MSB): (%d)",
+ ansi_637_bigbuf,
+ num_fields);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x80, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number of fields (LSB)",
+ ansi_637_bigbuf);
+
+ if (num_fields == 0) return;
+
+ if (num_fields > (len - 3))
+ {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing %d octet(s) for number of fields",
+ (num_fields + 3) - len);
+
+ return;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x7f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Most significant bits of first field",
+ ansi_637_bigbuf);
+
+ offset++;
+ oct = oct2;
+
+ i = 0;
+ while (i < num_fields)
+ {
+ ansi_637_bigbuf[i] = (oct & 0x7f) << 1;
+ ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0x80) >> 7;
+ i++;
+ }
+ ansi_637_bigbuf[i] = '\0';
+
+ proto_tree_add_text(tree, tvb, offset, num_fields - 1,
+ "Number: %s",
+ ansi_637_bigbuf);
+
+ offset += (num_fields - 1);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Least significant bit of last field",
+ ansi_637_bigbuf);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+ }
+ }
+ else
+ {
+ offset++;
+ num_fields = (oct & 0x3f) << 2;
+ oct2 = tvb_get_guint8(tvb, offset);
+ num_fields |= ((oct2 & 0xc0) >> 6);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, offset-1, 1,
+ "%s : Number of fields (MSB): (%d)",
+ ansi_637_bigbuf,
+ num_fields);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number of fields (LSB)",
+ ansi_637_bigbuf);
+
+ oct = oct2;
+ odd = FALSE;
+
+ if (num_fields > 0)
+ {
+ i = (num_fields - 1) * 4;
+ required_octs = (i / 8) + ((i % 8) ? 1 : 0);
+
+ if (required_octs + 2 > len)
+ {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing %d octet(s) for number of fields",
+ (required_octs + 2) - len);
+
+ return;
+ }
+
+ odd = num_fields & 0x01;
+ memset((void *) ansi_637_bigbuf, 0, sizeof(ansi_637_bigbuf));
+ saved_offset = offset;
+ offset++;
+
+ i = 0;
+ while (i < num_fields)
+ {
+ ansi_637_bigbuf[i] =
+ air_digits[(oct & 0x3c) >> 2];
+
+ i++;
+ if (i >= num_fields) break;
+
+ oct2 = tvb_get_guint8(tvb, offset);
+ offset++;
+
+ ansi_637_bigbuf[i] =
+ air_digits[((oct & 0x03) << 2) | ((oct2 & 0xc0) >> 6)];
+
+ oct = oct2;
+
+ i++;
+ }
+
+ proto_tree_add_text(tree, tvb, saved_offset, offset - saved_offset,
+ "Number: %s",
+ ansi_637_bigbuf);
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, odd ? 0x03: 0x3f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+ }
+}
+
+static void
+trans_param_subaddress(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+ guint8 oct, oct2, num_fields;
+ guint32 i;
+ gchar *str;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch ((oct & 0xe0) >> 5)
+ {
+ case 0: str = "NSAP (CCITT Recommendation X.213 or ISO 8348 AD2)"; break;
+ case 1: str = "User-specified"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Type: %s",
+ ansi_637_bigbuf,
+ str);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Odd",
+ ansi_637_bigbuf);
+
+ offset++;
+ num_fields = (oct & 0x0f) << 4;
+ oct2 = tvb_get_guint8(tvb, offset);
+ num_fields |= ((oct2 & 0xf0) >> 4);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, offset-1, 1,
+ "%s : Number of fields (MSB): (%d)",
+ ansi_637_bigbuf,
+ num_fields);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number of fields (LSB)",
+ ansi_637_bigbuf);
+
+ if (num_fields == 0) return;
+
+ if (num_fields > (len - 2))
+ {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing %d octet(s) for number of fields",
+ (num_fields + 2) - len);
+
+ return;
+ }
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct2, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Most significant bits of first field",
+ ansi_637_bigbuf);
+
+ offset++;
+ oct = oct2;
+
+ i = 0;
+ while (i < num_fields)
+ {
+ ansi_637_bigbuf[i] = (oct & 0x0f) << 4;
+ ansi_637_bigbuf[i] |= ((oct = tvb_get_guint8(tvb, offset+i)) & 0xf0) >> 4;
+ i++;
+ }
+ ansi_637_bigbuf[i] = '\0';
+
+ proto_tree_add_bytes(tree, hf_ansi_637_bin_addr, tvb, offset, num_fields - 1,
+ ansi_637_bigbuf);
+
+ offset += (num_fields - 1);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Least significant bits of last field",
+ ansi_637_bigbuf);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+}
+
+static void
+trans_param_bearer_reply_opt(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+ guint8 oct;
+
+ len = len;
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reply Sequence Number: %d",
+ ansi_637_bigbuf,
+ (oct & 0xfc) >> 2);
+
+ sprintf(add_string, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ ansi_637_bigbuf);
+}
+
+static void
+trans_param_cause_codes(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+ guint8 oct;
+ gchar *str = NULL;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reply Sequence Number: %d",
+ ansi_637_bigbuf,
+ (oct & 0xfc) >> 2);
+
+ switch (oct & 0x03)
+ {
+ case 0x00: str = "No error"; break;
+ case 0x02: str = "Temporary Condition"; break;
+ case 0x03: str = "Permanent Condition"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ sprintf(add_string, " - Reply Sequence Number (%d)", (oct & 0xfc) >> 2);
+
+ other_decode_bitfield_value(ansi_637_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Error Class: %s",
+ ansi_637_bigbuf,
+ str);
+
+ offset++;
+
+ if (!(oct & 0x03)) return;
+
+ if (len == 1) return;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch (oct)
+ {
+ case 0: str = "Address vacant"; break;
+ case 1: str = "Address translation failure"; break;
+ case 2: str = "Network resource shortage"; break;
+ case 3: str = "Network failure"; break;
+ case 4: str = "Invalid Teleservice ID"; break;
+ case 5: str = "Other network problem"; break;
+ case 6: str = "Unsupported network interface"; break;
+ case 32: str = "No page response"; break;
+ case 33: str = "Destination busy"; break;
+ case 34: str = "No acknowledgement"; break;
+ case 35: str = "Destination resource shortage"; break;
+ case 36: str = "SMS delivery postponed"; break;
+ case 37: str = "Destination out of service"; break;
+ case 38: str = "Destination no longer at this address"; break;
+ case 39: str = "Other terminal problem"; break;
+ case 64: str = "Radio interface resource shortage"; break;
+ case 65: str = "Radio interface incompatibility"; break;
+ case 66: str = "Other radio interface problem"; break;
+ case 67: str = "Unsupported Base Station Capability"; break;
+ case 96: str = "Encoding problem"; break;
+ case 97: str = "Service origination denied"; break;
+ case 98: str = "Service termination denied"; break;
+ case 99: str = "Supplementary service not supported"; break;
+ case 100: str = "Service not supported"; break;
+ case 101: str = "Reserved"; break;
+ case 102: str = "Missing expected parameter"; break;
+ case 103: str = "Missing mandatory parameter"; break;
+ case 104: str = "Unrecognized parameter value"; break;
+ case 105: str = "Unexpected parameter value"; break;
+ case 106: str = "User Data size error"; break;
+ case 107: str = "Other general problems"; break;
+ case 108: str = "Session not active"; break;
+ default:
+ if ((oct >= 7) && (oct <= 31)) { str = "Reserved, treat as Other network problem"; }
+ else if ((oct >= 40) && (oct <= 47)) { str = "Reserved, treat as Other terminal problem"; }
+ else if ((oct >= 48) && (oct <= 63)) { str = "Reserved, treat as SMS delivery postponed"; }
+ else if ((oct >= 68) && (oct <= 95)) { str = "Reserved, treat as Other radio interface problem"; }
+ else if ((oct >= 109) && (oct <= 223)) { str = "Reserved, treat as Other general problems"; }
+ else { str = "Reserved for protocol extension, treat as Other general problems"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, tvb, offset, 1,
+ str);
+}
+
+static void
+trans_param_bearer_data(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string)
+{
+ tvbuff_t *tele_tvb;
+
+ add_string = add_string;
+
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Bearer Data");
+
+ /*
+ * dissect the embedded teleservice data
+ */
+ tele_tvb = tvb_new_subset(tvb, offset, len, len);
+
+ dissector_try_port(tele_dissector_table, ansi_637_trans_tele_id,
+ tele_tvb, g_pinfo, g_tree);
+}
+
+#define NUM_TRANS_PARAM (sizeof(ansi_trans_param_strings)/sizeof(value_string))
+static gint ett_ansi_637_trans_param[NUM_TRANS_PARAM];
+static void (*ansi_637_trans_param_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string) = {
+ trans_param_tele_id, /* Teleservice Identifier */
+ trans_param_srvc_cat, /* Service Category */
+ trans_param_address, /* Originating Address */
+ trans_param_subaddress, /* Originating Subaddress */
+ trans_param_address, /* Destination Address */
+ trans_param_subaddress, /* Destination Subaddress */
+ trans_param_bearer_reply_opt, /* Bearer Reply Option */
+ trans_param_cause_codes, /* Cause Codes */
+ trans_param_bearer_data, /* Bearer Data */
+ NULL, /* NONE */
+};
+
+#define NUM_TRANS_MSG_TYPE (sizeof(ansi_trans_msg_type_strings)/sizeof(value_string))
+static gint ett_ansi_637_trans_msg[NUM_TRANS_MSG_TYPE];
+
+/* GENERIC IS-637 DISSECTOR FUNCTIONS */
+
+static gboolean
+dissect_ansi_637_tele_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
+{
+ void (*param_fcn)(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = NULL;
+ guint8 oct;
+ guint8 len;
+ guint32 curr_offset;
+ gint ett_param_idx, idx;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str = NULL;
+
+
+ curr_offset = *offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+ str = my_match_strval((guint32) oct, ansi_tele_param_strings, &idx);
+
+ if (NULL == str)
+ {
+ return(FALSE);
+ }
+
+ ett_param_idx = ett_ansi_637_tele_param[idx];
+ param_fcn = ansi_637_tele_param_fcn[idx];
+
+ item =
+ proto_tree_add_text(tree, tvb, curr_offset, -1, str);
+
+ subtree = proto_item_add_subtree(item, ett_param_idx);
+
+ proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id,
+ tvb, curr_offset, 1, oct);
+
+ curr_offset++;
+
+ len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_item_set_len(item, (curr_offset - *offset) + len + 1);
+
+ proto_tree_add_uint(subtree, hf_ansi_637_length,
+ tvb, curr_offset, 1, len);
+
+ curr_offset++;
+
+ if (len > 0)
+ {
+ if (param_fcn == NULL)
+ {
+ proto_tree_add_text(subtree, tvb, curr_offset,
+ len, "Parameter Data");
+ }
+ else
+ {
+ (*param_fcn)(tvb, subtree, len, curr_offset);
+ }
+
+ curr_offset += len;
+ }
+
+ *offset = curr_offset;
+
+ return(TRUE);
+}
+
+static void
+dissect_ansi_637_tele_message(tvbuff_t *tvb, proto_tree *ansi_637_tree)
+{
+ guint8 oct;
+ guint8 len;
+ guint32 octs;
+ guint32 curr_offset;
+ guint32 msg_id;
+ guint32 msg_type;
+ gchar *str = NULL;
+ proto_item *item;
+ proto_tree *subtree;
+
+
+ oct = tvb_get_guint8(tvb, 0);
+ if (oct != 0x00)
+ {
+ return;
+ }
+
+ len = tvb_get_guint8(tvb, 1);
+ if (len != 3)
+ {
+ return;
+ }
+
+ octs = tvb_get_ntoh24(tvb, 2);
+ msg_type = (octs >> 20) & 0x0f;
+ msg_id = (octs >> 4) & 0xffff;
+
+ str = match_strval(msg_type, ansi_tele_msg_type_strings);
+
+ /*
+ * do not append to COL_INFO
+ */
+
+ item =
+ proto_tree_add_none_format(ansi_637_tree, hf_ansi_637_none,
+ tvb, 0, -1, str);
+
+ subtree = proto_item_add_subtree(item, ett_params);
+
+ proto_tree_add_uint(subtree, hf_ansi_637_tele_subparam_id,
+ tvb, 0, 1, oct);
+
+ proto_tree_add_uint(subtree, hf_ansi_637_length,
+ tvb, 1, 1, len);
+
+ proto_tree_add_uint(subtree, hf_ansi_637_tele_msg_type,
+ tvb, 2, 3, octs);
+
+ proto_tree_add_uint(subtree, hf_ansi_637_tele_msg_id,
+ tvb, 2, 3, octs);
+
+ proto_tree_add_uint(subtree, hf_ansi_637_tele_msg_rsvd,
+ tvb, 2, 3, octs);
+
+ proto_item_set_len(item, 2 + len);
+
+ curr_offset = 2 + len;
+ len = tvb_length(tvb);
+
+ while ((len - curr_offset) > 0)
+ {
+ if (!dissect_ansi_637_tele_param(tvb, ansi_637_tree, &curr_offset))
+ {
+ proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset,
+ "Unknown Parameter Data");
+ break;
+ }
+ }
+}
+
+static void
+dissect_ansi_637_tele(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ansi_637_item;
+ proto_tree *ansi_637_tree = NULL;
+ gchar *str = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree)
+ {
+ /*
+ * create the ansi_637 protocol tree
+ */
+ str = match_strval(pinfo->match_port, ansi_tele_id_strings);
+
+ if (NULL == str) str = "Unrecognized Teleservice ID";
+
+ ansi_637_item =
+ proto_tree_add_protocol_format(tree, proto_ansi_637_tele, tvb, 0, -1,
+ "%s - %s (%d)",
+ ansi_proto_name_tele,
+ str,
+ pinfo->match_port);
+
+ ansi_637_tree =
+ proto_item_add_subtree(ansi_637_item, ett_ansi_637_tele);
+
+ dissect_ansi_637_tele_message(tvb, ansi_637_tree);
+ }
+}
+
+static gboolean
+dissect_ansi_637_trans_param(tvbuff_t *tvb, proto_tree *tree, guint32 *offset)
+{
+ void (*param_fcn)(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset, gchar *add_string) = NULL;
+ guint8 oct;
+ guint8 len;
+ guint32 curr_offset;
+ gint ett_param_idx, idx;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str = NULL;
+
+ curr_offset = *offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+ str = my_match_strval((guint32) oct, ansi_trans_param_strings, &idx);
+
+ if (NULL == str)
+ {
+ return(FALSE);
+ }
+
+ ett_param_idx = ett_ansi_637_trans_param[idx];
+ param_fcn = ansi_637_trans_param_fcn[idx];
+
+ item =
+ proto_tree_add_text(tree, tvb, curr_offset, -1, str);
+
+ subtree = proto_item_add_subtree(item, ett_param_idx);
+
+ proto_tree_add_uint(subtree, hf_ansi_637_trans_param_id,
+ tvb, curr_offset, 1, oct);
+
+ curr_offset++;
+
+ len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_item_set_len(item, (curr_offset - *offset) + len + 1);
+
+ proto_tree_add_uint(subtree, hf_ansi_637_length,
+ tvb, curr_offset, 1, len);
+
+ curr_offset++;
+
+ if (len > 0)
+ {
+ if (param_fcn == NULL)
+ {
+ proto_tree_add_text(subtree, tvb, curr_offset,
+ len, "Parameter Data");
+ }
+ else
+ {
+ ansi_637_add_string[0] = '\0';
+ (*param_fcn)(tvb, subtree, len, curr_offset, ansi_637_add_string);
+
+ if (ansi_637_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, ansi_637_add_string);
+ }
+ }
+
+ curr_offset += len;
+ }
+
+ *offset = curr_offset;
+
+ return(TRUE);
+}
+
+static void
+dissect_ansi_637_trans(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ansi_637_item;
+ proto_tree *ansi_637_tree = NULL;
+ guint32 curr_offset;
+ gint idx;
+ gchar *str = NULL;
+ guint8 oct;
+ guint8 len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree)
+ {
+ g_pinfo = pinfo;
+ g_tree = tree;
+
+ /*
+ * create the ansi_637 protocol tree
+ */
+ oct = tvb_get_guint8(tvb, 0);
+
+ str = my_match_strval(oct, ansi_trans_msg_type_strings, &idx);
+
+ if (NULL == str)
+ {
+ ansi_637_item =
+ proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
+ "%s - Unrecognized Transport Layer Message Type (%d)",
+ ansi_proto_name_trans,
+ oct);
+
+ ansi_637_tree =
+ proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans);
+ }
+ else
+ {
+ ansi_637_item =
+ proto_tree_add_protocol_format(tree, proto_ansi_637_trans, tvb, 0, -1,
+ "%s - %s",
+ ansi_proto_name_trans,
+ str);
+
+ ansi_637_tree =
+ proto_item_add_subtree(ansi_637_item, ett_ansi_637_trans_msg[idx]);
+ }
+
+ curr_offset = 1;
+
+ len = tvb_length(tvb);
+
+ while ((len - curr_offset) > 0)
+ {
+ if (!dissect_ansi_637_trans_param(tvb, ansi_637_tree, &curr_offset))
+ {
+ proto_tree_add_text(ansi_637_tree, tvb, curr_offset, len - curr_offset,
+ "Unknown Parameter Data");
+ break;
+ }
+ }
+ }
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_ansi_637(void)
+{
+ guint i;
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] =
+ {
+ { &hf_ansi_637_trans_msg_type,
+ { "Message Type",
+ "ansi_637.trans_msg_type",
+ FT_UINT24, BASE_DEC, VALS(ansi_trans_msg_type_strings), 0xf00000,
+ "", HFILL }},
+ { &hf_ansi_637_tele_msg_type,
+ { "Message Type",
+ "ansi_637.tele_msg_type",
+ FT_UINT24, BASE_DEC, VALS(ansi_tele_msg_type_strings), 0xf00000,
+ "", HFILL }},
+ { &hf_ansi_637_tele_msg_id,
+ { "Message ID",
+ "ansi_637.tele_msg_id",
+ FT_UINT24, BASE_DEC, NULL, 0x0ffff0,
+ "", HFILL }},
+ { &hf_ansi_637_tele_msg_rsvd,
+ { "Reserved",
+ "ansi_637.tele_msg_rsvd",
+ FT_UINT24, BASE_DEC, NULL, 0x00000f,
+ "", HFILL }},
+ { &hf_ansi_637_length,
+ { "Length", "ansi_637.len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_637_none,
+ { "Sub tree", "ansi_637.none",
+ FT_NONE, 0, 0, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_637_tele_subparam_id,
+ { "Teleservice Subparam ID", "ansi_637.tele_subparam_id",
+ FT_UINT8, BASE_DEC, VALS(ansi_tele_param_strings), 0,
+ "", HFILL }
+ },
+ { &hf_ansi_637_trans_param_id,
+ { "Transport Param ID", "ansi_637.trans_param_id",
+ FT_UINT8, BASE_DEC, VALS(ansi_trans_param_strings), 0,
+ "", HFILL }
+ },
+ { &hf_ansi_637_bin_addr,
+ { "Binary Address", "ansi_637.bin_addr",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+#define NUM_INDIVIDUAL_PARAMS 3
+ static gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+NUM_TRANS_PARAM];
+
+ memset((void *) ett, 0, sizeof(ett));
+
+ ett[0] = &ett_ansi_637_tele;
+ ett[1] = &ett_ansi_637_trans;
+ ett[2] = &ett_params;
+
+ for (i=0; i < NUM_TELE_PARAM; i++)
+ {
+ ett_ansi_637_tele_param[i] = -1;
+ ett[NUM_INDIVIDUAL_PARAMS+i] = &ett_ansi_637_tele_param[i];
+ }
+
+ for (i=0; i < NUM_TRANS_MSG_TYPE; i++)
+ {
+ ett_ansi_637_trans_msg[i] = -1;
+ ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+i] = &ett_ansi_637_trans_msg[i];
+ }
+
+ for (i=0; i < NUM_TRANS_PARAM; i++)
+ {
+ ett_ansi_637_trans_param[i] = -1;
+ ett[NUM_INDIVIDUAL_PARAMS+NUM_TELE_PARAM+NUM_TRANS_MSG_TYPE+i] = &ett_ansi_637_trans_param[i];
+ }
+
+ /* Register the protocol name and description */
+ proto_ansi_637_tele =
+ proto_register_protocol(ansi_proto_name_tele, "ANSI IS-637-A Teleservice", "ansi_637_tele");
+
+ proto_ansi_637_trans =
+ proto_register_protocol(ansi_proto_name_trans, "ANSI IS-637-A Transport", "ansi_637_trans");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ansi_637_tele, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ tele_dissector_table =
+ register_dissector_table("ansi_637.tele_id",
+ "ANSI IS-637-A Teleservice ID", FT_UINT8, BASE_DEC);
+}
+
+
+void
+proto_reg_handoff_ansi_637(void)
+{
+ dissector_handle_t ansi_637_tele_handle;
+ dissector_handle_t ansi_637_trans_handle;
+ guint i;
+
+ ansi_637_tele_handle = create_dissector_handle(dissect_ansi_637_tele, proto_ansi_637_tele);
+ ansi_637_trans_handle = create_dissector_handle(dissect_ansi_637_trans, proto_ansi_637_trans);
+
+ /*
+ * register for all known teleservices
+ * '-1' is to stop before trailing '0' entry
+ *
+ * to add teleservices, modify 'ansi_tele_id_strings'
+ */
+ for (i=0; i < ((sizeof(ansi_tele_id_strings)/sizeof(value_string))-1); i++)
+ {
+ /*
+ * ANSI MAP dissector will push out teleservice ids
+ */
+ dissector_add("ansi_map.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
+
+ /*
+ * we will push out teleservice ids after Transport layer decode
+ */
+ dissector_add("ansi_637.tele_id", ansi_tele_id_strings[i].value, ansi_637_tele_handle);
+ }
+
+ /*
+ * ANSI A-interface will push out transport layer data
+ */
+ dissector_add("ansi_a.sms", 0, ansi_637_trans_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ansi_683.c b/epan/dissectors/packet-ansi_683.c
new file mode 100644
index 0000000000..0cecfa7a93
--- /dev/null
+++ b/epan/dissectors/packet-ansi_683.c
@@ -0,0 +1,2093 @@
+/* packet-ansi_683.c
+ * Routines for ANSI IS-683-A (OTA (Mobile)) dissection
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gmodule.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <string.h>
+
+#include "epan/packet.h"
+
+
+static char *ansi_proto_name = "ANSI IS-683-A (OTA (Mobile))";
+static char *ansi_proto_name_short = "IS-683-A";
+
+#define ANSI_683_FORWARD 0
+#define ANSI_683_REVERSE 1
+
+
+/* Initialize the subtree pointers */
+static gint ett_ansi_683 = -1;
+static gint ett_for_nam_block = -1;
+static gint ett_for_sspr_block = -1;
+static gint ett_rev_sspr_block = -1;
+static gint ett_rev_nam_block = -1;
+static gint ett_key_p = -1;
+static gint ett_key_g = -1;
+static gint ett_rev_feat = -1;
+static gint ett_for_val_block = -1;
+static gint ett_band_cap = -1;
+
+/* Initialize the protocol and registered fields */
+static int proto_ansi_683 = -1;
+static int hf_ansi_683_none = -1;
+static int hf_ansi_683_for_msg_type = -1;
+static int hf_ansi_683_rev_msg_type = -1;
+static int hf_ansi_683_length = -1;
+
+static char bigbuf[1024];
+static dissector_handle_t data_handle;
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
+
+
+/* FUNCTIONS */
+
+static gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr)
+ {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+
+/* PARAM FUNCTIONS */
+
+#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
+ if ((edc_len) > (edc_max_len)) \
+ { \
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb, \
+ offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
+ }
+
+#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
+ if ((sdc_len) < (sdc_min_len)) \
+ { \
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb, \
+ offset, (sdc_len), "Short Data (?)"); \
+ return; \
+ }
+
+#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
+ if ((edc_len) != (edc_eq_len)) \
+ { \
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb, \
+ offset, (edc_len), "Unexpected Data Length"); \
+ return; \
+ }
+
+static gchar *
+rev_feat_id_type(guint8 feat_id)
+{
+ gchar *str;
+
+ switch (feat_id)
+ {
+ case 0: str = "NAM Download (DATA_P_REV)"; break;
+ case 1: str = "Key Exchange (A_KEY_P_REV)"; break;
+ case 2: str = "System Selection for Preferred Roaming (SSPR_P_REV)"; break;
+ case 3: str = "Service Programming Lock (SPL_P_REV)"; break;
+ case 4: str = "Over-The-Air Parameter Administration (OTAPA_P_REV)"; break;
+ default:
+ if ((feat_id >= 5) && (feat_id <= 191)) { str = "Reserved for future standardization"; break; }
+ else if ((feat_id >= 192) && (feat_id <= 254)) { str = "Available for manufacturer-specific features"; break; }
+ else { str = "Reserved"; break; }
+ }
+
+ return(str);
+}
+
+static gchar *
+rev_res_code_type(guint8 res_code)
+{
+ gchar *str;
+
+ switch (res_code)
+ {
+ case 0: str = "Accepted - Operation successful"; break;
+ case 1: str = "Rejected - Unknown reason"; break;
+ case 2: str = "Rejected - Data size mismatch"; break;
+ case 3: str = "Rejected - Protocol version mismatch"; break;
+ case 4: str = "Rejected - Invalid parameter"; break;
+ case 5: str = "Rejected - SID/NID length mismatch"; break;
+ case 6: str = "Rejected - Message not expected in this mode"; break;
+ case 7: str = "Rejected - BLOCK_ID value not supported"; break;
+ case 8: str = "Rejected - Preferred roaming list length mismatch"; break;
+ case 9: str = "Rejected - CRC error"; break;
+ case 10: str = "Rejected - Mobile station locked"; break;
+ case 11: str = "Rejected - Invalid SPC"; break;
+ case 12: str = "Rejected - SPC change denied by the user"; break;
+ case 13: str = "Rejected - Invalid SPASM"; break;
+ case 14: str = "Rejected - BLOCK_ID not expected in this mode"; break;
+ default:
+ if ((res_code >= 15) && (res_code <= 127)) { str = "Reserved for future standardization"; break; }
+ else if ((res_code >= 128) && (res_code <= 254)) { str = "Available for manufacturer-specific Result Code definitions"; break; }
+ else { str = "Reserved"; break; }
+ }
+
+ return(str);
+}
+
+#define VERIFY_SPC_VAL_BLOCK 0
+#define CHANGE_SPC_VAL_BLOCK 1
+#define VALDATE_SPASM_VAL_BLOCK 2
+
+static gchar *
+for_val_param_block_type(guint8 block_type)
+{
+ gchar *str;
+
+ switch (block_type)
+ {
+ case 0: str = "Verify SPC"; break;
+ case 1: str = "Change SPC"; break;
+ case 2: str = "Validate SPASM"; break;
+ default:
+ if ((block_type >= 3) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
+ else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
+ else { str = "Reserved"; break; }
+ }
+
+ return(str);
+}
+
+static gchar *
+rev_sspr_param_block_type(guint8 block_type)
+{
+ gchar *str;
+
+ switch (block_type)
+ {
+ case 0: str = "Preferred Roaming List Dimensions"; break;
+ case 1: str = "Preferred Roaming List"; break;
+ default:
+ if ((block_type >= 2) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
+ else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
+ else { str = "Reserved"; break; }
+ }
+
+ return(str);
+}
+
+static gchar *
+for_sspr_param_block_type(guint8 block_type)
+{
+ gchar *str;
+
+ switch (block_type)
+ {
+ case 0: str = "Preferred Roaming List"; break;
+ default:
+ if ((block_type >= 1) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
+ else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
+ else { str = "Reserved"; break; }
+ }
+
+ return(str);
+}
+
+#define CDMA_ANALOG_NAM_BLOCK 0
+#define MDN_NAM_BLOCK 1
+#define CDMA_NAM_BLOCK 2
+#define IMSI_T_NAM_BLOCK 3
+
+static gchar *
+rev_nam_param_block_type(guint8 block_type)
+{
+ gchar *str;
+
+ switch (block_type)
+ {
+ case 0: str = "CDMA/Analog NAM"; break;
+ case 1: str = "Mobile Directory Number"; break;
+ case 2: str = "CDMA NAM"; break;
+ case 3: str = "IMSI_T"; break;
+ default:
+ if ((block_type >= 4) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
+ else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
+ else { str = "Reserved"; break; }
+ }
+
+ return(str);
+}
+
+static gchar *
+for_nam_param_block_type(guint8 block_type)
+{
+ gchar *str;
+
+ switch (block_type)
+ {
+ case 0: str = "CDMA/Analog NAM Download"; break;
+ case 1: str = "Mobile Directory Number"; break;
+ case 2: str = "CDMA NAM Download"; break;
+ case 3: str = "IMSI_T"; break;
+ default:
+ if ((block_type >= 4) && (block_type <= 127)) { str = "Reserved for future standardization"; break; }
+ else if ((block_type >= 128) && (block_type <= 254)) { str = "Available for manufacturer-specific parameter block definitions"; break; }
+ else { str = "Reserved"; break; }
+ }
+
+ return(str);
+}
+
+static void
+param_verify_spc_val_block(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 value;
+
+
+ EXACT_DATA_CHECK(len, 3);
+
+ saved_offset = offset;
+
+ value = tvb_get_ntoh24(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, len,
+ "Service programming code (%d)",
+ value);
+}
+
+static void
+param_cdma_analog_nam_block(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 value;
+ guint32 count;
+
+ saved_offset = offset;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0xffe0, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : First paging channel (FIRSTCHP) used in the home system (%d)",
+ bigbuf,
+ (value & 0xffe0) >> 5);
+
+ offset++;
+
+ value = tvb_get_ntoh24(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1fffc0, 24);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 3,
+ "%s : Home system identification (HOME_SID) (%d)",
+ bigbuf,
+ (value & 0x1fffc0) >> 6);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset + 2, 1,
+ "%s : Extended address indicator (EX)",
+ bigbuf);
+
+ offset += 2;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1fe0, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Station class mark (SCM) (%d)",
+ bigbuf,
+ (value & 0x1fe0) >> 5);
+
+ offset++;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1fe0, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Mobile station protocol revision number (MOB_P_REV) (%d)",
+ bigbuf,
+ (value & 0x1fe0) >> 5);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset + 1, 1,
+ "%s : IMSI_M Class assignment of the mobile station (IMSI_M_CLASS), Class %d",
+ bigbuf,
+ (value & 0x10) >> 4);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0e, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset + 1, 1,
+ "%s : Number of IMSI_M address digits (IMSI_M_ADDR_NUM) (%d), %d digits in NMSI",
+ bigbuf,
+ (value & 0x0e) >> 1,
+ (value & 0x10) ? ((value & 0x0e) >> 1) + 4 : 0);
+
+ offset++;
+
+ value = tvb_get_ntoh24(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01ff80, 24);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 3,
+ "%s : Mobile country code (MCC_M)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x7f, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset + 2, 1,
+ "%s : 11th and 12th digits of the IMSI_M (IMSI__M_11_12)",
+ bigbuf);
+
+ offset += 3;
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 5,
+ "The least significant 10 digits of the IMSI_M (IMSI_M_S) (34 bits)");
+
+ offset += 4;
+
+ value = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3c, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Access overload class (ACCOLC) (%d)",
+ bigbuf,
+ (value & 0x3c) >> 2);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Local control status (LOCAL_CONTROL)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Termination indicator for the home system (MOB_TERM_HOME)",
+ bigbuf);
+
+ offset++;
+
+ value = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Termination indicator for SID roaming (MOB_TERM_FOR_SID)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Termination indicator for NID roaming (MOB_TERM_FOR_NID)",
+ bigbuf);
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3fc0, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Maximum stored SID/NID pairs (MAX_SID_NID) (%d)",
+ bigbuf,
+ (value & 0x3fc0) >> 6);
+
+ offset++;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ count = (value & 0x3fc0) >> 6;
+
+ other_decode_bitfield_value(bigbuf, value, 0x3fc0, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Number of stored SID/NID pairs (STORED_SID_NID) (%d)",
+ bigbuf,
+ count);
+
+ other_decode_bitfield_value(bigbuf, value, 0x003f, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : SID/NID pairs (MSB)",
+ bigbuf);
+
+ offset += 2;
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, len - (offset - saved_offset),
+ "SID/NID pairs, Reserved");
+}
+
+static void
+param_mdn_nam_block(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 value, count, i;
+
+ memset((void *) bigbuf, 0, sizeof(bigbuf));
+
+ saved_offset = offset;
+
+ value = tvb_get_guint8(tvb, offset);
+
+ count = (value & 0xf0) >> 4;
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Number of digits (N_DIGITS) (%d)",
+ bigbuf,
+ count);
+
+ for (i=0; i < count; i++)
+ {
+ bigbuf[i] = 0x30 + (value & 0x0f);
+
+ if ((i + 1) < count)
+ {
+ offset++;
+ value = tvb_get_guint8(tvb, offset);
+ bigbuf[i+1] = 0x30 + (value & 0xf0);
+ i++;
+ }
+ }
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, saved_offset, len,
+ "Mobile directory number, %s",
+ bigbuf);
+
+ if (!(count & 0x01))
+ {
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+ }
+}
+
+static void
+param_cdma_nam_block(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 value;
+ guint32 count;
+
+ saved_offset = offset;
+
+ value = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Slotted Mode",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ offset++;
+
+ value = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Mobile station protocol revision number (MOB_P_REV) (%d)",
+ bigbuf,
+ value);
+
+ offset++;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x8000, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : IMSI_M Class assignment of the mobile station (IMSI_M_CLASS), Class %d",
+ bigbuf,
+ (value & 0x8000) >> 15);
+
+ other_decode_bitfield_value(bigbuf, value, 0x7000, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Number of IMSI_M address digits (IMSI_M_ADDR_NUM) (%d), %d digits in NMSI",
+ bigbuf,
+ (value & 0x7000) >> 12,
+ (value & 0x8000) ? ((value & 0x7000) >> 12) + 4 : 0);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0ffc, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Mobile country code (MCC_M)",
+ bigbuf);
+
+ offset++;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f80, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : 11th and 12th digits of the IMSI_M (IMSI__M_11_12)",
+ bigbuf);
+
+ offset++;
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 5,
+ "The least significant 10 digits of the IMSI_M (IMSI_M_S) (34 bits)");
+
+ offset += 4;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01e0, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Access overload class (ACCOLC) (%d)",
+ bigbuf,
+ (value & 0x01e0) >> 5);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset+1, 1,
+ "%s : Local control status (LOCAL_CONTROL)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset+1, 1,
+ "%s : Termination indicator for the home system (MOB_TERM_HOME)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset+1, 1,
+ "%s : Termination indicator for SID roaming (MOB_TERM_FOR_SID)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset+1, 1,
+ "%s : Termination indicator for NID roaming (MOB_TERM_FOR_NID)",
+ bigbuf);
+
+ offset++;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01fe, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Maximum stored SID/NID pairs (MAX_SID_NID) (%d)",
+ bigbuf,
+ (value & 0x01fe) >> 1);
+
+ offset++;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ count = (value & 0x01fe) >> 1;
+
+ other_decode_bitfield_value(bigbuf, value, 0x01fe, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Number of stored SID/NID pairs (STORED_SID_NID) (%d)",
+ bigbuf,
+ count);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset+1, 1,
+ "%s : SID/NID pairs (MSB)",
+ bigbuf);
+
+ offset += 2;
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, len - (offset - saved_offset),
+ "SID/NID pairs, Reserved");
+}
+
+static void
+param_imsi_t_nam_block(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 value;
+
+ /*
+ * XXX avoid warning for now, may use this variable
+ * for validation later
+ */
+ len = len;
+
+ saved_offset = offset;
+
+ value = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : IMSI_T Class assignment of the mobile station (IMSI_T_CLASS), Class %d",
+ bigbuf,
+ (value & 0x80) >> 7);
+
+ other_decode_bitfield_value(bigbuf, value, 0x70, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Number of IMSI_T address digits (IMSI_T_ADDR_NUM ) (%d), %d digits in NMSI",
+ bigbuf,
+ (value & 0x70) >> 4,
+ (value & 0x80) ? ((value & 0x70) >> 4) + 4 : 0);
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0ffc, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Mobile country code (MCC_T)",
+ bigbuf);
+
+ offset++;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03f8, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : 11th and 12th digits of the IMSI_T (IMSI__T_11_12)",
+ bigbuf);
+
+ offset++;
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 5,
+ "The least significant 10 digits of the IMSI_T (IMSI_T_S) (34 bits)");
+
+ offset += 4;
+
+ value = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+}
+
+static void
+msg_config_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, num_blocks;
+ gchar *str = NULL;
+ guint32 i, saved_offset;
+
+ SHORT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ num_blocks = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Number of parameter blocks (%d)",
+ num_blocks);
+
+ offset++;
+
+ if (num_blocks > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ for (i=0; i < num_blocks; i++)
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_nam_param_block_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ offset++;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_download_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, block_id, block_len;
+ gchar *str = NULL;
+ proto_tree *subtree;
+ proto_item *item;
+ guint32 i, saved_offset;
+
+ SHORT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Number of parameter blocks (%d)",
+ oct);
+
+ offset++;
+
+ for (i=0; i < oct; i++)
+ {
+ block_id = tvb_get_guint8(tvb, offset);
+
+ str = for_nam_param_block_type(block_id);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ block_id);
+
+ subtree = proto_item_add_subtree(item, ett_for_nam_block);
+ offset++;
+
+ block_len = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(subtree, hf_ansi_683_length,
+ tvb, offset, 1, block_len);
+ offset++;
+
+ if (block_len > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ if (block_len > 0)
+ {
+ switch (block_id)
+ {
+ case CDMA_ANALOG_NAM_BLOCK:
+ param_cdma_analog_nam_block(tvb, subtree, block_len, offset);
+ break;
+
+ case MDN_NAM_BLOCK:
+ param_mdn_nam_block(tvb, subtree, block_len, offset);
+ break;
+
+ case CDMA_NAM_BLOCK:
+ param_cdma_nam_block(tvb, subtree, block_len, offset);
+ break;
+
+ case IMSI_T_NAM_BLOCK:
+ param_imsi_t_nam_block(tvb, subtree, block_len, offset);
+ break;
+
+ default:
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, block_len, "Block Data");
+ break;
+ }
+
+ offset += block_len;
+ }
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_ms_key_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, param_len;
+ proto_tree *subtree;
+ proto_item *item;
+ guint32 saved_offset;
+
+ SHORT_DATA_CHECK(len, 3);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "A-Key Protocol Revision (%d)",
+ oct);
+ offset++;
+
+ param_len = tvb_get_guint8(tvb, offset);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, param_len + 1,
+ "Key exchange parameter P");
+ subtree = proto_item_add_subtree(item, ett_key_p);
+
+ proto_tree_add_uint(subtree, hf_ansi_683_length,
+ tvb, offset, 1, param_len);
+ offset++;
+
+ if (param_len > 0)
+ {
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, param_len,
+ "Parameter P");
+ offset += param_len;
+ }
+
+ param_len = tvb_get_guint8(tvb, offset);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, param_len + 1,
+ "Key exchange parameter G");
+ subtree = proto_item_add_subtree(item, ett_key_g);
+
+ proto_tree_add_uint(subtree, hf_ansi_683_length,
+ tvb, offset, 1, param_len);
+ offset++;
+
+ if (param_len > 0)
+ {
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, param_len,
+ "Parameter G");
+ offset += param_len;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_key_gen_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 param_len;
+ guint32 saved_offset;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ saved_offset = offset;
+
+ param_len = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(tree, hf_ansi_683_length,
+ tvb, offset, 1, param_len);
+ offset++;
+
+ if (param_len > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ if (param_len > 0)
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, param_len,
+ "Calculation Result");
+ offset += param_len;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_reauth_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+
+ EXACT_DATA_CHECK(len, 4);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 4,
+ "Random Challenge value");
+}
+
+static void
+msg_sspr_config_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+ guint32 saved_offset;
+ guint32 value;
+ proto_tree *subtree;
+ proto_item *item;
+
+ SHORT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_sspr_param_block_type(oct);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ offset++;
+
+ if (oct == 0x01)
+ {
+ subtree = proto_item_add_subtree(item, ett_rev_sspr_block);
+
+ if ((len - (offset - saved_offset)) < 3)
+ {
+ proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "Segment offset (%d)",
+ value);
+ offset += 2;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Maximum segment size (%d)",
+ oct);
+ offset++;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_sspr_download_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, block_len;
+ gchar *str = NULL;
+ guint32 saved_offset;
+ proto_tree *subtree;
+ proto_item *item;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = for_sspr_param_block_type(oct);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ subtree = proto_item_add_subtree(item, ett_for_sspr_block);
+ offset++;
+
+ block_len = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(subtree, hf_ansi_683_length,
+ tvb, offset, 1, block_len);
+ offset++;
+
+ if (block_len > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ if (block_len > 0)
+ {
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, block_len, "Block Data");
+ offset += block_len;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_validate_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, block_id, block_len;
+ gchar *str = NULL;
+ proto_tree *subtree;
+ proto_item *item;
+ guint32 i, saved_offset, block_offset;
+
+ SHORT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Number of parameter blocks (%d)",
+ oct);
+
+ offset++;
+
+ if ((guint32)(oct * 2) > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ for (i=0; i < oct; i++)
+ {
+ block_offset = offset;
+ block_id = tvb_get_guint8(tvb, offset);
+
+ str = for_val_param_block_type(block_id);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, -1,
+ str);
+
+ subtree = proto_item_add_subtree(item, ett_for_val_block);
+
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Block ID (%d)",
+ block_id);
+
+ offset++;
+
+ block_len = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(subtree, hf_ansi_683_length,
+ tvb, offset, 1, block_len);
+
+ offset++;
+
+ proto_item_set_len(item, (offset - block_offset) + block_len);
+
+ if (block_len > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ if (block_len > 0)
+ {
+ switch (block_id)
+ {
+ case VERIFY_SPC_VAL_BLOCK:
+ param_verify_spc_val_block(tvb, subtree, block_len, offset);
+ break;
+
+ case CHANGE_SPC_VAL_BLOCK:
+ case VALDATE_SPASM_VAL_BLOCK:
+ default:
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, block_len, "Block Data");
+ break;
+ }
+
+ offset += block_len;
+ }
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_otapa_req(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ guint32 saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : %s OTAPA session",
+ bigbuf,
+ (oct & 0x80) ? "Start" : "Stop");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ offset++;
+}
+
+static void
+msg_config_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, num_blocks, block_len;
+ gchar *str = NULL;
+ guint32 i, saved_offset;
+ proto_tree *subtree;
+ proto_item *item;
+
+ SHORT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ num_blocks = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Number of parameter blocks (%d)",
+ num_blocks);
+
+ offset++;
+
+ if ((guint32)(num_blocks * 2) > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ for (i=0; i < num_blocks; i++)
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_nam_param_block_type(oct);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ subtree = proto_item_add_subtree(item, ett_rev_nam_block);
+ offset++;
+
+ block_len = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(subtree, hf_ansi_683_length,
+ tvb, offset, 1, block_len);
+ offset++;
+
+ if (block_len > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(subtree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ if (block_len > 0)
+ {
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, block_len, "Block Data");
+ offset += block_len;
+ }
+ }
+
+ if (num_blocks > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ for (i=0; i < num_blocks; i++)
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_res_code_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ offset++;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_download_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, num_blocks;
+ gchar *str = NULL;
+ guint32 i, saved_offset;
+ proto_tree *subtree;
+ proto_item *item;
+
+ SHORT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ num_blocks = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Number of parameter blocks (%d)",
+ num_blocks);
+
+ offset++;
+
+ if ((guint32)(num_blocks * 2) > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ for (i=0; i < num_blocks; i++)
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = for_nam_param_block_type(oct);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ subtree = proto_item_add_subtree(item, ett_for_nam_block);
+ offset++;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_res_code_type(oct);
+
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ offset++;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_ms_key_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+ guint32 saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_res_code_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Key exchange result code, %s (%d)",
+ str,
+ oct);
+
+ offset++;
+}
+
+static void
+msg_key_gen_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, result_len;
+ gchar *str = NULL;
+ guint32 saved_offset;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_res_code_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Key exchange result code, %s (%d)",
+ str,
+ oct);
+
+ offset++;
+
+ result_len = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(tree, hf_ansi_683_length,
+ tvb, offset, 1, result_len);
+ offset++;
+
+ if (result_len > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ if (result_len > 0)
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, result_len, "Calculation Result");
+ offset += result_len;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_reauth_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 value;
+
+ EXACT_DATA_CHECK(len, 7);
+
+ saved_offset = offset;
+
+ value = tvb_get_ntoh24(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0xffffc0, 24);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 3,
+ "%s : Authentication signature data (AUTHR) (%d)",
+ bigbuf,
+ (value & 0xffffc0) >> 6);
+
+ offset += 2;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3fc0, 16);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "%s : Random challenge value (RANDC) (%d)",
+ bigbuf,
+ (value & 0x3fc0) >> 6);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset + 1, 1,
+ "%s : Call history parameter (COUNT) (%d)",
+ bigbuf,
+ value & 0x3f);
+
+ offset += 2;
+
+ value = tvb_get_ntoh24(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value, 0xffffff, 24);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 3,
+ "%s : Authentication Data input parameter (AUTH_DATA) (%d)",
+ bigbuf,
+ value);
+}
+
+static void
+msg_commit_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+ guint32 saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_res_code_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Data commit result code, %s (%d)",
+ str,
+ oct);
+
+ offset++;
+}
+
+static void
+msg_protocap_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, num_feat, add_len;
+ gchar *str = NULL;
+ guint32 i, saved_offset;
+ guint32 value;
+ proto_tree *subtree;
+ proto_item *item;
+
+ SHORT_DATA_CHECK(len, 5);
+
+ saved_offset = offset;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "Mobile station firmware revision number (%d)",
+ value);
+
+ offset += 2;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Mobile station manufacturer’s model number (%d)",
+ oct);
+
+ offset++;
+
+ num_feat = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Number of features (%d)",
+ num_feat);
+
+ offset++;
+
+ if ((guint32)(num_feat * 2) > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ for (i=0; i < num_feat; i++)
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_feat_id_type(oct);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Feature ID, %s (%d)",
+ str,
+ oct);
+
+ subtree = proto_item_add_subtree(item, ett_rev_feat);
+ offset++;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Feature protocol version (%d)",
+ oct);
+
+ offset++;
+ }
+
+ add_len = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(tree, hf_ansi_683_length,
+ tvb, offset, 1, add_len);
+ offset++;
+
+ if (add_len > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ if (add_len > 0)
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Band/Mode Capability Information");
+
+ subtree = proto_item_add_subtree(item, ett_band_cap);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Band Class 0 Analog",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Band Class 0 CDMA",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Band Class 1 CDMA",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ offset++;
+
+ if (add_len > 1)
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, add_len - 1,
+ "More Additional Fields");
+ offset += (add_len - 1);
+ }
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_sspr_config_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, block_len;
+ gchar *str = NULL;
+ guint32 saved_offset;
+
+ SHORT_DATA_CHECK(len, 3);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_sspr_param_block_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ offset++;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_res_code_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "SSPR Configuration result code, %s (%d)",
+ str,
+ oct);
+
+ offset++;
+
+ block_len = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(tree, hf_ansi_683_length,
+ tvb, offset, 1, block_len);
+ offset++;
+
+ if (block_len > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ if (block_len > 0)
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, block_len, "Block Data");
+ offset += block_len;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_sspr_download_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+ guint32 saved_offset;
+ guint32 value;
+
+ EXACT_DATA_CHECK(len, 5);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = for_sspr_param_block_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ offset++;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_res_code_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "SSPR Download result code, %s (%d)",
+ str,
+ oct);
+
+ offset++;
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 2,
+ "Segment offset (%d)",
+ value);
+ offset += 2;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Maximum segment size (%d)",
+ oct);
+ offset++;
+}
+
+static void
+msg_validate_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct, block_id, num_blocks;
+ gchar *str = NULL;
+ guint32 i, saved_offset;
+ proto_tree *subtree;
+ proto_item *item;
+
+ SHORT_DATA_CHECK(len, 1);
+
+ saved_offset = offset;
+
+ num_blocks = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "Number of parameter blocks (%d)",
+ num_blocks);
+
+ offset++;
+
+ if ((guint32)(num_blocks * 2) > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ for (i=0; i < num_blocks; i++)
+ {
+ block_id = tvb_get_guint8(tvb, offset);
+
+ str = for_val_param_block_type(block_id);
+
+ item =
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ block_id);
+
+ subtree = proto_item_add_subtree(item, ett_for_val_block);
+ offset++;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_res_code_type(oct);
+
+ proto_tree_add_none_format(subtree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ offset++;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static void
+msg_otapa_rsp(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint8 oct;
+ gchar *str = NULL;
+ guint32 saved_offset;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ saved_offset = offset;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ str = rev_res_code_type(oct);
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s (%d)",
+ str,
+ oct);
+
+ offset++;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0xfe, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 1,
+ "%s : NAM_LOCK indicator",
+ bigbuf);
+
+ offset++;
+
+ if (oct & 0x01)
+ {
+ if (4 > (len - (offset - saved_offset)))
+ {
+ proto_tree_add_none_format(tree, hf_ansi_683_none, tvb,
+ offset, len - (offset - saved_offset), "Short Data (?)");
+ return;
+ }
+
+ proto_tree_add_none_format(tree, hf_ansi_683_none,
+ tvb, offset, 4,
+ "SPASM random challenge");
+ offset += 4;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static const value_string for_msg_type_strings[] = {
+ { 0, "Configuration Request" },
+ { 1, "Download Request" },
+ { 2, "MS Key Request" },
+ { 3, "Key Generation Request" },
+ { 4, "Re-Authenticate Request" },
+ { 5, "Commit Request" },
+ { 6, "Protocol Capability Request" },
+ { 7, "SSPR Configuration Request" },
+ { 8, "SSPR Download Request" },
+ { 9, "Validation Request" },
+ { 10, "OTAPA Request" },
+ { 0, NULL },
+};
+#define NUM_FOR_MSGS (sizeof(for_msg_type_strings)/sizeof(value_string))
+static void (*ansi_683_for_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
+ msg_config_req, /* Configuration Request */
+ msg_download_req, /* Download Request */
+ msg_ms_key_req, /* MS Key Request */
+ msg_key_gen_req, /* Key Generation Request */
+ msg_reauth_req, /* Re-Authenticate Request */
+ NULL /* No data */, /* Commit Request */
+ NULL /* No data */, /* Protocol Capability Request */
+ msg_sspr_config_req, /* SSPR Configuration Request */
+ msg_sspr_download_req, /* SSPR Download Request */
+ msg_validate_req, /* Validation Request */
+ msg_otapa_req, /* OTAPA Request */
+ NULL, /* NONE */
+};
+
+static const value_string rev_msg_type_strings[] = {
+ { 0, "Configuration Response" },
+ { 1, "Download Response" },
+ { 2, "MS Key Response" },
+ { 3, "Key Generation Response" },
+ { 4, "Re-Authenticate Response" },
+ { 5, "Commit Response" },
+ { 6, "Protocol Capability Response" },
+ { 7, "SSPR Configuration Response" },
+ { 8, "SSPR Download Response" },
+ { 9, "Validation Response" },
+ { 10, "OTAPA Response" },
+ { 0, NULL },
+};
+#define NUM_REV_MSGS (sizeof(rev_msg_type_strings)/sizeof(value_string))
+static void (*ansi_683_rev_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
+ msg_config_rsp, /* Configuration Response */
+ msg_download_rsp, /* Download Response */
+ msg_ms_key_rsp, /* MS Key Response */
+ msg_key_gen_rsp, /* Key Generation Response */
+ msg_reauth_rsp, /* Re-Authenticate Response */
+ msg_commit_rsp, /* Commit Response */
+ msg_protocap_rsp, /* Protocol Capability Response */
+ msg_sspr_config_rsp, /* SSPR Configuration Response */
+ msg_sspr_download_rsp, /* SSPR Download Response */
+ msg_validate_rsp, /* Validation Response */
+ msg_otapa_rsp, /* OTAPA Response */
+ NULL, /* NONE */
+};
+
+
+static void
+dissect_ansi_683_for_message(tvbuff_t *tvb, proto_tree *ansi_683_tree)
+{
+ guint8 msg_type;
+ gint idx;
+ gchar *str = NULL;
+
+
+ msg_type = tvb_get_guint8(tvb, 0);
+
+ str = my_match_strval(msg_type, for_msg_type_strings, &idx);
+
+ if (str == NULL)
+ {
+ return;
+ }
+
+ /*
+ * No Information column data
+ */
+
+ proto_tree_add_uint(ansi_683_tree, hf_ansi_683_for_msg_type,
+ tvb, 0, 1, msg_type);
+
+ if (ansi_683_for_msg_fcn[idx] != NULL)
+ {
+ (*ansi_683_for_msg_fcn[idx])(tvb, ansi_683_tree, tvb_length(tvb) - 1, 1);
+ }
+}
+
+static void
+dissect_ansi_683_rev_message(tvbuff_t *tvb, proto_tree *ansi_683_tree)
+{
+ guint8 msg_type;
+ gint idx;
+ gchar *str = NULL;
+
+
+ msg_type = tvb_get_guint8(tvb, 0);
+
+ str = my_match_strval(msg_type, rev_msg_type_strings, &idx);
+
+ if (str == NULL)
+ {
+ return;
+ }
+
+ /*
+ * No Information column data
+ */
+
+ proto_tree_add_uint(ansi_683_tree, hf_ansi_683_rev_msg_type,
+ tvb, 0, 1, msg_type);
+
+ (*ansi_683_rev_msg_fcn[idx])(tvb, ansi_683_tree, tvb_length(tvb) - 1, 1);
+}
+
+static void
+dissect_ansi_683(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ansi_683_item;
+ proto_tree *ansi_683_tree = NULL;
+
+ g_pinfo = pinfo;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree)
+ {
+ g_tree = tree;
+
+ /*
+ * create the ansi_683 protocol tree
+ */
+ ansi_683_item =
+ proto_tree_add_protocol_format(tree, proto_ansi_683, tvb, 0, -1,
+ "%s %s Link",
+ ansi_proto_name,
+ (pinfo->match_port == ANSI_683_FORWARD) ? "Forward" : "Reverse");
+
+ ansi_683_tree =
+ proto_item_add_subtree(ansi_683_item, ett_ansi_683);
+
+ if (pinfo->match_port == ANSI_683_FORWARD)
+ {
+ dissect_ansi_683_for_message(tvb, ansi_683_tree);
+ }
+ else
+ {
+ dissect_ansi_683_rev_message(tvb, ansi_683_tree);
+ }
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_ansi_683(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] =
+ {
+ { &hf_ansi_683_for_msg_type,
+ { "Forward Link Message Type",
+ "ansi_683.for_msg_type",
+ FT_UINT8, BASE_DEC, VALS(for_msg_type_strings), 0,
+ "", HFILL }},
+ { &hf_ansi_683_rev_msg_type,
+ { "Reverse Link Message Type",
+ "ansi_683.rev_msg_type",
+ FT_UINT8, BASE_DEC, VALS(rev_msg_type_strings), 0,
+ "", HFILL }},
+ { &hf_ansi_683_length,
+ { "Length", "ansi_683.len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_683_none,
+ { "Sub tree", "ansi_683.none",
+ FT_NONE, 0, 0, 0,
+ "", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+#define NUM_INDIVIDUAL_PARAMS 10
+ static gint *ett[NUM_INDIVIDUAL_PARAMS];
+
+ memset((void *) ett, 0, sizeof(ett));
+
+ ett[0] = &ett_ansi_683;
+ ett[1] = &ett_for_nam_block;
+ ett[2] = &ett_rev_nam_block;
+ ett[3] = &ett_key_p;
+ ett[4] = &ett_key_g;
+ ett[5] = &ett_rev_feat;
+ ett[6] = &ett_for_val_block;
+ ett[7] = &ett_for_sspr_block;
+ ett[8] = &ett_band_cap;
+ ett[9] = &ett_rev_sspr_block;
+
+ /* Register the protocol name and description */
+ proto_ansi_683 =
+ proto_register_protocol(ansi_proto_name, "ANSI IS-683-A (OTA (Mobile))", "ansi_683");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ansi_683, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_ansi_683(void)
+{
+ dissector_handle_t ansi_683_handle;
+
+ ansi_683_handle = create_dissector_handle(dissect_ansi_683, proto_ansi_683);
+
+ dissector_add("ansi_map.ota", ANSI_683_FORWARD, ansi_683_handle);
+ dissector_add("ansi_map.ota", ANSI_683_REVERSE, ansi_683_handle);
+ dissector_add("ansi_a.ota", ANSI_683_FORWARD, ansi_683_handle);
+ dissector_add("ansi_a.ota", ANSI_683_REVERSE, ansi_683_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ansi_801.c b/epan/dissectors/packet-ansi_801.c
new file mode 100644
index 0000000000..0dc32b518a
--- /dev/null
+++ b/epan/dissectors/packet-ansi_801.c
@@ -0,0 +1,956 @@
+/* packet-ansi_801.c
+ * Routines for ANSI IS-801 (Location Services (PLD)) dissection
+ *
+ * Location Services (Position Determination Service)
+ * 3GPP2 C.S0022-0 v1.0 IS-801
+ *
+ * Location Services (Position Determination Service)
+ * 3GPP2 C.S0022-0-1 v1.0 IS-801 Addendum
+ *
+ * Copyright 2004, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gmodule.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <string.h>
+
+#include "epan/packet.h"
+
+
+static char *ansi_proto_name = "ANSI IS-801 (Location Services (PLD))";
+static char *ansi_proto_name_short = "IS-801";
+
+#define ANSI_801_FORWARD 0
+#define ANSI_801_REVERSE 1
+
+
+/* Initialize the subtree pointers */
+static gint ett_ansi_801 = -1;
+
+/* Initialize the protocol and registered fields */
+static int proto_ansi_801 = -1;
+static int hf_ansi_801_for_req_type = -1;
+static int hf_ansi_801_for_rsp_type = -1;
+static int hf_ansi_801_rev_req_type = -1;
+static int hf_ansi_801_rev_rsp_type = -1;
+static int hf_ansi_801_for_sess_tag = -1;
+static int hf_ansi_801_rev_sess_tag = -1;
+static int hf_ansi_801_sess_tag = -1;
+
+static char bigbuf[1024];
+static dissector_handle_t data_handle;
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
+
+
+/* FUNCTIONS */
+
+static gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr)
+ {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+
+/* PARAM FUNCTIONS */
+
+#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
+ if ((edc_len) > (edc_max_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
+ }
+
+#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
+ if ((sdc_len) < (sdc_min_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ offset, (sdc_len), "Short Data (?)"); \
+ return; \
+ }
+
+#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
+ if ((edc_len) != (edc_eq_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ offset, (edc_len), "Unexpected Data Length"); \
+ return; \
+ }
+
+
+static void
+for_req_pseudo_meas(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset)
+{
+ guint32 value;
+ guint32 saved_offset;
+
+ SHORT_DATA_CHECK(len, 3);
+
+ saved_offset = offset;
+
+ value = tvb_get_ntoh24(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, value >> 16, 0xe0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Preferred response quality, %u",
+ bigbuf,
+ (value & 0xe00000) >> 21);
+
+ other_decode_bitfield_value(bigbuf, value >> 16, 0x1f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number of fixes (MSB), %u",
+ bigbuf,
+ (value & 0x1fe000) >> 13);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0xe0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number of fixes (LSB)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0x1f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Time between fixes (MSB), %u",
+ bigbuf,
+ (value & 0x001fe0) >> 5);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Time between fixes (LSB)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Offset %srequested",
+ bigbuf,
+ (value & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ offset += 3;
+
+ EXTRANEOUS_DATA_CHECK(len, offset - saved_offset);
+}
+
+static const value_string for_req_type_strings[] = {
+ { 0, "Reserved" },
+ { 2, "Request MS Information" },
+ { 3, "Request Autonomous Measurement Weighting Factors" },
+ { 4, "Request Pseudorange Measurement" },
+ { 5, "Request Pilot Phase Measurement" },
+ { 1, "Request Location Response" },
+ { 6, "Request Time Offset Measurement" },
+ { 7, "Request Cancellation" },
+ { 0, NULL },
+};
+#define NUM_FOR_REQ_TYPE (sizeof(for_req_type_strings)/sizeof(value_string))
+static gint ett_for_req_type[NUM_FOR_REQ_TYPE];
+static void (*for_req_type_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
+ NULL, /* Reserved */
+ NULL, /* Request MS Information */
+ NULL, /* Request Autonomous Measurement Weighting Factors */
+ for_req_pseudo_meas, /* Request Pseudorange Measurement */
+ NULL, /* Request Pilot Phase Measurement */
+ NULL, /* Request Location Response */
+ NULL, /* Request Time Offset Measurement */
+ NULL, /* Request Cancellation */
+ NULL, /* NONE */
+};
+
+static const value_string for_rsp_type_strings[] = {
+ { 0, "Reject" },
+ { 2, "Provide BS Capabilities" },
+ { 4, "Provide GPS Acquisition Assistance" },
+ { 6, "Provide GPS Location Assistance Spherical Coordinates" },
+ { 7, "Provide GPS Location Assistance Cartesian Coordinates" },
+ { 5, "Provide GPS Sensitivity Assistance" },
+ { 3, "Provide Base Station Almanac" },
+ { 8, "Provide GPS Almanac" },
+ { 9, "Provide GPS Ephemeris" },
+ { 10, "Provide GPS Navigation Message Bits" },
+ { 1, "Provide Location Response" },
+ { 11, "Provide GPS Almanac Correction" },
+ { 12, "Provide GPS Satellite Health Information" },
+ { 0, NULL },
+};
+#define NUM_FOR_RSP_TYPE (sizeof(for_rsp_type_strings)/sizeof(value_string))
+static gint ett_for_rsp_type[NUM_FOR_RSP_TYPE];
+static void (*for_rsp_type_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
+ NULL, /* Reject */
+ NULL, /* Provide BS Capabilities */
+ NULL, /* Provide GPS Acquisition Assistance */
+ NULL, /* Provide GPS Location Assistance Spherical Coordinates */
+ NULL, /* Provide GPS Location Assistance Cartesian Coordinates */
+ NULL, /* Provide GPS Sensitivity Assistance */
+ NULL, /* Provide Base Station Almanac */
+ NULL, /* Provide GPS Almanac */
+ NULL, /* Provide GPS Ephemeris */
+ NULL, /* Provide GPS Navigation Message Bits */
+ NULL, /* Provide Location Response */
+ NULL, /* Provide GPS Almanac Correction */
+ NULL, /* Provide GPS Satellite Health Information */
+ NULL, /* NONE */
+};
+
+static const value_string rev_req_type_strings[] = {
+ { 0, "Reserved" },
+ { 2, "Request BS Capabilities" },
+ { 4, "Request GPS Acquisition Assistance" },
+ { 6, "Request GPS Location Assistance" },
+ { 7, "Reserved" },
+ { 5, "Request GPS Sensitivity Assistance" },
+ { 3, "Request Base Station Almanac" },
+ { 8, "Request GPS Almanac" },
+ { 9, "Request GPS Ephemeris" },
+ { 10, "Request GPS Navigation Message Bits" },
+ { 1, "Request Location Response" },
+ { 11, "Request GPS Almanac Correction" },
+ { 12, "Request GPS Satellite Health Information" },
+ { 0, NULL },
+};
+#define NUM_REV_REQ_TYPE (sizeof(rev_req_type_strings)/sizeof(value_string))
+static gint ett_rev_req_type[NUM_REV_REQ_TYPE];
+static void (*rev_req_type_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
+ NULL, /* Reserved */
+ NULL, /* Request BS Capabilities */
+ NULL, /* Request GPS Acquisition Assistance */
+ NULL, /* Request GPS Location Assistance */
+ NULL, /* Reserved */
+ NULL, /* Request GPS Sensitivity Assistance */
+ NULL, /* Request Base Station Almanac */
+ NULL, /* Request GPS Almanac */
+ NULL, /* Request GPS Ephemeris */
+ NULL, /* Request GPS Navigation Message Bits */
+ NULL, /* Request Location Response */
+ NULL, /* Request GPS Almanac Correction */
+ NULL, /* Request GPS Satellite Health Information */
+ NULL, /* NONE */
+};
+
+static const value_string rev_rsp_type_strings[] = {
+ { 0, "Reject" },
+ { 2, "Provide MS Information" },
+ { 3, "Provide Autonomous Measurement Weighting Factors" },
+ { 4, "Provide Pseudorange Measurement" },
+ { 5, "Provide Pilot Phase Measurement" },
+ { 1, "Provide Location Response" },
+ { 6, "Provide Time Offset Measurement" },
+ { 7, "Provide Cancellation Acknowledgement" },
+ { 0, NULL },
+};
+#define NUM_REV_RSP_TYPE (sizeof(rev_rsp_type_strings)/sizeof(value_string))
+static gint ett_rev_rsp_type[NUM_REV_RSP_TYPE];
+static void (*rev_rsp_type_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint len, guint32 offset) = {
+ NULL, /* Reject */
+ NULL, /* Provide MS Information */
+ NULL, /* Provide Autonomous Measurement Weighting Factors */
+ NULL, /* Provide Pseudorange Measurement */
+ NULL, /* Provide Pilot Phase Measurement */
+ NULL, /* Provide Location Response */
+ NULL, /* Provide Time Offset Measurement */
+ NULL, /* Provide Cancellation Acknowledgement */
+ NULL, /* NONE */
+};
+
+static void
+for_request(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
+{
+ guint32 offset;
+ guint8 oct;
+ gchar *str = NULL;
+ gint idx;
+ proto_tree *subtree;
+ proto_item *item;
+
+ offset = *offset_p;
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ str = my_match_strval(oct & 0x0f, for_req_type_strings, &idx);
+
+ if (str == NULL)
+ {
+ return;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
+ item =
+ proto_tree_add_uint_format(tree, hf_ansi_801_for_req_type, tvb, offset,
+ 1, oct & 0x0f,
+ "%s : Request Type, %s (%u)",
+ bigbuf,
+ str,
+ oct & 0x0f);
+
+ subtree = proto_item_add_subtree(item, ett_for_req_type[idx]);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text(subtree, tvb, offset, 1,
+ "Length: %u",
+ oct);
+
+ offset++;
+
+ if (for_req_type_fcn[idx] != NULL)
+ {
+ (*for_req_type_fcn[idx])(tvb, subtree, oct, offset);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, tvb, offset, oct,
+ "Data");
+ }
+
+ *offset_p = offset + oct;
+}
+
+static void
+for_response(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
+{
+ guint32 offset;
+ guint8 oct;
+ gchar *str = NULL;
+ gint idx;
+ proto_tree *subtree;
+ proto_item *item;
+
+ offset = *offset_p;
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Unsolicited response indicator",
+ bigbuf);
+
+ str = my_match_strval(oct & 0x0f, for_rsp_type_strings, &idx);
+
+ if (str == NULL)
+ {
+ return;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
+ item =
+ proto_tree_add_uint_format(tree, hf_ansi_801_for_rsp_type, tvb, offset,
+ 1, oct & 0x0f,
+ "%s : Response Type, %s (%u)",
+ bigbuf,
+ str,
+ oct & 0x0f);
+
+ subtree = proto_item_add_subtree(item, ett_for_rsp_type[idx]);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text(subtree, tvb, offset, 1,
+ "Length: %u",
+ oct);
+
+ offset++;
+
+ if (for_rsp_type_fcn[idx] != NULL)
+ {
+ (*for_rsp_type_fcn[idx])(tvb, subtree, oct, offset);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, tvb, offset, oct,
+ "Data");
+ }
+
+ *offset_p = offset + oct;
+}
+
+static void
+rev_request(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
+{
+ guint32 offset;
+ guint8 oct;
+ gchar *str = NULL;
+ gint idx;
+ proto_tree *subtree;
+ proto_item *item;
+
+ offset = *offset_p;
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ str = my_match_strval(oct & 0x0f, rev_req_type_strings, &idx);
+
+ if (str == NULL)
+ {
+ return;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
+ item =
+ proto_tree_add_uint_format(tree, hf_ansi_801_rev_req_type, tvb, offset,
+ 1, oct & 0x0f,
+ "%s : Request Type, %s (%u)",
+ bigbuf,
+ str,
+ oct & 0x0f);
+
+ subtree = proto_item_add_subtree(item, ett_rev_req_type[idx]);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text(subtree, tvb, offset, 1,
+ "Length: %u",
+ oct);
+
+ offset++;
+
+ if (rev_req_type_fcn[idx] != NULL)
+ {
+ (*rev_req_type_fcn[idx])(tvb, subtree, oct, offset);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, tvb, offset, oct,
+ "Data");
+ }
+
+ *offset_p = offset + oct;
+}
+
+static void
+rev_response(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
+{
+ guint32 offset;
+ guint8 oct;
+ gchar *str = NULL;
+ gint idx;
+ proto_tree *subtree;
+ proto_item *item;
+
+ offset = *offset_p;
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Unsolicited response indicator",
+ bigbuf);
+
+ str = my_match_strval(oct & 0x0f, rev_rsp_type_strings, &idx);
+
+ if (str == NULL)
+ {
+ return;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
+ item =
+ proto_tree_add_uint_format(tree, hf_ansi_801_rev_rsp_type, tvb, offset,
+ 1, oct & 0x0f,
+ "%s : Response Type, %s (%u)",
+ bigbuf,
+ str,
+ oct & 0x0f);
+
+ subtree = proto_item_add_subtree(item, ett_rev_rsp_type[idx]);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text(subtree, tvb, offset, 1,
+ "Length: %u",
+ oct);
+
+ offset++;
+
+ if (rev_rsp_type_fcn[idx] != NULL)
+ {
+ (*rev_rsp_type_fcn[idx])(tvb, subtree, oct, offset);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, tvb, offset, oct,
+ "Data");
+ }
+
+ *offset_p = offset + oct;
+}
+
+static void
+dissect_ansi_801_for_message(tvbuff_t *tvb, proto_tree *tree)
+{
+ guint32 offset;
+ guint8 oct, num_req, num_rsp;
+ guint rem_len;
+ gchar *str = NULL;
+
+ offset = 0;
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Session Start",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Session End",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Session Source",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
+ proto_tree_add_uint_format(tree, hf_ansi_801_for_sess_tag, tvb, offset,
+ 1, oct & 0x1f,
+ "%s : Session Tag (%u)",
+ bigbuf,
+ oct & 0x1f);
+
+ proto_tree_add_uint_hidden(tree, hf_ansi_801_sess_tag, tvb, offset,
+ 1, oct & 0x1f);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch (oct)
+ {
+ case 0x00: str = "Position Determination Data Message"; break;
+ case 0xff: str = "Reserved"; break;
+ default:
+ if (oct < 0xc0)
+ {
+ str = "Reserved for future standardization";
+ }
+ else
+ {
+ str =
+ "Available for manufacturer-specific Position Determination "
+ "Data Message definition as specified in TSB-58";
+ }
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0xff, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : PD Message Type, %s (%u)",
+ bigbuf,
+ str,
+ oct);
+
+ offset++;
+
+ if (oct == 0x00)
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ num_req = (oct & 0xf0) >> 4;
+ num_rsp = oct & 0x0f;
+
+ other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number Requests (%u)",
+ bigbuf,
+ num_req);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number Responses (%u)",
+ bigbuf,
+ num_rsp);
+
+ offset++;
+ rem_len = tvb_length_remaining(tvb, offset);
+
+ while ((num_req > 0) &&
+ (rem_len >= 2))
+ {
+ for_request(tvb, tree, &offset);
+
+ rem_len = tvb_length_remaining(tvb, offset);
+ num_req--;
+ }
+
+ if (num_req != 0)
+ {
+ proto_tree_add_text(tree, tvb,
+ offset, -1, "Short Data (?)");
+ return;
+ }
+
+ while ((num_rsp > 0) &&
+ (rem_len >= 2))
+ {
+ for_response(tvb, tree, &offset);
+
+ rem_len = tvb_length_remaining(tvb, offset);
+ num_rsp--;
+ }
+
+ if (num_rsp != 0)
+ {
+ proto_tree_add_text(tree, tvb,
+ offset, -1, "Short Data (?)");
+ return;
+ }
+
+ if (rem_len > 0)
+ {
+ proto_tree_add_text(tree, tvb, offset, rem_len,
+ "Extraneous Data");
+ }
+ }
+ else
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Reserved/Proprietary/Future Data");
+ }
+}
+
+static void
+dissect_ansi_801_rev_message(tvbuff_t *tvb, proto_tree *tree)
+{
+ guint32 offset;
+ guint8 oct, num_req, num_rsp;
+ guint rem_len;
+ gchar *str = NULL;
+
+ offset = 0;
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Session Start",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Session End",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Session Source",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
+ proto_tree_add_uint_format(tree, hf_ansi_801_rev_sess_tag, tvb, offset,
+ 1, oct & 0x1f,
+ "%s : Session Tag (%u)",
+ bigbuf,
+ oct & 0x1f);
+
+ proto_tree_add_uint_hidden(tree, hf_ansi_801_sess_tag, tvb, offset,
+ 1, oct & 0x1f);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch (oct)
+ {
+ case 0x00: str = "Position Determination Data Message"; break;
+ case 0xff: str = "Reserved"; break;
+ default:
+ if (oct < 0xc0)
+ {
+ str = "Reserved for future standardization";
+ }
+ else
+ {
+ str =
+ "Available for manufacturer-specific Position Determination "
+ "Data Message definition as specified in TSB-58";
+ }
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0xff, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : PD Message Type, %s (%u)",
+ bigbuf,
+ str,
+ oct);
+
+ offset++;
+
+ if (oct == 0x00)
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ num_req = (oct & 0xf0) >> 4;
+ num_rsp = oct & 0x0f;
+
+ other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number Requests (%u)",
+ bigbuf,
+ num_req);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s : Number Responses (%u)",
+ bigbuf,
+ num_rsp);
+
+ offset++;
+ rem_len = tvb_length_remaining(tvb, offset);
+
+ while ((num_req > 0) &&
+ (rem_len >= 2))
+ {
+ rev_request(tvb, tree, &offset);
+
+ rem_len = tvb_length_remaining(tvb, offset);
+ num_req--;
+ }
+
+ if (num_req != 0)
+ {
+ proto_tree_add_text(tree, tvb,
+ offset, -1, "Short Data (?)");
+ return;
+ }
+
+ while ((num_rsp > 0) &&
+ (rem_len >= 2))
+ {
+ rev_response(tvb, tree, &offset);
+
+ rem_len = tvb_length_remaining(tvb, offset);
+ num_rsp--;
+ }
+
+ if (num_rsp != 0)
+ {
+ proto_tree_add_text(tree, tvb,
+ offset, -1, "Short Data (?)");
+ return;
+ }
+
+ if (rem_len > 0)
+ {
+ proto_tree_add_text(tree, tvb, offset, rem_len,
+ "Extraneous Data");
+ }
+ }
+ else
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Reserved/Proprietary/Future Data");
+ }
+}
+
+static void
+dissect_ansi_801(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ansi_801_item;
+ proto_tree *ansi_801_tree = NULL;
+
+ g_pinfo = pinfo;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, ansi_proto_name_short);
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree)
+ {
+ g_tree = tree;
+
+ /*
+ * create the ansi_801 protocol tree
+ */
+ ansi_801_item =
+ proto_tree_add_protocol_format(tree, proto_ansi_801, tvb, 0, -1,
+ "%s %s Link",
+ ansi_proto_name,
+ (pinfo->match_port == ANSI_801_FORWARD) ? "Forward" : "Reverse");
+
+ ansi_801_tree =
+ proto_item_add_subtree(ansi_801_item, ett_ansi_801);
+
+ if (pinfo->match_port == ANSI_801_FORWARD)
+ {
+ dissect_ansi_801_for_message(tvb, ansi_801_tree);
+ }
+ else
+ {
+ dissect_ansi_801_rev_message(tvb, ansi_801_tree);
+ }
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_ansi_801(void)
+{
+ guint i;
+ gint last_offset;
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] =
+ {
+ { &hf_ansi_801_for_req_type,
+ { "Forward Request Type", "ansi_801.for_req_type",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_801_for_rsp_type,
+ { "Forward Response Type", "ansi_801.for_rsp_type",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_801_rev_req_type,
+ { "Reverse Request Type", "ansi_801.rev_req_type",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_801_rev_rsp_type,
+ { "Reverse Response Type", "ansi_801.rev_rsp_type",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_801_for_sess_tag,
+ { "Forward Session Tag", "ansi_801.for_sess_tag",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_801_rev_sess_tag,
+ { "Reverse Session Tag", "ansi_801.rev_sess_tag",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_801_sess_tag,
+ { "Session Tag", "ansi_801.sess_tag",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+#define NUM_INDIVIDUAL_PARAMS 1
+ gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_FOR_REQ_TYPE+NUM_FOR_RSP_TYPE+NUM_REV_REQ_TYPE+NUM_REV_RSP_TYPE];
+
+ ett[0] = &ett_ansi_801;
+
+ last_offset = NUM_INDIVIDUAL_PARAMS;
+
+ for (i=0; i < NUM_FOR_REQ_TYPE; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_for_req_type[i];
+ }
+
+ for (i=0; i < NUM_FOR_RSP_TYPE; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_for_rsp_type[i];
+ }
+
+ for (i=0; i < NUM_REV_REQ_TYPE; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_rev_req_type[i];
+ }
+
+ for (i=0; i < NUM_REV_RSP_TYPE; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_rev_rsp_type[i];
+ }
+
+ /* Register the protocol name and description */
+ proto_ansi_801 =
+ proto_register_protocol(ansi_proto_name, "ANSI IS-801 (Location Services (PLD))", "ansi_801");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ansi_801, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_ansi_801(void)
+{
+ dissector_handle_t ansi_801_handle;
+
+ ansi_801_handle = create_dissector_handle(dissect_ansi_801, proto_ansi_801);
+
+ dissector_add("ansi_map.pld", ANSI_801_FORWARD, ansi_801_handle);
+ dissector_add("ansi_map.pld", ANSI_801_REVERSE, ansi_801_handle);
+ dissector_add("ansi_a.pld", ANSI_801_FORWARD, ansi_801_handle);
+ dissector_add("ansi_a.pld", ANSI_801_REVERSE, ansi_801_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ansi_a.c b/epan/dissectors/packet-ansi_a.c
new file mode 100644
index 0000000000..bc4884c05b
--- /dev/null
+++ b/epan/dissectors/packet-ansi_a.c
@@ -0,0 +1,8465 @@
+/* packet-ansi_a.c
+ * Routines for ANSI A Interface (IS-634/IOS) dissection
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * Title 3GPP2 Other
+ *
+ * Inter-operability Specification (IOS) for CDMA
+ * 2000 Access Network Interfaces
+ * 3GPP2 A.S0001-1 TIA/EIA-2001
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "epan/packet.h"
+#include "prefs.h"
+#include "tap.h"
+
+#include "packet-bssap.h"
+#include "packet-ansi_a.h"
+
+
+/* PROTOTYPES/FORWARDS */
+
+void proto_reg_handoff_ansi_a(void);
+
+#define ANSI_A_MAX(x,y) (((x) < (y)) ? (y) : (x))
+
+#define ANSI_A_MIN(x,y) (((x) < (y)) ? (x) : (y))
+
+const value_string ansi_a_ios401_bsmap_strings[] = {
+ { 0x69, "Additional Service Notification" },
+ { 0x65, "ADDS Page" },
+ { 0x66, "ADDS Page Ack" },
+ { 0x67, "ADDS Transfer" },
+ { 0x68, "ADDS Transfer Ack" },
+ { 0x02, "Assignment Complete" },
+ { 0x03, "Assignment Failure" },
+ { 0x01, "Assignment Request" },
+ { 0x45, "Authentication Request" },
+ { 0x46, "Authentication Response" },
+ { 0x48, "Base Station Challenge" },
+ { 0x49, "Base Station Challenge Response" },
+ { 0x40, "Block" },
+ { 0x41, "Block Acknowledge" },
+ { 0x09, "BS Service Request" },
+ { 0x0A, "BS Service Response" },
+ { 0x20, "Clear Command" },
+ { 0x21, "Clear Complete" },
+ { 0x22, "Clear Request" },
+ { 0x57, "Complete Layer 3 Information" },
+ { 0x60, "Feature Notification" },
+ { 0x61, "Feature Notification Ack" },
+ { 0x13, "Handoff Command" },
+ { 0x15, "Handoff Commenced" },
+ { 0x14, "Handoff Complete" },
+ { 0x16, "Handoff Failure" },
+ { 0x17, "Handoff Performed" },
+ { 0x10, "Handoff Request" },
+ { 0x12, "Handoff Request Acknowledge" },
+ { 0x11, "Handoff Required" },
+ { 0x1A, "Handoff Required Reject" },
+ { 0x6C, "PACA Command" },
+ { 0x6D, "PACA Command Ack" },
+ { 0x6E, "PACA Update" },
+ { 0x6F, "PACA Update Ack" },
+ { 0x52, "Paging Request" },
+ { 0x53, "Privacy Mode Command" },
+ { 0x55, "Privacy Mode Complete" },
+ { 0x23, "Radio Measurements for Position Request" },
+ { 0x25, "Radio Measurements for Position Response" },
+ { 0x56, "Rejection" },
+ { 0x05, "Registration Request" },
+ { 0x30, "Reset" },
+ { 0x31, "Reset Acknowledge" },
+ { 0x34, "Reset Circuit" },
+ { 0x35, "Reset Circuit Acknowledge" },
+ { 0x47, "SSD Update Request" },
+ { 0x4A, "SSD Update Response" },
+ { 0x6A, "Status Request" },
+ { 0x6B, "Status Response" },
+ { 0x39, "Transcoder Control Acknowledge" },
+ { 0x38, "Transcoder Control Request" },
+ { 0x42, "Unblock" },
+ { 0x43, "Unblock Acknowledge" },
+ { 0x0B, "User Zone Reject" },
+ { 0x04, "User Zone Update" },
+ { 0, NULL },
+};
+
+const value_string ansi_a_ios401_dtap_strings[] = {
+ { 0x62, "Additional Service Request" },
+ { 0x53, "ADDS Deliver" },
+ { 0x54, "ADDS Deliver Ack" },
+ { 0x26, "Alert With Information" },
+ { 0x45, "Authentication Request" },
+ { 0x46, "Authentication Response" },
+ { 0x48, "Base Station Challenge" },
+ { 0x49, "Base Station Challenge Response" },
+ { 0x24, "CM Service Request" },
+ { 0x25, "CM Service Request Continuation" },
+ { 0x07, "Connect" },
+ { 0x10, "Flash with Information" },
+ { 0x50, "Flash with Information Ack" },
+ { 0x02, "Location Updating Accept" },
+ { 0x04, "Location Updating Reject" },
+ { 0x08, "Location Updating Request" },
+ { 0x27, "Paging Response" },
+ { 0x2B, "Parameter Update Confirm" },
+ { 0x2C, "Parameter Update Request" },
+ { 0x56, "Rejection" },
+ { 0x03, "Progress" },
+ { 0x70, "Service Redirection" },
+ { 0x2E, "Service Release" },
+ { 0x2F, "Service Release Complete" },
+ { 0x47, "SSD Update Request" },
+ { 0x4A, "SSD Update Response" },
+ { 0x6A, "Status Request" },
+ { 0x6B, "Status Response" },
+ { 0x0B, "User Zone Reject" },
+ { 0x0C, "User Zone Update" },
+ { 0x0D, "User Zone Update Request" },
+ { 0, NULL },
+};
+
+const value_string ansi_a_ios401_elem_1_strings[] = {
+ { 0x20, "Access Network Identifiers" },
+ { 0x3D, "ADDS User Part" },
+ { 0x25, "AMPS Hard Handoff Parameters" },
+ { 0x30, "Anchor PDSN Address" },
+ { 0x7C, "Anchor P-P Address" },
+ { 0x41, "Authentication Challenge Parameter" },
+ { 0x28, "Authentication Confirmation Parameter (RANDC)" },
+ { 0x59, "Authentication Data" },
+ { 0x4A, "Authentication Event" },
+ { 0x40, "Authentication Parameter COUNT" },
+ { 0x42, "Authentication Response Parameter" },
+ { 0x37, "Band Class" },
+ { 0x5B, "Called Party ASCII Number" },
+ { 0x5E, "Called Party BCD Number" },
+ { 0x4B, "Calling Party ASCII Number" },
+ { 0x04, "Cause" },
+ { 0x08, "Cause Layer 3" },
+ { 0x0C, "CDMA Serving One Way Delay" },
+ { 0x05, "Cell Identifier" },
+ { 0x1A, "Cell Identifier List" },
+ { 0x23, "Channel Number" },
+ { 0x0B, "Channel Type" },
+ { 0x19, "Circuit Group" },
+ { 0x01, "Circuit Identity Code" },
+ { 0x24, "Circuit Identity Code Extension" },
+ { 0x12, "Classmark Information Type 2" },
+ { 0x29, "Downlink Radio Environment" },
+ { 0x2B, "Downlink Radio Environment List" },
+ { 0x0A, "Encryption Information" },
+ { 0x10, "Extended Handoff Direction Parameters" },
+ { 0x2C, "Geographic Location" },
+ { 0x5A, "Special Service Call Indicator" },
+ { 0x26, "Handoff Power Level" },
+ { 0x16, "Hard Handoff Parameters" },
+ { 0x2E, "Information Element Requested" },
+ { 0x09, "IS-2000 Channel Identity" },
+ { 0x27, "IS-2000 Channel Identity 3X" },
+ { 0x11, "IS-2000 Mobile Capabilities" },
+ { 0x0F, "IS-2000 Non-Negotiable Service Configuration Record" },
+ { 0x0E, "IS-2000 Service Configuration Record" },
+ { 0x62, "IS-95/IS-2000 Cause Value" },
+ { 0x67, "IS-2000 Redirection Record" },
+ { 0x22, "IS-95 Channel Identity" },
+ { 0x64, "IS-95 MS Measured Channel Identity" },
+ { 0x17, "Layer 3 Information" },
+ { 0x13, "Location Area Information" },
+ { 0x38, "Message Waiting Indication" },
+ { 0x0D, "Mobile Identity" },
+ { 0x15, "MS Information Records" },
+ { 0xA0, "Origination Continuation Indicator" },
+ { 0x5F, "PACA Order" },
+ { 0x60, "PACA Reorigination Indicator" },
+ { 0x4E, "PACA Timestamp" },
+ { 0x70, "Packet Session Parameters" },
+ { 0x14, "PDSN IP Address" },
+ { 0xA2, "Power Down Indicator" },
+ { 0x06, "Priority" },
+ { 0x3B, "Protocol Revision" },
+ { 0x18, "Protocol Type" },
+ { 0x2D, "PSMM Count" },
+ { 0x07, "Quality of Service Parameters" },
+ { 0x1D, "Radio Environment and Resources" },
+ { 0x1F, "Registration Type" },
+ { 0x44, "Reject Cause" },
+ { 0x1B, "Response Request" },
+ { 0x68, "Return Cause" },
+ { 0x21, "RF Channel Identity" },
+ { 0x03, "Service Option" },
+ { 0x1E, "Service Option Connection Identifier (SOCI)" },
+ { 0x2A, "Service Option List" },
+ { 0x69, "Service Redirection Info" },
+ { 0x71, "Session Reference Identifier (SR_ID)" },
+ { 0x32, "SID" },
+ { 0x34, "Signal" },
+ { 0x35, "Slot Cycle Index" },
+ { 0x31, "Software Version" },
+ { 0x39, "Source RNC to Target RNC Transparent Container" },
+ { 0x14, "Source PDSN Address" },
+ { 0x33, "Tag" },
+ { 0x3A, "Target RNC to Source RNC Transparent Container" },
+ { 0x36, "Transcoder Mode" }, /* XXX 0x1C in IOS 4.0.1 */
+ { 0x02, "User Zone ID" },
+ { 0xA1, "Voice Privacy Request" },
+ { 0, NULL },
+};
+
+#define ANSI_MS_INFO_REC_DISPLAY 0x01
+#define ANSI_MS_INFO_REC_CLD_PN 0x02
+#define ANSI_MS_INFO_REC_CLG_PN 0x03
+#define ANSI_MS_INFO_REC_CONN_N 0x04
+#define ANSI_MS_INFO_REC_SIGNAL 0x05
+#define ANSI_MS_INFO_REC_MW 0x06
+#define ANSI_MS_INFO_REC_SC 0x07
+#define ANSI_MS_INFO_REC_CLD_PSA 0x08
+#define ANSI_MS_INFO_REC_CLG_PSA 0x09
+#define ANSI_MS_INFO_REC_CONN_SA 0x0a
+#define ANSI_MS_INFO_REC_RED_N 0x0b
+#define ANSI_MS_INFO_REC_RED_SA 0x0c
+#define ANSI_MS_INFO_REC_MP 0x0d
+#define ANSI_MS_INFO_REC_PA 0x0e
+#define ANSI_MS_INFO_REC_LC 0x0f
+#define ANSI_MS_INFO_REC_EDISPLAY 0x10
+#define ANSI_MS_INFO_REC_NNSC 0x13
+#define ANSI_MS_INFO_REC_MC_EDISPLAY 0x14
+#define ANSI_MS_INFO_REC_CWI 0x15
+#define ANSI_MS_INFO_REC_ERTI 0xfe
+
+static const value_string ansi_ms_info_rec_str[] = {
+ { ANSI_MS_INFO_REC_DISPLAY, "Display" },
+ { ANSI_MS_INFO_REC_CLD_PN, "Called Party Number" },
+ { ANSI_MS_INFO_REC_CLG_PN, "Calling Party Number" },
+ { ANSI_MS_INFO_REC_CONN_N, "Connected Number" },
+ { ANSI_MS_INFO_REC_SIGNAL, "Signal" },
+ { ANSI_MS_INFO_REC_MW, "Message Waiting" },
+ { ANSI_MS_INFO_REC_SC, "Service Configuration" },
+ { ANSI_MS_INFO_REC_CLD_PSA, "Called Party Subaddress" },
+ { ANSI_MS_INFO_REC_CLG_PSA, "Calling Party Subaddress" },
+ { ANSI_MS_INFO_REC_CONN_SA, "Connected Subaddress" },
+ { ANSI_MS_INFO_REC_RED_N, "Redirecting Number" },
+ { ANSI_MS_INFO_REC_RED_SA, "Redirecting Subaddress" },
+ { ANSI_MS_INFO_REC_MP, "Meter Pulses" },
+ { ANSI_MS_INFO_REC_PA, "Parametric Alerting" },
+ { ANSI_MS_INFO_REC_LC, "Line Control" },
+ { ANSI_MS_INFO_REC_EDISPLAY, "Extended Display" },
+ { ANSI_MS_INFO_REC_NNSC, "Non-Negotiable Service Configuration" },
+ { ANSI_MS_INFO_REC_MC_EDISPLAY, "Multiple Character Extended Display" },
+ { ANSI_MS_INFO_REC_CWI, "Call Waiting Indicator" },
+ { ANSI_MS_INFO_REC_ERTI, "Extended Record Type International" },
+ { 0, NULL },
+};
+#define NUM_MS_INFO_REC (sizeof(ansi_ms_info_rec_str)/sizeof(value_string))
+static gint ett_ansi_ms_info_rec[NUM_MS_INFO_REC];
+
+static gchar *band_class_str[] = {
+ "800 MHz Cellular System",
+ "1.850 to 1.990 GHz Broadband PCS",
+ "872 to 960 MHz TACS Band",
+ "832 to 925 MHz JTACS Band",
+ "1.750 to 1.870 GHz Korean PCS",
+ "450 MHz NMT",
+ "2 GHz IMT-2000 Band",
+ "North American 700 MHz Cellular Band",
+ "1.710 to 1.880 GHz PCS",
+ "880 to 960 MHz Band",
+ "Secondary 800 MHz Band",
+ "400 MHz European PAMR Band",
+ "800 MHz European PAMR Band"
+};
+#define NUM_BAND_CLASS_STR (sizeof(band_class_str)/sizeof(gchar *))
+
+static gchar *cell_disc_str[] = {
+ "whole Cell Global Identification (CGI)",
+ "LAC/CI",
+ "Cell Identity (CI)",
+ "None",
+ "Location Area Identification (LAI)",
+ "Location Area Code (LAC)",
+ "ALL",
+ "IS-41 whole Cell Global Identification (ICGI)",
+ "Enhanced whole Cell Global Identification (ECGI)"
+};
+#define NUM_CELL_DISC_STR (sizeof(cell_disc_str)/sizeof(gchar *))
+
+/* Initialize the protocol and registered fields */
+static int proto_a_bsmap = -1;
+static int proto_a_dtap = -1;
+
+static int ansi_a_tap = -1;
+
+static int hf_ansi_a_none = -1;
+static int hf_ansi_a_bsmap_msgtype = -1;
+static int hf_ansi_a_dtap_msgtype = -1;
+static int hf_ansi_a_length = -1;
+static int hf_ansi_a_elem_id = -1;
+static int hf_ansi_a_esn = -1;
+static int hf_ansi_a_imsi = -1;
+static int hf_ansi_a_min = -1;
+static int hf_ansi_a_cld_party_bcd_num = -1;
+static int hf_ansi_a_clg_party_bcd_num = -1;
+static int hf_ansi_a_cld_party_ascii_num = -1;
+static int hf_ansi_a_clg_party_ascii_num = -1;
+static int hf_ansi_a_cell_ci = -1;
+static int hf_ansi_a_cell_lac = -1;
+static int hf_ansi_a_cell_mscid = -1;
+static int hf_ansi_a_pdsn_ip_addr = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_bsmap = -1;
+static gint ett_dtap = -1;
+static gint ett_elems = -1;
+static gint ett_elem = -1;
+static gint ett_dtap_oct_1 = -1;
+static gint ett_cm_srvc_type = -1;
+static gint ett_ansi_ms_info_rec_reserved = -1;
+static gint ett_ansi_enc_info = -1;
+static gint ett_cell_list = -1;
+
+#define A_VARIANT_IS634 4
+#define A_VARIANT_TSB80 5
+#define A_VARIANT_IS634A 6
+#define A_VARIANT_IOS2 7
+#define A_VARIANT_IOS3 8
+#define A_VARIANT_IOS401 9
+
+/*
+ * IOS 4, probably most common
+ */
+static gint a_global_variant = A_VARIANT_IOS401;
+
+/*
+ * Variables to allow for proper deletion of dissector registration when
+ * the user changes values
+ */
+static gint a_variant = 0;
+
+static char a_bigbuf[1024];
+static gchar a_add_string[1024];
+static dissector_handle_t data_handle;
+static dissector_handle_t bsmap_handle;
+static dissector_handle_t dtap_handle;
+static dissector_table_t is637_dissector_table; /* IS-637-A Transport Layer (SMS) */
+static dissector_table_t is683_dissector_table; /* IS-683-A (OTA) */
+static dissector_table_t is801_dissector_table; /* IS-801 (PLD) */
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
+
+
+typedef struct dgt_set_t
+{
+ unsigned char out[15];
+}
+dgt_set_t;
+
+static dgt_set_t Dgt_tbcd = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#'
+ }
+};
+
+static dgt_set_t Dgt_msid = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
+ }
+};
+
+/* FUNCTIONS */
+
+/*
+ * Unpack BCD input pattern into output ASCII pattern
+ *
+ * Input Pattern is supplied using the same format as the digits
+ *
+ * Returns: length of unpacked pattern
+ */
+static int
+my_dgt_tbcd_unpack(
+ char *out, /* ASCII pattern out */
+ guchar *in, /* packed pattern in */
+ int num_octs, /* Number of octets to unpack */
+ dgt_set_t *dgt /* Digit definitions */
+ )
+{
+ int cnt = 0;
+ unsigned char i;
+
+ while (num_octs)
+ {
+ /*
+ * unpack first value in byte
+ */
+ i = *in++;
+ *out++ = dgt->out[i & 0x0f];
+ cnt++;
+
+ /*
+ * unpack second value in byte
+ */
+ i >>= 4;
+
+ if (i == 0x0f) /* odd number bytes - hit filler */
+ break;
+
+ *out++ = dgt->out[i];
+ cnt++;
+ num_octs--;
+ }
+
+ *out = '\0';
+
+ return(cnt);
+}
+
+static gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr)
+ {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+/* ELEMENT FUNCTIONS */
+
+#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
+ if ((edc_len) > (edc_max_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ curr_offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
+ curr_offset += ((edc_len) - (edc_max_len)); \
+ }
+
+#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
+ if ((sdc_len) < (sdc_min_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ curr_offset, (sdc_len), "Short Data (?)"); \
+ curr_offset += (sdc_len); \
+ return(curr_offset - offset); \
+ }
+
+#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
+ if ((edc_len) != (edc_eq_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ asn1->offset, (edc_len), "Unexpected Data Length"); \
+ asn1->offset += (edc_len); \
+ return; \
+ }
+
+#define NO_MORE_DATA_CHECK(nmdc_len) \
+ if ((nmdc_len) == (curr_offset - offset)) return(nmdc_len);
+
+
+/*
+ * IOS 6.2.2.6
+ */
+static guint8
+elem_chan_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 value;
+ guint32 curr_offset;
+
+ len = len;
+ curr_offset = offset;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "Channel Number: %u",
+ value);
+
+ curr_offset += 2;
+
+ sprintf(add_string, " - (%u)", value);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.7
+ */
+static guint8
+elem_chan_type(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str = NULL;
+ gboolean data;
+
+ curr_offset = offset;
+ data = FALSE;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0: str = "No Alert"; break;
+ case 1: str = "Speech"; break;
+ case 2: str = "Data"; data = TRUE; break;
+ case 3: str = "Signaling"; break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Speech or Data Indicator: %s",
+ str);
+
+ sprintf(add_string, " - (%s)", str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0: str = "Reserved (invalid)"; break;
+ case 1: str = "DCCH"; break;
+ case 2: str = "Reserved for future use (invalid)"; break;
+ case 8: str = "Full rate TCH channel Bm"; break;
+ case 9: str = "Half rate TCH channel Lm"; break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Channel Rate and Type: %s",
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (data)
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : %sTransparent service",
+ a_bigbuf,
+ (oct & 0x40) ? "Non-" : "");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+ }
+ else
+ {
+ switch (oct)
+ {
+ case 0: str = "No Resources Required (invalid)"; break;
+ case 1: str = "Reserved"; break;
+ case 2: str = "Reserved"; break;
+ case 3: str = "TIA/EIA-IS-2000 8 kb/s vocoder"; break;
+ case 4: str = "8 kb/s enhanced vocoder (EVRC)"; break;
+ case 5: str = "13 kb/s vocoder"; break;
+ case 6: str = "ADPCM"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Speech Encoding Algorithm/data rate + Transparency Indicator: %s",
+ str);
+ }
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.8
+ */
+static guint8
+elem_rf_chan_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ guint32 curr_offset;
+
+ len = len;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Color Code");
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : N-AMPS",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ANSI/EIA/TIA-553",
+ a_bigbuf);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Timeslot Number",
+ a_bigbuf);
+
+ curr_offset++;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, value >> 8, 0xf8, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, value >> 8, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ARFCN (MSB): %u",
+ a_bigbuf,
+ value & 0x07ff);
+
+ other_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset + 1, 1,
+ "%s : ARFCN (LSB)",
+ a_bigbuf);
+
+ sprintf(add_string, " - (ARFCN: %u)", value & 0x07ff);
+
+ curr_offset += 2;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.9
+ */
+static guint8
+elem_sid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 value;
+ guint32 curr_offset;
+
+ len = len;
+ curr_offset = offset;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, value >> 8, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, value >> 8, 0x7f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : SID (MSB), %u",
+ a_bigbuf,
+ value & 0x7fff);
+
+ other_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset + 1, 1,
+ "%s : SID (LSB)",
+ a_bigbuf);
+
+ sprintf(add_string, " - (SID: %u)", value & 0x7fff);
+
+ curr_offset += 2;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.10
+ */
+static guint8
+elem_is95_chan_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Hard Handoff",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Number of Channels to Add: %u",
+ a_bigbuf,
+ (oct & 0x70) >> 4);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Frame Offset: (%u), %.2f ms",
+ a_bigbuf,
+ oct & 0x0f,
+ (oct & 0x0f) * 1.25);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ SHORT_DATA_CHECK(len - (curr_offset - offset), 4);
+
+ do
+ {
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Walsh Code Channel Index: %u",
+ oct);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Pilot PN Code (LSB)",
+ a_bigbuf);
+
+ curr_offset++;
+
+ value = oct;
+ oct = tvb_get_guint8(tvb, curr_offset);
+ value |= ((guint32) (oct & 0x80)) << 1;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Pilot PN Code (MSB): %u",
+ a_bigbuf,
+ value);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Power Combined",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Frequency Included",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ value = tvb_get_guint8(tvb, curr_offset + 1) | ((oct & 0x07) << 8);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ARFCN (MSB): %u",
+ a_bigbuf,
+ value);
+
+ curr_offset++;
+
+ other_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ARFCN (LSB)",
+ a_bigbuf);
+
+ if (add_string[0] == '\0')
+ {
+ sprintf(add_string, " - (ARFCN: %u)", value);
+ }
+
+ curr_offset++;
+ }
+ while ((len - (curr_offset - offset)) >= 4);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.11
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.12
+ */
+static guint8
+elem_enc_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 oct_len;
+ guint32 curr_offset;
+ gchar *str;
+ guint8 num_recs;
+ proto_tree *subtree;
+ proto_item *item;
+
+ curr_offset = offset;
+
+ num_recs = 0;
+
+ while ((len - (curr_offset - offset)) >= 2)
+ {
+ num_recs++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch ((oct & 0x7c) >> 2)
+ {
+ case 0: str = "Not Used - Invalid value"; break;
+ case 1: str = "SME Key: Signaling Message Encryption Key"; break;
+ case 2: str = "Reserved (VPM: Voice Privacy Mask)"; break;
+ case 3: str = "Reserved"; break;
+ case 4: str = "Private Longcode"; break;
+ case 5: str = "Data Key (ORYX)"; break;
+ case 6: str = "Initial RAND"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Encryption Info - %u: (%u) %s",
+ num_recs,
+ (oct & 0x7c) >> 2,
+ str);
+
+ subtree = proto_item_add_subtree(item, ett_ansi_enc_info);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7c, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : Encryption Parameter Identifier: (%u) %s",
+ a_bigbuf,
+ (oct & 0x7c) >> 2,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : Status: %s",
+ a_bigbuf,
+ (oct & 0x02) ? "active" : "inactive");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : Available: algorithm is %savailable",
+ a_bigbuf,
+ (oct & 0x01) ? "" : "not ");
+
+ curr_offset++;
+
+ oct_len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_uint(subtree, hf_ansi_a_length, tvb,
+ curr_offset, 1, oct_len);
+
+ curr_offset++;
+
+ if (oct_len > 0)
+ {
+ SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+ proto_tree_add_text(subtree, tvb, curr_offset, oct_len,
+ "Encryption Parameter value");
+
+ curr_offset += oct_len;
+ }
+ }
+
+ sprintf(add_string, " - %u record%s",
+ num_recs, plurality(num_recs, "", "s"));
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.13
+ * NO ASSOCIATED DATA
+ */
+
+/*
+ * IOS 6.2.2.14
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.15
+ */
+static guint8
+elem_cm_info_type_2(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 num_bands;
+ guint32 curr_offset;
+ gint temp_int;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Mobile P_REV: %u",
+ a_bigbuf,
+ (oct & 0xe0) >> 5);
+
+ sprintf(add_string, " - P_REV (%u)", (oct & 0xe0) >> 5);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : See List of Entries",
+ a_bigbuf);
+
+ switch (oct & 0x07)
+ {
+ case 0: str = "Class 1, vehicle and portable"; break;
+ case 1: str = "Class 2, portable"; break;
+ case 2: str = "Class 3, handheld"; break;
+ case 3: str = "Class 4, handheld"; break;
+ case 4: str = "Class 5, handheld"; break;
+ case 5: str = "Class 6, handheld"; break;
+ case 6: str = "Class 7, handheld"; break;
+ default:
+ str = "Class 8, handheld";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : RF Power Capability: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Reserved");
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : NAR_AN_CAP: N-AMPS %ssupported",
+ a_bigbuf,
+ (oct & 0x80) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : IS-95: %ssupported",
+ a_bigbuf,
+ (oct & 0x40) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Slotted: mobile is %sin slotted mode",
+ a_bigbuf,
+ (oct & 0x20) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : DTX: mobile is %scapable of DTX",
+ a_bigbuf,
+ (oct & 0x04) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Mobile Term: mobile is %scapable of receiving incoming calls",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Reserved");
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Mobile Term: mobile is %scapable of receiving incoming calls",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : PACA Supported Indicator (PSI): mobile station %s PACA",
+ a_bigbuf,
+ (oct & 0x01) ? "supports" : "does not support");
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "SCM Length: %u",
+ oct);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Station Class Mark: %u",
+ oct);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Count of Band Class Entries: %u",
+ oct);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Band Class Entry Length: %u",
+ oct);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ SHORT_DATA_CHECK(len - (curr_offset - offset), 3);
+
+ num_bands = 0;
+ do
+ {
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ temp_int = oct & 0x1f;
+ if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = band_class_str[temp_int];
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Band Class: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Band Class %u Air Interfaces Supported: %u",
+ a_bigbuf,
+ num_bands,
+ oct & 0x1f);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Band Class %u MS Protocol Level: %u",
+ num_bands,
+ oct);
+
+ curr_offset++;
+
+ num_bands++;
+ }
+ while ((len - (curr_offset - offset)) >= 3);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.16
+ */
+static guint8
+elem_mid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 *poctets;
+ guint32 value;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct & 0x07)
+ {
+ case 2:
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: Broadcast",
+ a_bigbuf);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch ((oct & 0xc0) >> 6)
+ {
+ case 0: str = "Normal"; break;
+ case 1: str = "Interactive"; break;
+ case 2: str = "Urgent"; break;
+ default:
+ str = "Emergency";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Priority: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Message ID: %u",
+ a_bigbuf,
+ oct & 0x3f);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Zone ID: %u",
+ oct);
+
+ sprintf(add_string, " - Broadcast (Zone ID: %u)", oct);
+
+ curr_offset++;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ switch (value)
+ {
+ case 0x0000: str = "Unknown or unspecified"; break;
+ case 0x0001: str = "Emergency Broadcasts"; break;
+ case 0x0002: str = "Administrative"; break;
+ case 0x0003: str = "Maintenance"; break;
+ case 0x0004: str = "General News - Local"; break;
+ case 0x0005: str = "General News - Regional"; break;
+ case 0x0006: str = "General News - National"; break;
+ case 0x0007: str = "General News - International"; break;
+ case 0x0008: str = "Business/Financial News - Local"; break;
+ case 0x0009: str = "Business/Financial News - Regional"; break;
+ case 0x000A: str = "Business/Financial News - National"; break;
+ case 0x000B: str = "Business/Financial News - International"; break;
+ case 0x000C: str = "Sports News - Local"; break;
+ case 0x000D: str = "Sports News - Regional"; break;
+ case 0x000E: str = "Sports News - National"; break;
+ case 0x000F: str = "Sports News - International"; break;
+ case 0x0010: str = "Entertainment News - Local"; break;
+ case 0x0011: str = "Entertainment News - Regional"; break;
+ case 0x0012: str = "Entertainment News - National"; break;
+ case 0x0013: str = "Entertainment News - International"; break;
+ case 0x0014: str = "Local Weather"; break;
+ case 0x0015: str = "Area Traffic Reports"; break;
+ case 0x0016: str = "Local Airport Flight Schedules"; break;
+ case 0x0017: str = "Restaurants"; break;
+ case 0x0018: str = "Lodgings"; break;
+ case 0x0019: str = "Retail Directory"; break;
+ case 0x001A: str = "Advertisements"; break;
+ case 0x001B: str = "Stock Quotes"; break;
+ case 0x001C: str = "Employment Opportunities"; break;
+ case 0x001D: str = "Medical/Health/Hospitals"; break;
+ case 0x001E: str = "Technology News"; break;
+ case 0x001F: str = "Multi-category"; break;
+ default:
+ if ((value >= 0x0020) && (value <= 0x8000)) { str = "Reserved for standard service categories"; }
+ else { str = "Reserved for proprietary service categories"; }
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "Service: (%u) %s",
+ value,
+ str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0: str = "Unknown or unspecified"; break;
+ case 1: str = "English"; break;
+ case 2: str = "French"; break;
+ case 3: str = "Spanish"; break;
+ case 4: str = "Japanese"; break;
+ case 5: str = "Korean"; break;
+ case 6: str = "Chinese"; break;
+ case 7: str = "Hebrew"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Language: (%u) %s",
+ oct,
+ str);
+
+ curr_offset++;
+ break;
+
+ case 0:
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Unused",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even Indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "ODD" : "EVEN");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: No Identity Code",
+ a_bigbuf);
+
+ strcpy(add_string, " - No Identity Code");
+
+ curr_offset++;
+
+ if (len > 1)
+ {
+ proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+ "Format not supported");
+ }
+
+ curr_offset += len - 1;
+ break;
+
+ case 1:
+ /*
+ * IS-634 value
+ */
+ /* FALLTHRU */
+
+ case 6:
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Identity Digit 1: %c",
+ a_bigbuf,
+ Dgt_msid.out[(oct & 0xf0) >> 4]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even Indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "ODD" : "EVEN");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: %s",
+ a_bigbuf,
+ ((oct & 0x07) == 1) ? "MIN" : "IMSI");
+
+ a_bigbuf[0] = Dgt_msid.out[(oct & 0xf0) >> 4];
+ curr_offset++;
+
+ poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+ my_dgt_tbcd_unpack(&a_bigbuf[1], poctets, len - (curr_offset - offset),
+ &Dgt_msid);
+ g_free(poctets);
+
+ proto_tree_add_string_format(tree,
+ ((oct & 0x07) == 1) ? hf_ansi_a_min : hf_ansi_a_imsi,
+ tvb, curr_offset, len - (curr_offset - offset),
+ a_bigbuf,
+ "BCD Digits: %s",
+ a_bigbuf);
+
+ sprintf(add_string, " - %s (%s)",
+ ((oct & 0x07) == 1) ? "MIN" : "IMSI",
+ a_bigbuf);
+
+ curr_offset += len - (curr_offset - offset);
+ break;
+
+ case 3:
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Unused",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even Indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "ODD" : "EVEN");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: Interface Directory Number",
+ a_bigbuf);
+
+ strcpy(add_string, " - Interface Directory Number");
+
+ curr_offset++;
+
+ if (len > 1)
+ {
+ proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+ "Format not supported");
+ }
+
+ curr_offset += len - 1;
+ break;
+
+ case 4:
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Unused",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even Indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "ODD" : "EVEN");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: TMSI",
+ a_bigbuf);
+
+ strcpy(add_string, " - TMSI");
+
+ curr_offset++;
+
+ if (len > 1)
+ {
+ proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+ "Format not supported");
+ }
+
+ curr_offset += len - 1;
+ break;
+
+ case 5:
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Unused",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even Indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "ODD" : "EVEN");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: ESN",
+ a_bigbuf);
+
+ curr_offset++;
+
+ value = tvb_get_ntohl(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_ansi_a_esn,
+ tvb, curr_offset, 4,
+ value);
+
+ sprintf(add_string, " - ESN (0x%04x)", value);
+
+ curr_offset += 4;
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ "Format Unknown");
+
+ strcpy(add_string, " - Format Unknown");
+
+ curr_offset += len;
+ break;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.17
+ */
+static guint8
+elem_sci(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Slot Cycle Index: %u",
+ a_bigbuf,
+ oct & 0x07);
+
+ sprintf(add_string, " - (%u)", oct & 0x07);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.18
+ */
+static guint8
+elem_prio(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3c, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Call Priority Level: %u",
+ a_bigbuf,
+ (oct & 0x3c) >> 2);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Queuing %sallowed",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Preemption %sallowed",
+ a_bigbuf,
+ (oct & 0x01) ? "" : "not ");
+
+ sprintf(add_string, " - (%u)", (oct & 0x3c) >> 2);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.19
+ */
+static guint8
+elem_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ guint32 curr_offset;
+ gchar *str = NULL;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ if (oct & 0x80)
+ {
+ /* 2 octet cause */
+
+ if ((oct & 0x0f) == 0x00)
+ {
+ /* national cause */
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "Normal Event"; break;
+ case 1: str = "Normal Event"; break;
+ case 2: str = "Resource Unavailable"; break;
+ case 3: str = "Service or option not available"; break;
+ case 4: str = "Service or option not implemented"; break;
+ case 5: str = "Invalid message (e.g., parameter out of range)"; break;
+ case 6: str = "Protocol error"; break;
+ default:
+ str = "Interworking";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Cause Class: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : National Cause",
+ a_bigbuf);
+
+ curr_offset++;
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Cause Value");
+
+ curr_offset++;
+
+ strcpy(add_string, " - (National Cause)");
+ }
+ else
+ {
+ value = tvb_get_guint8(tvb, curr_offset + 1);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Cause (MSB): %u",
+ a_bigbuf,
+ ((oct & 0x7f) << 8) | value);
+
+ curr_offset++;
+
+ other_decode_bitfield_value(a_bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Cause (LSB)",
+ a_bigbuf);
+
+ curr_offset++;
+ }
+ }
+ else
+ {
+ switch (oct)
+ {
+ case 0x00: str = "Radio interface message failure"; break;
+ case 0x01: str = "Radio interface failure"; break;
+ case 0x02: str = "Uplink Quality"; break;
+ case 0x03: str = "Uplink strength"; break;
+ case 0x04: str = "Downlink quality"; break;
+ case 0x05: str = "Downlink strength"; break;
+ case 0x06: str = "Distance"; break;
+ case 0x07: str = "OAM&P intervention"; break;
+ case 0x08: str = "MS busy"; break;
+ case 0x09: str = "Call processing"; break;
+ case 0x0A: str = "Reversion to old channel"; break;
+ case 0x0B: str = "Handoff successful"; break;
+ case 0x0C: str = "No response from MS"; break;
+ case 0x0D: str = "Timer expired"; break;
+ case 0x0E: str = "Better cell (power budget)"; break;
+ case 0x0F: str = "Interference"; break;
+ case 0x10: str = "Packet call going dormant"; break;
+ case 0x11: str = "Service option not available"; break;
+ case 0x12: str = "Invalid Call"; break;
+ case 0x13: str = "Successful operation"; break;
+ case 0x14: str = "Normal call release"; break;
+ case 0x1B: str = "Inter-BS Soft Handoff Drop Target"; break;
+ case 0x1D: str = "Intra-BS Soft Handoff Drop Target"; break;
+ case 0x20: str = "Equipment failure"; break;
+ case 0x21: str = "No radio resource available"; break;
+ case 0x22: str = "Requested terrestrial resource unavailable"; break;
+ case 0x25: str = "BS not equipped"; break;
+ case 0x26: str = "MS not equipped (or incapable)"; break;
+ case 0x29: str = "PACA Call Queued"; break;
+ case 0x2B: str = "Alternate signaling type reject"; break;
+ case 0x2D: str = "PACA Queue Overflow"; break;
+ case 0x2E: str = "PACA Cancel Request Rejected"; break;
+ case 0x30: str = "Requested transcoding/rate adaptation unavailable"; break;
+ case 0x31: str = "Lower priority radio resources not available"; break;
+ case 0x32: str = "PCF resources not available"; break;
+ case 0x33: str = "TFO Control request Failed"; break;
+ case 0x40: str = "Ciphering algorithm not supported"; break;
+ case 0x41: str = "Private Long Code not available or not supported."; break;
+ case 0x42: str = "Requested MUX option or rates not available."; break;
+ case 0x43: str = "Requested Privacy Configuration unavailable"; break;
+ case 0x4F: str = "Terrestrial circuit already allocated.a"; break;
+ case 0x50: str = "Terrestrial circuit already allocated"; break;
+ case 0x5F: str = "Protocol Error between BS and MSC.a"; break;
+ case 0x60: str = "Protocol Error between BS and MSC"; break;
+ case 0x71: str = "ADDS message too long for delivery on the paging channel"; break;
+ case 0x72: str = "MS-to-IWF TCP connection failure"; break;
+ case 0x73: str = "ATH0 (Modem hang up) Command"; break;
+ case 0x74: str = "+FSH/+FHNG (Fax session ended) Command"; break;
+ case 0x75: str = "No carrier"; break;
+ case 0x76: str = "PPP protocol failure"; break;
+ case 0x77: str = "PPP session closed by the MS"; break;
+ case 0x78: str = "Do not notify MS"; break;
+ case 0x79: str = "PDSN resources are not available"; break;
+ case 0x7A: str = "Data ready to send"; break;
+ case 0x7F: str = "Handoff procedure time-out"; break;
+ default:
+ str = "Reserved for future use";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Cause: (%u) %s",
+ a_bigbuf,
+ oct & 0x7f,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%u) %s", oct & 0x7f, str);
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.20
+ * Formats everything after the discriminator, shared function.
+ */
+static guint8
+elem_cell_id_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string, guint8 disc)
+{
+ guint32 value;
+ guint32 market_id;
+ guint32 switch_num;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ switch (disc)
+ {
+ case 0x02:
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_ansi_a_cell_ci, tvb,
+ curr_offset, 2, value);
+
+ curr_offset += 2;
+
+ sprintf(add_string, " - CI (%u)", value);
+ break;
+
+ case 0x05:
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_ansi_a_cell_lac, tvb,
+ curr_offset, 2, value);
+
+ curr_offset += 2;
+
+ sprintf(add_string, " - LAC (%u)", value);
+ break;
+
+ case 0x07:
+ market_id = tvb_get_ntohs(tvb, curr_offset);
+ switch_num = tvb_get_guint8(tvb, curr_offset + 2);
+
+ value = tvb_get_ntoh24(tvb, curr_offset);
+
+ proto_tree_add_uint_hidden(tree, hf_ansi_a_cell_mscid, tvb,
+ curr_offset, 3, value);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 3,
+ "Market ID %u Switch Number %u",
+ market_id, switch_num);
+
+ curr_offset += 3;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_ansi_a_cell_ci, tvb,
+ curr_offset, 2, value);
+
+ curr_offset += 2;
+
+ sprintf(add_string, " - Market ID (%u) Switch Number (%u) CI (%u)",
+ market_id,
+ switch_num,
+ value);
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+ "Cell ID - Non IOS format");
+
+ curr_offset += (len - 1);
+ break;
+ }
+
+ return(curr_offset - offset);
+}
+
+static guint8
+elem_cell_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str = NULL;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct >= (gint) NUM_CELL_DISC_STR)
+ {
+ str = "Unknown";
+ }
+ else
+ {
+ str = cell_disc_str[oct];
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Cell Identification Discriminator: (%u) %s",
+ oct,
+ str);
+
+ curr_offset++;
+
+ curr_offset +=
+ elem_cell_id_aux(tvb, tree, curr_offset, len - (curr_offset - offset), add_string, oct);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.21
+ */
+static guint8
+elem_cell_id_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 consumed;
+ guint8 num_cells;
+ guint32 curr_offset;
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+ gchar *str = NULL;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct >= (gint) NUM_CELL_DISC_STR)
+ {
+ str = "Unknown";
+ }
+ else
+ {
+ str = cell_disc_str[oct];
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Cell Identification Discriminator: (%u) %s",
+ oct,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ num_cells = 0;
+ do
+ {
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, -1,
+ "Cell %u",
+ num_cells + 1);
+
+ subtree = proto_item_add_subtree(item, ett_cell_list);
+
+ add_string[0] = '\0';
+ consumed =
+ elem_cell_id_aux(tvb, subtree, curr_offset, len - (curr_offset - offset), add_string, oct);
+
+ if (add_string[0] != '\0')
+ {
+ proto_item_append_text(item, add_string);
+ }
+
+ proto_item_set_len(item, consumed);
+
+ curr_offset += consumed;
+
+ num_cells++;
+ }
+ while ((len - (curr_offset - offset)) > 0);
+
+ sprintf(add_string, " - %u cell%s",
+ num_cells, plurality(num_cells, "", "s"));
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.22
+ */
+static guint8
+elem_cic(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 value;
+ guint32 curr_offset;
+
+ len = len;
+ curr_offset = offset;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0xffe0, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : PCM Multiplexer: %u",
+ a_bigbuf,
+ (value & 0xffe0) >> 5);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : Timeslot: %u",
+ a_bigbuf,
+ value & 0x001f);
+
+ curr_offset += 2;
+
+ sprintf(add_string, " - (%u) (0x%04x)", value, value);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.23
+ */
+static guint8
+elem_cic_ext(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ curr_offset = offset;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0xffe0, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : PCM Multiplexer: %u",
+ a_bigbuf,
+ (value & 0xffe0) >> 5);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : Timeslot: %u",
+ a_bigbuf,
+ value & 0x001f);
+
+ curr_offset += 2;
+
+ sprintf(add_string, " - (%u) (0x%04x)", value, value);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ switch (oct & 0x0f)
+ {
+ case 0x00: str = "Full-rate"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Circuit Mode: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.24
+ * UNUSED
+ */
+
+#define ANSI_A_CELL_ID_LEN(_disc) ((_disc == 7) ? 5 : 2)
+
+/*
+ * IOS 6.2.2.25
+ */
+static guint8
+elem_downlink_re(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 disc;
+ guint8 consumed;
+ guint8 num_cells;
+ guint32 value;
+ guint32 curr_offset;
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Number of Cells: %u",
+ oct);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ disc = tvb_get_guint8(tvb, curr_offset);
+
+ if (disc >= (gint) NUM_CELL_DISC_STR)
+ {
+ str = "Unknown";
+ }
+ else
+ {
+ str = cell_disc_str[disc];
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Cell Identification Discriminator: (%u) %s",
+ disc,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ SHORT_DATA_CHECK(len - (curr_offset - offset), (guint32) 3 + ANSI_A_CELL_ID_LEN(disc));
+
+ num_cells =0;
+
+ do
+ {
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, -1,
+ "Cell %u",
+ num_cells + 1);
+
+ subtree = proto_item_add_subtree(item, ett_cell_list);
+
+ add_string[0] = '\0';
+ consumed =
+ elem_cell_id_aux(tvb, subtree, curr_offset,
+ len - (curr_offset - offset), add_string, disc);
+
+ if (add_string[0] != '\0')
+ {
+ proto_item_append_text(item, add_string);
+ }
+
+ proto_item_set_len(item, consumed);
+
+ curr_offset += consumed;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Downlink Signal Strength Raw: %u",
+ a_bigbuf,
+ oct & 0x3f);
+
+ curr_offset++;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "CDMA Target One Way Delay: %u",
+ value);
+
+ curr_offset += 2;
+
+ num_cells++;
+ }
+ while ((len - (curr_offset - offset)) >= (guint32) (3 + ANSI_A_CELL_ID_LEN(disc)));
+
+ sprintf(add_string, " - %u cell%s",
+ num_cells, plurality(num_cells, "", "s"));
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.26
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.27
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.28
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.29
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.30
+ */
+static guint8
+elem_pdsn_ip_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_item(tree, hf_ansi_a_pdsn_ip_addr, tvb, curr_offset, len, FALSE);
+
+/*
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ "IPv4 Address");
+*/
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.31
+ */
+static guint8
+elem_ho_pow_lev(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 consumed;
+ guint8 num_cells;
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Number of Cells: %u",
+ oct);
+
+ curr_offset++;
+
+ SHORT_DATA_CHECK(len - (curr_offset - offset), (guint32) 6);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ID Type: %u",
+ a_bigbuf,
+ (oct & 0x60) >> 5);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Handoff Power Level: %u",
+ a_bigbuf,
+ oct & 0x1f);
+
+ curr_offset++;
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, -1,
+ "Cell 1");
+
+ subtree = proto_item_add_subtree(item, ett_cell_list);
+
+ add_string[0] = '\0';
+ consumed =
+ elem_cell_id_aux(tvb, subtree, curr_offset,
+ len - (curr_offset - offset), add_string, 0x7);
+
+ if (add_string[0] != '\0')
+ {
+ proto_item_append_text(item, add_string);
+ }
+
+ proto_item_set_len(item, consumed);
+
+ curr_offset += consumed;
+
+ num_cells = 1;
+
+ while ((len - (curr_offset - offset)) >= 3)
+ {
+ num_cells++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Handoff Power Level: %u",
+ a_bigbuf,
+ oct & 0x1f);
+
+ curr_offset++;
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, -1,
+ "Cell %u",
+ num_cells);
+
+ subtree = proto_item_add_subtree(item, ett_cell_list);
+
+ add_string[0] = '\0';
+ consumed =
+ elem_cell_id_aux(tvb, subtree, curr_offset,
+ len - (curr_offset - offset), add_string, 0x2);
+
+ if (add_string[0] != '\0')
+ {
+ proto_item_append_text(item, add_string);
+ }
+
+ proto_item_set_len(item, consumed);
+
+ curr_offset += consumed;
+ }
+
+ sprintf(add_string, " - %u cell%s",
+ num_cells, plurality(num_cells, "", "s"));
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.32
+ */
+static guint8
+elem_uz_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 value;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 2,
+ "UZID: %u",
+ value);
+
+ curr_offset += 2;
+
+ sprintf(add_string, " - (%u)", value);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.33
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.34
+ */
+static guint8
+elem_is2000_chan_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 num_chan;
+ guint32 value;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : OTD: Mobile will %sbe using OTD",
+ a_bigbuf,
+ (oct & 0x80) ? "" : "not ");
+
+ num_chan = (oct & 0x70) >> 4;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Channel Count: %u",
+ a_bigbuf,
+ num_chan);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Frame Offset: (%u), %.2f ms",
+ a_bigbuf,
+ oct & 0x0f,
+ (oct & 0x0f) * 1.25);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ SHORT_DATA_CHECK(len - (curr_offset - offset), 6);
+
+ do
+ {
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0x01: str = "Fundamental Channel (FCH) TIA/EIA/IS-2000"; break;
+ case 0x02: str = "Dedicated Control Channel (DCCH) TIA/EIA/IS-2000"; break;
+ case 0x03: str = "Supplemental Channel (SCH) TIA/EIA/IS-2000"; break;
+ default:
+ if ((oct >= 0x80) && (oct <= 0x9f)) { str = "Reserved for UMTS"; }
+ else { str = "Reserved"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Physical Channel Type: %s",
+ str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0: str = "Gating rate 1"; break;
+ case 1: str = "Gating rate 1/2"; break;
+ case 2: str = "Gating rate 1/4"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Pilot Gating Rate: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : QOF Mask",
+ a_bigbuf);
+
+ value = tvb_get_guint8(tvb, curr_offset + 1);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Walsh Code Channel Index (MSB): %u",
+ a_bigbuf,
+ ((guint32) (oct & 0x07) << 8) | value);
+
+ curr_offset++;
+
+ other_decode_bitfield_value(a_bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Walsh Code Channel Index (LSB)",
+ a_bigbuf);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Pilot PN Code (LSB)",
+ a_bigbuf);
+
+ curr_offset++;
+
+ value = oct;
+ oct = tvb_get_guint8(tvb, curr_offset);
+ value |= ((guint32) (oct & 0x80)) << 1;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Pilot PN Code (MSB): %u",
+ a_bigbuf,
+ value);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Frequency Included",
+ a_bigbuf);
+
+ value = tvb_get_guint8(tvb, curr_offset + 1) | ((oct & 0x07) << 8);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ARFCN (MSB): %u",
+ a_bigbuf,
+ value);
+
+ curr_offset++;
+
+ other_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ARFCN (LSB)",
+ a_bigbuf);
+
+ curr_offset++;
+ }
+ while ((len - (curr_offset - offset)) >= 6);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.35
+ * NO ASSOCIATED DATA
+ */
+
+/*
+ * IOS 6.2.2.36
+ */
+static guint8
+elem_is95_ms_meas_chan_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ gint temp_int;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ temp_int = (oct & 0xf8) >> 3;
+ if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = band_class_str[temp_int];
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Band Class: %s",
+ a_bigbuf,
+ str);
+
+ value = tvb_get_guint8(tvb, curr_offset + 1) | ((oct & 0x07) << 8);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ARFCN (MSB): %u",
+ a_bigbuf,
+ value);
+
+ curr_offset++;
+
+ other_decode_bitfield_value(a_bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ARFCN (LSB)",
+ a_bigbuf);
+
+ sprintf(add_string, " - (ARFCN: %u)", value);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.37
+ */
+static guint8
+elem_clg_party_ascii_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ guint8 *poctets;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "Not extended" : "Extended");
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "International number"; break;
+ case 2: str = "National number"; break;
+ case 3: str = "Network-specific number"; break;
+ case 4: str = "Dedicated PAD access, short code"; break;
+ case 5: str = "Reserved"; break;
+ case 6: str = "Reserved"; break;
+ default:
+ str = "Reserved for extension";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Type of Number: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x0f)
+ {
+ case 0x00: str = "Unknown"; break;
+ case 0x01: str = "ISDN/Telephony Numbering (ITU recommendation E.164/E.163)"; break;
+ case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break;
+ case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break;
+ case 0x07: str = "Reserved for extension"; break;
+ case 0x08: str = "National Numbering"; break;
+ case 0x09: str = "Private Numbering"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Number Plan Identification: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ if (!(oct & 0x80))
+ {
+ /* octet 3a */
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0: str = "Presentation allowed"; break;
+ case 1: str = "Presentation restricted"; break;
+ case 2: str = "Number not available due to interworking"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Presentation Indicator: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x03)
+ {
+ case 0: str = "User-provided, not screened"; break;
+ case 1: str = "User-provided, verified and passed"; break;
+ case 2: str = "User-provided, verified and failed"; break;
+ default:
+ str = "Network-provided";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1c, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Screening Indicator: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+ }
+
+ poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+ proto_tree_add_string_format(tree, hf_ansi_a_clg_party_ascii_num,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Digits: %s",
+ poctets);
+
+ curr_offset += len - (curr_offset - offset);
+
+ sprintf(add_string, " - (%s)", poctets);
+ g_free(poctets);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.38
+ */
+static guint8
+elem_l3_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+ tvbuff_t *l3_tvb;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ "Layer 3 Information");
+
+ /*
+ * dissect the embedded DTAP message
+ */
+ l3_tvb = tvb_new_subset(tvb, curr_offset, len, len);
+
+ call_dissector(dtap_handle, l3_tvb, g_pinfo, g_tree);
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.39
+ * Protocol Discriminator
+ */
+
+/*
+ * IOS 6.2.2.40
+ * Reserved Octet
+ */
+
+/*
+ * IOS 6.2.2.41
+ * Location Updating Type
+ * UNUSED in SPEC!
+ */
+
+/*
+ * IOS 6.2.2.42
+ * Simple data no decode required
+ */
+
+/*
+ * IOS 6.2.2.43
+ */
+static guint8
+elem_lai(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint16 value;
+ guint32 curr_offset;
+ gchar mcc[4];
+ gchar mnc[4];
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ mcc[0] = Dgt_tbcd.out[oct & 0x0f];
+ mcc[1] = Dgt_tbcd.out[(oct & 0xf0) >> 4];
+
+ oct = tvb_get_guint8(tvb, curr_offset+1);
+
+ mcc[2] = Dgt_tbcd.out[(oct & 0x0f)];
+ mcc[3] = '\0';
+
+ mnc[2] = Dgt_tbcd.out[(oct & 0xf0) >> 4];
+
+ oct = tvb_get_guint8(tvb, curr_offset+2);
+
+ mnc[0] = Dgt_tbcd.out[(oct & 0x0f)];
+ mnc[1] = Dgt_tbcd.out[(oct & 0xf0) >> 4];
+ mnc[3] = '\0';
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 3,
+ "Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
+ mcc,
+ mnc);
+
+ curr_offset += 3;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "Location Area Code (LAC): 0x%04x (%u)",
+ value,
+ value);
+
+ curr_offset += 2;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.44
+ */
+static guint8
+elem_rej_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0x01: str = "Reserved"; break;
+ case 0x02: str = "MIN/IMSI unknown in HLR"; break;
+ case 0x03: str = "Illegal MS"; break;
+ case 0x04: str = "TMSI/IMSI/MIN unknown in VLR"; break;
+ case 0x05: str = "Reserved"; break;
+ case 0x0b: str = "Roaming not allowed"; break;
+ case 0x0c: str = "Location area not allowed"; break;
+ case 0x20: str = "Service option not supported"; break;
+ case 0x21: str = "Requested service option not subscribed"; break;
+ case 0x22: str = "Service option temporarily out of order"; break;
+ case 0x26: str = "Call cannot be identified"; break;
+ case 0x51: str = "Network failure"; break;
+ case 0x56: str = "Congestion"; break;
+ case 0x62: str = "Message type non-existent or not implemented"; break;
+ case 0x63: str = "Information element non-existent or not implemented"; break;
+ case 0x64: str = "Invalid information element contents"; break;
+ case 0x65: str = "Message not compatible with the call state"; break;
+ case 0x66: str = "Protocol error, unspecified"; break;
+ case 0x6e: str = "Invalid message, unspecified"; break;
+ case 0x6f: str = "Mandatory information element error"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Reject Cause Value: (%u) %s",
+ oct,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%s)", str);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.45
+ */
+static guint8
+elem_auth_chlg_param(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ switch (oct & 0x0f)
+ {
+ case 1: str = "RAND 32 bits"; break;
+ case 2: str = "RANDU 24 bits"; break;
+ case 4: str = "RANDSSD 56 bits"; break;
+ case 8: str = "RANDBS 32 bits"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Random Number Type: (%u) %s",
+ a_bigbuf,
+ oct & 0x0f,
+ str);
+
+ curr_offset++;
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "RAND/RANDU/RANDBS/RANDSSD Value");
+
+ sprintf(add_string, " - (%s)", str);
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.46
+ */
+static guint8
+elem_auth_resp_param(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ switch (oct & 0x0f)
+ {
+ case 1: str = "AUTHR"; break;
+ case 2: str = "AUTHU"; break;
+ case 4: str = "AUTHBS"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Auth Signature Type: (%u) %s",
+ a_bigbuf,
+ oct & 0x0f,
+ str);
+
+ curr_offset++;
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Auth Signature");
+
+ sprintf(add_string, " - (%s)", str);
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.47
+ */
+static guint8
+elem_auth_param_count(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Count: %u",
+ a_bigbuf,
+ oct & 0x3f);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%u)", oct & 0x3f);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.48
+ */
+static guint8
+elem_mwi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Number of Messages: %u",
+ oct);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%u)", oct);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.49
+ * Progress
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.50
+ */
+static guint8
+elem_signal(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0x00: str = "Dial tone on"; break;
+ case 0x01: str = "Ring back tone on"; break;
+ case 0x02: str = "Intercept tone on"; break;
+ case 0x03: str = "Network congestion (reorder) tone on"; break;
+ case 0x04: str = "Busy tone on"; break;
+ case 0x05: str = "Confirm tone on"; break;
+ case 0x06: str = "Answer tone on"; break;
+ case 0x07: str = "Call waiting tone on"; break;
+ case 0x08: str = "Off-hook warning tone on"; break;
+ case 0x3f: str = "Tones off"; break;
+ case 0x40: str = "Normal Alerting"; break;
+ case 0x41: str = "Inter-group Alerting"; break;
+ case 0x42: str = "Special/Priority Alerting"; break;
+ case 0x43: str = "Reserved (ISDN Alerting pattern 3)"; break;
+ case 0x44: str = "Ping Ring (abbreviated alert)"; break;
+ case 0x45: str = "Reserved (ISDN Alerting pattern 5)"; break;
+ case 0x46: str = "Reserved (ISDN Alerting pattern 6)"; break;
+ case 0x47: str = "Reserved (ISDN Alerting pattern 7)"; break;
+ case 0x63: str = "Abbreviated intercept"; break;
+ case 0x65: str = "Abbreviated reorder"; break;
+ case 0x4f: str = "Alerting off"; break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Signal Value: (%u) %s",
+ oct,
+ str);
+
+ sprintf(add_string, " - (%s)", str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ switch (oct & 0x03)
+ {
+ case 0: str = "Medium pitch (standard alert)"; break;
+ case 1: str = "High pitch"; break;
+ case 2: str = "Low pitch"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Alert Pitch: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.51
+ * CM Service Type
+ */
+
+/*
+ * IOS 6.2.2.52
+ */
+static guint8
+elem_cld_party_bcd_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 *poctets;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "International number"; break;
+ case 2: str = "National number"; break;
+ case 3: str = "Network specific number"; break;
+ case 4: str = "Dedicated PAD access, short code"; break;
+ case 7: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Number: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x0f)
+ {
+ case 0x00: str = "Unknown"; break;
+ case 0x01: str = "ISDN/telephony number plan (ITU recommendation E.164/E.163)"; break;
+ case 0x03: str = "Data number plan (ITU recommendation X.121)"; break;
+ case 0x04: str = "Telex numbering plan (ITU recommendation F.69)"; break;
+ case 0x07: str = "Reserved for extension"; break;
+ case 0x08: str = "National numbering plan"; break;
+ case 0x09: str = "Private numbering plan"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Numbering Plan Identification: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+ my_dgt_tbcd_unpack(a_bigbuf, poctets, len - (curr_offset - offset),
+ &Dgt_tbcd);
+ g_free(poctets);
+
+ proto_tree_add_string_format(tree, hf_ansi_a_cld_party_bcd_num,
+ tvb, curr_offset, len - (curr_offset - offset),
+ a_bigbuf,
+ "BCD Digits: %s",
+ a_bigbuf);
+
+ sprintf(add_string, " - (%s)", a_bigbuf);
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.53
+ * UNUSED in SPEC and no IEI!
+ */
+#ifdef MAYBE_USED_FOR_OLDER_CODECS
+static guint8
+elem_clg_party_bcd_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 *poctets;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "Not extended" : "Extended");
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "International number"; break;
+ case 2: str = "National number"; break;
+ case 3: str = "Network specific number"; break;
+ case 4: str = "Dedicated PAD access, short code"; break;
+ case 7: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Number: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x0f)
+ {
+ case 0x00: str = "Unknown"; break;
+ case 0x01: str = "ISDN/telephony number plan (ITU recommendation E.164/E.163)"; break;
+ case 0x03: str = "Data number plan (ITU recommendation X.121)"; break;
+ case 0x04: str = "Telex numbering plan (ITU recommendation F.69)"; break;
+ case 0x07: str = "Reserved for extension"; break;
+ case 0x08: str = "National numbering plan"; break;
+ case 0x09: str = "Private numbering plan"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Numbering Plan Identification: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ if (!(oct & 0x80))
+ {
+ /* octet 3a */
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0: str = "Presentation allowed"; break;
+ case 1: str = "Presentation restricted"; break;
+ case 2: str = "Number not available due to interworking"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Presentation Indicator: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x03)
+ {
+ case 0: str = "User-provided, not screened"; break;
+ case 1: str = "User-provided, verified and passed"; break;
+ case 2: str = "User-provided, verified and failed"; break;
+ default:
+ str = "Network-provided";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1c, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Screening Indicator: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+ }
+
+ poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+ my_dgt_tbcd_unpack(a_bigbuf, poctets, len - (curr_offset - offset),
+ &Dgt_tbcd);
+ g_free(poctets);
+
+ proto_tree_add_string_format(tree, hf_ansi_a_clg_party_bcd_num,
+ tvb, curr_offset, len - (curr_offset - offset),
+ a_bigbuf,
+ "BCD Digits: %s",
+ a_bigbuf);
+
+ sprintf(add_string, " - (%s)", a_bigbuf);
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+#endif
+
+/*
+ * IOS 6.2.2.54
+ */
+static guint8
+elem_qos_params(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Packet Priority: %u",
+ a_bigbuf,
+ oct & 0x0f);
+
+ sprintf(add_string, " - (%u)", oct & 0x0f);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.55
+ */
+static guint8
+elem_cause_l3(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str = NULL;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0: str = "Standard as described in ITU Recommendation Q.931"; break;
+ case 1: str = "Reserved for other international standards"; break;
+ case 2: str = "National standard"; break;
+ default:
+ str = "Reserved for other international standards";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Coding Standard: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ switch (oct & 0x0f)
+ {
+ case 0: str = "User"; break;
+ case 1: str = "Private network serving the local user"; break;
+ case 2: str = "Public network serving the local user"; break;
+ case 3: str = "Transit network"; break;
+ case 4: str = "Public network serving the remote user"; break;
+ case 5: str = "Private network serving the remote user"; break;
+ case 7: str = "International network"; break;
+ case 10: str = "Network beyond interworking point"; break;
+ default:
+ str = "All other values Reserved"; break;
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Location: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "normal event"; break;
+ case 1: str = "normal event"; break;
+ case 2: str = "resource unavailable"; break;
+ case 3: str = "service or option not available"; break;
+ case 4: str = "service or option not implemented"; break;
+ case 5: str = "invalid message (e.g., parameter out of range)"; break;
+ case 6: str = "protocol error (e.g., unknown message)"; break;
+ default:
+ str = "interworking";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Class: (%u) %s",
+ a_bigbuf,
+ (oct & 0x70) >> 4,
+ str);
+
+ switch (oct & 0x7f)
+ {
+ case 0x01: str = "Unassigned (unallocated) number"; break;
+ case 0x03: str = "No route to destination"; break;
+ case 0x06: str = "Channel unacceptable"; break;
+ case 0x0F: str = "Procedure failed"; break;
+ case 0x10: str = "Normal Clearing"; break;
+ case 0x11: str = "User busy"; break;
+ case 0x12: str = "No user responding"; break;
+ case 0x13: str = "User alerting, no answer"; break;
+ case 0x15: str = "Call rejected"; break;
+ case 0x16: str = "Number changed New destination"; break;
+ case 0x1A: str = "Non selected user clearing"; break;
+ case 0x1B: str = "Destination out of order"; break;
+ case 0x1C: str = "Invalid number format (incomplete number)"; break;
+ case 0x1D: str = "Facility rejected"; break;
+ case 0x1F: str = "Normal, unspecified"; break;
+ case 0x22: str = "No circuit/channel available"; break;
+ case 0x26: str = "Network out of order"; break;
+ case 0x29: str = "Temporary failure"; break;
+ case 0x2A: str = "Switching equipment congestion"; break;
+ case 0x2B: str = "Access information discarded information element ids"; break;
+ case 0x2C: str = "requested circuit/channel not available"; break;
+ case 0x2F: str = "Resources unavailable, unspecified"; break;
+ case 0x31: str = "Quality of service unavailable"; break;
+ case 0x32: str = "Requested facility not subscribed"; break;
+ case 0x33: str = "Request MUX option or rates unavailable"; break;
+ case 0x39: str = "Bearer capability not authorized"; break;
+ case 0x3A: str = "Bearer capability not presently available"; break;
+ case 0x3B: str = "SSD Update Rejected"; break;
+ case 0x3F: str = "Service or option not available, unspecified"; break;
+ case 0x41: str = "Bearer service not implemented"; break;
+ case 0x45: str = "Requested facility not implement"; break;
+ case 0x46: str = "Only restricted digital information bearer capability is available"; break;
+ case 0x4F: str = "Service or option not implemented, unspecified"; break;
+ case 0x51: str = "Reserved"; break;
+ case 0x58: str = "Incompatible destination incompatible parameter"; break;
+ case 0x5B: str = "Invalid transit network selection"; break;
+ case 0x5F: str = "Invalid message, unspecified"; break;
+ case 0x60: str = "Mandatory information element error information element identifier(s)"; break;
+ case 0x61: str = "Message type nonexistent or not implemented message type"; break;
+ case 0x62: str = "Message not compatible with control state message type or message type nonexistent or not implemented"; break;
+ case 0x64: str = "Invalid information element contents Information element Identifier(s)"; break;
+ case 0x65: str = "Message not compatible with call state message type"; break;
+ case 0x6F: str = "Protocol error, unspecified"; break;
+ case 0x7F: str = "Interworking, unspecified"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Value: (%u)",
+ a_bigbuf,
+ oct & 0x0f);
+
+ sprintf(add_string, " - (%u) %s", oct & 0x7f, str);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.56
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.57
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.58
+ */
+static guint8
+elem_xmode(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfe, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : TFO Mode: %s",
+ a_bigbuf,
+ (oct & 0x01) ? "TFO" : "tandem");
+
+ sprintf(add_string, " - (%s)",
+ (oct & 0x01) ? "TFO" : "tandem");
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.59
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.60
+ * NO ASSOCIATED DATA
+ */
+
+/*
+ * IOS 6.2.2.61
+ */
+static guint8
+elem_reg_type(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0x00: str = "Timer-based"; break;
+ case 0x01: str = "Power-up"; break;
+ case 0x02: str = "Zone-based"; break;
+ case 0x03: str = "Power-down"; break;
+ case 0x04: str = "Parameter-change"; break;
+ case 0x05: str = "Ordered"; break;
+ case 0x06: str = "Distance-based"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Location Registration Type: %s",
+ str);
+
+ sprintf(add_string, " - (%s)", str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.62
+ */
+static guint8
+elem_tag(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 value;
+ guint32 curr_offset;
+
+ len = len;
+ curr_offset = offset;
+
+ value = tvb_get_ntohl(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 4,
+ "Tag Value: %u",
+ value);
+
+ sprintf(add_string, " - (%u)", value);
+
+ curr_offset += 4;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.63
+ */
+static guint8
+elem_hho_params(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ gint temp_int;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ temp_int = oct & 0x1f;
+ if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = band_class_str[temp_int];
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Band Class: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%s)", str);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Number of Preamble Frames: %u",
+ a_bigbuf,
+ (oct & 0xe0) >> 5);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reset L2: %s Layer 2 Acknowledgement",
+ a_bigbuf,
+ (oct & 0x10) ? "Reset" : "Do not reset");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reset FPC: %s counters",
+ a_bigbuf,
+ (oct & 0x10) ? "Reset" : "Do not reset");
+
+ switch ((oct & 0x06) >> 1)
+ {
+ case 0: str = "Encryption disabled"; break;
+ case 1: str = "Encryption enabled"; break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x06, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Encryption Mode: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Private LCM: %s Private Long Code Mask",
+ a_bigbuf,
+ (oct & 0x01) ? "Use" : "Do not use");
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Nom_Pwr_Ext",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Nom_Pwr: %u",
+ a_bigbuf,
+ oct & 0x0f);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3e, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : FPC Subchannel Information: %u",
+ a_bigbuf,
+ (oct & 0x3e) >> 1);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : FPC SubChannel Information Included",
+ a_bigbuf);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0e, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Power Control Step: %u",
+ a_bigbuf,
+ (oct & 0x0e) >> 1);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Power Control Step Included",
+ a_bigbuf);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.64
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.65
+ */
+static guint8
+elem_sw_ver(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 major, minor, point;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ major = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "IOS Major Revision Level: %u",
+ major);
+
+ curr_offset++;
+
+ minor = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "IOS Minor Revision Level: %u",
+ minor);
+
+ curr_offset++;
+
+ point = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "IOS Point Revision Level: %u",
+ point);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (IOS %u.%u.%u)", major, minor, point);
+
+ if (len > 3)
+ {
+ proto_tree_add_text(tree, tvb, curr_offset, len - 3,
+ "Manufacturer/Carrier Software Information");
+
+ curr_offset += len - 3;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+/*
+ * IOS 6.2.2.66
+ */
+static guint8
+elem_so(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint16 value;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ curr_offset = offset;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x8000, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : Proprietary Indicator",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x7000, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : Service Option Revision",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x0fff, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : Base Service Option Number",
+ a_bigbuf);
+
+ switch (value)
+ {
+ case 1: str = "Basic Variable Rate Voice Service (8 kbps)"; break;
+ case 2: str = "Mobile Station Loopback (8 kbps)"; break;
+ case 3: str = "Enhanced Variable Rate Voice Service (8 kbps)"; break;
+ case 4: str = "Asynchronous Data Service (9.6 kbps)"; break;
+ case 5: str = "Group 3 Facsimile (9.6 kbps)"; break;
+ case 6: str = "Short Message Services (Rate Set 1)"; break;
+ case 7: str = "Packet Data Service: Internet or ISO Protocol Stack (9.6 kbps)"; break;
+ case 8: str = "Packet Data Service: CDPD Protocol Stack (9.6 kbps)"; break;
+ case 9: str = "Mobile Station Loopback (13 kbps)"; break;
+ case 10: str = "STU-III Transparent Service"; break;
+ case 11: str = "STU-III Non-Transparent Service"; break;
+ case 12: str = "Asynchronous Data Service (14.4 or 9.6 kbps)"; break;
+ case 13: str = "Group 3 Facsimile (14.4 or 9.6 kbps)"; break;
+ case 14: str = "Short Message Services (Rate Set 2)"; break;
+ case 15: str = "Packet Data Service: Internet or ISO Protocol Stack (14.4 kbps)"; break;
+ case 16: str = "Packet Data Service: CDPD Protocol Stack (14.4 kbps)"; break;
+ case 17: str = "High Rate Voice Service (13 kbps)"; break;
+ case 32768: str = "QCELP (13 kbps)"; break;
+ case 32798: /* 0x801e */ str = "Qualcomm Loopback"; break;
+ case 32799: /* 0x801f */ str = "Qualcomm Markov 8 kbps Loopback"; break;
+ case 32800: /* 0x8020 */ str = "Qualcomm Packet Data"; break;
+ case 32801: /* 0x8021 */ str = "Qualcomm Async Data"; break;
+ case 18: str = "Over-the-Air Parameter Administration (Rate Set 1)"; break;
+ case 19: str = "Over-the-Air Parameter Administration (Rate Set 2)"; break;
+ case 20: str = "Group 3 Analog Facsimile (Rate Set 1)"; break;
+ case 21: str = "Group 3 Analog Facsimile (Rate Set 2)"; break;
+ case 22: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS1 forward, RS1 reverse)"; break;
+ case 23: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS1 forward, RS2 reverse)"; break;
+ case 24: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS2 forward, RS1 reverse)"; break;
+ case 25: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS2 forward, RS2 reverse)"; break;
+ case 26: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS1 forward, RS1 reverse)"; break;
+ case 27: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS1 forward, RS2 reverse)"; break;
+ case 28: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS2 forward, RS1 reverse)"; break;
+ case 29: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS2 forward, RS2 reverse)"; break;
+ case 30: str = "Supplemental Channel Loopback Test for Rate Set 1"; break;
+ case 31: str = "Supplemental Channel Loopback Test for Rate Set 2"; break;
+ case 32: str = "Test Data Service Option (TDSO)"; break;
+ case 33: str = "cdma2000 High Speed Packet Data Service, Internet or ISO Protocol Stack"; break;
+ case 34: str = "cdma2000 High Speed Packet Data Service, CDPD Protocol Stack"; break;
+ case 35: str = "Location Services, Rate Set 1 (9.6 kbps)"; break;
+ case 36: str = "Location Services, Rate Set 2 (14.4 kbps)"; break;
+ case 37: str = "ISDN Interworking Service (64 kbps)"; break;
+ case 38: str = "GSM Voice"; break;
+ case 39: str = "GSM Circuit Data"; break;
+ case 40: str = "GSM Packet Data"; break;
+ case 41: str = "GSM Short Message Service"; break;
+ case 42: str = "None Reserved for MC-MAP standard service options"; break;
+ case 54: str = "Markov Service Option (MSO)"; break;
+ case 55: str = "Loopback Service Option (LSO)"; break;
+ case 56: str = "Selectable Mode Vocoder"; break;
+ case 57: str = "32 kbps Circuit Video Conferencing"; break;
+ case 58: str = "64 kbps Circuit Video Conferencing"; break;
+ case 59: str = "HRPD Accounting Records Identifier"; break;
+ case 60: str = "Link Layer Assisted Robust Header Compression (LLA ROHC) - Header Removal"; break;
+ case 61: str = "Link Layer Assisted Robust Header Compression (LLA ROHC) - Header Compression"; break;
+ case 62: str = "- 4099 None Reserved for standard service options"; break;
+ case 4100: str = "Asynchronous Data Service, Revision 1 (9.6 or 14.4 kbps)"; break;
+ case 4101: str = "Group 3 Facsimile, Revision 1 (9.6 or 14.4 kbps)"; break;
+ case 4102: str = "Reserved for standard service option"; break;
+ case 4103: str = "Packet Data Service: Internet or ISO Protocol Stack, Revision 1 (9.6 or 14.4 kbps)"; break;
+ case 4104: str = "Packet Data Service: CDPD Protocol Stack, Revision 1 (9.6 or 14.4 kbps)"; break;
+ default:
+ if ((value >= 4105) && (value <= 32767)) { str = "Reserved for standard service options"; }
+ else if ((value >= 32769) && (value <= 32771)) { str = "Proprietary QUALCOMM Incorporated"; }
+ else if ((value >= 32772) && (value <= 32775)) { str = "Proprietary OKI Telecom"; }
+ else if ((value >= 32776) && (value <= 32779)) { str = "Proprietary Lucent Technologies"; }
+ else if ((value >= 32780) && (value <=32783)) { str = "Nokia"; }
+ else if ((value >= 32784) && (value <=32787)) { str = "NORTEL NETWORKS"; }
+ else if ((value >= 32788) && (value <=32791)) { str = "Sony Electronics Inc."; }
+ else if ((value >= 32792) && (value <=32795)) { str = "Motorola"; }
+ else if ((value >= 32796) && (value <=32799)) { str = "QUALCOMM Incorporated"; }
+ else if ((value >= 32800) && (value <=32803)) { str = "QUALCOMM Incorporated"; }
+ else if ((value >= 32804) && (value <=32807)) { str = "QUALCOMM Incorporated"; }
+ else if ((value >= 32808) && (value <=32811)) { str = "QUALCOMM Incorporated"; }
+ else if ((value >= 32812) && (value <=32815)) { str = "Lucent Technologies"; }
+ else if ((value >= 32816) && (value <=32819)) { str = "Denso International"; }
+ else if ((value >= 32820) && (value <=32823)) { str = "Motorola"; }
+ else if ((value >= 32824) && (value <=32827)) { str = "Denso International"; }
+ else if ((value >= 32828) && (value <=32831)) { str = "Denso International"; }
+ else if ((value >= 32832) && (value <=32835)) { str = "Denso International"; }
+ else if ((value >= 32836) && (value <=32839)) { str = "NEC America"; }
+ else if ((value >= 32840) && (value <=32843)) { str = "Samsung Electronics"; }
+ else if ((value >= 32844) && (value <=32847)) { str = "Texas Instruments Incorporated"; }
+ else if ((value >= 32848) && (value <=32851)) { str = "Toshiba Corporation"; }
+ else if ((value >= 32852) && (value <=32855)) { str = "LG Electronics Inc."; }
+ else if ((value >= 32856) && (value <=32859)) { str = "VIA Telecom Inc."; }
+ else { str = "Reserved"; }
+ break;
+ }
+
+ sprintf(add_string, " - (%u) (0x%04x)", value, value);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s %s",
+ &add_string[3],
+ str);
+
+ curr_offset += 2;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+#define ADDS_APP_SMS 0x03
+#define ADDS_APP_OTA 0x04
+#define ADDS_APP_PLD 0x05
+
+/*
+ * IOS 6.2.2.67
+ */
+static guint8
+elem_adds_user_part(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 adds_app;
+ guint32 curr_offset;
+ gchar *str;
+ tvbuff_t *adds_tvb;
+
+ curr_offset = offset;
+ adds_app = 0;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ adds_app = oct & 0x3f;
+
+ switch (adds_app)
+ {
+ case ADDS_APP_SMS:
+ str = "SMS";
+
+ adds_tvb = tvb_new_subset(tvb, curr_offset + 1, len - 1, len - 1);
+
+ dissector_try_port(is637_dissector_table,
+ 0, adds_tvb, g_pinfo, g_tree);
+ break;
+
+ case ADDS_APP_OTA:
+ str = "OTA";
+
+ adds_tvb = tvb_new_subset(tvb, curr_offset + 1, len - 1, len - 1);
+
+ dissector_try_port(is683_dissector_table,
+ (g_pinfo->p2p_dir == P2P_DIR_RECV), adds_tvb, g_pinfo, g_tree);
+ break;
+
+ case ADDS_APP_PLD:
+ str = "PLD";
+
+ adds_tvb = tvb_new_subset(tvb, curr_offset + 1, len - 1, len - 1);
+
+ dissector_try_port(is801_dissector_table,
+ (g_pinfo->p2p_dir == P2P_DIR_RECV), adds_tvb, g_pinfo, g_tree);
+ break;
+
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Data Burst Type: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+ "Application Data Message");
+
+ sprintf(add_string, " - (%s)", str);
+
+ curr_offset += (len - 1);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.68
+ */
+static guint8
+elem_is2000_scr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Bit-Exact Length Fill Bits: %u",
+ a_bigbuf,
+ oct & 0x07);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree, tvb, curr_offset,
+ len - (curr_offset - offset),
+ "IS-2000 Service Configuration Record Content");
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.69
+ */
+static guint8
+elem_is2000_nn_scr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 oct_len;
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct_len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Bit-Exact Length Octet Count: %u",
+ oct_len);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Bit-Exact Length Fill Bits: %u",
+ a_bigbuf,
+ oct & 0x07);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (oct_len > 0)
+ {
+ SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+ proto_tree_add_text(tree, tvb, curr_offset, oct_len,
+ "IS-2000 Non-Negotiable Service Configuration Record Content");
+
+ curr_offset += oct_len;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.70
+ */
+static guint8
+elem_is2000_mob_cap(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 oct_len;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : DCCH Supported: IS-2000 DCCH %ssupported",
+ a_bigbuf,
+ (oct & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : FCH Supported: IS-2000 FCH %ssupported",
+ a_bigbuf,
+ (oct & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : OTD Supported: Orthogonal Transmit Diversity %ssupported",
+ a_bigbuf,
+ (oct & 0x04) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Enhanced RC CFG Supported: Radio configuration in radio class 2 %ssupported",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : QPCH Supported: Quick Paging Channel %ssupported",
+ a_bigbuf,
+ (oct & 0x01) ? "" : "not ");
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct_len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "FCH Information: Bit-Exact Length Octet Count: %u",
+ oct_len);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "No mobile assisted geo-location capabilities"; break;
+ case 1: str = "IS801 capable (Advanced Forward Link Triangulation only (AFLT))"; break;
+ case 2: str = "IS801 capable (Advanced Forward Link Triangulation and Global Positioning Systems"; break;
+ case 3: str = "Global Positioning Systems Only"; break;
+ default:
+ str = "All Other values reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Geo Location Type: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Geo Location Included",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : FCH Information: Bit-Exact Length Fill Bits: %u",
+ a_bigbuf,
+ oct & 0x07);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (oct_len > 0)
+ {
+ SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+ proto_tree_add_text(tree, tvb, curr_offset, oct_len,
+ "FCH Information Content");
+
+ curr_offset += oct_len;
+
+ NO_MORE_DATA_CHECK(len);
+ }
+
+ oct_len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "DCCH Information: Bit-Exact Length Octet Count: %u",
+ oct_len);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : DCCH Information: Bit-Exact Length Fill Bits: %u",
+ a_bigbuf,
+ oct & 0x07);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (oct_len > 0)
+ {
+ SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+ proto_tree_add_text(tree, tvb, curr_offset, oct_len,
+ "DCCH Information Content");
+
+ curr_offset += oct_len;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.71
+ */
+static guint8
+elem_ptype(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 value;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ switch (value)
+ {
+ case 0x880b: str = "PPP"; break;
+ case 0x8881: str = "Unstructured Byte Stream"; break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "(%u) %s",
+ value,
+ str);
+
+ sprintf(add_string, " - (%s)", str);
+
+ curr_offset += 2;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.72
+ */
+static guint8
+elem_ms_info_recs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 oct_len;
+ guint8 rec_type;
+ guint8 num_recs;
+ guint32 value;
+ guint32 curr_offset;
+ gchar *str;
+ gint ett_elem_idx, idx, i;
+ proto_tree *subtree;
+ proto_item *item;
+
+ curr_offset = offset;
+
+ num_recs = 0;
+
+ while ((len - (curr_offset - offset)) >= 2)
+ {
+ num_recs++;
+
+ rec_type = tvb_get_guint8(tvb, curr_offset);
+
+ str = my_match_strval((guint32) rec_type, ansi_ms_info_rec_str, &idx);
+
+ if (str == NULL)
+ {
+ str = "Reserved";
+ ett_elem_idx = ett_ansi_ms_info_rec_reserved;
+ }
+ else
+ {
+ ett_elem_idx = ett_ansi_ms_info_rec[idx];
+ }
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Information Record Type - %u: (%u) %s",
+ num_recs,
+ rec_type,
+ str);
+
+ subtree = proto_item_add_subtree(item, ett_elem_idx);
+
+ curr_offset++;
+
+ oct_len = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_uint(subtree, hf_ansi_a_length, tvb,
+ curr_offset, 1, oct_len);
+
+ curr_offset++;
+
+ if (oct_len > 0)
+ {
+ SHORT_DATA_CHECK(len - (curr_offset - offset), oct_len);
+
+ switch (rec_type)
+ {
+ case ANSI_MS_INFO_REC_CLD_PN:
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch ((oct & 0xe0) >> 5)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "International number"; break;
+ case 2: str = "National number"; break;
+ case 3: str = "Network-specific number"; break;
+ case 4: str = "Subscriber number"; break;
+ case 5: str = "Reserved"; break;
+ case 6: str = "Abbreviated number"; break;
+ default:
+ str = "Reserved for extension";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : Number Type: %s",
+ a_bigbuf,
+ str);
+
+ switch ((oct & 0x1e) >> 1)
+ {
+ case 0x00: str = "Unknown"; break;
+ case 0x01: str = "ISDN/Telephony Numbering"; break;
+ case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break;
+ case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break;
+ case 0x09: str = "Private Numbering"; break;
+ case 0x0f: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1e, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : Number Plan: %s",
+ a_bigbuf,
+ str);
+
+ if (oct_len > 1)
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : MSB of first digit",
+ a_bigbuf);
+
+ curr_offset++;
+
+ for (i=0; i < (oct_len - 1); i++)
+ {
+ a_bigbuf[i] = (oct & 0x01) << 7;
+
+ oct = tvb_get_guint8(tvb, curr_offset + i);
+
+ a_bigbuf[i] |= (oct & 0xfe) >> 1;
+ }
+ a_bigbuf[i] = '\0';
+
+ proto_tree_add_text(subtree, tvb, curr_offset, oct_len - 1,
+ "Digits: %s",
+ a_bigbuf);
+
+ curr_offset += (oct_len - 2);
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ curr_offset++;
+ break;
+
+ case ANSI_MS_INFO_REC_CLG_PN:
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ oct = (value & 0xff00) >> 8;
+
+ switch ((oct & 0xe0) >> 5)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "International number"; break;
+ case 2: str = "National number"; break;
+ case 3: str = "Network-specific number"; break;
+ case 4: str = "Subscriber number"; break;
+ case 5: str = "Reserved"; break;
+ case 6: str = "Abbreviated number"; break;
+ default:
+ str = "Reserved for extension";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, value, 0xe000, 16);
+ proto_tree_add_text(subtree, tvb, curr_offset, 2,
+ "%s : Number Type: %s",
+ a_bigbuf,
+ str);
+
+ switch ((oct & 0x1e) >> 1)
+ {
+ case 0x00: str = "Unknown"; break;
+ case 0x01: str = "ISDN/Telephony Numbering"; break;
+ case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break;
+ case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break;
+ case 0x09: str = "Private Numbering"; break;
+ case 0x0f: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x1e00, 16);
+ proto_tree_add_text(subtree, tvb, curr_offset, 2,
+ "%s : Number Plan: %s",
+ a_bigbuf,
+ str);
+
+ switch ((value & 0x0180) >> 7)
+ {
+ case 0: str = "Presentation allowed"; break;
+ case 1: str = "Presentation restricted"; break;
+ case 2: str = "Number not available"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x0180, 16);
+ proto_tree_add_text(subtree, tvb, curr_offset, 2,
+ "%s : Presentation Indicator (PI): %s",
+ a_bigbuf,
+ str);
+
+ switch ((value & 0x0060) >> 5)
+ {
+ case 0: str = "User-provided, not screened"; break;
+ case 1: str = "User-provided, verified and passed"; break;
+ case 2: str = "User-provided, verified and failed"; break;
+ default:
+ str = "Network-provided";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x0060, 16);
+ proto_tree_add_text(subtree, tvb, curr_offset, 2,
+ "%s : Screening Indicator (SI): %s",
+ a_bigbuf,
+ str);
+
+ if (oct_len > 2)
+ {
+ oct = (value & 0x00ff);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+ proto_tree_add_text(subtree, tvb, curr_offset, 2,
+ "%s : MSB of first digit",
+ a_bigbuf);
+
+ curr_offset += 2;
+
+ for (i=0; i < (oct_len - 2); i++)
+ {
+ a_bigbuf[i] = (oct & 0x1f) << 3;
+
+ oct = tvb_get_guint8(tvb, curr_offset + i);
+
+ a_bigbuf[i] |= (oct & 0xe0) >> 5;
+ }
+ a_bigbuf[i] = '\0';
+
+ proto_tree_add_text(subtree, tvb, curr_offset, oct_len - 2,
+ "Digits: %s",
+ a_bigbuf);
+
+ curr_offset += (oct_len - 3);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ curr_offset++;
+ }
+ else
+ {
+ other_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+ proto_tree_add_text(subtree, tvb, curr_offset, 2,
+ "%s : Reserved",
+ a_bigbuf);
+
+ curr_offset += 2;
+ }
+ break;
+
+ case ANSI_MS_INFO_REC_MW:
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "Number of messages waiting: %u",
+ oct);
+
+ curr_offset++;
+ break;
+
+ default:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, oct_len,
+ "Record Content");
+
+ curr_offset += oct_len;
+ break;
+ }
+ }
+ }
+
+ sprintf(add_string, " - %u record%s",
+ num_recs, plurality(num_recs, "", "s"));
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.73
+ */
+static guint8
+elem_ext_ho_dir_params(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Search Window A Size (Srch_Win_A): %u",
+ a_bigbuf,
+ (oct & 0xf0) >> 4);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Search Window N Size (Srch_Win_N): %u",
+ a_bigbuf,
+ oct & 0x0f);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Search Window R Size (Srch_Win_R): %u",
+ a_bigbuf,
+ (oct & 0xf0) >> 4);
+
+ value = tvb_get_guint8(tvb, curr_offset + 1);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Add Pilot Threshold (T_Add) (MSB): %u",
+ a_bigbuf,
+ (oct & 0x0f) << 2 | (value & 0xc0) >> 6);
+
+ curr_offset++;
+
+ oct = value;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Add Pilot Threshold (T_Add) (LSB)",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Drop Pilot Threshold (T_Drop): %u",
+ a_bigbuf,
+ oct & 0x3f);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Compare Threshold (T_Comp): %u",
+ a_bigbuf,
+ (oct & 0xf0) >> 4);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Drop Timer Value (T_TDrop): %u",
+ a_bigbuf,
+ oct & 0x0f);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Neighbor Max Age (Nghbor_Max_AGE): %u",
+ a_bigbuf,
+ (oct & 0xf0) >> 4);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : SOFT_SLOPE: %u",
+ a_bigbuf,
+ oct & 0x3f);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : ADD_INTERCEPT: %u",
+ a_bigbuf,
+ oct & 0x3f);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : DROP_INTERCEPT: %u",
+ a_bigbuf,
+ oct & 0x3f);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Target BS P_REV: %u",
+ oct);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.74
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.75
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.76
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.77
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.78
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.79
+ */
+static guint8
+elem_cdma_sowd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ guint32 curr_offset;
+ gchar *str = NULL;
+
+ curr_offset = offset;
+
+ curr_offset += elem_cell_id(tvb, tree, offset, len, add_string);
+ add_string[0] = '\0';
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "CDMA Serving One Way Delay: %u",
+ value);
+
+ curr_offset += 2;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ switch (oct & 0x03)
+ {
+ case 0: str = "100 nsec"; break;
+ case 1: str = "50 nsec"; break;
+ case 2: str = "1/16 CDMA PN Chip"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Resolution: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.80
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.81
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.82
+ */
+static guint8
+elem_re_res(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Include Priority: MSC %s include priority in Assignment Request",
+ a_bigbuf,
+ (oct & 0x40) ? "should" : "does not need to");
+
+ switch ((oct & 0x30) >> 4)
+ {
+ case 0: str = "Not reported"; break;
+ case 1: str = "radio environment is acceptable"; break;
+ case 2: str = "radio environment is marginally acceptable"; break;
+ default:
+ str = "radio environment is poor";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Forward: %s",
+ a_bigbuf,
+ str);
+
+ switch ((oct & 0x0c) >> 2)
+ {
+ case 0: str = "Not reported"; break;
+ case 1: str = "radio environment is acceptable"; break;
+ case 2: str = "radio environment is marginally acceptable"; break;
+ default:
+ str = "radio environment is poor";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0c, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reverse: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Alloc: resources are %sallocated",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Avail: resources are %savailable",
+ a_bigbuf,
+ (oct & 0x01) ? "" : "not ");
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.83
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.84
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.85
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.86
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.87
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.88
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.89
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.90
+ * UNUSED in SPEC and no IEI!
+ */
+
+/*
+ * IOS 6.2.2.91
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.92
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.93
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.94
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.95
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.96
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.97
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.98
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.99
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.100
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.101
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.102
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.103
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.104
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.105
+ */
+static guint8
+elem_cld_party_ascii_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ guint8 *poctets;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "International number"; break;
+ case 2: str = "National number"; break;
+ case 3: str = "Network specific number"; break;
+ case 4: str = "Dedicated PAD access, short code"; break;
+ case 7: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Number: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x0f)
+ {
+ case 0x00: str = "Unknown"; break;
+ case 0x01: str = "ISDN/telephony number plan (ITU recommendation E.164/E.163)"; break;
+ case 0x03: str = "Data number plan (ITU recommendation X.121)"; break;
+ case 0x04: str = "Telex numbering plan (ITU recommendation F.69)"; break;
+ case 0x07: str = "Reserved for extension"; break;
+ case 0x08: str = "National numbering plan"; break;
+ case 0x09: str = "Private numbering plan"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Numbering Plan Identification: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+ proto_tree_add_string_format(tree, hf_ansi_a_cld_party_ascii_num,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Digits: %s",
+ poctets);
+
+ curr_offset += len - (curr_offset - offset);
+
+ sprintf(add_string, " - (%s)", poctets);
+ g_free(poctets);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.106
+ */
+static guint8
+elem_band_class(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gint temp_int;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xe0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ temp_int = oct & 0x1f;
+ if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = band_class_str[temp_int];
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Band Class: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%s)", str);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.107
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.108
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.109
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.110
+ */
+static guint8
+elem_is2000_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree, tvb, curr_offset, len, "IS-95/IS-2000 Cause Information");
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.111
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.112
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.113
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.114
+ */
+static guint8
+elem_auth_event(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ if (len == 1)
+ {
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0x01: str = "Event: Authentication parameters were NOT received from mobile"; break;
+ case 0x02: str = "Event: RANDC mis-match"; break;
+ default:
+ str = "Event";
+ break;
+ }
+
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ str);
+ }
+ else
+ {
+ proto_tree_add_text(tree, tvb, curr_offset, len, "Event");
+ }
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.115
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.116
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.117
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.118
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.119
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.120
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.121
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.122
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.123
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.124
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.125
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.126
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.127
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.128
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.129
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.130
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.131
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.132
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.133
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.134
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.135
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.136
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.137
+ * Generic decode is good enough
+ */
+
+/*
+ * IOS 6.2.2.138
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.139
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.140
+ * UNUSED
+ */
+
+/*
+ * IOS 6.2.2.141
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.142
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.143
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.144
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.145
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.146
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.147
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.148
+ */
+static guint8
+elem_cct_group(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : All Circuits",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Inclusive",
+ a_bigbuf);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Count: %u circuit%s",
+ oct, plurality(oct, "", "s"));
+
+ sprintf(add_string, " - %u circuit%s",
+ oct, plurality(oct, "", "s"));
+
+ curr_offset++;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0xffe0, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : PCM Multiplexer: %u",
+ a_bigbuf,
+ (value & 0xffe0) >> 5);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : Timeslot: %u",
+ a_bigbuf,
+ value & 0x001f);
+
+ curr_offset += 2;
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Circuit Bitmap");
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.149
+ */
+static guint8
+elem_paca_ts(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree, tvb, curr_offset, len, "PACA Queuing Time");
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.150
+ */
+static guint8
+elem_paca_order(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf8, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ switch (oct & 0x07)
+ {
+ case 0: str = "Reserved"; break;
+ case 1: str = "Update Queue Position and notify MS"; break;
+ case 2: str = "Remove MS from the queue and release MS"; break;
+ case 3: str = "Remove MS from the queue"; break;
+ case 4: str = "MS Requested PACA Cancel"; break;
+ case 5: str = "BS Requested PACA Cancel"; break;
+ default:
+ str = "All other values Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : PACA Action Required: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%s)", str);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.151
+ */
+static guint8
+elem_paca_reoi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfe, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : PACA Reorigination Indicator (PRI)",
+ a_bigbuf);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%sReorigination)", (oct & 0x01) ? "" : "Not ");
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * IOS 6.2.2.152
+ * A3/A7
+ */
+
+/*
+ * IOS 6.2.2.153
+ * A3/A7
+ */
+
+typedef enum
+{
+ ANSI_A_E_ACC_NET_ID, /* Access Network Identifiers */
+ ANSI_A_E_ADDS_USER_PART, /* ADDS User Part */
+ ANSI_A_E_AMPS_HHO_PARAM, /* AMPS Hard Handoff Parameters */
+ ANSI_A_E_ANCH_PDSN_ADDR, /* Anchor PDSN Address */
+ ANSI_A_E_ANCH_PP_ADDR, /* Anchor P-P Address */
+ ANSI_A_E_AUTH_CHLG_PARAM, /* Authentication Challenge Parameter */
+ ANSI_A_E_AUTH_CNF_PARAM, /* Authentication Confirmation Parameter (RANDC) */
+ ANSI_A_E_AUTH_DATA, /* Authentication Data */
+ ANSI_A_E_AUTH_EVENT, /* Authentication Event */
+ ANSI_A_E_AUTH_PARAM_COUNT, /* Authentication Parameter COUNT */
+ ANSI_A_E_AUTH_RESP_PARAM, /* Authentication Response Parameter */
+ ANSI_A_E_BAND_CLASS, /* Band Class */
+ ANSI_A_E_CLD_PARTY_ASCII_NUM, /* Called Party ASCII Number */
+ ANSI_A_E_CLD_PARTY_BCD_NUM, /* Called Party BCD Number */
+ ANSI_A_E_CLG_PARTY_ASCII_NUM, /* Calling Party ASCII Number */
+ ANSI_A_E_CAUSE, /* Cause */
+ ANSI_A_E_CAUSE_L3, /* Cause Layer 3 */
+ ANSI_A_E_CDMA_SOWD, /* CDMA Serving One Way Delay */
+ ANSI_A_E_CELL_ID, /* Cell Identifier */
+ ANSI_A_E_CELL_ID_LIST, /* Cell Identifier List */
+ ANSI_A_E_CHAN_NUM, /* Channel Number */
+ ANSI_A_E_CHAN_TYPE, /* Channel Type */
+ ANSI_A_E_CCT_GROUP, /* Circuit Group */
+ ANSI_A_E_CIC, /* Circuit Identity Code */
+ ANSI_A_E_CIC_EXT, /* Circuit Identity Code Extension */
+ ANSI_A_E_CM_INFO_TYPE_2, /* Classmark Information Type 2 */
+ ANSI_A_E_DOWNLINK_RE, /* Downlink Radio Environment */
+ ANSI_A_E_DOWNLINK_RE_LIST, /* Downlink Radio Environment List */
+ ANSI_A_E_ENC_INFO, /* Encryption Information */
+ ANSI_A_E_EXT_HO_DIR_PARAMS, /* Extended Handoff Direction Parameters */
+ ANSI_A_E_GEO_LOC, /* Geographic Location */
+ ANSI_A_E_SSCI, /* Special Service Call Indicator */
+ ANSI_A_E_HO_POW_LEV, /* Handoff Power Level */
+ ANSI_A_E_HHO_PARAMS, /* Hard Handoff Parameters */
+ ANSI_A_E_IE_REQD, /* Information Element Requested */
+ ANSI_A_E_IS2000_CHAN_ID, /* IS-2000 Channel Identity */
+ ANSI_A_E_IS2000_CHAN_ID_3X, /* IS-2000 Channel Identity 3X */
+ ANSI_A_E_IS2000_MOB_CAP, /* IS-2000 Mobile Capabilities */
+ ANSI_A_E_IS2000_NN_SCR, /* IS-2000 Non-Negotiable Service Configuration Record */
+ ANSI_A_E_IS2000_SCR, /* IS-2000 Service Configuration Record */
+ ANSI_A_E_IS2000_CAUSE, /* IS-95/IS-2000 Cause Value */
+ ANSI_A_E_IS2000_RED_RECORD, /* IS-2000 Redirection Record */
+ ANSI_A_E_IS95_CHAN_ID, /* IS-95 Channel Identity */
+ ANSI_A_E_IS95_MS_MEAS_CHAN_ID, /* IS-95 MS Measured Channel Identity */
+ ANSI_A_E_L3_INFO, /* Layer 3 Information */
+ ANSI_A_E_LAI, /* Location Area Information */
+ ANSI_A_E_MWI, /* Message Waiting Indication */
+ ANSI_A_E_MID, /* Mobile Identity */
+ ANSI_A_E_MS_INFO_RECS, /* MS Information Records */
+ ANSI_A_E_ORIG_CI, /* Origination Continuation Indicator */
+ ANSI_A_E_PACA_ORDER, /* PACA Order */
+ ANSI_A_E_PACA_REOI, /* PACA Reorigination Indicator */
+ ANSI_A_E_PACA_TS, /* PACA Timestamp */
+ ANSI_A_E_PSP, /* Packet Session Parameters */
+ ANSI_A_E_PDSN_IP_ADDR, /* PDSN IP Address */
+ ANSI_A_E_PDI, /* Power Down Indicator */
+ ANSI_A_E_PRIO, /* Priority */
+ ANSI_A_E_PREV, /* Protocol Revision */
+ ANSI_A_E_PTYPE, /* Protocol Type */
+ ANSI_A_E_PSMM_COUNT, /* PSMM Count */
+ ANSI_A_E_QOS_PARAMS, /* Quality of Service Parameters */
+ ANSI_A_E_RE_RES, /* Radio Environment and Resources */
+ ANSI_A_E_REG_TYPE, /* Registration Type */
+ ANSI_A_E_REJ_CAUSE, /* Reject Cause */
+ ANSI_A_E_RESP_REQ, /* Response Request */
+ ANSI_A_E_RET_CAUSE, /* Return Cause */
+ ANSI_A_E_RF_CHAN_ID, /* RF Channel Identity */
+ ANSI_A_E_SO, /* Service Option */
+ ANSI_A_E_SOCI, /* Service Option Connection Identifier (SOCI) */
+ ANSI_A_E_SO_LIST, /* Service Option List */
+ ANSI_A_E_S_RED_INFO, /* Service Redirection Info */
+ ANSI_A_E_SR_ID, /* Session Reference Identifier (SR_ID) */
+ ANSI_A_E_SID, /* SID */
+ ANSI_A_E_SIGNAL, /* Signal */
+ ANSI_A_E_SCI, /* Slot Cycle Index */
+ ANSI_A_E_SW_VER, /* Software Version */
+ ANSI_A_E_SRNC_TRNC_TC, /* Source RNC to Target RNC Transparent Container */
+ ANSI_A_E_S_PDSN_ADDR, /* Source PDSN Address */
+ ANSI_A_E_TAG, /* Tag */
+ ANSI_A_E_TRNC_SRNC_TC, /* Target RNC to Source RNC Transparent Container */
+ ANSI_A_E_XMODE, /* Transcoder Mode */
+ ANSI_A_E_UZ_ID, /* User Zone ID */
+ ANSI_A_E_VP_REQ, /* Voice Privacy Request */
+ ANSI_A_E_NONE /* NONE */
+}
+elem_idx_t;
+
+#define NUM_ELEM_1 (sizeof(ansi_a_ios401_elem_1_strings)/sizeof(value_string))
+static gint ett_ansi_elem_1[NUM_ELEM_1];
+static guint8 (*elem_1_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string) = {
+ NULL, /* Access Network Identifiers */
+ elem_adds_user_part, /* ADDS User Part */
+ NULL, /* AMPS Hard Handoff Parameters */
+ NULL, /* Anchor PDSN Address */
+ NULL, /* Anchor P-P Address */
+ elem_auth_chlg_param, /* Authentication Challenge Parameter */
+ NULL /* no decode required */, /* Authentication Confirmation Parameter (RANDC) */
+ NULL /* no decode required */, /* Authentication Data */
+ elem_auth_event, /* Authentication Event */
+ elem_auth_param_count, /* Authentication Parameter COUNT */
+ elem_auth_resp_param, /* Authentication Response Parameter */
+ elem_band_class, /* Band Class */
+ elem_cld_party_ascii_num, /* Called Party ASCII Number */
+ elem_cld_party_bcd_num, /* Called Party BCD Number */
+ elem_clg_party_ascii_num, /* Calling Party ASCII Number */
+ elem_cause, /* Cause */
+ elem_cause_l3, /* Cause Layer 3 */
+ elem_cdma_sowd, /* CDMA Serving One Way Delay */
+ elem_cell_id, /* Cell Identifier */
+ elem_cell_id_list, /* Cell Identifier List */
+ elem_chan_num, /* Channel Number */
+ elem_chan_type, /* Channel Type */
+ elem_cct_group, /* Circuit Group */
+ elem_cic, /* Circuit Identity Code */
+ elem_cic_ext, /* Circuit Identity Code Extension */
+ elem_cm_info_type_2, /* Classmark Information Type 2 */
+ elem_downlink_re, /* Downlink Radio Environment */
+ NULL, /* Downlink Radio Environment List */
+ elem_enc_info, /* Encryption Information */
+ elem_ext_ho_dir_params, /* Extended Handoff Direction Parameters */
+ NULL, /* Geographic Location */
+ NULL, /* Special Service Call Indicator */
+ elem_ho_pow_lev, /* Handoff Power Level */
+ elem_hho_params, /* Hard Handoff Parameters */
+ NULL, /* Information Element Requested */
+ elem_is2000_chan_id, /* IS-2000 Channel Identity */
+ NULL, /* IS-2000 Channel Identity 3X */
+ elem_is2000_mob_cap, /* IS-2000 Mobile Capabilities */
+ elem_is2000_nn_scr, /* IS-2000 Non-Negotiable Service Configuration Record */
+ elem_is2000_scr, /* IS-2000 Service Configuration Record */
+ elem_is2000_cause, /* IS-95/IS-2000 Cause Value */
+ NULL, /* IS-2000 Redirection Record */
+ elem_is95_chan_id, /* IS-95 Channel Identity */
+ elem_is95_ms_meas_chan_id, /* IS-95 MS Measured Channel Identity */
+ elem_l3_info, /* Layer 3 Information */
+ elem_lai, /* Location Area Information */
+ elem_mwi, /* Message Waiting Indication */
+ elem_mid, /* Mobile Identity */
+ elem_ms_info_recs, /* MS Information Records */
+ NULL, /* Origination Continuation Indicator */
+ elem_paca_order, /* PACA Order */
+ elem_paca_reoi, /* PACA Reorigination Indicator */
+ elem_paca_ts, /* PACA Timestamp */
+ NULL, /* Packet Session Parameters */
+ elem_pdsn_ip_addr, /* PDSN IP Address */
+ NULL /* no associated data */, /* Power Down Indicator */
+ elem_prio, /* Priority */
+ NULL, /* Protocol Revision */
+ elem_ptype, /* Protocol Type */
+ NULL, /* PSMM Count */
+ elem_qos_params, /* Quality of Service Parameters */
+ elem_re_res, /* Radio Environment and Resources */
+ elem_reg_type, /* Registration Type */
+ elem_rej_cause, /* Reject Cause */
+ NULL /* no associated data */, /* Response Request */
+ NULL, /* Return Cause */
+ elem_rf_chan_id, /* RF Channel Identity */
+ elem_so, /* Service Option */
+ NULL, /* Service Option Connection Identifier (SOCI) */
+ NULL, /* Service Option List */
+ NULL, /* Service Redirection Info */
+ NULL, /* Session Reference Identifier (SR_ID) */
+ elem_sid, /* SID */
+ elem_signal, /* Signal */
+ elem_sci, /* Slot Cycle Index */
+ elem_sw_ver, /* Software Version */
+ NULL, /* Source RNC to Target RNC Transparent Container */
+ NULL, /* Source PDSN Address */
+ elem_tag, /* Tag */
+ NULL, /* Target RNC to Source RNC Transparent Container */
+ elem_xmode, /* Transcoder Mode */
+ elem_uz_id, /* User Zone ID */
+ NULL /* no associated data */, /* Voice Privacy Request */
+ NULL, /* NONE */
+};
+
+/* MESSAGE FUNCTIONS */
+
+/*
+ * Type Length Value (TLV) element dissector
+ */
+static guint8
+elem_tlv(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset, guint len, gchar *name_add)
+{
+ guint8 oct, parm_len;
+ guint8 consumed;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+
+ len = len;
+ curr_offset = offset;
+ consumed = 0;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct == (guint8) ansi_a_ios401_elem_1_strings[idx].value)
+ {
+ parm_len = tvb_get_guint8(tvb, curr_offset + 1);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, parm_len + 2,
+ "%s%s",
+ ansi_a_ios401_elem_1_strings[idx].strptr,
+ (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+ subtree = proto_item_add_subtree(item, ett_ansi_elem_1[idx]);
+
+ proto_tree_add_uint(subtree, hf_ansi_a_elem_id, tvb,
+ curr_offset, 1, oct);
+
+ proto_tree_add_uint(subtree, hf_ansi_a_length, tvb,
+ curr_offset + 1, 1, parm_len);
+
+ if (parm_len > 0)
+ {
+ if (elem_1_fcn[idx] == NULL)
+ {
+ proto_tree_add_text(subtree,
+ tvb, curr_offset + 2, parm_len,
+ "Element Value");
+
+ consumed = parm_len;
+ }
+ else
+ {
+ a_add_string[0] = '\0';
+ consumed =
+ (*elem_1_fcn[idx])(tvb, subtree, curr_offset + 2,
+ parm_len, a_add_string);
+
+ if (a_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, a_add_string);
+ a_add_string[0] = '\0';
+ }
+ }
+ }
+
+ consumed += 2;
+ }
+
+ return(consumed);
+}
+
+/*
+ * Type Value (TV) element dissector
+ *
+ * Length cannot be used in these functions, big problem if a element dissector
+ * is not defined for these.
+ */
+static guint8
+elem_tv(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset, gchar *name_add)
+{
+ guint8 oct;
+ guint8 consumed;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+
+ curr_offset = offset;
+ consumed = 0;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct == (guint8) ansi_a_ios401_elem_1_strings[idx].value)
+ {
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, -1,
+ "%s%s",
+ ansi_a_ios401_elem_1_strings[idx].strptr,
+ (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+ subtree = proto_item_add_subtree(item, ett_ansi_elem_1[idx]);
+
+ proto_tree_add_uint(subtree, hf_ansi_a_elem_id, tvb, curr_offset, 1, oct);
+
+ if (elem_1_fcn[idx] == NULL)
+ {
+ /* BAD THING, CANNOT DETERMINE LENGTH */
+
+ proto_tree_add_text(subtree,
+ tvb, curr_offset + 1, 1,
+ "No element dissector, rest of dissection may be incorrect");
+
+ consumed = 1;
+ }
+ else
+ {
+ a_add_string[0] = '\0';
+ consumed = (*elem_1_fcn[idx])(tvb, subtree, curr_offset + 1, -1, a_add_string);
+
+ if (a_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, a_add_string);
+ a_add_string[0] = '\0';
+ }
+ }
+
+ consumed++;
+
+ proto_item_set_len(item, consumed);
+ }
+
+ return(consumed);
+}
+
+/*
+ * Type (T) element dissector
+ *
+ * Length cannot be used in these functions, big problem if a element dissector
+ * is not defined for these.
+ */
+static guint8
+elem_t(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset, gchar *name_add)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ guint8 consumed;
+
+ curr_offset = offset;
+ consumed = 0;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct == (guint8) ansi_a_ios401_elem_1_strings[idx].value)
+ {
+ proto_tree_add_uint_format(tree, hf_ansi_a_elem_id, tvb, curr_offset, 1, oct,
+ "%s%s",
+ ansi_a_ios401_elem_1_strings[idx].strptr,
+ (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+ consumed = 1;
+ }
+
+ return(consumed);
+}
+
+/*
+ * Length Value (LV) element dissector
+ */
+static guint8
+elem_lv(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset, guint len, gchar *name_add)
+{
+ guint8 parm_len;
+ guint8 consumed;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+
+ len = len;
+ curr_offset = offset;
+ consumed = 0;
+
+ parm_len = tvb_get_guint8(tvb, curr_offset);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, parm_len + 1,
+ "%s%s",
+ ansi_a_ios401_elem_1_strings[idx].strptr,
+ (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+ subtree = proto_item_add_subtree(item, ett_ansi_elem_1[idx]);
+
+ proto_tree_add_uint(subtree, hf_ansi_a_length, tvb,
+ curr_offset, 1, parm_len);
+
+ if (parm_len > 0)
+ {
+ if (elem_1_fcn[idx] == NULL)
+ {
+ proto_tree_add_text(subtree,
+ tvb, curr_offset + 1, parm_len,
+ "Element Value");
+
+ consumed = parm_len;
+ }
+ else
+ {
+ a_add_string[0] = '\0';
+ consumed =
+ (*elem_1_fcn[idx])(tvb, subtree, curr_offset + 1,
+ parm_len, a_add_string);
+
+ if (a_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, a_add_string);
+ a_add_string[0] = '\0';
+ }
+ }
+ }
+
+ return(consumed + 1);
+}
+
+/*
+ * Value (V) element dissector
+ *
+ * Length cannot be used in these functions, big problem if a element dissector
+ * is not defined for these.
+ */
+static guint8
+elem_v(tvbuff_t *tvb, proto_tree *tree, elem_idx_t idx, guint32 offset)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+
+ curr_offset = offset;
+ consumed = 0;
+
+ if (elem_1_fcn[idx] == NULL)
+ {
+ /* BAD THING, CANNOT DETERMINE LENGTH */
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "No element dissector, rest of dissection may be incorrect");
+
+ consumed = 1;
+ }
+ else
+ {
+ a_add_string[0] = '\0';
+ consumed = (*elem_1_fcn[idx])(tvb, tree, curr_offset, -1, a_add_string);
+ a_add_string[0] = '\0';
+ }
+
+ return(consumed);
+}
+
+
+#define ELEM_MAND_TLV(elem_idx, elem_name_addition) \
+{\
+ if ((consumed = elem_tlv(tvb, tree, elem_idx, curr_offset, curr_len, elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ else \
+ { \
+ proto_tree_add_text(tree, \
+ tvb, curr_offset, 0, \
+ "Missing Mandatory element (0x%02x) %s%s, rest of dissection is suspect", \
+ ansi_a_ios401_elem_1_strings[elem_idx].value, \
+ ansi_a_ios401_elem_1_strings[elem_idx].strptr, \
+ (elem_name_addition == NULL) || (elem_name_addition[0] == '\0') ? "" : elem_name_addition \
+ ); \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_TLV(elem_idx, elem_name_addition) \
+{\
+ if ((consumed = elem_tlv(tvb, tree, elem_idx, curr_offset, curr_len, elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_MAND_TV(elem_idx, elem_name_addition) \
+{\
+ if ((consumed = elem_tv(tvb, tree, elem_idx, curr_offset, elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ else \
+ { \
+ proto_tree_add_text(tree, \
+ tvb, curr_offset, 0, \
+ "Missing Mandatory element (0x%02x) %s%s, rest of dissection is suspect", \
+ ansi_a_ios401_elem_1_strings[elem_idx].value, \
+ ansi_a_ios401_elem_1_strings[elem_idx].strptr, \
+ (elem_name_addition == NULL) || (elem_name_addition[0] == '\0') ? "" : elem_name_addition \
+ ); \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_TV(elem_idx, elem_name_addition) \
+{\
+ if ((consumed = elem_tv(tvb, tree, elem_idx, curr_offset, elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_T(elem_idx, elem_name_addition) \
+{\
+ if ((consumed = elem_t(tvb, tree, elem_idx, curr_offset, elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_MAND_LV(elem_idx, elem_name_addition) \
+{\
+ if ((consumed = elem_lv(tvb, tree, elem_idx, curr_offset, curr_len, elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ else \
+ { \
+ /* Mandatory, but nothing we can do */ \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_MAND_V(elem_idx) \
+{\
+ if ((consumed = elem_v(tvb, tree, elem_idx, curr_offset)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ else \
+ { \
+ /* Mandatory, but nothing we can do */ \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+
+/*
+ * IOS 6.1.2.1
+ */
+static void
+bsmap_cl3_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CELL_ID, "");
+
+ ELEM_MAND_TLV(ANSI_A_E_L3_INFO, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.2
+ */
+static void
+dtap_cm_srvc_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+ guint8 oct;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ /*
+ * special dissection for CM Service Type
+ */
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct & 0x0f)
+ {
+ case 0x01: str = "Mobile Originating Call"; break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "CM Service Type: %s",
+ str);
+
+ subtree = proto_item_add_subtree(item, ett_cm_srvc_type);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Element ID",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Service Type: (%u) %s",
+ a_bigbuf,
+ oct & 0x0f,
+ str);
+
+ curr_offset++;
+ curr_len--;
+
+ ELEM_MAND_LV(ANSI_A_E_CM_INFO_TYPE_2, "");
+
+ ELEM_MAND_LV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CLD_PARTY_BCD_NUM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SCI, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_RESP_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_CNF_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_PARAM_COUNT, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_CHLG_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SO, "");
+
+ ELEM_OPT_T(ANSI_A_E_VP_REQ, "");
+
+ ELEM_OPT_TV(ANSI_A_E_RE_RES, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CLD_PARTY_ASCII_NUM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_CIC, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_EVENT, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_DATA, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PACA_REOI, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_UZ_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_MOB_CAP, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CDMA_SOWD, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.3
+ */
+static void
+bsmap_page_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CELL_ID_LIST, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SCI, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SO, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_MOB_CAP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.4
+ */
+static void
+dtap_page_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_LV(ANSI_A_E_CM_INFO_TYPE_2, "");
+
+ ELEM_MAND_LV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SCI, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_RESP_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_CNF_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_PARAM_COUNT, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_CHLG_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SO, "");
+
+ ELEM_OPT_T(ANSI_A_E_VP_REQ, "");
+
+ ELEM_OPT_TV(ANSI_A_E_CIC, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_EVENT, "");
+
+ ELEM_OPT_TV(ANSI_A_E_RE_RES, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_UZ_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_MOB_CAP, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CDMA_SOWD, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.12
+ */
+static void
+dtap_progress(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TV(ANSI_A_E_SIGNAL, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MS_INFO_RECS, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.15
+ */
+static void
+bsmap_ass_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CHAN_TYPE, "");
+
+ ELEM_OPT_TV(ANSI_A_E_CIC, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_ENC_INFO, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SO, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SIGNAL, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CLG_PARTY_ASCII_NUM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MS_INFO_RECS, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PRIO, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PACA_TS, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_QOS_PARAMS, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.16
+ */
+static void
+bsmap_ass_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TV(ANSI_A_E_CHAN_NUM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_ENC_INFO, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SO, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.17
+ */
+static void
+bsmap_ass_failure(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.20
+ */
+static void
+bsmap_clr_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CAUSE_L3, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.21
+ */
+static void
+bsmap_clr_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CAUSE_L3, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.22
+ */
+static void
+bsmap_clr_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_T(ANSI_A_E_PDI, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.24
+ */
+static void
+dtap_alert_with_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_MS_INFO_RECS, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.28
+ */
+static void
+bsmap_bs_srvc_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SO, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.2.29
+ */
+static void
+bsmap_bs_srvc_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.7
+ */
+static void
+dtap_flash_with_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_CLD_PARTY_BCD_NUM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SIGNAL, "");
+
+ ELEM_OPT_TV(ANSI_A_E_MWI, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CLG_PARTY_ASCII_NUM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MS_INFO_RECS, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.8
+ */
+static void
+dtap_flash_with_info_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.9
+ */
+static void
+bsmap_feat_noti(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CELL_ID_LIST, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SCI, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SIGNAL, "");
+
+ ELEM_OPT_TV(ANSI_A_E_MWI, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CLG_PARTY_ASCII_NUM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MS_INFO_RECS, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_MOB_CAP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.10
+ */
+static void
+bsmap_feat_noti_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.11
+ */
+static void
+bsmap_paca_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_PRIO, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PACA_TS, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.12
+ */
+static void
+bsmap_paca_command_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.13
+ */
+static void
+bsmap_paca_update(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PACA_ORDER, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PRIO, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_RESP_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_CNF_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_PARAM_COUNT, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_CHLG_PARAM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_EVENT, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.3.14
+ */
+static void
+bsmap_paca_update_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PRIO, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.1
+ */
+static void
+bsmap_auth_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_AUTH_CHLG_PARAM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CELL_ID_LIST, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SCI, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+static void
+dtap_auth_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_LV(ANSI_A_E_AUTH_CHLG_PARAM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_MOB_CAP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.2
+ */
+static void
+bsmap_auth_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_AUTH_RESP_PARAM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+static void
+dtap_auth_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_LV(ANSI_A_E_AUTH_RESP_PARAM, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.3
+ */
+static void
+bsmap_user_zone_update(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_UZ_ID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.4
+ */
+static void
+dtap_ssd_update_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_LV(ANSI_A_E_AUTH_CHLG_PARAM, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.5
+ */
+static void
+dtap_bs_challenge(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_LV(ANSI_A_E_AUTH_CHLG_PARAM, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.6
+ */
+static void
+dtap_bs_challenge_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_LV(ANSI_A_E_AUTH_RESP_PARAM, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.7
+ */
+static void
+dtap_ssd_update_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_CAUSE_L3, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.8
+ */
+static void
+dtap_lu_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_LV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_LAI, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CM_INFO_TYPE_2, "");
+
+ ELEM_OPT_TV(ANSI_A_E_REG_TYPE, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SCI, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_RESP_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_CNF_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_PARAM_COUNT, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_CHLG_PARAM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_EVENT, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_UZ_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_MOB_CAP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.9
+ */
+static void
+dtap_lu_accept(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TV(ANSI_A_E_LAI, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.10
+ */
+static void
+dtap_lu_reject(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_V(ANSI_A_E_REJ_CAUSE);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.18
+ */
+static void
+bsmap_priv_mode_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_ENC_INFO, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.4.19
+ */
+static void
+bsmap_priv_mode_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_ENC_INFO, "");
+
+ ELEM_OPT_T(ANSI_A_E_VP_REQ, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.4
+ */
+static void
+bsmap_ho_reqd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ ELEM_MAND_TLV(ANSI_A_E_CELL_ID_LIST, " (Target)");
+
+ ELEM_OPT_TLV(ANSI_A_E_CM_INFO_TYPE_2, "");
+
+ ELEM_OPT_T(ANSI_A_E_RESP_REQ, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_ENC_INFO, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS95_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_DOWNLINK_RE, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SO, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CDMA_SOWD, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS95_MS_MEAS_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_QOS_PARAMS, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_MOB_CAP, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_SCR, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PDSN_IP_ADDR, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PTYPE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.5
+ */
+static void
+bsmap_ho_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CHAN_TYPE, "");
+
+ ELEM_MAND_TLV(ANSI_A_E_ENC_INFO, "");
+
+ ELEM_MAND_TLV(ANSI_A_E_CM_INFO_TYPE_2, "");
+
+ ELEM_MAND_TLV(ANSI_A_E_CELL_ID_LIST, "(Target)");
+
+ ELEM_OPT_TLV(ANSI_A_E_CIC_EXT, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS95_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_DOWNLINK_RE, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SO, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CDMA_SOWD, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS95_MS_MEAS_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_QOS_PARAMS, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_MOB_CAP, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_SCR, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PDSN_IP_ADDR, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_PTYPE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.6
+ */
+static void
+bsmap_ho_req_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_IS95_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CELL_ID_LIST, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_EXT_HO_DIR_PARAMS, "");
+
+ ELEM_OPT_TV(ANSI_A_E_HHO_PARAMS, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_SCR, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_NN_SCR, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.7
+ */
+static void
+bsmap_ho_failure(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.8
+ */
+static void
+bsmap_ho_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TV(ANSI_A_E_RF_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS95_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CELL_ID_LIST, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_HO_POW_LEV, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_EXT_HO_DIR_PARAMS, "");
+
+ ELEM_OPT_TV(ANSI_A_E_HHO_PARAMS, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_CHAN_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_SCR, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_NN_SCR, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.9
+ */
+static void
+bsmap_ho_reqd_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.5.12
+ */
+static void
+bsmap_ho_performed(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CELL_ID_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.2
+ */
+static void
+bsmap_block(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TV(ANSI_A_E_CIC, "");
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CCT_GROUP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.3
+ */
+static void
+bsmap_block_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TV(ANSI_A_E_CIC, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.4
+ */
+static void
+bsmap_unblock(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TV(ANSI_A_E_CIC, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CCT_GROUP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.5
+ */
+static void
+bsmap_unblock_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TV(ANSI_A_E_CIC, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.6
+ */
+static void
+bsmap_reset(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_SW_VER, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.7
+ */
+static void
+bsmap_reset_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_SW_VER, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.8
+ */
+static void
+bsmap_reset_cct(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TV(ANSI_A_E_CIC, "");
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CCT_GROUP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.9
+ */
+static void
+bsmap_reset_cct_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TV(ANSI_A_E_CIC, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.10
+ */
+static void
+bsmap_xmode_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_XMODE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.6.11
+ */
+static void
+bsmap_xmode_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.1
+ */
+static void
+bsmap_adds_page(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_MID, "");
+
+ ELEM_MAND_TLV(ANSI_A_E_ADDS_USER_PART, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CELL_ID_LIST, "");
+
+ ELEM_OPT_TV(ANSI_A_E_SCI, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_MOB_CAP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.2
+ */
+static void
+bsmap_adds_transfer(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_MID, "");
+
+ ELEM_MAND_TLV(ANSI_A_E_ADDS_USER_PART, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_RESP_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_CNF_PARAM, "");
+
+ ELEM_OPT_TV(ANSI_A_E_AUTH_PARAM_COUNT, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_CHLG_PARAM, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_AUTH_EVENT, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CELL_ID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CDMA_SOWD, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.3
+ */
+static void
+dtap_adds_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_LV(ANSI_A_E_ADDS_USER_PART, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CDMA_SOWD, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.4
+ */
+static void
+bsmap_adds_page_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_MAND_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CAUSE, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CELL_ID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.7.5
+ */
+static void
+dtap_adds_deliver_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TV(ANSI_A_E_TAG, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * IOS 6.1.8.1
+ */
+static void
+bsmap_rejection(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_MID, "");
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+static void
+dtap_rejection(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ ELEM_OPT_TLV(ANSI_A_E_IS2000_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+#define ANSI_A_IOS401_BSMAP_NUM_MSG (sizeof(ansi_a_ios401_bsmap_strings)/sizeof(value_string))
+static gint ett_bsmap_msg[ANSI_A_IOS401_BSMAP_NUM_MSG];
+static void (*bsmap_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ NULL, /* Additional Service Notification */
+ bsmap_adds_page, /* ADDS Page */
+ bsmap_adds_page_ack, /* ADDS Page Ack */
+ bsmap_adds_transfer, /* ADDS Transfer */
+ NULL, /* ADDS Transfer Ack */
+ bsmap_ass_complete, /* Assignment Complete */
+ bsmap_ass_failure, /* Assignment Failure */
+ bsmap_ass_req, /* Assignment Request */
+ bsmap_auth_req, /* Authentication Request */
+ bsmap_auth_resp, /* Authentication Response */
+ NULL, /* Base Station Challenge */
+ NULL, /* Base Station Challenge Response */
+ bsmap_block, /* Block */
+ bsmap_block_ack, /* Block Acknowledge */
+ bsmap_bs_srvc_req, /* BS Service Request */
+ bsmap_bs_srvc_resp, /* BS Service Response */
+ bsmap_clr_command, /* Clear Command */
+ bsmap_clr_complete, /* Clear Complete */
+ bsmap_clr_req, /* Clear Request */
+ bsmap_cl3_info, /* Complete Layer 3 Information */
+ bsmap_feat_noti, /* Feature Notification */
+ bsmap_feat_noti_ack, /* Feature Notification Ack */
+ bsmap_ho_command, /* Handoff Command */
+ NULL /* no associated data */, /* Handoff Commenced */
+ NULL /* no associated data */, /* Handoff Complete */
+ bsmap_ho_failure, /* Handoff Failure */
+ bsmap_ho_performed, /* Handoff Performed */
+ bsmap_ho_req, /* Handoff Request */
+ bsmap_ho_req_ack, /* Handoff Request Acknowledge */
+ bsmap_ho_reqd, /* Handoff Required */
+ bsmap_ho_reqd_rej, /* Handoff Required Reject */
+ bsmap_paca_command, /* PACA Command */
+ bsmap_paca_command_ack, /* PACA Command Ack */
+ bsmap_paca_update, /* PACA Update */
+ bsmap_paca_update_ack, /* PACA Update Ack */
+ bsmap_page_req, /* Paging Request */
+ bsmap_priv_mode_command, /* Privacy Mode Command */
+ bsmap_priv_mode_complete, /* Privacy Mode Complete */
+ NULL, /* Radio Measurements for Position Request */
+ NULL, /* Radio Measurements for Position Response */
+ bsmap_rejection, /* Rejection */
+ NULL, /* Registration Request */
+ bsmap_reset, /* Reset */
+ bsmap_reset_ack, /* Reset Acknowledge */
+ bsmap_reset_cct, /* Reset Circuit */
+ bsmap_reset_cct_ack, /* Reset Circuit Acknowledge */
+ NULL, /* SSD Update Request */
+ NULL, /* SSD Update Response */
+ NULL, /* Status Request */
+ NULL, /* Status Response */
+ bsmap_xmode_ack, /* Transcoder Control Acknowledge */
+ bsmap_xmode_req, /* Transcoder Control Request */
+ bsmap_unblock, /* Unblock */
+ bsmap_unblock_ack, /* Unblock Acknowledge */
+ NULL, /* User Zone Reject */
+ bsmap_user_zone_update, /* User Zone Update */
+ NULL, /* NONE */
+};
+
+#define ANSI_A_IOS401_DTAP_NUM_MSG (sizeof(ansi_a_ios401_dtap_strings)/sizeof(value_string))
+static gint ett_dtap_msg[ANSI_A_IOS401_DTAP_NUM_MSG];
+static void (*dtap_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ NULL, /* Additional Service Request */
+ dtap_adds_deliver, /* ADDS Deliver */
+ dtap_adds_deliver_ack, /* ADDS Deliver Ack */
+ dtap_alert_with_info, /* Alert With Information */
+ dtap_auth_req, /* Authentication Request */
+ dtap_auth_resp, /* Authentication Response */
+ dtap_bs_challenge, /* Base Station Challenge */
+ dtap_bs_challenge_resp, /* Base Station Challenge Response */
+ dtap_cm_srvc_req, /* CM Service Request */
+ NULL, /* CM Service Request Continuation */
+ NULL /* no associated data */, /* Connect */
+ dtap_flash_with_info, /* Flash with Information */
+ dtap_flash_with_info_ack, /* Flash with Information Ack */
+ dtap_lu_accept, /* Location Updating Accept */
+ dtap_lu_reject, /* Location Updating Reject */
+ dtap_lu_req, /* Location Updating Request */
+ dtap_page_resp, /* Paging Response */
+ NULL /* no associated data */, /* Parameter Update Confirm */
+ NULL /* no associated data */, /* Parameter Update Request */
+ dtap_rejection, /* Rejection */
+ dtap_progress, /* Progress */
+ NULL, /* Service Redirection */
+ NULL, /* Service Release */
+ NULL, /* Service Release Complete */
+ dtap_ssd_update_req, /* SSD Update Request */
+ dtap_ssd_update_resp, /* SSD Update Response */
+ NULL, /* Status Request */
+ NULL, /* Status Response */
+ NULL, /* User Zone Reject */
+ NULL, /* User Zone Update */
+ NULL, /* User Zone Update Request */
+ NULL, /* NONE */
+};
+
+/* GENERIC MAP DISSECTOR FUNCTIONS */
+
+static void
+dissect_bsmap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ static ansi_a_tap_rec_t tap_rec[4];
+ static ansi_a_tap_rec_t *tap_p;
+ static int tap_current=0;
+ guint8 oct;
+ guint32 offset, saved_offset;
+ guint32 len;
+ gint idx;
+ proto_item *bsmap_item = NULL;
+ proto_tree *bsmap_tree = NULL;
+ gchar *msg_str;
+
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, "(BSMAP) ");
+ }
+
+ /*
+ * set tap record pointer
+ */
+ tap_current++;
+ if (tap_current == 4)
+ {
+ tap_current = 0;
+ }
+ tap_p = &tap_rec[tap_current];
+
+
+ offset = 0;
+ saved_offset = offset;
+
+ g_pinfo = pinfo;
+ g_tree = tree;
+
+ len = tvb_length(tvb);
+
+ /*
+ * add BSMAP message name
+ */
+ oct = tvb_get_guint8(tvb, offset++);
+
+ msg_str = my_match_strval((guint32) oct, ansi_a_ios401_bsmap_strings, &idx);
+
+ /*
+ * create the a protocol tree
+ */
+ if (msg_str == NULL)
+ {
+ bsmap_item =
+ proto_tree_add_protocol_format(tree, proto_a_bsmap, tvb, 0, len,
+ "ANSI A-I/F BSMAP - Unknown BSMAP Message Type (%u)",
+ oct);
+
+ bsmap_tree = proto_item_add_subtree(bsmap_item, ett_bsmap);
+ }
+ else
+ {
+ bsmap_item =
+ proto_tree_add_protocol_format(tree, proto_a_bsmap, tvb, 0, -1,
+ "ANSI A-I/F BSMAP - %s",
+ msg_str);
+
+ bsmap_tree = proto_item_add_subtree(bsmap_item, ett_bsmap_msg[idx]);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", msg_str);
+ }
+ }
+
+ /*
+ * add BSMAP message name
+ */
+ proto_tree_add_uint_format(bsmap_tree, hf_ansi_a_bsmap_msgtype,
+ tvb, saved_offset, 1, oct, "Message Type");
+
+ tap_p->pdu_type = BSSAP_PDU_TYPE_BSMAP;
+ tap_p->message_type = oct;
+
+ tap_queue_packet(ansi_a_tap, pinfo, tap_p);
+
+ if (msg_str == NULL) return;
+
+ if ((len - offset) <= 0) return;
+
+ /*
+ * decode elements
+ */
+ if (bsmap_msg_fcn[idx] == NULL)
+ {
+ proto_tree_add_text(bsmap_tree,
+ tvb, offset, len - offset,
+ "Message Elements");
+ }
+ else
+ {
+ (*bsmap_msg_fcn[idx])(tvb, bsmap_tree, offset, len - offset);
+ }
+}
+
+static void
+dissect_dtap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ static ansi_a_tap_rec_t tap_rec[4];
+ static ansi_a_tap_rec_t *tap_p;
+ static int tap_current=0;
+ guint8 oct;
+ guint32 offset, saved_offset;
+ guint32 len;
+ guint32 oct_1, oct_2;
+ gint idx;
+ proto_item *dtap_item = NULL;
+ proto_tree *dtap_tree = NULL;
+ proto_item *oct_1_item = NULL;
+ proto_tree *oct_1_tree = NULL;
+ gchar *msg_str;
+ gchar *str;
+
+
+ len = tvb_length(tvb);
+
+ if (len < 3)
+ {
+ /*
+ * too short to be DTAP
+ */
+ call_dissector(data_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, "(DTAP) ");
+ }
+
+ /*
+ * set tap record pointer
+ */
+ tap_current++;
+ if (tap_current == 4)
+ {
+ tap_current = 0;
+ }
+ tap_p = &tap_rec[tap_current];
+
+
+ offset = 0;
+ saved_offset = offset;
+
+ g_pinfo = pinfo;
+ g_tree = tree;
+
+ /*
+ * get protocol discriminator
+ */
+ oct_1 = tvb_get_guint8(tvb, offset++);
+ oct_2 = tvb_get_guint8(tvb, offset++);
+
+ /*
+ * add DTAP message name
+ */
+ saved_offset = offset;
+ oct = tvb_get_guint8(tvb, offset++);
+
+ msg_str = my_match_strval((guint32) oct, ansi_a_ios401_dtap_strings, &idx);
+
+ /*
+ * create the a protocol tree
+ */
+ if (msg_str == NULL)
+ {
+ dtap_item =
+ proto_tree_add_protocol_format(tree, proto_a_dtap, tvb, 0, len,
+ "ANSI A-I/F DTAP - Unknown DTAP Message Type (%u)",
+ oct);
+
+ dtap_tree = proto_item_add_subtree(dtap_item, ett_dtap);
+ }
+ else
+ {
+ dtap_item =
+ proto_tree_add_protocol_format(tree, proto_a_dtap, tvb, 0, -1,
+ "ANSI A-I/F DTAP - %s",
+ msg_str);
+
+ dtap_tree = proto_item_add_subtree(dtap_item, ett_dtap_msg[idx]);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", msg_str);
+ }
+ }
+
+ /*
+ * octet 1
+ */
+ switch (oct_1 & 0x0f)
+ {
+ case 3: str = "Call Control, call related SS"; break;
+ case 5: str = "Mobility Management"; break;
+ case 6: str = "Radio Resource Management"; break;
+ case 9: str = "Facility Management"; break;
+ case 11: str = "Other Signaling Procedures"; break;
+ case 15: str = "Reserved for tests"; break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ oct_1_item =
+ proto_tree_add_text(dtap_tree,
+ tvb, 0, 1,
+ "Protocol Discriminator: %s",
+ str);
+
+ oct_1_tree = proto_item_add_subtree(oct_1_item, ett_dtap_oct_1);
+
+ other_decode_bitfield_value(a_bigbuf, oct_1, 0xf0, 8);
+ proto_tree_add_text(oct_1_tree,
+ tvb, 0, 1,
+ "%s : Reserved",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct_1, 0x0f, 8);
+ proto_tree_add_text(oct_1_tree,
+ tvb, 0, 1,
+ "%s : Protocol Discriminator: %u",
+ a_bigbuf,
+ oct_1 & 0x0f);
+
+ /*
+ * octet 2
+ */
+ switch (a_variant)
+ {
+ case A_VARIANT_IS634:
+ other_decode_bitfield_value(a_bigbuf, oct_2, 0x80, 8);
+ proto_tree_add_text(dtap_tree,
+ tvb, 1, 1,
+ "%s : Transaction Identifier (TI) Flag: %s",
+ a_bigbuf,
+ ((oct_2 & 0x80) ? "allocated by receiver" : "allocated by sender"));
+
+ other_decode_bitfield_value(a_bigbuf, oct_2, 0x70, 8);
+ proto_tree_add_text(dtap_tree,
+ tvb, 1, 1,
+ "%s : Transaction Identifier (TI): %u",
+ a_bigbuf,
+ (oct_2 & 0x70) >> 4);
+
+ other_decode_bitfield_value(a_bigbuf, oct_2, 0x0f, 8);
+ proto_tree_add_text(dtap_tree,
+ tvb, 1, 1,
+ "%s : Reserved",
+ a_bigbuf);
+ break;
+
+ default:
+ proto_tree_add_text(dtap_tree,
+ tvb, 1, 1,
+ "Reserved Octet");
+ break;
+ }
+
+ /*
+ * add DTAP message name
+ */
+ proto_tree_add_uint_format(dtap_tree, hf_ansi_a_dtap_msgtype,
+ tvb, saved_offset, 1, oct,
+ "Message Type");
+
+ tap_p->pdu_type = BSSAP_PDU_TYPE_DTAP;
+ tap_p->message_type = oct;
+
+ tap_queue_packet(ansi_a_tap, pinfo, tap_p);
+
+ if (msg_str == NULL) return;
+
+ if ((len - offset) <= 0) return;
+
+ /*
+ * decode elements
+ */
+ if (dtap_msg_fcn[idx] == NULL)
+ {
+ proto_tree_add_text(dtap_tree,
+ tvb, offset, len - offset,
+ "Message Elements");
+ }
+ else
+ {
+ (*dtap_msg_fcn[idx])(tvb, dtap_tree, offset, len - offset);
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_ansi_a(void)
+{
+ module_t *ansi_a_module;
+ guint i;
+ gint last_offset;
+
+ /* Setup list of header fields */
+
+ static hf_register_info hf[] =
+ {
+ { &hf_ansi_a_bsmap_msgtype,
+ { "BSMAP Message Type", "ansi_a.bsmap_msgtype",
+ FT_UINT8, BASE_HEX, VALS(ansi_a_ios401_bsmap_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_dtap_msgtype,
+ { "DTAP Message Type", "ansi_a.dtap_msgtype",
+ FT_UINT8, BASE_HEX, VALS(ansi_a_ios401_dtap_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_elem_id,
+ { "Element ID", "ansi_a.elem_id",
+ FT_UINT8, BASE_DEC, VALS(ansi_a_ios401_elem_1_strings), 0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_length,
+ { "Length", "ansi_a.len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_none,
+ { "Sub tree", "ansi_a.none",
+ FT_NONE, 0, 0, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_esn,
+ { "ESN", "ansi_a.esn",
+ FT_UINT32, BASE_HEX, 0, 0x0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_imsi,
+ { "IMSI", "ansi_a.imsi",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_min,
+ { "MIN", "ansi_a.min",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_cld_party_bcd_num,
+ { "Called Party BCD Number", "ansi_a.cld_party_bcd_num",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_clg_party_bcd_num,
+ { "Calling Party BCD Number", "ansi_a.clg_party_bcd_num",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_cld_party_ascii_num,
+ { "Called Party ASCII Number", "ansi_a.cld_party_ascii_num",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_clg_party_ascii_num,
+ { "Calling Party ASCII Number", "ansi_a.clg_party_ascii_num",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_cell_ci,
+ { "Cell CI", "ansi_a.cell_ci",
+ FT_UINT16, BASE_HEX, 0, 0x0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_cell_lac,
+ { "Cell LAC", "ansi_a.cell_lac",
+ FT_UINT16, BASE_HEX, 0, 0x0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_cell_mscid,
+ { "Cell MSCID", "ansi_a.cell_mscid",
+ FT_UINT24, BASE_HEX, 0, 0x0,
+ "", HFILL }
+ },
+ { &hf_ansi_a_pdsn_ip_addr,
+ { "PDSN IP Address", "ansi_a.pdsn_ip_addr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "IP Address", HFILL}},
+ };
+
+ static enum_val_t a_variant_options[] = {
+ { "is-634-rev0", "IS-634 rev. 0", A_VARIANT_IS634 },
+ { "tsb-80", "TSB-80", A_VARIANT_TSB80 },
+ { "is-634-a", "IS-634-A", A_VARIANT_IS634A },
+ { "ios-2.x", "IOS 2.x", A_VARIANT_IOS2 },
+ { "ios-3.x", "IOS 3.x", A_VARIANT_IOS3 },
+ { "ios-4.0.1", "IOS 4.0.1", A_VARIANT_IOS401 },
+ { NULL, NULL, 0 }
+
+ };
+
+ /* Setup protocol subtree array */
+#define MAX_NUM_DTAP_MSG ANSI_A_MAX(ANSI_A_IOS401_DTAP_NUM_MSG, 0)
+#define MAX_NUM_BSMAP_MSG ANSI_A_MAX(ANSI_A_IOS401_BSMAP_NUM_MSG, 0)
+#define NUM_INDIVIDUAL_ELEMS 9
+ gint **ett;
+ gint ett_len = (NUM_INDIVIDUAL_ELEMS+MAX_NUM_DTAP_MSG+MAX_NUM_BSMAP_MSG+NUM_ELEM_1+NUM_MS_INFO_REC) * sizeof(gint *);
+
+ /*
+ * XXX - at least one version of the HP C compiler apparently doesn't
+ * recognize constant expressions using the "?" operator as being
+ * constant expressions, so you can't use the expression that
+ * initializes "ett_let" as an array size. Therefore, we dynamically
+ * allocate the array instead.
+ */
+ ett = g_malloc(ett_len);
+
+ memset((void *) ett_dtap_msg, -1, sizeof(gint) * MAX_NUM_DTAP_MSG);
+ memset((void *) ett_bsmap_msg, -1, sizeof(gint) * MAX_NUM_BSMAP_MSG);
+ memset((void *) ett_ansi_elem_1, -1, sizeof(gint) * NUM_ELEM_1);
+ memset((void *) ett_ansi_ms_info_rec, -1, sizeof(gint) * NUM_MS_INFO_REC);
+
+ ett[0] = &ett_bsmap;
+ ett[1] = &ett_dtap;
+ ett[2] = &ett_elems;
+ ett[3] = &ett_elem;
+ ett[4] = &ett_dtap_oct_1;
+ ett[5] = &ett_cm_srvc_type;
+ ett[6] = &ett_ansi_ms_info_rec_reserved;
+ ett[7] = &ett_ansi_enc_info;
+ ett[8] = &ett_cell_list;
+
+ last_offset = NUM_INDIVIDUAL_ELEMS;
+
+ for (i=0; i < MAX_NUM_DTAP_MSG; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_dtap_msg[i];
+ }
+
+ for (i=0; i < MAX_NUM_BSMAP_MSG; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_bsmap_msg[i];
+ }
+
+ for (i=0; i < NUM_ELEM_1; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_ansi_elem_1[i];
+ }
+
+ for (i=0; i < NUM_MS_INFO_REC; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_ansi_ms_info_rec[i];
+ }
+
+ /* Register the protocol name and description */
+
+ proto_a_bsmap =
+ proto_register_protocol("ANSI A-I/F BSMAP", "ANSI BSMAP", "ansi_a_bsmap");
+
+ proto_register_field_array(proto_a_bsmap, hf, array_length(hf));
+
+ proto_a_dtap =
+ proto_register_protocol("ANSI A-I/F DTAP", "ANSI DTAP", "ansi_a_dtap");
+
+ is637_dissector_table =
+ register_dissector_table("ansi_a.sms", "IS-637-A (SMS)",
+ FT_UINT8, BASE_DEC);
+
+ is683_dissector_table =
+ register_dissector_table("ansi_a.ota", "IS-683-A (OTA)",
+ FT_UINT8, BASE_DEC);
+
+ is801_dissector_table =
+ register_dissector_table("ansi_a.pld", "IS-801 (PLD)",
+ FT_UINT8, BASE_DEC);
+
+ proto_register_subtree_array(ett, ett_len / sizeof(gint *));
+
+ ansi_a_tap = register_tap("ansi_a");
+
+ /*
+ * setup for preferences
+ */
+ ansi_a_module = prefs_register_protocol(proto_a_bsmap, proto_reg_handoff_ansi_a);
+
+ prefs_register_enum_preference(ansi_a_module,
+ "global_variant",
+ "Dissect PDU as",
+ "(if other than the default of IOS 4.0.1)",
+ &a_global_variant,
+ a_variant_options,
+ FALSE);
+
+ g_free(ett);
+}
+
+
+void
+proto_reg_handoff_ansi_a(void)
+{
+ static int ansi_a_prefs_initialized = FALSE;
+
+
+ if (!ansi_a_prefs_initialized)
+ {
+ bsmap_handle = create_dissector_handle(dissect_bsmap, proto_a_bsmap);
+ dtap_handle = create_dissector_handle(dissect_dtap, proto_a_dtap);
+
+ ansi_a_prefs_initialized = TRUE;
+ }
+ else
+ {
+ dissector_delete("bsap.pdu_type", BSSAP_PDU_TYPE_BSMAP, bsmap_handle);
+ dissector_delete("bsap.pdu_type", BSSAP_PDU_TYPE_DTAP, dtap_handle);
+ }
+
+ if (a_variant != a_global_variant)
+ {
+ a_variant = a_global_variant;
+ }
+
+ dissector_add("bsap.pdu_type", BSSAP_PDU_TYPE_BSMAP, bsmap_handle);
+ dissector_add("bsap.pdu_type", BSSAP_PDU_TYPE_DTAP, dtap_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ansi_a.h b/epan/dissectors/packet-ansi_a.h
new file mode 100644
index 0000000000..9c49486aff
--- /dev/null
+++ b/epan/dissectors/packet-ansi_a.h
@@ -0,0 +1,57 @@
+/* packet-ansi_a.h
+ *
+ * $Id$
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>,
+ * In association with Telos Technology Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+typedef struct _ansi_a_tap_rec_t {
+ /*
+ * value from packet-bssap.h
+ */
+ guint8 pdu_type;
+ guint8 message_type;
+} ansi_a_tap_rec_t;
+
+
+/*
+ * the following allows TAP code access to the messages
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string ansi_a_ios401_bsmap_strings[];
+ETH_VAR_IMPORT const value_string ansi_a_ios401_dtap_strings[];
+
+/*
+ * allows ANSI MAP to use this for IS-880 enhancements
+ */
+extern const value_string ansi_a_ios401_elem_1_strings[];
+
+/*
+ * maximum number of strings that are allowed
+ * 255 because IEI are 1 octet in length
+ *
+ * this define is required by dissectors that need to
+ * size based on the 'ansi_a_ios401_elem_1_strings'
+ * array
+ */
+#define ANSI_A_MAX_NUM_IOS401_ELEM_1_STRINGS 255
diff --git a/epan/dissectors/packet-ansi_map.c b/epan/dissectors/packet-ansi_map.c
new file mode 100644
index 0000000000..3cc58ede94
--- /dev/null
+++ b/epan/dissectors/packet-ansi_map.c
@@ -0,0 +1,13242 @@
+/* packet-ansi_map.c
+ * Routines for ANSI 41 Mobile Application Part (IS41 MAP) dissection
+ * Specications from 3GPP2 (www.3gpp2.org)
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * Should be very close to what ANSI/TIA/EIA-41-E will be as most known
+ * changes have been added: i.e. IS-778, IS-751, IS-725, IS-841, ...
+ *
+ * Title 3GPP2 Other
+ *
+ * Cellular Radiotelecommunications Intersystem Operations
+ * 3GPP2 N.S0005-0 ANSI/TIA/EIA-41-D
+ *
+ * Network Support for MDN-Based Message Centers
+ * 3GPP2 N.S0024-0 v1.0 IS-841
+ *
+ * Enhanced International Calling
+ * 3GPP2 N.S0027 IS-875
+ *
+ * E-911 Phase 2
+ * 3GPP2 N.S0030 J-STD-036-A
+ * XXX Teleservice_Priority not implemented, no parameter ID given!
+ *
+ * ANSI-41-D Miscellaneous Enhancements Revision 0
+ * 3GPP2 N.S0015 PN-3590 (ANSI-41-E)
+ *
+ * TIA/EIA-41-D Internationalization
+ * 3GPP2 N.S0016-0 v1.0
+ *
+ * Authentication Enhancements
+ * 3GPP2 N.S0014-0 v1.0 IS-778
+ *
+ * PCS Multi-band-Based on IS-41C
+ * 3GPP2 N.S0006-0 v1.0 TIA/EIA TSB-76
+ *
+ * Roamer Database Verification Revision B
+ * 3GPP2 N.S0025-B v1.0 IS-947 (aka IS-847 ?)
+ * XXX InvokingNEType not implemented, no parameter ID given!
+ *
+ * Features In CDMA
+ * 3GPP2 N.S0010-0 v1.0 IS-735
+ *
+ * TIA/EIA-41-D Based Network Enhancements for CDMA Packet Data Service (C-PDS), Phase 1
+ * 3GPP2 N.S0029-0 v1.0 IS-880
+ *
+ * OTASP and OTAPA
+ * 3GPP2 N.S0011-0 v1.0 IS-725-A
+ *
+ * Circuit Mode Services
+ * 3GPP2 N.S0008-0 v1.0 IS-737
+ * XXX SecondInterMSCCircuitID not implemented, parameter ID conflicts with ISLP Information!
+ *
+ * IMSI
+ * 3GPP2 N.S0009-0 v1.0 IS-751
+ *
+ * WIN Phase 1
+ * 3GPP2 N.S0013-0 v1.0 IS-771
+ *
+ * WIN Phase 2
+ * 3GPP2 N.S0004-0 v1.0 IS-848
+ *
+ * TIA/EIA-41-D Pre-Paid Charging
+ * 3GPP2 N.S0018-0 v1.0 IS-826
+ *
+ * User Selective Call Forwarding
+ * 3GPP2 N.S0021-0 v1.0 IS-838
+ *
+ * CNAP/CNAR
+ * 3GPP2 N.S0012-0 v1.0
+ *
+ * Answer Hold
+ * 3GPP2 N.S0022-0 v1.0 IS-837
+ *
+ * Automatic Code Gapping
+ * 3GPP2 N.S0023-0 v1.0
+ *
+ * UIM
+ * 3GPP2 N.S0003
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+
+#include "epan/packet.h"
+#include "asn1.h"
+#include "tap.h"
+
+#include "packet-ansi_a.h"
+#include "packet-ansi_map.h"
+
+
+/* PROTOTYPES/FORWARDS */
+
+static gboolean dissect_ansi_param(ASN1_SCK *asn1, proto_tree *tree);
+
+/* ANSI PARAM STRINGS */
+static const value_string ansi_param_1_strings[] = {
+ { 0x81, "Billing ID" },
+ { 0x82, "Serving Cell ID" },
+ { 0x83, "Target Cell ID" },
+ { 0x84, "Digits" },
+ { 0x85, "Channel Data" },
+ { 0x86, "Inter MSC Circuit ID" },
+ { 0x87, "Inter Switch Count" },
+ { 0x88, "Mobile Identification Number" },
+ { 0x89, "Electronic Serial Number" },
+ { 0x8A, "Release Reason" },
+ { 0x8B, "Signal Quality" },
+ { 0x8C, "Station Class Mark" },
+ { 0x8D, "Authorization Denied" },
+ { 0x8E, "Authorization Period" },
+ { 0x8F, "Seizure Type" },
+ { 0x90, "Trunk Status" },
+ { 0x91, "Qualification Information Code" },
+ { 0x92, "Feature Result" },
+ { 0x93, "Redirection Reason" },
+ { 0x94, "Access Denied Reason" },
+ { 0x95, "MSCID" },
+ { 0x96, "System My Type Code" },
+ { 0x97, "Origination Indicator" },
+ { 0x98, "Termination Restriction Code" },
+ { 0x99, "Calling Features Indicator" },
+ { 0x9A, "Faulty Parameter" },
+ { 0x9B, "Usage Indicator" },
+ { 0x9C, "TDMA Channel Data" },
+ { 0x9D, "TDMA Call Mode" },
+ { 0x9E, "Handoff Reason" },
+ { 0, NULL },
+};
+
+static const value_string ansi_param_2_strings[] = {
+ { 0x9F1F, "TDMA Burst Indicator" },
+ { 0x9F20, "PC_SSN" },
+ { 0x9F21, "Location Area ID" },
+ { 0x9F22, "System Access Type" },
+ { 0x9F23, "Authentication Response" },
+ { 0x9F24, "Authentication Response Base Station" },
+ { 0x9F25, "Authentication Response Unique Challenge" },
+ { 0x9F26, "Call History Count" },
+ { 0x9F27, "Confidentiality Modes" },
+ { 0x9F28, "Random Variable" },
+ { 0x9F29, "Random Variable Base Station" },
+ { 0x9F2A, "Random Variable SSD" },
+ { 0x9F2B, "Random Variable Unique Challenge" },
+ { 0x9F2C, "Report Type" },
+ { 0x9F2D, "Signaling Message Encryption Key" },
+ { 0x9F2E, "Shared Secret Data" },
+ { 0x9F2F, "Terminal Type" },
+ { 0x9F30, "Voice Privacy Mask" },
+ { 0x9F31, "System Capabilities" },
+ { 0x9F32, "Deny Access" },
+ { 0x9F33, "Update Count" },
+ { 0x9F34, "SSD Not Shared" },
+ { 0x9F35, "Extended MSCID" },
+ { 0x9F36, "Extended System My Type Code" },
+ { 0x9F37, "Control Channel Data" },
+ { 0x9F38, "System Access Data" },
+ { 0x9F39, "Cancellation Denied" },
+ { 0x9F3A, "Border Cell Access" },
+ { 0x9F3B, "CDMA Station Class Mark" },
+ { 0x9F3C, "CDMA Serving One Way Delay" },
+ { 0x9F3D, "CDMA Target One Way Delay" },
+ { 0x9F3E, "CDMA Call Mode" },
+ { 0x9F3F, "CDMA Channel Data" },
+ { 0x9F40, "CDMA Signal Quality" },
+ { 0x9F41, "CDMA Pilot Strength" },
+ { 0x9F42, "CDMA Mobile Protocol Revision" },
+ { 0x9F43, "CDMA Private Long Code Mask" },
+ { 0x9F44, "CDMA Code Channel" },
+ { 0x9F45, "CDMA Search Window" },
+ { 0x9F46, "MS Location" },
+ { 0x9F47, "Page Indicator" },
+ { 0x9F48, "Received Signal Quality" },
+ { 0x9F49, "Deregistration Type" },
+ { 0x9F4A, "NAMPS Channel Data" },
+ { 0x9F4B, "Alert Code" },
+ { 0x9F4C, "Announcement Code" },
+ { 0x9F4D, "Authentication Algorithm Version" },
+ { 0x9F4E, "Authentication Capability" },
+ { 0x9F4F, "Call History Count Expected" },
+ { 0x9F50, "Calling Party Number Digits 1" },
+ { 0x9F51, "Calling Party Number Digits 2" },
+ { 0x9F52, "Calling Party Number String 1" },
+ { 0x9F53, "Calling Party Number String 2" },
+ { 0x9F54, "Calling Party Subaddress" },
+ { 0x9F55, "Cancellation Type" },
+ { 0x9F56, "Carrier Digits" },
+ { 0x9F57, "Destination Digits" },
+ { 0x9F58, "DMH Redirection Indicator" },
+ { 0x9F59, "Inter System Termination" },
+ { 0x9F5A, "Availability Type" },
+ { 0x9F5B, "Local Termination" },
+ { 0x9F5C, "Message Waiting Notification Count" },
+ { 0x9F5D, "Mobile Directory Number" },
+ { 0x9F5E, "MSCID Number" },
+ { 0x9F5F, "PSTN Termination" },
+ { 0x9F60, "No Answer Time" },
+ { 0x9F61, "One Time Feature Indicator" },
+ { 0x9F62, "Origination Triggers" },
+ { 0x9F63, "RANDC" },
+ { 0x9F64, "Redirecting Number Digits" },
+ { 0x9F65, "Redirecting Number String" },
+ { 0x9F66, "Redirecting Number Subaddress" },
+ { 0x9F67, "Sender Identification Number" },
+ { 0x9F68, "SMS Address" },
+ { 0x9F69, "SMS Bearer Data" },
+ { 0x9F6A, "SMS Charge Indicator" },
+ { 0x9F6B, "SMS Destination Address" },
+ { 0x9F6C, "SMS Message Count" },
+ { 0x9F6D, "SMS Notification Indicator" },
+ { 0x9F6E, "SMS Original Destination Address" },
+ { 0x9F6F, "SMS Original Destination Subaddress" },
+ { 0x9F70, "SMS Original Originating Address" },
+ { 0x9F71, "SMS Original Originating Subaddress" },
+ { 0x9F72, "SMS Originating Address" },
+ { 0x9F73, "SMS Originating Restrictions" },
+ { 0x9F74, "SMS Teleservice Identifier" },
+ { 0x9F75, "SMS Termination Restrictions" },
+ { 0x9F76, "SMS Message Waiting Indicator" },
+ { 0x9F77, "Termination Access Type" },
+ { 0x9F78, "Termination List" },
+ { 0x9F79, "Termination Treatment" },
+ { 0x9F7A, "Termination Triggers" },
+ { 0x9F7B, "Transaction Capability" },
+ { 0x9F7C, "Unique Challenge Report" },
+ { 0, NULL },
+};
+
+static const value_string ansi_param_3_strings[] = {
+ { 0x9F8100, "Action Code" },
+ { 0x9F8101, "Alert Result" },
+ { 0xBF8102, "Announcement List" },
+ { 0xBF8103, "CDMA Code Channel Information" },
+ { 0xBF8104, "CDMA Code Channel List" },
+ { 0xBF8105, "CDMA Target Measurement Information" },
+ { 0xBF8106, "CDMA Target Measurement List" },
+ { 0xBF8107, "CDMA Target MAHO Information" },
+ { 0xBF8108, "CDMA Target MAHO List" },
+ { 0x9F8109, "Conference Calling Indicator" },
+ { 0x9F810A, "Count Update Report" },
+ { 0x9F810B, "Digit Collection Control" },
+ { 0x9F810C, "DMH Account Code Digits" },
+ { 0x9F810D, "DMH Alternate Billing Digits" },
+ { 0x9F810E, "DMH Billing Digits" },
+ { 0x9F810F, "Geographic Authorization" },
+ { 0x9F8110, "Leg Information" },
+ { 0x9F8111, "Message Waiting Notification Type" },
+ { 0x9F8112, "PACA Indicator" },
+ { 0x9F8113, "Preferred Language Indicator" },
+ { 0x9F8114, "Random Valid Time" },
+ { 0x9F8115, "Restriction Digits" },
+ { 0x9F8116, "Routing Digits" },
+ { 0x9F8117, "Setup Result" },
+ { 0x9F8118, "SMS Access Denied Reason" },
+ { 0x9F8119, "SMS Cause Code" },
+ { 0x9F811A, "SPINI PIN" },
+ { 0x9F811B, "SPINI Triggers" },
+ { 0x9F811C, "SSD Update Report" },
+ { 0x9F811D, "Target Measurement Information" },
+ { 0x9F811E, "Target Measurement List" },
+ { 0x9F811F, "Voice Mailbox PIN" },
+ { 0x9F8120, "Voice Mailbox Number" },
+ { 0x9F8121, "Authentication Data" },
+ { 0x9F8122, "Conditionally Denied Reason" },
+ { 0x9F8123, "Group Information" },
+ { 0x9F8124, "Handoff State" },
+ { 0x9F8125, "NAMPS Call Mode" },
+ { 0x9F8126, "CDMA Slot Cycle Index" },
+ { 0x9F8127, "Denied Authorization Period" },
+ { 0x9F8128, "Pilot Number" },
+ { 0x9F8129, "Pilot Billing ID" },
+ { 0x9F812A, "CDMA Band Class" },
+ { 0x9F8172, "International Mobile Subscriber Identity" },
+ { 0x9F8173, "Calling Party Name" },
+ { 0x9F8174, "Display Text" },
+ { 0x9F8175, "Redirecting Party Name" },
+ { 0x9F8176, "Service ID" },
+ { 0x9F8177, "All Or None" },
+ { 0x9F8178, "Change" },
+ { 0xBF8179, "Data Access Element" },
+ { 0xBF817A, "Data Access Element List" },
+ { 0xBF817E, "Data Update Result" },
+ { 0xBF817F, "Data Update Result List" },
+ { 0x9F812D, "CDMA Pilot PN" },
+ { 0x9F812E, "CDMA Service Configuration Record" },
+ { 0x9F812F, "CDMA Service Option" },
+ { 0x9F8131, "CDMA Station Class Mark 2" },
+ { 0x9F8132, "TDMA Service Code" },
+ { 0x9F8133, "TDMA Terminal Capability" },
+ { 0x9F8134, "TDMA Voice Coder" },
+ { 0x9F8135, "A-Key Protocol Version" },
+ { 0x9F8136, "Authentication Response Reauthentication" },
+ { 0x9F8137, "Base Station Partial Key" },
+ { 0x9F8138, "Mobile Station MIN" },
+ { 0x9F8139, "Mobile Station Partial Key" },
+ { 0x9F813A, "Modulus Value" },
+ { 0x9F813B, "Newly Assigned MIN" },
+ { 0x9F813D, "OTASP Result Code" },
+ { 0x9F813E, "Primitive Value" },
+ { 0x9F813F, "Random Variable Reauthentication" },
+ { 0x9F8140, "Reauthentication Report" },
+ { 0x9F8141, "Service Indicator" },
+ { 0x9F8142, "Signaling Message Encryption Report" },
+ { 0x9F8143, "Temporary Reference Number" },
+ { 0x9F8144, "Voice Privacy Report" },
+ { 0x9F8147, "Control Channel Mode" },
+ { 0x9F8152, "CDMA Connection Reference" },
+ { 0x9F8153, "CDMA Connection Reference Information" },
+ { 0x9F8154, "CDMA Connection Reference List" },
+ { 0x9F8156, "Change Service Attributes" },
+ { 0x9F8157, "Data Key" },
+ { 0x9F8158, "Data Privacy Parameters" },
+ { 0x9F8159, "ISLP Information" }, /* IS-737 *SPEC CONFLICT* */
+ { 0x9F815A, "Reason List" },
+ { 0x9F815C, "TDMA Bandwidth" },
+ { 0x9F815D, "TDMA Data Features Indicator" },
+ { 0x9F815E, "TDMA Data Mode" },
+ { 0x9F815F, "TDMA Voice Mode" },
+ { 0x9F8160, "Analog Redirect Info" },
+ { 0xBF812B, "CDMA Band Class Information" },
+ { 0xBF812C, "CDMA Band Class List" },
+ { 0xBF8130, "CDMA Service Option List" },
+ { 0xBF8153, "CDMA Connection Reference Information" },
+ { 0xBF8154, "CDMA Connection Reference List" },
+ { 0xBF8161, "Analog Redirect Record" },
+ { 0xBF8202, "Execute Script" },
+ { 0xBF8206, "Modification Request" },
+ { 0xBF8207, "Modification Request List" },
+ { 0xBF8208, "Modification Result List" },
+ { 0xBF820E, "Service Data Access Element" },
+ { 0xBF820F, "Service Data Access Element List" },
+ { 0xBF8210, "Service Data Result" },
+ { 0xBF8211, "Service Data Result List" },
+ { 0xBF8214, "Trigger Address List" },
+ { 0xBF8216, "Trigger List" },
+ { 0xBF8218, "WIN Capability" },
+ { 0xBF822F, "Call Recovery ID" },
+ { 0xBF8230, "Call Recovery ID List" },
+ { 0xBF8250, "Position Information" },
+ { 0xBF825A, "CDMA PSMM List" },
+ { 0x9F8162, "CDMA Channel Number" },
+ { 0xBF8163, "CDMA Channel Number List" },
+ { 0x9F8164, "CDMA Power Combined Indicator" },
+ { 0x9F8165, "CDMA Redirect Record" },
+ { 0x9F8166, "CDMA Search Parameters" },
+ { 0x9F8168, "CDMA Network Identification" },
+ { 0x9F8169, "Network TMSI" },
+ { 0x9F816A, "Network TMSI Expiration Time" },
+ { 0x9F816B, "New Network TMSI" },
+ { 0x9F816C, "Required Parameters Mask" },
+ { 0x9F816D, "Service Redirection Cause" },
+ { 0x9F816E, "Service Redirection Info" },
+ { 0x9F816F, "Roaming Indication" },
+ { 0x9F8170, "MSID" },
+ { 0x9F817B, "Data ID" },
+ { 0x9F817C, "Database Key" },
+ { 0x9F817D, "Data Result" },
+ { 0x9F8200, "Data Value" },
+ { 0x9F8203, "Failure Cause" },
+ { 0x9F8204, "Failure Type" },
+ { 0x9F8205, "Global Title" },
+ { 0x9F8209, "Private Specialized Resource" },
+ { 0x9F820A, "Resume PIC" },
+ { 0x9F820B, "Script Argument" },
+ { 0x9F820C, "Script Name" },
+ { 0x9F820D, "Script Result" },
+ { 0x9F8212, "Specialized Resource" },
+ { 0x9F8213, "Time Date Offset" },
+ { 0x9F8215, "Trigger Capability" },
+ { 0x9F8217, "Trigger Type" },
+ { 0x9F8219, "WIN Operations Capability" },
+ { 0x9F821B, "WIN Trigger List" },
+ { 0x9F821C, "MSC Address" },
+ { 0x9F821D, "Suspicious Access" },
+ { 0x9F821E, "Mobile Station IMSI" },
+ { 0x9F821F, "Newly Assigned IMSI" },
+ { 0x9F822A, "Command Code" },
+ { 0x9F822B, "Display Text 2" },
+ { 0x9F822C, "Page Count" },
+ { 0x9F822D, "Page Response Time" },
+ { 0x9F822E, "SMS Transaction ID" },
+ { 0x9F8231, "DMH Service ID" },
+ { 0x9F8232, "Feature Indicator" },
+ { 0x9F8233, "Control Network ID" },
+ { 0x9F8234, "Release Cause" },
+ { 0x9F8235, "Time Of Day" },
+ { 0x9F8236, "Call Status" },
+ { 0x9F8237, "DMH Charge Information" },
+ { 0x9F8238, "DMH Billing Indicator" },
+ { 0x9F8239, "MS Status" },
+ { 0x9F823B, "Position Information Code" },
+ { 0x9F8246, "Inter Message Time" },
+ { 0x9F8247, "MSID Usage" },
+ { 0x9F8248, "New MIN Extension" },
+ { 0x9F8249, "DTX Indication" },
+ { 0x9F824A, "CDMA Mobile Capabilities" },
+ { 0x9F824B, "Generalized Time" },
+ { 0x9F824C, "Generic Digits" },
+ { 0x9F824D, "Geographic Position" },
+ { 0x9F824E, "Mobile Call Status" },
+ { 0x9F824F, "Mobile Position Capability" },
+ { 0x9F8251, "Position Request Type" },
+ { 0x9F8252, "Position Result" },
+ { 0x9F8253, "Position Source" },
+ { 0x9F8254, "ACG Encountered" },
+ { 0x9F8255, "CDMA State/Control Type *" }, /* PN-3590 (ANSI-41-E)/ACG *SPEC CONFLICT* */
+ { 0x9F8256, "Gap Duration" },
+ { 0x9F8257, "SCF Overload Gap Interval" },
+ { 0x9F8258, "Service Management System Gap Interval" },
+ { 0x9F8259, "CDMA PSMM Count" },
+ { 0x9F825B, "CDMA Serving One Way Delay 2" },
+ { 0x9F825C, "QoS Priority" },
+ { 0x9F825D, "PDSN Address" },
+ { 0x9F825E, "PDSN Protocol Type" },
+ { 0x9F825F, "CDMA MS Measured Channel Identity" },
+ { 0x9F8261, "Range" },
+ { 0x9F8263, "Calling Party Category" },
+ { 0x9F8264, "cdma2000 Handoff Invoke IOS Data" },
+ { 0x9F8265, "cdma2000 Handoff Response IOS Data" },
+ { 0x9F8266, "LCS Client ID" },
+ { 0x9F8267, "TDMA MAHO Cell ID" },
+ { 0x9F8268, "TDMA MAHO Channel" },
+ { 0x9F8269, "CDMA Service Option Connection Identifier" },
+ { 0x9F826A, "TDMA Time Alignment" },
+ { 0x9F826C, "TDMA MAHO Request" },
+ { 0, NULL },
+};
+
+/* ANSI TCAP component type */
+#define ANSI_TC_INVOKE_L 0xe9
+#define ANSI_TC_RRL 0xea
+#define ANSI_TC_RE 0xeb
+#define ANSI_TC_REJECT 0xec
+#define ANSI_TC_INVOKE_N 0xed
+#define ANSI_TC_RRN 0xee
+
+static const value_string ansi_cmp_type_strings[] = {
+ { ANSI_TC_INVOKE_L, "Invoke(Last)" },
+ { ANSI_TC_RRL, "RetRes(Last)" },
+ { ANSI_TC_RE, "RetErr" },
+ { ANSI_TC_REJECT, "Reject" },
+ { ANSI_TC_INVOKE_N, "Invoke(Not Last)" },
+ { ANSI_TC_RRN, "RetRes(Not Last)" },
+ { 0, NULL },
+};
+
+const value_string ansi_map_opr_code_strings[] = {
+ { 1, "Handoff Measurement Request" },
+ { 2, "Facilities Directive" },
+ { 3, "Mobile On Channel" },
+ { 4, "Handoff Back" },
+ { 5, "Facilities Release" },
+ { 6, "Qualification Request" },
+ { 7, "Qualification Directive" },
+ { 8, "Blocking" },
+ { 9, "Unblocking" },
+ { 10, "Reset Circuit" },
+ { 11, "Trunk Test" },
+ { 12, "Trunk Test Disconnect" },
+ { 13, "Registration Notification" },
+ { 14, "Registration Cancellation" },
+ { 15, "Location Request" },
+ { 16, "Routing Request" },
+ { 17, "Feature Request" },
+ { 18, "Reserved 18 (Service Profile Request, IS-41-C)" },
+ { 19, "Reserved 19 (Service Profile Directive, IS-41-C)" },
+ { 20, "Unreliable Roamer Data Directive" },
+ { 21, "Reserved 21 (Call Data Request, IS-41-C)" },
+ { 22, "MS Inactive" },
+ { 23, "Transfer To Number Request" },
+ { 24, "Redirection Request" },
+ { 25, "Handoff To Third" },
+ { 26, "Flash Request" },
+ { 27, "Authentication Directive" },
+ { 28, "Authentication Request" },
+ { 29, "Base Station Challenge" },
+ { 30, "Authentication Failure Report" },
+ { 31, "Count Request" },
+ { 32, "Inter System Page" },
+ { 33, "Unsolicited Response" },
+ { 34, "Bulk Deregistration" },
+ { 35, "Handoff Measurement Request 2" },
+ { 36, "Facilities Directive 2" },
+ { 37, "Handoff Back 2" },
+ { 38, "Handoff To Third 2" },
+ { 39, "Authentication Directive Forward" },
+ { 40, "Authentication Status Report" },
+ { 41, "Reserved 41" },
+ { 42, "Information Directive" },
+ { 43, "Information Forward" },
+ { 44, "Inter System Answer" },
+ { 45, "Inter System Page 2" },
+ { 46, "Inter System Setup" },
+ { 47, "Origination Request" },
+ { 48, "Random Variable Request" },
+ { 49, "Redirection Directive" },
+ { 50, "Remote User Interaction Directive" },
+ { 51, "SMS Delivery Backward" },
+ { 52, "SMS Delivery Forward" },
+ { 53, "SMS Delivery Point to Point" },
+ { 54, "SMS Notification" },
+ { 55, "SMS Request" },
+ { 56, "OTASP Request" },
+ { 57, "Information Backward" },
+ { 58, "Change Facilities" },
+ { 59, "Change Service" },
+ { 60, "Parameter Request" },
+ { 61, "TMSI Directive" },
+ { 62, "Reserved 62" },
+ { 63, "Service Request" },
+ { 64, "Analyzed Information Request" },
+ { 65, "Connection Failure Report" },
+ { 66, "Connect Resource" },
+ { 67, "Disconnect Resource" },
+ { 68, "Facility Selected and Available" },
+ { 69, "Instruction Request" },
+ { 70, "Modify" },
+ { 71, "Reset Timer" },
+ { 72, "Search" },
+ { 73, "Seize Resource" },
+ { 74, "SRF Directive" },
+ { 75, "T Busy" },
+ { 76, "T NoAnswer" },
+ { 77, "Release" },
+ { 78, "SMS Delivery Point to Point Ack" },
+ { 79, "Message Directive" },
+ { 80, "Bulk Disconnection" },
+ { 81, "Call Control Directive" },
+ { 82, "O Answer" },
+ { 83, "O Disconnect" },
+ { 84, "Call Recovery Report" },
+ { 85, "T Answer" },
+ { 86, "T Disconnect" },
+ { 87, "Unreliable Call Data" },
+ { 88, "O CalledPartyBusy" },
+ { 89, "O NoAnswer" },
+ { 90, "Position Request" },
+ { 91, "Position Request Forward" },
+ { 92, "Call Termination Report" },
+ { 93, "Geo Position Directive" },
+ { 94, "Geo Position Request" },
+ { 95, "Inter System Position Request" },
+ { 96, "Inter System Position Request Forward" },
+ { 97, "ACG Directive" },
+ { 98, "Roamer Database Verification Request" },
+ { 99, "Add Service" },
+ { 100, "Drop Service" },
+ { 0, NULL },
+};
+
+static const value_string ansi_tele_strings[] = {
+ { 1, "Reserved for maintenance" },
+ { 4096, "AMPS Extended Protocol Enhanced Services" },
+ { 4097, "CDMA Cellular Paging Teleservice" },
+ { 4098, "CDMA Cellular Messaging Teleservice" },
+ { 4099, "CDMA Voice Mail Notification" },
+ { 32513, "TDMA Cellular Messaging Teleservice" },
+ { 32520, "TDMA System Assisted Mobile Positioning through Satellite (SAMPS)" },
+ { 32584, "TDMA Segmented System Assisted Mobile Positioning Service" },
+ { 0, NULL },
+};
+
+#define NUM_BAND_CLASS_STR (sizeof(band_class_str)/sizeof(gchar *))
+static gchar *band_class_str[] = {
+ "800 MHz Cellular System",
+ "1.850 to 1.990 GHz Broadband PCS",
+ "872 to 960 MHz TACS Band",
+ "832 to 925 MHz JTACS Band",
+ "1.750 to 1.870 GHz Korean PCS",
+ "450 MHz NMT",
+ "2 GHz IMT-2000 Band",
+ "North American 700 MHz Cellular Band",
+ "1.710 to 1.880 GHz PCS",
+ "880 to 960 MHz Band",
+ "Secondary 800 MHz Band",
+ "400 MHz European PAMR Band",
+ "800 MHz European PAMR Band"
+};
+
+#define NUM_QOS_PRI_STR (sizeof(qos_pri_str)/sizeof(gchar *))
+static gchar *qos_pri_str[] = {
+ "Priority Level 0. This is the lowest level",
+ "Priority Level 1",
+ "Priority Level 2",
+ "Priority Level 3",
+ "Priority Level 4",
+ "Priority Level 5",
+ "Priority Level 6",
+ "Priority Level 7",
+ "Priority Level 8",
+ "Priority Level 9",
+ "Priority Level 10",
+ "Priority Level 11",
+ "Priority Level 12",
+ "Priority Level 13",
+ "Reserved, treat as Priority Level 14",
+ "Reserved, treat as Priority Level 15"
+};
+
+/*
+ * would prefer to have had the define set to the exact number of
+ * elements in the array but that is not without it's own problems
+ * (sizeof(ansi_a_ios401_elem_1_strings)/sizeof(value_string))
+ */
+#define NUM_IOS401_ELEM ANSI_A_MAX_NUM_IOS401_ELEM_1_STRINGS
+static gint ett_ansi_map_ios401_elem[NUM_IOS401_ELEM];
+
+
+/* Initialize the protocol and registered fields */
+static int proto_ansi_map = -1;
+
+static int ansi_map_tap = -1;
+
+static int hf_ansi_map_tag = -1;
+static int hf_ansi_map_length = -1;
+static int hf_ansi_map_id = -1;
+static int hf_ansi_map_opr_code = -1;
+static int hf_ansi_map_param_id = -1;
+static int hf_ansi_map_ios401_elem_id = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_ansi_map = -1;
+static gint ett_opr_code = -1;
+static gint ett_component = -1;
+static gint ett_components = -1;
+static gint ett_params = -1;
+static gint ett_param = -1;
+static gint ett_error = -1;
+static gint ett_problem = -1;
+static gint ett_natnum = -1;
+static gint ett_call_mode = -1;
+static gint ett_chan_data = -1;
+static gint ett_code_chan = -1;
+static gint ett_clr_dig_mask = -1;
+static gint ett_ent_dig_mask = -1;
+static gint ett_all_dig_mask = -1;
+
+
+static char bigbuf[1024];
+static gchar ansi_map_add_string[1024];
+static dissector_handle_t data_handle;
+static dissector_table_t is637_tele_id_dissector_table; /* IS-637 Teleservice ID */
+static dissector_table_t is683_dissector_table; /* IS-683-A (OTA) */
+static dissector_table_t is801_dissector_table; /* IS-801 (PLD) */
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
+static gint32 ansi_map_sms_tele_id = -1;
+static gboolean is683_ota;
+static gboolean is801_pld;
+static gboolean ansi_map_is_invoke;
+
+
+typedef struct dgt_set_t
+{
+ unsigned char out[15];
+}
+dgt_set_t;
+
+static dgt_set_t Dgt_tbcd = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#'
+ }
+};
+
+static dgt_set_t Dgt_msid = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
+ }
+};
+
+/* FUNCTIONS */
+
+/*
+ * Unpack BCD input pattern into output ASCII pattern
+ *
+ * Input Pattern is supplied using the same format as the digits
+ *
+ * Returns: length of unpacked pattern
+ */
+static int
+my_dgt_tbcd_unpack(
+ char *out, /* ASCII pattern out */
+ guchar *in, /* packed pattern in */
+ int num_octs, /* Number of octets to unpack */
+ dgt_set_t *dgt /* Digit definitions */
+ )
+{
+ int cnt = 0;
+ unsigned char i;
+
+ while (num_octs)
+ {
+ /*
+ * unpack first value in byte
+ */
+ i = *in++;
+ *out++ = dgt->out[i & 0x0f];
+ cnt++;
+
+ /*
+ * unpack second value in byte
+ */
+ i >>= 4;
+
+ if (i == 0x0f) /* odd number bytes - hit filler */
+ break;
+
+ *out++ = dgt->out[i];
+ cnt++;
+ num_octs--;
+ }
+
+ *out = '\0';
+
+ return(cnt);
+}
+
+static gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr)
+ {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+
+/* PARAM FUNCTIONS */
+
+#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
+ if ((edc_len) > (edc_max_len)) \
+ { \
+ proto_tree_add_text(tree, asn1->tvb, \
+ asn1->offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
+ asn1->offset += ((edc_len) - (edc_max_len)); \
+ }
+
+#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
+ if ((sdc_len) < (sdc_min_len)) \
+ { \
+ proto_tree_add_text(tree, asn1->tvb, \
+ asn1->offset, (sdc_len), "Short Data (?)"); \
+ asn1->offset += (sdc_len); \
+ return; \
+ }
+
+#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
+ if ((edc_len) != (edc_eq_len)) \
+ { \
+ proto_tree_add_text(tree, asn1->tvb, \
+ asn1->offset, (edc_len), "Unexpected Data Length"); \
+ asn1->offset += (edc_len); \
+ return; \
+ }
+
+static void
+param_mscid(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 market_id, switch_num;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 3);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &market_id);
+ asn1_int32_value_decode(asn1, 1, &switch_num);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Market ID %u Switch Number %u",
+ market_id, switch_num);
+}
+
+static void
+param_page_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Page"; break;
+ case 2: str = "Listen only"; break;
+ default:
+ if ((value >= 3) && (value <= 223)) { str = "Reserved, treat as Page"; }
+ else { str = "Reserved for protocol extension, treat as Page"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_srvc_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Undefined Service"; break;
+ case 1: str = "CDMA OTASP Service"; is683_ota = TRUE; break;
+ case 2: str = "TDMA OTASP Service"; break;
+ case 3: str = "CDMA OTAPA Service"; is683_ota = TRUE; break;
+ case 4: str = "CDMA Position Determination Service"; is801_pld = TRUE; break;
+ case 5: str = "AMPS Position Determination Service"; break;
+ default:
+ if ((value >= 6) && (value <= 223)) { str = "Reserved, treat as Undefined Service"; }
+ else { str = "Reserved for protocol extension, treat as Undefined Service"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s (%u)",
+ str,
+ value);
+}
+
+static void
+param_sme_report(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Signaling Message Encryption enabling not attempted"; break;
+ case 2: str = "Signaling Message Encryption enabling no response"; break;
+ case 3: str = "Signaling Message Encryption is enabled"; break;
+ case 4: str = "Signaling Message Encryption enabling failed"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, treat as Signaling Message Encryption enabling not attempted"; }
+ else { str = "Reserved for protocol extension, treat as Signaling Message Encryption enabling not attempted"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s (%u)",
+ str,
+ value);
+}
+
+static void
+param_alert_code(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0xc0) >> 6)
+ {
+ case 0: str = "Medium"; break;
+ case 1: str = "High"; break;
+ case 2: str = "Low"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Pitch, %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x3f)
+ {
+ case 0: str = "NoTone"; break;
+ case 1: str = "Long"; break;
+ case 2: str = "ShortShort"; break;
+ case 3: str = "ShortShortLong"; break;
+ case 4: str = "ShortShort2"; break;
+ case 5: str = "ShortLongShort"; break;
+ case 6: str = "ShortShortShortShort"; break;
+ case 7: str = "PBXLong"; break;
+ case 8: str = "PBXShortShort"; break;
+ case 9: str = "PBXShortShortLong"; break;
+ case 10: str = "PBXShortLongShort"; break;
+ case 11: str = "PBXShortShortShortShort"; break;
+ case 12: str = "PipPipPipPip"; break;
+ default:
+ str = "Reserved, treat as NoTone";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Cadence, %s",
+ bigbuf,
+ str);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf8, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x07)
+ {
+ case 0: str = "Alert without waiting to report"; break;
+ case 1: str = "Apply a reminder alert once"; break;
+ default:
+ str = "Reserved, treat as Alert without waiting to report";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x07, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Alert Action, %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_term_acc_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 252: str = "Mobile-to-Mobile Directory Number access"; break;
+ case 253: str = "Land-to-Mobile Directory Number access"; break;
+ case 254: str = "Land-to-Mobile Directory Number access"; break;
+ case 255: str = "Roamer port access"; break;
+ default:
+ if ((value >= 1) && (value <= 127)) { str = "Reserved for controlling system assignment"; }
+ else if ((value >= 128) && (value <= 160)) { str = "Reserved for protocol extension, treat as Land-to-Mobile Directory Number access"; }
+ else { str = "Reserved"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_term_treat(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "MS Termination"; break;
+ case 2: str = "Voice Mail Storage"; break;
+ case 3: str = "Voice Mail Retrieval"; break;
+ case 4: str = "Dialogue Termination"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, treat as Unrecognized parameter value"; }
+ else { str = "Reserved for protocol extension, treat as Unrecognized parameter value"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_term_trig(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0xc0) >> 6)
+ {
+ case 0: str = "No Answer Call"; break;
+ case 1: str = "No Answer Trigger"; break;
+ case 2: str = "No Answer Leg"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : No Answer (NA), %s",
+ bigbuf,
+ str);
+
+ switch ((value & 0x30) >> 4)
+ {
+ case 0: str = "No Page Response Call"; break;
+ case 1: str = "No Page Response Trigger"; break;
+ case 2: str = "No Page Response Leg"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : No Page Response (NPR), %s",
+ bigbuf,
+ str);
+
+ switch ((value & 0x0c) >> 2)
+ {
+ case 0: str = "Failed Call"; break;
+ case 1: str = "Routing Failure Trigger"; break;
+ case 2: str = "Failed Leg"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Routing Failure (RF), %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Busy Call"; break;
+ case 1: str = "Busy Trigger"; break;
+ case 2: str = "Busy Leg"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Busy, %s",
+ bigbuf,
+ str);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfe, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : None Reachable (NR), %s",
+ bigbuf,
+ (value & 0x01) ? "Group Not Reachable" : "Member Not Reachable");
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_aav(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Value as used in the CAVE algorithm (%u)",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_ann_code(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 3);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Dialtone"; break;
+ case 1: str = "Ringback or Audible Alerting"; break;
+ case 2: str = "Intercept or Mobile Reorder"; break;
+ case 3: str = "Congestion or Reorder"; break;
+ case 4: str = "Busy"; break;
+ case 5: str = "Confirmation"; break;
+ case 6: str = "Answer"; break;
+ case 7: str = "Call Waiting"; break;
+ case 8: str = "Offhook"; break;
+ case 17: str = "Recall Dial"; break;
+ case 18: str = "Barge In"; break;
+ case 20: str = "PPC Insufficient"; break;
+ case 21: str = "PPC Warning 1"; break;
+ case 22: str = "PPC Warning 2"; break;
+ case 23: str = "PPC Warning 3"; break;
+ case 24: str = "PPC Disconnect"; break;
+ case 25: str = "PPC Redirect"; break;
+ case 63: str = "Tones Off"; break;
+ case 192: str = "Pip"; break;
+ case 193: str = "Abbreviated Intercept"; break;
+ case 194: str = "Abbreviated Congestion"; break;
+ case 195: str = "Warning"; break;
+ case 196: str = "Denial Tone Burst"; break;
+ case 197: str = "Dial Tone Burst"; break;
+ case 250: str = "Incoming Additional Call"; break;
+ case 251: str = "Priority Additional Call"; break;
+ default:
+ str = "Reserved, treat as Tones Off";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Tone %u, %s",
+ bigbuf,
+ value,
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x0f)
+ {
+ case 0: str = "Concurrent"; break;
+ case 1: str = "Sequential"; break;
+ default:
+ if ((value >= 2) && (value <= 7)) { str = "Reserved, treat as Concurrent"; }
+ else { str = "Reserved, treat as Sequential"; }
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Class %s",
+ bigbuf,
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "None"; break;
+ case 1: str = "Unauthorized User"; break;
+ case 2: str = "Invalid ESN"; break;
+ case 3: str = "Unauthorized Mobile"; break;
+ case 4: str = "Suspended Origination"; break;
+ case 5: str = "Origination Denied"; break;
+ case 6: str = "Service Area Denial"; break;
+ case 16: str = "Partial Dial"; break;
+ case 17: str = "Require 1 Plus"; break;
+ case 18: str = "Require 1 Plus NPA"; break;
+ case 19: str = "Require 0 Plus"; break;
+ case 20: str = "Require 0 Plus NPA"; break;
+ case 21: str = "Deny 1 Plus"; break;
+ case 22: str = "Unsupported 10 plus"; break;
+ case 23: str = "Deny 10 plus"; break;
+ case 24: str = "Unsupported 10 XXX"; break;
+ case 25: str = "Deny 10 XXX"; break;
+ case 26: str = "Deny 10 XXX Locally"; break;
+ case 27: str = "Require 10 Plus"; break;
+ case 28: str = "Require NPA"; break;
+ case 29: str = "Deny Toll Origination"; break;
+ case 30: str = "Deny International Origination"; break;
+ case 31: str = "Deny 0 Minus"; break;
+ case 48: str = "Deny Number"; break;
+ case 49: str = "Alternate Operator Services"; break;
+ case 64: str = "No Circuit or All Circuits Busy or FacilityProblem"; break;
+ case 65: str = "Overload"; break;
+ case 66: str = "Internal Office Failure"; break;
+ case 67: str = "No Wink Received"; break;
+ case 68: str = "Interoffice Link Failure"; break;
+ case 69: str = "Vacant"; break;
+ case 70: str = "Invalid Prefix or Invalid Access Code"; break;
+ case 71: str = "Other Dialing Irregularity"; break;
+ case 80: str = "Vacant Number or Disconnected Number"; break;
+ case 81: str = "Deny Termination"; break;
+ case 82: str = "Suspended Termination"; break;
+ case 83: str = "Changed Number"; break;
+ case 84: str = "Inaccessible Subscriber"; break;
+ case 85: str = "Deny Incoming Toll"; break;
+ case 86: str = "Roamer Access Screening"; break;
+ case 87: str = "Refuse Call"; break;
+ case 88: str = "Redirect Call"; break;
+ case 89: str = "No Page Response"; break;
+ case 90: str = "No Answer"; break;
+ case 96: str = "Roamer Intercept"; break;
+ case 97: str = "General Information"; break;
+ case 112: str = "Unrecognized Feature Code"; break;
+ case 113: str = "Unauthorized Feature Code"; break;
+ case 114: str = "Restricted Feature Code"; break;
+ case 115: str = "Invalid Modifier Digits"; break;
+ case 116: str = "Successful Feature Registration"; break;
+ case 117: str = "Successful Feature Deregistration"; break;
+ case 118: str = "Successful Feature Activation"; break;
+ case 119: str = "Successful Feature Deactivation"; break;
+ case 120: str = "Invalid Forward To Number"; break;
+ case 121: str = "Courtesy Call Warning"; break;
+ case 128: str = "Enter PIN Send Prompt"; break;
+ case 129: str = "Enter PIN Prompt"; break;
+ case 130: str = "Reenter PIN Send Prompt"; break;
+ case 131: str = "Reenter PIN Prompt"; break;
+ case 132: str = "Enter Old PIN Send Prompt"; break;
+ case 133: str = "Enter Old PIN Prompt"; break;
+ case 134: str = "Enter New PIN Send Prompt"; break;
+ case 135: str = "Enter New PIN Prompt"; break;
+ case 136: str = "Reenter New PIN Send Prompt"; break;
+ case 137: str = "Reenter New PIN Prompt"; break;
+ case 138: str = "Enter Password Prompt"; break;
+ case 139: str = "Enter Directory Number Prompt"; break;
+ case 140: str = "Reenter Directory Number Prompt"; break;
+ case 141: str = "Enter Feature Code Prompt"; break;
+ case 142: str = "Enter Credit Card Number Prompt"; break;
+ case 143: str = "Enter Destination Number Prompt"; break;
+ case 152: str = "PPC Insufficient Account Balance"; break;
+ case 153: str = "PPC Five Minute Warning"; break;
+ case 154: str = "PPC Three Minute Warning"; break;
+ case 155: str = "PPC Two Minute Warning"; break;
+ case 156: str = "PPC One Minute Warning"; break;
+ case 157: str = "PPC Disconnect"; break;
+ case 158: str = "PPC Redirect"; break;
+ default:
+ str = "Reserved, treat as None";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Standard Announcement, %s",
+ bigbuf,
+ str);
+
+ if (len == 3) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Custom Announcement %u",
+ bigbuf,
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 4);
+}
+
+static void
+param_alert_res(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not specified"; break;
+ case 1: str = "Success"; break;
+ case 2: str = "Failure"; break;
+ case 3: str = "Denied"; break;
+ case 4: str = "Not attempted"; break;
+ case 5: str = "No page response"; break;
+ case 6: str = "Busy"; break;
+ default:
+ str = "Reserved, treat as Not specified";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_conf_call_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = ", Not specified"; break;
+ case 255: str = ", Unlimited number of conferees"; break;
+ default:
+ str = "";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Maximum Number of Conferees, (%u)%s",
+ value,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_count_upd_report(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "COUNT Update not attempted"; break;
+ case 2: str = "COUNT Update no response"; break;
+ case 3: str = "COUNT Update successful"; break;
+ default:
+ if ((value >= 4) && (value <= 223)) { str = "Reserved, treat as COUNT Update not attempted"; }
+ else { str = "Reserved for protocol extension, treat as COUNT Update not attempted"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_ssd_upd_report(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "SSD Update not attempted"; break;
+ case 2: str = "SSD Update no response"; break;
+ case 3: str = "SSD Update successful"; break;
+ case 4: str = "SSD Update failed"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, treat as SSD Update not attempted"; }
+ else { str = "Reserved for protocol extension, treat as SSD Update not attempted"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_cond_den_reason(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Waitable (i.e., Call Waiting is possible)"; break;
+ default:
+ if ((value >= 2) && (value <= 223)) { str = "Reserved, treat as Waitable"; }
+ else { str = "Reserved for protocol extension, treat as Waitable"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_den_auth_per(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Per Call. Re-authorization should be attempted on the next call attempt"; break;
+ case 2: str = "Hours"; break;
+ case 3: str = "Days"; break;
+ case 4: str = "Weeks"; break;
+ case 5: str = "Per Agreement"; break;
+ case 6: str = "Reserved"; break;
+ case 7: str = "Number of calls. Re-authorization should be attempted after this number of (rejected) call attempts"; break;
+ case 8: str = "Minutes"; break;
+ default:
+ if ((value >= 9) && (value <= 223)) { str = "Reserved, treat as Per Call"; }
+ else { str = "Reserved for protocol extension, treat as Per Call"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Period, %s",
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Value %u",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_ho_state(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfe, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Party Involved (PI), %s",
+ bigbuf,
+ (value & 0x01) ? "Terminator is handing off" : "Originator is handing off");
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_geo_auth(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Authorized for all Market IDs served by the VLR"; break;
+ case 2: str = "Authorized for this Market ID only"; break;
+ case 3: str = "Authorized for this Market ID and Switch Number only"; break;
+ case 4: str = "Authorized for this Location Area ID within a Market ID only"; break;
+ default:
+ if ((value >= 5) && (value <= 95)) { str = "Reserved, treat as Authorized for all Market IDs served by the VLR"; }
+ else if ((value >= 96) && (value <= 127)) { str = "Reserved for protocol extension, treat as Authorized for all Market IDs served by the VLR"; }
+ else if ((value >= 128) && (value <= 223)) { str = "Reserved, treat as Authorized for this Location Area ID within a Market ID only"; }
+ else { str = "Reserved for protocol extension, treat as Authorized for this Location Area ID within a Market ID only"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_mw_noti_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x0c) >> 2)
+ {
+ case 0: str = "No MWI. Notification is not authorized or notification is not required"; break;
+ case 1: str = "Reserved"; break;
+ case 2: str = "MWI On. Notification is required. Messages waiting"; break;
+ case 3: str = "MWI Off. Notification is required. No messages waiting"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Message Waiting Indication (MWI), %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Alert Pip Tone (APT), %s",
+ bigbuf,
+ (value & 0x02) ? "notification is required" : "notification is not authorized or notification is not required");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Pip Tone (PT), %s",
+ bigbuf,
+ (value & 0x01) ? "notification is required" : "notification is not authorized or notification is not required");
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_paca_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x1e) >> 1)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Priority Level 1"; break;
+ case 2: str = "Priority Level 2"; break;
+ case 3: str = "Priority Level 3"; break;
+ case 4: str = "Priority Level 4"; break;
+ case 5: str = "Priority Level 5"; break;
+ case 6: str = "Priority Level 6"; break;
+ case 7: str = "Priority Level 7"; break;
+ case 8: str = "Priority Level 8"; break;
+ case 9: str = "Priority Level 9"; break;
+ case 10: str = "Priority Level 10"; break;
+ case 11: str = "Priority Level 11"; break;
+ case 12: str = "Priority Level 12"; break;
+ case 13: str = "Priority Level 13"; break;
+ case 14: str = "Priority Level 14"; break;
+ case 15: str = "Priority Level 15"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x1e, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : PACA Level, %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : PACA is %spermanently activated",
+ bigbuf,
+ (value & 0x01) ? "" : "not ");
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_digit_collect_ctrl(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ proto_item *item;
+ proto_tree *subtree;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Break (BRK), %s",
+ bigbuf,
+ (value & 0x80) ? "Break In (default)" : "No Break");
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Type Ahead (TA), %s",
+ bigbuf,
+ (value & 0x40) ? "Buffer (default)" : "No Type Ahead");
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Maximum Collect (%u)",
+ bigbuf,
+ (value & 0x1f));
+
+ if (len == 1) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Minimum Collect (%u)",
+ bigbuf,
+ (value & 0x1f));
+
+ if (len == 2) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Maximum Interaction Time (%u) seconds",
+ value);
+
+ if (len == 3) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Initial Interdigit Time (%u) seconds",
+ bigbuf,
+ (value & 0x1f));
+
+ if (len == 4) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Normal Interdigit Time (%u) seconds",
+ bigbuf,
+ (value & 0x1f));
+
+ if (len == 5) return;
+
+ saved_offset = asn1->offset;
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, (len > 6) ? 2 : 1,
+ "Clear Digits Digit Mask");
+
+ subtree = proto_item_add_subtree(item, ett_clr_dig_mask);
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 7 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 6 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 5 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 4 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 3 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 2 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 0 Digit",
+ bigbuf);
+
+ if (len == 6) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : # Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : * Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 9 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 8 Digit",
+ bigbuf);
+
+ if (len == 7) return;
+
+ saved_offset = asn1->offset;
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, (len > 8) ? 2 : 1,
+ "Enter Digits Digit Mask");
+
+ subtree = proto_item_add_subtree(item, ett_ent_dig_mask);
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 7 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 6 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 5 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 4 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 3 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 2 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 0 Digit",
+ bigbuf);
+
+ if (len == 8) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : # Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : * Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 9 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 8 Digit",
+ bigbuf);
+
+ if (len == 9) return;
+
+ saved_offset = asn1->offset;
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, (len > 10) ? 2 : 1,
+ "Allowed Digits Digit Mask");
+
+ subtree = proto_item_add_subtree(item, ett_all_dig_mask);
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 7 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 6 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 5 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 4 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 3 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 2 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 0 Digit",
+ bigbuf);
+
+ if (len == 10) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : # Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : * Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 9 Digit",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 8 Digit",
+ bigbuf);
+
+ if (len == 11) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Special Interdigit Time (%u)",
+ bigbuf,
+ value & 0x1f);
+
+ if (len == 12) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 8",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 7",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 6",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 5",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 4",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 3",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 2",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 1",
+ bigbuf);
+
+ if (len == 13) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 16",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 15",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 14",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 13",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 12",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 11",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 10",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 9",
+ bigbuf);
+
+ if (len == 14) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 24",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 23",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 22",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 21",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 20",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 19",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 18",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 17",
+ bigbuf);
+
+ if (len == 15) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 31",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 30",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 29",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 28",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 27",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 26",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SIT 25",
+ bigbuf);
+
+ EXTRANEOUS_DATA_CHECK(len, 16);
+}
+
+static void
+param_no_ans_time(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "(%u) The number of seconds to wait after alerting an MS or after seizing an outgoing trunk before applying no answer trigger treatment.",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_mw_noti_count(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset, orig_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+
+ do
+ {
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Voice Messages"; break;
+ case 1: str = "Short Message Services (SMS) messages"; break;
+ case 2: str = "Group 3 (G3) Fax messages"; break;
+ case 255: str = "Not specified"; break;
+ default:
+ str = "Reserved, treat as Not specified";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Type of messages, %s",
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "No messages are waiting"; break;
+ case 254: str = "254 or more messages are waiting"; break;
+ case 255: str = "An unknown number of messages are waiting (greater than zero)"; break;
+ default:
+ sprintf(bigbuf, "%u messages are waiting", value);
+ str = bigbuf;
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ saved_offset = asn1->offset;
+ }
+ while ((len - (saved_offset - orig_offset)) >= 2);
+
+ EXTRANEOUS_DATA_CHECK((len - (saved_offset - orig_offset)), 0);
+}
+
+static void
+param_otfi(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0xc0) >> 6)
+ {
+ case 0: str = "Ignore"; break;
+ case 1: str = "Presentation Allowed"; break;
+ case 2: str = "Presentation Restricted"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Calling Number ID Restriction, %s",
+ bigbuf,
+ str);
+
+ switch ((value & 0x30) >> 4)
+ {
+ case 0: str = "Ignore"; break;
+ case 1: str = "Pip Tone Inactive"; break;
+ case 2: str = "Pip Tone Active"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Message Waiting Notification, %s",
+ bigbuf,
+ str);
+
+ switch ((value & 0x0c) >> 2)
+ {
+ case 0: str = "Ignore"; break;
+ case 1: str = "No CW"; break;
+ case 2: str = "Normal CW"; break;
+ case 3: str = "Priority CW"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Call Waiting for Incoming Call (CWIC), %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Ignore"; break;
+ case 1: str = "No CW"; break;
+ case 2: str = "Normal CW"; break;
+ case 3: str = "Priority CW"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Call Waiting for Future Incoming Call (CWFI), %s",
+ bigbuf,
+ str);
+
+ if (len == 1) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x30) >> 4)
+ {
+ case 0: str = "Ignore"; break;
+ case 1: str = "Presentation Allowed"; break;
+ case 2: str = "Presentation Restricted"; break;
+ case 3: str = "Blocking Toggle"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Calling Name Restriction (CNAR), %s",
+ bigbuf,
+ str);
+
+ switch ((value & 0x0c) >> 2)
+ {
+ case 0: str = "Ignore"; break;
+ case 1: str = "Flash Inactive"; break;
+ case 2: str = "Flash Active"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Flash Privileges (Flash), %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Ignore"; break;
+ case 1: str = "PACA Demand Inactive"; break;
+ case 2: str = "PACA Demand Actived"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Priority Access and Channel Assignment (PACA), %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+/*
+ * For:
+ * Authentication Response
+ * Authentication Response Base Station
+ * Authentication Response Unique Challenge
+ */
+static void
+param_auth_resp_all(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 3);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfc, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Response (MSB)",
+ bigbuf);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Response",
+ bigbuf);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Response (LSB)",
+ bigbuf);
+}
+
+static void
+param_sys_acc_data(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 5);
+
+ param_mscid(asn1, tree, 3, add_string);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Serving Cell ID %u",
+ value);
+}
+
+static void
+param_bill_id(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 id, segcount;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 7);
+
+ param_mscid(asn1, tree, 3, add_string);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 3, &id);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "ID Number %u",
+ id);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &segcount);
+
+ if (segcount == 255) { str = "Unspecified"; }
+ else if ((segcount >= 0) && (segcount <= 127)) { str = "Number of call segments"; }
+ else if ((segcount >= 128) && (segcount < 255)) { str = "Not used in TIA/EIA-41"; }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Segment Counter %u: %s",
+ segcount, str);
+}
+
+static void
+param_cdma_so(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 so;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 2, &so);
+
+ switch (so)
+ {
+ case 1: str = "Basic Variable Rate Voice Service (8 kbps)"; break;
+ case 2: str = "Mobile Station Loopback (8 kbps)"; break;
+ case 3: str = "Enhanced Variable Rate Voice Service (8 kbps)"; break;
+ case 4: str = "Asynchronous Data Service (9.6 kbps)"; break;
+ case 5: str = "Group 3 Facsimile (9.6 kbps)"; break;
+ case 6: str = "Short Message Services (Rate Set 1)"; break;
+ case 7: str = "Packet Data Service: Internet or ISO Protocol Stack (9.6 kbps)"; break;
+ case 8: str = "Packet Data Service: CDPD Protocol Stack (9.6 kbps)"; break;
+ case 9: str = "Mobile Station Loopback (13 kbps)"; break;
+ case 10: str = "STU-III Transparent Service"; break;
+ case 11: str = "STU-III Non-Transparent Service"; break;
+ case 12: str = "Asynchronous Data Service (14.4 or 9.6 kbps)"; break;
+ case 13: str = "Group 3 Facsimile (14.4 or 9.6 kbps)"; break;
+ case 14: str = "Short Message Services (Rate Set 2)"; break;
+ case 15: str = "Packet Data Service: Internet or ISO Protocol Stack (14.4 kbps)"; break;
+ case 16: str = "Packet Data Service: CDPD Protocol Stack (14.4 kbps)"; break;
+ case 17: str = "High Rate Voice Service (13 kbps)"; break;
+ case 32768: str = "QCELP (13 kbps)"; break;
+ case 18: str = "Over-the-Air Parameter Administration (Rate Set 1)"; break;
+ case 19: str = "Over-the-Air Parameter Administration (Rate Set 2)"; break;
+ case 20: str = "Group 3 Analog Facsimile (Rate Set 1)"; break;
+ case 21: str = "Group 3 Analog Facsimile (Rate Set 2)"; break;
+ case 22: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS1 forward, RS1 reverse)"; break;
+ case 23: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS1 forward, RS2 reverse)"; break;
+ case 24: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS2 forward, RS1 reverse)"; break;
+ case 25: str = "High Speed Packet Data Service: Internet or ISO Protocol Stack (RS2 forward, RS2 reverse)"; break;
+ case 26: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS1 forward, RS1 reverse)"; break;
+ case 27: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS1 forward, RS2 reverse)"; break;
+ case 28: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS2 forward, RS1 reverse)"; break;
+ case 29: str = "High Speed Packet Data Service: CDPD Protocol Stack (RS2 forward, RS2 reverse)"; break;
+ case 30: str = "Supplemental Channel Loopback Test for Rate Set 1"; break;
+ case 31: str = "Supplemental Channel Loopback Test for Rate Set 2"; break;
+ case 32: str = "Test Data Service Option (TDSO)"; break;
+ case 33: str = "cdma2000 High Speed Packet Data Service, Internet or ISO Protocol Stack"; break;
+ case 34: str = "cdma2000 High Speed Packet Data Service, CDPD Protocol Stack"; break;
+ case 35: str = "Location Services, Rate Set 1 (9.6 kbps)"; break;
+ case 36: str = "Location Services, Rate Set 2 (14.4 kbps)"; break;
+ case 37: str = "ISDN Interworking Service (64 kbps)"; break;
+ case 38: str = "GSM Voice"; break;
+ case 39: str = "GSM Circuit Data"; break;
+ case 40: str = "GSM Packet Data"; break;
+ case 41: str = "GSM Short Message Service"; break;
+ case 42: str = "None Reserved for MC-MAP standard service options"; break;
+ case 54: str = "Markov Service Option (MSO)"; break;
+ case 55: str = "Loopback Service Option (LSO)"; break;
+ case 56: str = "Selectable Mode Vocoder"; break;
+ case 57: str = "32 kbps Circuit Video Conferencing"; break;
+ case 58: str = "64 kbps Circuit Video Conferencing"; break;
+ case 59: str = "HRPD Accounting Records Identifier"; break;
+ case 60: str = "Link Layer Assisted Robust Header Compression (LLA ROHC) - Header Removal"; break;
+ case 61: str = "Link Layer Assisted Robust Header Compression (LLA ROHC) - Header Compression"; break;
+ case 62: str = "- 4099 None Reserved for standard service options"; break;
+ case 4100: str = "Asynchronous Data Service, Revision 1 (9.6 or 14.4 kbps)"; break;
+ case 4101: str = "Group 3 Facsimile, Revision 1 (9.6 or 14.4 kbps)"; break;
+ case 4102: str = "Reserved for standard service option"; break;
+ case 4103: str = "Packet Data Service: Internet or ISO Protocol Stack, Revision 1 (9.6 or 14.4 kbps)"; break;
+ case 4104: str = "Packet Data Service: CDPD Protocol Stack, Revision 1 (9.6 or 14.4 kbps)"; break;
+ default:
+ if ((so >= 4105) && (so <= 32767)) { str = "Reserved for standard service options"; }
+ else if ((so >= 32769) && (so <= 32771)) { str = "Proprietary QUALCOMM Incorporated"; }
+ else if ((so >= 32772) && (so <= 32775)) { str = "Proprietary OKI Telecom"; }
+ else if ((so >= 32776) && (so <= 32779)) { str = "Proprietary Lucent Technologies"; }
+ else if ((so >= 32780) && (so <=32783)) { str = "Nokia"; }
+ else if ((so >= 32784) && (so <=32787)) { str = "NORTEL NETWORKS"; }
+ else if ((so >= 32788) && (so <=32791)) { str = "Sony Electronics Inc."; }
+ else if ((so >= 32792) && (so <=32795)) { str = "Motorola"; }
+ else if ((so >= 32796) && (so <=32799)) { str = "QUALCOMM Incorporated"; }
+ else if ((so >= 32800) && (so <=32803)) { str = "QUALCOMM Incorporated"; }
+ else if ((so >= 32804) && (so <=32807)) { str = "QUALCOMM Incorporated"; }
+ else if ((so >= 32808) && (so <=32811)) { str = "QUALCOMM Incorporated"; }
+ else if ((so >= 32812) && (so <=32815)) { str = "Lucent Technologies"; }
+ else if ((so >= 32816) && (so <=32819)) { str = "Denso International"; }
+ else if ((so >= 32820) && (so <=32823)) { str = "Motorola"; }
+ else if ((so >= 32824) && (so <=32827)) { str = "Denso International"; }
+ else if ((so >= 32828) && (so <=32831)) { str = "Denso International"; }
+ else if ((so >= 32832) && (so <=32835)) { str = "Denso International"; }
+ else if ((so >= 32836) && (so <=32839)) { str = "NEC America"; }
+ else if ((so >= 32840) && (so <=32843)) { str = "Samsung Electronics"; }
+ else if ((so >= 32844) && (so <=32847)) { str = "Texas Instruments Incorporated"; }
+ else if ((so >= 32848) && (so <=32851)) { str = "Toshiba Corporation"; }
+ else if ((so >= 32852) && (so <=32855)) { str = "LG Electronics Inc."; }
+ else if ((so >= 32856) && (so <=32859)) { str = "VIA Telecom Inc."; }
+ else { str = "Reserved"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s %u/0x%04x",
+ str, so, so);
+
+ sprintf(add_string, " - (SO=0x%04x)", so);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_tdma_sc(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Analog Speech Only"; break;
+ case 1: str = "Digital Speech Only"; break;
+ case 2: str = "Analog or Digital Speech, Analog Preferred"; break;
+ case 3: str = "Analog or Digital Speech, Digital Preferred"; break;
+ case 4: str = "Asynchronous Data"; break;
+ case 5: str = "G3 Fax"; break;
+ case 6: str = "Not Used (Service Rejected)"; break;
+ case 7: str = "STU III (Secure Telephone Unit)"; break;
+ default:
+ str = "Reserved, treat as Analog Speech Only";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s %u",
+ str, value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_dmh_red_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 redind;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &redind);
+
+ switch (redind)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Call Forwarding Unconditional (CFU)"; break;
+ case 2: str = "Call Forwarding Busy (CFB)"; break;
+ case 3: str = "Call Forwarding No Answer (CFNA)"; break;
+ case 4: str = "Call Forwarding Other (CFO)"; break;
+ case 5: str = "CD Unspecified"; break;
+ case 6: str = "CD PSTN"; break;
+ case 7: str = "CD Private"; break;
+ case 8: str = "PSTN Tandem"; break;
+ case 9: str = "Private Tandem"; break;
+ case 10: str = "Busy"; break;
+ case 11: str = "Inactive"; break;
+ case 12: str = "Unassigned"; break;
+ case 13: str = "Termination Denied"; break;
+ case 14: str = "CD Failure"; break;
+ case 15: str = "Explicit Call Transfer (ECT)"; break;
+ case 16: str = "Mobile Access Hunting (MAH)"; break;
+ case 17: str = "Flexible Alerting (FA)"; break;
+ case 18: str = "Abandoned Call Leg"; break;
+ case 19: str = "Password Call Acceptance (PCA) Call Refused"; break;
+ case 20: str = "Selective Call Acceptance (SCA) Call Refused"; break;
+ case 21: str = "Dialogue"; break;
+ case 22: str = "Call Forwarding Default (CFD)"; break;
+ case 23: str = "CD Local"; break;
+ case 24: str = "Voice Mail Retrieval"; break;
+ default:
+ if ((redind >= 25) && (redind <= 127))
+ {
+ str = "Reserved/Unknown";
+ }
+ else
+ {
+ str = "Reserved for bilateral agreements";
+ }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s (%u)",
+ str, redind);
+}
+
+static void
+param_cic(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 tg, mem;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &tg);
+ asn1_int32_value_decode(asn1, 1, &mem);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "Trunk Group %u Member %u",
+ tg, mem);
+
+ sprintf(add_string, "- (%u/%u)", tg, mem);
+}
+
+static void
+param_qic(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 qic;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &qic);
+
+ switch (qic)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "No information"; break;
+ case 2: str = "Validation only"; break;
+ case 3: str = "Validation and profile"; break;
+ case 4: str = "Profile only"; break;
+ default:
+ if ((qic >= 5) && (qic <= 223))
+ {
+ str = "Reserved, treat as Validation and profile";
+ }
+ else
+ {
+ str = "Reserved for extension, treat as Validation and profile";
+ }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_feat_result(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Unsuccessful"; break;
+ case 2: str = "Successful"; break;
+ default:
+ if ((value >= 3) && (value <= 95)) { str = "Reserved, treat as Unsuccessful"; }
+ else if ((value >= 96) && (value <= 127)) { str = "Reserved, treat as Unsuccessful"; }
+ else if ((value >= 128) && (value <= 223)) { str = "Reserved, treat as Successful"; }
+ else { str = "Reserved for protocol extension, treat as Successful"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+gchar *calling_feat_ind_str[] = {
+ "Not used",
+ "Not authorized",
+ "Authorized but de-activated",
+ "Authorized and activated"
+};
+
+static void
+param_calling_feat_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Call Waiting Feature Activity (CW-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0xc0) >> 6]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Call Forwarding No Answer Feature Activity (CFNA-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x30) >> 4]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Call Forwarding Busy Feature Activity (CFB-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x0c) >> 2]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Call Forwarding Unconditional Feature Activity (CFU-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[value & 0x03]);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Call Transfer Feature Activity (CT-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0xc0) >> 6]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Voice Privacy Feature Activity (VP-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x30) >> 4]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Call Delivery Feature Activity (CD-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x0c) >> 2]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Three-Way Calling Feature Activity (3WC-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[value & 0x03]);
+
+ if (len == 2) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Calling Number ID Restriction Override Feature Activity (CNIROver-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0xc0) >> 6]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Calling Number ID Restriction Feature Activity (CNIR-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x30) >> 4]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Two number Calling Number ID Presentation Feature Activity (CNIP2-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x0c) >> 2]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : One number Calling Number ID Presentation Feature Activity (CNIP1-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[value & 0x03]);
+
+ if (len == 3) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : USCF divert to voice mail Feature Activity (USCFvm-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0xc0) >> 6]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Answer Hold Feature Activity (AH-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x30) >> 4]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Data Privacy Feature Activity (DP-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x0c) >> 2]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Priority Call Waiting Feature Activity (PCW-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[value & 0x03]);
+
+ if (len == 4) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : CDMA-Concurrent Service Feature Activity (CCS-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0xc0) >> 6]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : CDMA-Packet Data Service Feature Activity (CPDS-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x30) >> 4]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : USCF divert to network registered DN Feature Activity (USCFnr-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[(value & 0x0c) >> 2]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : USCF divert to mobile station provided DN Feature Activity (USCFms-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[value & 0x03]);
+
+ if (len == 5) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfc, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : TDMA Enhanced Privacy and Encryption Feature Activity (TDMA EPE-FA), %s",
+ bigbuf,
+ calling_feat_ind_str[value & 0x03]);
+
+ EXTRANEOUS_DATA_CHECK(len, 6);
+}
+
+static void
+param_usage_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Unspecified"; break;
+ case 1: str = "Sent-paid call"; break;
+ case 2: str = "3rd number bill"; break;
+ default:
+ str = "Reserved, treat as Unspecified";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s (%u)",
+ str,
+ value);
+}
+
+gchar *tdma_data_feat_ind_str[] = {
+ "Not used",
+ "Not authorized",
+ "Authorized but de-activated",
+ "Authorized and activated"
+};
+
+static void
+param_tdma_data_feat_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : STU-III Feature Activity (STUIII-FA), %s",
+ bigbuf,
+ tdma_data_feat_ind_str[(value & 0x30) >> 4]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : G3 Fax Feature Activity (G3FAX-FA), %s",
+ bigbuf,
+ tdma_data_feat_ind_str[(value & 0x0c) >> 2]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : ADS Feature Activity (ADS-FA), %s",
+ bigbuf,
+ tdma_data_feat_ind_str[value & 0x03]);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Triple Rate data Feature Activity (3RATE-FA), %s",
+ bigbuf,
+ tdma_data_feat_ind_str[(value & 0xc0) >> 6]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Double Rate data Feature Activity (2RATE-FA), %s",
+ bigbuf,
+ tdma_data_feat_ind_str[(value & 0x30) >> 4]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Full Rate data Feature Activity (FRATE-FA), %s",
+ bigbuf,
+ tdma_data_feat_ind_str[(value & 0x0c) >> 2]);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Half Rate data Feature Activity (HRATE-FA), %s",
+ bigbuf,
+ tdma_data_feat_ind_str[value & 0x03]);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_faulty(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+ gint idx;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ str = my_match_strval((guint32) value, ansi_param_1_strings, &idx);
+
+ if (NULL == str)
+ {
+ if (len < 2)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "Unrecognized parameter ID");
+ return;
+ }
+
+ asn1->offset = saved_offset;
+ asn1_uint32_value_decode(asn1, 2, &value);
+
+ str = my_match_strval((guint32) value, ansi_param_2_strings, &idx);
+
+ if (NULL == str)
+ {
+ if (len < 3)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "Unrecognized parameter ID");
+ return;
+ }
+
+ asn1->offset = saved_offset;
+ asn1_int32_value_decode(asn1, 3, &value);
+
+ str = my_match_strval((guint32) value, ansi_param_3_strings, &idx);
+
+ if (NULL == str)
+ {
+ if (((value >= 0x9FFF00) && (value <= 0x9FFF7F)) ||
+ ((value >= 0xBFFF00) && (value <= 0xBFFF7F)))
+ {
+ str = "Reserved for protocol extension";
+ }
+ else if (((value >= 0x9FFE76) && (value <= 0x9FFE7F)) ||
+ ((value >= 0xBFFE76) && (value <= 0xBFFE7F)))
+ {
+ str = "Reserved for National Network Use";
+ }
+ else
+ {
+ str = "Unrecognized parameter ID";
+ }
+ }
+ }
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, asn1->offset - saved_offset);
+}
+
+static void
+param_sys_type_code(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 sys_type_code;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &sys_type_code);
+
+ switch (sys_type_code)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "EDS"; break;
+ case 2: str = "Astronet"; break;
+ case 3: str = "Lucent Technologies"; break;
+ case 4: str = "Ericsson"; break;
+ case 5: str = "GTE"; break;
+ case 6: str = "Motorola"; break;
+ case 7: str = "NEC"; break;
+ case 8: str = "NORTEL"; break;
+ case 9: str = "NovAtel"; break;
+ case 10: str = "Plexsys"; break;
+ case 11: str = "Digital Equipment Corp"; break;
+ case 12: str = "INET"; break;
+ case 13: str = "Bellcore"; break;
+ case 14: str = "Alcatel SEL"; break;
+ case 15: str = "Compaq (Tandem)"; break;
+ case 16: str = "QUALCOMM"; break;
+ case 17: str = "Aldiscon"; break;
+ case 18: str = "Celcore"; break;
+ case 19: str = "TELOS"; break;
+ case 20: str = "ADI Limited (Stanilite)"; break;
+ case 21: str = "Coral Systems"; break;
+ case 22: str = "Synacom Technology"; break;
+ case 23: str = "DSC"; break;
+ case 24: str = "MCI"; break;
+ case 25: str = "NewNet"; break;
+ case 26: str = "Sema Group Telecoms"; break;
+ case 27: str = "LG Information and Communications"; break;
+ case 28: str = "CBIS"; break;
+ case 29: str = "Siemens"; break;
+ case 30: str = "Samsung Electronics"; break;
+ case 31: str = "ReadyCom Inc."; break;
+ case 32: str = "AG Communication Systems"; break;
+ case 33: str = "Hughes Network Systems"; break;
+ case 34: str = "Phoenix Wireless Group"; break;
+ default:
+ str = "Reserved/Unknown";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Vendor ID (%u) %s",
+ sys_type_code, str);
+}
+
+static void
+param_ext_sys_type_code(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 type;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &type);
+
+ switch (type)
+ {
+ case 0: str = "Not specified"; break;
+ case 1: str = "Serving MSC"; break;
+ case 2: str = "Home MSC"; break;
+ case 3: str = "Gateway MSC"; break;
+ case 4: str = "HLR"; break;
+ case 5: str = "VLR"; break;
+ case 6: str = "EIR (reserved)"; break;
+ case 7: str = "AC"; break;
+ case 8: str = "Border MSC"; break;
+ case 9: str = "Originating MSC"; break;
+ default:
+ if ((type >= 10) && (type <= 223)) { str = "Reserved, treat as Not specified"; }
+ else { str = "Reserved for protocol extension, treat as Not specified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Type (%u) %s",
+ type,
+ str);
+
+ param_sys_type_code(asn1, tree, len-1, add_string);
+}
+
+static void
+param_cdma_sea_win(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Value %u",
+ bigbuf,
+ value & 0x0f);
+}
+
+static void
+param_cdma_sea_param(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : CDMA Search Window, %u",
+ bigbuf,
+ value & 0x0f);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : T_ADD, %u",
+ bigbuf,
+ value & 0x3f);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : T_DROP, %u",
+ bigbuf,
+ value & 0x3f);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : T_TDROP, %u",
+ bigbuf,
+ value & 0xf0);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : T_COMP, %u",
+ bigbuf,
+ value & 0x0f);
+
+ EXTRANEOUS_DATA_CHECK(len, 4);
+}
+
+static void
+param_cdma_code_chan(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : CDMA Code Channel %u",
+ bigbuf,
+ value & 0x3f);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_chan_data(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 3);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : SAT Color Code %u",
+ bigbuf,
+ (value & 0xc0 >> 6));
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ (value & 0x20) ? "Reserved" : "Analog Band Class",
+ bigbuf);
+
+ switch ((value & 0x18) >> 3)
+ {
+ case 0: str = "DTX disabled (not active/acceptable)"; break;
+ case 1: str = "Reserved, treat as DTX disabled"; break;
+ case 2: str = "DTX-low mode (i.e., 8 dB below DTX active/acceptable)"; break;
+ case 3: str = "DTX mode active or acceptable"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x18, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value, 0x07, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Voice Mobile Attenuation Code (VMAC) %u",
+ bigbuf,
+ value & 0x07);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Channel Number %u",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 3);
+}
+
+static void
+param_cdma_plcm(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 6);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfc, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : CDMA Private Long Code Mask (PLCM) (MSB)",
+ bigbuf);
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len - 1,
+ "CDMA Private Long Code Mask (PLCM)");
+
+ asn1->offset += (len - 1);
+}
+
+static void
+param_ctrl_chan_data(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Digital Color Code (DCC)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x38, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x07, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Control Mobile Attenuation Code (CMAC)",
+ bigbuf);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Channel Number (CHNO), %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Supplementary Digital Color Codes (SDCC1)",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Supplementary Digital Color Codes (SDCC2)",
+ bigbuf);
+}
+
+static void
+param_cdma_chan_data(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, temp_int;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 8);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0x78, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Frame Offset (%u), %.2f ms",
+ bigbuf,
+ (value & 0x7800) >> 11,
+ ((value & 0x7800) >> 11) * 1.25);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0x07, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : CDMA Channel Number (MSB), %u",
+ bigbuf,
+ value & 0x07ff);
+
+ other_decode_bitfield_value(bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset+1, 1,
+ "%s : CDMA Channel Number (LSB)",
+ bigbuf);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ temp_int = (value & 0x7c) >> 2;
+ if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = band_class_str[temp_int];
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x7c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Band Class, %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Long Code Mask (MSB)",
+ bigbuf);
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset + 1, 1,
+ "%s : Long Code Mask",
+ bigbuf);
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset + 2, 1,
+ "%s : Long Code Mask",
+ bigbuf);
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset + 3, 1,
+ "%s : Long Code Mask",
+ bigbuf);
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset + 4, 1,
+ "%s : Long Code Mask",
+ bigbuf);
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset + 5, 1,
+ "%s : Long Code Mask (LSB)",
+ bigbuf);
+
+ if (len == 8) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : NP Extension",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x78, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Nominal Power, %u",
+ bigbuf,
+ (value & 0x78) >> 3);
+
+ other_decode_bitfield_value(bigbuf, value, 0x07, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Number Preamble, %u",
+ bigbuf,
+ value & 0x07);
+
+ if (len == 9) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Base Station Protocol Revision, %u",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 10);
+}
+
+static void
+param_namps_chan_data(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x1c) >> 2)
+ {
+ case 0: str = "Channel Data parameter SCC field applies"; break;
+ case 1: str = "Digital SAT Color Code 1 (ignore SCC field)"; break;
+ case 2: str = "Digital SAT Color Code 2 (ignore SCC field)"; break;
+ case 3: str = "Digital SAT Color Code 3 (ignore SCC field)"; break;
+ case 4: str = "Digital SAT Color Code 4 (ignore SCC field)"; break;
+ case 5: str = "Digital SAT Color Code 5 (ignore SCC field)"; break;
+ case 6: str = "Digital SAT Color Code 6 (ignore SCC field)"; break;
+ case 7: str = "Digital SAT Color Code 7 (ignore SCC field)"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x1c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Color Code Indicator (CCIndicator), %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Wide. 30 kHz AMPS voice channel"; break;
+ case 1: str = "Upper. 10 kHz NAMPS voice channel"; break;
+ case 2: str = "Middle. 10 kHz NAMPS voice channel"; break;
+ case 3: str = "Lower. 10 kHz NAMPS voice channel"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Narrow Analog Voice Channel Assignment (NAVCA), %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_cdma_ms_meas_chan_id(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, temp_int;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ temp_int = (value & 0xf800) >> 11;
+ if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = band_class_str[temp_int];
+ }
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0xf8, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Band Class, %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0x07, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : CDMA Channel Number (MSB), %u",
+ bigbuf,
+ value & 0x07ff);
+
+ other_decode_bitfield_value(bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset+1, 1,
+ "%s : CDMA Channel Number (LSB)",
+ bigbuf);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_tdma_chan_data(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 5);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x1f)
+ {
+ case 0: str = "Analog (not used if ChannelData is present)"; break;
+ case 1: str = "Assigned to timeslot 1, full rate"; break;
+ case 2: str = "Assigned to timeslot 2, full rate"; break;
+ case 3: str = "Assigned to timeslot 3, full rate"; break;
+ case 4: str = "Assigned to timeslots 1, 4 and 2, 5 Double rate"; break;
+ case 5: str = "Assigned to timeslots 1, 4 and 3, 6 Double rate"; break;
+ case 6: str = "Assigned to timeslots 2, 5 and 3, 6 Double rate"; break;
+ case 9: str = "Assigned to timeslot 1, half rate"; break;
+ case 10: str = "Assigned to timeslot 2, half rate"; break;
+ case 11: str = "Assigned to timeslot 3, half rate"; break;
+ case 12: str = "Assigned to timeslot 4, half rate"; break;
+ case 13: str = "Assigned to timeslot 5, half rate"; break;
+ case 14: str = "Assigned to timeslot 6, half rate"; break;
+ case 15: str = "Assigned to timeslot 1, 2, 3, 4, 5, 6 Triple rate"; break;
+ default:
+ str = "Reserved, treat as Analog";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Time Slot and Rate indicator (TSR), %s",
+ bigbuf,
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Digital Verification Color Code (DVCC) %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0xf0) >> 4)
+ {
+ case 0: str = "800 MHz"; break;
+ case 1: str = "1800 MHz"; break;
+ default:
+ str = "Reserved, treat as 800 MHz";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Hyper Band, %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Digital Mobile Attenuation Code (DMAC) %u",
+ bigbuf,
+ value & 0x0f);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Channel Number (MSB), %u",
+ bigbuf,
+ value);
+
+ other_decode_bitfield_value(bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset + 1, 1,
+ "%s : Channel Number (LSB)",
+ bigbuf);
+
+ EXTRANEOUS_DATA_CHECK(len, 5);
+}
+
+static void
+param_tdma_call_mode(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %sxtended modulation and framing",
+ bigbuf,
+ (value & 0x20) ? "E" : "No e");
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Other voice coding %sacceptable",
+ bigbuf,
+ (value & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Other DQPSK channel %sacceptable",
+ bigbuf,
+ (value & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Half rate digital traffic channel %sacceptable",
+ bigbuf,
+ (value & 0x04) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Full rate digital traffic channel %sacceptable",
+ bigbuf,
+ (value & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : AMPS channel %sacceptable",
+ bigbuf,
+ (value & 0x01) ? "" : "not ");
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_cdma_call_mode(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ if (len == 1)
+ {
+ /* assuming older spec. no IS-880 */
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+ }
+ else
+ {
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 450 MHz channel (Band Class 5) %sacceptable",
+ bigbuf,
+ (value & 0x80) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Korean PCS channel (Band Class 4) %sacceptable",
+ bigbuf,
+ (value & 0x40) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : JTACS channel (Band Class 3) %sacceptable",
+ bigbuf,
+ (value & 0x20) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : TACS channel (Band Class 2) %sacceptable",
+ bigbuf,
+ (value & 0x10) ? "" : "not ");
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : CDMA 1900 MHz channel (Band Class 1) %sacceptable",
+ bigbuf,
+ (value & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : NAMPS 800 MHz channel %sacceptable",
+ bigbuf,
+ (value & 0x04) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : AMPS 800 MHz channel %sacceptable",
+ bigbuf,
+ (value & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : CDMA 800 MHz channel (Band Class 0) %sacceptable",
+ bigbuf,
+ (value & 0x01) ? "" : "not ");
+
+ if (len == 1) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Secondary 800 MHz channel (Band Class 10) %sacceptable",
+ bigbuf,
+ (value & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 900 MHz channel (Band Class 9) %sacceptable",
+ bigbuf,
+ (value & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1800 MHz channel (Band Class 8) %sacceptable",
+ bigbuf,
+ (value & 0x04) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 700 MHz channel (Band Class 7) %sacceptable",
+ bigbuf,
+ (value & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 2 GHz channel (Band Class 6) %sacceptable",
+ bigbuf,
+ (value & 0x01) ? "" : "not ");
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_namps_call_mode(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ ".... %u... : AMPS 1800 MHz channel %sacceptable",
+ (value & 0x08) >> 3, (value & 0x08) ? "" : "not ");
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ ".... .%u.. : NAMPS 1800 MHz channel %sacceptable",
+ (value & 0x04) >> 2, (value & 0x04) ? "" : "not ");
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ ".... ..%u. : AMPS 800 MHz channel %sacceptable",
+ (value & 0x02) >> 1, (value & 0x02) ? "" : "not ");
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ ".... ...%u : NAMPS 800 MHz channel %sacceptable",
+ value & 0x01, (value & 0x01) ? "" : "not ");
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_mob_rev(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Revision %u",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_cdma_band_class(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, temp_int;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ temp_int = value & 0x1f;
+ if ((temp_int < 0) || (temp_int >= (gint) NUM_BAND_CLASS_STR))
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = band_class_str[temp_int];
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Band Class %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_calling_party_name(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Spec. has hardcoded as 0 0 1",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Availability, %s",
+ bigbuf,
+ (value & 0x10) ? "Name not available" : "Name available/unknown");
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Presentation allowed"; break;
+ case 1: str = "Presentation restricted"; break;
+ case 2: str = "Blocking toggle"; break;
+ case 3: str = "No indication"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Presentation Status, %s",
+ bigbuf,
+ str);
+
+ if (len == 1) return;
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len - 1,
+ "IA5 Digits");
+
+ asn1->offset += (len - 1);
+}
+
+static void
+param_red_party_name(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Spec. has hardcoded as 0 1 1",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Availability, %s",
+ bigbuf,
+ (value & 0x10) ? "Name not available" : "Name available/unknown");
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Presentation allowed"; break;
+ case 1: str = "Presentation restricted"; break;
+ case 2: str = "Blocking toggle"; break;
+ case 3: str = "No indication"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Presentation Status, %s",
+ bigbuf,
+ str);
+
+ if (len == 1) return;
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len - 1,
+ "IA5 Digits");
+
+ asn1->offset += (len - 1);
+}
+
+static void
+param_srvc_id(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+
+ add_string = add_string;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len,
+ "Service Identifier (Spec. does not define clearly)");
+
+ asn1->offset += len;
+}
+
+static void
+param_all_or_none(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "All changes must succeed or none should be applied"; break;
+ case 2: str = "Treat each change independently"; break;
+ default:
+ if ((value >= 3) && (value <= 223)) { str = "Reserved, treat as All changes must succeed or none should be applied"; }
+ else { str = "Reserved for protocol extension, treat as All changes must succeed or none should be applied"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_change(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Set Data Item to Default Value"; break;
+ case 2: str = "Add Data Item"; break;
+ case 3: str = "Delete Data Item"; break;
+ case 4: str = "Replace Data Item with associated DataValue"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, treat as Set Data Item to Default Value"; }
+ else { str = "Reserved for protocol extension, treat as Set Data Item to Default Value"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_data_result(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Successful"; break;
+ case 2: str = "Unsuccessful, unspecified"; break;
+ case 3: str = "Unsuccessful, no default value available"; break;
+ default:
+ if ((value >= 4) && (value <= 95)) { str = "Reserved, treat as Unsuccessful"; }
+ else if ((value >= 96) && (value <= 127)) { str = "Reserved for protocol extension, treat as Unsuccessful"; }
+ else if ((value >= 128) && (value <= 223)) { str = "Reserved, treat as Successful"; }
+ else { str = "Reserved for protocol extension, treat as Successful"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_fail_cause(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "ISUP Cause Indicator");
+
+ asn1->offset += len;
+}
+
+static void
+param_fail_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Call abandoned"; break;
+ case 2: str = "Resource disconnect"; break;
+ case 3: str = "Failure at MSC"; break;
+ case 4: str = "SSFT expiration"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, ignore"; }
+ else { str = "Reserved for protocol extension, ignore"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_resume_pic(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Continue Call Processing"; break;
+ case 2: str = "Collect Information PIC"; break;
+ case 3: str = "Analyze Information PIC"; break;
+ case 4: str = "Select Route PIC"; break;
+ case 5: str = "Authorize Origination_Attempt PIC"; break;
+ case 6: str = "Authorize Call Setup PIC"; break;
+ case 7: str = "Send Call PIC"; break;
+ case 8: str = "O Alerting PIC"; break;
+ case 9: str = "O Active PIC"; break;
+ case 10: str = "O Suspended PIC"; break;
+ case 11: str = "O Null PIC"; break;
+ case 32: str = "Select Facility PIC"; break;
+ case 33: str = "Present Call PIC"; break;
+ case 34: str = "Authorize Termination Attempt PIC"; break;
+ case 35: str = "T Alerting PIC"; break;
+ case 36: str = "T Active PIC"; break;
+ case 37: str = "T Suspended PIC"; break;
+ case 38: str = "T Null PIC"; break;
+ default:
+ if ((value >= 12) && (value <= 31)) { str = "Reserved, treat as Not used"; }
+ else if ((value >= 39) && (value <= 223)) { str = "Reserved, ignore"; }
+ else { str = "Reserved for protocol extension, ignore"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Point in Call, %s (%u)",
+ str,
+ value);
+}
+
+static void
+param_special_rsc(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, i;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ i = 0;
+
+ do
+ {
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "DTMF tone detector"; break;
+ case 2: str = "Automatic Speech Recognition - Speaker Independent - Digits"; break;
+ case 3: str = "Automatic Speech Recognition - Speaker Independent - Speech User Interface Version 1"; break;
+ default:
+ if ((value >= 4) && (value <= 223)) { str = "Reserved, treat as Not used"; }
+ else { str = "Reserved for protocol extension, treat as Not used"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "[%u] Resource Type, %s",
+ i++,
+ str);
+
+ saved_offset = asn1->offset;
+ }
+ while ((len - i) > 0);
+}
+
+static void
+param_time_date_offset(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "In minutes (%u)",
+ value);
+}
+
+static void
+param_network_tmsi(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, addr_type, first_dig;
+ guint saved_offset;
+ gchar *str = NULL;
+ guchar *poctets;
+
+ SHORT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 4, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "TMSI Code, %u",
+ value);
+
+ if (len == 4) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ first_dig = Dgt_tbcd.out[(value & 0xf0) >> 4];
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : First digit of TMSI Zone, %c",
+ bigbuf,
+ first_dig);
+
+ addr_type = value & 0x0f;
+ switch (addr_type)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "E.212 based routing"; break;
+ case 2: str = "20-bit TDMA TMSI"; break;
+ case 3: str = "24-bit TDMA TMSI"; break;
+ default:
+ str = "Reserved for protocol extension, treat as Not used";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Type of addressing, %s",
+ bigbuf,
+ str);
+
+ if (len == 5) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_string_value_decode(asn1, (len-5), &poctets);
+
+ bigbuf[0] = first_dig;
+
+ my_dgt_tbcd_unpack(bigbuf+1, poctets, (len-5), &Dgt_tbcd);
+ g_free(poctets);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset - 1, (len-5)+1,
+ "TMSI Zone, %s",
+ bigbuf);
+}
+
+static void
+param_reqd_param_mask(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Location Area ID (LOCID) %srequired",
+ bigbuf,
+ (value & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : TMSI %srequired",
+ bigbuf,
+ (value & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : ESN %srequired",
+ bigbuf,
+ (value & 0x04) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : MIN %srequired",
+ bigbuf,
+ (value & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : IMSI %srequired",
+ bigbuf,
+ (value & 0x01) ? "" : "not ");
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_srvc_red_cause(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Normal Registration"; break;
+ case 2: str = "System Not Found"; break;
+ case 3: str = "Protocol Mismatch"; break;
+ case 4: str = "Registration Rejection"; break;
+ case 5: str = "Wrong SID"; break;
+ case 6: str = "Wrong NID"; break;
+ default:
+ if ((value >= 7) && (value <= 223)) { str = "Reserved, treat as Normal Registration"; }
+ else { str = "Reserved for protocol extension. If unknown, treat as Normal Registration"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_srvc_red_info(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfc, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : NDSS Status (NDS), %ssuppressed",
+ bigbuf,
+ (value & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Return If Fail (RIF), If MS fails to access the redirected system, MS shall %sreturn to the serving system",
+ bigbuf,
+ (value & 0x01) ? "" : "not ");
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_roaming_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Roaming Indicator On"; break;
+ case 1: str = "Roaming Indicator Off"; break;
+ case 2: str = "Roaming Indicator Flashing"; break;
+ case 3: str = "Out of Neighborhood"; break;
+ case 4: str = "Out of Building"; break;
+ case 5: str = "Roaming - Preferred System"; break;
+ case 6: str = "Roaming - Available System"; break;
+ case 7: str = "Roaming - Alliance Partner"; break;
+ case 8: str = "Roaming - Premium Partner"; break;
+ case 9: str = "Roaming - Full Service Functionality"; break;
+ case 10: str = "Roaming - Partial Service Functionality"; break;
+ case 11: str = "Roaming Banner On"; break;
+ case 12: str = "Roaming Banner Off"; break;
+ default:
+ if ((value >= 13) && (value <= 63)) { str = "Reserved for Standard Enhanced Roaming Indicator Numbers"; }
+ else if ((value >= 64) && (value <= 127)) { str = "Reserved for Non-Standard Enhanced Roaming Indicator Numbers"; }
+ else { str = "Reserved"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_cdma_pci(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfe, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : CDMA PWR_COMB_IND",
+ bigbuf);
+}
+
+static void
+param_cdma_chan_num(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0xf8, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0x07, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : CDMA Channel Number (MSB) %u",
+ bigbuf,
+ value & 0x07ff);
+
+ other_decode_bitfield_value(bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset+1, 1,
+ "%s : CDMA Channel Number (LSB)",
+ bigbuf);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_cdma_sci(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf8, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x07, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Slot Cycle Index, %u",
+ bigbuf,
+ (value & 0x07));
+}
+
+static void
+param_vp_report(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Voice Privacy not attempted"; break;
+ case 2: str = "Voice Privacy no response"; break;
+ case 3: str = "Voiec Privacy successful is active"; break;
+ case 4: str = "Voice Privacy failed"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, treat as Voice Privacy not attempted"; }
+ else { str = "Reserved for protocol extension, treat as Voice Privacy not attempted"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s (%u)",
+ str,
+ value);
+}
+
+static void
+param_cdma_scm(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Dual-mode Indicator, %s",
+ bigbuf,
+ (value & 0x40) ? "Dual mode CDMA" : "CDMA only");
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Slotted mode Indicator, %s",
+ bigbuf,
+ (value & 0x20) ? "slotted capable" : "slotted incapable");
+
+ other_decode_bitfield_value(bigbuf, value, 0x18, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Analog Transmission, %s",
+ bigbuf,
+ (value & 0x04) ? "discontinuous" : "continuous");
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Power Class I"; break;
+ case 1: str = "Power Class II"; break;
+ case 2: str = "Power Class III"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_ota_result_code(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Accepted - Successful"; break;
+ case 1: str = "Rejected - Unknown cause"; break;
+ case 2: str = "Computation Failure - E.g., unable to compute A-key"; break;
+ case 3: str = "CSC Rejected - CSC challenge failure"; break;
+ case 4: str = "Unrecognized OTASPCallEntry"; break;
+ case 5: str = "Unsupported AKeyProtocolVersion(s)"; break;
+ case 6: str = "Unable to Commit"; break;
+ default:
+ if ((value >= 7) && (value <= 223)) { str = "Reserved, treat as Rejected - Unknown cause"; }
+ else { str = "Reserved for protocol extension, treat as Rejected - Unknown cause"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s (%u)",
+ str,
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_cdma_scm2(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Value %u",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_tdma_term_cap(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1800 MHz F channel %sacceptable",
+ bigbuf,
+ (value & 0x40) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1800 MHz E channel %sacceptable",
+ bigbuf,
+ (value & 0x20) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1800 MHz D channel %sacceptable",
+ bigbuf,
+ (value & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1800 MHz C channel %sacceptable",
+ bigbuf,
+ (value & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1800 MHz B channel %sacceptable",
+ bigbuf,
+ (value & 0x04) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s acceptable",
+ bigbuf,
+ (value & 0x02) ? "1800 MHz A channel" : "1800 MHz A&B Digital channel not");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 800 MHz A&B channel %sacceptable",
+ bigbuf,
+ (value & 0x01) ? "" : "not ");
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfc, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : IS-641 Voice Coder %sacceptable",
+ bigbuf,
+ (value & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : VSELP Voice Coder %sacceptable",
+ bigbuf,
+ (value & 0x01) ? "" : "not ");
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "EIA-553 or IS-54-A"; break;
+ case 1: str = "TIA/EIA-627 (IS-54-B)"; break;
+ case 2: str = "IS-136"; break;
+ case 3: str = "Reserved (ANSI J-STD-011)"; break;
+ case 4: str = "PV 0 as published in TIA/EIA-136-0 and IS-136-A"; break;
+ case 5: str = "PV 1 as published in TIA/EIA-136-A"; break;
+ case 6: str = "PV 2 as published in TIA/EIA-136-A"; break;
+ case 7: str = "PV 3 as published in TIA/EIA-136-A"; break;
+ default:
+ str = "Reserved, treat as EIA-553 or IS-54-A";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "Protocol Version, %s",
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Triple Rate (3RATE) %ssupported",
+ bigbuf,
+ (value & 0x80) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Double Rate (2RATE) %ssupported",
+ bigbuf,
+ (value & 0x40) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Full Rate (FRATE) %ssupported",
+ bigbuf,
+ (value & 0x20) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Half Rate (HRATE) %ssupported",
+ bigbuf,
+ (value & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Analog Voice (AVOX) %ssupported",
+ bigbuf,
+ (value & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Secure Telephone Unit III (STU3) %ssupported",
+ bigbuf,
+ (value & 0x04) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Group 3 Fax (G3FAX) %ssupported",
+ bigbuf,
+ (value & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Asynchronous Data (ADS) %ssupported",
+ bigbuf,
+ (value & 0x01) ? "" : "not ");
+
+ EXTRANEOUS_DATA_CHECK(len, 4);
+}
+
+static void
+param_tdma_voice_coder(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, vc;
+ guint orig_offset, saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+
+ do
+ {
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ vc = (value & 0x0f);
+ switch (vc)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "VSELP Voice Coder acceptable"; break;
+ case 2: str = "IS-641 Voice Coder acceptable"; break;
+ case 6: str = "Reserved for SOC/BSMC Specific signaling. If unknown, use any acceptable value"; break;
+ default:
+ if ((vc >= 3) && (vc <= 5)) { str = "Reserved. Ignore on reception, use any acceptable value"; }
+ else if ((vc >= 7) && (vc <= 12)) { str = "Reserved. Ignore on reception, use any acceptable value"; }
+ else if ((vc >= 13) && (vc <= 15)) { str = "Reserved for protocol extension. If unknown, use any acceptable value"; }
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Voice Coder, %s",
+ bigbuf,
+ str);
+
+ saved_offset = asn1->offset;
+ }
+ while ((len - (saved_offset - orig_offset)) > 0);
+}
+
+static void
+param_cdma_pilot_pn(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0xfe, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Pilot PN (MSB), %u",
+ bigbuf, value & 0x01ff);
+
+ other_decode_bitfield_value(bigbuf, value & 0x00ff, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset + 1, 1,
+ "%s : Pilot PN (LSB)",
+ bigbuf);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_cdma_pilot_strength(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Value %u",
+ bigbuf,
+ value & 0x3f);
+}
+
+static void
+param_trunk_stat(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Idle"; break;
+ case 1: str = "Blocked"; break;
+ default:
+ if ((value >= 2) && (value <= 223)) { str = "Reserved, treat as ERROR or Blocked"; }
+ else { str = "Reserved for protocol extension, treat as ERROR or Blocked"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Trunk Status, %s",
+ str);
+}
+
+static void
+param_pref_lang_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Unspecified"; break;
+ case 1: str = "English"; break;
+ case 2: str = "French"; break;
+ case 3: str = "Spanish"; break;
+ case 4: str = "German"; break;
+ case 5: str = "Portuguese"; break;
+ default:
+ str = "Reserved, treat as Unspecified";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Preferred Language, %s",
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_rand_valtime(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ if (value == 0)
+ {
+ str = "RAND shall not be stored";
+ }
+ else
+ {
+ sprintf(bigbuf, "RAND may be used for %u minutes", value);
+ str = bigbuf;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_tdma_burst_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x7c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Time Alignment Offset (TA), %u",
+ bigbuf,
+ (value & 0x7c) >> 2);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Transmit normal burst after cell-to-cell handoff"; break;
+ case 1: str = "Transmit normal burst after handoff within cell"; break;
+ case 2: str = "Transmit shortened burst after cell-to-cell handoff"; break;
+ case 3: str = "Reserved, treat with RETURN ERROR"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Burst Code, %s",
+ bigbuf,
+ str);
+}
+
+static void
+param_orig_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Prior agreement"; break;
+ case 2: str = "Origination denied"; break;
+ case 3: str = "Local calls only"; break;
+ case 4: str = "Selected leading digits of directory number or of international E.164 number, see Digits(Destination)"; break;
+ case 5: str = "Selected leading digits of directory number or of international E.164 number and local calls only, see Digits(Destination)"; break;
+ case 6: str = "National long distance"; break;
+ case 7: str = "International calls"; break;
+ case 8: str = "Single directory number or international E.164 number, see Digits(Destination)"; break;
+ default:
+ if ((value >= 9) && (value <= 223)) { str = "Reserved, treat as Local calls only"; }
+ else { str = "Reserved for protocol extension, treat as Local calls only"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Allowed Call Types, %s",
+ str);
+}
+
+static void
+param_ms_loc(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 7);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 3, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Latitude in tenths of a second, %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 3, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Longitude in tenths of a second, %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, MIN(len - 6, 2), &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Resolution in units of 1 foot, %u",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 8);
+}
+
+static void
+param_unique_chal_rep(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Unique Challenge not attempted"; break;
+ case 2: str = "Unique Challenge no response"; break;
+ case 3: str = "Unique Challenge successful"; break;
+ case 4: str = "Unique Challenge failed"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, treat as Unique Challenge not attempted"; }
+ else { str = "Reserved for protocol extension, treat as Unique Challenge not attempted"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_rand_unique(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 3);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "24-bit random number used as input to the CAVE algorithm for authenticating a specific MS");
+
+ asn1->offset += len;
+}
+
+static void
+param_vpmask(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 66);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Voice Privacy Mask-A (VPMASK-A) (MSB)",
+ bigbuf);
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 32,
+ "Voice Privacy Mask-A (VPMASK-A)");
+
+ asn1->offset += 32;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Voice Privacy Mask-B (VPMASK-B) (MSB)",
+ bigbuf);
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 32,
+ "Voice Privacy Mask-B (VPMASK-B)");
+
+ asn1->offset += 32;
+}
+
+static void
+param_ssd(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 16);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 8,
+ "Shared Secret Data-A (SSD-A)");
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset+8, 8,
+ "Shared Secret Data-B (SSD-B)");
+
+ asn1->offset += len;
+}
+
+static void
+param_upd_count(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Update COUNT"; break;
+ default:
+ if ((value >= 2) && (value <= 223)) { str = "Reserved, treat as Update COUNT"; }
+ else { str = "Reserved for protocol extension, treat as Update COUNT"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s",
+ str);
+}
+
+static void
+param_sme_key(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 8);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "Signaling Message Encryption Key (SMEKEY)");
+
+ asn1->offset += len;
+}
+
+static void
+param_rand_ssd(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 7);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "56-bit random number used as input to the CAVE algorithm for generating Shared Secret Data");
+
+ asn1->offset += len;
+}
+
+static void
+param_setup_result(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Unsuccessful"; break;
+ case 2: str = "Successful"; break;
+ default:
+ str = "Reserved, treat as Unsuccessful";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_randc(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "The 8 most significant bits of the 32-bit Random Variable used to compute the Authentication Response");
+
+ asn1->offset += 1;
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_ext_mscid(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 type;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 4);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &type);
+
+ switch (type)
+ {
+ case 0: str = "Not specified"; break;
+ case 1: str = "Serving MSC"; break;
+ case 2: str = "Home MSC"; break;
+ case 3: str = "Gateway MSC"; break;
+ case 4: str = "HLR"; break;
+ case 5: str = "VLR"; break;
+ case 6: str = "EIR (reserved)"; break;
+ case 7: str = "AC"; break;
+ case 8: str = "Border MSC"; break;
+ case 9: str = "Originating MSC"; break;
+ default:
+ if ((type >= 10) && (type <= 223)) { str = "Reserved, treat as Not specified"; }
+ else { str = "Reserved for protocol extension, treat as Not specified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Type (%u), %s",
+ type,
+ str);
+
+ param_mscid(asn1, tree, len-1, add_string);
+}
+
+static void
+param_sub_addr(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Should be 1",
+ bigbuf);
+
+ switch ((value & 0x70) >> 4)
+ {
+ case 0x00: str = "NSAP (CCITT Rec. X.213 or ISO 8348 AD2)"; break;
+ case 0x02: str = "User specified"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x70, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Type of Subaddress %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Even number of subaddress signals follow"; break;
+ case 0x01: str = "Odd number of subaddress signals follow"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len - 1,
+ "Subaddress");
+
+ asn1->offset += len - 1;
+}
+
+static void
+param_digits(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, b1, b2, b3, b4, enc, plan;
+ guint saved_offset;
+ gchar *str = NULL;
+ proto_item *item;
+ proto_tree *subtree;
+ guchar *poctets;
+
+ SHORT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Dialed Numer or Called Party Number"; break;
+ case 2: str = "Calling Party Number"; break;
+ case 3: str = "Caller Interaction (Not used)"; break;
+ case 4: str = "Routing Number"; break;
+ case 5: str = "Billing Number"; break;
+ case 6: str = "Destination Number"; break;
+ case 7: str = "LATA (Not used)"; break;
+ case 8: str = "Carrier"; break;
+ case 13: str = "ESRD"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Type of Digits %u: %s",
+ value, str);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Nature of Number");
+
+ subtree = proto_item_add_subtree(item, ett_natnum);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x30) >> 4)
+ {
+ case 0x00: str = "User provided, not screened"; break;
+ case 0x01: str = "User provided, screening passed"; break;
+ case 0x02: str = "User provided, screening failed"; break;
+ case 0x03: str = "Network provided"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x30, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ ".... %u... : Reserved",
+ (value & 0x08) >> 3);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ ".... .%u.. : Number is %savailable",
+ (value & 0x04) >> 2, (value & 0x04) ? "not " : "");
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ ".... ..%u. : Presentation %s",
+ (value & 0x02) >> 1, (value & 0x02) ? "Restricted" : "Allowed");
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ ".... ...%u : %s",
+ value & 0x01, (value & 0x01) ? "International" : "National");
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ plan = (value & 0xf0) >> 4;
+ switch (plan)
+ {
+ case 0x00: str = "Unknown or not applicable"; break;
+ case 0x01: str = "ISDN Numbering (Not used)"; break;
+ case 0x02: str = "Telephony Numbering (ITU-T Rec. E.164, E.163)"; break;
+ case 0x03: str = "Data Numbering (ITU-T Rec. X.121)(Not used)"; break;
+ case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)(Not used)"; break;
+ case 0x05: str = "Maritime Mobile Numbering (Not used)"; break;
+ case 0x06: str = "Land Mobile Numbering (ITU-T Rec. E.212)"; break;
+ case 0x07: str = "Private Numbering Plan (service provider defined)"; break;
+ case 0x0d: str = "ANSI SS7 Point Code (PC) and Subsystem Number (SSN)"; break;
+ case 0x0e: str = "Internet Protocol (IP) Address"; break;
+ case 0x0f: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Numbering Plan: %s",
+ bigbuf, str);
+
+ enc = value & 0x0f;
+ switch (enc)
+ {
+ case 0x00: str = "Not used"; break;
+ case 0x01: str = "BCD"; break;
+ case 0x02: str = "IA5"; break;
+ case 0x03: str = "Octet String"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Encoding: %s",
+ bigbuf, str);
+
+ saved_offset = asn1->offset;
+
+ if (plan == 0x0d)
+ {
+ asn1_int32_value_decode(asn1, 1, &b1);
+ asn1_int32_value_decode(asn1, 1, &b2);
+ asn1_int32_value_decode(asn1, 1, &b3);
+ asn1_int32_value_decode(asn1, 1, &b4);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Point Code %u-%u-%u SSN %u",
+ b3, b2, b1, b4);
+ }
+ else if (plan == 0x0e)
+ {
+ asn1_int32_value_decode(asn1, 1, &b1);
+ asn1_int32_value_decode(asn1, 1, &b2);
+ asn1_int32_value_decode(asn1, 1, &b3);
+ asn1_int32_value_decode(asn1, 1, &b4);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "IP Address %u.%u.%u.%u",
+ b1, b2, b3, b4);
+ }
+ else
+ {
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Number of Digits: %u",
+ value);
+
+ if (enc == 0x02)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, value,
+ "IA5 Digits: %s",
+ tvb_format_text(asn1->tvb, asn1->offset, value));
+
+ asn1->offset += value;
+ }
+ else if (enc == 0x01)
+ {
+ saved_offset = asn1->offset;
+ asn1_string_value_decode(asn1, (value+1)/2, &poctets);
+
+ my_dgt_tbcd_unpack(bigbuf, poctets, (value+1)/2, &Dgt_tbcd);
+ g_free(poctets);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, (value+1)/2,
+ "BCD Digits: %s",
+ bigbuf);
+ }
+ }
+}
+
+static void
+param_esn(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 4, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "ESN 0x%04x",
+ value);
+
+ sprintf(add_string, " - 0x%04x", value);
+}
+
+static void
+param_sms_noti(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Notify when available"; break;
+ case 2: str = "Do not notify when available"; break;
+ default:
+ if ((value >= 3) && (value <= 127)) { str = "Reserved, treat as Notify when available"; }
+ else if ((value >= 128) && (value <= 223)) { str = "Reserved, treat as Do not notify when available"; }
+ else { str = "Reserved for protocol extension"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s (%u)",
+ str,
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_sms_orig_restric(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x08)
+ {
+ case 0x00: str = "No effect"; break;
+ default:
+ str = "Force indirect";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Force Message Center, %s",
+ bigbuf, str);
+
+ switch (value & 0x04)
+ {
+ case 0x00: str = "Block direct"; break;
+ default:
+ str = "Allow direct";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : DIRECT, %s",
+ bigbuf, str);
+
+ switch (value & 0x03)
+ {
+ case 0x00: str = "Block all"; break;
+ case 0x02: str = "Allow specific"; break;
+ case 0x03: str = "Allow all"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : DEFAULT, %s",
+ bigbuf, str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_seizure(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Unspecified"; break;
+ case 1: str = "Loopback"; break;
+ default:
+ if ((value >= 2) && (value <= 223)) { str = "Reserved"; }
+ else { str = "Reserved for protocol extension"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_sms_tele(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ ansi_map_sms_tele_id = -1;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ str = match_strval(value, ansi_tele_strings);
+ if (str == NULL)
+ {
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ default:
+ if ((value >= 2) && (value <= 4095)) { str = "Reserved for assignment by TIA/EIA-41"; }
+ else if ((value >= 4100) && (value <= 32512)) { str = "Reserved for assignment by TIA/EIA-41"; }
+ else if ((value >= 32514) && (value <= 32639)) { str = "Reserved for assignment by this Standard for TDMA MS-based SMEs."; }
+ else if ((value >= 32640) && (value <= 32767)) { str = "Reserved for carrier specific teleservices for TDMA MS-based SMEs."; }
+ else if ((value >= 32768) && (value <= 49151)) { str = "Reserved for node specific teleservices."; }
+ else if ((value >= 49152) && (value <= 65535)) { str = "Reserved for carrier specific teleservices."; }
+ else { str = "Unknown teleservice ID"; }
+ break;
+ }
+ }
+
+ ansi_map_sms_tele_id = value;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s (%u)",
+ str,
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_sms_term_restric(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf8, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x04)
+ {
+ case 0x00: str = "Block messages charged to destination"; break;
+ default:
+ str = "Allow messages charged to destination";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reverse Charges, %s",
+ bigbuf, str);
+
+ switch (value & 0x03)
+ {
+ case 0x00: str = "Block all"; break;
+ case 0x02: str = "Allow specific"; break;
+ case 0x03: str = "Allow all"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : DEFAULT, %s",
+ bigbuf, str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_sms_msg_count(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "No more pending SMS messages"; break;
+ default:
+ sprintf(bigbuf, "%u pending SMS messages", value);
+ str = bigbuf;
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_qos_pri(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, temp_int;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ temp_int = (value & 0xf0) >> 4;
+ if ((temp_int < 0) || (temp_int >= (gint) NUM_QOS_PRI_STR))
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = qos_pri_str[temp_int];
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Assured Priority, %s",
+ bigbuf,
+ str);
+
+ temp_int = value & 0x0f;
+ if ((temp_int < 0) || (temp_int >= (gint) NUM_QOS_PRI_STR))
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = qos_pri_str[temp_int];
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Non-Assured Priority, %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_calling_party_cat(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Calling Party's Category, Refer to ITU-T Q.763 (Signalling System No. 7 ISDN user part formats and codes) for encoding of this parameter");
+}
+
+/*
+ * Dissect IOS data parameters expected to be in TLV format
+ */
+static void
+dissect_cdma2000_ios_data(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint num_elems;
+ guchar elem_len;
+ guint32 orig_offset, saved_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+ gint idx;
+
+ num_elems = 0;
+ orig_offset = saved_offset = asn1->offset;
+
+ while ((saved_offset - orig_offset + 2) <= len)
+ {
+ num_elems++;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+ str = my_match_strval((guint32) value, ansi_a_ios401_elem_1_strings, &idx);
+
+ asn1_octet_decode(asn1, &elem_len);
+
+ item =
+ proto_tree_add_text(tree,
+ asn1->tvb, saved_offset, elem_len + 2,
+ "IOS - %s",
+ str);
+
+ subtree = proto_item_add_subtree(item, ett_ansi_map_ios401_elem[idx]);
+
+ proto_tree_add_none_format(subtree, hf_ansi_map_ios401_elem_id, asn1->tvb,
+ saved_offset, 1, "Element ID");
+
+ proto_tree_add_uint(subtree, hf_ansi_map_length, asn1->tvb,
+ saved_offset + 1, 1, elem_len);
+
+ if (elem_len > 0)
+ {
+ proto_tree_add_text(subtree,
+ asn1->tvb, saved_offset + 2, elem_len,
+ "Element Value");
+
+ asn1->offset += elem_len;
+ }
+
+ saved_offset += elem_len + 2;
+ }
+
+ sprintf(add_string, " - (%u)", num_elems);
+
+ EXTRANEOUS_DATA_CHECK((len - (saved_offset - orig_offset)), 0);
+}
+
+static void
+param_cdma2000_ho_ivk_ios(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+
+ dissect_cdma2000_ios_data(asn1, tree, len, add_string);
+}
+
+static void
+param_cdma2000_ho_rsp_ios(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+
+ dissect_cdma2000_ios_data(asn1, tree, len, add_string);
+}
+
+static void
+param_msid_usage(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfc, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "MIN last used"; break;
+ case 2: str = "IMSI last used"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_new_min_ext(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 3);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : MCC_M (MSB), see CDMA",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x0e, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : IMSI_M_ADDR_NUM, see CDMA",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : IMSI_M_CLASS, see CDMA",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+
+ bigbuf[0] = Dgt_tbcd.out[(value & 0xf0) >> 4];
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ bigbuf[1] = Dgt_tbcd.out[value & 0x0f];
+ bigbuf[2] = Dgt_tbcd.out[(value & 0xf0) >> 4];
+ bigbuf[3] = '\0';
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "MCC_M, %s, see CDMA",
+ bigbuf);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ bigbuf[0] = Dgt_tbcd.out[value & 0x0f];
+ bigbuf[1] = Dgt_tbcd.out[(value & 0xf0) >> 4];
+ bigbuf[2] = '\0';
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "IMSI_11_12, %s, see CDMA",
+ bigbuf);
+}
+
+static void
+param_dtx_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfe, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x01)
+ {
+ case 0: str = "Discontinuous Transmission mode is not active"; break;
+ case 1: str = "Discontinuous Transmission mode is active"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_cdma_mob_cap(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfe, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x01)
+ {
+ case 0: str = "No MS-initiated position determination"; break;
+ case 1: str = "MS-initiated position determination"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_gen_time(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ gint32 h, m, s, ts;
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 6);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Year-2000, %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Month, %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Day of month, %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 3, &value);
+
+ h = value / (3600 * 10);
+ m = (value - (h * (3600 * 10))) / (60 * 10);
+ s = (value - (h * (3600 * 10)) - (m * (60 * 10))) / 10;
+ ts = (value - (h * (3600 * 10)) - (m * (60 * 10)) - (s * 10));
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Time of day (UTC) (in tenths of seconds - 1), %u (%u:%u:%u.%u)",
+ value,
+ h,
+ m,
+ s,
+ ts);
+
+ EXTRANEOUS_DATA_CHECK(len, 6);
+}
+
+static void
+param_geo_pos(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "Calling Geodetic Location (CGL), see T1.628 CallingGeodeticLocation TCAP parameter for encoding");
+}
+
+static void
+param_mob_call_status(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, auth;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ auth = (value & 0xf0) >> 4;
+ switch (auth)
+ {
+ case 0: str = "Authorization not performed"; break;
+ case 1: str = "Authorization successful"; break;
+ case 2: str = "Invalid Electronic Serial Number (ESN)"; break;
+ case 3: str = "Unassigned Directory Number (DN)"; break;
+ case 4: str = "Duplicate Unit"; break;
+ case 5: str = "Delinquent Account"; break;
+ case 6: str = "Stolen Unit"; break;
+ case 7: str = "Not authorized for MSC"; break;
+ case 8: str = "Unspecified"; break;
+ default:
+ str = "Reserved, treat as Authorization not performed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Authorization, %s",
+ bigbuf,
+ str);
+
+ auth = value & 0x0f;
+ switch (auth)
+ {
+ case 0: str = "Authentication not performed. Authentication has not yet occurred or the MS is not capable of authentication"; break;
+ case 1: str = "Authentication successful. Authentication has successfully occurred on the MS"; break;
+ case 2: str = "Authentication failure. An authentication failure has occurred on the MS"; break;
+ default:
+ str = "Reserved, treat as Authentication not performed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Authentication, %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_pos_req_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Initial position. Return updated position only if initial position is unavailable."; break;
+ case 2: str = "Return the updated position"; break;
+ case 3: str = "Return the updated or last known position"; break;
+ case 4: str = "Reserved for LSP interface. Treat as Not used"; break;
+ default:
+ if ((value >= 5) && (value <= 95)) { str = "Reserved, treat as Initial position"; }
+ else { str = "Reserved for protocol extension, treat as Initial position"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Position Request Type, %s",
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_pos_result(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Initial position returned"; break;
+ case 2: str = "Updated position returned"; break;
+ case 3: str = "Last known position returned"; break;
+ case 4: str = "Requested position is not available"; break;
+ case 5: str = "Caller disconnected. No call in progress for caller identified"; break;
+ case 6: str = "Caller has handed-off. Position is unavailable due to a hand-off (e.g. handoff to a position incapable system)"; break;
+ case 7: str = "Identified MS is inactive or has roamed to another system"; break;
+ case 8: str = "Unresponsive"; break;
+ case 9: str = "Identified MS is responsive, but refused position request"; break;
+ case 10: str = "System Failure"; break;
+ case 11: str = "MSID is not known"; break;
+ case 12: str = "Callback number is not known"; break;
+ case 13: str = "Improper request (e.g. invalid channel information, invalid ESN)"; break;
+ case 14: str = "Mobile channel information returned"; break;
+ case 15: str = "Signal not detected"; break;
+ case 16: str = "PDE Timeout"; break;
+ case 17: str = "Position pending"; break;
+ case 18: str = "TDMA MAHO Information Returned"; break;
+ case 19: str = "TDMA MAHO Information is not available"; break;
+ default:
+ if ((value >= 20) && (value <= 223)) { str = "Reserved, treat as Not used"; }
+ else { str = "Reserved for protocol extension, treat as Not used"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Position Result, %s",
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_pos_source(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Network Unspecified"; break;
+ case 2: str = "Network AOA (Angle of Arrival)"; break;
+ case 3: str = "Network TOA (Time of Arrival)"; break;
+ case 4: str = "Network TDOA (Time Difference of Arrival)"; break;
+ case 5: str = "Network RF Fingerprinting"; break;
+ case 6: str = "Network Cell/Sector"; break;
+ case 7: str = "Network Cell/Sector with Timing"; break;
+ case 16: str = "Handset Unspecified"; break;
+ case 17: str = "Handset GPS"; break;
+ case 18: str = "Handset AGPS (Assisted GPS)"; break;
+ case 19: str = "Handset EOTD (Enhanced Observed Time Difference)"; break;
+ case 20: str = "Handset AFLT (Advanced Forward Link Trilateration)"; break;
+ case 21: str = "Handset EFLT (Enhanced Forward Link Trilateration)"; break;
+ default:
+ if ((value >= 8) && (value <= 15)) { str = "Reserved, treat as Network Unspecified"; }
+ else if ((value >= 22) && (value <= 31)) { str = "Reserved, treat as Handset Unspecified"; }
+ else { str = "Reserved for protocol extension, treat as Not used"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Position Source, %s",
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_acg_encounter(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0xc0) >> 6)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Service Management System Initiated control encountered"; break;
+ case 2: str = "SCF Overload control encountered"; break;
+ case 3: str = "Reserved, treat as Not used"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Control Type, %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x3f)
+ {
+ case 0: str = "PC_SSN"; break;
+ case 1: str = "1-digit control"; break;
+ case 2: str = "2-digit control"; break;
+ case 3: str = "3-digit control"; break;
+ case 4: str = "4-digit control"; break;
+ case 5: str = "5-digit control"; break;
+ case 6: str = "6-digit control"; break;
+ case 7: str = "7-digit control"; break;
+ case 8: str = "8-digit control"; break;
+ case 9: str = "9-digit control"; break;
+ case 10: str = "10-digit control"; break;
+ case 11: str = "11-digit control"; break;
+ case 12: str = "12-digit control"; break;
+ case 13: str = "13-digit control"; break;
+ case 14: str = "14-digit control"; break;
+ case 15: str = "15-digit control"; break;
+ default:
+ str = "Reserved, treat as 15-digit control";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+}
+
+static void
+param_ctrl_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0xc0) >> 6)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Service Management System Initiated control"; break;
+ case 2: str = "SCF Overload control"; break;
+ case 3: str = "Reserved, treat as Not used"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Control Type, %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x3f)
+ {
+ case 0: str = "PC_SSN"; break;
+ case 1: str = "1-digit control"; break;
+ case 2: str = "2-digit control"; break;
+ case 3: str = "3-digit control"; break;
+ case 4: str = "4-digit control"; break;
+ case 5: str = "5-digit control"; break;
+ case 6: str = "6-digit control"; break;
+ case 7: str = "7-digit control"; break;
+ case 8: str = "8-digit control"; break;
+ case 9: str = "9-digit control"; break;
+ case 10: str = "10-digit control"; break;
+ case 11: str = "11-digit control"; break;
+ case 12: str = "12-digit control"; break;
+ case 13: str = "13-digit control"; break;
+ case 14: str = "14-digit control"; break;
+ case 15: str = "15-digit control"; break;
+ default:
+ str = "Reserved, treat as 15-digit control";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+}
+
+static void
+param_gap_duration(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "1 second"; break;
+ case 2: str = "2 seconds"; break;
+ case 3: str = "4 seconds"; break;
+ case 4: str = "8 seconds"; break;
+ case 5: str = "16 seconds"; break;
+ case 6: str = "32 seconds"; break;
+ case 7: str = "64 seconds"; break;
+ case 8: str = "128 seconds"; break;
+ case 9: str = "256 seconds"; break;
+ case 10: str = "512 seconds"; break;
+ case 11: str = "1024 seconds"; break;
+ case 12: str = "2048 seconds"; break;
+ case 13: str = "Infinity"; break;
+ default:
+ str = "Reserved, treat as Not used";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_scf_overload_gap_int(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "0 seconds"; break;
+ case 1: str = "3 seconds"; break;
+ case 2: str = "4 seconds"; break;
+ case 3: str = "6 seconds"; break;
+ case 4: str = "8 seconds"; break;
+ case 5: str = "11 seconds"; break;
+ case 6: str = "16 seconds"; break;
+ case 7: str = "22 seconds"; break;
+ case 8: str = "30 seconds"; break;
+ case 9: str = "42 seconds"; break;
+ case 10: str = "58 seconds"; break;
+ case 11: str = "81 seconds"; break;
+ case 12: str = "112 seconds"; break;
+ case 13: str = "156 seconds"; break;
+ case 14: str = "217 seconds"; break;
+ case 15: str = "300 seconds"; break;
+ case 16: str = "Remove gap control"; break;
+ case 17: str = "0.10 seconds"; break;
+ case 18: str = "0.25 seconds"; break;
+ case 19: str = "0.5 seconds"; break;
+ case 20: str = "1 second"; break;
+ case 21: str = "2 seconds"; break;
+ default:
+ str = "Reserved, treat as 0 seconds";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_tdma_time_align(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Time Alignment Offset (TA), %u",
+ bigbuf,
+ value & 0x1f);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+dump_rssi(ASN1_SCK *asn1, proto_tree *tree, gchar *leader)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0xc0) >> 6)
+ {
+ case 0: str = "800 MHz"; break;
+ case 1: str = "1900 MHz"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %sHyper, %s",
+ bigbuf,
+ leader,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %sRSSI, %u",
+ bigbuf,
+ leader,
+ value & 0x1f);
+}
+
+static void
+param_tdma_maho_cell_id(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, num_rssi, num_msc;
+ guint saved_offset, orig_offset;
+ gint32 i, j;
+
+ SHORT_DATA_CHECK(len, 3);
+
+ orig_offset = asn1->offset;
+
+ dump_rssi(asn1, tree, "Serving Cell ");
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &num_rssi);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Number of RSSI %u",
+ num_rssi);
+
+ for (i = 0; i < num_rssi; i++)
+ {
+ if ((len - (asn1->offset - orig_offset)) < 3)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len - (asn1->offset - orig_offset),
+ "Short Data (?)");
+
+ asn1->offset += len - (asn1->offset - orig_offset);
+ return;
+ }
+
+ dump_rssi(asn1, tree, "");
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Measured Cell ID %u",
+ value);
+ }
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &num_msc);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Number of MSC %u",
+ num_msc);
+
+ for (i = 0; i < num_msc; i++)
+ {
+ if ((len - (asn1->offset - orig_offset)) < 4)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len - (asn1->offset - orig_offset),
+ "Short Data (?)");
+
+ asn1->offset += len - (asn1->offset - orig_offset);
+ return;
+ }
+
+ param_mscid(asn1, tree, 3, add_string);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &num_rssi);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Number of RSSI %u",
+ num_rssi);
+
+ for (j = 0; j < num_rssi; j++)
+ {
+ if ((len - (asn1->offset - orig_offset)) < 3)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len - (asn1->offset - orig_offset),
+ "Short Data (?)");
+
+ asn1->offset += len - (asn1->offset - orig_offset);
+ return;
+ }
+
+ dump_rssi(asn1, tree, "");
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Measured Cell ID %u",
+ value);
+ }
+ }
+
+ EXTRANEOUS_DATA_CHECK((len - (asn1->offset - orig_offset)), 0);
+}
+
+static void
+param_tdma_maho_chan(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, num_rssi, num_msc;
+ guint saved_offset, orig_offset;
+ gint32 i, j;
+
+ SHORT_DATA_CHECK(len, 3);
+
+ orig_offset = asn1->offset;
+
+ dump_rssi(asn1, tree, "Serving Cell ");
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &num_rssi);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Number of RSSI %u",
+ num_rssi);
+
+ for (i = 0; i < num_rssi; i++)
+ {
+ if ((len - (asn1->offset - orig_offset)) < 3)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len - (asn1->offset - orig_offset),
+ "Short Data (?)");
+
+ asn1->offset += len - (asn1->offset - orig_offset);
+ return;
+ }
+
+ dump_rssi(asn1, tree, "");
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Measured Channel (MSB), %u",
+ bigbuf,
+ (value & 0xffe0) >> 5);
+
+ other_decode_bitfield_value(bigbuf, value & 0xff, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset+1, 1,
+ "%s : Measured Channel (LSB)",
+ bigbuf);
+ }
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &num_msc);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Number of MSC %u",
+ num_msc);
+
+ for (i = 0; i < num_msc; i++)
+ {
+ if ((len - (asn1->offset - orig_offset)) < 4)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len - (asn1->offset - orig_offset),
+ "Short Data (?)");
+
+ asn1->offset += len - (asn1->offset - orig_offset);
+ return;
+ }
+
+ param_mscid(asn1, tree, 3, add_string);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &num_rssi);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Number of RSSI %u",
+ num_rssi);
+
+ for (j = 0; j < num_rssi; j++)
+ {
+ if ((len - (asn1->offset - orig_offset)) < 3)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len - (asn1->offset - orig_offset),
+ "Short Data (?)");
+
+ asn1->offset += len - (asn1->offset - orig_offset);
+ return;
+ }
+
+ dump_rssi(asn1, tree, "");
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ other_decode_bitfield_value(bigbuf, value >> 8, 0xff, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Measured Channel (MSB), %u",
+ bigbuf,
+ (value & 0xffe0) >> 5);
+
+ other_decode_bitfield_value(bigbuf, value & 0xff, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset+1, 1,
+ "%s : Measured Channel (LSB)",
+ bigbuf);
+ }
+ }
+
+ EXTRANEOUS_DATA_CHECK((len - (asn1->offset - orig_offset)), 0);
+}
+
+static void
+param_tdma_maho_req(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "No MAHO information requested"; break;
+ case 1: str = "MAHO information requested"; break;
+ default:
+ str = "Reserved, treat as No MAHO information requested";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_sm_gap_int(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Remove gap control"; break;
+ case 1: str = "0 seconds"; break;
+ case 2: str = "0.10 seconds"; break;
+ case 3: str = "0.25 seconds"; break;
+ case 4: str = "0.50 seconds"; break;
+ case 5: str = "1 second"; break;
+ case 6: str = "2 seconds"; break;
+ case 7: str = "5 seconds"; break;
+ case 8: str = "10 seconds"; break;
+ case 9: str = "15 seconds"; break;
+ case 10: str = "30 seconds"; break;
+ case 11: str = "60 seconds"; break;
+ case 12: str = "120 seconds"; break;
+ case 13: str = "300 seconds"; break;
+ case 14: str = "600 seconds"; break;
+ case 15: str = "Stop all queries"; break;
+ default:
+ str = "Reserved, treat as Remove gap control";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_mob_cap(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset, i;
+ gchar *str = NULL;
+
+ add_string = add_string;
+
+ for (i=0; i < len; i++)
+ {
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Undefined Mobile Position Capabilities"; break;
+ case 1: str = "CDMA None"; break;
+ case 2: str = "CDMA Pilot Phase + GPS - MS shall be capable of supporting A-FLT and GPS for position determination"; break;
+ case 3: str = "CDMA Pilot Phase Only - MS shall be capable of supporting A-FLT only for position determination"; break;
+ case 4: str = "CDMA GPS Only - MS shall be capable of supporting GPS only for position determination"; break;
+ case 51: str = "TDMA None. See TIA/EIA-136-740"; break;
+ case 52: str = "TDMA MS-Based with Network Assistance SAMPS Supported. See TIA/EIA-136-740"; break;
+ case 53: str = "TDMA MS-Assisted SAMPS Supported. See TIA/EIA-136-740"; break;
+ case 54: str = "TDMA SAMPS Time Measurement Capability Supported. See TIA/EIA-136-740"; break;
+ case 55: str = "TDMA MS-Based Stand-alone SAMPS Supported. See TIA/EIA-136-740"; break;
+ case 101: str = "AMPS None"; break;
+ case 102: str = "AMPS MS-based - MS shall be capable of autonomously determining the position without assistance from the network"; break;
+ case 103: str = "AMPS assisted GPS - MS shall be capable of utilizing network assistance in providing GPS satellite measurements for position determination in the network or of utilizing network assistance in position determination in the MS"; break;
+ default:
+ if ((value >= 5) && (value <= 50)) { str = "Reserved for CDMA, treat as CDMA None"; }
+ else if ((value >= 56) && (value <= 100)) { str = "Reserved for TDMA, treat as TDMA None"; }
+ else if ((value >= 104) && (value <= 150)) { str = "Reserved for AMPS, treat as AMPS None"; }
+ else if ((value >= 151) && (value <= 223)) { str = "Reserved, treat as Undefined"; }
+ else { str = "Reserved for protocol extension, treat as Undefined"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Mobile Position Capability, %s",
+ str);
+ }
+}
+
+static void
+param_cdma_psmm_count(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Number of CDMA Pilot Strength Measurements to return, %u",
+ value);
+}
+
+static void
+param_cdma_sowd2(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 5);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "CDMA Serving One Way Delay, %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfc, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "100 nsec"; break;
+ case 1: str = "50 nsec"; break;
+ case 2: str = "1/16 CDMA PN Chip"; break;
+ case 3: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Resolution, %s",
+ bigbuf,
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Serving One Way Delay TimeStamp, %u",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 5);
+}
+
+static void
+param_sms_charge_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "No charge"; break;
+ case 2: str = "Charge original originator"; break;
+ case 3: str = "Charge original destination"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Charge %u, %s",
+ value,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_auth_per(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Per call"; break;
+ case 2: str = "Hours"; break;
+ case 3: str = "Days"; break;
+ case 4: str = "Weeks"; break;
+ case 5: str = "Per agreement"; break;
+ case 6: str = "Indefinite"; break;
+ case 7: str = "Number of calls"; break;
+ default:
+ if ((value >= 8) && (value <= 223)) { str = "Reserved, treat as Per call"; }
+ else { str = "Reserved for protocol extension, treat as Per call"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Period (%u) %s",
+ value,
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Value %u",
+ value);
+}
+
+static void
+param_ctrl_chan_mode(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "MS is in Analog CC Mode"; break;
+ case 2: str = "MS is in Digital CC Mode"; break;
+ case 3: str = "MS is in NAMPS CC Mode"; break;
+ default:
+ if ((value >= 4) && (value <= 223)) { str = "Reserved, treat as Unknown"; }
+ else { str = "Reserved for protocol extension, treat as Unknown"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_tdma_data_mode(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0xe0) >> 5)
+ {
+ case 0: str = "As per IS-135"; break;
+ case 1: str = "As per FSVS - 211 (STU-III)"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Data Part, %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : AD, %s",
+ bigbuf,
+ (value & 0x10) ? "unacknowledged data only" : "unacked data or both");
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ (value & 0x08) ? "SAP 0 and 1" : "SAP 0 only");
+
+ switch (value & 0x07)
+ {
+ case 0: str = "No Data Privacy"; break;
+ case 1: str = "Data Privacy Algorithm A"; break;
+ default:
+ str = "Reserved, treat as No Data Privacy";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x07, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Data Privacy Mode, %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x0c) >> 2)
+ {
+ case 0: str = "RLP1"; break;
+ case 1: str = "RLP2"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "16-bit Cyclic Redundancy Check"; break;
+ case 1: str = "24-bit Cyclic Redundancy Check"; break;
+ case 2: str = "No Cyclic Redundancy Check"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+}
+
+static void
+param_tdma_voice_mode(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0xf0) >> 4)
+ {
+ case 0: str = "No Voice Privacy"; break;
+ case 1: str = "Voice Privacy Algorithm A"; break;
+ case 2: str = "Reserved, treat as No Voice Privacy"; break;
+ case 3: str = "Reserved, treat as No Voice Privacy"; break;
+ case 4: str = "Reserved for SOC/BMSC Specific signaling"; break;
+ default:
+ str = "Reserved, treat as No Voice Privacy";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Voice Privacy Mode, %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x0f)
+ {
+ case 0: str = "No Voice Coder"; break;
+ case 1: str = "VSELP Voice Coder"; break;
+ case 2: str = "IS-641 Voice Coder"; break;
+ case 6: str = "Reserved for SOC/BMSC Specific signaling"; break;
+ default:
+ str = "Reserved, treat as No Voice Coder";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Voice Coder, %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_tdma_bandwidth(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x0f)
+ {
+ case 0: str = "Half-Rate Digital Traffic Channel Only"; break;
+ case 1: str = "Full-Rate Digital Traffic Channel Only"; break;
+ case 2: str = "Half-Rate or Full-rate Digital Traffic Channel - Full-Rate Preferred"; break;
+ case 3: str = "Half-rate or Full-rate Digital Traffic Channel - Half-rate Preferred"; break;
+ case 4: str = "Double Full-Rate Digital Traffic Channel Only"; break;
+ case 5: str = "Triple Full-Rate Digital Traffic Channel Only"; break;
+ default:
+ str = "Reserved, treat as Full-Rate Digital Traffic Channel Only";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Bandwidth, %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_change_srvc_attr(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x0c) >> 2)
+ {
+ case 0: str = "Service Negotiation Used"; break;
+ case 1: str = "Service Negotiation Not Used"; break;
+ case 2: str = "Service Negotiation Required"; break;
+ case 3: str = "Service Negotiation Not Required"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Service Negotiate Flag (SRVNEG), %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x03)
+ {
+ case 0 : str = "Change Facilities Operation Requested"; break;
+ case 1 : str = "Change Facilities Operation Not Requested"; break;
+ case 2 : str = "Change Facilities Operation Used"; break;
+ case 3 : str = "Change Facilities Operation Not Used"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Change Facilities Flag (CHGFAC), %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_dp_params(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xfc, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (value & 0x03)
+ {
+ case 0: str = "Privacy inactive or not supported"; break;
+ case 1: str = "Privacy Requested or Acknowledged"; break;
+ default:
+ str = "Reserved, treat as Privacy inactive or not supported";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Privacy Mode, %s",
+ bigbuf,
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Data Privacy Version 1"; break;
+ default:
+ if ((value >= 2) && (value <= 223)) { str = "Reserved, treat as Not used"; }
+ else { str = "Reserved for protocol extension, treat as Not used"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Data Privacy Version, %s",
+ str);
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len - 2,
+ "Data Privacy data");
+
+ asn1->offset += (len - 2);
+}
+
+static void
+param_trn(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+ guchar *poctets;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_string_value_decode(asn1, len, &poctets);
+
+ my_dgt_tbcd_unpack(bigbuf, poctets, len, &Dgt_msid);
+ g_free(poctets);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len, "TRN %s", bigbuf);
+}
+
+static void
+param_islp_info(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "No ISLP supported"; break;
+ case 1: str = "ISLP supported (see ISLP)"; break;
+ default:
+ if ((value >= 2) && (value <= 112)) { str = "Reserved, treat as No ISLP supported"; }
+ else if ((value >= 113) && (value <= 223)) { str = "Reserved, treat as ISLP supported"; }
+ else if ((value >= 224) && (value <= 240)) { str = "Reserved for protocol extension, treat as No ISLP supported"; }
+ else { str = "Reserved for protocol extension, treat as ISLP supported"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_ana_red_info(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Ignore CDMA, %s",
+ bigbuf,
+ (value & 0x20) ? "Ignore the CDMA Capability Message on the analog system to which it is being redirected" :
+ "Don't ignore the CDMA Capability Message on the analog system to which it is being redirected");
+
+ switch (value & 0x1f)
+ {
+ case 0: str = "Attempt to obtain service on either System A or B in accordance with the custom system selection process"; break;
+ case 1: str = "Attempt to obtain service on System A only"; break;
+ case 2: str = "Error in IS-735, text was unspecified but not reserved"; break;
+ case 3: str = "Attempt to obtain service on System A first. If unsuccessful, attempt to obtain service on System B"; break;
+ case 4: str = "Attempt to obtain service on System B first. If unsuccessful, attempt to obtain service on System A"; break;
+ case 5: str = "Attempt to obtain service on either System A or System B. If unsuccessful, attempt to obtain service on the alternate system (System A or System B)"; break;
+
+ default:
+ str = "Reserved for protocol extension";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x1f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Sys Ordering, %s",
+ bigbuf,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_reason_list(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ gint i;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ i = 0;
+
+ do
+ {
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "Unable to configure ISLP"; break;
+ case 2: str = "ISLP failure"; break;
+ case 3: str = "Service allowed but facilities not available"; break;
+ case 4: str = "Service not allowed"; break;
+ case 5: str = "No Response to TMSI assignment"; break;
+ case 6: str = "Required parameters unavailable. (e.g., as indicated by the RequiredParametersMask parameter)"; break;
+ default:
+ if ((value >= 7) && (value <= 110)) { str = "Reserved for common CDMA and TDMA network error causes. If unknown, treat as Unknown"; }
+ else if ((value >= 111) && (value <= 127)) { str = "Reserved for common CDMA and TDMA network error causes for protocol extension. If unknown, treat as Unknown"; }
+ else if ((value >= 128) && (value <= 174)) { str = "CDMA Specific error causes. If unknown, treat as Unknown"; }
+ else if ((value >= 175) && (value <= 191)) { str = "CDMA Specific error causes for protocol extension. If unknown treat as Unknown"; }
+ else if ((value >= 192) && (value <= 237)) { str = "TDMA Specific error causes as defined by the TDMACause parameter. If unknown treat as Unknown"; }
+ else { str = "TDMA Specific error causes for protocol extension. If unknown, treat as Unknown"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "[%u] %s",
+ i++,
+ str);
+
+ saved_offset = asn1->offset;
+ }
+ while ((len - i) > 0);
+}
+
+static void
+param_imsi(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+ guchar *poctets;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+ asn1_string_value_decode(asn1, len, &poctets);
+
+ my_dgt_tbcd_unpack(bigbuf, poctets, len, &Dgt_msid);
+ g_free(poctets);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "IMSI %s",
+ bigbuf);
+
+ sprintf(add_string, " - %s", bigbuf);
+}
+
+static void
+param_min(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+ guchar *poctets;
+
+ EXACT_DATA_CHECK(len, 5);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+ asn1_string_value_decode(asn1, len, &poctets);
+
+ my_dgt_tbcd_unpack(bigbuf, poctets, len, &Dgt_msid);
+ g_free(poctets);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "MIN %s",
+ bigbuf);
+
+ sprintf(add_string, " - %s", bigbuf);
+}
+
+static void
+param_auth_cap(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "No authentication required"; break;
+ case 2: str = "Authentication required"; break;
+ case 128: str = "Authentication required and UIM capable"; break;
+ default:
+ if ((value >= 3) && (value <= 95)) { str = "Reserved, treat as No authentication required"; }
+ else if ((value >= 96) && (value <= 127)) { str = "Reserved for protocol extension, treat as No authentication required"; }
+ else if ((value >= 129) && (value <= 223)) { str = "Reserved, treat as Authentication required"; }
+ else { str = "Reserved for protocol extension, treat as Authentication required"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_sus_acc(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Anomalous digits"; break;
+ case 2: str = "Unspecified"; break;
+ default:
+ if ((value >= 3) && (value <= 113)) { str = "Reserved, treat as Anomalous digits"; }
+ else if ((value >= 114) && (value <= 223)) { str = "Reserved, treat as Unspecified"; }
+ else { str = "Reserved for protocol extension, treat as Unspecified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Reason, %s",
+ str);
+}
+
+static void
+param_dis_text(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 3);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Spec. has hardcoded 1",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x7f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Display type, see ANSI T1.610 for encoding",
+ bigbuf);
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len - 1,
+ "Display data");
+
+ asn1->offset += len - 1;
+}
+
+static void
+param_dis_text2(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint orig_offset, saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+
+ do
+ {
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "ASCII"; break;
+ case 2: str = "ITU T.50. The International Reference Alphabet as defined in ITU-R Rec. T.50"; break;
+ case 3: str = "User Specific"; break;
+ case 4: str = "ISO 8859-1. The 8-bit single-byte coded character set Latin 1 as defined in ISO/IEC Standard 8859-1"; break;
+ case 5: str = "ISO 10646. The Universal Multiple-Octet Coded Character Set (USC) as defined in ISO/IEC Standard 10646"; break;
+ case 6: str = "ISO 8859-8. The 8-bit single-byte coded character set Hebrew as defined in ISO/IEC Standard 8859-8"; break;
+ case 7: str = "IS-91 Extended Protocol Message. The length is determined by the Message Type; see TIA/EIA/IS-90"; break;
+ case 8: str = "Shift-JIS. Variable 1-2 byte nonmodal encoding for Kanji, Kana, and Latin character sets defined in JIS X0201 and JIS X0206"; break;
+ case 9: str = "KC C 5601. Variable 1-2 byte Korean encoding method"; break;
+ default:
+ if ((value >= 10) && (value <= 223)) { str = "Reserved, treat as ASCII"; }
+ else { str = "Reserved, treat as ASCII"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Display Character Set, %s",
+ str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Display Type, %u, see ANSI T1.610",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Display Tag, %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Display Length, %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ if (value > 0)
+ {
+ if ((guint32) value > (len - (saved_offset - orig_offset)))
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len - (saved_offset - orig_offset),
+ "Short Data (?)");
+
+ asn1->offset += len - (saved_offset - orig_offset);
+ return;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, value,
+ "Display data");
+
+ asn1->offset += value;
+
+ saved_offset = asn1->offset;
+ }
+ }
+ while ((len - (saved_offset - orig_offset)) >= 4);
+
+ EXTRANEOUS_DATA_CHECK((len - (saved_offset - orig_offset)), 0);
+}
+
+static void
+param_dmh_srvc_id(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint orig_offset, saved_offset;
+
+ SHORT_DATA_CHECK(len, 5);
+
+ add_string = add_string;
+
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+
+ do
+ {
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Market ID %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Market Segment ID %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "DMH Service ID Value %u",
+ value);
+
+ saved_offset = asn1->offset;
+ }
+ while ((len - (saved_offset - orig_offset)) >= 5);
+
+ EXTRANEOUS_DATA_CHECK((len - (saved_offset - orig_offset)), 0);
+}
+
+static void
+param_feat_ind(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint orig_offset, saved_offset;
+
+ SHORT_DATA_CHECK(len, 5);
+
+ add_string = add_string;
+
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+
+ do
+ {
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Market ID %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Market Segment ID %u",
+ value);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "DMH Service ID Value %u",
+ value);
+
+ saved_offset = asn1->offset;
+ }
+ while ((len - (saved_offset - orig_offset)) >= 5);
+
+ EXTRANEOUS_DATA_CHECK((len - (saved_offset - orig_offset)), 0);
+}
+
+static void
+param_a_key_ver(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ gint i;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ i = 0;
+
+ do
+ {
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "A-key Generation not supported"; break;
+ case 2: str = "Diffie Hellman with 768-bit modulus, 160-bit primitive, and 160-bit exponents"; break;
+ case 3: str = "Diffie Hellman with 512-bit modulus, 160-bit primitive, and 160-bit exponents"; break;
+ case 4: str = "Diffie Hellman with 768-bit modulus, 32-bit primitive, and 160-bit exponents"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, treat as A-key Generation not supported"; }
+ else { str = "Reserved for protocol extension, treat as A-key Generation not supported"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "[%u] %s",
+ i++,
+ str);
+
+ saved_offset = asn1->offset;
+ }
+ while ((len - i) > 0);
+}
+
+static void
+param_inter_msg_time(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Timer Value, %u, %u seconds",
+ value,
+ value * 10);
+
+ /* XXX * 10 or / 10 ? */
+}
+
+static void
+param_rel_cause(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Unspecified"; break;
+ case 1: str = "Calling Party"; break;
+ case 2: str = "Called Party"; break;
+ case 3: str = "Commanded Disconnect"; break;
+ default:
+ if ((value >= 4) && (value <= 23)) { str = "Reserved, treat as Calling Party"; }
+ else if ((value >= 24) && (value <= 31)) { str = "Reserved for protocol extension. If unknown, treat as Calling Party"; }
+ else if ((value >= 32) && (value <= 55)) { str = "Reserved, treat as Called Party"; }
+ else if ((value >= 56) && (value <= 63)) { str = "Reserved for protocol extension. If unknown, treat as Called Party"; }
+ else if ((value >= 64) && (value <= 87)) { str = "Reserved, treat as Commanded Disconnect"; }
+ else if ((value >= 88) && (value <= 95)) { str = "Reserved for protocol extension. If unknown, treat as Commanded Disconnect"; }
+ else if ((value >= 96) && (value <= 223)) { str = "Reserved, treat as Unspecified"; }
+ else { str = "Reserved for protocol extension. If unknown, treat as Unspecified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_time_day(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ gint32 h, m, s, ts;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 3);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 3, &value);
+
+ h = value / (3600 * 10);
+ m = (value - (h * (3600 * 10))) / (60 * 10);
+ s = (value - (h * (3600 * 10)) - (m * (60 * 10))) / 10;
+ ts = (value - (h * (3600 * 10)) - (m * (60 * 10)) - (s * 10));
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "(UTC) (in tenths of seconds - 1), %u (%u:%u:%u.%u)",
+ value,
+ h,
+ m,
+ s,
+ ts);
+}
+
+static void
+param_call_status(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+
+ if (len > 4)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len, "Long Data (?)");
+ asn1->offset += len;
+ return;
+ }
+
+ saved_offset = asn1->offset;
+
+ asn1->offset = saved_offset;
+
+ asn1_int32_value_decode(asn1, len, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Call Setup in Progress"; break;
+ case 2: str = "Locally Allowed Call - No Action"; break;
+ default:
+ if (value < 0) { str = "Reserved for bilateral agreements. If unknown, treat as Not used"; }
+ else { str = "Reserved, treat as Not used"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ str);
+}
+
+static void
+param_ms_status(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+ gboolean has_chan;
+ gboolean extended;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ extended = (value & 0x80) >> 7;
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Extension (EXT), %s",
+ bigbuf,
+ extended ? "No Extension, last octet of sequence" : "Extension indicator, the octet continues through the next octet");
+
+ other_decode_bitfield_value(bigbuf, value, 0x60, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Location Information (LOC), %s",
+ bigbuf,
+ (value & 0x10) ? "MS location information available" : "No MS location information available");
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Contact, %s",
+ bigbuf,
+ (value & 0x08) ? "Radio Contact Established" : "No Radio Contact");
+
+ has_chan = (value & 0x04) >> 2;
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Channel, %s",
+ bigbuf,
+ has_chan ? "Traffic Channel Assigned" : "No Traffic Channel");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Handoff, %s",
+ bigbuf,
+ (value & 0x02) ? "Intersystem Handoff" : "No Intersystem Handoff");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Inactive, %s",
+ bigbuf,
+ (value & 0x01) ? "MS Inactive" : "MS Active");
+
+ if (len == 1) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ if (extended)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Octet 1a ? spec. does not provide details");
+
+ saved_offset = asn1->offset;
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+
+ return;
+ }
+
+ if (has_chan)
+ {
+ switch (value)
+ {
+ case 0: str = "Not used "; break;
+ case 1: str = "Analog. The MS is currently assigned to an analog traffic channel"; break;
+ case 2: str = "NAMPS. The MS is currently assigned to an NAMPS traffic channel"; break;
+ case 3: str = "TDMA. The MS is currently assigned to a TDMA traffic channel"; break;
+ case 4: str = "CDMA. The MS is currently assigned to a CDMA traffic channel"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, treat as Not used"; }
+ else { str = "Reserved for protocol extension, treat as Not used"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Radio Channel Type, %s",
+ str);
+
+ saved_offset = asn1->offset;
+
+ EXTRANEOUS_DATA_CHECK(len, 2);
+
+ return;
+ }
+
+ asn1->offset -= 1;
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_pos_info_code(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : MS Identity (MSID), %s",
+ bigbuf,
+ (value & 0x10) ? "MS Identity Requested" : "No MS Identity Requested");
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Routing Address (ROUTE), %s",
+ bigbuf,
+ (value & 0x08) ? "Routing Address Requested" : "No Routing Address Requested");
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Serving Cell ID (CELLID), %s",
+ bigbuf,
+ (value & 0x04) ? "Serving Cell ID Requested" : "No Serving Cell ID Requested");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Location Area ID (LOCID), %s",
+ bigbuf,
+ (value & 0x02) ? "Location Area ID Requested" : "No Location Area ID Requested");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Current, %s",
+ bigbuf,
+ (value & 0x01) ? "Provide the current MS location" : "Provide the last known MS location information, if known");
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_rel_reason(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Unspecified"; break;
+ case 1: str = "Call Over Clear Forward"; break;
+ case 2: str = "Call Over Clear Backward"; break;
+ case 3: str = "Handoff Successful"; break;
+ case 4: str = "Handoff Abort - call over"; break;
+ case 5: str = "Handoff Abort - not received"; break;
+ case 6: str = "Abnormal mobile termination"; break;
+ case 7: str = "Abnormal switch termination"; break;
+ case 8: str = "Special feature release"; break;
+ case 9: str = "Session Over Clear Forward"; break;
+ case 10: str = "Session Over Clear Backward"; break;
+ case 11: str = "Clear All Services Forward"; break;
+ case 12: str = "Clear All Services Backward"; break;
+ case 13: str = "Anchor MSC was removed from the packet data session"; break;
+ default:
+ if ((value >= 14) && (value <= 223)) { str = "Reserved, treat as Unspecified"; }
+ else { str = "Reserved for protocol extension, treat as Unspecified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Reason, %s",
+ str);
+}
+
+static void
+param_ho_reason(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Unspecified"; break;
+ case 2: str = "Weak signal"; break;
+ case 3: str = "Off-loading"; break;
+ case 4: str = "Anticipatory"; break;
+ default:
+ if ((value >= 5) && (value <= 223)) { str = "Reserved, treat as Unspecified"; }
+ else { str = "Reserved for protocol extension, treat as Unspecified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_red_reason(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Busy"; break;
+ case 2: str = "No answer"; break;
+ case 3: str = "Unconditional"; break;
+ case 4: str = "No page response"; break;
+ case 5: str = "Unavailable"; break;
+ case 6: str = "Unroutable"; break;
+ case 7: str = "Call accepted"; break;
+ case 8: str = "Call refused"; break;
+ case 9: str = "USCFvm, divert to voice mail"; break;
+ case 10: str = "USCFms, divert to an MS provided DN"; break;
+ case 11: str = "USCFnr, divert to a network registered DN"; break;
+ default:
+ if ((value >= 12) && (value <= 223)) { str = "Reserved, treat as No answer"; }
+ else { str = "Reserved for protocol extension, treat as No answer"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_confid_mode(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf8, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Data Privacy (DP), %s",
+ bigbuf,
+ (value & 0x04) ? "ON" : "OFF");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Signaling Message Encryption (SE), %s",
+ bigbuf,
+ (value & 0x02) ? "ON" : "OFF");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Voice Privacy (VP), %s",
+ bigbuf,
+ (value & 0x01) ? "ON" : "OFF");
+}
+
+static void
+param_sys_acc_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Unspecified"; break;
+ case 2: str = "Flash request"; break;
+ case 3: str = "Autonomous registration"; break;
+ case 4: str = "Call origination"; break;
+ case 5: str = "Page response"; break;
+ case 6: str = "No access"; break;
+ case 7: str = "Power down registration"; break;
+ case 8: str = "SMS page response"; break;
+ case 9: str = "OTASP"; break;
+ default:
+ if ((value >= 10) && (value <= 223)) { str = "Reserved, treat as Unspecified"; }
+ else { str = "Reserved for protocol extension, treat as Unspecified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_scm(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, temp_int;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ temp_int = ((value & 0x10) >> 2) | (value & 0x03);
+ switch (temp_int)
+ {
+ case 0: str = "Class I"; break;
+ case 1: str = "Class II"; break;
+ case 2: str = "Class III"; break;
+ case 3: str = "Class IV"; break;
+ case 4: str = "Class V"; break;
+ case 5: str = "Class VI"; break;
+ case 6: str = "Class VII"; break;
+ case 7: str = "Class VIII"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x13, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Power %s",
+ bigbuf,
+ str);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Bandwidth %s",
+ bigbuf,
+ (value & 0x08) ? "25 MHz" : "20 MHz");
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Transmission, %s",
+ bigbuf,
+ (value & 0x04) ? "Discontinuous" : "Continuous");
+}
+
+static void
+param_deny_acc(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Unspecified"; break;
+ case 2: str = "SSD Update failure"; break;
+ case 3: str = "COUNT Update failure"; break;
+ case 4: str = "Unique Challenge failure"; break;
+ case 5: str = "AUTHR mismatch"; break;
+ case 6: str = "COUNT mismatch"; break;
+ case 7: str = "Process collision"; break;
+ case 8: str = "Missing authentication parameters"; break;
+ case 9: str = "TerminalType mismatch"; break;
+ case 10: str = "MIN, IMSI or ESN authorization failure"; break;
+ default:
+ if ((value >= 11) && (value <= 223)) { str = "Reserved, treat as Unspecified"; }
+ else { str = "Reserved for protocol extension, treat as Unspecified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_cdma_sig_qual(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x3f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Value %u",
+ bigbuf,
+ value & 0x3f);
+}
+
+static void
+param_rec_sig_qual(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not a usable signal"; break;
+ case 255: str = "Interference"; break;
+ default:
+ if ((value >= 1) && (value <= 8)) { str = "Reserved, treat as Not a usable signal"; }
+ else if ((value >= 9) && (value <= 245)) { str = "Usable signal range"; }
+ else if ((value >= 246) && (value <= 254)) { str = "Reserved, treat as Interference"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_sig_qual(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not a usable signal"; break;
+ case 255: str = "Interference"; break;
+ default:
+ if ((value >= 1) && (value <= 8)) { str = "Reserved, treat as Not a usable signal"; }
+ else if ((value >= 9) && (value <= 245)) { str = "Usable signal range"; }
+ else if ((value >= 246) && (value <= 254)) { str = "Reserved, treat as Interference"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_ssd_no_share(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Discard SSD"; break;
+ default:
+ str = "Reserved, treat as Discard SSD";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_report_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Unspecified security violation"; break;
+ case 2: str = "MSID/ESN mismatch"; break;
+ case 3: str = "RANDC mismatch"; break;
+ case 4: str = "Reserved (see TSB51)"; break;
+ case 5: str = "SSD Update failed"; break;
+ case 6: str = "Reserved (see TSB51)"; break;
+ case 7: str = "COUNT mismatch"; break;
+ case 8: str = "Reserved (see TSB51)"; break;
+ case 9: str = "Unique Challenge failed"; break;
+ case 10: str = "Unsolicited Base Station Challenge"; break;
+ case 11: str = "SSD Update no response"; break;
+ case 12: str = "COUNT Update no response"; break;
+ case 13: str = "Unique Challenge no response"; break;
+ case 14: str = "AUTHR mismatch"; break;
+ case 15: str = "TERMTYP mismatch"; break;
+ case 16: str = "Missing authentication parameters"; break;
+ default:
+ if ((value >= 17) && (value <= 223)) { str = "Reserved, treat as Unspecified security violation"; }
+ else { str = "Reserved for protocol extension, treat as Unspecified security violation"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_term_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Not distinguished, EIA/TIA-553, IS-54-A, IS-88, IS-91, IS-94"; break;
+ case 2: str = "IS-54-B"; break;
+ case 3: str = "IS-136"; break;
+ case 4: str = "J-STD-011 (rescinded 11/23/99)"; break;
+ case 5: str = "IS-136-A or TIA/EIA-136 Revision-0"; break;
+ case 6: str = "TIA/EIA-136-A"; break;
+ case 7: str = "TIA/EIA-136-B"; break;
+ case 32: str = "IS-95"; break;
+ case 33: str = "IS-95-A"; break;
+ case 34: str = "J-STD-008"; break;
+ case 35: str = "IS-95-B"; break;
+ case 36: str = "IS-2000"; break;
+ case 64: str = "IS-88"; break;
+ case 65: str = "IS-94"; break;
+ case 66: str = "IS-91"; break;
+ case 67: str = "J-STD-014"; break;
+ case 68: str = "TIA/EIA-553-A"; break;
+ case 69: str = "IS-91-A"; break;
+ default:
+ if ((value >= 8) && (value <= 31)) { str = "Reserved, treat as IS-54-B"; }
+ else if ((value >= 37) && (value <= 63)) { str = "Reserved, treat as IS-95-A"; }
+ else if ((value >= 70) && (value <= 223)) { str = "Reserved, treat as Not distinguished"; }
+ else { str = "Reserved for protocol extension, treat as Not distinguished"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_term_res(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Termination denied"; break;
+ case 2: str = "Unrestricted"; break;
+ case 3: str = "Treatment for this value is not specified"; break;
+ default:
+ if ((value >= 4) && (value <= 223)) { str = "Reserved, treat as Unrestricted"; }
+ else { str = "Reserved for protocol extension, treat as Unrestricted"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_dereg(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Deregister for an unspecified reason"; break;
+ case 2: str = "Deregister for an adminstrative reason"; break;
+ case 3: str = "Deregister due to MS power down"; break;
+ default:
+ if ((value >= 4) && (value <= 223)) { str = "Reserved, treat as Deregister for an unspecified reason"; }
+ else { str = "Reserved for protocol extension, treat as Deregister for an unspecified reason"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+}
+
+static void
+param_group_info(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ SHORT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 4, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Value %u",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 4);
+}
+
+static void
+param_auth_den(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Delinquent account"; break;
+ case 2: str = "Invalid serial number"; break;
+ case 3: str = "Stolen unit"; break;
+ case 4: str = "Duplicate unit"; break;
+ case 5: str = "Unassigned directory number"; break;
+ case 6: str = "Unspecified"; break;
+ case 7: str = "Multiple access"; break;
+ case 8: str = "Not Authorized for the MSC"; break;
+ case 9: str = "Missing authentication parameters"; break;
+ case 10: str = "Terminal Type mismatch"; break;
+ default:
+ if ((value >= 11) && (value <= 223)) { str = "Reserved, treat as Unspecified"; }
+ else { str = "Reserved for protocol extension, treat as Unspecified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Reason, %s (%u)",
+ str,
+ value);
+}
+
+static gchar *
+find_trig_type(gint32 value)
+{
+ gchar *str = NULL;
+
+ switch (value)
+ {
+ case 0: str = "Unspecified"; break;
+ case 1: str = "All Calls"; break;
+ case 2: str = "Double Introducing Star"; break;
+ case 3: str = "Single Introducing Star"; break;
+ case 4: str = "Reserved [for Home System Feature Code"; break;
+ case 5: str = "Double Introducing Pound"; break;
+ case 6: str = "Single Introducing Pound"; break;
+ case 7: str = "Revertive Call"; break;
+ case 8: str = "0 Digit"; break;
+ case 9: str = "1 Digit"; break;
+ case 10: str = "2 Digit"; break;
+ case 11: str = "3 Digit"; break;
+ case 12: str = "4 Digit"; break;
+ case 13: str = "5 Digit"; break;
+ case 14: str = "6 Digit"; break;
+ case 15: str = "7 Digit"; break;
+ case 16: str = "8 Digit"; break;
+ case 17: str = "9 Digit"; break;
+ case 18: str = "10 Digit"; break;
+ case 19: str = "11 Digit"; break;
+ case 20: str = "12 Digit"; break;
+ case 21: str = "13 Digit"; break;
+ case 22: str = "14 Digit"; break;
+ case 23: str = "15 Digit"; break;
+ case 24: str = "Local Call"; break;
+ case 25: str = "Intra-LATA Toll Call"; break;
+ case 26: str = "Inter-LATA Toll Call"; break;
+ case 27: str = "World Zone Call"; break;
+ case 28: str = "International Call"; break;
+ case 29: str = "Unrecognized Number"; break;
+ case 30: str = "Prior Agreement"; break;
+ case 31: str = "Specific Called Party Digit String"; break;
+ case 32: str = "Mobile Termination"; break;
+ case 33: str = "Advanced Termination"; break;
+ case 34: str = "Location"; break;
+ case 35: str = "Locally Allowed Specific Digit String"; break;
+ case 36: str = "Origination Attempt Authorized"; break;
+ case 37: str = "Calling Routing Address Available"; break;
+ case 38: str = "Initial Termination"; break;
+ case 39: str = "Called Routing Address Available"; break;
+ case 40: str = "O Answer"; break;
+ case 41: str = "O Disconnect"; break;
+ case 42: str = "O Called Party Busy"; break;
+ case 43: str = "O No Answer"; break;
+ case 64: str = "Terminating Resource Available"; break;
+ case 65: str = "T Busy"; break;
+ case 66: str = "T No Answer"; break;
+ case 67: str = "T No Page Response"; break;
+ case 68: str = "T Unroutable"; break;
+ case 69: str = "T Answer"; break;
+ case 70: str = "T Disconnect"; break;
+ case 220: str = "Reserved for TDP-R DP Type value"; break;
+ case 221: str = "Reserved for TDP-N DP Type value"; break;
+ case 222: str = "Reserved for EDP-R DP Type value"; break;
+ case 223: str = "Reserved for EDP-N DP Type value"; break;
+ default:
+ if ((value >= 44) && (value <= 63)) { str = "Reserved, treat as Unspecified"; }
+ else if ((value >= 71) && (value <= 219)) { str = "Reserved, treat as Unspecified"; }
+ else { str = "Reserved for protocol extension, treat as Unspecified"; }
+ break;
+ }
+
+ return(str);
+}
+
+static void
+param_trig_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Trigger (%u) %s",
+ value,
+ find_trig_type(value));
+}
+
+static void
+param_win_op_cap(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf8, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Sender does not support PositionRequest OP"; break;
+ default:
+ str = "Sender supports PositionRequest OP";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Sender does not support CallControlDirective OP"; break;
+ default:
+ str = "Sender supports CallControlDirective OP";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Sender does not support ConnectResource, DisconnectResource, ConnectionFailureReport and ResetTimer (SSFT timer) OPs"; break;
+ default:
+ str = "Sender supports ConnectResource, DisconnectResource, ConnectionFailureReport and ResetTimer (SSFT timer) OPs";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_win_trig_list(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, i, j;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ j = 0;
+ i = 0;
+
+ do
+ {
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0xdc:
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "TDP-R's armed");
+
+ j = 0;
+ break;
+
+ case 0xdd:
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "TDP-N's armed");
+
+ j = 0;
+ break;
+
+ case 0xde:
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "EDP-R's armed");
+
+ j = 0;
+ break;
+
+ case 0xdf:
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "EDP-N's armed");
+
+ j = 0;
+ break;
+
+ default:
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "[%u] (%u) %s",
+ j,
+ value,
+ find_trig_type(value));
+ j++;
+ break;
+ }
+
+ saved_offset = asn1->offset;
+ i++;
+ }
+ while ((len - i) > 0);
+}
+
+static void
+param_trans_cap(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+ char *p;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "System is not capable of supporting CNAP/CNAR (NAMI)"; break;
+ default:
+ str = "System is capable of supporting CNAP/CNAR (NAMI)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "System is not capable of supporting NDSS"; break;
+ default:
+ str = "System is capable of supporting NDSS";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "System is not capable of supporting User Zones (UZCI)"; break;
+ default:
+ str = "System is capable of supporting User Zones (UZCI)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "System is not capable of supporting local SPINI"; break;
+ default:
+ str = "System is capable of supporting local SPINI";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "System is not capable of interacting with the user (RUI)"; break;
+ default:
+ str = "System is capable of interacting with the user (RUI)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "System is not capable of honoring the Announcement List parameter (ANN)"; break;
+ default:
+ str = "System is capable of honoring the Announcement List parameter (ANN)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "System is not capable of detecting a busy condition (BUSY)"; break;
+ default:
+ str = "System is capable of detecting a busy condition (BUSY)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "System is not capable of supporting the IS-41-C profile parameter (PROFILE)"; break;
+ default:
+ str = "System is capable of supporting the IS-41-C profile parameter (PROFILE)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ if (len == 1) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "System is not capable of supporting the CDMA Over the Air Parameter Administration"; break;
+ default:
+ str = "System is capable of supporting the CDMA Over the Air Parameter Administration";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "System is not capable of supporting lower layer segmentation & reassembly (S&R)"; break;
+ default:
+ str = "System is capable of supporting lower layer segmentation & reassembly (S&R)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "System is not capable of supporting the Trigger Address List parameter (WADDR)"; break;
+ default:
+ str = "System is capable of supporting the Trigger Address List parameter (WADDR)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "System is not capable of supporting the Termination List parameter (TL)"; break;
+ default:
+ str = "System is capable of supporting the Termination List parameter (TL)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ p = other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ switch (value & 0x0f)
+ {
+ case 0x00: strcat(p, " : System cannot accept a termination at this time"); break;
+ default:
+ sprintf(p, " : System supports %u call leg(s)", value & 0x0f);
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s",
+ bigbuf);
+
+ if (len == 2) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf8, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "The system is not capable of supporting external MAHO requests"; break;
+ default:
+ str = "The system is capable of supporting external MAHO requests (e.g. for positioning)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ EXTRANEOUS_DATA_CHECK(len, 3);
+}
+
+static void
+param_spini_trig(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any Revertive Call attempt"; break;
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Revertive Call (RvtC), %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt to an unrecognized number"; break;
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Unrecognized Number (Unrec), %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt outside of the current World Zone (as defined in ITU-T Rec. E.164)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : World Zone (WZ), %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any international call attempt";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : International (Intl), %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any toll calls outside the local carrier's serving area";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Non-Local (Inter-LATA) Toll (NLTOLL/OLATA), %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any local toll call attempt. Refers to intra-LATA toll within the NANP";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Local (Intra-LATA) Toll (LTOLL/ILATA), %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any local call attempt";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Local, %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt. This overrides all other values.";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : All Origination (All), %s",
+ bigbuf, str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any number matching a criteria of a prior agreement";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Prior Agreement (PA), %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any number beginning with two Pound ## digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Double Pound (DP), %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any number beginning with a Pound # digit";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Pound, %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any number beginning with two Star ** digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Double Star (DS), %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any number beginning with a Star * digit";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Star, %s",
+ bigbuf, str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 7 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 7 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 6 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 6 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 5 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 5 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 4 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 4 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 3 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 3 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 2 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 2 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 1 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1 digits, %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with no digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : No digits, %s",
+ bigbuf, str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 15 or more digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 15 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 14 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 14 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 13 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 13 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 12 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 12 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 11 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 11 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 10 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 10 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 9 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 9 digits, %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Execute local SPINI procedures for any call attempt with 8 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 8 digits, %s",
+ bigbuf, str);
+
+ EXTRANEOUS_DATA_CHECK(len, 4);
+}
+
+static void
+param_orig_trig(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ SHORT_DATA_CHECK(len, 4);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any Revertive Call attempt"; break;
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Revertive Call (RvtC), %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt to an unrecognized number"; break;
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Unrecognized Number (Unrec), %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt outside of the current World Zone (as defined in ITU-T Rec. E.164)";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : World Zone (WZ), %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any international call attempt";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : International (Intl), %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any toll calls outside the local carrier's serving area";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Non-Local (Inter-LATA) Toll (NLTOLL/OLATA), %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any local toll call attempt. Refers to intra-LATA toll within the NANP";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Local (Intra-LATA) Toll (LTOLL/ILATA), %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any local call attempt";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Local, %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt. This overrides all other values.";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : All Origination (All), %s",
+ bigbuf, str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any number matching a criteria of a prior agreement";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Prior Agreement (PA), %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any number beginning with two Pound ## digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Double Pound (DP), %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any number beginning with a Pound # digit";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Pound, %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any number beginning with two Star ** digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Double Star (DS), %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any number beginning with a Star * digit";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Star, %s",
+ bigbuf, str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 7 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 7 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 6 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 6 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 5 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 5 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 4 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 4 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 3 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 3 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 2 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 2 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 1 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 1 digits, %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with no digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : No digits, %s",
+ bigbuf, str);
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 15 or more digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 15 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 14 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 14 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 13 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 13 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 12 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 12 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 11 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 11 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 10 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 10 digits, %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 9 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 9 digits, %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Trigger is not active"; break;
+ default:
+ str = "Launch an Origination Request for any call attempt with 8 digits";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : 8 digits, %s",
+ bigbuf, str);
+
+ EXTRANEOUS_DATA_CHECK(len, 4);
+}
+
+static void
+param_trig_cap(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "O No Answer (ONA) cannot be armed"; break;
+ default:
+ str = "O No Answer (ONA) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "O Disconnect (ODISC) cannot be armed"; break;
+ default:
+ str = "O Disconnect (ODISC) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "O Answer (OANS) cannot be armed"; break;
+ default:
+ str = "O Answer (OANS) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Origination Attempt Authorized (OAA) cannot be armed"; break;
+ default:
+ str = "Origination Attempt Authorized (OAA) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Revertive Call trigger (RvtC) cannot be armed"; break;
+ default:
+ str = "Revertive Call trigger (RvtC) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "All Calls trigger (All) cannot be armed"; break;
+ default:
+ str = "All Calls trigger (All) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "K-digit triggers (K-digit) cannot be armed"; break;
+ default:
+ str = "K-digit triggers (K-digit) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Introducing Star/Pound triggers (INIT) cannot be armed"; break;
+ default:
+ str = "Introducing Star/Pound triggers (INIT) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ if (len == 1) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch ((value & 0x80) >> 7)
+ {
+ case 0x00: str = "O Called Party Busy (OBSY) cannot be armed"; break;
+ default:
+ str = "O Called Party Busy (OBSY) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x40) >> 6)
+ {
+ case 0x00: str = "Called Routing Address Available (CdRAA) cannot be armed"; break;
+ default:
+ str = "Called Routing Address Available (CdRAA) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "Initial Termination (IT) cannot be armed"; break;
+ default:
+ str = "Initial Termination (IT) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "Calling Routing Address Available (CgRAA) cannot be armed"; break;
+ default:
+ str = "Calling Routing Address Available (CgRAA) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "Advanced Termination trigger (AT) cannot be armed"; break;
+ default:
+ str = "Advanced Termination trigger (AT) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Prior Agreement trigger (PA) cannot be armed"; break;
+ default:
+ str = "Prior Agreement trigger (PA) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "Unrecognized Number trigger (Unrec) cannot be armed"; break;
+ default:
+ str = "Unrecognized Number trigger (Unrec) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Call Type triggers (CT) cannot be armed"; break;
+ default:
+ str = "Call Type triggers (CT) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ if (len == 2) return;
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xe0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "T Disconnect (TDISC) cannot be armed"; break;
+ default:
+ str = "T Disconnect (TDISC) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "T Answer (TANS) cannot be armed"; break;
+ default:
+ str = "T Answer (TANS) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "T No Answer trigger (TNA) cannot be armed"; break;
+ default:
+ str = "T No Answer trigger (TNA) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "T Busy trigger (TBusy) cannot be armed"; break;
+ default:
+ str = "T Busy trigger (TBusy) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Terminating Resource Available triggers (TRA) cannot be armed"; break;
+ default:
+ str = "Terminating Resource Available triggers (TRA) can be armed";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ EXTRANEOUS_DATA_CHECK(len, 3);
+}
+
+static void
+param_sys_cap(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : Reserved",
+ bigbuf);
+
+ switch ((value & 0x20) >> 5)
+ {
+ case 0x00: str = "DP is not supported by the system"; break;
+ default:
+ str = "DP is supported by the system";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x10) >> 4)
+ {
+ case 0x00: str = "SSD is not shared with the system for the indicated MS"; break;
+ default:
+ str = "SSD is shared with the system for the indicated MS";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x08) >> 3)
+ {
+ case 0x00: str = "System cannot execute CAVE algorithm"; break;
+ default:
+ str = "System can execute CAVE algorithm";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x04) >> 2)
+ {
+ case 0x00: str = "Voice Privacy is not supported"; break;
+ default:
+ str = "Voice Privacy is supported";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch ((value & 0x02) >> 1)
+ {
+ case 0x00: str = "SME is not supported"; break;
+ default:
+ str = "SME is supported";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch (value & 0x01)
+ {
+ case 0x00: str = "Authentication parameters were not requested"; break;
+ default:
+ str = "Authentication parameters were requested";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+}
+
+static void
+param_act_code(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Continue processing"; break;
+ case 2: str = "Disconnect call"; break;
+ case 3: str = "Disconnect call leg"; break;
+ case 4: str = "Conference calling drop last party"; break;
+ case 5: str = "Bridge call leg(s) to conference call"; break;
+ case 6: str = "Drop call leg on busy or routing failure"; break;
+ case 7: str = "Disconnect all call legs"; break;
+ case 8: str = "Attach MSC to OTAF"; break;
+ case 9: str = "Initiate Registration Notification"; break;
+ case 10: str = "Generate Public Encryption values"; break;
+ case 11: str = "Generate A-Key"; break;
+ case 12: str = "Perform SSD Update procedure"; break;
+ case 13: str = "Perform Re-authentication procedure"; break;
+ case 14: str = "Release TRN"; break;
+ case 15: str = "Commit A-key"; break;
+ case 16: str = "Release Resources"; break;
+ case 17: str = "Record NEWMSID"; break;
+ case 18: str = "Allocate Resources"; break;
+ case 19: str = "Generate Authentication Signature"; break;
+ case 20: str = "Release leg and redirect subscriber"; break;
+ case 21: str = "Do Not Wait For MS User Level Response"; break;
+ default:
+ if ((value >= 22) && (value <= 95)) { str = "Reserved, treat as Continue processing"; }
+ if ((value >= 96) && (value <= 127)) { str = "Reserved for protocol extension, treat as Continue processing"; }
+ if ((value >= 128) && (value <= 223)) { str = "Reserved, treat as Disconnect call"; }
+ else { str = "Reserved for protocol extension, treat as Disconnect call"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Action Code, %s (%u)",
+ str,
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_border_acc(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Border Cell Access"; break;
+ default:
+ if ((value >= 2) && (value <= 223)) { str = "Reserved, treat as Border Cell Access"; }
+ else { str = "Reserved for protocol extension, treat as Border Cell Access"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Indication, %s (%u)",
+ str,
+ value);
+}
+
+static void
+param_avail_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Unspecified MS inactivity type"; break;
+ default:
+ if ((value >= 2) && (value <= 223)) { str = "Reserved, treat as Unspecified"; }
+ else { str = "Reserved for protocol extension, treat as Unspecified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_can_type(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Serving System Option. The serving system may discontinue a call or service in progress at its option."; break;
+ case 2: str = "Report In Call. The serving system shall continue to provide service when a call or service is in progress and just report its incidence."; break;
+ case 3: str = "Discontinue. The serving system shall discontinue any call or service in progress, regardless of the MS’s qualification, profile or authentication."; break;
+ default:
+ if ((value >= 4) && (value <= 223)) { str = "Reserved, treat as Serving System Option"; }
+ else { str = "Reserved for protocol extension, treat as Serving System Option"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ str);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_can_den(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Multiple Access"; break;
+ case 2: str = "Busy"; break;
+ default:
+ if ((value >= 3) && (value <= 223)) { str = "Reserved, treat as Multiple Access"; }
+ else { str = "Reserved for protocol extension, treat as Multiple Access"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Indication, %s (%u)",
+ str,
+ value);
+}
+
+static void
+param_acc_den(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 1);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Unassigned directory number"; break;
+ case 2: str = "Inactive"; break;
+ case 3: str = "Busy"; break;
+ case 4: str = "Termination denied"; break;
+ case 5: str = "No Page response"; break;
+ case 6: str = "Unavailable"; break;
+ case 7: str = "Service Rejected by MS"; break;
+ case 8: str = "Service Rejected by the System"; break;
+ case 9: str = "Service Type Mismatch"; break;
+ case 10: str = "Service Denied"; break;
+ case 11: str = "Call Rejected"; break;
+ default:
+ if ((value >= 12) && (value <= 223)) { str = "Reserved, treat as Termination denied"; }
+ else { str = "Reserved for protocol extension, treat as Termination denied"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Access Denied Reason, %s (%u)",
+ str,
+ value);
+}
+
+static void
+param_sms_acc_den_reason(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not used"; break;
+ case 1: str = "Denied"; break;
+ case 2: str = "Postponed"; break;
+ case 3: str = "Unavailable"; break;
+ case 4: str = "Invalid"; break;
+ default:
+ if ((value >= 5) && (value <= 63)) { str = "Reserved, treat as Denied"; }
+ else if ((value >= 64) && (value <= 127)) { str = "Reserved, treat as Postponed"; }
+ else if ((value >= 128) && (value <= 223)) { str = "Reserved, treat as Unavailable"; }
+ else { str = "Reserved for protocol extension, treat as Unavailable"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Access Denied Reason, %s (%u)",
+ str,
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_sms_bd(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ tvbuff_t *next_tvb;
+
+ add_string = add_string;
+
+ next_tvb = tvb_new_subset(asn1->tvb, asn1->offset, len, len);
+
+ if (ansi_map_sms_tele_id != -1)
+ {
+ dissector_try_port(is637_tele_id_dissector_table, ansi_map_sms_tele_id, next_tvb, g_pinfo, g_tree);
+ ansi_map_sms_tele_id = -1;
+ }
+ else if (is683_ota)
+ {
+ dissector_try_port(is683_dissector_table, ansi_map_is_invoke ? 0 : 1, next_tvb, g_pinfo, g_tree);
+ }
+ else if (is801_pld)
+ {
+ dissector_try_port(is801_dissector_table, ansi_map_is_invoke ? 0 : 1, next_tvb, g_pinfo, g_tree);
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len,
+ "Parameter Data");
+
+ asn1->offset += len;
+}
+
+static void
+param_sms_cause(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Address vacant"; break;
+ case 1: str = "Address translation failure"; break;
+ case 2: str = "Network resource shortage"; break;
+ case 3: str = "Network failure"; break;
+ case 4: str = "Invalid Teleservice ID"; break;
+ case 5: str = "Other network problem"; break;
+ case 6: str = "Unsupported network interface"; break;
+ case 32: str = "No page response"; break;
+ case 33: str = "Destination busy"; break;
+ case 34: str = "No acknowledgement"; break;
+ case 35: str = "Destination resource shortage"; break;
+ case 36: str = "SMS delivery postponed"; break;
+ case 37: str = "Destination out of service"; break;
+ case 38: str = "Destination no longer at this address"; break;
+ case 39: str = "Other terminal problem"; break;
+ case 64: str = "Radio interface resource shortage"; break;
+ case 65: str = "Radio interface incompatibility"; break;
+ case 66: str = "Other radio interface problem"; break;
+ case 67: str = "Unsupported Base Station Capability"; break;
+ case 96: str = "Encoding problem"; break;
+ case 97: str = "Service origination denied"; break;
+ case 98: str = "Service termination denied"; break;
+ case 99: str = "Supplementary service not supported"; break;
+ case 100: str = "Service not supported"; break;
+ case 101: str = "Reserved"; break;
+ case 102: str = "Missing expected parameter"; break;
+ case 103: str = "Missing mandatory parameter"; break;
+ case 104: str = "Unrecognized parameter value"; break;
+ case 105: str = "Unexpected parameter value"; break;
+ case 106: str = "User Data size error"; break;
+ case 107: str = "Other general problems"; break;
+ case 108: str = "Session not active"; break;
+ default:
+ if ((value >= 7) && (value <= 31)) { str = "Reserved, treat as Other network problem"; }
+ else if ((value >= 40) && (value <= 47)) { str = "Reserved, treat as Other terminal problem"; }
+ else if ((value >= 48) && (value <= 63)) { str = "Reserved, treat as SMS delivery postponed"; }
+ else if ((value >= 68) && (value <= 95)) { str = "Reserved, treat as Other radio interface problem"; }
+ else if ((value >= 109) && (value <= 223)) { str = "Reserved, treat as Other general problems"; }
+ else { str = "Reserved for protocol extension, treat as Other general problems"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s (%u)",
+ str,
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_cdma_soci(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Value %u",
+ value);
+
+ EXTRANEOUS_DATA_CHECK(len, 1);
+}
+
+static void
+param_int(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ add_string = add_string;
+
+ if (len > 4)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, len, "Long Data (?)");
+ asn1->offset += len;
+ return;
+ }
+
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, len, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Value %u",
+ value);
+}
+
+static void
+param_pc_ssn(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value, b1, b2, b3, b4;
+ guint saved_offset;
+ gchar *str = NULL;
+
+ EXACT_DATA_CHECK(len, 5);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "Not specified"; break;
+ case 1: str = "Serving MSC"; break;
+ case 2: str = "Home MSC"; break;
+ case 3: str = "Gateway MSC"; break;
+ case 4: str = "HLR"; break;
+ case 5: str = "VLR"; break;
+ case 6: str = "EIR (reserved)"; break;
+ case 7: str = "AC"; break;
+ case 8: str = "Border MSC"; break;
+ case 9: str = "Originating MSC"; break;
+ default:
+ if ((value >= 10) && (value <= 223)) { str = "Reserved, treat as Not specified"; }
+ else { str = "Reserved for protocol extension, treat as Not specified"; }
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Type (%u) %s",
+ value,
+ str);
+
+ asn1_int32_value_decode(asn1, 1, &b1);
+ asn1_int32_value_decode(asn1, 1, &b2);
+ asn1_int32_value_decode(asn1, 1, &b3);
+ asn1_int32_value_decode(asn1, 1, &b4);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Point Code %u-%u-%u SSN %u",
+ b3, b2, b1, b4);
+}
+
+static void
+param_lai(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ gint32 value;
+ guint saved_offset;
+
+ EXACT_DATA_CHECK(len, 2);
+
+ add_string = add_string;
+ saved_offset = asn1->offset;
+
+ asn1_int32_value_decode(asn1, 2, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "LAI %u (0x%04x)",
+ value,
+ value);
+}
+
+static void
+param_list(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string)
+{
+ guint saved_offset;
+ guint num_parms;
+
+ add_string = add_string;
+ num_parms = 0;
+ saved_offset = asn1->offset;
+
+ while (len > (asn1->offset - saved_offset))
+ {
+ num_parms++;
+
+ if (!dissect_ansi_param(asn1, tree))
+ {
+ proto_tree_add_text(tree,
+ asn1->tvb, asn1->offset, len - (asn1->offset - saved_offset),
+ "Unknown Parameter Data");
+
+ asn1->offset = saved_offset + len;
+ break;
+ }
+ }
+
+ sprintf(add_string, " - (%u)", num_parms);
+}
+
+
+#define NUM_PARAM_1 (sizeof(ansi_param_1_strings)/sizeof(value_string))
+static gint ett_ansi_param_1[NUM_PARAM_1];
+static void (*param_1_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string) = {
+ param_bill_id, /* Billing ID */
+ param_int, /* Serving Cell ID */
+ param_int, /* Target Cell ID */
+ param_digits, /* Digits */
+ param_chan_data, /* Channel Data */
+ param_cic, /* Inter MSC Circuit ID */
+ param_int, /* Inter Switch Count */
+ param_min, /* Mobile Identification Number */
+ param_esn, /* Electronic Serial Number */
+ param_rel_reason, /* Release Reason */
+ param_sig_qual, /* Signal Quality */
+ param_scm, /* Station Class Mark */
+ param_auth_den, /* Authorization Denied */
+ param_auth_per, /* Authorization Period */
+ param_seizure, /* Seizure Type */
+ param_trunk_stat, /* Trunk Status */
+ param_qic, /* Qualification Information Code */
+ param_feat_result, /* Feature Result */
+ param_red_reason, /* Redirection Reason */
+ param_acc_den, /* Access Denied Reason */
+ param_mscid, /* MSCID */
+ param_sys_type_code, /* System My Type Code */
+ param_orig_ind, /* Origination Indicator */
+ param_term_res, /* Termination Restriction Code */
+ param_calling_feat_ind, /* Calling Features Indicator */
+ param_faulty, /* Faulty Parameter */
+ param_usage_ind, /* Usage Indicator */
+ param_tdma_chan_data, /* TDMA Channel Data */
+ param_tdma_call_mode, /* TDMA Call Mode */
+ param_ho_reason, /* Handoff Reason */
+ NULL, /* NONE */
+};
+
+
+#define NUM_PARAM_2 (sizeof(ansi_param_2_strings)/sizeof(value_string))
+static gint ett_ansi_param_2[NUM_PARAM_2];
+static void (*param_2_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string) = {
+ param_tdma_burst_ind, /* TDMA Burst Indicator */
+ param_pc_ssn, /* PC_SSN */
+ param_lai, /* Location Area ID */
+ param_sys_acc_type, /* System Access Type */
+ param_auth_resp_all, /* Authentication Response */
+ param_auth_resp_all, /* Authentication Response Base Station */
+ param_auth_resp_all, /* Authentication Response Unique Challenge */
+ param_int, /* Call History Count */
+ param_confid_mode, /* Confidentiality Modes */
+ param_int, /* Random Variable */
+ param_int, /* Random Variable Base station */
+ param_rand_ssd, /* Random Variable SSD */
+ param_rand_unique, /* Random Variable Unique Challenge */
+ param_report_type, /* Report Type */
+ param_sme_key, /* Signaling Message Encryption Key */
+ param_ssd, /* Shared Secret Data */
+ param_term_type, /* Terminal Type */
+ param_vpmask, /* Voice Privacy Mask */
+ param_sys_cap, /* System Capabilities */
+ param_deny_acc, /* Deny Access */
+ param_upd_count, /* Update Count */
+ param_ssd_no_share, /* SSD Not Shared */
+ param_ext_mscid, /* Extended MSCID */
+ param_ext_sys_type_code, /* Extended System My Type Code */
+ param_ctrl_chan_data, /* Control Channel Data */
+ param_sys_acc_data, /* System Access Data */
+ param_can_den, /* Cancellation Denied */
+ param_border_acc, /* Border Cell Access */
+ param_cdma_scm, /* CDMA Station Class Mark */
+ param_int, /* CDMA Serving One Way Delay */
+ param_int, /* CDMA Target One Way Delay */
+ param_cdma_call_mode, /* CDMA Call Mode */
+ param_cdma_chan_data, /* CDMA Channel Data */
+ param_cdma_sig_qual, /* CDMA Signal Quality */
+ param_cdma_pilot_strength, /* CDMA Pilot Strength */
+ param_mob_rev, /* CDMA Mobile Protocol Revision */
+ param_cdma_plcm, /* CDMA Private Long Code Mask */
+ param_cdma_code_chan, /* CDMA Code Channel */
+ param_cdma_sea_win, /* CDMA Search Window */
+ param_ms_loc, /* MS Location */
+ param_page_ind, /* Page Indicator */
+ param_rec_sig_qual, /* Received Signal Quality */
+ param_dereg, /* Deregistration Type */
+ param_namps_chan_data, /* NAMPS Channel Data */
+ param_alert_code, /* Alert Code */
+ param_ann_code, /* Announcement Code */
+ param_aav, /* Authentication Algorithm Version */
+ param_auth_cap, /* Authentication Capability */
+ param_int, /* Call History Count Expected */
+ param_digits, /* Calling Party Number Digits 1 */
+ param_digits, /* Calling Party Number Digits 2 */
+ param_digits, /* Calling Party Number String 1 */
+ param_digits, /* Calling Party Number String 2 */
+ param_sub_addr, /* Calling Party Subaddress */
+ param_can_type, /* Cancellation Type */
+ param_digits, /* Carrier Digits */
+ param_digits, /* Destination Digits */
+ param_dmh_red_ind, /* DMH Redirection Indicator */
+ param_list, /* Inter System Termination */
+ param_avail_type, /* Availability Type */
+ param_list, /* Local Termination */
+ param_mw_noti_count, /* Message Waiting Notification Count */
+ param_digits, /* Mobile Directory Number */
+ param_digits, /* MSCID Number */
+ param_list, /* PSTN Termination */
+ param_no_ans_time, /* No Answer Time */
+ param_otfi, /* One Time Feature Indicator */
+ param_orig_trig, /* Origination Triggers */
+ param_randc, /* RANDC */
+ param_digits, /* Redirecting Number Digits */
+ param_digits, /* Redirecting Number String */
+ param_sub_addr, /* Redirecting Number Subaddress */
+ param_digits, /* Sender Identification Number */
+ param_digits, /* SMS Address */
+ param_sms_bd, /* SMS Bearer Data */
+ param_sms_charge_ind, /* SMS Charge Indicator */
+ param_digits, /* SMS Destination Address */
+ param_sms_msg_count, /* SMS Message Count */
+ param_sms_noti, /* SMS Notification Indicator */
+ param_digits, /* SMS Original Destination Address */
+ param_sub_addr, /* SMS Original Destination Subaddress */
+ param_digits, /* SMS Original Originating Address */
+ param_sub_addr, /* SMS Original Originating Subaddress */
+ param_digits, /* SMS Originating Address */
+ param_sms_orig_restric, /* SMS Originating Restrictions */
+ param_sms_tele, /* SMS Teleservice Identifier */
+ param_sms_term_restric, /* SMS Termination Restrictions */
+ NULL/* no data */, /* SMS Message Waiting Indicator */
+ param_term_acc_type, /* Termination Access Type */
+ param_list, /* Termination List */
+ param_term_treat, /* Termination Treatment */
+ param_term_trig, /* Termination Triggers */
+ param_trans_cap, /* Transaction Capability */
+ param_unique_chal_rep, /* Unique Challenge Report */
+ NULL, /* NONE */
+};
+
+
+#define NUM_PARAM_3 (sizeof(ansi_param_3_strings)/sizeof(value_string))
+static gint ett_ansi_param_3[NUM_PARAM_3];
+static void (*param_3_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string) = {
+ param_act_code, /* Action Code */
+ param_alert_res, /* Alert Result */
+ param_list, /* Announcement List */
+ param_list, /* CDMA Code Channel Information */
+ param_list, /* CDMA Code Channel List */
+ param_list, /* CDMA Target Measurement Information */
+ param_list, /* CDMA Target Measurement List */
+ param_list, /* CDMA Target MAHO Information */
+ param_list, /* CDMA Target MAHO List */
+ param_conf_call_ind, /* Conference Calling Indicator */
+ param_count_upd_report, /* Count Update Report */
+ param_digit_collect_ctrl, /* Digit Collection Control */
+ param_digits, /* DMH Account Code Digits */
+ param_digits, /* DMH Alternate Billing Digits */
+ param_digits, /* DMH Billing Digits */
+ param_geo_auth, /* Geographic Authorization */
+ param_int, /* Leg Information */
+ param_mw_noti_type, /* Message Waiting Notification Type */
+ param_paca_ind, /* PACA Indicator */
+ param_pref_lang_ind, /* Preferred Language Indicator */
+ param_rand_valtime, /* Random Valid Time */
+ param_digits, /* Restriction Digits */
+ param_digits, /* Routing Digits */
+ param_setup_result, /* Setup Result */
+ param_sms_acc_den_reason, /* SMS Access Denied Reason */
+ param_sms_cause, /* SMS Cause Code */
+ param_digits, /* SPINI PIN */
+ param_spini_trig, /* SPINI Triggers */
+ param_ssd_upd_report, /* SSD Update Report */
+ param_list, /* Target Measurement Information */
+ param_list, /* Target Measurement List */
+ param_digits, /* Voice Mailbox PIN */
+ param_digits, /* Voice Mailbox Number */
+ NULL/* no special handling */, /* Authentication Data */
+ param_cond_den_reason, /* Conditionally Denied Reason */
+ param_group_info, /* Group Information */
+ param_ho_state, /* Handoff State */
+ param_namps_call_mode, /* NAMPS Call Mode */
+ param_cdma_sci, /* CDMA Slot Cycle Index */
+ param_den_auth_per, /* Denied Authorization Period */
+ param_digits, /* Pilot Number */
+ param_bill_id, /* Pilot Billing ID */
+ param_cdma_band_class, /* CDMA Band Class */
+ param_imsi, /* International Mobile Subscriber Identity */
+ param_calling_party_name, /* Calling Party Name */
+ param_dis_text, /* Display Text */
+ param_red_party_name, /* Redirecting Party Name */
+ param_srvc_id, /* Service ID */
+ param_all_or_none, /* All Or None */
+ param_change, /* Change */
+ param_list, /* Data Access Element */
+ param_list, /* Data Access Element List */
+ param_list, /* Data Update Result */
+ param_list, /* Data Update Result List */
+ param_cdma_pilot_pn, /* CDMA Pilot PN */
+ NULL/* no special handling */, /* CDMA Service Configuration Record */
+ param_cdma_so, /* CDMA Service Option */
+ param_cdma_scm2, /* CDMA Station Class Mark 2 */
+ param_tdma_sc, /* TDMA Service Code */
+ param_tdma_term_cap, /* TDMA Terminal Capability */
+ param_tdma_voice_coder, /* TDMA Voice Coder */
+ param_a_key_ver, /* A-Key Protocol Version */
+ NULL/* XXX what spec ? */, /* Authentication Response Reauthentication */
+ NULL/* no special handling */, /* Base Station Partial Key */
+ param_min, /* Mobile Station MIN */
+ NULL/* no special handling */, /* Mobile Station Partial Key */
+ NULL/* no special handling */, /* Modulus Value */
+ param_min, /* Newly Assigned MIN */
+ param_ota_result_code, /* OTASP Result Code */
+ NULL/* no special handling */, /* Primitive Value */
+ NULL/* XXX what spec ? */, /* Random Variable Reauthentication */
+ NULL/* XXX what spec ? */, /* Reauthentication Report */
+ param_srvc_ind, /* Service Indicator */
+ param_sme_report, /* Signaling Message Encryption Report */
+ param_trn, /* Temporary Reference Number */
+ param_vp_report, /* Voice Privacy Report */
+ param_ctrl_chan_mode, /* Control Channel Mode */
+ NULL/* no special handling */, /* CDMA Connection Reference */
+ param_list, /* CDMA Connection Reference Information */
+ param_list, /* CDMA Connection Reference List */
+ param_change_srvc_attr, /* Change Service Attributes */
+ NULL/* no special handling */, /* Data Key */
+ param_dp_params, /* Data Privacy Parameters */
+ param_islp_info, /* ISLP Information */
+ param_reason_list, /* Reason List */
+ param_tdma_bandwidth, /* TDMA Bandwidth */
+ param_tdma_data_feat_ind, /* TDMA Data Features Indicator */
+ param_tdma_data_mode, /* TDMA Data Mode */
+ param_tdma_voice_mode, /* TDMA Voice Mode */
+ param_ana_red_info, /* Analog Redirect Info */
+ param_list, /* CDMA Band Class Information */
+ param_list, /* CDMA Band Class List */
+ param_list, /* CDMA Service Option List */
+ param_list, /* CDMA Connection Reference Information */
+ param_list, /* CDMA Connection Reference List */
+ param_list, /* Analog Redirect Record */
+ param_list, /* Execute Script */
+ param_list, /* Modification Request */
+ param_list, /* Modification Request List */
+ param_list, /* Modification Result List */
+ param_list, /* Service Data Access Element */
+ param_list, /* Service Data Access Element List */
+ param_list, /* Service Data Result */
+ param_list, /* Service Data Result List */
+ param_list, /* Trigger Address List */
+ param_list, /* Trigger List */
+ param_list, /* WIN Capability */
+ param_list, /* Call Recovery ID */
+ param_list, /* Call Recovery ID List */
+ param_list, /* Position Information */
+ param_list, /* CDMA PSMM List */
+ param_cdma_chan_num, /* CDMA Channel Number */
+ param_list, /* CDMA Channel Number List */
+ param_cdma_pci, /* CDMA Power Combined Indicator */
+ param_list, /* CDMA Redirect Record */
+ param_cdma_sea_param, /* CDMA Search Parameters */
+ param_int, /* CDMA Network Identification */
+ param_network_tmsi, /* Network TMSI */
+ param_int, /* Network TMSI Expiration Time */
+ param_network_tmsi, /* New Network TMSI */
+ param_reqd_param_mask, /* Required Parameters Mask */
+ param_srvc_red_cause, /* Service Redirection Cause */
+ param_srvc_red_info, /* Service Redirection Info */
+ param_roaming_ind, /* Roaming Indication */
+ NULL/* XXX what spec ? */, /* MSID */
+ NULL/* no special handling */, /* Data ID */
+ NULL/* no special handling */, /* Database Key */
+ param_data_result, /* Data Result */
+ NULL/* no special handling */, /* Data Value */
+ param_fail_cause, /* Failure Cause */
+ param_fail_type, /* Failure Type */
+ NULL/* no special handling */, /* Global Title */
+ NULL/* no special handling */, /* Private Specialized Resource */
+ param_resume_pic, /* Resume PIC */
+ NULL/* no special handling */, /* Script Argument */
+ NULL/* no special handling */, /* Script Name */
+ NULL/* no special handling */, /* Script Result */
+ param_special_rsc, /* Specialized Resource */
+ param_time_date_offset, /* Time Date Offset */
+ param_trig_cap, /* Trigger Capability */
+ param_trig_type, /* Trigger Type */
+ param_win_op_cap, /* WIN Operations Capability */
+ param_win_trig_list, /* WIN Trigger List */
+ param_digits, /* MSC Address */
+ param_sus_acc, /* Suspicious Access */
+ param_imsi, /* Mobile Station IMSI */
+ param_imsi, /* Newly Assigned IMSI */
+ NULL/* XXX what spec ? */, /* Command Code */
+ param_dis_text2, /* Display Text 2 */
+ NULL/* XXX what spec ? */, /* Page Count */
+ NULL/* XXX what spec ? */, /* Page Response Time */
+ NULL/* XXX what spec ? */, /* SMS Transaction ID */
+ param_dmh_srvc_id, /* DMH Service ID */
+ param_feat_ind, /* Feature Indicator */
+ param_mscid, /* Control Network ID */
+ param_rel_cause, /* Release Cause */
+ param_time_day, /* Time Of Day */
+ param_call_status, /* Call Status */
+ NULL/* no special handling */, /* DMH Charge Information */
+ NULL/* no special handling */, /* DMH Billing Indicator */
+ param_ms_status, /* MS Status */
+ param_pos_info_code, /* Position Information Code */
+ param_inter_msg_time, /* Inter Message Time */
+ param_msid_usage, /* MSID Usage */
+ param_new_min_ext, /* New MIN Extension */
+ param_dtx_ind, /* DTX Indication */
+ param_cdma_mob_cap, /* CDMA Mobile Capabilities */
+ param_gen_time, /* Generalized Time */
+ param_digits, /* Generic Digits */
+ param_geo_pos, /* Geographic Position */
+ param_mob_call_status, /* Mobile Call Status */
+ param_mob_cap, /* Mobile Position Capability */
+ param_pos_req_type, /* Position Request Type */
+ param_pos_result, /* Position Result */
+ param_pos_source, /* Position Source */
+ param_acg_encounter, /* ACG Encountered */
+ param_ctrl_type, /* CDMA State/Control Type */
+ param_gap_duration, /* Gap Duration */
+ param_scf_overload_gap_int, /* SCF Overload Gap Interval */
+ param_sm_gap_int, /* Service Management System Gap Interval */
+ param_cdma_psmm_count, /* CDMA PSMM Count */
+ param_cdma_sowd2, /* CDMA Serving One Way Delay 2 */
+ param_qos_pri, /* QoS Priority */
+ NULL/* no special handling */, /* PDSN Address */
+ NULL/* no special handling */, /* PDSN Protocol Type */
+ param_cdma_ms_meas_chan_id, /* CDMA MS Measured Channel Identity */
+ NULL/* no special handling */, /* Range */
+ param_calling_party_cat, /* Calling Party Category */
+ param_cdma2000_ho_ivk_ios, /* cdma2000 Handoff Invoke IOS Data */
+ param_cdma2000_ho_rsp_ios, /* cdma2000 Handoff Response IOS Data */
+ param_digits, /* LCS Client ID */
+ param_tdma_maho_cell_id, /* TDMA MAHO Cell ID */
+ param_tdma_maho_chan, /* TDMA MAHO Channel */
+ param_cdma_soci, /* CDMA Service Option Connection Identifier */
+ param_tdma_time_align, /* TDMA Time Alignment */
+ param_tdma_maho_req, /* TDMA MAHO Request */
+ NULL, /* NONE */
+};
+
+/* GENERIC MAP DISSECTOR FUNCTIONS */
+
+static void
+dissect_ansi_map_len(ASN1_SCK *asn1, proto_tree *tree, gboolean *def_len, guint *len)
+{
+ guint saved_offset;
+ int ret;
+
+
+ saved_offset = asn1->offset;
+ *def_len = FALSE;
+ *len = 0;
+
+ ret = asn1_length_decode(asn1, def_len, len);
+
+ if (*def_len)
+ {
+ proto_tree_add_uint(tree, hf_ansi_map_length, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ *len);
+ }
+ else
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "Length: Indefinite");
+ }
+
+}
+
+static gboolean
+check_ansi_map_tag(ASN1_SCK *asn1, guint tag)
+{
+ guint saved_offset, real_tag;
+
+
+ saved_offset = asn1->offset;
+
+ asn1_id_decode1(asn1, &real_tag);
+
+ asn1->offset = saved_offset;
+
+ return(tag == real_tag);
+}
+
+static void
+dissect_ansi_map_octet(ASN1_SCK *asn1, proto_tree *tree, guchar * str)
+{
+ guint saved_offset;
+ guchar my_oct;
+
+
+ saved_offset = asn1->offset;
+
+ asn1_octet_decode(asn1, &my_oct);
+
+ proto_tree_add_uint_format(tree, hf_ansi_map_id, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, my_oct,
+ "%s %u",
+ str, my_oct);
+}
+
+static proto_tree *
+dissect_ansi_map_component(ASN1_SCK *asn1, proto_tree *tree, guint *len_p)
+{
+ guint saved_offset;
+ guint tag;
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean def_len;
+
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, -1, "Component ID");
+
+ subtree = proto_item_add_subtree(item, ett_component);
+
+ proto_tree_add_uint_format(subtree, hf_ansi_map_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag,
+ "Component ID Identifier");
+
+ dissect_ansi_map_len(asn1, subtree, &def_len, len_p);
+
+ proto_item_set_len(item, (asn1->offset - saved_offset) + *len_p);
+
+ return(subtree);
+}
+
+static void
+dissect_ansi_opr_code(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree, gint32 *opr_code_p)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ gint32 val;
+ gchar *str = NULL;
+ guchar my_oct;
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean def_len;
+
+
+ *opr_code_p = -1;
+
+#define TCAP_NAT_OPR_CODE_TAG 0xd0
+ if (check_ansi_map_tag(asn1, TCAP_NAT_OPR_CODE_TAG))
+ {
+ str = "National TCAP Operation Code Identifier";
+ }
+#define TCAP_PRIV_OPR_CODE_TAG 0xd1
+ else if (check_ansi_map_tag(asn1, TCAP_PRIV_OPR_CODE_TAG))
+ {
+ str = "Private TCAP Operation Code Identifier";
+ }
+ else
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ asn1->offset, -1, "Unexpected tag, not National or Private TCAP Operation Code");
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, -1, "Operation Code");
+
+ subtree = proto_item_add_subtree(item, ett_opr_code);
+
+ proto_tree_add_uint_format(subtree, hf_ansi_map_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, str);
+
+ dissect_ansi_map_len(asn1, subtree, &def_len, &len);
+ proto_item_set_len(item, (asn1->offset - saved_offset) + len);
+
+ if (len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_octet_decode(asn1, &my_oct);
+
+#define ANSI_MAP_OPR_FAMILY 0x09
+ if (my_oct != ANSI_MAP_OPR_FAMILY)
+ {
+ asn1->offset = saved_offset;
+ return;
+ }
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1, "Operation Code Family");
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len-1, &val);
+ proto_tree_add_int(subtree, hf_ansi_map_opr_code, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, val);
+
+ str = match_strval(val, ansi_map_opr_code_strings);
+
+ if (NULL == str) return;
+
+ *opr_code_p = val;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
+ }
+ }
+}
+
+static void
+dissect_ansi_problem(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ proto_tree *subtree;
+ proto_item *item = NULL;
+ gchar *str = NULL;
+ gchar *type_str = NULL;
+ gint32 type, spec;
+ gboolean def_len;
+
+
+#define TCAP_PROB_CODE_TAG 0xd5
+ if (check_ansi_map_tag(asn1, TCAP_PROB_CODE_TAG))
+ {
+ str = "Problem Code Identifier";
+ }
+ else
+ {
+ /* XXX */
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, -1, "Problem Code");
+
+ subtree = proto_item_add_subtree(item, ett_problem);
+
+ proto_tree_add_uint_format(subtree, hf_ansi_map_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, str);
+
+ dissect_ansi_map_len(asn1, subtree, &def_len, &len);
+ proto_item_set_len(item, (asn1->offset - saved_offset) + len);
+
+ if (len != 2)
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ asn1->offset, len, "Unknown encoding of Problem Code");
+
+ asn1->offset += len;
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &type);
+ asn1_int32_value_decode(asn1, 1, &spec);
+
+ switch (type)
+ {
+ case 0: type_str = "Not used"; break;
+
+ case 1:
+ type_str = "General";
+ switch (spec)
+ {
+ case 1: str = "Unrecognized Component Type"; break;
+ case 2: str = "Incorrect Component Portion"; break;
+ case 3: str = "Badly Structured Component Portion"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 2:
+ type_str = "Invoke";
+ switch (spec)
+ {
+ case 1: str = "Duplicate Invoke ID"; break;
+ case 2: str = "Unrecognized Operation Code"; break;
+ case 3: str = "Incorrect Parameter"; break;
+ case 4: str = "Unrecognized Correlation ID"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 3:
+ type_str = "Return Result";
+ switch (spec)
+ {
+ case 1: str = "Unrecognized Correlation ID"; break;
+ case 2: str = "Unexpected Return Result"; break;
+ case 3: str = "Incorrect Parameter"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 4:
+ type_str = "Return Error";
+ switch (spec)
+ {
+ case 1: str = "Unrecognized Correlation ID"; break;
+ case 2: str = "Unexpected Return Error"; break;
+ case 3: str = "Unrecognized Error"; break;
+ case 4: str = "Unexpected Error"; break;
+ case 5: str = "Incorrect Parameter"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 5:
+ type_str = "Transaction Portion";
+ switch (spec)
+ {
+ case 1: str = "Unrecognized Package Type"; break;
+ case 2: str = "Incorrect Transaction Portion"; break;
+ case 3: str = "Badly Structured Transaction Portion"; break;
+ case 4: str = "Unrecognized Transaction ID"; break;
+ case 5: str = "Permission to Release"; break;
+ case 6: str = "Resource Unavailable"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ default:
+ type_str = "Undefined";
+ break;
+ }
+
+ if (spec == 255) { str = "Reserved"; }
+ else if (spec == 0) { str = "Not used"; }
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1, "Problem Type %s", type_str);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset + 1, 1, "Problem Specifier %s", str);
+}
+
+static void
+dissect_ansi_error(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ gint32 value;
+ proto_tree *subtree;
+ proto_item *item = NULL;
+ gchar *str = NULL;
+ gboolean def_len;
+
+
+#define TCAP_NAT_ERR_CODE_TAG 0xd3
+ if (check_ansi_map_tag(asn1, TCAP_NAT_ERR_CODE_TAG))
+ {
+ str = "National TCAP Error Code Identifier";
+ }
+#define TCAP_PRIV_ERR_CODE_TAG 0xd4
+ else if (check_ansi_map_tag(asn1, TCAP_PRIV_ERR_CODE_TAG))
+ {
+ str = "Private TCAP Error Code Identifier";
+ }
+ else
+ {
+ /* XXX */
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, -1, "TCAP Error Code");
+
+ subtree = proto_item_add_subtree(item, ett_error);
+
+ proto_tree_add_uint_format(subtree, hf_ansi_map_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, str);
+
+ dissect_ansi_map_len(asn1, subtree, &def_len, &len);
+ proto_item_set_len(item, (asn1->offset - saved_offset) + len);
+
+ if ((tag == TCAP_PRIV_ERR_CODE_TAG) &&
+ (len == 1))
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0x81: str = "Unrecognized MIN"; break;
+ case 0x82: str = "Unrecognized ESN"; break;
+ case 0x83: str = "MIN/HLR Mismatch"; break;
+ case 0x84: str = "Operation Sequence Problem"; break;
+ case 0x85: str = "Resource Shortage"; break;
+ case 0x86: str = "Operation Not Supported"; break;
+ case 0x87: str = "Trunk Unavailable"; break;
+ case 0x88: str = "Parameter Error"; break;
+ case 0x89: str = "System Failure"; break;
+ case 0x8a: str = "Unrecognized Parameter Value"; break;
+ case 0x8b: str = "Feature Inactive"; break;
+ case 0x8c: str = "Missing Parameter"; break;
+ default:
+ if ((value >= 0xe0) && (value <= 0xff)) { str = "Reserved for protocol extension"; }
+ else { str = "Reserved"; }
+ break;
+ }
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1, str);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ asn1->offset, len, "Error Code");
+
+ asn1->offset += len;
+ }
+}
+
+
+static gboolean
+dissect_ansi_param(ASN1_SCK *asn1, proto_tree *tree)
+{
+ void (*param_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar *add_string) = NULL;
+ guint saved_offset = 0;
+ guint len;
+ proto_tree *subtree;
+ proto_item *item;
+ guint val;
+ gchar *str = NULL;
+ gint ett_param_idx, idx;
+ gboolean def_len;
+
+
+ saved_offset = asn1->offset;
+
+ asn1_uint32_value_decode(asn1, 1, &val);
+ str = my_match_strval((guint32) val, ansi_param_1_strings, &idx);
+
+ if (NULL == str)
+ {
+ asn1->offset = saved_offset;
+ asn1_uint32_value_decode(asn1, 2, &val);
+
+ str = my_match_strval((guint32) val, ansi_param_2_strings, &idx);
+
+ if (NULL == str)
+ {
+ asn1->offset = saved_offset;
+ asn1_int32_value_decode(asn1, 3, &val);
+
+ str = my_match_strval((guint32) val, ansi_param_3_strings, &idx);
+
+ if (NULL == str)
+ {
+ if (((val >= 0x9FFF00) && (val <= 0x9FFF7F)) ||
+ ((val >= 0xBFFF00) && (val <= 0xBFFF7F)))
+ {
+ str = "Reserved for protocol extension";
+ }
+ else if (((val >= 0x9FFE76) && (val <= 0x9FFE7F)) ||
+ ((val >= 0xBFFE76) && (val <= 0xBFFE7F)))
+ {
+ str = "Reserved for National Network Use";
+ }
+ else
+ {
+ str = "Unknown Parameter Data";
+ param_fcn = NULL;
+ }
+
+ ett_param_idx = ett_param;
+ }
+ else
+ {
+ ett_param_idx = ett_ansi_param_3[idx];
+ param_fcn = param_3_fcn[idx];
+ }
+ }
+ else
+ {
+ ett_param_idx = ett_ansi_param_2[idx];
+ param_fcn = param_2_fcn[idx];
+ }
+ }
+ else
+ {
+ ett_param_idx = ett_ansi_param_1[idx];
+ param_fcn = param_1_fcn[idx];
+ }
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, -1, str);
+
+ subtree = proto_item_add_subtree(item, ett_param_idx);
+
+ proto_tree_add_uint_format(subtree, hf_ansi_map_param_id, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, val, "Parameter ID");
+
+ dissect_ansi_map_len(asn1, subtree, &def_len, &len);
+
+ proto_item_set_len(item, asn1->offset - saved_offset + len);
+
+ if (len > 0)
+ {
+ if (param_fcn == NULL)
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ asn1->offset, len, "Parameter Data");
+ asn1->offset += len;
+ }
+ else
+ {
+ ansi_map_add_string[0] = '\0';
+
+ (*param_fcn)(asn1, subtree, len, ansi_map_add_string);
+
+ if (ansi_map_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, ansi_map_add_string);
+ ansi_map_add_string[0] = '\0';
+ }
+ }
+ }
+
+ return(TRUE);
+}
+
+
+static void
+dissect_ansi_params(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ proto_tree *subtree;
+ proto_item *item = NULL;
+ gchar *str = NULL;
+ gboolean def_len;
+
+#define TCAP_PARAM_SET_TAG 0xf2
+ if (check_ansi_map_tag(asn1, TCAP_PARAM_SET_TAG))
+ {
+ str = "Parameter Set Identifier";
+ }
+#define TCAP_PARAM_SEQ_TAG 0x30
+ else if (check_ansi_map_tag(asn1, TCAP_PARAM_SEQ_TAG))
+ {
+ str = "Parameter Sequence Identifier";
+ }
+ else
+ {
+ /* XXX */
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, -1, "Parameters");
+
+ subtree = proto_item_add_subtree(item, ett_params);
+
+ proto_tree_add_uint_format(subtree, hf_ansi_map_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, str);
+
+ dissect_ansi_map_len(asn1, subtree, &def_len, &len);
+ proto_item_set_len(item, (asn1->offset - saved_offset) + len);
+
+ ansi_map_add_string[0] = '\0';
+
+ param_list(asn1, subtree, len, ansi_map_add_string);
+
+ if (ansi_map_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, ansi_map_add_string);
+ ansi_map_add_string[0] = '\0';
+ }
+}
+
+static void
+dissect_ansi_map_reject(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ proto_tree *subtree;
+
+#define COMPONENT_ID_TAG 0xcf
+ if (check_ansi_map_tag(asn1, COMPONENT_ID_TAG))
+ {
+ subtree = dissect_ansi_map_component(asn1, tree, &len);
+
+ switch (len)
+ {
+ case 1:
+ dissect_ansi_map_octet(asn1, subtree, "Correlation ID:");
+ break;
+ }
+ }
+
+ dissect_ansi_problem(asn1, tree);
+
+ dissect_ansi_params(asn1, tree);
+}
+
+static void
+dissect_ansi_map_re(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ proto_tree *subtree;
+
+#define COMPONENT_ID_TAG 0xcf
+ if (check_ansi_map_tag(asn1, COMPONENT_ID_TAG))
+ {
+ subtree = dissect_ansi_map_component(asn1, tree, &len);
+
+ switch (len)
+ {
+ case 1:
+ dissect_ansi_map_octet(asn1, subtree, "Correlation ID:");
+ break;
+ }
+ }
+
+ dissect_ansi_error(asn1, tree);
+
+ dissect_ansi_params(asn1, tree);
+}
+
+static void
+dissect_ansi_map_rr(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ proto_tree *subtree;
+
+#define COMPONENT_ID_TAG 0xcf
+ if (check_ansi_map_tag(asn1, COMPONENT_ID_TAG))
+ {
+ subtree = dissect_ansi_map_component(asn1, tree, &len);
+
+ switch (len)
+ {
+ case 1:
+ dissect_ansi_map_octet(asn1, subtree, "Correlation ID:");
+ break;
+ }
+ }
+
+ dissect_ansi_params(asn1, tree);
+}
+
+static void
+dissect_ansi_map_invoke(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree, gint *opr_code_p)
+{
+ guint len;
+ proto_tree *subtree;
+
+#define COMPONENT_ID_TAG 0xcf
+ if (check_ansi_map_tag(asn1, COMPONENT_ID_TAG))
+ {
+ subtree = dissect_ansi_map_component(asn1, tree, &len);
+
+ switch (len)
+ {
+ case 1:
+ dissect_ansi_map_octet(asn1, subtree, "Invoke ID:");
+ break;
+
+ case 2:
+ dissect_ansi_map_octet(asn1, subtree, "Invoke ID:");
+ dissect_ansi_map_octet(asn1, subtree, "Correlation ID:");
+ break;
+ }
+ }
+
+ ansi_map_is_invoke = TRUE;
+
+ dissect_ansi_opr_code(asn1, pinfo, tree, opr_code_p);
+
+ dissect_ansi_params(asn1, tree);
+}
+
+static void
+dissect_ansi_map_message(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *ansi_map_tree)
+{
+ static ansi_map_tap_rec_t tap_rec;
+ guint saved_offset;
+ guint tag;
+ guint len;
+ gchar *str = NULL;
+ proto_item *item, *tag_item;
+ proto_tree *subtree, *tag_subtree;
+ gboolean def_len;
+ static int i = 0;
+ gint opr_code;
+
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ str = match_strval(tag, ansi_cmp_type_strings);
+
+ if (NULL == str) return;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (0 == i)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "& %s ", str);
+ }
+ }
+
+ item =
+ proto_tree_add_text(ansi_map_tree, asn1->tvb,
+ saved_offset, -1, "Components");
+ subtree = proto_item_add_subtree(item, ett_components);
+
+ tag_item =
+ proto_tree_add_uint_format(subtree, hf_ansi_map_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, str);
+
+ dissect_ansi_map_len(asn1, subtree, &def_len, &len);
+
+ tag_subtree = proto_item_add_subtree(tag_item, ett_components);
+
+ opr_code = -1;
+
+ switch (tag)
+ {
+ case ANSI_TC_INVOKE_L:
+ dissect_ansi_map_invoke(asn1, pinfo, tag_subtree, &opr_code);
+ break;
+
+ case ANSI_TC_RRL:
+ dissect_ansi_map_rr(asn1, tag_subtree);
+ break;
+
+ case ANSI_TC_RE:
+ dissect_ansi_map_re(asn1, tag_subtree);
+ break;
+
+ case ANSI_TC_REJECT:
+ dissect_ansi_map_reject(asn1, tag_subtree);
+ break;
+
+ case ANSI_TC_INVOKE_N:
+ dissect_ansi_map_invoke(asn1, pinfo, tag_subtree, &opr_code);
+ break;
+
+ case ANSI_TC_RRN:
+ dissect_ansi_map_rr(asn1, tag_subtree);
+ break;
+
+ default:
+ /* XXX */
+ break;
+ }
+
+ proto_item_set_len(item, asn1->offset - saved_offset);
+
+ if (opr_code != -1)
+ {
+ tap_rec.message_type = opr_code;
+ tap_rec.size = asn1->offset - saved_offset;
+
+ tap_queue_packet(ansi_map_tap, pinfo, &tap_rec);
+ }
+}
+
+static void
+dissect_ansi_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ansi_map_item;
+ proto_tree *ansi_map_tree = NULL;
+ ASN1_SCK asn1;
+ int offset = 0;
+
+ g_pinfo = pinfo;
+
+ /*
+ * Make entry in the Protocol column on summary display
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ANSI MAP");
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree)
+ {
+ g_tree = tree;
+
+ /*
+ * create the ansi_map protocol tree
+ */
+ ansi_map_item =
+ proto_tree_add_item(tree, proto_ansi_map, tvb, 0, -1, FALSE);
+
+ ansi_map_tree =
+ proto_item_add_subtree(ansi_map_item, ett_ansi_map);
+
+ asn1_open(&asn1, tvb, offset);
+
+ ansi_map_is_invoke = FALSE;
+ is683_ota = FALSE;
+ is801_pld = FALSE;
+ dissect_ansi_map_message(&asn1, pinfo, ansi_map_tree);
+
+ asn1_close(&asn1, &offset);
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_ansi_map(void)
+{
+ guint i;
+ gint last_offset;
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] =
+ {
+ { &hf_ansi_map_tag,
+ { "Tag", "ansi_map.tag",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_map_length,
+ { "Length", "ansi_map.len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_map_id,
+ { "Value", "ansi_map.id",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_map_opr_code,
+ { "Operation Code", "ansi_map.oprcode",
+ FT_INT32, BASE_DEC, VALS(ansi_map_opr_code_strings), 0,
+ "", HFILL }
+ },
+ { &hf_ansi_map_param_id,
+ { "Param ID", "ansi_map.param_id",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_ansi_map_ios401_elem_id,
+ { "IOS 4.0.1 Element ID", "ansi_map.ios401_elem_id",
+ FT_NONE, 0, NULL, 0,
+ "", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+#define NUM_INDIVIDUAL_PARAMS 15
+ gint *ett[NUM_INDIVIDUAL_PARAMS+NUM_PARAM_1+NUM_PARAM_2+NUM_PARAM_3+NUM_IOS401_ELEM];
+
+ memset((void *) ett, -1, sizeof(ett));
+
+ ett[0] = &ett_ansi_map;
+ ett[1] = &ett_opr_code;
+ ett[2] = &ett_component;
+ ett[3] = &ett_components;
+ ett[4] = &ett_param;
+ ett[5] = &ett_params;
+ ett[6] = &ett_error;
+ ett[7] = &ett_problem;
+ ett[8] = &ett_natnum;
+ ett[9] = &ett_call_mode;
+ ett[10] = &ett_chan_data;
+ ett[11] = &ett_code_chan;
+ ett[12] = &ett_clr_dig_mask;
+ ett[13] = &ett_ent_dig_mask;
+ ett[14] = &ett_all_dig_mask;
+
+ last_offset = NUM_INDIVIDUAL_PARAMS;
+
+ for (i=0; i < NUM_PARAM_1; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_ansi_param_1[i];
+ }
+
+ for (i=0; i < NUM_PARAM_2; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_ansi_param_2[i];
+ }
+
+ for (i=0; i < NUM_PARAM_3; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_ansi_param_3[i];
+ }
+
+ for (i=0; i < NUM_IOS401_ELEM; i++, last_offset++)
+ {
+ ett[last_offset] = &ett_ansi_map_ios401_elem[i];
+ }
+
+ /* Register the protocol name and description */
+ proto_ansi_map =
+ proto_register_protocol("ANSI Mobile Application Part",
+ "ANSI MAP", "ansi_map");
+
+ is637_tele_id_dissector_table =
+ register_dissector_table("ansi_map.tele_id", "IS-637 Teleservice ID",
+ FT_UINT8, BASE_DEC);
+
+ is683_dissector_table =
+ register_dissector_table("ansi_map.ota", "IS-683-A (OTA)",
+ FT_UINT8, BASE_DEC);
+
+ is801_dissector_table =
+ register_dissector_table("ansi_map.pld", "IS-801 (PLD)",
+ FT_UINT8, BASE_DEC);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ansi_map, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ansi_map_tap = register_tap("ansi_map");
+}
+
+
+void
+proto_reg_handoff_ansi_map(void)
+{
+ dissector_handle_t ansi_map_handle;
+
+ ansi_map_handle = create_dissector_handle(dissect_ansi_map, proto_ansi_map);
+
+ dissector_add("tcap.ansi_ssn", 5, ansi_map_handle);
+ dissector_add("tcap.ansi_ssn", 6, ansi_map_handle);
+ dissector_add("tcap.ansi_ssn", 7, ansi_map_handle);
+ dissector_add("tcap.ansi_ssn", 8, ansi_map_handle);
+ dissector_add("tcap.ansi_ssn", 9 , ansi_map_handle);
+ dissector_add("tcap.ansi_ssn", 10 , ansi_map_handle);
+ dissector_add("tcap.ansi_ssn", 11 , ansi_map_handle);
+ dissector_add("tcap.ansi_ssn", 12 , ansi_map_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ansi_map.h b/epan/dissectors/packet-ansi_map.h
new file mode 100644
index 0000000000..db7e4e9f79
--- /dev/null
+++ b/epan/dissectors/packet-ansi_map.h
@@ -0,0 +1,41 @@
+/* packet-ansi_map.h
+ *
+ * $Id$
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>,
+ * In association with Telos Technology Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ANSI_MAP_MAX_NUM_MESSAGE_TYPES 256
+
+typedef struct _ansi_map_tap_rec_t {
+ guint8 message_type;
+ guint16 size;
+} ansi_map_tap_rec_t;
+
+
+/*
+ * the following allows TAP code access to the messages
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string ansi_map_opr_code_strings[];
+
diff --git a/epan/dissectors/packet-aodv.c b/epan/dissectors/packet-aodv.c
new file mode 100644
index 0000000000..b262dccc79
--- /dev/null
+++ b/epan/dissectors/packet-aodv.c
@@ -0,0 +1,979 @@
+/* packet-aodv.c
+ * Routines for AODV dissection
+ * Copyright 2000, Erik Nordström <erik.nordstrom@it.uu.se>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/int-64bit.h>
+#include <epan/packet.h>
+#include <epan/ipv6-utils.h>
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+/*
+ * See
+ *
+ * http://www.ietf.org/internet-drafts/draft-ietf-manet-aodv-13.txt
+ *
+ * http://www.cs.ucsb.edu/~ebelding/txt/aodv6.txt
+ *
+ * http://www.tcs.hut.fi/~anttit/manet/drafts/draft-perkins-aodv6-01.txt
+ */
+
+#define INET6_ADDRLEN 16
+#define UDP_PORT_AODV 654
+
+/* Message Types */
+#define RREQ 1
+#define RREP 2
+#define RERR 3
+#define RREP_ACK 4
+#define DRAFT_01_V6_RREQ 16
+#define DRAFT_01_V6_RREP 17
+#define DRAFT_01_V6_RERR 18
+#define DRAFT_01_V6_RREP_ACK 19
+
+/* Extension Types */
+#define AODV_EXT 1
+#define AODV_EXT_INT 2
+#define AODV_EXT_NTP 3
+
+/* Flag bits: */
+#define RREQ_GRAT 0x20
+#define RREQ_REP 0x40
+#define RREQ_JOIN 0x80
+
+#define RREP_ACK_REQ 0x40
+#define RREP_REP 0x80
+
+#define RERR_NODEL 0x80
+
+static const value_string type_vals[] = {
+ { RREQ, "Route Request" },
+ { RREP, "Route Reply" },
+ { RERR, "Route Error" },
+ { RREP_ACK, "Route Reply Acknowledgment"},
+ { DRAFT_01_V6_RREQ, "draft-perkins-aodv6-01 Route Request"},
+ { DRAFT_01_V6_RREP, "draft-perkins-aodv6-01 Route Reply"},
+ { DRAFT_01_V6_RERR, "draft-perkins-aodv6-01 Route Error"},
+ { DRAFT_01_V6_RREP_ACK, "draft-perkins-aodv6-01 Route Reply Acknowledgment"},
+ { 0, NULL }
+};
+
+static const value_string exttype_vals[] = {
+ { AODV_EXT, "None"},
+ { AODV_EXT_INT, "Hello Interval"},
+ { AODV_EXT_NTP, "Timestamp"},
+ { 0, NULL}
+};
+
+typedef struct v6_ext {
+ guint8 type;
+ guint8 length;
+} aodv_ext_t;
+
+/* Initialize the protocol and registered fields */
+static int proto_aodv = -1;
+static int hf_aodv_type = -1;
+static int hf_aodv_flags = -1;
+static int hf_aodv_prefix_sz = -1;
+static int hf_aodv_hopcount = -1;
+static int hf_aodv_rreq_id = -1;
+static int hf_aodv_dest_ip = -1;
+static int hf_aodv_dest_ipv6 = -1;
+static int hf_aodv_dest_seqno = -1;
+static int hf_aodv_orig_ip = -1;
+static int hf_aodv_orig_ipv6 = -1;
+static int hf_aodv_orig_seqno = -1;
+static int hf_aodv_lifetime = -1;
+static int hf_aodv_destcount = -1;
+static int hf_aodv_unreach_dest_ip = -1;
+static int hf_aodv_unreach_dest_ipv6 = -1;
+static int hf_aodv_unreach_dest_seqno = -1;
+static int hf_aodv_flags_rreq_join = -1;
+static int hf_aodv_flags_rreq_repair = -1;
+static int hf_aodv_flags_rreq_gratuitous = -1;
+static int hf_aodv_flags_rrep_repair = -1;
+static int hf_aodv_flags_rrep_ack = -1;
+static int hf_aodv_flags_rerr_nodelete = -1;
+static int hf_aodv_ext_type = -1;
+static int hf_aodv_ext_length = -1;
+static int hf_aodv_ext_interval = -1;
+static int hf_aodv_ext_timestamp = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_aodv = -1;
+static gint ett_aodv_flags = -1;
+static gint ett_aodv_unreach_dest = -1;
+static gint ett_aodv_extensions = -1;
+
+/* Code to actually dissect the packets */
+
+static void
+dissect_aodv_ext(tvbuff_t * tvb, int offset, proto_tree * tree)
+{
+ proto_tree *ext_tree;
+ proto_item *ti;
+ aodv_ext_t aodvext, *ext;
+ int len;
+
+ if (!tree)
+ return;
+
+ again:
+ if ((int) tvb_reported_length(tvb) <= offset)
+ return; /* No more options left */
+
+ ext = &aodvext;
+ tvb_memcpy(tvb, (guint8 *) ext, offset, sizeof(*ext));
+ len = ext->length;
+
+ ti = proto_tree_add_text(tree, tvb, offset, sizeof(aodv_ext_t) +
+ len, "Extensions");
+ ext_tree = proto_item_add_subtree(ti, ett_aodv_extensions);
+
+ if (len == 0) {
+ proto_tree_add_text(ext_tree, tvb,
+ offset + offsetof(aodv_ext_t, length), 1,
+ "Invalid option length: %u", ext->length);
+ return; /* we must not try to decode this */
+ }
+
+ proto_tree_add_text(ext_tree, tvb,
+ offset + offsetof(aodv_ext_t, type), 1,
+ "Type: %u (%s)", ext->type,
+ val_to_str(ext->type, exttype_vals, "Unknown"));
+ proto_tree_add_text(ext_tree, tvb,
+ offset + offsetof(aodv_ext_t, length), 1,
+ "Length: %u bytes", ext->length);
+
+ offset += sizeof(aodv_ext_t);
+
+ switch (ext->type) {
+ case AODV_EXT_INT:
+ proto_tree_add_uint(ext_tree, hf_aodv_ext_interval,
+ tvb, offset, 4, tvb_get_ntohl(tvb, offset));
+ break;
+ case AODV_EXT_NTP:
+ proto_tree_add_item(ext_tree, hf_aodv_ext_timestamp,
+ tvb, offset, 8, FALSE);
+ break;
+ default:
+ break;
+ }
+ /* If multifield extensions appear, we need more
+ * sophisticated handler. For now, this is okay. */
+
+ offset += ext->length;
+ goto again;
+}
+
+static void
+dissect_aodv_rreq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
+ proto_item *ti, gboolean is_ipv6)
+{
+ int offset = 1;
+ proto_item *tj;
+ proto_tree *aodv_flags_tree;
+ guint8 flags;
+ guint8 hop_count;
+ guint32 rreq_id;
+ guint32 dest_addr_v4;
+ struct e_in6_addr dest_addr_v6;
+ guint32 dest_seqno;
+ guint32 orig_addr_v4;
+ struct e_in6_addr orig_addr_v6;
+ guint32 orig_seqno;
+ int extlen;
+
+ flags = tvb_get_guint8(tvb, offset);
+ if (aodv_tree) {
+ tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
+ aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_join,
+ tvb, offset, 1, flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_repair,
+ tvb, offset, 1, flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_gratuitous,
+ tvb, offset, 1, flags);
+ if (flags & RREQ_JOIN)
+ proto_item_append_text(tj, " J");
+ if (flags & RREQ_REP)
+ proto_item_append_text(tj, " R");
+ if (flags & RREQ_GRAT)
+ proto_item_append_text(tj, " G");
+ }
+ offset += 2; /* skip reserved byte */
+
+ hop_count = tvb_get_guint8(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
+ hop_count);
+ offset += 1;
+
+ rreq_id = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_rreq_id, tvb, offset, 4,
+ rreq_id);
+ offset += 4;
+
+ if (is_ipv6) {
+ tvb_memcpy(tvb, (guint8 *)&dest_addr_v6, offset, INET6_ADDRLEN);
+ if (aodv_tree) {
+ proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
+ INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
+ proto_item_append_text(ti, ", Dest IP: %s",
+ ip6_to_str(&dest_addr_v6));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
+ ip6_to_str(&dest_addr_v6));
+ offset += INET6_ADDRLEN;
+ } else {
+ tvb_memcpy(tvb, (guint8 *)&dest_addr_v4, offset, 4);
+ if (aodv_tree) {
+ proto_tree_add_ipv4(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
+ dest_addr_v4);
+ proto_item_append_text(ti, ", Dest IP: %s",
+ ip_to_str((guint8 *)&dest_addr_v4));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
+ ip_to_str((guint8 *)&dest_addr_v4));
+ offset += 4;
+ }
+
+ dest_seqno = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
+ dest_seqno);
+ offset += 4;
+
+ if (is_ipv6) {
+ tvb_memcpy(tvb, (guint8 *)&orig_addr_v6, offset, INET6_ADDRLEN);
+ if (aodv_tree) {
+ proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
+ INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
+ proto_item_append_text(ti, ", Orig IP: %s",
+ ip6_to_str(&orig_addr_v6));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
+ ip6_to_str(&orig_addr_v6));
+ offset += INET6_ADDRLEN;
+ } else {
+ tvb_memcpy(tvb, (guint8 *)&orig_addr_v4, offset, 4);
+ if (aodv_tree) {
+ proto_tree_add_ipv4(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
+ orig_addr_v4);
+ proto_item_append_text(ti, ", Orig IP: %s",
+ ip_to_str((guint8 *)&orig_addr_v4));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
+ ip_to_str((guint8 *)&orig_addr_v4));
+ offset += 4;
+ }
+
+ orig_seqno = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
+ orig_seqno);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Id=%u Hcnt=%u DSN=%u OSN=%u",
+ rreq_id,
+ hop_count,
+ dest_seqno,
+ orig_seqno);
+ offset += 4;
+
+ if (aodv_tree) {
+ extlen = tvb_reported_length_remaining(tvb, offset);
+ if (extlen > 0)
+ dissect_aodv_ext(tvb, offset, aodv_tree);
+ }
+}
+
+static void
+dissect_aodv_rrep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
+ proto_item *ti, gboolean is_ipv6)
+{
+ int offset = 1;
+ proto_item *tj;
+ proto_tree *aodv_flags_tree;
+ guint8 flags;
+ guint8 prefix_sz;
+ guint8 hop_count;
+ guint32 dest_addr_v4;
+ struct e_in6_addr dest_addr_v6;
+ guint32 dest_seqno;
+ guint32 orig_addr_v4;
+ struct e_in6_addr orig_addr_v6;
+ guint32 lifetime;
+ int extlen;
+
+ flags = tvb_get_guint8(tvb, offset);
+ if (aodv_tree) {
+ tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
+ aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_repair,
+ tvb, offset, 1, flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_ack, tvb,
+ offset, 1, flags);
+ if (flags & RREP_REP)
+ proto_item_append_text(tj, " R");
+ if (flags & RREP_ACK_REQ)
+ proto_item_append_text(tj, " A");
+ }
+ offset += 1;
+
+ prefix_sz = tvb_get_guint8(tvb, offset) & 0x1F;
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
+ prefix_sz);
+ offset += 1;
+
+ hop_count = tvb_get_guint8(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
+ hop_count);
+ offset += 1;
+
+ if (is_ipv6) {
+ tvb_memcpy(tvb, (guint8 *)&dest_addr_v6, offset, INET6_ADDRLEN);
+ if (aodv_tree) {
+ proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
+ INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
+ proto_item_append_text(ti, ", Dest IP: %s",
+ ip6_to_str(&dest_addr_v6));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
+ ip6_to_str(&dest_addr_v6));
+ offset += INET6_ADDRLEN;
+ } else {
+ tvb_memcpy(tvb, (guint8 *)&dest_addr_v4, offset, 4);
+ if (aodv_tree) {
+ proto_tree_add_ipv4(aodv_tree, hf_aodv_dest_ip, tvb, offset, 4,
+ dest_addr_v4);
+ proto_item_append_text(ti, ", Dest IP: %s",
+ ip_to_str((guint8 *)&dest_addr_v4));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
+ ip_to_str((guint8 *)&dest_addr_v4));
+ offset += 4;
+ }
+
+ dest_seqno = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
+ dest_seqno);
+ offset += 4;
+
+ if (is_ipv6) {
+ tvb_memcpy(tvb, (guint8 *)&orig_addr_v6, offset, INET6_ADDRLEN);
+ if (aodv_tree) {
+ proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
+ INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
+ proto_item_append_text(ti, ", Dest IP: %s",
+ ip6_to_str(&orig_addr_v6));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
+ ip6_to_str(&orig_addr_v6));
+ offset += INET6_ADDRLEN;
+ } else {
+ tvb_memcpy(tvb, (guint8 *)&orig_addr_v4, offset, 4);
+ if (aodv_tree) {
+ proto_tree_add_ipv4(aodv_tree, hf_aodv_orig_ip, tvb, offset, 4,
+ orig_addr_v4);
+ proto_item_append_text(ti, ", Orig IP: %s",
+ ip_to_str((guint8 *)&orig_addr_v4));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", O: %s",
+ ip_to_str((guint8 *)&orig_addr_v4));
+ offset += 4;
+ }
+
+ lifetime = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree) {
+ proto_tree_add_uint(aodv_tree, hf_aodv_lifetime, tvb, offset, 4,
+ lifetime);
+ proto_item_append_text(ti, ", Lifetime=%u", lifetime);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Hcnt=%u DSN=%u Lifetime=%u",
+ hop_count,
+ dest_seqno,
+ lifetime);
+ offset += 4;
+
+ if (aodv_tree) {
+ extlen = tvb_reported_length_remaining(tvb, offset);
+ if (extlen > 0)
+ dissect_aodv_ext(tvb, offset, aodv_tree);
+ }
+}
+
+static void
+dissect_aodv_rerr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *aodv_tree,
+ gboolean is_ipv6)
+{
+ int offset = 1;
+ proto_item *tj;
+ proto_tree *aodv_flags_tree;
+ proto_tree *aodv_unreach_dest_tree;
+ guint8 flags;
+ guint8 dest_count;
+ int i;
+
+ flags = tvb_get_guint8(tvb, offset);
+ if (aodv_tree) {
+ tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
+ aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rerr_nodelete,
+ tvb, offset, 1, flags);
+ if (flags & RERR_NODEL)
+ proto_item_append_text(tj, " N");
+ }
+ offset += 2; /* skip reserved byte */
+
+ dest_count = tvb_get_guint8(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_destcount, tvb, offset, 1,
+ dest_count);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
+ dest_count);
+ offset += 1;
+
+ if (is_ipv6) {
+ tj = proto_tree_add_text(aodv_tree, tvb, offset,
+ (INET6_ADDRLEN + 4)*dest_count,
+ "Unreachable Destinations");
+ aodv_unreach_dest_tree = proto_item_add_subtree(tj, ett_aodv_unreach_dest);
+ for (i = 0; i < dest_count; i++) {
+ proto_tree_add_item(aodv_unreach_dest_tree,
+ hf_aodv_unreach_dest_ipv6,
+ tvb, offset, INET6_ADDRLEN, FALSE);
+ proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
+ tvb, offset, 4, FALSE);
+ offset += INET6_ADDRLEN + 4;
+ }
+ } else {
+ tj = proto_tree_add_text(aodv_tree, tvb, offset, (4 + 4)*dest_count,
+ "Unreachable Destinations");
+ aodv_unreach_dest_tree = proto_item_add_subtree(tj, ett_aodv_unreach_dest);
+ for (i = 0; i < dest_count; i++) {
+ proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_unreach_dest_ip,
+ tvb, offset, 4, FALSE);
+ proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
+ tvb, offset, 4, FALSE);
+ offset += 4 + 4;
+ }
+ }
+}
+
+static void
+dissect_aodv_draft_01_v6_rreq(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *aodv_tree, proto_item *ti)
+{
+ int offset = 1;
+ proto_item *tj;
+ proto_tree *aodv_flags_tree;
+ guint8 flags;
+ guint8 hop_count;
+ guint32 rreq_id;
+ guint32 dest_seqno;
+ guint32 orig_seqno;
+ struct e_in6_addr dest_addr_v6;
+ struct e_in6_addr orig_addr_v6;
+ int extlen;
+
+ flags = tvb_get_guint8(tvb, offset);
+ if (aodv_tree) {
+ tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
+ aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_join,
+ tvb, offset, 1, flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_repair,
+ tvb, offset, 1, flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rreq_gratuitous,
+ tvb, offset, 1, flags);
+ if (flags & RREQ_JOIN)
+ proto_item_append_text(tj, " J");
+ if (flags & RREQ_REP)
+ proto_item_append_text(tj, " R");
+ if (flags & RREQ_GRAT)
+ proto_item_append_text(tj, " G");
+ }
+ offset += 2; /* skip reserved byte */
+
+ hop_count = tvb_get_guint8(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
+ hop_count);
+ offset += 1;
+
+ rreq_id = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_rreq_id, tvb, offset, 4,
+ rreq_id);
+ offset += 4;
+
+ dest_seqno = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
+ dest_seqno);
+ offset += 4;
+
+ orig_seqno = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_orig_seqno, tvb, offset, 4,
+ orig_seqno);
+ offset += 4;
+
+ tvb_memcpy(tvb, (guint8 *)&dest_addr_v6, offset, INET6_ADDRLEN);
+ if (aodv_tree) {
+ proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
+ INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
+ proto_item_append_text(ti, ", Dest IP: %s",
+ ip6_to_str(&dest_addr_v6));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
+ ip6_to_str(&dest_addr_v6));
+ offset += INET6_ADDRLEN;
+
+ tvb_memcpy(tvb, (guint8 *)&orig_addr_v6, offset, INET6_ADDRLEN);
+ if (aodv_tree) {
+ proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
+ INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
+ proto_item_append_text(ti, ", Orig IP: %s",
+ ip6_to_str(&orig_addr_v6));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", O: %s Id=%u Hcnt=%u DSN=%u OSN=%u",
+ ip6_to_str(&orig_addr_v6),
+ rreq_id,
+ hop_count,
+ dest_seqno,
+ orig_seqno);
+ offset += INET6_ADDRLEN;
+
+ if (aodv_tree) {
+ extlen = tvb_reported_length_remaining(tvb, offset);
+ if (extlen > 0)
+ dissect_aodv_ext(tvb, offset, aodv_tree);
+ }
+}
+
+static void
+dissect_aodv_draft_01_v6_rrep(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *aodv_tree, proto_item *ti)
+{
+ int offset = 1;
+ proto_item *tj;
+ proto_tree *aodv_flags_tree;
+ guint8 flags;
+ guint8 prefix_sz;
+ guint8 hop_count;
+ guint32 dest_seqno;
+ struct e_in6_addr dest_addr_v6;
+ struct e_in6_addr orig_addr_v6;
+ guint32 lifetime;
+ int extlen;
+
+ flags = tvb_get_guint8(tvb, offset);
+ if (aodv_tree) {
+ tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
+ aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_repair,
+ tvb, offset, 1, flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rrep_ack, tvb,
+ offset, 1, flags);
+ if (flags & RREP_REP)
+ proto_item_append_text(tj, " R");
+ if (flags & RREP_ACK_REQ)
+ proto_item_append_text(tj, " A");
+ }
+ offset += 1;
+
+ prefix_sz = tvb_get_guint8(tvb, offset) & 0x1F;
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_prefix_sz, tvb, offset, 1,
+ prefix_sz);
+ offset += 1;
+
+ hop_count = tvb_get_guint8(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_hopcount, tvb, offset, 1,
+ hop_count);
+ offset += 1;
+
+ dest_seqno = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_dest_seqno, tvb, offset, 4,
+ dest_seqno);
+ offset += 4;
+
+ tvb_memcpy(tvb, (guint8 *)&dest_addr_v6, offset, INET6_ADDRLEN);
+ if (aodv_tree) {
+ proto_tree_add_ipv6(aodv_tree, hf_aodv_dest_ipv6, tvb, offset,
+ INET6_ADDRLEN, (guint8 *)&dest_addr_v6);
+ proto_item_append_text(ti, ", Dest IP: %s",
+ ip6_to_str(&dest_addr_v6));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
+ ip6_to_str(&dest_addr_v6));
+ offset += INET6_ADDRLEN;
+
+ tvb_memcpy(tvb, (guint8 *)&orig_addr_v6, offset, INET6_ADDRLEN);
+ if (aodv_tree) {
+ proto_tree_add_ipv6(aodv_tree, hf_aodv_orig_ipv6, tvb, offset,
+ INET6_ADDRLEN, (guint8 *)&orig_addr_v6);
+ proto_item_append_text(ti, ", Dest IP: %s",
+ ip6_to_str(&orig_addr_v6));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", D: %s",
+ ip6_to_str(&orig_addr_v6));
+ offset += INET6_ADDRLEN;
+
+ lifetime = tvb_get_ntohl(tvb, offset);
+ if (aodv_tree) {
+ proto_tree_add_uint(aodv_tree, hf_aodv_lifetime, tvb, offset, 4,
+ lifetime);
+ proto_item_append_text(ti, ", Lifetime=%u", lifetime);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Hcnt=%u DSN=%u Lifetime=%u",
+ hop_count,
+ dest_seqno,
+ lifetime);
+ offset += 4;
+
+ if (aodv_tree) {
+ extlen = tvb_reported_length_remaining(tvb, offset);
+ if (extlen > 0)
+ dissect_aodv_ext(tvb, offset, aodv_tree);
+ }
+}
+
+static void
+dissect_aodv_draft_01_v6_rerr(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *aodv_tree)
+{
+ int offset = 1;
+ proto_item *tj;
+ proto_tree *aodv_flags_tree;
+ proto_tree *aodv_unreach_dest_tree;
+ guint8 flags;
+ guint8 dest_count;
+ int i;
+
+ flags = tvb_get_guint8(tvb, offset);
+ if (aodv_tree) {
+ tj = proto_tree_add_text(aodv_tree, tvb, offset, 1, "Flags:");
+ aodv_flags_tree = proto_item_add_subtree(tj, ett_aodv_flags);
+ proto_tree_add_boolean(aodv_flags_tree, hf_aodv_flags_rerr_nodelete,
+ tvb, offset, 1, flags);
+ if (flags & RERR_NODEL)
+ proto_item_append_text(tj, " N");
+ }
+ offset += 2; /* skip reserved byte */
+
+ dest_count = tvb_get_guint8(tvb, offset);
+ if (aodv_tree)
+ proto_tree_add_uint(aodv_tree, hf_aodv_destcount, tvb, offset, 1,
+ dest_count);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Dest Count=%u",
+ dest_count);
+ offset += 1;
+
+ tj = proto_tree_add_text(aodv_tree, tvb, offset,
+ (4 + INET6_ADDRLEN)*dest_count,
+ "Unreachable Destinations");
+ aodv_unreach_dest_tree = proto_item_add_subtree(tj, ett_aodv_unreach_dest);
+ for (i = 0; i < dest_count; i++) {
+ proto_tree_add_item(aodv_unreach_dest_tree, hf_aodv_dest_seqno,
+ tvb, offset, 4, FALSE);
+ proto_tree_add_item(aodv_unreach_dest_tree,
+ hf_aodv_unreach_dest_ipv6,
+ tvb, offset, INET6_ADDRLEN, FALSE);
+ offset += 4 + INET6_ADDRLEN;
+ }
+}
+
+static int
+dissect_aodv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti = NULL;
+ proto_tree *aodv_tree = NULL;
+ gboolean is_ipv6;
+ guint8 type;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AODV");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* Is this running over IPv6? */
+ is_ipv6 = (pinfo->src.type == AT_IPv6);
+
+ /* Check the type of AODV packet. */
+ type = tvb_get_guint8(tvb, 0);
+ if (match_strval(type, type_vals) == NULL) {
+ /*
+ * We assume this is not an AODV packet.
+ */
+ return 0;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(type, type_vals,
+ "Unknown AODV Packet Type (%u)"));
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_aodv, tvb, 0, -1,
+ "Ad hoc On-demand Distance Vector Routing Protocol, %s",
+ val_to_str(type, type_vals, "Unknown AODV Packet Type (%u)"));
+ aodv_tree = proto_item_add_subtree(ti, ett_aodv);
+
+ proto_tree_add_uint(aodv_tree, hf_aodv_type, tvb, 0, 1, type);
+ }
+
+ switch (type) {
+ case RREQ:
+ dissect_aodv_rreq(tvb, pinfo, tree, ti, is_ipv6);
+ break;
+ case RREP:
+ dissect_aodv_rrep(tvb, pinfo, tree, ti, is_ipv6);
+ break;
+ case RERR:
+ dissect_aodv_rerr(tvb, pinfo, tree, is_ipv6);
+ break;
+ case RREP_ACK:
+ break;
+ case DRAFT_01_V6_RREQ:
+ dissect_aodv_draft_01_v6_rreq(tvb, pinfo, tree, ti);
+ break;
+ case DRAFT_01_V6_RREP:
+ dissect_aodv_draft_01_v6_rrep(tvb, pinfo, tree, ti);
+ break;
+ case DRAFT_01_V6_RERR:
+ dissect_aodv_draft_01_v6_rerr(tvb, pinfo, tree);
+ break;
+ case DRAFT_01_V6_RREP_ACK:
+ break;
+ default:
+ proto_tree_add_text(aodv_tree, tvb, 0, -1,
+ "Unknown AODV Packet Type (%u)", type);
+ }
+
+ return tvb_length(tvb);
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_aodv(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_aodv_type,
+ { "Type", "aodv.type",
+ FT_UINT8, BASE_DEC, VALS(type_vals), 0x0,
+ "AODV packet type", HFILL }
+ },
+ { &hf_aodv_flags,
+ { "Flags", "aodv.flags",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Flags", HFILL }
+ },
+ { &hf_aodv_flags_rreq_join,
+ { "RREQ Join", "aodv.flags.rreq_join",
+ FT_BOOLEAN, 8, TFS(&flags_set_truth), RREQ_JOIN,
+ "", HFILL }
+ },
+ { &hf_aodv_flags_rreq_repair,
+ { "RREQ Repair", "aodv.flags.rreq_repair",
+ FT_BOOLEAN, 8, TFS(&flags_set_truth), RREQ_REP,
+ "", HFILL }
+ },
+ { &hf_aodv_flags_rreq_gratuitous,
+ { "RREQ Gratuitous", "aodv.flags.rreq_gratuitous",
+ FT_BOOLEAN, 8, TFS(&flags_set_truth), RREQ_GRAT,
+ "", HFILL }
+ },
+ { &hf_aodv_flags_rrep_repair,
+ { "RREP Repair", "aodv.flags.rrep_repair",
+ FT_BOOLEAN, 8, TFS(&flags_set_truth), RREP_REP,
+ "", HFILL }
+ },
+ { &hf_aodv_flags_rrep_ack,
+ { "RREP Acknowledgement", "aodv.flags.rrep_ack",
+ FT_BOOLEAN, 8, TFS(&flags_set_truth), RREP_ACK_REQ,
+ "", HFILL }
+ },
+ { &hf_aodv_flags_rerr_nodelete,
+ { "RERR No Delete", "aodv.flags.rerr_nodelete",
+ FT_BOOLEAN, 8, TFS(&flags_set_truth), RERR_NODEL,
+ "", HFILL }
+ },
+ { &hf_aodv_prefix_sz,
+ { "Prefix Size", "aodv.prefix_sz",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Prefix Size", HFILL }
+ },
+ { &hf_aodv_hopcount,
+ { "Hop Count", "aodv.hopcount",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Hop Count", HFILL }
+ },
+ { &hf_aodv_rreq_id,
+ { "RREQ Id", "aodv.rreq_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "RREQ Id", HFILL }
+ },
+ { &hf_aodv_dest_ip,
+ { "Destination IP", "aodv.dest_ip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Destination IP Address", HFILL }
+ },
+ { &hf_aodv_dest_ipv6,
+ { "Destination IPv6", "aodv.dest_ipv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Destination IPv6 Address", HFILL}
+ },
+ { &hf_aodv_dest_seqno,
+ { "Destination Sequence Number", "aodv.dest_seqno",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Destination Sequence Number", HFILL }
+ },
+ { &hf_aodv_orig_ip,
+ { "Originator IP", "aodv.orig_ip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Originator IP Address", HFILL }
+ },
+ { &hf_aodv_orig_ipv6,
+ { "Originator IPv6", "aodv.orig_ipv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Originator IPv6 Address", HFILL}
+ },
+ { &hf_aodv_orig_seqno,
+ { "Originator Sequence Number", "aodv.orig_seqno",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Originator Sequence Number", HFILL }
+ },
+ { &hf_aodv_lifetime,
+ { "Lifetime", "aodv.lifetime",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Lifetime", HFILL }
+ },
+ { &hf_aodv_destcount,
+ { "Destination Count", "aodv.destcount",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Unreachable Destinations Count", HFILL }
+ },
+ { &hf_aodv_unreach_dest_ip,
+ { "Unreachable Destination IP", "aodv.unreach_dest_ip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Unreachable Destination IP Address", HFILL }
+ },
+ { &hf_aodv_unreach_dest_ipv6,
+ { "Unreachable Destination IPv6", "aodv.unreach_dest_ipv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Unreachable Destination IPv6 Address", HFILL}
+ },
+ { &hf_aodv_unreach_dest_seqno,
+ { "Unreachable Destination Sequence Number", "aodv.unreach_dest_seqno",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Unreachable Destination Sequence Number", HFILL }
+ },
+ { &hf_aodv_ext_type,
+ { "Extension Type", "aodv.ext_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Extension Format Type", HFILL}
+ },
+ { &hf_aodv_ext_length,
+ { "Extension Length", "aodv.ext_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Extension Data Length", HFILL}
+ },
+ { &hf_aodv_ext_interval,
+ { "Hello Interval", "aodv.hello_interval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Hello Interval Extension", HFILL}
+ },
+ { &hf_aodv_ext_timestamp,
+ { "Timestamp", "aodv.timestamp",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Timestamp Extension", HFILL}
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_aodv,
+ &ett_aodv_flags,
+ &ett_aodv_unreach_dest,
+ &ett_aodv_extensions,
+ };
+
+/* Register the protocol name and description */
+ proto_aodv = proto_register_protocol("Ad hoc On-demand Distance Vector Routing Protocol", "AODV", "aodv");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_aodv, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_aodv(void)
+{
+ dissector_handle_t aodv_handle;
+
+ aodv_handle = new_create_dissector_handle(dissect_aodv,
+ proto_aodv);
+ dissector_add("udp.port", UDP_PORT_AODV, aodv_handle);
+}
diff --git a/epan/dissectors/packet-ap1394.c b/epan/dissectors/packet-ap1394.c
new file mode 100644
index 0000000000..9560391eaa
--- /dev/null
+++ b/epan/dissectors/packet-ap1394.c
@@ -0,0 +1,125 @@
+/* packet-ap1394.c
+ * Routines for Apple IP-over-IEEE 1394 packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include <epan/strutil.h>
+
+#include "packet-ap1394.h"
+#include "etypes.h"
+
+static int proto_ap1394 = -1;
+static int hf_ap1394_dst = -1;
+static int hf_ap1394_src = -1;
+static int hf_ap1394_type = -1;
+
+static gint ett_ap1394 = -1;
+
+void
+capture_ap1394(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ guint16 etype;
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, 18)) {
+ ld->other++;
+ return;
+ }
+
+ /* Skip destination and source addresses */
+ offset += 16;
+
+ etype = pntohs(&pd[offset]);
+ offset += 2;
+ capture_ethertype(etype, pd, offset, len, ld);
+}
+
+static void
+dissect_ap1394(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *fh_tree = NULL;
+ const char *src_addr, *dst_addr;
+ guint16 etype;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP/IEEE1394");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ src_addr=tvb_get_ptr(tvb, 8, 8);
+ SET_ADDRESS(&pinfo->dl_src, AT_EUI64, 8, src_addr);
+ SET_ADDRESS(&pinfo->src, AT_EUI64, 8, src_addr);
+ dst_addr=tvb_get_ptr(tvb, 0, 8);
+ SET_ADDRESS(&pinfo->dl_dst, AT_EUI64, 8, dst_addr);
+ SET_ADDRESS(&pinfo->dst, AT_EUI64, 8, dst_addr);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_ap1394, tvb, 0, 18,
+ "Apple IP-over-IEEE 1394, Src: %s, Dst: %s",
+ bytes_to_str(src_addr, 8), bytes_to_str(dst_addr, 8));
+ fh_tree = proto_item_add_subtree(ti, ett_ap1394);
+ proto_tree_add_bytes(fh_tree, hf_ap1394_dst, tvb, 0, 8, dst_addr);
+ proto_tree_add_bytes(fh_tree, hf_ap1394_src, tvb, 8, 8, src_addr);
+ }
+ etype = tvb_get_ntohs(tvb, 16);
+ ethertype(etype, tvb, 18, pinfo, tree, fh_tree, hf_ap1394_type, -1, 0);
+}
+
+void
+proto_register_ap1394(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ap1394_dst,
+ { "Destination", "ap1394.dst", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "Destination address", HFILL }},
+ { &hf_ap1394_src,
+ { "Source", "ap1394.src", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "Source address", HFILL }},
+ /* registered here but handled in ethertype.c */
+ { &hf_ap1394_type,
+ { "Type", "ap1394.type", FT_UINT16, BASE_HEX,
+ VALS(etype_vals), 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ap1394,
+ };
+
+ proto_ap1394 = proto_register_protocol("Apple IP-over-IEEE 1394", "IP/IEEE1394", "ap1394");
+ proto_register_field_array(proto_ap1394, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ap1394(void)
+{
+ dissector_handle_t ap1394_handle;
+
+ ap1394_handle = create_dissector_handle(dissect_ap1394, proto_ap1394);
+ dissector_add("wtap_encap", WTAP_ENCAP_APPLE_IP_OVER_IEEE1394, ap1394_handle);
+}
diff --git a/epan/dissectors/packet-ap1394.h b/epan/dissectors/packet-ap1394.h
new file mode 100644
index 0000000000..f8f8cbc0ab
--- /dev/null
+++ b/epan/dissectors/packet-ap1394.h
@@ -0,0 +1,29 @@
+/* packet-ap1394.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_AP1394_H__
+#define __PACKET_AP1394_H__
+
+void capture_ap1394(const guchar *, int, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-arcnet.c b/epan/dissectors/packet-arcnet.c
new file mode 100644
index 0000000000..9fe970b3e0
--- /dev/null
+++ b/epan/dissectors/packet-arcnet.c
@@ -0,0 +1,389 @@
+/* packet-arcnet.c
+ * Routines for arcnet dissection
+ * Copyright 2001-2002, Peter Fales <ethereal@fales-lorenz.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "packet-arcnet.h"
+#include "arcnet_pids.h"
+#include "packet-ip.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_arcnet = -1;
+static int hf_arcnet_src = -1;
+static int hf_arcnet_dst = -1;
+static int hf_arcnet_offset = -1;
+static int hf_arcnet_protID = -1;
+static int hf_arcnet_exception_flag = -1;
+static int hf_arcnet_split_flag = -1;
+static int hf_arcnet_sequence = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_arcnet = -1;
+
+static dissector_table_t arcnet_dissector_table;
+static dissector_handle_t data_handle;
+
+void
+capture_arcnet (const guchar *pd, int len, packet_counts *ld,
+ gboolean has_offset, gboolean has_exception)
+{
+ int offset = has_offset ? 4 : 2;
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, 1)) {
+ ld->other++;
+ return;
+ }
+
+ switch (pd[offset]) {
+
+ case ARCNET_PROTO_IP_1051:
+ /* No fragmentation stuff in the header */
+ capture_ip(pd, offset + 1, len, ld);
+ break;
+
+ case ARCNET_PROTO_IP_1201:
+ /*
+ * There's fragmentation stuff in the header.
+ *
+ * XXX - on at least some versions of NetBSD, it appears that we
+ * might we get ARCNET frames, not reassembled packets; we should
+ * perhaps bump "ld->other" for all but the first frame of a packet.
+ *
+ * XXX - but on FreeBSD it appears that we get reassembled packets
+ * on input (but apparently we get frames on output - or maybe
+ * we get the packet *and* all its frames!); how to tell the
+ * difference? It looks from the FreeBSD reassembly code as if
+ * the reassembled packet arrives with the header for the first
+ * frame. It also looks as if, on output, we first get the
+ * full packet, with a header containing none of the fragmentation
+ * stuff, and then get the frames.
+ *
+ * On Linux, we get only reassembled packets, and the exception
+ * frame stuff is hidden - there's a split flag and sequence
+ * number, but it appears that it will never have the exception
+ * frame stuff.
+ *
+ * XXX - what about OpenBSD? And, for that matter, what about
+ * Windows? (I suspect Windows supplies reassembled frames,
+ * as WinPcap, like PF_PACKET sockets, taps into the networking
+ * stack just as other protocols do.)
+ */
+ offset++;
+ if (!BYTES_ARE_IN_FRAME(offset, len, 1)) {
+ ld->other++;
+ return;
+ }
+ if (has_exception && pd[offset] == 0xff) {
+ /* This is an exception packet. The flag value there is the
+ "this is an exception flag" packet; the next two bytes
+ after it are padding, and another copy of the packet
+ type appears after the padding. */
+ offset += 4;
+ }
+ capture_ip(pd, offset + 3, len, ld);
+ break;
+
+ case ARCNET_PROTO_ARP_1051:
+ case ARCNET_PROTO_ARP_1201:
+ /*
+ * XXX - do we have to worry about fragmentation for ARP?
+ */
+ ld->arp++;
+ break;
+
+ case ARCNET_PROTO_IPX:
+ ld->ipx++;
+ break;
+
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+static void
+dissect_arcnet_common (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
+ gboolean has_offset, gboolean has_exception)
+{
+ int offset = 0;
+ guint8 dst, src, protID, split_flag;
+ tvbuff_t *next_tvb;
+ proto_item *ti = NULL;
+ proto_tree *arcnet_tree = NULL;
+
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "ARCNET");
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_set_str (pinfo->cinfo, COL_INFO, "ARCNET");
+
+ src = tvb_get_guint8 (tvb, 0);
+ dst = tvb_get_guint8 (tvb, 1);
+ SET_ADDRESS(&pinfo->dl_src, AT_ARCNET, 1, tvb_get_ptr(tvb, 0, 1));
+ SET_ADDRESS(&pinfo->src, AT_ARCNET, 1, tvb_get_ptr(tvb, 0, 1));
+ SET_ADDRESS(&pinfo->dl_dst, AT_ARCNET, 1, tvb_get_ptr(tvb, 1, 1));
+ SET_ADDRESS(&pinfo->dst, AT_ARCNET, 1, tvb_get_ptr(tvb, 1, 1));
+
+ if (tree)
+ {
+ ti =
+ proto_tree_add_item (tree, proto_arcnet, tvb, 0, -1, FALSE);
+
+ arcnet_tree = proto_item_add_subtree (ti, ett_arcnet);
+
+ proto_tree_add_uint (tree, hf_arcnet_src, tvb, offset, 1, src);
+ }
+ offset++;
+
+ if (tree)
+ proto_tree_add_uint (tree, hf_arcnet_dst, tvb, offset, 1, dst);
+ offset++;
+
+ if (has_offset) {
+ if (tree)
+ proto_tree_add_item (tree, hf_arcnet_offset, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ protID = tvb_get_guint8 (tvb, offset);
+ if (tree)
+ proto_tree_add_uint (tree, hf_arcnet_protID, tvb, offset, 1, protID);
+ offset++;
+
+ switch (protID) {
+
+ case ARCNET_PROTO_IP_1051:
+ case ARCNET_PROTO_ARP_1051:
+ case ARCNET_PROTO_DIAGNOSE:
+ case ARCNET_PROTO_BACNET: /* XXX - no fragmentation? */
+ /* No fragmentation stuff in the header */
+ break;
+
+ default:
+ /*
+ * Show the fragmentation stuff - flag and sequence ID.
+ *
+ * XXX - on at least some versions of NetBSD, it appears that
+ * we might get ARCNET frames, not reassembled packets; if so,
+ * we should reassemble them.
+ *
+ * XXX - but on FreeBSD it appears that we get reassembled packets
+ * on input (but apparently we get frames on output - or maybe
+ * we get the packet *and* all its frames!); how to tell the
+ * difference? It looks from the FreeBSD reassembly code as if
+ * the reassembled packet arrives with the header for the first
+ * frame. It also looks as if, on output, we first get the
+ * full packet, with a header containing none of the fragmentation
+ * stuff, and then get the frames.
+ *
+ * On Linux, we get only reassembled packets, and the exception
+ * frame stuff is hidden - there's a split flag and sequence
+ * number, but it appears that it will never have the exception
+ * frame stuff.
+ *
+ * XXX - what about OpenBSD? And, for that matter, what about
+ * Windows? (I suspect Windows supplies reassembled frames,
+ * as WinPcap, like PF_PACKET sockets, taps into the networking
+ * stack just as other protocols do.)
+ */
+ split_flag = tvb_get_guint8 (tvb, offset);
+ if (has_exception && split_flag == 0xff) {
+ /* This is an exception packet. The flag value there is the
+ "this is an exception flag" packet; the next two bytes
+ after it are padding. */
+ if (tree) {
+ proto_tree_add_uint (tree, hf_arcnet_exception_flag, tvb, offset, 1,
+ split_flag);
+ }
+ offset++;
+
+ if (tree)
+ proto_tree_add_text (tree, tvb, offset, 2, "Padding");
+ offset += 2;
+
+ /* Another copy of the packet type appears after the padding. */
+ if (tree)
+ proto_tree_add_item (tree, hf_arcnet_protID, tvb, offset, 1, FALSE);
+ offset++;
+
+ /* And after that comes the real split flag. */
+ split_flag = tvb_get_guint8 (tvb, offset);
+ }
+ if (tree) {
+ proto_tree_add_uint (tree, hf_arcnet_split_flag, tvb, offset, 1,
+ split_flag);
+ }
+ offset++;
+
+ if (tree)
+ proto_tree_add_item (tree, hf_arcnet_sequence, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ break;
+ }
+
+ /* Set the length of the ARCNET header protocol tree item. */
+ if (tree)
+ proto_item_set_len(ti, offset);
+
+ next_tvb = tvb_new_subset (tvb, offset, -1, -1);
+
+ if (!dissector_try_port (arcnet_dissector_table, protID,
+ next_tvb, pinfo, tree))
+ {
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_add_fstr (pinfo->cinfo, COL_PROTOCOL, "0x%04x", protID);
+ }
+ call_dissector (data_handle, next_tvb, pinfo, tree);
+ }
+
+}
+
+/*
+ * BSD-style ARCNET headers - they don't have the offset field from the
+ * ARCNET hardware packet, but we might get an exception frame header.
+ */
+static void
+dissect_arcnet (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ dissect_arcnet_common (tvb, pinfo, tree, FALSE, TRUE);
+}
+
+/*
+ * Linux-style ARCNET headers - they *do* have the offset field from the
+ * ARCNET hardware packet, but we should never see an exception frame
+ * header.
+ */
+static void
+dissect_arcnet_linux (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ dissect_arcnet_common (tvb, pinfo, tree, TRUE, FALSE);
+}
+
+static const value_string arcnet_prot_id_vals[] = {
+ {ARCNET_PROTO_IP_1051, "RFC 1051 IP"},
+ {ARCNET_PROTO_ARP_1051, "RFC 1051 ARP"},
+ {ARCNET_PROTO_IP_1201, "RFC 1201 IP"},
+ {ARCNET_PROTO_ARP_1201, "RFC 1201 ARP"},
+ {ARCNET_PROTO_RARP_1201, "RFC 1201 RARP"},
+ {ARCNET_PROTO_IPX, "IPX"},
+ {ARCNET_PROTO_NOVELL_EC, "Novell of some sort"},
+ {ARCNET_PROTO_IPv6, "IPv6"},
+ {ARCNET_PROTO_ETHERNET, "Encapsulated Ethernet"},
+ {ARCNET_PROTO_DATAPOINT_BOOT, "Datapoint boot"},
+ {ARCNET_PROTO_DATAPOINT_MOUNT, "Datapoint mount"},
+ {ARCNET_PROTO_POWERLAN_BEACON, "PowerLAN beacon"},
+ {ARCNET_PROTO_POWERLAN_BEACON2, "PowerLAN beacon2"},
+ {ARCNET_PROTO_APPLETALK, "Appletalk"},
+ {ARCNET_PROTO_BANYAN, "Banyan VINES"},
+ {ARCNET_PROTO_DIAGNOSE, "Diagnose"},
+ {ARCNET_PROTO_BACNET, "BACnet"},
+ {0, NULL}
+};
+
+void
+proto_register_arcnet (void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ {&hf_arcnet_src,
+ {"Source", "arcnet.src",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Source ID", HFILL}
+ },
+ {&hf_arcnet_dst,
+ {"Dest", "arcnet.dst",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Dest ID", HFILL}
+ },
+ {&hf_arcnet_offset,
+ {"Offset", "arcnet.offset",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "Offset", HFILL}
+ },
+ {&hf_arcnet_protID,
+ {"Protocol ID", "arcnet.protID",
+ FT_UINT8, BASE_HEX, VALS(arcnet_prot_id_vals), 0,
+ "Proto type", HFILL}
+ },
+ {&hf_arcnet_split_flag,
+ {"Split Flag", "arcnet.split_flag",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Split flag", HFILL}
+ },
+ {&hf_arcnet_exception_flag,
+ {"Exception Flag", "arcnet.exception_flag",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Exception flag", HFILL}
+ },
+ {&hf_arcnet_sequence,
+ {"Sequence", "arcnet.sequence",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Sequence number", HFILL}
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_arcnet,
+ };
+
+ arcnet_dissector_table = register_dissector_table ("arcnet.protocol_id",
+ "ARCNET Protocol ID",
+ FT_UINT8, BASE_HEX);
+
+/* Register the protocol name and description */
+ proto_arcnet = proto_register_protocol ("ARCNET", "ARCNET", "arcnet");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array (proto_arcnet, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+
+void
+proto_reg_handoff_arcnet (void)
+{
+ dissector_handle_t arcnet_handle, arcnet_linux_handle;
+
+ arcnet_handle = create_dissector_handle (dissect_arcnet, proto_arcnet);
+ dissector_add ("wtap_encap", WTAP_ENCAP_ARCNET, arcnet_handle);
+
+ arcnet_linux_handle = create_dissector_handle (dissect_arcnet_linux,
+ proto_arcnet);
+ dissector_add ("wtap_encap", WTAP_ENCAP_ARCNET_LINUX, arcnet_linux_handle);
+ data_handle = find_dissector ("data");
+}
diff --git a/epan/dissectors/packet-arcnet.h b/epan/dissectors/packet-arcnet.h
new file mode 100644
index 0000000000..7047671e51
--- /dev/null
+++ b/epan/dissectors/packet-arcnet.h
@@ -0,0 +1,29 @@
+/* packet-arcnet.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_ARCNET_H__
+#define __PACKET_ARCNET_H__
+
+void capture_arcnet (const guchar *, int, packet_counts *, gboolean, gboolean);
+
+#endif
diff --git a/epan/dissectors/packet-arp.c b/epan/dissectors/packet-arp.c
new file mode 100644
index 0000000000..a0e5153e13
--- /dev/null
+++ b/epan/dissectors/packet-arp.c
@@ -0,0 +1,1043 @@
+/* packet-arp.c
+ * Routines for ARP packet disassembly (RFC 826)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/resolv.h>
+#include "packet-arp.h"
+#include "etypes.h"
+#include "arcnet_pids.h"
+
+static int proto_arp = -1;
+static int hf_arp_hard_type = -1;
+static int hf_arp_proto_type = -1;
+static int hf_arp_hard_size = -1;
+static int hf_atmarp_sht = -1;
+static int hf_atmarp_shl = -1;
+static int hf_atmarp_sst = -1;
+static int hf_atmarp_ssl = -1;
+static int hf_arp_proto_size = -1;
+static int hf_arp_opcode = -1;
+static int hf_atmarp_spln = -1;
+static int hf_atmarp_tht = -1;
+static int hf_atmarp_thl = -1;
+static int hf_atmarp_tst = -1;
+static int hf_atmarp_tsl = -1;
+static int hf_atmarp_tpln = -1;
+static int hf_arp_src_hw = -1;
+static int hf_arp_src_hw_mac = -1;
+static int hf_arp_src_proto = -1;
+static int hf_arp_src_proto_ipv4 = -1;
+static int hf_arp_dst_hw = -1;
+static int hf_arp_dst_hw_mac = -1;
+static int hf_arp_dst_proto = -1;
+static int hf_arp_dst_proto_ipv4 = -1;
+static int hf_atmarp_src_atm_num_e164 = -1;
+static int hf_atmarp_src_atm_num_nsap = -1;
+static int hf_atmarp_src_atm_subaddr = -1;
+static int hf_atmarp_dst_atm_num_e164 = -1;
+static int hf_atmarp_dst_atm_num_nsap = -1;
+static int hf_atmarp_dst_atm_subaddr = -1;
+
+static gint ett_arp = -1;
+static gint ett_atmarp_nsap = -1;
+static gint ett_atmarp_tl = -1;
+
+static dissector_handle_t atmarp_handle;
+
+/* Definitions taken from Linux "linux/if_arp.h" header file, and from
+
+ http://www.iana.org/assignments/arp-parameters
+
+ */
+
+/* ARP protocol HARDWARE identifiers. */
+#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
+#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
+#define ARPHRD_EETHER 2 /* Experimental Ethernet */
+#define ARPHRD_AX25 3 /* AX.25 Level 2 */
+#define ARPHRD_PRONET 4 /* PROnet token ring */
+#define ARPHRD_CHAOS 5 /* Chaosnet */
+#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
+#define ARPHRD_ARCNET 7 /* ARCnet */
+#define ARPHRD_HYPERCH 8 /* Hyperchannel */
+#define ARPHRD_LANSTAR 9 /* Lanstar */
+#define ARPHRD_AUTONET 10 /* Autonet Short Address */
+#define ARPHRD_LOCALTLK 11 /* Localtalk */
+#define ARPHRD_LOCALNET 12 /* LocalNet (IBM PCNet/Sytek LocalNET) */
+#define ARPHRD_ULTRALNK 13 /* Ultra link */
+#define ARPHRD_SMDS 14 /* SMDS */
+#define ARPHRD_DLCI 15 /* Frame Relay DLCI */
+#define ARPHRD_ATM 16 /* ATM */
+#define ARPHRD_HDLC 17 /* HDLC */
+#define ARPHRD_FIBREC 18 /* Fibre Channel */
+#define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
+#define ARPHRD_SERIAL 20 /* Serial Line */
+#define ARPHRD_ATM2 21 /* ATM */
+#define ARPHRD_MS188220 22 /* MIL-STD-188-220 */
+#define ARPHRD_METRICOM 23 /* Metricom STRIP */
+#define ARPHRD_IEEE1394 24 /* IEEE 1394.1995 */
+#define ARPHRD_MAPOS 25 /* MAPOS */
+#define ARPHRD_TWINAX 26 /* Twinaxial */
+#define ARPHRD_EUI_64 27 /* EUI-64 */
+
+/* ARP / RARP structs and definitions */
+#ifndef ARPOP_REQUEST
+#define ARPOP_REQUEST 1 /* ARP request. */
+#endif
+#ifndef ARPOP_REPLY
+#define ARPOP_REPLY 2 /* ARP reply. */
+#endif
+/* Some OSes have different names, or don't define these at all */
+#ifndef ARPOP_RREQUEST
+#define ARPOP_RREQUEST 3 /* RARP request. */
+#endif
+#ifndef ARPOP_RREPLY
+#define ARPOP_RREPLY 4 /* RARP reply. */
+#endif
+#ifndef ARPOP_IREQUEST
+#define ARPOP_IREQUEST 8 /* Inverse ARP (RFC 1293) request. */
+#endif
+#ifndef ARPOP_IREPLY
+#define ARPOP_IREPLY 9 /* Inverse ARP reply. */
+#endif
+#ifndef ATMARPOP_NAK
+#define ATMARPOP_NAK 10 /* ATMARP NAK. */
+#endif
+
+static const value_string op_vals[] = {
+ {ARPOP_REQUEST, "request" },
+ {ARPOP_REPLY, "reply" },
+ {ARPOP_RREQUEST, "reverse request"},
+ {ARPOP_RREPLY, "reverse reply" },
+ {ARPOP_IREQUEST, "inverse request"},
+ {ARPOP_IREPLY, "inverse reply" },
+ {0, NULL } };
+
+static const value_string atmop_vals[] = {
+ {ARPOP_REQUEST, "request" },
+ {ARPOP_REPLY, "reply" },
+ {ARPOP_IREQUEST, "inverse request"},
+ {ARPOP_IREPLY, "inverse reply" },
+ {ATMARPOP_NAK, "nak" },
+ {0, NULL } };
+
+#define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
+#define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
+
+/*
+ * Given the hardware address type and length, check whether an address
+ * is an Ethernet address - the address must be of type "Ethernet" or
+ * "IEEE 802.x", and the length must be 6 bytes.
+ */
+#define ARP_HW_IS_ETHER(ar_hrd, ar_hln) \
+ (((ar_hrd) == ARPHRD_ETHER || (ar_hrd) == ARPHRD_IEEE802) \
+ && (ar_hln) == 6)
+
+/*
+ * Given the protocol address type and length, check whether an address
+ * is an IPv4 address - the address must be of type "IP", and the length
+ * must be 4 bytes.
+ */
+#define ARP_PRO_IS_IPv4(ar_pro, ar_pln) \
+ ((ar_pro) == ETHERTYPE_IP && (ar_pln) == 4)
+
+gchar *
+arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
+{
+ if (ad_len == 0)
+ return "<No address>";
+ if (ARP_HW_IS_ETHER(type, ad_len)) {
+ /* Ethernet address (or IEEE 802.x address, which is the same type of
+ address). */
+ return ether_to_str(ad);
+ }
+ return bytes_to_str(ad, ad_len);
+}
+
+static gchar *
+arpproaddr_to_str(const guint8 *ad, int ad_len, guint16 type)
+{
+ if (ad_len == 0)
+ return "<No address>";
+ if (ARP_PRO_IS_IPv4(type, ad_len)) {
+ /* IPv4 address. */
+ return ip_to_str(ad);
+ }
+ return bytes_to_str(ad, ad_len);
+}
+
+#define N_ATMARPNUM_TO_STR_STRINGS 2
+#define MAX_E164_STR_LEN 20
+
+static gchar *
+atmarpnum_to_str(const guint8 *ad, int ad_tl)
+{
+ int ad_len = ad_tl & ATMARP_LEN_MASK;
+ static gchar str[N_ATMARPNUM_TO_STR_STRINGS][MAX_E164_STR_LEN+3+1];
+ static int cur_idx;
+ gchar *cur;
+
+ if (ad_len == 0)
+ return "<No address>";
+
+ if (ad_tl & ATMARP_IS_E164) {
+ /*
+ * I'm assuming this means it's an ASCII (IA5) string.
+ */
+ cur_idx++;
+ if (cur_idx >= N_ATMARPNUM_TO_STR_STRINGS)
+ cur_idx = 0;
+ cur = &str[cur_idx][0];
+ if (ad_len > MAX_E164_STR_LEN) {
+ /* Can't show it all. */
+ memcpy(cur, ad, MAX_E164_STR_LEN);
+ strcpy(&cur[MAX_E164_STR_LEN], "...");
+ } else {
+ memcpy(cur, ad, ad_len);
+ cur[ad_len + 1] = '\0';
+ }
+ return cur;
+ } else {
+ /*
+ * NSAP.
+ *
+ * XXX - break down into subcomponents.
+ */
+ return bytes_to_str(ad, ad_len);
+ }
+}
+
+static gchar *
+atmarpsubaddr_to_str(const guint8 *ad, int ad_tl)
+{
+ int ad_len = ad_tl & ATMARP_LEN_MASK;
+
+ if (ad_len == 0)
+ return "<No address>";
+
+ /*
+ * E.164 isn't considered legal in subaddresses (RFC 2225 says that
+ * a null or unknown ATM address is indicated by setting the length
+ * to 0, in which case the type must be ignored; we've seen some
+ * captures in which the length of a subaddress is 0 and the type
+ * is E.164).
+ *
+ * XXX - break down into subcomponents?
+ */
+ return bytes_to_str(ad, ad_len);
+}
+
+static const value_string hrd_vals[] = {
+ {ARPHRD_NETROM, "NET/ROM pseudo" },
+ {ARPHRD_ETHER, "Ethernet" },
+ {ARPHRD_EETHER, "Experimental Ethernet"},
+ {ARPHRD_AX25, "AX.25" },
+ {ARPHRD_PRONET, "ProNET" },
+ {ARPHRD_CHAOS, "Chaos" },
+ {ARPHRD_IEEE802, "IEEE 802" },
+ {ARPHRD_ARCNET, "ARCNET" },
+ {ARPHRD_HYPERCH, "Hyperchannel" },
+ {ARPHRD_LANSTAR, "Lanstar" },
+ {ARPHRD_AUTONET, "Autonet Short Address"},
+ {ARPHRD_LOCALTLK, "Localtalk" },
+ {ARPHRD_LOCALNET, "LocalNet" },
+ {ARPHRD_ULTRALNK, "Ultra link" },
+ {ARPHRD_SMDS, "SMDS" },
+ {ARPHRD_DLCI, "Frame Relay DLCI" },
+ {ARPHRD_ATM, "ATM" },
+ {ARPHRD_HDLC, "HDLC" },
+ {ARPHRD_FIBREC, "Fibre Channel" },
+ {ARPHRD_ATM2225, "ATM (RFC 2225)" },
+ {ARPHRD_SERIAL, "Serial Line" },
+ {ARPHRD_ATM2, "ATM" },
+ {ARPHRD_MS188220, "MIL-STD-188-220" },
+ {ARPHRD_METRICOM, "Metricom STRIP" },
+ {ARPHRD_IEEE1394, "IEEE 1394.1995" },
+ {ARPHRD_MAPOS, "MAPOS" },
+ {ARPHRD_TWINAX, "Twinaxial" },
+ {ARPHRD_EUI_64, "EUI-64" },
+ {0, NULL } };
+
+gchar *
+arphrdtype_to_str(guint16 hwtype, const char *fmt) {
+ return val_to_str(hwtype, hrd_vals, fmt);
+}
+
+/* Offsets of fields within an ARP packet. */
+#define AR_HRD 0
+#define AR_PRO 2
+#define AR_HLN 4
+#define AR_PLN 5
+#define AR_OP 6
+#define MIN_ARP_HEADER_SIZE 8
+
+/* Offsets of fields within an ATMARP packet. */
+#define ATM_AR_HRD 0
+#define ATM_AR_PRO 2
+#define ATM_AR_SHTL 4
+#define ATM_AR_SSTL 5
+#define ATM_AR_OP 6
+#define ATM_AR_SPLN 8
+#define ATM_AR_THTL 9
+#define ATM_AR_TSTL 10
+#define ATM_AR_TPLN 11
+#define MIN_ATMARP_HEADER_SIZE 12
+
+static void
+dissect_atm_number(tvbuff_t *tvb, int offset, int tl, int hf_e164,
+ int hf_nsap, proto_tree *tree)
+{
+ int len = tl & ATMARP_LEN_MASK;
+ proto_item *ti;
+ proto_tree *nsap_tree;
+
+ if (tl & ATMARP_IS_E164)
+ proto_tree_add_item(tree, hf_e164, tvb, offset, len, FALSE);
+ else {
+ ti = proto_tree_add_item(tree, hf_nsap, tvb, offset, len, FALSE);
+ if (len >= 20) {
+ nsap_tree = proto_item_add_subtree(ti, ett_atmarp_nsap);
+ dissect_atm_nsap(tvb, offset, len, nsap_tree);
+ }
+ }
+}
+
+void
+dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
+{
+ guint8 afi;
+
+ afi = tvb_get_guint8(tvb, offset);
+ switch (afi) {
+
+ case 0x39: /* DCC ATM format */
+ case 0xBD: /* DCC ATM group format */
+ proto_tree_add_text(tree, tvb, offset + 0, 3,
+ "Data Country Code%s: 0x%04X",
+ (afi == 0xBD) ? " (group)" : "",
+ tvb_get_ntohs(tvb, offset + 1));
+ proto_tree_add_text(tree, tvb, offset + 3, 10,
+ "High Order DSP: %s",
+ tvb_bytes_to_str(tvb, offset + 3, 10));
+ proto_tree_add_text(tree, tvb, offset + 13, 6,
+ "End System Identifier: %s",
+ tvb_bytes_to_str(tvb, offset + 13, 6));
+ proto_tree_add_text(tree, tvb, offset + 19, 1,
+ "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
+ break;
+
+ case 0x47: /* ICD ATM format */
+ case 0xC5: /* ICD ATM group format */
+ proto_tree_add_text(tree, tvb, offset + 0, 3,
+ "International Code Designator%s: 0x%04X",
+ (afi == 0xC5) ? " (group)" : "",
+ tvb_get_ntohs(tvb, offset + 1));
+ proto_tree_add_text(tree, tvb, offset + 3, 10,
+ "High Order DSP: %s",
+ tvb_bytes_to_str(tvb, offset + 3, 10));
+ proto_tree_add_text(tree, tvb, offset + 13, 6,
+ "End System Identifier: %s",
+ tvb_bytes_to_str(tvb, offset + 13, 6));
+ proto_tree_add_text(tree, tvb, offset + 19, 1,
+ "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
+ break;
+
+ case 0x45: /* E.164 ATM format */
+ case 0xC3: /* E.164 ATM group format */
+ proto_tree_add_text(tree, tvb, offset + 0, 9,
+ "E.164 ISDN%s: %s",
+ (afi == 0xC3) ? " (group)" : "",
+ tvb_bytes_to_str(tvb, offset + 1, 8));
+ proto_tree_add_text(tree, tvb, offset + 9, 4,
+ "High Order DSP: %s",
+ tvb_bytes_to_str(tvb, offset + 3, 10));
+ proto_tree_add_text(tree, tvb, offset + 13, 6,
+ "End System Identifier: %s",
+ tvb_bytes_to_str(tvb, offset + 13, 6));
+ proto_tree_add_text(tree, tvb, offset + 19, 1,
+ "Selector: 0x%02X", tvb_get_guint8(tvb, offset + 19));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Unknown AFI: 0x%02X", afi);
+ proto_tree_add_text(tree, tvb, offset + 1, len - 1,
+ "Rest of address: %s",
+ tvb_bytes_to_str(tvb, offset + 1, len - 1));
+ break;
+ }
+}
+
+/*
+ * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
+ */
+static void
+dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 ar_hrd;
+ guint16 ar_pro;
+ guint8 ar_shtl;
+ guint8 ar_shl;
+ guint8 ar_sstl;
+ guint8 ar_ssl;
+ guint16 ar_op;
+ guint8 ar_spln;
+ guint8 ar_thtl;
+ guint8 ar_thl;
+ guint8 ar_tstl;
+ guint8 ar_tsl;
+ guint8 ar_tpln;
+ int tot_len;
+ proto_tree *arp_tree;
+ proto_item *ti;
+ gchar *op_str;
+ int sha_offset, ssa_offset, spa_offset;
+ int tha_offset, tsa_offset, tpa_offset;
+ const guint8 *sha_val, *ssa_val, *spa_val;
+ const guint8 *tha_val, *tsa_val, *tpa_val;
+ gchar *sha_str, *ssa_str, *spa_str;
+ gchar *tha_str, *tsa_str, *tpa_str;
+ proto_tree *tl_tree;
+ proto_item *tl;
+
+ /* Override the setting to "ARP/RARP". */
+ pinfo->current_proto = "ATMARP";
+
+ ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
+ ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
+ ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
+ ar_shl = ar_shtl & ATMARP_LEN_MASK;
+ ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
+ ar_ssl = ar_sstl & ATMARP_LEN_MASK;
+ ar_op = tvb_get_ntohs(tvb, AR_OP);
+ ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
+ ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
+ ar_thl = ar_thtl & ATMARP_LEN_MASK;
+ ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
+ ar_tsl = ar_tstl & ATMARP_LEN_MASK;
+ ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);
+
+ tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
+ ar_thl + ar_tsl + ar_tpln;
+
+ /* Adjust the length of this tvbuff to include only the ARP datagram.
+ Our caller may use that to determine how much of its packet
+ was padding. */
+ tvb_set_reported_length(tvb, tot_len);
+
+ /* Extract the addresses. */
+ sha_offset = MIN_ATMARP_HEADER_SIZE;
+ if (ar_shl != 0) {
+ sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
+ sha_str = atmarpnum_to_str(sha_val, ar_shtl);
+ } else {
+ sha_val = NULL;
+ sha_str = "<No address>";
+ }
+
+ ssa_offset = sha_offset + ar_shl;
+ if (ar_ssl != 0) {
+ ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
+ ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
+ } else {
+ ssa_val = NULL;
+ ssa_str = NULL;
+ }
+
+ spa_offset = ssa_offset + ar_ssl;
+ spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
+ spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);
+
+ tha_offset = spa_offset + ar_spln;
+ if (ar_thl != 0) {
+ tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
+ tha_str = atmarpnum_to_str(tha_val, ar_thtl);
+ } else {
+ tha_val = NULL;
+ tha_str = "<No address>";
+ }
+
+ tsa_offset = tha_offset + ar_thl;
+ if (ar_tsl != 0) {
+ tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
+ tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
+ } else {
+ tsa_val = NULL;
+ tsa_str = NULL;
+ }
+
+ tpa_offset = tsa_offset + ar_tsl;
+ tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
+ tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ switch (ar_op) {
+
+ case ARPOP_REQUEST:
+ case ARPOP_REPLY:
+ case ATMARPOP_NAK:
+ default:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
+ break;
+
+ case ARPOP_RREQUEST:
+ case ARPOP_RREPLY:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
+ break;
+
+ case ARPOP_IREQUEST:
+ case ARPOP_IREPLY:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
+ break;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ switch (ar_op) {
+ case ARPOP_REQUEST:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s",
+ tpa_str, spa_str);
+ break;
+ case ARPOP_REPLY:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
+ ((ssa_str != NULL) ? "," : ""),
+ ((ssa_str != NULL) ? ssa_str : ""));
+ break;
+ case ARPOP_IREQUEST:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s? Tell %s%s%s",
+ tha_str,
+ ((tsa_str != NULL) ? "," : ""),
+ ((tsa_str != NULL) ? tsa_str : ""),
+ sha_str,
+ ((ssa_str != NULL) ? "," : ""),
+ ((ssa_str != NULL) ? ssa_str : ""));
+ break;
+ case ARPOP_IREPLY:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
+ sha_str,
+ ((ssa_str != NULL) ? "," : ""),
+ ((ssa_str != NULL) ? ssa_str : ""),
+ spa_str);
+ break;
+ case ATMARPOP_NAK:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
+ break;
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
+ break;
+ }
+ }
+
+ if (tree) {
+ if ((op_str = match_strval(ar_op, atmop_vals)))
+ ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
+ "ATM Address Resolution Protocol (%s)",
+ op_str);
+ else
+ ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
+ "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
+ arp_tree = proto_item_add_subtree(ti, ett_arp);
+
+ proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);
+
+ proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);
+
+ tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
+ "Sender ATM number type/length: %s/%u",
+ (ar_shtl & ATMARP_IS_E164 ?
+ "E.164" :
+ "ATM Forum NSAPA"),
+ ar_shl);
+ tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
+ proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
+ proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);
+
+ tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
+ "Sender ATM subaddress type/length: %s/%u",
+ (ar_sstl & ATMARP_IS_E164 ?
+ "E.164" :
+ "ATM Forum NSAPA"),
+ ar_ssl);
+ tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
+ proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
+ proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);
+
+ proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
+
+ proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);
+
+ tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
+ "Target ATM number type/length: %s/%u",
+ (ar_thtl & ATMARP_IS_E164 ?
+ "E.164" :
+ "ATM Forum NSAPA"),
+ ar_thl);
+ tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
+ proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
+ proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);
+
+ tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
+ "Target ATM subaddress type/length: %s/%u",
+ (ar_tstl & ATMARP_IS_E164 ?
+ "E.164" :
+ "ATM Forum NSAPA"),
+ ar_tsl);
+ tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
+ proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
+ proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);
+
+ proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);
+
+ if (ar_shl != 0)
+ dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
+ hf_atmarp_src_atm_num_nsap, arp_tree);
+
+ if (ar_ssl != 0)
+ proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
+ ar_ssl,
+ ssa_val,
+ "Sender ATM subaddress: %s", ssa_str);
+
+ if (ar_spln != 0) {
+ proto_tree_add_item(arp_tree,
+ ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
+ : hf_arp_src_proto,
+ tvb, spa_offset, ar_spln, FALSE);
+ }
+
+ if (ar_thl != 0)
+ dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
+ hf_atmarp_dst_atm_num_nsap, arp_tree);
+
+ if (ar_tsl != 0)
+ proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
+ ar_tsl,
+ tsa_val,
+ "Target ATM subaddress: %s", tsa_str);
+
+ if (ar_tpln != 0) {
+ proto_tree_add_item(arp_tree,
+ ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
+ : hf_arp_dst_proto,
+ tvb, tpa_offset, ar_tpln, FALSE);
+ }
+ }
+}
+
+static const guint8 mac_broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+static const guint8 mac_allzero[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static void
+dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 ar_hrd;
+ guint16 ar_pro;
+ guint8 ar_hln;
+ guint8 ar_pln;
+ guint16 ar_op;
+ int tot_len;
+ proto_tree *arp_tree;
+ proto_item *ti;
+ gchar *op_str;
+ int sha_offset, spa_offset, tha_offset, tpa_offset;
+ const guint8 *sha_val, *spa_val, *tha_val, *tpa_val;
+ gboolean is_gratuitous;
+
+ /* Call it ARP, for now, so that if we throw an exception before
+ we decide whether it's ARP or RARP or IARP or ATMARP, it shows
+ up in the packet list as ARP.
+
+ Clear the Info column so that, if we throw an exception, it
+ shows up as a short or malformed ARP frame. */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* Hardware Address Type */
+ ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
+ if (ar_hrd == ARPHRD_ATM2225) {
+ call_dissector(atmarp_handle, tvb, pinfo, tree);
+ return;
+ }
+ /* Protocol Address Type */
+ ar_pro = tvb_get_ntohs(tvb, AR_PRO);
+ /* Hardware Address Size */
+ ar_hln = tvb_get_guint8(tvb, AR_HLN);
+ /* Protocol Address Size */
+ ar_pln = tvb_get_guint8(tvb, AR_PLN);
+ /* Operation */
+ ar_op = tvb_get_ntohs(tvb, AR_OP);
+
+ tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;
+
+ /* Adjust the length of this tvbuff to include only the ARP datagram.
+ Our caller may use that to determine how much of its packet
+ was padding. */
+ tvb_set_reported_length(tvb, tot_len);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ switch (ar_op) {
+
+ case ARPOP_REQUEST:
+ case ARPOP_REPLY:
+ default:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
+ break;
+
+ case ARPOP_RREQUEST:
+ case ARPOP_RREPLY:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
+ break;
+
+ case ARPOP_IREQUEST:
+ case ARPOP_IREPLY:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
+ break;
+ }
+ }
+
+ /* Get the offsets of the addresses. */
+ /* Source Hardware Address */
+ sha_offset = MIN_ARP_HEADER_SIZE;
+ /* Source Protocol Address */
+ spa_offset = sha_offset + ar_hln;
+ /* Target Hardware Address */
+ tha_offset = spa_offset + ar_pln;
+ /* Target Protocol Address */
+ tpa_offset = tha_offset + ar_hln;
+
+ if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
+ ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
+ ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {
+
+ /* inform resolv.c module of the new discovered addresses */
+
+ guint ip;
+ const guint8 *mac;
+
+ /* Add sender address if sender MAC address is neither a broadcast/
+ multicast address nor an all-zero address and if sender IP address
+ isn't all zeroes. */
+ tvb_memcpy(tvb, (guint8 *)&ip, spa_offset, sizeof(ip));
+ mac = tvb_get_ptr(tvb, sha_offset, 6);
+ if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
+ add_ether_byip(ip, mac);
+
+ /* Add target address if target MAC address is neither a broadcast/
+ multicast address nor an all-zero address and if target IP address
+ isn't all zeroes. */
+ tvb_memcpy(tvb, (guint8 *)&ip, tpa_offset, sizeof(ip));
+ mac = tvb_get_ptr(tvb, tha_offset, 6);
+ if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
+ add_ether_byip(ip, mac);
+ }
+
+ if (!tree && !check_col(pinfo->cinfo, COL_INFO)) {
+ /* We're not building a protocol tree and we're not setting the Info
+ column, so we don't have any more work to do. */
+ return;
+ }
+
+ sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
+ spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
+ tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
+ tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
+
+ /* ARP requests with the same sender and target protocol address
+ are flagged as "gratuitous ARPs", i.e. ARPs sent out as, in
+ effect, an announcement that the machine has MAC address
+ XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY, to provoke
+ complaints if some other machine has the same IPv4 address. */
+ if ((ar_op == ARPOP_REQUEST) && (memcmp(spa_val, tpa_val, ar_pln) == 0))
+ is_gratuitous = TRUE;
+ else
+ is_gratuitous = FALSE;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ switch (ar_op) {
+ case ARPOP_REQUEST:
+ if (is_gratuitous)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Gratuitous ARP",
+ arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s? Tell %s",
+ arpproaddr_to_str(tpa_val, ar_pln, ar_pro),
+ arpproaddr_to_str(spa_val, ar_pln, ar_pro));
+ break;
+ case ARPOP_REPLY:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
+ arpproaddr_to_str(spa_val, ar_pln, ar_pro),
+ arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
+ break;
+ case ARPOP_RREQUEST:
+ case ARPOP_IREQUEST:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s? Tell %s",
+ arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
+ arphrdaddr_to_str(sha_val, ar_hln, ar_hrd));
+ break;
+ case ARPOP_RREPLY:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
+ arphrdaddr_to_str(tha_val, ar_hln, ar_hrd),
+ arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
+ break;
+ case ARPOP_IREPLY:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
+ arphrdaddr_to_str(sha_val, ar_hln, ar_hrd),
+ arpproaddr_to_str(spa_val, ar_pln, ar_pro));
+ break;
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
+ break;
+ }
+ }
+
+ if (tree) {
+ if ((op_str = match_strval(ar_op, op_vals))) {
+ if (is_gratuitous)
+ op_str = "request/gratuitous ARP";
+ ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
+ "Address Resolution Protocol (%s)", op_str);
+ } else
+ ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
+ "Address Resolution Protocol (opcode 0x%04x)", ar_op);
+ arp_tree = proto_item_add_subtree(ti, ett_arp);
+ proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
+ proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
+ proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
+ proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
+ proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP, 2, ar_op);
+ if (ar_hln != 0) {
+ proto_tree_add_item(arp_tree,
+ ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_src_hw_mac : hf_arp_src_hw,
+ tvb, sha_offset, ar_hln, FALSE);
+ }
+ if (ar_pln != 0) {
+ proto_tree_add_item(arp_tree,
+ ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_src_proto_ipv4
+ : hf_arp_src_proto,
+ tvb, spa_offset, ar_pln, FALSE);
+ }
+ if (ar_hln != 0) {
+ proto_tree_add_item(arp_tree,
+ ARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_arp_dst_hw_mac : hf_arp_dst_hw,
+ tvb, tha_offset, ar_hln, FALSE);
+ }
+ if (ar_pln != 0) {
+ proto_tree_add_item(arp_tree,
+ ARP_PRO_IS_IPv4(ar_pro, ar_pln) ? hf_arp_dst_proto_ipv4
+ : hf_arp_dst_proto,
+ tvb, tpa_offset, ar_pln, FALSE);
+ }
+ }
+}
+
+void
+proto_register_arp(void)
+{
+ static struct true_false_string type_bit = { "E.164", "ATM Forum NSAPA" };
+
+ static hf_register_info hf[] = {
+ { &hf_arp_hard_type,
+ { "Hardware type", "arp.hw.type",
+ FT_UINT16, BASE_HEX, VALS(hrd_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_arp_proto_type,
+ { "Protocol type", "arp.proto.type",
+ FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_arp_hard_size,
+ { "Hardware size", "arp.hw.size",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_atmarp_sht,
+ { "Sender ATM number type", "arp.src.htype",
+ FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
+ "", HFILL }},
+
+ { &hf_atmarp_shl,
+ { "Sender ATM number length", "arp.src.hlen",
+ FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
+ "", HFILL }},
+
+ { &hf_atmarp_sst,
+ { "Sender ATM subaddress type", "arp.src.stype",
+ FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
+ "", HFILL }},
+
+ { &hf_atmarp_ssl,
+ { "Sender ATM subaddress length", "arp.src.slen",
+ FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
+ "", HFILL }},
+
+ { &hf_arp_proto_size,
+ { "Protocol size", "arp.proto.size",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_arp_opcode,
+ { "Opcode", "arp.opcode",
+ FT_UINT16, BASE_HEX, VALS(op_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_atmarp_spln,
+ { "Sender protocol size", "arp.src.pln",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_atmarp_tht,
+ { "Target ATM number type", "arp.dst.htype",
+ FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
+ "", HFILL }},
+
+ { &hf_atmarp_thl,
+ { "Target ATM number length", "arp.dst.hlen",
+ FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
+ "", HFILL }},
+
+ { &hf_atmarp_tst,
+ { "Target ATM subaddress type", "arp.dst.stype",
+ FT_BOOLEAN, 8, &type_bit, ATMARP_IS_E164,
+ "", HFILL }},
+
+ { &hf_atmarp_tsl,
+ { "Target ATM subaddress length", "arp.dst.slen",
+ FT_UINT8, BASE_DEC, NULL, ATMARP_LEN_MASK,
+ "", HFILL }},
+
+ { &hf_atmarp_tpln,
+ { "Target protocol size", "arp.dst.pln",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_arp_src_hw,
+ { "Sender hardware address", "arp.src.hw",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_arp_src_hw_mac,
+ { "Sender MAC address", "arp.src.hw_mac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_atmarp_src_atm_num_e164,
+ { "Sender ATM number (E.164)", "arp.src.atm_num_e164",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_atmarp_src_atm_num_nsap,
+ { "Sender ATM number (NSAP)", "arp.src.atm_num_nsap",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_atmarp_src_atm_subaddr,
+ { "Sender ATM subaddress", "arp.src.atm_subaddr",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_arp_src_proto,
+ { "Sender protocol address", "arp.src.proto",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_arp_src_proto_ipv4,
+ { "Sender IP address", "arp.src.proto_ipv4",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_arp_dst_hw,
+ { "Target hardware address", "arp.dst.hw",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_arp_dst_hw_mac,
+ { "Target MAC address", "arp.dst.hw_mac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_atmarp_dst_atm_num_e164,
+ { "Target ATM number (E.164)", "arp.dst.atm_num_e164",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_atmarp_dst_atm_num_nsap,
+ { "Target ATM number (NSAP)", "arp.dst.atm_num_nsap",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_atmarp_dst_atm_subaddr,
+ { "Target ATM subaddress", "arp.dst.atm_subaddr",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_arp_dst_proto,
+ { "Target protocol address", "arp.dst.proto",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_arp_dst_proto_ipv4,
+ { "Target IP address", "arp.dst.proto_ipv4",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_arp,
+ &ett_atmarp_nsap,
+ &ett_atmarp_tl,
+ };
+
+ proto_arp = proto_register_protocol("Address Resolution Protocol",
+ "ARP/RARP", "arp");
+ proto_register_field_array(proto_arp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ atmarp_handle = create_dissector_handle(dissect_atmarp, proto_arp);
+
+ register_dissector( "arp" , dissect_arp, proto_arp );
+}
+
+void
+proto_reg_handoff_arp(void)
+{
+ dissector_handle_t arp_handle;
+
+ arp_handle = find_dissector("arp");
+
+ dissector_add("ethertype", ETHERTYPE_ARP, arp_handle);
+ dissector_add("ethertype", ETHERTYPE_REVARP, arp_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1051, arp_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_ARP_1201, arp_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_RARP_1201, arp_handle);
+
+}
diff --git a/epan/dissectors/packet-arp.h b/epan/dissectors/packet-arp.h
new file mode 100644
index 0000000000..782ac7fbf5
--- /dev/null
+++ b/epan/dissectors/packet-arp.h
@@ -0,0 +1,35 @@
+/* packet-arp.h
+ * Definitions of routines for ARP packet disassembly that are used
+ * elsewhere
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_ARP_H__
+#define __PACKET_ARP_H__
+
+gchar *arphrdaddr_to_str(const guint8 *ad, int ad_len, guint16 type);
+gchar *arphrdtype_to_str(guint16 hwtype, const char *fmt);
+
+void dissect_atm_nsap(tvbuff_t *tvb, int offset, int len, proto_tree *tree);
+
+#endif /* packet-atm.h */
diff --git a/epan/dissectors/packet-asap.c b/epan/dissectors/packet-asap.c
new file mode 100644
index 0000000000..d06aef7434
--- /dev/null
+++ b/epan/dissectors/packet-asap.c
@@ -0,0 +1,665 @@
+/* packet-asap.c
+ * Routines for Aggregate Server Access Protocol
+ * It is hopefully (needs testing) compilant to
+ * http://www.ietf.org/internet-drafts/draft-ietf-rserpool-common-param-06.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-rserpool-asap-09.txt
+ *
+ * Copyright 2004, Michael Tuexen <tuexen [AT] fh-muenster.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include "sctpppids.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_asap = -1;
+static int hf_cause_code = -1;
+static int hf_cause_length = -1;
+static int hf_cause_info = -1;
+static int hf_cause_padding = -1;
+static int hf_message_type = -1;
+static int hf_message_flags = -1;
+static int hf_message_length = -1;
+static int hf_parameter_type = -1;
+static int hf_parameter_length = -1;
+static int hf_parameter_value = -1;
+static int hf_parameter_padding = -1;
+static int hf_parameter_ipv4_address = -1;
+static int hf_parameter_ipv6_address = -1;
+static int hf_sctp_port = -1;
+static int hf_transport_use = -1;
+static int hf_tcp_port = -1;
+static int hf_udp_port = -1;
+static int hf_udp_reserved = -1;
+static int hf_policy_type = -1;
+static int hf_policy_value = -1;
+static int hf_pool_handle = -1;
+static int hf_pe_pe_identifier = -1;
+static int hf_home_enrp_id = -1;
+static int hf_reg_life = -1;
+static int hf_server_identifier = -1;
+static int hf_m_bit = -1;
+static int hf_reserved = -1;
+static int hf_cookie = -1;
+static int hf_pe_identifier = -1;
+static int hf_pe_checksum = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_asap = -1;
+static gint ett_asap_parameter = -1;
+static gint ett_asap_cause = -1;
+
+static void
+dissect_parameters(tvbuff_t *, proto_tree *);
+
+#define NETWORK_BYTE_ORDER FALSE
+#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
+
+/* Dissectors for error causes */
+#define CAUSE_CODE_LENGTH 2
+#define CAUSE_LENGTH_LENGTH 2
+#define CAUSE_HEADER_LENGTH (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
+
+#define CAUSE_HEADER_OFFSET 0
+#define CAUSE_CODE_OFFSET CAUSE_HEADER_OFFSET
+#define CAUSE_LENGTH_OFFSET (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
+#define CAUSE_INFO_OFFSET (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
+
+static void
+dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
+{
+ guint16 code, length, cause_info_length;
+
+ code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
+ length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
+ cause_info_length = length - CAUSE_HEADER_LENGTH;
+ if (cause_info_length > 0)
+ proto_tree_add_bytes(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length,
+ tvb_get_ptr(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length));
+ proto_item_append_text(cause_item, " (code %u and %u byte%s information)", code, cause_info_length, plurality(cause_info_length, "", "s"));
+}
+
+#define UNRECOGNIZED_PARAMETER_CAUSE_CODE 1
+#define UNRECONGNIZED_MESSAGE_CAUSE_CODE 2
+#define INVALID_VALUES 3
+#define NON_UNIQUE_PE_IDENTIFIER 4
+#define POOLING_POLICY_INCONSISTENT_CAUSE_CODE 5
+#define LACK_OF_RESOURCES_CAUSE_CODE 6
+#define INCONSISTENT_TRANSPORT_TYPE_CAUSE_CODE 7
+#define INCONSISTENT_DATA_CONTROL_CONFIGURATION_CAUSE_CODE 8
+
+static const value_string cause_code_values[] = {
+ { UNRECOGNIZED_PARAMETER_CAUSE_CODE, "Unrecognized parameter" },
+ { UNRECONGNIZED_MESSAGE_CAUSE_CODE, "Unrecognized message" },
+ { INVALID_VALUES, "Invalid values" },
+ { NON_UNIQUE_PE_IDENTIFIER, "Non-unique PE identifier" },
+ { POOLING_POLICY_INCONSISTENT_CAUSE_CODE, "Pooling policy inconsistent" },
+ { LACK_OF_RESOURCES_CAUSE_CODE, "Lack of resources" },
+ { INCONSISTENT_TRANSPORT_TYPE_CAUSE_CODE, "Inconsistent transport type" },
+ { INCONSISTENT_DATA_CONTROL_CONFIGURATION_CAUSE_CODE, "Inconsistent data/control type" },
+ { 0, NULL } };
+
+static void
+dissect_error_cause(tvbuff_t *cause_tvb, proto_tree *parameter_tree)
+{
+ guint16 code, length, padding_length;
+ proto_item *cause_item;
+ proto_tree *cause_tree;
+
+ code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
+ length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
+ padding_length = tvb_length(cause_tvb) - length;
+
+ cause_item = proto_tree_add_text(parameter_tree, cause_tvb, CAUSE_HEADER_OFFSET, tvb_length(cause_tvb), val_to_str(code, cause_code_values, "Unknown error cause"));
+ cause_tree = proto_item_add_subtree(cause_item, ett_asap_cause);
+
+ proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(code) {
+ default:
+ dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
+ break;
+ }
+ if (padding_length > 0)
+ proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_error_causes(tvbuff_t *error_causes_tvb, proto_tree *parameter_tree)
+{
+ guint16 length, total_length;
+ gint offset;
+ tvbuff_t *error_cause_tvb;
+
+ offset = 0;
+ while(tvb_reported_length_remaining(error_causes_tvb, offset)) {
+ length = tvb_get_ntohs(error_causes_tvb, offset + CAUSE_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ error_cause_tvb = tvb_new_subset(error_causes_tvb, offset , total_length, total_length);
+ dissect_error_cause(error_cause_tvb, parameter_tree);
+ offset += total_length;
+ }
+}
+
+/* Dissectors for parameters. This is common for ASAP and ENRP */
+
+#define PARAMETER_TYPE_LENGTH 2
+#define PARAMETER_LENGTH_LENGTH 2
+#define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
+
+#define PARAMETER_HEADER_OFFSET 0
+#define PARAMETER_TYPE_OFFSET PARAMETER_HEADER_OFFSET
+#define PARAMETER_LENGTH_OFFSET (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
+#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
+
+#define IPV4_ADDRESS_LENGTH 4
+#define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_parameter_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
+}
+
+#define IPV6_ADDRESS_LENGTH 16
+#define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_parameter_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
+}
+
+#define TRANSPORT_USE_DATA_ONLY 0
+#define TRANSPORT_USE_DATA_PLUS_CONTROL 1
+
+static const value_string transport_use_values[] = {
+ { TRANSPORT_USE_DATA_ONLY, "Data only" },
+ { TRANSPORT_USE_DATA_PLUS_CONTROL, "Data plus control" },
+ { 0, NULL } };
+
+#define SCTP_PORT_LENGTH 2
+#define SCTP_TRANSPORT_USE_LENGTH 2
+#define SCTP_PORT_OFFSET PARAMETER_VALUE_OFFSET
+#define SCTP_TRANSPORT_USE_OFFSET (SCTP_PORT_OFFSET + SCTP_PORT_LENGTH)
+#define SCTP_ADDRESS_OFFSET (SCTP_TRANSPORT_USE_OFFSET + SCTP_TRANSPORT_USE_LENGTH)
+
+static void
+dissect_sctp_transport_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_sctp_port, parameter_tvb, SCTP_PORT_OFFSET, SCTP_PORT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_transport_use, parameter_tvb, SCTP_TRANSPORT_USE_OFFSET, SCTP_TRANSPORT_USE_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, SCTP_ADDRESS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define TCP_PORT_LENGTH 2
+#define TCP_TRANSPORT_USE_LENGTH 2
+#define TCP_PORT_OFFSET PARAMETER_VALUE_OFFSET
+#define TCP_TRANSPORT_USE_OFFSET (TCP_PORT_OFFSET + TCP_PORT_LENGTH)
+#define TCP_ADDRESS_OFFSET (TCP_TRANSPORT_USE_OFFSET + TCP_TRANSPORT_USE_LENGTH)
+
+static void
+dissect_tcp_transport_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_tcp_port, parameter_tvb, TCP_PORT_OFFSET, TCP_PORT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_transport_use, parameter_tvb, TCP_TRANSPORT_USE_OFFSET, TCP_TRANSPORT_USE_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, TCP_ADDRESS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define UDP_PORT_LENGTH 2
+#define UDP_RESERVED_LENGTH 2
+#define UDP_PORT_OFFSET PARAMETER_VALUE_OFFSET
+#define UDP_RESERVED_OFFSET (UDP_PORT_OFFSET + UDP_PORT_LENGTH)
+#define UDP_ADDRESS_OFFSET (UDP_RESERVED_OFFSET + UDP_RESERVED_LENGTH)
+
+static void
+dissect_udp_transport_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_udp_port, parameter_tvb, UDP_PORT_OFFSET, UDP_PORT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_udp_reserved, parameter_tvb, UDP_RESERVED_OFFSET, UDP_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, UDP_ADDRESS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define POLICY_TYPE_LENGTH 1
+#define POLICY_VALUE_LENGTH 3
+
+#define POLICY_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+#define POLICY_VALUE_OFFSET (POLICY_TYPE_OFFSET + POLICY_TYPE_LENGTH)
+
+#define ROUND_ROBIN_POLICY 1
+#define LEAST_USED_POLICY 2
+#define LEAST_USED_WITH_DEG 3
+#define WEIGHTED_ROUND_ROBIN 4
+
+static const value_string policy_type_values[] = {
+ { ROUND_ROBIN_POLICY, "Round robin" },
+ { LEAST_USED_POLICY, "Least used" },
+ { LEAST_USED_WITH_DEG, "Least used with degradation" },
+ { WEIGHTED_ROUND_ROBIN, "Weighted round robin" },
+ { 0, NULL } };
+
+static void
+dissect_pool_member_selection_policy_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_tree_add_item(parameter_tree, hf_policy_type, parameter_tvb, POLICY_TYPE_OFFSET, POLICY_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_policy_value, parameter_tvb, POLICY_VALUE_OFFSET, POLICY_VALUE_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define POOL_HANDLE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_pool_handle_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ guint16 handle_length;
+
+ handle_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_pool_handle, parameter_tvb, POOL_HANDLE_OFFSET, handle_length, NETWORK_BYTE_ORDER);
+}
+
+#define PE_PE_IDENTIFIER_LENGTH 4
+#define HOME_ENRP_INDENTIFIER_LENGTH 4
+#define REGISTRATION_LIFE_LENGTH 4
+
+#define PE_PE_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+#define HOME_ENRP_INDENTIFIER_OFFSET (PE_PE_IDENTIFIER_OFFSET + PE_PE_IDENTIFIER_LENGTH)
+#define REGISTRATION_LIFE_OFFSET (HOME_ENRP_INDENTIFIER_OFFSET + HOME_ENRP_INDENTIFIER_LENGTH)
+#define USER_TRANSPORT_PARAMETER_OFFSET (REGISTRATION_LIFE_OFFSET + REGISTRATION_LIFE_LENGTH)
+
+static void
+dissect_pool_element_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_pe_pe_identifier, parameter_tvb, PE_PE_IDENTIFIER_OFFSET, PE_PE_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_home_enrp_id, parameter_tvb, HOME_ENRP_INDENTIFIER_OFFSET, HOME_ENRP_INDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_reg_life, parameter_tvb, REGISTRATION_LIFE_OFFSET, REGISTRATION_LIFE_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, USER_TRANSPORT_PARAMETER_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define SERVER_ID_LENGTH 4
+#define RESERVED_LENGTH 4
+
+#define SERVER_ID_OFFSET PARAMETER_VALUE_OFFSET
+#define RESERVED_OFFSET (SERVER_ID_OFFSET + SERVER_ID_LENGTH)
+#define SERVER_TRANSPORT_OFFSET (RESERVED_OFFSET + RESERVED_LENGTH)
+
+#define M_BIT_MASK 0x80000000
+#define RESERVED_MASK 0x7fffffff
+
+static void
+dissect_server_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_server_identifier, parameter_tvb, SERVER_ID_OFFSET, SERVER_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_m_bit, parameter_tvb, RESERVED_OFFSET, RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_reserved, parameter_tvb, RESERVED_OFFSET, RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, SERVER_TRANSPORT_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define ERROR_CAUSES_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_operation_error_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *error_causes_tvb;
+
+ error_causes_tvb = tvb_new_subset(parameter_tvb, ERROR_CAUSES_OFFSET, -1,-1);
+ dissect_error_causes(error_causes_tvb, parameter_tree);
+}
+
+#define COOKIE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 cookie_length;
+
+ cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ if (cookie_length > 0)
+ proto_tree_add_item(parameter_tree, hf_cookie, parameter_tvb, COOKIE_OFFSET, cookie_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", cookie_length, plurality(cookie_length, "", "s"));
+}
+
+#define PE_IDENTIFIER_LENGTH 4
+#define PE_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_pe_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_pe_identifier, parameter_tvb, PE_IDENTIFIER_OFFSET, PE_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (0x%x)", tvb_get_ntohl(parameter_tvb, PE_IDENTIFIER_OFFSET));
+}
+
+#define PE_CHECKSUM_LENGTH 4
+#define PE_CHECKSUM_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_pe_checksum_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_pe_checksum, parameter_tvb, PE_CHECKSUM_OFFSET, PE_CHECKSUM_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (0x%x)", tvb_get_ntohl(parameter_tvb, PE_CHECKSUM_OFFSET));
+}
+
+static void
+dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 type, parameter_value_length;
+
+ type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
+ parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+
+ if (parameter_value_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
+
+ proto_item_append_text(parameter_item, " (type %u and %u byte%s value)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
+}
+
+#define IPV4_ADDRESS_PARAMETER_TYPE 0x01
+#define IPV6_ADDRESS_PARAMETER_TYPE 0x02
+#define SCTP_TRANSPORT_PARAMETER_TYPE 0x03
+#define TCP_TRANSPORT_PARAMETER_TYPE 0x04
+#define UDP_TRANSPORT_PARAMETER_TYPE 0x05
+#define POOL_MEMBER_SELECTION_POLICY_PARAMETER_TYPE 0x06
+#define POOL_HANDLE_PARAMETER_TYPE 0x07
+#define POOL_ELEMENT_PARAMETER_TYPE 0x08
+#define SERVER_INFORMATION_PARAMETER_TYPE 0x09
+#define OPERATION_ERROR_PARAMETER_TYPE 0x0a
+#define COOKIE_PARAMETER_TYPE 0x0b
+#define PE_IDENTIFIER_PARAMETER_TYPE 0x0c
+#define PE_CHECKSUM_PARAMETER_TYPE 0x0d
+
+static const value_string parameter_type_values[] = {
+ { IPV4_ADDRESS_PARAMETER_TYPE, "IPV4 address" },
+ { IPV6_ADDRESS_PARAMETER_TYPE, "IPV6 address" },
+ { SCTP_TRANSPORT_PARAMETER_TYPE, "SCTP transport address" },
+ { TCP_TRANSPORT_PARAMETER_TYPE, "TCP transport address" },
+ { UDP_TRANSPORT_PARAMETER_TYPE, "UDP transport address" },
+ { POOL_MEMBER_SELECTION_POLICY_PARAMETER_TYPE, "Pool member selection policy" },
+ { POOL_HANDLE_PARAMETER_TYPE, "Pool handle" },
+ { POOL_ELEMENT_PARAMETER_TYPE, "Pool element" },
+ { SERVER_INFORMATION_PARAMETER_TYPE, "Server Information" },
+ { OPERATION_ERROR_PARAMETER_TYPE, "Operation error" },
+ { COOKIE_PARAMETER_TYPE, "Cookie" },
+ { PE_IDENTIFIER_PARAMETER_TYPE, "Pool Element identifier" },
+ { PE_CHECKSUM_PARAMETER_TYPE, "PE checksum" },
+ { 0, NULL } };
+
+
+static void
+dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *asap_tree)
+{
+ guint16 type, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+
+ /* extract tag and length from the parameter */
+ type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = tvb_length(parameter_tvb) - length;
+
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(asap_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), val_to_str(type, parameter_type_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_asap_parameter);
+
+ /* add tag and length to the asap tree */
+ proto_tree_add_item(parameter_tree, hf_parameter_type, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(type) {
+ case IPV4_ADDRESS_PARAMETER_TYPE:
+ dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case IPV6_ADDRESS_PARAMETER_TYPE:
+ dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case SCTP_TRANSPORT_PARAMETER_TYPE:
+ dissect_sctp_transport_parameter(parameter_tvb, parameter_tree);
+ break;
+ case TCP_TRANSPORT_PARAMETER_TYPE:
+ dissect_tcp_transport_parameter(parameter_tvb, parameter_tree);
+ break;
+ case UDP_TRANSPORT_PARAMETER_TYPE:
+ dissect_udp_transport_parameter(parameter_tvb, parameter_tree);
+ break;
+ case POOL_MEMBER_SELECTION_POLICY_PARAMETER_TYPE:
+ dissect_pool_member_selection_policy_parameter(parameter_tvb, parameter_tree);
+ break;
+ case POOL_HANDLE_PARAMETER_TYPE:
+ dissect_pool_handle_parameter(parameter_tvb, parameter_tree);
+ break;
+ case POOL_ELEMENT_PARAMETER_TYPE:
+ dissect_pool_element_parameter(parameter_tvb, parameter_tree);
+ break;
+ case SERVER_INFORMATION_PARAMETER_TYPE:
+ dissect_server_information_parameter(parameter_tvb, parameter_tree);
+ break;
+ case OPERATION_ERROR_PARAMETER_TYPE:
+ dissect_operation_error_parameter(parameter_tvb, parameter_tree);
+ break;
+ case COOKIE_PARAMETER_TYPE:
+ dissect_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PE_IDENTIFIER_PARAMETER_TYPE:
+ dissect_pe_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PE_CHECKSUM_PARAMETER_TYPE:
+ dissect_pe_checksum_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ default:
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ };
+
+ if (padding_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_parameters(tvbuff_t *parameters_tvb, proto_tree *tree)
+{
+ gint offset, length, total_length, remaining_length;
+ tvbuff_t *parameter_tvb;
+
+ offset = 0;
+ while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
+ length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ if (remaining_length >= length)
+ total_length = MIN(total_length, remaining_length);
+ /* create a tvb for the parameter including the padding bytes */
+ parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
+ dissect_parameter(parameter_tvb, tree);
+ /* get rid of the handled parameter */
+ offset += total_length;
+ }
+}
+
+#define MESSAGE_TYPE_LENGTH 1
+#define MESSAGE_FLAGS_LENGTH 1
+#define MESSAGE_LENGTH_LENGTH 2
+
+#define MESSAGE_TYPE_OFFSET 0
+#define MESSAGE_FLAGS_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
+#define MESSAGE_LENGTH_OFFSET (MESSAGE_FLAGS_OFFSET + MESSAGE_FLAGS_LENGTH)
+#define MESSAGE_VALUE_OFFSET (MESSAGE_LENGTH_OFFSET + MESSAGE_LENGTH_LENGTH)
+
+#define REGISTRATION_MESSAGE_TYPE 0x01
+#define DEREGISTRATION_MESSAGE_TYPE 0x02
+#define REGISTRATION_RESPONSE_MESSAGE_TYPE 0x03
+#define DEREGISTRATION_RESPONSE_MESSAGE_TYPE 0x04
+#define NAME_RESOLUTION_MESSAGE_TYPE 0x05
+#define NAME_RESOLUTION_RESPONSE_MESSAGE_TYPE 0x06
+#define ENDPOINT_KEEP_ALIVE_MESSAGE_TYPE 0x07
+#define ENDPOINT_KEEP_ALIVE_ACK_MESSAGE_TYPE 0x08
+#define ENDPOINT_UNREACHABLE_MESSAGE_TYPE 0x09
+#define SERVER_ANNOUNCE_MESSAGE_TYPE 0x0a
+#define COOKIE_MESSAGE_TYPE 0x0b
+#define COOKIE_ECHO_MESSAGE_TYPE 0x0c
+#define BUSINESS_CARD_MESSAGE_TYPE 0x0d
+#define PEER_ERROR_MESSAGE_TYPE 0x0e
+
+static const value_string message_type_values[] = {
+ { REGISTRATION_MESSAGE_TYPE, "Registration" },
+ { DEREGISTRATION_MESSAGE_TYPE, "Deregistration" },
+ { REGISTRATION_RESPONSE_MESSAGE_TYPE, "Registration response" },
+ { DEREGISTRATION_RESPONSE_MESSAGE_TYPE, "Deregistration response" },
+ { NAME_RESOLUTION_MESSAGE_TYPE, "Name resolution" },
+ { NAME_RESOLUTION_RESPONSE_MESSAGE_TYPE, "Name resolution response" },
+ { ENDPOINT_KEEP_ALIVE_MESSAGE_TYPE, "Endpoint keep alive" },
+ { ENDPOINT_KEEP_ALIVE_ACK_MESSAGE_TYPE, "Endpoint keep alive acknowledgement" },
+ { ENDPOINT_UNREACHABLE_MESSAGE_TYPE, "Endpoint unreachable" },
+ { SERVER_ANNOUNCE_MESSAGE_TYPE, "Server announce" },
+ { COOKIE_MESSAGE_TYPE, "Cookie" },
+ { COOKIE_ECHO_MESSAGE_TYPE, "Cookie echo" },
+ { BUSINESS_CARD_MESSAGE_TYPE, "Business card" },
+ { PEER_ERROR_MESSAGE_TYPE, "Peer error" },
+ { 0, NULL } };
+
+static void
+dissect_asap_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *asap_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(tvb_get_guint8(message_tvb, MESSAGE_TYPE_OFFSET), message_type_values, "Unknown ASAP type"));
+
+ if (asap_tree) {
+ proto_tree_add_item(asap_tree, hf_message_type, message_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(asap_tree, hf_message_flags, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(asap_tree, hf_message_length, message_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ parameters_tvb = tvb_new_subset(message_tvb, MESSAGE_VALUE_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, asap_tree);
+ }
+}
+
+static void
+dissect_asap(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *asap_item;
+ proto_tree *asap_tree;
+
+ /* make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ASAP");
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the asap protocol tree */
+ asap_item = proto_tree_add_item(tree, proto_asap, message_tvb, 0, -1, FALSE);
+ asap_tree = proto_item_add_subtree(asap_item, ett_asap);
+ } else {
+ asap_tree = NULL;
+ };
+ /* dissect the message */
+ dissect_asap_message(message_tvb, pinfo, asap_tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_asap(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_message_type, { "Type", "asap.message_type", FT_UINT8, BASE_DEC, VALS(message_type_values), 0x0, "", HFILL } },
+ { &hf_message_flags, { "Flags", "asap.message_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_message_length, { "Length", "asap.message_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause_code, { "Cause code", "asap.cause_code", FT_UINT16, BASE_HEX, VALS(cause_code_values), 0x0, "", HFILL } },
+ { &hf_cause_length, { "Cause length", "asap.cause_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause_info, { "Cause info", "asap.cause_info", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_cause_padding, { "Padding", "asap.cause_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_type, { "Parameter Type", "asap.parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_type_values), 0x0, "", HFILL } },
+ { &hf_parameter_length, { "Parameter length", "asap.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_value, { "Parameter value", "asap.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_padding, { "Padding", "asap.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_ipv4_address, { "IP Version 4 address", "asap.ipv4_address", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_ipv6_address, { "IP Version 6 address", "asap.ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_sctp_port, { "Port", "asap.sctp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_transport_use, { "Transport use", "asap.transport_use", FT_UINT16, BASE_DEC, VALS(transport_use_values), 0x0, "", HFILL } },
+ { &hf_tcp_port, { "Port", "asap.tcp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_udp_port, { "Port", "asap.udp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_udp_reserved, { "Reserved", "asap.udp_transport_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_policy_type, { "Policy type", "asap.pool_member_slection_policy_type", FT_UINT8, BASE_DEC, VALS(policy_type_values), 0x0, "", HFILL } },
+ { &hf_policy_value, { "Policy value", "asap.pool_member_slection_policy_value", FT_INT24, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_pool_handle, { "Pool handle", "asap.pool_handle_pool_handle", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_pe_pe_identifier, { "PE identifier", "asap.pool_element_pe_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_home_enrp_id, { "Home ENRP server identifier", "asap.pool_element_home_enrp_server_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_reg_life, { "Registration life", "asap.pool_element_registration_life", FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_server_identifier, { "Server identifier", "asap.server_information_server_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_m_bit, { "M-Bit", "asap.server_information_m_bit", FT_BOOLEAN, 32, NULL, M_BIT_MASK, "", HFILL } },
+ { &hf_reserved, { "Reserved", "asap.server_information_reserved", FT_UINT32, BASE_HEX, NULL, RESERVED_MASK, "", HFILL } },
+ { &hf_cookie, { "Cookie", "asap.cookie", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_pe_identifier, { "PE identifier", "asap.pe_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_pe_checksum, { "PE checksum", "asap.pe_checksum", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_asap,
+ &ett_asap_parameter,
+ &ett_asap_cause,
+ };
+
+ /* Register the protocol name and description */
+ proto_asap = proto_register_protocol("Aggregate Server Access Protocol", "ASAP", "asap");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_asap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_asap(void)
+{
+ dissector_handle_t asap_handle;
+
+ asap_handle = create_dissector_handle(dissect_asap, proto_asap);
+ dissector_add("sctp.ppi", ASAP_PAYLOAD_PROTOCOL_ID, asap_handle);
+}
diff --git a/epan/dissectors/packet-ascend.c b/epan/dissectors/packet-ascend.c
new file mode 100644
index 0000000000..1c3caa7f8d
--- /dev/null
+++ b/epan/dissectors/packet-ascend.c
@@ -0,0 +1,169 @@
+/* packet-ascend.c
+ * Routines for decoding Lucent/Ascend packet traces
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+
+static int proto_ascend = -1;
+static int hf_link_type = -1;
+static int hf_session_id = -1;
+static int hf_called_number = -1;
+static int hf_chunk = -1;
+static int hf_task = -1;
+static int hf_user_name = -1;
+
+static gint ett_raw = -1;
+
+static const value_string encaps_vals[] = {
+ {ASCEND_PFX_WDS_X, "PPP Transmit"},
+ {ASCEND_PFX_WDS_R, "PPP Receive" },
+ {ASCEND_PFX_WDD, "Ethernet" },
+ {0, NULL } };
+
+static dissector_handle_t eth_handle;
+static dissector_handle_t ppp_hdlc_handle;
+
+static void
+dissect_ascend(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *fh_tree;
+ proto_item *ti;
+ union wtap_pseudo_header *pseudo_header = pinfo->pseudo_header;
+
+ /* load the top pane info. This should be overwritten by
+ the next protocol in the stack */
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A" );
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A" );
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "N/A" );
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Lucent/Ascend packet trace" );
+
+ /* If this is a transmitted or received PPP frame, set the PPP direction. */
+ switch (pseudo_header->ascend.type) {
+
+ case ASCEND_PFX_WDS_X:
+ pinfo->p2p_dir = P2P_DIR_SENT;
+ break;
+
+ case ASCEND_PFX_WDS_R:
+ pinfo->p2p_dir = P2P_DIR_RECV;
+ break;
+ }
+
+ /* populate a tree in the second pane with the status of the link
+ layer (ie none) */
+ if(tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_ascend, tvb, 0, 0,
+ "Lucent/Ascend packet trace");
+ fh_tree = proto_item_add_subtree(ti, ett_raw);
+ proto_tree_add_uint(fh_tree, hf_link_type, tvb, 0, 0,
+ pseudo_header->ascend.type);
+ if (pseudo_header->ascend.type == ASCEND_PFX_WDD) {
+ proto_tree_add_string(fh_tree, hf_called_number, tvb, 0, 0,
+ pseudo_header->ascend.call_num);
+ proto_tree_add_uint(fh_tree, hf_chunk, tvb, 0, 0,
+ pseudo_header->ascend.chunk);
+ proto_tree_add_uint_hidden(fh_tree, hf_session_id, tvb, 0, 0, 0);
+ } else { /* It's wandsession data */
+ proto_tree_add_string(fh_tree, hf_user_name, tvb, 0, 0,
+ pseudo_header->ascend.user);
+ proto_tree_add_uint(fh_tree, hf_session_id, tvb, 0, 0,
+ pseudo_header->ascend.sess);
+ proto_tree_add_uint_hidden(fh_tree, hf_chunk, tvb, 0, 0, 0);
+ }
+ proto_tree_add_uint(fh_tree, hf_task, tvb, 0, 0, pseudo_header->ascend.task);
+ }
+
+ switch (pseudo_header->ascend.type) {
+ case ASCEND_PFX_WDS_X:
+ case ASCEND_PFX_WDS_R:
+ call_dissector(ppp_hdlc_handle, tvb, pinfo, tree);
+ break;
+ case ASCEND_PFX_WDD:
+ call_dissector(eth_handle, tvb, pinfo, tree);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+proto_register_ascend(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_link_type,
+ { "Link type", "ascend.type", FT_UINT32, BASE_DEC, VALS(encaps_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_session_id,
+ { "Session ID", "ascend.sess", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_called_number,
+ { "Called number", "ascend.number", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_chunk,
+ { "WDD Chunk", "ascend.chunk", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_task,
+ { "Task", "ascend.task", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_user_name,
+ { "User name", "ascend.user", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_raw,
+ };
+
+ proto_ascend = proto_register_protocol("Lucent/Ascend debug output",
+ "Lucent/Ascend", "ascend");
+ proto_register_field_array(proto_ascend, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ascend(void)
+{
+ dissector_handle_t ascend_handle;
+
+ /*
+ * Get handles for the Ethernet and PPP-in-HDLC-like-framing dissectors.
+ */
+ eth_handle = find_dissector("eth");
+ ppp_hdlc_handle = find_dissector("ppp_hdlc");
+
+ ascend_handle = create_dissector_handle(dissect_ascend, proto_ascend);
+ dissector_add("wtap_encap", WTAP_ENCAP_ASCEND, ascend_handle);
+}
diff --git a/epan/dissectors/packet-asf.c b/epan/dissectors/packet-asf.c
new file mode 100644
index 0000000000..db0b534d18
--- /dev/null
+++ b/epan/dissectors/packet-asf.c
@@ -0,0 +1,146 @@
+/* packet-asf.c
+ * Routines for ASF packet dissection
+ *
+ * Duncan Laurie <duncan@sun.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-rmcp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+/*
+ * See
+ *
+ * http://www.dmtf.org/standards/standard_alert.php
+ */
+
+#define RMCP_CLASS_ASF 0x06
+
+static int proto_asf = -1;
+static int hf_asf_iana = -1;
+static int hf_asf_type = -1;
+static int hf_asf_tag = -1;
+static int hf_asf_len = -1;
+
+static dissector_handle_t data_handle;
+static gint ett_asf = -1;
+
+static const value_string asf_type_vals[] = {
+ { 0x10, "Reset" },
+ { 0x11, "Power-up" },
+ { 0x12, "Unconditional Power-down" },
+ { 0x13, "Power Cycle" },
+ { 0x40, "Presence Pong" },
+ { 0x41, "Capabilities Response" },
+ { 0x42, "System State Response" },
+ { 0x80, "Presence Ping" },
+ { 0x81, "Capabilities Request" },
+ { 0x82, "System State Request" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_asf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *asf_tree = NULL;
+ proto_item *ti;
+ guint8 type;
+ guint8 len;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ASF");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ type = tvb_get_guint8(tvb, 4);
+ len = tvb_get_guint8(tvb, 7);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(type, asf_type_vals, "Unknown (0x%02x)"));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_asf, tvb, 0, 8, TRUE);
+ asf_tree = proto_item_add_subtree(ti, ett_asf);
+ proto_tree_add_item(asf_tree, hf_asf_iana, tvb, 0, 4, TRUE);
+ proto_tree_add_item(asf_tree, hf_asf_type, tvb, 4, 1, TRUE);
+ proto_tree_add_item(asf_tree, hf_asf_tag, tvb, 5, 1, TRUE);
+ proto_tree_add_item(asf_tree, hf_asf_len, tvb, 7, 1, TRUE);
+ }
+
+ if (len) {
+ next_tvb = tvb_new_subset(tvb, 8, -1, len);
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+}
+
+void
+proto_register_asf(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_asf_iana, {
+ "IANA Enterprise Number", "asf.iana",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "ASF IANA Enterprise Number", HFILL }},
+ { &hf_asf_type, {
+ "Message Type", "asf.type",
+ FT_UINT8, BASE_HEX, VALS(asf_type_vals), 0,
+ "ASF Message Type", HFILL }},
+ { &hf_asf_tag, {
+ "Message Tag", "asf.tag",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "ASF Message Tag", HFILL }},
+ { &hf_asf_len, {
+ "Data Length", "asf.len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "ASF Data Length", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_asf,
+ };
+
+ proto_asf = proto_register_protocol(
+ "Alert Standard Forum", "ASF", "asf");
+
+ proto_register_field_array(proto_asf, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_asf(void)
+{
+ dissector_handle_t asf_handle;
+
+ data_handle = find_dissector("data");
+
+ asf_handle = create_dissector_handle(dissect_asf, proto_asf);
+ dissector_add("rmcp.class", RMCP_CLASS_ASF, asf_handle);
+}
diff --git a/epan/dissectors/packet-atalk.c b/epan/dissectors/packet-atalk.c
new file mode 100644
index 0000000000..f74520ef27
--- /dev/null
+++ b/epan/dissectors/packet-atalk.c
@@ -0,0 +1,2303 @@
+/* packet-atalk.c
+ * Routines for AppleTalk packet disassembly: LLAP, DDP, NBP, ATP, ASP,
+ * RTMP.
+ *
+ * $Id$
+ *
+ * Simon Wilkinson <sxw@dcs.ed.ac.uk>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <string.h>
+
+#include "etypes.h"
+#include "ppptypes.h"
+#include "aftypes.h"
+#include "arcnet_pids.h"
+#include <epan/atalk-utils.h>
+#include <epan/conversation.h>
+
+#include "prefs.h"
+#include "reassemble.h"
+
+#include "packet-afp.h"
+
+/* Tables for reassembly of fragments. */
+static GHashTable *atp_fragment_table = NULL;
+static GHashTable *atp_reassembled_table = NULL;
+
+/* desegmentation of ATP */
+static gboolean atp_defragment = TRUE;
+
+static dissector_handle_t afp_handle;
+
+static int proto_llap = -1;
+static int hf_llap_dst = -1;
+static int hf_llap_src = -1;
+static int hf_llap_type = -1;
+
+static int proto_ddp = -1;
+static int hf_ddp_hopcount = -1;
+static int hf_ddp_len = -1;
+static int hf_ddp_checksum = -1;
+static int hf_ddp_dst = -1;
+static int hf_ddp_dst_net = -1;
+static int hf_ddp_src = -1;
+static int hf_ddp_src_net = -1;
+static int hf_ddp_dst_node = -1;
+static int hf_ddp_src_node = -1;
+static int hf_ddp_dst_socket = -1;
+static int hf_ddp_src_socket = -1;
+static int hf_ddp_type = -1;
+
+static dissector_handle_t ddp_handle;
+
+/* --------------------------------------
+ * ATP protocol parameters
+ * from netatalk/include/atalk/atp.h
+ */
+#define ATP_MAXDATA (578+4) /* maximum ATP data size */
+#define ATP_BUFSIZ 587 /* maximum packet size */
+#define ATP_HDRSIZE 5 /* includes DDP type field */
+
+#define ATP_TRELMASK 0x07 /* mask all but TREL */
+#define ATP_RELTIME 30 /* base release timer (in secs) */
+
+#define ATP_TREL30 0x0 /* release time codes */
+#define ATP_TREL1M 0x1 /* these are passed in flags of */
+#define ATP_TREL2M 0x2 /* atp_sreq call, and set in the */
+#define ATP_TREL4M 0x3 /* packet control info. */
+#define ATP_TREL8M 0x4
+
+/* flags for ATP options (and control byte)
+*/
+#define ATP_XO 0x20 /* (1<<5) eXactly Once mode */
+#define ATP_EOM 0x10 /* (1<<4) End Of Message */
+#define ATP_STS 0x08 /* (1<<3) Transaction Status */
+
+/* function codes
+*/
+#define ATP_FUNCMASK (3<<6) /* mask all but function */
+
+#define ATP_TREQ 1 /* (1<<6) Trans. REQuest */
+#define ATP_TRESP 2 /* (2<<6) Trans. RESPonse */
+#define ATP_TREL 3 /* (3<<6) Trans. RELease */
+
+/* ------------------------- */
+static dissector_handle_t asp_handle;
+
+static int proto_atp = -1;
+static int hf_atp_ctrlinfo = -1; /* guint8_t control information */
+static int hf_atp_function = -1; /* bits 7,6 function */
+static int hf_atp_xo = -1; /* bit 5 exactly-once */
+static int hf_atp_eom = -1; /* bit 4 end-of-message */
+static int hf_atp_sts = -1; /* bit 3 send transaction status */
+static int hf_atp_treltimer = -1; /* bits 2,1,0 TRel timeout indicator */
+
+static int hf_atp_bitmap = -1; /* guint8_t bitmap or sequence number */
+static int hf_atp_tid = -1; /* guint16_t transaction id. */
+static int hf_atp_user_bytes = -1;
+
+static int hf_atp_segments = -1;
+static int hf_atp_segment = -1;
+static int hf_atp_segment_overlap = -1;
+static int hf_atp_segment_overlap_conflict = -1;
+static int hf_atp_segment_multiple_tails = -1;
+static int hf_atp_segment_too_long_segment = -1;
+static int hf_atp_segment_error = -1;
+static int hf_atp_reassembled_in = -1;
+
+/* ------------------------- */
+static int proto_zip = -1;
+static dissector_handle_t zip_atp_handle;
+
+static int hf_zip_function = -1;
+static int hf_zip_atp_function = -1;
+static int hf_zip_start_index = -1;
+static int hf_zip_count = -1;
+static int hf_zip_zero_value = -1;
+
+static int hf_zip_network_count = -1;
+static int hf_zip_network = -1;
+static int hf_zip_network_start = -1;
+static int hf_zip_network_end = -1;
+
+static int hf_zip_flags = -1;
+
+static int hf_zip_flags_zone_invalid = -1;
+static int hf_zip_flags_use_broadcast = -1;
+static int hf_zip_flags_only_one_zone = -1;
+
+static int hf_zip_last_flag = -1;
+
+static int hf_zip_zone_name = -1;
+static int hf_zip_default_zone = -1;
+
+static int hf_zip_multicast_length = -1;
+static int hf_zip_multicast_address = -1;
+
+static const value_string zip_function_vals[] = {
+ {1, "Query"},
+ {2, "Reply"},
+ {5, "GetNetInfo request"},
+ {6, "GetNetInfo reply"},
+ {7, "notify"},
+ {8, "Extended reply"},
+ {0, NULL}
+};
+
+static const value_string zip_atp_function_vals[] = {
+ {7, "GetMyZone"},
+ {8, "GetZoneList"},
+ {9, "GetLocalZones"},
+ {0, NULL}
+};
+
+static gint ett_zip = -1;
+static gint ett_zip_flags = -1;
+static gint ett_zip_zones_list = -1;
+static gint ett_zip_network_list = -1;
+
+/* --------------------------------
+ * from netatalk/include/atalk/ats.h
+ */
+
+#define ASPFUNC_CLOSE 1
+#define ASPFUNC_CMD 2
+#define ASPFUNC_STAT 3
+#define ASPFUNC_OPEN 4
+#define ASPFUNC_TICKLE 5
+#define ASPFUNC_WRITE 6
+#define ASPFUNC_WRTCONT 7
+#define ASPFUNC_ATTN 8
+
+#define ASP_HDRSIZ 4
+#define ASPERR_OK 0x0000
+#define ASPERR_BADVERS 0xfbd6
+#define ASPERR_BUFSMALL 0xfbd5
+#define ASPERR_NOSESS 0xfbd4
+#define ASPERR_NOSERV 0xfbd3
+#define ASPERR_PARM 0xfbd2
+#define ASPERR_SERVBUSY 0xfbd1
+#define ASPERR_SESSCLOS 0xfbd0
+#define ASPERR_SIZERR 0xfbcf
+#define ASPERR_TOOMANY 0xfbce
+#define ASPERR_NOACK 0xfbcd
+
+static int proto_asp = -1;
+static int hf_asp_func = -1;
+static int hf_asp_error = -1;
+static int hf_asp_socket = -1;
+static int hf_asp_version = -1;
+static int hf_asp_session_id = -1;
+static int hf_asp_zero_value = -1;
+static int hf_asp_init_error = -1;
+static int hf_asp_attn_code = -1;
+static int hf_asp_seq = -1;
+static int hf_asp_size = -1;
+
+/* status stuff same for asp and afp */
+static int hf_asp_server_name = -1;
+static int hf_asp_server_type = -1;
+static int hf_asp_server_vers = -1;
+static int hf_asp_server_uams = -1;
+static int hf_asp_server_icon = -1;
+static int hf_asp_server_directory = -1;
+
+static int hf_asp_server_flag = -1;
+static int hf_asp_server_flag_copyfile = -1;
+static int hf_asp_server_flag_passwd = -1;
+static int hf_asp_server_flag_no_save_passwd = -1;
+static int hf_asp_server_flag_srv_msg = -1;
+static int hf_asp_server_flag_srv_sig = -1;
+static int hf_asp_server_flag_tcpip = -1;
+static int hf_asp_server_flag_notify = -1;
+static int hf_asp_server_flag_reconnect = -1;
+static int hf_asp_server_flag_directory = -1;
+static int hf_asp_server_flag_utf8_name = -1;
+static int hf_asp_server_flag_fast_copy = -1;
+static int hf_asp_server_signature = -1;
+static int hf_asp_server_utf8_name_len = -1;
+static int hf_asp_server_utf8_name = -1;
+
+static int hf_asp_server_addr_len = -1;
+static int hf_asp_server_addr_type = -1;
+static int hf_asp_server_addr_value = -1;
+
+static gint ett_asp_status = -1;
+static gint ett_asp_uams = -1;
+static gint ett_asp_vers = -1;
+static gint ett_asp_addr = -1;
+static gint ett_asp_addr_line = -1;
+static gint ett_asp_directory = -1;
+static gint ett_asp_utf8_name = -1;
+static gint ett_asp_status_server_flag = -1;
+
+static guint asp_packet_init_count = 200;
+
+typedef struct {
+ guint32 conversation;
+ guint8 src[4];
+ guint16 seq;
+} asp_request_key;
+
+typedef struct {
+ guint8 value; /* command for asp, bitmap for atp */
+} asp_request_val;
+
+static GHashTable *asp_request_hash = NULL;
+static GMemChunk *asp_request_keys = NULL;
+static GMemChunk *asp_request_vals = NULL;
+
+/* Hash Functions */
+static gint asp_equal (gconstpointer v, gconstpointer v2)
+{
+ const asp_request_key *val1 = (const asp_request_key*)v;
+ const asp_request_key *val2 = (const asp_request_key*)v2;
+
+ if (val1->conversation == val2->conversation &&
+ val1->seq == val2->seq &&
+ !memcmp(val1->src, val2->src, 4)) {
+ return 1;
+ }
+ return 0;
+}
+
+static guint asp_hash (gconstpointer v)
+{
+ const asp_request_key *asp_key = (const asp_request_key*)v;
+ return asp_key->seq;
+}
+
+/* ------------------------------------ */
+static GHashTable *atp_request_hash = NULL;
+static GMemChunk *atp_request_keys = NULL;
+static GMemChunk *atp_request_vals = NULL;
+
+
+/* ------------------------------------ */
+static int proto_nbp = -1;
+static int hf_nbp_op = -1;
+static int hf_nbp_info = -1;
+static int hf_nbp_count = -1;
+static int hf_nbp_tid = -1;
+
+static int hf_nbp_node_net = -1;
+static int hf_nbp_node_port = -1;
+static int hf_nbp_node_node = -1;
+static int hf_nbp_node_enum = -1;
+static int hf_nbp_node_object = -1;
+static int hf_nbp_node_type = -1;
+static int hf_nbp_node_zone = -1;
+
+static int proto_rtmp = -1;
+static int hf_rtmp_net = -1;
+static int hf_rtmp_node_len = -1;
+static int hf_rtmp_node = -1;
+static int hf_rtmp_tuple_net = -1;
+static int hf_rtmp_tuple_range_start = -1;
+static int hf_rtmp_tuple_range_end = -1;
+static int hf_rtmp_tuple_dist = -1;
+static int hf_rtmp_function = -1;
+
+static gint ett_atp = -1;
+
+static gint ett_atp_segments = -1;
+static gint ett_atp_segment = -1;
+static gint ett_atp_info = -1;
+static gint ett_asp = -1;
+
+static gint ett_nbp = -1;
+static gint ett_nbp_info = -1;
+static gint ett_nbp_node = -1;
+static gint ett_rtmp = -1;
+static gint ett_rtmp_tuple = -1;
+static gint ett_ddp = -1;
+static gint ett_llap = -1;
+static gint ett_pstring = -1;
+
+static const fragment_items atp_frag_items = {
+ &ett_atp_segment,
+ &ett_atp_segments,
+ &hf_atp_segments,
+ &hf_atp_segment,
+ &hf_atp_segment_overlap,
+ &hf_atp_segment_overlap_conflict,
+ &hf_atp_segment_multiple_tails,
+ &hf_atp_segment_too_long_segment,
+ &hf_atp_segment_error,
+ &hf_atp_reassembled_in,
+ "segments"
+};
+
+static dissector_table_t ddp_dissector_table;
+
+static dissector_handle_t data_handle;
+
+#define DDP_SHORT_HEADER_SIZE 5
+
+/*
+ * P = Padding, H = Hops, L = Len
+ *
+ * PPHHHHLL LLLLLLLL
+ *
+ * Assumes the argument is in host byte order.
+ */
+#define ddp_hops(x) ( ( x >> 10) & 0x3C )
+#define ddp_len(x) ( x & 0x03ff )
+typedef struct _e_ddp {
+ guint16 hops_len; /* combines pad, hops, and len */
+ guint16 sum,dnet,snet;
+ guint8 dnode,snode;
+ guint8 dport,sport;
+ guint8 type;
+} e_ddp;
+
+#define DDP_HEADER_SIZE 13
+
+
+static const value_string op_vals[] = {
+ {DDP_RTMPDATA, "AppleTalk Routing Table response or data" },
+ {DDP_NBP, "AppleTalk Name Binding Protocol packet"},
+ {DDP_ATP, "AppleTalk Transaction Protocol packet"},
+ {DDP_AEP, "AppleTalk Echo Protocol packet"},
+ {DDP_RTMPREQ, "AppleTalk Routing Table request"},
+ {DDP_ZIP, "AppleTalk Zone Information Protocol packet"},
+ {DDP_ADSP, "AppleTalk Data Stream Protocol"},
+ {DDP_EIGRP, "Cisco EIGRP for AppleTalk"},
+ {0, NULL}
+};
+
+static const value_string rtmp_function_vals[] = {
+ {1, "Request"},
+ {2, "Route Data Request (split horizon processed)"},
+ {3, "Route Data Request (no split horizon processing)"},
+ {0, NULL}
+};
+
+#define NBP_BROADCAST 1
+#define NBP_LOOKUP 2
+#define NBP_FORWARD 4
+#define NBP_REPLY 3
+
+static const value_string nbp_op_vals[] = {
+ {NBP_BROADCAST, "broadcast request"},
+ {NBP_LOOKUP, "lookup"},
+ {NBP_FORWARD, "forward request"},
+ {NBP_REPLY, "reply"},
+ {0, NULL}
+};
+
+static const value_string atp_function_vals[] = {
+ {ATP_TREQ ,"REQuest"},
+ {ATP_TRESP ,"RESPonse"},
+ {ATP_TREL ,"RELease"},
+ {0, NULL}
+};
+
+static const value_string atp_trel_timer_vals[] = {
+ {0, "30 seconds"},
+ {1, "1 minute"},
+ {2, "2 minutes"},
+ {3, "4 minutes"},
+ {4, "8 minutes"},
+ {0, NULL}
+};
+
+/*
+*/
+static const value_string asp_func_vals[] = {
+ {ASPFUNC_CLOSE, "CloseSession" },
+ {ASPFUNC_CMD, "Command" },
+ {ASPFUNC_STAT, "GetStatus" },
+ {ASPFUNC_OPEN, "OpenSession" },
+ {ASPFUNC_TICKLE, "Tickle" },
+ {ASPFUNC_WRITE, "Write" },
+ {ASPFUNC_WRTCONT, "Write Cont" },
+ {ASPFUNC_ATTN, "Attention" },
+ {0, NULL } };
+
+const value_string asp_error_vals[] = {
+ {AFP_OK , "success"},
+ {AFPERR_ACCESS , "permission denied" },
+ {AFPERR_AUTHCONT , "logincont" },
+ {AFPERR_BADUAM , "uam doesn't exist" },
+ {AFPERR_BADVERS , "bad afp version number" },
+ {AFPERR_BITMAP , "invalid bitmap" },
+ {AFPERR_CANTMOVE , "can't move file" },
+ {AFPERR_DENYCONF , "file synchronization locks conflict" },
+ {AFPERR_DIRNEMPT , "directory not empty" },
+ {AFPERR_DFULL , "disk full" },
+ {AFPERR_EOF , "end of file" },
+ {AFPERR_BUSY , "FileBusy" },
+ {AFPERR_FLATVOL , "volume doesn't support directories" },
+ {AFPERR_NOITEM , "ItemNotFound" },
+ {AFPERR_LOCK , "LockErr" },
+ {AFPERR_MISC , "misc. err" },
+ {AFPERR_NLOCK , "no more locks" },
+ {AFPERR_NOSRVR , "no response by server at that address" },
+ {AFPERR_EXIST , "object already exists" },
+ {AFPERR_NOOBJ , "object not found" },
+ {AFPERR_PARAM , "parameter error" },
+ {AFPERR_NORANGE , "no range lock" },
+ {AFPERR_RANGEOVR , "range overlap" },
+ {AFPERR_SESSCLOS , "session closed" },
+ {AFPERR_NOTAUTH , "user not authenticated" },
+ {AFPERR_NOOP , "command not supported" },
+ {AFPERR_BADTYPE , "object is the wrong type" },
+ {AFPERR_NFILE , "too many files open" },
+ {AFPERR_SHUTDOWN , "server is going down" },
+ {AFPERR_NORENAME , "can't rename" },
+ {AFPERR_NODIR , "couldn't find directory" },
+ {AFPERR_ITYPE , "wrong icon type" },
+ {AFPERR_VLOCK , "volume locked" },
+ {AFPERR_OLOCK , "object locked" },
+ {AFPERR_CTNSHRD , "share point contains a share point" },
+ {AFPERR_NOID , "file thread not found" },
+ {AFPERR_EXISTID , "file already has an id" },
+ {AFPERR_DIFFVOL , "different volume" },
+ {AFPERR_CATCHNG , "catalog has changed" },
+ {AFPERR_SAMEOBJ , "source file == destination file" },
+ {AFPERR_BADID , "non-existent file id" },
+ {AFPERR_PWDSAME , "same password/can't change password" },
+ {AFPERR_PWDSHORT , "password too short" },
+ {AFPERR_PWDEXPR , "password expired" },
+ {AFPERR_INSHRD , "folder being shared is inside a shared folder." },
+ {AFPERR_INTRASH , "shared folder in trash." },
+ {AFPERR_PWDCHNG , "password needs to be changed" },
+ {AFPERR_PWDPOLCY , "password fails policy check" },
+ {AFPERR_USRLOGIN , "user already logged on" },
+ {0, NULL } };
+
+/*
+ * XXX - do this with an FT_UINT_STRING?
+ * Unfortunately, you can't extract from an FT_UINT_STRING the string,
+ * which we'd want to do in order to put it into the "Data:" portion.
+ *
+ * Are these always in the Mac extended character set?
+ */
+static int dissect_pascal_string(tvbuff_t *tvb, int offset, proto_tree *tree,
+ int hf_index)
+{
+ int len;
+
+ len = tvb_get_guint8(tvb, offset);
+ offset++;
+
+ if ( tree )
+ {
+ char *tmp;
+ proto_tree *item;
+ proto_tree *subtree;
+
+ /*
+ * XXX - if we could do this inside the protocol tree
+ * code, we could perhaps avoid allocating and freeing
+ * this string buffer.
+ */
+ tmp = tvb_get_string(tvb, offset, len);
+ item = proto_tree_add_string(tree, hf_index, tvb, offset-1, len+1, tmp);
+
+ subtree = proto_item_add_subtree(item, ett_pstring);
+ proto_tree_add_text(subtree, tvb, offset-1, 1, "Length: %d", len);
+ proto_tree_add_text(subtree, tvb, offset, len, "Data: %s", tmp);
+
+ g_free(tmp);
+ }
+ offset += len;
+
+ return offset;
+}
+
+static void
+dissect_rtmp_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ proto_tree *rtmp_tree;
+ proto_item *ti;
+ guint8 function;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ function = tvb_get_guint8(tvb, 0);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(function, rtmp_function_vals, "Unknown function (%02x)"));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_rtmp, tvb, 0, 1, FALSE);
+ rtmp_tree = proto_item_add_subtree(ti, ett_rtmp);
+
+ proto_tree_add_uint(rtmp_tree, hf_rtmp_function, tvb, 0, 1, function);
+ }
+}
+
+static void
+dissect_rtmp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ proto_tree *rtmp_tree;
+ proto_item *ti;
+ int offset = 0;
+ guint16 net;
+ guint8 nodelen,nodelen_bits;
+ guint16 node; /* might be more than 8 bits */
+ int i;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTMP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ net = tvb_get_ntohs(tvb, offset);
+ nodelen_bits = tvb_get_guint8(tvb, offset+2);
+ if ( nodelen_bits <= 8 ) {
+ node = tvb_get_guint8(tvb, offset)+1;
+ nodelen = 1;
+ } else {
+ node = tvb_get_ntohs(tvb, offset);
+ nodelen = 2;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Net: %u Node Len: %u Node: %u",
+ net, nodelen_bits, node);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_rtmp, tvb, offset, -1, FALSE);
+ rtmp_tree = proto_item_add_subtree(ti, ett_rtmp);
+
+ proto_tree_add_uint(rtmp_tree, hf_rtmp_net, tvb, offset, 2, net);
+ proto_tree_add_uint(rtmp_tree, hf_rtmp_node_len, tvb, offset+2, 1,
+ nodelen_bits);
+ proto_tree_add_uint(rtmp_tree, hf_rtmp_node, tvb, offset+3, nodelen,
+ node);
+ offset += 3 + nodelen;
+
+ i = 1;
+ while (tvb_offset_exists(tvb, offset)) {
+ proto_tree *tuple_item, *tuple_tree;
+ guint16 tuple_net;
+ guint8 tuple_dist;
+ guint16 tuple_range_end;
+
+ tuple_net = tvb_get_ntohs(tvb, offset);
+ tuple_dist = tvb_get_guint8(tvb, offset+2);
+
+ if (tuple_dist & 0x80) {
+ tuple_range_end = tvb_get_ntohs(tvb, offset+3);
+ tuple_item = proto_tree_add_text(rtmp_tree, tvb, offset, 6,
+ "Tuple %d: Range Start: %u Dist: %u Range End: %u",
+ i, tuple_net, tuple_dist&0x7F, tuple_range_end);
+ } else {
+ tuple_item = proto_tree_add_text(rtmp_tree, tvb, offset, 3,
+ "Tuple %d: Net: %u Dist: %u",
+ i, tuple_net, tuple_dist);
+ }
+ tuple_tree = proto_item_add_subtree(tuple_item, ett_rtmp_tuple);
+
+ if (tuple_dist & 0x80) {
+ proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_range_start, tvb, offset, 2,
+ tuple_net);
+ } else {
+ proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_net, tvb, offset, 2,
+ tuple_net);
+ }
+ proto_tree_add_uint(tuple_tree, hf_rtmp_tuple_dist, tvb, offset+2, 1,
+ tuple_dist & 0x7F);
+
+ if (tuple_dist & 0x80) {
+ /*
+ * Extended network tuple.
+ */
+ proto_tree_add_item(tuple_tree, hf_rtmp_tuple_range_end, tvb, offset+3, 2,
+ FALSE);
+ offset += 6;
+ } else
+ offset += 3;
+
+ i++;
+ }
+ }
+}
+
+static void
+dissect_nbp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ proto_tree *nbp_tree;
+ proto_tree *nbp_info_tree;
+ proto_item *ti, *info_item;
+ int offset = 0;
+ guint8 info;
+ guint op, count;
+ unsigned int i;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ info = tvb_get_guint8(tvb, offset);
+ op = info >> 4;
+ count = info & 0x0F;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Op: %s Count: %u",
+ val_to_str(op, nbp_op_vals, "Unknown (0x%01x)"), count);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nbp, tvb, offset, -1, FALSE);
+ nbp_tree = proto_item_add_subtree(ti, ett_nbp);
+
+ info_item = proto_tree_add_uint_format(nbp_tree, hf_nbp_info, tvb, offset, 1,
+ info,
+ "Info: 0x%01X Operation: %s Count: %u", info,
+ val_to_str(op, nbp_op_vals, "Unknown (0x%01X)"),
+ count);
+ nbp_info_tree = proto_item_add_subtree(info_item, ett_nbp_info);
+ proto_tree_add_uint(nbp_info_tree, hf_nbp_op, tvb, offset, 1, info);
+ proto_tree_add_uint(nbp_info_tree, hf_nbp_count, tvb, offset, 1, info);
+ proto_tree_add_item(nbp_tree, hf_nbp_tid, tvb, offset+1, 1, FALSE);
+ offset += 2;
+
+ for (i=0; i<count; i++) {
+ proto_tree *node_item,*node_tree;
+ int soffset = offset;
+
+ node_item = proto_tree_add_text(nbp_tree, tvb, offset, -1,
+ "Node %u", i+1);
+ node_tree = proto_item_add_subtree(node_item, ett_nbp_node);
+
+ proto_tree_add_item(node_tree, hf_nbp_node_net, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(node_tree, hf_nbp_node_node, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(node_tree, hf_nbp_node_port, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(node_tree, hf_nbp_node_enum, tvb, offset, 1, FALSE);
+ offset++;
+
+ offset = dissect_pascal_string(tvb, offset, node_tree, hf_nbp_node_object);
+ offset = dissect_pascal_string(tvb, offset, node_tree, hf_nbp_node_type);
+ offset = dissect_pascal_string(tvb, offset, node_tree, hf_nbp_node_zone);
+
+ proto_item_set_len(node_item, offset-soffset);
+ }
+ }
+
+ return;
+}
+
+/* -----------------------------
+ ATP protocol cf. inside appletalk chap. 9
+ desegmentation from packet-ieee80211.c
+*/
+static void
+dissect_atp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ proto_tree *atp_tree = NULL;
+ proto_item *ti;
+ proto_tree *atp_info_tree;
+ proto_item *info_item;
+ int offset = 0;
+ guint8 ctrlinfo;
+ guint8 frag_number = 0;
+ guint op;
+ guint16 tid;
+ guint8 query;
+ struct aspinfo aspinfo;
+ tvbuff_t *new_tvb = NULL;
+ gboolean save_fragmented;
+ gboolean more_fragment = FALSE;
+ int len;
+ guint8 bitmap;
+ guint8 nbe = 0;
+ guint8 t = 0;
+ conversation_t *conversation;
+ asp_request_key request_key, *new_request_key;
+ asp_request_val *request_val;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATP");
+
+ ctrlinfo = tvb_get_guint8(tvb, offset);
+ bitmap = tvb_get_guint8(tvb, offset +1);
+ tid = tvb_get_ntohs(tvb, offset +2);
+
+ t = bitmap;
+ while(t) {
+ nbe++;
+ t >>= 1;
+ }
+
+ op = ctrlinfo >> 6;
+
+ aspinfo.reply = (0x80 == (ctrlinfo & ATP_FUNCMASK))?1:0;
+ aspinfo.release = (0xC0 == (ctrlinfo & ATP_FUNCMASK))?1:0;
+ aspinfo.seq = tid;
+ aspinfo.code = 0;
+ query = (!aspinfo.reply && !aspinfo.release);
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if (conversation == NULL)
+ {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+
+ request_key.conversation = conversation->index;
+ memcpy(request_key.src, (!aspinfo.reply)?pinfo->src.data:pinfo->dst.data, 4);
+ request_key.seq = aspinfo.seq;
+
+ request_val = (asp_request_val *) g_hash_table_lookup(atp_request_hash, &request_key);
+
+ if (!request_val && query ) {
+ new_request_key = g_mem_chunk_alloc(atp_request_keys);
+ *new_request_key = request_key;
+
+ request_val = g_mem_chunk_alloc(atp_request_vals);
+ request_val->value = nbe;
+
+ g_hash_table_insert(atp_request_hash, new_request_key,request_val);
+ }
+
+ /*
+ ATP_EOM is not mandatory. Some implementations don't always set it
+ if the query is only one packet.
+
+ So it needs to keep the number of packets asked in request.
+ */
+
+ if (aspinfo.reply) {
+ more_fragment = !((ATP_EOM & ctrlinfo) || (request_val && 1 == request_val->value));
+ frag_number = bitmap;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s transaction %u",
+ val_to_str(op, atp_function_vals, "Unknown (0x%01x)"),tid);
+ if (more_fragment)
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [fragment]");
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_atp, tvb, offset, -1, FALSE);
+ atp_tree = proto_item_add_subtree(ti, ett_atp);
+ proto_item_set_len(atp_tree, aspinfo.release?8:ATP_HDRSIZE -1);
+
+ info_item = proto_tree_add_item(atp_tree, hf_atp_ctrlinfo, tvb, offset, 1, FALSE);
+ atp_info_tree = proto_item_add_subtree(info_item, ett_atp_info);
+
+ proto_tree_add_item(atp_info_tree, hf_atp_function, tvb, offset, 1, FALSE);
+ proto_tree_add_item(atp_info_tree, hf_atp_xo, tvb, offset, 1, FALSE);
+ proto_tree_add_item(atp_info_tree, hf_atp_eom, tvb, offset, 1, FALSE);
+ proto_tree_add_item(atp_info_tree, hf_atp_sts, tvb, offset, 1, FALSE);
+ if ((ctrlinfo & (ATP_FUNCMASK|ATP_XO)) == (0x40|ATP_XO)) {
+ /* TReq with XO set */
+ proto_tree_add_item(atp_info_tree, hf_atp_treltimer, tvb, offset, 1, FALSE);
+ }
+ if (query) {
+ proto_tree_add_text(atp_tree, tvb, offset +1, 1,
+ "Bitmap: 0x%02x %u packet(s) max", bitmap, nbe);
+ }
+ else {
+ proto_tree_add_item(atp_tree, hf_atp_bitmap, tvb, offset +1, 1, FALSE);
+ }
+ proto_tree_add_item(atp_tree, hf_atp_tid, tvb, offset +2, 2, FALSE);
+
+ if (aspinfo.release)
+ proto_tree_add_item(atp_tree, hf_atp_user_bytes, tvb, offset +4, 4, FALSE);
+
+ }
+
+ if (aspinfo.release)
+ return;
+
+ save_fragmented = pinfo->fragmented;
+
+ /* FIXME
+ asp doesn't fit very well here
+ move asp back in atp?
+ */
+ if (atp_defragment && aspinfo.reply && (more_fragment || frag_number != 0)) {
+ fragment_data *fd_head;
+ int hdr;
+
+ hdr = ATP_HDRSIZE -1;
+ if (frag_number != 0)
+ hdr += 4; /* asp header */
+ len = tvb_reported_length_remaining(tvb, hdr);
+ fd_head = fragment_add_seq_check(tvb, hdr, pinfo, tid,
+ atp_fragment_table,
+ atp_reassembled_table,
+ frag_number,
+ len,
+ more_fragment);
+ new_tvb = process_reassembled_data(tvb, ATP_HDRSIZE -1, pinfo,
+ "Reassembled ATP", fd_head, &atp_frag_items,
+ NULL, atp_tree);
+ }
+ else {
+ /* full packet */
+ new_tvb = tvb_new_subset(tvb, ATP_HDRSIZE -1, -1,- 1);
+ }
+
+ if (new_tvb) {
+ pinfo->private_data = &aspinfo;
+ /* if port == 6 it's not an ASP packet but a ZIP packet */
+ if (pinfo->srcport == 6 || pinfo->destport == 6 )
+ call_dissector(zip_atp_handle, new_tvb, pinfo, tree);
+ else
+ call_dissector(asp_handle, new_tvb, pinfo, tree);
+ }
+ else {
+ /* Just show this as a fragment. */
+ new_tvb = tvb_new_subset (tvb, ATP_HDRSIZE -1, -1, -1);
+ call_dissector(data_handle, new_tvb, pinfo, tree);
+ }
+ pinfo->fragmented = save_fragmented;
+ return;
+}
+
+/*
+ copy and paste from dsi
+ XXX - is the format of this reply dependent on the type of server,
+ with this format being the format for AFP servers?
+*/
+static gint
+dissect_asp_reply_get_status(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint offset)
+{
+ proto_tree *sub_tree;
+ proto_item *ti;
+
+ guint16 ofs;
+ guint16 flag;
+ guint16 machine_ofs;
+ guint16 sign_ofs = 0;
+ guint16 adr_ofs = 0;
+ guint16 dir_ofs = 0;
+ guint16 utf_ofs = 0;
+ guint8 nbe;
+ guint8 len;
+ guint8 i;
+
+ if (!tree)
+ return offset;
+
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "Get Status");
+ tree = proto_item_add_subtree(ti, ett_asp_status);
+
+ machine_ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
+ proto_tree_add_text(tree, tvb, offset +AFPSTATUS_MACHOFF, 2, "Machine offset: %u", machine_ofs);
+ if (machine_ofs)
+ machine_ofs += offset;
+
+ ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
+ proto_tree_add_text(tree, tvb, offset +AFPSTATUS_VERSOFF, 2, "Version offset: %u", ofs);
+
+ ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
+ proto_tree_add_text(tree, tvb, offset +AFPSTATUS_UAMSOFF, 2, "UAMS offset: %u", ofs);
+
+ ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
+ proto_tree_add_text(tree, tvb, offset +AFPSTATUS_ICONOFF, 2, "Icon offset: %u", ofs);
+
+ ofs = offset +AFPSTATUS_FLAGOFF;
+ ti = proto_tree_add_item(tree, hf_asp_server_flag, tvb, ofs, 2, FALSE);
+ sub_tree = proto_item_add_subtree(ti, ett_asp_status_server_flag);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_copyfile , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_passwd , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_no_save_passwd, tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_srv_msg , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_srv_sig , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_tcpip , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_notify , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_reconnect , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_directory , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_utf8_name , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_asp_server_flag_fast_copy , tvb, ofs, 2, FALSE);
+
+ proto_tree_add_item(tree, hf_asp_server_name, tvb, offset +AFPSTATUS_PRELEN, 1, FALSE);
+
+ flag = tvb_get_ntohs(tvb, ofs);
+ if ((flag & AFPSRVRINFO_SRVSIGNATURE)) {
+ ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN) +1;
+ if ((ofs & 1))
+ ofs++;
+
+ sign_ofs = tvb_get_ntohs(tvb, ofs);
+ proto_tree_add_text(tree, tvb, ofs, 2, "Signature offset: %u", sign_ofs);
+ sign_ofs += offset;
+ ofs += 2;
+
+ if ((flag & AFPSRVRINFO_TCPIP) && ofs < machine_ofs ) {
+ adr_ofs = tvb_get_ntohs(tvb, ofs);
+ proto_tree_add_text(tree, tvb, ofs, 2, "Network address offset: %u", adr_ofs);
+ adr_ofs += offset;
+ ofs += 2;
+ }
+
+ if ((flag & AFPSRVRINFO_SRVDIRECTORY) && ofs < machine_ofs) {
+ dir_ofs = tvb_get_ntohs(tvb, ofs);
+ proto_tree_add_text(tree, tvb, ofs, 2, "Directory services offset: %u", dir_ofs);
+ dir_ofs += offset;
+ ofs += 2;
+ }
+
+ if ((flag & AFPSRVRINFO_SRVUTF8) && ofs < machine_ofs) {
+ utf_ofs = tvb_get_ntohs(tvb, ofs);
+ proto_tree_add_text(tree, tvb, ofs, 2, "UTF-8 Server name offset: %u", utf_ofs);
+ utf_ofs += offset;
+ }
+ }
+
+ if (machine_ofs)
+ proto_tree_add_item(tree, hf_asp_server_type, tvb, machine_ofs, 1, FALSE);
+
+ ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
+ if (ofs) {
+ nbe = tvb_get_guint8(tvb, ofs);
+ ti = proto_tree_add_text(tree, tvb, ofs, 1, "Version list: %u", nbe);
+ ofs++;
+ sub_tree = proto_item_add_subtree(ti, ett_asp_vers);
+ for (i = 0; i < nbe; i++) {
+ len = tvb_get_guint8(tvb, ofs);
+ proto_tree_add_item(sub_tree, hf_asp_server_vers, tvb, ofs, 1, FALSE);
+ ofs += len + 1;
+ }
+ }
+
+ ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
+ if (ofs) {
+ nbe = tvb_get_guint8(tvb, ofs);
+ ti = proto_tree_add_text(tree, tvb, ofs, 1, "UAMS list: %u", nbe);
+ ofs++;
+ sub_tree = proto_item_add_subtree(ti, ett_asp_uams);
+ for (i = 0; i < nbe; i++) {
+ len = tvb_get_guint8(tvb, ofs);
+ proto_tree_add_item(sub_tree, hf_asp_server_uams, tvb, ofs, 1, FALSE);
+ ofs += len + 1;
+ }
+ }
+
+ ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
+ if (ofs)
+ proto_tree_add_item(tree, hf_asp_server_icon, tvb, ofs, 256, FALSE);
+
+ if (sign_ofs) {
+ proto_tree_add_item(tree, hf_asp_server_signature, tvb, sign_ofs, 16, FALSE);
+ }
+
+ if (adr_ofs) {
+ proto_tree *adr_tree;
+ char *tmp;
+ const guint8 *ip;
+ guint16 net;
+ guint8 node;
+ guint16 port;
+
+ ofs = adr_ofs;
+ nbe = tvb_get_guint8(tvb, ofs);
+ ti = proto_tree_add_text(tree, tvb, ofs, 1, "Address list: %u", nbe);
+ ofs++;
+ adr_tree = proto_item_add_subtree(ti, ett_asp_addr);
+ for (i = 0; i < nbe; i++) {
+ guint8 type;
+
+ len = tvb_get_guint8(tvb, ofs);
+ type = tvb_get_guint8(tvb, ofs +1);
+ switch (type) {
+ case 1: /* IP */
+ ip = tvb_get_ptr(tvb, ofs+2, 4);
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip %s", ip_to_str(ip));
+ break;
+ case 2: /* IP + port */
+ ip = tvb_get_ptr(tvb, ofs+2, 4);
+ port = tvb_get_ntohs(tvb, ofs+6);
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip %s:%u",ip_to_str(ip),port);
+ break;
+ case 3: /* DDP, atalk_addr_to_str want host order not network */
+ net = tvb_get_ntohs(tvb, ofs+2);
+ node = tvb_get_guint8(tvb, ofs +4);
+ port = tvb_get_guint8(tvb, ofs +5);
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ddp %u.%u:%u",
+ net, node, port);
+ break;
+ case 5: /* IP + port ssh tunnel */
+ ip = tvb_get_ptr(tvb, ofs+2, 4);
+ port = tvb_get_ntohs(tvb, ofs+6);
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip (ssh tunnel) %s:%u",ip_to_str(ip),port);
+ break;
+ case 4: /* DNS */
+ if (len > 2) {
+ tmp = tvb_get_string(tvb, ofs +2, len -2);
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "dns %s", tmp);
+ g_free(tmp);
+ break;
+ }
+ /* else fall to default malformed record */
+ default:
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Unknow type : %u", type);
+ break;
+ }
+ len -= 2;
+ sub_tree = proto_item_add_subtree(ti,ett_asp_addr_line);
+ proto_tree_add_item(sub_tree, hf_asp_server_addr_len, tvb, ofs, 1, FALSE);
+ ofs++;
+ proto_tree_add_item(sub_tree, hf_asp_server_addr_type, tvb, ofs, 1, FALSE);
+ ofs++;
+ proto_tree_add_item(sub_tree, hf_asp_server_addr_value,tvb, ofs, len, FALSE);
+ ofs += len;
+ }
+ }
+
+ if (dir_ofs) {
+ ofs = dir_ofs;
+ nbe = tvb_get_guint8(tvb, ofs);
+ ti = proto_tree_add_text(tree, tvb, ofs, 1, "Directory services list: %u", nbe);
+ ofs++;
+ sub_tree = proto_item_add_subtree(ti, ett_asp_directory);
+ for (i = 0; i < nbe; i++) {
+ len = tvb_get_guint8(tvb, ofs);
+ proto_tree_add_item(sub_tree, hf_asp_server_directory, tvb, ofs, 1, FALSE);
+ ofs += len + 1;
+ }
+ }
+ if (utf_ofs) {
+ guint16 ulen;
+ char *tmp;
+
+ ofs = utf_ofs;
+ ulen = tvb_get_ntohs(tvb, ofs);
+ tmp = tvb_get_string(tvb, ofs + 2, ulen);
+ ti = proto_tree_add_text(tree, tvb, ofs, ulen +2, "UTF8 server name: %s", tmp);
+ sub_tree = proto_item_add_subtree(ti, ett_asp_utf8_name);
+ proto_tree_add_uint(sub_tree, hf_asp_server_utf8_name_len, tvb, ofs, 2, ulen);
+ ofs += 2;
+ proto_tree_add_string(sub_tree, hf_asp_server_utf8_name, tvb, ofs, ulen, tmp);
+ ofs += ulen;
+ g_free(tmp);
+ }
+ /* FIXME: offset is not updated */
+ return offset;
+}
+
+/* -----------------------------
+ ASP protocol cf. inside appletalk chap. 11
+*/
+static struct aspinfo *
+get_transaction(tvbuff_t *tvb, packet_info *pinfo)
+{
+ struct aspinfo *aspinfo = pinfo->private_data;
+ conversation_t *conversation;
+ asp_request_key request_key, *new_request_key;
+ asp_request_val *request_val;
+ guint8 fn;
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if (conversation == NULL)
+ {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+
+ request_key.conversation = conversation->index;
+ memcpy(request_key.src, (!aspinfo->reply)?pinfo->src.data:pinfo->dst.data, 4);
+ request_key.seq = aspinfo->seq;
+
+ request_val = (asp_request_val *) g_hash_table_lookup(
+ asp_request_hash, &request_key);
+ if (!request_val && !aspinfo->reply ) {
+ fn = tvb_get_guint8(tvb, 0);
+ new_request_key = g_mem_chunk_alloc(asp_request_keys);
+ *new_request_key = request_key;
+
+ request_val = g_mem_chunk_alloc(asp_request_vals);
+ request_val->value = fn;
+
+ g_hash_table_insert(asp_request_hash, new_request_key,
+ request_val);
+ }
+
+ if (!request_val)
+ return NULL;
+
+ aspinfo->command = request_val->value;
+ return aspinfo;
+}
+
+
+static void
+dissect_asp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct aspinfo *aspinfo;
+ int offset = 0;
+ proto_tree *asp_tree = NULL;
+ proto_item *ti;
+ guint8 fn;
+ int len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ASP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ aspinfo = get_transaction(tvb, pinfo);
+ if (!aspinfo)
+ return;
+
+ fn = (guint8) aspinfo->command;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (aspinfo->reply)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Reply tid %u",aspinfo->seq);
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Function: %s tid %u",
+ val_to_str(fn, asp_func_vals, "Unknown (0x%01x)"), aspinfo->seq);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_asp, tvb, offset, -1, FALSE);
+ asp_tree = proto_item_add_subtree(ti, ett_asp);
+ }
+ if (!aspinfo->reply) {
+ tvbuff_t *new_tvb;
+ /* let the called deal with asp_tree == NULL */
+
+ proto_tree_add_item(asp_tree, hf_asp_func, tvb, offset, 1, FALSE);
+ offset++;
+ switch(fn) {
+ case ASPFUNC_OPEN:
+ proto_tree_add_item(asp_tree, hf_asp_socket, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_version, tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+ case ASPFUNC_TICKLE:
+ case ASPFUNC_CLOSE:
+ proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, FALSE);
+ offset +=2;
+ break;
+ case ASPFUNC_STAT:
+ proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+ case ASPFUNC_ATTN:
+ proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_attn_code, tvb, offset, 2, FALSE);
+ offset +=2;
+ break;
+ case ASPFUNC_CMD:
+ case ASPFUNC_WRITE:
+ proto_item_set_len(asp_tree, 4);
+ proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_seq, tvb, offset, 2, FALSE);
+ offset += 2;
+ len = tvb_reported_length_remaining(tvb,offset);
+ new_tvb = tvb_new_subset(tvb, offset,-1,len);
+ call_dissector(afp_handle, new_tvb, pinfo, tree);
+ break;
+ case ASPFUNC_WRTCONT:
+ proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_seq, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(asp_tree, hf_asp_size, tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+ default:
+ proto_item_set_len(asp_tree, 4);
+ offset += 3;
+ len = tvb_reported_length_remaining(tvb,offset);
+ call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,len), pinfo, tree);
+ break;
+ }
+ }
+ else {
+ tvbuff_t *new_tvb;
+
+ proto_tree_add_uint(asp_tree, hf_asp_func, tvb, 0, 0, fn);
+ switch(fn) {
+ case ASPFUNC_OPEN:
+ proto_tree_add_item(asp_tree, hf_asp_socket, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_session_id, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_init_error, tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+ case ASPFUNC_CLOSE:
+ proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+ case ASPFUNC_STAT:
+ proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 4, FALSE);
+ offset += 4;
+ dissect_asp_reply_get_status(tvb, pinfo, asp_tree, offset);
+ break;
+ case ASPFUNC_CMD:
+ case ASPFUNC_WRITE:
+ proto_item_set_len(asp_tree, 4);
+ aspinfo->code = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(asp_tree, hf_asp_error, tvb, offset, 4, FALSE);
+ offset += 4;
+ len = tvb_reported_length_remaining(tvb,offset);
+ new_tvb = tvb_new_subset(tvb, offset,-1,len);
+ call_dissector(afp_handle, new_tvb, pinfo, tree);
+ break;
+ case ASPFUNC_TICKLE:
+ case ASPFUNC_WRTCONT:
+ proto_tree_add_item(asp_tree, hf_asp_zero_value, tvb, offset, 4, FALSE);
+ /* fall */
+ case ASPFUNC_ATTN: /* FIXME capture and spec disagree */
+ default:
+ proto_item_set_len(asp_tree, 4);
+ offset += 4;
+ len = tvb_reported_length_remaining(tvb,offset);
+ call_dissector(data_handle,tvb_new_subset(tvb, offset,-1,len), pinfo, tree);
+ break;
+ }
+ }
+}
+
+/* -----------------------------
+ ZIP protocol cf. inside appletalk chap. 8
+*/
+static void
+dissect_atp_zip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct aspinfo *aspinfo;
+ int offset = 0;
+ proto_tree *zip_tree;
+ proto_tree *sub_tree;
+ proto_item *ti;
+ guint8 fn;
+ guint16 count;
+ guint8 len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZIP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ aspinfo = get_transaction(tvb, pinfo);
+ if (!aspinfo)
+ return;
+
+ fn = (guint8) aspinfo->command;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (aspinfo->reply)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Reply tid %u",aspinfo->seq);
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Function: %s tid %u",
+ val_to_str(fn, zip_atp_function_vals, "Unknown (0x%01x)"), aspinfo->seq);
+ }
+
+ if (!tree)
+ return;
+
+ ti = proto_tree_add_item(tree, proto_zip, tvb, offset, -1, FALSE);
+ zip_tree = proto_item_add_subtree(ti, ett_zip);
+
+ if (!aspinfo->reply) {
+ proto_tree_add_item(zip_tree, hf_zip_atp_function, tvb, offset, 1, FALSE);
+ offset++;
+ switch(fn) {
+ case 7: /* start_index = 0 */
+ case 8:
+ case 9:
+ proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(zip_tree, hf_zip_start_index, tvb, offset, 2, FALSE);
+ break;
+ }
+ }
+ else {
+ guint8 i;
+
+ proto_tree_add_uint(zip_tree, hf_zip_atp_function, tvb, 0, 0, fn);
+ switch(fn) {
+ case 7:
+ case 8:
+ case 9:
+ proto_tree_add_item(zip_tree, hf_zip_last_flag, tvb, offset, 1, FALSE);
+ offset++;
+
+ proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 1, FALSE);
+ offset++;
+ count = tvb_get_ntohs(tvb, offset);
+ ti = proto_tree_add_item(zip_tree, hf_zip_count, tvb, offset, 2, FALSE);
+ offset += 2;
+ sub_tree = proto_item_add_subtree(ti, ett_zip_zones_list);
+ for (i= 1; i <= count; i++) {
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(sub_tree, hf_zip_zone_name, tvb, offset, 1,FALSE);
+ offset += len +1;
+ }
+ break;
+ }
+ }
+}
+
+static void
+dissect_ddp_zip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *zip_tree = NULL;
+ proto_item *ti;
+ guint8 fn;
+ guint8 len;
+ gint offset = 0;
+ proto_tree *flag_tree;
+ proto_tree *sub_tree;
+ proto_tree *net_tree;
+ guint8 flag;
+ guint16 net;
+ guint8 i;
+ guint8 count;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZIP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ fn = tvb_get_guint8(tvb, 0);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(fn, zip_function_vals, "Unknown ZIP function (%02x)"));
+ }
+
+ if (!tree)
+ return;
+
+ ti = proto_tree_add_item(tree, proto_zip, tvb, 0, -1, FALSE);
+ zip_tree = proto_item_add_subtree(ti, ett_zip);
+
+ proto_tree_add_item(zip_tree, hf_zip_function, tvb, offset, 1,FALSE);
+ offset++;
+ /* fn 1,7,2,8 are not tested */
+ switch (fn) {
+ case 1: /* Query */
+ count = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_item(zip_tree, hf_zip_network_count, tvb, offset, 1, FALSE);
+ offset++;
+ sub_tree = proto_item_add_subtree(ti, ett_zip_network_list);
+ for (i= 1; i <= count; i++) {
+ proto_tree_add_item(sub_tree, hf_zip_network, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ break;
+ case 7: /* Notify */
+ flag = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(zip_tree, tvb, offset , 1,"Flags : 0x%02x", flag);
+ flag_tree = proto_item_add_subtree(ti, ett_zip_flags);
+ proto_tree_add_item(flag_tree, hf_zip_flags_zone_invalid, tvb, offset, 1,FALSE);
+ proto_tree_add_item(flag_tree, hf_zip_flags_use_broadcast,tvb, offset, 1,FALSE);
+ proto_tree_add_item(flag_tree, hf_zip_flags_only_one_zone,tvb, offset, 1,FALSE);
+ offset++;
+
+ proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(zip_tree, hf_zip_zone_name, tvb, offset, 1,FALSE);
+ offset += len +1;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(zip_tree, hf_zip_multicast_length,tvb, offset, 1,FALSE);
+ offset++;
+ proto_tree_add_item(zip_tree, hf_zip_multicast_address,tvb, offset, len,FALSE);
+ offset += len;
+
+ proto_tree_add_item(zip_tree, hf_zip_zone_name, tvb, offset, 1,FALSE);
+ break;
+
+ case 2: /* Reply */
+ case 8: /* Extended Reply */
+ count = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_item(zip_tree, hf_zip_network_count, tvb, offset, 1, FALSE);
+ offset++;
+ sub_tree = proto_item_add_subtree(ti, ett_zip_network_list);
+ for (i= 1; i <= count; i++) {
+ net = tvb_get_ntohs(tvb, offset);
+ ti = proto_tree_add_text(zip_tree, tvb, offset , 2, "Zone for network : %u", net);
+ net_tree = proto_item_add_subtree(ti, ett_zip_network_list);
+ proto_tree_add_item(net_tree, hf_zip_network, tvb, offset, 2, FALSE);
+ offset += 2;
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(net_tree, hf_zip_zone_name, tvb, offset, 1,FALSE);
+ offset += len +1;
+ }
+ break;
+
+ case 5 : /* GetNetInfo request */
+ proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(zip_tree, hf_zip_zero_value, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(zip_tree, hf_zip_zone_name, tvb, offset, 1,FALSE);
+ break;
+
+ case 6 : /* GetNetInfo reply */
+ flag = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(zip_tree, tvb, offset , 1,"Flags : 0x%02x", flag);
+ flag_tree = proto_item_add_subtree(ti, ett_zip_flags);
+ proto_tree_add_item(flag_tree, hf_zip_flags_zone_invalid, tvb, offset, 1,FALSE);
+ proto_tree_add_item(flag_tree, hf_zip_flags_use_broadcast,tvb, offset, 1,FALSE);
+ proto_tree_add_item(flag_tree, hf_zip_flags_only_one_zone,tvb, offset, 1,FALSE);
+ offset++;
+
+ proto_tree_add_item(zip_tree, hf_zip_network_start, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(zip_tree, hf_zip_network_end, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(zip_tree, hf_zip_zone_name, tvb, offset, 1,FALSE);
+ offset += len +1;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(zip_tree, hf_zip_multicast_length,tvb, offset, 1,FALSE);
+ offset++;
+ proto_tree_add_item(zip_tree, hf_zip_multicast_address,tvb, offset, len,FALSE);
+ offset += len;
+ if ((flag & 0x80) != 0)
+ proto_tree_add_item(zip_tree, hf_zip_default_zone, tvb, offset, 1,FALSE);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+dissect_ddp_short(tvbuff_t *tvb, packet_info *pinfo, guint8 dnode,
+ guint8 snode, proto_tree *tree)
+{
+ guint16 len;
+ guint8 dport;
+ guint8 sport;
+ guint8 type;
+ proto_tree *ddp_tree = NULL;
+ proto_item *ti;
+ static struct atalk_ddp_addr src, dst;
+ tvbuff_t *new_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DDP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ddp, tvb, 0, DDP_SHORT_HEADER_SIZE,
+ FALSE);
+ ddp_tree = proto_item_add_subtree(ti, ett_ddp);
+ }
+ len = tvb_get_ntohs(tvb, 0);
+ if (tree)
+ proto_tree_add_uint(ddp_tree, hf_ddp_len, tvb, 0, 2, len);
+ dport = tvb_get_guint8(tvb, 2);
+ if (tree)
+ proto_tree_add_uint(ddp_tree, hf_ddp_dst_socket, tvb, 2, 1, dport);
+ sport = tvb_get_guint8(tvb, 3);
+ if (tree)
+ proto_tree_add_uint(ddp_tree, hf_ddp_src_socket, tvb, 3, 1, sport);
+ type = tvb_get_guint8(tvb, 4);
+
+ src.net = 0;
+ src.node = snode;
+ dst.net = 0;
+ dst.node = dnode;
+ SET_ADDRESS(&pinfo->net_src, AT_ATALK, sizeof src, (guint8 *)&src);
+ SET_ADDRESS(&pinfo->src, AT_ATALK, sizeof src, (guint8 *)&src);
+ SET_ADDRESS(&pinfo->net_dst, AT_ATALK, sizeof dst, (guint8 *)&dst);
+ SET_ADDRESS(&pinfo->dst, AT_ATALK, sizeof dst, (guint8 *)&dst);
+
+ pinfo->ptype = PT_DDP;
+ pinfo->destport = dport;
+ pinfo->srcport = sport;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(type, op_vals, "Unknown DDP protocol (%02x)"));
+ }
+ if (tree) {
+ proto_tree_add_string_hidden(ddp_tree, hf_ddp_src, tvb,
+ 4, 3, atalk_addr_to_str(&src));
+ proto_tree_add_string_hidden(ddp_tree, hf_ddp_dst, tvb,
+ 6, 3, atalk_addr_to_str(&dst));
+
+ proto_tree_add_uint(ddp_tree, hf_ddp_type, tvb, 4, 1, type);
+ }
+ new_tvb = tvb_new_subset(tvb, DDP_SHORT_HEADER_SIZE, -1, -1);
+
+ if (!dissector_try_port(ddp_dissector_table, type, new_tvb, pinfo, tree))
+ call_dissector(data_handle,new_tvb, pinfo, tree);
+}
+
+static void
+dissect_ddp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ e_ddp ddp;
+ proto_tree *ddp_tree;
+ proto_item *ti;
+ static struct atalk_ddp_addr src, dst;
+ tvbuff_t *new_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DDP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb, (guint8 *)&ddp, 0, sizeof(e_ddp));
+ ddp.dnet=g_ntohs(ddp.dnet);
+ ddp.snet=g_ntohs(ddp.snet);
+ ddp.sum=g_ntohs(ddp.sum);
+ ddp.hops_len=g_ntohs(ddp.hops_len);
+
+ src.net = ddp.snet;
+ src.node = ddp.snode;
+ dst.net = ddp.dnet;
+ dst.node = ddp.dnode;
+ SET_ADDRESS(&pinfo->net_src, AT_ATALK, sizeof src, (guint8 *)&src);
+ SET_ADDRESS(&pinfo->src, AT_ATALK, sizeof src, (guint8 *)&src);
+ SET_ADDRESS(&pinfo->net_dst, AT_ATALK, sizeof dst, (guint8 *)&dst);
+ SET_ADDRESS(&pinfo->dst, AT_ATALK, sizeof dst, (guint8 *)&dst);
+
+ pinfo->ptype = PT_DDP;
+ pinfo->destport = ddp.dport;
+ pinfo->srcport = ddp.sport;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(ddp.type, op_vals, "Unknown DDP protocol (%02x)"));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ddp, tvb, 0, DDP_HEADER_SIZE,
+ FALSE);
+ ddp_tree = proto_item_add_subtree(ti, ett_ddp);
+
+ proto_tree_add_string_hidden(ddp_tree, hf_ddp_src, tvb,
+ 4, 3, atalk_addr_to_str(&src));
+ proto_tree_add_string_hidden(ddp_tree, hf_ddp_dst, tvb,
+ 6, 3, atalk_addr_to_str(&dst));
+
+ proto_tree_add_uint(ddp_tree, hf_ddp_hopcount, tvb, 0, 1,
+ ddp_hops(ddp.hops_len));
+ proto_tree_add_uint(ddp_tree, hf_ddp_len, tvb, 0, 2,
+ ddp_len(ddp.hops_len));
+ proto_tree_add_uint(ddp_tree, hf_ddp_checksum, tvb, 2, 2,
+ ddp.sum);
+ proto_tree_add_uint(ddp_tree, hf_ddp_dst_net, tvb, 4, 2,
+ ddp.dnet);
+ proto_tree_add_uint(ddp_tree, hf_ddp_src_net, tvb, 6, 2,
+ ddp.snet);
+ proto_tree_add_uint(ddp_tree, hf_ddp_dst_node, tvb, 8, 1,
+ ddp.dnode);
+ proto_tree_add_uint(ddp_tree, hf_ddp_src_node, tvb, 9, 1,
+ ddp.snode);
+ proto_tree_add_uint(ddp_tree, hf_ddp_dst_socket, tvb, 10, 1,
+ ddp.dport);
+ proto_tree_add_uint(ddp_tree, hf_ddp_src_socket, tvb, 11, 1,
+ ddp.sport);
+ proto_tree_add_uint(ddp_tree, hf_ddp_type, tvb, 12, 1,
+ ddp.type);
+ }
+
+ new_tvb = tvb_new_subset(tvb, DDP_HEADER_SIZE, -1, -1);
+
+ if (!dissector_try_port(ddp_dissector_table, ddp.type, new_tvb, pinfo, tree))
+ call_dissector(data_handle,new_tvb, pinfo, tree);
+}
+
+static const value_string llap_type_vals[] = {
+ {0x01, "Short DDP"},
+ {0x02, "DDP" },
+ {0x81, "Enquiry"},
+ {0x82, "Acknowledgement"},
+ {0x84, "RTS"},
+ {0x85, "CTS"},
+ {0, NULL}
+};
+
+void
+capture_llap(packet_counts *ld)
+{
+ ld->other++;
+}
+
+static void
+dissect_llap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 dnode;
+ guint8 snode;
+ guint8 type;
+ proto_tree *llap_tree = NULL;
+ proto_item *ti;
+ tvbuff_t *new_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLAP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_llap, tvb, 0, 3, FALSE);
+ llap_tree = proto_item_add_subtree(ti, ett_llap);
+ }
+
+ dnode = tvb_get_guint8(tvb, 0);
+ if (tree)
+ proto_tree_add_uint(llap_tree, hf_llap_dst, tvb, 0, 1, dnode);
+ snode = tvb_get_guint8(tvb, 1);
+ if (tree)
+ proto_tree_add_uint(llap_tree, hf_llap_src, tvb, 1, 1, snode);
+ type = tvb_get_guint8(tvb, 2);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(type, llap_type_vals, "Unknown LLAP type (%02x)"));
+ }
+ if (tree)
+ proto_tree_add_uint(llap_tree, hf_llap_type, tvb, 2, 1, type);
+
+ new_tvb = tvb_new_subset(tvb, 3, -1, -1);
+
+ switch (type) {
+
+ case 0x01:
+ if (proto_is_protocol_enabled(find_protocol_by_id(proto_ddp))) {
+ pinfo->current_proto = "DDP";
+ dissect_ddp_short(new_tvb, pinfo, dnode, snode, tree);
+ return;
+ }
+
+ case 0x02:
+ if (call_dissector(ddp_handle, new_tvb, pinfo, tree))
+ return;
+ }
+ call_dissector(data_handle,new_tvb, pinfo, tree);
+}
+
+static void
+atp_init(void)
+{
+ /* fragment */
+ fragment_table_init(&atp_fragment_table);
+ reassembled_table_init(&atp_reassembled_table);
+ /* bitmap */
+ if (atp_request_hash)
+ g_hash_table_destroy(atp_request_hash);
+ if (atp_request_keys)
+ g_mem_chunk_destroy(atp_request_keys);
+ if (atp_request_vals)
+ g_mem_chunk_destroy(atp_request_vals);
+
+ atp_request_hash = g_hash_table_new(asp_hash, asp_equal);
+
+ atp_request_keys = g_mem_chunk_new("atp_request_keys",
+ sizeof(asp_request_key),
+ asp_packet_init_count * sizeof(asp_request_key),
+ G_ALLOC_AND_FREE);
+ atp_request_vals = g_mem_chunk_new("atp_request_vals",
+ sizeof(asp_request_val),
+ asp_packet_init_count * sizeof(asp_request_val),
+ G_ALLOC_AND_FREE);
+}
+
+static void
+asp_reinit( void)
+{
+
+ if (asp_request_hash)
+ g_hash_table_destroy(asp_request_hash);
+ if (asp_request_keys)
+ g_mem_chunk_destroy(asp_request_keys);
+ if (asp_request_vals)
+ g_mem_chunk_destroy(asp_request_vals);
+
+ asp_request_hash = g_hash_table_new(asp_hash, asp_equal);
+
+ asp_request_keys = g_mem_chunk_new("asp_request_keys",
+ sizeof(asp_request_key),
+ asp_packet_init_count * sizeof(asp_request_key),
+ G_ALLOC_AND_FREE);
+ asp_request_vals = g_mem_chunk_new("asp_request_vals",
+ sizeof(asp_request_val),
+ asp_packet_init_count * sizeof(asp_request_val),
+ G_ALLOC_AND_FREE);
+
+}
+
+void
+proto_register_atalk(void)
+{
+ static hf_register_info hf_llap[] = {
+ { &hf_llap_dst,
+ { "Destination Node", "llap.dst", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_llap_src,
+ { "Source Node", "llap.src", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_llap_type,
+ { "Type", "llap.type", FT_UINT8, BASE_HEX, VALS(llap_type_vals), 0x0,
+ "", HFILL }},
+ };
+
+ static hf_register_info hf_ddp[] = {
+ { &hf_ddp_hopcount,
+ { "Hop count", "ddp.hopcount", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_len,
+ { "Datagram length", "ddp.len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_checksum,
+ { "Checksum", "ddp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_dst,
+ { "Destination address", "ddp.dst", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_dst_net,
+ { "Destination Net", "ddp.dst.net", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_src,
+ { "Source address", "ddp.src", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_src_net,
+ { "Source Net", "ddp.src.net", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_dst_node,
+ { "Destination Node", "ddp.dst.node", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_src_node,
+ { "Source Node", "ddp.src.node", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_dst_socket,
+ { "Destination Socket", "ddp.dst_socket", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_src_socket,
+ { "Source Socket", "ddp.src_socket", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ddp_type,
+ { "Protocol type", "ddp.type", FT_UINT8, BASE_DEC, VALS(op_vals), 0x0,
+ "", HFILL }},
+ };
+
+ static hf_register_info hf_nbp[] = {
+ { &hf_nbp_op,
+ { "Operation", "nbp.op", FT_UINT8, BASE_DEC,
+ VALS(nbp_op_vals), 0xF0, "Operation", HFILL }},
+ { &hf_nbp_info,
+ { "Info", "nbp.info", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Info", HFILL }},
+ { &hf_nbp_count,
+ { "Count", "nbp.count", FT_UINT8, BASE_DEC,
+ NULL, 0x0F, "Count", HFILL }},
+ { &hf_nbp_node_net,
+ { "Network", "nbp.net", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Network", HFILL }},
+ { &hf_nbp_node_node,
+ { "Node", "nbp.node", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Node", HFILL }},
+ { &hf_nbp_node_port,
+ { "Port", "nbp.port", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Port", HFILL }},
+ { &hf_nbp_node_enum,
+ { "Enumerator", "nbp.enum", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Enumerator", HFILL }},
+ { &hf_nbp_node_object,
+ { "Object", "nbp.object", FT_STRING, BASE_DEC,
+ NULL, 0x0, "Object", HFILL }},
+ { &hf_nbp_node_type,
+ { "Type", "nbp.type", FT_STRING, BASE_DEC,
+ NULL, 0x0, "Type", HFILL }},
+ { &hf_nbp_node_zone,
+ { "Zone", "nbp.zone", FT_STRING, BASE_DEC,
+ NULL, 0x0, "Zone", HFILL }},
+ { &hf_nbp_tid,
+ { "Transaction ID", "nbp.tid", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Transaction ID", HFILL }}
+ };
+
+ static hf_register_info hf_rtmp[] = {
+ { &hf_rtmp_net,
+ { "Net", "rtmp.net", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Net", HFILL }},
+ { &hf_rtmp_node,
+ { "Node", "nbp.nodeid", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Node", HFILL }},
+ { &hf_rtmp_node_len,
+ { "Node Length", "nbp.nodeid.length", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Node Length", HFILL }},
+ { &hf_rtmp_tuple_net,
+ { "Net", "rtmp.tuple.net", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Net", HFILL }},
+ { &hf_rtmp_tuple_range_start,
+ { "Range Start", "rtmp.tuple.range_start", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Range Start", HFILL }},
+ { &hf_rtmp_tuple_range_end,
+ { "Range End", "rtmp.tuple.range_end", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Range End", HFILL }},
+ { &hf_rtmp_tuple_dist,
+ { "Distance", "rtmp.tuple.dist", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Distance", HFILL }},
+ { &hf_rtmp_function,
+ { "Function", "rtmp.function", FT_UINT8, BASE_DEC,
+ VALS(rtmp_function_vals), 0x0, "Request Function", HFILL }}
+ };
+
+ static hf_register_info hf_atp[] = {
+ { &hf_atp_ctrlinfo,
+ { "Control info", "atp.ctrlinfo", FT_UINT8, BASE_HEX,
+ NULL, 0, "control info", HFILL }},
+
+ { &hf_atp_function,
+ { "Function", "atp.function", FT_UINT8, BASE_DEC,
+ VALS(atp_function_vals), ATP_FUNCMASK, "function code", HFILL }},
+
+
+ { &hf_atp_xo,
+ { "XO", "atp.xo", FT_BOOLEAN, 8,
+ NULL, ATP_XO, "Exactly-once flag", HFILL }},
+
+ { &hf_atp_eom,
+ { "EOM", "atp.eom", FT_BOOLEAN, 8,
+ NULL, ATP_EOM, "End-of-message", HFILL }},
+
+ { &hf_atp_sts,
+ { "STS", "atp.sts", FT_BOOLEAN, 8,
+ NULL, ATP_STS, "Send transaction status", HFILL }},
+
+ { &hf_atp_treltimer,
+ { "TRel timer", "atp.treltimer", FT_UINT8, BASE_DEC,
+ VALS(atp_trel_timer_vals), 0x07, "TRel timer", HFILL }},
+
+ { &hf_atp_bitmap,
+ { "Bitmap", "atp.bitmap", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Bitmap or sequence number", HFILL }},
+
+ { &hf_atp_tid,
+ { "TID", "atp.tid", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Transaction id", HFILL }},
+ { &hf_atp_user_bytes,
+ { "User bytes", "atp.user_bytes", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "User bytes", HFILL }},
+
+ { &hf_atp_segment_overlap,
+ { "Segment overlap", "atp.segment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Segment overlaps with other segments", HFILL }},
+
+ { &hf_atp_segment_overlap_conflict,
+ { "Conflicting data in segment overlap", "atp.segment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Overlapping segments contained conflicting data", HFILL }},
+
+ { &hf_atp_segment_multiple_tails,
+ { "Multiple tail segments found", "atp.segment.multipletails",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Several tails were found when desegmenting the packet", HFILL }},
+
+ { &hf_atp_segment_too_long_segment,
+ { "Segment too long", "atp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Segment contained data past end of packet", HFILL }},
+
+ { &hf_atp_segment_error,
+ {"Desegmentation error", "atp.segment.error", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "Desegmentation error due to illegal segments", HFILL }},
+
+ { &hf_atp_segment,
+ { "ATP Fragment", "atp.fragment", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "ATP Fragment", HFILL }},
+
+ { &hf_atp_segments,
+ { "ATP Fragments", "atp.fragments", FT_NONE, BASE_NONE,
+ NULL, 0x0, "ATP Fragments", HFILL }},
+
+ { &hf_atp_reassembled_in,
+ { "Reassembled ATP in frame", "atp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This ATP packet is reassembled in this frame", HFILL }}
+ };
+
+ static hf_register_info hf_asp[] = {
+ { &hf_asp_func,
+ { "asp function", "asp.function", FT_UINT8, BASE_DEC,
+ VALS(asp_func_vals), 0, "asp function", HFILL }},
+
+ { &hf_asp_error,
+ { "asp error", "asp.error", FT_INT32, BASE_DEC,
+ VALS(asp_error_vals), 0, "return error code", HFILL }},
+
+ { &hf_asp_version,
+ { "Version", "asp.version", FT_UINT16, BASE_HEX,
+ NULL, 0, "asp version", HFILL }},
+
+ { &hf_asp_attn_code,
+ { "Attn code", "asp.attn_code", FT_UINT16, BASE_HEX,
+ NULL, 0, "asp attention code", HFILL }},
+
+ { &hf_asp_init_error,
+ { "Error", "asp.init_error", FT_UINT16, BASE_DEC,
+ NULL, 0, "asp init error", HFILL }},
+
+ { &hf_asp_session_id,
+ { "Session ID", "asp.session_id", FT_UINT8, BASE_DEC,
+ NULL, 0, "asp session id", HFILL }},
+
+ { &hf_asp_socket,
+ { "Socket", "asp.socket", FT_UINT8, BASE_DEC,
+ NULL, 0, "asp socket", HFILL }},
+
+ { &hf_asp_seq,
+ { "Sequence", "asp.seq", FT_UINT16, BASE_DEC,
+ NULL, 0, "asp sequence number", HFILL }},
+
+ { &hf_asp_size,
+ { "size", "asp.size", FT_UINT16, BASE_DEC,
+ NULL, 0, "asp available size for reply", HFILL }},
+
+ { &hf_asp_zero_value,
+ { "Pad (0)", "asp.zero_value",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Pad", HFILL }},
+
+ /* asp ,dsi, afp */
+ { &hf_asp_server_name,
+ { "Server name", "asp.server_name",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "Server name", HFILL }},
+
+ { &hf_asp_server_type,
+ { "Server type", "asp.server_type",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "Server type", HFILL }},
+
+ { &hf_asp_server_vers,
+ { "AFP version", "asp.server_vers",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "AFP version", HFILL }},
+
+ { &hf_asp_server_uams,
+ { "UAM", "asp.server_uams",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "UAM", HFILL }},
+
+ { &hf_asp_server_icon,
+ { "Icon bitmap", "asp.server_icon",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Server icon bitmap", HFILL }},
+
+ { &hf_asp_server_directory,
+ { "Directory service", "asp.server_directory",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "Server directory service", HFILL }},
+
+ { &hf_asp_server_signature,
+ { "Server signature", "asp.server_signature",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Server signature", HFILL }},
+
+ { &hf_asp_server_flag,
+ { "Flag", "asp.server_flag",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Server capabilities flag", HFILL }},
+ { &hf_asp_server_flag_copyfile,
+ { "Support copyfile", "asp.server_flag.copyfile",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_COPY,
+ "Server support copyfile", HFILL }},
+ { &hf_asp_server_flag_passwd,
+ { "Support change password", "asp.server_flag.passwd",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_PASSWD,
+ "Server support change password", HFILL }},
+ { &hf_asp_server_flag_no_save_passwd,
+ { "Don't allow save password", "asp.server_flag.no_save_passwd",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_NOSAVEPASSWD,
+ "Don't allow save password", HFILL }},
+ { &hf_asp_server_flag_srv_msg,
+ { "Support server message", "asp.server_flag.srv_msg",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVMSGS,
+ "Support server message", HFILL }},
+ { &hf_asp_server_flag_srv_sig,
+ { "Support server signature", "asp.server_flag.srv_sig",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVSIGNATURE,
+ "Support server signature", HFILL }},
+ { &hf_asp_server_flag_tcpip,
+ { "Support TCP/IP", "asp.server_flag.tcpip",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_TCPIP,
+ "Server support TCP/IP", HFILL }},
+ { &hf_asp_server_flag_notify,
+ { "Support server notifications", "asp.server_flag.notify",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVNOTIFY,
+ "Server support notifications", HFILL }},
+ { &hf_asp_server_flag_reconnect,
+ { "Support server reconnect", "asp.server_flag.reconnect",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVRECONNECT,
+ "Server support reconnect", HFILL }},
+ { &hf_asp_server_flag_directory,
+ { "Support directory services", "asp.server_flag.directory",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVDIRECTORY,
+ "Server support directory services", HFILL }},
+ { &hf_asp_server_flag_utf8_name,
+ { "Support UTF8 server name", "asp.server_flag.utf8_name",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVUTF8,
+ "Server support UTF8 server name", HFILL }},
+ { &hf_asp_server_flag_fast_copy,
+ { "Support fast copy", "asp.server_flag.fast_copy",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_FASTBOZO,
+ "Server support fast copy", HFILL }},
+
+ { &hf_asp_server_addr_len,
+ { "Length", "asp.server_addr.len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Address length.", HFILL }},
+
+ { &hf_asp_server_addr_type,
+ { "Type", "asp.server_addr.type",
+ FT_UINT8, BASE_DEC, VALS(afp_server_addr_type_vals), 0x0,
+ "Address type.", HFILL }},
+
+ { &hf_asp_server_addr_value,
+ { "Value", "asp.server_addr.value",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Address value", HFILL }},
+
+ { &hf_asp_server_utf8_name_len,
+ { "Server name length", "asp.server_utf8_name_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "UTF8 server name length", HFILL }},
+
+ { &hf_asp_server_utf8_name,
+ { "Server name (UTF8)", "asp.server_utf8_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Server name (UTF8)", HFILL }},
+ };
+
+ static hf_register_info hf_zip[] = {
+ { &hf_zip_function,
+ { "Function", "zip.function", FT_UINT8, BASE_DEC, VALS(zip_function_vals), 0x0,
+ "ZIP function", HFILL }},
+
+ { &hf_zip_zero_value,
+ { "Pad (0)", "zip.zero_value",FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Pad", HFILL }},
+
+ { &hf_zip_atp_function,
+ { "Function", "zip.atp_function", FT_UINT8, BASE_DEC, VALS(zip_atp_function_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_zip_start_index,
+ { "Start index", "zip.start_index", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_zip_count,
+ { "Count", "zip.count", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_zip_network_count,
+ { "Count", "zip.network_count", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_zip_network,
+ { "Network","zip.network", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_zip_network_start,
+ { "Network start","zip.network_start", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_zip_network_end,
+ { "Network end", "zip.network_end", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_zip_flags,
+ { "Flags", "zip.flags", FT_BOOLEAN, 8, NULL, 0xC0,
+ "", HFILL }},
+
+ { &hf_zip_last_flag,
+ { "Last Flag", "zip.last_flag", FT_BOOLEAN, 8, NULL, 0,
+ "Non zero if contains last zone name in the zone list", HFILL }},
+
+ { &hf_zip_flags_zone_invalid,
+ { "Zone invalid", "zip.flags.zone_invalid", FT_BOOLEAN, 8, NULL, 0x80,
+ "", HFILL }},
+
+ { &hf_zip_flags_use_broadcast,
+ { "Use broadcast","zip.flags.use_broadcast", FT_BOOLEAN, 8, NULL, 0x40,
+ "", HFILL }},
+
+ { &hf_zip_flags_only_one_zone,
+ { "Only one zone","zip.flags.only_one_zone", FT_BOOLEAN, 8, NULL, 0x20,
+ "", HFILL }},
+
+ { &hf_zip_zone_name,
+ { "Zone", "zip.zone_name", FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_zip_default_zone,
+ { "Default zone", "zip.default_zone",FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_zip_multicast_length,
+ { "Multicast length", "zip.multicast_length", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Multicast address length", HFILL }},
+
+ { &hf_zip_multicast_address,
+ { "Multicast address", "zip.multicast_address",FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Multicast address", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_llap,
+ &ett_ddp,
+ &ett_atp,
+ &ett_atp_info,
+ &ett_atp_segments,
+ &ett_atp_segment,
+ &ett_asp,
+
+ /* asp dsi afp */
+ &ett_asp_status,
+ &ett_asp_status_server_flag,
+ &ett_asp_vers,
+ &ett_asp_uams,
+ &ett_asp_addr,
+ &ett_asp_addr_line,
+ &ett_asp_directory,
+ &ett_asp_utf8_name,
+
+ &ett_nbp,
+ &ett_nbp_info,
+ &ett_nbp_node,
+ &ett_pstring,
+ &ett_rtmp,
+ &ett_rtmp_tuple,
+
+ &ett_zip,
+ &ett_zip_flags,
+ &ett_zip_zones_list,
+ &ett_zip_network_list,
+ };
+ module_t *atp_module;
+
+ proto_llap = proto_register_protocol("LocalTalk Link Access Protocol", "LLAP", "llap");
+ proto_register_field_array(proto_llap, hf_llap, array_length(hf_llap));
+
+ proto_ddp = proto_register_protocol("Datagram Delivery Protocol", "DDP", "ddp");
+ proto_register_field_array(proto_ddp, hf_ddp, array_length(hf_ddp));
+
+ proto_nbp = proto_register_protocol("Name Binding Protocol", "NBP", "nbp");
+ proto_register_field_array(proto_nbp, hf_nbp, array_length(hf_nbp));
+
+ proto_atp = proto_register_protocol("AppleTalk Transaction Protocol packet", "ATP", "atp");
+ proto_register_field_array(proto_atp, hf_atp, array_length(hf_atp));
+
+ proto_asp = proto_register_protocol("AppleTalk Session Protocol", "ASP", "asp");
+ proto_register_field_array(proto_asp, hf_asp, array_length(hf_asp));
+
+ proto_zip = proto_register_protocol("Zone Information Protocol", "ZIP", "zip");
+ proto_register_field_array(proto_zip, hf_zip, array_length(hf_zip));
+
+ atp_module = prefs_register_protocol(proto_atp, NULL);
+ prefs_register_bool_preference(atp_module, "desegment",
+ "Desegment all ATP messages spanning multiple DDP packets",
+ "Whether the ATP dissector should desegment all messages spanning multiple DDP packets",
+ &atp_defragment);
+
+ proto_rtmp = proto_register_protocol("Routing Table Maintenance Protocol",
+ "RTMP", "rtmp");
+ proto_register_field_array(proto_rtmp, hf_rtmp, array_length(hf_rtmp));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ ddp_dissector_table = register_dissector_table("ddp.type", "DDP packet type",
+ FT_UINT8, BASE_HEX);
+}
+
+void
+proto_reg_handoff_atalk(void)
+{
+ dissector_handle_t nbp_handle, rtmp_request_handle;
+ dissector_handle_t atp_handle;
+ dissector_handle_t zip_ddp_handle;
+ dissector_handle_t rtmp_data_handle, llap_handle;
+
+ ddp_handle = create_dissector_handle(dissect_ddp, proto_ddp);
+ dissector_add("ethertype", ETHERTYPE_ATALK, ddp_handle);
+ dissector_add("chdlctype", ETHERTYPE_ATALK, ddp_handle);
+ dissector_add("ppp.protocol", PPP_AT, ddp_handle);
+ dissector_add("null.type", BSD_AF_APPLETALK, ddp_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_APPLETALK, ddp_handle);
+
+ nbp_handle = create_dissector_handle(dissect_nbp, proto_nbp);
+ dissector_add("ddp.type", DDP_NBP, nbp_handle);
+
+ atp_handle = create_dissector_handle(dissect_atp, proto_atp);
+ dissector_add("ddp.type", DDP_ATP, atp_handle);
+
+ asp_handle = create_dissector_handle(dissect_asp, proto_asp);
+
+ rtmp_request_handle = create_dissector_handle(dissect_rtmp_request, proto_rtmp);
+ rtmp_data_handle = create_dissector_handle(dissect_rtmp_data, proto_rtmp);
+ dissector_add("ddp.type", DDP_RTMPREQ, rtmp_request_handle);
+ dissector_add("ddp.type", DDP_RTMPDATA, rtmp_data_handle);
+
+ zip_ddp_handle = create_dissector_handle(dissect_ddp_zip, proto_zip);
+ dissector_add("ddp.type", DDP_ZIP, zip_ddp_handle);
+
+ zip_atp_handle = create_dissector_handle(dissect_atp_zip, proto_zip);
+
+ llap_handle = create_dissector_handle(dissect_llap, proto_llap);
+ dissector_add("wtap_encap", WTAP_ENCAP_LOCALTALK, llap_handle);
+
+ register_init_routine( atp_init);
+ register_init_routine( &asp_reinit);
+
+ afp_handle = find_dissector("afp");
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-atalk.h b/epan/dissectors/packet-atalk.h
new file mode 100644
index 0000000000..592dd1948e
--- /dev/null
+++ b/epan/dissectors/packet-atalk.h
@@ -0,0 +1,53 @@
+/* packet-atalk.h
+ * Definitions for Appletalk packet disassembly (DDP, currently).
+ *
+ * $Id$
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_ATALK_H__
+#define __PACKET_ATALK_H__
+
+/*
+ * Structure used to represent a DDP address; gives the layout of the
+ * data pointed to by an AT_ATALK "address" structure.
+ */
+struct atalk_ddp_addr {
+ guint16 net;
+ guint8 node;
+ guint8 port;
+};
+
+/*
+ * DDP packet types.
+ */
+#define DDP_RTMPDATA 0x01
+#define DDP_NBP 0x02
+#define DDP_ATP 0x03
+#define DDP_AEP 0x04
+#define DDP_RTMPREQ 0x05
+#define DDP_ZIP 0x06
+#define DDP_ADSP 0x07
+#define DDP_EIGRP 0x58
+
+/*
+ * Routine to take a DDP address and generate a string.
+ */
+extern gchar *atalk_addr_to_str(const struct atalk_ddp_addr *addrp);
+
+extern void capture_llap(packet_counts *ld);
+
+#endif
diff --git a/epan/dissectors/packet-atm.c b/epan/dissectors/packet-atm.c
new file mode 100644
index 0000000000..1c2420d6d2
--- /dev/null
+++ b/epan/dissectors/packet-atm.c
@@ -0,0 +1,1640 @@
+/* packet-atm.c
+ * Routines for ATM packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "oui.h"
+#include <epan/resolv.h>
+
+#include "packet-atm.h"
+#include "packet-snmp.h"
+#include "packet-eth.h"
+#include "packet-tr.h"
+#include "packet-llc.h"
+
+static int proto_atm = -1;
+static int hf_atm_aal = -1;
+static int hf_atm_vpi = -1;
+static int hf_atm_vci = -1;
+static int proto_atm_lane = -1;
+static int proto_ilmi = -1;
+static int proto_aal1 = -1;
+static int proto_aal3_4 = -1;
+static int proto_oamaal = -1;
+
+static gint ett_atm = -1;
+static gint ett_atm_lane = -1;
+static gint ett_atm_lane_lc_lan_dest = -1;
+static gint ett_atm_lane_lc_lan_dest_rd = -1;
+static gint ett_atm_lane_lc_flags = -1;
+static gint ett_atm_lane_lc_tlv = -1;
+static gint ett_ilmi = -1;
+static gint ett_aal1 = -1;
+static gint ett_aal3_4 = -1;
+static gint ett_oamaal = -1;
+
+static dissector_handle_t eth_handle;
+static dissector_handle_t tr_handle;
+static dissector_handle_t llc_handle;
+static dissector_handle_t sscop_handle;
+static dissector_handle_t lane_handle;
+static dissector_handle_t ilmi_handle;
+static dissector_handle_t data_handle;
+
+/*
+ * See
+ *
+ * http://www.atmforum.org/atmforum/specs/approved.html
+ *
+ * for a number of ATM Forum specifications, e.g. the LAN Emulation
+ * over ATM 1.0 spec, whence I got most of this.
+ */
+
+/* LE Control opcodes */
+#define LE_CONFIGURE_REQUEST 0x0001
+#define LE_CONFIGURE_RESPONSE 0x0101
+#define LE_JOIN_REQUEST 0x0002
+#define LE_JOIN_RESPONSE 0x0102
+#define READY_QUERY 0x0003
+#define READY_IND 0x0103
+#define LE_REGISTER_REQUEST 0x0004
+#define LE_REGISTER_RESPONSE 0x0104
+#define LE_UNREGISTER_REQUEST 0x0005
+#define LE_UNREGISTER_RESPONSE 0x0105
+#define LE_ARP_REQUEST 0x0006
+#define LE_ARP_RESPONSE 0x0106
+#define LE_FLUSH_REQUEST 0x0007
+#define LE_FLUSH_RESPONSE 0x0107
+#define LE_NARP_REQUEST 0x0008
+#define LE_TOPOLOGY_REQUEST 0x0009
+#define LE_VERIFY_REQUEST 0x000A
+#define LE_VERIFY_RESPONSE 0x010A
+
+static const value_string le_control_opcode_vals[] = {
+ { LE_CONFIGURE_REQUEST, "LE_CONFIGURE_REQUEST" },
+ { LE_CONFIGURE_RESPONSE, "LE_CONFIGURE_RESPONSE" },
+ { LE_JOIN_REQUEST, "LE_JOIN_REQUEST" },
+ { LE_JOIN_RESPONSE, "LE_JOIN_RESPONSE" },
+ { READY_QUERY, "READY_QUERY" },
+ { READY_IND, "READY_IND" },
+ { LE_REGISTER_REQUEST, "LE_REGISTER_REQUEST" },
+ { LE_REGISTER_RESPONSE, "LE_REGISTER_RESPONSE" },
+ { LE_UNREGISTER_REQUEST, "LE_UNREGISTER_REQUEST" },
+ { LE_UNREGISTER_RESPONSE, "LE_UNREGISTER_RESPONSE" },
+ { LE_ARP_REQUEST, "LE_ARP_REQUEST" },
+ { LE_ARP_RESPONSE, "LE_ARP_RESPONSE" },
+ { LE_FLUSH_REQUEST, "LE_FLUSH_REQUEST" },
+ { LE_FLUSH_RESPONSE, "LE_FLUSH_RESPONSE" },
+ { LE_NARP_REQUEST, "LE_NARP_REQUEST" },
+ { LE_TOPOLOGY_REQUEST, "LE_TOPOLOGY_REQUEST" },
+ { LE_VERIFY_REQUEST, "LE_VERIFY_REQUEST" },
+ { LE_VERIFY_RESPONSE, "LE_VERIFY_RESPONSE" },
+ { 0, NULL }
+};
+
+/* LE Control statuses */
+static const value_string le_control_status_vals[] = {
+ { 0, "Success" },
+ { 1, "Version not supported" },
+ { 2, "Invalid request parameters" },
+ { 4, "Duplicate LAN destination registration" },
+ { 5, "Duplicate ATM address" },
+ { 6, "Insufficient resources to grant request" },
+ { 7, "Access denied" },
+ { 8, "Invalid REQUESTOR-ID" },
+ { 9, "Invalid LAN destination" },
+ { 10, "Invalid ATM address" },
+ { 20, "No configuraton" },
+ { 21, "LE_CONFIGURE error" },
+ { 22, "Insufficient information" },
+ { 24, "TLV not found" },
+ { 0, NULL }
+};
+
+/* LE Control LAN destination tags */
+#define TAG_NOT_PRESENT 0x0000
+#define TAG_MAC_ADDRESS 0x0001
+#define TAG_ROUTE_DESCRIPTOR 0x0002
+
+static const value_string le_control_landest_tag_vals[] = {
+ { TAG_NOT_PRESENT, "Not present" },
+ { TAG_MAC_ADDRESS, "MAC address" },
+ { TAG_ROUTE_DESCRIPTOR, "Route descriptor" },
+ { 0, NULL }
+};
+
+/* LE Control LAN types */
+#define LANT_UNSPEC 0x00
+#define LANT_802_3 0x01
+#define LANT_802_5 0x02
+
+static const value_string le_control_lan_type_vals[] = {
+ { LANT_UNSPEC, "Unspecified" },
+ { LANT_802_3, "Ethernet/802.3" },
+ { LANT_802_5, "802.5" },
+ { 0, NULL }
+};
+
+static const value_string le_control_frame_size_vals[] = {
+ { 0x00, "Unspecified" },
+ { 0x01, "1516/1528/1580/1592" },
+ { 0x02, "4544/4556/1580/1592" },
+ { 0x03, "9234/9246" },
+ { 0x04, "18190/18202" },
+ { 0, NULL }
+};
+
+static void
+dissect_le_client(tvbuff_t *tvb, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *lane_tree;
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, 0, 2, "ATM LANE");
+ lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
+
+ proto_tree_add_text(lane_tree, tvb, 0, 2, "LE Client: 0x%04X",
+ tvb_get_ntohs(tvb, 0));
+ }
+}
+
+static void
+dissect_lan_destination(tvbuff_t *tvb, int offset, const char *type, proto_tree *tree)
+{
+ proto_item *td;
+ proto_tree *dest_tree;
+ guint16 tag;
+ proto_item *trd;
+ proto_tree *rd_tree;
+ guint16 route_descriptor;
+
+ td = proto_tree_add_text(tree, tvb, offset, 8, "%s LAN destination",
+ type);
+ dest_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest);
+ tag = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(dest_tree, tvb, offset, 2, "Tag: %s",
+ val_to_str(tag, le_control_landest_tag_vals,
+ "Unknown (0x%04X)"));
+ offset += 2;
+
+ switch (tag) {
+
+ case TAG_MAC_ADDRESS:
+ proto_tree_add_text(dest_tree, tvb, offset, 6, "MAC address: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ break;
+
+ case TAG_ROUTE_DESCRIPTOR:
+ offset += 4;
+ route_descriptor = tvb_get_ntohs(tvb, offset);
+ trd = proto_tree_add_text(dest_tree, tvb, offset, 2, "Route descriptor: 0x%02X",
+ route_descriptor);
+ rd_tree = proto_item_add_subtree(td, ett_atm_lane_lc_lan_dest_rd);
+ proto_tree_add_text(rd_tree, tvb, offset, 2,
+ decode_numeric_bitfield(route_descriptor, 0xFFF0, 2*8,
+ "LAN ID = %u"));
+ proto_tree_add_text(rd_tree, tvb, offset, 2,
+ decode_numeric_bitfield(route_descriptor, 0x000F, 2*8,
+ "Bridge number = %u"));
+ break;
+ }
+}
+
+/*
+ * TLV values in LE Control frames.
+ */
+#define TLV_TYPE(oui, ident) (((oui) << 8) | (ident))
+
+#define LE_CONTROL_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x01)
+#define LE_MAX_UNK_FRAME_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x02)
+#define LE_MAX_UNK_FRAME_TIME TLV_TYPE(OUI_ATM_FORUM, 0x03)
+#define LE_VCC_TIMEOUT_PERIOD TLV_TYPE(OUI_ATM_FORUM, 0x04)
+#define LE_MAX_RETRY_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x05)
+#define LE_AGING_TIME TLV_TYPE(OUI_ATM_FORUM, 0x06)
+#define LE_FORWARD_DELAY_TIME TLV_TYPE(OUI_ATM_FORUM, 0x07)
+#define LE_EXPECTED_ARP_RESPONSE_TIME TLV_TYPE(OUI_ATM_FORUM, 0x08)
+#define LE_FLUSH_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x09)
+#define LE_PATH_SWITCHING_DELAY TLV_TYPE(OUI_ATM_FORUM, 0x0A)
+#define LE_LOCAL_SEGMENT_ID TLV_TYPE(OUI_ATM_FORUM, 0x0B)
+#define LE_MCAST_SEND_VCC_TYPE TLV_TYPE(OUI_ATM_FORUM, 0x0C)
+#define LE_MCAST_SEND_VCC_AVGRATE TLV_TYPE(OUI_ATM_FORUM, 0x0D)
+#define LE_MCAST_SEND_VCC_PEAKRATE TLV_TYPE(OUI_ATM_FORUM, 0x0E)
+#define LE_CONN_COMPLETION_TIMER TLV_TYPE(OUI_ATM_FORUM, 0x0F)
+#define LE_CONFIG_FRAG_INFO TLV_TYPE(OUI_ATM_FORUM, 0x10)
+#define LE_LAYER_3_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x11)
+#define LE_ELAN_ID TLV_TYPE(OUI_ATM_FORUM, 0x12)
+#define LE_SERVICE_CATEGORY TLV_TYPE(OUI_ATM_FORUM, 0x13)
+#define LE_LLC_MUXED_ATM_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x2B)
+#define LE_X5_ADJUSTMENT TLV_TYPE(OUI_ATM_FORUM, 0x2C)
+#define LE_PREFERRED_LES TLV_TYPE(OUI_ATM_FORUM, 0x2D)
+
+static const value_string le_tlv_type_vals[] = {
+ { LE_CONTROL_TIMEOUT, "Control Time-out" },
+ { LE_MAX_UNK_FRAME_COUNT, "Maximum Unknown Frame Count" },
+ { LE_MAX_UNK_FRAME_TIME, "Maximum Unknown Frame Time" },
+ { LE_VCC_TIMEOUT_PERIOD, "VCC Time-out" },
+ { LE_MAX_RETRY_COUNT, "Maximum Retry Count" },
+ { LE_AGING_TIME, "Aging Time" },
+ { LE_FORWARD_DELAY_TIME, "Forwarding Delay Time" },
+ { LE_EXPECTED_ARP_RESPONSE_TIME, "Expected LE_ARP Response Time" },
+ { LE_FLUSH_TIMEOUT, "Flush Time-out" },
+ { LE_PATH_SWITCHING_DELAY, "Path Switching Delay" },
+ { LE_LOCAL_SEGMENT_ID, "Local Segment ID" },
+ { LE_MCAST_SEND_VCC_TYPE, "Mcast Send VCC Type" },
+ { LE_MCAST_SEND_VCC_AVGRATE, "Mcast Send VCC AvgRate" },
+ { LE_MCAST_SEND_VCC_PEAKRATE, "Mcast Send VCC PeakRate" },
+ { LE_CONN_COMPLETION_TIMER, "Connection Completion Timer" },
+ { LE_CONFIG_FRAG_INFO, "Config Frag Info" },
+ { LE_LAYER_3_ADDRESS, "Layer 3 Address" },
+ { LE_ELAN_ID, "ELAN ID" },
+ { LE_SERVICE_CATEGORY, "Service Category" },
+ { LE_LLC_MUXED_ATM_ADDRESS, "LLC-muxed ATM Address" },
+ { LE_X5_ADJUSTMENT, "X5 Adjustment" },
+ { LE_PREFERRED_LES, "Preferred LES" },
+ { 0, NULL },
+};
+
+static void
+dissect_le_control_tlvs(tvbuff_t *tvb, int offset, guint num_tlvs,
+ proto_tree *tree)
+{
+ guint32 tlv_type;
+ guint8 tlv_length;
+ proto_item *ttlv;
+ proto_tree *tlv_tree;
+
+ while (num_tlvs != 0) {
+ tlv_type = tvb_get_ntohl(tvb, offset);
+ tlv_length = tvb_get_guint8(tvb, offset+4);
+ ttlv = proto_tree_add_text(tree, tvb, offset, 5+tlv_length, "TLV type: %s",
+ val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
+ tlv_tree = proto_item_add_subtree(ttlv, ett_atm_lane_lc_tlv);
+ proto_tree_add_text(tlv_tree, tvb, offset, 4, "TLV Type: %s",
+ val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
+ proto_tree_add_text(tlv_tree, tvb, offset+4, 1, "TLV Length: %u", tlv_length);
+ offset += 5+tlv_length;
+ num_tlvs--;
+ }
+}
+
+static void
+dissect_le_configure_join_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint8 num_tlvs;
+ guint8 name_size;
+
+ dissect_lan_destination(tvb, offset, "Source", tree);
+ offset += 8;
+
+ dissect_lan_destination(tvb, offset, "Target", tree);
+ offset += 8;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "LAN type: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), le_control_lan_type_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "Maximum frame size: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), le_control_frame_size_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+
+ num_tlvs = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
+ offset += 1;
+
+ name_size = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "ELAN name size: %u", name_size);
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ if (name_size > 32)
+ name_size = 32;
+ if (name_size != 0) {
+ proto_tree_add_text(tree, tvb, offset, name_size, "ELAN name: %s",
+ tvb_bytes_to_str(tvb, offset, name_size));
+ }
+ offset += 32;
+
+ dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
+}
+
+static void
+dissect_le_registration_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint8 num_tlvs;
+
+ dissect_lan_destination(tvb, offset, "Source", tree);
+ offset += 8;
+
+ dissect_lan_destination(tvb, offset, "Target", tree);
+ offset += 8;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ /* Reserved */
+ offset += 2;
+
+ num_tlvs = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
+ offset += 1;
+
+ /* Reserved */
+ offset += 53;
+
+ dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
+}
+
+static void
+dissect_le_arp_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint8 num_tlvs;
+
+ dissect_lan_destination(tvb, offset, "Source", tree);
+ offset += 8;
+
+ dissect_lan_destination(tvb, offset, "Target", tree);
+ offset += 8;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ /* Reserved */
+ offset += 2;
+
+ num_tlvs = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
+ offset += 1;
+
+ /* Reserved */
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ /* Reserved */
+ offset += 32;
+
+ dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
+}
+
+static void
+dissect_le_verify_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint8 num_tlvs;
+
+ /* Reserved */
+ offset += 38;
+
+ num_tlvs = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
+ offset += 1;
+
+ /* Reserved */
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ /* Reserved */
+ offset += 32;
+
+ dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
+}
+
+static void
+dissect_le_flush_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ dissect_lan_destination(tvb, offset, "Source", tree);
+ offset += 8;
+
+ dissect_lan_destination(tvb, offset, "Target", tree);
+ offset += 8;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ /* Reserved */
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ /* Reserved */
+ offset += 32;
+}
+
+static void
+dissect_le_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *lane_tree = NULL;
+ int offset = 0;
+ proto_item *tf;
+ proto_tree *flags_tree;
+ guint16 opcode;
+ guint16 flags;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "LE Control");
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_atm_lane, tvb, offset, 108, "ATM LANE");
+ lane_tree = proto_item_add_subtree(ti, ett_atm_lane);
+
+ proto_tree_add_text(lane_tree, tvb, offset, 2, "Marker: 0x%04X",
+ tvb_get_ntohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (tree) {
+ proto_tree_add_text(lane_tree, tvb, offset, 1, "Protocol: 0x%02X",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_text(lane_tree, tvb, offset, 1, "Version: 0x%02X",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+
+ opcode = tvb_get_ntohs(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
+ val_to_str(opcode, le_control_opcode_vals,
+ "Unknown opcode (0x%04X)"));
+ }
+ if (tree) {
+ proto_tree_add_text(lane_tree, tvb, offset, 2, "Opcode: %s",
+ val_to_str(opcode, le_control_opcode_vals,
+ "Unknown (0x%04X)"));
+ }
+ offset += 2;
+
+ if (opcode == READY_QUERY || opcode == READY_IND) {
+ /* There's nothing more in this packet. */
+ return;
+ }
+
+ if (tree) {
+ if (opcode & 0x0100) {
+ /* Response; decode status. */
+ proto_tree_add_text(lane_tree, tvb, offset, 2, "Status: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), le_control_status_vals,
+ "Unknown (0x%04X)"));
+ }
+ offset += 2;
+
+ proto_tree_add_text(lane_tree, tvb, offset, 4, "Transaction ID: 0x%08X",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(lane_tree, tvb, offset, 2, "Requester LECID: 0x%04X",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ flags = tvb_get_ntohs(tvb, offset);
+ tf = proto_tree_add_text(lane_tree, tvb, offset, 2, "Flags: 0x%04X",
+ flags);
+ flags_tree = proto_item_add_subtree(tf, ett_atm_lane_lc_flags);
+
+ switch (opcode) {
+
+ case LE_CONFIGURE_REQUEST:
+ case LE_CONFIGURE_RESPONSE:
+ proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0002, 8*2,
+ "V2 capable", "Not V2 capable"));
+ offset += 2;
+ dissect_le_configure_join_frame(tvb, offset, lane_tree);
+ break;
+
+ case LE_JOIN_REQUEST:
+ case LE_JOIN_RESPONSE:
+ proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0002, 8*2,
+ "V2 capable", "Not V2 capable"));
+ if (opcode == LE_JOIN_REQUEST) {
+ proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0004, 8*2,
+ "Selective multicast", "No selective multicast"));
+ } else {
+ proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0008, 8*2,
+ "V2 required", "V2 not required"));
+ }
+ proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0080, 8*2,
+ "Proxy", "Not proxy"));
+ proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0200, 8*2,
+ "Exclude explorer frames",
+ "Don't exclude explorer frames"));
+ offset += 2;
+ dissect_le_configure_join_frame(tvb, offset, lane_tree);
+ break;
+
+ case LE_REGISTER_REQUEST:
+ case LE_REGISTER_RESPONSE:
+ case LE_UNREGISTER_REQUEST:
+ case LE_UNREGISTER_RESPONSE:
+ offset += 2;
+ dissect_le_registration_frame(tvb, offset, lane_tree);
+ break;
+
+ case LE_ARP_REQUEST:
+ case LE_ARP_RESPONSE:
+ case LE_NARP_REQUEST:
+ if (opcode != LE_NARP_REQUEST) {
+ proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0001, 8*2,
+ "Remote address", "Local address"));
+ }
+ offset += 2;
+ dissect_le_arp_frame(tvb, offset, lane_tree);
+ break;
+
+ case LE_TOPOLOGY_REQUEST:
+ proto_tree_add_text(flags_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0100, 8*2,
+ "Topology change", "No topology change"));
+ offset += 2;
+ /* 92 reserved bytes */
+ break;
+
+ case LE_VERIFY_REQUEST:
+ case LE_VERIFY_RESPONSE:
+ offset += 2;
+ dissect_le_verify_frame(tvb, offset, lane_tree);
+ break;
+
+ case LE_FLUSH_REQUEST:
+ case LE_FLUSH_RESPONSE:
+ offset += 2;
+ dissect_le_flush_frame(tvb, offset, lane_tree);
+ break;
+ }
+ }
+}
+
+static void
+capture_lane(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
+ int len, packet_counts *ld)
+{
+ /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
+ switch (pseudo_header->atm.subtype) {
+
+ case TRAF_ST_LANE_802_3:
+ case TRAF_ST_LANE_802_3_MC:
+ /* Dissect as Ethernet */
+ capture_eth(pd, 2, len, ld);
+ break;
+
+ case TRAF_ST_LANE_802_5:
+ case TRAF_ST_LANE_802_5_MC:
+ /* Dissect as Token-Ring */
+ capture_tr(pd, 2, len, ld);
+ break;
+
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+static void
+dissect_lane(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *next_tvb;
+ tvbuff_t *next_tvb_le_client;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM LANE");
+
+ /* Is it LE Control, 802.3, 802.5, or "none of the above"? */
+ switch (pinfo->pseudo_header->atm.subtype) {
+
+ case TRAF_ST_LANE_LE_CTRL:
+ dissect_le_control(tvb, pinfo, tree);
+ break;
+
+ case TRAF_ST_LANE_802_3:
+ case TRAF_ST_LANE_802_3_MC:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "LE Client - Ethernet/802.3");
+ dissect_le_client(tvb, tree);
+
+ /* Dissect as Ethernet */
+ next_tvb_le_client = tvb_new_subset(tvb, 2, -1, -1);
+ call_dissector(eth_handle, next_tvb_le_client, pinfo, tree);
+ break;
+
+ case TRAF_ST_LANE_802_5:
+ case TRAF_ST_LANE_802_5_MC:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "LE Client - 802.5");
+ dissect_le_client(tvb, tree);
+
+ /* Dissect as Token-Ring */
+ next_tvb_le_client = tvb_new_subset(tvb, 2, -1, -1);
+ call_dissector(tr_handle, next_tvb_le_client, pinfo, tree);
+ break;
+
+ default:
+ /* Dump it as raw data. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Unknown LANE traffic type");
+ next_tvb = tvb_new_subset(tvb, 0, -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ break;
+ }
+}
+
+static void
+dissect_ilmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_ilmi, ett_ilmi, FALSE);
+}
+
+/* AAL types */
+static const value_string aal_vals[] = {
+ { AAL_UNKNOWN, "Unknown AAL" },
+ { AAL_1, "AAL1" },
+ { AAL_2, "AAL2" },
+ { AAL_3_4, "AAL3/4" },
+ { AAL_5, "AAL5" },
+ { AAL_USER, "User AAL" },
+ { AAL_SIGNALLING, "Signalling AAL" },
+ { AAL_OAMCELL, "OAM cell" },
+ { 0, NULL }
+};
+
+/* AAL5 higher-level traffic types */
+static const value_string aal5_hltype_vals[] = {
+ { TRAF_UNKNOWN, "Unknown traffic type" },
+ { TRAF_LLCMX, "LLC multiplexed" },
+ { TRAF_VCMX, "VC multiplexed" },
+ { TRAF_LANE, "LANE" },
+ { TRAF_ILMI, "ILMI" },
+ { TRAF_FR, "Frame Relay" },
+ { TRAF_SPANS, "FORE SPANS" },
+ { TRAF_IPSILON, "Ipsilon" },
+ { 0, NULL }
+};
+
+/* Traffic subtypes for VC multiplexed traffic */
+static const value_string vcmx_type_vals[] = {
+ { TRAF_ST_UNKNOWN, "Unknown VC multiplexed traffic type" },
+ { TRAF_ST_VCMX_802_3_FCS, "802.3 FCS" },
+ { TRAF_ST_VCMX_802_4_FCS, "802.4 FCS" },
+ { TRAF_ST_VCMX_802_5_FCS, "802.5 FCS" },
+ { TRAF_ST_VCMX_FDDI_FCS, "FDDI FCS" },
+ { TRAF_ST_VCMX_802_6_FCS, "802.6 FCS" },
+ { TRAF_ST_VCMX_802_3, "802.3" },
+ { TRAF_ST_VCMX_802_4, "802.4" },
+ { TRAF_ST_VCMX_802_5, "802.5" },
+ { TRAF_ST_VCMX_FDDI, "FDDI" },
+ { TRAF_ST_VCMX_802_6, "802.6" },
+ { TRAF_ST_VCMX_FRAGMENTS, "Fragments" },
+ { TRAF_ST_VCMX_BPDU, "BPDU" },
+ { 0, NULL }
+};
+
+/* Traffic subtypes for LANE traffic */
+static const value_string lane_type_vals[] = {
+ { TRAF_ST_UNKNOWN, "Unknown LANE traffic type" },
+ { TRAF_ST_LANE_LE_CTRL, "LE Control" },
+ { TRAF_ST_LANE_802_3, "802.3" },
+ { TRAF_ST_LANE_802_5, "802.5" },
+ { TRAF_ST_LANE_802_3_MC, "802.3 multicast" },
+ { TRAF_ST_LANE_802_5_MC, "802.5 multicast" },
+ { 0, NULL }
+};
+
+/* Traffic subtypes for Ipsilon traffic */
+static const value_string ipsilon_type_vals[] = {
+ { TRAF_ST_UNKNOWN, "Unknown Ipsilon traffic type" },
+ { TRAF_ST_IPSILON_FT0, "Flow type 0" },
+ { TRAF_ST_IPSILON_FT1, "Flow type 1" },
+ { TRAF_ST_IPSILON_FT2, "Flow type 2" },
+ { 0, NULL }
+};
+
+void
+capture_atm(const union wtap_pseudo_header *pseudo_header, const guchar *pd,
+ int len, packet_counts *ld)
+{
+ if (pseudo_header->atm.aal == AAL_5) {
+ switch (pseudo_header->atm.type) {
+
+ case TRAF_LLCMX:
+ /* Dissect as WTAP_ENCAP_ATM_RFC1483 */
+ /* The ATM iptrace capture that we have shows LLC at this point,
+ * so that's what I'm calling */
+ capture_llc(pd, 0, len, ld);
+ break;
+
+ case TRAF_LANE:
+ capture_lane(pseudo_header, pd, len, ld);
+ break;
+
+ default:
+ ld->other++;
+ break;
+ }
+ } else
+ ld->other++;
+}
+
+/*
+ * Charles Michael Heard's CRC-32 code, from
+ *
+ * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/32bitCRC.c.html
+ *
+ * with the CRC table initialized with values computed by
+ * his "gen_crc_table()" routine, rather than by calling that routine
+ * at run time, and with various data type cleanups.
+ */
+
+/* crc32h.c -- package to compute 32-bit CRC one byte at a time using */
+/* the high-bit first (Big-Endian) bit ordering convention */
+/* */
+/* Synopsis: */
+/* gen_crc_table() -- generates a 256-word table containing all CRC */
+/* remainders for every possible 8-bit byte. It */
+/* must be executed (once) before any CRC updates. */
+/* */
+/* unsigned update_crc(crc_accum, data_blk_ptr, data_blk_size) */
+/* unsigned crc_accum; char *data_blk_ptr; int data_blk_size; */
+/* Returns the updated value of the CRC accumulator after */
+/* processing each byte in the addressed block of data. */
+/* */
+/* It is assumed that an unsigned long is at least 32 bits wide and */
+/* that the predefined type char occupies one 8-bit byte of storage. */
+/* */
+/* The generator polynomial used for this version of the package is */
+/* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 */
+/* as specified in the Autodin/Ethernet/ADCCP protocol standards. */
+/* Other degree 32 polynomials may be substituted by re-defining the */
+/* symbol POLYNOMIAL below. Lower degree polynomials must first be */
+/* multiplied by an appropriate power of x. The representation used */
+/* is that the coefficient of x^0 is stored in the LSB of the 32-bit */
+/* word and the coefficient of x^31 is stored in the most significant */
+/* bit. The CRC is to be appended to the data most significant byte */
+/* first. For those protocols in which bytes are transmitted MSB */
+/* first and in the same order as they are encountered in the block */
+/* this convention results in the CRC remainder being transmitted with */
+/* the coefficient of x^31 first and with that of x^0 last (just as */
+/* would be done by a hardware shift register mechanization). */
+/* */
+/* The table lookup technique was adapted from the algorithm described */
+/* by Avram Perez, Byte-wise CRC Calculations, IEEE Micro 3, 40 (1983).*/
+
+static const guint32 crc_table[256] = {
+ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+ 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+ 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+ 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
+ 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
+ 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
+ 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
+ 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
+ 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
+ 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+ 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
+ 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
+ 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+ 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
+ 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
+ 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
+ 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
+ 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
+ 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
+ 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+ 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
+ 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
+ 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+ 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
+ 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
+ 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
+ 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
+ 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
+ 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
+ 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+ 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
+ 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
+ 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+ 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
+ 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
+ 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
+ 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
+ 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
+ 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
+ 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+ 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
+ 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
+ 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4,
+};
+
+static guint32
+update_crc(guint32 crc_accum, const guint8 *data_blk_ptr, int data_blk_size)
+{
+ register int i, j;
+
+ /* update the CRC on the data block one byte at a time */
+ for (j = 0; j < data_blk_size; j++) {
+ i = ( (int) ( crc_accum >> 24) ^ *data_blk_ptr++ ) & 0xff;
+ crc_accum = ( crc_accum << 8 ) ^ crc_table[i];
+ }
+ return crc_accum;
+}
+
+static void
+dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *atm_tree, gboolean truncated)
+{
+ guint length, reported_length;
+ guint16 aal5_length;
+ int pad_length;
+ tvbuff_t *next_tvb;
+ guint32 crc;
+ guint32 calc_crc;
+
+ /*
+ * This is reassembled traffic, so the cell headers are missing;
+ * show the traffic type for AAL5 traffic, and the VPI and VCI,
+ * from the pseudo-header.
+ */
+ if (pinfo->pseudo_header->atm.aal == AAL_5) {
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Traffic type: %s",
+ val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
+ "Unknown AAL5 traffic type (%u)"));
+ switch (pinfo->pseudo_header->atm.type) {
+
+ case TRAF_VCMX:
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "VC multiplexed traffic type: %s",
+ val_to_str(pinfo->pseudo_header->atm.subtype,
+ vcmx_type_vals, "Unknown VCMX traffic type (%u)"));
+ break;
+
+ case TRAF_LANE:
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "LANE traffic type: %s",
+ val_to_str(pinfo->pseudo_header->atm.subtype,
+ lane_type_vals, "Unknown LANE traffic type (%u)"));
+ break;
+
+ case TRAF_IPSILON:
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Ipsilon traffic type: %s",
+ val_to_str(pinfo->pseudo_header->atm.subtype,
+ ipsilon_type_vals, "Unknown Ipsilon traffic type (%u)"));
+ break;
+ }
+ }
+ proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
+ pinfo->pseudo_header->atm.vpi);
+ proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
+ pinfo->pseudo_header->atm.vci);
+
+ next_tvb = tvb;
+ if (truncated) {
+ /*
+ * The packet data does not include stuff such as the AAL5
+ * trailer.
+ */
+ if (pinfo->pseudo_header->atm.cells != 0) {
+ /*
+ * If the cell count is 0, assume it means we don't know how
+ * many cells it was.
+ *
+ * XXX - also assume it means we don't know what was in the AAL5
+ * trailer. We may, however, find some capture program that can
+ * give us the AAL5 trailer information but not the cell count,
+ * in which case we need some other way of indicating whether we
+ * have the AAL5 trailer information.
+ */
+ if (tree) {
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
+ pinfo->pseudo_header->atm.cells);
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 UU: 0x%02x",
+ pinfo->pseudo_header->atm.aal5t_u2u >> 8);
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CPI: 0x%02x",
+ pinfo->pseudo_header->atm.aal5t_u2u & 0xFF);
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 len: %u",
+ pinfo->pseudo_header->atm.aal5t_len);
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "AAL5 CRC: 0x%08X",
+ pinfo->pseudo_header->atm.aal5t_chksum);
+ }
+ }
+ } else {
+ /*
+ * The packet data includes stuff such as the AAL5 trailer, if
+ * it wasn't cut off by the snapshot length.
+ * Decode the trailer, if present, and then chop it off.
+ */
+ length = tvb_length(tvb);
+ reported_length = tvb_reported_length(tvb);
+ if ((reported_length % 48) == 0) {
+ /*
+ * Reported length is a multiple of 48, so we can presumably
+ * divide it by 48 to get the number of cells.
+ */
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Cells: %u",
+ reported_length/48);
+ }
+ if (length >= reported_length) {
+ /*
+ * XXX - what if the packet is truncated? Can that happen?
+ * What if you capture with Windows Sniffer on an ATM link
+ * and tell it not to save the entire packet? What happens
+ * to the trailer?
+ */
+ aal5_length = tvb_get_ntohs(tvb, length - 6);
+
+ /*
+ * Check for sanity in the AAL5 length. It must be > 0
+ * and must be less than the amount of space left after
+ * we remove the trailer.
+ *
+ * If it's not sane, assume we don't have a trailer.
+ */
+ if (aal5_length > 0 && aal5_length <= length - 8) {
+ /*
+ * How much padding is there?
+ */
+ pad_length = length - aal5_length - 8;
+
+ /*
+ * There is no reason for more than 47 bytes of padding.
+ * The most padding you can have would be 7 bytes at the
+ * end of the next-to-last cell (8 bytes after the end of
+ * the data means you can fit the trailer in that cell),
+ * plus 40 bytes in the last cell (with the last 8 bytes
+ * being padding).
+ *
+ * If there's more than 47 bytes of padding, assume we don't
+ * have a trailer.
+ */
+ if (pad_length <= 47) {
+ if (tree) {
+ if (pad_length > 0) {
+ proto_tree_add_text(atm_tree, tvb, aal5_length, pad_length,
+ "Padding");
+ }
+ proto_tree_add_text(atm_tree, tvb, length - 8, 1, "AAL5 UU: 0x%02x",
+ tvb_get_guint8(tvb, length - 8));
+ proto_tree_add_text(atm_tree, tvb, length - 7, 1, "AAL5 CPI: 0x%02x",
+ tvb_get_guint8(tvb, length - 7));
+ proto_tree_add_text(atm_tree, tvb, length - 6, 2, "AAL5 len: %u",
+ aal5_length);
+ crc = tvb_get_ntohl(tvb, length - 4);
+ calc_crc = update_crc(0xFFFFFFFF, tvb_get_ptr(tvb, 0, length),
+ length);
+ proto_tree_add_text(atm_tree, tvb, length - 4, 4,
+ "AAL5 CRC: 0x%08X (%s)", crc,
+ (calc_crc == 0xC704DD7B) ? "correct" : "incorrect");
+ }
+ next_tvb = tvb_new_subset(tvb, 0, aal5_length, aal5_length);
+ }
+ }
+ }
+ }
+
+ switch (pinfo->pseudo_header->atm.aal) {
+
+ case AAL_SIGNALLING:
+ call_dissector(sscop_handle, next_tvb, pinfo, tree);
+ break;
+
+ case AAL_5:
+ switch (pinfo->pseudo_header->atm.type) {
+
+ case TRAF_LLCMX:
+ call_dissector(llc_handle, next_tvb, pinfo, tree);
+ break;
+
+ case TRAF_LANE:
+ call_dissector(lane_handle, next_tvb, pinfo, tree);
+ break;
+
+ case TRAF_ILMI:
+ call_dissector(ilmi_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ if (tree) {
+ /* Dump it as raw data. */
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ break;
+ }
+ }
+ break;
+
+ default:
+ if (tree) {
+ /* Dump it as raw data. */
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ break;
+ }
+}
+
+/*
+ * Charles Michael Heard's HEC code, from
+ *
+ * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/32bitCRC.tutorial.html
+ *
+ * with the syndrome and error position tables initialized with values
+ * computed by his "gen_syndrome_table()" and "gen_err_posn_table()" routines,
+ * rather than by calling those routines at run time, and with various data
+ * type cleanups and changes not to correct the header if a correctible
+ * error was detected.
+ */
+#define COSET_LEADER 0x055 /* x^6 + x^4 + x^2 + 1 */
+
+static const guint8 syndrome_table[256] = {
+ 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15,
+ 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
+ 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
+ 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
+ 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5,
+ 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
+ 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85,
+ 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
+ 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
+ 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
+ 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2,
+ 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
+ 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32,
+ 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
+ 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
+ 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
+ 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c,
+ 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
+ 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec,
+ 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
+ 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
+ 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
+ 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
+ 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
+ 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b,
+ 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
+ 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
+ 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
+ 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb,
+ 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
+ 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb,
+ 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
+};
+
+#define NO_ERROR_DETECTED -128
+#define UNCORRECTIBLE_ERROR 128
+
+static const int err_posn_table[256] = {
+ NO_ERROR_DETECTED, 37,
+ 36, UNCORRECTIBLE_ERROR,
+ 35, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, 29,
+ 34, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, 6,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ 28, UNCORRECTIBLE_ERROR,
+ 33, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, 21,
+ 5, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ 27, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ 32, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ 20, UNCORRECTIBLE_ERROR,
+ 4, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ 26, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+ UNCORRECTIBLE_ERROR, UNCORRECTIBLE_ERROR,
+};
+
+/*
+ * Return an indication of whether there was an error in the cell header
+ * and, if so, where the error was, if it was correctable.
+ */
+static int
+get_header_err(const guint8 *cell_header)
+{
+ register guint8 syndrome;
+ register int i, err_posn;
+
+ syndrome = 0;
+ for (i = 0; i < 4; i++)
+ syndrome = syndrome_table[syndrome ^ cell_header[i]];
+ syndrome ^= cell_header[4] ^ COSET_LEADER;
+
+ err_posn = err_posn_table [syndrome];
+
+ if (err_posn < 0)
+ return NO_ERROR_DETECTED;
+ else if (err_posn < 40)
+ return err_posn;
+ else
+ return UNCORRECTIBLE_ERROR;
+}
+
+static const value_string pt_vals[] = {
+ { 0, "User data cell, congestion not experienced, SDU-type = 0" },
+ { 1, "User data cell, congestion not experienced, SDU-type = 1" },
+ { 2, "User data cell, congestion experienced, SDU-type = 0" },
+ { 3, "User data cell, congestion experienced, SDU-type = 1" },
+ { 4, "Segment OAM F5 flow related cell" },
+ { 5, "End-to-end OAM F5 flow related cell" },
+ { 0, NULL }
+};
+
+/*
+ * Charles Michael Heard's CRC-10 code, from
+ *
+ * http://cell-relay.indiana.edu/cell-relay/publications/software/CRC/crc10.html
+ *
+ * with the CRC table initialized with values computed by
+ * his "gen_byte_crc10_table()" routine, rather than by calling that
+ * routine at run time, and with various data type cleanups.
+ */
+static const guint16 byte_crc10_table[256] = {
+ 0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
+ 0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
+ 0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
+ 0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
+ 0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
+ 0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
+ 0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
+ 0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
+ 0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
+ 0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
+ 0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
+ 0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
+ 0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
+ 0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
+ 0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
+ 0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
+ 0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
+ 0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
+ 0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
+ 0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
+ 0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
+ 0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
+ 0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
+ 0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
+ 0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
+ 0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
+ 0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
+ 0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
+ 0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
+ 0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
+ 0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
+ 0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1,
+};
+
+/* update the data block's CRC-10 remainder one byte at a time */
+static guint16
+update_crc10_by_bytes(guint16 crc10_accum, const guint8 *data_blk_ptr,
+ int data_blk_size)
+{
+ register int i;
+
+ for (i = 0; i < data_blk_size; i++) {
+ crc10_accum = ((crc10_accum << 8) & 0x3ff)
+ ^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
+ ^ *data_blk_ptr++;
+ }
+ return crc10_accum;
+}
+
+static const value_string st_vals[] = {
+ { 2, "BOM" },
+ { 0, "COM" },
+ { 1, "EOM" },
+ { 3, "SSM" },
+ { 0, NULL }
+};
+
+#define OAM_TYPE_FM 1 /* Fault Management */
+#define OAM_TYPE_PM 2 /* Performance Management */
+#define OAM_TYPE_AD 8 /* Activation/Deactivation */
+
+static const value_string oam_type_vals[] = {
+ { OAM_TYPE_FM, "Fault Management" },
+ { OAM_TYPE_PM, "Performance Management" },
+ { OAM_TYPE_AD, "Activation/Deactivation" },
+ { 0, NULL }
+};
+
+static const value_string ft_fm_vals[] = {
+ { 0, "Alarm Indication Signal" },
+ { 1, "Far End Receive Failure" },
+ { 8, "OAM Cell Loopback" },
+ { 4, "Continuity Check" },
+ { 0, NULL }
+};
+
+static const value_string ft_pm_vals[] = {
+ { 0, "Forward Monitoring" },
+ { 1, "Backward Reporting" },
+ { 2, "Monitoring and Reporting" },
+ { 0, NULL }
+};
+
+static const value_string ft_ad_vals[] = {
+ { 0, "Performance Monitoring" },
+ { 1, "Continuity Check" },
+ { 0, NULL }
+};
+
+static void
+dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *atm_tree)
+{
+ int offset;
+ proto_tree *aal_tree;
+ proto_item *ti;
+ guint8 octet;
+ int err;
+ guint8 vpi;
+ guint16 vci;
+ guint16 aal3_4_hdr, aal3_4_trlr;
+ guint16 oam_crc;
+ gint length;
+ guint16 crc10;
+ tvbuff_t *next_tvb;
+
+ octet = tvb_get_guint8(tvb, 0);
+ proto_tree_add_text(atm_tree, tvb, 0, 1, "GFC: 0x%x", octet >> 4);
+ vpi = (octet & 0xF0) << 4;
+ octet = tvb_get_guint8(tvb, 1);
+ vpi |= octet >> 4;
+ proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
+ vci = (octet & 0x0F) << 12;
+ octet = tvb_get_guint8(tvb, 2);
+ vci |= octet << 4;
+ octet = tvb_get_guint8(tvb, 3);
+ vci |= octet >> 4;
+ proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
+ proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
+ val_to_str((octet >> 1) & 0x7, pt_vals, "Unknown (%u)"));
+ proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
+ (octet & 0x01) ? "Low priority" : "High priority");
+ ti = proto_tree_add_text(atm_tree, tvb, 4, 1, "Header Error Check: 0x%02x",
+ tvb_get_guint8(tvb, 4));
+ err = get_header_err(tvb_get_ptr(tvb, 0, 5));
+ if (err == NO_ERROR_DETECTED)
+ proto_item_append_text(ti, " (correct)");
+ else if (err == UNCORRECTIBLE_ERROR)
+ proto_item_append_text(ti, " (uncorrectable error)");
+ else
+ proto_item_append_text(ti, " (error in bit %d)", err);
+ offset = 5;
+
+ switch (pinfo->pseudo_header->atm.aal) {
+
+ case AAL_1:
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL1");
+ ti = proto_tree_add_item(tree, proto_aal1, tvb, offset, -1, FALSE);
+ aal_tree = proto_item_add_subtree(ti, ett_aal1);
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(aal_tree, tvb, offset, 1, "CSI: %u", octet >> 7);
+ proto_tree_add_text(aal_tree, tvb, offset, 1, "Sequence Count: %u",
+ (octet >> 4) & 0x7);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Sequence count = %u",
+ (octet >> 4) & 0x7);
+ }
+ proto_tree_add_text(aal_tree, tvb, offset, 1, "CRC: 0x%x",
+ (octet >> 1) & 0x7);
+ proto_tree_add_text(aal_tree, tvb, offset, 1, "Parity: %u",
+ octet & 0x1);
+ offset++;
+
+ proto_tree_add_text(aal_tree, tvb, offset, 47, "Payload");
+ break;
+
+ case AAL_3_4:
+ /*
+ * XXX - or should this be the CS PDU?
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AAL3/4");
+ ti = proto_tree_add_item(tree, proto_aal3_4, tvb, offset, -1, FALSE);
+ aal_tree = proto_item_add_subtree(ti, ett_aal3_4);
+ aal3_4_hdr = tvb_get_ntohs(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s, sequence number = %u",
+ val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"),
+ (aal3_4_hdr >> 10) & 0xF);
+ }
+ proto_tree_add_text(aal_tree, tvb, offset, 2, "Segment Type: %s",
+ val_to_str(aal3_4_hdr >> 14, st_vals, "Unknown (%u)"));
+ proto_tree_add_text(aal_tree, tvb, offset, 2, "Sequence Number: %u",
+ (aal3_4_hdr >> 10) & 0xF);
+ proto_tree_add_text(aal_tree, tvb, offset, 2, "Multiplex ID: %u",
+ aal3_4_hdr & 0x3FF);
+ offset += 2;
+
+ proto_tree_add_text(aal_tree, tvb, offset, 44, "Information");
+ offset += 44;
+
+ aal3_4_trlr = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(aal_tree, tvb, offset, 2, "Length Indicator: %u",
+ (aal3_4_trlr >> 10) & 0x3F);
+ length = tvb_length_remaining(tvb, 5);
+ crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
+ length);
+ proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC: 0x%03x (%s)",
+ aal3_4_trlr & 0x3FF,
+ (crc10 == 0) ? "correct" : "incorrect");
+ break;
+
+ case AAL_OAMCELL:
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
+ ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, FALSE);
+ aal_tree = proto_item_add_subtree(ti, ett_oamaal);
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(aal_tree, tvb, offset, 1, "OAM Type: %s",
+ val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
+ switch (octet >> 4) {
+
+ case OAM_TYPE_FM:
+ proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
+ val_to_str(octet & 0x0F, ft_fm_vals, "Unknown (%u)"));
+ break;
+
+ case OAM_TYPE_PM:
+ proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
+ val_to_str(octet & 0x0F, ft_pm_vals, "Unknown (%u)"));
+ break;
+
+ case OAM_TYPE_AD:
+ proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %s",
+ val_to_str(octet & 0x0F, ft_ad_vals, "Unknown (%u)"));
+ break;
+
+ default:
+ proto_tree_add_text(aal_tree, tvb, offset, 1, "Function Type: %u",
+ octet & 0x0F);
+ break;
+ }
+ offset += 1;
+
+ proto_tree_add_text(aal_tree, tvb, offset, 45, "Function-specific information");
+ offset += 45;
+
+ length = tvb_length_remaining(tvb, 5);
+ crc10 = update_crc10_by_bytes(0, tvb_get_ptr(tvb, 5, length),
+ length);
+ oam_crc = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(aal_tree, tvb, offset, 2, "CRC-10: 0x%03x (%s)",
+ oam_crc & 0x3FF,
+ (crc10 == 0) ? "correct" : "incorrect");
+ break;
+
+ default:
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ break;
+ }
+}
+
+static void
+dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean truncated)
+{
+ proto_tree *atm_tree = NULL;
+ proto_item *ti = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
+
+ switch (pinfo->pseudo_header->atm.channel) {
+
+ case 0:
+ /* Traffic from DTE to DCE. */
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
+ break;
+
+ case 1:
+ /* Traffic from DCE to DTE. */
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (pinfo->pseudo_header->atm.aal == AAL_5) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "AAL5 %s",
+ val_to_str(pinfo->pseudo_header->atm.type, aal5_hltype_vals,
+ "Unknown traffic type (%u)"));
+ } else {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
+ "Unknown AAL (%u)"));
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
+ atm_tree = proto_item_add_subtree(ti, ett_atm);
+
+ switch (pinfo->pseudo_header->atm.channel) {
+
+ case 0:
+ /* Traffic from DTE to DCE. */
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
+ break;
+
+ case 1:
+ /* Traffic from DCE to DTE. */
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
+ break;
+
+ default:
+ /* Sniffers shouldn't provide anything other than 0 or 1. */
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
+ pinfo->pseudo_header->atm.channel);
+ break;
+ }
+
+ proto_tree_add_uint_format(atm_tree, hf_atm_aal, tvb, 0, 0,
+ pinfo->pseudo_header->atm.aal,
+ "AAL: %s",
+ val_to_str(pinfo->pseudo_header->atm.aal, aal_vals,
+ "Unknown AAL (%u)"));
+ }
+ if (pinfo->pseudo_header->atm.flags & ATM_RAW_CELL) {
+ /* This is a single cell, with the cell header at the beginning. */
+ proto_item_set_len(ti, 5);
+ dissect_atm_cell(tvb, pinfo, tree, atm_tree);
+ } else {
+ /* This is a reassembled PDU. */
+ dissect_reassembled_pdu(tvb, pinfo, tree, atm_tree, truncated);
+ }
+}
+
+static void
+dissect_atm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_atm_common(tvb, pinfo, tree, TRUE);
+}
+
+static void
+dissect_atm_untruncated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_atm_common(tvb, pinfo, tree, FALSE);
+}
+
+void
+proto_register_atm(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_atm_aal,
+ { "AAL", "atm.aal", FT_UINT8, BASE_DEC, VALS(aal_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_atm_vpi,
+ { "VPI", "atm.vpi", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_atm_vci,
+ { "VCI", "atm.vci", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_atm,
+ &ett_ilmi,
+ &ett_aal1,
+ &ett_aal3_4,
+ &ett_oamaal,
+ &ett_atm_lane,
+ &ett_atm_lane_lc_lan_dest,
+ &ett_atm_lane_lc_lan_dest_rd,
+ &ett_atm_lane_lc_flags,
+ &ett_atm_lane_lc_tlv,
+ };
+ proto_atm = proto_register_protocol("ATM", "ATM", "atm");
+ proto_aal1 = proto_register_protocol("ATM AAL1", "AAL1", "aal1");
+ proto_aal3_4 = proto_register_protocol("ATM AAL3/4", "AAL3/4", "aal3_4");
+ proto_oamaal = proto_register_protocol("ATM OAM AAL", "OAM AAL", "oamaal");
+ proto_register_field_array(proto_atm, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ proto_ilmi = proto_register_protocol("ILMI", "ILMI", "ilmi");
+
+ register_dissector("ilmi", dissect_ilmi, proto_ilmi);
+
+ proto_atm_lane = proto_register_protocol("ATM LAN Emulation",
+ "ATM LANE", "lane");
+
+ register_dissector("lane", dissect_lane, proto_atm_lane);
+}
+
+void
+proto_reg_handoff_atm(void)
+{
+ dissector_handle_t atm_handle, atm_untruncated_handle;
+
+ /*
+ * Get handles for the Ethernet, Token Ring, LLC, SSCOP, LANE,
+ * and ILMI dissectors.
+ */
+ eth_handle = find_dissector("eth");
+ tr_handle = find_dissector("tr");
+ llc_handle = find_dissector("llc");
+ sscop_handle = find_dissector("sscop");
+ lane_handle = find_dissector("lane");
+ ilmi_handle = find_dissector("ilmi");
+ data_handle = find_dissector("data");
+
+ atm_handle = create_dissector_handle(dissect_atm, proto_atm);
+ dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS, atm_handle);
+
+ atm_untruncated_handle = create_dissector_handle(dissect_atm_untruncated,
+ proto_atm);
+ dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
+ atm_untruncated_handle);
+}
diff --git a/epan/dissectors/packet-atm.h b/epan/dissectors/packet-atm.h
new file mode 100644
index 0000000000..3e60eeeafe
--- /dev/null
+++ b/epan/dissectors/packet-atm.h
@@ -0,0 +1,30 @@
+/* packet-atm.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_ATM_H__
+#define __PACKET_ATM_H__
+
+void capture_atm(const union wtap_pseudo_header *, const guchar *, int,
+ packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-auto_rp.c b/epan/dissectors/packet-auto_rp.c
new file mode 100644
index 0000000000..2bfc62cfcf
--- /dev/null
+++ b/epan/dissectors/packet-auto_rp.c
@@ -0,0 +1,295 @@
+/* packet-auto_rp.c
+ * Routines for the Cisco Auto-RP protocol
+ * ftp://ftpeng.cisco.com/ftp/ipmulticast/specs/pim-autorp-spec01.txt
+ *
+ * Heikki Vatiainen <hessu@cs.tut.fi>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+
+static gint proto_auto_rp = -1;
+static gint ett_auto_rp = -1;
+static gint ett_auto_rp_ver_type = -1;
+static gint ett_auto_rp_map = -1;
+static gint ett_auto_rp_group = -1;
+
+static gint hf_auto_rp_version = -1;
+static gint hf_auto_rp_type = -1;
+static gint hf_auto_rp_count = -1;
+static gint hf_auto_rp_holdtime = -1;
+static gint hf_auto_rp_pim_ver = -1;
+static gint hf_auto_rp_rp_addr = -1;
+static gint hf_auto_rp_prefix_sgn = -1;
+static gint hf_auto_rp_mask_len = -1;
+static gint hf_auto_rp_group_prefix = -1;
+
+#define UDP_PORT_PIM_RP_DISC 496
+
+struct auto_rp_fixed_hdr {
+#define AUTO_RP_VERSION_MASK 0xf0
+#define AUTO_RP_TYPE_MASK 0x0f
+ guint8 ver_type; /* pim-autorp-spec01.txt defines version 1+ */
+ guint8 rp_count; /* Number of struct auto_rp_maps that follow the this header */
+ guint16 holdtime; /* Time in seconds this announcement is valid. 0 equals forever */
+ guint32 reserved;
+};
+
+struct auto_rp_map_hdr {
+ guint32 rp_address; /* The unicast IPv4 address of this RP */
+#define AUTO_RP_PIM_VER_MASK 0x03
+ guint8 pim_version; /* RP's highest PIM version. 2-bit field */
+ guint8 group_count; /* Number of encoded group addresses that follow this header */
+};
+
+struct auto_rp_enc_grp_hdr { /* Encoded group address */
+#define AUTO_RP_SIGN_MASK 0x01
+ guint8 prefix_sgn; /* 0 positive, 1 negative group prefix */
+ guint8 mask_len; /* Length of group prefix */
+ guint32 addr; /* Group prefix */
+};
+
+#define AUTO_RP_VER_1PLUS 1
+static const value_string auto_rp_ver_vals[] = {
+ {AUTO_RP_VER_1PLUS, "1 or 1+"},
+ {0, NULL}
+};
+
+#define AUTO_RP_TYPE_ANNOUNCEMENT 1
+#define AUTO_RP_TYPE_MAPPING 2
+static const value_string auto_rp_type_vals[] = {
+ {AUTO_RP_TYPE_ANNOUNCEMENT, "RP announcement"},
+ {AUTO_RP_TYPE_MAPPING, "RP mapping"},
+ {0, NULL}
+};
+
+#define AUTO_RP_PIM_VERSION_UNKNOWN 0x00
+#define AUTO_RP_PIM_VERSION_1 0x01
+#define AUTO_RP_PIM_VERSION_2 0x02
+#define AUTO_RP_PIM_VERSION_DUAL 0x03
+static const value_string auto_rp_pim_ver_vals[] = {
+ {AUTO_RP_PIM_VERSION_UNKNOWN, "Version unknown"},
+ {AUTO_RP_PIM_VERSION_1, "Version 1"},
+ {AUTO_RP_PIM_VERSION_2, "Version 2"},
+ {AUTO_RP_PIM_VERSION_DUAL, "Dual version 1 and 2"},
+ {0, NULL}
+};
+
+#define AUTO_RP_GROUP_MASK_SIGN_POS 0
+#define AUTO_RP_GROUP_MASK_SIGN_NEG 1
+static const value_string auto_rp_mask_sign_vals[] = {
+ {AUTO_RP_GROUP_MASK_SIGN_POS, "Positive group prefix"},
+ {AUTO_RP_GROUP_MASK_SIGN_NEG, "Negative group prefix"},
+ {0, NULL}
+};
+
+static int do_auto_rp_map(tvbuff_t *tvb, int offset, proto_tree *auto_rp_tree);
+
+static void dissect_auto_rp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 ver_type, rp_count;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Auto-RP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ver_type = tvb_get_guint8(tvb, 0);
+ rp_count = tvb_get_guint8(tvb, 1);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (v%s) for %u RP%s",
+ val_to_str(lo_nibble(ver_type), auto_rp_type_vals, "Unknown"),
+ val_to_str(hi_nibble(ver_type), auto_rp_ver_vals, "Unknown"),
+ rp_count, plurality(rp_count, "", "s"));
+
+ if (tree) {
+ proto_item *ti, *tv;
+ proto_tree *auto_rp_tree, *ver_type_tree;
+ int i, offset;
+ guint16 holdtime;
+
+ offset = 0;
+ ti = proto_tree_add_item(tree, proto_auto_rp, tvb, offset, -1, FALSE);
+ auto_rp_tree = proto_item_add_subtree(ti, ett_auto_rp);
+
+ tv = proto_tree_add_text(auto_rp_tree, tvb, offset, 1, "Version: %s, Packet type: %s",
+ val_to_str(hi_nibble(ver_type), auto_rp_ver_vals, "Unknown"),
+ val_to_str(lo_nibble(ver_type), auto_rp_type_vals, "Unknown"));
+ ver_type_tree = proto_item_add_subtree(tv, ett_auto_rp_ver_type);
+ proto_tree_add_uint(ver_type_tree, hf_auto_rp_version, tvb, offset, 1, ver_type);
+ proto_tree_add_uint(ver_type_tree, hf_auto_rp_type, tvb, offset, 1, ver_type);
+ offset++;
+
+ proto_tree_add_uint(auto_rp_tree, hf_auto_rp_count, tvb, offset, 1, rp_count);
+ offset++;
+
+ holdtime = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint_format(auto_rp_tree, hf_auto_rp_holdtime, tvb, offset, 2, holdtime,
+ "Holdtime: %u second%s", holdtime, plurality(holdtime, "", "s"));
+ offset+=2;
+
+ proto_tree_add_text(auto_rp_tree, tvb, offset, 4, "Reserved: 0x%x", tvb_get_ntohs(tvb, offset));
+ offset+=4;
+
+ for (i = 0; i < rp_count; i++)
+ offset = do_auto_rp_map(tvb, offset, auto_rp_tree);
+
+ if (tvb_offset_exists(tvb, offset))
+ proto_tree_add_text(tree, tvb, offset, -1, "Trailing junk");
+ }
+
+ return;
+}
+
+void proto_register_auto_rp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_auto_rp_version,
+ {"Protocol version", "auto_rp.version",
+ FT_UINT8, BASE_DEC, VALS(auto_rp_ver_vals), AUTO_RP_VERSION_MASK,
+ "Auto-RP protocol version", HFILL }},
+
+ { &hf_auto_rp_type,
+ {"Packet type", "auto_rp.type",
+ FT_UINT8, BASE_DEC, VALS(auto_rp_type_vals), AUTO_RP_TYPE_MASK,
+ "Auto-RP packet type", HFILL }},
+
+ { &hf_auto_rp_count,
+ {"RP count", "auto_rp.rp_count",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "The number of RP addresses contained in this message", HFILL }},
+
+ { &hf_auto_rp_holdtime,
+ {"Holdtime", "auto_rp.holdtime",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "The amount of time in seconds this announcement is valid", HFILL }},
+
+ { &hf_auto_rp_pim_ver,
+ {"Version", "auto_rp.pim_ver",
+ FT_UINT8, BASE_DEC, VALS(auto_rp_pim_ver_vals), AUTO_RP_PIM_VER_MASK,
+ "RP's highest PIM version", HFILL }},
+
+ { &hf_auto_rp_rp_addr,
+ {"RP address", "auto_rp.rp_addr",
+ FT_IPv4, 0, NULL, 0,
+ "The unicast IP address of the RP", HFILL }},
+
+ { &hf_auto_rp_prefix_sgn,
+ {"Sign", "auto_rp.prefix_sign",
+ FT_UINT8, BASE_DEC, VALS(auto_rp_mask_sign_vals), AUTO_RP_SIGN_MASK,
+ "Group prefix sign", HFILL }},
+
+ { &hf_auto_rp_mask_len,
+ {"Mask length", "auto_rp.mask_len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of group prefix", HFILL }},
+
+ { &hf_auto_rp_group_prefix,
+ {"Prefix", "auto_rp.group_prefix",
+ FT_IPv4, 0, NULL, 0,
+ "Group prefix", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_auto_rp,
+ &ett_auto_rp_ver_type,
+ &ett_auto_rp_map,
+ &ett_auto_rp_group
+ };
+
+ proto_auto_rp = proto_register_protocol("Cisco Auto-RP",
+ "Auto-RP", "auto_rp");
+ proto_register_field_array(proto_auto_rp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ return;
+}
+
+void
+proto_reg_handoff_auto_rp(void)
+{
+ dissector_handle_t auto_rp_handle;
+
+ auto_rp_handle = create_dissector_handle(dissect_auto_rp,
+ proto_auto_rp);
+ dissector_add("udp.port", UDP_PORT_PIM_RP_DISC, auto_rp_handle);
+}
+
+/*
+ * Handles one Auto-RP map entry. Returns the new offset.
+ */
+static int do_auto_rp_map(tvbuff_t *tvb, int offset, proto_tree *auto_rp_tree)
+{
+ proto_item *ti;
+ proto_tree *map_tree;
+ guint8 group_count;
+ guint32 rp_addr; /* In network byte order */
+ int i;
+
+ tvb_memcpy(tvb, (guint8 *)&rp_addr, offset, 4);
+ group_count = tvb_get_guint8(tvb, offset + 5);
+
+ /* sizeof map header + n * sizeof encoded group addresses */
+ ti = proto_tree_add_text(auto_rp_tree, tvb, offset, 6 + group_count * 6,
+ "RP %s: %u group%s", ip_to_str((void *)&rp_addr),
+ group_count, plurality(group_count, "", "s"));
+ map_tree = proto_item_add_subtree(ti, ett_auto_rp_map);
+
+ proto_tree_add_ipv4(map_tree, hf_auto_rp_rp_addr, tvb, offset, 4, rp_addr);
+ offset += 4;
+ proto_tree_add_uint(map_tree, hf_auto_rp_pim_ver, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ offset++;
+ proto_tree_add_text(map_tree, tvb, offset, 1, "Number of groups this RP maps to: %u", group_count);
+ offset++;
+
+ for (i = 0; i < group_count; i++) {
+ proto_item *gi;
+ proto_tree *grp_tree;
+ guint8 sign, mask_len;
+ guint32 group_addr; /* In network byte order */
+
+ sign = tvb_get_guint8(tvb, offset);
+ mask_len = tvb_get_guint8(tvb, offset + 1);
+ tvb_memcpy(tvb, (guint8 *)&group_addr, offset + 2, 4);
+ gi = proto_tree_add_text(map_tree, tvb, offset, 6, "Group %s/%u (%s)",
+ ip_to_str((void *)&group_addr), mask_len,
+ val_to_str(sign&AUTO_RP_SIGN_MASK, auto_rp_mask_sign_vals, ""));
+ grp_tree = proto_item_add_subtree(gi, ett_auto_rp_group);
+
+ proto_tree_add_uint(grp_tree, hf_auto_rp_prefix_sgn, tvb, offset, 1, sign);
+ offset++;
+ proto_tree_add_uint(grp_tree, hf_auto_rp_mask_len, tvb, offset, 1, mask_len);
+ offset++;
+ proto_tree_add_ipv4(grp_tree, hf_auto_rp_group_prefix, tvb, offset, 4, group_addr);
+ offset += 4;
+
+ }
+
+ return offset;
+}
diff --git a/epan/dissectors/packet-bacapp.c b/epan/dissectors/packet-bacapp.c
new file mode 100644
index 0000000000..b89a5051c6
--- /dev/null
+++ b/epan/dissectors/packet-bacapp.c
@@ -0,0 +1,122 @@
+/* packet-bacapp.c
+ * Routines for BACnet (APDU) dissection
+ * Copyright 2001, Hartmut Mueller <hartmut@abmlinux.org>, FH Dortmund
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer,v 1.23
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+static const char*
+bacapp_type_name (guint8 bacapp_type){
+ static const char *type_names[] = {
+ "Confirmed-Request-PDU",
+ "Unconfirmed-Request-PDU",
+ "SimpleACK-PDU",
+ "ComplexACK-PDU",
+ "SegmentACK-PDU",
+ "Error-PDU",
+ "Reject-PDU",
+ "Abort-PDU"
+ };
+ return (bacapp_type > 7)? "unknown PDU" : type_names[bacapp_type];
+}
+
+static int proto_bacapp = -1;
+static int hf_bacapp_type = -1;
+
+static gint ett_bacapp = -1;
+
+static dissector_handle_t data_handle;
+
+static void
+dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *bacapp_tree;
+ guint8 offset;
+ guint8 bacapp_type;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-APDU");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "BACnet APDU ");
+
+ offset = 0;
+ bacapp_type = (tvb_get_guint8(tvb, offset) >> 4) & 0x0f;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(%s)",
+ bacapp_type_name(bacapp_type));
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, FALSE);
+
+ bacapp_tree = proto_item_add_subtree(ti, ett_bacapp);
+
+ proto_tree_add_uint_format(bacapp_tree, hf_bacapp_type, tvb,
+ offset, 1, bacapp_type, "APDU Type: %u (%s)", bacapp_type,
+ bacapp_type_name(bacapp_type));
+ offset ++;
+
+ }
+ next_tvb = tvb_new_subset(tvb,offset,-1,-1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+}
+
+
+void
+proto_register_bacapp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bacapp_type,
+ { "APDU Type", "bacapp.bacapp_type",
+ FT_UINT8, BASE_DEC, NULL, 0xf0, "APDU Type", HFILL }
+ },
+ };
+ static gint *ett[] = {
+ &ett_bacapp,
+ };
+ proto_bacapp = proto_register_protocol("Building Automation and Control Network APDU",
+ "BACapp", "bacapp");
+ proto_register_field_array(proto_bacapp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("bacapp", dissect_bacapp, proto_bacapp);
+}
+
+void
+proto_reg_handoff_bacapp(void)
+{
+ data_handle = find_dissector("data");
+}
+
diff --git a/epan/dissectors/packet-bacnet.c b/epan/dissectors/packet-bacnet.c
new file mode 100644
index 0000000000..46053b7e5a
--- /dev/null
+++ b/epan/dissectors/packet-bacnet.c
@@ -0,0 +1,595 @@
+/* packet-bacnet.c
+ * Routines for BACnet (NPDU) dissection
+ * Copyright 2001, Hartmut Mueller <hartmut@abmlinux.org>, FH Dortmund
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer,v 1.23
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#include "llcsaps.h"
+
+static dissector_handle_t bacapp_handle;
+static dissector_handle_t data_handle;
+
+static const char*
+bacnet_mesgtyp_name (guint8 bacnet_mesgtyp){
+ static const char *type_names[] = {
+ "Who-Is-Router-To-Network",
+ "I-Am-Router-To-Network",
+ "I-Could-Be-Router-To-Network",
+ "Reject-Message-To-Network",
+ "Router-Busy-To-Network",
+ "Router-Available-To-Network",
+ "Initialize-Routing-Table",
+ "Initialize-Routing-Table-Ack",
+ "Establish-Connection-To-Network",
+ "Disconnect-Connection-To-Network"
+ };
+ if(bacnet_mesgtyp < 0x0a) {
+ return type_names[bacnet_mesgtyp];
+ } else {
+ return (bacnet_mesgtyp < 0x80)? "Reserved for Use by ASHRAE" : "Vendor Proprietary Message";
+ }
+}
+
+static const char*
+bacnet_rejectreason_name (guint8 bacnet_rejectreason) {
+ static const char *type_names[] = {
+ "Other error.",
+ "The router is not directly connected to DNET and cannot find a router to DNET on any directly connected network using Who-Is-Router-To-Network messages.",
+ "The router is busy and unable to accept messages for the specified DNET at the present time.",
+ "It is an unknown network layer message type.",
+ "The message is too long to be routed to this DNET.",
+ "The router is no longer directly connected to DNET but can reconnect if requested.",
+ "The router is no longer directly connected to DNET and cannot reconnect even if requested."
+ };
+ return (bacnet_rejectreason > 6)? "Invalid Rejection Reason.": type_names[bacnet_rejectreason];
+}
+
+/* Network Layer Control Information */
+#define BAC_CONTROL_NET 0x80
+#define BAC_CONTROL_RES1 0x40
+#define BAC_CONTROL_DEST 0x20
+#define BAC_CONTROL_RES2 0x10
+#define BAC_CONTROL_SRC 0x08
+#define BAC_CONTROL_EXPECT 0x04
+#define BAC_CONTROL_PRIO_HIGH 0x02
+#define BAC_CONTROL_PRIO_LOW 0x01
+
+/* Network Layer Message Types */
+#define BAC_NET_WHO_R 0x00
+#define BAC_NET_IAM_R 0x01
+#define BAC_NET_ICB_R 0x02
+#define BAC_NET_REJ 0x03
+#define BAC_NET_R_BUSY 0x04
+#define BAC_NET_R_AVA 0x05
+#define BAC_NET_INIT_RTAB 0x06
+#define BAC_NET_INIT_RTAB_ACK 0x07
+#define BAC_NET_EST_CON 0x08
+#define BAC_NET_DISC_CON 0x09
+
+static const true_false_string control_net_set_high = {
+ "network layer message, message type field present.",
+ "BACnet APDU, message type field absent."
+};
+
+static const true_false_string control_res_high = {
+ "Shall be zero, but is one.",
+ "Shall be zero and is zero."
+};
+static const true_false_string control_dest_high = {
+ "DNET, DLEN and Hop Count present. If DLEN=0: broadcast, dest. address field absent.",
+ "DNET, DLEN, DADR and Hop Count absent."
+};
+
+static const true_false_string control_src_high = {
+ "SNET, SLEN and SADR present, SLEN=0 invalid, SLEN specifies length of SADR",
+ "SNET, SLEN and SADR absent"
+};
+
+static const true_false_string control_expect_high = {
+ "BACnet-Confirmed-Request-PDU, a segment of BACnet-ComplexACK-PDU or Network Message expecting a reply present.",
+ "Other than a BACnet-Confirmed-Request-PDU, segment of BACnet-ComplexACK-PDU or network layer message expecting a reply present."
+};
+
+static const true_false_string control_prio_high_high = {
+ "Life Safety or Critical Equipment message.",
+ "Not a Life Safety or Critical Equipment message."
+};
+
+static const true_false_string control_prio_low_high = {
+ "Urgent message",
+ "Normal message"
+};
+
+
+static int proto_bacnet = -1;
+static int hf_bacnet_version = -1;
+static int hf_bacnet_control = -1;
+static int hf_bacnet_control_net = -1;
+static int hf_bacnet_control_res1 = -1;
+static int hf_bacnet_control_dest = -1;
+static int hf_bacnet_control_res2 = -1;
+static int hf_bacnet_control_src = -1;
+static int hf_bacnet_control_expect = -1;
+static int hf_bacnet_control_prio_high = -1;
+static int hf_bacnet_control_prio_low = -1;
+static int hf_bacnet_dnet = -1;
+static int hf_bacnet_dlen = -1;
+static int hf_bacnet_dadr_eth = -1;
+static int hf_bacnet_dadr_tmp = -1;
+static int hf_bacnet_snet = -1;
+static int hf_bacnet_slen = -1;
+static int hf_bacnet_sadr_eth = -1;
+static int hf_bacnet_sadr_tmp = -1;
+static int hf_bacnet_hopc = -1;
+static int hf_bacnet_mesgtyp = -1;
+static int hf_bacnet_vendor = -1;
+static int hf_bacnet_perf = -1;
+static int hf_bacnet_rejectreason = -1;
+static int hf_bacnet_rportnum = -1;
+static int hf_bacnet_portid = -1;
+static int hf_bacnet_pinfolen = -1;
+static int hf_bacnet_pinfo = -1;
+
+static gint ett_bacnet = -1;
+static gint ett_bacnet_control = -1;
+
+static void
+dissect_bacnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_item *ct;
+ proto_tree *bacnet_tree;
+ proto_tree *control_tree;
+
+ gint offset;
+ guint8 bacnet_version;
+ guint8 bacnet_control;
+ guint8 bacnet_dlen;
+ guint8 bacnet_slen;
+ guint8 bacnet_mesgtyp;
+ guint8 bacnet_rejectreason;
+ guint8 bacnet_rportnum;
+ guint8 bacnet_pinfolen;
+ guint8 i;
+ guint8 j;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-NPDU");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Building Automation and Control Network NPDU");
+
+ offset = 0;
+ bacnet_version = tvb_get_guint8(tvb, offset);
+ bacnet_control = tvb_get_guint8(tvb, offset+1);
+ bacnet_dlen = 0;
+ bacnet_slen = 0;
+ bacnet_mesgtyp = 0;
+ bacnet_rejectreason = 0;
+ bacnet_rportnum = 0;
+ bacnet_pinfolen =0;
+ i = 0;
+ j = 0;
+
+/* I don't know the length of the NPDU by now. Setting the length after dissection */
+ ti = proto_tree_add_item(tree, proto_bacnet, tvb, 0, -1, FALSE);
+
+ bacnet_tree = proto_item_add_subtree(ti, ett_bacnet);
+
+ proto_tree_add_uint_format(bacnet_tree, hf_bacnet_version, tvb,
+ offset, 1,
+ bacnet_version,"Version: 0x%02x (%s)",bacnet_version,
+ (bacnet_version == 0x01)?"ASHRAE 135-1995":"unknown");
+ offset ++;
+ ct = proto_tree_add_uint(bacnet_tree, hf_bacnet_control,
+ tvb, offset, 1, bacnet_control);
+ control_tree = proto_item_add_subtree(ct, ett_bacnet_control);
+ proto_tree_add_boolean(control_tree, hf_bacnet_control_net,
+ tvb, offset, 1, bacnet_control);
+ proto_tree_add_boolean(control_tree, hf_bacnet_control_res1, tvb,
+ offset, 1, bacnet_control);
+ proto_tree_add_boolean(control_tree, hf_bacnet_control_dest, tvb,
+ offset, 1, bacnet_control);
+ proto_tree_add_boolean(control_tree, hf_bacnet_control_res2, tvb,
+ offset, 1, bacnet_control);
+ proto_tree_add_boolean(control_tree, hf_bacnet_control_src, tvb,
+ offset, 1, bacnet_control);
+ proto_tree_add_boolean(control_tree, hf_bacnet_control_expect, tvb,
+ offset, 1, bacnet_control);
+ proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_high,
+ tvb, offset, 1, bacnet_control);
+ proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_low,
+ tvb, offset, 1, bacnet_control);
+ offset ++;
+ if (bacnet_control & BAC_CONTROL_DEST) { /* DNET, DLEN, DADR */
+ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ bacnet_dlen = tvb_get_guint8(tvb, offset);
+ /* DLEN = 0 is broadcast on dest.network */
+ if( bacnet_dlen == 0) {
+ /* append to hf_bacnet_dlen: broadcast */
+ proto_tree_add_uint_format(bacnet_tree,
+ hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen,
+ "Destination MAC Layer Address Length: %d indicates Broadcast on Destination Network",
+ bacnet_dlen);
+ offset ++;
+ /* going to SNET */
+ } else if (bacnet_dlen==6) {
+ proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen,
+ tvb, offset, 1, bacnet_dlen);
+ offset ++;
+ /* Ethernet MAC */
+ proto_tree_add_item(bacnet_tree,
+ hf_bacnet_dadr_eth, tvb, offset,
+ bacnet_dlen, FALSE);
+ offset += bacnet_dlen;
+ } else if (bacnet_dlen<7) {
+ proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen,
+ tvb, offset, 1, bacnet_dlen);
+ offset ++;
+ /* Other MAC formats should be included here */
+ proto_tree_add_item(bacnet_tree,
+ hf_bacnet_dadr_tmp, tvb, offset,
+ bacnet_dlen, FALSE);
+ offset += bacnet_dlen;
+ } else {
+ proto_tree_add_uint_format(bacnet_tree,
+ hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen,
+ "Destination MAC Layer Address Length: %d invalid!",
+ bacnet_dlen);
+ }
+ }
+ if (bacnet_control & BAC_CONTROL_SRC) { /* SNET, SLEN, SADR */
+ /* SNET */
+ proto_tree_add_uint(bacnet_tree, hf_bacnet_snet,
+ tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ bacnet_slen = tvb_get_guint8(tvb, offset);
+ if( bacnet_slen == 0) { /* SLEN = 0 invalid */
+ proto_tree_add_uint_format(bacnet_tree,
+ hf_bacnet_slen, tvb, offset, 1, bacnet_slen,
+ "Source MAC Layer Address Length: %d invalid!",
+ bacnet_slen);
+ offset ++;
+ } else if (bacnet_slen==6) {
+ /* SLEN */
+ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen,
+ tvb, offset, 1, bacnet_slen);
+ offset ++;
+ /* Ethernet MAC */
+ proto_tree_add_item(bacnet_tree,
+ hf_bacnet_sadr_eth, tvb, offset,
+ bacnet_slen, FALSE);
+ offset += bacnet_slen;
+ } else if (bacnet_slen<6) { /* LON,ARCNET,MS/TP MAC */
+ /* SLEN */
+ proto_tree_add_uint(bacnet_tree, hf_bacnet_slen,
+ tvb, offset, 1, bacnet_slen);
+ offset ++;
+ /* Other MAC formats should be included here */
+ proto_tree_add_item(bacnet_tree,
+ hf_bacnet_sadr_tmp, tvb, offset,
+ bacnet_slen, FALSE);
+ offset += bacnet_slen;
+ } else {
+ proto_tree_add_uint_format(bacnet_tree,
+ hf_bacnet_slen, tvb, offset, 1, bacnet_slen,
+ "Source MAC Layer Address Length: %d invalid!",
+ bacnet_slen);
+ offset ++;
+ }
+ }
+ if (bacnet_control & BAC_CONTROL_DEST) { /* Hopcount */
+ proto_tree_add_item(bacnet_tree, hf_bacnet_hopc,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ }
+ /* Network Layer Message Type */
+ if (bacnet_control & BAC_CONTROL_NET) {
+ bacnet_mesgtyp = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(bacnet_tree,
+ hf_bacnet_mesgtyp, tvb, offset, 1, bacnet_mesgtyp,
+ "Network Layer Message Type: %02x (%s)", bacnet_mesgtyp,
+ bacnet_mesgtyp_name(bacnet_mesgtyp));
+ offset ++;
+ }
+ /* Vendor ID
+ * The standard says: "If Bit 7 of the control octet is 1 and
+ * the Message Type field contains a value in the range
+ * X'80' - X'FF', then a Vendor ID field shall be present (...)."
+ * We should not go any further in dissecting the packet if it's
+ * not present, but we don't know about that: No length field...
+ */
+ if ((bacnet_mesgtyp > 0x7f) && (bacnet_control == BAC_CONTROL_NET)) {
+ proto_tree_add_item(bacnet_tree, hf_bacnet_vendor,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ /* attention: doesnt work here because of if(tree) */
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+ /* Performance Index (in I-Could-Be-Router-To-Network) */
+ if (bacnet_mesgtyp == BAC_NET_ICB_R) {
+ proto_tree_add_item(bacnet_tree, hf_bacnet_perf,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ }
+ /* Reason, DNET (in Reject-Message-To-Network) */
+ if (bacnet_mesgtyp == BAC_NET_REJ) {
+ bacnet_rejectreason = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(bacnet_tree,
+ hf_bacnet_rejectreason,
+ tvb, offset, 1,
+ bacnet_rejectreason, "Rejection Reason: %d (%s)",
+ bacnet_rejectreason,
+ bacnet_rejectreason_name(bacnet_rejectreason));
+ offset ++;
+ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ /* N*DNET (in Router-Busy-To-Network,Router-Available-To-Network) */
+ if ((bacnet_mesgtyp == BAC_NET_R_BUSY) ||
+ (bacnet_mesgtyp == BAC_NET_R_AVA) || (bacnet_mesgtyp == BAC_NET_IAM_R) ) {
+ while(tvb_reported_length_remaining(tvb, offset) > 1 ) {
+ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ }
+ /* Initialize-Routing-Table */
+ if ( (bacnet_mesgtyp == BAC_NET_INIT_RTAB) ||
+ (bacnet_mesgtyp == BAC_NET_INIT_RTAB_ACK) ) {
+ bacnet_rportnum = tvb_get_guint8(tvb, offset);
+ /* number of ports */
+ proto_tree_add_uint(bacnet_tree, hf_bacnet_rportnum,
+ tvb, offset, 1, bacnet_rportnum);
+ offset ++;
+ for(i=0; i>bacnet_rportnum; i++) {
+ /* Connected DNET */
+ proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ /* Port ID */
+ proto_tree_add_item(bacnet_tree, hf_bacnet_portid,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ /* Port Info Length */
+ bacnet_pinfolen = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(bacnet_tree, hf_bacnet_pinfolen,
+ tvb, offset, 1, bacnet_pinfolen);
+ offset ++;
+ for(j=0; j>bacnet_pinfolen; j++){
+ /* Port Info */
+ proto_tree_add_item(bacnet_tree, hf_bacnet_pinfo,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ }
+ }
+ }
+ proto_item_set_len(ti, offset);
+
+/* dissect BACnet APDU
+ */
+ next_tvb = tvb_new_subset(tvb,offset,-1,-1);
+ if (bacnet_control & BAC_CONTROL_NET) {
+ /* Unknown function - dissect the payload as data */
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ } else {
+ /* APDU - call the APDU dissector */
+ call_dissector(bacapp_handle, next_tvb, pinfo, tree);
+ }
+}
+
+void
+proto_register_bacnet(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bacnet_version,
+ { "Version", "bacnet.version",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "BACnet Version", HFILL }
+ },
+ { &hf_bacnet_control,
+ { "Control", "bacnet.control",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "BACnet Control", HFILL }
+ },
+ { &hf_bacnet_control_net,
+ { "NSDU contains",
+ "bacnet.control_net",
+ FT_BOOLEAN, 8, TFS(&control_net_set_high),
+ BAC_CONTROL_NET, "BACnet Control", HFILL }
+ },
+ { &hf_bacnet_control_res1,
+ { "Reserved",
+ "bacnet.control_res1",
+ FT_BOOLEAN, 8, TFS(&control_res_high),
+ BAC_CONTROL_RES1, "BACnet Control", HFILL }
+ },
+ { &hf_bacnet_control_dest,
+ { "Destination Specifier",
+ "bacnet.control_dest",
+ FT_BOOLEAN, 8, TFS(&control_dest_high),
+ BAC_CONTROL_DEST, "BACnet Control", HFILL }
+ },
+ { &hf_bacnet_control_res2,
+ { "Reserved",
+ "bacnet.control_res2",
+ FT_BOOLEAN, 8, TFS(&control_res_high),
+ BAC_CONTROL_RES2, "BACnet Control", HFILL }
+ },
+ { &hf_bacnet_control_src,
+ { "Source specifier",
+ "bacnet.control_src",
+ FT_BOOLEAN, 8, TFS(&control_src_high),
+ BAC_CONTROL_SRC, "BACnet Control", HFILL }
+ },
+ { &hf_bacnet_control_expect,
+ { "Expecting Reply",
+ "bacnet.control_expect",
+ FT_BOOLEAN, 8, TFS(&control_expect_high),
+ BAC_CONTROL_EXPECT, "BACnet Control", HFILL }
+ },
+ { &hf_bacnet_control_prio_high,
+ { "Priority",
+ "bacnet.control_prio_high",
+ FT_BOOLEAN, 8, TFS(&control_prio_high_high),
+ BAC_CONTROL_PRIO_HIGH, "BACnet Control", HFILL }
+ },
+ { &hf_bacnet_control_prio_low,
+ { "Priority",
+ "bacnet.control_prio_low",
+ FT_BOOLEAN, 8, TFS(&control_prio_low_high),
+ BAC_CONTROL_PRIO_LOW, "BACnet Control", HFILL }
+ },
+ { &hf_bacnet_dnet,
+ { "Destination Network Address", "bacnet.dnet",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Destination Network Address", HFILL }
+ },
+ { &hf_bacnet_dlen,
+ { "Destination MAC Layer Address Length", "bacnet.dlen",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Destination MAC Layer Address Length", HFILL }
+ },
+ { &hf_bacnet_dadr_eth,
+ { "Destination ISO 8802-3 MAC Address", "bacnet.dadr_eth",
+ FT_ETHER, BASE_HEX, NULL, 0,
+ "Destination ISO 8802-3 MAC Address", HFILL }
+ },
+ { &hf_bacnet_dadr_tmp,
+ { "Unknown Destination MAC", "bacnet.dadr_tmp",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Unknown Destination MAC", HFILL }
+ },
+ { &hf_bacnet_snet,
+ { "Source Network Address", "bacnet.snet",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Source Network Address", HFILL }
+ },
+ { &hf_bacnet_slen,
+ { "Source MAC Layer Address Length", "bacnet.slen",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Source MAC Layer Address Length", HFILL }
+ },
+ { &hf_bacnet_sadr_eth,
+ { "SADR", "bacnet.sadr_eth",
+ FT_ETHER, BASE_HEX, NULL, 0,
+ "Source ISO 8802-3 MAC Address", HFILL }
+ },
+ { &hf_bacnet_sadr_tmp,
+ { "Unknown Source MAC", "bacnet.sadr_tmp",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Unknown Source MAC", HFILL }
+ },
+ { &hf_bacnet_hopc,
+ { "Hop Count", "bacnet.hopc",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Hop Count", HFILL }
+ },
+ { &hf_bacnet_mesgtyp,
+ { "Message Type", "bacnet.mesgtyp",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Message Type", HFILL }
+ },
+ { &hf_bacnet_vendor,
+ { "Vendor ID", "bacnet.vendor",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Vendor ID", HFILL }
+ },
+ { &hf_bacnet_perf,
+ { "Performance Index", "bacnet.perf",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Performance Index", HFILL }
+ },
+ { &hf_bacnet_rejectreason,
+ { "Reject Reason", "bacnet.rejectreason",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Reject Reason", HFILL }
+ },
+ { &hf_bacnet_rportnum,
+ { "Number of Port Mappings", "bacnet.rportnum",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Number of Port Mappings", HFILL }
+ },
+ { &hf_bacnet_pinfolen,
+ { "Port Info Length", "bacnet.pinfolen",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Port Info Length", HFILL }
+ },
+ { &hf_bacnet_portid,
+ { "Port ID", "bacnet.portid",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Port ID", HFILL }
+ },
+ { &hf_bacnet_pinfo,
+ { "Port Info", "bacnet.pinfo",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Port Info", HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_bacnet,
+ &ett_bacnet_control,
+ };
+
+ proto_bacnet = proto_register_protocol("Building Automation and Control Network NPDU",
+ "BACnet", "bacnet");
+
+ proto_register_field_array(proto_bacnet, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("bacnet", dissect_bacnet, proto_bacnet);
+}
+
+void
+proto_reg_handoff_bacnet(void)
+{
+ dissector_handle_t bacnet_handle;
+
+ bacnet_handle = find_dissector("bacnet");
+ dissector_add("bvlc.function", 0x04, bacnet_handle);
+ dissector_add("bvlc.function", 0x09, bacnet_handle);
+ dissector_add("bvlc.function", 0x0a, bacnet_handle);
+ dissector_add("bvlc.function", 0x0b, bacnet_handle);
+ dissector_add("llc.dsap", SAP_BACNET, bacnet_handle);
+ bacapp_handle = find_dissector("bacapp");
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-beep.c b/epan/dissectors/packet-beep.c
new file mode 100644
index 0000000000..7b02f1ce17
--- /dev/null
+++ b/epan/dissectors/packet-beep.c
@@ -0,0 +1,1121 @@
+/* packet-beep.c
+ * Routines for BEEP packet disassembly
+ *
+ * $Id$
+ *
+ * Copyright (c) 2000 by Richard Sharpe <rsharpe@ns.aus.com>
+ * Modified 2001 Darren New <dnew@invisible.net> for BEEP.
+ *
+ * Original BXXP dissector developed with funding from InvisibleWorlds
+ * (www.invisibleworlds.com) via Collab.Net.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs
+ * Copyright 1999 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "prefs.h"
+#include <epan/conversation.h>
+
+#define TCP_PORT_BEEP 10288
+void proto_reg_handoff_beep(void);
+
+
+static int global_beep_tcp_port = TCP_PORT_BEEP;
+static int global_beep_strict_term = TRUE;
+
+static int proto_beep = -1;
+
+static int hf_beep_req = -1;
+static int hf_beep_req_chan = -1;
+static int hf_beep_rsp_chan = -1;
+static int hf_beep_seq_chan = -1;
+static int hf_beep_rsp = -1;
+static int hf_beep_seq = -1;
+static int hf_beep_end = -1;
+static int hf_beep_proto_viol = -1;
+static int hf_beep_complete = -1; /* No More data follows */
+static int hf_beep_intermediate = -1; /* More data follows */
+static int hf_beep_msgno = -1;
+static int hf_beep_ansno = -1;
+static int hf_beep_seqno = -1;
+static int hf_beep_size = -1;
+static int hf_beep_channel = -1;
+static int hf_beep_positive = -1;
+static int hf_beep_negative = -1;
+static int hf_beep_ackno = -1;
+static int hf_beep_window = -1;
+
+/* Arrays of hf entry pointers for some routines to use. If you want more
+ * hidden items added for a field, add them to the list before the NULL,
+ * and the various routines that these are passed to will add them.
+ */
+
+static int *req_msgno_hfa[] = { &hf_beep_msgno, NULL };
+static int *req_ansno_hfa[] = { &hf_beep_ansno, NULL };
+static int *req_seqno_hfa[] = { &hf_beep_seqno, NULL };
+static int *req_size_hfa[] = { &hf_beep_size, NULL };
+static int *req_chan_hfa[] = { &hf_beep_channel, &hf_beep_req_chan, NULL };
+/*
+static int *rsp_msgno_hfa[] = { &hf_beep_msgno, NULL };
+static int *rsp_seqno_hfa[] = { &hf_beep_seqno, NULL };
+static int *rsp_size_hfa[] = { &hf_beep_size, NULL };
+*/
+static int *seq_chan_hfa[] = { &hf_beep_channel, &hf_beep_seq_chan, NULL };
+static int *seq_ackno_hfa[] = { &hf_beep_ackno, NULL };
+static int *seq_window_hfa[] = { &hf_beep_window, NULL };
+
+static int ett_beep = -1;
+static int ett_mime_header = -1;
+static int ett_header = -1;
+static int ett_trailer = -1;
+
+static unsigned int tcp_port = 0;
+
+/* Get the state of the more flag ... */
+
+#define BEEP_VIOL 0
+#define BEEP_INTERMEDIATE 1
+#define BEEP_COMPLETE 2
+
+/*
+ * Per-frame data
+ *
+ * pl_left is the amount of data in this packet that belongs to another
+ * frame ...
+ *
+ * It relies on TCP segments not being re-ordered too much ...
+ */
+struct beep_proto_data {
+ int pl_left; /* Payload at beginning of frame */
+ int pl_size; /* Payload in current message ...*/
+ int mime_hdr; /* Whether we expect a mime header. 1 on first, 0 on rest
+ * in a message
+ */
+};
+
+/*
+ * Conversation stuff
+ */
+static int beep_packet_init_count = 100;
+
+struct beep_request_key {
+ guint32 conversation;
+};
+
+struct beep_request_val {
+ guint16 processed; /* Have we processed this conversation? */
+ int size; /* Size of the message */
+ /* We need an indication in each dirn of
+ * whether on not a mime header is expected
+ */
+ int c_mime_hdr, s_mime_hdr;
+};
+
+static GHashTable *beep_request_hash = NULL;
+static GMemChunk *beep_request_keys = NULL;
+static GMemChunk *beep_request_vals = NULL;
+static GMemChunk *beep_packet_infos = NULL;
+
+/* Hash Functions */
+static gint
+beep_equal(gconstpointer v, gconstpointer w)
+{
+ const struct beep_request_key *v1 = (const struct beep_request_key *)v;
+ const struct beep_request_key *v2 = (const struct beep_request_key *)w;
+
+#if defined(DEBUG_BEEP_HASH)
+ printf("Comparing %08X\n and %08X\n",
+ v1->conversation, v2->conversation);
+#endif
+
+ if (v1->conversation == v2->conversation)
+ return 1;
+
+ return 0;
+
+}
+
+static guint
+beep_hash(gconstpointer v)
+{
+ const struct beep_request_key *key = (const struct beep_request_key *)v;
+ guint val;
+
+ val = key->conversation;
+
+#if defined(DEBUG_BEEP_HASH)
+ printf("BEEP Hash calculated as %u\n", val);
+#endif
+
+ return val;
+
+}
+
+static void
+beep_init_protocol(void)
+{
+#if defined(DEBUG_BEEP_HASH)
+ fprintf(stderr, "Initializing BEEP hashtable area\n");
+#endif
+
+ if (beep_request_hash)
+ g_hash_table_destroy(beep_request_hash);
+ if (beep_request_keys)
+ g_mem_chunk_destroy(beep_request_keys);
+ if (beep_request_vals)
+ g_mem_chunk_destroy(beep_request_vals);
+ if (beep_packet_infos)
+ g_mem_chunk_destroy(beep_packet_infos);
+
+ beep_request_hash = g_hash_table_new(beep_hash, beep_equal);
+ beep_request_keys = g_mem_chunk_new("beep_request_keys",
+ sizeof(struct beep_request_key),
+ beep_packet_init_count * sizeof(struct beep_request_key), G_ALLOC_AND_FREE);
+ beep_request_vals = g_mem_chunk_new("beep_request_vals",
+ sizeof(struct beep_request_val),
+ beep_packet_init_count * sizeof(struct beep_request_val), G_ALLOC_AND_FREE);
+ beep_packet_infos = g_mem_chunk_new("beep_packet_infos",
+ sizeof(struct beep_proto_data),
+ beep_packet_init_count * sizeof(struct beep_proto_data), G_ALLOC_AND_FREE);
+}
+
+/*
+ * BEEP routines
+ */
+
+static int beep_get_more(char more)
+{
+
+ if (more == '.')
+ return BEEP_COMPLETE;
+ else if (more == '*')
+ return BEEP_INTERMEDIATE;
+
+ return BEEP_VIOL;
+}
+
+/* dissect the more flag, and return a value of:
+ * 1 -> more
+ * 0 -> no more
+ * -1 -> Proto violation
+ */
+
+static int
+dissect_beep_more(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+
+
+ switch (beep_get_more(tvb_get_guint8(tvb, offset))) {
+
+ case BEEP_COMPLETE:
+
+ if (tree) {
+ proto_tree_add_boolean_hidden(tree, hf_beep_complete, tvb, offset, 1, TRUE);
+ proto_tree_add_text(tree, tvb, offset, 1, "More: Complete");
+ }
+
+ return 0;
+
+ break;
+
+ case BEEP_INTERMEDIATE:
+
+ if (tree) {
+ proto_tree_add_boolean_hidden(tree, hf_beep_intermediate, tvb, offset, 1, TRUE);
+ proto_tree_add_text(tree, tvb, offset, 1, "More: Intermediate");
+ }
+
+ return 1;
+
+ break;
+
+ default:
+
+ if (tree) {
+ proto_tree_add_boolean_hidden(tree, hf_beep_proto_viol, tvb, offset, 1, TRUE);
+ proto_tree_add_text(tree, tvb, offset, 1, "PROTOCOL VIOLATION: Expected More Flag (* or .)");
+ }
+
+ return -1;
+
+ break;
+ }
+
+}
+
+#if 0
+static void dissect_beep_status(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+
+ /* FIXME: We should return a value to indicate all OK. */
+
+ switch(tvb_get_guint8(tvb, offset)) {
+
+ case '+':
+
+ if (tree) {
+ proto_tree_add_boolean_hidden(tree, hf_beep_positive, tvb, offset, 1, TRUE);
+ proto_tree_add_text(tree, tvb, offset, 1, "Status: Positive");
+ }
+
+ break;
+
+ case '-':
+
+ if (tree) {
+ proto_tree_add_boolean_hidden(tree, hf_beep_negative, tvb, offset, 1, TRUE);
+ proto_tree_add_text(tree, tvb, offset, 1, "Status: Negative");
+ }
+
+ break;
+
+ default: /* Proto violation: FIXME */
+
+ break;
+
+ }
+
+}
+#endif
+
+static int num_len(tvbuff_t *tvb, int offset)
+{
+ unsigned int i = 0;
+
+ while (isdigit(tvb_get_guint8(tvb, offset + i))) i++;
+
+ return i;
+
+}
+
+/*
+ * We check for a terminator. This can be CRLF, which will be recorded
+ * as a terminator, or CR or LF by itself, which will be redorded as
+ * an incorrect terminator ... We build the tree at this point
+ * However, we depend on the variable beep_strict_term
+ */
+
+static int
+check_term(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+
+ /* First, check for CRLF, or, if global_beep_strict_term is false,
+ * one of CR or LF ... If neither of these hold, we add an element
+ * that complains of a protocol violation, and return -1, else
+ * we add a terminator to the tree (possibly non-standard) and return
+ * the count of characters we saw ... This may throw off the rest of the
+ * dissection ... so-be-it!
+ */
+
+ if ((tvb_get_guint8(tvb, offset) == 0x0d &&
+ tvb_get_guint8(tvb, offset + 1) == 0x0a)){ /* Correct terminator */
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 2, "Terminator: CRLF");
+ }
+ return 2;
+
+ }
+ else if ((tvb_get_guint8(tvb, offset) == 0x0d) && !global_beep_strict_term) {
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1, "Nonstandard Terminator: CR");
+ proto_tree_add_boolean_hidden(tree, hf_beep_proto_viol, tvb, offset, 1, TRUE);
+ }
+ return 1;
+
+ }
+ else if ((tvb_get_guint8(tvb, offset) == 0x0a) && !global_beep_strict_term) {
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1, "Nonstandard Terminator: LF");
+ proto_tree_add_boolean_hidden(tree, hf_beep_proto_viol, tvb, offset, 1, TRUE);
+ }
+ return 1;
+
+ }
+ else {
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 2, "PROTOCOL VIOLATION, Invalid Terminator: %s", tvb_format_text(tvb, offset, 2));
+ proto_tree_add_boolean_hidden(tree, hf_beep_proto_viol, tvb, offset, 2, TRUE);
+ }
+ return -1;
+
+ }
+
+}
+
+/* Get the header length, up to CRLF or CR or LF */
+static int header_len(tvbuff_t *tvb, int offset)
+{
+ int i = 0;
+ guint8 sc;
+
+ /* FIXME: Have to make sure we stop looking at the end of the tvb ... */
+
+ /* We look for CRLF, or CR or LF if global_beep_strict_term is
+ * not set.
+ */
+
+ while (1) {
+
+ if ((sc = tvb_get_guint8(tvb, offset + i)) == 0x0d
+ && tvb_get_guint8(tvb, offset + i + 1) == 0x0a)
+ return i; /* Done here ... */
+
+ if (!global_beep_strict_term && (sc == 0x0d || sc == 0x0a))
+ return i; /* Done here also ... */
+
+ i++;
+
+ }
+}
+
+static int
+dissect_beep_mime_header(tvbuff_t *tvb, int offset,
+ struct beep_proto_data *frame_data,
+ proto_tree *tree)
+{
+ proto_tree *ti = NULL, *mime_tree = NULL;
+ int mime_length = header_len(tvb, offset), cc = 0;
+
+ if (frame_data && !frame_data->mime_hdr) return 0;
+
+ if (tree) {
+
+ /* FIXME: Should calculate the whole length of the mime headers */
+
+ ti = proto_tree_add_text(tree, tvb, offset, mime_length, "Mime header: %s", tvb_format_text(tvb, offset, mime_length));
+ mime_tree = proto_item_add_subtree(ti, ett_mime_header);
+ }
+
+ if (mime_length == 0) { /* Default header */
+
+ if (tree) {
+ proto_tree_add_text(mime_tree, tvb, offset, 0, "Default values");
+ }
+
+ if ((cc = check_term(tvb, offset, mime_tree)) <= 0) {
+
+ /* Ignore it, it will cause funnies in the rest of the dissect */
+
+ }
+
+ }
+ else { /* FIXME: Process the headers */
+
+ if (tree) {
+ proto_tree_add_text(mime_tree, tvb, offset, mime_length, "Header: %s",
+ tvb_format_text(tvb, offset, mime_length));
+ }
+
+ if ((cc = check_term(tvb, offset + mime_length, mime_tree)) <= 0) {
+
+ /* Ignore it, it will cause funnies in the rest of the dissect */
+
+ }
+
+ }
+
+ return mime_length + cc; /* FIXME: Check that the CRLF is there */
+
+}
+
+static int
+dissect_beep_int(tvbuff_t *tvb, int offset,
+ proto_tree *tree, int hf, int *val, int *hfa[])
+{
+ int ival, ind = 0;
+ unsigned int i = num_len(tvb, offset);
+ guint8 int_buff[100];
+
+ memset(int_buff, '\0', sizeof(int_buff));
+
+ tvb_memcpy(tvb, int_buff, offset, MIN(sizeof(int_buff) - 1, i));
+
+ /* XXX - is this still "Dangerous" now that we don't copy to the
+ last byte of "int_buff[]"? */
+ sscanf(int_buff, "%d", &ival);
+
+ if (tree) {
+ proto_tree_add_uint(tree, hf, tvb, offset, i, ival);
+ }
+
+ while (hfa[ind]) {
+
+ proto_tree_add_uint_hidden(tree, *hfa[ind], tvb, offset, i, ival);
+ ind++;
+
+ }
+
+ *val = ival; /* Return the value */
+
+ return i;
+
+}
+
+static void
+set_mime_hdr_flags(int more, struct beep_request_val *request_val,
+ struct beep_proto_data *frame_data, packet_info *pinfo)
+{
+
+ if (!request_val) return; /* Nothing to do ??? */
+
+ if (pinfo->destport == tcp_port) { /* Going to the server ... client */
+
+ if (request_val->c_mime_hdr) {
+
+ frame_data->mime_hdr = 0;
+
+ if (!more) request_val->c_mime_hdr = 0;
+
+ }
+ else {
+
+ frame_data->mime_hdr = 1;
+
+ if (more) request_val->c_mime_hdr = 1;
+
+ }
+
+ }
+ else {
+
+ if (request_val->s_mime_hdr) {
+
+ frame_data->mime_hdr = 0;
+
+ if (!more) request_val->s_mime_hdr = 0;
+
+ }
+ else {
+
+ frame_data->mime_hdr = 1;
+
+ if (more) request_val->s_mime_hdr = 1;
+
+ }
+
+ }
+
+}
+
+/* Build the tree
+ *
+ * A return value of <= 0 says we bailed out, skip the rest of this message,
+ * if any.
+ *
+ * A return value > 0 is the count of bytes we consumed ...
+ */
+
+static int
+dissect_beep_tree(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, struct beep_request_val *request_val,
+ struct beep_proto_data *frame_data)
+{
+ proto_tree *ti = NULL, *hdr = NULL;
+ int st_offset, msgno, ansno, seqno, size, channel, ackno, window, cc,
+ more;
+
+ char * cmd_temp = NULL;
+ int is_ANS = 0;
+ st_offset = offset;
+
+ if (tvb_strneql(tvb, offset, "MSG ", 4) == 0)
+ cmd_temp = "Command: MSG";
+ if (tvb_strneql(tvb, offset, "RPY ", 4) == 0)
+ cmd_temp = "Command: RPY";
+ if (tvb_strneql(tvb, offset, "ERR ", 4) == 0)
+ cmd_temp = "Command: ERR";
+ if (tvb_strneql(tvb, offset, "NUL ", 4) == 0)
+ cmd_temp = "Command: NUL";
+ if (tvb_strneql(tvb, offset, "ANS ", 4) == 0) {
+ cmd_temp = "Command: ANS";
+ is_ANS = 1;
+ }
+
+ if (cmd_temp != NULL) {
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, header_len(tvb, offset) + 2, "Header");
+
+ hdr = proto_item_add_subtree(ti, ett_header);
+
+ proto_tree_add_boolean_hidden(hdr, hf_beep_req, tvb, offset, 3, TRUE);
+ proto_tree_add_text(hdr, tvb, offset, 3, cmd_temp);
+ }
+
+ offset += 4;
+
+ /* Get the channel */
+ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_channel, &channel, req_chan_hfa);
+ offset += 1; /* Skip the space */
+
+ /* Dissect the message number */
+ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_msgno, &msgno, req_msgno_hfa);
+ offset += 1; /* skip the space */
+
+ /* Insert the more elements ... */
+ if ((more = dissect_beep_more(tvb, offset, hdr)) >= 0) {
+ /* Figure out which direction this is in and what mime_hdr flag to
+ * add to the frame_data. If there are missing segments, this code
+ * will get it wrong!
+ */
+ set_mime_hdr_flags(more, request_val, frame_data, pinfo);
+ }
+ else { /* Protocol violation, so dissect rest as undisectable */
+ if (tree) {
+ proto_tree_add_text(hdr, tvb, offset,
+ tvb_length_remaining(tvb, offset),
+ "Undissected Payload: %s",
+ tvb_format_text(tvb, offset,
+ tvb_length_remaining(tvb, offset)
+ )
+ );
+
+ }
+ return -1;
+ }
+
+ offset += 2; /* Skip the flag and the space ... */
+
+ /* now for the seqno */
+ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_seqno, &seqno, req_seqno_hfa);
+ offset += 1; /* skip the space */
+
+ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_size, &size, req_size_hfa);
+ if (request_val) /* FIXME, is this the right order ... */
+ request_val -> size = size; /* Stash this away */
+ else {
+ frame_data->pl_size = size;
+ if (frame_data->pl_size < 0) frame_data->pl_size = 0; /* FIXME: OK? */
+ }
+ /* offset += 1; skip the space */
+
+ if (is_ANS) { /* We need to put in the ansno */
+ offset += 1; /* skip the space */
+ /* Dissect the message number */
+ offset += dissect_beep_int(tvb, offset, hdr, hf_beep_ansno, &ansno, req_ansno_hfa);
+ }
+
+ if ((cc = check_term(tvb, offset, hdr)) <= 0) {
+
+ /* We dissect the rest as data and bail ... */
+
+ if (tree) {
+ proto_tree_add_text(hdr, tvb, offset,
+ tvb_length_remaining(tvb, offset),
+ "Undissected Payload: %s",
+ tvb_format_text(tvb, offset,
+ tvb_length_remaining(tvb, offset)
+ )
+ );
+ }
+
+ return -1;
+
+ }
+
+ offset += cc;
+
+ /* Insert MIME header ... */
+
+ if (frame_data && frame_data->mime_hdr)
+ offset += dissect_beep_mime_header(tvb, offset, frame_data, hdr);
+
+ /* Now for the payload, if any */
+
+ if (tvb_length_remaining(tvb, offset) > 0) { /* Dissect what is left as payload */
+
+ int pl_size = MIN(size, tvb_length_remaining(tvb, offset));
+
+ /* Except, check the payload length, and only dissect that much */
+
+ /* We need to keep track, in the conversation, of how much is left
+ * so in the next packet, we can figure out what is part of the payload
+ * and what is the next message
+ */
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, pl_size, "Payload: %s", tvb_format_text(tvb, offset, pl_size));
+
+ }
+
+ offset += pl_size;
+
+ if (request_val) {
+ request_val->size -= pl_size;
+ if (request_val->size < 0) request_val->size = 0;
+ }
+ else {
+ frame_data->pl_size -= pl_size;
+ if (frame_data->pl_size < 0) frame_data->pl_size = 0;
+ }
+ }
+
+ /* If anything else left, dissect it ... */
+
+ if (tvb_length_remaining(tvb, offset) > 0)
+ offset += dissect_beep_tree(tvb, offset, pinfo, tree, request_val, frame_data);
+
+ } else if (tvb_strneql(tvb, offset, "SEQ ", 4) == 0) {
+
+ if (tree) {
+ proto_tree_add_boolean_hidden(tree, hf_beep_seq, tvb, offset, 3, TRUE);
+ proto_tree_add_text(tree, tvb, offset, 3, "Command: SEQ");
+ }
+
+ offset += 3;
+
+ /* Now check the space: FIXME */
+
+ offset += 1;
+
+ offset += dissect_beep_int(tvb, offset, tree, hf_beep_channel, &channel, seq_chan_hfa);
+
+ /* Check the space: FIXME */
+
+ offset += 1;
+
+ offset += dissect_beep_int(tvb, offset, tree, hf_beep_ackno, &ackno, seq_ackno_hfa);
+
+ /* Check the space: FIXME */
+
+ offset += 1;
+
+ offset += dissect_beep_int(tvb, offset, tree, hf_beep_window, &window, seq_window_hfa);
+
+ if ((cc = check_term(tvb, offset, tree)) <= 0) {
+
+ /* We dissect the rest as data and bail ... */
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset,
+ tvb_length_remaining(tvb, offset),
+ "Undissected Payload: %s",
+ tvb_format_text(tvb, offset,
+ tvb_length_remaining(tvb, offset)
+ )
+ );
+ }
+
+ return -1;
+
+ }
+
+ offset += cc;
+
+ } else if (tvb_strneql(tvb, offset, "END", 3) == 0) {
+
+ proto_tree *tr = NULL;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, MIN(5, tvb_length_remaining(tvb, offset)), "Trailer");
+
+ tr = proto_item_add_subtree(ti, ett_trailer);
+
+ proto_tree_add_boolean_hidden(tr, hf_beep_end, tvb, offset, 3, TRUE);
+ proto_tree_add_text(tr, tvb, offset, 3, "Command: END");
+
+ }
+
+ offset += 3;
+
+ if ((cc = check_term(tvb, offset, tr)) <= 0) {
+
+ /* We dissect the rest as data and bail ... */
+
+ if (tree) {
+ proto_tree_add_text(tr, tvb, offset, tvb_length_remaining(tvb, offset),
+ "Undissected Payload: %s",
+ tvb_format_text(tvb, offset,
+ tvb_length_remaining(tvb, offset)
+ )
+ );
+ }
+
+ return -1;
+
+ }
+
+ offset += cc;
+
+ }
+
+ if (tvb_length_remaining(tvb, offset) > 0) { /* Dissect anything left over */
+
+ int pl_size = 0;
+
+ if (request_val) {
+
+ pl_size = MIN(request_val->size, tvb_length_remaining(tvb, offset));
+
+ if (pl_size == 0) { /* The whole of the rest must be payload */
+
+ pl_size = tvb_length_remaining(tvb, offset); /* Right place ? */
+
+ }
+
+ } else if (frame_data) {
+ pl_size = MIN(frame_data->pl_size, tvb_length_remaining(tvb, offset));
+ } else { /* Just in case */
+ pl_size = tvb_length_remaining(tvb, offset);
+ }
+
+ /* Take care here to handle the payload correctly, and if there is
+ * another message here, then handle it correctly as well.
+ */
+
+ /* If the pl_size == 0 and the offset == 0?, then we have not processed
+ * anything in this frame above, so we better treat all this data as
+ * payload to avoid recursion loops
+ */
+
+ if (pl_size == 0 && offset == st_offset)
+ pl_size = tvb_length_remaining(tvb, offset);
+
+ if (pl_size > 0) {
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, pl_size, "Payload: %s",
+ tvb_format_text(tvb, offset, pl_size));
+ }
+
+ offset += pl_size; /* Advance past the payload */
+
+ if (request_val){
+ request_val->size -= pl_size; /* Reduce payload by what we added */
+ if (request_val->size < 0) request_val->size = 0;
+ }
+ else {
+ frame_data->pl_size -= pl_size;
+ if (frame_data->pl_size < 0) frame_data->pl_size = 0;
+ }
+ }
+
+ if (tvb_length_remaining(tvb, offset) > 0) {
+ offset += dissect_beep_tree(tvb, offset, pinfo, tree, request_val, frame_data);
+ }
+ }
+
+ return offset - st_offset;
+
+}
+
+static void
+dissect_beep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset;
+ struct beep_proto_data *frame_data = NULL;
+ proto_tree *beep_tree = NULL, *ti = NULL;
+ conversation_t *conversation = NULL;
+ struct beep_request_key request_key, *new_request_key;
+ struct beep_request_val *request_val = NULL;
+
+ offset = 0;
+
+ /* If we have per frame data, use that, else, we must have lost the per-
+ * frame data, and we have to do a full dissect pass again.
+ *
+ * The per-frame data tells us how much of this frame is left over from a
+ * previous frame, so we dissect it as payload and then try to dissect the
+ * rest.
+ *
+ * We use the conversation to build up info on the first pass over the
+ * packets of type BEEP, and record anything that is needed if the user
+ * does random dissects of packets in per packet data.
+ *
+ * Once we have per-packet data, we don't need the conversation stuff
+ * anymore, but if per-packet data and conversation stuff gets deleted, as
+ * it does under some circumstances when a rescan is done, it all gets
+ * rebuilt.
+ */
+
+ /* Find out what conversation this packet is part of ... but only
+ * if we have no information on this packet, so find the per-frame
+ * info first.
+ */
+
+ frame_data = p_get_proto_data(pinfo->fd, proto_beep);
+
+ if (!frame_data) {
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL) { /* No conversation, create one */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ }
+
+ /*
+ * Check for and insert an entry in the request table if does not exist
+ */
+ request_key.conversation = conversation->index;
+
+ request_val = (struct beep_request_val *)g_hash_table_lookup(beep_request_hash, &request_key);
+
+ if (!request_val) { /* Create one */
+
+ new_request_key = g_mem_chunk_alloc(beep_request_keys);
+ new_request_key->conversation = conversation->index;
+
+ request_val = g_mem_chunk_alloc(beep_request_vals);
+ request_val->processed = 0;
+ request_val->size = 0;
+
+ g_hash_table_insert(beep_request_hash, new_request_key, request_val);
+
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BEEP");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) { /* Check the type ... */
+
+ /* "tvb_format_text()" is passed a value that won't go past the end
+ * of the packet, so it won't throw an exception. */
+ col_add_str(pinfo->cinfo, COL_INFO, tvb_format_text(tvb, offset, tvb_length_remaining(tvb, offset)));
+
+ }
+
+ /* Here, we parse the message so we can retrieve the info we need, which
+ * is that there is some payload left from a previous segment on the
+ * front of this segment ... This all depends on TCP segments not getting
+ * out of order ...
+ *
+ * As a huge kludge, we push the checking for the tree down into the code
+ * and process as if we were given a tree but not call the routines that
+ * adorn the protocol tree if they were NULL.
+ */
+
+ if (tree) { /* Build the tree info ... */
+
+ ti = proto_tree_add_item(tree, proto_beep, tvb, offset, -1, FALSE);
+
+ beep_tree = proto_item_add_subtree(ti, ett_beep);
+
+ }
+
+ /* Check the per-frame data and the conversation for any left-over
+ * payload from the previous frame
+ *
+ * We check that per-frame data exists first, and if so, use it,
+ * else we use the conversation data.
+ *
+ * We create per-frame data here as well, but we must ensure we create it
+ * after we have done the check for per-frame or conversation data.
+ *
+ * We also depend on the first frame in a group having a pl_size of 0.
+ */
+
+ if (frame_data && frame_data->pl_left > 0) {
+
+ int pl_left = frame_data->pl_left;
+
+ pl_left = MIN(pl_left, tvb_length_remaining(tvb, offset));
+
+ /* Add the payload bit, only if we have a tree */
+ if (tree) {
+ proto_tree_add_text(beep_tree, tvb, offset, pl_left, "Payload: %s",
+ tvb_format_text(tvb, offset, pl_left));
+ }
+ offset += pl_left;
+ }
+ else if (request_val && request_val->size > 0) {
+
+ int pl_left = request_val->size;
+
+ request_val->size = 0;
+
+ /* We create the frame data here for this case, and
+ * elsewhere for other frames
+ */
+
+ frame_data = g_mem_chunk_alloc(beep_packet_infos);
+
+ frame_data->pl_left = pl_left;
+ frame_data->pl_size = 0;
+ frame_data->mime_hdr = 0;
+
+ p_add_proto_data(pinfo->fd, proto_beep, frame_data);
+
+ }
+
+ /* Set up the per-frame data here if not already done so
+ * This _must_ come after the checks above ...
+ */
+
+ if (frame_data == NULL) {
+
+ frame_data = g_mem_chunk_alloc(beep_packet_infos);
+
+ frame_data->pl_left = 0;
+ frame_data->pl_size = 0;
+ frame_data->mime_hdr = 0;
+
+ p_add_proto_data(pinfo->fd, proto_beep, frame_data);
+
+ }
+
+ if (tvb_length_remaining(tvb, offset) > 0) {
+
+ offset += dissect_beep_tree(tvb, offset, pinfo, beep_tree, request_val, frame_data);
+
+ }
+
+}
+
+/* Register all the bits needed with the filtering engine */
+
+void
+proto_register_beep(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_beep_proto_viol,
+ { "Protocol Violation", "beep.violation", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_req,
+ { "Request", "beep.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_req_chan,
+ { "Request Channel Number", "beep.req.channel", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_rsp,
+ { "Response", "beep.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_rsp_chan,
+ { "Response Channel Number", "beep.rsp.channel", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_seq,
+ { "Sequence", "beep.seq", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_seq_chan,
+ { "Sequence Channel Number", "beep.seq.channel", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_end,
+ { "End", "beep.end", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_complete,
+ { "Complete", "beep.more.complete", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_intermediate,
+ { "Intermediate", "beep.more.intermediate", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_msgno,
+ { "Msgno", "beep.msgno", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_ansno,
+ { "Ansno", "beep.ansno", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_seqno,
+ { "Seqno", "beep.seqno", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_size,
+ { "Size", "beep.size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_channel,
+ { "Channel", "beep.channel", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_negative,
+ { "Negative", "beep.status.negative", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_positive,
+ { "Positive", "beep.status.positive", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_ackno,
+ { "Ackno", "beep.seq.ackno", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_beep_window,
+ { "Window", "beep.seq.window", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_beep,
+ &ett_mime_header,
+ &ett_header,
+ &ett_trailer,
+ };
+ module_t *beep_module;
+
+ proto_beep = proto_register_protocol("Blocks Extensible Exchange Protocol",
+ "BEEP", "beep");
+
+ proto_register_field_array(proto_beep, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&beep_init_protocol);
+
+ /* Register our configuration options for BEEP, particularly our port */
+
+ beep_module = prefs_register_protocol(proto_beep, proto_reg_handoff_beep);
+
+ prefs_register_uint_preference(beep_module, "tcp.port", "BEEP TCP Port",
+ "Set the port for BEEP messages (if other"
+ " than the default of 10288)",
+ 10, &global_beep_tcp_port);
+
+ prefs_register_bool_preference(beep_module, "strict_header_terminator",
+ "BEEP Header Requires CRLF",
+ "Specifies that BEEP requires CRLF as a "
+ "terminator, and not just CR or LF",
+ &global_beep_strict_term);
+}
+
+/* The registration hand-off routine */
+void
+proto_reg_handoff_beep(void)
+{
+ static int beep_prefs_initialized = FALSE;
+ static dissector_handle_t beep_handle;
+
+ if (!beep_prefs_initialized) {
+
+ beep_handle = create_dissector_handle(dissect_beep, proto_beep);
+
+ beep_prefs_initialized = TRUE;
+
+ }
+ else {
+
+ dissector_delete("tcp.port", tcp_port, beep_handle);
+
+ }
+
+ /* Set our port number for future use */
+
+ tcp_port = global_beep_tcp_port;
+
+ dissector_add("tcp.port", global_beep_tcp_port, beep_handle);
+
+}
diff --git a/epan/dissectors/packet-ber.c b/epan/dissectors/packet-ber.c
new file mode 100644
index 0000000000..b681b9bdc0
--- /dev/null
+++ b/epan/dissectors/packet-ber.c
@@ -0,0 +1,1054 @@
+/* packet-ber.c
+ * Helpers for ASN.1/BER dissection
+ * Ronnie Sahlberg (C) 2004
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * ITU-T Recommendation X.690 (07/2002),
+ * Information technology ASN.1 encoding rules:
+ * Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#include <epan/strutil.h>
+#include <epan/int-64bit.h>
+#include "prefs.h"
+#include "packet-ber.h"
+
+
+static gint proto_ber = -1;
+static gint hf_ber_id_class = -1;
+static gint hf_ber_id_pc = -1;
+static gint hf_ber_id_uni_tag = -1;
+static gint hf_ber_id_tag = -1;
+static gint hf_ber_length = -1;
+static gint hf_ber_bitstring_padding = -1;
+
+static gint ett_ber_octet_string = -1;
+
+static gboolean show_internal_ber_fields = FALSE;
+
+proto_item *ber_last_created_item=NULL;
+
+
+static const value_string ber_class_codes[] = {
+ { BER_CLASS_UNI, "Universal" },
+ { BER_CLASS_APP, "Application" },
+ { BER_CLASS_CON, "Context Specific" },
+ { BER_CLASS_PRI, "Private" },
+ { 0, NULL }
+};
+
+static const true_false_string ber_pc_codes = {
+ "Constructed Encoding",
+ "Primitive Encoding"
+};
+
+static const value_string ber_uni_tag_codes[] = {
+ { BER_UNI_TAG_EOC , "'end-of-content'" },
+ { BER_UNI_TAG_BOOLEAN , "BOOLEAN" },
+ { BER_UNI_TAG_INTEGER , "INTEGER" },
+ { BER_UNI_TAG_BITSTRING , "BIT STRING" },
+ { BER_UNI_TAG_OCTETSTRING , "OCTET STRING" },
+ { BER_UNI_TAG_NULL , "NULL" },
+ { BER_UNI_TAG_OID , "OBJECT IDENTIFIER" },
+ { BER_UNI_TAG_ObjectDescriptor, "ObjectDescriptor" },
+ { BER_UNI_TAG_REAL , "REAL" },
+ { BER_UNI_TAG_ENUMERATED , "ENUMERATED" },
+ { BER_UNI_TAG_EMBEDDED_PDV , "EMBEDDED PDV" },
+ { BER_UNI_TAG_UTF8String , "UTF8String" },
+ { BER_UNI_TAG_RELATIVE_OID , "RELATIVE-OID" },
+ { BER_UNI_TAG_SEQUENCE , "SEQUENCE, SEQUENCE OF" },
+ { BER_UNI_TAG_SET , "SET, SET OF" },
+ { BER_UNI_TAG_NumericString , "NumericString" },
+ { BER_UNI_TAG_PrintableString , "PrintableString" },
+ { BER_UNI_TAG_TeletextString , "TeletextString, T61String" },
+ { BER_UNI_TAG_VideotexString , "VideotexString" },
+ { BER_UNI_TAG_IA5String , "IA5String" },
+ { BER_UNI_TAG_UTCTime , "UTCTime" },
+ { BER_UNI_TAG_GeneralizedTime , "GeneralizedTime" },
+ { BER_UNI_TAG_GraphicString , "GraphicString" },
+ { BER_UNI_TAG_VisibleString , "VisibleString, ISO64String" },
+ { BER_UNI_TAG_GeneralString , "GeneralString" },
+ { BER_UNI_TAG_UniversalString , "UniversalString" },
+ { BER_UNI_TAG_CHARACTERSTRING , "CHARACTER STRING" },
+ { BER_UNI_TAG_BMPString , "BMPString" },
+ { 0, NULL }
+};
+
+
+proto_item *get_ber_last_created_item(void) {
+ return ber_last_created_item;
+}
+
+static int dissect_ber_sq_of(gboolean implicit_tag, guint32 type, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, ber_sequence *seq, gint hf_id, gint ett_id);
+
+/* 8.1 General rules for encoding */
+
+/* 8.1.2 Identifier octets */
+int get_ber_identifier(tvbuff_t *tvb, int offset, guint8 *class, gboolean *pc, guint32 *tag) {
+ guint8 id, t;
+ guint8 tmp_class;
+ gboolean tmp_pc;
+ guint32 tmp_tag;
+
+ id = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ /* 8.1.2.2 */
+ tmp_class = (id>>6) & 0x03;
+ tmp_pc = (id>>5) & 0x01;
+ tmp_tag = id&0x1F;
+ /* 8.1.2.4 */
+ if (tmp_tag == 0x1F) {
+ tmp_tag = 0;
+ while (tvb_length_remaining(tvb, offset) > 0) {
+ t = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ tmp_tag <<= 7;
+ tmp_tag |= t & 0x7F;
+ if (t & 0x80) break;
+ }
+ }
+
+ if (class)
+ *class = tmp_class;
+ if (pc)
+ *pc = tmp_pc;
+ if (tag)
+ *tag = tmp_tag;
+
+ return offset;
+}
+
+int dissect_ber_identifier(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint8 *class, gboolean *pc, guint32 *tag)
+{
+ int old_offset = offset;
+ guint8 tmp_class;
+ gboolean tmp_pc;
+ guint32 tmp_tag;
+
+ offset = get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
+
+ if(show_internal_ber_fields){
+ proto_tree_add_uint(tree, hf_ber_id_class, tvb, old_offset, 1, tmp_class<<6);
+ proto_tree_add_boolean(tree, hf_ber_id_pc, tvb, old_offset, 1, (tmp_pc)?0x20:0x00);
+ if(tmp_class==BER_CLASS_UNI){
+ proto_tree_add_uint(tree, hf_ber_id_uni_tag, tvb, old_offset, offset - old_offset, tmp_tag);
+ } else {
+ proto_tree_add_uint(tree, hf_ber_id_tag, tvb, old_offset, offset - old_offset, tmp_tag);
+ }
+ }
+
+ if (class)
+ *class = tmp_class;
+ if (pc)
+ *pc = tmp_pc;
+ if (tag)
+ *tag = tmp_tag;
+
+ return offset;
+}
+
+/* this function gets the length octets of the BER TLV.
+ * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
+ */
+/* 8.1.3 Length octets */
+int
+get_ber_length(tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind) {
+ guint8 oct, len;
+ guint32 tmp_length;
+ gboolean tmp_ind;
+
+ tmp_length = 0;
+ tmp_ind = FALSE;
+
+ oct = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ if (!(oct&0x80)) {
+ /* 8.1.3.4 */
+ tmp_length = oct;
+ } else {
+ len = oct & 0x7F;
+ if (len) {
+ /* 8.1.3.5 */
+ while (len--) {
+ oct = tvb_get_guint8(tvb, offset);
+ offset++;
+ tmp_length = (tmp_length<<8) + oct;
+ }
+ } else {
+ /* 8.1.3.6 */
+ tmp_ind = TRUE;
+ /* TO DO */
+ }
+ }
+
+ if (length)
+ *length = tmp_length;
+ if (ind)
+ *ind = tmp_ind;
+
+ return offset;
+}
+
+/* this function dissects the length octets of the BER TLV.
+ * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
+ */
+int
+dissect_ber_length(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind)
+{
+ int old_offset = offset;
+ guint32 tmp_length;
+ gboolean tmp_ind;
+
+ offset = get_ber_length(tvb, offset, &tmp_length, &tmp_ind);
+
+ if(show_internal_ber_fields){
+ proto_tree_add_uint(tree, hf_ber_length, tvb, old_offset, offset - old_offset, tmp_length);
+ }
+ if (length)
+ *length = tmp_length;
+ if (ind)
+ *ind = tmp_ind;
+ return offset;
+}
+
+/* 8.7 Encoding of an octetstring value */
+int
+dissect_ber_octet_string(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb) {
+ guint8 class;
+ gboolean pc, ind;
+ guint32 tag;
+ guint32 len;
+ int end_offset;
+ proto_item *it;
+
+ /* read header and len for the octet string */
+ offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+ offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, &ind);
+ end_offset=offset+len;
+
+ /* sanity check: we only handle Constructed Universal Sequences */
+ if (!implicit_tag) {
+ if( (class!=BER_CLASS_UNI)
+ ||(tag!=BER_UNI_TAG_OCTETSTRING) ){
+ proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: OctetString expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
+ return end_offset;
+ }
+ }
+
+ ber_last_created_item = NULL;
+ if (pc) {
+ /* constructed */
+ /* TO DO */
+ } else {
+ /* primitive */
+ if (hf_id != -1) {
+ it = proto_tree_add_item(tree, hf_id, tvb, offset, len, FALSE);
+ ber_last_created_item = it;
+ }
+ if (out_tvb) {
+ *out_tvb = tvb_new_subset(tvb, offset, len, len);
+ }
+ }
+ return end_offset;
+}
+
+int dissect_ber_octet_string_wcb(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, ber_callback func)
+{
+ tvbuff_t *out_tvb;
+
+ offset = dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, offset, hf_id, (func)?&out_tvb:NULL);
+ if (func && (tvb_length(out_tvb)>0)) {
+ if (hf_id != -1)
+ tree = proto_item_add_subtree(ber_last_created_item, ett_ber_octet_string);
+ func(pinfo, tree, out_tvb, 0);
+ }
+ return offset;
+}
+
+
+int
+dissect_ber_integer(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value)
+{
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 len;
+ gint32 val;
+ guint32 i;
+
+ offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+ offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
+
+/* if(class!=BER_CLASS_UNI)*/
+
+ /* ok, we cant handle >4 byte integers so lets fake them */
+ if(len>8){
+ proto_tree_add_text(tree, tvb, offset, len, "BER: Can not parse %d byte integers", len);
+ return 0xdeadbeef;
+ }
+ if(len>4){
+ header_field_info *hfinfo;
+ char buf[8]={0,0,0,0,0,0,0,0};
+
+ tvb_memcpy(tvb, buf+8-len, offset, len);
+ hfinfo = proto_registrar_get_nth(hf_id);
+ proto_tree_add_text(tree, tvb, offset, len, "%s: %s", hfinfo->name, u64toa(buf));
+ return 0xdeadbeef;
+ }
+
+ val=0;
+ if (len > 0) {
+ /* extend sign bit */
+ val = (gint8)tvb_get_guint8(tvb, offset);
+ offset++;
+ }
+ for(i=1;i<len;i++){
+ val=(val<<8)|tvb_get_guint8(tvb, offset);
+ offset++;
+ }
+
+ ber_last_created_item=NULL;
+
+ if(hf_id!=-1){
+ /* XXX - what if "len" is not 1, 2, 3, or 4? */
+ ber_last_created_item=proto_tree_add_item(tree, hf_id, tvb, offset-len, len, FALSE);
+ }
+ if(value){
+ *value=val;
+ }
+
+ return offset;
+}
+
+
+
+
+
+int
+dissect_ber_boolean(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
+{
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 len;
+ guint8 val;
+ header_field_info *hfi;
+
+ offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+ offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
+
+/* if(class!=BER_CLASS_UNI)*/
+
+ val=tvb_get_guint8(tvb, offset);
+ offset+=1;
+
+ ber_last_created_item=NULL;
+
+ if(hf_id!=-1){
+ hfi = proto_registrar_get_nth(hf_id);
+ if (hfi->type == FT_BOOLEAN)
+ ber_last_created_item=proto_tree_add_boolean(tree, hf_id, tvb, offset-1, 1, val);
+ else
+ ber_last_created_item=proto_tree_add_uint(tree, hf_id, tvb, offset-1, 1, val?1:0);
+ }
+
+ return offset;
+}
+
+
+
+
+
+/* this function dissects a BER sequence
+ */
+int dissect_ber_sequence(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, ber_sequence *seq, gint hf_id, gint ett_id) {
+ guint8 class;
+ gboolean pc, ind;
+ guint32 tag;
+ guint32 len;
+ proto_tree *tree = parent_tree;
+ proto_item *item = NULL;
+ int end_offset;
+
+ /* first we must read the sequence header */
+ offset = dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+ offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, &ind);
+ end_offset = offset + len;
+
+ /* sanity check: we only handle Constructed Universal Sequences */
+ if ((!pc)
+ ||(!implicit_tag&&((class!=BER_CLASS_UNI)
+ ||(tag!=BER_UNI_TAG_SEQUENCE)))) {
+ proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Sequence expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
+ return end_offset;
+ }
+
+ /* create subtree */
+ if (hf_id != -1) {
+ if(parent_tree){
+ item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
+ tree = proto_item_add_subtree(item, ett_id);
+ }
+ }
+
+ /* loop over all entries until we reach the end of the sequence */
+ while (offset < end_offset){
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 len;
+ int hoffset, eoffset;
+
+ hoffset = offset;
+ /* read header and len for next field */
+ offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
+ offset = get_ber_length(tvb, offset, &len, NULL);
+ eoffset = offset + len;
+
+ber_sequence_try_again:
+ /* have we run out of known entries in the sequence ?*/
+ if (!seq->func) {
+ /* it was not, move to the enxt one and try again */
+ proto_tree_add_text(tree, tvb, offset, len, "BER Error: This field lies beyond the end of the known sequence definition.");
+ offset = eoffset;
+ continue;
+ }
+
+ /* verify that this one is the one we want */
+ if( (seq->class!=class)
+ ||(seq->tag!=tag) ){
+ /* it was not, move to the enxt one and try again */
+ if(seq->flags&BER_FLAGS_OPTIONAL){
+ /* well this one was optional so just skip to the next one and try again. */
+ seq++;
+ goto ber_sequence_try_again;
+ }
+ if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
+ proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field");
+ seq++;
+ offset=eoffset;
+ continue;
+ }
+ }
+
+ if (!(seq->flags & BER_FLAGS_NOOWNTAG) && !(seq->flags & BER_FLAGS_IMPLTAG)) {
+ /* dissect header and len for field */
+ hoffset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
+ hoffset = dissect_ber_length(pinfo, tree, tvb, hoffset, NULL, NULL);
+ }
+
+ /* call the dissector for this field */
+ seq->func(pinfo, tree, tvb, hoffset);
+
+ seq++;
+ offset = eoffset;
+ }
+
+ /* if we didnt end up at exactly offset, then we ate too many bytes */
+ if (offset != end_offset) {
+ proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Sequence ate %d too many bytes", offset-end_offset);
+ }
+
+ return end_offset;
+}
+
+
+
+/* this function dissects a BER choice
+ */
+int
+dissect_ber_choice(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_choice *choice, gint hf_id, gint ett_id)
+{
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 len;
+ const ber_choice *ch;
+ proto_tree *tree=parent_tree;
+ proto_item *item=NULL;
+ int end_offset;
+ int hoffset = offset;
+ header_field_info *hfinfo;
+
+
+ /* read header and len for choice field */
+ offset=get_ber_identifier(tvb, offset, &class, &pc, &tag);
+ offset=get_ber_length(tvb, offset, &len, NULL);
+ end_offset=offset+len;
+
+ /* Some sanity checks.
+ * The hf field passed to us MUST be an integer type
+ */
+ if(hf_id!=-1){
+ hfinfo=proto_registrar_get_nth(hf_id);
+ switch(hfinfo->type) {
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, len,"dissect_ber_choice(): Was passed a HF field that was not integer type : %s",hfinfo->abbrev);
+ fprintf(stderr,"dissect_ber_choice(): frame:%d offset:%d Was passed a HF field that was not integer type : %s\n",pinfo->fd->num,offset,hfinfo->abbrev);
+ return end_offset;
+ }
+ }
+
+
+
+ /* loop over all entries until we find the right choice or
+ run out of entries */
+ ch = choice;
+ while(ch->func){
+ if( (ch->class==class)
+ &&(ch->tag==tag) ){
+ if (!(ch->flags & BER_FLAGS_NOOWNTAG) && !(ch->flags & BER_FLAGS_IMPLTAG)) {
+ /* dissect header and len for field */
+ hoffset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
+ hoffset = dissect_ber_length(pinfo, tree, tvb, hoffset, NULL, NULL);
+ }
+ /* create subtree */
+ if(hf_id!=-1){
+ if(parent_tree){
+ item = proto_tree_add_uint(parent_tree, hf_id, tvb, hoffset, end_offset - hoffset, ch->value);
+ tree = proto_item_add_subtree(item, ett_id);
+ }
+ }
+ offset=ch->func(pinfo, tree, tvb, hoffset);
+ return end_offset;
+ break;
+ }
+ ch++;
+ }
+ /* oops no more entries and we still havent found
+ * our guy :-(
+ */
+ proto_tree_add_text(tree, tvb, offset, len, "BER Error: This choice field was not found.");
+
+ return end_offset;
+}
+
+#if 0
+/* this function dissects a BER GeneralString
+ */
+int
+dissect_ber_GeneralString(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, int name_len)
+{
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 len;
+ int end_offset;
+ char str_arr[256];
+ guint32 max_len;
+ char *str;
+
+ str=str_arr;
+ max_len=255;
+ if(name_string){
+ str=name_string;
+ max_len=name_len;
+ }
+
+ /* first we must read the GeneralString header */
+ offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+ offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
+ end_offset=offset+len;
+
+ /* sanity check: we only handle Universal GeneralString*/
+ if( (class!=BER_CLASS_UNI)
+ ||(tag!=BER_UNI_TAG_GENSTR) ){
+ proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: GeneralString expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
+ return end_offset;
+ }
+
+ if(len>=(max_len-1)){
+ len=max_len-1;
+ }
+
+ tvb_memcpy(tvb, str, offset, len);
+ str[len]=0;
+
+ if(hf_id!=-1){
+ proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
+ }
+
+ return end_offset;
+}
+#endif
+int
+dissect_ber_restricted_string(gboolean implicit_tag, guint32 type, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb) {
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 len;
+ int eoffset;
+ int hoffset = offset;
+
+ offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
+ offset = get_ber_length(tvb, offset, &len, NULL);
+ eoffset = offset + len;
+
+ /* sanity check */
+ if (!implicit_tag) {
+ if( (class!=BER_CLASS_UNI)
+ ||(tag != type) ){
+ proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: String with tag=%d expected but Class:%d PC:%d Tag:%d was unexpected", type, class, pc, tag);
+ return eoffset;
+ }
+ }
+
+ /* 8.21.3 */
+ return dissect_ber_octet_string(TRUE, pinfo, tree, tvb, hoffset, hf_id, out_tvb);
+}
+
+int
+dissect_ber_GeneralString(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, guint name_len)
+{
+ tvbuff_t *out_tvb;
+
+ offset = dissect_ber_restricted_string(FALSE, BER_UNI_TAG_GeneralString, pinfo, tree, tvb, offset, hf_id, (name_string)?&out_tvb:NULL);
+
+ if (name_string) {
+ if (tvb_length(out_tvb) >= name_len) {
+ tvb_memcpy(out_tvb, name_string, 0, name_len-1);
+ name_string[name_len-1] = '\0';
+ } else {
+ tvb_memcpy(out_tvb, name_string, 0, -1);
+ name_string[tvb_length(out_tvb)] = '\0';
+ }
+ }
+
+ return offset;
+}
+
+/* 8.19 Encoding of an object identifier value */
+int dissect_ber_object_identifier(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *value_string) {
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 i, len;
+ int eoffset;
+ guint8 byte;
+ guint32 value;
+ char str[256],*strp;
+
+ offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
+ offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
+ eoffset = offset + len;
+
+ if (value_string) {
+ value_string[0] = '\0';
+ }
+
+ /* sanity check */
+ if (!implicit_tag) {
+ if( (class!=BER_CLASS_UNI)
+ ||(tag != BER_UNI_TAG_OID) ){
+ proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: Object Identifier expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
+ return eoffset;
+ }
+ }
+
+ value=0;
+ for (i=0,strp=str; i<len; i++){
+ byte = tvb_get_guint8(tvb, offset);
+ offset++;
+
+ if((strp-str)>200){
+ proto_tree_add_text(tree, tvb, offset, eoffset - offset, "BER Error: too long Object Identifier");
+ return offset;
+ }
+
+ /* 8.19.4 */
+ if (i == 0) {
+ strp += sprintf(strp, "%d.%d", byte/40, byte%40);
+ continue;
+ }
+
+ value = (value << 7) | (byte & 0x7F);
+ if (byte & 0x80) {
+ continue;
+ }
+
+ strp += sprintf(strp, ".%d", value);
+ value = 0;
+ }
+ *strp = '\0';
+
+ if (hf_id != -1) {
+ proto_tree_add_string(tree, hf_id, tvb, offset - len, len, str);
+ }
+
+ if (value_string) {
+ strcpy(value_string, str);
+ }
+
+ return eoffset;
+}
+
+static int dissect_ber_sq_of(gboolean implicit_tag, guint32 type, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, ber_sequence *seq, gint hf_id, gint ett_id) {
+ guint8 class;
+ gboolean pc, ind;
+ guint32 tag;
+ guint32 len;
+ proto_tree *tree = parent_tree;
+ proto_item *item = NULL;
+ int cnt, hoffset, end_offset;
+ header_field_info *hfi;
+
+ /* first we must read the sequence header */
+ offset = dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+ offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, &ind);
+ end_offset = offset + len;
+
+ /* sanity check: we only handle Constructed Universal Sequences */
+ if (!pc
+ ||(!implicit_tag&&((class!=BER_CLASS_UNI)
+ ||(tag!=type)))) {
+ proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: %s Of expected but Class:%d PC:%d Tag:%d was unexpected",
+ (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", class, pc, tag);
+ return end_offset;
+ }
+
+ /* count number of items */
+ cnt = 0;
+ hoffset = offset;
+ while (offset < end_offset){
+ guint32 len;
+ /* read header and len for next field */
+ offset = get_ber_identifier(tvb, offset, NULL, NULL, NULL);
+ offset = get_ber_length(tvb, offset, &len, NULL);
+ offset += len;
+ cnt++;
+ }
+ offset = hoffset;
+
+ /* create subtree */
+ if (hf_id != -1) {
+ hfi = proto_registrar_get_nth(hf_id);
+ if(parent_tree){
+ if (hfi->type == FT_NONE) {
+ item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
+ proto_item_append_text(item, ":");
+ } else {
+ item = proto_tree_add_uint(parent_tree, hf_id, tvb, offset, len, cnt);
+ proto_item_append_text(item, (cnt==1)?" item":" items");
+ }
+ tree = proto_item_add_subtree(item, ett_id);
+ }
+ }
+
+ /* loop over all entries until we reach the end of the sequence */
+ while (offset < end_offset){
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 len;
+ int eoffset;
+ int hoffset;
+
+ hoffset = offset;
+ /* read header and len for next field */
+ offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
+ offset = get_ber_length(tvb, offset, &len, NULL);
+ eoffset = offset + len;
+
+ /* verify that this one is the one we want */
+ if ((seq->class!=class)
+ ||(seq->tag!=tag) ){
+ if (!(seq->flags & BER_FLAGS_NOTCHKTAG)) {
+ proto_tree_add_text(tree, tvb, offset, len, "BER Error: Wrong field");
+ offset = eoffset;
+ continue;
+ }
+ }
+
+ if (!(seq->flags & BER_FLAGS_NOOWNTAG) && !(seq->flags & BER_FLAGS_IMPLTAG)) {
+ /* dissect header and len for field */
+ hoffset = dissect_ber_identifier(pinfo, tree, tvb, hoffset, NULL, NULL, NULL);
+ hoffset = dissect_ber_length(pinfo, tree, tvb, hoffset, NULL, NULL);
+ }
+
+ /* call the dissector for this field */
+ seq->func(pinfo, tree, tvb, hoffset);
+ cnt++;
+ offset = eoffset;
+ }
+
+ /* if we didnt end up at exactly offset, then we ate too many bytes */
+ if (offset != end_offset) {
+ proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: %s Of ate %d too many bytes",
+ (type==BER_UNI_TAG_SEQUENCE)?"Set":"Sequence", offset-end_offset);
+ }
+
+ return end_offset;
+}
+
+int dissect_ber_sequence_of(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, ber_sequence *seq, gint hf_id, gint ett_id) {
+ return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SEQUENCE, pinfo, parent_tree, tvb, offset, seq, hf_id, ett_id);
+}
+
+int dissect_ber_set_of(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, ber_sequence *seq, gint hf_id, gint ett_id) {
+ return dissect_ber_sq_of(implicit_tag, BER_UNI_TAG_SET, pinfo, parent_tree, tvb, offset, seq, hf_id, ett_id);
+}
+
+int
+dissect_ber_generalized_time(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)
+{
+ char str[32];
+ const guint8 *tmpstr;
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 len;
+ int end_offset;
+
+ offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+ offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
+ end_offset=offset+len;
+
+ /* sanity check. we only handle universal/generalized time */
+ if( (class!=BER_CLASS_UNI)
+ ||(tag!=BER_UNI_TAG_GeneralizedTime)){
+ proto_tree_add_text(tree, tvb, offset-2, 2, "BER Error: GeneralizedTime expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
+ return end_offset;
+ end_offset=offset+len;
+ }
+
+ tmpstr=tvb_get_ptr(tvb, offset, len);
+ snprintf(str, 31, "%.4s-%.2s-%.2s %.2s:%.2s:%.2s (%.1s)",
+ tmpstr, tmpstr+4, tmpstr+6, tmpstr+8,
+ tmpstr+10, tmpstr+12, tmpstr+14);
+ str[31]=0; /* just in case ... */
+
+ if(hf_id!=-1){
+ proto_tree_add_string(tree, hf_id, tvb, offset, len, str);
+ }
+
+ offset+=len;
+ return offset;
+}
+
+/* 8.6 Encoding of a bitstring value */
+int dissect_ber_bitstring(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn_namedbit *named_bits, gint hf_id, gint ett_id, tvbuff_t **out_tvb)
+{
+ guint8 class;
+ gboolean pc, ind;
+ guint32 tag;
+ guint32 len;
+ guint8 pad=0, b0, b1, val;
+ int end_offset;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ asn_namedbit *nb;
+ char *sep;
+ gboolean term;
+
+ /* read header and len for the octet string */
+ offset = dissect_ber_identifier(pinfo, parent_tree, tvb, offset, &class, &pc, &tag);
+ offset = dissect_ber_length(pinfo, parent_tree, tvb, offset, &len, &ind);
+ end_offset = offset + len;
+
+ /* sanity check: we only handle Universal BitSrings */
+ if (!implicit_tag) {
+ if( (class!=BER_CLASS_UNI)
+ ||(tag!=BER_UNI_TAG_BITSTRING) ){
+ proto_tree_add_text(parent_tree, tvb, offset-2, 2, "BER Error: BitString expected but Class:%d PC:%d Tag:%d was unexpected", class, pc, tag);
+ return end_offset;
+ }
+ }
+
+ ber_last_created_item = NULL;
+
+ if (pc) {
+ /* constructed */
+ /* TO DO */
+ } else {
+ /* primitive */
+ /* padding */
+ pad = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(parent_tree, hf_ber_bitstring_padding, tvb, offset, 1, FALSE);
+ offset++;
+ len--;
+ if ( hf_id != -1) {
+ item = proto_tree_add_item(parent_tree, hf_id, tvb, offset, len, FALSE);
+ ber_last_created_item = item;
+ if (ett_id != -1) {
+ tree = proto_item_add_subtree(item, ett_id);
+ }
+ }
+ if (out_tvb) {
+ *out_tvb = tvb_new_subset(tvb, offset, len, 8*len-pad);
+ }
+ }
+
+ if (named_bits) {
+ sep = " (";
+ term = FALSE;
+ nb = named_bits;
+ while (nb->p_id) {
+ if (nb->bit < (8*len-pad)) {
+ val = tvb_get_guint8(tvb, offset + nb->bit/8);
+ val &= 0x80 >> (nb->bit%8);
+ b0 = (nb->gb0 == -1) ? nb->bit/8 :
+ ((guint32)nb->gb0)/8;
+ b1 = (nb->gb1 == -1) ? nb->bit/8 :
+ ((guint32)nb->gb1)/8;
+ proto_tree_add_item(tree, *(nb->p_id), tvb, offset + b0, b1 - b0 + 1, FALSE);
+ } else { /* 8.6.2.4 */
+ val = 0;
+ proto_tree_add_boolean(tree, *(nb->p_id), tvb, offset + len, 0, 0x00);
+ }
+ if (val) {
+ if (item && nb->tstr)
+ proto_item_append_text(item, "%s%s", sep, nb->tstr);
+ } else {
+ if (item && nb->fstr)
+ proto_item_append_text(item, "%s%s", sep, nb->fstr);
+ }
+ nb++;
+ sep = ", ";
+ term = TRUE;
+ }
+ if (term)
+ proto_item_append_text(item, ")");
+ }
+
+ return end_offset;
+}
+
+int dissect_ber_bitstring32(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, int **bit_fields, gint hf_id, gint ett_id, tvbuff_t **out_tvb)
+{
+ tvbuff_t *tmp_tvb;
+ proto_tree *tree;
+ guint32 val;
+ int **bf;
+ header_field_info *hfi;
+ char *sep;
+ gboolean term;
+ unsigned int i, tvb_len;
+
+ offset = dissect_ber_bitstring(implicit_tag, pinfo, parent_tree, tvb, offset, NULL, hf_id, ett_id, &tmp_tvb);
+
+ tree = proto_item_get_subtree(ber_last_created_item);
+ if (bit_fields && tree) {
+ /* tmp_tvb points to the actual bitstring (including any pad bits at the end.
+ * note that this bitstring is not neccessarily always encoded as 4 bytes
+ * so we have to read it byte by byte.
+ */
+ val=0;
+ tvb_len=tvb_length(tmp_tvb);
+ for(i=0;i<4;i++){
+ val<<=8;
+ if(i<tvb_len){
+ val|=tvb_get_guint8(tmp_tvb,i);
+ }
+ }
+ bf = bit_fields;
+ sep = " (";
+ term = FALSE;
+ while (*bf) {
+ proto_tree_add_boolean(tree, **bf, tmp_tvb, 0, tvb_len, val);
+ hfi = proto_registrar_get_nth(**bf);
+ if (val & hfi->bitmask) {
+ proto_item_append_text(ber_last_created_item, "%s%s", sep, hfi->name);
+ sep = ", ";
+ term = TRUE;
+ }
+ bf++;
+ }
+ if (term)
+ proto_item_append_text(ber_last_created_item, ")");
+ }
+
+ if (out_tvb)
+ *out_tvb = tmp_tvb;
+
+ return offset;
+}
+
+void
+proto_register_ber(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ber_id_class, {
+ "Class", "ber.id.class", FT_UINT8, BASE_DEC,
+ VALS(ber_class_codes), 0xc0, "Class of BER TLV Identifier", HFILL }},
+ { &hf_ber_bitstring_padding, {
+ "Padding", "ber.bitstring.padding", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Number of unsused bits in the last octet of the bitstring", HFILL }},
+ { &hf_ber_id_pc, {
+ "P/C", "ber.id.pc", FT_BOOLEAN, 8,
+ TFS(&ber_pc_codes), 0x20, "Primitive or Constructed BER encoding", HFILL }},
+ { &hf_ber_id_uni_tag, {
+ "Tag", "ber.id.uni_tag", FT_UINT8, BASE_DEC,
+ VALS(ber_uni_tag_codes), 0x1f, "Universal tag type", HFILL }},
+ { &hf_ber_id_tag, {
+ "Tag", "ber.id.tag", FT_UINT32, BASE_DEC,
+ NULL, 0, "Tag value for non-Universal classes", HFILL }},
+ { &hf_ber_length, {
+ "Length", "ber.length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of contents", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_ber_octet_string,
+ };
+ module_t *ber_module;
+
+ proto_ber = proto_register_protocol("Basic Encoding Rules (ASN.1 X.690)", "BER", "ber");
+ proto_register_field_array(proto_ber, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ proto_set_cant_toggle(proto_ber);
+
+ /* Register preferences */
+ ber_module = prefs_register_protocol(proto_ber, NULL);
+ prefs_register_bool_preference(ber_module, "show_internals",
+ "Show internal BER encapsulation tokens",
+ "Whether the dissector should also display internal"
+ " ASN.1 BER details such as Identifier and Length fields", &show_internal_ber_fields);
+}
+
+void
+proto_reg_handoff_ber(void)
+{
+}
diff --git a/epan/dissectors/packet-ber.h b/epan/dissectors/packet-ber.h
new file mode 100644
index 0000000000..5d00016602
--- /dev/null
+++ b/epan/dissectors/packet-ber.h
@@ -0,0 +1,161 @@
+/* packet-ber.h
+ * Helpers for ASN.1/BER dissection
+ * Ronnie Sahlberg (C) 2004
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_BER_H__
+#define __PACKET_BER_H__
+
+#define BER_NOT_DECODED_YET(x) \
+proto_tree_add_text(tree, tvb, offset, 0, "something unknown here [%s]",x); \
+fprintf(stderr,"Not decoded yet in packet : %d [%s]\n", pinfo->fd->num,x); \
+if (check_col(pinfo->cinfo, COL_INFO)){ \
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[UNKNOWN BER: %s]", x); \
+} \
+tvb_get_guint8(tvb, 9999);
+
+typedef int (*ber_callback)(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+
+#define BER_CLASS_UNI 0
+#define BER_CLASS_APP 1
+#define BER_CLASS_CON 2
+#define BER_CLASS_PRI 3
+
+
+#define BER_UNI_TAG_EOC 0 /* 'end-of-content' */
+#define BER_UNI_TAG_BOOLEAN 1
+#define BER_UNI_TAG_INTEGER 2
+#define BER_UNI_TAG_BITSTRING 3
+#define BER_UNI_TAG_OCTETSTRING 4
+#define BER_UNI_TAG_NULL 5
+#define BER_UNI_TAG_OID 6 /* OBJECT IDENTIFIER */
+#define BER_UNI_TAG_ObjectDescriptor 7
+#define BER_UNI_TAG_REAL 9
+#define BER_UNI_TAG_ENUMERATED 10
+#define BER_UNI_TAG_EMBEDDED_PDV 11
+#define BER_UNI_TAG_UTF8String 12
+#define BER_UNI_TAG_RELATIVE_OID 13
+#define BER_UNI_TAG_SEQUENCE 16 /* SEQUENCE, SEQUENCE OF */
+#define BER_UNI_TAG_SET 17 /* SET, SET OF */
+#define BER_UNI_TAG_NumericString 18
+#define BER_UNI_TAG_PrintableString 19
+#define BER_UNI_TAG_TeletextString 20 /* TeletextString, T61String */
+#define BER_UNI_TAG_VideotexString 21
+#define BER_UNI_TAG_IA5String 22
+#define BER_UNI_TAG_UTCTime 23
+#define BER_UNI_TAG_GeneralizedTime 24
+#define BER_UNI_TAG_GraphicString 25
+#define BER_UNI_TAG_VisibleString 26 /* VisibleString, ISO64String */
+#define BER_UNI_TAG_GeneralString 27
+#define BER_UNI_TAG_UniversalString 28
+#define BER_UNI_TAG_CHARACTERSTRING 29
+#define BER_UNI_TAG_BMPString 30
+
+/* this function dissects the identifier octer of the BER TLV.
+ * We only handle TAGs (and LENGTHs) that fit inside 32 bit integers.
+ */
+extern int get_ber_identifier(tvbuff_t *tvb, int offset, guint8 *class, gboolean *pc, guint32 *tag);
+extern int dissect_ber_identifier(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint8 *class, gboolean *pc, guint32 *tag);
+
+/* this function dissects the identifier octer of the BER TLV.
+ * We only handle (TAGs and) LENGTHs that fit inside 32 bit integers.
+ */
+extern int get_ber_length(tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind);
+extern int dissect_ber_length(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 *length, gboolean *ind);
+
+extern int dissect_ber_octet_string(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb);
+extern int dissect_ber_octet_string_wcb(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, ber_callback func);
+
+extern int dissect_ber_integer(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value);
+
+
+extern int dissect_ber_boolean(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id);
+
+
+#define BER_FLAGS_OPTIONAL 0x00000001
+#define BER_FLAGS_IMPLTAG 0x00000002
+#define BER_FLAGS_NOOWNTAG 0x00000004
+#define BER_FLAGS_NOTCHKTAG 0x00000008
+typedef struct _ber_sequence {
+ guint8 class;
+ guint32 tag;
+ guint32 flags;
+ ber_callback func;
+} ber_sequence;
+
+/* this function dissects a BER sequence
+ */
+extern int dissect_ber_sequence(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, ber_sequence *seq, gint hf_id, gint ett_id);
+
+
+typedef struct _ber_choice {
+ guint32 value;
+ guint8 class;
+ guint32 tag;
+ guint32 flags;
+ ber_callback func;
+} ber_choice;
+
+
+/* this function dissects a BER choice
+ */
+extern int dissect_ber_choice(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, const ber_choice *ch, gint hf_id, gint ett_id);
+
+
+/* this function dissects a BER strings
+ */
+extern int dissect_ber_restricted_string(gboolean implicit_tag, guint32 type, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb);
+extern int dissect_ber_GeneralString(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *name_string, guint name_len);
+
+
+/* this function dissects a BER Object Identifier
+ */
+extern int dissect_ber_object_identifier(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, char *value_string);
+
+/* this function dissects a BER sequence of
+ */
+extern int dissect_ber_sequence_of(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, ber_sequence *seq, gint hf_id, gint ett_id);
+
+extern int dissect_ber_set_of(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, ber_sequence *seq, gint hf_id, gint ett_id);
+
+
+extern int dissect_ber_generalized_time(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id);
+
+typedef struct _asn_namedbit {
+ guint32 bit;
+ int *p_id;
+ gint32 gb0; /* the 1st bit of "bit group", -1 = the 1st bit of current byte */
+ gint32 gb1; /* last bit of "bit group", -1 = last bit of current byte */
+ gchar *tstr; /* true string */
+ gchar *fstr; /* false string */
+} asn_namedbit;
+/* this function dissects a BER BIT-STRING
+ */
+extern int dissect_ber_bitstring(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn_namedbit *named_bits, gint hf_id, gint ett_id, tvbuff_t **out_tvb);
+extern int dissect_ber_bitstring32(gboolean implicit_tag, packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, int **bit_fields, gint hf_id, gint ett_id, tvbuff_t **out_tvb);
+
+
+extern proto_item *ber_last_created_item;
+extern proto_item *get_ber_last_created_item(void);
+
+#endif /* __PACKET_BER_H__ */
diff --git a/epan/dissectors/packet-bfd.c b/epan/dissectors/packet-bfd.c
new file mode 100644
index 0000000000..50d35d571f
--- /dev/null
+++ b/epan/dissectors/packet-bfd.c
@@ -0,0 +1,273 @@
+/* packet-bfd.c
+ * Routines for Bi-directional Fault Detection (BFD) message dissection
+ *
+ * Copyright 2003, Hannes Gredler <hannes@juniper.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+#define UDP_PORT_BFD_CONTROL 3784 /* draft-katz-ward-bfd-v4v6-1hop-00.txt */
+
+static const value_string bfd_control_diag_values[] = {
+ { 0, "No Diagnostic" },
+ { 1, "Control Detection Time Expired" },
+ { 2, "Echo Function Failed" },
+ { 3, "Neighbor Signaled Session Down" },
+ { 4, "Forwarding Plane Reset" },
+ { 5, "Path Down" },
+ { 6, "Concatenated Path Down" },
+ { 7, "Administratively Down" },
+ { 0, NULL }
+};
+
+static const value_string bfd_control_flag_values[] = {
+ { 0x80, "I Hear You" },
+ { 0x40, "Demand" },
+ { 0x20, "Poll" },
+ { 0x10, "Final" },
+ { 0x08, "Reserved" },
+ { 0x04, "Reserved" },
+ { 0x02, "Reserved" },
+ { 0x01, "Reserved" },
+ { 0, NULL }
+};
+
+static gint proto_bfd = -1;
+
+static gint hf_bfd_version = -1;
+static gint hf_bfd_diag = -1;
+static gint hf_bfd_flags = -1;
+static gint hf_bfd_detect_time_multiplier = -1;
+static gint hf_bfd_my_discriminator = -1;
+static gint hf_bfd_your_discriminator = -1;
+static gint hf_bfd_desired_min_tx_interval = -1;
+static gint hf_bfd_required_min_rx_interval = -1;
+static gint hf_bfd_required_min_echo_interval = -1;
+
+static gint ett_bfd = -1;
+
+/*
+ * Control packet, draft-katz-ward-bfd-01.txt
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |Vers | Diag |H|D|P|F| Rsvd | Detect Mult | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | My Discriminator |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Your Discriminator |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Desired Min TX Interval |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Required Min RX Interval |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Required Min Echo RX Interval |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+static void dissect_bfd_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gint bfd_version = -1;
+ gint bfd_diag = -1;
+ gint bfd_flags = -1;
+ gint bfd_detect_time_multiplier = -1;
+ gint bfd_length = -1;
+ gint bfd_my_discriminator = -1;
+ gint bfd_your_discriminator = -1;
+ gint bfd_desired_min_tx_interval = -1;
+ gint bfd_required_min_rx_interval = -1;
+ gint bfd_required_min_echo_interval = -1;
+
+ proto_item *ti;
+ proto_tree *bfd_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BFD Control");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ bfd_version = ((tvb_get_guint8(tvb, 0) & 0xe0) >> 5);
+ bfd_diag = (tvb_get_guint8(tvb, 0) & 0x1f);
+ bfd_flags = tvb_get_guint8(tvb, 1);
+ bfd_detect_time_multiplier = tvb_get_guint8(tvb, 2);
+ bfd_length = tvb_get_guint8(tvb, 3);
+
+ bfd_my_discriminator = tvb_get_ntohl(tvb, 4);
+ bfd_your_discriminator = tvb_get_ntohl(tvb, 8);
+ bfd_desired_min_tx_interval = tvb_get_ntohl(tvb, 12);
+ bfd_required_min_rx_interval = tvb_get_ntohl(tvb, 16);
+ bfd_required_min_echo_interval = tvb_get_ntohl(tvb, 20);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Diag: %s, Flags: %s",
+ val_to_str(bfd_diag, bfd_control_diag_values, "UNKNOWN"),
+ decode_enumerated_bitfield(bfd_flags,
+ 0xf0,
+ 8,
+ bfd_control_flag_values,
+ "%s"));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_bfd, tvb, 0, -1,
+ "BFD Control message");
+
+ bfd_tree = proto_item_add_subtree(ti, ett_bfd);
+
+ ti = proto_tree_add_uint(bfd_tree, hf_bfd_version, tvb, 0,
+ 1, bfd_version);
+
+ ti = proto_tree_add_uint(bfd_tree, hf_bfd_diag, tvb, 0,
+ 1, bfd_diag);
+
+ ti = proto_tree_add_text ( bfd_tree, tvb, 1, 1, "Message Flags: %s",
+ decode_enumerated_bitfield(bfd_flags,
+ 0xf0,
+ 8,
+ bfd_control_flag_values,
+ "%s"));
+
+ ti = proto_tree_add_uint_format(bfd_tree, hf_bfd_detect_time_multiplier, tvb, 2,
+ 1, bfd_detect_time_multiplier,
+ "%s: %u (= %u ms Detection time)",
+ proto_registrar_get_nth(hf_bfd_detect_time_multiplier) -> name,
+ bfd_detect_time_multiplier,
+ bfd_detect_time_multiplier * bfd_desired_min_tx_interval/1000);
+
+ ti = proto_tree_add_text ( bfd_tree, tvb, 3, 1, "Message Length: %u Bytes", bfd_length );
+
+ ti = proto_tree_add_uint(bfd_tree, hf_bfd_my_discriminator, tvb, 4,
+ 4, bfd_my_discriminator);
+
+ ti = proto_tree_add_uint(bfd_tree, hf_bfd_your_discriminator, tvb, 8,
+ 4, bfd_your_discriminator);
+
+ ti = proto_tree_add_uint_format(bfd_tree, hf_bfd_desired_min_tx_interval, tvb, 12,
+ 4, bfd_desired_min_tx_interval,
+ "%s: %4u ms",
+ proto_registrar_get_nth(hf_bfd_desired_min_tx_interval) -> name,
+ bfd_desired_min_tx_interval/1000);
+
+ ti = proto_tree_add_uint_format(bfd_tree, hf_bfd_required_min_rx_interval, tvb, 16,
+ 4, bfd_required_min_rx_interval,
+ "%s: %4u ms",
+ proto_registrar_get_nth(hf_bfd_required_min_rx_interval) -> name,
+ bfd_required_min_rx_interval/1000);
+
+ ti = proto_tree_add_uint_format(bfd_tree, hf_bfd_required_min_echo_interval, tvb, 20,
+ 4, bfd_required_min_echo_interval,
+ "%s: %4u ms",
+ proto_registrar_get_nth(hf_bfd_required_min_echo_interval) -> name,
+ bfd_required_min_echo_interval/1000);
+
+ }
+ return;
+}
+
+/* Register the protocol with Ethereal */
+void proto_register_bfd(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_bfd_version,
+ { "Protocol Version", "bfd.version",
+ FT_UINT8, BASE_DEC, NULL , 0xe0,
+ "", HFILL }
+ },
+ { &hf_bfd_diag,
+ { "Diagnostic Code", "bfd.diag",
+ FT_UINT8, BASE_HEX, VALS(bfd_control_diag_values), 0x1f,
+ "", HFILL }
+ },
+ { &hf_bfd_flags,
+ { "Message Flags", "bfd.flags",
+ FT_UINT8, BASE_HEX, NULL, 0xf0,
+ "", HFILL }
+ },
+ { &hf_bfd_detect_time_multiplier,
+ { "Detect Time Multiplier", "bfd.detect_time_multiplier",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_bfd_my_discriminator,
+ { "My Discriminator", "bfd.my_discriminator",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_bfd_your_discriminator,
+ { "Your Discriminator", "bfd.your_discriminator",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_bfd_desired_min_tx_interval,
+ { "Desired Min TX Interval", "bfd.desired_min_tx_interval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_bfd_required_min_rx_interval,
+ { "Required Min RX Interval", "bfd.required_min_rx_interval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_bfd_required_min_echo_interval,
+ { "Required Min Echo Interval", "bfd.required_min_echo_interval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_bfd,
+ };
+
+ /* Register the protocol name and description */
+ proto_bfd = proto_register_protocol("Bi-directional Fault Detection Control Message",
+ "BFD Control",
+ "bfdcontrol");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_bfd, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_bfd(void)
+{
+ dissector_handle_t bfd_control_handle;
+
+ bfd_control_handle = create_dissector_handle(dissect_bfd_control, proto_bfd);
+ dissector_add("udp.port", UDP_PORT_BFD_CONTROL, bfd_control_handle);
+}
diff --git a/epan/dissectors/packet-bgp.c b/epan/dissectors/packet-bgp.c
new file mode 100644
index 0000000000..a0b91350f3
--- /dev/null
+++ b/epan/dissectors/packet-bgp.c
@@ -0,0 +1,2802 @@
+/* packet-bgp.c
+ * Routines for BGP packet dissection.
+ * Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
+ *
+ * $Id$
+ *
+ * Supports:
+ * RFC1771 A Border Gateway Protocol 4 (BGP-4)
+ * RFC1965 Autonomous System Confederations for BGP
+ * RFC1997 BGP Communities Attribute
+ * RFC2547 BGP/MPLS VPNs
+ * RFC2796 BGP Route Reflection An alternative to full mesh IBGP
+ * RFC2842 Capabilities Advertisement with BGP-4
+ * RFC2858 Multiprotocol Extensions for BGP-4
+ * RFC2918 Route Refresh Capability for BGP-4
+ * RFC3107 Carrying Label Information in BGP-4
+ * draft-ietf-idr-as4bytes-06
+ * draft-ietf-idr-dynamic-cap-03
+ * draft-ietf-idr-bgp-ext-communities-05
+ *
+ * TODO:
+ * Destination Preference Attribute for BGP (work in progress)
+ * RFC1863 A BGP/IDRP Route Server alternative to a full mesh routing
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/addr_and_mask.h>
+#include "packet-bgp.h"
+#include "packet-ipv6.h"
+#include "packet-frame.h"
+#include "afn.h"
+#include "prefs.h"
+
+static const value_string bgptypevals[] = {
+ { BGP_OPEN, "OPEN Message" },
+ { BGP_UPDATE, "UPDATE Message" },
+ { BGP_NOTIFICATION, "NOTIFICATION Message" },
+ { BGP_KEEPALIVE, "KEEPALIVE Message" },
+ { BGP_ROUTE_REFRESH, "ROUTE-REFRESH Message" },
+ { BGP_CAPABILITY, "CAPABILITY Message" },
+ { BGP_ROUTE_REFRESH_CISCO, "Cisco ROUTE-REFRESH Message" },
+ { 0, NULL },
+};
+
+static const value_string bgpnotify_major[] = {
+ { 1, "Message Header Error" },
+ { 2, "OPEN Message Error" },
+ { 3, "UPDATE Message Error" },
+ { 4, "Hold Timer Expired" },
+ { 5, "Finite State Machine Error" },
+ { 6, "Cease" },
+ { 7, "CAPABILITY Message Error" },
+ { 0, NULL },
+};
+
+static const value_string bgpnotify_minor_1[] = {
+ { 1, "Connection Not Synchronized" },
+ { 2, "Bad Message Length" },
+ { 3, "Bad Message Type" },
+ { 0, NULL },
+};
+
+static const value_string bgpnotify_minor_2[] = {
+ { 1, "Unsupported Version Number" },
+ { 2, "Bad Peer AS" },
+ { 3, "Bad BGP Identifier" },
+ { 4, "Unsupported Optional Parameter" },
+ { 5, "Authentication Failure" },
+ { 6, "Unacceptable Hold Time" },
+ { 7, "Unsupported Capability" },
+ { 0, NULL },
+};
+
+static const value_string bgpnotify_minor_3[] = {
+ { 1, "Malformed Attribute List" },
+ { 2, "Unrecognized Well-known Attribute" },
+ { 3, "Missing Well-known Attribute" },
+ { 4, "Attribute Flags Error" },
+ { 5, "Attribute Length Error" },
+ { 6, "Invalid ORIGIN Attribute" },
+ { 7, "AS Routing Loop" },
+ { 8, "Invalid NEXT_HOP Attribute" },
+ { 9, "Optional Attribute Error" },
+ { 10, "Invalid Network Field" },
+ { 11, "Malformed AS_PATH" },
+ { 0, NULL },
+};
+
+/* draft-ietf-idr-cease-subcode-02 */
+static const value_string bgpnotify_minor_6[] = {
+ { 1, "Maximum Number of Prefixes Reached"},
+ { 2, "Administratively Shutdown"},
+ { 3, "Peer Unconfigured"},
+ { 4, "Administratively Reset"},
+ { 5, "Connection Rejected"},
+ { 6, "Other Configuration Change"},
+ { 7, "Connection Collision Resolution"},
+ { 0, NULL},
+};
+
+static const value_string bgpnotify_minor_7[] = {
+ { 1, "Invalid Action Value" },
+ { 2, "Invalid Capability Length" },
+ { 3, "Malformed Capability Value" },
+ { 4, "Unsupported Capability Code" },
+ { 0, NULL },
+};
+
+static const value_string *bgpnotify_minor[] = {
+ NULL,
+ bgpnotify_minor_1, /* open */
+ bgpnotify_minor_2, /* update */
+ bgpnotify_minor_3, /* notification */
+ NULL, /* hold-timer expired */
+ NULL, /* FSM error */
+ bgpnotify_minor_6, /* cease */
+ bgpnotify_minor_7 /* capability */
+};
+
+static const value_string bgpattr_origin[] = {
+ { 0, "IGP" },
+ { 1, "EGP" },
+ { 2, "INCOMPLETE" },
+ { 0, NULL },
+};
+
+static const value_string as_segment_type[] = {
+ { 1, "AS_SET" },
+ { 2, "AS_SEQUENCE" },
+/* RFC1965 has the wrong values, corrected in */
+/* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
+ { 4, "AS_CONFED_SET" },
+ { 3, "AS_CONFED_SEQUENCE" },
+ { 0, NULL },
+};
+
+static const value_string bgpattr_type[] = {
+ { BGPTYPE_ORIGIN, "ORIGIN" },
+ { BGPTYPE_AS_PATH, "AS_PATH" },
+ { BGPTYPE_NEXT_HOP, "NEXT_HOP" },
+ { BGPTYPE_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
+ { BGPTYPE_LOCAL_PREF, "LOCAL_PREF" },
+ { BGPTYPE_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
+ { BGPTYPE_AGGREGATOR, "AGGREGATOR" },
+ { BGPTYPE_COMMUNITIES, "COMMUNITIES" },
+ { BGPTYPE_ORIGINATOR_ID, "ORIGINATOR_ID" },
+ { BGPTYPE_CLUSTER_LIST, "CLUSTER_LIST" },
+ { BGPTYPE_MP_REACH_NLRI, "MP_REACH_NLRI" },
+ { BGPTYPE_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
+ { BGPTYPE_EXTENDED_COMMUNITY, "EXTENDED_COMMUNITIES" },
+ { BGPTYPE_NEW_AS_PATH, "NEW_AS_PATH" },
+ { BGPTYPE_NEW_AGGREGATOR, "NEW_AGGREGATOR" },
+ { 0, NULL },
+};
+
+static const value_string bgpext_com_type[] = {
+ { BGP_EXT_COM_RT_0, "Route Target" },
+ { BGP_EXT_COM_RT_1, "Route Target" },
+ { BGP_EXT_COM_RT_2, "Route Target" },
+ { BGP_EXT_COM_RO_0, "Route Origin" },
+ { BGP_EXT_COM_RO_1, "Route Origin" },
+ { BGP_EXT_COM_RO_2, "Route Origin" },
+ { BGP_EXT_COM_LINKBAND, "Link Bandwidth" },
+ { BGP_EXT_COM_VPN_ORIGIN, "OSPF Domain" },
+ { BGP_EXT_COM_OSPF_RTYPE, "OSPF Route Type" },
+ { BGP_EXT_COM_OSPF_RID, "OSPF Router ID" },
+ { BGP_EXT_COM_L2INFO, "Layer 2 Information" },
+ { 0, NULL },
+};
+
+static const value_string bgp_l2vpn_encaps[] = {
+ { 0, "Reserved"},
+ { 1, "Frame Relay"},
+ { 2, "ATM AAL5 VCC transport"},
+ { 3, "ATM transparent cell transport"},
+ { 4, "Ethernet VLAN"},
+ { 5, "Ethernet"},
+ { 6, "Cisco-HDLC"},
+ { 7, "PPP"},
+ { 8, "CEM"},
+ { 9, "ATM VCC cell transport"},
+ { 10, "ATM VPC cell transport"},
+ { 11, "MPLS"},
+ { 12, "VPLS"},
+ { 64, "IP-interworking"},
+ { 0, NULL},
+};
+
+static const value_string bgpext_ospf_rtype[] = {
+ { BGP_OSPF_RTYPE_RTR, "Router" },
+ { BGP_OSPF_RTYPE_NET, "Network" },
+ { BGP_OSPF_RTYPE_SUM, "Summary" },
+ { BGP_OSPF_RTYPE_EXT, "External" },
+ { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
+ { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
+ { 0, NULL },
+};
+
+/* Subsequent address family identifier, RFC2858 */
+static const value_string bgpattr_nlri_safi[] = {
+ { 0, "Reserved" },
+ { SAFNUM_UNICAST, "Unicast" },
+ { SAFNUM_MULCAST, "Multicast" },
+ { SAFNUM_UNIMULC, "Unicast+Multicast" },
+ { SAFNUM_MPLS_LABEL, "Labeled Unicast"},
+ { SAFNUM_LAB_VPNUNICAST, "Labeled VPN Unicast" }, /* draft-rosen-rfc2547bis-03 */
+ { SAFNUM_LAB_VPNMULCAST, "Labeled VPN Multicast" },
+ { SAFNUM_LAB_VPNUNIMULC, "Labeled VPN Unicast+Multicast" },
+ { 0, NULL },
+};
+
+/* ORF Type, draft-ietf-idr-route-filter-04.txt */
+static const value_string orf_type_vals[] = {
+ { 2, "Communities ORF-Type" },
+ { 3, "Extended Communities ORF-Type" },
+ { 128, "Cisco PrefixList ORF-Type" },
+ { 129, "Cisco CommunityList ORF-Type" },
+ { 130, "Cisco Extended CommunityList ORF-Type" },
+ { 131, "Cisco AsPathList ORF-Type" },
+ { 0, NULL },
+};
+
+/* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
+static const value_string orf_send_recv_vals[] = {
+ { 1, "Receive" },
+ { 2, "Send" },
+ { 3, "Both" },
+ { 0, NULL },
+};
+
+/* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
+static const value_string orf_when_vals[] = {
+ { 1, "Immediate" },
+ { 2, "Defer" },
+ { 0, NULL },
+};
+
+static const value_string orf_entry_action_vals[] = {
+ { 0, "Add" },
+ { 0x40, "Remove" },
+ { 0x80, "RemoveAll" },
+ { 0, NULL },
+};
+
+static const value_string orf_entry_match_vals[] = {
+ { 0, "Permit" },
+ { 0x20, "Deny" },
+ { 0, NULL },
+};
+
+static const value_string capability_vals[] = {
+ { BGP_CAPABILITY_RESERVED, "Reserved capability" },
+ { BGP_CAPABILITY_MULTIPROTOCOL, "Multiprotocol extensions capability" },
+ { BGP_CAPABILITY_ROUTE_REFRESH, "Route refresh capability" },
+ { BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING, "Cooperative route filtering capability" },
+ { BGP_CAPABILITY_GRACEFUL_RESTART, "Graceful Restart capability" },
+ { BGP_CAPABILITY_4_OCTET_AS_NUMBER, "Support for 4-octet AS number capability" },
+ { BGP_CAPABILITY_DYNAMIC_CAPABILITY, "Support for Dynamic capability" },
+ { BGP_CAPABILITY_ROUTE_REFRESH_CISCO, "Route refresh capability" },
+ { BGP_CAPABILITY_ORF_CISCO, "Cooperative route filtering capability" },
+};
+
+/* Capability Message action code */
+static const value_string bgpcap_action[] = {
+ { 0, "advertising a capability" },
+ { 1, "removing a capability" },
+ { 0, NULL },
+};
+
+
+/* Maximal size of an IP address string */
+#define MAX_SIZE_OF_IP_ADDR_STRING 16
+
+static int proto_bgp = -1;
+static int hf_bgp_type = -1;
+static int hf_bgp_next_hop = -1;
+static int hf_bgp_as_path = -1;
+static int hf_bgp_cluster_identifier = -1;
+static int hf_bgp_community_as = -1;
+static int hf_bgp_community_value = -1;
+static int hf_bgp_origin = -1;
+static int hf_bgp_cluster_list = -1;
+static int hf_bgp_originator_id = -1;
+static int hf_bgp_local_pref = -1;
+static int hf_bgp_multi_exit_disc = -1;
+static int hf_bgp_aggregator_as = -1;
+static int hf_bgp_aggregator_origin = -1;
+static int hf_bgp_mp_reach_nlri_ipv4_prefix = -1;
+static int hf_bgp_mp_unreach_nlri_ipv4_prefix = -1;
+static int hf_bgp_withdrawn_prefix = -1;
+static int hf_bgp_nlri_prefix = -1;
+
+static gint ett_bgp = -1;
+static gint ett_bgp_prefix = -1;
+static gint ett_bgp_unfeas = -1;
+static gint ett_bgp_attrs = -1;
+static gint ett_bgp_attr = -1;
+static gint ett_bgp_attr_flags = -1;
+static gint ett_bgp_mp_nhna = -1;
+static gint ett_bgp_mp_reach_nlri = -1;
+static gint ett_bgp_mp_unreach_nlri = -1;
+static gint ett_bgp_mp_snpa = -1;
+static gint ett_bgp_nlri = -1;
+static gint ett_bgp_open = -1;
+static gint ett_bgp_update = -1;
+static gint ett_bgp_notification = -1;
+static gint ett_bgp_route_refresh = -1; /* ROUTE-REFRESH message tree */
+static gint ett_bgp_capability = -1;
+static gint ett_bgp_as_paths = -1;
+static gint ett_bgp_as_path_segments = -1;
+static gint ett_bgp_communities = -1;
+static gint ett_bgp_cluster_list = -1; /* cluster list tree */
+static gint ett_bgp_options = -1; /* optional parameters tree */
+static gint ett_bgp_option = -1; /* an optional parameter tree */
+static gint ett_bgp_extended_communities = -1 ; /* extended communities list tree */
+static gint ett_bgp_orf = -1; /* orf (outbound route filter) tree */
+static gint ett_bgp_orf_entry = -1; /* orf entry tree */
+
+/* desegmentation */
+static gboolean bgp_desegment = TRUE;
+
+static gint bgp_asn_len = 0;
+
+/*
+ * Decode an IPv4 prefix.
+ */
+static int
+decode_prefix4(proto_tree *tree, int hf_addr, tvbuff_t *tvb, gint offset,
+ guint16 tlen, char *tag)
+{
+ proto_item *ti;
+ proto_tree *prefix_tree;
+ union {
+ guint8 addr_bytes[4];
+ guint32 addr;
+ } ip_addr; /* IP address */
+ guint8 plen; /* prefix length */
+ int length; /* number of octets needed for prefix */
+
+ /* snarf length and prefix */
+ plen = tvb_get_guint8(tvb, offset);
+ length = ipv4_addr_and_mask(tvb, offset + 1, ip_addr.addr_bytes, plen);
+ if (length < 0) {
+ proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid (> 32)",
+ tag, plen);
+ return -1;
+ }
+
+ /* put prefix into protocol tree */
+ ti = proto_tree_add_text(tree, tvb, offset,
+ tlen != 0 ? tlen : 1 + length, "%s/%u",
+ ip_to_str(ip_addr.addr_bytes), plen);
+ prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
+ proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
+ tag, plen);
+ if (hf_addr != -1) {
+ proto_tree_add_ipv4(prefix_tree, hf_addr, tvb, offset + 1, length,
+ ip_addr.addr);
+ } else {
+ proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
+ "%s prefix: %s", tag, ip_to_str(ip_addr.addr_bytes));
+ }
+ return(1 + length);
+}
+
+/*
+ * Decode an IPv6 prefix.
+ */
+static int
+decode_prefix6(proto_tree *tree, int hf_addr, tvbuff_t *tvb, gint offset,
+ guint16 tlen, char *tag)
+{
+ proto_item *ti;
+ proto_tree *prefix_tree;
+ struct e_in6_addr addr; /* IPv6 address */
+ int plen; /* prefix length */
+ int length; /* number of octets needed for prefix */
+
+ /* snarf length and prefix */
+ plen = tvb_get_guint8(tvb, offset);
+ length = ipv6_addr_and_mask(tvb, offset + 1, &addr, plen);
+ if (length < 0) {
+ proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid",
+ tag, plen);
+ return -1;
+ }
+
+ /* put prefix into protocol tree */
+ ti = proto_tree_add_text(tree, tvb, offset,
+ tlen != 0 ? tlen : 1 + length, "%s/%u",
+ ip6_to_str(&addr), plen);
+ prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
+ proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
+ tag, plen);
+ if (hf_addr != -1) {
+ proto_tree_add_ipv6(prefix_tree, hf_addr, tvb, offset + 1, length,
+ addr.s6_addr);
+ } else {
+ proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
+ "%s prefix: %s", tag, ip6_to_str(&addr));
+ }
+ return(1 + length);
+}
+
+
+
+/*
+ * Decode an MPLS label stack
+ * XXX - Should we convert "buf" to a GString?
+ */
+static guint
+decode_MPLS_stack(tvbuff_t *tvb, gint offset, char *buf, size_t buflen)
+{
+ guint32 label_entry; /* an MPLS label enrty (label + COS field + stack bit */
+ gint index; /* index for the label stack */
+ char junk_buf[256]; /* tmp */
+
+ index = offset ;
+ label_entry = 0x000000 ;
+
+ buf[0] = '\0' ;
+
+ while ((label_entry & 0x000001) == 0) {
+
+ label_entry = tvb_get_ntoh24(tvb, index) ;
+
+ /* withdrawn routes may contain 0 or 0x800000 in the first label */
+ if((index-offset)==0&&(label_entry==0||label_entry==0x800000)) {
+ snprintf(buf, buflen, "0 (withdrawn)");
+ return (1);
+ }
+
+ snprintf(junk_buf, sizeof(junk_buf),"%u%s", (label_entry >> 4), ((label_entry & 0x000001) == 0) ? "," : " (bottom)");
+ if (strlen(buf) + strlen(junk_buf) + 1 <= buflen)
+ strcat(buf, junk_buf);
+ index += 3 ;
+
+ if ((label_entry & 0x000001) == 0) {
+ /* real MPLS multi-label stack in BGP? - maybe later; for now, it must be a bogus packet */
+ strcpy(junk_buf, " (BOGUS: Bottom of Stack NOT set!)");
+ if (strlen(buf) + strlen(junk_buf) + 1 <= buflen)
+ strcat(buf, junk_buf);
+ break;
+ }
+ }
+
+ return((index - offset) / 3);
+}
+
+/*
+ * Decode a multiprotocol address
+ */
+
+static int
+mp_addr_to_str (guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, GString *buf)
+{
+ int length; /* length of the address in byte */
+ guint8 ip4addr[4],ip4addr2[4]; /* IPv4 address */
+ guint16 rd_type; /* Route Distinguisher type */
+ struct e_in6_addr ip6addr; /* IPv6 address */
+
+ length = 0 ;
+ switch (afi) {
+ case AFNUM_INET:
+ switch (safi) {
+ case SAFNUM_UNICAST:
+ case SAFNUM_MULCAST:
+ case SAFNUM_UNIMULC:
+ case SAFNUM_MPLS_LABEL:
+ length = 4 ;
+ tvb_memcpy(tvb, ip4addr, offset, sizeof(ip4addr));
+ g_string_sprintf(buf, "%s", ip_to_str(ip4addr));
+ break;
+ case SAFNUM_LAB_VPNUNICAST:
+ case SAFNUM_LAB_VPNMULCAST:
+ case SAFNUM_LAB_VPNUNIMULC:
+ rd_type=tvb_get_ntohs(tvb,offset) ;
+ switch (rd_type) {
+ case FORMAT_AS2_LOC:
+ length = 8 + sizeof(ip4addr);
+ tvb_memcpy(tvb, ip4addr, offset + 8, sizeof(ip4addr)); /* Next Hop */
+ g_string_sprintf(buf, "Empty Label Stack RD=%u:%u IP=%s",
+ tvb_get_ntohs(tvb, offset + 2),
+ tvb_get_ntohl(tvb, offset + 4),
+ ip_to_str(ip4addr));
+ break;
+ case FORMAT_IP_LOC:
+ length = 8 + sizeof(ip4addr);
+ tvb_memcpy(tvb, ip4addr, offset + 2, sizeof(ip4addr)); /* IP part of the RD */
+ tvb_memcpy(tvb, ip4addr2, offset + 8, sizeof(ip4addr)); /* Next Hop */
+ g_string_sprintf(buf, "Empty Label Stack RD=%s:%u IP=%s",
+ ip_to_str(ip4addr),
+ tvb_get_ntohs(tvb, offset + 6),
+ ip_to_str(ip4addr2));
+ break ;
+ default:
+ length = 0 ;
+ g_string_sprintf(buf, "Unknown (0x%04x)labeled VPN address format",rd_type);
+ break;
+ }
+ break;
+ default:
+ length = 0 ;
+ g_string_sprintf(buf, "Unknown SAFI (%u) for AFI %u", safi, afi);
+ break;
+ }
+ break;
+ case AFNUM_INET6:
+ switch (safi) {
+ case SAFNUM_UNICAST:
+ case SAFNUM_MULCAST:
+ case SAFNUM_UNIMULC:
+ case SAFNUM_MPLS_LABEL:
+ length = 16 ;
+ tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8,offset, 16);
+ g_string_sprintf(buf, "%s", ip6_to_str(&ip6addr));
+ break;
+ case SAFNUM_LAB_VPNUNICAST:
+ case SAFNUM_LAB_VPNMULCAST:
+ case SAFNUM_LAB_VPNUNIMULC:
+ rd_type=tvb_get_ntohs(tvb,offset) ;
+ switch (rd_type) {
+ case FORMAT_AS2_LOC:
+ length = 8 + 16;
+ tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, 16); /* Next Hop */
+ g_string_sprintf(buf, "Empty Label Stack RD=%u:%u IP=%s",
+ tvb_get_ntohs(tvb, offset + 2),
+ tvb_get_ntohl(tvb, offset + 4),
+ ip6_to_str(&ip6addr));
+ break;
+ case FORMAT_IP_LOC:
+ length = 8 + 16;
+ tvb_memcpy(tvb, ip4addr, offset + 2, sizeof(ip4addr)); /* IP part of the RD */
+ tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, 16); /* Next Hop */
+ g_string_sprintf(buf, "Empty Label Stack RD=%s:%u IP=%s",
+ ip_to_str(ip4addr),
+ tvb_get_ntohs(tvb, offset + 6),
+ ip6_to_str(&ip6addr));
+ break ;
+ default:
+ length = 0 ;
+ g_string_sprintf(buf, "Unknown (0x%04x)labeled VPN address format",rd_type);
+ break;
+ }
+ break;
+ default:
+ length = 0 ;
+ g_string_sprintf(buf, "Unknown SAFI (%u) for AFI %u", safi, afi);
+ break;
+ }
+ break;
+ case AFNUM_L2VPN:
+ switch (safi) {
+ case SAFNUM_LAB_VPNUNICAST: /* only labeles prefixes do make sense */
+ case SAFNUM_LAB_VPNMULCAST:
+ case SAFNUM_LAB_VPNUNIMULC:
+ length = 4; /* the next-hop is simply an ipv4 addr */
+ tvb_memcpy(tvb, ip4addr, offset + 0, 4);
+ g_string_sprintf(buf, "IP=%s",
+ ip_to_str(ip4addr));
+ break;
+ default:
+ length = 0 ;
+ g_string_sprintf(buf, "Unknown SAFI (%u) for AFI %u", safi, afi);
+ break;
+ }
+ break;
+ default:
+ length = 0 ;
+ g_string_sprintf(buf, "Unknown AFI (%u) value", afi);
+ break;
+ }
+ return(length) ;
+}
+
+/*
+ * Decode a multiprotocol prefix
+ */
+static int
+decode_prefix_MP(proto_tree *tree, int hf_addr4, int hf_addr6,
+ guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, char *tag)
+{
+ int start_offset = offset;
+ proto_item *ti;
+ proto_tree *prefix_tree;
+ int total_length; /* length of the entire item */
+ int length; /* length of the prefix address, in bytes */
+ guint plen; /* length of the prefix address, in bits */
+ guint labnum; /* number of labels */
+ int ce_id,labblk_off;
+ union {
+ guint8 addr_bytes[4];
+ guint32 addr;
+ } ip4addr, ip4addr2; /* IPv4 address */
+ struct e_in6_addr ip6addr; /* IPv6 address */
+ guint16 rd_type; /* Route Distinguisher type */
+ char lab_stk[256]; /* label stack */
+
+ switch (afi) {
+
+ case AFNUM_INET:
+ switch (safi) {
+
+ case SAFNUM_UNICAST:
+ case SAFNUM_MULCAST:
+ case SAFNUM_UNIMULC:
+ total_length = decode_prefix4(tree, hf_addr4, tvb, offset, 0, tag);
+ if (total_length < 0)
+ return -1;
+ break;
+
+ case SAFNUM_MPLS_LABEL:
+ plen = tvb_get_guint8(tvb, offset);
+ labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
+
+ offset += (1 + labnum * 3);
+ if (plen <= (labnum * 3*8)) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv4 prefix length %u invalid", tag, plen);
+ return -1;
+ }
+ plen -= (labnum * 3*8);
+ length = ipv4_addr_and_mask(tvb, offset, ip4addr.addr_bytes, plen);
+ if (length < 0) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv4 prefix length %u invalid",
+ tag, plen + (labnum * 3*8));
+ return -1;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, start_offset,
+ (offset + 1 + length) - start_offset,
+ "Label Stack=%s IP=%s/%u",
+ lab_stk, ip_to_str(ip4addr.addr_bytes), plen);
+ prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
+ if (hf_addr4 != -1) {
+ proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb, offset + 1,
+ length, ip4addr.addr);
+ } else {
+ proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
+ "%s IPv4 prefix: %s",
+ tag, ip_to_str(ip4addr.addr_bytes));
+ }
+ total_length = (1 + labnum*3) + length;
+ break;
+
+ case SAFNUM_LAB_VPNUNICAST:
+ case SAFNUM_LAB_VPNMULCAST:
+ case SAFNUM_LAB_VPNUNIMULC:
+ plen = tvb_get_guint8(tvb, offset);
+ labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
+
+ offset += (1 + labnum * 3);
+ if (plen <= (labnum * 3*8)) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv4 prefix length %u invalid", tag, plen);
+ return -1;
+ }
+ plen -= (labnum * 3*8);
+
+ rd_type = tvb_get_ntohs(tvb, offset);
+ if (plen <= 8*8) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv4 prefix length %u invalid",
+ tag, plen + (labnum * 3*8));
+ return -1;
+ }
+ plen -= 8*8;
+
+ switch (rd_type) {
+
+ case FORMAT_AS2_LOC: /* Code borrowed from the decode_prefix4 function */
+ length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr.addr_bytes, plen);
+ if (length < 0) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv4 prefix length %u invalid",
+ tag, plen + (labnum * 3*8) + 8*8);
+ return -1;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, start_offset,
+ (offset + 8 + length) - start_offset,
+ "Label Stack=%s RD=%u:%u, IP=%s/%u",
+ lab_stk,
+ tvb_get_ntohs(tvb, offset + 2),
+ tvb_get_ntohl(tvb, offset + 4),
+ ip_to_str(ip4addr.addr_bytes), plen);
+ prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
+ if (hf_addr4 != -1) {
+ proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
+ offset + 8, length, ip4addr.addr);
+ } else {
+ proto_tree_add_text(prefix_tree, tvb, offset + 8,
+ length, "%s IPv4 prefix: %s", tag,
+ ip_to_str(ip4addr.addr_bytes));
+ }
+ total_length = (1 + labnum * 3 + 8) + length;
+ break;
+
+ case FORMAT_IP_LOC: /* Code borrowed from the decode_prefix4 function */
+ tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
+
+ length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr2.addr_bytes, plen);
+ if (length < 0) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv4 prefix length %u invalid",
+ tag, plen + (labnum * 3*8) + 8*8);
+ return -1;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, start_offset,
+ (offset + 8 + length) - start_offset,
+ "Label Stack=%s RD=%s:%u, IP=%s/%u",
+ lab_stk,
+ ip_to_str(ip4addr.addr_bytes),
+ tvb_get_ntohs(tvb, offset + 6),
+ ip_to_str(ip4addr2.addr_bytes),
+ plen);
+ total_length = (1 + labnum * 3 + 8) + length;
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, start_offset,
+ (offset - start_offset) + 2,
+ "Unknown labeled VPN address format %u", rd_type);
+ return -1;
+ }
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, start_offset, 0,
+ "Unknown SAFI (%u) for AFI %u", safi, afi);
+ return -1;
+ }
+ break;
+
+ case AFNUM_INET6:
+ switch (safi) {
+
+ case SAFNUM_UNICAST:
+ case SAFNUM_MULCAST:
+ case SAFNUM_UNIMULC:
+ total_length = decode_prefix6(tree, hf_addr6, tvb, offset, 0, tag);
+ if (total_length < 0)
+ return -1;
+ break;
+
+ case SAFNUM_MPLS_LABEL:
+ plen = tvb_get_guint8(tvb, offset);
+ labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
+
+ offset += (1 + labnum * 3);
+ if (plen <= (labnum * 3*8)) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv6 prefix length %u invalid", tag, plen);
+ return -1;
+ }
+ plen -= (labnum * 3*8);
+
+ length = ipv6_addr_and_mask(tvb, offset, &ip6addr, plen);
+ if (length < 0) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv6 prefix length %u invalid", tag, plen);
+ return -1;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, start_offset,
+ (offset + length) - start_offset,
+ "Label Stack=%s, IP=%s/%u",
+ lab_stk,
+ ip6_to_str(&ip6addr), plen);
+ total_length = (1 + labnum * 3) + length;
+ break;
+
+ case SAFNUM_LAB_VPNUNICAST:
+ case SAFNUM_LAB_VPNMULCAST:
+ case SAFNUM_LAB_VPNUNIMULC:
+ plen = tvb_get_guint8(tvb, offset);
+ labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
+
+ offset += (1 + labnum * 3);
+ if (plen <= (labnum * 3*8)) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv6 prefix length %u invalid", tag, plen);
+ return -1;
+ }
+ plen -= (labnum * 3*8);
+
+ rd_type = tvb_get_ntohs(tvb,offset);
+ if (plen <= 8*8) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv6 prefix length %u invalid",
+ tag, plen + (labnum * 3*8));
+ return -1;
+ }
+ plen -= 8*8;
+
+ switch (rd_type) {
+
+ case FORMAT_AS2_LOC:
+ length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
+ if (length < 0) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv6 prefix length %u invalid",
+ tag, plen + (labnum * 3*8) + 8*8);
+ return -1;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, start_offset,
+ (offset + 8 + length) - start_offset,
+ "Label Stack=%s RD=%u:%u, IP=%s/%u",
+ lab_stk,
+ tvb_get_ntohs(tvb, offset + 2),
+ tvb_get_ntohl(tvb, offset + 4),
+ ip6_to_str(&ip6addr), plen);
+ total_length = (1 + labnum * 3 + 8) + length;
+ break;
+
+ case FORMAT_IP_LOC:
+ tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
+
+ length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
+ if (length < 0) {
+ proto_tree_add_text(tree, tvb, start_offset, 1,
+ "%s IPv6 prefix length %u invalid",
+ tag, plen + (labnum * 3*8) + 8*8);
+ return -1;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, start_offset,
+ (offset + 8 + length) - start_offset,
+ "Label Stack=%s RD=%s:%u, IP=%s/%u",
+ lab_stk,
+ ip_to_str(ip4addr.addr_bytes),
+ tvb_get_ntohs(tvb, offset + 6),
+ ip6_to_str(&ip6addr), plen);
+ total_length = (1 + labnum * 3 + 8) + length;
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, start_offset, 0,
+ "Unknown labeled VPN address format %u", rd_type);
+ return -1;
+ }
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, start_offset, 0,
+ "Unknown SAFI (%u) for AFI %u", safi, afi);
+ return -1;
+ }
+ break;
+
+ case AFNUM_L2VPN:
+ switch (safi) {
+
+ case SAFNUM_LAB_VPNUNICAST:
+ case SAFNUM_LAB_VPNMULCAST:
+ case SAFNUM_LAB_VPNUNIMULC:
+ plen = tvb_get_ntohs(tvb,offset);
+ rd_type=tvb_get_ntohs(tvb,offset+2);
+ ce_id=tvb_get_ntohs(tvb,offset+10);
+ labblk_off=tvb_get_ntohs(tvb,offset+12);
+ labnum = decode_MPLS_stack(tvb, offset + 14, lab_stk, sizeof(lab_stk));
+
+ switch (rd_type) {
+
+ case FORMAT_AS2_LOC:
+ tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 6, 4);
+ proto_tree_add_text(tree, tvb, start_offset,
+ (offset + plen + 1) - start_offset,
+ "RD: %u:%s, CE-ID: %u, Label-Block Offset: %u, Label Base %s",
+ tvb_get_ntohs(tvb, offset + 4),
+ ip_to_str(ip4addr.addr_bytes),
+ ce_id,
+ labblk_off,
+ lab_stk);
+ break;
+
+ case FORMAT_IP_LOC:
+ tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 4, 4);
+ proto_tree_add_text(tree, tvb, offset,
+ (offset + plen + 1) - start_offset,
+ "RD: %s:%u, CE-ID: %u, Label-Block Offset: %u, Label Base %s",
+ ip_to_str(ip4addr.addr_bytes),
+ tvb_get_ntohs(tvb, offset + 8),
+ ce_id,
+ labblk_off,
+ lab_stk);
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, start_offset,
+ (offset - start_offset) + 2,
+ "Unknown labeled VPN address format %u", rd_type);
+ return -1;
+ }
+ /* FIXME there are subTLVs left to decode ... for now lets omit them */
+ total_length = plen+2;
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, start_offset, 0,
+ "Unknown SAFI (%u) for AFI %u", safi, afi);
+ return -1;
+ }
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, start_offset, 0,
+ "Unknown AFI (%u) value", afi);
+ return -1;
+ }
+ return(total_length);
+}
+
+/*
+ * Dissect a BGP capability.
+ */
+static void
+dissect_bgp_capability_item(tvbuff_t *tvb, int *p, proto_tree *tree, int ctype, int clen)
+{
+ proto_tree *subtree;
+ proto_item *ti;
+ guint8 orfnum; /* number of ORFs */
+ guint8 orftype; /* ORF Type */
+ guint8 orfsendrecv; /* ORF Send/Receive */
+ int tclen; /* capability length */
+ int i;
+
+ /* check the capability type */
+ switch (ctype) {
+ case BGP_CAPABILITY_RESERVED:
+ proto_tree_add_text(tree, tvb, *p - 2, 1,
+ "Capability code: %s (%d)", val_to_str(ctype,
+ capability_vals, "Unknown capability"), ctype);
+ proto_tree_add_text(tree, tvb, *p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ if (clen != 0) {
+ proto_tree_add_text(tree, tvb, *p,
+ clen, "Capability value: Unknown");
+ }
+ *p += clen;
+ break;
+ case BGP_CAPABILITY_MULTIPROTOCOL:
+ proto_tree_add_text(tree, tvb, *p - 2, 1,
+ "Capability code: %s (%d)", val_to_str(ctype,
+ capability_vals, "Unknown capability"), ctype);
+ if (clen != 4) {
+ proto_tree_add_text(tree, tvb, *p - 1,
+ 1, "Capability length: Invalid");
+ proto_tree_add_text(tree, tvb, *p,
+ clen, "Capability value: Unknown");
+ }
+ else {
+ proto_tree_add_text(tree, tvb, *p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
+ subtree = proto_item_add_subtree(ti, ett_bgp_option);
+ /* AFI */
+ i = tvb_get_ntohs(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p,
+ 2, "Address family identifier: %s (%u)",
+ val_to_str(i, afn_vals, "Unknown"), i);
+ *p += 2;
+ /* Reserved */
+ proto_tree_add_text(subtree, tvb, *p, 1, "Reserved: 1 byte");
+ (*p)++;
+ /* SAFI */
+ i = tvb_get_guint8(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p,
+ 1, "Subsequent address family identifier: %s (%u)",
+ val_to_str(i, bgpattr_nlri_safi,
+ i >= 128 ? "Vendor specific" : "Unknown"), i);
+ (*p)++;
+ }
+ break;
+ case BGP_CAPABILITY_GRACEFUL_RESTART:
+ proto_tree_add_text(tree, tvb, *p - 2, 1,
+ "Capability code: %s (%d)", val_to_str(ctype,
+ capability_vals, "Unknown capability"), ctype);
+ if (clen < 6) {
+ proto_tree_add_text(tree, tvb, *p,
+ clen, "Capability value: Invalid");
+ }
+ else {
+ proto_tree_add_text(tree, tvb, *p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
+ subtree = proto_item_add_subtree(ti, ett_bgp_option);
+ /* Timers */
+ i = tvb_get_ntohs(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p,
+ 2, "Restart Flags: [%s], Restart Time %us",
+ (i&0x8000) ? "R" : "none", i&0xfff);
+ *p += 2;
+ tclen = clen - 2;
+ /*
+ * what follows is alist of AFI/SAFI/flag triplets
+ * read it until the TLV ends
+ */
+ while (tclen >=4) {
+ /* AFI */
+ i = tvb_get_ntohs(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p,
+ 2, "Address family identifier: %s (%u)",
+ val_to_str(i, afn_vals, "Unknown"), i);
+ *p += 2;
+ /* SAFI */
+ i = tvb_get_guint8(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p,
+ 1, "Subsequent address family identifier: %s (%u)",
+ val_to_str(i, bgpattr_nlri_safi,
+ i >= 128 ? "Vendor specific" : "Unknown"), i);
+ (*p)++;
+ /* flags */
+ i = tvb_get_guint8(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p, 1,
+ "Preserve forwarding state: %s",
+ (i&0x80) ? "yes" : "no");
+ (*p)++;
+ tclen-=4;
+ }
+ }
+ *p += clen;
+ break;
+ case BGP_CAPABILITY_4_OCTET_AS_NUMBER:
+ proto_tree_add_text(tree, tvb, *p - 2, 1,
+ "Capability code: %s (%d)", val_to_str(ctype,
+ capability_vals, "Unknown capability"), ctype);
+ if (clen != 4) {
+ proto_tree_add_text(tree, tvb, *p,
+ clen, "Capability value: Invalid");
+ }
+ else {
+ proto_tree_add_text(tree, tvb, *p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
+ subtree = proto_item_add_subtree(ti, ett_bgp_option);
+ proto_tree_add_text(subtree, tvb, *p, 4,
+ "AS number: %d", tvb_get_ntohl(tvb, *p));
+ }
+ *p += clen;
+ break;
+ case BGP_CAPABILITY_DYNAMIC_CAPABILITY:
+ proto_tree_add_text(tree, tvb, *p - 2, 1,
+ "Capability code: %s (%d)", val_to_str(ctype,
+ capability_vals, "Unknown capability"), ctype);
+ proto_tree_add_text(tree, tvb, *p - 1, 1,
+ "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ if (clen > 0) {
+ ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
+ subtree = proto_item_add_subtree(ti, ett_bgp_option);
+ for (i = 0; (int)i <= clen; i++) {
+ proto_tree_add_text(subtree, tvb, *p, 1,
+ "Capability code: %s (%d)", val_to_str(ctype,
+ capability_vals, "Unknown capability"),
+ tvb_get_guint8(tvb, *p));
+ (*p)++;
+ }
+ }
+ break;
+ case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
+ case BGP_CAPABILITY_ROUTE_REFRESH:
+ proto_tree_add_text(tree, tvb, *p - 2, 1,
+ "Capability code: %s (%d)", val_to_str(ctype,
+ capability_vals, "Unknown capability"), ctype);
+ if (clen != 0) {
+ proto_tree_add_text(tree, tvb, *p,
+ clen, "Capability value: Invalid");
+ }
+ else {
+ proto_tree_add_text(tree, tvb, *p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ }
+ *p += clen;
+ break;
+ case BGP_CAPABILITY_ORF_CISCO:
+ case BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING:
+ proto_tree_add_text(tree, tvb, *p - 2, 1,
+ "Capability code: %s (%d)", val_to_str(ctype,
+ capability_vals, "Unknown capability"), ctype);
+ proto_tree_add_text(tree, tvb, *p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
+ subtree = proto_item_add_subtree(ti, ett_bgp_option);
+ /* AFI */
+ i = tvb_get_ntohs(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p,
+ 2, "Address family identifier: %s (%u)",
+ val_to_str(i, afn_vals, "Unknown"), i);
+ *p += 2;
+ /* Reserved */
+ proto_tree_add_text(subtree, tvb, *p, 1, "Reserved: 1 byte");
+ (*p)++;
+ /* SAFI */
+ i = tvb_get_guint8(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p,
+ 1, "Subsequent address family identifier: %s (%u)",
+ val_to_str(i, bgpattr_nlri_safi,
+ i >= 128 ? "Vendor specific" : "Unknown"), i);
+ (*p)++;
+ /* Number of ORFs */
+ orfnum = tvb_get_guint8(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p, 1, "Number of ORFs: %u", orfnum);
+ (*p)++;
+ for (i=0; i<orfnum; i++) {
+ /* ORF Type */
+ orftype = tvb_get_guint8(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p, 1, "ORF Type: %s (%u)",
+ val_to_str(orftype, orf_type_vals,"Unknown"), orftype);
+ (*p)++;
+ /* Send/Receive */
+ orfsendrecv = tvb_get_guint8(tvb, *p);
+ proto_tree_add_text(subtree, tvb, *p,
+ 1, "Send/Receive: %s (%u)",
+ val_to_str(orfsendrecv, orf_send_recv_vals,
+ "Uknown"), orfsendrecv);
+ (*p)++;
+ }
+ break;
+ /* unknown capability */
+ default:
+ proto_tree_add_text(tree, tvb, *p - 2, 1,
+ "Capability code: %s (%d)", val_to_str(ctype,
+ capability_vals, "Unknown capability"), ctype);
+ proto_tree_add_text(tree, tvb, *p - 2,
+ 1, "Capability code: %s (%d)",
+ ctype >= 128 ? "Private use" : "Unknown", ctype);
+ proto_tree_add_text(tree, tvb, *p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ if (clen != 0) {
+ proto_tree_add_text(tree, tvb, *p,
+ clen, "Capability value: Unknown");
+ }
+ *p += clen;
+ break;
+ }
+}
+
+
+/*
+ * Dissect a BGP OPEN message.
+ */
+static const value_string community_vals[] = {
+ { BGP_COMM_NO_EXPORT, "NO_EXPORT" },
+ { BGP_COMM_NO_ADVERTISE, "NO_ADVERTISE" },
+ { BGP_COMM_NO_EXPORT_SUBCONFED, "NO_EXPORT_SUBCONFED" },
+ { 0, NULL }
+};
+
+static void
+dissect_bgp_open(tvbuff_t *tvb, proto_tree *tree)
+{
+ struct bgp_open bgpo; /* BGP OPEN message */
+ int hlen; /* message length */
+ int ptype; /* parameter type */
+ int plen; /* parameter length */
+ int ctype; /* capability type */
+ int clen; /* capability length */
+ int cend; /* capabilities end */
+ int ostart; /* options start */
+ int oend; /* options end */
+ int p; /* tvb offset counter */
+ proto_item *ti; /* tree item */
+ proto_tree *subtree; /* subtree for options */
+ proto_tree *subtree1; /* subtree for an option */
+ proto_tree *subtree2; /* subtree for an option */
+
+ /* snarf OPEN message */
+ tvb_memcpy(tvb, bgpo.bgpo_marker, 0, BGP_MIN_OPEN_MSG_SIZE);
+ hlen = g_ntohs(bgpo.bgpo_len);
+
+ proto_tree_add_text(tree, tvb,
+ offsetof(struct bgp_open, bgpo_version), 1,
+ "Version: %u", bgpo.bgpo_version);
+ proto_tree_add_text(tree, tvb,
+ offsetof(struct bgp_open, bgpo_myas), 2,
+ "My AS: %u", g_ntohs(bgpo.bgpo_myas));
+ proto_tree_add_text(tree, tvb,
+ offsetof(struct bgp_open, bgpo_holdtime), 2,
+ "Hold time: %u", g_ntohs(bgpo.bgpo_holdtime));
+ proto_tree_add_text(tree, tvb,
+ offsetof(struct bgp_open, bgpo_id), 4,
+ "BGP identifier: %s", ip_to_str((guint8 *)&bgpo.bgpo_id));
+ proto_tree_add_text(tree, tvb,
+ offsetof(struct bgp_open, bgpo_optlen), 1,
+ "Optional parameters length: %u %s", bgpo.bgpo_optlen,
+ (bgpo.bgpo_optlen == 1) ? "byte" : "bytes");
+
+ /* optional parameters */
+ if (bgpo.bgpo_optlen > 0) {
+ /* add a subtree and setup some offsets */
+ ostart = BGP_MIN_OPEN_MSG_SIZE;
+ ti = proto_tree_add_text(tree, tvb, ostart, bgpo.bgpo_optlen,
+ "Optional parameters");
+ subtree = proto_item_add_subtree(ti, ett_bgp_options);
+ p = ostart;
+ oend = p + bgpo.bgpo_optlen;
+
+ /* step through all of the optional parameters */
+ while (p < oend) {
+
+ /* grab the type and length */
+ ptype = tvb_get_guint8(tvb, p++);
+ plen = tvb_get_guint8(tvb, p++);
+
+ /* check the type */
+ switch (ptype) {
+ case BGP_OPTION_AUTHENTICATION:
+ proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
+ "Authentication information (%u %s)", plen,
+ (plen == 1) ? "byte" : "bytes");
+ break;
+ case BGP_OPTION_CAPABILITY:
+ /* grab the capability code */
+ cend = p - 1 + plen;
+ ctype = tvb_get_guint8(tvb, p++);
+ clen = tvb_get_guint8(tvb, p++);
+ ti = proto_tree_add_text(subtree, tvb, p - 4,
+ 2 + plen, "Capabilities Advertisement (%u bytes)",
+ 2 + plen);
+ subtree1 = proto_item_add_subtree(ti, ett_bgp_option);
+ proto_tree_add_text(subtree1, tvb, p - 4,
+ 1, "Parameter type: Capabilities (2)");
+ proto_tree_add_text(subtree1, tvb, p - 3,
+ 1, "Parameter length: %u %s", plen,
+ (plen == 1) ? "byte" : "bytes");
+ p -= 2;
+
+ /* step through all of the capabilities */
+ while (p < cend) {
+ ctype = tvb_get_guint8(tvb, p++);
+ clen = tvb_get_guint8(tvb, p++);
+
+ ti = proto_tree_add_text(subtree1, tvb, p - 2,
+ 2 + clen, "%s (%u %s)", val_to_str(ctype,
+ capability_vals, "Unknown capability"),
+ 2 + clen, (clen == 1) ? "byte" : "bytes");
+ subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+ dissect_bgp_capability_item(tvb, &p,
+ subtree2, ctype, clen);
+ }
+ break;
+ default:
+ proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
+ "Unknown optional parameter");
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Dissect a BGP UPDATE message.
+ */
+static void
+dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree)
+{
+ struct bgp_attr bgpa; /* path attributes */
+ guint16 hlen; /* message length */
+ gint o; /* packet offset */
+ gint q; /* tmp */
+ gint end; /* message end */
+ guint16 ext_com; /* EXTENDED COMMUNITY type */
+ guint16 len; /* tmp */
+ int advance; /* tmp */
+ proto_item *ti; /* tree item */
+ proto_tree *subtree; /* subtree for attributes */
+ proto_tree *subtree2; /* subtree for attributes */
+ proto_tree *subtree3; /* subtree for attributes */
+ proto_tree *subtree4; /* subtree for attributes */
+ proto_tree *as_paths_tree; /* subtree for AS_PATHs */
+ proto_tree *as_path_tree; /* subtree for AS_PATH */
+ proto_tree *as_path_segment_tree; /* subtree for AS_PATH segments */
+ proto_tree *communities_tree; /* subtree for COMMUNITIES */
+ proto_tree *community_tree; /* subtree for a community */
+ proto_tree *cluster_list_tree; /* subtree for CLUSTER_LIST */
+ int i, j; /* tmp */
+ guint8 length; /* AS_PATH length */
+ guint8 type; /* AS_PATH type */
+ guint32 as_path_item; /* item in AS_PATH segment */
+ static GString *as_path_gstr = NULL; /* AS_PATH GString */
+ static GString *communities_gstr = NULL; /* COMMUNITIES GString */
+ static GString *cluster_list_gstr = NULL; /* CLUSTER_LIST GString */
+ static GString *junk_gbuf = NULL; /* tmp */
+ guint8 ipaddr[4]; /* IPv4 address */
+ guint32 aggregator_as;
+
+ hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
+ o = BGP_HEADER_SIZE;
+ if (junk_gbuf == NULL)
+ junk_gbuf = g_string_sized_new(0);
+
+ /* check for withdrawals */
+ len = tvb_get_ntohs(tvb, o);
+ proto_tree_add_text(tree, tvb, o, 2,
+ "Unfeasible routes length: %u %s", len, (len == 1) ? "byte" : "bytes");
+ o += 2;
+
+ /* parse unfeasible prefixes */
+ if (len > 0) {
+ ti = proto_tree_add_text(tree, tvb, o, len, "Withdrawn routes:");
+ subtree = proto_item_add_subtree(ti, ett_bgp_unfeas);
+
+ /* parse each prefix */
+ end = o + len;
+ while (o < end) {
+ i = decode_prefix4(subtree, hf_bgp_withdrawn_prefix, tvb, o, len,
+ "Withdrawn route");
+ if (i < 0)
+ return;
+ o += i;
+ }
+ }
+
+ /* check for advertisements */
+ len = tvb_get_ntohs(tvb, o);
+ proto_tree_add_text(tree, tvb, o, 2, "Total path attribute length: %u %s",
+ len, (len == 1) ? "byte" : "bytes");
+
+ /* path attributes */
+ if (len > 0) {
+ ti = proto_tree_add_text(tree, tvb, o + 2, len, "Path attributes");
+ subtree = proto_item_add_subtree(ti, ett_bgp_attrs);
+ i = 2;
+ while (i < len) {
+ char *msg;
+ int off;
+ gint k;
+ guint16 alen, tlen, aoff;
+ guint16 af;
+ guint8 saf, snpa;
+ guint8 nexthop_len;
+ guint8 asn_len = 0;
+
+ tvb_memcpy(tvb, (guint8 *)&bgpa, o + i, sizeof(bgpa));
+ /* check for the Extended Length bit */
+ if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
+ alen = tvb_get_ntohs(tvb, o + i + sizeof(bgpa));
+ aoff = sizeof(bgpa) + 2;
+ } else {
+ alen = tvb_get_guint8(tvb, o + i + sizeof(bgpa));
+ aoff = sizeof(bgpa) + 1;
+ }
+ tlen = alen;
+
+ /* This is kind of ugly - similar code appears twice, but it
+ helps browsing attrs. */
+ /* the first switch prints things in the title of the subtree */
+ switch (bgpa.bgpa_type) {
+ case BGPTYPE_ORIGIN:
+ if (tlen != 1)
+ goto default_attribute_top;
+ msg = val_to_str(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown");
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s: %s (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ msg, tlen + aoff, (tlen + aoff == 1) ? "byte" :
+ "bytes");
+ break;
+ case BGPTYPE_AS_PATH:
+ case BGPTYPE_NEW_AS_PATH:
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + tlen;
+ /* must be freed by second switch! */
+ /* "tlen * 11" (10 digits + space) should be a good estimate
+ of how long the AS path string could be */
+ if (as_path_gstr == NULL)
+ as_path_gstr = g_string_sized_new((tlen + 1) * 11);
+ if (as_path_gstr == NULL) break;
+ g_string_truncate(as_path_gstr, 0);
+
+ /* estimate the length of the AS number */
+ if (bgpa.bgpa_type == BGPTYPE_NEW_AS_PATH)
+ asn_len = 4;
+ else {
+ if (bgp_asn_len == 0) {
+ k = q;
+ while (k < end) {
+ k++;
+ length = tvb_get_guint8(tvb, k++);
+ k += length * 2;
+ }
+ asn_len = (k == end) ? 2 : 4;
+ }
+ else {
+ asn_len = bgp_asn_len;
+ }
+ }
+
+ /* snarf each AS path */
+ while (q < end) {
+ type = tvb_get_guint8(tvb, q++);
+ if (as_path_gstr->len > 1 &&
+ as_path_gstr->str[as_path_gstr->len - 1] != ' ')
+ g_string_append_c(as_path_gstr, ' ');
+ if (type == AS_SET) {
+ g_string_append_c(as_path_gstr, '{');
+ }
+ else if (type == AS_CONFED_SET) {
+ g_string_append_c(as_path_gstr, '[');
+ }
+ else if (type == AS_CONFED_SEQUENCE) {
+ g_string_append_c(as_path_gstr, '(');
+ }
+ length = tvb_get_guint8(tvb, q++);
+
+ /* snarf each value in path */
+ for (j = 0; j < length; j++) {
+ g_string_sprintfa(as_path_gstr, "%u%s",
+ (asn_len == 2) ?
+ tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
+ (type == AS_SET || type == AS_CONFED_SET) ?
+ ", " : " ");
+ q += asn_len;
+ }
+
+ /* cleanup end of string */
+ if (type == AS_SET) {
+ g_string_truncate(as_path_gstr, as_path_gstr->len - 2);
+ g_string_append_c(as_path_gstr, '}');
+ }
+ else if (type == AS_CONFED_SET) {
+ g_string_truncate(as_path_gstr, as_path_gstr->len - 2);
+ g_string_append_c(as_path_gstr, ']');
+ }
+ else if (type == AS_CONFED_SEQUENCE) {
+ g_string_truncate(as_path_gstr, as_path_gstr->len - 1);
+ g_string_append_c(as_path_gstr, ')');
+ }
+ else {
+ g_string_truncate(as_path_gstr, as_path_gstr->len - 1);
+ }
+ }
+
+ /* check for empty AS_PATH */
+ if (tlen == 0)
+ g_string_sprintf(as_path_gstr, "empty");
+
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s: %s (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ as_path_gstr->str, tlen + aoff,
+ (tlen + aoff == 1) ? "byte" : "bytes");
+ break;
+ case BGPTYPE_NEXT_HOP:
+ if (tlen != 4)
+ goto default_attribute_top;
+ tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s: %s (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ ip_to_str(ipaddr), tlen + aoff, (tlen + aoff == 1)
+ ? "byte" : "bytes");
+ break;
+ case BGPTYPE_MULTI_EXIT_DISC:
+ if (tlen != 4)
+ goto default_attribute_top;
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s: %u (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
+ (tlen + aoff == 1) ? "byte" : "bytes");
+ break;
+ case BGPTYPE_LOCAL_PREF:
+ if (tlen != 4)
+ goto default_attribute_top;
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s: %u (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
+ (tlen + aoff == 1) ? "byte" : "bytes");
+ break;
+ case BGPTYPE_ATOMIC_AGGREGATE:
+ if (tlen != 0)
+ goto default_attribute_top;
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ tlen + aoff, (tlen + aoff == 1) ? "byte" : "bytes");
+ break;
+ case BGPTYPE_AGGREGATOR:
+ if (tlen != 6 && tlen != 8)
+ goto default_attribute_top;
+ case BGPTYPE_NEW_AGGREGATOR:
+ if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
+ goto default_attribute_top;
+ asn_len = tlen - 4;
+ tvb_memcpy(tvb, ipaddr, o + i + aoff + asn_len, 4);
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s: AS: %u origin: %s (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ (asn_len == 2) ? tvb_get_ntohs(tvb, o + i + aoff) :
+ tvb_get_ntohl(tvb, o + i + aoff),
+ ip_to_str(ipaddr), tlen + aoff,
+ (tlen + aoff == 1) ? "byte" : "bytes");
+ break;
+ case BGPTYPE_COMMUNITIES:
+ if (tlen % 4 != 0)
+ goto default_attribute_top;
+
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + tlen;
+ /* must be freed by second switch! */
+ /* "tlen * 12" (5 digits, a :, 5 digits + space ) should be
+ a good estimate of how long the communities string could
+ be */
+ if (communities_gstr == NULL)
+ communities_gstr = g_string_sized_new((tlen + 1) * 12);
+ if (communities_gstr == NULL) break;
+ g_string_truncate(communities_gstr, 0);
+
+ /* snarf each community */
+ while (q < end) {
+ /* check for well-known communities */
+ if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT)
+ g_string_append(communities_gstr, "NO_EXPORT ");
+ else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_ADVERTISE)
+ g_string_append(communities_gstr, "NO_ADVERTISE ");
+ else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT_SUBCONFED)
+ g_string_append(communities_gstr, "NO_EXPORT_SUBCONFED ");
+ else {
+ g_string_sprintfa(communities_gstr, "%u:%u ",
+ tvb_get_ntohs(tvb, q),
+ tvb_get_ntohs(tvb, q + 2));
+ }
+ q += 4;
+ }
+ /* cleanup end of string */
+ g_string_truncate(communities_gstr, communities_gstr->len - 1);
+
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s: %s (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ communities_gstr->str, tlen + aoff,
+ (tlen + aoff == 1) ? "byte" : "bytes");
+ break;
+ case BGPTYPE_ORIGINATOR_ID:
+ if (tlen != 4)
+ goto default_attribute_top;
+ tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s: %s (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ ip_to_str(ipaddr), tlen + aoff, (tlen + aoff == 1)
+ ? "byte" : "bytes");
+ break;
+ case BGPTYPE_CLUSTER_LIST:
+ if (tlen % 4 != 0)
+ goto default_attribute_top;
+
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + tlen;
+ /* must be freed by second switch! */
+ /* "tlen * 16" (12 digits, 3 dots + space ) should be
+ a good estimate of how long the cluster_list string could
+ be */
+ if (cluster_list_gstr == NULL)
+ cluster_list_gstr = g_string_sized_new((tlen + 1) * 16);
+ if (cluster_list_gstr == NULL) break;
+ g_string_truncate(cluster_list_gstr, 0);
+
+ /* snarf each cluster list */
+ tvb_memcpy(tvb, ipaddr, q, 4);
+ while (q < end) {
+ g_string_sprintfa(cluster_list_gstr, "%s ", ip_to_str(ipaddr));
+ q += 4;
+ }
+ /* cleanup end of string */
+ g_string_truncate(cluster_list_gstr, cluster_list_gstr->len - 1);
+
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s: %s (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ cluster_list_gstr->str, tlen + aoff,
+ (tlen + aoff == 1) ? "byte" : "bytes");
+ break;
+ case BGPTYPE_EXTENDED_COMMUNITY:
+ if (tlen %8 != 0)
+ break;
+ ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff,
+ "%s: (%u %s)",
+ val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
+ tlen + aoff,
+ (tlen + aoff == 1) ? "byte" : "bytes");
+ break;
+
+ default:
+ default_attribute_top:
+ ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
+ "%s (%u %s)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ tlen + aoff, (tlen + aoff == 1) ? "byte" : "bytes");
+ } /* end of first switch */
+ subtree2 = proto_item_add_subtree(ti, ett_bgp_attr);
+
+ /* figure out flags */
+ g_string_truncate(junk_gbuf, 0);
+ if (bgpa.bgpa_flags & BGP_ATTR_FLAG_OPTIONAL) {
+ g_string_append(junk_gbuf, "Optional, ");
+ }
+ else {
+ g_string_append(junk_gbuf, "Well-known, ");
+ }
+ if (bgpa.bgpa_flags & BGP_ATTR_FLAG_TRANSITIVE) {
+ g_string_append(junk_gbuf, "Transitive, ");
+ }
+ else {
+ g_string_append(junk_gbuf, "Non-transitive, ");
+ }
+ if (bgpa.bgpa_flags & BGP_ATTR_FLAG_PARTIAL) {
+ g_string_append(junk_gbuf, "Partial, ");
+ }
+ else {
+ g_string_append(junk_gbuf, "Complete, ");
+ }
+ if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
+ g_string_append(junk_gbuf, "Extended Length, ");
+ }
+ /* stomp last ", " */
+ g_string_truncate(junk_gbuf, junk_gbuf->len - 2);
+ ti = proto_tree_add_text(subtree2, tvb,
+ o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
+ "Flags: 0x%02x (%s)", bgpa.bgpa_flags, junk_gbuf->str);
+ subtree3 = proto_item_add_subtree(ti, ett_bgp_attr_flags);
+
+ /* add flag bitfield subtrees */
+ proto_tree_add_text(subtree3, tvb,
+ o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
+ "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
+ BGP_ATTR_FLAG_OPTIONAL, 8, "Optional", "Well-known"));
+ proto_tree_add_text(subtree3, tvb,
+ o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
+ "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
+ BGP_ATTR_FLAG_TRANSITIVE, 8, "Transitive",
+ "Non-transitive"));
+ proto_tree_add_text(subtree3, tvb,
+ o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
+ "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
+ BGP_ATTR_FLAG_PARTIAL, 8, "Partial", "Complete"));
+ proto_tree_add_text(subtree3, tvb,
+ o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
+ "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
+ BGP_ATTR_FLAG_EXTENDED_LENGTH, 8, "Extended length",
+ "Regular length"));
+
+ proto_tree_add_text(subtree2, tvb,
+ o + i + offsetof(struct bgp_attr, bgpa_type), 1,
+ "Type code: %s (%u)",
+ val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
+ bgpa.bgpa_type);
+
+ proto_tree_add_text(subtree2, tvb, o + i + sizeof(bgpa),
+ aoff - sizeof(bgpa), "Length: %d %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+
+ /* the second switch prints things in the actual subtree of each
+ attribute */
+ switch (bgpa.bgpa_type) {
+ case BGPTYPE_ORIGIN:
+ if (tlen != 1) {
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Origin (invalid): %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+ } else {
+ proto_tree_add_item(subtree2, hf_bgp_origin, tvb,
+ o + i + aoff, 1, FALSE);
+ }
+ break;
+ case BGPTYPE_AS_PATH:
+ case BGPTYPE_NEW_AS_PATH:
+ ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "AS path: %s", as_path_gstr->str);
+ as_paths_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
+
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + tlen;
+
+ /* snarf each AS path tuple, we have to step through each one
+ again to make a separate subtree so we can't just reuse
+ as_path_gstr from above */
+ /* XXX - Can we use some g_string*() trickery instead, e.g.
+ g_string_erase()? */
+ while (q < end) {
+ g_string_truncate(as_path_gstr, 0);
+ type = tvb_get_guint8(tvb, q++);
+ if (type == AS_SET) {
+ g_string_append_c(as_path_gstr, '{');
+ }
+ else if (type == AS_CONFED_SET) {
+ g_string_append_c(as_path_gstr, '[');
+ }
+ else if (type == AS_CONFED_SEQUENCE) {
+ g_string_append_c(as_path_gstr, '(');
+ }
+ length = tvb_get_guint8(tvb, q++);
+
+ /* snarf each value in path */
+ for (j = 0; j < length; j++) {
+ g_string_sprintfa(as_path_gstr, "%u%s",
+ (asn_len == 2) ?
+ tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
+ (type == AS_SET || type == AS_CONFED_SET) ? ", " : " ");
+ q += asn_len;
+ }
+
+ /* cleanup end of string */
+ if (type == AS_SET) {
+ g_string_truncate(as_path_gstr, as_path_gstr->len - 2);
+ g_string_append_c(as_path_gstr, '}');
+ }
+ else if (type == AS_CONFED_SET) {
+ g_string_truncate(as_path_gstr, as_path_gstr->len - 2);
+ g_string_append_c(as_path_gstr, ']');
+ }
+ else if (type == AS_CONFED_SEQUENCE) {
+ g_string_truncate(as_path_gstr, as_path_gstr->len - 1);
+ g_string_append_c(as_path_gstr, ')');
+ }
+ else {
+ g_string_truncate(as_path_gstr, as_path_gstr->len - 1);
+ }
+
+ /* length here means number of ASs, ie length * 2 bytes */
+ ti = proto_tree_add_text(as_paths_tree, tvb,
+ q - length * asn_len - 2,
+ length * asn_len + 2, "AS path segment: %s", as_path_gstr->str);
+ as_path_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
+ proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 2,
+ 1, "Path segment type: %s (%u)",
+ val_to_str(type, as_segment_type, "Unknown"), type);
+ proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 1,
+ 1, "Path segment length: %u %s", length,
+ (length == 1) ? "AS" : "ASs");
+
+ /* backup and reprint path segment value(s) only */
+ q -= asn_len * length;
+ ti = proto_tree_add_text(as_path_tree, tvb, q,
+ length * asn_len, "Path segment value:");
+ as_path_segment_tree = proto_item_add_subtree(ti,
+ ett_bgp_as_path_segments);
+ for (j = 0; j < length; j++) {
+ as_path_item = (asn_len == 2) ?
+ tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q);
+ proto_item_append_text(ti, " %u", as_path_item);
+ proto_tree_add_uint_hidden(as_path_tree, hf_bgp_as_path, tvb,
+ q, asn_len, as_path_item);
+ q += asn_len;
+ }
+ }
+
+ break;
+ case BGPTYPE_NEXT_HOP:
+ if (tlen != 4) {
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Next hop (invalid): %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+ } else {
+ proto_tree_add_item(subtree2, hf_bgp_next_hop, tvb,
+ o + i + aoff, tlen, FALSE);
+ }
+ break;
+ case BGPTYPE_MULTI_EXIT_DISC:
+ if (tlen != 4) {
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Multiple exit discriminator (invalid): %u %s",
+ tlen, (tlen == 1) ? "byte" : "bytes");
+ } else {
+ proto_tree_add_item(subtree2, hf_bgp_multi_exit_disc, tvb,
+ o + i + aoff, tlen, FALSE);
+ }
+ break;
+ case BGPTYPE_LOCAL_PREF:
+ if (tlen != 4) {
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Local preference (invalid): %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+ } else {
+ proto_tree_add_item(subtree2, hf_bgp_local_pref, tvb,
+ o + i + aoff, tlen, FALSE);
+ }
+ break;
+ case BGPTYPE_ATOMIC_AGGREGATE:
+ if (tlen != 0) {
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Atomic aggregate (invalid): %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+ }
+ break;
+ case BGPTYPE_AGGREGATOR:
+ if (tlen != 6 && tlen != 8) {
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Aggregator (invalid): %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+ break;
+ }
+ case BGPTYPE_NEW_AGGREGATOR:
+ if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Aggregator (invalid): %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+ else {
+ asn_len = tlen - 4;
+ aggregator_as = (asn_len == 2) ?
+ tvb_get_ntohs(tvb, o + i + aoff) :
+ tvb_get_ntohl(tvb, o + i + aoff);
+ proto_tree_add_uint(subtree2, hf_bgp_aggregator_as, tvb,
+ o + i + aoff, asn_len, aggregator_as);
+ proto_tree_add_item(subtree2, hf_bgp_aggregator_origin, tvb,
+ o + i + aoff + asn_len, 4, FALSE);
+ }
+ break;
+ case BGPTYPE_COMMUNITIES:
+ if (tlen % 4 != 0) {
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Communities (invalid): %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+ break;
+ }
+
+ ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Communities: %s", communities_gstr->str);
+ communities_tree = proto_item_add_subtree(ti,
+ ett_bgp_communities);
+
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + tlen;
+
+ /* snarf each community */
+ while (q < end) {
+ /* check for reserved values */
+ guint32 community = tvb_get_ntohl(tvb, q);
+ if ((community & 0xFFFF0000) == FOURHEX0 ||
+ (community & 0xFFFF0000) == FOURHEXF) {
+ proto_tree_add_text(communities_tree, tvb,
+ q - 3 + aoff, 4,
+ "Community: %s (0x%08x)",
+ val_to_str(community, community_vals, "(reserved)"),
+ community);
+ }
+ else {
+ ti = proto_tree_add_text(communities_tree, tvb,
+ q - 3 + aoff, 4, "Community: %u:%u",
+ tvb_get_ntohs(tvb, q), tvb_get_ntohs(tvb, q + 2));
+ community_tree = proto_item_add_subtree(ti,
+ ett_bgp_communities);
+ proto_tree_add_item(community_tree, hf_bgp_community_as,
+ tvb, q - 3 + aoff, 2, FALSE);
+ proto_tree_add_item(community_tree, hf_bgp_community_value,
+ tvb, q - 1 + aoff, 2, FALSE);
+ }
+
+ q += 4;
+ }
+
+ break;
+ case BGPTYPE_ORIGINATOR_ID:
+ if (tlen != 4) {
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Originator identifier (invalid): %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+ } else {
+ proto_tree_add_item(subtree2, hf_bgp_originator_id, tvb,
+ o + i + aoff, tlen, FALSE);
+ }
+ break;
+ case BGPTYPE_MP_REACH_NLRI:
+ /*
+ * RFC 2545 specifies that there may be more than one
+ * address in the MP_REACH_NLRI attribute in section
+ * 3, "Constructing the Next Hop field".
+ *
+ * Yes, RFC 2858 says you can't do that, and, yes, RFC
+ * 2858 obsoletes RFC 2283, which says you can do that,
+ * but that doesn't mean we shouldn't dissect packets
+ * that conform to RFC 2283 but not RFC 2858, as some
+ * device on the network might implement the 2283-style
+ * BGP extensions rather than RFC 2858-style extensions.
+ */
+ af = tvb_get_ntohs(tvb, o + i + aoff);
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
+ "Address family: %s (%u)",
+ val_to_str(af, afn_vals, "Unknown"), af);
+ saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
+ proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
+ "Subsequent address family identifier: %s (%u)",
+ val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
+ saf);
+ if (af != AFNUM_INET && af != AFNUM_INET6 && af != AFNUM_L2VPN) {
+ /*
+ * The addresses don't contain lengths, so if we
+ * don't understand the address family type, we
+ * cannot parse the subsequent addresses as we
+ * don't know how long they are.
+ *
+ * XXX - we should put a protocol tree item in for
+ * this, as an unknown blob.
+ */
+ break;
+ }
+ nexthop_len = tvb_get_guint8(tvb, o + i + aoff + 3);
+ ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
+ nexthop_len + 1,
+ "Next hop network address (%d %s)",
+ nexthop_len, plurality(nexthop_len, "byte", "bytes"));
+ subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_nhna);
+ j = 0;
+ while (j < nexthop_len) {
+ advance = mp_addr_to_str(af, saf, tvb, o + i + aoff + 4 + j,
+ junk_gbuf) ;
+ if (advance == 0) /* catch if this is a unknown AFI type*/
+ break;
+ if (j + advance > nexthop_len)
+ break;
+ proto_tree_add_text(subtree3, tvb,o + i + aoff + 4 + j,
+ advance, "Next hop: %s (%u)", junk_gbuf->str, advance);
+ j += advance;
+ }
+ tlen -= nexthop_len + 4;
+ aoff += nexthop_len + 4 ;
+
+ off = 0;
+ snpa = tvb_get_guint8(tvb, o + i + aoff);
+ ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, 1,
+ "Subnetwork points of attachment: %u", snpa);
+ off++;
+ if (snpa) {
+ subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_snpa);
+ for (/*nothing*/; snpa > 0; snpa--) {
+ proto_tree_add_text(subtree3, tvb, o + i + aoff + off, 1,
+ "SNPA length: %u", tvb_get_guint8(tvb, o + i + aoff + off));
+ off++;
+ proto_tree_add_text(subtree3, tvb, o + i + aoff + off,
+ tvb_get_guint8(tvb, o + i + aoff + off - 1),
+ "SNPA (%u %s)", tvb_get_guint8(tvb, o + i + aoff + off - 1),
+ (tvb_get_guint8(tvb, o + i + aoff + off - 1) == 1) ? "byte" : "bytes");
+ off += tvb_get_guint8(tvb, o + i + aoff + off - 1);
+ }
+ }
+ tlen -= off;
+ aoff += off;
+
+ ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Network layer reachability information (%u %s)",
+ tlen, (tlen == 1) ? "byte" : "bytes");
+ if (tlen) {
+ subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_reach_nlri);
+
+ while (tlen > 0) {
+ advance = decode_prefix_MP(subtree3,
+ hf_bgp_mp_reach_nlri_ipv4_prefix,
+ -1,
+ af, saf,
+ tvb, o + i + aoff, "MP Reach NLRI");
+ if (advance < 0)
+ break;
+ tlen -= advance;
+ aoff += advance;
+ }
+ }
+ break;
+ case BGPTYPE_MP_UNREACH_NLRI:
+ af = tvb_get_ntohs(tvb, o + i + aoff);
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
+ "Address family: %s (%u)",
+ val_to_str(af, afn_vals, "Unknown"), af);
+ saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
+ proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
+ "Subsequent address family identifier: %s (%u)",
+ val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
+ saf);
+ ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
+ tlen - 3, "Withdrawn routes (%u %s)", tlen - 3,
+ (tlen - 3 == 1) ? "byte" : "bytes");
+
+ tlen -= 3;
+ aoff += 3;
+ if (tlen > 0) {
+ subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_unreach_nlri);
+
+ while (tlen > 0) {
+ advance = decode_prefix_MP(subtree3,
+ hf_bgp_mp_unreach_nlri_ipv4_prefix,
+ -1,
+ af, saf,
+ tvb, o + i + aoff, "MP Unreach NLRI");
+ if (advance < 0)
+ break;
+ tlen -= advance;
+ aoff += advance;
+ }
+ }
+ break;
+ case BGPTYPE_CLUSTER_LIST:
+ if (tlen % 4 != 0) {
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Cluster list (invalid): %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes");
+ break;
+ }
+
+ ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Cluster list: %s", cluster_list_gstr->str);
+ cluster_list_tree = proto_item_add_subtree(ti,
+ ett_bgp_cluster_list);
+
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + tlen;
+
+ /* snarf each cluster identifier */
+ while (q < end) {
+ proto_tree_add_item(cluster_list_tree, hf_bgp_cluster_list,
+ tvb, q - 3 + aoff, 4, FALSE);
+ q += 4;
+ }
+
+ break;
+ case BGPTYPE_EXTENDED_COMMUNITY:
+ if (tlen %8 != 0) {
+ proto_tree_add_text(subtree3, tvb, o + i + aoff, tlen, "Extended community (invalid) : %u %s", tlen,
+ (tlen == 1) ? "byte" : "bytes") ;
+ } else {
+ q = o + i + aoff ;
+ end = o + i + aoff + tlen ;
+ ti = proto_tree_add_text(subtree2,tvb,q,tlen, "Carried Extended communities");
+ subtree3 = proto_item_add_subtree(ti,ett_bgp_extended_communities) ;
+
+ while (q < end) {
+ ext_com = tvb_get_ntohs(tvb,q) ;
+ g_string_sprintfa(junk_gbuf, "%s",
+ val_to_str(ext_com,bgpext_com_type,"Unknown"));
+ switch (ext_com) {
+ case BGP_EXT_COM_RT_0:
+ case BGP_EXT_COM_RT_2:
+ case BGP_EXT_COM_RO_0:
+ case BGP_EXT_COM_RO_2:
+ g_string_sprintfa(junk_gbuf, ": %u%s%d",
+ tvb_get_ntohs(tvb,q+2),":",tvb_get_ntohl(tvb,q+4));
+ proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_gbuf->str);
+ break ;
+ case BGP_EXT_COM_RT_1:
+ case BGP_EXT_COM_RO_1:
+ tvb_memcpy(tvb,ipaddr,q+2,4);
+ g_string_sprintfa(junk_gbuf, ": %s%s%u",
+ ip_to_str(ipaddr),":",tvb_get_ntohs(tvb,q+6));
+ proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_gbuf->str);
+ break;
+ case BGP_EXT_COM_VPN_ORIGIN:
+ case BGP_EXT_COM_OSPF_RID:
+ tvb_memcpy(tvb,ipaddr,q+2,4);
+ g_string_sprintfa(junk_gbuf, ": %s", ip_to_str(ipaddr));
+ proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_gbuf->str);
+ break;
+ case BGP_EXT_COM_OSPF_RTYPE:
+ tvb_memcpy(tvb,ipaddr,q+2,4);
+ g_string_sprintfa(junk_gbuf, ": Area:%s %s", ip_to_str(ipaddr),
+ val_to_str(tvb_get_guint8(tvb,q+6),bgpext_ospf_rtype,"Unknown"));
+ /* print OSPF Metric type if selected */
+ /* always print E2 even if not external route -- receiving router should ignore */
+ if ( (tvb_get_guint8(tvb,q+7)) & BGP_OSPF_RTYPE_METRIC_TYPE ) {
+ g_string_sprintfa(junk_gbuf," E2");
+ } else if (tvb_get_guint8(tvb,q+6)==(BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA ) ) {
+ g_string_sprintfa(junk_gbuf," E1");
+ }
+ proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_gbuf->str);
+ break;
+ case BGP_EXT_COM_LINKBAND:
+ tvb_memcpy(tvb,ipaddr,q+2,4); /* need to check on IEEE format on all platforms */
+ g_string_sprintfa(junk_gbuf, ": %.3f Mbps",
+ ((double)*ipaddr)*8/1000000);
+ proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_gbuf->str);
+ break;
+ case BGP_EXT_COM_L2INFO:
+ g_string_sprintf(junk_gbuf,
+ ": %s, Control Flags: %s%s%s%s%s, MTU: %u %s",
+ val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"),
+ tvb_get_guint8(tvb,q+3) ? "" : "none",
+ tvb_get_ntohs(tvb,q+3)&0x08 ? "Q" : "",
+ tvb_get_ntohs(tvb,q+3)&0x04 ? "F" : "",
+ tvb_get_ntohs(tvb,q+3)&0x02 ? "C" : "",
+ tvb_get_ntohs(tvb,q+3)&0x01 ? "S" : "",
+ tvb_get_ntohs(tvb,q+4),
+ tvb_get_ntohs(tvb,q+4)==1 ? "byte" : "bytes");
+ ti = proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_gbuf->str);
+
+ subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities) ;
+ proto_tree_add_text(subtree4,tvb,q+2,1, "Encapsulation: %s",
+ val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"));
+ proto_tree_add_text(subtree4,tvb,q+3,1, "Control Flags: %s%sControl Word %s required, Sequenced delivery %s required",
+ tvb_get_ntohs(tvb,q+3)&0x08 ? "Q flag (Reserved) set" : "",
+ tvb_get_ntohs(tvb,q+3)&0x04 ? "F flag (reserved) set" : "",
+ tvb_get_ntohs(tvb,q+3)&0x02 ? "is" : "not",
+ tvb_get_ntohs(tvb,q+3)&0x01 ? "is" : "not");
+ proto_tree_add_text(subtree4,tvb,q+4,2, "MTU: %u %s",
+ tvb_get_ntohs(tvb,q+4),
+ tvb_get_ntohs(tvb,q+4)==1 ? "byte" : "bytes");
+ break;
+ default:
+ g_string_sprintf(junk_gbuf, " ");
+ proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_gbuf->str);
+ break ;
+ }
+ q = q + 8 ;
+ }
+ }
+ break;
+ default:
+ proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
+ "Unknown (%d %s)", tlen, (tlen == 1) ? "byte" :
+ "bytes");
+ break;
+ } /* end of second switch */
+
+ i += alen + aoff;
+ }
+
+ o += 2 + len;
+
+ /* NLRI */
+ len = hlen - o;
+
+ /* parse prefixes */
+ if (len > 0) {
+ ti = proto_tree_add_text(tree, tvb, o, len,
+ "Network layer reachability information: %u %s", len,
+ (len == 1) ? "byte" : "bytes");
+ subtree = proto_item_add_subtree(ti, ett_bgp_nlri);
+ end = o + len;
+ while (o < end) {
+ i = decode_prefix4(subtree, hf_bgp_nlri_prefix, tvb, o, 0,
+ "NLRI");
+ if (i < 0)
+ return;
+ o += i;
+ }
+ }
+ }
+}
+
+/*
+ * Dissect a BGP NOTIFICATION message.
+ */
+static void
+dissect_bgp_notification(tvbuff_t *tvb, proto_tree *tree)
+{
+ struct bgp_notification bgpn; /* BGP NOTIFICATION message */
+ int hlen; /* message length */
+ char *p; /* string pointer */
+
+ /* snarf message */
+ tvb_memcpy(tvb, bgpn.bgpn_marker, 0, BGP_MIN_NOTIFICATION_MSG_SIZE);
+ hlen = g_ntohs(bgpn.bgpn_len);
+
+ /* print error code */
+ proto_tree_add_text(tree, tvb,
+ offsetof(struct bgp_notification, bgpn_major), 1,
+ "Error code: %s (%u)",
+ val_to_str(bgpn.bgpn_major, bgpnotify_major, "Unknown"),
+ bgpn.bgpn_major);
+
+ /* print error subcode */
+ if (bgpn.bgpn_major < array_length(bgpnotify_minor)
+ && bgpnotify_minor[bgpn.bgpn_major] != NULL) {
+ p = val_to_str(bgpn.bgpn_minor, bgpnotify_minor[bgpn.bgpn_major],
+ "Unknown");
+ } else if (bgpn.bgpn_minor == 0)
+ p = "Unspecified";
+ else
+ p = "Unknown";
+ proto_tree_add_text(tree, tvb,
+ offsetof(struct bgp_notification, bgpn_minor), 1,
+ "Error subcode: %s (%u)", p, bgpn.bgpn_minor);
+
+ /* only print if there is optional data */
+ if (hlen > BGP_MIN_NOTIFICATION_MSG_SIZE) {
+ proto_tree_add_text(tree, tvb, BGP_MIN_NOTIFICATION_MSG_SIZE,
+ hlen - BGP_MIN_NOTIFICATION_MSG_SIZE, "Data");
+ }
+}
+
+/*
+ * Dissect a BGP ROUTE-REFRESH message.
+ */
+static void
+dissect_bgp_route_refresh(tvbuff_t *tvb, proto_tree *tree)
+{
+ guint16 i; /* tmp */
+ int p; /* tvb offset counter */
+ int pend; /* end of list of entries for one orf type */
+ guint16 hlen; /* tvb RR msg length */
+ proto_item *ti; /* tree item */
+ proto_item *ti1; /* tree item */
+ proto_tree *subtree; /* tree for orf */
+ proto_tree *subtree1; /* tree for orf entry */
+ guint8 orftype; /* ORF Type */
+ guint8 orfwhen; /* ORF flag: immediate, defer */
+ guint16 orflen; /* ORF len */
+ guint8 entryflag; /* ORF Entry flag: action(add,del,delall) match(permit,deny) */
+ guint32 entryseq; /* ORF Entry sequence number */
+ int entrylen; /* ORF Entry length */
+ guint8 pfx_ge; /* ORF PrefixList mask lower bound */
+ guint8 pfx_le; /* ORF PrefixList mask upper bound */
+ int advance; /* tmp */
+
+
+/*
+example 1
+ 00 1c 05 hlen=28
+ 00 01 00 01 afi,safi= ipv4-unicast
+ 02 80 00 01 defer, prefix-orf, len=1
+ 80 removeall
+example 2
+ 00 25 05 hlen=37
+ 00 01 00 01 afi,saif= ipv4-unicast
+ 01 80 00 0a immediate, prefix-orf, len=10
+ 00 add
+ 00 00 00 05 seqno = 5
+ 12 ge = 18
+ 18 le = 24
+ 10 07 02 prefix = 7.2.0.0/16
+*/
+ hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
+ p = BGP_HEADER_SIZE;
+ /* AFI */
+ i = tvb_get_ntohs(tvb, p);
+ proto_tree_add_text(tree, tvb, p, 2,
+ "Address family identifier: %s (%u)",
+ val_to_str(i, afn_vals, "Unknown"), i);
+ p += 2;
+ /* Reserved */
+ proto_tree_add_text(tree, tvb, p, 1,
+ "Reserved: 1 byte");
+ p++;
+ /* SAFI */
+ i = tvb_get_guint8(tvb, p);
+ proto_tree_add_text(tree, tvb, p, 1,
+ "Subsequent address family identifier: %s (%u)",
+ val_to_str(i, bgpattr_nlri_safi,
+ i >= 128 ? "Vendor specific" : "Unknown"),
+ i);
+ p++;
+ if ( hlen == BGP_HEADER_SIZE + 4 )
+ return;
+ while (p < hlen) {
+ /* ORF type */
+ orfwhen = tvb_get_guint8(tvb, p);
+ orftype = tvb_get_guint8(tvb, p+1);
+ orflen = tvb_get_ntohs(tvb, p+2);
+ ti = proto_tree_add_text(tree, tvb, p , orflen + 4 , "ORF information (%u bytes)", orflen + 4);
+ subtree = proto_item_add_subtree(ti, ett_bgp_orf);
+ proto_tree_add_text(subtree, tvb, p , 1, "ORF flag: %s", val_to_str(orfwhen, orf_when_vals,"UNKNOWN"));
+ proto_tree_add_text(subtree, tvb, p+1 , 1, "ORF type: %s", val_to_str(orftype, orf_type_vals,"UNKNOWN"));
+ proto_tree_add_text(subtree, tvb, p+2 , 2, "ORF len: %u %s", orflen, (orflen == 1) ? "byte" : "bytes");
+ p += 4;
+
+ if (orftype != BGP_ORF_PREFIX_CISCO) {
+ proto_tree_add_text(subtree, tvb, p, orflen,
+ "ORFEntry-Unknown (%u bytes)", orflen);
+ p += orflen;
+ continue;
+ }
+ pend = p + orflen;
+ while (p < pend) {
+ entryflag = tvb_get_guint8(tvb, p);
+ if ((entryflag & BGP_ORF_ACTION) == BGP_ORF_REMOVEALL) {
+ ti1 = proto_tree_add_text(subtree, tvb, p, 1,
+ "ORFEntry-PrefixList (1 byte)");
+ subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
+ proto_tree_add_text(subtree1, tvb, p , 1, "RemoveAll");
+ p++;
+ } else {
+ ti1 = proto_tree_add_text(subtree, tvb, p, -1,
+ "ORFEntry-PrefixList");
+ subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
+ proto_tree_add_text(subtree1, tvb, p, 1,
+ "ACTION: %s MATCH: %s",
+ val_to_str(entryflag&BGP_ORF_ACTION,
+ orf_entry_action_vals, "UNKNOWN"),
+ val_to_str(entryflag&BGP_ORF_MATCH,
+ orf_entry_match_vals, "UNKNOWN"));
+ p++;
+ entryseq = tvb_get_ntohl(tvb, p);
+ proto_tree_add_text(subtree1, tvb, p, 4,
+ "Entry Sequence No: %u", entryseq);
+ p += 4;
+ pfx_ge = tvb_get_guint8(tvb, p);
+ proto_tree_add_text(subtree1, tvb, p, 1,
+ "PrefixMask length lower bound: %u", pfx_ge);
+ p++;
+ pfx_le = tvb_get_guint8(tvb, p);
+ proto_tree_add_text(subtree1, tvb, p, 1,
+ "PrefixMask length upper bound: %u", pfx_le);
+ p++;
+
+ advance = decode_prefix4(subtree1, -1, tvb, p, 0, "ORF");
+ if (advance < 0)
+ break;
+ entrylen = 7 + 1 + advance;
+
+ proto_item_append_text(ti1, " (%u bytes)", entrylen);
+ proto_item_set_len(ti1, entrylen);
+ p += advance;
+ }
+ }
+ }
+}
+
+/*
+ * Dissect a BGP CAPABILITY message.
+ */
+static void
+dissect_bgp_capability(tvbuff_t *tvb, proto_tree *tree)
+{
+ int offset = 0;
+ proto_item *ti;
+ proto_tree *subtree;
+ guint8 action;
+ int ctype;
+ int clen;
+ int mend;
+
+ mend = offset + tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
+ offset += BGP_HEADER_SIZE;
+ /* step through all of the capabilities */
+ while (offset < mend) {
+ action = tvb_get_guint8(tvb, offset++);
+ ctype = tvb_get_guint8(tvb, offset++);
+ clen = tvb_get_guint8(tvb, offset++);
+
+ ti = proto_tree_add_text(tree, tvb, offset - 2, 2 + clen,
+ "%s (%u %s)", val_to_str(ctype, capability_vals,
+ "Unknown capability"), 2 + clen, (clen == 1) ? "byte" : "bytes");
+ subtree = proto_item_add_subtree(ti, ett_bgp_option);
+ proto_tree_add_text(subtree, tvb, offset-2, 1, "Action: %d (%s)",
+ action, val_to_str(action, bgpcap_action, "Invalid action value"));
+ dissect_bgp_capability_item(tvb, &offset, subtree, ctype, clen);
+ }
+}
+
+static void
+dissect_bgp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean first)
+{
+ guint16 bgp_len; /* Message length */
+ guint8 bgp_type; /* Message type */
+ char *typ; /* Message type (string) */
+ proto_item *ti; /* tree item */
+ proto_tree *bgp_tree; /* BGP packet tree */
+ proto_tree *bgp1_tree; /* BGP message tree */
+
+ bgp_len = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
+ bgp_type = tvb_get_guint8(tvb, BGP_MARKER_SIZE + 2);
+ typ = val_to_str(bgp_type, bgptypevals, "Unknown message type (0x%02x)");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (first)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", typ);
+ else
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", typ);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, FALSE);
+ bgp_tree = proto_item_add_subtree(ti, ett_bgp);
+
+ ti = proto_tree_add_text(bgp_tree, tvb, 0, -1, "%s", typ);
+
+ /* add a different tree for each message type */
+ switch (bgp_type) {
+ case BGP_OPEN:
+ bgp1_tree = proto_item_add_subtree(ti, ett_bgp_open);
+ break;
+ case BGP_UPDATE:
+ bgp1_tree = proto_item_add_subtree(ti, ett_bgp_update);
+ break;
+ case BGP_NOTIFICATION:
+ bgp1_tree = proto_item_add_subtree(ti, ett_bgp_notification);
+ break;
+ case BGP_KEEPALIVE:
+ bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
+ break;
+ case BGP_ROUTE_REFRESH_CISCO:
+ case BGP_ROUTE_REFRESH:
+ bgp1_tree = proto_item_add_subtree(ti, ett_bgp_route_refresh);
+ break;
+ case BGP_CAPABILITY:
+ bgp1_tree = proto_item_add_subtree(ti, ett_bgp_capability);
+ break;
+ default:
+ bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
+ break;
+ }
+
+ proto_tree_add_text(bgp1_tree, tvb, 0, BGP_MARKER_SIZE,
+ "Marker: 16 bytes");
+
+ if (bgp_len < BGP_HEADER_SIZE || bgp_len > BGP_MAX_PACKET_SIZE) {
+ proto_tree_add_text(bgp1_tree, tvb, BGP_MARKER_SIZE, 2,
+ "Length (invalid): %u %s", bgp_len,
+ (bgp_len == 1) ? "byte" : "bytes");
+ return;
+ } else {
+ proto_tree_add_text(bgp1_tree, tvb, BGP_MARKER_SIZE, 2,
+ "Length: %u %s", bgp_len,
+ (bgp_len == 1) ? "byte" : "bytes");
+ }
+
+ proto_tree_add_uint(bgp1_tree, hf_bgp_type, tvb,
+ BGP_MARKER_SIZE + 2, 1,
+ bgp_type);
+
+ switch (bgp_type) {
+ case BGP_OPEN:
+ dissect_bgp_open(tvb, bgp1_tree);
+ break;
+ case BGP_UPDATE:
+ dissect_bgp_update(tvb, bgp1_tree);
+ break;
+ case BGP_NOTIFICATION:
+ dissect_bgp_notification(tvb, bgp1_tree);
+ break;
+ case BGP_KEEPALIVE:
+ /* no data in KEEPALIVE messages */
+ break;
+ case BGP_ROUTE_REFRESH_CISCO:
+ case BGP_ROUTE_REFRESH:
+ dissect_bgp_route_refresh(tvb, bgp1_tree);
+ break;
+ case BGP_CAPABILITY:
+ dissect_bgp_capability(tvb, bgp1_tree);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * Dissect a BGP packet.
+ */
+static void
+dissect_bgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ volatile int offset = 0; /* offset into the tvbuff */
+ gint reported_length_remaining;
+ guint8 bgp_marker[BGP_MARKER_SIZE]; /* Marker (should be all ones */
+ static guchar marker[] = { /* BGP message marker */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ proto_item *ti; /* tree item */
+ proto_tree *bgp_tree; /* BGP packet tree */
+ guint16 bgp_len; /* Message length */
+ int offset_before;
+ guint length_remaining;
+ guint length;
+ volatile gboolean first = TRUE; /* TRUE for the first BGP message in packet */
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BGP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /*
+ * Scan through the TCP payload looking for a BGP marker.
+ */
+ while ((reported_length_remaining = tvb_reported_length_remaining(tvb, offset))
+ != 0) {
+ /*
+ * "reported_length_remaining" is the number of bytes of TCP payload
+ * remaining. If it's more than the length of a BGP marker,
+ * we check only the number of bytes in a BGP marker.
+ */
+ if (reported_length_remaining > BGP_MARKER_SIZE)
+ reported_length_remaining = BGP_MARKER_SIZE;
+
+ /*
+ * OK, is there a BGP marker starting at the specified offset -
+ * or, at least, the beginning of a BGP marker running to the end
+ * of the TCP payload?
+ *
+ * This will throw an exception if the frame is short; that's what
+ * we want.
+ */
+ tvb_memcpy(tvb, bgp_marker, offset, reported_length_remaining);
+ if (memcmp(bgp_marker, marker, reported_length_remaining) == 0) {
+ /*
+ * Yes - stop scanning and start processing BGP packets.
+ */
+ break;
+ }
+
+ /*
+ * No - keep scanning through the tvbuff to try to find a marker.
+ */
+ offset++;
+ }
+
+ /*
+ * If we skipped any bytes, mark it as a BGP continuation.
+ */
+ if (offset > 0) {
+ ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, FALSE);
+ bgp_tree = proto_item_add_subtree(ti, ett_bgp);
+
+ proto_tree_add_text(bgp_tree, tvb, 0, offset, "Continuation");
+ }
+
+ /*
+ * Now process the BGP packets in the TCP payload.
+ *
+ * XXX - perhaps "tcp_dissect_pdus()" should take a starting
+ * offset, in which case we can replace the loop below with
+ * a call to "tcp_dissect_pdus()".
+ */
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * This will throw an exception if we don't have any data left.
+ * That's what we want. (See "tcp_dissect_pdus()", which is
+ * similar.)
+ */
+ length_remaining = tvb_ensure_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (bgp_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - would a BGP header starting at this offset be split
+ * across segment boundaries?
+ */
+ if (length_remaining < BGP_HEADER_SIZE) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = BGP_HEADER_SIZE - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Get the length and type from the BGP header.
+ */
+ bgp_len = tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
+ if (bgp_len < BGP_HEADER_SIZE) {
+ /*
+ * The BGP length doesn't include the BGP header; report that
+ * as an error.
+ */
+ show_reported_bounds_error(tvb, pinfo, tree);
+ return;
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (bgp_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the PDU split across segment boundaries?
+ */
+ if (length_remaining < bgp_len) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = bgp_len - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload we have
+ * available. Make its reported length the amount of data in the PDU.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector will throw a
+ * BoundsError exception, rather than a ReportedBoundsError exception.
+ * We really want a tvbuff where the length is "length", the reported
+ * length is "plen", and the "if the snapshot length were infinite"
+ * length is the minimum of the reported length of the tvbuff handed
+ * to us and "plen", with a new type of exception thrown if the offset
+ * is within the reported length but beyond that third length, with
+ * that exception getting the "Unreassembled Packet" error.
+ */
+ length = length_remaining;
+ if (length > bgp_len)
+ length = bgp_len;
+ next_tvb = tvb_new_subset(tvb, offset, length, bgp_len);
+
+ /*
+ * Dissect the PDU.
+ *
+ * Catch the ReportedBoundsError exception; if this particular message
+ * happens to get a ReportedBoundsError exception, that doesn't mean
+ * that we should stop dissecting PDUs within this frame or chunk of
+ * reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing more to
+ * see, so we just re-throw it.
+ */
+ TRY {
+ dissect_bgp_pdu(next_tvb, pinfo, tree, first);
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ }
+ ENDTRY;
+
+ first = FALSE;
+
+ /*
+ * Step to the next PDU.
+ * Make sure we don't overflow.
+ */
+ offset_before = offset;
+ offset += bgp_len;
+ if (offset <= offset_before)
+ break;
+ }
+}
+
+/*
+ * Register ourselves.
+ */
+void
+proto_register_bgp(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_bgp_type,
+ { "Type", "bgp.type", FT_UINT8, BASE_DEC,
+ VALS(bgptypevals), 0x0, "BGP message type", HFILL }},
+ { &hf_bgp_aggregator_as,
+ { "Aggregator AS", "bgp.aggregator_as", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_aggregator_origin,
+ { "Aggregator origin", "bgp.aggregator_origin", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_as_path,
+ { "AS Path", "bgp.as_path", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_cluster_identifier,
+ { "Cluster identifier", "bgp.cluster_identifier", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_community_as,
+ { "Community AS", "bgp.community_as", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_community_value,
+ { "Community value", "bgp.community_value", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_local_pref,
+ { "Local preference", "bgp.local_pref", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_mp_reach_nlri_ipv4_prefix,
+ { "MP Reach NLRI IPv4 prefix", "bgp.mp_reach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_mp_unreach_nlri_ipv4_prefix,
+ { "MP Unreach NLRI IPv4 prefix", "bgp.mp_unreach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_multi_exit_disc,
+ { "Multiple exit discriminator", "bgp.multi_exit_disc", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_next_hop,
+ { "Next hop", "bgp.next_hop", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_nlri_prefix,
+ { "NLRI prefix", "bgp.nlri_prefix", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_origin,
+ { "Origin", "bgp.origin", FT_UINT8, BASE_DEC,
+ VALS(bgpattr_origin), 0x0, "", HFILL}},
+ { &hf_bgp_originator_id,
+ { "Originator identifier", "bgp.originator_id", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_withdrawn_prefix,
+ { "Withdrawn prefix", "bgp.withdrawn_prefix", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ { &hf_bgp_cluster_list,
+ { "Cluster List", "bgp.cluster_list", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_bgp,
+ &ett_bgp_prefix,
+ &ett_bgp_unfeas,
+ &ett_bgp_attrs,
+ &ett_bgp_attr,
+ &ett_bgp_attr_flags,
+ &ett_bgp_mp_nhna,
+ &ett_bgp_mp_reach_nlri,
+ &ett_bgp_mp_unreach_nlri,
+ &ett_bgp_mp_snpa,
+ &ett_bgp_nlri,
+ &ett_bgp_open,
+ &ett_bgp_update,
+ &ett_bgp_notification,
+ &ett_bgp_route_refresh,
+ &ett_bgp_capability,
+ &ett_bgp_as_paths,
+ &ett_bgp_as_path_segments,
+ &ett_bgp_communities,
+ &ett_bgp_cluster_list,
+ &ett_bgp_options,
+ &ett_bgp_option,
+ &ett_bgp_extended_communities,
+ &ett_bgp_orf,
+ &ett_bgp_orf_entry
+ };
+ module_t *bgp_module;
+ static enum_val_t asn_len[] = {
+ {"auto-detect", "Auto-detect", 0},
+ {"2", "2 octet", 2},
+ {"4", "4 octet", 4},
+ {NULL, NULL, -1}
+ };
+
+ proto_bgp = proto_register_protocol("Border Gateway Protocol",
+ "BGP", "bgp");
+ proto_register_field_array(proto_bgp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ bgp_module = prefs_register_protocol(proto_bgp, NULL);
+ prefs_register_bool_preference(bgp_module, "desegment",
+ "Desegment all BGP messages spanning multiple TCP segments",
+ "Whether the BGP dissector should desegment all messages spanning multiple TCP segments",
+ &bgp_desegment);
+ prefs_register_enum_preference(bgp_module, "asn_len",
+ "Length of the AS number",
+ "BGP dissector detect the length of the AS number in AS_PATH attributes automatically or manually (NOTE: Automatic detection is not 100% accurate)",
+ &bgp_asn_len, asn_len, FALSE);
+}
+
+void
+proto_reg_handoff_bgp(void)
+{
+ dissector_handle_t bgp_handle;
+
+ bgp_handle = create_dissector_handle(dissect_bgp, proto_bgp);
+ dissector_add("tcp.port", BGP_TCP_PORT, bgp_handle);
+}
diff --git a/epan/dissectors/packet-bgp.h b/epan/dissectors/packet-bgp.h
new file mode 100644
index 0000000000..e92f278a21
--- /dev/null
+++ b/epan/dissectors/packet-bgp.h
@@ -0,0 +1,200 @@
+/* packet-bgp.c
+ * Definitions for BGP packet disassembly structures and routine
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_BGP_H__
+#define __PACKET_BGP_H__
+
+/* some handy things to know */
+#define BGP_MAX_PACKET_SIZE 4096
+#define BGP_MARKER_SIZE 16 /* size of BGP marker */
+#define BGP_HEADER_SIZE 19 /* size of BGP header, including marker */
+#define BGP_MIN_OPEN_MSG_SIZE 29
+#define BGP_MIN_UPDATE_MSG_SIZE 23
+#define BGP_MIN_NOTIFICATION_MSG_SIZE 21
+#define BGP_MIN_KEEPALVE_MSG_SIZE BGP_HEADER_SIZE
+#define BGP_TCP_PORT 179
+
+/* BGP message types */
+#define BGP_OPEN 1
+#define BGP_UPDATE 2
+#define BGP_NOTIFICATION 3
+#define BGP_KEEPALIVE 4
+#define BGP_ROUTE_REFRESH 5
+#define BGP_CAPABILITY 6
+#define BGP_ROUTE_REFRESH_CISCO 0x80
+
+/* BGP OPEN message */
+struct bgp_open {
+ guint8 bgpo_marker[BGP_MARKER_SIZE];
+ guint16 bgpo_len;
+ guint8 bgpo_type;
+ guint8 bgpo_version;
+ guint16 bgpo_myas;
+ guint16 bgpo_holdtime;
+ guint32 bgpo_id;
+ guint8 bgpo_optlen;
+ /* options should follow */
+};
+
+/* BGP NOTIFICATION message */
+struct bgp_notification {
+ guint8 bgpn_marker[BGP_MARKER_SIZE];
+ guint16 bgpn_len;
+ guint8 bgpn_type;
+ guint8 bgpn_major;
+ guint8 bgpn_minor;
+ /* data should follow */
+};
+
+/* BGP ROUTE-REFRESH message */
+struct bgp_route_refresh {
+ guint8 bgpr_marker[BGP_MARKER_SIZE];
+ guint16 bgpr_len;
+ guint8 bgpr_type;
+ guint16 bgpr_afi;
+ guint8 bgpr_reserved;
+ guint8 bgpr_safi;
+};
+
+/* path attribute */
+struct bgp_attr {
+ guint8 bgpa_flags;
+ guint8 bgpa_type;
+};
+
+/* attribute flags, from RFC1771 */
+#define BGP_ATTR_FLAG_OPTIONAL 0x80
+#define BGP_ATTR_FLAG_TRANSITIVE 0x40
+#define BGP_ATTR_FLAG_PARTIAL 0x20
+#define BGP_ATTR_FLAG_EXTENDED_LENGTH 0x10
+
+/* AS_PATH segment types */
+#define AS_SET 1 /* RFC1771 */
+#define AS_SEQUENCE 2 /* RFC1771 */
+#define AS_CONFED_SET 4 /* RFC1965 has the wrong values, corrected in */
+#define AS_CONFED_SEQUENCE 3 /* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
+
+/* OPEN message Optional Parameter types */
+#define BGP_OPTION_AUTHENTICATION 1 /* RFC1771 */
+#define BGP_OPTION_CAPABILITY 2 /* RFC2842 */
+
+/* BGP capability code */
+#define BGP_CAPABILITY_RESERVED 0 /* RFC2434 */
+#define BGP_CAPABILITY_MULTIPROTOCOL 1 /* RFC2858 */
+#define BGP_CAPABILITY_ROUTE_REFRESH 2 /* RFC2918 */
+#define BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING 3 /* draft-ietf-idr-route-filter-04.txt */
+#define BGP_CAPABILITY_GRACEFUL_RESTART 0x40 /* draft-ietf-idr-restart-05 */
+#define BGP_CAPABILITY_4_OCTET_AS_NUMBER 0x41 /* draft-ietf-idr-as4bytes-06 */
+#define BGP_CAPABILITY_DYNAMIC_CAPABILITY 0x42 /* draft-ietf-idr-dynamic-cap-03 */
+#define BGP_CAPABILITY_ORF_CISCO 0x82 /* Cisco */
+#define BGP_CAPABILITY_ROUTE_REFRESH_CISCO 0x80 /* Cisco */
+
+#define BGP_ORF_PREFIX_CISCO 0x80 /* Cisco */
+#define BGP_ORF_COMM_CISCO 0x81 /* Cisco */
+#define BGP_ORF_EXTCOMM_CISCO 0x82 /* Cisco */
+#define BGP_ORF_ASPATH_CISCO 0x83 /* Cisco */
+#define BGP_ORF_COMM 0x02 /* draft-ietf-idr-route-filter-06.txt */
+#define BGP_ORF_EXTCOMM 0x03 /* draft-ietf-idr-route-filter-06.txt */
+#define BGP_ORF_ASPATH 0x04 /* draft-ietf-idr-aspath-orf-02.txt */
+/* draft-ietf-idr-route-filter-06.txt */
+#define BGP_ORF_ACTION 0xc0
+#define BGP_ORF_ADD 0x00
+#define BGP_ORF_REMOVE 0x40
+#define BGP_ORF_REMOVEALL 0x80
+#define BGP_ORF_MATCH 0x10
+#define BGP_ORF_PERMIT 0x00
+#define BGP_ORF_DENY 0x10
+
+/* well-known communities, from RFC1997 */
+#define BGP_COMM_NO_EXPORT 0xFFFFFF01
+#define BGP_COMM_NO_ADVERTISE 0xFFFFFF02
+#define BGP_COMM_NO_EXPORT_SUBCONFED 0xFFFFFF03
+#define FOURHEX0 0x00000000
+#define FOURHEXF 0xFFFF0000
+
+/* attribute types */
+#define BGPTYPE_ORIGIN 1 /* RFC1771 */
+#define BGPTYPE_AS_PATH 2 /* RFC1771 */
+#define BGPTYPE_NEXT_HOP 3 /* RFC1771 */
+#define BGPTYPE_MULTI_EXIT_DISC 4 /* RFC1771 */
+#define BGPTYPE_LOCAL_PREF 5 /* RFC1771 */
+#define BGPTYPE_ATOMIC_AGGREGATE 6 /* RFC1771 */
+#define BGPTYPE_AGGREGATOR 7 /* RFC1771 */
+#define BGPTYPE_COMMUNITIES 8 /* RFC1997 */
+#define BGPTYPE_ORIGINATOR_ID 9 /* RFC2796 */
+#define BGPTYPE_CLUSTER_LIST 10 /* RFC2796 */
+#define BGPTYPE_DPA 11 /* work in progress */
+#define BGPTYPE_ADVERTISER 12 /* RFC1863 */
+#define BGPTYPE_RCID_PATH 13 /* RFC1863 */
+#define BGPTYPE_MP_REACH_NLRI 14 /* RFC2858 */
+#define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2858 */
+#define BGPTYPE_EXTENDED_COMMUNITY 16 /* Draft Ramachandra */
+#define BGPTYPE_NEW_AS_PATH 17 /* draft-ietf-idr-as4bytes */
+#define BGPTYPE_NEW_AGGREGATOR 18 /* draft-ietf-idr-as4bytes */
+
+/* Extended community type */
+ /* draft-ramachandra-bgp-ext-communities */
+#define BGP_EXT_COM_RT_0 0x0002 /* Route Target,Format AS(2bytes):AN(4bytes) */
+#define BGP_EXT_COM_RT_1 0x0102 /* Route Target,Format IP address:AN(2bytes) */
+#define BGP_EXT_COM_RT_2 0x0202 /* Route Target,Format AS(2bytes):AN(4bytes) */
+#define BGP_EXT_COM_RO_0 0x0003 /* Route Origin,Format AS(2bytes):AN(4bytes) */
+#define BGP_EXT_COM_RO_1 0x0103 /* Route Origin,Format IP address:AN(2bytes) */
+#define BGP_EXT_COM_RO_2 0x0203 /* Route Origin,Format AS(2bytes):AN(4bytes) */
+#define BGP_EXT_COM_LINKBAND 0x0004 /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */
+ /* rfc2547 bgp-mpls-vpns */
+#define BGP_EXT_COM_VPN_ORIGIN 0x0005 /* OSPF Domin ID / VPN of Origin */
+ /* draft-rosen-vpns-ospf-bgp-mpls */
+#define BGP_EXT_COM_OSPF_RTYPE 0X8000 /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */
+#define BGP_EXT_COM_OSPF_RID 0x8001 /* OSPF Router ID,Format RouterID(4B):Unused(2B) */
+#define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */
+
+
+/* OSPF codes for BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls */
+#define BGP_OSPF_RTYPE_RTR 1 /* OSPF Router LSA */
+#define BGP_OSPF_RTYPE_NET 2 /* OSPF Network LSA */
+#define BGP_OSPF_RTYPE_SUM 3 /* OSPF Summary LSA */
+#define BGP_OSPF_RTYPE_EXT 5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */
+#define BGP_OSPF_RTYPE_NSSA 7 /* OSPF NSSA External*/
+#define BGP_OSPF_RTYPE_SHAM 129 /* OSPF-MPLS-VPN Sham link */
+#define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */
+
+/* Extended community & Route dinstinguisher formats */
+#define FORMAT_AS2_LOC 0x00 /* Format AS(2bytes):AN(4bytes) */
+#define FORMAT_IP_LOC 0x01 /* Format IP address:AN(2bytes) */
+#define FORMAT_AS4_LOC 0x02 /* Format AS(4bytes):AN(2bytes) */
+
+/* RFC 2858 subsequent address family numbers */
+#define SAFNUM_UNICAST 1
+#define SAFNUM_MULCAST 2
+#define SAFNUM_UNIMULC 3
+#define SAFNUM_MPLS_LABEL 4 /* rfc3107 */
+#define SAFNUM_LAB_VPNUNICAST 128 /* Draft-rosen-rfc2547bis-03 */
+#define SAFNUM_LAB_VPNMULCAST 129
+#define SAFNUM_LAB_VPNUNIMULC 130
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+#endif
diff --git a/epan/dissectors/packet-bofl.c b/epan/dissectors/packet-bofl.c
new file mode 100644
index 0000000000..3a9e9dd2f7
--- /dev/null
+++ b/epan/dissectors/packet-bofl.c
@@ -0,0 +1,140 @@
+/* packet-bofl.c
+ * Routines for Wellfleet BOFL dissection
+ * Author: Endoh Akira (endoh@netmarks.co.jp)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@unicom.net>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The following information was copied from
+ * http://www.protocols.com/pbook/bridge.htm#WellfleetBOFL
+ *
+ * The Wellfleet Breath of Life (BOFL) protocol is used as a line sensing
+ * protocol on:
+ *
+ * - Ethernet LANs to detect transmitter jams.
+ * - Synchronous lines running WFLT STD protocols to determine if the line
+ * is up.
+ * - Dial backup PPP lines.
+ *
+ * The frame format of Wellfleet BOFL is shown following the Ethernet header
+ * in the following illustration:
+ *
+ * Destination Source 8102 PDU Sequence Padding
+ * 6 6 2 4 4 n bytes
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#define ETHER_TYPE_BOFL 0x8102
+#define BOFL_MIN_LEN 8
+
+/* Initialize the protocol and registered fields */
+static int proto_bofl = -1;
+static int hf_bofl_pdu = -1;
+static int hf_bofl_sequence = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_bofl = -1;
+
+/* Code to actually dissect the packets */
+static void
+dissect_bofl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *bofl_tree = NULL;
+ gint len;
+ guint32 pdu, sequence;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BOFL");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_bofl, tvb, 0, -1, FALSE);
+ bofl_tree = proto_item_add_subtree(ti, ett_bofl);
+ }
+
+ pdu = tvb_get_ntohl(tvb, 0);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "PDU: 0x%08x", pdu);
+ }
+ if (tree)
+ proto_tree_add_uint(bofl_tree, hf_bofl_pdu, tvb, 0, 4, pdu);
+
+ sequence = tvb_get_ntohl(tvb, 4);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " Sequence: %u", sequence);
+ }
+ if (tree) {
+ proto_tree_add_uint(bofl_tree, hf_bofl_sequence, tvb, 4, 4, sequence);
+
+ len = tvb_length_remaining(tvb, 8);
+ if (len > 0)
+ proto_tree_add_text(bofl_tree, tvb, 8, len,
+ "Padding (%d byte)", len);
+ }
+}
+
+
+void
+proto_register_bofl(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bofl_pdu,
+ { "PDU", "bofl.pdu",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "PDU; normally equals 0x01010000 or 0x01011111", HFILL }
+ },
+ { &hf_bofl_sequence,
+ { "Sequence", "bofl.sequence",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "incremental counter", HFILL }
+ }
+ };
+
+ static gint *ett[] = {
+ &ett_bofl,
+ };
+
+ proto_bofl = proto_register_protocol("Wellfleet Breath of Life",
+ "BOFL", "bofl");
+ proto_register_field_array(proto_bofl, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_bofl(void)
+{
+ dissector_handle_t bofl_handle;
+
+ bofl_handle = create_dissector_handle(dissect_bofl, proto_bofl);
+ dissector_add("ethertype", ETHER_TYPE_BOFL, bofl_handle);
+}
diff --git a/epan/dissectors/packet-bootp.c b/epan/dissectors/packet-bootp.c
new file mode 100644
index 0000000000..02ce06d3e7
--- /dev/null
+++ b/epan/dissectors/packet-bootp.c
@@ -0,0 +1,1823 @@
+/* packet-bootp.c
+ * Routines for BOOTP/DHCP packet disassembly
+ * Copyright 1998, Gilbert Ramirez <gram@alumni.rice.edu>
+ * Copyright 2004, Thomas Anders <thomas.anders [AT] blue-cable.de>
+ *
+ * $Id$
+ *
+ * The information used comes from:
+ * RFC 951: Bootstrap Protocol
+ * RFC 1497: BOOTP extensions
+ * RFC 1542: Clarifications and Extensions for the Bootstrap Protocol
+ * RFC 2131: Dynamic Host Configuration Protocol
+ * RFC 2132: DHCP Options and BOOTP Vendor Extensions
+ * RFC 2489: Procedure for Defining New DHCP Options
+ * RFC 2610: DHCP Options for Service Location Protocol
+ * RFC 3046: DHCP Relay Agent Information Option
+ * RFC 3118: Authentication for DHCP Messages
+ * RFC 3203: DHCP reconfigure extension
+ * RFC 3495: DHCP Option (122) for CableLabs Client Configuration
+ * RFC 3594: PacketCable Security Ticket Control Sub-Option (122.9)
+ * BOOTP and DHCP Parameters
+ * http://www.iana.org/assignments/bootp-dhcp-parameters
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/int-64bit.h>
+#include <epan/packet.h>
+#include "packet-arp.h"
+#include "packet-dns.h" /* for get_dns_name() */
+
+#include "prefs.h"
+#include "tap.h"
+
+static int bootp_dhcp_tap = -1;
+static int proto_bootp = -1;
+static int hf_bootp_type = -1;
+static int hf_bootp_hw_type = -1;
+static int hf_bootp_hw_len = -1;
+static int hf_bootp_hops = -1;
+static int hf_bootp_id = -1;
+static int hf_bootp_secs = -1;
+static int hf_bootp_flags = -1;
+static int hf_bootp_flags_broadcast = -1;
+static int hf_bootp_flags_reserved = -1;
+static int hf_bootp_ip_client = -1;
+static int hf_bootp_ip_your = -1;
+static int hf_bootp_ip_server = -1;
+static int hf_bootp_ip_relay = -1;
+static int hf_bootp_hw_addr = -1;
+static int hf_bootp_server = -1;
+static int hf_bootp_file = -1;
+static int hf_bootp_cookie = -1;
+static int hf_bootp_vendor = -1;
+static int hf_bootp_dhcp = -1;
+
+static guint ett_bootp = -1;
+static guint ett_bootp_flags = -1;
+static guint ett_bootp_option = -1;
+
+gboolean novell_string = FALSE;
+
+#define UDP_PORT_BOOTPS 67
+#define UDP_PORT_BOOTPC 68
+
+#define BOOTP_BC 0x8000
+#define BOOTP_MBZ 0x7FFF
+
+#define PLURALIZE(n) (((n) > 1) ? "s" : "")
+
+enum field_type { none, ipv4, string, toggle, yes_no, special, opaque,
+ time_in_secs,
+ val_u_byte, val_u_short, val_u_le_short, val_u_long,
+ val_s_long, fqdn, ipv4_or_fqdn, bytes };
+
+struct opt_info {
+ char *text;
+ enum field_type ftype;
+};
+
+static const true_false_string flag_set_broadcast = {
+ "Broadcast",
+ "Unicast"
+};
+
+
+static int dissect_vendor_pxeclient_suboption(proto_tree *v_tree, tvbuff_t *tvb,
+ int optp);
+static int dissect_vendor_cablelabs_suboption(proto_tree *v_tree, tvbuff_t *tvb,
+ int optp);
+static int dissect_cablelabs_clientconfig_suboption(proto_tree *v_tree, tvbuff_t *tvb,
+ int optp);
+static int dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb,
+ int optp);
+static int bootp_dhcp_decode_agent_info(proto_tree *v_tree, tvbuff_t *tvb,
+ int optp);
+
+static const char *
+get_dhcp_type(guint8 byte)
+{
+ static const char *opt53_text[] = {
+ "Unknown Message Type",
+ "Discover",
+ "Offer",
+ "Request",
+ "Decline",
+ "ACK",
+ "NAK",
+ "Release",
+ "Inform",
+ "Force Renew"
+ };
+ int i;
+
+ if (byte > 0 && byte < (sizeof opt53_text / sizeof opt53_text[0]))
+ i = byte;
+ else
+ i = 0;
+ return opt53_text[i];
+}
+
+/* DHCP Authentication protocols */
+#define AUTHEN_PROTO_CONFIG_TOKEN 0
+#define AUTHEN_PROTO_DELAYED_AUTHEN 1
+
+/* DHCP Authentication algorithms for delayed authentication */
+#define AUTHEN_DELAYED_ALGO_HMAC_MD5 1
+
+/* DHCP Authentication Replay Detection Methods */
+#define AUTHEN_RDM_MONOTONIC_COUNTER 0x00
+
+/* DHCP Option Overload (option code 52) */
+#define OPT_OVERLOAD_FILE 1
+#define OPT_OVERLOAD_SNAME 2
+#define OPT_OVERLOAD_BOTH 3
+
+/* Server name and boot file offsets and lengths */
+#define SERVER_NAME_OFFSET 44
+#define SERVER_NAME_LEN 64
+#define FILE_NAME_OFFSET 108
+#define FILE_NAME_LEN 128
+#define VENDOR_INFO_OFFSET 236
+
+/* Returns the number of bytes consumed by this option. */
+static int
+bootp_option(tvbuff_t *tvb, proto_tree *bp_tree, int voff, int eoff,
+ gboolean first_pass, gboolean *at_end, const char **dhcp_type_p,
+ const guint8 **vendor_class_id_p)
+{
+ char *text;
+ enum field_type ftype;
+ guchar code = tvb_get_guint8(tvb, voff);
+ int vlen;
+ guchar byte;
+ int i,optp, consumed;
+ gulong time_secs;
+ proto_tree *v_tree, *o52tree;
+ proto_item *vti;
+ guint8 protocol;
+ guint8 algorithm;
+ guint8 rdm;
+ int o52voff, o52eoff;
+ gboolean o52at_end;
+
+ static const value_string nbnt_vals[] = {
+ {0x1, "B-node" },
+ {0x2, "P-node" },
+ {0x4, "M-node" },
+ {0x8, "H-node" },
+ {0, NULL } };
+
+ static const value_string slpda_vals[] = {
+ {0x00, "Dynamic Discovery" },
+ {0x01, "Static Discovery" },
+ {0x80, "Backwards compatibility" },
+ {0, NULL } };
+
+ static const value_string slp_scope_vals[] = {
+ {0x00, "Preferred Scope" },
+ {0x01, "Mandatory Scope" },
+ {0, NULL } };
+
+ static const value_string authen_protocol_vals[] = {
+ {AUTHEN_PROTO_CONFIG_TOKEN, "configuration token" },
+ {AUTHEN_PROTO_DELAYED_AUTHEN, "delayed authentication" },
+ {0, NULL } };
+
+ static const value_string authen_da_algo_vals[] = {
+ {AUTHEN_DELAYED_ALGO_HMAC_MD5, "HMAC_MD5" },
+ {0, NULL } };
+
+ static const value_string authen_rdm_vals[] = {
+ {AUTHEN_RDM_MONOTONIC_COUNTER, "Monotonically-increasing counter" },
+ {0, NULL } };
+
+ static const value_string opt_overload_vals[] = {
+ { OPT_OVERLOAD_FILE, "Boot file name holds options", },
+ { OPT_OVERLOAD_SNAME, "Server host name holds options", },
+ { OPT_OVERLOAD_BOTH, "Boot file and server host names hold options" },
+ { 0, NULL } };
+
+ static struct opt_info opt[] = {
+ /* 0 */ { "Padding", none },
+ /* 1 */ { "Subnet Mask", ipv4 },
+ /* 2 */ { "Time Offset", time_in_secs },
+ /* 3 */ { "Router", ipv4 },
+ /* 4 */ { "Time Server", ipv4 },
+ /* 5 */ { "Name Server", ipv4 },
+ /* 6 */ { "Domain Name Server", ipv4 },
+ /* 7 */ { "Log Server", ipv4 },
+ /* 8 */ { "Cookie Server", ipv4 },
+ /* 9 */ { "LPR Server", ipv4 },
+ /* 10 */ { "Impress Server", ipv4 },
+ /* 11 */ { "Resource Location Server", ipv4 },
+ /* 12 */ { "Host Name", string },
+ /* 13 */ { "Boot File Size", val_u_short },
+ /* 14 */ { "Merit Dump File", string },
+ /* 15 */ { "Domain Name", string },
+ /* 16 */ { "Swap Server", ipv4 },
+ /* 17 */ { "Root Path", string },
+ /* 18 */ { "Extensions Path", string },
+ /* 19 */ { "IP Forwarding", toggle },
+ /* 20 */ { "Non-Local Source Routing", toggle },
+ /* 21 */ { "Policy Filter", special },
+ /* 22 */ { "Maximum Datagram Reassembly Size", val_u_short },
+ /* 23 */ { "Default IP Time-to-Live", val_u_byte },
+ /* 24 */ { "Path MTU Aging Timeout", time_in_secs },
+ /* 25 */ { "Path MTU Plateau Table", val_u_short },
+ /* 26 */ { "Interface MTU", val_u_short },
+ /* 27 */ { "All Subnets are Local", yes_no },
+ /* 28 */ { "Broadcast Address", ipv4 },
+ /* 29 */ { "Perform Mask Discovery", toggle },
+ /* 30 */ { "Mask Supplier", yes_no },
+ /* 31 */ { "Perform Router Discover", toggle },
+ /* 32 */ { "Router Solicitation Address", ipv4 },
+ /* 33 */ { "Static Route", special },
+ /* 34 */ { "Trailer Encapsulation", toggle },
+ /* 35 */ { "ARP Cache Timeout", time_in_secs },
+ /* 36 */ { "Ethernet Encapsulation", toggle },
+ /* 37 */ { "TCP Default TTL", val_u_byte },
+ /* 38 */ { "TCP Keepalive Interval", time_in_secs },
+ /* 39 */ { "TCP Keepalive Garbage", toggle },
+ /* 40 */ { "Network Information Service Domain", string },
+ /* 41 */ { "Network Information Service Servers", ipv4 },
+ /* 42 */ { "Network Time Protocol Servers", ipv4 },
+ /* 43 */ { "Vendor-Specific Information", special },
+ /* 44 */ { "NetBIOS over TCP/IP Name Server", ipv4 },
+ /* 45 */ { "NetBIOS over TCP/IP Datagram Distribution Name Server", ipv4 },
+ /* 46 */ { "NetBIOS over TCP/IP Node Type", special },
+ /* 47 */ { "NetBIOS over TCP/IP Scope", string },
+ /* 48 */ { "X Window System Font Server", ipv4 },
+ /* 49 */ { "X Window System Display Manager", ipv4 },
+ /* 50 */ { "Requested IP Address", ipv4 },
+ /* 51 */ { "IP Address Lease Time", time_in_secs },
+ /* 52 */ { "Option Overload", special },
+ /* 53 */ { "DHCP Message Type", special },
+ /* 54 */ { "Server Identifier", ipv4 },
+ /* 55 */ { "Parameter Request List", special },
+ /* 56 */ { "Message", string },
+ /* 57 */ { "Maximum DHCP Message Size", val_u_short },
+ /* 58 */ { "Renewal Time Value", time_in_secs },
+ /* 59 */ { "Rebinding Time Value", time_in_secs },
+ /* 60 */ { "Vendor class identifier", special },
+ /* 61 */ { "Client identifier", special },
+ /* 62 */ { "Novell/Netware IP domain", string },
+ /* 63 */ { "Novell Options", special },
+ /* 64 */ { "Network Information Service+ Domain", string },
+ /* 65 */ { "Network Information Service+ Servers", ipv4 },
+ /* 66 */ { "TFTP Server Name", string },
+ /* 67 */ { "Bootfile name", string },
+ /* 68 */ { "Mobile IP Home Agent", ipv4 },
+ /* 69 */ { "SMTP Server", ipv4 },
+ /* 70 */ { "POP3 Server", ipv4 },
+ /* 71 */ { "NNTP Server", ipv4 },
+ /* 72 */ { "Default WWW Server", ipv4 },
+ /* 73 */ { "Default Finger Server", ipv4 },
+ /* 74 */ { "Default IRC Server", ipv4 },
+ /* 75 */ { "StreetTalk Server", ipv4 },
+ /* 76 */ { "StreetTalk Directory Assistance Server", ipv4 },
+ /* 77 */ { "User Class Information", opaque },
+ /* 78 */ { "Directory Agent Information", special },
+ /* 79 */ { "Service Location Agent Scope", special },
+ /* 80 */ { "Naming Authority", opaque },
+ /* 81 */ { "Client Fully Qualified Domain Name", opaque },
+ /* 82 */ { "Agent Information Option", special },
+ /* 83 */ { "Unassigned", opaque },
+ /* 84 */ { "Unassigned", opaque },
+ /* 85 */ { "Novell Directory Services Servers", special },
+ /* 86 */ { "Novell Directory Services Tree Name", string },
+ /* 87 */ { "Novell Directory Services Context", string },
+ /* 88 */ { "IEEE 1003.1 POSIX Timezone", opaque },
+ /* 89 */ { "Fully Qualified Domain Name", opaque },
+ /* 90 */ { "Authentication", special },
+ /* 91 */ { "Vines TCP/IP Server Option", opaque },
+ /* 92 */ { "Server Selection Option", opaque },
+ /* 93 */ { "Client System Architecture", opaque },
+ /* 94 */ { "Client Network Device Interface", opaque },
+ /* 95 */ { "Lightweight Directory Access Protocol", opaque },
+ /* 96 */ { "IPv6 Transitions", opaque },
+ /* 97 */ { "UUID/GUID-based Client Identifier", opaque },
+ /* 98 */ { "Open Group's User Authentication", opaque },
+ /* 99 */ { "Unassigned", opaque },
+ /* 100 */ { "Printer Name", opaque },
+ /* 101 */ { "MDHCP multicast address", opaque },
+ /* 102 */ { "Removed/unassigned", opaque },
+ /* 103 */ { "Removed/unassigned", opaque },
+ /* 104 */ { "Removed/unassigned", opaque },
+ /* 105 */ { "Removed/unassigned", opaque },
+ /* 106 */ { "Removed/unassigned", opaque },
+ /* 107 */ { "Removed/unassigned", opaque },
+ /* 108 */ { "Swap Path Option", opaque },
+ /* 109 */ { "Unassigned", opaque },
+ /* 110 */ { "IPX Compability", opaque },
+ /* 111 */ { "Unassigned", opaque },
+ /* 112 */ { "NetInfo Parent Server Address", ipv4 },
+ /* 113 */ { "NetInfo Parent Server Tag", string },
+ /* 114 */ { "URL", opaque },
+ /* 115 */ { "DHCP Failover Protocol", opaque },
+ /* 116 */ { "DHCP Auto-Configuration", opaque },
+ /* 117 */ { "Name Service Search", opaque },
+ /* 118 */ { "Subnet Selection Option", opaque },
+ /* 119 */ { "Domain Search", opaque },
+ /* 120 */ { "SIP Servers", opaque },
+ /* 121 */ { "Classless Static Route", opaque },
+ /* 122 */ { "CableLabs Client Configuration", special },
+ /* 123 */ { "Unassigned", opaque },
+ /* 124 */ { "Unassigned", opaque },
+ /* 125 */ { "Unassigned", opaque },
+ /* 126 */ { "Extension", opaque },
+ /* 127 */ { "Extension", opaque },
+ /* 128 */ { "Private", opaque },
+ /* 129 */ { "Private", opaque },
+ /* 130 */ { "Private", opaque },
+ /* 131 */ { "Private", opaque },
+ /* 132 */ { "Private", opaque },
+ /* 133 */ { "Private", opaque },
+ /* 134 */ { "Private", opaque },
+ /* 135 */ { "Private", opaque },
+ /* 136 */ { "Private", opaque },
+ /* 137 */ { "Private", opaque },
+ /* 138 */ { "Private", opaque },
+ /* 139 */ { "Private", opaque },
+ /* 140 */ { "Private", opaque },
+ /* 141 */ { "Private", opaque },
+ /* 142 */ { "Private", opaque },
+ /* 143 */ { "Private", opaque },
+ /* 144 */ { "Private", opaque },
+ /* 145 */ { "Private", opaque },
+ /* 146 */ { "Private", opaque },
+ /* 147 */ { "Private", opaque },
+ /* 148 */ { "Private", opaque },
+ /* 149 */ { "Private", opaque },
+ /* 150 */ { "Private", opaque },
+ /* 151 */ { "Private", opaque },
+ /* 152 */ { "Private", opaque },
+ /* 153 */ { "Private", opaque },
+ /* 154 */ { "Private", opaque },
+ /* 155 */ { "Private", opaque },
+ /* 156 */ { "Private", opaque },
+ /* 157 */ { "Private", opaque },
+ /* 158 */ { "Private", opaque },
+ /* 159 */ { "Private", opaque },
+ /* 160 */ { "Private", opaque },
+ /* 161 */ { "Private", opaque },
+ /* 162 */ { "Private", opaque },
+ /* 163 */ { "Private", opaque },
+ /* 164 */ { "Private", opaque },
+ /* 165 */ { "Private", opaque },
+ /* 166 */ { "Private", opaque },
+ /* 167 */ { "Private", opaque },
+ /* 168 */ { "Private", opaque },
+ /* 169 */ { "Private", opaque },
+ /* 170 */ { "Private", opaque },
+ /* 171 */ { "Private", opaque },
+ /* 172 */ { "Private", opaque },
+ /* 173 */ { "Private", opaque },
+ /* 174 */ { "Private", opaque },
+ /* 175 */ { "Private", opaque },
+ /* 176 */ { "Private", opaque },
+ /* 177 */ { "Private", opaque },
+ /* 178 */ { "Private", opaque },
+ /* 179 */ { "Private", opaque },
+ /* 180 */ { "Private", opaque },
+ /* 181 */ { "Private", opaque },
+ /* 182 */ { "Private", opaque },
+ /* 183 */ { "Private", opaque },
+ /* 184 */ { "Private", opaque },
+ /* 185 */ { "Private", opaque },
+ /* 186 */ { "Private", opaque },
+ /* 187 */ { "Private", opaque },
+ /* 188 */ { "Private", opaque },
+ /* 189 */ { "Private", opaque },
+ /* 190 */ { "Private", opaque },
+ /* 191 */ { "Private", opaque },
+ /* 192 */ { "Private", opaque },
+ /* 193 */ { "Private", opaque },
+ /* 194 */ { "Private", opaque },
+ /* 195 */ { "Private", opaque },
+ /* 196 */ { "Private", opaque },
+ /* 197 */ { "Private", opaque },
+ /* 198 */ { "Private", opaque },
+ /* 199 */ { "Private", opaque },
+ /* 200 */ { "Private", opaque },
+ /* 201 */ { "Private", opaque },
+ /* 202 */ { "Private", opaque },
+ /* 203 */ { "Private", opaque },
+ /* 204 */ { "Private", opaque },
+ /* 205 */ { "Private", opaque },
+ /* 206 */ { "Private", opaque },
+ /* 207 */ { "Private", opaque },
+ /* 208 */ { "Private", opaque },
+ /* 209 */ { "Private", opaque },
+ /* 210 */ { "Authentication", special }
+ };
+
+ /* Options whose length isn't "vlen + 2". */
+ switch (code) {
+
+ case 0: /* Padding */
+ /* check how much padding we have */
+ for (i = voff + 1; i < eoff; i++ ) {
+ if (tvb_get_guint8(tvb, i) != 0) {
+ break;
+ }
+ }
+ i = i - voff;
+ if (!first_pass) {
+ if (bp_tree != NULL) {
+ proto_tree_add_text(bp_tree, tvb, voff, i,
+ "Padding");
+ }
+ }
+ consumed = i;
+ return consumed;
+ break;
+
+ case 255: /* End Option */
+ if (!first_pass) {
+ if (bp_tree != NULL) {
+ proto_tree_add_text(bp_tree, tvb, voff, 1,
+ "End Option");
+ }
+ }
+ *at_end = TRUE;
+ consumed = 1;
+ return consumed;
+ }
+
+ /*
+ * Get the length of the option, and the number of bytes it
+ * consumes (the length doesn't include the option code or
+ * length bytes).
+ *
+ * On the first pass, check first whether we have the length
+ * byte, so that we don't throw an exception; if we throw an
+ * exception in the first pass, which is only checking for options
+ * whose values we need in order to properly dissect the packet
+ * on the second pass, we won't actually dissect the options, so
+ * you won't be able to see which option had the problem.
+ */
+ if (first_pass) {
+ if (!tvb_bytes_exist(tvb, voff+1, 1)) {
+ /*
+ * We don't have the length byte; just return 1
+ * as the number of bytes we consumed, to count
+ * the code byte.
+ */
+ return 1;
+ }
+ }
+ vlen = tvb_get_guint8(tvb, voff+1);
+ consumed = vlen + 2;
+
+ /*
+ * In the first pass, we don't put anything into the protocol
+ * tree; we just check for some options we have to look at
+ * in order to properly process the packet:
+ *
+ * 53 (DHCP message type) - if this is present, this is DHCP
+ *
+ * 60 (Vendor class identifier) - we need this in order to
+ * interpret the vendor-specific info
+ *
+ * We also check, before fetching anything, to make sure we
+ * have the entire item we're fetching, so that we don't throw
+ * an exception.
+ */
+ if (first_pass) {
+ if (tvb_bytes_exist(tvb, voff+2, consumed-2)) {
+ switch (code) {
+
+ case 53:
+ *dhcp_type_p =
+ get_dhcp_type(tvb_get_guint8(tvb, voff+2));
+ break;
+
+ case 60:
+ *vendor_class_id_p =
+ tvb_get_ptr(tvb, voff+2, consumed-2);
+ break;
+ }
+ }
+
+ /*
+ * We don't do anything else here.
+ */
+ return consumed;
+ }
+
+ /*
+ * This is the second pass - if there's a protocol tree to be
+ * built, we put stuff into it, otherwise we just return.
+ */
+ if (bp_tree == NULL) {
+ /* Don't put anything in the protocol tree. */
+ return consumed;
+ }
+
+ text = opt[code].text;
+ /* Special cases */
+ switch (code) {
+
+ case 21: /* Policy Filter */
+ if (vlen == 8) {
+ /* one IP address pair */
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s/%s", code, text,
+ ip_to_str(tvb_get_ptr(tvb, voff+2, 4)),
+ ip_to_str(tvb_get_ptr(tvb, voff+6, 4)));
+ } else {
+ /* > 1 IP address pair. Let's make a sub-tree */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ consumed, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ for (i = voff + 2; i < voff + consumed; i += 8) {
+ proto_tree_add_text(v_tree, tvb, i, 8, "IP Address/Mask: %s/%s",
+ ip_to_str(tvb_get_ptr(tvb, i, 4)),
+ ip_to_str(tvb_get_ptr(tvb, i+4, 4)));
+ }
+ }
+ break;
+
+ case 33: /* Static Route */
+ if (vlen == 8) {
+ /* one IP address pair */
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s/%s", code, text,
+ ip_to_str(tvb_get_ptr(tvb, voff+2, 4)),
+ ip_to_str(tvb_get_ptr(tvb, voff+6, 4)));
+ } else {
+ /* > 1 IP address pair. Let's make a sub-tree */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ consumed, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ for (i = voff + 2; i < voff + consumed; i += 8) {
+ proto_tree_add_text(v_tree, tvb, i, 8,
+ "Destination IP Address/Router: %s/%s",
+ ip_to_str(tvb_get_ptr(tvb, i, 4)),
+ ip_to_str(tvb_get_ptr(tvb, i+4, 4)));
+ }
+ }
+ break;
+
+ case 43: /* Vendor-Specific Info */
+ /* PXE protocol 2.1 as described in the intel specs */
+ if (*vendor_class_id_p != NULL &&
+ strncmp(*vendor_class_id_p, "PXEClient", strlen("PXEClient")) == 0) {
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ consumed, "Option %d: %s (PXEClient)", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+
+ optp = voff+2;
+ while (optp < voff+consumed) {
+ optp = dissect_vendor_pxeclient_suboption(v_tree,
+ tvb, optp);
+ }
+ } else if (*vendor_class_id_p != NULL &&
+ ((strncmp(*vendor_class_id_p, "pktc", strlen("pktc")) == 0) ||
+ (strncmp(*vendor_class_id_p, "docsis", strlen("docsis")) == 0) ||
+ (strncmp(*vendor_class_id_p, "CableHome", strlen("CableHome")) == 0))) {
+ /* CableLabs standard - see www.cablelabs.com/projects */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ consumed, "Option %d: %s (CableLabs)", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+
+ optp = voff+2;
+ while (optp < voff+consumed) {
+ optp = dissect_vendor_cablelabs_suboption(v_tree,
+ tvb, optp);
+ }
+ } else {
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s (%d bytes)", code, text, vlen);
+ }
+ break;
+
+ case 46: /* NetBIOS-over-TCP/IP Node Type */
+ byte = tvb_get_guint8(tvb, voff+2);
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s", code, text,
+ val_to_str(byte, nbnt_vals,
+ "Unknown (0x%02x)"));
+ break;
+
+ case 52: /* Option Overload */
+ byte = tvb_get_guint8(tvb, voff+2);
+ vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s", code, text,
+ val_to_str(byte, opt_overload_vals,
+ "Unknown (0x%02x)"));
+
+ /* Just in case we find an option 52 in sname or file */
+ if (voff > VENDOR_INFO_OFFSET && byte >= 1 && byte <= 3) {
+ o52tree = proto_item_add_subtree(vti, ett_bootp_option);
+ if (byte == 1 || byte == 3) { /* 'file' */
+ vti = proto_tree_add_text (o52tree, tvb,
+ FILE_NAME_OFFSET, FILE_NAME_LEN,
+ "Boot file name option overload");
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ o52voff = FILE_NAME_OFFSET;
+ o52eoff = FILE_NAME_OFFSET + FILE_NAME_LEN;
+ o52at_end = FALSE;
+ while (o52voff < o52eoff && !o52at_end) {
+ o52voff += bootp_option(tvb, v_tree, o52voff,
+ o52eoff, FALSE, &o52at_end,
+ dhcp_type_p, vendor_class_id_p);
+ }
+ }
+ if (byte == 2 || byte == 3) { /* 'sname' */
+ vti = proto_tree_add_text (o52tree, tvb,
+ SERVER_NAME_OFFSET, SERVER_NAME_LEN,
+ "Server host name option overload");
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ o52voff = SERVER_NAME_OFFSET;
+ o52eoff = SERVER_NAME_OFFSET + SERVER_NAME_LEN;
+ o52at_end = FALSE;
+ while (o52voff < o52eoff && !o52at_end) {
+ o52voff += bootp_option(tvb, v_tree, o52voff,
+ o52eoff, FALSE, &o52at_end,
+ dhcp_type_p, vendor_class_id_p);
+ }
+ }
+ }
+
+/* protocol = tvb_get_guint8(tvb, voff+2);
+ proto_tree_add_text(v_tree, tvb, voff+2, 1, "Protocol: %s (%u)",
+ val_to_str(protocol, authen_protocol_vals, "Unknown"),
+ protocol); */
+ break;
+ case 53: /* DHCP Message Type */
+ proto_tree_add_text(bp_tree, tvb, voff, 3, "Option %d: %s = DHCP %s",
+ code, text, get_dhcp_type(tvb_get_guint8(tvb, voff+2)));
+ break;
+
+ case 55: /* Parameter Request List */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ vlen + 2, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ for (i = 0; i < vlen; i++) {
+ byte = tvb_get_guint8(tvb, voff+2+i);
+ if (byte < array_length(opt)) {
+ proto_tree_add_text(v_tree, tvb, voff+2+i, 1, "%d = %s",
+ byte, opt[byte].text);
+ } else {
+ proto_tree_add_text(vti, tvb, voff+2+i, 1,
+ "Unknown Option Code: %d", byte);
+ }
+ }
+ break;
+
+ case 60: /* Vendor class identifier */
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = \"%.*s\"", code, text, vlen,
+ tvb_get_ptr(tvb, voff+2, consumed-2));
+ break;
+
+ case 61: /* Client Identifier */
+ /* We *MAY* use hwtype/hwaddr. If we have 7 bytes, I'll
+ guess that the first is the hwtype, and the last 6
+ are the hw addr */
+ if (vlen == 7) {
+ guint8 htype;
+
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ consumed, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ htype = tvb_get_guint8(tvb, voff+2);
+ proto_tree_add_text(v_tree, tvb, voff+2, 1,
+ "Hardware type: %s",
+ arphrdtype_to_str(htype,
+ "Unknown (0x%02x)"));
+ proto_tree_add_text(v_tree, tvb, voff+3, 6,
+ "Client hardware address: %s",
+ arphrdaddr_to_str(tvb_get_ptr(tvb, voff+3, 6),
+ 6, htype));
+ } else {
+ /* otherwise, it's opaque data */
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s (%d bytes)", code, text, vlen);
+ }
+ break;
+
+ case 63: /* NetWare/IP options */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ consumed, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+
+ optp = voff+2;
+ while (optp < voff+consumed)
+ optp = dissect_netware_ip_suboption(v_tree, tvb, optp);
+ break;
+
+ case 78: /* SLP Directory Agent Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/
+ byte = tvb_get_guint8(tvb, voff+2);
+ vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s", code, text,
+ val_to_str(byte, slpda_vals,
+ "Unknown (0x%02x)"));
+ if (byte == 0x80) {
+ voff++;
+ consumed--;
+ }
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ for (i = voff + 3; i < voff + consumed; i += 4) {
+ proto_tree_add_text(v_tree, tvb, i, 4, "SLPDA Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, i, 4)));
+ }
+ if (byte == 0x80) {
+ consumed++;
+ }
+ break;
+
+ case 79: /* SLP Service Scope Option RFC2610 Added by Greg Morris (gmorris@novell.com)*/
+ byte = tvb_get_guint8(tvb, voff+2);
+ vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s", code, text,
+ val_to_str(byte, slp_scope_vals,
+ "Unknown (0x%02x)"));
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ proto_tree_add_text(v_tree, tvb, voff+3, consumed-3,
+ "%s = \"%.*s\"", text, vlen-1,
+ tvb_get_ptr(tvb, voff+3, vlen-1));
+ break;
+
+ case 82: /* Relay Agent Information Option */
+ vti = proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s (%d bytes)",
+ code, text, vlen);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ optp = voff+2;
+ while (optp < voff+consumed) {
+ optp = bootp_dhcp_decode_agent_info(v_tree, tvb, optp);
+ }
+ break;
+
+ case 85: /* Novell Servers */
+ /* Option 85 can be sent as a string */
+ /* Added by Greg Morris (gmorris@novell.com) */
+ if (novell_string && code==85) {
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = \"%.*s\"", code, text, vlen,
+ tvb_get_ptr(tvb, voff+2, consumed-2));
+ }
+ else
+ {
+ if (vlen == 4) {
+ /* one IP address */
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s", code, text,
+ ip_to_str(tvb_get_ptr(tvb, voff+2, 4)));
+ } else {
+ /* > 1 IP addresses. Let's make a sub-tree */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ consumed, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ for (i = voff + 2; i < voff + consumed; i += 4) {
+ proto_tree_add_text(v_tree, tvb, i, 4, "IP Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, i, 4)));
+ }
+ }
+ }
+ break;
+
+ case 122: /* CableLabs Client Configuration */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ vlen + 2, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ optp = voff+2;
+ while (optp < voff+consumed) {
+ optp = dissect_cablelabs_clientconfig_suboption(v_tree, tvb, optp);
+ }
+ break;
+
+ case 90: /* DHCP Authentication */
+ case 210: /* Was this used for authentication at one time? */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ vlen + 2, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+
+ protocol = tvb_get_guint8(tvb, voff+2);
+ proto_tree_add_text(v_tree, tvb, voff+2, 1, "Protocol: %s (%u)",
+ val_to_str(protocol, authen_protocol_vals, "Unknown"),
+ protocol);
+
+ algorithm = tvb_get_guint8(tvb, voff+3);
+ switch (protocol) {
+
+ case AUTHEN_PROTO_DELAYED_AUTHEN:
+ proto_tree_add_text(v_tree, tvb, voff+3, 1,
+ "Algorithm: %s (%u)",
+ val_to_str(algorithm, authen_da_algo_vals, "Unknown"),
+ algorithm);
+ break;
+
+ default:
+ proto_tree_add_text(v_tree, tvb, voff+3, 1,
+ "Algorithm: %u", algorithm);
+ break;
+ }
+
+ rdm = tvb_get_guint8(tvb, voff+4);
+ proto_tree_add_text(v_tree, tvb, voff+4, 1,
+ "Replay Detection Method: %s (%u)",
+ val_to_str(rdm, authen_rdm_vals, "Unknown"),
+ rdm);
+
+ switch (rdm) {
+
+ case AUTHEN_RDM_MONOTONIC_COUNTER:
+ proto_tree_add_text(v_tree, tvb, voff+5, 8,
+ "Replay Detection Value: %s",
+ u64toh(tvb_get_ptr(tvb, voff+5, 8)));
+ break;
+
+ default:
+ proto_tree_add_text(v_tree, tvb, voff+5, 8,
+ "Replay Detection Value: %s",
+ tvb_bytes_to_str(tvb, voff+5, 8));
+ break;
+ }
+
+ switch (protocol) {
+
+ case AUTHEN_PROTO_DELAYED_AUTHEN:
+ switch (algorithm) {
+
+ case AUTHEN_DELAYED_ALGO_HMAC_MD5:
+ proto_tree_add_text(v_tree, tvb, voff+13, 4,
+ "Secret ID: 0x%08x",
+ tvb_get_ntohl(tvb, voff+13));
+ proto_tree_add_text(v_tree, tvb, voff+17, 16,
+ "HMAC MD5 Hash: %s",
+ tvb_bytes_to_str(tvb, voff+17, 16));
+ break;
+
+ default:
+ proto_tree_add_text(v_tree, tvb, voff+13, vlen-11,
+ "Authentication Information: %s",
+ tvb_bytes_to_str(tvb, voff+17, vlen-11));
+ break;
+ }
+ break;
+
+ default:
+ proto_tree_add_text(v_tree, tvb, voff+13, vlen-11,
+ "Authentication Information: %s",
+ tvb_bytes_to_str(tvb, voff+17, vlen-11));
+ break;
+ }
+ break;
+
+ default: /* not special */
+ break;
+ }
+
+ /* Normal cases */
+ if (code < array_length(opt)) {
+ text = opt[code].text;
+ ftype = opt[code].ftype;
+
+ switch (ftype) {
+
+ case special:
+ return consumed;
+
+ case ipv4:
+ if (vlen == 4) {
+ /* one IP address */
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s", code, text,
+ ip_to_str(tvb_get_ptr(tvb, voff+2, 4)));
+ } else {
+ /* > 1 IP addresses. Let's make a sub-tree */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ consumed, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ for (i = voff + 2; i < voff + consumed; i += 4) {
+ proto_tree_add_text(v_tree, tvb, i, 4, "IP Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, i, 4)));
+ }
+ }
+ break;
+
+ case string:
+ /* Fix for non null-terminated string supplied by
+ * John Lines <John.Lines@aeat.co.uk>
+ */
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = \"%.*s\"", code, text, vlen,
+ tvb_get_ptr(tvb, voff+2, consumed-2));
+ break;
+
+ case opaque:
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s (%d bytes)",
+ code, text, vlen);
+ break;
+
+ case val_u_short:
+ if (vlen == 2) {
+ /* one gushort */
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %d", code, text,
+ tvb_get_ntohs(tvb, voff+2));
+ } else {
+ /* > 1 gushort */
+ vti = proto_tree_add_text(bp_tree, tvb, voff,
+ consumed, "Option %d: %s", code, text);
+ v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ for (i = voff + 2; i < voff + consumed; i += 2) {
+ proto_tree_add_text(v_tree, tvb, i, 4, "Value: %d",
+ tvb_get_ntohs(tvb, i));
+ }
+ }
+ break;
+
+ case val_u_long:
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %d", code, text,
+ tvb_get_ntohl(tvb, voff+2));
+ break;
+
+ case val_u_byte:
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %d", code, text,
+ tvb_get_guint8(tvb, voff+2));
+ break;
+
+ case toggle:
+ i = tvb_get_guint8(tvb, voff+2);
+ if (i != 0 && i != 1) {
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = Invalid Value %d", code, text,
+ i);
+ } else {
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s", code, text,
+ i == 0 ? "Disabled" : "Enabled");
+ }
+ break;
+
+ case yes_no:
+ i = tvb_get_guint8(tvb, voff+2);
+ if (i != 0 && i != 1) {
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = Invalid Value %d", code, text,
+ i);
+ } else {
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s", code, text,
+ i == 0 ? "No" : "Yes");
+ }
+ break;
+
+ case time_in_secs:
+ time_secs = tvb_get_ntohl(tvb, voff+2);
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s = %s", code, text,
+ ((time_secs == 0xffffffff) ?
+ "infinity" :
+ time_secs_to_str(time_secs)));
+ break;
+
+ default:
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Option %d: %s (%d bytes)", code, text, vlen);
+ }
+ } else {
+ proto_tree_add_text(bp_tree, tvb, voff, consumed,
+ "Unknown Option Code: %d (%d bytes)", code, vlen);
+ }
+
+ return consumed;
+}
+
+static int
+bootp_dhcp_decode_agent_info(proto_tree *v_tree, tvbuff_t *tvb, int optp)
+{
+ guint8 subopt;
+ guint8 subopt_len;
+
+ subopt = tvb_get_guint8(tvb, optp);
+ subopt_len = tvb_get_guint8(tvb, optp+1);
+ switch (subopt) {
+ case 1:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len + 2,
+ "Agent Circuit ID: %s",
+ tvb_bytes_to_str(tvb, optp+2, subopt_len));
+ break;
+ case 2:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len + 2,
+ "Agent Remote ID: %s",
+ tvb_bytes_to_str(tvb, optp+2, subopt_len));
+ break;
+ default:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len + 2,
+ "Invalid agent suboption %d (%d bytes)",
+ subopt, subopt_len);
+ break;
+ }
+ optp += (subopt_len + 2);
+ return optp;
+}
+
+static int
+dissect_vendor_pxeclient_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp)
+{
+ guint8 subopt;
+ guint8 subopt_len;
+ int slask;
+ proto_tree *o43pxeclient_v_tree;
+ proto_item *vti;
+
+ struct o43pxeclient_opt_info {
+ char *text;
+ enum field_type ft;
+ };
+
+ static struct o43pxeclient_opt_info o43pxeclient_opt[]= {
+ /* 0 */ {"nop", special}, /* dummy */
+ /* 1 */ {"PXE mtftp IP", ipv4},
+ /* 2 */ {"PXE mtftp client port", val_u_le_short},
+ /* 3 */ {"PXE mtftp server port",val_u_le_short},
+ /* 4 */ {"PXE mtftp timeout", val_u_byte},
+ /* 5 */ {"PXE mtftp delay", val_u_byte},
+ /* 6 */ {"PXE discovery control", val_u_byte},
+ /*
+ * Correct: b0 (lsb): disable broadcast discovery
+ * b1: disable multicast discovery
+ * b2: only use/accept servers in boot servers
+ * b3: download bootfile without prompt/menu/disc
+ */
+ /* 7 */ {"PXE multicast address", ipv4},
+ /* 8 */ {"PXE boot servers", special},
+ /* 9 */ {"PXE boot menu", special},
+ /* 10 */ {"PXE menu prompt", special},
+ /* 11 */ {"PXE multicast address alloc", special},
+ /* 12 */ {"PXE credential types", special},
+ /* 71 {"PXE boot item", special} */
+ /* 255 {"PXE end options", special} */
+ };
+
+ subopt = tvb_get_guint8(tvb, optp);
+
+ if (subopt == 0 ) {
+ proto_tree_add_text(v_tree, tvb, optp, 1, "Padding");
+ return (optp+1);
+ } else if (subopt == 255) { /* End Option */
+ proto_tree_add_text(v_tree, tvb, optp, 1, "End PXEClient option");
+ /* Make sure we skip any junk left this option */
+ return (optp+255);
+ }
+
+ subopt_len = tvb_get_guint8(tvb, optp+1);
+
+ if ( subopt == 71 ) { /* 71 {"PXE boot item", special} */
+ /* case special */
+ /* I may need to decode that properly one day */
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s (%d byte%s)" ,
+ subopt, "PXE boot item",
+ subopt_len, PLURALIZE(subopt_len));
+ } else if ((subopt < 1 ) || (subopt > array_length(o43pxeclient_opt))) {
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Unknown suboption %d (%d byte%s)", subopt, subopt_len,
+ PLURALIZE(subopt_len));
+ } else {
+ switch (o43pxeclient_opt[subopt].ft) {
+
+/* XXX case string:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s", subopt, o43pxeclient_opt[subopt].text);
+ break;
+ XXX */
+ case special:
+ /* I may need to decode that properly one day */
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s (%d byte%s)" ,
+ subopt, o43pxeclient_opt[subopt].text,
+ subopt_len, PLURALIZE(subopt_len));
+ break;
+
+ case val_u_le_short:
+ proto_tree_add_text(v_tree, tvb, optp, 4, "Suboption %d: %s = %u",
+ subopt, o43pxeclient_opt[subopt].text,
+ tvb_get_letohs(tvb, optp+2));
+ break;
+
+ case val_u_byte:
+ proto_tree_add_text(v_tree, tvb, optp, 3, "Suboption %d: %s = %u",
+ subopt, o43pxeclient_opt[subopt].text,
+ tvb_get_guint8(tvb, optp+2));
+ break;
+
+ case ipv4:
+ if (subopt_len == 4) {
+ /* one IP address */
+ proto_tree_add_text(v_tree, tvb, optp, 6,
+ "Suboption %d : %s = %s",
+ subopt, o43pxeclient_opt[subopt].text,
+ ip_to_str(tvb_get_ptr(tvb, optp+2, 4)));
+ } else {
+ /* > 1 IP addresses. Let's make a sub-tree */
+ vti = proto_tree_add_text(v_tree, tvb, optp,
+ subopt_len+2, "Suboption %d: %s",
+ subopt, o43pxeclient_opt[subopt].text);
+ o43pxeclient_v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ for (slask = optp + 2 ; slask < optp+subopt_len; slask += 4) {
+ proto_tree_add_text(o43pxeclient_v_tree, tvb, slask, 4, "IP Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, slask, 4)));
+ }
+ }
+ break;
+ default:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
+ break;
+ }
+ }
+ optp += (subopt_len + 2);
+ return optp;
+}
+
+static int
+dissect_vendor_cablelabs_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp)
+{
+ guint8 subopt;
+ guint8 subopt_len;
+
+ struct o43cablelabs_opt_info {
+ char *text;
+ enum field_type ft;
+ };
+
+ static struct o43cablelabs_opt_info o43cablelabs_opt[]= {
+ /* 0 */ {"nop", special}, /* dummy */
+ /* 1 */ {"Suboption Request List", string},
+ /* 2 */ {"Device Type", string},
+ /* 3 */ {"eSAFE Types", string},
+ /* 4 */ {"Serial Number", string},
+ /* 5 */ {"Hardware Version", string},
+ /* 6 */ {"Software Version", string},
+ /* 7 */ {"Boot ROM version", string},
+ /* 8 */ {"Organizational Unique Identifier", bytes},
+ /* 9 */ {"Model Number", string},
+ /* 10 */ {"Vendor Name", string},
+ /* *** 11-30: CableHome *** */
+ /* 11 */ {"PS WAN-Man", special},
+ /* 12 */ {"CM/PS System Description", string},
+ /* 13 */ {"CM/PS Firmware Revision", string},
+ /* 14 */ {"Firewall Policy File Version", string},
+ /* 15 */ {"Unassigned (CableHome)", special},
+ /* 16 */ {"Unassigned (CableHome)", special},
+ /* 17 */ {"Unassigned (CableHome)", special},
+ /* 18 */ {"Unassigned (CableHome)", special},
+ /* 19 */ {"Unassigned (CableHome)", special},
+ /* 20 */ {"Unassigned (CableHome)", special},
+ /* 21 */ {"Unassigned (CableHome)", special},
+ /* 22 */ {"Unassigned (CableHome)", special},
+ /* 23 */ {"Unassigned (CableHome)", special},
+ /* 24 */ {"Unassigned (CableHome)", special},
+ /* 25 */ {"Unassigned (CableHome)", special},
+ /* 26 */ {"Unassigned (CableHome)", special},
+ /* 27 */ {"Unassigned (CableHome)", special},
+ /* 28 */ {"Unassigned (CableHome)", special},
+ /* 29 */ {"Unassigned (CableHome)", special},
+ /* 30 */ {"Unassigned (CableHome)", special},
+ /* *** 31-50: PacketCable *** */
+ /* 31 */ {"MTA MAC Address", string},
+ /* 32 */ {"Correlation ID", string},
+ /* 33-50 {"Unassigned (PacketCable)", special}, */
+ /* *** 51-127: CableLabs *** */
+ /* 51-127 {"Unassigned (CableLabs)", special}, */
+ /* *** 128-254: Vendors *** */
+ /* 128-254 {"Unassigned (Vendors)", special}, */
+ /* 255 {"end options", special} */
+ };
+
+ subopt = tvb_get_guint8(tvb, optp);
+
+ if (subopt == 0 ) {
+ proto_tree_add_text(v_tree, tvb, optp, 1, "Padding");
+ return (optp+1);
+ } else if (subopt == 255) { /* End Option */
+ proto_tree_add_text(v_tree, tvb, optp, 1, "End option");
+ /* Make sure we skip any junk left this option */
+ return (optp+255);
+ }
+
+ subopt_len = tvb_get_guint8(tvb, optp+1);
+
+ if ( (subopt < 1 ) || (subopt > array_length(o43cablelabs_opt)) ) {
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: Unassigned (%d byte%s)", subopt, subopt_len,
+ PLURALIZE(subopt_len));
+ } else {
+ switch (o43cablelabs_opt[subopt].ft) {
+
+ case string:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s = \"%.*s\"", subopt,
+ o43cablelabs_opt[subopt].text, subopt_len,
+ tvb_get_ptr(tvb, optp+2, subopt_len));
+ break;
+
+ case bytes:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s = 0x%s", subopt,
+ o43cablelabs_opt[subopt].text,
+ tvb_bytes_to_str(tvb, optp+2, subopt_len));
+ break;
+
+ case special:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s (%d byte%s)" ,
+ subopt, o43cablelabs_opt[subopt].text,
+ subopt_len, PLURALIZE(subopt_len));
+ break;
+
+ default:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
+ break;
+ }
+ }
+ optp += (subopt_len + 2);
+ return optp;
+}
+
+static int
+dissect_netware_ip_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp)
+{
+ guint8 subopt;
+ guint8 subopt_len;
+ int slask;
+ proto_tree *o63_v_tree;
+ proto_item *vti;
+
+ struct o63_opt_info {
+ char *truet;
+ char *falset;
+ enum field_type ft;
+ };
+
+ static struct o63_opt_info o63_opt[]= {
+ /* 0 */ {"","",none},
+ /* 1 */ {"NWIP does not exist on subnet","",string},
+ /* 2 */ {"NWIP exist in options area","",string},
+ /* 3 */ {"NWIP exists in sname/file","",string},
+ /* 4 */ {"NWIP exists, but too big","",string},
+ /* 5 */ {"Broadcast for nearest Netware server","Do NOT Broadcast for nearest Netware server",yes_no},
+ /* 6 */ {"Preferred DSS server","",ipv4},
+ /* 7 */ {"Nearest NWIP server","",ipv4},
+ /* 8 */ {"Autoretries","",val_u_short},
+ /* 9 */ {"Autoretry delay, secs ","",val_u_short},
+ /* 10*/ {"Support NetWare/IP v1.1","Do NOT support NetWare/IP v1.1",yes_no},
+ /* 11*/ {"Primary DSS ", "" , special}
+ };
+
+ subopt = tvb_get_guint8(tvb, optp);
+ if (subopt > array_length(o63_opt)) {
+ proto_tree_add_text(v_tree, tvb,optp,1,"Unknown suboption %d", subopt);
+ optp++;
+ } else {
+ switch (o63_opt[subopt].ft) {
+
+ case string:
+ proto_tree_add_text(v_tree, tvb, optp, 2, "Suboption %d: %s", subopt, o63_opt[subopt].truet);
+ optp+=2;
+ break;
+
+ case yes_no:
+ if (tvb_get_guint8(tvb, optp+2)==1) {
+ proto_tree_add_text(v_tree, tvb, optp, 3, "Suboption %d: %s", subopt, o63_opt[subopt].truet);
+ } else {
+ proto_tree_add_text(v_tree, tvb, optp, 3, "Suboption %d: %s" , subopt, o63_opt[subopt].falset);
+ }
+ optp+=3;
+ break;
+
+ case special:
+ proto_tree_add_text(v_tree, tvb, optp, 6,
+ "Suboption %d: %s = %s" ,
+ subopt, o63_opt[subopt].truet,
+ ip_to_str(tvb_get_ptr(tvb, optp+2, 4)));
+ optp=optp+6;
+ break;
+
+ case val_u_short:
+ proto_tree_add_text(v_tree, tvb, optp, 3, "Suboption %d: %s = %u",
+ subopt, o63_opt[subopt].truet,
+ tvb_get_guint8(tvb, optp+2)); /* XXX - 1 byte? */
+ optp+=3;
+ break;
+
+ case ipv4:
+ subopt_len = tvb_get_guint8(tvb, optp+1);
+ if (subopt_len == 4) {
+ /* one IP address */
+ proto_tree_add_text(v_tree, tvb, optp, 6,
+ "Suboption %d : %s = %s",
+ subopt, o63_opt[subopt].truet,
+ ip_to_str(tvb_get_ptr(tvb, optp+2, 4)));
+ optp=optp+6;
+ } else {
+ /* > 1 IP addresses. Let's make a sub-tree */
+ vti = proto_tree_add_text(v_tree, tvb, optp,
+ subopt_len+2, "Suboption %d: %s",
+ subopt, o63_opt[subopt].truet);
+ o63_v_tree = proto_item_add_subtree(vti, ett_bootp_option);
+ for (slask = optp + 2 ; slask < optp+subopt_len; slask += 4) {
+ proto_tree_add_text(o63_v_tree, tvb, slask, 4, "IP Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, slask, 4)));
+ }
+ optp=slask;
+ }
+ break;
+ default:
+ proto_tree_add_text(v_tree, tvb,optp,1,"Unknown suboption %d", subopt);
+ optp++;
+ break;
+ }
+ }
+ return optp;
+}
+
+static int
+dissect_cablelabs_clientconfig_suboption(proto_tree *v_tree, tvbuff_t *tvb, int optp)
+{
+ guint8 subopt;
+ guint8 subopt_len;
+ guint8 flag;
+ char dname[MAXDNAME];
+ int dname_len;
+
+ struct o122cablelabs_opt_info {
+ char *text;
+ enum field_type ft;
+ };
+
+ static struct o122cablelabs_opt_info o122cablelabs_opt[]= {
+ /* 0 */ {"nop", special}, /* dummy */
+ /* 1 */ {"TSP's Primary DHCP Server Address", ipv4},
+ /* 2 */ {"TSP's Secondary DHCP Server Address", ipv4},
+ /* 3 */ {"TSP's Provisioning Server Address", ipv4_or_fqdn},
+ /* 4 */ {"TSP's AS-REQ/AS-REP Backoff and Retry", special},
+ /* 5 */ {"TSP's AP-REQ/AP-REP Backoff and Retry", special},
+ /* 6 */ {"TSP's Kerberos Realm Name", fqdn},
+ /* 7 */ {"TSP's Ticket Granting Server Utilization", special},
+ /* 8 */ {"TSP's Provisioning Timer Value", special},
+ /* 9 */ {"PacketCable Security Ticket Control", special},
+ /* *** 10-255: Reserved for future use *** */
+ };
+
+ subopt = tvb_get_guint8(tvb, optp);
+ subopt_len = tvb_get_guint8(tvb, optp+1);
+
+ if ((subopt < 1 ) || (subopt > array_length(o122cablelabs_opt))) {
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: Unassigned (%d byte%s)", subopt, subopt_len,
+ PLURALIZE(subopt_len));
+ } else {
+ switch (o122cablelabs_opt[subopt].ft) {
+
+ case string:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s = \"%.*s\"", subopt,
+ o122cablelabs_opt[subopt].text, subopt_len,
+ tvb_get_ptr(tvb, optp+2, subopt_len));
+ break;
+
+ case special:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s (%d byte%s)" ,
+ subopt, o122cablelabs_opt[subopt].text,
+ subopt_len, PLURALIZE(subopt_len));
+ break;
+ case ipv4:
+ proto_tree_add_text(v_tree, tvb, optp, 6,
+ "Suboption %d: %s = %s",
+ subopt, o122cablelabs_opt[subopt].text,
+ ip_to_str(tvb_get_ptr(tvb, optp+2, 4)));
+ break;
+ case fqdn:
+ dname_len = get_dns_name(tvb, optp+2, optp+2, dname, sizeof(dname));
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s = %.*s", subopt,
+ o122cablelabs_opt[subopt].text,
+ dname_len, dname);
+ break;
+ case ipv4_or_fqdn:
+ flag = tvb_get_guint8(tvb, optp+2);
+ if (flag == 0) { /* FQDN */
+ dname_len = get_dns_name(tvb, optp+3, optp+3, dname, sizeof(dname));
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s = %.*s", subopt,
+ o122cablelabs_opt[subopt].text,
+ dname_len, dname);
+ } else if (flag == 1) { /* IPv4 */
+ proto_tree_add_text(v_tree, tvb, optp, 6,
+ "Suboption %d: %s = %s",
+ subopt, o122cablelabs_opt[subopt].text,
+ ip_to_str(tvb_get_ptr(tvb, optp+3, 4)));
+ } else {
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s = Invalid Value (%d byte%s)",
+ subopt, o122cablelabs_opt[subopt].text,
+ subopt_len, PLURALIZE(subopt_len));
+ }
+ break;
+ case yes_no:
+ flag = tvb_get_guint8(tvb, optp+2);
+ if (flag == 0 || flag == 1) {
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s = %s", subopt,
+ o122cablelabs_opt[subopt].text,
+ flag == 0 ? "No" : "Yes");
+ } else {
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,
+ "Suboption %d: %s = Invalid Value %d",
+ subopt, o122cablelabs_opt[subopt].text, flag);
+ }
+ break;
+ default:
+ proto_tree_add_text(v_tree, tvb, optp, subopt_len+2,"ERROR, please report: Unknown subopt type handler %d", subopt);
+ break;
+ }
+ }
+ optp += (subopt_len + 2);
+ return optp;
+}
+
+
+#define BOOTREQUEST 1
+#define BOOTREPLY 2
+
+static const value_string op_vals[] = {
+ { BOOTREQUEST, "Boot Request" },
+ { BOOTREPLY, "Boot Reply" },
+ { 0, NULL }
+};
+
+static void
+dissect_bootp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *bp_tree = NULL;
+ proto_item *ti;
+ proto_tree *flag_tree = NULL;
+ proto_item *fi;
+ guint8 op;
+ guint8 htype, hlen;
+ const guint8 *haddr;
+ int voff, eoff, tmpvoff; /* vendor offset, end offset */
+ guint32 ip_addr;
+ gboolean at_end;
+ const char *dhcp_type = NULL;
+ const guint8 *vendor_class_id = NULL;
+ guint16 flags;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BOOTP");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * In case we throw an exception fetching the opcode, etc.
+ */
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ op = tvb_get_guint8(tvb, 0);
+ htype = tvb_get_guint8(tvb, 1);
+ hlen = tvb_get_guint8(tvb, 2);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ switch (op) {
+
+ case BOOTREQUEST:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Boot Request from %s",
+ arphrdaddr_to_str(tvb_get_ptr(tvb, 28, hlen),
+ hlen, htype));
+ break;
+
+ case BOOTREPLY:
+ col_set_str(pinfo->cinfo, COL_INFO, "Boot Reply");
+ break;
+
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown BOOTP message type (%u)",
+ op);
+ break;
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_bootp, tvb, 0, -1, FALSE);
+ bp_tree = proto_item_add_subtree(ti, ett_bootp);
+
+ proto_tree_add_uint(bp_tree, hf_bootp_type, tvb,
+ 0, 1,
+ op);
+ proto_tree_add_uint_format(bp_tree, hf_bootp_hw_type, tvb,
+ 1, 1,
+ htype,
+ "Hardware type: %s",
+ arphrdtype_to_str(htype,
+ "Unknown (0x%02x)"));
+ proto_tree_add_uint(bp_tree, hf_bootp_hw_len, tvb,
+ 2, 1, hlen);
+ proto_tree_add_item(bp_tree, hf_bootp_hops, tvb,
+ 3, 1, FALSE);
+ proto_tree_add_item(bp_tree, hf_bootp_id, tvb,
+ 4, 4, FALSE);
+ proto_tree_add_item(bp_tree, hf_bootp_secs, tvb,
+ 8, 2, FALSE);
+ flags = tvb_get_ntohs(tvb, 10);
+ fi = proto_tree_add_uint(bp_tree, hf_bootp_flags, tvb,
+ 10, 2, flags);
+ proto_item_append_text(fi, " (%s)",
+ (flags & BOOTP_BC) ? "Broadcast" : "Unicast");
+ flag_tree = proto_item_add_subtree(fi, ett_bootp_flags);
+ proto_tree_add_boolean(flag_tree, hf_bootp_flags_broadcast, tvb,
+ 10, 2, flags);
+ proto_tree_add_uint(flag_tree, hf_bootp_flags_reserved, tvb,
+ 10, 2, flags);
+ proto_tree_add_item(bp_tree, hf_bootp_ip_client, tvb,
+ 12, 4, FALSE);
+ proto_tree_add_item(bp_tree, hf_bootp_ip_your, tvb,
+ 16, 4, FALSE);
+ proto_tree_add_item(bp_tree, hf_bootp_ip_server, tvb,
+ 20, 4, FALSE);
+ proto_tree_add_item(bp_tree, hf_bootp_ip_relay, tvb,
+ 24, 4, FALSE);
+
+ if (hlen > 0) {
+ haddr = tvb_get_ptr(tvb, 28, hlen);
+ proto_tree_add_bytes_format(bp_tree, hf_bootp_hw_addr, tvb,
+ 28, hlen,
+ haddr,
+ "Client hardware address: %s",
+ arphrdaddr_to_str(haddr,
+ hlen,
+ htype));
+ }
+ else {
+ proto_tree_add_text(bp_tree, tvb,
+ 28, 0, "Client address not given");
+ }
+
+ /* The server host name is optional */
+ if (tvb_get_guint8(tvb, 44) != '\0') {
+ proto_tree_add_item(bp_tree, hf_bootp_server, tvb,
+ SERVER_NAME_OFFSET,
+ SERVER_NAME_LEN, FALSE);
+ }
+ else {
+ proto_tree_add_string_format(bp_tree, hf_bootp_server, tvb,
+ SERVER_NAME_OFFSET,
+ SERVER_NAME_LEN,
+ tvb_get_ptr(tvb, SERVER_NAME_OFFSET, 1),
+ "Server host name not given");
+ }
+
+ /* Boot file */
+ if (tvb_get_guint8(tvb, 108) != '\0') {
+ proto_tree_add_item(bp_tree, hf_bootp_file, tvb,
+ FILE_NAME_OFFSET,
+ FILE_NAME_LEN, FALSE);
+ }
+ else {
+ proto_tree_add_string_format(bp_tree, hf_bootp_file, tvb,
+ FILE_NAME_OFFSET,
+ FILE_NAME_LEN,
+ tvb_get_ptr(tvb, FILE_NAME_OFFSET, 1),
+ "Boot file name not given");
+ }
+ }
+
+ voff = VENDOR_INFO_OFFSET;
+
+ /* rfc2132 says it SHOULD exist, not that it MUST exist */
+ if (tvb_bytes_exist(tvb, voff, 4)) {
+ if (tvb_get_ntohl(tvb, voff) == 0x63825363) {
+ if (tree) {
+ tvb_memcpy(tvb, (void *)&ip_addr, voff, sizeof(ip_addr));
+ proto_tree_add_ipv4_format(bp_tree, hf_bootp_cookie, tvb,
+ voff, 4, ip_addr,
+ "Magic cookie: (OK)");
+ }
+ voff += 4;
+ }
+ else {
+ if (tree) {
+ proto_tree_add_text(bp_tree, tvb,
+ voff, 64, "Bootp vendor specific options");
+ }
+ voff += 64;
+ }
+ }
+
+ eoff = tvb_reported_length(tvb);
+
+ /*
+ * In the first pass, we just look for the DHCP message type
+ * and Vendor class identifier options.
+ */
+ tmpvoff = voff;
+ at_end = FALSE;
+ while (tmpvoff < eoff && !at_end) {
+ tmpvoff += bootp_option(tvb, 0, tmpvoff, eoff, TRUE, &at_end,
+ &dhcp_type, &vendor_class_id);
+ }
+
+ /*
+ * If there was a DHCP message type option, flag this packet
+ * as DHCP.
+ */
+ if (dhcp_type != NULL) {
+ /*
+ * Yes, this is a DHCP packet, and "dhcp_type" is the
+ * packet type.
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "DHCP %-8s - Transaction ID 0x%x",
+ dhcp_type, tvb_get_ntohl(tvb, 4));
+ if (tree)
+ proto_tree_add_boolean_hidden(bp_tree, hf_bootp_dhcp,
+ tvb, 0, 0, 1);
+ tap_queue_packet( bootp_dhcp_tap, pinfo, (gpointer) dhcp_type);
+ }
+
+ /*
+ * If we're not building the protocol tree, we don't need to
+ * make a second pass.
+ */
+ if (tree == NULL)
+ return;
+
+ /*
+ * OK, now build the protocol tree.
+ */
+ at_end = FALSE;
+ while (voff < eoff && !at_end) {
+ voff += bootp_option(tvb, bp_tree, voff, eoff, FALSE, &at_end,
+ &dhcp_type, &vendor_class_id);
+ }
+ if (voff < eoff) {
+ /*
+ * Padding after the end option.
+ */
+ proto_tree_add_text(bp_tree, tvb, voff, eoff - voff, "Padding");
+ }
+}
+
+void
+proto_register_bootp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bootp_dhcp,
+ { "Frame is DHCP", "bootp.dhcp", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_type,
+ { "Message type", "bootp.type", FT_UINT8,
+ BASE_DEC, VALS(op_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_hw_type,
+ { "Hardware type", "bootp.hw.type", FT_UINT8,
+ BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_hw_len,
+ { "Hardware address length", "bootp.hw.len", FT_UINT8,
+ BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_hops,
+ { "Hops", "bootp.hops", FT_UINT8,
+ BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_id,
+ { "Transaction ID", "bootp.id", FT_UINT32,
+ BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_secs,
+ { "Seconds elapsed", "bootp.secs", FT_UINT16,
+ BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_flags,
+ { "Bootp flags", "bootp.flags", FT_UINT16,
+ BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_flags_broadcast,
+ { "Broadcast flag", "bootp.flags.bc", FT_BOOLEAN,
+ 16, TFS(&flag_set_broadcast), BOOTP_BC,
+ "", HFILL }},
+
+ { &hf_bootp_flags_reserved,
+ { "Reserved flags", "bootp.flags.reserved", FT_UINT16,
+ BASE_HEX, NULL, BOOTP_MBZ,
+ "", HFILL }},
+
+ { &hf_bootp_ip_client,
+ { "Client IP address", "bootp.ip.client",FT_IPv4,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_ip_your,
+ { "Your (client) IP address", "bootp.ip.your", FT_IPv4,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_ip_server,
+ { "Next server IP address", "bootp.ip.server",FT_IPv4,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_ip_relay,
+ { "Relay agent IP address", "bootp.ip.relay", FT_IPv4,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_hw_addr,
+ { "Client hardware address", "bootp.hw.addr", FT_BYTES,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_server,
+ { "Server host name", "bootp.server", FT_STRING,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_file,
+ { "Boot file name", "bootp.file", FT_STRING,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_cookie,
+ { "Magic cookie", "bootp.cookie", FT_IPv4,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bootp_vendor,
+ { "Bootp Vendor Options", "bootp.vendor", FT_BYTES,
+ BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_bootp,
+ &ett_bootp_flags,
+ &ett_bootp_option,
+ };
+
+ module_t *bootp_module;
+
+ proto_bootp = proto_register_protocol("Bootstrap Protocol", "BOOTP/DHCP",
+ "bootp");
+ proto_register_field_array(proto_bootp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ bootp_dhcp_tap = register_tap("bootp");
+
+ bootp_module = prefs_register_protocol(proto_bootp, NULL);
+
+ prefs_register_bool_preference(bootp_module, "novellserverstring",
+ "Decode Option 85 as String",
+ "Novell Servers option 85 can be configured as a string instead of address",
+ &novell_string);
+}
+
+void
+proto_reg_handoff_bootp(void)
+{
+ dissector_handle_t bootp_handle;
+
+ bootp_handle = create_dissector_handle(dissect_bootp, proto_bootp);
+ dissector_add("udp.port", UDP_PORT_BOOTPS, bootp_handle);
+ dissector_add("udp.port", UDP_PORT_BOOTPC, bootp_handle);
+}
diff --git a/epan/dissectors/packet-bootparams.c b/epan/dissectors/packet-bootparams.c
new file mode 100644
index 0000000000..3634a82a11
--- /dev/null
+++ b/epan/dissectors/packet-bootparams.c
@@ -0,0 +1,201 @@
+/* packet-bootparams.c
+ * Routines for bootparams dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-smb.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+
+#include "packet-rpc.h"
+#include "packet-bootparams.h"
+
+static int proto_bootparams = -1;
+static int hf_bootparams_procedure_v1 = -1;
+static int hf_bootparams_host = -1;
+static int hf_bootparams_domain = -1;
+static int hf_bootparams_fileid = -1;
+static int hf_bootparams_filepath = -1;
+static int hf_bootparams_hostaddr = -1;
+static int hf_bootparams_routeraddr = -1;
+static int hf_bootparams_addresstype = -1;
+
+static gint ett_bootparams = -1;
+
+
+static const value_string addr_type[] =
+{
+ { 1, "IPv4-ADDR" },
+ { 0, NULL }
+};
+
+static int
+dissect_bp_address(tvbuff_t *tvb, int offset, proto_tree *tree, int hfindex)
+{
+ guint32 type;
+ guint32 ipaddr;
+
+
+ type = tvb_get_ntohl(tvb, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_bootparams_addresstype, offset);
+
+ switch(type){
+ case 1:
+ ipaddr = ((tvb_get_guint8(tvb, offset+3 )&0xff)<<24)
+ |((tvb_get_guint8(tvb, offset+7 )&0xff)<<16)
+ |((tvb_get_guint8(tvb, offset+11)&0xff)<<8 )
+ |((tvb_get_guint8(tvb, offset+15)&0xff) );
+ proto_tree_add_ipv4(tree, hfindex, tvb,
+ offset, 16, g_ntohl(ipaddr));
+ offset += 16;
+ break;
+
+ default:
+ break;
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_getfile_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ offset = dissect_rpc_string(tvb, tree, hf_bootparams_host, offset, NULL);
+ offset = dissect_rpc_string(tvb, tree, hf_bootparams_fileid, offset, NULL);
+ }
+
+ return offset;
+}
+
+static int
+dissect_getfile_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ offset = dissect_rpc_string(tvb, tree, hf_bootparams_host, offset, NULL);
+ offset = dissect_bp_address(tvb, offset, tree, hf_bootparams_hostaddr);
+ offset = dissect_rpc_string(tvb, tree, hf_bootparams_filepath, offset, NULL);
+ }
+
+ return offset;
+}
+
+static int
+dissect_whoami_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ offset = dissect_bp_address(tvb, offset, tree, hf_bootparams_hostaddr);
+ }
+
+ return offset;
+}
+
+static int
+dissect_whoami_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ offset = dissect_rpc_string(tvb, tree, hf_bootparams_host, offset, NULL);
+ offset = dissect_rpc_string(tvb, tree, hf_bootparams_domain, offset, NULL);
+ offset = dissect_bp_address(tvb, offset, tree, hf_bootparams_routeraddr);
+ }
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff bootparams1_proc[] = {
+ { BOOTPARAMSPROC_NULL, "NULL",
+ NULL, NULL },
+ { BOOTPARAMSPROC_WHOAMI, "WHOAMI",
+ dissect_whoami_call, dissect_whoami_reply },
+ { BOOTPARAMSPROC_GETFILE, "GETFILE",
+ dissect_getfile_call, dissect_getfile_reply },
+ { 0, NULL, NULL, NULL }
+};
+/* end of Bootparams version 1 */
+
+static const value_string bootparams1_proc_vals[] = {
+ { BOOTPARAMSPROC_NULL, "NULL" },
+ { BOOTPARAMSPROC_WHOAMI, "WHOAMI" },
+ { BOOTPARAMSPROC_GETFILE, "GETFILE" },
+ { 0, NULL }
+};
+
+void
+proto_register_bootparams(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bootparams_procedure_v1, {
+ "V1 Procedure", "bootparams.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(bootparams1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_bootparams_host, {
+ "Client Host", "bootparams.host", FT_STRING, BASE_DEC,
+ NULL, 0, "Client Host", HFILL }},
+ { &hf_bootparams_domain, {
+ "Client Domain", "bootparams.domain", FT_STRING, BASE_DEC,
+ NULL, 0, "Client Domain", HFILL }},
+ { &hf_bootparams_fileid, {
+ "File ID", "bootparams.fileid", FT_STRING, BASE_DEC,
+ NULL, 0, "File ID", HFILL }},
+ { &hf_bootparams_filepath, {
+ "File Path", "bootparams.filepath", FT_STRING, BASE_DEC,
+ NULL, 0, "File Path", HFILL }},
+ { &hf_bootparams_hostaddr, {
+ "Client Address", "bootparams.hostaddr", FT_IPv4, BASE_DEC,
+ NULL, 0, "Address", HFILL }},
+ { &hf_bootparams_routeraddr, {
+ "Router Address", "bootparams.routeraddr", FT_IPv4, BASE_DEC,
+ NULL, 0, "Router Address", HFILL }},
+ { &hf_bootparams_addresstype, {
+ "Address Type", "bootparams.type", FT_UINT32, BASE_DEC,
+ VALS(addr_type), 0, "Address Type", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_bootparams,
+ };
+
+ proto_bootparams = proto_register_protocol("Boot Parameters",
+ "BOOTPARAMS", "bootparams");
+ proto_register_field_array(proto_bootparams, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_bootparams(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_bootparams, BOOTPARAMS_PROGRAM, ett_bootparams);
+ /* Register the procedure tables */
+ rpc_init_proc_table(BOOTPARAMS_PROGRAM, 1, bootparams1_proc, hf_bootparams_procedure_v1);
+}
diff --git a/epan/dissectors/packet-bootparams.h b/epan/dissectors/packet-bootparams.h
new file mode 100644
index 0000000000..9601a6a6d1
--- /dev/null
+++ b/epan/dissectors/packet-bootparams.h
@@ -0,0 +1,13 @@
+/* packet-bootparams.h */
+/* $Id$ */
+
+#ifndef PACKET_BOOTPARAMS_H
+#define PACKET_BOOTPARAMS_H
+
+#define BOOTPARAMSPROC_NULL 0
+#define BOOTPARAMSPROC_WHOAMI 1
+#define BOOTPARAMSPROC_GETFILE 2
+
+#define BOOTPARAMS_PROGRAM 100026
+
+#endif
diff --git a/epan/dissectors/packet-bpdu.c b/epan/dissectors/packet-bpdu.c
new file mode 100644
index 0000000000..194b54d25f
--- /dev/null
+++ b/epan/dissectors/packet-bpdu.c
@@ -0,0 +1,828 @@
+/* packet-bpdu.c
+ * Routines for BPDU (Spanning Tree Protocol) disassembly
+ *
+ * $Id$
+ *
+ * Copyright 1999 Christophe Tronche <ch.tronche@computer.org>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "llcsaps.h"
+#include "ppptypes.h"
+#include "chdlctypes.h"
+#include <epan/resolv.h>
+
+/* Offsets of fields within a BPDU */
+
+#define BPDU_IDENTIFIER 0
+#define BPDU_VERSION_IDENTIFIER 2
+#define BPDU_TYPE 3
+#define BPDU_FLAGS 4
+#define BPDU_ROOT_IDENTIFIER 5
+#define BPDU_ROOT_PATH_COST 13
+#define BPDU_BRIDGE_IDENTIFIER 17
+#define BPDU_PORT_IDENTIFIER 25
+#define BPDU_MESSAGE_AGE 27
+#define BPDU_MAX_AGE 29
+#define BPDU_HELLO_TIME 31
+#define BPDU_FORWARD_DELAY 33
+#define BPDU_VERSION_1_LENGTH 35
+#define BPDU_VERSION_3_LENGTH 36
+#define BPDU_MST_CONFIG_FORMAT_SELECTOR 38
+#define BPDU_MST_CONFIG_NAME 39
+#define BPDU_MST_CONFIG_REVISION_LEVEL 71
+#define BPDU_MST_CONFIG_DIGEST 73
+#define BPDU_CIST_INTERNAL_ROOT_PATH_COST 89
+#define BPDU_CIST_BRIDGE_IDENTIFIER 93
+#define BPDU_CIST_REMAINING_HOPS 101
+#define BPDU_MSTI 102
+#define MSTI_FLAGS 0
+#define MSTI_REGIONAL_ROOT 1
+#define MSTI_INTERNAL_ROOT_PATH_COST 9
+#define MSTI_BRIDGE_IDENTIFIER_PRIORITY 13
+#define MSTI_PORT_IDENTIFIER_PRIORITY 14
+#define MSTI_REMAINING_HOPS 15
+
+#define CONF_BPDU_SIZE 35
+#define TC_BPDU_SIZE 4
+#define RST_BPDU_SIZE 36
+#define VERSION_3_STATIC_LENGTH 66
+#define MSTI_MESSAGE_SIZE 16
+
+/* Flag bits */
+
+#define BPDU_FLAGS_TCACK 0x80
+#define BPDU_FLAGS_AGREEMENT 0x40
+#define BPDU_FLAGS_FORWARDING 0x20
+#define BPDU_FLAGS_LEARNING 0x10
+#define BPDU_FLAGS_PORT_ROLE_MASK 0x0C
+#define BPDU_FLAGS_PORT_ROLE_SHIFT 2
+#define BPDU_FLAGS_PROPOSAL 0x02
+#define BPDU_FLAGS_TC 0x01
+
+static int proto_bpdu = -1;
+static int hf_bpdu_proto_id = -1;
+static int hf_bpdu_version_id = -1;
+static int hf_bpdu_type = -1;
+static int hf_bpdu_flags = -1;
+static int hf_bpdu_flags_tcack = -1;
+static int hf_bpdu_flags_agreement = -1;
+static int hf_bpdu_flags_forwarding = -1;
+static int hf_bpdu_flags_learning = -1;
+static int hf_bpdu_flags_port_role = -1;
+static int hf_bpdu_flags_proposal = -1;
+static int hf_bpdu_flags_tc = -1;
+static int hf_bpdu_root_mac = -1;
+static int hf_bpdu_root_cost = -1;
+static int hf_bpdu_bridge_mac = -1;
+static int hf_bpdu_port_id = -1;
+static int hf_bpdu_msg_age = -1;
+static int hf_bpdu_max_age = -1;
+static int hf_bpdu_hello_time = -1;
+static int hf_bpdu_forward_delay = -1;
+static int hf_bpdu_version_1_length = -1;
+static int hf_bpdu_version_3_length = -1;
+static int hf_bpdu_mst_config_format_selector = -1;
+static int hf_bpdu_mst_config_name = -1;
+static int hf_bpdu_mst_config_revision_level = -1;
+static int hf_bpdu_mst_config_digest = -1;
+static int hf_bpdu_cist_internal_root_path_cost = -1;
+static int hf_bpdu_cist_bridge_identifier_mac = -1;
+static int hf_bpdu_cist_remaining_hops = -1;
+static int hf_bpdu_msti_flags = -1;
+static int hf_bpdu_msti_regional_root_mac = -1;
+static int hf_bpdu_msti_internal_root_path_cost = -1;
+static int hf_bpdu_msti_bridge_identifier_priority = -1;
+static int hf_bpdu_msti_port_identifier_priority = -1;
+static int hf_bpdu_msti_remaining_hops = -1;
+
+static gint ett_bpdu = -1;
+static gint ett_bpdu_flags = -1;
+static gint ett_mstp = -1;
+static gint ett_msti = -1;
+
+static dissector_handle_t gvrp_handle;
+static dissector_handle_t gmrp_handle;
+static dissector_handle_t data_handle;
+
+static const value_string protocol_id_vals[] = {
+ { 0, "Spanning Tree Protocol" },
+ { 0, NULL }
+};
+
+#define BPDU_TYPE_CONF 0x00 /* STP Configuration BPDU */
+#define BPDU_TYPE_RST 0x02 /* RST BPDU (or MST) */
+#define BPDU_TYPE_TOPOLOGY_CHANGE 0x80 /* STP TCN (Topology change notify) BPDU */
+
+static const value_string bpdu_type_vals[] = {
+ { BPDU_TYPE_CONF, "Configuration" },
+ { BPDU_TYPE_RST, "Rapid/Multiple Spanning Tree" },
+ { BPDU_TYPE_TOPOLOGY_CHANGE, "Topology Change Notification" },
+ { 0, NULL }
+};
+
+#define PROTO_VERSION_STP 0
+#define PROTO_VERSION_RSTP 2
+#define PROTO_VERSION_MSTP 3
+
+static const value_string version_id_vals[] = {
+ { PROTO_VERSION_STP, "Spanning Tree" },
+ { PROTO_VERSION_RSTP, "Rapid Spanning Tree" },
+ { PROTO_VERSION_MSTP, "Multiple Spanning Tree" },
+ { 0, NULL}
+};
+static const value_string role_vals[] = {
+ { 1, "Alternate or Backup" },
+ { 2, "Root" },
+ { 3, "Designated" },
+ { 0, NULL }
+};
+
+static const char initial_sep[] = " (";
+static const char cont_sep[] = ", ";
+
+#define APPEND_BOOLEAN_FLAG(flag, item, string) \
+ if(flag){ \
+ if(item) \
+ proto_item_append_text(item, string, sep); \
+ sep = cont_sep; \
+ }
+
+static void
+dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 protocol_identifier;
+ guint8 protocol_version_identifier;
+ guint8 bpdu_type;
+ guint8 flags;
+ guint16 root_identifier_bridge_priority;
+ const guint8 *root_identifier_mac;
+ gchar *root_identifier_mac_str;
+ guint32 root_path_cost;
+ guint16 bridge_identifier_bridge_priority;
+ const guint8 *bridge_identifier_mac;
+ gchar *bridge_identifier_mac_str;
+ guint16 port_identifier;
+ double message_age;
+ double max_age;
+ double hello_time;
+ double forward_delay;
+ guint16 version_3_length;
+ guint32 cist_internal_root_path_cost;
+ guint8 mst_config_format_selector;
+ guint16 cist_bridge_identifier_bridge_priority;
+ const guint8 *cist_bridge_identifier_mac;
+ gchar *cist_bridge_identifier_mac_str;
+ const guint8 *mst_config_name;
+ guint16 mst_config_revision_level;
+ guint8 cist_remaining_hops, msti_remaining_hops;
+ guint32 msti_internal_root_path_cost;
+ guint32 msti_regional_root_mstid, msti_regional_root_priority;
+ const guint8 *msti_regional_root_mac;
+ gchar *msti_regional_root_mac_str;
+ guint8 msti_bridge_identifier_priority, msti_port_identifier_priority;
+ int length, offset, msti;
+
+ proto_tree *bpdu_tree;
+ proto_tree *mstp_tree, *msti_tree;
+ proto_item *bpdu_item;
+ proto_item *mstp_item, *msti_item;
+ proto_tree *flags_tree;
+ proto_item *flags_item;
+ guint8 rstp_bpdu, mstp_bpdu=0;
+ const char *sep;
+
+ /* GARP application frames require special interpretation of the
+ destination address field; otherwise, they will be mistaken as
+ BPDU frames.
+ Fortunately, they can be recognized by checking the first 6 octets
+ of the destination address, which are in the range from
+ 01-80-C2-00-00-20 to 01-80-C2-00-00-2F.
+
+ Yes - we *do* need to check the destination address type;
+ on Linux cooked captures, there *is* no destination address,
+ so it's AT_NONE. */
+ if (pinfo->dl_dst.type == AT_ETHER &&
+ pinfo->dl_dst.data[0] == 0x01 && pinfo->dl_dst.data[1] == 0x80 &&
+ pinfo->dl_dst.data[2] == 0xC2 && pinfo->dl_dst.data[3] == 0x00 &&
+ pinfo->dl_dst.data[4] == 0x00 && ((pinfo->dl_dst.data[5] & 0xF0) == 0x20)) {
+
+ protocol_identifier = tvb_get_ntohs(tvb, BPDU_IDENTIFIER);
+
+ switch (pinfo->dl_dst.data[5]) {
+
+ case 0x20:
+ /* for GMRP */
+ call_dissector(gmrp_handle, tvb, pinfo, tree);
+ return;
+
+ case 0x21:
+ /* for GVRP */
+ call_dissector(gvrp_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ pinfo->current_proto = "GARP";
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GARP");
+ /* Generic Attribute Registration Protocol */
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Unknown GARP application (0x%02X)",
+ pinfo->dl_dst.data[5]);
+ }
+
+ return;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "STP"); /* Spanning Tree Protocol */
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ bpdu_type = tvb_get_guint8(tvb, BPDU_TYPE);
+
+ protocol_version_identifier = tvb_get_guint8(tvb, BPDU_VERSION_IDENTIFIER);
+
+ switch (bpdu_type) {
+
+ case BPDU_TYPE_CONF:
+ case BPDU_TYPE_RST:
+ flags = tvb_get_guint8(tvb, BPDU_FLAGS);
+ root_identifier_bridge_priority = tvb_get_ntohs(tvb,BPDU_ROOT_IDENTIFIER);
+ root_identifier_mac = tvb_get_ptr(tvb, BPDU_ROOT_IDENTIFIER + 2, 6);
+ root_identifier_mac_str = ether_to_str(root_identifier_mac);
+ root_path_cost = tvb_get_ntohl(tvb, BPDU_ROOT_PATH_COST);
+ port_identifier = tvb_get_ntohs(tvb, BPDU_PORT_IDENTIFIER);
+ break;
+
+ default:
+ /* Squelch GCC complaints. */
+ flags = 0;
+ root_identifier_bridge_priority = 0;
+ root_identifier_mac = NULL;
+ root_identifier_mac_str = NULL;
+ root_path_cost = 0;
+ port_identifier = 0;
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ switch (bpdu_type) {
+
+ case BPDU_TYPE_CONF:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Conf. %sRoot = %d/%s Cost = %d Port = 0x%04x",
+ flags & 0x1 ? "TC + " : "",
+ root_identifier_bridge_priority, root_identifier_mac_str, root_path_cost,
+ port_identifier);
+ break;
+
+ case BPDU_TYPE_TOPOLOGY_CHANGE:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Topology Change Notification");
+ break;
+
+ case BPDU_TYPE_RST:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%cST. %sRoot = %d/%s Cost = %d Port = 0x%04x",
+ protocol_version_identifier == 3 ? 'M':'R',
+ flags & 0x1 ? "TC + " : "",
+ root_identifier_bridge_priority, root_identifier_mac_str, root_path_cost,
+ port_identifier);
+ break;
+
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown BPDU type (%u)",
+ bpdu_type);
+ break;
+ }
+ }
+
+ switch (bpdu_type) {
+
+ case BPDU_TYPE_CONF:
+ set_actual_length(tvb, CONF_BPDU_SIZE);
+ break;
+
+ case BPDU_TYPE_TOPOLOGY_CHANGE:
+ set_actual_length(tvb, TC_BPDU_SIZE);
+ break;
+
+ case BPDU_TYPE_RST:
+ if (protocol_version_identifier == 3) {
+ version_3_length = tvb_get_ntohs(tvb, BPDU_VERSION_3_LENGTH);
+ /*
+ * XXX - there appears to be an ambiguity in the 802.1s spec.
+ * In 14.6.q and Figure 14-1, the "Version 3 Length" field
+ * "is the number of octets taken by the parameters that
+ * follow in the BPDU", but item 14.4.e.3 speaks of "a
+ * Version 3 length representing an integral number, from 0
+ * to 64 inclusive, of MSTI Configuration Messages".
+ *
+ * According to mail from a member of the stds-802-1@ieee.org
+ * list, item 14.4.e.3 is just saying that the length must
+ * not have a value that implies that there's a partial
+ * MSTI message in the packet, and that it's in units of
+ * bytes, not messages.
+ *
+ * However, it appears that Cisco's C3550 software
+ * (C3550-I5Q3L2-M, Version 12.1(12c)EA1) might be sending out
+ * lengths in units of messages.
+ *
+ * So if the length is too short, we assume it's because it's
+ * in units of messages, not bytes.
+ */
+ if (version_3_length < VERSION_3_STATIC_LENGTH - 2) {
+ set_actual_length(tvb, RST_BPDU_SIZE +
+ VERSION_3_STATIC_LENGTH +
+ version_3_length * MSTI_MESSAGE_SIZE);
+ } else
+ set_actual_length(tvb, RST_BPDU_SIZE + 2 + version_3_length);
+ } else
+ set_actual_length(tvb, RST_BPDU_SIZE);
+ break;
+ }
+
+ if (tree) {
+ bpdu_item = proto_tree_add_protocol_format(tree, proto_bpdu, tvb,
+ 0, -1, "Spanning Tree Protocol");
+ bpdu_tree = proto_item_add_subtree(bpdu_item, ett_bpdu);
+
+ protocol_identifier = tvb_get_ntohs(tvb, BPDU_IDENTIFIER);
+ proto_tree_add_uint(bpdu_tree, hf_bpdu_proto_id, tvb,
+ BPDU_IDENTIFIER, 2, protocol_identifier);
+
+ proto_tree_add_uint(bpdu_tree, hf_bpdu_version_id, tvb,
+ BPDU_VERSION_IDENTIFIER, 1,
+ protocol_version_identifier);
+ switch (protocol_version_identifier) {
+ case 0:
+ break;
+ case 2:
+ case 3:
+ break;
+ default:
+ proto_tree_add_text(bpdu_tree, tvb, BPDU_VERSION_IDENTIFIER, 1,
+ " (Warning: this version of Ethereal only knows about versions 0, 2 & 3)");
+ break;
+ }
+ proto_tree_add_uint(bpdu_tree, hf_bpdu_type, tvb,
+ BPDU_TYPE, 1,
+ bpdu_type);
+
+ if (bpdu_type != BPDU_TYPE_CONF && bpdu_type != BPDU_TYPE_RST) {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, BPDU_TYPE + 1, -1, -1),
+ pinfo, tree);
+ return;
+ }
+
+ rstp_bpdu = (bpdu_type == BPDU_TYPE_RST);
+ if (rstp_bpdu) mstp_bpdu = (protocol_version_identifier == 3);
+
+ bridge_identifier_bridge_priority = tvb_get_ntohs(tvb, BPDU_BRIDGE_IDENTIFIER);
+ bridge_identifier_mac = tvb_get_ptr(tvb, BPDU_BRIDGE_IDENTIFIER + 2, 6);
+ bridge_identifier_mac_str = ether_to_str(bridge_identifier_mac);
+
+ flags_item = proto_tree_add_uint(bpdu_tree, hf_bpdu_flags, tvb,
+ BPDU_FLAGS, 1, flags);
+ flags_tree = proto_item_add_subtree(flags_item, ett_bpdu_flags);
+ sep = initial_sep;
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TCACK, flags_item,
+ "%sTopology Change Acknowledgment");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tcack, tvb,
+ BPDU_FLAGS, 1, flags);
+ if (rstp_bpdu) {
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_AGREEMENT, flags_item,
+ "%sAgreement");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_agreement, tvb,
+ BPDU_FLAGS, 1, flags);
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_FORWARDING, flags_item,
+ "%sForwarding");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_forwarding, tvb,
+ BPDU_FLAGS, 1, flags);
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_LEARNING, flags_item,
+ "%sLearning");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_learning, tvb,
+ BPDU_FLAGS, 1, flags);
+ if (flags_item) {
+ guint8 port_role;
+
+ port_role = (flags & BPDU_FLAGS_PORT_ROLE_MASK) >> BPDU_FLAGS_PORT_ROLE_SHIFT;
+ proto_item_append_text(flags_item, "%sPort Role: %s", sep,
+ val_to_str(port_role, role_vals,
+ "Unknown (%u)"));
+ }
+ sep = cont_sep;
+ proto_tree_add_uint(flags_tree, hf_bpdu_flags_port_role, tvb,
+ BPDU_FLAGS, 1, flags);
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_PROPOSAL, flags_item,
+ "%sProposal");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_proposal, tvb,
+ BPDU_FLAGS, 1, flags);
+ }
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TC, flags_item,
+ "%sTopology Change");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tc, tvb,
+ BPDU_FLAGS, 1, flags);
+ if (sep != initial_sep) {
+ /* We put something in; put in the terminating ")" */
+ proto_item_append_text(flags_item, ")");
+ }
+
+ proto_tree_add_ether_hidden(bpdu_tree, hf_bpdu_root_mac, tvb,
+ BPDU_ROOT_IDENTIFIER + 2, 6,
+ root_identifier_mac);
+ proto_tree_add_text(bpdu_tree, tvb,
+ BPDU_ROOT_IDENTIFIER, 8,
+ "Root Identifier: %d / %s",
+ root_identifier_bridge_priority,
+ root_identifier_mac_str);
+ proto_tree_add_uint(bpdu_tree, hf_bpdu_root_cost, tvb,
+ BPDU_ROOT_PATH_COST, 4,
+ root_path_cost);
+ proto_tree_add_text(bpdu_tree, tvb,
+ BPDU_BRIDGE_IDENTIFIER, 8,
+ "Bridge Identifier: %d / %s",
+ bridge_identifier_bridge_priority,
+ bridge_identifier_mac_str);
+ proto_tree_add_ether_hidden(bpdu_tree, hf_bpdu_bridge_mac, tvb,
+ BPDU_BRIDGE_IDENTIFIER + 2, 6,
+ bridge_identifier_mac);
+ proto_tree_add_uint(bpdu_tree, hf_bpdu_port_id, tvb,
+ BPDU_PORT_IDENTIFIER, 2,
+ port_identifier);
+ message_age = tvb_get_ntohs(tvb, BPDU_MESSAGE_AGE) / 256.0;
+ proto_tree_add_double(bpdu_tree, hf_bpdu_msg_age, tvb,
+ BPDU_MESSAGE_AGE, 2,
+ message_age);
+ max_age = tvb_get_ntohs(tvb, BPDU_MAX_AGE) / 256.0;
+ proto_tree_add_double(bpdu_tree, hf_bpdu_max_age, tvb,
+ BPDU_MAX_AGE, 2,
+ max_age);
+ hello_time = tvb_get_ntohs(tvb, BPDU_HELLO_TIME) / 256.0;
+ proto_tree_add_double(bpdu_tree, hf_bpdu_hello_time, tvb,
+ BPDU_HELLO_TIME, 2,
+ hello_time);
+ forward_delay = tvb_get_ntohs(tvb, BPDU_FORWARD_DELAY) / 256.0;
+ proto_tree_add_double(bpdu_tree, hf_bpdu_forward_delay, tvb,
+ BPDU_FORWARD_DELAY, 2,
+ forward_delay);
+ if (rstp_bpdu) {
+ proto_tree_add_item(bpdu_tree, hf_bpdu_version_1_length, tvb,
+ BPDU_VERSION_1_LENGTH, 1, FALSE);
+ }
+ if (mstp_bpdu) {
+ version_3_length = tvb_get_ntohs(tvb, BPDU_VERSION_3_LENGTH);
+
+ mstp_item = proto_tree_add_uint(bpdu_tree, hf_bpdu_version_3_length, tvb,
+ BPDU_VERSION_3_LENGTH, 2, version_3_length);
+ /*
+ * XXX - see comment above about the interpretation of the
+ * "Version 3 Length" field not being clear.
+ */
+ if (version_3_length < VERSION_3_STATIC_LENGTH - 2) {
+ proto_item_append_text(mstp_item,
+ " (Malformed: number of MSTI messages!!! Must be %u)",
+ (VERSION_3_STATIC_LENGTH - 2 + version_3_length * MSTI_MESSAGE_SIZE));
+ } else {
+ proto_item_append_text(mstp_item,
+ " (Number of MSTI messages: %u)",
+ (version_3_length - (VERSION_3_STATIC_LENGTH - 2)) / MSTI_MESSAGE_SIZE);
+ }
+ mstp_tree = proto_item_add_subtree(mstp_item, ett_mstp);
+
+ mst_config_format_selector = tvb_get_guint8(tvb, BPDU_MST_CONFIG_FORMAT_SELECTOR);
+ proto_tree_add_uint(mstp_tree, hf_bpdu_mst_config_format_selector, tvb,
+ BPDU_MST_CONFIG_FORMAT_SELECTOR, 1, mst_config_format_selector);
+ mst_config_name = tvb_get_ptr (tvb, BPDU_MST_CONFIG_NAME, 32);
+ proto_tree_add_string(mstp_tree, hf_bpdu_mst_config_name, tvb, BPDU_MST_CONFIG_NAME, 32, mst_config_name);
+
+ mst_config_revision_level = tvb_get_ntohs(tvb, BPDU_MST_CONFIG_REVISION_LEVEL);
+ proto_tree_add_uint(mstp_tree, hf_bpdu_mst_config_revision_level, tvb,
+ BPDU_MST_CONFIG_REVISION_LEVEL, 2, mst_config_revision_level);
+ proto_tree_add_bytes(mstp_tree, hf_bpdu_mst_config_digest, tvb,
+ BPDU_MST_CONFIG_DIGEST, 16, tvb_get_ptr(tvb, BPDU_MST_CONFIG_DIGEST, 16));
+
+ cist_internal_root_path_cost = tvb_get_ntohl(tvb, BPDU_CIST_INTERNAL_ROOT_PATH_COST);
+ proto_tree_add_uint(mstp_tree, hf_bpdu_cist_internal_root_path_cost, tvb,
+ BPDU_CIST_INTERNAL_ROOT_PATH_COST, 4, cist_internal_root_path_cost);
+
+ cist_bridge_identifier_bridge_priority = tvb_get_ntohs(tvb,BPDU_CIST_BRIDGE_IDENTIFIER);
+ cist_bridge_identifier_mac = tvb_get_ptr(tvb, BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6);
+ cist_bridge_identifier_mac_str = ether_to_str(cist_bridge_identifier_mac);
+ proto_tree_add_text(mstp_tree, tvb, BPDU_CIST_BRIDGE_IDENTIFIER, 8,
+ "CIST Bridge Identifier: %d / %s",
+ cist_bridge_identifier_bridge_priority,
+ cist_bridge_identifier_mac_str);
+ proto_tree_add_ether_hidden(mstp_tree, hf_bpdu_cist_bridge_identifier_mac, tvb,
+ BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6,
+ cist_bridge_identifier_mac);
+
+ cist_remaining_hops = tvb_get_guint8(tvb, BPDU_CIST_REMAINING_HOPS);
+ proto_tree_add_uint(mstp_tree, hf_bpdu_cist_remaining_hops, tvb,
+ BPDU_CIST_REMAINING_HOPS, 1, cist_remaining_hops);
+
+ /* MSTI messages */
+ offset = BPDU_MSTI;
+ length = tvb_reported_length_remaining(tvb, offset);
+ msti = 1;
+ while (length >= MSTI_MESSAGE_SIZE) {
+ msti_regional_root_mstid = tvb_get_guint8(tvb, offset+ MSTI_REGIONAL_ROOT);
+ msti_regional_root_priority = (msti_regional_root_mstid &0xf0) << 8;
+ msti_regional_root_mstid = ((msti_regional_root_mstid & 0x0f) << 8) +
+ tvb_get_guint8(tvb, offset+ MSTI_REGIONAL_ROOT+1);
+ msti_regional_root_mac = tvb_get_ptr(tvb, offset+ MSTI_REGIONAL_ROOT + 2, 6);
+ msti_regional_root_mac_str = ether_to_str(msti_regional_root_mac);
+
+ msti_item = proto_tree_add_text(mstp_tree, tvb, offset, 16,
+ "MSTID %d, Regional Root Identifier %d / %s",
+ msti_regional_root_mstid, msti_regional_root_priority,
+ msti_regional_root_mac_str);
+ msti_tree = proto_item_add_subtree(msti_item, ett_msti);
+
+ /* flags */
+ flags = tvb_get_guint8(tvb, offset+MSTI_FLAGS);
+ flags_item = proto_tree_add_uint(msti_tree, hf_bpdu_msti_flags, tvb,
+ offset+MSTI_FLAGS, 1, flags);
+ flags_tree = proto_item_add_subtree(flags_item, ett_bpdu_flags);
+
+ sep = initial_sep;
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TCACK, flags_item, "%sMaster");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tcack, tvb,
+ offset+MSTI_FLAGS, 1, flags);
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_AGREEMENT, flags_item, "%sAgreement");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_agreement, tvb,
+ offset+MSTI_FLAGS, 1, flags);
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_FORWARDING, flags_item, "%sForwarding");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_forwarding, tvb,
+ offset+MSTI_FLAGS, 1, flags);
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_LEARNING, flags_item, "%sLearning");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_learning, tvb,
+ offset+MSTI_FLAGS, 1, flags);
+ if (flags_item) {
+ guint8 port_role;
+ port_role = (flags & BPDU_FLAGS_PORT_ROLE_MASK) >> BPDU_FLAGS_PORT_ROLE_SHIFT;
+ proto_item_append_text(flags_item, "%sPort Role: %s", sep,
+ val_to_str(port_role, role_vals, "Unknown (%u)"));
+ }
+ proto_tree_add_uint(flags_tree, hf_bpdu_flags_port_role, tvb,
+ offset+MSTI_FLAGS, 1, flags);
+ sep = cont_sep;
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_PROPOSAL, flags_item, "%sProposal");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_proposal, tvb,
+ offset+MSTI_FLAGS, 1, flags);
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TC, flags_item, "%sTopology Change");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tc, tvb,
+ offset+MSTI_FLAGS, 1, flags);
+ if (sep != initial_sep) { /* We put something in; put in the terminating ")" */
+ proto_item_append_text(flags_item, ")");
+ }
+
+ /* pri, MSTID, Regional root */
+ proto_tree_add_ether_hidden(msti_tree, hf_bpdu_msti_regional_root_mac, tvb,
+ offset + MSTI_REGIONAL_ROOT + 2, 6,
+ msti_regional_root_mac);
+ proto_tree_add_text(msti_tree, tvb, offset + MSTI_REGIONAL_ROOT, 8,
+ "MSTID %d, priority %d Root Identifier %s",
+ msti_regional_root_mstid, msti_regional_root_priority,
+ msti_regional_root_mac_str);
+
+
+ msti_internal_root_path_cost = tvb_get_ntohs(tvb, offset+MSTI_INTERNAL_ROOT_PATH_COST);
+ proto_tree_add_uint(msti_tree, hf_bpdu_msti_internal_root_path_cost, tvb,
+ offset+MSTI_INTERNAL_ROOT_PATH_COST, 4, msti_internal_root_path_cost);
+
+ msti_bridge_identifier_priority = tvb_get_guint8(tvb, offset+MSTI_BRIDGE_IDENTIFIER_PRIORITY) >> 4;
+ msti_port_identifier_priority = tvb_get_guint8(tvb, offset+MSTI_PORT_IDENTIFIER_PRIORITY) >> 4;
+
+ proto_tree_add_uint(msti_tree, hf_bpdu_msti_bridge_identifier_priority, tvb,
+ offset+MSTI_BRIDGE_IDENTIFIER_PRIORITY, 1, msti_bridge_identifier_priority);
+ proto_tree_add_uint(msti_tree, hf_bpdu_msti_port_identifier_priority, tvb,
+ offset+MSTI_PORT_IDENTIFIER_PRIORITY, 1, msti_port_identifier_priority);
+
+ msti_remaining_hops = tvb_get_guint8(tvb, offset+MSTI_REMAINING_HOPS);
+ proto_tree_add_uint(msti_tree, hf_bpdu_msti_remaining_hops, tvb,
+ offset + MSTI_REMAINING_HOPS, 1, msti_remaining_hops);
+
+ length -= MSTI_MESSAGE_SIZE;
+ offset += MSTI_MESSAGE_SIZE;
+ msti++;
+ }
+
+ }
+ }
+}
+
+static const true_false_string yesno = {
+ "Yes",
+ "No"
+};
+
+void
+proto_register_bpdu(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_bpdu_proto_id,
+ { "Protocol Identifier", "stp.protocol",
+ FT_UINT16, BASE_HEX, VALS(&protocol_id_vals), 0x0,
+ "", HFILL }},
+ { &hf_bpdu_version_id,
+ { "Protocol Version Identifier", "stp.version",
+ FT_UINT8, BASE_DEC, VALS(&version_id_vals), 0x0,
+ "", HFILL }},
+ { &hf_bpdu_type,
+ { "BPDU Type", "stp.type",
+ FT_UINT8, BASE_HEX, VALS(&bpdu_type_vals), 0x0,
+ "", HFILL }},
+ { &hf_bpdu_flags,
+ { "BPDU flags", "stp.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_flags_tcack,
+ { "Topology Change Acknowledgment", "stp.flags.tcack",
+ FT_BOOLEAN, 8, TFS(&yesno), BPDU_FLAGS_TCACK,
+ "", HFILL }},
+ { &hf_bpdu_flags_agreement,
+ { "Agreement", "stp.flags.agreement",
+ FT_BOOLEAN, 8, TFS(&yesno), BPDU_FLAGS_AGREEMENT,
+ "", HFILL }},
+ { &hf_bpdu_flags_forwarding,
+ { "Forwarding", "stp.flags.forwarding",
+ FT_BOOLEAN, 8, TFS(&yesno), BPDU_FLAGS_FORWARDING,
+ "", HFILL }},
+ { &hf_bpdu_flags_learning,
+ { "Learning", "stp.flags.learning",
+ FT_BOOLEAN, 8, TFS(&yesno), BPDU_FLAGS_LEARNING,
+ "", HFILL }},
+ { &hf_bpdu_flags_port_role,
+ { "Port Role", "stp.flags.port_role",
+ FT_UINT8, BASE_DEC, VALS(role_vals), BPDU_FLAGS_PORT_ROLE_MASK,
+ "", HFILL }},
+ { &hf_bpdu_flags_proposal,
+ { "Proposal", "stp.flags.proposal",
+ FT_BOOLEAN, 8, TFS(&yesno), BPDU_FLAGS_PROPOSAL,
+ "", HFILL }},
+ { &hf_bpdu_flags_tc,
+ { "Topology Change", "stp.flags.tc",
+ FT_BOOLEAN, 8, TFS(&yesno), BPDU_FLAGS_TC,
+ "", HFILL }},
+ { &hf_bpdu_root_mac,
+ { "Root Identifier", "stp.root.hw",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_root_cost,
+ { "Root Path Cost", "stp.root.cost",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_bridge_mac,
+ { "Bridge Identifier", "stp.bridge.hw",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_port_id,
+ { "Port identifier", "stp.port",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_msg_age,
+ { "Message Age", "stp.msg_age",
+ FT_DOUBLE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_max_age,
+ { "Max Age", "stp.max_age",
+ FT_DOUBLE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_hello_time,
+ { "Hello Time", "stp.hello",
+ FT_DOUBLE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_forward_delay,
+ { "Forward Delay", "stp.forward",
+ FT_DOUBLE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_version_1_length,
+ { "Version 1 Length", "stp.version_1_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_version_3_length,
+ { "MST Extension, Length", "mstp.version_3_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_mst_config_format_selector,
+ { "MST Config ID format selector", "mstp.config_format_selector",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_mst_config_name,
+ { "MST Config name", "mstp.config_name",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_mst_config_revision_level,
+ { "MST Config revision", "mstp.config_revision_level",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_mst_config_digest,
+ { "MST Config digest", "mstp.config_digest",
+ FT_BYTES, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_cist_internal_root_path_cost,
+ { "CIST Internal Root Path Cost", "mstp.cist_internal_root_path_cost",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_cist_bridge_identifier_mac,
+ { "CIST Bridge Identifier", "mstp.cist_bridge.hw",
+ FT_ETHER, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_cist_remaining_hops,
+ { "CIST Remaining hops", "mstp.cist_remaining_hops",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_msti_flags,
+ { "MSTI flags", "mstp.msti.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_msti_regional_root_mac,
+ { "Regional Root", "mstp.msti.root.hw",
+ FT_ETHER, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_msti_internal_root_path_cost,
+ { "Internal root path cost", "mstp.msti.root_cost",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_msti_bridge_identifier_priority,
+ { "Bridge Identifier Priority", "mstp.msti.bridge_priority",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_msti_port_identifier_priority,
+ { "Port identifier prority", "mstp.msti.port_priority",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_bpdu_msti_remaining_hops,
+ { "Remaining hops", "mstp.msti.remaining_hops",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_bpdu,
+ &ett_bpdu_flags,
+ &ett_mstp,
+ &ett_msti
+ };
+
+ proto_bpdu = proto_register_protocol("Spanning Tree Protocol", "STP", "stp");
+ proto_register_field_array(proto_bpdu, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("bpdu", dissect_bpdu, proto_bpdu);
+}
+
+void
+proto_reg_handoff_bpdu(void)
+{
+ dissector_handle_t bpdu_handle;
+
+ /*
+ * Get handle for the GVRP dissector.
+ */
+ gvrp_handle = find_dissector("gvrp");
+
+ /*
+ * Get handle for the GMRP dissector.
+ */
+ gmrp_handle = find_dissector("gmrp");
+ data_handle = find_dissector("data");
+
+ bpdu_handle = find_dissector("bpdu");
+ dissector_add("llc.dsap", SAP_BPDU, bpdu_handle);
+ dissector_add("ppp.protocol", PPP_BPDU, bpdu_handle);
+ dissector_add("chdlctype", CHDLCTYPE_BPDU, bpdu_handle);
+ dissector_add("llc.cisco_pid", 0x010b, bpdu_handle);
+}
diff --git a/epan/dissectors/packet-brdwlk.c b/epan/dissectors/packet-brdwlk.c
new file mode 100644
index 0000000000..1fce4130d8
--- /dev/null
+++ b/epan/dissectors/packet-brdwlk.c
@@ -0,0 +1,404 @@
+/* packet-brdwlk.c
+ * Routines for decoding MDS Port Analyzer Adapter (FC in Eth) Header
+ * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "etypes.h"
+
+#define BRDWLK_MAX_PACKET_CNT 0xFFFF
+#define BRDWLK_TRUNCATED_BIT 0x8
+#define BRDWLK_HAS_PLEN 0x1
+
+#define FCM_DELIM_SOFC1 0x01
+#define FCM_DELIM_SOFI1 0x02
+#define FCM_DELIM_SOFI2 0x04
+#define FCM_DELIM_SOFI3 0x06
+#define FCM_DELIM_SOFN1 0x03
+#define FCM_DELIM_SOFN2 0x05
+#define FCM_DELIM_SOFN3 0x07
+#define FCM_DELIM_SOFF 0x08
+#define FCM_DELIM_SOFC4 0x09
+#define FCM_DELIM_SOFI4 0x0A
+#define FCM_DELIM_SOFN4 0x0B
+
+#define FCM_DELIM_EOFT 0x01
+#define FCM_DELIM_EOFDT 0x02
+#define FCM_DELIM_EOFN 0x03
+#define FCM_DELIM_EOFA 0x04
+#define FCM_DELIM_EOFNI 0x07
+#define FCM_DELIM_EOFDTI 0x06
+#define FCM_DELIM_EOFRT 0x0A
+#define FCM_DELIM_EOFRTI 0x0E
+#define FCM_DELIM_NOEOF 0xF0
+#define FCM_DELIM_EOFJUMBO 0xF1
+
+static const value_string brdwlk_sof_vals[] = {
+ {FCM_DELIM_SOFI1, "SOFi1"},
+ {FCM_DELIM_SOFI2, "SOFi2"},
+ {FCM_DELIM_SOFI3, "SOFi3"},
+ {FCM_DELIM_SOFN1, "SOFn1"},
+ {FCM_DELIM_SOFN2, "SOFn2"},
+ {FCM_DELIM_SOFN3, "SOFn3"},
+ {FCM_DELIM_SOFF, "SOFf"},
+ {0, NULL},
+};
+
+static const value_string brdwlk_eof_vals[] = {
+ {FCM_DELIM_EOFDT, "EOFdt"},
+ {FCM_DELIM_EOFA, "EOFa"},
+ {FCM_DELIM_EOFN, "EOFn"},
+ {FCM_DELIM_EOFT, "EOFt"},
+ {0, NULL},
+};
+
+static int hf_brdwlk_sof = -1;
+static int hf_brdwlk_eof = -1;
+static int hf_brdwlk_error = -1;
+static int hf_brdwlk_vsan = -1;
+static int hf_brdwlk_pktcnt = -1;
+static int hf_brdwlk_drop = -1;
+static int hf_brdwlk_plen = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_brdwlk = -1;
+
+static gint proto_brdwlk = -1;
+
+static guint16 packet_count = 0;
+static gboolean first_pkt = TRUE; /* start of capture */
+
+static dissector_handle_t data_handle;
+static dissector_handle_t fc_dissector_handle;
+
+static gchar *
+brdwlk_err_to_str (guint8 error, char *str)
+{
+ if (str != NULL) {
+ str[0] = '\0';
+
+ if (error & 0x1) {
+ strcat (str, "Packet Length Present");
+ }
+
+ if (error & 0x2) {
+ strcat (str, "Empty Frame, ");
+ }
+
+ if (error & 0x4) {
+ strcat (str, "No Data, ");
+ }
+
+ if (error & 0x8) {
+ strcat (str, "Truncated, ");
+ }
+
+ if (error & 0x10) {
+ strcat (str, "Bad FC CRC, ");
+ }
+
+ if (error & 0x20) {
+ strcat (str, "Fifo Full, ");
+ }
+
+ if (error & 0x40) {
+ strcat (str, "Jumbo FC Frame, ");
+ }
+
+ if (error & 0x80) {
+ strcat (str, "Ctrl Char Inside Frame");
+ }
+ }
+
+ return (str);
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_brdwlk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *brdwlk_tree = NULL;
+ tvbuff_t *next_tvb;
+ guint8 error, eof, sof;
+ int hdrlen = 2,
+ offset = 0;
+ gint len, reported_len, plen;
+ guint16 pkt_cnt;
+ gboolean dropped_packets;
+ gchar errstr[512];
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Boardwalk");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ pinfo->vsan = (tvb_get_ntohs (tvb, offset) & 0xFFF);
+ sof = (tvb_get_guint8 (tvb, offset) & 0xF0) >> 4;
+
+ if ((sof == FCM_DELIM_SOFI3) || (sof == FCM_DELIM_SOFI2) || (sof == FCM_DELIM_SOFI1)
+ || (sof == FCM_DELIM_SOFI4)) {
+ pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
+ }
+ else if (sof == FCM_DELIM_SOFF) {
+ pinfo->sof_eof = PINFO_SOF_SOFF;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_brdwlk, tvb, 0,
+ hdrlen, "Boardwalk");
+
+ brdwlk_tree = proto_item_add_subtree (ti, ett_brdwlk);
+
+ proto_tree_add_item (brdwlk_tree, hf_brdwlk_sof, tvb, offset, 1, 0);
+ proto_tree_add_item (brdwlk_tree, hf_brdwlk_vsan, tvb, offset, 2, 0);
+
+ }
+
+ /* Locate EOF which is the last 4 bytes of the frame */
+ len = tvb_length_remaining(tvb, hdrlen);
+ reported_len = tvb_reported_length_remaining(tvb, hdrlen);
+ if (reported_len < 4) {
+ /*
+ * This packet is claimed not to even have enough data for
+ * a 4-byte EOF.
+ * Don't try to process the EOF.
+ */
+ ;
+ }
+ else if (len < reported_len) {
+ /*
+ * This packet is claimed to have enough data for a 4-byte EOF,
+ * but we didn't capture all of the packet.
+ * Slice off the 4-byte EOF from the reported length, and trim
+ * the captured length so it's no more than the reported length;
+ * that will slice off what of the EOF, if any, is in the
+ * captured length.
+ */
+ reported_len -= 4;
+ if (len > reported_len)
+ len = reported_len;
+ }
+ else {
+ /*
+ * We have the entire packet, and it includes a 4-byte EOF.
+ * Slice it off, and put it into the tree if we're building
+ * a tree.
+ */
+ len -= 4;
+ reported_len -= 4;
+ offset = tvb_reported_length(tvb) - 4;
+ pkt_cnt = tvb_get_ntohs (tvb, offset);
+ if (tree) {
+ proto_tree_add_uint (brdwlk_tree, hf_brdwlk_pktcnt, tvb, offset,
+ 2, pkt_cnt);
+ }
+ dropped_packets = FALSE;
+ if (pinfo->fd->flags.visited) {
+ /*
+ * This isn't the first pass, so we can't use the global
+ * "packet_count" variable to determine whether there were
+ * any dropped frames or not.
+ * We therefore attach a non-null pointer as frame data to
+ * any frame preceded by dropped packets.
+ */
+ if (p_get_proto_data(pinfo->fd, proto_brdwlk) != NULL)
+ dropped_packets = TRUE;
+ } else {
+ /*
+ * This is the first pass, so we have to use the global
+ * "packet_count" variable to determine whether there were
+ * any dropped frames or not.
+ *
+ * XXX - can there be more than one stream of packets, so that
+ * we can't just use a global variable?
+ */
+ if (pkt_cnt != packet_count + 1) {
+ if (!first_pkt &&
+ (pkt_cnt != 0 || (packet_count != BRDWLK_MAX_PACKET_CNT))) {
+ dropped_packets = TRUE;
+
+ /*
+ * Mark this frame as having been preceded by dropped
+ * packets. (The data we use as the frame data doesn't
+ * matter - it just matters that it's non-null.)
+ */
+ p_add_proto_data(pinfo->fd, proto_brdwlk, &packet_count);
+ }
+ }
+
+ if (tree) {
+ proto_tree_add_boolean_hidden (brdwlk_tree, hf_brdwlk_drop,
+ tvb, offset, 0, dropped_packets);
+ }
+ }
+ packet_count = pkt_cnt;
+
+ error = tvb_get_guint8 (tvb, offset+2);
+ if (tree) {
+ proto_tree_add_uint_format (brdwlk_tree, hf_brdwlk_error, tvb,
+ offset+2, 1, error, "Error: 0x%x (%s)",
+ error,
+ brdwlk_err_to_str (error, errstr));
+ }
+
+ eof = tvb_get_guint8 (tvb, offset+3);
+ if (eof != FCM_DELIM_EOFN) {
+ pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
+ }
+ else if (eof != FCM_DELIM_EOFT) {
+ pinfo->sof_eof |= PINFO_EOF_INVALID;
+ }
+
+ if (tree) {
+ proto_tree_add_item (brdwlk_tree, hf_brdwlk_eof, tvb, offset+3,
+ 1, 0);
+ }
+
+ if ((error & BRDWLK_HAS_PLEN) && tree) {
+ /* In newer Boardwalks, if this bit is set, the actual frame length
+ * is also provided. This length is the size between SOF & EOF
+ * including FC CRC.
+ */
+ plen = tvb_get_ntohl (tvb, offset-4);
+ plen *= 4;
+ proto_tree_add_uint (brdwlk_tree, hf_brdwlk_plen, tvb, offset-4,
+ 4, plen);
+
+#if 0
+ /* XXX - this would throw an exception if it would increase
+ * the reported length.
+ */
+ if (error & BRDWLK_TRUNCATED_BIT) {
+ tvb_set_reported_length (tvb, plen);
+ }
+#endif
+ }
+ }
+
+ next_tvb = tvb_new_subset (tvb, 2, len, reported_len);
+ if (fc_dissector_handle) {
+ call_dissector (fc_dissector_handle, next_tvb, pinfo, tree);
+ }
+}
+
+static void
+brdwlk_init(void)
+{
+ packet_count = 0;
+ first_pkt = TRUE;
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_brdwlk (void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_brdwlk_sof,
+ {"SOF", "brdwlk.sof", FT_UINT8, BASE_HEX, VALS (brdwlk_sof_vals),
+ 0xF0, "SOF", HFILL}},
+ { &hf_brdwlk_eof,
+ {"EOF", "brdwlk.eof", FT_UINT8, BASE_HEX, VALS (brdwlk_eof_vals),
+ 0x0F, "EOF", HFILL}},
+ { &hf_brdwlk_error,
+ {"Error", "brdwlk.error", FT_UINT8, BASE_DEC, NULL, 0x0, "Error",
+ HFILL}},
+ { &hf_brdwlk_pktcnt,
+ {"Packet Count", "brdwlk.pktcnt", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_brdwlk_drop,
+ {"Packet Dropped", "brdwlk.drop", FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_brdwlk_vsan,
+ {"VSAN", "brdwlk.vsan", FT_UINT16, BASE_DEC, NULL, 0xFFF, "",
+ HFILL}},
+ { &hf_brdwlk_plen,
+ {"Original Packet Length", "brdwlk.plen", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_brdwlk,
+ };
+
+/* Register the protocol name and description */
+ proto_brdwlk = proto_register_protocol("Boardwalk",
+ "Boardwalk", "brdwlk");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_brdwlk, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine(&brdwlk_init);
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_brdwlk(void)
+{
+ dissector_handle_t brdwlk_handle;
+
+ brdwlk_handle = create_dissector_handle (dissect_brdwlk, proto_brdwlk);
+ dissector_add("ethertype", ETHERTYPE_BRDWALK, brdwlk_handle);
+ dissector_add("ethertype", 0xABCD, brdwlk_handle);
+ data_handle = find_dissector("data");
+ fc_dissector_handle = find_dissector ("fc");
+}
diff --git a/epan/dissectors/packet-bssap.c b/epan/dissectors/packet-bssap.c
new file mode 100644
index 0000000000..c422677a99
--- /dev/null
+++ b/epan/dissectors/packet-bssap.c
@@ -0,0 +1,480 @@
+/* packet-bssap.c
+ * Routines for Base Station Subsystem Application Part (BSSAP/BSAP) dissection
+ * Specifications from 3GPP2 (www.3gpp2.org) and 3GPP (www.3gpp.org)
+ * IOS 4.0.1 (BSAP)
+ * GSM 08.06 (BSSAP)
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gmodule.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <string.h>
+
+#include "epan/packet.h"
+#include "prefs.h"
+#include "packet-bssap.h"
+
+#define BSSAP 0
+#define BSAP 1
+
+#define BSSAP_OR_BSAP_DEFAULT BSSAP
+
+#define PDU_TYPE_OFFSET 0
+#define PDU_TYPE_LENGTH 1
+
+/* Same as below but with names typed out */
+static const value_string bssap_pdu_type_values[] = {
+ { BSSAP_PDU_TYPE_BSSMAP, "BSS Management" },
+ { BSSAP_PDU_TYPE_DTAP, "Direct Transfer" },
+ { 0, NULL } };
+
+static const value_string bsap_pdu_type_values[] = {
+ { BSSAP_PDU_TYPE_BSSMAP, "BS Management" },
+ { BSSAP_PDU_TYPE_DTAP, "Direct Transfer" },
+ { 0, NULL } };
+
+/* Same as above but in acronym for (for the Info column) */
+static const value_string bssap_pdu_type_acro_values[] = {
+ { BSSAP_PDU_TYPE_BSSMAP, "BSSMAP" },
+ { BSSAP_PDU_TYPE_DTAP, "DTAP" },
+ { 0, NULL } };
+
+/* Same as above but in acronym for (for the Info column) */
+static const value_string bsap_pdu_type_acro_values[] = {
+ { BSSAP_PDU_TYPE_BSSMAP, "BSMAP" },
+ { BSSAP_PDU_TYPE_DTAP, "DTAP" },
+ { 0, NULL } };
+
+#define PARAMETER_DLCI 0x00
+#define PARAMETER_LENGTH 0x01
+#define PARAMETER_DATA 0x02
+
+#define DLCI_LENGTH 1
+#define LENGTH_LENGTH 1
+#define DATA_LENGTH 1
+
+#define CC_MASK 0xc0
+#define SPARE_MASK 0x38
+#define SAPI_MASK 0x07
+
+static const value_string bssap_cc_values[] = {
+ { 0x00, "not further specified" },
+ { 0x80, "FACCH or SDCCH" },
+ { 0xc0, "SACCH" },
+ { 0, NULL } };
+
+static const value_string bsap_cc_values[] = {
+ { 0x00, "default for TIA/EIA/IS-2000" },
+ { 0, NULL } };
+
+static const value_string bssap_sapi_values[] = {
+ { 0x00, "RR/MM/CC" },
+ { 0x03, "SMS" },
+ { 0, NULL } };
+
+static const value_string bsap_sapi_values[] = {
+ { 0x00, "Not used" },
+ { 0, NULL } };
+
+
+/* Initialize the protocol and registered fields */
+static int proto_bssap = -1;
+static int hf_bssap_pdu_type = -1;
+static int hf_bsap_pdu_type = -1;
+static int hf_bssap_dlci_cc = -1;
+static int hf_bsap_dlci_cc = -1;
+static int hf_bssap_dlci_spare = -1;
+static int hf_bsap_dlci_rsvd = -1;
+static int hf_bssap_dlci_sapi = -1;
+static int hf_bsap_dlci_sapi = -1;
+static int hf_bssap_length = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_bssap = -1;
+static gint ett_bssap_dlci = -1;
+
+static dissector_handle_t data_handle;
+
+static dissector_table_t bssap_dissector_table;
+static dissector_table_t bsap_dissector_table;
+
+/*
+ * Keep track of pdu_type so we can call appropriate sub-dissector
+ */
+static guint8 pdu_type = 0xFF;
+
+static guint bssap_or_bsap_global = BSSAP_OR_BSAP_DEFAULT;
+
+
+static void
+dissect_bssap_unknown_message(tvbuff_t *message_tvb, proto_tree *bssap_tree)
+{
+ guint32 message_length;
+
+ message_length = tvb_length(message_tvb);
+
+ proto_tree_add_text(bssap_tree, message_tvb, 0, message_length,
+ "Unknown message (%u byte%s)",
+ message_length, plurality(message_length, "", "s"));
+}
+
+static void
+dissect_bssap_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint16 length)
+{
+ proto_tree_add_text(tree, tvb, 0, length,
+ "Unknown parameter 0x%x (%u byte%s)",
+ type, length, plurality(length, "", "s"));
+}
+
+static void
+dissect_bssap_data_param(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *bssap_tree, proto_tree *tree)
+{
+ if ((pdu_type <= 0x01))
+ {
+ if (bssap_or_bsap_global == BSSAP)
+ {
+ /* BSSAP */
+ if (dissector_try_port(bssap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
+ }
+ else
+ {
+ /* BSAP */
+ if (dissector_try_port(bsap_dissector_table, pdu_type, tvb, pinfo, tree)) return;
+ }
+ }
+
+ /* No sub-dissection occured, treat it as raw data */
+ call_dissector(data_handle, tvb, pinfo, bssap_tree);
+}
+
+static void
+dissect_bssap_dlci_param(tvbuff_t *tvb, proto_tree *tree, guint16 length)
+{
+ proto_item *dlci_item = 0;
+ proto_tree *dlci_tree = 0;
+ guint8 oct;
+
+ dlci_item =
+ proto_tree_add_text(tree, tvb, 0, length,
+ "Data Link Connection Identifier");
+
+ dlci_tree = proto_item_add_subtree(dlci_item, ett_bssap_dlci);
+
+ oct = tvb_get_guint8(tvb, 0);
+
+ if (bssap_or_bsap_global == BSSAP)
+ {
+ proto_tree_add_uint(dlci_tree, hf_bssap_dlci_cc, tvb, 0, length, oct);
+ proto_tree_add_uint(dlci_tree, hf_bssap_dlci_spare, tvb, 0, length, oct);
+ proto_tree_add_uint(dlci_tree, hf_bssap_dlci_sapi, tvb, 0, length, oct);
+ }
+ else
+ {
+ proto_tree_add_uint(dlci_tree, hf_bsap_dlci_cc, tvb, 0, length, oct);
+ proto_tree_add_uint(dlci_tree, hf_bsap_dlci_rsvd, tvb, 0, length, oct);
+ proto_tree_add_uint(dlci_tree, hf_bsap_dlci_sapi, tvb, 0, length, oct);
+ }
+}
+
+static void
+dissect_bssap_length_param(tvbuff_t *tvb, proto_tree *tree, guint16 length)
+{
+ guint8 data_length;
+
+ data_length = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(tree, hf_bssap_length, tvb, 0, length, data_length);
+}
+
+/*
+ * Dissect a parameter given its type, offset into tvb, and length.
+ */
+static guint16
+dissect_bssap_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
+ proto_tree *tree, guint8 parameter_type, gint offset,
+ guint16 parameter_length)
+{
+ tvbuff_t *parameter_tvb;
+
+ parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
+
+ switch (parameter_type)
+ {
+ case PARAMETER_DLCI:
+ dissect_bssap_dlci_param(parameter_tvb, bssap_tree, parameter_length);
+ break;
+
+ case PARAMETER_LENGTH:
+ dissect_bssap_length_param(parameter_tvb, bssap_tree, parameter_length);
+ break;
+
+ case PARAMETER_DATA:
+ dissect_bssap_data_param(parameter_tvb, pinfo, bssap_tree, tree);
+ break;
+
+ default:
+ dissect_bssap_unknown_param(parameter_tvb, bssap_tree, parameter_type,
+ parameter_length);
+ break;
+ }
+
+ return(parameter_length);
+}
+
+static guint16
+dissect_bssap_var_parameter(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *bssap_tree, proto_tree *tree,
+ guint8 parameter_type, gint offset)
+{
+ guint16 parameter_length;
+ guint8 length_length;
+
+ parameter_length = tvb_get_guint8(tvb, offset);
+ length_length = LENGTH_LENGTH;
+
+ offset += length_length;
+
+ dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree, parameter_type,
+ offset, parameter_length);
+
+ return(parameter_length + length_length);
+}
+
+static void
+dissect_bssap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bssap_tree,
+ proto_tree *tree)
+{
+ gint offset = 0;
+
+ /*
+ * Extract the PDU type
+ */
+ pdu_type = tvb_get_guint8(tvb, PDU_TYPE_OFFSET);
+ offset = PDU_TYPE_LENGTH;
+
+ if (bssap_tree)
+ {
+ /*
+ * add the message type to the protocol tree
+ */
+ proto_tree_add_uint(bssap_tree,
+ (bssap_or_bsap_global == BSSAP) ? hf_bssap_pdu_type : hf_bsap_pdu_type,
+ tvb, PDU_TYPE_OFFSET, PDU_TYPE_LENGTH, pdu_type);
+ }
+
+ /* Starting a new message dissection */
+
+ switch (pdu_type)
+ {
+ case BSSAP_PDU_TYPE_BSSMAP:
+ offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
+ PARAMETER_LENGTH, offset,
+ LENGTH_LENGTH);
+ offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
+ PARAMETER_DATA,
+ (offset - LENGTH_LENGTH));
+ break;
+
+ case BSSAP_PDU_TYPE_DTAP:
+ offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
+ PARAMETER_DLCI,
+ offset, DLCI_LENGTH);
+ offset += dissect_bssap_parameter(tvb, pinfo, bssap_tree, tree,
+ PARAMETER_LENGTH, offset,
+ LENGTH_LENGTH);
+ offset += dissect_bssap_var_parameter(tvb, pinfo, bssap_tree, tree,
+ PARAMETER_DATA,
+ (offset - LENGTH_LENGTH));
+ break;
+
+ default:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(pdu_type, ((bssap_or_bsap_global == BSSAP) ?
+ bssap_pdu_type_acro_values : bsap_pdu_type_acro_values),
+ "Unknown"));
+
+ }
+
+ dissect_bssap_unknown_message(tvb, bssap_tree);
+ break;
+ }
+}
+
+static void
+dissect_bssap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *bssap_item;
+ proto_tree *bssap_tree = NULL;
+
+ /*
+ * Make entry in the Protocol column on summary display
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, ((bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP"));
+ }
+
+ /*
+ * create the bssap protocol tree
+ */
+ proto_tree_add_item_hidden(tree, proto_bssap, tvb, 0, -1, FALSE);
+ bssap_item = proto_tree_add_text(tree, tvb, 0, -1, (bssap_or_bsap_global == BSSAP) ? "BSSAP" : "BSAP");
+ bssap_tree = proto_item_add_subtree(bssap_item, ett_bssap);
+
+ /* dissect the message */
+
+ dissect_bssap_message(tvb, pinfo, bssap_tree, tree);
+}
+
+static gboolean
+dissect_bssap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Is it a BSSAP/BSAP packet?
+ * If octet_1 == 0x00 and octet_2 == length(tvb) - 2
+ * or if octet_1 == 0x01 and octet_3 == length(tvb) - 3
+ * then we'll assume it is a bssap packet
+ */
+ switch (tvb_get_guint8(tvb, 0))
+ {
+ case 0x00:
+ if (tvb_get_guint8(tvb, 1) != (tvb_length(tvb) - 2)) { return(FALSE); }
+ break;
+
+ case 0x01:
+ if (tvb_get_guint8(tvb, 2) != (tvb_length(tvb) - 3)) { return(FALSE); }
+ break;
+
+ default:
+ return(FALSE);
+ }
+
+ dissect_bssap(tvb, pinfo, tree);
+
+ return(TRUE);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_bssap(void)
+{
+ module_t *bssap_module;
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_bssap_pdu_type,
+ { "Message Type", "bssap.pdu_type",
+ FT_UINT8, BASE_HEX, VALS(bssap_pdu_type_values), 0x0,
+ "", HFILL}},
+ { &hf_bsap_pdu_type,
+ { "Message Type", "bsap.pdu_type",
+ FT_UINT8, BASE_HEX, VALS(bsap_pdu_type_values), 0x0,
+ "", HFILL}},
+ { &hf_bssap_dlci_cc,
+ { "Control Channel", "bssap.dlci.cc",
+ FT_UINT8, BASE_HEX, VALS(bssap_cc_values), CC_MASK,
+ "", HFILL}},
+ { &hf_bsap_dlci_cc,
+ { "Control Channel", "bsap.dlci.cc",
+ FT_UINT8, BASE_HEX, VALS(bsap_cc_values), CC_MASK,
+ "", HFILL}},
+ { &hf_bssap_dlci_spare,
+ { "Spare", "bssap.dlci.spare",
+ FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
+ "", HFILL}},
+ { &hf_bsap_dlci_rsvd,
+ { "Reserved", "bsap.dlci.rsvd",
+ FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
+ "", HFILL}},
+ { &hf_bssap_dlci_sapi,
+ { "SAPI", "bssap.dlci.sapi",
+ FT_UINT8, BASE_HEX, VALS(bssap_sapi_values), SAPI_MASK,
+ "", HFILL}},
+ { &hf_bsap_dlci_sapi,
+ { "SAPI", "bsap.dlci.sapi",
+ FT_UINT8, BASE_HEX, VALS(bsap_sapi_values), SAPI_MASK,
+ "", HFILL}},
+ { &hf_bssap_length,
+ { "Length", "bssap.length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_bssap,
+ &ett_bssap_dlci,
+ };
+
+ static enum_val_t bssap_or_bsap_options[] = {
+ { "bssap", "BSSAP", BSSAP },
+ { "bsap", "BSAP", BSAP },
+ { NULL, NULL, 0 }
+ };
+
+
+ /* Register the protocol name and description */
+ proto_bssap = proto_register_protocol("BSSAP/BSAP", "BSSAP", "bssap");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_bssap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ bssap_module = prefs_register_protocol(proto_bssap, NULL);
+
+ prefs_register_enum_preference(bssap_module,
+ "bsap_or_bssap",
+ "Identify to sub-dissector as",
+ "For the sake of sub-dissectors registering to accept data from the BSSAP/BSAP dissector, this defines whether it is identified as BSSAP or BSAP.",
+ &bssap_or_bsap_global,
+ bssap_or_bsap_options,
+ FALSE);
+
+ bssap_dissector_table = register_dissector_table("bssap.pdu_type", "BSSAP Message Type", FT_UINT8, BASE_DEC);
+ bsap_dissector_table = register_dissector_table("bsap.pdu_type", "BSAP Message Type", FT_UINT8, BASE_DEC);
+}
+
+void
+proto_reg_handoff_bssap(void)
+{
+ heur_dissector_add("sccp", dissect_bssap_heur, proto_bssap);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-bssap.h b/epan/dissectors/packet-bssap.h
new file mode 100644
index 0000000000..63a2ce3df6
--- /dev/null
+++ b/epan/dissectors/packet-bssap.h
@@ -0,0 +1,34 @@
+/* packet-bssap.h
+ * Routines for Base Station Subsystem Application Part (BSSAP/BSAP) dissection
+ * Specifications from 3GPP2 (www.3gpp2.org) and 3GPP (www.3gpp.org)
+ * IOS 4.0.1 (BSAP)
+ * GSM 08.06 (BSSAP)
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define BSSAP_PDU_TYPE_BSSMAP 0x00
+#define BSSAP_PDU_TYPE_DTAP 0x01
+
+#define BSSAP_PDU_TYPE_BSMAP BSSAP_PDU_TYPE_BSSMAP
diff --git a/epan/dissectors/packet-bssgp.c b/epan/dissectors/packet-bssgp.c
new file mode 100644
index 0000000000..01e4e16dd6
--- /dev/null
+++ b/epan/dissectors/packet-bssgp.c
@@ -0,0 +1,1686 @@
+/* packet-bssgp.c
+ * Routines for BSSGP (BSS GPRS Protocol ETSI GSM 08.18 version 6.7.1 TS 101 343 ) dissection
+ * Copyright 2000, Josef Korelus <jkor@quick.cz>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+/*#include "packet-bssgp.h"*/
+
+
+/*PDU Type GSM 08.18 version 6.7.1 table 11.27 page 53*/
+#define DL_UNITDATA 0x0
+#define UL_UNITDATA 0x1
+#define RA_CAPABILITY 0X2
+#define PTM_UNITDAT 0X3
+#define PAGING_PS 0X6
+#define PAGING_CS 0x7
+#define RA_CAPABILITY_UPDATE 0X8
+#define RA_CAPABILITY_UPDATE_ACK 0X9
+#define RADIO_STATUS 0xa
+#define SUSPEND 0xb
+#define SUSPEND_ACK 0xc
+#define SUSPEND_NACK 0xd
+#define RESUME 0xe
+#define RESUME_ACK 0xf
+#define RESUME_NACK 0x10
+#define BVC_BLOCK 0x20
+#define BVC_BLOCK_ACK 0x21
+#define BVC_RESET 0X22
+#define BVC_RESET_ACK 0X23
+#define BVC_UNBLOCK 0x24
+#define BVC_UNBLOCK_ACK 0x25
+#define FLOW_CONTROL_BVC 0x26
+#define FLOW_CONTROL_BVC_ACK 0x27
+#define FLOW_CONTROL_MS 0x28
+#define FLOW_CONTROL_MS_ACK 0x29
+#define FLUSH_LL 0x2a
+#define FLUSH_LL_ACK 0x2b
+#define LLC_DISCARDED 0x2c
+#define SGSN_INVOKE_TRACE 0x40
+#define STATUS 0x41
+
+
+#define BSSGP_M 1
+#define BSSGP_O 2
+#define BSSGP_C 3
+
+#define QOSO5CR 0x20
+#define QOSO5T 0x10
+#define QOSO5A 0x08
+#define LOW3B 0x07
+#define ODD_EVEN_INDIC 0x08
+/*GSM 08.18 version 6.7.1 table 11.27*/
+
+static const value_string tab_bssgp_pdu_type[] = {
+ { DL_UNITDATA, "DL-UNITDATA" },
+ { UL_UNITDATA, "UL-UNITDATA" },
+ { RA_CAPABILITY, "RA_CAPABILITY" },
+ { PTM_UNITDAT, "PTM-UNITDATA" },
+ { PAGING_PS, "PAGING PS" },
+ { PAGING_CS, "PAGING CS" },
+ { RA_CAPABILITY_UPDATE, "RA-CAPABILITY-UPDATE" },
+ { RA_CAPABILITY_UPDATE_ACK, "RA-CAPABILITY-UPDATE-ACK" },
+ { RADIO_STATUS, "RADIO-STATUS" },
+ { SUSPEND, "SUSPEND" },
+ { SUSPEND_ACK, "SUSPEND-ACK" },
+ { SUSPEND_NACK, "SUSPEND-NACK" },
+ { RESUME, "RESUME" },
+ { RESUME_ACK, "RESUME-ACK" },
+ { RESUME_NACK, "RESUME-NACK" },
+ { BVC_BLOCK, "BVC-BLOCK" },
+ { BVC_BLOCK_ACK, "BVC-BLOCK-ACK" },
+ { BVC_RESET, "BVC-RESET" },
+ { BVC_RESET_ACK, "BVC-RESET-ACK" },
+ { BVC_UNBLOCK, "BVC-UNBLOCK" },
+ { BVC_UNBLOCK_ACK, "BVC_UNBLOCK_ACK" },
+ { FLOW_CONTROL_BVC, "FLOW-CONTROL-BVC" },
+ { FLOW_CONTROL_BVC_ACK, "FLOW-CONTROL-BVC-ACK" },
+ { FLOW_CONTROL_MS, "FLOW-CONTROL-MS" },
+ { FLOW_CONTROL_MS_ACK, "FLOW-CONTROL-MS-ACK" },
+ { FLUSH_LL, "FLUSH-LL" },
+ { FLUSH_LL_ACK, "FLUSH-LL-ACK" },
+ { LLC_DISCARDED, "LLC-DISCARDED" },
+ { SGSN_INVOKE_TRACE, "SGSN_INVOKE_TRACE" },
+ { STATUS, "STATUS" },
+ { 0, NULL },
+};
+
+static const value_string bssgp_iei[] = {
+ { 0x0, "Alignment Octets" },
+ { 0x1, "Bmax default MS" },
+ { 0x2, "BSS Area Indication" },
+ { 0x3, "Bucket Leak Rate" },
+ { 0x4, "BVCI" },
+ { 0x5, "BVC Bucket Size" },
+ { 0x6, "BVC Measurment" },
+ { 0x7, "Cause" },
+ { 0x8, "Cell Identifier" },
+ { 0x9, "Channel needed" },
+ { 0xa, "DRX Parameters" },
+ { 0xb, "eMLPP-Priority" },
+ { 0xc, "Flush Action" },
+ { 0xd, "IMSI" },
+ { 0xe, "LLC-PDU"},
+ { 0xf, "LLC Frames Discarded" },
+ { 0x10, "Location Area" },
+ { 0x11, "Mobile Id" },
+ { 0x12, "MS Bucket Size" },
+ { 0x13, "MS Radio Access Capability" },
+ { 0x14, "OMC Id" },
+ { 0x15, "PDU In Error" },
+ { 0x16, "PDU Lifetime" },
+ { 0x17, "Priority" },
+ { 0x18, "QoS Profile" },
+ { 0x19, "Radio Cause" },
+ { 0x1a, "RA-Cap-UPD-Cause" },
+ { 0x1b, "Routeing Area" },
+ { 0x1c, "R_default_MS" },
+ { 0x1d, "Suspend Reference Number" },
+ { 0x1e, "Tag" },
+ { 0x1f, "TLLI" },
+ { 0x20, "TMSI" },
+ { 0x21, "Trace Reference" },
+ { 0x22, "Trace Type" },
+ { 0x23, "Transaction Id" },
+ { 0x24, "Trigger Id" },
+ { 0x25, "Number of octets affected" },
+ { 0, NULL },
+};
+
+static const value_string bssgp_cause[] = {
+ { 0x0, "Processor overload" },
+ { 0x1, "Equipment failure" },
+ { 0x2, "Transit network service failure" },
+ { 0x3, "Network service transmission capacity modified from zero kbps to greater than zero" },
+ { 0x4, "Unknown MS" },
+ { 0x5, "BVCI unknown" },
+ { 0x6, "Cell traffic congestion" },
+ { 0x7, "SGSN congestion" },
+ { 0x8, "O&M intervention" },
+ { 0x9, "BVCI-blocked" },
+ { 0x20, "Semantically incorect PDU" },
+ { 0x21, "Invalid mandatory information" },
+ { 0x22, "Missing mandatory information" },
+ { 0x23, "Missing conditional IE" },
+ { 0x24, "Unexpected conditional IE" },
+ { 0x25, "Conditional IE error" },
+ { 0x26, "PDU not compatible with protocol state" },
+ { 0x27, "Protocol error-unspecified" },
+ { 0, NULL },
+};
+
+#define TOI_IMSI 0x01
+#define TOI_IMEI 0x02
+#define TOI_IMEISV 0x03
+#define TOI_TMSI_P_TMSI 0x04
+#define TOI_NO_IDENTITY 0x00
+
+static const value_string type_of_identity[] = {
+ { TOI_IMSI, "IMSI" },
+ { TOI_IMEI, "IMEI" },
+ { TOI_IMEISV, "IMEISV" },
+ { TOI_TMSI_P_TMSI, "TMSI/P-TMSI" },
+ { TOI_NO_IDENTITY, "No identity" },
+ { 0, NULL },
+};
+static const value_string radio_cause[] = {
+ { 0x0, "Radio contact lost with the MS" },
+ { 0x1, "Radio link quality insufficient to continue communication" },
+ { 0x2, "cell-reselction ordered" },
+ { 0, NULL },
+};
+static const true_false_string cr_string = {
+ "The SDU does not contain a LLC ACK or SACK command/response frame type",
+ "The SDU contains a LLC ACK or SACK command/response frame type",
+};
+static const true_false_string t_string = {
+ "The SDU contains data",
+ "The SDU contains signalling "
+};
+static const true_false_string a_string = {
+ "Radio interface uses RLC/MAC-UNITDATA functionality",
+ "Radio interface uses RLC/MAC ARQ functionality"
+};
+static const true_false_string imsi_odd_even = {
+ "even number of identity digits and also when the TMSI/P-TMSI is used",
+ "odd number of identity digits"
+};
+static const value_string prec_dl[] = {
+ { 0, "High priority"},
+ { 1, "Normal priority"},
+ { 2, "Low priority"},
+ { 3, "Reserved:Taken like Low priority"},
+ { 4, "Reserved:Taken like Low priority"},
+ { 0, NULL},
+};
+static const value_string prec[] = {
+ { 0, "Radio priority 1" },
+ { 1, "Radio priority 2" },
+ { 2, "Radio priority 3" },
+ { 3, "Radio priority 4" },
+ { 4, "Radio priority Unknown" },
+ { 0, NULL },
+};
+static const value_string prec_both[] = {
+ { 0, "High priority/Radio priority 1"},
+ { 1, "Normal priority/Radio priority 2"},
+ { 2, "Low priority/Radio priority 3"},
+ { 3, "Reserved/Radio priority 4"},
+ { 4, "Reserved/Radio priority Unknown"},
+ { 0, NULL},
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_bssgp = -1;
+static int hf_bssgp_pdu_type= -1;
+static int hf_bssgp_cause = -1;
+static int hf_bssgp_cid = -1;
+static int hf_bssgp_imsi = -1;
+static int hf_bssgp_imsi_toi = -1;
+static int hf_bssgp_imsi_even_odd_indic = -1;
+static int hf_bssgp_imsi_lsix = -1;
+static int hf_bssgp_tlli = -1;
+/*static int hf_bssgp_tag = -1;
+static int hf_bssgp_tlli_old = -1;
+static int hf_bssgp_aligment = -1;
+static int hf_bssgp_drx_param = -1;
+static int hf_bssgp_ms_radio_cap = -1;
+*/
+static int hf_bssgp_qos = -1;
+static int hf_bssgp_pbr = -1;
+static int hf_bssgp_pdu_lifetime = -1;
+/*static int hf_bssgp_priority = -1;
+static int hf_bssgp_llc_pdu = -1;
+static int hf_bssgp_ptmsi = -1;
+*/
+static int hf_bssgp_bvci = -1;
+/*static int hf_bssgp_la = -1;
+*/
+static int hf_bssgp_ra_mccmnc = -1;
+static int hf_bssgp_ra_lac = -1;
+static int hf_bssgp_ra_rac = -1;
+/*static int hf_bssgp_bss_area = -1;
+static int hf_bssgp_channel_needed = -1;
+static int hf_bssgp_emlpp_priority = -1;
+static int hf_bssgp_ra_cap_upd_cause = -1;
+*/
+static int hf_bssgp_radio_cause = -1;
+/*static int hf_bssgp_sus_ref_num = -1;
+*/
+static int hf_bssgp_bvci_new = -1;
+/*static int hf_bssgp_flush_action = -1;
+static int hf_bssgp_num_oct_affect = -1;
+static int hf_bssgp_llc_disc = -1;
+*/
+static int hf_bssgp_bvc_buck_size = -1;
+static int hf_bssgp_buck_leak_rate = -1;
+static int hf_bssgp_bmax_def_ms = -1;
+static int hf_bssgp_r_defau_ms = -1;
+/*static int hf_bssgp_bvc_measur = -1;
+static int hf_bssgp_ms_buck_size = -1;
+static int hf_bssgp_trace_type = -1;
+static int hf_bssgp_trace_ref = -1;
+static int hf_bssgp_trigg_id = -1;
+static int hf_bssgp_mobile_id = -1;
+static int hf_bssgp_omc_id = -1;
+static int hf_bssgp_transactionid = -1;
+*/
+static int hf_bssgp_ietype = -1;
+static int hf_bssgp_qos_cr = -1;
+static int hf_bssgp_qos_t = -1;
+static int hf_bssgp_qos_a = -1;
+static int hf_bssgp_qos_prec = -1;
+static int hf_bssgp_frdsc = -1;
+static int hf_bssgp_noaff = -1;
+/*static int hf_bssgp_FIELDABBREV = -1;*/
+
+/*static dissector_handle_t data_handle;
+*/
+static dissector_handle_t llcgprs_handle;
+
+/* Initialize the subtree pointers */
+static gint ett_bssgp = -1;
+static gint ett_bssgp_tlli = -1;
+static gint ett_bssgp_qos = -1;
+static gint ett_bssgp_o5 = -1;
+static gint ett_bssgp_lft = -1;
+static gint ett_bssgp_racc = -1;
+static gint ett_prio_tree = -1;
+static gint ett_drx_tree = -1;
+static gint ett_bssgp_imsi = -1;
+static gint ett_bssgp_imsi_stru_tree = -1;
+static gint ett_algn_tree = -1;
+static gint ett_b_llc_tree = -1;
+static gint ett_celid_tree = -1;
+static gint ett_tag_tree = -1;
+static gint ett_bsize_tree = -1;
+static gint ett_bucklr_tree = -1;
+static gint ett_bmaxms_tree = -1;
+static gint ett_rdefms_tree = -1;
+static gint ett_bvci_tree = -1;
+static gint ett_bvcin_tree = -1;
+static gint ett_cause_tree = -1;
+static gint ett_frdsc_tree = -1;
+static gint ett_noaff_tree = -1;
+static gint ett_racaus_tree = -1;
+static gint ett_ra_tree = -1;
+/*Functions for decoding IEs of BSSGP V6.7.1 */
+typedef struct {
+ int type;
+ packet_info *pinfo;
+ proto_tree *tree;
+ int k;
+} dec_fu_param_stru_t;
+static int dcd_bssgp_algn ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_bmaxms ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+/*static int dcd_bssgp_bss_aind ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+static int dcd_bssgp_bucklr ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_bvci ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_bvci_n ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_bvc_bsize ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+/*static int dcd_bssgp_bvc_meas ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+static int dcd_bssgp_cause ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_cellid ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+/*static int dcd_bssgp_chan_need ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+static int dcd_bssgp_drx ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+/*static int dcd_bssgp_emlpp_prio ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_flush_act ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+static int dcd_bssgp_imsi ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_llc_pdu ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_llc_frdsc ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+/*static int dcd_bssgp_la ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_mid ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_ms_buck ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+static int dcd_bssgp_radio_acc ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+/*static int dcd_bssgp_omc_id ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+/*static int dcd_bssgp_pdu_err ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+static int dcd_bssgp_pdu_life ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_prio ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_qos ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_radio_caus ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+/*static int dcd_bssgp_racap_upd ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+static int dcd_bssgp_ra ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_r_def_ms ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+/*static int dcd_bssgp_sus_ref_num( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+static int dcd_bssgp_tag ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_tlli ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+/*static int dcd_bssgp_tlli_o ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+/*static int dcd_bssgp_tmsi ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+/*static int dcd_bssgp_trace_ref ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+/*static int dcd_bssgp_trace_type ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+/*static int dcd_bssgp_trans_id ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+/*static int dcd_bssgp_trig_id ( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+*/
+static int dcd_bssgp_num_oct_aff( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static int dcd_bssgp_not_yet_dcd( tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm );
+static void mccmnc(guint32 mcmn, char buf[]);
+/*---------------------------------------------------------*/
+typedef struct _bssgp_ie {
+ guint8 code;
+ guint8 presence;
+ guint8 type;
+/* int (*decode)(tvbuff_t *, int, int, packet_info *, proto_tree *);
+*/
+ int (*decode)(tvbuff_t *, int, dec_fu_param_stru_t *);
+ } bssgp_ie_t;
+typedef struct _bssgp_pdu {
+ guint8 pdu;
+ bssgp_ie_t infe[12];
+} _bssgp_pdu_t;
+/*------------------------------------------------------------*/
+static _bssgp_pdu_t bssgp_pdu[] = {
+ {
+ DL_UNITDATA, {
+ { 0x1f, BSSGP_M, 3, dcd_bssgp_tlli },
+ { 0x18, BSSGP_M, 3, dcd_bssgp_qos },
+ { 0x16, BSSGP_M, 4, dcd_bssgp_pdu_life },
+ { 0x13, BSSGP_O, 4, dcd_bssgp_radio_acc },
+ { 0x17, BSSGP_O, 4, dcd_bssgp_prio },
+ { 0x0a, BSSGP_O, 4, dcd_bssgp_drx },
+ { 0x0d, BSSGP_O, 4, dcd_bssgp_imsi },
+/* { 0x1f, BSSGP_O, 4, dcd_bssgp_tlli_o },
+*/
+ { 0x1f, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
+ { 0x00, BSSGP_O, 4, dcd_bssgp_algn },
+ { 0x0e, BSSGP_M, 4, dcd_bssgp_llc_pdu },
+ { 0,0,0,NULL }
+ }
+
+ },
+ {
+ UL_UNITDATA, {
+ { 0x1f, BSSGP_M, 3, dcd_bssgp_tlli },
+ { 0x18, BSSGP_M, 3, dcd_bssgp_qos },
+ { 0x08, BSSGP_M, 4, dcd_bssgp_cellid },
+ { 0x00, BSSGP_O, 4, dcd_bssgp_algn },
+ { 0x0e, BSSGP_M, 4, dcd_bssgp_llc_pdu },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ RA_CAPABILITY, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x13, BSSGP_M, 4, dcd_bssgp_radio_acc },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ PAGING_PS, {
+ { 0x0d, BSSGP_M, 4, dcd_bssgp_imsi },
+ { 0x0a, BSSGP_O, 4, dcd_bssgp_drx },
+ { 0x04, BSSGP_C, 4, dcd_bssgp_bvci },
+/* { 0x10, BSSGP_C, 4, dcd_bssgp_la },
+*/
+ { 0x10, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
+ { 0x1b, BSSGP_C, 4, dcd_bssgp_ra },
+/* { 0x02, BSSGP_C, 4, dcd_bssgp_bss_aind },
+*/
+ { 0x02, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
+ { 0x18, BSSGP_M, 4, dcd_bssgp_qos },
+/* { 0x20, BSSGP_O, 4, dcd_bssgp_tmsi },
+*/
+ { 0x20, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ PAGING_CS, {
+ { 0x0d, BSSGP_M, 4, dcd_bssgp_imsi },
+ { 0x0a, BSSGP_M, 4, dcd_bssgp_drx },
+ { 0x04, BSSGP_C, 4, dcd_bssgp_bvci },
+/* { 0x10, BSSGP_C, 4, dcd_bssgp_la },
+*/
+ { 0x10, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
+ { 0x1b, BSSGP_C, 4, dcd_bssgp_ra },
+/* { 0x02, BSSGP_C, 4, dcd_bssgp_bss_aind },
+*/
+ { 0x02, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
+ { 0x1f, BSSGP_O, 4, dcd_bssgp_tlli },
+/* { 0x09, BSSGP_O, 4, dcd_bssgp_chan_need },
+*/
+ { 0x09, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
+/* { 0x0b, BSSGP_O, 4, dcd_bssgp_emlpp_prio },
+*/
+ { 0x0b, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
+/* { 0x20, BSSGP_O, 4, dcd_bssgp_tmsi },
+*/
+ { 0x20, BSSGP_O, 4, dcd_bssgp_not_yet_dcd},
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ RA_CAPABILITY_UPDATE, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
+ { 0,0,0,NULL }
+ }
+
+ },
+ {
+ RA_CAPABILITY_UPDATE_ACK, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
+ { 0x0d, BSSGP_O, 4, dcd_bssgp_imsi },
+/* { 0x1a, BSSGP_M, 4, dcd_bssgp_racap_upd },
+*/
+ { 0x1a, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
+ { 0x13, BSSGP_C, 4, dcd_bssgp_radio_acc },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ RADIO_STATUS, {
+ { 0x1f, BSSGP_C, 4, dcd_bssgp_tlli },
+/* { 0x20, BSSGP_C, 4, dcd_bssgp_tmsi },
+*/
+ { 0x20, BSSGP_C, 4, dcd_bssgp_not_yet_dcd},
+ { 0x0d, BSSGP_C, 4, dcd_bssgp_imsi },
+ { 0x19, BSSGP_M, 4, dcd_bssgp_radio_caus },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ SUSPEND, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ SUSPEND_ACK, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
+/* { 0x1d, BSSGP_M, 4, dcd_bssgp_sus_ref_num },
+*/
+ { 0x1d, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ SUSPEND_NACK, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
+ { 0x07, BSSGP_O, 4, dcd_bssgp_cause },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ RESUME, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
+/* { 0x1d, BSSGP_M, 4, dcd_bssgp_sus_ref_num },
+*/
+ { 0x1d, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ RESUME_ACK, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ RESUME_NACK, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1b, BSSGP_M, 4, dcd_bssgp_ra },
+ { 0x07, BSSGP_O, 4, dcd_bssgp_cause },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ BVC_BLOCK, {
+ { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
+ { 0x07, BSSGP_M, 4, dcd_bssgp_cause },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ BVC_BLOCK_ACK, {
+ { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ BVC_RESET, {
+ { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
+ { 0x07, BSSGP_M, 4, dcd_bssgp_cause },
+ { 0x08, BSSGP_C, 4, dcd_bssgp_cellid },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ BVC_RESET_ACK, {
+ { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
+ { 0x08, BSSGP_C, 4, dcd_bssgp_cellid },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ BVC_UNBLOCK, {
+ { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ BVC_UNBLOCK_ACK, {
+ { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ FLOW_CONTROL_BVC, {
+ { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
+ { 0x05, BSSGP_M, 4, dcd_bssgp_bvc_bsize },
+ { 0x03, BSSGP_M, 4, dcd_bssgp_bucklr },
+ { 0x01, BSSGP_M, 4, dcd_bssgp_bmaxms },
+ { 0x1c, BSSGP_M, 4, dcd_bssgp_r_def_ms },
+/* { 0x06, BSSGP_O, 4, dcd_bssgp_bvc_meas }, */
+ { 0x06, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ FLOW_CONTROL_BVC_ACK, {
+ { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ FLOW_CONTROL_MS, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
+/* { 0x12, BSSGP_M, 4, dcd_bssgp_ms_buck},
+*/
+ { 0x12, BSSGP_M, 4, dcd_bssgp_not_yet_dcd},
+ { 0x03, BSSGP_M, 4, dcd_bssgp_bucklr },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ FLOW_CONTROL_MS_ACK, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x1e, BSSGP_M, 4, dcd_bssgp_tag },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ FLUSH_LL, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
+ { 0x04, BSSGP_O, 4, dcd_bssgp_bvci_n },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ FLUSH_LL_ACK, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+/* { 0x0c, BSSGP_M, 4, dcd_bssgp_flush_act },
+*/
+ { 0x0c, BSSGP_M, 4, dcd_bssgp_not_yet_dcd },
+ { 0x04, BSSGP_C, 4, dcd_bssgp_bvci_n },
+ { 0x25, BSSGP_M, 4, dcd_bssgp_num_oct_aff },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ LLC_DISCARDED, {
+ { 0x1f, BSSGP_M, 4, dcd_bssgp_tlli },
+ { 0x0f, BSSGP_M, 4, dcd_bssgp_llc_frdsc },
+ { 0x04, BSSGP_M, 4, dcd_bssgp_bvci },
+ { 0x25, BSSGP_M, 4, dcd_bssgp_num_oct_aff },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ SGSN_INVOKE_TRACE, {
+/* { 0x22, BSSGP_M, 4, dcd_bssgp_trace_type },
+ { 0x21, BSSGP_M, 4, dcd_bssgp_trace_ref },
+ { 0x24, BSSGP_O, 4, dcd_bssgp_trig_id },
+ { 0x11, BSSGP_O, 4, dcd_bssgp_mid },
+ { 0x14, BSSGP_O, 4, dcd_bssgp_omc_id },
+ { 0x23, BSSGP_O, 4, dcd_bssgp_trans_id },
+*/
+ { 0x22, BSSGP_M, 4, dcd_bssgp_not_yet_dcd },
+ { 0x21, BSSGP_M, 4, dcd_bssgp_not_yet_dcd },
+ { 0x24, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
+ { 0x11, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
+ { 0x14, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
+ { 0x23, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ STATUS, {
+ { 0x07, BSSGP_M, 4, dcd_bssgp_cause },
+ { 0x04, BSSGP_C, 4, dcd_bssgp_bvci },
+/* { 0x15, BSSGP_O, 4, dcd_bssgp_pdu_err },
+*/
+ { 0x15, BSSGP_O, 4, dcd_bssgp_not_yet_dcd },
+ { 0,0,0,NULL }
+ }
+ },
+ {
+ 0, {
+ { 0,0,0,NULL }
+ }
+ }
+};
+/*-----------------------------------------------------------------------------------------------------------------*/
+static void mccmnc(guint32 mcmn, char buf[]){
+ typedef struct {
+ guint32 mnc1 : 4 ;
+ guint32 mnc2 : 4 ;
+ guint32 mcc3 : 4 ;
+ guint32 mnc3 : 4 ;
+ guint32 mcc1 : 4 ;
+ guint32 mcc2 : 4 ;
+ } stru_mncmcc;
+ typedef union {
+ guint32 i;
+ stru_mncmcc s;
+ } u_mncmcc;
+ u_mncmcc *r_mncmcc;
+ guint8 pom =0,i=0 ;
+ r_mncmcc = (u_mncmcc *)&mcmn;
+ for (i=0;i<8;i++){
+ switch (i) {
+ case 0 :
+ pom = r_mncmcc->s.mcc1;
+ break;
+ case 1 :
+ pom = r_mncmcc->s.mcc2;
+ break;
+ case 2 :
+ pom = r_mncmcc->s.mcc3;
+ break;
+ case 3 :
+ pom = 0x61;/* 0x61 because i need space " " (0x61-1)^0x40*/
+ break;
+ case 4 :
+ pom = r_mncmcc->s.mnc1;
+ break;
+ case 5 :
+ pom = r_mncmcc->s.mnc2;
+ break;
+ case 6 :
+ pom = r_mncmcc->s.mnc3;
+ pom = (pom == 0xf)?0x41: pom;/* 0x41 because i need null on the end of string (0x41-1)^0x40*/
+ break;
+ case 7 :
+ pom = 0x41;
+ break;
+
+ }
+ pom = (pom > 9)?(pom-1) ^ 0x40: pom ^ 0x30;
+ buf[i] = pom;
+ }
+}
+static int dcd_bssgp_not_yet_dcd(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, pom=0,k=2;
+ guint16 llen=0;
+
+ pom = tvb_get_guint8(tvb,offset+1);
+ if ( pom >= 128 ){
+ llen = pom & 0x7f;
+ k = 2;
+ }
+ else{
+ llen = tvb_get_ntohs( tvb, offset+1);
+ k=3;
+ }
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ proto_tree_add_uint_format(dprm_p->tree,hf_bssgp_ietype,tvb,offset,llen+k,code,"IE type: %s (%#.2x) ....Not yet decoded",match_strval(code,bssgp_iei),code);
+ }
+return llen+k;
+}
+static int dcd_bssgp_algn(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ proto_item *ti=NULL;
+ proto_tree *algn_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%u Aligment octets", len+2 );
+ algn_tree = proto_item_add_subtree(ti, ett_algn_tree);
+ proto_tree_add_uint_format(algn_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_text(algn_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+static int dcd_bssgp_bmaxms(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ guint16 bucket=0;
+ proto_item *ti=NULL;
+ proto_tree *bmaxms_tree=NULL;
+
+ if (dprm_p->tree){
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ code = tvb_get_guint8(tvb,offset);
+ bucket = tvb_get_ntohs(tvb,offset+2);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u bytes", match_strval(code,bssgp_iei),100*bucket);
+ bmaxms_tree = proto_item_add_subtree(ti, ett_bmaxms_tree);
+ proto_tree_add_uint_format(bmaxms_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(bmaxms_tree, hf_bssgp_bmax_def_ms,tvb,offset+2,len,bucket,"%s in 100 octet increments: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
+ proto_tree_add_text(bmaxms_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+/*static int dcd_bssgp_bss_aind(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+static int dcd_bssgp_bucklr(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ guint16 bucket=0;
+ proto_item *ti=NULL;
+ proto_tree *bucklr_tree=NULL;
+
+ bucket = tvb_get_ntohs(tvb,offset+2);
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ code = tvb_get_guint8(tvb,offset);
+
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u bits/sec",match_strval(code,bssgp_iei),bucket*100 );
+ }
+ if (dprm_p->tree){
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "Bucket Leak Rate(R): %u bits/sec", 100*bucket);
+ bucklr_tree = proto_item_add_subtree(ti, ett_bucklr_tree);
+ proto_tree_add_uint_format(bucklr_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(bucklr_tree, hf_bssgp_buck_leak_rate,tvb,offset+2,len,bucket,"%s in 100 bits/sec increments: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
+ proto_tree_add_text(bucklr_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+static int dcd_bssgp_bvci(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ guint16 bucket=0;
+ proto_item *ti=NULL;
+ proto_tree *bvci_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ code = tvb_get_guint8(tvb,offset);
+ bucket = tvb_get_ntohs(tvb,offset+2);
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u",match_strval(code,bssgp_iei),bucket );
+ }
+ if (dprm_p->tree){
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u", match_strval(code,bssgp_iei), bucket);
+ bvci_tree = proto_item_add_subtree(ti, ett_bvci_tree);
+ proto_tree_add_uint_format(bvci_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(bvci_tree, hf_bssgp_bvci,tvb,offset+2,len,bucket,"%s: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
+ proto_tree_add_text(bvci_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+static int dcd_bssgp_bvci_n(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ guint16 bucket=0;
+ proto_item *ti=NULL;
+ proto_tree *bvcin_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ code = tvb_get_guint8(tvb,offset);
+ bucket = tvb_get_ntohs(tvb,offset+2);
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, " New %s: %u",match_strval(code,bssgp_iei),bucket );
+ }
+ if (dprm_p->tree){
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "New %s: %u", match_strval(code,bssgp_iei), bucket);
+ bvcin_tree = proto_item_add_subtree(ti, ett_bvcin_tree);
+ proto_tree_add_uint_format(bvcin_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s(New) %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(bvcin_tree, hf_bssgp_bvci_new,tvb,offset+2,len,bucket,"New %s: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
+ proto_tree_add_text(bvcin_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+static int dcd_bssgp_bvc_bsize(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ guint16 bucket=0;
+ proto_item *ti=NULL;
+ proto_tree *bsize_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ code = tvb_get_guint8(tvb,offset);
+ bucket = tvb_get_ntohs(tvb,offset+2);
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u bytes",match_strval(code,bssgp_iei),bucket*100 );
+ }
+ if (dprm_p->tree){
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "BVC Bucket Size: %u bytes", 100*bucket);
+ bsize_tree = proto_item_add_subtree(ti, ett_bsize_tree);
+ proto_tree_add_uint_format(bsize_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(bsize_tree, hf_bssgp_bvc_buck_size,tvb,offset+2,len,bucket,"%s in 100 octet increments: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
+ proto_tree_add_text(bsize_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+/*static int dcd_bssgp_bvc_meas(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+return 4;
+};
+*/
+static int dcd_bssgp_cause(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0,cause=0;
+ proto_item *ti=NULL;
+ proto_tree *cause_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ code = tvb_get_guint8(tvb,offset);
+ cause = tvb_get_guint8(tvb,offset+2);
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %s",match_strval(code,bssgp_iei),match_strval(cause,bssgp_cause));
+ }
+ if (dprm_p->tree){
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %s", match_strval(code,bssgp_iei),match_strval(cause,bssgp_cause));
+ cause_tree = proto_item_add_subtree(ti, ett_cause_tree);
+ proto_tree_add_uint_format(cause_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(cause_tree, hf_bssgp_cause,tvb,offset+2,len,cause,"%s: %s (%#.2x)",match_strval(code,bssgp_iei),match_strval(cause,bssgp_cause),cause);
+ proto_tree_add_text(cause_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+
+static int dcd_bssgp_cellid(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ char mccmnc_str[8];
+ guint32 mnccc;
+ guint16 lac,cid;
+ guint8 len=8, code=0,rac;
+ proto_item *ti = NULL;
+ proto_tree *celid_tree = NULL;
+
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ mnccc = tvb_get_ntoh24(tvb,offset+2);
+ lac = tvb_get_ntohs(tvb,offset+5);
+ rac = tvb_get_guint8(tvb,offset+7);
+ cid = tvb_get_ntohs(tvb,offset+8);
+ mccmnc(mnccc, mccmnc_str);
+
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "Cell Identifier: %s %u %u %u",mccmnc_str,lac,rac,cid);
+ celid_tree = proto_item_add_subtree(ti, ett_celid_tree);
+ proto_tree_add_uint_format(celid_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_string_format(celid_tree,hf_bssgp_ra_mccmnc,tvb,offset+2,3,mccmnc_str,"MCC MNC: %s",mccmnc_str);
+ proto_tree_add_uint_format(celid_tree,hf_bssgp_ra_lac,tvb,offset+5,2,lac,"LAC: %u",lac);
+ proto_tree_add_uint_format(celid_tree,hf_bssgp_ra_rac,tvb,offset+7,1,rac,"RAC: %u",rac);
+ proto_tree_add_uint_format(celid_tree,hf_bssgp_cid,tvb,offset+8,2,cid,"Cell Id: %u",cid);
+ proto_tree_add_text(celid_tree,tvb,offset+1,1,"Length:%u",len);
+
+ }
+
+ return len+2;
+}
+
+/*static int dcd_bssgp_chan_need(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+static int dcd_bssgp_drx(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ proto_item *ti=NULL;
+ proto_tree *drx_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, 4,"DRX Parameters");
+ drx_tree = proto_item_add_subtree(ti, ett_drx_tree);
+ proto_tree_add_uint_format(drx_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_text(drx_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+
+}
+
+/*static int dcd_bssgp_emlpp_prio(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+
+/*static int dcd_bssgp_flush_act(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+
+static int dcd_bssgp_imsi(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 nextb=0, first_b=0, toi=0, i, k;
+ guint8 num=0,code=0,len=0;
+ char buf[17],imsi_mccn[6],imsi_val[11], toibuf[9];
+ proto_item *ti=NULL, *ti2=NULL;
+ proto_tree *imsi_tree = NULL, *imsi_stru_tree = NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ first_b = tvb_get_guint8(tvb,offset+2);
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ decode_bitfield_value(toibuf,toi,LOW3B,8);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+2 ,"IMSI");
+ imsi_tree = proto_item_add_subtree(ti, ett_bssgp_imsi);
+ proto_tree_add_uint_format(imsi_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_text(imsi_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+ toi = first_b & LOW3B;
+ switch (toi) {
+
+ case TOI_IMSI:
+ case TOI_IMEI:
+ case TOI_IMEISV:
+ num = first_b >> 4;
+ buf[0] = num + '0';
+ for (i=1,k=1;i<len;i++){
+ nextb = tvb_get_guint8(tvb, offset+2+i);
+ num = nextb & 0x0f;
+ buf[k] = num + '0';
+ k++;
+ if (i < len - 1 || (first_b & ODD_EVEN_INDIC)) {
+ /*
+ * Either this isn't the last octet
+ * of the number, or it is, but there's
+ * an odd number of digits, so the last
+ * nibble is part of the number.
+ */
+ num = nextb >> 4;
+ buf[k] = num + '0';
+ k++;
+ }
+ buf[k] = '\0';
+ switch (i*2){
+ case 4:
+ memcpy(&imsi_mccn,&buf,6);
+ break;
+ case 14:
+ memcpy(&imsi_val, &buf[5],11);
+ break;
+ }
+
+ }
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO,
+ ", %s: %s %s",
+ val_to_str(toi,type_of_identity,"Unknown TOI (0x%x)"),
+ imsi_mccn, imsi_val );
+ }
+
+ if (dprm_p->tree){
+ proto_item_append_text(ti, ": %s", buf);
+ ti2 = proto_tree_add_text(imsi_tree,tvb,offset+2,len,"Mobile identity: %s",buf);
+ imsi_stru_tree = proto_item_add_subtree( ti2, ett_bssgp_imsi_stru_tree);
+ proto_tree_add_uint(imsi_stru_tree,hf_bssgp_imsi_toi,tvb,offset+2,1,first_b);
+ proto_tree_add_boolean(imsi_stru_tree,hf_bssgp_imsi_even_odd_indic,tvb,offset+2,1,first_b);
+ proto_tree_add_string(imsi_stru_tree,hf_bssgp_imsi,tvb,offset+2,len,buf);
+ proto_tree_add_string_hidden(imsi_stru_tree,hf_bssgp_imsi_lsix,tvb,offset+2,len,imsi_val);
+ }
+ break;
+ }
+return len+2;
+}
+
+static int dcd_bssgp_llc_pdu(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, pom=0,k=0;
+ guint16 llen=0;
+ proto_item *ti=NULL;
+ proto_tree *b_llc_tree=NULL;
+
+ pom = tvb_get_guint8(tvb,offset+1);
+ if ( pom >= 128 ){
+ llen = pom & 0x7f;
+ k = 2;
+ }
+ else{
+ llen = tvb_get_ntohs( tvb, offset+1);
+ k=3;
+ }
+
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", LLC PDU length %u bytes", llen );
+ }
+
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset,llen+2 ,"LLC PDU %u bytes", llen);
+ b_llc_tree = proto_item_add_subtree(ti, ett_b_llc_tree);
+ proto_tree_add_uint_format(b_llc_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_text(b_llc_tree,tvb,offset+1,k-1,"Length:%u",llen);
+ }
+
+dprm_p->k=offset+k;
+return llen+k;
+}
+
+static int dcd_bssgp_llc_frdsc(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0,frdsc=0;
+ proto_item *ti=NULL;
+ proto_tree *frdsc_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ frdsc = tvb_get_guint8(tvb,offset+2);
+ code = tvb_get_guint8(tvb,offset);
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %u",match_strval(code,bssgp_iei), frdsc);
+ }
+ if (dprm_p->tree){
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u", match_strval(code,bssgp_iei), frdsc);
+ frdsc_tree = proto_item_add_subtree(ti, ett_frdsc_tree);
+ proto_tree_add_uint_format(frdsc_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(frdsc_tree, hf_bssgp_frdsc,tvb,offset+2,len,frdsc,"%s: %u",match_strval(code,bssgp_iei),frdsc);
+ proto_tree_add_text(frdsc_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+
+/*static int dcd_bssgp_la(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+
+/*static int dcd_bssgp_mid(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+
+/*static int dcd_bssgp_ms_buck(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+
+static int dcd_bssgp_radio_acc(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0,len=0;
+ proto_item *ti=NULL;
+ proto_tree *racc_tree = NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+2 ,"MS Radio Access Capability: ");
+ racc_tree = proto_item_add_subtree(ti, ett_bssgp_racc);
+ proto_tree_add_uint_format(racc_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_text(racc_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+
+/*static int dcd_bssgp_omc_id(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+
+/*static int dcd_bssgp_pdu_err(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+
+static int dcd_bssgp_pdu_life(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ gfloat ms_lifetime;
+ guint16 lifetime;
+ guint8 code=0, len=0;
+ proto_item *ti=NULL;
+ proto_tree *lft_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ lifetime = tvb_get_ntohs(tvb,offset+2);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, 4,"PDU Lifetime (s): ");
+ lft_tree = proto_item_add_subtree(ti, ett_bssgp_lft);
+ proto_tree_add_uint_format(lft_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_text(lft_tree,tvb,offset+1,1,"Length:%u",len);
+ if (lifetime == 0xFFFF){
+ proto_item_append_text(ti,"infinite delay");
+ proto_tree_add_uint_format(lft_tree,hf_bssgp_pdu_lifetime,tvb,offset+2,2,lifetime,"PDU Life time: infinite delay (%#.4x centi seconds)", lifetime);
+ }
+ else{
+ ms_lifetime = (gfloat) (lifetime/100);
+ proto_item_append_text(ti,"%f",ms_lifetime);
+ proto_tree_add_uint_format(lft_tree,hf_bssgp_pdu_lifetime,tvb,offset+2,2,lifetime,"PDU Life time: %fs (%#.4x centi seconds)", ms_lifetime, lifetime);
+ }
+ }
+return 4;
+}
+
+static int dcd_bssgp_prio(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ proto_item *ti=NULL;
+ proto_tree *prio_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, 4,"Priority");
+ prio_tree = proto_item_add_subtree(ti, ett_prio_tree);
+ proto_tree_add_uint_format(prio_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_text(prio_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+
+static int dcd_bssgp_qos(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint16 blr=0;
+ guint32 bps=0;
+ char buf[16];
+ gint8 disp=0, opet=0, code=0,len=0,start=0,pre=0;
+ proto_item *ti=NULL, *ti2=NULL;
+ proto_tree *qos_tree=NULL,*o5_tree;
+ switch (dprm_p->type){
+ case 3:
+ break;
+ case 4:
+ code = tvb_get_guint8(tvb,offset);
+ disp++;
+ len = tvb_get_guint8(tvb,offset+disp);
+ disp++;
+ len = len & 0x7f;
+ break;
+ }
+ start=disp;
+ blr = tvb_get_ntohs(tvb, offset+disp);
+ disp = disp+2;
+ opet = tvb_get_guint8(tvb,offset+disp);
+ disp++;
+ if (dprm_p->tree){
+ bps = 100*blr/8;
+ decode_bitfield_value(buf,opet,LOW3B,8);
+ pre = opet & LOW3B;
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+disp,"QoS Profile IE");
+ qos_tree = proto_item_add_subtree(ti,ett_bssgp_qos);
+ switch (dprm_p->type){
+ case 4:
+ proto_tree_add_uint_format(qos_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_text(qos_tree,tvb,offset+1,1,"Length:%u",len);
+ case 3:
+ if (blr){
+ proto_tree_add_uint_format(qos_tree,hf_bssgp_pbr,tvb,offset+start,2,blr,"Peak bit rate: %u bytes/s, (%#.4x)in 100bits/sec increments",bps,blr);
+ }
+ else{
+ proto_tree_add_uint_format(qos_tree,hf_bssgp_pbr,tvb,offset+start,2,blr,"Peak bit rate: best effort (%#.4x)in 100bits/sec increments",blr);
+ }
+ ti2 = proto_tree_add_item(qos_tree,hf_bssgp_qos,tvb,offset+(disp-1),1,FALSE);
+ o5_tree = proto_item_add_subtree(ti2, ett_bssgp_o5);
+ proto_tree_add_boolean(o5_tree,hf_bssgp_qos_cr,tvb,offset+(disp-1),1,opet);
+ proto_tree_add_boolean(o5_tree,hf_bssgp_qos_t,tvb,offset+(disp-1),1,opet);
+ proto_tree_add_boolean(o5_tree,hf_bssgp_qos_a,tvb,offset+(disp-1),1,opet);
+ if(tvb_get_guint8(tvb,0)){
+ proto_tree_add_uint_format(o5_tree,hf_bssgp_qos_prec,tvb,offset+(disp-1),1,pre,"%s %s", buf,match_strval(pre,prec));
+
+ }
+ else{
+ proto_tree_add_uint_format(o5_tree,hf_bssgp_qos_prec,tvb,offset+(disp-1),1,pre,"%s %s", buf,match_strval(pre,prec_dl));
+ }
+ }
+
+ }
+ return disp;
+}
+
+static int dcd_bssgp_radio_caus(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0,racaus=0;
+ proto_item *ti=NULL;
+ proto_tree *racaus_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ racaus = tvb_get_guint8(tvb,offset+2);
+ code = tvb_get_guint8(tvb,offset);
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO, ", %s: %s",match_strval(code,bssgp_iei), val_to_str(racaus,radio_cause,"%u reserved value"));
+ }
+ if (dprm_p->tree){
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %s", match_strval(code,bssgp_iei), val_to_str(racaus,radio_cause,"%u reserved value, if received , it shall be handled as ""radio contact lost with MS"""));
+ racaus_tree = proto_item_add_subtree(ti, ett_racaus_tree);
+ proto_tree_add_uint_format(racaus_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(racaus_tree, hf_bssgp_radio_cause,tvb,offset+2,len,racaus,"%s: %#.2x",match_strval(code,bssgp_iei),racaus);
+ proto_tree_add_text(racaus_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+
+/*static int dcd_bssgp_racap_upd(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+
+static int dcd_bssgp_ra(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint16 lac;
+ guint32 mnccc;
+ guint8 rac, len = 0,code=0 ;
+ char st_mccn[8];
+ proto_item *ti=NULL;
+ proto_tree *ra_tree = NULL;
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ mnccc = tvb_get_ntoh24(tvb,offset+2);
+ lac = tvb_get_ntohs(tvb,offset+5);
+ rac = tvb_get_guint8(tvb,offset+7);
+ mccmnc(mnccc, st_mccn);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+2, "Routing area: %s %u %u",st_mccn,lac,rac);
+ ra_tree = proto_item_add_subtree(ti, ett_ra_tree);
+ proto_tree_add_uint_format(ra_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_string_format(ra_tree,hf_bssgp_ra_mccmnc,tvb,offset+2,3,st_mccn,"MCC MNC: %s",st_mccn);
+ proto_tree_add_uint_format(ra_tree,hf_bssgp_ra_lac,tvb,offset+5,2,lac,"LAC: %u",lac);
+ proto_tree_add_uint_format(ra_tree,hf_bssgp_ra_rac,tvb,offset+7,1,rac,"RAC: %u",rac);
+ proto_tree_add_text(ra_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+
+static int dcd_bssgp_r_def_ms(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ guint16 bucket=0;
+ proto_item *ti=NULL;
+ proto_tree *rdefms_tree=NULL;
+
+ if (dprm_p->tree){
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ code = tvb_get_guint8(tvb,offset);
+ bucket = tvb_get_ntohs(tvb,offset+2);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u bits/sec", match_strval(code,bssgp_iei),100*bucket);
+ rdefms_tree = proto_item_add_subtree(ti, ett_rdefms_tree);
+ proto_tree_add_uint_format(rdefms_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(rdefms_tree, hf_bssgp_r_defau_ms,tvb,offset+2,len,bucket,"%s in 100 bits/sec increments: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
+ proto_tree_add_text(rdefms_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+
+/*static int dcd_bssgp_sus_ref_num(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+
+static int dcd_bssgp_tag(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0,tag=0;
+ proto_item *ti=NULL;
+ proto_tree *tag_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ tag = tvb_get_guint8(tvb,offset+2);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2,"Tag: %u", tag);
+ tag_tree = proto_item_add_subtree(ti, ett_tag_tree);
+ proto_tree_add_uint_format(tag_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_text(tag_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+
+static int dcd_bssgp_tlli(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint32 tlli;
+ guint8 len=0, code=0, disp=0;
+ proto_item *ti=NULL;
+ proto_tree *tlli_tree=NULL;
+ switch (dprm_p->type){
+ case 3:
+ disp = 0;
+ break;
+ case 4:
+ code = tvb_get_guint8(tvb, offset);
+ disp++;
+ len = tvb_get_guint8(tvb,offset+disp);
+ len = len & 0x7f;
+ disp++;
+ break;
+ }
+ tlli = tvb_get_ntohl(tvb, offset+disp);
+ if (check_col((dprm_p->pinfo)->cinfo, COL_INFO)){
+ col_append_fstr( (dprm_p->pinfo)->cinfo, COL_INFO,", TLLI: %X", tlli);
+ }
+ if (dprm_p->tree){
+ switch (dprm_p->type){
+ case 3:
+ proto_tree_add_uint_format(dprm_p->tree,hf_bssgp_tlli,tvb,offset,4,tlli,"TLLI: %#.4x", tlli );
+ break;
+ case 4:
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset,len+disp,"TLLI: %#.4x",tlli);
+ tlli_tree =proto_item_add_subtree(ti,ett_bssgp_tlli);
+ proto_tree_add_uint_format(tlli_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+
+ proto_tree_add_text(tlli_tree,tvb,offset+1,1,"Length:%u",len);
+ proto_tree_add_uint_format(tlli_tree,hf_bssgp_tlli,tvb,offset+disp,len,tlli,"TLLI: %#.4x", tlli );
+
+ }
+ }
+ return 4 + disp;
+}
+/*static int dcd_bssgp_tlli_o(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ return 6;
+};
+*/
+
+/*static int dcd_bssgp_tmsi(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+/*static int dcd_bssgp_trace_ref(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+/*static int dcd_bssgp_trace_type(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+/*static int dcd_bssgp_trans_id(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+/*static int dcd_bssgp_trig_id(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+};
+*/
+static int dcd_bssgp_num_oct_aff(tvbuff_t *tvb, int offset, dec_fu_param_stru_t *dprm_p){
+ guint8 code=0, len=0;
+ guint32 bucket=0;
+ proto_item *ti=NULL;
+ proto_tree *noaff_tree=NULL;
+
+ len = tvb_get_guint8(tvb,offset+1) & 0x7f;
+ if (dprm_p->tree){
+ code = tvb_get_guint8(tvb,offset);
+ bucket = tvb_get_ntoh24(tvb,offset+2);
+ ti = proto_tree_add_text(dprm_p->tree,tvb,offset, len+2, "%s: %u", match_strval(code,bssgp_iei), bucket);
+ noaff_tree = proto_item_add_subtree(ti, ett_noaff_tree);
+ proto_tree_add_uint_format(noaff_tree,hf_bssgp_ietype,tvb,offset,1,code,"IE type: %s %#.2x",match_strval(code,bssgp_iei),code);
+ proto_tree_add_uint_format(noaff_tree, hf_bssgp_noaff,tvb,offset+2,len,bucket,"%s: %u (%#.2x)",match_strval(code,bssgp_iei),bucket,bucket);
+ proto_tree_add_text(noaff_tree,tvb,offset+1,1,"Length:%u",len);
+ }
+return len+2;
+}
+
+
+/* Code to actually dissect the packets */
+static void
+dissect_bssgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+static dec_fu_param_stru_t decp , *decodeparam=&decp;
+guint8 pdutype, i, j , iele , stay;
+guint16 offset=1;
+tvbuff_t *next_tvb;
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti=NULL;
+ proto_tree *bssgp_tree=NULL;
+
+ pdutype=tvb_get_guint8(tvb,0);
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BSSGP");
+
+/* This field shows up as the "Info" column in the display; you should make
+ it, if possible, summarize what's in the packet, so that a user looking
+ at the list of packets can tell what type of packet it is. See section 1.5
+ for more information.
+
+ If you are setting it to a constant string, use "col_set_str()", as
+ it's more efficient than the other "col_set_XXX()" calls.
+
+ If you're setting it to a string you've constructed, or will be
+ appending to the column later, use "col_add_str()".
+
+ "col_add_fstr()" can be used instead of "col_add_str()"; it takes
+ "printf()"-like arguments. Don't use "col_add_fstr()" with a format
+ string of "%s" - just use "col_add_str()" or "col_set_str()", as it's
+ more efficient than "col_add_fstr()".
+
+ If you will be fetching any data from the packet before filling in
+ the Info column, clear that column first, in case the calls to fetch
+ data from the packet throw an exception because they're fetching data
+ past the end of the packet, so that the Info column doesn't have data
+ left over from the previous dissector; do
+*/
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_str(pinfo->cinfo, COL_INFO,match_strval(pdutype,tab_bssgp_pdu_type));
+ }
+/* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+/* if (tree) { */
+
+/* NOTE: The offset and length values in the call to
+ "proto_tree_add_item()" define what data bytes to highlight in the hex
+ display window when the line in the protocol tree display
+ corresponding to that item is selected.
+
+ tvb_length(tvb) is a handy way to highlight all data from the offset to
+ the end of the packet. */
+
+/* create display subtree for the protocol */
+/* ti = proto_tree_add_item(tree, proto_bssgp, tvb, 0, tvb_length(tvb), FALSE );
+
+ bssgp_tree = proto_item_add_subtree(ti, ett_bssgp);
+*/
+ decodeparam->pinfo=pinfo;
+ decodeparam->tree=tree;
+ i = 0;
+ stay = 1;
+ while (bssgp_pdu[i].infe[0].presence && stay){
+ if (bssgp_pdu[i].pdu == pdutype) {
+ j = 0;
+ stay = 0;
+ if (tree){
+ ti = proto_tree_add_protocol_format(tree, proto_bssgp, tvb, 0, tvb_length(tvb),"BSS GPRS protocol PDU type: %s (%#.2x)", match_strval(pdutype,tab_bssgp_pdu_type), pdutype);
+ bssgp_tree = proto_item_add_subtree(ti, ett_bssgp);
+ proto_tree_add_uint_format(bssgp_tree, hf_bssgp_pdu_type, tvb, 0, offset, pdutype, "PDU type: %s (%#.2x)",match_strval(pdutype,tab_bssgp_pdu_type), pdutype );
+ decodeparam->tree=bssgp_tree;
+ }
+ while (bssgp_pdu[i].infe[j].presence){
+ switch(bssgp_pdu[i].infe[j].type){
+ case 3:
+ decodeparam->type=3;
+ offset=offset+( *bssgp_pdu[i].infe[j].decode)(tvb, offset, decodeparam );
+ j++;
+ break;
+ case 4:
+ decodeparam->type=4;
+ if (offset >= tvb_length(tvb)) {
+ j++;
+ break;
+ }
+ iele = tvb_get_guint8( tvb, offset);
+ while ((bssgp_pdu[i].infe[j].code != iele) && bssgp_pdu[i].infe[j].presence ) {
+ if (bssgp_pdu[i].infe[j].presence > 1) j++;
+ else break;
+ }
+ if (bssgp_pdu[i].infe[j].presence){
+ offset=offset+( *bssgp_pdu[i].infe[j].decode)(tvb, offset, decodeparam );
+ if (iele == 0x0e ){
+ next_tvb = tvb_new_subset(tvb, decodeparam->k, -1, -1);
+ call_dissector(llcgprs_handle, next_tvb, pinfo, tree);
+/* call_dissector(data_handle, next_tvb, pinfo, tree);
+*/
+ }
+ j++;
+ }
+ break;
+ }
+ }
+ }
+ i++;
+ };
+
+/* add an item to the subtree, see section 1.6 for more information */
+/*
+ proto_tree_add_uint(tree, hf_bssgp_FIELDABBREV, tvb, offset, len, value);
+*/
+/* proto_tree_add_uint_format(bssgp_tree, hf_bssgp_pdu_type, tvb, 0, 1, pdutype, "PDU type: %s (%#.2x)",match_strval(pdutype,tab_bssgp_pdu_type), pdutype );
+*/
+
+/* Continue adding tree items to process the packet here */
+
+
+/* }*/
+
+/* If this protocol has a sub-dissector call it here, see section 1.8 */
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_bssgp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bssgp_pdu_type,
+ { "PDU", "bssgp.pdu",
+ FT_UINT8, BASE_HEX, VALS(tab_bssgp_pdu_type), 0x0,
+ "BSSGP PDU", HFILL }},
+ {&hf_bssgp_tlli,
+ { "TLLI","bssgp.tlli",FT_UINT32, BASE_HEX, NULL,0x0,"Current TLLI",HFILL}},
+ {&hf_bssgp_ietype,
+ {"IE Type", "bssgp.ietype", FT_UINT8, BASE_HEX, VALS(bssgp_iei),0x0,"Information element", HFILL }},
+ {&hf_bssgp_pbr,
+ {"QoS_Profile","bssgp.pbr",FT_UINT16, BASE_HEX, NULL, 0x0, "Peak bit rate",HFILL }},
+ {&hf_bssgp_qos,
+ {"Last byte QoS Profile","bssgp.qos",FT_UINT8, BASE_HEX, NULL, 0x0,"5th byte of QoS profile(contains Precedence..)",HFILL}},
+ {&hf_bssgp_qos_cr,
+ {"C/R bit","bssgp.qos.cr",FT_BOOLEAN,8, TFS(&cr_string),QOSO5CR,"The SDU contains LLC ACK/SACK command/responce frame type",HFILL }},
+ {&hf_bssgp_qos_t,
+ {"T bit", "bssgp.qos.t", FT_BOOLEAN, 8, TFS( &t_string) , QOSO5T, "The SDU contains signaling/data" , HFILL}},
+ {&hf_bssgp_qos_a,
+ {"A bit" , "bssgp.qos.a" , FT_BOOLEAN,8, TFS( &a_string), QOSO5A, "Radio interface uses ARQ/UNITDATA functionality",HFILL}},
+ {&hf_bssgp_qos_prec,
+ {"Precedence", "bssgp.qos.prec", FT_UINT8,BASE_HEX ,VALS(prec_both), 0x0,"Precedence coding", HFILL }},
+ {&hf_bssgp_pdu_lifetime,
+ {"PDU Lifetime","bssgp.lft", FT_UINT16, BASE_HEX, NULL, 0x0, "PDU Lifetime for PDU inside the BSS",HFILL}},
+ {&hf_bssgp_imsi,
+ {"IMSI","bssgp.imsi", FT_STRING, BASE_DEC, NULL, 0x0, "International Mobile Subscriber Identity",HFILL}},
+ {&hf_bssgp_imsi_toi,
+ { "Type of Mobile identity", "bssgp.mobid", FT_UINT8, BASE_HEX, VALS(type_of_identity), LOW3B, "Type of mobile identity",HFILL }},
+ {&hf_bssgp_imsi_even_odd_indic,
+ { "Odd/even indication", "bssgp.oei", FT_BOOLEAN, 8, TFS(&imsi_odd_even), ODD_EVEN_INDIC, "Odd/even indication",HFILL }},
+ {&hf_bssgp_imsi_lsix,
+ {"IMSI last ten numbers","bssgp.imsi.last10num",FT_STRING, BASE_NONE, NULL, 0x0, "Last ten numbers of IMSI",HFILL}},
+ {&hf_bssgp_bvc_buck_size,
+ {"Bmax(in 100 oct incr)","bssgp.bmax", FT_UINT16, BASE_HEX, NULL, 0x0, "BVC Bucket Size in 100 octet increments",HFILL}},
+ {&hf_bssgp_buck_leak_rate,
+ {"Bucket Leak Rate","bssgp.R", FT_UINT16, BASE_HEX, NULL, 0x0, "Bucket Leak Rate in 100 bits/sec increments",HFILL}},
+ {&hf_bssgp_bmax_def_ms,
+ {"Bmax default MS","bssgp.bmaxms", FT_UINT16, BASE_HEX, NULL, 0x0, "Default bucket size in 100 octetsincrement for an MS",HFILL}},
+ {&hf_bssgp_r_defau_ms,
+ {"R default MS","bssgp.Rms", FT_UINT16, BASE_HEX,NULL, 0x0, "Dfeault bucket leak rate to be applied to a flow control bucket for an MS", HFILL}},
+ {&hf_bssgp_bvci,
+ {"BVCI","bssgp.bvci",FT_UINT16, BASE_HEX, NULL, 0x0, "BSSGP Virtual Connection Identifier", HFILL}},
+ {&hf_bssgp_cause,
+ {"Cause","bssgp.cause", FT_UINT8, BASE_HEX, NULL,0x0, " Cause information element indicates the reason for an exception condition",HFILL }},
+ {&hf_bssgp_bvci_new,{"BVCI(New)","bssgp.bvci.new",FT_UINT16, BASE_HEX, NULL, 0x0, "BSSGP Virtual Connection Identifier", HFILL}},
+ {&hf_bssgp_frdsc,
+ {"LLC frames discarded","bssgp.llcdisc.frames", FT_UINT8, BASE_HEX, NULL, 0x0,"LLC frames that have been discarded inside BSS", HFILL}},
+ {&hf_bssgp_noaff,
+ {"Number of octets affected","bssgp.noaff", FT_UINT24, BASE_HEX,NULL,0x0,"It indicates,for MS,the number of octets transferred or deleted by BSS",HFILL}},
+ {&hf_bssgp_radio_cause,
+ {"Radio Cause","bssgp.racase", FT_UINT8, BASE_HEX, NULL, 0x0, "Reason for an exception condition on the radio interface",HFILL}},
+ {&hf_bssgp_ra_mccmnc,
+ {"MCC and MNC","bssgp.ra.mccmnc", FT_STRING, BASE_DEC, NULL, 0x0, "Mobile country code and Mobile network code", HFILL}},
+ {&hf_bssgp_ra_lac,
+ {"LAC","bssgp.ra.lac",FT_UINT16, BASE_HEX, NULL, 0x0, "Location area code",HFILL }},
+ {&hf_bssgp_ra_rac,
+ {"RAC","bssgp.ra.rac",FT_UINT8, BASE_HEX, NULL, 0x0, "Routing area code", HFILL }},
+ {&hf_bssgp_cid,
+ {"Cell id","bssgp.cid",FT_UINT16, BASE_HEX, NULL, 0x0, "Cell identity", HFILL }},
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_bssgp,
+ &ett_bssgp_tlli,
+ &ett_bssgp_qos,
+ &ett_bssgp_o5,
+ &ett_bssgp_lft,
+ &ett_bssgp_racc,
+ &ett_prio_tree,
+ &ett_drx_tree,
+ &ett_bssgp_imsi,
+ &ett_bssgp_imsi_stru_tree,
+ &ett_algn_tree,
+ &ett_b_llc_tree,
+ &ett_celid_tree,
+ &ett_tag_tree,
+ &ett_bsize_tree,
+ &ett_bucklr_tree,
+ &ett_bmaxms_tree,
+ &ett_rdefms_tree,
+ &ett_bvci_tree,
+ &ett_bvcin_tree,
+ &ett_cause_tree,
+ &ett_frdsc_tree,
+ &ett_noaff_tree,
+ &ett_racaus_tree,
+ &ett_ra_tree
+ };
+
+/* Register the protocol name and description */
+ proto_bssgp = proto_register_protocol("BSS GPRS Protocol",
+ "BSSGP", "bssgp");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_bssgp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("bssgp", dissect_bssgp, proto_bssgp);
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_bssgp(void)
+{
+/* dissector_handle_t bssgp_handle;
+
+ bssgp_handle = create_dissector_handle(dissect_bssgp,
+ proto_bssgp);
+*/
+/* dissector_add("fr.nspduname", NS_UNITDATA, bssgp_handle);*/
+/* dissector_add("fr.nspduname", 0x0, bssgp_handle);
+*/
+/* dissector_add("fr.ietf", 0x0, bssgp_handle);
+*/
+/* data_handle = find_dissector("data");
+*/
+ llcgprs_handle = find_dissector ("llcgprs");
+}
diff --git a/epan/dissectors/packet-bvlc.c b/epan/dissectors/packet-bvlc.c
new file mode 100644
index 0000000000..16a703d1e5
--- /dev/null
+++ b/epan/dissectors/packet-bvlc.c
@@ -0,0 +1,401 @@
+/* packet-bvlc.c
+ * Routines for BACnet/IP (BVLL, BVLC) dissection
+ * Copyright 2001, Hartmut Mueller <hartmut@abmlinux.org>, FH Dortmund
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer,v 1.23
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "prefs.h"
+#include <epan/strutil.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+static int proto_bvlc = -1;
+static int hf_bvlc_type = -1;
+static int hf_bvlc_function = -1;
+static int hf_bvlc_length = -1;
+static int hf_bvlc_result = -1;
+static int hf_bvlc_bdt_ip = -1;
+static int hf_bvlc_bdt_mask = -1;
+static int hf_bvlc_bdt_port = -1;
+static int hf_bvlc_reg_ttl = -1;
+static int hf_bvlc_fdt_ip = -1;
+static int hf_bvlc_fdt_port = -1;
+static int hf_bvlc_fdt_ttl = -1;
+static int hf_bvlc_fdt_timeout = -1;
+static int hf_bvlc_fwd_ip = -1;
+static int hf_bvlc_fwd_port = -1;
+
+static dissector_handle_t data_handle;
+
+static dissector_table_t bvlc_dissector_table;
+
+static const value_string bvlc_function_names[] = {
+ { 0x00, "BVLC-Result", },
+ { 0x01, "Write-Broadcast-Distribution-Table", },
+ { 0x02, "Read-Broadcast-Distribution-Table", },
+ { 0x03, "Read-Broadcast-Distribution-Table-Ack", },
+ { 0x04, "Forwarded-NPDU", },
+ { 0x05, "Register-Foreign-Device", },
+ { 0x06, "Read-Foreign-Device-Table", },
+ { 0x07, "Read-Foreign-Device-Table-Ack", },
+ { 0x08, "Delete-Foreign-Device-Table-Entry", },
+ { 0x09, "Distribute-Broadcast-To-Network", },
+ { 0x0a, "Original-Unicast-NPDU", },
+ { 0x0b, "Original-Broadcast-NPDU" },
+ { 0, NULL }
+};
+
+static const value_string bvlc_result_names[] = {
+ { 0x00, "Successful completion" },
+ { 0x10, "Write-Broadcast-Distribution-Table NAK" },
+ { 0x20, "Read-Broadcast-Distribution-Table NAK" },
+ { 0x30, "Register-Foreign-Device NAK" },
+ { 0x40, "Read-Foreign-Device-Table NAK" },
+ { 0x50, "Delete-Foreign-Device-Table-Entry NAK" },
+ { 0x60, "Distribute-Broadcast-To-Network NAK" },
+ { 0, NULL }
+};
+
+static gint ett_bvlc = -1;
+static gint ett_bdt = -1;
+static gint ett_fdt = -1;
+
+static void
+dissect_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ proto_item *ti;
+ proto_item *ti_bdt;
+ proto_item *ti_fdt;
+ proto_tree *bvlc_tree;
+ proto_tree *bdt_tree; /* Broadcast Distribution Table */
+ proto_tree *fdt_tree; /* Foreign Device Table */
+
+ gint offset;
+ guint8 bvlc_type;
+ guint8 bvlc_function;
+ guint16 bvlc_length;
+ guint16 packet_length;
+ guint npdu_length;
+ guint16 bvlc_result;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BVLC");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "BACnet Virtual Link Control");
+
+ offset = 0;
+
+ bvlc_type = tvb_get_guint8(tvb, offset);
+ bvlc_function = tvb_get_guint8(tvb, offset+1);
+ packet_length = tvb_get_ntohs(tvb, offset+2);
+ if (bvlc_function > 0x08) {
+ /* We have a constant header length of BVLC of 4 in every
+ * BVLC-packet forewarding an NPDU. Beware: Changes in the
+ * BACnet-IP-standard may break this.
+ * At the moment, no functions above 0x0b
+ * exist (Addendum 135a to ANSI/ASHRAE 135-1995 - BACnet)
+ */
+ bvlc_length = 4;
+ } else if(bvlc_function == 0x04) {
+ /* 4 Bytes + 6 Bytes for B/IP Address of Originating Device */
+ bvlc_length = 10;
+ } else {
+ /* BVLC-packets with function below 0x09 contain
+ * routing-level data (e.g. Broadcast Distribution)
+ * but no NPDU for BACnet, so bvlc_length goes up to the end
+ * of the captured frame.
+ */
+ bvlc_length = packet_length;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_bvlc, tvb, 0,
+ bvlc_length, FALSE);
+ bvlc_tree = proto_item_add_subtree(ti, ett_bvlc);
+ proto_tree_add_uint_format(bvlc_tree, hf_bvlc_type, tvb, offset, 1,
+ bvlc_type,"Type: 0x%x (Version %s)",bvlc_type,
+ (bvlc_type == 0x81)?"BACnet/IP (Annex J)":"unknown");
+ offset ++;
+ proto_tree_add_uint_format(bvlc_tree, hf_bvlc_function, tvb,
+ offset, 1, bvlc_function,"Function: 0x%02x (%s)",
+ bvlc_function, val_to_str (bvlc_function,
+ bvlc_function_names, "Unknown"));
+ offset ++;
+ proto_tree_add_uint_format(bvlc_tree, hf_bvlc_length, tvb, offset,
+ 2, bvlc_length, "BVLC-Length: %d of %d bytes BACnet packet length",
+ bvlc_length, packet_length);
+ offset += 2;
+ switch (bvlc_function) {
+ case 0x00: /* BVLC-Result */
+ bvlc_result = tvb_get_ntohs(tvb, offset);
+ /* I dont know why the result code is encoded in 4 nibbles,
+ * but only using one: 0x00r0. Shifting left 4 bits.
+ */
+ /* We should bitmask the result correctly when we have a
+ * packet to dissect, see README.developer, 1.6.2, FID */
+ proto_tree_add_uint_format(bvlc_tree, hf_bvlc_result, tvb,
+ offset, 2, bvlc_result,"Result: 0x%04x (%s)",
+ bvlc_result, val_to_str(bvlc_result << 4,
+ bvlc_result_names, "Unknown"));
+ offset += 2;
+ break;
+ case 0x01: /* Write-Broadcast-Distribution-Table */
+ case 0x03: /* Read-Broadcast-Distribution-Table-Ack */
+ /* List of BDT Entries: N*10-octet */
+ ti_bdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
+ offset, bvlc_length-4, FALSE);
+ bdt_tree = proto_item_add_subtree(ti_bdt, ett_bdt);
+ /* List of BDT Entries: N*10-octet */
+ while ((bvlc_length - offset) > 9) {
+ proto_tree_add_item(bdt_tree, hf_bvlc_bdt_ip,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(bdt_tree, hf_bvlc_bdt_port,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(bdt_tree,
+ hf_bvlc_bdt_mask, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ }
+ /* We check this if we get a BDT-packet somewhere */
+ break;
+ case 0x02: /* Read-Broadcast-Distribution-Table */
+ /* nothing to do here */
+ break;
+ case 0x05: /* Register-Foreign-Device */
+ /* Time-to-Live 2-octets T, Time-to-Live T, in seconds */
+ proto_tree_add_item(bvlc_tree, hf_bvlc_reg_ttl,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+ case 0x06: /* Read-Foreign-Device-Table */
+ /* nothing to do here */
+ break;
+ case 0x07: /* Read-Foreign-Device-Table-Ack */
+ /* List of FDT Entries: N*10-octet */
+ /* N indicates the number of entries in the FDT whose
+ * contents are being returned. Each returned entry
+ * consists of the 6-octet B/IP address of the registrant;
+ * the 2-octet Time-to-Live value supplied at the time of
+ * registration; and a 2-octet value representing the
+ * number of seconds remaining before the BBMD will purge
+ * the registrant's FDT entry if no re-registration occurs.
+ */
+ ti_fdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
+ offset, bvlc_length -4, FALSE);
+ fdt_tree = proto_item_add_subtree(ti_fdt, ett_fdt);
+ /* List of FDT Entries: N*10-octet */
+ while ((bvlc_length - offset) > 9) {
+ proto_tree_add_item(fdt_tree, hf_bvlc_fdt_ip,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(fdt_tree, hf_bvlc_fdt_port,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(fdt_tree,
+ hf_bvlc_fdt_ttl, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ proto_tree_add_item(fdt_tree,
+ hf_bvlc_fdt_timeout, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ }
+ /* We check this if we get a FDT-packet somewhere */
+ break;
+ case 0x08: /* Delete-Foreign-Device-Table-Entry */
+ /* FDT Entry: 6-octets */
+ proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_ip,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_port,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+ /* We check this if we get a FDT-packet somewhere */
+ case 0x04: /* Forwarded-NPDU
+ * Why is this 0x04? It would have been a better
+ * idea to append all forewarded NPDUs at the
+ * end of the function table in the B/IP-standard!
+ */
+ /* proto_tree_add_bytes_format(); */
+ proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_ip,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_port,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ default:/* Distribute-Broadcast-To-Network
+ * Original-Unicast-NPDU
+ * Original-Broadcast-NPDU
+ * Going to the next dissector...
+ */
+ break;
+ }
+
+ }
+/* Ok, no routing information BVLC packet. Dissect as
+ * BACnet NPDU
+ */
+ npdu_length = packet_length - bvlc_length;
+ next_tvb = tvb_new_subset(tvb,bvlc_length,-1,npdu_length);
+ /* Code from Guy Harris */
+ if (!dissector_try_port(bvlc_dissector_table,
+ bvlc_function, next_tvb, pinfo, tree)) {
+ /* Unknown function - dissect the paylod as data */
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+}
+
+void
+proto_register_bvlc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bvlc_type,
+ { "Type", "bvlc.type",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Type", HFILL }
+ },
+ { &hf_bvlc_function,
+ { "Function", "bvlc.function",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "BLVC Function", HFILL }
+ },
+ { &hf_bvlc_length,
+ { "Length", "bvlc.length",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Length of BVLC", HFILL }
+ },
+ /* We should bitmask the result correctly when we have a
+ * packet to dissect */
+ { &hf_bvlc_result,
+ { "Result", "bvlc.result",
+ FT_UINT16, BASE_HEX, NULL, 0xffff,
+ "Result Code", HFILL }
+ },
+ { &hf_bvlc_bdt_ip,
+ { "IP", "bvlc.bdt_ip",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "BDT IP", HFILL }
+ },
+ { &hf_bvlc_bdt_port,
+ { "Port", "bvlc.bdt_port",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "BDT Port", HFILL }
+ },
+ { &hf_bvlc_bdt_mask,
+ { "Mask", "bvlc.bdt_mask",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "BDT Broadcast Distribution Mask", HFILL }
+ },
+ { &hf_bvlc_reg_ttl,
+ { "TTL", "bvlc.reg_ttl",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Foreign Device Time To Live", HFILL }
+ },
+ { &hf_bvlc_fdt_ip,
+ { "IP", "bvlc.fdt_ip",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "FDT IP", HFILL }
+ },
+ { &hf_bvlc_fdt_port,
+ { "Port", "bvlc.fdt_port",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "FDT Port", HFILL }
+ },
+ { &hf_bvlc_fdt_ttl,
+ { "TTL", "bvlc.fdt_ttl",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Foreign Device Time To Live", HFILL }
+ },
+ { &hf_bvlc_fdt_timeout,
+ { "Timeout", "bvlc.fdt_timeout",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Foreign Device Timeout (seconds)", HFILL }
+ },
+ { &hf_bvlc_fwd_ip,
+ { "IP", "bvlc.fwd_ip",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "FWD IP", HFILL }
+ },
+ { &hf_bvlc_fwd_port,
+ { "Port", "bvlc.fwd_port",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "FWD Port", HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_bvlc,
+ &ett_bdt,
+ &ett_fdt,
+ };
+
+ proto_bvlc = proto_register_protocol("BACnet Virtual Link Control",
+ "BVLC", "bvlc");
+
+ proto_register_field_array(proto_bvlc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("bvlc", dissect_bvlc, proto_bvlc);
+
+ bvlc_dissector_table = register_dissector_table("bvlc.function",
+ "BVLC Function", FT_UINT8, BASE_HEX);
+}
+
+void
+proto_reg_handoff_bvlc(void)
+{
+ dissector_handle_t bvlc_handle;
+
+ bvlc_handle = find_dissector("bvlc");
+ dissector_add("udp.port", 0xBAC0, bvlc_handle);
+ data_handle = find_dissector("data");
+}
+/* Taken from add-135a (BACnet-IP-standard paper):
+ *
+ * The default UDP port for both directed messages and broadcasts shall
+ * be X'BAC0' and all B/IP devices shall support it. In some cases,
+ * e.g., a situation where it is desirable for two groups of BACnet devices
+ * to coexist independently on the same IP subnet, the UDP port may be
+ * configured locally to a different value without it being considered
+ * a violation of this protocol.
+ *
+ * This dissector does not analyse UDP packets other than on port 0xBAC0.
+ * If you changed your BACnet port locally, use the ethereal feature
+ * "Decode As".
+ */
diff --git a/epan/dissectors/packet-cast.c b/epan/dissectors/packet-cast.c
new file mode 100644
index 0000000000..2c1d36a0bb
--- /dev/null
+++ b/epan/dissectors/packet-cast.c
@@ -0,0 +1,1776 @@
+/* packet-cast.c
+ *
+ * Dissector for the CAST Client Control Protocol
+ * (The "D-Channel"-Protocol for Cisco Systems' IP-Phones)
+ *
+ * $Id$
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This implementation is based on a draft version of the 3.0
+ * specification
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include <epan/packet.h>
+#include "prefs.h"
+
+#include "packet-tcp.h"
+
+#define TCP_PORT_CAST 4224
+
+
+/* I will probably need this again when I change things
+ * to function pointers, but let me use the existing
+ * infrastructure for now
+ *
+ * typedef struct {
+ * guint32 id;
+ * char * name;
+ * } message_id_t;
+ */
+
+static const value_string message_id[] = {
+
+ {0x0000, "KeepAliveMessage"},
+ {0x0001, "KeepAliveVersionMessage"},
+ {0x0002, "KeepAliveVersionACKMessage"},
+ {0x0003, "UpdateCapabilitiesMessage"},
+ {0x0004, "EmptyCapabilitiesMessage"},
+ {0x0005, "OpenMultiMediaReceiveChannelMessage"},
+ {0x0006, "OpenMultiMediaReceiveChannelACKMessage"},
+ {0x0007, "CloseMultiMediaReceiveChannelMessage"},
+ {0x0008, "StartMultiMediaTransmissionMessage"},
+ {0x0009, "StopMultiMediaTransmissionMessage"},
+ {0x000A, "MiscellaneousCommandMessage"},
+ {0x000B, "FlowControlCommandMessage"},
+ {0x000C, "ClearConferenceMessage"},
+ {0x000D, "CallStateMessage"},
+ {0x000E, "RequestCallStateMessage"},
+ {0x000F, "RequestAllCallStatesMessage"},
+ {0x0010, "CallInfoMessage"},
+ {0x0011, "RequestCallInfoMessage"},
+ {0x0012, "CallFocusMessage"},
+ {0x0013, "MakeCallMessage"},
+ {0x0014, "HangUpMessage"},
+ {0x0015, "AnswerMessage"},
+
+ {0x0040, "KeepAliveACKMessage"},
+ {0x0041, "StreamStartMessage"},
+ {0x0042, "StreamStopMessage"},
+ {0x0043, "MuteStartMessage"},
+ {0x0044, "MuteStopMessage"},
+ {0x0045, "SpeakerStartMessage"},
+ {0x0046, "SpeakerStopMessage"},
+ {0x0047, "StreamStartMessageWithCodec"},
+
+ {0x0050, "VIEODiscoveryprotocol"},
+ {0x0051, "VIEOControlprotocol"},
+
+ {0x0060, "T120protocol"},
+ {0x0061, "T121protocol"},
+ {0x0062, "T122protocol"},
+
+ {0x0070, "IMSessionDiscoveryprotocol"},
+ {0x0071, "IMSessionControlprotocol"},
+
+ {0x0074, "SlidesDiscoveryprotocol"},
+ {0x0075, "SlidesControlprotocol"},
+
+ {0x0080, "CastTunnelMessage"},
+
+ {0x0090, "RemoteRequestMessage"},
+ {0x0091, "RemoteResponseMessage"},
+
+ {0x00A0, "CollabDiscoveryprotocol"},
+ {0x00A1, "CollabControlprotocol"},
+
+ {0x00A4, "FECCDiscoveryprotocol"},
+ {0x00A5, "FECCControlprotocol"},
+
+ {0x00B0, "ClockSyncprotocol"},
+ {0x00B1, "StreamSyncprotocol"},
+
+ {0x00B4, "MediaDiscoveryprotocol"},
+ {0x00B5, "MediaControlprotocol"},
+
+ {0x00C0, "SessionDiscoveryprotocol"},
+ {0x00C1, "SessionControlprotocol"},
+
+ {0x00C4, "ConferenceDiscoveryprotocol"},
+ {0x00C5, "Conferenceprotocol"},
+
+ {0x00CC, "SCCPCallControlProxyprotocol"},
+
+ {0x00D0, "CallDiscoveryprotocol"},
+ {0x00D1, "CallControlprotocol"},
+
+ {0 , NULL} /* terminator */
+};
+
+static const value_string audioCodecTypes[] = {
+ {1 , "G711"},
+ {1 , "G729"},
+ {2 , "GSM"},
+ {3 , "G723"},
+ {4 , "G722"},
+ {5 , "WideBand"},
+ { 0 , NULL}
+};
+
+static const value_string orcStatus[] = {
+ {0 , "orcOk"},
+ {1 , "orcError"},
+ {0 , NULL}
+};
+
+static const value_string mediaPayloads[] = {
+ {1 , "Non-standard codec"},
+ {2 , "G.711 A-law 64k"},
+ {3 , "G.711 A-law 56k"},
+ {4 , "G.711 u-law 64k"},
+ {5 , "G.711 u-law 56k"},
+ {6 , "G.722 64k"},
+ {7 , "G.722 56k"},
+ {8 , "G.722 48k"},
+ {9 , "G.723.1"},
+ {10 , "G.728"},
+ {11 , "G.729"},
+ {12 , "G.729 Annex A"},
+ {13 , "IS11172 AudioCap"}, /* IS11172 is an ISO MPEG standard */
+ {14 , "IS13818 AudioCap"}, /* IS13818 is an ISO MPEG standard */
+ {15 , "G.729 Annex B"},
+ {16 , "G.729 Annex A+Annex B"},
+ {18 , "GSM Full Rate"},
+ {19 , "GSM Half Rate"},
+ {20 , "GSM Enhanced Full Rate"},
+ {25 , "Wideband 256k"},
+ {32 , "Data 64k"},
+ {33 , "Data 56k"},
+ {80 , "GSM"},
+ {81 , "ActiveVoice"},
+ {82 , "G.726 32K"},
+ {83 , "G.726 24K"},
+ {84 , "G.726 16K"},
+ {85 , "G.729B"},
+ {86 , "G.729B Low Complexity"},
+ {100 , "H261"},
+ {101 , "H263"},
+ {102 , "Vieo"},
+ {105 , "T120"},
+ {106 , "H224"},
+ {257 , "RFC2833_DynPayload"},
+ {0 , NULL}
+};
+
+static const value_string cast_Layouts[] = {
+ {0 , "NoLayout"},
+ {1 , "OneByOne"},
+ {2 , "OneByTwo"},
+ {3 , "TwoByTwo"},
+ {4 , "TwoByTwo3Alt1"},
+ {5 , "TwoByTwo3Alt2"},
+ {6 , "ThreeByThree"},
+ {7 , "ThreeByThree6Alt1"},
+ {8 , "ThreeByThree6Alt2"},
+ {9 , "ThreeByThree4Alt1"},
+ {10 , "ThreeByThree4Alt2"},
+ {0 , NULL}
+};
+
+static const value_string cast_transmitOrReceive[] = {
+ {1 , "Station_Receive_only"},
+ {2 , "Station_Transmit_only"},
+ {3 , "Station_Receive_Transmit"},
+ {0 , NULL}
+};
+
+static const value_string cast_formatTypes[] = {
+ {1 , "sqcif (128x96)"},
+ {2 , "qcif (176x144)"},
+ {3 , "cif (352x288)"},
+ {4 , "4cif (704x576)"},
+ {5 , "16cif (1408x1152)"},
+ {6 , "custom_base"},
+ {0 , NULL}
+};
+
+static const value_string cast_echoCancelTypes[] = {
+ {0 , "Media_EchoCancellation_Off"},
+ {1 , "Media_EchoCancellation_On"},
+ {0 , NULL}
+};
+
+static const value_string cast_g723BitRates[] = {
+ {1 , "Media_G723BRate_5_3"},
+ {2 , "Media_G723BRate_6_4"},
+ {0 , NULL}
+};
+
+static const value_string cast_miscCommandType[] = {
+ {0 , "videoFreezePicture"},
+ {1 , "videoFastUpdatePicture"},
+ {2 , "videoFastUpdateGOB"},
+ {3 , "videoFastUpdateMB"},
+ {4 , "lostPicture"},
+ {5 , "lostPartialPicture"},
+ {6 , "recoveryReferencePicture"},
+ {7 , "temporalSpatialTradeOff"},
+ {0 , NULL}
+};
+
+static const value_string cast_callStateTypes[] = {
+ {0 , "TsIdle"},
+ {1 , "TsOffHook"},
+ {2 , "TsOnHook"},
+ {3 , "TsRingOut"},
+ {4 , "TsRingIn"},
+ {5 , "TsConnected"},
+ {6 , "TsBusy"},
+ {7 , "TsCongestion"},
+ {8 , "TsHold"},
+ {9 , "TsCallWaiting"},
+ {10 , "TsCallTransfer"},
+ {11 , "TsCallPark"},
+ {12 , "TsProceed"},
+ {13 , "TsCallRemoteMultiline"},
+ {14 , "TsInvalidNumber"},
+ {15 , "TsMaxState"},
+ {0 , NULL}
+};
+
+/* Defined Call Type */
+static const value_string cast_callTypes[] = {
+ {1 , "InBoundCall"},
+ {2 , "OutBoundCall"},
+ {3 , "ForwardCall"},
+ {0 , NULL}
+};
+
+static const value_string cast_callSecurityStatusTypes[] = {
+ {0 , "CallSecurityStatusUnknown"},
+ {1 , "CallSecurityStatusNotAuthenticated"},
+ {2 , "CallSecurityStatusAuthenticated"},
+ {0 , NULL}
+};
+
+
+#define MAX_CUSTOM_PICTURES 6
+#define MAX_SERVICE_TYPE 4
+#define MAX_LAYOUT_WITH_SAME_SERVICE 5
+#define MAX_PICTURE_FORMAT 5
+#define MAX_REFERENCE_PICTURE 4
+#define MAX_LEVEL_PREFERENCE 4
+#define StationMaxVideoCapabilities 10
+#define StationMaxDataCapabilities 5
+#define StationMaxNameSize 40 /* max size of calling party's name */
+#define StationMaxDirnumSize 24 /* max size of calling or called party dirnum */
+
+
+static void dissect_cast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/* Initialize the protocol and registered fields */
+static int proto_cast = -1;
+static int hf_cast_data_length = -1;
+static int hf_cast_reserved = -1;
+static int hf_cast_messageid = -1;
+static int hf_cast_version = -1;
+static int hf_cast_ORCStatus = -1;
+static int hf_cast_ipAddress = -1;
+static int hf_cast_portNumber = -1;
+static int hf_cast_passThruPartyID = -1;
+static int hf_cast_callIdentifier = -1;
+static int hf_cast_conferenceID = -1;
+static int hf_cast_payloadType = -1;
+static int hf_cast_lineInstance = -1;
+static int hf_cast_payloadCapability = -1;
+static int hf_cast_isConferenceCreator = -1;
+static int hf_cast_payload_rfc_number = -1;
+static int hf_cast_videoCapCount = -1;
+static int hf_cast_dataCapCount = -1;
+static int hf_cast_RTPPayloadFormat = -1;
+static int hf_cast_customPictureFormatCount = -1;
+static int hf_cast_pictureWidth = -1;
+static int hf_cast_pictureHeight = -1;
+static int hf_cast_pixelAspectRatio = -1;
+static int hf_cast_clockConversionCode = -1;
+static int hf_cast_clockDivisor = -1;
+static int hf_cast_activeStreamsOnRegistration = -1;
+static int hf_cast_maxBW = -1;
+static int hf_cast_serviceResourceCount = -1;
+static int hf_cast_layoutCount = -1;
+static int hf_cast_layout = -1;
+static int hf_cast_maxConferences = -1;
+static int hf_cast_activeConferenceOnRegistration = -1;
+static int hf_cast_transmitOrReceive = -1;
+static int hf_cast_levelPreferenceCount = -1;
+static int hf_cast_transmitPreference = -1;
+static int hf_cast_format = -1;
+static int hf_cast_maxBitRate = -1;
+static int hf_cast_minBitRate = -1;
+static int hf_cast_MPI = -1;
+static int hf_cast_serviceNumber = -1;
+static int hf_cast_temporalSpatialTradeOffCapability = -1;
+static int hf_cast_stillImageTransmission = -1;
+static int hf_cast_h263_capability_bitfield = -1;
+static int hf_cast_annexNandWFutureUse = -1;
+static int hf_cast_modelNumber = -1;
+static int hf_cast_bandwidth = -1;
+static int hf_cast_protocolDependentData = -1;
+static int hf_cast_DSCPValue = -1;
+static int hf_cast_serviceNum = -1;
+static int hf_cast_precedenceValue = -1;
+static int hf_cast_maxStreams = -1;
+static int hf_cast_millisecondPacketSize = -1;
+static int hf_cast_echoCancelType = -1;
+static int hf_cast_g723BitRate = -1;
+static int hf_cast_bitRate = -1;
+static int hf_cast_pictureFormatCount = -1;
+static int hf_cast_confServiceNum = -1;
+static int hf_cast_miscCommandType = -1;
+static int hf_cast_temporalSpatialTradeOff = -1;
+static int hf_cast_firstGOB = -1;
+static int hf_cast_numberOfGOBs = -1;
+static int hf_cast_firstMB = -1;
+static int hf_cast_numberOfMBs = -1;
+static int hf_cast_pictureNumber = -1;
+static int hf_cast_longTermPictureIndex = -1;
+static int hf_cast_recoveryReferencePictureCount = -1;
+static int hf_cast_calledParty = -1;
+static int hf_cast_privacy = -1;
+static int hf_cast_precedenceLv = -1;
+static int hf_cast_precedenceDm = -1;
+static int hf_cast_callState = -1;
+static int hf_cast_callingPartyName = -1;
+static int hf_cast_callingParty = -1;
+static int hf_cast_calledPartyName = -1;
+static int hf_cast_callType = -1;
+static int hf_cast_originalCalledPartyName = -1;
+static int hf_cast_originalCalledParty = -1;
+static int hf_cast_lastRedirectingPartyName = -1;
+static int hf_cast_lastRedirectingParty = -1;
+static int hf_cast_cgpnVoiceMailbox = -1;
+static int hf_cast_cdpnVoiceMailbox = -1;
+static int hf_cast_originalCdpnVoiceMailbox = -1;
+static int hf_cast_lastRedirectingVoiceMailbox = -1;
+static int hf_cast_originalCdpnRedirectReason = -1;
+static int hf_cast_lastRedirectingReason = -1;
+static int hf_cast_callInstance = -1;
+static int hf_cast_callSecurityStatus = -1;
+static int hf_cast_directoryNumber = -1;
+static int hf_cast_requestorIpAddress = -1;
+static int hf_cast_stationIpAddress = -1;
+static int hf_cast_stationFriendlyName = -1;
+static int hf_cast_stationGUID = -1;
+static int hf_cast_audio = -1;
+
+
+
+/* Initialize the subtree pointers */
+static gint ett_cast = -1;
+static gint ett_cast_tree = -1;
+
+/* desegmentation of SCCP */
+static gboolean cast_desegment = TRUE;
+
+static dissector_handle_t data_handle;
+
+/* Dissect a single CAST PDU */
+static void dissect_cast_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+
+ /* Header fields */
+ guint32 hdr_data_length;
+ guint32 hdr_marker;
+ guint32 data_messageid;
+ gchar *messageid_str;
+ /* guint32 data_size; */
+
+ guint i = 0;
+ guint t = 0;
+ int count;
+ int val;
+
+ /* Set up structures we will need to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *cast_tree = NULL;
+ proto_item *ti_sub;
+ proto_tree *cast_sub_tree;
+ proto_tree *cast_sub_tree_sav;
+ proto_tree *cast_sub_tree_sav_sav;
+
+ hdr_data_length = tvb_get_letohl(tvb, offset);
+ hdr_marker = tvb_get_letohl(tvb, offset+4);
+ data_messageid = tvb_get_letohl(tvb, offset+8);
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items. */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cast, tvb, offset, hdr_data_length+8, FALSE);
+ cast_tree = proto_item_add_subtree(ti, ett_cast);
+ proto_tree_add_uint(cast_tree, hf_cast_data_length, tvb, offset, 4, hdr_data_length);
+ proto_tree_add_uint(cast_tree, hf_cast_reserved, tvb, offset+4, 4, hdr_marker);
+ }
+
+ messageid_str = val_to_str(data_messageid, message_id, "0x%08X (Unknown)");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, messageid_str);
+ }
+
+ if (tree) {
+ proto_tree_add_uint(cast_tree, hf_cast_messageid, tvb,offset+8, 4, data_messageid );
+ }
+
+ if (tree) {
+ switch(data_messageid) {
+
+ case 0x0 : /* keepAlive */
+ /* no data in message */
+ break;
+
+ case 0x1 : /* KeepAliveVersion */
+ proto_tree_add_item(cast_tree, hf_cast_version, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x2 : /* KeepAliveVersionAck */
+ proto_tree_add_item(cast_tree, hf_cast_version, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x3 : /* UpdateCapabilities */
+ /* to do - this message is very large and will span multiple packets, it would be nice to someday */
+ /* find out a way to join the next packet and get the complete message to decode */
+ proto_tree_add_item(cast_tree, hf_cast_videoCapCount, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_dataCapCount, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_RTPPayloadFormat, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_customPictureFormatCount, tvb, offset+24, 4, TRUE);
+ count = offset+28;
+ /* total of 120 bytes */
+ for ( i = 0; i < MAX_CUSTOM_PICTURES; i++ ) {
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 20, "customPictureFormat[%d]", i);
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_pictureWidth, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_pictureHeight, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_pixelAspectRatio, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_clockConversionCode, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_clockDivisor, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 8, "confResources");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_activeStreamsOnRegistration, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_maxBW, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_serviceResourceCount, tvb, count, 4, TRUE);
+ count+= 4;
+ cast_sub_tree_sav = cast_sub_tree;
+ /* total of 160 bytes */
+ for ( i = 0; i < MAX_SERVICE_TYPE; i++ ) {
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 20, "serviceResource[%d]", i);
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_layoutCount, tvb, count, 4, TRUE);
+ count+= 4;
+ cast_sub_tree_sav_sav = cast_sub_tree_sav;
+ for ( t = 0; t < MAX_LAYOUT_WITH_SAME_SERVICE; t++ ) {
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 20, "layouts[%d]", t);
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_layout, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ cast_sub_tree = cast_sub_tree_sav_sav;
+ proto_tree_add_item(cast_sub_tree, hf_cast_serviceNum, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_maxStreams, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_maxConferences, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_activeConferenceOnRegistration, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ /* total of 176 bytes */
+ for ( i = 0; i < StationMaxVideoCapabilities; i++ ) {
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 20, "vidCaps[%d]", i);
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_payloadCapability, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_transmitOrReceive, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_levelPreferenceCount, tvb, count, 4, TRUE);
+ count+= 4;
+ cast_sub_tree_sav = cast_sub_tree;
+ for ( t = 0; t < MAX_LEVEL_PREFERENCE; t++ ) {
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 20, "levelPreference[%d]", t);
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_transmitPreference, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_format, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_maxBitRate, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_minBitRate, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_MPI, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_serviceNumber, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+
+ /* H.261 */
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "h261VideoCapability");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_temporalSpatialTradeOffCapability, tvb, count, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_stillImageTransmission, tvb, count+4, 4, TRUE);
+
+ /* H.263 */
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "h263VideoCapability");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_h263_capability_bitfield, tvb, count, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_annexNandWFutureUse, tvb, count+4, 4, TRUE);
+
+ /* Vieo */
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "vieoVideoCapability");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_modelNumber, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_bandwidth, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ /* total 80 bytes */
+ for ( i = 0; i < StationMaxDataCapabilities; i++ ) {
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 20, "dataCaps[%d]", i);
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_payloadCapability, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_transmitOrReceive, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_protocolDependentData, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_maxBitRate, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ break;
+
+ case 0x4 : /* */
+ break;
+
+ case 0x5 : /* OpenMultiMediaReceiveChannel */
+ proto_tree_add_item(cast_tree, hf_cast_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_payloadCapability, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_lineInstance, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_payload_rfc_number, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_payloadType, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_isConferenceCreator, tvb, offset+40, 4, TRUE);
+
+ /* add audio part of union */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 12, "audioParameters");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_millisecondPacketSize, tvb, offset+44, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_echoCancelType, tvb, offset+48, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_g723BitRate, tvb, offset+52, 4, TRUE);
+
+ /* add video part of union */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 30, "videoParameters");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_bitRate, tvb, offset+44, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_pictureFormatCount, tvb, offset+48, 4, TRUE);
+ cast_sub_tree_sav = cast_sub_tree;
+ count = offset+52;
+ for ( i = 0; i < MAX_PICTURE_FORMAT; i++ ) {
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8 * MAX_PICTURE_FORMAT, "pictureFormat[%d]", i);
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_format, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_MPI, tvb, count, 4, TRUE);
+ count += 4;
+ }
+ cast_sub_tree = cast_sub_tree_sav;
+ proto_tree_add_item(cast_sub_tree, hf_cast_confServiceNum, tvb, count, 4, TRUE);
+ count += 4;
+
+ /* add H261 part of union */
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "h261VideoCapability");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_temporalSpatialTradeOffCapability, tvb, count, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_stillImageTransmission, tvb, count+4, 4, TRUE);
+
+ /* add H263 part of union */
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "h263VideoCapability");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_h263_capability_bitfield, tvb, count, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_annexNandWFutureUse, tvb, count+4, 4, TRUE);
+
+ /* add Vieo part of union */
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "vieoVideoCapability");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_modelNumber, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_bandwidth, tvb, count, 4, TRUE);
+
+ /* add data part of union */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 8, "dataParameters");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_protocolDependentData, tvb, offset+44, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_maxBitRate, tvb, offset+48, 4, TRUE);
+ break;
+
+ case 0x6 : /* OpenMultiMediaReceiveChannelACK */
+ proto_tree_add_item(cast_tree, hf_cast_ORCStatus, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_ipAddress, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_portNumber, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_passThruPartyID, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+28, 4, TRUE);
+ break;
+
+ case 0x7 : /* CloseMultiMediaReceiveChannel */
+ proto_tree_add_item(cast_tree, hf_cast_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x8 : /* StartMultiMediaTransmission */
+ proto_tree_add_item(cast_tree, hf_cast_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_payloadCapability, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_ipAddress, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_portNumber, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_payload_rfc_number, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_payloadType, tvb, offset+40, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_DSCPValue, tvb, offset+44, 4, TRUE);
+
+ /* add video part of union */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 30, "videoParameters");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_bitRate, tvb, offset+48, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_pictureFormatCount, tvb, offset+52, 4, TRUE);
+ cast_sub_tree_sav = cast_sub_tree;
+ count = offset+56;
+ for ( i = 0; i < MAX_PICTURE_FORMAT; i++ ) {
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8 * MAX_PICTURE_FORMAT, "pictureFormat[%d]", i);
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_format, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_MPI, tvb, count, 4, TRUE);
+ count += 4;
+ }
+ cast_sub_tree = cast_sub_tree_sav;
+ proto_tree_add_item(cast_sub_tree, hf_cast_confServiceNum, tvb, count, 4, TRUE);
+ count += 4;
+
+ val = count;
+ /* add H261 part of union */
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "h261VideoCapability");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_temporalSpatialTradeOffCapability, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_stillImageTransmission, tvb, count, 4, TRUE);
+
+ /* add H263 part of union */
+ count = val;
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "h263VideoCapability");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_h263_capability_bitfield, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_annexNandWFutureUse, tvb, count, 4, TRUE);
+
+ /* add Vieo part of union */
+ count = val;
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "vieoVideoCapability");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_modelNumber, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(cast_sub_tree, hf_cast_bandwidth, tvb, count, 4, TRUE);
+
+ /* add data part of union */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 8, "dataParameters");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_protocolDependentData, tvb, offset+48, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_maxBitRate, tvb, offset+52, 4, TRUE);
+ break;
+
+ case 0x9 : /* StopMultiMediaTransmission */
+ proto_tree_add_item(cast_tree, hf_cast_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0xA : /* MiscellaneousCommand */
+ proto_tree_add_item(cast_tree, hf_cast_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_miscCommandType, tvb, offset+24, 4, TRUE);
+
+ /* show videoFreezePicture */
+ /* not sure of format */
+
+ /* show videoFastUpdatePicture */
+ /* not sure of format */
+
+ /* show videoFastUpdateGOB */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 8, "videoFastUpdateGOB");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_firstGOB, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_numberOfGOBs, tvb, offset+32, 4, TRUE);
+
+ /* show videoFastUpdateMB */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 8, "videoFastUpdateGOB");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_firstGOB, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_firstMB, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_numberOfMBs, tvb, offset+36, 4, TRUE);
+
+ /* show lostPicture */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 8, "lostPicture");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_pictureNumber, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_longTermPictureIndex, tvb, offset+32, 4, TRUE);
+
+ /* show lostPartialPicture */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 8, "lostPartialPicture");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_pictureNumber, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_longTermPictureIndex, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_firstMB, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_numberOfMBs, tvb, offset+40, 4, TRUE);
+
+ /* show recoveryReferencePicture */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 8, "recoveryReferencePicture");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_recoveryReferencePictureCount, tvb, offset+28, 4, TRUE);
+ cast_sub_tree_sav = cast_sub_tree;
+ for ( i = 0; i < MAX_REFERENCE_PICTURE; i++ ) {
+ ti_sub = proto_tree_add_text(cast_sub_tree_sav, tvb, offset, 8, "recoveryReferencePicture[%d]", i);
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_pictureNumber, tvb, offset+32+(i*8), 4, TRUE);
+ proto_tree_add_item(cast_sub_tree, hf_cast_longTermPictureIndex, tvb, offset+36+(i*8), 4, TRUE);
+ }
+
+ /* show temporalSpatialTradeOff */
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 4, "temporalSpatialTradeOff");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_item(cast_sub_tree, hf_cast_temporalSpatialTradeOff, tvb, offset+28, 4, TRUE);
+ break;
+
+ case 0xB : /* FlowControlCommand */
+ proto_tree_add_item(cast_tree, hf_cast_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_maxBitRate, tvb, offset+24, 4, TRUE);
+ break;
+
+ case 0xC : /* ClearConference */
+ proto_tree_add_item(cast_tree, hf_cast_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_serviceNum, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0xD : /* CallState */
+ proto_tree_add_item(cast_tree, hf_cast_callState, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_lineInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_privacy, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_precedenceLv, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_precedenceDm, tvb, offset+32, 4, TRUE);
+ break;
+
+ case 0xE : /* RequestCallState */
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0xF : /* RequestAllCallStates */
+ /* no data in message */
+ break;
+
+ case 0x10 : /* CallInfo */
+ i = offset+12;
+ proto_tree_add_item(cast_tree, hf_cast_callingPartyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(cast_tree, hf_cast_callingParty, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(cast_tree, hf_cast_calledPartyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(cast_tree, hf_cast_calledParty, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(cast_tree, hf_cast_lineInstance, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(cast_tree, hf_cast_callType, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(cast_tree, hf_cast_originalCalledPartyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(cast_tree, hf_cast_originalCalledParty, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(cast_tree, hf_cast_lastRedirectingPartyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(cast_tree, hf_cast_lastRedirectingParty, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(cast_tree, hf_cast_originalCdpnRedirectReason, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(cast_tree, hf_cast_lastRedirectingReason, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(cast_tree, hf_cast_cgpnVoiceMailbox, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(cast_tree, hf_cast_cdpnVoiceMailbox, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(cast_tree, hf_cast_originalCdpnVoiceMailbox, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(cast_tree, hf_cast_lastRedirectingVoiceMailbox, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(cast_tree, hf_cast_callInstance, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(cast_tree, hf_cast_callSecurityStatus, tvb, i, 4, TRUE);
+ i += 4;
+ val = tvb_get_letohl( tvb, i);
+ ti_sub = proto_tree_add_text(cast_tree, tvb, offset, 8, "partyPIRestrictionBits");
+ cast_sub_tree = proto_item_add_subtree(ti_sub, ett_cast_tree);
+ proto_tree_add_text(cast_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x01, 4*8, "Does RestrictCallingPartyName", "Doesn't RestrictCallingPartyName"));
+ proto_tree_add_text(cast_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x02, 4*8, "Does RestrictCallingPartyNumber", "Doesn't RestrictCallingPartyNumber"));
+ proto_tree_add_text(cast_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x04, 4*8, "Does RestrictCalledPartyName", "Doesn't RestrictCalledPartyName"));
+ proto_tree_add_text(cast_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x08, 4*8, "Does RestrictCalledPartyNumber", "Doesn't RestrictCalledPartyNumber"));
+ proto_tree_add_text(cast_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x10, 4*8, "Does RestrictOriginalCalledPartyName", "Doesn't RestrictOriginalCalledPartyName"));
+ proto_tree_add_text(cast_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x20, 4*8, "Does RestrictOriginalCalledPartyNumber", "Doesn't RestrictOriginalCalledPartyNumber"));
+ proto_tree_add_text(cast_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x40, 4*8, "Does RestrictLastRedirectPartyName", "Doesn't RestrictLastRedirectPartyName"));
+ proto_tree_add_text(cast_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x80, 4*8, "Does RestrictLastRedirectPartyNumber", "Doesn't RestrictLastRedirectPartyNumber"));
+ break;
+
+ case 0x11 : /* RequestCallInfo */
+ proto_tree_add_item(cast_tree, hf_cast_lineInstance, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x12 : /* CallFocus */
+ proto_tree_add_item(cast_tree, hf_cast_lineInstance, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_callIdentifier, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x13 : /* MakeCall */
+ proto_tree_add_item(cast_tree, hf_cast_calledParty, tvb, offset+12, StationMaxDirnumSize, TRUE);
+ proto_tree_add_item(cast_tree, hf_cast_lineInstance, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x14 : /* HangUp */
+ proto_tree_add_item(cast_tree, hf_cast_lineInstance, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x15 : /* Answer */
+ proto_tree_add_item(cast_tree, hf_cast_lineInstance, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x40 : /* keepAliveAck */
+ /* no data in message */
+ break;
+
+ case 0x41 : /* StreamStart */
+ /* no data in message */
+ break;
+
+ case 0x42 : /* StreamStop */
+ /* no data in message */
+ break;
+
+ case 0x43 : /* MuteStart */
+ /* no data in message */
+ break;
+
+ case 0x44 : /* MuteStop */
+ /* no data in message */
+ break;
+
+ case 0x45 : /* SpeakerStart */
+ /* no data in message */
+ break;
+
+ case 0x46 : /* SpeakerStop */
+ /* no data in message */
+ break;
+
+ case 0x47 : /* StreamStartMessageWithCodec */
+ proto_tree_add_item(cast_tree, hf_cast_audio, tvb, offset+12, 4, TRUE);
+ break;
+
+
+ case 0x50 : /* VIEODiscoveryprotocol */
+ break;
+
+ case 0x51 : /* VIEOControlprotocol */
+ break;
+
+
+ case 0x60 : /* VeT120protocol */
+ break;
+
+ case 0x61 : /* VeT121protocol */
+ break;
+
+ case 0x62 : /* VeT122protocol */
+ break;
+
+
+ case 0x70 : /* IMSessionDiscoveryprotocol */
+ break;
+
+ case 0x71 : /* IMSessionControlprotocol */
+ break;
+
+
+ case 0x74 : /* SlidesDiscoveryprotocol */
+ break;
+
+ case 0x75 : /* SlidesControlprotocol */
+ break;
+
+
+ case 0x80 : /* Tunnel */
+ break;
+
+ case 0x90 : /* RemoteInfoRequest */
+ i = offset+12;
+ proto_tree_add_item(cast_tree, hf_cast_stationFriendlyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(cast_tree, hf_cast_stationGUID, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(cast_tree, hf_cast_requestorIpAddress, tvb, i, 4, TRUE);
+ break;
+
+ case 0x91 : /* RemoteInfoResponse */
+ i = offset+12;
+ proto_tree_add_item(cast_tree, hf_cast_stationFriendlyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(cast_tree, hf_cast_stationGUID, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(cast_tree, hf_cast_stationIpAddress, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(cast_tree, hf_cast_directoryNumber, tvb, i, StationMaxNameSize, TRUE);
+ break;
+
+
+ case 0xA0 : /* CollabDiscoveryprotocol */
+ break;
+
+ case 0xA1 : /* CollabControlprotocol */
+ break;
+
+
+ case 0xA4 : /* FECCDiscoveryprotocol */
+ break;
+
+ case 0xA5 : /* FECCControlprotocol */
+ break;
+
+
+ case 0xB0 : /* ClockSyncprotocol */
+ break;
+
+ case 0xB1 : /* StreamSyncprotocol */
+ break;
+
+
+ case 0xB4 : /* MediaDiscoveryprotocol */
+ break;
+
+ case 0xB5 : /* MediaControlprotocol */
+ break;
+
+
+ case 0xC0 : /* SessionDiscoveryprotocol */
+ break;
+
+ case 0xC1 : /* SessionControlprotocol */
+ break;
+
+
+ case 0xC4 : /* ConferenceDiscoveryprotocol */
+ break;
+
+ case 0xC5 : /* Conferenceprotocol */
+ break;
+
+
+ case 0xCC : /* SCCPCallControlProxyprotocol */
+ break;
+
+
+ case 0xD0 : /* CallDiscoveryprotocol */
+ break;
+
+ case 0xD1 : /* CallControlprotocol */
+ break;
+
+
+ default:
+ break;
+ }
+ }
+}
+
+/* Get the length of a single CAST PDU */
+static guint get_cast_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint32 hdr_data_length;
+
+ /*
+ * Get the length of the CAST packet.
+ */
+ hdr_data_length = tvb_get_letohl(tvb, offset);
+
+ /*
+ * That length doesn't include the length of the header itself;
+ * add that in.
+ */
+ return hdr_data_length + 8;
+}
+
+/* Code to actually dissect the packets */
+static void dissect_cast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* The general structure of a packet: {IP-Header|TCP-Header|n*CAST}
+ * CAST-Packet: {Header(Size, Reserved)|Data(MessageID, Message-Data)}
+ */
+ /* Header fields */
+ volatile guint32 hdr_data_length;
+ guint32 hdr_marker;
+
+ /* check, if this is really an SKINNY packet, they start with a length + 0 */
+
+ /* get relevant header information */
+ hdr_data_length = tvb_get_letohl(tvb, 0);
+ hdr_marker = tvb_get_letohl(tvb, 4);
+
+ /* data_size = MIN(8+hdr_data_length, tvb_length(tvb)) - 0xC; */
+
+ if (hdr_data_length < 4 || hdr_marker != 0) {
+ /* Not an CAST packet, just happened to use the same port */
+ call_dissector(data_handle,tvb, pinfo, tree);
+ return;
+ }
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CAST");
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Cast Client Control Protocol");
+ }
+ tcp_dissect_pdus(tvb, pinfo, tree, cast_desegment, 4, get_cast_pdu_len, dissect_cast_pdu);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_cast(void)
+{
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_cast_data_length,
+ { "Data Length", "cast.data_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of bytes in the data portion.",
+ HFILL }
+ },
+
+ { &hf_cast_reserved,
+ { "Marker", "cast.marker",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Marker value should ne zero.",
+ HFILL }
+ },
+
+ /* FIXME: Enable use of message name ??? */
+ { &hf_cast_messageid,
+ { "Message ID", "cast.messageid",
+ FT_UINT32, BASE_HEX, VALS(message_id), 0x0,
+ "The function requested/done with this message.",
+ HFILL }
+ },
+
+ { &hf_cast_version,
+ { "Version", "cast.version",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The version in the keepalive version messages.",
+ HFILL }
+ },
+
+ { &hf_cast_ORCStatus,
+ { "ORCStatus", "cast.ORCStatus",
+ FT_UINT32, BASE_DEC, VALS(orcStatus), 0x0,
+ "The status of the opened receive channel.",
+ HFILL }
+ },
+
+ { &hf_cast_ipAddress,
+ { "IP Address", "cast.ipAddress",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "An IP address",
+ HFILL }
+ },
+
+ { &hf_cast_portNumber,
+ { "Port Number", "cast.portNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "A port number",
+ HFILL }
+ },
+
+ { &hf_cast_passThruPartyID,
+ { "PassThruPartyID", "cast.passThruPartyID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The pass thru party id",
+ HFILL }
+ },
+
+ { &hf_cast_callIdentifier,
+ { "Call Identifier", "cast.callIdentifier",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Call identifier for this call.",
+ HFILL }
+ },
+
+ { &hf_cast_conferenceID,
+ { "Conference ID", "cast.conferenceID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The conference ID",
+ HFILL }
+ },
+
+ { &hf_cast_payloadType,
+ { "PayloadType", "cast.payloadType",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PayloadType.",
+ HFILL }
+ },
+
+ { &hf_cast_lineInstance,
+ { "Line Instance", "cast.lineInstance",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The display call plane associated with this call.",
+ HFILL }
+ },
+
+ { &hf_cast_payloadCapability,
+ { "PayloadCapability", "cast.payloadCapability",
+ FT_UINT32, BASE_DEC, VALS(mediaPayloads), 0x0,
+ "The payload capability for this media capability structure.",
+ HFILL }
+ },
+
+ { &hf_cast_isConferenceCreator,
+ { "IsConferenceCreator", "cast.isConferenceCreator",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "IsConferenceCreator.",
+ HFILL }
+ },
+
+ { &hf_cast_payload_rfc_number,
+ { "Payload_rfc_number", "cast.payload_rfc_number",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Payload_rfc_number.",
+ HFILL }
+ },
+
+ { &hf_cast_videoCapCount,
+ { "VideoCapCount", "cast.videoCapCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "VideoCapCount.",
+ HFILL }
+ },
+
+ { &hf_cast_dataCapCount,
+ { "DataCapCount", "cast.dataCapCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "DataCapCount.",
+ HFILL }
+ },
+
+ { &hf_cast_RTPPayloadFormat,
+ { "RTPPayloadFormat", "cast.RTPPayloadFormat",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "RTPPayloadFormat.",
+ HFILL }
+ },
+
+ { &hf_cast_customPictureFormatCount,
+ { "CustomPictureFormatCount", "cast.customPictureFormatCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "CustomPictureFormatCount.",
+ HFILL }
+ },
+
+ { &hf_cast_pictureWidth,
+ { "PictureWidth", "cast.pictureWidth",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PictureWidth.",
+ HFILL }
+ },
+
+ { &hf_cast_pictureHeight,
+ { "PictureHeight", "cast.pictureHeight",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PictureHeight.",
+ HFILL }
+ },
+
+ { &hf_cast_pixelAspectRatio,
+ { "PixelAspectRatio", "cast.pixelAspectRatio",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PixelAspectRatio.",
+ HFILL }
+ },
+
+ { &hf_cast_clockConversionCode,
+ { "ClockConversionCode", "cast.clockConversionCode",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ClockConversionCode.",
+ HFILL }
+ },
+
+ { &hf_cast_clockDivisor,
+ { "ClockDivisor", "cast.clockDivisor",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Clock Divisor.",
+ HFILL }
+ },
+
+ { &hf_cast_activeStreamsOnRegistration,
+ { "ActiveStreamsOnRegistration", "cast.activeStreamsOnRegistration",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ActiveStreamsOnRegistration.",
+ HFILL }
+ },
+
+ { &hf_cast_maxBW,
+ { "MaxBW", "cast.maxBW",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MaxBW.",
+ HFILL }
+ },
+
+ { &hf_cast_serviceResourceCount,
+ { "ServiceResourceCount", "cast.serviceResourceCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ServiceResourceCount.",
+ HFILL }
+ },
+
+ { &hf_cast_layoutCount,
+ { "LayoutCount", "cast.layoutCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LayoutCount.",
+ HFILL }
+ },
+
+ { &hf_cast_layout,
+ { "Layout", "cast.layout",
+ FT_UINT32, BASE_DEC, VALS(cast_Layouts), 0x0,
+ "Layout",
+ HFILL }
+ },
+
+ { &hf_cast_maxConferences,
+ { "MaxConferences", "cast.maxConferences",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MaxConferences.",
+ HFILL }
+ },
+
+ { &hf_cast_activeConferenceOnRegistration,
+ { "ActiveConferenceOnRegistration", "cast.activeConferenceOnRegistration",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ActiveConferenceOnRegistration.",
+ HFILL }
+ },
+
+ { &hf_cast_transmitOrReceive,
+ { "TransmitOrReceive", "cast.transmitOrReceive",
+ FT_UINT32, BASE_DEC, VALS(cast_transmitOrReceive), 0x0,
+ "TransmitOrReceive",
+ HFILL }
+ },
+
+ { &hf_cast_levelPreferenceCount,
+ { "LevelPreferenceCount", "cast.levelPreferenceCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LevelPreferenceCount.",
+ HFILL }
+ },
+
+ { &hf_cast_transmitPreference,
+ { "TransmitPreference", "cast.transmitPreference",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "TransmitPreference.",
+ HFILL }
+ },
+
+ { &hf_cast_format,
+ { "Format", "cast.format",
+ FT_UINT32, BASE_DEC, VALS(cast_formatTypes), 0x0,
+ "Format.",
+ HFILL }
+ },
+
+ { &hf_cast_maxBitRate,
+ { "MaxBitRate", "cast.maxBitRate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MaxBitRate.",
+ HFILL }
+ },
+
+ { &hf_cast_minBitRate,
+ { "MinBitRate", "cast.minBitRate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MinBitRate.",
+ HFILL }
+ },
+
+ { &hf_cast_MPI,
+ { "MPI", "cast.MPI",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MPI.",
+ HFILL }
+ },
+
+ { &hf_cast_serviceNumber,
+ { "ServiceNumber", "cast.serviceNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ServiceNumber.",
+ HFILL }
+ },
+
+ { &hf_cast_temporalSpatialTradeOffCapability,
+ { "TemporalSpatialTradeOffCapability", "cast.temporalSpatialTradeOffCapability",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "TemporalSpatialTradeOffCapability.",
+ HFILL }
+ },
+
+ { &hf_cast_stillImageTransmission,
+ { "StillImageTransmission", "cast.stillImageTransmission",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "StillImageTransmission.",
+ HFILL }
+ },
+
+ { &hf_cast_h263_capability_bitfield,
+ { "H263_capability_bitfield", "cast.h263_capability_bitfield",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "H263_capability_bitfield.",
+ HFILL }
+ },
+
+ { &hf_cast_annexNandWFutureUse,
+ { "AnnexNandWFutureUse", "cast.annexNandWFutureUse",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "AnnexNandWFutureUse.",
+ HFILL }
+ },
+
+ { &hf_cast_modelNumber,
+ { "ModelNumber", "cast.modelNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ModelNumber.",
+ HFILL }
+ },
+
+ { &hf_cast_bandwidth,
+ { "Bandwidth", "cast.bandwidth",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Bandwidth.",
+ HFILL }
+ },
+
+ { &hf_cast_protocolDependentData,
+ { "ProtocolDependentData", "cast.protocolDependentData",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ProtocolDependentData.",
+ HFILL }
+ },
+
+ { &hf_cast_DSCPValue,
+ { "DSCPValue", "cast.DSCPValue",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "DSCPValue.",
+ HFILL }
+ },
+
+ { &hf_cast_serviceNum,
+ { "ServiceNum", "cast.serviceNum",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ServiceNum.",
+ HFILL }
+ },
+
+ { &hf_cast_precedenceValue,
+ { "Precedence", "cast.precedenceValue",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Precedence value",
+ HFILL }
+ },
+
+ { &hf_cast_maxStreams,
+ { "MaxStreams", "cast.maxStreams",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "32 bit unsigned integer indicating the maximum number of simultansous RTP duplex streams that the client can handle.",
+ HFILL }
+ },
+
+ { &hf_cast_millisecondPacketSize,
+ { "MS/Packet", "cast.millisecondPacketSize",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The number of milliseconds of conversation in each packet",
+ HFILL }
+ },
+
+ { &hf_cast_echoCancelType,
+ { "Echo Cancel Type", "cast.echoCancelType",
+ FT_UINT32, BASE_DEC, VALS(cast_echoCancelTypes), 0x0,
+ "Is echo cancelling enabled or not",
+ HFILL }
+ },
+
+ { &hf_cast_g723BitRate,
+ { "G723 BitRate", "cast.g723BitRate",
+ FT_UINT32, BASE_DEC, VALS(cast_g723BitRates), 0x0,
+ "The G723 bit rate for this stream/JUNK if not g723 stream",
+ HFILL }
+ },
+
+ { &hf_cast_pictureFormatCount,
+ { "PictureFormatCount", "cast.pictureFormatCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PictureFormatCount.",
+ HFILL }
+ },
+
+ { &hf_cast_confServiceNum,
+ { "ConfServiceNum", "cast.confServiceNum",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ConfServiceNum.",
+ HFILL }
+ },
+
+ { &hf_cast_miscCommandType,
+ { "MiscCommandType", "cast.miscCommandType",
+ FT_UINT32, BASE_DEC, VALS(cast_miscCommandType), 0x0,
+ "MiscCommandType",
+ HFILL }
+ },
+
+ { &hf_cast_temporalSpatialTradeOff,
+ { "TemporalSpatialTradeOff", "cast.temporalSpatialTradeOff",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "TemporalSpatialTradeOff.",
+ HFILL }
+ },
+
+ { &hf_cast_firstGOB,
+ { "FirstGOB", "cast.firstGOB",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "FirstGOB.",
+ HFILL }
+ },
+
+ { &hf_cast_numberOfGOBs,
+ { "NumberOfGOBs", "cast.numberOfGOBs",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "NumberOfGOBs.",
+ HFILL }
+ },
+
+ { &hf_cast_firstMB,
+ { "FirstMB", "cast.firstMB",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "FirstMB.",
+ HFILL }
+ },
+
+ { &hf_cast_numberOfMBs,
+ { "NumberOfMBs", "cast.numberOfMBs",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "NumberOfMBs.",
+ HFILL }
+ },
+
+ { &hf_cast_pictureNumber,
+ { "PictureNumber", "cast.pictureNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PictureNumber.",
+ HFILL }
+ },
+
+ { &hf_cast_longTermPictureIndex,
+ { "LongTermPictureIndex", "cast.longTermPictureIndex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LongTermPictureIndex.",
+ HFILL }
+ },
+
+ { &hf_cast_recoveryReferencePictureCount,
+ { "RecoveryReferencePictureCount", "cast.recoveryReferencePictureCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "RecoveryReferencePictureCount.",
+ HFILL }
+ },
+
+ { &hf_cast_calledParty,
+ { "CalledParty", "cast.calledParty",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The number called.",
+ HFILL }
+ },
+
+ { &hf_cast_privacy,
+ { "Privacy", "cast.privacy",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Privacy.",
+ HFILL }
+ },
+
+ { &hf_cast_precedenceLv,
+ { "PrecedenceLv", "cast.precedenceLv",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Precedence Level.",
+ HFILL }
+ },
+
+ { &hf_cast_precedenceDm,
+ { "PrecedenceDm", "cast.precedenceDm",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Precedence Domain.",
+ HFILL }
+ },
+
+ { &hf_cast_callState,
+ { "CallState", "cast.callState",
+ FT_UINT32, BASE_DEC, VALS(cast_callStateTypes), 0x0,
+ "CallState.",
+ HFILL }
+ },
+
+ { &hf_cast_callingPartyName,
+ { "Calling Party Name", "cast.callingPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The passed name of the calling party.",
+ HFILL }
+ },
+
+ { &hf_cast_callingParty,
+ { "Calling Party", "cast.callingPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The passed number of the calling party.",
+ HFILL }
+ },
+
+ { &hf_cast_calledPartyName,
+ { "Called Party Name", "cast.calledPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The name of the party we are calling.",
+ HFILL }
+ },
+
+ { &hf_cast_callType,
+ { "Call Type", "cast.callType",
+ FT_UINT32, BASE_DEC, VALS(cast_callTypes), 0x0,
+ "What type of call, in/out/etc",
+ HFILL }
+ },
+
+ { &hf_cast_originalCalledPartyName,
+ { "Original Called Party Name", "cast.originalCalledPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "name of the original person who placed the call.",
+ HFILL }
+ },
+
+ { &hf_cast_originalCalledParty,
+ { "Original Called Party", "cast.originalCalledParty",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The number of the original calling party.",
+ HFILL }
+ },
+
+ { &hf_cast_lastRedirectingPartyName,
+ { "LastRedirectingPartyName", "cast.lastRedirectingPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LastRedirectingPartyName.",
+ HFILL }
+ },
+
+ { &hf_cast_lastRedirectingParty,
+ { "LastRedirectingParty", "cast.lastRedirectingParty",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LastRedirectingParty.",
+ HFILL }
+ },
+
+ { &hf_cast_cgpnVoiceMailbox,
+ { "CgpnVoiceMailbox", "cast.cgpnVoiceMailbox",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "CgpnVoiceMailbox.",
+ HFILL }
+ },
+
+ { &hf_cast_cdpnVoiceMailbox,
+ { "CdpnVoiceMailbox", "cast.cdpnVoiceMailbox",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "CdpnVoiceMailbox.",
+ HFILL }
+ },
+
+ { &hf_cast_originalCdpnVoiceMailbox,
+ { "OriginalCdpnVoiceMailbox", "cast.originalCdpnVoiceMailbox",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "OriginalCdpnVoiceMailbox.",
+ HFILL }
+ },
+
+ { &hf_cast_lastRedirectingVoiceMailbox,
+ { "LastRedirectingVoiceMailbox", "cast.lastRedirectingVoiceMailbox",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LastRedirectingVoiceMailbox.",
+ HFILL }
+ },
+
+ { &hf_cast_originalCdpnRedirectReason,
+ { "OriginalCdpnRedirectReason", "cast.originalCdpnRedirectReason",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "OriginalCdpnRedirectReason.",
+ HFILL }
+ },
+
+ { &hf_cast_lastRedirectingReason,
+ { "LastRedirectingReason", "cast.lastRedirectingReason",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LastRedirectingReason.",
+ HFILL }
+ },
+
+ { &hf_cast_callInstance,
+ { "CallInstance", "cast.callInstance",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "CallInstance.",
+ HFILL }
+ },
+
+ { &hf_cast_callSecurityStatus,
+ { "CallSecurityStatus", "cast.callSecurityStatus",
+ FT_UINT32, BASE_DEC, VALS(cast_callSecurityStatusTypes), 0x0,
+ "CallSecurityStatus.",
+ HFILL }
+ },
+
+ { &hf_cast_directoryNumber,
+ { "Directory Number", "cast.directoryNumber",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The number we are reporting statistics for.",
+ HFILL }
+ },
+
+ { &hf_cast_requestorIpAddress,
+ { "RequestorIpAddress", "cast.requestorIpAddress",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "RequestorIpAddress",
+ HFILL }
+ },
+
+ { &hf_cast_stationIpAddress,
+ { "StationIpAddress", "cast.stationIpAddress",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "StationIpAddress",
+ HFILL }
+ },
+
+ { &hf_cast_stationFriendlyName,
+ { "StationFriendlyName", "cast.stationFriendlyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "StationFriendlyName.",
+ HFILL }
+ },
+
+ { &hf_cast_stationGUID,
+ { "stationGUID", "cast.stationGUID",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "stationGUID.",
+ HFILL }
+ },
+
+ { &hf_cast_audio,
+ { "AudioCodec", "cast.audio",
+ FT_UINT32, BASE_DEC, VALS(audioCodecTypes), 0x0,
+ "The audio codec that is in use.",
+ HFILL }
+ },
+
+ { &hf_cast_bitRate,
+ { "BitRate", "skinny.bitRate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "BitRate.",
+ HFILL }
+ },
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_cast,
+ &ett_cast_tree,
+ };
+
+ module_t *cast_module;
+
+ /* Register the protocol name and description */
+ proto_cast = proto_register_protocol("Cast Client Control Protocol",
+ "CAST", "cast");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_cast, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ cast_module = prefs_register_protocol(proto_cast, NULL);
+ prefs_register_bool_preference(cast_module, "reassembly", /*"desegment",*/
+ "Desegment all CAST messages spanning multiple TCP segments",
+ "Whether the CAST dissector should desegment all messages spanning multiple TCP segments",
+ &cast_desegment);
+}
+
+void
+proto_reg_handoff_cast(void)
+{
+ dissector_handle_t cast_handle;
+
+ data_handle = find_dissector("data");
+ cast_handle = create_dissector_handle(dissect_cast, proto_cast);
+ dissector_add("tcp.port", TCP_PORT_CAST, cast_handle);
+}
+
diff --git a/epan/dissectors/packet-ccsds.c b/epan/dissectors/packet-ccsds.c
new file mode 100644
index 0000000000..b3292a672c
--- /dev/null
+++ b/epan/dissectors/packet-ccsds.c
@@ -0,0 +1,259 @@
+/* packet-ccsds.c
+ * Routines for CCSDS dissection
+ * Copyright 2000, Scott Hovis scott.hovis@ums.msfc.nasa.gov
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+
+/*
+ * See
+ *
+ * http://stationpayloads.jsc.nasa.gov/J-reference/documents/ssp57002B.pdf
+ */
+
+/* Initialize the protocol and registered fields */
+static int proto_ccsds = -1;
+static int hf_ccsds_apid = -1;
+static int hf_ccsds_version = -1;
+static int hf_ccsds_secheader = -1;
+static int hf_ccsds_type = -1;
+static int hf_ccsds_seqnum = -1;
+static int hf_ccsds_seqflag = -1;
+static int hf_ccsds_length = -1;
+static int hf_ccsds_time = -1;
+static int hf_ccsds_timeid = -1;
+static int hf_ccsds_checkword = -1;
+static int hf_ccsds_zoe = -1;
+static int hf_ccsds_packtype = -1;
+static int hf_ccsds_vid = -1;
+static int hf_ccsds_dcc = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_ccsds = -1;
+static gint ett_header = -1;
+static gint ett_header2 = -1;
+
+/*
+ * Bits in the first 16-bit header word
+ */
+#define HDR_VERSION 0xe000
+#define HDR_TYPE 0x1000
+#define HDR_SECHDR 0x0800
+#define HDR_APID 0x07ff
+
+/* Code to actually dissect the packets */
+static void
+dissect_ccsds(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_item *ti;
+ proto_tree *ccsds_tree;
+ proto_item *header;
+ proto_tree *header_tree;
+ guint16 first_word;
+ proto_item *header2;
+ proto_tree *header2_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CCSDS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "CCSDS Packet");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ccsds, tvb, 0, -1, FALSE);
+ ccsds_tree = proto_item_add_subtree(ti, ett_ccsds);
+
+ header=proto_tree_add_text(ccsds_tree, tvb, 0, -1,
+ "Primary CCSDS Header");
+ header_tree=proto_item_add_subtree(header, ett_header);
+
+ first_word=tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_ccsds_version, tvb, offset, 2, first_word);
+ proto_tree_add_uint(header_tree, hf_ccsds_type, tvb, offset, 2, first_word);
+ proto_tree_add_boolean(header_tree, hf_ccsds_secheader, tvb, offset, 2, first_word);
+ proto_tree_add_uint(header_tree, hf_ccsds_apid, tvb, offset, 2, first_word);
+ offset += 2;
+
+ proto_tree_add_item(header_tree, hf_ccsds_seqflag, tvb, offset, 2, FALSE);
+ proto_tree_add_item(header_tree, hf_ccsds_seqnum, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(header_tree, hf_ccsds_length, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_item_set_end(header, tvb, offset);
+
+ if(first_word&HDR_SECHDR)
+ {
+ header2=proto_tree_add_text(ccsds_tree, tvb, offset, -1,
+ "Secondary CCSDS Header");
+ header2_tree=proto_item_add_subtree(header2, ett_header2);
+
+ proto_tree_add_item(header2_tree, hf_ccsds_time, tvb, offset, 5, FALSE);
+ offset += 5;
+
+ proto_tree_add_item(header2_tree, hf_ccsds_timeid, tvb, offset, 1, FALSE);
+ proto_tree_add_item(header2_tree, hf_ccsds_checkword, tvb, offset, 1, FALSE);
+ proto_tree_add_item(header2_tree, hf_ccsds_zoe, tvb, offset, 1, FALSE);
+ proto_tree_add_item(header2_tree, hf_ccsds_packtype, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(header2_tree, hf_ccsds_vid, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(header2_tree, hf_ccsds_dcc, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_item_set_end(header2, tvb, offset);
+ }
+
+ proto_tree_add_text(ccsds_tree, tvb, offset, -1,
+ "Data");
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+void
+proto_register_ccsds(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_ccsds_version,
+ { "version", "ccsds.version",
+ FT_UINT16, BASE_DEC, NULL, HDR_VERSION,
+ "version", HFILL }
+ },
+ { &hf_ccsds_type,
+ { "type", "ccsds.type",
+ FT_UINT16, BASE_DEC, NULL, HDR_TYPE,
+ "type", HFILL }
+ },
+ { &hf_ccsds_secheader,
+ { "secondary header", "ccsds.secheader",
+ FT_BOOLEAN, 16, NULL, HDR_SECHDR,
+ "secondary header present", HFILL }
+ },
+ { &hf_ccsds_apid,
+ { "APID", "ccsds.apid",
+ FT_UINT16, BASE_DEC, NULL, HDR_APID,
+ "Represents APID", HFILL }
+ },
+ { &hf_ccsds_seqflag,
+ { "sequence flags", "ccsds.seqflag",
+ FT_UINT16, BASE_DEC, NULL, 0xc000,
+ "sequence flags", HFILL }
+ },
+ { &hf_ccsds_seqnum,
+ { "sequence number", "ccsds.seqnum",
+ FT_UINT16, BASE_DEC, NULL, 0x3fff,
+ "sequence number", HFILL }
+ },
+ { &hf_ccsds_length,
+ { "packet length", "ccsds.length",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ "packet length", HFILL }
+ },
+ { &hf_ccsds_time,
+ { "time", "ccsds.time",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "time", HFILL }
+ },
+ { &hf_ccsds_timeid,
+ { "time identifier", "ccsds.timeid",
+ FT_UINT8, BASE_DEC, NULL, 0xC0,
+ "time identifier", HFILL }
+ },
+ { &hf_ccsds_checkword,
+ { "checkword indicator", "ccsds.checkword",
+ FT_UINT8, BASE_DEC, NULL, 0x20,
+ "checkword indicator", HFILL }
+ },
+ { &hf_ccsds_zoe,
+ { "ZOE TLM", "ccsds.zoe",
+ FT_UINT8, BASE_DEC, NULL, 0x10,
+ "CONTAINS S-BAND ZOE PACKETS", HFILL }
+ },
+ { &hf_ccsds_packtype,
+ { "packet type", "ccsds.packtype",
+ FT_UINT8, BASE_DEC, NULL, 0x0f,
+ "Packet Type - Unused in Ku-Band", HFILL }
+ },
+ { &hf_ccsds_vid,
+ { "version identifier", "ccsds.vid",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "version identifier", HFILL }
+ },
+ { &hf_ccsds_dcc,
+ { "Data Cycle Counter", "ccsds.dcc",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Data Cycle Counter", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_ccsds,
+ &ett_header,
+ &ett_header2,
+ };
+
+/* Register the protocol name and description */
+ proto_ccsds = proto_register_protocol("CCSDS", "CCSDS", "CCSDS");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ccsds, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_ccsds(void)
+{
+ dissector_handle_t ccsds_handle;
+
+ ccsds_handle = create_dissector_handle(dissect_ccsds,
+ proto_ccsds);
+ dissector_add_handle("udp.port", ccsds_handle);
+}
diff --git a/epan/dissectors/packet-cdp.c b/epan/dissectors/packet-cdp.c
new file mode 100644
index 0000000000..1c3a100096
--- /dev/null
+++ b/epan/dissectors/packet-cdp.c
@@ -0,0 +1,832 @@
+/* packet-cdp.c
+ * Routines for the disassembly of the "Cisco Discovery Protocol"
+ * (c) Copyright Hannes R. Boehm <hannes@boehm.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "oui.h"
+#include "nlpid.h"
+
+
+/*
+ * See
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
+ *
+ * for some information on CDP.
+ *
+ * See
+ *
+ * http://www.cisco.com/en/US/products/hw/switches/ps663/products_tech_note09186a0080094713.shtml
+ *
+ * for some more information on CDP version 2.
+ */
+
+/* Offsets in TLV structure. */
+#define TLV_TYPE 0
+#define TLV_LENGTH 2
+
+static int proto_cdp = -1;
+static int hf_cdp_version = -1;
+static int hf_cdp_checksum = -1;
+static int hf_cdp_ttl = -1;
+static int hf_cdp_tlvtype = -1;
+static int hf_cdp_tlvlength = -1;
+
+static gint ett_cdp = -1;
+static gint ett_cdp_tlv = -1;
+static gint ett_cdp_address = -1;
+static gint ett_cdp_capabilities = -1;
+
+static dissector_handle_t data_handle;
+
+static int
+dissect_address_tlv(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
+static void
+dissect_capabilities(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
+static void
+add_multi_line_string_to_tree(proto_tree *tree, tvbuff_t *tvb, gint start,
+ gint len, const gchar *prefix);
+
+#define TYPE_DEVICE_ID 0x0001
+#define TYPE_ADDRESS 0x0002
+#define TYPE_PORT_ID 0x0003
+#define TYPE_CAPABILITIES 0x0004
+#define TYPE_IOS_VERSION 0x0005
+#define TYPE_PLATFORM 0x0006
+#define TYPE_IP_PREFIX 0x0007
+#define TYPE_PROTOCOL_HELLO 0x0008 /* Protocol Hello */
+#define TYPE_VTP_MGMT_DOMAIN 0x0009 /* VTP Domain, CTPv2 - see second URL */
+#define TYPE_NATIVE_VLAN 0x000a /* Native VLAN, CTPv2 - see second URL */
+#define TYPE_DUPLEX 0x000b /* Full/Half Duplex - see second URL */
+/* Somewhere in here there's a Power Draw TLV */
+/* 0x000c */
+/* 0x000d */
+#define TYPE_VOIP_VLAN_REPLY 0x000e /* VoIP VLAN reply */
+#define TYPE_VOIP_VLAN_QUERY 0x000f /* VoIP VLAN query */
+#define TYPE_MTU 0x0011 /* MTU */
+#define TYPE_TRUST_BITMAP 0x0012 /* Trust bitmap */
+#define TYPE_UNTRUSTED_COS 0x0013 /* Untrusted port CoS */
+#define TYPE_SYSTEM_NAME 0x0014 /* System Name */
+#define TYPE_SYSTEM_OID 0x0015 /* System OID */
+#define TYPE_MANAGEMENT_ADDR 0x0016 /* Management Address(es) */
+#define TYPE_LOCATION 0x0017 /* Location */
+
+
+static const value_string type_vals[] = {
+ { TYPE_DEVICE_ID, "Device ID" },
+ { TYPE_ADDRESS, "Addresses" },
+ { TYPE_PORT_ID, "Port ID" },
+ { TYPE_CAPABILITIES, "Capabilities" },
+ { TYPE_IOS_VERSION, "Software version" },
+ { TYPE_PLATFORM, "Platform" },
+ { TYPE_IP_PREFIX, "IP Prefix/Gateway (used for ODR)" },
+ { TYPE_PROTOCOL_HELLO, "Protocol Hello" },
+ { TYPE_VTP_MGMT_DOMAIN, "VTP Management Domain" },
+ { TYPE_NATIVE_VLAN, "Native VLAN" },
+ { TYPE_DUPLEX, "Duplex" },
+ { TYPE_VOIP_VLAN_REPLY, "VoIP VLAN Reply" },
+ { TYPE_VOIP_VLAN_QUERY, "VoIP VLAN Query" },
+ { TYPE_MTU, "MTU"},
+ { TYPE_TRUST_BITMAP, "Trust Bitmap" },
+ { TYPE_UNTRUSTED_COS, "Untrusted Port CoS" },
+ { TYPE_SYSTEM_NAME, "System Name" },
+ { TYPE_SYSTEM_OID, "System Object ID" },
+ { TYPE_MANAGEMENT_ADDR, "Management Address" },
+ { TYPE_LOCATION, "Location" },
+ { 0, NULL },
+};
+
+#define TYPE_HELLO_CLUSTER_MGMT 0x0112
+
+static const value_string type_hello_vals[] = {
+ { TYPE_HELLO_CLUSTER_MGMT, "Cluster Management" },
+ { 0, NULL },
+};
+
+static void
+dissect_cdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *cdp_tree = NULL;
+ int offset = 0;
+ guint16 type;
+ guint16 length;
+ proto_item *tlvi;
+ proto_tree *tlv_tree;
+ int real_length;
+ guint32 naddresses;
+ int addr_length;
+ guint32 ip_addr;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CDP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Cisco Discovery Protocol");
+
+ if (tree){
+ ti = proto_tree_add_item(tree, proto_cdp, tvb, offset, -1, FALSE);
+ cdp_tree = proto_item_add_subtree(ti, ett_cdp);
+
+ /* CDP header */
+ proto_tree_add_item(cdp_tree, hf_cdp_version, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_uint_format(cdp_tree, hf_cdp_ttl, tvb, offset, 1,
+ tvb_get_guint8(tvb, offset),
+ "TTL: %u seconds",
+ tvb_get_guint8(tvb, offset));
+ offset += 1;
+ proto_tree_add_item(cdp_tree, hf_cdp_checksum, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ type = tvb_get_ntohs(tvb, offset + TLV_TYPE);
+ length = tvb_get_ntohs(tvb, offset + TLV_LENGTH);
+ if (length < 4) {
+ tlvi = proto_tree_add_text(cdp_tree, tvb, offset, 4,
+ "TLV with invalid length %u (< 4)",
+ length);
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ offset += 4;
+ break;
+ }
+
+ switch (type) {
+
+ case TYPE_DEVICE_ID:
+ /* Device ID */
+ tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
+ length, "Device ID: %s",
+ tvb_format_stringzpad(tvb, offset + 4, length - 4));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "Device ID: %s",
+ tvb_format_stringzpad(tvb, offset + 4, length - 4));
+ offset += length;
+ break;
+
+ case TYPE_ADDRESS:
+ /* Addresses */
+ tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
+ length, "Addresses");
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ offset += 4;
+ length -= 4;
+ naddresses = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tlv_tree, tvb, offset, 4,
+ "Number of addresses: %u", naddresses);
+ offset += 4;
+ length -= 4;
+ while (naddresses != 0) {
+ addr_length = dissect_address_tlv(tvb, offset, length,
+ tlv_tree);
+ if (addr_length < 0)
+ break;
+ offset += addr_length;
+ length -= addr_length;
+
+ naddresses--;
+ }
+ offset += length;
+ break;
+
+ case TYPE_PORT_ID:
+ real_length = length;
+ if (tvb_get_guint8(tvb, offset + real_length) != 0x00) {
+ /* The length in the TLV doesn't appear to be the
+ length of the TLV, as the byte just past it
+ isn't the first byte of a 2-byte big-endian
+ small integer; make the length of the TLV the length
+ in the TLV, plus 4 bytes for the TLV type and length,
+ minus 1 because that's what makes one capture work. */
+ real_length = length + 3;
+ }
+ tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
+ real_length, "Port ID: %s",
+ tvb_format_text(tvb, offset + 4, real_length - 4));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ real_length - 4,
+ "Sent through Interface: %s",
+ tvb_format_text(tvb, offset + 4, real_length - 4));
+ offset += real_length;
+ break;
+
+ case TYPE_CAPABILITIES:
+ tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
+ length, "Capabilities");
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ offset += 4;
+ length -= 4;
+ dissect_capabilities(tvb, offset, length, tlv_tree);
+ offset += length;
+ break;
+
+ case TYPE_IOS_VERSION:
+ tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
+ length, "Software Version");
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ add_multi_line_string_to_tree(tlv_tree, tvb, offset + 4,
+ length - 4, "Software Version: ");
+ offset += length;
+ break;
+
+ case TYPE_PLATFORM:
+ /* ??? platform */
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "Platform: %s",
+ tvb_format_text(tvb, offset + 4, length - 4));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "Platform: %s",
+ tvb_format_text(tvb, offset + 4, length - 4));
+ offset += length;
+ break;
+ case TYPE_IP_PREFIX:
+ if (length == 8) {
+ /* if length is 8 then this is default gw not prefix */
+ tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
+ length, "ODR Default gateway: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset+4, 4,
+ "ODR Default gateway = %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
+ offset += 8;
+ } else {
+ tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
+ length, "IP Prefixes: %d",length/5);
+
+ /* the actual number of prefixes is (length-4)/5
+ but if the variable is not a "float" but "integer"
+ then length/5=(length-4)/5 :) */
+
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ offset += 4;
+ length -= 4;
+ while (length > 0) {
+ proto_tree_add_text(tlv_tree, tvb, offset, 5,
+ "IP Prefix = %s/%u",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)),
+ tvb_get_guint8(tvb,offset+4));
+ offset += 5;
+ length -= 5;
+ }
+ }
+ break;
+ case TYPE_PROTOCOL_HELLO:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset,length, "Protocol Hello: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset+7), type_hello_vals, "Unknown (0x%04x)"));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset+4, 3,
+ "OUI: 0x%06X (%s)",
+ tvb_get_ntoh24(tvb,offset+4),
+ val_to_str(tvb_get_ntoh24(tvb,offset+4), oui_vals, "Unknown"));
+ proto_tree_add_text(tlv_tree, tvb, offset+7, 2,
+ "Protocol ID: 0x%04X (%s)",
+ tvb_get_ntohs(tvb, offset+7),
+ val_to_str(tvb_get_ntohs(tvb, offset+7), type_hello_vals, "Unknown"));
+ switch(tvb_get_ntohs(tvb, offset+7)) {
+ case TYPE_HELLO_CLUSTER_MGMT:
+ /* proto_tree_add_text(tlv_tree, tvb, offset+9,
+ length - 9, "Cluster Management");
+ */
+ tvb_memcpy(tvb, (guint8 *)&ip_addr, offset+9, 4);
+ proto_tree_add_text(tlv_tree, tvb, offset+9, 4,
+ "Cluster Master IP: %s",ip_to_str((guint8 *)&ip_addr));
+ tvb_memcpy(tvb, (guint8 *)&ip_addr, offset+13, 4);
+ proto_tree_add_text(tlv_tree, tvb, offset+13, 4,
+ "UNKNOWN (IP?): 0x%08X (%s)",
+ ip_addr, ip_to_str((guint8 *)&ip_addr));
+ proto_tree_add_text(tlv_tree, tvb, offset+17, 1,
+ "Version?: 0x%02X",
+ tvb_get_guint8(tvb, offset+17));
+ proto_tree_add_text(tlv_tree, tvb, offset+18, 1,
+ "Sub Version?: 0x%02X",
+ tvb_get_guint8(tvb, offset+18));
+ proto_tree_add_text(tlv_tree, tvb, offset+19, 1,
+ "Status?: 0x%02X",
+ tvb_get_guint8(tvb, offset+19));
+ proto_tree_add_text(tlv_tree, tvb, offset+20, 1,
+ "UNKNOWN: 0x%02X",
+ tvb_get_guint8(tvb, offset+20));
+ proto_tree_add_text(tlv_tree, tvb, offset+21, 6,
+ "Cluster Commander MAC: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset+21, 6)));
+ proto_tree_add_text(tlv_tree, tvb, offset+27, 6,
+ "Switch's MAC: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset+27, 6)));
+ proto_tree_add_text(tlv_tree, tvb, offset+33, 1,
+ "UNKNOWN: 0x%02X",
+ tvb_get_guint8(tvb, offset+33));
+ proto_tree_add_text(tlv_tree, tvb, offset+34, 2,
+ "Management VLAN: %d",
+ tvb_get_ntohs(tvb, offset+34));
+ break;
+ default:
+ proto_tree_add_text(tlv_tree, tvb, offset + 9,
+ length - 9, "Unknown");
+ break;
+ }
+ offset += length;
+ break;
+ case TYPE_VTP_MGMT_DOMAIN:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "VTP Management Domain: %s",
+ tvb_format_text(tvb, offset + 4, length - 4));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "VTP Management Domain: %s",
+ tvb_format_text(tvb, offset + 4, length - 4));
+ offset += length;
+ break;
+ case TYPE_NATIVE_VLAN:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "Native VLAN: %u",
+ tvb_get_ntohs(tvb, offset + 4));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "Native VLAN: %u",
+ tvb_get_ntohs(tvb, offset + 4));
+ offset += length;
+ break;
+ case TYPE_DUPLEX:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "Duplex: %s",
+ tvb_get_guint8(tvb, offset + 4) ?
+ "Full" : "Half" );
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "Duplex: %s",
+ tvb_get_guint8(tvb, offset + 4) ?
+ "Full" : "Half" );
+ offset += length;
+ break;
+ case TYPE_VOIP_VLAN_REPLY:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "VoIP VLAN Reply");
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "Data");
+ offset += length;
+ break;
+ case TYPE_VOIP_VLAN_QUERY:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "VoIP VLAN Query");
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "Data");
+ offset += length;
+ break;
+ case TYPE_MTU:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "MTU: %u",
+ tvb_get_ntohl(tvb,offset + 4));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "MTU: %u",
+ tvb_get_ntohl(tvb,offset + 4));
+ offset += length;
+ break;
+ case TYPE_TRUST_BITMAP:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "Trust Bitmap: 0x%02X",
+ tvb_get_guint8(tvb, offset + 4));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "Trust Bitmap: %02x",
+ tvb_get_guint8(tvb, offset + 4));
+ offset += length;
+ break;
+ case TYPE_UNTRUSTED_COS:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "Untrusted port CoS: 0x%02X",
+ tvb_get_guint8(tvb, offset + 4));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "Untrusted port CoS: %02x",
+ tvb_get_guint8(tvb, offset + 4));
+ offset += length;
+ break;
+ case TYPE_SYSTEM_NAME:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "System Name: %s",
+ tvb_format_text(tvb, offset + 4, length - 4));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "System Name: %s",
+ tvb_format_text(tvb, offset + 4, length - 4));
+ offset += length;
+ break;
+ case TYPE_SYSTEM_OID:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "System Object Identifier");
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "System Object Identifier: %s",
+ tvb_bytes_to_str(tvb, offset + 4, length - 4));
+ offset += length;
+ break;
+ case TYPE_MANAGEMENT_ADDR:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "Management Addresses");
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ offset += 4;
+ length -= 4;
+ naddresses = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tlv_tree, tvb, offset, 4,
+ "Number of addresses: %u", naddresses);
+ offset += 4;
+ length -= 4;
+ while (naddresses != 0) {
+ addr_length = dissect_address_tlv(tvb, offset, length,
+ tlv_tree);
+ if (addr_length < 0)
+ break;
+ offset += addr_length;
+ length -= addr_length;
+
+ naddresses--;
+ }
+ offset += length;
+ break;
+ case TYPE_LOCATION:
+ tlvi = proto_tree_add_text(cdp_tree, tvb,
+ offset, length, "Location: %s",
+ tvb_format_text(tvb, offset + 5, length - 5));
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ 1 , "UNKNOWN: 0x%02X",
+ tvb_get_guint8(tvb, offset + 4));
+ proto_tree_add_text(tlv_tree, tvb, offset + 5,
+ length - 5, "Location: %s",
+ tvb_format_text(tvb, offset + 5, length - 5));
+ offset += length;
+ break;
+ default:
+ tlvi = proto_tree_add_text(cdp_tree, tvb, offset,
+ length, "Type: %s, length: %u",
+ val_to_str(type, type_vals, "Unknown (0x%04x)"),
+ length);
+ tlv_tree = proto_item_add_subtree(tlvi, ett_cdp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvtype, tvb,
+ offset + TLV_TYPE, 2, type);
+ proto_tree_add_uint(tlv_tree, hf_cdp_tlvlength, tvb,
+ offset + TLV_LENGTH, 2, length);
+ if (length > 4) {
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,
+ length - 4, "Data");
+ } else
+ return;
+ offset += length;
+ }
+ }
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
+ cdp_tree);
+ }
+}
+
+#define PROTO_TYPE_NLPID 1
+#define PROTO_TYPE_IEEE_802_2 2
+
+static const value_string proto_type_vals[] = {
+ { PROTO_TYPE_NLPID, "NLPID" },
+ { PROTO_TYPE_IEEE_802_2, "802.2" },
+ { 0, NULL },
+};
+
+static int
+dissect_address_tlv(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *address_tree;
+ guint8 protocol_type;
+ guint8 protocol_length;
+ int nlpid;
+ char *protocol_str;
+ guint16 address_length;
+ char *address_type_str;
+ char *address_str;
+
+ if (length < 1)
+ return -1;
+ ti = proto_tree_add_text(tree, tvb, offset, length, "Truncated address");
+ address_tree = proto_item_add_subtree(ti, ett_cdp_address);
+ protocol_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(address_tree, tvb, offset, 1, "Protocol type: %s",
+ val_to_str(protocol_type, proto_type_vals, "Unknown (0x%02x)"));
+ offset += 1;
+ length -= 1;
+
+ if (length < 1)
+ return -1;
+ protocol_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(address_tree, tvb, offset, 1, "Protocol length: %u",
+ protocol_length);
+ offset += 1;
+ length -= 1;
+
+ if (length < protocol_length) {
+ if (length != 0) {
+ proto_tree_add_text(address_tree, tvb, offset, length,
+ "Protocol: %s (truncated)",
+ tvb_bytes_to_str(tvb, offset, length));
+ }
+ return -1;
+ }
+ protocol_str = NULL;
+ if (protocol_type == PROTO_TYPE_NLPID && protocol_length == 1) {
+ nlpid = tvb_get_guint8(tvb, offset);
+ protocol_str = val_to_str(nlpid, nlpid_vals, "Unknown (0x%02x)");
+ } else
+ nlpid = -1;
+ if (protocol_str == NULL)
+ protocol_str = tvb_bytes_to_str(tvb, offset, protocol_length);
+ proto_tree_add_text(address_tree, tvb, offset, protocol_length,
+ "Protocol: %s", protocol_str);
+ offset += protocol_length;
+ length -= protocol_length;
+
+ if (length < 2)
+ return -1;
+ address_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(address_tree, tvb, offset, 2, "Address length: %u",
+ address_length);
+ offset += 2;
+ length -= 2;
+
+ if (length < address_length) {
+ if (length != 0) {
+ proto_tree_add_text(address_tree, tvb, offset, length,
+ "Address: %s (truncated)",
+ tvb_bytes_to_str(tvb, offset, length));
+ }
+ return -1;
+ }
+ /* XXX - the Cisco document seems to be saying that, for 802.2-format
+ protocol types, 0xAAAA03 0x000000 0x0800 is IPv6, but 0x0800 is
+ the Ethernet protocol type for IPv4. */
+ length = 2 + protocol_length + 2 + address_length;
+ address_type_str = NULL;
+ address_str = NULL;
+ if (protocol_type == PROTO_TYPE_NLPID && protocol_length == 1) {
+ switch (nlpid) {
+
+ /* XXX - dissect NLPID_ISO8473_CLNP as OSI CLNP address? */
+
+ case NLPID_IP:
+ if (address_length == 4) {
+ /* The address is an IP address. */
+ address_type_str = "IP address";
+ address_str = ip_to_str(tvb_get_ptr(tvb, offset, 4));
+ }
+ break;
+ }
+ }
+ if (address_type_str == NULL)
+ address_type_str = "Address";
+ if (address_str == NULL) {
+ address_str = tvb_bytes_to_str(tvb, offset, address_length);
+ }
+ proto_item_set_text(ti, "%s: %s", address_type_str, address_str);
+ proto_tree_add_text(address_tree, tvb, offset, address_length, "%s: %s",
+ address_type_str, address_str);
+ return 2 + protocol_length + 2 + address_length;
+}
+
+static void
+dissect_capabilities(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *capabilities_tree;
+ guint32 capabilities;
+
+ if (length < 4)
+ return;
+ capabilities = tvb_get_ntohl(tvb, offset);
+ ti = proto_tree_add_text(tree, tvb, offset, length, "Capabilities: 0x%08x",
+ capabilities);
+ capabilities_tree = proto_item_add_subtree(ti, ett_cdp_capabilities);
+ proto_tree_add_text(capabilities_tree, tvb, offset, 4,
+ decode_boolean_bitfield(capabilities, 0x01, 4*8,
+ "Is a Router",
+ "Not a Router"));
+ proto_tree_add_text(capabilities_tree, tvb, offset, 4,
+ decode_boolean_bitfield(capabilities, 0x02, 4*8,
+ "Is a Transparent Bridge",
+ "Not a Transparent Bridge"));
+ proto_tree_add_text(capabilities_tree, tvb, offset, 4,
+ decode_boolean_bitfield(capabilities, 0x04, 4*8,
+ "Is a Source Route Bridge",
+ "Not a Source Route Bridge"));
+ proto_tree_add_text(capabilities_tree, tvb, offset, 4,
+ decode_boolean_bitfield(capabilities, 0x08, 4*8,
+ "Is a Switch",
+ "Not a Switch"));
+ proto_tree_add_text(capabilities_tree, tvb, offset, 4,
+ decode_boolean_bitfield(capabilities, 0x10, 4*8,
+ "Is a Host",
+ "Not a Host"));
+ proto_tree_add_text(capabilities_tree, tvb, offset, 4,
+ decode_boolean_bitfield(capabilities, 0x20, 4*8,
+ "Is IGMP capable",
+ "Not IGMP capable"));
+ proto_tree_add_text(capabilities_tree, tvb, offset, 4,
+ decode_boolean_bitfield(capabilities, 0x40, 4*8,
+ "Is a Repeater",
+ "Not a Repeater"));
+}
+
+static void
+add_multi_line_string_to_tree(proto_tree *tree, tvbuff_t *tvb, gint start,
+ gint len, const gchar *prefix)
+{
+ int prefix_len;
+ int i;
+ char blanks[64+1];
+ gint next;
+ int line_len;
+ int data_len;
+
+ prefix_len = strlen(prefix);
+ if (prefix_len > 64)
+ prefix_len = 64;
+ for (i = 0; i < prefix_len; i++)
+ blanks[i] = ' ';
+ blanks[i] = '\0';
+ while (len > 0) {
+ line_len = tvb_find_line_end(tvb, start, len, &next, FALSE);
+ data_len = next - start;
+ proto_tree_add_text(tree, tvb, start, data_len, "%s%s", prefix,
+ tvb_format_stringzpad(tvb, start, line_len));
+ start += data_len;
+ len -= data_len;
+ prefix = blanks;
+ }
+}
+
+void
+proto_register_cdp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_cdp_version,
+ { "Version", "cdp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_cdp_ttl,
+ { "TTL", "cdp.ttl", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_cdp_checksum,
+ { "Checksum", "cdp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_cdp_tlvtype,
+ { "Type", "cdp.tlv.type", FT_UINT16, BASE_HEX, VALS(type_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_cdp_tlvlength,
+ { "Length", "cdp.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_cdp,
+ &ett_cdp_tlv,
+ &ett_cdp_address,
+ &ett_cdp_capabilities,
+ };
+
+ proto_cdp = proto_register_protocol("Cisco Discovery Protocol",
+ "CDP", "cdp");
+ proto_register_field_array(proto_cdp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_cdp(void)
+{
+ dissector_handle_t cdp_handle;
+
+ data_handle = find_dissector("data");
+ cdp_handle = create_dissector_handle(dissect_cdp, proto_cdp);
+ dissector_add("llc.cisco_pid", 0x2000, cdp_handle);
+ dissector_add("chdlctype", 0x2000, cdp_handle);
+ dissector_add("ppp.protocol", 0x0207, cdp_handle);
+}
diff --git a/epan/dissectors/packet-cgmp.c b/epan/dissectors/packet-cgmp.c
new file mode 100644
index 0000000000..d3611c7190
--- /dev/null
+++ b/epan/dissectors/packet-cgmp.c
@@ -0,0 +1,143 @@
+/* packet-cgmp.c
+ * Routines for the disassembly of the Cisco Group Management Protocol
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+
+/*
+ * See
+ *
+ * http://www.barnett.sk/software/bbooks/cisco_multicasting_routing/chap04.html
+ *
+ * for some information on CGMP.
+ */
+
+static int proto_cgmp = -1;
+static int hf_cgmp_version = -1;
+static int hf_cgmp_type = -1;
+static int hf_cgmp_count = -1;
+static int hf_cgmp_gda = -1;
+static int hf_cgmp_usa = -1;
+
+static gint ett_cgmp = -1;
+
+static const value_string type_vals[] = {
+ { 0, "Join" },
+ { 1, "Leave" },
+ { 0, NULL },
+};
+
+static void
+dissect_cgmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *cgmp_tree = NULL;
+ int offset = 0;
+ guint8 count;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CGMP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Cisco Group Management Protocol");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cgmp, tvb, offset, -1,
+ FALSE);
+ cgmp_tree = proto_item_add_subtree(ti, ett_cgmp);
+
+ proto_tree_add_item(cgmp_tree, hf_cgmp_version, tvb, offset, 1,
+ FALSE);
+ proto_tree_add_item(cgmp_tree, hf_cgmp_type, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ offset += 2; /* skip reserved field */
+
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cgmp_tree, hf_cgmp_count, tvb, offset, 1,
+ count);
+ offset += 1;
+
+ while (count != 0) {
+ proto_tree_add_item(cgmp_tree, hf_cgmp_gda, tvb, offset, 6,
+ FALSE);
+ offset += 6;
+
+ proto_tree_add_item(cgmp_tree, hf_cgmp_usa, tvb, offset, 6,
+ FALSE);
+ offset += 6;
+
+ count--;
+ }
+ }
+}
+
+void
+proto_register_cgmp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_cgmp_version,
+ { "Version", "cgmp.version", FT_UINT8, BASE_DEC, NULL, 0xF0,
+ "", HFILL }},
+
+ { &hf_cgmp_type,
+ { "Type", "cgmp.type", FT_UINT8, BASE_DEC, VALS(type_vals), 0x0F,
+ "", HFILL }},
+
+ { &hf_cgmp_count,
+ { "Count", "cgmp.count", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_cgmp_gda,
+ { "Group Destination Address", "cgmp.gda", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Group Destination Address", HFILL }},
+
+ { &hf_cgmp_usa,
+ { "Unicast Source Address", "cgmp.usa", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Unicast Source Address", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_cgmp,
+ };
+
+ proto_cgmp = proto_register_protocol("Cisco Group Management Protocol",
+ "CGMP", "cgmp");
+ proto_register_field_array(proto_cgmp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_cgmp(void)
+{
+ dissector_handle_t cgmp_handle;
+
+ cgmp_handle = create_dissector_handle(dissect_cgmp, proto_cgmp);
+ dissector_add("llc.cisco_pid", 0x2001, cgmp_handle);
+ dissector_add("ethertype", 0x2001, cgmp_handle);
+}
diff --git a/epan/dissectors/packet-chdlc.c b/epan/dissectors/packet-chdlc.c
new file mode 100644
index 0000000000..18eef17644
--- /dev/null
+++ b/epan/dissectors/packet-chdlc.c
@@ -0,0 +1,374 @@
+/* packet-chdlc.c
+ * Routines for Cisco HDLC packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "etypes.h"
+#include "prefs.h"
+#include "chdlctypes.h"
+#include <epan/resolv.h>
+#include "packet-chdlc.h"
+#include "packet-ppp.h"
+#include "packet-ip.h"
+
+/*
+ * See section 4.3.1 of RFC 1547, and
+ *
+ * http://www.nethelp.no/net/cisco-hdlc.txt
+ */
+
+static int proto_chdlc = -1;
+static int hf_chdlc_addr = -1;
+static int hf_chdlc_proto = -1;
+
+static gint ett_chdlc = -1;
+
+static int proto_slarp = -1;
+static int hf_slarp_ptype = -1;
+static int hf_slarp_address = -1;
+static int hf_slarp_mysequence = -1;
+static int hf_slarp_yoursequence = -1;
+
+static gint ett_slarp = -1;
+
+static dissector_handle_t data_handle;
+
+/*
+ * Protocol types for the Cisco HDLC format.
+ *
+ * As per the above, according to RFC 1547, these are "standard 16 bit
+ * Ethernet protocol type code[s]", but 0x8035 is Reverse ARP, and
+ * that is (at least according to the Linux ISDN code) not the
+ * same as Cisco SLARP.
+ *
+ * In addition, 0x2000 is apparently the Cisco Discovery Protocol, but
+ * on Ethernet those are encapsulated inside SNAP with an OUI of
+ * OUI_CISCO, not OUI_ENCAP_ETHER.
+ *
+ * Perhaps we should set up a protocol table for those protocols
+ * that differ between Ethernet and Cisco HDLC, and have the PPP
+ * code first try that table and, if it finds nothing in that
+ * table, call "ethertype()". (Unfortunately, that means that -
+ * assuming we had a Cisco SLARP dissector - said dissector were
+ * disabled, SLARP packets would be dissected as Reverse ARP
+ * packets, not as data.)
+ */
+#define CISCO_SLARP 0x8035 /* Cisco SLARP protocol */
+
+static dissector_table_t subdissector_table;
+
+static const value_string chdlc_address_vals[] = {
+ {CHDLC_ADDR_UNICAST, "Unicast"},
+ {CHDLC_ADDR_MULTICAST, "Multicast"},
+ {0, NULL}
+};
+
+const value_string chdlc_vals[] = {
+ {0x2000, "Cisco Discovery Protocol"},
+ {ETHERTYPE_IP, "IP"},
+ {CISCO_SLARP, "SLARP"},
+ {ETHERTYPE_DEC_LB, "DEC LanBridge"},
+ {CHDLCTYPE_BPDU, "Spanning Tree BPDU"},
+ {ETHERTYPE_ATALK, "Appletalk"},
+ {ETHERTYPE_AARP, "AARP"},
+ {ETHERTYPE_IPX, "Netware IPX/SPX"},
+ {ETHERTYPE_ETHBRIDGE, "Transparent Ethernet bridging" },
+ {CHDLCTYPE_OSI, "OSI" },
+ {ETHERTYPE_MPLS, "MPLS unicast"},
+ {ETHERTYPE_MPLS_MULTI, "MPLS multicast"},
+ {0, NULL}
+};
+
+void
+capture_chdlc( const guchar *pd, int offset, int len, packet_counts *ld ) {
+ if (!BYTES_ARE_IN_FRAME(offset, len, 4)) {
+ ld->other++;
+ return;
+ }
+ switch (pntohs(&pd[offset + 2])) {
+ case ETHERTYPE_IP:
+ capture_ip(pd, offset + 4, len, ld);
+ break;
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+void
+chdlctype(guint16 chdlctype, tvbuff_t *tvb, int offset_after_chdlctype,
+ packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
+ int chdlctype_id)
+{
+ tvbuff_t *next_tvb;
+
+ if (tree) {
+ proto_tree_add_uint(fh_tree, chdlctype_id, tvb,
+ offset_after_chdlctype - 2, 2, chdlctype);
+ }
+
+ if (chdlctype == CHDLCTYPE_OSI) {
+ /* There is a Padding Byte for CLNS protocols over Cisco HDLC */
+ proto_tree_add_text(fh_tree, tvb, offset_after_chdlctype, 1, "CLNS Padding: 0x%02x",
+ tvb_get_guint8(tvb, offset_after_chdlctype));
+ next_tvb = tvb_new_subset(tvb, offset_after_chdlctype + 1, -1, -1);
+ } else {
+ next_tvb = tvb_new_subset(tvb, offset_after_chdlctype, -1, -1);
+ }
+
+ /* do lookup with the subdissector table */
+ if (!dissector_try_port(subdissector_table, chdlctype, next_tvb, pinfo, tree)) {
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", chdlctype);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+}
+
+static gint chdlc_fcs_decode = 0; /* 0 = No FCS, 1 = 16 bit FCS, 2 = 32 bit FCS */
+
+static void
+dissect_chdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *fh_tree = NULL;
+ guint8 addr;
+ guint16 proto;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CHDLC");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ switch (pinfo->p2p_dir) {
+
+ case P2P_DIR_SENT:
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
+ break;
+
+ case P2P_DIR_RECV:
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
+ break;
+
+ default:
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
+ break;
+ }
+
+ addr = tvb_get_guint8(tvb, 0);
+ proto = tvb_get_ntohs(tvb, 2);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_chdlc, tvb, 0, 4, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_chdlc);
+
+ proto_tree_add_uint(fh_tree, hf_chdlc_addr, tvb, 0, 1, addr);
+ }
+
+ decode_fcs(tvb, fh_tree, chdlc_fcs_decode, 2);
+
+ chdlctype(proto, tvb, 4, pinfo, tree, fh_tree, hf_chdlc_proto);
+}
+
+void
+proto_register_chdlc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_chdlc_addr,
+ { "Address", "chdlc.address", FT_UINT8, BASE_HEX,
+ VALS(chdlc_address_vals), 0x0, "", HFILL }},
+ { &hf_chdlc_proto,
+ { "Protocol", "chdlc.protocol", FT_UINT16, BASE_HEX,
+ VALS(chdlc_vals), 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_chdlc,
+ };
+
+ module_t *chdlc_module;
+
+ proto_chdlc = proto_register_protocol("Cisco HDLC", "CHDLC", "chdlc");
+ proto_register_field_array(proto_chdlc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+/* subdissector code */
+ subdissector_table = register_dissector_table("chdlctype",
+ "Cisco HDLC frame type", FT_UINT16, BASE_HEX);
+
+ register_dissector("chdlc", dissect_chdlc, proto_chdlc);
+
+ /* Register the preferences for the chdlc protocol */
+ chdlc_module = prefs_register_protocol(proto_chdlc, NULL);
+
+ prefs_register_enum_preference(chdlc_module,
+ "fcs_type",
+ "CHDLC Frame Checksum Type",
+ "The type of CHDLC frame checksum (none, 16-bit, 32-bit)",
+ &chdlc_fcs_decode,
+ fcs_options, FALSE);
+
+}
+
+void
+proto_reg_handoff_chdlc(void)
+{
+ dissector_handle_t chdlc_handle;
+
+ data_handle = find_dissector("data");
+ chdlc_handle = find_dissector("chdlc");
+ dissector_add("wtap_encap", WTAP_ENCAP_CHDLC, chdlc_handle);
+ dissector_add("wtap_encap", WTAP_ENCAP_CHDLC_WITH_PHDR, chdlc_handle);
+}
+
+#define SLARP_REQUEST 0
+#define SLARP_REPLY 1
+#define SLARP_LINECHECK 2
+
+static const value_string slarp_ptype_vals[] = {
+ {SLARP_REQUEST, "Request"},
+ {SLARP_REPLY, "Reply"},
+ {SLARP_LINECHECK, "Line keepalive"},
+ {0, NULL}
+};
+
+static void
+dissect_slarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *slarp_tree = NULL;
+ guint32 code;
+ guint32 address;
+ guint32 mysequence;
+ guint32 yoursequence;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SLARP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ code = tvb_get_ntohl(tvb, 0);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_slarp, tvb, 0, 14, FALSE);
+ slarp_tree = proto_item_add_subtree(ti, ett_slarp);
+ }
+
+ switch (code) {
+
+ case SLARP_REQUEST:
+ case SLARP_REPLY:
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ tvb_memcpy(tvb, (guint8 *)&address, 4, 4);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s, from %s, mask %s",
+ match_strval(code, slarp_ptype_vals),
+ get_hostname(address),
+ ip_to_str(tvb_get_ptr(tvb, 8, 4)));
+ }
+ if (tree) {
+ proto_tree_add_uint(slarp_tree, hf_slarp_ptype, tvb, 0, 4, code);
+ proto_tree_add_item(slarp_tree, hf_slarp_address, tvb, 4, 4, FALSE);
+ proto_tree_add_text(slarp_tree, tvb, 8, 4,
+ "Netmask: %s", ip_to_str(tvb_get_ptr(tvb, 8, 4)));
+ }
+ break;
+
+ case SLARP_LINECHECK:
+ mysequence = tvb_get_ntohl(tvb, 4);
+ yoursequence = tvb_get_ntohl(tvb, 8);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s, outgoing sequence %u, returned sequence %u",
+ match_strval(code, slarp_ptype_vals),
+ mysequence, yoursequence);
+ }
+ if (tree) {
+ proto_tree_add_uint(slarp_tree, hf_slarp_ptype, tvb, 0, 4, code);
+ proto_tree_add_uint(slarp_tree, hf_slarp_mysequence, tvb, 4, 4,
+ mysequence);
+ proto_tree_add_uint(slarp_tree, hf_slarp_mysequence, tvb, 8, 4,
+ yoursequence);
+ }
+ break;
+
+ default:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown packet type 0x%08X", code);
+ if (tree) {
+ proto_tree_add_uint(slarp_tree, hf_slarp_ptype, tvb, 0, 4, code);
+ call_dissector(data_handle, tvb_new_subset(tvb, 4, -1, -1), pinfo,
+ slarp_tree);
+ }
+ break;
+ }
+}
+
+void
+proto_register_slarp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_slarp_ptype,
+ { "Packet type", "slarp.ptype", FT_UINT32, BASE_DEC,
+ VALS(slarp_ptype_vals), 0x0, "", HFILL }},
+ { &hf_slarp_address,
+ { "Address", "slarp.address", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ /* XXX - need an FT_ for netmasks, which is like FT_IPV4 but doesn't
+ get translated to a host name. */
+ { &hf_slarp_mysequence,
+ { "Outgoing sequence number", "slarp.mysequence", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_slarp_yoursequence,
+ { "Returned sequence number", "slarp.yoursequence", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_chdlc,
+ &ett_slarp,
+ };
+
+ proto_slarp = proto_register_protocol("Cisco SLARP", "SLARP", "slarp");
+ proto_register_field_array(proto_slarp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_slarp(void)
+{
+ dissector_handle_t slarp_handle;
+
+ slarp_handle = create_dissector_handle(dissect_slarp, proto_slarp);
+ dissector_add("chdlctype", CISCO_SLARP, slarp_handle);
+}
diff --git a/epan/dissectors/packet-chdlc.h b/epan/dissectors/packet-chdlc.h
new file mode 100644
index 0000000000..262b80a21b
--- /dev/null
+++ b/epan/dissectors/packet-chdlc.h
@@ -0,0 +1,45 @@
+/* packet-chdlc.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_CHDLC_H__
+#define __PACKET_CHDLC_H__
+
+/*
+ * See section 4.3.1 of RFC 1547, and
+ *
+ * http://www.nethelp.no/net/cisco-hdlc.txt
+ */
+
+#define CHDLC_ADDR_UNICAST 0x0f
+#define CHDLC_ADDR_MULTICAST 0x8f
+
+void capture_chdlc(const guchar *, int, int, packet_counts *);
+
+extern const value_string chdlc_vals[];
+
+void
+chdlctype(guint16 chdlctype, tvbuff_t *tvb, int offset_after_chdlctype,
+ packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
+ int chdlctype_id);
+
+#endif
diff --git a/epan/dissectors/packet-cisco-oui.c b/epan/dissectors/packet-cisco-oui.c
new file mode 100644
index 0000000000..073e034ab1
--- /dev/null
+++ b/epan/dissectors/packet-cisco-oui.c
@@ -0,0 +1,73 @@
+/* packet-cisco-oui.c
+ * Register an LLC dissector table for Cisco's OUI 00:00:0c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include "packet-llc.h"
+#include "oui.h"
+
+static int hf_llc_cisco_pid = -1;
+
+/*
+ * See various Cisco documents, including
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/vlan.htm
+ *
+ * and
+ *
+ * http://www.cisco.com/en/US/products/hw/switches/ps663/products_tech_note09186a0080094713.shtml
+ *
+ * for various PID values - and for a DRIP frame format.
+ */
+static const value_string cisco_pid_vals[] = {
+ { 0x0102, "DRIP" },
+ { 0x0104, "PagP" }, /* Port Aggregation Protocol */
+ { 0x0105, "MLS Hello" }, /* from a mail message found on the Web */
+ { 0x010b, "PVSTP+" }, /* Per-VLAN Spanning Tree Protocol */
+ { 0x010c, "VLAN Bridge" },
+ { 0x0111, "UDLD" }, /* Unidirectional Link Detection */
+ { 0x2000, "CDP" },
+ { 0x2001, "CGMP" },
+ { 0x2003, "VTP" },
+ { 0x2004, "DTP" }, /* Dynamic Trunking Protocol */
+ { 0x200a, "STP Uplink Fast" },
+ { 0, NULL }
+};
+
+/*
+ * NOTE: there's no dissector here, just registration routines to set
+ * up the dissector table for the Cisco OUI.
+ */
+void
+proto_register_cisco_oui(void)
+{
+ static hf_register_info hf = {
+ &hf_llc_cisco_pid,
+ { "PID", "llc.cisco_pid", FT_UINT16, BASE_HEX,
+ VALS(cisco_pid_vals), 0x0, "", HFILL },
+ };
+
+ llc_add_oui(OUI_CISCO, "llc.cisco_pid", "Cisco OUI PID", &hf);
+}
diff --git a/epan/dissectors/packet-clearcase.c b/epan/dissectors/packet-clearcase.c
new file mode 100644
index 0000000000..8f654bf38f
--- /dev/null
+++ b/epan/dissectors/packet-clearcase.c
@@ -0,0 +1,79 @@
+/* packet-clearcase.c
+ * Routines for ClearCase NFS dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-ypxfr.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-clearcase.h"
+
+static int proto_clearcase = -1;
+static int hf_clearcase_procedure_v3 = -1;
+
+static gint ett_clearcase = -1;
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff clearcase3_proc[] = {
+ { CLEARCASEPROC_NULL, "NULL", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string clearcase3_proc_vals[] = {
+ { CLEARCASEPROC_NULL, "NULL" },
+ { 0, NULL }
+};
+/* end of Clearcase version 3 */
+
+void
+proto_register_clearcase(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_clearcase_procedure_v3, {
+ "V3 Procedure", "clearcase.procedure_v3", FT_UINT32, BASE_DEC,
+ VALS(clearcase3_proc_vals), 0, "V3 Procedure", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_clearcase
+ };
+
+ proto_clearcase = proto_register_protocol("Clearcase NFS",
+ "CLEARCASE", "clearcase");
+ proto_register_field_array(proto_clearcase, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_clearcase(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_clearcase, CLEARCASE_PROGRAM, ett_clearcase);
+ /* Register the procedure tables */
+ rpc_init_proc_table(CLEARCASE_PROGRAM, 3, clearcase3_proc, hf_clearcase_procedure_v3);
+}
diff --git a/epan/dissectors/packet-clearcase.h b/epan/dissectors/packet-clearcase.h
new file mode 100644
index 0000000000..9d80c0e8f7
--- /dev/null
+++ b/epan/dissectors/packet-clearcase.h
@@ -0,0 +1,32 @@
+/* packet-clearcase.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_CLEARCASE_H
+#define PACKET_CLEARCASE_H
+
+#define CLEARCASEPROC_NULL 0
+
+#define CLEARCASE_PROGRAM 390512
+
+#endif
diff --git a/epan/dissectors/packet-clip.c b/epan/dissectors/packet-clip.c
new file mode 100644
index 0000000000..cae6dd1982
--- /dev/null
+++ b/epan/dissectors/packet-clip.c
@@ -0,0 +1,120 @@
+/* packet-clip.c
+ * Routines for clip packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ *
+ * This file created by Thierry Andry <Thierry.Andry@advalvas.be>
+ * from nearly-the-same packet-raw.c created by Mike Hall <mlh@io.com>
+ * Copyright 1999
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-clip.h"
+#include "packet-ip.h"
+
+static gint ett_clip = -1;
+
+static dissector_handle_t ip_handle;
+
+void
+capture_clip( const guchar *pd, int len, packet_counts *ld ) {
+
+ capture_ip(pd, 0, len, ld);
+}
+
+static void
+dissect_clip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *fh_tree;
+ proto_item *ti;
+
+ pinfo->current_proto = "CLIP";
+
+ /* load the top pane info. This should be overwritten by
+ the next protocol in the stack */
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A" );
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A" );
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLIP" );
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Classical IP frame" );
+
+ /* populate a tree in the second pane with the status of the link
+ layer (ie none)
+
+ XXX - the Linux Classical IP code supports both LLC Encapsulation,
+ which puts an LLC header and possibly a SNAP header in front of
+ the network-layer header, and VC Based Multiplexing, which puts
+ no headers in front of the network-layer header.
+
+ The ATM on Linux code includes a patch to "tcpdump"
+ that compares the first few bytes of the packet with the
+ LLC header that Classical IP frames may have and, if there's
+ a SNAP LLC header at the beginning of the packet, it gets
+ the packet type from that header and uses that, otherwise
+ it treats the packet as being raw IP with no link-level
+ header, in order to handle both of those.
+
+ This code, however, won't handle LLC Encapsulation. We've
+ not yet seen a capture taken on a machine using LLC Encapsulation,
+ however. If we see one, we can modify the code.
+
+ A future version of libpcap, however, will probably use DLT_LINUX_SLL
+ for both of those cases, to avoid the headache of having to
+ generate capture-filter code to handle both of those cases. */
+ if(tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, 0, "Classical IP frame" );
+ fh_tree = proto_item_add_subtree(ti, ett_clip);
+ proto_tree_add_text(fh_tree, tvb, 0, 0, "No link information available");
+ }
+ call_dissector(ip_handle, tvb, pinfo, tree);
+}
+
+void
+proto_register_clip(void)
+{
+ static gint *ett[] = {
+ &ett_clip,
+ };
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_clip(void)
+{
+ dissector_handle_t clip_handle;
+
+ /*
+ * Get a handle for the IP dissector.
+ */
+ ip_handle = find_dissector("ip");
+
+ clip_handle = create_dissector_handle(dissect_clip, -1);
+ /* XXX - no protocol, can't be disabled */
+ dissector_add("wtap_encap", WTAP_ENCAP_LINUX_ATM_CLIP, clip_handle);
+}
diff --git a/epan/dissectors/packet-clip.h b/epan/dissectors/packet-clip.h
new file mode 100644
index 0000000000..efc0ea66ff
--- /dev/null
+++ b/epan/dissectors/packet-clip.h
@@ -0,0 +1,29 @@
+/* packet-clip.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_CLIP_H__
+#define __PACKET_CLIP_H__
+
+void capture_clip(const guchar *, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-clnp.c b/epan/dissectors/packet-clnp.c
new file mode 100644
index 0000000000..c94b855043
--- /dev/null
+++ b/epan/dissectors/packet-clnp.c
@@ -0,0 +1,2396 @@
+/* packet-clnp.c
+ * Routines for ISO/OSI network and transport protocol packet disassembly
+ *
+ * $Id$
+ * Laurent Deniel <laurent.deniel@free.fr>
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+#include "prefs.h"
+#include <epan/packet.h>
+#include "reassemble.h"
+#include "packet-osi.h"
+#include "packet-osi-options.h"
+#include "packet-isis.h"
+#include "packet-esis.h"
+#include "nlpid.h"
+#include "ipproto.h"
+
+/* protocols and fields */
+
+static int proto_clnp = -1;
+static gint ett_clnp = -1;
+static gint ett_clnp_type = -1;
+static gint ett_clnp_segments = -1;
+static gint ett_clnp_segment = -1;
+static gint ett_clnp_disc_pdu = -1;
+
+static int hf_clnp_id = -1;
+static int hf_clnp_length = -1;
+static int hf_clnp_version = -1;
+static int hf_clnp_ttl = -1;
+static int hf_clnp_type = -1;
+static int hf_clnp_pdu_length = -1;
+static int hf_clnp_checksum = -1;
+static int hf_clnp_dest_length = -1;
+static int hf_clnp_dest = -1;
+static int hf_clnp_src_length = -1;
+static int hf_clnp_src = -1;
+static int hf_clnp_segments = -1;
+static int hf_clnp_segment = -1;
+static int hf_clnp_segment_overlap = -1;
+static int hf_clnp_segment_overlap_conflict = -1;
+static int hf_clnp_segment_multiple_tails = -1;
+static int hf_clnp_segment_too_long_segment = -1;
+static int hf_clnp_segment_error = -1;
+static int hf_clnp_reassembled_in = -1;
+
+static int proto_cotp = -1;
+static gint ett_cotp = -1;
+static gint ett_cotp_segments = -1;
+static gint ett_cotp_segment = -1;
+
+static int hf_cotp_srcref = -1;
+static int hf_cotp_destref = -1;
+static int hf_cotp_type = -1;
+static int hf_cotp_segments = -1;
+static int hf_cotp_segment = -1;
+static int hf_cotp_segment_overlap = -1;
+static int hf_cotp_segment_overlap_conflict = -1;
+static int hf_cotp_segment_multiple_tails = -1;
+static int hf_cotp_segment_too_long_segment = -1;
+static int hf_cotp_segment_error = -1;
+static int hf_cotp_reassembled_in = -1;
+
+static int proto_cltp = -1;
+static gint ett_cltp = -1;
+
+static int hf_cltp_type = -1;
+
+static const fragment_items clnp_frag_items = {
+ &ett_clnp_segment,
+ &ett_clnp_segments,
+ &hf_clnp_segments,
+ &hf_clnp_segment,
+ &hf_clnp_segment_overlap,
+ &hf_clnp_segment_overlap_conflict,
+ &hf_clnp_segment_multiple_tails,
+ &hf_clnp_segment_too_long_segment,
+ &hf_clnp_segment_error,
+ &hf_clnp_reassembled_in,
+ "segments"
+};
+
+static const fragment_items cotp_frag_items = {
+ &ett_cotp_segment,
+ &ett_cotp_segments,
+ &hf_cotp_segments,
+ &hf_cotp_segment,
+ &hf_cotp_segment_overlap,
+ &hf_cotp_segment_overlap_conflict,
+ &hf_cotp_segment_multiple_tails,
+ &hf_cotp_segment_too_long_segment,
+ &hf_cotp_segment_error,
+ &hf_cotp_reassembled_in,
+ "segments"
+};
+
+static dissector_handle_t clnp_handle;
+static dissector_handle_t data_handle;
+
+/*
+ * ISO 8473 OSI CLNP definition (see RFC994)
+ *
+ * _________________________________
+ * | Fixed Part |
+ * |_________________________________|
+ * | Address Part |
+ * |_________________________________|
+ * | Segmentation Part (optional) |
+ * |_________________________________|
+ * | Options Part (optional) |
+ * |_________________________________|
+ * | Data (optional) |
+ * |_________________________________|
+ */
+
+#define ISO8473_V1 0x01 /* CLNP version 1 */
+
+/* Fixed part */
+
+#define CNF_TYPE 0x1f
+#define CNF_ERR_OK 0x20
+#define CNF_MORE_SEGS 0x40
+#define CNF_SEG_OK 0x80
+
+#define DT_NPDU 0x1C
+#define MD_NPDU 0x1D
+#define ER_NPDU 0x01
+#define ERQ_NPDU 0x1E
+#define ERP_NPDU 0x1F
+
+static const value_string npdu_type_abbrev_vals[] = {
+ { DT_NPDU, "DT" },
+ { MD_NPDU, "MD" },
+ { ER_NPDU, "ER" },
+ { ERQ_NPDU, "ERQ" },
+ { ERP_NPDU, "ERP" },
+ { 0, NULL }
+};
+
+static const value_string npdu_type_vals[] = {
+ { DT_NPDU, "Data" },
+ { MD_NPDU, "Multicast Data" },
+ { ER_NPDU, "Error Report" },
+ { ERQ_NPDU, "Echo Request" },
+ { ERP_NPDU, "Echo Response" },
+ { 0, NULL }
+};
+
+/* field position */
+
+#define P_CLNP_PROTO_ID 0
+#define P_CLNP_HDR_LEN 1
+#define P_CLNP_VERS 2
+#define P_CLNP_TTL 3
+#define P_CLNP_TYPE 4
+#define P_CLNP_SEGLEN 5
+#define P_CLNP_CKSUM 7
+#define P_CLNP_ADDRESS_PART 9
+
+/* Segmentation part */
+
+struct clnp_segment {
+ gushort cng_id; /* data unit identifier */
+ gushort cng_off; /* segment offset */
+ gushort cng_tot_len; /* total length */
+};
+
+/* NSAP selector */
+
+#define NSEL_NET 0x00
+#define NSEL_NP 0x20
+#define NSEL_TP 0x21
+
+/*
+ * ISO8073 OSI COTP definition (see RFC905)
+ */
+
+/* don't use specific TPDU types to avoid alignment problems & copy overhead */
+
+/* TPDU definition */
+
+#define ED_TPDU 0x1 /* COTP */
+#define EA_TPDU 0x2 /* COTP */
+#define UD_TPDU 0x4 /* CLTP */
+#define RJ_TPDU 0x5 /* COTP */
+#define AK_TPDU 0x6 /* COTP */
+#define ER_TPDU 0x7 /* COTP */
+#define DR_TPDU 0x8 /* COTP */
+#define DC_TPDU 0xC /* COTP */
+#define CC_TPDU 0xD /* COTP */
+#define CR_TPDU 0xE /* COTP */
+#define DT_TPDU 0xF /* COTP */
+
+static const value_string cotp_tpdu_type_abbrev_vals[] = {
+ { ED_TPDU, "ED" },
+ { EA_TPDU, "EA" },
+ { RJ_TPDU, "RJ" },
+ { AK_TPDU, "AK" },
+ { ER_TPDU, "ER" },
+ { DR_TPDU, "DR" },
+ { DC_TPDU, "DC" },
+ { CC_TPDU, "CC" },
+ { CR_TPDU, "CR" },
+ { DT_TPDU, "DT" },
+ { 0, NULL }
+};
+
+static const value_string cltp_tpdu_type_abbrev_vals[] = {
+ { UD_TPDU, "UD" },
+ { 0, NULL }
+};
+
+/* field position */
+
+#define P_LI 0
+#define P_TPDU 1
+#define P_CDT 1
+#define P_DST_REF 2
+#define P_SRC_REF 4
+#define P_TPDU_NR_0_1 2
+#define P_TPDU_NR_234 4
+#define P_VAR_PART_NDT 5
+#define P_VAR_PART_EDT 8
+#define P_VAR_PART_DC 6
+#define P_CDT_IN_AK 8
+#define P_CDT_IN_RJ 8
+#define P_REJECT_ER 4
+#define P_REASON_IN_DR 6
+#define P_CLASS_OPTION 6
+
+/* TPDU length indicator */
+
+#define LI_NORMAL_DT_CLASS_01 2
+#define LI_NORMAL_DT_WITH_CHECKSUM 8
+#define LI_NORMAL_DT_WITHOUT_CHECKSUM 4
+#define LI_EXTENDED_DT_WITH_CHECKSUM 11
+#define LI_EXTENDED_DT_WITHOUT_CHECKSUM 7
+#define LI_NORMAL_EA_WITH_CHECKSUM 8
+#define LI_NORMAL_EA_WITHOUT_CHECKSUM 4
+#define LI_EXTENDED_EA_WITH_CHECKSUM 11
+#define LI_EXTENDED_EA_WITHOUT_CHECKSUM 7
+#define LI_NORMAL_RJ 4
+#define LI_EXTENDED_RJ 9
+#define LI_MIN_DR 6
+#define LI_MAX_DC 9
+#define LI_MAX_AK 27
+#define LI_MAX_EA 11
+#define LI_MAX_ER 8
+/* XXX - can we always decide this based on whether the length
+ indicator is odd or not? What if the variable part has an odd
+ number of octets? */
+#define is_LI_NORMAL_AK(p) ( ( p & 0x01 ) == 0 )
+
+/* variant part */
+
+#define VP_ACK_TIME 0x85
+#define VP_RES_ERROR 0x86
+#define VP_PRIORITY 0x87
+#define VP_TRANSIT_DEL 0x88
+#define VP_THROUGHPUT 0x89
+#define VP_SEQ_NR 0x8A /* in AK */
+#define VP_REASSIGNMENT 0x8B
+#define VP_FLOW_CNTL 0x8C /* in AK */
+#define VP_TPDU_SIZE 0xC0
+#define VP_SRC_TSAP 0xC1 /* in CR/CC */
+#define VP_DST_TSAP 0xC2
+#define VP_CHECKSUM 0xC3
+#define VP_VERSION_NR 0xC4
+#define VP_PROTECTION 0xC5
+#define VP_OPT_SEL 0xC6
+#define VP_PROTO_CLASS 0xC7
+#define VP_PREF_MAX_TPDU_SIZE 0xF0
+#define VP_INACTIVITY_TIMER 0xF2
+
+static const value_string tp_vpart_type_vals[] = {
+ { VP_ACK_TIME, "ack time" },
+ { VP_RES_ERROR, "res error" },
+ { VP_PRIORITY, "priority" },
+ { VP_TRANSIT_DEL, "transit delay" },
+ { VP_THROUGHPUT, "throughput" },
+ { VP_SEQ_NR, "seq number" },
+ { VP_REASSIGNMENT, "reassignment" },
+ { VP_FLOW_CNTL, "flow control" },
+ { VP_TPDU_SIZE, "tpdu-size" },
+ { VP_SRC_TSAP, "src-tsap" },
+ { VP_DST_TSAP, "dst-tsap" },
+ { VP_CHECKSUM, "checksum" },
+ { VP_VERSION_NR, "version" },
+ { VP_PROTECTION, "protection" },
+ { VP_OPT_SEL, "options" },
+ { VP_PROTO_CLASS, "proto class" },
+ { VP_PREF_MAX_TPDU_SIZE, "preferred max TPDU size" },
+ { 0, NULL }
+};
+
+static int hf_cotp_vp_src_tsap = -1;
+static int hf_cotp_vp_dst_tsap = -1;
+static int hf_cotp_vp_src_tsap_bytes = -1;
+static int hf_cotp_vp_dst_tsap_bytes = -1;
+
+
+/* misc */
+
+#define EXTRACT_SHORT(p) pntohs(p)
+#define EXTRACT_LONG(p) pntohl(p)
+
+/* global variables */
+
+/* List of dissectors to call for COTP packets put atop the Inactive
+ Subset of CLNP. */
+static heur_dissector_list_t cotp_is_heur_subdissector_list;
+/* List of dissectors to call for COTP packets put atop CLNP */
+static heur_dissector_list_t cotp_heur_subdissector_list;
+/* List of dissectors to call for CLNP packets */
+static heur_dissector_list_t clnp_heur_subdissector_list;
+
+/*
+ * Reassembly of CLNP.
+ */
+static GHashTable *clnp_segment_table = NULL;
+static GHashTable *clnp_reassembled_table = NULL;
+
+/*
+ * Reassembly of COTP.
+ */
+static GHashTable *cotp_segment_table = NULL;
+static GHashTable *cotp_reassembled_table = NULL;
+
+#define TSAP_DISPLAY_AUTO 0
+#define TSAP_DISPLAY_STRING 1
+#define TSAP_DISPLAY_BYTES 2
+
+
+/* options */
+static guint tp_nsap_selector = NSEL_TP;
+static gboolean always_decode_transport = FALSE;
+static gboolean clnp_reassemble = FALSE;
+static gboolean cotp_reassemble = FALSE;
+static gint32 tsap_display = TSAP_DISPLAY_AUTO;
+
+const enum_val_t tsap_display_options[] = {
+ {"auto", "As strings if printable", TSAP_DISPLAY_AUTO},
+ {"string", "As strings", TSAP_DISPLAY_STRING},
+ {"bytes", "As bytes", TSAP_DISPLAY_BYTES},
+ {NULL, NULL, -1}
+};
+
+
+/* function definitions */
+
+#define MAX_TSAP_LEN 32
+static gboolean is_all_printable(const guchar *stringtocheck, int length)
+{
+ gboolean allprintable;
+ int i;
+
+ allprintable=TRUE;
+ for (i=0;i<length;i++) {
+ if (!(isascii(stringtocheck[i]) && isprint(stringtocheck[i]))) {
+ allprintable=FALSE;
+ break;
+ }
+ }
+ return allprintable;
+} /* is_all_printable */
+
+
+static gchar *print_tsap(const guchar *tsap, int length)
+{
+
+ static gchar str[3][MAX_TSAP_LEN * 2 + 3]; /* TSAP in hex + '0x' + NULL */
+ static gchar *cur;
+ gchar tmp[3];
+ gboolean allprintable;
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+
+
+ cur[0] = '\0';
+ if (length <= 0 || length > MAX_TSAP_LEN)
+ sprintf(cur, "<unsupported TSAP length>");
+ else {
+ allprintable = is_all_printable(tsap,length);
+ if (!allprintable)
+ strcat(cur,"0x");
+ while (length != 0) {
+ if (allprintable)
+ sprintf(tmp, "%c", *tsap ++);
+ else
+ sprintf(tmp, "%02x", *tsap ++);
+ strcat(cur, tmp);
+ length --;
+ }
+ }
+ return cur;
+
+} /* print_tsap */
+
+static gboolean ositp_decode_var_part(tvbuff_t *tvb, int offset,
+ int vp_length, int class_option,
+ proto_tree *tree)
+{
+ guint8 code, length;
+ guint8 c1;
+ guint16 s, s1,s2,s3,s4;
+ guint32 t1, t2, t3, t4;
+ guint32 pref_max_tpdu_size;
+
+ while (vp_length != 0) {
+ code = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Parameter code: 0x%02x (%s)",
+ code,
+ val_to_str(code, tp_vpart_type_vals, "Unknown"));
+ offset += 1;
+ vp_length -= 1;
+
+ if (vp_length == 0)
+ break;
+ length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Parameter length: %u", length);
+ offset += 1;
+ vp_length -= 1;
+
+ switch (code) {
+
+ case VP_ACK_TIME:
+ s = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Ack time (ms): %u", s);
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_RES_ERROR:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Residual error rate, target value: 10^%u",
+ tvb_get_guint8(tvb, offset));
+ offset += 1;
+ length -= 1;
+ vp_length -= 1;
+
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Residual error rate, minimum acceptable: 10^%u",
+ tvb_get_guint8(tvb, offset));
+ offset += 1;
+ length -= 1;
+ vp_length -= 1;
+
+
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Residual error rate, TSDU size of interest: %u",
+ 1<<tvb_get_guint8(tvb, offset));
+ offset += 1;
+ length -= 1;
+ vp_length -= 1;
+
+ break;
+
+ case VP_PRIORITY:
+ s = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Priority: %u", s);
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_TRANSIT_DEL:
+ s1 = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Transit delay, target value, calling-called: %u ms", s1);
+ offset += 2;
+ length -= 2;
+ vp_length -= 2;
+
+ s2 = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Transit delay, maximum acceptable, calling-called: %u ms", s2);
+ offset += 2;
+ length -= 2;
+ vp_length -= 2;
+
+ s3 = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Transit delay, target value, called-calling: %u ms", s3);
+ offset += 2;
+ length -= 2;
+ vp_length -= 2;
+
+ s4 = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Transit delay, maximum acceptable, called-calling: %u ms", s4);
+ offset += 2;
+ length -= 2;
+ vp_length -= 2;
+ break;
+
+ case VP_THROUGHPUT:
+ t1 = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Maximum throughput, target value, calling-called: %u o/s", t1);
+ offset += 3;
+ length -= 3;
+ vp_length -= 3;
+
+ t2 = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Maximum throughput, minimum acceptable, calling-called: %u o/s", t2);
+ offset += 3;
+ length -= 3;
+ vp_length -= 3;
+
+ t3 = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Maximum throughput, target value, called-calling: %u o/s", t3);
+ offset += 3;
+ length -= 3;
+ vp_length -= 3;
+
+ t4 = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Maximum throughput, minimum acceptable, called-calling: %u o/s", t4);
+ offset += 3;
+ length -= 3;
+ vp_length -= 3;
+
+ if (length != 0) { /* XXX - should be 0 or 12 */
+ t1 = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Average throughput, target value, calling-called: %u o/s", t1);
+ offset += 3;
+ length -= 3;
+ vp_length -= 3;
+
+ t2 = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Average throughput, minimum acceptable, calling-called: %u o/s", t2);
+ offset += 3;
+ length -= 3;
+ vp_length -= 3;
+
+ t3 = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Average throughput, target value, called-calling: %u o/s", t3);
+ offset += 3;
+ length -= 3;
+ vp_length -= 3;
+
+ t4 = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Average throughput, minimum acceptable, called-calling: %u o/s", t4);
+ offset += 3;
+ length -= 3;
+ vp_length -= 3;
+ }
+ break;
+
+ case VP_SEQ_NR:
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_REASSIGNMENT:
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reassignment time: %u secs", tvb_get_ntohs(tvb, offset));
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_FLOW_CNTL:
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Lower window edge: 0x%08x", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ length -= 4;
+ vp_length -= 4;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Sequence number: 0x%04x", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ length -= 2;
+ vp_length -= 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Credit: 0x%04x", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ length -= 2;
+ vp_length -= 2;
+
+ break;
+
+ case VP_TPDU_SIZE:
+ c1 = tvb_get_guint8(tvb, offset) & 0x0F;
+ proto_tree_add_text(tree, tvb, offset, length,
+ "TPDU size: %u", 1 << c1);
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_SRC_TSAP:
+ /* if our preference is set to STRING or the
+ TSAP is not printable, add as bytes and hidden as string;
+ otherwise vice-versa */
+ if (tsap_display==TSAP_DISPLAY_STRING ||
+ (tsap_display==TSAP_DISPLAY_AUTO && is_all_printable(tvb_get_ptr(tvb,offset,length),length))) {
+ proto_tree_add_string(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
+ print_tsap(tvb_get_ptr(tvb, offset, length),length));
+ proto_tree_add_item_hidden(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset, length, TRUE);
+ } else {
+ proto_tree_add_string_hidden(tree, hf_cotp_vp_src_tsap, tvb, offset, length,
+ print_tsap(tvb_get_ptr(tvb, offset, length),length));
+ proto_tree_add_item(tree, hf_cotp_vp_src_tsap_bytes, tvb, offset, length, TRUE);
+ }
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_DST_TSAP:
+ /* if our preference is set to STRING or the
+ TSAP is not printable, add as bytes and hidden as string;
+ otherwise vice-versa */
+ if (tsap_display==TSAP_DISPLAY_STRING ||
+ (tsap_display==TSAP_DISPLAY_AUTO && is_all_printable(tvb_get_ptr(tvb,offset,length),length))) {
+ proto_tree_add_string(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
+ print_tsap(tvb_get_ptr(tvb, offset, length),length));
+ proto_tree_add_item_hidden(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset, length, TRUE);
+ } else {
+ proto_tree_add_string_hidden(tree, hf_cotp_vp_dst_tsap, tvb, offset, length,
+ print_tsap(tvb_get_ptr(tvb, offset, length),length));
+ proto_tree_add_item(tree, hf_cotp_vp_dst_tsap_bytes, tvb, offset, length, TRUE);
+ }
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_CHECKSUM:
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Checksum: 0x%04x", tvb_get_ntohs(tvb, offset));
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_VERSION_NR:
+ c1 = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Version: %u", c1);
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_OPT_SEL:
+ c1 = tvb_get_guint8(tvb, offset) & 0x0F;
+ switch (class_option) {
+
+ case 1:
+ if (c1 & 0x8)
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Use of network expedited data");
+ else
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Non use of network expedited data");
+ if (c1 & 0x4)
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Use of Receipt confirmation");
+ else
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Use of explicit AK variant");
+ break;
+
+ case 4:
+ if (c1 & 0x2)
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Non-use 16 bit checksum in class 4");
+ else
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Use 16 bit checksum ");
+ break;
+ }
+ if (c1 & 0x1)
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Use of transport expedited data transfer");
+ else
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Non-use of transport expedited data transfer");
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_PREF_MAX_TPDU_SIZE:
+ switch (length) {
+
+ case 1:
+ pref_max_tpdu_size = tvb_get_guint8(tvb, offset);
+ break;
+
+ case 2:
+ pref_max_tpdu_size = tvb_get_ntohs(tvb, offset);
+ break;
+
+ case 3:
+ pref_max_tpdu_size = tvb_get_ntoh24(tvb, offset);
+ break;
+
+ case 4:
+ pref_max_tpdu_size = tvb_get_ntohl(tvb, offset);
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Preferred maximum TPDU size: bogus length %u (not 1, 2, 3, or 4)",
+ length);
+ return FALSE;
+ }
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Preferred maximum TPDU size: %u", pref_max_tpdu_size*128);
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_INACTIVITY_TIMER:
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Inactivity timer: %u ms", tvb_get_ntohl(tvb, offset));
+ offset += length;
+ vp_length -= length;
+ break;
+
+ case VP_PROTECTION: /* user-defined */
+ case VP_PROTO_CLASS: /* todo */
+ default: /* unknown, no decoding */
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Parameter value: <not shown>");
+ offset += length;
+ vp_length -= length;
+ break;
+ }
+ } /* while */
+
+ return TRUE;
+}
+
+static int ositp_decode_DR(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ guint16 dst_ref, src_ref;
+ guchar reason;
+ char *str;
+
+ if (li < LI_MIN_DR)
+ return -1;
+
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+
+ src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
+
+ reason = tvb_get_guint8(tvb, offset + P_REASON_IN_DR);
+
+ /* the settings of the TCP srcport and destport are currently disables,
+ * for the following reasons:
+ * a) only used for ISO conversation handling (which currently doesn't work)
+ * b) will prevent "ISO on TCP" (RFC1006) packets from using "follow TCP stream" correctly
+ *
+ * A future conversation handling might be able to handle different kinds of conversations
+ * (TCP, ISO, TCP on TCP, ...), but in that case this has to be fixed in any case.
+ */
+ /*pinfo->srcport = src_ref;*/
+ /*pinfo->destport = dst_ref;*/
+ switch(reason) {
+ case (128+0): str = "Normal Disconnect"; break;
+ case (128+1): str = "Remote transport entity congestion"; break;
+ case (128+2): str = "Connection negotiation failed"; break;
+ case (128+3): str = "Duplicate source reference"; break;
+ case (128+4): str = "Mismatched references"; break;
+ case (128+5): str = "Protocol error"; break;
+ case (128+7): str = "Reference overflow"; break;
+ case (128+8): str = "Connection requestion refused"; break;
+ case (128+10):str = "Header or parameter length invalid"; break;
+ case (0): str = "Reason not specified"; break;
+ case (1): str = "Congestion at TSAP"; break;
+ case (2): str = "Session entity not attached to TSAP"; break;
+ case (3): str = "Address unknown"; break;
+ default: return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "DR TPDU src-ref: 0x%04x dst-ref: 0x%04x",
+ src_ref, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
+ "TPDU code: 0x%x (DR)", tpdu);
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
+ proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset + 4, 2, src_ref);
+ proto_tree_add_text(cotp_tree, tvb, offset + 6, 1,
+ "Cause: %s", str);
+ }
+
+ offset += li + 1;
+
+ /* User data */
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ offset += tvb_length_remaining(tvb, offset);
+ /* we dissected all of the containing PDU */
+
+ return offset;
+
+} /* ositp_decode_DR */
+
+static int ositp_decode_DT(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ packet_info *pinfo, proto_tree *tree,
+ gboolean uses_inactive_subset,
+ gboolean *subdissector_found)
+{
+ proto_tree *cotp_tree = NULL;
+ proto_item *ti;
+ gboolean is_extended;
+ gboolean is_class_234;
+ guint16 dst_ref;
+ guint tpdu_nr;
+ guint fragment = 0;
+ guint32 fragment_length = 0;
+ tvbuff_t *next_tvb;
+ tvbuff_t *reassembled_tvb = NULL;
+ fragment_data *fd_head;
+
+ /* VP_CHECKSUM is the only parameter allowed in the variable part.
+ (This means we may misdissect this if the packet is bad and
+ contains other parameters.) */
+ switch (li) {
+
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
+ return -1;
+ /* FALLTHROUGH */
+
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ fragment = 1;
+ is_extended = FALSE;
+ is_class_234 = TRUE;
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ break;
+
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
+ return -1;
+ /* FALLTHROUGH */
+
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ fragment = 1;
+ is_extended = TRUE;
+ is_class_234 = TRUE;
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ break;
+
+ case LI_NORMAL_DT_CLASS_01 :
+ tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_0_1);
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ fragment = 1;
+ is_extended = FALSE;
+ is_class_234 = FALSE;
+ dst_ref = 0;
+ break;
+
+ default : /* bad TPDU */
+ return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ /* pinfo->destport = dst_ref; */
+ /* pinfo->srcport = 0; */
+ pinfo->fragmented = fragment;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (is_class_234) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x %s",
+ tpdu_nr,
+ dst_ref,
+ (fragment)? "(fragment)" : "");
+ } else {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) %s",
+ tpdu_nr,
+ (fragment)? "(fragment)" : "");
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
+ "TPDU code: 0x%x (DT)", tpdu);
+ }
+ offset += 1;
+ li -= 1;
+
+ if (is_class_234) {
+ if (tree)
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
+ offset += 2;
+ li -= 2;
+ }
+
+ if (is_extended) {
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 4,
+ "TPDU number: 0x%08x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ }
+ offset += 4;
+ li -= 4;
+ } else {
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "TPDU number: 0x%02x (%s)",
+ tpdu_nr,
+ (fragment)? "fragment":"complete");
+ }
+ offset += 1;
+ li -= 1;
+ }
+
+ if (tree)
+ ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
+ offset += li;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (cotp_reassemble) {
+ fragment_length = tvb_length(next_tvb);
+ /*
+ * XXX - these sequence numbers are connection sequence number,
+ * not segment sequence numbers - the first segment of a
+ * segmented packet doesn't have a specific sequence number (e.g., 0
+ * or 1), it has whatever the appropriate sequence number is for
+ * it in the connection.
+ *
+ * For now, we assume segments arrive in order, and just supply
+ * the negation of the EOT flag as the "more flags" argument.
+ * We should probably handle out-of-order packets separately,
+ * so that we can deliver them in order even when *not*
+ * reassembling.
+ *
+ * Note also that TP0 has no sequence number, and relies on
+ * the protocol atop which it runs to guarantee in-order delivery.
+ */
+ fd_head = fragment_add_seq_next(next_tvb, 0, pinfo, dst_ref,
+ cotp_segment_table,
+ cotp_reassembled_table,
+ fragment_length, fragment);
+ if (fd_head) {
+ if (fd_head->next) {
+ /* This is the last packet */
+ reassembled_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->len,
+ fd_head->len);
+ tvb_set_child_real_data_tvbuff(next_tvb, reassembled_tvb);
+ add_new_data_source(pinfo, reassembled_tvb, "Reassembled COTP");
+
+ show_fragment_seq_tree(fd_head,
+ &cotp_frag_items,
+ cotp_tree,
+ pinfo, reassembled_tvb);
+ pinfo->fragmented = fragment;
+ next_tvb = reassembled_tvb;
+ }
+ }
+ if (fragment && reassembled_tvb == NULL) {
+ proto_tree_add_text(cotp_tree, tvb, offset, -1,
+ "User data (%u byte%s)", fragment_length,
+ plurality(fragment_length, "", "s"));
+ }
+
+ }
+
+ if (uses_inactive_subset) {
+ if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
+ pinfo, tree)) {
+ *subdissector_found = TRUE;
+ } else {
+ /* Fill in other Dissectors using inactive subset here */
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+ } else {
+ /*
+ * We dissect payload if one of the following is TRUE:
+ *
+ * - Reassembly option for COTP in preferences is unchecked
+ * - Reassembly option is checked and this packet is the last fragment
+ */
+ if ( (!cotp_reassemble) ||
+ ((cotp_reassemble) && (!fragment))) {
+ if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb,
+ pinfo, tree)) {
+ *subdissector_found = TRUE;
+ } else {
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+ }
+ }
+
+ offset += tvb_length_remaining(tvb, offset);
+ /* we dissected all of the containing PDU */
+
+ return offset;
+
+} /* ositp_decode_DT */
+
+static int ositp_decode_ED(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *cotp_tree = NULL;
+ proto_item *ti;
+ gboolean is_extended;
+ guint16 dst_ref;
+ guint tpdu_nr;
+ tvbuff_t *next_tvb;
+
+ /* ED TPDUs are never fragmented */
+
+ /* VP_CHECKSUM is the only parameter allowed in the variable part.
+ (This means we may misdissect this if the packet is bad and
+ contains other parameters.) */
+ switch (li) {
+
+ case LI_NORMAL_DT_WITH_CHECKSUM :
+ if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM)
+ return -1;
+ /* FALLTHROUGH */
+
+ case LI_NORMAL_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
+ if ( tpdu_nr & 0x80 )
+ tpdu_nr = tpdu_nr & 0x7F;
+ else
+ return -1;
+ is_extended = FALSE;
+ break;
+
+ case LI_EXTENDED_DT_WITH_CHECKSUM :
+ if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM)
+ return -1;
+ /* FALLTHROUGH */
+
+ case LI_EXTENDED_DT_WITHOUT_CHECKSUM :
+ tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
+ if ( tpdu_nr & 0x80000000 )
+ tpdu_nr = tpdu_nr & 0x7FFFFFFF;
+ else
+ return -1;
+ is_extended = TRUE;
+ break;
+
+ default : /* bad TPDU */
+ return -1;
+ /*NOTREACHED*/
+ break;
+ } /* li */
+
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+
+ /* pinfo->destport = dst_ref; */
+ /* pinfo->srcport = 0; */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
+ "TPDU code: 0x%x (ED)", tpdu);
+ }
+ offset += 1;
+ li -= 1;
+
+ if (tree)
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
+ offset += 2;
+ li -= 2;
+
+ if (is_extended) {
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 4,
+ "TPDU number: 0x%02x", tpdu_nr);
+ }
+ offset += 4;
+ li -= 4;
+ } else {
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "TPDU number: 0x%02x", tpdu_nr);
+ }
+ offset += 1;
+ li -= 1;
+ }
+
+ if (tree)
+ ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
+ offset += li;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+
+ offset += tvb_length_remaining(tvb, offset);
+ /* we dissected all of the containing PDU */
+
+ return offset;
+
+} /* ositp_decode_ED */
+
+static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ guint8 cdt, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ guint16 dst_ref;
+ guint tpdu_nr;
+ gushort credit = 0;
+
+ switch(li) {
+ case LI_NORMAL_RJ :
+ tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
+ break;
+ case LI_EXTENDED_RJ :
+ tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
+ credit = tvb_get_ntohs(tvb, offset + P_CDT_IN_RJ);
+ break;
+ default :
+ return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+
+ /* pinfo->destport = dst_ref; */
+ /* pinfo->srcport = 0; */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
+ "TPDU code: 0x%x (RJ)", tpdu);
+ if (li == LI_NORMAL_RJ)
+ proto_tree_add_text(cotp_tree, tvb, offset + 1, 1,
+ "Credit: %u", cdt);
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
+ if (li == LI_NORMAL_RJ)
+ proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ else {
+ proto_tree_add_text(cotp_tree, tvb, offset + 4, 4,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ proto_tree_add_text(cotp_tree, tvb, offset + 8, 2,
+ "Credit: 0x%02x", credit);
+ }
+ }
+
+ offset += li + 1;
+
+ return offset;
+
+} /* ositp_decode_RJ */
+
+static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ packet_info *pinfo, proto_tree *tree,
+ gboolean uses_inactive_subset,
+ gboolean *subdissector_found)
+{
+
+ /* CC & CR decoding in the same function */
+
+ proto_tree *cotp_tree = NULL;
+ proto_item *ti;
+ guint16 dst_ref, src_ref;
+ guchar class_option;
+ tvbuff_t *next_tvb;
+
+ src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
+
+ class_option = (tvb_get_guint8(tvb, offset + P_CLASS_OPTION) >> 4 ) & 0x0F;
+ if (class_option > 4)
+ return -1;
+
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ /* pinfo->srcport = src_ref; */
+ /* pinfo->destport = dst_ref; */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
+ (tpdu == CR_TPDU) ? "CR" : "CC",
+ src_ref,
+ dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
+ "TPDU code: 0x%x (%s)", tpdu,
+ (tpdu == CR_TPDU) ? "CR" : "CC");
+ }
+ offset += 1;
+ li -= 1;
+
+ if (tree)
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
+ offset += 2;
+ li -= 2;
+
+ if (tree)
+ proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
+ offset += 2;
+ li -= 2;
+
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Class option: 0x%02x", class_option);
+ }
+ offset += 1;
+ li -= 1;
+
+ if (tree)
+ ositp_decode_var_part(tvb, offset, li, class_option, cotp_tree);
+ offset += li;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (!uses_inactive_subset){
+ if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb,
+ pinfo, tree)) {
+ *subdissector_found = TRUE;
+ } else {
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+ }
+ else
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ offset += tvb_length_remaining(tvb, offset);
+ /* we dissected all of the containing PDU */
+
+ return offset;
+
+} /* ositp_decode_CC */
+
+static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *cotp_tree = NULL;
+ proto_item *ti;
+ guint16 dst_ref, src_ref;
+
+ if (li > LI_MAX_DC)
+ return -1;
+
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
+
+ /* pinfo->srcport = src_ref; */
+ /* pinfo->destport = dst_ref; */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
+ src_ref,
+ dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
+ "TPDU code: 0x%x (DC)", tpdu);
+ }
+ offset += 1;
+ li -= 1;
+
+ if (tree)
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
+ offset += 2;
+ li -= 2;
+
+ if (tree)
+ proto_tree_add_uint(cotp_tree, hf_cotp_srcref, tvb, offset, 2, src_ref);
+ offset += 2;
+ li -= 2;
+
+ if (tree)
+ ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
+ offset += li;
+
+ return offset;
+
+} /* ositp_decode_DC */
+
+static int ositp_decode_AK(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ guint8 cdt, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *cotp_tree = NULL;
+ proto_item *ti;
+ guint16 dst_ref;
+ guint tpdu_nr;
+ gushort cdt_in_ak;
+
+ if (li > LI_MAX_AK)
+ return -1;
+
+ if (is_LI_NORMAL_AK(li)) {
+
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
+
+ /* pinfo->srcport = 0; */
+ /* pinfo->destport = dst_ref; */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
+ "TPDU code: 0x%x (AK)", tpdu);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Credit: %u", cdt);
+ }
+ offset += 1;
+ li -= 1;
+
+ if (tree)
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
+ offset += 2;
+ li -= 2;
+
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ }
+ offset += 1;
+ li -= 1;
+
+ if (tree)
+ ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
+ offset += li;
+
+ } else { /* extended format */
+
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
+ cdt_in_ak = tvb_get_ntohs(tvb, offset + P_CDT_IN_AK);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
+ tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
+ "TPDU code: 0x%x (AK)", tpdu);
+ }
+ offset += 1;
+ li -= 1;
+
+ if (tree)
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
+ offset += 2;
+ li -= 2;
+
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 4,
+ "Your TPDU number: 0x%08x", tpdu_nr);
+ }
+ offset += 4;
+ li -= 4;
+
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 2,
+ "Credit: 0x%04x", cdt_in_ak);
+ }
+ offset += 2;
+ li -= 2;
+
+ if (tree)
+ ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
+ offset += li;
+
+ } /* is_LI_NORMAL_AK */
+
+ return offset;
+
+} /* ositp_decode_AK */
+
+static int ositp_decode_EA(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *cotp_tree = NULL;
+ proto_item *ti;
+ gboolean is_extended;
+ guint16 dst_ref;
+ guint tpdu_nr;
+
+ if (li > LI_MAX_EA)
+ return -1;
+
+ /* VP_CHECKSUM is the only parameter allowed in the variable part.
+ (This means we may misdissect this if the packet is bad and
+ contains other parameters.) */
+ switch (li) {
+
+ case LI_NORMAL_EA_WITH_CHECKSUM :
+ if (tvb_get_guint8(tvb, offset + P_VAR_PART_NDT) != VP_CHECKSUM ||
+ tvb_get_guint8(tvb, offset + P_VAR_PART_NDT + 1) != 2)
+ return -1;
+ /* FALLTHROUGH */
+
+ case LI_NORMAL_EA_WITHOUT_CHECKSUM :
+ tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
+ is_extended = FALSE;
+ break;
+
+ case LI_EXTENDED_EA_WITH_CHECKSUM :
+ if (tvb_get_guint8(tvb, offset + P_VAR_PART_EDT) != VP_CHECKSUM ||
+ tvb_get_guint8(tvb, offset + P_VAR_PART_EDT + 1) != 2)
+ return -1;
+ /* FALLTHROUGH */
+
+ case LI_EXTENDED_EA_WITHOUT_CHECKSUM :
+ tpdu_nr = tvb_get_ntohl(tvb, offset + P_TPDU_NR_234);
+ is_extended = TRUE;
+ break;
+
+ default : /* bad TPDU */
+ return -1;
+ /*NOTREACHED*/
+ break;
+ } /* li */
+
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ /* pinfo->srcport = 0; */
+ /* pinfo->destport = dst_ref; */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset, 1, tpdu,
+ "TPDU code: 0x%x (EA)", tpdu);
+ }
+ offset += 1;
+ li -= 1;
+
+ if (tree)
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset, 2, dst_ref);
+ offset += 2;
+ li -= 2;
+
+ if (is_extended) {
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 4,
+ "Your TPDU number: 0x%08x", tpdu_nr);
+ }
+ offset += 4;
+ li -= 4;
+ } else {
+ if (tree) {
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Your TPDU number: 0x%02x", tpdu_nr);
+ }
+ offset += 1;
+ li -= 1;
+ }
+
+ if (tree)
+ ositp_decode_var_part(tvb, offset, li, 4, cotp_tree);
+ offset += li;
+
+ return offset;
+
+} /* ositp_decode_EA */
+
+static int ositp_decode_ER(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *cotp_tree;
+ proto_item *ti;
+ guchar *str;
+ guint16 dst_ref;
+
+ if (li > LI_MAX_ER)
+ return -1;
+
+ switch(tvb_get_guint8(tvb, offset + P_REJECT_ER)) {
+ case 0 :
+ str = "Reason not specified";
+ break;
+ case 1 :
+ str = "Invalid parameter code";
+ break;
+ case 2 :
+ str = "Invalid TPDU type";
+ break;
+ case 3 :
+ str = "Invalid parameter value";
+ break;
+ default:
+ return -1;
+ /*NOTREACHED*/
+ break;
+ }
+
+ dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ /* pinfo->srcport = 0; */
+ /* pinfo->destport = dst_ref; */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cotp, tvb, offset, li + 1, FALSE);
+ cotp_tree = proto_item_add_subtree(ti, ett_cotp);
+ proto_tree_add_text(cotp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ proto_tree_add_uint_format(cotp_tree, hf_cotp_type, tvb, offset + 1, 1, tpdu,
+ "TPDU code: 0x%x (ER)", tpdu);
+ proto_tree_add_uint(cotp_tree, hf_cotp_destref, tvb, offset + 2, 2, dst_ref);
+ proto_tree_add_text(cotp_tree, tvb, offset + 4, 1,
+ "Reject cause: %s", str);
+ }
+
+ offset += li + 1;
+
+ return offset;
+
+} /* ositp_decode_ER */
+
+static int ositp_decode_UD(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *cltp_tree = NULL;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "UD TPDU");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cltp, tvb, offset, li + 1, FALSE);
+ cltp_tree = proto_item_add_subtree(ti, ett_cltp);
+ proto_tree_add_text(cltp_tree, tvb, offset, 1,
+ "Length indicator: %u", li);
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_uint_format(cltp_tree, hf_cltp_type, tvb, offset, 1, tpdu,
+ "TPDU code: 0x%x (UD)", tpdu);
+ }
+ offset += 1;
+ li -= 1;
+
+ if (tree)
+ ositp_decode_var_part(tvb, offset, li, 0, cltp_tree);
+ offset += li;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ offset += tvb_length_remaining(tvb, offset);
+ /* we dissected all of the containing PDU */
+
+ return offset;
+
+} /* ositp_decode_UD */
+
+/* Returns TRUE if we found at least one valid COTP or CLTP PDU, FALSE
+ otherwise.
+
+ There doesn't seem to be any way in which the OSI network layer protocol
+ distinguishes between COTP and CLTP, but the first two octets of both
+ protocols' headers mean the same thing - length and PDU type - and the
+ only valid CLTP PDU type is not a valid COTP PDU type, so we'll handle
+ both of them here. */
+static gboolean dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, gboolean uses_inactive_subset)
+{
+ int offset = 0;
+ guint8 li, tpdu, cdt;
+ gboolean first_tpdu = TRUE;
+ int new_offset;
+ gboolean found_ositp = FALSE;
+ gboolean is_cltp = FALSE;
+ gboolean subdissector_found = FALSE;
+
+ if (!proto_is_protocol_enabled(find_protocol_by_id(proto_cotp)))
+ return FALSE; /* COTP has been disabled */
+ /* XXX - what about CLTP? */
+
+ pinfo->current_proto = "COTP";
+
+ /* Initialize the COL_INFO field; each of the TPDUs will have its
+ information appended. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "");
+
+ while (tvb_offset_exists(tvb, offset)) {
+ if (!first_tpdu) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ }
+ if ((li = tvb_get_guint8(tvb, offset + P_LI)) == 0) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Length indicator is zero");
+ if (!first_tpdu)
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, tree);
+ return found_ositp;
+ }
+
+ tpdu = (tvb_get_guint8(tvb, offset + P_TPDU) >> 4) & 0x0F;
+ if (tpdu == UD_TPDU)
+ pinfo->current_proto = "CLTP"; /* connectionless transport */
+ cdt = tvb_get_guint8(tvb, offset + P_CDT) & 0x0F;
+
+ switch (tpdu) {
+ case CC_TPDU :
+ case CR_TPDU :
+ new_offset = ositp_decode_CC(tvb, offset, li, tpdu, pinfo, tree,
+ uses_inactive_subset, &subdissector_found);
+ break;
+ case DR_TPDU :
+ new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
+ break;
+ case DT_TPDU :
+ new_offset = ositp_decode_DT(tvb, offset, li, tpdu, pinfo, tree,
+ uses_inactive_subset, &subdissector_found);
+ break;
+ case ED_TPDU :
+ new_offset = ositp_decode_ED(tvb, offset, li, tpdu, pinfo, tree);
+ break;
+ case RJ_TPDU :
+ new_offset = ositp_decode_RJ(tvb, offset, li, tpdu, cdt, pinfo, tree);
+ break;
+ case DC_TPDU :
+ new_offset = ositp_decode_DC(tvb, offset, li, tpdu, pinfo, tree);
+ break;
+ case AK_TPDU :
+ new_offset = ositp_decode_AK(tvb, offset, li, tpdu, cdt, pinfo, tree);
+ break;
+ case EA_TPDU :
+ new_offset = ositp_decode_EA(tvb, offset, li, tpdu, pinfo, tree);
+ break;
+ case ER_TPDU :
+ new_offset = ositp_decode_ER(tvb, offset, li, tpdu, pinfo, tree);
+ break;
+ case UD_TPDU :
+ new_offset = ositp_decode_UD(tvb, offset, li, tpdu, pinfo, tree);
+ is_cltp = TRUE;
+ break;
+ default :
+ if (first_tpdu && check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TPDU type (0x%x)", tpdu);
+ new_offset = -1; /* bad PDU type */
+ break;
+ }
+
+ if (new_offset == -1) { /* incorrect TPDU */
+ if (!first_tpdu)
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, tree);
+ break;
+ }
+
+ if (first_tpdu) {
+ /* Well, we found at least one valid COTP or CLTP PDU, so I guess this
+ is either COTP or CLTP. */
+ if (!subdissector_found && check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, is_cltp ? "CLTP" : "COTP");
+ found_ositp = TRUE;
+ }
+
+ offset = new_offset;
+ first_tpdu = FALSE;
+ }
+ return found_ositp;
+} /* dissect_ositp_internal */
+
+static void dissect_ositp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (!dissect_ositp_internal(tvb, pinfo, tree, FALSE))
+ call_dissector(data_handle,tvb, pinfo, tree);
+}
+
+/*
+ * CLNP part / main entry point
+*/
+
+static void dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *clnp_tree = NULL;
+ proto_item *ti;
+ guint8 cnf_proto_id;
+ guint8 cnf_hdr_len;
+ guint8 cnf_vers;
+ guint8 cnf_ttl;
+ guint8 cnf_type;
+ char flag_string[6+1];
+ char *pdu_type_string;
+ proto_tree *type_tree;
+ guint16 segment_length;
+ guint16 du_id = 0;
+ guint16 segment_offset = 0;
+ guint16 cnf_cksum;
+ cksum_status_t cksum_status;
+ int offset;
+ guchar src_len, dst_len, nsel, opt_len = 0;
+ const guint8 *dst_addr, *src_addr;
+ gint len;
+ guint next_length;
+ proto_tree *discpdu_tree;
+ gboolean save_in_error_pkt;
+ fragment_data *fd_head;
+ tvbuff_t *next_tvb;
+ gboolean update_col_info = TRUE;
+ gboolean save_fragmented;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CLNP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
+ if (cnf_proto_id == NLPID_NULL) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, FALSE);
+ clnp_tree = proto_item_add_subtree(ti, ett_clnp);
+ proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
+ cnf_proto_id,
+ "Inactive subset");
+ }
+ next_tvb = tvb_new_subset(tvb, 1, -1, -1);
+ dissect_ositp_internal(next_tvb, pinfo, tree, TRUE);
+ return;
+ }
+
+ /* return if version not known */
+ cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
+ if (cnf_vers != ISO8473_V1) {
+ call_dissector(data_handle,tvb, pinfo, tree);
+ return;
+ }
+
+ /* fixed part decoding */
+ cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
+ opt_len = cnf_hdr_len;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, FALSE);
+ clnp_tree = proto_item_add_subtree(ti, ett_clnp);
+ proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
+ cnf_proto_id);
+ proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
+ cnf_hdr_len);
+ proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
+ cnf_vers);
+ cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
+ proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
+ cnf_ttl,
+ "Holding Time : %u (%u.%u secs)",
+ cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
+ }
+
+ cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
+ pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
+ "Unknown (0x%02x)");
+ flag_string[0] = '\0';
+ if (cnf_type & CNF_SEG_OK)
+ strcat(flag_string, "S ");
+ if (cnf_type & CNF_MORE_SEGS)
+ strcat(flag_string, "M ");
+ if (cnf_type & CNF_ERR_OK)
+ strcat(flag_string, "E ");
+ if (tree) {
+ ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
+ cnf_type,
+ "PDU Type : 0x%02x (%s%s)",
+ cnf_type,
+ flag_string,
+ pdu_type_string);
+ type_tree = proto_item_add_subtree(ti, ett_clnp_type);
+ proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
+ decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8,
+ "Segmentation permitted",
+ "Segmentation not permitted"));
+ proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
+ decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8,
+ "More segments",
+ "Last segment"));
+ proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
+ decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8,
+ "Report error if PDU discarded",
+ "Don't report error if PDU discarded"));
+ proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
+ decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8,
+ npdu_type_vals, "%s"));
+ }
+
+ /* If we don't have the full header - i.e., not enough to see the
+ segmentation part and determine whether this datagram is segmented
+ or not - set the Info column now; we'll get an exception before
+ we set it otherwise. */
+
+ if (!tvb_bytes_exist(tvb, 0, cnf_hdr_len)) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
+ }
+
+ segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
+ cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
+ cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
+ if (tree) {
+ proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
+ segment_length);
+ switch (cksum_status) {
+
+ default:
+ /*
+ * No checksum present, or not enough of the header present to
+ * checksum it.
+ */
+ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
+ P_CLNP_CKSUM, 2,
+ cnf_cksum,
+ "Checksum : 0x%04x",
+ cnf_cksum);
+ break;
+
+ case CKSUM_OK:
+ /*
+ * Checksum is correct.
+ */
+ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
+ P_CLNP_CKSUM, 2,
+ cnf_cksum,
+ "Checksum : 0x%04x (correct)",
+ cnf_cksum);
+ break;
+
+ case CKSUM_NOT_OK:
+ /*
+ * Checksum is not correct.
+ */
+ proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
+ P_CLNP_CKSUM, 2,
+ cnf_cksum,
+ "Checksum : 0x%04x (incorrect)",
+ cnf_cksum);
+ break;
+ }
+ opt_len -= 9; /* Fixed part of Hesder */
+ } /* tree */
+
+ /* address part */
+
+ offset = P_CLNP_ADDRESS_PART;
+ dst_len = tvb_get_guint8(tvb, offset);
+ dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
+ nsel = tvb_get_guint8(tvb, offset + dst_len);
+ src_len = tvb_get_guint8(tvb, offset + dst_len + 1);
+ src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);
+
+ if (tree) {
+ proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
+ dst_len);
+ proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
+ dst_addr,
+ " DA : %s",
+ print_nsap_net(dst_addr, dst_len));
+ proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
+ offset + 1 + dst_len, 1, src_len);
+ proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
+ offset + dst_len + 2, src_len,
+ src_addr,
+ " SA : %s",
+ print_nsap_net(src_addr, src_len));
+
+ opt_len -= dst_len + src_len +2;
+ }
+
+ SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
+ SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
+ SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
+ SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);
+
+ /* Segmentation Part */
+
+ offset += dst_len + src_len + 2;
+
+ if (cnf_type & CNF_SEG_OK) {
+ struct clnp_segment seg; /* XXX - not used */
+ tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg)); /* XXX - not used */
+
+ segment_offset = tvb_get_ntohs(tvb, offset + 2);
+ du_id = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_text(clnp_tree, tvb, offset, 2,
+ "Data unit identifier: %06u",
+ du_id);
+ proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
+ "Segment offset : %6u",
+ segment_offset);
+ proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
+ "Total length : %6u",
+ tvb_get_ntohs(tvb, offset + 4));
+ }
+
+ offset += 6;
+ opt_len -= 6;
+ }
+
+ if (tree) {
+ /* To do : decode options */
+/*
+ proto_tree_add_text(clnp_tree, tvb, offset,
+ cnf_hdr_len - offset,
+ "Options/Data: <not shown>");
+*/
+/* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/
+
+ dissect_osi_options( opt_len,
+ tvb, offset, clnp_tree );
+ }
+
+ /* Length of CLNP datagram plus headers above it. */
+ len = segment_length;
+
+ offset = cnf_hdr_len;
+
+ /* If clnp_reassemble is on, this is a segment, we have all the
+ * data in the segment, and the checksum is valid, then just add the
+ * segment to the hashtable.
+ */
+ save_fragmented = pinfo->fragmented;
+ if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
+ ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
+ tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
+ cksum_status != CKSUM_NOT_OK) {
+ fd_head = fragment_add_check(tvb, offset, pinfo, du_id, clnp_segment_table,
+ clnp_reassembled_table, segment_offset,
+ segment_length - cnf_hdr_len,
+ cnf_type & CNF_MORE_SEGS);
+
+ next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
+ fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
+ } else {
+ /* If this is the first segment, dissect its contents, otherwise
+ just show it as a segment.
+
+ XXX - if we eventually don't save the reassembled contents of all
+ segmented datagrams, we may want to always reassemble. */
+ if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
+ /* Not the first segment - don't dissect it. */
+ next_tvb = NULL;
+ } else {
+ /* First segment, or not segmented. Dissect what we have here. */
+
+ /* Get a tvbuff for the payload. */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ /*
+ * If this is the first segment, but not the only segment,
+ * tell the next protocol that.
+ */
+ if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
+ pinfo->fragmented = TRUE;
+ else
+ pinfo->fragmented = FALSE;
+ }
+ }
+
+ if (next_tvb == NULL) {
+ /* Just show this as a segment. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
+ pdu_type_string, flag_string, segment_offset);
+
+ /* As we haven't reassembled anything, we haven't changed "pi", so
+ we don't have to restore it. */
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
+ tree);
+ pinfo->fragmented = save_fragmented;
+ return;
+ }
+
+ if (tvb_offset_exists(tvb, offset)) {
+ switch (cnf_type & CNF_TYPE) {
+
+ case DT_NPDU:
+ case MD_NPDU:
+ /* Continue with COTP if any data.
+ XXX - if this isn't the first Derived PDU of a segmented Initial
+ PDU, skip that? */
+
+ if (nsel == (char)tp_nsap_selector || always_decode_transport) {
+ if (dissect_ositp_internal(next_tvb, pinfo, tree, FALSE)) {
+ pinfo->fragmented = save_fragmented;
+ return; /* yes, it appears to be COTP or CLTP */
+ }
+ }
+ if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
+ pinfo, tree)) {
+ pinfo->fragmented = save_fragmented;
+ return; /* yes, it appears to be COTP or CLTP */
+ }
+
+ break;
+
+ case ER_NPDU:
+ /* The payload is the header and "none, some, or all of the data
+ part of the discarded PDU", i.e. it's like an ICMP error;
+ dissect it as a CLNP PDU. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
+ if (tree) {
+ next_length = tvb_length_remaining(tvb, offset);
+ if (next_length != 0) {
+ /* We have payload; dissect it. */
+ ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
+ "Discarded PDU");
+ discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);
+
+ /* Save the current value of the "we're inside an error packet"
+ flag, and set that flag; subdissectors may treat packets
+ that are the payload of error packets differently from
+ "real" packets. */
+ save_in_error_pkt = pinfo->in_error_pkt;
+ pinfo->in_error_pkt = TRUE;
+
+ call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);
+
+ /* Restore the "we're inside an error packet" flag. */
+ pinfo->in_error_pkt = save_in_error_pkt;
+ }
+ }
+ pinfo->fragmented = save_fragmented;
+ return; /* we're done with this PDU */
+
+ case ERQ_NPDU:
+ case ERP_NPDU:
+ /* XXX - dissect this */
+ break;
+ }
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ pinfo->fragmented = save_fragmented;
+} /* dissect_clnp */
+
+static void
+clnp_reassemble_init(void)
+{
+ fragment_table_init(&clnp_segment_table);
+ reassembled_table_init(&clnp_reassembled_table);
+}
+
+static void
+cotp_reassemble_init(void)
+{
+ fragment_table_init(&cotp_segment_table);
+ reassembled_table_init(&cotp_reassembled_table);
+}
+
+void proto_register_clnp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_clnp_id,
+ { "Network Layer Protocol Identifier", "clnp.nlpi", FT_UINT8, BASE_HEX,
+ VALS(nlpid_vals), 0x0, "", HFILL }},
+
+ { &hf_clnp_length,
+ { "HDR Length ", "clnp.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_version,
+ { "Version ", "clnp.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_ttl,
+ { "Holding Time ", "clnp.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_type,
+ { "PDU Type ", "clnp.type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_pdu_length,
+ { "PDU length ", "clnp.pdu.len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_checksum,
+ { "Checksum ", "clnp.checksum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_dest_length,
+ { "DAL ", "clnp.dsap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_dest,
+ { " DA ", "clnp.dsap", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_src_length,
+ { "SAL ", "clnp.ssap.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_src,
+ { " SA ", "clnp.ssap", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_clnp_segment_overlap,
+ { "Segment overlap", "clnp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment overlaps with other segments", HFILL }},
+
+ { &hf_clnp_segment_overlap_conflict,
+ { "Conflicting data in segment overlap", "clnp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping segments contained conflicting data", HFILL }},
+
+ { &hf_clnp_segment_multiple_tails,
+ { "Multiple tail segments found", "clnp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when reassembling the packet", HFILL }},
+
+ { &hf_clnp_segment_too_long_segment,
+ { "Segment too long", "clnp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment contained data past end of packet", HFILL }},
+
+ { &hf_clnp_segment_error,
+ { "Reassembly error", "clnp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Reassembly error due to illegal segments", HFILL }},
+
+ { &hf_clnp_segment,
+ { "CLNP Segment", "clnp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "CLNP Segment", HFILL }},
+
+ { &hf_clnp_segments,
+ { "CLNP Segments", "clnp.segments", FT_NONE, BASE_DEC, NULL, 0x0,
+ "CLNP Segments", HFILL }},
+
+ { &hf_clnp_reassembled_in,
+ { "Reassembled CLNP in frame", "clnp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This CLNP packet is reassembled in this frame", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_clnp,
+ &ett_clnp_type,
+ &ett_clnp_segments,
+ &ett_clnp_segment,
+ &ett_clnp_disc_pdu,
+ };
+
+ module_t *clnp_module;
+
+ proto_clnp = proto_register_protocol(PROTO_STRING_CLNP, "CLNP", "clnp");
+ proto_register_field_array(proto_clnp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("clnp", dissect_clnp, proto_clnp);
+ register_heur_dissector_list("clnp", &clnp_heur_subdissector_list);
+ register_init_routine(clnp_reassemble_init);
+ register_init_routine(cotp_reassemble_init);
+
+ clnp_module = prefs_register_protocol(proto_clnp, NULL);
+ prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
+ "NSAP selector for Transport Protocol (last byte in hex)",
+ "NSAP selector for Transport Protocol (last byte in hex)",
+ 16, &tp_nsap_selector);
+ prefs_register_bool_preference(clnp_module, "always_decode_transport",
+ "Always try to decode NSDU as transport PDUs",
+ "Always try to decode NSDU as transport PDUs",
+ &always_decode_transport);
+ prefs_register_bool_preference(clnp_module, "reassemble",
+ "Reassemble segmented CLNP datagrams",
+ "Whether segmented CLNP datagrams should be reassembled",
+ &clnp_reassemble);
+}
+
+void
+proto_reg_handoff_clnp(void)
+{
+ data_handle = find_dissector("data");
+
+ clnp_handle = create_dissector_handle(dissect_clnp, proto_clnp);
+ dissector_add("osinl", NLPID_ISO8473_CLNP, clnp_handle);
+ dissector_add("osinl", NLPID_NULL, clnp_handle); /* Inactive subset */
+ dissector_add("x.25.spi", NLPID_ISO8473_CLNP, clnp_handle);
+}
+
+void proto_register_cotp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_cotp_srcref,
+ { "Source reference", "cotp.srcref", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Source address reference", HFILL}},
+ { &hf_cotp_destref,
+ { "Destination reference", "cotp.destref", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Destination address reference", HFILL}},
+ { &hf_cotp_type,
+ { "COTP PDU Type", "cotp.type", FT_UINT8, BASE_HEX, VALS(cotp_tpdu_type_abbrev_vals), 0x0,
+ "COTP PDU Type", HFILL}},
+ { &hf_cotp_segment_overlap,
+ { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment overlaps with other segments", HFILL }},
+ { &hf_cotp_segment_overlap_conflict,
+ { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping segments contained conflicting data", HFILL }},
+ { &hf_cotp_segment_multiple_tails,
+ { "Multiple tail segments found", "cotp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when reassembling the packet", HFILL }},
+ { &hf_cotp_segment_too_long_segment,
+ { "Segment too long", "cotp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment contained data past end of packet", HFILL }},
+ { &hf_cotp_segment_error,
+ { "Reassembly error", "cotp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Reassembly error due to illegal segments", HFILL }},
+ { &hf_cotp_segment,
+ { "COTP Segment", "cotp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "COTP Segment", HFILL }},
+ { &hf_cotp_segments,
+ { "COTP Segments", "cotp.segments", FT_NONE, BASE_DEC, NULL, 0x0,
+ "COTP Segments", HFILL }},
+ { &hf_cotp_reassembled_in,
+ { "Reassembled COTP in frame", "cotp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This COTP packet is reassembled in this frame", HFILL }},
+/* ISO DP 8073 i13.3.4(a) Source and destination TSAPs are defined as
+ identifiers of unspecified type and length.
+ Some implementations of COTP use printable strings, others use raw bytes.
+ We always add both representations to the tree; one will always be hidden
+ depending on the tsap display preference */
+ { &hf_cotp_vp_src_tsap,
+ { "Source TSAP", "cotp.src-tsap", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Calling TSAP", HFILL }},
+ { &hf_cotp_vp_src_tsap_bytes,
+ { "Source TSAP", "cotp.src-tsap-bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Calling TSAP (bytes representation)", HFILL }},
+ { &hf_cotp_vp_dst_tsap,
+ { "Destination TSAP", "cotp.dst-tsap", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Called TSAP", HFILL }},
+ { &hf_cotp_vp_dst_tsap_bytes,
+ { "Destination TSAP", "cotp.dst-tsap-bytes", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Called TSAP (bytes representation)", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_cotp,
+ &ett_cotp_segment,
+ &ett_cotp_segments,
+ };
+
+ module_t *cotp_module;
+
+ proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "COTP", "cotp");
+ proto_register_field_array(proto_cotp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ cotp_module = prefs_register_protocol(proto_cotp, NULL);
+
+ prefs_register_bool_preference(cotp_module, "reassemble",
+ "Reassemble segmented COTP datagrams",
+ "Whether segmented COTP datagrams should be reassembled",
+ &cotp_reassemble);
+
+ prefs_register_enum_preference(cotp_module, "tsap_display",
+ "Display TSAPs as strings or bytes",
+ "How TSAPs should be displayed",
+ &tsap_display,
+ tsap_display_options,
+ FALSE);
+
+ /* subdissector code in inactive subset */
+ register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
+
+ /* other COTP/ISO 8473 subdissectors */
+ register_heur_dissector_list("cotp", &cotp_heur_subdissector_list);
+
+ /* XXX - what about CLTP and proto_cltp? */
+ register_dissector("ositp", dissect_ositp, proto_cotp);
+}
+
+void
+proto_reg_handoff_cotp(void)
+{
+ dissector_handle_t ositp_handle;
+
+ ositp_handle = find_dissector("ositp");
+ dissector_add("ip.proto", IP_PROTO_TP, ositp_handle);
+}
+
+void proto_register_cltp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_cltp_type,
+ { "CLTP PDU Type", "cltp.type", FT_UINT8, BASE_HEX, VALS(cltp_tpdu_type_abbrev_vals), 0x0,
+ "CLTP PDU Type", HFILL}},
+ };
+ static gint *ett[] = {
+ &ett_cltp,
+ };
+
+ proto_cltp = proto_register_protocol(PROTO_STRING_CLTP, "CLTP", "cltp");
+ proto_register_field_array(proto_cltp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/epan/dissectors/packet-cops.c b/epan/dissectors/packet-cops.c
new file mode 100644
index 0000000000..8db35e43ed
--- /dev/null
+++ b/epan/dissectors/packet-cops.c
@@ -0,0 +1,2637 @@
+/* packet-cops.c
+ * Routines for the COPS (Common Open Policy Service) protocol dissection
+ * RFC2748 & COPS-PR extension RFC3084
+ *
+ * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
+ *
+ * Added PacketCable specifications by Dick Gooris <gooris@lucent.com>
+ *
+ * Taken from PacketCable specifications :
+ * PacketCable Dynamic Quality-of-Service Specification
+ * Based on PKT-SP-DQOS-I09-040402 (April 2, 2004)
+ * www.packetcable.com
+ *
+ * Implemented in ethereal at April 7-8, 2004
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include "isprint.h"
+
+#include <epan/packet.h>
+#include "packet-ipv6.h"
+#include "packet-tcp.h"
+
+#ifdef HAVE_SOME_SNMP
+#ifdef HAVE_NET_SNMP
+# include <net-snmp/net-snmp-config.h>
+# include <net-snmp/mib_api.h>
+# include <net-snmp/library/default_store.h>
+# include <net-snmp/config_api.h>
+#else /* HAVE_NET_SNMP */
+# include <ucd-snmp/ucd-snmp-config.h>
+# include <ucd-snmp/asn1.h>
+# include <ucd-snmp/snmp_api.h>
+# include <ucd-snmp/snmp_impl.h>
+# include <ucd-snmp/mib.h>
+# include <ucd-snmp/default_store.h>
+# include <ucd-snmp/read_config.h>
+# include <ucd-snmp/tools.h>
+#endif /* HAVE_NET_SNMP */
+#endif /* HAVE_SOME_SNMP */
+
+#include "asn1.h"
+#include "format-oid.h"
+#include "prefs.h"
+
+/* For PacketCable, port 2126 */
+#define TCP_PORT_COPS 3288
+
+/* Preference: Variable to hold the tcp port preference */
+static guint global_cops_tcp_port = TCP_PORT_COPS;
+
+/* Preference: desegmentation of COPS */
+static gboolean cops_desegment = TRUE;
+
+/* Variable to allow for proper deletion of dissector registration
+ * when the user changes port from the gui
+ */
+
+static guint cops_tcp_port = 0;
+
+/*Some local globals needed to read COPS-PR ASN.1 Types from PIB-MIBs */
+/*MAX_OID_LEN from NET-SNMP's asn1.h*/
+
+#ifdef HAVE_NET_SNMP
+static subid_t last_decoded_prid_oid[MAX_OID_LEN]={0};
+static subid_t last_decoded_prid_oid_length=0;
+extern struct tree *tree_head;
+
+/* Preference: COPS-PR ASN.1 type decoding based on PIB/MIB or data in packet */
+static gboolean cops_typefrommib = FALSE;
+
+#endif /* HAVE_NET_SNMP */
+
+#define COPS_OBJECT_HDR_SIZE 4
+
+/* Null string of type "guchar[]". */
+static const guchar nullstring[] = "";
+
+#define SAFE_STRING(s) (((s) != NULL) ? (s) : nullstring)
+
+/* COPS PR Tags */
+
+#define COPS_IPA 0 /* IP Address */
+#define COPS_U32 2 /* Unsigned 32*/
+#define COPS_TIT 3 /* TimeTicks */
+#define COPS_OPQ 4 /* Opaque */
+#define COPS_I64 10 /* Integer64 */
+#define COPS_U64 11 /* Uinteger64 */
+
+/* COPS PR Types */
+
+#define COPS_NULL 0
+#define COPS_INTEGER 1 /* l */
+#define COPS_OCTETSTR 2 /* c */
+#define COPS_OBJECTID 3 /* ul */
+#define COPS_IPADDR 4 /* uc */
+#define COPS_UNSIGNED32 5 /* ul */
+#define COPS_TIMETICKS 7 /* ul */
+#define COPS_OPAQUE 8 /* c */
+#define COPS_INTEGER64 10 /* ll */
+#define COPS_UNSIGNED64 11 /* ull */
+
+
+typedef struct _COPS_CNV COPS_CNV;
+
+struct _COPS_CNV
+{
+ guint class;
+ guint tag;
+ gint syntax;
+ gchar *name;
+};
+
+static COPS_CNV CopsCnv [] =
+{
+ {ASN1_UNI, ASN1_NUL, COPS_NULL, "NULL"},
+ {ASN1_UNI, ASN1_INT, COPS_INTEGER, "INTEGER"},
+ {ASN1_UNI, ASN1_OTS, COPS_OCTETSTR, "OCTET STRING"},
+ {ASN1_UNI, ASN1_OJI, COPS_OBJECTID, "OBJECTID"},
+ {ASN1_APL, COPS_IPA, COPS_IPADDR, "IPADDR"},
+ {ASN1_APL, COPS_U32, COPS_UNSIGNED32,"UNSIGNED32"},
+ {ASN1_APL, COPS_TIT, COPS_TIMETICKS, "TIMETICKS"},
+ {ASN1_APL, COPS_OPQ, COPS_OPAQUE, "OPAQUE"},
+ {ASN1_APL, COPS_I64, COPS_INTEGER64, "INTEGER64"},
+ {ASN1_APL, COPS_U64, COPS_UNSIGNED64, "UNSIGNED64"},
+ {0, 0, -1, NULL}
+};
+
+static gchar *
+cops_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
+{
+ COPS_CNV *cnv;
+
+ cnv = CopsCnv;
+ while (cnv->syntax != -1)
+ {
+ if (cnv->tag == tag && cnv->class == cls)
+ {
+ *syntax = cnv->syntax;
+ return cnv->name;
+ }
+ cnv++;
+ }
+ return NULL;
+}
+
+static const value_string cops_flags_vals[] = {
+ { 0x00, "None" },
+ { 0x01, "Solicited Message Flag Bit" },
+ { 0, NULL },
+};
+
+/* The different COPS message types */
+enum cops_op_code {
+ COPS_NO_MSG, /* Not a COPS Message type */
+
+ COPS_MSG_REQ, /* Request (REQ) */
+ COPS_MSG_DEC, /* Decision (DEC) */
+ COPS_MSG_RPT, /* Report State (RPT) */
+ COPS_MSG_DRQ, /* Delete Request State (DRQ) */
+ COPS_MSG_SSQ, /* Synchronize State Req (SSQ) */
+ COPS_MSG_OPN, /* Client-Open (OPN) */
+ COPS_MSG_CAT, /* Client-Accept (CAT) */
+ COPS_MSG_CC, /* Client-Close (CC) */
+ COPS_MSG_KA, /* Keep-Alive (KA) */
+ COPS_MSG_SSC, /* Synchronize Complete (SSC) */
+
+ COPS_LAST_OP_CODE /* For error checking */
+};
+
+static const value_string cops_op_code_vals[] = {
+ { COPS_MSG_REQ, "Request (REQ)" },
+ { COPS_MSG_DEC, "Decision (DEC)" },
+ { COPS_MSG_RPT, "Report State (RPT)" },
+ { COPS_MSG_DRQ, "Delete Request State (DRQ)" },
+ { COPS_MSG_SSQ, "Synchronize State Req (SSQ)" },
+ { COPS_MSG_OPN, "Client-Open (OPN)" },
+ { COPS_MSG_CAT, "Client-Accept (CAT)" },
+ { COPS_MSG_CC, "Client-Close (CC)" },
+ { COPS_MSG_KA, "Keep-Alive (KA)" },
+ { COPS_MSG_SSC, "Synchronize Complete (SSC)" },
+ { 0, NULL },
+};
+
+
+/* The different objects in COPS messages */
+enum cops_c_num {
+ COPS_NO_OBJECT, /* Not a COPS Object type */
+
+ COPS_OBJ_HANDLE, /* Handle Object (Handle) */
+ COPS_OBJ_CONTEXT, /* Context Object (Context) */
+ COPS_OBJ_IN_INT, /* In-Interface Object (IN-Int) */
+ COPS_OBJ_OUT_INT, /* Out-Interface Object (OUT-Int) */
+ COPS_OBJ_REASON, /* Reason Object (Reason) */
+ COPS_OBJ_DECISION, /* Decision Object (Decision) */
+ COPS_OBJ_LPDPDECISION, /* LPDP Decision Object (LPDPDecision) */
+ COPS_OBJ_ERROR, /* Error Object (Error) */
+ COPS_OBJ_CLIENTSI, /* Client Specific Information Object (ClientSI) */
+ COPS_OBJ_KATIMER, /* Keep-Alive Timer Object (KATimer) */
+ COPS_OBJ_PEPID, /* PEP Identification Object (PEPID) */
+ COPS_OBJ_REPORT_TYPE, /* Report-Type Object (Report-Type) */
+ COPS_OBJ_PDPREDIRADDR, /* PDP Redirect Address Object (PDPRedirAddr) */
+ COPS_OBJ_LASTPDPADDR, /* Last PDP Address (LastPDPaddr) */
+ COPS_OBJ_ACCTTIMER, /* Accounting Timer Object (AcctTimer) */
+ COPS_OBJ_INTEGRITY, /* Message Integrity Object (Integrity) */
+ COPS_LAST_C_NUM /* For error checking */
+};
+
+static const value_string cops_c_num_vals[] = {
+ { COPS_OBJ_HANDLE, "Handle Object (Handle)" },
+ { COPS_OBJ_CONTEXT, "Context Object (Context)" },
+ { COPS_OBJ_IN_INT, "In-Interface Object (IN-Int)" },
+ { COPS_OBJ_OUT_INT, "Out-Interface Object (OUT-Int)" },
+ { COPS_OBJ_REASON, "Reason Object (Reason)" },
+ { COPS_OBJ_DECISION, "Decision Object (Decision)" },
+ { COPS_OBJ_LPDPDECISION, "LPDP Decision Object (LPDPDecision)" },
+ { COPS_OBJ_ERROR, "Error Object (Error)" },
+ { COPS_OBJ_CLIENTSI, "Client Specific Information Object (ClientSI)" },
+ { COPS_OBJ_KATIMER, "Keep-Alive Timer Object (KATimer)" },
+ { COPS_OBJ_PEPID, "PEP Identification Object (PEPID)" },
+ { COPS_OBJ_REPORT_TYPE, "Report-Type Object (Report-Type)" },
+ { COPS_OBJ_PDPREDIRADDR, "PDP Redirect Address Object (PDPRedirAddr)" },
+ { COPS_OBJ_LASTPDPADDR, "Last PDP Address (LastPDPaddr)" },
+ { COPS_OBJ_ACCTTIMER, "Accounting Timer Object (AcctTimer)" },
+ { COPS_OBJ_INTEGRITY, "Message Integrity Object (Integrity)" },
+ { 0, NULL },
+};
+
+
+/* The different objects in COPS-PR messages */
+enum cops_s_num {
+ COPS_NO_PR_OBJECT, /* Not a COPS-PR Object type */
+ COPS_OBJ_PRID, /* Provisioning Instance Identifier (PRID) */
+ COPS_OBJ_PPRID, /* Prefix Provisioning Instance Identifier (PPRID) */
+ COPS_OBJ_EPD, /* Encoded Provisioning Instance Data (EPD) */
+ COPS_OBJ_GPERR, /* Global Provisioning Error Object (GPERR) */
+ COPS_OBJ_CPERR, /* PRC Class Provisioning Error Object (CPERR) */
+ COPS_OBJ_ERRPRID, /* Error Provisioning Instance Identifier (ErrorPRID)*/
+
+ COPS_LAST_S_NUM /* For error checking */
+};
+
+
+static const value_string cops_s_num_vals[] = {
+ { COPS_OBJ_PRID, "Provisioning Instance Identifier (PRID)" },
+ { COPS_OBJ_PPRID, "Prefix Provisioning Instance Identifier (PPRID)" },
+ { COPS_OBJ_EPD, "Encoded Provisioning Instance Data (EPD)" },
+ { COPS_OBJ_GPERR, "Global Provisioning Error Object (GPERR)" },
+ { COPS_OBJ_CPERR, "PRC Class Provisioning Error Object (CPERR)" },
+ { COPS_OBJ_ERRPRID, "Error Provisioning Instance Identifier (ErrorPRID)" },
+ { 0, NULL },
+
+};
+
+/* R-Type is carried within the Context Object */
+static const value_string cops_r_type_vals[] = {
+ { 0x01, "Incoming-Message/Admission Control request" },
+ { 0x02, "Resource-Allocation request" },
+ { 0x04, "Outgoing-Message request" },
+ { 0x08, "Configuration request" },
+ { 0, NULL },
+};
+/* S-Type is carried within the ClientSI Object for COPS-PR*/
+static const value_string cops_s_type_vals[] = {
+ { 0x01, "BER" },
+ { 0, NULL },
+};
+
+/* Reason-Code is carried within the Reason object */
+static const value_string cops_reason_vals[] = {
+ { 1, "Unspecified" },
+ { 2, "Management" },
+ { 3, "Preempted (Another request state takes precedence)" },
+ { 4, "Tear (Used to communicate a signaled state removal)" },
+ { 5, "Timeout (Local state has timed-out)" },
+ { 6, "Route Change (Change invalidates request state)" },
+ { 7, "Insufficient Resources (No local resource available)" },
+ { 8, "PDP's Directive (PDP decision caused the delete)" },
+ { 9, "Unsupported decision (PDP decision not supported)" },
+ { 10, "Synchronize Handle Unknown" },
+ { 11, "Transient Handle (stateless event)" },
+ { 12, "Malformed Decision (could not recover)" },
+ { 13, "Unknown COPS Object from PDP" },
+ { 0, NULL },
+};
+
+/* Command-Code is carried within the Decision object if C-Type is 1 */
+static const value_string cops_dec_cmd_code_vals[] = {
+ { 0, "NULL Decision (No configuration data available)" },
+ { 1, "Install (Admit request/Install configuration)" },
+ { 2, "Remove (Remove request/Remove configuration)" },
+ { 0, NULL },
+};
+
+/* Decision flags are also carried with the Decision object if C-Type is 1 */
+static const value_string cops_dec_cmd_flag_vals[] = {
+ { 0x00, "<None set>" },
+ { 0x01, "Trigger Error (Trigger error message if set)" },
+ { 0, NULL },
+};
+
+/* Error-Code from Error object */
+static const value_string cops_error_vals[] = {
+ {1, "Bad handle" },
+ {2, "Invalid handle reference" },
+ {3, "Bad message format (Malformed Message)" },
+ {4, "Unable to process (server gives up on query)" },
+ {5, "Mandatory client-specific info missing" },
+ {6, "Unsupported client" },
+ {7, "Mandatory COPS object missing" },
+ {8, "Client Failure" },
+ {9, "Communication Failure" },
+ {10, "Unspecified" },
+ {11, "Shutting down" },
+ {12, "Redirect to Preferred Server" },
+ {13, "Unknown COPS Object" },
+ {14, "Authentication Failure" },
+ {15, "Authentication Required" },
+ {0, NULL },
+};
+/* Error-Code from GPERR object */
+static const value_string cops_gperror_vals[] = {
+ {1, "AvailMemLow" },
+ {2, "AvailMemExhausted" },
+ {3, "unknownASN.1Tag" },
+ {4, "maxMsgSizeExceeded" },
+ {5, "unknownError" },
+ {6, "maxRequestStatesOpen" },
+ {7, "invalidASN.1Length" },
+ {8, "invalidObjectPad" },
+ {9, "unknownPIBData" },
+ {10, "unknownCOPSPRObject" },
+ {11, "malformedDecision" },
+ {0, NULL },
+};
+
+/* Error-Code from CPERR object */
+static const value_string cops_cperror_vals[] = {
+ {1, "priSpaceExhausted" },
+ {2, "priInstanceInvalid" },
+ {3, "attrValueInvalid" },
+ {4, "attrValueSupLimited" },
+ {5, "attrEnumSupLimited" },
+ {6, "attrMaxLengthExceeded" },
+ {7, "attrReferenceUnknown" },
+ {8, "priNotifyOnly" },
+ {9, "unknownPrc" },
+ {10, "tooFewAttrs" },
+ {11, "invalidAttrType" },
+ {12, "deletedInRef" },
+ {13, "priSpecificError" },
+ {0, NULL },
+};
+
+
+/* Report-Type from Report-Type object */
+static const value_string cops_report_type_vals[] = {
+ {1, " Success : Decision was successful at the PEP" },
+ {2, " Failure : Decision could not be completed by PEP" },
+ {3, " Accounting: Accounting update for an installed state" },
+ {0, NULL },
+};
+
+/* The next tables are for PacketCable */
+
+/* Transaction ID table */
+static const value_string table_cops_transaction_id[] =
+{
+ { 0x1, "Gate Alloc" },
+ { 0x2, "Gate Alloc Ack" },
+ { 0x3, "Gate Alloc Err" },
+ { 0x4, "Gate Set" },
+ { 0x5, "Gate Set Ack" },
+ { 0x6, "Gate Set Err" },
+ { 0x7, "Gate Info" },
+ { 0x8, "Gate Info Ack" },
+ { 0x9, "Gate Info Err" },
+ { 0xa, "Gate Delete" },
+ { 0xb, "Gate Delete Ack" },
+ { 0xc, "Gate Delete Err" },
+ { 0xd, "Gate Open" },
+ { 0xe, "Gate Close" },
+ { 0xFF, NULL },
+};
+
+/* Direction */
+static const value_string table_cops_direction[] =
+{
+ { 0x0, "Downstream gate" },
+ { 0x1, "Upstream gate" },
+ { 0xFF, NULL },
+};
+
+/* Session Class */
+static const value_string table_cops_session_class[] =
+{
+ { 0x0, "Unspecified" },
+ { 0x1, "Normal priority VoIP session" },
+ { 0x2, "High priority VoIP session" },
+ { 0x3, "Reserved" },
+ { 0xFF, NULL },
+};
+
+/* Reason Code */
+static const value_string table_cops_reason_code[] =
+{
+ { 0x0, "Gate Delete Operation" },
+ { 0x1, "Gate Close Operation" },
+ { 0xFF, NULL },
+};
+
+/* Reason Sub Code - Delete */
+static const value_string table_cops_reason_subcode_delete[] =
+{
+ { 0x0, "Normal Operation" },
+ { 0x1, "Local Gate-coordination not completed" },
+ { 0x2, "Remote Gate-coordination not completed" },
+ { 0x3, "Authorization revoked" },
+ { 0x4, "Unexpected Gate-Open" },
+ { 0x5, "Local Gate-Close failure" },
+ { 0x127,"Unspecified error" },
+ { 0xFF, NULL },
+};
+
+/* Reason Sub Code - Close */
+static const value_string table_cops_reason_subcode_close[] =
+{
+ { 0x0, "Client initiated release (normal operation)" },
+ { 0x1, "Reservation reassignment" },
+ { 0x2, "Lack of reservation maintenance" },
+ { 0x3, "Lack of Docsis Mac-layer responses" },
+ { 0x4, "Timer T0 expiration; no Gate-Set received from CMS" },
+ { 0x5, "Timer T1 expiration; no Commit received from MTA" },
+ { 0x6, "Timer T7 expiration; Service Flow reservation timeout" },
+ { 0x7, "Timer T8 expiration; Service Flow inactivity in the upstream direction" },
+ { 0x127,"Unspecified error" },
+ { 0xFF, NULL },
+};
+
+/* PacketCable Error */
+static const value_string table_cops_packetcable_error[] =
+{
+ { 0x1, "No gates urrently available" },
+ { 0x2, "Unknown Gate ID" },
+ { 0x3, "Illegal Session Class value" },
+ { 0x4, "Subscriber exceeded gate limit" },
+ { 0x5, "Gate already set" },
+ { 0x6, "Missing Required Object" },
+ { 0x7, "Invalid Object" },
+ { 0x127,"Unspecified error" },
+ { 0xFF, NULL },
+};
+
+/* End of PacketCable Tables */
+
+
+/* Initialize the protocol and registered fields */
+static gint proto_cops = -1;
+static gint hf_cops_ver_flags = -1;
+static gint hf_cops_version = -1;
+static gint hf_cops_flags = -1;
+
+static gint hf_cops_op_code = -1;
+static gint hf_cops_client_type = -1;
+static gint hf_cops_msg_len = -1;
+
+static gint hf_cops_obj_len = -1;
+static gint hf_cops_obj_c_num = -1;
+static gint hf_cops_obj_c_type = -1;
+
+static gint hf_cops_obj_s_num = -1;
+static gint hf_cops_obj_s_type = -1;
+
+static gint hf_cops_r_type_flags = -1;
+static gint hf_cops_m_type_flags = -1;
+
+static gint hf_cops_in_int_ipv4 = -1;
+static gint hf_cops_in_int_ipv6 = -1;
+static gint hf_cops_out_int_ipv4 = -1;
+static gint hf_cops_out_int_ipv6 = -1;
+static gint hf_cops_int_ifindex = -1;
+
+static gint hf_cops_reason = -1;
+static gint hf_cops_reason_sub = -1;
+
+static gint hf_cops_dec_cmd_code = -1;
+static gint hf_cops_dec_flags = -1;
+
+static gint hf_cops_error = -1;
+static gint hf_cops_error_sub = -1;
+
+static gint hf_cops_gperror = -1;
+static gint hf_cops_gperror_sub = -1;
+
+static gint hf_cops_cperror = -1;
+static gint hf_cops_cperror_sub = -1;
+
+static gint hf_cops_katimer = -1;
+
+static gint hf_cops_pepid = -1;
+
+static gint hf_cops_report_type = -1;
+
+static gint hf_cops_pdprediraddr_ipv4 = -1;
+static gint hf_cops_pdprediraddr_ipv6 = -1;
+static gint hf_cops_lastpdpaddr_ipv4 = -1;
+static gint hf_cops_lastpdpaddr_ipv6 = -1;
+static gint hf_cops_pdp_tcp_port = -1;
+
+static gint hf_cops_accttimer = -1;
+
+static gint hf_cops_key_id = -1;
+static gint hf_cops_seq_num = -1;
+
+/* For PacketCable */
+static gint hf_cops_subtree = -1;
+static gint hf_cops_pc_activity_count = -1;
+static gint hf_cops_pc_algorithm = -1;
+static gint hf_cops_pc_close_subcode = -1;
+static gint hf_cops_pc_cmts_ip = -1;
+static gint hf_cops_pc_cmts_ip_port = -1;
+static gint hf_cops_pc_prks_ip = -1;
+static gint hf_cops_pc_prks_ip_port = -1;
+static gint hf_cops_pc_srks_ip = -1;
+static gint hf_cops_pc_srks_ip_port = -1;
+static gint hf_cops_pc_delete_subcode = -1;
+static gint hf_cops_pc_dest_ip = -1;
+static gint hf_cops_pc_dest_port = -1;
+static gint hf_cops_pc_direction = -1;
+static gint hf_cops_pc_ds_field = -1;
+static gint hf_cops_pc_gate_id = -1;
+static gint hf_cops_pc_gate_spec_flags = -1;
+static gint hf_cops_pc_gate_command_type = -1;
+static gint hf_cops_pc_key = -1;
+static gint hf_cops_pc_max_packet_size = -1;
+static gint hf_cops_pc_min_policed_unit = -1;
+static gint hf_cops_pc_packetcable_err_code = -1;
+static gint hf_cops_pc_packetcable_sub_code = -1;
+static gint hf_cops_pc_peak_data_rate = -1;
+static gint hf_cops_pc_protocol_id = -1;
+static gint hf_cops_pc_reason_code = -1;
+static gint hf_cops_pc_remote_flags = -1;
+static gint hf_cops_pc_remote_gate_id = -1;
+static gint hf_cops_pc_reserved = -1;
+static gint hf_cops_pc_session_class = -1;
+static gint hf_cops_pc_slack_term = -1;
+static gint hf_cops_pc_spec_rate = -1;
+static gint hf_cops_pc_src_ip = -1;
+static gint hf_cops_pc_src_port = -1;
+static gint hf_cops_pc_subscriber_id = -1;
+static gint hf_cops_pc_t1_value = -1;
+static gint hf_cops_pc_t7_value = -1;
+static gint hf_cops_pc_t8_value = -1;
+static gint hf_cops_pc_token_bucket_rate = -1;
+static gint hf_cops_pc_token_bucket_size = -1;
+static gint hf_cops_pc_transaction_id = -1;
+static gint hf_cops_pc_bcid_ts = -1;
+static gint hf_cops_pc_bcid = -1;
+static gint hf_cops_pc_bcid_ev = -1;
+static gint hf_cops_pc_dfcdc_ip = -1;
+static gint hf_cops_pc_dfccc_ip = -1;
+static gint hf_cops_pc_dfcdc_ip_port = -1;
+static gint hf_cops_pc_dfccc_ip_port = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_cops = -1;
+static gint ett_cops_ver_flags = -1;
+static gint ett_cops_obj = -1;
+static gint ett_cops_pr_obj = -1;
+static gint ett_cops_obj_data = -1;
+static gint ett_cops_r_type_flags = -1;
+static gint ett_cops_itf = -1;
+static gint ett_cops_reason = -1;
+static gint ett_cops_decision = -1;
+static gint ett_cops_error = -1;
+static gint ett_cops_clientsi = -1;
+static gint ett_cops_asn1 = -1;
+static gint ett_cops_gperror = -1;
+static gint ett_cops_cperror = -1;
+static gint ett_cops_pdp = -1;
+
+/* For PacketCable */
+static gint ett_cops_subtree = -1;
+
+void proto_reg_handoff_cops(void);
+
+static guint get_cops_pdu_len(tvbuff_t *tvb, int offset);
+static void dissect_cops_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static int dissect_cops_object(tvbuff_t *tvb, guint32 offset, proto_tree *tree);
+static void dissect_cops_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
+ guint8 c_num, guint8 c_type, guint16 len);
+
+static void dissect_cops_pr_objects(tvbuff_t *tvb, guint32 offset, proto_tree *tree, guint16 pr_len);
+static int dissect_cops_pr_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
+ guint8 s_num, guint8 s_type, guint16 len);
+
+/* Added for PacketCable */
+proto_tree *info_to_cops_subtree(tvbuff_t *, proto_tree *, int, int, char *);
+void info_to_display(tvbuff_t *, proto_item *, int, int, char *, const value_string *, int, gint *);
+void cops_transaction_id(tvbuff_t *, proto_tree *, guint, guint32);
+void cops_subscriber_id_v4(tvbuff_t *, proto_tree *, guint, guint32);
+void cops_gate_id(tvbuff_t *, proto_tree *, guint, guint32);
+void cops_activity_count(tvbuff_t *, proto_tree *, guint, guint32);
+void cops_gate_specs(tvbuff_t *, proto_tree *, guint, guint32);
+void cops_remote_gate_info(tvbuff_t *, proto_tree *, guint, guint32);
+void cops_packetcable_reason(tvbuff_t *, proto_tree *, guint, guint32);
+void cops_packetcable_error(tvbuff_t *, proto_tree *, guint, guint32);
+void cops_analyze_packetcable_obj(tvbuff_t *, proto_tree *, guint32);
+void cops_event_generation_info(tvbuff_t *, proto_tree *, guint, guint32);
+void cops_surveillance_parameters(tvbuff_t *, proto_tree *, guint, guint32);
+
+static packet_info *cpinfo;
+static guint8 opcode_idx;
+static gboolean cops_packetcable = TRUE;
+/* End of addition for PacketCable */
+
+
+/* Code to actually dissect the packets */
+static void
+dissect_cops(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, cops_desegment, 8,
+ get_cops_pdu_len, dissect_cops_pdu);
+}
+
+static guint
+get_cops_pdu_len(tvbuff_t *tvb, int offset)
+{
+ /*
+ * Get the length of the COPS message.
+ */
+ return tvb_get_ntohl(tvb, offset + 4);
+}
+
+static void
+dissect_cops_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 op_code;
+ int object_len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "COPS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ op_code = tvb_get_guint8(tvb, 1);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "COPS %s",
+ val_to_str(op_code, cops_op_code_vals, "Unknown Op Code"));
+
+ /* PacketCable: Remember the next two values to manipulate the info field in the Gui */
+ cpinfo = pinfo;
+ opcode_idx = op_code;
+
+ if (tree) {
+ proto_item *ti, *tv;
+ proto_tree *cops_tree, *ver_flags_tree;
+ guint32 msg_len;
+ guint32 offset = 0;
+ guint8 ver_flags;
+ gint garbage;
+
+ ti = proto_tree_add_item(tree, proto_cops, tvb, offset, -1, FALSE);
+ cops_tree = proto_item_add_subtree(ti, ett_cops);
+
+ /* Version and flags share the same byte, put them in a subtree */
+ ver_flags = tvb_get_guint8(tvb, offset);
+ tv = proto_tree_add_uint_format(cops_tree, hf_cops_ver_flags, tvb, offset, 1,
+ ver_flags, "Version: %u, Flags: %s",
+ hi_nibble(ver_flags),
+ val_to_str(lo_nibble(ver_flags), cops_flags_vals, "Unknown"));
+ ver_flags_tree = proto_item_add_subtree(tv, ett_cops_ver_flags);
+ proto_tree_add_uint(ver_flags_tree, hf_cops_version, tvb, offset, 1, ver_flags);
+ proto_tree_add_uint(ver_flags_tree, hf_cops_flags, tvb, offset, 1, ver_flags);
+ offset++;
+
+ proto_tree_add_item(cops_tree, hf_cops_op_code, tvb, offset, 1, FALSE);
+ offset ++;
+ proto_tree_add_item(cops_tree, hf_cops_client_type, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ msg_len = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(cops_tree, hf_cops_msg_len, tvb, offset, 4, msg_len);
+ offset += 4;
+
+ while (tvb_reported_length_remaining(tvb, offset) >= COPS_OBJECT_HDR_SIZE) {
+ object_len = dissect_cops_object(tvb, offset, cops_tree);
+ if (object_len < 0)
+ return;
+ offset += object_len;
+ }
+
+ garbage = tvb_length_remaining(tvb, offset);
+ if (garbage > 0)
+ proto_tree_add_text(cops_tree, tvb, offset, garbage,
+ "Trailing garbage: %d byte%s", garbage,
+ plurality(garbage, "", "s"));
+ }
+}
+
+static char *cops_c_type_to_str(guint8 c_num, guint8 c_type)
+{
+ switch (c_num) {
+ case COPS_OBJ_HANDLE:
+ if (c_type == 1)
+ return "Client Handle";
+ break;
+ case COPS_OBJ_IN_INT:
+ case COPS_OBJ_OUT_INT:
+ if (c_type == 1)
+ return "IPv4 Address + Interface";
+ else if (c_type == 2)
+ return "IPv6 Address + Interface";
+ break;
+ case COPS_OBJ_DECISION:
+ case COPS_OBJ_LPDPDECISION:
+ if (c_type == 1)
+ return "Decision Flags (Mandatory)";
+ else if (c_type == 2)
+ return "Stateless Data";
+ else if (c_type == 3)
+ return "Replacement Data";
+ else if (c_type == 4)
+ return "Client Specific Decision Data";
+ else if (c_type == 5)
+ return "Named Decision Data";
+ break;
+ case COPS_OBJ_CLIENTSI:
+ if (c_type == 1)
+ return "Signaled ClientSI";
+ else if (c_type == 2)
+ return "Named ClientSI";
+ break;
+ case COPS_OBJ_KATIMER:
+ if (c_type == 1)
+ return "Keep-alive timer value";
+ break;
+ case COPS_OBJ_PDPREDIRADDR:
+ case COPS_OBJ_LASTPDPADDR:
+ if (c_type == 1)
+ return "IPv4 Address + TCP Port";
+ else if (c_type == 2)
+ return "IPv6 Address + TCP Port";
+ break;
+ case COPS_OBJ_ACCTTIMER:
+ if (c_type == 1)
+ return "Accounting timer value";
+ break;
+ case COPS_OBJ_INTEGRITY:
+ if (c_type == 1)
+ return "HMAC digest";
+ break;
+ }
+
+ return "";
+}
+
+static int dissect_cops_object(tvbuff_t *tvb, guint32 offset, proto_tree *tree)
+{
+ guint16 object_len, contents_len;
+ guint8 c_num, c_type;
+ proto_item *ti;
+ proto_tree *obj_tree;
+ char *type_str;
+
+ object_len = tvb_get_ntohs(tvb, offset);
+ if (object_len < COPS_OBJECT_HDR_SIZE) {
+ /* Bogus! */
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Bad COPS object length: %u, should be at least %u",
+ object_len, COPS_OBJECT_HDR_SIZE);
+ return -1;
+ }
+ c_num = tvb_get_guint8(tvb, offset + 2);
+ c_type = tvb_get_guint8(tvb, offset + 3);
+
+ ti = proto_tree_add_uint_format(tree, hf_cops_obj_c_num, tvb, offset, object_len, c_num,
+ "%s: %s", val_to_str(c_num, cops_c_num_vals, "Unknown"),
+ cops_c_type_to_str(c_num, c_type));
+ obj_tree = proto_item_add_subtree(ti, ett_cops_obj);
+
+ proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
+ offset += 2;
+
+ proto_tree_add_uint(obj_tree, hf_cops_obj_c_num, tvb, offset, 1, c_num);
+ offset++;
+
+ type_str = cops_c_type_to_str(c_num, c_type);
+ proto_tree_add_text(obj_tree, tvb, offset, 1, "C-Type: %s%s%u%s",
+ type_str,
+ strlen(type_str) ? " (" : "",
+ c_type,
+ strlen(type_str) ? ")" : "");
+ offset++;
+
+ contents_len = object_len - COPS_OBJECT_HDR_SIZE;
+ dissect_cops_object_data(tvb, offset, obj_tree, c_num, c_type, contents_len);
+
+ /* Pad to 32bit boundary */
+ if (object_len % sizeof (guint32))
+ object_len += (sizeof (guint32) - object_len % sizeof (guint32));
+
+ return object_len;
+}
+
+static void dissect_cops_pr_objects(tvbuff_t *tvb, guint32 offset, proto_tree *tree, guint16 pr_len)
+{
+ guint16 object_len, contents_len;
+ guint8 s_num, s_type;
+ char *type_str;
+ int ret;
+ proto_tree *cops_pr_tree, *obj_tree;
+ proto_item *ti;
+
+ cops_pr_tree = proto_item_add_subtree(tree, ett_cops_pr_obj);
+
+ while (pr_len >= COPS_OBJECT_HDR_SIZE) {
+ object_len = tvb_get_ntohs(tvb, offset);
+ if (object_len < COPS_OBJECT_HDR_SIZE) {
+ /* Bogus! */
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Bad COPS PR object length: %u, should be at least %u",
+ object_len, COPS_OBJECT_HDR_SIZE);
+ return;
+ }
+ s_num = tvb_get_guint8(tvb, offset + 2);
+
+ ti = proto_tree_add_uint_format(cops_pr_tree, hf_cops_obj_s_num, tvb, offset, object_len, s_num,
+ "%s", val_to_str(s_num, cops_s_num_vals, "Unknown"));
+ obj_tree = proto_item_add_subtree(cops_pr_tree, ett_cops_pr_obj);
+
+ proto_tree_add_uint(obj_tree, hf_cops_obj_len, tvb, offset, 2, object_len);
+ offset += 2;
+ pr_len -= 2;
+
+ proto_tree_add_uint(obj_tree, hf_cops_obj_s_num, tvb, offset, 1, s_num);
+ offset++;
+ pr_len--;
+
+ s_type = tvb_get_guint8(tvb, offset);
+ type_str = val_to_str(s_type, cops_s_type_vals, "Unknown");
+ proto_tree_add_text(obj_tree, tvb, offset, 1, "S-Type: %s%s%u%s",
+ type_str,
+ strlen(type_str) ? " (" : "",
+ s_type,
+ strlen(type_str) ? ")" : "");
+ offset++;
+ pr_len--;
+
+ contents_len = object_len - COPS_OBJECT_HDR_SIZE;
+ ret = dissect_cops_pr_object_data(tvb, offset, obj_tree, s_num, s_type, contents_len);
+ if (ret < 0)
+ break;
+
+ /*Pad to 32bit boundary */
+ if (object_len % sizeof (guint32))
+ object_len += (sizeof (guint32) - object_len % sizeof (guint32));
+
+ pr_len -= object_len - COPS_OBJECT_HDR_SIZE;
+ offset += object_len - COPS_OBJECT_HDR_SIZE;
+ }
+}
+
+static void dissect_cops_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
+ guint8 c_num, guint8 c_type, guint16 len)
+{
+ proto_item *ti;
+ proto_tree *r_type_tree, *itf_tree, *reason_tree, *dec_tree, *error_tree, *clientsi_tree, *pdp_tree;
+ guint16 r_type, m_type, reason, reason_sub, cmd_code, cmd_flags, error, error_sub, tcp_port;
+ guint32 ipv4addr, ifindex;
+ struct e_in6_addr ipv6addr;
+
+ switch (c_num) {
+ case COPS_OBJ_CONTEXT:
+ r_type = tvb_get_ntohs(tvb, offset);
+ m_type = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: R-Type: %s, M-Type: %u",
+ val_to_str(r_type, cops_r_type_vals, "Unknown"),
+ m_type);
+
+ r_type_tree = proto_item_add_subtree(ti, ett_cops_r_type_flags);
+ proto_tree_add_uint(r_type_tree, hf_cops_r_type_flags, tvb, offset, 2, r_type);
+ offset += 2;
+ proto_tree_add_uint(r_type_tree, hf_cops_m_type_flags, tvb, offset, 2, m_type);
+
+ break;
+ case COPS_OBJ_IN_INT:
+ case COPS_OBJ_OUT_INT:
+ if (c_type == 1) { /* IPv4 */
+ tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
+ ifindex = tvb_get_ntohl(tvb, offset + 4);
+ ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, ifIndex: %u",
+ ip_to_str((guint8 *)&ipv4addr), ifindex);
+ itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
+ proto_tree_add_ipv4(itf_tree,
+ (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv4 : hf_cops_out_int_ipv4,
+ tvb, offset, 4, ipv4addr);
+ offset += 4;
+ } else if (c_type == 2) { /* IPv6 */
+ tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
+ ifindex = tvb_get_ntohl(tvb, offset + sizeof ipv6addr);
+ ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, ifIndex: %u",
+ ip6_to_str(&ipv6addr), ifindex);
+ itf_tree = proto_item_add_subtree(ti, ett_cops_itf);
+ proto_tree_add_ipv6(itf_tree,
+ (c_num == COPS_OBJ_IN_INT) ? hf_cops_in_int_ipv6 : hf_cops_out_int_ipv6,
+ tvb, offset, 16, (guint8 *)&ipv6addr);
+ offset += 16;
+ } else {
+ break;
+ }
+ proto_tree_add_uint(itf_tree, hf_cops_int_ifindex, tvb, offset, 4, ifindex);
+
+ break;
+ case COPS_OBJ_REASON:
+ reason = tvb_get_ntohs(tvb, offset);
+ reason_sub = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Reason-Code: %s, Reason Sub-code: 0x%04x",
+ val_to_str(reason, cops_reason_vals, "<Unknown value>"), reason_sub);
+ reason_tree = proto_item_add_subtree(ti, ett_cops_reason);
+ proto_tree_add_uint(reason_tree, hf_cops_reason, tvb, offset, 2, reason);
+ offset += 2;
+ if (reason == 13) {
+ proto_tree_add_text(reason_tree, tvb, offset, 2, "Reason Sub-code: "
+ "Unknown object's C-Num %u, C-Type %u",
+ tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
+ } else
+ proto_tree_add_uint(reason_tree, hf_cops_reason_sub, tvb, offset, 2, reason_sub);
+
+ break;
+ case COPS_OBJ_DECISION:
+ case COPS_OBJ_LPDPDECISION:
+ if (c_type == 1) {
+ cmd_code = tvb_get_ntohs(tvb, offset);
+ cmd_flags = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Command-Code: %s, Flags: %s",
+ val_to_str(cmd_code, cops_dec_cmd_code_vals, "<Unknown value>"),
+ val_to_str(cmd_flags, cops_dec_cmd_flag_vals, "<Unknown flag>"));
+ dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
+ proto_tree_add_uint(dec_tree, hf_cops_dec_cmd_code, tvb, offset, 2, cmd_code);
+ offset += 2;
+ proto_tree_add_uint(dec_tree, hf_cops_dec_flags, tvb, offset, 2, cmd_flags);
+ } else if (c_type == 5) { /*COPS-PR Data*/
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
+ dec_tree = proto_item_add_subtree(ti, ett_cops_decision);
+ dissect_cops_pr_objects(tvb, offset, dec_tree, len);
+ }
+
+ /* PacketCable : Analyze the remaining data if available */
+ cops_analyze_packetcable_obj(tvb, tree, offset);
+
+ break;
+ case COPS_OBJ_ERROR:
+ if (c_type != 1)
+ break;
+
+ error = tvb_get_ntohs(tvb, offset);
+ error_sub = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
+ val_to_str(error, cops_error_vals, "<Unknown value>"), error_sub);
+ error_tree = proto_item_add_subtree(ti, ett_cops_error);
+ proto_tree_add_uint(error_tree, hf_cops_error, tvb, offset, 2, error);
+ offset += 2;
+ if (error == 13) {
+ proto_tree_add_text(error_tree, tvb, offset, 2, "Error Sub-code: "
+ "Unknown object's C-Num %u, C-Type %u",
+ tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
+ } else
+ proto_tree_add_uint(error_tree, hf_cops_error_sub, tvb, offset, 2, error_sub);
+
+ break;
+ case COPS_OBJ_CLIENTSI:
+
+ /* For PacketCable */
+ if (c_type == 1) {
+ cops_analyze_packetcable_obj(tvb, tree, offset);
+ break;
+ }
+
+ if (c_type != 2) /*Not COPS-PR data*/
+ break;
+
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: %u bytes", len);
+ clientsi_tree = proto_item_add_subtree(ti, ett_cops_clientsi);
+
+ dissect_cops_pr_objects(tvb, offset, clientsi_tree, len);
+
+ break;
+ case COPS_OBJ_KATIMER:
+ if (c_type != 1)
+ break;
+
+ proto_tree_add_item(tree, hf_cops_katimer, tvb, offset + 2, 2, FALSE);
+ if (tvb_get_ntohs(tvb, offset + 2) == 0)
+ proto_tree_add_text(tree, tvb, offset, 0, "Value of zero implies infinity.");
+
+ break;
+ case COPS_OBJ_PEPID:
+ if (c_type != 1)
+ break;
+
+ if (tvb_strnlen(tvb, offset, len) == -1)
+ proto_tree_add_text(tree, tvb, offset, len, "<PEP Id is not a NUL terminated ASCII string>");
+ else
+ proto_tree_add_item(tree, hf_cops_pepid, tvb, offset,
+ tvb_strnlen(tvb, offset, len) + 1, FALSE);
+
+ break;
+ case COPS_OBJ_REPORT_TYPE:
+ if (c_type != 1)
+ break;
+
+ proto_tree_add_item(tree, hf_cops_report_type, tvb, offset, 2, FALSE);
+
+ break;
+ case COPS_OBJ_PDPREDIRADDR:
+ case COPS_OBJ_LASTPDPADDR:
+ if (c_type == 1) { /* IPv4 */
+ tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset, 4);
+ tcp_port = tvb_get_ntohs(tvb, offset + 4 + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 8, "Contents: IPv4 address %s, TCP Port Number: %u",
+ ip_to_str((guint8 *)&ipv4addr), tcp_port);
+ pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
+ proto_tree_add_ipv4(pdp_tree,
+ (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv4 : hf_cops_lastpdpaddr_ipv4,
+ tvb, offset, 4, ipv4addr);
+ offset += 4;
+ } else if (c_type == 2) { /* IPv6 */
+ tvb_memcpy(tvb, (guint8 *)&ipv6addr, offset, sizeof ipv6addr);
+ tcp_port = tvb_get_ntohs(tvb, offset + sizeof ipv6addr + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 20, "Contents: IPv6 address %s, TCP Port Number: %u",
+ ip6_to_str(&ipv6addr), tcp_port);
+ pdp_tree = proto_item_add_subtree(ti, ett_cops_pdp);
+ proto_tree_add_ipv6(pdp_tree,
+ (c_num == COPS_OBJ_PDPREDIRADDR) ? hf_cops_pdprediraddr_ipv6 : hf_cops_lastpdpaddr_ipv6,
+ tvb, offset, 16, (guint8 *)&ipv6addr);
+ offset += 16;
+ } else {
+ break;
+ }
+ offset += 2;
+ proto_tree_add_uint(pdp_tree, hf_cops_pdp_tcp_port, tvb, offset, 2, tcp_port);
+
+ break;
+ case COPS_OBJ_ACCTTIMER:
+ if (c_type != 1)
+ break;
+
+ proto_tree_add_item(tree, hf_cops_accttimer, tvb, offset + 2, 2, FALSE);
+ if (tvb_get_ntohs(tvb, offset + 2) == 0)
+ proto_tree_add_text(tree, tvb, offset, 0, "Value of zero means "
+ "there SHOULD be no unsolicited accounting updates.");
+
+ break;
+ case COPS_OBJ_INTEGRITY:
+ if (c_type != 1)
+ break; /* Not HMAC digest */
+
+ proto_tree_add_item(tree, hf_cops_key_id, tvb, offset, 4, FALSE);
+ proto_tree_add_item(tree, hf_cops_seq_num, tvb, offset + 4, 4, FALSE);
+ proto_tree_add_text(tree, tvb, offset + 8 , len - 8, "Contents: Keyed Message Digest");
+
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
+
+ break;
+ }
+}
+
+#ifdef HAVE_NET_SNMP
+static guchar*format_asn_value (struct variable_list *variable, subid_t *variable_oid,
+ guint variable_oid_length, u_char type_from_packet)
+{
+ struct tree *subtree=tree_head;
+
+ guchar *buf=NULL;
+ size_t buf_len=0;
+ size_t out_len=0;
+
+ /*Get the ASN.1 type etc. from the PIB-MIB. If unsuccessful use the type from packet*/
+ subtree = get_tree(variable_oid,variable_oid_length, subtree);
+
+ if (subtree->type == 0)
+ variable->type= type_from_packet;
+
+ buf_len = SPRINT_MAX_LEN; /*defined in NET-SNMP's snmp-impl.h*/
+ buf = g_malloc(buf_len);
+ *buf = '\0';
+ out_len = 0;
+
+ /*If the ASN.1 type was found from PIB-MIB, use it for decoding*/
+ if (!variable->type)
+ variable->type=mib_to_asn_type(subtree->type);
+
+ if (!sprint_realloc_by_type(&buf, &buf_len, &out_len, TRUE, variable, subtree->enums, subtree->hint, NULL))
+ sprintf(buf,"%s","sprint_realloc_by_type failed");
+
+ return buf;
+}
+#endif /* HAVE_NET_SNMP */
+
+static int decode_cops_pr_asn1_data(tvbuff_t *tvb, guint32 offset,
+ proto_tree *tree, guint asnlen, guint8 cops_pr_obj
+#ifndef HAVE_NET_SNMP
+ _U_
+#endif
+ )
+{
+ ASN1_SCK asn1;
+ int start;
+ gboolean def;
+ guint length;
+
+ guint vb_length;
+ gushort vb_type;
+ gchar *vb_type_name;
+
+ int ret;
+ guint cls, con, tag;
+ subid_t epd_attribute_index=0;
+
+ gint32 vb_integer_value;
+ guint32 vb_uinteger_value;
+
+ guint8 *vb_octet_string;
+
+ subid_t *vb_oid;
+ guint vb_oid_length;
+
+ gchar *vb_display_string;
+ gchar *vb_display_string2;
+
+#ifdef HAVE_NET_SNMP
+ struct variable_list variable;
+ long value;
+#endif /* HAVE_NET_SNMP */
+
+ unsigned int i;
+ gchar *buf;
+ int len;
+
+ while (asnlen > 0) { /*while there is ASN stuff to be decoded*/
+
+ epd_attribute_index++;
+#ifdef HAVE_NET_SNMP
+ last_decoded_prid_oid[last_decoded_prid_oid_length-1]=epd_attribute_index;
+#endif /* HAVE_NET_SNMP */
+ asn1_open(&asn1, tvb, offset);
+
+ /* parse the type of the object */
+
+ start = asn1.offset;
+
+ ret = asn1_header_decode (&asn1, &cls, &con, &tag, &def, &vb_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return 0;
+ if (!def)
+ return ASN1_ERR_LENGTH_NOT_DEFINITE;
+
+ /* Convert the class, constructed flag, and tag to a type. */
+ vb_type_name = cops_tag_cls2syntax(tag, cls, &vb_type);
+ if (vb_type_name == NULL) {
+ /*
+ * Unsupported type.
+ * Dissect the value as an opaque string of octets.
+ */
+ vb_type_name = "unsupported type";
+ vb_type = COPS_OPAQUE;
+ }
+
+ /* parse the value */
+
+ switch (vb_type) {
+
+ case COPS_INTEGER:
+ ret = asn1_int32_value_decode(&asn1, vb_length, &vb_integer_value);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+ if (tree) {
+#ifdef HAVE_NET_SNMP
+ if (cops_typefrommib == TRUE)
+ {
+ variable.type = 0;
+ value = vb_integer_value;
+ variable.val.integer = &value;
+ variable.val_len = vb_length ;
+ vb_display_string=format_asn_value(&variable,
+ last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_INTEGER);
+
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s", vb_display_string);
+ g_free(vb_display_string);
+ }
+ else
+#endif /* HAVE_NET_SNMP */
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %d (%#x)", vb_type_name,
+ vb_integer_value, vb_integer_value);
+ }
+ break;
+
+ case COPS_UNSIGNED32:
+ case COPS_TIMETICKS:
+ ret = asn1_uint32_value_decode(&asn1, vb_length, &vb_uinteger_value);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+ if (tree) {
+#ifdef HAVE_NET_SNMP
+ if (cops_typefrommib == TRUE)
+ {
+ variable.type = 0;
+ value = vb_uinteger_value;
+ variable.val.integer = &value;
+ variable.val_len = vb_length;
+
+ vb_display_string=format_asn_value(&variable,
+ last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_UINTEGER);
+
+ proto_tree_add_text(tree, asn1.tvb, offset, length, "Value %s: %s",vb_type_name, vb_display_string);
+
+ g_free(vb_display_string);
+ }
+ else
+#endif /* HAVE_NET_SNMP */
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %u (%#x)", vb_type_name,
+ vb_uinteger_value, vb_uinteger_value);
+ }
+ break;
+
+ case COPS_OCTETSTR:
+ case COPS_IPADDR:
+ case COPS_OPAQUE:
+ case COPS_UNSIGNED64:
+ case COPS_INTEGER64:
+ ret = asn1_string_value_decode (&asn1, vb_length, &vb_octet_string);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+ if (tree) {
+#ifdef HAVE_NET_SNMP
+ if (cops_typefrommib == TRUE)
+ {
+ variable.type = 0;
+ variable.val.string = vb_octet_string;
+ variable.val_len = vb_length;
+ vb_display_string = format_asn_value(&variable,
+ last_decoded_prid_oid,last_decoded_prid_oid_length,ASN_OCTET_STR);
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s (ASN.1 type from packet: %s)", vb_display_string, vb_type_name);
+
+ g_free(vb_display_string);
+ }
+ else
+ {
+#endif /* HAVE_NET_SNMP */
+ for (i = 0; i < vb_length; i++) {
+ if (!(isprint(vb_octet_string[i]) ||isspace(vb_octet_string[i])))
+ break;
+ }
+
+ /*
+ * If some characters are not printable, display the string as bytes.
+ */
+ if (i < vb_length) {
+ /*
+ * We stopped, due to a non-printable character, before we got
+ * to the end of the string.
+ */
+ vb_display_string = g_malloc(4*vb_length);
+ buf = &vb_display_string[0];
+ len = sprintf(buf, "%03u", vb_octet_string[0]);
+ buf += len;
+ for (i = 1; i < vb_length; i++) {
+ len = sprintf(buf, ".%03u", vb_octet_string[i]);
+ buf += len;
+ }
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %s", vb_type_name, vb_display_string);
+ g_free(vb_display_string);
+ } else {
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %.*s", vb_type_name, (int)vb_length,
+ SAFE_STRING(vb_octet_string));
+ }
+#ifdef HAVE_NET_SNMP
+ }
+#endif /* HAVE_NET_SNMP */
+ }
+ g_free(vb_octet_string);
+ break;
+
+ case COPS_NULL:
+ ret = asn1_null_decode (&asn1, vb_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+ if (tree)
+ proto_tree_add_text(tree, asn1.tvb, offset, length, "Value: %s", vb_type_name);
+ break;
+
+ case COPS_OBJECTID:
+ ret = asn1_oid_value_decode (&asn1, vb_length, &vb_oid, &vb_oid_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1.offset - start;
+
+ if (tree) {
+ if (cops_pr_obj == COPS_OBJ_PPRID){
+ /*we're decoding Prefix PRID, that doesn't have a instance Id,
+ *Use full length of the OID when decoding it.
+ */
+ new_format_oid(vb_oid,vb_oid_length,&vb_display_string,&vb_display_string2);
+
+ if (!vb_display_string2) /*if OID couldn't be decoded, print only numeric format*/
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %s", vb_type_name, vb_display_string);
+ else
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %s (%s)", vb_type_name,
+ vb_display_string,
+ vb_display_string2);
+ }
+ else { /*we're decoding PRID, Error PRID or EPD*/
+ /*strip the instance Id from the OIDs before decoding and paste it back during printing*/
+ new_format_oid(vb_oid,vb_oid_length-1,&vb_display_string,&vb_display_string2);
+
+ if (!vb_display_string2) /*if OID couldn't be decoded, print only numeric format*/
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %s.%lu", vb_type_name,
+ vb_display_string,
+ (unsigned long)vb_oid[vb_oid_length-1]);
+ else
+ proto_tree_add_text(tree, asn1.tvb, offset, length,
+ "Value: %s: %s.%lu (%s.%lu)", vb_type_name,
+ vb_display_string,
+ (unsigned long)vb_oid[vb_oid_length-1],
+ vb_display_string2,
+ (unsigned long)vb_oid[vb_oid_length-1]);
+ }
+#ifdef HAVE_NET_SNMP
+ if (cops_pr_obj != COPS_OBJ_EPD) {
+ /* we're not decoding EPD, so let's store the OID of the PRID so that later
+ when we're decoding this PRID's EPD we can finetune the output.*/
+ memcpy(last_decoded_prid_oid,vb_oid,vb_oid_length*sizeof(subid_t));
+ last_decoded_prid_oid_length=vb_oid_length;
+ }
+#endif /* HAVE_NET_SNMP */
+
+ g_free(vb_display_string);
+ if(vb_display_string2)
+ g_free(vb_display_string2);
+ }
+ g_free(vb_oid);
+ break;
+
+ default:
+ g_assert_not_reached();
+ return ASN1_ERR_WRONG_TYPE;
+ }
+
+ asn1_close(&asn1,&offset);
+
+ asnlen -= length;
+ }
+ epd_attribute_index=0;
+ return 0;
+}
+
+static int dissect_cops_pr_object_data(tvbuff_t *tvb, guint32 offset, proto_tree *tree,
+ guint8 s_num, guint8 s_type, guint16 len)
+{
+ proto_item *ti;
+ proto_tree *asn1_object_tree, *gperror_tree, *cperror_tree;
+ guint16 gperror=0, gperror_sub=0, cperror=0, cperror_sub=0;
+
+ switch (s_num){
+ case COPS_OBJ_PRID:
+ if (s_type != 1) /* Not Provisioning Instance Identifier (PRID) */
+ break;
+
+ ti=proto_tree_add_text(tree, tvb, offset, len, "Contents:");
+ asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
+
+ decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_PRID);
+
+ break;
+ case COPS_OBJ_PPRID:
+ if (s_type != 1) /* Not Prefix Provisioning Instance Identifier (PPRID) */
+ break;
+
+ ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
+ asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
+
+ decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_PPRID);
+
+ break;
+ case COPS_OBJ_EPD:
+ if (s_type != 1) /* Not Encoded Provisioning Instance Data (EPD) */
+ break;
+
+ ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
+ asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
+
+ decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_EPD);
+
+ break;
+ case COPS_OBJ_GPERR:
+ if (s_type != 1) /* Not Global Provisioning Error Object (GPERR) */
+ break;
+
+ gperror = tvb_get_ntohs(tvb, offset);
+ gperror_sub = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
+ val_to_str(gperror, cops_gperror_vals, "<Unknown value>"), gperror_sub);
+ gperror_tree = proto_item_add_subtree(ti, ett_cops_gperror);
+ proto_tree_add_uint(gperror_tree, hf_cops_gperror, tvb, offset, 2, gperror);
+ offset += 2;
+ if (cperror == 13) {
+ proto_tree_add_text(gperror_tree, tvb, offset, 2, "Error Sub-code: "
+ "Unknown object's C-Num %u, C-Type %u",
+ tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
+ } else
+ proto_tree_add_uint(gperror_tree, hf_cops_gperror_sub, tvb, offset, 2, gperror_sub);
+
+ break;
+ case COPS_OBJ_CPERR:
+ if (s_type != 1) /*Not PRC Class Provisioning Error Object (CPERR) */
+ break;
+
+ break;
+
+ cperror = tvb_get_ntohs(tvb, offset);
+ cperror_sub = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Contents: Error-Code: %s, Error Sub-code: 0x%04x",
+ val_to_str(cperror, cops_cperror_vals, "<Unknown value>"), cperror_sub);
+ cperror_tree = proto_item_add_subtree(ti, ett_cops_cperror);
+ proto_tree_add_uint(cperror_tree, hf_cops_cperror, tvb, offset, 2, cperror);
+ offset += 2;
+ if (cperror == 13) {
+ proto_tree_add_text(cperror_tree, tvb, offset, 2, "Error Sub-code: "
+ "Unknown object's S-Num %u, C-Type %u",
+ tvb_get_guint8(tvb, offset), tvb_get_guint8(tvb, offset + 1));
+ } else
+ proto_tree_add_uint(cperror_tree, hf_cops_cperror_sub, tvb, offset, 2, cperror_sub);
+
+ break;
+ case COPS_OBJ_ERRPRID:
+ if (s_type != 1) /*Not Error Provisioning Instance Identifier (ErrorPRID)*/
+ break;
+
+ ti = proto_tree_add_text(tree, tvb, offset, len, "Contents:");
+ asn1_object_tree = proto_item_add_subtree(ti, ett_cops_asn1);
+
+ decode_cops_pr_asn1_data(tvb, offset, asn1_object_tree, len, COPS_OBJ_ERRPRID);
+
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, len, "Contents: %u bytes", len);
+ break;
+ }
+
+ return 0;
+}
+
+
+/* Register the protocol with Ethereal */
+void proto_register_cops(void)
+{
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_cops_ver_flags,
+ { "Version and Flags", "cops.ver_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Version and Flags in COPS Common Header", HFILL }
+ },
+ { &hf_cops_version,
+ { "Version", "cops.version",
+ FT_UINT8, BASE_DEC, NULL, 0xF0,
+ "Version in COPS Common Header", HFILL }
+ },
+ { &hf_cops_flags,
+ { "Flags", "cops.flags",
+ FT_UINT8, BASE_HEX, VALS(cops_flags_vals), 0x0F,
+ "Flags in COPS Common Header", HFILL }
+ },
+ { &hf_cops_op_code,
+ { "Op Code", "cops.op_code",
+ FT_UINT8, BASE_DEC, VALS(cops_op_code_vals), 0x0,
+ "Op Code in COPS Common Header", HFILL }
+ },
+ { &hf_cops_client_type,
+ { "Client Type", "cops.client_type",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Client Type in COPS Common Header", HFILL }
+ },
+ { &hf_cops_msg_len,
+ { "Message Length", "cops.msg_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Message Length in COPS Common Header", HFILL }
+ },
+ { &hf_cops_obj_len,
+ { "Object Length", "cops.obj.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Object Length in COPS Object Header", HFILL }
+ },
+ { &hf_cops_obj_c_num,
+ { "C-Num", "cops.c_num",
+ FT_UINT8, BASE_DEC, VALS(cops_c_num_vals), 0x0,
+ "C-Num in COPS Object Header", HFILL }
+ },
+ { &hf_cops_obj_c_type,
+ { "C-Type", "cops.c_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "C-Type in COPS Object Header", HFILL }
+ },
+
+ { &hf_cops_obj_s_num,
+ { "S-Num", "cops.s_num",
+ FT_UINT8, BASE_DEC, VALS(cops_s_num_vals), 0x0,
+ "S-Num in COPS-PR Object Header", HFILL }
+ },
+ { &hf_cops_obj_s_type,
+ { "S-Type", "cops.s_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "S-Type in COPS-PR Object Header", HFILL }
+ },
+
+ { &hf_cops_r_type_flags,
+ { "R-Type", "cops.context.r_type",
+ FT_UINT16, BASE_HEX, VALS(cops_r_type_vals), 0xFFFF,
+ "R-Type in COPS Context Object", HFILL }
+ },
+ { &hf_cops_m_type_flags,
+ { "M-Type", "cops.context.m_type",
+ FT_UINT16, BASE_HEX, NULL, 0xFFFF,
+ "M-Type in COPS Context Object", HFILL }
+ },
+ { &hf_cops_in_int_ipv4,
+ { "IPv4 address", "cops.in-int.ipv4",
+ FT_IPv4, 0, NULL, 0xFFFF,
+ "IPv4 address in COPS IN-Int object", HFILL }
+ },
+ { &hf_cops_in_int_ipv6,
+ { "IPv6 address", "cops.in-int.ipv6",
+ FT_IPv6, 0, NULL, 0xFFFF,
+ "IPv6 address in COPS IN-Int object", HFILL }
+ },
+ { &hf_cops_out_int_ipv4,
+ { "IPv4 address", "cops.out-int.ipv4",
+ FT_IPv4, 0, NULL, 0xFFFF,
+ "IPv4 address in COPS OUT-Int object", HFILL }
+ },
+ { &hf_cops_out_int_ipv6,
+ { "IPv6 address", "cops.out-int.ipv6",
+ FT_IPv6, 0, NULL, 0xFFFF,
+ "IPv6 address in COPS OUT-Int", HFILL }
+ },
+ { &hf_cops_int_ifindex,
+ { "ifIndex", "cops.in-out-int.ifindex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "If SNMP is supported, corresponds to MIB-II ifIndex", HFILL }
+ },
+ { &hf_cops_reason,
+ { "Reason", "cops.reason",
+ FT_UINT16, BASE_DEC, VALS(cops_reason_vals), 0,
+ "Reason in Reason object", HFILL }
+ },
+ { &hf_cops_reason_sub,
+ { "Reason Sub-code", "cops.reason_sub",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Reason Sub-code in Reason object", HFILL }
+ },
+ { &hf_cops_dec_cmd_code,
+ { "Command-Code", "cops.decision.cmd",
+ FT_UINT16, BASE_DEC, VALS(cops_dec_cmd_code_vals), 0,
+ "Command-Code in Decision/LPDP Decision object", HFILL }
+ },
+ { &hf_cops_dec_flags,
+ { "Flags", "cops.decision.flags",
+ FT_UINT16, BASE_HEX, VALS(cops_dec_cmd_flag_vals), 0xffff,
+ "Flags in Decision/LPDP Decision object", HFILL }
+ },
+ { &hf_cops_error,
+ { "Error", "cops.error",
+ FT_UINT16, BASE_DEC, VALS(cops_error_vals), 0,
+ "Error in Error object", HFILL }
+ },
+ { &hf_cops_error_sub,
+ { "Error Sub-code", "cops.error_sub",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Error Sub-code in Error object", HFILL }
+ },
+ { &hf_cops_katimer,
+ { "Contents: KA Timer Value", "cops.katimer.value",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Keep-Alive Timer Value in KATimer object", HFILL }
+ },
+ { &hf_cops_pepid,
+ { "Contents: PEP Id", "cops.pepid.id",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "PEP Id in PEPID object", HFILL }
+ },
+ { &hf_cops_report_type,
+ { "Contents: Report-Type", "cops.report_type",
+ FT_UINT16, BASE_DEC, VALS(cops_report_type_vals), 0,
+ "Report-Type in Report-Type object", HFILL }
+ },
+ { &hf_cops_pdprediraddr_ipv4,
+ { "IPv4 address", "cops.pdprediraddr.ipv4",
+ FT_IPv4, 0, NULL, 0xFFFF,
+ "IPv4 address in COPS PDPRedirAddr object", HFILL }
+ },
+ { &hf_cops_pdprediraddr_ipv6,
+ { "IPv6 address", "cops.pdprediraddr.ipv6",
+ FT_IPv6, 0, NULL, 0xFFFF,
+ "IPv6 address in COPS PDPRedirAddr object", HFILL }
+ },
+ { &hf_cops_lastpdpaddr_ipv4,
+ { "IPv4 address", "cops.lastpdpaddr.ipv4",
+ FT_IPv4, 0, NULL, 0xFFFF,
+ "IPv4 address in COPS LastPDPAddr object", HFILL }
+ },
+ { &hf_cops_lastpdpaddr_ipv6,
+ { "IPv6 address", "cops.lastpdpaddr.ipv6",
+ FT_IPv6, 0, NULL, 0xFFFF,
+ "IPv6 address in COPS LastPDPAddr object", HFILL }
+ },
+ { &hf_cops_pdp_tcp_port,
+ { "TCP Port Number", "cops.pdp.tcp_port",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "TCP Port Number of PDP in PDPRedirAddr/LastPDPAddr object", HFILL }
+ },
+ { &hf_cops_accttimer,
+ { "Contents: ACCT Timer Value", "cops.accttimer.value",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Accounting Timer Value in AcctTimer object", HFILL }
+ },
+ { &hf_cops_key_id,
+ { "Contents: Key ID", "cops.integrity.key_id",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Key ID in Integrity object", HFILL }
+ },
+ { &hf_cops_seq_num,
+ { "Contents: Sequence Number", "cops.integrity.seq_num",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Sequence Number in Integrity object", HFILL }
+ },
+ { &hf_cops_gperror,
+ { "Error", "cops.gperror",
+ FT_UINT16, BASE_DEC, VALS(cops_gperror_vals), 0,
+ "Error in Error object", HFILL }
+ },
+ { &hf_cops_gperror_sub,
+ { "Error Sub-code", "cops.gperror_sub",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Error Sub-code in Error object", HFILL }
+ },
+ { &hf_cops_cperror,
+ { "Error", "cops.cperror",
+ FT_UINT16, BASE_DEC, VALS(cops_cperror_vals), 0,
+ "Error in Error object", HFILL }
+ },
+ { &hf_cops_cperror_sub,
+ { "Error Sub-code", "cops.cperror_sub",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Error Sub-code in Error object", HFILL }
+ },
+
+ /* Added for PacketCable */
+
+ { &hf_cops_subtree,
+ { "Object Subtree", "cops.pc_subtree",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Object Subtree", HFILL }
+ },
+ { &hf_cops_pc_ds_field,
+ { "DS Field (DSCP or TOS)", "cops.pc_ds_field",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "DS Field (DSCP or TOS)", HFILL }
+ },
+ { &hf_cops_pc_direction,
+ { "Direction", "cops.pc_direction",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Direction", HFILL }
+ },
+ { &hf_cops_pc_gate_spec_flags,
+ { "Flags", "cops.pc_gate_spec_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Flags", HFILL }
+ },
+ { &hf_cops_pc_protocol_id,
+ { "Protocol ID", "cops.pc_protocol_id",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Protocol ID", HFILL }
+ },
+ { &hf_cops_pc_session_class,
+ { "Session Class", "cops.pc_session_class",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Session Class", HFILL }
+ },
+ { &hf_cops_pc_algorithm,
+ { "Algorithm", "cops.pc_algorithm",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Algorithm", HFILL }
+ },
+ { &hf_cops_pc_cmts_ip_port,
+ { "CMTS IP Port", "cops.pc_cmts_ip_port",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "CMTS IP Port", HFILL }
+ },
+ { &hf_cops_pc_prks_ip_port,
+ { "PRKS IP Port", "cops.pc_prks_ip_port",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "PRKS IP Port", HFILL }
+ },
+ { &hf_cops_pc_srks_ip_port,
+ { "SRKS IP Port", "cops.pc_srks_ip_port",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "SRKS IP Port", HFILL }
+ },
+ { &hf_cops_pc_dest_port,
+ { "Destination IP Port", "cops.pc_dest_port",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Destination IP Port", HFILL }
+ },
+ { &hf_cops_pc_packetcable_err_code,
+ { "Error Code", "cops.pc_packetcable_err_code",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Error Code", HFILL }
+ },
+ { &hf_cops_pc_packetcable_sub_code,
+ { "Error Sub Code", "cops.pc_packetcable_sub_code",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Error Sub Code", HFILL }
+ },
+ { &hf_cops_pc_remote_flags,
+ { "Flags", "cops.pc_remote_flags",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Flags", HFILL }
+ },
+ { &hf_cops_pc_close_subcode,
+ { "Reason Sub Code", "cops.pc_close_subcode",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Reason Sub Code", HFILL }
+ },
+ { &hf_cops_pc_gate_command_type,
+ { "Gate Command Type", "cops.pc_gate_command_type",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Gate Command Type", HFILL }
+ },
+ { &hf_cops_pc_reason_code,
+ { "Reason Code", "cops.pc_reason_code",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Reason Code", HFILL }
+ },
+ { &hf_cops_pc_delete_subcode,
+ { "Reason Sub Code", "cops.pc_delete_subcode",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Reason Sub Code", HFILL }
+ },
+ { &hf_cops_pc_src_port,
+ { "Source IP Port", "cops.pc_src_port",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Source IP Port", HFILL }
+ },
+ { &hf_cops_pc_t1_value,
+ { "Timer T1 Value (sec)", "cops.pc_t1_value",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Timer T1 Value (sec)", HFILL }
+ },
+ { &hf_cops_pc_t7_value,
+ { "Timer T7 Value (sec)", "cops.pc_t7_value",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Timer T7 Value (sec)", HFILL }
+ },
+ { &hf_cops_pc_t8_value,
+ { "Timer T8 Value (sec)", "cops.pc_t8_value",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Timer T8 Value (sec)", HFILL }
+ },
+ { &hf_cops_pc_transaction_id,
+ { "Transaction Identifier", "cops.pc_transaction_id",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Transaction Identifier", HFILL }
+ },
+ { &hf_cops_pc_cmts_ip,
+ { "CMTS IP Address", "cops.pc_cmts_ip",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "CMTS IP Address", HFILL }
+ },
+ { &hf_cops_pc_prks_ip,
+ { "PRKS IP Address", "cops.pc_prks_ip",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "PRKS IP Address", HFILL }
+ },
+ { &hf_cops_pc_srks_ip,
+ { "SRKS IP Address", "cops.pc_srks_ip",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "SRKS IP Address", HFILL }
+ },
+ { &hf_cops_pc_dfcdc_ip,
+ { "DF IP Address CDC", "cops.pc_dfcdc_ip",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "DF IP Address CDC", HFILL }
+ },
+ { &hf_cops_pc_dfccc_ip,
+ { "DF IP Address CCC", "cops.pc_dfccc_ip",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "DF IP Address CCC", HFILL }
+ },
+ { &hf_cops_pc_dfcdc_ip_port,
+ { "DF IP Port CDC", "cops.pc_dfcdc_ip_port",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "DF IP Port CDC", HFILL }
+ },
+ { &hf_cops_pc_dfccc_ip_port,
+ { "DF IP Port CCC", "cops.pc_dfccc_ip_port",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "DF IP Port CCC", HFILL }
+ },
+ { &hf_cops_pc_activity_count,
+ { "Count", "cops.pc_activity_count",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Count", HFILL }
+ },
+ { &hf_cops_pc_dest_ip,
+ { "Destination IP Address", "cops.pc_dest_ip",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Destination IP Address", HFILL }
+ },
+ { &hf_cops_pc_gate_id,
+ { "Gate Identifier", "cops.pc_gate_id",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Gate Identifier", HFILL }
+ },
+ { &hf_cops_pc_max_packet_size,
+ { "Maximum Packet Size", "cops.pc_max_packet_size",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Maximum Packet Size", HFILL }
+ },
+ { &hf_cops_pc_min_policed_unit,
+ { "Minimum Policed Unit", "cops.pc_min_policed_unit",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Minimum Policed Unit", HFILL }
+ },
+ { &hf_cops_pc_peak_data_rate,
+ { "Peak Data Rate", "cops.pc_peak_data_rate",
+ FT_FLOAT, BASE_NONE, NULL, 0x00,
+ "Peak Data Rate", HFILL }
+ },
+ { &hf_cops_pc_spec_rate,
+ { "Rate", "cops.pc_spec_rate",
+ FT_FLOAT, BASE_NONE, NULL, 0x00,
+ "Rate", HFILL }
+ },
+ { &hf_cops_pc_remote_gate_id,
+ { "Remote Gate ID", "cops.pc_remote_gate_id",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Remote Gate ID", HFILL }
+ },
+ { &hf_cops_pc_reserved,
+ { "Reserved", "cops.pc_reserved",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Reserved", HFILL }
+ },
+ { &hf_cops_pc_key,
+ { "Security Key", "cops.pc_key",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Security Key", HFILL }
+ },
+ { &hf_cops_pc_slack_term,
+ { "Slack Term", "cops.pc_slack_term",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Slack Term", HFILL }
+ },
+ { &hf_cops_pc_src_ip,
+ { "Source IP Address", "cops.pc_src_ip",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Source IP Address", HFILL }
+ },
+ { &hf_cops_pc_subscriber_id,
+ { "Subscriber Identifier (IPv4)", "cops.pc_subscriber_id",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Subscriber Identifier (IPv4)", HFILL }
+ },
+ { &hf_cops_pc_token_bucket_rate,
+ { "Token Bucket Rate", "cops.pc_token_bucket_rate",
+ FT_FLOAT, BASE_NONE, NULL, 0x00,
+ "Token Bucket Rate", HFILL }
+ },
+ { &hf_cops_pc_token_bucket_size,
+ { "Token Bucket Size", "cops.pc_token_bucket_size",
+ FT_FLOAT, BASE_NONE, NULL, 0x00,
+ "Token Bucket Size", HFILL }
+ },
+ { &hf_cops_pc_bcid,
+ { "Billing Correlation ID", "cops.pc_bcid",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "Billing Correlation ID", HFILL }
+ },
+ { &hf_cops_pc_bcid_ts,
+ { "BDID Timestamp", "cops.pc_bcid_ts",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "BCID Timestamp", HFILL }
+ },
+ { &hf_cops_pc_bcid_ev,
+ { "BDID Event Counter", "cops.pc_bcid_ev",
+ FT_UINT32, BASE_HEX, NULL, 0x00,
+ "BCID Event Counter", HFILL }
+ },
+
+
+ /* End of addition for PacketCable */
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_cops,
+ &ett_cops_ver_flags,
+ &ett_cops_obj,
+ &ett_cops_pr_obj,
+ &ett_cops_obj_data,
+ &ett_cops_r_type_flags,
+ &ett_cops_itf,
+ &ett_cops_reason,
+ &ett_cops_decision,
+ &ett_cops_error,
+ &ett_cops_clientsi,
+ &ett_cops_asn1,
+ &ett_cops_gperror,
+ &ett_cops_cperror,
+ &ett_cops_pdp,
+ &ett_cops_subtree,
+ };
+
+ module_t* cops_module;
+
+ /* Register the protocol name and description */
+ proto_cops = proto_register_protocol("Common Open Policy Service",
+ "COPS", "cops");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_cops, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register our configuration options for cops */
+ cops_module = prefs_register_protocol(proto_cops, proto_reg_handoff_cops);
+ prefs_register_uint_preference(cops_module,"tcp.cops_port",
+ "COPS TCP Port",
+ "Set the TCP port for COPS messages",
+ 10,&global_cops_tcp_port);
+ prefs_register_bool_preference(cops_module, "desegment",
+ "Desegment all COPS messages\nspanning multiple TCP segments",
+ "Whether the COPS dissector should desegment all messages spanning multiple TCP segments",
+ &cops_desegment);
+
+ /* For PacketCable */
+ prefs_register_bool_preference(cops_module, "packetcable",
+ "Decode for PacketCable clients",
+ "Decode the COPS messages using PacketCable clients. (Select port 2126)",
+ &cops_packetcable);
+
+#ifdef HAVE_NET_SNMP /*enable preference only if compiled with NET-SNMP*/
+ prefs_register_bool_preference(cops_module, "typefrommib",
+ "Decode COPS-PR ASN.1 types by reading them\nfrom PIBs (converted to MIBs)",
+ "Whether the COPS dissector should decode COPS-PR ASN.1 types based on data types read from packet or PIBs (converted to MIBs)",
+ &cops_typefrommib);
+#endif /*HAVE_NET_SNMP*/
+}
+
+void proto_reg_handoff_cops(void)
+{
+ static int cops_prefs_initialized = FALSE;
+ static dissector_handle_t cops_handle;
+
+ if (!cops_prefs_initialized) {
+ cops_handle = create_dissector_handle(dissect_cops, proto_cops);
+ cops_prefs_initialized = TRUE;
+ } else
+ dissector_delete("tcp.port",cops_tcp_port,cops_handle);
+
+ /* Set our port numbers for future use */
+ cops_tcp_port = global_cops_tcp_port;
+
+ dissector_add("tcp.port", cops_tcp_port, cops_handle);
+}
+
+
+/* Additions for PacketCable ( Added by Dick Gooris, Lucent Technologies ) */
+
+/* Definitions for print formatting */
+#define FMT_DEC 0
+#define FMT_HEX 1
+#define FMT_IP 2
+#define FMT_FLT 3
+
+/* Print the translated information in the display gui in a formatted way
+ *
+ * octets = The number of octets to obtain from the buffer
+ *
+ * vsp = If not a NULL pointer, it points to an array with text
+ *
+ * mode = 0 -> print decimal value
+ * 1 -> print hexadecimal vaue
+ * 2 -> print value as an ip address
+ * 3 -> print value as an ieee float
+ *
+ * This function in combination with the separate function info_to_cops_subtree() for subtrees.
+ *
+ */
+
+void info_to_display(tvbuff_t *tvb, proto_item *stt, int offset, int octets, char *str, const value_string *vsp, int mode,gint *hf_proto_parameter)
+{
+
+ guint8 code8 = 0;
+ guint16 code16 = 0;
+ guint32 code32 = 0;
+ guint32 codeip = 0;
+ float codefl = 0.0;
+
+ /* Print information elements in the specified way */
+ switch (octets) {
+
+ case 1:
+ /* Get the octet */
+ code8 = tvb_get_guint8( tvb, offset );
+ if (vsp == NULL) {
+ /* Hexadecimal format */
+ if (mode==FMT_HEX)
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
+ offset, octets, code8,"%-28s : 0x%02x",str,code8);
+ else
+ /* Print an 8 bits integer */
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
+ offset, octets, code8,"%-28s : %u",str,code8);
+ } else {
+ if (mode==FMT_HEX)
+ /* Hexadecimal format */
+ proto_tree_add_uint_format(
+ stt, *hf_proto_parameter,tvb, offset, octets, code8,
+ "%-28s : %s (0x%02x)",str,val_to_str(code8, vsp, "Unknown"),code8);
+ else
+ /* String table indexed */
+ proto_tree_add_uint_format(
+ stt, *hf_proto_parameter,tvb, offset, octets, code8,
+ "%-28s : %s (%u)",str,val_to_str(code8, vsp, "Unknown"),code8);
+ }
+ break;
+
+ case 2:
+
+ /* Get the next two octets */
+ code16 = tvb_get_ntohs(tvb,offset);
+ if (vsp == NULL) {
+ /* Hexadecimal format */
+ if (mode==FMT_HEX)
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
+ offset, octets, code16,"%-28s : 0x%04x",str,code16);
+ else
+ /* Print a 16 bits integer */
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
+ offset, octets, code16,"%-28s : %u",str,code16);
+ } else {
+ if (mode==FMT_HEX)
+ /* Hexadecimal format */
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
+ offset, octets, code16,"%-28s : %s (0x%04x)", str,
+ val_to_str(code16, vsp, "Unknown (0x%04x)"),code16);
+ else
+ /* Print a 16 bits integer */
+ proto_tree_add_uint_format(
+ stt, *hf_proto_parameter,tvb, offset, octets, code16,
+ "%-28s : %s (%u)",str,val_to_str(code16, vsp, "Unknown (0x%04x)"),code16);
+ }
+ break;
+
+ case 4:
+
+ /* Get the next four octets */
+ switch (mode) {
+ case FMT_FLT: codefl = tvb_get_ntohieee_float(tvb,offset);
+ break;
+ case FMT_IP: tvb_memcpy(tvb, (guint8 *)&code32, offset, 4);
+ codeip = tvb_get_ntohl(tvb,offset);
+ break;
+ default: code32 = tvb_get_ntohl(tvb,offset);
+ }
+
+ if (vsp == NULL) {
+ /* Hexadecimal format */
+ if (mode==FMT_HEX) {
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb,
+ offset, octets, code32,"%-28s : 0x%08x",str,code32);
+ break;
+ }
+ /* Ip address format*/
+ if (mode==FMT_IP) {
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset,octets,
+ codeip,"%-28s : %s",str,ip_to_str((guint8 *)&code32));
+ break;
+ }
+ /* Ieee float format */
+ if (mode==FMT_FLT) {
+ proto_tree_add_float_format(stt, *hf_proto_parameter,tvb, offset, octets,
+ codefl,"%-28s : %.10g",str,codefl);
+ break;
+ }
+ /* Print a 32 bits integer */
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset, octets,
+ code32,"%-28s : %u",str,code32);
+ } else {
+ /* Hexadecimal format */
+ if (mode==FMT_HEX)
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset, octets,
+ code32,"%-28s : %s (0x%08x)",str,val_to_str(code32, vsp, "Unknown"),code32);
+ else
+ /* String table indexed */
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,tvb, offset, octets,
+ code32,"%-28s : %s (%u)",str,val_to_str(code32, vsp, "Unknown"),code32);
+ }
+ break;
+
+ /* In case of more than 4 octets.... */
+ default: {
+ if (mode==FMT_HEX)
+ proto_tree_add_bytes(stt, *hf_proto_parameter,
+ tvb, offset, octets, tvb_get_ptr(tvb, offset,octets));
+ else
+ proto_tree_add_uint_format(stt, *hf_proto_parameter,
+ tvb, offset, octets, code32,"%s",str);
+ break;
+ }
+
+ }
+}
+
+/* Print the subtree information for cops */
+proto_tree *info_to_cops_subtree(tvbuff_t *tvb, proto_tree *st, int n, int offset, char *str) {
+ proto_item *tv;
+
+ tv = proto_tree_add_uint_format( st, hf_cops_subtree, tvb, offset, n, (guint)NULL, str);
+ return( proto_item_add_subtree( tv, ett_cops_subtree ) );
+}
+
+/* Cops - Section : Transaction ID */
+void cops_transaction_id(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_tree *stt;
+ guint16 code16;
+ char info[50];
+
+ /* Create a subtree */
+ stt = info_to_cops_subtree(tvb,st,n,offset,"Transaction ID");
+
+ /* Transaction Identifier */
+ info_to_display(tvb,stt,offset,2,"Transaction Identifier", NULL,FMT_DEC,&hf_cops_pc_transaction_id);
+ offset +=2;
+
+ /* Gate Command Type */
+ code16 = tvb_get_ntohs(tvb,offset);
+ proto_tree_add_uint_format(stt, hf_cops_pc_gate_command_type,tvb, offset, 2,
+ code16,"%-28s : %s (%u)", "Gate Command Type",
+ val_to_str(code16,table_cops_transaction_id, "Unknown (0x%04x)"),code16);
+
+ /* Write the right data into the 'info field' on the Gui */
+ sprintf(info,"COPS %-20s - ",val_to_str(opcode_idx,cops_op_code_vals, "Unknown"));
+ strcat(info,val_to_str(code16,table_cops_transaction_id, "Unknown"));
+
+ if (check_col(cpinfo->cinfo, COL_INFO)) {
+ col_clear(cpinfo->cinfo, COL_INFO);
+ col_add_str(cpinfo->cinfo, COL_INFO,info);
+ }
+
+}
+
+/* Cops - Section : Subscriber ID */
+void cops_subscriber_id_v4(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_item *tv;
+
+ /* Create a subtree */
+ tv = info_to_cops_subtree(tvb,st,n,offset,"Subscriber ID");
+
+ /* Subscriber Identifier */
+ info_to_display(tvb,tv,offset,4,"Subscriber Identifier (IPv4)", NULL,FMT_IP,&hf_cops_pc_subscriber_id);
+}
+
+/* Cops - Section : Gate ID */
+void cops_gate_id(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_tree *stt;
+
+ /* Create a subtree */
+ stt = info_to_cops_subtree(tvb,st,n,offset,"Gate ID");
+
+ /* Gate Identifier */
+ info_to_display(tvb,stt,offset,4,"Gate Identifier", NULL,FMT_HEX,&hf_cops_pc_gate_id);
+}
+
+/* Cops - Section : Activity Count */
+void cops_activity_count(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_tree *stt;
+
+ /* Create a subtree */
+ stt = info_to_cops_subtree(tvb,st,n,offset,"Activity Count");
+
+ /* Activity Count */
+ info_to_display(tvb,stt,offset,4,"Count", NULL,FMT_DEC,&hf_cops_pc_activity_count);
+}
+
+/* Cops - Section : Gate Specifications */
+void cops_gate_specs(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_tree *stt;
+
+ /* Create a subtree */
+ stt = info_to_cops_subtree(tvb,st,n,offset,"Gate Specifications");
+
+ /* Direction */
+ info_to_display(tvb,stt,offset,1,"Direction",table_cops_direction,FMT_DEC,&hf_cops_pc_direction);
+ offset += 1;
+
+ /* Protocol ID */
+ info_to_display(tvb,stt,offset,1,"Protocol ID",NULL,FMT_DEC,&hf_cops_pc_protocol_id);
+ offset += 1;
+
+ /* Flags */
+ info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_DEC,&hf_cops_pc_gate_spec_flags);
+ offset += 1;
+
+ /* Session Class */
+ info_to_display(tvb,stt,offset,1,"Session Class",table_cops_session_class,FMT_DEC,&hf_cops_pc_session_class);
+ offset += 1;
+
+ /* Source IP Address */
+ info_to_display(tvb,stt,offset,4,"Source IP Address",NULL,FMT_IP,&hf_cops_pc_src_ip);
+ offset += 4;
+
+ /* Destination IP Address */
+ info_to_display(tvb,stt,offset,4,"Destination IP Address",NULL,FMT_IP,&hf_cops_pc_dest_ip);
+ offset += 4;
+
+ /* Source IP Port */
+ info_to_display(tvb,stt,offset,2,"Source IP Port",NULL,FMT_DEC,&hf_cops_pc_src_port);
+ offset += 2;
+
+ /* Destination IP Port */
+ info_to_display(tvb,stt,offset,2,"Destination IP Port",NULL,FMT_DEC,&hf_cops_pc_dest_port);
+ offset += 2;
+
+ /* DiffServ Code Point */
+ info_to_display(tvb,stt,offset,1,"DS Field (DSCP or TOS)",NULL,FMT_HEX,&hf_cops_pc_ds_field);
+ offset += 1;
+
+ /* 3 octets Not specified */
+ offset += 3;
+
+ /* Timer T1 Value */
+ info_to_display(tvb,stt,offset,2,"Timer T1 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t1_value);
+ offset += 2;
+
+ /* Reserved */
+ info_to_display(tvb,stt,offset,2,"Reserved",NULL,FMT_DEC,&hf_cops_pc_reserved);
+ offset += 2;
+
+ /* Timer T7 Value */
+ info_to_display(tvb,stt,offset,2,"Timer T7 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t7_value);
+ offset += 2;
+
+ /* Timer T8 Value */
+ info_to_display(tvb,stt,offset,2,"Timer T8 Value (sec)",NULL,FMT_DEC,&hf_cops_pc_t8_value);
+ offset += 2;
+
+ /* Token Bucket Rate */
+ info_to_display(tvb,stt,offset,4,"Token Bucket Rate",NULL,FMT_FLT,&hf_cops_pc_token_bucket_rate);
+ offset += 4;
+
+ /* Token Bucket Size */
+ info_to_display(tvb,stt,offset,4,"Token Bucket Size",NULL,FMT_FLT,&hf_cops_pc_token_bucket_size);
+ offset += 4;
+
+ /* Peak Data Rate */
+ info_to_display(tvb,stt,offset,4,"Peak Data Rate",NULL,FMT_FLT,&hf_cops_pc_peak_data_rate);
+ offset += 4;
+
+ /* Minimum Policed Unit */
+ info_to_display(tvb,stt,offset,4,"Minimum Policed Unit",NULL,FMT_DEC,&hf_cops_pc_min_policed_unit);
+ offset += 4;
+
+ /* Maximum Packet Size */
+ info_to_display(tvb,stt,offset,4,"Maximum Packet Size",NULL,FMT_DEC,&hf_cops_pc_max_packet_size);
+ offset += 4;
+
+ /* Rate */
+ info_to_display(tvb,stt,offset,4,"Rate",NULL,FMT_FLT,&hf_cops_pc_spec_rate);
+ offset += 4;
+
+ /* Slack Term */
+ info_to_display(tvb,stt,offset,4,"Slack Term",NULL,FMT_DEC,&hf_cops_pc_slack_term);
+}
+
+/* Cops - Section : Electronic Surveillance Parameters */
+void cops_surveillance_parameters(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_tree *stt;
+ guint8 *bcid_str;
+
+ /* Create a subtree */
+ stt = info_to_cops_subtree(tvb,st,n,offset,"Electronic Surveillance Parameters");
+
+ /* DF IP Address for CDC */
+ info_to_display(tvb,stt,offset,4,"DF IP Address for CDC", NULL,FMT_IP,&hf_cops_pc_dfcdc_ip);
+ offset += 4;
+
+ /* DF IP Port for CDC */
+ info_to_display(tvb,stt,offset,2,"DF IP Port for CDC",NULL,FMT_DEC,&hf_cops_pc_dfcdc_ip_port);
+ offset += 2;
+
+ /* Flags */
+ info_to_display(tvb,stt,offset,2,"Flags",NULL,FMT_HEX,&hf_cops_pc_gate_spec_flags);
+ offset += 2;
+
+ /* DF IP Address for CCC */
+ info_to_display(tvb,stt,offset,4,"DF IP Address for CCC", NULL,FMT_IP,&hf_cops_pc_dfccc_ip);
+ offset += 4;
+
+ /* DF IP Port for CCC */
+ info_to_display(tvb,stt,offset,2,"DF IP Port for CCC",NULL,FMT_DEC,&hf_cops_pc_dfccc_ip_port);
+ offset += 2;
+
+ /* Reserved */
+ info_to_display(tvb,stt,offset,2,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
+ offset += 2;
+
+ /* CCCID */
+ info_to_display(tvb,stt,offset,4,"CCCID", NULL,FMT_HEX,&hf_cops_pc_srks_ip);
+ offset += 4;
+
+ /* BCID Timestamp */
+ info_to_display(tvb,stt,offset,4,"BCID - Timestamp",NULL,FMT_HEX,&hf_cops_pc_bcid_ts);
+ offset += 4;
+
+ /* BCID Element ID */
+ bcid_str = tvb_get_string(tvb, offset, 8);
+ proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Element ID",bcid_str);
+ offset += 8;
+
+ /* BCID Time Zone */
+ bcid_str = tvb_get_string(tvb, offset, 8);
+ proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Time Zone",bcid_str);
+ offset += 8;
+
+ /* BCID Event Counter */
+ info_to_display(tvb,stt,offset,4,"BCID - Event Counter",NULL,FMT_DEC,&hf_cops_pc_bcid_ev);
+}
+
+/* Cops - Section : Event Gereration-Info */
+void cops_event_generation_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_tree *stt;
+ guint8 *bcid_str;
+
+ /* Create a subtree */
+ stt = info_to_cops_subtree(tvb,st,n,offset,"Event Generation Info");
+
+ /* Primary Record Keeping Server IP Address */
+ info_to_display(tvb,stt,offset,4,"PRKS IP Address", NULL,FMT_IP,&hf_cops_pc_prks_ip);
+ offset += 4;
+
+ /* Primary Record Keeping Server IP Port */
+ info_to_display(tvb,stt,offset,2,"PRKS IP Port",NULL,FMT_DEC,&hf_cops_pc_prks_ip_port);
+ offset += 2;
+
+ /* Flags */
+ info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_HEX,&hf_cops_pc_gate_spec_flags);
+ offset += 1;
+
+ /* Reserved */
+ info_to_display(tvb,stt,offset,1,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
+ offset += 1;
+
+ /* Secundary Record Keeping Server IP Address */
+ info_to_display(tvb,stt,offset,4,"SRKS IP Address", NULL,FMT_IP,&hf_cops_pc_srks_ip);
+ offset += 4;
+
+ /* Secundary Record Keeping Server IP Port */
+ info_to_display(tvb,stt,offset,2,"SRKS IP Port",NULL,FMT_DEC,&hf_cops_pc_srks_ip_port);
+ offset += 2;
+
+ /* Flags */
+ info_to_display(tvb,stt,offset,1,"Flags",NULL,FMT_DEC,&hf_cops_pc_gate_spec_flags);
+ offset += 1;
+
+ /* Reserved */
+ info_to_display(tvb,stt,offset,1,"Reserved",NULL,FMT_HEX,&hf_cops_pc_reserved);
+ offset += 1;
+
+ /* BCID Timestamp */
+ info_to_display(tvb,stt,offset,4,"BCID - Timestamp",NULL,FMT_HEX,&hf_cops_pc_bcid_ts);
+ offset += 4;
+
+ /* BCID Element ID */
+ bcid_str = tvb_get_string(tvb, offset, 8);
+ proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Element ID",bcid_str);
+ offset += 8;
+
+ /* BCID Time Zone */
+ bcid_str = tvb_get_string(tvb, offset, 8);
+ proto_tree_add_text(stt, tvb, offset, 8,"%-28s : '%s'","BCID - Time Zone",bcid_str);
+ offset += 8;
+
+ /* BCID Event Counter */
+ info_to_display(tvb,stt,offset,4,"BCID - Event Counter",NULL,FMT_DEC,&hf_cops_pc_bcid_ev);
+}
+
+/* Cops - Section : Remote Gate */
+void cops_remote_gate_info(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_tree *stt;
+
+ /* Create a subtree */
+ stt = info_to_cops_subtree(tvb,st,n,offset,"Remote Gate Info");
+
+ /* CMTS IP Address */
+ info_to_display(tvb,stt,offset,4,"CMTS IP Address", NULL,FMT_IP,&hf_cops_pc_cmts_ip);
+ offset += 4;
+
+ /* CMTS IP Port */
+ info_to_display(tvb,stt,offset,2,"CMTS IP Port",NULL,FMT_DEC,&hf_cops_pc_cmts_ip_port);
+ offset += 2;
+
+ /* Flags */
+ info_to_display(tvb,stt,offset,2,"Flags",NULL,FMT_DEC,&hf_cops_pc_remote_flags);
+ offset += 2;
+
+ /* Remote Gate ID */
+ info_to_display(tvb,stt,offset,4,"Remote Gate ID", NULL,FMT_HEX,&hf_cops_pc_remote_gate_id);
+ offset += 4;
+
+ /* Algorithm */
+ info_to_display(tvb,stt,offset,2,"Algorithm", NULL,FMT_IP,&hf_cops_pc_algorithm);
+ offset += 2;
+
+ /* Reserved */
+ info_to_display(tvb,stt,offset,4,"Reserved", NULL,FMT_IP,&hf_cops_pc_reserved);
+ offset += 4;
+
+ /* Security Key */
+ info_to_display(tvb,stt,offset,4,"Security Key", NULL,FMT_HEX,&hf_cops_pc_key);
+ offset += 4;
+
+ /* Security Key */
+ info_to_display(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
+ offset += 4;
+
+ /* Security Key */
+ info_to_display(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
+ offset += 4;
+
+ /* Security Key */
+ info_to_display(tvb,stt,offset,4,"Security Key (cont)", NULL,FMT_HEX,&hf_cops_pc_key);
+}
+
+/* Cops - Section : PacketCable reason */
+void cops_packetcable_reason(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_tree *stt;
+ guint16 code16;
+
+ /* Create a subtree */
+ stt = info_to_cops_subtree(tvb,st,n,offset,"PacketCable Reason");
+
+ /* Reason Code */
+ code16 = tvb_get_ntohs(tvb,offset);
+ proto_tree_add_uint_format(stt, hf_cops_pc_reason_code,tvb, offset, 2,
+ code16, "%-28s : %s (%u)","Reason Code",
+ val_to_str(code16, table_cops_reason_code, "Unknown (0x%04x)"),code16);
+ offset += 2;
+
+ if ( code16 == 0 ) {
+ /* Reason Sub Code with Delete */
+ info_to_display(tvb,stt,offset,2,"Reason Sub Code",table_cops_reason_subcode_delete,FMT_DEC,&hf_cops_pc_delete_subcode);
+ } else {
+ /* Reason Sub Code with Close */
+ info_to_display(tvb,stt,offset,2,"Reason Sub Code",table_cops_reason_subcode_close,FMT_DEC,&hf_cops_pc_close_subcode);
+ }
+}
+
+/* Cops - Section : PacketCable error */
+void cops_packetcable_error(tvbuff_t *tvb, proto_tree *st, guint n, guint32 offset) {
+
+ proto_tree *stt;
+
+ /* Create a subtree */
+ stt = info_to_cops_subtree(tvb,st,n,offset,"PacketCable Error");
+
+ /* Error Code */
+ info_to_display(tvb,stt,offset,2,"Error Code",table_cops_packetcable_error,FMT_DEC,&hf_cops_pc_packetcable_err_code);
+ offset += 2;
+
+ /* Error Sub Code */
+ info_to_display(tvb,stt,offset,2,"Error Sub Code",NULL,FMT_HEX,&hf_cops_pc_packetcable_sub_code);
+
+}
+
+/* Analyze the PacketCable objects */
+void cops_analyze_packetcable_obj(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
+
+ gint remdata;
+ guint16 object_len;
+ guint8 s_num, s_type;
+
+ /* Only if this option is enabled by the Gui */
+ if ( cops_packetcable == FALSE ) {
+ return;
+ }
+
+ /* Do the remaining client specific objects */
+ remdata = tvb_length_remaining(tvb, offset);
+ while (remdata > 4) {
+
+ /* In case we have remaining data, then lets try to get this analyzed */
+ object_len = tvb_get_ntohs(tvb, offset);
+ if (object_len < 4) {
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Incorrect PacketCable object length %u < 4", object_len);
+ return;
+ }
+
+ s_num = tvb_get_guint8(tvb, offset + 2);
+ s_type = tvb_get_guint8(tvb, offset + 3);
+
+ /* Tune offset */
+ offset += 4;
+
+ /* Perform the appropriate functions */
+ switch (s_num){
+ case 1:
+ if (s_type == 1) {
+ cops_transaction_id(tvb, tree, object_len, offset);
+ }
+ break;
+ case 2:
+ if (s_type == 1) {
+ cops_subscriber_id_v4(tvb, tree, object_len, offset);
+ }
+ break;
+ case 3:
+ if (s_type == 1) {
+ cops_gate_id(tvb, tree, object_len, offset);
+ }
+ break;
+ case 4:
+ if (s_type == 1) {
+ cops_activity_count(tvb, tree, object_len, offset);
+ }
+ break;
+ case 5:
+ if (s_type == 1) {
+ cops_gate_specs(tvb, tree, object_len, offset);
+ }
+ break;
+ case 6:
+ if (s_type == 1) {
+ cops_remote_gate_info(tvb, tree, object_len, offset);
+ }
+ break;
+ case 7:
+ if (s_type == 1) {
+ cops_event_generation_info(tvb, tree, object_len, offset);
+ }
+ break;
+ case 9:
+ if (s_type == 1) {
+ cops_packetcable_error(tvb, tree, object_len, offset);
+ }
+ break;
+ case 10:
+ if (s_type == 1) {
+ cops_surveillance_parameters(tvb, tree, object_len, offset);
+ }
+ break;
+ case 13:
+ if (s_type == 1) {
+ cops_packetcable_reason(tvb, tree, object_len, offset);
+ }
+ break;
+ }
+
+ /* Tune offset */
+ offset += object_len-4;
+
+ /* See what we can still get from the buffer */
+ remdata = tvb_length_remaining(tvb, offset);
+ }
+}
+
+/* End of PacketCable Addition */
+
+
diff --git a/epan/dissectors/packet-cosine.c b/epan/dissectors/packet-cosine.c
new file mode 100644
index 0000000000..2c8fa84666
--- /dev/null
+++ b/epan/dissectors/packet-cosine.c
@@ -0,0 +1,193 @@
+/* packet-cosine.c
+ * Routines for decoding CoSine IPNOS L2 debug output
+ *
+ * $Id$
+ *
+ * Motonori Shindo <mshindo@mshindo.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * XXX TODO:
+ * o PPoATM and PPoFR encapsulation needs more test.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+
+static int proto_cosine = -1;
+static int hf_pro = -1;
+static int hf_off = -1;
+static int hf_pri = -1;
+static int hf_rm = -1;
+static int hf_err = -1;
+
+static gint ett_raw = -1;
+
+static dissector_handle_t eth_handle;
+static dissector_handle_t ppp_hdlc_handle;
+static dissector_handle_t llc_handle;
+static dissector_handle_t chdlc_handle;
+static dissector_handle_t fr_handle;
+static dissector_handle_t data_handle;
+
+static void
+dissect_cosine(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *fh_tree;
+ proto_item *ti;
+ union wtap_pseudo_header *pseudo_header = pinfo->pseudo_header;
+
+ /* load the top pane info. This should be overwritten by
+ the next protocol in the stack */
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A" );
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A" );
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "N/A" );
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "CoSine IPNOS L2 debug output" );
+
+ /* populate a tree in the second pane with the status of the link
+ layer (ie none) */
+ if(tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_cosine, tvb, 0, 4,
+ "CoSine IPNOS L2 debug output (%s)",
+ pseudo_header->cosine.if_name);
+ fh_tree = proto_item_add_subtree(ti, ett_raw);
+ proto_tree_add_uint(fh_tree, hf_pro, tvb, 0, 0, pseudo_header->cosine.pro);
+ proto_tree_add_uint(fh_tree, hf_off, tvb, 0, 0, pseudo_header->cosine.off);
+ proto_tree_add_uint(fh_tree, hf_pri, tvb, 0, 0, pseudo_header->cosine.pri);
+ proto_tree_add_uint(fh_tree, hf_rm, tvb, 0, 0, pseudo_header->cosine.rm);
+ proto_tree_add_uint(fh_tree, hf_err, tvb, 0, 0, pseudo_header->cosine.err);
+
+ switch (pseudo_header->cosine.encap) {
+ case COSINE_ENCAP_ETH:
+ break;
+ case COSINE_ENCAP_ATM:
+ case COSINE_ENCAP_PPoATM:
+ proto_tree_add_text(fh_tree, tvb, 0, 16, "SAR header");
+ break;
+ case COSINE_ENCAP_PPP:
+ case COSINE_ENCAP_FR:
+ case COSINE_ENCAP_PPoFR:
+ proto_tree_add_text(fh_tree, tvb, 0, 4, "Channel handle ID");
+ break;
+ case COSINE_ENCAP_HDLC:
+ if (pseudo_header->cosine.direction == COSINE_DIR_TX) {
+ proto_tree_add_text(fh_tree, tvb, 0, 2,
+ "Channel handle ID");
+ } else if (pseudo_header->cosine.direction == COSINE_DIR_RX) {
+ proto_tree_add_text(fh_tree, tvb, 0, 4,
+ "Channel handle ID");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (pseudo_header->cosine.encap) {
+ case COSINE_ENCAP_ETH:
+ call_dissector(eth_handle, tvb_new_subset(tvb, 0, -1, -1),
+ pinfo, tree);
+ break;
+ case COSINE_ENCAP_ATM:
+ case COSINE_ENCAP_PPoATM:
+ call_dissector(llc_handle, tvb_new_subset(tvb, 16, -1, -1),
+ pinfo, tree);
+ break;
+ case COSINE_ENCAP_PPP:
+ call_dissector(ppp_hdlc_handle, tvb_new_subset(tvb, 4, -1, -1),
+ pinfo, tree);
+ break;
+ case COSINE_ENCAP_HDLC:
+ if (pseudo_header->cosine.direction == COSINE_DIR_TX) {
+ call_dissector(chdlc_handle, tvb_new_subset(tvb, 2, -1, -1),
+ pinfo, tree);
+ } else if (pseudo_header->cosine.direction == COSINE_DIR_RX) {
+ call_dissector(chdlc_handle, tvb_new_subset(tvb, 4, -1, -1),
+ pinfo, tree);
+ }
+ break;
+ case COSINE_ENCAP_FR:
+ case COSINE_ENCAP_PPoFR:
+ call_dissector(fr_handle, tvb_new_subset(tvb, 4, -1, -1),
+ pinfo, tree);
+ break;
+ case COSINE_ENCAP_TEST:
+ case COSINE_ENCAP_UNKNOWN:
+ call_dissector(data_handle, tvb, pinfo, tree);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+proto_register_cosine(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pro,
+ { "Protocol", "cosine.pro", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_off,
+ { "Offset", "cosine.off", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_pri,
+ { "Priority", "cosine.pri", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_rm,
+ { "Rate Marking", "cosine.rm", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_err,
+ { "Error Code", "cosine.err", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_raw,
+ };
+
+ proto_cosine = proto_register_protocol("CoSine IPNOS L2 debug output",
+ "CoSine", "cosine");
+ proto_register_field_array(proto_cosine, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_cosine(void)
+{
+ dissector_handle_t cosine_handle;
+
+ /*
+ * Get handles for dissectors.
+ */
+ eth_handle = find_dissector("eth");
+ ppp_hdlc_handle = find_dissector("ppp_hdlc");
+ llc_handle = find_dissector("llc");
+ chdlc_handle = find_dissector("chdlc");
+ fr_handle = find_dissector("fr");
+ data_handle = find_dissector("data");
+
+ cosine_handle = create_dissector_handle(dissect_cosine, proto_cosine);
+ dissector_add("wtap_encap", WTAP_ENCAP_COSINE, cosine_handle);
+}
diff --git a/epan/dissectors/packet-cpfi.c b/epan/dissectors/packet-cpfi.c
new file mode 100644
index 0000000000..e478a255b6
--- /dev/null
+++ b/epan/dissectors/packet-cpfi.c
@@ -0,0 +1,527 @@
+/* packet-cpfi.c
+ * Routines for CPFI Cross Point Frame Injector dissection
+ * CPFI - Cross Point Frame Injector is a CNT proprietary
+ * protocol used to carry Fibre Channel data over UDP
+ *
+ * Copyright 2003, Dave Sclarsky <dave_sclarsky[AT]cnt.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-m2tp.c
+ * Thanks to Heinz Prantner for his motivation and assistance
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "prefs.h"
+
+void proto_reg_handoff_cpfi(void);
+
+#define CPFI_DEFAULT_UDP_PORT 5000
+#define CPFI_DEFAULT_TTOT_UDP_PORT 5001
+#define FIRST_TIO_CARD_ADDRESS 0x380
+
+
+/* SOF defines */
+#define CPFI_FRAME_TYPE_MASK 0xF0000000
+#define CPFI_FRAME_TYPE_SHIFT 28
+#define CPFI_SOURCE_MASK 0x0FFC0000
+#define CPFI_SOURCE_SHIFT 18
+#define CPFI_DEST_MASK 0x0003FF00
+#define CPFI_DEST_SHIFT 8
+#define CPFI_SOF_TYPE_MASK 0x000000F0
+#define CPFI_SPEED_MASK 0x0000000C
+#define CPFI_OPM_ERROR_MASK 0x00000002
+#define CPFI_FROM_LCM_MASK 0x00000001
+
+/* EOF defines */
+#define CPFI_EOF_TYPE_MASK 0x78000000
+#define CPFI_EOF_ERROR_MASK 0x7FE00000
+
+/* configurable parameters */
+static guint cpfi_udp_port = CPFI_DEFAULT_UDP_PORT;
+static guint cpfi_ttot_udp_port = CPFI_DEFAULT_TTOT_UDP_PORT;
+static gboolean cpfi_arrow_moves = TRUE;
+
+/* Initialize the protocol and registered fields */
+static int proto_cpfi = -1;
+static int hf_cpfi_word_one = -1;
+static int hf_cpfi_word_two = -1;
+/* SOF word 1: */
+static int hf_cpfi_frame_type = -1;
+static int hf_cpfi_source = -1;
+static int hf_cpfi_dest = -1;
+static int hf_cpfi_SOF_type = -1;
+static int hf_cpfi_speed = -1;
+static int hf_cpfi_OPM_error = -1;
+static int hf_cpfi_from_LCM = -1;
+/* EOF */
+static int hf_cpfi_CRC_32 = -1;
+static int hf_cpfi_EOF_type = -1;
+/* Hidden items */
+static int hf_cpfi_t_instance = -1;
+static int hf_cpfi_t_src_instance = -1;
+static int hf_cpfi_t_dst_instance = -1;
+static int hf_cpfi_t_board = -1;
+static int hf_cpfi_t_src_board = -1;
+static int hf_cpfi_t_dst_board = -1;
+static int hf_cpfi_t_port = -1;
+static int hf_cpfi_t_src_port = -1;
+static int hf_cpfi_t_dst_port = -1;
+
+static guint32 word1;
+static guint32 word2;
+static guint8 frame_type;
+static char src_str[20];
+static char dst_str[20];
+static char l_to_r_arrow[] = "-->";
+static char r_to_l_arrow[] = "<--";
+static const char *left = src_str;
+static const char *right = dst_str;
+static const char *arrow = l_to_r_arrow;
+static const char direction_and_port_string[] = "[%s %s %s] ";
+
+
+/* Initialize the subtree pointers */
+static gint ett_cpfi = -1;
+static gint ett_cpfi_header = -1;
+static gint ett_cpfi_footer = -1;
+
+static dissector_handle_t fc_handle;
+static dissector_handle_t data_handle;
+
+
+static const value_string sof_type_vals[] = {
+ {0, "SOFf"},
+ {1, "SOFi2"},
+ {2, "SOFn2"},
+ {3, "SOFi3"},
+ {4, "SOFn3"},
+ {5, "SOFc1"},
+ {6, "SOFi1"},
+ {7, "SOFn1"},
+ {8, "SOFc4"},
+ {9, "SOFi4"},
+ {10, "SOFn4"},
+ {0, NULL},
+};
+
+static const value_string speed_vals[] = {
+ {0, "1 GBIT"},
+ {1, "2 GBIT"},
+ {2, "4 GBIT"},
+ {3, "10 GBIT"},
+ {0, NULL},
+};
+
+static const value_string eof_type_vals[] = {
+ {0, "EOFn"},
+ {1, "EOFt"},
+ {2, "EOFni"},
+ {3, "EOFa"},
+ {4, "EOFdt"},
+ {5, "EOFdti"},
+ {6, "EOFrt"},
+ {7, "EOFrti"},
+ {0, NULL},
+};
+
+/* Header */
+static void
+dissect_cpfi_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 tda;
+ guint32 src;
+ guint8 src_instance;
+ guint8 src_board;
+ guint8 src_port;
+ guint32 dst;
+ guint8 dst_instance;
+ guint8 dst_board;
+ guint8 dst_port;
+ proto_item *extra_item = NULL;
+ proto_tree *extra_tree = NULL;
+
+ /* add a tree for the header */
+ if ( tree != NULL)
+ {
+ extra_item = proto_tree_add_protocol_format(tree, proto_cpfi, tvb, 0, -1, "Header");
+ extra_tree = proto_item_add_subtree(extra_item, ett_cpfi_header);
+ }
+
+ /* Extract the common header, and get the bits we need */
+ word1 = tvb_get_ntohl (tvb, 0);
+ word2 = tvb_get_ntohl (tvb, sizeof(word1));
+
+ /* Get the frame type, for later use */
+ frame_type = (word1 & CPFI_FRAME_TYPE_MASK) >> CPFI_FRAME_TYPE_SHIFT;
+
+ /* Figure out where the frame came from. dstTDA is source of frame! */
+ tda = (word1 & CPFI_DEST_MASK) >> CPFI_DEST_SHIFT;
+ if ( tda >= FIRST_TIO_CARD_ADDRESS )
+ {
+ strncpy(src_str, " CPFI", sizeof(src_str));
+ src = 0; /* Make it smallest */
+ }
+ else
+ {
+ src_instance = pinfo->src.data[2]-1;
+ src_board = tda >> 4;
+ src_port = tda & 0x0f;
+ src = (1 << 24) + (src_instance << 16) + (src_board << 8) + src_port;
+ snprintf(src_str, sizeof(src_str), "%u.%u.%u", src_instance, src_board, src_port);
+ }
+
+ /* Figure out where the frame is going. srcTDA is destination of frame! */
+ tda = (word1 & CPFI_SOURCE_MASK) >> CPFI_SOURCE_SHIFT;
+ if ( tda >= FIRST_TIO_CARD_ADDRESS )
+ {
+ strncpy(dst_str, " CPFI", sizeof(dst_str));
+ dst = 0; /* Make it smallest */
+ }
+ else
+ {
+ dst_instance = pinfo->dst.data[2]-1;
+ dst_board = tda >> 4;
+ dst_port = tda & 0x0f;
+ dst = (1 << 24) + (dst_instance << 16) + (dst_board << 8) + dst_port;
+ snprintf(dst_str, sizeof(dst_str), "%u.%u.%u", dst_instance, dst_board, dst_port);
+ }
+
+ /* Set up the source and destination and arrow per user configuration. */
+ if ( cpfi_arrow_moves && (dst < src) )
+ {
+ left = dst_str;
+ arrow = r_to_l_arrow;
+ right = src_str;
+ }
+ else
+ {
+ left = src_str;
+ arrow = l_to_r_arrow;
+ right = dst_str;
+ }
+
+ if (extra_tree) {
+ /* For "real" TDAs (i.e. not for microTDAs), add hidden addresses to allow filtering */
+ if ( src != 0 )
+ {
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_instance, tvb, 0, 1, &src_instance);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_src_instance, tvb, 0, 1, &src_instance);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_board, tvb, 0, 1, &src_board);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_src_board, tvb, 0, 1, &src_board);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_port, tvb, 0, 1, &src_port);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_src_port, tvb, 0, 1, &src_port);
+ }
+ if ( dst != 0 )
+ {
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_instance, tvb, 0, 1, &dst_instance);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_dst_instance, tvb, 0, 1, &dst_instance);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_board, tvb, 0, 1, &dst_board);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_dst_board, tvb, 0, 1, &dst_board);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_port, tvb, 0, 1, &dst_port);
+ proto_tree_add_bytes_hidden(extra_tree, hf_cpfi_t_dst_port, tvb, 0, 1, &dst_port);
+ }
+
+ /* add word 1 components to the protocol tree */
+ proto_tree_add_item(extra_tree, hf_cpfi_word_one , tvb, 0, 4, FALSE);
+
+ proto_tree_add_item(extra_tree, hf_cpfi_frame_type, tvb, 0, 4, FALSE);
+ proto_tree_add_item(extra_tree, hf_cpfi_source , tvb, 0, 4, FALSE);
+ proto_tree_add_item(extra_tree, hf_cpfi_dest , tvb, 0, 4, FALSE);
+ proto_tree_add_item(extra_tree, hf_cpfi_SOF_type , tvb, 0, 4, FALSE);
+ proto_tree_add_item(extra_tree, hf_cpfi_speed , tvb, 0, 4, FALSE);
+ proto_tree_add_item(extra_tree, hf_cpfi_OPM_error , tvb, 0, 4, FALSE);
+ proto_tree_add_item(extra_tree, hf_cpfi_from_LCM , tvb, 0, 4, FALSE);
+
+ /* add word 2 components to the protocol tree */
+ proto_tree_add_item(extra_tree, hf_cpfi_word_two , tvb, 4, 4, FALSE);
+ };
+}
+
+/* Footer */
+static void
+dissect_cpfi_footer(tvbuff_t *tvb, proto_tree *tree)
+{
+ proto_item *extra_item = NULL;
+ proto_tree *extra_tree = NULL;
+
+ /* add a tree for the footer */
+ if ( tree != NULL)
+ {
+ extra_item = proto_tree_add_protocol_format(tree, proto_cpfi, tvb, 0, -1, "Footer");
+ extra_tree = proto_item_add_subtree(extra_item, ett_cpfi_footer);
+ }
+
+ if (extra_tree) {
+ proto_tree_add_item(extra_tree, hf_cpfi_CRC_32 , tvb, 0, 4, FALSE);
+ proto_tree_add_item(extra_tree, hf_cpfi_EOF_type, tvb, 4, 4, FALSE);
+ }
+}
+
+/* CPFI */
+static void
+dissect_cpfi(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *header_tvb, *body_tvb, *footer_tvb;
+ proto_item *cpfi_item = NULL;
+ proto_tree *cpfi_tree = NULL;
+ gint length, reported_length, body_length, reported_body_length;
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the protocol tree */
+ cpfi_item = proto_tree_add_item(tree, proto_cpfi, message_tvb, 0, -1, FALSE);
+ cpfi_tree = proto_item_add_subtree(cpfi_item, ett_cpfi);
+ }
+
+ /* Set up the frame controls - can we do better than this? */
+ pinfo->sof_eof = 0;
+ pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
+ pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
+ pinfo->sof_eof |= PINFO_EOF_INVALID;
+
+ /* dissect the message */
+
+ /* extract and process the header */
+ header_tvb = tvb_new_subset(message_tvb, 0, 8, 8);
+ dissect_cpfi_header(header_tvb, pinfo, cpfi_tree);
+
+ /* Got good CPFI frame? */
+ if ( (frame_type == 9) && fc_handle )
+ {
+ /* create a tvb for the rest of the fc frame (exclude the checksum and CPFI trailer) */
+ length = tvb_length_remaining(message_tvb, 8);
+ reported_length = tvb_reported_length_remaining(message_tvb, 8);
+ if (reported_length < 8)
+ {
+ /* We don't even have enough for the footer. */
+ body_tvb = tvb_new_subset(message_tvb, 8, -1, -1);
+ call_dissector(data_handle, body_tvb, pinfo, tree);
+ return;
+ }
+ /* Length of packet, minus the footer. */
+ reported_body_length = reported_length - 8;
+ /* How much of that do we have in the tvbuff? */
+ body_length = length;
+ if (body_length > reported_body_length)
+ body_length = reported_body_length;
+ body_tvb = tvb_new_subset(message_tvb, 8, body_length, reported_body_length);
+ call_dissector(fc_handle, body_tvb, pinfo, tree);
+
+ /* add more info, now that FC added it's */
+ proto_item_append_text(cpfi_item, direction_and_port_string, left, arrow, right);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, direction_and_port_string, left, arrow, right);
+ }
+
+ /* Do the footer */
+ length = tvb_length_remaining(message_tvb, 8+body_length);
+ if (length < 0)
+ {
+ /* The footer wasn't captured at all.
+ XXX - we'd like to throw a BoundsError if that's the case. */
+ return;
+ }
+ footer_tvb = tvb_new_subset(message_tvb, 8+body_length, length, 8);
+ dissect_cpfi_footer(footer_tvb, cpfi_tree);
+ }
+ else if ( data_handle )
+ {
+ /* create a tvb for the rest of the frame */
+ body_tvb = tvb_new_subset(message_tvb, 8, -1, -1);
+ call_dissector(data_handle, body_tvb, pinfo, tree);
+ }
+
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_cpfi(void)
+{
+ module_t *cpfi_module;
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+
+ { &hf_cpfi_word_one,
+ { "Word one", "cpfi.word_one",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_cpfi_word_two,
+ { "Word two", "cfpi.word_two",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_cpfi_frame_type,
+ { "FrmType", "cpfi.frmtype",
+ FT_UINT32, BASE_HEX, NULL, CPFI_FRAME_TYPE_MASK,
+ "Frame Type", HFILL}},
+ { &hf_cpfi_source,
+ { "srcTDA", "cpfi.srcTDA",
+ FT_UINT32, BASE_HEX, NULL, CPFI_SOURCE_MASK,
+ "Source TDA (10 bits)", HFILL}},
+ { &hf_cpfi_dest,
+ { "dstTDA", "cpfi.dstTDA",
+ FT_UINT32, BASE_HEX, NULL, CPFI_DEST_MASK,
+ "Source TDA (10 bits)", HFILL}},
+ { &hf_cpfi_SOF_type,
+ { "SOFtype", "cpfi.SOFtype",
+ FT_UINT32, BASE_HEX, VALS(sof_type_vals), CPFI_SOF_TYPE_MASK,
+ "SOF Type", HFILL}},
+ { &hf_cpfi_speed,
+ { "speed", "cpfi.speed",
+ FT_UINT32, BASE_HEX, VALS(speed_vals), CPFI_SPEED_MASK,
+ "SOF Type", HFILL}},
+ { &hf_cpfi_OPM_error,
+ { "OPMerror", "cpfi.OPMerror",
+ FT_BOOLEAN, 32, NULL, CPFI_OPM_ERROR_MASK,
+ "OPM Error?", HFILL}},
+ { &hf_cpfi_from_LCM,
+ { "fromLCM", "cpfi.fromLCM",
+ FT_BOOLEAN, 32, NULL, CPFI_FROM_LCM_MASK,
+ "from LCM?", HFILL}},
+
+ { &hf_cpfi_CRC_32,
+ { "CRC-32", "cpfi.crc-32",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_cpfi_EOF_type,
+ { "EOFtype", "cpfi.EOFtype",
+ FT_UINT32, BASE_HEX, VALS(eof_type_vals), CPFI_EOF_TYPE_MASK,
+ "EOF Type", HFILL}},
+
+ { &hf_cpfi_t_instance,
+ { "Instance", "cpfi.instance",
+ FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ { &hf_cpfi_t_src_instance,
+ { "Source Instance", "cpfi.src_instance",
+ FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ { &hf_cpfi_t_dst_instance,
+ { "Destination Instance", "cpfi.dst_instance",
+ FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ { &hf_cpfi_t_board,
+ { "Board", "cpfi.board",
+ FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ { &hf_cpfi_t_src_board,
+ { "Source Board", "cpfi.src_board",
+ FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ { &hf_cpfi_t_dst_board,
+ { "Destination Board", "cpfi.dst_board",
+ FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ { &hf_cpfi_t_port,
+ { "Port", "cpfi.port",
+ FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ { &hf_cpfi_t_src_port,
+ { "Source Port", "cpfi.src_port",
+ FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ { &hf_cpfi_t_dst_port,
+ { "Destination Port", "cpfi.dst_port",
+ FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ };
+
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_cpfi,
+ &ett_cpfi_header,
+ &ett_cpfi_footer
+ };
+
+
+ /* Register the protocol name and description */
+ proto_cpfi = proto_register_protocol("Cross Point Frame Injector ", "CPFI", "cpfi");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_cpfi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register our configuration options for CPFI */
+ cpfi_module = prefs_register_protocol(proto_cpfi, proto_reg_handoff_cpfi);
+ prefs_register_uint_preference(cpfi_module, "udp.port", "CPFI UDP Port",
+ "Set the port for CPFI messages (if other"
+ " than the default of 5000)",
+ 10, &cpfi_udp_port);
+ prefs_register_uint_preference(cpfi_module, "udp.port2", "InstanceToInstance UDP Port",
+ "Set the port for InstanceToInstance messages (if other"
+ " than the default of 5001)",
+ 10, &cpfi_ttot_udp_port);
+ prefs_register_bool_preference(cpfi_module, "arrow_ctl",
+ "Enable Active Arrow Control",
+ "Control the way the '-->' is displayed."
+ " When enabled, keeps the 'lowest valued' endpoint of the src-dest pair"
+ " on the left, and the arrow moves to distinguish source from dest."
+ " When disabled, keeps the arrow pointing right so the source of the frame"
+ " is always on the left.",
+ &cpfi_arrow_moves);
+
+}
+
+void
+proto_reg_handoff_cpfi(void)
+{
+ static int cpfi_init_complete = FALSE;
+ static dissector_handle_t cpfi_handle;
+ static dissector_handle_t ttot_handle;
+ if ( !cpfi_init_complete )
+ {
+ cpfi_init_complete = TRUE;
+ fc_handle = find_dissector("fc");
+ data_handle = find_dissector("data");
+ cpfi_handle = create_dissector_handle(dissect_cpfi, proto_cpfi);
+ ttot_handle = create_dissector_handle(dissect_cpfi, proto_cpfi);
+ }
+ else
+ {
+ dissector_delete("udp.port", cpfi_udp_port, cpfi_handle);
+ dissector_delete("udp.port", cpfi_ttot_udp_port, ttot_handle);
+ }
+
+ dissector_add("udp.port", cpfi_udp_port, cpfi_handle);
+ dissector_add("udp.port", cpfi_ttot_udp_port, ttot_handle);
+}
diff --git a/epan/dissectors/packet-cpha.c b/epan/dissectors/packet-cpha.c
new file mode 100644
index 0000000000..77f7a75543
--- /dev/null
+++ b/epan/dissectors/packet-cpha.c
@@ -0,0 +1,567 @@
+/* packet-cpha.c
+ * Routines for the Check Point High-Availability Protocol (CPHAP)
+ * Copyright 2002, Yaniv Kaul <ykaul-at-netvision.net.il>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "ipproto.h"
+
+static int proto_cphap = -1;
+
+static int hf_magic_number = -1;
+static int hf_cpha_protocol_ver = -1;
+static int hf_cluster_number = -1;
+static int hf_opcode = -1;
+static int hf_src_if_num = -1;
+static int hf_random_id = -1;
+static int hf_src_machine_id = -1;
+static int hf_dst_machine_id = -1;
+static int hf_policy_id = -1;
+static int hf_filler = -1;
+static int hf_id_num = -1;
+static int hf_report_code = -1;
+static int hf_ha_mode = -1;
+static int hf_ha_time_unit = -1;
+/*static int hf_problem = -1;*/
+static int hf_num_reported_ifs = -1;
+static int hf_ethernet_add = -1;
+static int hf_is_if_trusted = -1;
+static int hf_ip = -1;
+static int hf_slot_num = -1;
+static int hf_machine_num = -1;
+static int hf_seed = -1;
+static int hf_hash_len = -1;
+static int hf_status = -1;
+static int hf_in_up_num = -1;
+static int hf_in_assumed_up_num = -1;
+static int hf_out_up_num = -1;
+static int hf_out_assumed_up_num = -1;
+static int hf_ifn = -1;
+
+static gint ett_cphap = -1;
+
+#define UDP_PORT_CPHA 8116
+#define CPHA_MAGIC 0x1A90
+
+struct cpha_hdr {
+ guint16 magic_number;
+ guint16 ha_protocol_ver;
+ guint16 cluster_number;
+ guint16 opcode;
+ guint16 src_if_num;
+ guint16 random_id;
+ guint16 src_machine_id;
+ guint16 dst_machine_id;
+ guint16 policy_id;
+ guint16 filler;
+ guint32 data;
+};
+
+struct fwha_my_state_hdr {
+ guint16 id_num;
+ guint16 report_code;
+ guint16 ha_mode;
+ guint16 ha_time_unit;
+ /*guint16 problem;*/
+};
+
+struct conf_reply_hdr {
+ guint32 num_reported_ifs;
+ guint8 ethernet_add[6];
+ guint16 is_if_trusted;
+ guint32 ip;
+};
+
+struct lb_conf_hdr {
+ guint16 slot_num;
+ guint16 machine_num;
+ guint32 seed;
+ guint32 hash_list_len;
+};
+
+struct fwhap_if_state_s {
+ guint8 in_up_num;
+ guint8 in_assumed_up_num;
+ guint8 out_up_num;
+ guint8 out_assumed_up_num;
+};
+
+#define NUM_OPCODE_TYPES 10
+
+static const char *opcode_type_str_short[NUM_OPCODE_TYPES+1] = {
+ "Unknown",
+ "FWHA_MY_STATE",
+ "FWHA_QUERY_STATE",
+ "FWHA_IF_PROBE_REQ",
+ "FWHA_IF_PROBE_REPLY",
+ "FWHA_IFCONF_REQ",
+ "FWHA_IFCONF_REPLY",
+ "FWHA_LB_CONF",
+ "FWHA_LB_CONFIRM",
+ "FWHA_POLICY_CHANGE",
+ "FWHAP_SYNC"
+};
+
+static const char *opcode_type_str_long[NUM_OPCODE_TYPES+1] = {
+ "Unknown OpCode",
+ "Report source machine's state",
+ "Query other machine's state",
+ "Interface active check request",
+ "Interface active check reply",
+ "Interface configuration request",
+ "Interface configuration reply",
+ "LB configuration report request",
+ "LB configuration report reply",
+ "Policy ID change request/notification",
+ "New Sync packet"
+};
+
+#define NUM_STATES 5
+static const char *state_str[NUM_STATES+1] = {
+ "Down/Dead",
+ "Initializing",
+ "Standby",
+ "Ready",
+ "Active/Active-Attention"
+};
+
+static const value_string status_vals[] = {
+ { 1, "New policy arrived - no need to modify HA configuration" },
+ { 2, "New policy arrived - need to modify HA configuration" },
+ { 3, "Ready to change configuration" },
+ { 0, NULL }
+};
+
+#define NUM_HA_MODES 4
+static const char *ha_mode_str[NUM_HA_MODES+1] = {
+ "FWHA_UNDEF_MODE",
+ "FWHA_NOT_ACTIVE_MODE - CPHA is not active",
+ "FWHA_BALANCE_MODE - More than one machine active",
+ "FWHA_PRIMARY_UP_MODE",
+ "FWHA_ONE_UP_MODE"
+};
+
+static const char *ha_magic_num2str(guint16 magic);
+static const char *version2str(guint16 version);
+static const char *opcode2str_short(guint16 opcode);
+static const char *opcode2str_long(guint16 opcode);
+static void dissect_my_state(tvbuff_t *, int, proto_tree *);
+static void dissect_lb_conf(tvbuff_t *, int, proto_tree *);
+static void dissect_policy_change(tvbuff_t *, int, proto_tree *);
+static void dissect_probe(tvbuff_t *, int, proto_tree *);
+static void dissect_conf_reply(tvbuff_t *, int, proto_tree *);
+int is_report_ifs(guint16);
+static const char *report_code2str(guint16);
+static const char *ha_mode2str(guint16);
+static const char *state2str(guint8);
+
+static int
+dissect_cpha(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ struct cpha_hdr hdr;
+ proto_item * ti;
+ proto_item * nti;
+ proto_tree * cpha_tree = NULL;
+ proto_tree * ntree = NULL;
+ guint16 opcode;
+
+ /*
+ * If the magic number or protocol version is unknown, don't treat this
+ * frame as a CPHA frame.
+ */
+ if (!tvb_bytes_exist(tvb, 0, 4)) {
+ /* Not enough data for the magic number or protocol version */
+ return 0;
+ }
+ hdr.magic_number = tvb_get_ntohs(tvb, 0);
+ hdr.ha_protocol_ver = tvb_get_ntohs(tvb, 2);
+ if (ha_magic_num2str(hdr.magic_number) == NULL) {
+ /* Bad magic number */
+ return 0;
+ }
+ if (version2str(hdr.ha_protocol_ver) == NULL) {
+ /* Bad version number */
+ return 0;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CPHA");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
+ hdr.magic_number = g_ntohs(hdr.magic_number);
+ hdr.ha_protocol_ver = g_ntohs(hdr.ha_protocol_ver);
+ hdr.random_id = g_ntohs(hdr.random_id);
+ hdr.src_if_num = g_ntohs(hdr.src_if_num);
+ hdr.src_machine_id = g_ntohs(hdr.src_machine_id);
+ hdr.dst_machine_id = g_ntohs(hdr.dst_machine_id);
+ hdr.policy_id = g_ntohs(hdr.policy_id);
+ hdr.filler = g_ntohs(hdr.filler);
+ opcode = g_ntohs(hdr.opcode);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "CPHAv%d: %s",
+ hdr.ha_protocol_ver, opcode2str_short(opcode));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cphap, tvb, offset, -1, FALSE);
+ cpha_tree = proto_item_add_subtree(ti, ett_cphap);
+ }
+ if (tree) {
+ proto_tree_add_uint_format(cpha_tree, hf_magic_number, tvb, offset, sizeof(hdr.magic_number), hdr.magic_number, "Magic Number: 0x%x (%s)", hdr.magic_number, ha_magic_num2str(hdr.magic_number));
+ offset += sizeof(hdr.magic_number);
+
+ proto_tree_add_uint_format(cpha_tree, hf_cpha_protocol_ver, tvb, offset, sizeof(hdr.ha_protocol_ver), hdr.ha_protocol_ver, "Protocol Version: %d (%s)", hdr.ha_protocol_ver,version2str(hdr.ha_protocol_ver));
+ offset += sizeof(hdr.ha_protocol_ver);
+
+ proto_tree_add_uint(cpha_tree, hf_cluster_number, tvb, offset, sizeof(hdr.cluster_number), g_ntohs(hdr.cluster_number));
+ offset += sizeof(hdr.cluster_number);
+
+ proto_tree_add_uint_format(cpha_tree, hf_opcode, tvb, offset, sizeof(hdr.opcode), opcode,
+ "HA OpCode: %d (%s - %s)", opcode, opcode2str_short(opcode), opcode2str_long(opcode));
+ offset += sizeof(hdr.opcode);
+
+ proto_tree_add_uint(cpha_tree, hf_src_if_num, tvb, offset, sizeof(hdr.src_if_num),
+ hdr.src_if_num);
+ offset += sizeof(hdr.src_if_num);
+
+ proto_tree_add_uint(cpha_tree, hf_random_id, tvb, offset, sizeof(hdr.random_id), hdr.random_id);
+ offset += sizeof(hdr.random_id);
+
+ proto_tree_add_uint(cpha_tree, hf_src_machine_id, tvb, offset, sizeof(hdr.src_machine_id), hdr.src_machine_id);
+ offset += sizeof(hdr.src_machine_id);
+
+ proto_tree_add_uint(cpha_tree, hf_dst_machine_id, tvb, offset, sizeof(hdr.dst_machine_id), hdr.dst_machine_id);
+ offset += sizeof(hdr.dst_machine_id);
+ if(hdr.ha_protocol_ver != 1) {/* 4.1 - no policy_id and filler*/
+ proto_tree_add_uint(cpha_tree, hf_policy_id, tvb, offset, sizeof(hdr.policy_id), hdr.policy_id);
+ offset += sizeof(hdr.policy_id);
+
+ proto_tree_add_uint(cpha_tree, hf_filler, tvb, offset, sizeof(hdr.filler), g_ntohs(hdr.filler));
+ offset += sizeof(hdr.filler);
+ }
+ nti = proto_tree_add_text(cpha_tree, tvb, offset, -1, opcode2str_short(opcode));
+ ntree = proto_item_add_subtree(nti, ett_cphap);
+
+ switch(opcode) {
+ case 1: dissect_my_state(tvb, offset, ntree); /* FWHAP_MY_STATE */
+ break;
+ case 2: break;
+ case 3: /* FWHAP_IF_PROBE_REQ */
+ case 4: dissect_probe(tvb, offset, ntree); /* FWHAP_IF_PROBE_RPLY */
+ break;
+ case 5: break;
+ case 6: dissect_conf_reply(tvb, offset, ntree); /* FWHAP_IFCONF_RPLY */
+ break;
+ case 7: dissect_lb_conf(tvb, offset, ntree); /* FWHAP_LB_CONF */
+ break;
+ case 9: dissect_policy_change(tvb, offset, ntree); /* FWHAP_POLICY_CHANGE */
+ break;
+ default: break;
+ }
+ }
+
+ return tvb_length(tvb);
+}
+
+static void dissect_my_state(tvbuff_t * tvb, int offset, proto_tree * tree) {
+ struct fwha_my_state_hdr hdr;
+ struct fwhap_if_state_s if_hdr;
+ int rep_mode, i;
+ proto_item * nti = NULL;
+ proto_tree * ntree = NULL;
+
+ tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
+ hdr.id_num = g_ntohs(hdr.id_num);
+ hdr.report_code = g_ntohs(hdr.report_code);
+ hdr.ha_mode = g_ntohs(hdr.ha_mode);
+ hdr.ha_time_unit = g_ntohs(hdr.ha_time_unit);
+
+ proto_tree_add_uint(tree, hf_id_num, tvb, offset, sizeof(hdr.id_num), hdr.id_num);
+ offset += sizeof(hdr.id_num);
+
+ proto_tree_add_text(tree, tvb, offset, sizeof(hdr.report_code), "Report Code: %s",report_code2str(hdr.report_code));
+ offset += sizeof(hdr.report_code);
+
+ proto_tree_add_uint_format(tree, hf_ha_mode, tvb, offset, sizeof(hdr.ha_mode), hdr.ha_mode, "HA mode: %d (%s)", hdr.ha_mode, ha_mode2str(hdr.ha_mode));
+ offset += sizeof(hdr.ha_mode);
+
+ proto_tree_add_uint_format(tree, hf_ha_time_unit, tvb, offset, sizeof(hdr.ha_time_unit), hdr.ha_time_unit, "HA Time unit: %d miliseconds", hdr.ha_time_unit);
+ offset += sizeof(hdr.ha_time_unit);
+
+ rep_mode = is_report_ifs(hdr.report_code);
+ if (hdr.report_code & 1) {
+ /* states */
+ nti = proto_tree_add_text(tree, tvb, offset, hdr.id_num * sizeof(guint8), "Machine states");
+ ntree = proto_item_add_subtree(nti, ett_cphap);
+ for(i=0; i < hdr.id_num; i++) {
+ proto_tree_add_text(ntree, tvb, offset, sizeof(guint8), "State of node %d: %d (%s)", i, tvb_get_guint8(tvb, offset), state2str(tvb_get_guint8(tvb, offset)));
+ offset += sizeof(guint8);
+ }
+ }
+ if (hdr.report_code & 2) {
+ /* interface information */
+ nti = proto_tree_add_text(tree, tvb, offset, sizeof(struct fwhap_if_state_s), "Interface states");
+ ntree = proto_item_add_subtree(nti, ett_cphap);
+ tvb_memcpy(tvb, (guint8 *)&if_hdr, offset, sizeof(if_hdr));
+ proto_tree_add_int(ntree, hf_in_up_num, tvb, offset, sizeof(if_hdr.in_up_num), if_hdr.in_up_num);
+ offset += sizeof(if_hdr.in_up_num);
+ proto_tree_add_int(ntree, hf_in_assumed_up_num, tvb, offset, sizeof(if_hdr.in_assumed_up_num), if_hdr.in_assumed_up_num);
+ offset += sizeof(if_hdr.in_assumed_up_num);
+ proto_tree_add_int(ntree, hf_out_up_num, tvb, offset, sizeof(if_hdr.out_up_num), if_hdr.out_up_num);
+ offset += sizeof(if_hdr.out_up_num);
+ proto_tree_add_int(ntree, hf_out_assumed_up_num, tvb, offset, sizeof(if_hdr.out_assumed_up_num), if_hdr.out_assumed_up_num);
+ offset += sizeof(if_hdr.out_assumed_up_num);
+
+ for(i=0; i < hdr.id_num; i++) {
+ proto_tree_add_text(tree, tvb, offset, sizeof(guint8), "Cluster %d: last packet seen %d time units ago", i, tvb_get_guint8(tvb, offset));
+ offset += sizeof(guint8);
+ }
+ }
+
+}
+
+static void dissect_lb_conf(tvbuff_t * tvb, int offset, proto_tree * tree) {
+ struct lb_conf_hdr hdr;
+
+ tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
+ hdr.slot_num = g_ntohs(hdr.slot_num);
+ hdr.machine_num = g_ntohs(hdr.machine_num);
+ hdr.seed = g_ntohs(hdr.seed);
+ hdr.hash_list_len = g_ntohs(hdr.hash_list_len);
+
+ proto_tree_add_uint(tree, hf_slot_num, tvb, offset, sizeof(hdr.slot_num), hdr.slot_num);
+ offset += sizeof(hdr.slot_num);
+
+ proto_tree_add_int(tree, hf_machine_num, tvb, offset, sizeof(hdr.machine_num), hdr.machine_num);
+ offset += sizeof(hdr.machine_num);
+
+ proto_tree_add_uint(tree, hf_seed, tvb, offset, sizeof(hdr.seed), hdr.seed);
+ offset += sizeof(hdr.seed);
+
+ proto_tree_add_uint(tree, hf_hash_len, tvb, offset, sizeof(hdr.hash_list_len), hdr.hash_list_len);
+ offset += sizeof(hdr.hash_list_len);
+
+}
+
+static void dissect_policy_change(tvbuff_t * tvb, int offset, proto_tree * tree) {
+ guint32 status;
+
+ status = tvb_get_ntohl(tvb, offset);
+
+ proto_tree_add_uint(tree, hf_status, tvb, offset, sizeof(status), status);
+ offset += sizeof(guint32);
+}
+
+static void dissect_probe(tvbuff_t * tvb, int offset, proto_tree * tree) {
+ guint32 ifn;
+
+ ifn = tvb_get_ntohl(tvb, offset);
+
+ proto_tree_add_uint(tree, hf_ifn, tvb, offset, sizeof(ifn), ifn);
+ offset += sizeof(guint32);
+}
+
+static void dissect_conf_reply(tvbuff_t * tvb, int offset, proto_tree * tree) {
+ struct conf_reply_hdr hdr;
+
+ tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
+ hdr.num_reported_ifs = g_ntohl(hdr.num_reported_ifs);
+ hdr.is_if_trusted = g_ntohs(hdr.is_if_trusted);
+
+ proto_tree_add_uint(tree, hf_num_reported_ifs, tvb, offset, sizeof(hdr.num_reported_ifs), hdr.num_reported_ifs);
+ offset += sizeof(hdr.num_reported_ifs);
+ proto_tree_add_ether(tree, hf_ethernet_add, tvb, offset, 6, hdr.ethernet_add);
+ offset += 6;
+
+ proto_tree_add_boolean(tree, hf_is_if_trusted, tvb, offset, sizeof(hdr.is_if_trusted), hdr.is_if_trusted);
+ offset += sizeof(hdr.is_if_trusted);
+
+ proto_tree_add_ipv4(tree, hf_ip, tvb, offset, sizeof(hdr.ip), hdr.ip);
+ offset += 4;
+}
+
+int is_report_ifs(guint16 report_code) {
+ if(report_code & 2)
+ return 1;
+ return 0;
+}
+
+static const char *
+report_code2str(guint16 report_code) {
+ int ret;
+ ret = is_report_ifs(report_code);
+ if(!(report_code & 1))
+ return "Machine information NOT present";
+ if(ret == 1)
+ return "Interface information included";
+ return "Unknown report code!";
+}
+static const char *
+ha_magic_num2str(guint16 magic) {
+ if(magic == CPHA_MAGIC)
+ return "correct";
+ return NULL;
+}
+
+static const char *
+version2str(guint16 version) {
+ switch(version) {
+ case 1: return "4.1";
+ break;
+ case 6: return "NG Feature Pack 2";
+ break;
+ case 530: return "NG Feature Pack 3";
+ break;
+ case 540: return "NG with Application Intelligence (Early Availability)";
+ break;
+ case 541: return "NG with Application Intelligence";
+ break;
+ default: return "Unknown Version";
+ break;
+ }
+ return NULL;
+}
+static const char *
+opcode2str_short(guint16 opcode) {
+ if(opcode <= NUM_OPCODE_TYPES)
+ return opcode_type_str_short[opcode];
+ return opcode_type_str_short[0];
+}
+
+static const char *
+ha_mode2str(guint16 hamode) {
+ if(hamode <= NUM_HA_MODES)
+ return ha_mode_str[hamode];
+ return "Unknown HA mode";
+}
+
+static const char *
+state2str(guint8 state) {
+ if(state <= NUM_STATES)
+ return state_str[state];
+ return state_str[0];
+}
+
+
+static const char *
+opcode2str_long(guint16 opcode) {
+ if(opcode <= NUM_OPCODE_TYPES)
+ return opcode_type_str_long[opcode];
+ return opcode_type_str_long[0];
+}
+
+void
+proto_register_cpha(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_magic_number,
+ { "CPHAP Magic Number", "cphap.magic_number", FT_UINT16, BASE_HEX, NULL, 0x0, "CPHAP Magic Number", HFILL}},
+ { &hf_cpha_protocol_ver,
+ { "Protocol Version", "cphap.version", FT_UINT16, BASE_DEC, NULL, 0x0, "CPHAP Version", HFILL}},
+ { &hf_cluster_number,
+ { "Cluster Number", "cphap.cluster_number", FT_UINT16, BASE_DEC, NULL, 0x0, "Cluster Number", HFILL}},
+ { &hf_opcode,
+ { "OpCode", "cphap.opcode", FT_UINT16, BASE_DEC, NULL, 0x0, "OpCode", HFILL}},
+ { &hf_src_if_num,
+ { "Source Interface", "cphap.src_if", FT_UINT16, BASE_DEC, NULL, 0x0, "Source Interface", HFILL}},
+ { &hf_random_id,
+ { "Random ID", "cphap.random_id", FT_UINT16, BASE_DEC, NULL, 0x0, "Random ID", HFILL}},
+ { &hf_src_machine_id,
+ { "Source Machine ID", "cphap.src_id", FT_UINT16, BASE_DEC, NULL, 0x0, "Source Machine ID", HFILL}},
+ { &hf_dst_machine_id,
+ { "Destination Machine ID", "cphap.dst_id", FT_UINT16, BASE_DEC, NULL, 0x0, "Destination Machine ID", HFILL}},
+ { &hf_policy_id,
+ { "Policy ID", "cphap.policy_id", FT_UINT16, BASE_DEC, NULL, 0x0, "Policy ID", HFILL}},
+ { &hf_filler,
+ { "Filler", "cphap.filler", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_id_num,
+ { "Number of IDs reported", "cphap.id_num", FT_UINT16, BASE_DEC, NULL, 0x0, "Number of IDs reported", HFILL}},
+ { &hf_report_code,
+ { "Report code", "cphap.id_num", FT_UINT16, BASE_DEC, NULL, 0x0, "Report Code", HFILL}},
+ { &hf_ha_mode,
+ { "HA mode", "cphap.ha_mode", FT_UINT16, BASE_DEC, NULL, 0x0, "HA Mode", HFILL}},
+ { &hf_ha_time_unit,
+ { "HA Time unit (ms)", "cphap.ha_time_unit", FT_UINT16, BASE_DEC, NULL, 0x0, "HA Time unit", HFILL}},
+ { &hf_num_reported_ifs,
+ { "Reported Interfaces", "cphap.reported_ifs", FT_UINT32, BASE_DEC, NULL, 0x0, "Reported Interfaces", HFILL}},
+ { &hf_ethernet_add,
+ { "Ethernet Address", "cphap.ethernet_addr", FT_ETHER, BASE_HEX, NULL, 0x0, "Ethernet Address", HFILL}},
+ { &hf_is_if_trusted,
+ { "Interface Trusted", "cphap.if_trusted", FT_BOOLEAN, BASE_DEC, NULL, 0x0, "Interface Trusted", HFILL}},
+ { &hf_ip,
+ { "IP Address", "cphap.ip", FT_IPv4, BASE_DEC, NULL, 0x0, "IP Address", HFILL}},
+ { &hf_slot_num,
+ { "Slot Number", "cphap.slot_num", FT_INT16, BASE_DEC, NULL, 0x0, "Slot Number", HFILL}},
+ { &hf_machine_num,
+ { "Machine Number", "cphap.machine_num", FT_INT16, BASE_DEC, NULL, 0x0, "Machine Number", HFILL}},
+ { &hf_seed,
+ { "Seed", "cphap.seed", FT_UINT32, BASE_DEC, NULL, 0x0, "Seed", HFILL}},
+ { &hf_hash_len,
+ { "Hash list length", "cphap.hash_len", FT_INT32, BASE_DEC, NULL, 0x0, "Hash list length", HFILL}},
+ { &hf_in_up_num,
+ { "Interfaces up in the Inbound", "cphap.in_up", FT_INT8, BASE_DEC, NULL, 0x0, "Interfaces up in the Inbound", HFILL}},
+ { &hf_in_assumed_up_num,
+ { "Interfaces assumed up in the Inbound", "cphap.in_assume_up", FT_INT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_out_up_num,
+ { "Interfaces up in the Outbound", "cphap.out_up", FT_INT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_out_assumed_up_num,
+ { "Interfaces assumed up in the Outbound", "cphap.out_assume_up", FT_INT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_status,
+ { "Status", "cphap.status", FT_UINT32, BASE_DEC, VALS(status_vals), 0x0, "", HFILL}},
+ { &hf_ifn,
+ { "Interface Number", "cpha.ifn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ };
+ static gint *ett[] = {
+ &ett_cphap,
+ };
+
+ proto_cphap = proto_register_protocol("Check Point High Availability Protocol",
+ "CPHA", "cpha");
+ proto_register_field_array(proto_cphap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_cpha(void)
+{
+ dissector_handle_t cpha_handle;
+
+ cpha_handle = new_create_dissector_handle(dissect_cpha, proto_cphap);
+ dissector_add("udp.port", UDP_PORT_CPHA, cpha_handle);
+}
diff --git a/epan/dissectors/packet-cups.c b/epan/dissectors/packet-cups.c
new file mode 100644
index 0000000000..9f48d390aa
--- /dev/null
+++ b/epan/dissectors/packet-cups.c
@@ -0,0 +1,391 @@
+/* packet-cups.c
+* Routines for Common Unix Printing System (CUPS) Browsing Protocol
+* packet disassembly for the Ethereal network traffic analyzer.
+*
+* Charles Levert <charles@comm.polymtl.ca>
+* Copyright 2001 Charles Levert
+*
+* $Id$
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+/**********************************************************************/
+
+/* From cups/cups.h, GNU GPL, Copyright 1997-2001 by Easy Software Products. */
+typedef guint32 cups_ptype_t; /**** Printer Type/Capability Bits ****/
+enum /* Not a typedef'd enum so we can OR */
+{
+ CUPS_PRINTER_LOCAL = 0x0000, /* Local printer or class */
+ CUPS_PRINTER_CLASS = 0x0001, /* Printer class */
+ CUPS_PRINTER_REMOTE = 0x0002, /* Remote printer or class */
+ CUPS_PRINTER_BW = 0x0004, /* Can do B&W printing */
+ CUPS_PRINTER_COLOR = 0x0008, /* Can do color printing */
+ CUPS_PRINTER_DUPLEX = 0x0010, /* Can do duplexing */
+ CUPS_PRINTER_STAPLE = 0x0020, /* Can staple output */
+ CUPS_PRINTER_COPIES = 0x0040, /* Can do copies */
+ CUPS_PRINTER_COLLATE = 0x0080, /* Can collage copies */
+ CUPS_PRINTER_PUNCH = 0x0100, /* Can punch output */
+ CUPS_PRINTER_COVER = 0x0200, /* Can cover output */
+ CUPS_PRINTER_BIND = 0x0400, /* Can bind output */
+ CUPS_PRINTER_SORT = 0x0800, /* Can sort output */
+ CUPS_PRINTER_SMALL = 0x1000, /* Can do Letter/Legal/A4 */
+ CUPS_PRINTER_MEDIUM = 0x2000, /* Can do Tabloid/B/C/A3/A2 */
+ CUPS_PRINTER_LARGE = 0x4000, /* Can do D/E/A1/A0 */
+ CUPS_PRINTER_VARIABLE = 0x8000, /* Can do variable sizes */
+ CUPS_PRINTER_IMPLICIT = 0x10000, /* Implicit class */
+ CUPS_PRINTER_DEFAULT = 0x20000, /* Default printer on network */
+ CUPS_PRINTER_OPTIONS = 0xfffc /* ~(CLASS | REMOTE | IMPLICIT) */
+};
+/* End insert from cups/cups.h */
+
+typedef struct {
+ guint32 bit;
+ char *on_string;
+ char *off_string;
+} cups_ptype_bit_info;
+
+static const cups_ptype_bit_info cups_ptype_bits[] = {
+ { CUPS_PRINTER_DEFAULT,
+ "Default printer on network", "Not default printer" },
+ { CUPS_PRINTER_IMPLICIT,
+ "Implicit class", "Explicit class" },
+ { CUPS_PRINTER_VARIABLE,
+ "Can print variable sizes", "Cannot print variable sizes" },
+ { CUPS_PRINTER_LARGE,
+ "Can print up to 36x48 inches", "Cannot print up to 36x48 inches" },
+ { CUPS_PRINTER_MEDIUM,
+ "Can print up to 18x24 inches", "Cannot print up to 18x24 inches" },
+ { CUPS_PRINTER_SMALL,
+ "Can print up to 9x14 inches", "Cannot print up to 9x14 inches" },
+ { CUPS_PRINTER_SORT,
+ "Can sort", "Cannot sort" },
+ { CUPS_PRINTER_BIND,
+ "Can bind", "Cannot bind" },
+ { CUPS_PRINTER_COVER,
+ "Can cover", "Cannot cover" },
+ { CUPS_PRINTER_PUNCH,
+ "Can punch holes", "Cannot punch holes" },
+ { CUPS_PRINTER_COLLATE,
+ "Can do fast collating", "Cannot do fast collating" },
+ { CUPS_PRINTER_COPIES,
+ "Can do fast copies", "Cannot do fast copies" },
+ { CUPS_PRINTER_STAPLE,
+ "Can staple", "Cannot staple" },
+ { CUPS_PRINTER_DUPLEX,
+ "Can duplex", "Cannot duplex" },
+ { CUPS_PRINTER_COLOR,
+ "Can print color", "Cannot print color" },
+ { CUPS_PRINTER_BW,
+ "Can print black", "Cannot print black" },
+ { CUPS_PRINTER_REMOTE,
+ "Remote", "Local (illegal)" },
+ { CUPS_PRINTER_CLASS,
+ "Printer class", "Single printer" }
+};
+
+#define N_CUPS_PTYPE_BITS (sizeof cups_ptype_bits / sizeof cups_ptype_bits[0])
+
+typedef enum _cups_state {
+ CUPS_IDLE = 3,
+ CUPS_PROCESSING,
+ CUPS_STOPPED
+} cups_state_t;
+
+static const value_string cups_state_values[] = {
+ { CUPS_IDLE, "idle" },
+ { CUPS_PROCESSING, "processing" },
+ { CUPS_STOPPED, "stopped" },
+ { 0, NULL }
+};
+
+static int proto_cups = -1;
+static int hf_cups_ptype = -1;
+static int hf_cups_state = -1;
+
+static gint ett_cups = -1;
+static gint ett_cups_ptype = -1;
+
+/* This protocol is heavily related to IPP, but it is CUPS-specific
+ and non-standard. */
+#define UDP_PORT_CUPS 631
+#define PROTO_TAG_CUPS "CUPS"
+
+static guint get_hex_uint(tvbuff_t *tvb, gint offset,
+ gint *next_offset);
+static gboolean skip_space(tvbuff_t *tvb, gint offset,
+ gint *next_offset);
+static const guint8* get_quoted_string(tvbuff_t *tvb, gint offset,
+ gint *next_offset, guint *len);
+static const guint8* get_unquoted_string(tvbuff_t *tvb, gint offset,
+ gint *next_offset, guint *len);
+
+/**********************************************************************/
+
+static void
+dissect_cups(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *cups_tree = 0;
+ proto_tree *ptype_subtree = 0;
+ proto_item *ti = 0;
+ gint offset = 0;
+ gint next_offset;
+ guint len;
+ unsigned int u;
+ const guint8 *str;
+ cups_ptype_t ptype;
+ unsigned int state;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_CUPS);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_cups, tvb, offset, -1,
+ FALSE);
+ cups_tree = proto_item_add_subtree(ti, ett_cups);
+ }
+
+ /* Format (1450 bytes max.): */
+ /* type state uri ["location" ["info" ["make-and-model"]]]\n */
+
+ ptype = get_hex_uint(tvb, offset, &next_offset);
+ len = next_offset - offset;
+ if (len != 0) {
+ if (cups_tree) {
+ ti = proto_tree_add_uint(cups_tree, hf_cups_ptype,
+ tvb, offset, len, ptype);
+ ptype_subtree = proto_item_add_subtree(ti,
+ ett_cups_ptype);
+ for (u = 0; u < N_CUPS_PTYPE_BITS; u++) {
+ proto_tree_add_text(ptype_subtree, tvb,
+ offset, len, "%s",
+ decode_boolean_bitfield(ptype,
+ cups_ptype_bits[u].bit, sizeof (ptype)*8,
+ cups_ptype_bits[u].on_string,
+ cups_ptype_bits[u].off_string));
+ }
+ }
+ }
+ offset = next_offset;
+
+ if (!skip_space(tvb, offset, &next_offset))
+ return; /* end of packet */
+ offset = next_offset;
+
+ state = get_hex_uint(tvb, offset, &next_offset);
+ len = next_offset - offset;
+ if (len != 0) {
+ if (cups_tree)
+ proto_tree_add_uint(cups_tree, hf_cups_state,
+ tvb, offset, len, state);
+ }
+ offset = next_offset;
+
+ if (!skip_space(tvb, offset, &next_offset))
+ return; /* end of packet */
+ offset = next_offset;
+
+ str = get_unquoted_string(tvb, offset, &next_offset, &len);
+ if (str == NULL)
+ return; /* separator/terminator not found */
+ if (cups_tree)
+ proto_tree_add_text(cups_tree, tvb, offset, len,
+ "URI: %.*s",
+ (guint16) len, str);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%.*s (%s)",
+ (guint16) len, str,
+ val_to_str(state, cups_state_values, "0x%x"));
+ offset = next_offset;
+
+ if (!cups_tree)
+ return;
+
+ if (!skip_space(tvb, offset, &next_offset))
+ return; /* end of packet */
+ offset = next_offset;
+
+ str = get_quoted_string(tvb, offset, &next_offset, &len);
+ if (str == NULL)
+ return; /* separator/terminator not found */
+ proto_tree_add_text(cups_tree, tvb, offset+1, len,
+ "Location: \"%.*s\"",
+ (guint16) len, str);
+ offset = next_offset;
+
+ if (!skip_space(tvb, offset, &next_offset))
+ return; /* end of packet */
+ offset = next_offset;
+
+ str = get_quoted_string(tvb, offset, &next_offset, &len);
+ if (str == NULL)
+ return; /* separator/terminator not found */
+ proto_tree_add_text(cups_tree, tvb, offset+1, len,
+ "Information: \"%.*s\"",
+ (guint16) len, str);
+ offset = next_offset;
+
+ if (!skip_space(tvb, offset, &next_offset))
+ return; /* end of packet */
+ offset = next_offset;
+
+ str = get_quoted_string(tvb, offset, &next_offset, &len);
+ if (str == NULL)
+ return; /* separator/terminator not found */
+ proto_tree_add_text(cups_tree, tvb, offset+1, len,
+ "Make and model: \"%.*s\"",
+ (guint16) len, str);
+ offset = next_offset;
+
+ return;
+}
+
+static guint
+get_hex_uint(tvbuff_t *tvb, gint offset, gint *next_offset)
+{
+ int c;
+ guint u = 0;
+
+ while (isxdigit(c = tvb_get_guint8(tvb, offset))) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isupper(c))
+ c -= 'A' - 10;
+ else if (islower(c))
+ c -= 'a' - 10;
+ else
+ c = 0; /* This should not happen. */
+
+ u = 16*u + c;
+
+ offset++;
+ }
+
+ *next_offset = offset;
+
+ return u;
+}
+
+static gboolean
+skip_space(tvbuff_t *tvb, gint offset, gint *next_offset)
+{
+ int c;
+
+ while ((c = tvb_get_guint8(tvb, offset)) == ' ')
+ offset++;
+ if (c == '\r' || c == '\n')
+ return FALSE; /* end of packet */
+
+ *next_offset = offset;
+
+ return TRUE;
+}
+
+static const guint8*
+get_quoted_string(tvbuff_t *tvb, gint offset, gint *next_offset, guint *len)
+{
+ int c;
+ const guint8* s = NULL;
+ guint l = 0;
+ gint o;
+
+ c = tvb_get_guint8(tvb, offset);
+ if (c == '"') {
+ o = tvb_find_guint8(tvb, offset+1, -1, '"');
+ if (o != -1) {
+ offset++;
+ l = o - offset;
+ s = tvb_get_ptr(tvb, offset, l);
+ offset = o + 1;
+ }
+ }
+
+ *next_offset = offset;
+ *len = l;
+
+ return s;
+}
+
+static const guint8*
+get_unquoted_string(tvbuff_t *tvb, gint offset, gint *next_offset, guint *len)
+{
+ const guint8* s = NULL;
+ guint l = 0;
+ gint o;
+
+ o = tvb_pbrk_guint8(tvb, offset, -1, " \t\r\n");
+ if (o != -1) {
+ l = o - offset;
+ s = tvb_get_ptr(tvb, offset, l);
+ offset = o;
+ }
+
+ *next_offset = offset;
+ *len = l;
+
+ return s;
+}
+
+/**********************************************************************/
+
+void
+proto_register_cups(void)
+{
+ static hf_register_info hf[] = {
+ /* This one could be split in separate fields. */
+ { &hf_cups_ptype,
+ { "Type", "cups.ptype", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_cups_state,
+ { "State", "cups.state", FT_UINT8, BASE_HEX,
+ VALS(cups_state_values), 0x0, "", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_cups,
+ &ett_cups_ptype
+ };
+
+ proto_cups = proto_register_protocol(
+ "Common Unix Printing System (CUPS) Browsing Protocol",
+ "CUPS", "cups");
+ proto_register_field_array(proto_cups, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_cups(void)
+{
+ dissector_handle_t cups_handle;
+
+ cups_handle = create_dissector_handle(dissect_cups, proto_cups);
+ dissector_add("udp.port", UDP_PORT_CUPS, cups_handle);
+}
diff --git a/epan/dissectors/packet-data.c b/epan/dissectors/packet-data.c
new file mode 100644
index 0000000000..29c190e524
--- /dev/null
+++ b/epan/dissectors/packet-data.c
@@ -0,0 +1,71 @@
+/* packet-data.c
+ * Routines for raw data (default case)
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-data.h"
+
+/* proto_data cannot be static because it's referenced in the
+ * print routines
+ */
+int proto_data = -1;
+
+static void
+dissect_data(tvbuff_t *tvb, packet_info *pinfo _U_ , proto_tree *tree)
+{
+ int bytes;
+
+ if (tree) {
+ bytes = tvb_length_remaining(tvb, 0);
+ if (bytes > 0) {
+ proto_tree_add_protocol_format(tree, proto_data, tvb,
+ 0,
+ bytes, "Data (%d byte%s)", bytes,
+ plurality(bytes, "", "s"));
+ }
+ }
+}
+
+void
+proto_register_data(void)
+{
+ proto_data = proto_register_protocol (
+ "Data", /* name */
+ "Data", /* short name */
+ "data" /* abbrev */
+ );
+
+ register_dissector("data", dissect_data, proto_data);
+
+ /*
+ * "Data" is used to dissect something whose normal dissector
+ * is disabled, so it cannot itself be disabled.
+ */
+ proto_set_cant_toggle(proto_data);
+}
diff --git a/epan/dissectors/packet-data.h b/epan/dissectors/packet-data.h
new file mode 100644
index 0000000000..9906948b50
--- /dev/null
+++ b/epan/dissectors/packet-data.h
@@ -0,0 +1,29 @@
+/* packet-data.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DATA_H__
+#define __PACKET_DATA_H__
+
+extern int proto_data;
+
+#endif /* __PACKET_DATA_H__ */
diff --git a/epan/dissectors/packet-dccp.c b/epan/dissectors/packet-dccp.c
new file mode 100644
index 0000000000..60cf3c64f7
--- /dev/null
+++ b/epan/dissectors/packet-dccp.c
@@ -0,0 +1,564 @@
+/* packet-dccp.c
+ * Routines for Distributed Checksum Clearinghouse packet dissection
+ * DCC Home: http://www.rhyolite.com/anti-spam/dcc/
+ *
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <packet-dccp.h>
+
+static int proto_dccp = -1;
+static int hf_dccp_len = -1;
+static int hf_dccp_pkt_vers = -1;
+static int hf_dccp_op = -1;
+static int hf_dccp_clientid = -1;
+static int hf_dccp_opnums_host = -1;
+static int hf_dccp_opnums_pid = -1;
+static int hf_dccp_opnums_report = -1;
+static int hf_dccp_opnums_retrans = -1;
+
+static int hf_dccp_signature = -1;
+static int hf_dccp_max_pkt_vers = -1;
+static int hf_dccp_qdelay_ms = -1;
+static int hf_dccp_brand = -1;
+
+static int hf_dccp_ck_type = -1;
+static int hf_dccp_ck_len = -1;
+static int hf_dccp_ck_sum = -1;
+
+static int hf_dccp_date = -1;
+
+static int hf_dccp_target = -1;
+
+static int hf_dccp_adminop = -1;
+static int hf_dccp_adminval = -1;
+static int hf_dccp_floodop = -1;
+static int hf_dccp_trace = -1;
+static int hf_dccp_trace_admin = -1;
+static int hf_dccp_trace_anon = -1;
+static int hf_dccp_trace_client = -1;
+static int hf_dccp_trace_rlim = -1;
+static int hf_dccp_trace_query = -1;
+static int hf_dccp_trace_ridc = -1;
+static int hf_dccp_trace_flood = -1;
+
+static gint ett_dccp = -1;
+static gint ett_dccp_opnums = -1;
+static gint ett_dccp_op = -1;
+static gint ett_dccp_ck = -1;
+static gint ett_dccp_trace = -1;
+
+/* Utility macros */
+#define D_SIGNATURE() \
+ proto_tree_add_item(dccp_optree, hf_dccp_signature, tvb, \
+ offset, sizeof(DCC_SIGNATURE), FALSE); \
+ offset += sizeof(DCC_SIGNATURE);
+
+#define D_LABEL(label,len) \
+ proto_tree_add_text(dccp_optree, tvb, offset, len, label); \
+ offset += len;
+
+#define D_TEXT(label, endpad) { \
+ int next_offset,linelen,left; \
+ const char *line; \
+ while (tvb_offset_exists(tvb, offset+endpad)) { \
+ left = tvb_length_remaining(tvb,offset) - endpad; \
+ linelen = tvb_find_line_end(tvb, offset, left, &next_offset, \
+ FALSE); \
+ line = tvb_get_ptr(tvb, offset, linelen); \
+ proto_tree_add_text(dccp_optree, tvb, offset, \
+ next_offset - offset, "%s: %s", \
+ label, tvb_format_text(tvb, offset, next_offset - offset)); \
+ offset = next_offset; \
+ } \
+}
+
+
+#define D_TARGET() \
+ proto_tree_add_item_hidden(dccp_tree, hf_dccp_target, tvb, \
+ offset, sizeof(DCC_TGTS), FALSE); \
+ proto_tree_add_text(dccp_optree, tvb, offset, sizeof(DCC_TGTS), \
+ val_to_str(tvb_get_ntohl(tvb,offset), dccp_target_vals, "Targets (%u)")); \
+ offset += sizeof(DCC_TGTS); \
+
+#define D_DATE() { \
+ nstime_t ts; \
+ ts.nsecs = 0; \
+ ts.secs = tvb_get_ntohl(tvb,offset); \
+ proto_tree_add_time(dccp_optree, hf_dccp_date, tvb, offset, 4, &ts); \
+ offset += 4; \
+}
+
+
+#define D_CHECKSUM() { \
+ proto_tree *cktree, *ti; \
+ ti = proto_tree_add_text(dccp_optree, tvb, offset, sizeof(DCC_CK), \
+ "Checksum - %s", val_to_str(tvb_get_guint8(tvb,offset), \
+ dccp_cktype_vals, \
+ "Unknown Type: %u")); \
+ cktree = proto_item_add_subtree(ti, ett_dccp_ck); \
+ proto_tree_add_item(cktree, hf_dccp_ck_type, tvb, offset, 1, FALSE); \
+ offset += 1; \
+ proto_tree_add_item(cktree, hf_dccp_ck_len, tvb, offset, 1, FALSE); \
+ offset += 1; \
+ proto_tree_add_item(cktree, hf_dccp_ck_sum, tvb, offset, \
+ sizeof(DCC_SUM), FALSE); \
+ offset += sizeof(DCC_SUM); \
+}
+
+
+/* Lookup string tables */
+static const value_string dccp_op_vals[] = {
+ {DCC_OP_INVALID, "Invalid Op"},
+ {DCC_OP_NOP, "No-Op"},
+ {DCC_OP_REPORT, "Report and Query"},
+ {DCC_OP_QUERY, "Query"},
+ {DCC_OP_QUERY_RESP, "Server Response"},
+ {DCC_OP_ADMN, "Admin"},
+ {DCC_OP_OK, "Ok"},
+ {DCC_OP_ERROR, "Server Failing"},
+ {DCC_OP_DELETE, "Delete Checksum(s)"},
+ {0, NULL}
+};
+
+static const value_string dccp_cktype_vals[] = {
+ {DCC_CK_INVALID, "Invalid/Deleted from DB when seen"},
+ {DCC_CK_IP, "MD5 of binary source IPv6 address"},
+ {DCC_CK_ENV_FROM, "MD5 of envelope Mail From value"},
+ {DCC_CK_FROM, "MD5 of header From: line"},
+ {DCC_CK_SUB, "MD5 of substitute header line"},
+ {DCC_CK_MESSAGE_ID, "MD5 of header Message-ID: line"},
+ {DCC_CK_RECEIVED, "MD5 of last header Received: line"},
+ {DCC_CK_BODY, "MD5 of body"},
+ {DCC_CK_FUZ1, "MD5 of filtered body - FUZ1"},
+ {DCC_CK_FUZ2, "MD5 of filtered body - FUZ2"},
+ {DCC_CK_FUZ3, "MD5 of filtered body - FUZ3"},
+ {DCC_CK_FUZ4, "MD5 of filtered body - FUZ4"},
+ {DCC_CK_SRVR_ID, "hostname for server-ID check "},
+ {DCC_CK_ENV_TO, "MD5 of envelope Rcpt To value"},
+ {0, NULL},
+};
+
+static const value_string dccp_adminop_vals[] = {
+ {DCC_AOP_OK, "Never sent"},
+ {DCC_AOP_STOP, "Stop Gracefully"},
+ {DCC_AOP_NEW_IDS, "Load keys and client IDs"},
+ {DCC_AOP_FLOD, "Flood control"},
+ {DCC_AOP_DB_UNLOCK, "Start Switch to new database"},
+ {DCC_AOP_DB_NEW, "Finish Switch to new database"},
+ {DCC_AOP_STATS, "Return counters"},
+ {DCC_AOP_STATS_CLEAR, "Return and zero counters"},
+ {DCC_AOP_TRACE_ON, "Enable tracing"},
+ {DCC_AOP_TRACE_OFF, "Disable tracing"},
+ {DCC_AOP_CUR_CLIENTS, "List clients"},
+ {0, NULL},
+};
+
+static const value_string dccp_target_vals[] = {
+ {DCC_TGTS_TOO_MANY, "Targets (>= 16777200)"},
+ {DCC_TGTS_OK, "Certified not spam"},
+ {DCC_TGTS_OK2, "Half certified not spam"},
+ {DCC_TGTS_DEL, "Deleted checksum"},
+ {DCC_TGTS_INVALID, "Invalid"},
+ {0, NULL},
+};
+
+static const value_string dccp_floodop_vals[] = {
+ {DCC_AOP_FLOD_CHECK, "Check"},
+ {DCC_AOP_FLOD_SHUTDOWN, "Shutdown"},
+ {DCC_AOP_FLOD_HALT, "Halt"},
+ {DCC_AOP_FLOD_RESUME, "Resume"},
+ {DCC_AOP_FLOD_REWIND, "Rewind"},
+ {DCC_AOP_FLOD_LIST, "List"},
+ {DCC_AOP_FLOD_STATS, "Stats"},
+ {DCC_AOP_FLOD_STATS_CLEAR, "Clear Stats"},
+ {0,NULL},
+};
+
+static gboolean
+dissect_dccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *dccp_tree, *dccp_optree, *dccp_opnumtree, *ti;
+ proto_tree *dccp_tracetree;
+ int offset = 0;
+ int client_is_le = 0;
+ int op = 0;
+ int i, is_response;
+
+ if (pinfo->srcport != DCC_PORT && pinfo->destport != DCC_PORT) {
+ /* Not the right port - not a DCC packet. */
+ return FALSE;
+ }
+
+ /* get at least a full packet structure */
+ if ( !tvb_bytes_exist(tvb, 0, sizeof(DCC_HDR)) ) {
+ /* Doesn't have enough bytes to contain packet header. */
+ return FALSE;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCCP");
+
+ offset = 0;
+ is_response = pinfo->srcport == DCC_PORT;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s: %s",
+ is_response ? "Response" : "Request",
+ val_to_str(tvb_get_guint8(tvb, offset+3),
+ dccp_op_vals, "Unknown Op: %u")
+ );
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_dccp, tvb, offset, -1,
+ FALSE);
+ dccp_tree = proto_item_add_subtree(ti, ett_dccp);
+
+ proto_tree_add_item(dccp_tree, hf_dccp_len, tvb,
+ offset, 2, FALSE);
+
+ if ( !tvb_bytes_exist(tvb, 0, tvb_get_ntohs(tvb, offset))) {
+ /* Doesn't have number of bytes that header claims. */
+ proto_tree_add_text(dccp_tree, tvb, offset, 2, "Error - packet is shorter than header claims!");
+ }
+ offset += 2;
+
+ proto_tree_add_item(dccp_tree, hf_dccp_pkt_vers, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ op = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(dccp_tree, hf_dccp_op, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(dccp_tree, hf_dccp_clientid, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ ti = proto_tree_add_text(dccp_tree, tvb, offset, -1, "Operation Numbers (Opaque to Server)");
+ dccp_opnumtree = proto_item_add_subtree(ti, ett_dccp_opnums);
+
+ /* Note - these are indeterminate - they are sortof considered opaque to the client */
+ /* Make some attempt to figure out if this data is little endian, not guaranteed to be
+ correct if connection went through a firewall or similar. */
+
+ /* Very hokey check - if all three of pid/report/retrans look like little-endian
+ numbers, host is probably little endian. Probably innacurate on super-heavily-used
+ DCC clients though. This should be good enough for now. */
+ client_is_le = ( (tvb_get_guint8(tvb, offset+4) | tvb_get_guint8(tvb, offset+4)) &&
+ (tvb_get_guint8(tvb, offset+8) | tvb_get_guint8(tvb, offset+9)) &&
+ (tvb_get_guint8(tvb, offset+12) | tvb_get_guint8(tvb, offset+13)) );
+
+ proto_tree_add_item(dccp_opnumtree, hf_dccp_opnums_host, tvb,
+ offset, 4, client_is_le);
+ offset += 4;
+
+ proto_tree_add_item(dccp_opnumtree, hf_dccp_opnums_pid, tvb,
+ offset, 4, client_is_le);
+ offset += 4;
+
+ proto_tree_add_item(dccp_opnumtree, hf_dccp_opnums_report, tvb,
+ offset, 4, client_is_le);
+ offset += 4;
+
+ proto_tree_add_item(dccp_opnumtree, hf_dccp_opnums_retrans, tvb,
+ offset, 4, client_is_le);
+ offset += 4;
+
+ ti = proto_tree_add_text(dccp_tree, tvb, offset, -1, "Operation: %s",
+ val_to_str(op, dccp_op_vals, "Unknown Op: %u"));
+ dccp_optree = proto_item_add_subtree(ti, ett_dccp_op);
+
+ switch(op) {
+ case DCC_OP_NOP:
+ D_SIGNATURE();
+ break;
+
+ case DCC_OP_REPORT:
+ D_TARGET();
+ for (i=0; i<=DCC_QUERY_MAX &&
+ tvb_bytes_exist(tvb, offset+sizeof(DCC_SIGNATURE),1); i++)
+ {
+ D_CHECKSUM();
+ }
+ D_SIGNATURE();
+ break;
+
+ case DCC_OP_QUERY_RESP:
+ for (i=0; i<=DCC_QUERY_MAX &&
+ tvb_bytes_exist(tvb, offset+sizeof(DCC_SIGNATURE),1); i++)
+ {
+ D_TARGET();
+ }
+ D_SIGNATURE();
+ break;
+
+ case DCC_OP_ADMN:
+ if ( is_response )
+ {
+ int left = tvb_length_remaining(tvb, offset) -
+ sizeof(DCC_SIGNATURE);
+ if ( left == sizeof(DCC_ADMN_RESP_CLIENTS) )
+ {
+ D_LABEL("Addr", 16);
+ D_LABEL("Id", sizeof(DCC_CLNT_ID));
+ D_LABEL("Last Used", 4);
+ D_LABEL("Requests", 4);
+ }
+ else
+ {
+ D_TEXT("Response Text", sizeof(DCC_SIGNATURE));
+ }
+ D_SIGNATURE();
+ }
+ else
+ {
+ int aop;
+
+ D_DATE();
+
+ aop = tvb_get_guint8(tvb, offset+4);
+ proto_tree_add_item(dccp_optree, hf_dccp_adminop, tvb, offset+4,
+ 1, FALSE);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(tvb_get_guint8(tvb,offset+4),
+ dccp_adminop_vals, "Unknown (%u)"));
+ }
+
+ if (aop == DCC_AOP_TRACE_ON || aop == DCC_AOP_TRACE_OFF )
+ {
+ ti = proto_tree_add_item(dccp_optree, hf_dccp_trace, tvb, offset,
+ 4, FALSE);
+ dccp_tracetree = proto_item_add_subtree(ti, ett_dccp_trace);
+ proto_tree_add_item(dccp_tracetree, hf_dccp_trace_admin, tvb, offset, 4, FALSE);
+ proto_tree_add_item(dccp_tracetree, hf_dccp_trace_anon, tvb, offset, 4, FALSE);
+ proto_tree_add_item(dccp_tracetree, hf_dccp_trace_client, tvb, offset, 4, FALSE);
+ proto_tree_add_item(dccp_tracetree, hf_dccp_trace_rlim, tvb, offset, 4, FALSE);
+ proto_tree_add_item(dccp_tracetree, hf_dccp_trace_query, tvb, offset, 4, FALSE);
+ proto_tree_add_item(dccp_tracetree, hf_dccp_trace_ridc, tvb, offset, 4, FALSE);
+ proto_tree_add_item(dccp_tracetree, hf_dccp_trace_flood, tvb, offset, 4, FALSE);
+ }
+ else if ( aop == DCC_AOP_FLOD )
+ {
+ proto_tree_add_item(dccp_optree, hf_dccp_floodop,
+ tvb, offset, 4, FALSE);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(tvb_get_ntohl(tvb,offset),
+ dccp_floodop_vals, "Unknown (%u)"));
+ }
+ }
+ else
+ {
+ proto_tree_add_item(dccp_optree, hf_dccp_adminval,
+ tvb, offset, 4, FALSE);
+ }
+ offset += 4;
+
+ offset += 1; /* admin op we did in reverse order */
+ D_LABEL("Pad", 3);
+ D_SIGNATURE();
+ }
+ break;
+
+ case DCC_OP_OK:
+ proto_tree_add_item(dccp_optree, hf_dccp_max_pkt_vers, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ D_LABEL("Unused", 1);
+
+ proto_tree_add_item(dccp_optree, hf_dccp_qdelay_ms, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(dccp_optree, hf_dccp_brand, tvb,
+ offset, sizeof(DCC_BRAND), FALSE);
+ offset += sizeof(DCC_BRAND);
+
+ D_SIGNATURE();
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+void
+proto_register_dccp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_dccp_len, {
+ "Packet Length", "dccp.len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Packet Length", HFILL }},
+
+ { &hf_dccp_pkt_vers, {
+ "Packet Version", "dccp.pkt_vers", FT_UINT16, BASE_DEC,
+ NULL, 0, "Packet Version", HFILL }},
+
+ { &hf_dccp_op, {
+ "Operation Type", "dccp.op", FT_UINT8, BASE_DEC,
+ VALS(dccp_op_vals), 0, "Operation Type", HFILL }},
+
+ { &hf_dccp_clientid, {
+ "Client ID", "dccp.clientid", FT_UINT32, BASE_DEC,
+ NULL, 0, "Client ID", HFILL }},
+
+ { &hf_dccp_opnums_host, {
+ "Host", "dccp.opnums.host", FT_IPv4, BASE_DEC,
+ NULL, 0, "Host", HFILL }},
+
+ { &hf_dccp_opnums_pid, {
+ "Process ID", "dccp.opnums.pid", FT_UINT32, BASE_DEC,
+ NULL, 0, "Process ID", HFILL }},
+
+ { &hf_dccp_opnums_report, {
+ "Report", "dccp.opnums.report", FT_UINT32, BASE_DEC,
+ NULL, 0, "Report", HFILL }},
+
+ { &hf_dccp_opnums_retrans, {
+ "Retransmission", "dccp.opnums.retrans", FT_UINT32, BASE_DEC,
+ NULL, 0, "Retransmission", HFILL }},
+
+ { &hf_dccp_signature, {
+ "Signature", "dccp.signature", FT_BYTES, BASE_HEX,
+ NULL, 0, "Signature", HFILL }},
+
+ { &hf_dccp_max_pkt_vers, {
+ "Maximum Packet Version", "dccp.max_pkt_vers", FT_UINT8, BASE_DEC,
+ NULL, 0, "Maximum Packet Version", HFILL }},
+
+ { &hf_dccp_qdelay_ms, {
+ "Client Delay", "dccp.qdelay_ms", FT_UINT16, BASE_DEC,
+ NULL, 0, "Client Delay", HFILL }},
+
+ { &hf_dccp_brand, {
+ "Server Brand", "dccp.brand", FT_STRING, BASE_DEC,
+ NULL, 0, "Server Brand", HFILL }},
+
+ { &hf_dccp_ck_type, {
+ "Type", "dccp.checksum.type", FT_UINT8, BASE_DEC,
+ VALS(dccp_cktype_vals), 0, "Checksum Type", HFILL }},
+
+ { &hf_dccp_ck_len, {
+ "Length", "dccp.checksum.length", FT_UINT8, BASE_DEC,
+ NULL, 0, "Checksum Length", HFILL }},
+
+ { &hf_dccp_ck_sum, {
+ "Sum", "dccp.checksum.sum", FT_BYTES, BASE_HEX,
+ NULL, 0, "Checksum", HFILL }},
+
+ { &hf_dccp_target, {
+ "Target", "dccp.target", FT_UINT32, BASE_HEX,
+ NULL, 0, "Target", HFILL }},
+
+ { &hf_dccp_date, {
+ "Date", "dccp.date", FT_ABSOLUTE_TIME, BASE_DEC,
+ NULL, 0, "Date", HFILL }},
+
+ { &hf_dccp_adminop, {
+ "Admin Op", "dccp.adminop", FT_UINT8, BASE_DEC,
+ VALS(dccp_adminop_vals), 0, "Admin Op", HFILL }},
+
+ { &hf_dccp_adminval, {
+ "Admin Value", "dccp.adminval", FT_UINT32, BASE_DEC,
+ NULL, 0, "Admin Value", HFILL }},
+
+ { &hf_dccp_trace, {
+ "Trace Bits", "dccp.trace", FT_UINT32, BASE_HEX,
+ NULL, 0, "Trace Bits", HFILL }},
+
+ { &hf_dccp_trace_admin, {
+ "Admin Requests", "dccp.trace.admin", FT_BOOLEAN, 32,
+ NULL, 0x00000001, "Admin Requests", HFILL }},
+
+ { &hf_dccp_trace_anon, {
+ "Anonymous Requests", "dccp.trace.anon", FT_BOOLEAN, 32,
+ NULL, 0x00000002, "Anonymous Requests", HFILL }},
+
+ { &hf_dccp_trace_client, {
+ "Authenticated Client Requests", "dccp.trace.client", FT_BOOLEAN, 32,
+ NULL, 0x00000004, "Authenticated Client Requests", HFILL }},
+
+ { &hf_dccp_trace_rlim, {
+ "Rate-Limited Requests", "dccp.trace.rlim", FT_BOOLEAN, 32,
+ NULL, 0x00000008, "Rate-Limited Requests", HFILL }},
+
+ { &hf_dccp_trace_query, {
+ "Queries and Reports", "dccp.trace.query", FT_BOOLEAN, 32,
+ NULL, 0x00000010, "Queries and Reports", HFILL }},
+
+ { &hf_dccp_trace_ridc, {
+ "RID Cache Messages", "dccp.trace.ridc", FT_BOOLEAN, 32,
+ NULL, 0x00000020, "RID Cache Messages", HFILL }},
+
+ { &hf_dccp_trace_flood, {
+ "Input/Output Flooding", "dccp.trace.flood", FT_BOOLEAN, 32,
+ NULL, 0x00000040, "Input/Output Flooding", HFILL }},
+
+ { &hf_dccp_floodop, {
+ "Flood Control Operation", "dccp.floodop", FT_UINT32, BASE_DEC,
+ VALS(dccp_floodop_vals), 0, "Flood Control Operation", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_dccp,
+ &ett_dccp_op,
+ &ett_dccp_ck,
+ &ett_dccp_opnums,
+ &ett_dccp_trace,
+ };
+
+ proto_dccp = proto_register_protocol("Distributed Checksum Clearinghouse Protocol",
+ "DCCP", "dccp");
+
+ proto_register_field_array(proto_dccp, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dccp(void)
+{
+ heur_dissector_add("udp", dissect_dccp, proto_dccp);
+}
diff --git a/epan/dissectors/packet-dccp.h b/epan/dissectors/packet-dccp.h
new file mode 100644
index 0000000000..6142cae2e1
--- /dev/null
+++ b/epan/dissectors/packet-dccp.h
@@ -0,0 +1,415 @@
+/* packet-dcc.c
+ * Protocol defs for Distributed Checksum Clearinghouse Protocol
+ * DCC Home: http://www.rhyolite.com/anti-spam/dcc/
+ *
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+/* Inserted below is dcc_proto.h from the dcc source distribution, with the
+ following changes made:
+
+:%s/u_in*t16_t/guint16/g
+:%s/u_in*t32_t/guint32/g
+:%s/u_ch*ar/guchar/g
+:%s/in*t32_t/gint32/g
+
+This includes more than is really necessary, but easier to just include whole
+header.
+
+*/
+
+
+/* Distributed Checksum Clearinghouse protocol
+ *
+ * Copyright (c) 2002 by Rhyolite Software
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE
+ * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Rhyolite Software DCC 1.0.53-1.45 $Revision: 1.3 $
+ */
+
+#ifndef DCC_PROTO_H
+#define DCC_PROTO_H
+
+
+#define DCC_PORT 6277 /* default UDP port #, MAPS in DTMF */
+
+
+/* No client's retransmission can be delayed by more than this
+ * This matters for how long a DCC server must remember old requests
+ * to recognize retransmissions */
+#define DCC_MAX_DELAY_SEC 30
+
+typedef guint16 DCC_MS;
+
+/* anonymous client delay */
+#define DCC_MAX_QDELAY_MS (DCC_MAX_DELAY_SEC*1000)
+#define DCC_DEF_QDELAY_MS 0
+
+
+/* types of checksums */
+typedef enum {
+ DCC_CK_INVALID =0, /* deleted from database when seen */
+ DCC_CK_IP =1, /* MD5 of binary source IPv6 address */
+ DCC_CK_ENV_FROM =2, /* " " envelope Mail From value */
+ DCC_CK_FROM =3, /* " " header From: line */
+ DCC_CK_SUB =4, /* " " substitute header line */
+ DCC_CK_MESSAGE_ID=5, /* " " header Message-ID: line */
+ DCC_CK_RECEIVED =6, /* " " last header Received: line */
+ DCC_CK_BODY =7, /* " " body */
+ DCC_CK_FUZ1 =8, /* " " filtered body */
+ DCC_CK_FUZ2 =9, /* " " " " */
+ DCC_CK_FUZ3 =10, /* " " " " */
+ DCC_CK_FUZ4 =11, /* " " " " */
+ DCC_CK_SRVR_ID =12, /* hostname for server-ID check */
+ DCC_CK_ENV_TO =13 /* MD5 of envelope Rcpt To value */
+# define DCC_CK_FLOD_PATH DCC_CK_ENV_TO /* flooding path in server-IDs */
+} DCC_CK_TYPES;
+#define DCC_CK_TYPE_FIRST DCC_CK_IP
+#define DCC_CK_TYPE_LAST DCC_CK_ENV_TO
+#define DCC_NUM_CKS DCC_CK_TYPE_LAST /* # of valid types */
+
+/* DCC_DIM_CKS dimensions arrays of checksum types including DCC_CK_INVALID
+ * Beware that DCC_DIM_CKS is used in the database header. */
+#define DCC_DIM_CKS (DCC_CK_TYPE_LAST+1)
+
+/* Ensure that arrays of DCC_CKs contain an even number so that structures
+ * containing them will have no extra structure packing */
+#define DCC_COMP_DIM_CKS ((((DCC_NUM_CKS+1)+1)/2)*2) /* == DCC_DIM_CKS */
+
+/* keep in the database longer than others */
+#define DCC_CK_LONG_TERM(t) ((t) >= DCC_CK_FUZ1 && (t) <= DCC_CK_FUZ4)
+
+#define DCC_CK_IS_BODY(t) ((t) >= DCC_CK_BODY && (t) <= DCC_CK_FUZ4)
+
+/* ok for users to talk about */
+#define DCC_CK_OK_USER(t) ((t) > DCC_CK_INVALID && (t) <= DCC_CK_FUZ4)
+/* ok in the database */
+#define DCC_CK_OK_DB(t) ((t) > DCC_CK_INVALID && (t) <= DCC_CK_TYPE_LAST)
+#define DCC_CK_OK_PROTO(t) DCC_CK_OK_USER(t) /* ok from clients */
+#define DCC_CK_OK_FLOD(t) DCC_CK_OK_DB(t) /* ok in floods */
+
+typedef guchar DCC_CK_TYPE;
+
+
+typedef enum {
+ DCC_OP_INVALID=0,
+ DCC_OP_NOP, /* see if the server is alive */
+ DCC_OP_REPORT, /* client reporting and querying */
+ DCC_OP_QUERY, /* client querying */
+ DCC_OP_QUERY_RESP, /* server responding */
+ DCC_OP_ADMN, /* local control of the server */
+ DCC_OP_OK, /* administrative operation ok */
+ DCC_OP_ERROR, /* server failing or complaining */
+ DCC_OP_DELETE /* delete some checksums */
+} DCC_OPS;
+
+typedef guint32 DCC_CLNT_ID;
+#define DCC_ID_INVALID 0
+#define DCC_ID_ANON 1 /* anonymous (non-paying) client */
+#define DCC_ID_WHITE 2 /* white-listed */
+#define DCC_ID_COMP 3 /* compressed */
+#define DCC_SRVR_ID_MIN 100 /* below reserved for special uses */
+#define DCC_SRVR_ID_MAX 32767 /* below are servers--must be 2**n-1 */
+#define DCC_CLNT_ID_MIN (DCC_SRVR_ID_MAX+1)
+#define DCC_CLNT_ID_MAX 16777215
+typedef guint16 DCC_SRVR_ID;
+#define DCC_SRVR_ID_AUTH (DCC_SRVR_ID_MAX+1) /* client was authenticated */
+
+/* client's identification of its transaction */
+typedef struct {
+ guint32 h; /* client host ID, e.g. IP address */
+ guint32 p; /* process ID, serial #, timestamp */
+ guint32 r; /* report ID */
+ guint32 t; /* client (re)transmission # */
+} DCC_OP_NUMS;
+
+/* The inter-DCC server flooding algorithm depends on unique-per-server
+ * timestamps to detect duplicates. That imposes a requirement on
+ * timestamps that they have resolution enough to separate reports
+ * from clients arriving at any single server.
+ * The timestamps are 48 bits consisting of 17 bits of 8's of microseconds
+ * and 31 bits of seconds. That's sufficient for the UNIX epoch.
+ * If the DCC is still around in the 2030's (and in the unlikely case that
+ * 8 microseconds are still fine enough), we can make the 31 bits be
+ * an offset in a bigger window.
+ */
+#define DCC_TS_USEC_RSHIFT 3
+#define DCC_TS_USEC_MULT (1<<DCC_TS_USEC_RSHIFT)
+#define DCC_TS_SEC_LSHIFT 17
+#define DCC_TS_USEC_MASK ((1<<DCC_TS_SEC_LSHIFT) - 1)
+typedef guchar DCC_TS[6];
+
+/* The start of any DCC packet.
+ * The length and version are early, since they are they only fields
+ * that are constrained in future versions. */
+typedef struct {
+ guint16 len; /* total DCC packet length (for TCP) */
+ guchar pkt_vers; /* packet protocol version */
+# define DCC_PKT_VERSION 4
+# define DCC_PKT_VERSION_MIN DCC_PKT_VERSION
+# define DCC_PKT_VERSION_MAX DCC_PKT_VERSION
+ guchar op; /* one of DCC_OPS */
+ /* Identify the transaction.
+ * Each client can have many hosts, each host can be multi-homed,
+ * and each host can be running many processes talking to the
+ * server. Each packet needs to be uniquely numbered, so that the
+ * server can recognize as interchangable all of the (re)transmissions
+ * of a single report (rid) from a client process (pid) on a single
+ * host (hid), and the client can know which transmission (tid)
+ * produced a given server response to maintain the client's RTT
+ * value for the server. */
+ DCC_CLNT_ID sender; /* official DCC client-ID */
+ DCC_OP_NUMS op_nums; /* op_num.t must be last */
+} DCC_HDR;
+
+typedef guchar DCC_SIGNATURE[16];
+
+typedef struct {
+ DCC_HDR hdr;
+ DCC_SIGNATURE signature;
+} DCC_NOP;
+
+
+/* administrative requests from localhost
+ * These can be freely changed, because the administrative tools
+ * should match the daemon. */
+typedef enum {
+ DCC_AOP_OK=-1, /* never really sent */
+ DCC_AOP_STOP=1, /* stop gracefully */
+ DCC_AOP_NEW_IDS, /* load keys and client-IDs */
+ DCC_AOP_FLOD, /* start or stop flooding */
+ DCC_AOP_DB_UNLOCK, /* start switch to new database */
+ DCC_AOP_DB_NEW, /* finish switch to new database */
+ DCC_AOP_STATS, /* return counters--val=buffer size */
+ DCC_AOP_STATS_CLEAR, /* return and zero counters */
+ DCC_AOP_TRACE_ON,
+ DCC_AOP_TRACE_OFF,
+ DCC_AOP_CUR_CLIENTS /* some client IP addresses */
+} DCC_AOPS;
+
+/* for DCC_AOP_FLOD */
+typedef enum {
+ DCC_AOP_FLOD_CHECK=0,
+ DCC_AOP_FLOD_SHUTDOWN,
+ DCC_AOP_FLOD_HALT,
+ DCC_AOP_FLOD_RESUME,
+ DCC_AOP_FLOD_REWIND,
+ DCC_AOP_FLOD_LIST,
+ DCC_AOP_FLOD_STATS,
+ DCC_AOP_FLOD_STATS_CLEAR
+} DCC_AOP_FLODS;
+
+typedef struct { /* with operation DCC_OP_ADMN */
+ DCC_HDR hdr;
+ gint32 date; /* seconds since epoch on caller */
+ guint32 val; /* request type, buffer size, etc. */
+ guchar aop; /* one of DCC_AOPS */
+ guchar pad[3];
+ DCC_SIGNATURE signature;
+} DCC_ADMN_REQ;
+
+/* noisy response to some DCC_AOPS with operation DCC_OP_ADMN */
+typedef struct {
+ guchar addr[16];
+ DCC_CLNT_ID id;
+ guint32 last_used;
+ guint32 requests;
+} DCC_ADMN_RESP_CLIENTS;
+typedef union {
+ char string[80*22];
+ DCC_ADMN_RESP_CLIENTS clients[1];
+} DCC_ADMN_RESP_VAL;
+typedef struct {
+ DCC_HDR hdr;
+ DCC_ADMN_RESP_VAL val;
+ DCC_SIGNATURE signature;
+} DCC_ADMN_RESP;
+
+
+#define DCC_TRACE_ADMN_BIT 0x0001 /* administrative requests */
+#define DCC_TRACE_ANON_BIT 0x0002 /* anonymous client errors */
+#define DCC_TRACE_CLNT_BIT 0x0004 /* authenticated client errors */
+#define DCC_TRACE_RLIM_BIT 0x0008 /* rate limited messages */
+#define DCC_TRACE_QUERY_BIT 0x0010 /* all queries and reports */
+#define DCC_TRACE_RIDC_BIT 0x0020 /* RID cache messages */
+#define DCC_TRACE_FLOD_BIT 0x0040 /* input and output flooding */
+/* INFO must always be on */
+#define DCC_TRACE_ALL_BITS (DCC_TRACE_ADMN_BIT | DCC_TRACE_ANON_BIT \
+ | DCC_TRACE_CLNT_BIT | DCC_TRACE_RLIM_BIT \
+ | DCC_TRACE_QUERY_BIT | DCC_TRACE_RIDC_BIT \
+ | DCC_TRACE_FLOD_BIT)
+
+
+typedef char DCC_BRAND[64];
+
+/* administrative or NOP ok */
+typedef struct {
+ DCC_HDR hdr;
+ guchar max_pkt_vers; /* can handle this version */
+ guchar unused;
+ DCC_MS qdelay_ms;
+ DCC_BRAND brand; /* identity or brandname of sender */
+ DCC_SIGNATURE signature;
+} DCC_OK;
+
+
+/* a reported checksum from a client */
+typedef guchar DCC_SUM[16]; /* for now all have 16 bytes */
+typedef struct {
+ DCC_CK_TYPE type;
+ guchar len; /* total length of this checksum */
+ DCC_SUM sum;
+} DCC_CK;
+
+typedef guint32 DCC_TGTS; /* database is limited to 24 bits */
+#define DCC_TGTS_TOO_MANY 0x00fffff0 /* >= 16777200 targets */
+#define DCC_TGTS_OK 0x00fffff1 /* certified not spam */
+#define DCC_TGTS_OK2 0x00fffff2 /* half certified not spam */
+#define DCC_TGTS_DEL 0x00fffff3 /* a deleted checksum */
+#define DCC_TGTS_INVALID 0x01000000
+
+/* query or query/report packet from client to server */
+typedef struct {
+ DCC_HDR hdr;
+ DCC_TGTS tgts; /* # of addressees */
+# define DCC_QUERY_MAX DCC_DIM_CKS
+ DCC_CK cks[DCC_QUERY_MAX]; /* even to prevent structure padding */
+ DCC_SIGNATURE signature;
+} DCC_QUERY_REPORT;
+
+
+typedef struct {
+ DCC_TGTS tgts[DCC_QUERY_MAX]; /* individual answers */
+} DCC_QUERY_RESP_BODY;
+
+/* response to a query or query/report */
+typedef struct {
+ DCC_HDR hdr;
+ DCC_QUERY_RESP_BODY body;
+ DCC_SIGNATURE signature;
+} DCC_QUERY_RESP;
+
+
+/* DCC_OP_DELETE request to delete checksums */
+typedef struct {
+ DCC_HDR hdr;
+ gint32 date; /* seconds since epoch on caller */
+ DCC_CK ck;
+ guchar pad[2]; /* structure padding */
+ DCC_SIGNATURE signature;
+} DCC_DELETE;
+
+
+/* error response from server to client */
+typedef struct {
+ DCC_HDR hdr;
+# define DCC_ERROR_MSG_LEN 128
+ char msg[DCC_ERROR_MSG_LEN];
+ DCC_SIGNATURE signature;
+} DCC_ERROR;
+
+
+/* sender's position or serial number
+ * Only the sender understands sender positions except for these
+ * special values. However, the special values imply that the position
+ * must be big endian. */
+typedef guchar DCC_FLOD_POS[8];
+/* special cases sent by the receiver back to the sender */
+#define DCC_FLOD_POS_END 0 /* receiver closing with message */
+#define DCC_FLOD_POS_END_REQ 1 /* receiver wants to stop */
+#define DCC_FLOD_POS_NOTE 2 /* receiver has a tracing message */
+#define DCC_FLOD_POS_COMPLAINT 3 /* receiver has a problem message */
+#define DCC_FLOD_POS_REWIND 4 /* receiver's database emptied */
+#define DCC_FLOD_POS_MIN 10
+
+#define DCC_FLOD_OK_STR "DCC flod ok: "
+#define DCC_FLOD_MAX_RESP 200
+
+/* report forwarded among servers */
+typedef struct {
+ DCC_FLOD_POS pos;
+ guchar tgts[sizeof(DCC_TGTS)];
+ guchar srvr_id_auth[sizeof(DCC_SRVR_ID)]; /* receiving server */
+ DCC_TS ts; /* date reported */
+ guchar num_cks;
+ DCC_CK cks[DCC_QUERY_MAX];
+} DCC_FLOD;
+
+/* record of path taken by a report */
+#define DCC_NUM_FLOD_PATH ((int)(sizeof(DCC_SUM)/sizeof(DCC_SRVR_ID)))
+typedef struct {
+ guchar hi, lo;
+} DCC_FLOD_PATH_ID;
+
+typedef struct {
+ DCC_FLOD_POS z;
+ char msg[DCC_FLOD_MAX_RESP];
+ char null;
+} FLOD_END;
+typedef struct {
+ DCC_FLOD_POS op;
+ guchar len;
+ char str[DCC_FLOD_MAX_RESP];
+} FLOD_NOTE;
+#define FLOD_NOTE_OVHD ((int)sizeof(FLOD_NOTE)-DCC_FLOD_MAX_RESP)
+
+#define DCC_FLOD_VERSION_STR_BASE "DCC flod version "
+#define DCC_FLOD_VERSION5_STR DCC_FLOD_VERSION_STR_BASE"5"
+#define DCC_FLOD_VERSION5 5
+#define DCC_FLOD_VERSION6_STR DCC_FLOD_VERSION_STR_BASE"6"
+#define DCC_FLOD_VERSION6 6
+#define DCC_FLOD_VERSION7_STR DCC_FLOD_VERSION_STR_BASE"7"
+#define DCC_FLOD_VERSION7 7
+#define DCC_FLOD_VERSION_DEF 0
+#define DCC_FLOD_VERSION_CUR_STR DCC_FLOD_VERSION7_STR
+#define DCC_FLOD_VERSION_CUR DCC_FLOD_VERSION7
+typedef struct {
+# define DCC_FLOD_VERSION_STR_LEN 64
+ char str[DCC_FLOD_VERSION_STR_LEN];
+ DCC_SRVR_ID sender_srvr_id;
+ guchar turn;
+ guchar unused[3];
+} DCC_FLOD_VERSION_BODY;
+typedef struct {
+ DCC_FLOD_VERSION_BODY body;
+ char pad[256-sizeof(DCC_FLOD_VERSION_BODY)-sizeof(DCC_SIGNATURE)];
+ DCC_SIGNATURE signature;
+} DCC_FLOD_VERSION_HDR;
+
+
+#endif /* DCC_PROTO_H */
diff --git a/epan/dissectors/packet-dcerpc-afs4int.c b/epan/dissectors/packet-dcerpc-afs4int.c
new file mode 100644
index 0000000000..eae7f2a8b1
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-afs4int.c
@@ -0,0 +1,4658 @@
+/* packet-dcerpc-afs4int.c
+ *
+ * Routines for dcerpc Afs4Int dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz file/fsint/afs4int.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * test
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dce122.h"
+
+#define AFS_SETMODTIME 1
+#define AFS_SETOWNER 2
+#define AFS_SETGROUP 4
+#define AFS_SETMODE 8
+#define AFS_SETACCESSTIME 0x10
+#define AFS_SETCHANGETIME 0x20
+#define AFS_SETLENGTH 0x40
+#define AFS_SETTYPEUUID 0x80
+#define AFS_SETDEVNUM 0x100
+#define AFS_SETMODEXACT 0x200
+#define AFS_SETTRUNCLENGTH 0x400
+#define AFS_SETCLIENTSPARE 0x800
+
+#define TKN_LOCK_READ 0x001
+#define TKN_LOCK_WRITE 0x002
+#define TKN_DATA_READ 0x004
+#define TKN_DATA_WRITE 0x008
+#define TKN_OPEN_READ 0x010
+#define TKN_OPEN_WRITE 0x020
+#define TKN_OPEN_SHARED 0x040
+#define TKN_OPEN_EXCLUSIVE 0x080
+#define TKN_OPEN_DELETE 0x100
+#define TKN_OPEN_PRESERVE 0x200
+#define TKN_STATUS_READ 0x400
+#define TKN_STATUS_WRITE 0x800
+#define TKN_OPEN_UNLINK 0x1000
+#define TKN_SPOT_HERE 0x2000
+#define TKN_SPOT_THERE 0x4000
+#define TKN_OPEN_NO_READ 0x8000
+#define TKN_OPEN_NO_WRITE 0x10000
+#define TKN_OPEN_NO_UNLINK 0x20000
+
+#define AFS_CONN_PARAM_HOSTLIFE 0
+#define AFS_CONN_PARAM_HOSTRPC 1
+#define AFS_CONN_PARAM_DEADSERVER 2
+#define AFS_CONN_PARAM_EPOCH 3
+#define AFS_CONN_PARAM_MAXFILE_CLIENT 4
+#define AFS_CONN_PARAM_MAXFILE_SERVER 5
+#define AFS_CONN_PARAM_HOST_TYPE_CLIENT 6
+#define AFS_CONN_PARAM_HOST_TYPE_SERVER 7
+#define AFS_CONN_PARAM_FT_MASK_CLIENT 8
+#define AFS_CONN_PARAM_FT_MASK_SERVER 9
+#define AFS_CONN_PARAM_SUPPORTS_64BITS 0x10000
+#define AFS_CONN_PARAM_512BYTE_BLOCKS 0x20000
+
+#define AFS_FLAG_SEC_SERVICE 0x1
+#define AFS_FLAG_CONTEXT_NEW_IF 0x2
+#define AFS_FLAG_CONTEXT_DO_RESET 0x4
+#define AFS_FLAG_CONTEXT_NEW_ACL_IF 0x8
+#define AFS_FLAG_CONTEXT_NEW_TKN_TYPES 0x10
+
+#define AFS_FLAG_RETURNTOKEN 1
+#define AFS_FLAG_TOKENJUMPQUEUE 2
+#define AFS_FLAG_SKIPTOKEN 4
+#define AFS_FLAG_NOOPTIMISM 0x8
+#define AFS_FLAG_TOKENID 0x10
+#define AFS_FLAG_RETURNBLOCKER 0x20
+#define AFS_FLAG_ASYNCGRANT 0x40
+#define AFS_FLAG_NOREVOKE 0x80
+#define AFS_FLAG_MOVE_REESTABLISH 0x100
+#define AFS_FLAG_SERVER_REESTABLISH 0x200
+#define AFS_FLAG_NO_NEW_EPOCH 0x400
+#define AFS_FLAG_MOVE_SOURCE_OK 0x800
+#define AFS_FLAG_SYNC 0x1000
+#define AFS_FLAG_ZERO 0x2000
+#define AFS_FLAG_SKIPSTATUS 0x4000
+#define AFS_FLAG_FORCEREVOCATIONS 0x8000
+#define AFS_FLAG_FORCEVOLQUIESCE 0x10000
+#define AFS_FLAG_FORCEREVOCATIONDOWN 0x20000
+
+static int hf_afs4int_opnum = -1;
+
+
+static int hf_afs4int_afsFid_cell_high = -1;
+static int hf_afs4int_afsuuid_uuid = -1;
+static int hf_afs4int_fetchdata_pipe_t_size = -1;
+static int hf_afs4int_afsNameString_t_principalName_string = -1;
+static int hf_afs4int_afsFid_cell_low = -1;
+static int hf_afs4int_afsFid_volume_high = -1;
+static int hf_afs4int_afsFid_volume_low = -1;
+static int hf_afs4int_afsFid_Vnode = -1;
+static int hf_afs4int_afsFid_Unique = -1;
+static int hf_afs4int_volume_high = -1;
+static int hf_afs4int_volume_low = -1;
+static int hf_afs4int_vnode = -1;
+static int hf_afs4int_unique = -1;
+static int hf_afs4int_interfaceversion = -1;
+static int hf_afs4int_filetype = -1;
+static int hf_afs4int_linkcount = -1;
+static int hf_afs4int_length_high = -1;
+static int hf_afs4int_length_low = -1;
+static int hf_afs4int_dataversion_high = -1;
+static int hf_afs4int_dataversion_low = -1;
+static int hf_afs4int_author = -1;
+static int hf_afs4int_owner = -1;
+static int hf_afs4int_group = -1;
+static int hf_afs4int_calleraccess = -1;
+static int hf_afs4int_anonymousaccess = -1;
+static int hf_afs4int_aclexpirationtime = -1;
+static int hf_afs4int_mode = -1;
+static int hf_afs4int_parentvnode = -1;
+static int hf_afs4int_parentunique = -1;
+static int hf_afs4int_modtime_sec = -1;
+static int hf_afs4int_modtime_msec = -1;
+static int hf_afs4int_changetime_sec = -1;
+static int hf_afs4int_changetime_msec = -1;
+static int hf_afs4int_accesstime_sec = -1;
+static int hf_afs4int_accesstime_msec = -1;
+static int hf_afs4int_servermodtime_sec = -1;
+static int hf_afs4int_servermodtime_msec = -1;
+static int hf_afs4int_typeuuid = -1;
+static int hf_afs4int_objectuuid = -1;
+static int hf_afs4int_devicenumber = -1;
+static int hf_afs4int_blocksused = -1;
+static int hf_afs4int_clientspare1 = -1;
+static int hf_afs4int_devicenumberhighbits = -1;
+static int hf_afs4int_agtypeunique = -1;
+static int hf_afs4int_himaxspare = -1;
+static int hf_afs4int_lomaxspare = -1;
+static int hf_afs4int_pathconfspare = -1;
+static int hf_afs4int_spare4 = -1;
+static int hf_afs4int_spare5 = -1;
+static int hf_afs4int_spare6 = -1;
+static int hf_afs4int_volid_hi = -1;
+static int hf_afs4int_volid_low = -1;
+static int hf_afs4int_vvage = -1;
+static int hf_afs4int_vv_hi = -1;
+static int hf_afs4int_vv_low = -1;
+static int hf_afs4int_vvpingage = -1;
+static int hf_afs4int_vvspare1 = -1;
+static int hf_afs4int_vvspare2 = -1;
+static int hf_afs4int_beginrange = -1;
+static int hf_afs4int_beginrangeext = -1;
+static int hf_afs4int_endrange = -1;
+static int hf_afs4int_endrangeext = -1;
+static int hf_afs4int_expirationtime = -1;
+static int hf_afs4int_tokenid_hi = -1;
+static int hf_afs4int_tokenid_low = -1;
+static int hf_afs4int_type_hi = -1;
+static int hf_afs4int_type_low = -1;
+static int hf_afs4int_tn_length = -1;
+static int hf_afs4int_storestatus_accesstime_sec = -1;
+static int hf_afs4int_storestatus_accesstime_usec = -1;
+static int hf_afs4int_storestatus_changetime_sec = -1;
+static int hf_afs4int_storestatus_changetime_usec = -1;
+static int hf_afs4int_storestatus_clientspare1 = -1;
+static int hf_afs4int_storestatus_cmask = -1;
+static int hf_afs4int_storestatus_devicenumber = -1;
+static int hf_afs4int_storestatus_devicenumberhighbits = -1;
+static int hf_afs4int_storestatus_devicetype = -1;
+static int hf_afs4int_storestatus_group = -1;
+static int hf_afs4int_storestatus_length_high = -1;
+static int hf_afs4int_storestatus_length_low = -1;
+static int hf_afs4int_storestatus_mask = -1;
+static int hf_afs4int_storestatus_mode = -1;
+static int hf_afs4int_storestatus_modtime_sec = -1;
+static int hf_afs4int_storestatus_modtime_usec = -1;
+static int hf_afs4int_storestatus_owner = -1;
+static int hf_afs4int_storestatus_spare1 = -1;
+static int hf_afs4int_storestatus_spare2 = -1;
+static int hf_afs4int_storestatus_spare3 = -1;
+static int hf_afs4int_storestatus_spare4 = -1;
+static int hf_afs4int_storestatus_spare5 = -1;
+static int hf_afs4int_storestatus_spare6 = -1;
+static int hf_afs4int_storestatus_trunc_high = -1;
+static int hf_afsconnparams_mask = -1;
+static int hf_afs4int_storestatus_trunc_low = -1;
+static int hf_afs4int_storestatus_typeuuid = -1;
+static int hf_afs4int_l_end_pos = -1;
+static int hf_afs4int_l_end_pos_ext = -1;
+static int hf_afs4int_l_fstype = -1;
+static int hf_afs4int_l_pid = -1;
+static int hf_afs4int_l_start_pos = -1;
+static int hf_afs4int_l_start_pos_ext = -1;
+static int hf_afs4int_l_sysid = -1;
+static int hf_afs4int_l_type = -1;
+static int hf_afs4int_l_whence = -1;
+static int hf_afs4int_acl_len = -1;
+static int hf_afs4int_st = -1;
+static int hf_afs4int_uint = -1;
+static int hf_afs4int_setcontext_rqst_epochtime = -1;
+static int hf_afs4int_setcontext_rqst_secobjectid = -1;
+static int hf_afs4int_setcontext_rqst_clientsizesattrs = -1;
+static int hf_afs4int_setcontext_rqst_parm7 = -1;
+static int hf_afs4int_afsNetAddr_type = -1;
+static int hf_afs4int_afsNetAddr_data = -1;
+static int hf_afs4int_returntokenidp_high = -1;
+static int hf_afs4int_minvvp_low = -1;
+static int hf_afs4int_position_high = -1;
+static int hf_afs4int_position_low = -1;
+static int hf_afs4int_offsetp_high = -1;
+static int hf_afs4int_nextoffsetp_low = -1;
+static int hf_afs4int_cellidp_high = -1;
+static int hf_afserrorstatus_st = -1;
+static int hf_afs4int_length = -1;
+static int hf_afsconnparams_values = -1;
+static int hf_afs4int_acltype = -1;
+static int hf_afs4int_afsTaggedPath_tp_chars = -1;
+static int hf_afs4int_afsTaggedPath_tp_tag = -1;
+static int hf_afs4int_afsacl_uuid1 = -1;
+static int hf_afs4int_bulkfetchstatus_size = -1;
+static int hf_afs4int_flags = -1;
+static int hf_afs4int_afsreturndesc_tokenid_high = -1;
+static int hf_afs4int_afsreturndesc_tokenid_low = -1;
+static int hf_afs4int_afsreturndesc_type_high = -1;
+static int hf_afs4int_afsreturndesc_type_low = -1;
+static int hf_afs4int_returntokenidp_low = -1;
+static int hf_afs4int_minvvp_high = -1;
+static int hf_afs4int_offsetp_low = -1;
+static int hf_afs4int_nextoffsetp_high = -1;
+static int hf_afs4int_cellidp_low = -1;
+static int hf_afs4int_tn_tag = -1;
+static int hf_afs4int_tn_size = -1;
+static int hf_afs4int_tn_string = -1;
+static int hf_afs4int_bulkfetchvv_numvols = -1;
+static int hf_afs4int_bulkfetchvv_spare1 = -1;
+static int hf_afs4int_bulkfetchvv_spare2 = -1;
+static int hf_afs4int_bulkkeepalive_numexecfids = -1;
+static int hf_afs4int_bulkkeepalive_spare4 = -1;
+static int hf_afs4int_bulkkeepalive_spare2 = -1;
+static int hf_afs4int_bulkkeepalive_spare1 = -1;
+static int hf_afs4int_afsacl_defaultcell_uuid = -1;
+static int hf_afs4int_gettime_syncdispersion = -1;
+static int hf_afs4int_gettime_syncdistance = -1;
+static int hf_afs4int_gettime_usecondsp = -1;
+static int hf_afs4int_readdir_size = -1;
+static int hf_afs4int_afsNameString_t_principalName_size = -1;
+static int hf_afs4int_afsNameString_t_principalName_size2 = -1;
+static int hf_afs4int_afsTaggedPath_tp_length = -1;
+static int hf_afs4int_fstype = -1;
+static int hf_afs4int_gettime_secondsp = -1;
+
+static int proto_afs4int = -1;
+
+static gint ett_afs4int = -1;
+static gint ett_afs4int_afsFid = -1;
+static gint ett_afs4int_afsReturnDesc = -1;
+static gint ett_afs4int_afsNetAddr = -1;
+static gint ett_afs4int_fetchstatus = -1;
+static gint ett_afs4int_afsflags = -1;
+static gint ett_afs4int_volsync = -1;
+static gint ett_afs4int_minvvp = -1;
+static gint ett_afs4int_afsfidtaggedname = -1;
+static gint ett_afs4int_afstaggedname = -1;
+static gint ett_afs4int_afstoken = -1;
+static gint ett_afs4int_afsstorestatus = -1;
+static gint ett_afs4int_afsRecordLock = -1;
+static gint ett_afs4int_afsAcl = -1;
+static gint ett_afs4int_afsNameString_t = -1;
+static gint ett_afs4int_afsConnParams = -1;
+static gint ett_afs4int_afsErrorStatus = -1;
+static gint ett_afs4int_afsNetData = -1;
+static gint ett_afs4int_afsTaggedPath = -1;
+static gint ett_afs4int_afsBulkStat = -1;
+static gint ett_afs4int_afsuuid = -1;
+static gint ett_afs4int_offsetp = -1;
+static gint ett_afs4int_returntokenidp = -1;
+static gint ett_afs4int_afsbundled_stat = -1;
+
+
+/* vars for our macro(s) */
+static int hf_error_st = -1;
+static guint32 st;
+static char *st_str;
+
+
+static e_uuid_t uuid_afs4int =
+ { 0x4d37f2dd, 0xed93, 0x0000, {0x02, 0xc0, 0x37, 0xcf, 0x1e, 0x00, 0x00,
+ 0x00}
+};
+static guint16 ver_afs4int = 4;
+
+/* XXX the only macro that I could not find the right way to convert easily.
+The reason is because we reset col_info if st is non zero for many rpcs.
+This is because on error, many structures are filled with garbage.
+We end up not knowing if data is valid until we get the st var at the very end of the stubdata..
+We can not just jump to the end, because more often than not an extra buffer exists in payload
+after st. Thus we have to advance on each item until we read in ST, then we clear col_info. on error
+A good example is FetchStatus() on a file that returns ENOEXIST.
+inode, volume, etc all will be garbage.
+*/
+
+#define MACRO_ST_CLEAR(name) \
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_error_st, &st); \
+ st_str = val_to_str (st, dce_error_vals, "%u"); \
+ if (st){ \
+if (check_col (pinfo->cinfo, COL_INFO)) \
+ col_add_fstr (pinfo->cinfo, COL_INFO, "%s st:%s ", name, st_str); \
+ }else{ \
+if (check_col (pinfo->cinfo, COL_INFO)) \
+ col_append_fstr (pinfo->cinfo, COL_INFO, " st:%s ", st_str); \
+}
+
+static int
+dissect_afsFid (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+
+/*
+ afsHyper Cell;
+ afsHyper Volume;
+ unsigned32 Vnode;
+ unsigned32 Unique;
+*/
+
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 volume_low, unique, vnode, inode;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "afsFid:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsFid);
+ }
+
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsFid_cell_high, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsFid_cell_low, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsFid_volume_high, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsFid_volume_low, &volume_low);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsFid_Vnode, &vnode);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsFid_Unique, &unique);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " :FSID:%u ", volume_low);
+
+ if ((vnode == 1) || (vnode == 2))
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, " InFS ");
+ }
+ else
+ {
+ inode = ((volume_low << 16) + vnode) & 0x7fffffff;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " inode:%u ", inode);
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_afsConnParams (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+
+/*
+ unsigned32 Mask;
+ unsigned32 Values[20];
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 mask, Values[20];
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsConnParams_t:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsConnParams);
+ }
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_mask, &mask);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[0]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[1]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[2]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[3]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[4]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[5]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[6]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[7]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[9]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[9]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[10]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[11]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[12]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[13]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[14]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[15]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[16]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[17]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[18]);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afsconnparams_values, &Values[19]);
+ if ((mask & AFS_CONN_PARAM_HOSTLIFE) == AFS_CONN_PARAM_HOSTLIFE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":HOSTLIFE");
+ }
+ if ((mask & AFS_CONN_PARAM_HOSTRPC) == AFS_CONN_PARAM_HOSTRPC)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":HOSTRPC");
+ }
+ if ((mask & AFS_CONN_PARAM_DEADSERVER) == AFS_CONN_PARAM_DEADSERVER)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":DEADSERVER");
+ }
+ if ((mask & AFS_CONN_PARAM_EPOCH) == AFS_CONN_PARAM_EPOCH)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":EPOCH");
+ }
+ if ((mask & AFS_CONN_PARAM_MAXFILE_CLIENT) == AFS_CONN_PARAM_MAXFILE_CLIENT)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":MAXFILE_CLIENT");
+ }
+ if ((mask & AFS_CONN_PARAM_MAXFILE_SERVER) == AFS_CONN_PARAM_MAXFILE_SERVER)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":MAXFILE_SERVER");
+ }
+ if ((mask & AFS_CONN_PARAM_HOST_TYPE_CLIENT) ==
+ AFS_CONN_PARAM_HOST_TYPE_CLIENT)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":HOST_TYPE_CLIENT");
+ }
+ if ((mask & AFS_CONN_PARAM_HOST_TYPE_SERVER) ==
+ AFS_CONN_PARAM_HOST_TYPE_SERVER)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":HOST_TYPE_SERVER");
+ }
+ if ((mask & AFS_CONN_PARAM_FT_MASK_CLIENT) == AFS_CONN_PARAM_FT_MASK_CLIENT)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":FT_MASK_CLIENT");
+ }
+ if ((mask & AFS_CONN_PARAM_FT_MASK_SERVER) == AFS_CONN_PARAM_FT_MASK_SERVER)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":FT_MASK_SERVER");
+ }
+ if ((mask & AFS_CONN_PARAM_SUPPORTS_64BITS) ==
+ AFS_CONN_PARAM_SUPPORTS_64BITS)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SUPPORTS_64BITS");
+ }
+ if ((mask & AFS_CONN_PARAM_512BYTE_BLOCKS) == AFS_CONN_PARAM_512BYTE_BLOCKS)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":512BYTE_BLOCKS");
+ }
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " Values:%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u",
+ Values[0], Values[1], Values[2], Values[3],
+ Values[4], Values[5], Values[6], Values[7], Values[8],
+ Values[9], Values[10], Values[11], Values[12],
+ Values[13], Values[14], Values[15], Values[16],
+ Values[17], Values[18], Values[19]);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_afsNameString_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+
+/*
+typedef [string] byte NameString_t[AFS_NAMEMAX];
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+#define AFS_NAMEMAX 256
+ guint32 string_size;
+ const guint8 *namestring;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsNameString_t:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsNameString_t);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsNameString_t_principalName_size,
+ &string_size);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " String_size:%u", string_size);
+ if (string_size < AFS_NAMEMAX)
+ {
+/* proto_tree_add_string(tree, id, tvb, start, length, value_ptr); */
+
+ proto_tree_add_string (tree, hf_afs4int_afsNameString_t_principalName_string, tvb, offset, string_size, tvb_get_ptr (tvb, offset, string_size));
+ namestring = tvb_get_ptr (tvb, offset, string_size);
+ offset += string_size;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Principal:%s", namestring);
+ }
+ else
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " :FIXME!: Invalid string length of %u",
+ string_size);
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_afsNetAddr (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+
+/* unsigned16 type;
+ unsigned8 data[14];
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint16 type;
+ guint8 data;
+ int i;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsNetAddr:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsNetAddr);
+ }
+
+
+ offset =
+ dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsNetAddr_type, &type);
+
+ if (type)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Type:%u ", type);
+
+
+ for (i = 0; i < 14; i++)
+ {
+
+ offset =
+ dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsNetAddr_data, &data);
+
+
+ switch (i)
+ {
+ case 1:
+ if (data)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Port:%u",
+ data);
+ }
+ break;
+ case 2:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " IP:%u.", data);
+ break;
+ case 3:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "%u.", data);
+ break;
+ case 4:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "%u.", data);
+ break;
+ case 5:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "%u", data);
+ break;
+ }
+
+ }
+
+ }
+ else
+ {
+
+ offset += 14; /* space left after reading in type for the array. */
+ }
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_afsNetData (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+/*
+ afsNetAddr sockAddr;
+ NameString_t principalName;
+*/
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1, "afsNetData:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsNetData);
+ }
+
+
+ offset = dissect_afsNetAddr ( tvb, offset, pinfo, tree, drep);
+ offset += 4; /* buffer */
+ offset = dissect_afsNameString_t ( tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+
+}
+
+static int
+dissect_afsTaggedPath (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+
+/*
+ codesetTag tp_tag;
+ unsigned16 tp_length;
+ byte tp_chars[AFS_PATHMAX+1]; 1024+1
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 tp_tag;
+ guint16 tp_length;
+ const guint8 *tp_chars;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1, "afsTaggedPath");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsTaggedPath);
+ }
+
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsTaggedPath_tp_tag, &tp_tag);
+ offset =
+ dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsTaggedPath_tp_length, &tp_length);
+ proto_tree_add_string (tree, hf_afs4int_afsTaggedPath_tp_chars, tvb, offset,
+ hf_afs4int_afsTaggedPath_tp_length, tvb_get_ptr (tvb,
+ offset,
+ tp_length));
+ tp_chars = tvb_get_ptr (tvb, offset, 1025);
+ offset += 1025;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " :tp_chars %s", tp_chars);
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_afsAcl (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+/*
+ unsigned32 afsACL_len;
+ [length_is(afsACL_len)] byte afsACL_val[AFS_ACLMAX];
+*/
+
+
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 acl_len;
+ e_uuid_t uuid1, defaultcell;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "afsAcl");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsAcl);
+ }
+
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_acl_len,
+ &acl_len);
+ offset += 8; /* bypass spare and duplicate acl_len */
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsacl_uuid1, &uuid1);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " - %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid1.Data1, uuid1.Data2, uuid1.Data3, uuid1.Data4[0],
+ uuid1.Data4[1], uuid1.Data4[2], uuid1.Data4[3],
+ uuid1.Data4[4], uuid1.Data4[5], uuid1.Data4[6],
+ uuid1.Data4[7]);
+
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsacl_defaultcell_uuid, &defaultcell);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ defaultcell.Data1, defaultcell.Data2, defaultcell.Data3,
+ defaultcell.Data4[0], defaultcell.Data4[1],
+ defaultcell.Data4[2], defaultcell.Data4[3],
+ defaultcell.Data4[4], defaultcell.Data4[5],
+ defaultcell.Data4[6], defaultcell.Data4[7]);
+
+ offset += (acl_len - 38);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+dissect_afsErrorStatus (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 st;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsErrorStatus");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsErrorStatus);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afserrorstatus_st,
+ &st);
+ st_str = val_to_str (st, dce_error_vals, "%u");
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " st:%s ", st_str);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_afsRecordLock (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+/*
+ signed16 l_type;
+ signed16 l_whence;
+ unsigned32 l_start_pos;
+ unsigned32 l_end_pos;
+ unsigned32 l_pid;
+ unsigned32 l_sysid;
+ unsigned32 l_fstype;
+ unsigned32 l_start_pos_ext; was l_spare0: high 32b of l_start_pos
+ unsigned32 l_end_pos_ext; was l_spare1: high 32b of l_end_pos
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint16 l_type, l_whence;
+ guint32 l_start_pos, l_end_pos, l_pid, l_sysid, l_fstype, l_start_pos_ext,
+ l_end_pos_ext;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsRecordLock:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsRecordLock);
+ }
+
+ offset =
+ dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep, hf_afs4int_l_type,
+ &l_type);
+ offset =
+ dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep, hf_afs4int_l_whence,
+ &l_whence);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_l_start_pos, &l_start_pos);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_l_end_pos,
+ &l_end_pos);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_l_pid,
+ &l_pid);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_l_sysid,
+ &l_sysid);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_l_fstype,
+ &l_fstype);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_l_start_pos_ext, &l_start_pos_ext);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_l_end_pos_ext, &l_end_pos_ext);
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_afsstorestatus (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+/*
+ unsigned32 mask;
+ afsTimeval modTime;
+ afsTimeval accessTime;
+ afsTimeval changeTime;
+ unsigned32 owner;
+ unsigned32 group;
+ unsigned32 mode;
+ afsHyper truncLength; applied first
+ afsHyper length;
+ afsUUID typeUUID;
+ unsigned32 deviceType; character or block
+ unsigned32 deviceNumber;
+ unsigned32 cmask;
+ unsigned32 clientSpare1; client-only attrs
+ unsigned32 deviceNumberHighBits;
+ unsigned32 spare1;
+ unsigned32 spare2;
+ unsigned32 spare3;
+ unsigned32 spare4;
+ unsigned32 spare5;
+ unsigned32 spare6;
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 mask, modtime_sec, changetime_sec, accesstime_sec, devicenumber,
+ clientspare1, devicenumberhighbits, spare1, spare2, spare3, spare4,
+ spare5, spare6, accesstime_usec, changetime_usec, owner, group, mode,
+ trunc_high, trunc_low, length_high, length_low, devicetype,
+ cmask, modtime_usec;
+ e_uuid_t typeuuid;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsStoreStatus:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsstorestatus);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_mask, &mask);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_modtime_sec, &modtime_sec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_modtime_usec, &modtime_usec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_accesstime_sec,
+ &accesstime_sec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_accesstime_usec,
+ &accesstime_usec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_changetime_sec,
+ &changetime_sec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_changetime_usec,
+ &changetime_usec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_owner, &owner);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_group, &group);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_mode, &mode);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_trunc_high, &trunc_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_trunc_low, &trunc_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_length_high, &length_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_length_low, &length_low);
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_typeuuid, &typeuuid);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_devicetype, &devicetype);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_devicenumber, &devicenumber);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_cmask, &cmask);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_clientspare1, &clientspare1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_devicenumberhighbits,
+ &devicenumberhighbits);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_spare1, &spare1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_spare2, &spare2);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_spare3, &spare3);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_spare4, &spare4);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_spare5, &spare5);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_storestatus_spare6, &spare6);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Mask=");
+ if ((mask & AFS_SETMODTIME) == AFS_SETMODTIME)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, ":SETMODTIME-%u.%u",
+ modtime_sec, modtime_usec);
+ }
+ if ((mask & AFS_SETOWNER) == AFS_SETOWNER)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, ":SETOWNER-%u", owner);
+ }
+ if ((mask & AFS_SETGROUP) == AFS_SETGROUP)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, ":SETGROUP-%u", group);
+ }
+ if ((mask & AFS_SETMODE) == AFS_SETMODE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, ":SETMODE-%o", mode);
+ }
+ if ((mask & AFS_SETACCESSTIME) == AFS_SETACCESSTIME)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, ":SETACCESSTIME-%u.%u",
+ accesstime_sec, accesstime_usec);
+ }
+ if ((mask & AFS_SETCHANGETIME) == AFS_SETCHANGETIME)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, ":SETCHANGETIME-%u.%u",
+ changetime_sec, changetime_usec);
+ }
+ if ((mask & AFS_SETLENGTH) == AFS_SETLENGTH)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SETLENGTH");
+ }
+ if ((mask & AFS_SETTYPEUUID) == AFS_SETTYPEUUID)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SETTYPEUUID");
+ }
+ if ((mask & AFS_SETDEVNUM) == AFS_SETDEVNUM)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SETDEVNUM");
+ }
+ if ((mask & AFS_SETMODEXACT) == AFS_SETMODEXACT)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SETMODEXACT");
+ }
+ if ((mask & AFS_SETTRUNCLENGTH) == AFS_SETTRUNCLENGTH)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SETTRUNCLENGTH");
+ }
+ if ((mask & AFS_SETCLIENTSPARE) == AFS_SETCLIENTSPARE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SETCLIENTSPARE");
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_afstoken (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+/*
+ afsHyper tokenID;
+ unsigned32 expirationTime;
+ afsHyper type;
+ unsigned32 beginRange;
+ unsigned32 endRange;
+ unsigned32 beginRangeExt;
+ unsigned32 endRangeExt;
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 tokenid_hi, tokenid_low, expirationtime, type_hi, type_low,
+ beginrange, endrange, beginrangeext, endrangeext, type;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "afsToken:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afstoken);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_tokenid_hi,
+ &tokenid_hi);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_tokenid_low, &tokenid_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_expirationtime, &expirationtime);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_type_hi,
+ &type_hi);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_type_low,
+ &type_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_beginrange,
+ &beginrange);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_endrange,
+ &endrange);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_beginrangeext, &beginrangeext);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_endrangeext, &endrangeext);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " :Tokenid:%u/%u ExpirationTime:%u beginrange:%u endrange:%u beginrangeext:%u endrangeext:%u",
+ tokenid_hi, tokenid_low, expirationtime, beginrange,
+ endrange, beginrangeext, endrangeext);
+ type = type_low;
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, " Type=");
+
+ if ((type & TKN_LOCK_READ) == TKN_LOCK_READ)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":LOCK_READ");
+ }
+ if ((type & TKN_LOCK_WRITE) == TKN_LOCK_WRITE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":LOCK_WRITE");
+ }
+ if ((type & TKN_DATA_READ) == TKN_DATA_READ)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":DATA_READ");
+ }
+ if ((type & TKN_DATA_WRITE) == TKN_DATA_WRITE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":DATA_WRITE");
+ }
+ if ((type & TKN_OPEN_READ) == TKN_OPEN_READ)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_READ");
+ }
+ if ((type & TKN_OPEN_WRITE) == TKN_OPEN_WRITE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_WRITE");
+ }
+ if ((type & TKN_OPEN_SHARED) == TKN_OPEN_SHARED)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_SHARED");
+ }
+ if ((type & TKN_OPEN_EXCLUSIVE) == TKN_OPEN_EXCLUSIVE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_EXCLUSIVE");
+ }
+ if ((type & TKN_OPEN_DELETE) == TKN_OPEN_DELETE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_DELETE");
+ }
+ if ((type & TKN_OPEN_PRESERVE) == TKN_OPEN_PRESERVE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_PRESERVE");
+ }
+ if ((type & TKN_STATUS_READ) == TKN_STATUS_READ)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":STATUS_READ");
+ }
+ if ((type & TKN_STATUS_WRITE) == TKN_STATUS_WRITE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":STATUS_WRITE");
+ }
+ if ((type & TKN_OPEN_UNLINK) == TKN_OPEN_UNLINK)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_UNLINK");
+ }
+ if ((type & TKN_SPOT_HERE) == TKN_SPOT_HERE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SPOT_HERE");
+ }
+ if ((type & TKN_SPOT_THERE) == TKN_SPOT_THERE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SPOT_THERE");
+ }
+ if ((type & TKN_OPEN_NO_READ) == TKN_OPEN_NO_READ)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_NO_READ");
+ }
+ if ((type & TKN_OPEN_NO_WRITE) == TKN_OPEN_NO_WRITE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_NO_WRITE");
+ }
+ if ((type & TKN_OPEN_NO_UNLINK) == TKN_OPEN_NO_UNLINK)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":OPEN_NO_UNLINK");
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_afstaggedname (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+
+/*
+ codesetTag tn_tag;
+ unsigned16 tn_length;
+ byte tn_chars[AFS_NAMEMAX+1];
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 tn_tag;
+ guint16 tn_length;
+ const guint8 *tn_string;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsTaggedName:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afstaggedname);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_tn_tag,
+ &tn_tag);
+ offset =
+ dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep, hf_afs4int_tn_length,
+ &tn_length);
+ if (tn_length < 254)
+ {
+ proto_tree_add_string (tree, hf_afs4int_tn_string, tvb, offset,
+ hf_afs4int_tn_size, tvb_get_ptr (tvb, offset,
+ tn_length));
+ tn_string = tvb_get_ptr (tvb, offset, 257);
+ offset += 257;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " :tn_tag: %s", tn_string);
+ }
+ else
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " :FIXME!: Invalid string length of %u", tn_length);
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_afsfidtaggedname (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+/*
+ afsFid fid;
+ afsTaggedName name;
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "FidTaggedName:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsfidtaggedname);
+ }
+ offset = dissect_afsFid (tvb, offset, pinfo, tree, drep);
+ offset = dissect_afstaggedname (tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+
+}
+
+static int
+dissect_minvvp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+
+/* unsigned32 minvvp_high
+ unsigned32 minvvp_low
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 minvvp_high, minvvp_low;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "minVVp:");
+ tree = proto_item_add_subtree (item, ett_afs4int_minvvp);
+ }
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_minvvp_high, &minvvp_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_minvvp_low,
+ &minvvp_low);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " minVVp:%u/%u", minvvp_high,
+ minvvp_low);
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_afsuuid (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+
+/* uuid UUID
+*/
+/*HEREN*/
+
+ e_uuid_t uuid1;
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "afsUUID:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsuuid);
+ }
+
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_afs4int_afsuuid_uuid, &uuid1);
+
+
+if (check_col (pinfo->cinfo, COL_INFO)) col_append_fstr (pinfo->cinfo, COL_INFO, ":%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid1.Data1, uuid1.Data2, uuid1.Data3, uuid1.Data4[0], uuid1.Data4[1], uuid1.Data4[2], uuid1.Data4[3], uuid1.Data4[4], uuid1.Data4[5], uuid1.Data4[6], uuid1.Data4[7]);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_offsetp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+
+/* unsigned32 offsetp_high
+ unsigned32 offsetp_low
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 offsetp_high, offsetp_low;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "minVVp:");
+ tree = proto_item_add_subtree (item, ett_afs4int_offsetp);
+ }
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_offsetp_high, &offsetp_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_offsetp_low,
+ &offsetp_low);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " offsetp:%u/%u", offsetp_high,
+ offsetp_low);
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_returntokenidp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+
+/* unsigned32 returntokenidp_high
+ unsigned32 returntokenidp_low
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 returntokenidp_high, returntokenidp_low;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "returnTokenIDp:");
+ tree = proto_item_add_subtree (item, ett_afs4int_returntokenidp);
+ }
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_returntokenidp_high, &returntokenidp_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_returntokenidp_low,
+ &returntokenidp_low);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " returnTokenIDp:%u/%u", returntokenidp_high,
+ returntokenidp_low);
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_volsync (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+/*
+ afsHyper VolID;
+ afsHyper VV; volume's version
+ unsigned32 VVAge; age, in seconds, of the knowledge that the
+ given VolVers is current
+ unsigned32 VVPingAge; age, in seconds, of the last probe from
+ the callee (the secondary) to the primary
+ unsigned32 vv_spare1;
+ unsigned32 vv_spare2;
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 volid_hi, volid_low, vv_hi, vv_low, vvage, vvpingage, vvspare1,
+ vvspare2;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "AfsVolSync:");
+ tree = proto_item_add_subtree (item, ett_afs4int_volsync);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_volid_hi,
+ &volid_hi);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_volid_low,
+ &volid_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_vv_hi,
+ &vv_hi);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_vv_low,
+ &vv_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_vvage,
+ &vvage);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_vvpingage,
+ &vvpingage);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_vvspare1,
+ &vvspare1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_vvspare2,
+ &vvspare2);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " volid_hi:%u volid_low:%u vv_hi:%u vv_low:%u vvage:%u vvpingage:%u vvpspare1:%u vvspare2:%u",
+ volid_hi, volid_low, vv_hi, vv_low, vvage, vvpingage,
+ vvspare1, vvspare2);
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+
+}
+
+static int
+dissect_afsFlags (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep)
+{
+
+
+/*
+ unsigned32 flags
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 flags;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "AfsFlags:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsflags);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_flags,
+ &flags);
+
+ if (flags)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, " Flags=");
+ if ((flags & AFS_FLAG_RETURNTOKEN) == AFS_FLAG_RETURNTOKEN)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":RETURNTOKEN");
+ }
+ if ((flags & AFS_FLAG_TOKENJUMPQUEUE) == AFS_FLAG_TOKENJUMPQUEUE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":TOKENJUMPQUEUE");
+ }
+ if ((flags & AFS_FLAG_SKIPTOKEN) == AFS_FLAG_SKIPTOKEN)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SKIPTOKEN");
+ }
+ if ((flags & AFS_FLAG_NOOPTIMISM) == AFS_FLAG_NOOPTIMISM)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":NOOPTIMISM");
+ }
+ if ((flags & AFS_FLAG_TOKENID) == AFS_FLAG_TOKENID)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":TOKENID");
+ }
+ if ((flags & AFS_FLAG_RETURNBLOCKER) == AFS_FLAG_RETURNBLOCKER)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":RETURNBLOCKER");
+ }
+ if ((flags & AFS_FLAG_ASYNCGRANT) == AFS_FLAG_ASYNCGRANT)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":ASYNCGRANT");
+ }
+ if ((flags & AFS_FLAG_NOREVOKE) == AFS_FLAG_NOREVOKE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":NOREVOKE");
+ }
+ if ((flags & AFS_FLAG_MOVE_REESTABLISH) == AFS_FLAG_MOVE_REESTABLISH)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":MOVE_REESTABLISH");
+ }
+ if ((flags & AFS_FLAG_SERVER_REESTABLISH) ==
+ AFS_FLAG_SERVER_REESTABLISH)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SERVER_REESTABLISH");
+ }
+ if ((flags & AFS_FLAG_NO_NEW_EPOCH) == AFS_FLAG_NO_NEW_EPOCH)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":NO_NEW_EPOCH");
+ }
+ if ((flags & AFS_FLAG_MOVE_SOURCE_OK) == AFS_FLAG_MOVE_SOURCE_OK)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":MOVE_SOURCE_OK");
+ }
+ if ((flags & AFS_FLAG_SYNC) == AFS_FLAG_SYNC)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SYNC");
+ }
+ if ((flags & AFS_FLAG_ZERO) == AFS_FLAG_ZERO)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":ZERO");
+ }
+ if ((flags & AFS_FLAG_SKIPSTATUS) == AFS_FLAG_SKIPSTATUS)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SKIPSTATUS");
+ }
+ if ((flags & AFS_FLAG_FORCEREVOCATIONS) == AFS_FLAG_FORCEREVOCATIONS)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":FORCEREVOCATIONS");
+ }
+ if ((flags & AFS_FLAG_FORCEVOLQUIESCE) == AFS_FLAG_FORCEVOLQUIESCE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":FORCEVOLQUIESCE");
+ }
+ if ((flags & AFS_FLAG_SEC_SERVICE) == AFS_FLAG_SEC_SERVICE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SEC_SERVICE");
+ }
+ if ((flags & AFS_FLAG_CONTEXT_NEW_ACL_IF) ==
+ AFS_FLAG_CONTEXT_NEW_ACL_IF)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":CONTEXT_NEW_ACL_IF");
+ }
+ }
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_fetchstatus (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+
+/*
+ unsigned32 interfaceVersion;
+ unsigned32 fileType;
+ unsigned32 linkCount;
+ afsHyper length;
+ afsHyper dataVersion;
+ unsigned32 author;
+ unsigned32 owner;
+ unsigned32 group;
+ unsigned32 callerAccess;
+ unsigned32 anonymousAccess;
+ unsigned32 aclExpirationTime;
+ unsigned32 mode;
+ unsigned32 parentVnode;
+ unsigned32 parentUnique;
+ afsTimeval modTime;
+ afsTimeval changeTime;
+ afsTimeval accessTime;
+ afsTimeval serverModTime;
+ afsUUID typeUUID;
+ afsUUID objectUUID;
+ unsigned32 deviceNumber;
+ unsigned32 blocksUsed;
+ unsigned32 clientSpare1; * client-only attrs *
+ unsigned32 deviceNumberHighBits;
+ unsigned32 spare0;
+ unsigned32 spare1;
+ unsigned32 spare2;
+ unsigned32 spare3;
+ unsigned32 spare4;
+ unsigned32 spare5;
+ unsigned32 spare6;
+*/
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 interfaceversion, filetype, linkcount, length_high, length_low,
+ dataversion_high, dataversion_low, author, owner, group, calleraccess,
+ anonymousaccess, aclexpirationtime, mode, parentvnode, parentunique,
+ modtime_sec, modtime_msec, changetime_sec, changetime_msec,
+ accesstime_sec, accesstime_msec, servermodtime_msec, servermodtime_sec,
+ devicenumber, blocksused, clientspare1, devicenumberhighbits,
+ agtypeunique, himaxspare, lomaxspare, pathconfspare, spare4, spare5,
+ spare6;
+ e_uuid_t typeuuid, objectuuid;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "FetchStatus:");
+ tree = proto_item_add_subtree (item, ett_afs4int_fetchstatus);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_interfaceversion, &interfaceversion);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_filetype,
+ &filetype);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_linkcount,
+ &linkcount);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_length_high, &length_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_length_low,
+ &length_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_dataversion_high, &dataversion_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_dataversion_low, &dataversion_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_author,
+ &author);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_owner,
+ &owner);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_group,
+ &group);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_calleraccess, &calleraccess);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_anonymousaccess, &anonymousaccess);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_aclexpirationtime, &aclexpirationtime);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_mode,
+ &mode);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_parentvnode, &parentvnode);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_parentunique, &parentunique);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_modtime_sec, &modtime_sec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_modtime_msec, &modtime_msec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_changetime_sec, &changetime_sec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_changetime_msec, &changetime_msec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_accesstime_sec, &accesstime_sec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_accesstime_msec, &accesstime_msec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_servermodtime_sec, &servermodtime_sec);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_servermodtime_msec, &servermodtime_msec);
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_afs4int_typeuuid,
+ &typeuuid);
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_afs4int_objectuuid,
+ &objectuuid);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_devicenumber, &devicenumber);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_blocksused,
+ &blocksused);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_clientspare1, &clientspare1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_devicenumberhighbits,
+ &devicenumberhighbits);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_agtypeunique, &agtypeunique);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_himaxspare,
+ &himaxspare);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_lomaxspare,
+ &lomaxspare);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_pathconfspare, &pathconfspare);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_spare4,
+ &spare4);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_spare5,
+ &spare5);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_spare6,
+ &spare6);
+
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " :interfacever:%u filetype:%u linkcount:%u length:%u dataver:%u author:%u owner:%u group:%u calleraccess:%u anonaccess:%u aclexpire:%u mode:%u parentvnode:%u parentunique:%u modtimesec:%u changetime_sec:%u accesstime_sec:%u servermodtimesec:%u devicenumber:%u blocksused:%u clientspare:%u devicehighbits:%u agtypeunique:%u",
+ interfaceversion, filetype, linkcount, length_low,
+ dataversion_low, author, owner, group, calleraccess,
+ anonymousaccess, aclexpirationtime, mode, parentvnode,
+ parentunique, modtime_sec, changetime_sec,
+ accesstime_sec, servermodtime_sec, devicenumber,
+ blocksused, clientspare1, devicenumberhighbits,
+ agtypeunique);
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_afsReturnDesc (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 *drep)
+{
+/*
+ afsFid fid; * useful hint *
+ afsHyper tokenID;
+ afsHyper type; * mask *
+ unsigned32 flags; * just in case *
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 tokenid_high, tokenid_low, type_high, type_low;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsReturnDesc:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsReturnDesc);
+ }
+
+
+ offset = dissect_afsFid ( tvb, offset, pinfo, tree, drep);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsreturndesc_tokenid_high, &tokenid_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsreturndesc_tokenid_low, &tokenid_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsreturndesc_type_high, &type_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_afsreturndesc_type_low, &type_low);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " TokenId:%u/%u Type:%u/%u",
+ tokenid_high, tokenid_low, type_high, type_low);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags: ", -1);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+
+static int
+dissect_afsReturns (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+
+/*
+ long afsReturns_len;
+ [length_is(afsReturns_len)] afsReturnDesc afsReturns_val[AFS_BULKMAX];
+*/
+
+ /* this is not really a ucvarray, but with the initial len, we can
+ cheat and pretend it is */
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ offset =
+ dissect_ndr_ucvarray (tvb, offset, pinfo, tree, drep,
+ dissect_afsReturnDesc);
+
+ return offset;
+}
+
+#if 0 /* not used */
+
+static int
+dissect_afsbundled_stat (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree, guint8 *drep _U_)
+{
+
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "afsbundled_stat:");
+ tree = proto_item_add_subtree (item, ett_afs4int_afsbundled_stat);
+ }
+
+/* bundled_stat
+
+ afsFid fid;
+ afsFetchStatus stat;
+ afsToken token;
+ error_status_t error;
+*/
+
+/*
+ offset = dissect_afsFid(tvb, offset, pinfo, tree, drep);
+*/
+/* SKIPTOKEN/STAT?
+ offset = dissect_fetchstatus(tvb, offset, pinfo, tree, drep);
+ offset = dissect_afstoken(tvb, offset, pinfo, tree, drep);
+*/
+/* This is currently under construction as I figure out the reverse layout of the packet. */
+/*
+ offset = dissect_afsErrorStatus (tvb, offset, pinfo, tree, drep);
+*/
+
+
+
+
+ proto_item_set_len (item, offset - old_offset);
+return offset;
+
+}
+
+#endif /* not used */
+
+static int
+dissect_afsBulkStat (tvbuff_t * tvb _U_, int offset,
+ packet_info * pinfo _U_, proto_tree * tree _U_,
+ guint8 *drep _U_)
+{
+/*
+ unsigned32 BulkStat_len;
+ [length_is(BulkStat_len)] bundled_stat BulkStat_val[AFS_BULKMAX];
+*/
+ /* this is not really a ucvarray, but with the initial len, we can
+ cheat and pretend it is */
+ /*
+ offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
+ dissect_afsbundled_stat);
+ */
+
+ return offset;
+}
+
+
+
+
+static int
+afs4int_dissect_removefile_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+
+
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsFidTaggedName *Namep,
+ [in] afsHyper *returnTokenIDp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsfidtaggedname, NDR_POINTER_REF,
+ "afsFidTaggedName: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_returntokenidp,
+ NDR_POINTER_REF, "afsReturnTokenIDp:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "afsMinVVp:", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_storedata_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ guint32 position_high, position_low, length;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *Fidp,
+ [in] afsStoreStatus *InStatusp,
+ [in] afsHyper *Position,
+ [in] signed32 Length,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+ [in] pipe_t *storeStream,
+*/
+
+
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsstorestatus, NDR_POINTER_REF,
+ "afsStoreStatus:", -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_position_high, &position_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_position_low, &position_low);
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_length, &length);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Position:%u/%u Length:%u",
+ position_high, position_low, length);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+/* XXX need to decode pipe_t still here */
+
+ return offset;
+}
+
+static int
+afs4int_dissect_gettoken_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [in] afsFid *Fidp,
+ [in] afsToken *MinTokenp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afstoken,
+ NDR_POINTER_REF, "afsToken: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+ return offset;
+}
+static int
+afs4int_dissect_gettoken_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+
+ dcerpc_info *di;
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsToken *OutTokenp,
+ [out] afsRecordLock *OutBlockerp,
+ [out] afsFetchStatus *OutStatusp,
+ [out] afsVolSync *Syncp
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afstoken,
+ NDR_POINTER_REF, "afsToken: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsRecordLock, NDR_POINTER_REF,
+ "afsRecordLock: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "afsFetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsErrorStatus, NDR_POINTER_REF,
+ "afsErrorStatus: ", -1);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_lookuproot_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ * [in] afsFid *InFidp,
+ * [in] afsHyper *minVVp,
+ * [in] unsigned32 Flags,
+ */
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_fetchdata_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ guint32 position_high, position_low, length;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *Fidp,
+ [in] afsHyper *minVVp,
+ [in] afsHyper *Position,
+ [in] signed32 Length,
+ [in] unsigned32 Flags,
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_position_high, &position_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_position_low, &position_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_length, &length);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Position:%u/%u Length:%u",
+ position_high, position_low, length);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_fetchacl_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+
+ guint32 acltype;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [in] afsFid *Fidp,
+ [in] unsigned32 aclType,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_acltype,
+ &acltype);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+ if (acltype)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO,
+ " :copy the ACL from specified fid:");
+ }
+
+
+ return offset;
+}
+static int
+afs4int_dissect_fetchstatus_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [in] afsFid *Fidp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+ return offset;
+}
+static int
+afs4int_dissect_storeacl_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ guint32 acltype;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *Fidp,
+ [in] afsACL *AccessListp,
+ [in] unsigned32 aclType,
+ [in] afsFid *aclFidp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsAcl,
+ NDR_POINTER_REF, "afsAcl: ", -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_afs4int_acltype,
+ &acltype);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " aclType:%u",acltype);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_storestatus_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [in] afsFid *Fidp,
+ [in] afsStoreStatus *InStatusp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsstorestatus, NDR_POINTER_REF,
+ "afsStoreStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+
+ return offset;
+}
+
+static int
+afs4int_dissect_createfile_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsTaggedName *Namep,
+ [in] afsStoreStatus *InStatusp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afstaggedname, NDR_POINTER_REF,
+ "afsTaggedName: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsstorestatus, NDR_POINTER_REF,
+ "afsStoreStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_rename_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *OldDirFidp,
+ [in] afsFidTaggedName *OldNamep,
+ [in] afsFid *NewDirFidp,
+ [in] afsFidTaggedName *NewNamep,
+ [in] afsHyper *returnTokenIDp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsfidtaggedname, NDR_POINTER_REF,
+ "afsFidTaggedName: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afstaggedname, NDR_POINTER_REF,
+ "afsFidTaggedName: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_returntokenidp, NDR_POINTER_REF,
+ "afsReturnTokenIDp: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_minvvp, NDR_POINTER_REF,
+ "afsminVVp: ", -1);
+
+ offset = dissect_afsFlags(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_symlink_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsTaggedName *Namep,
+ [in] afsTaggedPath *LinkContentsp,
+ [in] afsStoreStatus *InStatusp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afstaggedname, NDR_POINTER_REF,
+ "afsTaggedName: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsTaggedPath, NDR_POINTER_REF,
+ "afsTaggedPath: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsstorestatus, NDR_POINTER_REF,
+ "afsStoreStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset = dissect_afsFlags (tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_readdir_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ guint32 size;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsHyper *Offsetp,
+ [in] unsigned32 Size,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_offsetp,
+ NDR_POINTER_REF, "Offsetp: ", -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_readdir_size, &size);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Size:%u", size);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset = dissect_afsFlags ( tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_makedir_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsTaggedName *Namep,
+ [in] afsStoreStatus *InStatusp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afstaggedname, NDR_POINTER_REF,
+ "afsTaggedName: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsstorestatus, NDR_POINTER_REF,
+ "afsStoreStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset = dissect_afsFlags ( tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_removedir_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ guint32 returntokenidp_high, returntokenidp_low;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsFidTaggedName *Namep,
+ [in] afsHyper *returnTokenIDp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsfidtaggedname, NDR_POINTER_REF,
+ "afsFidTaggedName: ", -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_returntokenidp_high, &returntokenidp_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_returntokenidp_low, &returntokenidp_low);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " returnTokenIDp:%u/%u",
+ returntokenidp_high, returntokenidp_low);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset = dissect_afsFlags ( tvb, offset, pinfo, tree, drep );
+
+ return offset;
+}
+
+static int
+afs4int_dissect_lookup_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsTaggedName *Namep,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afstaggedname, NDR_POINTER_REF,
+ "afsTaggedName: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset = dissect_afsFlags ( tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+static int
+afs4int_dissect_lookup_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFid *OutFidp,
+ [out] afsFetchStatus *OutFidStatusp,
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsToken *OutTokenp,
+ [out] afsVolSync *Syncp
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afstoken,
+ NDR_POINTER_REF, "afsToken: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("Lookup reply");
+
+ return offset;
+
+}
+
+static int
+afs4int_dissect_makemountpoint_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+ guint16 type;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsTaggedName *Namep,
+ [in] afsTaggedName *cellNamep,
+ [in] afsFStype Type,
+ [in] afsTaggedName *volumeNamep,
+ [in] afsStoreStatus *InStatusp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afstaggedname, NDR_POINTER_REF,
+ "afsTaggedName: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afstaggedname, NDR_POINTER_REF,
+ "afsTaggedName: ", -1);
+ offset =
+ dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep, hf_afs4int_fstype,
+ &type);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afstaggedname, NDR_POINTER_REF,
+ "afsTaggedName: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsstorestatus, NDR_POINTER_REF,
+ "afsStoreStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+
+ offset = dissect_afsFlags (tvb, offset, pinfo, tree, drep);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Type:%u", type);
+
+ return offset;
+
+}
+
+static int
+afs4int_dissect_setcontext_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ guint32 epochtime, clientsizesattrs, parm7;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] unsigned32 epochTime,
+ [in] afsNetData *callbackAddr,
+ [in] unsigned32 Flags,
+ [in] afsUUID *secObjectID,
+ [in] unsigned32 clientSizesAttrs,
+ [in] unsigned32 parm7
+*/
+
+
+ offset =
+ dissect_dcerpc_time_t (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_setcontext_rqst_epochtime, &epochtime);
+
+ offset = dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsNetData,
+ NDR_POINTER_REF, "afsNetData:", -1);
+
+ offset = dissect_afsFlags (tvb, offset, pinfo, tree, drep);
+
+if (check_col (pinfo->cinfo, COL_INFO)) col_append_str (pinfo->cinfo, COL_INFO, " setObjectID");
+
+ offset = dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsuuid,
+ NDR_POINTER_REF, "afsUUID:", -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_setcontext_rqst_clientsizesattrs,
+ &clientsizesattrs);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_setcontext_rqst_parm7, &parm7);
+
+if (check_col (pinfo->cinfo, COL_INFO)) col_append_fstr (pinfo->cinfo, COL_INFO, " epochTime:%u clientSizesAttrs:%u parm7:%u", epochtime, clientsizesattrs, parm7);
+
+ return offset;
+}
+
+static int
+afs4int_dissect_setcontext_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+/* nothing but error code */
+
+ dcerpc_info *di;
+
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ MACRO_ST_CLEAR ("SetContext reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_lookuproot_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ /*
+ * [out] afsFid *OutFidp,
+ * [out] afsFetchStatus *OutFidStatusp,
+ * [out] afsToken *OutTokenp,
+ * [out] afsVolSync *Syncp
+ */
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afstoken,
+ NDR_POINTER_REF, "afsToken: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("LookupRoot reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_fetchdata_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+
+ dcerpc_info *di;
+ guint32 pipe_t_size;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFetchStatus *OutStatusp,
+ [out] afsToken *OutTokenp,
+ [out] afsVolSync *Syncp,
+ [out] pipe_t *fetchStream
+*/
+/* The SkipToken/SkipStatus flags are always used in every fetchdata request I have seen.
+There is also not sign of the afsVolSync structure... Just size, and data string... aka pipe_t */
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_fetchdata_pipe_t_size, &pipe_t_size);
+
+ return offset;
+}
+
+static int
+ afs4int_dissect_fetchacl_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [out] afsACL *AccessListp,
+ [out] afsFetchStatus *OutStatusp,
+ [out] afsVolSync *Syncp
+*/
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsAcl,
+ NDR_POINTER_REF, "afsAcl: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("FetchAcl reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_fetchstatus_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFetchStatus *OutStatusp,
+ [out] afsToken *OutTokenp,
+ [out] afsVolSync *Syncp
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afstoken,
+ NDR_POINTER_REF, "afsToken: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("FetchStatus reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_storedata_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFetchStatus *OutStatusp,
+ [out] afsVolSync *Syncp
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("StoreData reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_storeacl_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFetchStatus *OutStatusp,
+ [out] afsVolSync *Syncp
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("StoreAcl reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_storestatus_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFetchStatus *OutStatusp,
+ [out] afsVolSync *Syncp
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("StoreStatus reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_removefile_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsFetchStatus *OutFileStatusp,
+ [out] afsFid *OutFileFidp,
+ [out] afsVolSync *Syncp
+*/
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("RemoveFile reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_createfile_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFid *OutFidp,
+ [out] afsFetchStatus *OutFidStatusp,
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsToken *OutTokenp,
+ [out] afsVolSync *Syncp
+*/
+
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afstoken,
+ NDR_POINTER_REF, "afsToken: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("CreateFile reply");
+
+ return offset;
+}
+static int
+ afs4int_dissect_rename_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFetchStatus *OutOldDirStatusp,
+ [out] afsFetchStatus *OutNewDirStatusp,
+ [out] afsFid *OutOldFileFidp,
+ [out] afsFetchStatus *OutOldFileStatusp,
+ [out] afsFid *OutNewFileFidp,
+ [out] afsFetchStatus *OutNewFileStatusp,
+ [out] afsVolSync *Syncp
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR("Rename reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_symlink_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFid *OutFidp,
+ [out] afsFetchStatus *OutFidStatusp,
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsToken *OutTokenp,
+ [out] afsVolSync *Syncp
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afstoken,
+ NDR_POINTER_REF, "afsToken: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("Symlink reply");
+
+ return offset;
+}
+
+static int
+ afs4int_dissect_hardlink_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFetchStatus *OutFidStatusp,
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsVolSync *Syncp
+*/
+
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("Hardlink reply");
+
+ return offset;
+}
+static int
+ afs4int_dissect_hardlink_rqst
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsTaggedName *Namep,
+ [in] afsFid *ExistingFidp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afstaggedname, NDR_POINTER_REF,
+ "afsTaggedName: ", -1);
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+
+ offset = dissect_afsFlags ( tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+ afs4int_dissect_makedir_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFid *OutFidp,
+ [out] afsFetchStatus *OutFidStatusp,
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsToken *OutTokenp,
+ [out] afsVolSync *Syncp
+*/
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afstoken,
+ NDR_POINTER_REF, "afsToken: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+
+ MACRO_ST_CLEAR ("MakeDir reply");
+
+ return offset;
+}
+
+static int
+ afs4int_dissect_removedir_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsFid *OutFidp,
+ [out] afsFetchStatus *OutDelStatusp,
+ [out] afsVolSync *Syncp
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("RemoveDir reply");
+
+ return offset;
+
+}
+
+static int
+ afs4int_dissect_readdir_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+
+ guint32 nextoffsetp_high, nextoffsetp_low;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [out] afsHyper *NextOffsetp,
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsToken *OutTokenp,
+ [out] afsVolSync *Syncp,
+ [out] pipe_t *dirStream
+*/
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_nextoffsetp_high, &nextoffsetp_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_nextoffsetp_low, &nextoffsetp_low);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " NextOffsetp:%u/%u",
+ nextoffsetp_high, nextoffsetp_low);
+
+ /* all packets seem to have SKIPTOKEN/SKIPSTATUS sent, and thus these structures are missing on calls holding tokens. */
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ /* XXX need to add pipe_t here, once figured out. */
+
+ return offset;
+}
+
+static int
+ afs4int_dissect_releasetokens_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ /* no out */
+ MACRO_ST_CLEAR ("ReleaseTokens reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_releasetokens_rqst
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [in] afsReturns *Tokens_Arrayp,
+ [in] unsigned32 Flags
+*/
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsReturns,
+ NDR_POINTER_REF, "afsReturns: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags: ", -1);
+ return offset;
+}
+
+static int
+ afs4int_dissect_gettime_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+
+ guint32 secondsp, usecondsp, syncdistance, syncdispersion;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] unsigned32 *Secondsp,
+ [out] unsigned32 *USecondsp,
+ [out] unsigned32 *SyncDistance,
+ [out] unsigned32 *SyncDispersion
+*/
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_gettime_secondsp, &secondsp);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_gettime_usecondsp, &usecondsp);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_gettime_syncdistance, &syncdistance);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_gettime_syncdispersion, &syncdispersion);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) col_append_fstr (pinfo->cinfo, COL_INFO, " Secondsp:%u Usecondsp:%u SyncDistance:/%u SyncDispersion:%u", secondsp, usecondsp, syncdistance, syncdispersion);
+
+ MACRO_ST_CLEAR ("GetTime reply");
+
+ return offset;
+
+}
+
+static int
+ afs4int_dissect_gettime_rqst
+ (tvbuff_t *
+ tvb _U_, int offset, packet_info * pinfo, proto_tree * tree _U_, guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ /* nothing */
+
+ return offset;
+}
+
+static int
+ afs4int_dissect_processquota_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in,out] afsQuota *quotaListp,
+ [out] afsFetchStatus *OutStatusp,
+ [out] afsVolSync *Syncp
+*/
+
+ /* XXX need afsQuota */
+ offset += 92;
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("ProcessQuota reply");
+
+ return offset;
+}
+
+static int
+ afs4int_dissect_processquota_rqst
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsFid *Fidp,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+ [in,out] afsQuota *quotaListp,
+*/
+
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset = dissect_afsFlags ( tvb, offset, pinfo, tree, drep);
+
+ /* XXX need to figure out afsQuota here */
+ return offset;
+}
+
+static int
+ afs4int_dissect_getserverinterfaces_rqst
+ (tvbuff_t *
+ tvb _U_, int offset, packet_info * pinfo, proto_tree * tree _U_, guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in, out] dfs_interfaceList *serverInterfacesP
+*/
+ /* XXX figure out dfs_interfacelist */
+ return offset;
+}
+
+static int
+ afs4int_dissect_getserverinterfaces_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in, out] dfs_interfaceList *serverInterfacesP
+*/
+ /* XXX figure out dfs_interfacelist */
+
+ MACRO_ST_CLEAR ("GetServerInterfaces reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_setparams_rqst
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] unsigned32 Flags,
+ [in, out] afsConnParams *paramsP
+*/
+ offset = dissect_afsFlags( tvb, offset, pinfo, tree, drep);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsConnParams, NDR_POINTER_REF,
+ "afsConnParams:", -1);
+ return offset;
+}
+
+static int
+ afs4int_dissect_setparams_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in, out] afsConnParams *paramsP
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_afsConnParams, NDR_POINTER_REF,
+ "afsConnParams:", -1);
+ MACRO_ST_CLEAR ("SetParams reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_makemountpoint_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsFid *OutFidp,
+ [out] afsFetchStatus *OutFidStatusp,
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsVolSync *Syncp
+*/
+ /* afsFid */
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+ MACRO_ST_CLEAR ("MakeMountPoint reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_getstatistics_rqst
+ (tvbuff_t *
+ tvb _U_, int offset, packet_info * pinfo, proto_tree * tree _U_, guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ /* nothing for request */
+ return offset;
+}
+
+static int
+ afs4int_dissect_getstatistics_resp
+ (tvbuff_t *
+ tvb _U_, int offset, packet_info * pinfo, proto_tree * tree _U_, guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsStatistics *Statisticsp
+*/
+ /* XXX figure out afsStatistics */
+ return offset;
+}
+
+static int
+ afs4int_dissect_bulkfetchvv_rqst
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+
+ guint32 cellidp_high, cellidp_low, numvols, spare1, spare2;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsHyper *cellIdp,
+ [in] afsBulkVolIDs *VolIDsp,
+ [in] unsigned32 NumVols,
+ [in] unsigned32 Flags,
+ [in] unsigned32 spare1,
+ [in] unsigned32 spare2,
+*/
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_cellidp_high, &cellidp_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_cellidp_low, &cellidp_low);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " CellIDp:%u/%u", cellidp_high,
+ cellidp_low);
+
+ /* XXX figure out the afsBulkVolIDS */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_bulkfetchvv_numvols, &numvols);
+
+ offset = dissect_afsFlags (tvb, offset, pinfo, tree, drep);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_bulkfetchvv_spare1, &spare1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_bulkfetchvv_spare2, &spare2);
+ return offset;
+}
+
+static int
+ afs4int_dissect_bulkfetchvv_resp
+ (tvbuff_t *
+ tvb _U_, int offset, packet_info * pinfo, proto_tree * tree _U_, guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] afsBulkVVs *VolVVsp,
+ [out] unsigned32 *spare4
+*/
+ /* XXX need to figure out afsBulkVVs ; */
+ return offset;
+}
+
+static int
+ afs4int_dissect_bulkkeepalive_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ guint32 spare4;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] unsigned32 *spare4
+*/
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_bulkkeepalive_spare4, &spare4);
+ MACRO_ST_CLEAR ("BulkKeepAlive reply");
+ return offset;
+}
+
+static int
+ afs4int_dissect_bulkkeepalive_rqst
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ guint32 numexecfids, spare1, spare2;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] afsBulkFEX *KAFEXp,
+ [in] unsigned32 numExecFids,
+ [in] unsigned32 Flags,
+ [in] unsigned32 spare1,
+ [in] unsigned32 spare2,
+*/
+ /* XXX figure out afsBulkFEX */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_bulkkeepalive_numexecfids, &numexecfids);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFlags,
+ NDR_POINTER_REF, "afsFlags:", -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_bulkkeepalive_spare1, &spare1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_bulkkeepalive_spare2, &spare2);
+ return offset;
+}
+
+static int
+ afs4int_dissect_bulkfetchstatus_rqst
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+ guint32 offsetp_high, offsetp_low, size;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/*
+ [in] afsFid *DirFidp,
+ [in] afsHyper *Offsetp,
+ [in] unsigned32 Size,
+ [in] afsHyper *minVVp,
+ [in] unsigned32 Flags,
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsFid,
+ NDR_POINTER_REF, "afsFid: ", -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_offsetp_high, &offsetp_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_offsetp_low, &offsetp_low);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Offsetp:%u/%u", offsetp_high,
+ offsetp_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_bulkfetchstatus_size, &size);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_minvvp,
+ NDR_POINTER_REF, "MinVVp:", -1);
+ offset = dissect_afsFlags(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+ afs4int_dissect_bulkfetchstatus_resp
+ (tvbuff_t *
+ tvb, int offset, packet_info * pinfo, proto_tree * tree, guint8 *drep)
+{
+
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] BulkStat *bulkstats,
+ [out] afsHyper *NextOffsetp,
+ [out] afsFetchStatus *OutDirStatusp,
+ [out] afsToken *OutTokenp,
+ [out] afsVolSync *Syncp,
+ [out] pipe_t *dirStream
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afsBulkStat,
+ NDR_POINTER_REF, "BulkStat: ", -1);
+/* Under construction. The packet seems to have the pipe_t before the rest of the data listed in idl. */
+
+/*
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_nextoffsetp_high, &nextoffsetp_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_afs4int_nextoffsetp_low, &nextoffsetp_low);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " NextOffsetp:%u/%u",
+ nextoffsetp_high, nextoffsetp_low);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_fetchstatus,
+ NDR_POINTER_REF, "FetchStatus: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_afstoken,
+ NDR_POINTER_REF, "afsToken: ", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep, dissect_volsync,
+ NDR_POINTER_REF, "VolSync: ", -1);
+*/
+ /* XXX figure out pipe_t */
+
+ return offset;
+}
+
+static dcerpc_sub_dissector afs4int_dissectors[] = {
+ { 0, "SetContext", afs4int_dissect_setcontext_rqst, afs4int_dissect_setcontext_resp} ,
+ { 1, "LookupRoot", afs4int_dissect_lookuproot_rqst, afs4int_dissect_lookuproot_resp} ,
+ { 2, "FetchData", afs4int_dissect_fetchdata_rqst, afs4int_dissect_fetchdata_resp} ,
+ { 3, "FetchAcl", afs4int_dissect_fetchacl_rqst, afs4int_dissect_fetchacl_resp} ,
+ { 4, "FetchStatus", afs4int_dissect_fetchstatus_rqst, afs4int_dissect_fetchstatus_resp} ,
+ { 5, "StoreData", afs4int_dissect_storedata_rqst, afs4int_dissect_storedata_resp} ,
+ { 6, "StoreAcl", afs4int_dissect_storeacl_rqst, afs4int_dissect_storeacl_resp} ,
+ { 7, "StoreStatus", afs4int_dissect_storestatus_rqst, afs4int_dissect_storestatus_resp} ,
+ { 8, "RemoveFile", afs4int_dissect_removefile_rqst, afs4int_dissect_removefile_resp} ,
+ { 9, "CreateFile", afs4int_dissect_createfile_rqst, afs4int_dissect_createfile_resp} ,
+ { 10, "Rename", afs4int_dissect_rename_rqst, afs4int_dissect_rename_resp} ,
+ { 11, "Symlink", afs4int_dissect_symlink_rqst, afs4int_dissect_symlink_resp} ,
+ { 12, "HardLink", afs4int_dissect_hardlink_rqst, afs4int_dissect_hardlink_resp} ,
+ { 13, "MakeDir", afs4int_dissect_makedir_rqst, afs4int_dissect_makedir_resp} ,
+ { 14, "RemoveDir", afs4int_dissect_removedir_rqst, afs4int_dissect_removedir_resp} ,
+ { 15, "Readdir", afs4int_dissect_readdir_rqst, afs4int_dissect_readdir_resp} ,
+ { 16, "Lookup", afs4int_dissect_lookup_rqst, afs4int_dissect_lookup_resp} ,
+ { 17, "GetToken", afs4int_dissect_gettoken_rqst, afs4int_dissect_gettoken_resp} ,
+ { 18, "ReleaseTokens", afs4int_dissect_releasetokens_rqst, afs4int_dissect_releasetokens_resp} ,
+ { 19, "GetTime", afs4int_dissect_gettime_rqst, afs4int_dissect_gettime_resp} ,
+ { 20, "MakeMountPoint", afs4int_dissect_makemountpoint_rqst, afs4int_dissect_makemountpoint_resp} ,
+ { 21, "GetStatistics", afs4int_dissect_getstatistics_rqst, afs4int_dissect_getstatistics_resp} ,
+ { 22, "BulkFetchVV", afs4int_dissect_bulkfetchvv_rqst, afs4int_dissect_bulkfetchvv_resp} ,
+ { 23, "BulkKeepAlive", afs4int_dissect_bulkkeepalive_rqst, afs4int_dissect_bulkkeepalive_resp} ,
+ { 24, "ProcessQuota", afs4int_dissect_processquota_rqst, afs4int_dissect_processquota_resp} ,
+ { 25, "GetServerInterfaces", afs4int_dissect_getserverinterfaces_rqst, afs4int_dissect_getserverinterfaces_resp} ,
+ { 26, "SetParams", afs4int_dissect_setparams_rqst, afs4int_dissect_setparams_resp} ,
+ { 27, "BulkFetchStatus", afs4int_dissect_bulkfetchstatus_rqst, afs4int_dissect_bulkfetchstatus_resp} ,
+ { 0, NULL, NULL, NULL}
+ ,
+};
+void
+proto_register_afs4int (void)
+{
+
+
+ static hf_register_info hf[] = {
+ { &hf_error_st, {"AFS4Int Error Status Code", "afs4int.st", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_flags, {"DFS Flags", "afs4int.flags", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_tn_string, {"String ", "afs4int.string", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_tn_size, {"String Size", "afs4int.tn_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_opnum, {"Operation", "afs4int.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL}},
+ { &hf_afs4int_setcontext_rqst_epochtime, {"EpochTime:", "afs4int.setcontext_rqst_epochtime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_setcontext_rqst_secobjectid, { "SetObjectid:", "afs4int.setcontext_secobjextid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL} } ,
+ { &hf_afs4int_setcontext_rqst_clientsizesattrs, { "ClientSizeAttrs:", "afs4int.setcontext_clientsizesattrs", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_setcontext_rqst_parm7, { "Parm7:", "afs4int.setcontext.parm7", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_acl_len, {"Acl Length", "afs4int.acl_len", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_acltype, {"afs4int.acltype", "afs4int.acltype", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_minvvp_high, {"afs4int.minvvp_high", "afs4int.minvvp_high", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_minvvp_low, {"afs4int.minvvp_low", "afs4int.minvvp_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_volume_low, { "afs4int.volume_low", "afs4int.volume_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_volume_high, { "afs4int.volume_high", "afs4int.volume_high", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_vnode, { "afs4int.vnode", "afs4int.vnode", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_unique, { "afs4int.unique", "afs4int.unique", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_accesstime_msec, { "afs4int.accesstime_msec", "afs4int.accesstime_msec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_accesstime_sec, { "afs4int.accesstime_sec", "afs4int.accesstime_sec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_aclexpirationtime, { "afs4int.aclexpirationtime", "afs4int.aclexpirationtime", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_agtypeunique, { "afs4int.agtypeunique", "afs4int.agtypeunique", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_anonymousaccess, { "afs4int.anonymousaccess", "afs4int.anonymousaccess", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_author, { "afs4int.author", "afs4int.author", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_blocksused, { "afs4int.blocksused", "afs4int.blocksused", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} },
+ { &hf_afs4int_calleraccess, { "afs4int.calleraccess", "afs4int.calleraccess", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_changetime_msec, { "afs4int.changetime_msec", "afs4int.changetime_msec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_changetime_sec, { "afs4int.changetime_sec", "afs4int.changetime_sec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_clientspare1, { "afs4int.clientspare1", "afs4int.clientspare1", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_dataversion_high, { "afs4int.dataversion_high", "afs4int.dataversion_high", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_dataversion_low, { "afs4int.dataversion_low", "afs4int.dataversion_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_devicenumber, { "afs4int.devicenumber", "afs4int.devicenumber", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_devicenumberhighbits, { "afs4int.devicenumberhighbits", "afs4int.devicenumberhighbits", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_filetype, { "afs4int.filetype", "afs4int.filetype", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_group, { "afs4int.group", "afs4int.group", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_himaxspare, { "afs4int.himaxspare", "afs4int.himaxspare", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_interfaceversion, { "afs4int.interfaceversion", "afs4int.interfaceversion", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_length_high, { "afs4int.length_high", "afs4int.length_high", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_length_low, { "afs4int.length_low", "afs4int.length_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_linkcount, { "afs4int.linkcount", "afs4int.linkcount", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_lomaxspare, { "afs4int.lomaxspare", "afs4int.lomaxspare", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_mode, { "afs4int.mode", "afs4int.mode", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_modtime_msec, { "afs4int.modtime_msec", "afs4int.modtime_msec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_modtime_sec, { "afs4int.modtime_sec", "afs4int.modtime_sec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_objectuuid, { "afs4int.objectuuid", "afs4int.objectuuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL} } ,
+ { &hf_afs4int_owner, { "afs4int.owner", "afs4int.owner", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_parentunique, { "afs4int.parentunique", "afs4int.parentunique", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_parentvnode, { "afs4int.parentvnode", "afs4int.parentvnode", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_pathconfspare, { "afs4int.pathconfspare", "afs4int.pathconfspare", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_servermodtime_msec, { "afs4int.servermodtime_msec", "afs4int.servermodtime_msec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_servermodtime_sec, { "afs4int.servermodtime_sec", "afs4int.servermodtime_sec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_spare4, { "afs4int.spare4", "afs4int.spare4", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_spare5, { "afs4int.spare5", "afs4int.spare5", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_spare6, { "afs4int.spare6", "afs4int.spare6", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_typeuuid, { "afs4int.typeuuid", "afs4int.typeuuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL} } ,
+ { &hf_afs4int_volid_hi, { "afs4int.volid_hi", "afs4int.volid_hi", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_volid_low, { "afs4int.volid_low", "afs4int.volid_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_vvage, { "afs4int.vvage", "afs4int.vvage", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_vv_hi, { "afs4int.vv_hi", "afs4int.vv_hi", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_vv_low, { "afs4int.vv_low", "afs4int.vv_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_vvpingage, { "afs4int.vvpingage", "afs4int.vvpingage", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_vvspare1, { "afs4int.vvspare1", "afs4int.vvspare1", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_vvspare2, { "afs4int.vvspare2", "afs4int.vvspare2", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_beginrange, { "afs4int.beginrange", "afs4int.beginrange", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_beginrangeext, { "afs4int.beginrangeext", "afs4int.beginrangeext", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_endrange, { "afs4int.endrange", "afs4int.endrange", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_endrangeext, { "afs4int.endrangeext", "afs4int.endrangeext", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_expirationtime, { "afs4int.expirationtime", "afs4int.expirationtime", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_tokenid_hi, { "afs4int.tokenid_hi", "afs4int.tokenid_hi", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_tokenid_low, { "afs4int.tokenid_low", "afs4int.tokenid_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_type_hi, { "afs4int.type_hi", "afs4int.type_hi", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_type_low, { "afs4int.type_low", "afs4int.type_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_tn_length, { "afs4int.tn_length", "afs4int.tn_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_tn_tag, { "afs4int.tn_tag", "afs4int.tn_tag", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_accesstime_sec, { "afs4int.storestatus_accesstime_sec", "afs4int.storestatus_accesstime_sec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_accesstime_usec, { "afs4int.storestatus_accesstime_usec", "afs4int.storestatus_accesstime_usec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_changetime_sec, { "afs4int.storestatus_changetime_sec", "afs4int.storestatus_changetime_sec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_changetime_usec, { "afs4int.storestatus_changetime_usec", "afs4int.storestatus_changetime_usec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_clientspare1, { "afs4int.storestatus_clientspare1", "afs4int.storestatus_clientspare1", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_cmask, { "afs4int.storestatus_cmask", "afs4int.storestatus_cmask", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_devicenumber, { "afs4int.storestatus_devicenumber", "afs4int.storestatus_devicenumber", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_devicenumberhighbits, { "afs4int.storestatus_devicenumberhighbits", "afs4int.storestatus_devicenumberhighbits", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_devicetype, { "afs4int.storestatus_devicetype", "afs4int.storestatus_devicetype", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_group, { "afs4int.storestatus_group", "afs4int.storestatus_group", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_length_high, { "afs4int.storestatus_length_high", "afs4int.storestatus_length_high", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_length_low, { "afs4int.storestatus_length_low", "afs4int.storestatus_length_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_mask, { "afs4int.storestatus_mask", "afs4int.storestatus_mask", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_mode, { "afs4int.storestatus_mode", "afs4int.storestatus_mode", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_modtime_sec, { "afs4int.storestatus_modtime_sec", "afs4int.storestatus_modtime_sec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_modtime_usec, { "afs4int.storestatus_modtime_usec", "afs4int.storestatus_modtime_usec", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_owner, { "afs4int.storestatus_owner", "afs4int.storestatus_owner", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_spare1, { "afs4int.storestatus_spare1", "afs4int.storestatus_spare1", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_spare2, { "afs4int.storestatus_spare2", "afs4int.storestatus_spare2", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_spare3, { "afs4int.storestatus_spare3", "afs4int.storestatus_spare3", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_spare4, { "afs4int.storestatus_spare4", "afs4int.storestatus_spare4", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_spare5, { "afs4int.storestatus_spare5", "afs4int.storestatus_spare5", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_spare6, { "afs4int.storestatus_spare6", "afs4int.storestatus_spare6", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_trunc_high, { "afs4int.storestatus_trunc_high", "afs4int.storestatus_trunc_high", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_trunc_low, { "afs4int.storestatus_trunc_low", "afs4int.storestatus_trunc_low", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_storestatus_typeuuid, { "afs4int.storestatus_typeuuid", "afs4int.storestatus_typeuuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL} } ,
+ { &hf_afs4int_st, { "afs4int.st", "afs4int.st", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_uint, {"afs4int.uint", "afs4int.uint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_afs4int_l_end_pos, { "afs4int.l_end_pos", "afs4int.l_end_pos", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_l_end_pos_ext, { "afs4int.l_end_pos_ext", "afs4int.l_end_pos_ext", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_l_fstype, { "afs4int.l_fstype", "afs4int.l_fstype", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_l_pid, { "afs4int.l_pid", "afs4int.l_pid", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_l_start_pos, { "afs4int.l_start_pos", "afs4int.l_start_pos", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_l_start_pos_ext, { "afs4int.l_start_pos_ext", "afs4int.l_start_pos_ext", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_l_sysid, { "afs4int.l_sysid", "afs4int.l_sysid", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_l_type, { "afs4int.l_type", "afs4int.l_type", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ { &hf_afs4int_l_whence, { "afs4int.l_whence", "afs4int.l_whence", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} } ,
+ {&hf_afsconnparams_mask,
+ {"hf_afsconnparams_mask", "hf_afsconnparams_mask",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_afsconnparams_values,
+ {"hf_afsconnparams_values", "hf_afsconnparams_values",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsFid_cell_high,
+ {"Cell High", "afs4int.afsFid.cell_high", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "afsFid Cell High", HFILL}},
+ {&hf_afs4int_afsFid_cell_low,
+ {"Cell Low", "afs4int.afsFid.cell_low", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "afsFid Cell Low", HFILL}},
+ {&hf_afs4int_afsFid_volume_high,
+ {"Volume High", "afs4int.afsFid.volume_high", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "afsFid Volume High", HFILL}},
+ {&hf_afs4int_afsFid_volume_low,
+ {"Volume Low", "afs4int.afsFid.volume_low", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "afsFid Volume Low", HFILL}},
+ {&hf_afs4int_afsFid_Vnode,
+ {"Vnode", "afs4int.afsFid.Vnode", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "afsFid Vnode", HFILL}},
+ {&hf_afs4int_afsFid_Unique,
+ {"Unique", "afs4int.afsFid.Unique", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "afsFid Unique", HFILL}},
+ {&hf_afs4int_afsNetAddr_type,
+ {"Type", "afsNetAddr.type", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsNetAddr_data,
+ {"IP Data", "afsNetAddr.data", FT_UINT8, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_afs4int_position_high,
+ {"Position High", "afs4int.position_high", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ {&hf_afs4int_position_low,
+ {"Position Low", "afs4int.position_low", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ {&hf_afs4int_afsreturndesc_tokenid_high,
+ {"Tokenid High", "afs4int.afsreturndesc_tokenid_high", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsreturndesc_tokenid_low,
+ {"Tokenid low", "afs4int.afsreturndesc_tokenid_low", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsreturndesc_type_high,
+ {"Type high", "afs4int.type_high", FT_UINT32, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ {&hf_afs4int_afsreturndesc_type_low,
+ {"Type low", "afs4int.type_low", FT_UINT32, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ {&hf_afs4int_offsetp_high,
+ {"offset high", "afs4int.offset_high", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ {&hf_afs4int_offsetp_low,
+ {"offset high", "afs4int.offset_high", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ {&hf_afs4int_nextoffsetp_high,
+ {"next offset high", "afs4int.nextoffset_high", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_nextoffsetp_low,
+ {"next offset low", "afs4int.nextoffset_low", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ {&hf_afs4int_returntokenidp_high,
+ {"return token idp high", "afs4int.returntokenidp_high", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_returntokenidp_low,
+ {"return token idp low", "afs4int.returntokenidp_low", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_cellidp_high,
+ {"cellidp high", "afs4int.cellidp_high", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ {&hf_afs4int_cellidp_low,
+ {"cellidp low", "afs4int.cellidp_low", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ {&hf_afserrorstatus_st,
+ {"AFS Error Code", "afs4int.afserrortstatus_st", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_length,
+ {"Length", "afs4int.length", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsTaggedPath_tp_chars,
+ {"AFS Tagged Path", "afs4int.TaggedPath_tp_chars", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsTaggedPath_tp_tag,
+ {"AFS Tagged Path Name", "afs4int.TaggedPath_tp_tag", FT_UINT32,
+ BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsacl_uuid1,
+ {"AFS ACL UUID1", "afs4int.afsacl_uuid1", FT_STRING, BASE_NONE,
+ NULL, 0x0, "UUID", HFILL}},
+ {&hf_afs4int_bulkfetchstatus_size,
+ {"BulkFetchStatus Size", "afs4int.bulkfetchstatus_size", FT_UINT32,
+ BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_bulkfetchvv_numvols,
+ {"afs4int.bulkfetchvv_numvols", "afs4int.bulkfetchvv_numvols",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_bulkfetchvv_spare1,
+ {"afs4int.bulkfetchvv_spare1", "afs4int.bulkfetchvv_spare1",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_bulkfetchvv_spare2,
+ {"afs4int.bulkfetchvv_spare2", "afs4int.bulkfetchvv_spare2",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_bulkkeepalive_numexecfids, {"BulkKeepAlive numexecfids", "afs4int.bulkkeepalive_numexecfids", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_bulkkeepalive_spare4,
+ {"BulkKeepAlive spare4", "afs4int.bulkfetchkeepalive_spare2",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_bulkkeepalive_spare2,
+ {"BulkKeepAlive spare2", "afs4int.bulkfetchkeepalive_spare2",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_bulkkeepalive_spare1,
+ {"BulkFetch KeepAlive spare1", "afs4int.bulkfetchkeepalive_spare1",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsacl_defaultcell_uuid,
+ {"Default Cell UUID",
+ "afs4int.defaultcell_uuid", FT_STRING, BASE_NONE, NULL, 0x0,
+ "UUID", HFILL}},
+ {&hf_afs4int_afsuuid_uuid,
+ {"AFS UUID",
+ "afs4int.uuid", FT_STRING, BASE_NONE, NULL, 0x0,
+ "UUID", HFILL}},
+ {&hf_afs4int_gettime_syncdispersion,
+ {"GetTime Syncdispersion",
+ "afs4int.gettime_syncdispersion", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ {&hf_afs4int_gettime_syncdistance,
+ {"SyncDistance", "afs4int.gettime.syncdistance",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_gettime_usecondsp,
+ {"GetTime usecondsp", "afs4int.gettime_usecondsp",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_readdir_size,
+ {"Readdir Size", "afs4int.readdir.size", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsNameString_t_principalName_size,
+ {"Principal Name Size",
+ "afs4int.principalName_size", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsNameString_t_principalName_size2,
+ {"Principal Name Size2",
+ "afs4int.principalName_size2", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ {&hf_afs4int_afsTaggedPath_tp_length,
+ {"Tagged Path Length",
+ "afs4int.afsTaggedPath_length", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ {&hf_afs4int_fstype,
+ {"Filetype", "afs4int.fstype", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ {&hf_afs4int_gettime_secondsp,
+ {"GetTime secondsp", "afs4int.gettime_secondsp", FT_UINT32,
+ BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ {&hf_afs4int_afsNameString_t_principalName_string,
+ {"Principal Name", "afs4int.NameString_principal", FT_STRING,
+ BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ {&hf_afs4int_fetchdata_pipe_t_size,
+ {"FetchData Pipe_t size", "afs4int.fetchdata_pipe_t_size", FT_STRING,
+ BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ };
+ static gint *ett[] = {
+ &ett_afs4int,
+ &ett_afs4int_afsReturnDesc,
+ &ett_afs4int_afsFid,
+ &ett_afs4int_afsNetAddr,
+ &ett_afs4int_fetchstatus,
+ &ett_afs4int_afsflags,
+ &ett_afs4int_volsync,
+ &ett_afs4int_minvvp,
+ &ett_afs4int_afsfidtaggedname,
+ &ett_afs4int_afstaggedname,
+ &ett_afs4int_afstoken,
+ &ett_afs4int_afsstorestatus,
+ &ett_afs4int_afsRecordLock,
+ &ett_afs4int_afsAcl,
+ &ett_afs4int_afsNameString_t,
+ &ett_afs4int_afsConnParams,
+ &ett_afs4int_afsErrorStatus,
+ &ett_afs4int_afsTaggedPath,
+ &ett_afs4int_afsNetData,
+ &ett_afs4int_afsBulkStat,
+ &ett_afs4int_afsuuid,
+ &ett_afs4int_offsetp,
+ &ett_afs4int_returntokenidp,
+ &ett_afs4int_afsbundled_stat,
+ };
+ proto_afs4int = proto_register_protocol ("DFS Calls", "DCE_DFS", "dce_dfs");
+ proto_register_field_array (proto_afs4int, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_afs4int (void)
+{
+ /*
+ * Register the protocol as dcerpc
+ */
+ dcerpc_init_uuid (proto_afs4int, ett_afs4int, &uuid_afs4int, ver_afs4int,
+ afs4int_dissectors, hf_afs4int_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-atsvc.c b/epan/dissectors/packet-dcerpc-atsvc.c
new file mode 100644
index 0000000000..5fb8b99262
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-atsvc.c
@@ -0,0 +1,682 @@
+/* packet-dcerpc-atsvc.c
+ * Routines for SMB \pipe\atsvc packet disassembly
+ * Copyright 2003 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-atsvc.h"
+#include "smb.h"
+
+
+static int proto_dcerpc_atsvc = -1;
+
+static int hf_atsvc_server = -1;
+static int hf_atsvc_command = -1;
+static int hf_atsvc_opnum = -1;
+static int hf_atsvc_rc = -1;
+static int hf_atsvc_job_id = -1;
+static int hf_atsvc_job_time = -1;
+static int hf_atsvc_job_days_of_month = -1;
+static int hf_atsvc_job_days_of_week = -1;
+static int hf_atsvc_job_flags = -1;
+static int hf_atsvc_min_job_id = -1;
+static int hf_atsvc_max_job_id = -1;
+static int hf_atsvc_job_flags_noninteractive = -1;
+static int hf_atsvc_job_flags_add_current_date = -1;
+static int hf_atsvc_job_flags_runs_today = -1;
+static int hf_atsvc_job_flags_exec_error = -1;
+static int hf_atsvc_job_flags_run_periodically = -1;
+static int hf_atsvc_job_enum_hnd = -1;
+static int hf_atsvc_jobs_count = -1;
+static int hf_atsvc_enum_handle = -1;
+static int hf_atsvc_pref_max = -1;
+static int hf_atsvc_num_entries = -1;
+static int hf_atsvc_total_entries = -1;
+
+static gint ett_dcerpc_atsvc = -1;
+static gint ett_dcerpc_atsvc_job = -1;
+static gint ett_dcerpc_atsvc_job_flags = -1;
+
+
+/*
+IDL [ uuid(1ff70682-0a51-30e8-076d-740be8cee98b),
+IDL version(1.0),
+IDL implicit_handle(handle_t rpc_binding)
+IDL ] interface atsvc
+*/
+
+
+static e_uuid_t uuid_dcerpc_atsvc = {
+ 0x1ff70682, 0x0a51, 0x30e8,
+ { 0x07, 0x6d, 0x74, 0x0b, 0xe8, 0xce, 0xe9, 0x8b }
+};
+
+static guint16 ver_dcerpc_atsvc = 1;
+
+
+/*
+ IDL typedef struct {
+ IDL long JobTime;
+ IDL long DaysOfMonth;
+ IDL char DaysOfWeek;
+ IDL char Flags;
+ IDL [unique] [string] wchar_t *Command;
+ IDL } AT_INFO;
+ */
+
+static int
+atsvc_dissect_AT_INFO_fields(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *flags_tree = NULL;
+ guint32 job_time;
+ guint8 job_flags;
+ guint8 job_hour, job_min, job_sec;
+ guint16 job_msec;
+ dcerpc_info *di = (dcerpc_info *) pinfo->private_data;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ 0, &job_time);
+
+ job_hour = job_time / 3600000;
+ job_min = (job_time - job_hour * 3600000) / 60000;
+ job_sec = (job_time - (job_hour * 3600000) - (job_min * 60000)) / 1000;
+ job_msec = (job_time - (job_hour * 3600000) - (job_min * 60000) - (job_sec * 1000));
+
+ proto_tree_add_uint_format(tree, hf_atsvc_job_time, tvb, offset - 4,
+ 4, job_time, "Time: %02d:%02d:%02d:%03d", job_hour, job_min, job_sec, job_msec);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_job_days_of_month, NULL);
+
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_job_days_of_week, NULL);
+
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, NULL, drep,
+ 0, &job_flags);
+
+ item = proto_tree_add_text(tree, tvb, offset-1, 1, "Flags: 0x%02x", job_flags);
+ flags_tree = proto_item_add_subtree(item, ett_dcerpc_atsvc_job_flags);
+
+ if (flags_tree) {
+
+#define JOB_RUN_PERIODICALLY 0x01
+#define JOB_EXEC_ERROR 0x02
+#define JOB_RUNS_TODAY 0x04
+#define JOB_ADD_CURRENT_DATE 0x08
+#define JOB_NONINTERACTIVE 0x10
+
+ if (di->call_data->opnum == ATSVC_JOB_ADD) {
+
+ if (job_flags & JOB_RUN_PERIODICALLY) {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_run_periodically,
+ tvb, offset-1, 1, job_flags);
+ }
+ else {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_run_periodically,
+ tvb, offset-1, 1, 0);
+ }
+
+
+ if (job_flags & JOB_ADD_CURRENT_DATE) {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_add_current_date,
+ tvb, offset-1, 1, job_flags);
+ }
+ else {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_add_current_date,
+ tvb, offset-1, 1, 0);
+ }
+
+
+ if (job_flags & JOB_NONINTERACTIVE) {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_noninteractive,
+ tvb, offset-1, 1, job_flags);
+ }
+ else {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_noninteractive,
+ tvb, offset-1, 1, job_flags);
+ }
+
+ }
+
+ if ((di->call_data->opnum == ATSVC_JOB_GETINFO)
+ || (di->call_data->opnum == ATSVC_JOB_ENUM)) {
+
+
+ if (job_flags & JOB_RUN_PERIODICALLY) {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_run_periodically,
+ tvb, offset-1, 1, job_flags);
+ }
+ else {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_run_periodically,
+ tvb, offset-1, 1, 0);
+ }
+
+
+ if (job_flags & JOB_EXEC_ERROR) {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_exec_error,
+ tvb, offset-1, 1, job_flags);
+ }
+ else {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_exec_error,
+ tvb, offset-1, 1, 0);
+ }
+
+
+ if (job_flags & JOB_RUNS_TODAY) {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_runs_today,
+ tvb, offset-1, 1, job_flags);
+ }
+ else {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_runs_today,
+ tvb, offset-1, 1, 0);
+ }
+
+ if (job_flags & JOB_NONINTERACTIVE) {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_noninteractive,
+ tvb, offset-1, 1, job_flags);
+ }
+ else {
+ proto_tree_add_boolean(flags_tree, hf_atsvc_job_flags_noninteractive,
+ tvb, offset-1, 1, job_flags);
+ }
+
+ }
+
+ }
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Command", hf_atsvc_command, 0);
+
+ return offset;
+}
+
+static int
+atsvc_dissect_AT_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, -1, "Job");
+ subtree = proto_item_add_subtree(item, ett_dcerpc_atsvc_job);
+ }
+
+ offset = atsvc_dissect_AT_INFO_fields(tvb, offset, pinfo, subtree, drep);
+
+ return offset;
+}
+
+
+
+/*
+ IDL long NetrJobAdd(
+ IDL [in] [unique] [string] wchar_t *Servername,
+ IDL [in] [ref] AT_INFO *element_22,
+ IDL [out] [ref] long *JobId
+ IDL );
+ */
+
+static int
+atsvc_dissect_add_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_atsvc_server, 0);
+
+ offset = atsvc_dissect_AT_INFO(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+atsvc_dissect_add_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_job_id, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long NetrJobDel(
+ IDL [in] [unique] [string] wchar_t *Servername,
+ IDL [in] long MinJobId,
+ IDL [in] long MaxJobId,
+ IDL );
+ */
+
+static int
+atsvc_dissect_del_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_atsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_min_job_id, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_max_job_id, NULL);
+
+ return offset;
+}
+
+static int
+atsvc_dissect_del_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_rc, NULL);
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL long JobId;
+ IDL long JobTime;
+ IDL long DaysOfMonth;
+ IDL char DaysOfWeek;
+ IDL char Flags;
+ IDL [unique] [string] wchar_t *Command;
+ IDL } AT_ENUM;
+ */
+
+static int
+atsvc_dissect_AT_ENUM(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+ guint32 job_id;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ 0, &job_id);
+
+ if (tree) {
+ item = proto_tree_add_text(tree, tvb, offset, -1, "Job %d", job_id);
+ subtree = proto_item_add_subtree(item, ett_dcerpc_atsvc_job);
+ }
+
+ proto_tree_add_uint_format(subtree, hf_atsvc_job_id, tvb, offset - 4,
+ 4, job_id, "Job ID: %d", job_id);
+
+ offset = atsvc_dissect_AT_INFO_fields(tvb, offset, pinfo, subtree, drep);
+
+ return offset;
+}
+
+
+static int
+atsvc_dissect_ENUM_HANDLE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_enum_handle, 0);
+ return offset;
+
+}
+
+static int
+atsvc_dissect_AT_ENUM_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ atsvc_dissect_AT_ENUM);
+
+ return offset;
+}
+
+/*
+ IDL typedef struct {
+ IDL long EntriesRead;
+ IDL [size_is(EntriesRead)] [unique] AT_ENUM *first_entry;
+ IDL } AT_ENUM_CONTAINER;
+ */
+
+static int
+atsvc_dissect_AT_ENUM_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ atsvc_dissect_AT_ENUM_array, NDR_POINTER_UNIQUE,
+ "AT_ENUM array:", -1);
+
+ return offset;
+}
+
+
+/*
+ IDL long NetrJobEnum(
+ IDL [in] [unique] [string] wchar_t *Servername,
+ IDL [in,out] [ref] AT_ENUM_CONTAINER *PointerToBuffer,
+ IDL [in] long PreferredMaximumLength,
+ IDL [out] [ref] long *TotalEntries,
+ IDL [in,out] [unique] long *ResumeHandle
+ IDL );
+ */
+
+static int
+atsvc_dissect_enum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_atsvc_server, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ atsvc_dissect_AT_ENUM_CONTAINER,
+ NDR_POINTER_REF, "Job list", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_pref_max, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ atsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+
+static int
+atsvc_dissect_enum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ atsvc_dissect_AT_ENUM_CONTAINER,
+ NDR_POINTER_REF, "Job list", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_total_entries, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ atsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long NetrJobGetInfo(
+ IDL [in] [unique] [string] wchar_t *Servername,
+ IDL [in] long JobId,
+ IDL [out] [ref] AT_INFO **PointerToBuffer
+ IDL );
+ */
+
+static int
+atsvc_dissect_getinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_atsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_job_id, NULL);
+
+ return offset;
+}
+
+static int
+atsvc_dissect_getinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ atsvc_dissect_AT_INFO, NDR_POINTER_UNIQUE,
+ "Job info", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_atsvc_rc, NULL);
+
+ return offset;
+}
+
+static dcerpc_sub_dissector dcerpc_atsvc_dissectors[] = {
+ { ATSVC_JOB_ADD, "NetrJobAdd", atsvc_dissect_add_rqst, atsvc_dissect_add_reply },
+ { ATSVC_JOB_DEL, "NetrJobDel", atsvc_dissect_del_rqst, atsvc_dissect_del_reply },
+ { ATSVC_JOB_ENUM, "NetrJobEnum", atsvc_dissect_enum_rqst, atsvc_dissect_enum_reply },
+ { ATSVC_JOB_GETINFO, "NetrJobGetInfo", atsvc_dissect_getinfo_rqst, atsvc_dissect_getinfo_reply },
+ { 0, NULL, NULL, NULL }
+};
+
+static const value_string atsvc_job_day_of_month[] = {
+ { 0x00, "n/a" },
+ { 0x01, "01" },
+ { 0x02, "02" },
+ { 0x04, "03" },
+ { 0x08, "04" },
+ { 0x10, "05" },
+ { 0x20, "06" },
+ { 0x40, "07" },
+ { 0x80, "08" },
+ { 0x100, "09" },
+ { 0x200, "10" },
+ { 0x400, "11" },
+ { 0x800, "12" },
+ { 0x1000, "13" },
+ { 0x2000, "14" },
+ { 0x4000, "15" },
+ { 0x8000, "16" },
+ { 0x10000, "17" },
+ { 0x20000, "18" },
+ { 0x40000, "19" },
+ { 0x80000, "20" },
+ { 0x100000, "21" },
+ { 0x200000, "22" },
+ { 0x400000, "23" },
+ { 0x800000, "24" },
+ { 0x1000000, "25" },
+ { 0x2000000, "26" },
+ { 0x4000000, "27" },
+ { 0x8000000, "28" },
+ { 0x10000000, "29" },
+ { 0x20000000, "30" },
+ { 0x40000000, "31" },
+ { 0, NULL }
+};
+
+
+
+static const value_string atsvc_job_day_of_week[] = {
+ { 0x00, "n/a" },
+ { 0x01, "Monday" },
+ { 0x02, "Tuesday" },
+ { 0x04, "Wednesday" },
+ { 0x08, "Thursday" },
+ { 0x10, "Friday" },
+ { 0x20, "Saturday" },
+ { 0x40, "Sunday" },
+ { 0, NULL }
+};
+
+static const true_false_string tfs_job_flags_type = {
+ "Job runs periodically",
+ "Job runs once"
+};
+
+static const true_false_string tfs_job_flags_exec_error = {
+ "Last job execution FAILED",
+ "Last job execution was successful"
+};
+
+static const true_false_string tfs_job_flags_runs_today = {
+ "Job is scheduled to execute today",
+ "Job is NOT scheduled to execute today"
+};
+
+static const true_false_string tfs_job_flags_add_current_date = {
+ "Job is scheduled relative to current day of month",
+ "Job is NOT scheduled relative to current day of month"
+};
+
+static const true_false_string tfs_job_flags_noninteractive = {
+ "Job is NOT interactive",
+ "Job is interactive"
+};
+
+void
+proto_register_dcerpc_atsvc(void)
+{
+
+ static hf_register_info hf[] = {
+
+ { &hf_atsvc_server,
+ { "Server", "atsvc.server", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Server Name", HFILL}},
+
+ { &hf_atsvc_command,
+ { "Command", "atsvc.command", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Command to execute", HFILL}},
+
+ { &hf_atsvc_opnum,
+ { "Operation", "atsvc.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ {&hf_atsvc_rc,
+ { "Return code", "atsvc.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "atsvc status code", HFILL }},
+
+ { &hf_atsvc_job_id,
+ { "Job ID", "atsvc.job_id", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Job ID", HFILL}},
+
+ { &hf_atsvc_job_time,
+ { "Job time", "atsvc.job_time", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Job time", HFILL}},
+
+ { &hf_atsvc_job_days_of_month,
+ { "Job day of the month", "atsvc.job_day_of_month", FT_UINT32,
+ BASE_DEC, VALS(atsvc_job_day_of_month), 0x0, "Job day of the month", HFILL}},
+
+ { &hf_atsvc_job_days_of_week,
+ { "Job day of the week", "atsvc.job_day_of_week", FT_UINT8,
+ BASE_DEC, VALS(atsvc_job_day_of_week), 0x0, "Job day of the week", HFILL}},
+
+ { &hf_atsvc_job_flags,
+ { "Job flags", "atsvc.job_flags", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "Job flags", HFILL}},
+
+ { &hf_atsvc_min_job_id,
+ { "Min job ID", "atsvc.min_id", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Min job ID", HFILL}},
+
+ { &hf_atsvc_max_job_id,
+ { "Max job ID", "atsvc.max_id", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Max job ID", HFILL}},
+
+ { &hf_atsvc_job_flags_run_periodically,
+ { "Job type", "atsvc.jobs.flags.type", FT_BOOLEAN, 8,
+ TFS(&tfs_job_flags_type), JOB_RUN_PERIODICALLY, "Job type", HFILL }},
+
+ { &hf_atsvc_job_flags_exec_error,
+ { "Last job execution status", "atsvc.jobs.flags.exec_error", FT_BOOLEAN, 8,
+ TFS(&tfs_job_flags_exec_error), JOB_EXEC_ERROR, "Last job execution status", HFILL }},
+
+ { &hf_atsvc_job_flags_runs_today,
+ { "Job schedule", "atsvc.jobs.flags.runs_today", FT_BOOLEAN, 8,
+ TFS(&tfs_job_flags_runs_today), JOB_RUNS_TODAY, "Job schedule", HFILL }},
+
+ { &hf_atsvc_job_flags_add_current_date,
+ { "Job relative to current day of month", "atsvc.jobs.flags.add_current_date", FT_BOOLEAN, 8,
+ TFS(&tfs_job_flags_add_current_date), JOB_ADD_CURRENT_DATE, "Job relative to current day of month", HFILL }},
+
+ { &hf_atsvc_job_flags_noninteractive,
+ { "Job interactive status", "atsvc.jobs.flags.noninteractive", FT_BOOLEAN, 8,
+ TFS(&tfs_job_flags_noninteractive), JOB_NONINTERACTIVE, "Job interactive status", HFILL }},
+
+ { &hf_atsvc_job_enum_hnd,
+ { "Handle", "atsvc.job.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "Context handle", HFILL }},
+
+ { &hf_atsvc_jobs_count,
+ { "Jobs count", "atsvc.jobs_count", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of jobs", HFILL}},
+
+ { &hf_atsvc_enum_handle,
+ { "Enumeration handle", "atsvc.enum_hnd", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "Enumeration Handle", HFILL}},
+
+ { &hf_atsvc_pref_max,
+ { "Preferred max length", "atsvc.pref.max.len", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Preferred max length", HFILL}},
+
+ { &hf_atsvc_num_entries,
+ { "Returned entries", "atsvc.num.entries", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Number of returned entries", HFILL}},
+
+ { &hf_atsvc_total_entries,
+ { "Total entries", "atsvc.total.entries", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Total number of available entries", HFILL}},
+
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_atsvc,
+ &ett_dcerpc_atsvc_job,
+ &ett_dcerpc_atsvc_job_flags
+ };
+
+
+ proto_dcerpc_atsvc = proto_register_protocol(
+ "Microsoft Task Scheduler Service", "ATSVC", "atsvc");
+
+ proto_register_field_array(proto_dcerpc_atsvc, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+void
+proto_reg_handoff_dcerpc_atsvc(void)
+{
+ /* register protocol as dcerpc */
+
+ dcerpc_init_uuid(
+ proto_dcerpc_atsvc, ett_dcerpc_atsvc, &uuid_dcerpc_atsvc,
+ ver_dcerpc_atsvc, dcerpc_atsvc_dissectors, hf_atsvc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-atsvc.h b/epan/dissectors/packet-dcerpc-atsvc.h
new file mode 100644
index 0000000000..b5e79659be
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-atsvc.h
@@ -0,0 +1,39 @@
+/* packet-dcerpc-atsvc.h
+ * Routines for SMB \pipe\atsvc packet disassembly
+ * Copyright 2003 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_ATSVC_H
+#define __PACKET_DCERPC_ATSVC_H
+
+/* MSRPC functions available in the atsvc interface */
+
+#define ATSVC_JOB_ADD 0x00
+#define ATSVC_JOB_DEL 0x01
+#define ATSVC_JOB_ENUM 0x02
+#define ATSVC_JOB_GETINFO 0x03
+
+#endif /* packet-dcerpc-atsvc.h */
+
+
+
diff --git a/epan/dissectors/packet-dcerpc-bossvr.c b/epan/dissectors/packet-dcerpc-bossvr.c
new file mode 100644
index 0000000000..ea13a37ab1
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-bossvr.c
@@ -0,0 +1,116 @@
+/* packet-dcerpc-bossvr.c
+ *
+ * Routines for dcerpc bossvr dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz file/bosserver/bbos_ncs_interface.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_bossvr = -1;
+static int hf_bossvr_opnum = -1;
+
+
+static gint ett_bossvr = -1;
+
+
+static e_uuid_t uuid_bossvr = { 0x4d37f2dd, 0xed43, 0x0000, { 0x02, 0xc0, 0x37, 0xcf, 0x1e, 0x00, 0x00, 0x01 } };
+static guint16 ver_bossvr = 0;
+
+
+static dcerpc_sub_dissector bossvr_dissectors[] = {
+ { 0, "GetServerStatus", NULL, NULL},
+ { 1, "CreateBnode", NULL, NULL},
+ { 2, "DeleteBnode", NULL, NULL},
+ { 3, "SetStatus", NULL, NULL},
+ { 4, "GetStatus", NULL, NULL},
+ { 5, "EnumerateInstance", NULL, NULL},
+ { 6, "GetInstanceInfo", NULL, NULL},
+ { 7, "GetInstanceParm", NULL, NULL},
+ { 8, "AddSUser", NULL, NULL},
+ { 9, "DeleteSUser", NULL, NULL},
+ { 10, "ListSUsers", NULL, NULL},
+ { 11, "ListKeys", NULL, NULL},
+ { 12, "AddKey", NULL, NULL},
+ { 13, "DeleteKey", NULL, NULL},
+ { 14, "GenerateKey", NULL, NULL},
+ { 15, "GarbageCollectKeys", NULL, NULL},
+ { 16, "GetCellName", NULL, NULL},
+ { 17, "SetTStatus", NULL, NULL},
+ { 18, "ShutdownAll", NULL, NULL},
+ { 19, "RestartAll", NULL, NULL},
+ { 20, "StartupAll", NULL, NULL},
+ { 21, "SetNoAuthFlag", NULL, NULL},
+ { 22, "ReBossvr", NULL, NULL},
+ { 23, "Restart", NULL, NULL},
+ { 24, "Install", NULL, NULL},
+ { 25, "UnInstall", NULL, NULL},
+ { 26, "GetDates", NULL, NULL},
+ { 27, "Prune", NULL, NULL},
+ { 28, "SetRestartTime", NULL, NULL},
+ { 29, "GetRestartTime", NULL, NULL},
+ { 30, "GetLog", NULL, NULL},
+ { 31, "WaitAll", NULL, NULL},
+ { 32, "SetDebug", NULL, NULL},
+ { 33, "GetServerInterfaces", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_bossvr (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_bossvr_opnum,
+ { "Operation", "bossvr.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_bossvr,
+ };
+ proto_bossvr = proto_register_protocol ("DCE/RPC BOS Server", "BOSSVR", "bossvr");
+ proto_register_field_array (proto_bossvr, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_bossvr (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_bossvr, ett_bossvr, &uuid_bossvr, ver_bossvr, bossvr_dissectors, hf_bossvr_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-browser.c b/epan/dissectors/packet-dcerpc-browser.c
new file mode 100644
index 0000000000..3a4e4156f3
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-browser.c
@@ -0,0 +1,1181 @@
+/* packet-dcerpc-browser.c
+ * Routines for DCERPC Browser packet disassembly
+ * Copyright 2001, Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* The IDL file for this interface can be extracted by grepping for idl
+ * in capitals.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-browser.h"
+#include "packet-dcerpc-nt.h"
+#include "smb.h"
+
+static int proto_dcerpc_browser = -1;
+static int hf_browser_opnum = -1;
+static int hf_browser_rc = -1;
+static int hf_browser_unknown_long = -1;
+static int hf_browser_unknown_hyper = -1;
+static int hf_browser_unknown_bytes = -1;
+static int hf_browser_unknown_string = -1;
+
+
+static gint ett_dcerpc_browser = -1;
+
+
+static int
+dissect_browser_long_pointer(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ return offset;
+}
+
+
+
+/*
+ IDL [ uuid(6bffd098-a112-3610-9833-012892020162),
+ IDL version(0.0),
+ IDL implicit_handle(handle_t rpc_binding)
+ IDL ] interface browser
+ IDL {
+*/
+
+static e_uuid_t uuid_dcerpc_browser = {
+ 0x6bffd098, 0xa112, 0x3610,
+ { 0x98, 0x33, 0x01, 0x28, 0x92, 0x02, 0x01, 0x62 }
+};
+
+static guint16 ver_dcerpc_browser = 0;
+
+
+/*
+ IDL typedef struct {
+ IDL long element_7;
+ IDL [size_is(element_7)] [unique] byte *element_8;
+ IDL } TYPE_4;
+*/
+static int
+dissect_browser_TYPE_4_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* this call is to make ethereal eat the array header for the conformant run */
+ offset =dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, NULL);
+
+ return offset;
+ }
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, &len);
+
+ proto_tree_add_item(tree, hf_browser_unknown_bytes, tvb, offset, len,
+ FALSE);
+ offset += len;
+
+ return len;
+}
+static int
+dissect_browser_TYPE_4(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_4_data, NDR_POINTER_UNIQUE,
+ "unknown TYPE_4", -1);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL long element_5;
+ IDL [size_is(element_5)] [unique] byte *element_6;
+ IDL } TYPE_3;
+*/
+static int
+dissect_browser_TYPE_3_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* this call is to make ethereal eat the array header for the conformant run */
+ offset =dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, NULL);
+
+ return offset;
+ }
+
+ /* this is really the length of the encoded data */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, &len);
+ proto_tree_add_item(tree, hf_browser_unknown_bytes, tvb, offset, len,
+ FALSE);
+ offset += len;
+
+ return len;
+}
+static int
+dissect_browser_TYPE_3(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_3_data, NDR_POINTER_UNIQUE,
+ "unknown TYPE_3", -1);
+
+ return offset;
+}
+
+
+
+/*
+ IDL typedef [switch_type(long)] union {
+ IDL [case(100)] [unique] TYPE_3 *element_3;
+ IDL [case(101)] [unique] TYPE_4 *element_4;
+ IDL } TYPE_2;
+*/
+static int
+dissect_browser_TYPE_2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ /* this is really the union switch arm */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, &level);
+
+ ALIGN_TO_4_BYTES;
+
+ switch(level){
+ case 100:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_3, NDR_POINTER_UNIQUE,
+ "unknown TYPE_3", -1);
+ break;
+ case 101:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_4, NDR_POINTER_UNIQUE,
+ "unknown TYPE_4", -1);
+ break;
+ }
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL long element_1;
+ IDL TYPE_2 element_2;
+ IDL } TYPE_1;
+*/
+static int
+dissect_browser_TYPE_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_browser_TYPE_2(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+
+/*
+ IDL long BrowserrServerEnum(
+ IDL [in] [unique] [string] wchar_t *element_9,
+ IDL [in] [unique] [string] wchar_t *element_10,
+ IDL [in] [unique] [string] wchar_t *element_11,
+ IDL [in,out] [ref] TYPE_1 *element_12,
+ IDL [in] long element_13,
+ IDL [out] long element_14,
+ IDL [in] long element_15,
+ IDL [in] [unique] [string] wchar_t *element_16,
+ IDL [in,out] [unique] long *element_17
+ IDL );
+*/
+static int
+dissect_browser_browserr_server_enum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_1, NDR_POINTER_REF,
+ "unknown TYPE_1", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_long_pointer, NDR_POINTER_UNIQUE,
+ "unknown long", hf_browser_unknown_long);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_server_enum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_1, NDR_POINTER_REF,
+ "unknown TYPE_1", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_long_pointer, NDR_POINTER_UNIQUE,
+ "unknown long", hf_browser_unknown_long);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+/*
+ IDL long BrowserrDebugCall(
+ IDL [in] [unique] [string] wchar_t *element_18,
+ IDL [in] long element_19,
+ IDL [in] long element_20
+ IDL );
+*/
+static int
+dissect_browser_browserr_debug_call_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_debug_call_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long BrowserrQueryOtherDomains(
+ IDL [in] [unique] [string] wchar_t *element_21,
+ IDL [in,out] [ref] TYPE_1 *element_22,
+ IDL [out] long element_23
+ IDL );
+*/
+static int
+dissect_browser_browserr_query_other_domains_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_1, NDR_POINTER_REF,
+ "unknown TYPE_1", -1);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_query_other_domains_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long BrowserrResetNetlogonState(
+ IDL [in] [unique] [string] wchar_t *element_24
+ IDL );
+*/
+static int
+dissect_browser_browserr_reset_netlogon_state_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_reset_netlogon_state_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long BrowserrDebugTrace(
+ IDL [in] [unique] [string] wchar_t *element_25,
+ IDL [in] [string] char element_26
+ IDL );
+*/
+static int
+dissect_browser_browserr_debug_trace_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_debug_trace_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+ IDL typedef struct {
+ IDL TYPE_6 element_27;
+ IDL TYPE_6 element_28;
+ IDL TYPE_6 element_29;
+ IDL long element_30;
+ IDL long element_31;
+ IDL long element_32;
+ IDL long element_33;
+ IDL long element_34;
+ IDL long element_35;
+ IDL long element_36;
+ IDL long element_37;
+ IDL long element_38;
+ IDL long element_39;
+ IDL long element_40;
+ IDL long element_41;
+ IDL long element_42;
+ IDL long element_43;
+ IDL long element_44;
+ IDL TYPE_6 element_45;
+ IDL } TYPE_5;
+ IDL
+ IDL typedef struct {
+ IDL hyper element_46;
+ IDL } TYPE_6;
+*/
+static int
+dissect_browser_TYPE_5(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_hyper, NULL);
+
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_hyper, NULL);
+
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_hyper, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_hyper, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long BrowserrQueryStatistics(
+ IDL [in] [unique] [string] wchar_t *element_47,
+ IDL [out] [ref] TYPE_5 **element_48
+ IDL );
+*/
+static int
+dissect_browser_browserr_query_statistics_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_query_statistics_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_5, NDR_POINTER_UNIQUE,
+ "unknown TYPE_5", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long BrowserrResetStatistics(
+ IDL [in] [unique] [string] wchar_t *element_49
+ IDL );
+*/
+static int
+dissect_browser_browserr_reset_statistics_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_reset_statistics_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long NetrBrowserStatisticsClear(
+ IDL [in] [unique] [string] wchar_t *element_49
+ IDL );
+*/
+static int
+dissect_browser_netr_browser_statistics_clear_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ return offset;
+}
+static int
+dissect_browser_netr_browser_statistics_clear_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL TYPE_6 element_59;
+ IDL TYPE_6 element_60;
+ IDL TYPE_6 element_61;
+ IDL long element_62;
+ IDL long element_63;
+ IDL long element_64;
+ IDL TYPE_6 element_65;
+ IDL long element_66;
+ IDL long element_67;
+ IDL long element_68;
+ IDL long element_69;
+ IDL long element_70;
+ IDL long element_71;
+ IDL long element_72;
+ IDL long element_73;
+ IDL long element_74;
+ IDL } TYPE_11;
+*/
+static int
+dissect_browser_TYPE_11(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_hyper, NULL);
+
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_hyper, NULL);
+
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_hyper, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_hyper, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ return offset;
+}
+
+/*
+ IDL typedef struct {
+ IDL long element_57;
+ IDL [size_is(element_57)] [unique] TYPE_11 *element_58;
+ IDL } TYPE_10;
+*/
+static int
+dissect_browser_TYPE_11_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_11);
+
+ return offset;
+}
+
+static int
+dissect_browser_TYPE_10(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_11_array, NDR_POINTER_UNIQUE,
+ "unknown TYPE_11_ARRAY", -1);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL long element_55;
+ IDL [size_is(element_55)] [unique] byte *element_56;
+ IDL } TYPE_9;
+*/
+static int
+dissect_browser_TYPE_9_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* this call is to make ethereal eat the array header for the conformant run */
+ offset =dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, NULL);
+
+ return offset;
+ }
+
+ /* this is really the length of the encoded data */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, &len);
+
+ proto_tree_add_item(tree, hf_browser_unknown_bytes, tvb, offset, len,
+ FALSE);
+ offset += len;
+
+ return len;
+}
+static int
+dissect_browser_TYPE_9(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_9_data, NDR_POINTER_UNIQUE,
+ "unknown TYPE_9", -1);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef [switch_type(long)] union {
+ IDL [case(100)] [unique] TYPE_9 *element_53;
+ IDL [case(101)] [unique] TYPE_10 *element_54;
+ IDL } TYPE_8;
+*/
+static int
+dissect_browser_TYPE_8(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ /* this is really the union switch arm */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, &level);
+
+ ALIGN_TO_4_BYTES;
+
+ switch(level){
+ case 100:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_9, NDR_POINTER_UNIQUE,
+ "unknown TYPE_9", -1);
+ break;
+ case 101:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_10, NDR_POINTER_UNIQUE,
+ "unknown TYPE_10", -1);
+ break;
+ }
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL long element_51;
+ IDL TYPE_8 element_52;
+ IDL } TYPE_7;
+*/
+static int
+dissect_browser_TYPE_7(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_browser_TYPE_8(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+/*
+ IDL long NetrBrowserStatisticsGet(
+ IDL [in] [unique] [string] wchar_t *element_75,
+ IDL [in] long element_76,
+ IDL [in,out] [ref] TYPE_7 *element_77
+ IDL );
+*/
+static int
+dissect_browser_netr_browser_statistics_get_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_7, NDR_POINTER_REF,
+ "unknown TYPE_7", -1);
+
+ return offset;
+}
+static int
+dissect_browser_netr_browser_statistics_get_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_7, NDR_POINTER_REF,
+ "unknown TYPE_7", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long BrowserrSetNetlogonState(
+ IDL [in] [unique] [string] wchar_t *element_78,
+ IDL [in] [ref] [string] wchar_t *element_79,
+ IDL [in] [unique] [string] wchar_t *element_80,
+ IDL [in] long element_81
+ IDL );
+*/
+static int
+dissect_browser_browserr_set_netlogon_state_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_set_netlogon_state_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+
+
+/*
+ IDL typedef struct {
+ IDL long element_82;
+ IDL [size_is(element_82)] [unique] byte *element_83;
+ IDL } TYPE_12;
+*/
+static int
+dissect_browser_TYPE_12_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* this call is to make ethereal eat the array header for the conformant run */
+ offset =dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, NULL);
+
+ return offset;
+ }
+
+ /* this is really the length of the encoded data */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, &len);
+
+ proto_tree_add_item(tree, hf_browser_unknown_bytes, tvb, offset, len,
+ FALSE);
+ offset += len;
+
+ return len;
+}
+static int
+dissect_browser_TYPE_12(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_12_data, NDR_POINTER_UNIQUE,
+ "unknown TYPE_12", -1);
+
+ return offset;
+}
+
+
+/*
+ IDL long BrowserrQueryEmulatedDomains(
+ IDL [in] [unique] [string] wchar_t *element_84,
+ IDL [in,out] [ref] TYPE_12 *element_85
+ );
+*/
+static int
+dissect_browser_browserr_query_emulated_domains_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_12, NDR_POINTER_REF,
+ "unknown TYPE_12", -1);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_query_emulated_domains_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_12, NDR_POINTER_REF,
+ "unknown TYPE_12", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long BrowserrServerEnumEx(
+ IDL [in] [unique] [string] wchar_t *element_86,
+ IDL [in] [unique] [string] wchar_t *element_87,
+ IDL [in] [unique] [string] wchar_t *element_88,
+ IDL [in,out] [ref] TYPE_1 *element_89,
+ IDL [in] long element_90,
+ IDL [out] long element_91,
+ IDL [in] long element_92,
+ IDL [in] [unique] [string] wchar_t *element_93,
+ IDL [in] [unique] [string] wchar_t *element_94
+ IDL );
+*/
+static int
+dissect_browser_browserr_server_enum_ex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_1, NDR_POINTER_REF,
+ "unknown TYPE_1", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_browser_unknown_string, 0);
+
+ return offset;
+}
+static int
+dissect_browser_browserr_server_enum_ex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_browser_TYPE_1, NDR_POINTER_REF,
+ "unknown TYPE_1", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_browser_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+ IDL }
+*/
+static dcerpc_sub_dissector dcerpc_browser_dissectors[] = {
+ { BROWSER_BROWSERR_SERVER_ENUM, "BrowserrServerEnum",
+ dissect_browser_browserr_server_enum_rqst,
+ dissect_browser_browserr_server_enum_reply },
+ { BROWSER_BROWSERR_DEBUG_CALL, "BrowserrDebugCall",
+ dissect_browser_browserr_debug_call_rqst,
+ dissect_browser_browserr_debug_call_reply },
+ { BROWSER_BROWSERR_QUERY_OTHER_DOMAINS,
+ "BrowserrQueryOtherDomains",
+ dissect_browser_browserr_query_other_domains_rqst,
+ dissect_browser_browserr_query_other_domains_reply },
+ { BROWSER_BROWSERR_RESET_NETLOGON_STATE,
+ "BrowserrResetNetlogonState",
+ dissect_browser_browserr_reset_netlogon_state_rqst,
+ dissect_browser_browserr_reset_netlogon_state_reply },
+ { BROWSER_BROWSERR_DEBUG_TRACE,
+ "BrowserrDebugTrace",
+ dissect_browser_browserr_debug_trace_rqst,
+ dissect_browser_browserr_debug_trace_reply },
+ { BROWSER_BROWSERR_QUERY_STATISTICS,
+ "BrowserrQueryStatistics",
+ dissect_browser_browserr_query_statistics_rqst,
+ dissect_browser_browserr_query_statistics_reply },
+ { BROWSER_BROWSERR_RESET_STATISTICS,
+ "BrowserrResetStatistics",
+ dissect_browser_browserr_reset_statistics_rqst,
+ dissect_browser_browserr_reset_statistics_reply },
+ { BROWSER_NETR_BROWSER_STATISTICS_CLEAR,
+ "NetrBrowserStatisticsClear",
+ dissect_browser_netr_browser_statistics_clear_rqst,
+ dissect_browser_netr_browser_statistics_clear_reply },
+ { BROWSER_NETR_BROWSER_STATISTICS_GET,
+ "NetrBrowserStatisticsGet",
+ dissect_browser_netr_browser_statistics_get_rqst,
+ dissect_browser_netr_browser_statistics_get_reply },
+ { BROWSER_BROWSERR_SET_NETLOGON_STATE,
+ "BrowserrSetNetlogonState",
+ dissect_browser_browserr_set_netlogon_state_rqst,
+ dissect_browser_browserr_set_netlogon_state_reply },
+ { BROWSER_BROWSERR_QUERY_EMULATED_DOMAINS,
+ "BrowserrQueryEmulatedDomains",
+ dissect_browser_browserr_query_emulated_domains_rqst,
+ dissect_browser_browserr_query_emulated_domains_reply },
+ { BROWSER_BROWSERR_SERVER_ENUM_EX,
+ "BrowserrServerEnumEx",
+ dissect_browser_browserr_server_enum_ex_rqst,
+ dissect_browser_browserr_server_enum_ex_reply },
+
+ {0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_browser(void)
+{
+static hf_register_info hf[] = {
+
+ { &hf_browser_opnum, {
+ "Operation", "rpc_browser.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ { &hf_browser_rc, {
+ "Return code", "rpc_browser.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "Browser return code", HFILL }},
+
+ { &hf_browser_unknown_long, {
+ "Unknown long", "rpc_browser.unknown.long", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Unknown long. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_browser_unknown_hyper, {
+ "Unknown hyper", "rpc_browser.unknown.hyper", FT_UINT64, BASE_HEX,
+ NULL, 0x0, "Unknown hyper. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_browser_unknown_bytes, {
+ "Unknown bytes", "rpc_browser.unknown.bytes", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Unknown bytes. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_browser_unknown_string, {
+ "Unknown string", "rpc_browser.unknown.string", FT_STRING, BASE_HEX,
+ NULL, 0x0, "Unknown string. If you know what this is, contact ethereal developers.", HFILL }}
+
+ };
+ static gint *ett[] = {
+ &ett_dcerpc_browser
+ };
+
+ proto_dcerpc_browser = proto_register_protocol(
+ "RPC Browser", "RPC_BROWSER", "rpc_browser");
+
+ proto_register_field_array(proto_dcerpc_browser, hf,
+ array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_browser(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_browser, ett_dcerpc_browser,
+ &uuid_dcerpc_browser, ver_dcerpc_browser,
+ dcerpc_browser_dissectors, hf_browser_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-browser.h b/epan/dissectors/packet-dcerpc-browser.h
new file mode 100644
index 0000000000..3a434c8b87
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-browser.h
@@ -0,0 +1,42 @@
+/* packet-dcerpc-browser.h
+ * Routines for DCERPC Browser packet disassembly
+ * Copyright 2002, Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_BROWSER_H
+#define __PACKET_DCERPC_BROWSER_H
+
+#define BROWSER_BROWSERR_SERVER_ENUM 0x00
+#define BROWSER_BROWSERR_DEBUG_CALL 0x01
+#define BROWSER_BROWSERR_QUERY_OTHER_DOMAINS 0x02
+#define BROWSER_BROWSERR_RESET_NETLOGON_STATE 0x03
+#define BROWSER_BROWSERR_DEBUG_TRACE 0x04
+#define BROWSER_BROWSERR_QUERY_STATISTICS 0x05
+#define BROWSER_BROWSERR_RESET_STATISTICS 0x06
+#define BROWSER_NETR_BROWSER_STATISTICS_CLEAR 0x07
+#define BROWSER_NETR_BROWSER_STATISTICS_GET 0x08
+#define BROWSER_BROWSERR_SET_NETLOGON_STATE 0x09
+#define BROWSER_BROWSERR_QUERY_EMULATED_DOMAINS 0x0a
+#define BROWSER_BROWSERR_SERVER_ENUM_EX 0x0b
+
+#endif
diff --git a/epan/dissectors/packet-dcerpc-budb.c b/epan/dissectors/packet-dcerpc-budb.c
new file mode 100644
index 0000000000..002e06cf0c
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-budb.c
@@ -0,0 +1,107 @@
+/* packet-dcerpc-budb.c
+ * Routines for budb dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz bubasics/budb.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_budb = -1;
+static int hf_budb_opnum = -1;
+
+
+static gint ett_budb = -1;
+
+static e_uuid_t uuid_budb = { 0xeb814e2a, 0x0099, 0x11ca, { 0x86, 0x78, 0x02, 0x60, 0x8c, 0x2e, 0xa9, 0x6e } };
+static guint16 ver_budb = 4;
+
+
+static dcerpc_sub_dissector budb_dissectors[] = {
+{ 0, "AddVolume", NULL, NULL },
+{ 1, "CreateDump", NULL, NULL },
+{ 2, "DeleteDump", NULL, NULL },
+{ 3, "DeleteTape", NULL, NULL },
+{ 4, "DeleteVDP", NULL, NULL },
+{ 5, "FindClone", NULL, NULL },
+{ 6, "FindDump", NULL, NULL },
+{ 7, "FindLatestDump", NULL, NULL },
+{ 8, "FinishDump", NULL, NULL },
+{ 9, "FinishTape", NULL, NULL },
+{ 10, "GetDumps", NULL, NULL },
+{ 11, "GetTapes", NULL, NULL },
+{ 12, "GetVolumes", NULL, NULL },
+{ 13, "UseTape", NULL, NULL },
+{ 14, "GetText", NULL, NULL },
+{ 15, "GetTextVersion", NULL, NULL },
+{ 16, "SaveText", NULL, NULL },
+{ 17, "FreeAllLocks", NULL, NULL },
+{ 18, "FreeLock", NULL, NULL },
+{ 19, "GetInstanceId", NULL, NULL },
+{ 20, "GetLock", NULL, NULL },
+{ 21, "DbVerify", NULL, NULL },
+{ 22, "DumpDB", NULL, NULL },
+{ 23, "RestoreDbHeader", NULL, NULL },
+{ 24, "T_GetVersion", NULL, NULL },
+{ 25, "T_DumpHashTable", NULL, NULL },
+{ 26, "T_DumpDatabase", NULL, NULL },
+{ 27, "GetServerInterfaces", NULL, NULL },
+{ 28, "AddVolumes", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_budb (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_budb_opnum,
+ { "Operation", "budb.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_budb,
+ };
+ proto_budb = proto_register_protocol ("DCE/RPC BUDB", "BUDB", "budb");
+ proto_register_field_array (proto_budb, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_budb (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_budb, ett_budb, &uuid_budb, ver_budb, budb_dissectors, hf_budb_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-butc.c b/epan/dissectors/packet-dcerpc-butc.c
new file mode 100644
index 0000000000..a6478f1f25
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-butc.c
@@ -0,0 +1,121 @@
+/* packet-dcerpc-butc.c
+ * Routines for butc dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz bubasics/butc.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_butc = -1;
+static int hf_butc_opnum = -1;
+
+
+static gint ett_butc = -1;
+
+
+static e_uuid_t uuid_butc = { 0x1d193c08, 0x000b, 0x11ca, { 0xba, 0x1d, 0x02, 0x60, 0x8c, 0x2e, 0xa9, 0x6e } };
+static guint16 ver_butc = 4;
+
+
+#define TC_DEFAULT_STACK_SIZE (150*1024) /* stack size for tc threads */
+#define TC_MAXGENNAMELEN 512 /* length of generic name */
+#define TC_MAXDUMPPATH 256 /* dump path names*/
+#define TC_MAXNAMELEN 128 /* name length */
+#define TC_MAXFORMATLEN 100 /*size of the format statement */
+#define TC_MAXHOSTLEN 128 /*for server/machine names */
+#define TC_MAXTAPELEN 256 /*max tape name allowed */
+#define TC_STAT_DONE 1 /* all done */
+#define TC_STAT_OPRWAIT 2 /* waiting for user interaction */
+#define TC_STAT_DUMP 4 /* true if dump, false if restore */
+#define TC_STAT_ABORTED 8 /* the operation was aborted */
+#define TC_STAT_ERROR 16 /* error ocuured in the operation */
+#define TSK_STAT_FIRST 0x1 /* get id of first task */
+#define TSK_STAT_END 0x2 /* no more tasks */
+#define TSK_STAT_NOTFOUND 0x4 /* couldn't find task id requested */
+
+#define TCOP_NONE 0
+#define TCOP_READLABEL 1
+#define TCOP_LABELTAPE 2
+#define TCOP_DUMP 3
+#define TCOP_RESTORE 4
+#define TCOP_SCANTAPE 5
+#define TCOP_SAVEDB 6
+#define TCOP_RESTOREDB 7
+#define TCOP_STATUS 8
+#define TCOP_SPARE 9
+
+
+static dcerpc_sub_dissector butc_dissectors[] = {
+ { 0, "PerformDump", NULL, NULL},
+ { 1, "PerformRestore", NULL, NULL},
+ { 2, "AbortDump", NULL, NULL},
+ { 3, "LabelTape", NULL, NULL},
+ { 4, "ReadLabel", NULL, NULL},
+ { 5, "ScanDumps", NULL, NULL},
+ { 6, "TCInfo", NULL, NULL},
+ { 7, "SaveDb", NULL, NULL},
+ { 8, "RestoreDb", NULL, NULL},
+ { 9, "EndStatus", NULL, NULL},
+ { 10, "GetStatus", NULL, NULL},
+ { 11, "RequestAbort", NULL, NULL},
+ { 12, "ScanStatus", NULL, NULL},
+ { 13, "GetServerInterfaces", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_butc (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_butc_opnum,
+ { "Operation", "butc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_butc,
+ };
+ proto_butc = proto_register_protocol ("DCE/RPC BUTC", "BUTC", "butc");
+ proto_register_field_array (proto_butc, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_butc (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_butc, ett_butc, &uuid_butc, ver_butc, butc_dissectors, hf_butc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-cds_clerkserver.c b/epan/dissectors/packet-dcerpc-cds_clerkserver.c
new file mode 100644
index 0000000000..f708de6d75
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-cds_clerkserver.c
@@ -0,0 +1,111 @@
+/* packet-dcerpc-cds_clerkserver.c
+ *
+ * Routines for cds_clerkserver dissection
+ * Routines for dcerpc Afs4Int dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/directory.tar.gz directory/cds/stubs/cds_clerkserver.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_cds_clerkserver = -1;
+static int hf_cds_clerkserver_opnum = -1;
+
+
+static gint ett_cds_clerkserver = -1;
+
+
+static e_uuid_t uuid_cds_clerkserver = { 0x257df1c9, 0xc6d3, 0x11ca, { 0x85, 0x54, 0x08, 0x00, 0x2b, 0x1c, 0x8f, 0x1f } };
+static guint16 ver_cds_clerkserver = 1;
+
+
+
+static dcerpc_sub_dissector cds_clerkserver_dissectors[] = {
+ { 0, "AddReplica", NULL, NULL},
+ { 1, "AllowClearinghouses", NULL, NULL},
+ { 2, "Combine", NULL, NULL},
+ { 3, "CreateChild", NULL, NULL},
+ { 4, "CreateDirectory", NULL, NULL},
+ { 5, "CreateSoftLink", NULL, NULL},
+ { 6, "CreateObject", NULL, NULL},
+ { 7, "DeleteChild", NULL, NULL},
+ { 8, "DeleteObject", NULL, NULL},
+ { 9, "DeleteSoftLink", NULL, NULL},
+ { 10, "DeleteDirectory", NULL, NULL},
+ { 11, "DisallowClearinghouses", NULL, NULL},
+ { 12, "DoUpdate", NULL, NULL},
+ { 13, "EnumerateAttributes", NULL, NULL},
+ { 14, "EnumerateChildren", NULL, NULL},
+ { 15, "EnumerateObjects", NULL, NULL},
+ { 16, "EnumerateSoftLinks", NULL, NULL},
+ { 17, "LinkReplica", NULL, NULL},
+ { 18, "ModifyAttribute", NULL, NULL},
+ { 19, "ModifyReplica", NULL, NULL},
+ { 20, "NewEpoch", NULL, NULL},
+ { 21, "ReadAttribute", NULL, NULL},
+ { 22, "RemoveReplica", NULL, NULL},
+ { 23, "ResolveName", NULL, NULL},
+ { 24, "Skulk", NULL, NULL},
+ { 25, "TestAttribute", NULL, NULL},
+ { 26, "TestGroup", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_cds_clerkserver (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_cds_clerkserver_opnum,
+ { "Operation", "cds_clerkserver.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_cds_clerkserver,
+ };
+ proto_cds_clerkserver = proto_register_protocol ("CDS Clerk Server Calls", "CDS_CLERK", "cds_clerkserver");
+ proto_register_field_array (proto_cds_clerkserver, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_cds_clerkserver (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_cds_clerkserver, ett_cds_clerkserver, &uuid_cds_clerkserver, ver_cds_clerkserver, cds_clerkserver_dissectors, hf_cds_clerkserver_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-cds_solicit.c b/epan/dissectors/packet-dcerpc-cds_solicit.c
new file mode 100644
index 0000000000..6cb1375b51
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-cds_solicit.c
@@ -0,0 +1,83 @@
+/* packet-dcerpc-cds_solicit.c
+ * Routines for cds_solicit dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/directory.tar.gz directory/cds/stubs/cds_solicit.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_cds_solicit = -1;
+static int hf_cds_solicit_opnum = -1;
+
+
+static gint ett_cds_solicit = -1;
+
+
+static e_uuid_t uuid_cds_solicit = { 0xd5579459, 0x8bca, 0x11ca, { 0xb7, 0x71, 0x08, 0x00, 0x2b, 0x1c, 0x8f, 0x1f } };
+static guint16 ver_cds_solicit = 1;
+
+
+static dcerpc_sub_dissector cds_solicit_dissectors[] = {
+ { 0, "cds_Solicit", NULL, NULL},
+ { 1, "cds_Advertise", NULL, NULL},
+ { 2, "cds_SolicitServer", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_cds_solicit (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_cds_solicit_opnum,
+ { "Operation", "cds_solicit.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_cds_solicit,
+ };
+ proto_cds_solicit = proto_register_protocol ("DCE/RPC CDS Solicitation", "cds_solicit", "cds_solicit");
+ proto_register_field_array (proto_cds_solicit, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_cds_solicit (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_cds_solicit, ett_cds_solicit, &uuid_cds_solicit, ver_cds_solicit, cds_solicit_dissectors, hf_cds_solicit_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-conv.c b/epan/dissectors/packet-dcerpc-conv.c
new file mode 100644
index 0000000000..bc8d3e77cc
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-conv.c
@@ -0,0 +1,214 @@
+/* packet-dcerpc-conv.c
+ * Routines for dcerpc conv dissection
+ * Copyright 2001, Todd Sabin <tas@webspan.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dce122.h"
+
+
+static int proto_conv = -1;
+static int hf_conv_opnum = -1;
+static int hf_conv_rc = -1;
+static int hf_conv_who_are_you_rqst_actuid = -1;
+static int hf_conv_who_are_you_rqst_boot_time = -1;
+static int hf_conv_who_are_you2_rqst_actuid = -1;
+static int hf_conv_who_are_you2_rqst_boot_time = -1;
+static int hf_conv_who_are_you_resp_seq = -1;
+static int hf_conv_who_are_you2_resp_seq = -1;
+static int hf_conv_who_are_you2_resp_casuuid = -1;
+
+static gint ett_conv = -1;
+
+
+static e_uuid_t uuid_conv = { 0x333a2276, 0x0000, 0x0000, { 0x0d, 0x00, 0x00, 0x80, 0x9c, 0x00, 0x00, 0x00 } };
+static guint16 ver_conv = 3;
+
+
+static int
+conv_dissect_who_are_you_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /*
+ * [in] uuid_t *actuid,
+ * [in] unsigned32 boot_time,
+ */
+ e_uuid_t actuid;
+
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_conv_who_are_you_rqst_actuid, &actuid);
+ offset = dissect_ndr_time_t (tvb, offset, pinfo, tree, drep, hf_conv_who_are_you_rqst_boot_time, NULL);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "conv_who_are_you request actuid: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ actuid.Data1, actuid.Data2, actuid.Data3, actuid.Data4[0], actuid.Data4[1],
+ actuid.Data4[2], actuid.Data4[3], actuid.Data4[4], actuid.Data4[5], actuid.Data4[6], actuid.Data4[7]);
+ }
+
+ return offset;
+}
+
+static int
+conv_dissect_who_are_you_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /*
+ * [out] unsigned32 *seq,
+ * [out] unsigned32 *st
+ */
+ guint32 seq, st;
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_conv_who_are_you_resp_seq, &seq);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_conv_rc, &st);
+
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "conv_who_are_you response seq:%u st:%s",
+ seq, val_to_str(st, dce_error_vals, "%u"));
+ }
+
+ return offset;
+}
+
+
+
+static int
+conv_dissect_who_are_you2_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /*
+ * [in] uuid_t *actuid,
+ * [in] unsigned32 boot_time,
+ */
+ e_uuid_t actuid;
+
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_conv_who_are_you2_rqst_actuid, &actuid);
+ offset = dissect_ndr_time_t (tvb, offset, pinfo, tree, drep, hf_conv_who_are_you2_rqst_boot_time, NULL);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "conv_who_are_you2 request actuid: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ actuid.Data1, actuid.Data2, actuid.Data3, actuid.Data4[0], actuid.Data4[1],
+ actuid.Data4[2], actuid.Data4[3], actuid.Data4[4], actuid.Data4[5], actuid.Data4[6], actuid.Data4[7]);
+ }
+
+ return offset;
+}
+static int
+conv_dissect_who_are_you2_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /*
+ * [out] unsigned32 *seq,
+ * [out] uuid_t *cas_uuid,
+ *
+ * [out] unsigned32 *st
+ */
+ guint32 seq, st;
+ e_uuid_t cas_uuid;
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_conv_who_are_you2_resp_seq, &seq);
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_conv_who_are_you2_resp_casuuid, &cas_uuid);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_conv_rc, &st);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "conv_who_are_you2 response seq:%u st:%s cas:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ seq, val_to_str(st, dce_error_vals, "%u"),
+ cas_uuid.Data1, cas_uuid.Data2, cas_uuid.Data3, cas_uuid.Data4[0], cas_uuid.Data4[1],
+ cas_uuid.Data4[2], cas_uuid.Data4[3], cas_uuid.Data4[4], cas_uuid.Data4[5], cas_uuid.Data4[6], cas_uuid.Data4[7]);
+ }
+
+ return offset;
+}
+
+
+static dcerpc_sub_dissector conv_dissectors[] = {
+ { 0, "who_are_you",
+ conv_dissect_who_are_you_rqst, conv_dissect_who_are_you_resp },
+ { 1, "who_are_you2",
+ conv_dissect_who_are_you2_rqst, conv_dissect_who_are_you2_resp },
+ { 2, "are_you_there", NULL, NULL },
+ { 3, "who_are_you_auth", NULL, NULL },
+ { 4, "who_are_you_auth_more", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_conv (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_conv_opnum,
+ { "Operation", "conv.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ { &hf_conv_rc,
+ {"Status", "conv.status", FT_UINT32, BASE_DEC, VALS(dce_error_vals), 0x0, "", HFILL }},
+
+ { &hf_conv_who_are_you_rqst_actuid,
+ {"Activity UID", "conv.who_are_you_rqst_actuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL }},
+ { &hf_conv_who_are_you_rqst_boot_time,
+ {"Boot time", "conv.who_are_you_rqst_boot_time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_conv_who_are_you2_rqst_actuid,
+ {"Activity UID", "conv.who_are_you2_rqst_actuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL }},
+ { &hf_conv_who_are_you2_rqst_boot_time,
+ {"Boot time", "conv.who_are_you2_rqst_boot_time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_conv_who_are_you_resp_seq,
+ {"Sequence Number", "conv.who_are_you_resp_seq", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_conv_who_are_you2_resp_seq,
+ {"Sequence Number", "conv.who_are_you2_resp_seq", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_conv_who_are_you2_resp_casuuid,
+ {"Client's address space UUID", "conv.who_are_you2_resp_casuuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_conv
+ };
+ proto_conv = proto_register_protocol ("DCE/RPC Conversation Manager", "CONV", "conv");
+ proto_register_field_array (proto_conv, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_conv (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_conv, ett_conv, &uuid_conv, ver_conv, conv_dissectors, hf_conv_opnum);
+}
+
diff --git a/epan/dissectors/packet-dcerpc-cprpc_server.c b/epan/dissectors/packet-dcerpc-cprpc_server.c
new file mode 100644
index 0000000000..bb7b2f1200
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-cprpc_server.c
@@ -0,0 +1,82 @@
+/* packet-dcerpc-cprpc_server.c
+ * Routines for DNS Control Program Server dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/directory.tar.gz directory/cds/stubs/cprpc_server.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_cprpc_server = -1;
+static int hf_cprpc_server_opnum = -1;
+
+
+static gint ett_cprpc_server = -1;
+
+
+static e_uuid_t uuid_cprpc_server = { 0x4885772c, 0xc6d3, 0x11ca, { 0x84, 0xc6, 0x08, 0x00, 0x2b, 0x1c, 0x8f, 0x1f } };
+static guint16 ver_cprpc_server = 1;
+
+
+static dcerpc_sub_dissector cprpc_server_dissectors[] = {
+ { 0, "dnscp_server", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_cprpc_server (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_cprpc_server_opnum,
+ { "Operation", "cprpc_server.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_cprpc_server,
+ };
+ proto_cprpc_server = proto_register_protocol ("DNS Control Program Server", "cprpc_server", "cprpc_server");
+ proto_register_field_array (proto_cprpc_server, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_cprpc_server (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_cprpc_server, ett_cprpc_server, &uuid_cprpc_server, ver_cprpc_server, cprpc_server_dissectors, hf_cprpc_server_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-dce122.c b/epan/dissectors/packet-dcerpc-dce122.c
new file mode 100644
index 0000000000..d86869e927
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-dce122.c
@@ -0,0 +1,4428 @@
+/* packet-dcerpc-dce122.c
+ * Common defines for dce122
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "epan/value_string.h"
+#include "packet-dcerpc-dce122.h"
+
+const value_string dce_error_vals[] = {
+{ 0, "SUCCESS", },
+{ 539918337, "event already in set" },
+{ 539918338, "event still part of some set" },
+{ 539918339, "illegal invalid or inconsistent arguments" },
+{ 539918340, "too many initialized devices" },
+{ 539918341, "no such device" },
+{ 539918342, "device no longer available" },
+{ 543465473, "Unacceptable user supplied argument" },
+{ 543465474, "Object has been updated" },
+{ 543465475, "Search matched more than one item" },
+{ 543465476, "Can't allocate working memory" },
+{ 543465477, "Can't get cell configuration information" },
+{ 543465478, "Specified item already exists" },
+{ 543465479, "Error in configuration parameters" },
+{ 543465480, "No such fileset family" },
+{ 543465481, "No such fileset entry" },
+{ 543465482, "fileset family already exists" },
+{ 543465483, "bad fileset family name" },
+{ 543465484, "bad dump level name" },
+{ 543465485, "dump level already exists" },
+{ 543465486, "No such dump level" },
+{ 543465487, "No such parent dump level" },
+{ 543465488, "bad expiration date" },
+{ 543465489, "Bad tape coordinator id" },
+{ 543465490, "tape coordinator id already exists" },
+{ 543465491, "No such tape coordinator id" },
+{ 543465492, "Bad butc connection handle" },
+{ 543465493, "No butc connection handles available" },
+{ 543465494, "bad job specification" },
+{ 543465495, "No such job" },
+{ 543465496, "Too many dump/restore sessions in progress" },
+{ 543465497, "No such server" },
+{ 543465498, "No such aggregate" },
+{ 543465499, "Version mismatch between bak and butc" },
+{ 543465500, "error creating thread" },
+{ 543465501, "Lock has not been acquired" },
+{ 543465502, "Lock already acquired" },
+{ 543465503, "Internal error" },
+{ 543465504, "bad internal queue" },
+{ 543465505, "exception raised" },
+{ 543662081, "process not active" },
+{ 543662082, "no such entity" },
+{ 543662083, "can't do operation now" },
+{ 543662084, "entity already exists" },
+{ 543662085, "failed to create entity" },
+{ 543662086, "index out of range" },
+{ 543662087, "you are not authorized for this operation" },
+{ 543662088, "syntax error in create parameter" },
+{ 543662089, "I/O error" },
+{ 543662090, "network problem" },
+{ 543662091, "unrecognized bnode type" },
+{ 543662092, "unable to install file on server machine" },
+{ 543662093, "internal date parsing error in the bosserver" },
+{ 543662094, "illegal user list entry type" },
+{ 543662095, "error from the security system" },
+{ 543662096, "error returned from DCE key mgmt system; check bosserver log" },
+{ 543662097, "memory exhaustion in bosserver" },
+{ 543662098, "specified admin list file not found" },
+{ 543662099, "user or group not recognized by security registry" },
+{ 543662100, "unexpected internal error; check bosserver log" },
+{ 543662101, "operation not yet implemented" },
+{ 543662102, "specified executable not found" },
+{ 543662103, "time parameter required for cron type bnode" },
+{ 543920129, "dump with specified id already exists" },
+{ 543920130, "no dump matching the id was found" },
+{ 543920131, "no dump matching the name was found" },
+{ 543920132, "no tape matching the name was found" },
+{ 543920133, "no tape matching the name was found" },
+{ 543920134, "entry doesn't exist" },
+{ 543920135, "reference to a tape not being used" },
+{ 543920136, "dump of database failed" },
+{ 543920137, "access to database denied" },
+{ 543920138, "incompatible version numbers" },
+{ 543920139, "argument too long or out of range" },
+{ 543920140, "sequence of operations incorrect" },
+{ 543920141, "inconsistent or unsupported flags bit combination" },
+{ 543920142, "requested list too large" },
+{ 543920143, "index to iterator function is out of range" },
+{ 543920144, "bad database block type" },
+{ 543920145, "dumpinfo database empty" },
+{ 543920146, "lock is not set" },
+{ 543920147, "lock is held by another user" },
+{ 543920148, "attempt to lock a lock already held" },
+{ 543920149, "interface incompatible" },
+{ 543920150, "Ubik I/O error" },
+{ 543920151, "bad database address" },
+{ 543920152, "backup database is inconsistent" },
+{ 543920153, "internal error encountered in backup database server" },
+{ 543920154, "error reading cell database" },
+{ 543920155, "cell name not found" },
+{ 543920156, "database empty or corrupted" },
+{ 543920157, "Ubik ClientInit failed" },
+{ 543920158, "couldn't allocate entry" },
+{ 543920159, "can't allocate memory" },
+{ 543920160, "error creating thread" },
+{ 543920161, "invalid server group name" },
+{ 543920162, "reference to dump already in use" },
+{ 543920163, "reference to dump not in use" },
+{ 543920164, "reference to tape already in use" },
+{ 543920165, "dump to be deleted is not an initial dump" },
+{ 543920166, "duplicate tape name" },
+{ 546545665, "error in dump/restore process " },
+{ 546545666, "ungraceful abort " },
+{ 546545667, "the dump/restore has already been aborted" },
+{ 546545668, "unable to end dump/restore since work in progress" },
+{ 546545669, "some of the dump/restores were unsuccessful" },
+{ 546545670, "could not abort the process " },
+{ 546545671, "the dump/restore process was aborted by request" },
+{ 546545672, "No dump task with specified ID" },
+{ 546545673, "No tasks active" },
+{ 546545679, "no filesets on this tape" },
+{ 546545680, "tape not loaded or drive offline" },
+{ 546545681, "internal error" },
+{ 546545682, "memory allocation failure" },
+{ 546545683, "invalid tape coordinator port offset" },
+{ 546545684, "invalid debug level input" },
+{ 546545685, "invalid tape config file name" },
+{ 546545686, "tape coordinator already running on this tcid" },
+{ 546545687, "operation on thread failed" },
+{ 546545688, "invalid task" },
+{ 546545689, "invalid bakserver group name" },
+{ 546545690, "failed to scan tape" },
+{ 546545691, "invalid host" },
+{ 546545692, "No more dumps on this tape" },
+{ 546586625, "interface incompatible" },
+{ 546586626, "there is not a mounted tape" },
+{ 546586627, "multiple simulataneous mounts not permitted" },
+{ 546586628, "can't mount tape" },
+{ 546586629, "error during tape dismount" },
+{ 546586630, "tape I/O error" },
+{ 546586631, "write operation on read-only tape" },
+{ 546586632, "operation inappropriate in this context" },
+{ 546586633, "read file ended before all data read" },
+{ 546586634, "write a zero length file" },
+{ 546586635, "end of tape" },
+{ 546586636, "problem reading configuration" },
+{ 546586637, "argument too long or out of range" },
+{ 546586638, "unexpected end of volume data" },
+{ 546586639, "no tape loaded or device offline" },
+{ 546586640, "memory allocation failure" },
+{ 546586641, "end of dump" },
+{ 551956481, "More than the maximum number of parameters defined" },
+{ 551956482, "Internal parsing error" },
+{ 551956483, "Too many values specified after a CMD_SINGLE switch" },
+{ 551956484, "Too many parameters specified" },
+{ 551956485, "Two or more mutually exclusive parameters used" },
+{ 551956486, "Impossibly few arguments specified" },
+{ 551956487, "unrecognized or ambiguous command name" },
+{ 551956488, "unrecognized or ambiguous switch name" },
+{ 551956489, "<unused>" },
+{ 551956490, "Insufficient required parameters provided" },
+{ 551956491, "Invalid argument value given" },
+{ 551956492, "No appropriate commands found" },
+{ 551956493, "Interactive mode not available for specified command or suite" },
+{ 551956494, "Command execution aborted at user request" },
+{ 551956495, "Token too large" },
+{ 552005633, "Required pointer parameter has NULL value" },
+{ 552005634, "Not enough space in buffer passed to routine" },
+{ 552005635, "Malformed host name" },
+{ 552005636, "failed to disable cancels" },
+{ 552005637, "failed to reenable cancels" },
+{ 552005638, "memory allocation failure" },
+{ 552005639, "no bindings for this entry" },
+{ 552005640, "too many objects in group entry" },
+{ 552005641, "Unable to find required credentials to complete requested operation" },
+{ 552005642, "Unauthenticated mode forced due to use of short machine name" },
+{ 552005643, "one of the uuid parameters is nil" },
+{ 552005644, "no objects in group entry" },
+{ 556613633, "Not enough space in buffer passed to routine" },
+{ 556613634, "Malformed host name" },
+{ 556613635, "Error returned from security service" },
+{ 556613636, "Error returned from rpc service" },
+{ 556613637, "Error returned from threads service" },
+{ 556613638, "Requested access denied" },
+{ 556613639, "Access check operation requested before server initialization" },
+{ 556613640, "Dfsauth operation requested before client initialization" },
+{ 556613641, "Requested dfsauth operation not supported in noauth mode" },
+{ 556613642, "Required pointer parameter has NULL value" },
+{ 556613643, "Unable to obtain value of required environment variable (debugging only)" },
+{ 556613644, "Generation of a pathname that is too long was attempted" },
+{ 556613645, "Principal name cannot be defaulted in kernel mode" },
+{ 556613646, "Unable to dynamically allocate required memory" },
+{ 556613647, "Local host DCE name database appears to be corrupted" },
+{ 556613648, "No network credentials found for current login context" },
+{ 556613649, "Attempt to perform operation that requires root access" },
+{ 556613650, "Attempt to use localauth identity on a machine that does not have an identity" },
+{ 556613651, "Unable to find a valid key in local keyfile" },
+{ 556613652, "Requested protection level is not supported by the RPC system" },
+{ 556613653, "File system open error" },
+{ 556613654, "File system close error" },
+{ 556613655, "File system stat error" },
+{ 556613656, "File system read error" },
+{ 556613657, "File system write error" },
+{ 556613658, "File system rename error" },
+{ 556613659, "File system unlink error" },
+{ 556613660, "Client is using unsupported authentication service" },
+{ 556904449, "Too many bytes in acl byte buffer" },
+{ 556904450, "Too few bytes in acl byte buffer" },
+{ 556904451, "ACL entry not found" },
+{ 556904452, "ACL entry already exists" },
+{ 556904453, "Unrecognized entry type" },
+{ 556904454, "Unrecognized entry class" },
+{ 556904455, "Unimplemented entry type" },
+{ 556904456, "Error returned from security service" },
+{ 556904457, "Name required for specified entry type" },
+{ 556904458, "Attempt to remove required ACL entry" },
+{ 556904459, "Buffer allocation error" },
+{ 556904460, "Requested access (implicitly) denied by ACL" },
+{ 556904461, "Requested access explicitly denied by ACL" },
+{ 556904462, "File in which ACL creation was requested already exists" },
+{ 556904463, "Attempt to parse ACL by incorrect ACL manager" },
+{ 556904464, "ACL contains an entry not appropriate for the ACL manager type" },
+{ 556904465, "ACL manager requires parameters not passed to routine" },
+{ 556904466, "Required ACL entry missing from ACL" },
+{ 556904467, "Required pointer parameter has NULL value" },
+{ 556904468, "Unrecognized ACL manager type uuid" },
+{ 556904469, "ACL entry type is too large to be processed by current code" },
+{ 556904470, "Duplicate ACL entry found" },
+{ 556904471, "Specified ACL file not found" },
+{ 556904472, "Flat ACL buffer is of incorrect form" },
+{ 556904473, "User or group not recognized by Registry Server" },
+{ 556904474, "Non-local entry type encountered running in local mode" },
+{ 556904475, "File system open error" },
+{ 556904476, "File system close error" },
+{ 556904477, "File system stat error" },
+{ 556904478, "File system read error" },
+{ 556904479, "File system write error" },
+{ 556904480, "Removed unauthenticated entry from ACL" },
+{ 556904481, "Found unauthenticated entry from ACL" },
+{ 565575681, "insufficient space on aggregate" },
+{ 565575682, "container had no allocation handle" },
+{ 565575683, "invalid aggregate handle" },
+{ 565575684, "invalid anode handle" },
+{ 565575685, "index was out of range or anode was invalid" },
+{ 565575686, "illegal undefined or inconsistent arguments" },
+{ 565575687, "invalid device object" },
+{ 565575688, "the acl or plist file handle was invalid" },
+{ 565575689, "illegal undefined or inconsistent flag value" },
+{ 565575690, "a volume table index was invalid" },
+{ 565575691, "fid uniquifier didn't match" },
+{ 565575692, "fid volume id didn't match" },
+{ 565575693, "invalid volume handle" },
+{ 565575694, "invalid file handle" },
+{ 565575695, "file's link count would be negative" },
+{ 565575696, "no further volumes are in the aggregate" },
+{ 565575697, "no further container are in the volume" },
+{ 565575698, "block was past the allocated end of the container" },
+{ 565575699, "block address was too large" },
+{ 565575700, "specified device already has an aggregate" },
+{ 565575701, "too many initialized aggregates" },
+{ 565575702, "Specified volume id already exists" },
+{ 565575703, "Specified volume name already exists" },
+{ 565575704, "Specified anode index already exists" },
+{ 565575705, "no transaction specified when one was required" },
+{ 565575706, "block was interior to the container but was unallocated" },
+{ 565575707, "Specified anode index doesn't exist" },
+{ 565575708, "the anode did not contain a file" },
+{ 565575709, "the container did not contain a volume table" },
+{ 565575710, "the bitmap wasn't consistent w/ superblock" },
+{ 565575711, "the superblock did not lead to an AVL" },
+{ 565575712, "the file didn't point to an acl container" },
+{ 565575713, "container was stored inline or fragmented" },
+{ 565575714, "container was stored inline or blocked" },
+{ 565575715, "container was stored fragmented or blocked" },
+{ 565575716, "an anode being deleted is still open" },
+{ 565575717, "an anode is not empty" },
+{ 565575718, "other containers using these blocks for copy-on-write purposes" },
+{ 565575719, "read operation extends past container's length" },
+{ 565575720, "specified size of the status area was too large" },
+{ 565575721, "supplied status data extends too far" },
+{ 565575722, "insufficient memory to open another anode" },
+{ 565575723, "insufficient quota on volume" },
+{ 565575724, "copy-on-write is illegal for this container" },
+{ 565575725, "block allocation of log is in error" },
+{ 565575726, "block allocation for bitmap failed" },
+{ 565575727, "error in copy-on-write reference" },
+{ 565575728, "management of multiple quota procedures not yet implemented" },
+{ 565575729, "initialization entry point called more than once" },
+{ 565575730, "object or module not properly initialized" },
+{ 565575731, "tried to insert a block that was already allocated" },
+{ 565575732, "tried to insert a block at invalid location" },
+{ 565575733, "bad block insertion parameters" },
+{ 565575734, "a rock was specified whose value was zero" },
+{ 565575735, "a volume was referenced while (going) offline" },
+{ 565575736, "an aggregate was referenced while (going) offline" },
+{ 565575737, "system-special file is or would be made too big" },
+{ 565575738, "the container did not contain a volume header" },
+{ 565575739, "volume doesn't have a root directory" },
+{ 565575740, "not yet implemented" },
+{ 565575741, "operation being done piecemeal is not finished" },
+{ 565575742, "anode must be copy-on-write" },
+{ 565575743, "write operation encountered an inconsistent state" },
+{ 565575744, "existing fragment group can not be extended" },
+{ 565575745, "aggregate has some open volumes" },
+{ 565575746, "volume has some open anodes" },
+{ 565575747, "a volume being deleted is still open" },
+{ 565575748, "new length is inconsistent with storage method" },
+{ 565575749, "expected error code not encountered" },
+{ 565575750, "script version number unknown to test program" },
+{ 565575751, "iterator value indicates previous was last" },
+{ 565575752, "aux type inappropriate for non-dir files" },
+{ 565575753, "anode block/offset pair was invalid" },
+{ 565575754, "same block is referenced more than once from two different anodes" },
+{ 565575755, "failure on storage request during salvage" },
+{ 565575756, "copy on write block reference not in use in bitmap" },
+{ 565575757, "bad Block anode has copy on write references" },
+{ 565575758, "copy On Write pointer is incorrect" },
+{ 565575759, "block references beyond anode length" },
+{ 565575760, "block references beyond device length" },
+{ 565575761, "block reference to indirect block has inconsistent header" },
+{ 565575762, "backing anode has invalid indirect block" },
+{ 565575763, "block not allocated" },
+{ 565575764, "handle reserved for exclusive use of creator" },
+{ 565575765, "file has a positive link count" },
+{ 565575766, "aggregate may be damaged" },
+{ 565575767, "illegal operation on copy on write anode" },
+{ 565575768, "block is purged" },
+{ 572616705, "Stale context" },
+{ 572616706, "Internal corruption" },
+{ 572616707, "RPC binding contains no UUID" },
+{ 572616708, "Revocation RPC call failed--host still up" },
+{ 572616709, "Server initializing after restart: wait and retry" },
+{ 572616710, "Server finished with tokens after crash" },
+{ 572616711, "Fileset reestablishing tokens after move" },
+{ 572616712, "Fileset finished with tokens after move" },
+{ 572616713, "Authentication level too high for this fileserver" },
+{ 572616714, "Authentication level too low for this fileserver" },
+{ 572616715, "Authentication level too high for this fileset" },
+{ 572616716, "Authentication level too low for this fileset" },
+{ 572616717, "Authentication level too high somehow" },
+{ 572616718, "Authentication level too low somehow" },
+{ 572825601, "could not attach fileset" },
+{ 572825602, "could not detach fileset" },
+{ 572825603, "illegal aggregate" },
+{ 572825604, "bad fileset name" },
+{ 572825605, "insufficient privilege for fileset operation" },
+{ 572825606, "error from fileset location database" },
+{ 572825607, "fileset moved" },
+{ 572825608, "illegal fileset operation" },
+{ 572825609, "badly formatted dump" },
+{ 572825610, "restoring bad format dump" },
+{ 572825611, "fileset release failed" },
+{ 572825612, "fileset still in use by ftserver" },
+{ 572825613, "out of virtual memory in ftserver" },
+{ 572825614, "no such fileset" },
+{ 572825615, "more than one read/write fileset" },
+{ 572825616, "not all entries successfully processed" },
+{ 572825617, "I/O error" },
+{ 572825618, "the operation is not yet implemented" },
+{ 572825619, "FLDB client not initialized" },
+{ 572825620, "fldb entry is missing its R/W ID" },
+{ 572825621, "fldb entry is missing its R/O ID" },
+{ 572825622, "fldb entry is missing its backup ID" },
+{ 572825623, "bad rpc binding handle returned" },
+{ 572825624, "malformed server address" },
+{ 572825625, "I/O error in pipe" },
+{ 572825626, "source fileset is inconsistent" },
+{ 572825627, "specified group not in specified cell" },
+{ 572825628, "fldb entry inconsistency" },
+{ 572825629, "fileset already exists in a different site" },
+{ 572825630, "cannot restore replicated filesets" },
+{ 572825631, "fts spare3" },
+{ 572825632, "fts spare4" },
+{ 572825633, "could not attach fileset" },
+{ 572825634, "could not detach fileset" },
+{ 572825635, "aggregate not present and exported" },
+{ 572825636, "bad fileset name" },
+{ 572825637, "insufficient privilege for fileset operation" },
+{ 572825638, "error from fileset location database" },
+{ 572825639, "fileset moved" },
+{ 572825640, "illegal fileset operation" },
+{ 572825641, "badly formatted dump" },
+{ 572825642, "restoring bad format dump" },
+{ 572825643, "fileset release failed" },
+{ 572825644, "fileset still in use by ftserver" },
+{ 572825645, "fileset is offline" },
+{ 572825646, "out of virtual memory in ftserver" },
+{ 572825647, "no such fileset" },
+{ 572825648, "more than one read/write fileset" },
+{ 572825649, "I/O error" },
+{ 572825650, "Transaction already exists" },
+{ 572825651, "Transaction doesn't exist" },
+{ 572825652, "internal error releasing transaction" },
+{ 572825653, "Fileset already deleted" },
+{ 572825654, "Fileset locally mounted" },
+{ 572825655, "incremental dump date begins after target completes" },
+{ 572825656, "incremental dump version begins after target completes" },
+{ 572825657, "incremental dump completes before target does" },
+{ 572825658, "incremental dump decreases target's version" },
+{ 572825659, "dump contains a bad ACL" },
+{ 572825660, "dump contains an ACL with an unknown entry type" },
+{ 572825661, "unsupported data transfer protocol" },
+{ 572833793, "Aggregate is already attached" },
+{ 572833794, "Obsolete error code number 1" },
+{ 572833795, "Aggregate is not attached" },
+{ 572833796, "Aggregate may need to be recovered" },
+{ 572833797, "Fileset is locally mounted" },
+{ 572833798, "This fileset has no backing fileset" },
+{ 572833799, "Fileset does not exist" },
+{ 572833800, "Name is too long" },
+{ 572833801, "ID is not unique" },
+{ 572833802, "Name is not unique" },
+{ 572833803, "Fileset ID is malformed" },
+{ 572833804, "The aggregate is in use; detach before continuing" },
+{ 572833805, "Obsolete error code number 2" },
+{ 572833806, "Cannot find corresponding character device" },
+{ 572833807, "Device is locked; an administrative operation may be in progress" },
+{ 572833808, "Must specify a block device" },
+{ 572833809, "Must specify a character device" },
+{ 572833810, "Must specify a device" },
+{ 572833811, "Dump stream is corrupted" },
+{ 572833812, "Out of memory" },
+{ 572833813, "Date of incremental dump is newer than the last modification" },
+{ 572833814, "Version of incremental dump is newer than the last modification" },
+{ 572833815, "End date of incremental dump is older than the last modification" },
+{ 572833816, "End version of incremental dump is older than the last modification" },
+{ 572833817, "Specified mount type is unknown" },
+{ 572833818, "Specified fileset is not head of fileset chain" },
+{ 572833819, "The restored fileset is inconsistent" },
+{ 572833820, "Validation failure for the ACL being restored" },
+{ 572833821, "ACL being restored has a bad entry type" },
+{ 572833822, "Mismatch betwwen aggregate minor version number and DM management status; run salvage" },
+{ 572833823, "DM aggregate being attached as native Episode aggregate and without -force switch; check dfstab file" },
+{ 572833824, "Non-DM aggregate being attached as DM aggregate; check dfstab file" },
+{ 572833825, "Validation failure for the extended attribute list being restored" },
+{ 585773057, "Bad token." },
+{ 585773058, "Client host is down." },
+{ 585773059, "Only some of the tokens are revoked." },
+{ 585773060, "Unrecognized host pointer (not used)." },
+{ 585773061, "Revoke operation failed." },
+{ 585773062, "Dont need the token issued by async grant." },
+{ 585773063, "Revocation failed but host isn't down yet." },
+{ 585773064, "Interface is no longer supported." },
+{ 589672449, "specified set not found" },
+{ 589672450, "specified log not found" },
+{ 589672451, "cannot open specified dump file" },
+{ 589672452, "Date at time 0.000000 was: ..24s" },
+{ 589672453, "could not allocate the memory for bulk set info structure" },
+{ 589672454, "could not allocate the memory for bulk log info structure" },
+{ 589672455, "-follow not supported for user-level tracing" },
+{ 589672456, "-sleep not supported for user-level tracing" },
+{ 589672457, "-sleep can only be used with -follow" },
+{ 589672458, "file names for dumps of user-level tracing cannot contain '/'." },
+{ 589672459, "invalid operation on set" },
+{ 589672460, "cannot change state of set" },
+{ 589672461, "only the first 64 sets are recognized" },
+{ 589672462, "only the first 64 logs are recognized" },
+{ 589672463, "specified log is unallocated" },
+{ 589672464, "specified log has zero size" },
+{ 589672465, "zero-length record detected" },
+{ 589672466, "-log not yet supported for user-level tracing" },
+{ 589672467, "-raw not yet supported for user-level tracing" },
+{ 589672469, "Logging .d recs <=.d usec" },
+{ 589672470, "Logged .d records in .d usec (min .d/max .d)" },
+{ 609947649, "the buffer address given was invalid" },
+{ 609947650, "the log/buffer package was reinitialized" },
+{ 609947651, "the specified memory region is too small" },
+{ 609947652, "the buffer is not valid" },
+{ 609947653, "the log has not been recovered" },
+{ 609947654, "the specified log was not valid" },
+{ 609947655, "the specified transaction is not valid" },
+{ 609947656, "the specified transaction is no longer valid" },
+{ 609947657, "the specified buffer could not be deleted" },
+{ 609947658, "the specified transaction is active" },
+{ 609947659, "the specified transaction has ended" },
+{ 609947660, "the specified transaction has completed" },
+{ 609947661, "the specified transaction has committed" },
+{ 609947663, "the specified value is not valid" },
+{ 609947664, "the specified operation is not valid" },
+{ 609947665, "no buffers were available to satisfy the request" },
+{ 609947666, "the log was not active" },
+{ 609947667, "there are no free log buffers" },
+{ 609947669, "the requested log already exists" },
+{ 609947670, "an insufficient # of buffers were given to the log" },
+{ 609947671, "duplicate request to log_Shutdown" },
+{ 609947672, "there is no available space on the log device" },
+{ 609947673, "one or more arguments was invalid" },
+{ 609947674, "could not read log in for recovery" },
+{ 609947675, "an invalid start record was found in the log" },
+{ 609947676, "a transaction was detected out-of-order" },
+{ 609947677, "an error was encountered during recovery" },
+{ 609947678, "an invalid reference was found" },
+{ 609947679, "an invalid log record was found" },
+{ 609947680, "an internal sanity check failed" },
+{ 609947681, "an invalid log page was encountered" },
+{ 609947682, "a null pointer ref was detected" },
+{ 609947683, "an invalid pointer was detected" },
+{ 609947684, "an invalid record type was found during redo" },
+{ 609947685, "an invalid record type was found during undo" },
+{ 609947686, "an I/O error was detected during recovery" },
+{ 609947687, "performed recovery" },
+{ 609947688, "recovery must be run on this aggregate" },
+{ 609947689, "the requested operation would block" },
+{ 609947690, "a log page with a bad pass number was found" },
+{ 609947691, "an uncommitted kill preceded a metadata record" },
+{ 609947692, "an uncommitted metadata preceded a kill record" },
+{ 648998913, "Invalid parameter" },
+{ 648998914, "Volume Version log too short for that" },
+{ 648998915, "Given volume is not a replica" },
+{ 648998916, "Given volume is not on this server" },
+{ 648998917, "Minimum pounce interval not yet expired" },
+{ 648998918, "Ignoring your request" },
+{ 648998919, "Unknown replication type" },
+{ 648998920, "Out of (stable) storage" },
+{ 648998921, "Destroy volume rather than bring it up" },
+{ 648998922, "Cell ID mismatch" },
+{ 648998923, "End of returned items" },
+{ 648998924, "Draft volume being created" },
+{ 648998925, "Old replica volume busy" },
+{ 648998926, "A recent attempt to establish a connection failed" },
+{ 648998927, "A connection reset attempt failed" },
+{ 654880769, "insufficient memory to salvage " },
+{ 655257601, "SCX All OK: new-style exporter" },
+{ 655257602, "New-style exporter: needs a RESET" },
+{ 655257603, "SCX spare 1" },
+{ 655257604, "SCX spare 2" },
+{ 655257605, "SCX spare 3" },
+{ 655257606, "SCX spare 4" },
+{ 655257607, "SCX spare 5" },
+{ 655257608, "SCX spare 6" },
+{ 655257609, "SCX spare 7" },
+{ 655257610, "SCX spare 8" },
+{ 655257611, "SCX spare 9" },
+{ 655257612, "SCX spare 10" },
+{ 655257613, "SCX spare 11" },
+{ 655257614, "SCX spare 12" },
+{ 655257615, "SCX spare 13" },
+{ 655257616, "SCX spare 14" },
+{ 655257617, "SCX spare 15" },
+{ 655257618, "SCX spare 16" },
+{ 655257619, "SCX spare 17" },
+{ 655257620, "SCX spare 18" },
+{ 655257621, "SCX spare 19" },
+{ 655257622, "SCX spare 20" },
+{ 655257623, "SCX spare 21" },
+{ 655257624, "SCX spare 22" },
+{ 655257625, "SCX spare 23" },
+{ 655257626, "SCX spare 24" },
+{ 655257627, "SCX spare 25" },
+{ 655257628, "SCX spare 26" },
+{ 655257629, "SCX spare 27" },
+{ 655257630, "SCX spare 28" },
+{ 655257631, "SCX spare 29" },
+{ 655257632, "SCX spare 30" },
+{ 655257633, "SCX spare 31" },
+{ 655257634, "SCX spare 32" },
+{ 655257635, "SCX spare 33" },
+{ 655257636, "SCX spare 34" },
+{ 655257637, "SCX spare 35" },
+{ 655257638, "SCX spare 36" },
+{ 655257639, "SCX spare 37" },
+{ 655257640, "SCX spare 38" },
+{ 655257641, "SCX spare 39" },
+{ 655257642, "SCX spare 40" },
+{ 655257643, "SCX All OK: init-flags base value" },
+{ 663076865, "Illegal host specified" },
+{ 663076866, "Incorrect file specification" },
+{ 663076867, "Token type given is not a legal token type" },
+{ 663076868, "Invalid token ID specified" },
+{ 663076869, "TKM entry is locked by another entity" },
+{ 663076870, "TKM does not know about specified file" },
+{ 663076871, "Attempt to fulfill request took longer than time limit specified" },
+{ 663076872, "Token requested was in conflict with another (non-revocable) token" },
+{ 663076873, "Invalid or inconsistent token description given" },
+{ 663076874, "Token request was queued for later consideration" },
+{ 663076875, "Token was deleted from token database during locking" },
+{ 663076876, "TKM does not know about specified token" },
+{ 663076877, "Token permission set not within MaxToken for named volume" },
+{ 663076878, "Too many outstanding tokens on the fid specified" },
+{ 663076879, "Too many outstanding tokens held by the host specified" },
+{ 663076880, "Token request conflicted with non-revocable token, try again" },
+{ 663076881, "Token manager operation not supported" },
+{ 663076882, "Token manager unable to get required memory for operation" },
+{ 663076883, "Internal code for not TRYAGAIN" },
+{ 663076884, "Tokens for 64 bit byteranges cannot be granted yet" },
+{ 668147713, "no quorum elected" },
+{ 668147714, "not synchronization site (should work on sync site)" },
+{ 668147715, "too many hosts" },
+{ 668147716, "I/O error writing dbase or log" },
+{ 668147717, "mysterious internal error" },
+{ 668147718, "major synchronization error" },
+{ 668147719, "file not found when processing dbase" },
+{ 668147720, "bad lock range size (must be 1)" },
+{ 668147721, "read error reprocessing log" },
+{ 668147722, "problems with host name" },
+{ 668147723, "bad operation for this transaction type" },
+{ 668147724, "two commits or aborts done to transaction" },
+{ 668147725, "operation done after abort (or commmit)" },
+{ 668147726, "no servers appear to be up" },
+{ 668147727, "premature EOF" },
+{ 668147728, "error writing log file" },
+{ 668147729, "unsupported address family" },
+{ 668147730, "inconsistent cell name" },
+{ 668147731, "security group bad or missing" },
+{ 668147732, "server group name bad or missing" },
+{ 668147733, "server uuid bad or missing" },
+{ 668147734, "memory allocation failure" },
+{ 668147735, "host not a member of server group" },
+{ 668147736, "too many bindings per server" },
+{ 668147737, "inconsistent principal name from binding" },
+{ 668147738, "I/O error in ubik pipe" },
+{ 668147739, "two sync sites prevent dead lock" },
+{ 668147740, "rpc runtime exception caught" },
+{ 668147741, "vote thread pool queue operation failed" },
+{ 668147742, "clock skew among servers too high" },
+{ 668147743, "repeatedly failed to obtain ubik lock" },
+{ 668147744, "permission denied for attempted operation" },
+{ 668147745, "no space left on database device" },
+{ 668147746, "invalid DB pathname" },
+{ 668147747, "bad file descriptor" },
+{ 668147748, "cannot start async RPC call is in progress" },
+{ 668147749, "cannot end async RPC no call in progress" },
+{ 668147750, "down level server does not support this request" },
+{ 668147751, "invalid opcode in bulk update request" },
+{ 668147752, "null pointer passed to ubik routine" },
+{ 670412801, "Recoverable error" },
+{ 670412802, "Unrecoverable error" },
+{ 670412803, "Object is not in export list" },
+{ 670412804, "Can't create/open file" },
+{ 670412805, "Can't write file" },
+{ 670412806, "Unsupported rpc interface" },
+{ 676372481, "FLDB: fileset Id entry already exists in fldb" },
+{ 676372482, "FLDB: unsuccessful read from fldb" },
+{ 676372483, "FLDB: fileset name entry exists in fldb" },
+{ 676372484, "FLDB: internal creation failure" },
+{ 676372485, "FLDB: no such entry" },
+{ 676372486, "FLDB: fldb is empty" },
+{ 676372487, "FLDB: fileset name is illegal" },
+{ 676372488, "FLDB: index is out of range" },
+{ 676372489, "FLDB: bad fileset type" },
+{ 676372490, "FLDB: illegal server number (out of range)" },
+{ 676372491, "FLDB: bad partition number" },
+{ 676372492, "FLDB: run out of space for Replication sites" },
+{ 676372493, "FLDB: no such Replication server site exists" },
+{ 676372494, "FLDB: replication site already exists" },
+{ 676372495, "FLDB: parent R/W entry not found" },
+{ 676372496, "FLDB: illegal Reference Count number" },
+{ 676372497, "FLDB: fldb size for attributes exceeded" },
+{ 676372498, "FLDB: bad incoming fldb entry" },
+{ 676372499, "FLDB: illegal max fsid increment" },
+{ 676372500, "FLDB: RO/BACK id already hashed" },
+{ 676372501, "FLDB: fldb entry is already locked" },
+{ 676372502, "FLDB: bad fileset operation code" },
+{ 676372503, "FLDB: bad release lock type" },
+{ 676372504, "FLDB: status report: last release was aborted" },
+{ 676372505, "FLDB: invalid replication site server flag" },
+{ 676372506, "FLDB: no permission access" },
+{ 676372507, "FLDB: malloc(realloc) failed to alloc enough memory" },
+{ 676372508, "FLDB: site table corrupted" },
+{ 676372509, "FLDB: cannot remove last address for a site" },
+{ 676372510, "FLDB: out of space for addresses for a site" },
+{ 676372511, "FLDB: address already exists in this site" },
+{ 676372512, "FLDB: address already exists in another site" },
+{ 676372513, "FLDB: facility is not yet implemented" },
+{ 676372514, "FLDB: at end of list" },
+{ 676372515, "FLDB: no remaining quota for creations on a server" },
+{ 676372516, "FLDB: the given server does not exist" },
+{ 676372517, "FLDB: bad site cookie value given" },
+{ 676372518, "FLDB: internal inconsistency detected" },
+{ 676372519, "FLDB: no such server in FLDB" },
+{ 676372520, "FLDB: fileset ID was not reserved" },
+{ 676372521, "FLDB: site entry is still in use" },
+{ 676372522, "FLDB: FL entry refers to a deleted site" },
+{ 676372523, "FLDB: cannot create FLDB with read-only operation" },
+{ 676372524, "FLDB: principal name too long" },
+{ 688001025, "No entry found" },
+{ 688001026, "Not enough room in buffer" },
+{ 688001027, "Named base attribute doesn't exist" },
+{ 688001028, "Conflicting base attribute" },
+{ 691089409, "lowest bound for persistent errors" },
+{ 691089410, "fileset not present and exported on server: already deleted/moved" },
+{ 691089411, "bad opcode passed to dump" },
+{ 691089412, "bad dump format" },
+{ 691089413, "bad ftserver ops vector passed in" },
+{ 691089414, "fileset deleted by repserver" },
+{ 691089415, "fileset inconsistent" },
+{ 691089416, "bad fileset ops vector passed in" },
+{ 691089417, "fileset out of service pending a move cleanup" },
+{ 691089418, "fileset out of service pending clone completion" },
+{ 691089419, "fileset is being detached" },
+{ 691089420, "license for fileset or software is missing or expired" },
+{ 691089421, "replica not current enough" },
+{ 691089422, "fileset is locally mounted" },
+{ 691089423, "future persistent volerr 14" },
+{ 691089424, "future persistent volerr 15" },
+{ 691089425, "future persistent volerr 16" },
+{ 691089426, "future persistent volerr 17" },
+{ 691089427, "future persistent volerr 18" },
+{ 691089428, "future persistent volerr 19" },
+{ 691089429, "future persistent volerr 20" },
+{ 691089430, "future persistent volerr 21" },
+{ 691089431, "future persistent volerr 22" },
+{ 691089432, "future persistent volerr 23" },
+{ 691089433, "future persistent volerr 24" },
+{ 691089434, "future persistent volerr 25" },
+{ 691089435, "future persistent volerr 26" },
+{ 691089436, "future persistent volerr 27" },
+{ 691089437, "future persistent volerr 28" },
+{ 691089438, "future persistent volerr 29" },
+{ 691089439, "future persistent volerr 30" },
+{ 691089440, "future persistent volerr 31" },
+{ 691089441, "future persistent volerr 32" },
+{ 691089442, "future persistent volerr 33" },
+{ 691089443, "future persistent volerr 34" },
+{ 691089444, "future persistent volerr 35" },
+{ 691089445, "future persistent volerr 36" },
+{ 691089446, "future persistent volerr 37" },
+{ 691089447, "future persistent volerr 38" },
+{ 691089448, "future persistent volerr 39" },
+{ 691089449, "future persistent volerr 40" },
+{ 691089450, "future persistent volerr 41" },
+{ 691089451, "future persistent volerr 42" },
+{ 691089452, "future persistent volerr 43" },
+{ 691089453, "future persistent volerr 44" },
+{ 691089454, "future persistent volerr 45" },
+{ 691089455, "future persistent volerr 46" },
+{ 691089456, "future persistent volerr 47" },
+{ 691089457, "future persistent volerr 48" },
+{ 691089458, "future persistent volerr 49" },
+{ 691089459, "future persistent volerr 50" },
+{ 691089460, "future persistent volerr 51" },
+{ 691089461, "future persistent volerr 52" },
+{ 691089462, "future persistent volerr 53" },
+{ 691089463, "future persistent volerr 54" },
+{ 691089464, "future persistent volerr 55" },
+{ 691089465, "future persistent volerr 56" },
+{ 691089466, "future persistent volerr 57" },
+{ 691089467, "future persistent volerr 58" },
+{ 691089468, "future persistent volerr 59" },
+{ 691089469, "future persistent volerr 60" },
+{ 691089470, "future persistent volerr 61" },
+{ 691089471, "future persistent volerr 62" },
+{ 691089472, "future persistent volerr 63" },
+{ 691089473, "future persistent volerr 64" },
+{ 691089474, "future persistent volerr 65" },
+{ 691089475, "future persistent volerr 66" },
+{ 691089476, "future persistent volerr 67" },
+{ 691089477, "future persistent volerr 68" },
+{ 691089478, "future persistent volerr 69" },
+{ 691089479, "future persistent volerr 70" },
+{ 691089480, "future persistent volerr 71" },
+{ 691089481, "future persistent volerr 72" },
+{ 691089482, "future persistent volerr 73" },
+{ 691089483, "future persistent volerr 74" },
+{ 691089484, "future persistent volerr 75" },
+{ 691089485, "future persistent volerr 76" },
+{ 691089486, "future persistent volerr 77" },
+{ 691089487, "future persistent volerr 78" },
+{ 691089488, "future persistent volerr 79" },
+{ 691089489, "future persistent volerr 80" },
+{ 691089490, "future persistent volerr 81" },
+{ 691089491, "future persistent volerr 82" },
+{ 691089492, "future persistent volerr 83" },
+{ 691089493, "future persistent volerr 84" },
+{ 691089494, "future persistent volerr 85" },
+{ 691089495, "future persistent volerr 87" },
+{ 691089496, "future persistent volerr 88" },
+{ 691089497, "future persistent volerr 89" },
+{ 691089498, "future persistent volerr 90" },
+{ 691089499, "future persistent volerr 91" },
+{ 691089500, "future persistent volerr 92" },
+{ 691089501, "future persistent volerr 93" },
+{ 691089502, "future persistent volerr 94" },
+{ 691089503, "future persistent volerr 95" },
+{ 691089504, "future persistent volerr 96" },
+{ 691089505, "future persistent volerr 97" },
+{ 691089506, "future persistent volerr 98" },
+{ 691089507, "future persistent volerr 99" },
+{ 691089508, "future persistent volerr 100" },
+{ 691089509, "lowest bound for transient errors" },
+{ 691089510, "fileset being deleted/moved" },
+{ 691089511, "fileset being dumped" },
+{ 691089512, " fileset being restored" },
+{ 691089513, "fileset being cloned" },
+{ 691089514, "fileset being recloned" },
+{ 691089515, "list filesets" },
+{ 691089516, "get status on fileset" },
+{ 691089517, "create new fileset" },
+{ 691089518, "fileset being released" },
+{ 691089519, "set quota on fileset" },
+{ 691089520, "testing for fileset existence" },
+{ 691089521, "set flags on fileset" },
+{ 691089522, "set status on fileset" },
+{ 691089523, "copy the clone to a new location" },
+{ 691089524, "release-clone fileset being copied" },
+{ 691089525, "fileset being dumped to tape" },
+{ 691089526, "fileset being restored from tape" },
+{ 691089527, "repserver getting status on fileset" },
+{ 691089528, "repserver setting status on fileset" },
+{ 691089529, "repserver setting fileset version" },
+{ 691089530, "repserver cloning fileset" },
+{ 691089531, "repserver editing fileset status" },
+{ 691089532, "repserver clearing fileset status" },
+{ 691089533, "repserver uncloning fileset" },
+{ 691089534, "repserver switching filesets" },
+{ 691089535, "repserver getting fileset changes" },
+{ 691089536, "repserver forwarding fileset" },
+{ 691089537, "no more memory" },
+{ 691089538, "pipe i/o failure" },
+{ 691089539, "fileset is over quota" },
+{ 691089540, "replica earlier than latest seen" },
+{ 691089541, "fileset being moved" },
+{ 691089542, "fileset operation sequence being started" },
+{ 691089543, "license for fileset or software is expired or missing" },
+{ 691089544, "replica not known to be current enough" },
+{ 691089545, "external file manager is still working on this file" },
+{ 691089546, "file is externally managed for the next 1 second" },
+{ 691089547, "file is externally managed for the next 4 seconds" },
+{ 691089548, "file is externally managed for the next 16 seconds" },
+{ 691089549, "file is externally managed for the next 64 seconds" },
+{ 691089550, "file is externally managed for the next 256 seconds" },
+{ 691089551, "file is externally managed for the next 1024 seconds" },
+{ 691089552, "future transient volerr 43" },
+{ 691089553, "future transient volerr 44" },
+{ 691089554, "future transient volerr 45" },
+{ 691089555, "future transient volerr 46" },
+{ 691089556, "future transient volerr 47" },
+{ 691089557, "future transient volerr 48" },
+{ 691089558, "future transient volerr 49" },
+{ 691089559, "future transient volerr 50" },
+{ 691089560, "future transient volerr 51" },
+{ 691089561, "future transient volerr 52" },
+{ 691089562, "future transient volerr 53" },
+{ 691089563, "future transient volerr 54" },
+{ 691089564, "future transient volerr 55" },
+{ 691089565, "future transient volerr 56" },
+{ 691089566, "future transient volerr 57" },
+{ 691089567, "future transient volerr 58" },
+{ 691089568, "future transient volerr 59" },
+{ 691089569, "future transient volerr 60" },
+{ 691089570, "future transient volerr 61" },
+{ 691089571, "future transient volerr 62" },
+{ 691089572, "future transient volerr 63" },
+{ 691089573, "future transient volerr 64" },
+{ 691089574, "future transient volerr 65" },
+{ 691089575, "future transient volerr 66" },
+{ 691089576, "future transient volerr 67" },
+{ 691089577, "future transient volerr 68" },
+{ 691089578, "future transient volerr 69" },
+{ 691089579, "future transient volerr 70" },
+{ 691089580, "future transient volerr 71" },
+{ 691089581, "future transient volerr 72" },
+{ 691089582, "future transient volerr 73" },
+{ 691089583, "future transient volerr 74" },
+{ 691089584, "future transient volerr 75" },
+{ 691089585, "future transient volerr 76" },
+{ 691089586, "future transient volerr 77" },
+{ 691089587, "future transient volerr 78" },
+{ 691089588, "future transient volerr 79" },
+{ 691089589, "future transient volerr 80" },
+{ 691089590, "future transient volerr 81" },
+{ 691089591, "future transient volerr 82" },
+{ 691089592, "future transient volerr 83" },
+{ 691089593, "future transient volerr 84" },
+{ 691089594, "future transient volerr 85" },
+{ 691089595, "future transient volerr 87" },
+{ 691089596, "future transient volerr 88" },
+{ 691089597, "future transient volerr 89" },
+{ 691089598, "future transient volerr 90" },
+{ 691089599, "future transient volerr 91" },
+{ 691089600, "future transient volerr 92" },
+{ 691089601, "future transient volerr 93" },
+{ 691089602, "future transient volerr 94" },
+{ 691089603, "future transient volerr 95" },
+{ 691089604, "future transient volerr 96" },
+{ 691089605, "future transient volerr 97" },
+{ 691089606, "future transient volerr 98" },
+{ 691089607, "future transient volerr 99" },
+{ 691089608, "future transient volerr 100" },
+{ 691089609, "upper bound for transient errors" },
+{ 700735489, "agfs_Unmount vfsp .#x aggrid .d" },
+{ 700735490, "agfs_Unmount failed code .d" },
+{ 700735491, "agfs_Unmount result code .d" },
+{ 700878849, "bnode_GetString entered" },
+{ 700878850, "bnode_GetString returning .d" },
+{ 700878851, "bnode_GetParm entered" },
+{ 700878852, "bnode_GetParm returning .d" },
+{ 700878853, "bnode_GetStat entered" },
+{ 700878854, "bnode_GetStat returning .d" },
+{ 700878855, "bnode_RestartP entered" },
+{ 700878856, "bnode_RestartP returning .d" },
+{ 700878857, "bnode_Check entered" },
+{ 700878858, "bnode_Check returning .d" },
+{ 700878859, "bnode_HasCore entered" },
+{ 700878860, "bnode_HasCore returning .d" },
+{ 700878861, "bnode_WaitAll entered" },
+{ 700878862, "bnode_WaitAll returning .d" },
+{ 700878863, "bnode_WaitStatus entered" },
+{ 700878864, "bnode_WaitStatus returning .d" },
+{ 700878865, "bnode_SetStat entered" },
+{ 700878866, "bnode_SetStat returning .d" },
+{ 700878867, "bnode_SetGoal entered" },
+{ 700878868, "bnode_SetGoal returning .d" },
+{ 700878869, "bnode_SetFileGoal entered" },
+{ 700878870, "bnode_SetFileGoal returning .d" },
+{ 700878871, "bnode_InitFileGoal entered" },
+{ 700878872, "bnode_InitFileGoal returning .d" },
+{ 700878873, "bnode_ApplyInstance entered" },
+{ 700878874, "bnode_ApplyInstance returning .d" },
+{ 700878875, "bnode_Create entered" },
+{ 700878876, "bnode_Create returning .d" },
+{ 700878877, "bnode_DeleteName entered" },
+{ 700878878, "bnode_DeleteName returning .d" },
+{ 700878879, "bnode_Delete entered" },
+{ 700878880, "bnode_Delete returning .d" },
+{ 700878881, "bnode_PendingTimeout entered" },
+{ 700878882, "bnode_PendingTimeout returning .d" },
+{ 700878883, "bnode_SetTimeout entered" },
+{ 700878884, "bnode_SetTimeout returning .d" },
+{ 700878885, "bnode_InitBnode entered" },
+{ 700878886, "bnode_InitBnode returning .d" },
+{ 700878887, "bnode_DoExec entered" },
+{ 700878888, "bnode_DoExec: about to exec .s with .d args" },
+{ 700878889, "bnode_DoExec: about to return .d (this is an error condition!)" },
+{ 700878890, "bnode_NewProc entered bnode name: .s" },
+{ 700878891, "bnode_NewProc: returning .d" },
+{ 700878892, "bnode_StopProc entered" },
+{ 700878893, "bnode_StopProc: returning .d" },
+{ 700878894, "bnode_Deactivate entered" },
+{ 700878895, "bnode_Deactivate: returning .d" },
+{ 700878896, "bnode_IdValid entered" },
+{ 700878897, "bnode_IdValid returning .d" },
+{ 700878898, "bosserver: about to listen for network requests." },
+{ 700878899, "bosserver: NCS_Init about to call rpc_server_listen" },
+{ 700878900, "bosserver: NCS_Init returned from rpc_server_listen" },
+{ 700878901, ".s called." },
+{ 700878902, ".s returning: .s." },
+{ 700878903, "BOSSVR_GetServerStatus entered" },
+{ 700878904, "BOSSVR_GetServerStatus returning .d" },
+{ 700878905, "BOSSVR_CreateBnode params: name = .s type = .s cmdLine = .s .s . . ." },
+{ 700878906, " .s .s .s .s" },
+{ 700878907, "BOSSVR_GetStatus params: instance .s." },
+{ 700878908, "BOSSVR_GetInstanceInfo params: process: .s." },
+{ 700878909, "BOSSVR_AddSUser params: name: .s type: .s." },
+{ 700878910, ".s exiting; returning name: .s" },
+{ 700878911, "BOSSVR_GetDates params: file: .s" },
+{ 700878912, "BOSSVR_ListKeys: we have the wrong key and can't free it: .s" },
+{ 700878913, "BOSSVR_ListKeys: can't free key: .s" },
+{ 700878914, "BOSSVR_AddKey: can't free key: .s" },
+{ 700887041, "sec_id_parse_name: entry name=.s" },
+{ 700887042, "sec_id_parse_name: exit code:.d " },
+{ 700887043, "dfs_GetJunctionName: entry" },
+{ 700887044, "dfs_GetJunctionName: exit code:.d " },
+{ 700887045, "malloc: string of dfs junction: err" },
+{ 700887046, "rpc_ns_entry_inq_resolution: entry" },
+{ 700887047, "rpc_ns_entry_inq_resolution: exit code:.d " },
+{ 700887048, "ubik_ClientInit: entry" },
+{ 700887049, "ubik_ClientInit: exit code:.d " },
+{ 700887050, "dnsGetHandle: err" },
+{ 700887051, "dnsEnumAttr: entry" },
+{ 700887052, "dnsEnumAttr: exit code:.d " },
+{ 700887053, "rpc_binding_inq_object: entry conns:.x" },
+{ 700887054, "rpc_binding_inq_object: exit conns:.x code:.d" },
+{ 700887055, "rpcx_binding_to_sockaddr: entry conns:.x" },
+{ 700887056, "rpcx_binding_to_sockaddr: exit conns:.x code:.d" },
+{ 700887057, "helper read: entry" },
+{ 700887058, "helper read: exit code:.d " },
+{ 700887059, "ProcessRequest: entry" },
+{ 700887060, "ProcessRequest: exit code:.d " },
+{ 700887061, "helper write: entry" },
+{ 700887062, "helper write: exit code:.d " },
+{ 700887063, "do_auth_request: entry" },
+{ 700887064, "do_auth_request: exit code:.d " },
+{ 700887065, "pioctl returned invalid opcode:.d " },
+{ 700887066, "principal: .s expires: .s" },
+{ 700887067, "cred file: .s" },
+{ 700887068, "no flservers available" },
+{ 700887069, "freelist exhausted, queueing call" },
+{ 700887070, "License server sent event:.d " },
+{ 700887071, "license event type .d .s" },
+{ 700887072, "condensing request: .d" },
+{ 700887073, "ProcessRequest: entry, opcode .d" },
+{ 700887074, "ProcessRequest: took .d seconds, exit code:.d" },
+{ 700887075, "Dispatch: waiting for memory" },
+{ 700887076, "BetterError: given .d and default .d, returning .d" },
+{ 700887077, "helper write failed: errno:.d, tid:.d opcode:.d outSize:.d" },
+{ 700887078, "helper read failed: errno:.d, retrying in .d seconds" },
+{ 700887079, "adding req id=.d to .s-pri queue, now having .d item(s)" },
+{ 700887080, "removing req id=.d from .s-pri queue, now having .d item(s) left" },
+{ 700887081, "req .d: condensing .s-pri queue: from .d to .d item(s)" },
+{ 700887082, "ProcessRequest: entry, opcode .d; req .d" },
+{ 700887083, "req .d: op .d, size .d" },
+{ 700887084, "name lookup request (size .d): .s" },
+{ 700887085, "get_cred(pag .d, euid .d):" },
+{ 700887086, " get_cred(): server .s, level .d, protocol .d" },
+{ 700887087, "build_msg(pag .d, euid .d, credpag .d, credeuid .d):" },
+{ 700887088, " build_msg(): crlvl .d, crprotoc .d, exp .d, server .s" },
+{ 700887089, "decode_msg()" },
+{ 700887090, "UNKNOWN MESSAGE TYPE" },
+{ 700887091, "gen_block()" },
+{ 700887092, "gen_key()" },
+{ 700887093, "register_server(server .s)" },
+{ 700887094, "Substituting for sec_id_parse_name: results are ``.s'' and ``.s''" },
+{ 700887095, "Entry is local cell: .s" },
+{ 700887096, "Dispatch: waiting for memory for output buffer of size:.d" },
+{ 701087745, "CM write vp .x, off .lld, len .d" },
+{ 701087746, "CM read vp .x, off .lld, len .d, flen .lld" },
+{ 701087747, "CM write vp .x, error .d" },
+{ 701087748, "CM read vp .x, error .d" },
+{ 701087749, "CM bioread vp .x, off .lld, len .d, bflags .x" },
+{ 701087750, "CM biowrite vp .x, off .lld, len .d, bflags .x" },
+{ 701087751, "CM bioread done code .d" },
+{ 701087752, "CM biowrite done code .d" },
+{ 701087753, "CM cm_lookup .x .s" },
+{ 701087754, "CM cm_GetACLCache vp .x pag .x" },
+{ 701087755, "CM foundaclcache rights .x" },
+{ 701087756, "CM addacl vp .x pag .x rights .#x" },
+{ 701087757, "CM free all acls vp .x" },
+{ 701087758, "CM invalidate acl vp .x, user .x" },
+{ 701087759, "CM bkg found req .d, vp .x" },
+{ 701087760, "CM cm_NewCell .s" },
+{ 701087761, "CM creating cell .s" },
+{ 701087762, "CM looking for cell .s" },
+{ 701087763, "CM start VL_GetCellInfo" },
+{ 701087764, "CM end VL_GetCellInfo, code .d" },
+{ 701087765, "CM cm_ConnByAddr: creating conn type .#x, conn .x" },
+{ 701087766, "CM stomping binding .x" },
+{ 701087767, "CM mark conn bad for pag .x" },
+{ 701087768, "CM GC conns .#x" },
+{ 701087769, "CM get TGT time .x for pag .x" },
+{ 701087770, "CM start AFS_SetContext conn .x srv level .#x" },
+{ 701087771, "CM end AFS_SetContext code .d" },
+{ 701087772, "CM cm_ConnByMHosts server type .x" },
+{ 701087773, "CM cm_ConnByMHosts: all filesets bad" },
+{ 701087774, "CM cm_ConnByMHosts: fileset Id(.d) went busy" },
+{ 701087775, "CM cm_ConnByAddr server type .#x, serverp .x" },
+{ 701087776, "CM cm_ConnByMHosts: found .d-th server down" },
+{ 701087777, "CM cm_ConnByMHosts: reason .d for volume .d" },
+{ 701087778, "CM running cm_CheckVolumeNames" },
+{ 701087779, "CM running FlushActiveSCaches" },
+{ 701087780, "CM flushactivescaches starting .d concurrent storebacks" },
+{ 701087781, "CM running write through dslots" },
+{ 701087782, "CM servertokenmgt running .d subops" },
+{ 701087783, "CM running minor renewlazyreps" },
+{ 701087784, "CM running major renewlazyreps" },
+{ 701087785, "CM RenewLazyReps refresh vol .d, age .d, mtl .d totiv .d" },
+{ 701087786, "CM Renewlazyreps about to refresh .d vols" },
+{ 701087787, "CM running CheckOnVOLRoot" },
+{ 701087788, "CM running refreshkeepalives" },
+{ 701087789, "CM called RefreshKA with .d fids, code .d" },
+{ 701087790, "CM running gcexporter" },
+{ 701087791, "CM running Ping Servers" },
+{ 701087792, "CM Ping Servers queuing at time .x" },
+{ 701087793, "CM Ping Servers done at time .x" },
+{ 701087794, "CM running pingservers no adjust" },
+{ 701087795, "CM running Check Down Servers" },
+{ 701087796, "CM getdcache failed to find vp .x, chunk .d" },
+{ 701087797, "CM getdcache found vp .x, chunk .d in dcp .x" },
+{ 701087798, "CM fetchDCache scp .x, dcp .x" },
+{ 701087799, "CM faking 0 byte entry locally" },
+{ 701087800, "CM start AFS_Readdir at position .d" },
+{ 701087801, "CM end AFS_Readdir, code .d" },
+{ 701087802, "CM start AFS_FetchData at position .d" },
+{ 701087803, "CM end AFS_FetchData, code .d" },
+{ 701087804, "CM storeallsegments vp .x" },
+{ 701087805, "CM locally smushing scp .x, dcp .x" },
+{ 701087806, "CM in cm_GetDownD, need space .d" },
+{ 701087807, "CM in flushDCache, dcp .x" },
+{ 701087808, "CM cm_StoreDCache scp .x, dcp .x" },
+{ 701087809, "CM cm_StoreDCache starts store" },
+{ 701087810, "CM cm_StoreDCache starts end, code .d" },
+{ 701087811, "CM cm_InvalidateAllSegments scp .x" },
+{ 701087812, "CM nh_dolookup dvp .x, name .s" },
+{ 701087813, "CM nh_dolookup calling AFS_Lookup" },
+{ 701087814, "CM nh_dolookup back from AFS_Lookup, code .d" },
+{ 701087815, "CM cm_pioctl vp .x, opcode .d" },
+{ 701087816, "CM start AFS_StoreACL" },
+{ 701087817, "CM end AFS_StoreACL, code .d" },
+{ 701087818, "CM start AFS_FetchACL" },
+{ 701087819, "CM end AFS_FetchACL, code .d" },
+{ 701087820, "CM start removemount RPC" },
+{ 701087821, "CM end removemount RPC, code .d" },
+{ 701087822, "CM cm_Analyze: conn .x, code .d, pag .x" },
+{ 701087823, "CM cm_Analyze: volerr subcode .d" },
+{ 701087824, "CM cm_Analyze: host stale" },
+{ 701087825, "CM cm_Analyze: doing busy retry, vol.low .d" },
+{ 701087826, "CM cm_Analyze: doing fast busy retry, vol.low .d, code .d" },
+{ 701087827, "CM cm_Analyze: check loc of volume .d: result .d, gotNewLoc .d" },
+{ 701087828, "CM starting checkvldb's vlgetentrybyid" },
+{ 701087829, "CM checkvldb's vlgetentrybyid done, code .d" },
+{ 701087830, "CM havetoken revalidate replicated vol .d, time .x" },
+{ 701087831, "CM start AFS_FetchStatus" },
+{ 701087832, "CM end AFS_FetchStatus code .d" },
+{ 701087833, "CM begin AFS_StoreStatus" },
+{ 701087834, "CM end AFS_StoreStatus, code .d" },
+{ 701087835, "CM scanstatus vp .x, flags .#x" },
+{ 701087836, "CM begin AFS_LookupRoot" },
+{ 701087837, "CM end AFS_LookupRoot, code .d" },
+{ 701087838, "CM pingserver server .x" },
+{ 701087839, "CM checkdownservers server .x" },
+{ 701087840, "CM begin AFS_GetTime" },
+{ 701087841, "CM end AFS_GetTime, code .d" },
+{ 701087842, "CM getaccessbits starting fetch for vp .x" },
+{ 701087843, "CM getaccessbits end fetch, code .d" },
+{ 701087844, "CM checkvolsync updates time when vv current for vol .d to .d" },
+{ 701087845, "CM checkvolsync sees vv going back, vol .d, to vv.low .d" },
+{ 701087846, "CM checkvolsync notes .d fids from vol.low .d, to vv.low .d" },
+{ 701087847, "CM TKN_Probe called" },
+{ 701087848, "CM TKN_InitTokenState called" },
+{ 701087849, "CM TKN_InitTokenState's server is .x" },
+{ 701087850, "CM TKN_InitTokenState returning code .d" },
+{ 701087851, "CM TKN_InitTokenState start TSR" },
+{ 701087852, "CM TKN_InitTokenState end TSR" },
+{ 701087853, "CM TKN_TokenRevoke start" },
+{ 701087854, "CM Revoke one token; type .#x" },
+{ 701087855, "CM revoking .d tokens from server .x" },
+{ 701087856, "CM revoking here tokens for volume .#x" },
+{ 701087857, "CM RevokeHereTokens: checkvolumeinfo, Error .d" },
+{ 701087858, "CM RevokeHereTokens end" },
+{ 701087859, "CM VL_RESTORETOKENS is set" },
+{ 701087860, "CM revoking from vp .x, rights .#x, id .#x,,.#x, flags .#x" },
+{ 701087861, "CM revoke for vp .x returns code .d" },
+{ 701087862, "CM TKN_SetParams called" },
+{ 701087863, "CM TKN_GetServerInterfaces called" },
+{ 701087864, "CM TKN_GetServerInterfaces returns code .d" },
+{ 701087865, "CM begin AFS_GetToken for vp .x, rights .#x" },
+{ 701087866, "CM end AFS_GetToken, code .d" },
+{ 701087867, "CM begin AFS_ReleaseTokens for .d tokens" },
+{ 701087868, "CM end AFS_ReleaseTokens, code .d" },
+{ 701087869, "CM configure cell .s" },
+{ 701087870, "CM configure cell returned code .d" },
+{ 701087871, "CM in cm_fhtovp" },
+{ 701087872, "CM cm_open vp .x, flags .#x" },
+{ 701087873, "CM cm_close vp .x, flags .#x" },
+{ 701087874, "CM cm_write vp .x, flag .#x" },
+{ 701087875, "CM write overflows chunk, max .d, len .d" },
+{ 701087876, "CM cm_read vp .x, nolock .d" },
+{ 701087877, "CM waiting for fetchack, dcp .x" },
+{ 701087878, "CM waiting for data to arrive, validPos is .d" },
+{ 701087879, "CM in ioctl, vp .x" },
+{ 701087880, "CM in cm_getattr, vp .x, flag .#x" },
+{ 701087881, "CM in cm_setattr, vp .x, flag .#x" },
+{ 701087882, "CM in cm_access, vp .x, mode .#x" },
+{ 701087883, "CM lookup failed to find good '..' back pointer" },
+{ 701087884, "CM found fid .x..x..x..x (hex)" },
+{ 701087885, "CM lookup crossing mount point" },
+{ 701087886, "CM mount point points to fid .x..x..x..x" },
+{ 701087887, "CM mount point lookup failed" },
+{ 701087888, "CM lookup returning vp .x" },
+{ 701087889, "CM lookup connection failure" },
+{ 701087890, "CM create dvp .x, name .s, mode .#x" },
+{ 701087891, "CM begin AFS_CreateFile" },
+{ 701087892, "CM end AFS_CreateFile, code .d" },
+{ 701087893, "CM in EvalMountPoint, vp .x" },
+{ 701087894, "CM create's scache search returns .#x" },
+{ 701087895, "CM remove dvp .x, name .s" },
+{ 701087896, "CM begin AFS_RemoveFile" },
+{ 701087897, "CM end AFS_RemoveFile, code .d" },
+{ 701087898, "CM hard link to vp .x, from dir .x name .s" },
+{ 701087899, "CM begin AFS_HardLink" },
+{ 701087900, "CM end AFS_HardLink, code .d" },
+{ 701087901, "CM rename old vp .x, old name .s, new vp .x, new name .s" },
+{ 701087902, "CM begin AFS_Rename" },
+{ 701087903, "CM end AFS_Rename, code .d" },
+{ 701087904, "CM mkdir dvp .x, name .s" },
+{ 701087905, "CM begin AFS_MakeDir" },
+{ 701087906, "CM end AFS_MakeDir, code .d" },
+{ 701087907, "CM removedir dvp .x, name .s" },
+{ 701087908, "CM begin AFS_RemoveDir" },
+{ 701087909, "CM end AFS_RemoveDir, code .d" },
+{ 701087910, "CM cm_readdir vp .x, len .d" },
+{ 701087911, "CM readdir filePos .d, chunk .d" },
+{ 701087912, "CM lookup cookie returned .d" },
+{ 701087913, "CM lookup cookie failed, trying from chunk .d" },
+{ 701087914, "CM readdir resync, filePos .d, from chunk .d" },
+{ 701087915, "CM readdir reading from chunk .d, relative pos .d" },
+{ 701087916, "CM readdir returning new offset .d, code .d" },
+{ 701087917, "CM symlink creating dvp .x, name .s" },
+{ 701087918, "CM begin AFS_SymLink" },
+{ 701087919, "CM end AFS_SymLink, code .d" },
+{ 701087920, "CM readlink vp .x" },
+{ 701087921, "CM fsync vp .x" },
+{ 701087922, "CM inactive vp .x" },
+{ 701087923, "CM bmap vp .x" },
+{ 701087924, "CM strategy bp .x" },
+{ 701087925, "CM user strat, vp .x, bp->flags .#x" },
+{ 701087926, "CM noop" },
+{ 701087927, "CM mergestatus vp .x, tokenp .x, flags .#x" },
+{ 701087928, "CM mergestatus ctime OK for merging, local mod flags .#x" },
+{ 701087929, "CM mergestatus add pag .x rights .#x" },
+{ 701087930, "CM updatestatus dirvalequalp == .d" },
+{ 701087931, "CM begin AFS_Quota " },
+{ 701087932, "CM end AFS_Quota, code .d" },
+{ 701087933, "CM cm_getacl vp .x" },
+{ 701087934, "CM begin AFS_GetAcl" },
+{ 701087935, "CM end AFS_GetAcl, code .d" },
+{ 701087936, "CM cm_setacl vp .x" },
+{ 701087937, "CM begin AFS_SetAcl" },
+{ 701087938, "CM end AFS_SetAcl, code .d" },
+{ 701087939, "CM Install vol entry for volume ID .d" },
+{ 701087940, "CM begin VL_GetEntryByID" },
+{ 701087941, "CM end VL_GetEntryByID, code .d" },
+{ 701087942, "CM getvolbyname looking for volume .s" },
+{ 701087943, "CM begin VL_GetVolByName" },
+{ 701087944, "CM end VL_GetVolByName, code .d" },
+{ 701087945, "CM setting vol name for vol .x to .s" },
+{ 701087946, "CM in afs_xsetgroups" },
+{ 701087947, "CM used to be CM_TRACE_SETPAG" },
+{ 701087948, "CM getfreeaclent recycles acl entry from vp .x" },
+{ 701087949, "CM cm_GetCell failed to find cell .x..x" },
+{ 701087950, "CM cm_GetCellByName failed to find cell .s" },
+{ 701087951, "CM cm_ConnByAddr using conn .x, service .#x" },
+{ 701087952, "CM in cm_ResetUserConns for pag .x" },
+{ 701087953, "CM in cm_FlushQueuedServerTokens for server .x" },
+{ 701087954, "CM in GetDOnLine, scp .x, dcp .x" },
+{ 701087955, "CM getdonline: getting tokens to get chunk online" },
+{ 701087956, "CM cm_SyncDCache syncing all chunks from vp .x" },
+{ 701087957, "CM cm_SyncDCache fail (ETIMEDOUT) from vp .x" },
+{ 701087958, "CM TruncateAllSegments truncating vp .x to .d" },
+{ 701087959, "CM getdowndslot recycling dcp .x" },
+{ 701087960, "CM invalidateoneseg vp .x, dcp .x" },
+{ 701087961, "CM clearing online state for vp .x, dcp .x" },
+{ 701087962, "CM setting online token ID for vp .x, dcp .x" },
+{ 701087963, "CM in nh_enter, scp .x, name .s, vnode .#x" },
+{ 701087964, "CM in nh_delete, scp .x, name .s" },
+{ 701087965, "CM nh_deleted_vp for scp .x" },
+{ 701087966, "CM releaselockf vp .x, type .x, start .d, lastbyte .d" },
+{ 701087967, "CM cm_SetLockF vp .x, type .x, start .d, lastbyte .d" },
+{ 701087968, "CM cm_TryLockRevoke vp .x, type .x colA .x colB .x" },
+{ 701087969, "CM cm_TryLockRevoke: No lockf found vp .x" },
+{ 701087970, "CM lock token conflict" },
+{ 701087971, "CM setlockf: blocked locally == .d" },
+{ 701087972, "CM checkerror returning code .d" },
+{ 701087973, "CM cm_GetScache vp .x, volume.low .#x, vnode .#x" },
+{ 701087974, "CM MarkTime vp .x, time .x, flags .#x" },
+{ 701087975, "CM SyncSCache vp .x" },
+{ 701087976, "CM SyncSCache fail (ETIMEDOUT) from vp .x" },
+{ 701087977, "CM recycling scache .#x, really" },
+{ 701087978, "CM resetting all bind mount points" },
+{ 701087979, "CM lost race in reclaim, scp .x" },
+{ 701087980, "CM server .x just marked down" },
+{ 701087981, "CM cm_shutdown called!" },
+{ 701087982, "CM StabilizeSCache waiting vp .x" },
+{ 701087983, "CM StabilizeDCache waiting vp .x, dcp .x (1)" },
+{ 701087984, "CM StabilizeDCache waiting vp .x, dcp .x (2)" },
+{ 701087985, "CM cache fetch proc dcp .x, new pos .d" },
+{ 701087986, "CM cm_FreeAllCookies, scp .x" },
+{ 701087987, "CM reserveblocks emergency, scp .x, truncating dcp .x!" },
+{ 701087988, "CM gettokens vp .x, rights.low .#x" },
+{ 701087989, "CM token revoke race occurred" },
+{ 701087990, "CM in DoPartialWrite" },
+{ 701087991, "CM in cm_read, getting chunk online manually" },
+{ 701087992, "CM cm_read: read past chunk EOF, padding with zeroes" },
+{ 701087993, "CM read starting prefetch for offset .d" },
+{ 701087994, "CM swapping out vol structure at .x" },
+{ 701087995, "CM async grant RPC vp .x type .#x range(.d:.d)" },
+{ 701087996, "CM asycn grant returns code .d" },
+{ 701087997, "CM async can't find fid's server" },
+{ 701087998, "CM async done, states .#x, code .d" },
+{ 701087999, "CM TKN_AsyncGrant fid .x..x..x..x, rights .#x" },
+{ 701088000, "CM TKN_AsyncGrant done for vp .#x" },
+{ 701088001, "CM Refresh Tokens at time .x, opcount .d" },
+{ 701088002, "CM Refresh Tokens done at time .x" },
+{ 701088003, "CM start UpdateTokensLifetime" },
+{ 701088004, "CM Update Tokens for scp .x" },
+{ 701088005, "CM start AFS_SetParams" },
+{ 701088006, "CM end AFS_SetParams code .d" },
+{ 701088007, "CM restore move tokens" },
+{ 701088008, "CM recover token renew = .d" },
+{ 701088009, "CM start TSR AFS_GetToken, type .#x, verNum .d,.d" },
+{ 701088010, "CM end TSR AFS_GetToken, code .d, type .#x, verNum .d,.d" },
+{ 701088011, "CM RecoverTokenState, flags .#x, tsrMode .d" },
+{ 701088012, "CM cm_ReadVDir exit resid .d" },
+{ 701088013, "CM get a new tgt for pag .x, lifetime .x" },
+{ 701088014, "CM Trybind on name = .s" },
+{ 701088015, "CM Trybind: cannot get helper" },
+{ 701088016, "CM Trybind: read helper returns avpp .x, replyCode .d" },
+{ 701088017, "CM and ctime .#x,.#x vs .#x,.#x" },
+{ 701088018, "CM TSR Async start with server .x type .#x" },
+{ 701088019, "CM TSR Async end with server .x" },
+{ 701088020, "CM Wake up async grant from server .x START" },
+{ 701088021, "CM Wake up async grant END" },
+{ 701088022, "CM GetTokens mapping token conflict to volume busy" },
+{ 701088023, "CM Get HERE Token for volume .#x, request .#x" },
+{ 701088024, "CM HERE token GC revoke, code .d" },
+{ 701088025, "CM GetHereToken in RecoverTokenState failed, code .d" },
+{ 701088026, "CM RevokeHereTokens Relinquish! code = .d" },
+{ 701088027, "CM RevokeHereTokens end, code .d" },
+{ 701088028, "CM someone else is doing TSR-move, nowait = .d" },
+{ 701088029, "CM TSR-CRASH-MOVE for volume .#x" },
+{ 701088030, "CM TSR-MOVE has dirty data in volume .#x, tsr-mode .x" },
+{ 701088031, "CM havetokens: vol .d known .x: past hard limit .d" },
+{ 701088032, "CM havetokens: vol .d known .x, tried .x: past check interval .d" },
+{ 701088033, "CM pagein vp .x off .x len .x rw=.d" },
+{ 701088034, "CM pagein done code .d" },
+{ 701088035, "CM pageout vp .x off .x len .x flags=.x" },
+{ 701088036, "CM pageout done code .d" },
+{ 701088037, "CM vmrw vp .x, write=.d, off=.#x, len=.#x" },
+{ 701088038, "CM Simulating token revoke, scp=.#x rights.low=.#x" },
+{ 701088039, "CM TKN_TokenRevoke: incoming server .x not scp .x's RW server .x, and no hereServerp for volp .x" },
+{ 701088040, "CM TKN_TokenRevoke: incoming server .x neither scp .x's RW server .x nor hereServerp .x" },
+{ 701088041, "CM TKN_TokenRevoke: incoming server .x not scp .x's RW server .x, but same as volp .x's hereServerp" },
+{ 701088042, "CM cm strategy done, vp .#x, code .d, left .#x" },
+{ 701088043, "CM TSR fid .x..x..x..x, data version .u,,.u vs .u,,.u" },
+{ 701088044, "CM TSR fid .x..x..x..x, modChunks .d, modFlags .#x;" },
+{ 701088045, "CM TSR: server back up, fid .x..x..x..x, gettoken flags now .#x" },
+{ 701088046, "CM TSR: volume back up, fid .x..x..x..x, gettoken flags now .#x" },
+{ 701088047, "CM token async grant race occurred" },
+{ 701088048, "CM marking scache .#x bad (code is .d)" },
+{ 701088049, "CM TSR fid .x..x..x..x, tsrMode .#x, have LOCKS" },
+{ 701088050, "CM TSR fid .x..x..x..x, tsrMode .#x, move finished early" },
+{ 701088051, "CM STKN_InitTokenState: no server (IP .#x, UUID .x/.x/.x/.x)" },
+{ 701088052, "CM STKN_TokenRevoke: no server (IP .#x, UUID .x/.x/.x/.x)" },
+{ 701088053, "CM STKN_AsyncGrant: no server (IP .#x, UUID .x/.x/.x/.x)" },
+{ 701088054, "CM cm_ConnByAddr: setting UUID .x/.x/.x/.x in connp .x" },
+{ 701088055, "CM cm_ConnByAddr: passing other UUID .x/.x/.x/.x for connp .x" },
+{ 701088056, "CM cm_ConnByMHosts: found changed gen. count .d -> .d" },
+{ 701088057, "CM cm_ConnByAddr: new I/F, server .#lx needs a reset, calling with DO_RESET" },
+{ 701088058, "CM cm_ConnAndReset: conn .#lx, server .#lx, service .#lx" },
+{ 701088059, "CM cm_ConnAndReset: conn .#lx, server .#lx: reset .d tokens" },
+{ 701088060, "CM cm_ConnAndReset: conn .#lx, service .#lx: calling AFS_SetContext" },
+{ 701088061, "CM cm_ConnAndReset: conn .#lx: AFS_SetContext result is .d" },
+{ 701088062, "CM TSR: can't obtain by ID, fid .x..x..x..x, gettoken flags now .#x" },
+{ 701088063, "CM TSR fid .x..x..x..x, have LOCKS; gettoken flags .#lx, token types .#lx" },
+{ 701088064, "CM TSR: move finished already, fid .x..x..x..x, gettoken flags now .#x, tsrMode now .#x" },
+{ 701088065, "CM cm_StoreDCache: store was invalid, fid .x..x..x..x, from .lu,,.lu for .lu, code .d" },
+{ 701088066, "CM cm_StoreDCache: store was invalid, scp .x, fid .x..x..x..x, code .d" },
+{ 701088067, "CM cm_InvalidateAllSegments: invalidating active store, fid .x..x..x..x, scp states .#lx, storeCount .d, code .d" },
+{ 701088068, "CM cm_InvalidateOneSegment: invalidating active seg, scp .x, fid .x..x..x..x, dcp states .#lx, code .d" },
+{ 701088069, "CM cm_StoreSCache: store was invalid, scp .x, fid .x..x..x..x, code .d" },
+{ 701088070, "CM cm_setacl: store was invalid, scp .x, fid .x..x..x..x, code .d" },
+{ 701088071, "CM cm_setacl: cm_Conn set invalid, scp .x, fid .x..x..x..x, code .d" },
+{ 701088072, "CM cm_StoreSCache: cm_Conn set invalid, scp .x, fid .x..x..x..x, code .d" },
+{ 701088073, "CM cm_StoreDCache: cm_Conn set invalid, fid .x..x..x..x, from .lu,,.lu for .lu, code .d" },
+{ 701088074, "CM cm_StoreDCache: cm_Conn set invalid, scp .x, fid .x..x..x..x, code .d" },
+{ 701088075, "CM RevokeHereToken: holding ID .lu,,.lu for vol .lu,,.lu, so giving .lu,,.lu back to server .x" },
+{ 701088076, "CM RevokeHereToken: unrecognized cell .lu,,.lu, fid .x..x..x..x, so giving .lu,,.lu back to server .x" },
+{ 701088077, "CM start recheck AFS_SetContext: conn .x srv level .#x" },
+{ 701088078, "CM end recheck AFS_SetContext: code .d" },
+{ 701088079, "CM cm_ConnAndReset: SECONDARY waiting for PRIMARY: conn .#lx, server .#lx, service .#lx" },
+{ 701088080, "CM cm_ConnAndReset: waiting for mutex: conn .#lx, server .#lx, service .#lx" },
+{ 701088081, "CM checkvolsync, same vv: updates time when vv current for vol .lu,,.lu from .lu to .lu" },
+{ 701088082, "CM checkvolsync, advanced vv: updates time when vv current for vol .lu,,.lu from .lu to .lu" },
+{ 701088083, "CM checkvolsync sees vv going back, vol .lu,,.lu, from vv .lu,,.lu to vv .lu,,.lu" },
+{ 701088084, "CM checkvolsync notes .d fids from vol .lu,,.lu, incidental vv .lu,,.lu, to vv .lu,,.lu" },
+{ 701088085, "CM checkvolsync flushed .d fids from vol .lu,,.lu" },
+{ 701088086, "CM checkvolsync finally advances vv for vol .lu,,.lu from .lu,,.lu to .lu,,.lu; reallyvv .lu,,.lu" },
+{ 701088087, "CM cm_FindServerIP: found .#x type .d in serverp .#x" },
+{ 701088088, "CM cm_FindServerIP: could not find .#x type .d" },
+{ 701088089, "CM cm_SetServerRank: FX server .#x -> .d" },
+{ 701088090, "CM cm_SetServerRank: REP server .#x -> .d" },
+{ 701088091, "CM cm_SetServerRank: FL server .#x -> .d" },
+{ 701088092, "CM cm_SetServerRank: Existing Qd rank for .#x[.d] -> .d" },
+{ 701088093, "CM cm_SetServerRank: Adding Qd rank request for .#x[.d] -> .d" },
+{ 701088094, "CM cm_DefaultRank addr .#x type .#x" },
+{ 701088095, "CM cm_DefaultRank found sister server .#x rank .d" },
+{ 701088096, "CM cm_DefaultRank Found Qd Req rank .d" },
+{ 701088097, "CM cm_DefaultRank computed default rank .d" },
+{ 701088098, "CM cm_ReSortServers: sorting volumes referencing server .#x" },
+{ 701088099, "CM cm_ReSortCellSrvs: sorting cells referencing server .#x" },
+{ 701088100, "CM cm_ConnByMHosts: At position .d old server .#x new server .#x" },
+{ 701088101, "CM cm_ConnByMHosts: This index [.d] timeBad .#x EarliestIx .d code .d" },
+{ 701088102, "CM cm_ConnByMHosts: found either bad server .#x or gen. count changed .d -> .d" },
+{ 701088103, "CM cm_ConnByMHosts: The server at index .d is now NULL" },
+{ 701088104, "CM cm_ConnByMHosts: cm_ConnByAddr failed (fatal=.d)" },
+{ 701088105, "CM cm_ConnByMHosts: found gen. count changed after cm_ConnByHost .d -> .d" },
+{ 701088106, "CM Finished marking scache .#x bad (code is .d)" },
+{ 701088107, "CM cm_GetSLock(scp=.#x, tokens=.#x..) discovers async status of .d" },
+{ 701088108, "CM cm_GetSLock(scp=.#x, tokens=.#x..) gets code .d from GetTokensRange" },
+{ 701088109, "CM cm_write calls cm_FindDCache(scp=.#x, pos=.#x), returns EIO" },
+{ 701088110, "CM cm_GetDLock calls GetDOnLine(scp=.#x, dcp=.#x, tokentype=.x,,.x..): code .d" },
+{ 701088111, "CM cm_write calls cm_CFileRDWR, scp=.#x, dcp=.#x: code .d, resid .#x" },
+{ 701088112, "CM cm_write calls DoPartialWrite(scp=.#x, lastoffs=.#x...): code .d" },
+{ 701088113, "CM cm_StoreAllSegments calls StoreSCache(scp=.#x, aflags=.#x..): code .d" },
+{ 701088114, "CM cm_StoreAllSegments calls StoreDCache(scp=.#x, dcp=.#x, aflags=.#x..): code .d" },
+{ 701088115, "CM DoPartialWrite calls cm_StoreDCache(scp=.#x, dcp=.#x, ...): code .d" },
+{ 701088116, "CM bkgDaemon done with req .#x opcode .d: code .d" },
+{ 701088117, "CM bkgWait read req .#x and got code .d" },
+{ 701088118, "CM bkgQueue returns req .#x, doing op .d on .#x" },
+{ 701088119, "CM bkgRelease releasing req .#x" },
+{ 701088120, "CM cm_FlushExists considering flushing name .s in dir .#x for EEXIST error" },
+{ 701088121, "CM cm_FlushExists: nh_lookup returns code=.d, vnode=.d" },
+{ 701088122, "CM cm_FlushExists FLUSHING name .s in dir .#x for EEXIST error" },
+{ 701088123, "CM checkvolsync: flushing(#.d) fid .x..x..x..x, type .d vp .x" },
+{ 701088124, "CM checkvolsync: we flushed input fid .x..x..x..x, so return CM_REP_ADVANCED_AGAIN" },
+{ 701088125, "CM cm_GetDOnLine: Checking for fetch: scp dv .lu,,.lu, dcp dv .lu,,.lu, scp type .ld" },
+{ 701088126, "CM cm_NeedRPC(.lu,,.lu): Yes, we have to make an RPC" },
+{ 701088127, "CM cm_ConnAndReset: RPC rejection in .d seconds!" },
+{ 701088128, "CM cm_ConnByAddr: RPC rejection in .d seconds!" },
+{ 701088129, "CM cm_putapage throwing away page past EOF. scp .x length .x offset .x" },
+{ 701088130, "CM cm_getpage request fully past EOF, scp .x scp->m.Length .x offset .x len .x" },
+{ 701088131, "CM cm_setfl vp .x, oflags .#x, nflags .#x" },
+{ 701088132, "CM cm_CheckOpens(.x, .d): opens .d, v_count .d" },
+{ 701088133, "CM cm_CheckOpens: opens .d, readers .d, writers .d, shareds .d; CLEARING" },
+{ 701088134, "CM cm_addmap(.x): prot .#lx, flags .#lx: setting RMAPPED, WMAPPED" },
+{ 701088135, "CM cm_getpage(.x): setting RMAPPED, WMAPPED" },
+{ 701088136, "CM cm_map(.x): prot .#lx, maxprot .#lx, flags .#lx; setting RMAPPED, WMAPPED" },
+{ 701088137, "CM cm_RefreshKeepAlives(): calling .x with .d fids, for example .x..x..x..x" },
+{ 701088138, "CM cm_RefreshKeepAlives(), spot .d: adding fid .d for .x: .x..x..x..x" },
+{ 701088139, "CM cm_RefreshKeepAlives(): overwriting expr of .x (fid .x..x..x..x), was .d" },
+{ 701088140, "CM cm_StoreDCache: storing chunk without tokens, fid .x..x..x..x, from .lu,,.lu for .lu (scp = .x)" },
+{ 701088141, "CM cm_StoreDCache: storing offline chunk, fid .x..x..x..x, from .lu,,.lu for .lu (dcp = .x)" },
+{ 701088142, "CM cm_ReclaimVDirs: Vdir count is .d, so reclaming" },
+{ 701088143, "CM cm_ReclaimVDirs: scp .x, name '.s', giving vp .x; vdirp states .#lx" },
+{ 701088144, "CM cm_ReclaimVDirs: Ending; inspected .d vdirs; freed .d vdirs; count .d" },
+{ 701088145, "CM cm_GCVDirs: Ending; vdir count is now .d, after .d loops" },
+{ 701088146, "CM cm_GCVDirs: advancing minTimeout from .d to .d" },
+{ 701088147, "CM cm_GCVDirs: Bypassing GC since only .d seconds since .d" },
+{ 701088148, "CM cm_ConnByMHosts: Sleep interrupted" },
+{ 701088149, "CM cm_Analyze: TKM-induced sleep interrupted" },
+{ 701088150, "CM cm_Analyze: vol-induced sleep interrupted" },
+{ 701088151, "CM cm_RevalidateCellRoot: from volid .lu,,.lu to .lu,,.lu (.s)" },
+{ 701088152, "CM cm_DoCellRootScp: using fid .x..x..x..x" },
+{ 701088153, "CM used to be CM_TRACE_QUEUESETSIZE" },
+{ 701088154, "CM start AFS_SetParams, server .x, to set client size of .#x" },
+{ 701088155, "CM end AFS_SetParams got server size of .#x: code .d" },
+{ 701088156, "CM TKN_SetParams called: flag .d, mask .#x" },
+{ 701088157, "CM cm_RecoverSCacheToken: racing revoke for fid .x..x..x..x, ID .lu,,.lu" },
+{ 701088158, "CM cm_BulkFetchStatus: scp .x" },
+{ 701088159, "CM bulkstat: offset .d out of range .d" },
+{ 701088160, "CM bulkstat: server does not export bulkstat" },
+{ 701088161, "CM bulkstat: some other client changed dir" },
+{ 701088162, "CM bulkstat: some other thread changed dir" },
+{ 701088163, "CM bulkstat: token revoked" },
+{ 701088164, "CM bulkstat: error for file .s" },
+{ 701088165, "CM cm_BulkFetchStatus: scp .x, error .d" },
+{ 701088166, "CM bulkstat: error for file .s" },
+{ 701088167, "CM cm_RestoreMoveTokens: About to check tokens; orig=.x, new=.x" },
+{ 701088168, "CM cm_RestoreMoveTokens: VALIDATE on! Fid .x..x..x..x, token flags .#x, server .x, types .x" },
+{ 701088169, "CM cm_RestoreMoveTokens: on old server! Fid .x..x..x..x, token flags .#x, server .x, types .x" },
+{ 701088170, "CM cm_RestoreMoveTokens: not on new server! Fid .x..x..x..x, token flags .#x, server .x, types .x" },
+{ 701088171, "CM cm_StripRedundantTokens: token id .lu,,.lu types .x reduced by id .lu,,.lu types .x" },
+{ 701088172, "CM cm_StripRedundantTokens: token .x, id .lu,,.lu, types .x reduced to .x" },
+{ 701088173, "CM cm_ServerDown(.x): (lastcall=.d + TTL=.d) later than now=.d: server stays up" },
+{ 701088174, "CM tryLockRevoke preserving .lx: type .d, [.lx...lx]" },
+{ 701088175, "CM tryLockRevoke blocked preserving type .d [.lx...lx] pid .d" },
+{ 701088176, "CM tryLockRevoke returning token type .d, id .lx,,.lx, flags .#lx" },
+{ 701088177, "CM cm_Analyze: conn .x, code .d, pag .x, fid .x..x..x..x" },
+{ 701088178, "CM cm_AdjustSize: dcp .x has chunkBytes .x, startDirty .x, endDirty .x" },
+{ 701088179, "CM cm_AdjustSize: newSize .x: now chunkBytes .x, startDirty .x, endDirty .x" },
+{ 701088180, "CM cm_QuickDiscard: dcp .x starts with chunkBytes .x, startDirty .x, endDirty .x" },
+{ 701088181, "CM cm_SetChunkDirtyRange: dcp .x starts with startDirty .x, endDirty .x" },
+{ 701088182, "CM cm_SetChunkDirtyRange: given start=.x, end=.x; ends with startDirty .x, endDirty .x" },
+{ 701088183, "CM cm_HotWireSegment: scp .x, dcp .x, offset .x, checkLength .x" },
+{ 701088184, "CM cm_HotWireSegment: dcp .x (being hotwired) starts with chunkBytes .x, startDirty .x, endDirty .x" },
+{ 701088185, "CM cm_MergeStatus(.x): overwriting our cached .lu,,.lu with low half of .lu,,.lu" },
+{ 701088186, "CM cm_GetDOnLine: scp length now 0,,.#x, chunk start .x, chunkBytes .x" },
+{ 701088187, "CM cm_Conn: conn .x already in use (callCount .d); recycling." },
+{ 701088188, "CM mark TGT expired for pag .x" },
+{ 701088189, "CM TGTLifeTime(pag .x) gives time .x, expired .d" },
+{ 701088190, "CM cm_ReactToAuthCodes: conn .x, authn .d, authz .d" },
+{ 701088191, "CM cm_ReactToAuthnCodes: server .x (.d...d): max goes to .d" },
+{ 701088192, "CM cm_ReactToAuthnCodes: server .x (.d...d): min goes to .d" },
+{ 701088193, "CM cm_ReactToAuthnCodes: volume .x (.d...d): max goes to .d" },
+{ 701088194, "CM cm_ReactToAuthnCodes: volume .x (.d...d): min goes to .d" },
+{ 701088195, "CM cm_Conn: volp .x, cell flags .d: authn LB .d exceeds UB .d" },
+{ 701088196, "CM cm_Conn: volp .x, cell flags .d: authn LB .d >none (UB .d), but authz NONE" },
+{ 701088197, "CM cm_Conn: volp .x, cell flags .d: authn .d raised to LB .d" },
+{ 701088198, "CM cm_Conn: volp .x, cell flags .d: authn .d lowered to UB .d" },
+{ 701088199, "CM cm_Conn: giving up. forceUnauth .d, exp'd .d, authn .d, authz .d" },
+{ 701088200, "CM cm_ConnByAddr using conn .x, service .#x, authn .d, authz .d" },
+{ 701088201, "CM cm_ConnByAddr authenticating conn .x: result .d, authn .d, authz .d" },
+{ 701088202, "CM cm_InstallVolumeEntry: volume .lu,,.lu has bad min/max auth limits: min .d, max .d" },
+{ 701088203, "CM GCOldConn: GCing tgt entry .x with pag .x, time .d, flags .#x" },
+{ 701088204, "CM newtgt(pag .x, lifetime .x) called" },
+{ 701088205, "CM newtgt(): lifeTime expired: returning EINVAL" },
+{ 701088206, "CM newtgt(): mypag .x, pag .x: not super-user, so returning EACCES" },
+{ 701088207, "CM cm_ConnByAddr: isExp .d, cached conn expiry .d, forceUnauth .d: restarting." },
+{ 701088208, "CM cm_ConnByAddr: unsupported_authn: taking maxSupp from .d to .d; LB currently .d" },
+{ 701088209, "CM cm_ReactToAuthCodes: unsupported_authn: taking maxSupp from .d to .d; LB currently .d" },
+{ 701088210, "CM cm_ReactToAuthnCodes: raised LB .d -> .d but cannot raise UB .d past maxSupp .d" },
+{ 701088211, "CM cm_PCreateMountPoint: vnode .x" },
+{ 701088212, "CM cm_PCreateMountPoint returns code .d" },
+{ 701088213, "CM cm_AddrRankPut(addr=.#lx, svc=.ld, rank=.ld)" },
+{ 701088214, "CM cm_AddrRankGet(addr=.#lx, svc=.ld) yields rank=.ld returning .ld" },
+{ 701088215, "CM cm_AddrRankCompute(addr=.#lx) returning .ld" },
+{ 701088216, "CM cm_SiteAlloc(svc=.ld, addrvp=.#lx, addrvcnt=.ld)" },
+{ 701088217, "CM cm_SiteAlloc(svc=.ld, addrvp=.#lx) returns sitep=.#lx" },
+{ 701088218, "CM cm_SiteAddrReplace(sitep=.#lx, addrvp=.#lx, addrvcnt=.ld)" },
+{ 701088219, "CM cm_SiteAddrReplace(sitep=.#lx) same addrs, returning" },
+{ 701088220, "CM cm_SiteAddrReplace(sitep=.#lx) returning" },
+{ 701088221, "CM SiteAddrUpdate(sitep=.#lx) same-addr=.ld, new-addr=.ld" },
+{ 701088222, "CM SiteAddrUpdate(sitep=.#lx) addr-gen bumped to=.ld" },
+{ 701088223, "CM cm_SiteAddrSetRankAll(addr=.#lx, svc=.ld, rank=.ld)" },
+{ 701088224, "CM cm_SiteAddrSetRankAll(addr=.#lx) setting for sitep=.#lx" },
+{ 701088225, "CM cm_SiteAddrSetRankAll(addr=.#lx) addr-gen bumped to=.ld" },
+{ 701088226, "CM cm_SiteAddrSetRankAll(addr=.#lx) returning" },
+{ 701088227, "CM cm_SiteAddrDown(sitep=.#lx, addr=.#lx)" },
+{ 701088228, "CM cm_SiteAddrDown(sitep=.#lx) addr-gen bumped to=.ld" },
+{ 701088229, "CM cm_SiteAddrDown(sitep=.#lx) returning .ld" },
+{ 701088230, "CM cm_SiteAddrUp(sitep=.#lx, addr=.#lx)" },
+{ 701088231, "CM cm_SiteAddrUp(sitep=.#lx) addr-gen bumped to=.ld" },
+{ 701088232, "CM cm_SiteAddrUp(sitep=.#lx) returning" },
+{ 701088233, "CM cm_SiteAddrMarkAllUp(sitep=.#lx, ifAllDown=.ld)" },
+{ 701088234, "CM cm_SiteAddrMarkAllUp(sitep=.#lx) addr-gen bumped to=.ld" },
+{ 701088235, "CM cm_SiteAddrMarkAllUp(sitep=.#lx) returning" },
+{ 701088236, "CM cm_ConnByMHosts(service=.#lx) last-server info reused" },
+{ 701088237, "CM cm_ConnByMHosts(service=.#lx) try-addr=.#lx, got-addr=.#lx, successful, returning connp=.#lx" },
+{ 701088238, "CM cm_ConnByMHosts: addr or host gen count change noticed" },
+{ 701088239, "CM cm_ConnByHost(service=.#lx) try-addr=.#lx, got-addr=.#lx, with result connp=.#lx" },
+{ 701088240, "CM cm_ReviveAddrsForServers() entered" },
+{ 701088241, "CM cm_ReviveAddrsForServers() returning" },
+{ 701088242, "CM ReviveAddrsForServer(serverp=.#lx) entered" },
+{ 701088243, "CM ReviveAddrsForServer(serverp=.#lx) in progress, returning" },
+{ 701088244, "CM ReviveAddrsForServer(serverp=.#lx) no conn for addr=.#lx" },
+{ 701088245, "CM ReviveAddrsForServer(serverp=.#lx) tried addr=.#lx with result code=.ld" },
+{ 701088246, "CM ReviveAddrsForServer(serverp=.#lx) returning" },
+{ 701088247, "CM cm_FxRepAddrFetch() entered" },
+{ 701088248, "CM cm_FxRepAddrFetch() queue request failed" },
+{ 701088249, "CM cm_FxRepAddrFetch() returning" },
+{ 701088250, "CM FxRepAddrFetch(fxserverp=.#lx, repserverp=.#lx) entered" },
+{ 701088251, "CM FxRepAddrFetch() unable to get conn" },
+{ 701088252, "CM FxRepAddrFetch() start VL_GetSiteInfo()" },
+{ 701088253, "CM FxRepAddrFetch() end VL_GetSiteInfo(), code=.ld" },
+{ 701088254, "CM FxRepAddrFetch(fxserverp=.#lx, repserverp=.#lx) returning" },
+{ 701088255, "CM 64-bit server (.p) maxFileSize is .#x,,.#x" },
+{ 701088256, "CM 32-bit server (.p) maxFileSize is .#x,,.#x" },
+{ 701088257, "CM mergestatus length .u,,.u too long" },
+{ 701088258, "CM cm_SiteAddrRankOverride(sitep=.#lx, addr=.#lx) entered" },
+{ 701088259, "CM cm_SiteAddrRankOverride(sitep=.#lx) addr-gen bumped to=.ld" },
+{ 701088260, "CM cm_SiteAddrRankOverride(sitep=.#lx) returning" },
+{ 701088261, "CM cm_ReactToBindAddrChange(connp=.#lx, doOverride=.ld) conn-addr=.#lx, bind-addr=.#lx" },
+{ 701088262, "CM cm_ReactToBindAddrChange(connp=.#lx, doOverride=.ld) err getting addr=.ld" },
+{ 701088263, "CM running cm_ResetAuthnForServers()" },
+{ 701088264, "CM .s" },
+{ 701088265, "CM addacl entry: vp .x; conn flags .x, pag .x, uid .x" },
+{ 701088266, "CM getaclcache entry: vp .x; conn flags .x, pag .x, uid .x" },
+{ 701088267, "CM conn .x, authn .d authz .d: setting rreq connflags to .x" },
+{ 701088268, "CM cm_FlushTransient flushing name .s in dir .#x for error .d" },
+{ 701088269, "CM cm_readdir: nonzero tag .d or highoffset .d (node .d, name `.s'); returning ERANGE" },
+{ 701088270, "CM cm_lockctl: vp .#x, whence .d, start .lld len .lld" },
+{ 701088271, "CM cm_SetLockF vp .x, type .x, start .lld, lastbyte .lld" },
+{ 701088272, "CM tryLockRevoke preserving .lx: type .d, [.llx...llx]" },
+{ 701088273, "CM tryLockRevoke blocked preserving type .d [.llx...llx] pid .d" },
+{ 701088274, "CM releaselockf vp .x, type .x, start .lld, lastbyte .lld" },
+{ 701088275, "CM start AFS_FetchData at position .lld" },
+{ 701088276, "CM cm_GetDOnLine: scp length now .#llx, chunk start .llx, chunkBytes .x" },
+{ 701088277, "CM TruncateAllSegments truncating vp .x to .lld" },
+{ 701088278, "CM bulkstat: offset .lld out of range .d,,.d" },
+{ 701088279, "CM cache fetch proc dcp .x, new pos .lld" },
+{ 701088280, "CM waiting for data to arrive, validPos is .lld" },
+{ 701088281, "CM cm_write calls cm_FindDCache(scp=.#x, pos=.#llx), returns EIO" },
+{ 701088282, "CM cm_write calls DoPartialWrite(scp=.#x, lastoffs=.#llx...): code .d" },
+{ 701088283, "CM read starting prefetch for offset .lld" },
+{ 701088284, "CM cm_HotWireSegment: scp .x, dcp .x, offset .llx, checkLength .llx" },
+{ 701088285, "CM pagein vp .x off .llx len .x rw=.d" },
+{ 701088286, "CM vmrw vp .x, write=.d, off=.#llx, len=.#x" },
+{ 701088287, "CM cm_putapage throwing away page past EOF. scp .x length .x offset .llx" },
+{ 701088288, "CM pageout vp .x off .llx len .x flags=.x" },
+{ 701088289, "CM at len=.d; kluster got page, offset .llu, delta .d, hilim .llu" },
+{ 701088290, "CM writing past end-of-world: biggest .lu,,.lu, first .lu,,.lu, last .lu,,.lu; EFBIG." },
+{ 701088291, "CM truncing past end-of-world: biggest .lu,,.lu, this .lu,,.lu; EFBIG." },
+{ 701088292, "CM page-writing past EOW: start .llx past limit .llx; resid .ld; EFBIG." },
+{ 701088293, "CM set online token ID for vp .x, dcp .x, to .#x,,.#x" },
+{ 701088294, "CM set online tokID for dcp .x to .#x,,.#x (input id .#x,,.#x)" },
+{ 701088295, "CM found token match, id .#x,,.#x, [.#x,,.#x .. .#x,,.#x], type .#x" },
+{ 701088296, "CM cm_HotWireSegment ... has tokenID .#x,,.#x, flags .#x, validPos .lld" },
+{ 701088297, "CM HaveTokensRange uses tokid .#x,,.#x types .#x to satisfy part of .#x requested" },
+{ 701088298, "CM HaveTokensRange uses tokid .#x,,.#x types .#x to satisfy part of .#x requested ..." },
+{ 701088299, "CM HaveTokensRange uses tokid .#x,,.#x types .#x to MATCH .#x requested ..." },
+{ 701088300, "CM ... since its range [.#x,,.#x .. .#x,,.#x] covers requested [.#x,,.#x .. .#x,,.#x]" },
+{ 701088301, "CM ... revoking range [.#x,,.#x .. .#x,,.#x]" },
+{ 701088302, "CM cm_MergeStatus: current serverchg .d..06d; incoming chg .d..06d" },
+{ 701088303, "CM cm_ConnByAddr authenticating conn .x: principal .s, addr .x" },
+{ 701088304, "CM cm_ConnByAddr: creating conn type .#x, addr .x, conn .x" },
+{ 701088305, "CM cm_ConnByAddr server type .#x, serverp .x, addr .x" },
+{ 701088306, "CM ran minor renewlazyrep, vol .x, .d,,.u" },
+{ 701088307, "CM in cm_GetDownD, flags .#x, number .d, discards=.d" },
+{ 701088308, "CM cm_GetDownD: found .d entries in initial scan" },
+{ 701088309, "CM in cm_GetDownD, discarding .d" },
+{ 701088310, "CM in cm_GetDownD, GC .d" },
+{ 701088311, "CM in cm_GetDownD, get it all .d" },
+{ 701088312, "CM in cm_GetDownD, will reclaim .d" },
+{ 701088313, "CM in cm_GetDownD, discard 1" },
+{ 701088314, "CM in cm_GetDownD, freed .d" },
+{ 701088315, "CM calling VL_GetEntryByID without commit requested, type .d" },
+{ 701088316, "CM cm_ReactToAuthnCodes: rreq (.d...d): max goes to .d" },
+{ 701088317, "CM cm_ReactToAuthnCodes: rreq (.d...d): min goes to .d" },
+{ 701088318, "CM bulkstat: another change raced ahead of us (cached .d..06d != incoming .d..06d)" },
+{ 701088319, "CM truncating(cm_GetDownD), count of discarded chunks is .d, should be 0" },
+{ 701088320, "CM in cm_GetDownD, too many flags set on discarded chunk: .x" },
+{ 701088321, "CM in cm_GetDownD, refcount .d on discarded chunk, should be 0" },
+{ 701088322, "CM cm_ConnByAddr: unsupported_authn: maxsuppAuthn mask now .#x; LB currently .d" },
+{ 701088323, "CM cm_Conn: server .x, unsupp mask .#x: NOTHING in [.d...d]" },
+{ 701088324, "CM cm_ConnByHost: (try-addr=.#lx, svc=.ld, rank = never)" },
+{ 701088325, "CM cm_SiteAddrRankOverride: Address .#lx assigned new rank .ld (old rank = never)" },
+{ 701088326, "CM .s: no server (IP .#x, UUID .x/.x/.x/.x)" },
+{ 701088327, "CM GuessServer: server .x uses 1024-byte blocks based on fid .x..x..x..x length .lld, blocksUsed .ld" },
+{ 701088328, "CM GuessServer: server .x uses 512-byte blocks based on fid .x..x..x..x length .lld, blocksUsed .ld" },
+{ 701088329, "CM GuessServer: volume .x (fid .x..x..x..x) min alloc is .d (from blocksUsed=.d)" },
+{ 701088330, "CM cm_PurgeExtraData: dcp .x at pos .#llx can use toktype .d of token .x,,.x" },
+{ 701088331, "CM cm_JettisonUnwantedTokens: dumping types .x of token .x,,.x; .x left" },
+{ 701088332, "CM cm_JettisonUnwantedTokens done with scp .x (server .x): still need .x whole-file types and .x subrange types" },
+{ 701088333, "CM cm_PurgeExtraLocks: scp .x may need token .x,,.x range [.llx .. .llx] ..." },
+{ 701088334, "CM cm_PurgeExtraLocks: ... types .x to handle locktype .x, [.llx...llx]" },
+{ 701088335, "CM cm_VerifyNeededLocks: UNSATISFIED LOCK for scp .x, locktype .x, [.llx...llx]" },
+{ 701088336, "CM cm_VerifyNeededData: UNSATISFIED DATA for scp .x, tokentype .x, [.x,,.x .. .x,,.x] ..." },
+{ 701088337, "CM cm_VerifyNeededData: ... dcp .x, flags .x, started at .x,,.x" },
+{ 701088338, "CM cm_RecoverSCacheToken: scp .x, tokid .x,,.x, adding required whole-file types .x to existing .x" },
+{ 701088339, "CM cm_RecoverSCacheToken: scp .x, tokid .x,,.x, restricting token types .x to needed .x" },
+{ 701088340, "CM cm_RecoverSCacheToken: scp .x, got tokid .x,,.x; no longer need whole-file bits .x of .x" },
+{ 701088341, "CM cm_RecoverSCacheToken: got whole-file tokid .x,,.x; no longer need bits .x in whole-file .x or range .x" },
+{ 701088342, "CM mark pag .x .d? gone : expired" },
+{ 701088343, "CM cm_ConnByMHosts simply delaying for .d seconds" },
+{ 701088344, "CM cm_RemoveFromParentVDir: Attempting to remove scp .x, name '.s', vdirp states .x" },
+{ 701088345, "CM cm_RemoveFromParentVDir: Removed scp .x, name '.s', from pvp .x; vdirp states .x" },
+{ 701088346, "CM cm_IdleSCaches: beginning to idle stat cache" },
+{ 701088347, "CM cm_IdleSCaches: Failed to flush cm_rootVnode scp .x" },
+{ 701088348, "CM cm_IdleSCaches: Finished, returning .d, with .d retries left, and SLRU .s empty" },
+{ 701088349, "CM cm_Analyze: sleep interrupted" },
+{ 701088350, "CM getdcache found vp .x, chunk .d in dcp .x, slot .x" },
+{ 701088351, "CM getndcaches put vp .x, chunk .d in dcp .x, slot .x" },
+{ 701088352, "CM in flushDCache, dcp .x, slot .x" },
+{ 701088353, "CM faking 0 byte entry locally, version .u,,.u" },
+{ 701088354, "CM fetchdcache finishing: setting dcp .x, slot .x to have dv version .u,,.u" },
+{ 701088355, "CM cm_GetDOnLine: Checking for fetch: scp dv .lu,,.lu, dcp dv .lu,,.lu, scp type .ld, slot .x" },
+{ 701088356, "CM invalidateoneseg vp .x, dcp .x, slot .x" },
+{ 701088357, "CM clearing online state for vp .x, dcp .x, slot .x" },
+{ 701088358, "CM reading dcp .x from file slot .x: version .u,,.u, token .x,,.x" },
+{ 701088359, "CM reading file slot .x into a temp buffer: version .u,,.u, token .x,,.x" },
+{ 701088360, "CM storing dcp .x (dv .u,,.u) into file slot .x: result .d" },
+{ 701088361, "CM VM writing=.d at .llx: data .08x-.08x (.d bytes max)" },
+{ 701088362, "CM PUSH accepting at position .llx: data .08x-.08x (.d bytes max)" },
+{ 701088363, "CM PULL sending from chunk position .lx: data .08x-.08x (.d bytes max)" },
+{ 701088364, "CM memcache read at .lx: data .08x-.08x (.d bytes max)" },
+{ 701088365, "CM memcache write at .lx: data .08x-.08x (.d bytes max)" },
+{ 701088366, "CM cm_GetTokensRange(vp .x): restricting renewal of token .x from .x to requested bits (id .x,,.x)" },
+{ 701088367, "CM cm_GetTokensRange(vp .x): seeking .x; STATUS_READ not held; dropping token .x,,.x with rights .x" },
+{ 701088368, "CM cm_GetTokensRange(vp .x): seeking .x; STATUS_READ *is* held; accepting token .x,,.x with rights .x" },
+{ 701088369, "CM cm_GetTokensRange(vp .x): seeking .x; STATUS_READ *revoked*; dropping STATUS_READ from token .x,,.x with rights .x" },
+{ 701088370, "CM cm_TerminateTokenGrant: count decrs to .d, my seq is .d,,.d" },
+{ 701088371, "CM cm_TerminateTokenGrant: oldest seq is .d,,.d; .d freed, .d remaining" },
+{ 701088372, "CM TokenGrant: seq .d,,.d had revoked bits .x in ID .#x,,.#x, reducing incoming bits .x" },
+{ 701088373, "CM Update async cred: credp .x, pag .x" },
+{ 701088374, "CM cm_map: vp .x, flags .x" },
+{ 701088375, "FS_Attach entry, opcode_mode 0x.x" },
+{ 701088376, "FS_Attach exit, return code 0x.x" },
+{ 701088377, "FS_CHDIR entry, opcode_mode 0x.x" },
+{ 701088378, "FS_CHDIR exit, return code 0x.x" },
+{ 701088379, "FS_CHFILEPTR entry, opcode_mode 0x.x" },
+{ 701088380, "FS_CHFILEPTR exit, return code 0x.x" },
+{ 701088381, "FS_CLOSE entry, opcode_mode 0x.x" },
+{ 701088382, "FS_CLOSE exit, return code 0x.x" },
+{ 701088383, "FS_COMMIT entry, opcode_mode 0x.x" },
+{ 701088384, "FS_COMMIT exit, return code 0x.x" },
+{ 701088385, "FS_COPY entry, opcode_mode 0x.x" },
+{ 701088386, "FS_COPY exit, return code 0x.x" },
+{ 701088387, "FS_DELETE entry, opcode_mode 0x.x" },
+{ 701088388, "FS_DELETE exit, return code 0x.x" },
+{ 701088389, "FS_EXIT entry, opcode_mode 0x.x" },
+{ 701088390, "FS_EXIT exit, return code 0x.x" },
+{ 701088391, "FS_FILEATTRIBUTE entry, opcode_mode 0x.x" },
+{ 701088392, "FS_FILEATTRIBUTE exit, return code 0x.x" },
+{ 701088393, "FS_FILEINFO entry, opcode_mode 0x.x" },
+{ 701088394, "FS_FILEINFO exit, return code 0x.x" },
+{ 701088395, "FS_FILEIO entry, opcode_mode 0x.x" },
+{ 701088396, "FS_FILEIO exit, return code 0x.x" },
+{ 701088397, "FS_FINDCLOSE entry, opcode_mode 0x.x" },
+{ 701088398, "FS_FINDCLOSE exit, return code 0x.x" },
+{ 701088399, "FS_FINDFIRST entry, opcode_mode 0x.x" },
+{ 701088400, "FS_FINDFIRST exit, directory handle 0x.x, return code 0x.x" },
+{ 701088401, "FS_FINDFROMNAME entry, opcode_mode 0x.x" },
+{ 701088402, "FS_FINDFROMNAME exit, return code 0x.x" },
+{ 701088403, "FS_FINDNEXT entry, directory handle 0x.x, opcode_mode 0x.x" },
+{ 701088404, "FS_FINDNEXT exit, directory handle 0x.x, return code 0x.x" },
+{ 701088405, "FS_FINDNOTIFYCLOSE entry, opcode_mode 0x.x" },
+{ 701088406, "FS_FINDNOTIFYCLOSE exit, return code 0x.x" },
+{ 701088407, "FS_FINDNOTIFYFIRST entry, opcode_mode 0x.x" },
+{ 701088408, "FS_FINDNOTIFYFIRST exit, return code 0x.x" },
+{ 701088409, "FS_FINDNOTIFYNEXT entry, opcode_mode 0x.x" },
+{ 701088410, "FS_FINDNOTIFYNEXT exit, return code 0x.x" },
+{ 701088411, "FS_FLUSHBUF entry, opcode_mode 0x.x" },
+{ 701088412, "FS_FLUSHBUF exit, return code 0x.x" },
+{ 701088413, "FS_FSCTL entry, opcode_mode 0x.x" },
+{ 701088414, "FS_FSCTL exit, return code 0x.x" },
+{ 701088415, "FS_FSINFO entry, opcode_mode 0x.x" },
+{ 701088416, "FS_FSINFO exit, return code 0x.x" },
+{ 701088417, "FS_INIT entry, opcode_mode 0x.x" },
+{ 701088418, "FS_INIT exit, return code 0x.x" },
+{ 701088419, "FS_IOCTL entry, opcode_mode 0x.x" },
+{ 701088420, "FS_IOCTL exit, return code 0x.x" },
+{ 701088421, "FS_MKDIR entry, opcode_mode 0x.x" },
+{ 701088422, "FS_MKDIR exit, return code 0x.x" },
+{ 701088423, "FS_MOUNT entry, opcode_mode 0x.x" },
+{ 701088424, "FS_MOUNT exit, return code 0x.x" },
+{ 701088425, "FS_MOVE entry, opcode_mode 0x.x" },
+{ 701088426, "FS_MOVE exit, return code 0x.x" },
+{ 701088427, "FS_NEWSIZE entry, opcode_mode 0x.x" },
+{ 701088428, "FS_NEWSIZE exit, return code 0x.x" },
+{ 701088429, "FS_NMPIPE entry, opcode_mode 0x.x" },
+{ 701088430, "FS_NMPIPE exit, return code 0x.x" },
+{ 701088431, "FS_OPENCREATE entry, opcode_mode 0x.x" },
+{ 701088432, "FS_OPENCREATE exit, return code 0x.x" },
+{ 701088433, "FS_PATHINFO entry, opcode_mode 0x.x" },
+{ 701088434, "FS_PATHINFO exit, return code 0x.x" },
+{ 701088435, "FS_PROCESSNAME entry, opcode_mode 0x.x" },
+{ 701088436, "FS_PROCESSNAME exit, return code 0x.x" },
+{ 701088437, "FS_READ entry, opcode_mode 0x.x" },
+{ 701088438, "FS_READ exit, return code 0x.x" },
+{ 701088439, "FS_RMDIR entry, opcode_mode 0x.x" },
+{ 701088440, "FS_RMDIR exit, return code 0x.x" },
+{ 701088441, "FS_SETSWAP entry, opcode_mode 0x.x" },
+{ 701088442, "FS_SETSWAP exit, return code 0x.x" },
+{ 701088443, "FS_SHUTDOWN entry, opcode_mode 0x.x" },
+{ 701088444, "FS_SHUTDOWN exit, return code 0x.x" },
+{ 701088445, "FS_WRITE entry, opcode_mode 0x.x" },
+{ 701088446, "FS_WRITE exit, return code 0x.x" },
+{ 701088447, "FS_DEBUG entry, opcode_mode 0x.x" },
+{ 701088448, "FS_DEBUG exit, return code 0x.x" },
+{ 701088449, "FS_AlLOCATEPAGESPACE entry, opcode_mode 0x.x" },
+{ 701088450, "FS_AlLOCATEPAGESPACE exit, return code 0x.x" },
+{ 701088451, "FS_DOPAGEIO entry, opcode_mode 0x.x" },
+{ 701088452, "FS_DOPAGEIO exit, return code 0x.x" },
+{ 701088453, "FS_CANCELLOCKREQUEST entry, opcode_mode 0x.x" },
+{ 701088454, "FS_CANCELLOCKREQUEST exit, return code 0x.x" },
+{ 701088455, "FS_FILELOCKS entry, opcode_mode 0x.x" },
+{ 701088456, "FS_FILELOCKS exit, return code 0x.x" },
+{ 701088457, "FS_OPENPAGEFILE entry, opcode_mode 0x.x" },
+{ 701088458, "FS_OPENPAGEFILE exit, return code 0x.x" },
+{ 701088459, "FS unknown opcode entry, opcode_mode 0x.x" },
+{ 701088460, "FS unknown opcode exit, opcode_mode 0x.x, return code 0x.x" },
+{ 701088461, "CM cm_StoreDCache start store, chunk .d, len .d, smask .x" },
+{ 701202433, "dmb_Init_Routine called" },
+{ 701202434, "NewSession: no old session id .d: code .d" },
+{ 701202435, "findSession: no old session id .d: returning EINVAL" },
+{ 701202436, "stashIdent: xcred (.#x) but no EPAC: code .d" },
+{ 701202437, "stashIdent: auth .d of .d, .d gps, overflow at .d bytes" },
+{ 701202438, "stashIdent: auth .d, fgs .d of .d, overflow at .d bytes" },
+{ 701202439, "HandleToFs: discr .d not a FS; flags .#x, so returning EINVAL" },
+{ 701202440, "HandleToFs: discr .d not a file; flags .#x, so returning EINVAL" },
+{ 701202441, "HandleToFs: aggrId .d not found; returning EBADF" },
+{ 701202442, "HandleToFile: discr .d, returning .d" },
+{ 701202443, "GetRefs: sid is DM_NO_SESSION, so returning EINVAL" },
+{ 701202444, "GetRefs: flags .#x (incl. NOFS), but fp .#x is FS, so returning EINVAL" },
+{ 701202445, "GetRefs: flags .#x (incl. NOFILE), but fp .#x is file, so returning EINVAL" },
+{ 701202446, "GetRefs: flags .#x (incl. NEEDX), but fp .#x is not xlocked (.#x), so returning EACCES" },
+{ 701202447, "GetRefs: flags .#x (incl. NEEDS), but fp .#x is not slocked (.#x), so returning EACCES" },
+{ 701202448, "GetRefs: file not found on list for token .d, so returning EINVAL" },
+{ 701202449, "GetRefs: token .d not found on list for session .d, so returning EINVAL" },
+{ 701202450, "SetDisp: evset .x,,.x includes MOUNT event on non-global FS: EINVAL" },
+{ 701202451, "SetDisp: evset .x,,.x includes non-MOUNT event on global FS: EINVAL" },
+{ 701202452, "ObjRefOp: op .d, result .d" },
+{ 701202453, "ThingToHdl: path .s, result .d" },
+{ 701202454, "ThingToHdl: fd .d isn't, code .d" },
+{ 701202455, "ThingToHdl: agfs result .d" },
+{ 701202456, "ThingToHdl: non-agfs given; code .d" },
+{ 701202457, "dmb_Pending(sid .d, token .d, .d secs): returns .d" },
+{ 701202458, "dmb_GetTokenAuth(sid .d, token .d): output length .d, code .d" },
+{ 701202459, "dmb_SetAcl: src .#x is FS, not file; returning EINVAL" },
+{ 701202460, "dmb_SetAcl: src .#x NEEDX (flags .#x); returning EACCES" },
+{ 701202461, "dmb_DirNToHdl: string length (.d) wrong: returning EINVAL" },
+{ 701202462, "MoveEvent returning .d" },
+{ 701202463, "SendEvent: event id .d, type .d, state .d, session flags .#x" },
+{ 701202464, "AwaitReply: event id .d, type .d, state .d: about to wait" },
+{ 701202465, "AwaitReply: event id .d, type .d, response .d, errcode .d" },
+{ 701202466, "PollReply finishes: event id .d, type .d; response .d, errcode .d" },
+{ 701202467, "ExchangeMountEvent: aggrid .d session .#x, response .d, errcode .d)" },
+{ 701202468, "ExchangeMountEvent: SILLY answer for aggrid .d (sp .#x, response .d, errcode .d)" },
+{ 701202469, "LockOp: op .d, flags currently .#x, desiring .#x; result pre-set to .d" },
+{ 701202470, "dmab error conversion code .d to .d" },
+{ 701202471, "GetRefs: result code .d" },
+{ 701202472, "NewBareEvent: event id .d, type .d, pairid .d" },
+{ 701202473, "RespondEvent finishes: event id .d, type .d; response .d, errcode .d" },
+{ 701202474, "dmb_GetBulkAll: xflags .#x" },
+{ 701202475, "dmb_GetBulkAttr: xflags .#x" },
+{ 701202476, "dmb_GetDirAttrs: xflags .#x" },
+{ 701218817, "ag_dmepiAttach: dev .#x, vnode .x" },
+{ 701218818, "ag_dmepiAttach: internal error .d" },
+{ 701218819, "ag_dmepiAttach: sub-attach returns code .d" },
+{ 701218820, "ag_dmepiAttach: no ops vector for type .d" },
+{ 701218821, "ag_dmepiAttach: returning .d" },
+{ 701218822, "ag_dmepiDetach: aggr .#x" },
+{ 701218823, "ag_dmepiDetach: returning .d" },
+{ 701218824, "ag_dmepiStat: aggr .#x" },
+{ 701218825, "ag_dmepiStat: returning .d" },
+{ 701218826, "ag_dmepiVolCreate: aggr .#x, vid .u,,.u, flags .#x" },
+{ 701218827, "ag_dmepiVolCreate: returning .d" },
+{ 701218828, "ag_dmepiVolInfo: aggr .#x, index .d" },
+{ 701218829, "ag_dmepiVolInfo: returning .d" },
+{ 701218830, "ag_dmepiSync: aggr .#x, type .d" },
+{ 701218831, "ag_dmepiSync: returning .d" },
+{ 701218832, "vol_dmepiOpen: volp .#x, opentype .d, openerr .#x" },
+{ 701218833, "vol_dmepiOpen: volp .#x, myconcurr .d, subconcurr .d" },
+{ 701218834, "vol_dmepiOpen: returning .d" },
+{ 701218835, "vol_dmepiScan: volp .#x, position .d" },
+{ 701218836, "vol_dmepiScan: returning .d" },
+{ 701218837, "vol_dmepiClose: volp .#x, isAbort .d" },
+{ 701218838, "vol_dmepiClose: returning .d" },
+{ 701218839, "vol_dmepiDeplete: volp .#x" },
+{ 701218840, "vol_dmepiDeplete: returning .d" },
+{ 701218841, "vol_dmepiDestroy: volp .#x" },
+{ 701218842, "vol_dmepiDestroy: returning .d" },
+{ 701218843, "vol_dmepiAttach: volp .#x" },
+{ 701218844, "vol_dmepiAttach: returning .d" },
+{ 701218845, "vol_dmepiDetach: volp .#x, anyForce .d" },
+{ 701218846, "vol_dmepiDetach: returning .d" },
+{ 701218847, "vol_dmepiGetStatus: volp .#x, statusp .#x" },
+{ 701218848, "vol_dmepiGetStatus: returning .d" },
+{ 701218849, "vol_dmepiSetStatus: volp .#x, mask .#x, statusp .#x" },
+{ 701218850, "vol_dmepiSetStatus: returning .d" },
+{ 701218851, "vol_dmepiCreate: volp .#x, position .d" },
+{ 701218852, "vol_dmepiCreate: returning .d" },
+{ 701218853, "vol_dmepiRead: volp .#x, position .d,,.d, length .d" },
+{ 701218854, "vol_dmepiRead: returning .d, len .d" },
+{ 701218855, "vol_dmepiWrite: volp .#x, fid .x..x..x..x, position .d,,.d, length .d" },
+{ 701218856, "vol_dmepiWrite: returning .d" },
+{ 701218857, "vol_dmepiReadHole: volp .#x, fid .x..x..x..x, holedesc .#x" },
+{ 701218858, "vol_dmepiReadHole: returning .d" },
+{ 701218859, "vol_dmepiTruncate: volp .#x, fid .x..x..x..x, new size .d,,.d" },
+{ 701218860, "vol_dmepiTruncate: returning .d" },
+{ 701218861, "vol_dmepiDelete: volp .#x, fid .x..x..x..x" },
+{ 701218862, "vol_dmepiDelete: returning .d" },
+{ 701218863, "vol_dmepiGetattr: volp .#x, fid .x..x..x..x" },
+{ 701218864, "vol_dmepiGetattr: returning .d" },
+{ 701218865, "vol_dmepiSetattr: volp .#x, fid .x..x..x..x" },
+{ 701218866, "vol_dmepiSetattr: returning .d" },
+{ 701218867, "vol_dmepiGetAcl: volp .#x, fid .x..x..x..x, which .d" },
+{ 701218868, "vol_dmepiGetAcl: returning .d" },
+{ 701218869, "vol_dmepiSetAcl: volp .#x, fid .x..x..x..x, index .d, which .d" },
+{ 701218870, "vol_dmepiSetAcl: returning .d" },
+{ 701218871, "vol_dmepiClone: volp .#x, vol2p .#x" },
+{ 701218872, "vol_dmepiClone: returning .d" },
+{ 701218873, "vol_dmepiReclone: volp .#x, vol2p .#x" },
+{ 701218874, "vol_dmepiReclone: returning .d" },
+{ 701218875, "vol_dmepiUnclone: volp .#x, vol2p .#x" },
+{ 701218876, "vol_dmepiUnclone: returning .d" },
+{ 701218877, "vol_dmepiVget: volp .#x, fid .x..x..x..x" },
+{ 701218878, "vol_dmepiVget: returning .d, vnode .#x" },
+{ 701218879, "vol_dmepiRoot: volp .#x" },
+{ 701218880, "vol_dmepiRoot: returning .d, vnode .#x" },
+{ 701218881, "vol_dmepiIsRoot: volp .#x, fid .x..x..x..x" },
+{ 701218882, "vol_dmepiIsRoot: returning .d, flag .d" },
+{ 701218883, "vol_dmepiGetVV: volp .#x" },
+{ 701218884, "vol_dmepiGetVV: returning .d, vv .d,,.d" },
+{ 701218885, "vol_dmepiSetDyStat: volp .#x" },
+{ 701218886, "vol_dmepiSetDyStat: returning .d" },
+{ 701218887, "vol_dmepiSetNewVID: volp .#x, id .d,,.d" },
+{ 701218888, "vol_dmepiSetNewVID: returning .d" },
+{ 701218889, "vol_dmepiCopyAcl: volp .#x, fid .x..x..x..x, dest .d, ix .d" },
+{ 701218890, "vol_dmepiCopyAcl: returning .d" },
+{ 701218891, "vol_dmepiFreeDyStat: volp .#x" },
+{ 701218892, "vol_dmepiFreeDyStat: returning .d" },
+{ 701218893, "vol_dmepiConcurr: volp .#x, myconcurr .d, subconcurr .d" },
+{ 701218894, "vol_dmepiSwapIDs: volp .#x/id .d,,.d, volp .#x/id .d,,.d" },
+{ 701218895, "vol_dmepiSwapIDs: returning .d" },
+{ 701218896, "vol_dmepiSync: volp .#x, guarantee .d" },
+{ 701218897, "vol_dmepiSync: returning .d" },
+{ 701218898, "vol_dmepiPushStatus: volp .#x" },
+{ 701218899, "vol_dmepiPushStatus: returning .d" },
+{ 701218900, "vol_dmepiReaddir: volp .#x, fid .x..x..x..x, position .d,,.d, len .d" },
+{ 701218901, "vol_dmepiReaddir: returning .d, numEntries .d" },
+{ 701218902, "vol_dmepiAppenddir: volp .#x, fid .x..x..x..x, .d entries, preserve .d" },
+{ 701218903, "vol_dmepiAppenddir: returning .d" },
+{ 701218904, "vol_dmepiGetZLC: volp .#x, iter .#x" },
+{ 701218905, "vol_dmepiGetZLC: returning .d" },
+{ 701218906, "vol_dmepiGetNextHoles: volp .#x, fid .x..x..x..x, iter .#x" },
+{ 701218907, "vol_dmepiGetNextHoles: returning .d" },
+{ 701218908, "vol_dmepiBulkSetStatus: .d volumes" },
+{ 701218909, "vol_dmepiBulkSetStatus: returning .d" },
+{ 701218910, "getVfs: creating new VFS at .#x to be linked to existing at .#x; now .d exist" },
+{ 701218911, "getvNode: vnode .#x already converted" },
+{ 701218912, "getvNode: vnode .#x already linked to covered vnode .#x" },
+{ 701218913, "getvNode: allocating fresh vnode .#x to cover .#x (.d allocated so far, .d on freelist)" },
+{ 701218914, "getvNode: reusing free vnode .#x to cover .#x (.d allocated so far, .d on freelist)" },
+{ 701218915, "cvtVnode: NOT converting node .#x: cvted .d, cantCvt .d" },
+{ 701218916, "cvtVnode: converting node .#x to node .#x, code .d" },
+{ 701218917, "dmvn_open(.#x, .#x): covering .#x" },
+{ 701218918, "dmvn_open: returning node .#x, code .d" },
+{ 701218919, "dmvn_close(.#x, .#x): covering .#x" },
+{ 701218920, "dmvn_close: returning code .d" },
+{ 701218921, "dmvn_rdwr(.#x, .d, .d): covering .#x" },
+{ 701218922, "dmvn_rdwr: returning code .d" },
+{ 701218923, "dmvn_ioctl(.#x, .d, .d): covering .#x" },
+{ 701218924, "dmvn_ioctl: returning code .d" },
+{ 701218925, "dmvn_select(.#x, .d): covering .#x" },
+{ 701218926, "dmvn_select: returning code .d" },
+{ 701218927, "dmvn_getattr(.#x, .d): covering .#x" },
+{ 701218928, "dmvn_getattr: returning code .d" },
+{ 701218929, "dmvn_setattr(.#x, .d): covering .#x" },
+{ 701218930, "dmvn_setattr: returning code .d" },
+{ 701218931, "dmvn_access(.#x, .d): covering .#x" },
+{ 701218932, "dmvn_access: returning code .d" },
+{ 701218933, "dmvn_lookup(.#x, .s): covering .#x" },
+{ 701218934, "dmvn_lookup: returning code .d" },
+{ 701218935, "dmvn_create(.#x, .s, .d): covering .#x" },
+{ 701218936, "dmvn_create: returning code .d" },
+{ 701218937, "dmvn_remove(.#x, .s): covering .#x" },
+{ 701218938, "dmvn_remove: returning code .d" },
+{ 701218939, "dmvn_link(.#x, .#x, .s): second node NOT CVTED--use VOPN_LINK" },
+{ 701218940, "dmvn_link(.#x, .#x, .s): " },
+{ 701218941, "..... covering .#x, .#x: " },
+{ 701218942, "dmvn_link: returning code .d" },
+{ 701218943, "dmvn_rename(.#x, .s .#x, .s): second node NOT CVTED--use VOPN_RENAME" },
+{ 701218944, "dmvn_rename(.#x, .s, .#x, .s): " },
+{ 701218945, "..... covering .#x, .#x: " },
+{ 701218946, "dmvn_rename: returning code .d" },
+{ 701218947, "dmvn_mkdir(.#x, .s): covering .#x" },
+{ 701218948, "dmvn_mkdir: returning code .d" },
+{ 701218949, "dmvn_rmdir(.#x, .s, .#x): covering .#x" },
+{ 701218950, "dmvn_rmdir: returning code .d" },
+{ 701218951, "dmvn_readdir(.#x, .d): covering .#x" },
+{ 701218952, "dmvn_readdir: returning code .d" },
+{ 701218953, "dmvn_symlink(.#x, .s, .s): covering .#x" },
+{ 701218954, "dmvn_symlink: returning code .d" },
+{ 701218955, "dmvn_readlink(.#x): covering .#x" },
+{ 701218956, "dmvn_readlink: returning code .d" },
+{ 701218957, "dmvn_fsync(.#x): covering .#x" },
+{ 701218958, "dmvn_fsync: returning code .d" },
+{ 701218959, "dmvn_inactive(.#x): punt; new ref count .d > 0" },
+{ 701218960, "dmvn_inactive(.#x): covers .#x; freeing vp" },
+{ 701218961, "dmvn_inactive: freeing vfsp .#x that covers vfsp .#x; .d vfsp's" },
+{ 701218962, "dmvn_bmap(.#x, .d): covering .#x" },
+{ 701218963, "dmvn_bmap: returning code .d" },
+{ 701218964, "dmvn_lockctl(.#x, .d): covering .#x" },
+{ 701218965, "dmvn_lockctl: returning code .d" },
+{ 701218966, "dmvn_fid(.#x): covering .#x" },
+{ 701218967, "dmvn_fid: returning code .d" },
+{ 701218968, "dmvn_hold(.#x): covering .#x" },
+{ 701218969, "dmvn_hold: returning code .d" },
+{ 701218970, "dmvn_rele(.#x): covering .#x" },
+{ 701218971, "dmvn_rele: returning code .d" },
+{ 701218972, "dmvn_setacl(.#x, .d, .d): covering .#x" },
+{ 701218973, ".... (source vp .#x covering .#x) ...." },
+{ 701218974, "dmvn_setacl: returning code .d" },
+{ 701218975, "dmvn_getacl(.#x, .d): covering .#x" },
+{ 701218976, "dmvn_getacl: returning code .d" },
+{ 701218977, "dmvn_afsfid(.#x, .d): covering .#x" },
+{ 701218978, "dmvn_afsfid: returning code .d" },
+{ 701218979, "dmvn_getvolume(.#x): covering .#x" },
+{ 701218980, "dmvn_getvolume: returning code .d, volp .#x" },
+{ 701218981, "dmvn_getlength(.#x): covering .#x" },
+{ 701218982, "dmvn_getlength: returning code .d, length .#llx" },
+{ 701218983, "dmvn_map(.#x, .#x, .d): covering .#x" },
+{ 701218984, "dmvn_map: returning code .d" },
+{ 701218985, "dmvn_unmap(.#x, .d): covering .#x" },
+{ 701218986, "dmvn_unmap: returning code .d" },
+{ 701218987, "dmvn_read(.#x, .d): covering .#x" },
+{ 701218988, "dmvn_read: returning code .d" },
+{ 701218989, "dmvn_write(.#x, .d): covering .#x" },
+{ 701218990, "dmvn_write: returning code .d" },
+{ 701218991, "dmvn_realvp(.#x): covering .#x" },
+{ 701218992, "dmvn_realvp: returning vnode .#x, code .d" },
+{ 701218993, "dmvn_rwlock(.#x, .d): covering .#x" },
+{ 701218994, "dmvn_rwlock: returning" },
+{ 701218995, "dmvn_rwunlock(.#x, .d): covering .#x" },
+{ 701218996, "dmvn_rwunlock: returning" },
+{ 701218997, "dmvn_seek(.#x): covering .#x" },
+{ 701218998, "dmvn_seek: returning code .d" },
+{ 701218999, "dmvn_space(.#x, .d, .d): covering .#x" },
+{ 701219000, "dmvn_space: returning code .d" },
+{ 701219001, "dmvn_getpage(.#x, .d): covering .#x" },
+{ 701219002, "dmvn_getpage: returning code .d" },
+{ 701219003, "dmvn_putpage(.#x, .d): covering .#x" },
+{ 701219004, "dmvn_putpage: returning code .d" },
+{ 701219005, "dmvn_addmap(.#x, .d): covering .#x" },
+{ 701219006, "dmvn_addmap: returning code .d" },
+{ 701219007, "dmvn_delmap(.#x, .d): covering .#x" },
+{ 701219008, "dmvn_delmap: returning code .d" },
+{ 701219009, "dmvn_pageio(.#x, .d): covering .#x" },
+{ 701219010, "dmvn_pageio: returning code .d" },
+{ 701219011, "dmvn_setfl(.#x, .d, .d): covering .#x" },
+{ 701219012, "dmvn_setfl: returning code .d" },
+{ 701219013, "dmvn_dispose(.#x, .d, .d): covering .#x" },
+{ 701219014, "dmvn_dispose: returning" },
+{ 701219015, "dmvn_setsecattr(.#x, .d): covering .#x" },
+{ 701219016, "dmvn_setsecattr: returning code .d" },
+{ 701219017, "dmvn_getsecattr(.#x, .d): covering .#x" },
+{ 701219018, "dmvn_getsecattr: returning code .d" },
+{ 701219019, "dmvfs_root(.#x) called" },
+{ 701219020, "dmvfs_root: returning code .d, vnode .#x" },
+{ 701219021, "dmvfs_statfs(.#x): covering vfs .#x" },
+{ 701219022, "dmvfs_statfs: returning code .d" },
+{ 701219023, "dmvfs_sync(.#x): covering aggr .#x" },
+{ 701219024, "dmvfs_sync: returning code .d" },
+{ 701219025, "dmvfs_vget(.#x) called" },
+{ 701219026, "dmvfs_vget: returning code .d, vnode .#x" },
+{ 701219027, "dmvfs_vfsgetvolume(.#x) called" },
+{ 701219028, "dmvfs_vfsgetvolume: returning code .d, volp .#x" },
+{ 701219029, "dmvfs_mount(.#x) called; mounted-on vp .x" },
+{ 701219030, "dmvfs_mount: returning code .d" },
+{ 701219031, "dmvfs_unmount(.#x) called; covered op is .x" },
+{ 701219032, "dmvfs_unmount: returning code .d" },
+{ 701219033, "vol_dmepiDMWait(vol .#x, .#x) entered" },
+{ 701219034, "vol_dmepiDMFree(vol .#x, .#x) entered" },
+{ 701219035, "registerDmptr(.#x): tid .#x; .d in use, .d on free list" },
+{ 701219036, "unRegisterDmptr(.#x): tid .#x; .d left in use, .d on free list" },
+{ 701219037, "InterlockVnop(.#x..): ckbits .#x, adp->flags .#x, vnopflags .#x" },
+{ 701219038, "preDetach(aggrp .#x): creating preunmount evt, fsp .#x, ID .d" },
+{ 701219039, "preDetach: event created, code .d, pointer .#x" },
+{ 701219040, "preDetach: response: .d, retcode .d" },
+{ 701219041, "postDetach(aggrp .#x): creating unmount evt, fsp .#x, code .d" },
+{ 701219042, "postDetach: event created, code .d, pointer .#x" },
+{ 701219043, "postDetach: response received" },
+{ 701219044, "dmepi_checkLock(.#x): ckbits .#x in .#x, flags .#x" },
+{ 701219045, "dmvn_inactive(.x): covered .x, LOCKED: .x; LC is .d" },
+{ 701219046, "endVnop LEAVING dmptr: dmptr .x, evset .x, flags .d" },
+{ 701219047, "endVnop reclaiming dmptr: dmptr .x, evset .x, flags .d" },
+{ 701219048, "dmwait waiting: dmptr .x, evset .x, flags .d, evp .x" },
+{ 701219049, "dmwait--why?: dmptr .x, evset .x, flags .d" },
+{ 701219050, "ag_dmepiVolCreate: bailing from CREATE response (.d, code .d)" },
+{ 701219051, "throwAttributeEvt: ptr .#x, dt_change now .d, from .s" },
+{ 701219052, "eventPre: new type=.d event, pair .d; vp1 .#x, vp2 .#x" },
+{ 701219053, "eventPost: new type=.d event, pair .d; vp1 .#x, vp2 .#x" },
+{ 701219054, "eventSyncPost: new type=.d event, pair .d; vp1 .#x, vp2 .#x" },
+{ 701219055, "checkWhetherDone: expecting wait, pair .d; flags .#x, sequence .d" },
+{ 701219056, "checkWhetherDone: pair .d; raw delay .d, log4 .d, truncDelay .d" },
+{ 701219057, "abortPost: new type=.d event, pair .d; vp1 .#x, vp2 .#x" },
+{ 701219058, "abortSyncPost: new type=.d event, pair .d; vp1 .#x, vp2 .#x" },
+{ 701219059, "gcEvSets: abandoned set, pair .d; started .d, last resp .d" },
+{ 701219060, "gcEvSets: new CANCEL event, pair .d" },
+{ 701219061, "dmefs_getHdl: need to evaluate handle for vp .#x" },
+{ 701219062, "dmefs_setEventList: aggr .#x: changing from .x,,.x to .x,,.x" },
+{ 701219063, "dmefs_setEventList: vp .#x: changing from .x,,.x to .x,,.x (lkp code .d)" },
+{ 701219064, "safeGetVol: vol .#x, .d,,.d, unsafe: states .#x, accstat .#x" },
+{ 701219065, "setLock: aggr .#x, to right .d, flags .#x" },
+{ 701219066, "setLock: vp .#x, to right .d, flags .#x" },
+{ 701219067, "setLock: done; right .d, code .d" },
+{ 701219068, "getPath: fsp .#x: lengths .d and .d, so EINVAL" },
+{ 701219069, "getPath: fsp .#x: volid .d,,.d: returns .d" },
+{ 701219070, "getPath: fsp .#x: fid .x..x..x..x: returns .d" },
+{ 701219071, "getPath: fsp .#x: discr .d, fid .x..x..x..x: returns .d" },
+{ 701219072, "getPath: fsp .#x: done; returning .d" },
+{ 701219073, "dmepi_getAcl: vp .#x, which=.d" },
+{ 701219074, "dmepi_getAcl: vp .#x, outlen .d, code .d" },
+{ 701219075, "dmepi_setAcl: vp .#x, svp .#x, tgt which=.d, src which=.d" },
+{ 701219076, "dmepi_setAcl: vp .#x, code .d" },
+{ 701219077, "dmepi_getFtInfo: aggrp .#x, cookie .d, buflen .d" },
+{ 701219078, "dmepi_getFtInfo: aggrp .#x, ocookie .d, obuflen .d; code .d" },
+{ 701219079, "dmepi_dirNToHdl: vp .#x, name '.s'" },
+{ 701219080, "dmepi_dirNToHdl: returning code .d" },
+{ 701219081, "dmepi_getFileAttr: vp .#x, mask .#x" },
+{ 701219082, "dmepi_getFileAttr: vp .#x, returning code .d" },
+{ 701219083, "dmepi_getDirAttrs: vp .#x, pos .x,,.x, mask .#x, size .d" },
+{ 701219084, "dmepi_getDirAttrs: vp .#x, pos .x,,.x, used .d, returning code .d" },
+{ 701219085, "dmepi_getDirAttrs: READDIR returns code .d; of room for .#x, offset left at .#x and resid at .#x" },
+{ 701219086, "dmepi_getDirAttrs: VOPX_READDIR simply errs out with code .d" },
+{ 701219087, "dmepi_getDirAttrs: at EOF (blksize .#x, out resid .#x)" },
+{ 701219088, "dmepi_getDirAttrs: offset .#x: VOPX_LOOKUP(.s) gives vp .x, code .d" },
+{ 701219089, "dmepi_getDirAttrs: got error code .d from a vnode op" },
+{ 701219090, "dmepi_getDirAttrs: buffer full (.d > .d); dir offset .#x, buf offset .d" },
+{ 701219091, "dmepi_getDirAttrs: consuming .d bytes of dir, .d bytes to go; dir offset .#x, buf offset .d" },
+{ 701219092, "dmepi_getDirAttrs: overwriting offset .x,,.x with .x; dir offset .#x, buf offset .d" },
+{ 701219093, "dmepi_getDirAttrs: Updating offset to .x,,.x; dir offset .#x, buf offset .d" },
+{ 701219094, "dmepi_getBulkAttr: aggrp .#x, volix .d, vnix .d, mask .#x" },
+{ 701219095, "dmepi_getBulkAttr: volix .d, vnix .d, used .d bytes, returning code .d" },
+{ 701219096, "dmepi_getBulkAttr: volix .d is id .d,,.d; lookup result is .d" },
+{ 701219097, "dmvfs_mount() returns ENOSYS since epiops=.x and cvtedVfs=.x" },
+{ 701219098, "dmefs_getHdl: vp .#x, bad handle length .d; returning code EBADF." },
+{ 701219099, "vol_dmepiOpen(volp .#x): ckbits .#x, aggrflags .#x; eventp .x" },
+{ 701219100, "dmepi_getBulkAttr: ... and moreFlag is .d" },
+{ 701219101, "dmepi_getBulkAttr: Setting moreFlag; bneeded (.d) > bufleft (.d); vix .d, vnix .d" },
+{ 701219102, "vol_dmepiOpenVolume(volp .#x): ops .#x, event ptr .#x" },
+{ 701219103, "vol_dmepiOpenVolume: vol_open failed; returning code .d" },
+{ 701219104, "vol_dmepiOpenVolume returns success" },
+{ 701219105, "vol_dmepiCloseVolume(volp .#x): inCode .d" },
+{ 701219106, "vol_dmepiCloseVolume returns code .d" },
+{ 701219107, "dmvn_setxtdattr(.#x): covering .#x" },
+{ 701219108, "dmvn_setxtdattr: returning code .d" },
+{ 701219109, "dmvn_getxtdattr(.#x): covering .#x" },
+{ 701219110, "dmvn_getxtdattr: returning code .d" },
+{ 701219111, "dmefs_setEventList: replaced; code .d" },
+{ 701219112, "dmefs_setEventList: added; code .d" },
+{ 701219113, "dmefs_setEventList: on-disk replace returns .d" },
+{ 701219114, "dmepi_setDmAttr: vp .#x, name '.s', value len=.d, newdmtime=.d" },
+{ 701219115, "dmefs_setDmAttr: replaced; code .d" },
+{ 701219116, "dmefs_setDmAttr: added; code .d" },
+{ 701219117, "dmepi_setDmAttr returns code .d" },
+{ 701219118, "dmefs_NewDtime: replaced; code .d" },
+{ 701219119, "dmefs_NewDtime: added; code .d" },
+{ 701219120, "dmepi_getDmAttr: vp .#x, name '.s', buflen .d" },
+{ 701219121, "dmepi_getDmAttr returns outlen .d, code .d" },
+{ 701219122, "dmepi_rmDmAttr: vp .#x, name '.s', newdmtime=.d" },
+{ 701219123, "dmefs_rmDmAttr: removal returns code .d" },
+{ 701219124, "dmepi_rmDmAttr returns code .d" },
+{ 701219125, "dmepi_getAllDmAttr: vp .#x, buflen .d" },
+{ 701219126, "dmepi_getAllDmAttr returns outlen .d, code .d" },
+{ 701219127, "dmepi_getBulkAll: aggrp .#x, volix .d, vnix .d, mask .#x" },
+{ 701219128, "dmepi_getBulkAll: volix .d, vnix .d, used .d bytes, returning code .d" },
+{ 701219129, "dmepi_getBulkAll: volix .d is id .d,,.d; lookup result is .d" },
+{ 701219130, "dmepi_getBulkAll: ... and moreFlag is .d" },
+{ 701219131, "dmepi_LockFS(right .#x, aggrp .#x): adp flags are .#x, ..." },
+{ 701219132, "... vnops are rd=.d, wr=.d; volopens are rd=.d, wr=.d" },
+{ 701219133, "dmepi_LockFile(right .#x, vp .#x): dmlockState is .#x, ..." },
+{ 701219134, "... vnops are rd=.d, wr=.d" },
+{ 701219135, "dmepi_setFileAttr: vp .#x, mask .#x" },
+{ 701219136, "dmepi_setFileAttr returns code .d" },
+{ 701219137, "cvtVnode: node .#x has BAD regions length .d" },
+{ 701219138, "dmepi_getRegion(.#x) called, space for .d regions" },
+{ 701219139, "dmepi_getRegion returns code .d" },
+{ 701219140, "dmepi_setRegion returns EINVAL because of bad flag value[.d] .#x" },
+{ 701219141, "dmepi_setRegion returns EINVAL; .d'th region (starting .lu,,.lu, flags .#x) has 0 size (to EOF), not at end of .d regions" },
+{ 701219142, "dmepi_setRegion returns EINVAL; .d'th region (.lu,,.lu for .lu,,.lu) overlaps next region (starting .lu,,.lu)" },
+{ 701219143, "dmepi_setRegion(.#x) called with .d regions" },
+{ 701219144, "dmepi_setRegion returns code .d, exactflag .d" },
+{ 701219145, "dmepi_getRegion: type is .d, not VREG; returning code EINVAL" },
+{ 701219146, "dmepi_setRegion: type is .d, not VREG; returning code EINVAL" },
+{ 701219147, "dmepi_getAllocInfo(.#x) called, addr .lu,,.lu, space for .d extents" },
+{ 701219148, "dmepi_getAllocInfo: type is .d, not VREG; returning code EINVAL" },
+{ 701219149, "dmepi_getAllocInfo returns code .d, retval .d, addr .lu,,.lu, .d extents" },
+{ 701219150, "dataEventCheck: doing (rgop) .x on vp .x, from .lu,,.lu for .lu,,.lu" },
+{ 701219151, "dataEventCheck: considering ix .d, offset .lu,,.lu, len .lu,,.lu, rgops .x" },
+{ 701219152, "dataEventCheck: no matches, so no event" },
+{ 701219153, "dataEventCheck: matching for evtype .d, offset .lu,,.lu, len .lu,,.lu, rgops .x" },
+{ 701219154, "dataEventCheck: returning code .d (getting volume pointer)" },
+{ 701219155, "getSeq(type .d): looking, from .x,,.x for .x,,.x" },
+{ 701219156, "findSeq: checking one from .x,,.x for .x,,.x" },
+{ 701219157, "getSeq: no matches" },
+{ 701219158, "dmepi_readInvis vp .#x, off .#x,.#x, len .#x,.#x" },
+{ 701219159, "dmepi_readInvis done vp .#x, code .d, readlen .#x,.#x" },
+{ 701219160, "dmvn_readInvis vp .#x, off .#x,.#x, len .#x,.#x" },
+{ 701219161, "dmvn_readInvis done vp .#x, code .d, readlen .#x,.#x" },
+{ 701219162, "dmepi_writeInvis vp .#x, off .#x,.#x, len .#x,.#x" },
+{ 701219163, "dmepi_writeInvis done vp .#x, code .d, writelen .#x,.#x bytes" },
+{ 701219164, "dmvn_writeInvis vp .#x, off .#x,.#x, len .#x,.#x" },
+{ 701219165, "dmvn_writeInvis done vp .#x, code .d, writelen .#x,.#x" },
+{ 701219166, "dmepi_punchHole vp .#x, off .#x,.#x, len .#x,.#x" },
+{ 701219167, "dmepi_punchHole vp .#x, code .d" },
+{ 701219168, "dmvn_punch vp .#x, off .#x,.#x, len .#x,.#x, flag .#x" },
+{ 701219169, "dmvn_punch vp .#x, code .d" },
+{ 701219170, "dmepi_probeHole vp .#x, off .#x,.#x, len .#x,.#x" },
+{ 701219171, "dmepi_probeHole vp .#x, code .d, off .#x,.#x, len .#x,.#x" },
+{ 701219172, "dmvn_probehole vp .#x, off .#x,.#x, len .#x,.#x, flag .#x" },
+{ 701219173, "dmvn_probehole vp .#x, code .d, off .#x,.#x, len .#x,.#x" },
+{ 701219174, "dmvn_ckregion(vp .#x, off .#x,,.#x for .#x,,.#x, isWrite .d)" },
+{ 701219175, "dmvn_ckregion(vp .#x) returning code .d" },
+{ 701219176, "dmefs_BusyCode(pairid .d): raw delay .d, log4 .d, truncDelay .d" },
+{ 701219177, "dmepi_setRetDestroy aggrp .#x, attr '.s', doEnable .d" },
+{ 701219178, "dmepi_setRetDestroy returning code .d" },
+{ 701219179, "dmvn_inactive: enqueueing locked vnode .#x" },
+{ 701219180, "dmvn_inactive: vp .#x, getVol errors with code .d" },
+{ 701219181, "dmvn_inactive: vp .#x, getHdl errors with code .d" },
+{ 701219182, "makeDestroy(vp .#x, evtset .x,,.x) called" },
+{ 701219183, "processOneInactive, vp .#x: covers .#x; freeing vp" },
+{ 701219184, "badCov: no vnode for .#x at line .d, file .s" },
+{ 701219185, "inactiveDaemon, aggrid .d, did .d non-waits: about to call with wait (SQ .d)" },
+{ 701219186, "inactiveDaemon, aggrid .d, back from waiting call; .d pending, SQ .d" },
+{ 701219187, "inactiveDaemon, aggrid .d: finishing" },
+{ 701219188, "processOneInactive(aggrid .d, wait=.d): taking vp .#x" },
+{ 701219189, "processOneInactive, vp .#x: calling StartVnodeOp w/flags .#x before getattr" },
+{ 701219190, "processOneInactive(vp .#x): punt; new ref count .d > 0" },
+{ 701219191, "processOneInactive(vp .#x): linkcount guess still < 0, so putting back on queue" },
+{ 701219192, "processOneInactive(vp .#x): linkcount 0, so generating DESTROY evts" },
+{ 701219193, "processOneInactive(vp .#x): punt; no destroys; new ref count .d > 0" },
+{ 701219194, "processOneInactive(vp .#x): deallocating vnode. Count now .d, waiters .d" },
+{ 701219195, "awaitAllInactive(agid .d): about to wait for first" },
+{ 701219196, "awaitAllInactive(agid .d): all done" },
+{ 701219197, "awaitAllInactive(agid .d): about to sleep; count .d, waiters .d" },
+{ 701219198, "awaitAllInactive(agid .d): back from sleep; count .d, waiters .d" },
+{ 701219199, "FlushCovers(volid .lu,,.lu) called" },
+{ 701219200, "FlushCovers(volid .lu,,.lu) returning" },
+{ 701219201, "FlushCovers(volp=0) called" },
+{ 701219202, "FlushCovers(volp=0) returning" },
+{ 701219203, "dmvn_space off .d len .d" },
+{ 701219204, "dmvn_getextentinfo vp .#x, off .#llx, nextents .d" },
+{ 701219205, "dmvn_getextentinfo end vp .#x, off .#llx, flags .#x, nextents .d" },
+{ 701219206, "dmvn_getextentinfo failed vp .#x, code .d" },
+{ 701219207, "dmepi_getAllocInfo extent ix .d, exttype .d, extoff .#x, extlen .#x" },
+{ 701219208, "dmepi_getAllocInfo ix .d type .d to ix .d type .d" },
+{ 701219209, "dmepi_getAllocInfo stoff .#x,,.#x, stlen .#x,,.#x, dsttype .d" },
+{ 701219210, "dmepi_getAllocInfo soff .#x,,.#x, slen .#x,,.#x, dsttype .d" },
+{ 701219211, "dmepi_getAllocInfo dstIx .d, type .d, dstoff .#x,,.#x, dstlen .#x,,.#x" },
+{ 701219212, "px waiting for event pairid .d, flags .#x, sequence .d" },
+{ 701219213, "abandon_Seq: abandoned set, pair .d" },
+{ 701219214, "dmvn_pathconf(.#x, .d): covering .#x" },
+{ 701219215, "dmvn_pathconf: returning code .d" },
+{ 701219216, "getvNode: moribund dm vnode .#x, covered vnode .#x, code .d" },
+{ 701219217, "dmepi_getAllocInfo type RES, dstIx .d, dstoff .#x,,.#x, dstlen .#x,,.#x" },
+{ 701219218, "dmepi_checkLock(.#x): lockstate .#x, setting .#x" },
+{ 701219219, "dmepi_uncheckLock(.#x): lockstate .#x, unsetting XCLLOCKWAITING and SHRLOCKWAITING" },
+{ 701219220, "dmepi_LockFile(.#x), lockState .#x, unlock bit .#x" },
+{ 701219221, "dmepi_LockFile nonblocking (right .#x, vp .#x): dmlockState is .#x, ..." },
+{ 701219222, "dmepi_LockFile locking right .#x in vp .#x, current lockstate .#x, fp current flags .#x" },
+{ 701219223, "dmepi_checkLock(.#x) incr wr op count to .d" },
+{ 701219224, "dmepi_checkLock(.#x) incr rd op count to .d" },
+{ 701219225, "dmepi_uncheckLock(.#x) decr wr op count to .d" },
+{ 701219226, "dmepi_uncheckLock(.#x) decr rd op count to .d" },
+{ 701219227, "vol_dmepiReadPurgeHole: volp .#x, fid .x..x..x..x, holedesc .#x" },
+{ 701219228, "vol_dmepiReadPurgeHole: returning code .d" },
+{ 701219229, "vol_dmepiPunch: fid .x..x..x..x, offset .#x,,.#x, length .#x,,.#x, flags .#x" },
+{ 701219230, "vol_dmepiPunch: returning code .d" },
+{ 701219231, "vol_dmepiGetXtdattr: fid .x..x..x..x" },
+{ 701219232, "vol_dmepiGetXtdattr: returning code .d" },
+{ 701219233, "vol_dmepiSetXtdattr: fid .x..x..x..x" },
+{ 701219234, "vol_dmepiSetXtdattr: returning code .d" },
+{ 701219235, "findSeq(type .d): looking, from .x,,.x for .x,,.x" },
+{ 701219236, "dmepi_getBulkAll: DMAPI v2.3a version" },
+{ 701219237, "dmepi_getBulkAll: CAE XDSM version" },
+{ 701219238, "dmvn_finfo(.#x): covering .#x" },
+{ 701219239, "dmvn_finfo: returning code .d" },
+{ 701219240, "dmefs_CheckWhetherDone: not waiting, vp .#x, volp .#x, pairid .d, sequence .d" },
+{ 701219241, "dmepi_getBulkAll: volix .d, id .d,,.d, has max index of .d (code .d)" },
+{ 701219242, "dmepi_getBulkAttr: volix .d, id .d,,.d, has max index of .d (code .d)" },
+{ 701219243, "dmefs_CheckWhetherDone: not waiting, vp .#x, adp .#x, pairid .d, sequence .d" },
+{ 701219244, "dmepi_GetDFSToken wants tokens for .#x vp .d action .#x, .#x flags .d notinuse" },
+{ 701219245, "dmepi_GetDFSToken returns .#d" },
+{ 701219246, "dmepi_ReturnDFSToken entered" },
+{ 701219247, "dmepi_ReturnDFSToken returning token for .#x list id .#x id" },
+{ 701219248, "dmepih_RevokeToken wants token .#x types: .#x, .#x" },
+{ 701219249, "dmepi_LockFileExtended entered" },
+{ 701219250, "dmepi_LockFileExtended exit" },
+{ 701219251, "dmepi_getFtInfo: aggrp .#x, code2 .d, code3 .d, code4 .d" },
+{ 701247489, "dacl_FindMatchingListEntry: entered" },
+{ 701247490, "dacl_FindMatchingListEntry: user uuid is: `.s'" },
+{ 701247491, "dacl_FindMatchingListEntry: unable to translate user uuid into string" },
+{ 701247492, "dacl_FindMatchingListEntry: group uuid is: `.s'" },
+{ 701247493, "dacl_FindMatchingListEntry: unable to translate group uuid into string" },
+{ 701247494, "dacl_FindMatchingListEntry: realm uuid is: `.s'" },
+{ 701247495, "dacl_FindMatchingListEntry: unable to translate realm uuid into string" },
+{ 701247496, "dacl_FindMatchingListEntry: considering user id: `.s'" },
+{ 701247497, "dacl_FindMatchingListEntry: unable to translate user entry uuid into string" },
+{ 701247498, "dacl_FindMatchingListEntry: match found" },
+{ 701247499, "dacl_FindMatchingListEntry: considering group id: `.s'" },
+{ 701247500, "dacl_FindMatchingListEntry: unable to translate group entry uuid into string" },
+{ 701247501, "dacl_FindMatchingListEntry: match found" },
+{ 701247502, "dacl_FindMatchingListEntry: considering foreign other id: `.s'" },
+{ 701247503, "dacl_FindMatchingListEntry: unable to translate foreign other entry uuid into string" },
+{ 701247504, "dacl_FindMatchingListEntry: match found" },
+{ 701247505, "dacl_FindMatchingListEntry: considering foreign user id: `.s'@`.s'" },
+{ 701247506, "dacl_FindMatchingListEntry: unable to translate foreign user's realm uuid into string" },
+{ 701247507, "dacl_FindMatchingListEntry: unable to translate foreign user entry uuid into string" },
+{ 701247508, "dacl_FindMatchingListEntry: match found" },
+{ 701247509, "dacl_FindMatchingListEntry: considering foreign user id: `.s'@`.s'" },
+{ 701247510, "dacl_FindMatchingListEntry: unable to translate foreign user's realm uuid into string" },
+{ 701247511, "dacl_FindMatchingListEntry: unable to translate foreign user entry uuid into string" },
+{ 701247512, "dacl_FindMatchingListEntry: match found" },
+{ 701247513, ".s: realmIdP is NULL" },
+{ 701247514, ".s: realm is.s default" },
+{ 701247515, "dacl_epi_CheckAccessParams: error manager type (.s) requires object and group uuids in access comparison" },
+{ 701247516, "dacl_epi_CheckAccessParams: error manager type (.s) requires permission bits in access computation" },
+{ 701247517, "dacl_CheckAccessParams: error manager type (.s) requires object and group uuids in access comparison" },
+{ 701247518, "dacl_CheckAccessParams: error manager type (.s) requires permission bits in access computation" },
+{ 701247519, "dacl_ReadFromAnode: Episode aux data read error: .ld" },
+{ 701247520, "dacl_ReadFromAnode: unable to allocate .d bytes of memory" },
+{ 701247521, "dacl_SizeOfFlatList: byte count up to .d (incl. entry .d header)" },
+{ 701247522, "dacl_SizeOfFlatList: byte count up to .d (incl. entry .d)" },
+{ 701247523, "dacl_SizeOfFlatAcl: entered" },
+{ 701247524, "dacl_SizeOfFlatAcl: byte count up to .d (incl. acl header)" },
+{ 701247525, "dacl_SizeOfFlatAcl: byte count up to .d (incl. simple entries)" },
+{ 701247526, "dacl_SizeOfFlatAcl: byte count up to .d (incl. complex entries)" },
+{ 701247527, "dacl_SizeOfFlatAcl: exiting, returning .d" },
+{ 701247528, "dacl_FlattenExtendedInfo: entered, bytes left: .d" },
+{ 701247529, "dacl_FlattenExtendedInfo: Error: not enough bytes for extended entry data (.d needed, .d left)" },
+{ 701247530, "dacl_FlattenExtendedInfo: Error: not enough bytes for extended entry header (.d needed, .d left)" },
+{ 701247531, "dacl_FlattenExtendedInfo: exiting, returning .#x, bytes left: .d" },
+{ 701247532, "dacl_FlattenAclEntry: entered, bytes left: .d" },
+{ 701247533, "dacl_FlattenAclEntry: Error: not enough bytes for single epi_uuid (.d needed, .d left)" },
+{ 701247534, "dacl_FlattenAclEntry: Error: not enough bytes for single epi_uuid (.d needed, .d left)" },
+{ 701247535, "dacl_FlattenAclEntry: Error: not enough bytes for two epi_uuids (.d needed, .d left)" },
+{ 701247536, "dacl_FlattenAclEntry: Error: not enough bytes for entry header (.d needed, .d left)" },
+{ 701247537, "dacl_FlattenAclEntry: exiting, returning .#x, bytes left: .d" },
+{ 701247538, "dacl_FlattenAclWithModeBits: entered" },
+{ 701247539, "dacl_FlattenAclWithModeBits: buffer bytes: .d" },
+{ 701247540, "dacl_FlattenAclWithModeBits: not enough space given for flattening ACL" },
+{ 701247541, "dacl_FlattenAclWithModeBits: Error: not enough bytes for acl header (.d needed, .d left)" },
+{ 701247542, "dacl_FlattenAclWithModeBits: exiting, returning .#x, bytes in buffer: .d" },
+{ 701247543, "dacl_FlattenExtendedInfo: Warning: unexpected buffer misalignment" },
+{ 701247544, "dacl_FlattenAclEntry: Warning: unexpected pointer misalignment" },
+{ 701247545, "dacl_FlattenAclWithModeBits: Warning: unexpected pointer misalignment" },
+{ 701247546, "dacl_TestSimpleEntryInAcl: entered, entry type: .#x" },
+{ 701247547, "dacl_TestSimpleEntryInAcl: exiting, entry was.s found" },
+{ 701247548, "dacl_TestComplexEntryInList: entered, entry type: .#x" },
+{ 701247549, "dacl_TestComplexEntryInList: checking entry number .d, type is .#x" },
+{ 701247550, "dacl_TestComplexEntryInList: exiting, entry was.s found" },
+{ 701247551, "dacl_TestComplexEntryInAcl: entered, entry type: .#x" },
+{ 701247552, "dacl_TestComplexEntryInAcl: exiting, entry was.s found" },
+{ 701247553, "dacl_AddEntryToAcl: entry type has a much larger value than expected: .#x" },
+{ 701247554, "dacl_AddEntryToAcl: Warning: attempt to insert duplicate ACL entry of entry type .ld" },
+{ 701247555, "dacl_AddEntryToAcl: Warning: attempt to insert duplicate ACL entry of entry type .ld" },
+{ 701247556, "dacl_ModifyAclEntry: warning: attempt to modify non-existent acl entry" },
+{ 701247557, "dacl_DeleteAclEntry: warning: attempt to remove non-existent acl entry" },
+{ 701247558, "dacl_DeleteAclEntry: warning: attempt to remove required acl entry: .s" },
+{ 701247559, ".s: entered" },
+{ 701247560, ".s: principal uuid is: `.s'" },
+{ 701247561, ".s: unable to translate uuid into string" },
+{ 701247562, "dacl_ParseExtendedInfo: entered, bytes in buffer: .d" },
+{ 701247563, "dacl_ParseExtendedInfo: Error: not enough bytes for extended entry data (.d needed, .d left)" },
+{ 701247564, "dacl_ParseExtendedInfo: Error: not enough bytes for extended entry header (.d needed, .d left)" },
+{ 701247565, "dacl_ParseExtendedInfo: exiting, returning .#x, bytes left: .d" },
+{ 701247566, "dacl_ParseAclEntry: entered, bytes left: .d" },
+{ 701247567, "dacl_ParseAclEntry: found userobj entry" },
+{ 701247568, "dacl_ParseAclEntry: found groupobj entry" },
+{ 701247569, "dacl_ParseAclEntry: found otherobj entry" },
+{ 701247570, "dacl_ParseAclEntry: found mask obj entry" },
+{ 701247571, "dacl_ParseAclEntry: found anyother entry" },
+{ 701247572, "dacl_ParseAclEntry: found unauth entry" },
+{ 701247573, "dacl_ParseAclEntry: Error: duplicate ACL entry found of type .ld" },
+{ 701247574, "dacl_ParseAclEntry: found user entry" },
+{ 701247575, "dacl_ParseAclEntry: found group entry" },
+{ 701247576, "dacl_ParseAclEntry: Error: not enough bytes for single epi_uuid (.d needed, .d left)" },
+{ 701247577, "dacl_ParseAclEntry: found foreign other entry" },
+{ 701247578, "dacl_ParseAclEntry: Error: not enough bytes for single epi_uuid (.d needed, .d left)" },
+{ 701247579, "dacl_ParseAclEntry: found foreign user entry" },
+{ 701247580, "dacl_ParseAclEntry: found foreign group entry" },
+{ 701247581, "dacl_ParseAclEntry: Error: not enough bytes for an epi_uuid and an epi_principal_id (.d needed, .d left)" },
+{ 701247582, "dacl_ParseAclEntry: found extended entry" },
+{ 701247583, "dacl_ParseAclEntry: Error: not enough bytes for entry header (.d needed, .d left)" },
+{ 701247584, "dacl_ParseAclEntry: exiting, returning .#x, bytes left: .d" },
+{ 701247585, "dacl_ParseAclDiskOption: entered, bytes in buffer: .d" },
+{ 701247586, "dacl_ParseAclDiskOption: Error: acl mgr uuid passed does not match mgr uuid in acl to be parsed" },
+{ 701247587, "dacl_ParseAclDiskOption: required mgr uuid is: .s" },
+{ 701247588, "dacl_ParseAclDiskOption: unable to translate required mgr uuid in ACL to string" },
+{ 701247589, "dacl_ParseAclDiskOption: mgr uuid in ACL is: .s" },
+{ 701247590, "dacl_ParseAclDiskOption: unable to translate mgr uuid in ACL to string" },
+{ 701247591, "dacl_ParseAclDiskOption: realm uuid is: .s" },
+{ 701247592, "dacl_ParseAclDiskOption: unable to translate realm uuid in ACL to string" },
+{ 701247593, "dacl_ParseAclDiskOption: Error: not enough bytes for acl header (.d needed, .d left)" },
+{ 701247594, "dacl_ParseAclDiskOption: Error: .d bytes left-over after acl parse" },
+{ 701247595, "dacl_ParseAclDiskOption: exiting, returning .#x, bytes left: .d" },
+{ 701247596, "dacl_ParseExtendedInfo: Warning: unexpected buffer misalignment" },
+{ 701247597, "dacl_ParseExtendedInfo: Error: unable to allocate .d bytes of buffer space" },
+{ 701247598, "dacl_ParseAclEntry: Warning: unexpected buffer misalignment" },
+{ 701247599, "dacl_ParseAclEntry: entry type has a much larger value than expected: .#x" },
+{ 701247600, "dacl_CheckObjPtrsFromAcl: Error: required user object entry missing on ACL" },
+{ 701247601, "dacl_CheckObjPtrsFromAcl: Error: required group object entry missing on ACL" },
+{ 701247602, "dacl_CheckObjPtrsFromAcl: Error: required other object entry missing on ACL" },
+{ 701247603, "dacl_ParseAclDiskOption: Warning: unexpected buffer misalignment" },
+{ 701247604, "dacl_ParseAclDiskOption: Error: unable to allocate .d bytes of buffer space for list .d" },
+{ 701247605, "dacl_PermsetsToPermBits: Error: required parameter, permBitsP, is NULL" },
+{ 701247606, "dacl_WriteToDisk: .s write: .s" },
+{ 701247607, "dacl_WriteToDisk: .s close: .s" },
+{ 701247608, "dacl_WriteToDisk: .s open: .s" },
+{ 701247609, "dacl_CreateAclOnDisk: entered, filename is .s" },
+{ 701247610, "dacl_CreateAclOnDisk: about to create ACL" },
+{ 701247611, "dacl_CreateAclOnDisk: Warning: user_obj and group_obj perms ignored for ACL mgr type .s" },
+{ 701247612, "dacl_CreateAclOnDisk: .s afs_syscall to write ACL: .s" },
+{ 701247613, "dacl_CreateAclOnDisk: error flattening new ACL for Episode write: .s" },
+{ 701247614, "dacl_CreateAclOnDisk: file already exists" },
+{ 701247615, "dacl_CreateAclOnDisk: .s stat: .s" },
+{ 701247616, "dacl_CreateAclOnDisk: .s stat: .s" },
+{ 701247617, "dacl_CreateAclOnDisk: exiting, returning .ld" },
+{ 701247618, "dacl_PrintRealmName: sec_id_gen_name error on name: .d" },
+{ 701247619, "dacl_PrintRealmName: sec_id_gen_name error on name: .s" },
+{ 701247620, "dacl_ReadFromDisk: Error: unable to allocate .d bytes of buffer space" },
+{ 701247621, "dacl_ReadFromDisk: entered, filename is .s" },
+{ 701247622, "dacl_ReadFromDisk: .s read: .s" },
+{ 701247623, "dacl_ReadFromDisk: .s fstat: .s" },
+{ 701247624, "dacl_ReadFromDisk: .s close: .s" },
+{ 701247625, "dacl_ReadFromDisk: .s open: .s" },
+{ 701247626, "dacl_ReadFromDisk: exiting, returning .#x" },
+{ 701247627, "dacl_From_SecAcl_ExtendedInfo: unable to allocate buffer for extended bytes for daclEntryP" },
+{ 701247628, "dacl_From_SecAcl: unable to allocate buffer for complex entry array" },
+{ 701247629, "dacl_From_SecAcl: duplicate simple entry, type .d, found in secAclP" },
+{ 701247630, "dacl_From_SecAcl: something strange happened in identifying the entry type" },
+{ 701247631, "dacl_From_SecAcl: unrecognized entry type, .d, found in secAclP" },
+{ 701247632, "dacl_From_SecAcl: error allocating extended entry array buffer" },
+{ 701247633, "dacl_From_SecAcl: error incorrect ACL manager uuid in secAclP" },
+{ 701247634, "dacl_To_SecAcl_ExtendedInfo: error allocating buttfer for extended info for secAclEntryP" },
+{ 701247635, "dacl_To_SecAcl: unrecoginzed entry type, .d, found in daclP" },
+{ 701247636, "dacl_To_SecAcl: error allocating buffer for secAclP entries" },
+{ 701247637, "dacl_InitPac: no passwd file entry found for .s" },
+{ 701247638, "dacl_InitPac: no group file entry found for .s" },
+{ 701247639, "dacl_AddLocalGroupToPac: no group file entry found for .s" },
+{ 701247640, "dacl_InitAclEntryFromStrings: entered" },
+{ 701247641, "dacl_InitAclEntryFromStrings: name string `.s' ignored for acl entry type: .s" },
+{ 701247642, "dacl_InitAclEntryFromStrings: data string `.s' ignored for acl entry type: .s" },
+{ 701247643, "dacl_InitAclEntryFromStrings: no passwd file entry found for .s" },
+{ 701247644, "dacl_InitAclEntryFromStrings: entry type .s cannot be mapped locally" },
+{ 701247645, "dacl_InitAclEntryFromStrings: no group file entry found for .s" },
+{ 701247646, "dacl_InitAclEntryFromStrings: entry type .s cannot be mapped locally" },
+{ 701247647, "dacl_InitAclEntryFromStrings: exiting, returning: .s" },
+{ 701247648, "dacl_NameAndTypeStringsFromEntry entered" },
+{ 701247649, "dacl_NameAndTypeStringsFromEntry: no passwd file entry found for uid .d" },
+{ 701247650, "dacl_NameAndTypeStringsFromEntry: entry type .d cannot be mapped locally" },
+{ 701247651, "dacl_NameAndTypeStringsFromEntry: no group file entry found for if .d" },
+{ 701247652, "dacl_NameAndTypeStringsFromEntry: entry type .s cannot be mapped locally" },
+{ 701247653, "dacl_NameAndTypeStringsFromEntry exiting; returning .ld" },
+{ 701247654, "dacl_NameAndTypeStringsFromEntry exiting; returning .s" },
+{ 701247655, "dacl_InitPac: sec_rgy_pgo_name_to_id raised an exception on name: .d; see stdout" },
+{ 701247656, "dacl_InitPac: .s error on name: .s: .s" },
+{ 701247657, "dacl_InitPac: sec_rgy_pgo_name_to_id raised an exception on name: .s; see stdout" },
+{ 701247658, "dacl_InitPac: .s error on name: .s: .s" },
+{ 701247659, "dacl_InitPac: sec_id_parse_name raised an exception on name: .s; see stdout" },
+{ 701247660, "dacl_InitPac: sec_id_parse_name error on name: .s: .s" },
+{ 701247661, "dacl_AddLocalGroupToPac: buffer allocation error" },
+{ 701247662, "dacl_AddLocalGroupToPac: sec_rgy_pgo_name_to_id error on name: .s; see stdout" },
+{ 701247663, "dacl_AddLocalGroupToPac: .s error on name: .s: .s" },
+{ 701247664, "dacl_InitAclEntryFromStrings: attempt to add an entry type (.#x) inappropriate for the ACL mgr type: .s" },
+{ 701247665, "dacl_InitAclEntryFromStrings: error on uuid comparison: .s" },
+{ 701247666, "dacl_InitAclEntryFromStrings: sec_id_parse_name raised an exception in name: .s; see stdout" },
+{ 701247667, "dacl_InitAclEntryFromStrings: sec_id_parse_name error on name: .s: .s" },
+{ 701247668, "dacl_InitAclEntryFromStrings: error, name required for given acl entry type: .s" },
+{ 701247669, "dacl_InitAclEntryFromStrings: error, name required for given acl entry type: .s" },
+{ 701247670, "dacl_InitAclEntryFromStrings: error on uuid comparison: .s" },
+{ 701247671, "dacl_InitAclEntryFromStrings: sec_id_parse_group raised an exception in name: .s; see stdout" },
+{ 701247672, "dacl_InitAclEntryFromStrings: sec_id_parse_group error on name: .s: .s" },
+{ 701247673, "dacl_InitAclEntryFromStrings: error, name required for given acl entry type: .s" },
+{ 701247674, "dacl_NameAndTypeStringsFromEntry: .s returned an error: .s" },
+{ 701247675, "dacl_NameAndTypeStringsFromEntry: sec_rgy_pgo_unix_num_to_id raised an exception; see stdout" },
+{ 701247676, "dacl_NameAndTypeStringsFromEntry: sec_rgy_pgo_unix_num_to_id returned an error: .s" },
+{ 701247677, "dacl_NameAndTypeStringsFromEntry: sec_rgy_site_open returned an error: .s" },
+{ 701247678, "dacl_NameAndTypeStringsFromEntry: sec_id_gen_name raised an exception; see stdout" },
+{ 701247679, "dacl_NameAndTypeStringsFromEntry: sec_id_gen_name returned an error: .s" },
+{ 701247680, "dacl_NameAndTypeStringsFromEntry: sec_id_gen_group raised an exception; see stdout" },
+{ 701247681, "dacl_NameAndTypeStringsFromEntry: sec_id_gen_group returned an error: .s" },
+{ 701247682, "dacl_NameAndTypeStringsFromEntry: sec_id_gen_name raised an exception; see stdout" },
+{ 701247683, "dacl_NameAndTypeStringsFromEntry: sec_id_gen_name returned an error: .s" },
+{ 701247684, "dacl_EntryType_FromString: entered" },
+{ 701247685, "dacl_EntryType_FromString: copied type .#x for string .s" },
+{ 701247686, "dacl_EntryType_FromString: exiting, returning .#x" },
+{ 701247687, "dacl_ParsePermsetString: considering character .c" },
+{ 701247688, "dacl_ParsePermsetString: about to add perm, current permset: .#x" },
+{ 701247689, "dacl_ParsePermsetString: added perm for character .c, current permset: .#x" },
+{ 701247690, "dacl_ExtendedInfoUuidTranslate: entered, bytes in buffer: .d" },
+{ 701247691, "dacl_ExtendedInfoUuidTranslate: Error: not enough bytes for extended entry data (.d needed, .d left)" },
+{ 701247692, "dacl_ExtendedInfoUuidTranslate: Error: not enough bytes for extended entry header (.d needed, .d left)" },
+{ 701247693, "dacl_ExtendedInfoUuidTranslate: exiting, returning .#x, bytes left: .d" },
+{ 701247694, "dacl_AclEntryUuidTranslate: entered, bytes left: .d" },
+{ 701247695, "dacl_AclEntryUuidTranslate: Error: not enough bytes for single epi_uuid_t (.d needed, .d left)" },
+{ 701247696, "dacl_AclEntryUuidTranslate: Error: not enough bytes for two epi_uuid_ts (.d needed, .d left)" },
+{ 701247697, "dacl_AclEntryUuidTranslate: Error: not enough bytes for entry header (.d needed, .d left)" },
+{ 701247698, "dacl_AclEntryUuidTranslate: exiting, returning .#x, bytes left: .d" },
+{ 701247699, "dacl_BufferUuidTranslate entered, bytes in buffer: .d" },
+{ 701247700, "dacl_BufferUuidTranslate: Error: not enough bytes for acl header (.d needed, .d left)" },
+{ 701247701, "dacl_BufferUuidTranslate: Error: .d bytes left-over after acl parse" },
+{ 701247702, "dacl_BufferUuidTranslate: exiting, returning .#x, bytes left: .d" },
+{ 701247703, "dacl_ExtendedInfoUuidTranslate: Warning: unexpected pointer misalignment" },
+{ 701247704, "dacl_AclEntryUuidTranslate: Warning: unexpected pointer misalignment" },
+{ 701247705, "dacl_BufferUuidTranslate: Error: unable to allocate .d bytes of buffer space" },
+{ 701247706, "dacl_ComplexList_Validate: Error: entry specifies foreign user within default realm, repairing" },
+{ 701247707, "dacl_ComplexList_Validate: Error: entry specifies foreign user within default realm, failing validation" },
+{ 701247708, "dacl_ComplexList_Validate: Error: entry specifies foreign group within default realm, repairing" },
+{ 701247709, "dacl_ComplexList_Validate: Error: entry specifies foreign group within default realm, failing validation" },
+{ 701247710, "dacl_ComplexList_Validate: Error: foreign other entry specifies default cell, no repair done" },
+{ 701247711, "dacl_ValidateBuffer: error parsing ACL buffer: .ld" },
+{ 701247712, "dacl_ValidateBuffer: error parsing ACL buffer: .s" },
+{ 701272065, "dmrpc_Init called" },
+{ 701272066, "dmrpc_Init: memory alloc failure" },
+{ 701272067, "dmrpc_Init exiting with success" },
+{ 701272068, "dmrpc_finish called" },
+{ 701272069, "dmrpc_finish: forcing detach with .d pending reads" },
+{ 701272070, "dmrpc_finish: fails with EAGAIN; .d pending reads" },
+{ 701272071, "dmrpc_finish: .d reqs allocated .d on free list" },
+{ 701272072, "dmrpc_finish: returning 0" },
+{ 701272073, "dmrpc_close: clearing .d opens" },
+{ 701272074, "dmrpc_close: returing 0" },
+{ 701272075, "dmrpc_read: starting; uiop .x" },
+{ 701272076, "dmrpc_read: done; uiop .x returning .d" },
+{ 701272077, "dmrpc_write: interrupted code .d; returning EINTR" },
+{ 701272078, "dmrpc_write: awakened with code .d" },
+{ 701272079, "dmrpc_write: starting; uiop .x" },
+{ 701272080, "dmrpc_write: dispatching type .d length .#x" },
+{ 701272081, "dmrpc_write: done; uiop .x returning .d" },
+{ 701272082, "dmrpc_ioctl: starting; cmd .#x arg .#x" },
+{ 701272083, "dmrpc_ioctl: done; cmd .#x arg .#x; returning .d" },
+{ 701272084, "dmrpc_poll: starting; events .#x" },
+{ 701272085, "dmrpc_poll: done; in evts .#x out evts .#x" },
+{ 701280257, "dfsauth_client_GrabLock entered" },
+{ 701280258, "dfsauth_client_GrabLock exiting, returning .s" },
+{ 701280259, "dfsauth_client_GrabLock exiting, returning .lu" },
+{ 701280260, "dfsauth_client_ReleaseLock entered" },
+{ 701280261, "dfsauth_client_ReleaseLock exiting, returning .s" },
+{ 701280262, "dfsauth_client_ReleaseLock exiting, returning .lu" },
+{ 701280263, "dfsauth_EstablishLocalAuthContext entered" },
+{ 701280264, "dfsauth_EstablishLocalAuthContext: about to call sec_login_setup_identity with name: `.s'" },
+{ 701280265, "dfsauth_EstablishLocalAuthContext: sec_login_setup_identity returned" },
+{ 701280266, "dfsauth_EstablishLocalAuthContext: about to call sec_login_refresh_identity with name: `.s'" },
+{ 701280267, "dfsauth_EstablishLocalAuthContext: sec_login_refresh_identity returned" },
+{ 701280268, "dfsauth_EstablishLocalAuthContext: about to call sec_login_valid_from_keytable" },
+{ 701280269, "dfsauth_EstablishLocalAuthContext: returned from sec_login_valid_from_keytable" },
+{ 701280270, "dfsauth_EstablishLocalAuthContext: about to call sec_login_set_context" },
+{ 701280271, "dfsauth_EstablishLocalAuthContext: sec_login_set_context returned" },
+{ 701280272, "dfsauth_EstablishLocalAuthContext: dfsauth_PrinName_GetBaseName reported failure: .s" },
+{ 701280273, "dfsauth_EstablishLocalAuthContext: dfsauth_PrinName_GetBaseName reported failure: .lu" },
+{ 701280274, "dfsauth_EstablishLocalAuthContext: attempt to setup local auth, not from root" },
+{ 701280275, "dfsauth_EstablishLocalAuthContext exiting, returning .s" },
+{ 701280276, "dfsauth_EstablishLocalAuthContext exiting, returning .lu" },
+{ 701280277, "AutoRefreshThread: TGT will expire at .d" },
+{ 701280278, "AutoRefreshThread: Refreshing TGT" },
+{ 701280279, "dfsauth_client_InitAuthContext entered" },
+{ 701280280, "dfsauth_client_InitAuthContext exiting, returning .s" },
+{ 701280281, "dfsauth_client_InitAuthContext exiting, returning .lu" },
+{ 701280282, "dfsauth_client_InitBindingAuth entered" },
+{ 701280283, "dfsauth_client_InitBindingAuth: about to call rpc_binding_inq_auth_info" },
+{ 701280284, "dfsauth_client_InitBindingAuth: about to call rpc_binding_set_auth_info, authn svc = .s, principal name: .s" },
+{ 701280285, "dfsauth_client_InitBindingAuth: rpc_binding_set_auth_info returned" },
+{ 701280286, "dfsauth_client_InitBindingAuth: PrinName_GetName reported failure: .s" },
+{ 701280287, "dfsauth_client_InitBindingAuth: PrinName_GetName reported failure: .lu" },
+{ 701280288, "dfsauth_client_InitBindingAuth exiting, returning .s" },
+{ 701280289, "dfsauth_client_InitBindingAuth exiting, returning .lu" },
+{ 701280290, "dfsauth_client_InitAuthentication entered" },
+{ 701280291, "dfsauth_client_InitAuthentication: serverLocationP: .s, useNoAuth? .s, useLocalAuth? .s" },
+{ 701280292, "dfsauth_client_InitAuthentication: about to call rpc_binding_set_auth_info, authn svc = .s, principal name: .s" },
+{ 701280293, "dfsauth_client_InitAuthentication: rpc_binding_set_auth_info returned" },
+{ 701280294, "dfsauth_client_InitAuthentication: PrinName_GetName reported failure: .s" },
+{ 701280295, "dfsauth_client_InitAuthentication: PrinName_GetName reported failure: .lu" },
+{ 701280296, "dfsauth_client_InitAuthentication exiting, returning .s" },
+{ 701280297, "dfsauth_client_InitAuthentication exiting, returning .lu" },
+{ 701280298, "dfsauth_client_InitNullAuthentication entered" },
+{ 701280299, "dfsauth_client_InitNullAuthentication: serverLocationP: .s, useNoAuth? .s, useLocalAuth? .s" },
+{ 701280300, "dfsauth_client_InitNullAuthentication: about to call rpc_mgmt_inq_server_princ_name" },
+{ 701280301, "dfsauth_client_InitNullAuthentication: returned from call to rpc_mgmt_inq_server_princ_name" },
+{ 701280302, "dfsauth_client_InitNullAuthentication: rpc_mgmt_inq_server_princ_name returned error .s" },
+{ 701280303, "dfsauth_client_InitNullAuthentication: about to call rpc_binding_set_auth_info, authn svc = .s, principal name: .s" },
+{ 701280304, "dfsauth_client_InitNullAuthentication: rpc_binding_set_auth_info returned" },
+{ 701280305, "dfsauth_client_InitNullAuthentication: PrinName_GetName reported failure: .s" },
+{ 701280306, "dfsauth_client_InitNullAuthentication: PrinName_GetName reported failure: .lu" },
+{ 701280307, "dfsauth_client_InitNullAuthentication exiting, returning .s" },
+{ 701280308, "dfsauth_client_InitNullAuthentication exiting, returning .lu" },
+{ 701280309, "dfsauth_client_SetFullEncryption entered" },
+{ 701280310, "dfsauth_client_SetFullEncryption exiting, returning .s" },
+{ 701280311, "dfsauth_client_SetFullEncryption exiting, returning .lu" },
+{ 701280312, "dfsauth_client_ResetDefaultEncryption entered" },
+{ 701280313, "dfsauth_client_ResetDefaultEncryption exiting, returning .s" },
+{ 701280314, "dfsauth_client_ResetDefaultEncryption exiting, returning .lu" },
+{ 701280315, "dfsauth_client_CleanupAuthentication entered" },
+{ 701280316, "dfsauth_client_CleanupAuthentication exiting, returning .s" },
+{ 701280317, "dfsauth_client_CleanupAuthentication exiting, returning .lu" },
+{ 701280318, "dfsauth_EstablishLocalAuthContext: sec_login_valid_from_keytable raised an exception; see stdout" },
+{ 701280319, "dfsauth_EstablishLocalAuthContext: unexpected authorization error returned from sec_login_valid_from_keytable" },
+{ 701280320, "dfsauth_EstablishLocalAuthContext: error from sec_login_valid_from_keytable for principal .s: .s" },
+{ 701280321, "dfsauth_EstablishLocalAuthContext: sec_login_purge_context error: .s" },
+{ 701280322, "dfsauth_EstablishLocalAuthContext: sec_login_set_context raised an exception; see stdout" },
+{ 701280323, "dfsauth_EstablishLocalAuthContext: sec_login_set_context error: .s" },
+{ 701280324, "dfsauth_client_InitBindingAuth: rpc_binding_set_auth_info raised an exception; see stdout" },
+{ 701280325, "dfsauth_client_InitBindingAuth: rpc_binding_set_auth_info error: .s" },
+{ 701280326, "dfsauth_client_InitBindingAuth: rpc_binding_inq_auth_info raised an exception; see stdout" },
+{ 701280327, "dfsauth_client_InitBindingAuth: rpc_binding_inq_auth_info error: .s" },
+{ 701280328, "dfsauth_client_InitAuthentication: rpc_binding_set_auth_info raised an exception; see stdout" },
+{ 701280329, "dfsauth_client_InitAuthentication: rpc_binding_set_auth_info error: .s" },
+{ 701280330, "dfsauth_client_InitNullAuthentication: rpc_binding_set_auth_info raised an exception; see stdout" },
+{ 701280331, "dfsauth_client_InitNullAuthentication: rpc_binding_set_auth_info error: .s" },
+{ 701280332, "dfsauth_client_SetFullEncryption: rpc_binding_set_auth_info raised an exception; see stdout" },
+{ 701280333, "dfsauth_client_SetFullEncryption: rpc_binding_set_auth_info error: .s" },
+{ 701280334, "dfsauth_client_SetFullEncryption: rpc_binding_set_auth_info raised an exception; see stdout" },
+{ 701280335, "dfsauth_client_SetFullEncryption: rpc_binding_set_auth_info error: .s" },
+{ 701280336, "dfsauth_client_SetFullEncryption: rpc_binding_inq_auth_info raised an exception; see stdout" },
+{ 701280337, "dfsauth_client_SetFullEncryption: Error: authentication info required for full encryption: (no noauth)" },
+{ 701280338, "dfsauth_client_SetFullEncryption: rpc_binding_inq_auth_info error: .s" },
+{ 701280339, "dfsauth_client_ResetDefaultEncryption: rpc_binding_set_auth_info raised an exception; see stdout" },
+{ 701280340, "dfsauth_client_ResetDefaultEncryption: rpc_binding_set_auth_info error: .s" },
+{ 701280341, "dfsauth_client_ResetDefaultEncryption: rpc_binding_inq_auth_info raised an exception; see stdout" },
+{ 701280342, "dfsauth_client_ResetDefaultEncryption: rpc_binding_inq_auth_info error: .s" },
+{ 701280343, "dfsauth_client_CleanupAuthentication: sec_login_purge_context raised an exception; see stdout" },
+{ 701280344, "dfsauth_client_CleanupAuthentication: sec_login_purge_context error: .s" },
+{ 701280345, ".s: Error: required pointer parameter, .s, has NULL value" },
+{ 701280346, "dfsauth_InitKeytab: keyfile name `.s' too long; using `foobar' instead" },
+{ 701280347, "dfsauth_InitKeytab: error getting default keytab name" },
+{ 701280348, "dfsauth_InitKeytab: error resolving keytab name" },
+{ 701280349, "dfsauth_InitKeytab: error registering ops: .s" },
+{ 701280350, "dfsauth_InitKeytab: error registering ops: .lu" },
+{ 701280351, "dfsauth_Keytab_AddKey: error converting principal name to salt" },
+{ 701280352, "dfsauth_PassKey_Add: entered: principal name: .s, kvno: .d" },
+{ 701280353, "dfsauth_PassKey_Add: error adding password: .s" },
+{ 701280354, "dfsauth_PassKey_Add: error adding password: .lu" },
+{ 701280355, "dfsauth_PassKey_Add: error adding key: .s" },
+{ 701280356, "dfsauth_PassKey_Add: error adding key: .lu" },
+{ 701280357, "dfsauth_PassKey_Add: error initializing key table: .s" },
+{ 701280358, "dfsauth_PassKey_Add: error initializing key table: .lu" },
+{ 701280359, "dfsauth_PassKey_Add: error getting principal name: .s" },
+{ 701280360, "dfsauth_PassKey_Add: error getting principal name: .lu" },
+{ 701280361, "dfsauth_PassKey_Add: exiting, returning .s" },
+{ 701280362, "dfsauth_PassKey_Add: exiting, returning .lu" },
+{ 701280363, "dfsauth_PassKey_Remove: entered: principal name: .s, kvno: .d" },
+{ 701280364, "dfsauth_PassKey_Remove: error removing password: .s" },
+{ 701280365, "dfsauth_PassKey_Remove: error removing password: .lu" },
+{ 701280366, "dfsauth_PassKey_Remove: error removing key: .s" },
+{ 701280367, "dfsauth_PassKey_Remove: error removing key: .lu" },
+{ 701280368, "dfsauth_PassKey_Remove: error initializing key table: .s" },
+{ 701280369, "dfsauth_PassKey_Remove: error initializing key table: .lu" },
+{ 701280370, "dfsauth_PassKey_Remove: error getting principal name: .s" },
+{ 701280371, "dfsauth_PassKey_Remove: error getting principal name: .lu" },
+{ 701280372, "dfsauth_PassKey_Remove: exiting, returning .s" },
+{ 701280373, "dfsauth_PassKey_Remove: exiting, returning .lu" },
+{ 701280374, "dfsauth_PassKey_Change: entered: principal name: .s, kvno: .d" },
+{ 701280375, "dfsauth_PassKey_Change: error changing password: .s" },
+{ 701280376, "dfsauth_PassKey_Change: error changing password: .lu" },
+{ 701280377, "dfsauth_PassKey_Change: error changing key: .s" },
+{ 701280378, "dfsauth_PassKey_Change: error changing key: .lu" },
+{ 701280379, "dfsauth_PassKey_Change: error initializing key table: .s" },
+{ 701280380, "dfsauth_PassKey_Change: error initializing key table: .lu" },
+{ 701280381, "dfsauth_PassKey_Change: error getting principal name: .s" },
+{ 701280382, "dfsauth_PassKey_Change: error getting principal name: .lu" },
+{ 701280383, "dfsauth_PassKey_Change: exiting, returning .s" },
+{ 701280384, "dfsauth_PassKey_Change: exiting, returning .lu" },
+{ 701280385, "dfsauth_KeyTab_GetLocalKrb5Key entered" },
+{ 701280386, "dfsauth_KeyTab_GetLocalKrb5Key: about to call sec_key_mgmt_get_key" },
+{ 701280387, "dfsauth_KeyTab_GetLocalKrb5Key: returned from sec_key_mgmt_get_key" },
+{ 701280388, "dfsauth_KeyTab_GetLocalKrb5Key: sec_key_mgmt_free_key returned error: .s" },
+{ 701280389, "dfsauth_KeyTab_GetLocalKrb5Key: sec_key_mgmt_get_key returned wrong key type: .u" },
+{ 701280390, "dfsauth_KeyTab_GetLocalKrb5Key: sec_key_mgmt_get_key returned error: .s" },
+{ 701280391, "dfsauth_KeyTab_GetLocalKrb5Key exiting, returning .#x" },
+{ 701280392, "dfsauth_Keytab_GetLocalPasswdKey entered" },
+{ 701280393, "dfsauth_Keytab_GetLocalPasswdKey exiting, returning .#x" },
+{ 701280394, "dfsauth_Keytab_GetLocalKey entered" },
+{ 701280395, "dfsauth_Keytab_GetLocalKey exiting, returning .#x" },
+{ 701280396, "dfsauth_PrinName_MakePrincipalName entered, base name is: .s" },
+{ 701280397, "dfsauth_PrinName_MakePrincipalName: buffer too small, need at least .d characters; have .d characters" },
+{ 701280398, "dfsauth_PrinName_MakePrincipalName exiting, returning .d, constructed name is: .s" },
+{ 701280399, "dfsauth_PrinName_GetName entered" },
+{ 701280400, "dfsauth_PrinName_GetName: basename is .s, adding suffix? .s" },
+{ 701280401, "dfsauth_PrinName_GetName exiting, returning principal .s, value .#x" },
+{ 701280402, "dfsauth_pathnames_GrabLock entered" },
+{ 701280403, "dfsauth_pathnames_GrabLock exiting, returning .s" },
+{ 701280404, "dfsauth_pathnames_GrabLock exiting, returning .lu" },
+{ 701280405, "dfsauth_pathnames_ReleaseLock entered" },
+{ 701280406, "dfsauth_pathnames_ReleaseLock exiting, returning .s" },
+{ 701280407, "dfsauth_pathnames_ReleaseLock exiting, returning .lu" },
+{ 701280408, "dfsauth_InitPathnames: entered" },
+{ 701280409, "dfsauth_InitPathnames exiting, returning .s" },
+{ 701280410, "dfsauth_InitPathnames exiting, returning .lu" },
+{ 701280411, "dfsauth_server_SetNoAuthStatus: entered" },
+{ 701280412, "dfsauth_server_SetNoAuthStatus exiting, returning .s" },
+{ 701280413, "dfsauth_server_SetNoAuthStatus exiting, returning .lu" },
+{ 701280414, "dfsauth_server_GetNoAuthStatus: entered" },
+{ 701280415, "dfsauth_server_GetNoAuthStatus exiting, returning .s" },
+{ 701280416, "dfsauth_server_GetNoAuthStatus exiting, returning .lu" },
+{ 701280417, "dfsauth_GenerateAdminListPath: entered" },
+{ 701280418, "dfsauth_GenerateAdminListPath exiting, returning .s" },
+{ 701280419, "dfsauth_GenerateAdminListPath exiting, returning .lu" },
+{ 701280420, "dfsauth_InitPathnames: Error: unable to get base directory environment variable" },
+{ 701280421, ".s: .s: .s of NoAuth file, .s . . ." },
+{ 701280422, ", returned error: .s" },
+{ 701280423, "dfsauth_get_local_host_uuid entered" },
+{ 701280424, "dfsauth_get_local_host_uuid: unable to get local principal name: .s" },
+{ 701280425, "dfsauth_get_local_host_uuid exiting, returning .s" },
+{ 701280426, "dfsauth_rpc_mgmt_authz_check entered" },
+{ 701280427, "dfsauth_rpc_mgmt_authz_check: requested operation is .s" },
+{ 701280428, "dfsauth_rpc_mgmt_authz_check: requested operation is .s" },
+{ 701280429, "dfsauth_rpc_mgmt_authz_check: requested operation is .s" },
+{ 701280430, "dfsauth_rpc_mgmt_authz_check: requested operation is .s" },
+{ 701280431, "dfsauth_rpc_mgmt_authz_check: requested operation is .s" },
+{ 701280432, "dfsauth_rpc_mgmt_authz_check: found name authzn; name = .s" },
+{ 701280433, "dfsauth_rpc_mgmt_authz_check: binding has no auth info, checking noauth" },
+{ 701280434, "dfsauth_rpc_mgmt_authz_check: rpc_binding_inq_auth_client error: .s" },
+{ 701280435, "dfsauth_rpc_mgmt_authz_check: Error: unable to get client principal uuid" },
+{ 701280436, "dfsauth_rpc_mgmt_authz_check: Error: unable to get local host principal uuid: .s" },
+{ 701280437, "dfsauth_rpc_mgmt_authz_check exiting, returning .s" },
+{ 701280438, "dfsauth_get_local_host_uuid: rpc_binding_inq_auth_client raised an exception; see stdout" },
+{ 701280439, "dfsauth_get_local_host_uuid: unable to get local principal uuid: .s" },
+{ 701280440, "dfsauth_rpc_mgmt_authz_check: rpc_binding_inq_auth_client raised an exception; see stdout" },
+{ 701280441, "dfsauth_sec_key_mgmt_free_key: unexpected error freeing key data storage: .s" },
+{ 701280442, "dfsauth_sec_key_mgmt_keyinfo: Warning: real checksum length (.d) != dfsauth checksum length (.d)" },
+{ 701280443, "dfsauth_sec_key_mgmt_keyinfo: sec_rgy_acct_lookup error checking account change date: .s" },
+{ 701280444, "dfsauth_sec_key_mgmt_keyinfo: sec_id_parse_name error: .s" },
+{ 701280445, "dfsauth_server_GrabLock entered" },
+{ 701280446, "dfsauth_server_GrabLock exiting, returning .s" },
+{ 701280447, "dfsauth_server_GrabLock exiting, returning .lu" },
+{ 701280448, "dfsauth_server_ReleaseLock entered" },
+{ 701280449, "dfsauth_server_ReleaseLock exiting, returning .s" },
+{ 701280450, "dfsauth_server_ReleaseLock exiting, returning .lu" },
+{ 701280451, "dfsauth_CheckServerNoAuth: server is checking noauth status" },
+{ 701280452, "dfsauth_CheckServerNoAuth: server is assuming noauth mode" },
+{ 701280453, "dfsauth_CheckServerNoAuth: server is.s running in noauth mode" },
+{ 701280454, "dfsauth_server_InitAuth: about to call .s with principal name .s" },
+{ 701280455, "dfsauth_server_InitAuth: returned from .s" },
+{ 701280456, "dfsauth_server_InitAuth: dfsauth_PrinName_GetName returned error: .lu" },
+{ 701280457, "dfsauth_server_InitAuth: dfsauth_PrinName_GetName returned error: .s" },
+{ 701280458, "dfsauth_server_CheckAuthorizationAclOptional: entered" },
+{ 701280459, "dfsauth_server_CheckAuthorizationAclOptional: server is not running no auth, will check id" },
+{ 701280460, "dfsauth_server_CheckAuthorizationAclOptional: about to call .s" },
+{ 701280461, "dfsauth_server_CheckAuthorizationAclOptional: found authn svc: .s" },
+{ 701280462, "dfsauth_server_CheckAuthorizationAclOptional: found authn level: .d" },
+{ 701280463, "dfsauth_server_CheckAuthorizationAclOptional: found authz svc: .s" },
+{ 701280464, "dfsauth_server_CheckAuthorizationAclOptional: found name authzn; name = .s" },
+{ 701280465, "dfsauth_server_CheckAuthorizationAclOptional: error reading acl from disk: .lu" },
+{ 701280466, "dfsauth_server_CheckAuthorizationAclOptional: error reading acl from disk: .s" },
+{ 701280467, "dfsauth_server_CheckAuthorizationAclOptional: .s unrecognized authzn svc found in binding: .#x" },
+{ 701280468, "dfsauth_server_CheckAuthorizationAclOptional: binding has no auth info, checking noauth" },
+{ 701280469, "dfsauth_server_CheckAuthorizationAclOptional: .s error: .s" },
+{ 701280470, "dfsauth_server_CheckAuthorizationAclOptional: exiting, returning .d" },
+{ 701280471, "dfsauth_server_InitAuth: sec_id_parse_name raised an exception; see stdout" },
+{ 701280472, "dfsauth_server_InitAuth: unable to parse global name: .s (.s)" },
+{ 701280473, "dfsauth_server_InitAuth: unable to bind to a registry site: .s (.s)" },
+{ 701280474, "dfsauth_server_InitAuth: rpc_server_register_auth_info raised an exception; see stdout" },
+{ 701280475, "dfsauth_server_InitAuth: unable to register authn info: .s" },
+{ 701280476, "dfsauth_server_CheckAuthorizationAclOptional: rpc_binding_inq_auth_client raised an exception; see stdout" },
+{ 701280477, "dfsauth_server_CheckAdminListAccessBegin: entered" },
+{ 701280478, "dfsauth_server_CheckAdminListAccessBegin: returns .x" },
+{ 701280479, "dfsauth_server_CheckAdminListAccessNext: entered" },
+{ 701280480, "dfsauth_server_CheckAdminListAccessNext: returns .x" },
+{ 701280481, "AutoRefreshThread: exiting since dfsauth_client_initialized is turned off" },
+{ 701280482, "AutoRefreshThread: exiting since can't get expiration time: .d" },
+{ 701280483, "dfsauth_server_GetClientIdentity: entered (.#x, .#x, .#x)" },
+{ 701280484, "dfsauth_server_GetClientIdentity: returns .x (st=.x)" },
+{ 701280485, "... authn level = .d" },
+{ 701366273, "epia_Strategy(bp=.#x): zero length xfer because new file length is .#x" },
+{ 701366274, "BufRead: anode .#x bp .#x offset .#x length .#x" },
+{ 701366275, "BufWrite anode .#x bp .#x offset .#x length .#x" },
+{ 701366276, "epia_Strategy(bp=.#x): epia_Read anode .#x offset .#x length .#x" },
+{ 701366278, "BufRead(h=.#x): QIO bp .#x disk block .#x length .#x" },
+{ 701366279, "BufWrite(h=.#x): QIO bp .#x disk block .#x length .#x" },
+{ 701366280, "bp .#x: pagelist .#x .d page(s)" },
+{ 701366281, "pages: .#x .#x .#x .#x" },
+{ 701366282, "osi_bio_clean(bp=.#x): flags = .#x" },
+{ 701366283, "NotifyAndUnmapBufs(bp=.#x code=.#x unmap = .d" },
+{ 701366284, "pvn_read_done: bp .#x pages .#x flags .#x" },
+{ 701366285, "pvn_write_done: bp .#x pages .#x flags .#x" },
+{ 701366286, "anode layer converted error .lu to error .lu in file .s at line .d" },
+{ 701366287, "epif_Open: vol .#x, fid index .lu, epiv index .lu, epiv_OpenAnode failed, code .lu" },
+{ 701366288, "epif_Open: vol .#x, fid .lu..lu, GetHandle failed, code .lu" },
+{ 701366289, "queue_sick_vnode: vp .#x bp .#x block .#llx length .#x" },
+{ 701366290, "release_sick_vnode: vp .#x" },
+{ 701366291, "read thread .#x waiting for busy disk block .d dev .d .d" },
+{ 701366292, "write thread .#x waiting for busy disk block .d dev .d .d" },
+{ 701366293, "epif_ChangeLink anode .#x link delta .d delete .d (suspect) current link count .d" },
+{ 701366294, "epix_CheckBlockAllocation off .#llx emptyblks .#llx ibAddr .#lx outLen .#llx" },
+{ 701366295, "epix_CheckBlockAllocation off .#llx ibAddr .d highest ix .d start ix .d" },
+{ 701366296, "epix_CheckBlockAllocation multiplies by .#x to get .#llx" },
+{ 701366297, "epix_CheckBlockAllocation diff .llx bigger than MAX_OSI_OFF_T/(span .#x) so we use MAX_OSI_OFF_T" },
+{ 701366298, "epix_CheckBlockAllocation MIN with btoab(maxoff) to get .#llx result in bytes is .#llx" },
+{ 701411329, "WaitForTran(.d): to complete from state .#x" },
+{ 701411330, "WaitForTran(.d): wakeup in state .#x" },
+{ 701411331, "WaitForTran(.d): start GCtran" },
+{ 701411332, "WaitForTran(.d): end GCtran" },
+{ 701411333, "WaitForTran(.d): start wait for any" },
+{ 701411334, "WaitForTran(.d): end wait for any" },
+{ 701411335, "CompleteEC: ecSize is .d" },
+{ 701411336, "elbl_StartTran: logfull; .d running active size data/tran=.d/.d" },
+{ 701411337, "AllocBuffer: found no clean buffers in .dK pool" },
+{ 701452289, "lfswrite V .x F .x..x..x..x O .d L .d" },
+{ 701452290, "lfswriteZeros V .x F .x..x..x..x O .d L .d" },
+{ 701452291, "lfspgout FID .x..x..x..x FL .d FO .d NP .d" },
+{ 701452292, " diskw FID .x..x..x..x FO .d WL .d DB .d" },
+{ 701452293, " diskwZeros FID .x..x..x..x FO .d WL .d DB .d" },
+{ 701452294, "vnva_GetAttr: evp .#x ap .#x extended .d" },
+{ 701452295, "vnva_GetAttr end: md .#x perms .#x anonperms .#x" },
+{ 701452296, "vnax_GetAnonAccess: aclLen .#x perms .#x" },
+{ 701452297, "vnax_GetAccess: pacListP .#x aclP .#x perms .#x code .d" },
+{ 701452298, "vnax_GetAccess: pacListP .#x perms .#x" },
+{ 701452299, "vnax_GetAccess: code .d, .x" },
+{ 701452300, ".s" },
+{ 701452301, "vol_efsOpen: vid .lu has no last index: code .lu" },
+{ 701452302, "vol_efsTwiddleInconBit: vid .lu, turnon=.lu" },
+{ 701452303, "vol_efsTwiddleInconBit: vid .lu, returning .lu" },
+{ 701452304, "vol_efsClose: vid .lu, isabort .lu, returning .lu" },
+{ 701452305, "vol_efsDeplete: vid .lu; beginning init pass" },
+{ 701452306, "vol_efsDeplete: vid .lu; ending init pass" },
+{ 701452307, "vol_efsAttach: attaching vid .lu" },
+{ 701452308, "vol_efsDetach: detaching vid .lu" },
+{ 701452309, "vol_efsDetach: vid .lu: count .lu != (.lu + 1), so failing" },
+{ 701452310, "vol_efsDetach: vid .lu: InUse code .lu, so failing" },
+{ 701452311, "vol_efsDetach: vid .lu: succeeding" },
+{ 701452312, "vol_efsClone: vids .lu and .lu; beginning init pass" },
+{ 701452313, "vol_efsClone: vids .lu and .lu; ending init pass" },
+{ 701452314, "efsSomeClone, reclone=.ld: vids .lu and .lu; beginning init pass" },
+{ 701452315, "efsSomeClone, reclone=.ld: vids .lu and .lu; ending init pass" },
+{ 701452316, "vnm_StopUse: vid .lu; flags=.lu; .lu vnodes to scan" },
+{ 701452317, "vnm_StopUse: vid .lu; evp .#lx (#.ld) flags .#lx: sleeping for WAITFORME" },
+{ 701452318, "vnm_StopUse: vid .lu; evp .#lx (#.ld) flags .#lx: shutting down" },
+{ 701452319, "vnm_StopUse: vid .lu; finished" },
+{ 701452320, "vnm_FindVnode: sleeping for .#lx: flags .#lx" },
+{ 701452321, "vnm_Inuse: sleeping for .#lx: flags .#lx" },
+{ 701452322, "efs_reclaim: sleeping for .#lx: flags .#lx" },
+{ 701452323, "vnm_StopUse: back from calling vnm_SyncVnodes()" },
+{ 701452324, "efs_PageInDaemon: bp .#x blkno .#x bcount .#x flags .#x" },
+{ 701452325, "efs_PageinDaemon: calling efs_pagein(.#x) (vp .#x)" },
+{ 701452326, "efs_PageinDaemon: bp .#x finished" },
+{ 701452327, "efs_PageOutDaemon: bp .#x blkno .#x bcount .#x flags .#x" },
+{ 701452328, "efs_PageOutDaemon: calling efs_PageOut(.#x) (vp .#x)" },
+{ 701452329, "efs_PageOutDaemon: bp .#x finished" },
+{ 701452330, "PageUnprotectDaemon: bp .#x blkno .#x bcount .#x flags .#x" },
+{ 701452331, "PageUnprotectDaemon: calling efs_PageUnprotect(.#x) (vp .#x)" },
+{ 701452332, "PageUnprotectDaemon: bp .#x finished" },
+{ 701452333, "vol_efsScan: in vid .lu epif_GetStatus fails on fid.index .lu with code .lu" },
+{ 701452334, "vnode layer converted error .lu to error .lu in file .s at line .d" },
+{ 701452335, ".s: evp .#x fid .lu vnva_GetAttr failed with code .lu" },
+{ 701452336, "efs_lookup: name .s in non-dir object devp .#x, fid .lu fails, code .lu" },
+{ 701452337, "efs_lookup: name .s in unlinked dir devp .#x fid .lu fails, code .lu" },
+{ 701452338, "vnax_CanAccess: devp .#x fid .lu, epif_GetStatus returns .lu" },
+{ 701452339, "efs_lookup: name .s in devp .#x fid .lu, vnax_CanAccess fails code .lu" },
+{ 701452340, "efs_create: name .s in devp .#x fid .lu, failed code .d" },
+{ 701452341, "efs_create: name .s in devp .#x fid .lu, succeeded evp .#x" },
+{ 701452342, "vnva_GetAttr: evp .#x ap .#x fid.index .lu epif_GetStatus fails with code .lu" },
+{ 701452343, "EV_DEPHANTOM: evp .#x is stale" },
+{ 701452344, "vol_efsDetach: vid .lu: count .lu; had already been detached or destroyed" },
+{ 701452345, "ReleVnVol(.#x): releasing vnode .#x" },
+{ 701452346, "VFtoEV, vid .d: saving vn in voldata .#x: replacing .#x with .#x" },
+{ 701452347, "efs_CopyAcl, vid .d: saving vn in voldata .#x: replacing .#x with .#x" },
+{ 701452348, "vnm_VnodeBusy: evp .#x, flags .#lx" },
+{ 701452349, "vnm_VnodeNotBusy: evp .#x, flags .#lx" },
+{ 701452350, "vnm_VnodeNotBusy: waking evp .#x" },
+{ 701452351, "vnm_VnodeNotBusy: wakeup any with evp .#x" },
+{ 701452352, "vnm_WaitForBusyVnode: evp .#x, lock .#x" },
+{ 701452353, "vnm_WaitForAnyBusyVnode: lock .#x" },
+{ 701452354, "efs_unmount: vol .#x, epig_CloseVolume failed, code .#x" },
+{ 701452355, "efs_unmount: aggr .#x, epig_CloseAggregate failed, code .#x" },
+{ 701452356, "efs_unmount: vfsp .#x, vol .#x, avl .#x starting" },
+{ 701452357, "efs_unmount: vfsp .#x, vol .#x, avl .#x completed" },
+{ 701452358, "efs_unmount: vfsp .#x got .#x from vnm_Inuse, returning EBUSY" },
+{ 701452359, "efs_unmount: success of forced unmount of vfsp .#x inspite of code .#x from vnm_Inuse" },
+{ 701452360, "vnm_Inuse: busy vnode .#x, index .#x, ref count .d, state .#x" },
+{ 701452361, "vol_efsSetAcl: unauthenticated entry from .s acl for fid .#x..#x, volume id .#x..#x was removed" },
+{ 701452362, "ValidateRename: trouble obtaining locks on src .s, targ .s after .d loops" },
+{ 701452363, "efs_vmread .#x off .lld len .ld" },
+{ 701452364, "efs_vmwrite .#x off .lld len .ld" },
+{ 701452365, "efs_getpage .#x off .#llx len .#x rw .#x" },
+{ 701452366, "efs_getpage failed code .d" },
+{ 701452367, "efs_getpage returns .d pages (prot = .#x)" },
+{ 701452368, "efs_putpage .#x off .#llx len .#x flags .#x" },
+{ 701452369, "efs_putapage .#x off .#llx flags .#x" },
+{ 701452370, "efs_GetContents .#x off .lld len .ld rblk .#x" },
+{ 701452371, "putcontents" },
+{ 701452372, "create dirty zero pages for .#x .#llx -> .#llx" },
+{ 701452373, "zero to end of page vp .#x off .lld" },
+{ 701452374, "CreateBlock vp .#x off .lld len .lld first block .#x" },
+{ 701452375, "CreateBlock fails with code .d" },
+{ 701452376, "CopyBlock vp .#x off .lld remaining .d rblk .#x" },
+{ 701452377, "CopyBlock fails with code .d" },
+{ 701452378, "efs_HoldContents .#x off .lld len .d" },
+{ 701452379, "efs_ZeroBytes vp .#x dblk .#x len .d" },
+{ 701452380, "vol_efsDeplete: vid .lu; done with code .d" },
+{ 701452381, "vol_efsGetStatus: vid .lu, VV .d" },
+{ 701452382, "vol_efsGetStatus with code .d gets new vid .lu, states .#x VV .d" },
+{ 701452383, "vol_efsScan in vid .d to position .d" },
+{ 701452384, "vol_efsScan in vid .d past EOF to position .d" },
+{ 701452385, "vol_efsScan in vid .d at position .d to a deleted file" },
+{ 701452386, "vol_efsCreate in vid .d at position .d" },
+{ 701452387, "vol_efsCreate: file exists, new unique .d, old unique .d" },
+{ 701452388, "vol_efsCreate(vid .d, position .d) failed with code .d" },
+{ 701452389, "vol_efsCreate(vid .d, position .d) succeeded" },
+{ 701452390, "vol_efsAppenddir, vid .d, dir .d, entries .d, preserve .d" },
+{ 701452391, "vol_efsAppenddir: entry .s, vnum .d, off .d, pieces .d" },
+{ 701452392, "vol_efsAppenddir(vid .d, dir .d) failed with code .d" },
+{ 701452393, "vol_efsAppenddir(vid .d, dir .d) succeeded" },
+{ 701452394, "vol_efsTruncate(vid .d, vnum .d, newsz .lld) failed with code .d" },
+{ 701452395, "vol_efsTruncate(vid .d, vnum .d, newsz .lld) succeeded" },
+{ 701452396, "vol_efsDelete in vid .d the fid .#x..#x, code .d" },
+{ 701452397, "vol_efsGetAttr with code .d sees linkCount .d, VV .d" },
+{ 701452398, "vol_efsSetAttr with code .d sees linkCount .d, VV .d" },
+{ 701452399, "efs_rename of .#x/.s to .#x/.s failed" },
+{ 701452400, "efs_rename code .d" },
+{ 701452401, "vol_efsRead evp .#x, off .lld, len .d, fileLen .lld" },
+{ 701452402, "vol_efsWrite evp .#x, off .lld, len .lld, fileLen .lld" },
+{ 701452403, "vol_efsReadHole volp .#x, fid .x..x..x..x, off .lu,,.lu, len .d" },
+{ 701452404, "vol_efsReadHole error from VFtoEV, volp .#x, fid .x..x..x..x, code .d" },
+{ 701452405, "vol_efsReadHole on vdev file, volp .#x, fid .x..x..x..x, code .d" },
+{ 701452406, "vol_efsReadHole past file EOF, evp .#x, filelen .lld, offset .#lld, code .d" },
+{ 701452407, "vol_efsReadHole error from vol_efsBioWait/copyout, evp .#x, code .d" },
+{ 701452408, "vol_efsReadHole error from osi_ZeroUData uaddr .#x, zero len .#llx, code .d" },
+{ 701452409, "efs_setup_ra evp .#x, raOff .#llx, reason .d" },
+{ 701452410, "efs_setup_ra evp.#x, raOff .#llx, rLen .#llx, raLen .#x" },
+{ 701452411, "efs_do_ra evp .#x, off .#llx, len .#x" },
+{ 701452412, "efs_getpage_io evp 0x.x, off 0x.llx, rLen 0x.x, delta 0x.x" },
+{ 701452413, "efsx_getacl: non delegation aware client requested evp .#x, .d type acl with delegate entries, code .d" },
+{ 701452414, "vnax_GetAccess unauth access on vp .#x by uid .d" },
+{ 701452415, "vnax_GetAccess foreign access on no ACL vp .#x by PAC list .#x" },
+{ 701452416, "vnd_dirLookup: found negative cache devp .#x, name .s" },
+{ 701452417, "vnd_dirLookup: found positive cache devp .#x, name .s, fid .#x..#x" },
+{ 701452418, "vnd_dirLookup: dir_Lookup devp .#x, name .s failed with code .d" },
+{ 701452419, "vnd_dirLookup: enter negative cache devp .#x, name .s" },
+{ 701452420, "vnd_dirLookup: enter positive cache devp .#x, name .s, fid .#x..#x" },
+{ 701452421, "vnd_dirCheck: found negative cache devp .#x, name .s. Invalidate cache" },
+{ 701452422, "vnd_dirCheck: found positive cache devp .#x, name .s, fid .#x..#x. Invalidate cache" },
+{ 701452423, "vnd_Rename: invalidate dir cache for so vp .#x" },
+{ 701452424, "vnd_Rename: invalidate sd vp .#x, sname .s, td vp .#x, tname .s" },
+{ 701452425, "Episode: OpenVnode vol id (low word) .#x, fid index .#x, evp .#x, code .d" },
+{ 701452426, "Episode: Recycle vnode .#x, vol id (low word) .#x, fid .#x..#x" },
+{ 701452427, "vol_efsDetach: detaching vid .lu, anyForce .#x" },
+{ 701452428, "vnva_SetAttr invalidating access cache for vp .#x" },
+{ 701452429, "vnva_SetAcl invalidating access cache for vp .#x" },
+{ 701452430, "Episode: KillCacheStatus invalidating access cache for vp .#x" },
+{ 701452431, "Episode: ReinitVnode invalidating access cache for vp .#x" },
+{ 701452432, "vnax_CanAccess: access cache hit, evp .#x, uid .#x, cached .#x, desired .#x" },
+{ 701452433, "vnax_CanAccess: access cache miss, evp .#x, uid .#x, desired .#x" },
+{ 701452434, "vnax_CanAccess: access cache update, evp .#x, uid .#x, cached .#x, desired .#x" },
+{ 701452435, "vol_efsGetAttr (vid .d, pos .d) outputs info on deleted file" },
+{ 701452436, "vol_efsGetNextHoles volp .#x, fid .x..x..x..x, off .lu,,.lu" },
+{ 701452437, "vol_efsGetNextHoles error from VFtoEV, volp .#x, fid .x..x..x..x, code .d" },
+{ 701452438, "vol_efsGetNextHoles on vdev file, volp .#x, fid .x..x..x..x, code .d" },
+{ 701452439, "vol_efsGetNextHoles error from osi_ZeroUData uaddr .#x, zero len .#x, code .d" },
+{ 701452440, "vol_efsGetNextHoles error from osi_ZeroUData (at end) uaddr .#x, zero len .#x, code .d" },
+{ 701452441, "vol_efsGetNextHoles error from vol_efsBioWait/copyout, evp .#x, code .d" },
+{ 701452442, "vol_efsGetNextHoles: range [.#llx .. .#llx) becomes [.#llx .. .#llx)" },
+{ 701452443, "vnm_Truncate evp .#x, len .lld, flags .#x" },
+{ 701452444, "vnm_Truncate failed evp .#x, len .lld, flags .#x, code .d" },
+{ 701452445, "vnm_Truncate passed evp .#x, len .lld, flags .#x" },
+{ 701452446, "efs_vmread .#x off .lld len .ld, result .d" },
+{ 701452447, "efs_vmwrite ends .#x off .lld resid .d, result .d" },
+{ 701452448, "efsx_punch evp .#x, flags .#x, off .#x,.#x, len .#x,.#x" },
+{ 701452449, "efsx_punch finished evp .#x, code .d" },
+{ 701452450, "efsx_readinvis vp .#x, off .#x,.#x, len .#x,.#x" },
+{ 701452451, "efsx_readinvis vp .#x, code .d, outlen #.x,#.x" },
+{ 701452452, "efsx_writeinvis vp .#x, off .#x,.#x, len .#x,.#x" },
+{ 701452453, "efsx_writeinvis vp .#x, code .d, outlen #.x,#.x" },
+{ 701452454, "efsx_probehole vp .#x, in offset .#x,,.#x, in length .#x,,.#x" },
+{ 701452455, "efsx_probehole vp .#x, code .d, out offset .#x,,.#x, out length .#x,,.#x" },
+{ 701452456, "vnm_StopUse: volid .#x,,.#x openbits .#x, oldopen .#x" },
+{ 701452457, "vnm_StopUse: volid .#x,,.#x processed .d vnodes" },
+{ 701452458, "vol_efsAppenddir: entry .s, vnum .d, codeset tag .d (NONZERO); failing with EINVAL" },
+{ 701452459, "efs_MWB vp .#x, off .lld, len .d, flags .#x" },
+{ 701452460, "efs_MWB vp .#x, purged region at offset .lld, alen .lld, code .d" },
+{ 701452461, "CreateBlock vp .#x, off .d, len .d, internalflags .#x" },
+{ 701452462, "efs_vmwrite vp .#x, purged region at offset .d, size .d, code .d" },
+{ 701452463, "efs_getextentinfo vp .#x, offset .#llx, nextents .d, flags .#x" },
+{ 701452464, "efs_getextentinfo vp .#x, file length .#llx" },
+{ 701452465, "efs_getextentinfo findblocks offset .#llx, dblk .#x, wLen .#x, rLen .#x" },
+{ 701452466, "efs_getextentinfo end vp .#x, offset .#llx, nextents .d, flags .#x" },
+{ 701452467, "OpenVnode: failed to open anode for fid .#x..#x with code .lu, returning ESTALE" },
+{ 701452468, "ag_efsAttach aggregate hdr disk flags .#x, attach flags .#x, code .d" },
+{ 701452469, "vol_efsPunch fid .x..x..x..x, offset .#x,,.#x, length .#x,,.#x, flags .#x" },
+{ 701452470, "vol_efsPunch code .d" },
+{ 701452471, "vol_efsGetXtdattr fid .x..x..x..x" },
+{ 701452472, "vol_efsGetXtdattr code .d" },
+{ 701452473, "vol_efsSetXtdattr fid .x..x..x..x" },
+{ 701452474, "vol_efsSetXtdattr code .d" },
+{ 701452475, "EV_DEPHANTOM (line #.d): evp .#x is stale" },
+{ 701452476, "efs_GetVolume: evp .#x is stale" },
+{ 701452477, "efs_DiscardVM vp .#x, oldLen .lld, newLen .lld, fpage .ld" },
+{ 701452478, "efs_Promote vp .#x, src .d, dest .d" },
+{ 701452479, "efs_Promote result .ld" },
+{ 701452480, "efs_PutContents vp .#x, wblk .#x, len .ld, unlock .d" },
+{ 701452481, " zlp info dblk .#x, ioOff .lld, zoff .ld, iolen .ld" },
+{ 701452482, "efs_StabilizeVM vp .#x, fpage .ld, npages .ld" },
+{ 701452483, "efs_read_strategy bp .#x, evp .#x, off .lld, flen .lld" },
+{ 701452484, "disk read off .lld len .ld dblk .#x, ioflags .#x" },
+{ 701452485, "efs_write_strategy bp .#x, evp .#x, off .lld, alen .lld" },
+{ 701452486, "disk write off .lld len .ld dblk .#x, ioflags .#x" },
+{ 701452487, "CreateBlock vp .#x, off .d, len .d" },
+{ 701452488, "CreateBlock ends vp .#x len .lld first block .#x, code .d" },
+{ 701452489, "vnva_SetAttr: evp .#x, mask .#x, markmask .#x" },
+{ 701452490, "efs_GetContentsNoVM begin evp .#x len .d rblk .d" },
+{ 701452491, "efs_GetContentsNoVM done code .d" },
+{ 701452492, "efs_PutContentsNoVM begin evp .#x len .d rblk .d" },
+{ 701452493, "efs_PutContentsNoVM done code .d" },
+{ 701452494, "efs_AsyncGetContentsNoVM begin evp .#x len .d rblk .d" },
+{ 701452495, "efs_AsyncPutContentsNoVM begin evp .#x len .d rblk .d" },
+{ 701452496, "efsx_readinvis: len = .#llx, rlen = .#llx, osize = .#llx, iolen = .#llx" },
+{ 701452497, "zlistAdd evp .#x, page .d" },
+{ 701452498, "zlistAdd FULL inlist .d" },
+{ 701452499, "zlistRelease evp .#x page .d, is reader .d" },
+{ 701452500, "disk zero failed code .d, page .d" },
+{ 701452501, "vnd_Rename: delete prefix trans .d, do/undo .d code .d" },
+{ 701452502, "vnd_Rename: create or replace error code .d" },
+{ 701452503, "vnd_Rename: fixdotdot trans .d do/undo .d code .d" },
+{ 701452504, "vnd_Rename: delete_suffix trans .d code .d" },
+{ 701575169, "flserver calling dfs_GetJunctionName for .s" },
+{ 701575170, "flserver calling dfsauth_server_InitAuthentication" },
+{ 701575171, "flserver calling ubik_ServerInit" },
+{ 701575172, "flserver calling ubik_GetServerList" },
+{ 701575173, "ubik_GetServerList returns .d servers" },
+{ 701575174, "flserver ready to service requests" },
+{ 701575175, "flserver unregistering interface" },
+{ 701575176, "vlwrite(trans=0x.x, off=.d, buf=0x.x, len=.d) entered" },
+{ 701575177, "vlwrite returns .d" },
+{ 701575178, "vlread(trans=0x.x, off=.d, buf=0x.x, len=.d) entered" },
+{ 701575179, "vlread returns .d" },
+{ 701575180, "vlentrywrite(trans=0x.x, off=.d, buf=0x.x, len=.d) entered" },
+{ 701575181, "vlentryread(trans=0x.x, off=.d, buf=0x.x, len=.d) entered" },
+{ 701575182, "vlentrywrite returns .d" },
+{ 701575183, "vlentryread returns .d" },
+{ 701575184, "write_vital_vlheader(trans=0x.x) entered" },
+{ 701575185, "write_vital_vlheader returns .d" },
+{ 701575186, "CheckInit(trans=0x.x) entered" },
+{ 701575187, "CheckInit: check for db update" },
+{ 701575188, "CheckInit: reread db" },
+{ 701575189, "CheckInit: initialize fldb header" },
+{ 701575190, "CheckInit: fldb initialization failed, errorcode=.d" },
+{ 701575191, "CheckInit returns 0" },
+{ 701575192, "AllocBlock(trans=0x.x, tentry=0x.x, errp=0x.x) entered" },
+{ 701575193, "AllocBlock failed in read, err=.d" },
+{ 701575194, "AllocBlock failed because blockindex = 0" },
+{ 701575195, "AllocBlock failed in write, err=.d" },
+{ 701575196, "AllocBlock returns blockindex .d" },
+{ 701575197, "FreeBlock(trans=0x.x, blockindex=.d) entered" },
+{ 701575198, "FreeBlock returns .d" },
+{ 701575199, "FindById(trans=0x.x, volid=.d,,.d, voltix=.d, tentry=0x.x, ...) entered" },
+{ 701575200, "FindById: hash volid to .d" },
+{ 701575201, "FindById returns blockindex .d (errorcode = .d)" },
+{ 701575202, "FindByName(trans=0x.x, volname=.s, tentry=0x.x, errp=0x.x) entered" },
+{ 701575203, "FindByName: hash volid to .d" },
+{ 701575204, "FindByName returns blockindex .d (errorcode = .d)" },
+{ 701575205, "ThreadVLentry (trans=0x.x, blockindex=.d, tentry=0x.x) entered" },
+{ 701575206, "ThreadVLentry returns .d" },
+{ 701575207, "UnthreadVLentry (trans=0x.x, blockindex=.d, aentry=0x.x) entered" },
+{ 701575208, "UnthreadVLentry returns .d" },
+{ 701575209, "HashVolid(trans=0x.x, voltix=.d, blockindex=.d, tentry=0x.x) entered" },
+{ 701575210, "HashVolid returns .d" },
+{ 701575211, "UnhashVolid(trans=0x.x, voltix=.d, blockindex=.d, aentry=0x.x) entered" },
+{ 701575212, "UnhashVolid returns .d" },
+{ 701575213, "HashVolname(trans=0x.x, blockindex=.d, aentry=0x.x) entered" },
+{ 701575214, "HashVolname returns .d" },
+{ 701575215, "UnhashVolname(trans=0x.x, blockindex=.d, aentry=0x.x) entered" },
+{ 701575216, "UnhashVolname returns .d" },
+{ 701575217, "NextEntry (trans=0x.x, blockindex=.d, tentry=0x.x, remaining=0x.x) entered" },
+{ 701575218, "NextEntry returns .d (remaining = .d)" },
+{ 701575219, "Init_VLdbase (transPP=0x.x, locktype=.d, op=.d) entered (readany=.d)" },
+{ 701575220, "InitVLdbase returns .d" },
+{ 701575221, "VL_CreateEntry(connp=0x.x, newentry=0x.x) entered" },
+{ 701575222, "VL_CreateEntry returns .d" },
+{ 701575223, "VL_DeleteEntry(connp=0x.x, volid=.d,,.d, voltype=.d) entered" },
+{ 701575224, "VL_DeleteEntry returns .d" },
+{ 701575225, "VL_GetEntryByID (connp=0x.x, volid=.d,,.d, voltype=.d, aentry=0x.x) entered" },
+{ 701575226, "VL_GetEntryByID returns .d" },
+{ 701575227, "VL_GetEntryByName (connp=0x.x, volname=.s, aentry=0x.x) entered" },
+{ 701575228, "VL_GetEntryByName returns .d" },
+{ 701575229, "VL_GetNewVolumeId (connp=0x.x, Maxvolidbump=.d, Addrp=0x.x, newvolumeid=0x.x) entered" },
+{ 701575230, "VL_GetNewVolumeId returns new volume .d,,.d" },
+{ 701575231, "VL_GetNewVolumeId returns .d" },
+{ 701575232, "VL_ReplaceEntry (connp=0x.x, volid=.d,,.d, voltype=.d, newentry=0x.x, ...) entered" },
+{ 701575233, "VL_ReplaceEntry returns .d" },
+{ 701575234, "VL_SetLock (connp=0x.x, volid=.d,,.d, voltype=.d, voloper=.d) entered" },
+{ 701575235, "VL_SetLock returns .d" },
+{ 701575236, "VL_ReleaseLock (connp=0x.x, volid=.d,,.d, voltype=.d, releasetype=.d) entered" },
+{ 701575237, "VL_ReleaseLock returns .d" },
+{ 701575238, "VL_ListEntry (connp=0x.x, prev=.d, count=0x.x, next=0x.x, ...) entered" },
+{ 701575239, "VL_ListEntry returns .d" },
+{ 701575240, "VL_ListByAttributes(connp=0x.x, attributes=0x.x, cookie=0x.x, nentries=0x.x, ...) entered" },
+{ 701575241, "VL_ListByAttributes returns .d" },
+{ 701575242, "VL_GetStats(connp=0x.x, stats=0x.x, vital_header=0x.x) entered" },
+{ 701575243, "VL_GetStats returns .d" },
+{ 701575244, "VL_AddAddress(connp=0x.x, OldAddr=0x.x, AddrToAdd=0x.x) entered" },
+{ 701575245, "VL_AddAddress returns .d" },
+{ 701575246, "VL_RemoveAddress(connp=0x.x, AddrToRemove=0x.x) entered" },
+{ 701575247, "VL_RemoveAddress returns .d" },
+{ 701575248, "VL_ChangeAddress(connp=0x.x, OldAddr=0x.x, NewAddr=0x.x) entered" },
+{ 701575249, "VL_ChangeAddress returns .d" },
+{ 701575250, "VL_GetCellInfo(connp=0x.x, MyCell=0x.x) entered" },
+{ 701575251, "VL_GetCellInfo returns .d" },
+{ 701575252, "VL_GetNextServersByID (connp=0x.x, volid=.d,,.d, voltype=.d, startHere=.d, ...) entered" },
+{ 701575253, "VL_GetNextServersByID returns .d" },
+{ 701575254, "VL_GetNextServersByName (connp=0x.x, volname=.s, startHere=.d, ...) entered" },
+{ 701575255, "VL_GetNextServersByName returns .d" },
+{ 701575256, "VL_GetSiteInfo(connp=0x.x, OldAddr=0x.x, FullSiteInfo=0x.x) entered" },
+{ 701575257, "VL_GetSiteInfo returns .d" },
+{ 701575258, "VL_GenerateSites(connp=0x.x, startHere=.d, ..., TheseSites=0x.x, nSites=0x.x) entered" },
+{ 701575259, "VL_GenerateSites returns .d" },
+{ 701575260, "VL_GenerateSites returning .d sites at 0x.x" },
+{ 701575261, "VL_GetNewVolumeIds (connp=0x.x, numWanted=.d, Addrp=0x.x, newIDs=0x.x) entered" },
+{ 701575262, "VL_GetNewVolumeIds returns .d" },
+{ 701575263, "VL_CreateServer (connp=0x.x, FullSiteInfo=0x.x) entered" },
+{ 701575264, "VL_CreateServer returns .d" },
+{ 701575265, "VL_Probe(connp=0x.x) entered" },
+{ 701575266, "VL_GetCEntryByID (connp=0x.x, volid=.d,,.d, voltype=.d, centryp=0x.x) entered" },
+{ 701575267, "VL_GetCEntryById returns .d" },
+{ 701575268, "VL_GetCEntryByName (connp=0x.x, volname=.s, centryp=0x.x) entered" },
+{ 701575269, "VL_GetCEntryByName returns .d" },
+{ 701575270, "VL_GetCNextServersByID (connp=0x.x, volid=.d,,.d, voltype=.d, startHere=.d, ...) entered" },
+{ 701575271, "VL_GetCNextServersByID storing entry in 0x.x, flags in 0x.x" },
+{ 701575272, "VL_GetCNextServerByID returns .d" },
+{ 701575273, "VL_GetCNextServersByName (connp=0x.x, volname=.s, startHere=.d, ...) entered" },
+{ 701575274, "VL_GetCNextServersByName storing entry in 0x.x, flags in 0x.x" },
+{ 701575275, "VL_GetCNextServerByName returns .d" },
+{ 701575276, "VL_AlterServer(connp=0x.x, AddrOfHost=0x.x, AttrsP=0x.x) entered" },
+{ 701575277, "VL_AlterServer returns .d" },
+{ 701575278, "VL_ExpandSiteCookie (connp=0x.x, Cookie=.d, FullSiteInfo=0x.x) entered" },
+{ 701575279, "VL_ExpandSiteCookie returns .d" },
+{ 701575280, "VL_GetServerInterfaces (connp=0x.x, serverInterfacesP=0x.x) entered" },
+{ 701575281, "VL_GetServerInterfaces returns .d" },
+{ 701575282, "RemoveEntry(trans=0x.x, entryptr=.d, tentry=0x.x) entered" },
+{ 701575283, "RemoveEntry returns .d" },
+{ 701575284, "FreeSiteQuota(trans=0x.x, tentry=0x.x) entered" },
+{ 701575285, "FreeSiteQuota returns .d" },
+{ 701575286, "vldbentry_to_vlentry(atrans=0x.x, VldbEntry=0x.x, VlEntry=0x.x) entered" },
+{ 701575287, "vldbentry_to_vlentry returns 0" },
+{ 701575288, "vlentry_to_vldbentry(trans, VlEntry, VldbEntry) entered" },
+{ 701575289, "vlentry_to_vldbentry returns 0" },
+{ 701575290, "vlentry_to_comvldbentry(trans=0x.x, vlentp=0x.x, comvldbp=0x.x) entered" },
+{ 701575291, "vlentry_to_comvldbentry returns 0" },
+{ 701575292, "InvalidOperation: .d" },
+{ 701575293, "InvalidRelease: releasetype" },
+{ 701575294, "NotFlAdmin(connp=0x.x) entered" },
+{ 701575295, "NotFlAdmin returns .d" },
+{ 701575296, "AuthForSiteDesc(connp=0x.x, descp=0x.x, ...) entered" },
+{ 701575297, "AuthForSiteDesc returns .d, ok=.d" },
+{ 701575298, "AuthForAddress(connp=0x.x, trans=0x.x, addrp=0x.x, ...) entered" },
+{ 701575299, "AuthForAddress returns .d, ok=.d" },
+{ 701575300, "AuthForVlEntry(connp=0x.x, trans=0x.x, vlentryp=0x.x, ...) entered" },
+{ 701575301, "AuthForVlEntry returns .d, ok=.d" },
+{ 701575302, "GetSite(trans=0x.x, SitePtr=.d, descBuffP=0x.x) entered" },
+{ 701575303, "GetSite returns .d" },
+{ 701575304, "CarefullyGetSite(trans=0x.x, SitePtr=.d, descBuffP=0x.x) entered" },
+{ 701575305, "CarefullyGetSite returns .d" },
+{ 701575306, "PutSite(trans=0x.x, SitePtr=.d, descBuffP=0x.x, needLock=.d) entered" },
+{ 701575307, "PutSite returns .d" },
+{ 701575308, "quotaCheck(trans=0x.x, descaddr=.d, descp=0x.x, quotaIncr=.d) entered" },
+{ 701575309, "quotaCheck returns .d" },
+{ 701575310, "EnsureAddrEntry(trans=0x.x, Addr=0x.x, OutPtr=0x.x, " },
+{ 701575311, "\tDoAlloc=.d, WhichAddr=0x.x, quotaIncr=.d)" },
+{ 701575312, "EnsureAddrEntry returns .d" },
+{ 701607937, "SFTSERVER_CreateTrans(.#lx, .lu,,.lu, .lu, .#lx, OUT <transIdp>) entered" },
+{ 701607938, "SFTSERVER_CreateTrans(#.ld) returns .ld, *transId = .ld" },
+{ 701607939, "SFTSERVER_AbortTrans(.#lx, .lu) entered" },
+{ 701607940, "SFTSERVER_AbortTrans returns .ld" },
+{ 701607941, "SFTSERVER_DeleteTrans(.#lx, .lu) entered" },
+{ 701607942, "SFTSERVER_DeleteTrans returns .ld" },
+{ 701607943, "SFTSERVER_CreateVolume(.#lx, .lu, .s, .#lx," },
+{ 701607944, "\t.#lx, .lu,,.lu, .lu,,.lu, OUT <transIdP>) entered" },
+{ 701607945, "SFTSERVER_CreateVolume(#.ld) returns .ld, *transId = .ld" },
+{ 701607946, "SFTSERVER_DeleteVolume(.#lx, .ld) entered" },
+{ 701607947, "SFTSERVER_DeleteVolume(#.ld) returns .ld" },
+{ 701607948, "SFTSERVER_Dump(.#lx, .ld," },
+{ 701607949, "\t{.#lx, {.lu, .lu}, .lu,,.lu}," },
+{ 701607950, "\t.#lx) entered" },
+{ 701607951, "SFTSERVER_Dump returns .ld" },
+{ 701607952, "SFTSERVER_Restore(.#lx, .lu, .#lx, .#lx) entered" },
+{ 701607953, "SFTSERVER_Restore returns .ld" },
+{ 701607954, "SFTSERVER_Forward(.#lx, .lu," },
+{ 701607955, "\t{.#lx, {.lu, .lu}, .lu,,.lu}," },
+{ 701607956, "\t.#lx, .#lx, .lu/.lu) entered" },
+{ 701607957, "SFTSERVER_Forward returns .ld" },
+{ 701607958, "SFTSERVER_Clone(.#lx, .lu, .#lx, .s," },
+{ 701607959, "\t.lu,,.lu) entered" },
+{ 701607960, "SFTSERVER_Clone(#.ld) returns .ld" },
+{ 701607961, "SFTSERVER_ReClone(.#lx, .lu, .lu,,.lu) entered" },
+{ 701607962, "SFTSERVER_ReClone(#.ld) returns .ld" },
+{ 701607963, "SFTSERVER_GetFlags(.#lx, .lu, OUT <OutFlagsp>) entered" },
+{ 701607964, "SFTSERVER_GetFlags(#.ld) returns .ld, *OutFlagsp = .#lx" },
+{ 701607965, "SFTSERVER_SetFlags(.#lx, .lu, .#lx) entered" },
+{ 701607966, "SFTSERVER_SetFlags(#.ld) returns .ld" },
+{ 701607967, "SFTSERVER_GetStatus(.#lx, .lu, OUT .#lx) entered" },
+{ 701607968, "SFTSERVER_GetStatus(#.ld) returns .ld" },
+{ 701607969, "SFTSERVER_SetStatus(.#lx, .lu, .#lx, .#lx) entered" },
+{ 701607970, "SFTSERVER_SetStatus(#.ld) returns .ld" },
+{ 701607971, "SFTSERVER_ListVolumes(.#lx, .lu, {.lu, <uuid>}, OUT <outCookieP>, OUT <statEntries>) entered" },
+{ 701607972, "SFTSERVER_ListVolumes returns .ld, *outCookieP = {.lu, <uuid>}, *statEntries = {.lu, <ftserver_status_val[]>}" },
+{ 701607973, "SFTSERVER_ListAggregates(.#lx, {.lu, <uuid>}, OUT <outCookieP>, OUT <aggrList>) entered" },
+{ 701607974, "SFTSERVER_ListAggregates returns .ld, *outCookieP = {.lu, <uuid>}, *aggrList = {.lu, <ftserver_aggrEntries_val[]>}" },
+{ 701607975, "SFTSERVER_AggregateInfo(.#lx, .lu, OUT <aggrInfop>) entered" },
+{ 701607976, "SFTSERVER_AggregateInfo returns .ld, *aggrInfop = {.s, .s, .lu," },
+{ 701607977, "\t.lu, .lu, .lu}" },
+{ 701607978, "SFTSERVER_Monitor(.#lx, OUT <entriesp>) entered" },
+{ 701607979, "SFTSERVER_Monitor returns .ld, *entriesp = {.lu, ftserver_transStatus_val[]}" },
+{ 701607980, "SFTSERVER_GetOneVolStatus(.#lx, .lu,,.lu, .lu, <spare1>, OUT .#lx) entered" },
+{ 701607981, "SFTSERVER_GetOneVolStatus(#.ld) returns .ld" },
+{ 701607982, "SFTSERVER_GetServerInterfaces(.#lx, OUT <serverInterfacesP>) entered" },
+{ 701607983, "SFTSERVER_GetServerInterfaces returns .lu, *serverInterfacesP = {.lu, <dfs_interfaceList_val[]>}" },
+{ 701607984, "SFTSERVER_SwapIDs(.#lx, .lu, .lu) entered" },
+{ 701607985, "SFTSERVER_SwapIDs(#.ld) returns .ld" },
+{ 701607986, "getOrigStatus({..., .ld, .ld, .lu,,.lu, .ld, ...}) entered" },
+{ 701607987, "getOrigStatus(#.ld) returns .ld" },
+{ 701607988, "DeleteTrans(.#lx, .lu, .ld) entered" },
+{ 701607989, "DeleteTrans(#.ld) returns .ld" },
+{ 701607990, "ftserver_DeleteVolume({..., .ld, .ld, .lu,,.lu, .ld, ...}) entered" },
+{ 701607991, "ftserver_DeleteVolume(#.ld) returns .ld" },
+{ 701607992, "forwardPull(.#lx, .#lx, .lu, OUT <outSizeP>) entered" },
+{ 701607993, "forwardPull returns void, *outSizeP = .lu" },
+{ 701607994, "forwardWriter(.#lx," },
+{ 701607995, "\t{.#lx, {.lu, .lu}, .lu,,.lu}," },
+{ 701607996, "\t{..., .ld, .ld, .lu,,.lu, .ld, ...}) entered" },
+{ 701607997, "forwardWriter(#.ld) exits with .ld" },
+{ 701607998, "vols_Forward({..., .ld, .ld, .lu,,.lu, .ld, ...}," },
+{ 701607999, "\t.#lx, .lu," },
+{ 701608000, "\t{.#lx, {.lu, .lu}, .lu,,.lu}," },
+{ 701608001, "\t.#lx, .#lx, .lu) entered" },
+{ 701608002, "vols_Forward(#.ld) returns .ld" },
+{ 701608003, "ftserver_Clone({..., .ld, .ld, .lu,,.lu, .ld, ...}," },
+{ 701608004, "\t.lu,,.lu, .s, .#lx) entered" },
+{ 701608005, "ftserver_Clone(#.ld) returns .ld" },
+{ 701608006, "vols_ReClone({..., .ld, .ld, .lu,,.lu, .ld, ...}," },
+{ 701608007, "\t{..., .ld, .ld, .lu,,.lu, .ld, ...}) entered" },
+{ 701608008, "vols_ReClone(#.ld) returns .ld" },
+{ 701608009, "ftserver_UnClone({..., .ld, .ld, .lu,,.lu, .ld, ...}," },
+{ 701608010, "\t{..., .ld, .ld, .lu,,.lu, .ld, ...}) entered" },
+{ 701608011, "ftserver_UnClone(#.ld) returns .ld" },
+{ 701608012, "vols_FillBaseType({..., .ld, .ld, .lu,,.lu, .ld, ...}) entered" },
+{ 701608013, "vols_FillBaseType(#.ld) returns .ld" },
+{ 701608014, "vol_syscall(.ld, .#lx, .#lx, .#lx," },
+{ 701608015, "\t.#lx) entered" },
+{ 701608016, "vol_syscall returns .ld" },
+{ 701608017, "ag_syscall(.ld, .#lx, .#lx, .#lx," },
+{ 701608018, "\t.#lx) entered" },
+{ 701608019, "ag_syscall returns .ld" },
+{ 701608020, "ftserver_NewTrans(.lu,,.lu, .lu, OUT <codep>)" },
+{ 701608021, "ftserver_NewTrans(#.ld) returns .#lx (t_transId = .lu), *codep = .ld" },
+{ 701608022, "ftserver_FindTrans(.ld) entered" },
+{ 701608023, "ftserver_FindTrans(#.ld) returns .#lx (t_aggrId = .lu, t_volId = .lu,,.lu)" },
+{ 701608024, "ftserver_DeleteTrans({..., .ld, .ld, .lu,,.lu, .ld, ...}," },
+{ 701608025, "\t.ld) entered" },
+{ 701608026, "ftserver_DeleteTrans(#.ld) returns .ld" },
+{ 701608027, "ftserver_PutTrans({..., .ld, .ld, .lu,,.lu, .ld, ...}" },
+{ 701608028, "ftserver_PutTrans(#.ld) returns .ld" },
+{ 701608029, "ftserver_GCTrans(void) entered" },
+{ 701608030, "ftserver_GCTrans returns .ld" },
+{ 701608031, "ftserver_SwapTransStates({..., .ld, .ld, .lu,,.lu, .ld, ...}," },
+{ 701608032, "\t{..., .ld, .ld, .lu,,.lu, .ld, ...}) entered" },
+{ 701608033, "ftserver_SwapTransStates returns .ld" },
+{ 701608034, "vols_Lock(.s) called" },
+{ 701608035, "vols_Lock(.s) disables cancels: old state=.ld, cancelCode=.ld" },
+{ 701608036, "vols_Unlock(.s) called: old state=.ld" },
+{ 701608037, "vols_Unlock(.s) has re-enabled cancels (code .ld)" },
+{ 701608038, ".s: Authorization failure, code .ld" },
+{ 701608039, ".s: caught exception (code .ld): .s" },
+{ 701608040, ".s: Need to drain the input pipe; code so far = .lu" },
+{ 701608041, ".s: Draining done, .ld bytes in .ld calls" },
+{ 701608042, "SFTSERVER_ConnectSock(.#lx, .ld, .#lx, .#lx)" },
+{ 701608043, "SFTSERVER_ConnectSock TCP clntAddr(.ld, .ld, .#lx)" },
+{ 701608044, "SFTSERVER_ConnectSock UNIX clntAddr(.ld, .s)" },
+{ 701608045, "SFTSERVER_ConnectSock Unsupported protocol(.ld)" },
+{ 701608046, "SFTSERVER_ConnectSock TCP srvrAddr(.ld, .ld, .#lx)" },
+{ 701608047, "SFTSERVER_ConnectSock UNIX srvrAddr(.ld, .s)" },
+{ 701608048, "SFTSERVER_ConnectSock returns .ld" },
+{ 701608049, "SFTSERVER_DisconnectSock(.#lx, .ld)" },
+{ 701608050, "SFTSERVER_DisconnectSock returns .ld" },
+{ 701608051, "SFTSERVER_ListenSock(.#lx, .ld, .#lx)" },
+{ 701608052, "SFTSERVER_ListenSock TCP srvrAddr(.ld, .ld, .#lx)" },
+{ 701608053, "SFTSERVER_ListenSock returns .ld" },
+{ 701608054, "SFTSERVER_AcceptSock(.#lx, .ld, .#lx)" },
+{ 701608055, "SFTSERVER_AcceptSock TCP srvrAddr(.ld, .ld, .#lx)" },
+{ 701608056, "SFTSERVER_AcceptSock returns .ld" },
+{ 701612033, "ftu_AggrGetInfo(.lu, OUT <aggrInfoP>) entered" },
+{ 701612034, "ftu_AggrGetInfo returns .ld, *aggrInfoP = {.s, .s, .ld," },
+{ 701612035, "\t.ld, .ld, .ld}" },
+{ 701612036, "ftu_AggrSync(.lu, .d) entered" },
+{ 701612037, "ftu_AggrSync returns .ld" },
+{ 701612038, "ftu_AggrCreateFsetWithStatus(.lu, .u,,.u, {..., .u,,.u, ..., .#lx" },
+{ 701612039, "\t..., .s, ...}, .#lx) entered" },
+{ 701612040, "ftu_AggrCreateFsetWithStatus returns .ld" },
+{ 701612041, "ftu_AggrOpenFset(.lu, .u,,.u, .#lx," },
+{ 701612042, "\t.lu (.s), OUT <fsetDescP>) entered" },
+{ 701612043, "ftu_AggrOpenFset returns .ld, *fsetDescP = .ld" },
+{ 701612044, "ftu_AggrCloseFset(.ld) entered" },
+{ 701612045, "ftu_AggrCloseFset returns .ld" },
+{ 701612046, "ftu_AggrAbortFsetOpen(.ld) entered" },
+{ 701612047, "ftu_AggrAbortFsetOpen returns .ld" },
+{ 701612048, "ftu_AggrEnumerateFsets(.lu, INOUT *indexP = .u, .#lx, .u, OUT <numFsetsReturnedP>) entered" },
+{ 701612049, "ftu_AggrEnumerateFsets returns .ld, *indexP = .u, *numFsetsReturnedP = .u" },
+{ 701612050, "ftu_AggrLookupFset(.lu, .s, OUT <fsetIdP>) entered" },
+{ 701612051, "ftu_AggrLookupFset returns .ld, *fsetIdP = .u,,.u" },
+{ 701612052, "ftu_AggrLookupFset returns .ld" },
+{ 701612053, "ftu_FsetGetStatus(.ld, OUT <fsetStatusP>) entered" },
+{ 701612054, "ftu_FsetGetStatus returns .ld, *fsetStatusP = {.u,,.u, .u,,.u, ... .#lx," },
+{ 701612055, "\t.lu (.s), .lx, ..., .s}" },
+{ 701612056, "ftu_FsetSetStatus(.ld, .#lx, {.u,,.u, ... .#lx, ...}) entered" },
+{ 701612057, "ftu_FsetSetStatus returns .ld" },
+{ 701612058, "ftu_FsetBulkSetStatus(.u" },
+{ 701612059, "\t, {.ld, .#lx, .u,,.u}" },
+{ 701612060, ") entered" },
+{ 701612061, "ftu_FsetBulkSetStatus returns .ld" },
+{ 701612062, "ftu_FsetPushStatus(.ld) entered" },
+{ 701612063, "ftu_FsetPushStatus returns .ld" },
+{ 701612064, "ftu_FsetSync(.ld, .ld) entered" },
+{ 701612065, "ftu_FsetSync returns .ld" },
+{ 701612066, "ftu_FsetClone(.ld, .u,,.u, .s, .#lx) entered" },
+{ 701612067, "ftu_FsetClone: Raising .s limit on fset .u,,.u to .u,,.u (was .u,,.u)" },
+{ 701612068, "ftu_FsetClone: Zeroing bogus back ID in fset .u,,.u (was .u,,.u)" },
+{ 701612069, "ftu_FsetClone returns .ld" },
+{ 701612070, "ftu_FsetReclone(.ld) entered" },
+{ 701612071, "ftu_FsetReclone returns .ld" },
+{ 701612072, "ftu_FsetRecloneInto(.ld, .u,,.u) entered" },
+{ 701612073, "ftu_FsetRecloneInto returns .ld" },
+{ 701612074, "RecloneIntoAdjacentFset: Raising .s limit on fset .u,,.u to .u,,.u (was .u,,.u)" },
+{ 701612075, "DestroyFset(.ld, .ld) entered" },
+{ 701612076, "DestroyFset: Ignoring bogus back ID in fset .u,,.u (was .u,,.u)" },
+{ 701612077, "DestroyFset: Ignoring bogus fwd. ID in fset .u,,.u (was .u,,.u)" },
+{ 701612078, "DestroyFset: Raising .s limit on fset .u,,.u to .u,,.u (was .u,,.u)" },
+{ 701612079, "DestroyFset returns .ld" },
+{ 701612080, "ftu_FsetDumpToPipe(.ld," },
+{ 701612081, "\t{.#lx, {.lu, .lu}, .lu,,.lu}," },
+{ 701612082, "\t.#lx) entered" },
+{ 701612083, "ftu_FsetDumpToPipe returns .ld" },
+{ 701612084, "ftu_FsetRestoreFromPipe(.ld, .#lx, .#lx) entered" },
+{ 701612085, "ftu_FsetRestoreFromPipe returns .ld" },
+{ 701612086, "ftu_AggrSyscall(.ld, .#lx, .#lx, .#lx" },
+{ 701612087, "\t.#lx) entered" },
+{ 701612088, "ftu_AggrSyscall returns .ld" },
+{ 701612089, "ftu_VolSyscall(.ld, .#lx, .#lx, .#lx," },
+{ 701612090, "\t.#lx) entered" },
+{ 701612091, "ftu_VolSyscall returns .ld" },
+{ 701612092, "ftu_FsetCloneWithKA: Failed to open (and thus destroy) .s (.u,,.u)" },
+{ 701612093, "vols_DumpVolume: Caught exception: .s" },
+{ 701612094, ".s(.ld, .ld, .#lx," },
+{ 701612095, "\t.#lx, .#lx) entered" },
+{ 701612096, ".s returns .ld" },
+{ 701612097, "ftutil_VolDepleteAux(.ld, .#lx, .#lx, .#lx) entered" },
+{ 701612098, "ftutil_VolDepleteAux returns .ld" },
+{ 701612099, "ftu_FsetSwapIds(.ld, .ld) entered" },
+{ 701612100, "ftu_FsetSwapIds returns .ld" },
+{ 701612101, "ftu_VolSyscall(.ld) returns .ld" },
+{ 701612102, "vols_RestoreVnode: can't set acl type .d in vnode .d: error .d" },
+{ 701612103, "vols_DumpData: reading at offset .#llx for length .#lx" },
+{ 701612104, "vols_DumpData: op returns .d, len .#lx; holeOff .#lx,,.lx, holeLen .#lx,,.lx" },
+{ 701931521, "FSHS fshs_GetHost, cookie .x" },
+{ 701931522, "FSHS fshs_FindHost, cookie .x" },
+{ 701931523, "FSHS find a prime host .x" },
+{ 701931524, "FSHS find a sec host : .x, its prime host : .x" },
+{ 701931525, "FSHS allocate a prime host .x" },
+{ 701931526, "FSHS allocate a sec host .x" },
+{ 701931527, "FSHS find a host from slow path .x" },
+{ 701931528, "FSHS find a down host from slow path .x" },
+{ 701931529, "FSHS callback fails with ipaddr .x" },
+{ 701931530, "FSHS find a host in fast path .x" },
+{ 701931531, "FSHS cannot find a host in fast path" },
+{ 701931532, "FSHS PutHost ref = .d" },
+{ 701931533, "FSHS fshs_GCHost .x ref .d" },
+{ 701931534, "FSHS GC a prime host" },
+{ 701931535, "FSHS MarkSecHostBad: prime .x sec .x" },
+{ 701931536, "FSHS fshs_UpdateHostList called" },
+{ 701931537, "FSHS fshs_AssignHost .x, ipaddr .x" },
+{ 701931538, "FSHS fshs_FreeHost .x" },
+{ 701931539, "FSHS fshs_CheckHost START .x" },
+{ 701931540, "FSHS fshs_CheckHost END" },
+{ 701931541, "FSHS CheckHost: stale princ .x ref .d" },
+{ 701931542, "FSHS fshs_HostCheckDaemon .." },
+{ 701931543, "FSHS fshs_Enumerate END" },
+{ 701931544, "FSHS fshs_Enumerate START" },
+{ 701931545, "FSHS fshs_SetRecoveryParam.. " },
+{ 701931546, "FSHS fshs_AllocPrincipal START.." },
+{ 701931547, "FSHS fshs_AllocPrincipal END.." },
+{ 701931548, "FSHS fshs_FreePrincipal .x" },
+{ 701931549, "FSHS fshs_FindPrincipal.. " },
+{ 701931550, "FSHS found a princ slow .x ref .d" },
+{ 701931551, "FSHS found a princ fast .x ref .d" },
+{ 701931552, "FSHS rock hits .d, misses .d, cache empty .d, repop .d" },
+{ 701931553, "FSHS fshs_GetPrincipal START" },
+{ 701931554, "FSHS fshs_GetPrincipal END .x, ref .d" },
+{ 701931555, "FSHS find a princ (fast path) .x, ref .d" },
+{ 701931556, "FSHS assign a princ (slow path) .x" },
+{ 701931557, "FSHS fshs_PutPrincipal .x ref .d" },
+{ 701931558, "FSHS fshs_GCPrinc from host .x" },
+{ 701931559, "FSHS fshs_GCPrinc found a stale princ .x" },
+{ 701931560, "FSHS fshs_GetStalePrincipals START" },
+{ 701931561, "FSHS fshs_GetStalePrincipals END" },
+{ 701931562, "FSHS fshs_getcred: princp .x, anonymous uid .d" },
+{ 701931563, "FSHS fshs_RevokeToken host .x" },
+{ 701931564, "FSHS fshs_AsyncGrant host .x" },
+{ 701931565, "FSHS tokenint_InitTokenState host .x" },
+{ 701931566, "FSHS TKN_TokenRevoke code = .d" },
+{ 701931567, "FSHS set callback binding host .x" },
+{ 701931568, "FSHS fshs_RevokeToken host .x: flags .#x, .d token(s)" },
+{ 701931569, "FSHS fshs_RevokeToken: host .x is down; succeeding vacuously" },
+{ 701931570, "FSHS fshs_RevokeToken: RPC timeout (.d secs) exceeded for host .x; marking it DOWN" },
+{ 701931571, "FSHS fshs_RevokeToken: lifetime (.d secs) exceeded for host .x; marking it DOWN" },
+{ 701931572, "FSHS fshs_GetHost: host .x, states .#lx, flags .#lx: forcing null return" },
+{ 701931573, "FSHS fshs_GetTSRCode: host .x, returning .#lx" },
+{ 701931574, "FSHS fshs_CreateHost: creating host .x, primary=.d, flags=.#lx; host states now .#lx" },
+{ 701931575, "FSHS and host .x has fshost flags of .#lx" },
+{ 701931576, "FSHS fshs_CreateHost: clearing host .#lx" },
+{ 701931577, "FSHS fshs_CreateHost: calling TKN_InitTokenState on host .#lx (NOW OBSOLETE)" },
+{ 701931578, "FSHS fshs_CreateHost: host .x TKN_InitTokenState returned (NOW OBSOLETE) .ld" },
+{ 701931579, "FSHS fshs_CreateHost: host .x cleared: states now .#lx, returning .ld" },
+{ 701931580, "FSHS fshs_CreateHost: returning .ld" },
+{ 701931581, "FSHS fshs_RevokeToken: host .x refused .d HERE tokens for fileset .lu,,.lu; marking it DOWN" },
+{ 701931582, "FSHS entered fshs_SetupDelegationChain" },
+{ 701931583, "FSHS entering sec_cred_get_initiator" },
+{ 701931584, "FSHS entering sec_cred_initialize_cursor" },
+{ 701931585, "FSHS found pa: user .d, group .d, num_groups .d" },
+{ 701931586, "FSHS entering sec_cred_get_delegate" },
+{ 701931587, "FSHS CreateHost: BindingFromInBinding failed, host .x, code .d, try given binding" },
+{ 701931588, "FSHS CreateHost: Can't set rpc call timeout for host .x code .d" },
+{ 701931589, "FSHS CreateHost: Trying to call .x/.d rather than .x/.d (net byte order)" },
+{ 701931590, "FSHS CreateHost: Result (host .x) is .d" },
+{ 701931591, "FSHS fshs_getcred: princp .x is local: uid .d, gid .d, ngroups .d" },
+{ 701931592, "FSHS fshs_CheckAuthn: cookie .x, hostp .x, hostp->flags .x..." },
+{ 701931593, "FSHS ... minAuthn .d, maxAuthn .d, this .d: result .d" },
+{ 701931594, "FSHS fshs_InqContext: inq_auth_caller returns .d (authnLevel .d, authnSvc .d, authzSvc .d) (NOW OBSOLETE)" },
+{ 701931595, "FSHS fshs_InqContext: inq_auth_caller returns authz .d, principal name '.s' (NOW OBSOLETE)" },
+{ 701931596, "FSHS CreateHost: Authenticating host .x, reverse-binding, as self to .s: result .d" },
+{ 701931597, "FSHS CreateHost: Authenticating host .x, given binding, as self to .s: result .d" },
+{ 701931598, "FSHS CreateHost: Host .x, addr .x, changing port from .#x to .#x" },
+{ 701931599, "FSHS CreateHost: Authenticating host .x, new port binding, as self to .s: result .d" },
+{ 701931600, "FSHS fshs_RevokeToken, host .x marked DOWN: lifetime (.d secs) exceeded, err count .d too big, or time since OK rvk .d too big" },
+{ 701931601, "FSHS fshs_RevokeToken, Host .x skipping tokenID .lu,,.lu from clamped set." },
+{ 701931602, "FSHS fshs_RevokeToken, Host .x: all .d tokens in revoke request were clamped: skipped." },
+{ 701931603, "FSHS fshs_RevokeToken (host .x has address .x, rpcguarantee .d secs.)" },
+{ 701931604, "FSHS fshs_RevokeToken: host .x (addr .x) refused .d HERE tokens for fileset .lu,,.lu; marking it DOWN" },
+{ 701931605, "FSHS fshs_RevokeToken: host .x (addr .x) ignores forceflag .#x, refused types .x,,.x; marking it DOWN" },
+{ 701931606, "FSHS fshs_RevokeToken: we revoked .x,,.x from host .x, addr .x, but it refused to revoke .x,,.x" },
+{ 701931607, "FSHS fshs_RevokeToken host .x, addr .x: flags .#x, .d token(s)" },
+{ 701931608, "FSHS TKN_TokenRevoke to address .x: code = .d" },
+{ 701931609, "FSHS fshs_AsyncGrant host .x, addr .x" },
+{ 701931610, "FSHS fshs_AsyncGrant host .x, addr .x, RPC returned .d" },
+{ 701931611, "FSHS tokenint_InitTokenState host .x, addr .x, tsrCode .#x" },
+{ 701931612, "FSHS tokenint_InitTokenState host .x, addr .x: rpc returned .d" },
+{ 701931613, "FSHS find a prime host .x, addr .x" },
+{ 701931614, "FSHS and host .x has fshost flags of .#lx, addr .x" },
+{ 701931615, "FSHS CreateHost: Authenticating host .x, addr .x, given binding, as self to .s: result .d" },
+{ 701931616, "FSHS CreateHost: Authenticating host .x, addr .x, reverse-binding, as self to .s: result .d" },
+{ 701931617, "FSHS fshs_loadContext: inq_auth_caller authnLevel .d, authnSvc .d, authzSvc .d" },
+{ 701931618, "FSHS fshs_loadContext: inq_auth_caller, caller is unauthenticated .d" },
+{ 701931619, "FSHS fshs_loadContext: inq_auth_caller failed, code .d" },
+{ 701931620, "FSHS CreateHost: Host .x: changing addr from type .d, ip .x, port .#x..." },
+{ 701931621, "... to type .d, ip .x, port .#x (authn .d)" },
+{ 701931622, "FSHS newSAddr: Host .x: adding IP .x, port .d; addr count now .d" },
+{ 701931623, "FSHS fshs_NewAddr: Host .x: killing IP .x; error .d; addr count now .d" },
+{ 701931624, "FSHS fshs_CreateHost: Host .x, addr count .d: changing port from .d to .d" },
+{ 701931625, "FSHS fshs_PickAddr: all addresses for host .x are dead (code .d, count .d)" },
+{ 701931626, "FSHS fshs_PickAddr: host .x: picking IP .x port .d" },
+{ 701931627, "FSHS fshs_ReviveAddrs: host .x: reviving IP .x with last error .d; error addr count now .d" },
+{ 701931628, "FSHS fshs_AddrReact: all addresses for host .x are dead (count .d)" },
+{ 701931629, "FSHS fshs_AddrReact: host .x: ip addr .x redirected to .x" },
+{ 701931630, "FSHS fshs_AddrReact: host .x: ip addr .x got err .d, no replacement" },
+{ 701931631, "FSHS fshs_AddrReact: host .x: ip addr .x got err .d, so moving to ip .x" },
+{ 701931632, "FSHS newSAddr: Host .x: reviving exising IP .x (killed at .d with .d)" },
+{ 701931633, "FSHS TKN_TokenRevoke to address .x rtns code .d in .d secs" },
+{ 702357505, "TKC gettoken start vcp 0x.x type 0x.x" },
+{ 702357506, "TKC gettoken back, code .d" },
+{ 702357507, "TKC revoke start vcp 0x.x, rights 0x.x" },
+{ 702357508, "TKC revoke back, code .d" },
+{ 702357509, "GLUE read vp 0x.x, off 0x.x len 0x.x" },
+{ 702357510, "GLUE read code .d, 0x.x bytes left" },
+{ 702357511, "GLUE write vp 0x.x, off 0x.x len 0x.x" },
+{ 702357512, "GLUE write code .d, 0x.x bytes left" },
+{ 702357513, "GLUE purge vp 0x.x" },
+{ 702357514, "GLUE getacl: start, vp .#x" },
+{ 702357515, "GLUE getacl: xvfs_GetVolume failed with .d" },
+{ 702357516, "GLUE getacl: tkc_Get failed; returning EINVAL" },
+{ 702357517, "GLUE getacl: vp .#x, returning .d" },
+{ 702357518, "GLUE setacl: start, vp .#x" },
+{ 702357519, "GLUE setacl: xvfs_GetVolume failed with .d" },
+{ 702357520, "GLUE setacl: tkc_Get failed; returning EINVAL" },
+{ 702357521, "GLUE setacl: vp .#x, returning .d" },
+{ 702357522, "tkc_Get(type=.x) called" },
+{ 702357523, "tkc_Get has tokens: .x" },
+{ 702357524, "tkc_Get fails to get tokens: code .d" },
+{ 702357525, "tkc_Get gets tokens: .x" },
+{ 702357526, "tkc_Put puts .x; dataHolds now .d" },
+{ 702357527, "tkc_Release puts .x; refCount now .d" },
+{ 702357528, "tkc_GetTokens(.x, .d) called" },
+{ 702357529, "tkc_GetTokens() terminates with code .d (returns 0)" },
+{ 702357530, "tkc_ReleaseTokens called, size of .d" },
+{ 702357531, "tkc_PutTokens called, size of .d" },
+{ 702357532, "tkchs_RevokeToken called with revokeLen = .d" },
+{ 702357533, "GLUE getxtdattr: start, vp .#x" },
+{ 702357534, "GLUE getxtdattr: xvfs_GetVolume failed with .d" },
+{ 702357535, "GLUE getxtdattr: tkc_Get failed; returning EINVAL" },
+{ 702357536, "GLUE getxtdattr: vp .#x, returning .d" },
+{ 702357537, "GLUE setxtdattr: start, vp .#x" },
+{ 702357538, "GLUE setxtdattr: xvfs_GetVolume failed with .d" },
+{ 702357539, "GLUE setxtdattr: tkc_Get failed; returning EINVAL" },
+{ 702357540, "GLUE setxtdattr: vp .#x, returning .d" },
+{ 702357541, "GLUE read vp 0x.x, off .#lx,,.lx len .#x" },
+{ 702357542, "GLUE write vp 0x.x, off .#lx,,.lx len 0x.x" },
+{ 702357543, "GLUE punch: start, vp .#x" },
+{ 702357544, "GLUE punch: xvfs_GetVolume failed with .d" },
+{ 702357545, "GLUE punch: tkc_Get failed; returning EINVAL" },
+{ 702357546, "GLUE punch: vp .#x, returning .d" },
+{ 702357547, "TKC getlocks vcp .#x, type .#x, range .lx,,.lx through .lx,,.lx" },
+{ 702357548, "TKC putlocks vcp .#x, range .lx,,.lx through .lx,,.lx" },
+{ 702357549, "GLUE x->v vp 0x.x, write=.d, off .#lx,,.lx len .#x" },
+{ 703262721, "PX .s" },
+{ 703262722, "PX in SetContext, Flag .x" },
+{ 703262723, "PX in LookupRoot Volume .x..x" },
+{ 703262724, "PX LookupRoot returning Vnode .x, Unique .x, code .d" },
+{ 703262725, "PX FetchData Fid .x..x..x..x, Pos .d, Len .d, Flags 0x.x" },
+{ 703262726, "PX FetchData returns code .d" },
+{ 703262727, "PX FetchACL Fid .x..x..x..x, aclType .d" },
+{ 703262728, "PX FetchACL returns .d" },
+{ 703262729, "PX FetchStatus Fid .x..x..x..x, Flags 0x.x" },
+{ 703262730, "PX FetchStatus returns .d" },
+{ 703262731, "PX StoreData fid .x..x..x..x, mask .x, position .d, length .d" },
+{ 703262732, "PX StoreData returns .d" },
+{ 703262733, "PX StoreACL Fid .x..x..x..x, acl type .d, acl fid .x..x..x..x" },
+{ 703262734, "PX StoreACL returns .d" },
+{ 703262735, "PX StoreStatus fid .x..x..x..x mask 0x.x" },
+{ 703262736, "PX StoreStatus returns .d" },
+{ 703262737, "PX RemoveFile dirfid .x..x..x..x name .s, retID .d..d" },
+{ 703262738, "PX RemoveFile returns .d" },
+{ 703262739, "PX CreateFile dir .x..x..x..x, name .s, mask 0x.x" },
+{ 703262740, "PX CreateFile returns fid .x..x..x..x, new token ID .d..d, code .d" },
+{ 703262741, "PX Rename from .x..x..x..x/.s to .x..x..x..x/.s" },
+{ 703262742, "PX Rename returns .d" },
+{ 703262743, "PX Symlink dir .x..x..x..x/.s points at .s, mask 0x.x" },
+{ 703262744, "PX Symlink returned .x..x..x..x code .d" },
+{ 703262745, "PX Link .x..x..x..x/.s points to fid .x..x..x..x" },
+{ 703262746, "PX Link returns .d" },
+{ 703262747, "PX MakeDir .x..x..x..x/.s, mask 0x.x" },
+{ 703262748, "PX Makedir returns .x..x..x..x (tid .d..d) code .d" },
+{ 703262749, "PX RemoveDir .x..x..x..x/.s retID .d..d" },
+{ 703262750, "PX RemoveDir returns .d" },
+{ 703262751, "PX Readdir .x..x..x..x offset .d, size .d" },
+{ 703262752, "PX Readdir returns next offset .d, code .d" },
+{ 703262753, "PX Lookup .x..x..x..x/.s, flags 0x.x" },
+{ 703262754, "PX Lookup returns fid .x..x..x..x (tid .d..d), code .d" },
+{ 703262755, "PX GetStatistics" },
+{ 703262756, "PX GetStatistics returned .d" },
+{ 703262757, "PX ReleaseTokens returning .d tokens" },
+{ 703262758, "PX ReleaseTokens returns .d" },
+{ 703262759, "PX GetToken fid .x..x..x..x type 0x.x, id .d..d, flags 0x.x" },
+{ 703262760, "PX GetToken returns id .d..d, rights 0x.x..x, code .d" },
+{ 703262761, "PX GetTime" },
+{ 703262762, "PX GetTime returns .d" },
+{ 703262763, "PX BulkFetchVV cell .x..x, .d vols, Flags .d" },
+{ 703262764, "PX BulkFetchVV returns code .d" },
+{ 703262765, "PX BulkKeepAlive .d fids, flags 0x.x" },
+{ 703262766, "PX BulkKeepAlive returns .d" },
+{ 703262767, "PX Quota Fid .x..x..x..x, quota .d, Flags .d" },
+{ 703262768, "PX Quota returns .d" },
+{ 703262769, "PX GetServerInterfaces" },
+{ 703262770, "PX SetParams" },
+{ 703262771, "PX SetParams returns .d" },
+{ 703262772, "PX in runTokens" },
+{ 703262773, "PX runTokens action .d, mid .d, fid .x..x..x..x flags 0x.x" },
+{ 703262774, "PX runTokens returned code .d, exp .d" },
+{ 703262775, "PX runTokens applies to .d" },
+{ 703262776, "PX runTokens can't return, code .d" },
+{ 703262777, "PX runTokens done, .d current entries" },
+{ 703262778, "PX runTokens deleting expired entries" },
+{ 703262779, "PX in bulk keepalive" },
+{ 703262780, "PX BKA growing from .d to .d" },
+{ 703262781, "PX BKA execs .d, now .d reads" },
+{ 703262782, "PX in PeriodicKA" },
+{ 703262783, "PX RevokeSet len .d" },
+{ 703262784, "PX RevokeSet found it (index .d)" },
+{ 703262785, "PX RevokeSet holding token" },
+{ 703262786, "PX Revokeset relinquishing token" },
+{ 703262787, "PX Revokeset abandoning tokens" },
+{ 703262788, "PX rdwr bad file type for op .d, type is .d (failing)" },
+{ 703262789, "PX checkflservers checking .d servers" },
+{ 703262790, "PX starting fls probe" },
+{ 703262791, "PX end fls probe, code .d" },
+{ 703262792, "PX in px_initFLServers" },
+{ 703262793, "PX leaving px_initFLServers, .d servers" },
+{ 703262794, "PX flgetentrybyid for id .d..d" },
+{ 703262795, "PX flgetentrybyid server down conn 0x.x" },
+{ 703262796, "PX calling flserver conn .x" },
+{ 703262797, "PX flserver call done, code .d" },
+{ 703262798, "PX RPC exception while pushing" },
+{ 703262799, "PX RPC exception while pulling" },
+{ 703262800, "PX in pxvc_Cleanups" },
+{ 703262801, "PX piping data for length .d" },
+{ 703262802, "PX end piping data" },
+{ 703262803, "PX GetToken output range: .lu,,.lu thru .lu,,.lu" },
+{ 703262804, "PX GetToken input range: .lu,,.lu thru .lu,,.lu" },
+{ 703262805, "PX CreateFile couldn't get token on new fid .x..x..x..x: code .d" },
+{ 703262806, "PX Symlink couldn't get token on new fid .x..x..x..x: code .d" },
+{ 703262807, "PX MakeDir couldn't get token on new fid .x..x..x..x: code .d" },
+{ 703262808, "PX RPC exception (.d) while pushing" },
+{ 703262809, "PX RPC exception (.d) while pulling" },
+{ 703262810, "PX px_SetSync found a R/W volume .lu,,.lu (states .#x) that claims to be repserver managed" },
+{ 703262811, "PX BKA gets new fid .x..x..x..x, exec .d, timeout .d" },
+{ 703262812, "PX BKA extends lifetime of fid .x..x..x..x, exec .d, timeout .d" },
+{ 703262813, "PX RevokeSet holding token .x,,.x on fid .x..x..x..x until .d, flags .x" },
+{ 703262814, "PX Revokeset relinquishing old token .x,,.x on fid .x..x..x..x, flags .x" },
+{ 703262815, "PX runTokens sees horrible tkm_GetToken error .d, fid .x..x..x..x, position .d" },
+{ 703262816, "PX StoreData from host without tokens fid .x..x..x..x, off .d len .d (getrights code = .d)" },
+{ 703262817, "PX px_ComputeTokenRecoveryTime: Bringing server UP after a crash (now=.d, initRecTime=.d, endRecTime=.d, interval=.d)" },
+{ 703262818, "PX px_ComputeTokenRecoveryTime: Extending the recovery time (rpcRate=.d, endRecTime=.d, now=.d)" },
+{ 703262819, "PX px_ComputeTokenRecoveryTime: rpcRate is .d, as ((.d - .d) * 10) / .d" },
+{ 703262820, "PX px_RunCheckingDaemons: Bringing server UP after a crash (now=.d, endRecTime=.d)" },
+{ 703262821, "PX Pre DCE 1.1 client requesting fid .#x..#x, vp .#x, acl type .d" },
+{ 703262822, "PX BulkFetchStatus: fid .x..x..x..x, offset .d, size .d" },
+{ 703262823, "PX BulkFetchStatus: pipe broke while draining" },
+{ 703262824, "PX Bulkstat: bad flag parameter" },
+{ 703262825, "PX Bulkstat: called during post recovery" },
+{ 703262826, "PX Bulkstat: bad context" },
+{ 703262827, "PX Bulkstat: cannot get principal" },
+{ 703262828, "PX Bulkstat: lookup error on dir .x..x..x..x" },
+{ 703262829, "PX Bulkstat: attr on dir .x..x..x..x" },
+{ 703262830, "PX Bulkstat: cannot file file .s" },
+{ 703262831, "PX Bulkstat: no fid for vp .x" },
+{ 703262832, "PX Bulkstat: tkset relock: return" },
+{ 703262833, "PX Bulkstat: cannot stat vp .x" },
+{ 703262834, "PX Bulkstat: broken pipe: return" },
+{ 703262835, "PX BulkFetchStatus: fid .x..x..x..x, new offset .d, error .d" },
+{ 703262836, "PX Attempt to truncate via SETLENGTH, old .x, new .x" },
+{ 703262837, "PX StoreData: vp .x: Store of .d,,.u for .d will overrun new length of .d,,.u--returning EINVAL" },
+{ 703262838, "PX 64-bit host (.p) maxFileSize is .#x,,.#x" },
+{ 703262839, "PX 32-bit host (.p) maxFileSize is .#x,,.#x" },
+{ 703262840, "PX Lookup fid .x..x..x..x maps to volp .#x, vp .#x" },
+{ 703262841, "PX px_rdwr(rw=.d) decides on a big buffer (.d rather than .d)" },
+{ 703262842, "PX px_read asked vnop for .d bytes; got .d" },
+{ 703262843, "PX px_write asked PULL routine for .d bytes; got .d" },
+{ 703262844, "PX px_write calls VOPX_RDWR for .d bytes; resid .d, .d written; Length .d" },
+{ 703262845, "PX CheckFlags: inconsistent flags .#x: returning EINVAL." },
+{ 703262846, "PX CheckFlags: secondary call, flags .#x: returning EINVAL." },
+{ 703262847, "PX NameTagOK: tag .d nonzero (len .d, name `.s'); bad name." },
+{ 703262848, "PX FileNameOK: name ends with @sys (name `.s'); bad name." },
+{ 703262849, "PX FileNameOK: name contains slash (name `.s'); bad name." },
+{ 703262850, "PX SymLink: link codeset tag .d is not zero; returning EINVAL." },
+{ 703262851, "PX NameTagOK: file name has null first byte (tag .d, len .d); bad name." },
+{ 703262852, "PX FetchData Fid .x..x..x..x, Pos .d,,.u, Len .d, Flags .#x" },
+{ 703262853, "PX StoreData fid .x..x..x..x, mask .x, position .d,,.u, length .d" },
+{ 703262854, "PX StoreData from host without tokens fid .x..x..x..x, off .d,,.u len .d (getrights code = .d)" },
+{ 703262855, "PX Attempt to truncate via SETLENGTH, old .x,,.x, new .x,,.x" },
+{ 703262856, "PX Allowing FORCEDOWN revocations, princ .x, IP .x, ruid .d, flags .#x" },
+{ 703262857, "PX DIS-allowing FORCEDOWN revocations, princ .x, IP .x, ruid .d, flags .#x" },
+{ 703262858, "PX Quota Fid .x..x..x..x, op .d, Flags .x" },
+{ 703262859, "PX Quota returns .d" },
+{ 703262860, "PX SetContext returns .d" },
+{ 703262861, "PX Bulkstat: broken pipe (exception .d): return" },
+{ 703262862, "PX BulkFetchStatus: pipe broke (exception .d) while draining" },
+{ 703262863, "PX AFS_GetToken: returning volerr .d to somebody's TSR" },
+{ 703262864, "PX AFS_GetToken: returning volerr .d since they're new and not a renewal" },
+{ 703262865, "PX ClientHadFormerToken: too many tokens in tkset" },
+{ 703262866, "PX ClientHadFormerToken: error .d from GetFileRightsIgnoring" },
+{ 703262867, "PX ClientHadFormerToken: client .x had .x, and client asks for .x: return .d" },
+{ 703262868, "PX EvaluateWildcard: volp .x, turned fid .x..x..x..x into .x..x" },
+{ 703262869, "PX EvaluateWildcard: volp .x: failed on fid .x..x..x..x: code .d" },
+{ 703557633, "in .d" },
+{ 703557634, "Global mutex is initialized and locked" },
+{ 703557635, ".s: .s about to call rpc_register_dfs_server(tkn)" },
+{ 703557636, ".s: .s returned from rpc_register_dfs_server(tkn)" },
+{ 703557637, ".s: .s about to call rpc_register_dfs_server(rep)" },
+{ 703557638, ".s: .s returned from rpc_register_dfs_server(rep)" },
+{ 703557639, "Releasing the global mutex to allow background processing" },
+{ 703557640, "[.lu,,.lu: delay .lu secs: .s]" },
+{ 703557641, "[.lu,,.lu: renew .lu secs: .s]" },
+{ 703557642, "GetLVStatus calling AGOPEN" },
+{ 703557643, "GetLVStatus calling GETSTATUS" },
+{ 703557644, "GetLVStatus calling CLOSE" },
+{ 703557645, ".s: .s" },
+{ 703557646, "Interpreted vldb entry for .s .d reps, mySite=.d" },
+{ 703557647, "NeedSetVol figuring VV" },
+{ 703557648, "NeedSetVol TRUE: no lvp" },
+{ 703557649, "NeedSetVol TRUE: lvp ID .lu,,.lu not .lu,,.lu" },
+{ 703557650, "NeedSetVol TRUE: don't have lv states" },
+{ 703557651, "NeedSetVol TRUE: need set bits .#lx -> .#lx" },
+{ 703557652, "NeedSetVol TRUE: new tknExp time .lu..06lu -> .lu..06lu" },
+{ 703557653, "NeedSetVol TRUE: new Curr time .lu..06lu -> .lu..06lu" },
+{ 703557654, "NeedSetVol TRUE: new PingCurr time .lu..06lu -> .lu..06lu" },
+{ 703557655, "NeedSetVol: no change needed" },
+{ 703557656, "SetOpenVol calling SETVV" },
+{ 703557657, "SetOpenVol calling SYNC" },
+{ 703557658, "SetOpenVol: Set VV for .lu,,.lu: .s" },
+{ 703557659, "SetOpenVol calling GETSTATUS" },
+{ 703557660, "UpdateLocal: calling SetOpenVol" },
+{ 703557661, "UpdateLocal: calling CLOSE" },
+{ 703557662, "SetOpenVol returning .lu" },
+{ 703557663, "CheckSetOpenVol: calling SetOpenVol" },
+{ 703557664, "CheckSetOpenVol: returning .lu" },
+{ 703557665, "UpdateLocal calling AGOPEN" },
+{ 703557666, "UpdateLocal: returning .lu" },
+{ 703557667, "SetLVStatus calling AGOPEN" },
+{ 703557668, "SetLVStatus calling SETSTATUS to .#lx" },
+{ 703557669, "SetLVStatus calling CheckSetOpenVol" },
+{ 703557670, "SetLVStatus calling SYNC" },
+{ 703557671, "SetLVStatus: Set states for LV .lu,,.lu: .#lx" },
+{ 703557672, "SetLVStatus returning .d" },
+{ 703557673, "Destroying volume .lu,,.lu...." },
+{ 703557674, "Destroyvolume calling GETSTATUS" },
+{ 703557675, "DestroyVolume calling SETSTATUS" },
+{ 703557676, "DestroyVolume about to loop" },
+{ 703557677, "DestroyVolume calling CLOSE" },
+{ 703557678, "DestroyVolume returning .lu" },
+{ 703557679, "LoseWVT signals actNowCond" },
+{ 703557680, ".s: STKN_Probe() called" },
+{ 703557681, ".s: STKN_InitTokenState() called" },
+{ 703557682, ".s: STKN_InitTokenState about to get global lock" },
+{ 703557683, ".s: STKN_InitTokenState got global lock" },
+{ 703557684, ".s: STKN_InitTokenState released global lock and returns" },
+{ 703557685, ".s: STKN_TokenRevoke() called with .ld revocations" },
+{ 703557686, "STKN_TokenRevoke: calling LoseWVT, fid .s" },
+{ 703557687, ".s: STKN_GetCellName() called" },
+{ 703557688, ".s: STKN_GetCellName() returning .s" },
+{ 703557689, ".s: STKN_GetCellName() returning no-name" },
+{ 703557690, ".s: STKN_GetLock() called" },
+{ 703557691, ".s: STKN_GetCE() called" },
+{ 703557692, ".s" },
+{ 703557693, "GetToken result: .ld" },
+{ 703557694, "CloneAVolume called" },
+{ 703557695, "AG_VOLCREATE returns .ld, errno .d" },
+{ 703557696, "CloneAVolume calling AGOPEN(.d)" },
+{ 703557697, "CloneAVolume calling SETSTATUS" },
+{ 703557698, "CloneAVolume calling PUSHSTATUS" },
+{ 703557699, "CloneAVolume calling VolClone" },
+{ 703557700, "CloneAVolume calling SYNC(1)" },
+{ 703557701, "CloneAVolume calling CLOSE(1)" },
+{ 703557702, "CloneAVolume calling SYNC(2)" },
+{ 703557703, "CloneAVolume calling CLOSE(2)" },
+{ 703557704, "Getting dump for vol .lu,,.lu" },
+{ 703557705, "Incremental from version .lu,,.lu" },
+{ 703557706, "CompleteNewVol calling GETSTATUS" },
+{ 703557707, "CompleteNewVol calling SETSTATUS" },
+{ 703557708, "CompleteNewVol calling CheckSetOpenVol" },
+{ 703557709, "CompleteNewVol calling SYNC" },
+{ 703557710, "CompleteNewVol calling CLOSE" },
+{ 703557711, "ClearBackingID calling SETSTATUS" },
+{ 703557712, "ClearBackingID calling SYNC" },
+{ 703557713, "ClearBackingID calling CLOSE" },
+{ 703557714, "EliminateJunkVolume calling AGOPEN(2)" },
+{ 703557715, "EliminateJunkVolume calling VolUnClone" },
+{ 703557716, "EliminateJunkVolume calling SYNC(1)" },
+{ 703557717, "EliminateJunkVolume calling CLOSE(1)" },
+{ 703557718, "EliminateJunkVolume calling VolDestroy" },
+{ 703557719, "EliminateJunkVolume calling CLOSE(2)" },
+{ 703557720, "EliminateJunkVolume returned from CLOSE(2)" },
+{ 703557721, "CompleteAndSwitch calling AGOPEN(2)" },
+{ 703557722, "CompleteAndSwitch calling SetOpenVol" },
+{ 703557723, "CompleteAndSwitch calling SWAPVOLIDS" },
+{ 703557724, "CompleteAndSwitch calling GETSTATUS" },
+{ 703557725, "CompleteAndSwitch calling SYNC(1)" },
+{ 703557726, "CompleteAndSwitch calling SYNC(2)" },
+{ 703557727, "CompleteAndSwitch calling CLOSE(1)" },
+{ 703557728, "CompleteAndSwitch calling CLOSE(2)" },
+{ 703557729, "CompleteAndSwitch: Got states for LV .lu,,.lu: .#lx" },
+{ 703557730, "CheckWithVLDB signals actNowCond" },
+{ 703557731, "Found incomplete volume .lu,,.lu" },
+{ 703557732, "ProcessBundle() handles .d Attns." },
+{ 703557733, "BulkFetchVV result: .ld" },
+{ 703557734, "StartImporting(): .d replicas want attention" },
+{ 703557735, "[.lu,,.lu] Refreshing primary's last-call time" },
+{ 703557736, "GetTime result: .ld" },
+{ 703557737, "CheckVLDBRelationship signals actNowCond" },
+{ 703557738, ".s: REP_Probe called" },
+{ 703557739, ".s: REP_CheckReplicationConfig called" },
+{ 703557740, ".s: REP_AllCheckReplicationConfig called" },
+{ 703557741, ".s: REP_GetServerInterfaces called" },
+{ 703557742, "BundleKeepAlives: .d on this pass" },
+{ 703557743, "BundleKeepAlives(.lu,,.lu): calling .s: .ld fexs, .ld executing" },
+{ 703557744, "BundleKeepAlives: retval .ld" },
+{ 703557745, "PruneAndCheckKA(.lu,,.lu): from .lu to .lu used" },
+{ 703557746, ".s: ForceKeepAlive() called" },
+{ 703557747, "[.lu,,.lu] Freeing volChanged .lu,,.lu -> .lu,,.lu, .ld fids" },
+{ 703557748, "Background thread spawned: checking initialization mutex" },
+{ 703557749, "Background thread passed check on initialization mutex. Looping" },
+{ 703557750, "bkg: RenewTokens sleeps .ld secs" },
+{ 703557751, "bkg: StartImporting sleeps .ld secs" },
+{ 703557752, "bkg: ForceKeepAlives sleeps .ld secs" },
+{ 703557753, "bkg: DoWillCalls sleeps .ld secs" },
+{ 703557754, "bkg: ExpireVolChanges sleeps .ld secs" },
+{ 703557755, "Sleeping for .lu seconds (on actNowCond)" },
+{ 703557756, "bkg: now .lu, tgt .lu, .s: .s" },
+{ 703557757, ".s: REP_KeepFilesAlive called" },
+{ 703557758, "REP_KeepFilesAlive: got .lu fids, flags .lu" },
+{ 703557759, "Num/MaxKAs for .lu,,.lu: .lu, .lu (old max .lu)" },
+{ 703557760, "[.lu,,.lu] No vol for vsn .lu,,.lu" },
+{ 703557761, "[.lu,,.lu] Making a volChanged object from .lu,,.lu to .lu,,.lu" },
+{ 703557762, ".s: REP_GetRepStatus(.lu) called." },
+{ 703557763, "getVolChanged calling AGOPEN" },
+{ 703557764, "getVolChanged calling SCAN" },
+{ 703557765, "getVolChanged calling CLOSE" },
+{ 703557766, "getVolChanged after CLOSE" },
+{ 703557767, ".s: REP_GetVolChangedFiles called." },
+{ 703557768, ".s: REP_GetOneRepStatus called" },
+{ 703557769, ".s: REP_GetRepServerStatus called" },
+{ 703557770, "rep_doUpdate signals actNowCond" },
+{ 703557771, ".s: REP_UpdateSelf called" },
+{ 703557772, ".s: REP_Spare1 called" },
+{ 703557773, ".s: REP_Spare2 called" },
+{ 703557774, ".s: REP_Spare3 called" },
+{ 703557775, ".s" },
+{ 703557776, "Got an FLDB connection object" },
+{ 703557777, "can't deplete incomplete local vol .lu,,.lu: .s" },
+{ 703557778, "Found VLDB entry: .lu,,.lu" },
+{ 703557779, "...but we were already handling that one" },
+{ 703557780, "can't open local vol .lu,,.lu: .s" },
+{ 703557781, "can't get status for local vol .lu,,.lu: .s" },
+{ 703557782, "can't close local vol .lu,,.lu: .s" },
+{ 703557783, "can't destroy incomplete local vol .lu,,.lu: .s" },
+{ 703557784, "Got states for LV .lu,,.lu: .#lx" },
+{ 703557785, "can't close local vol .lu,,.lu after destroying it: .s" },
+{ 703557786, "LV .lu,,.lu is destroyed" },
+{ 703557787, ".s: .d aggregates to scan" },
+{ 703557788, ".s: skipping non-Episode aggregate .s, ID .ld, type .ld" },
+{ 703557789, ".s: scanning aggregate .s, ID .ld, type .ld" },
+{ 703557790, ".s: got a local volume to manage: id .lu,,.lu, name .s, states .#lx" },
+{ 703557791, ".s: done with scanning for local volumes. Rationalizing..." },
+{ 703557792, ".s: done rationalizing local volumes" },
+{ 703557793, ".s: adding .lu,,.lu due to discovered JUNK." },
+{ 703557794, ".s: attaching junk .lu,,.lu to rep .lu,,.lu" },
+{ 703557795, ".s: adding .lu,,.lu (.lu,,.lu) due to a discovered volume." },
+{ 703557796, "This machine has .d net address(es)." },
+{ 703557797, ".s" },
+{ 703557798, "DoWillCalls: connecting to .s" },
+{ 703557799, "DoWillCalls: cannot connect to .s; errno=.d" },
+{ 703557800, "DoWillCalls, flags .d: exception .s" },
+{ 703557801, "DoWillCalls: .s (.s) failed: .s" },
+{ 703557802, "Listening for net calls (calling rpc_server_listen)" },
+{ 703557803, "Starting the token-revocation listener thread" },
+{ 703557804, "Revocation socket is: inet/.s/.d" },
+{ 703557805, ".s: .d binding(s)" },
+{ 703557806, ".lu,,.lu: .s" },
+{ 703557807, ".s: No R/W site for fileset .s" },
+{ 703557808, "Release-style replicated fileset .s, rw=.lu,,.lu, ro=.lu,,.lu, with no R/O on primary!" },
+{ 703557809, "Interpreted vldb entry for .lu,,.lu (.s): .d reps, mySite=.d" },
+{ 703557810, "STKN_TokenRevoke: calling LoseWVT, fid .lu/.lu/.lu/.lu, id .lu,,.lu, type .#lx" },
+{ 703557811, "repq_Init(.#x)" },
+{ 703557812, "repq_Enter(.#x, .#x, .lu)" },
+{ 703557813, "repq_Enter returning .#x" },
+{ 703557814, "repq_Delete(.#x, .#x)" },
+{ 703557815, "repq_Delete: item is in use--deferring the delete" },
+{ 703557816, "repq_Delete returning" },
+{ 703557817, "repq_Get(.#x)" },
+{ 703557818, "repq_Get: queue is empty--waiting indefinitely" },
+{ 703557819, "repq_Get: waiting until .lu" },
+{ 703557820, "repq_Get returning .#x, *outCookieP=.#x" },
+{ 703557821, "repq_Put(.#x, .#x, .lu)" },
+{ 703557822, "repq_Delete: performing deferred delete" },
+{ 703557823, "repq_Put: setting deadline to .lu" },
+{ 703557824, "repq_Delete returning" },
+{ 703557825, "repq_ResetDeadline(.#x, .#x, .lu)" },
+{ 703557826, "repq_ResetDeadline: item is in use" },
+{ 703557827, "repq_ResetDeadline returning" },
+{ 703557828, "repq: waking up waiters" },
+{ 703557829, "reph_GetHost(.s, .lu, .s)" },
+{ 703557830, "reph_GetHost returning .#x" },
+{ 703557831, "reph_PutHost(.#x [.s])" },
+{ 703557832, "reph_GetConn(.#x [.s], .lu)" },
+{ 703557833, "reph_GetConn returning .lu, *outConnPP=.#x" },
+{ 703557834, "reph_ResetConn(.#x [.s], .#x, .lu)" },
+{ 703557835, "reph_ResetConn: failed to refresh auth context, code=.ld" },
+{ 703557836, "reph_ResetConn: reset failed, code=.ld" },
+{ 703557837, "reph_ResetConn returning .lu, *callersConnPP=.#x" },
+{ 703557838, "reph_PutConn(.#x)" },
+{ 703557839, "reph_PutConn: losing last reference--destroying connection" },
+{ 703557840, "reph_MergeSuccess: last success at .lu" },
+{ 703557841, "SetNewConn(.#x [.s], .#x, .lu)" },
+{ 703557842, "SetNewConn: Waiting for racing set context" },
+{ 703557843, "SetNewConn returning .lu, *connPP=.#x" },
+{ 703557844, "SetNewConn: Trying another address (#.lu), reason=.lu" },
+{ 703557845, "SetContext(.#x [.s], .#x)" },
+{ 703557846, "SetContext returning .lu" },
+{ 703557847, "REP_KeepFilesAlive: cell .lu,,.lu, vol .lu,,.lu, [.d...d)" },
+{ 703557848, "REP_KeepFilesAlive: matched replica .#lx" },
+{ 703557849, "BundleKeepAlives: adding .x..x..x..x with dally .d, exec .d" },
+{ 703557850, "BundleKeepAlives: .d,,.d (.x, .x) sent, flags now .#lx" },
+{ 703557851, "BundleKeepAlives: .d,,.d (.x, .x) reduces next-call time to .d;" },
+{ 703557852, "....got req at .d, dally .d secs, last sent at .d" },
+{ 703557853, "StartImporting rp=.#lx look=.lu flags=.#lx" },
+{ 703557854, "WantsAdvance look=.lu now=.lu" },
+{ 703557855, "WantsAdvance know VLDB" },
+{ 703557856, "WantsAdvance junked, deleted or zapped done" },
+{ 703557857, "WantsAdvance eliminated junk" },
+{ 703557858, "WantsAdvance (A) P=.#lx" },
+{ 703557859, "WantsAdvance (B) B=.#lx" },
+{ 703557860, "WantsAdvance (F) (M) P=.lx" },
+{ 703557861, "WantsAdvance (I) (J) WVTLeft=.#lx,.#lx now=.lu look=.lu" },
+{ 703557862, "WantsAdvance have WVT, ok start P=.#lx B=.#lx" },
+{ 703557863, "WantsAdvance (G) next=.lu" },
+{ 703557864, "WantsAdvance maybe no WVT look=.lu next=.lu" },
+{ 703557865, "WantsAdvance bottom next=.lu" },
+{ 703557866, "CloneLocalReplica: opened R/W .lu,,.lu as .d: getting status" },
+{ 703557867, "CloneLocalReplica: got R/W .lu,,.lu status; problem states = .#lx" },
+{ 703557868, "CloneLocalReplica: R/W .lu,,.lu, Pub=.#lx; cloning/recloning." },
+{ 703557869, "CloneLocalReplica: R/W .lu,,.lu; clone/reclone done; getting stat of R/O .lu,,.lu" },
+{ 703557870, "CloneLocalReplica: fixing states of R/O .lu,,.lu, from .#lx to .#lx" },
+{ 703557871, "recordCaller(SREP_.s): inq_auth_caller failed with .d" },
+{ 703557872, "recordCaller(SREP_.s): called us .s, with svc .d, level .d" },
+{ 703557873, "getPrincName(.x): got .s (from primary for .s)." },
+{ 703557874, "getPrincName(.x): err .d from VL_GetSiteInfo." },
+{ 703557875, "getPrincName(.x): got .s from FLDB." },
+{ 703557876, "DoWillCalls: cannot connect to .s; cannot get correct principal" },
+{ 703557877, "DoWillCalls: cannot connect to .s with princ '.s'; auth code .d" },
+{ 703557878, "getPrincName(.x): re-validates old entry '.s'." },
+{ 703557879, "STKN_TokenRevoke: declining revocation, fid .lu/.lu/.lu/.lu, token id .lu,,.lu, attempted .#x, keeping .#x" },
+{ 703557880, "GetNewAuthn: host .x, .s, old level .d, code .d:" },
+{ 703557881, "GetNewAuthn: Authmask .#x -> .#x; no possible authn level!" },
+{ 703557882, "GetNewAuthn: Authmask .#x -> .#x; going from .d to .d." },
+{ 703557883, "(reph_GetConn conn at .#x has type .d, authn .d)" },
+{ 703705089, "ERR: .s" },
+{ 703705090, "INF: .s" },
+{ 703705091, ".s" },
+{ 703705092, "OSI cred to pag .x" },
+{ 703705093, "OSI cred to thread pag .x tid .x" },
+{ 703705094, "OSI setpag err .d, parm1 .x parm2 .x" },
+{ 703705095, "OSI install pag .x" },
+{ 703705096, "OSI install thread pag .x tid .x" },
+{ 703705097, "OSI set pag .x" },
+{ 703705098, "OSI set thread pag .x tid .x" },
+{ 703705099, "OSI set thread unauth tid .x" },
+{ 703705100, "OSI reset pag" },
+{ 703705101, "OSI reset thread pag, tid .x" },
+{ 703873025, "TKM gettoken fid .#x..#x..#x..#x flags .#x type .#x..#x for host .#x" },
+{ 703873026, "TKM return token fid .#x..#x..#x..#x TID ..#x..#x rights .#x..#x" },
+{ 703873027, "TKM async grant host .#x, TID .#x..#x, reqID .#x" },
+{ 703873028, "TKM async done, code .d" },
+{ 703873029, "TKM revoke start: conflictq .#x host .#x, .d tokens" },
+{ 703873030, "TKM revoke: hshost revoke returns conflictq .#x host .#x code .d" },
+{ 703873031, "TKM revoke refused, token id .#x..#x, revoke .#x,.#x, refused .#x,.#x, refused time .#x" },
+{ 703873032, "TKM revoke success, token id .#x..#x, revoke .#x..#x" },
+{ 703873033, "TKM revoke complete conflictq .#x, host .#x, code .#x" },
+{ 703873034, "TKM Started periodic token cleanup at .d" },
+{ 703873035, "TKM Finished periodic token cleanup at .d" },
+{ 703873036, "TKM Adjusting expiration time to .d" },
+{ 703873037, "TKM Started token GC at .d" },
+{ 703873038, "TKM GC ended with only .d tokens free" },
+{ 703873039, "TKM looking at GC candidate .#x..#x" },
+{ 703873040, "TKM will GC .#x..#x expiration .d" },
+{ 703873041, "TKM GetRights host .#x fid .#x..#x..#x..#x (range .#x..#x -> .#x..#x)" },
+{ 703873042, "TKM gettoken back, code .d, type .#x..#x, TID .#x..#x" },
+{ 703873043, "TKM DeleteConflictQ(.#x)" },
+{ 703873044, "TKM Remove Conflict token id .#x..#x from Q .#x returns ix .d" },
+{ 703873045, "TKM Add Conflict 1 to Q .#x, token id .#x..#x, host .#x, revoke .#x" },
+{ 703873046, "TKM Add Conflict 2 token id .#x..#x, slice grant .#x, last refused rights .#x at time .#x" },
+{ 703873047, "" },
+{ 703873048, "TKM gettoken byte range is (.#x,,.#x -> .#x,,.#x)" },
+{ 703873049, "TKM getvoltoken volume .#x..#x, token type .#x, flags .#x, granted volume token mask .#x, granted file token mask .#x" },
+{ 703873050, "TKM parallel revoke start, conflictq .#x, revoke count .d, flags .d" },
+{ 703873051, "TKM parallel revoke empty conflictq .#x" },
+{ 703873052, "TKM parallel revoke preproceess conflictq .#x, code .d" },
+{ 703873053, "TKM parallel revoke after preprocess empty conflictq .#x" },
+{ 703873054, "TKM parallel revoke end, conflictq .#x, code .d" },
+{ 703873055, "TKM parallel revoke invoke revoke threads conflictq .#x, this revoke count .d" },
+{ 703873056, "TKM preprocess conflictq .#x, token id .#x..#x, to revoke .#x, revocation of .#x last denied at time .#x" },
+{ 703873057, "TKM gettoken endRange truncated to .#x,,.#x" },
+{ 703873058, "TKM AdjustAccepted: no internal token for client ID .#x..#x, bits .#x--dropping token" },
+{ 703873059, "TKM AdjustAccepted: client ID .#x..#x not internal .#x..#x (client bits .#x, our bits .#x)--dropping token" },
+{ 703873060, "TKM AdjustAccepted: ID .#x..#x: accepted bits .#x more than ours .#x--dropping extras" },
+{ 703873061, "TKM begin doGC" },
+{ 703873062, "TKM end doGC, reclaimed .d out of .d tkns in .d secs" },
+{ 703873063, "TKM TryAsyncGrantsOnList: Processing queued grants list .#x against revoked types .#x" },
+{ 703873064, "TKM AsyncGrantThread: Starting to process asyncTryQ .#x" },
+{ 703873065, "TKM ClearAsyncGrants: Clearing out async grants for volId .lu,,.lu" },
+{ 703873066, "TKM ClearAsyncGrants: Volume .#x: Cleared .d tokens on file lists and .d tokens on volume list" },
+{ 703873067, "TKM .s" },
+{ 703889409, "tpq_Init: minThreads=.d, medMaxThreads=.d, highMaxThreads=.d, threadEnnui=.d" },
+{ 703889410, "tpq_Init: returns pool pointer .x" },
+{ 703889411, "tpq_Adjust: poolHandle=.x, flags=.x . . ." },
+{ 703889412, "tpq_Adjust: minThreads=.d, medMaxThreads=.d, highMaxThreads=.d, threadEnnui=.d" },
+{ 703889413, "(tpq) CreatePoolEntry(.x) entered" },
+{ 703889414, "(tpq) CreatePoolEntry: created thread for thread pool .x, entry=.x" },
+{ 703889415, "tpq_GrowThreadPool(.x, .d, entryPP)" },
+{ 703889416, "tpq_GrowThreadPool: okay to create thread for pool .x" },
+{ 703889417, "tpq_ShutdownPool(.x) called" },
+{ 703889418, "tpq_ShutdownPool(.x) completed" },
+{ 703889419, "tpq_HelperDie(.x, .x) called" },
+{ 703889420, "tpq_GCThreads(.x) called" },
+{ 703889421, "tpq_GCThreads(.x): tell entry .x to die" },
+{ 703889422, "tpq_DispatcherThread(.x) started" },
+{ 703889423, "tpq_DispatcherThread(.x) ready to run .x, priority=.d, graceExpired=.d" },
+{ 703889424, "tpq_DispatcherThread(.x) has thread to run .x, thread=.x" },
+{ 703889425, "tpq_DispatcherThread(.x) sleep with interval=.d" },
+{ 703889426, "tpq_DispatcherThread(.x) awake!!" },
+{ 703889427, "tpq_DispatcherThread(.x) rest in peace" },
+{ 703889428, "tpq_WakeDispatcher(.x) called" },
+{ 703889429, "tpq_HelperThread(.x) for pool .x started" },
+{ 703889430, "tpq_HelperThread(.x) I'm dying <gasp>" },
+{ 703889431, "tpq_HelperThread(.x) found .x on my private queue (pool=.x)" },
+{ 703889432, "tpq_HelperThread(.x) .x done, reschedule interval = .d" },
+{ 703889433, "tpq_HelperThread(.x) checking queues" },
+{ 703889434, "tpq_HelperThread(.x) found .x to run" },
+{ 703889435, "tpq_HelperThread(.x) .x done, reschedule interval = .d" },
+{ 703889436, "tpq_HelperThread(.x) (pool .x) to sleep: perchance to dream" },
+{ 703889437, "(tpq) EnqueueEntry(.x, .x) called, priority = .d, grace period = .d" },
+{ 703889438, "tpq_QueueRequest(pool=.x, op=.x, arg=.x, priority=.d, ..." },
+{ 703889439, " gracePeriod=.d, resched=.d, dropDead=.d)" },
+{ 703889440, "tpq_DequeueRequest(pool=.x, entry=.x)" },
+{ 703889441, "(tpq) GCQueue(pool=.x, priority=.d, now=.d)" },
+{ 703889442, "tpq_FindQueue(pool=.x, priority=.d, now=.d, ...)" },
+{ 703889443, "tpq_FindQueue(pool=.x,...) returns nextExpired=.d, graceExpired=.d, entry=.x" },
+{ 703889444, "tpq_SetRescheduleInterval(entry=.x, old=.d, new=.d)" },
+{ 703889445, "tpq_HelperThread(.x) for pool .x: waiting for initial lock" },
+{ 703889446, "tpq_HelperThread(.x) for pool .x: lock released" },
+{ 704008193, "END .s .d" },
+{ 704008194, "ag_ufsHold(aggrp=0x.x refCount=.d)" },
+{ 704008195, "ag_ufsRele(aggrp=0x.x refCount=.d)" },
+{ 704008196, "IN ag_ufsLock(aggrp=0x.x type=.d)" },
+{ 704008197, "IN ag_ufsUnlock(aggrp=0x.x)" },
+{ 704008198, "IN ag_ufsStat(aggrp=0x.x)" },
+{ 704008199, "IN ag_ufsVolCreate(flags=0x.x)" },
+{ 704008200, "IN ag_ufsVolinfo(index=.d)" },
+{ 704008201, "IN ag_ufsDetach()" },
+{ 704008202, "IN ag_ufsAttach()" },
+{ 704008203, " ag_ufsAttach: usa_mountedon='.s'" },
+{ 704008204, "ag_ufsSync() = 0" },
+{ 704008205, "IN vol_ufsHold(volp=0x.x v_count=.d)" },
+{ 704008206, "IN vol_ufsRele(volp=0x.x v_count=.d)" },
+{ 704008207, "IN vol_ufsLock(volp=0x.x type=.d)" },
+{ 704008208, "IN vol_ufsUnlock(volp=0x.x type=.d)" },
+{ 704008209, "IN vol_ufsOpen(volp=0x.x type=.d errorType=.d)" },
+{ 704008210, " vol_ufsOpen(concurrency=.d)" },
+{ 704008211, "IN vol_ufsSeek(volp=0x.x position=.d)" },
+{ 704008212, "IN vol_ufsTell(volp=0x.x handlerp=ox.x)" },
+{ 704008213, "IN vol_ufsScan(volp=0x.x position=.d)" },
+{ 704008214, "IN vol_ufsClose(volp=0x.x isabort=.d)" },
+{ 704008215, "vol_ufsDeplete(volp=0x.x v_count=.d) = EINVAL" },
+{ 704008216, "vol_ufsDestroy(volp=0x.x v_count=.d) = EINVAL" },
+{ 704008217, "IN vol_ufsAttach(volp=0x.x ta=0x.x)" },
+{ 704008218, "IN vol_ufsDetach(volp=0x.x)" },
+{ 704008219, "IN vol_ufsGetStatus(volp=0x.x statusp=0x.x)" },
+{ 704008220, "IN vol_ufsSetStatus(volp=0x.x mask=0x.x)" },
+{ 704008221, "IN vol_ufsCreate(volp=0x.x position=.d xvattrp=0x.x)" },
+{ 704008222, "IN vol_ufsRead(volp=0x.x fid=.x..x..x..x position=.d,,.d len=.d)" },
+{ 704008223, "IN vol_ufsWrite(volp=0x.x fid=.x..x..x..x position=.d,,.d len=.d)" },
+{ 704008224, "IN vol_ufsReadHole(volp=0x.x fid=.x..x..x..x readHoleP=0x.x)" },
+{ 704008225, "IN vol_ufsTruncate(volp=0x.x fid=.x..x..x..x newsize=.d,,.d)" },
+{ 704008226, "IN vol_ufsDelete(volp=0x.x fid=.x..x..x..x)" },
+{ 704008227, "IN vol_ufsGetattr(volp=0x.x fid=.x..x..x..x xvattrp=0x.x)" },
+{ 704008228, "IN vol_ufsSetattr(volp=0x.x fid=.x..x..x..x xvattrp=0x.x)" },
+{ 704008229, "IN vol_ufsGetAcl(volp=0x.x fid=.x..x..x..x aclp=0x.x)" },
+{ 704008230, "IN vol_ufsSetAcl(volp=0x.x fid=.x..x..x..x aclp=0x.x)" },
+{ 704008231, "vol_ufsClone(volp=0x.x vol2_p=0x.x) = EINVAL" },
+{ 704008232, "vol_ufsReclone(volp=0x.x vol2_p=0x.x) = EINVAL" },
+{ 704008233, "vol_ufsUnclone(volp=0x.x vol2_p=0x.x) = EINVAL" },
+{ 704008234, "IN vol_ufsVget(volp=0x.x fid=.x..x..x..x)" },
+{ 704008235, "IN vol_ufsRoot(volp=0x.x)" },
+{ 704008236, "vol_ufsIsRoot(volp=0x.x fid=.x..x..x..x flag=.d)" },
+{ 704008237, "vol_ufsGetVV(volp=0x.x vv=.d,,.d)" },
+{ 704008238, "IN vol_ufsSetDyStat(volp=0x.x vsp=0x.x)" },
+{ 704008239, "vol_ufsSetNewVID(volp=0x.x newid=.d,,.d)" },
+{ 704008240, "vol_ufsCopyAcl(volp=0x.x Fid=.x..x..x..x destw=.d index=.d) = ENOTTY" },
+{ 704008241, "IN vol_ufsFreeDyStat(volp=0x.x fsDatap=0x.x)" },
+{ 704008242, "vol_ufsConcurr(volp=0x.x type=.d errorType=.d *concurr=.d)" },
+{ 704008243, "vol_ufsSwapIDs(vol1p=0x.x vol1->volID=.d,,.d vol2_p=0x.x vol2->volID=.d,,.d)" },
+{ 704008244, "vol_ufsSync(volp=0x.x volId=.d,,.d guarantee=.d)" },
+{ 704008245, "vol_ufsPushStatus(volp=0x.x volId=.d,,.d)" },
+{ 704008246, "vol_ufsReaddir(volp=0x.x volId=.d,,.d)" },
+{ 704008247, "vol_ufsAppenddir(volp=0x.x volId=.d,,.d)" },
+{ 704008248, "vol_ufsGetZLC(volp=0x.x volId=.d,,.d iterP=0x.x VpP=0x.x)" },
+{ 704008249, "IN vol_ufsGetNextHoles(volp=0x.x volId=.d,,.d)" },
+{ 704008250, "vol_ufsBulkSetStatus(arrayLen=.d statusArray=.x) = EINVAL" },
+{ 704008251, "END ag_ufsLock() .d" },
+{ 704008252, "END ag_ufsUnlock() .d" },
+{ 704008253, "END ag_ufsStat() .d" },
+{ 704008254, "END ag_ufsVolCreate() .d" },
+{ 704008255, "END ag_ufsVolInfo(): index != 1: .d" },
+{ 704008256, "END ag_ufsVolInfo(): no volume: .d" },
+{ 704008257, "END ag_ufsVolInfo(): .d" },
+{ 704008258, "END ag_ufsDetach(): .d" },
+{ 704008259, "END ag_ufsAttach(): code .d from osi_copyin()" },
+{ 704008260, "END ag_ufsAttach(): code .d from osi_lookupname()" },
+{ 704008261, "END ag_ufsAttach(): MOUNT_UFS (.d) != vfs_mtype (.d)" },
+{ 704008262, "END ag_ufsAttach(): returning EINVAL (.d)" },
+{ 704008263, "END ag_ufsAttach(): returning 0" },
+{ 704008264, "END vol_ufsHold()" },
+{ 704008265, "END vol_ufsRele()" },
+{ 704008266, "END vol_ufsLock(): .d" },
+{ 704008267, "END vol_ufsUnlock(): .d" },
+{ 704008268, "END vol_ufsOpen(): .d" },
+{ 704008269, "END vol_ufsSeek(): .d" },
+{ 704008270, "END vol_ufsTell(): 0" },
+{ 704008271, "END vol_ufsScan(): vol_ufsSeek returns .d" },
+{ 704008272, "END vol_ufsScan(): .d" },
+{ 704008273, "END vol_ufsClose(): 0" },
+{ 704008274, "END vol_ufsAttach(): no v_paggrp so returning .d" },
+{ 704008275, "END vol_ufsAttach(): 0" },
+{ 704008276, "END vol_ufsDetach(): .d" },
+{ 704008277, "END vol_ufsGetStatus(): ag_ufsStat returns .d" },
+{ 704008278, "END vol_ufsGetStatus(): 0" },
+{ 704008279, "END vol_ufsSetStatus(): .d" },
+{ 704008280, "END vol_ufsCreate(): vol_ufsDelete returns .d" },
+{ 704008281, "END vol_ufsCreate(): vol_ufsScan returns .d" },
+{ 704008282, "END vol_ufsCreate(): vol_ufsCreate_mach returns .d" },
+{ 704008283, "END vol_ufsRead(): VOL_VGET returns .d" },
+{ 704008284, "END vol_ufsRead(): .d" },
+{ 704008285, "END vol_ufsWrite(): VOL_VGET returns .d" },
+{ 704008286, "END vol_ufsWrite(): .d" },
+{ 704008287, "END vol_ufsReadHole(): .d" },
+{ 704008288, "END vol_ufsTruncate(): VOL_VGET returns .d" },
+{ 704008289, "END vol_ufsTruncate(): .d" },
+{ 704008290, "END vol_ufsDelete(): .d" },
+{ 704008291, "END vol_ufsGetattr(): VOL_VGET returns .d" },
+{ 704008292, "END vol_ufsGetattr(): .d" },
+{ 704008293, "END vol_ufsSetattr(): VOL_VGET returns .d" },
+{ 704008294, "END vol_ufsSetattr(): .d" },
+{ 704008295, "END vol_ufsGetAcl(): VOL_VGET returns .d" },
+{ 704008296, "END vol_ufsGetAcl(): .d" },
+{ 704008297, "END vol_ufsSetAcl(): VOL_VGET returns .d" },
+{ 704008298, "END vol_ufsSetAcl(): .d" },
+{ 704008299, "END vol_ufsVget(): .d" },
+{ 704008300, "END vol_ufsRoot(): VFSX_ROOT returns a null pointer: .d" },
+{ 704008301, "END vol_ufsRoot(): .d" },
+{ 704008302, "END vol_ufsSetDyStat(): 0" },
+{ 704008303, "END vol_ufsFreeDyStat(): 0" },
+{ 704008304, "END vol_ufsReaddir(): VOL_VGET returns .d" },
+{ 704008305, "END vol_ufsReaddir(): .d" },
+{ 704008306, "END vol_ufsAppenddir(): VOL_VGET returns .d" },
+{ 704008307, "END vol_ufsAppenddir(): .d" },
+{ 704008308, "END vol_ufsGetNextHoles(): VOL_VGET returns .d" },
+{ 704008309, "END vol_ufsGetNextHoles(): .d" },
+{ 704008310, "IN vol_ufsReadPurgeHole(volp=0x.x fid=.x..x..x..x readHoleP=.#x)" },
+{ 704008311, "END vol_ufsReadPurgeHole(): .d" },
+{ 704008312, "form GPFS fid: .#x, .#x, .#x" },
+{ 704028673, "ubik_ServerInit(myHost=0x.x, nsGroupP=.s, secGroupP=.s, pathName=.s) entered" },
+{ 704028674, "ubik_ServerInit returns (errorcode=.ld)" },
+{ 704028675, "ubik_GetServerList returns (groupName=.s, groupSize=.ld, errorcode=.ld)" },
+{ 704028676, "ContactQuorum (host=.s, func=0x.x, transPtr=0x.x)" },
+{ 704028677, "ContactQuorum(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028678, "ubik_BeginTrans (transMode=.ld)" },
+{ 704028679, "ubik_BeginTrans returns (transPtr=0x.x, errorcode=.ld)" },
+{ 704028680, "ubik_AbortTrans (transPtr=0x.x)" },
+{ 704028681, "ubik_AbortTrans(transPtr=0x.x) returns( errorcode=.ld)" },
+{ 704028682, "ubik_EndTrans (transPtr=0x.x)" },
+{ 704028683, "ubik_EndTrans(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028684, "ubik_Read (transPtr=0x.x, buffer=0x.x, length=.ld)" },
+{ 704028685, "ubik_Read(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028686, "ubik_Write (transPtr=0x.x, buffer=0x.x, length=.ld)" },
+{ 704028687, "ubik_Write(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028688, "ubik_Seek (transPtr=0x.x, fileid=.ld, position=.ld)" },
+{ 704028689, "ubik_Seek(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028690, "ubik_Tell (transPtr=0x.x)" },
+{ 704028691, "ubik_Tell(transPtr=0x.x) returns (fileid=.ld, position=.ld)" },
+{ 704028692, "ubik_Truncate (transPtr=0x.x, length=.ld)" },
+{ 704028693, "ubik_Truncate(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028694, "ubik_SetLock (transPtr=0x.x, position=.ld, length=.ld, type=.ld)" },
+{ 704028695, "ubik_SetLock(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028696, "ubik_WaitVersion (our version .ld..ld, wait for .ld..ld)" },
+{ 704028697, "ubik_thrPoolLookup, use ubik thread pool" },
+{ 704028698, "ubik_thrPoolLookup, use default thread pool" },
+{ 704028699, "SUBIKDISK_GetServerInterfaces (handle=0x.x)" },
+{ 704028700, "SUBIKDISK_GetServerInterfaces(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028701, "SUBIKDISK_Begin (handle=0x.x, transId .ld..ld)" },
+{ 704028702, "SUBIKDISK_Beginx(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028703, "SUBIKDISK_Commit (handle=0x.x, transId .ld..ld)" },
+{ 704028704, "SUBIKDISK_Commit(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028705, "SUBIKDISK_ReleaseLocks (handle=0x.x, transId .ld..ld)" },
+{ 704028706, "SUBIKDISK_ReleaseLocks(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028707, "SUBIKDISK_Abort (handle=0x.x, transId .ld..ld)" },
+{ 704028708, "SUBIKDISK_Abort(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028709, "SUBIKDISK_Lock (handle=0x.x, transId .ld..ld)" },
+{ 704028710, "SUBIKDISK_Lock (file=.ld, pos=.ld, len=.ld, type=.ld)" },
+{ 704028711, "SUBIKDISK_Lock(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028712, "SUBIKDISK_Write (handle=0x.x, transId .ld..ld)" },
+{ 704028713, "SUBIKDISK_Write (file=.ld, pos=.ld, len=.ld, buffer=0x.x)" },
+{ 704028714, "SUBIKDISK_Write(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028715, "SUBIKDISK_Truncate (handle=0x.x, transId .ld..ld)" },
+{ 704028716, "SUBIKDISK_Truncate (file=.ld, len=.ld)" },
+{ 704028717, "SUBIKDISK_Truncate(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028718, "SUBIKDISK_GetVersion (handle=0x.x)" },
+{ 704028719, "SUBIKDISK_GetVersion(handle=0x.x) returns (version .ld..ld, errorcode=.ld)" },
+{ 704028720, "SUBIKDISK_GetFile (handle=0x.x, file=.ld, pipe=0x.x)" },
+{ 704028721, "SUBIKDISK_GetFile(handle=0x.x) returns (version .ld..ld, errorcode=.ld)" },
+{ 704028722, "SUBIKDISK_SendFile (handle=0x.x, file=.ld, len=.ld, pipe=0x.x)" },
+{ 704028723, "SUBIKDISK_SendFile (version .ld..ld)" },
+{ 704028724, "SUBIKDISK_SendFile(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028725, "SUBIKDISK_Probe (handle=0x.x)" },
+{ 704028726, "SUBIKVOTE_GetServerInterfaces (handle=0x.x)" },
+{ 704028727, "SUBIKVOTE_Beacon (host=.s, state=.ld, start=.ld)" },
+{ 704028728, "SUBIKVOTE_Beacon (version .ld..ld, transId .ld..ld)" },
+{ 704028729, "SUBIKVOTE_Beacon host .s not found in configuration, vote=.d" },
+{ 704028730, "SUBIKVOTE_Beacon host .s not lowest, lowest host .s, vote=.d" },
+{ 704028731, "SUBIKVOTE_Beacon host .s not sync site, sync site .s,vote=.d" },
+{ 704028732, "SUBIKVOTE_Beacon(host=.s) returns (vote=.ld, errorcode=.ld)" },
+{ 704028733, "SUBIKVOTE_Beacon(handle=0x.x) returns (host=.s, errorcode=.ld)" },
+{ 704028734, "recovery running on host .s in state 0x.x" },
+{ 704028735, "recovery marking host .s as up" },
+{ 704028736, "recovery running on sync site, state 0x.x" },
+{ 704028737, "recovery got bad db version .ld..ld from server .s" },
+{ 704028738, "recovery failed to get version from server .s, errorcode=.ld" },
+{ 704028739, "recovery found best db version .ld..ld on server .s" },
+{ 704028740, "recovery failed to find best db, replies=.ld, errorcode=.ld" },
+{ 704028741, "recovery fetching database version .ld..ld from server .s" },
+{ 704028742, "recovery fetched db version .ld..ld, errorcode=.ld" },
+{ 704028743, "recovery already has latest db version .ld..ld, state 0x.x" },
+{ 704028744, "recovery labelling db .ld..ld, errocode=.ld" },
+{ 704028745, "recovery sending db to .s, errorcode=.ld" },
+{ 704028746, "recovery aborting all open transactions" },
+{ 704028747, "recovery noticed server going down, db to be sent on wake up" },
+{ 704028748, "recovery detected transaction mismatch; current transId.ld..ld, incoming transId .ld..ld, aborting current transaction" },
+{ 704028749, "received vote .ld from server .s, errorcode=.ld" },
+{ 704028750, "received .ld votes from .ld servers" },
+{ 704028751, "udisk_LogOpcode (opcode=.ld, sync=.ld)" },
+{ 704028752, "udisk_LogEnd (version .ld..ld)" },
+{ 704028753, "udisk_LogTruncate (file=.ld, length=.ld)" },
+{ 704028754, "udisk_LogWriteData (file=.ld, buffer=0x.x, pos=.ld, len=.ld)" },
+{ 704028755, "udisk_read (trans=0x.x)" },
+{ 704028756, "udisk_read (file=.ld, buffer=0x.x, pos=.ld, len=.ld)" },
+{ 704028757, "udisk_truncate (trans=0x.x, file=.ld, len=.ld)" },
+{ 704028758, "udisk_write (trans=0x.x)" },
+{ 704028759, "udisk_write (file=.ld, buffer=0x.x, pos=.ld, len=.ld)" },
+{ 704028760, "udisk_begin (type=.ld)" },
+{ 704028761, "udisk_begin returns (trans=0x.x)" },
+{ 704028762, "udisk_commit (trans=0x.x)" },
+{ 704028763, "udisk_abort (trans=0x.x)" },
+{ 704028764, "udisk_end (trans=0x.x)" },
+{ 704028765, "udisk_begin setting DBWRITING bit; flags 0x.x" },
+{ 704028766, "udisk_begin unsetting DBWRITING bit; flags 0x.x" },
+{ 704028767, "ulock_SetLock (trans=0x.x)" },
+{ 704028768, "ulock_SetLock (pos=.ld, len=.ld, type=.ld, wait=.ld)" },
+{ 704028769, "ulock_ReleaseAllLocks (trans=0x.x)" },
+{ 704028770, "ubik low level lock attempt to hold" },
+{ 704028771, "ubik low level lock held" },
+{ 704028772, "ubik low level lock attempt to release" },
+{ 704028773, "ubik low level lock released" },
+{ 704028774, "ubik version lock attempt to hold" },
+{ 704028775, "ubik version lock held" },
+{ 704028776, "ubik version lock attempt to release" },
+{ 704028777, "ubik version lock released" },
+{ 704028778, "ubik_sleep waiting for writer to finish; flags 0x.x" },
+{ 704028779, "upipe_FilePull reading=.ld, read=.ld, errorcode=.ld" },
+{ 704028780, "upipe_FilePush writing=.ld, wrote=.ld, errorcode=.ld" },
+{ 704028781, "ubik RPC generated exception .s, in file .s at line .ld" },
+{ 704028782, "upipe_FilePull entered" },
+{ 704028783, "upipe_FilePull exit, read .ld bytes" },
+{ 704028784, "upipe_FilePush entered, .ld bytes requested" },
+{ 704028785, "upipe_FilePush exit" },
+{ 704028786, "failed to queue a concurrent beacon RPC" },
+{ 704028787, "failed to begin concurrent beacons" },
+{ 704028788, "failed to queue a concurrent probe RPC" },
+{ 704028789, "failed to begin concurrent probes" },
+{ 704028790, "clock skew .ld between servers too high" },
+{ 704028791, "original server count .ld, tallied .ld, count from namespace .ld" },
+{ 704028792, "failed to queue request that keeps name space and configuration in sync" },
+{ 704028793, "caller not part of configuration, result of verification: .s" },
+{ 704028794, "bump tid counter by .d" },
+{ 704028795, "calling urecovery_CheckTid from .s" },
+{ 704028796, "write trans has to wait for existing writer" },
+{ 704028797, "writer has exited, go ahead and do the write" },
+{ 704028798, "wakeup the sleeping writer" },
+{ 704028799, "writer has exited, go ahead and propagate the database" },
+{ 704028800, "ShouldIRun: Yes; no known sync site (lastYes vote given at .lu)" },
+{ 704028801, "ShouldIRun: No; .#lx claimed to be sync (.ld) at time .ld" },
+{ 704028802, "ShouldIRun: No; .#lx is available and lower than us (.#lx)" },
+{ 704028803, "ShouldIRun: Yes; nobody better than us now" },
+{ 704028804, "uvote_ResetState: Resetting our configuration" },
+{ 704028805, "SUBIKDISK_Probe exit (code=.ld)" },
+{ 704028806, "sending probe to host .s" },
+{ 704028807, "probe to host .s failed, code= .ld" },
+{ 704028808, "ubik_Flush (transPtr=0x.x)" },
+{ 704028809, "ubik_Flush(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028810, "SUBIKDISK_BulkUpdate (handle=0x.x, transId .ld..ld)" },
+{ 704028811, "SUBIKDISK_BulkUpdate (uop=.ld, arg1=.ld, arg2=.ld, arg3=.ld," },
+{ 704028812, " arg4=.ld, length=.ld, data=0x.x)" },
+{ 704028813, "SUBIKDISK_BulkUpdate(handle=0x.x) returns (errorcode=.ld)" },
+{ 704028814, "DiskRpcCall (host=.s, func=0x.x, transPtr=0x.x)" },
+{ 704028815, "DiskRpcCall(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028816, "ContactQuorum (func=0x.x, transPtr=0x.x, pver=.d, compat=0x.x)" },
+{ 704028817, "AsyncContactQuorum (func=0x.x, transPtr=0x.x, pver=.d, compat=0x.x)" },
+{ 704028818, "AsyncContactQuorum(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028819, "WaitContactQuorum (transPtr=0x.x)" },
+{ 704028820, "WaitContactQuorum(transPtr=0x.x) returns (errorcode=.ld)" },
+{ 704028821, "PANIC: .s failed during commit (errorcode=.ld)" },
+{ 704028822, "SUBIKVOTE_Beacon(handle=0x.x) returns (host=.s, errorcode=.ld)" },
+{ 704196609, "vnl_alloc(flock=.lx, end=.lld): allocates .lx" },
+{ 704196610, "vnl_free(rlock=.x) called" },
+{ 704196611, "vnl_adjust(flock=.x, type=.d, start=.llx, end=.llx) called" },
+{ 704196612, "vnl_adjust: list .x, starting rlock .x, type .d, start=.llx" },
+{ 704196613, "vnl_adjust: element .x, next .x, elt start .llx, *end .llx" },
+{ 704196614, "vnl_adjust: skipping; element ID .d/.x differs from given .d/.x" },
+{ 704196615, "vnl_adjust: skipping; data end .llx less than given start .llx" },
+{ 704196616, "vnl_adjust: same type .d: deleting since elt start .llx > given start .llx; end now .llx" },
+{ 704196617, "vnl_adjust: same type .d: deleting since elt end .llx < given end .llx: given start now .llx" },
+{ 704196618, "vnl_adjust: same type .d: noop on rlock [.llx...llx], elt start .llx" },
+{ 704196619, "vnl_adjust: diff types, non-overlap (elt st .llx > given end .llx, or elt end .llx < given start .llx)" },
+{ 704196620, "vnl_adjust: elt end .llx > given end .llx, elt start .llx, new lock after .lx" },
+{ 704196621, "vnl_adjust: elt start .llx < given start .llx, so cutting elt end to .llx (given end .llx)" },
+{ 704196622, "vnl_adjust: deleting lock .lx, type .d, [.llx...llx]" },
+{ 704479233, "afscall_aggr(op=.ld)" },
+{ 704479234, "afscall_aggr returns .ld" },
+{ 704479235, "ag_volcreate(aggr .ld, id .lu,,.lu, flags .ld): calling AG_VOLCREATE" },
+{ 704479236, "ag_volcreate returns .ld" },
+{ 704479237, "ag_attach: params are .lx, .lx, .lx" },
+{ 704479238, "ag_attach: returns code .ld from osi_copyin()" },
+{ 704479239, "ag_attach: ag_GetAggr found the aggr; returning EEXIST" },
+{ 704479240, "unused" },
+{ 704479241, "unused" },
+{ 704479242, "ag_attach: osi_getvdev returns .ld" },
+{ 704479243, "ag_attach: AGGR_ATTACH_NOEXPORT set, so return .ld" },
+{ 704479244, "ag_attach: Already exported--returning .ld" },
+{ 704479245, "ag_attach: Registered after noexport--returning .ld" },
+{ 704479246, "ag_attach: unknown aggregate type: returning .ld" },
+{ 704479247, "ag_attach: .ld returned from dependent attach-op" },
+{ 704479248, "ag_attach: no ag-operations vector: returning .ld" },
+{ 704479249, "ag_attach: ag_NewAggr returned .ld" },
+{ 704479250, "ag_aggrInfo: for aggrid .ld" },
+{ 704479251, "ag_aggrInfo returns .ld" },
+{ 704479252, "ag_aggrEnumerate(.ld, .lx, .lx) called" },
+{ 704479253, "ag_aggrEnumerate: outlen .ld (for .ld aggrs) too small; return .ld" },
+{ 704479254, "ag_aggrEnumerate: returning .ld" },
+{ 704479255, "ag_volEnumerate(.ld, .lx, .lx, .lx) called" },
+{ 704479256, "ag_volEnumerate returns .ld from osi_copyin" },
+{ 704479257, "ag_volEnumerate can't store .ld bytes (.d vols): code .ld" },
+{ 704479258, "ag_volEnumerate: agid .lu, going for .lu vol(s)" },
+{ 704479259, "ag_volEnumerate: AG_VOLINFO, index .ld, gives code .ld" },
+{ 704479260, "ag_volEnumerate: index .ld, returning code .ld" },
+{ 704479261, "ag_volEnumerate: VOL_GETSTATUS for ix .ld returns code .ld" },
+{ 704479262, "ag_volEnumerate: batch done: returning code .ld" },
+{ 704479263, "ag_volEnumerate: ag_GetAggr(.ld) returns null; returning ENODEV" },
+{ 704479264, "ag_RegisterVolumes: registering on aggr .ld" },
+{ 704479265, "ag_RegisterVolumes: AG_VOLINFO ix .ld gives .lu,,.lu, code .ld" },
+{ 704479266, "ag_RegisterVolumes: vol_Attach(.lu,,.lu) gives states .x, code .ld" },
+{ 704479267, "ag_RegisterVolumes: finished code .d" },
+{ 704479268, "ag_UnRegisterVolumes: unregistering on aggr .ld" },
+{ 704479269, "ag_UnRegisterVolumes: AG_VOLINFO ix .ld gives .lu,,.lu, code .ld" },
+{ 704479270, "ag_UnRegisterVolumes: volreg_Lookup(.lu,,.lu) returns .ld" },
+{ 704479271, "ag_UnRegisterVolumes: vol .lu,,.lu is busy: returning .ld" },
+{ 704479272, "ag_UnRegisterVolumes: can't open vol .lu,,.lu: code .ld" },
+{ 704479273, "ag_UnRegisterVolumes: vol_Detach(.lu,,.lu) returns .ld" },
+{ 704479274, "ag_UnRegisterVolumes: after VOL_RELE(.lu,,.lu), code is .ld" },
+{ 704479275, "ag_NewAggr(.s, .ld, .#lx) called" },
+{ 704479276, "ag_NewAggr: .#lx already exists to match" },
+{ 704479277, "ag_NewAggr: aggr id .d, aggr structure .#lx, code .d" },
+{ 704479278, "ag_PutAggr: decreasing ref count on aggr .lx" },
+{ 704479279, "ag_PutAggr: FINAL decreasing of ref count on aggr .lx" },
+{ 704479280, "ag_PutAggr: returning code .ld" },
+{ 704479281, "ag_PutAggr: pointer .lx not in list: returning ENOENT" },
+{ 704479282, "ag_attach: ag_GetAggr found the aggr; returning .d from register-vols" },
+{ 704479283, "ag_fsHold: aggr .#x, ref now .d" },
+{ 704479284, "ag_fsRele: aggr .#x, ref now .d" },
+{ 704479285, "ag_fsLock: aggr .#x, type .d: obtaining lock" },
+{ 704479286, "ag_fsLock: returning code .d" },
+{ 704479287, "ag_fsUnlock: aggr .#x, type .d: releasing lock" },
+{ 704479288, "ag_fsUnlock: returning code .d" },
+{ 704479289, "ag_fsDMHold: aggr .#x" },
+{ 704479290, "ag_fsDMRele: aggr .#x" },
+{ 704479291, "ag_volcreate: vol_Attach for new volume returned code .d" },
+{ 704479292, "ag_volcreate: AG_VOLINFO failed for fresh volume with code .d" },
+{ 704479293, "ag_volcreate: AG_VOLCREATE failed with code .d" },
+{ 704479294, "ag_attach: resulting code .d" },
+{ 704479295, "ag_UnRegisterVolumes: starting system-wide DNLC purge" },
+{ 704479296, "ag_UnRegisterVolumes: finished system-wide DNLC purge" },
+{ 704565249, "vol syscall .lu: bit not set (accstatus .lu), line .lu" },
+{ 704565250, "afscall_volser: op .lu" },
+{ 704565251, "afscall_volser: no such volume as .lu: code .lu" },
+{ 704565252, "afscall_volser: no volume desc for .lu: code .lu" },
+{ 704565253, "afscall_volser: volop_close waking grabber for .lu" },
+{ 704565254, "afscall_volser: volop_close waking looker for .lu" },
+{ 704565255, "afscall_volser: cloneop: diff aggr for .lu (.lu) and .lu (.lu)" },
+{ 704565256, "afscall_volser: cloneop: diff volops for .lu and .lu" },
+{ 704565257, "afscall_volser: no volume desc for clone second .lu: code .lu" },
+{ 704565258, "afscall_volser: cloneop: diff volop vec for .lu and .lu" },
+{ 704565259, "afscall_volser: no volume desc for swap second .lu: code .lu" },
+{ 704565260, "vol_open: vid .lu,,.lu, accstat .lu, accerr .lu" },
+{ 704565261, "vol_open: no such volume as .lu,,.lu: code .lu" },
+{ 704565262, "vol_open: volume .lu,,.lu is busy (states .#lx, accerror .lu)" },
+{ 704565263, "vol_open: volume .lu,,.lu: WAITING; concur .lu, ref .lu, vnops .lu" },
+{ 704565264, "vol_open: volume .lu,,.lu: awake from waiting" },
+{ 704565265, "vol_open: volume .lu,,.lu: err .lu from VOL_OPEN" },
+{ 704565266, "vol_open: volume .lu,,.lu: err .lu from copyout()" },
+{ 704565267, "vol_open: volume .lu,,.lu: vol_open SUCCEEDS" },
+{ 704565268, "vol_RCZero: waking grabber for .lu" },
+{ 704565269, "vol_RCZero: waking looker for .lu" },
+{ 704565270, "vol_GCDesc: GCed .d structs" },
+{ 704565271, "vol_GetDesc: ALL ENTRIES FULL" },
+{ 704565272, "vol_GetDesc: returning entry .d" },
+{ 704565273, "vol_FindDesc: slot .d out of bounds" },
+{ 704565274, "vol_FindDesc: slot .d empty" },
+{ 704565275, "vol_FindDesc: diff procs (cdp: .d vs. current: .d)" },
+{ 704565276, "vol_FindDesc: diff descIds (cdp: .d vs. given: .d)" },
+{ 704565277, "vol_FindDesc: cdp .#lx, descId .d Deleted" },
+{ 704565278, "vol_FindDesc: returning cdp .#lx, slot .d" },
+{ 704565279, "vol_Init called" },
+{ 704565280, "vol_Attach: volId=.lu,,.lu, aggrid=.lu" },
+{ 704565281, "vol_Detach: volp=.#x, id=.lu,,.lu, refCnt=.lu" },
+{ 704565282, "vol_StartVnodeOp: volp .#lx, waiting on code .d" },
+{ 704565283, "afscall_volser: VOLOP_OPEN" },
+{ 704565284, "afscall_volser: VOLOP_AGOPEN" },
+{ 704565285, "afscall_volser: VOLOP_FCLOSE" },
+{ 704565286, "afscall_volser: VOLOP_FCLOSE: .lu,,.lu" },
+{ 704565287, "afscall_volser: VOLOP_BULKSETSTATUS: .lu status blocks" },
+{ 704565288, "afscall_volser: op .lu on volp .#lx, id .lu,,.lu" },
+{ 704565289, "vol_Detach(.#lx): also freeing tpq .#lx" },
+{ 704565290, "vol_SwapIdentities: swapping .#lx (.lu,,.lu) and .#lx (.lu,,.lu)" },
+{ 704565291, "vol_doMoveTimeout(.#lx), id .lu,,.lu: states .#lx: timeout .lu expired" },
+{ 704565292, "vol_doMoveTimeout: incomplete target fileset timed out" },
+{ 704565293, "vol_doMoveTimeout: TARGET timeout: setting OOS and timeout to .lu" },
+{ 704565294, "vol_doMoveTimeout: SOURCE timeout: setting OOS and timeout to .lu" },
+{ 704565295, "vol_doMoveTimeout: SOURCE|OFFLINE timeout: setting OOS and timeout to .lu" },
+{ 704565296, "vol_doMoveTimeout: TARGET|OOS timeout: returning to service" },
+{ 704565297, "vol_doMoveTimeout: SOURCE|OOS timeout: returning to service" },
+{ 704565298, "vol_doMoveTimeout: SOURCE|OFFLINE|OOS timeout: setting ZAPME" },
+{ 704565299, "vol_doMoveTimeout: incomplete source fileset timed out" },
+{ 704565300, "vol_doMoveTimeout(.#lx), id .lu,,.lu: unrecognized status .#lx!" },
+{ 704565301, "vol_advanceMove(.#lx), id .lu,,.lu: timeout .lu, calling doMoveTimeout" },
+{ 704565302, "vol_DriveMove(.#lx), id .lu,,.lu called" },
+{ 704565303, "vol_DriveMove(.lu,,.lu) called: volreg_Lookup returns .ld" },
+{ 704565304, "vol_DriveMove(.#lx): states .#lx, includes VOL_BUSY, so skipping" },
+{ 704565305, "vol_DriveMove(.#lx): rescheduling for .ld seconds from now" },
+{ 704565306, "vol_DriveMove(.#lx): states .#lx, timeout .lu, so no resched" },
+{ 704565307, "vol_DriveMove(.#lx): clearing tpq .#lx and freeing argp .#lx" },
+{ 704565308, "vol_SetMoveTimeoutTrigger(.#lx), id .lu,,.lu, states .#lx, timeout .lu:" },
+{ 704565309, " id arg at .#lx, reschedule is .ld, request ptr is .#lx" },
+{ 704565310, "CheckAndLinkZLC(volp=.x, states=.#lx) called" },
+{ 704565311, "LinkZLCList(volp=.x, exported=.d, replicated=.d) called" },
+{ 704565312, "LinkZLCList at iter .d: getzlc got vp .x, code .d" },
+{ 704565313, "LinkZLCList got fid .x..x..x..x, code .d" },
+{ 704565314, "LinkZLCList returns .d" },
+{ 704565315, "vol_StartInactiveVnodeOp: volp .x busy; vp .x; vol has concurr .d" },
+{ 704565316, "vol_StartInactiveVnodeOp: holding vp .x in element .x" },
+{ 704565317, "vol_ProcessDeferredReles: releasing vp .x from element .x" },
+{ 704565318, "vol_fsHold: volp .x: ref count now .d" },
+{ 704565319, "vol_fsRele: volp .x: ref count starts at .d" },
+{ 704565320, "vol_fsLock: volp .x type .d: about to lock" },
+{ 704565321, "vol_fsLock: locked, returning code .d" },
+{ 704565322, "vol_fsUnlock: volp .x type .d: about to unlock" },
+{ 704565323, "vol_fsUnlock: returning code .d" },
+{ 704565324, "vol_fsDMWait: volp .x, blobp .x" },
+{ 704565325, "vol_fsDMFree: volp .x, blobp .x" },
+{ 704565326, "vol_FindDesc: cdp .#lx, descId .d: volp is NULL" },
+{ 704565327, "volo_ClearOpener: volp .#x closed while thread .d still running" },
+{ 704565328, "vol_open: id .lu,,.lu: code .lu" },
+{ 704565329, "vol_GetDesc: returning slot .d, desc .d" },
+{ 704851969, "zlc_TryRemove(.#lx, .x..x..x..x, .ld, .ld) entered" },
+{ 704851970, "zlc_TryRemove: tokenID=.u,,.u, flags=.#lx, refCount=.ld, wait=.ld" },
+{ 704851971, "zlc_TryRemove returning" },
+{ 704851972, "zlc_GetDeleteToken(tokenID=.u,,.u, flags=.#lx, refCount=.ld, wait=.ld) entered" },
+{ 704851973, "zlc_GetDeleteToken: volreg_Lookup failed, code=.ld" },
+{ 704851974, "zlc_GetDeleteToken: volume being moved, volstates=.#lx" },
+{ 704851975, "zlc_GetDeleteToken: volume being moved, volstates=.#lx, wait=.ld" },
+{ 704851976, "zlc_GetDeleteToken: volume being moved locally, wait=.ld" },
+{ 704851977, "zlc_GetDeleteToken: remove granted" },
+{ 704851978, "zlc_GetDeleteToken: request queued" },
+{ 704851979, "zlc_GetDeleteToken returning" },
+{ 704851980, "zlc_CleanVolume(.u,,.u) entered" },
+{ 704851981, "zlc_CleanVolume returning" },
+{ 704851982, "zlc_Mgr: pruning remove queue" },
+{ 704851983, "zlc_Mgr: waiting for .ld seconds" },
+{ 704851984, "zlc_PruneQueue() entered" },
+{ 704851985, "zlc_PruneQueue: .x..x..x..x: token granted--returning token" },
+{ 704851986, "zlc_PruneQueue: .x..x..x..x: freeing clean trp" },
+{ 704851987, "zlc_PruneQueue: .x..x..x..x: trying for delete token" },
+{ 704851988, "zlc_PruneQueue: .x..x..x..x: waiting until .ld" },
+{ 704851989, "zlc_PruneQueue: .x..x..x..x: waiting until .ld for tsr on replicated ft" },
+{ 704851990, "zlc_PruneQueue: .x..x..x..x: waiting until .ld" },
+{ 704851991, "zlc_PruneQueue: .x..x..x..x: trying for delete token" },
+{ 704851992, "zlc_PruneQueue returning .ld" },
+{ 704851993, "zlc_WakeupMgr() entered" },
+{ 704851994, "[zlc]FreeDownToQuota() entered, list size=.ld" },
+{ 704851995, "[zlc]FreeDownToQuota: .x..x..x..x: moribund" },
+{ 704851996, "[zlc]FreeDownToQuota: adding entry to async list: tokenID=.u,,.u, flags=.#lx, refCount=.ld, wait=.ld" },
+{ 704851997, "[zlc]FreeDownToQuota: adding entry to dally list: tokenID=.u,,.u, flags=.#lx, refCount=.ld, wait=.ld" },
+{ 704851998, "[zlc]FreeDownToQuota: adding entry to wait list: tokenID=.u,,.u, flags=.#lx, refCount=.ld, wait=.ld" },
+{ 704851999, "[zlc]FreeDownToQuota: skipping entry: tokenID=.u,,.u, flags=.#lx, refCount=.ld, wait=.ld" },
+{ 704852000, "[zlc]FreeDownToQuota returning, vnodes held=.ld" },
+{ 704852001, "zlc_SetRestartState(.ld) entered" },
+{ 704852002, "zlc_SetRestartState returning" },
+{ 704852003, "zlc_AsyncGrant(.#lx, .#lx, .#lx) entered" },
+{ 704852004, "zlc_AsyncGrant: found entry: tokenID=.u,,.u, flags=.#lx, refCount=.ld, wait=.ld" },
+{ 704852005, "zlc_AsyncGrant: volreg_Lookup failed, code=.ld" },
+{ 704852006, "zlc_AsyncGrant: volume being moved, volstates=.#lx" },
+{ 704852007, "zlc_AsyncGrant: volume being moved, volstates=.#lx, wait=.ld" },
+{ 704852008, "zlc_AsyncGrant: .x..x..x..x: token granted" },
+{ 704852009, "zlc_AsyncGrant: entry not found" },
+{ 704852010, "zlc_RevokeToken(list-len=.ld, first-fid=.x..x..x..x) entered" },
+{ 704852011, "zlc_AsyncGrant: found entry: fid=.x..x..x..x, state=.ld" },
+{ 704852012, "zlc_AsyncGrant: fid=.x..x..x..x, from-state=.ld, to-state=.ld" },
+{ 704852013, "zlc_AsyncGrant returning" },
+{ 704852014, "zlc_CleanVolume: fid=.x..x..x..x, from-state=.ld, to-state=.ld" },
+{ 704852015, "zlc_GetDeleteToken(fid=.x..x..x..x) entered" },
+{ 704852016, "zlc_GetDeleteToken: fid=.x..x..x..x, OFD granted" },
+{ 704852017, "zlc_GetDeleteToken: fid=.x..x..x..x, OFD queued" },
+{ 704852018, "zlc_GetDeleteToken: fid=.x..x..x..x, tkm_GetToken error, code=.ld" },
+{ 704852019, "zlc_GetDeleteToken: fid=.x..x..x..x, tkm_ReturnToken error, code=.ld" },
+{ 704852020, "zlc_GetDeleteToken: fid=.x..x..x..x, from-state=.ld, to-state=.ld" },
+{ 704852021, "zlc_TryRemove(.#lx, .x..x..x..x) entered" },
+{ 704852022, "zlc_TryRemove: fid=.x..x..x..x, init-state=.ld" },
+{ 704852023, "zlc_GotoNextState: fid=.x..x..x..x, volreg_Lookup failed, code=.ld" },
+{ 704852024, "[zlc]FreeDownToTarget(vnodes-held=.ld) entered" },
+{ 704852025, "[zlc]FreeDownToTarget: fid=.x..x..x..x, from-state=.ld, to-state=.ld" },
+{ 704852026, "[zlc]FreeDownToTarget(vnodes-held=.ld) returning" },
+{ 704852027, "[zlc]PruneQueue() entered" },
+{ 704852028, "[zlc]PruneQueue: fid=.x..x..x..x, from-state=.ld, to-state=.ld" },
+{ 704852029, "[zlc]PruneQueue() returning .lu" },
+{ 704852030, "zlc_WakeupMgr(.lu) entered" },
+{ 704852031, "[zlc]MgrThread: sleeping until time .lu" },
+{ 704852032, "zlc_Init() returning .ld" },
+{ 0, NULL }
+};
diff --git a/epan/dissectors/packet-dcerpc-dce122.h b/epan/dissectors/packet-dcerpc-dce122.h
new file mode 100644
index 0000000000..270ef03a7b
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-dce122.h
@@ -0,0 +1,32 @@
+/* packet-dcerpc-dce122.h
+ * Common defines for dce122
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC__DCE122_H__
+#define __PACKET_DCERPC__DCE122_H__
+
+extern const value_string dce_error_vals[];
+
+#endif
diff --git a/epan/dissectors/packet-dcerpc-dcom.h b/epan/dissectors/packet-dcerpc-dcom.h
new file mode 100644
index 0000000000..f07b48a1cf
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-dcom.h
@@ -0,0 +1,82 @@
+/* packet-dcerpc-dcom.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_DCOM_H__
+#define __PACKET_DCERPC_DCOM_H__
+
+typedef struct tagCOMVERSION
+ {
+ guint16 MajorVersion;
+ guint16 MinorVersion;
+ } COMVERSION;
+
+typedef struct tagORPC_EXTENT
+ {
+ e_uuid_t id;
+ guint32 size;
+/* guint8 data[]; */
+ } ORPC_EXTENT;
+
+typedef struct tagORPC_EXTENT_ARRAY
+ {
+ guint32 size;
+ guint32 reserved;
+ ORPC_EXTENT **extent;
+ } ORPC_EXTENT_ARRAY;
+
+typedef struct tagORPCTHIS {
+ COMVERSION version;
+ guint32 flags;
+ guint32 reserved1;
+ e_uuid_t cid;
+ ORPC_EXTENT_ARRAY *extensions;
+ } ORPCTHIS;
+
+typedef struct tagMInterfacePointer {
+ guint32 ulCntData;
+/* guint8 abData[]; */
+ } MInterfacePointer, *PMInterfacePointer;
+
+typedef struct tagORPCTHAT {
+ guint32 flags;
+ ORPC_EXTENT_ARRAY *extensions;
+ } ORPCTHAT;
+
+typedef struct tagSTRINGBINDING {
+ unsigned short wTowerId; /* Cannot be zero. */
+ unsigned short aNetworkAddr; /* Zero terminated. */
+ } STRINGBINDING;
+
+typedef struct tagSECURITYBINDING {
+ unsigned short wAuthnSvc; /* Cannot be zero. */
+ unsigned short wAuthzSvc; /* Must not be zero. */
+ unsigned short aPrincName; /* Zero terminated. */
+ } SECURITYBINDING;
+
+typedef struct tagDUALSTRINGARRAY {
+ unsigned short wNumEntries; /* Number of entries in array. */
+ unsigned short wSecurityOffset; /* Offset of security info. */
+/* [size_is(wNumEntries)] unsigned short aStringArray[]; */
+ } DUALSTRINGARRAY;
+
+#endif /* packet-dcerpc-dcom.h */
diff --git a/epan/dissectors/packet-dcerpc-dfs.c b/epan/dissectors/packet-dcerpc-dfs.c
new file mode 100644
index 0000000000..84f887c9dd
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-dfs.c
@@ -0,0 +1,102 @@
+/* packet-dcerpc-dfs.c
+ * Routines for SMB \\PIPE\\netdfs packet disassembly
+ * Copyright 2001, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dfs.h"
+
+static int proto_dcerpc_dfs = -1;
+static gint ett_dcerpc_dfs = -1;
+
+static int hf_dfs_opnum = -1;
+
+static e_uuid_t uuid_dcerpc_dfs = {
+ 0x4fc742e0, 0x4a10, 0x11cf,
+ { 0x82, 0x73, 0x00, 0xaa, 0x00, 0x4a, 0xe6, 0x73 }
+};
+
+static guint16 ver_dcerpc_dfs = 3;
+
+static dcerpc_sub_dissector dcerpc_dfs_dissectors[] = {
+ { DFS_MANAGER_GET_VERSION, "NetrDfsManagerGetVersion", NULL, NULL },
+ { DFS_ADD, "NetrDfsAdd", NULL, NULL },
+ { DFS_REMOVE, "NetrDfsRemove", NULL, NULL },
+ { DFS_SET_INFO, "NetrDfsSetInfo", NULL, NULL },
+ { DFS_GET_INFO, "NetrDfsGetInfo", NULL, NULL },
+ { DFS_ENUM, "NetrDfsEnum", NULL, NULL },
+ { DFS_RENAME, "NetrDfsRename", NULL, NULL },
+ { DFS_MOVE, "NetrDfsMove", NULL, NULL },
+ { DFS_MANAGER_GET_CONFIG_INFO, "NetrDfsManagerGetConfigInfo", NULL, NULL },
+ { DFS_MANAGER_SEND_SITE_INFO, "NetrDfsManagerSendSiteInfo", NULL, NULL },
+ { DFS_ADD_FT_ROOT, "NetrDfsAddFtRoot", NULL, NULL },
+ { DFS_REMOVE_FT_ROOT, "NetrDfsRemoveFtRoot", NULL, NULL },
+ { DFS_ADD_STD_ROOT, "NetrDfsAddStdRoot", NULL, NULL },
+ { DFS_REMOVE_STD_ROOT, "NetrDfsRemoveStdRoot", NULL, NULL },
+ { DFS_MANAGER_INITIALIZE, "NetrDfsManagerInitialize", NULL, NULL },
+ { DFS_ADD_STD_ROOT_FORCED, "NetrDfsAddStdRootForced", NULL, NULL },
+ { DFS_GET_DC_ADDRESS, "NetrDfsGetDcAddress", NULL, NULL },
+ { DFS_SET_DC_ADDRESS, "NetrDfsSetDcAddress", NULL, NULL },
+ { DFS_FLUSH_FT_TABLE, "NetrDfsFlushFtTable", NULL, NULL },
+ { DFS_ADD2, "NetrDfsAdd2", NULL, NULL },
+ { DFS_REMOVE2, "NetrDfsRemove2", NULL, NULL },
+ { DFS_ENUM_EX, "NetrDfsEnumEx", NULL, NULL },
+ { DFS_SET_INFO_2, "NetrDfsSetInfo2 ", NULL, NULL },
+ {0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_dfs(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_dfs_opnum,
+ { "Operation", "dfs.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_dfs
+ };
+
+ proto_dcerpc_dfs = proto_register_protocol(
+ "Microsoft Distributed File System", "DFS", "dfs");
+
+ proto_register_field_array(proto_dcerpc_dfs, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_dfs(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_dfs, ett_dcerpc_dfs, &uuid_dcerpc_dfs,
+ ver_dcerpc_dfs, dcerpc_dfs_dissectors, hf_dfs_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-dfs.h b/epan/dissectors/packet-dcerpc-dfs.h
new file mode 100644
index 0000000000..672495bdce
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-dfs.h
@@ -0,0 +1,55 @@
+/* packet-dcerpc-dfs.h
+ * Routines for SMB \PIPE\netdfs packet disassembly
+ * Copyright 2001, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_DFS_H
+#define __PACKET_DCERPC_DFS_H
+
+/* Functions available on the NETDFS pipe. From Samba, include/rpc_dfs.h */
+
+#define DFS_MANAGER_GET_VERSION 0x00
+#define DFS_ADD 0x01
+#define DFS_REMOVE 0x02
+#define DFS_SET_INFO 0x03
+#define DFS_GET_INFO 0x04
+#define DFS_ENUM 0x05
+#define DFS_RENAME 0x06
+#define DFS_MOVE 0x07
+#define DFS_MANAGER_GET_CONFIG_INFO 0x08
+#define DFS_MANAGER_SEND_SITE_INFO 0x09
+#define DFS_ADD_FT_ROOT 0x0a
+#define DFS_REMOVE_FT_ROOT 0x0b
+#define DFS_ADD_STD_ROOT 0x0c
+#define DFS_REMOVE_STD_ROOT 0x0d
+#define DFS_MANAGER_INITIALIZE 0x0e
+#define DFS_ADD_STD_ROOT_FORCED 0x0f
+#define DFS_GET_DC_ADDRESS 0x10
+#define DFS_SET_DC_ADDRESS 0x11
+#define DFS_FLUSH_FT_TABLE 0x12
+#define DFS_ADD2 0x13
+#define DFS_REMOVE2 0x14
+#define DFS_ENUM_EX 0x15
+#define DFS_SET_INFO_2 0x16
+
+#endif /* packet-dcerpc-dfs.h */
diff --git a/epan/dissectors/packet-dcerpc-dnsserver.c b/epan/dissectors/packet-dcerpc-dnsserver.c
new file mode 100644
index 0000000000..e6fdd83ce3
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-dnsserver.c
@@ -0,0 +1,113 @@
+/* packet-dcerpc-dnsserver.c
+ * Routines for SMB \PIPE\DNSSERVER packet disassembly
+ * Copyright 2001, 2002 Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-dnsserver.h"
+#include "smb.h"
+
+/* Global hf index fields */
+
+static int hf_rc = -1;
+
+static int proto_dcerpc_dnsserver = -1;
+static int hf_opnum = -1;
+
+static gint ett_dnsserver = -1;
+
+static e_uuid_t uuid_dcerpc_dnsserver = {
+ 0x50abc2a4, 0x574d, 0x40b3,
+ { 0x9d, 0x66, 0xee, 0x4f, 0xd5, 0xfb, 0xa0, 0x76 }
+};
+
+static guint16 ver_dcerpc_dnsserver = 5;
+
+static dcerpc_sub_dissector dcerpc_dnsserver_dissectors[] = {
+ { DNSSERVER_DNSSRV_OPERATION, "DnssrvOperation",
+ NULL, NULL },
+ { DNSSERVER_DNSSRV_QUERY, "DnssrvQuery",
+ NULL, NULL },
+ { DNSSERVER_DNSSRV_COMPLEX_OPERATION, "DnssrvComplexOperation",
+ NULL, NULL },
+ { DNSSERVER_DNSSRV_ENUM_RECORDS, "DnssrvEnumRecords",
+ NULL, NULL },
+ { DNSSERVER_DNSSRV_UPDATE_RECORD, "DnssrvUpdateRecord",
+ NULL, NULL },
+ { DNSSERVER_DNSSRV_OPERATION_2, "DnssrvOperation2",
+ NULL, NULL },
+ { DNSSERVER_DNSSRV_QUERY_2, "DnssrvQuery2",
+ NULL, NULL },
+ { DNSSERVER_DNSSRV_COMPLEX_OPERATION_2, "DnssrvComplexOperation2",
+ NULL, NULL },
+ { DNSSERVER_DNSSRV_ENUM_RECORDS_2, "DnssrvEnumRecords2",
+ NULL, NULL },
+ { DNSSERVER_DNSSRV_UPDATE_RECORD_2, "DnssrvUpdateRecord2",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_dnsserver(void)
+{
+ static hf_register_info hf[] = {
+
+ /* Global indexes */
+
+ { &hf_rc,
+ { "Return code", "dnsserver.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "Return code", HFILL }},
+
+ { &hf_opnum,
+ { "Operation", "dnsserver.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_dnsserver
+ };
+
+ proto_dcerpc_dnsserver = proto_register_protocol(
+ "Windows 2000 DNS", "DNSSERVER", "dnsserver");
+
+ proto_register_field_array(proto_dcerpc_dnsserver, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_dnsserver(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(
+ proto_dcerpc_dnsserver, ett_dnsserver, &uuid_dcerpc_dnsserver,
+ ver_dcerpc_dnsserver, dcerpc_dnsserver_dissectors, hf_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-dnsserver.h b/epan/dissectors/packet-dcerpc-dnsserver.h
new file mode 100644
index 0000000000..39b13f0a58
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-dnsserver.h
@@ -0,0 +1,42 @@
+/* packet-dcerpc-dnsserver.h
+ * Routines for SMB \PIPE\DNSSERVER packet disassembly
+ * Copyright 2002, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_DNSSERVER_H
+#define __PACKET_DCERPC_DNSSERVER_H
+
+/* Functions available on the DNSSERVER pipe */
+
+#define DNSSERVER_DNSSRV_OPERATION 0x00
+#define DNSSERVER_DNSSRV_QUERY 0x01
+#define DNSSERVER_DNSSRV_COMPLEX_OPERATION 0x02
+#define DNSSERVER_DNSSRV_ENUM_RECORDS 0x03
+#define DNSSERVER_DNSSRV_UPDATE_RECORD 0x04
+#define DNSSERVER_DNSSRV_OPERATION_2 0x05
+#define DNSSERVER_DNSSRV_QUERY_2 0x06
+#define DNSSERVER_DNSSRV_COMPLEX_OPERATION_2 0x07
+#define DNSSERVER_DNSSRV_ENUM_RECORDS_2 0x08
+#define DNSSERVER_DNSSRV_UPDATE_RECORD_2 0x09
+
+#endif /* packet-dcerpc-dnsserver.h */
diff --git a/epan/dissectors/packet-dcerpc-drsuapi.c b/epan/dissectors/packet-dcerpc-drsuapi.c
new file mode 100644
index 0000000000..1f16f5ef52
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-drsuapi.c
@@ -0,0 +1,122 @@
+/* packet-dcerpc-drsuapi.c
+ * Routines for the drsuapi (Directory Replication Service) MSRPC interface
+ * Copyright 2003 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-drsuapi.h"
+
+static int proto_dcerpc_drsuapi = -1;
+
+static int hf_drsuapi_opnum = 0;
+
+static gint ett_dcerpc_drsuapi = -1;
+
+/*
+IDL [ uuid(e3514235-4b06-11d1-ab04-00c04fc2dcd2),
+IDL version(4.0),
+IDL implicit_handle(handle_t rpc_binding)
+IDL ] interface drsuapi
+*/
+
+static e_uuid_t uuid_dcerpc_drsuapi = {
+ 0xe3514235, 0x4b06, 0x11d1,
+ { 0xab, 0x04, 0x00, 0xc0, 0x4f, 0xc2, 0xdc, 0xd2 }
+};
+
+static guint16 ver_dcerpc_drsuapi = 4;
+
+
+static dcerpc_sub_dissector dcerpc_drsuapi_dissectors[] = {
+ { DRSUAPI_BIND, "DRSBind", NULL, NULL},
+ { DRSUAPI_UNBIND, "DRSUnbind", NULL, NULL},
+ { DRSUAPI_REPLICA_SYNC, "DRSReplicaSync", NULL, NULL},
+ { DRSUAPI_GET_NC_CHANGES, "DRSGetNCChanges", NULL, NULL},
+ { DRSUAPI_UPDATE_REFS, "DRSUpdateRefs", NULL, NULL},
+ { DRSUAPI_REPLICA_ADD, "DRSReplicaAdd", NULL, NULL},
+ { DRSUAPI_REPLICA_DEL, "DRSReplicaDel", NULL, NULL},
+ { DRSUAPI_REPLICA_MODIFY, "DRSReplicaModify", NULL, NULL},
+ { DRSUAPI_VERIFY_NAMES, "DRSVerifyNames", NULL, NULL},
+ { DRSUAPI_GET_MEMBERSHIPS, "DRSGetMemberships", NULL, NULL},
+ { DRSUAPI_INTER_DOMAIN_MOVE, "DRSInterDomainMove", NULL, NULL},
+ { DRSUAPI_GET_NT4_CHANGELOG, "DRSGetNT4ChangeLog", NULL, NULL},
+ { DRSUAPI_CRACKNAMES, "DRSCrackNames", NULL, NULL},
+ { DRSUAPI_WRITE_SPN, "DRSWriteSPN", NULL, NULL},
+ { DRSUAPI_REMOVE_DS_SERVER, "DRSRemoveDsServer", NULL, NULL},
+ { DRSUAPI_REMOVE_DS_DOMAIN, "DRSRemoveDsDomain", NULL, NULL},
+ { DRSUAPI_DOMAIN_CONTROLLER_INFO, "DRSDomainControllerInfo", NULL, NULL},
+ { DRSUAPI_ADD_ENTRY, "DRSAddEntry", NULL, NULL},
+ { DRSUAPI_EXECUTE_KCC, "DRSExecuteKCC", NULL, NULL},
+ { DRSUAPI_GET_REPL_INFO, "DRSGetReplInfo", NULL, NULL},
+ { DRSUAPI_ADD_SID_HISTORY, "DRSAddSidHistory", NULL, NULL},
+ { DRSUAPI_GET_MEMBERSHIPS2, "DRSGetMemberships2", NULL, NULL},
+ { DRSUAPI_REPLICA_VERIFY_OBJECTS, "DRSReplicaVerifyObjects", NULL, NULL},
+ { DRSUAPI_GET_OBJECT_EXISTENCE, "DRSGetObjectExistence", NULL, NULL},
+ { DRSUAPI_QUERY_SITES_BY_COST, "DRSQuerySitesByCost", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+
+void
+proto_register_dcerpc_drsuapi(void)
+{
+
+ static hf_register_info hf[] = {
+
+ { &hf_drsuapi_opnum,
+ { "Operation", "drsuapi.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ };
+
+
+ static gint *ett[] = {
+ &ett_dcerpc_drsuapi,
+ };
+
+
+ proto_dcerpc_drsuapi = proto_register_protocol(
+ "Microsoft Directory Replication Service", "DRSUAPI", "drsuapi");
+
+ proto_register_field_array(proto_dcerpc_drsuapi, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+void
+proto_reg_handoff_dcerpc_drsuapi(void)
+{
+ /* register protocol as dcerpc */
+
+ dcerpc_init_uuid(
+ proto_dcerpc_drsuapi, ett_dcerpc_drsuapi, &uuid_dcerpc_drsuapi,
+ ver_dcerpc_drsuapi, dcerpc_drsuapi_dissectors, hf_drsuapi_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-drsuapi.h b/epan/dissectors/packet-dcerpc-drsuapi.h
new file mode 100644
index 0000000000..eeb4a6c7a0
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-drsuapi.h
@@ -0,0 +1,60 @@
+/* packet-dcerpc-drsuapi.h
+ * Routines for the drsuapi (Directory Replication Service) MSRPC interface
+ * Copyright 2003 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_DRSUAPI_H
+#define __PACKET_DCERPC_DRSUAPI_H
+
+/* MSRPC functions available in the drsuapi interface */
+
+#define DRSUAPI_BIND 0x00
+#define DRSUAPI_UNBIND 0x01
+#define DRSUAPI_REPLICA_SYNC 0x02
+#define DRSUAPI_GET_NC_CHANGES 0x03
+#define DRSUAPI_UPDATE_REFS 0x04
+#define DRSUAPI_REPLICA_ADD 0x05
+#define DRSUAPI_REPLICA_DEL 0x06
+#define DRSUAPI_REPLICA_MODIFY 0x07
+#define DRSUAPI_VERIFY_NAMES 0x08
+#define DRSUAPI_GET_MEMBERSHIPS 0x09
+#define DRSUAPI_INTER_DOMAIN_MOVE 0x0a
+#define DRSUAPI_GET_NT4_CHANGELOG 0x0b
+#define DRSUAPI_CRACKNAMES 0x0c
+#define DRSUAPI_WRITE_SPN 0x0d
+#define DRSUAPI_REMOVE_DS_SERVER 0x0e
+#define DRSUAPI_REMOVE_DS_DOMAIN 0x0f
+#define DRSUAPI_DOMAIN_CONTROLLER_INFO 0x10
+#define DRSUAPI_ADD_ENTRY 0x11
+#define DRSUAPI_EXECUTE_KCC 0x12
+#define DRSUAPI_GET_REPL_INFO 0x13
+#define DRSUAPI_ADD_SID_HISTORY 0x14
+#define DRSUAPI_GET_MEMBERSHIPS2 0x15
+#define DRSUAPI_REPLICA_VERIFY_OBJECTS 0x16
+#define DRSUAPI_GET_OBJECT_EXISTENCE 0x17
+#define DRSUAPI_QUERY_SITES_BY_COST 0x18
+
+#endif /* packet-dcerpc-drsuapi.h */
+
+
+
diff --git a/epan/dissectors/packet-dcerpc-dtsprovider.c b/epan/dissectors/packet-dcerpc-dtsprovider.c
new file mode 100644
index 0000000000..c564e11b68
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-dtsprovider.c
@@ -0,0 +1,87 @@
+/* packet-dcerpc-dtsprovider.c
+ * Routines for dcerpc Time server dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/time.tar.gz time/service/dtsprovider.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dce122.h"
+
+static int proto_dtsprovider = -1;
+static int hf_dtsprovider_opnum = -1;
+static int hf_dtsprovider_status = -1;
+
+
+static gint ett_dtsprovider = -1;
+
+
+static e_uuid_t uuid_dtsprovider = { 0xbfca1238, 0x628a, 0x11c9, { 0xa0, 0x73, 0x08, 0x00, 0x2b, 0x0d, 0xea, 0x7a } };
+static guint16 ver_dtsprovider = 1;
+
+
+static dcerpc_sub_dissector dtsprovider_dissectors[] = {
+ { 0, "ContactProvider", NULL, NULL},
+ { 1, "ServerRequestProviderTime", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dtsprovider (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_dtsprovider_opnum,
+ { "Operation", "dtsprovider.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ { &hf_dtsprovider_status,
+ { "Status", "dtsprovider.status", FT_UINT32, BASE_DEC,
+ VALS(dce_error_vals), 0x0, "Return code, status of executed command", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_dtsprovider,
+ };
+ proto_dtsprovider = proto_register_protocol ("DCE Distributed Time Service Provider", "DTSPROVIDER", "dtsprovider");
+ proto_register_field_array (proto_dtsprovider, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_dtsprovider (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_dtsprovider, ett_dtsprovider, &uuid_dtsprovider, ver_dtsprovider, dtsprovider_dissectors, hf_dtsprovider_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-dtsstime_req.c b/epan/dissectors/packet-dcerpc-dtsstime_req.c
new file mode 100644
index 0000000000..e45d36c546
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-dtsstime_req.c
@@ -0,0 +1,82 @@
+/* packet-dcerpc-dtsstime_req.c
+ * Routines for Time services stuff.
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/time.tar.gz time/service/dtsstime_req.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_dtsstime_req = -1;
+static int hf_dtsstime_req_opnum = -1;
+
+
+static gint ett_dtsstime_req = -1;
+
+
+static e_uuid_t uuid_dtsstime_req = { 0x019ee420, 0x682d, 0x11c9, { 0xa6, 0x07, 0x08, 0x00, 0x2b, 0x0d, 0xea, 0x7a } };
+static guint16 ver_dtsstime_req = 1;
+
+
+static dcerpc_sub_dissector dtsstime_req_dissectors[] = {
+ { 0, "ClerkRequestTime", NULL, NULL},
+ { 1, "ServerRequestTime", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dtsstime_req (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_dtsstime_req_opnum,
+ { "Operation", "dtsstime_req.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_dtsstime_req,
+ };
+ proto_dtsstime_req = proto_register_protocol ("DCE Distributed Time Service Local Server", "DTSSTIME_REQ", "dtsstime_req");
+ proto_register_field_array (proto_dtsstime_req, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_dtsstime_req (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_dtsstime_req, ett_dtsstime_req, &uuid_dtsstime_req, ver_dtsstime_req, dtsstime_req_dissectors, hf_dtsstime_req_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-efs.c b/epan/dissectors/packet-dcerpc-efs.c
new file mode 100644
index 0000000000..260fbb0ef5
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-efs.c
@@ -0,0 +1,698 @@
+/* packet-dcerpc-efs.c
+ * Routines for the efsrpc MSRPC interface
+ * Copyright 2004 Ronnie Sahlberg, Jean-Baptiste Marchand
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-efs.h"
+#include "smb.h"
+
+
+static int proto_dcerpc_efs = -1;
+static int hf_efsrpc_opnum = -1;
+static int hf_efsrpc_rc = -1;
+static int hf_efsrpc_filename = -1;
+static int hf_efsrpc_flags = -1;
+static int hf_efsrpc_hnd = -1;
+static int hf_efsrpc_reserved = -1;
+static int hf_efsrpc_num_entries = -1;
+static int hf_efsrpc_data_size = -1;
+static int hf_efsrpc_cert_dn = -1;
+
+static gint ett_dcerpc_efs = -1;
+static gint ett_dcerpc_efs_cert_hash = -1;
+
+
+/*
+IDL [ uuid(c681d488-d850-11d0-8c52-00c04fd90f7e),
+IDL version(1.0),
+IDL implicit_handle(handle_t rpc_binding)
+IDL ] interface efsrpc
+*/
+
+
+static e_uuid_t uuid_dcerpc_efs = {
+ 0xc681d488, 0xd850, 0x11d0,
+ { 0x8c, 0x52, 0x00, 0xc0, 0x4f, 0xd9, 0x0f, 0x7e }
+};
+
+static guint16 ver_dcerpc_efs = 1;
+
+
+/*
+IDL long EfsRpcOpenFileRaw(
+IDL [out] [context_handle] void *pvContext,
+IDL [in] [string] wchar_t FileName,
+IDL [in] long Flags
+IDL );
+*/
+
+static int
+efsrpc_dissect_open_file_raw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint16),
+ hf_efsrpc_filename, TRUE, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_flags, NULL);
+
+ return offset;
+
+}
+
+static int
+efsrpc_dissect_open_file_raw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_hnd, NULL, NULL, TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+IDL long EfsRpcReadFileRaw(
+IDL [in] [context_handle] void *pvContext,
+IDL [out] ??? element_5
+IDL );
+*/
+
+static int
+efsrpc_dissect_read_file_raw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+
+}
+
+
+/*
+IDL long EfsRpcWriteFileRaw(
+IDL [in] [context_handle] void *pvContext,
+IDL [in] ??? element_7
+IDL );
+*/
+
+
+static int
+efsrpc_dissect_write_file_raw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+
+}
+
+
+static int
+efsrpc_dissect_write_file_raw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_rc, NULL);
+
+ return offset;
+
+}
+
+
+/*
+IDL
+IDL void EfsRpcCloseRaw(
+IDL [in,out] [context_handle] void *pvContext,
+IDL );
+*/
+
+
+static int
+efsrpc_dissect_close_file_raw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_hnd, NULL, NULL, FALSE, TRUE);
+
+ return offset;
+
+}
+
+
+static int
+efsrpc_dissect_close_file_raw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+
+}
+
+
+
+/*
+IDL long EfsRpcEncryptFileSrv(
+IDL [in] [string] wchar_t Filename
+IDL );
+ */
+
+static int
+efsrpc_dissect_encrypt_file_srv_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint16),
+ hf_efsrpc_filename, TRUE, NULL);
+
+ return offset;
+
+}
+
+
+static int
+efsrpc_dissect_encrypt_file_srv_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_rc, NULL);
+
+ return offset;
+
+}
+
+
+/*
+IDL long EfsRpcDecryptFileSrv(
+IDL [in] [string] wchar_t FileName,
+IDL [in] long Reserved
+IDL );
+*/
+
+
+static int
+efsrpc_dissect_decrypt_file_srv_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint16),
+ hf_efsrpc_filename, TRUE, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_reserved, NULL);
+
+ return offset;
+
+}
+
+
+static int
+efsrpc_dissect_decrypt_file_srv_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_rc, NULL);
+
+ return offset;
+
+}
+
+
+/*
+IDL typedef struct {
+IDL long cbData;
+IDL [size_is(cbData)] void *pbData;
+IDL } EFS_HASH_BLOB;
+*/
+
+static int
+efsrpc_dissect_EFS_HASH_BLOB_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 size;
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+
+ if(di->conformant_run){
+ return offset; /* cant modify offset while performing conformant run */
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_data_size, &size);
+
+ /* XXX insert some sort of proto_tree_add_item here and show hex data
+ of the blob */
+ offset += size;
+ return offset;
+}
+
+static int
+efsrpc_dissect_EFS_HASH_BLOB(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 size;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_data_size, &size);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ efsrpc_dissect_EFS_HASH_BLOB_data, NDR_POINTER_UNIQUE,
+ "HASH_BLOB", -1);
+
+ return offset;
+}
+
+
+static int
+efsrpc_dissect_efs_SID_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+/*
+IDL typedef struct {
+IDL long cbTotalLength;
+IDL SID *pUserSid;
+IDL EFS_HASH_BLOB *pHash;
+IDL [string] wchar_t lpDisplayInformation;
+IDL } ENCRYPTION_CERTIFICATE_HASH;
+*/
+
+static int
+efsrpc_dissect_ENCRYPTION_CERTIFICATE_HASH(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1, "ENCRYPTION_CERTIFICATE_HASH");
+ tree = proto_item_add_subtree(item, ett_dcerpc_efs_cert_hash);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_data_size, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ efsrpc_dissect_efs_SID_ptr, NDR_POINTER_UNIQUE,
+ "SID", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ efsrpc_dissect_EFS_HASH_BLOB, NDR_POINTER_UNIQUE,
+ "EFS_HASH_BLOB", -1);
+
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
+ "Certificate DN", hf_efsrpc_cert_dn, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ return offset;
+}
+
+
+static int
+efsrpc_dissect_ENCRYPTION_CERTIFICATE_HASH_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ efsrpc_dissect_ENCRYPTION_CERTIFICATE_HASH, NDR_POINTER_UNIQUE,
+ "ENCRYPTION_CERTIFICATE_HASH", -1);
+
+ return offset;
+
+}
+
+
+static int
+efsrpc_dissect_ENCRYPTION_CERTIFICATE_HASH_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ efsrpc_dissect_ENCRYPTION_CERTIFICATE_HASH_ptr);
+
+ return offset;
+}
+
+/*
+IDL typedef struct {
+IDL long nCert_Hash;
+IDL [size_is(nCert_Hash)] [unique] ENCRYPTION_CERTIFICATE_HASH *pUsers;
+IDL } ENCRYPTION_CERTIFICATE_HASH_LIST;
+*/
+
+static int
+efsrpc_dissect_ENCRYPTION_CERTIFICATE_HASH_LIST(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ efsrpc_dissect_ENCRYPTION_CERTIFICATE_HASH_array, NDR_POINTER_UNIQUE,
+ "ENCRYPTION_CERTIFICATE_HASH array:", -1);
+
+ return offset;
+
+}
+
+
+
+/*
+IDL long EfsRpcQueryUsersOnFile(
+IDL [in] [string] wchar_t FileName,
+IDL [out] [ref] ENCRYPTION_CERTIFICATE_HASH_LIST **pUsers
+IDL );
+*/
+
+
+static int
+efsrpc_dissect_query_users_on_file_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint16),
+ hf_efsrpc_filename, TRUE, NULL);
+
+
+ return offset;
+
+}
+
+
+static int
+efsrpc_dissect_query_users_on_file_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ efsrpc_dissect_ENCRYPTION_CERTIFICATE_HASH_LIST, NDR_POINTER_UNIQUE,
+ "ENCRYPTION_CERTIFICATE_HASH_LIST", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_rc, NULL);
+
+ return offset;
+
+}
+
+/*
+IDL long EfsRpcQueryRecoveryAgents(
+IDL [in] [string] wchar_t FileName,
+IDL [out] [ref] ENCRYPTION_CERTIFICATE_HASH_LIST **pRecoveryAgents
+IDL );
+*/
+
+static int
+efsrpc_dissect_query_recovery_agents_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint16),
+ hf_efsrpc_filename, TRUE, NULL);
+
+ return offset;
+
+}
+
+
+static int
+efsrpc_dissect_query_recovery_agents_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ efsrpc_dissect_ENCRYPTION_CERTIFICATE_HASH_LIST, NDR_POINTER_UNIQUE,
+ "ENCRYPTION_CERTIFICATE_HASH_LIST", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_rc, NULL);
+
+ return offset;
+
+
+}
+
+
+
+/*
+IDL long EfsRpcRemoveUsersFromFile(
+IDL [in] [string] wchar_t FileName,
+IDL [in] ENCRYPTION_CERTIFICATE_LIST Hashes
+IDL );
+*/
+
+static int
+efsrpc_dissect_remove_users_from_file_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint16),
+ hf_efsrpc_filename, TRUE, NULL);
+#if 0
+ offset = efsrpc_dissect_ENCRYPTION_CERTIFICATE_LIST(tvb, offset,
+ pinfo, tree, drep);
+#endif
+ return offset;
+
+}
+
+
+static int
+efsrpc_dissect_remove_users_from_file_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_rc, NULL);
+
+ return offset;
+
+}
+
+/*
+IDL long EfsRpcAddUsersToFile(
+IDL [in] [string] wchar_t FileName,
+IDL [in] ENCRYPTION_CERTIFICATE_LIST Hashes
+IDL );
+*/
+
+static int
+efsrpc_dissect_add_users_from_file_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint16),
+ hf_efsrpc_filename, TRUE, NULL);
+#if 0
+ offset = efsrpc_dissect_ENCRYPTION_CERTIFICATE_LIST(tvb, offset,
+ pinfo, tree, drep);
+#endif
+ return offset;
+
+}
+
+
+static int
+efsrpc_dissect_add_users_from_file_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_efsrpc_rc, NULL);
+
+ return offset;
+
+}
+
+
+/*
+IDL typedef struct {
+IDL long dwCertEncodingType;
+IDL long cbData;
+IDL [size_is(cbData)] [unique] byte *pbData
+IDL } EFS_CERTIFICATE_BLOB;
+*/
+
+/*
+IDL typedef struct {
+IDL long TotalLength;
+IDL [unique] SID *pUserSid;
+IDL [unique] EFS_CERTIFICATE_BLOB *pCertBlob;
+IDL } ENCRYPTION_CERTIFICATE;
+*/
+
+/*
+IDL long EfsRpcSetFileEncryptionKey(
+IDL [in] [unique] ENCRYPTION_CERTIFICATE *pEncryptionCertificate
+IDL );
+*/
+
+static dcerpc_sub_dissector dcerpc_efs_dissectors[] = {
+ { EFS_RPC_OPEN_FILE_RAW , "EfsRpcOpenFileRaw",
+ efsrpc_dissect_open_file_raw_rqst,
+ efsrpc_dissect_open_file_raw_reply },
+ { EFS_RPC_READ_FILE_RAW, "EfsRpcReadFileRaw",
+ efsrpc_dissect_read_file_raw_rqst,
+ NULL },
+ { EFS_RPC_WRITE_FILE_RAW, "EfsRpcWriteFileRaw",
+ efsrpc_dissect_write_file_raw_rqst,
+ efsrpc_dissect_write_file_raw_reply },
+ { EFS_RPC_CLOSE_RAW, "EfsRpcCloseRaw",
+ efsrpc_dissect_close_file_raw_rqst,
+ efsrpc_dissect_close_file_raw_reply },
+ { EFS_RPC_ENCRYPT_FILE_SRV, "EfsRpcEncryptFileSrv",
+ efsrpc_dissect_encrypt_file_srv_rqst,
+ efsrpc_dissect_encrypt_file_srv_reply },
+ { EFS_RPC_DECRYPT_FILE_SRV, "EfsRpcDecryptFileSrv",
+ efsrpc_dissect_decrypt_file_srv_rqst,
+ efsrpc_dissect_decrypt_file_srv_reply },
+ { EFS_RPC_QUERY_USERS_ON_FILE, "EfsRpcQueryUsersOnFile",
+ efsrpc_dissect_query_users_on_file_rqst,
+ efsrpc_dissect_query_users_on_file_reply },
+ { EFS_RPC_QUERY_RECOVERY_AGENTS, "EfsRpcQueryRecoveryAgents",
+ efsrpc_dissect_query_recovery_agents_rqst,
+ efsrpc_dissect_query_recovery_agents_reply },
+ { EFS_RPC_REMOVE_USERS_FROM_FILE, "EfsRpcRemoveUsersFromFile",
+ efsrpc_dissect_remove_users_from_file_rqst,
+ efsrpc_dissect_remove_users_from_file_reply },
+ { EFS_RPC_ADD_USERS_TO_FILE, "EfsRpcAddUsersToFile",
+ efsrpc_dissect_add_users_from_file_rqst,
+ efsrpc_dissect_add_users_from_file_reply },
+ { EFS_RPC_SET_FILE_ENCRYPTION_KEY, "EfsRpcSetFileEncryptionKey"
+ , NULL, NULL },
+ { EFS_RPC_NOT_SUPPORTED, "EfsRpcNotSupported"
+ , NULL, NULL },
+ { EFS_RPC_FILE_KEY_INFO, "EfsRpcFileKeyInfo"
+ , NULL, NULL },
+ { EFS_RPC_DUPLICATE_ENCRYPTION_INFO_FILE,
+ "EfsRpcDuplicateEncryptionInfoFile", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_efs(void)
+{
+static hf_register_info hf[] = {
+ { &hf_efsrpc_opnum, {
+ "Operation", "efsrpc.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_efsrpc_rc, {
+ "Return code", "efsrpc.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "EFSRPC return code", HFILL }},
+ { &hf_efsrpc_filename,
+ { "Filename", "efsrpc.filename", FT_STRING, BASE_NONE,
+ NULL, 0x0, "File name", HFILL}},
+
+ { &hf_efsrpc_flags, {
+ "Flags", "efsrpc.flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "EFSRPC Flags", HFILL }},
+
+ { &hf_efsrpc_hnd, {
+ "Context Handle", "efsrpc.hnd", FT_BYTES,
+ BASE_NONE, NULL, 0x0, "Context Handle", HFILL}},
+
+ { &hf_efsrpc_reserved, {
+ "Reserved value", "efsrpc.reserved", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Reserved value", HFILL }},
+
+ { &hf_efsrpc_num_entries,
+ { "Number of entries", "efsrpc.num_entries", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of Entries", HFILL}},
+
+ { &hf_efsrpc_data_size,
+ { "Size of data structure", "efsrpc.data_size", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Size of data structure", HFILL}},
+
+ { &hf_efsrpc_cert_dn,
+ { "Certificate DN", "efsrpc.cert_dn", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Distinguished Name of EFS certificate", HFILL}},
+
+
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_efs,
+ &ett_dcerpc_efs_cert_hash
+ };
+
+ proto_dcerpc_efs = proto_register_protocol(
+ "Microsoft Encrypted File System Service", "EFSRPC", "efsrpc");
+
+ proto_register_field_array(proto_dcerpc_efs, hf,
+ array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_efs(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_efs, ett_dcerpc_efs,
+ &uuid_dcerpc_efs, ver_dcerpc_efs,
+ dcerpc_efs_dissectors, hf_efsrpc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-efs.h b/epan/dissectors/packet-dcerpc-efs.h
new file mode 100644
index 0000000000..31ac17a4d5
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-efs.h
@@ -0,0 +1,46 @@
+/* packet-dcerpc-efs.h
+ * Routines for the efsrpc MSRPC interface
+ * Copyright 2004 Ronnie Sahlberg, Jean-Baptiste Marchand
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_EFS_H
+#define __PACKET_DCERPC_EFS_H
+
+/* MSRPC functions available in the efsrpc interface */
+
+#define EFS_RPC_OPEN_FILE_RAW 0x00
+#define EFS_RPC_READ_FILE_RAW 0x01
+#define EFS_RPC_WRITE_FILE_RAW 0x02
+#define EFS_RPC_CLOSE_RAW 0x03
+#define EFS_RPC_ENCRYPT_FILE_SRV 0x04
+#define EFS_RPC_DECRYPT_FILE_SRV 0x05
+#define EFS_RPC_QUERY_USERS_ON_FILE 0x06
+#define EFS_RPC_QUERY_RECOVERY_AGENTS 0x07
+#define EFS_RPC_REMOVE_USERS_FROM_FILE 0x08
+#define EFS_RPC_ADD_USERS_TO_FILE 0x09
+#define EFS_RPC_SET_FILE_ENCRYPTION_KEY 0x0a
+#define EFS_RPC_NOT_SUPPORTED 0x0b
+#define EFS_RPC_FILE_KEY_INFO 0x0c
+#define EFS_RPC_DUPLICATE_ENCRYPTION_INFO_FILE 0x0d
+
+#endif /* packet-dcerpc-efs.h */
diff --git a/epan/dissectors/packet-dcerpc-epm.c b/epan/dissectors/packet-dcerpc-epm.c
new file mode 100644
index 0000000000..548a3a6c90
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-epm.c
@@ -0,0 +1,735 @@
+/* packet-dcerpc-epm.c
+ * Routines for dcerpc endpoint mapper dissection
+ * Copyright 2001, Todd Sabin <tas@webspan.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+
+
+static int proto_epm = -1;
+
+static int hf_epm_opnum = -1;
+static int hf_epm_inquiry_type = -1;
+static int hf_epm_object = -1;
+static int hf_epm_if_id = -1;
+static int hf_epm_ver_maj = -1;
+static int hf_epm_ver_min = -1;
+static int hf_epm_ver_opt = -1;
+static int hf_epm_hnd = -1;
+static int hf_epm_max_ents = -1;
+static int hf_epm_num_ents = -1;
+static int hf_epm_uuid = -1;
+static int hf_epm_tower_length = -1;
+static int hf_epm_tower_data = -1;
+static int hf_epm_max_towers = -1;
+static int hf_epm_num_towers = -1;
+static int hf_epm_rc = -1;
+static int hf_epm_replace = -1;
+static int hf_epm_tower_num_floors = -1;
+static int hf_epm_tower_rhs_len = -1;
+static int hf_epm_tower_lhs_len = -1;
+static int hf_epm_tower_proto_id = -1;
+static int hf_epm_annotation = -1;
+static int hf_epm_ann_offset = -1;
+static int hf_epm_ann_len = -1;
+static int hf_epm_proto_named_pipes = -1;
+static int hf_epm_proto_netbios_name = -1;
+static int hf_epm_proto_ip = -1;
+static int hf_epm_proto_udp_port = -1;
+static int hf_epm_proto_tcp_port = -1;
+
+static gint ett_epm = -1;
+static gint ett_epm_tower_floor = -1;
+static gint ett_epm_entry = -1;
+
+static e_uuid_t uuid_epm = { 0xe1af8308, 0x5d1f, 0x11c9, { 0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa } };
+static guint16 ver_epm = 3;
+
+static const value_string ep_service[] = {
+ { 0, "rpc_c_ep_all_elts" },
+ { 1, "rpc_c_ep_match_by_if" },
+ { 2, "rpc_c_ep_match_by_obj" },
+ { 3, "rpc_c_ep_match_by_both" },
+ { 0, NULL },
+};
+
+/* typedef struct {
+ unsigned int tower_len,
+ [size_is(tower_len)] char tower[];
+ } twr_t, *twr_p_t;
+*/
+static int epm_dissect_tower (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep);
+
+
+static int
+epm_dissect_pointer_IF_ID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_epm_ver_maj, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_epm_ver_min, NULL);
+ return offset;
+}
+
+static int
+epm_dissect_pointer_UUID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ return offset;
+}
+
+static int
+epm_dissect_ept_lookup_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_inquiry_type, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_pointer_UUID, NDR_POINTER_PTR,
+ "Object:", hf_epm_object);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_pointer_IF_ID, NDR_POINTER_PTR,
+ "Interface:", hf_epm_if_id);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_ver_opt, NULL);
+
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm_hnd, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_max_ents, NULL);
+ return offset;
+}
+
+
+static int
+epm_dissect_ept_entry_t(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint32 len;
+ gint strlen;
+ dcerpc_info *di;
+ const char *str;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ return offset;
+ }
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1, "Entry:");
+ tree = proto_item_add_subtree(item, ett_epm_entry);
+ }
+
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ hf_epm_object, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_tower, NDR_POINTER_PTR,
+ "Tower pointer:", -1);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_ann_offset, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_ann_len, &len);
+ str=(const char *)tvb_get_ptr(tvb, offset, -1);
+ strlen=len;
+ strlen=MIN(strlen,tvb_length_remaining(tvb, offset));
+ proto_tree_add_item(tree, hf_epm_annotation, tvb, offset, len, TRUE);
+ offset += len;
+
+ if(str&&str[0]){
+ if(parent_tree) {
+ proto_item_append_text(item, " Service:%*s ", strlen, str);
+ proto_item_append_text(tree->parent, " Service:%*s ", strlen, str);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Service:%*s", strlen, str);
+ }
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+epm_dissect_ept_entry_t_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
+ epm_dissect_ept_entry_t);
+
+ return offset;
+}
+
+static int
+epm_dissect_ept_lookup_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm_hnd, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_num_ents, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_ept_entry_t_array, NDR_POINTER_REF,
+ "Entries:", -1);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_rc, NULL);
+
+ return offset;
+}
+
+static int
+epm_dissect_uuid (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ hf_epm_uuid, NULL);
+ return offset;
+}
+
+#define PROTO_ID_OSI_OID 0x00
+#define PROTO_ID_DNA_SESSCTL 0x02
+#define PROTO_ID_DNA_SESSCTL_V3 0x03
+#define PROTO_ID_DNA_NSP 0x04
+#define PROTO_ID_OSI_TP4 0x05
+#define PROTO_ID_OSI_CLNS 0x06
+#define PROTO_ID_TCP 0x07
+#define PROTO_ID_UDP 0x08
+#define PROTO_ID_IP 0x09
+#define PROTO_ID_RPC_CL 0x0a
+#define PROTO_ID_RPC_CO 0x0b
+#define PROTO_ID_UUID 0x0d
+#define PROTO_ID_NAMED_PIPES 0x0f
+#define PROTO_ID_NAMED_PIPES_2 0x10
+#define PROTO_ID_NETBIOS 0x11
+#define PROTO_ID_NETBEUI 0x12
+#define PROTO_ID_NETWARE_SPX 0x13
+#define PROTO_ID_NETWARE_IPX 0x14
+#define PROTO_ID_ATALK_STREAM 0x16
+#define PROTO_ID_ATALK_DATAGRAM 0x17
+#define PROTO_ID_ATALK 0x18
+#define PROTO_ID_NETBIOS_2 0x19
+#define PROTO_ID_VINES_SPP 0x1a
+#define PROTO_ID_VINES_IPC 0x1b
+#define PROTO_ID_STREETTALK 0x1c
+#define PROTO_ID_UNIX_DOMAIN 0x20
+#define PROTO_ID_NULL 0x21
+#define PROTO_ID_NETBIOS_3 0x22
+
+static const value_string proto_id_vals[] = {
+ { PROTO_ID_OSI_OID, "OSI OID"},
+ { PROTO_ID_DNA_SESSCTL, "DNA Session Control"},
+ { PROTO_ID_DNA_SESSCTL_V3, "DNA Session Control V3"},
+ { PROTO_ID_DNA_NSP, "DNA NSP Transport"},
+ { PROTO_ID_OSI_TP4, "OSI TP4"},
+ { PROTO_ID_OSI_CLNS, "OSI CLNS or DNA Routing"},
+ { PROTO_ID_TCP, "DOD TCP"},
+ { PROTO_ID_UDP, "DOD UDP"},
+ { PROTO_ID_IP, "DOD IP"},
+ { PROTO_ID_RPC_CL, "RPC connectionless protocol"},
+ { PROTO_ID_RPC_CO, "RPC connection-oriented protocol"},
+ { PROTO_ID_UUID, "UUID"},
+ { PROTO_ID_NAMED_PIPES, "Named Pipes"},
+ { PROTO_ID_NAMED_PIPES_2, "Named Pipes"},
+ { PROTO_ID_NETBIOS, "NetBIOS"},
+ { PROTO_ID_NETBEUI, "NetBEUI"},
+ { PROTO_ID_NETWARE_SPX, "Netware SPX"},
+ { PROTO_ID_NETWARE_IPX, "Netware IPX"},
+ { PROTO_ID_ATALK_STREAM, "Appletalk Stream"},
+ { PROTO_ID_ATALK_DATAGRAM, "Appletalk Datagram"},
+ { PROTO_ID_ATALK, "Appletalk"},
+ { PROTO_ID_NETBIOS_2, "NetBIOS"},
+ { PROTO_ID_VINES_SPP, "Vines SPP"},
+ { PROTO_ID_VINES_IPC, "Vines IPC"},
+ { PROTO_ID_STREETTALK, "StreetTalk"},
+ { PROTO_ID_UNIX_DOMAIN, "Unix Domain Socket"},
+ { PROTO_ID_NULL, "null"},
+ { PROTO_ID_NETBIOS_3, "NetBIOS"},
+ { 0, NULL},
+};
+
+
+/* XXX this function assumes LE encoding. can not use the NDR routines
+ since they assume padding.
+*/
+static int
+epm_dissect_tower_data (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 num_floors, i;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ return offset;
+ }
+
+ num_floors = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_epm_tower_num_floors, tvb, offset, 2, num_floors);
+ offset += 2;
+
+ for(i=1;i<=num_floors;i++){
+ proto_item *it = NULL;
+ proto_tree *tr = NULL;
+ int old_offset = offset;
+ guint16 len;
+ guint8 proto_id;
+ e_uuid_t uuid;
+
+ it = proto_tree_add_text(tree, tvb, offset, 0, "Floor %d ", i);
+ tr = proto_item_add_subtree(it, ett_epm_tower_floor);
+
+ len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tr, hf_epm_tower_lhs_len, tvb, offset, 2, len);
+ offset += 2;
+
+ proto_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tr, hf_epm_tower_proto_id, tvb, offset, 1, proto_id);
+
+ switch(proto_id){
+ case PROTO_ID_UUID:
+ dcerpc_tvb_get_uuid (tvb, offset+1, drep, &uuid);
+
+ proto_tree_add_string_format (tr, hf_epm_uuid, tvb, offset+1, 16, "",
+ "UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.Data1, uuid.Data2, uuid.Data3,
+ uuid.Data4[0], uuid.Data4[1],
+ uuid.Data4[2], uuid.Data4[3],
+ uuid.Data4[4], uuid.Data4[5],
+ uuid.Data4[6], uuid.Data4[7]);
+ proto_tree_add_text(tr, tvb, offset+17, 2, "Version %d.%d", tvb_get_guint8(tvb, offset+17), tvb_get_guint8(tvb, offset+18));
+
+ {
+ guint16 version = tvb_get_ntohs(tvb, offset+17);
+ char *service = dcerpc_get_proto_name(&uuid, version);
+ if (service)
+ proto_item_append_text(tr, "UUID: %s", service);
+ else
+ proto_item_append_text(tr, "UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x Version %d.%d", uuid.Data1, uuid.Data2, uuid.Data3,
+ uuid.Data4[0], uuid.Data4[1],
+ uuid.Data4[2], uuid.Data4[3],
+ uuid.Data4[4], uuid.Data4[5],
+ uuid.Data4[6], uuid.Data4[7],
+ tvb_get_guint8(tvb, offset+17),
+ tvb_get_guint8(tvb, offset+18));
+ }
+ break;
+ }
+ offset += len;
+
+ len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tr, hf_epm_tower_rhs_len, tvb, offset, 2, len);
+ offset += 2;
+
+ switch(proto_id){
+
+ case PROTO_ID_TCP: /* this one is always big endian */
+ proto_tree_add_item(tr, hf_epm_proto_tcp_port, tvb, offset, 2, FALSE);
+ proto_item_append_text(tr, "TCP Port:%d", tvb_get_ntohs(tvb, offset));
+ break;
+
+ case PROTO_ID_UDP: /* this one is always big endian */
+ proto_tree_add_item(tr, hf_epm_proto_udp_port, tvb, offset, 2, FALSE);
+ proto_item_append_text(tr, "UDP Port:%d", tvb_get_ntohs(tvb, offset));
+ break;
+
+ case PROTO_ID_IP: /* this one is always big endian */
+ proto_tree_add_item(tr, hf_epm_proto_ip, tvb, offset, 4, TRUE);
+ proto_item_append_text(tr, "IP:%s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ break;
+
+ case PROTO_ID_RPC_CO:
+ proto_item_append_text(tr, "RPC connection-oriented protocol");
+ break;
+
+ case PROTO_ID_NAMED_PIPES: /* \\PIPE\xxx named pipe */
+ proto_tree_add_item(tr, hf_epm_proto_named_pipes, tvb, offset, len, TRUE);
+ proto_item_append_text(tr, "NamedPipe:%*s",MIN(len,tvb_length_remaining(tvb, offset)), tvb_get_ptr(tvb, offset, -1));
+ break;
+
+ case PROTO_ID_NAMED_PIPES_2: /* PIPENAME named pipe */
+ proto_tree_add_item(tr, hf_epm_proto_named_pipes, tvb, offset, len, TRUE);
+ proto_item_append_text(tr, "PIPE:%*s",MIN(len,tvb_length_remaining(tvb, offset)), tvb_get_ptr(tvb, offset, -1));
+ break;
+
+ case PROTO_ID_NETBIOS: /* \\NETBIOS netbios name */
+ proto_tree_add_item(tr, hf_epm_proto_netbios_name, tvb, offset, len, TRUE);
+ proto_item_append_text(tr, "NetBIOS:%*s",MIN(len,tvb_length_remaining(tvb, offset)), tvb_get_ptr(tvb, offset, -1));
+ break;
+
+ default:
+ if(len){
+ proto_tree_add_text(tr, tvb, offset, len, "not decoded yet");
+ }
+ }
+ offset += len;
+
+ proto_item_set_len(it, offset-old_offset);
+ }
+ return offset;
+}
+
+/* typedef struct {
+ unsigned int tower_len,
+ [size_is(tower_len)] char tower[];
+ } twr_t, *twr_p_t;
+*/
+static int
+epm_dissect_tower (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ return offset;
+ }
+
+ /* first one is the header of the conformant array, second one is the
+ length field */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_tower_length, &len);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_tower_length, NULL);
+ offset = epm_dissect_tower_data(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+static int
+epm_dissect_tower_pointer (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_tower, NDR_POINTER_PTR,
+ "Tower pointer:", -1);
+ return offset;
+}
+static int
+epm_dissect_tower_array (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
+ epm_dissect_tower_pointer);
+
+ return offset;
+}
+
+static int
+epm_dissect_ept_map_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [in, ptr] uuid_p_t object */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_uuid, NDR_POINTER_PTR,
+ "UUID pointer:", -1);
+
+ /* [in, ptr] twr_p_t map_tower */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_tower, NDR_POINTER_PTR,
+ "Tower pointer:", -1);
+
+ /* [in, out] ept_lookup_handle_t *entry_handle */
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm_hnd, NULL);
+
+ /* [in] unsigned32 max_towers */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_max_towers, NULL);
+
+ return offset;
+}
+
+static int
+epm_dissect_ept_map_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [in, out] ept_lookup_handle_t *entry_handle */
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm_hnd, NULL);
+
+ /* [out, ptr] unsigned32 *num_towers */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_num_towers, NULL);
+
+ /* [out, length_is(*num_towers), size_is(max_towers), ptr] twr_p_t towers[] */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_tower_array, NDR_POINTER_REF,
+ "Tower array:", -1);
+
+ /* [out] error_status_t *status */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_rc, NULL);
+
+ return offset;
+}
+
+static int
+epm_dissect_ept_entry_t_ucarray(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ epm_dissect_ept_entry_t);
+
+ return offset;
+}
+
+static int
+epm_dissect_ept_insert_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_num_ents, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_ept_entry_t_ucarray, NDR_POINTER_REF,
+ "Entries:", -1);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_replace, NULL);
+
+ return offset;
+}
+
+
+
+static int
+epm_dissect_ept_insert_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [out] error_status_t *status */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+epm_dissect_ept_delete_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_num_ents, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm_dissect_ept_entry_t_ucarray, NDR_POINTER_REF,
+ "Entries:", -1);
+
+ return offset;
+}
+
+
+
+static int
+epm_dissect_ept_delete_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [out] error_status_t *status */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_rc, NULL);
+
+ return offset;
+}
+
+
+
+static int
+epm_dissect_ept_lookup_handle_free_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [in, out] ept_lookup_handle_t *entry_handle */
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm_hnd, NULL);
+
+ return offset;
+}
+
+static int
+epm_dissect_ept_lookup_handle_free_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [in, out] ept_lookup_handle_t *entry_handle */
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm_hnd, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm_rc, NULL);
+
+ return offset;
+}
+
+
+static dcerpc_sub_dissector epm_dissectors[] = {
+ { 0, "Insert",
+ epm_dissect_ept_insert_rqst,
+ epm_dissect_ept_insert_resp },
+ { 1, "Delete",
+ epm_dissect_ept_delete_rqst,
+ epm_dissect_ept_delete_resp },
+ { 2, "Lookup",
+ epm_dissect_ept_lookup_rqst,
+ epm_dissect_ept_lookup_resp },
+ { 3, "Map",
+ epm_dissect_ept_map_rqst,
+ epm_dissect_ept_map_resp },
+ { 4, "LookupHandleFree",
+ epm_dissect_ept_lookup_handle_free_rqst,
+ epm_dissect_ept_lookup_handle_free_resp },
+ { 5, "InqObject", NULL, NULL },
+ { 6, "MgmtDelete", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_epm (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_epm_opnum,
+ { "Operation", "epm.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ { &hf_epm_inquiry_type,
+ { "Inquiry type", "epm.inq_type", FT_UINT32, BASE_DEC, VALS(ep_service), 0x0, "", HFILL }},
+ { &hf_epm_object,
+ { "Object", "epm.object", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_epm_if_id,
+ { "Interface", "epm.if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_epm_ver_maj,
+ { "Version Major", "epm.ver_maj", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm_ver_min,
+ { "Version Minor", "epm.ver_min", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm_ver_opt,
+ { "Version Option", "epm.ver_opt", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm_hnd,
+ { "Handle", "epm.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "Context handle", HFILL }},
+ { &hf_epm_max_ents,
+ { "Max entries", "epm.max_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm_num_ents,
+ { "Num entries", "epm.num_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm_uuid,
+ { "UUID", "epm.uuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL }},
+ { &hf_epm_annotation,
+ { "Annotation", "epm.annotation", FT_STRING, BASE_NONE, NULL, 0x0, "Annotation", HFILL }},
+ { &hf_epm_proto_named_pipes,
+ { "Named Pipe", "epm.proto.named_pipe", FT_STRING, BASE_NONE, NULL, 0x0, "Name of the named pipe for this service", HFILL }},
+ { &hf_epm_proto_netbios_name,
+ { "NetBIOS Name", "epm.proto.netbios_name", FT_STRING, BASE_NONE, NULL, 0x0, "NetBIOS name where this service can be found", HFILL }},
+ { &hf_epm_tower_length,
+ { "Length", "epm.tower.len", FT_UINT32, BASE_DEC, NULL, 0x0, "Length of tower data", HFILL }},
+ { &hf_epm_tower_data,
+ { "Tower", "epm.tower", FT_BYTES, BASE_HEX, NULL, 0x0, "Tower data", HFILL }},
+ { &hf_epm_max_towers,
+ { "Max Towers", "epm.max_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum number of towers to return", HFILL }},
+ { &hf_epm_num_towers,
+ { "Num Towers", "epm.num_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Number number of towers to return", HFILL }},
+ { &hf_epm_ann_offset,
+ { "Annotation offset", "epm.ann_offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm_ann_len,
+ { "Annotation length", "epm.ann_len", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm_rc,
+ { "Return code", "epm.rc", FT_UINT32, BASE_HEX, NULL, 0x0, "EPM return value", HFILL }},
+ { &hf_epm_replace,
+ { "Replace", "epm.replace", FT_UINT8, BASE_DEC, NULL, 0x0, "Replace existing objects?", HFILL }},
+ { &hf_epm_tower_num_floors,
+ { "Number of floors", "epm.tower.num_floors", FT_UINT16, BASE_DEC, NULL, 0x0, "Number of floors in tower", HFILL }},
+ { &hf_epm_proto_udp_port,
+ { "UDP Port", "epm.proto.udp_port", FT_UINT16, BASE_DEC, NULL, 0x0, "UDP Port where this service can be found", HFILL }},
+ { &hf_epm_proto_tcp_port,
+ { "TCP Port", "epm.proto.tcp_port", FT_UINT16, BASE_DEC, NULL, 0x0, "TCP Port where this service can be found", HFILL }},
+ { &hf_epm_tower_rhs_len,
+ { "RHS Length", "epm.tower.rhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of RHS data", HFILL }},
+ { &hf_epm_tower_lhs_len,
+ { "LHS Length", "epm.tower.lhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of LHS data", HFILL }},
+ { &hf_epm_proto_ip,
+ { "IP", "epm.proto.ip", FT_IPv4, BASE_NONE, NULL, 0x0, "IP address where service is located", HFILL }},
+ { &hf_epm_tower_proto_id,
+ { "Protocol", "epm.tower.proto_id", FT_UINT8, BASE_HEX, VALS(proto_id_vals), 0x0, "Protocol identifier", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_epm,
+ &ett_epm_tower_floor,
+ &ett_epm_entry
+ };
+ proto_epm = proto_register_protocol ("DCE/RPC Endpoint Mapper", "EPM", "epm");
+ proto_register_field_array (proto_epm, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_epm (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_epm, ett_epm, &uuid_epm, ver_epm, epm_dissectors, hf_epm_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-epm4.c b/epan/dissectors/packet-dcerpc-epm4.c
new file mode 100644
index 0000000000..5d4c3ad385
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-epm4.c
@@ -0,0 +1,735 @@
+/* packet-dcerpc-epm4.c
+ * Routines for dcerpc endpoint mapper dissection
+ * Copyright 2001, Todd Sabin <tas@webspan.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+
+
+static int proto_epm4 = -1;
+
+static int hf_epm4_opnum = -1;
+static int hf_epm4_inquiry_type = -1;
+static int hf_epm4_object = -1;
+static int hf_epm4_if_id = -1;
+static int hf_epm4_ver_maj = -1;
+static int hf_epm4_ver_min = -1;
+static int hf_epm4_ver_opt = -1;
+static int hf_epm4_hnd = -1;
+static int hf_epm4_max_ents = -1;
+static int hf_epm4_num_ents = -1;
+static int hf_epm4_uuid = -1;
+static int hf_epm4_tower_length = -1;
+static int hf_epm4_tower_data = -1;
+static int hf_epm4_max_towers = -1;
+static int hf_epm4_num_towers = -1;
+static int hf_epm4_rc = -1;
+static int hf_epm4_replace = -1;
+static int hf_epm4_tower_num_floors = -1;
+static int hf_epm4_tower_rhs_len = -1;
+static int hf_epm4_tower_lhs_len = -1;
+static int hf_epm4_tower_proto_id = -1;
+static int hf_epm4_annotation = -1;
+static int hf_epm4_ann_offset = -1;
+static int hf_epm4_ann_len = -1;
+static int hf_epm4_proto_named_pipes = -1;
+static int hf_epm4_proto_netbios_name = -1;
+static int hf_epm4_proto_ip = -1;
+static int hf_epm4_proto_udp_port = -1;
+static int hf_epm4_proto_tcp_port = -1;
+
+static gint ett_epm4 = -1;
+static gint ett_epm4_tower_floor = -1;
+static gint ett_epm4_entry = -1;
+
+static e_uuid_t uuid_epm4 = { 0xe1af8308, 0x5d1f, 0x11c9, { 0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa } };
+static guint16 ver_epm4 = 4;
+
+static const value_string ep_service[] = {
+ { 0, "rpc_c_ep_all_elts" },
+ { 1, "rpc_c_ep_match_by_if" },
+ { 2, "rpc_c_ep_match_by_obj" },
+ { 3, "rpc_c_ep_match_by_both" },
+ { 0, NULL },
+};
+
+/* typedef struct {
+ unsigned int tower_len,
+ [size_is(tower_len)] char tower[];
+ } twr_t, *twr_p_t;
+*/
+static int epm4_dissect_tower (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep);
+
+
+static int
+epm4_dissect_pointer_IF_ID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_ver_maj, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_ver_min, NULL);
+ return offset;
+}
+
+static int
+epm4_dissect_pointer_UUID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ return offset;
+}
+
+static int
+epm4_dissect_ept_lookup_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_inquiry_type, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_pointer_UUID, NDR_POINTER_PTR,
+ "Object:", hf_epm4_object);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_pointer_IF_ID, NDR_POINTER_PTR,
+ "Interface:", hf_epm4_if_id);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_ver_opt, NULL);
+
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm4_hnd, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_max_ents, NULL);
+ return offset;
+}
+
+
+static int
+epm4_dissect_ept_entry_t(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint32 len;
+ gint strlen;
+ dcerpc_info *di;
+ const char *str;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ return offset;
+ }
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1, "Entry:");
+ tree = proto_item_add_subtree(item, ett_epm4_entry);
+ }
+
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ hf_epm4_object, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_tower, NDR_POINTER_PTR,
+ "Tower pointer:", -1);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_ann_offset, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_ann_len, &len);
+ str=(const char *)tvb_get_ptr(tvb, offset, -1);
+ strlen=len;
+ strlen=MIN(strlen,tvb_length_remaining(tvb, offset));
+ proto_tree_add_item(tree, hf_epm4_annotation, tvb, offset, len, TRUE);
+ offset += len;
+
+ if(str&&str[0]){
+ if(parent_tree) {
+ proto_item_append_text(item, " Service:%*s ", strlen, str);
+ proto_item_append_text(tree->parent, " Service:%*s ", strlen, str);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Service:%*s", strlen, str);
+ }
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+epm4_dissect_ept_entry_t_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_ept_entry_t);
+
+ return offset;
+}
+
+static int
+epm4_dissect_ept_lookup_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm4_hnd, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_num_ents, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_ept_entry_t_array, NDR_POINTER_REF,
+ "Entries:", -1);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_rc, NULL);
+
+ return offset;
+}
+
+static int
+epm4_dissect_uuid (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ hf_epm4_uuid, NULL);
+ return offset;
+}
+
+#define PROTO_ID_OSI_OID 0x00
+#define PROTO_ID_DNA_SESSCTL 0x02
+#define PROTO_ID_DNA_SESSCTL_V3 0x03
+#define PROTO_ID_DNA_NSP 0x04
+#define PROTO_ID_OSI_TP4 0x05
+#define PROTO_ID_OSI_CLNS 0x06
+#define PROTO_ID_TCP 0x07
+#define PROTO_ID_UDP 0x08
+#define PROTO_ID_IP 0x09
+#define PROTO_ID_RPC_CL 0x0a
+#define PROTO_ID_RPC_CO 0x0b
+#define PROTO_ID_UUID 0x0d
+#define PROTO_ID_NAMED_PIPES 0x0f
+#define PROTO_ID_NAMED_PIPES_2 0x10
+#define PROTO_ID_NETBIOS 0x11
+#define PROTO_ID_NETBEUI 0x12
+#define PROTO_ID_NETWARE_SPX 0x13
+#define PROTO_ID_NETWARE_IPX 0x14
+#define PROTO_ID_ATALK_STREAM 0x16
+#define PROTO_ID_ATALK_DATAGRAM 0x17
+#define PROTO_ID_ATALK 0x18
+#define PROTO_ID_NETBIOS_2 0x19
+#define PROTO_ID_VINES_SPP 0x1a
+#define PROTO_ID_VINES_IPC 0x1b
+#define PROTO_ID_STREETTALK 0x1c
+#define PROTO_ID_UNIX_DOMAIN 0x20
+#define PROTO_ID_NULL 0x21
+#define PROTO_ID_NETBIOS_3 0x22
+
+static const value_string proto_id_vals[] = {
+ { PROTO_ID_OSI_OID, "OSI OID"},
+ { PROTO_ID_DNA_SESSCTL, "DNA Session Control"},
+ { PROTO_ID_DNA_SESSCTL_V3, "DNA Session Control V3"},
+ { PROTO_ID_DNA_NSP, "DNA NSP Transport"},
+ { PROTO_ID_OSI_TP4, "OSI TP4"},
+ { PROTO_ID_OSI_CLNS, "OSI CLNS or DNA Routing"},
+ { PROTO_ID_TCP, "DOD TCP"},
+ { PROTO_ID_UDP, "DOD UDP"},
+ { PROTO_ID_IP, "DOD IP"},
+ { PROTO_ID_RPC_CL, "RPC connectionless protocol"},
+ { PROTO_ID_RPC_CO, "RPC connection-oriented protocol"},
+ { PROTO_ID_UUID, "UUID"},
+ { PROTO_ID_NAMED_PIPES, "Named Pipes"},
+ { PROTO_ID_NAMED_PIPES_2, "Named Pipes"},
+ { PROTO_ID_NETBIOS, "NetBIOS"},
+ { PROTO_ID_NETBEUI, "NetBEUI"},
+ { PROTO_ID_NETWARE_SPX, "Netware SPX"},
+ { PROTO_ID_NETWARE_IPX, "Netware IPX"},
+ { PROTO_ID_ATALK_STREAM, "Appletalk Stream"},
+ { PROTO_ID_ATALK_DATAGRAM, "Appletalk Datagram"},
+ { PROTO_ID_ATALK, "Appletalk"},
+ { PROTO_ID_NETBIOS_2, "NetBIOS"},
+ { PROTO_ID_VINES_SPP, "Vines SPP"},
+ { PROTO_ID_VINES_IPC, "Vines IPC"},
+ { PROTO_ID_STREETTALK, "StreetTalk"},
+ { PROTO_ID_UNIX_DOMAIN, "Unix Domain Socket"},
+ { PROTO_ID_NULL, "null"},
+ { PROTO_ID_NETBIOS_3, "NetBIOS"},
+ { 0, NULL},
+};
+
+
+/* XXX this function assumes LE encoding. can not use the NDR routines
+ since they assume padding.
+*/
+static int
+epm4_dissect_tower_data (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 num_floors, i;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ return offset;
+ }
+
+ num_floors = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_epm4_tower_num_floors, tvb, offset, 2, num_floors);
+ offset += 2;
+
+ for(i=1;i<=num_floors;i++){
+ proto_item *it = NULL;
+ proto_tree *tr = NULL;
+ int old_offset = offset;
+ guint16 len;
+ guint8 proto_id;
+ e_uuid_t uuid;
+
+ it = proto_tree_add_text(tree, tvb, offset, 0, "Floor %d ", i);
+ tr = proto_item_add_subtree(it, ett_epm4_tower_floor);
+
+ len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tr, hf_epm4_tower_lhs_len, tvb, offset, 2, len);
+ offset += 2;
+
+ proto_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tr, hf_epm4_tower_proto_id, tvb, offset, 1, proto_id);
+
+ switch(proto_id){
+ case PROTO_ID_UUID:
+ dcerpc_tvb_get_uuid (tvb, offset+1, drep, &uuid);
+
+ proto_tree_add_string_format (tr, hf_epm4_uuid, tvb, offset+1, 16, "",
+ "UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.Data1, uuid.Data2, uuid.Data3,
+ uuid.Data4[0], uuid.Data4[1],
+ uuid.Data4[2], uuid.Data4[3],
+ uuid.Data4[4], uuid.Data4[5],
+ uuid.Data4[6], uuid.Data4[7]);
+ proto_tree_add_text(tr, tvb, offset+17, 2, "Version %d.%d", tvb_get_guint8(tvb, offset+17), tvb_get_guint8(tvb, offset+18));
+
+ {
+ guint16 version = tvb_get_ntohs(tvb, offset+17);
+ char *service = dcerpc_get_proto_name(&uuid, version);
+ if (service)
+ proto_item_append_text(tr, "UUID: %s", service);
+ else
+ proto_item_append_text(tr, "UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x Version %d.%d", uuid.Data1, uuid.Data2, uuid.Data3,
+ uuid.Data4[0], uuid.Data4[1],
+ uuid.Data4[2], uuid.Data4[3],
+ uuid.Data4[4], uuid.Data4[5],
+ uuid.Data4[6], uuid.Data4[7],
+ tvb_get_guint8(tvb, offset+17),
+ tvb_get_guint8(tvb, offset+18));
+ }
+ break;
+ }
+ offset += len;
+
+ len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tr, hf_epm4_tower_rhs_len, tvb, offset, 2, len);
+ offset += 2;
+
+ switch(proto_id){
+
+ case PROTO_ID_TCP: /* this one is always big endian */
+ proto_tree_add_item(tr, hf_epm4_proto_tcp_port, tvb, offset, 2, FALSE);
+ proto_item_append_text(tr, "TCP Port:%d", tvb_get_ntohs(tvb, offset));
+ break;
+
+ case PROTO_ID_UDP: /* this one is always big endian */
+ proto_tree_add_item(tr, hf_epm4_proto_udp_port, tvb, offset, 2, FALSE);
+ proto_item_append_text(tr, "UDP Port:%d", tvb_get_ntohs(tvb, offset));
+ break;
+
+ case PROTO_ID_IP: /* this one is always big endian */
+ proto_tree_add_item(tr, hf_epm4_proto_ip, tvb, offset, 4, TRUE);
+ proto_item_append_text(tr, "IP:%s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ break;
+
+ case PROTO_ID_RPC_CO:
+ proto_item_append_text(tr, "RPC connection-oriented protocol");
+ break;
+
+ case PROTO_ID_NAMED_PIPES: /* \\PIPE\xxx named pipe */
+ proto_tree_add_item(tr, hf_epm4_proto_named_pipes, tvb, offset, len, TRUE);
+ proto_item_append_text(tr, "NamedPipe:%*s",MIN(len,tvb_length_remaining(tvb, offset)), tvb_get_ptr(tvb, offset, -1));
+ break;
+
+ case PROTO_ID_NAMED_PIPES_2: /* PIPENAME named pipe */
+ proto_tree_add_item(tr, hf_epm4_proto_named_pipes, tvb, offset, len, TRUE);
+ proto_item_append_text(tr, "PIPE:%*s",MIN(len,tvb_length_remaining(tvb, offset)), tvb_get_ptr(tvb, offset, -1));
+ break;
+
+ case PROTO_ID_NETBIOS: /* \\NETBIOS netbios name */
+ proto_tree_add_item(tr, hf_epm4_proto_netbios_name, tvb, offset, len, TRUE);
+ proto_item_append_text(tr, "NetBIOS:%*s",MIN(len,tvb_length_remaining(tvb, offset)), tvb_get_ptr(tvb, offset, -1));
+ break;
+
+ default:
+ if(len){
+ proto_tree_add_text(tr, tvb, offset, len, "not decoded yet");
+ }
+ }
+ offset += len;
+
+ proto_item_set_len(it, offset-old_offset);
+ }
+ return offset;
+}
+
+/* typedef struct {
+ unsigned int tower_len,
+ [size_is(tower_len)] char tower[];
+ } twr_t, *twr_p_t;
+*/
+static int
+epm4_dissect_tower (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ return offset;
+ }
+
+ /* first one is the header of the conformant array, second one is the
+ length field */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_tower_length, &len);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_tower_length, NULL);
+ offset = epm4_dissect_tower_data(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+static int
+epm4_dissect_tower_pointer (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_tower, NDR_POINTER_PTR,
+ "Tower pointer:", -1);
+ return offset;
+}
+static int
+epm4_dissect_tower_array (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_tower_pointer);
+
+ return offset;
+}
+
+static int
+epm4_dissect_ept_map_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [in, ptr] uuid_p_t object */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_uuid, NDR_POINTER_PTR,
+ "UUID pointer:", -1);
+
+ /* [in, ptr] twr_p_t map_tower */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_tower, NDR_POINTER_PTR,
+ "Tower pointer:", -1);
+
+ /* [in, out] ept_lookup_handle_t *entry_handle */
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm4_hnd, NULL);
+
+ /* [in] unsigned32 max_towers */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_max_towers, NULL);
+
+ return offset;
+}
+
+static int
+epm4_dissect_ept_map_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [in, out] ept_lookup_handle_t *entry_handle */
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm4_hnd, NULL);
+
+ /* [out, ptr] unsigned32 *num_towers */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_num_towers, NULL);
+
+ /* [out, length_is(*num_towers), size_is(max_towers), ptr] twr_p_t towers[] */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_tower_array, NDR_POINTER_REF,
+ "Tower array:", -1);
+
+ /* [out] error_status_t *status */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_rc, NULL);
+
+ return offset;
+}
+
+static int
+epm4_dissect_ept_entry_t_ucarray(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_ept_entry_t);
+
+ return offset;
+}
+
+static int
+epm4_dissect_ept_insert_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_num_ents, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_ept_entry_t_ucarray, NDR_POINTER_REF,
+ "Entries:", -1);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_replace, NULL);
+
+ return offset;
+}
+
+
+
+static int
+epm4_dissect_ept_insert_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [out] error_status_t *status */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+epm4_dissect_ept_delete_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_num_ents, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ epm4_dissect_ept_entry_t_ucarray, NDR_POINTER_REF,
+ "Entries:", -1);
+
+ return offset;
+}
+
+
+
+static int
+epm4_dissect_ept_delete_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [out] error_status_t *status */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_rc, NULL);
+
+ return offset;
+}
+
+
+
+static int
+epm4_dissect_ept_lookup_handle_free_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [in, out] ept_lookup_handle_t *entry_handle */
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm4_hnd, NULL);
+
+ return offset;
+}
+
+static int
+epm4_dissect_ept_lookup_handle_free_resp (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [in, out] ept_lookup_handle_t *entry_handle */
+ offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
+ hf_epm4_hnd, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_epm4_rc, NULL);
+
+ return offset;
+}
+
+
+static dcerpc_sub_dissector epm4_dissectors[] = {
+ { 0, "Insert",
+ epm4_dissect_ept_insert_rqst,
+ epm4_dissect_ept_insert_resp },
+ { 1, "Delete",
+ epm4_dissect_ept_delete_rqst,
+ epm4_dissect_ept_delete_resp },
+ { 2, "Lookup",
+ epm4_dissect_ept_lookup_rqst,
+ epm4_dissect_ept_lookup_resp },
+ { 3, "Map",
+ epm4_dissect_ept_map_rqst,
+ epm4_dissect_ept_map_resp },
+ { 4, "LookupHandleFree",
+ epm4_dissect_ept_lookup_handle_free_rqst,
+ epm4_dissect_ept_lookup_handle_free_resp },
+ { 5, "InqObject", NULL, NULL },
+ { 6, "MgmtDelete", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_epm4 (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_epm4_opnum,
+ { "Operation", "epm4.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ { &hf_epm4_inquiry_type,
+ { "Inquiry type", "epm4.inq_type", FT_UINT32, BASE_DEC, VALS(ep_service), 0x0, "", HFILL }},
+ { &hf_epm4_object,
+ { "Object", "epm4.object", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_epm4_if_id,
+ { "Interface", "epm4.if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_epm4_ver_maj,
+ { "Version Major", "epm4.ver_maj", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm4_ver_min,
+ { "Version Minor", "epm4.ver_min", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm4_ver_opt,
+ { "Version Option", "epm4.ver_opt", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm4_hnd,
+ { "Handle", "epm4.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "Context handle", HFILL }},
+ { &hf_epm4_max_ents,
+ { "Max entries", "epm4.max_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm4_num_ents,
+ { "Num entries", "epm4.num_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm4_uuid,
+ { "UUID", "epm4.uuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL }},
+ { &hf_epm4_annotation,
+ { "Annotation", "epm4.annotation", FT_STRING, BASE_NONE, NULL, 0x0, "Annotation", HFILL }},
+ { &hf_epm4_proto_named_pipes,
+ { "Named Pipe", "epm4.proto.named_pipe", FT_STRING, BASE_NONE, NULL, 0x0, "Name of the named pipe for this service", HFILL }},
+ { &hf_epm4_proto_netbios_name,
+ { "NetBIOS Name", "epm4.proto.netbios_name", FT_STRING, BASE_NONE, NULL, 0x0, "NetBIOS name where this service can be found", HFILL }},
+ { &hf_epm4_tower_length,
+ { "Length", "epm4.tower.len", FT_UINT32, BASE_DEC, NULL, 0x0, "Length of tower data", HFILL }},
+ { &hf_epm4_tower_data,
+ { "Tower", "epm4.tower", FT_BYTES, BASE_HEX, NULL, 0x0, "Tower data", HFILL }},
+ { &hf_epm4_max_towers,
+ { "Max Towers", "epm4.max_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum number of towers to return", HFILL }},
+ { &hf_epm4_num_towers,
+ { "Num Towers", "epm4.num_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Number number of towers to return", HFILL }},
+ { &hf_epm4_ann_offset,
+ { "Annotation offset", "epm4.ann_offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm4_ann_len,
+ { "Annotation length", "epm4.ann_len", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_epm4_rc,
+ { "Return code", "epm4.rc", FT_UINT32, BASE_HEX, NULL, 0x0, "EPM return value", HFILL }},
+ { &hf_epm4_replace,
+ { "Replace", "epm4.replace", FT_UINT8, BASE_DEC, NULL, 0x0, "Replace existing objects?", HFILL }},
+ { &hf_epm4_tower_num_floors,
+ { "Number of floors", "epm4.tower.num_floors", FT_UINT16, BASE_DEC, NULL, 0x0, "Number of floors in tower", HFILL }},
+ { &hf_epm4_proto_udp_port,
+ { "UDP Port", "epm4.proto.udp_port", FT_UINT16, BASE_DEC, NULL, 0x0, "UDP Port where this service can be found", HFILL }},
+ { &hf_epm4_proto_tcp_port,
+ { "TCP Port", "epm4.proto.tcp_port", FT_UINT16, BASE_DEC, NULL, 0x0, "TCP Port where this service can be found", HFILL }},
+ { &hf_epm4_tower_rhs_len,
+ { "RHS Length", "epm4.tower.rhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of RHS data", HFILL }},
+ { &hf_epm4_tower_lhs_len,
+ { "LHS Length", "epm4.tower.lhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of LHS data", HFILL }},
+ { &hf_epm4_proto_ip,
+ { "IP", "epm4.proto.ip", FT_IPv4, BASE_NONE, NULL, 0x0, "IP address where service is located", HFILL }},
+ { &hf_epm4_tower_proto_id,
+ { "Protocol", "epm4.tower.proto_id", FT_UINT8, BASE_HEX, VALS(proto_id_vals), 0x0, "Protocol identifier", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_epm4,
+ &ett_epm4_tower_floor,
+ &ett_epm4_entry
+ };
+ proto_epm4 = proto_register_protocol ("DCE/RPC Endpoint Mapper4", "EPM4", "epm4");
+ proto_register_field_array (proto_epm4, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_epm4 (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_epm4, ett_epm4, &uuid_epm4, ver_epm4, epm4_dissectors, hf_epm4_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-eventlog.c b/epan/dissectors/packet-dcerpc-eventlog.c
new file mode 100644
index 0000000000..4541330671
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-eventlog.c
@@ -0,0 +1,859 @@
+/* packet-dcerpc-eventlog.c
+ * Routines for SMB \pipe\eventlog packet disassembly
+ * Copyright 2004 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-eventlog.h"
+#include "smb.h"
+
+
+static int proto_dcerpc_eventlog = -1;
+
+static int hf_eventlog_opnum = -1;
+static int hf_eventlog_name = -1;
+static int hf_eventlog_numofrecords = -1;
+static int hf_eventlog_oldest_record = -1;
+static int hf_eventlog_rc = -1;
+static int hf_eventlog_hnd = -1;
+static int hf_eventlog_backup_file = -1;
+static int hf_eventlog_infolevel = -1;
+static int hf_eventlog_bufsize = -1;
+static int hf_eventlog_unknown = -1;
+static int hf_eventlog_unknown_string = -1;
+static int hf_eventlog_flags = -1;
+static int hf_eventlog_offset = -1;
+static int hf_eventlog_size = -1;
+
+static gint ett_dcerpc_eventlog = -1;
+
+
+/*
+ IDL [ uuid(82273fdc-e32a-18c3-3f78-827929dc23ea),
+ IDL version(0.0),
+ IDL implicit_handle(handle_t rpc_binding)
+ IDL ] interface eventlog
+*/
+
+
+static e_uuid_t uuid_dcerpc_eventlog = {
+ 0x82273fdc, 0xe32a, 0x18c3,
+ { 0x3f, 0x78, 0x82, 0x79, 0x29, 0xdc, 0x23, 0xea }
+};
+
+static guint16 ver_dcerpc_eventlog = 0;
+
+
+
+/*
+ IDL
+ IDL long ElfrClearELFW(
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [in] [string] [unique] wchar_t *BackupFileName
+ IDL );
+ */
+
+static int
+eventlog_dissect_clearw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_UNIQUE,
+ "Backup filename", hf_eventlog_backup_file);
+
+ return offset;
+}
+
+static int
+eventlog_dissect_clearw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long ElfrBackupELFW(
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [in] [string] wchar_t *BackupFileName
+ IDL );
+ */
+
+static int
+eventlog_dissect_backupw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
+ "Backup filename", hf_eventlog_backup_file);
+
+ return offset;
+}
+
+static int
+eventlog_dissect_backupw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL long ElfrCloseEL(
+ IDL [in,out] [context_handle] void *hEventLog,
+ IDL );
+ */
+
+static int
+eventlog_dissect_close_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, TRUE);
+
+ return offset;
+}
+
+static int
+eventlog_dissect_close_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL
+ IDL long ElfrDeregisterEventSource(
+ IDL [in,out] [context_handle] void *hEventLog
+ IDL );
+ */
+
+static int
+eventlog_dissect_deregister_evt_src_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+ return offset;
+}
+
+static int
+eventlog_dissect_deregister_evt_src_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL
+ IDL long ElfrNumberOfRecords(
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [out] long NumberOfRecords
+ IDL );
+ */
+
+static int
+eventlog_dissect_getnumofrecords_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+ return offset;
+}
+
+static int
+eventlog_dissect_getnumofrecords_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_numofrecords, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+/*
+ IDL
+ IDL long ElfrOldestRecord(
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [out] long OldestRecord
+ IDL );
+ */
+
+static int
+eventlog_dissect_oldestrecord_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+
+static int
+eventlog_dissect_oldestrecord_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_oldest_record, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL long element_14;
+ IDL long element_15;
+ IDL } TYPE_2;
+ */
+
+static int
+eventlog_dissect_TYPE_2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ return offset;
+}
+
+/*
+ IDL long ElfrChangeNotify (
+ IDL [in] [context_handle] void *element_16,
+ IDL [in] TYPE_2 element_17,
+ IDL [in] long element_18
+ IDL );
+ */
+
+
+static int
+eventlog_dissect_changenotify_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = eventlog_dissect_TYPE_2(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ return offset;
+}
+
+
+static int
+eventlog_dissect_changenotify_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL short unknown0;
+ IDL short unknown1;
+ IDL } TYPE_6;
+ */
+
+static int
+eventlog_dissect_TYPE_6(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL NTSTATUS ElfrOpenELW(
+ IDL [in] [unique] TYPE_6 *unknown0,
+ IDL [in] UNICODE_STRING eventlog_name,
+ IDL [in] UNICODE_STRING unknown1,
+ IDL [in] long unknown2,
+ IDL [in] long unknown3,
+ IDL [out] [context_handle] void *hEventLog
+ IDL );
+ */
+
+static int
+eventlog_dissect_openw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ eventlog_dissect_TYPE_6, NDR_POINTER_UNIQUE,
+ "Unknown struct pointer:", hf_eventlog_unknown);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree,
+ drep, hf_eventlog_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree,
+ drep, hf_eventlog_unknown_string, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ return offset;
+}
+
+static int
+eventlog_dissect_openw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+/*
+ IDL
+ IDL long ElfrRegisterEventSourceW(
+ IDL [in] [unique] TYPE_6 *unknown0,
+ IDL [in] UNICODE_STRING element_26,
+ IDL [in] UNICODE_STRING element_27,
+ IDL [in] long unknown3,
+ IDL [in] long unknown3,
+ IDL [out] [context_handle] void *hEventLog,
+ IDL );
+ */
+
+static int
+eventlog_dissect_register_evt_srcw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ eventlog_dissect_TYPE_6, NDR_POINTER_UNIQUE,
+ "Unknown struct pointer:", hf_eventlog_unknown);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree,
+ drep, hf_eventlog_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree,
+ drep, hf_eventlog_unknown_string, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ return offset;
+}
+
+static int
+eventlog_dissect_register_evt_srcw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+/*
+ IDL NTSTATUS ElfrOpenBELW(
+ IDL [in] [unique] TYPE_6 *unknown0,
+ IDL [in] UNICODE_STRING eventlog_name,
+ IDL [in] long unknown2,
+ IDL [in] long unknown3,
+ IDL [out] [context_handle] void *hEventLog
+ IDL );
+ */
+
+static int
+eventlog_dissect_open_backupw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ eventlog_dissect_TYPE_6, NDR_POINTER_UNIQUE,
+ "Unknown struct pointer:", hf_eventlog_unknown);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree,
+ drep, hf_eventlog_name, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_unknown, NULL);
+
+ return offset;
+}
+
+static int
+eventlog_dissect_open_backupw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_rc, NULL);
+
+ return offset;
+}
+
+/*
+ IDL long ElfrReadELW(
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [in] long flags,
+ IDL [in] long offset,
+ IDL [in,out] long number_of_bytes,
+ IDL [out] [size_is(number_of_bytes)] byte *data,
+ IDL [out] long sent_size,
+ IDL [out] long real_size
+ IDL );
+ */
+
+static int
+eventlog_dissect_readw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_flags, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_offset, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_size, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL char element_47[6];
+ IDL } TYPE_4;
+ */
+
+/*
+ IDL typedef struct {
+ IDL char element_43;
+ IDL char element_44;
+ IDL TYPE_4 element_45;
+ IDL [size_is(element_44)] byte element_46[*];
+ IDL } TYPE_3;
+ */
+
+/*
+ IDL long ElfrReportEventW(
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [in] long element_49,
+ IDL [in] short element_50,
+ IDL [in] short element_51,
+ IDL [in] long element_52,
+ IDL [in] short element_53,
+ IDL [in] long element_54,
+ IDL [in] UNICODE_STRING element_55,
+ IDL [in] [unique] TYPE_3 *element_56,
+ IDL [in] [size_is(element_53)] [unique] byte *element_57,
+ IDL [in] [size_is(element_54)] [unique] byte *element_58,
+ IDL [in] short element_59,
+ IDL [in,out] [unique] long *element_60,
+ IDL [in,out] [unique] long *element_61
+ IDL );
+ */
+
+/*
+ * IDL typedef struct {
+ * IDL short length;
+ * IDL short size;
+ * IDL [size_is(size] [unique] byte *string;
+ * IDL } ASCII_STRING;
+ */
+
+/*
+ IDL NTSTATUS ElfrClearELFA
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [in] [unique] ASCII_STRING *BackupFileName
+ IDL );
+ */
+
+/*
+ IDL NTSTATUS ElfrBackupELFA(
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [in] ASCII_STRING BackupFileName
+ IDL );
+ */
+
+/*
+ IDL NTSTATUS ElfrOpenELA(
+ IDL [in] [unique] TYPE_6 *unknown0,
+ IDL [in] ASCII_STRING eventlog_name,
+ IDL [in] ASCII_STRING unknown1,
+ IDL [in] long unknown2,
+ IDL [in] long unknown3,
+ IDL [out] [context_handle] void *hEventLog,
+ IDL );
+ */
+
+/*
+ IDL long ElfrRegisterEventSourceA(
+ IDL [in] [unique] char *element_75,
+ IDL [in] ASCII_STRING element_76,
+ IDL [in] ASCII_STRING element_77,
+ IDL [in] long element_78,
+ IDL [in] long element_79,
+ IDL [out] [context_handle] void *hEventLog,
+ );
+ */
+
+
+/*
+ IDL NTSTATUS ElfrOpenBELA(
+ IDL [in] [unique] char *element_81,
+ IDL [in] ASCII_STRING element_82,
+ IDL [in] long element_83,
+ IDL [in] long element_84,
+ IDL [out] [context_handle] void *hEventLog
+ );
+ */
+
+
+/*
+ IDL long ElfrReadELA(
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [in] long element_87,
+ IDL [in] long element_88,
+ IDL [in] long element_89,
+ IDL [out] [size_is(element_89)] byte element_90[*],
+ IDL [out] long element_91,
+ IDL [out] long element_92
+ IDL );
+ */
+
+/*
+ IDL long ElfrReportEventA
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [in] long element_94,
+ IDL [in] short element_95,
+ IDL [in] short element_96,
+ IDL [in] long element_97,
+ IDL [in] short element_98,
+ IDL [in] long element_99,
+ IDL [in] ASCII_STRING element_100,
+ IDL [in] [unique] TYPE_3 *element_101,
+ IDL [in] [size_is(element_98)] [unique] byte *element_102,
+ IDL [in] [size_is(element_99)] [unique] byte *element_103,
+ IDL [in] short element_104,
+ IDL [in,out] [unique] long *element_105,
+ IDL [in,out] [unique] long *element_106
+ IDL );
+ */
+
+
+/*
+ IDL long ElfrRegisterClusterSvc(
+ IDL [in] [unique] wchar_t *element_107,
+ IDL [out] long element_108,
+ IDL [out] [size_is(*element_108)] [ref] byte **element_109
+ IDL );
+ */
+
+/*
+ IDL long ElfrWriteClusterEvents(
+ IDL [in] [unique] wchar_t *element_110
+ IDL );
+ */
+
+/*
+ IDL long ElfrUnregisterClusterSvc(
+ IDL [in] [unique] wchar_t *element_111,
+ IDL [in] long element_112,
+ IDL [in] [size_is(element_112)] byte element_113[*]
+ IDL );
+ */
+
+
+
+
+static value_string infoLevels[] = {
+ { 0, "EVENTLOG_FULL_INFORMATION" },
+ { 0, NULL}
+};
+
+
+/*
+ IDL long ElfrGetLogInformation(
+ IDL [in] [context_handle] void *hEventLog,
+ IDL [in] long dwInfoLevel,
+ IDL [out] [size_is(cbBufSize)] char lpBuffer[*],
+ IDL [in] long cbBufSize,
+ IDL [out] long cbBytesNeeded,
+ IDL );
+ */
+
+static int
+eventlog_dissect_getloginfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_eventlog_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_infolevel, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_eventlog_bufsize, NULL);
+
+ return offset;
+}
+
+
+static dcerpc_sub_dissector dcerpc_eventlog_dissectors[] = {
+ { EVENTLOG_CLEAR, "ElfrClearELFW",
+ eventlog_dissect_clearw_rqst,
+ eventlog_dissect_clearw_reply},
+ { EVENTLOG_BACKUP, "ElfrBackupELFW",
+ eventlog_dissect_backupw_rqst,
+ eventlog_dissect_backupw_reply },
+ { EVENTLOG_CLOSE, "ElfrCloseEL",
+ eventlog_dissect_close_rqst,
+ eventlog_dissect_close_reply },
+ { EVENTLOG_DEREGISTER_EVT_SRC, "ElfrDeregisterEventSource",
+ eventlog_dissect_deregister_evt_src_rqst,
+ eventlog_dissect_deregister_evt_src_reply },
+ { EVENTLOG_NUMOFRECORDS, "ElfrNumberOfRecords",
+ eventlog_dissect_getnumofrecords_rqst,
+ eventlog_dissect_getnumofrecords_reply },
+ { EVENTLOG_GET_OLDEST_RECORD, "ElfrOldestRecord",
+ eventlog_dissect_oldestrecord_rqst,
+ eventlog_dissect_oldestrecord_reply },
+ { EVENTLOG_NOTIFY_CHANGE, "ElfrChangeNotify",
+ eventlog_dissect_changenotify_rqst,
+ eventlog_dissect_changenotify_reply },
+ { EVENTLOG_OPEN, "ElfrOpenELW",
+ eventlog_dissect_openw_rqst,
+ eventlog_dissect_openw_reply },
+ { EVENTLOG_REGISTER_EVT_SRC, "ElfrRegisterEventSourceW",
+ eventlog_dissect_register_evt_srcw_rqst,
+ eventlog_dissect_register_evt_srcw_reply },
+ { EVENTLOG_OPEN_BACKUP, "ElfrOpenBELW",
+ eventlog_dissect_open_backupw_rqst,
+ eventlog_dissect_open_backupw_reply },
+ { EVENTLOG_READ, "ElfrReadELW",
+ eventlog_dissect_readw_rqst,
+ NULL },
+ { EVENTLOG_REPORT, "ElfrReportEventW",
+ NULL, NULL },
+ { EVENTLOG_CLEAR_ASCII, "ElfrClearELFA",
+ NULL, NULL },
+ { EVENTLOG_BACKUP_ASCII, "ElfrBackupELFA",
+ NULL, NULL },
+ { EVENTLOG_OPEN_ASCII, "ElfrOpenELA",
+ NULL, NULL },
+ { EVENTLOG_REGISTER_EVT_SRC_ASCII, "ElfrRegisterEventSourceA",
+ NULL, NULL },
+ { EVENTLOG_OPEN_BACKUP_ASCII, "ElfrOpenBELA",
+ NULL, NULL },
+ { EVENTLOG_READ_ASCII, "ElfrReadELA",
+ NULL, NULL },
+ { EVENTLOG_REPORT_ASCII, "ElfrReportEventA",
+ NULL, NULL },
+ { EVENTLOG_REGISTER_CLUSTER_SVC, "ElfrRegisterClusterSvc",
+ NULL, NULL },
+ { EVENTLOG_DEREGISTER_CLUSTER_SVC, "ElfrDeregisterClusterSvc",
+ NULL, NULL },
+ { EVENTLOG_WRITE_CLUSTER_EVENTS, "ElfrWriteClusterEvents",
+ NULL, NULL },
+ { EVENTLOG_GET_INFO, "ElfrGetLogInformation",
+ eventlog_dissect_getloginfo_rqst,
+ NULL },
+ { EVENTLOG_FLUSH, "ElfrFlushEL",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+
+void
+proto_register_dcerpc_eventlog(void)
+{
+
+ static hf_register_info hf[] = {
+
+ { &hf_eventlog_opnum,
+ { "Operation", "eventlog.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ { &hf_eventlog_name,
+ { "Eventlog name", "eventlog.name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Eventlog name", HFILL}},
+
+ {&hf_eventlog_numofrecords,
+ { "Number of records", "eventlog.records", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of records in eventlog", HFILL }},
+
+ {&hf_eventlog_oldest_record,
+ { "Oldest record", "eventlog.oldest_record", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Oldest record available in eventlog", HFILL }},
+
+ {&hf_eventlog_rc,
+ { "Return code", "eventlog.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "Eventlog return status code", HFILL }},
+
+ { &hf_eventlog_hnd,
+ { "Context Handle", "eventlog.hnd", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "Eventlog context handle", HFILL }},
+
+ { &hf_eventlog_backup_file,
+ { "Backup filename", "eventlog.backup_file", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Eventlog backup file", HFILL}},
+
+ {&hf_eventlog_infolevel,
+ { "Information level", "eventlog.info_level", FT_UINT32, BASE_DEC,
+ &infoLevels, 0x0, "Eventlog information level", HFILL }},
+
+ {&hf_eventlog_bufsize,
+ { "Buffer size", "eventlog.buf_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Eventlog buffer size", HFILL }},
+
+ {&hf_eventlog_unknown,
+ { "Unknown field", "eventlog.unknown", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Unknown field", HFILL }},
+
+ { &hf_eventlog_unknown_string,
+ { "Unknown string", "eventlog.unknown_str", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Unknown string", HFILL}},
+
+ {&hf_eventlog_flags,
+ { "Eventlog flags", "eventlog.flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Eventlog flags", HFILL }},
+
+ {&hf_eventlog_offset,
+ { "Eventlog offset", "eventlog.offset", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Eventlog offset", HFILL }},
+
+ {&hf_eventlog_size,
+ { "Eventlog size", "eventlog.size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Eventlog size", HFILL }},
+
+ };
+
+
+ static gint *ett[] = {
+ &ett_dcerpc_eventlog,
+ };
+
+
+ proto_dcerpc_eventlog = proto_register_protocol(
+ "Microsoft Eventlog Service", "EVENTLOG", "eventlog");
+
+ proto_register_field_array(proto_dcerpc_eventlog, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+void
+proto_reg_handoff_dcerpc_eventlog(void)
+{
+
+ /* register protocol as dcerpc */
+
+ dcerpc_init_uuid(
+ proto_dcerpc_eventlog, ett_dcerpc_eventlog, &uuid_dcerpc_eventlog,
+ ver_dcerpc_eventlog, dcerpc_eventlog_dissectors, hf_eventlog_opnum);
+
+}
diff --git a/epan/dissectors/packet-dcerpc-eventlog.h b/epan/dissectors/packet-dcerpc-eventlog.h
new file mode 100644
index 0000000000..1c8e37eacc
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-eventlog.h
@@ -0,0 +1,57 @@
+/* packet-dcerpc-eventlog.h
+ * Routines for SMB \pipe\eventlog packet disassembly
+ * Copyright 2004 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_EVENTLOG_H
+#define __PACKET_DCERPC_EVENTLOG_H
+
+/* MSRPC functions available in the eventlog interface */
+
+#define EVENTLOG_CLEAR 0x00
+#define EVENTLOG_BACKUP 0x01
+#define EVENTLOG_CLOSE 0x02
+#define EVENTLOG_DEREGISTER_EVT_SRC 0x03
+#define EVENTLOG_NUMOFRECORDS 0x04
+#define EVENTLOG_GET_OLDEST_RECORD 0x05
+#define EVENTLOG_NOTIFY_CHANGE 0x06
+#define EVENTLOG_OPEN 0x07
+#define EVENTLOG_REGISTER_EVT_SRC 0x08
+#define EVENTLOG_OPEN_BACKUP 0x09
+#define EVENTLOG_READ 0x0a
+#define EVENTLOG_REPORT 0x0b
+#define EVENTLOG_CLEAR_ASCII 0x0c
+#define EVENTLOG_BACKUP_ASCII 0x0d
+#define EVENTLOG_OPEN_ASCII 0x0e
+#define EVENTLOG_REGISTER_EVT_SRC_ASCII 0x0f
+#define EVENTLOG_OPEN_BACKUP_ASCII 0x10
+#define EVENTLOG_READ_ASCII 0x11
+#define EVENTLOG_REPORT_ASCII 0x12
+#define EVENTLOG_REGISTER_CLUSTER_SVC 0x13
+#define EVENTLOG_DEREGISTER_CLUSTER_SVC 0x14
+#define EVENTLOG_WRITE_CLUSTER_EVENTS 0x15
+#define EVENTLOG_GET_INFO 0x16
+#define EVENTLOG_FLUSH 0x17
+
+#endif /* packet-dcerpc-eventlog.h */
+
diff --git a/epan/dissectors/packet-dcerpc-fldb.c b/epan/dissectors/packet-dcerpc-fldb.c
new file mode 100644
index 0000000000..ee39792543
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-fldb.c
@@ -0,0 +1,2142 @@
+/* packet-dcerpc-fldb.c
+ *
+ * Routines for dcerpc FLDB Calls
+ * Copyright 2004, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz file/flserver/fldb_proc.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dce122.h"
+
+
+static int proto_fldb = -1;
+static int hf_fldb_opnum = -1;
+
+static gint ett_fldb = -1;
+static gint ett_fldb_vldbentry = -1;
+static gint ett_fldb_afsnetaddr = -1;
+static gint ett_fldb_siteflags = -1;
+static gint ett_fldb_afsflags = -1;
+static gint ett_fldb_vlconf_cell = -1;
+static gint ett_fldb_afsNameString_t = -1;
+
+
+
+static e_uuid_t uuid_fldb =
+ { 0x4d37f2dd, 0xed43, 0x0000, {0x02, 0xc0, 0x37, 0xcf, 0x2e, 0x00, 0x00,
+ 0x01}
+};
+static guint16 ver_fldb = 4;
+
+static int hf_fldb_getentrybyname_rqst_var1 = -1;
+static int hf_fldb_getentrybyname_rqst_key_size = -1;
+static int hf_fldb_releaselock_rqst_fsid_high = -1;
+static int hf_fldb_releaselock_rqst_fsid_low = -1;
+static int hf_fldb_releaselock_rqst_voltype = -1;
+static int hf_fldb_releaselock_rqst_voloper = -1;
+static int hf_fldb_setlock_rqst_fsid_high = -1;
+static int hf_fldb_setlock_rqst_fsid_low = -1;
+static int hf_fldb_setlock_rqst_voltype = -1;
+static int hf_fldb_setlock_rqst_voloper = -1;
+static int hf_fldb_setlock_resp_st = -1;
+static int hf_fldb_setlock_resp_st2 = -1;
+static int hf_fldb_listentry_rqst_previous_index = -1;
+static int hf_fldb_listentry_rqst_var1 = -1;
+static int hf_fldb_listentry_resp_count = -1;
+static int hf_fldb_listentry_resp_next_index = -1;
+static int hf_fldb_listentry_resp_key_t = -1;
+static int hf_fldb_listentry_resp_key_size = -1;
+static int hf_fldb_listentry_resp_key_t2 = -1;
+static int hf_fldb_listentry_resp_key_size2 = -1;
+static int hf_fldb_listentry_resp_voltype = -1;
+static int hf_fldb_createentry_rqst_key_t = -1;
+static int hf_fldb_createentry_rqst_key_size = -1;
+static int hf_fldb_deleteentry_rqst_fsid_high = -1;
+static int hf_fldb_deleteentry_rqst_fsid_low = -1;
+static int hf_fldb_deleteentry_rqst_voltype = -1;
+static int hf_fldb_deleteentry_rqst_voloper = -1;
+static int hf_fldb_getentrybyid_rqst_fsid_high = -1;
+static int hf_fldb_getentrybyid_rqst_fsid_low = -1;
+static int hf_fldb_getentrybyid_rqst_voltype = -1;
+static int hf_fldb_getentrybyid_rqst_voloper = -1;
+static int hf_fldb_replaceentry_rqst_fsid_high = -1;
+static int hf_fldb_replaceentry_rqst_fsid_low = -1;
+static int hf_fldb_replaceentry_rqst_voltype = -1;
+static int hf_fldb_replaceentry_rqst_key_size = -1;
+static int hf_fldb_replaceentry_rqst_key_t = -1;
+static int hf_fldb_replaceentry_resp_st = -1;
+static int hf_fldb_replaceentry_resp_st2 = -1;
+static int hf_fldb_getentrybyname_resp_volumetype = -1;
+static int hf_fldb_getentrybyname_resp_numservers = -1;
+static int hf_fldb_getentrybyname_resp_sitecookies = -1;
+static int hf_fldb_getentrybyname_resp_sitepartition = -1;
+static int hf_fldb_getentrybyname_resp_siteflags = -1;
+static int hf_fldb_getentrybyname_resp_sitemaxreplat = -1;
+static int hf_fldb_getentrybyname_resp_volid_high = -1;
+static int hf_fldb_getentrybyname_resp_volid_low = -1;
+static int hf_fldb_getentrybyname_resp_voltype = -1;
+static int hf_fldb_getentrybyname_resp_cloneid_high = -1;
+static int hf_fldb_getentrybyname_resp_cloneid_low = -1;
+static int hf_fldb_getentrybyname_resp_flags = -1;
+static int hf_fldb_getentrybyname_resp_maxtotallat = -1;
+static int hf_fldb_getentrybyname_resp_hardmaxtotlat = -1;
+static int hf_fldb_getentrybyname_resp_minpouncedally = -1;
+static int hf_fldb_getentrybyname_resp_defaultmaxreplat = -1;
+static int hf_fldb_getentrybyname_resp_reclaimdally = -1;
+static int hf_fldb_getentrybyname_resp_whenlocked = -1;
+static int hf_fldb_getentrybyname_resp_spare1 = -1;
+static int hf_fldb_getentrybyname_resp_spare2 = -1;
+static int hf_fldb_getentrybyname_resp_spare3 = -1;
+static int hf_fldb_getentrybyname_resp_spare4 = -1;
+static int hf_fldb_getentrybyname_resp_key_t = -1;
+static int hf_fldb_getentrybyname_resp_key_size = -1;
+static int hf_fldb_getentrybyname_resp_test = -1;
+static int hf_dcerpc_error_status = -1;
+static int hf_fldb_vldbentry_volumename = -1;
+static int hf_fldb_vldbentry_volumetype = -1;
+static int hf_fldb_vldbentry_nservers = -1;
+static int hf_fldb_vldbentry_sitepartition = -1;
+static int hf_fldb_afsnetaddr_type = -1;
+static int hf_fldb_afsnetaddr_data = -1;
+static int hf_fldb_siteflags = -1;
+static int hf_fldb_vldbentry_sitemaxreplicalatency = -1;
+static int hf_fldb_vldbentry_siteprincipal = -1;
+static int hf_fldb_vldbentry_siteowner = -1;
+static int hf_fldb_vldbentry_siteobjid = -1;
+static int hf_fldb_vldbentry_volids_high = -1;
+static int hf_fldb_vldbentry_volids_low = -1;
+static int hf_fldb_vldbentry_voltypes = -1;
+static int hf_fldb_vldbentry_cloneid_high = -1;
+static int hf_fldb_vldbentry_cloneid_low = -1;
+static int hf_fldb_afsflags_flags = -1;
+static int hf_fldb_vldbentry_maxtotallatency = -1;
+static int hf_fldb_vldbentry_hardmaxtotallatency = -1;
+static int hf_fldb_vldbentry_minimumpouncedally = -1;
+static int hf_fldb_vldbentry_defaultmaxreplicalatency = -1;
+static int hf_fldb_vldbentry_reclaimdally = -1;
+static int hf_fldb_vldbentry_whenlocked = -1;
+static int hf_fldb_vldbentry_spare1 = -1;
+static int hf_fldb_vldbentry_spare2 = -1;
+static int hf_fldb_vldbentry_spare3 = -1;
+static int hf_fldb_vldbentry_spare4 = -1;
+static int hf_fldb_vldbentry_lockername = -1;
+static int hf_fldb_vldbentry_charspares = -1;
+static int hf_fldb_vlconf_cell_name = -1;
+static int hf_fldb_vlconf_cell_cellid_high = -1;
+static int hf_fldb_vlconf_cell_cellid_low = -1;
+static int hf_fldb_vlconf_cell_numservers = -1;
+static int hf_fldb_vlconf_cell_hostname = -1;
+static int hf_fldb_vlconf_cell_spare1 = -1;
+static int hf_fldb_vlconf_cell_spare2 = -1;
+static int hf_fldb_vlconf_cell_spare3 = -1;
+static int hf_fldb_vlconf_cell_spare4 = -1;
+static int hf_fldb_vlconf_cell_spare5 = -1;
+static int hf_fldb_flagsp = -1;
+static int hf_fldb_nextstartp = -1;
+static int hf_fldb_afsNameString_t_principalName_string = -1;
+static int hf_fldb_afsNameString_t_principalName_size = -1;
+static int hf_fldb_afsNameString_t_principalName_size2 = -1;
+static int hf_fldb_namestring = -1;
+static int hf_error_st = -1;
+static int hf_fldb_creationquota = -1;
+static int hf_fldb_creationuses = -1;
+static int hf_fldb_deletedflag = -1;
+static int hf_fldb_namestring_size = -1;
+static int hf_fldb_numwanted = -1;
+static int hf_fldb_spare2 = -1;
+static int hf_fldb_spare3 = -1;
+static int hf_fldb_spare4 = -1;
+static int hf_fldb_spare5 = -1;
+static int hf_fldb_uuid_objid = -1;
+static int hf_fldb_uuid_owner = -1;
+static int hf_fldb_volid_high = -1;
+static int hf_fldb_volid_low = -1;
+static int hf_fldb_voltype = -1;
+static guint32 st;
+static const guint8 *st_str;
+
+#define AFS_FLAG_RETURNTOKEN 1
+#define AFS_FLAG_TOKENJUMPQUEUE 2
+#define AFS_FLAG_SKIPTOKEN 4
+#define AFS_FLAG_NOOPTIMISM 0x8
+#define AFS_FLAG_TOKENID 0x10
+#define AFS_FLAG_RETURNBLOCKER 0x20
+#define AFS_FLAG_ASYNCGRANT 0x40
+#define AFS_FLAG_NOREVOKE 0x80
+#define AFS_FLAG_MOVE_REESTABLISH 0x100
+#define AFS_FLAG_SERVER_REESTABLISH 0x200
+#define AFS_FLAG_NO_NEW_EPOCH 0x400
+#define AFS_FLAG_MOVE_SOURCE_OK 0x800
+#define AFS_FLAG_SYNC 0x1000
+#define AFS_FLAG_ZERO 0x2000
+#define AFS_FLAG_SKIPSTATUS 0x4000
+#define AFS_FLAG_FORCEREVOCATIONS 0x8000
+#define AFS_FLAG_FORCEVOLQUIESCE 0x10000
+#define AFS_FLAG_FORCEREVOCATIONDOWN 0x20000
+
+#define AFS_FLAG_SEC_SERVICE 0x1
+#define AFS_FLAG_CONTEXT_NEW_IF 0x2
+#define AFS_FLAG_CONTEXT_DO_RESET 0x4
+#define AFS_FLAG_CONTEXT_NEW_ACL_IF 0x8
+#define AFS_FLAG_CONTEXT_NEW_TKN_TYPES 0x10
+
+#define VLSF_NEWREPSITE 0x01
+#define VLSF_SPARE1 0x02
+#define VLSF_SPARE2 0x04 /* used for VLSF_RWVOL in flprocs.c */
+#define VLSF_SPARE3 0x08 /* used for VLSF_BACKVOL in flprocs.c */
+#define VLSF_SAMEASPREV 0x10
+#define VLSF_DEFINED 0x20
+#define VLSF_PARTIALADDRS 0x40
+#define VLSF_ZEROIXHERE 0x80000000
+
+#define MACRO_ST_CLEAR(name) \
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_error_st, &st); \
+ st_str = val_to_str (st, dce_error_vals, "%u"); \
+ if (st){ \
+if (check_col (pinfo->cinfo, COL_INFO)) \
+ col_add_fstr (pinfo->cinfo, COL_INFO, "%s st:%s ", name, st_str); \
+ }else{ \
+if (check_col (pinfo->cinfo, COL_INFO)) \
+ col_append_fstr (pinfo->cinfo, COL_INFO, " st:%s ", st_str); \
+}
+
+static int
+dissect_afsnetaddr (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint16 type;
+ guint8 data;
+ int i;
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsNetAddr:");
+ tree = proto_item_add_subtree (item, ett_fldb_afsnetaddr);
+ }
+
+/* unsigned16 type;
+ unsigned8 data[14];
+*/
+
+ offset =
+ dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_afsnetaddr_type, &type);
+
+ if (type)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Type:%u ", type);
+
+
+ for (i = 0; i < 14; i++)
+ {
+
+ offset =
+ dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_afsnetaddr_data, &data);
+
+
+ switch (i)
+ {
+ case 1:
+ if (data)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Port:%u",
+ data);
+ }
+ break;
+ case 2:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " IP:%u.", data);
+ break;
+ case 3:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "%u.", data);
+ break;
+ case 4:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "%u.", data);
+ break;
+ case 5:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "%u", data);
+ break;
+ }
+
+ }
+
+ }
+ else
+ {
+
+ offset += 14; /* space left after reading in type for the array. */
+ }
+
+
+
+ proto_item_set_len (item, offset - old_offset);
+
+ return offset;
+}
+
+
+static int
+dissect_vlconf_cell (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+#define MAXVLCELLCHARS 128
+#define MAXVLHOSTSPERCELL 64
+ const guint8 *name, *hostname;
+ int i;
+ guint32 cellid_high, cellid_low, numservers, spare1, spare2, spare3, spare4,
+ spare5;
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "vlconf_cell:");
+ tree = proto_item_add_subtree (item, ett_fldb_vlconf_cell);
+ }
+
+ /* byte name[MAXVLCELLCHARS]; Cell name */
+ proto_tree_add_string (tree, hf_fldb_vlconf_cell_name, tvb, offset, 114,
+ tvb_get_ptr (tvb, offset, MAXVLCELLCHARS));
+ name = tvb_get_ptr (tvb, offset, MAXVLCELLCHARS);
+ offset += MAXVLCELLCHARS; /* some reason this 114 seems to be incorrect... cutting 4 short to compensate.... */
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Name: %s", name);
+
+
+ /* afsHyper CellID; identifier for that cell */
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vlconf_cell_cellid_high, &cellid_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vlconf_cell_cellid_low, &cellid_low);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " CellID:%u-%u", cellid_high,
+ cellid_low);
+
+
+ /* unsigned32 numServers; *Num active servers for the cell */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vlconf_cell_numservers, &numservers);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " numServers:%u", numservers);
+
+ /* afsNetAddr hostAddr[MAXVLHOSTSPERCELL]; *addresses for cell's servers */
+ for (i = 0; i < MAXVLHOSTSPERCELL; i++)
+ {
+ offset = dissect_afsnetaddr (tvb, offset, pinfo, tree, drep);
+ }
+
+
+ /* hostnam hostName[MAXVLHOSTSPERCELL]; *Names for cell's servers* */
+
+ for (i = 0; i < MAXVLHOSTSPERCELL; i++)
+ {
+ proto_tree_add_string (tree, hf_fldb_vlconf_cell_hostname, tvb, offset,
+ 64, tvb_get_ptr (tvb, offset, 64));
+ hostname = tvb_get_ptr (tvb, offset, 64);
+ offset += 64; /* some reason this 114 seems to be incorrect... cutting 4 short to compensate.... */
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " hostName: %s", hostname);
+ }
+
+ /* unsigned32 spare1; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vlconf_cell_spare1, &spare1);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " spare1:%u", spare1);
+
+
+ /* unsigned32 spare2; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vlconf_cell_spare2, &spare2);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " spare2:%u", spare2);
+
+ /* unsigned32 spare3; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vlconf_cell_spare3, &spare3);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " spare3:%u", spare3);
+
+
+ /* unsigned32 spare4; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vlconf_cell_spare4, &spare4);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " spare4:%u", spare4);
+
+ /* unsigned32 spare5; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vlconf_cell_spare5, &spare5);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " spare5:%u", spare5);
+
+
+ proto_item_set_len (item, offset - old_offset);
+
+ return offset;
+}
+
+static int
+dissect_afsNameString_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+/*
+typedef [string] byte NameString_t[AFS_NAMEMAX];
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+#define AFS_NAMEMAX 256
+ guint32 string_size;
+ const guint8 *namestring;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "afsNameString_t:");
+ tree = proto_item_add_subtree (item, ett_fldb_afsNameString_t);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_afsNameString_t_principalName_size,
+ &string_size);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " String_size:%u", string_size);
+ if (string_size < AFS_NAMEMAX)
+ {
+/* proto_tree_add_string(tree, id, tvb, start, length, value_ptr); */
+ proto_tree_add_string (tree,
+ hf_fldb_afsNameString_t_principalName_string,
+ tvb, offset, string_size, tvb_get_ptr (tvb,
+ offset,
+ string_size));
+ namestring = tvb_get_ptr (tvb, offset, string_size);
+ offset += string_size;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Principal:%s", namestring);
+ }
+ else
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " :FIXME!: Invalid string length of %u",
+ string_size);
+ }
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+
+static int
+dissect_afsflags (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 afsflags;
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "afsFlags:");
+ tree = proto_item_add_subtree (item, ett_fldb_afsflags);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_afsflags_flags, &afsflags);
+ if (afsflags)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, " afsFlags=");
+ if ((afsflags & AFS_FLAG_RETURNTOKEN) == AFS_FLAG_RETURNTOKEN)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":RETURNTOKEN");
+ }
+ if ((afsflags & AFS_FLAG_TOKENJUMPQUEUE) == AFS_FLAG_TOKENJUMPQUEUE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":TOKENJUMPQUEUE");
+ }
+ if ((afsflags & AFS_FLAG_SKIPTOKEN) == AFS_FLAG_SKIPTOKEN)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SKIPTOKEN");
+ }
+ if ((afsflags & AFS_FLAG_NOOPTIMISM) == AFS_FLAG_NOOPTIMISM)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":NOOPTIMISM");
+ }
+ if ((afsflags & AFS_FLAG_TOKENID) == AFS_FLAG_TOKENID)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":TOKENID");
+ }
+ if ((afsflags & AFS_FLAG_RETURNBLOCKER) == AFS_FLAG_RETURNBLOCKER)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":RETURNBLOCKER");
+ }
+ if ((afsflags & AFS_FLAG_ASYNCGRANT) == AFS_FLAG_ASYNCGRANT)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":ASYNCGRANT");
+ }
+ if ((afsflags & AFS_FLAG_NOREVOKE) == AFS_FLAG_NOREVOKE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":NOREVOKE");
+ }
+ if ((afsflags & AFS_FLAG_MOVE_REESTABLISH) == AFS_FLAG_MOVE_REESTABLISH)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":MOVE_REESTABLISH");
+ }
+ if ((afsflags & AFS_FLAG_SERVER_REESTABLISH) ==
+ AFS_FLAG_SERVER_REESTABLISH)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SERVER_REESTABLISH");
+ if ((afsflags & AFS_FLAG_NO_NEW_EPOCH) == AFS_FLAG_NO_NEW_EPOCH)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":NO_NEW_EPOCH");
+ }
+ if ((afsflags & AFS_FLAG_MOVE_SOURCE_OK) == AFS_FLAG_MOVE_SOURCE_OK)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":MOVE_SOURCE_OK");
+ }
+ if ((afsflags & AFS_FLAG_SYNC) == AFS_FLAG_SYNC)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SYNC");
+ }
+ if ((afsflags & AFS_FLAG_ZERO) == AFS_FLAG_ZERO)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":ZERO");
+ }
+ if ((afsflags & AFS_FLAG_SKIPSTATUS) == AFS_FLAG_SKIPSTATUS)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SKIPSTATUS");
+ }
+ if ((afsflags & AFS_FLAG_FORCEREVOCATIONS) ==
+ AFS_FLAG_FORCEREVOCATIONS)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":FORCEREVOCATIONS");
+ }
+ if ((afsflags & AFS_FLAG_FORCEVOLQUIESCE) ==
+ AFS_FLAG_FORCEVOLQUIESCE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":FORCEVOLQUIESCE");
+ }
+ if ((afsflags & AFS_FLAG_SEC_SERVICE) == AFS_FLAG_SEC_SERVICE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SEC_SERVICE");
+ }
+ if ((afsflags & AFS_FLAG_CONTEXT_NEW_ACL_IF) ==
+ AFS_FLAG_CONTEXT_NEW_ACL_IF)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO,
+ ":CONTEXT_NEW_ACL_IF");
+ }
+
+ }
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+
+ return offset;
+
+}
+
+
+static int
+dissect_siteflags (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 siteflags;
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "SiteFlags:");
+ tree = proto_item_add_subtree (item, ett_fldb_siteflags);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_siteflags,
+ &siteflags);
+
+ if (siteflags)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, " SiteFlags");
+ if ((siteflags & VLSF_NEWREPSITE) == VLSF_NEWREPSITE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":NEWREPSITE");
+ }
+ if ((siteflags & VLSF_SPARE1) == VLSF_SPARE1)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SPARE1");
+ }
+ if ((siteflags & VLSF_SPARE2) == VLSF_SPARE2)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SPARE2");
+ }
+ if ((siteflags & VLSF_SPARE3) == VLSF_SPARE3)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SPARE3");
+ }
+ if ((siteflags & VLSF_SAMEASPREV) == VLSF_SAMEASPREV)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":SAMEASPREV");
+ }
+ if ((siteflags & VLSF_DEFINED) == VLSF_DEFINED)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":DEFINED");
+ }
+ if ((siteflags & VLSF_PARTIALADDRS) == VLSF_PARTIALADDRS)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":PARTIALADDRS ");
+ }
+ if ((siteflags & VLSF_ZEROIXHERE) == VLSF_ZEROIXHERE)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":ZEROIXHERE");
+
+ }
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+
+ return offset;
+}
+
+
+
+static int
+dissect_vldbentry (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ const guint8 *volumename, *siteprincipal, *charspares, *lockername;
+ guint32 volumetype, nservers, sitepartition, sitemaxreplicalatency,
+ volids_high, volids_low, voltypes, cloneid_high, cloneid_low,
+ maxtotallatency, hardmaxtotallatency, minimumpouncedally,
+ defaultmaxreplicalatency, reclaimdally, whenlocked, spare1, spare2,
+ spare3, spare4;
+ e_uuid_t siteowner, siteobjid;
+ gint i;
+#define MAXNSERVERS 16
+#define MAXVOLTYPES 8
+#define MAXLOCKNAMELEN 64
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1, "vldbentry:");
+ tree = proto_item_add_subtree (item, ett_fldb_vldbentry);
+ }
+
+/* byte name[114]; Volume name */
+
+ proto_tree_add_string (tree, hf_fldb_vldbentry_volumename, tvb, offset, 114,
+ tvb_get_ptr (tvb, offset, 114));
+ volumename = tvb_get_ptr (tvb, offset, 114);
+ offset += 110; /* some reason this 114 seems to be incorrect... cutting 4 short to compensate.... */
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Name: %s", volumename);
+
+ /* unsigned32 volumeType; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_volumetype, &volumetype);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Type:%u", volumetype);
+
+ /*unsigned32 nServers; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_nservers, &nservers);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " nServers:%u", nservers);
+
+ /* afsNetAddr siteAddr[MAXNSERVERS]; 16 */
+ for (i = 0; i < MAXNSERVERS; i++)
+ {
+ /* if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Site:%u", i); */
+
+ offset = dissect_afsnetaddr (tvb, offset, pinfo, tree, drep);
+ }
+
+/* unsigned32 sitePartition[MAXNSERVERS]; */
+ for (i = 0; i < MAXNSERVERS; i++)
+ {
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_sitepartition, &sitepartition);
+ if (sitepartition)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " LFS:%u",
+ sitepartition);
+ }
+ }
+
+
+ /* unsigned32 siteFlags[MAXNSERVERS]; */
+ for (i = 0; i < MAXNSERVERS; i++)
+ {
+ offset = dissect_siteflags (tvb, offset, pinfo, tree, drep);
+ }
+
+ /* unsigned32 sitemaxReplicaLatency[MAXNSERVERS]; */
+ for (i = 0; i < MAXNSERVERS; i++)
+ {
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_sitemaxreplicalatency,
+ &sitemaxreplicalatency);
+ if (sitemaxreplicalatency)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " MaxRepLat%d:%u", i,
+ sitemaxreplicalatency);
+ }
+ }
+ /* kerb_princ_name sitePrincipal[MAXNSERVERS]; principal */
+ for (i = 0; i < MAXNSERVERS; i++)
+ {
+ proto_tree_add_string (tree, hf_fldb_vldbentry_siteprincipal, tvb,
+ offset, 64, tvb_get_ptr (tvb, offset, 64));
+ siteprincipal = tvb_get_ptr (tvb, offset, 64);
+ offset += 64;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Princ: %s", siteprincipal);
+ }
+
+ /* afsUUID siteOwner[MAXNSERVERS]; */
+
+ for (i = 0; i < MAXNSERVERS; i++)
+ {
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_siteowner, &siteowner);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " SiteOwner - %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ siteowner.Data1, siteowner.Data2, siteowner.Data3,
+ siteowner.Data4[0], siteowner.Data4[1],
+ siteowner.Data4[2], siteowner.Data4[3],
+ siteowner.Data4[4], siteowner.Data4[5],
+ siteowner.Data4[6], siteowner.Data4[7]);
+ }
+
+
+/* afsUUID siteObjID[MAXNSERVERS]; */
+ for (i = 0; i < MAXNSERVERS; i++)
+ {
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_siteobjid, &siteobjid);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " SiteObjID - %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ siteobjid.Data1, siteobjid.Data2, siteobjid.Data3,
+ siteobjid.Data4[0], siteobjid.Data4[1],
+ siteobjid.Data4[2], siteobjid.Data4[3],
+ siteobjid.Data4[4], siteobjid.Data4[5],
+ siteobjid.Data4[6], siteobjid.Data4[7]);
+ }
+
+
+ /* afsHyper VolIDs[MAXVOLTYPES]; */
+ /* XXX for these hypers, I will skip trying to use non portable guint64, and just read both, and use only low.
+ never seen a case of a volid going anywhere the overflow of the 32 low; */
+ for (i = 0; i < MAXVOLTYPES; i++)
+ {
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_volids_high, &volids_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_volids_low, &volids_low);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " VolIDs%d:%u", i,
+ volids_low);
+ }
+
+
+ /* unsigned32 VolTypes[MAXVOLTYPES]; */
+ for (i = 0; i < MAXVOLTYPES; i++)
+ {
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_voltypes, &voltypes);
+ if (voltypes)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " VolTypes:%d:%u", i,
+ voltypes);
+ }
+ }
+
+ /* afsHyper cloneId; Used during cloning */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_cloneid_high, &cloneid_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_cloneid_low, &cloneid_low);
+ if (cloneid_low)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " CloneId:%u", cloneid_low);
+ }
+
+ /* unsigned32 flags; General flags */
+ offset = dissect_afsflags (tvb, offset, pinfo, tree, drep);
+
+
+
+ /* unsigned32 maxTotalLatency; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_maxtotallatency, &maxtotallatency);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " MaxTotLat:%u",
+ maxtotallatency);
+
+
+ /* unsigned32 hardMaxTotalLatency; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_hardmaxtotallatency,
+ &hardmaxtotallatency);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " HardMaxTotLat:%u",
+ hardmaxtotallatency);
+
+
+ /* unsigned32 minimumPounceDally; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_minimumpouncedally,
+ &minimumpouncedally);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " minPounceDally:%u",
+ minimumpouncedally);
+
+
+ /* unsigned32 defaultMaxReplicaLatency; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_defaultmaxreplicalatency,
+ &defaultmaxreplicalatency);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " defaultMaxReplicaLatency:%u",
+ defaultmaxreplicalatency);
+
+ /* unsigned32 reclaimDally; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_reclaimdally, &reclaimdally);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " reclaimDally:%u",
+ reclaimdally);
+
+
+ /* unsigned32 WhenLocked; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_whenlocked, &whenlocked);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " WhenLocked:%u", whenlocked);
+
+
+ /* unsigned32 spare1; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_spare1, &spare1);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " spare1:%u", spare1);
+
+ /* unsigned32 spare2; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_spare2, &spare2);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " spare2:%u", spare2);
+
+
+ /* unsigned32 spare3; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_spare3, &spare3);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " spare3:%u", spare3);
+
+ /* unsigned32 spare4; */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_vldbentry_spare4, &spare4);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " spare4:%u", spare4);
+
+
+ /* byte LockerName[MAXLOCKNAMELEN]; */
+ proto_tree_add_string (tree, hf_fldb_vldbentry_lockername, tvb, offset,
+ MAXLOCKNAMELEN, tvb_get_ptr (tvb, offset,
+ MAXLOCKNAMELEN));
+ lockername = tvb_get_ptr (tvb, offset, MAXLOCKNAMELEN);
+ offset += MAXLOCKNAMELEN; /* some reason this 114 seems to be incorrect... cutting 4 short to compensate.... */
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " LockerName: %s", lockername);
+
+ /* byte charSpares[50]; */
+ proto_tree_add_string (tree, hf_fldb_vldbentry_charspares, tvb, offset, 50,
+ tvb_get_ptr (tvb, offset, 50));
+ charspares = tvb_get_ptr (tvb, offset, 50);
+ offset += 50; /* some reason this 114 seems to be incorrect... cutting 4 short to compensate.... */
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " charSpares:%s", charspares);
+
+
+
+ proto_item_set_len (item, offset - old_offset);
+
+ return offset;
+
+
+}
+
+static int
+fldb_dissect_getcellinfo_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+/* [out] vlconf_cell *MyCell */
+ offset = dissect_vlconf_cell (tvb, offset, pinfo, tree, drep);
+
+
+ return offset;
+}
+
+
+
+static int
+fldb_dissect_getentrybyname_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ /*
+ * [in] volumeName volName,
+ */
+
+ offset += 4;
+ offset = dissect_afsNameString_t (tvb, offset, pinfo, tree, drep);
+
+
+ return offset;
+
+}
+
+static int
+fldb_dissect_getentrybyname_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ /*
+ [out] vldbentry *entry
+ */
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ offset = dissect_vldbentry (tvb, offset, pinfo, tree, drep);
+
+ MACRO_ST_CLEAR ("GetEntryByName reply");
+ return offset;
+}
+
+static int
+fldb_dissect_getsiteinfo_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+
+ /*
+ * [in] afsNetAddr *OldAddr,
+ *
+ */
+
+ offset = dissect_afsnetaddr (tvb, offset, pinfo, tree, drep);
+
+
+ /*
+ *
+ * [in] afsNetAddr *OldAddr,
+ * unsigned16 type;
+ unsigned8 data[14];
+ */
+
+
+ return offset;
+}
+static int
+fldb_dissect_getsiteinfo_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+
+ dcerpc_info *di;
+ const guint8 *namestring;
+ e_uuid_t owner, objid;
+ guint32 creationquota, creationuses, deletedflag, spare2, spare3, spare4,
+ spare5;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ /*
+ [out] siteDessiib *FullSiteInfo
+ afsNetAddr Addr[ADDRSINSITE];
+ byte KerbPrin[MAXKPRINCIPALLEN] 64;
+ afsUUID Owner;
+ afsUUID ObjID;
+ unsigned32 CreationQuota;
+ unsigned32 CreationUses;
+ unsigned32 DeletedFlag;
+ unsigned32 spare2;
+ unsigned32 spare3;
+ unsigned32 spare4;
+ unsigned32 spare5;
+ */
+
+ offset = dissect_afsnetaddr (tvb, offset, pinfo, tree, drep);
+
+ /* handle byte KerbPrin[64]. */
+
+ offset += 48; /* part of kerbprin before name... */
+
+ proto_tree_add_string (tree, hf_fldb_namestring, tvb, offset, hf_fldb_namestring_size, tvb_get_ptr (tvb, offset, 64));
+ namestring = tvb_get_ptr (tvb, offset, 64);
+ offset += 64;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " %s", namestring);
+
+ offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_fldb_uuid_owner, &owner);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " Owner - %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ owner.Data1, owner.Data2, owner.Data3, owner.Data4[0],
+ owner.Data4[1], owner.Data4[2], owner.Data4[3],
+ owner.Data4[4], owner.Data4[5], owner.Data4[6],
+ owner.Data4[7]);
+
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_fldb_uuid_objid,
+ &objid);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " ObjID - %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ objid.Data1, objid.Data2, objid.Data3, objid.Data4[0],
+ objid.Data4[1], objid.Data4[2], objid.Data4[3],
+ objid.Data4[4], objid.Data4[5], objid.Data4[6],
+ objid.Data4[7]);
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_creationquota,
+ &creationquota);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_creationuses,
+ &creationuses);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_deletedflag,
+ &deletedflag);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_spare2,
+ &spare2);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_spare3,
+ &spare3);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_spare4,
+ &spare4);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_spare5,
+ &spare5);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " CreationQuota:%u CreationUses:%u DeletedFlag:%u Spare2:%u Spare3:%u Spare4:%u Spare5:%u",
+ creationquota, creationuses, deletedflag, spare2, spare3,
+ spare4, spare5);
+
+ MACRO_ST_CLEAR ("GetSiteInfo reply");
+
+ return offset;
+
+}
+
+static int
+fldb_dissect_listentry_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ guint32 var1, previous_index;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ /*
+ * [in] unsigned32 previous_index,
+ * [out] unsigned32 *count,
+ * [out] unsigned32 *next_index,
+ * [out] vldbentry *entry
+ */
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_listentry_rqst_previous_index,
+ &previous_index);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_listentry_rqst_var1, &var1);
+
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " :PrevIndex: %u",
+ previous_index);
+
+
+ return offset;
+
+}
+
+static int
+fldb_dissect_listentry_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+ guint32 count, next_index;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ /*
+ * [out] unsigned32 *count,
+ * [out] unsigned32 *next_index,
+ * [out] vldbentry *entry
+ */
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_listentry_resp_count, &count);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_listentry_resp_next_index, &next_index);
+ offset = dissect_vldbentry (tvb, offset, pinfo, tree, drep);
+ return offset;
+
+}
+
+static int
+fldb_dissect_setlock_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+ guint32 fsid_high, fsid_low, voltype, voloper;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_setlock_rqst_fsid_high, &fsid_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_setlock_rqst_fsid_low, &fsid_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_setlock_rqst_voltype, &voltype);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_setlock_rqst_voloper, &voloper);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " :FSID:%u/%u VolType:0x%x VolOper:%u", fsid_high,
+ fsid_low, voltype, voloper);
+
+ return offset;
+
+}
+static int
+fldb_dissect_setlock_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ MACRO_ST_CLEAR ("SetLock reply");
+
+
+
+ return offset;
+}
+static int
+fldb_dissect_deleteentry_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ MACRO_ST_CLEAR ("DeleteEntry reply");
+
+ return offset;
+}
+
+static int
+fldb_dissect_deleteentry_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+
+/*
+ [in] afsHyper *Volid,
+ [in] unsigned32 voltype
+*/
+ dcerpc_info *di;
+
+ guint32 fsid_high, fsid_low, voltype, voloper;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_deleteentry_rqst_fsid_high, &fsid_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_deleteentry_rqst_fsid_low, &fsid_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_deleteentry_rqst_voltype, &voltype);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_deleteentry_rqst_voloper, &voloper);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " :FSID:%u/%u", fsid_high,
+ fsid_low);
+
+
+ return offset;
+
+}
+
+static int
+fldb_dissect_createentry_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ MACRO_ST_CLEAR ("CreateEntry reply");
+
+ return offset;
+}
+
+static int
+fldb_dissect_createentry_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ offset = dissect_vldbentry (tvb, offset, pinfo, tree, drep);
+ return offset;
+
+}
+
+static int
+fldb_dissect_getentrybyid_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ guint32 volid_high, volid_low, voltype;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+
+/*
+ [in] afsHyper *Volid,
+ [in] unsigned32 voltype,
+*/
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_volid_high,
+ &volid_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_volid_low,
+ &volid_low);
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_voltype,
+ &voltype);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " VolID:%u/%u VolType:0x%x",
+ volid_high, volid_low, voltype);
+
+ return offset;
+
+}
+
+static int
+fldb_dissect_getnewvolumeids_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+/* [in] unsigned32 numWanted,
+ [in] afsNetAddr *ServerAddr,
+*/
+ dcerpc_info *di;
+ guint32 numwanted;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_numwanted,
+ &numwanted);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " numWanted:%u", numwanted);
+
+
+ offset = dissect_afsnetaddr (tvb, offset, pinfo, tree, drep);
+
+
+
+ return offset;
+}
+
+static int
+fldb_dissect_getentrybyid_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ offset = dissect_vldbentry (tvb, offset, pinfo, tree, drep);
+ return offset;
+}
+
+static int
+fldb_dissect_releaselock_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ MACRO_ST_CLEAR ("ReleaseLock reply");
+
+
+ return offset;
+}
+
+
+static int
+fldb_dissect_releaselock_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+ guint32 fsid_high, fsid_low, voltype, voloper;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_releaselock_rqst_fsid_high, &fsid_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_releaselock_rqst_fsid_low, &fsid_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_releaselock_rqst_voltype, &voltype);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_releaselock_rqst_voloper, &voloper);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " :FSID:%u/%u", fsid_high,
+ fsid_low);
+
+ return offset;
+
+}
+static int
+fldb_dissect_replaceentry_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ MACRO_ST_CLEAR ("ReplaceEntry reply");
+
+
+ return offset;
+}
+static int
+fldb_dissect_getnextserversbyid_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ guint32 nextstartp, flagsp;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+
+
+
+ /* [out] unsigned32 *nextStartP, */
+/* XXX */
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_nextstartp,
+ &nextstartp);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " nextStartP:%u", nextstartp);
+
+
+ /* [out] vldbentry *entry, */
+ offset = dissect_vldbentry (tvb, offset, pinfo, tree, drep);
+
+
+ /* [out] unsigned32 *flagsP */
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_fldb_flagsp,
+ &flagsp);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " flagsp:%u", flagsp);
+
+ return offset;
+}
+
+static int
+fldb_dissect_replaceentry_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+ guint32 fsid_high, fsid_low, voltype;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ /*
+ * [in] afsHyper *Volid,
+ * [in] unsigned32 voltype,
+ * [in] vldbentry *newentry,
+ * [in] unsigned32 ReleaseType
+ */
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_replaceentry_rqst_fsid_high, &fsid_high);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_replaceentry_rqst_fsid_low, &fsid_low);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_fldb_replaceentry_rqst_voltype, &voltype);
+
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " FSID:%u/%u Name:", fsid_high,
+ fsid_low);
+
+ offset = dissect_vldbentry (tvb, offset, pinfo, tree, drep);
+
+ return offset;
+
+}
+
+
+static dcerpc_sub_dissector fldb_dissectors[] = {
+ {0, "GetEntryByID", fldb_dissect_getentrybyid_rqst,
+ fldb_dissect_getentrybyid_resp},
+ {1, "GetEntryByName", fldb_dissect_getentrybyname_rqst,
+ fldb_dissect_getentrybyname_resp},
+ {2, "Probe", NULL, NULL},
+ {3, "GetCellInfo", NULL, fldb_dissect_getcellinfo_resp},
+ {4, "GetNextServersByID", NULL, fldb_dissect_getnextserversbyid_resp},
+ {5, "GetNextServersByName", NULL, NULL},
+ {6, "GetSiteInfo", fldb_dissect_getsiteinfo_rqst,
+ fldb_dissect_getsiteinfo_resp},
+ {7, "GetCEntryByID", NULL, NULL},
+ {8, "GetCEntryByName", NULL, NULL},
+ {9, "GetCNextServersByID", NULL, NULL},
+ {10, "GetCNextServersByName", NULL, NULL},
+ {11, "ExpandSiteCookie", NULL, NULL},
+ {12, "GetServerInterfaces", NULL, NULL},
+ {13, "CreateEntry", fldb_dissect_createentry_rqst,
+ fldb_dissect_createentry_resp},
+ {14, "DeleteEntry", fldb_dissect_deleteentry_rqst,
+ fldb_dissect_deleteentry_resp},
+ {15, "GetNewVolumeId", NULL, NULL},
+ {16, "ReplaceEntry", fldb_dissect_replaceentry_rqst,
+ fldb_dissect_replaceentry_resp},
+ {17, "SetLock", fldb_dissect_setlock_rqst, fldb_dissect_setlock_resp},
+ {18, "ReleaseLock", fldb_dissect_releaselock_rqst,
+ fldb_dissect_releaselock_resp},
+ {19, "ListEntry", fldb_dissect_listentry_rqst, fldb_dissect_listentry_resp},
+ {20, "ListByAttributes", NULL, NULL},
+ {21, "GetStats", NULL, NULL},
+ {22, "AddAddress", NULL, NULL},
+ {23, "RemoveAddress", NULL, NULL},
+ {24, "ChangeAddress", NULL, NULL},
+ {25, "GenerateSites", NULL, NULL},
+ {26, "GetNewVolumeIds", fldb_dissect_getnewvolumeids_rqst, NULL},
+ {27, "CreateServer", NULL, NULL},
+ {28, "AlterServer", NULL, NULL},
+ {0, NULL, NULL, NULL},
+};
+
+
+void
+proto_register_fldb (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_fldb_releaselock_rqst_fsid_low,
+ {"FSID releaselock Low", "hf_fldb_releaselock_rqst_fsid_low", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_releaselock_rqst_voltype,
+ {"voltype", "hf_fldb_releaselock_rqst_voltype", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_releaselock_rqst_voloper,
+ {"voloper", "hf_fldb_releaselock_rqst_voloper", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_setlock_rqst_fsid_high,
+ {"FSID setlock Hi", "hf_fldb_setlock_rqst_fsid_high", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_setlock_rqst_fsid_low,
+ {"FSID setlock Low", "hf_fldb_setlock_rqst_fsid_low", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_setlock_rqst_voltype,
+ {"voltype", "hf_fldb_setlock_rqst_voltype", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_setlock_rqst_voloper,
+ {"voloper", "hf_fldb_setlock_rqst_voloper", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_setlock_resp_st,
+ {"Error", "hf_fldb_setlock_resp_st", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_setlock_resp_st2,
+ {"Error", "hf_fldb_setlock_resp_st2", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_listentry_rqst_previous_index,
+ {"Previous Index", "hf_fldb_listentry_rqst_previous_index", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_listentry_rqst_var1,
+ {"Var 1", "hf_fldb_listentry_rqst_var1", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_listentry_resp_count,
+ {"Count", "hf_fldb_listentry_resp_count", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_listentry_resp_next_index,
+ {"Next Index", "hf_fldb_listentry_resp_next_index", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_listentry_resp_key_size,
+ {"Key Size", "hf_fldb_listentry_resp_key_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_listentry_resp_key_t,
+ {"Volume", "hf_fldb_listentry_resp_key_t", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_listentry_resp_voltype,
+ {"VolType", "hf_fldb_listentry_resp_voltype", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_listentry_resp_key_size2,
+ {"key_size2", "hf_fldb_listentry_resp_key_size2", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_listentry_resp_key_t2,
+ {"Server", "hf_fldb_listentry_resp_key_t2", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_createentry_rqst_key_t,
+ {"Volume", "hf_fldb_createentry_rqst_key_t", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_createentry_rqst_key_size,
+ {"Volume Size", "hf_fldb_createentry_rqst_key_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_deleteentry_rqst_fsid_high,
+ {"FSID deleteentry Hi", "hf_fldb_deleteentry_rqst_fsid_high", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_deleteentry_rqst_fsid_low,
+ {"FSID deleteentry Low", "hf_fldb_deleteentry_rqst_fsid_low", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_deleteentry_rqst_voltype,
+ {"voltype", "hf_fldb_deleteentry_rqst_voltype", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_deleteentry_rqst_voloper,
+ {"voloper", "hf_fldb_deleteentry_rqst_voloper", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyid_rqst_fsid_high,
+ {"FSID deleteentry Hi", "hf_fldb_getentrybyid_rqst_fsid_high", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyid_rqst_fsid_low,
+ {"FSID getentrybyid Low", "hf_fldb_getentrybyid_rqst_fsid_low",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyid_rqst_voltype,
+ {"voltype", "hf_fldb_getentrybyid_rqst_voltype", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyid_rqst_voloper,
+ {"voloper", "hf_fldb_getentrybyid_rqst_voloper", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_replaceentry_rqst_fsid_high,
+ {"FSID replaceentry Hi", "hf_fldb_replaceentry_rqst_fsid_high",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_replaceentry_rqst_fsid_low,
+ {"FSID replaceentry Low", "hf_fldb_replaceentry_rqst_fsid_low",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_replaceentry_rqst_voltype,
+ {"voltype", "hf_fldb_replaceentry_rqst_voltype", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_replaceentry_rqst_key_t,
+ {"Key", "hf_fldb_replaceentry_rqst_key_t", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_replaceentry_rqst_key_size,
+ {"Key Size", "hf_fldb_replaceentry_rqst_key_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_replaceentry_resp_st,
+ {"Error", "hf_fldb_replaceentry_resp_st", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_replaceentry_resp_st2,
+ {"Error", "hf_fldb_replaceentry_resp_st2", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_volumetype,
+ {"hf_fldb_getentrybyname_resp_volumetype",
+ "hf_fldb_getentrybyname_resp_volumetype", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_numservers,
+ {"hf_fldb_getentrybyname_resp_numservers",
+ "hf_fldb_getentrybyname_resp_numservers", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_sitecookies,
+ {"hf_fldb_getentrybyname_resp_sitecookies",
+ "hf_fldb_getentrybyname_resp_sitecookies", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_sitepartition,
+ {"hf_fldb_getentrybyname_resp_sitepartition",
+ "hf_fldb_getentrybyname_resp_sitepartition", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_siteflags,
+ {"hf_fldb_getentrybyname_resp_siteflags",
+ "hf_fldb_getentrybyname_resp_siteflags", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_sitemaxreplat,
+ {"hf_fldb_getentrybyname_resp_sitemaxreplat",
+ "hf_fldb_getentrybyname_resp_sitemaxreplat", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_volid_high,
+ {"hf_fldb_getentrybyname_resp_volid_high",
+ "hf_fldb_getentrybyname_resp_volid_high", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_volid_low,
+ {"hf_fldb_getentrybyname_resp_volid_low",
+ "hf_fldb_getentrybyname_resp_volid_low", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_voltype,
+ {"hf_fldb_getentrybyname_resp_voltype",
+ "hf_fldb_getentrybyname_resp_voltype", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_cloneid_high,
+ {"hf_fldb_getentrybyname_resp_cloneid_high",
+ "hf_fldb_getentrybyname_resp_cloneid_high", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_cloneid_low,
+ {"hf_fldb_getentrybyname_resp_cloneid_low",
+ "hf_fldb_getentrybyname_resp_cloneid_low", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_flags,
+ {"hf_fldb_getentrybyname_resp_flags",
+ "hf_fldb_getentrybyname_resp_flags", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_getentrybyname_resp_maxtotallat,
+ {"hf_fldb_getentrybyname_resp_maxtotallat",
+ "hf_fldb_getentrybyname_resp_maxtotallat", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_hardmaxtotlat,
+ {"hf_fldb_getentrybyname_resp_hardmaxtotlat",
+ "hf_fldb_getentrybyname_resp_hardmaxtotlat", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_minpouncedally,
+ {"hf_fldb_getentrybyname_resp_minpouncedally",
+ "hf_fldb_getentrybyname_resp_minpouncedally", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_defaultmaxreplat,
+ {"hf_fldb_getentrybyname_resp_defaultmaxreplat",
+ "hf_fldb_getentrybyname_resp_defaultmaxreplat", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_reclaimdally,
+ {"hf_fldb_getentrybyname_resp_reclaimdally",
+ "hf_fldb_getentrybyname_resp_reclaimdally", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_whenlocked,
+ {"hf_fldb_getentrybyname_resp_whenlocked",
+ "hf_fldb_getentrybyname_resp_whenlocked", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_spare1,
+ {"hf_fldb_getentrybyname_resp_spare1",
+ "hf_fldb_getentrybyname_resp_spare1", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_spare2,
+ {"hf_fldb_getentrybyname_resp_spare2",
+ "hf_fldb_getentrybyname_resp_spare2", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_spare3,
+ {"hf_fldb_getentrybyname_resp_spare3",
+ "hf_fldb_getentrybyname_resp_spare3", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_spare4,
+ {"hf_fldb_getentrybyname_resp_spare4",
+ "hf_fldb_getentrybyname_resp_spare4", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_key_t,
+ {"hf_fldb_getentrybyname_resp_key_t",
+ "hf_fldb_getentrybyname_resp_key_t", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_key_size,
+ {"hf_fldb_getentrybyname_resp_size",
+ "hf_fldb_getentrybyname_resp_key_size", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_getentrybyname_resp_test,
+ {"hf_fldb_getentrybyname_resp_test", "hf_fldb_getentrybyname_resp_test",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_releaselock_rqst_fsid_high,
+ {"FSID releaselock Hi", "hf_fldb_releaselock_rqst_fsid_high", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_opnum,
+ {"Operation", "fldb.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation",
+ HFILL}},
+ {&hf_fldb_vldbentry_volumename,
+ {"VolumeName", "vldbentry.volumename", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_vldbentry_volumetype,
+ {"VolumeType", "vldbentry.volumetype", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_vldbentry_nservers,
+ {"Number of Servers", "vldbentry.nservers", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_afsnetaddr_type,
+ {"Type", "afsnetaddr.type", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_afsnetaddr_data,
+ {"IP Data", "afsnetaddr.data", FT_UINT8, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vldbentry_sitepartition,
+ {"Site Partition", "vldbentry.sitepartition", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_siteflags,
+ {"Site Flags", "vldbentry.siteflags", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vldbentry_sitemaxreplicalatency,
+ {"Site Max Replica Latench", "vldbentry.sitemaxreplatency", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vldbentry_siteprincipal,
+ {"Principal Name", "vldbentry.siteprincipal", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_vldbentry_siteowner,
+ {"Site Owner", "vldbentry.siteowner", FT_STRING, BASE_NONE, NULL, 0x0,
+ "UUID", HFILL}},
+ {&hf_fldb_vldbentry_siteobjid,
+ {"Site Object ID", "vldbentry.siteobjid", FT_STRING, BASE_NONE, NULL,
+ 0x0, "UUID", HFILL}},
+ {&hf_fldb_vldbentry_volids_high,
+ {"VolIDs high", "vldbentry.volidshigh", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_vldbentry_volids_low,
+ {"VolIDs low", "vldbentry.volidslow", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vldbentry_voltypes,
+ {"VolTypes", "vldbentry.voltypes", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vldbentry_cloneid_high,
+ {"CloneID High", "vldbentry.cloneidhigh", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_vldbentry_cloneid_low,
+ {"CloneID Low", "vldbentry.cloneidlow", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_afsflags_flags,
+ {"AFS Flags", "vldbentry.afsflags", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vldbentry_maxtotallatency,
+ {"Max Total Latency", "vldbentry.maxtotallatency", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vldbentry_hardmaxtotallatency,
+ {"Hard Max Total Latency", "vldbentry.hardmaxtotallatency", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vldbentry_minimumpouncedally,
+ {"Minimum Pounce Dally", "vldbentry.minimumpouncedally", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vldbentry_defaultmaxreplicalatency,
+ {"Default Max Replica Latency", "vldbentry.defaultmaxreplicalatency",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vldbentry_reclaimdally,
+ {"Reclaim Dally", "vldbentry.reclaimdally", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_vldbentry_whenlocked,
+ {"When Locked", "vldbentry.whenlocked", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_vldbentry_spare1,
+ {"Spare 1", "vldbentry.spare1", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vldbentry_spare2,
+ {"Spare 2", "vldbentry.spare2", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vldbentry_spare3,
+ {"Spare 3", "vldbentry.spare3", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vldbentry_spare4,
+ {"Spare 4", "vldbentry.spare4", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vldbentry_lockername,
+ {"Locker Name", "vldbentry.lockername", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_vldbentry_charspares,
+ {"Char Spares", "vldbentry.charspares", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_vlconf_cell_name,
+ {"Name", "vlconf.name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vlconf_cell_cellid_high,
+ {"CellID High", "vlconf.cellidhigh", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vlconf_cell_cellid_low,
+ {"CellID Low", "vlconf.cellidlow", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vlconf_cell_numservers,
+ {"Number of Servers", "vlconf.numservers", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_vlconf_cell_hostname,
+ {"hostName", "vlconf.hostname", FT_STRING, BASE_NONE, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_vlconf_cell_spare1,
+ {"Spare1", "vlconf.spare1", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vlconf_cell_spare2,
+ {"Spare2", "vlconf.spare2", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vlconf_cell_spare3,
+ {"Spare3", "vlconf.spare3", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vlconf_cell_spare4,
+ {"Spare4", "vlconf.spare4", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_vlconf_cell_spare5,
+ {"Spare5", "vlconf.spare5", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_flagsp,
+ {"flagsp", "fldb.flagsp", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_nextstartp,
+ {"nextstartp", "fldb.nextstartp", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_afsNameString_t_principalName_size,
+ {"Principal Name Size", "fldb.principalName_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_afsNameString_t_principalName_size2,
+ {"Principal Name Size2", "fldb.principalName_size2", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_afsNameString_t_principalName_string,
+ {"Principal Name", "fldb.NameString_principal", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+ {&hf_fldb_namestring,
+ {"Name string", "fldb.NameString_principal", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ {&hf_dcerpc_error_status,
+ {"Error Status", "fldb.NameString_principal", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_error_st,
+ {"Error Status 2", "fldb.error_st", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_creationquota,
+ {"creation quota", "fldb.creationquota", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_creationuses,
+ {"creation uses", "fldb.creationuses", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_fldb_deletedflag,
+ {"deletedflag", "fldb.deletedflag", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_getentrybyname_rqst_key_size,
+ {"getentrybyname", "fldb.getentrybyname_rqst_key_size", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_getentrybyname_rqst_var1,
+ {"getentrybyname var1", "fldb.getentrybyname_rqst_var1", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_namestring_size,
+ {"namestring size", "fldb.namestring_size", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fldb_numwanted,
+ {"number wanted", "fldb.numwanted", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_spare2,
+ {"spare2", "fldb.spare2", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_spare3,
+ {"spare3", "fldb.spare3", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_spare4,
+ {"spare4", "fldb.spare4", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_spare5,
+ {"spare5", "fldb.spare5", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fldb_uuid_objid,
+ {"objid", "fldb.uuid_objid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID",
+ HFILL}},
+ {&hf_fldb_uuid_owner,
+ {"owner", "fldb.uuid_owner", FT_STRING, BASE_NONE, NULL, 0x0, "UUID",
+ HFILL}},
+ {&hf_fldb_volid_high,
+ {"volid high", "fldb.volid_high", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_volid_low,
+ {"volid low", "fldb.volid_low", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_fldb_voltype,
+ {"voltype", "fldb.voltype", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_fldb,
+ &ett_fldb_vldbentry,
+ &ett_fldb_afsnetaddr,
+ &ett_fldb_siteflags,
+ &ett_fldb_afsflags,
+ &ett_fldb_vlconf_cell,
+ &ett_fldb_afsNameString_t,
+ };
+
+ proto_fldb = proto_register_protocol ("DCE/RPC FLDB", "FLDB", "fldb");
+ proto_register_field_array (proto_fldb, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_fldb (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_fldb, ett_fldb, &uuid_fldb, ver_fldb,
+ fldb_dissectors, hf_fldb_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-frsapi.c b/epan/dissectors/packet-dcerpc-frsapi.c
new file mode 100644
index 0000000000..979e708f06
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-frsapi.c
@@ -0,0 +1,106 @@
+/* packet-dcerpc-frsapi.c
+ * Routines for the frs API (File Replication Service) MSRPC interface
+ * Copyright 2004 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-frsapi.h"
+
+static int proto_dcerpc_frsapi = -1;
+
+static int hf_frsapi_opnum = 0;
+
+static gint ett_dcerpc_frsapi = -1;
+
+/*
+IDL [ uuid(d049b186-814f-11d1-9a3c-00c04fc9b232),
+IDL version(1.1),
+IDL implicit_handle(handle_t rpc_binding)
+IDL ] interface frsapi
+*/
+
+static e_uuid_t uuid_dcerpc_frsapi = {
+ 0xd049b186, 0x814f, 0x11d1,
+ { 0x9a, 0x3c, 0x00, 0xc0, 0x4f, 0xc9, 0xb2, 0x32 }
+};
+
+static guint16 ver_dcerpc_frsapi = 1;
+
+
+static dcerpc_sub_dissector dcerpc_frsapi_dissectors[] = {
+ { FRSAPI_VERIFY_PROMOTION, "VerifyPromotion", NULL, NULL },
+ { FRSAPI_PROMOTION_STATUS, "PromotionStatus", NULL, NULL },
+ { FRSAPI_START_DEMOTION, "StartDemotion", NULL, NULL },
+ { FRSAPI_COMMIT_DEMOTION, "CommitDemotion", NULL, NULL },
+ { FRSAPI_SET_DS_POLLING_INTERVAL_W, "Set_DsPollingIntervalW", NULL, NULL },
+ { FRSAPI_GET_DS_POLLING_INTERVAL_W, "Get_DsPollingIntervalW", NULL, NULL },
+ { FRSAPI_VERIFY_PROMOTION_W, "VerifyPromotionW", NULL, NULL },
+ { FRSAPI_INFO_W, "InfoW", NULL, NULL },
+ { FRSAPI_IS_PATH_REPLICATED, "IsPathReplicated", NULL, NULL },
+ { FRSAPI_WRITER_COMMAND, "WriterCommand", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_frsapi(void)
+{
+
+ static hf_register_info hf[] = {
+
+ { &hf_frsapi_opnum,
+ { "Operation", "frsapi.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ };
+
+
+ static gint *ett[] = {
+ &ett_dcerpc_frsapi,
+ };
+
+
+ proto_dcerpc_frsapi = proto_register_protocol(
+ "Microsoft File Replication Service API", "FRSAPI", "frsapi");
+
+ proto_register_field_array(proto_dcerpc_frsapi, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+void
+proto_reg_handoff_dcerpc_frsapi(void)
+{
+ /* register protocol as dcerpc */
+
+ dcerpc_init_uuid(
+ proto_dcerpc_frsapi, ett_dcerpc_frsapi, &uuid_dcerpc_frsapi,
+ ver_dcerpc_frsapi, dcerpc_frsapi_dissectors, hf_frsapi_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-frsapi.h b/epan/dissectors/packet-dcerpc-frsapi.h
new file mode 100644
index 0000000000..dbd2ba9f5f
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-frsapi.h
@@ -0,0 +1,42 @@
+/* packet-dcerpc-frsapi.h
+ * Routines for the frs API (File Replication Service) MSRPC interface
+ * Copyright 2004 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_FRSAPI_H
+#define __PACKET_DCERPC_FRSAPI_H
+
+/* MSRPC functions available in the frsapi interface */
+
+#define FRSAPI_VERIFY_PROMOTION 0x00
+#define FRSAPI_PROMOTION_STATUS 0x01
+#define FRSAPI_START_DEMOTION 0x02
+#define FRSAPI_COMMIT_DEMOTION 0x03
+#define FRSAPI_SET_DS_POLLING_INTERVAL_W 0x04
+#define FRSAPI_GET_DS_POLLING_INTERVAL_W 0x05
+#define FRSAPI_VERIFY_PROMOTION_W 0x06
+#define FRSAPI_INFO_W 0x07
+#define FRSAPI_IS_PATH_REPLICATED 0x08
+#define FRSAPI_WRITER_COMMAND 0x09
+
+#endif /* packet-dcerpc-frsapi.h */
diff --git a/epan/dissectors/packet-dcerpc-frsrpc.c b/epan/dissectors/packet-dcerpc-frsrpc.c
new file mode 100644
index 0000000000..805e45b661
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-frsrpc.c
@@ -0,0 +1,114 @@
+/* packet-dcerpc-frsrpc.c
+ * Routines for the frs (File Replication Service) MSRPC interface
+ * Copyright 2004 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-frsrpc.h"
+
+static int proto_dcerpc_frsrpc = -1;
+
+static int hf_frsrpc_opnum = 0;
+
+static gint ett_dcerpc_frsrpc = -1;
+
+/*
+IDL [ uuid(f5cc59b4-4264-101a-8c59-08002b2f8426),
+IDL version(1.1),
+IDL implicit_handle(handle_t rpc_binding)
+IDL ] interface frsrpc
+*/
+
+
+static e_uuid_t uuid_dcerpc_frsrpc = {
+ 0xf5cc59b4, 0x4264, 0x101a,
+ { 0x8c, 0x59, 0x08, 0x00, 0x2b, 0x2f, 0x84, 0x26 }
+};
+
+static guint16 ver_dcerpc_frsrpc = 1;
+
+
+static dcerpc_sub_dissector dcerpc_frsrpc_dissectors[] = {
+ { FRSRPC_SEND_COMM_PKT, "FrsRpcSendCommPkt",
+ NULL, NULL },
+ { FRSRPC_VERIFY_PROMOTION_PARENT, "FrsRpcVerifyPromotionParent",
+ NULL, NULL },
+ { FRSRPC_START_PROMOTION_PARENT, "FrsRpcStartPromotionParent",
+ NULL, NULL },
+ { FRSRPC_NOP, "FrsRpcNop", NULL, NULL },
+/* operations 4 to 9 are apparently identical */
+ { FRSRPC_BACKUP_COMPLETE, "FrsRpcBackupComplete", NULL, NULL },
+ { FRSRPC_BACKUP_COMPLETE_5, "FrsRpcBackupComplete", NULL, NULL },
+ { FRSRPC_BACKUP_COMPLETE_6, "FrsRpcBackupComplete", NULL, NULL },
+ { FRSRPC_BACKUP_COMPLETE_7, "FrsRpcBackupComplete", NULL, NULL },
+ { FRSRPC_BACKUP_COMPLETE_8, "FrsRpcBackupComplete", NULL, NULL },
+ { FRSRPC_BACKUP_COMPLETE_9, "FrsRpcBackupComplete", NULL, NULL },
+ { FRSRPC_VERIFY_PROMOTION_PARENT_EX, "FrsRpcVerifyPromotionParentEx",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+
+void
+proto_register_dcerpc_frsrpc(void)
+{
+
+ static hf_register_info hf[] = {
+
+ { &hf_frsrpc_opnum,
+ { "Operation", "frsrpc.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ };
+
+
+ static gint *ett[] = {
+ &ett_dcerpc_frsrpc,
+ };
+
+
+ proto_dcerpc_frsrpc = proto_register_protocol(
+ "Microsoft File Replication Service", "FRSRPC", "frsrpc");
+
+ proto_register_field_array(proto_dcerpc_frsrpc, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+void
+proto_reg_handoff_dcerpc_frsrpc(void)
+{
+ /* register protocol as dcerpc */
+
+ dcerpc_init_uuid(
+ proto_dcerpc_frsrpc, ett_dcerpc_frsrpc, &uuid_dcerpc_frsrpc,
+ ver_dcerpc_frsrpc, dcerpc_frsrpc_dissectors, hf_frsrpc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-frsrpc.h b/epan/dissectors/packet-dcerpc-frsrpc.h
new file mode 100644
index 0000000000..8132405395
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-frsrpc.h
@@ -0,0 +1,43 @@
+/* packet-dcerpc-frsrpc.h
+ * Routines for the frs (File Replication Service) MSRPC interface
+ * Copyright 2004 Jean-Baptiste Marchand <jbm@hsc.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_FRSRPC_H
+#define __PACKET_DCERPC_FRSRPC_H
+
+/* MSRPC functions available in the frsrpc interface */
+
+#define FRSRPC_SEND_COMM_PKT 0x00
+#define FRSRPC_VERIFY_PROMOTION_PARENT 0x01
+#define FRSRPC_START_PROMOTION_PARENT 0x02
+#define FRSRPC_NOP 0x03
+#define FRSRPC_BACKUP_COMPLETE 0x04
+#define FRSRPC_BACKUP_COMPLETE_5 0x05
+#define FRSRPC_BACKUP_COMPLETE_6 0x06
+#define FRSRPC_BACKUP_COMPLETE_7 0x07
+#define FRSRPC_BACKUP_COMPLETE_8 0x08
+#define FRSRPC_BACKUP_COMPLETE_9 0x09
+#define FRSRPC_VERIFY_PROMOTION_PARENT_EX 0x0a
+
+#endif /* packet-dcerpc-frsrpc.h */
diff --git a/epan/dissectors/packet-dcerpc-ftserver.c b/epan/dissectors/packet-dcerpc-ftserver.c
new file mode 100644
index 0000000000..8d3223e088
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-ftserver.c
@@ -0,0 +1,104 @@
+/* packet-dcerpc-ftserver.c
+ *
+ * Routines for dcerpc ftserver dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tgz file/ftserver/ftserver_proc.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_ftserver = -1;
+static int hf_ftserver_opnum = -1;
+
+
+
+static gint ett_ftserver = -1;
+
+
+static e_uuid_t uuid_ftserver = { 0x4d37f2dd, 0xed43, 0x0004, { 0x02, 0xc0, 0x37, 0xcf, 0x1e, 0x00, 0x00, 0x00 } };
+static guint16 ver_ftserver = 4;
+
+
+static dcerpc_sub_dissector ftserver_dissectors[] = {
+ { 0, "CreateTrans", NULL, NULL },
+ { 1, "AbortTrans", NULL, NULL },
+ { 2, "DeleteTrans", NULL, NULL },
+ { 3, "CreateVolume", NULL, NULL },
+ { 4, "DeleteVolume", NULL, NULL },
+ { 5, "Dump", NULL, NULL },
+ { 6, "Restore", NULL, NULL },
+ { 7, "Forward", NULL, NULL },
+ { 8, "Clone", NULL, NULL },
+ { 9, "ReClone", NULL, NULL },
+ { 10, "GetFlags", NULL, NULL },
+ { 11, "SetFlags", NULL, NULL },
+ { 12, "GetStatus", NULL, NULL },
+ { 13, "SetStatus", NULL, NULL },
+ { 14, "ListVolumes", NULL, NULL },
+ { 15, "ListAggregates", NULL, NULL },
+ { 16, "AggregateInfo", NULL, NULL },
+ { 17, "Monitor", NULL, NULL },
+ { 18, "GetOneVolStatus", NULL, NULL },
+ { 19, "GetServerInterfaces", NULL, NULL },
+ { 20, "SwapIDs", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_ftserver (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ftserver_opnum,
+ { "Operation", "ftserver.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_ftserver,
+ };
+ proto_ftserver = proto_register_protocol ("FTServer Operations", "FTSERVER", "ftserver");
+ proto_register_field_array (proto_ftserver, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_ftserver (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_ftserver, ett_ftserver, &uuid_ftserver, ver_ftserver, ftserver_dissectors, hf_ftserver_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-icl_rpc.c b/epan/dissectors/packet-dcerpc-icl_rpc.c
new file mode 100644
index 0000000000..16016e6eb7
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-icl_rpc.c
@@ -0,0 +1,86 @@
+/* packet-dcerpc-icl_rpc.c
+ * Routines for icl_rpc dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz icl_rpc.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_icl_rpc = -1;
+static int hf_icl_rpc_opnum = -1;
+
+
+static gint ett_icl_rpc = -1;
+
+static e_uuid_t uuid_icl_rpc = { 0x003fd39c, 0x7feb, 0x1bbc, { 0xbe, 0xbe, 0x02, 0x60, 0x8c, 0x2e, 0xf4, 0xd2 } };
+static guint16 ver_icl_rpc = 1;
+
+
+
+static dcerpc_sub_dissector icl_rpc_dissectors[] = {
+ { 0, "DFSTRACE_GetSetInfo", NULL, NULL },
+ { 1, "DFSTRACE_SetSetInfo", NULL, NULL },
+ { 2, "DFSTRACE_GetLogInfo", NULL, NULL },
+ { 3, "DFSTRACE_SetLogInfo", NULL, NULL },
+ { 4, "DFSTRACE_ClearSet", NULL, NULL },
+ { 5, "DFSTRACE_ClearLog", NULL, NULL },
+ { 6, "DFSTRACE_DumpSet", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_icl_rpc (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_icl_rpc_opnum,
+ { "Operation", "icl_rpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_icl_rpc,
+ };
+ proto_icl_rpc = proto_register_protocol ("DCE/RPC ICL RPC", "ICL_RPC", "icl_rpc");
+ proto_register_field_array (proto_icl_rpc, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_icl_rpc (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_icl_rpc, ett_icl_rpc, &uuid_icl_rpc, ver_icl_rpc, icl_rpc_dissectors, hf_icl_rpc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-initshutdown.c b/epan/dissectors/packet-dcerpc-initshutdown.c
new file mode 100644
index 0000000000..2d38ec1322
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-initshutdown.c
@@ -0,0 +1,212 @@
+/* packet-dcerpc-initshutdown.c
+ * Routines for SMB \PIPE\initshutdown packet disassembly
+ * Based on packet-dcerpc-winreg.c
+ * Copyright 2001-2003 Tim Potter <tpot@samba.org>
+ * as per a suggestion by Jim McDonough
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-initshutdown.h"
+#include "smb.h"
+
+/* Global hf index fields */
+
+static int hf_rc = -1;
+static int hf_shutdown_message = -1;
+static int hf_shutdown_seconds = -1;
+static int hf_shutdown_force = -1;
+static int hf_shutdown_reboot = -1;
+static int hf_shutdown_server = -1;
+static int hf_shutdown_reason = -1;
+
+
+/* Reg Shutdown functions */
+static int
+dissect_shutdown_server(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_server, NULL);
+
+ return offset;
+}
+
+static int
+dissect_shutdown_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_message, 0);
+
+ return offset;
+}
+
+static int
+InitshutdownShutdown_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_shutdown_server, NDR_POINTER_UNIQUE,
+ "Server", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_shutdown_message, NDR_POINTER_UNIQUE,
+ "message", -1);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_seconds, NULL);
+
+ offset = dissect_ndr_uint8(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_force, NULL);
+ offset = dissect_ndr_uint8(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_reboot, NULL);
+
+ return offset;
+}
+
+static int
+InitshutdownShutdown_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+static int
+InitshutdownAbortShutdown_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_shutdown_server, NDR_POINTER_UNIQUE,
+ "Server", -1);
+
+ return offset;
+}
+
+static int
+InitshutdownShutdownEx_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = InitshutdownShutdown_q(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_reason, NULL);
+
+ return offset;
+}
+
+static int proto_dcerpc_initshutdown = -1;
+static int hf_initshutdown_opnum = -1;
+static gint ett_dcerpc_initshutdown = -1;
+
+static e_uuid_t uuid_dcerpc_initshutdown = {
+ 0x894de0c0, 0x0d55, 0x11d3,
+ { 0xa3, 0x22, 0x00, 0xc0, 0x4f, 0xa3, 0x21, 0xa1 }
+};
+
+static guint16 ver_dcerpc_initshutdown = 1;
+
+static dcerpc_sub_dissector dcerpc_initshutdown_dissectors[] = {
+ { INITSHUTDOWN_INITIATE_SYSTEM_SHUTDOWN, "InitiateSystemShutdown",
+ InitshutdownShutdown_q, InitshutdownShutdown_r },
+ { INITSHUTDOWN_ABORT_SYSTEM_SHUTDOWN, "AbortSystemShutdown",
+ InitshutdownAbortShutdown_q, InitshutdownShutdown_r },
+ { INITSHUTDOWN_INITIATE_SYSTEM_SHUTDOWN_EX, "InitiateSystemShutdownEx",
+ InitshutdownShutdownEx_q, InitshutdownShutdown_r },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_initshutdown(void)
+{
+ static hf_register_info hf[] = {
+
+ /* Global indexes */
+
+ { &hf_rc,
+ { "Return code", "initshutdown.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "Initshutdown return code", HFILL }},
+
+ { &hf_initshutdown_opnum,
+ { "Operation", "initshutdown.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ { &hf_shutdown_message,
+ { "Message", "initshutdown.message", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Message", HFILL }},
+
+ { &hf_shutdown_seconds,
+ { "Seconds", "initshutdown.seconds", FT_UINT32, BASE_DEC,
+ NULL, 0x00, "Seconds", HFILL }},
+
+ { &hf_shutdown_force,
+ { "Force applications shut", "initshutdown.force", FT_UINT8,
+ BASE_DEC, NULL, 0x00, "Force applications shut", HFILL }},
+
+ { &hf_shutdown_reboot,
+ { "Reboot", "initshutdown.reboot", FT_UINT8, BASE_DEC,
+ NULL, 0x00, "Reboot", HFILL }},
+
+ { &hf_shutdown_server,
+ { "Server", "initshutdown.server", FT_UINT16, BASE_HEX,
+ NULL, 0x00, "Server", HFILL }},
+
+ { &hf_shutdown_reason,
+ { "Reason", "initshutdown.reason", FT_UINT32, BASE_HEX,
+ NULL, 0x00, "Reason", HFILL }}
+
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_initshutdown
+ };
+
+ proto_dcerpc_initshutdown = proto_register_protocol(
+ "Remote Shutdown", "INITSHUTDOWN", "initshutdown");
+
+ proto_register_field_array(proto_dcerpc_initshutdown, hf,
+ array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_initshutdown(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_initshutdown, ett_dcerpc_initshutdown,
+ &uuid_dcerpc_initshutdown, ver_dcerpc_initshutdown,
+ dcerpc_initshutdown_dissectors, hf_initshutdown_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-initshutdown.h b/epan/dissectors/packet-dcerpc-initshutdown.h
new file mode 100644
index 0000000000..4ff8b36eaf
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-initshutdown.h
@@ -0,0 +1,37 @@
+/* packet-dcerpc-initshutdown.h
+ * Routines for SMB \PIPE\initshutdown packet disassembly
+ * Based on packet-dcerpc-winreg.h
+ * Copyright 2001-2003 Tim Potter <tpot@samba.org>
+ * as per a suggestion by Jim McDonough
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_INITSHUTDOWN_H
+#define __PACKET_DCERPC_INITSHUTDOWN_H
+
+/* Functions available on the INITSHUTDOWN pipe. */
+
+#define INITSHUTDOWN_INITIATE_SYSTEM_SHUTDOWN 0x00
+#define INITSHUTDOWN_ABORT_SYSTEM_SHUTDOWN 0x01
+#define INITSHUTDOWN_INITIATE_SYSTEM_SHUTDOWN_EX 0x02
+
+#endif /* packet-dcerpc-initshutdown.h */
diff --git a/epan/dissectors/packet-dcerpc-krb5rpc.c b/epan/dissectors/packet-dcerpc-krb5rpc.c
new file mode 100644
index 0000000000..b062e52db9
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-krb5rpc.c
@@ -0,0 +1,211 @@
+/* packet-dcerpc-krb5rpc.c
+ *
+ * Routines for dcerpc DCE/KRB5 interface
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/krb5rpc.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-kerberos.h"
+#include "packet-dcerpc-dce122.h"
+
+static int proto_krb5rpc = -1;
+
+static gint ett_krb5rpc = -1;
+
+
+static e_uuid_t uuid_krb5rpc =
+ { 0x8f73de50, 0x768c, 0x11ca, {0xbf, 0xfc, 0x08, 0x00, 0x1e, 0x03, 0x94,
+ 0x31}
+};
+static guint16 ver_krb5rpc = 1;
+static int hf_krb5rpc_opnum = -1;
+static int hf_krb5rpc_sendto_kdc_rqst_keysize = -1;
+static int hf_krb5rpc_sendto_kdc_rqst_spare1 = -1;
+static int hf_krb5rpc_sendto_kdc_resp_len = -1;
+static int hf_krb5rpc_sendto_kdc_resp_max = -1;
+static int hf_krb5rpc_sendto_kdc_resp_spare1 = -1;
+static int hf_krb5rpc_sendto_kdc_resp_keysize = -1;
+static int hf_krb5rpc_sendto_kdc_resp_st = -1;
+static int hf_krb5rpc_krb5 = -1;
+static gint ett_krb5rpc_krb5 = -1;
+
+static int
+krb5rpc_dissect_sendto_kdc_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ guint32 keysize, spare1, remain;
+ proto_item *item;
+ tvbuff_t *krb5_tvb;
+ proto_tree *subtree;
+
+
+ /*
+ * [in] handle_t h,
+ * [in] unsigned32 len,
+ * [in, size_is(len)]
+ * byte message[],
+ * [in] unsigned32 out_buf_len,
+ */
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_krb5rpc_sendto_kdc_rqst_keysize, &keysize);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_krb5rpc_sendto_kdc_rqst_spare1, &spare1);
+ item = proto_tree_add_item (tree, hf_krb5rpc_krb5, tvb, offset, -1, TRUE);
+ subtree = proto_item_add_subtree (item, ett_krb5rpc_krb5);
+
+ remain = tvb_length_remaining(tvb, offset);
+ krb5_tvb = tvb_new_subset (tvb, offset, remain, remain);
+ offset = dissect_kerberos_main (krb5_tvb, pinfo, subtree, TRUE, NULL);
+
+
+ return offset;
+}
+
+
+static int
+krb5rpc_dissect_sendto_kdc_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 *drep)
+{
+ guint32 resp_len, maxsize, spare1, keysize, remain;
+ proto_item *item;
+ tvbuff_t *krb5_tvb;
+ proto_tree *subtree;
+
+
+ /*
+ *
+ * [out] unsigned32 *resp_len,
+ * [out, length_is(*resp_len), size_is(out_buf_len)]
+ * byte out_buf[],
+ * [out] error_status_t *st unsigned long
+ *
+ */
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_krb5rpc_sendto_kdc_resp_len, &resp_len);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_krb5rpc_sendto_kdc_resp_max, &maxsize);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_krb5rpc_sendto_kdc_resp_spare1, &spare1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_krb5rpc_sendto_kdc_resp_keysize, &keysize);
+
+
+ item = proto_tree_add_item (tree, hf_krb5rpc_krb5, tvb, offset, -1, TRUE);
+ subtree = proto_item_add_subtree (item, ett_krb5rpc_krb5);
+ remain = tvb_length_remaining(tvb, offset);
+ krb5_tvb = tvb_new_subset (tvb, offset, remain, remain);
+
+ offset = dissect_kerberos_main (krb5_tvb, pinfo, subtree, TRUE, NULL);
+ offset += 16; /* no idea what this is, probably just extended encrypted text. */
+
+ return offset;
+}
+
+
+static dcerpc_sub_dissector krb5rpc_dissectors[] = {
+ {0, "rsec_krb5rpc_sendto_kdc", krb5rpc_dissect_sendto_kdc_rqst,
+ krb5rpc_dissect_sendto_kdc_resp},
+ {0, NULL, NULL, NULL},
+};
+
+
+void
+proto_register_krb5rpc (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_krb5rpc_opnum,
+ {"hf_krb5rpc_opnum", "hf_krb5rpc_opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&hf_krb5rpc_sendto_kdc_rqst_keysize,
+ {"hf_krb5rpc_sendto_kdc_rqst_keysize",
+ "hf_krb5rpc_sendto_kdc_rqst_keysize", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_krb5rpc_sendto_kdc_rqst_spare1,
+ {"hf_krb5rpc_sendto_kdc_rqst_spare1",
+ "hf_krb5rpc_sendto_kdc_rqst_spare1", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_krb5rpc_sendto_kdc_resp_len,
+ {"hf_krb5rpc_sendto_kdc_resp_len", "hf_krb5rpc_sendto_kdc_resp_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_krb5rpc_sendto_kdc_resp_max,
+ {"hf_krb5rpc_sendto_kdc_resp_max", "hf_krb5rpc_sendto_kdc_resp_max",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_krb5rpc_sendto_kdc_resp_spare1,
+ {"hf_krb5rpc_sendto_kdc_resp_spare1",
+ "hf_krb5rpc_sendto_kdc_resp_spare1", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_krb5rpc_sendto_kdc_resp_keysize,
+ {"hf_krb5rpc_sendto_kdc_resp_keysize",
+ "hf_krb5rpc_sendto_kdc_resp_keysize", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_krb5rpc_sendto_kdc_resp_st,
+ {"hf_krb5rpc_sendto_kdc_resp_st", "hf_krb5rpc_sendto_kdc_resp_st",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_krb5rpc_krb5,
+ {"hf_krb5rpc_krb5", "hf_krb5rpc_krb5", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "krb5_blob", HFILL}},
+
+ };
+
+ static gint *ett[] = {
+ &ett_krb5rpc,
+ &ett_krb5rpc_krb5,
+ };
+ proto_krb5rpc =
+ proto_register_protocol ("DCE/RPC Kerberos V", "KRB5RPC", "krb5rpc");
+ proto_register_field_array (proto_krb5rpc, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_krb5rpc (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_krb5rpc, ett_krb5rpc, &uuid_krb5rpc, ver_krb5rpc,
+ krb5rpc_dissectors, hf_krb5rpc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-llb.c b/epan/dissectors/packet-dcerpc-llb.c
new file mode 100644
index 0000000000..efbd3e90b4
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-llb.c
@@ -0,0 +1,90 @@
+/* packet-dcerpc-llb.c
+ *
+ * Routines for llb dissection
+ * Copyright 2004, Jaime Fournier <jaime.fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/admin.tar.gz ./admin/dced/idl/llb.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dce122.h"
+
+
+static int proto_llb = -1;
+static int hf_llb_opnum = -1;
+
+static gint ett_llb = -1;
+
+
+static e_uuid_t uuid_llb =
+ { 0x333b33c3, 0x0000, 0x0000, {0x0d, 0x00, 0x00, 0x87, 0x84, 0x00, 0x00,
+ 0x00} };
+static guint16 ver_llb = 4;
+
+
+static dcerpc_sub_dissector llb_dissectors[] = {
+ {0, "insert", NULL, NULL},
+ {1, "delete", NULL, NULL},
+ {2, "lookup", NULL, NULL},
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_llb (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_llb_opnum,
+ {"Operation", "llb.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation",
+ HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_llb,
+ };
+ proto_llb =
+ proto_register_protocol ("DCE/RPC NCS 1.5.1 Local Location Broker", "llb",
+ "llb");
+ proto_register_field_array (proto_llb, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_llb (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_llb, ett_llb, &uuid_llb, ver_llb, llb_dissectors,
+ hf_llb_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-lsa-ds.c b/epan/dissectors/packet-dcerpc-lsa-ds.c
new file mode 100644
index 0000000000..8f48809115
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-lsa-ds.c
@@ -0,0 +1,378 @@
+/* packet-dcerpc-lsa-ds.c
+ * Routines for SMB \PIPE\lsarpc packet disassembly
+ * Copyright 2002-2003, Tim Potter <tpot@samba.org>
+ * Copyright 2002, Jim McDonough <jmcd@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "smb.h"
+
+#define LSA_DS_DSROLERGETDOMINFO 0x0000
+#define LSA_DS_DSROLER_DNS_NAME_TO_FLAT_NAME 0x0001
+#define LSA_DS_DSROLER_DC_AS_DC 0x0002
+#define LSA_DS_DSROLER_DC_AS_REPLICA 0x0003
+#define LSA_DS_DSROLER_DEMOTE_DC 0x0004
+#define LSA_DS_DSROLER_GET_DC_OPERATION_PROGRESS 0x0005
+#define LSA_DS_DSROLER_GET_DC_OPERATION_RESULTS 0x0006
+#define LSA_DS_DSROLER_CANCEL 0x0007
+#define LSA_DS_DSROLER_SERVER_SAVE_STATE_FOR_UPGRADE 0x0008
+#define LSA_DS_DSROLER_UPGRADE_DOWNLEVEL_SERVER 0x0009
+#define LSA_DS_DSROLER_ABORT_DOWNLEVEL_SERVER_UPGRADE 0x000a
+
+#define LSA_DS_DSROLE_BASIC_INFO 0x0001
+#define LSA_DS_DSROLE_UPGRADE_STATUS 0x0002
+#define LSA_DS_DSROLE_OP_STATUS 0x0003
+
+static int proto_dcerpc_lsa_ds = -1;
+
+static int hf_lsa_ds_opnum = -1;
+static int hf_lsa_ds_dominfo_level = -1;
+static int hf_lsa_ds_machine_role = -1;
+static int hf_lsa_ds_dominfo_flags = -1;
+static int hf_lsa_ds_dominfo_netb_name = -1;
+static int hf_lsa_ds_dominfo_dns_name = -1;
+static int hf_lsa_ds_dominfo_forest_name = -1;
+static int hf_lsa_ds_upgrade_state = -1;
+static int hf_lsa_ds_previous_role = -1;
+static int hf_lsa_ds_op_status = -1;
+static int hf_lsa_ds_rc = -1;
+
+static gint ett_dcerpc_lsa_ds = -1;
+static gint ett_lsa_ds_domain_info = -1;
+static gint ett_lsa_ds_basic_domain_info = -1;
+static gint ett_lsa_ds_upgrade_status = -1;
+static gint ett_lsa_ds_op_status = -1;
+
+static int
+lsa_ds_dissect_DSROLE_BASIC_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DSROLE_BASIC_DOMAIN_INFO:");
+ tree = proto_item_add_subtree(item,
+ ett_lsa_ds_basic_domain_info);
+ }
+
+ ALIGN_TO_4_BYTES;
+ /* role */
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_ds_machine_role, 0);
+
+ /* flags */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_ds_dominfo_flags, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "NetBIOS domain name pointer",
+ hf_lsa_ds_dominfo_netb_name, 0);
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "DNS domain pointer",
+ hf_lsa_ds_dominfo_dns_name, 0);
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "DNS forest name pointer",
+ hf_lsa_ds_dominfo_forest_name, 0);
+
+ /* GUID */
+ offset = dissect_nt_GUID(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_ds_dissect_DSROLE_UPGRADE_STATUS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DSROLE_UPGRADE_STATUS:");
+ tree = proto_item_add_subtree(item,
+ ett_lsa_ds_upgrade_status);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_ds_upgrade_state, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_ds_previous_role, NULL);
+ proto_item_set_len(item, offset-old_offset);
+
+ return offset;
+}
+
+static int
+lsa_ds_dissect_DSROLE_OP_STATUS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DSROLE_OP_STATUS:");
+ tree = proto_item_add_subtree(item,
+ ett_lsa_ds_op_status);
+ }
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_ds_op_status, NULL);
+ proto_item_set_len(item, offset-old_offset);
+
+ return offset;
+}
+
+static int
+lsa_ds_dissect_DS_DOMINFO_CTR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DOMAIN_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_ds_domain_info);
+ }
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_ds_dominfo_level, &level);
+
+ switch(level){
+ case LSA_DS_DSROLE_BASIC_INFO:
+ offset = lsa_ds_dissect_DSROLE_BASIC_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case LSA_DS_DSROLE_UPGRADE_STATUS:
+ offset = lsa_ds_dissect_DSROLE_UPGRADE_STATUS(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case LSA_DS_DSROLE_OP_STATUS:
+ offset = lsa_ds_dissect_DSROLE_OP_STATUS(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ }
+ proto_item_set_len(item, offset-old_offset);
+
+ return offset;
+}
+
+static int
+lsa_ds_dissect_role_get_dom_info_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_ds_dominfo_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ return offset;
+}
+
+static int
+lsa_ds_dissect_role_get_dom_info_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_ds_dissect_DS_DOMINFO_CTR, NDR_POINTER_UNIQUE,
+ "DOMAIN_INFORMATION pointer", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_ds_rc, NULL);
+
+ return offset;
+}
+
+static const value_string lsa_ds_dominfo_levels[] = {
+ { LSA_DS_DSROLE_BASIC_INFO, "DsRoleBasicInfo"},
+ { LSA_DS_DSROLE_UPGRADE_STATUS, "DsRoleUpgradeStatus"},
+ { LSA_DS_DSROLE_OP_STATUS, "DsRoleOpStatus"},
+ { 0, NULL }
+};
+
+static const value_string lsa_ds_role_vals[] = {
+ { 0, "Standalone Workstation" },
+ { 1, "Domain Member Workstation" },
+ { 2, "Standalone Server" },
+ { 3, "Domain Member Server" },
+ { 4, "Backup Domain Controller" },
+ { 5, "Primary Domain Controller" },
+ { 0, NULL }
+};
+
+static const value_string lsa_ds_upgrade_vals[] = {
+ { 0, "Not currently upgrading"},
+ { 1, "Upgrade in progress"},
+ { 0, NULL }
+};
+
+static const value_string lsa_ds_previous_roles[] = {
+ { 0, "Unknown state" },
+ { 1, "Primary" },
+ { 2, "Backup" },
+ { 0, NULL }
+};
+
+static const value_string lsa_ds_op_states[] = {
+ { 0, "Idle" },
+ { 1, "Active" },
+ { 2, "Needs reboot" },
+ { 0, NULL }
+};
+
+void
+proto_register_dcerpc_lsa_ds(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_lsa_ds_opnum,
+ { "Operation", "ls_ads.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ { &hf_lsa_ds_dominfo_level,
+ { "Level", "lsa_ds.dominfo.level", FT_UINT16, BASE_DEC,
+ VALS(lsa_ds_dominfo_levels), 0x0,
+ "Information level of requested data", HFILL }},
+
+ { &hf_lsa_ds_machine_role,
+ { "Machine role", "lsa_ds.role", FT_UINT16, BASE_HEX,
+ VALS(lsa_ds_role_vals), 0x0, "Role of machine in domain", HFILL}},
+
+ { &hf_lsa_ds_dominfo_flags,
+ { "Flags", "lsa_ds.dominfo.flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Machine flags", HFILL }},
+
+ { &hf_lsa_ds_dominfo_netb_name,
+ { "Netbios name", "lsa_ds.dominfo.nbname", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Netbios Domain Name", HFILL}},
+
+ { &hf_lsa_ds_dominfo_dns_name,
+ { "DNS name", "lsa_ds.dominfo.dnsname", FT_STRING, BASE_NONE,
+ NULL, 0x0, "DNS Domain Name", HFILL}},
+
+ { &hf_lsa_ds_dominfo_forest_name,
+ { "Forest name", "lsa_ds.dominfo.forest", FT_STRING, BASE_NONE,
+ NULL, 0x0, "DNS Forest Name", HFILL}},
+
+ { &hf_lsa_ds_upgrade_state,
+ { "Upgrading", "ls_ads.upgrading", FT_UINT32, BASE_DEC,
+ VALS(lsa_ds_upgrade_vals), 0x0, "Upgrade State", HFILL }},
+
+ { &hf_lsa_ds_previous_role,
+ { "Previous role", "ls_ads.upgrading", FT_UINT16, BASE_DEC,
+ VALS(lsa_ds_previous_roles), 0x0,
+ "Previous server role before upgrade", HFILL }},
+
+ { &hf_lsa_ds_op_status,
+ { "Operational status", "ls_ads.op_status", FT_UINT16, BASE_DEC,
+ VALS(lsa_ds_op_states), 0x0,
+ "Current operational status", HFILL }},
+
+ { &hf_lsa_ds_rc,
+ { "Return code", "lsa_ds.rc", FT_UINT32, BASE_HEX,
+ VALS (NT_errors), 0x0, "LSA_DS return status code", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_lsa_ds,
+ &ett_lsa_ds_domain_info,
+ &ett_lsa_ds_basic_domain_info,
+ &ett_lsa_ds_upgrade_status,
+ &ett_lsa_ds_op_status
+ };
+
+ proto_dcerpc_lsa_ds = proto_register_protocol(
+ "Microsoft Local Security Architecture (Directory Services)",
+ "LSA_DS", "lsa_ds");
+ proto_register_field_array(proto_dcerpc_lsa_ds, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+/* Protocol handoff */
+
+static e_uuid_t uuid_dcerpc_lsa_ds = {
+ 0x3919286a, 0xb10c, 0x11d0,
+ { 0x9b, 0xa8, 0x00, 0xc0, 0x4f, 0xd9, 0x2e, 0xf5}
+};
+
+static guint16 ver_dcerpc_lsa_ds = 0;
+
+static dcerpc_sub_dissector lsa_ds_dissectors[] = {
+ { LSA_DS_DSROLERGETDOMINFO, "DsRolerGetDomInfo",
+ lsa_ds_dissect_role_get_dom_info_rqst,
+ lsa_ds_dissect_role_get_dom_info_reply },
+ { LSA_DS_DSROLER_DNS_NAME_TO_FLAT_NAME,
+ "DsRolerDnsNameToFlatName", NULL, NULL },
+ { LSA_DS_DSROLER_DC_AS_DC,
+ "DsRolerDcAsDc", NULL, NULL },
+ { LSA_DS_DSROLER_DC_AS_REPLICA,
+ "DsRolerDcAsReplica", NULL, NULL },
+ { LSA_DS_DSROLER_DEMOTE_DC,
+ "DsRolerDemoteDc", NULL, NULL },
+ { LSA_DS_DSROLER_GET_DC_OPERATION_PROGRESS,
+ "DsRolerGetDcOperationProgress", NULL, NULL },
+ { LSA_DS_DSROLER_GET_DC_OPERATION_RESULTS,
+ "DsRolerGetDcOperationResults", NULL, NULL },
+ { LSA_DS_DSROLER_CANCEL,
+ "DsRolerCancel", NULL, NULL },
+ { LSA_DS_DSROLER_SERVER_SAVE_STATE_FOR_UPGRADE,
+ "DsRolerServerSaveStateForUpgrade", NULL, NULL },
+ { LSA_DS_DSROLER_UPGRADE_DOWNLEVEL_SERVER,
+ "DsRolerUpgradeDownlevelServer", NULL, NULL },
+ { LSA_DS_DSROLER_ABORT_DOWNLEVEL_SERVER_UPGRADE,
+ "DsRolerAbortDownlevelServerUpgrade", NULL, NULL },
+ { 0, NULL, NULL, NULL },
+};
+
+void
+proto_reg_handoff_dcerpc_lsa_ds(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_lsa_ds, ett_dcerpc_lsa_ds,
+ &uuid_dcerpc_lsa_ds, ver_dcerpc_lsa_ds,
+ lsa_ds_dissectors, hf_lsa_ds_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-lsa.c b/epan/dissectors/packet-dcerpc-lsa.c
new file mode 100644
index 0000000000..d276869292
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-lsa.c
@@ -0,0 +1,4541 @@
+/* packet-dcerpc-lsa.c
+ * Routines for SMB \PIPE\lsarpc packet disassembly
+ * Copyright 2001,2003 Tim Potter <tpot@samba.org>
+ * 2002 Added LSA command dissectors Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-lsa.h"
+#include "packet-smb-common.h"
+#include "smb.h"
+
+static int proto_dcerpc_lsa = -1;
+
+static int hf_lsa_opnum = -1;
+static int hf_lsa_rc = -1;
+static int hf_lsa_hnd = -1;
+static int hf_lsa_policy_information = -1;
+static int hf_lsa_server = -1;
+static int hf_lsa_controller = -1;
+static int hf_lsa_obj_attr = -1;
+static int hf_lsa_obj_attr_len = -1;
+static int hf_lsa_obj_attr_name = -1;
+static int hf_lsa_access_mask = -1;
+static int hf_lsa_info_level = -1;
+static int hf_lsa_trusted_info_level = -1;
+static int hf_lsa_sd_size = -1;
+static int hf_lsa_qos_len = -1;
+static int hf_lsa_qos_impersonation_level = -1;
+static int hf_lsa_qos_track_context = -1;
+static int hf_lsa_qos_effective_only = -1;
+static int hf_lsa_pali_percent_full = -1;
+static int hf_lsa_pali_log_size = -1;
+static int hf_lsa_pali_retention_period = -1;
+static int hf_lsa_pali_time_to_shutdown = -1;
+static int hf_lsa_pali_shutdown_in_progress = -1;
+static int hf_lsa_pali_next_audit_record = -1;
+static int hf_lsa_paei_enabled = -1;
+static int hf_lsa_paei_settings = -1;
+static int hf_lsa_count = -1;
+static int hf_lsa_size = -1;
+static int hf_lsa_size16 = -1;
+static int hf_lsa_privilege_display_name_size = -1;
+static int hf_lsa_max_count = -1;
+static int hf_lsa_index = -1;
+static int hf_lsa_fqdomain = -1;
+static int hf_lsa_domain = -1;
+static int hf_lsa_acct = -1;
+static int hf_lsa_server_role = -1;
+static int hf_lsa_source = -1;
+static int hf_lsa_quota_paged_pool = -1;
+static int hf_lsa_quota_non_paged_pool = -1;
+static int hf_lsa_quota_min_wss = -1;
+static int hf_lsa_quota_max_wss = -1;
+static int hf_lsa_quota_pagefile = -1;
+static int hf_lsa_mod_seq_no = -1;
+static int hf_lsa_mod_mtime = -1;
+static int hf_lsa_cur_mtime = -1;
+static int hf_lsa_old_mtime = -1;
+static int hf_lsa_name = -1;
+static int hf_lsa_key = -1;
+static int hf_lsa_flat_name = -1;
+static int hf_lsa_forest = -1;
+static int hf_lsa_info_type = -1;
+static int hf_lsa_old_pwd = -1;
+static int hf_lsa_new_pwd = -1;
+static int hf_lsa_sid_type = -1;
+static int hf_lsa_rid = -1;
+static int hf_lsa_rid_offset = -1;
+static int hf_lsa_num_mapped = -1;
+static int hf_lsa_policy_information_class = -1;
+static int hf_lsa_secret = -1;
+static int hf_nt_luid_high = -1;
+static int hf_nt_luid_low = -1;
+static int hf_lsa_privilege_name = -1;
+static int hf_lsa_privilege_display_name = -1;
+static int hf_lsa_attr = -1;
+static int hf_lsa_resume_handle = -1;
+static int hf_lsa_trust_direction = -1;
+static int hf_lsa_trust_type = -1;
+static int hf_lsa_trust_attr = -1;
+static int hf_lsa_trust_attr_non_trans = -1;
+static int hf_lsa_trust_attr_uplevel_only = -1;
+static int hf_lsa_trust_attr_tree_parent = -1;
+static int hf_lsa_trust_attr_tree_root = -1;
+static int hf_lsa_auth_update = -1;
+static int hf_lsa_auth_type = -1;
+static int hf_lsa_auth_len = -1;
+static int hf_lsa_auth_blob = -1;
+static int hf_lsa_rights = -1;
+static int hf_lsa_remove_all = -1;
+
+static int hf_lsa_unknown_hyper = -1;
+static int hf_lsa_unknown_long = -1;
+static int hf_lsa_unknown_short = -1;
+static int hf_lsa_unknown_char = -1;
+static int hf_lsa_unknown_string = -1;
+#ifdef LSA_UNUSED_HANDLES
+static int hf_lsa_unknown_time = -1;
+#endif
+
+
+static gint ett_dcerpc_lsa = -1;
+static gint ett_lsa_OBJECT_ATTRIBUTES = -1;
+static gint ett_LSA_SECURITY_DESCRIPTOR = -1;
+static gint ett_lsa_policy_info = -1;
+static gint ett_lsa_policy_audit_log_info = -1;
+static gint ett_lsa_policy_audit_events_info = -1;
+static gint ett_lsa_policy_primary_domain_info = -1;
+static gint ett_lsa_policy_primary_account_info = -1;
+static gint ett_lsa_policy_server_role_info = -1;
+static gint ett_lsa_policy_replica_source_info = -1;
+static gint ett_lsa_policy_default_quota_info = -1;
+static gint ett_lsa_policy_modification_info = -1;
+static gint ett_lsa_policy_audit_full_set_info = -1;
+static gint ett_lsa_policy_audit_full_query_info = -1;
+static gint ett_lsa_policy_dns_domain_info = -1;
+static gint ett_lsa_translated_names = -1;
+static gint ett_lsa_translated_name = -1;
+static gint ett_lsa_referenced_domain_list = -1;
+static gint ett_lsa_trust_information = -1;
+static gint ett_lsa_trust_information_ex = -1;
+static gint ett_LUID = -1;
+static gint ett_LSA_PRIVILEGES = -1;
+static gint ett_LSA_PRIVILEGE = -1;
+static gint ett_LSA_LUID_AND_ATTRIBUTES_ARRAY = -1;
+static gint ett_LSA_LUID_AND_ATTRIBUTES = -1;
+static gint ett_LSA_TRUSTED_DOMAIN_LIST = -1;
+static gint ett_LSA_TRUSTED_DOMAIN = -1;
+static gint ett_LSA_TRANSLATED_SIDS = -1;
+static gint ett_lsa_trusted_domain_info = -1;
+static gint ett_lsa_trust_attr = -1;
+static gint ett_lsa_trusted_domain_auth_information = -1;
+static gint ett_lsa_auth_information = -1;
+
+
+static int
+lsa_dissect_pointer_NTTIME(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ di->hf_index);
+
+ return offset;
+}
+
+static int
+lsa_dissect_pointer_UNICODE_STRING(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ di->hf_index, 0);
+ return offset;
+}
+
+static int
+lsa_dissect_pointer_pointer_UNICODE_STRING(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+ "DOMAIN pointer: ", di->hf_index);
+
+ return offset;
+}
+
+static int
+lsa_dissect_pointer_STRING(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ di->hf_index, 0);
+ return offset;
+}
+
+
+static int
+lsa_dissect_LSA_SECRET_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ /* this is probably a varying and conformant array */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_sd_size, &len);
+ offset+=4;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_sd_size, &len);
+ proto_tree_add_item(tree, hf_lsa_secret, tvb, offset, len, FALSE);
+ offset += len;
+
+ return offset;
+}
+
+int
+lsa_dissect_LSA_SECRET(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "LSA_SECRET:");
+ tree = proto_item_add_subtree(item, ett_LSA_SECURITY_DESCRIPTOR);
+ }
+
+ /* XXX need to figure this one out */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_sd_size, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_sd_size, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET_data, NDR_POINTER_UNIQUE,
+ "LSA_SECRET data: pointer", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_SECRET_pointer(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET, NDR_POINTER_UNIQUE,
+ "LSA_SECRET pointer: data", -1);
+
+ return offset;
+}
+
+/* Dissect LSA specific access rights */
+
+static gint hf_view_local_info = -1;
+static gint hf_view_audit_info = -1;
+static gint hf_get_private_info = -1;
+static gint hf_trust_admin = -1;
+static gint hf_create_account = -1;
+static gint hf_create_secret = -1;
+static gint hf_create_priv = -1;
+static gint hf_set_default_quota_limits = -1;
+static gint hf_set_audit_requirements = -1;
+static gint hf_audit_log_admin = -1;
+static gint hf_server_admin = -1;
+static gint hf_lookup_names = -1;
+
+static void
+lsa_specific_rights(tvbuff_t *tvb, gint offset, proto_tree *tree,
+ guint32 access)
+{
+ proto_tree_add_boolean(
+ tree, hf_lookup_names, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_server_admin, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_audit_log_admin, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_set_audit_requirements, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_set_default_quota_limits, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_create_priv, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_create_secret, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_create_account, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_trust_admin, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_get_private_info, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_view_audit_info, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_view_local_info, tvb, offset, 4, access);
+}
+
+struct access_mask_info lsa_access_mask_info = {
+ "LSA", /* Name of specific rights */
+ lsa_specific_rights, /* Dissection function */
+ NULL, /* Generic mapping table */
+ NULL /* Standard mapping table */
+};
+
+int
+lsa_dissect_LSA_SECURITY_DESCRIPTOR_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_sd_size, &len);
+
+ dissect_nt_sec_desc(
+ tvb, offset, pinfo, tree, drep, len, &lsa_access_mask_info);
+
+ offset += len;
+
+ return offset;
+}
+int
+lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "LSA_SECURITY_DESCRIPTOR:");
+ tree = proto_item_add_subtree(item, ett_LSA_SECURITY_DESCRIPTOR);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_sd_size, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR_data, NDR_POINTER_UNIQUE,
+ "LSA SECURITY DESCRIPTOR data:", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_LPSTR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_char, NULL);
+
+ return offset;
+}
+
+static const value_string lsa_impersonation_level_vals[] = {
+ {0, "Anonymous"},
+ {1, "Identification"},
+ {2, "Impersonation"},
+ {3, "Delegation"},
+ {0, NULL}
+};
+
+
+static int
+lsa_dissect_SECURITY_QUALITY_OF_SERVICE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* Length */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_qos_len, NULL);
+
+ /* impersonation level */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_qos_impersonation_level, NULL);
+
+ /* context tracking mode */
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_qos_track_context, NULL);
+
+ /* effective only */
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_qos_effective_only, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_ACCESS_MASK(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_lsa_access_mask,
+ &lsa_access_mask_info, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_OBJECT_ATTRIBUTES(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ int old_offset=offset;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1, "Object Attributes");
+ tree = proto_item_add_subtree(item, ett_lsa_OBJECT_ATTRIBUTES);
+ }
+
+ /* Length */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_obj_attr_len, NULL);
+
+ /* LPSTR */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LPSTR, NDR_POINTER_UNIQUE,
+ "LSPTR pointer: ", -1);
+
+ /* attribute name */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_STRING, NDR_POINTER_UNIQUE,
+ "NAME pointer: ", hf_lsa_obj_attr_name);
+
+ /* Attr */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_obj_attr, NULL);
+
+ /* security descriptor */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR, NDR_POINTER_UNIQUE,
+ "LSA_SECURITY_DESCRIPTOR pointer: ", -1);
+
+ /* security quality of service */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_SECURITY_QUALITY_OF_SERVICE, NDR_POINTER_UNIQUE,
+ "LSA_SECURITY_QUALITY_OF_SERVICE pointer: ", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_lsarclose_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, TRUE);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarclose_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+/* A bug in the NT IDL for lsa openpolicy only stores the first (wide)
+ character of the server name which is always '\'. This is fixed in lsa
+ openpolicy2 but the function remains for backwards compatibility. */
+
+static int dissect_lsa_openpolicy_server(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ return dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_server, NULL);
+}
+
+static int
+lsa_dissect_lsaropenpolicy_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_lsa_openpolicy_server, NDR_POINTER_UNIQUE,
+ "Server", hf_lsa_server);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_OBJECT_ATTRIBUTES, NDR_POINTER_REF,
+ "OBJECT_ATTRIBUTES", -1);
+
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsaropenpolicy_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, &status);
+
+ if (status == 0) {
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
+ "OpenPolicy handle");
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": OpenPolicy handle");
+ }
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsaropenpolicy2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer_cb(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE, "Server",
+ hf_lsa_server, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_OBJECT_ATTRIBUTES, NDR_POINTER_REF,
+ "OBJECT_ATTRIBUTES", -1);
+
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsaropenpolicy2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+ char *pol_name;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, &status);
+
+ if (status == 0) {
+ if (dcv->private_data)
+ pol_name = g_strdup_printf(
+ "OpenPolicy2(%s)", (char *)dcv->private_data);
+ else
+ pol_name = g_strdup("OpenPolicy2 handle");
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": %s", pol_name);
+
+ g_free(pol_name);
+ }
+
+ return offset;
+}
+
+static const value_string policy_information_class_vals[] = {
+ {1, "Audit Log Information"},
+ {2, "Audit Events Information"},
+ {3, "Primary Domain Information"},
+ {4, "Pd Account Information"},
+ {5, "Account Domain Information"},
+ {6, "Server Role Information"},
+ {7, "Replica Source Information"},
+ {8, "Default Quota Information"},
+ {9, "Modification Information"},
+ {10, "Audit Full Set Information"},
+ {11, "Audit Full Query Information"},
+ {12, "DNS Domain Information"},
+ {0, NULL}
+};
+
+static int
+lsa_dissect_lsarqueryinformationpolicy_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_policy_information_class, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(level, policy_information_class_vals,
+ "Unknown (%d)"));
+
+ return offset;
+}
+
+static int
+lsa_dissect_POLICY_AUDIT_LOG_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_AUDIT_LOG_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_audit_log_info);
+ }
+
+ /* percent full */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_pali_percent_full, NULL);
+
+ /* log size */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_pali_log_size, NULL);
+
+ /* retention period */
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_lsa_pali_retention_period);
+
+ /* shutdown in progress */
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_pali_shutdown_in_progress, NULL);
+
+ /* time to shutdown */
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_lsa_pali_time_to_shutdown);
+
+ /* next audit record */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_pali_next_audit_record, NULL);
+
+ /* unknown */
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_POLICY_AUDIT_EVENTS_INFO_settings(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_paei_settings, NULL);
+ return offset;
+}
+
+static int
+lsa_dissect_POLICY_AUDIT_EVENTS_INFO_settings_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_AUDIT_EVENTS_INFO_settings);
+
+ return offset;
+}
+
+static int
+lsa_dissect_POLICY_AUDIT_EVENTS_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_AUDIT_EVENTS_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_audit_events_info);
+ }
+
+ /* enabled */
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_paei_enabled, NULL);
+
+ /* settings */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_AUDIT_EVENTS_INFO_settings_array, NDR_POINTER_UNIQUE,
+ "Settings", -1);
+
+ /* count */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+lsa_dissect_POLICY_PRIMARY_DOMAIN_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_PRIMARY_DOMAIN_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_primary_domain_info);
+ }
+
+ /* domain */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_domain, 0);
+
+ /* sid */
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+lsa_dissect_POLICY_ACCOUNT_DOMAIN_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_ACCOUNT_DOMAIN_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_primary_account_info);
+ }
+
+ /* account */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_domain, 0);
+
+ /* sid */
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static const value_string server_role_vals[] = {
+ {0, "Standalone"},
+ {1, "Domain Member"},
+ {2, "Backup"},
+ {3, "Primary"},
+ {0, NULL}
+};
+static int
+lsa_dissect_POLICY_SERVER_ROLE_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_SERVER_ROLE_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_server_role_info);
+ }
+
+ /* server role */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_server_role, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_POLICY_REPLICA_SOURCE_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_REPLICA_SOURCE_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_replica_source_info);
+ }
+
+ /* source */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_source, 0);
+
+ /* account */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_acct, 0);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+lsa_dissect_POLICY_DEFAULT_QUOTA_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_DEFAULT_QUOTA_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_default_quota_info);
+ }
+
+ /* paged pool */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_quota_paged_pool, NULL);
+
+ /* non paged pool */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_quota_non_paged_pool, NULL);
+
+ /* min wss */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_quota_min_wss, NULL);
+
+ /* max wss */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_quota_max_wss, NULL);
+
+ /* pagefile */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_quota_pagefile, NULL);
+
+ /* */
+ offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_hyper, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+lsa_dissect_POLICY_MODIFICATION_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_MODIFICATION_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_modification_info);
+ }
+
+ /* seq no */
+ offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_mod_seq_no, NULL);
+
+ /* mtime */
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_lsa_mod_mtime);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+lsa_dissect_POLICY_AUDIT_FULL_SET_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_AUDIT_FULL_SET_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_audit_full_set_info);
+ }
+
+ /* unknown */
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_char, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+lsa_dissect_POLICY_AUDIT_FULL_QUERY_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_AUDIT_FULL_QUERY_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_audit_full_query_info);
+ }
+
+ /* unknown */
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_char, NULL);
+
+ /* unknown */
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_char, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+int
+lsa_dissect_POLICY_DNS_DOMAIN_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "POLICY_DNS_DOMAIN_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_policy_dns_domain_info);
+ }
+
+ /* name */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_domain, 0);
+
+ /* domain */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_fqdomain, 0);
+
+ /* forest */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_forest, 0);
+
+ /* GUID */
+ offset = dissect_nt_GUID(tvb, offset,
+ pinfo, tree, drep);
+
+ /* SID pointer */
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_POLICY_INFORMATION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_item(parent_tree, hf_lsa_policy_information, tvb, offset, 0, FALSE);
+
+ tree = proto_item_add_subtree(item, ett_lsa_policy_info);
+ }
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_info_level, &level);
+
+ ALIGN_TO_4_BYTES; /* all union arms aligned to 4 bytes, case 7 and 9 need this */
+ switch(level){
+ case 1:
+ offset = lsa_dissect_POLICY_AUDIT_LOG_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 2:
+ offset = lsa_dissect_POLICY_AUDIT_EVENTS_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 3:
+ offset = lsa_dissect_POLICY_PRIMARY_DOMAIN_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 4:
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_lsa_acct, 0);
+ break;
+ case 5:
+ offset = lsa_dissect_POLICY_ACCOUNT_DOMAIN_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 6:
+ offset = lsa_dissect_POLICY_SERVER_ROLE_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 7:
+ offset = lsa_dissect_POLICY_REPLICA_SOURCE_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 8:
+ offset = lsa_dissect_POLICY_DEFAULT_QUOTA_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 9:
+ offset = lsa_dissect_POLICY_MODIFICATION_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 10:
+ offset = lsa_dissect_POLICY_AUDIT_FULL_SET_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 11:
+ offset = lsa_dissect_POLICY_AUDIT_FULL_QUERY_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 12:
+ offset = lsa_dissect_POLICY_DNS_DOMAIN_INFO(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_lsarqueryinformationpolicy_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* This is really a pointer to a pointer though the first level is REF
+ so we just ignore that one */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_INFORMATION, NDR_POINTER_UNIQUE,
+ "POLICY_INFORMATION pointer: info", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsardelete_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsardelete_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarquerysecurityobject_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_info_type, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarquerysecurityobject_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR, NDR_POINTER_UNIQUE,
+ "LSA_SECURITY_DESCRIPTOR pointer: sec_info", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsetsecurityobject_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_info_type, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR, NDR_POINTER_REF,
+ "LSA_SECURITY_DESCRIPTOR: sec_info", -1);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarsetsecurityobject_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarchangepassword_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* server */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_server, 0);
+
+ /* domain */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_domain, 0);
+
+ /* account */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_acct, 0);
+
+ /* old password */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_old_pwd, 0);
+
+ /* new password */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_new_pwd, 0);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarchangepassword_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static const value_string sid_type_vals[] = {
+ {1, "User"},
+ {2, "Group"},
+ {3, "Domain"},
+ {4, "Alias"},
+ {5, "Well Known Group"},
+ {6, "Deleted Account"},
+ {7, "Invalid"},
+ {8, "Unknown"},
+ {9, "Computer"},
+ {0, NULL}
+};
+static int
+lsa_dissect_LSA_TRANSLATED_NAME(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "LSA_TRANSLATED_NAME:");
+ tree = proto_item_add_subtree(item, ett_lsa_translated_name);
+ }
+
+ /* sid type */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_sid_type, NULL);
+
+ /* name */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_name, 0);
+
+ /* index */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_index, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRANSLATED_NAME_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_NAME);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRANSLATED_NAMES(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "LSA_TRANSLATED_NAMES:");
+ tree = proto_item_add_subtree(item, ett_lsa_translated_names);
+ }
+
+ /* count */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ /* settings */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_NAME_array, NDR_POINTER_UNIQUE,
+ "TRANSLATED_NAME_ARRAY", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarlookupsids_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
+ "PSID_ARRAY", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_NAMES, NDR_POINTER_REF,
+ "LSA_TRANSLATED_NAMES pointer: names", -1);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_info_level, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_num_mapped, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRUST_INFORMATION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "TRUST INFORMATION:");
+ tree = proto_item_add_subtree(item, ett_lsa_trust_information);
+ }
+
+ /* name */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_name, 0);
+
+ /* sid */
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static const value_string trusted_direction_vals[] = {
+ {0, "Trust disabled"},
+ {1, "Inbound trust"},
+ {2, "Outbound trust"},
+ {0, NULL}
+};
+
+static const value_string trusted_type_vals[] = {
+ {1, "Downlevel"},
+ {2, "Uplevel"},
+ {3, "MIT"},
+ {4, "DCE"},
+ {0, NULL}
+};
+
+static const true_false_string tfs_trust_attr_non_trans = {
+ "NON TRANSITIVE is set",
+ "Non transitive is NOT set"
+};
+static const true_false_string tfs_trust_attr_uplevel_only = {
+ "UPLEVEL ONLY is set",
+ "Uplevel only is NOT set"
+};
+static const true_false_string tfs_trust_attr_tree_parent = {
+ "TREE PARENT is set",
+ "Tree parent is NOT set"
+};
+static const true_false_string tfs_trust_attr_tree_root = {
+ "TREE ROOT is set",
+ "Tree root is NOT set"
+};
+static int
+lsa_dissect_trust_attr(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_lsa_trust_attr, &mask);
+
+ if(parent_tree){
+ item = proto_tree_add_uint(parent_tree, hf_lsa_trust_attr,
+ tvb, offset-4, 4, mask);
+ tree = proto_item_add_subtree(item, ett_lsa_trust_attr);
+ }
+
+ proto_tree_add_boolean(tree, hf_lsa_trust_attr_tree_root,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_lsa_trust_attr_tree_parent,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_lsa_trust_attr_uplevel_only,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_lsa_trust_attr_non_trans,
+ tvb, offset-4, 4, mask);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRUST_INFORMATION_EX(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "TRUST INFORMATION EX:");
+ tree = proto_item_add_subtree(item, ett_lsa_trust_information_ex);
+ }
+
+ /* name */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_name, 0);
+
+ /* flat name */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_flat_name, 0);
+
+ /* sid */
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ /* direction */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_trust_direction, NULL);
+
+ /* type */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_trust_type, NULL);
+
+ /* attributes */
+ offset = lsa_dissect_trust_attr(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_auth_info_blob(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di;
+ guint32 len;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ /* len */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_auth_len, &len);
+
+ proto_tree_add_item(tree, hf_lsa_auth_blob, tvb, offset, len, FALSE);
+ offset += len;
+
+ return offset;
+}
+
+static int
+lsa_dissect_auth_info(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "AUTH INFORMATION:");
+ tree = proto_item_add_subtree(item, ett_lsa_auth_information);
+ }
+
+ /* update */
+ offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_auth_update, NULL);
+
+ /* type */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_auth_type, NULL);
+
+ /* len */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_auth_len, NULL);
+
+ /* auth info blob */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_auth_info_blob, NDR_POINTER_UNIQUE,
+ "AUTH INFO blob:", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRUSTED_DOMAIN_AUTH_INFORMATION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "TRUSTED DOMAIN AUTH INFORMATION:");
+ tree = proto_item_add_subtree(item, ett_lsa_trusted_domain_auth_information);
+ }
+
+ /* unknown */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ /* unknown */
+ offset = lsa_dissect_auth_info(tvb, offset, pinfo, tree, drep);
+
+ /* unknown */
+ offset = lsa_dissect_auth_info(tvb, offset, pinfo, tree, drep);
+
+ /* unknown */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ /* unknown */
+ offset = lsa_dissect_auth_info(tvb, offset, pinfo, tree, drep);
+
+ /* unknown */
+ offset = lsa_dissect_auth_info(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+lsa_dissect_LSA_TRUST_INFORMATION_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUST_INFORMATION);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_REFERENCED_DOMAIN_LIST(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "LSA_REFERENCED_DOMAIN_LIST:");
+ tree = proto_item_add_subtree(item, ett_lsa_referenced_domain_list);
+ }
+
+ /* count */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ /* trust information */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUST_INFORMATION_array, NDR_POINTER_UNIQUE,
+ "TRUST INFORMATION array:", -1);
+
+ /* max count */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_max_count, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_lsarlookupsids_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_REFERENCED_DOMAIN_LIST, NDR_POINTER_UNIQUE,
+ "LSA_REFERENCED_DOMAIN_LIST pointer: domains", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_NAMES, NDR_POINTER_REF,
+ "LSA_TRANSLATED_NAMES pointer: names", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_num_mapped, NULL);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsetquotasforaccount_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_DEFAULT_QUOTA_INFO, NDR_POINTER_REF,
+ "POLICY_DEFAULT_QUOTA_INFO pointer: quotas", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsetquotasforaccount_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsargetquotasforaccount_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsargetquotasforaccount_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_DEFAULT_QUOTA_INFO, NDR_POINTER_REF,
+ "POLICY_DEFAULT_QUOTA_INFO pointer: quotas", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsetinformationpolicy_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_policy_information_class, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_INFORMATION, NDR_POINTER_REF,
+ "POLICY_INFORMATION pointer: info", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsetinformationpolicy_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarclearauditlog_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ /* unknown */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarclearauditlog_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsargetsystemaccessaccount_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsargetsystemaccessaccount_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_rid, NULL);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsetsystemaccessaccount_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_rid, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsetsystemaccessaccount_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsaropentrusteddomain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsaropentrusteddomain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsardeletetrusteddomain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsardeletetrusteddomain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+int
+dissect_nt_LUID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "LUID:");
+ tree = proto_item_add_subtree(item, ett_LUID);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_nt_luid_low, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_nt_luid_high, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_PRIVILEGE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "LSA_PRIVILEGE:");
+ tree = proto_item_add_subtree(item, ett_LSA_PRIVILEGE);
+ }
+
+ /* privilege name */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_privilege_name, 0);
+
+ /* LUID */
+ offset = dissect_nt_LUID(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_PRIVILEGE_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_PRIVILEGE);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_PRIVILEGES(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "LSA_PRIVILEGES:");
+ tree = proto_item_add_subtree(item, ett_LSA_PRIVILEGES);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ /* privileges */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_PRIVILEGE_array, NDR_POINTER_UNIQUE,
+ "LSA_PRIVILEGE array:", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumerateprivileges_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_size, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumerateprivileges_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_PRIVILEGES, NDR_POINTER_REF,
+ "LSA_PRIVILEGES pointer: privs", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarlookupprivilegevalue_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* privilege name */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+ "NAME pointer: ", hf_lsa_privilege_name);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarlookupprivilegevalue_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ /* LUID */
+ offset = dissect_nt_LUID(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarlookupprivilegename_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* LUID */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_nt_LUID, NDR_POINTER_REF,
+ "LUID pointer: value", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarlookupprivilegename_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out, ref] LSA_UNICODE_STRING **name */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+ "PRIVILEGE NAME pointer:", hf_lsa_privilege_name);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarenumerateprivilegesaccount_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_LUID_AND_ATTRIBUTES(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "LUID_AND_ATTRIBUTES:");
+ tree = proto_item_add_subtree(item, ett_LSA_LUID_AND_ATTRIBUTES);
+ }
+
+ /* LUID */
+ offset = dissect_nt_LUID(tvb, offset, pinfo, tree, drep);
+
+ /* attr */
+ offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_attr, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_LUID_AND_ATTRIBUTES_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LUID_AND_ATTRIBUTES);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LUID_AND_ATTRIBUTES_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "LUID_AND_ATTRIBUTES_ARRAY:");
+ tree = proto_item_add_subtree(item, ett_LSA_LUID_AND_ATTRIBUTES_ARRAY);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ /* luid and attributes */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LUID_AND_ATTRIBUTES_array, NDR_POINTER_UNIQUE,
+ "LUID_AND_ATTRIBUTES array:", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumerateprivilegesaccount_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out, ref] LUID_AND_ATTRIBUTES_ARRAY * *privs */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LUID_AND_ATTRIBUTES_ARRAY, NDR_POINTER_UNIQUE,
+ "LUID_AND_ATTRIBUTES_ARRAY pointer: privs", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsaraddprivilegestoaccount_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LUID_AND_ATTRIBUTES_ARRAY *privs */
+ offset = lsa_dissect_LUID_AND_ATTRIBUTES_ARRAY(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsaraddprivilegestoaccount_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarremoveprivilegesfromaccount_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in] char unknown */
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_char, NULL);
+
+ /* [in, unique] LUID_AND_ATTRIBUTES_ARRAY *privs */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LUID_AND_ATTRIBUTES_ARRAY, NDR_POINTER_UNIQUE,
+ "LUID_AND_ATTRIBUTES_ARRAY pointer: privs", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarremoveprivilegesfromaccount_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumerateaccounts_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in,out, ref] LSA_ENUMERATION_HANDLE *resume_hnd */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_resume_handle, NULL);
+
+ /* [in] ULONG pref_maxlen */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_max_count, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumerateaccounts_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in,out, ref] LSA_ENUMERATION_HANDLE *resume_hnd */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_resume_handle, NULL);
+
+ /* [out, ref] PSID_ARRAY **accounts */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
+ "PSID_ARRAY", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarcreatetrusteddomain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd_pol */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LSA_TRUST_INFORMATION *domain */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUST_INFORMATION, NDR_POINTER_REF,
+ "LSA_TRUST_INFORMATION pointer: domain", -1);
+
+ /* [in] ACCESS_MASK access */
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarcreatetrusteddomain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out] LSA_HANDLE *hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumeratetrusteddomains_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, out, ref] LSA_ENUMERATION_HANDLE *resume_hnd */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_resume_handle, NULL);
+
+ /* [in] ULONG pref_maxlen */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_max_count, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRUSTED_DOMAIN(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "TRUSTED_DOMAIN:");
+ tree = proto_item_add_subtree(item, ett_LSA_TRUSTED_DOMAIN);
+ }
+
+ /* domain */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_domain, 0);
+
+ /* sid */
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRUSTED_DOMAIN_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUSTED_DOMAIN);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRUSTED_DOMAIN_LIST(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "TRUSTED_DOMAIN_LIST:");
+ tree = proto_item_add_subtree(item, ett_LSA_TRUSTED_DOMAIN_LIST);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ /* privileges */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUSTED_DOMAIN_array, NDR_POINTER_UNIQUE,
+ "TRUSTED_DOMAIN array:", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumeratetrusteddomains_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in, out, ref] LSA_ENUMERATION_HANDLE *resume_hnd */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_resume_handle, NULL);
+
+ /* [out, ref] LSA_REFERENCED_DOMAIN_LIST *domains */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUSTED_DOMAIN_LIST, NDR_POINTER_REF,
+ "LSA_TRUSTED_DOMAIN_LIST pointer: domains", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_LSA_UNICODE_STRING_item(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ di->hf_index, 0);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_UNICODE_STRING_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_UNICODE_STRING_item);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_UNICODE_STRING_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_UNICODE_STRING_array, NDR_POINTER_UNIQUE,
+ "UNICODE_STRING pointer: ", di->hf_index);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRANSLATED_SID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* sid type */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_sid_type, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_rid, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_index, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRANSLATED_SIDS_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_SID);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRANSLATED_SIDS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "LSA_TRANSLATED_SIDS:");
+ tree = proto_item_add_subtree(item, ett_LSA_TRANSLATED_SIDS);
+ }
+
+ /* count */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ /* settings */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_SIDS_array, NDR_POINTER_UNIQUE,
+ "Translated SIDS", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_lsarlookupnames_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in] ULONG count */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ /* [in, size_is(count), ref] LSA_UNICODE_STRING *names */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_UNICODE_STRING_array, NDR_POINTER_REF,
+ "Account pointer: names", hf_lsa_acct);
+
+ /* [in, out, ref] LSA_TRANSLATED_SIDS *rids */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_SIDS, NDR_POINTER_REF,
+ "LSA_TRANSLATED_SIDS pointer: rids", -1);
+
+ /* [in] USHORT level */
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_info_level, NULL);
+
+ /* [in, out, ref] ULONG *num_mapped */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_num_mapped, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarlookupnames_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out] LSA_REFERENCED_DOMAIN_LIST *domains */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_REFERENCED_DOMAIN_LIST, NDR_POINTER_UNIQUE,
+ "LSA_REFERENCED_DOMAIN_LIST pointer: domains", -1);
+
+ /* [in, out, ref] LSA_TRANSLATED_SIDS *rids */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_SIDS, NDR_POINTER_REF,
+ "LSA_TRANSLATED_SIDS pointer: rids", -1);
+
+ /* [in, out, ref] ULONG *num_mapped */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_num_mapped, NULL);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarcreatesecret_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd_pol */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LSA_UNICODE_STRING *name */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_name, 0);
+
+ /* [in] ACCESS_MASK access */
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarcreatesecret_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ /* [out] LSA_HANDLE *hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsaropenaccount_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd_pol */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] SID *account */
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ /* [in] ACCESS_MASK access */
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsaropenaccount_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out] LSA_HANDLE *hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static const value_string trusted_info_level_vals[] = {
+ {1, "Domain Name Information"},
+ {2, "Controllers Information"},
+ {3, "Posix Offset Information"},
+ {4, "Password Information"},
+ {5, "Domain Information Basic"},
+ {6, "Domain Information Ex"},
+ {7, "Domain Auth Information"},
+ {8, "Domain Full Information"},
+ {9, "Domain Security Descriptor"},
+ {10, "Domain Private Information"},
+ {0, NULL}
+};
+
+static int
+lsa_dissect_TRUSTED_DOMAIN_INFORMATION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "TRUSTED_DOMAIN_INFO:");
+ tree = proto_item_add_subtree(item, ett_lsa_trusted_domain_info);
+ }
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_trusted_info_level, &level);
+
+ ALIGN_TO_4_BYTES; /* all union arms aligned to 4 bytes, case 7 and 9 need this */
+ switch(level){
+ case 1:
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_domain, 0);
+ break;
+ case 2:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_UNICODE_STRING_array, NDR_POINTER_UNIQUE,
+ "Controllers pointer: ", hf_lsa_controller);
+ break;
+ case 3:
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_rid_offset, NULL);
+ break;
+ case 4:
+ offset = lsa_dissect_LSA_SECRET(tvb, offset, pinfo, tree, drep);
+ offset = lsa_dissect_LSA_SECRET(tvb, offset, pinfo, tree, drep);
+ break;
+ case 5:
+ offset = lsa_dissect_LSA_TRUST_INFORMATION(tvb, offset,
+ pinfo, tree, drep);
+ break;
+ case 6:
+ offset = lsa_dissect_LSA_TRUST_INFORMATION_EX(tvb, offset,
+ pinfo, tree, drep);
+ break;
+ case 7:
+ offset = lsa_dissect_LSA_TRUSTED_DOMAIN_AUTH_INFORMATION(tvb, offset, pinfo, tree, drep);
+ break;
+ case 8:
+ offset = lsa_dissect_LSA_TRUST_INFORMATION_EX(tvb, offset,
+ pinfo, tree, drep);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_rid_offset, NULL);
+ offset = lsa_dissect_LSA_TRUSTED_DOMAIN_AUTH_INFORMATION(tvb, offset, pinfo, tree, drep);
+ break;
+ case 9:
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset, pinfo, tree, drep);
+ break;
+ case 10:
+ offset = lsa_dissect_LSA_TRUST_INFORMATION_EX(tvb, offset,
+ pinfo, tree, drep);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_rid_offset, NULL);
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset, pinfo, tree, drep);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_lsarqueryinfotrusteddomain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in] TRUSTED_INFORMATION_CLASS level */
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_trusted_info_level, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarqueryinfotrusteddomain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out, ref] TRUSTED_DOMAIN_INFORMATION *info */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_TRUSTED_DOMAIN_INFORMATION, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_INFORMATION pointer: info", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarsetinformationtrusteddomain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in] TRUSTED_INFORMATION_CLASS level */
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_trusted_info_level, NULL);
+
+ /* [in, ref] TRUSTED_DOMAIN_INFORMATION *info */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_TRUSTED_DOMAIN_INFORMATION, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_INFORMATION pointer: info", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsetinformationtrusteddomain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsaropensecret_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd_pol */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LSA_UNICODE_STRING *name */
+ offset = dissect_ndr_counted_string_cb(
+ tvb, offset, pinfo, tree, drep, hf_lsa_name,
+ cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ /* [in] ACCESS_MASK access */
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsaropensecret_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out] LSA_HANDLE *hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarsetsecret_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, unique] LSA_SECRET *new_val */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET, NDR_POINTER_UNIQUE,
+ "LSA_SECRET pointer: new_val", -1);
+
+ /* [in, unique] LSA_SECRET *old_val */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET, NDR_POINTER_UNIQUE,
+ "LSA_SECRET pointer: old_val", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsetsecret_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarquerysecret_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, out, unique] LSA_SECRET **curr_val */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET_pointer, NDR_POINTER_UNIQUE,
+ "LSA_SECRET pointer: curr_val", -1);
+
+ /* [in, out, unique] LARGE_INTEGER *curr_mtime */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_NTTIME, NDR_POINTER_UNIQUE,
+ "NTIME pointer: old_mtime", hf_lsa_cur_mtime);
+
+ /* [in, out, unique] LSA_SECRET **old_val */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET_pointer, NDR_POINTER_UNIQUE,
+ "LSA_SECRET pointer: old_val", -1);
+
+ /* [in, out, unique] LARGE_INTEGER *old_mtime */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_NTTIME, NDR_POINTER_UNIQUE,
+ "NTIME pointer: old_mtime", hf_lsa_old_mtime);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarquerysecret_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in, out, unique] LSA_SECRET **curr_val */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET_pointer, NDR_POINTER_UNIQUE,
+ "LSA_SECRET pointer: curr_val", -1);
+
+ /* [in, out, unique] LARGE_INTEGER *curr_mtime */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_NTTIME, NDR_POINTER_UNIQUE,
+ "NTIME pointer: old_mtime", hf_lsa_cur_mtime);
+
+ /* [in, out, unique] LSA_SECRET **old_val */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET_pointer, NDR_POINTER_UNIQUE,
+ "LSA_SECRET pointer: old_val", -1);
+
+ /* [in, out, unique] LARGE_INTEGER *old_mtime */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_NTTIME, NDR_POINTER_UNIQUE,
+ "NTIME pointer: old_mtime", hf_lsa_old_mtime);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsardeleteobject_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsardeleteobject_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumerateaccountswithuserright_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, unique] LSA_UNICODE_STRING *rights */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+ "LSA_UNICODE_STRING pointer: rights", hf_lsa_rights);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumerateaccountswithuserright_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out, ref] LSA_UNICODE_STRING_ARRAY *accounts */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_UNICODE_STRING_ARRAY, NDR_POINTER_REF,
+ "Account pointer: names", hf_lsa_acct);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumerateaccountrights_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] SID *account */
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarenumerateaccountrights_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out, ref] LSA_UNICODE_STRING_ARRAY *rights */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_UNICODE_STRING_ARRAY, NDR_POINTER_REF,
+ "Account pointer: rights", hf_lsa_rights);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsaraddaccountrights_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] SID *account */
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ /* [in, ref] LSA_UNICODE_STRING_ARRAY *rights */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_UNICODE_STRING_ARRAY, NDR_POINTER_REF,
+ "Account pointer: rights", hf_lsa_rights);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsaraddaccountrights_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarremoveaccountrights_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] SID *account */
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ /* remove all */
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_remove_all, NULL);
+
+ /* [in, ref] LSA_UNICODE_STRING_ARRAY *rights */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_UNICODE_STRING_ARRAY, NDR_POINTER_REF,
+ "Account pointer: rights", hf_lsa_rights);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarremoveaccountrights_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarquerytrusteddomaininfobyname_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE handle */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LSA_UNICODE_STRING *name */
+ /* domain */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_domain, 0);
+
+ /* [in] TRUSTED_INFORMATION_CLASS level */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_trusted_info_level, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarquerytrusteddomaininfobyname_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out, ref] TRUSTED_DOMAIN_INFORMATION *info) */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_TRUSTED_DOMAIN_INFORMATION, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_INFORMATION pointer: info", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsettrusteddomaininfobyname_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE handle */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LSA_UNICODE_STRING *name */
+ /* domain */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_domain, 0);
+
+ /* [in] TRUSTED_INFORMATION_CLASS level */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_trusted_info_level, NULL);
+
+ /* [in, ref] TRUSTED_DOMAIN_INFORMATION *info) */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_TRUSTED_DOMAIN_INFORMATION, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_INFORMATION pointer: info", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsettrusteddomaininfobyname_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarquerytrusteddomaininfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE handle */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] SID *sid */
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ /* [in] TRUSTED_INFORMATION_CLASS level */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_trusted_info_level, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsaropentrusteddomainbyname_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE handle */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LSA_UNICODE_STRING *name */
+ /* domain */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_domain, 0);
+
+ /* [in] ACCESS_MASK access */
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsaropentrusteddomainbyname_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out] LSA_HANDLE handle */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+
+static int
+lsa_dissect_lsarquerytrusteddomaininfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out, ref] TRUSTED_DOMAIN_INFORMATION *info) */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_TRUSTED_DOMAIN_INFORMATION, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_INFORMATION pointer: info", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarsettrusteddomaininfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE handle */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] SID *sid */
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ /* [in] TRUSTED_INFORMATION_CLASS level */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_trusted_info_level, NULL);
+
+ /* [ref, ref] TRUSTED_DOMAIN_INFORMATION *info) */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_TRUSTED_DOMAIN_INFORMATION, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_INFORMATION pointer: info", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarsettrusteddomaininfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarqueryinformationpolicy2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_policy_information_class, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(level, policy_information_class_vals,
+ "Unknown (%d)"));
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarqueryinformationpolicy2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* This is really a pointer to a pointer though the first level is REF
+ so we just ignore that one */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_INFORMATION, NDR_POINTER_UNIQUE,
+ "POLICY_INFORMATION pointer: info", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarsetinformationpolicy2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_policy_information_class, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_INFORMATION, NDR_POINTER_REF,
+ "POLICY_INFORMATION pointer: info", -1);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarsetinformationpolicy2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarquerydomaininformationpolicy_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_policy_information_class, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarquerydomaininformationpolicy_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_INFORMATION, NDR_POINTER_REF,
+ "POLICY_INFORMATION pointer: info", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarsetdomaininformationpolicy_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_policy_information_class, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_POLICY_INFORMATION, NDR_POINTER_REF,
+ "POLICY_INFORMATION pointer: info", -1);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarsetdomaininformationpolicy_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarlookupnames2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in] ULONG count */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ /* [in, size_is(count), ref] LSA_UNICODE_STRING *names */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_UNICODE_STRING_array, NDR_POINTER_REF,
+ "Account pointer: names", hf_lsa_acct);
+
+ /* [in, out, ref] LSA_TRANSLATED_SIDS *rids */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_SIDS, NDR_POINTER_REF,
+ "LSA_TRANSLATED_SIDS pointer: rids", -1);
+
+ /* [in] USHORT level */
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_info_level, NULL);
+
+ /* [in, out, ref] ULONG *num_mapped */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_num_mapped, NULL);
+
+ /* unknown */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ /* unknown */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarlookupnames2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out] LSA_REFERENCED_DOMAIN_LIST *domains */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_REFERENCED_DOMAIN_LIST, NDR_POINTER_UNIQUE,
+ "LSA_REFERENCED_DOMAIN_LIST pointer: domains", -1);
+
+ /* [in, out, ref] LSA_TRANSLATED_SIDS *rids */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_SIDS, NDR_POINTER_REF,
+ "LSA_TRANSLATED_SIDS pointer: rids", -1);
+
+ /* [in, out, ref] ULONG *num_mapped */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_num_mapped, NULL);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarcreateaccount_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarcreateaccount_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarlookupprivilegedisplayname_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LSA_UNICODE_STRING *name */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_privilege_name, 0);
+
+ /* [in, ref] long *size */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_privilege_display_name_size, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarlookupprivilegedisplayname_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out, ref] LSA_UNICODE_STRING **disp_name */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+ "NAME pointer: ", hf_lsa_privilege_display_name);
+
+ /* [out, ref] long *size */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_privilege_display_name_size, NULL);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarstoreprivatedata_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LSA_UNICODE_STRING *key */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_key, 0);
+
+ /* [in, unique] LSA_SECRET **data */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET_pointer, NDR_POINTER_UNIQUE,
+ "LSA_SECRET* pointer: data", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarstoreprivatedata_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarretrieveprivatedata_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] LSA_UNICODE_STRING *key */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_key, 0);
+
+ /* [in, out, ref] LSA_SECRET **data */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET_pointer, NDR_POINTER_REF,
+ "LSA_SECRET* pointer: data", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarretrieveprivatedata_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in, out, ref] LSA_SECRET **data */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECRET_pointer, NDR_POINTER_REF,
+ "LSA_SECRET* pointer: data", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarclosetrusteddomainex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ /* [in, out] LSA_HANDLE *tdHnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarclosetrusteddomainex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ /* [in, out] LSA_HANDLE *tdHnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRANSLATED_NAME_EX(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "LSA_TRANSLATED_NAME:");
+ tree = proto_item_add_subtree(item, ett_lsa_translated_name);
+ }
+
+ /* sid type */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_sid_type, NULL);
+
+ /* name */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_lsa_name, 0);
+
+ /* index */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_index, NULL);
+
+ /* unknown */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRANSLATED_NAME_EX_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_NAME_EX);
+
+ return offset;
+}
+static int
+lsa_dissect_LSA_TRANSLATED_NAMES_EX(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* count */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_NAME_EX_array, NDR_POINTER_UNIQUE,
+ "LSA_TRANSLATED_NAME_EX: pointer", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarlookupsids2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
+ "PSID_ARRAY", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_NAMES_EX, NDR_POINTER_REF,
+ "LSA_TRANSLATED_NAMES_EX pointer: names", -1);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_info_level, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_num_mapped, NULL);
+
+ /* unknown */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ /* unknown */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarlookupsids2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_REFERENCED_DOMAIN_LIST, NDR_POINTER_UNIQUE,
+ "LSA_REFERENCED_DOMAIN_LIST pointer: domains", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRANSLATED_NAMES_EX, NDR_POINTER_REF,
+ "LSA_TRANSLATED_NAMES_EX pointer: names", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_num_mapped, NULL);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsargetusername_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ /* [in, unique, string] WCHAR *server */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_lsa_openpolicy_server, NDR_POINTER_UNIQUE,
+ "Server:", hf_lsa_server);
+
+ /* [in, out, ref] LSA_UNICODE_STRING **user */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+ "ACCOUNT pointer: ", hf_lsa_acct);
+
+ /* [in, out, unique] LSA_UNICODE_STRING **domain */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+ "DOMAIN pointer: ", hf_lsa_domain);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsargetusername_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in, out, ref] LSA_UNICODE_STRING **user */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+ "ACCOUNT pointer: ", hf_lsa_acct);
+
+ /* [in, out, unique] LSA_UNICODE_STRING **domain */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_pointer_pointer_UNICODE_STRING, NDR_POINTER_UNIQUE,
+ "DOMAIN pointer: ", hf_lsa_domain);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarcreatetrusteddomainex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] TRUSTED_DOMAIN_INFORMATION_EX *info */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUST_INFORMATION_EX, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_INFORMATION_EX pointer: info", -1);
+
+ /* [in, ref] TRUSTED_DOMAIN_AUTH_INFORMATION *auth */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUSTED_DOMAIN_AUTH_INFORMATION, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_AUTH_INFORMATION pointer: auth", -1);
+
+ /* [in] ACCESS_MASK mask */
+ offset = lsa_dissect_ACCESS_MASK(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarcreatetrusteddomainex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out] LSA_HANDLE *tdHnd) */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumeratetrusteddomainsex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, out, ref] LSA_ENUMERATION_HANDLE *resume_hnd */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_resume_handle, NULL);
+
+ /* [in] ULONG pref_maxlen */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_max_count, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_LSA_TRUSTED_DOMAIN_INFORMATION_EX_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUST_INFORMATION_EX);
+
+ return offset;
+}
+
+static int
+lsa_dissect_LSA_TRUSTED_DOMAIN_INFORMATION_LIST_EX(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* count */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_count, NULL);
+
+ /* trust information */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUSTED_DOMAIN_INFORMATION_EX_array, NDR_POINTER_UNIQUE,
+ "TRUST INFORMATION array:", -1);
+
+ /* max count */
+ /* The original code here was wrong. It now handles these correctly */
+ /*offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_lsa_max_count, NULL);
+ */
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarenumeratetrusteddomainsex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in, out, ref] LSA_ENUMERATION_HANDLE *resume_hnd */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_resume_handle, NULL);
+
+ /* [out, ref] TRUSTED_DOMAIN_INFORMATION_LIST_EX *domains */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUSTED_DOMAIN_INFORMATION_LIST_EX, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_INFORMATION_LIST_EX pointer: domains", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsartestcall_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE handle */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in] USHORT flag */
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_short, NULL);
+
+ /* [in, ref] LSA_SECURITY_DESCRIPTOR *sd */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR, NDR_POINTER_REF,
+ "LSA_SECURITY_DESCRIPTOR pointer: sd", -1);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsartestcall_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out, ref] LSA_SECURITY_DESCRIPTOR **psd) */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR, NDR_POINTER_UNIQUE,
+ "LSA_SECURITY_DESCRIPTOR pointer: psd)", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+static int
+lsa_dissect_lsarcreatetrusteddomainex2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [in] LSA_HANDLE hnd */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ /* [in, ref] TRUSTED_DOMAIN_INFORMATION_EX *info */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_TRUST_INFORMATION_EX, NDR_POINTER_REF,
+ "TRUSTED_DOMAIN_INFORMATION_EX pointer: info", -1);
+
+ /* [in, ref] LSA_SECURITY_DESCRIPTOR *sd */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR, NDR_POINTER_REF,
+ "LSA_SECURITY_DESCRIPTOR pointer: sd", -1);
+
+ /* [in] ULONG unknown */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_lsa_unknown_long, NULL);
+
+ return offset;
+}
+
+
+static int
+lsa_dissect_lsarcreatetrusteddomainex2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* [out] LSA_HANDLE *h2) */
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_lsa_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_lsa_rc, NULL);
+
+ return offset;
+}
+
+
+static dcerpc_sub_dissector dcerpc_lsa_dissectors[] = {
+ { LSA_LSARCLOSE, "LsarClose",
+ lsa_dissect_lsarclose_rqst,
+ lsa_dissect_lsarclose_reply },
+ { LSA_LSARDELETE, "LsarDelete",
+ lsa_dissect_lsardelete_rqst,
+ lsa_dissect_lsardelete_reply },
+ { LSA_LSARENUMERATEPRIVILEGES, "LsarEnumeratePrivileges",
+ lsa_dissect_lsarenumerateprivileges_rqst,
+ lsa_dissect_lsarenumerateprivileges_reply },
+ { LSA_LSARQUERYSECURITYOBJECT, "LsarQuerySecurityObject",
+ lsa_dissect_lsarquerysecurityobject_rqst,
+ lsa_dissect_lsarquerysecurityobject_reply },
+ { LSA_LSARSETSECURITYOBJECT, "LsarSetSecurityObject",
+ lsa_dissect_lsarsetsecurityobject_rqst,
+ lsa_dissect_lsarsetsecurityobject_reply },
+ { LSA_LSARCHANGEPASSWORD, "LsarChangePassword",
+ lsa_dissect_lsarchangepassword_rqst,
+ lsa_dissect_lsarchangepassword_reply },
+ { LSA_LSAROPENPOLICY, "LsarOpenPolicy",
+ lsa_dissect_lsaropenpolicy_rqst,
+ lsa_dissect_lsaropenpolicy_reply },
+ { LSA_LSARQUERYINFORMATIONPOLICY, "LsarQueryInformationPolicy",
+ lsa_dissect_lsarqueryinformationpolicy_rqst,
+ lsa_dissect_lsarqueryinformationpolicy_reply },
+ { LSA_LSARSETINFORMATIONPOLICY, "LsarSetInformationPolicy",
+ lsa_dissect_lsarsetinformationpolicy_rqst,
+ lsa_dissect_lsarsetinformationpolicy_reply },
+ { LSA_LSARCLEARAUDITLOG, "LsarClearAuditLog",
+ lsa_dissect_lsarclearauditlog_rqst,
+ lsa_dissect_lsarclearauditlog_reply },
+ { LSA_LSARCREATEACCOUNT, "LsarCreateAccount",
+ lsa_dissect_lsarcreateaccount_rqst,
+ lsa_dissect_lsarcreateaccount_reply },
+ { LSA_LSARENUMERATEACCOUNTS, "LsarEnumerateAccounts",
+ lsa_dissect_lsarenumerateaccounts_rqst,
+ lsa_dissect_lsarenumerateaccounts_reply },
+ { LSA_LSARCREATETRUSTEDDOMAIN, "LsarCreateTrustedDomain",
+ lsa_dissect_lsarcreatetrusteddomain_rqst,
+ lsa_dissect_lsarcreatetrusteddomain_reply },
+ { LSA_LSARENUMERATETRUSTEDDOMAINS, "LsarEnumerateTrustedDomains",
+ lsa_dissect_lsarenumeratetrusteddomains_rqst,
+ lsa_dissect_lsarenumeratetrusteddomains_reply },
+ { LSA_LSARLOOKUPNAMES, "LsarLookupNames",
+ lsa_dissect_lsarlookupnames_rqst,
+ lsa_dissect_lsarlookupnames_reply },
+ { LSA_LSARLOOKUPSIDS, "LsarLookupSids",
+ lsa_dissect_lsarlookupsids_rqst,
+ lsa_dissect_lsarlookupsids_reply },
+ { LSA_LSARCREATESECRET, "LsarCreateSecret",
+ lsa_dissect_lsarcreatesecret_rqst,
+ lsa_dissect_lsarcreatesecret_reply },
+ { LSA_LSAROPENACCOUNT, "LsarOpenAccount",
+ lsa_dissect_lsaropenaccount_rqst,
+ lsa_dissect_lsaropenaccount_reply },
+ { LSA_LSARENUMERATEPRIVILEGESACCOUNT, "LsarEnumeratePrivilegesAccount",
+ lsa_dissect_lsarenumerateprivilegesaccount_rqst,
+ lsa_dissect_lsarenumerateprivilegesaccount_reply },
+ { LSA_LSARADDPRIVILEGESTOACCOUNT, "LsarAddPrivilegesToAccount",
+ lsa_dissect_lsaraddprivilegestoaccount_rqst,
+ lsa_dissect_lsaraddprivilegestoaccount_reply },
+ { LSA_LSARREMOVEPRIVILEGESFROMACCOUNT, "LsarRemovePrivilegesFromAccount",
+ lsa_dissect_lsarremoveprivilegesfromaccount_rqst,
+ lsa_dissect_lsarremoveprivilegesfromaccount_reply },
+ { LSA_LSARGETQUOTASFORACCOUNT, "LsarGetQuotasForAccount",
+ lsa_dissect_lsargetquotasforaccount_rqst,
+ lsa_dissect_lsargetquotasforaccount_reply },
+ { LSA_LSARSETQUOTASFORACCOUNT, "LsarSetQuotasForAccount",
+ lsa_dissect_lsarsetquotasforaccount_rqst,
+ lsa_dissect_lsarsetquotasforaccount_reply },
+ { LSA_LSARGETSYSTEMACCESSACCOUNT, "LsarGetSystemAccessAccount",
+ lsa_dissect_lsargetsystemaccessaccount_rqst,
+ lsa_dissect_lsargetsystemaccessaccount_reply },
+ { LSA_LSARSETSYSTEMACCESSACCOUNT, "LsarSetSystemAccessAccount",
+ lsa_dissect_lsarsetsystemaccessaccount_rqst,
+ lsa_dissect_lsarsetsystemaccessaccount_reply },
+ { LSA_LSAROPENTRUSTEDDOMAIN, "LsarOpenTrustedDomain",
+ lsa_dissect_lsaropentrusteddomain_rqst,
+ lsa_dissect_lsaropentrusteddomain_reply },
+ { LSA_LSARQUERYINFOTRUSTEDDOMAIN, "LsarQueryInfoTrustedDomain",
+ lsa_dissect_lsarqueryinfotrusteddomain_rqst,
+ lsa_dissect_lsarqueryinfotrusteddomain_reply },
+ { LSA_LSARSETINFORMATIONTRUSTEDDOMAIN, "LsarSetInformationTrustedDomain",
+ lsa_dissect_lsarsetinformationtrusteddomain_rqst,
+ lsa_dissect_lsarsetinformationtrusteddomain_reply },
+ { LSA_LSAROPENSECRET, "LsarOpenSecret",
+ lsa_dissect_lsaropensecret_rqst,
+ lsa_dissect_lsaropensecret_reply },
+ { LSA_LSARSETSECRET, "LsarSetSecret",
+ lsa_dissect_lsarsetsecret_rqst,
+ lsa_dissect_lsarsetsecret_reply },
+ { LSA_LSARQUERYSECRET, "LsarQuerySecret",
+ lsa_dissect_lsarquerysecret_rqst,
+ lsa_dissect_lsarquerysecret_reply },
+ { LSA_LSARLOOKUPPRIVILEGEVALUE, "LsarLookupPrivilegeValue",
+ lsa_dissect_lsarlookupprivilegevalue_rqst,
+ lsa_dissect_lsarlookupprivilegevalue_reply },
+ { LSA_LSARLOOKUPPRIVILEGENAME, "LsarLookupPrivilegeName",
+ lsa_dissect_lsarlookupprivilegename_rqst,
+ lsa_dissect_lsarlookupprivilegename_reply },
+ { LSA_LSARLOOKUPPRIVILEGEDISPLAYNAME, "LsarLookupPrivilegeDisplayName",
+ lsa_dissect_lsarlookupprivilegedisplayname_rqst,
+ lsa_dissect_lsarlookupprivilegedisplayname_reply },
+ { LSA_LSARDELETEOBJECT, "LsarDeleteObject",
+ lsa_dissect_lsardeleteobject_rqst,
+ lsa_dissect_lsardeleteobject_reply },
+ { LSA_LSARENUMERATEACCOUNTSWITHUSERRIGHT, "LsarEnumerateAccountsWithUserRight",
+ lsa_dissect_lsarenumerateaccountswithuserright_rqst,
+ lsa_dissect_lsarenumerateaccountswithuserright_reply },
+ { LSA_LSARENUMERATEACCOUNTRIGHTS, "LsarEnumerateAccountRights",
+ lsa_dissect_lsarenumerateaccountrights_rqst,
+ lsa_dissect_lsarenumerateaccountrights_reply },
+ { LSA_LSARADDACCOUNTRIGHTS, "LsarAddAccountRights",
+ lsa_dissect_lsaraddaccountrights_rqst,
+ lsa_dissect_lsaraddaccountrights_reply },
+ { LSA_LSARREMOVEACCOUNTRIGHTS, "LsarRemoveAccountRights",
+ lsa_dissect_lsarremoveaccountrights_rqst,
+ lsa_dissect_lsarremoveaccountrights_reply },
+ { LSA_LSARQUERYTRUSTEDDOMAININFO, "LsarQueryTrustedDomainInfo",
+ lsa_dissect_lsarquerytrusteddomaininfo_rqst,
+ lsa_dissect_lsarquerytrusteddomaininfo_reply },
+ { LSA_LSARSETTRUSTEDDOMAININFO, "LsarSetTrustedDomainInfo",
+ lsa_dissect_lsarsettrusteddomaininfo_rqst,
+ lsa_dissect_lsarsettrusteddomaininfo_reply },
+ { LSA_LSARDELETETRUSTEDDOMAIN, "LsarDeleteTrustedDomain",
+ lsa_dissect_lsardeletetrusteddomain_rqst,
+ lsa_dissect_lsardeletetrusteddomain_reply },
+ { LSA_LSARSTOREPRIVATEDATA, "LsarStorePrivateData",
+ lsa_dissect_lsarstoreprivatedata_rqst,
+ lsa_dissect_lsarstoreprivatedata_reply },
+ { LSA_LSARRETRIEVEPRIVATEDATA, "LsarRetrievePrivateData",
+ lsa_dissect_lsarretrieveprivatedata_rqst,
+ lsa_dissect_lsarretrieveprivatedata_reply },
+ { LSA_LSAROPENPOLICY2, "LsarOpenPolicy2",
+ lsa_dissect_lsaropenpolicy2_rqst,
+ lsa_dissect_lsaropenpolicy2_reply },
+ { LSA_LSARGETUSERNAME, "LsarGetUserName",
+ lsa_dissect_lsargetusername_rqst,
+ lsa_dissect_lsargetusername_reply },
+ { LSA_LSARQUERYINFORMATIONPOLICY2, "LsarQueryInformationPolicy2",
+ lsa_dissect_lsarqueryinformationpolicy2_rqst,
+ lsa_dissect_lsarqueryinformationpolicy2_reply },
+ { LSA_LSARSETINFORMATIONPOLICY2, "LsarSetInformationPolicy2",
+ lsa_dissect_lsarsetinformationpolicy2_rqst,
+ lsa_dissect_lsarsetinformationpolicy2_reply },
+ { LSA_LSARQUERYTRUSTEDDOMAININFOBYNAME, "LsarQueryTrustedDomainInfoByName",
+ lsa_dissect_lsarquerytrusteddomaininfobyname_rqst,
+ lsa_dissect_lsarquerytrusteddomaininfobyname_reply },
+ { LSA_LSARSETTRUSTEDDOMAININFOBYNAME, "LsarSetTrustedDomainInfoByName",
+ lsa_dissect_lsarsettrusteddomaininfobyname_rqst,
+ lsa_dissect_lsarsettrusteddomaininfobyname_reply },
+ { LSA_LSARENUMERATETRUSTEDDOMAINSEX, "LsarEnumerateTrustedDomainsEx",
+ lsa_dissect_lsarenumeratetrusteddomainsex_rqst,
+ lsa_dissect_lsarenumeratetrusteddomainsex_reply },
+ { LSA_LSARCREATETRUSTEDDOMAINEX, "LsarCreateTrustedDomainEx",
+ lsa_dissect_lsarcreatetrusteddomainex_rqst,
+ lsa_dissect_lsarcreatetrusteddomainex_reply },
+ { LSA_LSARCLOSETRUSTEDDOMAINEX, "LsarCloseTrustedDomainEx",
+ lsa_dissect_lsarclosetrusteddomainex_rqst,
+ lsa_dissect_lsarclosetrusteddomainex_reply },
+ { LSA_LSARQUERYDOMAININFORMATIONPOLICY, "LsarQueryDomainInformationPolicy",
+ lsa_dissect_lsarquerydomaininformationpolicy_rqst,
+ lsa_dissect_lsarquerydomaininformationpolicy_reply },
+ { LSA_LSARSETDOMAININFORMATIONPOLICY, "LsarSetDomainInformationPolicy",
+ lsa_dissect_lsarsetdomaininformationpolicy_rqst,
+ lsa_dissect_lsarsetdomaininformationpolicy_reply },
+ { LSA_LSAROPENTRUSTEDDOMAINBYNAME, "LsarOpenTrustedDomainByName",
+ lsa_dissect_lsaropentrusteddomainbyname_rqst,
+ lsa_dissect_lsaropentrusteddomainbyname_reply },
+ { LSA_LSARTESTCALL, "LsarTestCall",
+ lsa_dissect_lsartestcall_rqst,
+ lsa_dissect_lsartestcall_reply },
+ { LSA_LSARLOOKUPSIDS2, "LsarLookupSids2",
+ lsa_dissect_lsarlookupsids2_rqst,
+ lsa_dissect_lsarlookupsids2_reply },
+ { LSA_LSARLOOKUPNAMES2, "LsarLookupNames2",
+ lsa_dissect_lsarlookupnames2_rqst,
+ lsa_dissect_lsarlookupnames2_reply },
+ { LSA_LSARCREATETRUSTEDDOMAINEX2, "LsarCreateTrustedDomainEx2",
+ lsa_dissect_lsarcreatetrusteddomainex2_rqst,
+ lsa_dissect_lsarcreatetrusteddomainex2_reply },
+ { LSA_CREDRWRITE, "CredrWrite", NULL, NULL },
+ { LSA_CREDRREAD, "CredrRead", NULL, NULL },
+ { LSA_CREDRENUMERATE, "CredrEnumerate", NULL, NULL },
+ { LSA_CREDRWRITEDOMAINCREDENTIALS, "CredrWriteDomainCredentials",
+ NULL, NULL },
+ { LSA_CREDRREADDOMAINCREDENTIALS, "CredrReadDomainCredentials",
+ NULL, NULL },
+ { LSA_CREDRDELETE, "CredrDelete", NULL, NULL },
+ { LSA_CREDRGETTARGETINFO, "CredrGetTargetInfo", NULL, NULL },
+ { LSA_CREDRPROFILELOADED, "CredrProfileLoaded", NULL, NULL },
+ { LSA_LSARLOOKUPNAMES3, "LsarLookupNames3", NULL, NULL },
+ { LSA_CREDRGETSESSIONTYPES, "CredrGetSessionTypes", NULL, NULL },
+ { LSA_LSARREGISTERAUDITEVENT, "LsarRegisterAuditEvent", NULL, NULL },
+ { LSA_LSARGENAUDITEVENT, "LsarGenAuditEvent", NULL, NULL },
+ { LSA_LSARUNREGISTERAUDITEVENT, "LsarUnregisterAuditEvent", NULL, NULL},
+ { LSA_LSARQUERYFORESTTRUSTINFORMATION,
+ "LsarQueryForestTrustInformation", NULL, NULL },
+ { LSA_LSARSETFORESTTRUSTINFORMATION, "LsarSetForestTrustInformation",
+ NULL, NULL },
+ { LSA_CREDRRENAME, "CredrRename", NULL, NULL },
+ { LSA_LSARLOOKUPSIDS3, "LsarLookupSids3", NULL, NULL },
+ { LSA_LSARLOOKUPNAMES4, "LsarLookupNames4", NULL, NULL },
+ { LSA_LSAROPENPOLICYSCE, "LsarOpenPolicySce", NULL, NULL },
+ { LSA_LSARADTREGISTERSECURITYEVENTSOURCE,
+ "LsarAdtRegisterSecurityEventSource", NULL, NULL },
+ { LSA_LSARADTUNREGISTERSECURITYEVENTSOURCE,
+ "LsarAdtUnregisterSecurityEventSource", NULL, NULL },
+ { LSA_LSARADTREPORTSECURITYEVENT, "LsarAdtReportSecurityEvent",
+ NULL, NULL },
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_dcerpc_lsa(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_lsa_opnum,
+ { "Operation", "lsa.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+
+ { &hf_lsa_unknown_string,
+ { "Unknown string", "lsa.unknown_string", FT_STRING, BASE_NONE,
+ NULL, 0, "Unknown string. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_lsa_hnd,
+ { "Context Handle", "lsa.hnd", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "LSA policy handle", HFILL }},
+
+ { &hf_lsa_server,
+ { "Server", "lsa.server", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of Server", HFILL }},
+
+ { &hf_lsa_controller,
+ { "Controller", "lsa.controller", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of Domain Controller", HFILL }},
+
+ { &hf_lsa_unknown_hyper,
+ { "Unknown hyper", "lsa.unknown.hyper", FT_UINT64, BASE_HEX,
+ NULL, 0x0, "Unknown hyper. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_lsa_unknown_long,
+ { "Unknown long", "lsa.unknown.long", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Unknown long. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_lsa_unknown_short,
+ { "Unknown short", "lsa.unknown.short", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Unknown short. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_lsa_unknown_char,
+ { "Unknown char", "lsa.unknown.char", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Unknown char. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_lsa_rc,
+ { "Return code", "lsa.rc", FT_UINT32, BASE_HEX,
+ VALS (NT_errors), 0x0, "LSA return status code", HFILL }},
+
+ { &hf_lsa_obj_attr,
+ { "Attributes", "lsa.obj_attr", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "LSA Attributes", HFILL }},
+
+ { &hf_lsa_obj_attr_len,
+ { "Length", "lsa.obj_attr.len", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Length of object attribute structure", HFILL }},
+
+ { &hf_lsa_obj_attr_name,
+ { "Name", "lsa.obj_attr.name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Name of object attribute", HFILL }},
+
+ { &hf_lsa_access_mask,
+ { "Access Mask", "lsa.access_mask", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "LSA Access Mask", HFILL }},
+
+ { &hf_lsa_info_level,
+ { "Level", "lsa.info.level", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Information level of requested data", HFILL }},
+
+ { &hf_lsa_trusted_info_level,
+ { "Info Level", "lsa.trusted.info_level", FT_UINT16, BASE_DEC,
+ VALS(trusted_info_level_vals), 0x0, "Information level of requested Trusted Domain Information", HFILL }},
+
+ { &hf_lsa_sd_size,
+ { "Size", "lsa.sd_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of lsa security descriptor", HFILL }},
+
+ { &hf_lsa_qos_len,
+ { "Length", "lsa.qos.len", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Length of quality of service structure", HFILL }},
+
+ { &hf_lsa_qos_impersonation_level,
+ { "Impersonation level", "lsa.qos.imp_lev", FT_UINT16, BASE_DEC,
+ VALS(lsa_impersonation_level_vals), 0x0, "QOS Impersonation Level", HFILL }},
+
+ { &hf_lsa_qos_track_context,
+ { "Context Tracking", "lsa.qos.track_ctx", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "QOS Context Tracking Mode", HFILL }},
+
+ { &hf_lsa_qos_effective_only,
+ { "Effective only", "lsa.qos.effective_only", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "QOS Flag whether this is Effective Only or not", HFILL }},
+
+ { &hf_lsa_pali_percent_full,
+ { "Percent Full", "lsa.pali.percent_full", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "How full audit log is in percentage", HFILL }},
+
+ { &hf_lsa_pali_log_size,
+ { "Log Size", "lsa.pali.log_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of audit log", HFILL }},
+
+ { &hf_lsa_pali_retention_period,
+ { "Retention Period", "lsa.pali.retention_period", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_pali_time_to_shutdown,
+ { "Time to shutdown", "lsa.pali.time_to_shutdown", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0x0, "Time to shutdown", HFILL }},
+
+ { &hf_lsa_pali_shutdown_in_progress,
+ { "Shutdown in progress", "lsa.pali.shutdown_in_progress", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Flag whether shutdown is in progress or not", HFILL }},
+
+ { &hf_lsa_pali_next_audit_record,
+ { "Next Audit Record", "lsa.pali.next_audit_record", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Next audit record", HFILL }},
+
+ { &hf_lsa_paei_enabled,
+ { "Auditing enabled", "lsa.paei.enabled", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "If Security auditing is enabled or not", HFILL }},
+
+ { &hf_lsa_paei_settings,
+ { "Settings", "lsa.paei.settings", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Audit Events Information settings", HFILL }},
+
+ { &hf_lsa_count,
+ { "Count", "lsa.count", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Count of objects", HFILL }},
+
+ { &hf_lsa_max_count,
+ { "Max Count", "lsa.max_count", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_fqdomain,
+ { "FQDN", "lsa.fqdn_domain", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Fully Qualified Domain Name", HFILL }},
+
+ { &hf_lsa_domain,
+ { "Domain", "lsa.domain", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Domain", HFILL }},
+
+ { &hf_lsa_acct,
+ { "Account", "lsa.acct", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Account", HFILL }},
+
+ { &hf_lsa_source,
+ { "Source", "lsa.source", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Replica Source", HFILL }},
+
+ { &hf_lsa_server_role,
+ { "Role", "lsa.server_role", FT_UINT16, BASE_DEC,
+ VALS(server_role_vals), 0x0, "LSA Server Role", HFILL }},
+
+ { &hf_lsa_quota_paged_pool,
+ { "Paged Pool", "lsa.quota.paged_pool", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of Quota Paged Pool", HFILL }},
+
+ { &hf_lsa_quota_non_paged_pool,
+ { "Non Paged Pool", "lsa.quota.non_paged_pool", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of Quota non-Paged Pool", HFILL }},
+
+ { &hf_lsa_quota_min_wss,
+ { "Min WSS", "lsa.quota.min_wss", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of Quota Min WSS", HFILL }},
+
+ { &hf_lsa_quota_max_wss,
+ { "Max WSS", "lsa.quota.max_wss", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of Quota Max WSS", HFILL }},
+
+ { &hf_lsa_quota_pagefile,
+ { "Pagefile", "lsa.quota.pagefile", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of quota pagefile usage", HFILL }},
+
+ { &hf_lsa_mod_seq_no,
+ { "Seq No", "lsa.mod.seq_no", FT_UINT64, BASE_DEC,
+ NULL, 0x0, "Sequence number for this modification", HFILL }},
+
+ { &hf_lsa_mod_mtime,
+ { "MTime", "lsa.mod.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0x0, "Time when this modification occured", HFILL }},
+
+ { &hf_lsa_cur_mtime,
+ { "Current MTime", "lsa.cur.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0x0, "Current MTime to set", HFILL }},
+
+ { &hf_lsa_old_mtime,
+ { "Old MTime", "lsa.old.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0x0, "Old MTime for this object", HFILL }},
+
+ { &hf_lsa_name,
+ { "Name", "lsa.name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_key,
+ { "Key", "lsa.key", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_flat_name,
+ { "Flat Name", "lsa.flat_name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_forest,
+ { "Forest", "lsa.forest", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_info_type,
+ { "Info Type", "lsa.info_type", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_new_pwd,
+ { "New Password", "lsa.new_pwd", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "New password", HFILL }},
+
+ { &hf_lsa_old_pwd,
+ { "Old Password", "lsa.old_pwd", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Old password", HFILL }},
+
+ { &hf_lsa_sid_type,
+ { "SID Type", "lsa.sid_type", FT_UINT16, BASE_DEC,
+ VALS(sid_type_vals), 0x0, "Type of SID", HFILL }},
+
+ { &hf_lsa_rid,
+ { "RID", "lsa.rid", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "RID", HFILL }},
+
+ { &hf_lsa_rid_offset,
+ { "RID Offset", "lsa.rid.offset", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "RID Offset", HFILL }},
+
+ { &hf_lsa_index,
+ { "Index", "lsa.index", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_num_mapped,
+ { "Num Mapped", "lsa.num_mapped", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_policy_information_class,
+ { "Info Class", "lsa.policy.info", FT_UINT16, BASE_DEC,
+ VALS(policy_information_class_vals), 0x0, "Policy information class", HFILL }},
+
+ { &hf_lsa_secret,
+ { "LSA Secret", "lsa.secret", FT_BYTES, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_lsa_auth_blob,
+ { "Auth blob", "lsa.auth.blob", FT_BYTES, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_nt_luid_high,
+ { "High", "nt.luid.high", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "LUID High component", HFILL }},
+
+ { &hf_nt_luid_low,
+ { "Low", "nt.luid.low", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "LUID Low component", HFILL }},
+
+ { &hf_lsa_size,
+ { "Size", "lsa.size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_size16,
+ { "Size", "lsa.size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_lsa_privilege_display_name_size,
+ { "Size Needed", "lsa.privilege.display__name.size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of characters in the privilege display name", HFILL }},
+
+ { &hf_lsa_privilege_name,
+ { "Name", "lsa.privilege.name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "LSA Privilege Name", HFILL }},
+
+ { &hf_lsa_privilege_display_name,
+ { "Display Name", "lsa.privilege.display_name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "LSA Privilege Display Name", HFILL }},
+
+ { &hf_lsa_rights,
+ { "Rights", "lsa.rights", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Account Rights", HFILL }},
+
+ { &hf_lsa_policy_information,
+ { "POLICY INFO", "lsa.policy_information", FT_NONE, BASE_NONE,
+ NULL, 0x0, "Policy Information union", HFILL }},
+
+ { &hf_lsa_attr,
+ { "Attr", "lsa.attr", FT_UINT64, BASE_HEX,
+ NULL, 0x0, "LSA Attributes", HFILL }},
+
+ { &hf_lsa_auth_update,
+ { "Update", "lsa.auth.update", FT_UINT64, BASE_HEX,
+ NULL, 0x0, "LSA Auth Info update", HFILL }},
+
+ { &hf_lsa_resume_handle,
+ { "Resume Handle", "lsa.resume_handle", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Resume Handle", HFILL }},
+
+ { &hf_lsa_trust_direction,
+ { "Trust Direction", "lsa.trust.direction", FT_UINT32, BASE_DEC,
+ VALS(trusted_direction_vals), 0x0, "Trust direction", HFILL }},
+
+ { &hf_lsa_trust_type,
+ { "Trust Type", "lsa.trust.type", FT_UINT32, BASE_DEC,
+ VALS(trusted_type_vals), 0x0, "Trust type", HFILL }},
+
+ { &hf_lsa_trust_attr,
+ { "Trust Attr", "lsa.trust.attr", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Trust attributes", HFILL }},
+
+ { &hf_lsa_trust_attr_non_trans,
+ { "Non Transitive", "lsa.trust.attr.non_trans", FT_BOOLEAN, 32,
+ TFS(&tfs_trust_attr_non_trans), 0x00000001, "Non Transitive trust", HFILL }},
+
+ { &hf_lsa_trust_attr_uplevel_only,
+ { "Upleve only", "lsa.trust.attr.uplevel_only", FT_BOOLEAN, 32,
+ TFS(&tfs_trust_attr_uplevel_only), 0x00000002, "Uplevel only trust", HFILL }},
+
+ { &hf_lsa_trust_attr_tree_parent,
+ { "Tree Parent", "lsa.trust.attr.tree_parent", FT_BOOLEAN, 32,
+ TFS(&tfs_trust_attr_tree_parent), 0x00400000, "Tree Parent trust", HFILL }},
+
+ { &hf_lsa_trust_attr_tree_root,
+ { "Tree Root", "lsa.trust.attr.tree_root", FT_BOOLEAN, 32,
+ TFS(&tfs_trust_attr_tree_root), 0x00800000, "Tree Root trust", HFILL }},
+
+ { &hf_lsa_auth_type,
+ { "Auth Type", "lsa.auth.type", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Auth Info type", HFILL }},
+
+ { &hf_lsa_auth_len,
+ { "Auth Len", "lsa.auth.len", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Auth Info len", HFILL }},
+
+ { &hf_lsa_remove_all,
+ { "Remove All", "lsa.remove_all", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Flag whether all rights should be removed or only the specified ones", HFILL }},
+
+ { &hf_view_local_info,
+ { "View non-sensitive policy information", "lsa.access_mask.view_local_info",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_VIEW_LOCAL_INFORMATION,
+ "View non-sensitive policy information", HFILL }},
+
+ { &hf_view_audit_info,
+ { "View system audit requirements", "lsa.access_mask.view_audit_info",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_VIEW_AUDIT_INFORMATION,
+ "View system audit requirements", HFILL }},
+
+ { &hf_get_private_info,
+ { "Get sensitive policy information", "lsa.access_mask.get_privateinfo",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_GET_PRIVATE_INFORMATION,
+ "Get sensitive policy information", HFILL }},
+
+ { &hf_trust_admin,
+ { "Modify domain trust relationships", "lsa.access_mask.trust_admin",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_TRUST_ADMIN,
+ "Modify domain trust relationships", HFILL }},
+
+ { &hf_create_account,
+ { "Create special accounts (for assignment of user rights)", "lsa.access_mask.create_account",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_CREATE_ACCOUNT,
+ "Create special accounts (for assignment of user rights)", HFILL }},
+
+ { &hf_create_secret,
+ { "Create a secret object", "lsa.access_mask.create_secret",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_CREATE_SECRET,
+ "Create a secret object", HFILL }},
+
+ { &hf_create_priv,
+ { "Create a privilege", "lsa.access_mask.create_priv",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_CREATE_PRIVILEGE,
+ "Create a privilege", HFILL }},
+
+ { &hf_set_default_quota_limits,
+ { "Set default quota limits", "lsa.access_mask.set_default_quota_limits",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_SET_DEFAULT_QUOTA_LIMITS,
+ "Set default quota limits", HFILL }},
+
+ { &hf_set_audit_requirements,
+ { "Change system audit requirements", "lsa.access_mask.set_audit_requirements",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_SET_AUDIT_REQUIREMENTS,
+ "Change system audit requirements", HFILL }},
+
+ { &hf_audit_log_admin,
+ { "Administer audit log attributes", "lsa.access_mask.audit_log_admin",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_AUDIT_LOG_ADMIN,
+ "Administer audit log attributes", HFILL }},
+
+ { &hf_server_admin,
+ { "Enable/Disable LSA", "lsa.access_mask.server_admin",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_SERVER_ADMIN,
+ "Enable/Disable LSA", HFILL }},
+
+ { &hf_lookup_names,
+ { "Lookup Names/SIDs", "lsa.access_mask.lookup_names",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth), POLICY_LOOKUP_NAMES,
+ "Lookup Names/SIDs", HFILL }}
+};
+
+ static gint *ett[] = {
+ &ett_dcerpc_lsa,
+ &ett_lsa_OBJECT_ATTRIBUTES,
+ &ett_LSA_SECURITY_DESCRIPTOR,
+ &ett_lsa_policy_info,
+ &ett_lsa_policy_audit_log_info,
+ &ett_lsa_policy_audit_events_info,
+ &ett_lsa_policy_primary_domain_info,
+ &ett_lsa_policy_primary_account_info,
+ &ett_lsa_policy_server_role_info,
+ &ett_lsa_policy_replica_source_info,
+ &ett_lsa_policy_default_quota_info,
+ &ett_lsa_policy_modification_info,
+ &ett_lsa_policy_audit_full_set_info,
+ &ett_lsa_policy_audit_full_query_info,
+ &ett_lsa_policy_dns_domain_info,
+ &ett_lsa_translated_names,
+ &ett_lsa_translated_name,
+ &ett_lsa_referenced_domain_list,
+ &ett_lsa_trust_information,
+ &ett_lsa_trust_information_ex,
+ &ett_LUID,
+ &ett_LSA_PRIVILEGES,
+ &ett_LSA_PRIVILEGE,
+ &ett_LSA_LUID_AND_ATTRIBUTES_ARRAY,
+ &ett_LSA_LUID_AND_ATTRIBUTES,
+ &ett_LSA_TRUSTED_DOMAIN_LIST,
+ &ett_LSA_TRUSTED_DOMAIN,
+ &ett_LSA_TRANSLATED_SIDS,
+ &ett_lsa_trusted_domain_info,
+ &ett_lsa_trust_attr,
+ &ett_lsa_trusted_domain_auth_information,
+ &ett_lsa_auth_information
+ };
+
+ proto_dcerpc_lsa = proto_register_protocol(
+ "Microsoft Local Security Architecture", "LSA", "lsa");
+
+ proto_register_field_array (proto_dcerpc_lsa, hf, array_length (hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+/* Protocol handoff */
+
+static e_uuid_t uuid_dcerpc_lsa = {
+ 0x12345778, 0x1234, 0xabcd,
+ { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab}
+};
+
+static guint16 ver_dcerpc_lsa = 0;
+
+void
+proto_reg_handoff_dcerpc_lsa(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_lsa, ett_dcerpc_lsa, &uuid_dcerpc_lsa,
+ ver_dcerpc_lsa, dcerpc_lsa_dissectors, hf_lsa_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-lsa.h b/epan/dissectors/packet-dcerpc-lsa.h
new file mode 100644
index 0000000000..3347c34d06
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-lsa.h
@@ -0,0 +1,145 @@
+/* packet-dcerpc-lsa.h
+ * Routines for SMB \PIPE\lsarpc packet disassembly
+ * Copyright 2001, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_LSA_H
+#define __PACKET_DCERPC_LSA_H
+
+#define LSA_LSARCLOSE 0x00
+#define LSA_LSARDELETE 0x01
+#define LSA_LSARENUMERATEPRIVILEGES 0x02
+#define LSA_LSARQUERYSECURITYOBJECT 0x03
+#define LSA_LSARSETSECURITYOBJECT 0x04
+#define LSA_LSARCHANGEPASSWORD 0x05
+#define LSA_LSAROPENPOLICY 0x06
+#define LSA_LSARQUERYINFORMATIONPOLICY 0x07
+#define LSA_LSARSETINFORMATIONPOLICY 0x08
+#define LSA_LSARCLEARAUDITLOG 0x09
+#define LSA_LSARCREATEACCOUNT 0x0a
+#define LSA_LSARENUMERATEACCOUNTS 0x0b
+#define LSA_LSARCREATETRUSTEDDOMAIN 0x0c
+#define LSA_LSARENUMERATETRUSTEDDOMAINS 0x0d
+#define LSA_LSARLOOKUPNAMES 0x0e
+#define LSA_LSARLOOKUPSIDS 0x0f
+#define LSA_LSARCREATESECRET 0x10
+#define LSA_LSAROPENACCOUNT 0x11
+#define LSA_LSARENUMERATEPRIVILEGESACCOUNT 0x12
+#define LSA_LSARADDPRIVILEGESTOACCOUNT 0x13
+#define LSA_LSARREMOVEPRIVILEGESFROMACCOUNT 0x14
+#define LSA_LSARGETQUOTASFORACCOUNT 0x15
+#define LSA_LSARSETQUOTASFORACCOUNT 0x16
+#define LSA_LSARGETSYSTEMACCESSACCOUNT 0x17
+#define LSA_LSARSETSYSTEMACCESSACCOUNT 0x18
+#define LSA_LSAROPENTRUSTEDDOMAIN 0x19
+#define LSA_LSARQUERYINFOTRUSTEDDOMAIN 0x1a
+#define LSA_LSARSETINFORMATIONTRUSTEDDOMAIN 0x1b
+#define LSA_LSAROPENSECRET 0x1c
+#define LSA_LSARSETSECRET 0x1d
+#define LSA_LSARQUERYSECRET 0x1e
+#define LSA_LSARLOOKUPPRIVILEGEVALUE 0x1f
+#define LSA_LSARLOOKUPPRIVILEGENAME 0x20
+#define LSA_LSARLOOKUPPRIVILEGEDISPLAYNAME 0x21
+#define LSA_LSARDELETEOBJECT 0x22
+#define LSA_LSARENUMERATEACCOUNTSWITHUSERRIGHT 0x23
+#define LSA_LSARENUMERATEACCOUNTRIGHTS 0x24
+#define LSA_LSARADDACCOUNTRIGHTS 0x25
+#define LSA_LSARREMOVEACCOUNTRIGHTS 0x26
+#define LSA_LSARQUERYTRUSTEDDOMAININFO 0x27
+#define LSA_LSARSETTRUSTEDDOMAININFO 0x28
+#define LSA_LSARDELETETRUSTEDDOMAIN 0x29
+#define LSA_LSARSTOREPRIVATEDATA 0x2a
+#define LSA_LSARRETRIEVEPRIVATEDATA 0x2b
+#define LSA_LSAROPENPOLICY2 0x2c
+#define LSA_LSARGETUSERNAME 0x2d
+#define LSA_LSARQUERYINFORMATIONPOLICY2 0x2e
+#define LSA_LSARSETINFORMATIONPOLICY2 0x2f
+#define LSA_LSARQUERYTRUSTEDDOMAININFOBYNAME 0x30
+#define LSA_LSARSETTRUSTEDDOMAININFOBYNAME 0x31
+#define LSA_LSARENUMERATETRUSTEDDOMAINSEX 0x32
+#define LSA_LSARCREATETRUSTEDDOMAINEX 0x33
+#define LSA_LSARCLOSETRUSTEDDOMAINEX 0x34
+#define LSA_LSARQUERYDOMAININFORMATIONPOLICY 0x35
+#define LSA_LSARSETDOMAININFORMATIONPOLICY 0x36
+#define LSA_LSAROPENTRUSTEDDOMAINBYNAME 0x37
+#define LSA_LSARTESTCALL 0x38
+#define LSA_LSARLOOKUPSIDS2 0x39
+#define LSA_LSARLOOKUPNAMES2 0x3a
+#define LSA_LSARCREATETRUSTEDDOMAINEX2 0x3b
+#define LSA_CREDRWRITE 0x3c
+#define LSA_CREDRREAD 0x3d
+#define LSA_CREDRENUMERATE 0x3e
+#define LSA_CREDRWRITEDOMAINCREDENTIALS 0x3f
+#define LSA_CREDRREADDOMAINCREDENTIALS 0x40
+#define LSA_CREDRDELETE 0x41
+#define LSA_CREDRGETTARGETINFO 0x42
+#define LSA_CREDRPROFILELOADED 0x43
+#define LSA_LSARLOOKUPNAMES3 0x44
+#define LSA_CREDRGETSESSIONTYPES 0x45
+#define LSA_LSARREGISTERAUDITEVENT 0x46
+#define LSA_LSARGENAUDITEVENT 0x47
+#define LSA_LSARUNREGISTERAUDITEVENT 0x48
+#define LSA_LSARQUERYFORESTTRUSTINFORMATION 0x49
+#define LSA_LSARSETFORESTTRUSTINFORMATION 0x4a
+#define LSA_CREDRRENAME 0x4b
+#define LSA_LSARLOOKUPSIDS3 0x4c
+#define LSA_LSARLOOKUPNAMES4 0x4d
+#define LSA_LSAROPENPOLICYSCE 0x4e
+#define LSA_LSARADTREGISTERSECURITYEVENTSOURCE 0x4f
+#define LSA_LSARADTUNREGISTERSECURITYEVENTSOURCE 0x50
+#define LSA_LSARADTREPORTSECURITYEVENT 0x51
+
+int
+lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep);
+int
+lsa_dissect_LSA_SECURITY_DESCRIPTOR_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep);
+int
+lsa_dissect_LSA_SECRET(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep);
+
+int
+lsa_dissect_POLICY_DNS_DOMAIN_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep);
+
+/* Specific access rights */
+
+#define POLICY_VIEW_LOCAL_INFORMATION 0x00000001
+#define POLICY_VIEW_AUDIT_INFORMATION 0x00000002
+#define POLICY_GET_PRIVATE_INFORMATION 0x00000004
+#define POLICY_TRUST_ADMIN 0x00000008
+#define POLICY_CREATE_ACCOUNT 0x00000010
+#define POLICY_CREATE_SECRET 0x00000020
+#define POLICY_CREATE_PRIVILEGE 0x00000040
+#define POLICY_SET_DEFAULT_QUOTA_LIMITS 0x00000080
+#define POLICY_SET_AUDIT_REQUIREMENTS 0x00000100
+#define POLICY_AUDIT_LOG_ADMIN 0x00000200
+#define POLICY_SERVER_ADMIN 0x00000400
+#define POLICY_LOOKUP_NAMES 0x00000800
+
+#endif /* packet-dcerpc-lsa.h */
diff --git a/epan/dissectors/packet-dcerpc-mapi.c b/epan/dissectors/packet-dcerpc-mapi.c
new file mode 100644
index 0000000000..5792f418e0
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-mapi.c
@@ -0,0 +1,476 @@
+/* packet-dcerpc-mapi.c
+ * Routines for MS Exchange MAPI
+ * Copyright 2002, Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-mapi.h"
+#include "smb.h" /* for "NT_errors[]" */
+#include "prefs.h"
+
+static int proto_dcerpc_mapi = -1;
+static int hf_mapi_opnum = -1;
+static int hf_mapi_unknown_string = -1;
+static int hf_mapi_unknown_short = -1;
+static int hf_mapi_unknown_long = -1;
+static int hf_mapi_hnd = -1;
+static int hf_mapi_rc = -1;
+static int hf_mapi_encap_datalen = -1;
+static int hf_mapi_encrypted_data = -1;
+static int hf_mapi_decrypted_data_maxlen = -1;
+static int hf_mapi_decrypted_data_offset = -1;
+static int hf_mapi_decrypted_data_len = -1;
+static int hf_mapi_decrypted_data = -1;
+static int hf_mapi_pdu_len = -1;
+static int hf_mapi_pdu_trailer = -1;
+static int hf_mapi_pdu_extra_trailer = -1;
+
+static gint ett_dcerpc_mapi = -1;
+static gint ett_mapi_decrypted_pdu = -1;
+
+static e_uuid_t uuid_dcerpc_mapi = {
+ 0xa4f1db00, 0xca47, 0x1067,
+ { 0xb3, 0x1f, 0x00, 0xdd, 0x01, 0x06, 0x62, 0xda }
+};
+
+static guint16 ver_dcerpc_mapi = 0;
+
+#define DISSECT_UNKNOWN(len) \
+ {\
+ proto_tree_add_text(tree, tvb, offset, len,\
+ "unknown data (%d byte%s)", len,\
+ plurality(len, "", "s"));\
+ offset += len;\
+ }
+
+/* decryption */
+static gboolean mapi_decrypt = FALSE;
+static GMemChunk *mapi_decrypted_data_chunk = NULL;
+static int mapi_decrypted_data_init_count = 200;
+static GHashTable *mapi_decrypted_table = NULL;
+typedef struct {
+ guint32 frame;
+ guint32 callid;
+ tvbuff_t *tvb;
+ unsigned char *data;
+} mapi_decrypted_data_t;
+
+static gboolean
+free_all_decrypted(gpointer key_arg, gpointer value _U_, gpointer user_data _U_)
+{
+ mapi_decrypted_data_t *mdd=(mapi_decrypted_data_t *)key_arg;
+
+ if(mdd->tvb){
+ tvb_free(mdd->tvb);
+ mdd->tvb=NULL;
+ }
+ if(mdd->data){
+ g_free(mdd->data);
+ mdd->data=NULL;
+ }
+ return TRUE;
+}
+static guint
+mapi_decrypt_hash(gconstpointer k)
+{
+ const mapi_decrypted_data_t *mdd=(const mapi_decrypted_data_t *)k;
+ return mdd->frame;
+}
+static gint
+mapi_decrypt_equal(gconstpointer k1, gconstpointer k2)
+{
+ const mapi_decrypted_data_t *mdd1=(const mapi_decrypted_data_t *)k1;
+ const mapi_decrypted_data_t *mdd2=(const mapi_decrypted_data_t *)k2;
+
+ return ( (mdd1->frame==mdd2->frame)
+ &&(mdd1->callid==mdd2->callid) );
+}
+static void
+mapi_decrypt_init(void)
+{
+ if(mapi_decrypted_table){
+ g_hash_table_foreach_remove(mapi_decrypted_table,
+ free_all_decrypted, NULL);
+ } else {
+ mapi_decrypted_table=g_hash_table_new(mapi_decrypt_hash,
+ mapi_decrypt_equal);
+ }
+
+ if(mapi_decrypted_data_chunk){
+ g_mem_chunk_destroy(mapi_decrypted_data_chunk);
+ mapi_decrypted_data_chunk=NULL;
+ }
+
+ if(mapi_decrypt){
+ mapi_decrypted_data_chunk=g_mem_chunk_new("mapi_decrypt_chunk",
+ sizeof(mapi_decrypted_data_t),
+ mapi_decrypted_data_init_count*sizeof(mapi_decrypted_data_t),
+ G_ALLOC_ONLY);
+ }
+}
+
+
+static int
+mapi_decrypt_pdu(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di;
+ mapi_decrypted_data_t *mmd=NULL;
+ guint32 len;
+ const unsigned char *ptr;
+ guint32 i;
+ guint16 pdu_len;
+ proto_item *it = NULL;
+ proto_tree *tr = NULL;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ return offset;
+ }
+
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_mapi_decrypted_data_maxlen, NULL);
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_mapi_decrypted_data_offset, NULL);
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_mapi_decrypted_data_len, &len);
+
+ if(len>(guint32)tvb_length_remaining(tvb, offset)){
+ len=tvb_length_remaining(tvb, offset);
+ }
+
+ if(!pinfo->fd->flags.visited){
+ ptr=(const unsigned char *)tvb_get_ptr(tvb, offset, len);
+ mmd=g_mem_chunk_alloc(mapi_decrypted_data_chunk);
+ mmd->callid=di->call_id;
+ mmd->frame=pinfo->fd->num;
+ mmd->data=g_malloc(len);
+ for(i=0;i<len;i++){
+ mmd->data[i]=ptr[i]^0xa5;
+ }
+ mmd->tvb=tvb_new_real_data(mmd->data, len, len);
+ g_hash_table_insert(mapi_decrypted_table, mmd, mmd);
+ }
+
+ if(!mmd){
+ mapi_decrypted_data_t mmd_key;
+ mmd_key.callid=di->call_id;
+ mmd_key.frame=pinfo->fd->num;
+ mmd=g_hash_table_lookup(mapi_decrypted_table, &mmd_key);
+ }
+
+ add_new_data_source(pinfo, mmd->tvb, "Decrypted MAPI");
+
+ /* decrypted PDU */
+ /* All from 10 minutes eyeballing. This may be wrong.
+ The PDU is NOT NDR encoded. So this completely new marshalling
+ used by MAPI needs to be figured out.
+
+ It seems that ASCII text strings always are NULL terminated,
+ also no obvious string-length-byte can be seen so it seems the
+ length of strings are determined by searching the terminating null
+ byte.
+
+ The first two bytes of the PDU is the length of the PDU including
+ the two length bytes.
+ The third byte may be a subcommand byte ?
+
+ After the PDU comes, in requests a 4 byte thing. Which is either
+ (not very often) 0xffffffff or something else. If it is
+ 'something else' these four bytes are repeated for the matching
+ response packet.
+ In some repsonse packets, this 4 byte trailer are sometimes followed
+ by some other data. Unclear if this is just random padding or actual
+ data. Seems a bit non-random for padding though.
+
+ Some response packets have a PDU of 2 bytes only, ie only the
+ 2 byte length field followed by the 4 byte trailer.
+ strange.
+ perhaps the 4 byte trailers, and the extra trailers have some
+ special meaning?
+ More work needs to be done in this area.
+ */
+ it=proto_tree_add_text(tree, mmd->tvb, 0, len, "Decrypted MAPI PDU");
+ tr=proto_item_add_subtree(it, ett_mapi_decrypted_pdu);
+
+ pdu_len=tvb_get_letohs(mmd->tvb, 0);
+ proto_tree_add_uint(tr, hf_mapi_pdu_len, mmd->tvb, 0, 2, pdu_len);
+
+ /*XXX call dissector here */
+ proto_tree_add_item(tr, hf_mapi_decrypted_data, mmd->tvb, 2, pdu_len-2, FALSE);
+
+ proto_tree_add_item(tr, hf_mapi_pdu_trailer, mmd->tvb, pdu_len, 4, FALSE);
+ if(len>((guint32)pdu_len+4)){
+ proto_tree_add_item(tr, hf_mapi_pdu_extra_trailer, mmd->tvb, pdu_len+4, len-(pdu_len+4), FALSE);
+ }
+
+
+ offset+=len;
+
+ return offset;
+}
+
+static int
+mapi_logon_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint8), hf_mapi_unknown_string, TRUE, NULL);
+
+ DISSECT_UNKNOWN(tvb_length_remaining(tvb, offset));
+
+ return offset;
+}
+
+/* The strings in this function are decoded properly on seen captures.
+There might be offsets/padding mismatched due to potential pointer expansions
+or padding bytes. Captures where this code breaks will tell us about that */
+static int
+mapi_logon_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
+
+ DISSECT_UNKNOWN(20); /* this is 20 bytes, unless there are pointers */
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint8), hf_mapi_unknown_string, TRUE, NULL);
+
+ /* Was DISSECT_UNKNOWN(6), but the 1 or 2 bytes the comment that
+ was here referred to probably were padding, if they were seen;
+ in another capture, there are 5 bytes there - it's probably a
+ 4-byte quantity, always aligned on a 4-byte boundary. */
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_mapi_unknown_long, NULL);
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint8), hf_mapi_unknown_string, TRUE, NULL);
+
+ DISSECT_UNKNOWN( tvb_length_remaining(tvb, offset)-4 );
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_mapi_rc, NULL);
+
+ return offset;
+}
+
+static int
+mapi_ec_do_rpc_request(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
+
+ if(!mapi_decrypt){
+ /* this is a unidimensional varying and conformant array of
+ encrypted data */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_byte_array, NDR_POINTER_REF,
+ "Encrypted data", hf_mapi_encrypted_data);
+ } else {
+ offset = mapi_decrypt_pdu(tvb, offset, pinfo, tree, drep);
+ }
+
+ /* length of encrypted data. */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_mapi_encap_datalen, NULL);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_mapi_unknown_short, NULL);
+
+ return offset;
+}
+static int
+mapi_ec_do_rpc_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
+
+ if(!mapi_decrypt){
+ /* this is a unidimensional varying and conformant array of
+ encrypted data */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_byte_array, NDR_POINTER_REF,
+ "Encrypted data", hf_mapi_encrypted_data);
+ } else {
+ offset = mapi_decrypt_pdu(tvb, offset, pinfo, tree, drep);
+ }
+
+ /* length of encrypted data */
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_mapi_encap_datalen, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_mapi_rc, NULL);
+
+ return offset;
+}
+
+static int
+mapi_logoff_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+mapi_logoff_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_mapi_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_mapi_rc, NULL);
+
+ return offset;
+}
+
+
+static dcerpc_sub_dissector dcerpc_mapi_dissectors[] = {
+ { MAPI_EC_DO_CONNECT, "EcDoConnect",
+ mapi_logon_rqst,
+ mapi_logon_reply },
+ { MAPI_EC_DO_DISCONNECT,"EcDoDisconnect",
+ mapi_logoff_rqst,
+ mapi_logoff_reply },
+ { MAPI_EC_DO_RPC, "EcDoRpc",
+ mapi_ec_do_rpc_request,
+ mapi_ec_do_rpc_reply },
+ { MAPI_EC_GET_MORE_RPC, "EcGetMoreRpc", NULL, NULL },
+ { MAPI_EC_REGISTER_PUSH_NOTIFICATION, "EcRRegisterPushNotification",
+ NULL, NULL },
+ { MAPI_EC_UNREGISTER_PUSH_NOTIFICATION, "EcRUnregisterPushNotification",
+ NULL, NULL },
+ { MAPI_EC_DUMMY_RPC, "EcDummyRpc", NULL, NULL },
+ { MAPI_EC_GET_DC_NAME, "EcRGetDCName", NULL, NULL },
+ { MAPI_EC_NET_GET_DC_NAME, "EcRNetGetDCName", NULL, NULL },
+ { MAPI_EC_DO_RPC_EXT, "EcDoRpcExt", NULL, NULL },
+ {0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_mapi(void)
+{
+
+static hf_register_info hf[] = {
+ { &hf_mapi_opnum,
+ { "Operation", "mapi.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_mapi_hnd,
+ { "Context Handle", "mapi.hnd", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_mapi_rc,
+ { "Return code", "mapi.rc", FT_UINT32, BASE_HEX,
+ VALS (NT_errors), 0x0, "", HFILL }},
+
+ { &hf_mapi_unknown_string,
+ { "Unknown string", "mapi.unknown_string", FT_STRING, BASE_NONE,
+ NULL, 0, "Unknown string. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_mapi_unknown_short,
+ { "Unknown short", "mapi.unknown_short", FT_UINT16, BASE_HEX,
+ NULL, 0, "Unknown short. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_mapi_unknown_long,
+ { "Unknown long", "mapi.unknown_long", FT_UINT32, BASE_HEX,
+ NULL, 0, "Unknown long. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_mapi_encap_datalen,
+ { "Length", "mapi.encap_len", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of encapsulated/encrypted data", HFILL }},
+
+ { &hf_mapi_encrypted_data,
+ { "Encrypted data", "mapi.encrypted_data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Encrypted data", HFILL }},
+
+ { &hf_mapi_decrypted_data_maxlen,
+ { "Max Length", "mapi.decrypted.data.maxlen", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Maximum size of buffer for decrypted data", HFILL }},
+
+ { &hf_mapi_decrypted_data_offset,
+ { "Offset", "mapi.decrypted.data.offset", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Offset into buffer for decrypted data", HFILL }},
+
+ { &hf_mapi_decrypted_data_len,
+ { "Length", "mapi.decrypted.data.len", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Used size of buffer for decrypted data", HFILL }},
+
+ { &hf_mapi_decrypted_data,
+ { "Decrypted data", "mapi.decrypted.data", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Decrypted data", HFILL }},
+
+ { &hf_mapi_pdu_len,
+ { "Length", "mapi.pdu.len", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Size of the command PDU", HFILL }},
+
+ { &hf_mapi_pdu_trailer,
+ { "Trailer", "mapi.pdu.trailer", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "If you know what this is, contact ethereal developers", HFILL }},
+
+ { &hf_mapi_pdu_extra_trailer,
+ { "unknown", "mapi.pdu.extra_trailer", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "If you know what this is, contact ethereal developers", HFILL }}
+ };
+
+
+ static gint *ett[] = {
+ &ett_dcerpc_mapi,
+ &ett_mapi_decrypted_pdu
+ };
+ module_t *mapi_module;
+
+ proto_dcerpc_mapi = proto_register_protocol(
+ "Microsoft Exchange MAPI", "MAPI", "mapi");
+
+ proto_register_field_array(proto_dcerpc_mapi, hf,
+ array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ mapi_module = prefs_register_protocol(proto_dcerpc_mapi, NULL);
+ prefs_register_bool_preference(mapi_module, "decrypt",
+ "Decrypt MAPI PDUs",
+ "Whether the dissector should decrypt MAPI PDUs",
+ &mapi_decrypt);
+ register_init_routine(mapi_decrypt_init);
+}
+
+void
+proto_reg_handoff_dcerpc_mapi(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_mapi, ett_dcerpc_mapi,
+ &uuid_dcerpc_mapi, ver_dcerpc_mapi,
+ dcerpc_mapi_dissectors, hf_mapi_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-mapi.h b/epan/dissectors/packet-dcerpc-mapi.h
new file mode 100644
index 0000000000..ca92d508e9
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-mapi.h
@@ -0,0 +1,41 @@
+/* packet-dcerpc-mapi.h
+ * Routines for MS Exchange MAPI dissection
+ * Copyright 2002, Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_MAPI_H
+#define __PACKET_DCERPC_MAPI_H
+
+#define MAPI_EC_DO_CONNECT 0x00
+#define MAPI_EC_DO_DISCONNECT 0x01
+#define MAPI_EC_DO_RPC 0x02
+#define MAPI_EC_GET_MORE_RPC 0x03
+#define MAPI_EC_REGISTER_PUSH_NOTIFICATION 0x04
+#define MAPI_EC_UNREGISTER_PUSH_NOTIFICATION 0x05
+#define MAPI_EC_DUMMY_RPC 0x06
+#define MAPI_EC_GET_DC_NAME 0x07
+#define MAPI_EC_NET_GET_DC_NAME 0x08
+#define MAPI_EC_DO_RPC_EXT 0x09
+
+
+#endif
diff --git a/epan/dissectors/packet-dcerpc-messenger.c b/epan/dissectors/packet-dcerpc-messenger.c
new file mode 100644
index 0000000000..757fe2fb02
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-messenger.c
@@ -0,0 +1,147 @@
+/* packet-dcerpc-messenger.c
+ * Routines for SMB \PIPE\msgsvc packet disassembly
+ * Copyright 2003 Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include "prefs.h"
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "smb.h"
+
+
+static int proto_dcerpc_messenger = -1;
+static int hf_messenger_opnum = -1;
+static int hf_messenger_rc = -1;
+static int hf_messenger_server = -1;
+static int hf_messenger_client = -1;
+static int hf_messenger_message = -1;
+
+static gint ett_dcerpc_messenger = -1;
+
+
+/* Windows messenger service listens on two endpoints:
+ * \pipe\msgsvc named pipe
+ * a dynamic UDP port
+ */
+
+static e_uuid_t uuid_dcerpc_messenger = {
+ 0x5a7b91f8, 0xff00, 0x11d0,
+ { 0xa9, 0xb2, 0x00, 0xc0, 0x4f, 0xb6, 0xe6, 0xfc}
+};
+
+static guint16 ver_dcerpc_messenger = 1;
+
+
+
+/*
+ * IDL [in][string][ref] char *server;
+ * IDL [in][string][ref] char *client;
+ * IDL [in][string][ref] char *message;
+ */
+static int
+messenger_dissect_send_message_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_char_cvstring, NDR_POINTER_REF,
+ "Server", hf_messenger_server);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_char_cvstring, NDR_POINTER_REF,
+ "Client", hf_messenger_client);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_char_cvstring, NDR_POINTER_REF,
+ "Message", hf_messenger_message);
+
+
+ return offset;
+}
+static int
+messenger_dissect_send_message_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_messenger_rc, NULL);
+
+ return offset;
+}
+
+
+
+static dcerpc_sub_dissector dcerpc_messenger_dissectors[] = {
+ {0, "NetrSendMessage",
+ messenger_dissect_send_message_rqst,
+ messenger_dissect_send_message_reply },
+ {0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_messenger(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_messenger_opnum,
+ { "Operation", "messenger.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ { &hf_messenger_rc,
+ { "Return code", "messenger.rc", FT_UINT32, BASE_HEX, VALS (NT_errors), 0x0, "", HFILL }},
+
+ { &hf_messenger_server, {
+ "Server", "messenger.server",
+ FT_STRING, BASE_NONE, NULL, 0, "Server to send the message to", HFILL }},
+
+ { &hf_messenger_client, {
+ "Client", "messenger.client",
+ FT_STRING, BASE_NONE, NULL, 0, "Client that sent the message", HFILL }},
+
+ { &hf_messenger_message, {
+ "Message", "messenger.message",
+ FT_STRING, BASE_NONE, NULL, 0, "The message being sent", HFILL }}
+
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_messenger
+ };
+
+ proto_dcerpc_messenger = proto_register_protocol(
+ "Microsoft Messenger Service", "Messenger", "messenger");
+
+ proto_register_field_array (proto_dcerpc_messenger, hf, array_length (hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_dcerpc_messenger(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_messenger, ett_dcerpc_messenger, &uuid_dcerpc_messenger,
+ ver_dcerpc_messenger, dcerpc_messenger_dissectors, hf_messenger_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-mgmt.c b/epan/dissectors/packet-dcerpc-mgmt.c
new file mode 100644
index 0000000000..ac4f3e56a5
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-mgmt.c
@@ -0,0 +1,80 @@
+/* packet-dcerpc-mgmt.c
+ * Routines for dcerpc mgmt dissection
+ * Copyright 2001, Todd Sabin <tas@webspan.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_mgmt = -1;
+static int hf_opnum = -1;
+
+static gint ett_mgmt = -1;
+
+
+static e_uuid_t uuid_mgmt = { 0xafa8bd80, 0x7d8a, 0x11c9, { 0xbe, 0xf4, 0x08, 0x00, 0x2b, 0x10, 0x29, 0x89 } };
+static guint16 ver_mgmt = 1;
+
+
+static dcerpc_sub_dissector mgmt_dissectors[] = {
+ { 0, "rpc__mgmt_inq_if_ids", NULL, NULL },
+ { 1, "rpc__mgmt_inq_stats", NULL, NULL },
+ { 2, "rpc__mgmt_is_server_listening", NULL, NULL },
+ { 3, "rpc__mgmt_stop_server_listening", NULL, NULL },
+ { 4, "rpc__mgmt_inq_princ_name", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+
+void
+proto_register_mgmt (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_opnum,
+ { "Operation", "mgmt.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_mgmt
+ };
+ proto_mgmt = proto_register_protocol ("DCE/RPC Remote Management", "MGMT", "mgmt");
+ proto_register_field_array (proto_mgmt, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_mgmt (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_mgmt, ett_mgmt, &uuid_mgmt, ver_mgmt, mgmt_dissectors, hf_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-ndr.c b/epan/dissectors/packet-dcerpc-ndr.c
new file mode 100644
index 0000000000..df2193ca72
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-ndr.c
@@ -0,0 +1,273 @@
+/* packet-dcerpc-ndr.c
+ * Routines for DCERPC NDR dissection
+ * Copyright 2001, Todd Sabin <tas@webspan.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+/*
+ * The NDR routines are for use by dcerpc subdissetors. They're
+ * primarily for making sure things are aligned properly according
+ * to the rules of NDR.
+ */
+
+int
+dissect_ndr_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint8 *pdata)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ /* no alignment needed */
+ return dissect_dcerpc_uint8 (tvb, offset, pinfo,
+ tree, drep, hfindex, pdata);
+}
+
+int
+dissect_ndr_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint16 *pdata)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+
+ if (offset % 2) {
+ offset++;
+ }
+ return dissect_dcerpc_uint16 (tvb, offset, pinfo,
+ tree, drep, hfindex, pdata);
+}
+
+int
+dissect_ndr_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+
+ if (offset % 4) {
+ offset += 4 - (offset % 4);
+ }
+ return dissect_dcerpc_uint32 (tvb, offset, pinfo,
+ tree, drep, hfindex, pdata);
+}
+
+int
+dissect_ndr_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, unsigned char *pdata)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ if (offset % 4) {
+ offset += 4 - (offset % 4);
+ }
+ return dissect_dcerpc_uint64 (tvb, offset, pinfo,
+ tree, drep, hfindex, pdata);
+}
+
+
+int
+dissect_ndr_float(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, gfloat *pdata)
+{
+ dcerpc_info *di;
+
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ if (offset % 4) {
+ offset += 4 - (offset % 4);
+ }
+ return dissect_dcerpc_float(tvb, offset, pinfo,
+ tree, drep, hfindex, pdata);
+}
+
+
+int
+dissect_ndr_double(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, gdouble *pdata)
+{
+ dcerpc_info *di;
+
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ if (offset % 8) {
+ offset += 8 - (offset % 8);
+ }
+ return dissect_dcerpc_double(tvb, offset, pinfo,
+ tree, drep, hfindex, pdata);
+}
+
+/* handles unix 32 bit time_t */
+int
+dissect_ndr_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+
+ if (offset % 4) {
+ offset += 4 - (offset % 4);
+ }
+ return dissect_dcerpc_time_t (tvb, offset, pinfo,
+ tree, drep, hfindex, pdata);
+}
+
+int
+dissect_ndr_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, e_uuid_t *pdata)
+{
+ e_uuid_t uuid;
+ dcerpc_info *di;
+ char uuid_str[DCERPC_UUID_STR_LEN];
+ int uuid_str_len;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ /* uuid's are aligned to 4 bytes, due to initial uint32 in struct */
+ if (offset % 4) {
+ offset += 4 - (offset % 4);
+ }
+ dcerpc_tvb_get_uuid (tvb, offset, drep, &uuid);
+ if (tree) {
+ /*
+ * XXX - look up the UUID to see if it's registered, and use
+ * the name of the protocol? Unfortunately, we need the version
+ * as well.
+ */
+ uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.Data1, uuid.Data2, uuid.Data3,
+ uuid.Data4[0], uuid.Data4[1],
+ uuid.Data4[2], uuid.Data4[3],
+ uuid.Data4[4], uuid.Data4[5],
+ uuid.Data4[6], uuid.Data4[7]);
+ if (uuid_str_len >= DCERPC_UUID_STR_LEN)
+ memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
+ proto_tree_add_string_format (tree, hfindex, tvb, offset, 16,
+ uuid_str, "%s: %s",
+ proto_registrar_get_name(hfindex),
+ uuid_str);
+ }
+ if (pdata) {
+ *pdata = uuid;
+ }
+ return offset + 16;
+}
+
+/*
+ * XXX - at least according to the DCE RPC 1.1 "nbase.idl", an
+ * "ndr_context_handle" is an unsigned32 "context_handle_attributes"
+ * and a uuid_t "context_handle_uuid". The attributes do not appear to
+ * be used, and always appear to be set to 0, in the DCE RPC 1.1 code.
+ *
+ * Should we display an "ndr_context_handle" with a tree holding the
+ * attributes and the uuid_t?
+ */
+int
+dissect_ndr_ctx_hnd (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, e_ctx_hnd *pdata)
+{
+ static e_ctx_hnd ctx_hnd;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ if (offset % 4) {
+ offset += 4 - (offset % 4);
+ }
+ ctx_hnd.attributes = dcerpc_tvb_get_ntohl (tvb, offset, drep);
+ dcerpc_tvb_get_uuid (tvb, offset+4, drep, &ctx_hnd.uuid);
+ if (tree) {
+ /* Bytes is bytes - don't worry about the data representation */
+ proto_tree_add_item (tree, hfindex, tvb, offset, 20, FALSE);
+ }
+ if (pdata) {
+ *pdata = ctx_hnd;
+ }
+ return offset + 20;
+}
diff --git a/epan/dissectors/packet-dcerpc-netlogon.c b/epan/dissectors/packet-dcerpc-netlogon.c
new file mode 100644
index 0000000000..7f06a040ac
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-netlogon.c
@@ -0,0 +1,7666 @@
+/* packet-dcerpc-netlogon.c
+ * Routines for SMB \PIPE\NETLOGON packet disassembly
+ * Copyright 2001,2003 Tim Potter <tpot@samba.org>
+ * 2002 structure and command dissectors by Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-netlogon.h"
+#include "smb.h" /* for "NT_errors[]" */
+#include "packet-smb-common.h"
+#include "packet-dcerpc-lsa.h"
+
+static int proto_dcerpc_netlogon = -1;
+static int hf_netlogon_group_attrs_mandatory = -1;
+static int hf_netlogon_group_attrs_enabled_by_default = -1;
+static int hf_netlogon_group_attrs_enabled = -1;
+static int hf_netlogon_opnum = -1;
+static int hf_netlogon_guid = -1;
+static int hf_netlogon_rc = -1;
+static int hf_netlogon_len = -1;
+static int hf_netlogon_sensitive_data_flag = -1;
+static int hf_netlogon_sensitive_data_len = -1;
+static int hf_netlogon_sensitive_data = -1;
+static int hf_netlogon_security_information = -1;
+static int hf_netlogon_dummy = -1;
+static int hf_netlogon_neg_flags = -1;
+static int hf_netlogon_minworkingsetsize = -1;
+static int hf_netlogon_maxworkingsetsize = -1;
+static int hf_netlogon_pagedpoollimit = -1;
+static int hf_netlogon_pagefilelimit = -1;
+static int hf_netlogon_timelimit = -1;
+static int hf_netlogon_nonpagedpoollimit = -1;
+static int hf_netlogon_pac_size = -1;
+static int hf_netlogon_pac_data = -1;
+static int hf_netlogon_auth_size = -1;
+static int hf_netlogon_auth_data = -1;
+static int hf_netlogon_cipher_len = -1;
+static int hf_netlogon_cipher_maxlen = -1;
+static int hf_netlogon_cipher_current_data = -1;
+static int hf_netlogon_cipher_current_set_time = -1;
+static int hf_netlogon_cipher_old_data = -1;
+static int hf_netlogon_cipher_old_set_time = -1;
+static int hf_netlogon_priv = -1;
+static int hf_netlogon_privilege_entries = -1;
+static int hf_netlogon_privilege_control = -1;
+static int hf_netlogon_privilege_name = -1;
+static int hf_netlogon_systemflags = -1;
+static int hf_netlogon_pdc_connection_status = -1;
+static int hf_netlogon_tc_connection_status = -1;
+static int hf_netlogon_restart_state = -1;
+static int hf_netlogon_attrs = -1;
+static int hf_netlogon_count = -1;
+static int hf_netlogon_entries = -1;
+static int hf_netlogon_minpasswdlen = -1;
+static int hf_netlogon_passwdhistorylen = -1;
+static int hf_netlogon_level16 = -1;
+static int hf_netlogon_validation_level = -1;
+static int hf_netlogon_reference = -1;
+static int hf_netlogon_next_reference = -1;
+static int hf_netlogon_timestamp = -1;
+static int hf_netlogon_level = -1;
+static int hf_netlogon_challenge = -1;
+static int hf_netlogon_reserved = -1;
+static int hf_netlogon_audit_retention_period = -1;
+static int hf_netlogon_auditing_mode = -1;
+static int hf_netlogon_max_audit_event_count = -1;
+static int hf_netlogon_event_audit_option = -1;
+static int hf_netlogon_unknown_string = -1;
+static int hf_netlogon_unknown_long = -1;
+static int hf_netlogon_unknown_short = -1;
+static int hf_netlogon_unknown_char = -1;
+static int hf_netlogon_logon_time = -1;
+static int hf_netlogon_logoff_time = -1;
+static int hf_netlogon_last_logoff_time = -1;
+static int hf_netlogon_kickoff_time = -1;
+static int hf_netlogon_pwd_age = -1;
+static int hf_netlogon_pwd_last_set_time = -1;
+static int hf_netlogon_pwd_can_change_time = -1;
+static int hf_netlogon_pwd_must_change_time = -1;
+static int hf_netlogon_nt_chal_resp = -1;
+static int hf_netlogon_lm_chal_resp = -1;
+static int hf_netlogon_credential = -1;
+static int hf_netlogon_acct_name = -1;
+static int hf_netlogon_acct_desc = -1;
+static int hf_netlogon_group_desc = -1;
+static int hf_netlogon_full_name = -1;
+static int hf_netlogon_comment = -1;
+static int hf_netlogon_parameters = -1;
+static int hf_netlogon_logon_script = -1;
+static int hf_netlogon_profile_path = -1;
+static int hf_netlogon_home_dir = -1;
+static int hf_netlogon_dir_drive = -1;
+static int hf_netlogon_logon_count = -1;
+static int hf_netlogon_logon_count16 = -1;
+static int hf_netlogon_bad_pw_count = -1;
+static int hf_netlogon_bad_pw_count16 = -1;
+static int hf_netlogon_user_rid = -1;
+static int hf_netlogon_alias_rid = -1;
+static int hf_netlogon_group_rid = -1;
+static int hf_netlogon_logon_srv = -1;
+static int hf_netlogon_principal = -1;
+static int hf_netlogon_logon_dom = -1;
+static int hf_netlogon_resourcegroupcount = -1;
+static int hf_netlogon_downlevel_domain_name = -1;
+static int hf_netlogon_dns_domain_name = -1;
+static int hf_netlogon_domain_name = -1;
+static int hf_netlogon_domain_create_time = -1;
+static int hf_netlogon_domain_modify_time = -1;
+static int hf_netlogon_modify_count = -1;
+static int hf_netlogon_db_modify_time = -1;
+static int hf_netlogon_db_create_time = -1;
+static int hf_netlogon_oem_info = -1;
+static int hf_netlogon_serial_number = -1;
+static int hf_netlogon_num_rids = -1;
+static int hf_netlogon_num_trusts = -1;
+static int hf_netlogon_num_controllers = -1;
+static int hf_netlogon_num_other_groups = -1;
+static int hf_netlogon_computer_name = -1;
+static int hf_netlogon_site_name = -1;
+static int hf_netlogon_trusted_dc_name = -1;
+static int hf_netlogon_dc_name = -1;
+static int hf_netlogon_dc_site_name = -1;
+static int hf_netlogon_dns_forest_name = -1;
+static int hf_netlogon_dc_address = -1;
+static int hf_netlogon_dc_address_type = -1;
+static int hf_netlogon_client_site_name = -1;
+static int hf_netlogon_workstation = -1;
+static int hf_netlogon_workstation_site_name = -1;
+static int hf_netlogon_workstation_os = -1;
+static int hf_netlogon_workstations = -1;
+static int hf_netlogon_workstation_fqdn = -1;
+static int hf_netlogon_group_name = -1;
+static int hf_netlogon_alias_name = -1;
+static int hf_netlogon_country = -1;
+static int hf_netlogon_codepage = -1;
+static int hf_netlogon_flags = -1;
+static int hf_netlogon_trust_attribs = -1;
+static int hf_netlogon_trust_type = -1;
+static int hf_netlogon_trust_flags = -1;
+static int hf_netlogon_trust_flags_inbound = -1;
+static int hf_netlogon_trust_flags_outbound = -1;
+static int hf_netlogon_trust_flags_in_forest = -1;
+static int hf_netlogon_trust_flags_native_mode = -1;
+static int hf_netlogon_trust_flags_primary = -1;
+static int hf_netlogon_trust_flags_tree_root = -1;
+static int hf_netlogon_trust_parent_index = -1;
+static int hf_netlogon_user_account_control = -1;
+static int hf_netlogon_user_account_control_dont_require_preauth = -1;
+static int hf_netlogon_user_account_control_use_des_key_only = -1;
+static int hf_netlogon_user_account_control_not_delegated = -1;
+static int hf_netlogon_user_account_control_trusted_for_delegation = -1;
+static int hf_netlogon_user_account_control_smartcard_required = -1;
+static int hf_netlogon_user_account_control_encrypted_text_password_allowed = -1;
+static int hf_netlogon_user_account_control_account_auto_locked = -1;
+static int hf_netlogon_user_account_control_dont_expire_password = -1;
+static int hf_netlogon_user_account_control_server_trust_account = -1;
+static int hf_netlogon_user_account_control_workstation_trust_account = -1;
+static int hf_netlogon_user_account_control_interdomain_trust_account = -1;
+static int hf_netlogon_user_account_control_mns_logon_account = -1;
+static int hf_netlogon_user_account_control_normal_account = -1;
+static int hf_netlogon_user_account_control_temp_duplicate_account = -1;
+static int hf_netlogon_user_account_control_password_not_required = -1;
+static int hf_netlogon_user_account_control_home_directory_required = -1;
+static int hf_netlogon_user_account_control_account_disabled = -1;
+static int hf_netlogon_user_flags = -1;
+static int hf_netlogon_user_flags_extra_sids = -1;
+static int hf_netlogon_user_flags_resource_groups = -1;
+static int hf_netlogon_auth_flags = -1;
+static int hf_netlogon_pwd_expired = -1;
+static int hf_netlogon_nt_pwd_present = -1;
+static int hf_netlogon_lm_pwd_present = -1;
+static int hf_netlogon_code = -1;
+static int hf_netlogon_database_id = -1;
+static int hf_netlogon_sync_context = -1;
+static int hf_netlogon_max_size = -1;
+static int hf_netlogon_max_log_size = -1;
+static int hf_netlogon_dns_host = -1;
+static int hf_netlogon_acct_expiry_time = -1;
+static int hf_netlogon_encrypted_lm_owf_password = -1;
+static int hf_netlogon_lm_owf_password = -1;
+static int hf_netlogon_nt_owf_password = -1;
+static int hf_netlogon_param_ctrl = -1;
+static int hf_netlogon_logon_id = -1;
+static int hf_netlogon_num_deltas = -1;
+static int hf_netlogon_user_session_key = -1;
+static int hf_netlogon_blob_size = -1;
+static int hf_netlogon_blob = -1;
+static int hf_netlogon_logon_attempts = -1;
+static int hf_netlogon_authoritative = -1;
+static int hf_netlogon_secure_channel_type = -1;
+static int hf_netlogon_logonsrv_handle = -1;
+static int hf_netlogon_delta_type = -1;
+static int hf_netlogon_get_dcname_request_flags = -1;
+static int hf_netlogon_get_dcname_request_flags_force_rediscovery = -1;
+static int hf_netlogon_get_dcname_request_flags_directory_service_required = -1;
+static int hf_netlogon_get_dcname_request_flags_directory_service_preferred = -1;
+static int hf_netlogon_get_dcname_request_flags_gc_server_required = -1;
+static int hf_netlogon_get_dcname_request_flags_pdc_required = -1;
+static int hf_netlogon_get_dcname_request_flags_background_only = -1;
+static int hf_netlogon_get_dcname_request_flags_ip_required = -1;
+static int hf_netlogon_get_dcname_request_flags_kdc_required = -1;
+static int hf_netlogon_get_dcname_request_flags_timeserv_required = -1;
+static int hf_netlogon_get_dcname_request_flags_writable_required = -1;
+static int hf_netlogon_get_dcname_request_flags_good_timeserv_preferred = -1;
+static int hf_netlogon_get_dcname_request_flags_avoid_self = -1;
+static int hf_netlogon_get_dcname_request_flags_only_ldap_needed = -1;
+static int hf_netlogon_get_dcname_request_flags_is_flat_name = -1;
+static int hf_netlogon_get_dcname_request_flags_is_dns_name = -1;
+static int hf_netlogon_get_dcname_request_flags_return_dns_name = -1;
+static int hf_netlogon_get_dcname_request_flags_return_flat_name = -1;
+static int hf_netlogon_dc_flags = -1;
+static int hf_netlogon_dc_flags_pdc_flag = -1;
+static int hf_netlogon_dc_flags_gc_flag = -1;
+static int hf_netlogon_dc_flags_ldap_flag = -1;
+static int hf_netlogon_dc_flags_ds_flag = -1;
+static int hf_netlogon_dc_flags_kdc_flag = -1;
+static int hf_netlogon_dc_flags_timeserv_flag = -1;
+static int hf_netlogon_dc_flags_closest_flag = -1;
+static int hf_netlogon_dc_flags_writable_flag = -1;
+static int hf_netlogon_dc_flags_good_timeserv_flag = -1;
+static int hf_netlogon_dc_flags_ndnc_flag = -1;
+static int hf_netlogon_dc_flags_dns_controller_flag = -1;
+static int hf_netlogon_dc_flags_dns_domain_flag = -1;
+static int hf_netlogon_dc_flags_dns_forest_flag = -1;
+
+static gint ett_dcerpc_netlogon = -1;
+static gint ett_group_attrs = -1;
+static gint ett_user_flags = -1;
+static gint ett_user_account_control = -1;
+static gint ett_QUOTA_LIMITS = -1;
+static gint ett_IDENTITY_INFO = -1;
+static gint ett_DELTA_ENUM = -1;
+static gint ett_CYPHER_VALUE = -1;
+static gint ett_UNICODE_MULTI = -1;
+static gint ett_DOMAIN_CONTROLLER_INFO = -1;
+static gint ett_UNICODE_STRING_512 = -1;
+static gint ett_TYPE_50 = -1;
+static gint ett_TYPE_52 = -1;
+static gint ett_DELTA_ID_UNION = -1;
+static gint ett_TYPE_44 = -1;
+static gint ett_DELTA_UNION = -1;
+static gint ett_LM_OWF_PASSWORD = -1;
+static gint ett_NT_OWF_PASSWORD = -1;
+static gint ett_GROUP_MEMBERSHIP = -1;
+static gint ett_BLOB = -1;
+static gint ett_DS_DOMAIN_TRUSTS = -1;
+static gint ett_DOMAIN_TRUST_INFO = -1;
+static gint ett_trust_flags = -1;
+static gint ett_get_dcname_request_flags = -1;
+static gint ett_dc_flags = -1;
+
+static e_uuid_t uuid_dcerpc_netlogon = {
+ 0x12345678, 0x1234, 0xabcd,
+ { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0xcf, 0xfb }
+};
+
+static guint16 ver_dcerpc_netlogon = 1;
+
+
+static const true_false_string user_account_control_dont_require_preauth= {
+ "This account DONT_REQUIRE_PREAUTHENTICATION",
+ "This account REQUIRES preauthentication",
+};
+static const true_false_string user_account_control_use_des_key_only= {
+ "This account must USE_DES_KEY_ONLY for passwords",
+ "This account does NOT have to use_des_key_only",
+};
+static const true_false_string user_account_control_not_delegated= {
+ "This account is NOT_DELEGATED",
+ "This might have been delegated",
+};
+static const true_false_string user_account_control_trusted_for_delegation= {
+ "This account is TRUSTED_FOR_DELEGATION",
+ "This account is NOT trusted_for_delegation",
+};
+static const true_false_string user_account_control_smartcard_required= {
+ "This account REQUIRES_SMARTCARD to authenticate",
+ "This account does NOT require_smartcard to authenticate",
+};
+static const true_false_string user_account_control_encrypted_text_password_allowed= {
+ "This account allows ENCRYPTED_TEXT_PASSWORD",
+ "This account does NOT allow encrypted_text_password",
+};
+static const true_false_string user_account_control_account_auto_locked= {
+ "This account is AUTO_LOCKED",
+ "This account is NOT auto_locked",
+};
+static const true_false_string user_account_control_dont_expire_password= {
+ "This account DONT_EXPIRE_PASSWORDs",
+ "This account might expire_passwords",
+};
+static const true_false_string user_account_control_server_trust_account= {
+ "This account is a SERVER_TRUST_ACCOUNT",
+ "This account is NOT a server_trust_account",
+};
+static const true_false_string user_account_control_workstation_trust_account= {
+ "This account is a WORKSTATION_TRUST_ACCOUNT",
+ "This account is NOT a workstation_trust_account",
+};
+static const true_false_string user_account_control_interdomain_trust_account= {
+ "This account is an INTERDOMAIN_TRUST_ACCOUNT",
+ "This account is NOT an interdomain_trust_account",
+};
+static const true_false_string user_account_control_mns_logon_account= {
+ "This account is a MNS_LOGON_ACCOUNT",
+ "This account is NOT a mns_logon_account",
+};
+static const true_false_string user_account_control_normal_account= {
+ "This account is a NORMAL_ACCOUNT",
+ "This account is NOT a normal_account",
+};
+static const true_false_string user_account_control_temp_duplicate_account= {
+ "This account is a TEMP_DUPLICATE_ACCOUNT",
+ "This account is NOT a temp_duplicate_account",
+};
+static const true_false_string user_account_control_password_not_required= {
+ "This account REQUIRES_NO_PASSWORD",
+ "This account REQUIRES a password",
+};
+static const true_false_string user_account_control_home_directory_required= {
+ "This account REQUIRES_HOME_DIRECTORY",
+ "This account does NOT require_home_directory",
+};
+static const true_false_string user_account_control_account_disabled= {
+ "This account is DISABLED",
+ "This account is NOT disabled",
+};
+static int
+netlogon_dissect_USER_ACCOUNT_CONTROL(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_netlogon_user_account_control, &mask);
+
+ if(parent_tree){
+ item = proto_tree_add_uint(parent_tree, hf_netlogon_user_account_control,
+ tvb, offset-4, 4, mask);
+ tree = proto_item_add_subtree(item, ett_user_account_control);
+ }
+
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_dont_require_preauth,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_use_des_key_only,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_not_delegated,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_trusted_for_delegation,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_smartcard_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_encrypted_text_password_allowed,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_account_auto_locked,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_dont_expire_password,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_server_trust_account,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_workstation_trust_account,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_interdomain_trust_account,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_mns_logon_account,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_normal_account,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_temp_duplicate_account,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_password_not_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_home_directory_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_account_control_account_disabled,
+ tvb, offset-4, 4, mask);
+ return offset;
+}
+
+
+static int
+netlogon_dissect_LOGONSRV_HANDLE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server Handle",
+ hf_netlogon_logonsrv_handle, 0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [unique][string] wchar_t *effective_name;
+ * IDL long priv;
+ * IDL long auth_flags;
+ * IDL long logon_count;
+ * IDL long bad_pw_count;
+ * IDL long last_logon;
+ * IDL long last_logoff;
+ * IDL long logoff_time;
+ * IDL long kickoff_time;
+ * IDL long password_age;
+ * IDL long pw_can_change;
+ * IDL long pw_must_change;
+ * IDL [unique][string] wchar_t *computer;
+ * IDL [unique][string] wchar_t *domain;
+ * IDL [unique][string] wchar_t *script_path;
+ * IDL long reserved;
+ */
+static int
+netlogon_dissect_VALIDATION_UAS_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Effective Account",
+ hf_netlogon_acct_name, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_priv, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_auth_flags, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_count, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_bad_pw_count, NULL);
+
+
+ offset = dissect_ndr_time_t(tvb, offset, pinfo, tree, drep, hf_netlogon_logon_time, NULL);
+
+ offset = dissect_ndr_time_t(tvb, offset, pinfo, tree, drep, hf_netlogon_last_logoff_time, NULL);
+
+ offset = dissect_ndr_time_t(tvb, offset, pinfo, tree, drep, hf_netlogon_logoff_time, NULL);
+
+ offset = dissect_ndr_time_t(tvb, offset, pinfo, tree, drep, hf_netlogon_kickoff_time, NULL);
+
+ offset = dissect_ndr_time_t(tvb, offset, pinfo, tree, drep, hf_netlogon_pwd_age, NULL);
+
+ offset = dissect_ndr_time_t(tvb, offset, pinfo, tree, drep, hf_netlogon_pwd_can_change_time, NULL);
+
+ offset = dissect_ndr_time_t(tvb, offset, pinfo, tree, drep, hf_netlogon_pwd_must_change_time, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Computer", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_netlogon_domain_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Script", hf_netlogon_logon_script, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrLogonUasLogon(
+ * IDL [in][unique][string] wchar_t *ServerName,
+ * IDL [in][ref][string] wchar_t *UserName,
+ * IDL [in][ref][string] wchar_t *Workstation,
+ * IDL [out][unique] VALIDATION_UAS_INFO *info
+ * IDL );
+ */
+static int
+netlogon_dissect_netrlogonuaslogon_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Account", hf_netlogon_acct_name, CB_STR_COL_INFO);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Workstation", hf_netlogon_workstation, 0);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogonuaslogon_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_VALIDATION_UAS_INFO, NDR_POINTER_UNIQUE,
+ "VALIDATION_UAS_INFO", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long duration;
+ * IDL short logon_count;
+ * IDL } LOGOFF_UAS_INFO;
+ */
+static int
+netlogon_dissect_LOGOFF_UAS_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ proto_tree_add_text(tree, tvb, offset, 4, "Duration: unknown time format");
+ offset+= 4;
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_count16, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrLogonUasLogoff(
+ * IDL [in][unique][string] wchar_t *ServerName,
+ * IDL [in][ref][string] wchar_t *UserName,
+ * IDL [in][ref][string] wchar_t *Workstation,
+ * IDL [out][ref] LOGOFF_UAS_INFO *info
+ * IDL );
+ */
+static int
+netlogon_dissect_netrlogonuaslogoff_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Account", hf_netlogon_acct_name, CB_STR_COL_INFO);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Workstation", hf_netlogon_workstation, 0);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogonuaslogoff_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_LOGOFF_UAS_INFO, NDR_POINTER_REF,
+ "LOGOFF_UAS_INFO", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+
+
+/*
+ * IDL typedef struct {
+ * IDL UNICODESTRING LogonDomainName;
+ * IDL long ParameterControl;
+ * IDL uint64 LogonID;
+ * IDL UNICODESTRING UserName;
+ * IDL UNICODESTRING Workstation;
+ * IDL } LOGON_IDENTITY_INFO;
+ */
+static int
+netlogon_dissect_LOGON_IDENTITY_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "IDENTITY_INFO:");
+ tree = proto_item_add_subtree(item, ett_IDENTITY_INFO);
+ }
+
+ /* XXX: It would be nice to get the domain and account name
+ displayed in COL_INFO. */
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_param_ctrl, NULL);
+
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_id, NULL);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_acct_name, CB_STR_COL_INFO|3);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_workstation, 0);
+
+#ifdef REMOVED
+ /* NetMon does not recognize these bytes. Ill comment them out until someone complains */
+ /* XXX 8 extra bytes here */
+ /* there were 8 extra bytes, either here or in NETWORK_INFO that does not match
+ the idl file. Could be a bug in either the NETLOGON implementation or in the
+ idl file.
+ */
+ offset = netlogon_dissect_8_unknown_bytes(tvb, offset, pinfo, tree, drep);
+#endif
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL char password[16];
+ * IDL } LM_OWF_PASSWORD;
+ */
+static int
+netlogon_dissect_LM_OWF_PASSWORD(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep _U_)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect.*/
+ return offset;
+ }
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 16,
+ "LM_OWF_PASSWORD:");
+ tree = proto_item_add_subtree(item, ett_LM_OWF_PASSWORD);
+ }
+
+ proto_tree_add_item(tree, hf_netlogon_lm_owf_password, tvb, offset, 16,
+ FALSE);
+ offset += 16;
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL char password[16];
+ * IDL } NT_OWF_PASSWORD;
+ */
+static int
+netlogon_dissect_NT_OWF_PASSWORD(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep _U_)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect.*/
+ return offset;
+ }
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 16,
+ "NT_OWF_PASSWORD:");
+ tree = proto_item_add_subtree(item, ett_NT_OWF_PASSWORD);
+ }
+
+ proto_tree_add_item(tree, hf_netlogon_nt_owf_password, tvb, offset, 16,
+ FALSE);
+ offset += 16;
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL LOGON_IDENTITY_INFO identity_info;
+ * IDL LM_OWF_PASSWORD lmpassword;
+ * IDL NT_OWF_PASSWORD ntpassword;
+ * IDL } INTERACTIVE_INFO;
+ */
+static int
+netlogon_dissect_INTERACTIVE_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = netlogon_dissect_LOGON_IDENTITY_INFO(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_LM_OWF_PASSWORD(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_NT_OWF_PASSWORD(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL char chl[8];
+ * IDL } CHALLENGE;
+ */
+static int
+netlogon_dissect_CHALLENGE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect.*/
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_netlogon_challenge, tvb, offset, 8,
+ FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL LOGON_IDENTITY_INFO logon_info;
+ * IDL CHALLENGE chal;
+ * IDL STRING ntchallengeresponse;
+ * IDL STRING lmchallengeresponse;
+ * IDL } NETWORK_INFO;
+ */
+
+static void dissect_nt_chal_resp_cb(packet_info *pinfo _U_, proto_tree *tree,
+ proto_item *item _U_, tvbuff_t *tvb,
+ int start_offset, int end_offset,
+ void *callback_args _U_)
+{
+ int len;
+
+ /* Skip over 3 guint32's in NDR format */
+
+ if (start_offset % 4)
+ start_offset += 4 - (start_offset % 4);
+
+ start_offset += 12;
+ len = end_offset - start_offset;
+
+ /* Call ntlmv2 response dissector */
+
+ if (len > 24)
+ dissect_ntlmv2_response(tvb, tree, start_offset, len);
+}
+
+static int
+netlogon_dissect_NETWORK_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = netlogon_dissect_LOGON_IDENTITY_INFO(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_CHALLENGE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_byte_array_cb(
+ tvb, offset, pinfo, tree, drep, hf_netlogon_nt_chal_resp,
+ dissect_nt_chal_resp_cb, NULL);
+
+ offset = dissect_ndr_counted_byte_array(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_lm_chal_resp);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL LOGON_IDENTITY_INFO logon_info;
+ * IDL LM_OWF_PASSWORD lmpassword;
+ * IDL NT_OWF_PASSWORD ntpassword;
+ * IDL } SERVICE_INFO;
+ */
+static int
+netlogon_dissect_SERVICE_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = netlogon_dissect_LOGON_IDENTITY_INFO(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_LM_OWF_PASSWORD(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_NT_OWF_PASSWORD(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(short)] union {
+ * IDL [case(1)][unique] INTERACTIVE_INFO *iinfo;
+ * IDL [case(2)][unique] NETWORK_INFO *ninfo;
+ * IDL [case(3)][unique] SERVICE_INFO *sinfo;
+ * IDL } LEVEL;
+ */
+static int
+netlogon_dissect_LEVEL(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level16, &level);
+
+ ALIGN_TO_4_BYTES;
+ switch(level){
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_INTERACTIVE_INFO, NDR_POINTER_UNIQUE,
+ "INTERACTIVE_INFO:", -1);
+ break;
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_NETWORK_INFO, NDR_POINTER_UNIQUE,
+ "NETWORK_INFO:", -1);
+ break;
+ case 3:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_SERVICE_INFO, NDR_POINTER_UNIQUE,
+ "SERVICE_INFO:", -1);
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL char cred[8];
+ * IDL } CREDENTIAL;
+ */
+static int
+netlogon_dissect_CREDENTIAL(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect.*/
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_netlogon_credential, tvb, offset, 8,
+ FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL CREDENTIAL cred;
+ * IDL long timestamp;
+ * IDL } AUTHENTICATOR;
+ */
+static int
+netlogon_dissect_AUTHENTICATOR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+ nstime_t ts;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = netlogon_dissect_CREDENTIAL(tvb, offset,
+ pinfo, tree, drep);
+
+ /*
+ * XXX - this appears to be a UNIX time_t in some credentials, but
+ * appears to be random junk in other credentials.
+ * For example, it looks like a UNIX time_t in "credential"
+ * AUTHENTICATORs, but like random junk in "return_authenticator"
+ * AUTHENTICATORs.
+ */
+ ALIGN_TO_4_BYTES;
+ ts.secs = tvb_get_letohl(tvb, offset);
+ ts.nsecs = 0;
+ proto_tree_add_time(tree, hf_netlogon_timestamp, tvb, offset, 4, &ts);
+ offset+= 4;
+
+ return offset;
+}
+
+
+static const true_false_string group_attrs_mandatory = {
+ "The MANDATORY bit is SET",
+ "The mandatory bit is NOT set",
+};
+static const true_false_string group_attrs_enabled_by_default = {
+ "The ENABLED_BY_DEFAULT bit is SET",
+ "The enabled_by_default bit is NOT set",
+};
+static const true_false_string group_attrs_enabled = {
+ "The enabled bit is SET",
+ "The enabled bit is NOT set",
+};
+static int
+netlogon_dissect_GROUP_MEMBERSHIP_ATTRIBUTES(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_netlogon_attrs, &mask);
+
+ if(parent_tree){
+ item = proto_tree_add_uint(parent_tree, hf_netlogon_attrs,
+ tvb, offset-4, 4, mask);
+ tree = proto_item_add_subtree(item, ett_group_attrs);
+ }
+
+ proto_tree_add_boolean(tree, hf_netlogon_group_attrs_enabled,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_group_attrs_enabled_by_default,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_group_attrs_mandatory,
+ tvb, offset-4, 4, mask);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long user_id;
+ * IDL long attributes;
+ * IDL } GROUP_MEMBERSHIP;
+ */
+static int
+netlogon_dissect_GROUP_MEMBERSHIP(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "GROUP_MEMBERSHIP:");
+ tree = proto_item_add_subtree(item, ett_GROUP_MEMBERSHIP);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_group_rid, NULL);
+
+ offset = netlogon_dissect_GROUP_MEMBERSHIP_ATTRIBUTES(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_GROUP_MEMBERSHIP_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_GROUP_MEMBERSHIP);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL char user_session_key[16];
+ * IDL } USER_SESSION_KEY;
+ */
+static int
+netlogon_dissect_USER_SESSION_KEY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect.*/
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_netlogon_user_session_key, tvb, offset, 16,
+ FALSE);
+ offset += 16;
+
+ return offset;
+}
+
+
+
+static const true_false_string user_flags_extra_sids= {
+ "The EXTRA_SIDS bit is SET",
+ "The extra_sids is NOT set",
+};
+static const true_false_string user_flags_resource_groups= {
+ "The RESOURCE_GROUPS bit is SET",
+ "The resource_groups is NOT set",
+};
+static int
+netlogon_dissect_USER_FLAGS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_netlogon_user_flags, &mask);
+
+ if(parent_tree){
+ item = proto_tree_add_uint(parent_tree, hf_netlogon_user_flags,
+ tvb, offset-4, 4, mask);
+ tree = proto_item_add_subtree(item, ett_user_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_netlogon_user_flags_resource_groups,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_user_flags_extra_sids,
+ tvb, offset-4, 4, mask);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL uint64 LogonTime;
+ * IDL uint64 LogoffTime;
+ * IDL uint64 KickOffTime;
+ * IDL uint64 PasswdLastSet;
+ * IDL uint64 PasswdCanChange;
+ * IDL uint64 PasswdMustChange;
+ * IDL unicodestring effectivename;
+ * IDL unicodestring fullname;
+ * IDL unicodestring logonscript;
+ * IDL unicodestring profilepath;
+ * IDL unicodestring homedirectory;
+ * IDL unicodestring homedirectorydrive;
+ * IDL short LogonCount;
+ * IDL short BadPasswdCount;
+ * IDL long userid;
+ * IDL long primarygroup;
+ * IDL long groupcount;
+ * IDL [unique][size_is(groupcount)] GROUP_MEMBERSHIP *groupids;
+ * IDL long userflags;
+ * IDL USER_SESSION_KEY key;
+ * IDL unicodestring logonserver;
+ * IDL unicodestring domainname;
+ * IDL [unique] SID logondomainid;
+ * IDL long expansionroom[2];
+ * IDL long useraccountcontrol;
+ * IDL long expansionroom[7];
+ * IDL } VALIDATION_SAM_INFO;
+ */
+static int
+netlogon_dissect_VALIDATION_SAM_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ int i;
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logoff_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_kickoff_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_last_set_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_can_change_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_must_change_time);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_acct_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_full_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_script, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_profile_path, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_home_dir, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dir_drive, 0);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_count16, NULL);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_bad_pw_count16, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_group_rid, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_rids, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_GROUP_MEMBERSHIP_ARRAY, NDR_POINTER_UNIQUE,
+ "GROUP_MEMBERSHIP_ARRAY", -1);
+
+ offset = netlogon_dissect_USER_FLAGS(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_USER_SESSION_KEY(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_srv, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ for(i=0;i<2;i++){
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ }
+ offset = netlogon_dissect_USER_ACCOUNT_CONTROL(tvb, offset,
+ pinfo, tree, drep);
+
+ for(i=0;i<7;i++){
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ }
+
+ return offset;
+}
+
+
+
+/*
+ * IDL typedef struct {
+ * IDL uint64 LogonTime;
+ * IDL uint64 LogoffTime;
+ * IDL uint64 KickOffTime;
+ * IDL uint64 PasswdLastSet;
+ * IDL uint64 PasswdCanChange;
+ * IDL uint64 PasswdMustChange;
+ * IDL unicodestring effectivename;
+ * IDL unicodestring fullname;
+ * IDL unicodestring logonscript;
+ * IDL unicodestring profilepath;
+ * IDL unicodestring homedirectory;
+ * IDL unicodestring homedirectorydrive;
+ * IDL short LogonCount;
+ * IDL short BadPasswdCount;
+ * IDL long userid;
+ * IDL long primarygroup;
+ * IDL long groupcount;
+ * IDL [unique] GROUP_MEMBERSHIP *groupids;
+ * IDL long userflags;
+ * IDL USER_SESSION_KEY key;
+ * IDL unicodestring logonserver;
+ * IDL unicodestring domainname;
+ * IDL [unique] SID logondomainid;
+ * IDL long expansionroom[2];
+ * IDL long useraccountcontrol;
+ * IDL long expansionroom[7];
+ * IDL long sidcount;
+ * IDL [unique] SID_AND_ATTRIBS;
+ * IDL } VALIDATION_SAM_INFO2;
+ */
+static int
+netlogon_dissect_VALIDATION_SAM_INFO2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ int i;
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logoff_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_kickoff_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_last_set_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_can_change_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_must_change_time);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_acct_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_full_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_script, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_profile_path, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_home_dir, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dir_drive, 0);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_count16, NULL);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_bad_pw_count16, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_group_rid, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_rids, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_GROUP_MEMBERSHIP_ARRAY, NDR_POINTER_UNIQUE,
+ "GROUP_MEMBERSHIP_ARRAY", -1);
+
+ offset = netlogon_dissect_USER_FLAGS(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_USER_SESSION_KEY(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_srv, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ for(i=0;i<2;i++){
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ }
+ offset = netlogon_dissect_USER_ACCOUNT_CONTROL(tvb, offset,
+ pinfo, tree, drep);
+
+ for(i=0;i<7;i++){
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_other_groups, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_SID_AND_ATTRIBUTES_ARRAY, NDR_POINTER_UNIQUE,
+ "SID_AND_ATTRIBUTES_ARRAY:", -1);
+
+ return offset;
+}
+
+
+
+
+
+/*
+ * IDL typedef struct {
+ * IDL uint64 LogonTime;
+ * IDL uint64 LogoffTime;
+ * IDL uint64 KickOffTime;
+ * IDL uint64 PasswdLastSet;
+ * IDL uint64 PasswdCanChange;
+ * IDL uint64 PasswdMustChange;
+ * IDL unicodestring effectivename;
+ * IDL unicodestring fullname;
+ * IDL unicodestring logonscript;
+ * IDL unicodestring profilepath;
+ * IDL unicodestring homedirectory;
+ * IDL unicodestring homedirectorydrive;
+ * IDL short LogonCount;
+ * IDL short BadPasswdCount;
+ * IDL long userid;
+ * IDL long primarygroup;
+ * IDL long groupcount;
+ * IDL [unique] GROUP_MEMBERSHIP *groupids;
+ * IDL long userflags;
+ * IDL USER_SESSION_KEY key;
+ * IDL unicodestring logonserver;
+ * IDL unicodestring domainname;
+ * IDL [unique] SID logondomainid;
+ * IDL long expansionroom[2];
+ * IDL long useraccountcontrol;
+ * IDL long expansionroom[7];
+ * IDL long sidcount;
+ * IDL [unique] SID_AND_ATTRIBS;
+ * IDL [unique] SID resourcegroupdomainsid;
+ * IDL long resourcegroupcount;
+qqq
+ * IDL } PAC_LOGON_INFO;
+ */
+int
+netlogon_dissect_PAC_LOGON_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ int i;
+ guint32 rgc;
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logoff_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_kickoff_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_last_set_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_can_change_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_must_change_time);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_acct_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_full_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_script, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_profile_path, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_home_dir, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dir_drive, 0);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_count16, NULL);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_bad_pw_count16, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_group_rid, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_rids, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_GROUP_MEMBERSHIP_ARRAY, NDR_POINTER_UNIQUE,
+ "GROUP_MEMBERSHIP_ARRAY", -1);
+
+ offset = netlogon_dissect_USER_FLAGS(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_USER_SESSION_KEY(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_srv, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ for(i=0;i<2;i++){
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ }
+ offset = netlogon_dissect_USER_ACCOUNT_CONTROL(tvb, offset,
+ pinfo, tree, drep);
+
+ for(i=0;i<7;i++){
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_other_groups, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_SID_AND_ATTRIBUTES_ARRAY, NDR_POINTER_UNIQUE,
+ "SID_AND_ATTRIBUTES_ARRAY:", -1);
+
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_resourcegroupcount, &rgc);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_GROUP_MEMBERSHIP_ARRAY, NDR_POINTER_UNIQUE,
+ "ResourceGroupIDs", -1);
+
+ return offset;
+}
+
+
+
+static int
+netlogon_dissect_PAC(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+ guint32 pac_size;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pac_size, &pac_size);
+
+ proto_tree_add_item(tree, hf_netlogon_pac_data, tvb, offset, pac_size,
+ FALSE);
+ offset += pac_size;
+
+ return offset;
+}
+
+static int
+netlogon_dissect_AUTH(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+ guint32 auth_size;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_auth_size, &auth_size);
+
+ proto_tree_add_item(tree, hf_netlogon_auth_data, tvb, offset, auth_size,
+ FALSE);
+ offset += auth_size;
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long pac_size
+ * IDL [unique][size_is(pac_size)] char *pac;
+ * IDL UNICODESTRING logondomain;
+ * IDL UNICODESTRING logonserver;
+ * IDL UNICODESTRING principalname;
+ * IDL long auth_size;
+ * IDL [unique][size_is(auth_size)] char *auth;
+ * IDL USER_SESSION_KEY user_session_key;
+ * IDL long expansionroom[2];
+ * IDL long useraccountcontrol;
+ * IDL long expansionroom[7];
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL } VALIDATION_PAC_INFO;
+ */
+static int
+netlogon_dissect_VALIDATION_PAC_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ int i;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pac_size, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_PAC, NDR_POINTER_UNIQUE, "PAC:", -1);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_srv, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_principal, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_auth_size, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTH, NDR_POINTER_UNIQUE, "AUTH:", -1);
+
+ offset = netlogon_dissect_USER_SESSION_KEY(tvb, offset,
+ pinfo, tree, drep);
+
+ for(i=0;i<2;i++){
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ }
+ offset = netlogon_dissect_USER_ACCOUNT_CONTROL(tvb, offset,
+ pinfo, tree, drep);
+
+ for(i=0;i<7;i++){
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef [switch_type(short)] union {
+ * IDL [case(2)][unique] VALIDATION_SAM_INFO *sam;
+ * IDL [case(3)][unique] VALIDATION_SAM_INFO2 *sam2;
+ * IDL [case(4)][unique] VALIDATION_PAC_INFO *pac;
+ * IDL [case(5)][unique] VALIDATION_PAC_INFO *pac2;
+ * IDL } VALIDATION;
+ */
+static int
+netlogon_dissect_VALIDATION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_validation_level, &level);
+
+ ALIGN_TO_4_BYTES;
+ switch(level){
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_VALIDATION_SAM_INFO, NDR_POINTER_UNIQUE,
+ "VALIDATION_SAM_INFO:", -1);
+ break;
+ case 3:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_VALIDATION_SAM_INFO2, NDR_POINTER_UNIQUE,
+ "VALIDATION_SAM_INFO2:", -1);
+ break;
+ case 4:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_VALIDATION_PAC_INFO, NDR_POINTER_UNIQUE,
+ "VALIDATION_PAC_INFO:", -1);
+ break;
+ case 5:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_VALIDATION_PAC_INFO, NDR_POINTER_UNIQUE,
+ "VALIDATION_PAC_INFO:", -1);
+ break;
+ }
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrLogonSamLogon(
+ * IDL [in][unique][string] wchar_t *ServerName,
+ * IDL [in][unique][string] wchar_t *Workstation,
+ * IDL [in][unique] AUTHENTICATOR *credential,
+ * IDL [in][out][unique] AUTHENTICATOR *returnauthenticator,
+ * IDL [in] short LogonLevel,
+ * IDL [in][ref] LOGON_LEVEL *logonlevel,
+ * IDL [in] short ValidationLevel,
+ * IDL [out][ref] VALIDATION *validation,
+ * IDL [out][ref] boolean Authorative
+ * IDL );
+ */
+static int
+netlogon_dissect_netrlogonsamlogon_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Computer Name",
+ hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level16, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_LEVEL, NDR_POINTER_REF,
+ "LEVEL: LogonLevel", -1);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_validation_level, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogonsamlogon_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_VALIDATION, NDR_POINTER_REF,
+ "VALIDATION:", -1);
+
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_authoritative, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrLogonSamLogoff(
+ * IDL [in][unique][string] wchar_t *ServerName,
+ * IDL [in][unique][string] wchar_t *ComputerName,
+ * IDL [in][unique] AUTHENTICATOR credential,
+ * IDL [in][unique] AUTHENTICATOR return_authenticator,
+ * IDL [in] short logon_level,
+ * IDL [in][ref] LEVEL logoninformation
+ * IDL );
+ */
+static int
+netlogon_dissect_netrlogonsamlogoff_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Computer Name",
+ hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level16, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_LEVEL, NDR_POINTER_REF,
+ "LEVEL: logoninformation", -1);
+
+ return offset;
+}
+static int
+netlogon_dissect_netrlogonsamlogoff_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrServerReqChallenge(
+ * IDL [in][unique][string] wchar_t *ServerName,
+ * IDL [in][ref][string] wchar_t *ComputerName,
+ * IDL [in][ref] CREDENTIAL client_credential,
+ * IDL [out][ref] CREDENTIAL server_credential
+ * IDL );
+ */
+static int
+netlogon_dissect_netrserverreqchallenge_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_REF,
+ "Computer Name", hf_netlogon_computer_name,
+ cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CREDENTIAL, NDR_POINTER_REF,
+ "CREDENTIAL: client challenge", -1);
+
+ return offset;
+}
+static int
+netlogon_dissect_netrserverreqchallenge_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CREDENTIAL, NDR_POINTER_REF,
+ "CREDENTIAL: server credential", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_NETLOGON_SECURE_CHANNEL_TYPE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_secure_channel_type, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrServerAuthenticate(
+ * IDL [in][unique][string] wchar_t *ServerName,
+ * IDL [in][ref][string] wchar_t *UserName,
+ * IDL [in] short secure_challenge_type,
+ * IDL [in][ref][string] wchar_t *ComputerName,
+ * IDL [in][ref] CREDENTIAL client_challenge,
+ * IDL [out][ref] CREDENTIAL server_challenge
+ * IDL );
+ */
+static int
+netlogon_dissect_netrserverauthenticate_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "User Name", hf_netlogon_acct_name, CB_STR_COL_INFO);
+
+ offset = netlogon_dissect_NETLOGON_SECURE_CHANNEL_TYPE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, CB_STR_COL_INFO);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CREDENTIAL, NDR_POINTER_REF,
+ "CREDENTIAL: client challenge", -1);
+
+ return offset;
+}
+static int
+netlogon_dissect_netrserverauthenticate_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CREDENTIAL, NDR_POINTER_REF,
+ "CREDENTIAL: server challenge", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+ * IDL typedef struct {
+ * IDL char encrypted_password[16];
+ * IDL } ENCRYPTED_LM_OWF_PASSWORD;
+ */
+static int
+netlogon_dissect_ENCRYPTED_LM_OWF_PASSWORD(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect.*/
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_netlogon_encrypted_lm_owf_password, tvb, offset, 16,
+ FALSE);
+ offset += 16;
+
+ return offset;
+}
+
+/*
+ * IDL long NetrServerPasswordSet(
+ * IDL [in][unique][string] wchar_t *ServerName,
+ * IDL [in][ref][string] wchar_t *UserName,
+ * IDL [in] short secure_challenge_type,
+ * IDL [in][ref][string] wchar_t *ComputerName,
+ * IDL [in][ref] AUTHENTICATOR credential,
+ * IDL [in][ref] LM_OWF_PASSWORD UasNewPassword,
+ * IDL [out][ref] AUTHENTICATOR return_authenticator
+ * IDL );
+ */
+static int
+netlogon_dissect_netrserverpasswordset_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "User Name", hf_netlogon_acct_name, 0);
+
+ offset = netlogon_dissect_NETLOGON_SECURE_CHANNEL_TYPE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_ENCRYPTED_LM_OWF_PASSWORD, NDR_POINTER_REF,
+ "ENCRYPTED_LM_OWF_PASSWORD: hashed_pwd", -1);
+
+ return offset;
+}
+static int
+netlogon_dissect_netrserverpasswordset_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL [unique][string] wchar_t *UserName;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_DELETE_USER;
+ */
+static int
+netlogon_dissect_DELTA_DELETE_USER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Account Name", hf_netlogon_acct_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL bool SensitiveDataFlag;
+ * IDL long DataLength;
+ * IDL [unique][size_is(DataLength)] char *SensitiveData;
+ * IDL } USER_PRIVATE_INFO;
+ */
+static int
+netlogon_dissect_SENSITIVE_DATA(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+ guint32 data_len;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_sensitive_data_len, &data_len);
+
+ proto_tree_add_item(tree, hf_netlogon_sensitive_data, tvb, offset,
+ data_len, FALSE);
+ offset += data_len;
+
+ return offset;
+}
+static int
+netlogon_dissect_USER_PRIVATE_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_sensitive_data_flag, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_sensitive_data_len, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_SENSITIVE_DATA, NDR_POINTER_UNIQUE,
+ "SENSITIVE_DATA", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL UNICODESTRING UserName;
+ * IDL UNICODESTRING FullName;
+ * IDL long UserID;
+ * IDL long PrimaryGroupID;
+ * IDL UNICODESTRING HomeDir;
+ * IDL UNICODESTRING HomeDirDrive;
+ * IDL UNICODESTRING LogonScript;
+ * IDL UNICODESTRING Comment;
+ * IDL UNICODESTRING Workstations;
+ * IDL NTTIME LastLogon;
+ * IDL NTTIME LastLogoff;
+ * IDL LOGON_HOURS logonhours;
+ * IDL short BadPwCount;
+ * IDL short LogonCount;
+ * IDL NTTIME PwLastSet;
+ * IDL NTTIME AccountExpires;
+ * IDL long AccountControl;
+ * IDL LM_OWF_PASSWORD lmpw;
+ * IDL NT_OWF_PASSWORD ntpw;
+ * IDL bool NTPwPresent;
+ * IDL bool LMPwPresent;
+ * IDL bool PwExpired;
+ * IDL UNICODESTRING UserComment;
+ * IDL UNICODESTRING Parameters;
+ * IDL short CountryCode;
+ * IDL short CodePage;
+ * IDL USER_PRIVATE_INFO user_private_info;
+ * IDL long SecurityInformation;
+ * IDL LSA_SECURITY_DESCRIPTOR sec_desc;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_USER;
+ */
+static int
+netlogon_dissect_DELTA_USER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_acct_name, 3);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_full_name, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_group_rid, NULL);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_home_dir, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dir_drive, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_script, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_acct_desc, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_workstations, 0);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logoff_time);
+
+ offset = dissect_ndr_nt_LOGON_HOURS(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_bad_pw_count16, NULL);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_count16, NULL);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_last_set_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_acct_expiry_time);
+
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+
+ offset = netlogon_dissect_LM_OWF_PASSWORD(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_NT_OWF_PASSWORD(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_nt_pwd_present, NULL);
+
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_lm_pwd_present, NULL);
+
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_expired, NULL);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_comment, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_parameters, 0);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_country, NULL);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_codepage, NULL);
+
+ offset = netlogon_dissect_USER_PRIVATE_INFO(tvb, offset, pinfo, tree,
+ drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_security_information, NULL);
+
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL UNICODESTRING DomainName;
+ * IDL UNICODESTRING OEMInfo;
+ * IDL NTTIME forcedlogoff;
+ * IDL short minpasswdlen;
+ * IDL short passwdhistorylen;
+ * IDL NTTIME pwd_must_change_time;
+ * IDL NTTIME pwd_can_change_time;
+ * IDL NTTIME domain_modify_time;
+ * IDL NTTIME domain_create_time;
+ * IDL long SecurityInformation;
+ * IDL LSA_SECURITY_DESCRIPTOR sec_desc;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_DOMAIN;
+ */
+static int
+netlogon_dissect_DELTA_DOMAIN(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_domain_name, 3);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_oem_info, 0);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_kickoff_time);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_minpasswdlen, NULL);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_passwdhistorylen, NULL);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_must_change_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pwd_can_change_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_domain_modify_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_domain_create_time);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_security_information, NULL);
+
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL UNICODESTRING groupname;
+ * IDL GROUP_MEMBERSHIP group_membership;
+ * IDL UNICODESTRING comment;
+ * IDL long SecurityInformation;
+ * IDL LSA_SECURITY_DESCRIPTOR sec_desc;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_GROUP;
+ */
+static int
+netlogon_dissect_DELTA_GROUP(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_group_name, 3);
+
+ offset = netlogon_dissect_GROUP_MEMBERSHIP(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_group_desc, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_security_information, NULL);
+
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL UNICODESTRING OldName;
+ * IDL UNICODESTRING NewName;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_RENAME;
+ */
+static int
+netlogon_dissect_DELTA_RENAME(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ di->hf_index, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ di->hf_index, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_RID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_RID_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_RID);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_ATTRIB(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_attrs, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_ATTRIB_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_ATTRIB);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [unique][size_is(num_rids)] long *rids;
+ * IDL [unique][size_is(num_rids)] long *attribs;
+ * IDL long num_rids;
+ * IDL long dummy1;
+ * IDL long dummy2;
+ * IDL long dummy3;
+ * IDL long dummy4;
+ * IDL } DELTA_GROUP_MEMBER;
+ */
+static int
+netlogon_dissect_DELTA_GROUP_MEMBER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_RID_array, NDR_POINTER_UNIQUE,
+ "RIDs:", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_ATTRIB_array, NDR_POINTER_UNIQUE,
+ "Attribs:", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_rids, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL UNICODESTRING alias_name;
+ * IDL long rid;
+ * IDL long SecurityInformation;
+ * IDL LSA_SECURITY_DESCRIPTOR sec_desc;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_ALIAS;
+ */
+static int
+netlogon_dissect_DELTA_ALIAS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_alias_name, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_alias_rid, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_security_information, NULL);
+
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL [unique] SID_ARRAY sids;
+ * IDL long dummy1;
+ * IDL long dummy2;
+ * IDL long dummy3;
+ * IDL long dummy4;
+ * IDL } DELTA_ALIAS_MEMBER;
+ */
+static int
+netlogon_dissect_DELTA_ALIAS_MEMBER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_nt_PSID_ARRAY(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_EVENT_AUDIT_OPTION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_event_audit_option, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_EVENT_AUDIT_OPTIONS_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_EVENT_AUDIT_OPTION);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long pagedpoollimit;
+ * IDL long nonpagedpoollimit;
+ * IDL long minimumworkingsetsize;
+ * IDL long maximumworkingsetsize;
+ * IDL long pagefilelimit;
+ * IDL NTTIME timelimit;
+ * IDL } QUOTA_LIMITS;
+ */
+static int
+netlogon_dissect_QUOTA_LIMITS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "QUOTA_LIMTS:");
+ tree = proto_item_add_subtree(item, ett_QUOTA_LIMITS);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pagedpoollimit, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_nonpagedpoollimit, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_minworkingsetsize, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_maxworkingsetsize, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pagefilelimit, NULL);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_timelimit);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long maxlogsize;
+ * IDL NTTIME auditretentionperiod;
+ * IDL bool auditingmode;
+ * IDL long maxauditeventcount;
+ * IDL [unique][size_is(maxauditeventcount)] long *eventauditoptions;
+ * IDL UNICODESTRING primarydomainname;
+ * IDL [unique] SID *sid;
+ * IDL QUOTA_LIMITS quota_limits;
+ * IDL NTTIME db_modify_time;
+ * IDL NTTIME db_create_time;
+ * IDL long SecurityInformation;
+ * IDL LSA_SECURITY_DESCRIPTOR sec_desc;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_POLICY;
+ */
+static int
+netlogon_dissect_DELTA_POLICY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_max_log_size, NULL);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_audit_retention_period);
+
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_auditing_mode, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_max_audit_event_count, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_EVENT_AUDIT_OPTIONS_ARRAY, NDR_POINTER_UNIQUE,
+ "Event Audit Options:", -1);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_domain_name, 0);
+
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ offset = netlogon_dissect_QUOTA_LIMITS(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_db_modify_time);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_db_create_time);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_security_information, NULL);
+
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_CONTROLLER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dc_name, 0);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_CONTROLLER_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CONTROLLER);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL UNICODESTRING DomainName;
+ * IDL long num_controllers;
+ * IDL [unique][size_is(num_controllers)] UNICODESTRING *controller_names;
+ * IDL long SecurityInformation;
+ * IDL LSA_SECURITY_DESCRIPTOR sec_desc;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_TRUSTED_DOMAINS;
+ */
+static int
+netlogon_dissect_DELTA_TRUSTED_DOMAINS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_domain_name, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_controllers, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CONTROLLER_ARRAY, NDR_POINTER_UNIQUE,
+ "Domain Controllers:", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_security_information, NULL);
+
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_PRIV_ATTR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_attrs, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_PRIV_ATTR_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_PRIV_ATTR);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_PRIV_NAME(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_privilege_name, 1);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_PRIV_NAME_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_PRIV_NAME);
+
+ return offset;
+}
+
+
+
+/*
+ * IDL typedef struct {
+ * IDL long privilegeentries;
+ * IDL long provolegecontrol;
+ * IDL [unique][size_is(privilege_entries)] long *privilege_attrib;
+ * IDL [unique][size_is(privilege_entries)] UNICODESTRING *privilege_name;
+ * IDL QUOTALIMITS quotalimits;
+ * IDL long SecurityInformation;
+ * IDL LSA_SECURITY_DESCRIPTOR sec_desc;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_ACCOUNTS;
+ */
+static int
+netlogon_dissect_DELTA_ACCOUNTS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_privilege_entries, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_privilege_control, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_PRIV_ATTR_ARRAY, NDR_POINTER_UNIQUE,
+ "PRIV_ATTR_ARRAY:", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_PRIV_NAME_ARRAY, NDR_POINTER_UNIQUE,
+ "PRIV_NAME_ARRAY:", -1);
+
+ offset = netlogon_dissect_QUOTA_LIMITS(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_systemflags, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_security_information, NULL);
+
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long len;
+ * IDL long maxlen;
+ * IDL [unique][size_is(maxlen)][length_is(len)] char *cipher_data;
+ * IDL } CIPHER_VALUE;
+ */
+static int
+netlogon_dissect_CIPHER_VALUE_DATA(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+ guint32 data_len;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_netlogon_cipher_maxlen, NULL);
+
+ /* skip offset */
+ offset += 4;
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_netlogon_cipher_len, &data_len);
+
+ proto_tree_add_item(tree, di->hf_index, tvb, offset,
+ data_len, FALSE);
+ offset += data_len;
+
+ return offset;
+}
+static int
+netlogon_dissect_CIPHER_VALUE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep, char *name, int hf_index)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ name);
+ tree = proto_item_add_subtree(item, ett_CYPHER_VALUE);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_netlogon_cipher_len, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_netlogon_cipher_maxlen, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CIPHER_VALUE_DATA, NDR_POINTER_UNIQUE,
+ name, hf_index);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL CIPHER_VALUE current_cipher;
+ * IDL NTTIME current_cipher_set_time;
+ * IDL CIPHER_VALUE old_cipher;
+ * IDL NTTIME old_cipher_set_time;
+ * IDL long SecurityInformation;
+ * IDL LSA_SECURITY_DESCRIPTOR sec_desc;
+ * IDL UNICODESTRING dummy1;
+ * IDL UNICODESTRING dummy2;
+ * IDL UNICODESTRING dummy3;
+ * IDL UNICODESTRING dummy4;
+ * IDL long dummy5;
+ * IDL long dummy6;
+ * IDL long dummy7;
+ * IDL long dummy8;
+ * IDL } DELTA_SECRET;
+ */
+static int
+netlogon_dissect_DELTA_SECRET(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = netlogon_dissect_CIPHER_VALUE(tvb, offset,
+ pinfo, tree, drep,
+ "CIPHER_VALUE: current cipher value",
+ hf_netlogon_cipher_current_data);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_cipher_current_set_time);
+
+ offset = netlogon_dissect_CIPHER_VALUE(tvb, offset,
+ pinfo, tree, drep,
+ "CIPHER_VALUE: old cipher value",
+ hf_netlogon_cipher_old_data);
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_cipher_old_set_time);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_security_information, NULL);
+
+ offset = lsa_dissect_LSA_SECURITY_DESCRIPTOR(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dummy, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long low_value;
+ * IDL long high_value;
+ * } MODIFIED_COUNT;
+ */
+static int
+netlogon_dissect_MODIFIED_COUNT(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_modify_count, NULL);
+
+ return offset;
+}
+
+
+#define DT_DELTA_DOMAIN 1
+#define DT_DELTA_GROUP 2
+#define DT_DELTA_DELETE_GROUP 3
+#define DT_DELTA_RENAME_GROUP 4
+#define DT_DELTA_USER 5
+#define DT_DELTA_DELETE_USER 6
+#define DT_DELTA_RENAME_USER 7
+#define DT_DELTA_GROUP_MEMBER 8
+#define DT_DELTA_ALIAS 9
+#define DT_DELTA_DELETE_ALIAS 10
+#define DT_DELTA_RENAME_ALIAS 11
+#define DT_DELTA_ALIAS_MEMBER 12
+#define DT_DELTA_POLICY 13
+#define DT_DELTA_TRUSTED_DOMAINS 14
+#define DT_DELTA_DELETE_TRUST 15
+#define DT_DELTA_ACCOUNTS 16
+#define DT_DELTA_DELETE_ACCOUNT 17
+#define DT_DELTA_SECRET 18
+#define DT_DELTA_DELETE_SECRET 19
+#define DT_DELTA_DELETE_GROUP2 20
+#define DT_DELTA_DELETE_USER2 21
+#define DT_MODIFIED_COUNT 22
+static const value_string delta_type_vals[] = {
+ { DT_DELTA_DOMAIN, "Domain" },
+ { DT_DELTA_GROUP, "Group" },
+ { DT_DELTA_DELETE_GROUP, "Delete Group" },
+ { DT_DELTA_RENAME_GROUP, "Rename Group" },
+ { DT_DELTA_USER, "User" },
+ { DT_DELTA_DELETE_USER, "Delete User" },
+ { DT_DELTA_RENAME_USER, "Rename User" },
+ { DT_DELTA_GROUP_MEMBER, "Group Member" },
+ { DT_DELTA_ALIAS, "Alias" },
+ { DT_DELTA_DELETE_ALIAS, "Delete Alias" },
+ { DT_DELTA_RENAME_ALIAS, "Rename Alias" },
+ { DT_DELTA_ALIAS_MEMBER, "Alias Member" },
+ { DT_DELTA_POLICY, "Policy" },
+ { DT_DELTA_TRUSTED_DOMAINS, "Trusted Domains" },
+ { DT_DELTA_DELETE_TRUST, "Delete Trust" },
+ { DT_DELTA_ACCOUNTS, "Accounts" },
+ { DT_DELTA_DELETE_ACCOUNT, "Delete Account" },
+ { DT_DELTA_SECRET, "Secret" },
+ { DT_DELTA_DELETE_SECRET, "Delete Secret" },
+ { DT_DELTA_DELETE_GROUP2, "Delete Group2" },
+ { DT_DELTA_DELETE_USER2, "Delete User2" },
+ { DT_MODIFIED_COUNT, "Modified Count" },
+ { 0, NULL }
+};
+/*
+ * IDL typedef [switch_type(short)] union {
+ * IDL [case(1)][unique] DELTA_DOMAIN *domain;
+ * IDL [case(2)][unique] DELTA_GROUP *group;
+ * IDL [case(3)][unique] rid only ;
+ * IDL [case(4)][unique] DELTA_RENAME_GROUP *rename_group;
+ * IDL [case(5)][unique] DELTA_USER *user;
+ * IDL [case(6)][unique] rid only ;
+ * IDL [case(7)][unique] DELTA_RENAME_USER *rename_user;
+ * IDL [case(8)][unique] DELTA_GROUP_MEMBER *group_member;
+ * IDL [case(9)][unique] DELTA_ALIAS *alias;
+ * IDL [case(10)][unique] rid only ;
+ * IDL [case(11)][unique] DELTA_RENAME_ALIAS *alias;
+ * IDL [case(12)][unique] DELTA_ALIAS_MEMBER *alias_member;
+ * IDL [case(13)][unique] DELTA_POLICY *policy;
+ * IDL [case(14)][unique] DELTA_TRUSTED_DOMAINS *trusted_domains;
+ * IDL [case(15)][unique] PSID ;
+ * IDL [case(16)][unique] DELTA_ACCOUNTS *accounts;
+ * IDL [case(17)][unique] PSID ;
+ * IDL [case(18)][unique] DELTA_SECRET *secret;
+ * IDL [case(19)][unique] string;
+ * IDL [case(20)][unique] DELTA_DELETE_GROUP2 *delete_group;
+ * IDL [case(21)][unique] DELTA_DELETE_USER2 *delete_user;
+ * IDL [case(22)][unique] MODIFIED_COUNT *modified_count;
+ * IDL } DELTA_UNION;
+ */
+static int
+netlogon_dissect_DELTA_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "DELTA_UNION:");
+ tree = proto_item_add_subtree(item, ett_DELTA_UNION);
+ }
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_delta_type, &level);
+
+ ALIGN_TO_4_BYTES;
+ switch(level){
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_DOMAIN, NDR_POINTER_UNIQUE,
+ "DELTA_DOMAIN:", -1);
+ break;
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_GROUP, NDR_POINTER_UNIQUE,
+ "DELTA_GROUP:", -1);
+ break;
+ case 4:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_RENAME, NDR_POINTER_UNIQUE,
+ "DELTA_RENAME_GROUP:", hf_netlogon_group_name);
+ break;
+ case 5:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_USER, NDR_POINTER_UNIQUE,
+ "DELTA_USER:", -1);
+ break;
+ case 7:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_RENAME, NDR_POINTER_UNIQUE,
+ "DELTA_RENAME_USER:", hf_netlogon_acct_name);
+ break;
+ case 8:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_GROUP_MEMBER, NDR_POINTER_UNIQUE,
+ "DELTA_GROUP_MEMBER:", -1);
+ break;
+ case 9:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_ALIAS, NDR_POINTER_UNIQUE,
+ "DELTA_ALIAS:", -1);
+ break;
+ case 11:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_RENAME, NDR_POINTER_UNIQUE,
+ "DELTA_RENAME_ALIAS:", hf_netlogon_alias_name);
+ break;
+ case 12:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_ALIAS_MEMBER, NDR_POINTER_UNIQUE,
+ "DELTA_ALIAS_MEMBER:", -1);
+ break;
+ case 13:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_POLICY, NDR_POINTER_UNIQUE,
+ "DELTA_POLICY:", -1);
+ break;
+ case 14:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_TRUSTED_DOMAINS, NDR_POINTER_UNIQUE,
+ "DELTA_TRUSTED_DOMAINS:", -1);
+ break;
+ case 16:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_ACCOUNTS, NDR_POINTER_UNIQUE,
+ "DELTA_ACCOUNTS:", -1);
+ break;
+ case 18:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_SECRET, NDR_POINTER_UNIQUE,
+ "DELTA_SECRET:", -1);
+ break;
+ case 20:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_DELETE_USER, NDR_POINTER_UNIQUE,
+ "DELTA_DELETE_GROUP:", -1);
+ break;
+ case 21:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_DELETE_USER, NDR_POINTER_UNIQUE,
+ "DELTA_DELETE_USER:", -1);
+ break;
+ case 22:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_MODIFIED_COUNT, NDR_POINTER_UNIQUE,
+ "MODIFIED_COUNT:", -1);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+
+/* IDL XXX must verify this one, especially 13-19
+ * IDL typedef [switch_type(short)] union {
+ * IDL [case(1)] long rid;
+ * IDL [case(2)] long rid;
+ * IDL [case(3)] long rid;
+ * IDL [case(4)] long rid;
+ * IDL [case(5)] long rid;
+ * IDL [case(6)] long rid;
+ * IDL [case(7)] long rid;
+ * IDL [case(8)] long rid;
+ * IDL [case(9)] long rid;
+ * IDL [case(10)] long rid;
+ * IDL [case(11)] long rid;
+ * IDL [case(12)] long rid;
+ * IDL [case(13)] [unique] SID *sid;
+ * IDL [case(14)] [unique] SID *sid;
+ * IDL [case(15)] [unique] SID *sid;
+ * IDL [case(16)] [unique] SID *sid;
+ * IDL [case(17)] [unique] SID *sid;
+ * IDL [case(18)] [unique][string] wchar_t *Name ;
+ * IDL [case(19)] [unique][string] wchar_t *Name ;
+ * IDL [case(20)] long rid;
+ * IDL [case(21)] long rid;
+ * IDL } DELTA_ID_UNION;
+ */
+static int
+netlogon_dissect_DELTA_ID_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "DELTA_ID_UNION:");
+ tree = proto_item_add_subtree(item, ett_DELTA_ID_UNION);
+ }
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_delta_type, &level);
+
+ ALIGN_TO_4_BYTES;
+ switch(level){
+ case 1:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_group_rid, NULL);
+ break;
+ case 2:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 3:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 4:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 5:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 6:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 7:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 8:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 9:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 10:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 11:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 12:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 13:
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+ break;
+ case 14:
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+ break;
+ case 15:
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+ break;
+ case 16:
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+ break;
+ case 17:
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+ break;
+ case 18:
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo,
+ tree, drep, NDR_POINTER_UNIQUE, "unknown",
+ hf_netlogon_unknown_string, 0);
+ break;
+ case 19:
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo,
+ tree, drep, NDR_POINTER_UNIQUE, "unknown",
+ hf_netlogon_unknown_string, 0);
+ break;
+ case 20:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ case 21:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_user_rid, NULL);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL short delta_type;
+ * IDL DELTA_ID_UNION delta_id_union;
+ * IDL DELTA_UNION delta_union;
+ * IDL } DELTA_ENUM;
+ */
+static int
+netlogon_dissect_DELTA_ENUM(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 type;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "DELTA_ENUM:");
+ tree = proto_item_add_subtree(item, ett_DELTA_ENUM);
+ }
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_delta_type, &type);
+
+ proto_item_append_text(item, val_to_str(
+ type, delta_type_vals, "Unknown"));
+
+ offset = netlogon_dissect_DELTA_ID_UNION(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_DELTA_UNION(tvb, offset,
+ pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+netlogon_dissect_DELTA_ENUM_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_ENUM);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long num_deltas;
+ * IDL [unique][size_is(num_deltas)] DELTA_ENUM *delta_enum;
+ * IDL } DELTA_ENUM_ARRAY;
+ */
+static int
+netlogon_dissect_DELTA_ENUM_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_deltas, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_ENUM_array, NDR_POINTER_UNIQUE,
+ "DELTA_ENUM: deltas", -1);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrDatabaseDeltas(
+ * IDL [in][string][ref] wchar_t *logonserver, # REF!!!
+ * IDL [in][string][ref] wchar_t *computername,
+ * IDL [in][ref] AUTHENTICATOR credential,
+ * IDL [in][out][ref] AUTHENTICATOR return_authenticator,
+ * IDL [in] long database_id,
+ * IDL [in][out][ref] MODIFIED_COUNT domain_modify_count,
+ * IDL [in] long preferredmaximumlength,
+ * IDL [out][unique] DELTA_ENUM_ARRAY *delta_enum_array
+ * IDL );
+ */
+static int
+netlogon_dissect_netrdatabasedeltas_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Server Handle", hf_netlogon_logonsrv_handle, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_database_id, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_MODIFIED_COUNT, NDR_POINTER_REF,
+ "MODIFIED_COUNT: domain modified count", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_max_size, NULL);
+
+ return offset;
+}
+static int
+netlogon_dissect_netrdatabasedeltas_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_MODIFIED_COUNT, NDR_POINTER_REF,
+ "MODIFIED_COUNT: domain modified count", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_ENUM_ARRAY, NDR_POINTER_UNIQUE,
+ "DELTA_ENUM_ARRAY: deltas", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrDatabaseSync(
+ * IDL [in][string][ref] wchar_t *logonserver, # REF!!!
+ * IDL [in][string][ref] wchar_t *computername,
+ * IDL [in][ref] AUTHENTICATOR credential,
+ * IDL [in][out][ref] AUTHENTICATOR return_authenticator,
+ * IDL [in] long database_id,
+ * IDL [in][out][ref] long sync_context,
+ * IDL [in] long preferredmaximumlength,
+ * IDL [out][unique] DELTA_ENUM_ARRAY *delta_enum_array
+ * IDL );
+ */
+static int
+netlogon_dissect_netrdatabasesync_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Server Handle", hf_netlogon_logonsrv_handle, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_database_id, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_sync_context, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_max_size, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrdatabasesync_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_sync_context, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_ENUM_ARRAY, NDR_POINTER_UNIQUE,
+ "DELTA_ENUM_ARRAY: deltas", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL char computer_name[16];
+ * IDL long timecreated;
+ * IDL long serial_number;
+ * IDL } UAS_INFO_0;
+ */
+static int
+netlogon_dissect_UAS_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_netlogon_computer_name, tvb, offset, 16, FALSE);
+ offset += 16;
+
+ proto_tree_add_text(tree, tvb, offset, 4, "Time Created: unknown time format");
+ offset+= 4;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_serial_number, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_BYTE_byte(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_char, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_BYTE_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_byte);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrAccountDeltas(
+ * IDL [in][string][unique] wchar_t *logonserver,
+ * IDL [in][string][ref] wchar_t *computername,
+ * IDL [in][ref] AUTHENTICATOR credential,
+ * IDL [in][out][ref] AUTHENTICATOR return_authenticator,
+ * IDL [out][ref][size_is(count_returned)] char *Buffer,
+ * IDL [out][ref] long count_returned,
+ * IDL [out][ref] long total_entries,
+ * IDL [in][out][ref] UAS_INFO_0 recordid,
+ * IDL [in][long] count,
+ * IDL [in][long] level,
+ * IDL [in][long] buffersize,
+ * IDL );
+ */
+static int
+netlogon_dissect_netraccountdeltas_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_UAS_INFO_0, NDR_POINTER_REF,
+ "UAS_INFO_0: RecordID", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_count, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_max_size, NULL);
+
+ return offset;
+}
+static int
+netlogon_dissect_netraccountdeltas_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_array, NDR_POINTER_REF,
+ "BYTE_array: Buffer", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_count, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_UAS_INFO_0, NDR_POINTER_REF,
+ "UAS_INFO_0: RecordID", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrAccountSync(
+ * IDL [in][string][unique] wchar_t *logonserver,
+ * IDL [in][string][ref] wchar_t *computername,
+ * IDL [in][ref] AUTHENTICATOR credential,
+ * IDL [in][out][ref] AUTHENTICATOR return_authenticator,
+ * IDL [out][ref][size_is(count_returned)] char *Buffer,
+ * IDL [out][ref] long count_returned,
+ * IDL [out][ref] long total_entries,
+ * IDL [out][ref] long next_reference,
+ * IDL [in][long] reference,
+ * IDL [in][long] level,
+ * IDL [in][long] buffersize,
+ * IDL [in][out][ref] UAS_INFO_0 recordid,
+ * IDL );
+ */
+static int
+netlogon_dissect_netraccountsync_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reference, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_max_size, NULL);
+
+ return offset;
+}
+static int
+netlogon_dissect_netraccountsync_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_array, NDR_POINTER_REF,
+ "BYTE_array: Buffer", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_count, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_entries, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_next_reference, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_UAS_INFO_0, NDR_POINTER_REF,
+ "UAS_INFO_0: RecordID", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrGetDcName(
+ * IDL [in][ref][string] wchar_t *logon_server,
+ * IDL [in][unique][string] wchar_t *domainname,
+ * IDL [out][unique][string] wchar_t *dcname,
+ * IDL };
+ */
+static int
+netlogon_dissect_netrgetdcname_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Server Handle", hf_netlogon_logonsrv_handle, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_netlogon_domain_name, 0);
+
+ return offset;
+}
+static int
+netlogon_dissect_netrgetdcname_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_netlogon_dc_name, 0);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+ * IDL typedef struct {
+ * IDL long flags;
+ * IDL long pdc_connection_status;
+ * IDL } NETLOGON_INFO_1;
+ */
+static int
+netlogon_dissect_NETLOGON_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_flags, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pdc_connection_status, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long flags;
+ * IDL long pdc_connection_status;
+ * IDL [unique][string] wchar_t trusted_dc_name;
+ * IDL long tc_connection_status;
+ * IDL } NETLOGON_INFO_2;
+ */
+static int
+netlogon_dissect_NETLOGON_INFO_2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_flags, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_pdc_connection_status, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Trusted DC Name",
+ hf_netlogon_trusted_dc_name, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_tc_connection_status, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long flags;
+ * IDL long logon_attempts;
+ * IDL long reserved;
+ * IDL long reserved;
+ * IDL long reserved;
+ * IDL long reserved;
+ * IDL long reserved;
+ * IDL } NETLOGON_INFO_3;
+ */
+static int
+netlogon_dissect_NETLOGON_INFO_3(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_flags, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_logon_attempts, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_reserved, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(1)] [unique] NETLOGON_INFO_1 *i1;
+ * IDL [case(2)] [unique] NETLOGON_INFO_2 *i2;
+ * IDL [case(3)] [unique] NETLOGON_INFO_3 *i3;
+ * IDL } CONTROL_QUERY_INFORMATION;
+ */
+static int
+netlogon_dissect_CONTROL_QUERY_INFORMATION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, &level);
+
+ ALIGN_TO_4_BYTES;
+ switch(level){
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_NETLOGON_INFO_1, NDR_POINTER_UNIQUE,
+ "NETLOGON_INFO_1:", -1);
+ break;
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_NETLOGON_INFO_2, NDR_POINTER_UNIQUE,
+ "NETLOGON_INFO_2:", -1);
+ break;
+ case 3:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_NETLOGON_INFO_3, NDR_POINTER_UNIQUE,
+ "NETLOGON_INFO_3:", -1);
+ break;
+ }
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrLogonControl(
+ * IDL [in][string][unique] wchar_t *logonserver,
+ * IDL [in] long function_code,
+ * IDL [in] long level,
+ * IDL [out][ref] CONTROL_QUERY_INFORMATION
+ * IDL );
+ */
+static int
+netlogon_dissect_netrlogoncontrol_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_code, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, NULL);
+
+ return offset;
+}
+static int
+netlogon_dissect_netrlogoncontrol_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CONTROL_QUERY_INFORMATION, NDR_POINTER_REF,
+ "CONTROL_QUERY_INFORMATION:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrGetAnyDCName(
+ * IDL [in][unique][string] wchar_t *logon_server,
+ * IDL [in][unique][string] wchar_t *domainname,
+ * IDL [out][unique][string] wchar_t *dcname,
+ * IDL };
+ */
+static int
+netlogon_dissect_netrgetanydcname_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server Handle",
+ hf_netlogon_logonsrv_handle, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_netlogon_domain_name, 0);
+
+ return offset;
+}
+static int
+netlogon_dissect_netrgetanydcname_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_netlogon_dc_name, 0);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(5)] [unique][string] wchar_t *unknown;
+ * IDL [case(6)] [unique][string] wchar_t *unknown;
+ * IDL [case(0xfffe)] long unknown;
+ * IDL [case(7)] [unique][string] wchar_t *unknown;
+ * IDL } CONTROL_DATA_INFORMATION;
+ */
+/* XXX
+ * According to muddle this is what CONTROL_DATA_INFORMATION is supposed
+ * to look like. However NetMon does not recognize any such informationlevels.
+ *
+ * Ill leave it as CONTROL_DATA_INFORMATION with no informationlevels
+ * until someone has any source of better authority to call upon.
+ */
+static int
+netlogon_dissect_CONTROL_DATA_INFORMATION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, &level);
+
+ ALIGN_TO_4_BYTES;
+ switch(level){
+ case 5:
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo,
+ tree, drep, NDR_POINTER_UNIQUE, "unknown",
+ hf_netlogon_unknown_string, 0);
+ break;
+ case 6:
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo,
+ tree, drep, NDR_POINTER_UNIQUE, "unknown",
+ hf_netlogon_unknown_string, 0);
+ break;
+ case 0xfffe:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ break;
+ case 8:
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo,
+ tree, drep, NDR_POINTER_UNIQUE, "unknown",
+ hf_netlogon_unknown_string, 0);
+ break;
+ }
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrLogonControl2(
+ * IDL [in][string][unique] wchar_t *logonserver,
+ * IDL [in] long function_code,
+ * IDL [in] long level,
+ * IDL [in][ref] CONTROL_DATA_INFORMATION *data,
+ * IDL [out][ref] CONTROL_QUERY_INFORMATION *query
+ * IDL );
+ */
+static int
+netlogon_dissect_netrlogoncontrol2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_code, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CONTROL_DATA_INFORMATION, NDR_POINTER_REF,
+ "CONTROL_DATA_INFORMATION: ", -1);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogoncontrol2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CONTROL_QUERY_INFORMATION, NDR_POINTER_REF,
+ "CONTROL_QUERY_INFORMATION:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrServerAuthenticate2(
+ * IDL [in][string][unique] wchar_t *logonserver,
+ * IDL [in][ref][string] wchar_t *username,
+ * IDL [in] short secure_channel_type,
+ * IDL [in][ref][string] wchar_t *computername,
+ * IDL [in][ref] CREDENTIAL *client_chal,
+ * IDL [out][ref] CREDENTIAL *server_chal,
+ * IDL [in][out][ref] long *negotiate_flags,
+ * IDL );
+ */
+static int
+netlogon_dissect_netrserverauthenticate2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_REF,
+ "User Name", hf_netlogon_acct_name,
+ cb_wstr_postprocess, GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ offset = netlogon_dissect_NETLOGON_SECURE_CHANNEL_TYPE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CREDENTIAL, NDR_POINTER_REF,
+ "CREDENTIAL: client_chal", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_neg_flags, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrserverauthenticate2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CREDENTIAL, NDR_POINTER_REF,
+ "CREDENTIAL: server_chal", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_neg_flags, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrDatabaseSync2(
+ * IDL [in][string][ref] wchar_t *logonserver, # REF!!!
+ * IDL [in][string][ref] wchar_t *computername,
+ * IDL [in][ref] AUTHENTICATOR credential,
+ * IDL [in][out][ref] AUTHENTICATOR return_authenticator,
+ * IDL [in] long database_id,
+ * IDL [in] short restart_state,
+ * IDL [in][out][ref] long *sync_context,
+ * IDL [in] long preferredmaximumlength,
+ * IDL [out][unique] DELTA_ENUM_ARRAY *delta_enum_array
+ * IDL );
+ */
+static int
+netlogon_dissect_netrdatabasesync2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Server Handle", hf_netlogon_logonsrv_handle, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_database_id, NULL);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_restart_state, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_sync_context, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_max_size, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrdatabasesync2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_sync_context, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_ENUM_ARRAY, NDR_POINTER_UNIQUE,
+ "DELTA_ENUM_ARRAY: deltas", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrDatabaseRedo(
+ * IDL [in][string][ref] wchar_t *logonserver, # REF!!!
+ * IDL [in][string][ref] wchar_t *computername,
+ * IDL [in][ref] AUTHENTICATOR credential,
+ * IDL [in][out][ref] AUTHENTICATOR return_authenticator,
+ * IDL [in][ref][size_is(change_log_entry_size)] char *change_log_entry,
+ * IDL [in] long change_log_entry_size,
+ * IDL [out][unique] DELTA_ENUM_ARRAY *delta_enum_array
+ * IDL );
+ */
+static int
+netlogon_dissect_netrdatabaseredo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Server Handle", hf_netlogon_logonsrv_handle, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_array, NDR_POINTER_REF,
+ "Change log entry: ", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_max_log_size, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrdatabaseredo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DELTA_ENUM_ARRAY, NDR_POINTER_UNIQUE,
+ "DELTA_ENUM_ARRAY: deltas", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrLogonControl2Ex(
+ * IDL [in][string][unique] wchar_t *logonserver,
+ * IDL [in] long function_code,
+ * IDL [in] long level,
+ * IDL [in][ref] CONTROL_DATA_INFORMATION *data,
+ * IDL [out][ref] CONTROL_QUERY_INFORMATION *query
+ * IDL );
+ */
+static int
+netlogon_dissect_netrlogoncontrol2ex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_code, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CONTROL_DATA_INFORMATION, NDR_POINTER_REF,
+ "CONTROL_DATA_INFORMATION: ", -1);
+
+ return offset;
+}
+static int
+netlogon_dissect_netrlogoncontrol2ex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CONTROL_QUERY_INFORMATION, NDR_POINTER_REF,
+ "CONTROL_QUERY_INFORMATION:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string trust_type_vals[] = {
+ { 1, "DOWNLEVEL" },
+ { 2, "UPLEVEL" },
+ { 3, "MIT" },
+ { 4, "DCE" },
+ { 0, NULL }
+};
+
+#define DS_INET_ADDRESS 1
+#define DS_NETBIOS_ADDRESS 2
+static const value_string dc_address_types[] = {
+ { DS_INET_ADDRESS, "IP/DNS name" },
+ { DS_NETBIOS_ADDRESS, "NetBIOS name" },
+ { 0, NULL}
+};
+
+
+#define DS_DOMAIN_IN_FOREST 0x0001
+#define DS_DOMAIN_DIRECT_OUTBOUND 0x0002
+#define DS_DOMAIN_TREE_ROOT 0x0004
+#define DS_DOMAIN_PRIMARY 0x0008
+#define DS_DOMAIN_NATIVE_MODE 0x0010
+#define DS_DOMAIN_DIRECT_INBOUND 0x0020
+static const true_false_string trust_inbound = {
+ "There is a DIRECT INBOUND trust for the servers domain",
+ "There is NO direct inbound trust for the servers domain"
+};
+static const true_false_string trust_outbound = {
+ "There is a DIRECT OUTBOUND trust for this domain",
+ "There is NO direct outbound trust for this domain"
+};
+static const true_false_string trust_in_forest = {
+ "The domain is a member IN the same FOREST as the queried server",
+ "The domain is NOT a member of the queried servers domain"
+};
+static const true_false_string trust_native_mode = {
+ "The primary domain is a NATIVE MODE w2k domain",
+ "The primary is NOT a native mode w2k domain"
+};
+static const true_false_string trust_primary = {
+ "The domain is the PRIMARY domain of the queried server",
+ "The domain is NOT the primary domain of the queried server"
+};
+static const true_false_string trust_tree_root = {
+ "The domain is the ROOT of a domain TREE",
+ "The domain is NOT a root of a domain tree"
+};
+static int
+netlogon_dissect_DOMAIN_TRUST_FLAGS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_netlogon_trust_flags, &mask);
+
+ if(parent_tree){
+ item = proto_tree_add_uint(parent_tree, hf_netlogon_trust_flags,
+ tvb, offset-4, 4, mask);
+ tree = proto_item_add_subtree(item, ett_trust_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_netlogon_trust_flags_inbound,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_trust_flags_native_mode,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_trust_flags_primary,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_trust_flags_tree_root,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_trust_flags_outbound,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_trust_flags_in_forest,
+ tvb, offset-4, 4, mask);
+
+ return offset;
+}
+
+
+#define DS_FORCE_REDISCOVERY 0x00000001
+#define DS_DIRECTORY_SERVICE_REQUIRED 0x00000010
+#define DS_DIRECTORY_SERVICE_PREFERRED 0x00000020
+#define DS_GC_SERVER_REQUIRED 0x00000040
+#define DS_PDC_REQUIRED 0x00000080
+#define DS_BACKGROUND_ONLY 0x00000100
+#define DS_IP_REQUIRED 0x00000200
+#define DS_KDC_REQUIRED 0x00000400
+#define DS_TIMESERV_REQUIRED 0x00000800
+#define DS_WRITABLE_REQUIRED 0x00001000
+#define DS_GOOD_TIMESERV_PREFERRED 0x00002000
+#define DS_AVOID_SELF 0x00004000
+#define DS_ONLY_LDAP_NEEDED 0x00008000
+#define DS_IS_FLAT_NAME 0x00010000
+#define DS_IS_DNS_NAME 0x00020000
+#define DS_RETURN_DNS_NAME 0x40000000
+#define DS_RETURN_FLAT_NAME 0x80000000
+static const true_false_string get_dcname_request_flags_force_rediscovery = {
+ "FORCE REDISCOVERY of any cached data",
+ "You may return cached data"
+};
+static const true_false_string get_dcname_request_flags_directory_service_required = {
+ "DIRECRTORY SERVICE is REQUIRED on the server",
+ "We do NOT require directory service servers"
+};
+static const true_false_string get_dcname_request_flags_directory_service_preferred = {
+ "DIRECTORY SERVICE servers are PREFERRED",
+ "We do NOT have a preference for directory service servers"
+};
+static const true_false_string get_dcname_request_flags_gc_server_required = {
+ "GC SERVER is REQUIRED",
+ "gc server is NOT required"
+};
+static const true_false_string get_dcname_request_flags_pdc_required = {
+ "PDC SERVER is REQUIRED",
+ "pdc server is NOT required"
+};
+static const true_false_string get_dcname_request_flags_background_only = {
+ "Only returned cahced data, even if it has expired",
+ "Return cached data unless it has expired"
+};
+static const true_false_string get_dcname_request_flags_ip_required = {
+ "IP address is REQUIRED",
+ "ip address is NOT required"
+};
+static const true_false_string get_dcname_request_flags_kdc_required = {
+ "KDC server is REQUIRED",
+ "kdc server is NOT required"
+};
+static const true_false_string get_dcname_request_flags_timeserv_required = {
+ "TIMESERV service is REQUIRED",
+ "timeserv service is NOT required"
+};
+static const true_false_string get_dcname_request_flags_writable_required = {
+ "the requrned dc MUST be WRITEABLE",
+ "a read-only dc may be returned"
+};
+static const true_false_string get_dcname_request_flags_good_timeserv_preferred = {
+ "GOOD TIMESERV servers are PREFERRED",
+ "we do NOT have a preference for good timeserv servers"
+};
+static const true_false_string get_dcname_request_flags_avoid_self = {
+ "do NOT return self as dc, return someone else",
+ "you may return yourSELF as the dc"
+};
+static const true_false_string get_dcname_request_flags_only_ldap_needed = {
+ "we ONLY NEED LDAP, you dont have to return a dc",
+ "we need a normal dc, an ldap only server will not do"
+};
+static const true_false_string get_dcname_request_flags_is_flat_name = {
+ "the name we specify is a NetBIOS name",
+ "the name we specify is NOT a NetBIOS name"
+};
+static const true_false_string get_dcname_request_flags_is_dns_name = {
+ "the name we specify is a DNS name",
+ "ther name we specify is NOT a dns name"
+};
+static const true_false_string get_dcname_request_flags_return_dns_name = {
+ "return a DNS name",
+ "you may return a NON-dns name"
+};
+static const true_false_string get_dcname_request_flags_return_flat_name = {
+ "return a NetBIOS name",
+ "you may return a NON-NetBIOS name"
+};
+static int
+netlogon_dissect_GET_DCNAME_REQUEST_FLAGS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_netlogon_get_dcname_request_flags, &mask);
+
+ if(parent_tree){
+ item = proto_tree_add_uint(parent_tree, hf_netlogon_get_dcname_request_flags,
+ tvb, offset-4, 4, mask);
+ tree = proto_item_add_subtree(item, ett_get_dcname_request_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_return_flat_name,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_return_dns_name,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_is_flat_name,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_is_dns_name,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_only_ldap_needed,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_avoid_self,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_good_timeserv_preferred,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_writable_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_timeserv_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_kdc_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_ip_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_background_only,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_pdc_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_gc_server_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_directory_service_preferred,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_directory_service_required,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_get_dcname_request_flags_force_rediscovery,
+ tvb, offset-4, 4, mask);
+
+ return offset;
+}
+
+
+
+#define DS_PDC_FLAG 0x00000001
+#define DS_GC_FLAG 0x00000004
+#define DS_LDAP_FLAG 0x00000008
+#define DS_DS_FLAG 0x00000010
+#define DS_KDC_FLAG 0x00000020
+#define DS_TIMESERV_FLAG 0x00000040
+#define DS_CLOSEST_FLAG 0x00000080
+#define DS_WRITABLE_FLAG 0x00000100
+#define DS_GOOD_TIMESERV_FLAG 0x00000200
+#define DS_NDNC_FLAG 0x00000400
+#define DS_DNS_CONTROLLER_FLAG 0x20000000
+#define DS_DNS_DOMAIN_FLAG 0x40000000
+#define DS_DNS_FOREST_FLAG 0x80000000
+static const true_false_string dc_flags_pdc_flag = {
+ "this is the PDC of the domain",
+ "this is NOT the pdc of the domain"
+};
+static const true_false_string dc_flags_gc_flag = {
+ "this is the GC of the forest",
+ "this is NOT the gc of the forest"
+};
+static const true_false_string dc_flags_ldap_flag = {
+ "this is an LDAP server",
+ "this is NOT an ldap server"
+};
+static const true_false_string dc_flags_ds_flag = {
+ "this is a DS server",
+ "this is NOT a ds server"
+};
+static const true_false_string dc_flags_kdc_flag = {
+ "this is a KDC server",
+ "this is NOT a kdc server"
+};
+static const true_false_string dc_flags_timeserv_flag = {
+ "this is a TIMESERV server",
+ "this is NOT a timeserv server"
+};
+static const true_false_string dc_flags_closest_flag = {
+ "this is the CLOSEST server",
+ "this is NOT the closest server"
+};
+static const true_false_string dc_flags_writable_flag = {
+ "this server has a WRITABLE ds database",
+ "this server has a READ-ONLY ds database"
+};
+static const true_false_string dc_flags_good_timeserv_flag = {
+ "this server is a GOOD TIMESERV server",
+ "this is NOT a good timeserv server"
+};
+static const true_false_string dc_flags_ndnc_flag = {
+ "NDNC is set",
+ "ndnc is NOT set"
+};
+static const true_false_string dc_flags_dns_controller_flag = {
+ "DomainControllerName is a DNS name",
+ "DomainControllerName is NOT a dns name"
+};
+static const true_false_string dc_flags_dns_domain_flag = {
+ "DomainName is a DNS name",
+ "DomainName is NOT a dns name"
+};
+static const true_false_string dc_flags_dns_forest_flag = {
+ "DnsForestName is a DNS name",
+ "DnsForestName is NOT a dns name"
+};
+static int
+netlogon_dissect_DC_FLAGS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_netlogon_dc_flags, &mask);
+
+ if(parent_tree){
+ item = proto_tree_add_uint_format(parent_tree, hf_netlogon_dc_flags,
+ tvb, offset-4, 4, mask, "Domain Controller Flags: 0x%08x%s", mask, (mask==0x0000ffff)?" PING (mask==0x0000ffff)":"");
+ tree = proto_item_add_subtree(item, ett_dc_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_dns_forest_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_dns_domain_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_dns_controller_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_ndnc_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_good_timeserv_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_writable_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_closest_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_timeserv_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_kdc_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_ds_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_ldap_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_gc_flag,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_netlogon_dc_flags_pdc_flag,
+ tvb, offset-4, 4, mask);
+
+ return offset;
+}
+
+
+
+static int
+netlogon_dissect_pointer_long(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ return offset;
+}
+
+static int
+netlogon_dissect_pointer_char(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ return offset;
+}
+
+static int
+netlogon_dissect_UNICODE_MULTI_byte(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_char, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_UNICODE_MULTI_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_UNICODE_MULTI_byte);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_UNICODE_MULTI(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "UNICODE_MULTI:");
+ tree = proto_item_add_subtree(item, ett_UNICODE_MULTI);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_len, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_UNICODE_MULTI_array, NDR_POINTER_UNIQUE,
+ "unknown", hf_netlogon_unknown_string);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+int
+dissect_nt_GUID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset=dissect_ndr_uuid_t(tvb, offset, pinfo, tree, drep, hf_netlogon_guid, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_DOMAIN_CONTROLLER_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "DOMAIN_CONTROLLER_INFO:");
+ tree = proto_item_add_subtree(item, ett_DOMAIN_CONTROLLER_INFO);
+ }
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "DC Name", hf_netlogon_dc_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "DC Address", hf_netlogon_dc_address, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dc_address_type, NULL);
+
+ offset = dissect_nt_GUID(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Logon Domain", hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "DNS Forest", hf_netlogon_dns_forest_name, 0);
+
+ offset = netlogon_dissect_DC_FLAGS(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "DC Site", hf_netlogon_dc_site_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Client Site",
+ hf_netlogon_client_site_name, 0);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+netlogon_dissect_BLOB_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect.*/
+ return offset;
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_blob_size, &len);
+
+ proto_tree_add_item(tree, hf_netlogon_blob, tvb, offset, len,
+ FALSE);
+ offset += len;
+
+ return offset;
+}
+
+static int
+netlogon_dissect_BLOB(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "BLOB:");
+ tree = proto_item_add_subtree(item, ett_BLOB);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_blob_size, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BLOB_array, NDR_POINTER_UNIQUE,
+ "BLOB:", -1);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_DOMAIN_TRUST_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "DOMAIN_TRUST_INFO:");
+ tree = proto_item_add_subtree(item, ett_DOMAIN_TRUST_INFO);
+ }
+
+
+ offset = lsa_dissect_POLICY_DNS_DOMAIN_INFO(tvb, offset, pinfo, tree, drep);
+
+ /* Guesses at best. */
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+netlogon_dissect_DOMAIN_TRUST_INFO_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_TRUST_INFO);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_DOMAIN_QUERY_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = netlogon_dissect_BLOB(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Workstation FQDN",
+ hf_netlogon_workstation_fqdn, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Workstation Site",
+ hf_netlogon_workstation_site_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown", hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown", hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown", hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown", hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_workstation_os, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_DOMAIN_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = netlogon_dissect_DOMAIN_TRUST_INFO(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_trusts, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_TRUST_INFO_ARRAY, NDR_POINTER_UNIQUE,
+ "DOMAIN_TRUST_ARRAY: Trusts", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_num_trusts, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_TRUST_INFO_ARRAY, NDR_POINTER_UNIQUE,
+ "DOMAIN_TRUST_ARRAY:", -1);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_dns_domain_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_string, 0);
+
+ /* These four integers appear to mirror the last four in the query. */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_DOMAIN_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, &level);
+
+ ALIGN_TO_4_BYTES;
+ switch(level){
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_INFO_1, NDR_POINTER_UNIQUE,
+ "DOMAIN_INFO_1:", -1);
+ break;
+ }
+
+ return offset;
+}
+
+static int
+netlogon_dissect_UNICODE_STRING_512(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ int i;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "UNICODE_STRING_512:");
+ tree = proto_item_add_subtree(item, ett_UNICODE_STRING_512);
+ }
+
+ for(i=0;i<512;i++){
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_short, NULL);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+netlogon_dissect_element_844_byte(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_char, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_element_844_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_element_844_byte);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_TYPE_50(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "TYPE_50:");
+ tree = proto_item_add_subtree(item, ett_TYPE_50);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_element_844_array, NDR_POINTER_UNIQUE,
+ "unknown", hf_netlogon_unknown_string);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+netlogon_dissect_TYPE_50_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_TYPE_50, NDR_POINTER_UNIQUE,
+ "TYPE_50 pointer: unknown_TYPE_50", -1);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_DS_DOMAIN_TRUSTS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ guint32 tmp;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "DS_DOMAIN_TRUSTS");
+ tree = proto_item_add_subtree(item, ett_DS_DOMAIN_TRUSTS);
+ }
+
+ /* name */
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "NetBIOS Name",
+ hf_netlogon_downlevel_domain_name, 0);
+
+ /* domain */
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "DNS Domain Name",
+ hf_netlogon_dns_domain_name, 0);
+
+ offset = netlogon_dissect_DOMAIN_TRUST_FLAGS(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_trust_parent_index, &tmp);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_trust_type, &tmp);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_trust_attribs, &tmp);
+
+ /* SID pointer */
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ /* GUID */
+ offset = dissect_nt_GUID(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+netlogon_dissect_DS_DOMAIN_TRUSTS_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DS_DOMAIN_TRUSTS);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_element_865_byte(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_char, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_element_865_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_element_865_byte);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_element_866_byte(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_char, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_element_866_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_element_866_byte);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_TYPE_52(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "TYPE_52:");
+ tree = proto_item_add_subtree(item, ett_TYPE_52);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_element_865_array, NDR_POINTER_UNIQUE,
+ "unknown", hf_netlogon_unknown_string);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_element_866_array, NDR_POINTER_UNIQUE,
+ "unknown", hf_netlogon_unknown_string);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+netlogon_dissect_TYPE_52_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_TYPE_52, NDR_POINTER_UNIQUE,
+ "TYPE_52 pointer: unknown_TYPE_52", -1);
+ return offset;
+}
+
+
+static int
+netlogon_dissect_TYPE_44(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint32 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "TYPE_44:");
+ tree = proto_item_add_subtree(item, ett_TYPE_44);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, &level);
+
+ ALIGN_TO_4_BYTES;
+ switch(level){
+ case 1:
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+netlogon_dissect_DOMAIN_QUERY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_level, &level);
+
+ ALIGN_TO_4_BYTES;
+ switch(level){
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_QUERY_1, NDR_POINTER_UNIQUE,
+ "DOMAIN_QUERY_1:", -1);
+ break;
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_QUERY_1, NDR_POINTER_UNIQUE,
+ "DOMAIN_QUERY_1:", -1);
+ break;
+ }
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrenumeratetrusteddomains_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrenumeratetrusteddomains_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_UNICODE_MULTI, NDR_POINTER_REF,
+ "UNICODE_MULTI pointer: trust_dom_name_list", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_dsrgetdcname_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_nt_GUID, NDR_POINTER_UNIQUE,
+ "GUID pointer: domain_guid", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_nt_GUID, NDR_POINTER_UNIQUE,
+ "GUID pointer: site_guid", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_flags, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsrgetdcname_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_CONTROLLER_INFO, NDR_POINTER_UNIQUE,
+ "DOMAIN_CONTROLLER_INFO:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogondummyroutine1_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogondummyroutine1_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_TYPE_44, NDR_POINTER_UNIQUE,
+ "TYPE_44 pointer: unknown_TYPE_44", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogonsetservicebits_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogonsetservicebits_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogongettrustrid_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_netlogon_unknown_string, 0);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogongettrustrid_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "ULONG pointer: unknown_ULONG", hf_netlogon_unknown_long);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogoncomputeserverdigest_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_array, NDR_POINTER_UNIQUE,
+ "BYTE pointer: unknown_BYTE", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_BYTE_16_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ int i;
+
+ for(i=0;i<16;i++){
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_char, NULL);
+ }
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogoncomputeserverdigest_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_16_array, NDR_POINTER_UNIQUE,
+ "BYTE pointer: unknown_BYTE", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogoncomputeclientdigest_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_array, NDR_POINTER_UNIQUE,
+ "BYTE pointer: unknown_BYTE", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogoncomputeclientdigest_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_16_array, NDR_POINTER_UNIQUE,
+ "BYTE pointer: unknown_BYTE", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrserverauthenticate3_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Acct Name", hf_netlogon_acct_name, 0);
+
+ offset = netlogon_dissect_NETLOGON_SECURE_CHANNEL_TYPE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer Name", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CREDENTIAL, NDR_POINTER_REF,
+ "CREDENTIAL: authenticator", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_neg_flags, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrserverauthenticate3_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_CREDENTIAL, NDR_POINTER_REF,
+ "CREDENTIAL pointer: unknown_NETLOGON_CREDENTIAL", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_neg_flags, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_pointer_long, NDR_POINTER_REF,
+ "ULONG: unknown_ULONG", hf_netlogon_unknown_long);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_dsrgetdcnameex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_nt_GUID, NDR_POINTER_UNIQUE,
+ "GUID pointer: domain_guid", -1);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Site Name", hf_netlogon_site_name, 0);
+
+ offset = netlogon_dissect_GET_DCNAME_REQUEST_FLAGS(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsrgetdcnameex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_CONTROLLER_INFO, NDR_POINTER_UNIQUE,
+ "DOMAIN_CONTROLLER_INFO:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_dsrgetsitename_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsrgetsitename_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ /* XXX hmmm this does not really look like a UNIQUE pointer but
+ will do for now. I think it is really a 32bit integer followed by
+ a REF pointer to a unicode string */
+ offset = dissect_ndr_pointer_cb(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE, "Site Name",
+ hf_netlogon_site_name, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogongetdomaininfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ /* Unlike the other NETLOGON RPCs, this is not a unique pointer. */
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Server Handle", hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Computer Name",
+ hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_QUERY, NDR_POINTER_REF,
+ "DOMAIN_QUERY: ", -1);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogongetdomaininfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_INFO, NDR_POINTER_REF,
+ "DOMAIN_INFO: ", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrserverpasswordset2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_short, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = netlogon_dissect_UNICODE_STRING_512(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrserverpasswordset2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrserverpasswordget_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Acct Name", hf_netlogon_acct_name, 0);
+
+ offset = netlogon_dissect_NETLOGON_SECURE_CHANNEL_TYPE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Computer Name",
+ hf_netlogon_computer_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrserverpasswordget_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_LM_OWF_PASSWORD, NDR_POINTER_REF,
+ "LM_OWF_PASSWORD pointer: server_pwd", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogonsendtosam_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_REF,
+ "AUTHENTICATOR: credential", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_array, NDR_POINTER_UNIQUE,
+ "BYTE pointer: unknown_BYTE", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogonsendtosam_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_AUTHENTICATOR, NDR_POINTER_UNIQUE,
+ "AUTHENTICATOR: return_authenticator", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_dsraddresstositenamesw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_array, NDR_POINTER_UNIQUE,
+ "BYTE pointer: unknown_BYTE", -1);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsraddresstositenamesw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_TYPE_50_ptr, NDR_POINTER_UNIQUE,
+ "TYPE_50** pointer: unknown_TYPE_50", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_dsrgetdcnameex2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Client Account",
+ hf_netlogon_acct_name, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Client Account",
+ hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_nt_GUID, NDR_POINTER_UNIQUE,
+ "Domain GUID:", -1);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Client Site",
+ hf_netlogon_site_name, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsrgetdcnameex2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DOMAIN_CONTROLLER_INFO, NDR_POINTER_UNIQUE,
+ "DOMAIN_CONTROLLER_INFO:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogongettimeserviceparentdomain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogongettimeserviceparentdomain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "ULONG pointer: unknown_ULONG", hf_netlogon_unknown_long);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrenumeratetrusteddomainsex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrenumeratetrusteddomainsex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DS_DOMAIN_TRUSTS_ARRAY, NDR_POINTER_UNIQUE,
+ "DS_DOMAIN_TRUSTS_ARRAY:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_dsraddresstositenamesexw_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_long, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_BYTE_array, NDR_POINTER_UNIQUE,
+ "BYTE pointer: unknown_BYTE", -1);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsraddresstositenamesexw_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_TYPE_52_ptr, NDR_POINTER_UNIQUE,
+ "TYPE_52 pointer: unknown_TYPE_52", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_site_name_item(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_counted_string_cb(
+ tvb, offset, pinfo, tree, drep, hf_netlogon_site_name,
+ cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ return offset;
+}
+static int
+netlogon_dissect_site_name_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_site_name_item);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_site_names(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_count, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_site_name_array, NDR_POINTER_UNIQUE,
+ "Site name array", -1);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_dsrgetdcsitecoveragew_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsrgetdcsitecoveragew_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_site_names, NDR_POINTER_UNIQUE,
+ "Site names", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_netrlogonsamlogonex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "unknown string",
+ hf_netlogon_unknown_string, 0);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_short, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_LEVEL, NDR_POINTER_UNIQUE,
+ "LEVEL pointer: unknown_NETLOGON_LEVEL", -1);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_unknown_short, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "ULONG pointer: unknown_ULONG", hf_netlogon_unknown_long);
+ return offset;
+}
+
+
+static int
+netlogon_dissect_netrlogonsamlogonex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_VALIDATION, NDR_POINTER_UNIQUE,
+ "VALIDATION: unknown_NETLOGON_VALIDATION", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_pointer_char, NDR_POINTER_UNIQUE,
+ "BOOLEAN pointer: unknown_BOOLEAN", hf_netlogon_unknown_char);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "ULONG pointer: unknown_ULONG", hf_netlogon_unknown_long);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsrenumeratedomaintrusts_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = netlogon_dissect_DOMAIN_TRUST_FLAGS(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsrenumeratedomaintrusts_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_DS_DOMAIN_TRUSTS_ARRAY, NDR_POINTER_UNIQUE,
+ "DS_DOMAIN_TRUSTS_ARRAY:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+static int
+netlogon_dissect_dsrderegisterdnshostrecords_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = netlogon_dissect_LOGONSRV_HANDLE(tvb, offset,
+ pinfo, tree, drep);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_netlogon_logon_dom, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_nt_GUID, NDR_POINTER_UNIQUE,
+ "GUID pointer: domain_guid", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_nt_GUID, NDR_POINTER_UNIQUE,
+ "GUID pointer: dsa_guid", -1);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "dns_host", hf_netlogon_dns_host, 0);
+
+ return offset;
+}
+
+
+static int
+netlogon_dissect_dsrderegisterdnshostrecords_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_netlogon_rc, NULL);
+
+ return offset;
+}
+
+/* Dissect secure channel stuff */
+
+static int hf_netlogon_secchan_bind_unknown1 = -1;
+static int hf_netlogon_secchan_bind_unknown2 = -1;
+static int hf_netlogon_secchan_domain = -1;
+static int hf_netlogon_secchan_host = -1;
+static int hf_netlogon_secchan_bind_ack_unknown1 = -1;
+static int hf_netlogon_secchan_bind_ack_unknown2 = -1;
+static int hf_netlogon_secchan_bind_ack_unknown3 = -1;
+
+static gint ett_secchan_verf = -1;
+static gint ett_secchan_bind_creds = -1;
+static gint ett_secchan_bind_ack_creds = -1;
+
+static int dissect_secchan_bind_creds(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+ int len;
+
+ if (tree) {
+ item = proto_tree_add_text(
+ tree, tvb, offset, -1,
+ "Secure Channel Bind Credentials");
+ subtree = proto_item_add_subtree(
+ item, ett_secchan_bind_creds);
+ }
+
+ /* We can't use the NDR routines as the DCERPC call data hasn't
+ been initialised since we haven't made a DCERPC call yet, just
+ a bind request. */
+
+ offset = dissect_dcerpc_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_netlogon_secchan_bind_unknown1, NULL);
+
+ offset = dissect_dcerpc_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_netlogon_secchan_bind_unknown2, NULL);
+
+ len = tvb_strsize(tvb, offset);
+
+ proto_tree_add_item(
+ subtree, hf_netlogon_secchan_domain, tvb, offset, len, FALSE);
+
+ offset += len;
+
+ len = tvb_strsize(tvb, offset);
+
+ proto_tree_add_item(
+ subtree, hf_netlogon_secchan_host, tvb, offset, len, FALSE);
+
+ offset += len;
+
+ return offset;
+}
+
+static int dissect_secchan_bind_ack_creds(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+
+ if (tree) {
+ item = proto_tree_add_text(
+ tree, tvb, offset, -1,
+ "Secure Channel Bind ACK Credentials");
+ subtree = proto_item_add_subtree(
+ item, ett_secchan_bind_ack_creds);
+ }
+
+ /* Don't use NDR routines here */
+
+ offset = dissect_dcerpc_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_netlogon_secchan_bind_ack_unknown1, NULL);
+
+ offset = dissect_dcerpc_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_netlogon_secchan_bind_ack_unknown2, NULL);
+
+ offset = dissect_dcerpc_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_netlogon_secchan_bind_ack_unknown3, NULL);
+
+ return offset;
+}
+
+/* Subdissectors */
+
+static dcerpc_sub_dissector dcerpc_netlogon_dissectors[] = {
+ { NETLOGON_NETRLOGONUASLOGON, "NetrLogonUasLogon",
+ netlogon_dissect_netrlogonuaslogon_rqst,
+ netlogon_dissect_netrlogonuaslogon_reply },
+ { NETLOGON_NETRLOGONUASLOGOFF, "NetrLogonUasLogoff",
+ netlogon_dissect_netrlogonuaslogoff_rqst,
+ netlogon_dissect_netrlogonuaslogoff_reply },
+ { NETLOGON_NETRLOGONSAMLOGON, "NetrLogonSamLogon",
+ netlogon_dissect_netrlogonsamlogon_rqst,
+ netlogon_dissect_netrlogonsamlogon_reply },
+ { NETLOGON_NETRLOGONSAMLOGOFF, "NetrLogonSamLogoff",
+ netlogon_dissect_netrlogonsamlogoff_rqst,
+ netlogon_dissect_netrlogonsamlogoff_reply },
+ { NETLOGON_NETRSERVERREQCHALLENGE, "NetrServerReqChallenge",
+ netlogon_dissect_netrserverreqchallenge_rqst,
+ netlogon_dissect_netrserverreqchallenge_reply },
+ { NETLOGON_NETRSERVERAUTHENTICATE, "NetrServerAuthenticate",
+ netlogon_dissect_netrserverauthenticate_rqst,
+ netlogon_dissect_netrserverauthenticate_reply },
+ { NETLOGON_NETRSERVERPASSWORDSET, "NetrServerPasswordSet",
+ netlogon_dissect_netrserverpasswordset_rqst,
+ netlogon_dissect_netrserverpasswordset_reply },
+ { NETLOGON_NETRDATABASEDELTAS, "NetrDatabaseDeltas",
+ netlogon_dissect_netrdatabasedeltas_rqst,
+ netlogon_dissect_netrdatabasedeltas_reply },
+ { NETLOGON_NETRDATABASESYNC, "NetrDatabaseSync",
+ netlogon_dissect_netrdatabasesync_rqst,
+ netlogon_dissect_netrdatabasesync_reply },
+ { NETLOGON_NETRACCOUNTDELTAS, "NetrAccountDeltas",
+ netlogon_dissect_netraccountdeltas_rqst,
+ netlogon_dissect_netraccountdeltas_reply },
+ { NETLOGON_NETRACCOUNTSYNC, "NetrAccountSync",
+ netlogon_dissect_netraccountsync_rqst,
+ netlogon_dissect_netraccountsync_reply },
+ { NETLOGON_NETRGETDCNAME, "NetrGetDCName",
+ netlogon_dissect_netrgetdcname_rqst,
+ netlogon_dissect_netrgetdcname_reply },
+ { NETLOGON_NETRLOGONCONTROL, "NetrLogonControl",
+ netlogon_dissect_netrlogoncontrol_rqst,
+ netlogon_dissect_netrlogoncontrol_reply },
+ { NETLOGON_NETRGETANYDCNAME, "NetrGetAnyDCName",
+ netlogon_dissect_netrgetanydcname_rqst,
+ netlogon_dissect_netrgetanydcname_reply },
+ { NETLOGON_NETRLOGONCONTROL2, "NetrLogonControl2",
+ netlogon_dissect_netrlogoncontrol2_rqst,
+ netlogon_dissect_netrlogoncontrol2_reply },
+ { NETLOGON_NETRSERVERAUTHENTICATE2, "NetrServerAuthenticate2",
+ netlogon_dissect_netrserverauthenticate2_rqst,
+ netlogon_dissect_netrserverauthenticate2_reply },
+ { NETLOGON_NETRDATABASESYNC2, "NetrDatabaseSync2",
+ netlogon_dissect_netrdatabasesync2_rqst,
+ netlogon_dissect_netrdatabasesync2_reply },
+ { NETLOGON_NETRDATABASEREDO, "NetrDatabaseRedo",
+ netlogon_dissect_netrdatabaseredo_rqst,
+ netlogon_dissect_netrdatabaseredo_reply },
+ { NETLOGON_NETRLOGONCONTROL2EX, "NetrLogonControl2Ex",
+ netlogon_dissect_netrlogoncontrol2ex_rqst,
+ netlogon_dissect_netrlogoncontrol2ex_reply },
+ { NETLOGON_NETRENUMERATETRUSTEDDOMAINS, "NetrEnumerateTrustedDomains",
+ netlogon_dissect_netrenumeratetrusteddomains_rqst,
+ netlogon_dissect_netrenumeratetrusteddomains_reply },
+ { NETLOGON_DSRGETDCNAME, "DsrGetDcName",
+ netlogon_dissect_dsrgetdcname_rqst,
+ netlogon_dissect_dsrgetdcname_reply },
+ { NETLOGON_NETRLOGONDUMMYROUTINE1, "NetrLogonDummyRoutine1",
+ netlogon_dissect_netrlogondummyroutine1_rqst,
+ netlogon_dissect_netrlogondummyroutine1_reply },
+ { NETLOGON_NETRLOGONSETSERVICEBITS, "NetrLogonSetServiceBits",
+ netlogon_dissect_netrlogonsetservicebits_rqst,
+ netlogon_dissect_netrlogonsetservicebits_reply },
+ { NETLOGON_NETRLOGONGETTRUSTRID, "NetrLogonGetTrustRid",
+ netlogon_dissect_netrlogongettrustrid_rqst,
+ netlogon_dissect_netrlogongettrustrid_reply },
+ { NETLOGON_NETRLOGONCOMPUTESERVERDIGEST, "NetrLogonComputeServerDigest",
+ netlogon_dissect_netrlogoncomputeserverdigest_rqst,
+ netlogon_dissect_netrlogoncomputeserverdigest_reply },
+ { NETLOGON_NETRLOGONCOMPUTECLIENTDIGEST, "NetrLogonComputeClientDigest",
+ netlogon_dissect_netrlogoncomputeclientdigest_rqst,
+ netlogon_dissect_netrlogoncomputeclientdigest_reply },
+ { NETLOGON_NETRSERVERAUTHENTICATE3, "NetrServerAuthenticate3",
+ netlogon_dissect_netrserverauthenticate3_rqst,
+ netlogon_dissect_netrserverauthenticate3_reply },
+ { NETLOGON_DSRGETDCNAMEX, "DsrGetDcNameEx",
+ netlogon_dissect_dsrgetdcnameex_rqst,
+ netlogon_dissect_dsrgetdcnameex_reply },
+ { NETLOGON_DSRGETSITENAME, "DsrGetSiteName",
+ netlogon_dissect_dsrgetsitename_rqst,
+ netlogon_dissect_dsrgetsitename_reply },
+ { NETLOGON_NETRLOGONGETDOMAININFO, "NetrLogonGetDomainInfo",
+ netlogon_dissect_netrlogongetdomaininfo_rqst,
+ netlogon_dissect_netrlogongetdomaininfo_reply },
+ { NETLOGON_NETRSERVERPASSWORDSET2, "NetrServerPasswordSet2",
+ netlogon_dissect_netrserverpasswordset2_rqst,
+ netlogon_dissect_netrserverpasswordset2_reply },
+ { NETLOGON_NETRSERVERPASSWORDGET, "NetrServerPasswordGet",
+ netlogon_dissect_netrserverpasswordget_rqst,
+ netlogon_dissect_netrserverpasswordget_reply },
+ { NETLOGON_NETRLOGONSENDTOSAM, "NetrLogonSendToSam",
+ netlogon_dissect_netrlogonsendtosam_rqst,
+ netlogon_dissect_netrlogonsendtosam_reply },
+ { NETLOGON_DSRADDRESSTOSITENAMESW, "DsrAddressToSiteNamesW",
+ netlogon_dissect_dsraddresstositenamesw_rqst,
+ netlogon_dissect_dsraddresstositenamesw_reply },
+ { NETLOGON_DSRGETDCNAMEEX2, "DsrGetDcNameEx2",
+ netlogon_dissect_dsrgetdcnameex2_rqst,
+ netlogon_dissect_dsrgetdcnameex2_reply },
+ { NETLOGON_NETRLOGONGETTIMESERVICEPARENTDOMAIN,
+ "NetrLogonGetTimeServiceParentDomain",
+ netlogon_dissect_netrlogongettimeserviceparentdomain_rqst,
+ netlogon_dissect_netrlogongettimeserviceparentdomain_reply },
+ { NETLOGON_NETRENUMERATETRUSTEDDOMAINSEX, "NetrEnumerateTrustedDomainsEx",
+ netlogon_dissect_netrenumeratetrusteddomainsex_rqst,
+ netlogon_dissect_netrenumeratetrusteddomainsex_reply },
+ { NETLOGON_DSRADDRESSTOSITENAMESEXW, "DsrAddressToSiteNamesExW",
+ netlogon_dissect_dsraddresstositenamesexw_rqst,
+ netlogon_dissect_dsraddresstositenamesexw_reply },
+ { NETLOGON_DSRGETDCSITECOVERAGEW, "DsrGetDcSiteCoverageW",
+ netlogon_dissect_dsrgetdcsitecoveragew_rqst,
+ netlogon_dissect_dsrgetdcsitecoveragew_reply },
+ { NETLOGON_NETRLOGONSAMLOGONEX, "NetrLogonSamLogonEx",
+ netlogon_dissect_netrlogonsamlogonex_rqst,
+ netlogon_dissect_netrlogonsamlogonex_reply },
+ { NETLOGON_DSRENUMERATEDOMAINTRUSTS, "DsrEnumerateDomainTrusts",
+ netlogon_dissect_dsrenumeratedomaintrusts_rqst,
+ netlogon_dissect_dsrenumeratedomaintrusts_reply },
+ { NETLOGON_DSRDEREGISTERDNSHOSTRECORDS, "DsrDeregisterDnsHostRecords",
+ netlogon_dissect_dsrderegisterdnshostrecords_rqst,
+ netlogon_dissect_dsrderegisterdnshostrecords_reply },
+ { NETLOGON_NETRSERVERTRUSTPASSWORDSGET, "NetrServerTrustPasswordsGet",
+ NULL, NULL },
+ { NETLOGON_DSRGETFORESTTRUSTINFORMATION, "DsrGetForestTrustInformation",
+ NULL, NULL },
+ { NETLOGON_NETRGETFORESTTRUSTINFORMATION, "NetrGetForestTrustInformation",
+ NULL, NULL },
+ { NETLOGON_NETRLOGONSAMLOGONWITHFLAGS, "NetrLogonSamLogonWithFlags",
+ NULL, NULL },
+ { NETLOGON_NETRSERVERGETTRUSTINFO, "NetrServerGetTrustInfo",
+ NULL, NULL },
+ {0, NULL, NULL, NULL }
+};
+
+static int hf_netlogon_secchan_verf = -1;
+static int hf_netlogon_secchan_verf_sig = -1;
+static int hf_netlogon_secchan_verf_unk = -1;
+static int hf_netlogon_secchan_verf_seq = -1;
+static int hf_netlogon_secchan_verf_nonce = -1;
+
+static int
+dissect_secchan_verf(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ proto_item *vf = NULL;
+ proto_tree *subtree = NULL;
+
+ /*
+ * Create a new tree, and split into 4 components ...
+ */
+ vf = proto_tree_add_item(tree, hf_netlogon_secchan_verf, tvb,
+ offset, -1, FALSE);
+ subtree = proto_item_add_subtree(vf, ett_secchan_verf);
+
+ proto_tree_add_item(subtree, hf_netlogon_secchan_verf_sig, tvb,
+ offset, 8, FALSE);
+ offset += 8;
+
+ proto_tree_add_item(subtree, hf_netlogon_secchan_verf_unk, tvb,
+ offset, 8, FALSE);
+ offset += 8;
+
+ proto_tree_add_item(subtree, hf_netlogon_secchan_verf_seq, tvb,
+ offset, 8, FALSE);
+ offset += 8;
+
+ /* In some cases the nonce isn't present although it isn't clear
+ why this is so. */
+
+ if (tvb_bytes_exist(tvb, offset, 8)) {
+ proto_tree_add_item(subtree, hf_netlogon_secchan_verf_nonce,
+ tvb, offset, 8, FALSE);
+ offset += 8;
+ }
+
+ return offset;
+}
+
+/* Secure channel types */
+
+static const value_string sec_chan_type_vals[] = {
+ { SEC_CHAN_WKSTA, "Workstation" },
+ { SEC_CHAN_DOMAIN, "Domain trust" },
+ { SEC_CHAN_BDC, "Backup domain controller" },
+ { 0, NULL }
+};
+
+void
+proto_register_dcerpc_netlogon(void)
+{
+
+static hf_register_info hf[] = {
+ { &hf_netlogon_opnum,
+ { "Operation", "netlogon.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ { &hf_netlogon_rc, {
+ "Return code", "netlogon.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "Netlogon return code", HFILL }},
+
+ { &hf_netlogon_param_ctrl, {
+ "Param Ctrl", "netlogon.param_ctrl", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Param ctrl", HFILL }},
+
+ { &hf_netlogon_logon_id, {
+ "Logon ID", "netlogon.logon_id", FT_UINT64, BASE_DEC,
+ NULL, 0x0, "Logon ID", HFILL }},
+
+ { &hf_netlogon_modify_count, {
+ "Modify Count", "netlogon.modify_count", FT_UINT64, BASE_DEC,
+ NULL, 0x0, "How many times the object has been modified", HFILL }},
+
+ { &hf_netlogon_security_information, {
+ "Security Information", "netlogon.security_information", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Security Information", HFILL }},
+
+ { &hf_netlogon_count, {
+ "Count", "netlogon.count", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_entries, {
+ "Entries", "netlogon.entries", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_credential, {
+ "Credential", "netlogon.credential", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Netlogon Credential", HFILL }},
+
+ { &hf_netlogon_challenge, {
+ "Challenge", "netlogon.challenge", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Netlogon challenge", HFILL }},
+
+ { &hf_netlogon_lm_owf_password, {
+ "LM Pwd", "netlogon.lm_owf_pwd", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "LanManager OWF Password", HFILL }},
+
+ { &hf_netlogon_user_session_key, {
+ "User Session Key", "netlogon.user_session_key", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "User Session Key", HFILL }},
+
+ { &hf_netlogon_encrypted_lm_owf_password, {
+ "Encrypted LM Pwd", "netlogon.lm_owf_pwd.encrypted", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Encrypted LanManager OWF Password", HFILL }},
+
+ { &hf_netlogon_nt_owf_password, {
+ "NT Pwd", "netlogon.nt_owf_pwd", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "NT OWF Password", HFILL }},
+
+ { &hf_netlogon_blob, {
+ "BLOB", "netlogon.blob", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "BLOB", HFILL }},
+
+ { &hf_netlogon_len, {
+ "Len", "netlogon.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length", HFILL }},
+
+ { &hf_netlogon_priv, {
+ "Priv", "netlogon.priv", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_privilege_entries, {
+ "Privilege Entries", "netlogon.privilege_entries", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_privilege_control, {
+ "Privilege Control", "netlogon.privilege_control", FT_UINT32, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_privilege_name, {
+ "Privilege Name", "netlogon.privilege_name", FT_STRING, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_pdc_connection_status, {
+ "PDC Connection Status", "netlogon.pdc_connection_status", FT_UINT32, BASE_DEC,
+ NULL, 0, "PDC Connection Status", HFILL }},
+
+ { &hf_netlogon_tc_connection_status, {
+ "TC Connection Status", "netlogon.tc_connection_status", FT_UINT32, BASE_DEC,
+ NULL, 0, "TC Connection Status", HFILL }},
+
+ { &hf_netlogon_attrs, {
+ "Attributes", "netlogon.attrs", FT_UINT32, BASE_HEX,
+ NULL, 0, "Attributes", HFILL }},
+
+ { &hf_netlogon_unknown_string,
+ { "Unknown string", "netlogon.unknown_string", FT_STRING, BASE_NONE,
+ NULL, 0, "Unknown string. If you know what this is, contact ethereal developers.", HFILL }},
+ { &hf_netlogon_unknown_long,
+ { "Unknown long", "netlogon.unknown.long", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Unknown long. If you know what this is, contact ethereal developers.", HFILL }},
+ { &hf_netlogon_reserved,
+ { "Reserved", "netlogon.reserved", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Reserved", HFILL }},
+ { &hf_netlogon_unknown_short,
+ { "Unknown short", "netlogon.unknown.short", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Unknown short. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_netlogon_unknown_char,
+ { "Unknown char", "netlogon.unknown.char", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Unknown char. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_netlogon_acct_expiry_time,
+ { "Acct Expiry Time", "netlogon.acct.expiry_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0x0, "When this account will expire", HFILL }},
+
+ { &hf_netlogon_nt_pwd_present,
+ { "NT PWD Present", "netlogon.nt_pwd_present", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Is NT password present for this account?", HFILL }},
+
+ { &hf_netlogon_lm_pwd_present,
+ { "LM PWD Present", "netlogon.lm_pwd_present", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Is LanManager password present for this account?", HFILL }},
+
+ { &hf_netlogon_pwd_expired,
+ { "PWD Expired", "netlogon.pwd_expired", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Whether this password has expired or not", HFILL }},
+
+ { &hf_netlogon_authoritative,
+ { "Authoritative", "netlogon.authoritative", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_sensitive_data_flag,
+ { "Sensitive Data", "netlogon.sensitive_data_flag", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Sensitive data flag", HFILL }},
+
+ { &hf_netlogon_auditing_mode,
+ { "Auditing Mode", "netlogon.auditing_mode", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Auditing Mode", HFILL }},
+
+ { &hf_netlogon_max_audit_event_count,
+ { "Max Audit Event Count", "netlogon.max_audit_event_count", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Max audit event count", HFILL }},
+
+ { &hf_netlogon_event_audit_option,
+ { "Event Audit Option", "netlogon.event_audit_option", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Event audit option", HFILL }},
+
+ { &hf_netlogon_sensitive_data_len,
+ { "Length", "netlogon.sensitive_data_len", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Length of sensitive data", HFILL }},
+
+ { &hf_netlogon_nt_chal_resp,
+ { "NT Chal resp", "netlogon.nt_chal_resp", FT_BYTES, BASE_HEX,
+ NULL, 0, "Challenge response for NT authentication", HFILL }},
+
+ { &hf_netlogon_lm_chal_resp,
+ { "LM Chal resp", "netlogon.lm_chal_resp", FT_BYTES, BASE_HEX,
+ NULL, 0, "Challenge response for LM authentication", HFILL }},
+
+ { &hf_netlogon_cipher_len,
+ { "Cipher Len", "netlogon.cipher_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_cipher_maxlen,
+ { "Cipher Max Len", "netlogon.cipher_maxlen", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_pac_data,
+ { "Pac Data", "netlogon.pac.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Pac Data", HFILL }},
+
+ { &hf_netlogon_sensitive_data,
+ { "Data", "netlogon.sensitive_data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Sensitive Data", HFILL }},
+
+ { &hf_netlogon_auth_data,
+ { "Auth Data", "netlogon.auth.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Auth Data", HFILL }},
+
+ { &hf_netlogon_cipher_current_data,
+ { "Cipher Current Data", "netlogon.cipher_current_data", FT_BYTES, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_cipher_old_data,
+ { "Cipher Old Data", "netlogon.cipher_old_data", FT_BYTES, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_acct_name,
+ { "Acct Name", "netlogon.acct_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Account Name", HFILL }},
+
+ { &hf_netlogon_acct_desc,
+ { "Acct Desc", "netlogon.acct_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "Account Description", HFILL }},
+
+ { &hf_netlogon_group_desc,
+ { "Group Desc", "netlogon.group_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "Group Description", HFILL }},
+
+ { &hf_netlogon_full_name,
+ { "Full Name", "netlogon.full_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Full Name", HFILL }},
+
+ { &hf_netlogon_comment,
+ { "Comment", "netlogon.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "Comment", HFILL }},
+
+ { &hf_netlogon_parameters,
+ { "Parameters", "netlogon.parameters", FT_STRING, BASE_NONE,
+ NULL, 0, "Parameters", HFILL }},
+
+ { &hf_netlogon_logon_script,
+ { "Logon Script", "netlogon.logon_script", FT_STRING, BASE_NONE,
+ NULL, 0, "Logon Script", HFILL }},
+
+ { &hf_netlogon_profile_path,
+ { "Profile Path", "netlogon.profile_path", FT_STRING, BASE_NONE,
+ NULL, 0, "Profile Path", HFILL }},
+
+ { &hf_netlogon_home_dir,
+ { "Home Dir", "netlogon.home_dir", FT_STRING, BASE_NONE,
+ NULL, 0, "Home Directory", HFILL }},
+
+ { &hf_netlogon_dir_drive,
+ { "Dir Drive", "netlogon.dir_drive", FT_STRING, BASE_NONE,
+ NULL, 0, "Drive letter for home directory", HFILL }},
+
+ { &hf_netlogon_logon_srv,
+ { "Server", "netlogon.server", FT_STRING, BASE_NONE,
+ NULL, 0, "Server", HFILL }},
+
+ { &hf_netlogon_principal,
+ { "Principal", "netlogon.principal", FT_STRING, BASE_NONE,
+ NULL, 0, "Principal", HFILL }},
+
+ { &hf_netlogon_logon_dom,
+ { "Domain", "netlogon.domain", FT_STRING, BASE_NONE,
+ NULL, 0, "Domain", HFILL }},
+
+ { &hf_netlogon_resourcegroupcount,
+ { "ResourceGroup count", "netlogon.resourcegroupcount", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of Resource Groups", HFILL }},
+
+ { &hf_netlogon_computer_name,
+ { "Computer Name", "netlogon.computer_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Computer Name", HFILL }},
+
+ { &hf_netlogon_site_name,
+ { "Site Name", "netlogon.site_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Site Name", HFILL }},
+
+ { &hf_netlogon_dc_name,
+ { "DC Name", "netlogon.dc.name", FT_STRING, BASE_NONE,
+ NULL, 0, "DC Name", HFILL }},
+
+ { &hf_netlogon_dc_site_name,
+ { "DC Site Name", "netlogon.dc.site_name", FT_STRING, BASE_NONE,
+ NULL, 0, "DC Site Name", HFILL }},
+
+ { &hf_netlogon_dns_forest_name,
+ { "DNS Forest Name", "netlogon.dns.forest_name", FT_STRING, BASE_NONE,
+ NULL, 0, "DNS Forest Name", HFILL }},
+
+ { &hf_netlogon_dc_address,
+ { "DC Address", "netlogon.dc.address", FT_STRING, BASE_NONE,
+ NULL, 0, "DC Address", HFILL }},
+
+ { &hf_netlogon_dc_address_type,
+ { "DC Address Type", "netlogon.dc.address_type", FT_UINT32, BASE_DEC,
+ VALS(dc_address_types), 0, "DC Address Type", HFILL }},
+
+ { &hf_netlogon_client_site_name,
+ { "Client Site Name", "netlogon.client.site_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Client Site Name", HFILL }},
+
+ { &hf_netlogon_workstation_site_name,
+ { "Wkst Site Name", "netlogon.wkst.site_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Workstation Site Name", HFILL }},
+
+ { &hf_netlogon_workstation,
+ { "Wkst Name", "netlogon.wkst.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Workstation Name", HFILL }},
+
+ { &hf_netlogon_workstation_os,
+ { "Wkst OS", "netlogon.wkst.os", FT_STRING, BASE_NONE,
+ NULL, 0, "Workstation OS", HFILL }},
+
+ { &hf_netlogon_workstations,
+ { "Workstations", "netlogon.wksts", FT_STRING, BASE_NONE,
+ NULL, 0, "Workstations", HFILL }},
+
+ { &hf_netlogon_workstation_fqdn,
+ { "Wkst FQDN", "netlogon.wkst.fqdn", FT_STRING, BASE_NONE,
+ NULL, 0, "Workstation FQDN", HFILL }},
+
+ { &hf_netlogon_group_name,
+ { "Group Name", "netlogon.group_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Group Name", HFILL }},
+
+ { &hf_netlogon_alias_name,
+ { "Alias Name", "netlogon.alias_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Alias Name", HFILL }},
+
+ { &hf_netlogon_dns_host,
+ { "DNS Host", "netlogon.dns_host", FT_STRING, BASE_NONE,
+ NULL, 0, "DNS Host", HFILL }},
+
+ { &hf_netlogon_downlevel_domain_name,
+ { "Downlevel Domain", "netlogon.downlevel_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "Downlevel Domain Name", HFILL }},
+
+ { &hf_netlogon_dns_domain_name,
+ { "DNS Domain", "netlogon.dns_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "DNS Domain Name", HFILL }},
+
+ { &hf_netlogon_domain_name,
+ { "Domain", "netlogon.domain", FT_STRING, BASE_NONE,
+ NULL, 0, "Domain Name", HFILL }},
+
+ { &hf_netlogon_oem_info,
+ { "OEM Info", "netlogon.oem_info", FT_STRING, BASE_NONE,
+ NULL, 0, "OEM Info", HFILL }},
+
+ { &hf_netlogon_trusted_dc_name,
+ { "Trusted DC", "netlogon.trusted_dc", FT_STRING, BASE_NONE,
+ NULL, 0, "Trusted DC", HFILL }},
+
+ { &hf_netlogon_logonsrv_handle,
+ { "Handle", "netlogon.handle", FT_STRING, BASE_NONE,
+ NULL, 0, "Logon Srv Handle", HFILL }},
+
+ { &hf_netlogon_dummy,
+ { "Dummy", "netlogon.dummy", FT_STRING, BASE_NONE,
+ NULL, 0, "Dummy string", HFILL }},
+
+ { &hf_netlogon_logon_count16,
+ { "Logon Count", "netlogon.logon_count16", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Number of successful logins", HFILL }},
+
+ { &hf_netlogon_logon_count,
+ { "Logon Count", "netlogon.logon_count", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of successful logins", HFILL }},
+
+ { &hf_netlogon_bad_pw_count16,
+ { "Bad PW Count", "netlogon.bad_pw_count16", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Number of failed logins", HFILL }},
+
+ { &hf_netlogon_bad_pw_count,
+ { "Bad PW Count", "netlogon.bad_pw_count", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of failed logins", HFILL }},
+
+ { &hf_netlogon_country,
+ { "Country", "netlogon.country", FT_UINT16, BASE_DEC,
+ VALS(ms_country_codes), 0x0, "Country setting for this account", HFILL }},
+
+ { &hf_netlogon_codepage,
+ { "Codepage", "netlogon.codepage", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Codepage setting for this account", HFILL }},
+
+ { &hf_netlogon_level16,
+ { "Level", "netlogon.level16", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Which option of the union is represented here", HFILL }},
+
+ { &hf_netlogon_validation_level,
+ { "Validation Level", "netlogon.validation_level", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Requested level of validation", HFILL }},
+
+ { &hf_netlogon_minpasswdlen,
+ { "Min Password Len", "netlogon.min_passwd_len", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Minimum length of password", HFILL }},
+
+ { &hf_netlogon_passwdhistorylen,
+ { "Passwd History Len", "netlogon.passwd_history_len", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of password history", HFILL }},
+
+ { &hf_netlogon_secure_channel_type,
+ { "Sec Chan Type", "netlogon.sec_chan_type", FT_UINT16, BASE_DEC,
+ VALS(sec_chan_type_vals), 0x0, "Secure Channel Type", HFILL }},
+
+ { &hf_netlogon_restart_state,
+ { "Restart State", "netlogon.restart_state", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Restart State", HFILL }},
+
+ { &hf_netlogon_delta_type,
+ { "Delta Type", "netlogon.delta_type", FT_UINT16, BASE_DEC,
+ VALS(delta_type_vals), 0x0, "Delta Type", HFILL }},
+
+ { &hf_netlogon_blob_size,
+ { "Size", "netlogon.blob.size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size in bytes of BLOB", HFILL }},
+
+ { &hf_netlogon_code,
+ { "Code", "netlogon.code", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Code", HFILL }},
+
+ { &hf_netlogon_level,
+ { "Level", "netlogon.level", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Which option of the union is represented here", HFILL }},
+
+ { &hf_netlogon_reference,
+ { "Reference", "netlogon.reference", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_next_reference,
+ { "Next Reference", "netlogon.next_reference", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_timestamp,
+ { "Timestamp", "netlogon.timestamp", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_user_rid,
+ { "User RID", "netlogon.rid", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_alias_rid,
+ { "Alias RID", "netlogon.alias_rid", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_group_rid,
+ { "Group RID", "netlogon.group_rid", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_num_rids,
+ { "Num RIDs", "netlogon.num_rids", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of RIDs", HFILL }},
+
+ { &hf_netlogon_num_controllers,
+ { "Num DCs", "netlogon.num_dc", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of domain controllers", HFILL }},
+
+ { &hf_netlogon_num_other_groups,
+ { "Num Other Groups", "netlogon.num_other_groups", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_flags,
+ { "Flags", "netlogon.flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_user_account_control,
+ { "User Account Control", "netlogon.user_account_control", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "User Account control", HFILL }},
+
+ { &hf_netlogon_user_flags,
+ { "User Flags", "netlogon.user_flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "User flags", HFILL }},
+
+ { &hf_netlogon_auth_flags,
+ { "Auth Flags", "netlogon.auth_flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_systemflags,
+ { "System Flags", "netlogon.system_flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_database_id,
+ { "Database Id", "netlogon.database_id", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Database Id", HFILL }},
+
+ { &hf_netlogon_sync_context,
+ { "Sync Context", "netlogon.sync_context", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Sync Context", HFILL }},
+
+ { &hf_netlogon_max_size,
+ { "Max Size", "netlogon.max_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Max Size of database", HFILL }},
+
+ { &hf_netlogon_max_log_size,
+ { "Max Log Size", "netlogon.max_log_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Max Size of log", HFILL }},
+
+ { &hf_netlogon_pac_size,
+ { "Pac Size", "netlogon.pac.size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of PacData in bytes", HFILL }},
+
+ { &hf_netlogon_auth_size,
+ { "Auth Size", "netlogon.auth.size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of AuthData in bytes", HFILL }},
+
+ { &hf_netlogon_num_deltas,
+ { "Num Deltas", "netlogon.num_deltas", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of SAM Deltas in array", HFILL }},
+
+ { &hf_netlogon_num_trusts,
+ { "Num Trusts", "netlogon.num_trusts", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_logon_attempts,
+ { "Logon Attempts", "netlogon.logon_attempts", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of logon attempts", HFILL }},
+
+ { &hf_netlogon_pagefilelimit,
+ { "Page File Limit", "netlogon.page_file_limit", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_pagedpoollimit,
+ { "Paged Pool Limit", "netlogon.paged_pool_limit", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_nonpagedpoollimit,
+ { "Non-Paged Pool Limit", "netlogon.nonpaged_pool_limit", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_minworkingsetsize,
+ { "Min Working Set Size", "netlogon.min_working_set_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_maxworkingsetsize,
+ { "Max Working Set Size", "netlogon.max_working_set_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_serial_number,
+ { "Serial Number", "netlogon.serial_number", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_neg_flags,
+ { "Neg Flags", "netlogon.neg_flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Negotiation Flags", HFILL }},
+
+ { &hf_netlogon_dc_flags,
+ { "Flags", "netlogon.dc.flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Domain Controller Flags", HFILL }},
+
+ { &hf_netlogon_dc_flags_pdc_flag,
+ { "PDC", "netlogon.dc.flags.pdc",
+ FT_BOOLEAN, 32, TFS(&dc_flags_pdc_flag), DS_PDC_FLAG,
+ "If this server is a PDC", HFILL }},
+
+ { &hf_netlogon_dc_flags_gc_flag,
+ { "GC", "netlogon.dc.flags.gc",
+ FT_BOOLEAN, 32, TFS(&dc_flags_gc_flag), DS_GC_FLAG,
+ "If this server is a GC", HFILL }},
+
+ { &hf_netlogon_dc_flags_ldap_flag,
+ { "LDAP", "netlogon.dc.flags.ldap",
+ FT_BOOLEAN, 32, TFS(&dc_flags_ldap_flag), DS_LDAP_FLAG,
+ "If this is an LDAP server", HFILL }},
+
+ { &hf_netlogon_dc_flags_ds_flag,
+ { "DS", "netlogon.dc.flags.ds",
+ FT_BOOLEAN, 32, TFS(&dc_flags_ds_flag), DS_DS_FLAG,
+ "If this server is a DS", HFILL }},
+
+ { &hf_netlogon_dc_flags_kdc_flag,
+ { "KDC", "netlogon.dc.flags.kdc",
+ FT_BOOLEAN, 32, TFS(&dc_flags_kdc_flag), DS_KDC_FLAG,
+ "If this is a KDC", HFILL }},
+
+ { &hf_netlogon_dc_flags_timeserv_flag,
+ { "Timeserv", "netlogon.dc.flags.timeserv",
+ FT_BOOLEAN, 32, TFS(&dc_flags_timeserv_flag), DS_TIMESERV_FLAG,
+ "If this server is a TimeServer", HFILL }},
+
+ { &hf_netlogon_dc_flags_closest_flag,
+ { "Closest", "netlogon.dc.flags.closest",
+ FT_BOOLEAN, 32, TFS(&dc_flags_closest_flag), DS_CLOSEST_FLAG,
+ "If this is the closest server", HFILL }},
+
+ { &hf_netlogon_dc_flags_writable_flag,
+ { "Writable", "netlogon.dc.flags.writable",
+ FT_BOOLEAN, 32, TFS(&dc_flags_writable_flag), DS_WRITABLE_FLAG,
+ "If this server can do updates to the database", HFILL }},
+
+ { &hf_netlogon_dc_flags_good_timeserv_flag,
+ { "Good Timeserv", "netlogon.dc.flags.good_timeserv",
+ FT_BOOLEAN, 32, TFS(&dc_flags_good_timeserv_flag), DS_GOOD_TIMESERV_FLAG,
+ "If this is a Good TimeServer", HFILL }},
+
+ { &hf_netlogon_dc_flags_ndnc_flag,
+ { "NDNC", "netlogon.dc.flags.ndnc",
+ FT_BOOLEAN, 32, TFS(&dc_flags_ndnc_flag), DS_NDNC_FLAG,
+ "If this is an NDNC server", HFILL }},
+
+ { &hf_netlogon_dc_flags_dns_controller_flag,
+ { "DNS Controller", "netlogon.dc.flags.dns_controller",
+ FT_BOOLEAN, 32, TFS(&dc_flags_dns_controller_flag), DS_DNS_CONTROLLER_FLAG,
+ "If this server is a DNS Controller", HFILL }},
+
+ { &hf_netlogon_dc_flags_dns_domain_flag,
+ { "DNS Domain", "netlogon.dc.flags.dns_domain",
+ FT_BOOLEAN, 32, TFS(&dc_flags_dns_domain_flag), DS_DNS_DOMAIN_FLAG,
+ "", HFILL }},
+
+ { &hf_netlogon_dc_flags_dns_forest_flag,
+ { "DNS Forest", "netlogon.dc.flags.dns_forest",
+ FT_BOOLEAN, 32, TFS(&dc_flags_dns_forest_flag), DS_DNS_FOREST_FLAG,
+ "", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags,
+ { "Flags", "netlogon.get_dcname.request.flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Flags for DSGetDCName request", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_force_rediscovery,
+ { "Force Rediscovery", "netlogon.get_dcname.request.flags.force_rediscovery",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_force_rediscovery), DS_FORCE_REDISCOVERY,
+ "Whether to allow the server to returned cached information or not", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_directory_service_required,
+ { "DS Required", "netlogon.get_dcname.request.flags.ds_required",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_directory_service_required), DS_DIRECTORY_SERVICE_REQUIRED,
+ "Whether we require that the returned DC supports w2k or not", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_directory_service_preferred,
+ { "DS Preferred", "netlogon.get_dcname.request.flags.ds_preferred",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_directory_service_preferred), DS_DIRECTORY_SERVICE_PREFERRED,
+ "Whether we prefer the call to return a w2k server (if available)", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_gc_server_required,
+ { "GC Required", "netlogon.get_dcname.request.flags.gc_server_required",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_gc_server_required), DS_GC_SERVER_REQUIRED,
+ "Whether we require that the returned DC is a Global Catalog server", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_pdc_required,
+ { "PDC Required", "netlogon.get_dcname.request.flags.pdc_required",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_pdc_required), DS_PDC_REQUIRED,
+ "Whether we require the returned DC to be the PDC", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_background_only,
+ { "Background Only", "netlogon.get_dcname.request.flags.background_only",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_background_only), DS_BACKGROUND_ONLY,
+ "If we want cached data, even if it may have expired", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_ip_required,
+ { "IP Required", "netlogon.get_dcname.request.flags.ip_required",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_ip_required), DS_IP_REQUIRED,
+ "If we requre the IP of the DC in the reply", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_kdc_required,
+ { "KDC Required", "netlogon.get_dcname.request.flags.kdc_required",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_kdc_required), DS_KDC_REQUIRED,
+ "If we require that the returned server is a KDC", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_timeserv_required,
+ { "Timeserv Required", "netlogon.get_dcname.request.flags.timeserv_required",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_timeserv_required), DS_TIMESERV_REQUIRED,
+ "If we require the retruned server to be a NTP serveruns WindowsTimeServicer", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_writable_required,
+ { "Writable Required", "netlogon.get_dcname.request.flags.writable_required",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_writable_required), DS_WRITABLE_REQUIRED,
+ "If we require that the return server is writable", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_good_timeserv_preferred,
+ { "Timeserv Preferred", "netlogon.get_dcname.request.flags.good_timeserv_preferred",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_good_timeserv_preferred), DS_GOOD_TIMESERV_PREFERRED,
+ "If we prefer Windows Time Servers", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_avoid_self,
+ { "Avoid Self", "netlogon.get_dcname.request.flags.avoid_self",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_avoid_self), DS_AVOID_SELF,
+ "Return another DC than the one we ask", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_only_ldap_needed,
+ { "Only LDAP Needed", "netlogon.get_dcname.request.flags.only_ldap_needed",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_only_ldap_needed), DS_ONLY_LDAP_NEEDED,
+ "We just want an LDAP server, it does not have to be a DC", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_is_flat_name,
+ { "Is Flat Name", "netlogon.get_dcname.request.flags.is_flat_name",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_is_flat_name), DS_IS_FLAT_NAME,
+ "If the specified domain name is a NetBIOS name", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_is_dns_name,
+ { "Is DNS Name", "netlogon.get_dcname.request.flags.is_dns_name",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_is_dns_name), DS_IS_DNS_NAME,
+ "If the specified domain name is a DNS name", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_return_dns_name,
+ { "Return DNS Name", "netlogon.get_dcname.request.flags.return_dns_name",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_return_dns_name), DS_RETURN_DNS_NAME,
+ "Only return a DNS name (or an error)", HFILL }},
+
+ { &hf_netlogon_get_dcname_request_flags_return_flat_name,
+ { "Return Flat Name", "netlogon.get_dcname.request.flags.return_flat_name",
+ FT_BOOLEAN, 32, TFS(&get_dcname_request_flags_return_flat_name), DS_RETURN_FLAT_NAME,
+ "Only return a NetBIOS name (or an error)", HFILL }},
+
+ { &hf_netlogon_trust_attribs,
+ { "Trust Attributes", "netlogon.trust_attribs", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Trust Attributes", HFILL }},
+
+ { &hf_netlogon_trust_type,
+ { "Trust Type", "netlogon.trust_type", FT_UINT32, BASE_DEC,
+ VALS(trust_type_vals), 0x0, "Trust Type", HFILL }},
+
+ { &hf_netlogon_trust_flags,
+ { "Trust Flags", "netlogon.trust_flags", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Trust Flags", HFILL }},
+
+ { &hf_netlogon_trust_flags_inbound,
+ { "Inbound Trust", "netlogon.trust.flags.inbound",
+ FT_BOOLEAN, 32, TFS(&trust_inbound), DS_DOMAIN_DIRECT_INBOUND,
+ "Inbound trust. Whether the domain directly trusts the queried servers domain", HFILL }},
+
+ { &hf_netlogon_trust_flags_outbound,
+ { "Outbound Trust", "netlogon.trust.flags.outbound",
+ FT_BOOLEAN, 32, TFS(&trust_outbound), DS_DOMAIN_DIRECT_OUTBOUND,
+ "Outbound Trust. Whether the domain is directly trusted by the servers domain", HFILL }},
+
+ { &hf_netlogon_trust_flags_in_forest,
+ { "In Forest", "netlogon.trust.flags.in_forest",
+ FT_BOOLEAN, 32, TFS(&trust_in_forest), DS_DOMAIN_IN_FOREST,
+ "Whether this domain is a member of the same forest as the servers domain", HFILL }},
+
+ { &hf_netlogon_trust_flags_native_mode,
+ { "Native Mode", "netlogon.trust.flags.native_mode",
+ FT_BOOLEAN, 32, TFS(&trust_native_mode), DS_DOMAIN_NATIVE_MODE,
+ "Whether the domain is a w2k native mode domain or not", HFILL }},
+
+ { &hf_netlogon_trust_flags_primary,
+ { "Primary", "netlogon.trust.flags.primary",
+ FT_BOOLEAN, 32, TFS(&trust_primary), DS_DOMAIN_PRIMARY,
+ "Whether the domain is the primary domain for the queried server or not", HFILL }},
+
+ { &hf_netlogon_trust_flags_tree_root,
+ { "Tree Root", "netlogon.trust.flags.tree_root",
+ FT_BOOLEAN, 32, TFS(&trust_tree_root), DS_DOMAIN_TREE_ROOT,
+ "Whether the domain is the root of the tree for the queried server", HFILL }},
+
+ { &hf_netlogon_trust_parent_index,
+ { "Parent Index", "netlogon.parent_index", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Parent Index", HFILL }},
+
+ { &hf_netlogon_logon_time,
+ { "Logon Time", "netlogon.logon_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time for last time this user logged on", HFILL }},
+
+ { &hf_netlogon_kickoff_time,
+ { "Kickoff Time", "netlogon.kickoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time when this user will be kicked off", HFILL }},
+
+ { &hf_netlogon_logoff_time,
+ { "Logoff Time", "netlogon.logoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time for last time this user logged off", HFILL }},
+
+ { &hf_netlogon_last_logoff_time,
+ { "Last Logoff Time", "netlogon.last_logoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time for last time this user logged off", HFILL }},
+
+ { &hf_netlogon_pwd_last_set_time,
+ { "PWD Last Set", "netlogon.pwd_last_set_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Last time this users password was changed", HFILL }},
+
+ { &hf_netlogon_pwd_age,
+ { "PWD Age", "netlogon.pwd_age", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Time since this users password was changed", HFILL }},
+
+ { &hf_netlogon_pwd_can_change_time,
+ { "PWD Can Change", "netlogon.pwd_can_change_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "When this users password may be changed", HFILL }},
+
+ { &hf_netlogon_pwd_must_change_time,
+ { "PWD Must Change", "netlogon.pwd_must_change_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "When this users password must be changed", HFILL }},
+
+ { &hf_netlogon_domain_create_time,
+ { "Domain Create Time", "netlogon.domain_create_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time when this domain was created", HFILL }},
+
+ { &hf_netlogon_domain_modify_time,
+ { "Domain Modify Time", "netlogon.domain_modify_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time when this domain was last modified", HFILL }},
+
+ { &hf_netlogon_db_modify_time,
+ { "DB Modify Time", "netlogon.db_modify_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time when last modified", HFILL }},
+
+ { &hf_netlogon_db_create_time,
+ { "DB Create Time", "netlogon.db_create_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time when created", HFILL }},
+
+ { &hf_netlogon_cipher_current_set_time,
+ { "Cipher Current Set Time", "netlogon.cipher_current_set_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time when current cipher was initiated", HFILL }},
+
+ { &hf_netlogon_cipher_old_set_time,
+ { "Cipher Old Set Time", "netlogon.cipher_old_set_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time when previous cipher was initiated", HFILL }},
+
+ { &hf_netlogon_audit_retention_period,
+ { "Audit Retention Period", "netlogon.audit_retention_period", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Audit retention period", HFILL }},
+
+ { &hf_netlogon_guid,
+ { "GUID", "netlogon.guid", FT_STRING, BASE_NONE,
+ NULL, 0x0, "GUID (uuid for groups?)", HFILL }},
+
+ { &hf_netlogon_timelimit,
+ { "Time Limit", "netlogon.time_limit", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "", HFILL }},
+
+ /* Secure channel dissection */
+
+ { &hf_netlogon_secchan_bind_unknown1,
+ { "Unknown1", "netlogon.secchan.bind.unknown1", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_secchan_bind_unknown2,
+ { "Unknown2", "netlogon.secchan.bind.unknown2", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_secchan_domain,
+ { "Domain", "netlogon.secchan.domain", FT_STRING, BASE_NONE,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_secchan_host,
+ { "Host", "netlogon.secchan.host", FT_STRING, BASE_NONE,
+ NULL, 0, "", HFILL }},
+
+ { &hf_netlogon_secchan_bind_ack_unknown1,
+ { "Unknown1", "netlogon.secchan.bind_ack.unknown1", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_secchan_bind_ack_unknown2,
+ { "Unknown2", "netlogon.secchan.bind_ack.unknown2", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_secchan_bind_ack_unknown3,
+ { "Unknown3", "netlogon.secchan.bind_ack.unknown3", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_netlogon_secchan_verf,
+ { "Secure Channel Verifier", "netlogon.secchan.verifier", FT_NONE, BASE_NONE,
+ NULL, 0x0, "Verifier", HFILL }},
+
+ { &hf_netlogon_secchan_verf_sig,
+ { "Signature", "netlogon.secchan.sig", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "Signature", HFILL }},
+
+ { &hf_netlogon_secchan_verf_unk,
+ { "Unknown", "netlogon.secchan.unk", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "Unknown", HFILL }},
+
+ { &hf_netlogon_secchan_verf_seq,
+ { "Sequence No", "netlogon.secchan.seq", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "Sequence No", HFILL }},
+
+ { &hf_netlogon_secchan_verf_nonce,
+ { "Nonce", "netlogon.secchan.nonce", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "Nonce", HFILL }},
+
+ { &hf_netlogon_group_attrs_mandatory,
+ { "Mandatory", "netlogon.groups.attrs.mandatory",
+ FT_BOOLEAN, 32, TFS(&group_attrs_mandatory), 0x00000001,
+ "The group attributes MANDATORY flag", HFILL }},
+
+ { &hf_netlogon_group_attrs_enabled_by_default,
+ { "Enabled By Default", "netlogon.groups.attrs.enabled_by_default",
+ FT_BOOLEAN, 32, TFS(&group_attrs_enabled_by_default), 0x00000002,
+ "The group attributes ENABLED_BY_DEFAULT flag", HFILL }},
+
+ { &hf_netlogon_group_attrs_enabled,
+ { "Enabled", "netlogon.groups.attrs.enabled",
+ FT_BOOLEAN, 32, TFS(&group_attrs_enabled), 0x00000004,
+ "The group attributes ENABLED flag", HFILL }},
+
+ { &hf_netlogon_user_flags_extra_sids,
+ { "Extra SIDs", "netlogon.user.flags.extra_sids",
+ FT_BOOLEAN, 32, TFS(&user_flags_extra_sids), 0x00000020,
+ "The user flags EXTRA_SIDS", HFILL }},
+
+ { &hf_netlogon_user_flags_resource_groups,
+ { "Resource Groups", "netlogon.user.flags.resource_groups",
+ FT_BOOLEAN, 32, TFS(&user_flags_resource_groups), 0x00000200,
+ "The user flags RESOURCE_GROUPS", HFILL }},
+
+ { &hf_netlogon_user_account_control_dont_require_preauth,
+ { "Dont Require PreAuth", "netlogon.user.account_control.dont_require_preauth",
+ FT_BOOLEAN, 32, TFS(&user_account_control_dont_require_preauth), 0x00010000,
+ "The user account control DONT_REQUIRE_PREAUTH flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_use_des_key_only,
+ { "Use DES Key Only", "netlogon.user.account_control.use_des_key_only",
+ FT_BOOLEAN, 32, TFS(&user_account_control_use_des_key_only), 0x00008000,
+ "The user account control use_des_key_only flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_not_delegated,
+ { "Not Delegated", "netlogon.user.account_control.not_delegated",
+ FT_BOOLEAN, 32, TFS(&user_account_control_not_delegated), 0x00004000,
+ "The user account control not_delegated flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_trusted_for_delegation,
+ { "Trusted For Delegation", "netlogon.user.account_control.trusted_for_delegation",
+ FT_BOOLEAN, 32, TFS(&user_account_control_trusted_for_delegation), 0x00002000,
+ "The user account control trusted_for_delegation flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_smartcard_required,
+ { "SmartCard Required", "netlogon.user.account_control.smartcard_required",
+ FT_BOOLEAN, 32, TFS(&user_account_control_smartcard_required), 0x00001000,
+ "The user account control smartcard_required flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_encrypted_text_password_allowed,
+ { "Encrypted Text Password Allowed", "netlogon.user.account_control.encrypted_text_password_allowed",
+ FT_BOOLEAN, 32, TFS(&user_account_control_encrypted_text_password_allowed), 0x00000800,
+ "The user account control encrypted_text_password_allowed flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_account_auto_locked,
+ { "Account Auto Locked", "netlogon.user.account_control.account_auto_locked",
+ FT_BOOLEAN, 32, TFS(&user_account_control_account_auto_locked), 0x00000400,
+ "The user account control account_auto_locked flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_dont_expire_password,
+ { "Dont Expire Password", "netlogon.user.account_control.dont_expire_password",
+ FT_BOOLEAN, 32, TFS(&user_account_control_dont_expire_password), 0x00000200,
+ "The user account control dont_expire_password flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_server_trust_account,
+ { "Server Trust Account", "netlogon.user.account_control.server_trust_account",
+ FT_BOOLEAN, 32, TFS(&user_account_control_server_trust_account), 0x00000100,
+ "The user account control server_trust_account flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_workstation_trust_account,
+ { "Workstation Trust Account", "netlogon.user.account_control.workstation_trust_account",
+ FT_BOOLEAN, 32, TFS(&user_account_control_workstation_trust_account), 0x00000080,
+ "The user account control workstation_trust_account flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_interdomain_trust_account,
+ { "Interdomain trust Account", "netlogon.user.account_control.interdomain_trust_account",
+ FT_BOOLEAN, 32, TFS(&user_account_control_interdomain_trust_account), 0x00000040,
+ "The user account control interdomain_trust_account flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_mns_logon_account,
+ { "MNS Logon Account", "netlogon.user.account_control.mns_logon_account",
+ FT_BOOLEAN, 32, TFS(&user_account_control_mns_logon_account), 0x00000020,
+ "The user account control mns_logon_account flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_normal_account,
+ { "Normal Account", "netlogon.user.account_control.normal_account",
+ FT_BOOLEAN, 32, TFS(&user_account_control_normal_account), 0x00000010,
+ "The user account control normal_account flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_temp_duplicate_account,
+ { "Temp Duplicate Account", "netlogon.user.account_control.temp_duplicate_account",
+ FT_BOOLEAN, 32, TFS(&user_account_control_temp_duplicate_account), 0x00000008,
+ "The user account control temp_duplicate_account flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_password_not_required,
+ { "Password Not Required", "netlogon.user.account_control.password_not_required",
+ FT_BOOLEAN, 32, TFS(&user_account_control_password_not_required), 0x00000004,
+ "The user account control password_not_required flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_home_directory_required,
+ { "Home Directory Required", "netlogon.user.account_control.home_directory_required",
+ FT_BOOLEAN, 32, TFS(&user_account_control_home_directory_required), 0x00000002,
+ "The user account control home_directory_required flag ", HFILL }},
+
+ { &hf_netlogon_user_account_control_account_disabled,
+ { "Account Disabled", "netlogon.user.account_control.account_disabled",
+ FT_BOOLEAN, 32, TFS(&user_account_control_account_disabled), 0x00000001,
+ "The user account control account_disabled flag ", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_netlogon,
+ &ett_CYPHER_VALUE,
+ &ett_QUOTA_LIMITS,
+ &ett_IDENTITY_INFO,
+ &ett_DELTA_ENUM,
+ &ett_UNICODE_MULTI,
+ &ett_DOMAIN_CONTROLLER_INFO,
+ &ett_UNICODE_STRING_512,
+ &ett_TYPE_50,
+ &ett_TYPE_52,
+ &ett_DELTA_ID_UNION,
+ &ett_TYPE_44,
+ &ett_DELTA_UNION,
+ &ett_LM_OWF_PASSWORD,
+ &ett_NT_OWF_PASSWORD,
+ &ett_GROUP_MEMBERSHIP,
+ &ett_DS_DOMAIN_TRUSTS,
+ &ett_BLOB,
+ &ett_DOMAIN_TRUST_INFO,
+ &ett_trust_flags,
+ &ett_get_dcname_request_flags,
+ &ett_dc_flags,
+ &ett_secchan_bind_creds,
+ &ett_secchan_bind_ack_creds,
+ &ett_secchan_verf,
+ &ett_group_attrs,
+ &ett_user_flags,
+ &ett_user_account_control
+ };
+
+ proto_dcerpc_netlogon = proto_register_protocol(
+ "Microsoft Network Logon", "RPC_NETLOGON", "rpc_netlogon");
+
+ proto_register_field_array(proto_dcerpc_netlogon, hf,
+ array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+static dcerpc_auth_subdissector_fns secchan_auth_fns = {
+ dissect_secchan_bind_creds, /* Bind */
+ dissect_secchan_bind_ack_creds, /* Bind ACK */
+ NULL, /* AUTH3 */
+ dissect_secchan_verf, /* Request verifier */
+ dissect_secchan_verf, /* Response verifier */
+ NULL, /* Request data */
+ NULL /* Response data */
+};
+
+void
+proto_reg_handoff_dcerpc_netlogon(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_netlogon, ett_dcerpc_netlogon,
+ &uuid_dcerpc_netlogon, ver_dcerpc_netlogon,
+ dcerpc_netlogon_dissectors, hf_netlogon_opnum);
+
+ register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
+ DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN,
+ &secchan_auth_fns);
+ register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
+ DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN,
+ &secchan_auth_fns);
+}
diff --git a/epan/dissectors/packet-dcerpc-netlogon.h b/epan/dissectors/packet-dcerpc-netlogon.h
new file mode 100644
index 0000000000..429d525e78
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-netlogon.h
@@ -0,0 +1,90 @@
+/* packet-dcerpc-netlogon.h
+ * Routines for SMB \PIPE\NETLOGON packet disassembly
+ * Copyright 2001,2003 Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_NETLOGON_H
+#define __PACKET_DCERPC_NETLOGON_H
+
+#define NETLOGON_NETRLOGONUASLOGON 0x00
+#define NETLOGON_NETRLOGONUASLOGOFF 0x01
+#define NETLOGON_NETRLOGONSAMLOGON 0x02
+#define NETLOGON_NETRLOGONSAMLOGOFF 0x03
+#define NETLOGON_NETRSERVERREQCHALLENGE 0x04
+#define NETLOGON_NETRSERVERAUTHENTICATE 0x05
+#define NETLOGON_NETRSERVERPASSWORDSET 0x06
+#define NETLOGON_NETRDATABASEDELTAS 0x07
+#define NETLOGON_NETRDATABASESYNC 0x08
+#define NETLOGON_NETRACCOUNTDELTAS 0x09
+#define NETLOGON_NETRACCOUNTSYNC 0x0a
+#define NETLOGON_NETRGETDCNAME 0x0b
+#define NETLOGON_NETRLOGONCONTROL 0x0c
+#define NETLOGON_NETRGETANYDCNAME 0x0d
+#define NETLOGON_NETRLOGONCONTROL2 0x0e
+#define NETLOGON_NETRSERVERAUTHENTICATE2 0x0f
+#define NETLOGON_NETRDATABASESYNC2 0x10
+#define NETLOGON_NETRDATABASEREDO 0x11
+#define NETLOGON_NETRLOGONCONTROL2EX 0x12
+#define NETLOGON_NETRENUMERATETRUSTEDDOMAINS 0x13
+#define NETLOGON_DSRGETDCNAME 0x14
+#define NETLOGON_NETRLOGONDUMMYROUTINE1 0x15
+#define NETLOGON_NETRLOGONSETSERVICEBITS 0x16
+#define NETLOGON_NETRLOGONGETTRUSTRID 0x17
+#define NETLOGON_NETRLOGONCOMPUTESERVERDIGEST 0x18
+#define NETLOGON_NETRLOGONCOMPUTECLIENTDIGEST 0x19
+#define NETLOGON_NETRSERVERAUTHENTICATE3 0x1a
+#define NETLOGON_DSRGETDCNAMEX 0x1b
+#define NETLOGON_DSRGETSITENAME 0x1c
+#define NETLOGON_NETRLOGONGETDOMAININFO 0x1d
+#define NETLOGON_NETRSERVERPASSWORDSET2 0x1e
+#define NETLOGON_NETRSERVERPASSWORDGET 0x1f
+#define NETLOGON_NETRLOGONSENDTOSAM 0x20
+#define NETLOGON_DSRADDRESSTOSITENAMESW 0x21
+#define NETLOGON_DSRGETDCNAMEEX2 0x22
+#define NETLOGON_NETRLOGONGETTIMESERVICEPARENTDOMAIN 0x23
+#define NETLOGON_NETRENUMERATETRUSTEDDOMAINSEX 0x24
+#define NETLOGON_DSRADDRESSTOSITENAMESEXW 0x25
+#define NETLOGON_DSRGETDCSITECOVERAGEW 0x26
+#define NETLOGON_NETRLOGONSAMLOGONEX 0x27
+#define NETLOGON_DSRENUMERATEDOMAINTRUSTS 0x28
+#define NETLOGON_DSRDEREGISTERDNSHOSTRECORDS 0x29
+#define NETLOGON_NETRSERVERTRUSTPASSWORDSGET 0x2a
+#define NETLOGON_DSRGETFORESTTRUSTINFORMATION 0x2b
+#define NETLOGON_NETRGETFORESTTRUSTINFORMATION 0x2c
+#define NETLOGON_NETRLOGONSAMLOGONWITHFLAGS 0x2d
+#define NETLOGON_NETRSERVERGETTRUSTINFO 0x2e
+
+/* Secure channel types */
+
+#define SEC_CHAN_WKSTA 2
+#define SEC_CHAN_DOMAIN 4
+#define SEC_CHAN_BDC 6
+
+
+/* needed to decrypt PAC_LOGON_INFO in kerberos */
+int
+netlogon_dissect_PAC_LOGON_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep);
+
+#endif /* packet-dcerpc-netlogon.h */
diff --git a/epan/dissectors/packet-dcerpc-nspi.c b/epan/dissectors/packet-dcerpc-nspi.c
new file mode 100644
index 0000000000..459bd503d9
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-nspi.c
@@ -0,0 +1,116 @@
+/* packet-dcerpc-nspi.c
+ * Routines for dcerpc nspi dissection
+ * Copyright 2001, Todd Sabin <tsabin@optonline.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_nspi = -1;
+
+static int hf_nspi_opnum = -1;
+
+static gint ett_nspi = -1;
+
+static e_uuid_t uuid_nspi = { 0xf5cc5a18, 0x4264, 0x101a, { 0x8c, 0x59, 0x08, 0x00, 0x2b, 0x2f, 0x84, 0x26 } };
+static guint16 ver_nspi = 56;
+
+static dcerpc_sub_dissector nspi_dissectors[] = {
+ { 0, "NspiBind", NULL, NULL },
+ { 1, "NspiUnbind", NULL, NULL },
+ { 2, "NspiUpdateStat", NULL, NULL },
+ { 3, "NspiQueryRows", NULL, NULL },
+ { 4, "NspiSeekEntries", NULL, NULL },
+ { 5, "NspiGetMatches", NULL, NULL },
+ { 6, "NspiResortRestriction", NULL, NULL },
+ { 7, "NspiDNToEph", NULL, NULL },
+ { 8, "NspiGetPropList", NULL, NULL },
+ { 9, "NspiGetProps", NULL, NULL },
+ { 10, "NspiCompareDNTs", NULL, NULL },
+ { 11, "NspiModProps", NULL, NULL },
+ { 12, "NspiGetHierarchyInfo", NULL, NULL },
+ { 13, "NspiGetTemplateInfo", NULL, NULL },
+ { 14, "NspiModLinkAttr", NULL, NULL },
+ { 15, "NspiDeleteEntries", NULL, NULL },
+ { 16, "NspiQueryColumns", NULL, NULL },
+ { 17, "NspiGetNamesFromIDs", NULL, NULL },
+ { 18, "NspiGetIDsFromNames", NULL, NULL },
+ { 19, "NspiResolveNames", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+static const value_string nspi_opnum_vals[] = {
+ { 0, "Bind" },
+ { 1, "Unbind" },
+ { 2, "UpdateStat" },
+ { 3, "QueryRows" },
+ { 4, "SeekEntries" },
+ { 5, "GetMatches" },
+ { 6, "ResortRestriction" },
+ { 7, "DNToEph" },
+ { 8, "GetPropList" },
+ { 9, "GetProps" },
+ { 10, "CompareDNTs" },
+ { 11, "ModProps" },
+ { 12, "GetHierarchyInfo" },
+ { 13, "GetTemplateInfo" },
+ { 14, "ModLinkAttr" },
+ { 15, "DeleteEntries" },
+ { 16, "QueryColumns" },
+ { 17, "GetNamesFromIDs" },
+ { 18, "GetIDsFromNames" },
+ { 19, "ResolveNames" },
+ { 0, NULL }
+};
+
+
+void
+proto_register_nspi (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_nspi_opnum,
+ { "Operation", "nspi.opnum", FT_UINT16, BASE_DEC,
+ VALS(nspi_opnum_vals), 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_nspi
+ };
+ proto_nspi = proto_register_protocol ("NSPI", "NSPI", "nspi");
+ proto_register_field_array(proto_nspi, hf, array_length(hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_nspi (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_nspi, ett_nspi, &uuid_nspi, ver_nspi, nspi_dissectors, hf_nspi_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-nt.c b/epan/dissectors/packet-dcerpc-nt.c
new file mode 100644
index 0000000000..5af4750a3c
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-nt.c
@@ -0,0 +1,1509 @@
+/* packet-dcerpc-nt.c
+ * Routines for DCERPC over SMB packet disassembly
+ * Copyright 2001-2003, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "smb.h"
+#include "packet-smb-common.h" /* for dissect_smb_64bit_time() */
+
+/*
+ * This file contains helper routines that are used by the DCERPC over SMB
+ * dissectors for ethereal.
+ */
+
+/*
+ * Used by several dissectors.
+ */
+const value_string platform_id_vals[] = {
+ { 300, "DOS" },
+ { 400, "OS/2" },
+ { 500, "Windows NT" },
+ { 600, "OSF" },
+ { 700, "VMS" },
+ { 0, NULL }
+};
+
+/* Parse some common RPC structures */
+
+gint ett_nt_unicode_string = -1; /* FIXME: make static */
+
+/* Dissect a counted string as a callback to dissect_ndr_pointer_cb() */
+
+static int hf_nt_cs_len = -1;
+static int hf_nt_cs_size = -1;
+
+int
+dissect_ndr_counted_string_cb(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int hf_index,
+ dcerpc_callback_fnct_t *callback,
+ void *callback_args)
+{
+ dcerpc_info *di = pinfo->private_data;
+ guint16 len, size;
+
+ /* Structure starts with short, but is aligned for longs */
+
+ ALIGN_TO_4_BYTES;
+
+ if (di->conformant_run)
+ return offset;
+
+ /*
+ struct {
+ short len;
+ short size;
+ [size_is(size/2), length_is(len/2), ptr] unsigned short *string;
+ } UNICODE_STRING;
+
+ */
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_nt_cs_len, &len);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_nt_cs_size, &size);
+
+ offset = dissect_ndr_pointer_cb(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
+ "Character Array", hf_index, callback, callback_args);
+
+ return offset;
+}
+
+static gint ett_nt_counted_string = -1;
+
+static int
+dissect_ndr_counted_string_helper(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int hf_index, int levels,
+ gboolean add_subtree)
+{
+ proto_item *item;
+ proto_tree *subtree = tree;
+
+ if (add_subtree) {
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0,
+ proto_registrar_get_name(hf_index));
+
+ subtree = proto_item_add_subtree(item, ett_nt_counted_string);
+ }
+
+ /*
+ * Add 2 levels, so that the string gets attached to the
+ * "Character Array" top-level item and to the top-level item
+ * added above.
+ */
+ return dissect_ndr_counted_string_cb(
+ tvb, offset, pinfo, subtree, drep, hf_index,
+ cb_wstr_postprocess, GINT_TO_POINTER(2 + levels));
+}
+
+/* Dissect a counted string in-line. */
+
+int
+dissect_ndr_counted_string(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int hf_index, int levels)
+{
+ return dissect_ndr_counted_string_helper(
+ tvb, offset, pinfo, tree, drep, hf_index, levels, TRUE);
+}
+
+/* Dissect a counted string as a callback to dissect_ndr_pointer().
+ This doesn't add a adds a proto item and subtreee for the string as
+ the pointer dissection already creates one. */
+
+int
+dissect_ndr_counted_string_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = pinfo->private_data;
+
+ return dissect_ndr_counted_string_helper(
+ tvb, offset, pinfo, tree, drep, di->hf_index, 0, FALSE);
+}
+
+/* Dissect a counted byte_array as a callback to dissect_ndr_pointer_cb() */
+
+static gint ett_nt_counted_byte_array = -1;
+
+/* Dissect a counted byte array in-line. */
+
+int
+dissect_ndr_counted_byte_array_cb(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int hf_index,
+ dcerpc_callback_fnct_t *callback,
+ void *callback_args)
+{
+ dcerpc_info *di = pinfo->private_data;
+ proto_item *item;
+ proto_tree *subtree;
+ guint16 len, size;
+
+ /* Structure starts with short, but is aligned for longs */
+
+ ALIGN_TO_4_BYTES;
+
+ if (di->conformant_run)
+ return offset;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0,
+ proto_registrar_get_name(hf_index));
+
+ subtree = proto_item_add_subtree(item, ett_nt_counted_byte_array);
+
+ /*
+ struct {
+ short len;
+ short size;
+ [size_is(size), length_is(len), ptr] unsigned char *string;
+ } WHATEVER_THIS_IS_CALLED;
+
+ */
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
+ hf_nt_cs_len, &len);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
+ hf_nt_cs_size, &size);
+
+ offset = dissect_ndr_pointer_cb(tvb, offset, pinfo, subtree, drep,
+ dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
+ "Byte Array", hf_index, callback, callback_args);
+
+ return offset;
+}
+
+int
+dissect_ndr_counted_byte_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int hf_index)
+{
+ return dissect_ndr_counted_byte_array_cb(
+ tvb, offset, pinfo, tree, drep, hf_index, NULL, NULL);
+}
+
+/* This function is used to dissect a DCERPC encoded 64 bit time value.
+ XXX it should be fixed both here and in dissect_smb_64bit_time so
+ it can handle both BIG and LITTLE endian encodings
+ */
+int
+dissect_ndr_nt_NTTIME (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_, int hf_index)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_index);
+ return offset;
+}
+
+/* Define this symbol to display warnings about request/response and
+ policy handle hash table collisions. This happens when a packet with
+ the same conversation, smb fid and dcerpc call id occurs. I think this
+ is due to a bug in the dcerpc/smb fragment reassembly code. */
+
+#undef DEBUG_HASH_COLL
+
+/*
+ * Policy handle hashing.
+ *
+ * We hash based on the policy handle value; the items in the hash table
+ * are lists of policy handle information about one or more policy
+ * handles with that value. We have multiple values in case a given
+ * policy handle is opened in frame N, closed in frame M, and re-opened
+ * in frame O, where N < M < O.
+ *
+ * XXX - we really should also use a DCE RPC conversation/session handle
+ * of some sort, in case two separate sessions have the same handle
+ * value. A transport-layer conversation might not be sufficient, as you
+ * might, for example, have multiple pipes in a single SMB connection,
+ * and you might have the same handle opened and closed separately on
+ * those two pipes.
+ *
+ * The policy handle information has "first frame" and "last frame"
+ * information; the entry should be used when dissecting a given frame
+ * only if that frame is within the interval [first frame,last frame].
+ * The list is sorted by "first frame".
+ *
+ * This doesn't handle the case of a handle being opened in frame N and
+ * re-opened in frame M, where N < M, with no intervening close, but I'm
+ * not sure anything can handle that if it's within the same DCE RPC
+ * session (if it's not, the conversation/session handle would fix that).
+ */
+
+typedef struct {
+ guint8 policy_hnd[20];
+} pol_hash_key;
+
+typedef struct pol_value {
+ struct pol_value *next; /* Next entry in hash bucket */
+ guint32 open_frame, close_frame; /* Frame numbers for open/close */
+ guint32 first_frame; /* First frame in which this instance was seen */
+ guint32 last_frame; /* Last frame in which this instance was seen */
+ char *name; /* Name of policy handle */
+} pol_value;
+
+typedef struct {
+ pol_value *list; /* List of policy handle entries */
+} pol_hash_value;
+
+#define POL_HASH_INIT_COUNT 100
+
+static GHashTable *pol_hash;
+static GMemChunk *pol_hash_key_chunk;
+static GMemChunk *pol_value_chunk;
+static GMemChunk *pol_hash_value_chunk;
+
+/* Hash function */
+
+static guint pol_hash_fn(gconstpointer k)
+{
+ const pol_hash_key *key = (const pol_hash_key *)k;
+
+ /* Bytes 4-7 of the policy handle are a timestamp so should make a
+ reasonable hash value */
+
+ return key->policy_hnd[4] + (key->policy_hnd[5] << 8) +
+ (key->policy_hnd[6] << 16) + (key->policy_hnd[7] << 24);
+}
+
+/* Return true if a policy handle is all zeros */
+
+static gboolean is_null_pol(e_ctx_hnd *policy_hnd)
+{
+ static guint8 null_policy_hnd[20];
+
+ return memcmp(policy_hnd, null_policy_hnd, 20) == 0;
+}
+
+/* Hash compare function */
+
+static gint pol_hash_compare(gconstpointer k1, gconstpointer k2)
+{
+ const pol_hash_key *key1 = (const pol_hash_key *)k1;
+ const pol_hash_key *key2 = (const pol_hash_key *)k2;
+
+ return memcmp(key1->policy_hnd, key2->policy_hnd,
+ sizeof(key1->policy_hnd)) == 0;
+}
+
+/*
+ * Look up the instance of a policy handle value in whose range of frames
+ * the specified frame falls.
+ */
+static pol_value *find_pol_handle(e_ctx_hnd *policy_hnd, guint32 frame,
+ pol_hash_value **valuep)
+{
+ pol_hash_key key;
+ pol_value *pol;
+
+ memcpy(&key.policy_hnd, policy_hnd, sizeof(key.policy_hnd));
+ if ((*valuep = g_hash_table_lookup(pol_hash, &key))) {
+ /*
+ * Look for the first value such that both:
+ *
+ * 1) the first frame in which it was seen is
+ * <= the specified frame;
+ *
+ * 2) the last frame in which it was seen is
+ * either unknown (meaning we haven't yet
+ * seen a close or another open of the
+ * same handle, which is assumed to imply
+ * an intervening close that wasn't captured)
+ * or is >= the specified frame.
+ *
+ * If there's more than one such frame, that's the
+ * case where a handle is opened in frame N and
+ * reopened in frame M, with no intervening close;
+ * there is no right answer for that, so the instance
+ * opened in frame N is as right as anything else.
+ */
+ for (pol = (*valuep)->list; pol != NULL; pol = pol->next) {
+ if (pol->first_frame <= frame &&
+ (pol->last_frame == 0 ||
+ pol->last_frame >= frame))
+ break; /* found one */
+ }
+ return pol;
+ } else {
+ /*
+ * The handle isn't in the hash table.
+ */
+ return NULL;
+ }
+}
+
+static void add_pol_handle(e_ctx_hnd *policy_hnd, guint32 frame,
+ pol_value *pol, pol_hash_value *value)
+{
+ pol_hash_key *key;
+ pol_value *polprev, *polnext;
+
+ if (value == NULL) {
+ /*
+ * There's no hash value; create one, put the new
+ * value at the beginning of its policy handle list,
+ * and put the hash value in the policy handle hash
+ * table.
+ */
+ value = g_mem_chunk_alloc(pol_hash_value_chunk);
+ value->list = pol;
+ pol->next = NULL;
+ key = g_mem_chunk_alloc(pol_hash_key_chunk);
+ memcpy(&key->policy_hnd, policy_hnd, sizeof(key->policy_hnd));
+ g_hash_table_insert(pol_hash, key, value);
+ } else {
+ /*
+ * Put the new value in the hash value's policy handle
+ * list so that it's sorted by the first frame in
+ * which it appeared.
+ *
+ * Search for the first entry whose first frame number
+ * is greater than the current frame number, if any.
+ */
+ for (polnext = value->list, polprev = NULL;
+ polnext != NULL && polnext->first_frame <= frame;
+ polprev = polnext, polnext = polnext->next)
+ ;
+
+ /*
+ * "polprev" points to the entry in the list after
+ * which we should put the new entry; if it's null,
+ * that means we should put it at the beginning of
+ * the list.
+ */
+ if (polprev == NULL)
+ value->list = pol;
+ else
+ polprev->next = pol;
+
+ /*
+ * "polnext" points to the entry in the list before
+ * which we should put the new entry; if it's null,
+ * that means we should put it at the end of the list.
+ */
+ pol->next = polnext;
+ }
+}
+
+/* Store the open and close frame numbers of a policy handle */
+
+void dcerpc_smb_store_pol_pkts(e_ctx_hnd *policy_hnd, packet_info *pinfo,
+ gboolean is_open, gboolean is_close)
+{
+ pol_hash_value *value;
+ pol_value *pol;
+
+ /*
+ * By the time the first pass is done, the policy handle database
+ * has been completely constructed. If we've already seen this
+ * frame, there's nothing to do.
+ */
+ if (pinfo->fd->flags.visited)
+ return;
+
+ if (is_null_pol(policy_hnd))
+ return;
+
+ /* Look up existing value */
+ pol = find_pol_handle(policy_hnd, pinfo->fd->num, &value);
+
+ if (pol != NULL) {
+ /*
+ * Update the existing value as appropriate.
+ */
+ if (is_open) {
+ /*
+ * This is an open; we assume that we missed
+ * a close of this handle, so we set its
+ * "last frame" value and act as if we didn't
+ * see it.
+ *
+ * XXX - note that we might be called twice for
+ * the same operation (see "dissect_pipe_dcerpc()",
+ * which calls the DCE RPC dissector twice), so we
+ * must first check to see if this is a handle we
+ * just filled in.
+ *
+ * We check whether this handle's "first frame"
+ * frame number is this frame and its "last frame
+ * is 0; if so, this is presumably a duplicate call,
+ * and we don't do an implicit close.
+ */
+ if (pol->first_frame == pinfo->fd->num &&
+ pol->last_frame == 0)
+ return;
+ pol->last_frame = pinfo->fd->num;
+ pol = NULL;
+ } else {
+ if (is_close) {
+ pol->close_frame = pinfo->fd->num;
+ pol->last_frame = pinfo->fd->num;
+ }
+ return;
+ }
+ }
+
+ /* Create a new value */
+
+ pol = g_mem_chunk_alloc(pol_value_chunk);
+
+ pol->open_frame = is_open ? pinfo->fd->num : 0;
+ pol->close_frame = is_close ? pinfo->fd->num : 0;
+ pol->first_frame = pinfo->fd->num;
+ pol->last_frame = pol->close_frame; /* if 0, unknown; if non-0, known */
+
+ pol->name = NULL;
+
+ add_pol_handle(policy_hnd, pinfo->fd->num, pol, value);
+}
+
+/* Store a text string with a policy handle */
+
+void dcerpc_smb_store_pol_name(e_ctx_hnd *policy_hnd, packet_info *pinfo,
+ char *name)
+{
+ pol_hash_value *value;
+ pol_value *pol;
+
+ /*
+ * By the time the first pass is done, the policy handle database
+ * has been completely constructed. If we've already seen this
+ * frame, there's nothing to do.
+ */
+ if (pinfo->fd->flags.visited)
+ return;
+
+ if (is_null_pol(policy_hnd))
+ return;
+
+ /* Look up existing value */
+ pol = find_pol_handle(policy_hnd, pinfo->fd->num, &value);
+
+ if (pol != NULL) {
+ /*
+ * This is the first pass; update the existing
+ * value as appropriate.
+ */
+ if (pol->name && name) {
+#ifdef DEBUG_HASH_COLL
+ if (strcmp(pol->name, name) != 0)
+ g_warning("dcerpc_smb: pol_hash name collision %s/%s\n", value->name, name);
+#endif
+ free(pol->name);
+ }
+
+ pol->name = strdup(name);
+
+ return;
+ }
+
+ /* Create a new value */
+
+ pol = g_mem_chunk_alloc(pol_value_chunk);
+
+ pol->open_frame = 0;
+ pol->close_frame = 0;
+ pol->first_frame = pinfo->fd->num;
+ pol->last_frame = 0;
+
+ if (name)
+ pol->name = strdup(name);
+ else
+ pol->name = strdup("<UNKNOWN>");
+
+ add_pol_handle(policy_hnd, pinfo->fd->num, pol, value);
+}
+
+/*
+ * Retrieve a policy handle.
+ *
+ * XXX - should this get an "is_close" argument, and match even closed
+ * policy handles if the call is a close, so we can handle retransmitted
+ * close operations?
+ */
+
+gboolean dcerpc_smb_fetch_pol(e_ctx_hnd *policy_hnd, char **name,
+ guint32 *open_frame, guint32 *close_frame,
+ guint32 cur_frame)
+{
+ pol_hash_value *value;
+ pol_value *pol;
+
+ /* Prevent uninitialised return vars */
+
+ if (name)
+ *name = NULL;
+
+ if (open_frame)
+ *open_frame = 0;
+
+ if (close_frame)
+ *close_frame = 0;
+
+ /* Look up existing value */
+ pol = find_pol_handle(policy_hnd, cur_frame, &value);
+
+ if (pol) {
+ if (name)
+ *name = pol->name;
+
+ if (open_frame)
+ *open_frame = pol->open_frame;
+
+ if (close_frame)
+ *close_frame = pol->close_frame;
+ }
+
+ return pol != NULL;
+}
+
+/* Iterator to free a policy handle key/value pair, and all
+ the policy handle values to which the hash table value
+ points */
+
+static void free_pol_keyvalue(gpointer key _U_, gpointer value_arg,
+ gpointer user_data _U_)
+{
+ pol_hash_value *value = (pol_hash_value *)value_arg;
+ pol_value *pol;
+
+ /* Free user data */
+
+ for (pol = value->list; pol != NULL; pol = pol->next) {
+ free(pol->name);
+ pol->name = NULL;
+ }
+}
+
+/* Initialise policy handle hash */
+
+static void init_pol_hash(void)
+{
+ /* Initialise memory chunks */
+
+ if (pol_hash_key_chunk)
+ g_mem_chunk_destroy(pol_hash_key_chunk);
+
+ pol_hash_key_chunk = g_mem_chunk_new(
+ "Policy handle hash keys", sizeof(pol_hash_key),
+ POL_HASH_INIT_COUNT * sizeof(pol_hash_key), G_ALLOC_ONLY);
+
+ if (pol_value_chunk)
+ g_mem_chunk_destroy(pol_value_chunk);
+
+ pol_value_chunk = g_mem_chunk_new(
+ "Policy handle values", sizeof(pol_value),
+ POL_HASH_INIT_COUNT * sizeof(pol_value), G_ALLOC_ONLY);
+
+ if (pol_hash_value_chunk)
+ g_mem_chunk_destroy(pol_hash_value_chunk);
+
+ pol_hash_value_chunk = g_mem_chunk_new(
+ "Policy handle hash values", sizeof(pol_hash_value),
+ POL_HASH_INIT_COUNT * sizeof(pol_hash_value), G_ALLOC_ONLY);
+
+ /* Initialise hash table */
+
+ if (pol_hash) {
+ g_hash_table_foreach(pol_hash, free_pol_keyvalue, NULL);
+ g_hash_table_destroy(pol_hash);
+ }
+
+ pol_hash = g_hash_table_new(pol_hash_fn, pol_hash_compare);
+}
+
+/* Dissect a NT status code */
+
+int
+dissect_ntstatus(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata)
+{
+ guint32 status;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hfindex, &status);
+
+ if (status != 0 && check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(status, NT_errors,
+ "Unknown error 0x%08x"));
+ if (pdata)
+ *pdata = status;
+
+ return offset;
+}
+
+/* Dissect a DOS status code */
+
+int
+dissect_doserror(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata)
+{
+ guint32 status;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hfindex, &status);
+
+ if (status != 0 && check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(status, DOS_errors,
+ "Unknown error 0x%08x"));
+ if (pdata)
+ *pdata = status;
+
+ return offset;
+}
+
+/* Dissect a NT policy handle */
+
+static int hf_nt_policy_open_frame = -1;
+static int hf_nt_policy_close_frame = -1;
+
+static gint ett_nt_policy_hnd = -1;
+
+int
+dissect_nt_policy_hnd(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, int hfindex,
+ e_ctx_hnd *pdata, proto_item **pitem,
+ gboolean is_open, gboolean is_close)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ e_ctx_hnd hnd;
+ guint32 open_frame = 0, close_frame = 0;
+ char *name;
+ int old_offset = offset;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*
+ * just a run to handle conformant arrays, no scalars to
+ * dissect - and "dissect_ndr_ctx_hnd()" won't return
+ * a handle, so we can't do the hashing stuff in any
+ * case
+ */
+ return offset;
+ }
+
+ /* Add to proto tree */
+
+ item = proto_tree_add_text(tree, tvb, offset, sizeof(e_ctx_hnd),
+ "Policy Handle");
+
+ subtree = proto_item_add_subtree(item, ett_nt_policy_hnd);
+
+ offset = dissect_ndr_ctx_hnd(tvb, offset, pinfo, subtree, drep,
+ hfindex, &hnd);
+
+ /*
+ * Create a new entry for this handle if it's not a null handle
+ * and no entry already exists, and, in any case, set the
+ * open, close, first, and last frame information as appropriate.
+ */
+ dcerpc_smb_store_pol_pkts(&hnd, pinfo, is_open, is_close);
+
+ /* Insert open/close/name information if known */
+
+ if (dcerpc_smb_fetch_pol(&hnd, &name, &open_frame, &close_frame,
+ pinfo->fd->num)) {
+
+ if (open_frame)
+ proto_tree_add_uint(
+ subtree, hf_nt_policy_open_frame, tvb,
+ old_offset, sizeof(e_ctx_hnd), open_frame);
+
+ if (close_frame)
+ proto_tree_add_uint(
+ subtree, hf_nt_policy_close_frame, tvb,
+ old_offset, sizeof(e_ctx_hnd), close_frame);
+
+ /*
+ * Don't append the handle name if pitem is null; that's
+ * an indication that our caller will do so, as we're
+ * supplying a pointer to the item so that they can do
+ * so.
+ */
+ if (name != NULL && pitem == NULL)
+ proto_item_append_text(item, ": %s", name);
+ }
+
+ if (pdata)
+ *pdata = hnd;
+
+ if (pitem)
+ *pitem = item;
+
+ return offset;
+}
+
+/* Some helper routines to dissect a range of uint8 characters. I don't
+ think these are "official" NDR representations and are probably specific
+ to NT so for the moment they're put here instead of in packet-dcerpc.c
+ and packet-dcerpc-ndr.c. */
+
+int
+dissect_dcerpc_uint8s(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep, int hfindex,
+ int length, const guint8 **pdata)
+{
+ const guint8 *data;
+
+ data = (const guint8 *)tvb_get_ptr(tvb, offset, length);
+
+ if (tree) {
+ proto_tree_add_item (tree, hfindex, tvb, offset, length, (drep[0] & 0x10));
+ }
+
+ if (pdata)
+ *pdata = data;
+
+ return offset + length;
+}
+
+int
+dissect_ndr_uint8s(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, int length, const guint8 **pdata)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ /* no alignment needed */
+ return dissect_dcerpc_uint8s(tvb, offset, pinfo,
+ tree, drep, hfindex, length, pdata);
+}
+
+int
+dissect_dcerpc_uint16s(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep, int hfindex,
+ int length)
+{
+ if (tree) {
+ proto_tree_add_item (tree, hfindex, tvb, offset, length * 2, (drep[0] & 0x10));
+ }
+
+ return offset + length * 2;
+}
+
+int
+dissect_ndr_uint16s(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, int length)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ if (offset % 2)
+ offset++;
+
+ return dissect_dcerpc_uint16s(tvb, offset, pinfo,
+ tree, drep, hfindex, length);
+}
+
+/*
+ * Helper routines for dissecting NDR strings
+ */
+
+void cb_wstr_postprocess(packet_info *pinfo, proto_tree *tree _U_,
+ proto_item *item, tvbuff_t *tvb,
+ int start_offset, int end_offset,
+ void *callback_args)
+{
+ gint options = GPOINTER_TO_INT(callback_args);
+ gint levels = CB_STR_ITEM_LEVELS(options);
+ char *s;
+
+ /* Align start_offset on 4-byte boundary. */
+
+ if (start_offset % 4)
+ start_offset += 4 - (start_offset % 4);
+
+ /* Get string value */
+
+ if ((end_offset - start_offset) <= 12)
+ return; /* XXX: Use unistr2 dissector instead? */
+
+ /*
+ * XXX - need to handle non-printable characters here.
+ *
+ * XXX - this is typically called after the string has already
+ * been fetched and processed by some other routine; is there
+ * some way we can get that string, rather than duplicating the
+ * efforts of that routine?
+ */
+ s = tvb_fake_unicode(
+ tvb, start_offset + 12, (end_offset - start_offset - 12) / 2,
+ TRUE);
+
+ /* Append string to COL_INFO */
+
+ if (options & CB_STR_COL_INFO) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
+ }
+
+ /* Append string to upper-level proto_items */
+
+ if (levels > 0 && item && s && s[0]) {
+ proto_item_append_text(item, ": %s", s);
+ item = item->parent;
+ levels--;
+ if (levels > 0) {
+ proto_item_append_text(item, ": %s", s);
+ item = item->parent;
+ levels--;
+ while (levels > 0) {
+ proto_item_append_text(item, " %s", s);
+ item = item->parent;
+ levels--;
+ }
+ }
+ }
+
+ /* Save string to dcv->private_data */
+
+ if (options & CB_STR_SAVE) {
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+
+ dcv->private_data = g_strdup(s);
+ }
+
+ g_free(s);
+}
+
+void cb_str_postprocess(packet_info *pinfo, proto_tree *tree _U_,
+ proto_item *item, tvbuff_t *tvb,
+ int start_offset, int end_offset,
+ void *callback_args)
+{
+ gint options = GPOINTER_TO_INT(callback_args);
+ gint levels = CB_STR_ITEM_LEVELS(options);
+ char *s;
+
+ /* Align start_offset on 4-byte boundary. */
+
+ if (start_offset % 4)
+ start_offset += 4 - (start_offset % 4);
+
+ /* Get string value */
+
+ if ((end_offset - start_offset) <= 12)
+ return; /* XXX: Use unistr2 dissector instead? */
+
+ /*
+ * XXX - need to handle non-printable characters here.
+ *
+ * XXX - this is typically called after the string has already
+ * been fetched and processed by some other routine; is there
+ * some way we can get that string, rather than duplicating the
+ * efforts of that routine?
+ */
+ s = tvb_get_string(
+ tvb, start_offset + 12, (end_offset - start_offset - 12) );
+
+ /* Append string to COL_INFO */
+
+ if (options & CB_STR_COL_INFO) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
+ }
+
+ /* Append string to upper-level proto_items */
+
+ if (levels > 0 && item && s && s[0]) {
+ proto_item_append_text(item, ": %s", s);
+ item = item->parent;
+ levels--;
+ if (levels > 0) {
+ proto_item_append_text(item, ": %s", s);
+ item = item->parent;
+ levels--;
+ while (levels > 0) {
+ proto_item_append_text(item, " %s", s);
+ item = item->parent;
+ levels--;
+ }
+ }
+ }
+
+ /* Save string to dcv->private_data */
+
+ if (options & CB_STR_SAVE) {
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+
+ dcv->private_data = g_strdup(s);
+ }
+
+ g_free(s);
+}
+
+/* Dissect a pointer to a NDR string and append the string value to the
+ proto_item. */
+
+int dissect_ndr_str_pointer_item(tvbuff_t *tvb, gint offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int type, char *text,
+ int hf_index, int levels)
+{
+ return dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, type, text, hf_index,
+ cb_wstr_postprocess, GINT_TO_POINTER(levels + 1));
+}
+
+/* SID dissection routines */
+
+static int hf_nt_count = -1;
+static int hf_nt_domain_sid = -1;
+
+int
+dissect_ndr_nt_SID(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ char *sid_str;
+ char *name;
+
+ if(di->hf_index!=-1){
+ name=proto_registrar_get_name(di->hf_index);
+ } else {
+ name="Domain";
+ }
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ /* the SID contains a conformant array, first we must eat
+ the 4-byte max_count before we can hand it off */
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_nt_count, NULL);
+
+ offset = dissect_nt_sid(tvb, offset, tree, name, &sid_str,
+ hf_nt_domain_sid);
+
+ /* dcv can be null, for example when this ndr structure is embedded
+ * inside non-dcerpc pdus, i.e. kerberos PAC structure
+ */
+ if(dcv){
+ dcv->private_data = sid_str;
+ }
+
+ return offset;
+}
+
+static int
+dissect_ndr_nt_SID_hf_through_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static gint ett_nt_sid_pointer = -1;
+
+int
+dissect_ndr_nt_PSID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "SID pointer:");
+ tree = proto_item_add_subtree(item, ett_nt_sid_pointer);
+ }
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_SID_hf_through_ptr, NDR_POINTER_UNIQUE,
+ "SID pointer", hf_nt_domain_sid);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static const true_false_string tfs_nt_acb_disabled = {
+ "Account is DISABLED",
+ "Account is NOT disabled"
+};
+static const true_false_string tfs_nt_acb_homedirreq = {
+ "Homedir is REQUIRED",
+ "Homedir is NOT required"
+};
+static const true_false_string tfs_nt_acb_pwnotreq = {
+ "Password is NOT required",
+ "Password is REQUIRED"
+};
+static const true_false_string tfs_nt_acb_tempdup = {
+ "This is a TEMPORARY DUPLICATE account",
+ "This is NOT a temporary duplicate account"
+};
+static const true_false_string tfs_nt_acb_normal = {
+ "This is a NORMAL USER account",
+ "This is NOT a normal user account"
+};
+static const true_false_string tfs_nt_acb_mns = {
+ "This is a MNS account",
+ "This is NOT a mns account"
+};
+static const true_false_string tfs_nt_acb_domtrust = {
+ "This is a DOMAIN TRUST account",
+ "This is NOT a domain trust account"
+};
+static const true_false_string tfs_nt_acb_wstrust = {
+ "This is a WORKSTATION TRUST account",
+ "This is NOT a workstation trust account"
+};
+static const true_false_string tfs_nt_acb_svrtrust = {
+ "This is a SERVER TRUST account",
+ "This is NOT a server trust account"
+};
+static const true_false_string tfs_nt_acb_pwnoexp = {
+ "Passwords does NOT expire",
+ "Password will EXPIRE"
+};
+static const true_false_string tfs_nt_acb_autolock = {
+ "This account has been AUTO LOCKED",
+ "This account has NOT been auto locked"
+};
+
+static gint ett_nt_acct_ctrl = -1;
+
+static int hf_nt_acct_ctrl = -1;
+static int hf_nt_acb_disabled = -1;
+static int hf_nt_acb_homedirreq = -1;
+static int hf_nt_acb_pwnotreq = -1;
+static int hf_nt_acb_tempdup = -1;
+static int hf_nt_acb_normal = -1;
+static int hf_nt_acb_mns = -1;
+static int hf_nt_acb_domtrust = -1;
+static int hf_nt_acb_wstrust = -1;
+static int hf_nt_acb_svrtrust = -1;
+static int hf_nt_acb_pwnoexp = -1;
+static int hf_nt_acb_autolock = -1;
+
+int
+dissect_ndr_nt_acct_ctrl(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_nt_acct_ctrl, &mask);
+
+ if(parent_tree){
+ item = proto_tree_add_uint(parent_tree, hf_nt_acct_ctrl,
+ tvb, offset-4, 4, mask);
+ tree = proto_item_add_subtree(item, ett_nt_acct_ctrl);
+ }
+
+ proto_tree_add_boolean(tree, hf_nt_acb_autolock,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_pwnoexp,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_svrtrust,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_wstrust,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_domtrust,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_mns,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_normal,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_tempdup,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_pwnotreq,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_homedirreq,
+ tvb, offset-4, 4, mask);
+ proto_tree_add_boolean(tree, hf_nt_acb_disabled,
+ tvb, offset-4, 4, mask);
+
+ return offset;
+}
+
+static int hf_logonhours_unknown_char;
+
+static int
+dissect_LOGON_HOURS_entry(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
+ hf_logonhours_unknown_char, NULL);
+ return offset;
+}
+
+static gint ett_nt_logon_hours_hours = -1;
+
+static int
+dissect_LOGON_HOURS_hours(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "LOGON_HOURS:");
+ tree = proto_item_add_subtree(item, ett_nt_logon_hours_hours);
+ }
+
+ offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
+ dissect_LOGON_HOURS_entry);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+
+ return offset;
+}
+
+static gint ett_nt_logon_hours = -1;
+static int hf_logonhours_divisions = -1;
+
+int
+dissect_ndr_nt_LOGON_HOURS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ ALIGN_TO_4_BYTES; /* strcture starts with short, but is aligned for longs */
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "LOGON_HOURS:");
+ tree = proto_item_add_subtree(item, ett_nt_logon_hours);
+ }
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_logonhours_divisions, NULL);
+ /* XXX - is this a bitmask like the "logon hours" field in the
+ Remote API call "NetUserGetInfo()" with an information level
+ of 11? */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_LOGON_HOURS_hours, NDR_POINTER_UNIQUE,
+ "LOGON_HOURS", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_ndr_nt_PSID_no_hf(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ offset=dissect_ndr_nt_PSID(tvb, offset, pinfo, parent_tree, drep);
+ return offset;
+}
+
+static int
+dissect_ndr_nt_PSID_ARRAY_sids (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_PSID_no_hf);
+
+ return offset;
+}
+
+static gint ett_nt_sid_array = -1;
+
+int
+dissect_ndr_nt_PSID_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 count;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "SID array:");
+ tree = proto_item_add_subtree(item, ett_nt_sid_array);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_nt_count, &count);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_PSID_ARRAY_sids, NDR_POINTER_UNIQUE,
+ "PSID_ARRAY", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static gint ett_nt_sid_and_attributes = -1;
+static int hf_nt_attrib = -1;
+
+int
+dissect_ndr_nt_SID_AND_ATTRIBUTES(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "SID_AND_ATTRIBUTES:");
+ tree = proto_item_add_subtree(item, ett_nt_sid_and_attributes);
+ }
+
+ offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_nt_attrib, NULL);
+
+ return offset;
+}
+
+static gint ett_nt_sid_and_attributes_array = -1;
+
+int
+dissect_ndr_nt_SID_AND_ATTRIBUTES_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ "SID_AND_ATTRIBUTES array:");
+ tree = proto_item_add_subtree(item, ett_nt_sid_and_attributes_array);
+ }
+
+ /*offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_count, &count); */
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_SID_AND_ATTRIBUTES);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+/*
+ * Register ett/hf values and perform DCERPC over SMB specific
+ * initialisation.
+ */
+void dcerpc_smb_init(int proto_dcerpc)
+{
+ static hf_register_info hf[] = {
+
+ /* String handling */
+
+ { &hf_nt_cs_size,
+ { "Size", "nt.str.size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Size of string in short integers",
+ HFILL }},
+
+ { &hf_nt_cs_len,
+ { "Length", "nt.str.len", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of string in short integers",
+ HFILL }},
+
+ /* Policy handles */
+
+ { &hf_nt_policy_open_frame,
+ { "Frame handle opened", "dcerpc.nt.open_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Frame handle opened", HFILL }},
+
+ { &hf_nt_policy_close_frame,
+ { "Frame handle closed", "dcerpc.nt.close_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Frame handle closed", HFILL }},
+
+ /* ACBs */
+
+ { &hf_nt_acct_ctrl,
+ { "Acct Ctrl", "nt.acct_ctrl", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Acct CTRL", HFILL }},
+
+ { &hf_nt_acb_disabled,
+ { "", "nt.acb.disabled", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_disabled), 0x0001,
+ "If this account is enabled or disabled", HFILL }},
+
+ { &hf_nt_acb_homedirreq,
+ { "", "nt.acb.homedirreq", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_homedirreq), 0x0002,
+ "Is hom,edirs required for this account?", HFILL }},
+
+ { &hf_nt_acb_pwnotreq,
+ { "", "nt.acb.pwnotreq", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_pwnotreq), 0x0004,
+ "If a password is required for this account?", HFILL }},
+
+ { &hf_nt_acb_tempdup,
+ { "", "nt.acb.tempdup", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_tempdup), 0x0008,
+ "If this is a temporary duplicate account", HFILL }},
+
+ { &hf_nt_acb_normal,
+ { "", "nt.acb.normal", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_normal), 0x0010,
+ "If this is a normal user account", HFILL }},
+
+ { &hf_nt_acb_mns,
+ { "", "nt.acb.mns", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_mns), 0x0020,
+ "MNS logon user account", HFILL }},
+
+ { &hf_nt_acb_domtrust,
+ { "", "nt.acb.domtrust", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_domtrust), 0x0040,
+ "Interdomain trust account", HFILL }},
+
+ { &hf_nt_acb_wstrust,
+ { "", "nt.acb.wstrust", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_wstrust), 0x0080,
+ "Workstation trust account", HFILL }},
+
+ { &hf_nt_acb_svrtrust,
+ { "", "nt.acb.svrtrust", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_svrtrust), 0x0100,
+ "Server trust account", HFILL }},
+
+ { &hf_nt_acb_pwnoexp,
+ { "", "nt.acb.pwnoexp", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_pwnoexp), 0x0200,
+ "If this account expires or not", HFILL }},
+
+ { &hf_nt_acb_autolock,
+ { "", "nt.acb.autolock", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_acb_autolock), 0x0400,
+ "If this account has been autolocked", HFILL }},
+
+ /* SIDs */
+
+ { &hf_nt_domain_sid,
+ { "Domain SID", "nt.domain_sid",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The Domain SID", HFILL }},
+
+ { &hf_nt_count,
+ { "Count", "nt.count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of elements in following array", HFILL }},
+
+ /* Logon hours */
+
+ { &hf_logonhours_divisions,
+ { "Divisions", "logonhours.divisions",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Number of divisions for LOGON_HOURS", HFILL }},
+
+ { &hf_logonhours_unknown_char,
+ { "Unknown char", "nt.unknown.char",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Unknown char. If you know what this is, contact "
+ "ethereal developers.", HFILL }},
+
+ /* Misc */
+
+ { &hf_nt_attrib,
+ { "Attributes", "nt.attr",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_nt_unicode_string,
+ &ett_nt_counted_string,
+ &ett_nt_counted_byte_array,
+ &ett_nt_policy_hnd,
+ &ett_nt_sid_pointer,
+ &ett_nt_acct_ctrl,
+ &ett_nt_logon_hours,
+ &ett_nt_logon_hours_hours,
+ &ett_nt_sid_array,
+ &ett_nt_sid_and_attributes_array,
+ &ett_nt_sid_and_attributes,
+ };
+
+ /* Register ett's and hf's */
+
+ proto_register_subtree_array(ett, array_length(ett));
+ proto_register_field_array(proto_dcerpc, hf, array_length(hf));
+
+ /* Initialise policy handle hash */
+
+ init_pol_hash();
+}
diff --git a/epan/dissectors/packet-dcerpc-nt.h b/epan/dissectors/packet-dcerpc-nt.h
new file mode 100644
index 0000000000..59dc173469
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-nt.h
@@ -0,0 +1,210 @@
+/* packet-dcerpc-nt.h
+ * Routines for DCERPC over SMB packet disassembly
+ * Copyright 2001-2003 Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_NT_H
+#define __PACKET_DCERPC_NT_H
+
+/*
+ * ett_ value for Unicode strings.
+ */
+extern gint ett_nt_unicode_string;
+
+/*
+ * Platform ID values, used by several dissectors.
+ */
+extern const value_string platform_id_vals[];
+
+/* Routines for handling deferral of referants in NDR */
+
+#define ALIGN_TO_4_BYTES \
+ { dcerpc_info *xzdi; \
+ xzdi=pinfo->private_data; \
+ if(!xzdi->conformant_run) { \
+ if(offset&0x03) { \
+ offset=(offset&0xfffffffc)+4; \
+ } \
+ } \
+ }
+
+int
+dissect_ndr_counted_string_cb(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int hf_index,
+ dcerpc_callback_fnct_t *callback,
+ void *callback_args);
+
+int
+dissect_ndr_counted_string_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep);
+
+int
+dissect_ndr_counted_string(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep, int hf_index, int levels);
+
+int
+dissect_ndr_counted_byte_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep, int hf_index);
+
+int
+dissect_ndr_counted_byte_array_cb(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int hf_index,
+ dcerpc_callback_fnct_t *callback,
+ void *callback_args);
+
+int
+dissect_ndr_nt_acct_ctrl(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep);
+int
+dissect_ndr_nt_NTTIME (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int hf_index);
+int
+dissect_ndr_nt_LOGON_HOURS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep);
+int
+dissect_ndr_nt_SID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep);
+int
+dissect_ndr_nt_PSID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep);
+int
+dissect_ndr_nt_PSID_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep);
+
+int
+dissect_ndr_nt_SID_AND_ATTRIBUTES_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep);
+int
+dissect_ndr_nt_SID_AND_ATTRIBUTES(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep);
+
+/*
+ * Policy handle hashing
+ */
+
+/* Store open and close packet numbers for a policy handle */
+
+void
+dcerpc_smb_store_pol_pkts(e_ctx_hnd *policy_hnd, packet_info *pinfo,
+ gboolean is_open, gboolean is_close);
+
+/* Store a name with a policy handle */
+
+void
+dcerpc_smb_store_pol_name(e_ctx_hnd *policy_hnd, packet_info *pinfo,
+ char *name);
+
+/* Fetch details stored with a policy handle */
+
+gboolean
+dcerpc_smb_fetch_pol(e_ctx_hnd *policy_hnd, char **name,
+ guint32 *open_frame, guint32 *close_frame,
+ guint32 cur_frame);
+
+/* Dissect NT specific things */
+
+int
+dissect_ntstatus(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata);
+
+int
+dissect_doserror(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata);
+
+int
+dissect_nt_policy_hnd(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, int hfindex,
+ e_ctx_hnd *pdata, proto_item **pitem,
+ gboolean is_open, gboolean is_close);
+
+int
+dissect_nt_GUID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep);
+
+int
+dissect_nt_LUID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep);
+
+/* Stored here instead of packet-dcerpc{,-ndr}.c as they are probably not
+ official NDR representations. */
+
+int dissect_dcerpc_uint8s(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, int length, const guint8 **pdata);
+
+int dissect_ndr_uint8s(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, int length, const guint8 **pdata);
+
+int dissect_dcerpc_uint16s(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, int length);
+
+int dissect_ndr_uint16s(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, int length);
+
+int dissect_ndr_str_pointer_item(tvbuff_t *tvb, gint offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep, int type, char *text,
+ int hf_index, int levels);
+
+/*
+ * Helper routines for dissecting NDR strings
+ */
+
+/* Number of levels to go up appending string to pointer item */
+#define CB_STR_ITEM_LEVELS(x) ((x) & 0xFFFF)
+#define CB_STR_COL_INFO 0x10000 /* Append string to COL_INFO */
+#define CB_STR_SAVE 0x20000 /* Save string to dcv->private_data */
+
+void cb_wstr_postprocess(packet_info *pinfo, proto_tree *tree _U_,
+ proto_item *item, tvbuff_t *tvb,
+ int start_offset, int end_offset,
+ void *callback_args);
+void cb_str_postprocess(packet_info *pinfo, proto_tree *tree _U_,
+ proto_item *item, tvbuff_t *tvb,
+ int start_offset, int end_offset,
+ void *callback_args);
+
+/* Initialise DCERPC over SMB */
+
+void dcerpc_smb_init(int proto_dcerpc);
+
+#endif /* packet-dcerpc-nt.h */
diff --git a/epan/dissectors/packet-dcerpc-oxid.c b/epan/dissectors/packet-dcerpc-oxid.c
new file mode 100644
index 0000000000..0c31a527a0
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-oxid.c
@@ -0,0 +1,282 @@
+/* packet-dcerpc-oxid.c
+ * Routines for DCOM OXID Resolver
+ * Copyright 2001, Todd Sabin <tas@webspan.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dcom.h"
+#include "packet-smb-common.h"
+
+static int proto_oxid = -1;
+
+static int hf_opnum = -1;
+static int hf_COMVERSION_MjrVer = -1;
+static int hf_COMVERSION_MnrVer = -1;
+static int hf_wNumEntries = -1;
+static int hf_wSecurityOffset = -1;
+static int hf_wTowerId = -1;
+static int hf_aNetworkAddr = -1;
+static int hf_wAuthnSvc = -1;
+static int hf_wAuthzSvc = -1;
+static int hf_aPrinceName = -1;
+static int hf_Unknown1 = -1;
+static int hf_Unknown2 = -1;
+
+static gint ett_oxid = -1;
+
+static e_uuid_t uuid_oxid = { 0x99fcfec4, 0x5260, 0x101b, { 0xbb, 0xcb, 0x00, 0xaa, 0x00, 0x21, 0x34, 0x7a } };
+static guint16 ver_oxid = 0;
+
+static const char *
+authz_val2str(unsigned short authz) {
+ switch (authz) {
+ case 0:
+ return "RPC_C_AUTHZ_NONE";
+ break;
+ case 1:
+ return "RPC_C_AUTHZ_NAME";
+ break;
+ case 2:
+ return "RPC_C_AUTHZ_DCE";
+ break;
+ case 0xffff:
+ return "Default";
+ break;
+ default:
+ return "Unknown";
+ break;
+ }
+}
+
+static const char *
+authn_val2str(unsigned short authn) {
+ switch (authn) {
+ case 0:
+ return "RPC_C_AUTHN_NONE";
+ break;
+ case 1:
+ return "RPC_C_AUTHN_DCE_PRIVATE";
+ break;
+ case 2:
+ return "RPC_C_AUTHN_DCE_PUBLIC";
+ break;
+ case 4:
+ return "RPC_C_AUTHN_DEC_PUBLIC";
+ break;
+ case 9:
+ return "RPC_C_AUTHN_GSS_NEGOTIATE";
+ break;
+ case 10:
+ return "RPC_C_AUTH_WINNT";
+ break;
+ case 14:
+ return "RPC_C_AUTHN_GSS_SCHANNEL";
+ break;
+ case 16:
+ return "RPC_C_AUTHN_GSS_KERBEROS";
+ break;
+ case 17:
+ return "RPC_C_AUTHN_MSN";
+ break;
+ case 18:
+ return "RPC_C_AUTHN_DPA";
+ break;
+ case 100:
+ return "RPC_C_AUTHN_MQ";
+ break;
+ case 0xffff:
+ return "RPC_C_AUTHN_DEFAULT";
+ break;
+ default:
+ return "Unknown";
+ break;
+ }
+}
+
+static const char *
+towerid_val2str(unsigned short tower) {
+ switch (tower) {
+ case 0x4:
+ return "NCACN_DNET_NSP";
+ break;
+ case 0x7:
+ return "NCACN_IP_TCP";
+ break;
+ case 0x8:
+ return "NCADG_IP_UDP";
+ break;
+ case 0xC:
+ return "NCACN_SPX";
+ break;
+
+ case 0xD:
+ return "NCACN_NB_IPX";
+ break;
+ case 0xE:
+ return "NCADG_IPX";
+ break;
+ case 0x12:
+ return "NCACN_NB_NB";
+ break;
+ case 0x1F:
+ return "NCACN_HTTP";
+ break;
+ default:
+ return "Unknown";
+ break;
+ }
+}
+
+static int
+oxid_server_alive2_dissect_rply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep) {
+ COMVERSION comver;
+ DUALSTRINGARRAY stringarray;
+ STRINGBINDING stringbind;
+ SECURITYBINDING securitybind;
+ proto_item *bind_hdr, *entries_hdr, *sec_hdr;
+ proto_tree *bind_tree, *entries_tree, *sec_tree;
+ char *aNetworkAddr = NULL;
+ char *aPrinceName = NULL;
+ unsigned short string_len = 0;
+ unsigned short security_len = 0;
+ unsigned char unknown1[8];
+ unsigned char unknown2[8];
+
+ dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_COMVERSION_MjrVer, &comver.MajorVersion);
+ offset += sizeof(comver.MajorVersion);
+
+ dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_COMVERSION_MnrVer, &comver.MinorVersion);
+ offset += sizeof(comver.MinorVersion);
+
+ dissect_dcerpc_uint64(tvb , offset, pinfo, tree, drep, hf_Unknown1, unknown1);
+
+ offset += sizeof(unknown1); /*FIXME - understand what those 8 bytes mean! don't skip'em!*/
+ string_len = dcerpc_tvb_get_ntohs(tvb, offset, drep) * 2;
+ bind_hdr = proto_tree_add_text(tree, tvb, offset, (int)string_len, "DUALSTRINGARRAY structure");
+ bind_tree = proto_item_add_subtree(bind_hdr, 0);
+
+ dissect_dcerpc_uint16(tvb, offset, pinfo, bind_tree, drep, hf_wNumEntries, &stringarray.wNumEntries);
+ offset += sizeof(stringarray.wNumEntries);
+
+ security_len = dcerpc_tvb_get_ntohs(tvb, offset, drep) * 2;
+ dissect_dcerpc_uint16(tvb, offset, pinfo, bind_tree, drep, hf_wSecurityOffset, &stringarray.wSecurityOffset);
+ offset += sizeof(stringarray.wSecurityOffset);
+
+ entries_hdr = proto_tree_add_text(bind_tree, tvb, offset, (int)security_len, "STRING BINDING");
+ entries_tree = proto_item_add_subtree(entries_hdr, 0);
+
+ while(tvb_get_ntohs(tvb, offset) != 0) { /* check that this is not terminating zero */
+
+ stringbind.wTowerId = dcerpc_tvb_get_ntohs(tvb, offset, drep);
+ proto_tree_add_text(entries_tree, tvb, offset, sizeof(stringbind.wTowerId), "Network Protocol ('TowerID'): %s (0x%x)",towerid_val2str(stringbind.wTowerId), stringbind.wTowerId);
+
+ offset += sizeof(stringbind.wTowerId);
+
+ offset = display_unicode_string(tvb, entries_tree, offset, hf_aNetworkAddr, &aNetworkAddr);
+ }
+ offset += 2; /* hop over the extra terminating zero */
+
+ sec_hdr = proto_tree_add_text(bind_tree, tvb, offset, 0, "SECURITY BINDING");
+ sec_tree = proto_item_add_subtree(sec_hdr, 0);
+
+ while(tvb_get_ntohs(tvb, offset) != 0) {
+ securitybind.wAuthnSvc = dcerpc_tvb_get_ntohs(tvb, offset, drep);
+ proto_tree_add_text(sec_tree, tvb, offset, sizeof(securitybind.wAuthnSvc), "Authentication Service: %s (0x%x)",authn_val2str(securitybind.wAuthnSvc),securitybind.wAuthnSvc);
+ offset += sizeof(securitybind.wAuthnSvc);
+
+ securitybind.wAuthzSvc = dcerpc_tvb_get_ntohs(tvb, offset, drep);
+ proto_tree_add_text(sec_tree, tvb, offset, sizeof(securitybind.wAuthzSvc), "Authorization Service: %s (0x%x)",authz_val2str(securitybind.wAuthzSvc),securitybind.wAuthzSvc);
+ offset += sizeof(securitybind.wAuthzSvc);
+
+ offset = display_unicode_string(tvb, sec_tree, offset, hf_aPrinceName, &aPrinceName);
+ }
+ offset += 2; /* hop over the extra terminating zero */
+
+ dissect_dcerpc_uint64(tvb, offset, pinfo, tree, drep, hf_Unknown2, unknown2);
+ offset += sizeof(unknown2);
+ return offset;
+}
+
+static dcerpc_sub_dissector oxid_dissectors[] = {
+ { 0, "ResolveOxid", NULL, NULL },
+ { 1, "SimplePing", NULL, NULL },
+ { 2, "ComplexPing", NULL, NULL },
+ { 3, "ServerAlive", NULL, NULL },
+ { 4, "ResolveOxid2", NULL, NULL },
+ { 5, "ServerAlive2", NULL, oxid_server_alive2_dissect_rply },
+ { 0, NULL, NULL, NULL },
+};
+
+void
+proto_register_oxid (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_opnum,
+ { "Operation", "oxid.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_COMVERSION_MjrVer,
+ { "COM Major Version", "oxid5.com_mjr_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_COMVERSION_MnrVer,
+ { "COM Minor Version", "oxid5.com_mnr_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_wNumEntries,
+ { "Total Entries length (in 16 bytes blocks)", "oxid5.NumEntries", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_wSecurityOffset,
+ { "Offset of Security Binding (in 16 bytes blocks)", "oxid5.SecurityOffset", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_wTowerId,
+ { "Network Protocol ('TowerID')", "oxid5.wTowerId", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_aNetworkAddr,
+ { "Network Address ('aNetworkAddr')", "oxid5.aNetworkAddr", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_wAuthnSvc,
+ { "Authentication Service", "oxid5.AuthnSvc", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_wAuthzSvc,
+ { "Autherization Service", "oxid5.AuthzSvc", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_aPrinceName,
+ { "aPrinceName", "oxid5.aPrinceName", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_Unknown1,
+ { "unknown 8 bytes 1", "oxid5.unknown1", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_Unknown2,
+ { "unknown 8 bytes 2", "oxid5.unknown2", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_oxid
+ };
+ proto_oxid = proto_register_protocol ("DCOM OXID Resolver", "OXID", "oxid");
+ proto_register_field_array (proto_oxid, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_oxid (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_oxid, ett_oxid, &uuid_oxid, ver_oxid, oxid_dissectors, hf_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rdaclif.c b/epan/dissectors/packet-dcerpc-rdaclif.c
new file mode 100644
index 0000000000..fb0b431f96
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rdaclif.c
@@ -0,0 +1,94 @@
+/* packet-dcerpc-rdaclif.c
+ *
+ * Routines for rdaclif dissection
+ * Copyright 2004, Jaime Fournier <jaime.fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz ../security/idl/rdaclif.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_rdaclif = -1;
+static int hf_rdaclif_opnum = -1;
+
+
+static gint ett_rdaclif = -1;
+static e_uuid_t uuid_rdaclif =
+ { 0x47b33331, 0x8000, 0x0000, {0x0d, 0x00, 0x01, 0xdc, 0x6c, 0x00, 0x00,
+ 0x00} };
+
+static guint16 ver_rdaclif = 1;
+
+
+static dcerpc_sub_dissector rdaclif_dissectors[] = {
+ {0, "lookup", NULL, NULL},
+ {1, "replace", NULL, NULL},
+ {2, "get_access", NULL, NULL},
+ {3, "test_access", NULL, NULL},
+ {4, "test_access_on_behalf", NULL, NULL},
+ {5, "get_manager_types", NULL, NULL},
+ {6, "get_printstring", NULL, NULL},
+ {7, "get_referral", NULL, NULL},
+ {8, "get_mgr_types_semantics", NULL, NULL},
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_rdaclif (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rdaclif_opnum,
+ {"Operation", "rdaclif.opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operation", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_rdaclif,
+ };
+ proto_rdaclif =
+ proto_register_protocol ("DCE/RPC Directory Acl Interface ", "rdaclif",
+ "rdaclif");
+ proto_register_field_array (proto_rdaclif, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rdaclif (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rdaclif, ett_rdaclif, &uuid_rdaclif, ver_rdaclif,
+ rdaclif_dissectors, hf_rdaclif_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-reg.c b/epan/dissectors/packet-dcerpc-reg.c
new file mode 100644
index 0000000000..5cc600ad13
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-reg.c
@@ -0,0 +1,926 @@
+/* packet-dcerpc-reg.c
+ * Routines for SMB \PIPE\winreg packet disassembly
+ * Copyright 2001-2003 Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-reg.h"
+#include "smb.h"
+
+/* Global hf index fields */
+
+static int hf_rc = -1;
+static int hf_hnd = -1;
+static int hf_access_mask = -1;
+static int hf_keytype = -1;
+static int hf_keydata = -1;
+static int hf_offered = -1;
+static int hf_returned = -1;
+static int hf_reserved = -1;
+static int hf_unknown = -1;
+
+/* OpenHKLM */
+
+static int hf_openhklm_unknown1 = -1;
+static int hf_openhklm_unknown2 = -1;
+
+/* QueryInfoKey */
+
+static int hf_querykey_class = -1;
+static int hf_querykey_num_subkeys = -1;
+static int hf_querykey_max_subkey_len = -1;
+static int hf_querykey_reserved = -1;
+static int hf_querykey_num_values = -1;
+static int hf_querykey_max_valname_len = -1;
+static int hf_querykey_max_valbuf_size = -1;
+static int hf_querykey_secdesc = -1;
+static int hf_querykey_modtime = -1;
+
+/* OpenKey */
+
+static int hf_keyname = -1;
+static int hf_openkey_unknown1 = -1;
+
+/* GetVersion */
+
+static int hf_getversion_version = -1;
+
+/* Shutdown */
+static int hf_shutdown_message = -1;
+static int hf_shutdown_seconds = -1;
+static int hf_shutdown_force = -1;
+static int hf_shutdown_reboot = -1;
+static int hf_shutdown_server = -1;
+static int hf_shutdown_reason = -1;
+
+/* Data that is passed to a open call */
+
+static int
+dissect_open_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep,
+ hf_openhklm_unknown1, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep,
+ hf_openhklm_unknown1, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_access_mask, NULL);
+
+ return offset;
+}
+
+/*
+ * OpenHKLM
+ */
+
+static int
+RegOpenHKLM_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_open_data,
+ NDR_POINTER_UNIQUE, "Unknown", -1);
+
+ return offset;
+}
+
+static int
+RegOpenHKLM_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_rc, &status);
+
+ if (status == 0) {
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, "HKLM handle");
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": HKLM handle");
+ }
+
+ return offset;
+}
+
+/*
+ * OpenHKU
+ */
+
+static int
+RegOpenHKU_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_open_data,
+ NDR_POINTER_UNIQUE, "Unknown", -1);
+
+ return offset;
+}
+
+static int
+RegOpenHKU_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, &status);
+
+ if (status == 0) {
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, "HKU handle");
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": HKU handle");
+ }
+
+ return offset;
+}
+
+/*
+ * OpenHKCR
+ */
+
+static int
+RegOpenHKCR_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_open_data,
+ NDR_POINTER_UNIQUE, "Unknown", -1);
+
+ return offset;
+}
+
+static int
+RegOpenHKCR_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, &status);
+
+ if (status == 0) {
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, "HKCR handle");
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": HKCR handle");
+ }
+
+ return offset;
+}
+
+/*
+ * CloseKey
+ */
+
+static int
+RegCloseKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, NULL, NULL, FALSE, TRUE);
+
+ return offset;
+}
+
+static int
+RegCloseKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * QueryInfoKey
+ */
+
+static int
+RegQueryInfoKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
+
+ return offset;
+}
+
+static int
+RegQueryInfoKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_querykey_num_subkeys, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_querykey_max_subkey_len, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_querykey_reserved, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_querykey_num_values, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_querykey_max_valname_len, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_querykey_max_valbuf_size, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_querykey_secdesc, NULL);
+
+ offset = dissect_ndr_nt_NTTIME(
+ tvb, offset, pinfo, tree, drep, hf_querykey_modtime);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * OpenKey
+ */
+
+static int
+RegOpenKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_openkey_unknown1, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_access_mask, NULL);
+
+ return offset;
+}
+
+static int
+RegOpenKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, &status);
+
+ if (status == 0) {
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
+ "OpenKey handle");
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": OpenKey handle");
+ }
+
+ return offset;
+}
+
+/*
+ * GetVersion
+ */
+
+static int
+RegGetVersion_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+RegGetVersion_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_getversion_version, NULL);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * EnumKey
+ */
+
+static int
+RegEnumKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+RegEnumKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * RegQueryValue
+ */
+
+static int
+dissect_reserved(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_reserved, NULL);
+
+ return offset;
+}
+
+static int
+dissect_offered(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static int
+dissect_returned(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_returned, NULL);
+
+ return offset;
+}
+
+static int
+dissect_unknown(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_unknown, NULL);
+
+ return offset;
+}
+
+static int
+RegQueryValue_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_reserved, NDR_POINTER_UNIQUE,
+ "Reserved", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_offered, NDR_POINTER_UNIQUE,
+ "Offered", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_unknown, NDR_POINTER_UNIQUE,
+ "Unknown", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_unknown, NDR_POINTER_UNIQUE,
+ "Unknown", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_offered, NDR_POINTER_UNIQUE,
+ "Offered", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_returned, NDR_POINTER_UNIQUE,
+ "Returned", -1);
+
+ return offset;
+}
+
+static int
+dissect_key_type(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_keytype, NULL);
+
+ return offset;
+}
+
+static int
+RegQueryValue_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_key_type, NDR_POINTER_UNIQUE,
+ "Key Type", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_byte_array, NDR_POINTER_UNIQUE,
+ "Key Data", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_offered, NDR_POINTER_UNIQUE,
+ "Offered", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_returned, NDR_POINTER_UNIQUE,
+ "Returned", -1);
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/* Reg Shutdown functions */
+static int
+dissect_shutdown_server(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_server, NULL);
+
+ return offset;
+}
+
+static int
+dissect_shutdown_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_message, 0);
+
+ return offset;
+}
+
+static int
+RegShutdown_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_shutdown_server, NDR_POINTER_UNIQUE,
+ "Server", -1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_shutdown_message, NDR_POINTER_UNIQUE,
+ "message", -1);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_seconds, NULL);
+
+ offset = dissect_ndr_uint8(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_force, NULL);
+ offset = dissect_ndr_uint8(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_reboot, NULL);
+
+ return offset;
+}
+
+static int
+RegShutdown_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+static int
+RegAbortShutdown_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_shutdown_server, NDR_POINTER_UNIQUE,
+ "Server", -1);
+
+ return offset;
+}
+
+static int
+RegShutdownEx_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = RegShutdown_q(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_shutdown_reason, NULL);
+
+ return offset;
+}
+
+#if 0
+
+/* Templates for new subdissectors */
+
+/*
+ * FOO
+ */
+
+static int
+RegFoo_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+
+ /* Parse packet */
+
+ return offset;
+}
+
+static int
+RegFoo_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+
+ /* Parse packet */
+
+ offset = dissect_ntstatus(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+#endif
+
+/* Registry data types */
+
+const value_string reg_datatypes[] = {
+ { DCERPC_REG_NONE, "REG_NONE" },
+ { DCERPC_REG_SZ, "REG_SZ" },
+ { DCERPC_REG_EXPAND_SZ, "REG_EXPAND_SZ" },
+ { DCERPC_REG_BINARY, "REG_BINARY" },
+ { DCERPC_REG_DWORD, "REG_DWORD" },
+ { DCERPC_REG_DWORD_LE, "REG_DWORD_LE" },
+ { DCERPC_REG_DWORD_BE, "REG_DWORD_BE" },
+ { DCERPC_REG_LINK, "REG_LINK" },
+ { DCERPC_REG_MULTI_SZ, "REG_MULTI_SZ" },
+ { DCERPC_REG_RESOURCE_LIST, "REG_RESOURCE_LIST" },
+ { DCERPC_REG_FULL_RESOURCE_DESCRIPTOR, "REG_FULL_RESOURCE_DESCRIPTOR" },
+ { DCERPC_REG_RESOURCE_REQUIREMENTS_LIST, "REG_RESOURCE_REQUIREMENTS_LIST" },
+ {0, NULL }
+};
+
+static int proto_dcerpc_reg = -1;
+static int hf_reg_opnum = -1;
+static gint ett_dcerpc_reg = -1;
+
+static e_uuid_t uuid_dcerpc_reg = {
+ 0x338cd001, 0x2244, 0x31f1,
+ { 0xaa, 0xaa, 0x90, 0x00, 0x38, 0x00, 0x10, 0x03 }
+};
+
+static guint16 ver_dcerpc_reg = 1;
+
+static dcerpc_sub_dissector dcerpc_reg_dissectors[] = {
+ { REG_OPEN_HKCR, "OpenHKCR", RegOpenHKCR_q, RegOpenHKCR_r },
+ { REG_OPEN_HKCU, "OpenHKCU", NULL, NULL },
+ { REG_OPEN_HKLM, "OpenHKLM", RegOpenHKLM_q, RegOpenHKLM_r },
+ { REG_OPEN_HKPD, "OpenHKPD", NULL, NULL },
+ { REG_OPEN_HKU, "OpenHKU", RegOpenHKU_q, RegOpenHKU_r },
+ { REG_CLOSE_KEY, "CloseKey", RegCloseKey_q, RegCloseKey_r },
+ { REG_CREATE_KEY, "CreateKey", NULL, NULL },
+ { REG_DELETE_KEY, "DeleteKey", NULL, NULL },
+ { REG_DELETE_VALUE, "DeleteValue", NULL, NULL },
+ { REG_ENUM_KEY, "EnumKey", RegEnumKey_q, RegEnumKey_r },
+ { REG_ENUM_VALUE, "EnumValue", NULL, NULL },
+ { REG_FLUSH_KEY, "FlushKey", NULL, NULL },
+ { REG_GET_KEY_SEC, "GetKeySecurity", NULL, NULL },
+ { REG_LOAD_KEY, "LoadKey", NULL, NULL },
+ { REG_NOTIFY_CHANGE_KEY_VALUE, "NotifyChangeKeyValue", NULL, NULL },
+ { REG_OPEN_KEY, "OpenKey", RegOpenKey_q, RegOpenKey_r },
+ { REG_QUERY_INFO_KEY, "QueryInfoKey", RegQueryInfoKey_q, RegQueryInfoKey_r },
+ { REG_QUERY_VALUE, "QueryValue", RegQueryValue_q, RegQueryValue_r },
+ { REG_REPLACE_KEY, "ReplaceKey", NULL, NULL },
+ { REG_RESTORE_KEY, "RestoreKey", NULL, NULL },
+ { REG_SAVE_KEY, "SaveKey", NULL, NULL },
+ { REG_SET_KEY_SEC, "SetKeySecurity", NULL, NULL },
+ { REG_SET_VALUE, "SetValue", NULL, NULL },
+ { REG_UNLOAD_KEY, "UnLoadKey", NULL, NULL },
+ { REG_INITIATE_SYSTEM_SHUTDOWN, "InitiateSystemShutdown",
+ RegShutdown_q, RegShutdown_r },
+ { REG_ABORT_SYSTEM_SHUTDOWN, "AbortSystemShutdown",
+ RegAbortShutdown_q, RegShutdown_r },
+ { REG_GET_VERSION, "GetVersion", RegGetVersion_q, RegGetVersion_r },
+ { REG_OPEN_HKCC, "OpenHKCC", NULL, NULL },
+ { REG_OPEN_HKDD, "OpenHKDD", NULL, NULL },
+ { REG_QUERY_MULTIPLE_VALUES, "QueryMultipleValues", NULL, NULL },
+ { REG_INITIATE_SYSTEM_SHUTDOWN_EX, "InitiateSystemShutdownEx",
+ RegShutdownEx_q, RegShutdown_r },
+ { REG_SAVE_KEY_EX, "SaveKeyEx", NULL, NULL },
+ { REG_OPEN_HKPT, "OpenHKPT", NULL, NULL },
+ { REG_OPEN_HKPN, "OpenHKPN", NULL, NULL },
+ { REG_QUERY_MULTIPLE_VALUES_2, "QueryMultipleValues2", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_reg(void)
+{
+ static hf_register_info hf[] = {
+
+ /* Global indexes */
+
+ { &hf_hnd,
+ { "Context handle", "reg.hnd", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "REG policy handle", HFILL }},
+
+ { &hf_rc,
+ { "Return code", "reg.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "REG return code", HFILL }},
+
+ { &hf_reg_opnum,
+ { "Operation", "reg.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ { &hf_access_mask,
+ { "Access mask", "reg.access_mask", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Access mask", HFILL }},
+
+ { &hf_keytype,
+ { "Key type", "reg.type", FT_UINT32, BASE_DEC,
+ VALS(reg_datatypes), 0x0, "Key type", HFILL }},
+
+ { &hf_keydata,
+ { "Key data", "reg.data", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Key data", HFILL }},
+
+ { &hf_offered,
+ { "Offered", "reg.offered", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Offered", HFILL }},
+
+ { &hf_returned,
+ { "Returned", "reg.returned", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Returned", HFILL }},
+
+ { &hf_reserved,
+ { "Reserved", "reg.reserved", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Reserved", HFILL }},
+
+ { &hf_unknown,
+ { "Unknown", "reg.unknown", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Unknown", HFILL }},
+
+ /* OpenHKLM */
+
+ { &hf_openhklm_unknown1,
+ { "Unknown 1", "reg.openhklm.unknown1", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Unknown 1", HFILL }},
+
+ { &hf_openhklm_unknown2,
+ { "Unknown 2", "reg.openhklm.unknown2", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Unknown 2", HFILL }},
+
+ /* QueryClass */
+
+ { &hf_querykey_class,
+ { "Class", "reg.querykey.class", FT_STRING, BASE_NONE,
+ NULL, 0, "Class", HFILL }},
+
+ { &hf_querykey_num_subkeys,
+ { "Num subkeys", "reg.querykey.num_subkeys", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Num subkeys", HFILL }},
+
+ { &hf_querykey_max_subkey_len,
+ { "Max subkey len", "reg.querykey.max_subkey_len", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Max subkey len", HFILL }},
+
+ { &hf_querykey_reserved,
+ { "Reserved", "reg.querykey.reserved", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Reserved", HFILL }},
+
+ { &hf_querykey_num_values,
+ { "Num values", "reg.querykey.num_values", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Num values", HFILL }},
+
+ { &hf_querykey_max_valname_len,
+ { "Max valnum len", "reg.querykey.max_valname_len", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Max valname len", HFILL }},
+
+ { &hf_querykey_max_valbuf_size,
+ { "Max valbuf size", "reg.querykey.max_valbuf_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Max valbuf size", HFILL }},
+
+ { &hf_querykey_secdesc,
+ { "Secdesc", "reg.querykey.secdesc", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Secdesc", HFILL }},
+
+ { &hf_querykey_modtime,
+ { "Mod time", "reg.querykey.modtime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0x0, "Secdesc", HFILL }},
+
+ /* OpenKey */
+
+ { &hf_keyname,
+ { "Key name", "reg.keyname", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Keyname", HFILL }},
+
+ { &hf_openkey_unknown1,
+ { "Unknown 1", "reg.openkey.unknown1", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Unknown 1", HFILL }},
+
+ /* GetVersion */
+
+ { &hf_getversion_version,
+ { "Version", "reg.getversion.version", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Version", HFILL }},
+
+ /* Shutdown */
+ { &hf_shutdown_message,
+ { "Message", "reg.shutdown.message", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Message", HFILL }},
+
+ { &hf_shutdown_seconds,
+ { "Seconds", "reg.shutdown.seconds", FT_UINT32, BASE_DEC,
+ NULL, 0x00, "Seconds", HFILL }},
+
+ { &hf_shutdown_force,
+ { "Force applications shut", "reg.shutdown.force", FT_UINT8,
+ BASE_DEC, NULL, 0x00, "Force applications shut", HFILL }},
+
+ { &hf_shutdown_reboot,
+ { "Reboot", "reg.shutdown.reboot", FT_UINT8, BASE_DEC,
+ NULL, 0x00, "Reboot", HFILL }},
+
+ { &hf_shutdown_server,
+ { "Server", "reg.shutdown.server", FT_UINT16, BASE_HEX,
+ NULL, 0x00, "Server", HFILL }},
+
+ { &hf_shutdown_reason,
+ { "Reason", "reg.shutdown.reason", FT_UINT32, BASE_HEX,
+ NULL, 0x00, "Reason", HFILL }}
+
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_reg
+ };
+
+ proto_dcerpc_reg = proto_register_protocol(
+ "Microsoft Registry", "WINREG", "winreg");
+
+ proto_register_field_array(proto_dcerpc_reg, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_reg(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_reg, ett_dcerpc_reg, &uuid_dcerpc_reg,
+ ver_dcerpc_reg, dcerpc_reg_dissectors, hf_reg_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-reg.h b/epan/dissectors/packet-dcerpc-reg.h
new file mode 100644
index 0000000000..6c7805aefb
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-reg.h
@@ -0,0 +1,84 @@
+/* packet-dcerpc-reg.h
+ * Routines for SMB \PIPE\winreg packet disassembly
+ * Copyright 2001, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_REG_H
+#define __PACKET_DCERPC_REG_H
+
+/* Functions available on the WINREG pipe. From Samba, include/rpc_reg.h */
+
+#define REG_OPEN_HKCR 0x00
+#define REG_OPEN_HKCU 0x01
+#define REG_OPEN_HKLM 0x02
+#define REG_OPEN_HKPD 0x03
+#define REG_OPEN_HKU 0x04
+#define REG_CLOSE_KEY 0x05
+#define REG_CREATE_KEY 0x06
+#define REG_DELETE_KEY 0x07
+#define REG_DELETE_VALUE 0x08
+#define REG_ENUM_KEY 0x09
+#define REG_ENUM_VALUE 0x0a
+#define REG_FLUSH_KEY 0x0b
+#define REG_GET_KEY_SEC 0x0c
+#define REG_LOAD_KEY 0x0d
+#define REG_NOTIFY_CHANGE_KEY_VALUE 0x0e
+#define REG_OPEN_KEY 0x0f
+#define REG_QUERY_INFO_KEY 0x10
+#define REG_QUERY_VALUE 0x11
+#define REG_REPLACE_KEY 0x12
+#define REG_RESTORE_KEY 0x13
+#define REG_SAVE_KEY 0x14
+#define REG_SET_KEY_SEC 0x15
+#define REG_SET_VALUE 0x16
+#define REG_UNLOAD_KEY 0x17
+#define REG_INITIATE_SYSTEM_SHUTDOWN 0x18
+#define REG_ABORT_SYSTEM_SHUTDOWN 0x19
+#define REG_GET_VERSION 0x1a
+#define REG_OPEN_HKCC 0x1b
+#define REG_OPEN_HKDD 0x1c
+#define REG_QUERY_MULTIPLE_VALUES 0x1d
+#define REG_INITIATE_SYSTEM_SHUTDOWN_EX 0x1e
+#define REG_SAVE_KEY_EX 0x1f
+#define REG_OPEN_HKPT 0x20
+#define REG_OPEN_HKPN 0x21
+#define REG_QUERY_MULTIPLE_VALUES_2 0x22
+
+/* Registry data types */
+
+#define DCERPC_REG_NONE 0
+#define DCERPC_REG_SZ 1
+#define DCERPC_REG_EXPAND_SZ 2
+#define DCERPC_REG_BINARY 3
+#define DCERPC_REG_DWORD 4
+#define DCERPC_REG_DWORD_LE 4 /* DWORD, little endian */
+#define DCERPC_REG_DWORD_BE 5 /* DWORD, big endian */
+#define DCERPC_REG_LINK 6
+#define DCERPC_REG_MULTI_SZ 7
+#define DCERPC_REG_RESOURCE_LIST 8
+#define DCERPC_REG_FULL_RESOURCE_DESCRIPTOR 9
+#define DCERPC_REG_RESOURCE_REQUIREMENTS_LIST 10
+
+extern const value_string reg_datatypes[];
+
+#endif /* packet-dcerpc-reg.h */
diff --git a/epan/dissectors/packet-dcerpc-remact.c b/epan/dissectors/packet-dcerpc-remact.c
new file mode 100644
index 0000000000..352940929a
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-remact.c
@@ -0,0 +1,77 @@
+/* packet-dcerpc-remact.c
+ * Routines for DCOM Remote Activation
+ * Copyright 2001, Todd Sabin <tas@webspan.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_remact = -1;
+
+static int hf_opnum = -1;
+
+static gint ett_remact = -1;
+
+
+static e_uuid_t uuid_remact = { 0x4d9f4ab8, 0x7d1c, 0x11cf, { 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57 } };
+static guint16 ver_remact = 0;
+
+
+static dcerpc_sub_dissector remact_dissectors[] = {
+ { 0, "RemoteActivation", NULL, NULL },
+ { 0, NULL, NULL, NULL },
+};
+
+
+void
+proto_register_remact (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_opnum,
+ { "Operation", "remact.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_remact
+ };
+ proto_remact = proto_register_protocol ("DCOM Remote Activation", "REMACT", "remact");
+ proto_register_field_array (proto_remact, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_remact (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_remact, ett_remact, &uuid_remact, ver_remact, remact_dissectors, hf_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rep_proc.c b/epan/dissectors/packet-dcerpc-rep_proc.c
new file mode 100644
index 0000000000..350b22ade1
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rep_proc.c
@@ -0,0 +1,93 @@
+/* packet-dcerpc-rep_proc.c
+ *
+ * Routines for dcerpc Replica Server Call dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tgz file/fsint/rep_proc.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_rep_proc = -1;
+static int hf_rep_proc_opnum = -1;
+
+
+static gint ett_rep_proc = -1;
+
+
+static e_uuid_t uuid_rep_proc = { 0x4d37f2dd, 0xed43, 0x0005, { 0x02, 0xc0, 0x37, 0xcf, 0x1e, 0x00, 0x00, 0x00 } };
+static guint16 ver_rep_proc = 4;
+
+
+static dcerpc_sub_dissector rep_proc_dissectors[] = {
+ { 0, "CheckReplicationConfig", NULL, NULL },
+ { 1, "AllCheckReplicationConfig", NULL, NULL },
+ { 2, "KeepFilesAlive", NULL , NULL},
+ { 3, "GetVolChangedFiles", NULL, NULL },
+ { 4, "GetRepStatus", NULL, NULL},
+ { 5, "GetRepServerStatus", NULL, NULL},
+ { 6, "UpdateSelf", NULL, NULL},
+ { 7, "Probe", NULL, NULL},
+ { 8, "GetOneRepStatus", NULL, NULL },
+ { 9, "GetServerInterfaces", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+
+void
+proto_register_rep_proc (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rep_proc_opnum,
+ { "Operation", "rep_proc.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_rep_proc,
+ };
+ proto_rep_proc = proto_register_protocol ("AFS (4.0) Replication Server call declarations", "REP_PROC", "rep_proc");
+ proto_register_field_array (proto_rep_proc, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rep_proc (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rep_proc, ett_rep_proc, &uuid_rep_proc, ver_rep_proc, rep_proc_dissectors, hf_rep_proc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-roverride.c b/epan/dissectors/packet-dcerpc-roverride.c
new file mode 100644
index 0000000000..1423a6376a
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-roverride.c
@@ -0,0 +1,88 @@
+/* packet-dcerpc-roverride.c
+ *
+ * Routines for Remote Override Interface
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/roverride.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_roverride = -1;
+static int hf_roverride_opnum = -1;
+
+
+static gint ett_roverride = -1;
+
+
+static e_uuid_t uuid_roverride = { 0x5d978990, 0x4851, 0x11ca, { 0x99, 0x37, 0x08, 0x00, 0x1e, 0x03, 0x94, 0x48 } };
+static guint16 ver_roverride = 1;
+
+
+static dcerpc_sub_dissector roverride_dissectors[] = {
+ { 0, "roverride_get_login_info", NULL, NULL},
+ { 1, "roverride_check_passwd", NULL, NULL},
+ { 2, "roverride_is_passwd_overridden", NULL, NULL},
+ { 3, "roverride_get_by_unix_num", NULL, NULL},
+ { 4, "roverride_get_group_info", NULL, NULL},
+ { 5, "roverride_check_group_passwd", NULL, NULL},
+ { 6, "roverride_is_grp_pwd_overridden", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_roverride (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_roverride_opnum,
+ { "Operation", "roverride.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_roverride,
+ };
+ proto_roverride = proto_register_protocol ("Remote Override interface", "roverride", "roverride");
+ proto_register_field_array (proto_roverride, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_roverride (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_roverride, ett_roverride, &uuid_roverride, ver_roverride, roverride_dissectors, hf_roverride_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rpriv.c b/epan/dissectors/packet-dcerpc-rpriv.c
new file mode 100644
index 0000000000..50018c7b03
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rpriv.c
@@ -0,0 +1,152 @@
+/* packet-dcerpc-rpriv.c
+ *
+ * Routines for DCERPC Privilege Server operations
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rpriv.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_rpriv = -1;
+static int hf_rpriv_opnum = -1;
+static int hf_rpriv_get_eptgt_rqst_authn_svc = -1;
+static int hf_rpriv_get_eptgt_rqst_authz_svc = -1;
+static int hf_rpriv_get_eptgt_rqst_var1 = -1;
+static int hf_rpriv_get_eptgt_rqst_key_size = -1;
+static int hf_rpriv_get_eptgt_rqst_key_size2 = -1;
+static int hf_rpriv_get_eptgt_rqst_key_t = -1;
+static int hf_rpriv_get_eptgt_rqst_key_t2 = -1;
+
+static gint ett_rpriv = -1;
+
+
+static e_uuid_t uuid_rpriv = { 0xb1e338f8, 0x9533, 0x11c9, { 0xa3, 0x4a, 0x08, 0x00, 0x1e, 0x01, 0x9c, 0x1e } };
+static guint16 ver_rpriv = 1;
+
+
+static int
+rpriv_dissect_get_eptgt_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* [in] handle_t handle,
+ * [in] unsigned32 authn_svc,
+ * [in] unsigned32 authz_svc,
+ * [in] rpriv_pickle_t *ptgt_req,
+ * unsigned32 num_bytes;
+ * [size_is(num_bytes)]
+ * byte bytes[];
+ */
+
+ guint32 authn_svc, authz_svc, key_size, key_size2, var1;
+ const char *key_t = NULL;
+ const char *key_t2 = NULL;
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_rpriv_get_eptgt_rqst_authn_svc, &authn_svc);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_rpriv_get_eptgt_rqst_authz_svc, &authz_svc);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_rpriv_get_eptgt_rqst_var1, &var1);
+ offset += 276;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_rpriv_get_eptgt_rqst_key_size2, &key_size);
+ /* advance to get size of cell, and princ */
+
+ proto_tree_add_string (tree, hf_rpriv_get_eptgt_rqst_key_t, tvb, offset, hf_rpriv_get_eptgt_rqst_key_size, tvb_get_ptr (tvb, offset, key_size));
+ key_t = (const char *)tvb_get_ptr(tvb,offset,key_size);
+ offset += key_size;
+
+ offset += 8;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_rpriv_get_eptgt_rqst_key_size2, &key_size2);
+ proto_tree_add_string (tree, hf_rpriv_get_eptgt_rqst_key_t2, tvb, offset, hf_rpriv_get_eptgt_rqst_key_size2, tvb_get_ptr (tvb, offset, key_size2));
+ key_t2 = (const char *)tvb_get_ptr(tvb,offset,key_size2);
+ offset += key_size2;
+
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " Request for: %s in %s ", key_t2, key_t);
+ }
+
+ return offset;
+
+}
+
+
+static dcerpc_sub_dissector rpriv_dissectors[] = {
+ { 0, "get_ptgt", NULL,NULL},
+ { 1, "become_delegate", NULL, NULL},
+ { 2, "become_impersonator", NULL, NULL},
+ { 3, "get_eptgt", rpriv_dissect_get_eptgt_rqst , NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_rpriv (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rpriv_opnum,
+ { "Operation", "rpriv.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ { &hf_rpriv_get_eptgt_rqst_authn_svc,
+ { "Authn_Svc", "rpriv.get_eptgt_rqst_authn_svc", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_rpriv_get_eptgt_rqst_authz_svc,
+ { "Authz_Svc", "rpriv.get_eptgt_rqst_authz_svc", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_rpriv_get_eptgt_rqst_key_size,
+ { "Key_Size", "rpriv.get_eptgt_rqst_key_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_rpriv_get_eptgt_rqst_var1,
+ { "Var1", "rpriv.get_eptgt_rqst_var1", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_rpriv_get_eptgt_rqst_key_size2,
+ { "Key_Size", "rpriv.get_eptgt_rqst_key_size2", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_rpriv_get_eptgt_rqst_key_t,
+ { "Key_t", "rpriv.get_eptgt_rqst_key_t", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_rpriv_get_eptgt_rqst_key_t2,
+ { "Key_t2", "rpriv.get_eptgt_rqst_key_t2", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_rpriv,
+ };
+ proto_rpriv = proto_register_protocol ("Privilege Server operations", "rpriv", "rpriv");
+ proto_register_field_array (proto_rpriv, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rpriv (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rpriv, ett_rpriv, &uuid_rpriv, ver_rpriv, rpriv_dissectors, hf_rpriv_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_acct.c b/epan/dissectors/packet-dcerpc-rs_acct.c
new file mode 100644
index 0000000000..f5d38ecb7e
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_acct.c
@@ -0,0 +1,168 @@
+/* packet-dcerpc-rs_acct.c
+ *
+ * Routines for DFS/RS_ACCT
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_acct.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_rs_acct = -1;
+static int hf_rs_acct_opnum = -1;
+static int hf_rs_acct_lookup_rqst_var = -1;
+static int hf_rs_acct_lookup_rqst_key_size = -1;
+static int hf_rs_acct_lookup_rqst_key_t = -1;
+static int hf_rs_acct_get_projlist_rqst_var1 = -1;
+static int hf_rs_acct_get_projlist_rqst_key_size = -1;
+static int hf_rs_acct_get_projlist_rqst_key_t = -1;
+
+
+static gint ett_rs_acct = -1;
+
+
+
+static e_uuid_t uuid_rs_acct = { 0x4c878280, 0x2000, 0x0000, { 0x0d, 0x00, 0x02, 0x87, 0x14, 0x00, 0x00, 0x00 } };
+static guint16 ver_rs_acct = 1;
+
+
+static int
+rs_acct_dissect_lookup_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ guint32 key_size;
+ const char *key_t = NULL;
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_acct_lookup_rqst_var, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_acct_lookup_rqst_key_size, &key_size);
+
+ if (key_size){ /* Not able to yet decipher the OTHER versions of this call just yet. */
+ proto_tree_add_string (tree, hf_rs_acct_lookup_rqst_key_t, tvb, offset, hf_rs_acct_lookup_rqst_key_size, tvb_get_ptr (tvb, offset, key_size));
+ key_t = (const char *)tvb_get_ptr(tvb,offset,key_size);
+ offset += key_size;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " Request for: %s ", key_t);
+ }
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO,
+ " Request (other)");
+ }
+ }
+
+ return offset;
+}
+
+
+
+static int
+rs_acct_dissect_get_projlist_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ guint32 key_size;
+ const char *key_t = NULL;
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_acct_get_projlist_rqst_var1, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_acct_get_projlist_rqst_key_size, &key_size);
+
+ proto_tree_add_string (tree, hf_rs_acct_get_projlist_rqst_key_t,
+ tvb, offset, hf_rs_acct_get_projlist_rqst_key_size,
+ tvb_get_ptr (tvb, offset, key_size));
+ key_t = (const char *)tvb_get_ptr(tvb,offset,key_size);
+ offset += key_size;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " Request for: %s", key_t);
+ }
+
+ return offset;
+}
+
+
+static dcerpc_sub_dissector rs_acct_dissectors[] = {
+ { 0, "add", NULL, NULL},
+ { 1, "delete", NULL, NULL},
+ { 2, "rename", NULL, NULL},
+ { 3, "lookup", rs_acct_dissect_lookup_rqst, NULL},
+ { 4, "replace", NULL, NULL},
+ { 5, "get_projlist", rs_acct_dissect_get_projlist_rqst, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_rs_acct (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rs_acct_opnum,
+ { "Operation", "rs_acct.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ { &hf_rs_acct_lookup_rqst_var,
+ { "Var", "rs_acct.lookup_rqst_var", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_rs_acct_lookup_rqst_key_size,
+ { "Key Size", "rs_acct.lookup_rqst_key_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_rs_acct_lookup_rqst_key_t,
+ { "Key", "rs_lookup.get_rqst_key_t", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_rs_acct_get_projlist_rqst_var1,
+ { "Var1", "rs_acct.get_projlist_rqst_var1", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_rs_acct_get_projlist_rqst_key_size,
+ { "Var1", "rs_acct.get_projlist_rqst_key_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_rs_acct_get_projlist_rqst_key_t,
+ { "Var1", "rs_acct.get_projlist_rqst_key_t", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_rs_acct,
+ };
+ proto_rs_acct = proto_register_protocol ("DCE/RPC RS_ACCT", "RS_ACCT", "rs_acct");
+ proto_register_field_array (proto_rs_acct, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+
+
+void
+proto_reg_handoff_rs_acct (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_acct, ett_rs_acct, &uuid_rs_acct, ver_rs_acct, rs_acct_dissectors, hf_rs_acct_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_attr.c b/epan/dissectors/packet-dcerpc-rs_attr.c
new file mode 100644
index 0000000000..7c6f3f3e8e
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_attr.c
@@ -0,0 +1,90 @@
+/* packet-dcerpc-rs_attr.c
+ *
+ * Routines for dcerpc Registry Server Attributes Manipulation Interface
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_attr.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_rs_attr = -1;
+static int hf_rs_attr_opnum = -1;
+
+
+static gint ett_rs_attr = -1;
+
+
+static e_uuid_t uuid_rs_attr = { 0xa71fc1e8, 0x567f, 0x11cb, { 0x98, 0xa0, 0x08, 0x00, 0x1e, 0x04, 0xde, 0x8c } };
+static guint16 ver_rs_attr = 0;
+
+
+static dcerpc_sub_dissector rs_attr_dissectors[] = {
+ { 0, "rs_attr_cursor_init", NULL, NULL},
+ { 1, "rs_attr_lookup_by_id", NULL, NULL},
+ { 2, "rs_attr_lookup_no_expand", NULL, NULL},
+ { 3, "rs_attr_lookup_by_name", NULL, NULL},
+ { 4, "rs_attr_update", NULL, NULL},
+ { 5, "rs_attr_test_and_update", NULL, NULL},
+ { 6, "rs_attr_delete", NULL, NULL},
+ { 7, "rs_attr_get_referral", NULL, NULL},
+ { 8, "rs_attr_get_effective", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_rs_attr (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rs_attr_opnum,
+ { "Operation", "rs_attr.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_attr,
+ };
+ proto_rs_attr = proto_register_protocol ("Registry Server Attributes Manipulation Interface", "RS_ATTR", "rs_attr");
+ proto_register_field_array (proto_rs_attr, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_attr (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_attr, ett_rs_attr, &uuid_rs_attr, ver_rs_attr, rs_attr_dissectors, hf_rs_attr_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_attr_schema.c b/epan/dissectors/packet-dcerpc-rs_attr_schema.c
new file mode 100644
index 0000000000..7f3d768678
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_attr_schema.c
@@ -0,0 +1,95 @@
+/* packet-dcerpc-rs_attr_schema.c
+ *
+ * Routines for rs_attr_schema dissection
+ * Copyright 2004, Jaime Fournier <jaime.fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_attr_schema.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_rs_attr_schema = -1;
+static int hf_rs_attr_schema_opnum = -1;
+
+
+static gint ett_rs_attr_schema = -1;
+static e_uuid_t uuid_rs_attr_schema =
+ { 0xb47c9460, 0x567f, 0x11cb, {0x8c, 0x09, 0x08, 0x00, 0x1e, 0x04, 0xde,
+ 0x8c} };
+static guint16 ver_rs_attr_schema = 0;
+
+
+static dcerpc_sub_dissector rs_attr_schema_dissectors[] = {
+ {0, "create_entry", NULL, NULL},
+ {1, "delete_entry", NULL, NULL},
+ {2, "update_entry", NULL, NULL},
+ {3, "cursor_init", NULL, NULL},
+ {4, "scan", NULL, NULL},
+ {5, "lookup_by_name", NULL, NULL},
+ {6, "lookup_by_id", NULL, NULL},
+ {7, "get_referral", NULL, NULL},
+ {8, "get_acl_mgrs", NULL, NULL},
+ {9, "aclmgr_strings", NULL, NULL},
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_rs_attr_schema (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rs_attr_schema_opnum,
+ {"Operation", "rs_attr_schema.opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operation", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_attr_schema,
+ };
+ proto_rs_attr_schema =
+ proto_register_protocol ("DCE/RPC Registry Server Attributes Schema",
+ "rs_attr_schema", "rs_attr_schema");
+ proto_register_field_array (proto_rs_attr_schema, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_attr_schema (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_attr_schema, ett_rs_attr_schema,
+ &uuid_rs_attr_schema, ver_rs_attr_schema,
+ rs_attr_schema_dissectors, hf_rs_attr_schema_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_bind.c b/epan/dissectors/packet-dcerpc-rs_bind.c
new file mode 100644
index 0000000000..eda49acbeb
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_bind.c
@@ -0,0 +1,89 @@
+/* packet-dcerpc-rs_bind.c
+ *
+ * Routines for DFS/RS_BIND
+ * Copyright 2003, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_bind.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dce122.h"
+
+
+static int proto_rs_bind = -1;
+static int hf_rs_bind_opnum = -1;
+
+static gint ett_rs_bind = -1;
+
+
+static e_uuid_t uuid_rs_bind =
+ { 0xd46113d0, 0xa848, 0x11cb, {0xb8, 0x63, 0x08, 0x00, 0x1e, 0x04, 0x6a,
+ 0xa5}
+
+};
+static guint16 ver_rs_bind = 2;
+
+
+static dcerpc_sub_dissector rs_bind_dissectors[] = {
+ {0, "get_update_site", NULL, NULL},
+ {0, NULL, NULL, NULL},
+
+};
+
+void
+proto_register_rs_bind (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rs_bind_opnum,
+ { "Operation", "rs_bind.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_bind,
+ };
+ proto_rs_bind =
+ proto_register_protocol ("DCE/RPC RS_BIND", "RS_BIND", "rs_bind");
+ proto_register_field_array (proto_rs_bind, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_bind (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_bind, ett_rs_bind, &uuid_rs_bind, ver_rs_bind,
+ rs_bind_dissectors, hf_rs_bind_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_misc.c b/epan/dissectors/packet-dcerpc-rs_misc.c
new file mode 100644
index 0000000000..27fb388910
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_misc.c
@@ -0,0 +1,131 @@
+/* packet-dcerpc-rs_misc.c
+ *
+ * Routines for dcerpc RS-MISC
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_misc.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_rs_misc = -1;
+static int hf_rs_misc_opnum = -1;
+static int hf_rs_misc_login_get_info_rqst_var = -1;
+static int hf_rs_misc_login_get_info_rqst_key_size = -1;
+static int hf_rs_misc_login_get_info_rqst_key_t = -1;
+
+
+static gint ett_rs_misc = -1;
+
+
+static e_uuid_t uuid_rs_misc = { 0x4c878280, 0x5000, 0x0000, { 0x0d, 0x00, 0x02, 0x87, 0x14, 0x00, 0x00, 0x00 } };
+static guint16 ver_rs_misc = 1;
+
+
+static int
+rs_misc_dissect_login_get_info_rqst (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+
+ guint32 key_size;
+ const char *key_t = NULL;
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_misc_login_get_info_rqst_var, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_misc_login_get_info_rqst_key_size, &key_size);
+
+ if (key_size){ /* Not able to yet decipher the OTHER versions of this call just yet. */
+
+ proto_tree_add_string (tree, hf_rs_misc_login_get_info_rqst_key_t, tvb, offset, hf_rs_misc_login_get_info_rqst_key_size, tvb_get_ptr (tvb, offset, key_size));
+ key_t = (const char *)tvb_get_ptr(tvb,offset,key_size);
+ offset += key_size;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "rs_login_get_info Request for: %s ", key_t);
+ }
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO,
+ "rs_login_get_info Request (other)");
+ }
+ }
+
+ return offset;
+}
+
+
+static dcerpc_sub_dissector rs_misc_dissectors[] = {
+ { 0, "login_get_info", rs_misc_dissect_login_get_info_rqst, NULL},
+ { 1, "wait_until_consistent", NULL, NULL},
+ { 2, "check_consistency", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_rs_misc (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rs_misc_opnum,
+ { "Operation", "rs_misc.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ { &hf_rs_misc_login_get_info_rqst_var,
+ { "Var", "rs_misc.login_get_info_rqst_var", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_rs_misc_login_get_info_rqst_key_size,
+ { "Key Size", "rs_misc.login_get_info_rqst_key_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_rs_misc_login_get_info_rqst_key_t,
+ { "Key", "rs.misc_login_get_info_rqst_key_t", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_rs_misc,
+ };
+ proto_rs_misc = proto_register_protocol ("DCE/RPC RS_MISC", "rs_misc", "rs_misc");
+ proto_register_field_array (proto_rs_misc, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_misc (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_misc, ett_rs_misc, &uuid_rs_misc, ver_rs_misc, rs_misc_dissectors, hf_rs_misc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_pgo.c b/epan/dissectors/packet-dcerpc-rs_pgo.c
new file mode 100644
index 0000000000..8357184eec
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_pgo.c
@@ -0,0 +1,1900 @@
+/* packet-dcerpc-rs_pgo.c
+ *
+ * Routines for dcerpc Afs4Int dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_pgo.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dce122.h"
+/*
+delete
+dissect_rgy_acct_user_flags_t
+*/
+
+static int proto_rs_pgo = -1;
+static int hf_rs_pgo_opnum = -1;
+static int hf_rgy_name_domain = -1;
+static int hf_rgy_sec_rgy_name_max_len = -1;
+static int hf_rgy_sec_rgy_name_t_size = -1;
+static int hf_rgy_sec_rgy_name_t = -1;
+static int hf_rgy_get_rqst_name_domain = -1;
+static int hf_rgy_get_rqst_var = -1;
+static int hf_rgy_get_rqst_var2 = -1;
+static int hf_rgy_get_rqst_key_size = -1;
+static int hf_rgy_get_rqst_key_t = -1;
+static int hf_rgy_key_transfer_rqst_var1 = -1;
+static int hf_rgy_key_transfer_rqst_var2 = -1;
+static int hf_rgy_key_transfer_rqst_var3 = -1;
+static int hf_rgy_is_member_rqst_var1 = -1;
+static int hf_rgy_is_member_rqst_var2 = -1;
+static int hf_rgy_is_member_rqst_var3 = -1;
+static int hf_rgy_is_member_rqst_var4 = -1;
+static int hf_rgy_is_member_rqst_key1 = -1;
+static int hf_rgy_is_member_rqst_key2 = -1;
+static int hf_rgy_is_member_rqst_key1_size = -1;
+static int hf_rgy_is_member_rqst_key2_size = -1;
+static int hf_rs_var1 = -1;
+static int hf_rs_pgo_query_result_t = -1;
+static int hf_sec_rgy_pgo_item_t = -1;
+static int hf_rs_pgo_id_key_t = -1;
+static int hf_rs_pgo_query_t = -1;
+static int hf_rs_pgo_query_key_t = -1;
+static int hf_error_status_t = -1;
+static int hf_sec_rgy_pgo_flags_t = -1;
+static int hf_sec_passwd_version_t = -1;
+static int hf_rgy_acct_user_flags_t = -1;
+static int hf_rs_sec_rgy_pgo_item_t_quota = -1;
+static int hf_rs_sec_rgy_pgo_item_t_unix_num = -1;
+static int hf_rs_timeval = -1;
+static int hf_rs_uuid1 = -1;
+static int hf_sec_attr_component_name_t_handle = -1;
+static int hf_sec_attr_component_name_t_valid = -1;
+static int hf_sec_passwd_type_t = -1;
+static int hf_sec_rgy_acct_admin_flags = -1;
+static int hf_sec_rgy_acct_auth_flags_t = -1;
+static int hf_sec_rgy_acct_key_t = -1;
+static int hf_sec_rgy_domain_t = -1;
+static int hf_sec_rgy_name_t_principalName_string = -1;
+static int hf_sec_rgy_name_t_size = -1;
+static int hf_sec_rgy_pname_t_principalName_string = -1;
+static int hf_sec_rgy_unix_sid_t_group = -1;
+static int hf_sec_rgy_unix_sid_t_org = -1;
+static int hf_sec_rgy_unix_sid_t_person = -1;
+static int hf_sec_timeval_sec_t = -1;
+static int hf_rs_pgo_unix_num_key_t = -1;
+
+static gint ett_rs_cache_data_t = -1;
+static gint ett_sec_rgy_domain_t = -1;
+static gint ett_rgy_acct_user_flags_t = -1;
+static gint ett_sec_attr_component_name_t = -1;
+static gint ett_sec_passwd_type_t = -1;
+static gint ett_sec_rgy_acct_admin_flags_t = -1;
+static gint ett_sec_rgy_acct_admin_t = -1;
+static gint ett_sec_rgy_acct_auth_flags_t = -1;
+static gint ett_sec_rgy_acct_key_t = -1;
+static gint ett_sec_rgy_acct_user_t = -1;
+static gint ett_sec_rgy_cursor_t = -1;
+static gint ett_sec_rgy_foreign_id_t = -1;
+static gint ett_sec_rgy_login_name_t = -1;
+static gint ett_sec_rgy_name_t = -1;
+static gint ett_sec_rgy_pgo_item_t = -1;
+static gint ett_sec_rgy_pname_t = -1;
+static gint ett_sec_rgy_sid_t = -1;
+static gint ett_sec_rgy_unix_passwd_buf_t = -1;
+static gint ett_sec_rgy_unix_sid_t = -1;
+static gint ett_sec_timeval_sec_t = -1;
+static gint ett_sec_rgy_pgo_flags_t = -1;
+static gint ett_error_status_t = -1;
+static gint ett_rs_pgo_query_t = -1;
+static gint ett_rs_pgo_query_key_t = -1;
+static gint ett_rs_pgo_id_key_t = -1;
+static gint ett_rs_pgo_unix_num_key_t = -1;
+static gint ett_rs_pgo_query_result_t = -1;
+static gint ett_rs_pgo_result_t = -1;
+static guint8 *st_str;
+
+
+#define sec_rgy_acct_admin_valid 0x1
+#define sec_rgy_acct_admin_audit 0x2
+#define sec_rgy_acct_admin_server 0x4
+#define sec_rgy_acct_admin_client 0x8
+#define sec_rgy_acct_admin_flags_none 0
+#define sec_rgy_acct_auth_post_dated 0x1
+#define sec_rgy_acct_auth_forwardable 0x2
+#define sec_rgy_acct_auth_tgt 0x4
+#define sec_rgy_acct_auth_renewable 0x8
+#define sec_rgy_acct_auth_proxiable 0x10
+#define sec_rgy_acct_auth_dup_skey 0x20
+#define sec_rgy_acct_auth_user_to_user 0x40
+#define sec_rgy_acct_auth_flags_none 0
+#define sec_rgy_acct_user_passwd_valid 0x1
+#define sec_rgy_acct_user_flags_none 0
+#define rs_acct_part_user 0x1
+#define rs_acct_part_admin 0x2
+#define rs_acct_part_passwd 0x4
+#define rs_acct_part_unused 0x8
+#define rs_acct_part_login_name 0x10
+#define sec_rgy_pgo_is_an_alias 0x1
+#define sec_rgy_pgo_is_required 0x2
+#define sec_rgy_pgo_projlist_ok 0x4
+#define sec_rgy_pgo_flags_none 0
+#define sec_rgy_acct_user_passwd_valid 0x1
+#define sec_rgy_acct_user_flags_none 0
+
+static gint ett_rs_pgo = -1;
+
+static e_uuid_t uuid_rs_pgo =
+ { 0x4c878280, 0x3000, 0x0000, {0x0d, 0x00, 0x02, 0x87, 0x14, 0x00, 0x00,
+ 0x00}
+};
+static guint16 ver_rs_pgo = 1;
+
+
+static int
+dissect_error_status_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 st;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "error_status_t");
+ tree = proto_item_add_subtree (item, ett_error_status_t);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_error_status_t,
+ &st);
+ st_str = val_to_str (st, dce_error_vals, "%u");
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " st:%s ", st_str);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_sec_rgy_pname_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+#define sec_rgy_pname_t_size 257
+/*
+dissect sec_rgy_pname const signed32 sec_rgy_pname_t_size = 257; * Include final '\0' *
+ typedef [string] char sec_rgy_pname_t[sec_rgy_pname_t_size];
+*/
+ guint32 string_size;
+ const guint8 *namestring;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1, "sec_rgy_pname_t");
+ tree = proto_item_add_subtree (item, ett_sec_rgy_pname_t);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ sec_rgy_pname_t_size, &string_size);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " String_size:%u", string_size);
+ if (string_size < sec_rgy_pname_t_size)
+ {
+/* proto_tree_add_string(tree, id, tvb, start, length, value_ptr); */
+
+ proto_tree_add_string (tree, hf_sec_rgy_pname_t_principalName_string,
+ tvb, offset, string_size, tvb_get_ptr (tvb,
+ offset,
+ string_size));
+ if (string_size > 1)
+ {
+ namestring = tvb_get_ptr (tvb, offset, string_size);
+ offset += string_size;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Principal:%s",
+ namestring);
+ }
+ }
+ else
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " :FIXME!: Invalid string length of %u",
+ string_size);
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_sec_rgy_pgo_flags_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+/*
+
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+ guint32 flags;
+
+/*
+ typedef bitset sec_rgy_pgo_flags_t;
+*/
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "sec_rgy_pgo_flags_t ");
+ tree = proto_item_add_subtree (item, ett_sec_rgy_pgo_flags_t);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_sec_rgy_pgo_flags_t, &flags);
+
+/*
+ *
+ * s e c _ r g y _ p g o _ f l a g s _ t
+ *
+
+ * pgo item is an alias *
+ const unsigned32 sec_rgy_pgo_is_an_alias = 0x1;
+
+ * pgo item is required - cannot be deleted *
+ const unsigned32 sec_rgy_pgo_is_required = 0x2;
+
+ *
+ * projlist_ok: on person items indicates person can have a concurrent
+ * group set on group items indicates this group can appear on a
+ * concurrent group set. On org items this flag is undefined.
+ *
+ const unsigned32 sec_rgy_pgo_projlist_ok = 0x4;
+
+ *
+ * bits 4-32 unused
+ *
+ const unsigned32 sec_rgy_pgo_flags_none = 0;
+*/
+#define sec_rgy_pgo_is_an_alias 0x1
+#define sec_rgy_pgo_is_required 0x2
+#define sec_rgy_pgo_projlist_ok 0x4
+#define sec_rgy_pgo_flags_none 0
+
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, " PgoFlags=");
+ if ((flags & sec_rgy_pgo_is_an_alias) == sec_rgy_pgo_is_an_alias)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":IS_AN_ALIAS");
+ }
+ if ((flags & sec_rgy_pgo_is_required) == sec_rgy_pgo_is_required)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":IS_REQUIRED");
+ }
+ if ((flags & sec_rgy_pgo_projlist_ok) == sec_rgy_pgo_projlist_ok)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":PROJLIST_OK");
+ }
+ if ((flags & sec_rgy_acct_admin_client) == sec_rgy_acct_admin_client)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":NONE");
+ }
+ if ((flags & sec_rgy_pgo_flags_none) == sec_rgy_pgo_flags_none)
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, ":NONE");
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+
+
+static int
+dissect_rs_cache_data_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+/*
+ typedef struct {
+ uuid_t site_id;
+ sec_timeval_sec_t person_dtm;
+ sec_timeval_sec_t group_dtm;
+ sec_timeval_sec_t org_dtm;
+ } rs_cache_data_t;
+*/
+
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+ guint32 person_dtm, group_dtm, org_dtm;
+ e_uuid_t uuid1;
+
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1, "rs_cache_data_t");
+ tree = proto_item_add_subtree (item, ett_rs_cache_data_t);
+ }
+
+
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_rs_uuid1, &uuid1);
+ offset =
+ dissect_dcerpc_time_t (tvb, offset, pinfo, tree, drep, hf_rs_timeval,
+ &person_dtm);
+ offset =
+ dissect_dcerpc_time_t (tvb, offset, pinfo, tree, drep, hf_rs_timeval,
+ &group_dtm);
+ offset =
+ dissect_dcerpc_time_t (tvb, offset, pinfo, tree, drep, hf_rs_timeval,
+ &org_dtm);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " siteid %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x person_dtm:%u group_dtm:%u org_dtm:%u",
+ uuid1.Data1, uuid1.Data2, uuid1.Data3, uuid1.Data4[0],
+ uuid1.Data4[1], uuid1.Data4[2], uuid1.Data4[3],
+ uuid1.Data4[4], uuid1.Data4[5], uuid1.Data4[6],
+ uuid1.Data4[7], person_dtm, group_dtm, org_dtm);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+
+static int
+dissect_sec_rgy_name_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+#define sec_rgy_name_t_size 1025
+/* typedef [string] char sec_rgy_name_t[sec_rgy_name_t_size]; */
+ guint32 string_size;
+ const guint8 *namestring;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1, "sec_rgy_name_t");
+ tree = proto_item_add_subtree (item, ett_sec_rgy_name_t);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_sec_rgy_name_t_size, &string_size);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " String_size:%u", string_size);
+ if (string_size < sec_rgy_name_t_size)
+ {
+/* proto_tree_add_string(tree, id, tvb, start, length, value_ptr); */
+
+ proto_tree_add_string (tree, hf_sec_rgy_name_t_principalName_string,
+ tvb, offset, string_size, tvb_get_ptr (tvb,
+ offset,
+ string_size));
+ if (string_size > 1)
+ {
+ namestring = tvb_get_ptr (tvb, offset, string_size);
+ offset += string_size;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Principal:%s",
+ namestring);
+ }
+ }
+ else
+ {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " :FIXME!: Invalid string length of %u",
+ string_size);
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_sec_rgy_domain_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+/*
+ typedef signed32 sec_rgy_domain_t;
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+ guint32 domain_t;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1, "sec_rgy_domain_t");
+ tree = proto_item_add_subtree (item, ett_sec_rgy_domain_t);
+ }
+
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_sec_rgy_domain_t,
+ &domain_t);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " sec_rgy_domain_t:%u",
+ domain_t);
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_sec_rgy_pgo_item_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+/*
+ typedef struct {
+ uuid_t id;
+ signed32 unix_num;
+ signed32 quota;
+ sec_rgy_pgo_flags_t flags;
+ sec_rgy_pname_t fullname;
+ } sec_rgy_pgo_item_t;
+
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+ e_uuid_t id;
+ guint32 unix_num, quota;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1,
+ " sec_rgy_pgo_item_t ");
+ tree = proto_item_add_subtree (item, ett_sec_rgy_pgo_item_t);
+ }
+
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_rs_uuid1, &id);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_sec_rgy_pgo_item_t_unix_num, &unix_num);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_sec_rgy_pgo_item_t_quota, &quota);
+ offset = dissect_sec_rgy_pgo_flags_t (tvb, offset, pinfo, tree, drep);
+ offset += 4; /* XXX */
+ offset = dissect_sec_rgy_pname_t (tvb, offset, pinfo, tree, drep);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " sec_rgy_pgo_item_t - id %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x unix_num:%u quota:%u",
+ id.Data1, id.Data2, id.Data3, id.Data4[0],
+ id.Data4[1], id.Data4[2], id.Data4[3],
+ id.Data4[4], id.Data4[5], id.Data4[6],
+ id.Data4[7], unix_num, quota);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_sec_rgy_cursor_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+/*
+ * Database cursor for iterative operations
+ *
+ typedef struct {
+ uuid_t source;
+ signed32 handle;
+ boolean32 valid;
+ } sec_rgy_cursor_t;
+
+
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+ e_uuid_t source;
+ guint32 handle, valid;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1,
+ " sec_rgy_cursor_t ");
+ tree = proto_item_add_subtree (item, ett_sec_rgy_cursor_t);
+ }
+
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_rs_uuid1, &source);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_sec_rgy_pgo_item_t_unix_num, &handle);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_sec_rgy_pgo_item_t_quota, &valid);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " sec_rgy_cursor_t - source %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x handle:%u valid:%u",
+ source.Data1, source.Data2, source.Data3,
+ source.Data4[0], source.Data4[1], source.Data4[2],
+ source.Data4[3], source.Data4[4], source.Data4[5],
+ source.Data4[6], source.Data4[7], handle, valid);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+static int
+dissect_rs_pgo_query_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+ typedef enum
+ {
+ rs_pgo_query_name,
+ rs_pgo_query_id,
+ rs_pgo_query_unix_num,
+ rs_pgo_query_next,
+ rs_pgo_query_none
+ } rs_pgo_query_t;
+
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+ guint8 query_t;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1, "rs_pgo_query_t ");
+ tree = proto_item_add_subtree (item, ett_rs_pgo_query_t);
+ }
+ offset =
+ dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep, hf_rs_pgo_query_t,
+ &query_t);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, " rs_pgo_query_t:");
+
+ switch (query_t)
+ {
+ case rs_pgo_query_name:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "NAME");
+ break;
+ case rs_pgo_query_id:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "ID");
+ break;
+ case rs_pgo_query_unix_num:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "UNIX_NUM");
+ break;
+ case rs_pgo_query_next:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "NEXT");
+ break;
+ case rs_pgo_query_none:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "NONE");
+ break;
+ default:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " unknown:%u", query_t);
+ break;
+ ;
+ }
+
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+static int
+dissect_rs_pgo_id_key_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+/*
+ typedef struct {
+ uuid_t id;
+ sec_rgy_name_t scope;
+ } rs_pgo_id_key_t;
+
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+ e_uuid_t id;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "rs_pgo_id_key_t ");
+ tree = proto_item_add_subtree (item, ett_rs_pgo_id_key_t);
+ }
+
+ offset =
+ dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, hf_rs_uuid1, &id);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " rs_pgo_id_key_t - id %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ id.Data1, id.Data2, id.Data3, id.Data4[0],
+ id.Data4[1], id.Data4[2], id.Data4[3],
+ id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_rs_pgo_result_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+/*
+ typedef struct {
+ sec_rgy_name_t name;
+ sec_rgy_pgo_item_t item;
+ } rs_pgo_result_t;
+
+
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "rs_pgo_result_t ");
+ tree = proto_item_add_subtree (item, ett_rs_pgo_result_t);
+ }
+
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_pgo_item_t (tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+
+static int
+dissect_rs_pgo_unix_num_key_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+/*
+ typedef struct {
+ signed32 unix_num;
+ sec_rgy_name_t scope;
+ } rs_pgo_unix_num_key_t;
+
+
+r
+
+*/
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+ guint32 rs_pgo_unix_num_key_t;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1,
+ " rs_pgo_unix_num_key_t ");
+ tree = proto_item_add_subtree (item, ett_rs_pgo_unix_num_key_t);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_pgo_unix_num_key_t, &rs_pgo_unix_num_key_t);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " rs_pgo_unix_num_key_t:%u", rs_pgo_unix_num_key_t);
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_rs_pgo_query_key_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+
+ typedef enum
+ {
+ rs_pgo_query_name,
+ rs_pgo_query_id,
+ rs_pgo_query_unix_num,
+ rs_pgo_query_next,
+ rs_pgo_query_none
+ } rs_pgo_query_t;
+/*
+ typedef union switch (rs_pgo_query_t query) tagged_union {
+ case rs_pgo_query_name:
+ sec_rgy_name_t name;
+
+ case rs_pgo_query_id:
+ rs_pgo_id_key_t id_key;
+
+ case rs_pgo_query_unix_num:
+ rs_pgo_unix_num_key_t unix_num_key;
+
+ case rs_pgo_query_next:
+ sec_rgy_name_t scope;
+
+ default:
+ ; * empty branch of union *
+
+ } rs_pgo_query_key_t;
+*/
+
+
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ dcerpc_info *di;
+ guint16 query_t;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+ if (parent_tree)
+ {
+ item =
+ proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "rs_pgo_query_key_t ");
+ tree = proto_item_add_subtree (item, ett_rs_pgo_query_key_t);
+ }
+ offset =
+ dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep, hf_rs_pgo_query_key_t,
+ &query_t);
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, " rs_pgo_query_key_t:");
+ offset += 4;
+ switch (query_t)
+ {
+ case rs_pgo_query_name:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "NAME");
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ break;
+ case rs_pgo_query_id:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "ID");
+ offset = dissect_rs_pgo_id_key_t (tvb, offset, pinfo, tree, drep);
+ break;
+ case rs_pgo_query_unix_num:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "UNIX_NUM");
+ offset = dissect_rs_pgo_unix_num_key_t (tvb, offset, pinfo, tree, drep);
+ break;
+ case rs_pgo_query_next:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "NEXT");
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ break;
+ case rs_pgo_query_none:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO, "NONE");
+ break;
+
+ default:
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " unknown:%u", query_t);
+ ;
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+static int
+dissect_rs_pgo_query_result_t (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * parent_tree,
+ guint8 * drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint32 st;
+ dcerpc_info *di;
+ guint8 *status;
+#define error_status_ok 0
+
+ /*
+ typedef union switch (signed32 status) tagged_union {
+ case error_status_ok:
+ rs_pgo_result_t result;
+
+ default:
+ ; * empty branch of union *
+
+ } rs_pgo_query_result_t;
+ */
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ if (parent_tree)
+ {
+ item = proto_tree_add_text (parent_tree, tvb, offset, -1,
+ "rs_pgo_query_result_t");
+ tree = proto_item_add_subtree (item, ett_rs_pgo_query_result_t);
+ }
+
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_rs_pgo_query_result_t, &st);
+ status = val_to_str (st, dce_error_vals, "%u");
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " status:%s ", status);
+
+ offset += 4; /* XXX */
+
+ switch (st)
+ {
+ case error_status_ok:
+ offset = dissect_rs_pgo_result_t (tvb, offset, pinfo, tree, drep);
+ break;
+ default:
+ ;
+
+ }
+
+ proto_item_set_len (item, offset - old_offset);
+ return offset;
+}
+
+
+
+static int
+rs_pgo_dissect_add_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] sec_rgy_domain_t name_domain,
+ [in] sec_rgy_name_t pgo_name,
+ [in] sec_rgy_pgo_item_t *pgo_item,
+*/
+
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset += 4;
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_sec_rgy_pgo_item_t, NDR_POINTER_REF,
+ "sec_rgy_pgo_item_t: ", -1);
+
+ return offset;
+}
+static int
+rs_pgo_dissect_add_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+ guint32 buff_remain;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] rs_cache_data_t *cache_info,
+ [out] error_status_t *status
+*/
+
+ buff_remain = tvb_length_remaining(tvb, offset);
+
+/* found several add_member responses that had 8 bytes of data. first was 4 0's and last was 3 zeros and a 1 */
+if (buff_remain > 8) {
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_cache_data_t, NDR_POINTER_REF,
+ "cache_info: ", -1);
+}
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_error_status_t, NDR_POINTER_REF, "status: ",
+ -1);
+ return offset;
+}
+
+static int
+rs_pgo_dissect_delete_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] sec_rgy_domain_t name_domain,
+ [in] sec_rgy_name_t pgo_name,
+*/
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+rs_pgo_dissect_delete_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+ guint32 buff_remain;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] rs_cache_data_t *cache_info,
+ [out] error_status_t *status
+*/
+ buff_remain = tvb_length_remaining(tvb, offset);
+
+/* found several add_member responses that had 8 bytes of data. first was 4 0's and last was 3 zeros and a 1 */
+
+ if (buff_remain > 8) {
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_cache_data_t, NDR_POINTER_REF,
+ "cache_info:", -1);
+ }
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_error_status_t, NDR_POINTER_REF, "status:",
+ -1);
+
+ return offset;
+}
+
+static int
+rs_pgo_dissect_replace_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] sec_rgy_domain_t name_domain,
+ [in] sec_rgy_name_t pgo_name,
+ [in] sec_rgy_pgo_item_t *pgo_item,
+*/
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_sec_rgy_pgo_item_t, NDR_POINTER_REF,
+ "pgo_item:", -1);
+
+ return offset;
+}
+
+static int
+rs_pgo_dissect_replace_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] rs_cache_data_t *cache_info,
+ [out] error_status_t *status
+
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_cache_data_t, NDR_POINTER_REF,
+ "cache_info:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_error_status_t, NDR_POINTER_REF, "status:",
+ -1);
+
+ return offset;
+}
+
+
+static int
+rs_pgo_dissect_add_member_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+
+
+/*
+ [in] sec_rgy_domain_t name_domain,
+ [in] sec_rgy_name_t go_name,
+ [in] sec_rgy_name_t person_name,
+*/
+
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+
+
+ return offset;
+
+}
+static int
+rs_pgo_dissect_rename_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] sec_rgy_domain_t name_domain,
+ [in] sec_rgy_name_t old_name,
+ [in] sec_rgy_name_t new_name,
+*/
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+
+
+ return offset;
+}
+
+static int
+rs_pgo_dissect_rename_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] rs_cache_data_t *cache_info,
+ [out] error_status_t *status
+*/
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_cache_data_t, NDR_POINTER_REF,
+ "cache_info:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_error_status_t, NDR_POINTER_REF, "status:",
+ -1);
+
+ return offset;
+}
+
+
+static int
+rs_pgo_dissect_add_member_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+ guint32 buff_remain;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] rs_cache_data_t *cache_info,
+ [out] error_status_t *status
+*/
+
+ buff_remain = tvb_length_remaining(tvb, offset);
+
+/* found several add responses that had 8 bytes of data. first was 4 0's and last was 3 zeros and a 1 */
+if (buff_remain > 8) {
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_cache_data_t, NDR_POINTER_REF,
+ "cache_info:", -1);
+}
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_error_status_t, NDR_POINTER_REF, "status:",
+ -1);
+
+
+ return offset;
+}
+
+static int
+rs_pgo_dissect_delete_member_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ void rs_pgo_delete_member (
+ [in] sec_rgy_domain_t name_domain,
+ [in] sec_rgy_name_t go_name,
+ [in] sec_rgy_name_t person_name,
+ );
+*/
+
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+
+ return offset;
+
+}
+
+
+static int
+rs_pgo_dissect_get_members_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+
+ guint32 max_members;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] sec_rgy_domain_t name_domain,
+ [in] sec_rgy_name_t go_name,
+ [in, out] sec_rgy_cursor_t *member_cursor,
+ [in] signed32 max_members,
+*/
+
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset += 4;
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_sec_rgy_cursor_t, NDR_POINTER_REF,
+ "member_cursor:", -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_rs_var1,
+ &max_members);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " :max_members:%u", max_members);
+
+ return offset;
+}
+
+static int
+rs_pgo_dissect_key_transfer_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] sec_rgy_domain_t name_domain,
+ [in] rs_pgo_query_t requested_result_type,
+ [in, out] rs_pgo_query_key_t *key,
+*/
+
+ offset += 4;
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_rs_pgo_query_t (tvb, offset, pinfo, tree, drep);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_pgo_query_key_t, NDR_POINTER_REF, "key:",
+ -1);
+
+ return offset;
+}
+
+static int
+rs_pgo_dissect_key_transfer_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in, out] rs_pgo_query_key_t *key,
+ [out] rs_cache_data_t *cache_info,
+ [out] error_status_t *status
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_pgo_query_key_t, NDR_POINTER_REF, "key:",
+ -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_cache_data_t, NDR_POINTER_REF,
+ "cache_info:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_error_status_t, NDR_POINTER_REF, "status:",
+ -1);
+
+ return offset;
+}
+
+
+static int
+rs_pgo_dissect_is_member_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] rs_cache_data_t *cache_info,
+ [out] error_status_t *status
+*/
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_cache_data_t, NDR_POINTER_REF,
+ "cache_info:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_error_status_t, NDR_POINTER_REF, "status:",
+ -1);
+
+ return offset;
+}
+
+static int
+rs_pgo_dissect_is_member_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+/*
+ [in] sec_rgy_domain_t name_domain,
+ [in] sec_rgy_name_t go_name,
+ [in] sec_rgy_name_t person_name,
+*/
+
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+ offset += 4;
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+ offset += 4;
+ offset = dissect_sec_rgy_name_t (tvb, offset, pinfo, tree, drep);
+
+
+ return offset;
+
+}
+
+
+static int
+rs_pgo_dissect_get_rqst (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+ dcerpc_info *di;
+ guint32 allow_aliases;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in] sec_rgy_domain_t name_domain,
+ [in] rs_pgo_query_key_t *key,
+ [in] boolean32 allow_aliases,
+ [in, out] sec_rgy_cursor_t *item_cursor,
+*/
+
+ offset = dissect_sec_rgy_domain_t (tvb, offset, pinfo, tree, drep);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_pgo_query_key_t, NDR_POINTER_REF, "key:",
+ -1);
+ offset =
+ dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, hf_rs_var1,
+ &allow_aliases);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " :allow_aliases:%u",
+ allow_aliases);
+
+
+ offset += 4; /* XXX */
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_sec_rgy_cursor_t, NDR_POINTER_REF,
+ "item_cursor:", -1);
+ return offset;
+
+}
+
+static int
+rs_pgo_dissect_get_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [in, out] sec_rgy_cursor_t *item_cursor,
+ [out] rs_cache_data_t *cache_info,
+ [out] rs_pgo_query_result_t *result
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_sec_rgy_cursor_t, NDR_POINTER_REF,
+ "item_cursor:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_cache_data_t, NDR_POINTER_REF,
+ "cache_info:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_pgo_query_result_t, NDR_POINTER_REF,
+ "result:", -1);
+
+ return offset;
+
+}
+
+static int
+rs_pgo_dissect_delete_member_resp (tvbuff_t * tvb, int offset,
+ packet_info * pinfo, proto_tree * tree,
+ guint8 * drep)
+{
+
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+ if (di->conformant_run)
+ {
+ return offset;
+ }
+
+/*
+ [out] rs_cache_data_t *cache_info,
+ [out] error_status_t *status
+
+*/
+
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_rs_cache_data_t, NDR_POINTER_REF,
+ "cache_info:", -1);
+ offset =
+ dissect_ndr_pointer (tvb, offset, pinfo, tree, drep,
+ dissect_error_status_t, NDR_POINTER_REF, "status:",
+ -1);
+
+ return offset;
+
+}
+
+
+static dcerpc_sub_dissector rs_pgo_dissectors[] = {
+ {0, "add", rs_pgo_dissect_add_rqst, rs_pgo_dissect_add_resp},
+ {1, "delete", rs_pgo_dissect_delete_rqst, rs_pgo_dissect_delete_resp},
+ {2, "replace", rs_pgo_dissect_replace_rqst, rs_pgo_dissect_replace_resp},
+ {3, "rename", rs_pgo_dissect_rename_rqst, rs_pgo_dissect_rename_resp},
+ {4, "get", rs_pgo_dissect_get_rqst, rs_pgo_dissect_get_resp},
+ {5, "key_transfer", rs_pgo_dissect_key_transfer_rqst,
+ rs_pgo_dissect_key_transfer_resp},
+ {6, "add_member", rs_pgo_dissect_add_member_rqst,
+ rs_pgo_dissect_add_member_resp},
+ {7, "delete_member", rs_pgo_dissect_delete_member_rqst,
+ rs_pgo_dissect_delete_member_resp},
+ {8, "is_member", rs_pgo_dissect_is_member_rqst,
+ rs_pgo_dissect_is_member_resp},
+ {9, "get_members", rs_pgo_dissect_get_members_rqst, NULL},
+ {0, NULL, NULL, NULL},
+};
+
+
+void
+proto_register_rs_pgo (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rs_pgo_opnum,
+ {"Operation", "rs_pgo.opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operation", HFILL}},
+ {&hf_error_status_t,
+ {"hf_error_status_t", "hf_error_status_t", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_rgy_acct_user_flags_t,
+ {"hf_rgy_acct_user_flags_t ", "hf_rgy_acct_user_flags_t", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_get_rqst_key_size,
+ {"hf_rgy_get_rqst_key_size ", "hf_rgy_get_rqst_key_size", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_get_rqst_key_t,
+ {"hf_rgy_get_rqst_key_t ", "hf_rgy_get_rqst_key_t", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_rgy_get_rqst_name_domain,
+ {"hf_rgy_get_rqst_name_domain ", "hf_rgy_get_rqst_name_domain",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_get_rqst_var,
+ {"hf_rgy_get_rqst_var ", "hf_rgy_get_rqst_var", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_rgy_get_rqst_var2,
+ {"hf_rgy_get_rqst_var2 ", "hf_rgy_get_rqst_var2", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_rgy_is_member_rqst_key1,
+ {"hf_rgy_is_member_rqst_key1 ", "hf_rgy_is_member_rqst_key1", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_is_member_rqst_key1_size,
+ {"hf_rgy_is_member_rqst_key1_size ", "hf_rgy_is_member_rqst_key1_size",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_is_member_rqst_key2,
+ {"hf_rgy_is_member_rqst_key2 ", "hf_rgy_is_member_rqst_key2", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_is_member_rqst_key2_size,
+ {"hf_rgy_is_member_rqst_key2_size ", "hf_rgy_is_member_rqst_key2_size",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_is_member_rqst_var1,
+ {"hf_rgy_is_member_rqst_var1 ", "hf_rgy_is_member_rqst_var1", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_is_member_rqst_var2,
+ {"hf_rgy_is_member_rqst_var2 ", "hf_rgy_is_member_rqst_var2", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_is_member_rqst_var3,
+ {"hf_rgy_is_member_rqst_var3 ", "hf_rgy_is_member_rqst_var3", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_is_member_rqst_var4,
+ {"hf_rgy_is_member_rqst_var4 ", "hf_rgy_is_member_rqst_var4", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_key_transfer_rqst_var1,
+ {"hf_rgy_key_transfer_rqst_var1 ", "hf_rgy_key_transfer_rqst_var1",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_key_transfer_rqst_var2,
+ {"hf_rgy_key_transfer_rqst_var2 ", "hf_rgy_key_transfer_rqst_var2",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_key_transfer_rqst_var3,
+ {"hf_rgy_key_transfer_rqst_var3 ", "hf_rgy_key_transfer_rqst_var3",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_name_domain,
+ {"hf_rgy_name_domain ", "hf_rgy_name_domain", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_rgy_sec_rgy_name_max_len,
+ {"hf_rgy_sec_rgy_name_max_len ", "hf_rgy_sec_rgy_name_max_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rgy_sec_rgy_name_t,
+ {"hf_rgy_sec_rgy_name_t ", "hf_rgy_sec_rgy_name_t", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_rgy_sec_rgy_name_t_size,
+ {"hf_rgy_sec_rgy_name_t_size ", "hf_rgy_sec_rgy_name_t_size", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rs_pgo_id_key_t,
+ {"hf_rs_pgo_id_key_t ", "hf_rs_pgo_id_key_t", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_rs_pgo_query_key_t,
+ {"hf_rs_pgo_query_key_t ", "hf_rs_pgo_query_key_t", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_rs_pgo_query_result_t,
+ {"hf_rs_pgo_query_result_t ", "hf_rs_pgo_query_result_t", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rs_pgo_query_t,
+ {"hf_rs_pgo_query_t ", "hf_rs_pgo_query_t", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_rs_sec_rgy_pgo_item_t_quota,
+ {"hf_rs_sec_rgy_pgo_item_t_quota ", "hf_rs_sec_rgy_pgo_item_t_quota",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_rs_sec_rgy_pgo_item_t_unix_num,
+ {"hf_rs_sec_rgy_pgo_item_t_unix_num ",
+ "hf_rs_sec_rgy_pgo_item_t_unix_num", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_rs_timeval,
+ {"hf_rs_timeval ", "hf_rs_timeval", FT_RELATIVE_TIME, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ {&hf_rs_uuid1,
+ {"hf_rs_uuid1 ", "hf_rs_uuid1", FT_STRING, BASE_NONE, NULL, 0x0, "UUID",
+ HFILL}},
+ {&hf_rs_var1,
+ {"hf_rs_var1 ", "hf_rs_var1", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ {&hf_sec_attr_component_name_t_handle,
+ {"hf_sec_attr_component_name_t_handle ",
+ "hf_sec_attr_component_name_t_handle", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_sec_attr_component_name_t_valid,
+ {"hf_sec_attr_component_name_t_valid ",
+ "hf_sec_attr_component_name_t_valid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ {&hf_sec_passwd_type_t,
+ {"hf_sec_passwd_type_t ", "hf_sec_passwd_type_t", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_sec_passwd_version_t,
+ {"hf_sec_passwd_version_t ", "hf_sec_passwd_version_t", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_acct_admin_flags,
+ {"hf_sec_rgy_acct_admin_flags ", "hf_sec_rgy_acct_admin_flags",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_acct_auth_flags_t,
+ {"hf_sec_rgy_acct_auth_flags_t ", "hf_sec_rgy_acct_auth_flags_t",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_acct_key_t,
+ {"hf_sec_rgy_acct_key_t ", "hf_sec_rgy_acct_key_t", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_domain_t,
+ {"hf_sec_rgy_domain_t ", "hf_sec_rgy_domain_t", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_name_t_principalName_string,
+ {"hf_sec_rgy_name_t_principalName_string ",
+ "hf_sec_rgy_name_t_principalName_string", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ {&hf_sec_rgy_name_t_size,
+ {"hf_sec_rgy_name_t_size ", "hf_sec_rgy_name_t_size", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_pgo_flags_t,
+ {"hf_sec_rgy_pgo_flags_t ", "hf_sec_rgy_pgo_flags_t", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_pgo_item_t,
+ {"hf_sec_rgy_pgo_item_t ", "hf_sec_rgy_pgo_item_t", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_pname_t_principalName_string,
+ {"hf_sec_rgy_pname_t_principalName_string ",
+ "hf_sec_rgy_pname_t_principalName_string", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+ {&hf_sec_rgy_unix_sid_t_group,
+ {"hf_sec_rgy_unix_sid_t_group ", "hf_sec_rgy_unix_sid_t_group",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_unix_sid_t_org,
+ {"hf_sec_rgy_unix_sid_t_org ", "hf_sec_rgy_unix_sid_t_org", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_sec_rgy_unix_sid_t_person,
+ {"hf_sec_rgy_unix_sid_t_person ", "hf_sec_rgy_unix_sid_t_person",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_sec_timeval_sec_t,
+ {"hf_sec_timeval_sec_t ", "hf_sec_timeval_sec_t", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ {&hf_rs_pgo_unix_num_key_t,
+ {"hf_rs_pgo_unix_num_key_t", "hf_rs_pgo_unix_num_key_t", FT_UINT32,
+ BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ };
+
+ static gint *ett[] = {
+ &ett_error_status_t,
+ &ett_rgy_acct_user_flags_t,
+ &ett_rs_pgo,
+ &ett_rs_pgo_id_key_t,
+ &ett_rs_pgo_query_key_t,
+ &ett_rs_pgo_query_result_t,
+ &ett_rs_pgo_query_t,
+ &ett_rs_pgo_result_t,
+ &ett_rs_pgo_unix_num_key_t,
+ &ett_sec_attr_component_name_t,
+ &ett_sec_passwd_type_t,
+ &ett_sec_rgy_acct_admin_flags_t,
+ &ett_sec_rgy_acct_admin_t,
+ &ett_sec_rgy_acct_auth_flags_t,
+ &ett_sec_rgy_acct_key_t,
+ &ett_sec_rgy_acct_user_t,
+ &ett_sec_rgy_cursor_t,
+ &ett_sec_rgy_foreign_id_t,
+ &ett_sec_rgy_login_name_t,
+ &ett_sec_rgy_name_t,
+ &ett_sec_rgy_domain_t,
+ &ett_sec_rgy_pgo_flags_t,
+ &ett_sec_rgy_pgo_item_t,
+ &ett_sec_rgy_pname_t,
+ &ett_sec_rgy_sid_t,
+ &ett_sec_rgy_unix_passwd_buf_t,
+ &ett_sec_rgy_unix_sid_t,
+ &ett_sec_timeval_sec_t,
+ &ett_rs_cache_data_t,
+ };
+ proto_rs_pgo =
+ proto_register_protocol ("DCE Name Service", "RS_PGO", "rs_pgo");
+ proto_register_field_array (proto_rs_pgo, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_pgo (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_pgo, ett_rs_pgo, &uuid_rs_pgo, ver_rs_pgo,
+ rs_pgo_dissectors, hf_rs_pgo_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_plcy.c b/epan/dissectors/packet-dcerpc-rs_plcy.c
new file mode 100644
index 0000000000..58b499d010
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_plcy.c
@@ -0,0 +1,99 @@
+/* packet-dcerpc-rs_plcy.c
+ *
+ * Routines for dcerpc RS_PLCY dissection
+ * Copyright 2003, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz rs_plcy.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+/* Global hf index fields */
+
+static int proto_dcerpc_rs_plcy = -1;
+static int hf_rs_plcy_opnum = -1;
+static gint ett_dcerpc_rs_plcy = -1;
+
+static e_uuid_t uuid_dcerpc_rs_plcy = {
+ 0x4c878280, 0x4000, 0x0000,
+ { 0x0D, 0x00, 0x02, 0x87, 0x14, 0x00, 0x00, 0x00 }
+};
+
+static guint16 ver_dcerpc_rs_plcy = 1;
+
+static dcerpc_sub_dissector dcerpc_rs_plcy_dissectors[] = {
+ { 0, "rs_properties_get_info", NULL, NULL },
+ { 1, "rs_properties_set_info ", NULL, NULL },
+ { 2, "rs_policy_get_info", NULL, NULL },
+ { 3, "rs_policy_set_info", NULL, NULL },
+ { 4, "rs_policy_get_effective", NULL, NULL },
+ { 5, "rs_policy_get_override_info", NULL, NULL },
+ { 6, "rs_policy_set_override_info", NULL, NULL },
+ { 7, "rs_auth_policy_get_info", NULL, NULL },
+ { 8, "rs_auth_policy_get_effective", NULL, NULL },
+ { 9, "rs_auth_policy_set_info", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_rs_plcy(void)
+{
+ static hf_register_info hf[] = {
+
+ /* Global indexes */
+
+
+ { &hf_rs_plcy_opnum,
+ { "Operation", "rs_plcy.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_rs_plcy
+ };
+
+ proto_dcerpc_rs_plcy = proto_register_protocol(
+ "RS Interface properties", "RS_PLCY", "rs_plcy");
+
+ proto_register_field_array(proto_dcerpc_rs_plcy, hf,
+ array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_rs_plcy(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_rs_plcy, ett_dcerpc_rs_plcy,
+ &uuid_dcerpc_rs_plcy, ver_dcerpc_rs_plcy,
+ dcerpc_rs_plcy_dissectors, hf_rs_plcy_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_prop_acct.c b/epan/dissectors/packet-dcerpc-rs_prop_acct.c
new file mode 100644
index 0000000000..49f0401659
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_prop_acct.c
@@ -0,0 +1,83 @@
+/* packet-dcerpc-rs_prop_acct.c
+ * Routines for rs_prop_acct dissection
+ * Copyright 2003, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz bubasics/rs_prop_acct.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_rs_prop_acct = -1;
+static int hf_rs_prop_acct_opnum = -1;
+
+
+static gint ett_rs_prop_acct = -1;
+static e_uuid_t uuid_rs_prop_acct = { 0x68097130, 0xde43, 0x11ca, { 0xa5, 0x54, 0x08, 0x00, 0x1e, 0x03, 0x94, 0xc7 } };
+static guint16 ver_rs_prop_acct = 1;
+
+
+static dcerpc_sub_dissector rs_prop_acct_dissectors[] = {
+{ 0, "rs_prop_acct_add", NULL, NULL },
+{ 1, "rs_prop_acct_delete", NULL, NULL },
+{ 2, "rs_prop_acct_rename", NULL, NULL },
+{ 3, "rs_prop_acct_replace", NULL, NULL },
+{ 4, "rs_prop_acct_add_key_version", NULL, NULL },
+{ 2, "rs_prop_acct_rename", NULL, NULL },
+{ 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_rs_prop_acct (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rs_prop_acct_opnum,
+ { "Operation", "rs_prop_acct.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_prop_acct,
+ };
+ proto_rs_prop_acct = proto_register_protocol ("DCE/RPC RS_PROP_ACCT ", "rs_prop_acct", "rs_prop_acct");
+ proto_register_field_array (proto_rs_prop_acct, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_prop_acct (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_prop_acct, ett_rs_prop_acct, &uuid_rs_prop_acct, ver_rs_prop_acct, rs_prop_acct_dissectors, hf_rs_prop_acct_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_prop_acl.c b/epan/dissectors/packet-dcerpc-rs_prop_acl.c
new file mode 100644
index 0000000000..2a96a833bb
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_prop_acl.c
@@ -0,0 +1,88 @@
+/* packet-dcerpc-rs_prop_acl.c
+ *
+ * Routines for rs_prop_acl dissection
+ * Copyright 2004, Jaime Fournier <jaime.fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_prop_acl.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_rs_prop_acl = -1;
+static int hf_rs_prop_acl_opnum = -1;
+
+
+static gint ett_rs_prop_acl = -1;
+static e_uuid_t uuid_rs_prop_acl =
+ { 0x591d87d0, 0xde64, 0x11ca, {0xa1, 0x1c, 0x08, 0x00, 0x1e, 0x03, 0x94,
+ 0xc7} };
+
+static guint16 ver_rs_prop_acl = 1;
+
+
+static dcerpc_sub_dissector rs_prop_acl_dissectors[] = {
+ {0, "replace", NULL, NULL},
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_rs_prop_acl (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rs_prop_acl_opnum,
+ {"Operation", "rs_prop_acl.opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operation", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_prop_acl,
+ };
+ proto_rs_prop_acl =
+ proto_register_protocol
+ ("DCE/RPC Registry server propagation interface - ACLs. ", "rs_prop_acl",
+ "rs_prop_acl");
+ proto_register_field_array (proto_rs_prop_acl, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_prop_acl (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_prop_acl, ett_rs_prop_acl, &uuid_rs_prop_acl,
+ ver_rs_prop_acl, rs_prop_acl_dissectors,
+ hf_rs_prop_acl_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_prop_attr.c b/epan/dissectors/packet-dcerpc-rs_prop_attr.c
new file mode 100644
index 0000000000..f03bbfe0ae
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_prop_attr.c
@@ -0,0 +1,88 @@
+/* packet-dcerpc-rs_prop_attr.c
+ *
+ * Routines for rs_prop_attr dissection
+ * Copyright 2004, Jaime Fournier <jaime.fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_prop_attr.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_rs_prop_attr = -1;
+static int hf_rs_prop_attr_opnum = -1;
+
+
+static gint ett_rs_prop_attr = -1;
+static e_uuid_t uuid_rs_prop_attr =
+ { 0x0eff23e6, 0x555a, 0x11cd, {0x95, 0xbf, 0x08, 0x00, 0x09, 0x27, 0x84,
+ 0xc3} };
+
+static guint16 ver_rs_prop_attr = 1;
+
+
+static dcerpc_sub_dissector rs_prop_attr_dissectors[] = {
+ {0, "update", NULL, NULL},
+ {1, "delete", NULL, NULL},
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_rs_prop_attr (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rs_prop_attr_opnum,
+ {"Operation", "rs_prop_attr.opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operation", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_prop_attr,
+ };
+ proto_rs_prop_attr =
+ proto_register_protocol ("DCE/RPC Prop Attr", "rs_prop_attr",
+ "rs_prop_attr");
+ proto_register_field_array (proto_rs_prop_attr, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_prop_attr (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_prop_attr, ett_rs_prop_attr, &uuid_rs_prop_attr,
+ ver_rs_prop_attr, rs_prop_attr_dissectors,
+ hf_rs_prop_attr_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_prop_pgo.c b/epan/dissectors/packet-dcerpc-rs_prop_pgo.c
new file mode 100644
index 0000000000..5dbe7a9d3f
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_prop_pgo.c
@@ -0,0 +1,93 @@
+/* packet-dcerpc-rs_prop_pgo.c
+ *
+ * Routines for rs_prop_pgo dissection
+ * Copyright 2004, Jaime Fournier <jaime.fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_prop_pgo.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_rs_prop_pgo = -1;
+static int hf_rs_prop_pgo_opnum = -1;
+
+
+static gint ett_rs_prop_pgo = -1;
+static e_uuid_t uuid_rs_prop_pgo =
+ { 0xc23626e8, 0xde34, 0x11ca, {0x8c, 0xbc, 0x08, 0x00, 0x1e, 0x03, 0x94,
+ 0xc7} };
+
+static guint16 ver_rs_prop_pgo = 1;
+
+
+static dcerpc_sub_dissector rs_prop_pgo_dissectors[] = {
+ {0, "add", NULL, NULL},
+ {1, "rename", NULL, NULL},
+ {2, "replace", NULL, NULL},
+ {3, "add_member", NULL, NULL},
+ {4, "delete_member", NULL, NULL},
+ {5, "add_member_global", NULL, NULL},
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_rs_prop_pgo (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rs_prop_pgo_opnum,
+ {"Operation", "rs_prop_pgo.opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operation", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_prop_pgo,
+ };
+ proto_rs_prop_pgo =
+ proto_register_protocol
+ ("DCE/RPC Registry server propagation interface - PGO items",
+ "rs_prop_pgo", "rs_prop_pgo");
+ proto_register_field_array (proto_rs_prop_pgo, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_prop_pgo (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_prop_pgo, ett_rs_prop_pgo, &uuid_rs_prop_pgo,
+ ver_rs_prop_pgo, rs_prop_pgo_dissectors,
+ hf_rs_prop_pgo_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_prop_plcy.c b/epan/dissectors/packet-dcerpc-rs_prop_plcy.c
new file mode 100644
index 0000000000..afcace8964
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_prop_plcy.c
@@ -0,0 +1,91 @@
+/* packet-dcerpc-rs_prop_plcy.c
+ *
+ * Routines for rs_prop_plcy dissection
+ * Copyright 2004, Jaime Fournier <jaime.fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_prop_plcy.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_rs_prop_plcy = -1;
+static int hf_rs_prop_plcy_opnum = -1;
+
+
+static gint ett_rs_prop_plcy = -1;
+static e_uuid_t uuid_rs_prop_plcy =
+ { 0xe6ac5cb8, 0xde3e, 0x11ca, {0x93, 0x76, 0x08, 0x00, 0x1e, 0x03, 0x94,
+ 0xc7} };
+
+static guint16 ver_rs_prop_plcy = 1;
+
+
+static dcerpc_sub_dissector rs_prop_plcy_dissectors[] = {
+ {0, "rs_prop_properties_set_info", NULL, NULL},
+ {1, "rs_prop_plcy_set_info", NULL, NULL},
+ {2, "rs_prop_auth_plcy_set_info", NULL, NULL},
+ {3, "rs_prop_plcy_set_dom_cache_info", NULL, NULL},
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_rs_prop_plcy (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rs_prop_plcy_opnum,
+ {"Operation", "rs_prop_plcy.opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operation", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_prop_plcy,
+ };
+ proto_rs_prop_plcy =
+ proto_register_protocol
+ ("DCE/RPC Registry server propagation interface - properties and policies",
+ "rs_prop_plcy", "rs_prop_plcy");
+ proto_register_field_array (proto_rs_prop_plcy, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_prop_plcy (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_prop_plcy, ett_rs_prop_plcy, &uuid_rs_prop_plcy,
+ ver_rs_prop_plcy, rs_prop_plcy_dissectors,
+ hf_rs_prop_plcy_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_pwd_mgmt.c b/epan/dissectors/packet-dcerpc-rs_pwd_mgmt.c
new file mode 100644
index 0000000000..7e029e1ccf
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_pwd_mgmt.c
@@ -0,0 +1,95 @@
+/* packet-dcerpc-rs_pwd_mgmt.c
+ *
+ * Routines for rs_pwd_mgmt dissection
+ * Copyright 2004, Jaime Fournier <jaime.fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_pwd_mgmt.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_rs_pwd_mgmt = -1;
+static int hf_rs_pwd_mgmt_opnum = -1;
+
+
+static gint ett_rs_pwd_mgmt = -1;
+static e_uuid_t uuid_rs_pwd_mgmt =
+ { 0x3139a0e2, 0x68da, 0x11cd, {0x91, 0xc7, 0x08, 0x00, 0x09, 0x24, 0x24,
+ 0x44} };
+
+static guint16 ver_rs_pwd_mgmt = 1;
+
+
+static dcerpc_sub_dissector rs_pwd_mgmt_dissectors[] = {
+ {0, "lookup", NULL, NULL},
+ {1, "replace", NULL, NULL},
+ {2, "get_access", NULL, NULL},
+ {3, "test_access", NULL, NULL},
+ {4, "test_access_on_behalf", NULL, NULL},
+ {5, "get_manager_types", NULL, NULL},
+ {6, "get_printstring", NULL, NULL},
+ {7, "get_referral", NULL, NULL},
+ {8, "get_mgr_types_semantics", NULL, NULL},
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_rs_pwd_mgmt (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rs_pwd_mgmt_opnum,
+ {"Operation", "rs_pwd_mgmt.opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operation", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_pwd_mgmt,
+ };
+ proto_rs_pwd_mgmt =
+ proto_register_protocol ("DCE/RPC Registry Password Management ",
+ "rs_pwd_mgmt", "rs_pwd_mgmt");
+ proto_register_field_array (proto_rs_pwd_mgmt, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_pwd_mgmt (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_pwd_mgmt, ett_rs_pwd_mgmt, &uuid_rs_pwd_mgmt,
+ ver_rs_pwd_mgmt, rs_pwd_mgmt_dissectors,
+ hf_rs_pwd_mgmt_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_repadm.c b/epan/dissectors/packet-dcerpc-rs_repadm.c
new file mode 100644
index 0000000000..6f1d035595
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_repadm.c
@@ -0,0 +1,96 @@
+/* packet-dcerpc-rs_repadm.c
+ *
+ * Routines for dcerpc Registry server administration operations.
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_repadm.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_rs_repadm = -1;
+static int hf_rs_repadm_opnum = -1;
+
+
+static gint ett_rs_repadm = -1;
+
+
+static e_uuid_t uuid_rs_repadm = { 0x5b8c2fa8, 0xb60b, 0x11c9, { 0xbe, 0x0f, 0x08, 0x00, 0x1e, 0x01, 0x8f, 0xa0 } };
+static guint16 ver_rs_repadm = 1;
+
+
+
+
+static dcerpc_sub_dissector rs_repadm_dissectors[] = {
+ { 0, "stop", NULL, NULL},
+ { 1, "maint", NULL, NULL},
+ { 2, "mkey", NULL, NULL},
+ { 3, "info", NULL, NULL},
+ { 4, "info_full", NULL, NULL},
+ { 5, "destroy", NULL, NULL},
+ { 6, "init_replica", NULL, NULL},
+ { 7, "change_master", NULL, NULL},
+ { 8, "become_master", NULL, NULL},
+ { 9, "become_slave", NULL, NULL},
+ { 10, "set_sw_rev", NULL, NULL},
+ { 11, "get_sw_vers_info", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+
+void
+proto_register_rs_repadm (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rs_repadm_opnum,
+ { "Operation", "rs_repadmin.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_rs_repadm,
+ };
+ proto_rs_repadm = proto_register_protocol ("Registry server administration operations.", "RS_REPADM", "rs_repadm");
+ proto_register_field_array (proto_rs_repadm, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_repadm (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_repadm, ett_rs_repadm, &uuid_rs_repadm, ver_rs_repadm, rs_repadm_dissectors, hf_rs_repadm_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_replist.c b/epan/dissectors/packet-dcerpc-rs_replist.c
new file mode 100644
index 0000000000..e0baac8d3a
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_replist.c
@@ -0,0 +1,92 @@
+/* packet-dcerpc-rs_replist.c
+ *
+ * Routines for dcerpc RepServer Calls
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_repadm.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_rs_replist = -1;
+static int hf_rs_replist_opnum = -1;
+
+
+static gint ett_rs_replist = -1;
+
+
+static e_uuid_t uuid_rs_replist = { 0x850446b0, 0xe95b, 0x11CA, { 0xad, 0x90, 0x08, 0x00, 0x1e, 0x01, 0x45, 0xb1 } };
+static guint16 ver_rs_replist = 2;
+
+
+static dcerpc_sub_dissector rs_replist_dissectors[] = {
+ { 0, "rs_replist_add_replica", NULL, NULL},
+ { 1, "rs_replist_replace_replica", NULL, NULL},
+ { 2, "rs_replist_delete_replica", NULL, NULL},
+ { 3, "rs_replist_read", NULL, NULL},
+ { 4, "rs_replist_read_full", NULL, NULL},
+ { 5, "rs_replist_add_replica", NULL, NULL},
+ { 6, "rs_replist_replace_replica", NULL, NULL},
+ { 7, "rs_replist_delete_replica", NULL, NULL},
+ { 8, "rs_replist_read", NULL, NULL},
+ { 9, "rs_replist_read_full", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_rs_replist (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rs_replist_opnum,
+ { "Operation", "rs_replist.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_replist,
+ };
+ proto_rs_replist = proto_register_protocol ("DCE/RPC Repserver Calls", "RS_REPLIST", "rs_replist");
+
+ proto_register_field_array (proto_rs_replist, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_replist (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_replist, ett_rs_replist, &uuid_rs_replist, ver_rs_replist, rs_replist_dissectors, hf_rs_replist_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_repmgr.c b/epan/dissectors/packet-dcerpc-rs_repmgr.c
new file mode 100644
index 0000000000..d9e52e9359
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_repmgr.c
@@ -0,0 +1,95 @@
+/* packet-dcerpc-rs_repmgr.c
+ *
+ * Routines for rs_repmgr dissection
+ * Copyright 2004, Jaime Fournier <jaime.fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_repmgr.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_rs_repmgr = -1;
+static int hf_rs_repmgr_opnum = -1;
+
+
+static gint ett_rs_repmgr = -1;
+static e_uuid_t uuid_rs_repmgr =
+ { 0xb62dc198, 0xdfd4, 0x11ca, {0x94, 0x8f, 0x08, 0x00, 0x1e, 0x02, 0x59,
+ 0x4c} };
+
+static guint16 ver_rs_repmgr = 2;
+
+
+static dcerpc_sub_dissector rs_repmgr_dissectors[] = {
+ {0, "get_info_and_creds", NULL, NULL},
+ {1, "init", NULL, NULL},
+ {2, "init_done", NULL, NULL},
+ {3, "i_am_slave", NULL, NULL},
+ {4, "i_am_master", NULL, NULL},
+ {5, "become_master", NULL, NULL},
+ {6, "copy_all", NULL, NULL},
+ {7, "copy_propq", NULL, NULL},
+ {8, "stop_until_compat_sw", NULL, NULL},
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_rs_repmgr (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rs_repmgr_opnum,
+ {"Operation", "rs_repmgr.opnum", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operation", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_rs_repmgr,
+ };
+ proto_rs_repmgr =
+ proto_register_protocol
+ ("DCE/RPC Operations between registry server replicas", "rs_repmgr",
+ "rs_repmgr");
+ proto_register_field_array (proto_rs_repmgr, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_repmgr (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_repmgr, ett_rs_repmgr, &uuid_rs_repmgr,
+ ver_rs_repmgr, rs_repmgr_dissectors, hf_rs_repmgr_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rs_unix.c b/epan/dissectors/packet-dcerpc-rs_unix.c
new file mode 100644
index 0000000000..e51963adfa
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rs_unix.c
@@ -0,0 +1,82 @@
+/* packet-dcerpc-rs_unix.c
+ *
+ * Routines for dcerpc Unix ops
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rs_unix.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_rs_unix = -1;
+static int hf_rs_unix_opnum = -1;
+
+static gint ett_rs_unix = -1;
+
+
+static e_uuid_t uuid_rs_unix = { 0x361993c0, 0xb000, 0x0000, { 0x0d, 0x00, 0x00, 0x87, 0x84, 0x00, 0x00, 0x00 } };
+static guint16 ver_rs_unix = 1;
+
+
+static dcerpc_sub_dissector rs_unix_dissectors[] = {
+ { 0, "getpwents", NULL, NULL },
+ { 0, NULL, NULL, NULL },
+};
+
+void
+proto_register_rs_unix (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rs_unix_opnum,
+ { "Operation", "rs_unix.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_rs_unix,
+ };
+ proto_rs_unix = proto_register_protocol ("DCE/RPC RS_UNIX", "RS_UNIX", "rs_unix");
+ proto_register_field_array (proto_rs_unix, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rs_unix (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rs_unix, ett_rs_unix, &uuid_rs_unix, ver_rs_unix, rs_unix_dissectors, hf_rs_unix_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-rsec_login.c b/epan/dissectors/packet-dcerpc-rsec_login.c
new file mode 100644
index 0000000000..26b11e304c
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-rsec_login.c
@@ -0,0 +1,81 @@
+/* packet-dcerpc-rsec_login.c
+ *
+ * Routines for dcerpc Remote sec_login preauth interface.
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rsec_login.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_rsec_login = -1;
+static int hf_rsec_login_opnum = -1;
+
+static gint ett_rsec_login = -1;
+
+
+static e_uuid_t uuid_rsec_login = { 0xa76e832a, 0x10df, 0x11cd, { 0x90, 0x56, 0x08, 0x00, 0x09, 0x24, 0x24, 0x44 } };
+static guint16 ver_rsec_login = 2;
+
+
+static dcerpc_sub_dissector rsec_login_dissectors[] = {
+ { 0, "rsec_login_get_trusted_preauth", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_rsec_login (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rsec_login_opnum,
+ { "Operation", "rsec_login.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_rsec_login,
+ };
+ proto_rsec_login = proto_register_protocol ("Remote sec_login preauth interface.", "rsec_login", "rsec_login");
+ proto_register_field_array (proto_rsec_login, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_rsec_login (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_rsec_login, ett_rsec_login, &uuid_rsec_login, ver_rsec_login, rsec_login_dissectors, hf_rsec_login_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-samr.c b/epan/dissectors/packet-dcerpc-samr.c
new file mode 100644
index 0000000000..9e6d52fb43
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-samr.c
@@ -0,0 +1,5636 @@
+/* packet-dcerpc-samr.c
+ * Routines for SMB \PIPE\samr packet disassembly
+ * Copyright 2001,2003 Tim Potter <tpot@samba.org>
+ * 2002 Added all command dissectors Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <string.h>
+#include "prefs.h"
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-samr.h"
+#include "smb.h" /* for "NT_errors[]" */
+#include "packet-smb-common.h"
+#include "crypt-md4.h"
+#include "crypt-rc4.h"
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+static int proto_dcerpc_samr = -1;
+
+static int hf_samr_opnum = -1;
+static int hf_samr_hnd = -1;
+static int hf_samr_group = -1;
+static int hf_samr_rid = -1;
+static int hf_samr_type = -1;
+static int hf_samr_alias = -1;
+static int hf_samr_rid_attrib = -1;
+static int hf_samr_rc = -1;
+static int hf_samr_index = -1;
+static int hf_samr_count = -1;
+static int hf_samr_sd_size = -1;
+
+static int hf_samr_level = -1;
+static int hf_samr_start_idx = -1;
+static int hf_samr_max_entries = -1;
+static int hf_samr_entries = -1;
+static int hf_samr_pref_maxsize = -1;
+static int hf_samr_total_size = -1;
+static int hf_samr_ret_size = -1;
+static int hf_samr_alias_name = -1;
+static int hf_samr_group_name = -1;
+static int hf_samr_acct_name = -1;
+static int hf_samr_full_name = -1;
+static int hf_samr_acct_desc = -1;
+static int hf_samr_home = -1;
+static int hf_samr_home_drive = -1;
+static int hf_samr_script = -1;
+static int hf_samr_workstations = -1;
+static int hf_samr_profile = -1;
+static int hf_samr_callback = -1;
+static int hf_samr_server = -1;
+static int hf_samr_domain = -1;
+static int hf_samr_controller = -1;
+static int hf_samr_access = -1;
+static int hf_samr_access_granted = -1;
+static int hf_samr_crypt_password = -1;
+static int hf_samr_crypt_hash = -1;
+static int hf_samr_lm_change = -1;
+static int hf_samr_lm_passchange_block = -1;
+static int hf_samr_nt_passchange_block = -1;
+static int hf_samr_nt_passchange_block_decrypted = -1;
+static int hf_samr_nt_passchange_block_newpass = -1;
+static int hf_samr_nt_passchange_block_newpass_len = -1;
+static int hf_samr_nt_passchange_block_pseudorandom = -1;
+static int hf_samr_lm_verifier = -1;
+static int hf_samr_nt_verifier = -1;
+static int hf_samr_attrib = -1;
+static int hf_samr_max_pwd_age = -1;
+static int hf_samr_min_pwd_age = -1;
+static int hf_samr_min_pwd_len = -1;
+static int hf_samr_pwd_history_len = -1;
+static int hf_samr_num_users = -1;
+static int hf_samr_num_groups = -1;
+static int hf_samr_num_aliases = -1;
+static int hf_samr_resume_hnd = -1;
+static int hf_samr_bad_pwd_count = -1;
+static int hf_samr_logon_count = -1;
+static int hf_samr_logon_time = -1;
+static int hf_samr_logoff_time = -1;
+static int hf_samr_kickoff_time = -1;
+static int hf_samr_pwd_last_set_time = -1;
+static int hf_samr_pwd_can_change_time = -1;
+static int hf_samr_pwd_must_change_time = -1;
+static int hf_samr_acct_expiry_time = -1;
+static int hf_samr_country = -1;
+static int hf_samr_codepage = -1;
+static int hf_samr_comment = -1;
+static int hf_samr_nt_pwd_set = -1;
+static int hf_samr_lm_pwd_set = -1;
+static int hf_samr_pwd_expired = -1;
+static int hf_samr_revision = -1;
+static int hf_samr_info_type = -1;
+static int hf_samr_primary_group_rid = -1;
+static int hf_samr_group_num_of_members = -1;
+static int hf_samr_group_desc = -1;
+static int hf_samr_alias_num_of_members = -1;
+static int hf_samr_alias_desc = -1;
+
+static int hf_samr_unknown_hyper = -1;
+static int hf_samr_unknown_long = -1;
+static int hf_samr_unknown_short = -1;
+static int hf_samr_unknown_char = -1;
+static int hf_samr_unknown_string = -1;
+static int hf_samr_unknown_time = -1;
+
+static gint ett_dcerpc_samr = -1;
+static gint ett_SAM_SECURITY_DESCRIPTOR = -1;
+static gint ett_samr_user_dispinfo_1 = -1;
+static gint ett_samr_user_dispinfo_1_array = -1;
+static gint ett_samr_user_dispinfo_2 = -1;
+static gint ett_samr_user_dispinfo_2_array = -1;
+static gint ett_samr_group_dispinfo = -1;
+static gint ett_samr_group_dispinfo_array = -1;
+static gint ett_samr_ascii_dispinfo = -1;
+static gint ett_samr_ascii_dispinfo_array = -1;
+static gint ett_samr_display_info = -1;
+static gint ett_samr_password_info = -1;
+static gint ett_samr_server = -1;
+static gint ett_samr_user_group = -1;
+static gint ett_samr_user_group_array = -1;
+static gint ett_samr_alias_info = -1;
+static gint ett_samr_group_info = -1;
+static gint ett_samr_domain_info_1 = -1;
+static gint ett_samr_domain_info_2 = -1;
+static gint ett_samr_domain_info_8 = -1;
+static gint ett_samr_replication_status = -1;
+static gint ett_samr_domain_info_11 = -1;
+static gint ett_samr_domain_info_13 = -1;
+static gint ett_samr_domain_info = -1;
+static gint ett_samr_index_array = -1;
+static gint ett_samr_idx_and_name = -1;
+static gint ett_samr_idx_and_name_array = -1;
+static gint ett_samr_user_info_1 = -1;
+static gint ett_samr_user_info_2 = -1;
+static gint ett_samr_user_info_3 = -1;
+static gint ett_samr_user_info_5 = -1;
+static gint ett_samr_user_info_6 = -1;
+static gint ett_samr_user_info_10 = -1;
+static gint ett_samr_user_info_18 = -1;
+static gint ett_samr_user_info_19 = -1;
+static gint ett_samr_buffer_buffer = -1;
+static gint ett_samr_buffer = -1;
+static gint ett_samr_user_info_21 = -1;
+static gint ett_samr_user_info_22 = -1;
+static gint ett_samr_user_info_23 = -1;
+static gint ett_samr_user_info_24 = -1;
+static gint ett_samr_user_info_25 = -1;
+static gint ett_samr_user_info = -1;
+static gint ett_samr_member_array_types = -1;
+static gint ett_samr_member_array_rids = -1;
+static gint ett_samr_member_array = -1;
+static gint ett_samr_names = -1;
+static gint ett_samr_rids = -1;
+#ifdef SAMR_UNUSED_HANDLES
+static gint ett_samr_hnd = -1;
+#endif
+
+static e_uuid_t uuid_dcerpc_samr = {
+ 0x12345778, 0x1234, 0xabcd,
+ { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xac}
+};
+
+static guint16 ver_dcerpc_samr = 1;
+
+/* Configuration variables */
+static char *nt_password = NULL;
+
+/* Dissect connect specific access rights */
+
+static gint hf_access_connect_connect_to_server = -1;
+static gint hf_access_connect_shutdown_server = -1;
+static gint hf_access_connect_initialize_server = -1;
+static gint hf_access_connect_create_domain = -1;
+static gint hf_access_connect_enum_domains = -1;
+static gint hf_access_connect_open_domain = -1;
+
+static void
+specific_rights_connect(tvbuff_t *tvb, gint offset, proto_tree *tree,
+ guint32 access)
+{
+ proto_tree_add_boolean(
+ tree, hf_access_connect_open_domain,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_connect_enum_domains,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_connect_create_domain,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_connect_initialize_server,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_connect_shutdown_server,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_connect_connect_to_server,
+ tvb, offset, 4, access);
+}
+
+struct access_mask_info samr_connect_access_mask_info = {
+ "SAMR connect",
+ specific_rights_connect,
+ NULL, /* Generic rights mapping */
+ NULL /* Standard rights mapping */
+};
+
+
+int
+sam_dissect_SAM_SECURITY_DESCRIPTOR_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_sd_size, &len);
+
+ dissect_nt_sec_desc(
+ tvb, offset, pinfo, tree, drep, len, &samr_connect_access_mask_info);
+
+ offset += len;
+
+ return offset;
+}
+
+int
+sam_dissect_SAM_SECURITY_DESCRIPTOR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "SAM_SECURITY_DESCRIPTOR:");
+ tree = proto_item_add_subtree(item, ett_SAM_SECURITY_DESCRIPTOR);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_sd_size, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ sam_dissect_SAM_SECURITY_DESCRIPTOR_data, NDR_POINTER_UNIQUE,
+ "SAM SECURITY DESCRIPTOR data:", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+/* Dissect domain specific access rights */
+
+static gint hf_access_domain_lookup_info1 = -1;
+static gint hf_access_domain_set_info1 = -1;
+static gint hf_access_domain_lookup_info2 = -1;
+static gint hf_access_domain_set_info2 = -1;
+static gint hf_access_domain_create_user = -1;
+static gint hf_access_domain_create_group = -1;
+static gint hf_access_domain_create_alias = -1;
+static gint hf_access_domain_lookup_alias_by_mem = -1;
+static gint hf_access_domain_enum_accounts = -1;
+static gint hf_access_domain_open_account = -1;
+static gint hf_access_domain_set_info3 = -1;
+
+static void
+specific_rights_domain(tvbuff_t *tvb, gint offset, proto_tree *tree,
+ guint32 access)
+{
+ proto_tree_add_boolean(
+ tree, hf_access_domain_set_info3,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_open_account,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_enum_accounts,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_lookup_alias_by_mem,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_create_alias,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_create_group,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_create_user,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_set_info2,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_lookup_info2,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_set_info1,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_domain_lookup_info1,
+ tvb, offset, 4, access);
+ }
+
+struct access_mask_info samr_domain_access_mask_info = {
+ "SAMR domain",
+ specific_rights_domain,
+ NULL, /* Generic mapping table */
+ NULL /* Standard mapping table */
+};
+
+/* Dissect user specific access rights */
+
+static gint hf_access_user_get_name_etc = -1;
+static gint hf_access_user_get_locale = -1;
+static gint hf_access_user_get_loc_com = -1;
+static gint hf_access_user_get_logoninfo = -1;
+static gint hf_access_user_get_attributes = -1;
+static gint hf_access_user_set_attributes = -1;
+static gint hf_access_user_change_password = -1;
+static gint hf_access_user_set_password = -1;
+static gint hf_access_user_get_groups = -1;
+static gint hf_access_user_get_group_membership = -1;
+static gint hf_access_user_change_group_membership = -1;
+
+static void
+specific_rights_user(tvbuff_t *tvb, gint offset, proto_tree *tree,
+ guint32 access)
+{
+ proto_tree_add_boolean(
+ tree, hf_access_user_change_group_membership,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_get_group_membership,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_get_groups,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_set_password,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_change_password,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_set_attributes,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_get_attributes,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_get_logoninfo,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_get_loc_com,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_get_locale,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_user_get_name_etc,
+ tvb, offset, 4, access);
+}
+
+struct access_mask_info samr_user_access_mask_info = {
+ "SAMR user",
+ specific_rights_user,
+ NULL, /* Generic mapping table */
+ NULL /* Standard mapping table */
+};
+
+/* Dissect alias specific access rights */
+
+static gint hf_access_alias_add_member = -1;
+static gint hf_access_alias_remove_member = -1;
+static gint hf_access_alias_get_members = -1;
+static gint hf_access_alias_lookup_info = -1;
+static gint hf_access_alias_set_info = -1;
+
+static void
+specific_rights_alias(tvbuff_t *tvb, gint offset, proto_tree *tree,
+ guint32 access)
+{
+ proto_tree_add_boolean(
+ tree, hf_access_alias_set_info,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_alias_lookup_info,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_alias_get_members,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_alias_remove_member,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_alias_add_member,
+ tvb, offset, 4, access);
+}
+
+struct access_mask_info samr_alias_access_mask_info = {
+ "SAMR alias",
+ specific_rights_alias,
+ NULL, /* Generic mapping table */
+ NULL /* Standard mapping table */
+};
+
+/* Dissect group specific access rights */
+
+static gint hf_access_group_lookup_info = -1;
+static gint hf_access_group_set_info = -1;
+static gint hf_access_group_add_member = -1;
+static gint hf_access_group_remove_member = -1;
+static gint hf_access_group_get_members = -1;
+
+static void
+specific_rights_group(tvbuff_t *tvb, gint offset, proto_tree *tree,
+ guint32 access)
+{
+ proto_tree_add_boolean(
+ tree, hf_access_group_get_members,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_group_remove_member,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_group_add_member,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_group_set_info,
+ tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_access_group_lookup_info,
+ tvb, offset, 4, access);
+}
+
+struct access_mask_info samr_group_access_mask_info = {
+ "SAMR group",
+ specific_rights_group,
+ NULL, /* Generic mapping table */
+ NULL /* Standard mapping table */
+};
+
+static int
+dissect_ndr_nt_SID_no_hf(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
+ return offset;
+}
+
+/* above this line, just some general support routines which should be placed
+ in some more generic file common to all NT services dissectors
+*/
+
+static int
+samr_dissect_open_user_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 rid;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_user_access_mask_info, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, &rid);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", rid 0x%x", rid);
+
+ dcv->private_data = GINT_TO_POINTER(rid);
+
+ return offset;
+}
+
+static int
+samr_dissect_open_user_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+ guint32 rid = GPOINTER_TO_INT(dcv->private_data);
+ char *pol_name;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ if (rid)
+ pol_name = g_strdup_printf("OpenUser(rid 0x%x)", rid);
+ else
+ pol_name = g_strdup("OpenUser handle");
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": %s", pol_name);
+
+ g_free(pol_name);
+ }
+
+ return offset;
+}
+
+static int
+samr_dissect_pointer_long(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ return offset;
+}
+
+static int
+samr_dissect_pointer_STRING(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ di->hf_index, 0);
+ return offset;
+}
+
+static int
+samr_dissect_pointer_short(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ return offset;
+}
+
+
+static int
+samr_dissect_query_dispinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 level;
+ guint32 start_idx;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_start_idx, &start_idx);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_max_entries, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_pref_maxsize, NULL);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", level %d, start_idx %d",
+ level, start_idx);
+
+ return offset;
+}
+
+static int
+samr_dissect_USER_DISPINFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "User_DispInfo_1");
+ tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_index, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_full_name, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_desc, 0);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_DISPINFO_1_ARRAY_users(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_DISPINFO_1);
+
+ return offset;
+}
+
+static int
+samr_dissect_USER_DISPINFO_1_ARRAY (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 count;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "User_DispInfo_1 Array");
+ tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_1_array);
+ }
+
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_count, &count);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_DISPINFO_1_ARRAY_users, NDR_POINTER_PTR,
+ "USER_DISPINFO_1_ARRAY", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+
+static int
+samr_dissect_USER_DISPINFO_2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "User_DispInfo_2");
+ tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_2);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_index, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_desc, 0);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_DISPINFO_2_ARRAY_users (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_DISPINFO_2);
+
+ return offset;
+}
+
+static int
+samr_dissect_USER_DISPINFO_2_ARRAY (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 count;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "User_DispInfo_2 Array");
+ tree = proto_item_add_subtree(item, ett_samr_user_dispinfo_2_array);
+ }
+
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_count, &count);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_DISPINFO_2_ARRAY_users, NDR_POINTER_PTR,
+ "USER_DISPINFO_2_ARRAY", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_GROUP_DISPINFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "Group_DispInfo");
+ tree = proto_item_add_subtree(item, ett_samr_group_dispinfo);
+ }
+
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_index, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_desc, 0);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_GROUP_DISPINFO_ARRAY_groups(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_GROUP_DISPINFO);
+
+ return offset;
+}
+
+static int
+samr_dissect_GROUP_DISPINFO_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 count;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "Group_DispInfo Array");
+ tree = proto_item_add_subtree(item, ett_samr_group_dispinfo_array);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_count, &count);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_GROUP_DISPINFO_ARRAY_groups, NDR_POINTER_PTR,
+ "GROUP_DISPINFO_ARRAY", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+
+static int
+samr_dissect_ASCII_DISPINFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "Ascii_DispInfo");
+ tree = proto_item_add_subtree(item, ett_samr_ascii_dispinfo);
+ }
+
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_index, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_desc, 0);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_ASCII_DISPINFO_ARRAY_users(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_ASCII_DISPINFO);
+
+ return offset;
+}
+
+static int
+samr_dissect_ASCII_DISPINFO_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 count;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "Ascii_DispInfo Array");
+ tree = proto_item_add_subtree(item, ett_samr_ascii_dispinfo_array);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_count, &count);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_ASCII_DISPINFO_ARRAY_users, NDR_POINTER_PTR,
+ "ACSII_DISPINFO_ARRAY", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+samr_dissect_DISPLAY_INFO (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DISP_INFO:");
+ tree = proto_item_add_subtree(item, ett_samr_display_info);
+ }
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+ switch(level){
+ case 1:
+ offset = samr_dissect_USER_DISPINFO_1_ARRAY(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 2:
+ offset = samr_dissect_USER_DISPINFO_2_ARRAY(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 3:
+ offset = samr_dissect_GROUP_DISPINFO_ARRAY(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 4:
+ offset = samr_dissect_ASCII_DISPINFO_ARRAY(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 5:
+ offset = samr_dissect_ASCII_DISPINFO_ARRAY(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_query_dispinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Total Size", hf_samr_total_size);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Returned Size", hf_samr_ret_size);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_DISPLAY_INFO, NDR_POINTER_REF,
+ "DISPLAY_INFO:", -1);
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_display_enumeration_index_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_display_enumeration_index_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Index", hf_samr_index);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+
+
+
+static int
+samr_dissect_PASSWORD_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ ALIGN_TO_4_BYTES; /* strcture starts with short, but is aligned for longs */
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "PASSWORD_INFO:");
+ tree = proto_item_add_subtree(item, ett_samr_password_info);
+ }
+
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_short, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_get_usrdom_pwinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_usrdom_pwinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_PASSWORD_INFO, NDR_POINTER_REF,
+ "PASSWORD_INFO:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+ return offset;
+}
+
+static int
+samr_dissect_connect2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
+ "Server", hf_samr_server, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_connect_access_mask_info, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_connect3_4_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
+ "Server", hf_samr_server, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_connect_access_mask_info, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_connect2_3_4_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+ char *server = (char *)dcv->private_data, *pol_name = NULL;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ if (server) {
+ if (dcv->opnum == SAMR_CONNECT2)
+ pol_name = g_strdup_printf("Connect2(%s)", server);
+ if (dcv->opnum == SAMR_CONNECT3)
+ pol_name = g_strdup_printf("Connect3(%s)", server);
+ if (dcv->opnum == SAMR_CONNECT4)
+ pol_name = g_strdup_printf("Connect4(%s)", server);
+ }
+ else {
+ if (dcv->opnum == SAMR_CONNECT2)
+ pol_name = g_strdup("Connect2 handle");
+ if (dcv->opnum == SAMR_CONNECT3)
+ pol_name = g_strdup("Connect3 handle");
+ if (dcv->opnum == SAMR_CONNECT4)
+ pol_name = g_strdup("Connect4 handle");
+ }
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": %s", pol_name);
+
+ g_free(pol_name);
+ }
+
+ return offset;
+}
+
+static int
+samr_dissect_connect_anon_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ char str[2];
+ guint16 server;
+
+ offset=dissect_ndr_uint16(tvb, offset, pinfo, NULL, drep,
+ hf_samr_server, &server);
+ str[0]=server&0xff;
+ str[1]=0;
+ proto_tree_add_string_format(tree, hf_samr_server, tvb, offset-2, 2,
+ str, "Server: %s", str);
+
+ return offset;
+}
+
+static int
+samr_dissect_connect_anon_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
+ "ConnectAnon handle");
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": ConnectAnon handle");
+ }
+
+ return offset;
+}
+
+static int
+samr_dissect_USER_GROUP(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_GROUP:");
+ tree = proto_item_add_subtree(item, ett_samr_user_group);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid_attrib, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_GROUP_ARRAY_groups (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_GROUP);
+
+ return offset;
+}
+
+static int
+samr_dissect_USER_GROUP_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 count;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_GROUP_ARRAY");
+ tree = proto_item_add_subtree(item, ett_samr_user_group_array);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_count, &count);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_GROUP_ARRAY_groups, NDR_POINTER_UNIQUE,
+ "USER_GROUP_ARRAY", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_GROUP_ARRAY_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_GROUP_ARRAY, NDR_POINTER_UNIQUE,
+ "USER_GROUP_ARRAY", -1);
+ return offset;
+}
+
+static int
+samr_dissect_get_groups_for_user_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_groups_for_user_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_GROUP_ARRAY_ptr, NDR_POINTER_REF,
+ "USER_GROUP_ARRAY:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+ return offset;
+}
+
+
+static void append_sid_col_info(packet_info *pinfo, proto_tree *tree _U_,
+ proto_item *item _U_, tvbuff_t *tvb _U_,
+ int start_offset _U_, int end_offset _U_,
+ void *callback_args _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ char *sid_str = dcv->private_data;
+
+ if (sid_str && check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", sid_str);
+}
+
+static int
+samr_dissect_open_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_domain_access_mask_info, NULL);
+
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep, dissect_ndr_nt_SID_no_hf,
+ NDR_POINTER_REF, "SID:", -1, append_sid_col_info, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_open_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+ char *pol_name, *sid_str = (char *)dcv->private_data;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ if (sid_str) {
+ pol_name = g_strdup_printf("OpenDomain(%s)", sid_str);
+ } else {
+ pol_name = g_strdup("OpenDomain handle");
+ }
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": %s", pol_name);
+
+ g_free(pol_name);
+ }
+
+ return offset;
+}
+
+#if 0
+static int
+samr_dissect_context_handle_SID(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_SID_no_hf, NDR_POINTER_REF,
+ "SID pointer", -1);
+
+ return offset;
+}
+#endif
+
+static int
+samr_dissect_add_member_to_group_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_group, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_add_member_to_group_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_boot_key_information_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_boot_key_information_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_short, NDR_POINTER_REF,
+ "unknown short", hf_samr_unknown_short);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+ return offset;
+}
+
+static int
+samr_dissect_create_alias_in_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
+ "Alias Name", hf_samr_alias_name);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_alias_access_mask_info, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_create_alias_in_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
+ "CreateAlias handle");
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": CreateAlias handle");
+ }
+ return offset;
+}
+
+static int
+samr_dissect_query_information_alias_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ return offset;
+}
+
+static int
+samr_dissect_ALIAS_INFO_1 (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_alias_name, 0);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_alias_num_of_members, NULL);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_alias_desc, 0);
+ return offset;
+}
+
+static int
+samr_dissect_ALIAS_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "ALIAS_INFO:");
+ tree = proto_item_add_subtree(item, ett_samr_alias_info);
+ }
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+ switch(level){
+ case 1:
+ offset = samr_dissect_ALIAS_INFO_1(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 2:
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_alias_name, 0);
+ break;
+ case 3:
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_alias_desc, 0);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_ALIAS_INFO_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_ALIAS_INFO, NDR_POINTER_UNIQUE,
+ "ALIAS_INFO", -1);
+ return offset;
+}
+
+static int
+samr_dissect_query_information_alias_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_ALIAS_INFO_ptr, NDR_POINTER_REF,
+ "ALIAS_INFO:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_set_information_alias_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_ALIAS_INFO, NDR_POINTER_REF,
+ "ALIAS_INFO:", -1);
+ return offset;
+}
+
+static int
+samr_dissect_set_information_alias_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+ return offset;
+}
+
+static int
+samr_dissect_CRYPT_PASSWORD(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_samr_crypt_password, tvb, offset, 516,
+ TRUE);
+ offset += 516;
+ return offset;
+}
+
+static int
+samr_dissect_CRYPT_HASH(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_samr_crypt_hash, tvb, offset, 16,
+ TRUE);
+ offset += 16;
+ return offset;
+}
+
+#define NT_BLOCK_SIZE 516
+
+static void
+samr_dissect_decrypted_NT_PASSCHANGE_BLOCK(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ guint32 new_password_len = 0;
+ guint32 pseudorandom_len = 0;
+ const char *printable_password;
+ guint16 bc;
+ int result_length;
+
+ /* The length of the new password is represented in the last four
+ octets of the decrypted buffer. Since the password length cannot
+ exceed 512, we can check the contents of those bytes to determine
+ if decryption was successful. If the decrypted contents of those
+ four bytes is less than 512, then there is a 99% chance that
+ we decrypted the buffer successfully. Of course, this isn't good
+ enough for a security application, (NT uses the "verifier" field
+ to come to the same conclusion), but it should be good enough for
+ our dissector. */
+
+ new_password_len = tvb_get_letohl(tvb, 512);
+
+ if (new_password_len <= 512)
+ {
+ /* Decryption successful */
+ proto_tree_add_text (tree, tvb, offset, -1,
+ "Decryption of NT Password Encrypted block successful");
+
+ /* Whatever is before the password is pseudorandom data. We calculate
+ the length by examining the password length (at the end), and working
+ backward */
+ pseudorandom_len = NT_BLOCK_SIZE - new_password_len - 4;
+
+ /* Pseudorandom data padding up to password */
+ proto_tree_add_item(tree, hf_samr_nt_passchange_block_pseudorandom,
+ tvb, offset, pseudorandom_len, TRUE);
+ offset += pseudorandom_len;
+
+ /* The new password itself */
+ bc = new_password_len;
+ printable_password = get_unicode_or_ascii_string(tvb, &offset,
+ TRUE,
+ &result_length,
+ FALSE, TRUE, &bc);
+ proto_tree_add_string(tree, hf_samr_nt_passchange_block_newpass,
+ tvb, offset, result_length,
+ printable_password);
+ offset += new_password_len;
+
+ /* Length of password */
+ proto_tree_add_item(tree, hf_samr_nt_passchange_block_newpass_len,
+ tvb, offset, 4, TRUE);
+ }
+ else
+ {
+ /* Decryption failure. Just show the encrypted block */
+ proto_tree_add_text (tree, tvb, offset, -1,
+ "Decryption of NT Passchange block failed");
+
+ proto_tree_add_item(tree, hf_samr_nt_passchange_block_decrypted, tvb,
+ offset, NT_BLOCK_SIZE, TRUE);
+ }
+}
+
+static int
+samr_dissect_NT_PASSCHANGE_BLOCK(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+ size_t password_len;
+ unsigned char *password_unicode;
+ size_t password_len_unicode;
+ unsigned char password_md4_hash[16];
+ guint8 *block;
+ tvbuff_t *decr_tvb; /* Used to store decrypted buffer */
+ rc4_state_struct rc4_state;
+ guint i;
+
+ /* This implements the the algorithm discussed in lkcl -"DCE/RPC
+ over SMB" page 257. Note that this code does not properly support
+ Unicode. */
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ /* Put in a protocol tree entry for the encrypted block. */
+ proto_tree_add_text(tree, tvb, offset, NT_BLOCK_SIZE,
+ "Encrypted NT Password Block");
+
+ if (nt_password[0] != '\0') {
+ /* We have an NT password, so we can decrypt the password
+ change block. */
+
+ /* Convert the password provided in the Ethereal GUI to Unicode
+ (UCS-2). Since the input is always ASCII, we can just fake
+ it and pad every other byte with a NUL. If we ever support
+ UTF-8 in the GUI, we would have to perform a real UTF-8 to
+ UCS-2 conversion */
+ password_len = strlen(nt_password);
+ password_len_unicode = password_len*2;
+ password_unicode = g_malloc(password_len_unicode);
+ for (i = 0; i < password_len; i++) {
+ password_unicode[i*2] = nt_password[i];
+ password_unicode[i*2+1] = 0;
+ }
+
+ /* Run MD4 against the resulting Unicode password. This will
+ be used to perform RC4 decryption on the password change
+ block. Then free the Unicode password, as we're done
+ with it. */
+ crypt_md4(password_md4_hash, password_unicode,
+ password_len_unicode);
+ g_free(password_unicode);
+
+ /* Copy the block into a temporary buffer so we can decrypt
+ it */
+ block = g_malloc(NT_BLOCK_SIZE);
+ memset(block, 0, NT_BLOCK_SIZE);
+ tvb_memcpy(tvb, block, offset, NT_BLOCK_SIZE);
+
+ /* RC4 decrypt the block with the old NT password hash */
+ crypt_rc4_init(&rc4_state, password_md4_hash, 16);
+ crypt_rc4(&rc4_state, block, NT_BLOCK_SIZE);
+
+ /* Show the decrypted buffer in a new window */
+ decr_tvb = tvb_new_real_data(block, NT_BLOCK_SIZE,
+ NT_BLOCK_SIZE);
+ tvb_set_free_cb(decr_tvb, g_free);
+ tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
+ add_new_data_source(pinfo, decr_tvb,
+ "Decrypted NT Password Block");
+
+ /* Dissect the decrypted block */
+ samr_dissect_decrypted_NT_PASSCHANGE_BLOCK(decr_tvb, 0, pinfo,
+ tree, drep);
+ }
+ offset += NT_BLOCK_SIZE;
+ return offset;
+}
+
+static int
+samr_dissect_LM_PASSCHANGE_BLOCK(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ /* Right now, this just dumps the output. In the long term, we can use
+ the algorithm discussed in lkcl -"DCE/RPC over SMB" page 257 to
+ actually decrypt the block */
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_samr_lm_passchange_block, tvb, offset,
+ 516, TRUE);
+ offset += 516;
+ return offset;
+}
+
+static int
+samr_dissect_LM_VERIFIER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ /* Right now, this just dumps the output. In the long term, we can use
+ the algorithm discussed in lkcl -"DCE/RPC over SMB" page 257 to
+ actually validate the verifier */
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_samr_lm_verifier, tvb, offset, 16,
+ TRUE);
+ offset += 16;
+ return offset;
+}
+
+
+static int
+samr_dissect_NT_VERIFIER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di;
+
+ /* Right now, this just dumps the output. In the long term, we can use
+ the algorithm discussed in lkcl -"DCE/RPC over SMB" page 257 to
+ actually validate the verifier */
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_samr_nt_verifier, tvb, offset, 16,
+ TRUE);
+ offset += 16;
+ return offset;
+}
+
+
+static int
+samr_dissect_oem_change_password_user2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_STRING, NDR_POINTER_UNIQUE,
+ "Server", hf_samr_server);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_STRING, NDR_POINTER_REF,
+ "Account Name", hf_samr_acct_name);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_CRYPT_PASSWORD, NDR_POINTER_UNIQUE,
+ "Password", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+ "Hash", -1);
+ return offset;
+}
+
+static int
+samr_dissect_oem_change_password_user2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_unicode_change_password_user2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_PASSWORD_INFO, NDR_POINTER_REF,
+ "PASSWORD_INFO:", -1);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_samr_server, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
+ "Account Name", hf_samr_acct_name);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_NT_PASSCHANGE_BLOCK, NDR_POINTER_UNIQUE,
+ "New NT Password Encrypted Block", -1);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_NT_VERIFIER, NDR_POINTER_UNIQUE,
+ "NT Password Verifier", -1);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_lm_change, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_LM_PASSCHANGE_BLOCK, NDR_POINTER_UNIQUE,
+ "New Lan Manager Password Encrypted Block", -1);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_LM_VERIFIER, NDR_POINTER_UNIQUE,
+ "Lan Manager Password Verifier", -1);
+ return offset;
+}
+
+static int
+samr_dissect_unicode_change_password_user2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_set_boot_key_information_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_short, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_UNIQUE,
+ "Unknown", hf_samr_unknown_string);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_UNIQUE,
+ "Unknown", hf_samr_unknown_string);
+ return offset;
+}
+
+static int
+samr_dissect_set_boot_key_information_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_create_user2_in_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
+ "Account Name", hf_samr_acct_name);
+
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_user_access_mask_info, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_create_user2_in_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access_granted,
+ &samr_user_access_mask_info, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
+ "CreateUser2 handle");
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": CreateUser2 handle");
+ }
+
+ return offset;
+}
+
+static int
+samr_dissect_get_display_enumeration_index2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
+ "Account Name", hf_samr_acct_name);
+ return offset;
+}
+
+static int
+samr_dissect_get_display_enumeration_index2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_index, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+ return offset;
+}
+
+static int
+samr_dissect_change_password_user_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+ "Hash", -1);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+ "Hash", -1);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+ "Hash", -1);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+ "Hash", -1);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+ "Hash", -1);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_CRYPT_HASH, NDR_POINTER_UNIQUE,
+ "Hash", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_change_password_user_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_set_member_attributes_of_group_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_attrib, NULL);
+ return offset;
+}
+
+static int
+samr_dissect_set_member_attributes_of_group_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_GROUP_INFO_1 (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_group_name, 0);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_group_num_of_members, NULL);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_group_desc, 0);
+ return offset;
+}
+
+static int
+samr_dissect_GROUP_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "GROUP_INFO:");
+ tree = proto_item_add_subtree(item, ett_samr_group_info);
+ }
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+ switch(level){
+ case 1:
+ offset = samr_dissect_GROUP_INFO_1(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 2:
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_group_name, 0);
+ break;
+ case 3:
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_attrib, NULL);
+ break;
+ case 4:
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_group_desc, 0);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_GROUP_INFO_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_GROUP_INFO, NDR_POINTER_UNIQUE,
+ "GROUP_INFO", -1);
+ return offset;
+}
+
+static int
+samr_dissect_query_information_group_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_query_information_group_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_GROUP_INFO_ptr, NDR_POINTER_REF,
+ "GROUP_INFO", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+ return offset;
+}
+
+static int
+samr_dissect_set_information_group_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_GROUP_INFO, NDR_POINTER_REF,
+ "GROUP_INFO", -1);
+ return offset;
+}
+
+static int
+samr_dissect_set_information_group_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_domain_password_information_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_PASSWORD_INFO, NDR_POINTER_REF,
+ "PASSWORD_INFO:", -1);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_samr_domain, 0);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_domain_password_information_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_PASSWORD_INFO, NDR_POINTER_REF,
+ "PASSWORD_INFO:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_DOMAIN_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ ALIGN_TO_4_BYTES; /* strcture starts with short, but is aligned for longs */
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DOMAIN_INFO_1:");
+ tree = proto_item_add_subtree(item, ett_samr_domain_info_1);
+ }
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_samr_min_pwd_len, NULL);
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_samr_pwd_history_len, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_max_pwd_age);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_min_pwd_age);
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_DOMAIN_INFO_2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DOMAIN_INFO_2:");
+ tree = proto_item_add_subtree(item, ett_samr_domain_info_2);
+ }
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_time);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_string, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_domain, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_controller, 0);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_time);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_num_users, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_num_groups, NULL);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_num_aliases, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_DOMAIN_INFO_8(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DOMAIN_INFO_8:");
+ tree = proto_item_add_subtree(item, ett_samr_domain_info_8);
+ }
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_max_pwd_age);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_min_pwd_age);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_REPLICATION_STATUS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "REPLICATION_STATUS:");
+ tree = proto_item_add_subtree(item, ett_samr_replication_status);
+ }
+
+ offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_hyper, NULL);
+ offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_hyper, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_short, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_DOMAIN_INFO_11(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DOMAIN_INFO_11:");
+ tree = proto_item_add_subtree(item, ett_samr_domain_info_11);
+ }
+
+ offset = samr_dissect_DOMAIN_INFO_2(
+ tvb, offset, pinfo, tree, drep);
+ offset = samr_dissect_REPLICATION_STATUS(
+ tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_DOMAIN_INFO_13(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DOMAIN_INFO_13:");
+ tree = proto_item_add_subtree(item, ett_samr_domain_info_13);
+ }
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_time);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+samr_dissect_DOMAIN_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "DOMAIN_INFO:");
+ tree = proto_item_add_subtree(item, ett_samr_domain_info);
+ }
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ ALIGN_TO_4_BYTES; /* all union arms aligned to 4 bytes, case 7 and 9 need this */
+ switch(level){
+ case 1:
+ offset = samr_dissect_DOMAIN_INFO_1(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 2:
+ offset = samr_dissect_DOMAIN_INFO_2(
+ tvb, offset, pinfo, tree, drep);
+ break;
+
+ case 3:
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_time);
+ break;
+ case 4:
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_unknown_string, 0);
+ break;
+
+ case 5:
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_domain, 0);
+ break;
+
+ case 6:
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, hf_samr_controller, 0);
+ break;
+
+ case 7:
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_short, NULL);
+ break;
+ case 8:
+ offset = samr_dissect_DOMAIN_INFO_8(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 9:
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_short, NULL);
+ break;
+ case 11:
+ offset = samr_dissect_DOMAIN_INFO_11(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 12:
+ offset = samr_dissect_REPLICATION_STATUS(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 13:
+ offset = samr_dissect_DOMAIN_INFO_13(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_set_information_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = samr_dissect_DOMAIN_INFO(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+samr_dissect_set_information_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_create_group_in_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
+ "Group Name", hf_samr_group_name);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_group_access_mask_info, NULL);
+
+ return offset;
+
+
+}
+
+static int
+samr_dissect_create_group_in_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
+ "CreateGroup handle");
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": CreateGroup handle");
+ }
+ return offset;
+
+
+}
+
+
+static int
+samr_dissect_lookup_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
+ "Domain", hf_samr_domain);
+
+ return offset;
+}
+
+static int
+samr_dissect_lookup_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_SID_no_hf, NDR_POINTER_UNIQUE,
+ "SID pointer", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+ return offset;
+}
+
+static int
+samr_dissect_index(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+
+ return offset;
+}
+
+
+static int
+samr_dissect_INDEX_ARRAY_value (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_index);
+
+ return offset;
+}
+
+static char *
+plural_ending(const char *string)
+{
+ size_t string_len;
+
+ string_len = strlen(string);
+ if (string_len > 0 && string[string_len - 1] == 's') {
+ /* String ends with "s" - pluralize by adding "es" */
+ return "es";
+ } else {
+ /* Field name doesn't end with "s" - pluralize by adding "s" */
+ return "s";
+ }
+}
+
+static int
+samr_dissect_INDEX_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ char *field_name;
+ guint32 count;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ dcerpc_info *di;
+ char str[256];
+
+ di=pinfo->private_data;
+
+ field_name = proto_registrar_get_name(di->hf_index);
+ snprintf(str, 255, "INDEX_ARRAY: %s%s:", field_name,
+ plural_ending(field_name));
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "%s", str);
+ tree = proto_item_add_subtree(item, ett_samr_index_array);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_count, &count);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_INDEX_ARRAY_value, NDR_POINTER_UNIQUE,
+ str, di->hf_index);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_get_alias_membership_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
+ "PSID_ARRAY:", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_alias_membership_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_INDEX_ARRAY, NDR_POINTER_REF,
+ "INDEX_ARRAY:", hf_samr_alias);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_IDX_AND_NAME(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ char str[256];
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+
+ snprintf(str, 255, "IDX_AND_NAME: %s:",proto_registrar_get_name(di->hf_index));
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "%s",str);
+ tree = proto_item_add_subtree(item, ett_samr_idx_and_name);
+ }
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_index, NULL);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo,
+ tree, drep, di->hf_index, 4);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_IDX_AND_NAME_entry (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_IDX_AND_NAME);
+
+ return offset;
+}
+
+
+static int
+samr_dissect_IDX_AND_NAME_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ char *field_name;
+ guint32 count;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ dcerpc_info *di;
+ char str[256];
+
+ di=pinfo->private_data;
+
+ field_name = proto_registrar_get_name(di->hf_index);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "IDX_AND_NAME_ARRAY: %s%s:", field_name,
+ plural_ending(field_name));
+ tree = proto_item_add_subtree(item, ett_samr_idx_and_name_array);
+ }
+
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_count, &count);
+ snprintf(str, 255, "IDX_AND_NAME pointer: %s%s:", field_name,
+ plural_ending(field_name));
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_IDX_AND_NAME_entry, NDR_POINTER_UNIQUE,
+ str, di->hf_index);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_IDX_AND_NAME_ARRAY_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ char *field_name;
+ char str[256];
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+
+ field_name = proto_registrar_get_name(di->hf_index);
+ snprintf(str, 255, "IDX_AND_NAME_ARRAY pointer: %s%s:", field_name,
+ plural_ending(field_name));
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_IDX_AND_NAME_ARRAY, NDR_POINTER_UNIQUE,
+ str, di->hf_index);
+ return offset;
+}
+
+static int
+samr_dissect_enum_domains_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Resume Handle", hf_samr_resume_hnd);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_pref_maxsize, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_enum_domains_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Resume Handle:", hf_samr_resume_hnd);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_IDX_AND_NAME_ARRAY_ptr, NDR_POINTER_REF,
+ "IDX_AND_NAME_ARRAY:", hf_samr_domain);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Entries:", hf_samr_entries);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_enum_dom_groups_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Resume Handle:", hf_samr_resume_hnd);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_pref_maxsize, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_enum_dom_groups_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Resume Handle:", hf_samr_resume_hnd);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_IDX_AND_NAME_ARRAY_ptr, NDR_POINTER_REF,
+ "IDX_AND_NAME_ARRAY:", hf_samr_group_name);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Entries:", hf_samr_entries);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_enum_dom_aliases_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Resume Handle:", hf_samr_resume_hnd);
+
+ offset = dissect_ndr_nt_acct_ctrl(
+ tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int
+samr_dissect_enum_dom_aliases_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Resume Handle:", hf_samr_resume_hnd);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_IDX_AND_NAME_ARRAY_ptr, NDR_POINTER_REF,
+ "IDX_AND_NAME_ARRAY:", hf_samr_alias_name);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Entries:", hf_samr_entries);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_members_in_alias_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_get_members_in_alias_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
+ "PSID_ARRAY:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_1:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_1);
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_full_name, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_primary_group_rid, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_desc, 0);
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_comment, 0);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_2:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_2);
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_comment, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_string, 0);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_country, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_codepage, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_3(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_3:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_3);
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_full_name, 0);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_primary_group_rid, NULL);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_home, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_home_drive, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_script, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_profile, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_workstations, 0);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_logon_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_logoff_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_pwd_last_set_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_pwd_can_change_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_pwd_must_change_time);
+ offset = dissect_ndr_nt_LOGON_HOURS(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_bad_pwd_count, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_logon_count, NULL);
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_5(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_5:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_5);
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_full_name, 0);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_primary_group_rid, NULL);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_home, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_home_drive, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_script, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_desc, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_workstations, 0);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_logon_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_logoff_time);
+ offset = dissect_ndr_nt_LOGON_HOURS(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_bad_pwd_count, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_logon_count, NULL);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_pwd_last_set_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_expiry_time);
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_6(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_6:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_6);
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_full_name, 0);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_10(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_10:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_10);
+ }
+
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_home, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_home_drive, 0);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+samr_dissect_USER_INFO_18(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_18:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_18);
+ }
+
+ offset = samr_dissect_CRYPT_HASH(tvb, offset, pinfo, tree, drep);
+ offset = samr_dissect_CRYPT_HASH(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_19(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_19:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_19);
+ }
+
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_logon_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_logoff_time);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_bad_pwd_count, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_logon_count, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_BUFFER_entry(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+ return offset;
+}
+
+
+static int
+samr_dissect_BUFFER_buffer(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "BUFFER:");
+ tree = proto_item_add_subtree(item, ett_samr_buffer_buffer);
+ }
+
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_BUFFER_entry);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+
+ return offset;
+}
+
+static int
+samr_dissect_BUFFER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "BUFFER:");
+ tree = proto_item_add_subtree(item, ett_samr_buffer);
+ }
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_count, NULL);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_BUFFER_buffer, NDR_POINTER_UNIQUE,
+ "BUFFER", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_21(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_21:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_21);
+ }
+
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_logon_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_logoff_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_pwd_last_set_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_expiry_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_pwd_can_change_time);
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_pwd_must_change_time);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 2);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_full_name, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_home, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_home_drive, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_script, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_profile, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_desc, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_workstations, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_comment, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_callback, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_string, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_string, 0);
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_string, 0);
+ offset = samr_dissect_BUFFER(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_primary_group_rid, NULL);
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+ offset = dissect_ndr_nt_LOGON_HOURS(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_bad_pwd_count, NULL);
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_logon_count, NULL);
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_samr_country, NULL);
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
+ hf_samr_codepage, NULL);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_nt_pwd_set, NULL);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_lm_pwd_set, NULL);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_pwd_expired, NULL);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_22(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_22:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_22);
+ }
+
+ offset = samr_dissect_USER_INFO_21(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint64 (tvb, offset, pinfo, tree, drep,
+ hf_samr_revision, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_23(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_23:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_23);
+ }
+
+ offset = samr_dissect_USER_INFO_21(tvb, offset, pinfo, tree, drep);
+ offset = samr_dissect_CRYPT_PASSWORD(tvb, offset, pinfo, tree, drep);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_24(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_24:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_24);
+ }
+
+ offset = samr_dissect_CRYPT_PASSWORD(tvb, offset, pinfo, tree, drep);
+ offset = dissect_ndr_uint8 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_char, NULL);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+samr_dissect_USER_INFO_25(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+
+ if(parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO_25:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info_25);
+ }
+
+ offset = samr_dissect_USER_INFO_21(tvb, offset, pinfo, tree, drep);
+
+ proto_tree_add_item(tree, hf_samr_crypt_password, tvb, offset, 532,
+ TRUE);
+ offset += 532;
+
+ proto_item_set_len(item, offset - old_offset);
+
+ return offset;
+}
+
+
+static int
+samr_dissect_USER_INFO (tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+ guint16 level;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "USER_INFO:");
+ tree = proto_item_add_subtree(item, ett_samr_user_info);
+ }
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ switch(level){
+ case 1:
+ offset = samr_dissect_USER_INFO_1(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 2:
+ offset = samr_dissect_USER_INFO_2(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 3:
+ offset = samr_dissect_USER_INFO_3(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 4:
+ offset = dissect_ndr_nt_LOGON_HOURS(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 5:
+ offset = samr_dissect_USER_INFO_5(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 6:
+ offset = samr_dissect_USER_INFO_6(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 7:
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_samr_acct_name, 0);
+ break;
+ case 8:
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_samr_full_name, 0);
+ break;
+ case 9:
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_primary_group_rid, NULL);
+ break;
+ case 10:
+ offset = samr_dissect_USER_INFO_10(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 11:
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_samr_script, 0);
+ break;
+ case 12:
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_samr_profile, 0);
+ break;
+ case 13:
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_samr_acct_desc, 0);
+ break;
+ case 14:
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_samr_workstations, 0);
+ break;
+ case 16:
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree,
+ drep);
+ break;
+ case 17:
+ offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_expiry_time);
+ break;
+ case 18:
+ offset = samr_dissect_USER_INFO_18(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 19:
+ offset = samr_dissect_USER_INFO_19(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 20:
+ offset = dissect_ndr_counted_string(
+ tvb, offset, pinfo, tree, drep, hf_samr_callback, 0);
+ break;
+ case 21:
+ offset = samr_dissect_USER_INFO_21(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 22:
+ offset = samr_dissect_USER_INFO_22(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 23:
+ offset = samr_dissect_USER_INFO_23(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ case 24:
+ offset = samr_dissect_USER_INFO_24(
+ tvb, offset, pinfo, tree, drep);
+ case 25:
+ offset = samr_dissect_USER_INFO_25(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_USER_INFO_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_INFO, NDR_POINTER_UNIQUE,
+ "USER_INFO pointer", -1);
+ return offset;
+}
+
+static int
+samr_dissect_set_information_user2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_INFO, NDR_POINTER_REF,
+ "USER_INFO:", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_set_information_user2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_query_information_user2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ return offset;
+}
+
+static int
+samr_dissect_query_information_user2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_INFO_ptr, NDR_POINTER_REF,
+ "USER_INFO:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_MEMBER_ARRAY_type(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_type, NULL);
+
+ return offset;
+}
+
+
+static int
+samr_dissect_MEMBER_ARRAY_types(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "MEMBER_ARRAY_types:");
+ tree = proto_item_add_subtree(item, ett_samr_member_array_types);
+ }
+
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_MEMBER_ARRAY_type);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+
+ return offset;
+}
+
+static int
+samr_dissect_MEMBER_ARRAY_rid(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+
+ return offset;
+}
+
+
+static int
+samr_dissect_MEMBER_ARRAY_rids(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "MEMBER_ARRAY_rids:");
+ tree = proto_item_add_subtree(item, ett_samr_member_array_rids);
+ }
+
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_MEMBER_ARRAY_rid);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+
+ return offset;
+}
+
+static int
+samr_dissect_MEMBER_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 count;
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "MEMBER_ARRAY:");
+ tree = proto_item_add_subtree(item, ett_samr_member_array);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_count, &count);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_MEMBER_ARRAY_rids, NDR_POINTER_UNIQUE,
+ "RIDs", -1);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_MEMBER_ARRAY_types, NDR_POINTER_UNIQUE,
+ "Types", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+samr_dissect_MEMBER_ARRAY_ptr(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_MEMBER_ARRAY, NDR_POINTER_UNIQUE,
+ "MEMBER_ARRAY", -1);
+ return offset;
+}
+
+static int
+samr_dissect_query_groupmem_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_query_groupmem_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_MEMBER_ARRAY_ptr, NDR_POINTER_REF,
+ "MEMBER_ARRAY:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_set_sec_object_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 info_type;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_info_type, &info_type);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", info type %d", info_type);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ sam_dissect_SAM_SECURITY_DESCRIPTOR, NDR_POINTER_REF,
+ "SAM_SECURITY_DESCRIPTOR pointer: ", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_set_sec_object_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_query_sec_object_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 info_type;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_info_type, &info_type);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", info_type %d", info_type);
+
+ return offset;
+}
+
+static int
+samr_dissect_query_sec_object_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ sam_dissect_SAM_SECURITY_DESCRIPTOR, NDR_POINTER_UNIQUE,
+ "SAM_SECURITY_DESCRIPTOR pointer: ", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_LOOKUP_NAMES_name(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 1);
+ return offset;
+}
+
+static int
+samr_dissect_LOOKUP_NAMES(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "NAMES:");
+ tree = proto_item_add_subtree(item, ett_samr_names);
+ }
+
+ offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_LOOKUP_NAMES_name);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+samr_dissect_lookup_names_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_count, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_LOOKUP_NAMES, NDR_POINTER_REF,
+ "LOOKUP_NAMES:", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_lookup_names_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_INDEX_ARRAY, NDR_POINTER_REF,
+ "Rids:", hf_samr_rid);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_INDEX_ARRAY, NDR_POINTER_REF,
+ "Types:", hf_samr_type);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_LOOKUP_RIDS_rid(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_LOOKUP_RIDS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "RIDS:");
+ tree = proto_item_add_subtree(item, ett_samr_rids);
+ }
+
+ offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_LOOKUP_RIDS_rid);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+samr_dissect_lookup_rids_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_count, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_LOOKUP_RIDS, NDR_POINTER_REF,
+ "LOOKUP_RIDS:", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_UNICODE_STRING_ARRAY_name(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_counted_string(tvb, offset, pinfo, tree, drep,
+ hf_samr_acct_name, 0);
+ return offset;
+}
+
+static int
+samr_dissect_UNICODE_STRING_ARRAY_names(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ samr_dissect_UNICODE_STRING_ARRAY_name);
+ return offset;
+}
+
+static int
+samr_dissect_UNICODE_STRING_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ int old_offset=offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "NAMES:");
+ tree = proto_item_add_subtree(item, ett_samr_names);
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_samr_count, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_UNICODE_STRING_ARRAY_names, NDR_POINTER_UNIQUE,
+ "Strings", -1);
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+
+ return offset;
+}
+
+
+static int
+samr_dissect_lookup_rids_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_UNICODE_STRING_ARRAY, NDR_POINTER_REF,
+ "RIDs:", hf_samr_rid);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_INDEX_ARRAY, NDR_POINTER_REF,
+ "Types:", hf_samr_type);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_close_hnd_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ char *name;
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_samr_hnd, &policy_hnd,
+ NULL, FALSE, TRUE);
+
+ dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL, pinfo->fd->num);
+
+ if (name != NULL && check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", %s", name);
+
+ return offset;
+}
+
+static int
+samr_dissect_close_hnd_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_shutdown_sam_server_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_shutdown_sam_server_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_delete_dom_group_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_delete_dom_group_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_remove_member_from_group_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_group, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_remove_member_from_group_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_delete_dom_alias_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_delete_dom_alias_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_add_alias_member_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_SID_no_hf, NDR_POINTER_REF,
+ "SID pointer", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_add_alias_member_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_remove_alias_member_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_SID_no_hf, NDR_POINTER_REF,
+ "SID pointer", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_remove_alias_member_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_delete_dom_user_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_delete_dom_user_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_test_private_fns_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_test_private_fns_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_test_private_fns_user_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ return offset;
+}
+
+static int
+samr_dissect_test_private_fns_user_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_remove_member_from_foreign_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_SID_no_hf, NDR_POINTER_REF,
+ "SID pointer", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_remove_member_from_foreign_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_remove_multiple_members_from_alias_rqst(tvbuff_t *tvb,
+ int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
+ "PSID_ARRAY:", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_remove_multiple_members_from_alias_reply(tvbuff_t *tvb,
+ int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_open_group_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 rid;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_group_access_mask_info, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, &rid);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", rid 0x%x", rid);
+
+ dcv->private_data = GINT_TO_POINTER(rid);
+
+ return offset;
+}
+
+static int
+samr_dissect_open_group_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 rid = GPOINTER_TO_INT(dcv->private_data);
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+ char *pol_name;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ if (rid)
+ pol_name = g_strdup_printf("OpenGroup(rid 0x%x)", rid);
+ else
+ pol_name = g_strdup("OpenGroup handle");
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": %s", pol_name);
+
+ g_free(pol_name);
+ }
+
+ return offset;
+}
+
+static int
+samr_dissect_open_alias_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 rid;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_alias_access_mask_info, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, &rid);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", rid 0x%x", rid);
+
+ dcv->private_data = GINT_TO_POINTER(rid);
+
+ return offset;
+}
+
+static int
+samr_dissect_open_alias_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ char *pol_name;
+ proto_item *hnd_item;
+ guint32 status;
+ guint32 rid;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ rid = GPOINTER_TO_INT(dcv->private_data);
+
+ if (rid)
+ pol_name = g_strdup_printf("OpenAlias(rid 0x%x)", rid);
+ else
+ pol_name = g_strdup_printf("OpenAlias handle");
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": %s", pol_name);
+
+ g_free(pol_name);
+ }
+
+ return offset;
+}
+
+static int
+samr_dissect_add_multiple_members_to_alias_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_nt_PSID_ARRAY, NDR_POINTER_REF,
+ "PSID_ARRAY:", -1);
+
+ return offset;
+}
+
+static int
+samr_dissect_add_multiple_members_to_alias_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_create_user_in_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_ndr_counted_string_ptr, NDR_POINTER_REF,
+ "Account Name", hf_samr_acct_name);
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_user_access_mask_info, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_create_user_in_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 rid;
+ guint32 status;
+ char *pol_name;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_rid, &rid);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ pol_name = g_strdup_printf("CreateUser(rid 0x%x)", rid);
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": %s", pol_name);
+
+ g_free(pol_name);
+ }
+
+ return offset;
+}
+
+
+static int
+samr_dissect_enum_users_in_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Resume Handle", hf_samr_resume_hnd);
+
+ offset = dissect_ndr_nt_acct_ctrl(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_pref_maxsize, NULL);
+
+ return offset;
+}
+
+
+static int
+samr_dissect_enum_users_in_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Resume Handle:", hf_samr_resume_hnd);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_IDX_AND_NAME_ARRAY_ptr, NDR_POINTER_REF,
+ "IDX_AND_NAME_ARRAY:", hf_samr_acct_name);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_pointer_long, NDR_POINTER_REF,
+ "Entries:", hf_samr_entries);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+
+
+static int
+samr_dissect_query_information_domain_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ return offset;
+}
+
+static int
+samr_dissect_query_information_domain_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /*
+ * Yes, in at least one capture with replies from a W2K server,
+ * this was, indeed, a UNIQUE pointer, not a REF pointer.
+ */
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_DOMAIN_INFO, NDR_POINTER_UNIQUE,
+ "DOMAIN_INFO pointer", hf_samr_domain);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+static int
+samr_dissect_query_information_user_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ guint16 level;
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
+ hf_samr_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ return offset;
+}
+
+static int
+samr_dissect_query_information_user_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ samr_dissect_USER_INFO_ptr, NDR_POINTER_REF,
+ "USER_INFO:", -1);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, NULL);
+
+ return offset;
+}
+
+
+static int
+samr_dissect_connect5_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
+ "Server", hf_samr_server, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_samr_access,
+ &samr_connect_access_mask_info, NULL);
+
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ return offset;
+
+}
+
+
+static int
+samr_dissect_connect5_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+ char *server = (char *)dcv->private_data, *pol_name;
+
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_samr_unknown_long, NULL);
+
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_samr_hnd, &policy_hnd,
+ &hnd_item, TRUE, FALSE);
+
+ offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
+ hf_samr_rc, &status);
+
+ if (status == 0) {
+ if (server)
+ pol_name = g_strdup_printf("Connect5(%s)", server);
+ else
+ pol_name = g_strdup("Connect5 handle");
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ if (hnd_item != NULL)
+ proto_item_append_text(hnd_item, ": %s", pol_name);
+
+ g_free(pol_name);
+ }
+
+ return offset;
+}
+
+
+
+static dcerpc_sub_dissector dcerpc_samr_dissectors[] = {
+ { SAMR_CONNECT, "SamrConnect",
+ samr_dissect_connect_anon_rqst,
+ samr_dissect_connect_anon_reply },
+ { SAMR_CLOSE_HND, "SamrCloseHandle",
+ samr_dissect_close_hnd_rqst,
+ samr_dissect_close_hnd_reply },
+ { SAMR_SET_SEC_OBJECT, "SamrSetSecurityObject",
+ samr_dissect_set_sec_object_rqst,
+ samr_dissect_set_sec_object_reply },
+ { SAMR_QUERY_SEC_OBJECT, "SamrQuerySecurityObject",
+ samr_dissect_query_sec_object_rqst,
+ samr_dissect_query_sec_object_reply },
+ { SAMR_SHUTDOWN_SAM_SERVER, "SamrShutdownSamServer",
+ samr_dissect_shutdown_sam_server_rqst,
+ samr_dissect_shutdown_sam_server_reply },
+ { SAMR_LOOKUP_DOMAIN, "SamrLookupDomainInSamServer",
+ samr_dissect_lookup_domain_rqst,
+ samr_dissect_lookup_domain_reply },
+ { SAMR_ENUM_DOMAINS, "SamrEnumerateDomainsInSamServer",
+ samr_dissect_enum_domains_rqst,
+ samr_dissect_enum_domains_reply },
+ { SAMR_OPEN_DOMAIN, "SamrOpenDomain",
+ samr_dissect_open_domain_rqst,
+ samr_dissect_open_domain_reply },
+ { SAMR_QUERY_DOMAIN_INFO, "SamrQueryInformationDomain",
+ samr_dissect_query_information_alias_rqst,
+ samr_dissect_query_information_domain_reply },
+ { SAMR_SET_DOMAIN_INFO, "SamrSetInformationDomain",
+ samr_dissect_set_information_domain_rqst,
+ samr_dissect_set_information_domain_reply },
+ { SAMR_CREATE_DOM_GROUP, "SamrCreateGroupInDomain",
+ samr_dissect_create_group_in_domain_rqst,
+ samr_dissect_create_group_in_domain_reply },
+ { SAMR_ENUM_DOM_GROUPS, "SamrEnumerateGroupsInDomain",
+ samr_dissect_enum_dom_groups_rqst,
+ samr_dissect_enum_dom_groups_reply },
+ { SAMR_CREATE_USER_IN_DOMAIN, "SamrCreateUserInDomain",
+ samr_dissect_create_user_in_domain_rqst,
+ samr_dissect_create_user_in_domain_reply },
+ { SAMR_ENUM_DOM_USERS, "SamrEnumerateUsersInDomain",
+ samr_dissect_enum_users_in_domain_rqst,
+ samr_dissect_enum_users_in_domain_reply },
+ { SAMR_CREATE_DOM_ALIAS, "SamrCreateAliasInDomain",
+ samr_dissect_create_alias_in_domain_rqst,
+ samr_dissect_create_alias_in_domain_reply },
+ { SAMR_ENUM_DOM_ALIASES, "SamrEnumerateAliasesInDomain",
+ samr_dissect_enum_dom_aliases_rqst,
+ samr_dissect_enum_dom_aliases_reply },
+ { SAMR_GET_ALIAS_MEMBERSHIP, "SamrGetAliasMembership",
+ samr_dissect_get_alias_membership_rqst,
+ samr_dissect_get_alias_membership_reply },
+ { SAMR_LOOKUP_NAMES, "SamrLookupNamesInDomain",
+ samr_dissect_lookup_names_rqst,
+ samr_dissect_lookup_names_reply },
+ { SAMR_LOOKUP_RIDS, "SamrLookupIdsInDomain",
+ samr_dissect_lookup_rids_rqst,
+ samr_dissect_lookup_rids_reply },
+ { SAMR_OPEN_GROUP, "SamrOpenGroup",
+ samr_dissect_open_group_rqst,
+ samr_dissect_open_group_reply },
+ { SAMR_QUERY_GROUPINFO, "SamrQueryInformationGroup",
+ samr_dissect_query_information_group_rqst,
+ samr_dissect_query_information_group_reply },
+ { SAMR_SET_GROUPINFO, "SamrSetInformationGroup",
+ samr_dissect_set_information_group_rqst,
+ samr_dissect_set_information_group_reply },
+ { SAMR_ADD_GROUPMEM, "SamrAddMemberToGroup",
+ samr_dissect_add_member_to_group_rqst,
+ samr_dissect_add_member_to_group_reply },
+ { SAMR_DELETE_DOM_GROUP, "SamrDeleteGroup",
+ samr_dissect_delete_dom_group_rqst,
+ samr_dissect_delete_dom_group_reply },
+ { SAMR_DEL_GROUPMEM, "SamrRemoveMemberFromGroup",
+ samr_dissect_remove_member_from_group_rqst,
+ samr_dissect_remove_member_from_group_reply },
+ { SAMR_QUERY_GROUPMEM, "SamrGetMembersInGroup",
+ samr_dissect_query_groupmem_rqst,
+ samr_dissect_query_groupmem_reply },
+ { SAMR_SET_MEMBER_ATTRIBUTES_OF_GROUP, "SamrSetMemberAttributesOfGroup",
+ samr_dissect_set_member_attributes_of_group_rqst,
+ samr_dissect_set_member_attributes_of_group_reply },
+ { SAMR_OPEN_ALIAS, "SamrOpenAlias",
+ samr_dissect_open_alias_rqst,
+ samr_dissect_open_alias_reply },
+ { SAMR_QUERY_ALIASINFO, "SamrQueryInformationAlias",
+ samr_dissect_query_information_alias_rqst,
+ samr_dissect_query_information_alias_reply },
+ { SAMR_SET_ALIASINFO, "SamrSetInformationAlias",
+ samr_dissect_set_information_alias_rqst,
+ samr_dissect_set_information_alias_reply },
+ { SAMR_DELETE_DOM_ALIAS, "SamrDeleteAlias",
+ samr_dissect_delete_dom_alias_rqst,
+ samr_dissect_delete_dom_alias_reply },
+ { SAMR_ADD_ALIASMEM, "SamrAddMemberToAlias",
+ samr_dissect_add_alias_member_rqst,
+ samr_dissect_add_alias_member_reply },
+ { SAMR_DEL_ALIASMEM, "SamrRemoveMemberFromAlias",
+ samr_dissect_remove_alias_member_rqst,
+ samr_dissect_remove_alias_member_reply },
+ { SAMR_GET_MEMBERS_IN_ALIAS, "SamrGetMembersInAlias",
+ samr_dissect_get_members_in_alias_rqst,
+ samr_dissect_get_members_in_alias_reply },
+ { SAMR_OPEN_USER, "SamrOpenUser",
+ samr_dissect_open_user_rqst,
+ samr_dissect_open_user_reply },
+ { SAMR_DELETE_DOM_USER, "SamrDeleteUser",
+ samr_dissect_delete_dom_user_rqst,
+ samr_dissect_delete_dom_user_reply },
+ { SAMR_QUERY_USERINFO, "SamrQueryInformationUser",
+ samr_dissect_query_information_user_rqst,
+ samr_dissect_query_information_user_reply },
+ { SAMR_SET_USERINFO, "SamrSetInformationUser",
+ samr_dissect_set_information_user2_rqst,
+ samr_dissect_set_information_user2_reply },
+ { SAMR_CHANGE_PASSWORD_USER, "SamrChangePasswordUser",
+ samr_dissect_change_password_user_rqst,
+ samr_dissect_change_password_user_reply },
+ { SAMR_GET_GROUPS_FOR_USER, "SamrGetGroupsForUser",
+ samr_dissect_get_groups_for_user_rqst,
+ samr_dissect_get_groups_for_user_reply },
+ { SAMR_QUERY_DISPINFO, "SamrQueryDisplayInformation",
+ samr_dissect_query_dispinfo_rqst,
+ samr_dissect_query_dispinfo_reply },
+ { SAMR_GET_DISPLAY_ENUMERATION_INDEX, "SamrGetDisplayEnumerationIndex",
+ samr_dissect_get_display_enumeration_index_rqst,
+ samr_dissect_get_display_enumeration_index_reply },
+ { SAMR_TEST_PRIVATE_FUNCTIONS_DOMAIN, "SamrTestPrivateFunctionsDomain",
+ samr_dissect_test_private_fns_domain_rqst,
+ samr_dissect_test_private_fns_domain_reply },
+ { SAMR_TEST_PRIVATE_FUNCTIONS_USER, "SamrTestPrivateFunctionsUser",
+ samr_dissect_test_private_fns_user_rqst,
+ samr_dissect_test_private_fns_user_reply },
+ { SAMR_GET_USRDOM_PWINFO, "SamrGetUserDomainPasswordInformation",
+ samr_dissect_get_usrdom_pwinfo_rqst,
+ samr_dissect_get_usrdom_pwinfo_reply },
+ { SAMR_REMOVE_MEMBER_FROM_FOREIGN_DOMAIN, "SamrRemoveMemberFromForeignDomain",
+ samr_dissect_remove_member_from_foreign_domain_rqst,
+ samr_dissect_remove_member_from_foreign_domain_reply },
+ { SAMR_QUERY_INFORMATION_DOMAIN2, "SamrQueryInformationDomain2",
+ samr_dissect_query_information_domain_rqst,
+ samr_dissect_query_information_domain_reply },
+ { SAMR_QUERY_INFORMATION_USER2, "SamrQueryInformationUser2",
+ samr_dissect_query_information_user2_rqst,
+ samr_dissect_query_information_user2_reply },
+ { SAMR_QUERY_DISPINFO2, "SamrQueryDisplayInformation2",
+ samr_dissect_query_dispinfo_rqst,
+ samr_dissect_query_dispinfo_reply },
+ { SAMR_GET_DISPLAY_ENUMERATION_INDEX2, "SamrGetDisplayEnumerationIndex2",
+ samr_dissect_get_display_enumeration_index2_rqst,
+ samr_dissect_get_display_enumeration_index2_reply },
+ { SAMR_CREATE_USER2_IN_DOMAIN, "SamrCreateUser2InDomain",
+ samr_dissect_create_user2_in_domain_rqst,
+ samr_dissect_create_user2_in_domain_reply },
+ { SAMR_QUERY_DISPINFO3, "SamrQueryDisplayInformation3",
+ samr_dissect_query_dispinfo_rqst,
+ samr_dissect_query_dispinfo_reply },
+ { SAMR_ADD_MULTIPLE_MEMBERS_TO_ALIAS, "SamrAddMultipleMembersToAlias",
+ samr_dissect_add_multiple_members_to_alias_rqst,
+ samr_dissect_add_multiple_members_to_alias_reply },
+ { SAMR_REMOVE_MULTIPLE_MEMBERS_FROM_ALIAS, "SamrRemoveMultipleMembersFromAlias",
+ samr_dissect_remove_multiple_members_from_alias_rqst,
+ samr_dissect_remove_multiple_members_from_alias_reply },
+ { SAMR_OEM_CHANGE_PASSWORD_USER2, "SamrOemChangePasswordUser2",
+ samr_dissect_oem_change_password_user2_rqst,
+ samr_dissect_oem_change_password_user2_reply },
+ { SAMR_UNICODE_CHANGE_PASSWORD_USER2, "SamrUnicodeChangePasswordUser2",
+ samr_dissect_unicode_change_password_user2_rqst,
+ samr_dissect_unicode_change_password_user2_reply },
+ { SAMR_GET_DOM_PWINFO, "SamrGetDomainPasswordInformation",
+ samr_dissect_get_domain_password_information_rqst,
+ samr_dissect_get_domain_password_information_reply },
+ { SAMR_CONNECT2, "SamrConnect2",
+ samr_dissect_connect2_rqst,
+ samr_dissect_connect2_3_4_reply },
+ { SAMR_SET_USERINFO2, "SamrSetInformationUser2",
+ samr_dissect_set_information_user2_rqst,
+ samr_dissect_set_information_user2_reply },
+ { SAMR_SET_BOOT_KEY_INFORMATION, "SamrSetBootKeyInformation",
+ samr_dissect_set_boot_key_information_rqst,
+ samr_dissect_set_boot_key_information_reply },
+ { SAMR_GET_BOOT_KEY_INFORMATION, "SamrGetBootKeyInformation",
+ samr_dissect_get_boot_key_information_rqst,
+ samr_dissect_get_boot_key_information_reply },
+ { SAMR_CONNECT3, "SamrConnect3",
+ samr_dissect_connect3_4_rqst,
+ samr_dissect_connect2_3_4_reply },
+ { SAMR_CONNECT4, "SamrConnect4",
+ samr_dissect_connect3_4_rqst,
+ samr_dissect_connect2_3_4_reply },
+ { SAMR_UNICODE_CHANGE_PASSWORD_USER3, "SamrUnicodeChangePasswordUser3",
+ NULL, NULL },
+ { SAMR_CONNECT5, "SamrConnect5",
+ samr_dissect_connect5_rqst,
+ samr_dissect_connect5_reply },
+ { SAMR_RID_TO_SID, "SamrRidToSid", NULL, NULL },
+ { SAMR_SET_DSRM_PASSWORD, "SamrSetDSRMPassword", NULL, NULL },
+ { SAMR_VALIDATE_PASSWORD, "SamrValidatePassword", NULL, NULL },
+ {0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_samr(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_samr_opnum,
+ { "Operation", "samr.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }},
+ { &hf_samr_hnd,
+ { "Context Handle", "samr.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_samr_group,
+ { "Group", "samr.group", FT_UINT32, BASE_DEC, NULL, 0x0, "Group", HFILL }},
+ { &hf_samr_rid,
+ { "Rid", "samr.rid", FT_UINT32, BASE_DEC, NULL, 0x0, "RID", HFILL }},
+ { &hf_samr_type,
+ { "Type", "samr.type", FT_UINT32, BASE_HEX, NULL, 0x0, "Type", HFILL }},
+ { &hf_samr_alias,
+ { "Alias", "samr.alias", FT_UINT32, BASE_HEX, NULL, 0x0, "Alias", HFILL }},
+ { &hf_samr_rid_attrib,
+ { "Rid Attrib", "samr.rid.attrib", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_samr_attrib,
+ { "Attributes", "samr.attr", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_samr_rc,
+ { "Return code", "samr.rc", FT_UINT32, BASE_HEX, VALS (NT_errors), 0x0, "", HFILL }},
+
+ { &hf_samr_level,
+ { "Level", "samr.level", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Level requested/returned for Information", HFILL }},
+ { &hf_samr_start_idx,
+ { "Start Idx", "samr.start_idx", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Start Index for returned Information", HFILL }},
+
+ { &hf_samr_entries,
+ { "Entries", "samr.entries", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of entries to return", HFILL }},
+
+ { &hf_samr_max_entries,
+ { "Max Entries", "samr.max_entries", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Maximum number of entries", HFILL }},
+
+ { &hf_samr_pref_maxsize,
+ { "Pref MaxSize", "samr.pref_maxsize", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Maximum Size of data to return", HFILL }},
+
+ { &hf_samr_total_size,
+ { "Total Size", "samr.total_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Total size of data", HFILL }},
+
+ { &hf_samr_bad_pwd_count,
+ { "Bad Pwd Count", "samr.bad_pwd_count", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Number of bad pwd entries for this user", HFILL }},
+
+ { &hf_samr_logon_count,
+ { "Logon Count", "samr.logon_count", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Number of logons for this user", HFILL }},
+
+ { &hf_samr_ret_size,
+ { "Returned Size", "samr.ret_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of returned objects in this PDU", HFILL }},
+
+ { &hf_samr_index,
+ { "Index", "samr.index", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Index", HFILL }},
+
+ { &hf_samr_count,
+ { "Count", "samr.count", FT_UINT32, BASE_DEC, NULL, 0x0, "Number of elements in following array", HFILL }},
+
+ { &hf_samr_alias_name,
+ { "Alias Name", "samr.alias_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of Alias (Local Group)", HFILL }},
+
+ { &hf_samr_group_name,
+ { "Group Name", "samr.group_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of Group", HFILL }},
+
+ { &hf_samr_acct_name,
+ { "Account Name", "samr.acct_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of Account", HFILL }},
+
+ { &hf_samr_server,
+ { "Server", "samr.server", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of Server", HFILL }},
+
+ { &hf_samr_domain,
+ { "Domain", "samr.domain", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of Domain", HFILL }},
+
+ { &hf_samr_controller,
+ { "DC", "samr.dc", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of Domain Controller", HFILL }},
+
+ { &hf_samr_full_name,
+ { "Full Name", "samr.full_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Full Name of Account", HFILL }},
+
+ { &hf_samr_home,
+ { "Home", "samr.home", FT_STRING, BASE_NONE,
+ NULL, 0, "Home directory for this user", HFILL }},
+
+ { &hf_samr_home_drive,
+ { "Home Drive", "samr.home_drive", FT_STRING, BASE_NONE,
+ NULL, 0, "Home drive for this user", HFILL }},
+
+ { &hf_samr_script,
+ { "Script", "samr.script", FT_STRING, BASE_NONE,
+ NULL, 0, "Login script for this user", HFILL }},
+
+ { &hf_samr_workstations,
+ { "Workstations", "samr.workstations", FT_STRING, BASE_NONE,
+ NULL, 0, "", HFILL }},
+
+ { &hf_samr_profile,
+ { "Profile", "samr.profile", FT_STRING, BASE_NONE,
+ NULL, 0, "Profile for this user", HFILL }},
+
+ { &hf_samr_acct_desc,
+ { "Account Desc", "samr.acct_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "Account Description", HFILL }},
+
+ { &hf_samr_comment,
+ { "Account Comment", "samr.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "Account Comment", HFILL }},
+
+ { &hf_samr_unknown_string,
+ { "Unknown string", "samr.unknown_string", FT_STRING, BASE_NONE,
+ NULL, 0, "Unknown string. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_samr_unknown_hyper,
+ { "Unknown hyper", "samr.unknown.hyper", FT_UINT64, BASE_HEX,
+ NULL, 0x0, "Unknown hyper. If you know what this is, contact ethereal developers.", HFILL }},
+ { &hf_samr_unknown_long,
+ { "Unknown long", "samr.unknown.long", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Unknown long. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_samr_unknown_short,
+ { "Unknown short", "samr.unknown.short", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Unknown short. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_samr_unknown_char,
+ { "Unknown char", "samr.unknown.char", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Unknown char. If you know what this is, contact ethereal developers.", HFILL }},
+
+ { &hf_samr_revision,
+ { "Revision", "samr.revision", FT_UINT64, BASE_HEX,
+ NULL, 0x0, "Revision number for this structure", HFILL }},
+
+ { &hf_samr_nt_pwd_set,
+ { "NT Pwd Set", "samr.nt_pwd_set", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Flag indicating whether the NT password has been set", HFILL }},
+
+ { &hf_samr_lm_pwd_set,
+ { "LM Pwd Set", "samr.lm_pwd_set", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Flag indicating whether the LanManager password has been set", HFILL }},
+
+ { &hf_samr_pwd_expired,
+ { "Expired flag", "samr.pwd_Expired", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Flag indicating if the password for this account has expired or not", HFILL }},
+
+ { &hf_samr_access,
+ { "Access Mask", "samr.access", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Access", HFILL }},
+
+ { &hf_samr_access_granted,
+ { "Access Granted", "samr.access_granted", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Access Granted", HFILL }},
+
+ { &hf_samr_crypt_password, {
+ "Password", "samr.crypt_password", FT_BYTES, BASE_HEX,
+ NULL, 0, "Encrypted Password", HFILL }},
+
+ { &hf_samr_crypt_hash, {
+ "Hash", "samr.crypt_hash", FT_BYTES, BASE_HEX,
+ NULL, 0, "Encrypted Hash", HFILL }},
+
+ { &hf_samr_lm_verifier, {
+ "Verifier", "samr.lm_password_verifier", FT_BYTES, BASE_HEX,
+ NULL, 0, "Lan Manager Password Verifier", HFILL }},
+
+ { &hf_samr_nt_verifier, {
+ "Verifier", "samr.nt_password_verifier", FT_BYTES, BASE_HEX,
+ NULL, 0, "NT Password Verifier", HFILL }},
+
+ { &hf_samr_lm_passchange_block, {
+ "Encrypted Block", "samr.lm_passchange_block", FT_BYTES,
+ BASE_HEX, NULL, 0, "Lan Manager Password Change Block",
+ HFILL }},
+
+ { &hf_samr_nt_passchange_block, {
+ "Encrypted Block", "samr.nt_passchange_block", FT_BYTES,
+ BASE_HEX, NULL, 0, "NT Password Change Block", HFILL }},
+
+ { &hf_samr_nt_passchange_block_decrypted, {
+ "Decrypted Block", "samr.nt_passchange_block_decrypted",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "NT Password Change Decrypted Block", HFILL }},
+
+ { &hf_samr_nt_passchange_block_newpass, {
+ "New NT Password", "samr.nt_passchange_block_new_ntpassword",
+ FT_STRING, BASE_NONE, NULL, 0, "New NT Password", HFILL }},
+
+ { &hf_samr_nt_passchange_block_newpass_len, {
+ "New NT Unicode Password length",
+ "samr.nt_passchange_block_new_ntpassword_len", FT_UINT32,
+ BASE_DEC, NULL, 0, "New NT Password Unicode Length", HFILL }},
+
+ { &hf_samr_nt_passchange_block_pseudorandom, {
+ "Pseudorandom data", "samr.nt_passchange_block_pseudorandom",
+ FT_BYTES, BASE_HEX, NULL, 0, "Pseudorandom data", HFILL }},
+
+ { &hf_samr_lm_change, {
+ "LM Change", "samr.lm_change", FT_UINT8, BASE_HEX,
+ NULL, 0, "LM Change value", HFILL }},
+
+ { &hf_samr_max_pwd_age,
+ { "Max Pwd Age", "samr.max_pwd_age", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Maximum Password Age before it expires", HFILL }},
+
+ { &hf_samr_min_pwd_age,
+ { "Min Pwd Age", "samr.min_pwd_age", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Minimum Password Age before it can be changed", HFILL }},
+ { &hf_samr_unknown_time,
+ { "Unknown time", "samr.unknown_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Unknown NT TIME, contact ethereal developers if you know what this is", HFILL }},
+ { &hf_samr_logon_time,
+ { "Last Logon Time", "samr.logon_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time for last time this user logged on", HFILL }},
+ { &hf_samr_kickoff_time,
+ { "Kickoff Time", "samr.kickoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time when this user will be kicked off", HFILL }},
+ { &hf_samr_logoff_time,
+ { "Last Logoff Time", "samr.logoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time for last time this user logged off", HFILL }},
+ { &hf_samr_pwd_last_set_time,
+ { "PWD Last Set", "samr.pwd_last_set_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Last time this users password was changed", HFILL }},
+ { &hf_samr_pwd_can_change_time,
+ { "PWD Can Change", "samr.pwd_can_change_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "When this users password may be changed", HFILL }},
+ { &hf_samr_pwd_must_change_time,
+ { "PWD Must Change", "samr.pwd_must_change_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "When this users password must be changed", HFILL }},
+ { &hf_samr_acct_expiry_time,
+ { "Acct Expiry", "samr.acct_expiry_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "When this user account expires", HFILL }},
+
+ { &hf_samr_min_pwd_len, {
+ "Min Pwd Len", "samr.min_pwd_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Minimum Password Length", HFILL }},
+ { &hf_samr_pwd_history_len, {
+ "Pwd History Len", "samr.pwd_history_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Password History Length", HFILL }},
+ { &hf_samr_num_users, {
+ "Num Users", "samr.num_users", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of users in this domain", HFILL }},
+ { &hf_samr_num_groups, {
+ "Num Groups", "samr.num_groups", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of groups in this domain", HFILL }},
+ { &hf_samr_num_aliases, {
+ "Num Aliases", "samr.num_aliases", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of aliases in this domain", HFILL }},
+ { &hf_samr_info_type, {
+ "Info Type", "samr.info_type", FT_UINT32, BASE_DEC,
+ NULL, 0, "Information Type", HFILL }},
+ { &hf_samr_resume_hnd, {
+ "Resume Hnd", "samr.resume_hnd", FT_UINT32, BASE_DEC,
+ NULL, 0, "Resume handle", HFILL }},
+ { &hf_samr_country, {
+ "Country", "samr.country", FT_UINT16, BASE_DEC,
+ VALS(ms_country_codes), 0, "Country setting for this user", HFILL }},
+ { &hf_samr_codepage, {
+ "Codepage", "samr.codepage", FT_UINT16, BASE_DEC,
+ NULL, 0, "Codepage setting for this user", HFILL }},
+ { &hf_samr_primary_group_rid,
+ { "Primary group RID", "samr.primary_group_rid", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "RID of the user primary group", HFILL }},
+ { &hf_samr_callback,
+ { "Callback", "samr.callback", FT_STRING, BASE_NONE,
+ NULL, 0, "Callback for this user", HFILL }},
+ { &hf_samr_alias_desc,
+ { "Alias Desc", "samr.alias.desc", FT_STRING, BASE_NONE,
+ NULL, 0, "Alias (Local Group) Description", HFILL }},
+ { &hf_samr_alias_num_of_members,
+ { "Num of Members in Alias", "samr.alias.num_of_members",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Number of members in Alias (Local Group)", HFILL }},
+ { &hf_samr_group_desc,
+ { "Group Desc", "samr.group.desc", FT_STRING, BASE_NONE,
+ NULL, 0, "Group Description", HFILL }},
+ { &hf_samr_group_num_of_members,
+ { "Num of Members in Group", "samr.group.num_of_members",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Number of members in Group", HFILL }},
+
+ /* Object specific access rights */
+
+ { &hf_access_domain_lookup_info1,
+ { "Lookup info1", "samr_access_mask.domain_lookup_info1",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_LOOKUP_INFO_1, "Lookup info1", HFILL }},
+
+ { &hf_access_domain_set_info1,
+ { "Set info1", "samr_access_mask.domain_set_info1",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_SET_INFO_1, "Set info1", HFILL }},
+
+ { &hf_access_domain_lookup_info2,
+ { "Lookup info2", "samr_access_mask.domain_lookup_info2",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_LOOKUP_INFO_2, "Lookup info2", HFILL }},
+
+ { &hf_access_domain_set_info2,
+ { "Set info2", "samr_access_mask.domain_set_info2",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_SET_INFO_2, "Set info2", HFILL }},
+
+ { &hf_access_domain_create_user,
+ { "Create user", "samr_access_mask.domain_create_user",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_CREATE_USER, "Create user", HFILL }},
+
+ { &hf_access_domain_create_group,
+ { "Create group", "samr_access_mask.domain_create_group",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_CREATE_GROUP, "Create group", HFILL }},
+
+ { &hf_access_domain_create_alias,
+ { "Create alias", "samr_access_mask.domain_create_alias",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_CREATE_ALIAS, "Create alias", HFILL }},
+
+ { &hf_access_domain_lookup_alias_by_mem,
+ { "Lookup alias", "samr_access_mask.domain_lookup_alias_by_mem",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_LOOKUP_ALIAS, "Lookup alias", HFILL }},
+
+ { &hf_access_domain_enum_accounts,
+ { "Enum accounts", "samr_access_mask.domain_enum_accounts",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_ENUM_ACCOUNTS, "Enum accounts", HFILL }},
+
+ { &hf_access_domain_open_account,
+ { "Open account", "samr_access_mask.domain_open_account",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_OPEN_ACCOUNT, "Open account", HFILL }},
+
+ { &hf_access_domain_set_info3,
+ { "Set info3", "samr_access_mask.domain_set_info3",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DOMAIN_ACCESS_SET_INFO_3, "Set info3", HFILL }},
+
+ { &hf_access_user_get_name_etc,
+ { "Get name, etc", "samr_access_mask.user_get_name_etc",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_GET_NAME_ETC, "Get name, etc", HFILL }},
+
+ { &hf_access_user_get_locale,
+ { "Get locale", "samr_access_mask.user_get_locale",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_GET_LOCALE, "Get locale", HFILL }},
+
+ { &hf_access_user_get_loc_com,
+ { "Set loc com", "samr_access_mask.user_set_loc_com",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_SET_LOC_COM, "Set loc com", HFILL }},
+
+ { &hf_access_user_get_logoninfo,
+ { "Get logon info", "samr_access_mask.user_get_logoninfo",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_GET_LOGONINFO, "Get logon info", HFILL }},
+
+ { &hf_access_user_get_attributes,
+ { "Get attributes", "samr_access_mask.user_get_attributes",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_GET_ATTRIBUTES, "Get attributes", HFILL }},
+
+ { &hf_access_user_set_attributes,
+ { "Set attributes", "samr_access_mask.user_set_attributes",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_SET_ATTRIBUTES, "Set attributes", HFILL }},
+
+ { &hf_access_user_change_password,
+ { "Change password", "samr_access_mask.user_change_password",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_CHANGE_PASSWORD, "Change password", HFILL }},
+
+ { &hf_access_user_set_password,
+ { "Set password", "samr_access_mask.user_set_password",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_SET_PASSWORD, "Set password", HFILL }},
+
+ { &hf_access_user_get_groups,
+ { "Get groups", "samr_access_mask.user_get_groups",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_GET_GROUPS, "Get groups", HFILL }},
+
+ { &hf_access_user_get_group_membership,
+ { "Get group membership", "samr_access_mask.user_get_group_membership",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_GET_GROUP_MEMBERSHIP, "Get group membership", HFILL }},
+
+ { &hf_access_user_change_group_membership,
+ { "Change group membership", "samr_access_mask.user_change_group_membership",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ USER_ACCESS_CHANGE_GROUP_MEMBERSHIP, "Change group membership", HFILL }},
+
+ { &hf_access_group_lookup_info,
+ { "Lookup info", "samr_access_mask.group_lookup_info",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GROUP_ACCESS_LOOKUP_INFO, "Lookup info", HFILL }},
+
+ { &hf_access_group_set_info,
+ { "Get info", "samr_access_mask.group_set_info",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GROUP_ACCESS_SET_INFO, "Get info", HFILL }},
+
+ { &hf_access_group_add_member,
+ { "Add member", "samr_access_mask.group_add_member",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GROUP_ACCESS_ADD_MEMBER, "Add member", HFILL }},
+
+ { &hf_access_group_remove_member,
+ { "Remove member", "samr_access_mask.group_remove_member",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GROUP_ACCESS_REMOVE_MEMBER, "Remove member", HFILL }},
+
+ { &hf_access_group_get_members,
+ { "Get members", "samr_access_mask.group_get_members",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GROUP_ACCESS_GET_MEMBERS, "Get members", HFILL }},
+
+ { &hf_access_alias_add_member,
+ { "Add member", "samr_access_mask.alias_add_member",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ ALIAS_ACCESS_ADD_MEMBER, "Add member", HFILL }},
+
+ { &hf_access_alias_remove_member,
+ { "Remove member", "samr_access_mask.alias_remove_member",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ ALIAS_ACCESS_REMOVE_MEMBER, "Remove member", HFILL }},
+
+ { &hf_access_alias_get_members,
+ { "Get members", "samr_access_mask.alias_get_members",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ ALIAS_ACCESS_GET_MEMBERS, "Get members", HFILL }},
+
+ { &hf_access_alias_lookup_info,
+ { "Lookup info", "samr_access_mask.alias_lookup_info",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ ALIAS_ACCESS_LOOKUP_INFO, "Lookup info", HFILL }},
+
+ { &hf_access_alias_set_info,
+ { "Set info", "samr_access_mask.alias_set_info",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ ALIAS_ACCESS_SET_INFO, "Set info", HFILL }},
+
+ { &hf_access_connect_connect_to_server,
+ { "Connect to server", "samr_access_mask.connect_connect_to_server",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SAMR_ACCESS_CONNECT_TO_SERVER, "Connect to server", HFILL }},
+
+ { &hf_access_connect_shutdown_server,
+ { "Shutdown server", "samr_access_mask.connect_shutdown_server",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SAMR_ACCESS_SHUTDOWN_SERVER, "Shutdown server", HFILL }},
+
+ { &hf_access_connect_initialize_server,
+ { "Initialize server", "samr_access_mask.connect_initialize_server",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SAMR_ACCESS_INITIALIZE_SERVER, "Initialize server", HFILL }},
+
+ { &hf_access_connect_create_domain,
+ { "Create domain", "samr_access_mask.connect_create_domain",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SAMR_ACCESS_CREATE_DOMAIN, "Create domain", HFILL }},
+
+ { &hf_access_connect_enum_domains,
+ { "Enum domains", "samr_access_mask.connect_enum_domains",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SAMR_ACCESS_ENUM_DOMAINS, "Enum domains", HFILL }},
+
+ { &hf_access_connect_open_domain,
+ { "Open domain", "samr_access_mask.connect_open_domain",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SAMR_ACCESS_OPEN_DOMAIN, "Open domain", HFILL }},
+
+ { &hf_samr_sd_size,
+ { "Size", "sam.sd_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of SAM security descriptor", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_samr,
+ &ett_SAM_SECURITY_DESCRIPTOR,
+ &ett_samr_user_dispinfo_1,
+ &ett_samr_user_dispinfo_1_array,
+ &ett_samr_user_dispinfo_2,
+ &ett_samr_user_dispinfo_2_array,
+ &ett_samr_group_dispinfo,
+ &ett_samr_group_dispinfo_array,
+ &ett_samr_ascii_dispinfo,
+ &ett_samr_ascii_dispinfo_array,
+ &ett_samr_display_info,
+ &ett_samr_password_info,
+ &ett_samr_server,
+ &ett_samr_user_group,
+ &ett_samr_user_group_array,
+ &ett_samr_alias_info,
+ &ett_samr_group_info,
+ &ett_samr_domain_info_1,
+ &ett_samr_domain_info_2,
+ &ett_samr_domain_info_8,
+ &ett_samr_replication_status,
+ &ett_samr_domain_info_11,
+ &ett_samr_domain_info_13,
+ &ett_samr_domain_info,
+ &ett_samr_index_array,
+ &ett_samr_idx_and_name,
+ &ett_samr_idx_and_name_array,
+ &ett_samr_user_info_1,
+ &ett_samr_user_info_2,
+ &ett_samr_user_info_3,
+ &ett_samr_user_info_5,
+ &ett_samr_user_info_6,
+ &ett_samr_user_info_10,
+ &ett_samr_user_info_18,
+ &ett_samr_user_info_19,
+ &ett_samr_buffer_buffer,
+ &ett_samr_buffer,
+ &ett_samr_user_info_21,
+ &ett_samr_user_info_22,
+ &ett_samr_user_info_23,
+ &ett_samr_user_info_24,
+ &ett_samr_user_info_25,
+ &ett_samr_user_info,
+ &ett_samr_member_array_types,
+ &ett_samr_member_array_rids,
+ &ett_samr_member_array,
+ &ett_samr_names,
+ &ett_samr_rids,
+ };
+ module_t *dcerpc_samr_module;
+
+ proto_dcerpc_samr = proto_register_protocol(
+ "Microsoft Security Account Manager", "SAMR", "samr");
+
+ proto_register_field_array (proto_dcerpc_samr, hf, array_length (hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ dcerpc_samr_module = prefs_register_protocol(proto_dcerpc_samr, NULL);
+
+ prefs_register_string_preference(dcerpc_samr_module, "nt_password",
+ "NT Password",
+ "NT Password (used to verify password changes)",
+ &nt_password);
+}
+
+void
+proto_reg_handoff_dcerpc_samr(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_samr, ett_dcerpc_samr, &uuid_dcerpc_samr,
+ ver_dcerpc_samr, dcerpc_samr_dissectors, hf_samr_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-samr.h b/epan/dissectors/packet-dcerpc-samr.h
new file mode 100644
index 0000000000..b8b83a7296
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-samr.h
@@ -0,0 +1,145 @@
+/* packet-dcerpc-samr.h
+ * Routines for SMB \PIPE\samr packet disassembly
+ * Copyright 2001, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_SAMR_H
+#define __PACKET_DCERPC_SAMR_H
+
+/* Functions available on the SAMR pipe. From Samba, include/rpc_samr.h */
+
+#define SAMR_CONNECT 0x00
+#define SAMR_CLOSE_HND 0x01
+#define SAMR_SET_SEC_OBJECT 0x02
+#define SAMR_QUERY_SEC_OBJECT 0x03
+#define SAMR_SHUTDOWN_SAM_SERVER 0x04
+#define SAMR_LOOKUP_DOMAIN 0x05
+#define SAMR_ENUM_DOMAINS 0x06
+#define SAMR_OPEN_DOMAIN 0x07
+#define SAMR_QUERY_DOMAIN_INFO 0x08
+#define SAMR_SET_DOMAIN_INFO 0x09
+#define SAMR_CREATE_DOM_GROUP 0x0a
+#define SAMR_ENUM_DOM_GROUPS 0x0b
+#define SAMR_CREATE_USER_IN_DOMAIN 0x0c
+#define SAMR_ENUM_DOM_USERS 0x0d
+#define SAMR_CREATE_DOM_ALIAS 0x0e
+#define SAMR_ENUM_DOM_ALIASES 0x0f
+#define SAMR_GET_ALIAS_MEMBERSHIP 0x10
+#define SAMR_LOOKUP_NAMES 0x11
+#define SAMR_LOOKUP_RIDS 0x12
+#define SAMR_OPEN_GROUP 0x13
+#define SAMR_QUERY_GROUPINFO 0x14
+#define SAMR_SET_GROUPINFO 0x15
+#define SAMR_ADD_GROUPMEM 0x16
+#define SAMR_DELETE_DOM_GROUP 0x17
+#define SAMR_DEL_GROUPMEM 0x18
+#define SAMR_QUERY_GROUPMEM 0x19
+#define SAMR_SET_MEMBER_ATTRIBUTES_OF_GROUP 0x1a
+#define SAMR_OPEN_ALIAS 0x1b
+#define SAMR_QUERY_ALIASINFO 0x1c
+#define SAMR_SET_ALIASINFO 0x1d
+#define SAMR_DELETE_DOM_ALIAS 0x1e
+#define SAMR_ADD_ALIASMEM 0x1f
+#define SAMR_DEL_ALIASMEM 0x20
+#define SAMR_GET_MEMBERS_IN_ALIAS 0x21
+#define SAMR_OPEN_USER 0x22
+#define SAMR_DELETE_DOM_USER 0x23
+#define SAMR_QUERY_USERINFO 0x24
+#define SAMR_SET_USERINFO 0x25
+#define SAMR_CHANGE_PASSWORD_USER 0x26
+#define SAMR_GET_GROUPS_FOR_USER 0x27
+#define SAMR_QUERY_DISPINFO 0x28
+#define SAMR_GET_DISPLAY_ENUMERATION_INDEX 0x29
+#define SAMR_TEST_PRIVATE_FUNCTIONS_DOMAIN 0x2a
+#define SAMR_TEST_PRIVATE_FUNCTIONS_USER 0x2b
+#define SAMR_GET_USRDOM_PWINFO 0x2c
+#define SAMR_REMOVE_MEMBER_FROM_FOREIGN_DOMAIN 0x2d
+#define SAMR_QUERY_INFORMATION_DOMAIN2 0x2e
+#define SAMR_QUERY_INFORMATION_USER2 0x2f
+#define SAMR_QUERY_DISPINFO2 0x30
+#define SAMR_GET_DISPLAY_ENUMERATION_INDEX2 0x31
+#define SAMR_CREATE_USER2_IN_DOMAIN 0x32
+#define SAMR_QUERY_DISPINFO3 0x33
+#define SAMR_ADD_MULTIPLE_MEMBERS_TO_ALIAS 0x34
+#define SAMR_REMOVE_MULTIPLE_MEMBERS_FROM_ALIAS 0x35
+#define SAMR_OEM_CHANGE_PASSWORD_USER2 0x36
+#define SAMR_UNICODE_CHANGE_PASSWORD_USER2 0x37
+#define SAMR_GET_DOM_PWINFO 0x38
+#define SAMR_CONNECT2 0x39
+#define SAMR_SET_USERINFO2 0x3a
+#define SAMR_SET_BOOT_KEY_INFORMATION 0x3b
+#define SAMR_GET_BOOT_KEY_INFORMATION 0x3c
+#define SAMR_CONNECT3 0x3d
+#define SAMR_CONNECT4 0x3e
+#define SAMR_UNICODE_CHANGE_PASSWORD_USER3 0x3f
+#define SAMR_CONNECT5 0x40
+#define SAMR_RID_TO_SID 0x41
+#define SAMR_SET_DSRM_PASSWORD 0x42
+#define SAMR_VALIDATE_PASSWORD 0x43
+
+/* Specific access rights */
+
+#define SAMR_ACCESS_CONNECT_TO_SERVER 0x00000001
+#define SAMR_ACCESS_SHUTDOWN_SERVER 0x00000002
+#define SAMR_ACCESS_INITIALIZE_SERVER 0x00000004
+#define SAMR_ACCESS_CREATE_DOMAIN 0x00000008
+#define SAMR_ACCESS_ENUM_DOMAINS 0x00000010
+#define SAMR_ACCESS_OPEN_DOMAIN 0x00000020
+
+#define DOMAIN_ACCESS_LOOKUP_INFO_1 0x00000001
+#define DOMAIN_ACCESS_SET_INFO_1 0x00000002
+#define DOMAIN_ACCESS_LOOKUP_INFO_2 0x00000004
+#define DOMAIN_ACCESS_SET_INFO_2 0x00000008
+#define DOMAIN_ACCESS_CREATE_USER 0x00000010
+#define DOMAIN_ACCESS_CREATE_GROUP 0x00000020
+#define DOMAIN_ACCESS_CREATE_ALIAS 0x00000040
+#define DOMAIN_ACCESS_LOOKUP_ALIAS 0x00000080
+#define DOMAIN_ACCESS_ENUM_ACCOUNTS 0x00000100
+#define DOMAIN_ACCESS_OPEN_ACCOUNT 0x00000200
+#define DOMAIN_ACCESS_SET_INFO_3 0x00000400
+
+#define USER_ACCESS_GET_NAME_ETC 0x00000001
+#define USER_ACCESS_GET_LOCALE 0x00000002
+#define USER_ACCESS_SET_LOC_COM 0x00000004
+#define USER_ACCESS_GET_LOGONINFO 0x00000008
+#define USER_ACCESS_GET_ATTRIBUTES 0x00000010
+#define USER_ACCESS_SET_ATTRIBUTES 0x00000020
+#define USER_ACCESS_CHANGE_PASSWORD 0x00000040
+#define USER_ACCESS_SET_PASSWORD 0x00000080
+#define USER_ACCESS_GET_GROUPS 0x00000100
+#define USER_ACCESS_GET_GROUP_MEMBERSHIP 0x00000200
+#define USER_ACCESS_CHANGE_GROUP_MEMBERSHIP 0x00000400
+
+#define ALIAS_ACCESS_ADD_MEMBER 0x00000001
+#define ALIAS_ACCESS_REMOVE_MEMBER 0x00000002
+#define ALIAS_ACCESS_GET_MEMBERS 0x00000004
+#define ALIAS_ACCESS_LOOKUP_INFO 0x00000008
+#define ALIAS_ACCESS_SET_INFO 0x00000010
+
+#define GROUP_ACCESS_LOOKUP_INFO 0x00000001
+#define GROUP_ACCESS_SET_INFO 0x00000002
+#define GROUP_ACCESS_ADD_MEMBER 0x00000004
+#define GROUP_ACCESS_REMOVE_MEMBER 0x00000008
+#define GROUP_ACCESS_GET_MEMBERS 0x00000010
+
+#endif /* packet-dcerpc-samr.h */
diff --git a/epan/dissectors/packet-dcerpc-secidmap.c b/epan/dissectors/packet-dcerpc-secidmap.c
new file mode 100644
index 0000000000..9161d52422
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-secidmap.c
@@ -0,0 +1,88 @@
+/* packet-dcerpc-secidmap.c
+ *
+ * Routines for dcerpc DCE Security ID Mapper
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/security.tar.gz security/idl/rsecidmap.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+static int proto_secidmap = -1;
+static int hf_secidmap_opnum = -1;
+
+
+static gint ett_secidmap = -1;
+
+static e_uuid_t uuid_secidmap = { 0x0d7c1e50, 0x113a, 0x11ca, { 0xb7, 0x1f, 0x08, 0x00, 0x1e, 0x01, 0xdc, 0x6c } };
+static guint16 ver_secidmap = 1;
+
+
+
+static dcerpc_sub_dissector secidmap_dissectors[] = {
+ { 0, "parse_name", NULL, NULL},
+ { 1, "gen_name", NULL, NULL},
+ { 2, "avoid_cn_bug", NULL, NULL},
+ { 3, "parse_name_cache", NULL, NULL},
+ { 4, "gen_name_cache", NULL, NULL},
+
+ { 0, NULL, NULL, NULL },
+};
+
+void
+proto_register_secidmap (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_secidmap_opnum,
+ { "Operation", "secidmap.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_secidmap,
+ };
+ proto_secidmap = proto_register_protocol ("DCE Security ID Mapper", "SECIDMAP", "secidmap");
+ proto_register_field_array (proto_secidmap, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_secidmap (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_secidmap, ett_secidmap, &uuid_secidmap, ver_secidmap, secidmap_dissectors, hf_secidmap_opnum);
+}
+
diff --git a/epan/dissectors/packet-dcerpc-spoolss.c b/epan/dissectors/packet-dcerpc-spoolss.c
new file mode 100644
index 0000000000..86220411b3
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-spoolss.c
@@ -0,0 +1,8226 @@
+/* packet-dcerpc-spoolss.c
+ * Routines for SMB \PIPE\spoolss packet disassembly
+ * Copyright 2001-2003, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* TODO list:
+
+ - audit of item lengths
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-spoolss.h"
+#include "packet-dcerpc-reg.h"
+#include "smb.h"
+#include "packet-smb-common.h"
+
+/* GetPrinterDriver2 */
+
+static int hf_clientmajorversion = -1;
+static int hf_clientminorversion = -1;
+static int hf_servermajorversion = -1;
+static int hf_serverminorversion = -1;
+static int hf_driverpath = -1;
+static int hf_datafile = -1;
+static int hf_configfile = -1;
+static int hf_helpfile = -1;
+static int hf_monitorname = -1;
+static int hf_defaultdatatype = -1;
+static int hf_driverinfo_cversion = -1;
+static int hf_dependentfiles = -1;
+
+/* GetPrinter */
+
+/* Times */
+
+static int hf_start_time = -1;
+static int hf_end_time = -1;
+static int hf_elapsed_time = -1;
+
+/****************************************************************************/
+
+/*
+ * New hf index values - I'm in the process of doing a bit of a cleanup -tpot
+ */
+
+static int hf_opnum = -1;
+static int hf_hnd = -1;
+static int hf_rc = -1;
+static int hf_offered = -1;
+static int hf_needed = -1;
+static int hf_returned = -1;
+static int hf_buffer_size = -1;
+static int hf_buffer_data = -1;
+static int hf_offset = -1;
+static int hf_level = -1;
+static int hf_access_required = -1;
+
+static int hf_printername = -1;
+static int hf_machinename = -1;
+static int hf_notifyname = -1;
+static int hf_printerdesc = -1;
+static int hf_printercomment = -1;
+static int hf_servername = -1;
+static int hf_sharename = -1;
+static int hf_portname = -1;
+static int hf_printerlocation = -1;
+static int hf_drivername = -1;
+static int hf_architecture = -1;
+static int hf_username = -1;
+static int hf_documentname = -1;
+static int hf_outputfile = -1;
+static int hf_datatype = -1;
+static int hf_textstatus = -1;
+static int hf_sepfile = -1;
+static int hf_printprocessor = -1;
+static int hf_parameters = -1;
+
+/* Printer information */
+
+static int hf_printer_cjobs = -1;
+static int hf_printer_total_jobs = -1;
+static int hf_printer_total_bytes = -1;
+static int hf_printer_global_counter = -1;
+static int hf_printer_total_pages = -1;
+static int hf_printer_major_version = -1;
+static int hf_printer_build_version = -1;
+static int hf_printer_unk7 = -1;
+static int hf_printer_unk8 = -1;
+static int hf_printer_unk9 = -1;
+static int hf_printer_session_ctr = -1;
+static int hf_printer_unk11 = -1;
+static int hf_printer_printer_errors = -1;
+static int hf_printer_unk13 = -1;
+static int hf_printer_unk14 = -1;
+static int hf_printer_unk15 = -1;
+static int hf_printer_unk16 = -1;
+static int hf_printer_changeid = -1;
+static int hf_printer_unk18 = -1;
+static int hf_printer_unk20 = -1;
+static int hf_printer_c_setprinter = -1;
+static int hf_printer_unk22 = -1;
+static int hf_printer_unk23 = -1;
+static int hf_printer_unk24 = -1;
+static int hf_printer_unk25 = -1;
+static int hf_printer_unk26 = -1;
+static int hf_printer_unk27 = -1;
+static int hf_printer_unk28 = -1;
+static int hf_printer_unk29 = -1;
+static int hf_printer_flags = -1;
+static int hf_printer_priority = -1;
+static int hf_printer_default_priority = -1;
+static int hf_printer_jobs = -1;
+static int hf_printer_averageppm = -1;
+static int hf_printer_guid = -1;
+static int hf_printer_action = -1;
+
+/* Printer data */
+
+static int hf_printerdata = -1;
+static int hf_printerdata_key = -1;
+static int hf_printerdata_value = -1;
+static int hf_printerdata_type = -1;
+static int hf_printerdata_size = -1; /* Length of printer data */
+static int hf_printerdata_data = -1;
+static int hf_printerdata_data_sz = -1;
+static int hf_printerdata_data_dword = -1;
+
+/* Devicemode */
+
+static int hf_devmodectr_size = -1;
+
+static int hf_devmode = -1;
+static int hf_devmode_size = -1;
+static int hf_devmode_spec_version = -1;
+static int hf_devmode_driver_version = -1;
+static int hf_devmode_size2 = -1;
+static int hf_devmode_driver_extra_len = -1;
+static int hf_devmode_fields = -1;
+static int hf_devmode_orientation = -1;
+static int hf_devmode_paper_size = -1;
+static int hf_devmode_paper_width = -1;
+static int hf_devmode_paper_length = -1;
+static int hf_devmode_scale = -1;
+static int hf_devmode_copies = -1;
+static int hf_devmode_default_source = -1;
+static int hf_devmode_print_quality = -1;
+static int hf_devmode_color = -1;
+static int hf_devmode_duplex = -1;
+static int hf_devmode_y_resolution = -1;
+static int hf_devmode_tt_option = -1;
+static int hf_devmode_collate = -1;
+static int hf_devmode_log_pixels = -1;
+static int hf_devmode_bits_per_pel = -1;
+static int hf_devmode_pels_width = -1;
+static int hf_devmode_pels_height = -1;
+static int hf_devmode_display_flags = -1;
+static int hf_devmode_display_freq = -1;
+static int hf_devmode_icm_method = -1;
+static int hf_devmode_icm_intent = -1;
+static int hf_devmode_media_type = -1;
+static int hf_devmode_dither_type = -1;
+static int hf_devmode_reserved1 = -1;
+static int hf_devmode_reserved2 = -1;
+static int hf_devmode_panning_width = -1;
+static int hf_devmode_panning_height = -1;
+static int hf_devmode_driver_extra = -1;
+
+static int hf_devmode_fields_orientation = -1;
+static int hf_devmode_fields_papersize = -1;
+static int hf_devmode_fields_paperlength = -1;
+static int hf_devmode_fields_paperwidth = -1;
+static int hf_devmode_fields_scale = -1;
+static int hf_devmode_fields_position = -1;
+static int hf_devmode_fields_nup = -1;
+static int hf_devmode_fields_copies = -1;
+static int hf_devmode_fields_defaultsource = -1;
+static int hf_devmode_fields_printquality = -1;
+static int hf_devmode_fields_color = -1;
+static int hf_devmode_fields_duplex = -1;
+static int hf_devmode_fields_yresolution = -1;
+static int hf_devmode_fields_ttoption = -1;
+static int hf_devmode_fields_collate = -1;
+static int hf_devmode_fields_formname = -1;
+static int hf_devmode_fields_logpixels = -1;
+static int hf_devmode_fields_bitsperpel = -1;
+static int hf_devmode_fields_pelswidth = -1;
+static int hf_devmode_fields_pelsheight = -1;
+static int hf_devmode_fields_displayflags = -1;
+static int hf_devmode_fields_displayfrequency = -1;
+static int hf_devmode_fields_icmmethod = -1;
+static int hf_devmode_fields_icmintent = -1;
+static int hf_devmode_fields_mediatype = -1;
+static int hf_devmode_fields_dithertype = -1;
+static int hf_devmode_fields_panningwidth = -1;
+static int hf_devmode_fields_panningheight = -1;
+
+/* Print job */
+
+static int hf_job_id = -1;
+static int hf_job_priority = -1;
+static int hf_job_position = -1;
+static int hf_job_totalpages = -1;
+static int hf_job_totalbytes = -1;
+static int hf_job_pagesprinted = -1;
+static int hf_job_bytesprinted = -1;
+static int hf_job_size = -1;
+
+static int hf_job_status = -1;
+static int hf_job_status_paused = -1;
+static int hf_job_status_error = -1;
+static int hf_job_status_deleting = -1;
+static int hf_job_status_spooling = -1;
+static int hf_job_status_printing = -1;
+static int hf_job_status_offline = -1;
+static int hf_job_status_paperout = -1;
+static int hf_job_status_printed = -1;
+static int hf_job_status_deleted = -1;
+static int hf_job_status_blocked = -1;
+static int hf_job_status_user_intervention = -1;
+
+/* Forms */
+
+static int hf_form = -1;
+static int hf_form_level = -1;
+static int hf_form_name = -1;
+static int hf_form_flags = -1;
+static int hf_form_unknown = -1;
+static int hf_form_width = -1;
+static int hf_form_height = -1;
+static int hf_form_left_margin = -1;
+static int hf_form_top_margin = -1;
+static int hf_form_horiz_len = -1;
+static int hf_form_vert_len = -1;
+
+static int hf_enumforms_num = -1;
+
+/* Print notify */
+
+static int hf_notify_options_version = -1;
+static int hf_notify_options_flags = -1;
+static int hf_notify_options_flags_refresh = -1;
+static int hf_notify_options_count = -1;
+static int hf_notify_option_type = -1;
+static int hf_notify_option_reserved1 = -1;
+static int hf_notify_option_reserved2 = -1;
+static int hf_notify_option_reserved3 = -1;
+static int hf_notify_option_count = -1;
+static int hf_notify_option_data_count = -1;
+static int hf_notify_info_count = -1;
+static int hf_notify_info_version = -1;
+static int hf_notify_info_flags = -1;
+static int hf_notify_info_data_type = -1;
+static int hf_notify_info_data_count = -1;
+static int hf_notify_info_data_id = -1;
+static int hf_notify_info_data_value1 = -1;
+static int hf_notify_info_data_value2 = -1;
+static int hf_notify_info_data_bufsize = -1;
+static int hf_notify_info_data_buffer = -1;
+static int hf_notify_info_data_buffer_len = -1;
+static int hf_notify_info_data_buffer_data = -1;
+
+static int hf_notify_field = -1;
+
+static int hf_printerlocal = -1;
+
+static int hf_rrpcn_changelow = -1;
+static int hf_rrpcn_changehigh = -1;
+static int hf_rrpcn_unk0 = -1;
+static int hf_rrpcn_unk1 = -1;
+
+static int hf_replyopenprinter_unk0 = -1;
+static int hf_replyopenprinter_unk1 = -1;
+
+/****************************************************************************/
+
+/*
+ * Dissect SPOOLSS specific access rights
+ */
+
+static int hf_server_access_admin = -1;
+static int hf_server_access_enum = -1;
+static int hf_printer_access_admin = -1;
+static int hf_printer_access_use = -1;
+static int hf_job_access_admin = -1;
+
+static void
+spoolss_printer_specific_rights(tvbuff_t *tvb, gint offset, proto_tree *tree,
+ guint32 access)
+{
+ proto_tree_add_boolean(
+ tree, hf_printer_access_use, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_printer_access_admin, tvb, offset, 4, access);
+}
+
+struct access_mask_info spoolss_printer_access_mask_info = {
+ "SPOOLSS printer",
+ spoolss_printer_specific_rights,
+ NULL, /* Generic mapping table */
+ NULL /* Standard mapping table */
+};
+
+static void
+spoolss_printserver_specific_rights(tvbuff_t *tvb, gint offset,
+ proto_tree *tree, guint32 access)
+{
+ proto_tree_add_boolean(
+ tree, hf_server_access_enum, tvb, offset, 4, access);
+
+ proto_tree_add_boolean(
+ tree, hf_server_access_admin, tvb, offset, 4, access);
+}
+
+struct access_mask_info spoolss_printserver_access_mask_info = {
+ "SPOOLSS print server",
+ spoolss_printserver_specific_rights,
+ NULL, /* Generic mapping table */
+ NULL /* Standard mapping table */
+};
+
+static void
+spoolss_job_specific_rights(tvbuff_t *tvb, gint offset,
+ proto_tree *tree, guint32 access)
+{
+ proto_tree_add_boolean(
+ tree, hf_job_access_admin, tvb, offset, 4, access);
+}
+
+struct access_mask_info spoolss_job_access_mask_info = {
+ "SPOOLSS job",
+ spoolss_job_specific_rights,
+ NULL, /* Generic mapping table */
+ NULL /* Standard mapping table */
+};
+
+/*
+ * Routines to dissect a spoolss BUFFER
+ */
+
+typedef struct {
+ tvbuff_t *tvb;
+ proto_item *tree; /* Proto tree buffer located in */
+ proto_item *item;
+} BUFFER;
+
+static gint ett_BUFFER = -1;
+
+static int
+dissect_spoolss_buffer_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = pinfo->private_data;
+ BUFFER *b = (BUFFER *)di->private_data;
+ proto_item *item;
+ guint32 size;
+ const guint8 *data;
+
+ if (di->conformant_run)
+ return offset;
+
+ /* Dissect size and data */
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_buffer_size, &size);
+
+ offset = dissect_ndr_uint8s(tvb, offset, pinfo, NULL, drep,
+ hf_buffer_data, size, &data);
+
+ item = proto_tree_add_item(
+ tree, hf_buffer_data, tvb, offset - size,
+ size, drep[0] & 0x10);
+
+ /* Return buffer info */
+
+ if (b) {
+
+ /* I'm not sure about this. Putting the buffer into
+ it's own tvb makes sense and the dissection code is
+ much clearer, but the data is a proper subset of
+ the actual tvb. Not adding the new data source
+ makes the hex display confusing as it switches
+ between the 'DCERPC over SMB' tvb and the buffer
+ tvb with no visual cues as to what is going on. */
+
+ b->tvb = tvb_new_real_data(data, size, size);
+ tvb_set_child_real_data_tvbuff(tvb, b->tvb);
+ add_new_data_source(pinfo, b->tvb, "SPOOLSS buffer");
+
+ b->item = item;
+ b->tree = proto_item_add_subtree(item, ett_BUFFER);
+ }
+
+ return offset;
+}
+
+/* Dissect a spoolss buffer and return buffer data */
+
+static int
+dissect_spoolss_buffer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, BUFFER *b)
+{
+ dcerpc_info *di = pinfo->private_data;
+
+ if (b)
+ memset(b, 0, sizeof(BUFFER));
+
+ di->private_data = b;
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_spoolss_buffer_data, NDR_POINTER_UNIQUE,
+ "Buffer", -1);
+
+ return offset;
+}
+
+/*
+ * SYSTEM_TIME
+ */
+
+static gint ett_SYSTEM_TIME;
+
+static int hf_time_year = -1;
+static int hf_time_month = -1;
+static int hf_time_dow = -1;
+static int hf_time_day = -1;
+static int hf_time_hour = -1;
+static int hf_time_minute = -1;
+static int hf_time_second = -1;
+static int hf_time_msec = -1;
+
+static int
+dissect_SYSTEM_TIME(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, char *name,
+ gboolean add_subtree, char **data)
+{
+ proto_item *item = NULL;
+ proto_tree *subtree = tree;
+ guint16 year, month, day, hour, minute, second, millisecond;
+ char *str;
+
+ if (add_subtree) {
+ item = proto_tree_add_text(tree, tvb, offset, 16, name);
+ subtree = proto_item_add_subtree(item, ett_SYSTEM_TIME);
+ }
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep, hf_time_year, &year);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep, hf_time_month, &month);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep, hf_time_dow, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep, hf_time_day, &day);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep, hf_time_hour, &hour);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep, hf_time_minute, &minute);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep, hf_time_second, &second);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep, hf_time_msec, &millisecond);
+
+ str = g_strdup_printf("%d/%02d/%02d %02d:%02d:%02d.%03d",
+ year, month, day, hour, minute, second,
+ millisecond);
+
+ if (add_subtree)
+ proto_item_append_text(item, ": %s", str);
+
+ if (data)
+ *data = str;
+ else
+ g_free(str);
+
+ return offset;
+}
+
+static int
+dissect_SYSTEM_TIME_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ char *str;
+
+ offset = dissect_SYSTEM_TIME(
+ tvb, offset, pinfo, tree, drep, NULL, FALSE, &str);
+
+ dcv->private_data = str;
+
+ return offset;
+}
+
+/*
+ * SpoolssClosePrinter
+ */
+
+static int SpoolssClosePrinter_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ e_ctx_hnd policy_hnd;
+ char *pol_name;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
+ FALSE, TRUE);
+
+ dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
+ pinfo->fd->num);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ pol_name);
+
+ return offset;
+}
+
+static int SpoolssClosePrinter_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/* Dissect some printer data. The get/set/enum printerdata routines all
+ store value/data in a uint8 array. We could use the ndr routines for
+ this but that would result in one item for each byte in the printer
+ data. */
+
+static gint ett_printerdata_data = -1;
+static gint ett_printerdata_value = -1;
+
+static int dissect_printerdata_data(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_, guint32 type)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 size;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Data");
+
+ subtree = proto_item_add_subtree(item, ett_printerdata_data);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_printerdata_size, &size);
+
+ if (size) {
+
+ offset = dissect_ndr_uint8s(
+ tvb, offset, pinfo, subtree, drep,
+ hf_printerdata_data, size, NULL);
+
+ switch(type) {
+ case DCERPC_REG_SZ: {
+ char *data = tvb_fake_unicode(tvb, offset - size, size/2, TRUE);
+
+ proto_item_append_text(item, ": %s", data);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, " = %s", data);
+
+ proto_tree_add_string_hidden(
+ tree, hf_printerdata_data_sz, tvb,
+ offset - size, size, data);
+
+ g_free(data);
+
+ break;
+ }
+ case DCERPC_REG_DWORD: {
+ guint32 data = tvb_get_letohl(tvb, offset - size);
+
+ proto_item_append_text(item, ": 0x%08x", data);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, " = 0x%08x",
+ data);
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata_data_dword, tvb,
+ offset - size, 4, data);
+
+ break;
+ }
+ case DCERPC_REG_BINARY:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO,
+ " = <binary data>");
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ proto_item_set_len(item, size + 4);
+
+ return offset;
+}
+
+/*
+ * SpoolssGetPrinterData
+ */
+
+static int SpoolssGetPrinterData_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ char *value_name;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ value_name = dcv->private_data;
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_printerdata_value, TRUE, value_name ? NULL : &value_name);
+
+ dcv->private_data = value_name;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static int SpoolssGetPrinterData_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 type;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_printerdata_type, &type);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ char *data = dcv->private_data ? dcv->private_data : "????";
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", data);
+ }
+
+ offset = dissect_printerdata_data(
+ tvb, offset, pinfo, tree, drep, type);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * SpoolssGetPrinterDataEx
+ */
+
+static int SpoolssGetPrinterDataEx_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ char *key_name, *value_name;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_printerdata_key, TRUE, &key_name);
+
+ /*
+ * Register a cleanup function in case on of our tvbuff accesses
+ * throws an exception. We need to clean up key_name.
+ */
+ CLEANUP_PUSH(g_free, key_name);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_printerdata_value, TRUE, &value_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
+ key_name, value_name);
+
+ if (!dcv->private_data)
+ dcv->private_data = g_strdup_printf(
+ "%s/%s", key_name, value_name);
+
+ /*
+ * We're done with key_name, so we can call the cleanup handler to
+ * free it, and then pop the cleanup handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
+ /*
+ * We're also done with value_name.
+ */
+ g_free(value_name);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ return offset;
+}
+
+static int SpoolssGetPrinterDataEx_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 size, type;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printerdata_type, &type);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_returned, &size);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ char *data = dcv->private_data ? dcv->private_data : "????";
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", data);
+ }
+
+ if (size)
+ dissect_printerdata_data(tvb, offset, pinfo, tree, drep, type);
+
+ offset += size;
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * SpoolssSetPrinterData
+ */
+
+static int SpoolssSetPrinterData_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ char *value_name = NULL;
+ guint32 type;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_printerdata_value, TRUE, &value_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
+
+ g_free(value_name);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_printerdata_type, &type);
+
+ offset = dissect_printerdata_data(
+ tvb, offset, pinfo, tree, drep, type);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static int SpoolssSetPrinterData_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * SpoolssSetPrinterDataEx
+ */
+
+static int hf_setprinterdataex_max_len = -1;
+static int hf_setprinterdataex_real_len = -1;
+static int hf_setprinterdataex_data = -1;
+
+static int SpoolssSetPrinterDataEx_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ char *key_name, *value_name;
+ guint32 max_len;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_printerdata_key, TRUE, &key_name);
+
+ CLEANUP_PUSH(g_free, key_name);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_printerdata_value, TRUE, &value_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s/%s",
+ key_name, value_name);
+
+ CLEANUP_CALL_AND_POP;
+ g_free(value_name);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_printerdata_type, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_setprinterdataex_max_len, &max_len);
+
+ offset = dissect_ndr_uint8s(
+ tvb, offset, pinfo, tree, drep,
+ hf_setprinterdataex_data, max_len, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_setprinterdataex_real_len, NULL);
+
+ return offset;
+}
+
+static int SpoolssSetPrinterDataEx_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/* Yet another way to represent a unicode string - sheesh. This function
+ dissects a NULL terminate unicode string at the current offset and
+ returns the (char *) equivalent. This really should return UTF8 or
+ something but we use tvb_fake_unicode() instead. */
+
+/* XXX - "name" should be an hf_ value for an FT_STRING. */
+static int
+dissect_spoolss_uint16uni(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep _U_, char **data,
+ char *name)
+{
+ gint len, remaining;
+ char *text;
+
+ if (offset % 2)
+ offset += 2 - (offset % 2);
+
+ /* Get remaining data in buffer as a string */
+
+ remaining = tvb_length_remaining(tvb, offset) / 2;
+ text = tvb_fake_unicode(tvb, offset, remaining, TRUE);
+ len = strlen(text);
+
+ proto_tree_add_text(tree, tvb, offset, len * 2, "%s: %s",
+ name ? name : "String", text);
+
+ if (data)
+ *data = text;
+ else
+ g_free(text);
+
+ return offset + (len + 1) * 2;
+}
+
+/*
+ * DEVMODE
+ */
+
+/* Devicemode orientation values */
+
+static const value_string devmode_orientation_vals[] =
+{
+ { DEVMODE_ORIENTATION_PORTRAIT, "Portrait" },
+ { DEVMODE_ORIENTATION_LANDSCAPE, "Landscape" },
+ { 0, NULL }
+};
+
+/* Paper size values. International paper sizes is a fascinating
+ topic. No seriously! (-: */
+
+static const value_string devmode_papersize_vals[] =
+{
+ { DEVMODE_PAPERSIZE_LETTER, "Letter" },
+ { DEVMODE_PAPERSIZE_LETTERSMALL, "Letter (small)" },
+ { DEVMODE_PAPERSIZE_TABLOID, "Tabloid" },
+ { DEVMODE_PAPERSIZE_LEDGER, "Ledger" },
+ { DEVMODE_PAPERSIZE_LEGAL, "Legal" },
+ { DEVMODE_PAPERSIZE_STATEMENT, "Statement" },
+ { DEVMODE_PAPERSIZE_EXECUTIVE, "Executive" },
+ { DEVMODE_PAPERSIZE_A3, "A3" },
+ { DEVMODE_PAPERSIZE_A4, "A4" },
+ { DEVMODE_PAPERSIZE_A4SMALL, "A4 (small)" },
+ { DEVMODE_PAPERSIZE_A5, "A5" },
+ { DEVMODE_PAPERSIZE_B4, "B4" },
+ { DEVMODE_PAPERSIZE_B5, "B5" },
+ { DEVMODE_PAPERSIZE_FOLIO, "Folio" },
+ { DEVMODE_PAPERSIZE_QUARTO, "Quarto" },
+ { DEVMODE_PAPERSIZE_10X14, "10x14" },
+ { DEVMODE_PAPERSIZE_11X17, "11x17" },
+ { DEVMODE_PAPERSIZE_NOTE, "Note" },
+ { DEVMODE_PAPERSIZE_ENV9, "Envelope #9" },
+ { DEVMODE_PAPERSIZE_ENV10, "Envelope #10" },
+ { DEVMODE_PAPERSIZE_ENV11, "Envelope #11" },
+ { DEVMODE_PAPERSIZE_ENV12, "Envelope #12" },
+ { DEVMODE_PAPERSIZE_ENV14, "Envelope #14" },
+ { DEVMODE_PAPERSIZE_CSHEET, "C sheet" },
+ { DEVMODE_PAPERSIZE_DSHEET, "D sheet" },
+ { DEVMODE_PAPERSIZE_ESHEET, "E sheet" },
+ { DEVMODE_PAPERSIZE_ENVDL, "Envelope DL" },
+ { DEVMODE_PAPERSIZE_ENVC5, "Envelope C5" },
+ { DEVMODE_PAPERSIZE_ENVC3, "Envelope C3" },
+ { DEVMODE_PAPERSIZE_ENVC4, "Envelope C4" },
+ { DEVMODE_PAPERSIZE_ENVC6, "Envelope C6" },
+ { DEVMODE_PAPERSIZE_ENVC65, "Envelope C65" },
+ { DEVMODE_PAPERSIZE_ENVB4, "Envelope B4" },
+ { DEVMODE_PAPERSIZE_ENVB5, "Envelope B5" },
+ { DEVMODE_PAPERSIZE_ENVB6, "Envelope B6" },
+ { DEVMODE_PAPERSIZE_ENVITALY, "Envelope (Italy)" },
+ { DEVMODE_PAPERSIZE_ENVMONARCH, "Envelope (Monarch)" },
+ { DEVMODE_PAPERSIZE_ENVPERSONAL, "Envelope (Personal)" },
+ { DEVMODE_PAPERSIZE_FANFOLDUS, "Fanfold (US)" },
+ { DEVMODE_PAPERSIZE_FANFOLDSTDGERMAN, "Fanfold (Std German)" },
+ { DEVMODE_PAPERSIZE_FANFOLDLGLGERMAN, "Fanfold (Legal German)" },
+ { DEVMODE_PAPERSIZE_ISOB4, "B4 (ISO)" },
+ { DEVMODE_PAPERSIZE_JAPANESEPOSTCARD, "Japanese postcard" },
+ { DEVMODE_PAPERSIZE_9X11, "9x11" },
+ { DEVMODE_PAPERSIZE_10X11, "10x11" },
+ { DEVMODE_PAPERSIZE_15X11, "15x11" },
+ { DEVMODE_PAPERSIZE_ENVINVITE, "Envelope (Invite)" },
+ { DEVMODE_PAPERSIZE_RESERVED48, "Reserved (48)" },
+ { DEVMODE_PAPERSIZE_RESERVED49, "Reserved (49)" },
+ { DEVMODE_PAPERSIZE_LETTEREXTRA, "Letter (Extra)" },
+ { DEVMODE_PAPERSIZE_LEGALEXTRA, "Legal (Extra)" },
+ { DEVMODE_PAPERSIZE_TABLOIDEXTRA, "Tabloid (Extra)" },
+ { DEVMODE_PAPERSIZE_A4EXTRA, "A4 (Extra)" },
+ { DEVMODE_PAPERSIZE_LETTERTRANS, "Letter (Transverse)" },
+ { DEVMODE_PAPERSIZE_A4TRANS, "A4 (Transverse)" },
+ { DEVMODE_PAPERSIZE_LETTEREXTRATRANS, "Letter (Extra, Transverse)" },
+ { DEVMODE_PAPERSIZE_APLUS, "A+" },
+ { DEVMODE_PAPERSIZE_BPLUS, "B+" },
+ { DEVMODE_PAPERSIZE_LETTERPLUS, "Letter+" },
+ { DEVMODE_PAPERSIZE_A4PLUS, "A4+" },
+ { DEVMODE_PAPERSIZE_A5TRANS, "A5 (Transverse)" },
+ { DEVMODE_PAPERSIZE_B5TRANS, "B5 (Transverse)" },
+ { DEVMODE_PAPERSIZE_A3EXTRA, "A3 (Extra)" },
+ { DEVMODE_PAPERSIZE_A5EXTRA, "A5 (Extra)" },
+ { DEVMODE_PAPERSIZE_B5EXTRA, "B5 (Extra)" },
+ { DEVMODE_PAPERSIZE_A2, "A2" },
+ { DEVMODE_PAPERSIZE_A3TRANS, "A3 (Transverse)" },
+ { DEVMODE_PAPERSIZE_A3EXTRATRANS, "A3 (Extra, Transverse" },
+ { DEVMODE_PAPERSIZE_DBLJAPANESEPOSTCARD, "Double Japanese Postcard" },
+ { DEVMODE_PAPERSIZE_A6, "A6" },
+ { DEVMODE_PAPERSIZE_JENVKAKU2, "Japanese Envelope (Kaku #2)" },
+ { DEVMODE_PAPERSIZE_JENVKAKU3, "Japanese Envelope (Kaku #3)" },
+ { DEVMODE_PAPERSIZE_JENVCHOU3, "Japanese Envelope (Chou #3)" },
+ { DEVMODE_PAPERSIZE_JENVCHOU4, "Japaneve Envelope (Chou #4)" },
+ { DEVMODE_PAPERSIZE_LETTERROT, "Letter (Rotated)" },
+ { DEVMODE_PAPERSIZE_A3ROT, "A3 (Rotated)" },
+ { DEVMODE_PAPERSIZE_A4ROT, "A4 (Rotated)" },
+ { DEVMODE_PAPERSIZE_A5ROT, "A5 (Rotated)" },
+ { DEVMODE_PAPERSIZE_B4JISROT, "B4 (JIS, Rotated)" },
+ { DEVMODE_PAPERSIZE_B5JISROT, "B5 (JIS, Rotated)"},
+ { DEVMODE_PAPERSIZE_JAPANESEPOSTCARDROT,
+ "Japanese Postcard (Rotated)" },
+ { DEVMODE_PAPERSIZE_DBLJAPANESEPOSTCARDROT82,
+ "Double Japanese Postcard (Rotated)" },
+ { DEVMODE_PAPERSIZE_A6ROT, "A6 (Rotated)" },
+ { DEVMODE_PAPERSIZE_JENVKAKU2ROT,
+ "Japanese Envelope (Kaku #2, Rotated)" },
+ { DEVMODE_PAPERSIZE_JENVKAKU3ROT,
+ "Japanese Envelope (Kaku #3, Rotated)" },
+ { DEVMODE_PAPERSIZE_JENVCHOU3ROT,
+ "Japanese Envelope (Chou #3, Rotated)" },
+ { DEVMODE_PAPERSIZE_JENVCHOU4ROT,
+ "Japanese Envelope (Chou #4, Rotated)" },
+ { DEVMODE_PAPERSIZE_B6JIS, "B6 (JIS)" },
+ { DEVMODE_PAPERSIZE_B6JISROT, "B6 (JIS, Rotated)" },
+ { DEVMODE_PAPERSIZE_12X11, "12x11" },
+ { DEVMODE_PAPERSIZE_JENVYOU4, "Japanese Envelope (You #4)" },
+ { DEVMODE_PAPERSIZE_JENVYOU4ROT,
+ "Japanese Envelope (You #4, Rotated" },
+ { DEVMODE_PAPERSIZE_P16K, "PRC 16K" },
+ { DEVMODE_PAPERSIZE_P32K, "PRC 32K" },
+ { DEVMODE_PAPERSIZE_P32KBIG, "P32K (Big)" },
+ { DEVMODE_PAPERSIZE_PENV1, "PRC Envelope #1" },
+ { DEVMODE_PAPERSIZE_PENV2, "PRC Envelope #2" },
+ { DEVMODE_PAPERSIZE_PENV3, "PRC Envelope #3" },
+ { DEVMODE_PAPERSIZE_PENV4, "PRC Envelope #4" },
+ { DEVMODE_PAPERSIZE_PENV5, "PRC Envelope #5" },
+ { DEVMODE_PAPERSIZE_PENV6, "PRC Envelope #6" },
+ { DEVMODE_PAPERSIZE_PENV7, "PRC Envelope #7" },
+ { DEVMODE_PAPERSIZE_PENV8, "PRC Envelope #8" },
+ { DEVMODE_PAPERSIZE_PENV9, "PRC Envelope #9" },
+ { DEVMODE_PAPERSIZE_PENV10, "PRC Envelope #10" },
+ { DEVMODE_PAPERSIZE_P16KROT, "PRC 16K (Rotated)" },
+ { DEVMODE_PAPERSIZE_P32KROT, "PRC 32K (Rotated)" },
+ { DEVMODE_PAPERSIZE_P32KBIGROT, "PRC 32K (Big, Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV1ROT, "PRC Envelope #1 (Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV2ROT, "PRC Envelope #2 (Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV3ROT, "PRC Envelope #3 (Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV4ROT, "PRC Envelope #4 (Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV5ROT, "PRC Envelope #5 (Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV6ROT, "PRC Envelope #6 (Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV7ROT, "PRC Envelope #7 (Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV8ROT, "PRC Envelope #8 (Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV9ROT, "PRC Envelope #9 (Rotated)" },
+ { DEVMODE_PAPERSIZE_PENV10ROT, "PRC Envelope #10 (Rotated)" },
+ { 0, NULL }
+};
+
+/* List of observed specversions */
+
+static const value_string devmode_specversion_vals[] =
+{
+ { 0x0320, "Observed" },
+ { 0x0400, "Observed" },
+ { 0x0401, "Observed" },
+ { 0x040d, "Observed" },
+ { 0, NULL }
+};
+
+/* Paper sources */
+
+static const value_string devmode_papersource_vals[] =
+{
+ { DEVMODE_PAPERSOURCE_UPPER, "Upper" },
+ { DEVMODE_PAPERSOURCE_LOWER, "Lower" },
+ { DEVMODE_PAPERSOURCE_MIDDLE, "Middle" },
+ { DEVMODE_PAPERSOURCE_MANUAL, "Manual" },
+ { DEVMODE_PAPERSOURCE_ENV, "Envelope" },
+ { DEVMODE_PAPERSOURCE_ENVMANUAL, "Envelope Manual" },
+ { DEVMODE_PAPERSOURCE_AUTO, "Auto" },
+ { DEVMODE_PAPERSOURCE_TRACTOR, "Tractor" },
+ { DEVMODE_PAPERSOURCE_SMALLFMT, "Small Format" },
+ { DEVMODE_PAPERSOURCE_LARGEFMAT, "Large Format" },
+ { DEVMODE_PAPERSOURCE_LARGECAP, "Large Capacity" },
+ { DEVMODE_PAPERSOURCE_CASSETTE, "Cassette" },
+ { DEVMODE_PAPERSOURCE_FORMSRC, "Form Source" },
+ { 0, NULL }
+};
+
+/* Print quality */
+
+static const value_string devmode_printquality_vals[] =
+{
+ { DEVMODE_PRINTQUALITY_HIGH, "High" },
+ { DEVMODE_PRINTQUALITY_MEDIUM, "Medium" },
+ { DEVMODE_PRINTQUALITY_LOW, "Low" },
+ { DEVMODE_PRINTQUALITY_DRAFT, "Draft" },
+ { 0, NULL }
+};
+
+/* Color */
+
+static const value_string devmode_colour_vals[] =
+{
+ { DEVMODE_COLOUR_COLOUR, "Colour" },
+ { DEVMODE_COLOUR_MONO, "Monochrome" },
+ { 0, NULL }
+};
+
+/* TrueType options */
+
+static const value_string devmode_ttoption_vals[] =
+{
+ { 0, "Not set" },
+ { DEVMODE_TTOPTION_BITMAP, "Bitmap" },
+ { DEVMODE_TTOPTION_DOWNLOAD, "Download" },
+ { DEVMODE_TTOPTION_DOWNLOAD_OUTLINE, "Download outline" },
+ { DEVMODE_TTOPTION_SUBDEV, "Substitute device fonts" },
+ { 0, NULL }
+};
+
+/* Collate info */
+
+static const value_string devmode_collate_vals[] =
+{
+ { DEVMODE_COLLATE_FALSE, "False" },
+ { DEVMODE_COLLATE_TRUE, "True" },
+ { 0, NULL }
+};
+
+/* Duplex info */
+
+static const value_string devmode_duplex_vals[] =
+{
+ { DEVMODE_DUPLEX_SIMPLEX, "Simplex" },
+ { DEVMODE_DUPLEX_VERT, "Vertical" },
+ { DEVMODE_DUPLEX_HORIZ, "Horizontal" },
+ { 0, NULL }
+};
+
+static const value_string devmode_displayflags_vals[] =
+{
+ { 0, "Colour" },
+ { DEVMODE_DISPLAYFLAGS_GRAYSCALE, "Grayscale" },
+ { DEVMODE_DISPLAYFLAGS_INTERLACED, "Interlaced" },
+ { 0, NULL }
+};
+
+static const value_string devmode_icmmethod_vals[] =
+{
+ { DEVMODE_ICMMETHOD_NONE, "None" },
+ { DEVMODE_ICMMETHOD_SYSTEM, "System" },
+ { DEVMODE_ICMMETHOD_DRIVER, "Driver" },
+ { DEVMODE_ICMMETHOD_DEVICE, "Device" },
+ { 0, NULL }
+};
+
+static const value_string devmode_icmintent_vals[] =
+{
+ { 0, "Not set" },
+ { DEVMODE_ICMINTENT_SATURATE, "Saturate" },
+ { DEVMODE_ICMINTENT_CONTRAST, "Contrast" },
+ { DEVMODE_ICMINTENT_COLORIMETRIC, "Colorimetric" },
+ { DEVMODE_ICMINTENT_ABS_COLORIMETRIC, "Absolute colorimetric" },
+ { 0, NULL }
+};
+
+static const value_string devmode_mediatype_vals[] =
+{
+ { 0, "Not set" },
+ { DEVMODE_MEDIATYPE_STANDARD, "Standard" },
+ { DEVMODE_MEDIATYPE_TRANSPARENCY, "Transparency" },
+ { DEVMODE_MEDIATYPE_GLOSSY, "Glossy" },
+ { 0, NULL }
+};
+
+static const value_string devmode_dithertype_vals[] =
+{
+ { 0, "Not set" },
+ { DEVMODE_DITHERTYPE_NONE, "None" },
+ { DEVMODE_DITHERTYPE_COARSE, "Coarse" },
+ { DEVMODE_DITHERTYPE_LINE, "Line" },
+ { DEVMODE_DITHERTYPE_LINEART, "Line art" },
+ { DEVMODE_DITHERTYPE_ERRORDIFFUSION, "Error diffusion" },
+ { DEVMODE_DITHERTYPE_RESERVED6, "Reserved 6" },
+ { DEVMODE_DITHERTYPE_RESERVED7, "Reserved 7" },
+ { DEVMODE_DITHERTYPE_GRAYSCALE, "Grayscale" },
+ { 0, NULL }
+};
+
+static gint ett_DEVMODE_fields;
+
+static int
+dissect_DEVMODE_fields(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_, guint32 *pdata)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 fields;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_devmode, tvb, offset, 0, 1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_devmode_fields, &fields);
+
+ item = proto_tree_add_text(tree, tvb, offset - 4, 4,
+ "Fields: 0x%08x", fields);
+
+ subtree = proto_item_add_subtree(item, ett_DEVMODE_fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_orientation,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_papersize,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_paperlength,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_paperwidth,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_scale,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_position,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_nup,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_copies,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_defaultsource,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_printquality,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_color,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_duplex,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_yresolution,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_ttoption,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_collate,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_formname,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_logpixels,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_bitsperpel,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_pelswidth,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_pelsheight,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_displayflags,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_displayfrequency,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_icmmethod,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_icmintent,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_mediatype,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_dithertype,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_panningwidth,
+ tvb, offset - 4, 4, fields);
+
+ proto_tree_add_boolean(
+ subtree, hf_devmode_fields_panningheight,
+ tvb, offset - 4, 4, fields);
+
+ if (pdata)
+ *pdata = fields;
+
+ return offset;
+}
+
+static gint ett_DEVMODE = -1;
+
+static int dissect_DEVMODE(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = pinfo->private_data;
+ proto_item *item;
+ proto_tree *subtree;
+ guint16 driver_extra;
+ gint16 print_quality;
+ guint32 fields;
+ int struct_start = offset;
+
+ if (di->conformant_run)
+ return offset;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Devicemode");
+ subtree = proto_item_add_subtree(item, ett_DEVMODE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_devmode_size,
+ NULL);
+
+ /* The device name is stored in a 32-wchar buffer */
+
+ dissect_spoolss_uint16uni(tvb, offset, pinfo, subtree, drep, NULL,
+ "Devicename");
+ offset += 64;
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_spec_version, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_driver_version, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_size2, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_driver_extra_len, &driver_extra);
+
+ offset = dissect_DEVMODE_fields(
+ tvb, offset, pinfo, subtree, drep, &fields);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_orientation, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_paper_size, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_paper_length, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_paper_width, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_scale, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_copies, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_default_source, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, NULL, drep,
+ hf_devmode_print_quality, &print_quality);
+
+ if (print_quality < 0)
+ proto_tree_add_item(
+ subtree, hf_devmode_print_quality, tvb,
+ offset - 2, 2, drep[0] & 0x10);
+ else
+ proto_tree_add_text(
+ subtree, tvb, offset - 4, 4,
+ "Print Quality: %d dpi", print_quality);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_color, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_duplex, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_y_resolution, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_tt_option, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_collate, NULL);
+
+ dissect_spoolss_uint16uni(tvb, offset, pinfo, subtree, drep, NULL,
+ "Form name");
+ offset += 64;
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_log_pixels, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_bits_per_pel, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_pels_width, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_pels_height, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_display_flags, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_display_freq, NULL);
+
+ /* TODO: Some of the remaining fields are optional. See
+ rpc_parse/parse_spoolss.c in the Samba source for details. */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_icm_method, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_icm_intent, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_media_type, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_dither_type, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_reserved1, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_reserved2, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_panning_width, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_panning_height, NULL);
+
+ if (driver_extra)
+ offset = dissect_ndr_uint8s(
+ tvb, offset, pinfo, subtree, drep,
+ hf_devmode_driver_extra, driver_extra, NULL);
+
+ proto_item_set_len(item, offset - struct_start);
+
+ return offset;
+}
+
+/*
+ * DEVMODE_CTR
+ */
+
+static gint ett_DEVMODE_CTR = -1;
+
+static int dissect_DEVMODE_CTR(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 size;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Devicemode container");
+
+ subtree = proto_item_add_subtree(item, ett_DEVMODE_CTR);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_devmodectr_size, &size);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, subtree, drep,
+ dissect_DEVMODE, NDR_POINTER_UNIQUE, "Devicemode", -1);
+
+ return offset;
+}
+
+/*
+ * Relative string given by offset into the current buffer. Note that
+ * the offset for subsequent relstrs are against the structure start, not
+ * the point where the offset is parsed from.
+ */
+
+static gint ett_RELSTR = -1;
+
+static int
+dissect_spoolss_relstr(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, int hf_index,
+ int struct_start, char **data)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 relstr_offset, relstr_start, relstr_end;
+ char *text;
+
+ /* Peek ahead to read the string. We need this for the
+ proto_tree_add_string() call so filtering will work. */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_offset, &relstr_offset);
+
+ relstr_start = relstr_offset + struct_start;
+
+ if (relstr_offset)
+ relstr_end = dissect_spoolss_uint16uni(
+ tvb, relstr_start, pinfo, NULL, drep, &text, NULL);
+ else /* relstr_offset == 0 is a NULL string */
+ text = g_strdup("");
+
+ /* OK now add the proto item with the string value */
+
+ item = proto_tree_add_string(tree, hf_index, tvb, offset, 4, text);
+ subtree = proto_item_add_subtree(item, ett_RELSTR);
+
+ dissect_ndr_uint32(
+ tvb, offset - 4, pinfo, subtree, drep, hf_offset, NULL);
+
+ if (relstr_offset)
+ dissect_spoolss_uint16uni(
+ tvb, relstr_start, pinfo, subtree, drep, NULL, NULL);
+
+ if (data)
+ *data = text;
+ else
+ g_free(text);
+
+ return offset;
+}
+
+/* An array of relative strings. This is currently just a copy of the
+ dissect_spoolss_relstr() function as I can't find an example driver that
+ has more than one dependent file. */
+
+static gint ett_RELSTR_ARRAY = -1;
+
+static int
+dissect_spoolss_relstrarray(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, int hf_index,
+ int struct_start, char **data)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 relstr_offset, relstr_start, relstr_end, relstr_len;
+ char *text;
+
+ item = proto_tree_add_string(tree, hf_index, tvb, offset, 4, "");
+
+ subtree = proto_item_add_subtree(item, ett_RELSTR_ARRAY);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_offset, &relstr_offset);
+
+ /* A relative offset of zero is a NULL string */
+
+ relstr_start = relstr_offset + struct_start;
+
+ if (relstr_offset)
+ relstr_end = dissect_spoolss_uint16uni(
+ tvb, relstr_start, pinfo, subtree, drep, &text, NULL);
+ else {
+ text = g_strdup("NULL");
+ relstr_end = offset;
+ }
+
+ relstr_len = relstr_end - relstr_start;
+
+ proto_item_append_text(item, text);
+
+ if (data)
+ *data = text;
+ else
+ g_free(text);
+
+ return offset;
+}
+
+/*
+ * PRINTER_INFO_0
+ */
+
+static int hf_printer_status = -1;
+
+static const value_string printer_status_vals[] =
+{
+ { PRINTER_STATUS_OK, "OK" },
+ { PRINTER_STATUS_PAUSED, "Paused" },
+ { PRINTER_STATUS_ERROR, "Error" },
+ { PRINTER_STATUS_PENDING_DELETION, "Pending deletion" },
+ { PRINTER_STATUS_PAPER_JAM, "Paper jam" },
+ { PRINTER_STATUS_PAPER_OUT, "Paper out" },
+ { PRINTER_STATUS_MANUAL_FEED, "Manual feed" },
+ { PRINTER_STATUS_PAPER_PROBLEM, "Paper problem" },
+ { PRINTER_STATUS_OFFLINE, "Offline" },
+ { PRINTER_STATUS_IO_ACTIVE, "IO active" },
+ { PRINTER_STATUS_BUSY, "Busy" },
+ { PRINTER_STATUS_PRINTING, "Printing" },
+ { PRINTER_STATUS_OUTPUT_BIN_FULL, "Output bin full" },
+ { PRINTER_STATUS_NOT_AVAILABLE, "Not available" },
+ { PRINTER_STATUS_WAITING, "Waiting" },
+ { PRINTER_STATUS_PROCESSING, "Processing" },
+ { PRINTER_STATUS_INITIALIZING, "Initialising" },
+ { PRINTER_STATUS_WARMING_UP, "Warming up" },
+ { PRINTER_STATUS_TONER_LOW, "Toner low" },
+ { PRINTER_STATUS_NO_TONER, "No toner" },
+ { PRINTER_STATUS_PAGE_PUNT, "Page punt" },
+ { PRINTER_STATUS_USER_INTERVENTION, "User intervention" },
+ { PRINTER_STATUS_OUT_OF_MEMORY, "Out of memory" },
+ { PRINTER_STATUS_DOOR_OPEN, "Door open" },
+ { PRINTER_STATUS_SERVER_UNKNOWN, "Server unknown" },
+ { PRINTER_STATUS_POWER_SAVE, "Power save" },
+ { 0, NULL }
+};
+
+static gint ett_PRINTER_INFO_0 = -1;
+
+static int dissect_PRINTER_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_printername,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_servername,
+ 0, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_cjobs, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_total_jobs,
+ NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_total_bytes,
+ NULL);
+
+ offset = dissect_SYSTEM_TIME(
+ tvb, offset, pinfo, tree, drep, "Unknown time", TRUE, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_global_counter,
+ NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_total_pages,
+ NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_major_version,
+ NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_build_version,
+ NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk7, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk8, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk9, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_session_ctr,
+ NULL);
+
+ offset = dissect_ndr_uint32( tvb, offset, pinfo, tree, drep,
+ hf_printer_unk11, NULL);
+
+ offset = dissect_ndr_uint32( tvb, offset, pinfo, tree, drep,
+ hf_printer_printer_errors, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk13, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk14, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk15, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk16, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_changeid, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk18, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_status, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk20, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printer_c_setprinter,
+ NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk22, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk23, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk24, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk25, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk26, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk27, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk28, NULL);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, tree, drep, hf_printer_unk29, NULL);
+
+ return offset;
+}
+
+/*
+ * PRINTER_INFO_1
+ */
+
+static gint ett_PRINTER_INFO_1 = -1;
+
+static int dissect_PRINTER_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_printer_flags, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_printerdesc,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_printername,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_printercomment,
+ 0, NULL);
+
+ return offset;
+}
+
+/* Job status */
+
+static const true_false_string tfs_job_status_paused = {
+ "Job is paused",
+ "Job is not paused"
+};
+
+static const true_false_string tfs_job_status_error = {
+ "Job has an error",
+ "Job is OK"
+};
+
+static const true_false_string tfs_job_status_deleting = {
+ "Job is being deleted",
+ "Job is not being deleted"
+};
+
+static const true_false_string tfs_job_status_spooling = {
+ "Job is being spooled",
+ "Job is not being spooled"
+};
+
+static const true_false_string tfs_job_status_printing = {
+ "Job is being printed",
+ "Job is not being printed"
+};
+
+static const true_false_string tfs_job_status_offline = {
+ "Job is offline",
+ "Job is not offline"
+};
+
+static const true_false_string tfs_job_status_paperout = {
+ "Job is out of paper",
+ "Job is not out of paper"
+};
+
+static const true_false_string tfs_job_status_printed = {
+ "Job has completed printing",
+ "Job has not completed printing"
+};
+
+static const true_false_string tfs_job_status_deleted = {
+ "Job has been deleted",
+ "Job has not been deleted"
+};
+
+static const true_false_string tfs_job_status_blocked = {
+ "Job has been blocked",
+ "Job has not been blocked"
+};
+
+static const true_false_string tfs_job_status_user_intervention = {
+ "User intervention required",
+ "User intervention not required"
+};
+
+static gint ett_job_status = -1;
+
+static int
+dissect_job_status(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 status;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_job_status, &status);
+
+ item = proto_tree_add_text(tree, tvb, offset - 4, 4,
+ "Status: 0x%08x", status);
+
+ subtree = proto_item_add_subtree(item, ett_job_status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_user_intervention, tvb, offset - 4, 4,
+ status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_blocked, tvb, offset - 4, 4, status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_deleted, tvb, offset - 4, 4, status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_printed, tvb, offset - 4, 4, status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_paperout, tvb, offset - 4, 4, status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_offline, tvb, offset - 4, 4, status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_printing, tvb, offset - 4, 4, status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_spooling, tvb, offset - 4, 4, status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_deleting, tvb, offset - 4, 4, status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_error, tvb, offset - 4, 4, status);
+
+ proto_tree_add_boolean(
+ subtree, hf_job_status_paused, tvb, offset - 4, 4, status);
+
+ return offset;
+}
+
+/* Printer attributes */
+
+static gint ett_printer_attributes = -1;
+
+static int hf_printer_attributes = -1;
+static int hf_printer_attributes_queued = -1;
+static int hf_printer_attributes_direct = -1;
+static int hf_printer_attributes_default = -1;
+static int hf_printer_attributes_shared = -1;
+static int hf_printer_attributes_network = -1;
+static int hf_printer_attributes_hidden = -1;
+static int hf_printer_attributes_local = -1;
+static int hf_printer_attributes_enable_devq = -1;
+static int hf_printer_attributes_keep_printed_jobs = -1;
+static int hf_printer_attributes_do_complete_first = -1;
+static int hf_printer_attributes_work_offline = -1;
+static int hf_printer_attributes_enable_bidi = -1;
+static int hf_printer_attributes_raw_only = -1;
+static int hf_printer_attributes_published = -1;
+
+static const true_false_string tfs_printer_attributes_queued = {
+ "Printer starts printing after last page spooled",
+ "Printer starts printing while spooling"
+};
+
+static const true_false_string tfs_printer_attributes_direct = {
+ "Jobs sent directly to printer",
+ "Jobs are spooled to printer before printing"
+};
+
+static const true_false_string tfs_printer_attributes_default = {
+ "Printer is the default printer",
+ "Printer is not the default printer"
+};
+
+static const true_false_string tfs_printer_attributes_shared = {
+ "Printer is shared",
+ "Printer is not shared"
+};
+
+static const true_false_string tfs_printer_attributes_network = {
+ "Printer is a network printer connection",
+ "Printer is not a network printer connection"
+};
+
+static const true_false_string tfs_printer_attributes_hidden = {
+ "Reserved",
+ "Reserved"
+};
+
+static const true_false_string tfs_printer_attributes_local = {
+ "Printer is a local printer",
+ "Printer is not a local printer"
+};
+
+static const true_false_string tfs_printer_attributes_enable_devq = {
+ "Call DevQueryPrint",
+ "Do not call DevQueryPrint"
+};
+
+static const true_false_string tfs_printer_attributes_keep_printed_jobs = {
+ "Jobs are kept after they are printed",
+ "Jobs are deleted after printing"
+};
+
+static const true_false_string tfs_printer_attributes_do_complete_first = {
+ "Jobs that have completed spooling are scheduled before still spooling jobs",
+ "Jobs are scheduled in the order they start spooling"
+};
+
+static const true_false_string tfs_printer_attributes_work_offline = {
+ "The printer is currently connected",
+ "The printer is currently not connected"
+};
+
+static const true_false_string tfs_printer_attributes_enable_bidi = {
+ "Bidirectional communications are supported",
+ "Bidirectional communications are not supported"
+};
+
+static const true_false_string tfs_printer_attributes_raw_only = {
+ "Only raw data type print jobs can be spooled",
+ "All data type print jobs can be spooled"
+};
+
+static const true_false_string tfs_printer_attributes_published = {
+ "Printer is published in the directory",
+ "Printer is not published in the directory"
+};
+
+static int
+dissect_printer_attributes(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 attributes;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_printer_attributes, &attributes);
+
+ item = proto_tree_add_text(tree, tvb, offset - 4, 4,
+ "Attributes: 0x%08x", attributes);
+
+ subtree = proto_item_add_subtree(item, ett_printer_attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_published,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_raw_only,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_enable_bidi,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_work_offline,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_do_complete_first,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_keep_printed_jobs,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_enable_devq,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_local,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_hidden,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_network,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_shared,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_default,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_direct,
+ tvb, offset - 4, 4, attributes);
+
+ proto_tree_add_boolean(
+ subtree, hf_printer_attributes_queued,
+ tvb, offset - 4, 4, attributes);
+
+ return offset;
+}
+
+/*
+ * PRINTER_INFO_2
+ */
+
+static gint ett_PRINTER_INFO_2 = -1;
+
+static int dissect_PRINTER_INFO_2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 devmode_offset, secdesc_offset;
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_servername,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_printername,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_sharename,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_portname,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_drivername,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_printercomment,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_printerlocation,
+ 0, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_offset,
+ &devmode_offset);
+
+ dissect_DEVMODE(tvb, devmode_offset - 4, pinfo, tree, drep);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_sepfile,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_printprocessor,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_datatype,
+ 0, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_parameters,
+ 0, NULL);
+
+ /*
+ * XXX - what *is* the length of this security descriptor?
+ * "prs_PRINTER_INFO_2()" is passed to "defer_ptr()", but
+ * "defer_ptr" takes, as an argument, a function with a
+ * different calling sequence from "prs_PRINTER_INFO_2()",
+ * lacking the "len" argument, so that won't work.
+ */
+
+ /* TODO: I think the length is only used to fix up the hex display
+ pane. We should be able to use proto_item_set_len() to avoid
+ having to calculate the length. -tpot */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_offset,
+ &secdesc_offset);
+
+ dissect_nt_sec_desc(
+ tvb, secdesc_offset, pinfo, tree, drep,
+ tvb_length_remaining(tvb, secdesc_offset),
+ &spoolss_printer_access_mask_info);
+
+ offset = dissect_printer_attributes(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_printer_priority,
+ NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep,
+ hf_printer_default_priority, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_start_time, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_end_time, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_printer_status, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_printer_jobs,
+ NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep,
+ hf_printer_averageppm, NULL);
+
+ return offset;
+}
+
+/*
+ * PRINTER_INFO_3
+ */
+
+static gint ett_PRINTER_INFO_3 = -1;
+
+static int dissect_PRINTER_INFO_3(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_printer_flags, NULL);
+
+ offset = dissect_nt_sec_desc(
+ tvb, offset, pinfo, tree, drep,
+ tvb_length_remaining(tvb, offset),
+ &spoolss_printer_access_mask_info);
+
+ return offset;
+}
+
+/*
+ * PRINTER_INFO_7
+ */
+
+static gint ett_PRINTER_INFO_7 = -1;
+
+static const value_string getprinter_action_vals[] = {
+ { DS_PUBLISH, "Publish" },
+ { DS_UNPUBLISH, "Unpublish" },
+ { DS_UPDATE, "Update" },
+
+ /* Not sure what the constant values are here */
+
+/* { DS_PENDING, "Pending" }, */
+/* { DS_REPUBLISH, "Republish" }, */
+
+ { 0, NULL }
+};
+
+static int dissect_PRINTER_INFO_7(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, tree, drep, hf_printer_guid,
+ 0, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_printer_action, NULL);
+
+ return offset;
+}
+
+/*
+ * PRINTER_DATATYPE structure
+ */
+
+static gint ett_PRINTER_DATATYPE = -1;
+
+static int dissect_PRINTER_DATATYPE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = pinfo->private_data;
+
+ if (di->conformant_run)
+ return offset;
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_datatype, TRUE, NULL);
+
+ return offset;
+}
+
+/*
+ * USER_LEVEL_1 structure
+ */
+
+static gint ett_USER_LEVEL_1 = -1;
+
+static int hf_userlevel_size = -1;
+static int hf_userlevel_client = -1;
+static int hf_userlevel_user = -1;
+static int hf_userlevel_build = -1;
+static int hf_userlevel_major = -1;
+static int hf_userlevel_minor = -1;
+static int hf_userlevel_processor = -1;
+
+static int dissect_USER_LEVEL_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ /* Guy has pointed out that this dissection looks wrong. In
+ the ethereal output for a USER_LEVEL_1 it looks like the
+ info level and container pointer are transposed. I'm not
+ even sure this structure is a container. */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, &level);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_userlevel_size, NULL);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
+ "Client", hf_userlevel_client, 0);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
+ "User", hf_userlevel_user, 0);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_userlevel_build, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_userlevel_major, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_userlevel_minor, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_userlevel_processor, NULL);
+
+ return offset;
+}
+
+/*
+ * USER_LEVEL_CTR structure
+ */
+
+static gint ett_USER_LEVEL_CTR = -1;
+
+static int dissect_USER_LEVEL_CTR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = pinfo->private_data;
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 level;
+
+ if (di->conformant_run)
+ return offset;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "User level container");
+
+ subtree = proto_item_add_subtree(item, ett_USER_LEVEL_CTR);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_level, &level);
+
+ switch(level) {
+ case 1:
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, subtree, drep,
+ dissect_USER_LEVEL_1, NDR_POINTER_UNIQUE,
+ "User level 1", -1);
+ break;
+ default:
+ proto_tree_add_text(
+ tree, tvb, offset, 0,
+ "[Info level %d not decoded]", level);
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * SpoolssOpenPrinterEx
+ */
+
+static int SpoolssOpenPrinterEx_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ char *name;
+
+ /* Parse packet */
+
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
+ "Printer name", hf_printername, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_PRINTER_DATATYPE, NDR_POINTER_UNIQUE,
+ "Printer datatype", -1);
+
+ offset = dissect_DEVMODE_CTR(tvb, offset, pinfo, tree, drep);
+
+ /* Luckily we can use the string stored in dcv->private_data as it
+ appears before the printer datatype since we are at the top
+ level. */
+
+ name = (char *)dcv->private_data;
+
+ if (name) {
+ if (name[0] == '\\' && name[1] == '\\')
+ name += 2;
+
+ /* Determine if we are opening a printer or a print server */
+
+ if (strchr(name, '\\'))
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep,
+ hf_access_required,
+ &spoolss_printer_access_mask_info, NULL);
+ else
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep,
+ hf_access_required,
+ &spoolss_printserver_access_mask_info, NULL);
+ } else {
+
+ /* We can't decide what type of object being opened */
+
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_access_required,
+ NULL, NULL);
+ }
+
+ offset = dissect_USER_LEVEL_CTR(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int SpoolssOpenPrinterEx_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, &status);
+
+ if (status == 0) {
+
+ /* Associate the returned printer handle with a name */
+
+ if (dcv->private_data) {
+ char *pol_name;
+
+ pol_name = g_strdup_printf(
+ "OpenPrinterEx(%s)",
+ (char *)dcv->private_data);
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ g_free(pol_name);
+ g_free(dcv->private_data);
+ dcv->private_data = NULL;
+ }
+
+ /*
+ * If we have a name for the handle, attach it to the item.
+ *
+ * XXX - we can't just do that above, as this may be called
+ * twice (see "dissect_pipe_dcerpc()", which calls the
+ * DCE RPC dissector twice), and in the first call we're
+ * not building a protocol tree (so we don't have an item
+ * to which to attach it) and in the second call
+ * "dcv->private_data" is NULL so we don't construct a
+ * name.
+ */
+
+ if (hnd_item != NULL) {
+ char *name;
+
+ if (dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL,
+ pinfo->fd->num) && name != NULL)
+ proto_item_append_text(hnd_item, ": %s", name);
+ }
+ }
+
+ return offset;
+}
+
+static const value_string printer_notify_option_data_vals[] = {
+ { PRINTER_NOTIFY_SERVER_NAME, "Server name" },
+ { PRINTER_NOTIFY_PRINTER_NAME, "Printer name" },
+ { PRINTER_NOTIFY_SHARE_NAME, "Share name" },
+ { PRINTER_NOTIFY_PORT_NAME, "Port name" },
+ { PRINTER_NOTIFY_DRIVER_NAME, "Driver name" },
+ { PRINTER_NOTIFY_COMMENT, "Comment" },
+ { PRINTER_NOTIFY_LOCATION, "Location" },
+ { PRINTER_NOTIFY_DEVMODE, "Devmode" },
+ { PRINTER_NOTIFY_SEPFILE, "Sepfile" },
+ { PRINTER_NOTIFY_PRINT_PROCESSOR, "Print processor" },
+ { PRINTER_NOTIFY_PARAMETERS, "Parameters" },
+ { PRINTER_NOTIFY_DATATYPE, "Datatype" },
+ { PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "Security descriptor" },
+ { PRINTER_NOTIFY_ATTRIBUTES, "Attributes" },
+ { PRINTER_NOTIFY_PRIORITY, "Priority" },
+ { PRINTER_NOTIFY_DEFAULT_PRIORITY, "Default priority" },
+ { PRINTER_NOTIFY_START_TIME, "Start time" },
+ { PRINTER_NOTIFY_UNTIL_TIME, "Until time" },
+ { PRINTER_NOTIFY_STATUS, "Status" },
+ { PRINTER_NOTIFY_STATUS_STRING, "Status string" },
+ { PRINTER_NOTIFY_CJOBS, "Cjobs" },
+ { PRINTER_NOTIFY_AVERAGE_PPM, "Average PPM" },
+ { PRINTER_NOTIFY_TOTAL_PAGES, "Total pages" },
+ { PRINTER_NOTIFY_PAGES_PRINTED, "Pages printed" },
+ { PRINTER_NOTIFY_TOTAL_BYTES, "Total bytes" },
+ { PRINTER_NOTIFY_BYTES_PRINTED, "Bytes printed" },
+ { 0, NULL}
+};
+
+static const value_string job_notify_option_data_vals[] = {
+ { JOB_NOTIFY_PRINTER_NAME, "Printer name" },
+ { JOB_NOTIFY_MACHINE_NAME, "Machine name" },
+ { JOB_NOTIFY_PORT_NAME, "Port name" },
+ { JOB_NOTIFY_USER_NAME, "User name" },
+ { JOB_NOTIFY_NOTIFY_NAME, "Notify name" },
+ { JOB_NOTIFY_DATATYPE, "Data type" },
+ { JOB_NOTIFY_PRINT_PROCESSOR, "Print processor" },
+ { JOB_NOTIFY_PARAMETERS, "Parameters" },
+ { JOB_NOTIFY_DRIVER_NAME, "Driver name" },
+ { JOB_NOTIFY_DEVMODE, "Devmode" },
+ { JOB_NOTIFY_STATUS, "Status" },
+ { JOB_NOTIFY_STATUS_STRING, "Status string" },
+ { JOB_NOTIFY_SECURITY_DESCRIPTOR, "Security descriptor" },
+ { JOB_NOTIFY_DOCUMENT, "Document" },
+ { JOB_NOTIFY_PRIORITY, "Priority" },
+ { JOB_NOTIFY_POSITION, "Position" },
+ { JOB_NOTIFY_SUBMITTED, "Submitted" },
+ { JOB_NOTIFY_START_TIME, "Start time" },
+ { JOB_NOTIFY_UNTIL_TIME, "Until time" },
+ { JOB_NOTIFY_TIME, "Time" },
+ { JOB_NOTIFY_TOTAL_PAGES, "Total pages" },
+ { JOB_NOTIFY_PAGES_PRINTED, "Pages printed" },
+ { JOB_NOTIFY_TOTAL_BYTES, "Total bytes" },
+ { JOB_NOTIFY_BYTES_PRINTED, "Bytes printed" },
+ { 0, NULL}
+};
+
+static int
+dissect_notify_field(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, guint16 type,
+ guint16 *data)
+{
+ guint16 field;
+ char *str;
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, NULL, drep,
+ hf_notify_field, &field);
+
+ switch(type) {
+ case PRINTER_NOTIFY_TYPE:
+ str = val_to_str(field, printer_notify_option_data_vals,
+ "Unknown");
+ break;
+ case JOB_NOTIFY_TYPE:
+ str = val_to_str(field, job_notify_option_data_vals,
+ "Unknown");
+ break;
+ default:
+ str = "Unknown notify type";
+ break;
+ }
+
+ proto_tree_add_text(tree, tvb, offset - 2, 2,
+ "Field: %s (%d)", str, field);
+
+ if (data)
+ *data = field;
+
+ return offset;
+}
+
+static int
+dissect_NOTIFY_OPTION_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 count, i;
+ guint16 type;
+
+ if (di->conformant_run)
+ return offset;
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_option_data_count, &count);
+
+ type = GPOINTER_TO_INT(dcv->private_data);
+
+ for (i = 0; i < count; i++)
+ offset = dissect_notify_field(
+ tvb, offset, pinfo, tree, drep, type, NULL);
+
+ return offset;
+}
+
+static const value_string printer_notify_types[] =
+{
+ { PRINTER_NOTIFY_TYPE, "Printer notify" },
+ { JOB_NOTIFY_TYPE, "Job notify" },
+ { 0, NULL }
+};
+
+static char *notify_plural(int count)
+{
+ if (count == 1)
+ return "notification";
+
+ return "notifies";
+}
+
+static gint ett_NOTIFY_OPTION = -1;
+
+static int
+dissect_NOTIFY_OPTION(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ proto_item *item;
+ proto_tree *subtree;
+ guint16 type;
+ guint32 count;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Notify Option");
+
+ subtree = proto_item_add_subtree(item, ett_NOTIFY_OPTION);
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
+ hf_notify_option_type, &type);
+
+ proto_item_append_text(
+ item, ": %s", val_to_str(type, printer_notify_types,
+ "Unknown (%d)"));
+
+ offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
+ hf_notify_option_reserved1, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_notify_option_reserved2, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_notify_option_reserved3, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_notify_option_count, &count);
+
+ proto_item_append_text(
+ item, ", %d %s", count, notify_plural(count));
+
+ dcv->private_data = GINT_TO_POINTER((int)type);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, subtree, drep,
+ dissect_NOTIFY_OPTION_DATA, NDR_POINTER_UNIQUE,
+ "Notify Option Data", -1);
+
+ return offset;
+}
+
+static int
+dissect_NOTIFY_OPTIONS_ARRAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* Why is a check for di->conformant_run not required here? */
+
+ offset = dissect_ndr_ucarray(
+ tvb, offset, pinfo, tree, drep, dissect_NOTIFY_OPTION);
+
+ return offset;
+}
+
+static gint ett_notify_options_flags = -1;
+
+static const true_false_string tfs_notify_options_flags_refresh = {
+ "Data for all monitored fields is present",
+ "Data for all monitored fields not present"
+};
+
+static int
+dissect_notify_options_flags(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 flags;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_notify_options_flags,
+ &flags);
+
+ item = proto_tree_add_text(tree, tvb, offset - 4, 4,
+ "Flags: 0x%08x", flags);
+
+ subtree = proto_item_add_subtree(item, ett_notify_options_flags);
+
+ proto_tree_add_boolean(
+ subtree, hf_notify_options_flags_refresh,
+ tvb, offset, 4, flags);
+
+ return offset;
+}
+
+static int
+dissect_NOTIFY_OPTIONS_ARRAY_CTR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = pinfo->private_data;
+
+ if (di->conformant_run)
+ return offset;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_notify_options_version, NULL);
+
+ offset = dissect_notify_options_flags(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_notify_options_count, NULL);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_NOTIFY_OPTIONS_ARRAY, NDR_POINTER_UNIQUE,
+ "Notify Options Array", -1);
+
+ return offset;
+}
+
+/*
+ * SpoolssRFFPCNEX
+ */
+
+static gint ett_rffpcnex_flags = -1;
+
+static int hf_rffpcnex_flags = -1;
+static int hf_rffpcnex_options = -1;
+
+static int hf_rffpcnex_flags_add_printer = -1;
+static int hf_rffpcnex_flags_set_printer = -1;
+static int hf_rffpcnex_flags_delete_printer = -1;
+static int hf_rffpcnex_flags_failed_printer_connection = -1;
+
+static const true_false_string tfs_rffpcnex_flags_add_printer = {
+ "Notify on add printer",
+ "Don't notify on add printer"
+};
+
+static const true_false_string tfs_rffpcnex_flags_set_printer = {
+ "Notify on set printer",
+ "Don't notify on set printer"
+};
+
+static const true_false_string tfs_rffpcnex_flags_delete_printer = {
+ "Notify on delete printer",
+ "Don't notify on delete printer"
+};
+
+static const true_false_string tfs_rffpcnex_flags_failed_connection_printer = {
+ "Notify on failed printer connection",
+ "Don't notify on failed printer connection"
+};
+
+static int hf_rffpcnex_flags_add_job = -1;
+static int hf_rffpcnex_flags_set_job = -1;
+static int hf_rffpcnex_flags_delete_job = -1;
+static int hf_rffpcnex_flags_write_job = -1;
+
+static const true_false_string tfs_rffpcnex_flags_add_job = {
+ "Notify on add job",
+ "Don't notify on add job"
+};
+
+static const true_false_string tfs_rffpcnex_flags_set_job = {
+ "Notify on set job",
+ "Don't notify on set job"
+};
+
+static const true_false_string tfs_rffpcnex_flags_delete_job = {
+ "Notify on delete job",
+ "Don't notify on delete job"
+};
+
+static const true_false_string tfs_rffpcnex_flags_write_job = {
+ "Notify on writejob",
+ "Don't notify on write job"
+};
+
+static int hf_rffpcnex_flags_add_form = -1;
+static int hf_rffpcnex_flags_set_form = -1;
+static int hf_rffpcnex_flags_delete_form = -1;
+
+static const true_false_string tfs_rffpcnex_flags_add_form = {
+ "Notify on add form",
+ "Don't notify on add form"
+};
+
+static const true_false_string tfs_rffpcnex_flags_set_form = {
+ "Notify on set form",
+ "Don't notify on set form"
+};
+
+static const true_false_string tfs_rffpcnex_flags_delete_form = {
+ "Notify on delete form",
+ "Don't notify on delete form"
+};
+
+static int hf_rffpcnex_flags_add_port = -1;
+static int hf_rffpcnex_flags_configure_port = -1;
+static int hf_rffpcnex_flags_delete_port = -1;
+
+static const true_false_string tfs_rffpcnex_flags_add_port = {
+ "Notify on add port",
+ "Don't notify on add port"
+};
+
+static const true_false_string tfs_rffpcnex_flags_configure_port = {
+ "Notify on configure port",
+ "Don't notify on configure port"
+};
+
+static const true_false_string tfs_rffpcnex_flags_delete_port = {
+ "Notify on delete port",
+ "Don't notify on delete port"
+};
+
+static int hf_rffpcnex_flags_add_print_processor = -1;
+static int hf_rffpcnex_flags_delete_print_processor = -1;
+
+static const true_false_string tfs_rffpcnex_flags_add_print_processor = {
+ "Notify on add driver",
+ "Don't notify on add driver"
+};
+
+static const true_false_string tfs_rffpcnex_flags_delete_print_processor = {
+ "Notify on add driver",
+ "Don't notify on add driver"
+};
+
+static int hf_rffpcnex_flags_add_driver = -1;
+static int hf_rffpcnex_flags_set_driver = -1;
+static int hf_rffpcnex_flags_delete_driver = -1;
+
+static const true_false_string tfs_rffpcnex_flags_add_driver = {
+ "Notify on add driver",
+ "Don't notify on add driver"
+};
+
+static const true_false_string tfs_rffpcnex_flags_set_driver = {
+ "Notify on set driver",
+ "Don't notify on set driver"
+};
+
+static const true_false_string tfs_rffpcnex_flags_delete_driver = {
+ "Notify on delete driver",
+ "Don't notify on delete driver"
+};
+
+static int hf_rffpcnex_flags_timeout = -1;
+
+static const true_false_string tfs_rffpcnex_flags_timeout = {
+ "Notify on timeout",
+ "Don't notify on timeout"
+};
+
+static int SpoolssRFFPCNEX_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ guint32 flags;
+ proto_item *flags_item;
+ proto_tree *flags_subtree;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hf_rffpcnex_flags, &flags);
+
+ flags_item = proto_tree_add_text(tree, tvb, offset - 4, 4,
+ "Flags: 0x%08x", flags);
+
+ flags_subtree = proto_item_add_subtree(flags_item, ett_rffpcnex_flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_timeout, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_delete_driver, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_set_driver, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_add_driver, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree,
+ hf_rffpcnex_flags_delete_print_processor, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_add_print_processor,
+ tvb, offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_delete_port, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_configure_port, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_add_port, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_delete_form, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_set_form, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_add_form, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_write_job, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_delete_job, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_set_job, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_add_job, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree,
+ hf_rffpcnex_flags_failed_printer_connection, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_delete_printer, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_set_printer, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_rffpcnex_flags_add_printer, tvb,
+ offset - 4, 4, flags);
+
+ if (flags & SPOOLSS_PRINTER_CHANGE_PRINTER)
+ proto_item_append_text(flags_item, ", change printer");
+
+ if (flags & SPOOLSS_PRINTER_CHANGE_JOB)
+ proto_item_append_text(flags_item, ", change job");
+
+ if (flags & SPOOLSS_PRINTER_CHANGE_FORM)
+ proto_item_append_text(flags_item, ", change form");
+
+ if (flags & SPOOLSS_PRINTER_CHANGE_PORT)
+ proto_item_append_text(flags_item, ", change port");
+
+ if (flags & SPOOLSS_PRINTER_CHANGE_PRINTER_DRIVER)
+ proto_item_append_text(flags_item, ", change printer driver");
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_rffpcnex_options, NULL);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
+ "Server", hf_servername, 0);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printerlocal, NULL);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_NOTIFY_OPTIONS_ARRAY_CTR, NDR_POINTER_UNIQUE,
+ "Notify Options Container", -1);
+
+ return offset;
+}
+
+static int SpoolssRFFPCNEX_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * SpoolssReplyOpenPrinter
+ */
+
+static int SpoolssReplyOpenPrinter_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 printerlocal;
+ char *name = NULL;
+
+ /* Parse packet */
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_servername, TRUE, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", name);
+
+ if (!dcv->private_data && name)
+ dcv->private_data = name;
+ else
+ g_free(name);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printerlocal,
+ &printerlocal);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_printerdata_type, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_replyopenprinter_unk0,
+ NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_replyopenprinter_unk1,
+ NULL);
+
+ return offset;
+}
+
+static int SpoolssReplyOpenPrinter_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, &status);
+
+ if (status == 0) {
+
+ /* Associate the returned printer handle with a name */
+
+ if (dcv->private_data) {
+ char *pol_name;
+
+ pol_name = g_strdup_printf(
+ "OpenPrinter(%s)",
+ (char *)dcv->private_data);
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ g_free(pol_name);
+ g_free(dcv->private_data);
+ dcv->private_data = NULL;
+ }
+
+ /*
+ * If we have a name for the handle, attach it to the item.
+ *
+ * XXX - we can't just do that above, as this may be called
+ * twice (see "dissect_pipe_dcerpc()", which calls the
+ * DCE RPC dissector twice), and in the first call we're
+ * not building a protocol tree (so we don't have an item
+ * to which to attach it) and in the second call
+ * "dcv->private_data" is NULL so we don't construct a
+ * name.
+ */
+
+ if (hnd_item != NULL) {
+ char *name;
+
+ if (dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL,
+ pinfo->fd->num) && name != NULL)
+ proto_item_append_text(hnd_item, ": %s", name);
+ }
+ }
+
+ return offset;
+}
+
+/*
+ * SpoolssGetPrinter
+ */
+
+
+
+static int SpoolssGetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 level;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ dcv->private_data = (void *)level;
+
+ offset = dissect_spoolss_buffer(
+ tvb, offset, pinfo, tree, drep, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static gint ett_PRINTER_INFO = -1;
+
+static int SpoolssGetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ BUFFER buffer;
+ gint16 level = (guint32)dcv->private_data;
+ proto_item *item;
+ proto_tree *subtree = NULL;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ /* Parse packet */
+
+ offset = dissect_spoolss_buffer(
+ tvb, offset, pinfo, tree, drep, &buffer);
+
+ if (buffer.tvb) {
+ switch(level) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 7:
+ item = proto_tree_add_text(
+ buffer.tree, buffer.tvb, 0, -1,
+ "Print info level %d", level);
+
+ subtree = proto_item_add_subtree(
+ item, ett_PRINTER_INFO);
+ break;
+ }
+
+ switch(level) {
+ case 0:
+ dissect_PRINTER_INFO_0(
+ buffer.tvb, 0, pinfo, subtree, drep);
+ break;
+ case 1:
+ dissect_PRINTER_INFO_1(
+ buffer.tvb, 0, pinfo, subtree, drep);
+ break;
+ case 2:
+ dissect_PRINTER_INFO_2(
+ buffer.tvb, 0, pinfo, subtree, drep);
+ break;
+ case 3:
+ dissect_PRINTER_INFO_3(
+ buffer.tvb, 0, pinfo, subtree, drep);
+ break;
+ case 7:
+ dissect_PRINTER_INFO_7(
+ buffer.tvb, 0, pinfo, subtree, drep);
+ break;
+ default:
+ proto_tree_add_text(
+ buffer.tree, buffer.tvb, 0, -1,
+ "[Unknown printer info level %d]", level);
+ break;
+ }
+ }
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * SEC_DESC_BUF
+ */
+
+static gint ett_SEC_DESC_BUF = -1;
+
+static int hf_secdescbuf_maxlen = -1;
+static int hf_secdescbuf_undoc = -1;
+static int hf_secdescbuf_len = -1;
+
+static int
+dissect_SEC_DESC_BUF(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 len;
+
+ /* XXX: I think this is really a array of bytes which can be
+ dissected using dissect_ndr_cvstring(). The dissected data
+ can be passed to dissect_nt_sec_desc(). The problem is that
+ dissect_nt_cvstring() passes back a char * where it really
+ should pass back a tvb. */
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Security descriptor buffer");
+
+ subtree = proto_item_add_subtree(item, ett_SEC_DESC_BUF);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_secdescbuf_maxlen, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_secdescbuf_undoc, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_secdescbuf_len, &len);
+
+ dissect_nt_sec_desc(
+ tvb, offset, pinfo, subtree, drep, len,
+ &spoolss_printer_access_mask_info);
+
+ offset += len;
+
+ return offset;
+}
+
+/*
+ * SPOOL_PRINTER_INFO_LEVEL
+ */
+
+static gint ett_SPOOL_PRINTER_INFO_LEVEL = -1;
+
+/* spool printer info */
+
+static int hf_spool_printer_info_devmode_ptr = -1;
+static int hf_spool_printer_info_secdesc_ptr = -1;
+
+static int
+dissect_SPOOL_PRINTER_INFO(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 level;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Spool printer info level");
+
+ subtree = proto_item_add_subtree(item, ett_SPOOL_PRINTER_INFO_LEVEL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_level, &level);
+
+ switch(level) {
+ case 3: {
+ guint32 devmode_ptr, secdesc_ptr;
+
+ /* I can't seem to get this working with the correct
+ dissect_ndr_pointer() function so let's cheat and
+ dissect the pointers by hand. )-: */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_spool_printer_info_devmode_ptr,
+ &devmode_ptr);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_spool_printer_info_secdesc_ptr,
+ &secdesc_ptr);
+
+ if (devmode_ptr)
+ offset = dissect_DEVMODE_CTR(
+ tvb, offset, pinfo, subtree, drep);
+
+ if (secdesc_ptr)
+ offset = dissect_SEC_DESC_BUF(
+ tvb, offset, pinfo, subtree, drep);
+
+ break;
+ }
+ case 2:
+ default:
+ proto_tree_add_text(
+ subtree, tvb, offset, 0,
+ "[Unknown spool printer info level %d]", level);
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * SpoolssSetPrinter
+ */
+
+static int hf_setprinter_cmd = -1;
+
+static const value_string setprinter_cmd_vals[] = {
+ { SPOOLSS_PRINTER_CONTROL_UNPAUSE, "Unpause" },
+ { SPOOLSS_PRINTER_CONTROL_PAUSE, "Pause" },
+ { SPOOLSS_PRINTER_CONTROL_RESUME, "Resume" },
+ { SPOOLSS_PRINTER_CONTROL_PURGE, "Purge" },
+ { SPOOLSS_PRINTER_CONTROL_SET_STATUS, "Set status" },
+ { 0, NULL }
+};
+
+static int SpoolssSetPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ guint32 level;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_SPOOL_PRINTER_INFO(
+ tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_setprinter_cmd, NULL);
+
+ return offset;
+}
+
+static int SpoolssSetPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * FORM_REL
+ */
+
+static const value_string form_type_vals[] =
+{
+ { SPOOLSS_FORM_USER, "User" },
+ { SPOOLSS_FORM_BUILTIN, "Builtin" },
+ { SPOOLSS_FORM_PRINTER, "Printer" },
+ { 0, NULL }
+};
+
+static gint ett_FORM_REL = -1;
+
+static int dissect_FORM_REL(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, int struct_start)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 flags;
+ int item_start = offset;
+ char *name = NULL;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Form");
+
+ subtree = proto_item_add_subtree(item, ett_FORM_REL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_form_flags, &flags);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_form_name,
+ struct_start, &name);
+
+ if (name) {
+ proto_item_append_text(item, ": %s", name);
+ g_free(name);
+ }
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_width, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_height, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_left_margin, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_top_margin, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_horiz_len, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_vert_len, NULL);
+
+ proto_item_set_len(item, offset - item_start);
+
+ return offset;
+}
+
+/*
+ * SpoolssEnumForms
+ */
+
+static int SpoolssEnumForms_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 level;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, &level);
+
+ dcv->private_data = (void *)level;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_spoolss_buffer(
+ tvb, offset, pinfo, tree, drep, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static int SpoolssEnumForms_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ BUFFER buffer;
+ guint32 level = (guint32)dcv->private_data, i, count;
+ int buffer_offset;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_spoolss_buffer(
+ tvb, offset, pinfo, tree, drep, &buffer);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_enumforms_num, &count);
+
+ /* Unfortunately this array isn't in NDR format so we can't
+ use prs_array(). The other weird thing is the
+ struct_start being inside the loop rather than outside.
+ Very strange. */
+
+ buffer_offset = 0;
+
+ for (i = 0; i < count; i++) {
+ int struct_start = buffer_offset;
+
+ buffer_offset = dissect_FORM_REL(
+ buffer.tvb, buffer_offset, pinfo, buffer.tree, drep,
+ struct_start);
+ }
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * SpoolssDeletePrinter
+ */
+
+static int SpoolssDeletePrinter_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ return offset;
+}
+
+static int SpoolssDeletePrinter_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+static int SpoolssAddPrinterEx_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, &hnd_item,
+ TRUE, FALSE);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, &status);
+
+ if (status == 0) {
+
+ /* Associate the returned printer handle with a name */
+
+ if (dcv->private_data) {
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", %s",
+ (char *)dcv->private_data);
+
+ dcerpc_smb_store_pol_name(
+ &policy_hnd, pinfo, dcv->private_data);
+
+ g_free(dcv->private_data);
+ dcv->private_data = NULL;
+ }
+
+ /*
+ * If we have a name for the handle, attach it to the item.
+ *
+ * XXX - we can't just do that above, as this may be called
+ * twice (see "dissect_pipe_dcerpc()", which calls the
+ * DCE RPC dissector twice), and in the first call we're
+ * not building a protocol tree (so we don't have an item
+ * to which to attach it) and in the second call
+ * "dcv->private_data" is NULL so we don't construct a
+ * name.
+ */
+
+ if (hnd_item != NULL) {
+ char *name;
+
+ if (dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL,
+ pinfo->fd->num) && name != NULL)
+ proto_item_append_text(hnd_item, ": %s", name);
+ }
+ }
+
+ return offset;
+}
+
+/*
+ * SpoolssEnumPrinterData
+ */
+
+static int hf_enumprinterdata_enumindex = -1;
+static int hf_enumprinterdata_value_offered = -1;
+static int hf_enumprinterdata_data_offered = -1;
+static int hf_enumprinterdata_value_len = -1;
+static int hf_enumprinterdata_value_needed = -1;
+static int hf_enumprinterdata_data_needed = -1;
+
+static int SpoolssEnumPrinterData_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ guint32 ndx;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_enumprinterdata_enumindex, &ndx);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", index %d", ndx);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_enumprinterdata_value_offered, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_enumprinterdata_data_offered, NULL);
+
+ return offset;
+}
+
+static int SpoolssEnumPrinterData_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ guint32 value_len, type;
+ char *value;
+ proto_item *value_item;
+ proto_tree *value_subtree;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ value_item = proto_tree_add_text(tree, tvb, offset, 0, "Value");
+
+ value_subtree = proto_item_add_subtree(
+ value_item, ett_printerdata_value);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, value_subtree, drep,
+ hf_enumprinterdata_value_len, &value_len);
+
+ if (value_len) {
+ dissect_spoolss_uint16uni(
+ tvb, offset, pinfo, value_subtree, drep, &value,
+ "Value name");
+
+ offset += value_len * 2;
+
+ if (check_col(pinfo->cinfo, COL_INFO) && value && value[0])
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value);
+
+ proto_item_append_text(value_item, ": %s", value);
+
+ proto_tree_add_string_hidden(
+ tree, hf_printerdata_value, tvb, offset, 0, value);
+
+ g_free(value);
+ }
+
+ proto_item_set_len(value_item, value_len * 2 + 4);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, value_subtree, drep,
+ hf_enumprinterdata_value_needed, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_printerdata_type, &type);
+
+ offset = dissect_printerdata_data(
+ tvb, offset, pinfo, tree, drep, type);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_enumprinterdata_data_needed, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * SpoolssEnumPrinters
+ */
+
+static gint ett_enumprinters_flags = -1;
+
+static int hf_enumprinters_flags = -1;
+static int hf_enumprinters_flags_local = -1;
+static int hf_enumprinters_flags_name = -1;
+static int hf_enumprinters_flags_shared = -1;
+static int hf_enumprinters_flags_default = -1;
+static int hf_enumprinters_flags_connections = -1;
+static int hf_enumprinters_flags_network = -1;
+static int hf_enumprinters_flags_remote = -1;
+
+static int SpoolssEnumPrinters_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ guint32 level, flags;
+ proto_tree *flags_subtree;
+ proto_item *flags_item;
+
+ /* Parse packet */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep,
+ hf_enumprinters_flags, &flags);
+
+ flags_item = proto_tree_add_text(tree, tvb, offset - 4, 4,
+ "Flags: 0x%08x", flags);
+
+ flags_subtree = proto_item_add_subtree(
+ flags_item, ett_enumprinters_flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_enumprinters_flags_network, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_enumprinters_flags_shared, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_enumprinters_flags_remote, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_enumprinters_flags_name, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_enumprinters_flags_connections, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_enumprinters_flags_local, tvb,
+ offset - 4, 4, flags);
+
+ proto_tree_add_boolean(
+ flags_subtree, hf_enumprinters_flags_default, tvb,
+ offset - 4, 4, flags);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server name", hf_servername, 0);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_spoolss_buffer(
+ tvb, offset, pinfo, tree, drep, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static int SpoolssEnumPrinters_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ guint32 num_drivers;
+
+ /* Parse packet */
+
+ offset = dissect_spoolss_buffer(
+ tvb, offset, pinfo, tree, drep, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_returned,
+ &num_drivers);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * AddPrinterDriver
+ */
+#if 0
+static int SpoolssAddPrinterDriver_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+
+ /* Parse packet */
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
+ "Server", hf_servername, 0);
+
+ offset = dissect_spoolss_DRIVER_INFO_CTR(
+ tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+#endif
+static int SpoolssAddPrinterDriver_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * FORM_1
+ */
+
+static gint ett_FORM_1 = -1;
+
+static int dissect_FORM_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 flags;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Form level 1");
+
+ subtree = proto_item_add_subtree(item, ett_FORM_1);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, subtree, drep, NDR_POINTER_UNIQUE,
+ "Name", hf_form_name, 0);
+
+ /* Eek - we need to know whether this pointer was NULL or not.
+ Currently there is not any way to do this. */
+
+ if (tvb_length_remaining(tvb, offset) == 0)
+ goto done;
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_form_flags, &flags);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_unknown, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_width, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_height, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_left_margin, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_top_margin, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_horiz_len, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_form_vert_len, NULL);
+
+ done:
+ return offset;
+}
+
+/*
+ * FORM_CTR
+ */
+
+static gint ett_FORM_CTR = -1;
+
+static int dissect_FORM_CTR(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 level;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Form container");
+
+ subtree = proto_item_add_subtree(item, ett_FORM_CTR);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_form_level, &level);
+
+ switch(level) {
+ case 1:
+ offset = dissect_FORM_1(tvb, offset, pinfo, subtree, drep);
+ break;
+
+ default:
+ proto_tree_add_text(
+ subtree, tvb, offset, 0,
+ "[Unknown form info level %d]", level);
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * AddForm
+ */
+
+static int SpoolssAddForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 level;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_form_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ /* Store info level to match with reply packet */
+
+ dcv->private_data = (void *)level;
+
+ offset = dissect_FORM_CTR(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int SpoolssAddForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * DeleteForm
+ */
+
+static int SpoolssDeleteForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ char *name = NULL;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep,
+ sizeof(guint16), hf_form_name, TRUE, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", name);
+
+ g_free(name);
+
+ return offset;
+}
+
+static int SpoolssDeleteForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * SetForm
+ */
+
+static int SpoolssSetForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ char *name = NULL;
+ guint32 level;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep,
+ sizeof(guint16), hf_form_name, TRUE, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", name);
+
+ g_free(name);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_form_level, &level);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_FORM_CTR(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int SpoolssSetForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * GetForm
+ */
+
+static int SpoolssGetForm_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 level;
+ char *name;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep,
+ sizeof(guint16), hf_form_name, TRUE, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", name);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_form_level, &level);
+
+ dcv->private_data = (void *)level;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d",
+ level);
+
+ offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static int SpoolssGetForm_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ BUFFER buffer;
+ guint32 level = (guint32)dcv->private_data;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_form, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_spoolss_buffer(
+ tvb, offset, pinfo, tree, drep, &buffer);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ if (buffer.tvb) {
+ int buffer_offset = 0;
+
+ switch(level) {
+ case 1: {
+ int struct_start = buffer_offset;
+
+ buffer_offset = dissect_FORM_REL(
+ buffer.tvb, buffer_offset, pinfo, tree, drep,
+ struct_start);
+ break;
+ }
+
+ default:
+ proto_tree_add_text(
+ buffer.tree, buffer.tvb, buffer_offset, -1,
+ "[Unknown form info level %d]", level);
+ break;
+ }
+ }
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/* A generic reply function that just parses the status code. Useful for
+ unimplemented dissectors so the status code can be inserted into the
+ INFO column. */
+
+static int SpoolssGeneric_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ int len = tvb_length(tvb);
+
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "[Unimplemented dissector: SPOOLSS]");
+
+ offset = dissect_doserror(
+ tvb, len - 4, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * JOB_INFO_1
+ */
+
+static gint ett_JOB_INFO_1;
+
+static int
+dissect_spoolss_JOB_INFO_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ int struct_start = offset;
+ char *document_name;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Job info level 1");
+
+ subtree = proto_item_add_subtree(item, ett_JOB_INFO_1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_job_id, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_printername,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_servername,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_username,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_documentname,
+ struct_start, &document_name);
+
+ proto_item_append_text(item, ": %s", document_name);
+ g_free(document_name);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_datatype,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_textstatus,
+ struct_start, NULL);
+
+ offset = dissect_job_status(tvb, offset, pinfo, subtree, drep);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_job_priority, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_job_position, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_job_totalpages, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_job_pagesprinted, NULL);
+
+ offset = dissect_SYSTEM_TIME(
+ tvb, offset, pinfo, subtree, drep, "Job Submission Time",
+ TRUE, NULL);
+
+ proto_item_set_len(item, offset - struct_start);
+
+ return offset;
+}
+
+/*
+ * JOB_INFO_2
+ */
+
+static gint ett_JOB_INFO_2;
+
+static int
+dissect_spoolss_JOB_INFO_2(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ int struct_start = offset;
+ char *document_name;
+ guint32 devmode_offset, secdesc_offset;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Job info level 2");
+
+ subtree = proto_item_add_subtree(item, ett_JOB_INFO_2);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_job_id, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_printername,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_machinename,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_username,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_documentname,
+ struct_start, &document_name);
+
+ proto_item_append_text(item, ": %s", document_name);
+ g_free(document_name);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_notifyname,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_datatype,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_printprocessor,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_parameters,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_drivername,
+ struct_start, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_offset,
+ &devmode_offset);
+
+ dissect_DEVMODE(
+ tvb, devmode_offset - 4 + struct_start, pinfo, subtree, drep);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_textstatus,
+ struct_start, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_offset,
+ &secdesc_offset);
+
+ dissect_nt_sec_desc(
+ tvb, secdesc_offset, pinfo, subtree, drep,
+ tvb_length_remaining(tvb, secdesc_offset),
+ &spoolss_job_access_mask_info);
+
+ offset = dissect_job_status(tvb, offset, pinfo, subtree, drep);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_job_priority, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_job_position, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_start_time, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_end_time, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_job_totalpages, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_job_size, NULL);
+
+ offset = dissect_SYSTEM_TIME(
+ tvb, offset, pinfo, subtree, drep, "Job Submission Time",
+ TRUE, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep, hf_elapsed_time, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_job_pagesprinted, NULL);
+
+ proto_item_set_len(item, offset - struct_start);
+
+ return offset;
+}
+
+/*
+ * EnumJobs
+ */
+
+static int hf_enumjobs_firstjob = -1;
+static int hf_enumjobs_numjobs = -1;
+
+static int SpoolssEnumJobs_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 level;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep,
+ hf_hnd, NULL, NULL, FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_enumjobs_firstjob, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_enumjobs_numjobs, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, &level);
+
+ dcv->private_data = (void *)level;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static int SpoolssEnumJobs_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ gint16 level = (guint32)dcv->private_data;
+ BUFFER buffer;
+ guint32 num_jobs, i;
+ int buffer_offset;
+
+ /* Parse packet */
+
+ offset = dissect_spoolss_buffer(
+ tvb, offset, pinfo, tree, drep, &buffer);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_enumjobs_numjobs,
+ &num_jobs);
+
+ buffer_offset = 0;
+
+ for (i = 0; i < num_jobs; i++) {
+ switch(level) {
+ case 1:
+ buffer_offset = dissect_spoolss_JOB_INFO_1(
+ buffer.tvb, buffer_offset, pinfo,
+ buffer.tree, drep);
+ break;
+ case 2:
+ buffer_offset = dissect_spoolss_JOB_INFO_2(
+ buffer.tvb, buffer_offset, pinfo,
+ buffer.tree, drep);
+ break;
+ default:
+ proto_tree_add_text(
+ buffer.tree, buffer.tvb, 0, -1,
+ "[Unknown job info level %d]", level);
+ break;
+ }
+
+ }
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * SetJob
+ */
+
+static const value_string setjob_commands[] = {
+ { JOB_CONTROL_PAUSE, "Pause" },
+ { JOB_CONTROL_RESUME, "Resume" },
+ { JOB_CONTROL_CANCEL, "Cancel" },
+ { JOB_CONTROL_RESTART, "Restart" },
+ { JOB_CONTROL_DELETE, "Delete" },
+ { 0, NULL }
+};
+
+static int hf_setjob_cmd = -1;
+
+static int SpoolssSetJob_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ guint32 jobid, cmd;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_job_id, &jobid);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_setjob_cmd, &cmd);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", %s jobid %d",
+ val_to_str(cmd, setjob_commands, "Unknown (%d)"),
+ jobid);
+
+ return offset;
+}
+
+static int SpoolssSetJob_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * GetJob
+ */
+
+static int SpoolssGetJob_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 level, jobid;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_job_id, &jobid);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, &level);
+
+ dcv->private_data = (void *)level;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d, jobid %d",
+ level, jobid);
+
+ offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static int SpoolssGetJob_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ gint32 level = (guint32)dcv->private_data;
+ BUFFER buffer;
+
+ /* Parse packet */
+
+ offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep,
+ &buffer);
+
+ if (buffer.tvb) {
+ int buffer_offset = 0;
+
+ switch(level) {
+ case 1:
+ buffer_offset = dissect_spoolss_JOB_INFO_1(
+ buffer.tvb, buffer_offset, pinfo,
+ buffer.tree, drep);
+ break;
+ case 2:
+ default:
+ proto_tree_add_text(
+ buffer.tree, buffer.tvb, buffer_offset, -1,
+ "[Unknown job info level %d]", level);
+ break;
+ }
+ }
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * StartPagePrinter
+ */
+
+static int SpoolssStartPagePrinter_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ char *pol_name;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
+ FALSE, FALSE);
+
+ dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
+ pinfo->fd->num);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ pol_name);
+
+ return offset;
+}
+
+static int SpoolssStartPagePrinter_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * EndPagePrinter
+ */
+
+static int SpoolssEndPagePrinter_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ char *pol_name;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
+ FALSE, FALSE);
+
+ dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
+ pinfo->fd->num);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ pol_name);
+
+ return offset;
+}
+
+static int SpoolssEndPagePrinter_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * DOC_INFO_1
+ */
+
+static gint ett_DOC_INFO_1 = -1;
+
+static int
+dissect_spoolss_doc_info_1(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Document info level 1");
+
+ subtree = proto_item_add_subtree(item, ett_DOC_INFO_1);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, subtree, drep, NDR_POINTER_UNIQUE,
+ "Document name", hf_documentname, 0);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, subtree, drep, NDR_POINTER_UNIQUE,
+ "Output file", hf_outputfile, 0);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, subtree, drep, NDR_POINTER_UNIQUE,
+ "Data type", hf_datatype, 0);
+
+ return offset;
+}
+
+static int
+dissect_spoolss_doc_info_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = pinfo->private_data;
+ guint32 info_level = 1; /* XXX */
+
+ if (di->conformant_run)
+ return offset;
+
+ switch(info_level) {
+ case 1:
+ offset = dissect_spoolss_doc_info_1(
+ tvb, offset, pinfo, tree, drep);
+ break;
+ default:
+ proto_tree_add_text(
+ tree, tvb, offset, 0,
+ "[Unknown documentinfo level %d]", info_level);
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * DOC_INFO
+ */
+
+static gint ett_DOC_INFO = -1;
+
+static int
+dissect_spoolss_doc_info(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 level;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Document info");
+
+ subtree = proto_item_add_subtree(item, ett_DOC_INFO);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_level, &level);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, subtree, drep,
+ dissect_spoolss_doc_info_data,
+ NDR_POINTER_UNIQUE, "Document info", -1);
+
+ return offset;
+}
+
+/*
+ * DOC_INFO_CTR
+ */
+
+static gint ett_DOC_INFO_CTR = -1;
+
+static int
+dissect_spoolss_doc_info_ctr(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Document info container");
+
+ subtree = proto_item_add_subtree(item, ett_DOC_INFO_CTR);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_level, NULL);
+
+ offset = dissect_spoolss_doc_info(
+ tvb, offset, pinfo, subtree, drep);
+
+ return offset;
+}
+
+/*
+ * StartDocPrinter
+ */
+
+static int SpoolssStartDocPrinter_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ char *pol_name;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
+ FALSE, FALSE);
+
+ dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
+ pinfo->fd->num);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ pol_name);
+
+ offset = dissect_spoolss_doc_info_ctr(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+static int SpoolssStartDocPrinter_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_job_id, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * EndDocPrinter
+ */
+
+static int SpoolssEndDocPrinter_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ char *pol_name;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
+ FALSE, FALSE);
+
+ dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
+ pinfo->fd->num);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ pol_name);
+
+
+ return offset;
+}
+
+static int SpoolssEndDocPrinter_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * WritePrinter
+ */
+
+static gint ett_writeprinter_buffer = -1;
+
+static int hf_writeprinter_numwritten = -1;
+
+static int SpoolssWritePrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ char *pol_name;
+ guint32 size;
+ proto_item *item;
+ proto_tree *subtree;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
+ FALSE, FALSE);
+
+ dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
+ pinfo->fd->num);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ pol_name);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_buffer_size, &size);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %d bytes", size);
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Buffer");
+
+ subtree = proto_item_add_subtree(item, ett_writeprinter_buffer);
+
+ offset = dissect_ndr_uint8s(tvb, offset, pinfo, subtree, drep,
+ hf_buffer_data, size, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_buffer_size, NULL);
+
+ proto_item_set_len(item, size + 4);
+
+ return offset;
+}
+
+static int SpoolssWritePrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ guint32 size;
+
+ /* Parse packet */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_writeprinter_numwritten,
+ &size);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", %d bytes written", size);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * DeletePrinterData
+ */
+
+static int SpoolssDeletePrinterData_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ char *value_name;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_printerdata_value, TRUE, &value_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", value_name);
+
+ g_free(value_name);
+
+ return offset;
+}
+
+static int SpoolssDeletePrinterData_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * DRIVER_INFO_1
+ */
+
+static gint ett_DRIVER_INFO_1 = -1;
+
+static int dissect_DRIVER_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ int struct_start = offset;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Driver info level 1");
+
+ subtree = proto_item_add_subtree(item, ett_DRIVER_INFO_1);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_drivername,
+ struct_start, NULL);
+
+ return offset;
+}
+
+/*
+ * DRIVER_INFO_3
+ */
+
+static const value_string driverinfo_cversion_vals[] =
+{
+ { 0, "Windows 95/98/Me" },
+ { 2, "Windows NT 4.0" },
+ { 3, "Windows 2000/XP" },
+ { 0, NULL }
+};
+
+static gint ett_DRIVER_INFO_3 = -1;
+
+static int dissect_DRIVER_INFO_3(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ int struct_start = offset;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Driver info level 3");
+
+ subtree = proto_item_add_subtree(item, ett_DRIVER_INFO_3);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, subtree, drep,
+ hf_driverinfo_cversion, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_drivername,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_architecture,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_driverpath,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_datafile,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_configfile,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_helpfile,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstrarray(
+ tvb, offset, pinfo, subtree, drep, hf_dependentfiles,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_monitorname,
+ struct_start, NULL);
+
+ offset = dissect_spoolss_relstr(
+ tvb, offset, pinfo, subtree, drep, hf_defaultdatatype,
+ struct_start, NULL);
+
+ return offset;
+}
+
+/*
+ * EnumPrinterDrivers
+ */
+
+static int SpoolssEnumPrinterDrivers_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 level;
+
+ /* Parse packet */
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
+ "Name", hf_servername, 0);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
+ "Environment", hf_servername, 0);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, &level);
+
+ dcv->private_data = (void *)level;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static int SpoolssEnumPrinterDrivers_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 level = (guint32)dcv->private_data, num_drivers, i;
+ int buffer_offset;
+ BUFFER buffer;
+
+ /* Parse packet */
+
+ offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep,
+ &buffer);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_returned,
+ &num_drivers);
+
+ buffer_offset = 0;
+
+ for (i = 0; i < num_drivers; i++) {
+ switch(level) {
+ case 1:
+ buffer_offset = dissect_DRIVER_INFO_1(
+ buffer.tvb, buffer_offset, pinfo,
+ buffer.tree, drep);
+ break;
+ case 3:
+ buffer_offset = dissect_DRIVER_INFO_3(
+ buffer.tvb, buffer_offset, pinfo,
+ buffer.tree, drep);
+ break;
+ default:
+ proto_tree_add_text(
+ buffer.tree, buffer.tvb, buffer_offset, -1,
+ "[Unknown driver info level %d]", level);
+ goto done;
+ }
+ }
+
+done:
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * GetPrinterDriver2
+ */
+
+static int SpoolssGetPrinterDriver2_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ char *pol_name;
+ guint32 level;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, &policy_hnd, NULL,
+ FALSE, FALSE);
+
+ dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
+ pinfo->fd->num);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ pol_name);
+
+ offset = dissect_ndr_str_pointer_item(
+ tvb, offset, pinfo, tree, drep, NDR_POINTER_UNIQUE,
+ "Architecture", hf_architecture, 0);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_level, &level);
+
+ dcv->private_data = (void *)level;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", level %d", level);
+
+ offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_clientmajorversion, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_clientminorversion, NULL);
+
+ return offset;
+}
+
+static int SpoolssGetPrinterDriver2_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ guint32 level = (guint32)dcv->private_data;
+ BUFFER buffer;
+
+ /* Parse packet */
+
+ offset = dissect_spoolss_buffer(tvb, offset, pinfo, tree, drep,
+ &buffer);
+
+ if (buffer.tvb) {
+ switch(level) {
+ case 1:
+ dissect_DRIVER_INFO_1(
+ buffer.tvb, 0, pinfo, buffer.tree, drep);
+ break;
+ case 3:
+ dissect_DRIVER_INFO_3(
+ buffer.tvb, 0, pinfo, buffer.tree, drep);
+ break;
+ default:
+ proto_tree_add_text(
+ buffer.tree, buffer.tvb, 0, -1,
+ "[Unknown driver info level %d]", level);
+ break;
+ }
+ }
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_servermajorversion, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_serverminorversion, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+static int
+dissect_notify_info_data_buffer(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ guint32 len;
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_buffer_len, &len);
+
+ offset = dissect_ndr_uint16s(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_buffer_data, len);
+
+ return offset;
+}
+
+static void cb_notify_str_postprocess(packet_info *pinfo _U_,
+ proto_tree *tree _U_,
+ proto_item *item, tvbuff_t *tvb,
+ int start_offset, int end_offset,
+ void *callback_args)
+{
+ gint levels, hf_index = GPOINTER_TO_INT(callback_args);
+ guint32 len;
+ char *s;
+
+ /* Align start_offset on 4-byte boundary. */
+
+ if (start_offset % 4)
+ start_offset += 4 - (start_offset % 4);
+
+ /* Get string length */
+
+ len = tvb_get_letohl(tvb, start_offset);
+
+ s = tvb_fake_unicode(
+ tvb, start_offset + 4, (end_offset - start_offset - 4) / 2, TRUE);
+
+ /* Append string to upper-level proto_items */
+
+ levels = 2;
+
+ if (levels > 0 && item && s && s[0]) {
+ proto_item_append_text(item, ": %s", s);
+ item = item->parent;
+ levels--;
+ if (levels > 0) {
+ proto_item_append_text(item, ": %s", s);
+ item = item->parent;
+ levels--;
+ while (levels > 0) {
+ proto_item_append_text(item, " %s", s);
+ item = item->parent;
+ levels--;
+ }
+ }
+ }
+
+ /* Add hidden field so filter brings up any notify data */
+
+ if (hf_index != -1)
+ proto_tree_add_string_hidden(
+ tree, hf_index, tvb, start_offset, len, s);
+
+ g_free(s);
+}
+
+/* Return the hf_index for a printer notify field. This is used to
+ add a hidden string to the display so that filtering will bring
+ up relevant notify data. */
+
+static int
+printer_notify_hf_index(int field)
+{
+ int result = -1;
+
+ switch(field) {
+ case PRINTER_NOTIFY_SERVER_NAME:
+ result = hf_servername;
+ break;
+ case PRINTER_NOTIFY_PRINTER_NAME:
+ result = hf_printername;
+ break;
+ case PRINTER_NOTIFY_SHARE_NAME:
+ result = hf_sharename;
+ break;
+ case PRINTER_NOTIFY_PORT_NAME:
+ result = hf_portname;
+ break;
+ case PRINTER_NOTIFY_DRIVER_NAME:
+ result = hf_drivername;
+ break;
+ case PRINTER_NOTIFY_COMMENT:
+ result = hf_printercomment;
+ break;
+ case PRINTER_NOTIFY_LOCATION:
+ result = hf_printerlocation;
+ break;
+ case PRINTER_NOTIFY_SEPFILE:
+ result = hf_sepfile;
+ break;
+ case PRINTER_NOTIFY_PRINT_PROCESSOR:
+ result = hf_printprocessor;
+ break;
+ case PRINTER_NOTIFY_PARAMETERS:
+ result = hf_parameters;
+ break;
+ case PRINTER_NOTIFY_DATATYPE:
+ result = hf_parameters;
+ break;
+ }
+
+ return result;
+}
+
+static int
+job_notify_hf_index(int field)
+{
+ int result = -1;
+
+ switch(field) {
+ case JOB_NOTIFY_PRINTER_NAME:
+ result = hf_printername;
+ break;
+ case JOB_NOTIFY_MACHINE_NAME:
+ result = hf_machinename;
+ break;
+ case JOB_NOTIFY_PORT_NAME:
+ result = hf_portname;
+ break;
+ case JOB_NOTIFY_USER_NAME:
+ result = hf_username;
+ break;
+ case JOB_NOTIFY_NOTIFY_NAME:
+ result = hf_notifyname;
+ break;
+ case JOB_NOTIFY_DATATYPE:
+ result = hf_datatype;
+ break;
+ case JOB_NOTIFY_PRINT_PROCESSOR:
+ result = hf_printprocessor;
+ break;
+ case JOB_NOTIFY_DRIVER_NAME:
+ result = hf_drivername;
+ break;
+ case JOB_NOTIFY_DOCUMENT:
+ result = hf_documentname;
+ break;
+ case JOB_NOTIFY_PRIORITY:
+ result = hf_job_priority;
+ break;
+ case JOB_NOTIFY_POSITION:
+ result = hf_job_position;
+ break;
+ case JOB_NOTIFY_TOTAL_PAGES:
+ result = hf_job_totalpages;
+ break;
+ case JOB_NOTIFY_PAGES_PRINTED:
+ result = hf_job_pagesprinted;
+ break;
+ case JOB_NOTIFY_TOTAL_BYTES:
+ result = hf_job_totalbytes;
+ break;
+ case JOB_NOTIFY_BYTES_PRINTED:
+ result = hf_job_bytesprinted;
+ break;
+ }
+
+ return result;
+}
+
+static int
+dissect_NOTIFY_INFO_DATA_printer(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_item *item,
+ guint8 *drep, guint16 field)
+{
+ guint32 value1;
+
+ switch (field) {
+
+ /* String notify data */
+
+ case PRINTER_NOTIFY_SERVER_NAME:
+ case PRINTER_NOTIFY_PRINTER_NAME:
+ case PRINTER_NOTIFY_SHARE_NAME:
+ case PRINTER_NOTIFY_DRIVER_NAME:
+ case PRINTER_NOTIFY_COMMENT:
+ case PRINTER_NOTIFY_LOCATION:
+ case PRINTER_NOTIFY_SEPFILE:
+ case PRINTER_NOTIFY_PRINT_PROCESSOR:
+ case PRINTER_NOTIFY_PARAMETERS:
+ case PRINTER_NOTIFY_DATATYPE:
+ case PRINTER_NOTIFY_PORT_NAME:
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_bufsize, &value1);
+
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_notify_info_data_buffer,
+ NDR_POINTER_UNIQUE, "String",
+ hf_notify_info_data_buffer,
+ cb_notify_str_postprocess,
+ GINT_TO_POINTER(printer_notify_hf_index(field)));
+
+ break;
+
+ case PRINTER_NOTIFY_ATTRIBUTES:
+
+ /* Value 1 is the printer attributes */
+
+ offset = dissect_printer_attributes(
+ tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep,
+ hf_notify_info_data_value2, NULL);
+
+ break;
+
+ case PRINTER_NOTIFY_STATUS: {
+ guint32 status;
+
+ /* Value 1 is the printer status */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_printer_status, &status);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep,
+ hf_notify_info_data_value2, NULL);
+
+ proto_item_append_text(
+ item, ": %s",
+ val_to_str(status, printer_status_vals, "Unknown"));
+
+ break;
+ }
+
+ /* Unknown notify data */
+
+ case PRINTER_NOTIFY_SECURITY_DESCRIPTOR: /* Secdesc */
+ case PRINTER_NOTIFY_DEVMODE: /* Devicemode */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_bufsize, &value1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_notify_info_data_buffer,
+ NDR_POINTER_UNIQUE, "Buffer",
+ hf_notify_info_data_buffer);
+
+ break;
+
+ default:
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_value1, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_value2, NULL);
+
+ break;
+ }
+ return offset;
+}
+
+static void notify_job_time_cb(packet_info *pinfo, proto_tree *tree _U_,
+ proto_item *item, tvbuff_t *tvb _U_,
+ int start_offset _U_, int end_offset _U_,
+ void *callback_args _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ char *str = (char *)dcv->private_data;
+
+ /* Append job string stored in dcv->private_data by
+ dissect_SYSTEM_TIME_ptr() in the current item as well
+ as the parent. */
+
+ proto_item_append_text(item, ": %s", str);
+
+ if (item)
+ proto_item_append_text(item->parent, ": %s", str);
+}
+
+static int
+dissect_NOTIFY_INFO_DATA_job(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_item *item, guint8 *drep,
+ guint16 field)
+{
+ guint32 value1;
+
+ switch (field) {
+
+ /* String notify data */
+
+ case JOB_NOTIFY_PRINTER_NAME:
+ case JOB_NOTIFY_MACHINE_NAME:
+ case JOB_NOTIFY_PORT_NAME:
+ case JOB_NOTIFY_USER_NAME:
+ case JOB_NOTIFY_NOTIFY_NAME:
+ case JOB_NOTIFY_DATATYPE:
+ case JOB_NOTIFY_PRINT_PROCESSOR:
+ case JOB_NOTIFY_PARAMETERS:
+ case JOB_NOTIFY_DRIVER_NAME:
+ case JOB_NOTIFY_STATUS_STRING:
+ case JOB_NOTIFY_DOCUMENT:
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_bufsize, &value1);
+
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_notify_info_data_buffer,
+ NDR_POINTER_UNIQUE, "String",
+ hf_notify_info_data_buffer,
+ cb_notify_str_postprocess,
+ GINT_TO_POINTER(job_notify_hf_index(field)));
+
+ break;
+
+ case JOB_NOTIFY_STATUS:
+ offset = dissect_job_status(
+ tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep,
+ hf_notify_info_data_value2, NULL);
+
+ break;
+
+ case JOB_NOTIFY_SUBMITTED:
+
+ /* SYSTEM_TIME */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_buffer_len, NULL);
+
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_SYSTEM_TIME_ptr, NDR_POINTER_UNIQUE,
+ "Time submitted", -1, notify_job_time_cb, NULL);
+
+ break;
+
+ case JOB_NOTIFY_PRIORITY:
+ case JOB_NOTIFY_POSITION:
+ case JOB_NOTIFY_TOTAL_PAGES:
+ case JOB_NOTIFY_PAGES_PRINTED:
+ case JOB_NOTIFY_TOTAL_BYTES:
+ case JOB_NOTIFY_BYTES_PRINTED: {
+ guint32 value;
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_value1, &value);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_value2, NULL);
+
+ proto_item_append_text(item, ": %d", value);
+
+ proto_tree_add_uint_hidden(
+ tree, job_notify_hf_index(field), tvb,
+ offset, 4, value);
+
+ break;
+ }
+
+ /* Unknown notify data */
+
+ case JOB_NOTIFY_DEVMODE:
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_bufsize, &value1);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_notify_info_data_buffer,
+ NDR_POINTER_UNIQUE, "Buffer",
+ hf_notify_info_data_buffer);
+
+ break;
+
+ default:
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_value1, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_notify_info_data_value2, NULL);
+ }
+ return offset;
+}
+
+static gint ett_NOTIFY_INFO_DATA;
+
+static int
+dissect_NOTIFY_INFO_DATA(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ guint32 count;
+ guint16 type, field;
+ char *field_string;
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "%s", "");
+
+ subtree = proto_item_add_subtree(item, ett_NOTIFY_INFO_DATA);
+
+ offset = dissect_ndr_uint16(
+ tvb, offset, pinfo, subtree, drep,
+ hf_notify_info_data_type, &type);
+
+ offset = dissect_notify_field(
+ tvb, offset, pinfo, subtree, drep, type, &field);
+
+ switch(type) {
+ case PRINTER_NOTIFY_TYPE:
+ field_string = val_to_str(
+ field, printer_notify_option_data_vals,
+ "Unknown (%d)");
+ break;
+ case JOB_NOTIFY_TYPE:
+ field_string = val_to_str(
+ field, job_notify_option_data_vals,
+ "Unknown (%d)");
+ break;
+ default:
+ field_string = "Unknown field";
+ break;
+ }
+
+ proto_item_append_text(
+ item, "%s, %s",
+ val_to_str(type, printer_notify_types, "Unknown (%d)"),
+ field_string);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_notify_info_data_count, &count);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_notify_info_data_id, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_notify_info_data_count, NULL);
+
+ /* The value here depends on (type, field) */
+
+ switch (type) {
+ case PRINTER_NOTIFY_TYPE:
+ offset = dissect_NOTIFY_INFO_DATA_printer(
+ tvb, offset, pinfo, subtree, item, drep, field);
+ break;
+ case JOB_NOTIFY_TYPE:
+ offset = dissect_NOTIFY_INFO_DATA_job(
+ tvb, offset, pinfo, subtree, item, drep, field);
+ break;
+ default:
+ proto_tree_add_text(
+ tree, tvb, offset, 0,
+ "[Unknown notify type %d]", type);
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_NOTIFY_INFO(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = pinfo->private_data;
+ guint32 count;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_notify_info_version, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_notify_info_flags, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_notify_info_count, &count);
+
+ if (!di->conformant_run && check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", %d %s", count,
+ notify_plural(count));
+
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ dissect_NOTIFY_INFO_DATA);
+
+ return offset;
+}
+
+/*
+ * RFNPCNEX
+ */
+
+static int SpoolssRFNPCNEX_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ guint32 changeid;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_rrpcn_changelow, &changeid);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", changeid %d", changeid);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_NOTIFY_OPTIONS_ARRAY_CTR, NDR_POINTER_UNIQUE,
+ "Notify Options Array Container", -1);
+
+ return offset;
+}
+
+static int SpoolssRFNPCNEX_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_NOTIFY_INFO, NDR_POINTER_UNIQUE,
+ "Notify Info", -1);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * RRPCN
+ */
+
+static int SpoolssRRPCN_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ guint32 changeid;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_rrpcn_changelow, &changeid);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", changeid %d", changeid);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_rrpcn_changehigh, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_rrpcn_unk0, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_rrpcn_unk1, NULL);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_NOTIFY_INFO, NDR_POINTER_UNIQUE,
+ "Notify Info", -1);
+
+ /* Notify info */
+
+ return offset;
+}
+
+static int SpoolssRRPCN_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_rrpcn_unk0, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * ReplyClosePrinter
+ */
+
+static int SpoolssReplyClosePrinter_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, TRUE);
+
+ return offset;
+}
+
+static int SpoolssReplyClosePrinter_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * FCPN
+ */
+
+static int SpoolssFCPN_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ return offset;
+}
+
+static int SpoolssFCPN_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * RouterReplyPrinter
+ */
+
+static int hf_routerreplyprinter_condition = -1;
+static int hf_routerreplyprinter_unknown1 = -1;
+static int hf_routerreplyprinter_changeid = -1;
+
+static int SpoolssRouterReplyPrinter_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_routerreplyprinter_condition, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_routerreplyprinter_unknown1, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_routerreplyprinter_changeid, NULL);
+
+ return offset;
+}
+
+static int SpoolssRouterReplyPrinter_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+static int hf_keybuffer_size = -1;
+static int hf_keybuffer_data = -1;
+
+static int
+dissect_spoolss_keybuffer(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = pinfo->private_data;
+ guint32 size;
+ int end_offset;
+
+ if (di->conformant_run)
+ return offset;
+
+ /* Dissect size and data */
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_keybuffer_size, &size);
+
+ end_offset = offset + (size*2);
+ if (end_offset < offset) {
+ /*
+ * Overflow - make the end offset one past the end of
+ * the packet data, so we throw an exception (as the
+ * size is almost certainly too big).
+ */
+ end_offset = tvb_reported_length_remaining(tvb, offset) + 1;
+ }
+
+ while (offset < end_offset)
+ offset = dissect_spoolss_uint16uni(
+ tvb, offset, pinfo, tree, drep, NULL, "Key");
+
+ return offset;
+}
+
+
+static int SpoolssEnumPrinterKey_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ char *key_name;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_printerdata_key, TRUE, &key_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ char *kn = key_name;
+
+ if (!key_name[0])
+ kn = "\"\"";
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", kn);
+ }
+
+ g_free(key_name);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ return offset;
+}
+
+static int SpoolssEnumPrinterKey_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* Parse packet */
+
+ offset = dissect_spoolss_keybuffer(tvb, offset, pinfo, tree, drep);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+static int hf_enumprinterdataex_num_values = -1;
+static int hf_enumprinterdataex_name_offset = -1;
+static int hf_enumprinterdataex_name_len = -1;
+static int hf_enumprinterdataex_name = -1;
+static int hf_enumprinterdataex_val_type = -1;
+static int hf_enumprinterdataex_val_offset = -1;
+static int hf_enumprinterdataex_val_len = -1;
+static int hf_enumprinterdataex_val_dword_low = -1;
+static int hf_enumprinterdataex_val_dword_high = -1;
+static int hf_enumprinterdataex_val_sz = -1;
+
+static int SpoolssEnumPrinterDataEx_q(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ char *key_name;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_hnd, NULL, NULL,
+ FALSE, FALSE);
+
+ offset = dissect_ndr_cvstring(
+ tvb, offset, pinfo, tree, drep, sizeof(guint16),
+ hf_printerdata_key, TRUE, &key_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", key_name);
+
+ g_free(key_name);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_offered, NULL);
+
+ return offset;
+}
+
+static gint ett_printer_enumdataex_value = -1;
+
+static int
+dissect_spoolss_printer_enum_values(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 start_offset = offset;
+ guint32 name_offset, name_len, val_offset, val_len, val_type;
+ char *name;
+ proto_item *item;
+ proto_tree *subtree;
+
+ /* Get offset of value name */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep,
+ hf_enumprinterdataex_name_offset, &name_offset);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, NULL, drep,
+ hf_enumprinterdataex_name_len, &name_len);
+
+ dissect_spoolss_uint16uni(
+ tvb, start_offset + name_offset, pinfo, NULL, drep,
+ &name, "Name");
+
+ item = proto_tree_add_text(tree, tvb, offset, 0, "Name: ");
+
+ subtree = proto_item_add_subtree(item, ett_printer_enumdataex_value);
+
+ proto_item_append_text(item, name);
+
+ proto_tree_add_text(
+ subtree, tvb, offset - 8, 4, "Name offset: %d", name_offset);
+
+ proto_tree_add_text(
+ subtree, tvb, offset - 4, 4, "Name len: %d", name_len);
+
+ proto_tree_add_text(
+ subtree, tvb, start_offset + name_offset, (strlen(name) + 1) * 2,
+ "Name: %s", name);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep, hf_printerdata_type,
+ &val_type);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_enumprinterdataex_val_offset, &val_offset);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, subtree, drep,
+ hf_enumprinterdataex_val_len, &val_len);
+
+ if (val_len == 0) {
+ proto_tree_add_text(subtree, tvb, start_offset + val_offset, 4,
+ "Value: (null)");
+ goto done;
+ }
+
+ switch(val_type) {
+ case DCERPC_REG_DWORD: {
+ guint32 value;
+ guint16 low, high;
+ int offset2 = start_offset + val_offset;
+
+ /* Needs to be broken into two 16-byte ints because it may
+ not be aligned. */
+
+ offset2 = dissect_ndr_uint16(
+ tvb, offset2, pinfo, subtree, drep,
+ hf_enumprinterdataex_val_dword_low, &low);
+
+ offset2 = dissect_ndr_uint16(
+ tvb, offset2, pinfo, subtree, drep,
+ hf_enumprinterdataex_val_dword_high, &high);
+
+ value = (high << 16) | low;
+
+ proto_tree_add_text(subtree, tvb, start_offset + val_offset, 4,
+ "Value: %d", value);
+
+ proto_item_append_text(item, ", Value: %d", value);
+
+ break;
+ }
+ case DCERPC_REG_SZ: {
+ char *value;
+
+ dissect_spoolss_uint16uni(
+ tvb, start_offset + val_offset, pinfo, subtree, drep,
+ &value, "Value");
+
+ proto_item_append_text(item, ", Value: %s", value);
+
+ g_free(value);
+
+ break;
+ }
+ case DCERPC_REG_BINARY:
+
+ /* FIXME: nicer way to display this */
+
+ proto_tree_add_text(
+ subtree, tvb, start_offset + val_offset, val_len,
+ "Value: <binary data>");
+ break;
+
+ case DCERPC_REG_MULTI_SZ:
+
+ /* FIXME: implement REG_MULTI_SZ support */
+
+ proto_tree_add_text(
+ subtree, tvb, start_offset + val_offset, val_len,
+ "Value: <REG_MULTI_SZ not implemented>");
+ break;
+
+ default:
+ proto_tree_add_text(
+ subtree, tvb, start_offset + val_offset, val_len,
+ "%s: unknown type %d", name, val_type);
+ }
+
+ done:
+ g_free(name);
+
+ return offset;
+}
+
+static gint ett_PRINTER_DATA_CTR;
+
+static int SpoolssEnumPrinterDataEx_r(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 size, num_values;
+
+ proto_tree_add_uint_hidden(
+ tree, hf_printerdata, tvb, offset, 0, 1);
+
+ /* Parse packet */
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep,
+ hf_buffer_size, &size);
+
+ dissect_ndr_uint32(
+ tvb, offset + size + 4, pinfo, NULL, drep, hf_returned,
+ &num_values);
+
+ if (size) {
+ proto_item *item;
+ proto_tree *subtree;
+ int offset2 = offset;
+ guint32 i;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Printer data");
+
+ subtree = proto_item_add_subtree(item, ett_PRINTER_DATA_CTR);
+
+ for (i=0; i < num_values; i++)
+ offset2 = dissect_spoolss_printer_enum_values(
+ tvb, offset2, pinfo, subtree, drep);
+ }
+
+ offset += size;
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_needed, NULL);
+
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_returned, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+#if 0
+
+/* Templates for new subdissectors */
+
+/*
+ * FOO
+ */
+
+static int SpoolssFoo_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+
+ /* Parse packet */
+
+ return offset;
+}
+
+static int SpoolssFoo_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+
+ /* Parse packet */
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_rc, NULL);
+
+ return offset;
+}
+
+#endif
+
+/*
+ * List of subdissectors for this pipe.
+ */
+
+static dcerpc_sub_dissector dcerpc_spoolss_dissectors[] = {
+ { SPOOLSS_ENUMPRINTERS, "EnumPrinters",
+ SpoolssEnumPrinters_q, SpoolssEnumPrinters_r },
+ { SPOOLSS_OPENPRINTER, "OpenPrinter",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_SETJOB, "SetJob",
+ SpoolssSetJob_q, SpoolssSetJob_r },
+ { SPOOLSS_GETJOB, "GetJob",
+ SpoolssGetJob_q, SpoolssGetJob_r },
+ { SPOOLSS_ENUMJOBS, "EnumJobs",
+ SpoolssEnumJobs_q, SpoolssEnumJobs_r },
+ { SPOOLSS_ADDPRINTER, "AddPrinter",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_DELETEPRINTER, "DeletePrinter",
+ SpoolssDeletePrinter_q, SpoolssDeletePrinter_r },
+ { SPOOLSS_SETPRINTER, "SetPrinter",
+ SpoolssSetPrinter_q, SpoolssSetPrinter_r },
+ { SPOOLSS_GETPRINTER, "GetPrinter",
+ SpoolssGetPrinter_q, SpoolssGetPrinter_r },
+ { SPOOLSS_ADDPRINTERDRIVER, "AddPrinterDriver",
+ NULL, SpoolssAddPrinterDriver_r },
+ { SPOOLSS_ENUMPRINTERDRIVERS, "EnumPrinterDrivers",
+ SpoolssEnumPrinterDrivers_q, SpoolssEnumPrinterDrivers_r },
+ { SPOOLSS_GETPRINTERDRIVER, "GetPrinterDriver",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_GETPRINTERDRIVERDIRECTORY, "GetPrinterDriverDirectory",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_DELETEPRINTERDRIVER, "DeletePrinterDriver",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ADDPRINTPROCESSOR, "AddPrintProcessor",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ENUMPRINTPROCESSORS, "EnumPrintProcessor",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_GETPRINTPROCESSORDIRECTORY, "GetPrintProcessorDirectory",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_STARTDOCPRINTER, "StartDocPrinter",
+ SpoolssStartDocPrinter_q, SpoolssStartDocPrinter_r },
+ { SPOOLSS_STARTPAGEPRINTER, "StartPagePrinter",
+ SpoolssStartPagePrinter_q, SpoolssStartPagePrinter_r },
+ { SPOOLSS_WRITEPRINTER, "WritePrinter",
+ SpoolssWritePrinter_q, SpoolssWritePrinter_r },
+ { SPOOLSS_ENDPAGEPRINTER, "EndPagePrinter",
+ SpoolssEndPagePrinter_q, SpoolssEndPagePrinter_r },
+ { SPOOLSS_ABORTPRINTER, "AbortPrinter",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_READPRINTER, "ReadPrinter",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ENDDOCPRINTER, "EndDocPrinter",
+ SpoolssEndDocPrinter_q, SpoolssEndDocPrinter_r },
+ { SPOOLSS_ADDJOB, "AddJob",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_SCHEDULEJOB, "ScheduleJob",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_GETPRINTERDATA, "GetPrinterData",
+ SpoolssGetPrinterData_q, SpoolssGetPrinterData_r },
+ { SPOOLSS_SETPRINTERDATA, "SetPrinterData",
+ SpoolssSetPrinterData_q, SpoolssSetPrinterData_r },
+ { SPOOLSS_WAITFORPRINTERCHANGE, "WaitForPrinterChange",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_CLOSEPRINTER, "ClosePrinter",
+ SpoolssClosePrinter_q, SpoolssClosePrinter_r },
+ { SPOOLSS_ADDFORM, "AddForm",
+ SpoolssAddForm_q, SpoolssAddForm_r },
+ { SPOOLSS_DELETEFORM, "DeleteForm",
+ SpoolssDeleteForm_q, SpoolssDeleteForm_r },
+ { SPOOLSS_GETFORM, "GetForm",
+ SpoolssGetForm_q, SpoolssGetForm_r },
+ { SPOOLSS_SETFORM, "SetForm",
+ SpoolssSetForm_q, SpoolssSetForm_r },
+ { SPOOLSS_ENUMFORMS, "EnumForms",
+ SpoolssEnumForms_q, SpoolssEnumForms_r },
+ { SPOOLSS_ENUMPORTS, "EnumPorts",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ENUMMONITORS, "EnumMonitors",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ADDPORT, "AddPort",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_CONFIGUREPORT, "ConfigurePort",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_DELETEPORT, "DeletePort",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_CREATEPRINTERIC, "CreatePrinterIC",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_PLAYGDISCRIPTONPRINTERIC, "PlayDiscriptOnPrinterIC",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_DELETEPRINTERIC, "DeletePrinterIC",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ADDPRINTERCONNECTION, "AddPrinterConnection",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_DELETEPRINTERCONNECTION, "DeletePrinterConnection",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_PRINTERMESSAGEBOX, "PrinterMessageBox",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ADDMONITOR, "AddMonitor",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_DELETEMONITOR, "DeleteMonitor",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_DELETEPRINTPROCESSOR, "DeletePrintProcessor",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ADDPRINTPROVIDER, "AddPrintProvider",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_DELETEPRINTPROVIDER, "DeletePrintProvider",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ENUMPRINTPROCDATATYPES, "EnumPrintProcDataTypes",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_RESETPRINTER, "ResetPrinter",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_GETPRINTERDRIVER2, "GetPrinterDriver2",
+ SpoolssGetPrinterDriver2_q, SpoolssGetPrinterDriver2_r },
+ { SPOOLSS_FINDFIRSTPRINTERCHANGENOTIFICATION,
+ "FindFirstPrinterChangeNotification",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_FINDNEXTPRINTERCHANGENOTIFICATION,
+ "FindNextPrinterChangeNotification",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_FCPN, "FCPN",
+ SpoolssFCPN_q, SpoolssFCPN_r },
+ { SPOOLSS_ROUTERFINDFIRSTPRINTERNOTIFICATIONOLD,
+ "RouterFindFirstPrinterNotificationOld",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_REPLYOPENPRINTER, "ReplyOpenPrinter",
+ SpoolssReplyOpenPrinter_q, SpoolssReplyOpenPrinter_r },
+ { SPOOLSS_ROUTERREPLYPRINTER, "RouterReplyPrinter",
+ SpoolssRouterReplyPrinter_q, SpoolssRouterReplyPrinter_r },
+ { SPOOLSS_REPLYCLOSEPRINTER, "ReplyClosePrinter",
+ SpoolssReplyClosePrinter_q, SpoolssReplyClosePrinter_r },
+ { SPOOLSS_ADDPORTEX, "AddPortEx",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFICATION,
+ "RemoteFindFirstPrinterChangeNotification",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_SPOOLERINIT, "SpoolerInit",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_RESETPRINTEREX, "ResetPrinterEx",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_RFFPCNEX, "RFFPCNEX",
+ SpoolssRFFPCNEX_q, SpoolssRFFPCNEX_r },
+ { SPOOLSS_RRPCN, "RRPCN",
+ SpoolssRRPCN_q, SpoolssRRPCN_r },
+ { SPOOLSS_RFNPCNEX, "RFNPCNEX",
+ SpoolssRFNPCNEX_q, SpoolssRFNPCNEX_r },
+ { SPOOLSS_OPENPRINTEREX, "OpenPrinterEx",
+ SpoolssOpenPrinterEx_q, SpoolssOpenPrinterEx_r },
+ { SPOOLSS_ADDPRINTEREX, "AddPrinterEx",
+ NULL, SpoolssAddPrinterEx_r },
+ { SPOOLSS_ENUMPRINTERDATA, "EnumPrinterData",
+ SpoolssEnumPrinterData_q, SpoolssEnumPrinterData_r },
+ { SPOOLSS_DELETEPRINTERDATA, "DeletePrinterData",
+ SpoolssDeletePrinterData_q, SpoolssDeletePrinterData_r },
+ { SPOOLSS_GETPRINTERDATAEX, "GetPrinterDataEx",
+ SpoolssGetPrinterDataEx_q, SpoolssGetPrinterDataEx_r },
+ { SPOOLSS_SETPRINTERDATAEX, "SetPrinterDataEx",
+ SpoolssSetPrinterDataEx_q, SpoolssSetPrinterDataEx_r },
+ { SPOOLSS_ENUMPRINTERDATAEX, "EnumPrinterDataEx",
+ SpoolssEnumPrinterDataEx_q, SpoolssEnumPrinterDataEx_r },
+ { SPOOLSS_ENUMPRINTERKEY, "EnumPrinterKey",
+ SpoolssEnumPrinterKey_q, SpoolssEnumPrinterKey_r },
+ { SPOOLSS_DELETEPRINTERDATAEX, "DeletePrinterDataEx",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_DELETEPRINTERDRIVEREX, "DeletePrinterDriverEx",
+ NULL, SpoolssGeneric_r },
+ { SPOOLSS_ADDPRINTERDRIVEREX, "AddPrinterDriverEx",
+ NULL, SpoolssGeneric_r },
+
+ { 0, NULL, NULL, NULL },
+};
+
+/*
+ * Dissector initialisation function
+ */
+
+/* Protocol registration */
+
+static int proto_dcerpc_spoolss = -1;
+static gint ett_dcerpc_spoolss = -1;
+
+void
+proto_register_dcerpc_spoolss(void)
+{
+ static hf_register_info hf[] = {
+
+ /* GetPrinterDriver2 */
+
+ { &hf_clientmajorversion,
+ { "Client major version", "spoolss.clientmajorversion", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Client printer driver major version", HFILL }},
+ { &hf_clientminorversion,
+ { "Client minor version", "spoolss.clientminorversion", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Client printer driver minor version", HFILL }},
+ { &hf_servermajorversion,
+ { "Server major version", "spoolss.servermajorversion", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Server printer driver major version", HFILL }},
+ { &hf_serverminorversion,
+ { "Server minor version", "spoolss.serverminorversion", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Server printer driver minor version", HFILL }},
+ { &hf_driverpath,
+ { "Driver path", "spoolss.driverpath", FT_STRING, BASE_NONE,
+ NULL, 0, "Driver path", HFILL }},
+ { &hf_datafile,
+ { "Data file", "spoolss.datafile", FT_STRING, BASE_NONE,
+ NULL, 0, "Data file", HFILL }},
+ { &hf_configfile,
+ { "Config file", "spoolss.configfile", FT_STRING, BASE_NONE,
+ NULL, 0, "Printer name", HFILL }},
+ { &hf_helpfile,
+ { "Help file", "spoolss.helpfile", FT_STRING, BASE_NONE,
+ NULL, 0, "Help file", HFILL }},
+ { &hf_monitorname,
+ { "Monitor name", "spoolss.monitorname", FT_STRING, BASE_NONE,
+ NULL, 0, "Monitor name", HFILL }},
+ { &hf_defaultdatatype,
+ { "Default data type", "spoolss.defaultdatatype", FT_STRING, BASE_NONE,
+ NULL, 0, "Default data type", HFILL }},
+ { &hf_driverinfo_cversion,
+ { "Driver version", "spoolss.driverversion", FT_UINT32, BASE_DEC,
+ VALS(driverinfo_cversion_vals), 0, "Printer name", HFILL }},
+ { &hf_dependentfiles,
+ { "Dependent files", "spoolss.dependentfiles", FT_STRING, BASE_NONE,
+ NULL, 0, "Dependent files", HFILL }},
+
+ { &hf_printer_status,
+ { "Status", "spoolss.printer_status", FT_UINT32, BASE_DEC,
+ VALS(printer_status_vals), 0, "Status", HFILL }},
+
+ /* Setprinter RPC */
+
+ { &hf_setprinter_cmd,
+ { "Command", "spoolss.setprinter_cmd", FT_UINT32, BASE_DEC,
+ VALS(setprinter_cmd_vals), 0, "Command", HFILL }},
+
+ /* Enumprinters */
+
+ { &hf_enumprinters_flags,
+ { "Flags", "spoolss.enumprinters.flags",
+ FT_UINT32, BASE_HEX, NULL, 0, "Flags", HFILL }},
+
+ { &hf_enumprinters_flags_local,
+ { "Enum local", "spoolss.enumprinters.flags.enum_local",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ PRINTER_ENUM_LOCAL, "Enum local", HFILL }},
+
+ { &hf_enumprinters_flags_name,
+ { "Enum name", "spoolss.enumprinters.flags.enum_name",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ PRINTER_ENUM_NAME, "Enum name", HFILL }},
+
+ { &hf_enumprinters_flags_shared,
+ { "Enum shared", "spoolss.enumprinters.flags.enum_shared",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ PRINTER_ENUM_SHARED, "Enum shared", HFILL }},
+
+ { &hf_enumprinters_flags_default,
+ { "Enum default", "spoolss.enumprinters.flags.enum_default",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ PRINTER_ENUM_DEFAULT, "Enum default", HFILL }},
+
+ { &hf_enumprinters_flags_connections,
+ { "Enum connections", "spoolss.enumprinters.flags.enum_connections",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ PRINTER_ENUM_CONNECTIONS, "Enum connections", HFILL }},
+
+ { &hf_enumprinters_flags_network,
+ { "Enum network", "spoolss.enumprinters.flags.enum_network",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ PRINTER_ENUM_NETWORK, "Enum network", HFILL }},
+
+ { &hf_enumprinters_flags_remote,
+ { "Enum remote", "spoolss.enumprinters.flags.enum_remote",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ PRINTER_ENUM_REMOTE, "Enum remote", HFILL }},
+
+ /* GetPrinter */
+
+ { &hf_start_time,
+ { "Start time", "spoolss.start_time",
+ FT_UINT32, BASE_DEC, NULL, 0, "Start time", HFILL }},
+
+ { &hf_end_time,
+ { "End time", "spoolss.end_time",
+ FT_UINT32, BASE_DEC, NULL, 0, "End time", HFILL }},
+
+ { &hf_elapsed_time,
+ { "Elapsed time", "spoolss.elapsed_time",
+ FT_UINT32, BASE_DEC, NULL, 0, "Elapsed time", HFILL }},
+
+ /*
+ * New hf index values
+ */
+
+ { &hf_opnum,
+ { "Operation", "spoolss.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+
+ { &hf_hnd,
+ { "Context handle", "spoolss.hnd", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "SPOOLSS policy handle", HFILL }},
+
+ { &hf_rc,
+ { "Return code", "spoolss.rc", FT_UINT32, BASE_HEX,
+ VALS(DOS_errors), 0x0, "SPOOLSS return code", HFILL }},
+
+ { &hf_offered,
+ { "Offered", "spoolss.offered", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of buffer offered in this request",
+ HFILL }},
+
+ { &hf_needed,
+ { "Needed", "spoolss.needed", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of buffer required for request", HFILL }},
+
+ { &hf_returned,
+ { "Returned", "spoolss.returned", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Number of items returned", HFILL }},
+
+ { &hf_buffer_size,
+ { "Buffer size", "spoolss.buffer.size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Size of buffer", HFILL }},
+
+ { &hf_buffer_data,
+ { "Buffer data", "spoolss.buffer.data", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Contents of buffer", HFILL }},
+
+ { &hf_offset,
+ { "Offset", "spoolss.offset", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Offset of data", HFILL }},
+
+ { &hf_level,
+ { "Info level", "spoolss.enumjobs.level", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Info level", HFILL }},
+
+
+ { &hf_printername,
+ { "Printer name", "spoolss.printername", FT_STRING,
+ BASE_NONE, NULL, 0, "Printer name", HFILL }},
+
+ { &hf_machinename,
+ { "Machine name", "spoolss.machinename", FT_STRING,
+ BASE_NONE, NULL, 0, "Machine name", HFILL }},
+
+ { &hf_notifyname,
+ { "Notify name", "spoolss.notifyname", FT_STRING,
+ BASE_NONE, NULL, 0, "Notify name", HFILL }},
+
+ { &hf_printerdesc,
+ { "Printer description", "spoolss.printerdesc", FT_STRING,
+ BASE_NONE, NULL, 0, "Printer description", HFILL }},
+
+ { &hf_printercomment,
+ { "Printer comment", "spoolss.printercomment", FT_STRING,
+ BASE_NONE, NULL, 0, "Printer comment", HFILL }},
+
+ { &hf_servername,
+ { "Server name", "spoolss.servername", FT_STRING, BASE_NONE,
+ NULL, 0, "Server name", HFILL }},
+
+ { &hf_sharename,
+ { "Share name", "spoolss.sharename", FT_STRING, BASE_NONE,
+ NULL, 0, "Share name", HFILL }},
+
+ { &hf_portname,
+ { "Port name", "spoolss.portname", FT_STRING, BASE_NONE,
+ NULL, 0, "Port name", HFILL }},
+
+ { &hf_printerlocation,
+ { "Printer location", "spoolss.printerlocation", FT_STRING,
+ BASE_NONE, NULL, 0, "Printer location", HFILL }},
+
+ { &hf_architecture,
+ { "Architecture name", "spoolss.architecture", FT_STRING,
+ BASE_NONE, NULL, 0, "Architecture name", HFILL }},
+
+ { &hf_drivername,
+ { "Driver name", "spoolss.drivername", FT_STRING, BASE_NONE,
+ NULL, 0, "Driver name", HFILL }},
+
+ { &hf_username,
+ { "User name", "spoolss.username", FT_STRING, BASE_NONE,
+ NULL, 0, "User name", HFILL }},
+
+ { &hf_documentname,
+ { "Document name", "spoolss.document", FT_STRING, BASE_NONE,
+ NULL, 0, "Document name", HFILL }},
+
+ { &hf_outputfile,
+ { "Output file", "spoolss.outputfile", FT_STRING, BASE_NONE,
+ NULL, 0, "Output File", HFILL }},
+
+ { &hf_datatype,
+ { "Datatype", "spoolss.Datatype", FT_STRING, BASE_NONE,
+ NULL, 0, "Datatype", HFILL }},
+
+ { &hf_textstatus,
+ { "Text status", "spoolss.textstatus", FT_STRING, BASE_NONE,
+ NULL, 0, "Text status", HFILL }},
+
+ { &hf_sepfile,
+ { "Separator file", "spoolss.setpfile", FT_STRING, BASE_NONE,
+ NULL, 0, "Separator file", HFILL }},
+
+ { &hf_parameters,
+ { "Parameters", "spoolss.parameters", FT_STRING, BASE_NONE,
+ NULL, 0, "Parameters", HFILL }},
+
+ { &hf_printprocessor,
+ { "Print processor", "spoolss.printprocessor", FT_STRING,
+ BASE_NONE, NULL, 0, "Print processor", HFILL }},
+
+ /* Printer data */
+
+ { &hf_printerdata,
+ { "Data", "spoolss.printerdata", FT_UINT32,
+ BASE_HEX, NULL, 0, "Data", HFILL }},
+
+ { &hf_printerdata_key,
+ { "Key", "spoolss.printerdata.key", FT_STRING,
+ BASE_NONE, NULL, 0, "Printer data key", HFILL }},
+
+ { &hf_printerdata_value,
+ { "Value", "spoolss.printerdata.value",
+ FT_STRING, BASE_NONE, NULL, 0, "Printer data value",
+ HFILL }},
+
+ { &hf_printerdata_type,
+ { "Type", "spoolss.printerdata.type",
+ FT_UINT32, BASE_DEC, VALS(reg_datatypes), 0,
+ "Printer data type", HFILL }},
+
+ { &hf_printerdata_size,
+ { "Size", "spoolss.printerdata.size",
+ FT_UINT32, BASE_DEC, NULL, 0, "Printer data size",
+ HFILL }},
+
+ { &hf_printerdata_data,
+ { "Data", "spoolss.printerdata.data", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Printer data", HFILL }},
+
+ { &hf_printerdata_data_dword,
+ { "DWORD data", "spoolss.printerdata.data.dword",
+ FT_UINT32, BASE_HEX, NULL, 0, "DWORD data", HFILL }},
+
+ { &hf_printerdata_data_sz,
+ { "String data", "spoolss.printerdata.data.sz",
+ FT_STRING, BASE_NONE, NULL, 0, "String data",
+ HFILL }},
+
+ /* Devicemode */
+
+ { &hf_devmodectr_size,
+ { "Devicemode ctr size", "spoolss.devicemodectr.size",
+ FT_UINT32, BASE_DEC, NULL, 0, "Devicemode ctr size",
+ HFILL }},
+
+ { &hf_devmode,
+ { "Devicemode", "spoolss.devmode", FT_UINT32,
+ BASE_HEX, NULL, 0, "Devicemode", HFILL }},
+
+ { &hf_devmode_size,
+ { "Size", "spoolss.devmode.size",
+ FT_UINT32, BASE_DEC, NULL, 0, "Size", HFILL }},
+
+ { &hf_devmode_spec_version,
+ { "Spec version", "spoolss.devmode.spec_version",
+ FT_UINT16, BASE_DEC, VALS(devmode_specversion_vals),
+ 0, "Spec version", HFILL }},
+
+ { &hf_devmode_driver_version,
+ { "Driver version", "spoolss.devmode.driver_version",
+ FT_UINT16, BASE_DEC, NULL, 0, "Driver version", HFILL }},
+
+ { &hf_devmode_size2,
+ { "Size2", "spoolss.devmode.size2",
+ FT_UINT16, BASE_DEC, NULL, 0, "Size2", HFILL }},
+
+ { &hf_devmode_fields,
+ { "Fields", "spoolss.devmode.fields",
+ FT_UINT32, BASE_HEX, NULL, 0, "Fields", HFILL }},
+
+ { &hf_devmode_orientation,
+ { "Orientation", "spoolss.devmode.orientation",
+ FT_UINT16, BASE_DEC, VALS(devmode_orientation_vals),
+ 0, "Orientation", HFILL }},
+
+ { &hf_devmode_paper_size,
+ { "Paper size", "spoolss.devmode.paper_size",
+ FT_UINT16, BASE_DEC, VALS(devmode_papersize_vals),
+ 0, "Paper size", HFILL }},
+
+ { &hf_devmode_paper_width,
+ { "Paper width", "spoolss.devmode.paper_width",
+ FT_UINT16, BASE_DEC, NULL, 0, "Paper width", HFILL }},
+
+ { &hf_devmode_paper_length,
+ { "Paper length", "spoolss.devmode.paper_length",
+ FT_UINT16, BASE_DEC, NULL, 0, "Paper length", HFILL }},
+
+ { &hf_devmode_scale,
+ { "Scale", "spoolss.devmode.scale",
+ FT_UINT16, BASE_DEC, NULL, 0, "Scale", HFILL }},
+
+ { &hf_devmode_copies,
+ { "Copies", "spoolss.devmode.copies",
+ FT_UINT16, BASE_DEC, NULL, 0, "Copies", HFILL }},
+
+ { &hf_devmode_default_source,
+ { "Default source", "spoolss.devmode.default_source",
+ FT_UINT16, BASE_DEC, VALS(devmode_papersource_vals),
+ 0, "Default source", HFILL }},
+
+ { &hf_devmode_print_quality,
+ { "Print quality", "spoolss.devmode.print_quality",
+ FT_UINT16, BASE_DEC, VALS(devmode_printquality_vals),
+ 0, "Print quality", HFILL }},
+
+ { &hf_devmode_color,
+ { "Color", "spoolss.devmode.color",
+ FT_UINT16, BASE_DEC, VALS(devmode_colour_vals), 0,
+ "Color", HFILL }},
+
+ { &hf_devmode_duplex,
+ { "Duplex", "spoolss.devmode.duplex",
+ FT_UINT16, BASE_DEC, VALS(devmode_duplex_vals), 0,
+ "Duplex", HFILL }},
+
+ { &hf_devmode_y_resolution,
+ { "Y resolution", "spoolss.devmode.y_resolution",
+ FT_UINT16, BASE_DEC, NULL, 0, "Y resolution", HFILL }},
+
+ { &hf_devmode_tt_option,
+ { "TT option", "spoolss.devmode.tt_option",
+ FT_UINT16, BASE_DEC, VALS(devmode_ttoption_vals), 0,
+ "TT option", HFILL }},
+
+ { &hf_devmode_collate,
+ { "Collate", "spoolss.devmode.collate",
+ FT_UINT16, BASE_DEC, VALS(devmode_collate_vals), 0,
+ "Collate", HFILL }},
+
+ { &hf_devmode_log_pixels,
+ { "Log pixels", "spoolss.devmode.log_pixels",
+ FT_UINT16, BASE_DEC, NULL, 0, "Log pixels", HFILL }},
+
+ { &hf_devmode_bits_per_pel,
+ { "Bits per pel", "spoolss.devmode.bits_per_pel",
+ FT_UINT32, BASE_DEC, NULL, 0, "Bits per pel", HFILL }},
+
+ { &hf_devmode_pels_width,
+ { "Pels width", "spoolss.devmode.pels_width",
+ FT_UINT32, BASE_DEC, NULL, 0, "Pels width", HFILL }},
+
+ { &hf_devmode_pels_height,
+ { "Pels height", "spoolss.devmode.pels_height",
+ FT_UINT32, BASE_DEC, NULL, 0, "Pels height", HFILL }},
+
+ { &hf_devmode_display_flags,
+ { "Display flags", "spoolss.devmode.display_flags",
+ FT_UINT32, BASE_DEC, VALS(devmode_displayflags_vals), 0,
+ "Display flags", HFILL }},
+
+ { &hf_devmode_display_freq,
+ { "Display frequency", "spoolss.devmode.display_freq",
+ FT_UINT32, BASE_DEC, NULL, 0, "Display frequency",
+ HFILL }},
+
+ { &hf_devmode_icm_method,
+ { "ICM method", "spoolss.devmode.icm_method",
+ FT_UINT32, BASE_DEC, VALS(devmode_icmmethod_vals), 0,
+ "ICM method", HFILL }},
+
+ { &hf_devmode_icm_intent,
+ { "ICM intent", "spoolss.devmode.icm_intent",
+ FT_UINT32, BASE_DEC, VALS(devmode_icmintent_vals), 0,
+ "ICM intent", HFILL }},
+
+ { &hf_devmode_media_type,
+ { "Media type", "spoolss.devmode.media_type",
+ FT_UINT32, BASE_DEC, VALS(devmode_mediatype_vals), 0,
+ "Media type", HFILL }},
+
+ { &hf_devmode_dither_type,
+ { "Dither type", "spoolss.devmode.dither_type",
+ FT_UINT32, BASE_DEC, VALS(devmode_dithertype_vals), 0,
+ "Dither type", HFILL }},
+
+ { &hf_devmode_reserved1,
+ { "Reserved1", "spoolss.devmode.reserved1",
+ FT_UINT32, BASE_DEC, NULL, 0, "Reserved1", HFILL }},
+
+ { &hf_devmode_reserved2,
+ { "Reserved2", "spoolss.devmode.reserved2",
+ FT_UINT32, BASE_DEC, NULL, 0, "Reserved2", HFILL }},
+
+ { &hf_devmode_panning_width,
+ { "Panning width", "spoolss.devmode.panning_width",
+ FT_UINT32, BASE_DEC, NULL, 0, "Panning width", HFILL }},
+
+ { &hf_devmode_panning_height,
+ { "Panning height", "spoolss.devmode.panning_height",
+ FT_UINT32, BASE_DEC, NULL, 0, "Panning height", HFILL }},
+
+ { &hf_devmode_driver_extra_len,
+ { "Driver extra length",
+ "spoolss.devmode.driver_extra_len",
+ FT_UINT32, BASE_DEC, NULL, 0, "Driver extra length",
+ HFILL }},
+
+ { &hf_devmode_driver_extra,
+ { "Driver extra", "spoolss.devmode.driver_extra",
+ FT_BYTES, BASE_NONE, NULL, 0, "Driver extra", HFILL }},
+
+ /* Devicemode fields */
+
+ { &hf_devmode_fields_orientation,
+ { "Orientation", "spoolss.devmode.fields.orientation",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_ORIENTATION, "Orientation", HFILL }},
+
+ { &hf_devmode_fields_papersize,
+ { "Paper size", "spoolss.devmode.fields.paper_size",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_PAPERSIZE, "Paper size", HFILL }},
+
+ { &hf_devmode_fields_paperlength,
+ { "Paper length", "spoolss.devmode.fields.paper_length",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_PAPERLENGTH, "Paper length", HFILL }},
+
+ { &hf_devmode_fields_paperwidth,
+ { "Paper width", "spoolss.devmode.fields.paper_width",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_PAPERWIDTH, "Paper width", HFILL }},
+
+ { &hf_devmode_fields_scale,
+ { "Scale", "spoolss.devmode.fields.scale",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_SCALE, "Scale", HFILL }},
+
+ { &hf_devmode_fields_position,
+ { "Position", "spoolss.devmode.fields.position",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_POSITION, "Position", HFILL }},
+
+ { &hf_devmode_fields_nup,
+ { "N-up", "spoolss.devmode.fields.nup",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_NUP, "N-up", HFILL }},
+
+ { &hf_devmode_fields_copies,
+ { "Copies", "spoolss.devmode.fields.copies",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_COPIES, "Copies", HFILL }},
+
+ { &hf_devmode_fields_defaultsource,
+ { "Default source", "spoolss.devmode.fields.default_source",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_DEFAULTSOURCE, "Default source", HFILL }},
+
+ { &hf_devmode_fields_printquality,
+ { "Print quality", "spoolss.devmode.fields.print_quality",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_PRINTQUALITY, "Print quality", HFILL }},
+
+ { &hf_devmode_fields_color,
+ { "Color", "spoolss.devmode.fields.color",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_COLOR, "Color", HFILL }},
+
+ { &hf_devmode_fields_duplex,
+ { "Duplex", "spoolss.devmode.fields.duplex",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_DUPLEX, "Duplex", HFILL }},
+
+ { &hf_devmode_fields_yresolution,
+ { "Y resolution", "spoolss.devmode.fields.y_resolution",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_YRESOLUTION, "Y resolution", HFILL }},
+
+ { &hf_devmode_fields_ttoption,
+ { "TT option", "spoolss.devmode.fields.tt_option",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_TTOPTION, "TT option", HFILL }},
+
+ { &hf_devmode_fields_collate,
+ { "Collate", "spoolss.devmode.fields.collate",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_COLLATE, "Collate", HFILL }},
+
+ { &hf_devmode_fields_formname,
+ { "Form name", "spoolss.devmode.fields.form_name",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_FORMNAME, "Form name", HFILL }},
+
+ { &hf_devmode_fields_logpixels,
+ { "Log pixels", "spoolss.devmode.fields.log_pixels",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_LOGPIXELS, "Log pixels", HFILL }},
+
+ { &hf_devmode_fields_bitsperpel,
+ { "Bits per pel", "spoolss.devmode.fields.bits_per_pel",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_BITSPERPEL, "Bits per pel", HFILL }},
+
+ { &hf_devmode_fields_pelswidth,
+ { "Pels width", "spoolss.devmode.fields.pels_width",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_PELSWIDTH, "Pels width", HFILL }},
+
+ { &hf_devmode_fields_pelsheight,
+ { "Pels height", "spoolss.devmode.fields.pels_height",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_PELSHEIGHT, "Pels height", HFILL }},
+
+ { &hf_devmode_fields_displayflags,
+ { "Display flags", "spoolss.devmode.fields.display_flags",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_DISPLAYFLAGS, "Display flags", HFILL }},
+
+ { &hf_devmode_fields_displayfrequency,
+ { "Display frequency",
+ "spoolss.devmode.fields.display_frequency",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_DISPLAYFREQUENCY, "Display frequency", HFILL }},
+
+ { &hf_devmode_fields_icmmethod,
+ { "ICM method", "spoolss.devmode.fields.icm_method",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_ICMMETHOD, "ICM method", HFILL }},
+
+ { &hf_devmode_fields_icmintent,
+ { "ICM intent", "spoolss.devmode.fields.icm_intent",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_ICMINTENT, "ICM intent", HFILL }},
+
+ { &hf_devmode_fields_mediatype,
+ { "Media type", "spoolss.devmode.fields.media_type",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_MEDIATYPE, "Media type", HFILL }},
+
+ { &hf_devmode_fields_dithertype,
+ { "Dither type", "spoolss.devmode.fields.dither_type",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_DITHERTYPE, "Dither type", HFILL }},
+
+ { &hf_devmode_fields_panningwidth,
+ { "Panning width", "spoolss.devmode.fields.panning_width",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_PANNINGWIDTH, "Panning width", HFILL }},
+
+ { &hf_devmode_fields_panningheight,
+ { "Panning height", "spoolss.devmode.fields.panning_height",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DEVMODE_PANNINGHEIGHT, "Panning height", HFILL }},
+
+ /* EnumPrinterData RPC */
+
+ { &hf_enumprinterdata_enumindex,
+ { "Enum index", "spoolss.enumprinterdata.enumindex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Index for start of enumeration", HFILL }},
+
+ { &hf_enumprinterdata_value_offered,
+ { "Value size offered",
+ "spoolss.enumprinterdata.value_offered", FT_UINT32,
+ BASE_DEC, NULL, 0x0,
+ "Buffer size offered for printerdata value", HFILL }},
+
+ { &hf_enumprinterdata_data_offered,
+ { "Data size offered",
+ "spoolss.enumprinterdata.data_offered", FT_UINT32,
+ BASE_DEC, NULL, 0x0,
+ "Buffer size offered for printerdata data", HFILL }},
+
+ { &hf_enumprinterdata_value_len,
+ { "Value length",
+ "spoolss.enumprinterdata.value_len", FT_UINT32,
+ BASE_DEC, NULL, 0x0,
+ "Size of printerdata value", HFILL }},
+
+ { &hf_enumprinterdata_value_needed,
+ { "Value size needed",
+ "spoolss.enumprinterdata.value_needed", FT_UINT32,
+ BASE_DEC, NULL, 0x0,
+ "Buffer size needed for printerdata value", HFILL }},
+
+ { &hf_enumprinterdata_data_needed,
+ { "Data size needed",
+ "spoolss.enumprinterdata.data_needed", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Buffer size needed for printerdata data",
+ HFILL }},
+
+ /* Print jobs */
+
+ { &hf_job_id,
+ { "Job ID", "spoolss.job.id", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Job identification number", HFILL }},
+
+ { &hf_job_status,
+ { "Job status", "spoolss.job.status", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Job status", HFILL }},
+
+ { &hf_job_status_paused,
+ { "Paused", "spoolss.job.status.paused", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_paused), JOB_STATUS_PAUSED,
+ "Paused", HFILL }},
+
+ { &hf_job_status_error,
+ { "Error", "spoolss.job.status.error", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_error), JOB_STATUS_ERROR,
+ "Error", HFILL }},
+
+ { &hf_job_status_deleting,
+ { "Deleting", "spoolss.job.status.deleting", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_deleting), JOB_STATUS_DELETING,
+ "Deleting", HFILL }},
+
+ { &hf_job_status_spooling,
+ { "Spooling", "spoolss.job.status.spooling", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_spooling), JOB_STATUS_SPOOLING,
+ "Spooling", HFILL }},
+
+ { &hf_job_status_printing,
+ { "Printing", "spoolss.job.status.printing", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_printing), JOB_STATUS_PRINTING,
+ "Printing", HFILL }},
+
+ { &hf_job_status_offline,
+ { "Offline", "spoolss.job.status.offline", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_offline), JOB_STATUS_OFFLINE,
+ "Offline", HFILL }},
+
+ { &hf_job_status_paperout,
+ { "Paperout", "spoolss.job.status.paperout", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_paperout), JOB_STATUS_PAPEROUT,
+ "Paperout", HFILL }},
+
+ { &hf_job_status_printed,
+ { "Printed", "spoolss.job.status.printed", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_printed), JOB_STATUS_PRINTED,
+ "Printed", HFILL }},
+
+ { &hf_job_status_deleted,
+ { "Deleted", "spoolss.job.status.deleted", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_deleted), JOB_STATUS_DELETED,
+ "Deleted", HFILL }},
+
+ { &hf_job_status_blocked,
+ { "Blocked", "spoolss.job.status.blocked", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_blocked), JOB_STATUS_BLOCKED,
+ "Blocked", HFILL }},
+
+ { &hf_job_status_user_intervention,
+ { "User intervention",
+ "spoolss.job.status.user_intervention", FT_BOOLEAN, 32,
+ TFS(&tfs_job_status_user_intervention),
+ JOB_STATUS_USER_INTERVENTION, "User intervention",
+ HFILL }},
+
+ { &hf_job_priority,
+ { "Job priority", "spoolss.job.priority", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Job priority", HFILL }},
+
+ { &hf_job_position,
+ { "Job position", "spoolss.job.position", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Job position", HFILL }},
+
+ { &hf_job_totalpages,
+ { "Job total pages", "spoolss.job.totalpages", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Job total pages", HFILL }},
+
+ { &hf_job_totalbytes,
+ { "Job total bytes", "spoolss.job.totalbytes", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Job total bytes", HFILL }},
+
+ { &hf_job_bytesprinted,
+ { "Job bytes printed", "spoolss.job.bytesprinted",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "Job bytes printed",
+ HFILL }},
+
+ { &hf_job_pagesprinted,
+ { "Job pages printed", "spoolss.job.pagesprinted",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "Job pages printed",
+ HFILL }},
+
+ { &hf_job_size,
+ { "Job size", "spoolss.job.size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Job size", HFILL }},
+
+ /* Forms */
+
+ { &hf_form,
+ { "Data", "spoolss.form", FT_UINT32,
+ BASE_HEX, NULL, 0, "Data", HFILL }},
+
+ { &hf_form_level,
+ { "Level", "spoolss.form.level", FT_UINT32,
+ BASE_DEC, NULL, 0, "Level", HFILL }},
+
+ { &hf_form_name,
+ { "Name", "spoolss.form.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name", HFILL }},
+
+ { &hf_form_flags,
+ { "Flags", "spoolss.form.flags", FT_UINT32,
+ BASE_DEC, VALS(form_type_vals), 0, "Flags", HFILL }},
+
+ { &hf_form_unknown,
+ { "Unknown", "spoolss.form.unknown", FT_UINT32,
+ BASE_HEX, NULL, 0, "Unknown", HFILL }},
+
+ { &hf_form_width,
+ { "Width", "spoolss.form.width", FT_UINT32,
+ BASE_DEC, NULL, 0, "Width", HFILL }},
+
+ { &hf_form_height,
+ { "Height", "spoolss.form.height", FT_UINT32,
+ BASE_DEC, NULL, 0, "Height", HFILL }},
+
+ { &hf_form_left_margin,
+ { "Left margin", "spoolss.form.left", FT_UINT32,
+ BASE_DEC, NULL, 0, "Left", HFILL }},
+
+ { &hf_form_top_margin,
+ { "Top", "spoolss.form.top", FT_UINT32,
+ BASE_DEC, NULL, 0, "Top", HFILL }},
+
+ { &hf_form_horiz_len,
+ { "Horizontal", "spoolss.form.horiz", FT_UINT32,
+ BASE_DEC, NULL, 0, "Horizontal", HFILL }},
+
+ { &hf_form_vert_len,
+ { "Vertical", "spoolss.form.vert", FT_UINT32,
+ BASE_DEC, NULL, 0, "Vertical", HFILL }},
+
+ { &hf_enumforms_num,
+ { "Num", "spoolss.enumforms.num", FT_UINT32,
+ BASE_DEC, NULL, 0, "Num", HFILL }},
+
+ /* Print notify */
+
+ { &hf_notify_options_version,
+ { "Version", "spoolss.notify_options.version", FT_UINT32,
+ BASE_DEC, NULL, 0, "Version", HFILL }},
+
+ { &hf_notify_options_flags,
+ { "Flags", "spoolss.notify_options.flags", FT_UINT32,
+ BASE_DEC, NULL, 0, "Flags", HFILL }},
+
+ { &hf_notify_options_count,
+ { "Count", "spoolss.notify_options.count", FT_UINT32,
+ BASE_DEC, NULL, 0, "Count", HFILL }},
+
+ { &hf_notify_option_type,
+ { "Type", "spoolss.notify_option.type", FT_UINT16, BASE_DEC,
+ VALS(printer_notify_types), 0, "Type", HFILL }},
+
+ { &hf_notify_option_reserved1,
+ { "Reserved1", "spoolss.notify_option.reserved1", FT_UINT16,
+ BASE_DEC, NULL, 0, "Reserved1", HFILL }},
+
+ { &hf_notify_option_reserved2,
+ { "Reserved2", "spoolss.notify_option.reserved2", FT_UINT32,
+ BASE_DEC, NULL, 0, "Reserved2", HFILL }},
+
+ { &hf_notify_option_reserved3,
+ { "Reserved3", "spoolss.notify_option.reserved3", FT_UINT32,
+ BASE_DEC, NULL, 0, "Reserved3", HFILL }},
+
+ { &hf_notify_option_count,
+ { "Count", "spoolss.notify_option.count", FT_UINT32,
+ BASE_DEC, NULL, 0, "Count", HFILL }},
+
+ { &hf_notify_option_data_count,
+ { "Count", "spoolss.notify_option_data.count", FT_UINT32,
+ BASE_DEC, NULL, 0, "Count", HFILL }},
+
+ { &hf_notify_options_flags_refresh,
+ { "Refresh", "spoolss.notify_options.flags", FT_BOOLEAN, 32,
+ TFS(&tfs_notify_options_flags_refresh),
+ PRINTER_NOTIFY_OPTIONS_REFRESH, "Refresh", HFILL }},
+
+ { &hf_notify_info_count,
+ { "Count", "spoolss.notify_info.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Count", HFILL }},
+
+ { &hf_notify_info_version,
+ { "Version", "spoolss.notify_info.version", FT_UINT32,
+ BASE_DEC, NULL, 0, "Version", HFILL }},
+
+ { &hf_notify_info_flags,
+ { "Flags", "spoolss.notify_info.flags", FT_UINT32, BASE_HEX,
+ NULL, 0, "Flags", HFILL }},
+
+ { &hf_notify_info_data_type,
+ { "Type", "spoolss.notify_info_data.type", FT_UINT16,
+ BASE_DEC, VALS(printer_notify_types), 0, "Type", HFILL }},
+
+ { &hf_notify_field,
+ { "Field", "spoolss.notify_field", FT_UINT16, BASE_DEC,
+ NULL, 0, "Field", HFILL }},
+
+ { &hf_notify_info_data_count,
+ { "Count", "spoolss.notify_info_data.count", FT_UINT32,
+ BASE_DEC, NULL, 0, "Count", HFILL }},
+
+ { &hf_notify_info_data_id,
+ { "Job Id", "spoolss.notify_info_data.jobid", FT_UINT32,
+ BASE_DEC, NULL, 0, "Job Id", HFILL }},
+
+ { &hf_notify_info_data_value1,
+ { "Value1", "spoolss.notify_info_data.value1", FT_UINT32,
+ BASE_HEX, NULL, 0, "Value1", HFILL }},
+
+ { &hf_notify_info_data_value2,
+ { "Value2", "spoolss.notify_info_data.value2", FT_UINT32,
+ BASE_HEX, NULL, 0, "Value2", HFILL }},
+
+ { &hf_notify_info_data_bufsize,
+ { "Buffer size", "spoolss.notify_info_data.bufsize",
+ FT_UINT32, BASE_DEC, NULL, 0, "Buffer size", HFILL }},
+
+ { &hf_notify_info_data_buffer,
+ { "Buffer", "spoolss.notify_info_data.buffer", FT_UINT32,
+ BASE_HEX, NULL, 0, "Buffer", HFILL }},
+
+ { &hf_notify_info_data_buffer_len,
+ { "Buffer length", "spoolss.notify_info_data.buffer.len",
+ FT_UINT32, BASE_HEX, NULL, 0, "Buffer length", HFILL }},
+
+ { &hf_notify_info_data_buffer_data,
+ { "Buffer data", "spoolss.notify_info_data.buffer.data",
+ FT_BYTES, BASE_HEX, NULL, 0, "Buffer data", HFILL }},
+
+ /* RffpCNex RPC */
+
+ { &hf_rffpcnex_options,
+ { "Options", "spoolss.rffpcnex.options", FT_UINT32, BASE_DEC,
+ NULL, 0, "RFFPCNEX options", HFILL }},
+
+ { &hf_printerlocal, /* XXX: move me */
+ { "Printer local", "spoolss.printer_local", FT_UINT32,
+ BASE_DEC, NULL, 0, "Printer local", HFILL }},
+
+ { &hf_rffpcnex_flags,
+ { "RFFPCNEX flags", "spoolss.rffpcnex.flags", FT_UINT32,
+ BASE_DEC, NULL, 0, "RFFPCNEX flags", HFILL }},
+
+ { &hf_rffpcnex_flags_add_printer,
+ { "Add printer", "spoolss.rffpcnex.flags.add_printer",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_printer),
+ SPOOLSS_PRINTER_CHANGE_ADD_PRINTER, "Add printer",
+ HFILL }},
+
+ { &hf_rffpcnex_flags_set_printer,
+ { "Set printer", "spoolss.rffpcnex.flags.set_printer",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_set_printer),
+ SPOOLSS_PRINTER_CHANGE_SET_PRINTER, "Set printer",
+ HFILL }},
+
+ { &hf_rffpcnex_flags_delete_printer,
+ { "Delete printer", "spoolss.rffpcnex.flags.delete_printer",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_printer),
+ SPOOLSS_PRINTER_CHANGE_DELETE_PRINTER, "Delete printer",
+ HFILL }},
+
+ { &hf_rffpcnex_flags_add_job,
+ { "Add job", "spoolss.rffpcnex.flags.add_job",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_job),
+ SPOOLSS_PRINTER_CHANGE_ADD_JOB, "Add job", HFILL }},
+
+ { &hf_rffpcnex_flags_set_job,
+ { "Set job", "spoolss.rffpcnex.flags.set_job",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_set_job),
+ SPOOLSS_PRINTER_CHANGE_SET_JOB, "Set job", HFILL }},
+
+ { &hf_rffpcnex_flags_delete_job,
+ { "Delete job", "spoolss.rffpcnex.flags.delete_job",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_job),
+ SPOOLSS_PRINTER_CHANGE_DELETE_JOB, "Delete job", HFILL }},
+
+ { &hf_rffpcnex_flags_write_job,
+ { "Write job", "spoolss.rffpcnex.flags.write_job",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_write_job),
+ SPOOLSS_PRINTER_CHANGE_WRITE_JOB, "Write job", HFILL }},
+
+ { &hf_rffpcnex_flags_add_form,
+ { "Add form", "spoolss.rffpcnex.flags.add_form",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_form),
+ SPOOLSS_PRINTER_CHANGE_ADD_FORM, "Add form", HFILL }},
+
+ { &hf_rffpcnex_flags_set_form,
+ { "Set form", "spoolss.rffpcnex.flags.set_form",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_set_form),
+ SPOOLSS_PRINTER_CHANGE_SET_FORM, "Set form", HFILL }},
+
+ { &hf_rffpcnex_flags_delete_form,
+ { "Delete form", "spoolss.rffpcnex.flags.delete_form",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_form),
+ SPOOLSS_PRINTER_CHANGE_DELETE_FORM, "Delete form",
+ HFILL }},
+
+ { &hf_rffpcnex_flags_add_port,
+ { "Add port", "spoolss.rffpcnex.flags.add_port",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_port),
+ SPOOLSS_PRINTER_CHANGE_ADD_PORT, "Add port", HFILL }},
+
+ { &hf_rffpcnex_flags_configure_port,
+ { "Configure port", "spoolss.rffpcnex.flags.configure_port",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_configure_port),
+ SPOOLSS_PRINTER_CHANGE_CONFIGURE_PORT, "Configure port",
+ HFILL }},
+
+ { &hf_rffpcnex_flags_delete_port,
+ { "Delete port", "spoolss.rffpcnex.flags.delete_port",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_port),
+ SPOOLSS_PRINTER_CHANGE_DELETE_PORT, "Delete port",
+ HFILL }},
+
+ { &hf_rffpcnex_flags_add_print_processor,
+ { "Add processor", "spoolss.rffpcnex.flags.add_processor",
+ FT_BOOLEAN, 32,
+ TFS(&tfs_rffpcnex_flags_add_print_processor),
+ SPOOLSS_PRINTER_CHANGE_ADD_PRINT_PROCESSOR,
+ "Add processor", HFILL }},
+
+ { &hf_rffpcnex_flags_delete_print_processor,
+ { "Delete processor",
+ "spoolss.rffpcnex.flags.delete_processor", FT_BOOLEAN, 32,
+ TFS(&tfs_rffpcnex_flags_delete_print_processor),
+ SPOOLSS_PRINTER_CHANGE_DELETE_PRINT_PROCESSOR,
+ "Delete processor", HFILL }},
+
+ { &hf_rffpcnex_flags_add_driver,
+ { "Add driver", "spoolss.rffpcnex.flags.add_driver",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_add_driver),
+ SPOOLSS_PRINTER_CHANGE_ADD_PRINTER_DRIVER, "Add driver",
+ HFILL }},
+
+ { &hf_rffpcnex_flags_set_driver,
+ { "Set driver", "spoolss.rffpcnex.flags.set_driver",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_set_driver),
+ SPOOLSS_PRINTER_CHANGE_SET_PRINTER_DRIVER, "Set driver",
+ HFILL }},
+
+ { &hf_rffpcnex_flags_delete_driver,
+ { "Delete driver", "spoolss.rffpcnex.flags.delete_driver",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_delete_driver),
+ SPOOLSS_PRINTER_CHANGE_DELETE_PRINTER_DRIVER,
+ "Delete driver", HFILL }},
+
+ { &hf_rffpcnex_flags_timeout,
+ { "Timeout", "spoolss.rffpcnex.flags.timeout",
+ FT_BOOLEAN, 32, TFS(&tfs_rffpcnex_flags_timeout),
+ SPOOLSS_PRINTER_CHANGE_TIMEOUT, "Timeout", HFILL }},
+
+ { &hf_rffpcnex_flags_failed_printer_connection,
+ { "Failed printer connection",
+ "spoolss.rffpcnex.flags.failed_connection_printer",
+ FT_BOOLEAN, 32,
+ TFS(&tfs_rffpcnex_flags_failed_connection_printer),
+ SPOOLSS_PRINTER_CHANGE_FAILED_CONNECTION_PRINTER,
+ "Failed printer connection", HFILL }},
+
+ /* RRPCN RPC */
+
+ { &hf_rrpcn_changelow,
+ { "Change low", "spoolss.rrpcn.changelow", FT_UINT32,
+ BASE_DEC, NULL, 0, "Change low", HFILL }},
+
+ { &hf_rrpcn_changehigh,
+ { "Change high", "spoolss.rrpcn.changehigh", FT_UINT32,
+ BASE_DEC, NULL, 0, "Change high", HFILL }},
+
+ { &hf_rrpcn_unk0,
+ { "Unknown 0", "spoolss.rrpcn.unk0", FT_UINT32, BASE_DEC,
+ NULL, 0, "Unknown 0", HFILL }},
+
+ { &hf_rrpcn_unk1,
+ { "Unknown 1", "spoolss.rrpcn.unk1", FT_UINT32, BASE_DEC,
+ NULL, 0, "Unknown 1", HFILL }},
+
+ /* ReplyOpenPrinter RPC */
+
+ { &hf_replyopenprinter_unk0,
+ { "Unknown 0", "spoolss.replyopenprinter.unk0", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 0", HFILL }},
+
+ { &hf_replyopenprinter_unk1,
+ { "Unknown 1", "spoolss.replyopenprinter.unk1", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 1", HFILL }},
+
+ /* Printer attributes */
+
+ { &hf_printer_attributes,
+ { "Attributes", "spoolss.printer_attributes", FT_UINT32,
+ BASE_HEX, NULL, 0, "Attributes", HFILL }},
+
+ { &hf_printer_attributes_queued,
+ { "Queued", "spoolss.printer_attributes.queued", FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_queued),
+ PRINTER_ATTRIBUTE_QUEUED, "Queued", HFILL }},
+
+ { &hf_printer_attributes_direct,
+ { "Direct", "spoolss.printer_attributes.direct", FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_direct),
+ PRINTER_ATTRIBUTE_DIRECT, "Direct", HFILL }},
+
+ { &hf_printer_attributes_default,
+ { "Default (9x/ME only)",
+ "spoolss.printer_attributes.default",FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_default),
+ PRINTER_ATTRIBUTE_DEFAULT, "Default", HFILL }},
+
+ { &hf_printer_attributes_shared,
+ { "Shared", "spoolss.printer_attributes.shared", FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_shared),
+ PRINTER_ATTRIBUTE_SHARED, "Shared", HFILL }},
+
+ { &hf_printer_attributes_network,
+ { "Network", "spoolss.printer_attributes.network",
+ FT_BOOLEAN, 32, TFS(&tfs_printer_attributes_network),
+ PRINTER_ATTRIBUTE_NETWORK, "Network", HFILL }},
+
+ { &hf_printer_attributes_hidden,
+ { "Hidden", "spoolss.printer_attributes.hidden", FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_hidden),
+ PRINTER_ATTRIBUTE_HIDDEN, "Hidden", HFILL }},
+
+ { &hf_printer_attributes_local,
+ { "Local", "spoolss.printer_attributes.local", FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_local),
+ PRINTER_ATTRIBUTE_LOCAL, "Local", HFILL }},
+
+ { &hf_printer_attributes_enable_devq,
+ { "Enable devq", "spoolss.printer_attributes.enable_devq",
+ FT_BOOLEAN, 32, TFS(&tfs_printer_attributes_enable_devq),
+ PRINTER_ATTRIBUTE_ENABLE_DEVQ, "Enable evq", HFILL }},
+
+ { &hf_printer_attributes_keep_printed_jobs,
+ { "Keep printed jobs",
+ "spoolss.printer_attributes.keep_printed_jobs", FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_keep_printed_jobs),
+ PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS, "Keep printed jobs",
+ HFILL }},
+
+ { &hf_printer_attributes_do_complete_first,
+ { "Do complete first",
+ "spoolss.printer_attributes.do_complete_first", FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_do_complete_first),
+ PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST, "Do complete first",
+ HFILL }},
+
+ { &hf_printer_attributes_work_offline,
+ { "Work offline (9x/ME only)",
+ "spoolss.printer_attributes.work_offline", FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_work_offline),
+ PRINTER_ATTRIBUTE_WORK_OFFLINE, "Work offline", HFILL }},
+
+ { &hf_printer_attributes_enable_bidi,
+ { "Enable bidi (9x/ME only)",
+ "spoolss.printer_attributes.enable_bidi", FT_BOOLEAN,
+ 32, TFS(&tfs_printer_attributes_enable_bidi),
+ PRINTER_ATTRIBUTE_ENABLE_BIDI, "Enable bidi", HFILL }},
+
+ { &hf_printer_attributes_raw_only,
+ { "Raw only", "spoolss.printer_attributes.raw_only",
+ FT_BOOLEAN, 32, TFS(&tfs_printer_attributes_raw_only),
+ PRINTER_ATTRIBUTE_RAW_ONLY, "Raw only", HFILL }},
+
+ { &hf_printer_attributes_published,
+ { "Published", "spoolss.printer_attributes.published",
+ FT_BOOLEAN, 32, TFS(&tfs_printer_attributes_published),
+ PRINTER_ATTRIBUTE_PUBLISHED, "Published", HFILL }},
+
+ /* Timestamps */
+
+ { &hf_time_year,
+ { "Year", "spoolss.time.year", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Year", HFILL }},
+
+ { &hf_time_month,
+ { "Month", "spoolss.time.month", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Month", HFILL }},
+
+ { &hf_time_dow,
+ { "Day of week", "spoolss.time.dow", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Day of week", HFILL }},
+
+ { &hf_time_day,
+ { "Day", "spoolss.time.day", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Day", HFILL }},
+
+ { &hf_time_hour,
+ { "Hour", "spoolss.time.hour", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Hour", HFILL }},
+
+ { &hf_time_minute,
+ { "Minute", "spoolss.time.minute", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Minute", HFILL }},
+
+ { &hf_time_second,
+ { "Second", "spoolss.time.second", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Second", HFILL }},
+
+ { &hf_time_msec,
+ { "Millisecond", "spoolss.time.msec", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Millisecond", HFILL }},
+
+ /* Userlevel */
+
+ { &hf_userlevel_size,
+ { "Size", "spoolss.userlevel.size",
+ FT_UINT32, BASE_DEC, NULL, 0, "Size", HFILL }},
+
+ { &hf_userlevel_client,
+ { "Client", "spoolss.userlevel.client", FT_STRING,
+ BASE_NONE, NULL, 0, "Client", HFILL }},
+
+ { &hf_userlevel_user,
+ { "User", "spoolss.userlevel.user", FT_STRING,
+ BASE_NONE, NULL, 0, "User", HFILL }},
+
+ { &hf_userlevel_build,
+ { "Build", "spoolss.userlevel.build",
+ FT_UINT32, BASE_DEC, NULL, 0, "Build", HFILL }},
+
+ { &hf_userlevel_major,
+ { "Major", "spoolss.userlevel.major",
+ FT_UINT32, BASE_DEC, NULL, 0, "Major", HFILL }},
+
+ { &hf_userlevel_minor,
+ { "Minor", "spoolss.userlevel.minor",
+ FT_UINT32, BASE_DEC, NULL, 0, "Minor", HFILL }},
+
+ { &hf_userlevel_processor,
+ { "Processor", "spoolss.userlevel.processor",
+ FT_UINT32, BASE_DEC, NULL, 0, "Processor", HFILL }},
+
+ /* EnumprinterdataEx RPC */
+
+ { &hf_enumprinterdataex_num_values,
+ { "Num values", "spoolss.enumprinterdataex.num_values",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of values returned", HFILL }},
+
+ { &hf_enumprinterdataex_name_offset,
+ { "Name offset", "spoolss.enumprinterdataex.name_offset",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Name offset", HFILL }},
+
+ { &hf_enumprinterdataex_name_len,
+ { "Name len", "spoolss.enumprinterdataex.name_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Name len", HFILL }},
+
+ { &hf_enumprinterdataex_name,
+ { "Name", "spoolss.enumprinterdataex.name",
+ FT_STRING, BASE_NONE, NULL, 0, "Name", HFILL }},
+
+ { &hf_enumprinterdataex_val_type,
+ { "Value type", "spoolss.enumprinterdataex.value_type",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Value type", HFILL }},
+
+ { &hf_enumprinterdataex_val_offset,
+ { "Value offset", "spoolss.enumprinterdataex.value_offset",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Value offset", HFILL }},
+
+ { &hf_enumprinterdataex_val_len,
+ { "Value len", "spoolss.enumprinterdataex.value_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Value len", HFILL }},
+
+ { &hf_enumprinterdataex_val_dword_high,
+ { "DWORD value (high)",
+ "spoolss.enumprinterdataex.val_dword.high",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "DWORD value (high)", HFILL }},
+
+ { &hf_enumprinterdataex_val_dword_low,
+ { "DWORD value (low)",
+ "spoolss.enumprinterdataex.val_dword.low",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "DWORD value (low)", HFILL }},
+
+ { &hf_enumprinterdataex_val_sz,
+ { "SZ value", "spoolss.printerdata.val_sz",
+ FT_STRING, BASE_NONE, NULL, 0, "SZ value", HFILL }},
+
+ /* RouterReplyPrinter RPC */
+
+ { &hf_routerreplyprinter_condition,
+ { "Condition", "spoolss.routerreplyprinter.condition",
+ FT_UINT32, BASE_DEC, NULL, 0, "Condition", HFILL }},
+
+ { &hf_routerreplyprinter_unknown1,
+ { "Unknown1", "spoolss.routerreplyprinter.unknown1",
+ FT_UINT32, BASE_DEC, NULL, 0, "Unknown1", HFILL }},
+
+ { &hf_routerreplyprinter_changeid,
+ { "Change id", "spoolss.routerreplyprinter.changeid",
+ FT_UINT32, BASE_DEC, NULL, 0, "Change id", HFILL }},
+
+ /* EnumPrinterKey RPC */
+
+ { &hf_keybuffer_size,
+ { "Key Buffer size", "spoolss.keybuffer.size", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Size of buffer", HFILL }},
+
+ { &hf_keybuffer_data,
+ { "Key Buffer data", "spoolss.keybuffer.data", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "Contents of buffer", HFILL }},
+
+ /* SetJob RPC */
+
+ { &hf_setjob_cmd,
+ { "Set job command", "spoolss.setjob.cmd", FT_UINT32,
+ BASE_DEC, VALS(setjob_commands), 0x0, "Printer data name",
+ HFILL }},
+
+ /* EnumJobs RPC */
+
+ { &hf_enumjobs_firstjob,
+ { "First job", "spoolss.enumjobs.firstjob", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Index of first job to return",
+ HFILL }},
+
+ { &hf_enumjobs_numjobs,
+ { "Num jobs", "spoolss.enumjobs.numjobs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of jobs to return", HFILL }},
+
+ /* Security descriptor buffer */
+
+ { &hf_secdescbuf_maxlen,
+ { "Max len", "secdescbuf.max_len",
+ FT_UINT32, BASE_DEC, NULL, 0, "Max len", HFILL }},
+
+ { &hf_secdescbuf_undoc,
+ { "Undocumented", "secdescbuf.undoc",
+ FT_UINT32, BASE_DEC, NULL, 0, "Undocumented", HFILL }},
+
+ { &hf_secdescbuf_len,
+ { "Length", "secdescbuf.len",
+ FT_UINT32, BASE_DEC, NULL, 0, "Length", HFILL }},
+
+ /* Spool printer info */
+
+ { &hf_spool_printer_info_devmode_ptr,
+ { "Devmode pointer", "spoolprinterinfo.devmode_ptr",
+ FT_UINT32, BASE_HEX, NULL, 0, "Devmode pointer", HFILL }},
+
+ { &hf_spool_printer_info_secdesc_ptr,
+ { "Secdesc pointer", "spoolprinterinfo.secdesc_ptr",
+ FT_UINT32, BASE_HEX, NULL, 0, "Secdesc pointer", HFILL }},
+
+ /* WritePrinter RPC */
+
+ { &hf_writeprinter_numwritten,
+ { "Num written", "spoolss.writeprinter.numwritten",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "Number of bytes written",
+ HFILL }},
+
+ /* Setprinterdataex RPC */
+
+ { &hf_setprinterdataex_max_len,
+ { "Max len", "setprinterdataex.max_len",
+ FT_UINT32, BASE_DEC, NULL, 0, "Max len", HFILL }},
+
+ { &hf_setprinterdataex_real_len,
+ { "Real len", "setprinterdataex.real_len",
+ FT_UINT32, BASE_DEC, NULL, 0, "Real len", HFILL }},
+
+ { &hf_setprinterdataex_data,
+ { "Data", "setprinterdataex.data",
+ FT_BYTES, BASE_HEX, NULL, 0, "Data", HFILL }},
+
+ /* Specific access rights */
+
+ { &hf_access_required,
+ { "Access required", "spoolss.access_required",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "Access required",
+ HFILL }},
+
+ { &hf_server_access_admin,
+ { "Server admin", "spoolss.access_mask.server_admin",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SERVER_ACCESS_ADMINISTER, "Server admin", HFILL }},
+
+ { &hf_server_access_enum,
+ { "Server enum", "spoolss.access_mask.server_enum",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SERVER_ACCESS_ENUMERATE, "Server enum", HFILL }},
+
+ { &hf_printer_access_admin,
+ { "Printer admin", "spoolss.access_mask.printer_admin",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ PRINTER_ACCESS_ADMINISTER, "Printer admin", HFILL }},
+
+ { &hf_printer_access_use,
+ { "Printer use", "spoolss.access_mask.printer_use",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ PRINTER_ACCESS_USE, "Printer use", HFILL }},
+
+ { &hf_job_access_admin,
+ { "Job admin", "spoolss.access_mask.job_admin",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ JOB_ACCESS_ADMINISTER, "Job admin", HFILL }},
+
+ /* Printer information */
+
+ { &hf_printer_cjobs,
+ { "CJobs", "spoolss.printer.cjobs", FT_UINT32,
+ BASE_DEC, NULL, 0, "CJobs", HFILL }},
+
+ { &hf_printer_total_jobs,
+ { "Total jobs", "spoolss.printer.total_jobs", FT_UINT32,
+ BASE_DEC, NULL, 0, "Total jobs", HFILL }},
+
+ { &hf_printer_total_bytes,
+ { "Total bytes", "spoolss.printer.total_bytes", FT_UINT32,
+ BASE_DEC, NULL, 0, "Total bytes", HFILL }},
+
+ { &hf_printer_global_counter,
+ { "Global counter", "spoolss.printer.global_counter",
+ FT_UINT32, BASE_DEC, NULL, 0, "Global counter", HFILL }},
+
+ { &hf_printer_total_pages,
+ { "Total pages", "spoolss.printer.total_pages", FT_UINT32,
+ BASE_DEC, NULL, 0, "Total pages", HFILL }},
+
+ { &hf_printer_major_version,
+ { "Major version", "spoolss.printer.major_version",
+ FT_UINT16, BASE_DEC, NULL, 0, "Major version", HFILL }},
+
+ { &hf_printer_build_version,
+ { "Build version", "spoolss.printer.build_version",
+ FT_UINT16, BASE_DEC, NULL, 0, "Build version", HFILL }},
+
+ { &hf_printer_unk7,
+ { "Unknown 7", "spoolss.printer.unknown7", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 7", HFILL }},
+
+ { &hf_printer_unk8,
+ { "Unknown 8", "spoolss.printer.unknown8", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 8", HFILL }},
+
+ { &hf_printer_unk9,
+ { "Unknown 9", "spoolss.printer.unknown9", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 9", HFILL }},
+
+ { &hf_printer_session_ctr,
+ { "Session counter", "spoolss.printer.session_ctr",
+ FT_UINT32, BASE_DEC, NULL, 0, "Sessopm counter", HFILL }},
+
+ { &hf_printer_unk11,
+ { "Unknown 11", "spoolss.printer.unknown11", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 11", HFILL }},
+
+ { &hf_printer_printer_errors,
+ { "Printer errors", "spoolss.printer.printer_errors",
+ FT_UINT32, BASE_DEC, NULL, 0, "Printer errors", HFILL }},
+
+ { &hf_printer_unk13,
+ { "Unknown 13", "spoolss.printer.unknown13", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 13", HFILL }},
+
+ { &hf_printer_unk14,
+ { "Unknown 14", "spoolss.printer.unknown14", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 14", HFILL }},
+
+ { &hf_printer_unk15,
+ { "Unknown 15", "spoolss.printer.unknown15", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 15", HFILL }},
+
+ { &hf_printer_unk16,
+ { "Unknown 16", "spoolss.printer.unknown16", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 16", HFILL }},
+
+ { &hf_printer_changeid,
+ { "Change id", "spoolss.printer.changeid", FT_UINT32,
+ BASE_DEC, NULL, 0, "Change id", HFILL }},
+
+ { &hf_printer_unk18,
+ { "Unknown 18", "spoolss.printer.unknown18", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 18", HFILL }},
+
+ { &hf_printer_unk20,
+ { "Unknown 20", "spoolss.printer.unknown20", FT_UINT32,
+ BASE_DEC, NULL, 0, "Unknown 20", HFILL }},
+
+ { &hf_printer_c_setprinter,
+ { "Csetprinter", "spoolss.printer.c_setprinter",
+ FT_UINT32, BASE_DEC, NULL, 0, "Csetprinter", HFILL }},
+
+ { &hf_printer_unk22,
+ { "Unknown 22", "spoolss.printer.unknown22",
+ FT_UINT16, BASE_DEC, NULL, 0, "Unknown 22", HFILL }},
+
+ { &hf_printer_unk23,
+ { "Unknown 23", "spoolss.printer.unknown23",
+ FT_UINT16, BASE_DEC, NULL, 0, "Unknown 23", HFILL }},
+
+ { &hf_printer_unk24,
+ { "Unknown 24", "spoolss.printer.unknown24",
+ FT_UINT16, BASE_DEC, NULL, 0, "Unknown 24", HFILL }},
+
+ { &hf_printer_unk25,
+ { "Unknown 25", "spoolss.printer.unknown25",
+ FT_UINT16, BASE_DEC, NULL, 0, "Unknown 25", HFILL }},
+
+ { &hf_printer_unk26,
+ { "Unknown 26", "spoolss.printer.unknown26",
+ FT_UINT16, BASE_DEC, NULL, 0, "Unknown 26", HFILL }},
+
+ { &hf_printer_unk27,
+ { "Unknown 27", "spoolss.printer.unknown27",
+ FT_UINT16, BASE_DEC, NULL, 0, "Unknown 27", HFILL }},
+
+ { &hf_printer_unk28,
+ { "Unknown 28", "spoolss.printer.unknown28",
+ FT_UINT16, BASE_DEC, NULL, 0, "Unknown 28", HFILL }},
+
+ { &hf_printer_unk29,
+ { "Unknown 29", "spoolss.printer.unknown29",
+ FT_UINT16, BASE_DEC, NULL, 0, "Unknown 29", HFILL }},
+
+ { &hf_printer_flags,
+ { "Flags", "spoolss.printer.flags",
+ FT_UINT32, BASE_HEX, NULL, 0, "Flags", HFILL }},
+
+ { &hf_printer_guid,
+ { "GUID", "spoolss.printer.guid", FT_STRING,
+ BASE_NONE, NULL, 0, "GUID", HFILL }},
+
+ { &hf_printer_action,
+ { "Action", "spoolss.printer.action", FT_UINT32, BASE_DEC,
+ VALS(getprinter_action_vals), 0, "Action", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_spoolss,
+ &ett_PRINTER_DATATYPE,
+ &ett_DEVMODE_CTR,
+ &ett_DEVMODE,
+ &ett_DEVMODE_fields,
+ &ett_USER_LEVEL_CTR,
+ &ett_USER_LEVEL_1,
+ &ett_BUFFER,
+ &ett_PRINTER_INFO,
+ &ett_SPOOL_PRINTER_INFO_LEVEL,
+ &ett_PRINTER_INFO_0,
+ &ett_PRINTER_INFO_1,
+ &ett_PRINTER_INFO_2,
+ &ett_PRINTER_INFO_3,
+ &ett_PRINTER_INFO_7,
+ &ett_RELSTR,
+ &ett_RELSTR_ARRAY,
+ &ett_FORM_REL,
+ &ett_FORM_CTR,
+ &ett_FORM_1,
+ &ett_JOB_INFO_1,
+ &ett_JOB_INFO_2,
+ &ett_SEC_DESC_BUF,
+ &ett_SYSTEM_TIME,
+ &ett_DOC_INFO_1,
+ &ett_DOC_INFO,
+ &ett_DOC_INFO_CTR,
+ &ett_printerdata_value,
+ &ett_printerdata_data,
+ &ett_writeprinter_buffer,
+ &ett_DRIVER_INFO_1,
+ &ett_DRIVER_INFO_3,
+ &ett_rffpcnex_flags,
+ &ett_notify_options_flags,
+ &ett_NOTIFY_INFO_DATA,
+ &ett_NOTIFY_OPTION,
+ &ett_printer_attributes,
+ &ett_job_status,
+ &ett_enumprinters_flags,
+ &ett_PRINTER_DATA_CTR,
+ &ett_printer_enumdataex_value,
+ };
+
+ proto_dcerpc_spoolss = proto_register_protocol(
+ "Microsoft Spool Subsystem", "SPOOLSS", "spoolss");
+
+ proto_register_field_array(proto_dcerpc_spoolss, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+/* Protocol handoff */
+
+static e_uuid_t uuid_dcerpc_spoolss = {
+ 0x12345678, 0x1234, 0xabcd,
+ { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
+};
+
+static guint16 ver_dcerpc_spoolss = 1;
+
+void
+proto_reg_handoff_dcerpc_spoolss(void)
+{
+
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_spoolss, ett_dcerpc_spoolss,
+ &uuid_dcerpc_spoolss, ver_dcerpc_spoolss,
+ dcerpc_spoolss_dissectors, hf_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-spoolss.h b/epan/dissectors/packet-dcerpc-spoolss.h
new file mode 100644
index 0000000000..34a718dbaa
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-spoolss.h
@@ -0,0 +1,574 @@
+/* packet-dcerpc-spoolss.h
+ * Routines for SMB \PIPE\spoolss packet disassembly
+ * Copyright 2001, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_SPOOLSS_H
+#define __PACKET_DCERPC_SPOOLSS_H
+
+/* Functions available on the SPOOLSS pipe. From Samba,
+ include/rpc_spoolss.h */
+
+#define SPOOLSS_ENUMPRINTERS 0x00
+#define SPOOLSS_OPENPRINTER 0x01
+#define SPOOLSS_SETJOB 0x02
+#define SPOOLSS_GETJOB 0x03
+#define SPOOLSS_ENUMJOBS 0x04
+#define SPOOLSS_ADDPRINTER 0x05
+#define SPOOLSS_DELETEPRINTER 0x06
+#define SPOOLSS_SETPRINTER 0x07
+#define SPOOLSS_GETPRINTER 0x08
+#define SPOOLSS_ADDPRINTERDRIVER 0x09
+#define SPOOLSS_ENUMPRINTERDRIVERS 0x0a
+#define SPOOLSS_GETPRINTERDRIVER 0x0b
+#define SPOOLSS_GETPRINTERDRIVERDIRECTORY 0x0c
+#define SPOOLSS_DELETEPRINTERDRIVER 0x0d
+#define SPOOLSS_ADDPRINTPROCESSOR 0x0e
+#define SPOOLSS_ENUMPRINTPROCESSORS 0x0f
+#define SPOOLSS_GETPRINTPROCESSORDIRECTORY 0x10
+#define SPOOLSS_STARTDOCPRINTER 0x11
+#define SPOOLSS_STARTPAGEPRINTER 0x12
+#define SPOOLSS_WRITEPRINTER 0x13
+#define SPOOLSS_ENDPAGEPRINTER 0x14
+#define SPOOLSS_ABORTPRINTER 0x15
+#define SPOOLSS_READPRINTER 0x16
+#define SPOOLSS_ENDDOCPRINTER 0x17
+#define SPOOLSS_ADDJOB 0x18
+#define SPOOLSS_SCHEDULEJOB 0x19
+#define SPOOLSS_GETPRINTERDATA 0x1a
+#define SPOOLSS_SETPRINTERDATA 0x1b
+#define SPOOLSS_WAITFORPRINTERCHANGE 0x1c
+#define SPOOLSS_CLOSEPRINTER 0x1d
+#define SPOOLSS_ADDFORM 0x1e
+#define SPOOLSS_DELETEFORM 0x1f
+#define SPOOLSS_GETFORM 0x20
+#define SPOOLSS_SETFORM 0x21
+#define SPOOLSS_ENUMFORMS 0x22
+#define SPOOLSS_ENUMPORTS 0x23
+#define SPOOLSS_ENUMMONITORS 0x24
+#define SPOOLSS_ADDPORT 0x25
+#define SPOOLSS_CONFIGUREPORT 0x26
+#define SPOOLSS_DELETEPORT 0x27
+#define SPOOLSS_CREATEPRINTERIC 0x28
+#define SPOOLSS_PLAYGDISCRIPTONPRINTERIC 0x29
+#define SPOOLSS_DELETEPRINTERIC 0x2a
+#define SPOOLSS_ADDPRINTERCONNECTION 0x2b
+#define SPOOLSS_DELETEPRINTERCONNECTION 0x2c
+#define SPOOLSS_PRINTERMESSAGEBOX 0x2d
+#define SPOOLSS_ADDMONITOR 0x2e
+#define SPOOLSS_DELETEMONITOR 0x2f
+#define SPOOLSS_DELETEPRINTPROCESSOR 0x30
+#define SPOOLSS_ADDPRINTPROVIDER 0x31
+#define SPOOLSS_DELETEPRINTPROVIDER 0x32
+#define SPOOLSS_ENUMPRINTPROCDATATYPES 0x33
+#define SPOOLSS_RESETPRINTER 0x34
+#define SPOOLSS_GETPRINTERDRIVER2 0x35
+#define SPOOLSS_FINDFIRSTPRINTERCHANGENOTIFICATION 0x36
+#define SPOOLSS_FINDNEXTPRINTERCHANGENOTIFICATION 0x37
+#define SPOOLSS_FCPN 0x38
+#define SPOOLSS_ROUTERFINDFIRSTPRINTERNOTIFICATIONOLD 0x39
+#define SPOOLSS_REPLYOPENPRINTER 0x3a
+#define SPOOLSS_ROUTERREPLYPRINTER 0x3b
+#define SPOOLSS_REPLYCLOSEPRINTER 0x3c
+#define SPOOLSS_ADDPORTEX 0x3d
+#define SPOOLSS_REMOTEFINDFIRSTPRINTERCHANGENOTIFICATION 0x3e
+#define SPOOLSS_SPOOLERINIT 0x3f
+#define SPOOLSS_RESETPRINTEREX 0x40
+#define SPOOLSS_RFFPCNEX 0x41
+#define SPOOLSS_RRPCN 0x42
+#define SPOOLSS_RFNPCNEX 0x43
+#define SPOOLSS_OPENPRINTEREX 0x45
+#define SPOOLSS_ADDPRINTEREX 0x46
+#define SPOOLSS_ENUMPRINTERDATA 0x48
+#define SPOOLSS_DELETEPRINTERDATA 0x49
+#define SPOOLSS_SETPRINTERDATAEX 0x4d
+#define SPOOLSS_GETPRINTERDATAEX 0x4e
+#define SPOOLSS_ENUMPRINTERDATAEX 0x4f
+#define SPOOLSS_ENUMPRINTERKEY 0x50
+#define SPOOLSS_DELETEPRINTERDATAEX 0x51
+#define SPOOLSS_DELETEPRINTERDRIVEREX 0x54
+#define SPOOLSS_ADDPRINTERDRIVEREX 0x59
+
+/* Form types */
+
+#define SPOOLSS_FORM_USER 0
+#define SPOOLSS_FORM_BUILTIN 1
+#define SPOOLSS_FORM_PRINTER 2
+
+/* Printer change notification flags */
+
+#define SPOOLSS_PRINTER_CHANGE_ADD_PRINTER 0x00000001
+#define SPOOLSS_PRINTER_CHANGE_SET_PRINTER 0x00000002
+#define SPOOLSS_PRINTER_CHANGE_DELETE_PRINTER 0x00000004
+#define SPOOLSS_PRINTER_CHANGE_FAILED_CONNECTION_PRINTER 0x00000008
+#define SPOOLSS_PRINTER_CHANGE_PRINTER (SPOOLSS_PRINTER_CHANGE_ADD_PRINTER | \
+ SPOOLSS_PRINTER_CHANGE_SET_PRINTER | \
+ SPOOLSS_PRINTER_CHANGE_DELETE_PRINTER | \
+ SPOOLSS_PRINTER_CHANGE_FAILED_CONNECTION_PRINTER )
+#define SPOOLSS_PRINTER_CHANGE_ADD_JOB 0x00000100
+#define SPOOLSS_PRINTER_CHANGE_SET_JOB 0x00000200
+#define SPOOLSS_PRINTER_CHANGE_DELETE_JOB 0x00000400
+#define SPOOLSS_PRINTER_CHANGE_WRITE_JOB 0x00000800
+#define SPOOLSS_PRINTER_CHANGE_JOB (SPOOLSS_PRINTER_CHANGE_ADD_JOB | \
+ SPOOLSS_PRINTER_CHANGE_SET_JOB | \
+ SPOOLSS_PRINTER_CHANGE_DELETE_JOB | \
+ SPOOLSS_PRINTER_CHANGE_WRITE_JOB )
+#define SPOOLSS_PRINTER_CHANGE_ADD_FORM 0x00010000
+#define SPOOLSS_PRINTER_CHANGE_SET_FORM 0x00020000
+#define SPOOLSS_PRINTER_CHANGE_DELETE_FORM 0x00040000
+#define SPOOLSS_PRINTER_CHANGE_FORM (SPOOLSS_PRINTER_CHANGE_ADD_FORM | \
+ SPOOLSS_PRINTER_CHANGE_SET_FORM | \
+ SPOOLSS_PRINTER_CHANGE_DELETE_FORM )
+
+#define SPOOLSS_PRINTER_CHANGE_ADD_PORT 0x00100000
+#define SPOOLSS_PRINTER_CHANGE_CONFIGURE_PORT 0x00200000
+#define SPOOLSS_PRINTER_CHANGE_DELETE_PORT 0x00400000
+#define SPOOLSS_PRINTER_CHANGE_PORT (SPOOLSS_PRINTER_CHANGE_ADD_PORT | \
+ SPOOLSS_PRINTER_CHANGE_CONFIGURE_PORT | \
+ SPOOLSS_PRINTER_CHANGE_DELETE_PORT )
+
+#define SPOOLSS_PRINTER_CHANGE_ADD_PRINT_PROCESSOR 0x01000000
+#define SPOOLSS_PRINTER_CHANGE_DELETE_PRINT_PROCESSOR 0x04000000
+#define SPOOLSS_PRINTER_CHANGE_PRINT_PROCESSOR (SPOOLSS_PRINTER_CHANGE_ADD_PRINT_PROCESSOR | \
+ SPOOLSS_PRINTER_CHANGE_DELETE_PRINT_PROCESSOR )
+
+#define SPOOLSS_PRINTER_CHANGE_ADD_PRINTER_DRIVER 0x10000000
+#define SPOOLSS_PRINTER_CHANGE_SET_PRINTER_DRIVER 0x20000000
+#define SPOOLSS_PRINTER_CHANGE_DELETE_PRINTER_DRIVER 0x40000000
+#define SPOOLSS_PRINTER_CHANGE_PRINTER_DRIVER (SPOOLSS_PRINTER_CHANGE_ADD_PRINTER_DRIVER | \
+ SPOOLSS_PRINTER_CHANGE_SET_PRINTER_DRIVER | \
+ SPOOLSS_PRINTER_CHANGE_DELETE_PRINTER_DRIVER )
+
+#define SPOOLSS_PRINTER_CHANGE_TIMEOUT 0x80000000
+#define SPOOLSS_PRINTER_CHANGE_ALL (SPOOLSS_PRINTER_CHANGE_JOB | \
+ SPOOLSS_PRINTER_CHANGE_FORM | \
+ SPOOLSS_PRINTER_CHANGE_PORT | \
+ SPOOLSS_PRINTER_CHANGE_PRINT_PROCESSOR | \
+ SPOOLSS_PRINTER_CHANGE_PRINTER_DRIVER )
+
+/* Printer notify option types */
+
+#define PRINTER_NOTIFY_TYPE 0x00
+#define JOB_NOTIFY_TYPE 0x01
+
+/* Printer notify option flags */
+
+#define PRINTER_NOTIFY_OPTIONS_REFRESH 0x01
+
+/* Printer notify options */
+
+#define PRINTER_NOTIFY_SERVER_NAME 0x00
+#define PRINTER_NOTIFY_PRINTER_NAME 0x01
+#define PRINTER_NOTIFY_SHARE_NAME 0x02
+#define PRINTER_NOTIFY_PORT_NAME 0x03
+#define PRINTER_NOTIFY_DRIVER_NAME 0x04
+#define PRINTER_NOTIFY_COMMENT 0x05
+#define PRINTER_NOTIFY_LOCATION 0x06
+#define PRINTER_NOTIFY_DEVMODE 0x07
+#define PRINTER_NOTIFY_SEPFILE 0x08
+#define PRINTER_NOTIFY_PRINT_PROCESSOR 0x09
+#define PRINTER_NOTIFY_PARAMETERS 0x0A
+#define PRINTER_NOTIFY_DATATYPE 0x0B
+#define PRINTER_NOTIFY_SECURITY_DESCRIPTOR 0x0C
+#define PRINTER_NOTIFY_ATTRIBUTES 0x0D
+#define PRINTER_NOTIFY_PRIORITY 0x0E
+#define PRINTER_NOTIFY_DEFAULT_PRIORITY 0x0F
+#define PRINTER_NOTIFY_START_TIME 0x10
+#define PRINTER_NOTIFY_UNTIL_TIME 0x11
+#define PRINTER_NOTIFY_STATUS 0x12
+#define PRINTER_NOTIFY_STATUS_STRING 0x13
+#define PRINTER_NOTIFY_CJOBS 0x14
+#define PRINTER_NOTIFY_AVERAGE_PPM 0x15
+#define PRINTER_NOTIFY_TOTAL_PAGES 0x16
+#define PRINTER_NOTIFY_PAGES_PRINTED 0x17
+#define PRINTER_NOTIFY_TOTAL_BYTES 0x18
+#define PRINTER_NOTIFY_BYTES_PRINTED 0x19
+
+/* Job notify options */
+
+#define JOB_NOTIFY_PRINTER_NAME 0x00
+#define JOB_NOTIFY_MACHINE_NAME 0x01
+#define JOB_NOTIFY_PORT_NAME 0x02
+#define JOB_NOTIFY_USER_NAME 0x03
+#define JOB_NOTIFY_NOTIFY_NAME 0x04
+#define JOB_NOTIFY_DATATYPE 0x05
+#define JOB_NOTIFY_PRINT_PROCESSOR 0x06
+#define JOB_NOTIFY_PARAMETERS 0x07
+#define JOB_NOTIFY_DRIVER_NAME 0x08
+#define JOB_NOTIFY_DEVMODE 0x09
+#define JOB_NOTIFY_STATUS 0x0A
+#define JOB_NOTIFY_STATUS_STRING 0x0B
+#define JOB_NOTIFY_SECURITY_DESCRIPTOR 0x0C
+#define JOB_NOTIFY_DOCUMENT 0x0D
+#define JOB_NOTIFY_PRIORITY 0x0E
+#define JOB_NOTIFY_POSITION 0x0F
+#define JOB_NOTIFY_SUBMITTED 0x10
+#define JOB_NOTIFY_START_TIME 0x11
+#define JOB_NOTIFY_UNTIL_TIME 0x12
+#define JOB_NOTIFY_TIME 0x13
+#define JOB_NOTIFY_TOTAL_PAGES 0x14
+#define JOB_NOTIFY_PAGES_PRINTED 0x15
+#define JOB_NOTIFY_TOTAL_BYTES 0x16
+#define JOB_NOTIFY_BYTES_PRINTED 0x17
+
+/* Printer status codes */
+
+#define PRINTER_STATUS_OK 0x00000000
+#define PRINTER_STATUS_PAUSED 0x00000001
+#define PRINTER_STATUS_ERROR 0x00000002
+#define PRINTER_STATUS_PENDING_DELETION 0x00000004
+#define PRINTER_STATUS_PAPER_JAM 0x00000008
+#define PRINTER_STATUS_PAPER_OUT 0x00000010
+#define PRINTER_STATUS_MANUAL_FEED 0x00000020
+#define PRINTER_STATUS_PAPER_PROBLEM 0x00000040
+#define PRINTER_STATUS_OFFLINE 0x00000080
+#define PRINTER_STATUS_IO_ACTIVE 0x00000100
+#define PRINTER_STATUS_BUSY 0x00000200
+#define PRINTER_STATUS_PRINTING 0x00000400
+#define PRINTER_STATUS_OUTPUT_BIN_FULL 0x00000800
+#define PRINTER_STATUS_NOT_AVAILABLE 0x00001000
+#define PRINTER_STATUS_WAITING 0x00002000
+#define PRINTER_STATUS_PROCESSING 0x00004000
+#define PRINTER_STATUS_INITIALIZING 0x00008000
+#define PRINTER_STATUS_WARMING_UP 0x00010000
+#define PRINTER_STATUS_TONER_LOW 0x00020000
+#define PRINTER_STATUS_NO_TONER 0x00040000
+#define PRINTER_STATUS_PAGE_PUNT 0x00080000
+#define PRINTER_STATUS_USER_INTERVENTION 0x00100000
+#define PRINTER_STATUS_OUT_OF_MEMORY 0x00200000
+#define PRINTER_STATUS_DOOR_OPEN 0x00400000
+#define PRINTER_STATUS_SERVER_UNKNOWN 0x00800000
+#define PRINTER_STATUS_POWER_SAVE 0x01000000
+
+/* Job status codes */
+
+#define JOB_STATUS_PAUSED 0x00000001
+#define JOB_STATUS_ERROR 0x00000002
+#define JOB_STATUS_DELETING 0x00000004
+#define JOB_STATUS_SPOOLING 0x00000008
+#define JOB_STATUS_PRINTING 0x00000010
+#define JOB_STATUS_OFFLINE 0x00000020
+#define JOB_STATUS_PAPEROUT 0x00000040
+#define JOB_STATUS_PRINTED 0x00000080
+#define JOB_STATUS_DELETED 0x00000100
+#define JOB_STATUS_BLOCKED 0x00000200
+#define JOB_STATUS_USER_INTERVENTION 0x00000400
+
+/* Printer attributes */
+
+#define PRINTER_ATTRIBUTE_QUEUED 0x00000001
+#define PRINTER_ATTRIBUTE_DIRECT 0x00000002
+#define PRINTER_ATTRIBUTE_DEFAULT 0x00000004
+#define PRINTER_ATTRIBUTE_SHARED 0x00000008
+#define PRINTER_ATTRIBUTE_NETWORK 0x00000010
+#define PRINTER_ATTRIBUTE_HIDDEN 0x00000020
+#define PRINTER_ATTRIBUTE_LOCAL 0x00000040
+#define PRINTER_ATTRIBUTE_ENABLE_DEVQ 0x00000080
+#define PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS 0x00000100
+#define PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST 0x00000200
+#define PRINTER_ATTRIBUTE_WORK_OFFLINE 0x00000400
+#define PRINTER_ATTRIBUTE_ENABLE_BIDI 0x00000800
+#define PRINTER_ATTRIBUTE_RAW_ONLY 0x00001000
+#define PRINTER_ATTRIBUTE_PUBLISHED 0x00002000
+
+/* Setprinter control commands */
+
+#define SPOOLSS_PRINTER_CONTROL_UNPAUSE 0x00000000
+#define SPOOLSS_PRINTER_CONTROL_PAUSE 0x00000001
+#define SPOOLSS_PRINTER_CONTROL_RESUME 0x00000002
+#define SPOOLSS_PRINTER_CONTROL_PURGE 0x00000003
+#define SPOOLSS_PRINTER_CONTROL_SET_STATUS 0x00000004
+
+/* Specific access rights */
+
+#define SERVER_ACCESS_ADMINISTER 0x00000001
+#define SERVER_ACCESS_ENUMERATE 0x00000002
+#define PRINTER_ACCESS_ADMINISTER 0x00000004
+#define PRINTER_ACCESS_USE 0x00000008
+#define JOB_ACCESS_ADMINISTER 0x00000010
+
+/* Enumprinters flags */
+
+#define PRINTER_ENUM_DEFAULT 0x00000001
+#define PRINTER_ENUM_LOCAL 0x00000002
+#define PRINTER_ENUM_CONNECTIONS 0x00000004
+#define PRINTER_ENUM_FAVORITE 0x00000004
+#define PRINTER_ENUM_NAME 0x00000008
+#define PRINTER_ENUM_REMOTE 0x00000010
+#define PRINTER_ENUM_SHARED 0x00000020
+#define PRINTER_ENUM_NETWORK 0x00000040
+
+/* Devicemode field flags */
+
+#define DEVMODE_ORIENTATION 0x00000001
+#define DEVMODE_PAPERSIZE 0x00000002
+#define DEVMODE_PAPERLENGTH 0x00000004
+#define DEVMODE_PAPERWIDTH 0x00000008
+#define DEVMODE_SCALE 0x00000010
+#define DEVMODE_POSITION 0x00000020
+#define DEVMODE_NUP 0x00000040
+#define DEVMODE_COPIES 0x00000100
+#define DEVMODE_DEFAULTSOURCE 0x00000200
+#define DEVMODE_PRINTQUALITY 0x00000400
+#define DEVMODE_COLOR 0x00000800
+#define DEVMODE_DUPLEX 0x00001000
+#define DEVMODE_YRESOLUTION 0x00002000
+#define DEVMODE_TTOPTION 0x00004000
+#define DEVMODE_COLLATE 0x00008000
+#define DEVMODE_FORMNAME 0x00010000
+#define DEVMODE_LOGPIXELS 0x00020000
+#define DEVMODE_BITSPERPEL 0x00040000
+#define DEVMODE_PELSWIDTH 0x00080000
+#define DEVMODE_PELSHEIGHT 0x00100000
+#define DEVMODE_DISPLAYFLAGS 0x00200000
+#define DEVMODE_DISPLAYFREQUENCY 0x00400000
+#define DEVMODE_ICMMETHOD 0x00800000
+#define DEVMODE_ICMINTENT 0x01000000
+#define DEVMODE_MEDIATYPE 0x02000000
+#define DEVMODE_DITHERTYPE 0x04000000
+#define DEVMODE_PANNINGWIDTH 0x08000000
+#define DEVMODE_PANNINGHEIGHT 0x10000000
+
+/* Devicemode paper orientation */
+
+#define DEVMODE_ORIENTATION_PORTRAIT 1
+#define DEVMODE_ORIENTATION_LANDSCAPE 2
+
+/* Devicemode paper size */
+
+#define DEVMODE_PAPERSIZE_LETTER 1
+#define DEVMODE_PAPERSIZE_LETTERSMALL 2
+#define DEVMODE_PAPERSIZE_TABLOID 3
+#define DEVMODE_PAPERSIZE_LEDGER 4
+#define DEVMODE_PAPERSIZE_LEGAL 5
+#define DEVMODE_PAPERSIZE_STATEMENT 6
+#define DEVMODE_PAPERSIZE_EXECUTIVE 7
+#define DEVMODE_PAPERSIZE_A3 8
+#define DEVMODE_PAPERSIZE_A4 9
+#define DEVMODE_PAPERSIZE_A4SMALL 10
+#define DEVMODE_PAPERSIZE_A5 11
+#define DEVMODE_PAPERSIZE_B4 12
+#define DEVMODE_PAPERSIZE_B5 13
+#define DEVMODE_PAPERSIZE_FOLIO 14
+#define DEVMODE_PAPERSIZE_QUARTO 15
+#define DEVMODE_PAPERSIZE_10X14 16
+#define DEVMODE_PAPERSIZE_11X17 17
+#define DEVMODE_PAPERSIZE_NOTE 18
+#define DEVMODE_PAPERSIZE_ENV9 19
+#define DEVMODE_PAPERSIZE_ENV10 20
+#define DEVMODE_PAPERSIZE_ENV11 21
+#define DEVMODE_PAPERSIZE_ENV12 22
+#define DEVMODE_PAPERSIZE_ENV14 23
+#define DEVMODE_PAPERSIZE_CSHEET 24
+#define DEVMODE_PAPERSIZE_DSHEET 25
+#define DEVMODE_PAPERSIZE_ESHEET 26
+#define DEVMODE_PAPERSIZE_ENVDL 27
+#define DEVMODE_PAPERSIZE_ENVC5 28
+#define DEVMODE_PAPERSIZE_ENVC3 29
+#define DEVMODE_PAPERSIZE_ENVC4 30
+#define DEVMODE_PAPERSIZE_ENVC6 31
+#define DEVMODE_PAPERSIZE_ENVC65 32
+#define DEVMODE_PAPERSIZE_ENVB4 33
+#define DEVMODE_PAPERSIZE_ENVB5 34
+#define DEVMODE_PAPERSIZE_ENVB6 35
+#define DEVMODE_PAPERSIZE_ENVITALY 36
+#define DEVMODE_PAPERSIZE_ENVMONARCH 37
+#define DEVMODE_PAPERSIZE_ENVPERSONAL 38
+#define DEVMODE_PAPERSIZE_FANFOLDUS 39
+#define DEVMODE_PAPERSIZE_FANFOLDSTDGERMAN 40
+#define DEVMODE_PAPERSIZE_FANFOLDLGLGERMAN 41
+#define DEVMODE_PAPERSIZE_ISOB4 42
+#define DEVMODE_PAPERSIZE_JAPANESEPOSTCARD 43
+#define DEVMODE_PAPERSIZE_9X11 44
+#define DEVMODE_PAPERSIZE_10X11 45
+#define DEVMODE_PAPERSIZE_15X11 46
+#define DEVMODE_PAPERSIZE_ENVINVITE 47
+#define DEVMODE_PAPERSIZE_RESERVED48 48
+#define DEVMODE_PAPERSIZE_RESERVED49 49
+#define DEVMODE_PAPERSIZE_LETTEREXTRA 50
+#define DEVMODE_PAPERSIZE_LEGALEXTRA 51
+#define DEVMODE_PAPERSIZE_TABLOIDEXTRA 52
+#define DEVMODE_PAPERSIZE_A4EXTRA 53
+#define DEVMODE_PAPERSIZE_LETTERTRANS 54
+#define DEVMODE_PAPERSIZE_A4TRANS 55
+#define DEVMODE_PAPERSIZE_LETTEREXTRATRANS 56
+#define DEVMODE_PAPERSIZE_APLUS 57
+#define DEVMODE_PAPERSIZE_BPLUS 58
+#define DEVMODE_PAPERSIZE_LETTERPLUS 59
+#define DEVMODE_PAPERSIZE_A4PLUS 60
+#define DEVMODE_PAPERSIZE_A5TRANS 61
+#define DEVMODE_PAPERSIZE_B5TRANS 62
+#define DEVMODE_PAPERSIZE_A3EXTRA 63
+#define DEVMODE_PAPERSIZE_A5EXTRA 64
+#define DEVMODE_PAPERSIZE_B5EXTRA 65
+#define DEVMODE_PAPERSIZE_A2 66
+#define DEVMODE_PAPERSIZE_A3TRANS 67
+#define DEVMODE_PAPERSIZE_A3EXTRATRANS 68
+#define DEVMODE_PAPERSIZE_DBLJAPANESEPOSTCARD 69
+#define DEVMODE_PAPERSIZE_A6 70
+#define DEVMODE_PAPERSIZE_JENVKAKU2 71
+#define DEVMODE_PAPERSIZE_JENVKAKU3 72
+#define DEVMODE_PAPERSIZE_JENVCHOU3 73
+#define DEVMODE_PAPERSIZE_JENVCHOU4 74
+#define DEVMODE_PAPERSIZE_LETTERROT 75
+#define DEVMODE_PAPERSIZE_A3ROT 76
+#define DEVMODE_PAPERSIZE_A4ROT 77
+#define DEVMODE_PAPERSIZE_A5ROT 78
+#define DEVMODE_PAPERSIZE_B4JISROT 79
+#define DEVMODE_PAPERSIZE_B5JISROT 80
+#define DEVMODE_PAPERSIZE_JAPANESEPOSTCARDROT 81
+#define DEVMODE_PAPERSIZE_DBLJAPANESEPOSTCARDROT82 82
+#define DEVMODE_PAPERSIZE_A6ROT 83
+#define DEVMODE_PAPERSIZE_JENVKAKU2ROT 84
+#define DEVMODE_PAPERSIZE_JENVKAKU3ROT 85
+#define DEVMODE_PAPERSIZE_JENVCHOU3ROT 86
+#define DEVMODE_PAPERSIZE_JENVCHOU4ROT 87
+#define DEVMODE_PAPERSIZE_B6JIS 88
+#define DEVMODE_PAPERSIZE_B6JISROT 89
+#define DEVMODE_PAPERSIZE_12X11 90
+#define DEVMODE_PAPERSIZE_JENVYOU4 91
+#define DEVMODE_PAPERSIZE_JENVYOU4ROT 92
+#define DEVMODE_PAPERSIZE_P16K 93
+#define DEVMODE_PAPERSIZE_P32K 94
+#define DEVMODE_PAPERSIZE_P32KBIG 95
+#define DEVMODE_PAPERSIZE_PENV1 96
+#define DEVMODE_PAPERSIZE_PENV2 97
+#define DEVMODE_PAPERSIZE_PENV3 98
+#define DEVMODE_PAPERSIZE_PENV4 99
+#define DEVMODE_PAPERSIZE_PENV5 100
+#define DEVMODE_PAPERSIZE_PENV6 101
+#define DEVMODE_PAPERSIZE_PENV7 102
+#define DEVMODE_PAPERSIZE_PENV8 103
+#define DEVMODE_PAPERSIZE_PENV9 104
+#define DEVMODE_PAPERSIZE_PENV10 105
+#define DEVMODE_PAPERSIZE_P16KROT 106
+#define DEVMODE_PAPERSIZE_P32KROT 107
+#define DEVMODE_PAPERSIZE_P32KBIGROT 108
+#define DEVMODE_PAPERSIZE_PENV1ROT 109
+#define DEVMODE_PAPERSIZE_PENV2ROT 110
+#define DEVMODE_PAPERSIZE_PENV3ROT 111
+#define DEVMODE_PAPERSIZE_PENV4ROT 112
+#define DEVMODE_PAPERSIZE_PENV5ROT 113
+#define DEVMODE_PAPERSIZE_PENV6ROT 114
+#define DEVMODE_PAPERSIZE_PENV7ROT 115
+#define DEVMODE_PAPERSIZE_PENV8ROT 116
+#define DEVMODE_PAPERSIZE_PENV9ROT 117
+#define DEVMODE_PAPERSIZE_PENV10ROT 118
+
+/* Devicemode paper source */
+
+#define DEVMODE_PAPERSOURCE_UPPER 1
+#define DEVMODE_PAPERSOURCE_LOWER 2
+#define DEVMODE_PAPERSOURCE_MIDDLE 3
+#define DEVMODE_PAPERSOURCE_MANUAL 4
+#define DEVMODE_PAPERSOURCE_ENV 5
+#define DEVMODE_PAPERSOURCE_ENVMANUAL 6
+#define DEVMODE_PAPERSOURCE_AUTO 7
+#define DEVMODE_PAPERSOURCE_TRACTOR 8
+#define DEVMODE_PAPERSOURCE_SMALLFMT 9
+#define DEVMODE_PAPERSOURCE_LARGEFMAT 10
+#define DEVMODE_PAPERSOURCE_LARGECAP 11
+#define DEVMODE_PAPERSOURCE_CASSETTE 12
+#define DEVMODE_PAPERSOURCE_FORMSRC 13
+
+/* Devicemode print quality */
+
+#define DEVMODE_PRINTQUALITY_HIGH -1
+#define DEVMODE_PRINTQUALITY_MEDIUM -2
+#define DEVMODE_PRINTQUALITY_LOW -3
+#define DEVMODE_PRINTQUALITY_DRAFT -4
+
+/* Colour settings */
+
+#define DEVMODE_COLOUR_MONO 1
+#define DEVMODE_COLOUR_COLOUR 2
+
+/* TrueType options */
+
+#define DEVMODE_TTOPTION_BITMAP 1
+#define DEVMODE_TTOPTION_DOWNLOAD 2
+#define DEVMODE_TTOPTION_SUBDEV 3
+#define DEVMODE_TTOPTION_DOWNLOAD_OUTLINE 4
+
+/* Collate info */
+
+#define DEVMODE_COLLATE_FALSE 0
+#define DEVMODE_COLLATE_TRUE 1
+
+/* Duplex info */
+
+#define DEVMODE_DUPLEX_SIMPLEX 1
+#define DEVMODE_DUPLEX_VERT 2
+#define DEVMODE_DUPLEX_HORIZ 3
+
+/* Displayflags */
+
+#define DEVMODE_DISPLAYFLAGS_GRAYSCALE 1
+#define DEVMODE_DISPLAYFLAGS_INTERLACED 2
+
+/* ICM method */
+
+#define DEVMODE_ICMMETHOD_NONE 1
+#define DEVMODE_ICMMETHOD_SYSTEM 2
+#define DEVMODE_ICMMETHOD_DRIVER 3
+#define DEVMODE_ICMMETHOD_DEVICE 4
+
+/* ICM intent */
+
+#define DEVMODE_ICMINTENT_SATURATE 1
+#define DEVMODE_ICMINTENT_CONTRAST 2
+#define DEVMODE_ICMINTENT_COLORIMETRIC 3
+#define DEVMODE_ICMINTENT_ABS_COLORIMETRIC 4
+
+/* Media type */
+
+#define DEVMODE_MEDIATYPE_STANDARD 1
+#define DEVMODE_MEDIATYPE_TRANSPARENCY 2
+#define DEVMODE_MEDIATYPE_GLOSSY 3
+
+/* Dither type */
+
+#define DEVMODE_DITHERTYPE_NONE 1
+#define DEVMODE_DITHERTYPE_COARSE 2
+#define DEVMODE_DITHERTYPE_LINE 3
+#define DEVMODE_DITHERTYPE_LINEART 4
+#define DEVMODE_DITHERTYPE_ERRORDIFFUSION 5
+#define DEVMODE_DITHERTYPE_RESERVED6 6
+#define DEVMODE_DITHERTYPE_RESERVED7 7
+#define DEVMODE_DITHERTYPE_GRAYSCALE 10
+
+/* Printer info level 7 */
+
+#define DS_PUBLISH 1
+#define DS_UPDATE 2
+#define DS_UNPUBLISH 3
+
+/* SetJob command values */
+
+#define JOB_CONTROL_PAUSE 1
+#define JOB_CONTROL_RESUME 2
+#define JOB_CONTROL_CANCEL 3
+#define JOB_CONTROL_RESTART 4
+#define JOB_CONTROL_DELETE 5
+
+#endif /* packet-dcerpc-spoolss.h */
diff --git a/epan/dissectors/packet-dcerpc-srvsvc.c b/epan/dissectors/packet-dcerpc-srvsvc.c
new file mode 100644
index 0000000000..d699a3be33
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-srvsvc.c
@@ -0,0 +1,7485 @@
+/* packet-dcerpc-srvsvc.c
+ * Routines for SMB \PIPE\srvsvc packet disassembly
+ * Copyright 2001-2003, Tim Potter <tpot@samba.org>
+ * Copyright 2002, Richard Sharpe <rsharpe@ns.aus.com>
+ * decode srvsvc calls where Samba knows them ...
+ * Copyright 2002, Ronnie Sahlberg
+ * rewrote entire dissector
+ *
+ * 2002, some share information levels implemented based on samba
+ * sources.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* The IDL file for this interface can be extracted by grepping for IDL */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-srvsvc.h"
+#include "packet-dcerpc-lsa.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-smb-common.h"
+#include "packet-smb-browse.h"
+#include "smb.h"
+
+static int proto_dcerpc_srvsvc = -1;
+static int hf_srvsvc_opnum = -1;
+static int hf_srvsvc_reserved = -1;
+static int hf_srvsvc_server = -1;
+static int hf_srvsvc_emulated_server = -1;
+static int hf_srvsvc_alerts = -1;
+static int hf_srvsvc_guest = -1;
+static int hf_srvsvc_transport = -1;
+static int hf_srvsvc_session = -1;
+static int hf_srvsvc_session_num_opens = -1;
+static int hf_srvsvc_session_time = -1;
+static int hf_srvsvc_session_idle_time = -1;
+static int hf_srvsvc_session_user_flags = -1;
+static int hf_srvsvc_qualifier = -1;
+static int hf_srvsvc_computer = -1;
+static int hf_srvsvc_user = -1;
+static int hf_srvsvc_path = -1;
+static int hf_srvsvc_share_passwd = -1;
+static int hf_srvsvc_share_alternate_name = -1;
+static int hf_srvsvc_file_id = -1;
+static int hf_srvsvc_perm = -1;
+static int hf_srvsvc_policy = -1;
+static int hf_srvsvc_file_num_locks = -1;
+static int hf_srvsvc_con_id = -1;
+static int hf_srvsvc_max_uses = -1;
+static int hf_srvsvc_cur_uses = -1;
+static int hf_srvsvc_con_time = -1;
+static int hf_srvsvc_con_type = -1;
+static int hf_srvsvc_con_num_opens = -1;
+static int hf_srvsvc_chrqpri = -1;
+static int hf_srvsvc_chrqnumusers = -1;
+static int hf_srvsvc_chrqnumahead = -1;
+static int hf_srvsvc_chrdev = -1;
+static int hf_srvsvc_chrdevq = -1;
+static int hf_srvsvc_chrdev_time = -1;
+static int hf_srvsvc_chrdev_status = -1;
+static int hf_srvsvc_chrdev_opcode = -1;
+static int hf_srvsvc_info_level = -1;
+static int hf_srvsvc_rc = -1;
+static int hf_srvsvc_platform_id = -1;
+static int hf_srvsvc_ver_major = -1;
+static int hf_srvsvc_ver_minor = -1;
+static int hf_srvsvc_client_type = -1;
+static int hf_srvsvc_comment = -1;
+static int hf_srvsvc_users = -1;
+static int hf_srvsvc_disc = -1;
+static int hf_srvsvc_hidden = -1;
+static int hf_srvsvc_announce = -1;
+static int hf_srvsvc_anndelta = -1;
+static int hf_srvsvc_licences = -1;
+static int hf_srvsvc_user_path = -1;
+static int hf_srvsvc_share = -1;
+static int hf_srvsvc_share_type = -1;
+static int hf_srvsvc_num_entries = -1;
+static int hf_srvsvc_total_entries = -1;
+static int hf_srvsvc_preferred_len = -1;
+static int hf_srvsvc_parm_error = -1;
+static int hf_srvsvc_enum_handle = -1;
+static int hf_srvsvc_ulist_mtime = -1;
+static int hf_srvsvc_glist_mtime = -1;
+static int hf_srvsvc_alist_mtime = -1;
+static int hf_srvsvc_security = -1;
+static int hf_srvsvc_dfs_root_flags = -1;
+static int hf_srvsvc_numadmin = -1;
+static int hf_srvsvc_lanmask = -1;
+static int hf_srvsvc_chdevs = -1;
+static int hf_srvsvc_chdevqs = -1;
+static int hf_srvsvc_chdevjobs = -1;
+static int hf_srvsvc_connections = -1;
+static int hf_srvsvc_shares = -1;
+static int hf_srvsvc_openfiles = -1;
+static int hf_srvsvc_sessopens = -1;
+static int hf_srvsvc_sessvcs = -1;
+static int hf_srvsvc_sessreqs = -1;
+static int hf_srvsvc_opensearch = -1;
+static int hf_srvsvc_activelocks = -1;
+static int hf_srvsvc_sizreqbufs = -1;
+static int hf_srvsvc_numbigbufs = -1;
+static int hf_srvsvc_numfiletasks = -1;
+static int hf_srvsvc_alertsched = -1;
+static int hf_srvsvc_erroralert = -1;
+static int hf_srvsvc_logonalert = -1;
+static int hf_srvsvc_accessalert = -1;
+static int hf_srvsvc_diskalert = -1;
+static int hf_srvsvc_netioalert = -1;
+static int hf_srvsvc_maxauditsz = -1;
+static int hf_srvsvc_srvheuristics = -1;
+static int hf_srvsvc_auditedevents = -1;
+static int hf_srvsvc_auditprofile = -1;
+static int hf_srvsvc_autopath = -1;
+static int hf_srvsvc_initworkitems = -1;
+static int hf_srvsvc_maxworkitems = -1;
+static int hf_srvsvc_rawworkitems = -1;
+static int hf_srvsvc_irpstacksize = -1;
+static int hf_srvsvc_maxrawbuflen = -1;
+static int hf_srvsvc_maxpagedmemoryusage = -1;
+static int hf_srvsvc_maxnonpagedmemoryusage = -1;
+static int hf_srvsvc_enablesoftcompat = -1;
+static int hf_srvsvc_enableforcedlogoff = -1;
+static int hf_srvsvc_timesource = -1;
+static int hf_srvsvc_acceptdownlevelapis = -1;
+static int hf_srvsvc_lmannounce = -1;
+static int hf_srvsvc_domain = -1;
+static int hf_srvsvc_maxcopyreadlen = -1;
+static int hf_srvsvc_maxcopywritelen = -1;
+static int hf_srvsvc_minkeepsearch = -1;
+static int hf_srvsvc_maxkeepsearch = -1;
+static int hf_srvsvc_minkeepcomplsearch = -1;
+static int hf_srvsvc_maxkeepcomplsearch = -1;
+static int hf_srvsvc_threadcountadd = -1;
+static int hf_srvsvc_numblockthreads = -1;
+static int hf_srvsvc_scavtimeout = -1;
+static int hf_srvsvc_minrcvqueue = -1;
+static int hf_srvsvc_minfreeworkitems = -1;
+static int hf_srvsvc_xactmemsize = -1;
+static int hf_srvsvc_threadpriority = -1;
+static int hf_srvsvc_maxmpxct = -1;
+static int hf_srvsvc_oplockbreakwait = -1;
+static int hf_srvsvc_oplockbreakresponsewait = -1;
+static int hf_srvsvc_enableoplocks = -1;
+static int hf_srvsvc_enableoplockforceclose = -1;
+static int hf_srvsvc_enablefcbopens = -1;
+static int hf_srvsvc_enableraw = -1;
+static int hf_srvsvc_enablesharednetdrives = -1;
+static int hf_srvsvc_minfreeconnections = -1;
+static int hf_srvsvc_maxfreeconnections = -1;
+static int hf_srvsvc_initsesstable = -1;
+static int hf_srvsvc_initconntable = -1;
+static int hf_srvsvc_initfiletable = -1;
+static int hf_srvsvc_initsearchtable = -1;
+static int hf_srvsvc_errortreshold = -1;
+static int hf_srvsvc_networkerrortreshold = -1;
+static int hf_srvsvc_diskspacetreshold = -1;
+static int hf_srvsvc_maxlinkdelay = -1;
+static int hf_srvsvc_minlinkthroughput = -1;
+static int hf_srvsvc_linkinfovalidtime = -1;
+static int hf_srvsvc_scavqosinfoupdatetime = -1;
+static int hf_srvsvc_maxworkitemidletime = -1;
+static int hf_srvsvc_disk_name = -1;
+static int hf_srvsvc_disk_name_len = -1;
+static int hf_srvsvc_disk_inf0_unknown = -1;
+static int hf_srvsvc_service = -1;
+static int hf_srvsvc_service_options = -1;
+static int hf_srvsvc_transport_numberofvcs = -1;
+static int hf_srvsvc_transport_name = -1;
+static int hf_srvsvc_transport_address = -1;
+static int hf_srvsvc_transport_address_len = -1;
+static int hf_srvsvc_transport_networkaddress = -1;
+static int hf_srvsvc_service_bits = -1;
+static int hf_srvsvc_service_bits_of_interest = -1;
+static int hf_srvsvc_update_immediately = -1;
+static int hf_srvsvc_path_flags = -1;
+static int hf_srvsvc_share_flags = -1;
+static int hf_srvsvc_path_type = -1;
+static int hf_srvsvc_outbuflen = -1;
+static int hf_srvsvc_prefix = -1;
+static int hf_srvsvc_hnd = -1;
+static int hf_srvsvc_server_stat_start = -1;
+static int hf_srvsvc_server_stat_fopens = -1;
+static int hf_srvsvc_server_stat_devopens = -1;
+static int hf_srvsvc_server_stat_jobsqueued = -1;
+static int hf_srvsvc_server_stat_sopens = -1;
+static int hf_srvsvc_server_stat_stimeouts = -1;
+static int hf_srvsvc_server_stat_serrorout = -1;
+static int hf_srvsvc_server_stat_pwerrors = -1;
+static int hf_srvsvc_server_stat_permerrors = -1;
+static int hf_srvsvc_server_stat_syserrors = -1;
+static int hf_srvsvc_server_stat_bytessent = -1;
+static int hf_srvsvc_server_stat_bytesrcvd = -1;
+static int hf_srvsvc_server_stat_avresponse = -1;
+static int hf_srvsvc_server_stat_reqbufneed = -1;
+static int hf_srvsvc_server_stat_bigbufneed = -1;
+static int hf_srvsvc_tod_elapsed = -1;
+static int hf_srvsvc_tod_msecs = -1;
+static int hf_srvsvc_tod_hours = -1;
+static int hf_srvsvc_tod_mins = -1;
+static int hf_srvsvc_tod_secs = -1;
+static int hf_srvsvc_tod_hunds = -1;
+static int hf_srvsvc_tod_timezone = -1;
+static int hf_srvsvc_tod_tinterval = -1;
+static int hf_srvsvc_tod_day = -1;
+static int hf_srvsvc_tod_month = -1;
+static int hf_srvsvc_tod_year = -1;
+static int hf_srvsvc_tod_weekday = -1;
+static int hf_srvsvc_path_len = -1;
+
+static gint ett_dcerpc_srvsvc = -1;
+static gint ett_srvsvc_share_info_1 = -1;
+static gint ett_srvsvc_share_info_2 = -1;
+static gint ett_srvsvc_share_info_501 = -1;
+static gint ett_srvsvc_share_info_502 = -1;
+
+
+
+/*
+ IDL [ uuid(4b324fc8-1670-01d3-1278-5a47bf6ee188),
+ IDL version(3.0),
+ IDL implicit_handle(handle_t rpc_binding)
+ IDL ] interface srvsvc
+ IDL {
+*/
+static e_uuid_t uuid_dcerpc_srvsvc = {
+ 0x4b324fc8, 0x1670, 0x01d3,
+ { 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88 }
+};
+
+static guint16 ver_dcerpc_srvsvc = 3;
+
+static int
+srvsvc_dissect_pointer_long(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ return offset;
+}
+
+static int
+srvsvc_dissect_ENUM_HANDLE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enum_handle, 0);
+ return offset;
+
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *dev;
+ * IDL } CHARDEV_INFO_0;
+ */
+static int
+srvsvc_dissect_CHARDEV_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Char Device",
+ hf_srvsvc_chrdev, 0);
+
+ return offset;
+}
+
+static int
+srvsvc_dissect_CHARDEV_INFO_0_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_INFO_0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] CHARDEV_INFO_0 *devs;
+ * IDL } CHARDEV_INFO_0_CONTAINER;
+ */
+static int
+srvsvc_dissect_CHARDEV_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_INFO_0_array, NDR_POINTER_UNIQUE,
+ "CHARDEV_INFO_0 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *dev;
+ * IDL long status;
+ * IDL [string] [unique] wchar_t *user;
+ * IDL long time;
+ * IDL } CHARDEV_INFO_1;
+ */
+static int
+srvsvc_dissect_CHARDEV_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Char Device",
+ hf_srvsvc_chrdev, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chrdev_status, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ /* XXX dont know how to decode this time field */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chrdev_time, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_CHARDEV_INFO_1_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_INFO_1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] CHARDEV_INFO_1 *devs;
+ * IDL } CHARDEV_INFO_1_CONTAINER;
+ */
+static int
+srvsvc_dissect_CHARDEV_INFO_1_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_INFO_1_array, NDR_POINTER_UNIQUE,
+ "CHARDEV_INFO_1 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] CHARDEV_INFO_0_CONTAINER *dev0;
+ * IDL [case(1)] [unique] CHARDEV_INFO_1_CONTAINER *dev1;
+ * IDL } CHARDEV_ENUM_UNION;
+ */
+static int
+srvsvc_dissect_CHARDEV_ENUM_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_INFO_0_CONTAINER,
+ NDR_POINTER_UNIQUE, "CHARDEV_INFO_0_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", CHARDEV_INFO_0 level");
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_INFO_1_CONTAINER,
+ NDR_POINTER_UNIQUE, "CHARDEV_INFO_1_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", CHARDEV_INFO_1 level");
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long Level;
+ * IDL CHARDEV_ENUM_UNION devs;
+ * IDL } CHARDEV_ENUM_STRUCT;
+ */
+static int
+srvsvc_dissect_CHARDEV_ENUM_STRUCT(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = srvsvc_dissect_CHARDEV_ENUM_UNION(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] CHARDEV_INFO_0 *dev0;
+ * IDL [case(1)] [unique] CHARDEV_INFO_1 *dev1;
+ * IDL } CHARDEV_INFO_UNION;
+ */
+static int
+srvsvc_dissect_CHARDEV_INFO_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_INFO_0,
+ NDR_POINTER_UNIQUE, "CHARDEV_INFO_0:", -1);
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_INFO_1,
+ NDR_POINTER_UNIQUE, "CHARDEV_INFO_1:", -1);
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * IDL long NetrCharDevEnum(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [out] [ref] CHARDEV_ENUM_STRUCT *devs,
+ * IDL [in] long PreferredMaximumLength,
+ * IDL [out] long num_entries,
+ * IDL [in] [out] [unique] long *ResumeHandle
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrchardevenum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_ENUM_STRUCT,
+ NDR_POINTER_REF, "CHARDEV_ENUM_STRUCT", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_preferred_len, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrchardevenum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_ENUM_STRUCT,
+ NDR_POINTER_REF, "CHARDEV_ENUM_STRUCT", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrCharDevGetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *DevName,
+ * IDL [in] long Level ,
+ * IDL [out] [ref] CHARDEV_INFO_STRUCT *dev
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrchardevgetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Char Device", hf_srvsvc_chrdev, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrchardevgetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEV_INFO_UNION,
+ NDR_POINTER_REF, "CHARDEV_INFO_UNION", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrCharDevControl(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *DevName,
+ * IDL [in] long Opcode
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrchardevcontrol_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Char Device", hf_srvsvc_chrdev, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chrdev_opcode, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrchardevcontrol_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *dev;
+ * IDL } CHARDEVQ_INFO_0;
+ */
+static int
+srvsvc_dissect_CHARDEVQ_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Char QDevice", hf_srvsvc_chrdev, 0);
+
+ return offset;
+}
+
+static int
+srvsvc_dissect_CHARDEVQ_INFO_0_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO_0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] CHARDEVQ_INFO_0 *devs;
+ * IDL } CHARDEVQ_INFO_0_CONTAINER;
+ */
+static int
+srvsvc_dissect_CHARDEVQ_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO_0_array, NDR_POINTER_UNIQUE,
+ "CHARDEVQ_INFO_0 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *dev;
+ * IDL long priority;
+ * IDL [string] [unique] wchar_t *devs;
+ * IDL long users;
+ * IDL long num_ahead;
+ * IDL } CHARDEVQ_INFO_1;
+ */
+static int
+srvsvc_dissect_CHARDEVQ_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Char Device", hf_srvsvc_chrdev, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chrqpri, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Char Devices", hf_srvsvc_chrdevq, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chrqnumusers, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chrqnumahead, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_CHARDEVQ_INFO_1_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO_1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] CHARDEVQ_INFO_1 *devs;
+ * IDL } CHARDEVQ_INFO_1_CONTAINER;
+ */
+static int
+srvsvc_dissect_CHARDEVQ_INFO_1_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO_1_array, NDR_POINTER_UNIQUE,
+ "CHARDEVQ_INFO_1 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] CHARDEVQ_INFO_0_CONTAINER *dev0;
+ * IDL [case(1)] [unique] CHARDEVQ_INFO_1_CONTAINER *dev1;
+ * IDL } CHARDEVQ_ENUM_UNION;
+ */
+static int
+srvsvc_dissect_CHARDEVQ_ENUM_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO_0_CONTAINER,
+ NDR_POINTER_UNIQUE, "CHARDEVQ_INFO_0_CONTAINER:", -1);
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO_1_CONTAINER,
+ NDR_POINTER_UNIQUE, "CHARDEVQ_INFO_1_CONTAINER:", -1);
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long Level;
+ * IDL CHARDEVQ_ENUM_UNION devs;
+ * IDL } CHARDEVQ_ENUM_STRUCT;
+ */
+static int
+srvsvc_dissect_CHARDEVQ_ENUM_STRUCT(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = srvsvc_dissect_CHARDEVQ_ENUM_UNION(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] CHARDEVQ_INFO_0 *dev0;
+ * IDL [case(1)] [unique] CHARDEVQ_INFO_1 *dev1;
+ * IDL } CHARDEVQ_INFO;
+ */
+static int
+srvsvc_dissect_CHARDEVQ_INFO(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO_0,
+ NDR_POINTER_UNIQUE, "CHARDEVQ_INFO_0:", -1);
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO_1,
+ NDR_POINTER_UNIQUE, "CHARDEVQ_INFO_1:", -1);
+ break;
+ }
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrCharDevQEnum(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [unique] wchar_t *UserName,
+ * IDL [in] [out] [ref] CHARDEVQ_ENUM_STRUCT *devs,
+ * IDL [in] long PreferredMaximumLength,
+ * IDL [out] long num_entries,
+ * IDL [in] [out] [unique] long *ResumeHandle
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrchardevqenum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_ENUM_STRUCT,
+ NDR_POINTER_REF, "CHARDEVQ_ENUM_STRUCT", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_preferred_len, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrchardevqenum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_ENUM_STRUCT,
+ NDR_POINTER_REF, "CHARDEVQ_ENUM_STRUCT", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrCharDevQGetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *QueueName,
+ * IDL [in] [string] [ref] wchar_t *UserName,
+ * IDL [in] long Level,
+ * IDL [out] [ref] CHARDEVQ_INFO *devq
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrchardevqgetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Device Queue", hf_srvsvc_chrdevq, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "User", hf_srvsvc_user, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrchardevqgetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO,
+ NDR_POINTER_REF, "CHARDEVQ_INFO:", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrCharDevQSetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *QueueName,
+ * IDL [in] long Level,
+ * IDL [in] [ref] CHARDEVQ_INFO *dev,
+ * IDL [in] [out] [unique] long *ParmError
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrchardevqsetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Device Queue", hf_srvsvc_chrdevq, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CHARDEVQ_INFO,
+ NDR_POINTER_REF, "CHARDEVQ_INFO", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "Parameter Error:", hf_srvsvc_parm_error);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrchardevqsetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "Parameter Error:", hf_srvsvc_parm_error);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrCharDevQPurge(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *QueueName
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrchardevqpurge_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Device Queue", hf_srvsvc_chrdevq, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrchardevqpurge_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrCharDevQPurge(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *QueueName
+ * IDL [in] [string] [ref] wchar_t *ComputerName
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrchardevqpurgeself_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Device Queue", hf_srvsvc_chrdevq, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer", hf_srvsvc_computer, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrchardevqpurgeself_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+ * IDL typedef struct {
+ * IDL long con_id;
+ * IDL } CONNECT_INFO_0;
+ */
+static int
+srvsvc_dissect_CONNECT_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_con_id, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_CONNECT_INFO_0_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CONNECT_INFO_0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] CONNECT_INFO_0 *cons;
+ * IDL } CONNECT_INFO_0_CONTAINER;
+ */
+static int
+srvsvc_dissect_CONNECT_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CONNECT_INFO_0_array, NDR_POINTER_UNIQUE,
+ "CONNECT_INFO_0 array:", -1);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long conid;
+ * IDL long type;
+ * IDL long num_opens;
+ * IDL long users;
+ * IDL long time;
+ * IDL [string] [unique] wchar_t *username;
+ * IDL [string] [unique] wchar_t *share;
+ * IDL } CONNECT_INFO_1;
+ */
+static int
+srvsvc_dissect_CONNECT_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_con_id, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_con_type, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_con_num_opens, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_users, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_con_time, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Share", hf_srvsvc_share, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_CONNECT_INFO_1_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CONNECT_INFO_1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] CONNECT_INFO_0 *cons;
+ * IDL } CONNECT_INFO_1_CONTAINER;
+ */
+static int
+srvsvc_dissect_CONNECT_INFO_1_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CONNECT_INFO_1_array, NDR_POINTER_UNIQUE,
+ "CONNECT_INFO_1 array:", -1);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] CONNECT_INFO_0_CONTAINER *con0;
+ * IDL [case(1)] [unique] CONNECT_INFO_1_CONTAINER *con1;
+ * IDL } CONNECT_ENUM_UNION;
+ */
+static int
+srvsvc_dissect_CONNECT_ENUM_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CONNECT_INFO_0_CONTAINER,
+ NDR_POINTER_UNIQUE, "CONNECT_INFO_0_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", CONNECT_INFO_0 level");
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CONNECT_INFO_1_CONTAINER,
+ NDR_POINTER_UNIQUE, "CONNECT_INFO_1_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", CONNECT_INFO_1 level");
+ break;
+ }
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long Level;
+ * IDL CONNECT_ENUM_UNION devs;
+ * IDL } CONNECT_ENUM_STRUCT;
+ */
+static int
+srvsvc_dissect_CONNECT_ENUM_STRUCT(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = srvsvc_dissect_CONNECT_ENUM_UNION(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrConnectionEnum(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [unique] wchar_t *Qualifier,
+ * IDL [in] [out] [ref] CONNECT_ENUM_STRUCT *con,
+ * IDL [in] long MaxLen,
+ * IDL [in] long num_connections,
+ * IDL [in] [out] [unique] long *ResumeHandle
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrconnectionenum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Qualifier", hf_srvsvc_qualifier, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CONNECT_ENUM_STRUCT,
+ NDR_POINTER_REF, "CONNECT_ENUM_STRUCT:", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_preferred_len, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrconnectionenum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_CONNECT_ENUM_STRUCT,
+ NDR_POINTER_REF, "CONNECT_ENUM_STRUCT:", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long fileid;
+ * IDL } FILE_INFO_2;
+ */
+static int
+srvsvc_dissect_FILE_INFO_2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_file_id, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_FILE_INFO_2_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_INFO_2);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] FILE_INFO_2 *files;
+ * IDL } FILE_INFO_2_CONTAINER;
+ */
+static int
+srvsvc_dissect_FILE_INFO_2_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_INFO_2_array, NDR_POINTER_UNIQUE,
+ "FILE_INFO_2 array:", -1);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long file_id;
+ * IDL long permissions;
+ * IDL long num_locks;
+ * IDL [string] [unique] wchar_t *pathname;
+ * IDL [string] [unique] wchar_t *username;
+ * IDL } FILE_INFO_3;
+ */
+static int
+srvsvc_dissect_FILE_INFO_3(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_file_id, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_perm, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_file_num_locks, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_FILE_INFO_3_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_INFO_3);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] FILE_INFO_3 *files;
+ * IDL } FILE_INFO_3_CONTAINER;
+ */
+static int
+srvsvc_dissect_FILE_INFO_3_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_INFO_3_array, NDR_POINTER_UNIQUE,
+ "CHARDEV_INFO_3 array:", -1);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(2)] [unique] FILE_INFO_2_CONTAINER *file0;
+ * IDL [case(3)] [unique] FILE_INFO_3_CONTAINER *file1;
+ * IDL } FILE_ENUM_UNION;
+ */
+static int
+srvsvc_dissect_FILE_ENUM_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_INFO_2_CONTAINER,
+ NDR_POINTER_UNIQUE, "FILE_INFO_2_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", FILE_INFO_2 level");
+ break;
+ case 3:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_INFO_3_CONTAINER,
+ NDR_POINTER_UNIQUE, "FILE_INFO_3_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", FILE_INFO_3 level");
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(2)] [unique] FILE_INFO_2 *file0;
+ * IDL [case(3)] [unique] FILE_INFO_3 *file1;
+ * IDL } FILE_INFO_UNION;
+ */
+static int
+srvsvc_dissect_FILE_INFO_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_INFO_2,
+ NDR_POINTER_UNIQUE, "FILE_INFO_2:", -1);
+ break;
+ case 3:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_INFO_3,
+ NDR_POINTER_UNIQUE, "FILE_INFO_3:", -1);
+ break;
+ }
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long Level;
+ * IDL FILE_ENUM_UNION files;
+ * IDL } FILE_ENUM_STRUCT;
+ */
+static int
+srvsvc_dissect_FILE_ENUM_STRUCT(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = srvsvc_dissect_FILE_ENUM_UNION(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrFileEnum(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [unique] wchar_t *Path,
+ * IDL [in] [string] [unique] wchar_t *UserName,
+ * IDL [in] [out] [ref] FILE_ENUM_STRUCT *file,
+ * IDL [in] long MaxLen,
+ * IDL [out] long num_entries,
+ * IDL [in] [out] [unique] long *ResumeHandle
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrfileenum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_ENUM_STRUCT,
+ NDR_POINTER_REF, "FILE_ENUM_STRUCT:", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_preferred_len, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrfileenum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_ENUM_STRUCT,
+ NDR_POINTER_REF, "FILE_ENUM_STRUCT:", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrFileGetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long fileid,
+ * IDL [in] long level,
+ * IDL [out] [ref] FILE_INFO_UNION *file
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrfilegetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_file_id, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrfilegetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_FILE_INFO_UNION,
+ NDR_POINTER_REF, "FILE_INFO_UNION:", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrFileClose(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long fileid,
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrfileclose_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_file_id, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrfileclose_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *ses;
+ * IDL } SESSION_INFO_0;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Session", hf_srvsvc_session, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SESSION_INFO_0_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SESSION_INFO_0 *ses;
+ * IDL } SESSION_INFO_0_CONTAINER;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_0_array, NDR_POINTER_UNIQUE,
+ "SESSION_INFO_0 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *ses;
+ * IDL [string] [unique] wchar_t *user;
+ * IDL long num_open;
+ * IDL long time;
+ * IDL long idle_time;
+ * IDL long user_flags
+ * IDL } SESSION_INFO_1;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Session", hf_srvsvc_session, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_num_opens, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_time, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_idle_time, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_user_flags, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SESSION_INFO_1_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SESSION_INFO_1 *ses;
+ * IDL } SESSION_INFO_1_CONTAINER;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_1_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_1_array, NDR_POINTER_UNIQUE,
+ "SESSION_INFO_1 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *ses;
+ * IDL [string] [unique] wchar_t *user;
+ * IDL long num_open;
+ * IDL long time;
+ * IDL long idle_time;
+ * IDL long user_flags
+ * IDL [string] [unique] wchar_t *clienttype;
+ * IDL } SESSION_INFO_2;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_2(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Session", hf_srvsvc_session, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_num_opens, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_time, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_idle_time, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_user_flags, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Client Type",
+ hf_srvsvc_client_type, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SESSION_INFO_2_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_2);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SESSION_INFO_2 *ses;
+ * IDL } SESSION_INFO_2_CONTAINER;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_2_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_2_array, NDR_POINTER_UNIQUE,
+ "SESSION_INFO_2 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *ses;
+ * IDL [string] [unique] wchar_t *user;
+ * IDL long time;
+ * IDL long idle_time;
+ * IDL } SESSION_INFO_10;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_10(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Session", hf_srvsvc_session, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_time, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_idle_time, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SESSION_INFO_10_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_10);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SESSION_INFO_10 *ses;
+ * IDL } SESSION_INFO_10_CONTAINER;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_10_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_10_array, NDR_POINTER_UNIQUE,
+ "SESSION_INFO_10 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *ses;
+ * IDL [string] [unique] wchar_t *user;
+ * IDL long num_open;
+ * IDL long time;
+ * IDL long idle_time;
+ * IDL long user_flags
+ * IDL [string] [unique] wchar_t *clienttype;
+ * IDL [string] [unique] wchar_t *transport;
+ * IDL } SESSION_INFO_502;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_502(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Session", hf_srvsvc_session, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_num_opens, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_time, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_idle_time, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_session_user_flags, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Client Type",
+ hf_srvsvc_client_type, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Transport", hf_srvsvc_transport, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SESSION_INFO_502_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_502);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SESSION_INFO_502 *ses;
+ * IDL } SESSION_INFO_502_CONTAINER;
+ */
+static int
+srvsvc_dissect_SESSION_INFO_502_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_502_array, NDR_POINTER_UNIQUE,
+ "SESSION_INFO_502 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] SESSION_INFO_0_CONTAINER *ses0;
+ * IDL [case(1)] [unique] SESSION_INFO_1_CONTAINER *ses1;
+ * IDL [case(2)] [unique] SESSION_INFO_2_CONTAINER *ses2;
+ * IDL [case(10)] [unique] SESSION_INFO_10_CONTAINER *ses10;
+ * IDL [case(502)] [unique] SESSION_INFO_502_CONTAINER *ses502;
+ * IDL } SESSION_ENUM_UNION;
+ */
+static int
+srvsvc_dissect_SESSION_ENUM_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_0_CONTAINER,
+ NDR_POINTER_UNIQUE, "SESSION_INFO_0_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", SESSION_INFO_0 level");
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_1_CONTAINER,
+ NDR_POINTER_UNIQUE, "SESSION_INFO_1_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", SESSION_INFO_1 level");
+ break;
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_2_CONTAINER,
+ NDR_POINTER_UNIQUE, "SESSION_INFO_2_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", SESSION_INFO_2 level");
+ break;
+ case 10:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_10_CONTAINER,
+ NDR_POINTER_UNIQUE, "SESSION_INFO_10_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", SESSION_INFO_10 level");
+ break;
+ case 502:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_INFO_502_CONTAINER,
+ NDR_POINTER_UNIQUE, "SESSION_INFO_502_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO,
+ ", SESSION_INFO_502 level");
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long Level;
+ * IDL SESSION_ENUM_UNION ses;
+ * IDL } SESSION_ENUM_STRUCT;
+ */
+static int
+srvsvc_dissect_SESSION_ENUM_STRUCT(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = srvsvc_dissect_SESSION_ENUM_UNION(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrSessionEnum(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [unique] wchar_t *ClientName,
+ * IDL [in] [string] [unique] wchar_t *UserName,
+ * IDL [in] [out] [ref] SESSION_ENUM_STRUCT *ses,
+ * IDL [in] long maxlen,
+ * IDL [out] long num_sessions,
+ * IDL [in] [out] [unique] long *resumehandle,
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrsessionenum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Computer", hf_srvsvc_computer, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User", hf_srvsvc_user, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_ENUM_STRUCT,
+ NDR_POINTER_REF, "SESSION_ENUM_STRUCT", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_preferred_len, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsessionenum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SESSION_ENUM_STRUCT,
+ NDR_POINTER_REF, "SESSION_ENUM_STRUCT", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrSessionDel(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *ClientName,
+ * IDL [in] [string] [ref] wchar_t *UserName,
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrsessiondel_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Computer", hf_srvsvc_computer, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "User", hf_srvsvc_user, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsessiondel_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *share;
+ * IDL } SHARE_INFO_0;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Share", hf_srvsvc_share, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SHARE_INFO_0_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_0 *shares;
+ * IDL } SHARE_INFO_0_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_0_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_0 array:", -1);
+
+ return offset;
+}
+
+/*
+ IDL typedef struct {
+ IDL [unique] [string] wchar_t *share;
+ IDL long type;
+ IDL [unique] [string] wchar_t *comment;
+ IDL } SHARE_INFO_1;
+*/
+static int
+srvsvc_dissect_SHARE_INFO_1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1, "Share");
+ tree = proto_item_add_subtree(item, ett_srvsvc_share_info_1);
+ }
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Share", hf_srvsvc_share, 3);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_share_type, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Comment", hf_srvsvc_comment, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SHARE_INFO_1_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_1 *shares;
+ * IDL } SHARE_INFO_1_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_1_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_1 array:", -1);
+
+ return offset;
+}
+
+/*
+ IDL typedef struct {
+ IDL [unique] [string] wchar_t *share;
+ IDL long type;
+ IDL [unique] [string] wchar_t *comment;
+ IDL long permissions;
+ IDL long max_uses;
+ IDL long current_uses;
+ IDL [unique] [string] wchar_t *path;
+ IDL [unique] [string] wchar_t *passwd;
+ IDL } SHARE_INFO_2;
+*/
+static int
+srvsvc_dissect_SHARE_INFO_2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1, "Share");
+ tree = proto_item_add_subtree(item, ett_srvsvc_share_info_2);
+ }
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Share", hf_srvsvc_share, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_share_type, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Comment", hf_srvsvc_comment, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_perm, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_max_uses, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_cur_uses, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Password",
+ hf_srvsvc_share_passwd, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SHARE_INFO_2_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_2);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_2 *shares;
+ * IDL } SHARE_INFO_2_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_2_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_2_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_2 array:", -1);
+
+ return offset;
+}
+
+/*
+ IDL typedef struct {
+ IDL [unique] [string] wchar_t *share;
+ IDL long type;
+ IDL [unique] [string] wchar_t *comment;
+ IDL long policy;
+ IDL } SHARE_INFO_501;
+*/
+static int
+srvsvc_dissect_SHARE_INFO_501(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1, "Share");
+ tree = proto_item_add_subtree(item, ett_srvsvc_share_info_501);
+ }
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Share", hf_srvsvc_share, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_share_type, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Comment", hf_srvsvc_comment, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_policy, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SHARE_INFO_501_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_501);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_501 *shares;
+ * IDL } SHARE_INFO_501_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_501_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_501_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_501 array:", -1);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL [unique] [string] wchar_t *share;
+ IDL long type;
+ IDL [unique] [string] wchar_t *comment;
+ IDL long permissions;
+ IDL long max_uses;
+ IDL long current_uses;
+ IDL [unique] [string] wchar_t *path;
+ IDL [unique] [string] wchar_t *passwd;
+ IDL long reserved;
+ IDL SECDESC [unique] *securitysecriptor; 4byte-len followed by bytestring
+ IDL } SHARE_INFO_502;
+*/
+static int
+srvsvc_dissect_SHARE_INFO_502(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1, "Share");
+ tree = proto_item_add_subtree(item, ett_srvsvc_share_info_502);
+ }
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Share", hf_srvsvc_share, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_share_type, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Comment", hf_srvsvc_comment, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_perm, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_max_uses, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_cur_uses, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Password",
+ hf_srvsvc_share_passwd, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_reserved, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR_data, NDR_POINTER_UNIQUE,
+ "LSA SECURITY DESCRIPTOR data:", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SHARE_INFO_502_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_502);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_502 *shares;
+ * IDL } SHARE_INFO_502_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_502_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_502_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_502 array:", -1);
+
+ return offset;
+}
+
+#if 0
+/*
+ IDL typedef struct {
+ IDL [unique] [string] wchar_t *comment;
+ IDL } SHARE_INFO_1004;
+*/
+static int
+srvsvc_dissect_SHARE_INFO_1004(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Comment", hf_srvsvc_comment, 0);
+
+ return offset;
+}
+
+static int
+srvsvc_dissect_SHARE_INFO_1004_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1004);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_1004 *shares;
+ * IDL } SHARE_INFO_1004_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_1004_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 count;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, &count);
+
+ if (count) {
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1004_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_1004 array:", -1);
+ }
+
+ return offset;
+}
+
+/*
+ IDL typedef struct {
+ IDL long dfs_root_flags;
+ IDL } SHARE_INFO_1005;
+*/
+static int
+srvsvc_dissect_SHARE_INFO_1005(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_dfs_root_flags, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SHARE_INFO_1005_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1005);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_1005 *shares;
+ * IDL } SHARE_INFO_1005_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_1005_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1005_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_1005 array:", -1);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL long max_uses;
+ IDL } SHARE_INFO_1006;
+*/
+static int
+srvsvc_dissect_SHARE_INFO_1006(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_max_uses, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SHARE_INFO_1006_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1006);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_1006 *shares;
+ * IDL } SHARE_INFO_1006_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_1006_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1006_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_1006 array:", -1);
+
+ return offset;
+}
+
+
+/*
+ IDL typedef struct {
+ IDL long flags;
+ IDL [unique] [string] wchar_t *alternate_directory_name;
+ IDL } SHARE_INFO_1007;
+*/
+static int
+srvsvc_dissect_SHARE_INFO_1007(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_share_flags, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Alternate Name",
+ hf_srvsvc_share_alternate_name, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SHARE_INFO_1007_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1007);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_1007 *shares;
+ * IDL } SHARE_INFO_1007_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_1007_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1007_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_1007 array:", -1);
+
+ return offset;
+}
+
+/*
+ IDL typedef struct {
+ IDL SECDESC [unique] *securitysecriptor; 4byte-len followed by bytestring
+ IDL } SHARE_INFO_1501;
+*/
+static int
+srvsvc_dissect_SHARE_INFO_1501(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR_data, NDR_POINTER_UNIQUE,
+ "LSA SECURITY DESCRIPTOR data:", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_SHARE_INFO_1501_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1501);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] SHARE_INFO_1501 *shares;
+ * IDL } SHARE_INFO_1501_CONTAINER;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_1501_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1501_array, NDR_POINTER_UNIQUE,
+ "SHARE_INFO_1501 array:", -1);
+
+ return offset;
+}
+#endif
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] SHARE_INFO_0 *share0;
+ * IDL [case(1)] [unique] SHARE_INFO_1 *share1;
+ * IDL [case(2)] [unique] SHARE_INFO_2 *share2;
+ * IDL [case(501)] [unique] SHARE_INFO_501 *share501;
+ * IDL [case(502)] [unique] SHARE_INFO_502 *share502;
+ * IDL [case(1004)] [unique] SHARE_INFO_1004 *share1004;
+ * IDL [case(1005)] [unique] SHARE_INFO_1005 *share1005;
+ * IDL [case(1006)] [unique] SHARE_INFO_1006 *share1006;
+ * IDL [case(1007)] [unique] SHARE_INFO_1007 *share1007;
+ * IDL [case(1501)] [unique] SHARE_INFO_1501 *share1501;
+ * IDL } SHARE_INFO_UNION;
+ */
+static int
+srvsvc_dissect_SHARE_INFO_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_0,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_0:", -1);
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1:", -1);
+ break;
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_2,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_2:", -1);
+ break;
+ case 501:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_501,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_501:", -1);
+ break;
+ case 502:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_502,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_502:", -1);
+ break;
+ /*
+ * These next lot do not seem to be understood by Windows of any
+ * flavor
+ */
+#if 0
+ case 1004:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1004,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1004:", -1);
+ break;
+ case 1005:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1005,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1005:", -1);
+ break;
+ case 1006:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1006,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1006:", -1);
+ break;
+ case 1007:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1007,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1007:", -1);
+ break;
+ case 1501:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1501,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1501:", -1);
+ break;
+#endif
+ }
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrShareAdd(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long Level,
+ * IDL [in] [ref] SHARE_INFO_UNION *share,
+ * IDL [in] [out] [unique] long *ParmError
+ * IDL );
+*/
+static int
+srvsvc_dissect_netrshareadd_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_UNION,
+ NDR_POINTER_REF, "SHARE_INFO_UNION:", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "Parameter Error:", hf_srvsvc_parm_error);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrshareadd_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "Parameter Error:", hf_srvsvc_parm_error);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] SHARE_INFO_0_CONTAINER *share0;
+ * IDL [case(1)] [unique] SHARE_INFO_1_CONTAINER *share1;
+ * IDL [case(2)] [unique] SHARE_INFO_2_CONTAINER *share2;
+ * IDL [case(501)] [unique] SHARE_INFO_501_CONTAINER *share501;
+ * IDL [case(502)] [unique] SHARE_INFO_502_CONTAINER *share502;
+ * IDL [case(1004)] [unique] SHARE_INFO_1004_CONTAINER *share1004;
+ * IDL [case(1005)] [unique] SHARE_INFO_1005_CONTAINER *share1005;
+ * IDL [case(1006)] [unique] SHARE_INFO_1006_CONTAINER *share1006;
+ * IDL [case(1007)] [unique] SHARE_INFO_1007_CONTAINER *share1007;
+ * IDL [case(1501)] [unique] SHARE_INFO_1501_CONTAINER *share1501;
+ * IDL } SHARE_ENUM_UNION;
+ */
+static int
+srvsvc_dissect_SHARE_ENUM_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_0_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_0_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", SHARE_INFO_0 level");
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", SHARE_INFO_1 level");
+ break;
+ case 2:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_2_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_2_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", SHARE_INFO_2 level");
+ break;
+ case 501:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_501_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_501_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", SHARE_INFO_501 level");
+ break;
+ case 502:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_502_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_502_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", SHARE_INFO_502 level");
+ break;
+#if 0
+ case 1004:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1004_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1004_CONTAINER:", -1);
+ break;
+ case 1005:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1005_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1005_CONTAINER:", -1);
+ break;
+ case 1006:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1006_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1006_CONTAINER:", -1);
+ break;
+ case 1007:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1007_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1007_CONTAINER:", -1);
+ break;
+ case 1501:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_1501_CONTAINER,
+ NDR_POINTER_UNIQUE, "SHARE_INFO_1501_CONTAINER:", -1);
+ break;
+#endif
+ }
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL SHARE_ENUM_UNION shares;
+ * IDL } SHARE_ENUM_STRUCT;
+ */
+static int
+srvsvc_dissect_SHARE_ENUM_STRUCT(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = srvsvc_dissect_SHARE_ENUM_UNION(tvb, offset, pinfo, tree, drep);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrShareEnum(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [out] level
+ * IDL [in] [out] [ref] SHARE_ENUM_STRUCT *share,
+ * IDL [in] long MaxLen,
+ * IDL [out] long Entries,
+ * IDL [in] [out] [unique] *ResumeHandle
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrshareenum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_ENUM_UNION,
+ NDR_POINTER_REF, "Shares", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_preferred_len, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+
+static int
+srvsvc_dissect_netrshareenum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_ENUM_UNION,
+ NDR_POINTER_REF, "Shares", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_total_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrShareGetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *ShareName,
+ * IDL [in] long Level,
+ * IDL [out] [ref] SHARE_INFO_UNION *share
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrsharegetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
+ "Server", hf_srvsvc_server, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_REF,
+ "Share", hf_srvsvc_share, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ return offset;
+}
+
+static int
+srvsvc_dissect_netrsharegetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_UNION,
+ NDR_POINTER_REF, "Share:", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrShareSetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *ShareName,
+ * IDL [in] long Level,
+ * IDL [in] [ref] SHARE_INFO_UNION *share
+ * IDL [in] [out] [unique] long *ParmError,
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrsharesetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Share", hf_srvsvc_share, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_INFO_UNION,
+ NDR_POINTER_REF, "Share:", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "Parameter Error:", hf_srvsvc_parm_error);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsharesetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "Parameter Error:", hf_srvsvc_parm_error);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrShareDel(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *ShareName,
+ * IDL [in] long Reserved,
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrsharedel_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Share", hf_srvsvc_share, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_reserved, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsharedel_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrShareDelSticky(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *ShareName,
+ * IDL [in] long Reserved,
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrsharedelsticky_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Share", hf_srvsvc_share, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_reserved, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsharedelsticky_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrShareCheck(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *DeviceName,
+ * IDL [out] long type
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrsharecheck_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Char Device", hf_srvsvc_chrdev, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsharecheck_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_share_type, NULL);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long platform_id;
+ * IDL [string] [unique] wchar_t *server;
+ * IDL } SERVER_INFO_100;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_100(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_platform_id, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long platform_id;
+ * IDL [string] [unique] wchar_t *server;
+ * IDL long ver_major;
+ * IDL long ver_minor;
+ * IDL long type;
+ * IDL [string] [unique] wchar_t *comment;
+ * IDL } SERVER_INFO_101;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_101(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_platform_id, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_ver_major, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_ver_minor, NULL);
+
+ offset = dissect_smb_server_type_flags(
+ tvb, offset, pinfo, tree, drep, TRUE);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Comment", hf_srvsvc_comment, 0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long platform_id;
+ * IDL [string] [unique] wchar_t *server;
+ * IDL long ver_major;
+ * IDL long ver_minor;
+ * IDL long type;
+ * IDL [string] [unique] wchar_t *comment;
+ * IDL long users;
+ * IDL long disc;
+ * IDL long hidden;
+ * IDL long announce;
+ * IDL long anndelta;
+ * IDL long licences;
+ * IDL [string] [unique] wchar_t *userpath;
+ * IDL } SERVER_INFO_102;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_102(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_platform_id, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_ver_major, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_ver_minor, NULL);
+
+ offset = dissect_smb_server_type_flags(
+ tvb, offset, pinfo, tree, drep, TRUE);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Comment", hf_srvsvc_comment, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_users, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_disc, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_hidden, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_announce, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_anndelta, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_licences, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User Path", hf_srvsvc_user_path, 0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long ulist_mtime;
+ * IDL long glist_mtime;
+ * IDL long alist_mtime;
+ * IDL [string] [unique] wchar_t *alerts;
+ * IDL long security;
+ * IDL long numadmin;
+ * IDL long lanmask;
+ * IDL [string] [unique] wchar_t *guestaccount;
+ * IDL long chdevs;
+ * IDL long chdevqs;
+ * IDL long chdevjobs;
+ * IDL long connections;
+ * IDL long shares;
+ * IDL long openfiles;
+ * IDL long sessopens;
+ * IDL long sessvcs;
+ * IDL long sessreqs;
+ * IDL long opensearch;
+ * IDL long activelocks;
+ * IDL long sizreqbufs
+ * IDL long numbigbufs
+ * IDL long numfiletasks;
+ * IDL long alertsched;
+ * IDL long erroralert;
+ * IDL long logonalert;
+ * IDL long accessalert;
+ * IDL long diskalert;
+ * IDL long netioalert;
+ * IDL long maxauditsz;
+ * IDL [string] [unique] wchar_t *srvheuristics;
+ * IDL } SERVER_INFO_402;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_402(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_ulist_mtime, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_glist_mtime, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_alist_mtime, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Alerts", hf_srvsvc_alerts, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_security, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_numadmin, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_lanmask, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Guest", hf_srvsvc_guest, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chdevs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chdevqs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chdevjobs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_connections, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_shares, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_openfiles, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessvcs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessreqs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_opensearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_activelocks, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sizreqbufs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_numbigbufs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_numfiletasks, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_alertsched, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_erroralert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_logonalert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_accessalert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_diskalert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_netioalert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxauditsz, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server Heuristics",
+ hf_srvsvc_srvheuristics, 0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long ulist_mtime;
+ * IDL long glist_mtime;
+ * IDL long alist_mtime;
+ * IDL [string] [unique] wchar_t *alerts;
+ * IDL long security;
+ * IDL long numadmin;
+ * IDL long lanmask;
+ * IDL [string] [unique] wchar_t *guestaccount;
+ * IDL long chdevs;
+ * IDL long chdevqs;
+ * IDL long chdevjobs;
+ * IDL long connections;
+ * IDL long shares;
+ * IDL long openfiles;
+ * IDL long sessopens;
+ * IDL long sessvcs;
+ * IDL long sessreqs;
+ * IDL long opensearch;
+ * IDL long activelocks;
+ * IDL long sizreqbufs
+ * IDL long numbigbufs
+ * IDL long numfiletasks;
+ * IDL long alertsched;
+ * IDL long erroralert;
+ * IDL long logonalert;
+ * IDL long accessalert;
+ * IDL long diskalert;
+ * IDL long netioalert;
+ * IDL long maxauditsz;
+ * IDL [string] [unique] wchar_t *srvheuristics;
+ * IDL long auditedevents;
+ * IDL long auditprofile;
+ * IDL [string] [unique] wchar_t *autopath;
+ * IDL } SERVER_INFO_403;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_403(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_ulist_mtime, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_glist_mtime, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_alist_mtime, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Alerts", hf_srvsvc_alerts, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_security, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_numadmin, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_lanmask, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Guest", hf_srvsvc_guest, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chdevs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chdevqs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_chdevjobs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_connections, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_shares, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_openfiles, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessvcs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessreqs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_opensearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_activelocks, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sizreqbufs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_numbigbufs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_numfiletasks, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_alertsched, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_erroralert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_logonalert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_accessalert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_diskalert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_netioalert, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxauditsz, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server Heuristics",
+ hf_srvsvc_srvheuristics, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_auditedevents, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_auditprofile, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Autopath", hf_srvsvc_autopath, 0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long sessopens;
+ * IDL long sessvcs;
+ * IDL long opensearch;
+ * IDL long sizreqbufs
+ * IDL long initworkitems;
+ * IDL long maxworkitems;
+ * IDL long rawworkitems;
+ * IDL long irpstacksize;
+ * IDL long maxrawbuflen;
+ * IDL long sessusers;
+ * IDL long sessconns;
+ * IDL long maxpagedmemoryusage;
+ * IDL long maxnonpagedmemoryusage;
+ * IDL long enablesoftcompat;
+ * IDL long enableforcedlogoff;
+ * IDL long timesource
+ * IDL long acceptdownlevelapis;
+ * IDL long lmannounce;
+ * IDL } SERVER_INFO_502;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_502(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessvcs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_opensearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sizreqbufs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rawworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_irpstacksize, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxrawbuflen, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_users, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_connections, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxpagedmemoryusage, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxnonpagedmemoryusage, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablesoftcompat, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableforcedlogoff, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_timesource, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_acceptdownlevelapis, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_lmannounce, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long sessopens;
+ * IDL long sessvcs;
+ * IDL long opensearch;
+ * IDL long sizreqbufs
+ * IDL long initworkitems;
+ * IDL long maxworkitems;
+ * IDL long rawworkitems;
+ * IDL long irpstacksize;
+ * IDL long maxrawbuflen;
+ * IDL long sessusers;
+ * IDL long sessconns;
+ * IDL long maxpagedmemoryusage;
+ * IDL long maxnonpagedmemoryusage;
+ * IDL long enablesoftcompat;
+ * IDL long enableforcedlogoff;
+ * IDL long timesource
+ * IDL long acceptdownlevelapis;
+ * IDL long lmannounce;
+ * IDL [string] [unique] wchar_t *domain;
+ * IDL long maxcopyreadlen;
+ * IDL long maxcopywritelen;
+ * IDL long minkeepsearch;
+ * IDL long mankeepsearch;
+ * IDL long minkeepcomplsearch;
+ * IDL long mankeepcomplsearch;
+ * IDL long threadcountadd;
+ * IDL long numblockthreads;
+ * IDL long scavtimeout;
+ * IDL long minrcvqueue;
+ * IDL long minfreeworkitems;
+ * IDL long xactmemsize;
+ * IDL long threadpriority;
+ * IDL long maxmpxct;
+ * IDL long oplockbreakwait;
+ * IDL long oplockbreakresponsewait;
+ * IDL long enableoplocks;
+ * IDL long enableoplockforceclose
+ * IDL long enablefcbopens;
+ * IDL long enableraw;
+ * IDL long enablesharednetdrives;
+ * IDL long minfreeconnections;
+ * IDL long maxfreeconnections;
+ * IDL } SERVER_INFO_503;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_503(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessvcs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_opensearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sizreqbufs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rawworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_irpstacksize, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxrawbuflen, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_users, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_connections, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxpagedmemoryusage, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxnonpagedmemoryusage, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablesoftcompat, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableforcedlogoff, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_timesource, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_acceptdownlevelapis, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_lmannounce, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_srvsvc_domain, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxcopyreadlen, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxcopywritelen, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minkeepsearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxkeepsearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minkeepcomplsearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxkeepcomplsearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_threadcountadd, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_numblockthreads, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_scavtimeout, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minrcvqueue, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minfreeworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_xactmemsize, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_threadpriority, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxmpxct, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_oplockbreakwait, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_oplockbreakresponsewait, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableoplocks, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableoplockforceclose, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablefcbopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableraw, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablesharednetdrives, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minfreeconnections, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxfreeconnections, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long sessopens;
+ * IDL long sessvcs;
+ * IDL long opensearch;
+ * IDL long sizreqbufs
+ * IDL long initworkitems;
+ * IDL long maxworkitems;
+ * IDL long rawworkitems;
+ * IDL long irpstacksize;
+ * IDL long maxrawbuflen;
+ * IDL long sessusers;
+ * IDL long sessconns;
+ * IDL long maxpagedmemoryusage;
+ * IDL long maxnonpagedmemoryusage;
+ * IDL long enablesoftcompat;
+ * IDL long enableforcedlogoff;
+ * IDL long timesource
+ * IDL long acceptdownlevelapis;
+ * IDL long lmannounce;
+ * IDL [string] [unique] wchar_t *domain;
+ * IDL long maxcopyreadlen;
+ * IDL long maxcopywritelen;
+ * IDL long minkeepsearch;
+ * IDL long mankeepsearch;
+ * IDL long minkeepcomplsearch;
+ * IDL long mankeepcomplsearch;
+ * IDL long threadcountadd;
+ * IDL long numblockthreads;
+ * IDL long scavtimeout;
+ * IDL long minrcvqueue;
+ * IDL long minfreeworkitems;
+ * IDL long xactmemsize;
+ * IDL long threadpriority;
+ * IDL long maxmpxct;
+ * IDL long oplockbreakwait;
+ * IDL long oplockbreakresponsewait;
+ * IDL long enableoplocks;
+ * IDL long enableoplockforceclose
+ * IDL long enablefcbopens;
+ * IDL long enableraw;
+ * IDL long enablesharednetdrives;
+ * IDL long minfreeconnections;
+ * IDL long maxfreeconnections;
+ * IDL long initsesstable;
+ * IDL long initconntable;
+ * IDL long initfiletable;
+ * IDL long initsearchtable;
+ * IDL long alertsched;
+ * IDL long errortreshold;
+ * IDL long networkerrortreshold;
+ * IDL long diskspacetreshold;
+ * IDL long reserved;
+ * IDL long maxlinkdelay;
+ * IDL long minlinkthroughput;
+ * IDL long linkinfovalidtime;
+ * IDL long scavqosinfoupdatetime;
+ * IDL long maxworkitemidletime;
+ * IDL } SERVER_INFO_599;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_599(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessvcs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_opensearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sizreqbufs, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rawworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_irpstacksize, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxrawbuflen, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_users, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_connections, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxpagedmemoryusage, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxnonpagedmemoryusage, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablesoftcompat, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableforcedlogoff, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_timesource, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_acceptdownlevelapis, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_lmannounce, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_srvsvc_domain, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxcopyreadlen, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxcopywritelen, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minkeepsearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxkeepsearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minkeepcomplsearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxkeepcomplsearch, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_threadcountadd, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_numblockthreads, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_scavtimeout, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minrcvqueue, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minfreeworkitems, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_xactmemsize, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_threadpriority, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxmpxct, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_oplockbreakwait, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_oplockbreakresponsewait, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableoplocks, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableoplockforceclose, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablefcbopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableraw, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablesharednetdrives, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minfreeconnections, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxfreeconnections, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initsesstable, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initconntable, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initfiletable, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initsearchtable, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_alertsched, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_errortreshold, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_networkerrortreshold, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_diskspacetreshold, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_reserved, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_reserved, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxlinkdelay, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minlinkthroughput, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_linkinfovalidtime, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_scavqosinfoupdatetime, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxworkitemidletime, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *comment;
+ * IDL } SERVER_INFO_1005;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1005(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Comment", hf_srvsvc_comment, 0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long disc;
+ * IDL } SERVER_INFO_1010;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1010(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_disc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long hidden;
+ * IDL } SERVER_INFO_1016;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1016(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_hidden, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long announce;
+ * IDL } SERVER_INFO_1017;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1017(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_announce, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long anndelta;
+ * IDL } SERVER_INFO_1018;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1018(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_anndelta, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long users;
+ * IDL } SERVER_INFO_1107;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1107(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_users, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long sessopens;
+ * IDL } SERVER_INFO_1501;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1501(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessopens, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long sessvcs;
+ * IDL } SERVER_INFO_1502;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1502(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_sessvcs, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long opensearch;
+ * IDL } SERVER_INFO_1503;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1503(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_opensearch, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxworkitems;
+ * IDL } SERVER_INFO_1506;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1506(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxworkitems, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxrawbuflen;
+ * IDL } SERVER_INFO_1509;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1509(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxrawbuflen, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long sessusers;
+ * IDL } SERVER_INFO_1510;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1510(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_users, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long sessconns;
+ * IDL } SERVER_INFO_1511;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1511(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_connections, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxnonpagedmemoryusage;
+ * IDL } SERVER_INFO_1512;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1512(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxnonpagedmemoryusage, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxpagedmemoryusage;
+ * IDL } SERVER_INFO_1513;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1513(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxpagedmemoryusage, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long enablesoftcompat;
+ * IDL } SERVER_INFO_1514;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1514(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablesoftcompat, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long enableforcedlogoff;
+ * IDL } SERVER_INFO_1515;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1515(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableforcedlogoff, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long timesource;
+ * IDL } SERVER_INFO_1516;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1516(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_timesource, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long lmannounce;
+ * IDL } SERVER_INFO_1518;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1518(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_lmannounce, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxcopyreadlen;
+ * IDL } SERVER_INFO_1520;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1520(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxcopyreadlen, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxcopywritelen;
+ * IDL } SERVER_INFO_1521;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1521(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxcopywritelen, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long minkeepsearch;
+ * IDL } SERVER_INFO_1522;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1522(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minkeepsearch, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxkeepsearch;
+ * IDL } SERVER_INFO_1523;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1523(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxkeepsearch, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long minkeepcomplsearch;
+ * IDL } SERVER_INFO_1524;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1524(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minkeepcomplsearch, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxkeepcomplsearch;
+ * IDL } SERVER_INFO_1525;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1525(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxkeepcomplsearch, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long scavtimeout;
+ * IDL } SERVER_INFO_1528;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1528(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_scavtimeout, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long minrcvqueue;
+ * IDL } SERVER_INFO_1529;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1529(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minrcvqueue, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long minfreeworkitems;
+ * IDL } SERVER_INFO_1530;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1530(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minfreeworkitems, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxmpxct;
+ * IDL } SERVER_INFO_1533;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1533(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxmpxct, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long oplockbreakwait;
+ * IDL } SERVER_INFO_1534;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1534(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_oplockbreakwait, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long oplockbreakresponsewait;
+ * IDL } SERVER_INFO_1535;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1535(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_oplockbreakresponsewait, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long enableoplocks;
+ * IDL } SERVER_INFO_1536;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1536(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableoplocks, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long enableoplockforceclose;
+ * IDL } SERVER_INFO_1537;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1537(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableoplockforceclose, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long enablefcbopens;
+ * IDL } SERVER_INFO_1538;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1538(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablefcbopens, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long enableraw;
+ * IDL } SERVER_INFO_1539;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1539(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enableraw, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long enablesharednetdrives;
+ * IDL } SERVER_INFO_1540;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1540(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_enablesharednetdrives, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long minfreeconnections;
+ * IDL } SERVER_INFO_1541;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1541(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minfreeconnections, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxfreeconnections;
+ * IDL } SERVER_INFO_1542;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1542(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxfreeconnections, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long initsesstable;
+ * IDL } SERVER_INFO_1543;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1543(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initsesstable, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long initconntable;
+ * IDL } SERVER_INFO_1544;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1544(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initconntable, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long initfiletable;
+ * IDL } SERVER_INFO_1545;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1545(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initfiletable, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long initsearchtable;
+ * IDL } SERVER_INFO_1546;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1546(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_initsearchtable, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long alertsched;
+ * IDL } SERVER_INFO_1547;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1547(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_alertsched, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long errortreshold;
+ * IDL } SERVER_INFO_1548;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1548(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_errortreshold, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long networkerrortreshold;
+ * IDL } SERVER_INFO_1549;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1549(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_networkerrortreshold, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long diskspacetreshold;
+ * IDL } SERVER_INFO_1550;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1550(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_diskspacetreshold, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxlinkdelay;
+ * IDL } SERVER_INFO_1552;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1552(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxlinkdelay, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long minlinkthroughput;
+ * IDL } SERVER_INFO_1553;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1553(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_minlinkthroughput, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long linkinfovalidtime;
+ * IDL } SERVER_INFO_1554;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1554(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_linkinfovalidtime, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long scavqosinfoupdatetime;
+ * IDL } SERVER_INFO_1555;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1555(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_scavqosinfoupdatetime, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long maxworkitemidletime;
+ * IDL } SERVER_INFO_1556;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_1556(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_maxworkitemidletime, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(100)] [unique] SERVER_INFO_100 *srv100;
+ * IDL [case(101)] [unique] SERVER_INFO_101 *srv101;
+ * IDL [case(102)] [unique] SERVER_INFO_102 *srv102;
+ * IDL [case(402)] [unique] SERVER_INFO_402 *srv402;
+ * IDL [case(403)] [unique] SERVER_INFO_403 *srv403;
+ * IDL [case(502)] [unique] SERVER_INFO_502 *srv502;
+ * IDL [case(503)] [unique] SERVER_INFO_503 *srv503;
+ * IDL [case(599)] [unique] SERVER_INFO_599 *srv599;
+ * IDL [case(1005)] [unique] SERVER_INFO_1005 *srv1005;
+ * IDL [case(1010)] [unique] SERVER_INFO_1010 *srv1010;
+ * IDL [case(1016)] [unique] SERVER_INFO_1016 *srv1016;
+ * IDL [case(1017)] [unique] SERVER_INFO_1017 *srv1017;
+ * IDL [case(1018)] [unique] SERVER_INFO_1018 *srv1018;
+ * IDL [case(1107)] [unique] SERVER_INFO_1107 *srv1107;
+ * IDL [case(1501)] [unique] SERVER_INFO_1501 *srv1501;
+ * IDL [case(1502)] [unique] SERVER_INFO_1502 *srv1502;
+ * IDL [case(1503)] [unique] SERVER_INFO_1503 *srv1503;
+ * IDL [case(1506)] [unique] SERVER_INFO_1506 *srv1506;
+ * IDL [case(1509)] [unique] SERVER_INFO_1509 *srv1509;
+ * IDL [case(1510)] [unique] SERVER_INFO_1510 *srv1510;
+ * IDL [case(1511)] [unique] SERVER_INFO_1511 *srv1511;
+ * IDL [case(1512)] [unique] SERVER_INFO_1512 *srv1512;
+ * IDL [case(1513)] [unique] SERVER_INFO_1513 *srv1513;
+ * IDL [case(1514)] [unique] SERVER_INFO_1514 *srv1514;
+ * IDL [case(1515)] [unique] SERVER_INFO_1515 *srv1515;
+ * IDL [case(1516)] [unique] SERVER_INFO_1516 *srv1516;
+ * IDL [case(1518)] [unique] SERVER_INFO_1518 *srv1518;
+ * IDL [case(1520)] [unique] SERVER_INFO_1520 *srv1520;
+ * IDL [case(1521)] [unique] SERVER_INFO_1521 *srv1521;
+ * IDL [case(1522)] [unique] SERVER_INFO_1522 *srv1522;
+ * IDL [case(1523)] [unique] SERVER_INFO_1523 *srv1523;
+ * IDL [case(1524)] [unique] SERVER_INFO_1524 *srv1524;
+ * IDL [case(1525)] [unique] SERVER_INFO_1525 *srv1525;
+ * IDL [case(1528)] [unique] SERVER_INFO_1528 *srv1528;
+ * IDL [case(1529)] [unique] SERVER_INFO_1529 *srv1529;
+ * IDL [case(1530)] [unique] SERVER_INFO_1530 *srv1530;
+ * IDL [case(1533)] [unique] SERVER_INFO_1533 *srv1533;
+ * IDL [case(1534)] [unique] SERVER_INFO_1534 *srv1534;
+ * IDL [case(1535)] [unique] SERVER_INFO_1535 *srv1535;
+ * IDL [case(1536)] [unique] SERVER_INFO_1536 *srv1536;
+ * IDL [case(1537)] [unique] SERVER_INFO_1537 *srv1537;
+ * IDL [case(1538)] [unique] SERVER_INFO_1538 *srv1538;
+ * IDL [case(1539)] [unique] SERVER_INFO_1539 *srv1539;
+ * IDL [case(1540)] [unique] SERVER_INFO_1540 *srv1540;
+ * IDL [case(1541)] [unique] SERVER_INFO_1541 *srv1541;
+ * IDL [case(1542)] [unique] SERVER_INFO_1542 *srv1542;
+ * IDL [case(1543)] [unique] SERVER_INFO_1543 *srv1543;
+ * IDL [case(1544)] [unique] SERVER_INFO_1544 *srv1544;
+ * IDL [case(1545)] [unique] SERVER_INFO_1545 *srv1545;
+ * IDL [case(1546)] [unique] SERVER_INFO_1546 *srv1546;
+ * IDL [case(1547)] [unique] SERVER_INFO_1547 *srv1547;
+ * IDL [case(1548)] [unique] SERVER_INFO_1548 *srv1548;
+ * IDL [case(1549)] [unique] SERVER_INFO_1549 *srv1549;
+ * IDL [case(1550)] [unique] SERVER_INFO_1550 *srv1550;
+ * IDL [case(1552)] [unique] SERVER_INFO_1552 *srv1552;
+ * IDL [case(1553)] [unique] SERVER_INFO_1553 *srv1553;
+ * IDL [case(1554)] [unique] SERVER_INFO_1554 *srv1554;
+ * IDL [case(1555)] [unique] SERVER_INFO_1555 *srv1555;
+ * IDL [case(1556)] [unique] SERVER_INFO_1556 *srv1556;
+ * IDL } SERVER_INFO_UNION;
+ */
+static int
+srvsvc_dissect_SERVER_INFO_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 100:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_100,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_100:", -1);
+ break;
+
+ case 101:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_101,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_101:", -1);
+ break;
+
+ case 102:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_102,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_102:", -1);
+ break;
+
+ case 402:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_402,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_402:", -1);
+ break;
+
+ case 403:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_403,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_403:", -1);
+ break;
+
+ case 502:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_502,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_502:", -1);
+ break;
+
+ case 503:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_503,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_503:", -1);
+ break;
+
+ case 599:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_599,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_599:", -1);
+ break;
+
+ case 1005:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1005,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1005:", -1);
+ break;
+
+ case 1010:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1010,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1010:", -1);
+ break;
+
+ case 1016:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1016,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1016:", -1);
+ break;
+
+ case 1017:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1017,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1017:", -1);
+ break;
+
+ case 1018:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1018,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1018:", -1);
+ break;
+
+ case 1107:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1107,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1107:", -1);
+ break;
+
+ case 1501:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1501,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1501:", -1);
+ break;
+
+ case 1502:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1502,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1502:", -1);
+ break;
+
+ case 1503:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1503,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1503:", -1);
+ break;
+
+ case 1506:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1506,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1506:", -1);
+ break;
+
+ case 1509:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1509,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1509:", -1);
+ break;
+
+ case 1510:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1510,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1510:", -1);
+ break;
+
+ case 1511:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1511,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1511:", -1);
+ break;
+
+ case 1512:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1512,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1512:", -1);
+ break;
+
+ case 1513:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1513,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1513:", -1);
+ break;
+
+ case 1514:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1514,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1514:", -1);
+ break;
+
+ case 1515:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1515,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1515:", -1);
+ break;
+
+ case 1516:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1516,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1516:", -1);
+ break;
+
+ case 1518:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1518,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1518:", -1);
+ break;
+
+ case 1520:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1520,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1520:", -1);
+ break;
+
+ case 1521:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1521,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1521:", -1);
+ break;
+
+ case 1522:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1522,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1522:", -1);
+ break;
+
+ case 1523:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1523,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1523:", -1);
+ break;
+
+ case 1524:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1524,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1524:", -1);
+ break;
+
+ case 1525:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1525,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1525:", -1);
+ break;
+
+ case 1528:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1528,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1528:", -1);
+ break;
+
+ case 1529:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1529,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1529:", -1);
+ break;
+
+ case 1530:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1530,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1530:", -1);
+ break;
+
+ case 1533:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1533,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1533:", -1);
+ break;
+
+ case 1534:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1534,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1534:", -1);
+ break;
+
+ case 1535:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1535,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1535:", -1);
+ break;
+
+ case 1536:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1536,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1536:", -1);
+ break;
+
+ case 1537:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1537,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1537:", -1);
+ break;
+
+ case 1538:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1538,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1538:", -1);
+ break;
+
+ case 1539:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1539,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1539:", -1);
+ break;
+
+ case 1540:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1540,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1540:", -1);
+ break;
+
+ case 1541:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1541,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1541:", -1);
+ break;
+
+ case 1542:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1542,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1542:", -1);
+ break;
+
+ case 1543:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1543,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1543:", -1);
+ break;
+
+ case 1544:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1544,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1544:", -1);
+ break;
+
+ case 1545:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1545,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1545:", -1);
+ break;
+
+ case 1546:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1546,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1546:", -1);
+ break;
+
+ case 1547:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1547,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1547:", -1);
+ break;
+
+ case 1548:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1548,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1548:", -1);
+ break;
+
+ case 1549:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1549,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1549:", -1);
+ break;
+
+ case 1550:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1550,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1550:", -1);
+ break;
+
+ case 1552:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1552,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1552:", -1);
+ break;
+
+ case 1553:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1553,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1553:", -1);
+ break;
+
+ case 1554:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1554,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1554:", -1);
+ break;
+
+ case 1555:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1555,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1555:", -1);
+ break;
+
+ case 1556:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_1556,
+ NDR_POINTER_UNIQUE, "SERVER_INFO_1556:", -1);
+ break;
+
+ }
+
+ return offset;
+}
+
+/*
+ * IDL long NetrServerGetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long Level,
+ * IDL [out] [ref] SERVER_INFO_UNION *srv;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrservergetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
+ "Server", hf_srvsvc_server, cb_wstr_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrservergetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_UNION,
+ NDR_POINTER_REF, "Server Info", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrServerSetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long Level,
+ * IDL [in] [ref] SERVER_INFO_UNION *srv;
+ * IDL [in] [out] [unique] long *ParamError;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrserversetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_INFO_UNION,
+ NDR_POINTER_REF, "Server Info", -1);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "Parameter Error:", hf_srvsvc_parm_error);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrserversetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "Parameter Error:", hf_srvsvc_parm_error);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL [size_is()] [unique] wchar_t *disk;
+ * IDL } DISK_INFO_0;
+ */
+static int
+srvsvc_dissect_DISK_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* this call is to make ethereal eat the array header for the conformant run */
+ offset =dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, NULL);
+
+ return offset;
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_disk_inf0_unknown, &len);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_disk_name_len, &len);
+
+ offset = dissect_ndr_uint16s(
+ tvb, offset, pinfo, tree, drep, hf_srvsvc_disk_name, len);
+
+ return offset;
+}
+static int
+srvsvc_dissect_DISK_INFO_0_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_DISK_INFO_0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [length_is(EntriesRead)] [size_is(EntriesRead)] [unique] DISK_INFO_0 *disk;
+ * IDL } DISK_ENUM_CONTAINER;
+ */
+static int
+srvsvc_dissect_DISK_ENUM_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_DISK_INFO_0_array, NDR_POINTER_UNIQUE,
+ "DISK_INFO_0 array:", -1);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrServerDiskEnum(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long Level,
+ * IDL [in] [out] [ref] DISK_ENUM_CONTAINER *disk;
+ * IDL [in] long maxlen,
+ * IDL [out] long entries,
+ * IDL [in] [out] [unique] long *resumehandle,
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrserverdiskenum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_DISK_ENUM_CONTAINER,
+ NDR_POINTER_REF, "Disks", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_preferred_len, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrserverdiskenum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_DISK_ENUM_CONTAINER,
+ NDR_POINTER_REF, "Disks", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long start;
+ * IDL long fopens;
+ * IDL long devopens;
+ * IDL long jobsqueued;
+ * IDL long sopens;
+ * IDL long stimeouts;
+ * IDL long serrorout;
+ * IDL long pwerrors;
+ * IDL long permerrors;
+ * IDL long syserrors;
+ * IDL long bytessent_low;
+ * IDL long bytessent_high;
+ * IDL long bytesrcvd_low;
+ * IDL long bytesrcvd_high;
+ * IDL long avresponse;
+ * IDL long reqbufneed;
+ * IDL long bigbufneed;
+ * IDL } SERVER_STAT;
+ */
+
+static int
+srvsvc_dissect_SERVER_STAT(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_start, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_fopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_devopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_jobsqueued, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_sopens, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_stimeouts, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_serrorout, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_pwerrors, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_permerrors, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_syserrors, NULL);
+
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_bytessent, NULL);
+
+ offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_bytesrcvd, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_avresponse, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_reqbufneed, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_server_stat_bigbufneed, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrServerStatisticsGet(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [unique] wchar_t *Service,
+ * IDL [in] long Level,
+ * IDL [in] long Options,
+ * IDL [out] [ref] SERVER_STAT *stat
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrserverstatisticsget_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Service", hf_srvsvc_service, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_service_options, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrserverstatisticsget_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_STAT,
+ NDR_POINTER_REF, "Stat", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [size_is(transportaddresslen)] char transportaddress;
+ * IDL } TRANSPORT_ADDRESS;
+ */
+static int
+srvsvc_dissect_TRANSPORT_ADDRESS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+ guint32 len;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /*just a run to handle conformant arrays, nothing to dissect */
+ return offset;
+ }
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_transport_address_len, &len);
+
+ proto_tree_add_item(tree, hf_srvsvc_transport_address, tvb, offset,
+ len, FALSE);
+ offset += len;
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long numberofvcs;
+ * IDL [string] [unique] transportname;
+ * IDL [unique] TRANSPORT_ADDRESS *transportaddress;
+ * IDL long transportaddresslen;
+ * IDL [string] [unique] wchar_t *networkaddress;
+ * IDL } TRANSPORT_INFO_0;
+ */
+static int
+srvsvc_dissect_TRANSPORT_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_transport_numberofvcs, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Name",
+ hf_srvsvc_transport_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_TRANSPORT_ADDRESS,
+ NDR_POINTER_UNIQUE, "Transport Address", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_transport_address_len, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Network Address",
+ hf_srvsvc_transport_networkaddress, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_TRANSPORT_INFO_0_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_TRANSPORT_INFO_0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] TRANSPORT_INFO_0 *trans;
+ * IDL } SERVER_XPORT_INFO_0_CONTAINER;
+ */
+static int
+srvsvc_dissect_SERVER_XPORT_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_TRANSPORT_INFO_0_array, NDR_POINTER_UNIQUE,
+ "TRANSPORT_INFO_0 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long numberofvcs;
+ * IDL [string] [unique] transportname;
+ * IDL [unique] TRANSPORT_ADDRESS *transportaddress;
+ * IDL long transportaddresslen;
+ * IDL [string] [unique] wchar_t *networkaddress;
+ * IDL } TRANSPORT_INFO_1;
+ */
+static int
+srvsvc_dissect_TRANSPORT_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_transport_numberofvcs, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Name",
+ hf_srvsvc_transport_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_TRANSPORT_ADDRESS,
+ NDR_POINTER_UNIQUE, "Transport Address", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_transport_address_len, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Network Address",
+ hf_srvsvc_transport_networkaddress, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Domain", hf_srvsvc_domain, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_TRANSPORT_INFO_1_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_TRANSPORT_INFO_1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] TRANSPORT_INFO_1 *trans;
+ * IDL } SERVER_XPORT_INFO_1_CONTAINER;
+ */
+static int
+srvsvc_dissect_SERVER_XPORT_INFO_1_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_TRANSPORT_INFO_1_array, NDR_POINTER_UNIQUE,
+ "TRANSPORT_INFO_1 array:", -1);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] SERVER_XPORT_INFO_0_CONTAINER *xp0;
+ * IDL [case(1)] [unique] SERVER_XPORT_INFO_1_CONTAINER *xp1;
+ * IDL } SERVER_XPORT_ENUM_UNION;
+ */
+static int
+srvsvc_dissect_SERVER_XPORT_ENUM_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_srvsvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_XPORT_INFO_0_CONTAINER,
+ NDR_POINTER_UNIQUE, "SERVER_XPORT_INFO_0_CONTAINER:",
+ -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", TRANSPORT_INFO_0 level");
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_XPORT_INFO_1_CONTAINER,
+ NDR_POINTER_UNIQUE, "SERVER_XPORT_INFO_1_CONTAINER:",
+ -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", TRANSPORT_INFO_1 level");
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long Level;
+ * IDL SERVER_XPORT_ENUM_UNION xport;
+ * IDL } SERVER_XPORT_ENUM_STRUCT;
+ */
+static int
+srvsvc_dissect_SERVER_XPORT_ENUM_STRUCT(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = srvsvc_dissect_SERVER_XPORT_ENUM_UNION(tvb, offset,
+ pinfo, tree, drep);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrServerTransportAdd(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long Level,
+ * IDL [in] [ref] TRANSPORT_INFO_0 *trans;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrservertransportadd_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_TRANSPORT_INFO_0,
+ NDR_POINTER_REF, "Transports", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrservertransportadd_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrServerTransportEnum(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [out] [ref] SERVER_XPORT_ENUM_STRUCT *xport;
+ * IDL [in] long MaxLen,
+ * IDL [out] long entries,
+ * IDL [in] [out] [unique] long *resumehandle;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrservertransportenum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_XPORT_ENUM_STRUCT,
+ NDR_POINTER_REF, "Transports", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_preferred_len, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrservertransportenum_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_XPORT_ENUM_STRUCT,
+ NDR_POINTER_REF, "Transports", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrServerTransportDel(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long Level,
+ * IDL [in] [ref] TRANSPORT_INFO_0 *trans;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrservertransportdel_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_TRANSPORT_INFO_0,
+ NDR_POINTER_REF, "Transports", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrservertransportdel_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long elapsed;
+ * IDL long msecs;
+ * IDL long hours;
+ * IDL long mins;
+ * IDL long secs;
+ * IDL long hunds;
+ * IDL long timezone;
+ * IDL long tinterval;
+ * IDL long day;
+ * IDL long month;
+ * IDL long year;
+ * IDL long weekday;
+ * IDL } TIMEOFDAY;
+ */
+static int
+srvsvc_dissect_TIMEOFDAY(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /*
+ * XXX - is "hf_srvsvc_tod_elapsed" something that should be
+ * processed by "add_abstime_absent_unknown()" from
+ * "packet-smb-pipe.c"? This structure looks similar
+ * to the result of a NetRemoteTOD RAP call, and that has
+ * a "current time" field that's processed by
+ * "add_abstime_absent_unknown()".
+ *
+ * Should other fields, such as the time zone offset and
+ * the time interval, be processed as they are for
+ * "lm_data_resp_netremotetod_nolevel" as well?
+ */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_elapsed, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_msecs, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_hours, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_mins, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_secs, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_hunds, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_timezone, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_tinterval, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_day, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_month, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_year, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_tod_weekday, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrRemoteTOD(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [out] [unique] TIMEOFDAY *t
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrremotetod_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrremotetod_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_TIMEOFDAY,
+ NDR_POINTER_UNIQUE, "Time of day", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrSetServerServiceBits(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [unique] wchar_t *Transport,
+ * IDL [in] long ServiceBits;
+ * IDL [in] long UpdateImmediately;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrsetserverservicebits_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Transport", hf_srvsvc_transport, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_service_bits, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_update_immediately, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsetserverservicebits_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrPathType(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *PathName,
+ * IDL [in] long PathFlags;
+ * IDL [out] long PathType;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrpathtype_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_flags, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrpathtype_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_type, NULL);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrPathCanonicalize(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *PathName,
+ * IDL [in] long OutBufLen;
+ * IDL [in] [string] [ref] wchar_t *Prefix,
+ * IDL [in] [out] [ref] long *PathType;
+ * IDL [in] long PathFlags;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrpathcanonicalize_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_outbuflen, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Prefix", hf_srvsvc_prefix, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_type, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_flags, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrpathcanonicalize_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* this call is to make ethereal eat the array header for the conformant run */
+ offset =dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, NULL);
+
+ return offset;
+ }
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_len, &len);
+
+ offset = dissect_ndr_uint16s(
+ tvb, offset, pinfo, tree, drep, hf_srvsvc_path, len);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_type, NULL);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrPathCompare(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *PathName1,
+ * IDL [in] [string] [ref] wchar_t *PathName2,
+ * IDL [in] long PathType;
+ * IDL [in] long PathFlags;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrpathcompare_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path 1", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path 2", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_type, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_flags, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrpathcompare_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrNameValidate(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *PathName,
+ * IDL [in] long PathType;
+ * IDL [in] long PathFlags;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrnamevalidate_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_type, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_flags, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrnamevalidate_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrNameCanonicalize(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *PathName,
+ * IDL [in] long OutBufLen,
+ * IDL [in] long PathType,
+ * IDL [in] long PathFlags,
+ * IDL [out] [ref] *PathName
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrnamecanonicalize_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_outbuflen, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_type, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_flags, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrnamecanonicalize_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 len;
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* this call is to make ethereal eat the array header for the conformant run */
+ offset =dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep, NULL);
+
+ return offset;
+ }
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_len, &len);
+
+ offset = dissect_ndr_uint16s(
+ tvb, offset, pinfo, tree, drep, hf_srvsvc_path, len);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrNameCompare(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *PathName1,
+ * IDL [in] [string] [ref] wchar_t *PathName2,
+ * IDL [in] long PathType;
+ * IDL [in] long PathFlags;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrnamecompare_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path 1", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path 2", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_type, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_path_flags, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrnamecompare_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrShareEnumSticky(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [out] level
+ * IDL [in] [out] [ref] SHARE_ENUM_STRUCT *share,
+ * IDL [in] long MaxLen,
+ * IDL [out] long Entries,
+ * IDL [in] [out] [unique] *ResumeHandle
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrshareenumsticky_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_ENUM_STRUCT,
+ NDR_POINTER_REF, "Shares", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_preferred_len, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrshareenumsticky_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SHARE_ENUM_STRUCT,
+ NDR_POINTER_REF, "Shares", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrShareDelStart(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [ref] wchar_t *Share,
+ * IDL [in] long reserved,
+ * IDL [out] [context_handle] hnd
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrsharedelstart_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Share", hf_srvsvc_share, 0);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_reserved, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsharedelstart_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_hnd, NULL, NULL, TRUE, FALSE);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrShareDelCommit(
+ * IDL [in] [out] [contect_handle] h
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrsharedelcommit_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_hnd, NULL, NULL, TRUE, FALSE);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsharedelcommit_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_hnd, NULL, NULL, TRUE, FALSE);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/* XXX dont know the out parameters. only the in parameters.
+ *
+ * IDL long NetrGetFileSecurity(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [unique] wchar_t *Share,
+ * IDL [in] [string] [ref] wchar_t *File,
+ * IDL [in] long requetedinformation
+ * IDL [out] [ref] SECDESC *securitysecriptor; 4byte-len followed by bytestring
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrgetfilesecurity_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Share", hf_srvsvc_share, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrgetfilesecurity_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR_data, NDR_POINTER_REF,
+ "LSA SECURITY DESCRIPTOR data:", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrSetFileSecurity(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [unique] wchar_t *Share,
+ * IDL [in] [string] [ref] wchar_t *File,
+ * IDL [in] long sequrityinformation
+ * IDL SECDESC [ref] *securitysecriptor; 4byte-len followed by bytestring
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrsetfilesecurity_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Share", hf_srvsvc_share, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "Path", hf_srvsvc_path, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ lsa_dissect_LSA_SECURITY_DESCRIPTOR_data, NDR_POINTER_REF,
+ "LSA SECURITY DESCRIPTOR data:", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrsetfilesecurity_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrServerTransportAddEx(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long Level
+ * IDL [in] [ref] SERVER_XPORT_ENUM_STRUCT *sxes;
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrservertransportaddex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ srvsvc_dissect_SERVER_XPORT_ENUM_STRUCT,
+ NDR_POINTER_REF, "Transports", -1);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrservertransportaddex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrServerSetServiceBitsEx(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] [string] [unique] wchar_t *EmulatedServerName,
+ * IDL [in] [string] [unique] wchar_t *Transport,
+ * IDL [in] long servicebitsofinterest
+ * IDL [in] long servicebits
+ * IDL [in] long updateimmediately
+ * IDL );
+ */
+static int
+srvsvc_dissect_netrserversetservicebitsex_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_srvsvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Emulated Server",
+ hf_srvsvc_emulated_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Transport", hf_srvsvc_transport, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_service_bits_of_interest, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_service_bits, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_update_immediately, NULL);
+
+ return offset;
+}
+static int
+srvsvc_dissect_netrserversetservicebitsex_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_srvsvc_rc, NULL);
+
+ return offset;
+}
+
+
+
+
+/*
+ IDL }
+*/
+static dcerpc_sub_dissector dcerpc_srvsvc_dissectors[] = {
+ {SRV_NETRCHARDEVENUM, "NetrCharDevEnum",
+ srvsvc_dissect_netrchardevenum_rqst,
+ srvsvc_dissect_netrchardevenum_reply},
+ {SRV_NETRCHARDEVGETINFO, "NetrCharDevGetInfo",
+ srvsvc_dissect_netrchardevgetinfo_rqst,
+ srvsvc_dissect_netrchardevgetinfo_reply},
+ {SRV_NETRCHARDEVCONTROL, "NetrCharDevControl",
+ srvsvc_dissect_netrchardevcontrol_rqst,
+ srvsvc_dissect_netrchardevcontrol_reply},
+ {SRV_NETRCHARDEVQENUM, "NetrCharDevQEnum",
+ srvsvc_dissect_netrchardevqenum_rqst,
+ srvsvc_dissect_netrchardevqenum_reply},
+ {SRV_NETRCHARDEVQGETINFO, "NetrCharDevQGetInfo",
+ srvsvc_dissect_netrchardevqgetinfo_rqst,
+ srvsvc_dissect_netrchardevqgetinfo_reply},
+ {SRV_NETRCHARDEVQSETINFO, "NetrCharDevQSetInfo",
+ srvsvc_dissect_netrchardevqsetinfo_rqst,
+ srvsvc_dissect_netrchardevqsetinfo_reply},
+ {SRV_NETRCHARDEVQPURGE, "NetrCharDevQPurge",
+ srvsvc_dissect_netrchardevqpurge_rqst,
+ srvsvc_dissect_netrchardevqpurge_reply},
+ {SRV_NETRCHARDEVQPURGESELF, "NetrCharDevQPurgeSelf",
+ srvsvc_dissect_netrchardevqpurgeself_rqst,
+ srvsvc_dissect_netrchardevqpurgeself_reply},
+ {SRV_NETRCONNECTIONENUM, "NetrConnectionEnum",
+ srvsvc_dissect_netrconnectionenum_rqst,
+ srvsvc_dissect_netrconnectionenum_reply},
+ {SRV_NETRFILEENUM, "NetrFileEnum",
+ srvsvc_dissect_netrfileenum_rqst,
+ srvsvc_dissect_netrfileenum_reply},
+ {SRV_NETRFILEGETINFO, "NetrFileGetInfo",
+ srvsvc_dissect_netrfilegetinfo_rqst,
+ srvsvc_dissect_netrfilegetinfo_reply},
+ {SRV_NETRFILECLOSE, "NetrFileClose",
+ srvsvc_dissect_netrfileclose_rqst,
+ srvsvc_dissect_netrfileclose_reply},
+ {SRV_NETRSESSIONENUM, "NetrSessionEnum",
+ srvsvc_dissect_netrsessionenum_rqst,
+ srvsvc_dissect_netrsessionenum_reply},
+ {SRV_NETRSESSIONDEL, "NetrSessionDel",
+ srvsvc_dissect_netrsessiondel_rqst,
+ srvsvc_dissect_netrsessiondel_reply},
+ {SRV_NETRSHAREADD, "NetrShareAdd",
+ srvsvc_dissect_netrshareadd_rqst,
+ srvsvc_dissect_netrshareadd_reply},
+ {SRV_NETRSHAREENUM, "NetrShareEnum",
+ srvsvc_dissect_netrshareenum_rqst,
+ srvsvc_dissect_netrshareenum_reply},
+ {SRV_NETRSHAREGETINFO, "NetrShareGetInfo",
+ srvsvc_dissect_netrsharegetinfo_rqst,
+ srvsvc_dissect_netrsharegetinfo_reply},
+ {SRV_NETRSHARESETINFO, "NetrShareSetInfo",
+ srvsvc_dissect_netrsharesetinfo_rqst,
+ srvsvc_dissect_netrsharesetinfo_reply},
+ {SRV_NETRSHAREDEL, "NetrShareDel",
+ srvsvc_dissect_netrsharedel_rqst,
+ srvsvc_dissect_netrsharedel_reply},
+ {SRV_NETRSHAREDELSTICKY, "NetrShareDelSticky",
+ srvsvc_dissect_netrsharedelsticky_rqst,
+ srvsvc_dissect_netrsharedelsticky_reply},
+ {SRV_NETRSHARECHECK, "NetrShareCheck",
+ srvsvc_dissect_netrsharecheck_rqst,
+ srvsvc_dissect_netrsharecheck_reply},
+ {SRV_NETRSERVERGETINFO, "NetrServerGetInfo",
+ srvsvc_dissect_netrservergetinfo_rqst,
+ srvsvc_dissect_netrservergetinfo_reply},
+ {SRV_NETRSERVERSETINFO, "NetrServerSetInfo",
+ srvsvc_dissect_netrserversetinfo_rqst,
+ srvsvc_dissect_netrserversetinfo_reply},
+ {SRV_NETRSERVERDISKENUM, "NetrServerDiskEnum",
+ srvsvc_dissect_netrserverdiskenum_rqst,
+ srvsvc_dissect_netrserverdiskenum_reply},
+ {SRV_NETRSERVERSTATISTICSGET, "NetrServerStatisticsGet",
+ srvsvc_dissect_netrserverstatisticsget_rqst,
+ srvsvc_dissect_netrserverstatisticsget_reply},
+ {SRV_NETRSERVERTRANSPORTADD, "NetrServerTransportAdd",
+ srvsvc_dissect_netrservertransportadd_rqst,
+ srvsvc_dissect_netrservertransportadd_reply},
+ {SRV_NETRSERVERTRANSPORTENUM, "NetrServerTransportEnum",
+ srvsvc_dissect_netrservertransportenum_rqst,
+ srvsvc_dissect_netrservertransportenum_reply},
+ {SRV_NETRSERVERTRANSPORTDEL, "NetrServerTransportDel",
+ srvsvc_dissect_netrservertransportdel_rqst,
+ srvsvc_dissect_netrservertransportdel_reply},
+ {SRV_NETRREMOTETOD, "NetrRemoteTOD",
+ srvsvc_dissect_netrremotetod_rqst,
+ srvsvc_dissect_netrremotetod_reply},
+ {SRV_NETRSERVERSETSERVICEBITS, "NetrServerSetServiceBits",
+ srvsvc_dissect_netrsetserverservicebits_rqst,
+ srvsvc_dissect_netrsetserverservicebits_reply},
+ {SRV_NETRPRPATHTYPE, "NetrpPathType",
+ srvsvc_dissect_netrpathtype_rqst,
+ srvsvc_dissect_netrpathtype_reply},
+ {SRV_NETRPRPATHCANONICALIZE, "NetrpPathCanonicalize",
+ srvsvc_dissect_netrpathcanonicalize_rqst,
+ srvsvc_dissect_netrpathcanonicalize_reply},
+ {SRV_NETRPRPATHCOMPARE, "NetrpPathCompare",
+ srvsvc_dissect_netrpathcompare_rqst,
+ srvsvc_dissect_netrpathcompare_reply},
+ {SRV_NETRPRNAMEVALIDATE, "NetrpNameValidate",
+ srvsvc_dissect_netrnamevalidate_rqst,
+ srvsvc_dissect_netrnamevalidate_reply},
+ {SRV_NETRPRNAMECANONICALIZE, "NetrpNameCanonicalize",
+ srvsvc_dissect_netrnamecanonicalize_rqst,
+ srvsvc_dissect_netrnamecanonicalize_reply},
+ {SRV_NETRPRNAMECOMPARE, "NetrpNameCompare",
+ srvsvc_dissect_netrnamecompare_rqst,
+ srvsvc_dissect_netrnamecompare_reply},
+ {SRV_NETRSHAREENUMSTICKY, "NetrShareEnumSticky",
+ srvsvc_dissect_netrshareenumsticky_rqst,
+ srvsvc_dissect_netrshareenumsticky_reply},
+ {SRV_NETRSHAREDELSTART, "NetrShareDelStart",
+ srvsvc_dissect_netrsharedelstart_rqst,
+ srvsvc_dissect_netrsharedelstart_reply},
+ {SRV_NETRSHAREDELCOMMIT, "NetrShareDelCommit",
+ srvsvc_dissect_netrsharedelcommit_rqst,
+ srvsvc_dissect_netrsharedelcommit_reply},
+ {SRV_NETRPGETFILESECURITY, "NetrpGetFileSecurity",
+ srvsvc_dissect_netrgetfilesecurity_rqst,
+ srvsvc_dissect_netrgetfilesecurity_reply},
+ {SRV_NETRPSETFILESECURITY, "NetrpSetFileSecurity",
+ srvsvc_dissect_netrsetfilesecurity_rqst,
+ srvsvc_dissect_netrsetfilesecurity_reply},
+ {SRV_NETRSERVERTRANSPORTADDEX, "NetrServerTransportAddEx",
+ srvsvc_dissect_netrservertransportaddex_rqst,
+ srvsvc_dissect_netrservertransportaddex_reply},
+ {SRV_NETRSERVERSETSERVICEBITSEX,"NetrServerSetServiceBitsEx",
+ srvsvc_dissect_netrserversetservicebitsex_rqst,
+ srvsvc_dissect_netrserversetservicebitsex_reply},
+ { SRV_NETRDFSGETVERSION, "NetrDfsGetVersion",
+ NULL, NULL },
+ { SRV_NETRDFSCREATELOCALPARTITION, "NetrDfsCreateLocalPartition",
+ NULL, NULL },
+ { SRV_NETRDFSDELETELOCALPARTITION, "NetrDfsDeleteLocalPartition",
+ NULL, NULL },
+ { SRV_NETRDFSSETLOCALVOLUMESTATE, "NetrDfsSetLocalVolumeState",
+ NULL, NULL },
+ { SRV_NETRDFSSETSERVERINFO, "NetrDfsSetServerInfo",
+ NULL, NULL },
+ { SRV_NETRDFSCREATEEXITPOINT, "NetrDfsCreateExitPoint",
+ NULL, NULL },
+ { SRV_NETRDFSDELETEEXITPOINT, "NetrDfsDeleteExitPoint",
+ NULL, NULL },
+ { SRV_NETRDFSMODIFYPREFIX, "NetrDfsModifyPrefix",
+ NULL, NULL },
+ { SRV_NETRDFSFIXLOCALVOLUME, "NetrDfsFixLocalVolume",
+ NULL, NULL },
+ { SRV_NETRDFSMANAGERREPORTSITEINFO, "NetrDfsManagerReportSiteInfo",
+ NULL, NULL },
+ { SRV_NETRSERVERTRANSPORTDELEX, "NetrServerTransportDelEx",
+ NULL, NULL },
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_dcerpc_srvsvc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_srvsvc_opnum,
+ { "Operation", "srvsvc.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ { &hf_srvsvc_server,
+ { "Server", "srvsvc.server", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Server Name", HFILL}},
+ { &hf_srvsvc_emulated_server,
+ { "Emulated Server", "srvsvc.emulated_server", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Emulated Server Name", HFILL}},
+ { &hf_srvsvc_alerts,
+ { "Alerts", "srvsvc.alerts", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Alerts", HFILL}},
+ { &hf_srvsvc_guest,
+ { "Guest Account", "srvsvc.guest", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Guest Account", HFILL}},
+ { &hf_srvsvc_transport,
+ { "Transport", "srvsvc.transport", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Transport Name", HFILL}},
+ { &hf_srvsvc_session,
+ { "Session", "srvsvc.session", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Session Name", HFILL}},
+ { &hf_srvsvc_qualifier,
+ { "Qualifier", "srvsvc.qualifier", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Connection Qualifier", HFILL}},
+ { &hf_srvsvc_computer,
+ { "Computer", "srvsvc.computer", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Computer Name", HFILL}},
+ { &hf_srvsvc_chrdev,
+ { "Char Device", "srvsvc.chrdev", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Char Device Name", HFILL}},
+ { &hf_srvsvc_chrdevq,
+ { "Device Queue", "srvsvc.chrdevq", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Char Device Queue Name", HFILL}},
+ { &hf_srvsvc_user,
+ { "User", "srvsvc.user", FT_STRING, BASE_NONE,
+ NULL, 0x0, "User Name", HFILL}},
+ { &hf_srvsvc_path,
+ { "Path", "srvsvc.path", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Path", HFILL}},
+ { &hf_srvsvc_share_passwd,
+ { "Share Passwd", "srvsvc.share_passwd", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Password for this share", HFILL}},
+ { &hf_srvsvc_share_alternate_name,
+ { "Alternate Name", "srvsvc.share_alternate_name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Alternate name for this share", HFILL}},
+ { &hf_srvsvc_chrdev_status,
+ { "Status", "srvsvc.chrdev_status", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Char Device Status", HFILL}},
+ { &hf_srvsvc_chrqpri,
+ { "Priority", "srvsvc.chrqdev_pri", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Char QDevice Priority", HFILL}},
+ { &hf_srvsvc_chrqnumusers,
+ { "Num Users", "srvsvc.chrqdev_numusers", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Char QDevice Number Of Users", HFILL}},
+ { &hf_srvsvc_chrqnumahead,
+ { "Num Ahead", "srvsvc.chrqdev_numahead", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_chrdev_opcode,
+ { "Opcode", "srvsvc.chrdev_opcode", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Opcode to apply to the Char Device", HFILL}},
+ { &hf_srvsvc_chrdev_time,
+ { "Time", "srvsvc.chrdev_time", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Char Device Time?", HFILL}},
+ { &hf_srvsvc_info_level,
+ { "Info Level", "svrsvc.info_level", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Info Level", HFILL}},
+ { &hf_srvsvc_rc,
+ { "Return code", "srvsvc.rc", FT_UINT32,
+ BASE_HEX, VALS(DOS_errors), 0x0, "Return Code", HFILL}},
+
+ { &hf_srvsvc_platform_id,
+ { "Platform ID", "srvsvc.info.platform_id", FT_UINT32,
+ BASE_DEC, VALS(platform_id_vals), 0x0, "Platform ID", HFILL}},
+ { &hf_srvsvc_ver_major,
+ { "Major Version", "srvsvc.version.major", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Major Version", HFILL}},
+ { &hf_srvsvc_ver_minor,
+ { "Minor Version", "srvsvc.version.minor", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Minor Version", HFILL}},
+ { &hf_srvsvc_client_type,
+ { "Client Type", "srvsvc.client.type", FT_STRING,
+ BASE_NONE, NULL, 0x0, "Client Type", HFILL}},
+ { &hf_srvsvc_comment,
+ { "Comment", "srvsvc.comment", FT_STRING,
+ BASE_NONE, NULL, 0x0, "Comment", HFILL}},
+ { &hf_srvsvc_users,
+ { "Users", "srvsvc.users", FT_UINT32,
+ BASE_DEC, NULL, 0x0 , "User Count", HFILL}},
+ { &hf_srvsvc_disc,
+ { "Disc", "srvsvc.disc", FT_UINT32,
+ BASE_DEC, NULL, 0x0 , "", HFILL}},
+ { &hf_srvsvc_hidden,
+ { "Hidden", "srvsvc.hidden", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Hidden", HFILL}},
+ { &hf_srvsvc_reserved,
+ { "Reserved", "srvsvc.reserved", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Announce", HFILL }},
+ { &hf_srvsvc_announce,
+ { "Announce", "srvsvc.announce", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Announce", HFILL }},
+ { &hf_srvsvc_anndelta,
+ { "Announce Delta", "srvsvc.ann_delta", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Announce Delta", HFILL}},
+ { &hf_srvsvc_licences,
+ { "Licences", "srvsvc.licences", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Licences", HFILL}},
+ { &hf_srvsvc_user_path,
+ { "User Path", "srvsvc.user_path", FT_STRING,
+ BASE_NONE, NULL, 0x0, "User Path", HFILL}},
+ { &hf_srvsvc_share,
+ { "Share", "srvsvc.share", FT_STRING,
+ BASE_NONE, NULL, 0x0, "Share", HFILL}},
+ { &hf_srvsvc_share_type,
+ { "Share Type", "srvsvc.share_type", FT_UINT32,
+ BASE_HEX, VALS(share_type_vals), 0x0, "Share Type", HFILL}},
+ { &hf_srvsvc_file_id,
+ { "File ID", "srvsvc.file_id", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "File ID", HFILL}},
+ { &hf_srvsvc_perm,
+ { "Permissions", "srvsvc.perm", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Permissions", HFILL}},
+ { &hf_srvsvc_dfs_root_flags,
+ { "DFS Root Flags", "srvsvc.dfs_root_flags", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "DFS Root Flags. Contact ethereal developers if you know what the bits are", HFILL}},
+ { &hf_srvsvc_policy,
+ { "Policy", "srvsvc.policy", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Policy", HFILL}},
+ { &hf_srvsvc_file_num_locks,
+ { "Num Locks", "srvsvc.file_num_locks", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of locks for file", HFILL}},
+ { &hf_srvsvc_con_id,
+ { "Connection ID", "srvsvc.con_id", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Connection ID", HFILL}},
+ { &hf_srvsvc_max_uses,
+ { "Max Uses", "srvsvc.max_uses", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Max Uses", HFILL}},
+ { &hf_srvsvc_cur_uses,
+ { "Current Uses", "srvsvc.cur_uses", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Current Uses", HFILL}},
+ { &hf_srvsvc_con_num_opens,
+ { "Num Opens", "srvsvc.con_num_opens", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Num Opens", HFILL}},
+ { &hf_srvsvc_session_num_opens,
+ { "Num Opens", "srvsvc.session.num_opens", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Num Opens", HFILL}},
+ { &hf_srvsvc_session_time,
+ { "Time", "srvsvc.session.time", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Time", HFILL}},
+ { &hf_srvsvc_session_idle_time,
+ { "Idle Time", "srvsvc.session.idle_time", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Idle Time", HFILL}},
+ { &hf_srvsvc_session_user_flags,
+ { "User Flags", "srvsvc.session.user_flags", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "User Flags", HFILL}},
+ { &hf_srvsvc_con_type,
+ { "Connection Type", "srvsvc.con_type", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Connection Type", HFILL}},
+ { &hf_srvsvc_con_time,
+ { "Connection Time", "srvsvc.con_time", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Connection Time", HFILL}},
+ { &hf_srvsvc_ulist_mtime,
+ { "Ulist mtime", "srvsvc.ulist_mtime", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Ulist mtime", HFILL}},
+ { &hf_srvsvc_glist_mtime,
+ { "Glist mtime", "srvsvc.glist_mtime", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Glist mtime", HFILL}},
+ { &hf_srvsvc_alist_mtime,
+ { "Alist mtime", "srvsvc.alist_mtime", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Alist mtime", HFILL}},
+ { &hf_srvsvc_connections,
+ { "Connections", "srvsvc.connections", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of Connections", HFILL}},
+ { &hf_srvsvc_shares,
+ { "Shares", "srvsvc.shares", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of Shares", HFILL}},
+ { &hf_srvsvc_diskalert,
+ { "Disk Alerts", "srvsvc.diskalert", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of disk alerts", HFILL}},
+ { &hf_srvsvc_netioalert,
+ { "Net I/O Alerts", "srvsvc.netioalert", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of Net I/O Alerts", HFILL}},
+ { &hf_srvsvc_maxauditsz,
+ { "Max Audits", "srvsvc.maxaudits", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Maximum number of audits", HFILL}},
+ { &hf_srvsvc_srvheuristics,
+ { "Server Heuristics", "srvsvc.srvheuristics", FT_STRING,
+ BASE_DEC, NULL, 0x0, "Server Heuristics", HFILL}},
+ { &hf_srvsvc_openfiles,
+ { "Open Files", "srvsvc.openfiles", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Open Files", HFILL}},
+ { &hf_srvsvc_opensearch,
+ { "Open Search", "srvsvc.opensearch", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Open Search", HFILL}},
+ { &hf_srvsvc_activelocks,
+ { "Active Locks", "srvsvc.activelocks", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Active Locks", HFILL}},
+ { &hf_srvsvc_numfiletasks,
+ { "Num Filetasks", "srvsvc.numfiletasks", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of filetasks", HFILL}},
+ { &hf_srvsvc_alertsched,
+ { "Alert Sched", "srvsvc.alertsched", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Alert Schedule", HFILL}},
+ { &hf_srvsvc_erroralert,
+ { "Error Alerts", "srvsvc.erroralert", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of error alerts", HFILL}},
+ { &hf_srvsvc_logonalert,
+ { "Logon Alerts", "srvsvc.logonalert", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of logon alerts", HFILL}},
+ { &hf_srvsvc_accessalert,
+ { "Access Alerts", "srvsvc.accessalert", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of access alerts", HFILL}},
+ { &hf_srvsvc_sizreqbufs,
+ { "Siz Req Bufs", "srvsvc.sizreqbufs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_numbigbufs,
+ { "Num Big Bufs", "srvsvc.numbigbufs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of big buffers", HFILL}},
+ { &hf_srvsvc_sessopens,
+ { "Sessions Open", "srvsvc.sessopens", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Sessions Open", HFILL}},
+ { &hf_srvsvc_sessvcs,
+ { "Sessions VCs", "srvsvc.sessvcs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Sessions VCs", HFILL}},
+ { &hf_srvsvc_sessreqs,
+ { "Sessions Reqs", "srvsvc.sessreqs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Sessions Requests", HFILL}},
+ { &hf_srvsvc_auditedevents,
+ { "Audited Events", "srvsvc.auditedevents", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of audited events", HFILL}},
+ { &hf_srvsvc_auditprofile,
+ { "Audit Profile", "srvsvc.auditprofile", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Audit Profile", HFILL}},
+ { &hf_srvsvc_autopath,
+ { "Autopath", "srvsvc.autopath", FT_STRING,
+ BASE_DEC, NULL, 0x0, "Autopath", HFILL}},
+ { &hf_srvsvc_security,
+ { "Security", "srvsvc.security", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Security", HFILL}},
+ { &hf_srvsvc_numadmin,
+ { "Num Admins", "srvsvc.num_admins", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of Administrators", HFILL}},
+ { &hf_srvsvc_lanmask,
+ { "LANMask", "srvsvc.lanmask", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "LANMask", HFILL}},
+ { &hf_srvsvc_chdevs,
+ { "Char Devs", "srvsvc.chdevs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of Char Devices", HFILL}},
+ { &hf_srvsvc_chdevqs,
+ { "Char Devqs", "srvsvc.chdevqs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of Char Device Queues", HFILL}},
+ { &hf_srvsvc_chdevjobs,
+ { "Char Dev Jobs", "srvsvc.chdevjobs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of Char Device Jobs", HFILL}},
+ { &hf_srvsvc_num_entries,
+ { "Number of entries", "srvsvc.share.num_entries", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of Entries", HFILL}},
+ { &hf_srvsvc_total_entries,
+ { "Total entries", "srvsvc.share.tot_entries", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Total Entries", HFILL}},
+ { &hf_srvsvc_initworkitems,
+ { "Init Workitems", "srvsvc.initworkitems", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Workitems", HFILL}},
+ { &hf_srvsvc_maxworkitems,
+ { "Max Workitems", "srvsvc.maxworkitems", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Workitems", HFILL}},
+ { &hf_srvsvc_rawworkitems,
+ { "Raw Workitems", "srvsvc.rawworkitems", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Workitems", HFILL}},
+ { &hf_srvsvc_preferred_len,
+ { "Preferred length", "srvsvc.preferred_len", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Preferred Length", HFILL}},
+ { &hf_srvsvc_parm_error,
+ { "Parameter Error", "srvsvc.parm_error", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Parameter Error", HFILL}},
+ { &hf_srvsvc_enum_handle,
+ { "Enumeration handle", "srvsvc.enum_hnd", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "Enumeration Handle", HFILL}},
+ { &hf_srvsvc_irpstacksize,
+ { "Irp Stack Size", "srvsvc.irpstacksize", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Irp Stack Size", HFILL}},
+ { &hf_srvsvc_maxrawbuflen,
+ { "Max Raw Buf Len", "srvsvc.", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Max Raw Buf Len", HFILL}},
+ { &hf_srvsvc_maxpagedmemoryusage,
+ { "Max Paged Memory Usage", "srvsvc.maxpagedmemoryusage", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Max Paged Memory Usage", HFILL}},
+ { &hf_srvsvc_maxnonpagedmemoryusage,
+ { "Max Non-Paged Memory Usage", "srvsvc.maxnonpagedmemoryusage", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Max Non-Paged Memory Usage", HFILL}},
+ { &hf_srvsvc_enablesoftcompat,
+ { "Enable Soft Compat", "srvsvc.enablesoftcompat", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Enable Soft Compat", HFILL}},
+ { &hf_srvsvc_enableforcedlogoff,
+ { "Enable Forced Logoff", "srvsvc.enableforcedlogoff", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Enable Forced Logoff", HFILL}},
+ { &hf_srvsvc_timesource,
+ { "Timesource", "srvsvc.timesource", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Timesource", HFILL}},
+ { &hf_srvsvc_acceptdownlevelapis,
+ { "Accept Downlevel APIs", "srvsvc.acceptdownlevelapis", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Accept Downlevel APIs", HFILL}},
+ { &hf_srvsvc_lmannounce,
+ { "LM Announce", "srvsvc.lmannounce", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "LM Announce", HFILL}},
+ { &hf_srvsvc_domain,
+ { "Domain", "srvsvc.domain", FT_STRING,
+ BASE_HEX, NULL, 0x0, "Domain", HFILL}},
+ { &hf_srvsvc_maxcopyreadlen,
+ { "Max Copy Read Len", "srvsvc.maxcopyreadlen", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Max Copy Read Len", HFILL}},
+ { &hf_srvsvc_maxcopywritelen,
+ { "Max Copy Write Len", "srvsvc.maxcopywritelen", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Max Copy Write Len", HFILL}},
+ { &hf_srvsvc_minkeepsearch,
+ { "Min Keep Search", "srvsvc.minkeepsearch", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Min Keep Search", HFILL}},
+ { &hf_srvsvc_maxkeepsearch,
+ { "Max Keep Search", "srvsvc.maxkeepsearch", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Max Keep Search", HFILL}},
+ { &hf_srvsvc_minkeepcomplsearch,
+ { "Min Keep Compl Search", "srvsvc.minkeepcomplsearch", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Min Keep Compl Search", HFILL}},
+ { &hf_srvsvc_maxkeepcomplsearch,
+ { "Max Keep Compl Search", "srvsvc.maxkeepcomplsearch", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Max Keep Compl Search", HFILL}},
+ { &hf_srvsvc_threadcountadd,
+ { "Thread Count Add", "srvsvc.threadcountadd", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Thread Count Add", HFILL}},
+ { &hf_srvsvc_numblockthreads,
+ { "Num Block Threads", "srvsvc.numblockthreads", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Num Block Threads", HFILL}},
+ { &hf_srvsvc_scavtimeout,
+ { "Scav Timeout", "srvsvc.scavtimeout", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Scav Timeout", HFILL}},
+ { &hf_srvsvc_minrcvqueue,
+ { "Min Rcv Queue", "srvsvc.minrcvqueue", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Min Rcv Queue", HFILL}},
+ { &hf_srvsvc_minfreeworkitems,
+ { "Min Free Workitems", "srvsvc.minfreeworkitems", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Min Free Workitems", HFILL}},
+ { &hf_srvsvc_xactmemsize,
+ { "Xact Mem Size", "srvsvc.xactmemsize", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Xact Mem Size", HFILL}},
+ { &hf_srvsvc_threadpriority,
+ { "Thread Priority", "srvsvc.threadpriority", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Thread Priority", HFILL}},
+ { &hf_srvsvc_maxmpxct,
+ { "MaxMpxCt", "srvsvc.maxmpxct", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "MaxMpxCt", HFILL}},
+ { &hf_srvsvc_oplockbreakwait,
+ { "Oplock Break Wait", "srvsvc.oplockbreakwait", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Oplock Break Wait", HFILL}},
+ { &hf_srvsvc_oplockbreakresponsewait,
+ { "Oplock Break Response wait", "srvsvc.oplockbreakresponsewait", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Oplock Break response Wait", HFILL}},
+ { &hf_srvsvc_enableoplocks,
+ { "Enable Oplocks", "srvsvc.enableoplocks", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Enable Oplocks", HFILL}},
+ { &hf_srvsvc_enableoplockforceclose,
+ { "Enable Oplock Force Close", "srvsvc.enableoplockforceclose", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Enable Oplock Force Close", HFILL}},
+ { &hf_srvsvc_enablefcbopens,
+ { "Enable FCB Opens", "srvsvc.enablefcbopens", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Enable FCB Opens", HFILL}},
+ { &hf_srvsvc_enableraw,
+ { "Enable RAW", "srvsvc.enableraw", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Enable RAW", HFILL}},
+ { &hf_srvsvc_enablesharednetdrives,
+ { "Enable Shared Net Drives", "srvsvc.enablesharednetdrives", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Enable Shared Net Drives", HFILL}},
+ { &hf_srvsvc_minfreeconnections,
+ { "Min Free Conenctions", "srvsvc.minfreeconnections", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Min Free Connections", HFILL}},
+ { &hf_srvsvc_maxfreeconnections,
+ { "Max Free Conenctions", "srvsvc.maxfreeconnections", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Max Free Connections", HFILL}},
+ { &hf_srvsvc_initsesstable,
+ { "Init Session Table", "srvsvc.initsesstable", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Init Session Table", HFILL}},
+ { &hf_srvsvc_initconntable,
+ { "Init Connection Table", "srvsvc.initconntable", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Init Connection Table", HFILL}},
+ { &hf_srvsvc_initfiletable,
+ { "Init File Table", "srvsvc.initfiletable", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Init File Table", HFILL}},
+ { &hf_srvsvc_initsearchtable,
+ { "Init Search Table", "srvsvc.initsearchtable", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Init Search Table", HFILL}},
+ { &hf_srvsvc_errortreshold,
+ { "Error Treshold", "srvsvc.errortreshold", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Error Treshold", HFILL}},
+ { &hf_srvsvc_networkerrortreshold,
+ { "Network Error Treshold", "srvsvc.networkerrortreshold", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Network Error Treshold", HFILL}},
+ { &hf_srvsvc_diskspacetreshold,
+ { "Diskspace Treshold", "srvsvc.diskspacetreshold", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Diskspace Treshold", HFILL}},
+ { &hf_srvsvc_maxlinkdelay,
+ { "Max Link Delay", "srvsvc.maxlinkdelay", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Max Link Delay", HFILL}},
+ { &hf_srvsvc_minlinkthroughput,
+ { "Min Link Throughput", "srvsvc.minlinkthroughput", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Min Link Throughput", HFILL}},
+ { &hf_srvsvc_linkinfovalidtime,
+ { "Link Info Valid Time", "srvsvc.linkinfovalidtime", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Link Info Valid Time", HFILL}},
+ { &hf_srvsvc_scavqosinfoupdatetime,
+ { "Scav QoS Info Update Time", "srvsvc.scavqosinfoupdatetime", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Scav QoS Info Update Time", HFILL}},
+ { &hf_srvsvc_maxworkitemidletime,
+ { "Max Workitem Idle Time", "srvsvc.maxworkitemidletime", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Max Workitem Idle Time", HFILL}},
+ { &hf_srvsvc_disk_name,
+ { "Disk Name", "srvsvc.disk_name", FT_STRING,
+ BASE_DEC, NULL, 0x0, "Disk Name", HFILL}},
+ { &hf_srvsvc_disk_name_len,
+ { "Disk Name Length", "srvsvc.disk_name_len", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Length of Disk Name", HFILL}},
+ { &hf_srvsvc_disk_inf0_unknown,
+ { "Disk_Info0 unknown", "srvsvc.disk_info0_unknown1", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Disk Info 0 unknown uint32", HFILL}},
+ { &hf_srvsvc_service,
+ { "Service", "srvsvc.service", FT_STRING,
+ BASE_DEC, NULL, 0x0, "Service", HFILL}},
+ { &hf_srvsvc_service_options,
+ { "Options", "srvsvc.service_options", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Service Options", HFILL}},
+ { &hf_srvsvc_transport_numberofvcs,
+ { "VCs", "srvsvc.transport.num_vcs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of VCs for this transport", HFILL}},
+ { &hf_srvsvc_transport_name,
+ { "Name", "srvsvc.transport.name", FT_STRING,
+ BASE_HEX, NULL, 0x0, "Name of transport", HFILL}},
+ { &hf_srvsvc_transport_address,
+ { "Address", "srvsvc.transport.address", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "Address of transport", HFILL}},
+ { &hf_srvsvc_transport_address_len,
+ { "Address Len", "srvsvc.transport.addresslen", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Length of transport address", HFILL}},
+ { &hf_srvsvc_transport_networkaddress,
+ { "Network Address", "srvsvc.transport.networkaddress", FT_STRING,
+ BASE_HEX, NULL, 0x0, "Network address for transport", HFILL}},
+ { &hf_srvsvc_service_bits,
+ { "Service Bits", "srvsvc.service_bits", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Service Bits", HFILL}},
+ { &hf_srvsvc_service_bits_of_interest,
+ { "Service Bits Of Interest", "srvsvc.service_bits_of_interest", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Service Bits Of Interest", HFILL}},
+ { &hf_srvsvc_update_immediately,
+ { "Update Immediately", "srvsvc.update_immediately", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Update Immediately", HFILL}},
+ { &hf_srvsvc_path_flags,
+ { "Flags", "srvsvc.path_flags", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Path flags", HFILL}},
+ { &hf_srvsvc_share_flags,
+ { "Flags", "srvsvc.share_flags", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "Share flags", HFILL}},
+ { &hf_srvsvc_path_type,
+ { "Type", "srvsvc.path_type", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Path type", HFILL}},
+ { &hf_srvsvc_path_len,
+ { "Len", "srvsvc.path_len", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Path len", HFILL}},
+ { &hf_srvsvc_outbuflen,
+ { "OutBufLen", "srvsvc.outbuflen", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Output Buffer Length", HFILL}},
+ { &hf_srvsvc_prefix,
+ { "Prefix", "srvsvc.prefix", FT_STRING,
+ BASE_HEX, NULL, 0x0, "Path Prefix", HFILL}},
+ { &hf_srvsvc_hnd,
+ { "Context Handle", "srvsvc.hnd", FT_BYTES,
+ BASE_NONE, NULL, 0x0, "Context Handle", HFILL}},
+ { &hf_srvsvc_server_stat_start,
+ { "Start", "srvsvc.server_stat.start", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_server_stat_fopens,
+ { "Fopens", "srvsvc.server_stat.fopens", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of fopens", HFILL}},
+ { &hf_srvsvc_server_stat_devopens,
+ { "Devopens", "srvsvc.server_stat.devopens", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of devopens", HFILL}},
+ { &hf_srvsvc_server_stat_jobsqueued,
+ { "Jobs Queued", "srvsvc.server_stat.jobsqueued", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of jobs queued", HFILL}},
+ { &hf_srvsvc_server_stat_sopens,
+ { "Sopens", "srvsvc.server_stat.sopens", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of sopens", HFILL}},
+ { &hf_srvsvc_server_stat_stimeouts,
+ { "stimeouts", "srvsvc.server_stat.stimeouts", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of stimeouts", HFILL}},
+ { &hf_srvsvc_server_stat_serrorout,
+ { "Serrorout", "srvsvc.server_stat.serrorout", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of serrorout", HFILL}},
+ { &hf_srvsvc_server_stat_pwerrors,
+ { "Pwerrors", "srvsvc.server_stat.pwerrors", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of password errors", HFILL}},
+ { &hf_srvsvc_server_stat_permerrors,
+ { "Permerrors", "srvsvc.server_stat.permerrors", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of permission errors", HFILL}},
+ { &hf_srvsvc_server_stat_syserrors,
+ { "Syserrors", "srvsvc.server_stat.syserrors", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of system errors", HFILL}},
+ { &hf_srvsvc_server_stat_bytessent,
+ { "Bytes Sent", "srvsvc.server_stat.bytessent", FT_UINT64,
+ BASE_DEC, NULL, 0x0, "Number of bytes sent", HFILL}},
+ { &hf_srvsvc_server_stat_bytesrcvd,
+ { "Bytes Rcvd", "srvsvc.server_stat.bytesrcvd", FT_UINT64,
+ BASE_DEC, NULL, 0x0, "Number of bytes received", HFILL}},
+ { &hf_srvsvc_server_stat_avresponse,
+ { "Avresponse", "srvsvc.server_stat.avresponse", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_server_stat_reqbufneed,
+ { "Req Buf Need", "srvsvc.server_stat.reqbufneed", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of request buffers needed?", HFILL}},
+ { &hf_srvsvc_server_stat_bigbufneed,
+ { "Big Buf Need", "srvsvc.server_stat.bigbufneed", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Number of big buffers needed?", HFILL}},
+ { &hf_srvsvc_tod_elapsed,
+ { "Elapsed", "srvsvc.tod.elapsed", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_msecs,
+ { "msecs", "srvsvc.tod.msecs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_hours,
+ { "Hours", "srvsvc.tod.hours", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_mins,
+ { "Mins", "srvsvc.tod.mins", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_secs,
+ { "Secs", "srvsvc.tod.secs", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_hunds,
+ { "Hunds", "srvsvc.tod.hunds", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_timezone,
+ { "Timezone", "srvsvc.tod.timezone", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_tinterval,
+ { "Tinterval", "srvsvc.tod.tinterval", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_day,
+ { "Day", "srvsvc.tod.day", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_month,
+ { "Month", "srvsvc.tod.month", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_year,
+ { "Year", "srvsvc.tod.year", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_srvsvc_tod_weekday,
+ { "Weekday", "srvsvc.tod.weekday", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_srvsvc,
+ &ett_srvsvc_share_info_1,
+ &ett_srvsvc_share_info_2,
+ &ett_srvsvc_share_info_501,
+ &ett_srvsvc_share_info_502
+ };
+
+ proto_dcerpc_srvsvc = proto_register_protocol(
+ "Microsoft Server Service", "SRVSVC", "srvsvc");
+
+ proto_register_field_array(proto_dcerpc_srvsvc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_srvsvc(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_srvsvc, ett_dcerpc_srvsvc,
+ &uuid_dcerpc_srvsvc, ver_dcerpc_srvsvc,
+ dcerpc_srvsvc_dissectors, hf_srvsvc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-srvsvc.h b/epan/dissectors/packet-dcerpc-srvsvc.h
new file mode 100644
index 0000000000..008b2624ad
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-srvsvc.h
@@ -0,0 +1,89 @@
+/* packet-dcerpc-srvsvc.h
+ * Routines for SMB \PIPE\srvsvc packet disassembly
+ * initial version
+ * Copyright 2001, Tim Potter <tpot@samba.org>
+ *
+ * 2002, Ronnie Sahlberg.
+ * Rewrote entire file with a complete and correct list of all
+ * function names. Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_SRVSVC_H
+#define __PACKET_DCERPC_SRVSVC_H
+
+#define SRV_NETRCHARDEVENUM 0x00
+#define SRV_NETRCHARDEVGETINFO 0x01
+#define SRV_NETRCHARDEVCONTROL 0x02
+#define SRV_NETRCHARDEVQENUM 0x03
+#define SRV_NETRCHARDEVQGETINFO 0x04
+#define SRV_NETRCHARDEVQSETINFO 0x05
+#define SRV_NETRCHARDEVQPURGE 0x06
+#define SRV_NETRCHARDEVQPURGESELF 0x07
+#define SRV_NETRCONNECTIONENUM 0x08
+#define SRV_NETRFILEENUM 0x09
+#define SRV_NETRFILEGETINFO 0x0a
+#define SRV_NETRFILECLOSE 0x0b
+#define SRV_NETRSESSIONENUM 0x0c
+#define SRV_NETRSESSIONDEL 0x0d
+#define SRV_NETRSHAREADD 0x0e
+#define SRV_NETRSHAREENUM 0x0f
+#define SRV_NETRSHAREGETINFO 0x10
+#define SRV_NETRSHARESETINFO 0x11
+#define SRV_NETRSHAREDEL 0x12
+#define SRV_NETRSHAREDELSTICKY 0x13
+#define SRV_NETRSHARECHECK 0x14
+#define SRV_NETRSERVERGETINFO 0x15
+#define SRV_NETRSERVERSETINFO 0x16
+#define SRV_NETRSERVERDISKENUM 0x17
+#define SRV_NETRSERVERSTATISTICSGET 0x18
+#define SRV_NETRSERVERTRANSPORTADD 0x19
+#define SRV_NETRSERVERTRANSPORTENUM 0x1a
+#define SRV_NETRSERVERTRANSPORTDEL 0x1b
+#define SRV_NETRREMOTETOD 0x1c
+#define SRV_NETRSERVERSETSERVICEBITS 0x1d
+#define SRV_NETRPRPATHTYPE 0x1e
+#define SRV_NETRPRPATHCANONICALIZE 0x1f
+#define SRV_NETRPRPATHCOMPARE 0x20
+#define SRV_NETRPRNAMEVALIDATE 0x21
+#define SRV_NETRPRNAMECANONICALIZE 0x22
+#define SRV_NETRPRNAMECOMPARE 0x23
+#define SRV_NETRSHAREENUMSTICKY 0x24
+#define SRV_NETRSHAREDELSTART 0x25
+#define SRV_NETRSHAREDELCOMMIT 0x26
+#define SRV_NETRPGETFILESECURITY 0x27
+#define SRV_NETRPSETFILESECURITY 0x28
+#define SRV_NETRSERVERTRANSPORTADDEX 0x29
+#define SRV_NETRSERVERSETSERVICEBITSEX 0x2a
+#define SRV_NETRDFSGETVERSION 0x2b
+#define SRV_NETRDFSCREATELOCALPARTITION 0x2c
+#define SRV_NETRDFSDELETELOCALPARTITION 0x2d
+#define SRV_NETRDFSSETLOCALVOLUMESTATE 0x2e
+#define SRV_NETRDFSSETSERVERINFO 0x2f
+#define SRV_NETRDFSCREATEEXITPOINT 0x30
+#define SRV_NETRDFSDELETEEXITPOINT 0x31
+#define SRV_NETRDFSMODIFYPREFIX 0x32
+#define SRV_NETRDFSFIXLOCALVOLUME 0x33
+#define SRV_NETRDFSMANAGERREPORTSITEINFO 0x34
+#define SRV_NETRSERVERTRANSPORTDELEX 0x35
+
+#endif
diff --git a/epan/dissectors/packet-dcerpc-svcctl.c b/epan/dissectors/packet-dcerpc-svcctl.c
new file mode 100644
index 0000000000..b2040cbfc6
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-svcctl.c
@@ -0,0 +1,618 @@
+/* packet-dcerpc-svcctl.c
+ * Routines for SMB \PIPE\svcctl packet disassembly
+ * Copyright 2003, Tim Potter <tpot@samba.org>
+ * Copyright 2003, Ronnie Sahlberg, added function dissectors
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-svcctl.h"
+#include "packet-dcerpc-nt.h"
+#include "smb.h"
+#include "packet-smb-common.h"
+
+static int proto_dcerpc_svcctl = -1;
+static int hf_svcctl_opnum = -1;
+static int hf_svcctl_machinename = -1;
+static int hf_svcctl_database = -1;
+static int hf_svcctl_access_mask = -1;
+static int hf_svcctl_scm_rights_connect = -1;
+static int hf_svcctl_scm_rights_create_service = -1;
+static int hf_svcctl_scm_rights_enumerate_service = -1;
+static int hf_svcctl_scm_rights_lock = -1;
+static int hf_svcctl_scm_rights_query_lock_status = -1;
+static int hf_svcctl_scm_rights_modify_boot_config = -1;
+static int hf_svcctl_hnd = -1;
+static int hf_svcctl_lock = -1;
+static int hf_svcctl_rc = -1;
+static int hf_svcctl_size = -1;
+static int hf_svcctl_required_size = -1;
+static int hf_svcctl_is_locked = -1;
+static int hf_svcctl_lock_duration = -1;
+static int hf_svcctl_lock_owner = -1;
+static int hf_svcctl_service_type = -1;
+static int hf_svcctl_service_state = -1;
+static int hf_svcctl_resume = -1;
+
+static gint ett_dcerpc_svcctl = -1;
+
+static e_uuid_t uuid_dcerpc_svcctl = {
+ 0x367abb81, 0x9844, 0x35f1,
+ { 0xad, 0x32, 0x98, 0xf0, 0x38, 0x00, 0x10, 0x03 }
+};
+
+static guint16 ver_dcerpc_svcctl = 2;
+
+
+
+static int
+svcctl_dissect_pointer_long(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ di->hf_index, NULL);
+ return offset;
+}
+
+static void
+svcctl_scm_specific_rights(tvbuff_t *tvb, gint offset, proto_tree *tree,
+ guint32 access)
+{
+ proto_tree_add_boolean(tree, hf_svcctl_scm_rights_modify_boot_config, tvb, offset, 4, access);
+ proto_tree_add_boolean(tree, hf_svcctl_scm_rights_query_lock_status, tvb, offset, 4, access);
+ proto_tree_add_boolean(tree, hf_svcctl_scm_rights_lock, tvb, offset, 4, access);
+ proto_tree_add_boolean(tree, hf_svcctl_scm_rights_enumerate_service, tvb, offset, 4, access);
+ proto_tree_add_boolean(tree, hf_svcctl_scm_rights_create_service, tvb, offset, 4, access);
+ proto_tree_add_boolean(tree, hf_svcctl_scm_rights_connect, tvb, offset, 4, access);
+}
+
+struct access_mask_info svcctl_scm_access_mask_info = {
+ "SVCCTL",
+ svcctl_scm_specific_rights,
+ NULL, /* Generic mapping table */
+ NULL /* Standard mapping table */
+};
+
+/*
+ * IDL long OpenSCManager(
+ * IDL [in] [string] [unique] char *MachineName,
+ * IDL [in] [string] [unique] char *DatabaseName,
+ * IDL [in] long access_mask,
+ * IDL [out] SC_HANDLE handle,
+ * IDL );
+ */
+static int
+svcctl_dissect_OpenSCManager_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* MachineName */
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
+ "MachineName", hf_svcctl_machinename, cb_str_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
+
+ /* DatabaseName */
+ offset = dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
+ "Database", hf_svcctl_database, cb_str_postprocess,
+ GINT_TO_POINTER(CB_STR_COL_INFO | 1));
+
+ /* access mask */
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_access_mask,
+ &svcctl_scm_access_mask_info, NULL);
+
+ return offset;
+}
+
+static int
+svcctl_dissect_OpenSCManager_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+ dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
+ e_ctx_hnd policy_hnd;
+ proto_item *hnd_item;
+ guint32 status;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, &policy_hnd,
+ &hnd_item, TRUE, FALSE);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_rc, &status);
+
+ if (status == 0) {
+
+ /* Associate the returned svcctl with a name */
+
+ if (dcv->private_data) {
+ char *pol_name;
+
+ pol_name = g_strdup_printf(
+ "OpenSCManager(%s)",
+ (char *)dcv->private_data);
+
+ dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
+
+ g_free(pol_name);
+ g_free(dcv->private_data);
+ dcv->private_data = NULL;
+ }
+
+ /*
+ * If we have a name for the handle, attach it to the item.
+ *
+ * XXX - we can't just do that above, as this may be called
+ * twice (see "dissect_pipe_dcerpc()", which calls the
+ * DCE RPC dissector twice), and in the first call we're
+ * not building a protocol tree (so we don't have an item
+ * to which to attach it) and in the second call
+ * "dcv->private_data" is NULL so we don't construct a
+ * name.
+ */
+
+ if (hnd_item != NULL) {
+ char *name;
+
+ if (dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL,
+ pinfo->fd->num) && name != NULL)
+ proto_item_append_text(hnd_item, ": %s", name);
+ }
+ }
+
+ return offset;
+}
+
+
+
+/*
+ * IDL BOOL CloseServiceHandle(
+ * IDL [in][out] SC_HANDLE handle
+ * IDL );
+ */
+static int
+svcctl_dissect_CloseServiceHandle_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ e_ctx_hnd policy_hnd;
+ char *pol_name;
+
+ /* Parse packet */
+
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, &policy_hnd,
+ NULL, FALSE, TRUE);
+
+ dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
+ pinfo->fd->num);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ pol_name);
+
+ return offset;
+}
+
+static int
+svcctl_dissect_CloseServiceHandle_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
+ NULL, FALSE, TRUE);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+ * IDL long LockServiceDatabase(
+ * IDL [in] SC_HANDLE dbhandle,
+ * IDL [out] SC_HANDLE lock,
+ * IDL );
+ */
+static int
+svcctl_dissect_LockServiceDatabase_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* XXX - why is the "is a close" argument TRUE? */
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
+ NULL, FALSE, TRUE);
+
+ return offset;
+}
+static int
+svcctl_dissect_LockServiceDatabase_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* XXX - why is the "is an open" argument TRUE? */
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
+ NULL, TRUE, FALSE);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+ * IDL long UnlockServiceDatabase(
+ * IDL [in][out] SC_HANDLE lock,
+ * IDL );
+ */
+static int
+svcctl_dissect_UnlockServiceDatabase_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* XXX - why is the "is a close" argument TRUE? */
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
+ NULL, FALSE, TRUE);
+
+ return offset;
+}
+static int
+svcctl_dissect_UnlockServiceDatabase_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* XXX - why is the "is an open" argument TRUE? */
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
+ NULL, TRUE, FALSE);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL long is_locked,
+ * IDL [unique][string] char *lock_owner,
+ * IDL long lock_duration,
+ * IDL };
+ */
+static int
+svcctl_dissect_QUERY_SERVICE_LOCK_STATUS(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_svcctl_is_locked, NULL);
+
+ offset = dissect_ndr_pointer(
+ tvb, offset, pinfo, tree, drep,
+ dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
+ "Owner", hf_svcctl_lock_owner);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_svcctl_lock_duration, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long QueryServiceLockStatus(
+ * IDL [in] SC_HANDLE db_handle,
+ * IDL [in] long buf_size,
+ * IDL [out][ref] QUERY_SERVICE_LOCK_STATUS *status,
+ * IDL [out][ref] long *required_buf_size
+ * IDL );
+ */
+static int
+svcctl_dissect_QueryServiceLockStatus_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* XXX - why is the "is a close" argument TRUE? */
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
+ NULL, FALSE, TRUE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_svcctl_size, NULL);
+
+ return offset;
+}
+static int
+svcctl_dissect_QueryServiceLockStatus_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ svcctl_dissect_QUERY_SERVICE_LOCK_STATUS, NDR_POINTER_REF,
+ "LOCK_STATUS", -1);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_svcctl_required_size, NULL);
+
+ offset = dissect_doserror(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
+
+ return offset;
+}
+
+
+
+#define SVCCTL_SERVICE_DRIVER 0x0b
+#define SVCCTL_SERVICE_WIN32 0x30
+static const value_string svcctl_service_type_vals[] = {
+ { SVCCTL_SERVICE_DRIVER, "SERVICE_DRIVER" },
+ { SVCCTL_SERVICE_WIN32, "SERVICE_WIN32" },
+ { 0, NULL }
+};
+
+#define SVCCTL_SERVICE_ACTIVE 0x01
+#define SVCCTL_SERVICE_INACTIVE 0x02
+#define SVCCTL_SERVICE_STATE_ALL 0x03
+static const value_string svcctl_service_status_vals[] = {
+ { SVCCTL_SERVICE_ACTIVE, "SERVICE_ACTIVE" },
+ { SVCCTL_SERVICE_INACTIVE, "SERVICE_INACTIVE" },
+ { SVCCTL_SERVICE_STATE_ALL, "SERVICE_STATE_ALL" },
+ { 0, NULL }
+};
+
+/*
+ * IDL long EnumServicesStatus(
+ * IDL [in] SC_HANDLE db_handle,
+ * IDL [in] long type,
+ * IDL [in] long status,
+ * IDL [in] long buf_size,
+ * IDL [in][unique] long *resume_handle,
+ * IDL );
+ */
+static int
+svcctl_dissect_EnumServicesStatus_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ /* XXX - why is the "is a close" argument TRUE? */
+ offset = dissect_nt_policy_hnd(
+ tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
+ NULL, FALSE, TRUE);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_svcctl_service_type, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_svcctl_service_state, NULL);
+
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_svcctl_size, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ svcctl_dissect_pointer_long, NDR_POINTER_UNIQUE,
+ "Resume Handle", hf_svcctl_resume);
+
+ return offset;
+}
+
+
+
+
+
+static dcerpc_sub_dissector dcerpc_svcctl_dissectors[] = {
+ { SVC_CLOSE_SERVICE_HANDLE, "CloseServiceHandle",
+ svcctl_dissect_CloseServiceHandle_rqst,
+ svcctl_dissect_CloseServiceHandle_reply },
+ { SVC_CONTROL_SERVICE, "ControlService", NULL, NULL },
+ { SVC_DELETE_SERVICE, "DeleteService", NULL, NULL },
+ { SVC_LOCK_SERVICE_DATABASE, "LockServiceDatabase",
+ svcctl_dissect_LockServiceDatabase_rqst,
+ svcctl_dissect_LockServiceDatabase_reply },
+ { SVC_QUERY_SERVICE_OBJECT_SECURITY, "QueryServiceObjectSecurity",
+ NULL, NULL },
+ { SVC_SET_SERVICE_OBJECT_SECURITY, "SetServiceObjectSecurity",
+ NULL, NULL },
+ { SVC_QUERY_SERVICE_STATUS, "QueryServiceStatus",
+ NULL, NULL },
+ { SVC_SET_SERVICE_STATUS, "SetServiceStatus",
+ NULL, NULL },
+ { SVC_UNLOCK_SERVICE_DATABASE, "UnlockServiceDatabase",
+ svcctl_dissect_UnlockServiceDatabase_rqst,
+ svcctl_dissect_UnlockServiceDatabase_reply },
+ { SVC_NOTIFY_BOOT_CONFIG_STATUS, "NotifyBootConfigStatus",
+ NULL, NULL },
+ { SVC_SC_SET_SERVICE_BITS_W, "ScSetServiceBitsW",
+ NULL, NULL },
+ { SVC_CHANGE_SERVICE_CONFIG_W, "ChangeServiceConfigW",
+ NULL, NULL },
+ { SVC_CREATE_SERVICE_W, "CreateServiceW", NULL, NULL },
+ { SVC_ENUM_DEPENDENT_SERVICES_W, "EnumDependentServicesW",
+ NULL, NULL },
+ { SVC_ENUM_SERVICES_STATUS_W, "EnumServicesStatusW",
+ NULL, NULL },
+ { SVC_OPEN_SC_MANAGER_W, "OpenSCManagerW", NULL, NULL },
+ { SVC_OPEN_SERVICE_W, "OpenServiceW", NULL, NULL },
+ { SVC_QUERY_SERVICE_CONFIG_W, "QueryServiceConfigW", NULL, NULL },
+ { SVC_QUERY_SERVICE_LOCK_STATUS_W, "QueryServiceLockStatusW",
+ NULL, NULL },
+ { SVC_START_SERVICE_W, "StartServiceW", NULL, NULL },
+ { SVC_GET_SERVICE_DISPLAY_NAME_W, "GetServiceDisplayNameW",
+ NULL, NULL },
+ { SVC_GET_SERVICE_KEY_NAME_W, "GetServiceKeyNameW", NULL, NULL },
+ { SVC_SC_SET_SERVICE_BITS_A, "ScSetServiceBitsA", NULL, NULL },
+ { SVC_CHANGE_SERVICE_CONFIG_A, "ChangeServiceConfigA", NULL, NULL },
+ { SVC_CREATE_SERVICE_A, "CreateServiceA", NULL, NULL },
+ { SVC_ENUM_DEPENDENT_SERVICES_A, "EnumDependentServicesA",
+ NULL, NULL },
+ { SVC_ENUM_SERVICES_STATUS_A, "EnumServicesStatusA",
+ svcctl_dissect_EnumServicesStatus_rqst,
+ NULL },
+ { SVC_OPEN_SC_MANAGER_A, "OpenSCManagerA",
+ svcctl_dissect_OpenSCManager_rqst,
+ svcctl_dissect_OpenSCManager_reply },
+ { SVC_OPEN_SERVICE_A, "OpenServiceA", NULL, NULL },
+ { SVC_QUERY_SERVICE_CONFIG_A, "QueryServiceConfigA", NULL, NULL },
+ { SVC_QUERY_SERVICE_LOCK_STATUS_A, "QueryServiceLockStatusA",
+ svcctl_dissect_QueryServiceLockStatus_rqst,
+ svcctl_dissect_QueryServiceLockStatus_reply },
+ { SVC_START_SERVICE_A, "StartServiceA", NULL, NULL },
+ { SVC_GET_SERVICE_DISPLAY_NAME_A, "GetServiceDisplayNameA",
+ NULL, NULL },
+ { SVC_GET_SERVICE_KEY_NAME_A, "GetServiceKeyNameA", NULL, NULL },
+ { SVC_SC_GET_CURRENT_GROUPE_STATE_W, "ScGetCurrentGroupStateW",
+ NULL, NULL },
+ { SVC_ENUM_SERVICE_GROUP_W, "EnumServiceGroupW",
+ NULL, NULL },
+ { SVC_CHANGE_SERVICE_CONFIG2_A, "ChangeServiceConfig2A",
+ NULL, NULL },
+ { SVC_CHANGE_SERVICE_CONFIG2_W, "ChangeServiceConfig2W",
+ NULL, NULL },
+ { SVC_QUERY_SERVICE_CONFIG2_A, "QueryServiceConfig2A",
+ NULL, NULL },
+ { SVC_QUERY_SERVICE_CONFIG2_W, "QueryServiceConfig2W",
+ NULL, NULL },
+ { SVC_QUERY_SERVICE_STATUS_EX, "QueryServiceStatusEx",
+ NULL, NULL },
+ { SVC_ENUM_SERVICES_STATUS_EX_A, "EnumServicesStatusExA",
+ NULL, NULL },
+ { SVC_ENUM_SERVICES_STATUS_EX_W, "EnumServicesStatusExW",
+ NULL, NULL },
+ { SVC_SC_SEND_TS_MESSAGE, "ScSendTSMessage",
+ NULL, NULL },
+ {0, NULL, NULL, NULL}
+};
+
+void
+proto_register_dcerpc_svcctl(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_svcctl_opnum,
+ { "Operation", "svcctl.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }},
+ { &hf_svcctl_machinename,
+ { "MachineName", "svcctl.machinename", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Name of the host we want to open the database on", HFILL }},
+ { &hf_svcctl_database,
+ { "Database", "svcctl.database", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Name of the database to open", HFILL }},
+ { &hf_svcctl_access_mask,
+ { "Access Mask", "svcctl.access_mask", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "SVCCTL Access Mask", HFILL }},
+ { &hf_svcctl_scm_rights_connect,
+ { "Connect", "svcctl.scm_rights_connect", FT_BOOLEAN, 32,
+ TFS(&flags_set_truth), 0x00000001, "SVCCTL Rights to connect to SCM", HFILL }},
+ { &hf_svcctl_scm_rights_create_service,
+ { "Create Service", "svcctl.scm_rights_create_service", FT_BOOLEAN, 32,
+ TFS(&flags_set_truth), 0x00000002, "SVCCTL Rights to create services", HFILL }},
+ { &hf_svcctl_scm_rights_enumerate_service,
+ { "Enumerate Service", "svcctl.scm_rights_enumerate_service", FT_BOOLEAN, 32,
+ TFS(&flags_set_truth), 0x00000004, "SVCCTL Rights to enumerate services", HFILL }},
+ { &hf_svcctl_scm_rights_lock,
+ { "Lock", "svcctl.scm_rights_lock", FT_BOOLEAN, 32,
+ TFS(&flags_set_truth), 0x00000008, "SVCCTL Rights to lock database", HFILL }},
+ { &hf_svcctl_scm_rights_query_lock_status,
+ { "Query Lock Status", "svcctl.scm_rights_query_lock_status", FT_BOOLEAN, 32,
+ TFS(&flags_set_truth), 0x00000010, "SVCCTL Rights to query database lock status", HFILL }},
+ { &hf_svcctl_scm_rights_modify_boot_config,
+ { "Modify Boot Config", "svcctl.scm_rights_modify_boot_config", FT_BOOLEAN, 32,
+ TFS(&flags_set_truth), 0x00000020, "SVCCTL Rights to modify boot config", HFILL }},
+ { &hf_svcctl_hnd,
+ { "Context Handle", "svcctl.hnd", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "SVCCTL Context handle", HFILL }},
+ { &hf_svcctl_lock,
+ { "Lock", "svcctl.lock", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "SVCCTL Database Lock", HFILL }},
+ { &hf_svcctl_rc,
+ { "Return code", "svcctl.rc", FT_UINT32, BASE_HEX,
+ VALS(DOS_errors), 0x0, "SVCCTL return code", HFILL }},
+ { &hf_svcctl_size,
+ { "Size", "svcctl.size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "SVCCTL size of buffer", HFILL }},
+ { &hf_svcctl_required_size,
+ { "Required Size", "svcctl.required_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "SVCCTL required size of buffer for data to fit", HFILL }},
+ { &hf_svcctl_is_locked,
+ { "IsLocked", "svcctl.is_locked", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "SVCCTL whether the database is locked or not", HFILL }},
+ { &hf_svcctl_lock_duration,
+ { "Duration", "svcctl.lock_duration", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "SVCCTL number of seconds the database has been locked", HFILL }},
+ { &hf_svcctl_lock_owner,
+ { "Owner", "svcctl.lock_owner", FT_STRING, BASE_NONE,
+ NULL, 0x0, "SVCCTL the user that holds the database lock", HFILL }},
+ { &hf_svcctl_service_type,
+ { "Type", "svcctl.service_type", FT_UINT32, BASE_DEC,
+ VALS(svcctl_service_type_vals), 0x0, "SVCCTL type of service", HFILL }},
+
+ { &hf_svcctl_service_state,
+ { "State", "svcctl.service_state", FT_UINT32, BASE_DEC,
+ VALS(svcctl_service_status_vals), 0x0, "SVCCTL service state", HFILL }},
+ { &hf_svcctl_resume,
+ { "Resume Handle", "svcctl.resume", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "SVCCTL resume handle", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_svcctl,
+ };
+
+ proto_dcerpc_svcctl = proto_register_protocol(
+ "Microsoft Service Control", "SVCCTL", "svcctl");
+
+ proto_register_field_array(proto_dcerpc_svcctl, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_svcctl(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_svcctl, ett_dcerpc_svcctl,
+ &uuid_dcerpc_svcctl, ver_dcerpc_svcctl,
+ dcerpc_svcctl_dissectors, hf_svcctl_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-svcctl.h b/epan/dissectors/packet-dcerpc-svcctl.h
new file mode 100644
index 0000000000..f5431e7746
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-svcctl.h
@@ -0,0 +1,74 @@
+/* packet-dcerpc-svcctl.h
+ * Routines for SMB \PIPE\svcctl packet disassembly
+ * Copyright 2003, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_SVCCTL_H
+#define __PACKET_DCERPC_SVCCTL_H
+
+#define SVC_CLOSE_SERVICE_HANDLE 0x00
+#define SVC_CONTROL_SERVICE 0x01
+#define SVC_DELETE_SERVICE 0x02
+#define SVC_LOCK_SERVICE_DATABASE 0x03
+#define SVC_QUERY_SERVICE_OBJECT_SECURITY 0x04
+#define SVC_SET_SERVICE_OBJECT_SECURITY 0x05
+#define SVC_QUERY_SERVICE_STATUS 0x06
+#define SVC_SET_SERVICE_STATUS 0x07
+#define SVC_UNLOCK_SERVICE_DATABASE 0x08
+#define SVC_NOTIFY_BOOT_CONFIG_STATUS 0x09
+#define SVC_SC_SET_SERVICE_BITS_W 0x0a
+#define SVC_CHANGE_SERVICE_CONFIG_W 0x0b
+#define SVC_CREATE_SERVICE_W 0x0c
+#define SVC_ENUM_DEPENDENT_SERVICES_W 0x0d
+#define SVC_ENUM_SERVICES_STATUS_W 0x0e
+#define SVC_OPEN_SC_MANAGER_W 0x0f
+#define SVC_OPEN_SERVICE_W 0x10
+#define SVC_QUERY_SERVICE_CONFIG_W 0x11
+#define SVC_QUERY_SERVICE_LOCK_STATUS_W 0x12
+#define SVC_START_SERVICE_W 0x13
+#define SVC_GET_SERVICE_DISPLAY_NAME_W 0x14
+#define SVC_GET_SERVICE_KEY_NAME_W 0x15
+#define SVC_SC_SET_SERVICE_BITS_A 0x16
+#define SVC_CHANGE_SERVICE_CONFIG_A 0x17
+#define SVC_CREATE_SERVICE_A 0x18
+#define SVC_ENUM_DEPENDENT_SERVICES_A 0x19
+#define SVC_ENUM_SERVICES_STATUS_A 0x1a
+#define SVC_OPEN_SC_MANAGER_A 0x1b
+#define SVC_OPEN_SERVICE_A 0x1c
+#define SVC_QUERY_SERVICE_CONFIG_A 0x1d
+#define SVC_QUERY_SERVICE_LOCK_STATUS_A 0x1e
+#define SVC_START_SERVICE_A 0x1f
+#define SVC_GET_SERVICE_DISPLAY_NAME_A 0x20
+#define SVC_GET_SERVICE_KEY_NAME_A 0x21
+#define SVC_SC_GET_CURRENT_GROUPE_STATE_W 0x22
+#define SVC_ENUM_SERVICE_GROUP_W 0x23
+#define SVC_CHANGE_SERVICE_CONFIG2_A 0x24
+#define SVC_CHANGE_SERVICE_CONFIG2_W 0x25
+#define SVC_QUERY_SERVICE_CONFIG2_A 0x26
+#define SVC_QUERY_SERVICE_CONFIG2_W 0x27
+#define SVC_QUERY_SERVICE_STATUS_EX 0x28
+#define SVC_ENUM_SERVICES_STATUS_EX_A 0x29
+#define SVC_ENUM_SERVICES_STATUS_EX_W 0x2a
+#define SVC_SC_SEND_TS_MESSAGE 0x2b
+
+#endif
diff --git a/epan/dissectors/packet-dcerpc-tapi.c b/epan/dissectors/packet-dcerpc-tapi.c
new file mode 100644
index 0000000000..628b04841d
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-tapi.c
@@ -0,0 +1,248 @@
+/* packet-dcerpc-tapi.c
+ * Routines for DCERPC TAPI packet disassembly
+ * Copyright 2002, Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/* The IDL file for this interface can be extracted by grepping for idl
+ * in capitals.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "packet-dcerpc-tapi.h"
+#include "smb.h"
+
+static int proto_dcerpc_tapi = -1;
+static int hf_tapi_opnum = -1;
+static int hf_tapi_rc = -1;
+static int hf_tapi_hnd = -1;
+static int hf_tapi_unknown_long = -1;
+static int hf_tapi_unknown_string = -1;
+static int hf_tapi_unknown_bytes = -1;
+
+static gint ett_dcerpc_tapi = -1;
+
+/*
+ IDL [ uuid(2f5f6520-ca46-1067-b319-00dd010662da),
+ IDL version(1.0),
+ IDL implicit_handle(handle_t rpc_binding)
+ IDL ] interface tapi
+ IDL {
+*/
+static e_uuid_t uuid_dcerpc_tapi = {
+ 0x2f5f6520, 0xca46, 0x1067,
+ { 0xb3, 0x19, 0x00, 0xdd, 0x01, 0x06, 0x62, 0xda }
+};
+
+static guint16 ver_dcerpc_tapi = 1;
+
+/*
+ IDL long ClientAttach(
+ IDL [out] [context_handle] void *element_1,
+ IDL [in] long element_2,
+ IDL [out] long element_3,
+ IDL [in] [string] [ref] wchar_t *element_4,
+ IDL [in] [string] [ref] wchar_t *element_5
+ IDL );
+*/
+static int
+dissect_tapi_client_attach_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_tapi_unknown_long, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "unknown string",
+ hf_tapi_unknown_string, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_REF, "unknown string",
+ hf_tapi_unknown_string, 0);
+
+ return offset;
+}
+static int
+dissect_tapi_client_attach_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ctx_hnd(tvb, offset, pinfo, tree, drep,
+ hf_tapi_hnd, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_tapi_unknown_long, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_tapi_rc, NULL);
+
+ return offset;
+}
+
+/*
+ IDL long ClientRequest(
+ IDL [in] [context_handle] void *element_6,
+ IDL [in,out] [size_is(element_8)] [length_is(???)] char element_7[*],
+ IDL [in] long element_8
+ IDL );
+*/
+static int
+dissect_tapi_TYPE_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* this call is to make ethereal eat the array header for the conformant run */
+ offset =dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep, NULL);
+
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_tapi_unknown_bytes, tvb, offset,
+ di->array_actual_count, FALSE);
+ offset += di->array_actual_count;
+
+ return offset;
+}
+
+static int
+dissect_tapi_client_request_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ctx_hnd(tvb, offset, pinfo, tree, drep,
+ hf_tapi_hnd, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ dissect_tapi_TYPE_1, NDR_POINTER_REF,
+ "unknown array", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_tapi_unknown_long, NULL);
+
+ return offset;
+}
+static int
+dissect_tapi_client_request_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_tapi_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ IDL void ClientDetach(
+ IDL void
+ IDL );
+*/
+static int
+dissect_tapi_client_detach_rqst(tvbuff_t *tvb _U_, int offset _U_,
+ packet_info *pinfo _U_, proto_tree *tree _U_,
+ guint8 *drep _U_)
+{
+ return offset;
+}
+static int
+dissect_tapi_client_detach_reply(tvbuff_t *tvb _U_, int offset _U_,
+ packet_info *pinfo _U_, proto_tree *tree _U_,
+ guint8 *drep _U_)
+{
+ return offset;
+}
+
+/*
+ IDL }
+*/
+static dcerpc_sub_dissector dcerpc_tapi_dissectors[] = {
+ { TAPI_CLIENT_ATTACH, "ClientAttach",
+ dissect_tapi_client_attach_rqst,
+ dissect_tapi_client_attach_reply },
+ { TAPI_CLIENT_REQUEST, "ClientRequest",
+ dissect_tapi_client_request_rqst,
+ dissect_tapi_client_request_reply },
+ { TAPI_CLIENT_DETACH, "ClientDetach",
+ dissect_tapi_client_detach_rqst,
+ dissect_tapi_client_detach_reply },
+
+ {0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_tapi(void)
+{
+static hf_register_info hf[] = {
+ { &hf_tapi_opnum, {
+ "Operation", "tapi.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_tapi_rc, {
+ "Return code", "tapi.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "TAPI return code", HFILL }},
+ { &hf_tapi_hnd, {
+ "Context Handle", "tapi.hnd", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "Context handle", HFILL }},
+ { &hf_tapi_unknown_long, {
+ "Unknown long", "tapi.unknown.long", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Unknown long. If you know what this is, contact ethereal developers.", HFILL }},
+ { &hf_tapi_unknown_string, {
+ "Unknown string", "tapi.unknown.string", FT_STRING, BASE_HEX,
+ NULL, 0x0, "Unknown string. If you know what this is, contact ethereal developers.", HFILL }},
+ { &hf_tapi_unknown_bytes, {
+ "Unknown bytes", "tapi.unknown.bytes", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Unknown bytes. If you know what this is, contact ethereal developers.", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_tapi
+ };
+
+ proto_dcerpc_tapi = proto_register_protocol(
+ "Microsoft Telephony API Service", "TAPI", "tapi");
+
+ proto_register_field_array(proto_dcerpc_tapi, hf,
+ array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_tapi(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_tapi, ett_dcerpc_tapi,
+ &uuid_dcerpc_tapi, ver_dcerpc_tapi,
+ dcerpc_tapi_dissectors, hf_tapi_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-tapi.h b/epan/dissectors/packet-dcerpc-tapi.h
new file mode 100644
index 0000000000..8749c79401
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-tapi.h
@@ -0,0 +1,33 @@
+/* packet-dcerpc-tapi.h
+ * Routines for DCERPC TAPI packet disassembly
+ * Copyright 2002, Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_TAPI_H
+#define __PACKET_DCERPC_TAPI_H
+
+#define TAPI_CLIENT_ATTACH 0x00
+#define TAPI_CLIENT_REQUEST 0x01
+#define TAPI_CLIENT_DETACH 0x02
+
+#endif
diff --git a/epan/dissectors/packet-dcerpc-tkn4int.c b/epan/dissectors/packet-dcerpc-tkn4int.c
new file mode 100644
index 0000000000..55a5376595
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-tkn4int.c
@@ -0,0 +1,92 @@
+/* packet-dcerpc-tkn4int.c
+ *
+ * Routines for dcerpc Token Server Calls
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz file/fsint/tkn4int.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_tkn4int = -1;
+static int hf_tkn4int_opnum = -1;
+
+
+static gint ett_tkn4int = -1;
+
+
+static e_uuid_t uuid_tkn4int = { 0x4d37f2dd, 0xed96, 0x0000, { 0x02, 0xc0, 0x37, 0xcf, 0x1e, 0x00, 0x00, 0x00 } };
+static guint16 ver_tkn4int = 4;
+
+
+static dcerpc_sub_dissector tkn4int_dissectors[] = {
+ { 0, "Probe", NULL, NULL},
+ { 1, "InitTokenState", NULL, NULL},
+ { 2, "TokenRevoke", NULL, NULL},
+ { 3, "GetCellName", NULL, NULL},
+ { 4, "GetLock", NULL, NULL},
+ { 5, "GetCE", NULL, NULL},
+ { 6, "GetServerInterfaces", NULL, NULL},
+ { 7, "SetParams", NULL, NULL},
+ { 8, "AsyncGrant", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+
+};
+
+void
+proto_register_tkn4int (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tkn4int_opnum,
+ { "Operation", "tkn4int.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_tkn4int,
+ };
+ proto_tkn4int = proto_register_protocol ("DCE/RPC TokenServer Calls", "TKN4Int", "tkn4int");
+ proto_register_field_array (proto_tkn4int, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_tkn4int (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_tkn4int, ett_tkn4int, &uuid_tkn4int, ver_tkn4int, tkn4int_dissectors, hf_tkn4int_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-trksvr.c b/epan/dissectors/packet-dcerpc-trksvr.c
new file mode 100644
index 0000000000..e819c57346
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-trksvr.c
@@ -0,0 +1,99 @@
+/* packet-dcerpc-trksvr.c
+ * Routines for DCERPC Distributed Link tracking Server packet disassembly
+ * Copyright 2003, Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/* The IDL file for this interface can be extracted by grepping for idl
+ * in capitals.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "smb.h"
+
+static int proto_dcerpc_trksvr = -1;
+static int hf_trksvr_opnum = -1;
+static int hf_trksvr_rc = -1;
+
+static gint ett_dcerpc_trksvr = -1;
+
+/*
+ IDL [ uuid(4da1-943d-11d1-acae-00c0afc2aa3f),
+ IDL version(1.0),
+ IDL implicit_handle(handle_t rpc_binding)
+ IDL ] interface trksvr
+ IDL {
+*/
+static e_uuid_t uuid_dcerpc_trksvr = {
+ 0x4da1c422, 0x943d, 0x11d1,
+ { 0xac, 0xae, 0x00, 0xc0, 0x4f, 0xc2, 0xaa, 0x3f }
+};
+
+static guint16 ver_dcerpc_trksvr = 1;
+
+static dcerpc_sub_dissector dcerpc_trksvr_dissectors[] = {
+ { 0, "LnkSvrMessage",
+ NULL,
+ NULL },
+ {0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_trksvr(void)
+{
+static hf_register_info hf[] = {
+ { &hf_trksvr_opnum, {
+ "Operation", "trksvr.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_trksvr_rc, {
+ "Return code", "trksvr.rc", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0x0, "TRKSVR return code", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_dcerpc_trksvr
+ };
+
+ proto_dcerpc_trksvr = proto_register_protocol(
+ "Microsoft Distributed Link Tracking Server Service", "TRKSVR", "trksvr");
+
+ proto_register_field_array(proto_dcerpc_trksvr, hf,
+ array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_trksvr(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_trksvr, ett_dcerpc_trksvr,
+ &uuid_dcerpc_trksvr, ver_dcerpc_trksvr,
+ dcerpc_trksvr_dissectors, hf_trksvr_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-ubikdisk.c b/epan/dissectors/packet-dcerpc-ubikdisk.c
new file mode 100644
index 0000000000..c68b3d7e04
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-ubikdisk.c
@@ -0,0 +1,95 @@
+/* packet-dcerpc-ubikdisk.c
+ *
+ * Routines for dcerpc UBIK Disk routines
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz file/ncsubik/ubikdisk_proc.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_ubikdisk = -1;
+static int hf_ubikdisk_opnum = -1;
+
+
+static gint ett_ubikdisk = -1;
+
+
+static e_uuid_t uuid_ubikdisk = { 0x4d37f2dd, 0xed43, 0x0002, { 0x02, 0xc0, 0x37, 0xcf, 0x1e, 0x00, 0x00, 0x00 } };
+static guint16 ver_ubikdisk = 4;
+
+
+static dcerpc_sub_dissector ubikdisk_dissectors[] = {
+ { 0, "Begin", NULL, NULL},
+ { 1, "Commit", NULL, NULL},
+ { 2, "Lock", NULL, NULL},
+ { 3, "Write", NULL, NULL},
+ { 4, "GetVersion", NULL, NULL},
+ { 5, "GetFile", NULL, NULL},
+ { 6, "SendFile", NULL, NULL},
+ { 7, "Abort", NULL, NULL},
+ { 8, "ReleaseLocks", NULL, NULL},
+ { 9, "Truncate", NULL, NULL},
+ { 10, "Probe", NULL, NULL},
+ { 11, "GetServerInterfaces", NULL, NULL},
+ { 12, "BulkUpdate", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_ubikdisk (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ubikdisk_opnum,
+ { "Operation", "ubikdisk.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_ubikdisk,
+ };
+ proto_ubikdisk = proto_register_protocol ("DCE/RPC FLDB UBIK TRANSFER", "UBIKDISK", "ubikdisk");
+ proto_register_field_array (proto_ubikdisk, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_ubikdisk (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_ubikdisk, ett_ubikdisk, &uuid_ubikdisk, ver_ubikdisk, ubikdisk_dissectors, hf_ubikdisk_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-ubikvote.c b/epan/dissectors/packet-dcerpc-ubikvote.c
new file mode 100644
index 0000000000..eb9e79d162
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-ubikvote.c
@@ -0,0 +1,90 @@
+/* packet-dcerpc-ubikvote.c
+ *
+ * Routines for dcerpc Ubik Voting routines.
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz file/ncsubik/ubikvote_proc.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+
+
+static int proto_ubikvote = -1;
+static int hf_ubikvote_opnum = -1;
+
+
+static gint ett_ubikvote = -1;
+
+
+static e_uuid_t uuid_ubikvote = { 0x4d37f2dd, 0xed43, 0x0003, { 0x02, 0xc0, 0x37, 0xcf, 0x1e, 0x00, 0x00, 0x00 } };
+static guint16 ver_ubikvote = 4;
+
+
+static dcerpc_sub_dissector ubikvote_dissectors[] = {
+ { 0, "Beacon", NULL, NULL},
+ { 1, "Debug", NULL, NULL},
+ { 2, "SDebug", NULL, NULL},
+ { 3, "GetServerInterfaces", NULL, NULL},
+ { 4, "GetSyncSite", NULL, NULL},
+ { 5, "DebugV2", NULL, NULL},
+ { 6, "SDebugV2", NULL, NULL},
+ { 7, "GetSyncSiteIdentity", NULL, NULL},
+ { 0, NULL, NULL, NULL }
+};
+
+void
+proto_register_ubikvote (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ubikvote_opnum,
+ { "Operation", "ubikvote.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_ubikvote,
+ };
+ proto_ubikvote = proto_register_protocol ("DCE/RPC FLDB UBIKVOTE", "UBIKVOTE", "ubikvote");
+ proto_register_field_array (proto_ubikvote, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_ubikvote (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_ubikvote, ett_ubikvote, &uuid_ubikvote, ver_ubikvote, ubikvote_dissectors, hf_ubikvote_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-update.c b/epan/dissectors/packet-dcerpc-update.c
new file mode 100644
index 0000000000..9da2fa232e
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-update.c
@@ -0,0 +1,91 @@
+/* packet-dcerpc-update.c
+ *
+ * Routines for dcerpc upserv dissection
+ * Copyright 2002, Jaime Fournier <Jaime.Fournier@hush.com>
+ * This information is based off the released idl files from opengroup.
+ * ftp://ftp.opengroup.org/pub/dce122/dce/src/file.tar.gz file/update/update.idl
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-dce122.h"
+
+static int proto_dce_update = -1;
+static int hf_dce_update_opnum = -1;
+
+static gint ett_dce_update = -1;
+
+static e_uuid_t uuid_dce_update =
+ { 0x4d37f2dd, 0xed43, 0x0000, {0x02, 0xc0, 0x37, 0xcf, 0x1e, 0x00, 0x10,
+ 0x00}
+};
+static guint16 ver_dce_update = 4;
+
+
+static dcerpc_sub_dissector dce_update_dissectors[] = {
+ {0, "UPDATE_GetServerInterfaces", NULL, NULL},
+ {1, "UPDATE_FetchInfo", NULL, NULL},
+ {2, "UPDATE_FetchFile", NULL, NULL},
+ {3, "UPDATE_FetchObjectInfo", NULL, NULL},
+ {0, NULL, NULL, NULL},
+};
+
+void
+proto_register_dce_update (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_dce_update_opnum,
+ {"Operation", "dce_update.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Operation", HFILL}}
+
+ };
+
+ static gint *ett[] = {
+ &ett_dce_update,
+ };
+ proto_dce_update =
+ proto_register_protocol ("DCE/RPC UpServer", "dce_update", "dce_update");
+ proto_register_field_array (proto_dce_update, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_dce_update (void)
+{
+ /* Register the protocol as dcerpc */
+ dcerpc_init_uuid (proto_dce_update, ett_dce_update, &uuid_dce_update,
+ ver_dce_update, dce_update_dissectors,
+ hf_dce_update_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-wkssvc.c b/epan/dissectors/packet-dcerpc-wkssvc.c
new file mode 100644
index 0000000000..ed18756b1e
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-wkssvc.c
@@ -0,0 +1,1796 @@
+/* packet-dcerpc-wkssvc.c
+ * Routines for SMB \\PIPE\\wkssvc packet disassembly
+ * Copyright 2001, Tim Potter <tpot@samba.org>
+ * Copyright 2003, Richard Sharpe <rsharpe@richardsharpe.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-wkssvc.h"
+#include "packet-dcerpc-nt.h"
+#include "smb.h"
+
+static int proto_dcerpc_wkssvc = -1;
+static int hf_wkssvc_opnum = -1;
+static int hf_wkssvc_server = -1;
+static int hf_wkssvc_info_level = -1;
+static int hf_wkssvc_platform_id = -1;
+static int hf_wkssvc_net_group = -1;
+static int hf_wkssvc_ver_major = -1;
+static int hf_wkssvc_ver_minor = -1;
+static int hf_wkssvc_lan_root = -1;
+static int hf_wkssvc_rc = -1;
+static int hf_wkssvc_logged_on_users = -1;
+static int hf_wkssvc_pref_max = -1;
+static int hf_wkssvc_enum_handle = -1;
+static int hf_wkssvc_junk = -1;
+static int hf_wkssvc_user_name = -1;
+static int hf_wkssvc_num_entries = -1;
+static int hf_wkssvc_logon_domain = -1;
+static int hf_wkssvc_other_domains = -1;
+static int hf_wkssvc_logon_server = -1;
+static int hf_wkssvc_entries_read = -1;
+static int hf_wkssvc_total_entries = -1;
+static int hf_wkssvc_char_wait = -1;
+static int hf_wkssvc_collection_time = -1;
+static int hf_wkssvc_maximum_collection_count = -1;
+static int hf_wkssvc_keep_conn = -1;
+static int hf_wkssvc_max_cmds = -1;
+static int hf_wkssvc_sess_timeout = -1;
+static int hf_wkssvc_siz_char_buf = -1;
+static int hf_wkssvc_max_threads = -1;
+static int hf_wkssvc_lock_quota = -1;
+static int hf_wkssvc_lock_increment = -1;
+static int hf_wkssvc_lock_maximum = -1;
+static int hf_wkssvc_pipe_increment = -1;
+static int hf_wkssvc_pipe_maximum = -1;
+static int hf_wkssvc_cache_file_timeout = -1;
+static int hf_wkssvc_dormant_file_limit = -1;
+static int hf_wkssvc_read_ahead_throughput = -1;
+static int hf_wkssvc_num_mailslot_buffers = -1;
+static int hf_wkssvc_num_srv_announce_buffers = -1;
+static int hf_wkssvc_max_illegal_datagram_events = -1;
+static int hf_wkssvc_illegal_datagram_event_reset_frequency = -1;
+static int hf_wkssvc_log_election_packets = -1;
+static int hf_wkssvc_use_opportunistic_locking = -1;
+static int hf_wkssvc_use_unlock_behind = -1;
+static int hf_wkssvc_use_close_behind = -1;
+static int hf_wkssvc_buf_named_pipes = -1;
+static int hf_wkssvc_use_lock_read_unlock = -1;
+static int hf_wkssvc_utilize_nt_caching = -1;
+static int hf_wkssvc_use_raw_read = -1;
+static int hf_wkssvc_use_raw_write = -1;
+static int hf_wkssvc_use_write_raw_data = -1;
+static int hf_wkssvc_use_encryption = -1;
+static int hf_wkssvc_buf_files_deny_write = -1;
+static int hf_wkssvc_buf_read_only_files = -1;
+static int hf_wkssvc_force_core_create_mode = -1;
+static int hf_wkssvc_use_512_byte_max_transfer = -1;
+static int hf_wkssvc_parm_err = -1;
+static int hf_wkssvc_errlog_sz = -1;
+static int hf_wkssvc_print_buf_time = -1;
+static int hf_wkssvc_wrk_heuristics = -1;
+static int hf_wkssvc_quality_of_service = -1;
+static int hf_wkssvc_number_of_vcs = -1;
+static int hf_wkssvc_transport_name = -1;
+static int hf_wkssvc_transport_address = -1;
+static int hf_wkssvc_wan_ish = -1;
+static int hf_wkssvc_domain_to_join = -1;
+static int hf_wkssvc_ou_for_computer_account = -1;
+static int hf_wkssvc_account_used_for_join = -1;
+static int hf_wkssvc_encrypted_password = -1;
+static int hf_wkssvc_join_flags = -1;
+static int hf_wkssvc_unjoin_flags = -1;
+static int hf_wkssvc_rename_flags = -1;
+static int hf_wkssvc_join_options_join_type = -1;
+static int hf_wkssvc_join_options_acct_create = -1;
+static int hf_wkssvc_unjoin_options_acct_delete = -1;
+static int hf_wkssvc_join_options_win9x_upgrade = -1;
+static int hf_wkssvc_join_options_domain_join_if_joined = -1;
+static int hf_wkssvc_join_options_join_unsecure = -1;
+static int hf_wkssvc_join_options_machine_pwd_passed = -1;
+static int hf_wkssvc_join_options_defer_spn_set = -1;
+static int hf_wkssvc_account_used_for_unjoin = -1;
+static int hf_wkssvc_alternate_name = -1;
+static int hf_wkssvc_account_used_for_alternate_name = -1;
+static int hf_wkssvc_reserved = -1;
+
+static gint ett_dcerpc_wkssvc = -1;
+static gint ett_dcerpc_wkssvc_join_flags = -1;
+
+
+static e_uuid_t uuid_dcerpc_wkssvc = {
+ 0x6bffd098, 0xa112, 0x3610,
+ { 0x98, 0x33, 0x46, 0xc3, 0xf8, 0x7e, 0x34, 0x5a }
+};
+
+static int
+wkssvc_dissect_ENUM_HANDLE(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_enum_handle, 0);
+ return offset;
+
+}
+
+static guint16 ver_dcerpc_wkssvc = 1;
+
+/*
+ * IDL typedef struct {
+ * IDL long platform_id;
+ * IDL [string] [unique] wchar_t *server;
+ * IDL [string] [unique] wchar_t *lan_grp;
+ * IDL long ver_major;
+ * IDL long ver_minor;
+ * IDL } WKS_INFO_100;
+ */
+static int
+wkssvc_dissect_WKS_INFO_100(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_platform_id, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Net Group", hf_wkssvc_net_group, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_ver_major, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_ver_minor, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long platform_id;
+ * IDL [string] [unique] wchar_t *server;
+ * IDL [string] [unique] wchar_t *lan_grp;
+ * IDL long ver_major;
+ * IDL long ver_minor;
+ * IDL [string] [unique] wchar_t *lan_root;
+ * IDL } WKS_INFO_101;
+ */
+static int
+wkssvc_dissect_WKS_INFO_101(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_platform_id, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Net Group", hf_wkssvc_net_group, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_ver_major, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_ver_minor, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Lan Root", hf_wkssvc_lan_root, 0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long platform_id;
+ * IDL [string] [unique] wchar_t *server;
+ * IDL [string] [unique] wchar_t *lan_grp;
+ * IDL long ver_major;
+ * IDL long ver_minor;
+ * IDL [string] [unique] wchar_t *lan_root;
+ * IDL long logged_on_users;
+ * IDL } WKS_INFO_102;
+ */
+static int
+wkssvc_dissect_WKS_INFO_102(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_platform_id, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server", hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Net Group", hf_wkssvc_net_group, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_ver_major, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_ver_minor, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Lan Root", hf_wkssvc_lan_root, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_logged_on_users, NULL);
+
+ return offset;
+}
+/*
+ * IDL typedef struct {
+ * IDL long wki502_sess_timeout;
+ * IDL } WKS_INFO_502;
+ */
+static int
+wkssvc_dissect_WKS_INFO_502(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_char_wait, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_collection_time, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_maximum_collection_count, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_keep_conn, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_max_cmds, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_sess_timeout, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_siz_char_buf, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_max_threads, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_lock_quota, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_lock_increment, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_lock_maximum, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_pipe_increment, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_pipe_maximum, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_cache_file_timeout, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_dormant_file_limit, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_read_ahead_throughput, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_num_mailslot_buffers, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_num_srv_announce_buffers, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_max_illegal_datagram_events, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_illegal_datagram_event_reset_frequency,
+ NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_log_election_packets, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_use_opportunistic_locking, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_use_unlock_behind, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_use_close_behind, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_buf_named_pipes, NULL);
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_use_lock_read_unlock, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_utilize_nt_caching, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_use_raw_read, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_use_raw_write, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_use_write_raw_data, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_use_encryption, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_buf_files_deny_write, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_buf_read_only_files, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_force_core_create_mode, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_use_512_byte_max_transfer, NULL);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_WKS_INFO_1010(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_char_wait, NULL);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_WKS_INFO_1011(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_collection_time, NULL);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_WKS_INFO_1012(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_maximum_collection_count, NULL);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_WKS_INFO_1013(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_keep_conn, NULL);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_WKS_INFO_1018(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_sess_timeout, NULL);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_WKS_INFO_1023(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_siz_char_buf, NULL);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_WKS_INFO_1027(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_errlog_sz, NULL);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_WKS_INFO_1033(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_max_threads, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetWkstaGetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long level,
+ * IDL [out] [ref] WKS_INFO_UNION *wks
+ * IDL );
+ */
+static int
+wkssvc_dissect_netwkstagetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ dcerpc_info *di;
+ guint32 level;
+
+ di = pinfo->private_data;
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_info_level, &level);
+
+ if (!check_col(pinfo->cinfo, COL_INFO))
+ return offset;
+
+ switch (level) {
+ case 100:
+ col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_100 level");
+ break;
+ case 101:
+ col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_101 level");
+ break;
+ case 102:
+ col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_102 level");
+ break;
+ case 502:
+ col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_502 level");
+ break;
+ default:
+ col_append_str(pinfo->cinfo, COL_INFO, ", WKS_INFO_xxx level");
+ }
+
+ return offset;
+
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(100)] [unique] WKS_INFO_100 *wks100;
+ * IDL [case(101)] [unique] WKS_INFO_101 *wks101;
+ * IDL [case(102)] [unique] WKS_INFO_102 *wks102;
+ * IDL [case(502)] [unique] WKS_INFO_502 *wks502;
+ * IDL [case(1010)] [unique] WKS_INFO_1010 *wks1010;
+ * IDL [case(1011)] [unique] WKS_INFO_1011 *wks1011;
+ * IDL [case(1012)] [unique] WKS_INFO_1012 *wks1012;
+ * IDL [case(1013)] [unique] WKS_INFO_1013 *wks1013;
+ * IDL [case(1018)] [unique] WKS_INFO_1018 *wks1018;
+ * IDL [case(1023)] [unique] WKS_INFO_1023 *wks1023;
+ * IDL [case(1027)] [unique] WKS_INFO_1027 *wks1027;
+ * IDL [case(1033)] [unique] WKS_INFO_1033 *wks1033;
+ * IDL } WKS_INFO_UNION;
+ */
+static int
+wkssvc_dissect_WKS_GETINFO_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_wkssvc_info_level, &level);
+
+ switch(level){
+ case 100:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_100,
+ NDR_POINTER_UNIQUE, "WKS_INFO_100:", -1);
+ break;
+
+ case 101:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_101,
+ NDR_POINTER_UNIQUE, "WKS_INFO_101:", -1);
+ break;
+
+ case 102:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_102,
+ NDR_POINTER_UNIQUE, "WKS_INFO_102:", -1);
+ break;
+
+ /* There is a 302 and 402 level, but I am too lazy today */
+
+ case 502:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_502,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_502:", -1);
+ break;
+
+ case 1010:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_1010,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_1010:", -1);
+ break;
+
+ case 1011:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_1011,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_1011:", -1);
+ break;
+
+ case 1012:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_1012,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_1012:", -1);
+ break;
+
+ case 1013:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_1013,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_1013:", -1);
+ break;
+
+ case 1018:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_1018,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_1018:", -1);
+ break;
+
+ case 1023:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_1023,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_1023:", -1);
+ break;
+
+ case 1027:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_1027,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_1027:", -1);
+ break;
+
+ case 1033:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_1033,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_1033:", -1);
+ break;
+
+ /* case 1018:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_INFO_1018,
+ NDR_POINTER_UNIQUE,
+ "WKS_INFO_1018:", -1);
+ break; */
+
+ }
+
+ return offset;
+
+}
+
+static int wkssvc_dissect_netwkstagetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_GETINFO_UNION,
+ NDR_POINTER_REF, "Server Info", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetWkstaSetInfo(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long level,
+ * IDL [in] [ref] WKS_INFO_UNION *wks,
+ * IDL [out] long parm_err
+ * IDL );
+ */
+static int wkssvc_dissect_netwkstasetinfo_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_WKS_GETINFO_UNION,
+ NDR_POINTER_REF, "Server Info", -1);
+
+ return offset;
+
+}
+
+static int wkssvc_dissect_netwkstasetinfo_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_parm_err, 0);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_rc, NULL);
+
+ return offset;
+
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *dev;
+ * IDL } USER_INFO_0;
+ */
+static int
+wkssvc_dissect_USER_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User Name",
+ hf_wkssvc_user_name, 0);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_USER_INFO_0_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_USER_INFO_0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] USER_INFO_0 *devs;
+ * IDL } USER_INFO_0_CONTAINER;
+ */
+static int
+wkssvc_dissect_USER_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_USER_INFO_0_array, NDR_POINTER_UNIQUE,
+ "USER_INFO_0 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL [string] [unique] wchar_t *user_name;
+ * IDL [string] [unique] wchar_t *logon_domain;
+ * IDL [string] [unique] wchar_t *other_domains;
+ * IDL [string] [unique] wchar_t *logon_server;
+ * IDL } USER_INFO_1;
+ */
+static int
+wkssvc_dissect_USER_INFO_1(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "User Name",
+ hf_wkssvc_user_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Logon Domain",
+ hf_wkssvc_logon_domain, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Other Domains",
+ hf_wkssvc_other_domains, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Logon Server",
+ hf_wkssvc_logon_server, 0);
+
+
+ return offset;
+}
+static int
+wkssvc_dissect_USER_INFO_1_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_USER_INFO_1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] USER_INFO_1 *devs;
+ * IDL } USER_INFO_1_CONTAINER;
+ */
+static int
+wkssvc_dissect_USER_INFO_1_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_USER_INFO_1_array, NDR_POINTER_UNIQUE,
+ "USER_INFO_1 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] USER_INFO_0_CONTAINER *dev0;
+ * IDL [case(1)] [unique] USER_INFO_1_CONTAINER *dev1;
+ * IDL } CHARDEV_ENUM_UNION;
+ */
+static int
+wkssvc_dissect_USER_ENUM_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+ dcerpc_info *di;
+
+ di = pinfo->private_data;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_wkssvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_USER_INFO_0_CONTAINER,
+ NDR_POINTER_UNIQUE, "USER_INFO_0_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", USER_INFO_0 level");
+ break;
+ case 1:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_USER_INFO_1_CONTAINER,
+ NDR_POINTER_UNIQUE, "USER_INFO_1_CONTAINER:", -1);
+ if (check_col(pinfo->cinfo, COL_INFO) && di->ptype == PDU_REQ)
+ col_append_str(pinfo->cinfo, COL_INFO, ", USER_INFO_1 level");
+ break;
+ }
+
+ return offset;
+}
+
+/*
+ * IDL long NetWkstaEnumUsers(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long level,
+ * IDL [in] [out] [ref] WKS_USER_ENUM_STRUCT *users,
+ * IDL [in] long prefmaxlen,
+ * IDL [out] long *entriesread,
+ * IDL [out] long *totalentries,
+ * IDL [in] [out] [ref] long *resumehandle
+ * IDL );
+ */
+static int
+wkssvc_dissect_netwkstaenumusers_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_USER_ENUM_UNION,
+ NDR_POINTER_REF, "User Info", -1);
+ /* Seems to be junk here ... */
+ /* offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_junk, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Junk Handle", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_junk, 0); */
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_pref_max, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+
+}
+
+static int wkssvc_dissect_netwkstaenumusers_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ /* There seems to be an info level there first */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_USER_ENUM_UNION,
+ NDR_POINTER_REF, "User Info", -1);
+
+ /* Entries read seems to be in the enum array ... */
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_total_entries, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long quality_of_service;
+ * IDL long number_of_vcs;
+ * IDL [string] [unique] wchar_t *transport_name;
+ * IDL [string] [unique] wchar_t *transport_address;
+ * IDL BOOL wan_ish;
+ * IDL } TRANSPORT_INFO_0;
+ */
+static int
+wkssvc_dissect_TRANSPORT_INFO_0(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_quality_of_service, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_number_of_vcs, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Transport Name",
+ hf_wkssvc_transport_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Transport Address",
+ hf_wkssvc_transport_address, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_wan_ish, 0);
+
+ return offset;
+}
+
+static int
+wkssvc_dissect_TRANSPORT_INFO_0_array(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_TRANSPORT_INFO_0);
+
+ return offset;
+}
+
+/*
+ * IDL typedef struct {
+ * IDL long EntriesRead;
+ * IDL [size_is(EntriesRead)] [unique] TRANSPORT_INFO_0 *devs;
+ * IDL } TRANSPORT_INFO_0_CONTAINER;
+ */
+static int
+wkssvc_dissect_TRANSPORT_INFO_0_CONTAINER(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_num_entries, NULL);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_TRANSPORT_INFO_0_array, NDR_POINTER_UNIQUE,
+ "TRANSPORT_INFO_0 array:", -1);
+
+ return offset;
+}
+
+/*
+ * IDL typedef [switch_type(long)] union {
+ * IDL [case(0)] [unique] TRANSPORT_INFO_0_CONTAINER *dev0;
+ * IDL } TRANSPORT_ENUM_UNION;
+ */
+static int
+wkssvc_dissect_TRANSPORT_ENUM_UNION(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ guint32 level;
+
+ ALIGN_TO_4_BYTES;
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_wkssvc_info_level, &level);
+
+ switch(level){
+ case 0:
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_TRANSPORT_INFO_0_CONTAINER,
+ NDR_POINTER_UNIQUE, "TRANSPORT_INFO_0_CONTAINER:", -1);
+ break;
+
+ }
+
+ return offset;
+}
+
+/*
+ * IDL long NetWkstaTransportEnum(
+ * IDL [in] [string] [unique] wchar_t *ServerName,
+ * IDL [in] long level,
+ * IDL [in] [out] [ref] WKS_TRANSPORT_ENUM_STRUCT *users,
+ * IDL [in] long prefmaxlen,
+ * IDL [out] long *entriesread,
+ * IDL [out] long *totalentries,
+ * IDL [in] [out] [ref] long *resumehandle
+ * IDL );
+ */
+static int
+wkssvc_dissect_netwkstatransportenum_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_TRANSPORT_ENUM_UNION,
+ NDR_POINTER_REF, "Transport Info", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_pref_max, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ return offset;
+
+}
+
+static int wkssvc_dissect_netwkstatransportenum_reply(tvbuff_t *tvb,
+ int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ guint8 *drep)
+{
+ /* There seems to be an info level there first */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_info_level, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_TRANSPORT_ENUM_UNION,
+ NDR_POINTER_REF, "Transport Info", -1);
+
+ /* Entries read seems to be in the enum array ... */
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_total_entries, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_ENUM_HANDLE,
+ NDR_POINTER_UNIQUE, "Enum Handle", -1);
+
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL typedef struct {
+ * IDL char element_278[524];
+ * IDL } TYPE_30;
+ */
+
+static int
+wkssvc_dissect_TYPE_30(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep _U_)
+{
+ dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
+
+ if(di->conformant_run){
+ return offset; /* cant modify offset while performing conformant run */
+ }
+
+ proto_tree_add_item(tree, hf_wkssvc_encrypted_password, tvb, offset,
+ 524, TRUE);
+ offset += 524;
+
+ return offset;
+}
+
+
+
+/*
+ * IDL
+ * IDL long NetrJoinDomain2(
+ * IDL [in] [unique] [string] wchar_t *ServerName,
+ * IDL [in] [string] wchar_t DomainName,
+ * IDL [in] [unique] [string] wchar_t *AccountOU,
+ * IDL [in] [unique] [string] wchar_t *Account,
+ * IDL [in] [unique] TYPE_30 *Encrypted_password,
+ * IDL [in] long JoinOptions
+ * IDL );
+ */
+
+static const true_false_string join_flags_domain_join = {
+ "Join the computer to a domain",
+ "Join the computer to a workgroup"
+};
+
+static const true_false_string join_flags_acct_create = {
+ "Create the account on the domain",
+ "Do not create the account"
+};
+
+static const true_false_string unjoin_flags_acct_delete = {
+ "Delete the account when a domain is left",
+ "Do not delete the account when a domain is left"
+};
+
+static const true_false_string join_flags_win9x_upgrade = {
+ "The join operation is occuring as part of an upgrade of Windows 9x",
+ "The join operation is not part of a Windows 9x upgrade"
+};
+
+static const true_false_string join_flags_domain_join_if_joined = {
+ "Allow a join to a new domain even if the computer is already joined to a domain",
+ "Do not allow join to a new domain if the computer is already joined to a domain"
+};
+
+static const true_false_string join_flags_unsecure = {
+ "Performs an unsecured join",
+ "Perform a secured join"
+};
+
+static const true_false_string join_flags_machine_pwd_passed = {
+ "Set the machine password after domain join to passed password",
+ "Do not set the machine password after domain join to passed password"
+};
+
+static const true_false_string join_flags_defer_spn_set = {
+ "Defer setting of servicePrincipalName and dNSHostName attributes on the computer object until a rename operation",
+ "Set servicePrincipalName and dNSHostName attributes on the computer object"
+};
+
+
+static int wkssvc_dissect_netr_join_domain2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 join_flags = 0;
+ proto_item *item;
+ proto_tree *tree = NULL;
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
+ NDR_POINTER_UNIQUE, "Server",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_cvstring(tvb, offset, pinfo, parent_tree, drep,
+ sizeof(guint16), hf_wkssvc_domain_to_join,
+ TRUE, NULL);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
+ NDR_POINTER_UNIQUE, "Computer account OU",
+ hf_wkssvc_ou_for_computer_account, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
+ NDR_POINTER_UNIQUE,
+ "Account used for join operation",
+ hf_wkssvc_account_used_for_join, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, parent_tree, drep,
+ wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE,
+ "Encrypted password", -1);
+
+ join_flags = tvb_get_letohl(tvb, offset);
+ item = proto_tree_add_item(parent_tree, hf_wkssvc_join_flags, tvb, offset, 4, TRUE);
+ if (parent_tree) {
+ tree = proto_item_add_subtree(item, ett_dcerpc_wkssvc_join_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_wkssvc_join_options_defer_spn_set, tvb,
+ offset, 4, join_flags);
+
+ proto_tree_add_boolean(tree, hf_wkssvc_join_options_machine_pwd_passed, tvb,
+ offset, 4, join_flags);
+
+ proto_tree_add_boolean(tree, hf_wkssvc_join_options_join_unsecure, tvb,
+ offset, 4, join_flags);
+
+ proto_tree_add_boolean(tree, hf_wkssvc_join_options_domain_join_if_joined,
+ tvb, offset, 4, join_flags);
+
+ proto_tree_add_boolean(tree, hf_wkssvc_join_options_win9x_upgrade, tvb,
+ offset, 4, join_flags);
+
+ proto_tree_add_boolean(tree, hf_wkssvc_join_options_acct_create, tvb,
+ offset, 4, join_flags);
+
+ proto_tree_add_boolean(tree, hf_wkssvc_join_options_join_type, tvb,
+ offset, 4, join_flags);
+ offset += 4;
+
+ return offset;
+}
+
+
+static int wkssvc_dissect_netr_join_domain2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrUnjoinDomain2(
+ * IDL [in] [unique] [string] wchar_t *ServerName,
+ * IDL [in] [unique] [string] wchar_t *Account
+ * IDL [in] [unique] TYPE_30 *Encrypted_password,
+ * IDL [in] long UnjoinOptions
+ * IDL );
+ */
+
+static int wkssvc_dissect_netr_unjoin_domain2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 unjoin_flags = 0;
+ proto_item *item;
+ proto_tree *tree = NULL;
+
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
+ NDR_POINTER_UNIQUE, "Server",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
+ NDR_POINTER_UNIQUE,
+ "Account used for unjoin operation",
+ hf_wkssvc_account_used_for_unjoin, 0);
+
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, parent_tree, drep,
+ wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE,
+ "Encrypted password", -1);
+
+ unjoin_flags = tvb_get_letohl(tvb, offset);
+ item = proto_tree_add_item(parent_tree, hf_wkssvc_unjoin_flags, tvb, offset, 4, TRUE);
+ if (parent_tree) {
+ tree = proto_item_add_subtree(item, ett_dcerpc_wkssvc_join_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_wkssvc_unjoin_options_acct_delete, tvb,
+ offset, 4, unjoin_flags);
+ offset += 4;
+
+ return offset;
+
+}
+
+
+static int wkssvc_dissect_netr_unjoin_domain2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_rc, NULL);
+
+ return offset;
+}
+
+
+
+/*
+ * IDL long NetrRenameMachineInDomain2(
+ * IDL [in] [unique] [string] wchar_t *ServerName,
+ * IDL [in] [unique] [string] wchar_t *NewMachineName,
+ * IDL [in] [unique] [string] wchar_t *Account,
+ * IDL [in] [unique] TYPE_30 *EncryptedPassword,
+ * IDL [in] long RenameOptions
+ * IDL );
+ */
+
+static int wkssvc_dissect_netr_rename_machine_in_domain2_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *parent_tree,
+ guint8 *drep)
+{
+ guint32 rename_flags = 0;
+ proto_item *item;
+ proto_tree *tree = NULL;
+
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
+ NDR_POINTER_UNIQUE, "Server",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
+ NDR_POINTER_UNIQUE,
+ "New Machine Name",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, parent_tree, drep,
+ NDR_POINTER_UNIQUE,
+ "Account used for rename operation",
+ hf_wkssvc_account_used_for_unjoin, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, parent_tree, drep,
+ wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE,
+ "Encrypted password", -1);
+
+ rename_flags = tvb_get_letohl(tvb, offset);
+ item = proto_tree_add_item(parent_tree, hf_wkssvc_rename_flags, tvb, offset, 4, TRUE);
+ if (parent_tree) {
+ tree = proto_item_add_subtree(item, ett_dcerpc_wkssvc_join_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_wkssvc_join_options_acct_create, tvb,
+ offset, 4, rename_flags);
+ offset += 4;
+
+ return offset;
+
+}
+
+static int wkssvc_dissect_netr_rename_machine_in_domain2_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_rc, NULL);
+
+ return offset;
+}
+
+
+/*
+ * IDL long NetrAddAlternateComputerName(
+ * IDL [in] [unique] [string] wchar_t *ServerName,
+ * IDL [in] [unique] [string] wchar_t *NewAlternateMachineName,
+ * IDL [in] [unique] [string] wchar_t *Account,
+ * IDL [in] [unique] TYPE_30 *EncryptedPassword,
+ * IDL [in] long Reserved
+ * IDL );
+ */
+
+static int wkssvc_dissect_netr_add_alternate_computername_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "New alternate computer name",
+ hf_wkssvc_alternate_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Account name",
+ hf_wkssvc_account_used_for_alternate_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE,
+ "Encrypted password", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_reserved, NULL);
+
+ return offset;
+}
+
+static int wkssvc_dissect_netr_add_alternate_computername_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_rc, NULL);
+
+ return offset;
+}
+
+/*
+ * IDL long NetrRemoveAlternateComputerName(
+ * IDL [in] [unique] [string] wchar_t *ServerName,
+ * IDL [in] [unique] [string] wchar_t *AlternateMachineNameToRemove,
+ * IDL [in] [unique] [string] wchar_t *Account,
+ * IDL [in] [unique] TYPE_30 *EncryptedPassword,
+ * IDL [in] long Reserved
+ * IDL );
+ */
+
+static int wkssvc_dissect_netr_remove_alternate_computername_rqst(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Server",
+ hf_wkssvc_server, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Alternate computer name to remove",
+ hf_wkssvc_alternate_name, 0);
+
+ offset = dissect_ndr_str_pointer_item(tvb, offset, pinfo, tree, drep,
+ NDR_POINTER_UNIQUE, "Account name",
+ hf_wkssvc_account_used_for_alternate_name, 0);
+
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ wkssvc_dissect_TYPE_30, NDR_POINTER_UNIQUE,
+ "Encrypted password", -1);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_reserved, NULL);
+
+ return offset;
+}
+
+
+
+static int wkssvc_dissect_netr_remove_alternate_computername_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint8 *drep)
+{
+ offset = dissect_doserror(tvb, offset, pinfo, tree, drep,
+ hf_wkssvc_rc, NULL);
+
+ return offset;
+}
+
+static dcerpc_sub_dissector dcerpc_wkssvc_dissectors[] = {
+ { WKS_NETRWKSTAGETINFO, "NetrWkstaGetInfo",
+ wkssvc_dissect_netwkstagetinfo_rqst,
+ wkssvc_dissect_netwkstagetinfo_reply},
+ { WKS_NETRWKSTASETINFO, "NetrWkstaSetInfo",
+ wkssvc_dissect_netwkstasetinfo_rqst,
+ wkssvc_dissect_netwkstasetinfo_reply},
+ { WKS_NETRWKSTAUSERENUM, "NetrWkstaUserEnum",
+ wkssvc_dissect_netwkstaenumusers_rqst,
+ wkssvc_dissect_netwkstaenumusers_reply},
+ { WKS_NETRWKSTAUSERGETINFO, "NetrWkstaUserGetInfo", NULL, NULL },
+ { WKS_NETRWKSTAUSERSETINFO, "NetrWkstaUserSetInfo", NULL, NULL },
+ { WKS_NETRWKSTATRANSPORTENUM, "NetrWkstaTransportEnum",
+ wkssvc_dissect_netwkstatransportenum_rqst,
+ wkssvc_dissect_netwkstatransportenum_reply},
+ { WKS_NETRWKSTATRANSPORTADD, "NetrWkstaTransportAdd", NULL, NULL },
+ { WKS_NETRWKSTATRANSPORTDEL, "NetrWkstaTransportDel", NULL, NULL },
+ { WKS_NETRUSEADD, "NetrUseAdd", NULL, NULL },
+ { WKS_NETRUSEGETINFO, "NetrUseGetInfo", NULL, NULL },
+ { WKS_NETRUSEDEL, "NetrUseDel", NULL, NULL },
+ { WKS_NETRUSEENUM, "NetrUseEnum", NULL, NULL },
+ { WKS_NETRMESSAGEBUFFERSEND, "NetrMessageBufferSend", NULL, NULL },
+ { WKS_NETRWORKSTATIONSTATISTICSGET, "NetrWorkstationStatisticsGet",
+ NULL, NULL },
+ { WKS_NETRLOGONDOMAINNAMEADD, "NetrLogonDomainNameAdd", NULL, NULL },
+ { WKS_NETRLOGONDOMAINNAMEDEL, "NetrLogonDomainNameDel", NULL, NULL },
+ { WKS_NETRJOINDOMAIN, "NetrJoinDomain", NULL, NULL },
+ { WKS_NETRUNJOINDOMAIN, "NetrUnjoinDomain", NULL, NULL },
+ { WKS_NETRRENAMEMACHINEINDOMAIN, "NetrRenameMachineInDomain",
+ NULL, NULL },
+ { WKS_NETRVALIDATENAME, "NetrValidateName", NULL, NULL },
+ { WKS_NETRGETJOININFORMATION, "NetrGetJoinInformation", NULL, NULL },
+ { WKS_NETRGETJOINABLEOUS, "NetrGetJoinableOUs", NULL, NULL },
+ { WKS_NETRJOINDOMAIN2, "NetrJoinDomain2",
+ wkssvc_dissect_netr_join_domain2_rqst,
+ wkssvc_dissect_netr_join_domain2_reply},
+ { WKS_NETRUNJOINDOMAIN2, "NetrUnjoinDomain2",
+ wkssvc_dissect_netr_unjoin_domain2_rqst,
+ wkssvc_dissect_netr_unjoin_domain2_reply},
+ { WKS_NETRRENAMEMACHINEINDOMAIN2, "NetrRenameMachineInDomain2",
+ wkssvc_dissect_netr_rename_machine_in_domain2_rqst,
+ wkssvc_dissect_netr_rename_machine_in_domain2_reply},
+ { WKS_NETRVALIDATENAME2, "NetrValidateName2", NULL, NULL },
+ { WKS_NETRGETJOINABLEOUS2, "NetrGetJoinableOUs2", NULL, NULL },
+ { WKS_NETRADDALTERNATECOMPUTERNAME, "NetrAddAlternateComputerName",
+ wkssvc_dissect_netr_add_alternate_computername_rqst,
+ wkssvc_dissect_netr_add_alternate_computername_reply},
+ { WKS_NETRREMOVEALTERNATECOMPUTERNAME,
+ "NetrRemoveAlternateComputerName",
+ wkssvc_dissect_netr_remove_alternate_computername_rqst,
+ wkssvc_dissect_netr_remove_alternate_computername_reply},
+ { WKS_NETRSETPRIMARYCOMPUTERNAME, "NetrSetPrimaryComputerName",
+ NULL, NULL },
+ { WKS_NETRENUMERATECOMPUTERNAMES, "NetrEnumerateComputerNames",
+ NULL, NULL },
+ {0, NULL, NULL, NULL }
+};
+
+void
+proto_register_dcerpc_wkssvc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_wkssvc_opnum,
+ { "Operation", "wkssvc.opnum", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_wkssvc_server,
+ { "Server", "wkssvc.server", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Server Name", HFILL}},
+ { &hf_wkssvc_net_group,
+ { "Net Group", "wkssvc.netgrp", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Net Group", HFILL}},
+ { &hf_wkssvc_info_level,
+ { "Info Level", "wkssvc.info_level", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Info Level", HFILL}},
+ { &hf_wkssvc_platform_id,
+ { "Platform ID", "wkssvc.info.platform_id", FT_UINT32,
+ BASE_DEC, VALS(platform_id_vals), 0x0, "Platform ID", HFILL}},
+ { &hf_wkssvc_ver_major,
+ { "Major Version", "wkssvc.version.major", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Major Version", HFILL}},
+ { &hf_wkssvc_ver_minor,
+ { "Minor Version", "wkssvc.version.minor", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Minor Version", HFILL}},
+ { &hf_wkssvc_lan_root,
+ { "Lan Root", "wkssvc.lan.root", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Lan Root", HFILL}},
+ { &hf_wkssvc_logged_on_users,
+ { "Logged On Users", "wkssvc.logged.on.users", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Logged On Users", HFILL}},
+ { &hf_wkssvc_pref_max,
+ { "Preferred Max Len", "wkssvc.pref.max.len", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Preferred Max Len", HFILL}},
+ { &hf_wkssvc_junk,
+ { "Junk", "wkssvc.junk", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "Junk", HFILL}},
+ { &hf_wkssvc_enum_handle,
+ { "Enumeration handle", "wkssvc.enum_hnd", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "Enumeration Handle", HFILL}},
+ { &hf_wkssvc_user_name,
+ { "User Name", "wkssvc.user.name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "User Name", HFILL}},
+ { &hf_wkssvc_logon_domain,
+ { "Logon Domain", "wkssvc.logon.domain", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Logon Domain", HFILL}},
+ { &hf_wkssvc_other_domains,
+ { "Other Domains", "wkssvc.other.domains", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Other Domains", HFILL}},
+ { &hf_wkssvc_logon_server,
+ { "Logon Server", "wkssvc.logon.server", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Logon Server", HFILL}},
+ { &hf_wkssvc_rc,
+ { "Return code", "wkssvc.rc", FT_UINT32,
+ BASE_HEX, VALS(DOS_errors), 0x0, "Return Code", HFILL}},
+ { &hf_wkssvc_num_entries,
+ { "Num Entries", "wkssvc.num.entries", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Num Entries", HFILL}},
+ { &hf_wkssvc_entries_read,
+ { "Entries Read", "wkssvc.entries.read", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Entries Read", HFILL}},
+ { &hf_wkssvc_total_entries,
+ { "Total Entries", "wkssvc.total.entries", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Total Entries", HFILL}},
+ { &hf_wkssvc_char_wait,
+ { "Char Wait", "wkssvc.char.wait", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Char Wait", HFILL}},
+ { &hf_wkssvc_collection_time,
+ { "Collection Time", "wkssvc.collection.time", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Collection Time", HFILL}},
+ { &hf_wkssvc_maximum_collection_count,
+ { "Maximum Collection Count", "wkssvc.maximum.collection.count",
+ FT_INT32,
+ BASE_DEC, NULL, 0x0, "Maximum Collection Count", HFILL}},
+ { &hf_wkssvc_keep_conn,
+ { "Keep Connection", "wkssvc.keep.connection", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Keep Connection", HFILL}},
+ { &hf_wkssvc_max_cmds,
+ { "Maximum Commands", "wkssvc.maximum.commands", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Maximum Commands", HFILL}},
+ { &hf_wkssvc_sess_timeout,
+ { "Session Timeout", "wkssvc.session.timeout", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Session Timeout", HFILL}},
+ { &hf_wkssvc_siz_char_buf,
+ { "Character Buffer Size", "wkssvc.size.char.buff", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Character Buffer Size", HFILL}},
+ { &hf_wkssvc_max_threads,
+ { "Maximum Threads", "wkssvc.maximum.threads", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Maximum Threads", HFILL}},
+ { &hf_wkssvc_lock_quota,
+ { "Lock Quota", "wkssvc.lock.quota", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Lock Quota", HFILL}},
+ { &hf_wkssvc_lock_increment,
+ { "Lock Increment", "wkssvc.lock.increment", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Lock Increment", HFILL}},
+ { &hf_wkssvc_lock_maximum,
+ { "Lock Maximum", "wkssvc.lock.maximum", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Lock Maximum", HFILL}},
+ { &hf_wkssvc_pipe_increment,
+ { "Pipe Increment", "wkssvc.pipe.increment", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Pipe Increment", HFILL}},
+ { &hf_wkssvc_pipe_maximum,
+ { "Pipe Maximum", "wkssvc.pipe.maximum", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Pipe Maximum", HFILL}},
+ { &hf_wkssvc_cache_file_timeout,
+ { "Cache File Timeout", "wkssvc.cache.file.timeout", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Cache File Timeout", HFILL}},
+ { &hf_wkssvc_dormant_file_limit,
+ { "Dormant File Limit", "wkssvc.dormant.file.limit", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Dormant File Limit", HFILL}},
+ { &hf_wkssvc_read_ahead_throughput,
+ { "Read Ahead Throughput", "wkssvc.read.ahead.throughput", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Read Ahead Throughput", HFILL}},
+ { &hf_wkssvc_num_mailslot_buffers,
+ { "Num Mailslot Buffers", "wkssvc.num.mailslot.buffers", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Num Mailslot Buffers", HFILL}},
+ { &hf_wkssvc_num_srv_announce_buffers,
+ { "Num Srv Announce Buffers", "wkssvc.num.srv.announce.buffers", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Num Srv Announce Buffers", HFILL}},
+ { &hf_wkssvc_max_illegal_datagram_events,
+ { "Max Illegal Datagram Events", "wkssvc.max.illegal.datagram.events", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Max Illegal Datagram Events", HFILL}},
+ { &hf_wkssvc_illegal_datagram_event_reset_frequency,
+ { "Illegal Datagram Event Reset Frequency", "wkssvc.illegal.datagram.reset.frequency", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Illegal Datagram Event Reset Frequency", HFILL}},
+ { &hf_wkssvc_log_election_packets,
+ { "Log Election Packets", "wkssvc.log.election.packets", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Log Election Packets", HFILL}},
+ { &hf_wkssvc_use_opportunistic_locking,
+ { "Use Opportunistic Locking", "wkssvc.use.oplocks", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Use OpLocks", HFILL}},
+ { &hf_wkssvc_use_unlock_behind,
+ { "Use Lock Behind", "wkssvc.use.lock.behind", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Use Lock Behind", HFILL}},
+ { &hf_wkssvc_use_close_behind,
+ { "Use Close Behind", "wkssvc.use.close.behind", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Use Close Behind", HFILL}},
+ { &hf_wkssvc_buf_named_pipes,
+ { "Buffer Named Pipes", "wkssvc.buffer.named.pipes", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Buffer Named Pipes", HFILL}},
+ { &hf_wkssvc_use_lock_read_unlock,
+ { "Use Lock Read Unlock", "wkssvc.use.lock.read.unlock", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Use Lock Read Unlock", HFILL}},
+ { &hf_wkssvc_utilize_nt_caching,
+ { "Utilize NT Caching", "wkssvc.utilize.nt.caching", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Utilize NT Caching", HFILL}},
+ { &hf_wkssvc_use_raw_read,
+ { "Use Raw Read", "wkssvc.use.raw.read", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Use Raw Read", HFILL}},
+ { &hf_wkssvc_use_raw_write,
+ { "Use Raw Write", "wkssvc.use.raw.write", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Use Raw Write", HFILL}},
+ { &hf_wkssvc_use_write_raw_data,
+ { "Use Write Raw Data", "wkssvc.use.write.raw.data", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Use Write Raw Data", HFILL}},
+ { &hf_wkssvc_use_encryption,
+ { "Use Encryption", "wkssvc.use.encryption", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Use Encryption", HFILL}},
+ { &hf_wkssvc_buf_files_deny_write,
+ { "Buffer Files Deny Write", "wkssvc.buf.files.deny.write", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Buffer Files Deny Write", HFILL}},
+ { &hf_wkssvc_buf_read_only_files,
+ { "Buffer Files Read Only", "wkssvc.buf.files.read.only", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Buffer Files Read Only", HFILL}},
+ { &hf_wkssvc_force_core_create_mode,
+ { "Force Core Create Mode", "wkssvc.force.core.create.mode", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Force Core Create Mode", HFILL}},
+ { &hf_wkssvc_use_512_byte_max_transfer,
+ { "Use 512 Byte Max Transfer", "wkssvc.use.512.byte.max.transfer", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Use 512 Byte Maximum Transfer", HFILL}},
+ { &hf_wkssvc_parm_err,
+ { "Parameter Error Offset", "wkssvc.parm.err", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Parameter Error Offset", HFILL}},
+ { &hf_wkssvc_errlog_sz,
+ { "Error Log Size", "wkssvc.errlog.sz", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Error Log Size", HFILL}},
+ { &hf_wkssvc_print_buf_time,
+ { "Print Buf Time", "wkssvc.print.buf.time", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Print Buff Time", HFILL}},
+ { &hf_wkssvc_wrk_heuristics,
+ { "Wrk Heuristics", "wkssvc.wrk.heuristics", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Wrk Heuristics", HFILL}},
+ { &hf_wkssvc_quality_of_service,
+ { "Quality Of Service", "wkssvc.qos", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Quality Of Service", HFILL}},
+ { &hf_wkssvc_number_of_vcs,
+ { "Number Of VCs", "wkssvc.number.of.vcs", FT_INT32,
+ BASE_DEC, NULL, 0x0, "Number of VSs", HFILL}},
+ { &hf_wkssvc_transport_name,
+ { "Transport Name", "wkssvc.transport.name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Transport Name", HFILL}},
+ { &hf_wkssvc_transport_address,
+ { "Transport Address", "wkssvc.transport.address", FT_STRING,
+ BASE_NONE,
+ NULL, 0x0, "Transport Address", HFILL}},
+ { &hf_wkssvc_wan_ish,
+ { "WAN ish", "wkssvc.wan.ish", FT_INT32,
+ BASE_DEC, NULL, 0x0, "WAN ish", HFILL}},
+ { &hf_wkssvc_domain_to_join,
+ { "Domain or Workgroup to join", "wkssvc.join.domain", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Domain or Workgroup to join", HFILL}},
+ { &hf_wkssvc_ou_for_computer_account,
+ { "Organizational Unit (OU) for computer account",
+ "wkssvc.join.computer_account_ou", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Organizational Unit (OU) for computer account", HFILL}},
+ { &hf_wkssvc_account_used_for_join,
+ { "Account used for join operations", "wkssvc.join.account_used", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Account used for join operations", HFILL}},
+ { &hf_wkssvc_join_flags,
+ { "Domain join flags", "wkssvc.join.flags",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Domain join flags", HFILL }},
+ { &hf_wkssvc_unjoin_flags,
+ { "Domain unjoin flags", "wkssvc.unjoin.flags",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Domain unjoin flags", HFILL }},
+ { &hf_wkssvc_rename_flags,
+ { "Machine rename flags", "wkssvc.rename.flags",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Machine rename flags", HFILL }},
+ { &hf_wkssvc_join_options_join_type,
+ { "Join type", "wkssvc.join.options.join_type",
+ FT_BOOLEAN, 32, TFS(&join_flags_domain_join), 0x00000001,
+ "Join type", HFILL}},
+ { &hf_wkssvc_join_options_acct_create,
+ { "Computer account creation", "wkssvc.join.options.account_create",
+ FT_BOOLEAN, 32, TFS(&join_flags_acct_create), 0x00000002,
+ "Computer account creation", HFILL}},
+ { &hf_wkssvc_unjoin_options_acct_delete,
+ { "Computer account deletion", "wkssvc.unjoin.options.account_delete",
+ FT_BOOLEAN, 32, TFS(&unjoin_flags_acct_delete), 0x00000004,
+ "Computer account deletion", HFILL}},
+ { &hf_wkssvc_join_options_win9x_upgrade,
+ { "Win9x upgrade", "wkssvc.join.options.win9x_upgrade",
+ FT_BOOLEAN, 32, TFS(&join_flags_win9x_upgrade), 0x00000010,
+ "Win9x upgrade", HFILL}},
+ { &hf_wkssvc_join_options_domain_join_if_joined,
+ { "New domain join if already joined",
+ "wkssvc.join.options.domain_join_if_joined",
+ FT_BOOLEAN, 32, TFS(&join_flags_domain_join_if_joined),
+ 0x00000020,
+ "New domain join if already joined", HFILL}},
+ { &hf_wkssvc_join_options_join_unsecure,
+ { "Unsecure join", "wkssvc.join.options.insecure_join",
+ FT_BOOLEAN, 32, TFS(&join_flags_unsecure),
+ 0x00000040, "Unsecure join", HFILL}},
+ { &hf_wkssvc_join_options_machine_pwd_passed,
+ { "Machine pwd passed", "wkssvc.join.options.machine_pwd_passed",
+ FT_BOOLEAN, 32, TFS(&join_flags_machine_pwd_passed),
+ 0x00000080, "Machine pwd passed", HFILL}},
+ { &hf_wkssvc_join_options_defer_spn_set,
+ { "Defer SPN set", "wkssvc.join.options.defer_spn_set",
+ FT_BOOLEAN, 32, TFS(&join_flags_defer_spn_set),
+ 0x00000100, "Defer SPN set", HFILL}},
+ { &hf_wkssvc_account_used_for_unjoin,
+ { "Account used for unjoin operations",
+ "wkssvc.unjoin.account_used", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Account used for unjoin operations", HFILL}},
+ { &hf_wkssvc_account_used_for_alternate_name,
+ { "Account used for alternate name operations",
+ "wkssvc.alternate_operations_account", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Account used for alternate name operations", HFILL}},
+ { &hf_wkssvc_alternate_name,
+ { "Alternate computer name", "wkssvc.alternate_computer_name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Alternate computer name", HFILL}},
+ { &hf_wkssvc_encrypted_password,
+ { "Encrypted password", "wkssvc.crypt_password", FT_BYTES, BASE_HEX,
+ NULL, 0, "Encrypted Password", HFILL }},
+ { &hf_wkssvc_reserved,
+ { "Reserved field", "wkssvc.reserved", FT_INT32,
+ BASE_HEX, NULL, 0x0, "Reserved field", HFILL}},
+ };
+ static gint *ett[] = {
+ &ett_dcerpc_wkssvc,
+ &ett_dcerpc_wkssvc_join_flags
+ };
+
+ proto_dcerpc_wkssvc = proto_register_protocol(
+ "Microsoft Workstation Service", "WKSSVC", "wkssvc");
+
+ proto_register_field_array(proto_dcerpc_wkssvc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dcerpc_wkssvc(void)
+{
+ /* Register protocol as dcerpc */
+
+ dcerpc_init_uuid(proto_dcerpc_wkssvc, ett_dcerpc_wkssvc,
+ &uuid_dcerpc_wkssvc, ver_dcerpc_wkssvc,
+ dcerpc_wkssvc_dissectors, hf_wkssvc_opnum);
+}
diff --git a/epan/dissectors/packet-dcerpc-wkssvc.h b/epan/dissectors/packet-dcerpc-wkssvc.h
new file mode 100644
index 0000000000..5b442ba764
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc-wkssvc.h
@@ -0,0 +1,66 @@
+/* packet-dcerpc-wkssvc.h
+ * Routines for SMB \PIPE\wkssvc packet disassembly
+ * Copyright 2001, Tim Potter <tpot@samba.org>
+ * Copyright 2002, Richard Sharpe <rsharpe@richardsharpe.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_WKSSVC_H
+#define __PACKET_DCERPC_WKSSVC_H
+
+/* Functions available on the WKSSVC pipe. From Samba, include/rpc_wkssvc.h */
+
+#define WKS_NETRWKSTAGETINFO 0x00
+#define WKS_NETRWKSTASETINFO 0x01
+#define WKS_NETRWKSTAUSERENUM 0x02
+#define WKS_NETRWKSTAUSERGETINFO 0x03
+#define WKS_NETRWKSTAUSERSETINFO 0x04
+#define WKS_NETRWKSTATRANSPORTENUM 0x05
+#define WKS_NETRWKSTATRANSPORTADD 0x06
+#define WKS_NETRWKSTATRANSPORTDEL 0x07
+#define WKS_NETRUSEADD 0x08
+#define WKS_NETRUSEGETINFO 0x09
+#define WKS_NETRUSEDEL 0x0a
+#define WKS_NETRUSEENUM 0x0b
+#define WKS_NETRMESSAGEBUFFERSEND 0x0c
+#define WKS_NETRWORKSTATIONSTATISTICSGET 0x0d
+#define WKS_NETRLOGONDOMAINNAMEADD 0x0e
+#define WKS_NETRLOGONDOMAINNAMEDEL 0x0f
+#define WKS_NETRJOINDOMAIN 0x10
+#define WKS_NETRUNJOINDOMAIN 0x11
+#define WKS_NETRRENAMEMACHINEINDOMAIN 0x12
+#define WKS_NETRVALIDATENAME 0x13
+#define WKS_NETRGETJOININFORMATION 0x14
+#define WKS_NETRGETJOINABLEOUS 0x15
+#define WKS_NETRJOINDOMAIN2 0x16
+#define WKS_NETRUNJOINDOMAIN2 0x17
+#define WKS_NETRRENAMEMACHINEINDOMAIN2 0x18
+#define WKS_NETRVALIDATENAME2 0x19
+#define WKS_NETRGETJOINABLEOUS2 0x1a
+#define WKS_NETRADDALTERNATECOMPUTERNAME 0x1b
+#define WKS_NETRREMOVEALTERNATECOMPUTERNAME 0x1c
+#define WKS_NETRSETPRIMARYCOMPUTERNAME 0x1d
+#define WKS_NETRENUMERATECOMPUTERNAMES 0x1e
+
+
+
+#endif /* packet-dcerpc-wkssvc.h */
diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c
new file mode 100644
index 0000000000..afcafacf5a
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc.c
@@ -0,0 +1,4779 @@
+/* packet-dcerpc.c
+ * Routines for DCERPC packet disassembly
+ * Copyright 2001, Todd Sabin <tas@webspan.net>
+ * Copyright 2003, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/dissectors/packet-dcerpc.h>
+#include <epan/conversation.h>
+#include "prefs.h"
+#include "reassemble.h"
+#include "tap.h"
+#include <epan/dissectors/packet-frame.h>
+#include <epan/dissectors/packet-dcerpc-nt.h>
+
+static int dcerpc_tap = -1;
+
+
+static const value_string pckt_vals[] = {
+ { PDU_REQ, "Request"},
+ { PDU_PING, "Ping"},
+ { PDU_RESP, "Response"},
+ { PDU_FAULT, "Fault"},
+ { PDU_WORKING, "Working"},
+ { PDU_NOCALL, "Nocall"},
+ { PDU_REJECT, "Reject"},
+ { PDU_ACK, "Ack"},
+ { PDU_CL_CANCEL, "Cl_cancel"},
+ { PDU_FACK, "Fack"},
+ { PDU_CANCEL_ACK, "Cancel_ack"},
+ { PDU_BIND, "Bind"},
+ { PDU_BIND_ACK, "Bind_ack"},
+ { PDU_BIND_NAK, "Bind_nak"},
+ { PDU_ALTER, "Alter_context"},
+ { PDU_ALTER_ACK, "Alter_context_resp"},
+ { PDU_AUTH3, "AUTH3"},
+ { PDU_SHUTDOWN, "Shutdown"},
+ { PDU_CO_CANCEL, "Co_cancel"},
+ { PDU_ORPHANED, "Orphaned"},
+ { 0, NULL }
+};
+
+static const value_string drep_byteorder_vals[] = {
+ { 0, "Big-endian" },
+ { 1, "Little-endian" },
+ { 0, NULL }
+};
+
+static const value_string drep_character_vals[] = {
+ { 0, "ASCII" },
+ { 1, "EBCDIC" },
+ { 0, NULL }
+};
+
+#define DCE_RPC_DREP_FP_IEEE 0
+#define DCE_RPC_DREP_FP_VAX 1
+#define DCE_RPC_DREP_FP_CRAY 2
+#define DCE_RPC_DREP_FP_IBM 3
+
+static const value_string drep_fp_vals[] = {
+ { DCE_RPC_DREP_FP_IEEE, "IEEE" },
+ { DCE_RPC_DREP_FP_VAX, "VAX" },
+ { DCE_RPC_DREP_FP_CRAY, "Cray" },
+ { DCE_RPC_DREP_FP_IBM, "IBM" },
+ { 0, NULL }
+};
+
+/*
+ * Authentication services.
+ */
+static const value_string authn_protocol_vals[] = {
+ { DCE_C_RPC_AUTHN_PROTOCOL_NONE, "None" },
+ { DCE_C_RPC_AUTHN_PROTOCOL_KRB5, "Kerberos 5" },
+ { DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO, "SPNEGO" },
+ { DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, "NTLMSSP" },
+ { DCE_C_RPC_AUTHN_PROTOCOL_GSS_SCHANNEL, "SCHANNEL SSP" },
+ { DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS, "Kerberos SSP" },
+ { DCE_C_RPC_AUTHN_PROTOCOL_DPA,
+ "Distributed Password Authentication SSP"},
+ { DCE_C_RPC_AUTHN_PROTOCOL_MSN, "MSN SSP"},
+ { DCE_C_RPC_AUTHN_PROTOCOL_DIGEST, "Digest SSP"},
+ { DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN,"NETLOGON Secure Channel" },
+ { DCE_C_RPC_AUTHN_PROTOCOL_MQ, "MSMQ SSP"},
+ { 0, NULL }
+};
+
+/*
+ * Protection levels.
+ */
+static const value_string authn_level_vals[] = {
+ { DCE_C_AUTHN_LEVEL_NONE, "None" },
+ { DCE_C_AUTHN_LEVEL_CONNECT, "Connect" },
+ { DCE_C_AUTHN_LEVEL_CALL, "Call" },
+ { DCE_C_AUTHN_LEVEL_PKT, "Packet" },
+ { DCE_C_AUTHN_LEVEL_PKT_INTEGRITY, "Packet integrity" },
+ { DCE_C_AUTHN_LEVEL_PKT_PRIVACY, "Packet privacy" },
+ { 0, NULL }
+};
+
+/*
+ * Flag bits in first flag field in connectionless PDU header.
+ */
+#define PFCL1_RESERVED_01 0x01 /* Reserved for use by implementations */
+#define PFCL1_LASTFRAG 0x02 /* If set, the PDU is the last
+ * fragment of a multi-PDU
+ * transmission */
+#define PFCL1_FRAG 0x04 /* If set, the PDU is a fragment of
+ a multi-PDU transmission */
+#define PFCL1_NOFACK 0x08 /* If set, the receiver is not
+ * requested to send a `fack' PDU
+ * for the fragment */
+#define PFCL1_MAYBE 0x10 /* If set, the PDU is for a `maybe'
+ * request */
+#define PFCL1_IDEMPOTENT 0x20 /* If set, the PDU is for an idempotent
+ * request */
+#define PFCL1_BROADCAST 0x40 /* If set, the PDU is for a broadcast
+ * request */
+#define PFCL1_RESERVED_80 0x80 /* Reserved for use by implementations */
+
+/*
+ * Flag bits in second flag field in connectionless PDU header.
+ */
+#define PFCL2_RESERVED_01 0x01 /* Reserved for use by implementations */
+#define PFCL2_CANCEL_PENDING 0x02 /* Cancel pending at the call end */
+#define PFCL2_RESERVED_04 0x04 /* Reserved for future use */
+#define PFCL2_RESERVED_08 0x08 /* Reserved for future use */
+#define PFCL2_RESERVED_10 0x10 /* Reserved for future use */
+#define PFCL2_RESERVED_20 0x20 /* Reserved for future use */
+#define PFCL2_RESERVED_40 0x40 /* Reserved for future use */
+#define PFCL2_RESERVED_80 0x80 /* Reserved for future use */
+
+/*
+ * Flag bits in connection-oriented PDU header.
+ */
+#define PFC_FIRST_FRAG 0x01 /* First fragment */
+#define PFC_LAST_FRAG 0x02 /* Last fragment */
+#define PFC_PENDING_CANCEL 0x04 /* Cancel was pending at sender */
+#define PFC_RESERVED_1 0x08
+#define PFC_CONC_MPX 0x10 /* suports concurrent multiplexing
+ * of a single connection. */
+#define PFC_DID_NOT_EXECUTE 0x20 /* only meaningful on `fault' packet;
+ * if true, guaranteed call did not
+ * execute. */
+#define PFC_MAYBE 0x40 /* `maybe' call semantics requested */
+#define PFC_OBJECT_UUID 0x80 /* if true, a non-nil object UUID
+ * was specified in the handle, and
+ * is present in the optional object
+ * field. If false, the object field
+ * is omitted. */
+
+/*
+ * Tests whether a connection-oriented PDU is fragmented; returns TRUE if
+ * it's not fragmented (i.e., this is both the first *and* last fragment),
+ * and FALSE otherwise.
+ */
+#define PFC_NOT_FRAGMENTED(hdr) \
+ ((hdr->flags&(PFC_FIRST_FRAG|PFC_LAST_FRAG))==(PFC_FIRST_FRAG|PFC_LAST_FRAG))
+
+/*
+ * Presentation context negotiation result.
+ */
+static const value_string p_cont_result_vals[] = {
+ { 0, "Acceptance" },
+ { 1, "User rejection" },
+ { 2, "Provider rejection" },
+ { 0, NULL }
+};
+
+/*
+ * Presentation context negotiation rejection reasons.
+ */
+static const value_string p_provider_reason_vals[] = {
+ { 0, "Reason not specified" },
+ { 1, "Abstract syntax not supported" },
+ { 2, "Proposed transfer syntaxes not supported" },
+ { 3, "Local limit exceeded" },
+ { 0, NULL }
+};
+
+/*
+ * Reject reasons.
+ */
+#define REASON_NOT_SPECIFIED 0
+#define TEMPORARY_CONGESTION 1
+#define LOCAL_LIMIT_EXCEEDED 2
+#define CALLED_PADDR_UNKNOWN 3 /* not used */
+#define PROTOCOL_VERSION_NOT_SUPPORTED 4
+#define DEFAULT_CONTEXT_NOT_SUPPORTED 5 /* not used */
+#define USER_DATA_NOT_READABLE 6 /* not used */
+#define NO_PSAP_AVAILABLE 7 /* not used */
+
+static const value_string reject_reason_vals[] = {
+ { REASON_NOT_SPECIFIED, "Reason not specified" },
+ { TEMPORARY_CONGESTION, "Temporary congestion" },
+ { LOCAL_LIMIT_EXCEEDED, "Local limit exceeded" },
+ { CALLED_PADDR_UNKNOWN, "Called paddr unknown" },
+ { PROTOCOL_VERSION_NOT_SUPPORTED, "Protocol version not supported" },
+ { DEFAULT_CONTEXT_NOT_SUPPORTED, "Default context not supported" },
+ { USER_DATA_NOT_READABLE, "User data not readable" },
+ { NO_PSAP_AVAILABLE, "No PSAP available" },
+ { 0, NULL }
+};
+
+/*
+ * Reject status codes.
+ */
+static const value_string reject_status_vals[] = {
+ { 0, "Stub-defined exception" },
+ { 0x1c000001, "nca_s_fault_int_div_by_zero" },
+ { 0x1c000002, "nca_s_fault_addr_error" },
+ { 0x1c000003, "nca_s_fault_fp_div_zero" },
+ { 0x1c000004, "nca_s_fault_fp_underflow" },
+ { 0x1c000005, "nca_s_fault_fp_overflow" },
+ { 0x1c000006, "nca_s_fault_invalid_tag" },
+ { 0x1c000007, "nca_s_fault_invalid_bound" },
+ { 0x1c000008, "nca_rpc_version_mismatch" },
+ { 0x1c000009, "nca_unspec_reject" },
+ { 0x1c00000a, "nca_s_bad_actid" },
+ { 0x1c00000b, "nca_who_are_you_failed" },
+ { 0x1c00000c, "nca_manager_not_entered" },
+ { 0x1c00000d, "nca_s_fault_cancel" },
+ { 0x1c00000e, "nca_s_fault_ill_inst" },
+ { 0x1c00000f, "nca_s_fault_fp_error" },
+ { 0x1c000010, "nca_s_fault_int_overflow" },
+ { 0x1c000014, "nca_s_fault_pipe_empty" },
+ { 0x1c000015, "nca_s_fault_pipe_closed" },
+ { 0x1c000016, "nca_s_fault_pipe_order" },
+ { 0x1c000017, "nca_s_fault_pipe_discipline" },
+ { 0x1c000018, "nca_s_fault_pipe_comm_error" },
+ { 0x1c000019, "nca_s_fault_pipe_memory" },
+ { 0x1c00001a, "nca_s_fault_context_mismatch" },
+ { 0x1c00001b, "nca_s_fault_remote_no_memory" },
+ { 0x1c00001c, "nca_invalid_pres_context_id" },
+ { 0x1c00001d, "nca_unsupported_authn_level" },
+ { 0x1c00001f, "nca_invalid_checksum" },
+ { 0x1c000020, "nca_invalid_crc" },
+ { 0x1c000021, "ncs_s_fault_user_defined" },
+ { 0x1c000022, "nca_s_fault_tx_open_failed" },
+ { 0x1c000023, "nca_s_fault_codeset_conv_error" },
+ { 0x1c000024, "nca_s_fault_object_not_found" },
+ { 0x1c000025, "nca_s_fault_no_client_stub" },
+ { 0x1c010002, "nca_op_rng_error" },
+ { 0x1c010003, "nca_unk_if"},
+ { 0x1c010006, "nca_wrong_boot_time" },
+ { 0x1c010009, "nca_s_you_crashed" },
+ { 0x1c01000b, "nca_proto_error" },
+ { 0x1c010013, "nca_out_args_too_big" },
+ { 0x1c010014, "nca_server_too_busy" },
+ { 0x1c010017, "nca_unsupported_type" },
+ { 0, NULL }
+};
+
+
+/* we need to keep track of what transport were used, ie what handle we came
+ * in through so we know what kind of pinfo->private_data was passed to us.
+ */
+#define DCE_TRANSPORT_UNKNOWN 0
+#define DCE_CN_TRANSPORT_SMBPIPE 1
+
+
+static int proto_dcerpc = -1;
+
+/* field defines */
+static int hf_dcerpc_request_in = -1;
+static int hf_dcerpc_time = -1;
+static int hf_dcerpc_response_in = -1;
+static int hf_dcerpc_ver = -1;
+static int hf_dcerpc_ver_minor = -1;
+static int hf_dcerpc_packet_type = -1;
+static int hf_dcerpc_cn_flags = -1;
+static int hf_dcerpc_cn_flags_first_frag = -1;
+static int hf_dcerpc_cn_flags_last_frag = -1;
+static int hf_dcerpc_cn_flags_cancel_pending = -1;
+static int hf_dcerpc_cn_flags_reserved = -1;
+static int hf_dcerpc_cn_flags_mpx = -1;
+static int hf_dcerpc_cn_flags_dne = -1;
+static int hf_dcerpc_cn_flags_maybe = -1;
+static int hf_dcerpc_cn_flags_object = -1;
+static int hf_dcerpc_drep = -1;
+static int hf_dcerpc_drep_byteorder = -1;
+static int hf_dcerpc_drep_character = -1;
+static int hf_dcerpc_drep_fp = -1;
+static int hf_dcerpc_cn_frag_len = -1;
+static int hf_dcerpc_cn_auth_len = -1;
+static int hf_dcerpc_cn_call_id = -1;
+static int hf_dcerpc_cn_max_xmit = -1;
+static int hf_dcerpc_cn_max_recv = -1;
+static int hf_dcerpc_cn_assoc_group = -1;
+static int hf_dcerpc_cn_num_ctx_items = -1;
+static int hf_dcerpc_cn_ctx_id = -1;
+static int hf_dcerpc_cn_num_trans_items = -1;
+static int hf_dcerpc_cn_bind_if_id = -1;
+static int hf_dcerpc_cn_bind_if_ver = -1;
+static int hf_dcerpc_cn_bind_if_ver_minor = -1;
+static int hf_dcerpc_cn_bind_trans_id = -1;
+static int hf_dcerpc_cn_bind_trans_ver = -1;
+static int hf_dcerpc_cn_alloc_hint = -1;
+static int hf_dcerpc_cn_sec_addr_len = -1;
+static int hf_dcerpc_cn_sec_addr = -1;
+static int hf_dcerpc_cn_num_results = -1;
+static int hf_dcerpc_cn_ack_result = -1;
+static int hf_dcerpc_cn_ack_reason = -1;
+static int hf_dcerpc_cn_ack_trans_id = -1;
+static int hf_dcerpc_cn_ack_trans_ver = -1;
+static int hf_dcerpc_cn_reject_reason = -1;
+static int hf_dcerpc_cn_num_protocols = -1;
+static int hf_dcerpc_cn_protocol_ver_major = -1;
+static int hf_dcerpc_cn_protocol_ver_minor = -1;
+static int hf_dcerpc_cn_cancel_count = -1;
+static int hf_dcerpc_cn_status = -1;
+static int hf_dcerpc_auth_type = -1;
+static int hf_dcerpc_auth_level = -1;
+static int hf_dcerpc_auth_pad_len = -1;
+static int hf_dcerpc_auth_rsrvd = -1;
+static int hf_dcerpc_auth_ctx_id = -1;
+static int hf_dcerpc_dg_flags1 = -1;
+static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
+static int hf_dcerpc_dg_flags1_last_frag = -1;
+static int hf_dcerpc_dg_flags1_frag = -1;
+static int hf_dcerpc_dg_flags1_nofack = -1;
+static int hf_dcerpc_dg_flags1_maybe = -1;
+static int hf_dcerpc_dg_flags1_idempotent = -1;
+static int hf_dcerpc_dg_flags1_broadcast = -1;
+static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
+static int hf_dcerpc_dg_flags2 = -1;
+static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
+static int hf_dcerpc_dg_flags2_cancel_pending = -1;
+static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
+static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
+static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
+static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
+static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
+static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
+static int hf_dcerpc_dg_serial_hi = -1;
+static int hf_dcerpc_obj_id = -1;
+static int hf_dcerpc_dg_if_id = -1;
+static int hf_dcerpc_dg_act_id = -1;
+static int hf_dcerpc_dg_serial_lo = -1;
+static int hf_dcerpc_dg_ahint = -1;
+static int hf_dcerpc_dg_ihint = -1;
+static int hf_dcerpc_dg_frag_len = -1;
+static int hf_dcerpc_dg_frag_num = -1;
+static int hf_dcerpc_dg_auth_proto = -1;
+static int hf_dcerpc_opnum = -1;
+static int hf_dcerpc_dg_seqnum = -1;
+static int hf_dcerpc_dg_server_boot = -1;
+static int hf_dcerpc_dg_if_ver = -1;
+static int hf_dcerpc_krb5_av_prot_level = -1;
+static int hf_dcerpc_krb5_av_key_vers_num = -1;
+static int hf_dcerpc_krb5_av_key_auth_verifier = -1;
+static int hf_dcerpc_dg_cancel_vers = -1;
+static int hf_dcerpc_dg_cancel_id = -1;
+static int hf_dcerpc_dg_server_accepting_cancels = -1;
+static int hf_dcerpc_dg_fack_vers = -1;
+static int hf_dcerpc_dg_fack_window_size = -1;
+static int hf_dcerpc_dg_fack_max_tsdu = -1;
+static int hf_dcerpc_dg_fack_max_frag_size = -1;
+static int hf_dcerpc_dg_fack_serial_num = -1;
+static int hf_dcerpc_dg_fack_selack_len = -1;
+static int hf_dcerpc_dg_fack_selack = -1;
+static int hf_dcerpc_dg_status = -1;
+static int hf_dcerpc_array_max_count = -1;
+static int hf_dcerpc_array_offset = -1;
+static int hf_dcerpc_array_actual_count = -1;
+static int hf_dcerpc_array_buffer = -1;
+static int hf_dcerpc_op = -1;
+static int hf_dcerpc_referent_id = -1;
+static int hf_dcerpc_fragments = -1;
+static int hf_dcerpc_fragment = -1;
+static int hf_dcerpc_fragment_overlap = -1;
+static int hf_dcerpc_fragment_overlap_conflict = -1;
+static int hf_dcerpc_fragment_multiple_tails = -1;
+static int hf_dcerpc_fragment_too_long_fragment = -1;
+static int hf_dcerpc_fragment_error = -1;
+static int hf_dcerpc_reassembled_in = -1;
+static int hf_dcerpc_unknown_if_id = -1;
+
+static gint ett_dcerpc = -1;
+static gint ett_dcerpc_cn_flags = -1;
+static gint ett_dcerpc_cn_ctx = -1;
+static gint ett_dcerpc_cn_iface = -1;
+static gint ett_dcerpc_drep = -1;
+static gint ett_dcerpc_dg_flags1 = -1;
+static gint ett_dcerpc_dg_flags2 = -1;
+static gint ett_dcerpc_pointer_data = -1;
+static gint ett_dcerpc_string = -1;
+static gint ett_dcerpc_fragments = -1;
+static gint ett_dcerpc_fragment = -1;
+static gint ett_dcerpc_krb5_auth_verf = -1;
+
+static const fragment_items dcerpc_frag_items = {
+ &ett_dcerpc_fragments,
+ &ett_dcerpc_fragment,
+
+ &hf_dcerpc_fragments,
+ &hf_dcerpc_fragment,
+ &hf_dcerpc_fragment_overlap,
+ &hf_dcerpc_fragment_overlap_conflict,
+ &hf_dcerpc_fragment_multiple_tails,
+ &hf_dcerpc_fragment_too_long_fragment,
+ &hf_dcerpc_fragment_error,
+ NULL,
+
+ "fragments"
+};
+
+
+
+#ifdef WIN32
+int ResolveWin32UUID(e_uuid_t if_id, char *UUID_NAME, int UUID_NAME_MAX_LEN)
+{
+ char REG_UUID_NAME[MAX_PATH];
+ HKEY hKey = NULL;
+ DWORD UUID_MAX_SIZE = MAX_PATH;
+ char REG_UUID_STR[MAX_PATH];
+
+ if(UUID_NAME_MAX_LEN < 2)
+ return 0;
+ REG_UUID_NAME[0] = '\0';
+ snprintf(REG_UUID_STR, MAX_PATH, "SOFTWARE\\Classes\\Interface\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ if_id.Data1, if_id.Data2, if_id.Data3,
+ if_id.Data4[0], if_id.Data4[1],
+ if_id.Data4[2], if_id.Data4[3],
+ if_id.Data4[4], if_id.Data4[5],
+ if_id.Data4[6], if_id.Data4[7]);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)REG_UUID_STR, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ {
+ if (RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)REG_UUID_NAME, &UUID_MAX_SIZE) == ERROR_SUCCESS && UUID_MAX_SIZE <= MAX_PATH)
+ {
+ snprintf(UUID_NAME, UUID_NAME_MAX_LEN, "%s", REG_UUID_NAME);
+ RegCloseKey(hKey);
+ return strlen(REG_UUID_NAME);
+ }
+ RegCloseKey(hKey);
+ }
+ return 0; /* we didn't find anything anyhow. Please don't use the string! */
+
+}
+#endif
+
+static dcerpc_info *
+get_next_di(void)
+{
+ static dcerpc_info di[20];
+ static int di_counter=0;
+
+ di_counter++;
+ if(di_counter>=20){
+ di_counter=0;
+ }
+ return &di[di_counter];
+}
+
+/* try to desegment big DCE/RPC packets over TCP? */
+static gboolean dcerpc_cn_desegment = TRUE;
+
+/* reassemble DCE/RPC fragments */
+/* reassembly of dcerpc fragments will not work for the case where ONE frame
+ might contain multiple dcerpc fragments for different PDUs.
+ this case would be so unusual/weird so if you got captures like that:
+ too bad
+*/
+static gboolean dcerpc_reassemble = FALSE;
+static GHashTable *dcerpc_co_reassemble_table = NULL;
+static GHashTable *dcerpc_cl_reassemble_table = NULL;
+
+static void
+dcerpc_reassemble_init(void)
+{
+ fragment_table_init(&dcerpc_co_reassemble_table);
+ dcerpc_fragment_table_init(&dcerpc_cl_reassemble_table);
+}
+
+/*
+ * Authentication subdissectors. Used to dissect authentication blobs in
+ * DCERPC binds, requests and responses.
+ */
+
+typedef struct _dcerpc_auth_subdissector {
+ guint8 auth_level;
+ guint8 auth_type;
+ dcerpc_auth_subdissector_fns auth_fns;
+} dcerpc_auth_subdissector;
+
+static GSList *dcerpc_auth_subdissector_list;
+
+static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns(
+ guint8 auth_level, guint8 auth_type)
+{
+ gpointer data;
+ int i;
+
+ for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) {
+ dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data;
+
+ if (asd->auth_level == auth_level &&
+ asd->auth_type == auth_type)
+ return &asd->auth_fns;
+ }
+
+ return NULL;
+}
+
+void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type,
+ dcerpc_auth_subdissector_fns *fns)
+{
+ dcerpc_auth_subdissector *d;
+
+ if (get_auth_subdissector_fns(auth_level, auth_type))
+ return;
+
+ d = (dcerpc_auth_subdissector *)g_malloc(sizeof(dcerpc_auth_subdissector));
+
+ d->auth_level = auth_level;
+ d->auth_type = auth_type;
+ memcpy(&d->auth_fns, fns, sizeof(dcerpc_auth_subdissector_fns));
+
+ dcerpc_auth_subdissector_list = g_slist_append(dcerpc_auth_subdissector_list, d);
+}
+
+/* Hand off verifier data to a registered dissector */
+
+static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
+ proto_tree *tree,
+ dcerpc_auth_subdissector_fns *auth_fns,
+ e_dce_cn_common_hdr_t *hdr,
+ dcerpc_auth_info *auth_info)
+{
+ dcerpc_dissect_fnct_t *volatile fn = NULL;
+
+ switch (hdr->ptype) {
+ case PDU_BIND:
+ case PDU_ALTER:
+ fn = auth_fns->bind_fn;
+ break;
+ case PDU_BIND_ACK:
+ case PDU_ALTER_ACK:
+ fn = auth_fns->bind_ack_fn;
+ break;
+ case PDU_AUTH3:
+ fn = auth_fns->auth3_fn;
+ break;
+ case PDU_REQ:
+ fn = auth_fns->req_verf_fn;
+ break;
+ case PDU_RESP:
+ fn = auth_fns->resp_verf_fn;
+ break;
+
+ /* Don't know how to handle authentication data in this
+ pdu type. */
+
+ default:
+ g_warning("attempt to dissect %s pdu authentication data",
+ val_to_str(hdr->ptype, pckt_vals, "Unknown (%u)"));
+ break;
+ }
+
+ if (fn)
+ fn(auth_tvb, 0, pinfo, tree, hdr->drep);
+ else
+ proto_tree_add_text(tree, auth_tvb, 0, hdr->auth_len,
+ "%s Verifier",
+ val_to_str(auth_info->auth_type,
+ authn_protocol_vals,
+ "Unknown (%u)"));
+}
+
+/* Hand off payload data to a registered dissector */
+
+static tvbuff_t *decode_encrypted_data(tvbuff_t *enc_tvb,
+ packet_info *pinfo,
+ dcerpc_auth_subdissector_fns *auth_fns,
+ gboolean is_request,
+ dcerpc_auth_info *auth_info)
+{
+ dcerpc_decode_data_fnct_t *fn;
+
+ if (is_request)
+ fn = auth_fns->req_data_fn;
+ else
+ fn = auth_fns->resp_data_fn;
+
+ if (fn)
+ return fn(enc_tvb, 0, pinfo, auth_info);
+
+ return NULL;
+}
+
+/*
+ * Subdissectors
+ */
+
+/* the registered subdissectors */
+GHashTable *dcerpc_uuids=NULL;
+
+static gint
+dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
+{
+ const dcerpc_uuid_key *key1 = (const dcerpc_uuid_key *)k1;
+ const dcerpc_uuid_key *key2 = (const dcerpc_uuid_key *)k2;
+ return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
+ && (key1->ver == key2->ver));
+}
+
+static guint
+dcerpc_uuid_hash (gconstpointer k)
+{
+ const dcerpc_uuid_key *key = (const dcerpc_uuid_key *)k;
+ /* This isn't perfect, but the Data1 part of these is almost always
+ unique. */
+ return key->uuid.Data1;
+}
+
+void
+dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
+ dcerpc_sub_dissector *procs, int opnum_hf)
+{
+ dcerpc_uuid_key *key = g_malloc (sizeof (*key));
+ dcerpc_uuid_value *value = g_malloc (sizeof (*value));
+ header_field_info *hf_info;
+
+ key->uuid = *uuid;
+ key->ver = ver;
+
+ value->proto = find_protocol_by_id(proto);
+ value->proto_id = proto;
+ value->ett = ett;
+ value->name = proto_get_protocol_short_name (value->proto);
+ value->procs = procs;
+ value->opnum_hf = opnum_hf;
+
+ g_hash_table_insert (dcerpc_uuids, key, value);
+
+ hf_info = proto_registrar_get_nth(opnum_hf);
+ hf_info->strings = value_string_from_subdissectors(procs);
+}
+
+/* Function to find the name of a registered protocol
+ * or NULL if the protocol/version is not known to ethereal.
+ */
+char *
+dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver)
+{
+ dcerpc_uuid_key key;
+ dcerpc_uuid_value *sub_proto;
+
+ key.uuid = *uuid;
+ key.ver = ver;
+ if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
+ return NULL;
+ }
+ return sub_proto->name;
+}
+
+/* Function to find the opnum hf-field of a registered protocol
+ * or -1 if the protocol/version is not known to ethereal.
+ */
+int
+dcerpc_get_proto_hf_opnum(e_uuid_t *uuid, guint16 ver)
+{
+ dcerpc_uuid_key key;
+ dcerpc_uuid_value *sub_proto;
+
+ key.uuid = *uuid;
+ key.ver = ver;
+ if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
+ return -1;
+ }
+ return sub_proto->opnum_hf;
+}
+
+/* Create a value_string consisting of DCERPC opnum and name from a
+ subdissector array. */
+
+value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd)
+{
+ value_string *vs = NULL;
+ int i, num_sd = 0;
+
+ again:
+ for (i = 0; sd[i].name; i++) {
+ if (vs) {
+ vs[i].value = sd[i].num;
+ vs[i].strptr = sd[i].name;
+ } else
+ num_sd++;
+ }
+
+ if (!vs) {
+ vs = g_malloc((num_sd + 1) * sizeof(value_string));
+ goto again;
+ }
+
+ vs[num_sd].value = 0;
+ vs[num_sd].strptr = NULL;
+
+ return vs;
+}
+
+/* Function to find the subdissector table of a registered protocol
+ * or NULL if the protocol/version is not known to ethereal.
+ */
+dcerpc_sub_dissector *
+dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver)
+{
+ dcerpc_uuid_key key;
+ dcerpc_uuid_value *sub_proto;
+
+ key.uuid = *uuid;
+ key.ver = ver;
+ if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
+ return NULL;
+ }
+ return sub_proto->procs;
+}
+
+
+/*
+ * To keep track of ctx_id mappings.
+ *
+ * Everytime we see a bind call we update this table.
+ * Note that we always specify a SMB FID. For non-SMB transports this
+ * value is 0.
+ */
+static GHashTable *dcerpc_binds=NULL;
+
+typedef struct _dcerpc_bind_key {
+ conversation_t *conv;
+ guint16 ctx_id;
+ guint16 smb_fid;
+} dcerpc_bind_key;
+
+typedef struct _dcerpc_bind_value {
+ e_uuid_t uuid;
+ guint16 ver;
+} dcerpc_bind_value;
+
+static GMemChunk *dcerpc_bind_key_chunk=NULL;
+static GMemChunk *dcerpc_bind_value_chunk=NULL;
+
+static gint
+dcerpc_bind_equal (gconstpointer k1, gconstpointer k2)
+{
+ const dcerpc_bind_key *key1 = (const dcerpc_bind_key *)k1;
+ const dcerpc_bind_key *key2 = (const dcerpc_bind_key *)k2;
+ return (key1->conv == key2->conv
+ && key1->ctx_id == key2->ctx_id
+ && key1->smb_fid == key2->smb_fid);
+}
+
+static guint
+dcerpc_bind_hash (gconstpointer k)
+{
+ const dcerpc_bind_key *key = (const dcerpc_bind_key *)k;
+ return GPOINTER_TO_UINT(key->conv) + key->ctx_id + key->smb_fid;
+
+}
+
+/*
+ * To keep track of callid mappings. Should really use some generic
+ * conversation support instead.
+ */
+static GHashTable *dcerpc_cn_calls=NULL;
+static GHashTable *dcerpc_dg_calls=NULL;
+
+typedef struct _dcerpc_cn_call_key {
+ conversation_t *conv;
+ guint32 call_id;
+ guint16 smb_fid;
+} dcerpc_cn_call_key;
+
+typedef struct _dcerpc_dg_call_key {
+ conversation_t *conv;
+ guint32 seqnum;
+ e_uuid_t act_id ;
+} dcerpc_dg_call_key;
+
+static GMemChunk *dcerpc_cn_call_key_chunk=NULL;
+
+static GMemChunk *dcerpc_dg_call_key_chunk=NULL;
+
+static GMemChunk *dcerpc_call_value_chunk=NULL;
+
+
+static gint
+dcerpc_cn_call_equal (gconstpointer k1, gconstpointer k2)
+{
+ const dcerpc_cn_call_key *key1 = (const dcerpc_cn_call_key *)k1;
+ const dcerpc_cn_call_key *key2 = (const dcerpc_cn_call_key *)k2;
+ return (key1->conv == key2->conv
+ && key1->call_id == key2->call_id
+ && key1->smb_fid == key2->smb_fid);
+}
+
+static gint
+dcerpc_dg_call_equal (gconstpointer k1, gconstpointer k2)
+{
+ const dcerpc_dg_call_key *key1 = (const dcerpc_dg_call_key *)k1;
+ const dcerpc_dg_call_key *key2 = (const dcerpc_dg_call_key *)k2;
+ return (key1->conv == key2->conv
+ && key1->seqnum == key2->seqnum
+ && (memcmp (&key1->act_id, &key2->act_id, sizeof (e_uuid_t)) == 0));
+}
+
+static guint
+dcerpc_cn_call_hash (gconstpointer k)
+{
+ const dcerpc_cn_call_key *key = (const dcerpc_cn_call_key *)k;
+ return ((guint32)key->conv) + key->call_id + key->smb_fid;
+}
+
+static guint
+dcerpc_dg_call_hash (gconstpointer k)
+{
+ const dcerpc_dg_call_key *key = (const dcerpc_dg_call_key *)k;
+ return (((guint32)key->conv) + key->seqnum + key->act_id.Data1
+ + (key->act_id.Data2 << 16) + key->act_id.Data3
+ + (key->act_id.Data4[0] << 24) + (key->act_id.Data4[1] << 16)
+ + (key->act_id.Data4[2] << 8) + (key->act_id.Data4[3] << 0)
+ + (key->act_id.Data4[4] << 24) + (key->act_id.Data4[5] << 16)
+ + (key->act_id.Data4[6] << 8) + (key->act_id.Data4[7] << 0));
+}
+
+/* to keep track of matched calls/responses
+ this one uses the same value struct as calls, but the key is the frame id
+ and call id; there can be more than one call in a frame.
+
+ XXX - why not just use the same keys as are used for calls?
+*/
+
+static GHashTable *dcerpc_matched=NULL;
+
+typedef struct _dcerpc_matched_key {
+ guint32 frame;
+ guint32 call_id;
+} dcerpc_matched_key;
+
+static GMemChunk *dcerpc_matched_key_chunk=NULL;
+
+static gint
+dcerpc_matched_equal (gconstpointer k1, gconstpointer k2)
+{
+ const dcerpc_matched_key *key1 = (const dcerpc_matched_key *)k1;
+ const dcerpc_matched_key *key2 = (const dcerpc_matched_key *)k2;
+ return (key1->frame == key2->frame
+ && key1->call_id == key2->call_id);
+}
+
+static guint
+dcerpc_matched_hash (gconstpointer k)
+{
+ const dcerpc_matched_key *key = (const dcerpc_matched_key *)k;
+ return key->frame;
+}
+
+
+
+/*
+ * Utility functions. Modeled after packet-rpc.c
+ */
+
+int
+dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint8 *pdata)
+{
+ guint8 data;
+
+ data = tvb_get_guint8 (tvb, offset);
+ if (tree) {
+ proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
+ }
+ if (pdata)
+ *pdata = data;
+ return offset + 1;
+}
+
+int
+dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint16 *pdata)
+{
+ guint16 data;
+
+ data = ((drep[0] & 0x10)
+ ? tvb_get_letohs (tvb, offset)
+ : tvb_get_ntohs (tvb, offset));
+
+ if (tree) {
+ proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
+ }
+ if (pdata)
+ *pdata = data;
+ return offset + 2;
+}
+
+int
+dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata)
+{
+ guint32 data;
+
+ data = ((drep[0] & 0x10)
+ ? tvb_get_letohl (tvb, offset)
+ : tvb_get_ntohl (tvb, offset));
+
+ if (tree) {
+ proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
+ }
+ if (pdata)
+ *pdata = data;
+ return offset+4;
+}
+
+/* handles 32 bit unix time_t */
+int
+dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata)
+{
+ guint32 data;
+ nstime_t tv;
+
+ data = ((drep[0] & 0x10)
+ ? tvb_get_letohl (tvb, offset)
+ : tvb_get_ntohl (tvb, offset));
+
+ tv.secs=data;
+ tv.nsecs=0;
+ if (tree) {
+ if(data==0xffffffff){
+ /* special case, no time specified */
+ proto_tree_add_time_format(tree, hfindex, tvb, offset, 4, &tv, "%s: No time specified", proto_registrar_get_nth(hfindex)->name);
+ } else {
+ proto_tree_add_time (tree, hfindex, tvb, offset, 4, &tv);
+ }
+ }
+ if (pdata)
+ *pdata = data;
+
+ return offset+4;
+}
+
+int
+dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, unsigned char *pdata)
+{
+ if(pdata){
+ tvb_memcpy(tvb, pdata, offset, 8);
+ if(drep[0] & 0x10){/* XXX this might be the wrong way around */
+ unsigned char data;
+ data=pdata[0];pdata[0]=pdata[7];pdata[7]=data;
+ data=pdata[1];pdata[1]=pdata[6];pdata[6]=data;
+ data=pdata[2];pdata[2]=pdata[5];pdata[5]=data;
+ data=pdata[3];pdata[3]=pdata[4];pdata[4]=data;
+ }
+ }
+
+ if (tree) {
+ proto_tree_add_item(tree, hfindex, tvb, offset, 8, (drep[0] & 0x10));
+ }
+
+ return offset+8;
+}
+
+
+int
+dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, gfloat *pdata)
+{
+ gfloat data;
+
+
+ switch(drep[1]) {
+ case(DCE_RPC_DREP_FP_IEEE):
+ data = ((drep[0] & 0x10)
+ ? tvb_get_letohieee_float(tvb, offset)
+ : tvb_get_ntohieee_float(tvb, offset));
+ if (tree) {
+ proto_tree_add_float(tree, hfindex, tvb, offset, 4, data);
+ }
+ break;
+ case(DCE_RPC_DREP_FP_VAX): /* (fall trough) */
+ case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
+ case(DCE_RPC_DREP_FP_IBM): /* (fall trough) */
+ default:
+ /* ToBeDone: non IEEE floating formats */
+ /* Set data to a negative infinity value */
+ data = -G_MAXFLOAT;
+ if (tree) {
+ proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE floating formats currently not implemented (drep=%u)!", drep[1]);
+ }
+ }
+ if (pdata)
+ *pdata = data;
+ return offset + 4;
+}
+
+
+int
+dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, gdouble *pdata)
+{
+ gdouble data;
+
+
+ switch(drep[1]) {
+ case(DCE_RPC_DREP_FP_IEEE):
+ data = ((drep[0] & 0x10)
+ ? tvb_get_letohieee_double(tvb, offset)
+ : tvb_get_ntohieee_double(tvb, offset));
+ if (tree) {
+ proto_tree_add_double(tree, hfindex, tvb, offset, 8, data);
+ }
+ break;
+ case(DCE_RPC_DREP_FP_VAX): /* (fall trough) */
+ case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
+ case(DCE_RPC_DREP_FP_IBM): /* (fall trough) */
+ default:
+ /* ToBeDone: non IEEE double formats */
+ /* Set data to a negative infinity value */
+ data = -G_MAXDOUBLE;
+ if (tree) {
+ proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE double formats currently not implemented (drep=%u)!", drep[1]);
+ }
+ }
+ if (pdata)
+ *pdata = data;
+ return offset + 8;
+}
+
+
+/*
+ * a couple simpler things
+ */
+guint16
+dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, guint8 *drep)
+{
+ if (drep[0] & 0x10) {
+ return tvb_get_letohs (tvb, offset);
+ } else {
+ return tvb_get_ntohs (tvb, offset);
+ }
+}
+
+guint32
+dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, guint8 *drep)
+{
+ if (drep[0] & 0x10) {
+ return tvb_get_letohl (tvb, offset);
+ } else {
+ return tvb_get_ntohl (tvb, offset);
+ }
+}
+
+void
+dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, guint8 *drep, e_uuid_t *uuid)
+{
+ unsigned int i;
+ uuid->Data1 = dcerpc_tvb_get_ntohl (tvb, offset, drep);
+ uuid->Data2 = dcerpc_tvb_get_ntohs (tvb, offset+4, drep);
+ uuid->Data3 = dcerpc_tvb_get_ntohs (tvb, offset+6, drep);
+
+ for (i=0; i<sizeof (uuid->Data4); i++) {
+ uuid->Data4[i] = tvb_get_guint8 (tvb, offset+8+i);
+ }
+}
+
+
+
+/* NDR arrays */
+/* function to dissect a unidimensional conformant array */
+int
+dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ dcerpc_dissect_fnct_t *fnct)
+{
+ guint32 i;
+ dcerpc_info *di;
+ int old_offset;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* conformant run, just dissect the max_count header */
+ old_offset=offset;
+ di->conformant_run=0;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_dcerpc_array_max_count, &di->array_max_count);
+ di->array_max_count_offset=offset-4;
+ di->conformant_run=1;
+ di->conformant_eaten=offset-old_offset;
+ } else {
+ /* we don't remember where in the bytestream this field was */
+ proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
+
+ /* real run, dissect the elements */
+ for(i=0;i<di->array_max_count;i++){
+ offset = (*fnct)(tvb, offset, pinfo, tree, drep);
+ }
+ }
+
+ return offset;
+}
+/* function to dissect a unidimensional conformant and varying array */
+int
+dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ dcerpc_dissect_fnct_t *fnct)
+{
+ guint32 i;
+ dcerpc_info *di;
+ int old_offset;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* conformant run, just dissect the max_count header */
+ old_offset=offset;
+ di->conformant_run=0;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_dcerpc_array_max_count, &di->array_max_count);
+ di->array_max_count_offset=offset-4;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_dcerpc_array_offset, &di->array_offset);
+ di->array_offset_offset=offset-4;
+ offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
+ hf_dcerpc_array_actual_count, &di->array_actual_count);
+ di->array_actual_count_offset=offset-4;
+ di->conformant_run=1;
+ di->conformant_eaten=offset-old_offset;
+ } else {
+ /* we dont dont remember where in the bytestream these fields were */
+ proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
+ proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
+ proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
+
+ /* real run, dissect the elements */
+ for(i=0;i<di->array_actual_count;i++){
+ offset = (*fnct)(tvb, offset, pinfo, tree, drep);
+ }
+ }
+
+ return offset;
+}
+
+/* Dissect an string of bytes. This corresponds to
+ IDL of the form '[string] byte *foo'.
+
+ It can also be used for a conformant varying array of bytes if
+ the contents of the array should be shown as a big blob, rather
+ than showing each byte as an individual element.
+
+ XXX - which of those is really the IDL type for, for example,
+ the encrypted data in some MAPI packets? (Microsoft haven't
+ released that IDL.)
+
+ XXX - does this need to do all the conformant array stuff that
+ "dissect_ndr_ucvarray()" does? These are presumably for strings
+ that are conformant and varying - they're stored like conformant
+ varying arrays of bytes. */
+int
+dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di;
+ guint32 len;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ /* NDR array header */
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_dcerpc_array_max_count, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_dcerpc_array_offset, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
+ hf_dcerpc_array_actual_count, &len);
+
+ if (tree && len)
+ proto_tree_add_item(tree, hf_dcerpc_array_buffer,
+ tvb, offset, len, drep[0] & 0x10);
+
+ offset += len;
+
+ return offset;
+}
+
+/* For dissecting arrays that are to be interpreted as strings. */
+
+/* Dissect an NDR conformant varying string of elements.
+ The length of each element is given by the 'size_is' parameter;
+ the elements are assumed to be characters or wide characters.
+
+ XXX - does this need to do all the conformant array stuff that
+ "dissect_ndr_ucvarray()" does? */
+int
+dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, int size_is,
+ int hfindex, gboolean add_subtree, char **data)
+{
+ dcerpc_info *di;
+ proto_item *string_item;
+ proto_tree *string_tree;
+ guint32 len, buffer_len;
+ char *s;
+ header_field_info *hfinfo;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* just a run to handle conformant arrays, no scalars to dissect */
+ return offset;
+ }
+
+ if (add_subtree) {
+ string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
+ proto_registrar_get_name(hfindex));
+ string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
+ } else {
+ string_item = NULL;
+ string_tree = tree;
+ }
+
+ /* NDR array header */
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
+ hf_dcerpc_array_max_count, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
+ hf_dcerpc_array_offset, NULL);
+
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
+ hf_dcerpc_array_actual_count, &len);
+
+ buffer_len = size_is * len;
+
+ /* Adjust offset */
+ if (offset % size_is)
+ offset += size_is - (offset % size_is);
+
+ if (size_is == sizeof(guint16)) {
+ /* XXX - use drep to determine the byte order? */
+ s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
+ /*
+ * XXX - we don't support a string type with Unicode
+ * characters, so if this is a string item, we make
+ * its value be the "fake Unicode" string.
+ */
+ if (tree && buffer_len) {
+ hfinfo = proto_registrar_get_nth(hfindex);
+ if (hfinfo->type == FT_STRING) {
+ proto_tree_add_string(string_tree, hfindex, tvb, offset,
+ buffer_len, s);
+ } else {
+ proto_tree_add_item(string_tree, hfindex, tvb, offset,
+ buffer_len, drep[0] & 0x10);
+ }
+ }
+ } else {
+ /*
+ * "tvb_get_string()" throws an exception if the entire string
+ * isn't in the tvbuff. If the length is bogus, this should
+ * keep us from trying to allocate an immensely large buffer.
+ * (It won't help if the length is *valid* but immensely large,
+ * but that's another matter; in any case, that would happen only
+ * if we had an immensely large tvbuff....)
+ */
+ s = tvb_get_string(tvb, offset, buffer_len);
+ if (tree && buffer_len)
+ proto_tree_add_item(string_tree, hfindex, tvb, offset,
+ buffer_len, drep[0] & 0x10);
+ }
+
+ if (string_item != NULL)
+ proto_item_append_text(string_item, ": %s", s);
+
+ if (data)
+ *data = s;
+ else
+ g_free(s);
+
+ offset += buffer_len;
+
+ proto_item_set_end(string_item, tvb, offset);
+
+ return offset;
+}
+
+/* Dissect an conformant varying string of chars.
+ This corresponds to IDL of the form '[string] char *foo'.
+
+ XXX - at least according to the DCE RPC 1.1 spec, a string has
+ a null terminator, which isn't necessary as a terminator for
+ the transfer language (as there's a length), but is presumably
+ there for the benefit of null-terminated-string languages
+ such as C. Is this ever used for purely counted strings?
+ (Not that it matters if it is.) */
+int
+dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di;
+ di=pinfo->private_data;
+
+ return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint8), di->hf_index,
+ FALSE, NULL);
+}
+
+/* Dissect a conformant varying string of wchars (wide characters).
+ This corresponds to IDL of the form '[string] wchar *foo'
+
+ XXX - at least according to the DCE RPC 1.1 spec, a string has
+ a null terminator, which isn't necessary as a terminator for
+ the transfer language (as there's a length), but is presumably
+ there for the benefit of null-terminated-string languages
+ such as C. Is this ever used for purely counted strings?
+ (Not that it matters if it is.) */
+int
+dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep)
+{
+ dcerpc_info *di;
+ di=pinfo->private_data;
+
+ return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
+ sizeof(guint16), di->hf_index,
+ FALSE, NULL);
+}
+
+/* ndr pointer handling */
+/* list of pointers encountered so far */
+static GSList *ndr_pointer_list = NULL;
+
+/* position where in the list to insert newly encountered pointers */
+static int ndr_pointer_list_pos=0;
+
+/* boolean controlling whether pointers are top-level or embedded */
+static gboolean pointers_are_top_level = TRUE;
+
+/* as a kludge, we represent all embedded reference pointers as id==-1
+ hoping that his will not collide with any non-ref pointers */
+typedef struct ndr_pointer_data {
+ guint32 id;
+ proto_item *item; /* proto_item for pointer */
+ proto_tree *tree; /* subtree of above item */
+ dcerpc_dissect_fnct_t *fnct; /*if non-NULL, we have not called it yet*/
+ int hf_index;
+ dcerpc_callback_fnct_t *callback;
+ void *callback_args;
+} ndr_pointer_data_t;
+
+void
+init_ndr_pointer_list(packet_info *pinfo)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ di->conformant_run=0;
+
+ while(ndr_pointer_list){
+ ndr_pointer_data_t *npd;
+
+ npd=g_slist_nth_data(ndr_pointer_list, 0);
+ ndr_pointer_list=g_slist_remove(ndr_pointer_list, npd);
+ if(npd){
+ g_free(npd);
+ }
+ }
+
+ ndr_pointer_list=NULL;
+ ndr_pointer_list_pos=0;
+ pointers_are_top_level=TRUE;
+}
+
+static int
+dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 *drep)
+{
+ int found_new_pointer;
+ dcerpc_info *di;
+ int old_offset;
+ int next_pointer;
+
+ next_pointer=0;
+ di=pinfo->private_data;
+ do{
+ int i, len;
+
+ found_new_pointer=0;
+ len=g_slist_length(ndr_pointer_list);
+ for(i=next_pointer;i<len;i++){
+ ndr_pointer_data_t *tnpd;
+ tnpd=g_slist_nth_data(ndr_pointer_list, i);
+ if(tnpd->fnct){
+ dcerpc_dissect_fnct_t *fnct;
+
+ next_pointer=i+1;
+ found_new_pointer=1;
+ fnct=tnpd->fnct;
+ tnpd->fnct=NULL;
+ ndr_pointer_list_pos=i+1;
+ di->hf_index=tnpd->hf_index;
+ /* first a run to handle any conformant
+ array headers */
+ di->conformant_run=1;
+ di->conformant_eaten=0;
+ old_offset = offset;
+ offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
+
+ g_assert((offset-old_offset)==di->conformant_eaten);
+ /* This is to check for any bugs in the dissectors.
+ *
+ * Basically, the NDR representation will store all
+ * arrays in two blocks, one block with the dimension
+ * discreption, like size, number of elements and such,
+ * and another block that contains the actual data stored
+ * in the array.
+ * If the array is embedded directly inside another,
+ * encapsulating aggregate type, like a union or struct,
+ * then these two blocks will be stored at different places
+ * in the bytestream, with other data between the blocks.
+ *
+ * For this reason, all pointers to types (both aggregate
+ * and scalar, for simplicity no distinction is made)
+ * will have its dissector called twice.
+ * The dissector will first be called with conformant_run==1
+ * in which mode the dissector MUST NOT consume any data from
+ * the tvbuff (i.e. may not dissect anything) except the
+ * initial control block for arrays.
+ * The second time the dissector is called, with
+ * conformant_run==0, all other data for the type will be
+ * dissected.
+ *
+ * All dissect_ndr_<type> dissectors are already prepared
+ * for this and knows when it should eat data from the tvb
+ * and when not to, so implementors of dissectors will
+ * normally not need to worry about this or even know about
+ * it. However, if a dissector for an aggregate type calls
+ * a subdissector from outside packet-dcerpc.c, such as
+ * the dissector in packet-smb.c for NT Security Descriptors
+ * as an example, then it is VERY important to encapsulate
+ * this call to an external subdissector with the appropriate
+ * test for conformant_run, i.e. it will need something like
+ *
+ * dcerpc_info *di;
+ *
+ * di=pinfo->private_data;
+ * if(di->conformant_run){
+ * return offset;
+ * }
+ *
+ * to make sure it makes the right thing.
+ * This assert will signal when someone has forgotten to
+ * make the dissector aware of this requirement.
+ */
+
+ /* now we dissect the actual pointer */
+ di->conformant_run=0;
+ old_offset = offset;
+ offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
+ if (tnpd->callback)
+ tnpd->callback(pinfo, tnpd->tree, tnpd->item, tvb, old_offset, offset, tnpd->callback_args);
+ break;
+ }
+ }
+ } while(found_new_pointer);
+
+ return offset;
+}
+
+
+static void
+add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
+ dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index,
+ dcerpc_callback_fnct_t *callback, void *callback_args)
+{
+ ndr_pointer_data_t *npd;
+
+ /* check if this pointer is valid */
+ if(id!=0xffffffff){
+ dcerpc_info *di;
+ dcerpc_call_value *value;
+
+ di=pinfo->private_data;
+ value=di->call_data;
+
+ if(di->ptype == PDU_REQ){
+ if(!(pinfo->fd->flags.visited)){
+ if(id>value->max_ptr){
+ value->max_ptr=id;
+ }
+ }
+ } else {
+ /* if we havent seen the request bail out since we cant
+ know whether this is the first non-NULL instance
+ or not */
+ if(value->req_frame==0){
+ /* XXX THROW EXCEPTION */
+ }
+
+ /* We saw this one in the request frame, nothing to
+ dissect later */
+ if(id<=value->max_ptr){
+ return;
+ }
+ }
+ }
+
+ npd=g_malloc(sizeof(ndr_pointer_data_t));
+ npd->id=id;
+ npd->tree=tree;
+ npd->item=item;
+ npd->fnct=fnct;
+ npd->hf_index=hf_index;
+ npd->callback=callback;
+ npd->callback_args=callback_args;
+ ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
+ ndr_pointer_list_pos);
+ ndr_pointer_list_pos++;
+}
+
+
+static int
+find_pointer_index(guint32 id)
+{
+ ndr_pointer_data_t *npd;
+ int i,len;
+
+ len=g_slist_length(ndr_pointer_list);
+ for(i=0;i<len;i++){
+ npd=g_slist_nth_data(ndr_pointer_list, i);
+ if(npd){
+ if(npd->id==id){
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/* This function dissects an NDR pointer and stores the callback for later
+ * deferred dissection.
+ *
+ * fnct is the callback function for when we have reached this object in
+ * the bytestream.
+ *
+ * type is what type of pointer.
+ *
+ * this is text is what text we should put in any created tree node.
+ *
+ * hf_index is what hf value we want to pass to the callback function when
+ * it is called, the callback can later pich this one up from di->hf_index.
+ *
+ * callback is executed after the pointer has been dereferenced.
+ *
+ * callback_args is passed as an argument to the callback function
+ *
+ * See packet-dcerpc-samr.c for examples
+ */
+int
+dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
+ int type, char *text, int hf_index,
+ dcerpc_callback_fnct_t *callback, void *callback_args)
+{
+ dcerpc_info *di;
+
+ di=pinfo->private_data;
+ if(di->conformant_run){
+ /* this call was only for dissecting the header for any
+ embedded conformant array. we will not parse any
+ pointers in this mode.
+ */
+ return offset;
+ }
+
+ /*TOP LEVEL REFERENCE POINTER*/
+ if( pointers_are_top_level
+ &&(type==NDR_POINTER_REF) ){
+ proto_item *item;
+ proto_tree *tr;
+
+ /* we must find out a nice way to do the length here */
+ item=proto_tree_add_text(tree, tvb, offset, 0,
+ "%s", text);
+ tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
+
+ add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
+ hf_index, callback, callback_args);
+ goto after_ref_id;
+ }
+
+ /*TOP LEVEL FULL POINTER*/
+ if( pointers_are_top_level
+ && (type==NDR_POINTER_PTR) ){
+ int idx;
+ guint32 id;
+ proto_item *item;
+ proto_tree *tr;
+
+ /* get the referent id */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
+
+ /* we got a NULL pointer */
+ if(id==0){
+ proto_tree_add_text(tree, tvb, offset-4, 4,
+ "(NULL pointer) %s",text);
+ goto after_ref_id;
+ }
+
+ /* see if we have seen this pointer before */
+ idx=find_pointer_index(id);
+
+ /* we have seen this pointer before */
+ if(idx>=0){
+ proto_tree_add_text(tree, tvb, offset-4, 4,
+ "(duplicate PTR) %s",text);
+ goto after_ref_id;
+ }
+
+ /* new pointer */
+ item=proto_tree_add_text(tree, tvb, offset-4, 4,
+ "%s", text);
+ tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
+ proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
+ add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
+ callback, callback_args);
+ goto after_ref_id;
+ }
+ /*TOP LEVEL UNIQUE POINTER*/
+ if( pointers_are_top_level
+ && (type==NDR_POINTER_UNIQUE) ){
+ guint32 id;
+ proto_item *item;
+ proto_tree *tr;
+
+ /* get the referent id */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
+
+ /* we got a NULL pointer */
+ if(id==0){
+ proto_tree_add_text(tree, tvb, offset-4, 4,
+ "(NULL pointer) %s",text);
+ goto after_ref_id;
+ }
+
+ /* new pointer */
+ item=proto_tree_add_text(tree, tvb, offset-4, 4,
+ "%s", text);
+ tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
+ proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
+ add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
+ hf_index, callback, callback_args);
+ goto after_ref_id;
+ }
+
+ /*EMBEDDED REFERENCE POINTER*/
+ if( (!pointers_are_top_level)
+ && (type==NDR_POINTER_REF) ){
+ guint32 id;
+ proto_item *item;
+ proto_tree *tr;
+
+ /* get the referent id */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
+
+ /* new pointer */
+ item=proto_tree_add_text(tree, tvb, offset-4, 4,
+ "%s",text);
+ tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
+ proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
+ add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
+ hf_index, callback, callback_args);
+ goto after_ref_id;
+ }
+
+ /*EMBEDDED UNIQUE POINTER*/
+ if( (!pointers_are_top_level)
+ && (type==NDR_POINTER_UNIQUE) ){
+ guint32 id;
+ proto_item *item;
+ proto_tree *tr;
+
+ /* get the referent id */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
+
+ /* we got a NULL pointer */
+ if(id==0){
+ proto_tree_add_text(tree, tvb, offset-4, 4,
+ "(NULL pointer) %s", text);
+ goto after_ref_id;
+ }
+
+ /* new pointer */
+ item=proto_tree_add_text(tree, tvb, offset-4, 4,
+ "%s",text);
+ tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
+ proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
+ add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
+ hf_index, callback, callback_args);
+ goto after_ref_id;
+ }
+
+ /*EMBEDDED FULL POINTER*/
+ if( (!pointers_are_top_level)
+ && (type==NDR_POINTER_PTR) ){
+ int idx;
+ guint32 id;
+ proto_item *item;
+ proto_tree *tr;
+
+ /* get the referent id */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
+
+ /* we got a NULL pointer */
+ if(id==0){
+ proto_tree_add_text(tree, tvb, offset-4, 4,
+ "(NULL pointer) %s",text);
+ goto after_ref_id;
+ }
+
+ /* see if we have seen this pointer before */
+ idx=find_pointer_index(id);
+
+ /* we have seen this pointer before */
+ if(idx>=0){
+ proto_tree_add_text(tree, tvb, offset-4, 4,
+ "(duplicate PTR) %s",text);
+ goto after_ref_id;
+ }
+
+ /* new pointer */
+ item=proto_tree_add_text(tree, tvb, offset-4, 4,
+ "%s", text);
+ tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
+ proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
+ add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
+ callback, callback_args);
+ goto after_ref_id;
+ }
+
+
+after_ref_id:
+ /* After each top level pointer we have dissected we have to
+ dissect all deferrals before we move on to the next top level
+ argument */
+ if(pointers_are_top_level==TRUE){
+ pointers_are_top_level=FALSE;
+ offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);
+ pointers_are_top_level=TRUE;
+ }
+
+ return offset;
+}
+
+int
+dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
+ int type, char *text, int hf_index)
+{
+ return dissect_ndr_pointer_cb(
+ tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
+ NULL, NULL);
+}
+
+static void
+show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
+ dcerpc_auth_info *auth_info, gboolean is_encrypted)
+{
+ int length;
+
+ /*
+ * We don't show stub data unless we have some in the tvbuff;
+ * however, in the protocol tree, we show, as the number of
+ * bytes, the reported number of bytes, not the number of bytes
+ * that happen to be in the tvbuff.
+ */
+ if (tvb_length_remaining (tvb, offset) > 0) {
+ length = tvb_reported_length_remaining (tvb, offset);
+ if (auth_info != NULL &&
+ auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
+ if (is_encrypted) {
+ proto_tree_add_text(dcerpc_tree, tvb, offset, -1,
+ "Encrypted stub data (%d byte%s)",
+ length, plurality(length, "", "s"));
+ } else {
+ proto_tree_add_text(dcerpc_tree, tvb, offset, -1,
+ "Decrypted stub data (%d byte%s)",
+ length, plurality(length, "", "s"));
+ }
+ } else {
+ proto_tree_add_text (dcerpc_tree, tvb, offset, -1,
+ "Stub data (%d byte%s)", length,
+ plurality(length, "", "s"));
+ }
+ }
+}
+
+static int
+dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
+ proto_tree *dcerpc_tree,
+ tvbuff_t *volatile tvb, tvbuff_t *decrypted_tvb,
+ guint8 *drep, dcerpc_info *info,
+ dcerpc_auth_info *auth_info)
+{
+ volatile gint offset = 0;
+ dcerpc_uuid_key key;
+ dcerpc_uuid_value *sub_proto;
+ proto_tree *volatile sub_tree = NULL;
+ dcerpc_sub_dissector *proc;
+ gchar *name = NULL;
+ dcerpc_dissect_fnct_t *volatile sub_dissect;
+ const char *volatile saved_proto;
+ void *volatile saved_private_data;
+ guint length, reported_length;
+ tvbuff_t *volatile stub_tvb;
+ volatile guint auth_pad_len;
+ volatile int auth_pad_offset;
+#ifdef WIN32
+ char UUID_NAME[MAX_PATH];
+#endif
+
+ key.uuid = info->call_data->uuid;
+ key.ver = info->call_data->ver;
+
+
+ if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == NULL
+ || !proto_is_protocol_enabled(sub_proto->proto)) {
+ /*
+ * We don't have a dissector for this UUID, or the protocol
+ * for that UUID is disabled.
+ */
+
+ proto_tree_add_boolean_hidden(dcerpc_tree, hf_dcerpc_unknown_if_id,
+ tvb, offset, 0, TRUE);
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+#ifdef WIN32
+ if(ResolveWin32UUID(info->call_data->uuid, UUID_NAME, MAX_PATH))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " [%s] UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x rpcver: %u",
+ UUID_NAME, info->call_data->uuid.Data1, info->call_data->uuid.Data2, info->call_data->uuid.Data3, info->call_data->uuid.Data4[0],
+ info->call_data->uuid.Data4[1], info->call_data->uuid.Data4[2], info->call_data->uuid.Data4[3],
+ info->call_data->uuid.Data4[4], info->call_data->uuid.Data4[5], info->call_data->uuid.Data4[6],
+ info->call_data->uuid.Data4[7], info->call_data->ver);
+else
+#endif
+ col_append_fstr (pinfo->cinfo, COL_INFO, " UNKUUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x rpcver: %u",
+ info->call_data->uuid.Data1, info->call_data->uuid.Data2, info->call_data->uuid.Data3, info->call_data->uuid.Data4[0],
+ info->call_data->uuid.Data4[1], info->call_data->uuid.Data4[2], info->call_data->uuid.Data4[3],
+ info->call_data->uuid.Data4[4], info->call_data->uuid.Data4[5], info->call_data->uuid.Data4[6],
+ info->call_data->uuid.Data4[7], info->call_data->ver);
+ }
+
+ if (decrypted_tvb != NULL) {
+ show_stub_data (decrypted_tvb, 0, dcerpc_tree, auth_info,
+ FALSE);
+ } else
+ show_stub_data (tvb, 0, dcerpc_tree, auth_info, TRUE);
+ return -1;
+ }
+
+ for (proc = sub_proto->procs; proc->name; proc++) {
+ if (proc->num == info->call_data->opnum) {
+ name = proc->name;
+ break;
+ }
+ }
+
+ if (!name)
+ name = "Unknown?!";
+
+ if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
+ }
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s",
+ name, (info->ptype == PDU_REQ) ? "request" : "response");
+ }
+
+ if (tree) {
+ proto_item *sub_item;
+ sub_item = proto_tree_add_item (tree, sub_proto->proto_id, tvb, 0,
+ -1, FALSE);
+
+ if (sub_item) {
+ sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
+ proto_item_append_text(sub_item, ", %s", name);
+ }
+
+ /*
+ * Put the operation number into the tree along with
+ * the operation's name.
+ */
+
+ if (sub_proto->opnum_hf != -1)
+ proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
+ tvb, 0, 0, info->call_data->opnum,
+ "Operation: %s (%u)",
+ name, info->call_data->opnum);
+ else
+ proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
+ 0, 0, info->call_data->opnum,
+ "Operation: %s (%u)",
+ name, info->call_data->opnum);
+ }
+
+ sub_dissect = (info->ptype == PDU_REQ) ?
+ proc->dissect_rqst : proc->dissect_resp;
+
+ if (decrypted_tvb != NULL) {
+ /* Either there was no encryption or we successfully decrypted
+ the entrypted payload. */
+ if (sub_dissect) {
+ /* We have a subdissector - call it. */
+ saved_proto = pinfo->current_proto;
+ saved_private_data = pinfo->private_data;
+ pinfo->current_proto = sub_proto->name;
+ pinfo->private_data = (void *)info;
+
+ init_ndr_pointer_list(pinfo);
+
+ /*
+ * Remove the authentication padding from the stub data.
+ */
+ if (auth_info != NULL && auth_info->auth_pad_len != 0) {
+ length = tvb_length(decrypted_tvb);
+ reported_length = tvb_reported_length(decrypted_tvb);
+ if (reported_length >= auth_info->auth_pad_len) {
+ /*
+ * OK, the padding length isn't so big that it
+ * exceeds the stub length. Trim the reported
+ * length of the tvbuff.
+ */
+ reported_length -= auth_info->auth_pad_len;
+
+ /*
+ * If that exceeds the actual amount of data in
+ * the tvbuff (which means we have at least one
+ * byte of authentication padding in the tvbuff),
+ * trim the actual amount.
+ */
+ if (length > reported_length)
+ length = reported_length;
+
+ stub_tvb = tvb_new_subset(tvb, 0, length, reported_length);
+ auth_pad_len = auth_info->auth_pad_len;
+ auth_pad_offset = reported_length;
+ } else {
+ /*
+ * The padding length exceeds the stub length.
+ * Don't bother dissecting the stub, trim the padding
+ * length to what's in the stub data, and show the
+ * entire stub as authentication padding.
+ */
+ stub_tvb = NULL;
+ auth_pad_len = reported_length;
+ auth_pad_offset = 0;
+ }
+ } else {
+ /*
+ * No authentication padding.
+ */
+ stub_tvb = decrypted_tvb;
+ auth_pad_len = 0;
+ auth_pad_offset = 0;
+ }
+
+ if (stub_tvb != NULL) {
+ /*
+ * Catch all exceptions other than BoundsError, so that even
+ * if the stub data is bad, we still show the authentication
+ * padding, if any.
+ *
+ * If we get BoundsError, it means the frame was cut short
+ * by a snapshot length, so there's nothing more to
+ * dissect; just re-throw that exception.
+ */
+ TRY {
+ offset = sub_dissect (decrypted_tvb, 0, pinfo, sub_tree,
+ drep);
+
+ /* If we have a subdissector and it didn't dissect all
+ data in the tvb, make a note of it. */
+
+ if (tvb_reported_length_remaining(stub_tvb, offset) > 0) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "[Long frame (%d bytes)]",
+ tvb_reported_length_remaining(stub_tvb, offset));
+ }
+ } CATCH(BoundsError) {
+ RETHROW;
+ } CATCH_ALL {
+ show_exception(decrypted_tvb, pinfo, tree, EXCEPT_CODE);
+ } ENDTRY;
+ }
+
+ /* If there is auth padding at the end of the stub, display it */
+ if (auth_pad_len != 0) {
+ proto_tree_add_text (sub_tree, decrypted_tvb, auth_pad_offset,
+ auth_pad_len,
+ "Auth Padding (%u byte%s)",
+ auth_pad_len,
+ plurality(auth_pad_len, "", "s"));
+ }
+
+ pinfo->current_proto = saved_proto;
+ pinfo->private_data = saved_private_data;
+ } else {
+ /* No subdissector - show it as stub data. */
+ if(decrypted_tvb){
+ show_stub_data (decrypted_tvb, 0, sub_tree, auth_info, FALSE);
+ } else {
+ show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
+ }
+ }
+ } else
+ show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
+
+ tap_queue_packet(dcerpc_tap, pinfo, info);
+ return 0;
+}
+
+static int
+dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
+ dcerpc_auth_info *auth_info)
+{
+ int auth_offset;
+
+ auth_info->auth_data = NULL;
+
+ if (auth_info->auth_size != 0) {
+ dcerpc_auth_subdissector_fns *auth_fns;
+ tvbuff_t *auth_tvb;
+
+ auth_offset = hdr->frag_len - hdr->auth_len;
+
+ auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len,
+ hdr->auth_len);
+
+ auth_info->auth_data = auth_tvb;
+
+ if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
+ auth_info->auth_type))) {
+ /*
+ * Catch all exceptions, so that even if the verifier is bad
+ * or we don't have all of it, we still show the stub data.
+ */
+ TRY {
+ dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
+ hdr, auth_info);
+ } CATCH_ALL {
+ show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE);
+ } ENDTRY;
+ } else {
+ proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
+ "Auth Verifier");
+ }
+ }
+
+ return hdr->auth_len;
+}
+
+static void
+dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
+ gboolean are_credentials, dcerpc_auth_info *auth_info)
+{
+ volatile int offset;
+
+ /*
+ * Initially set auth_level and auth_type to zero to indicate that we
+ * haven't yet seen any authentication level information.
+ */
+ auth_info->auth_level = 0;
+ auth_info->auth_type = 0;
+ auth_info->auth_size = 0;
+ auth_info->auth_pad_len = 0;
+
+ /*
+ * The authentication information is at the *end* of the PDU; in
+ * request and response PDUs, the request and response stub data
+ * come before it.
+ *
+ * Is there any authentication data (i.e., is the authentication length
+ * non-zero), and is the authentication length valid (i.e., is it, plus
+ * 8 bytes for the type/level/pad length/reserved/context id, less than
+ * or equal to the fragment length minus the starting offset of the
+ * stub data?)
+ */
+
+ if (hdr->auth_len
+ && (hdr->auth_len + 8 <= hdr->frag_len - stub_offset)) {
+
+ /*
+ * Yes, there is authentication data, and the length is valid.
+ * Do we have all the bytes of stub data?
+ * (If not, we'd throw an exception dissecting *that*, so don't
+ * bother trying to dissect the authentication information and
+ * throwing another exception there.)
+ */
+ offset = hdr->frag_len - (hdr->auth_len + 8);
+ if (offset == 0 || tvb_offset_exists(tvb, offset - 1)) {
+ /*
+ * Either there's no stub data, or the last byte of the stub
+ * data is present in the captured data, so we shouldn't
+ * get a BoundsError dissecting the stub data.
+ *
+ * Try dissecting the authentication data.
+ * Catch all exceptions, so that even if the auth info is bad
+ * or we don't have all of it, we still show the stuff we
+ * dissect after this, such as stub data.
+ */
+ TRY {
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_auth_type,
+ &auth_info->auth_type);
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_auth_level,
+ &auth_info->auth_level);
+
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_auth_pad_len,
+ &auth_info->auth_pad_len);
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_auth_rsrvd, NULL);
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_auth_ctx_id, NULL);
+
+ /*
+ * Dissect the authentication data.
+ */
+ if (are_credentials) {
+ tvbuff_t *auth_tvb;
+ dcerpc_auth_subdissector_fns *auth_fns;
+
+ auth_tvb = tvb_new_subset(tvb, offset, hdr->auth_len,
+ hdr->auth_len);
+
+ if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
+ auth_info->auth_type)))
+ dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
+ hdr, auth_info);
+ else
+ proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
+ "Auth Credentials");
+ }
+
+ /* Compute the size of the auth block. Note that this should not
+ include auth padding, since when NTLMSSP encryption is used, the
+ padding is actually inside the encrypted stub */
+ auth_info->auth_size = hdr->auth_len + 8;
+ } CATCH_ALL {
+ show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE);
+ } ENDTRY;
+ }
+ }
+}
+
+
+/* We need to hash in the SMB fid number to generate a unique hash table
+ * key as DCERPC over SMB allows several pipes over the same TCP/IP
+ * socket.
+ * We pass this function the transport type here to make sure we only look
+ * at this function iff it came across an SMB pipe.
+ * Other transports might need to mix in their own extra multiplexing data
+ * as well in the future.
+ */
+
+static guint16 get_transport_salt (packet_info *pinfo, int transport_type)
+{
+ dcerpc_private_info *priv = (dcerpc_private_info *)pinfo->private_data;
+
+ if (!priv)
+ return 0; /* Nothing to see here */
+
+ switch(transport_type){
+ case DCE_CN_TRANSPORT_SMBPIPE:
+ /* DCERPC over smb */
+ return priv->fid;
+ }
+
+ /* Some other transport... */
+ return 0;
+}
+
+/*
+ * Connection oriented packet types
+ */
+
+static void
+dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
+ int transport_type)
+{
+ conversation_t *conv = NULL;
+ guint8 num_ctx_items = 0;
+ guint i;
+ gboolean saw_ctx_item = FALSE;
+ guint16 ctx_id;
+ guint16 num_trans_items;
+ guint j;
+ e_uuid_t if_id;
+ e_uuid_t trans_id;
+ guint32 trans_ver;
+ guint16 if_ver, if_ver_minor;
+ char uuid_str[DCERPC_UUID_STR_LEN];
+ int uuid_str_len;
+ dcerpc_auth_info auth_info;
+#ifdef WIN32
+ char UUID_NAME[MAX_PATH];
+#endif
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_max_xmit, NULL);
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_max_recv, NULL);
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_assoc_group, NULL);
+
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
+
+ /* padding */
+ offset += 3;
+
+ for (i = 0; i < num_ctx_items; i++) {
+ proto_tree *ctx_tree = NULL, *iface_tree = NULL;
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, NULL, hdr->drep,
+ hf_dcerpc_cn_ctx_id, &ctx_id);
+
+ if (dcerpc_tree) {
+ proto_item *ctx_item;
+
+ ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_id,
+ tvb, offset - 2, 2,
+ hdr->drep[0] & 0x10);
+
+ ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
+ }
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree, hdr->drep,
+ hf_dcerpc_cn_num_trans_items, &num_trans_items);
+
+ /* XXX - use "dissect_ndr_uuid_t()"? */
+ dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
+ if (ctx_tree) {
+ proto_item *iface_item;
+
+ uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ if_id.Data1, if_id.Data2, if_id.Data3,
+ if_id.Data4[0], if_id.Data4[1],
+ if_id.Data4[2], if_id.Data4[3],
+ if_id.Data4[4], if_id.Data4[5],
+ if_id.Data4[6], if_id.Data4[7]);
+
+ if (uuid_str_len >= DCERPC_UUID_STR_LEN)
+ memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
+#ifdef WIN32
+ if(ResolveWin32UUID(if_id, UUID_NAME, MAX_PATH))
+ iface_item = proto_tree_add_string_format (ctx_tree, hf_dcerpc_cn_bind_if_id, tvb,
+ offset, 16, uuid_str, "Interface [%s] UUID: %s", UUID_NAME, uuid_str);
+ else
+#endif
+ iface_item = proto_tree_add_string_format (ctx_tree, hf_dcerpc_cn_bind_if_id, tvb,
+ offset, 16, uuid_str, "Interface UUID: %s", uuid_str);
+ iface_tree = proto_item_add_subtree(iface_item, ett_dcerpc_cn_iface);
+ }
+ offset += 16;
+
+ if (hdr->drep[0] & 0x10) {
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
+ hf_dcerpc_cn_bind_if_ver, &if_ver);
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
+ hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
+ } else {
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
+ hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
+ hf_dcerpc_cn_bind_if_ver, &if_ver);
+ }
+
+ if (!saw_ctx_item) {
+ conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (conv == NULL) {
+ conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+
+ /* if this is the first time we see this packet, we need to
+ update the dcerpc_binds table so that any later calls can
+ match to the interface.
+ XXX We assume that BINDs will NEVER be fragmented.
+ */
+ if(!(pinfo->fd->flags.visited)){
+ dcerpc_bind_key *key;
+ dcerpc_bind_value *value;
+
+ key = g_mem_chunk_alloc (dcerpc_bind_key_chunk);
+ key->conv = conv;
+ key->ctx_id = ctx_id;
+ key->smb_fid = get_transport_salt(pinfo, transport_type);
+
+ value = g_mem_chunk_alloc (dcerpc_bind_value_chunk);
+ value->uuid = if_id;
+ value->ver = if_ver;
+
+ /* add this entry to the bind table, first removing any
+ previous ones that are identical
+ */
+ if(g_hash_table_lookup(dcerpc_binds, key)){
+ g_hash_table_remove(dcerpc_binds, key);
+ }
+ g_hash_table_insert (dcerpc_binds, key, value);
+ }
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ dcerpc_uuid_key key;
+ dcerpc_uuid_value *value;
+
+ key.uuid = if_id;
+ key.ver = if_ver;
+
+ if (num_ctx_items > 1)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %u context items, 1st", num_ctx_items);
+
+ if ((value = g_hash_table_lookup(dcerpc_uuids, &key)))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %s", value->name);
+ else
+#ifdef WIN32
+ if(ResolveWin32UUID(if_id, UUID_NAME, MAX_PATH))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %u.%u",
+ UUID_NAME, if_id.Data1, if_id.Data2, if_id.Data3,
+ if_id.Data4[0], if_id.Data4[1],
+ if_id.Data4[2], if_id.Data4[3],
+ if_id.Data4[4], if_id.Data4[5],
+ if_id.Data4[6], if_id.Data4[7],
+ if_ver, if_ver_minor);
+ else
+#endif
+ col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %u.%u",
+ if_id.Data1, if_id.Data2, if_id.Data3,
+ if_id.Data4[0], if_id.Data4[1],
+ if_id.Data4[2], if_id.Data4[3],
+ if_id.Data4[4], if_id.Data4[5],
+ if_id.Data4[6], if_id.Data4[7],
+ if_ver, if_ver_minor);
+ }
+ saw_ctx_item = TRUE;
+ }
+
+ for (j = 0; j < num_trans_items; j++) {
+ /* XXX - use "dissect_ndr_uuid_t()"? */
+ dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
+ if (iface_tree) {
+ uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ trans_id.Data1, trans_id.Data2, trans_id.Data3,
+ trans_id.Data4[0], trans_id.Data4[1],
+ trans_id.Data4[2], trans_id.Data4[3],
+ trans_id.Data4[4], trans_id.Data4[5],
+ trans_id.Data4[6], trans_id.Data4[7]);
+ if (uuid_str_len >= DCERPC_UUID_STR_LEN)
+ memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
+ proto_tree_add_string_format (iface_tree, hf_dcerpc_cn_bind_trans_id, tvb,
+ offset, 16, uuid_str, "Transfer Syntax: %s", uuid_str);
+ }
+ offset += 16;
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, iface_tree, hdr->drep,
+ hf_dcerpc_cn_bind_trans_ver, &trans_ver);
+ }
+ }
+
+ /*
+ * XXX - we should save the authentication type *if* we have
+ * an authentication header, and associate it with an authentication
+ * context, so subsequent PDUs can use that context.
+ */
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
+}
+
+static void
+dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
+{
+ guint16 max_xmit, max_recv;
+ guint16 sec_addr_len;
+ guint8 num_results;
+ guint i;
+ guint16 result;
+ guint16 reason;
+ e_uuid_t trans_id;
+ guint32 trans_ver;
+ char uuid_str[DCERPC_UUID_STR_LEN];
+ int uuid_str_len;
+ dcerpc_auth_info auth_info;
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_max_xmit, &max_xmit);
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_max_recv, &max_recv);
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_assoc_group, NULL);
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
+ if (sec_addr_len != 0) {
+ proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
+ sec_addr_len, FALSE);
+ offset += sec_addr_len;
+ }
+
+ if (offset % 4) {
+ offset += 4 - offset % 4;
+ }
+
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_num_results, &num_results);
+
+ /* padding */
+ offset += 3;
+
+ for (i = 0; i < num_results; i++) {
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_cn_ack_result,
+ &result);
+ if (result != 0) {
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_cn_ack_reason,
+ &reason);
+ } else {
+ /*
+ * The reason for rejection isn't meaningful, and often isn't
+ * set, when the syntax was accepted.
+ */
+ offset += 2;
+ }
+
+ /* XXX - use "dissect_ndr_uuid_t()"? */
+ dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
+ if (dcerpc_tree) {
+ uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ trans_id.Data1, trans_id.Data2, trans_id.Data3,
+ trans_id.Data4[0], trans_id.Data4[1],
+ trans_id.Data4[2], trans_id.Data4[3],
+ trans_id.Data4[4], trans_id.Data4[5],
+ trans_id.Data4[6], trans_id.Data4[7]);
+ if (uuid_str_len >= DCERPC_UUID_STR_LEN)
+ memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
+ proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_ack_trans_id, tvb,
+ offset, 16, uuid_str, "Transfer Syntax: %s", uuid_str);
+ }
+ offset += 16;
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_ack_trans_ver, &trans_ver);
+ }
+
+ /*
+ * XXX - do we need to do anything with the authentication level
+ * we get back from this?
+ */
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if (num_results != 0 && result == 0) {
+ /* XXX - only checks the last result */
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " accept max_xmit: %u max_recv: %u",
+ max_xmit, max_recv);
+ } else {
+ /* XXX - only shows the last result and reason */
+ col_append_fstr (pinfo->cinfo, COL_INFO, " %s, reason: %s",
+ val_to_str(result, p_cont_result_vals,
+ "Unknown result (%u)"),
+ val_to_str(reason, p_provider_reason_vals,
+ "Unknown (%u)"));
+ }
+ }
+}
+
+static void
+dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
+{
+ guint16 reason;
+ guint8 num_protocols;
+ guint i;
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_cn_reject_reason,
+ &reason);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, " reason: %s",
+ val_to_str(reason, reject_reason_vals, "Unknown (%u)"));
+ }
+
+ if (reason == PROTOCOL_VERSION_NOT_SUPPORTED) {
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_num_protocols,
+ &num_protocols);
+
+ for (i = 0; i < num_protocols; i++) {
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_cn_protocol_ver_major,
+ NULL);
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_cn_protocol_ver_minor,
+ NULL);
+ }
+ }
+}
+
+/* Return a string describing a DCE/RPC fragment as first, middle, or end
+ fragment. */
+
+#define PFC_FRAG_MASK 0x03
+
+static char *
+fragment_type(guint8 flags)
+{
+ flags = flags & PFC_FRAG_MASK;
+
+ if (flags == PFC_FIRST_FRAG)
+ return "first";
+
+ if (flags == 0)
+ return "middle";
+
+ if (flags == PFC_LAST_FRAG)
+ return "last";
+
+ if (flags == (PFC_FIRST_FRAG | PFC_LAST_FRAG))
+ return "whole";
+
+ return "unknown";
+}
+
+/* Dissect stub data (payload) of a DCERPC packet. */
+
+static void
+dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, proto_tree *tree,
+ e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
+ dcerpc_auth_info *auth_info, guint32 alloc_hint,
+ guint32 frame)
+{
+ gboolean save_fragmented;
+ fragment_data *fd_head=NULL;
+ guint32 tot_len;
+ tvbuff_t *payload_tvb, *decrypted_tvb;
+ proto_item *pi;
+
+ save_fragmented = pinfo->fragmented;
+
+ payload_tvb = tvb_new_subset(
+ tvb, offset, tvb_length_remaining(tvb, offset) -
+ auth_info->auth_size, tvb_length_remaining(tvb, offset) -
+ auth_info->auth_size);
+
+ /* Decrypt the PDU if it is encrypted */
+
+ if (auth_info->auth_type &&
+ auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
+ /*
+ * We know the authentication type, and the authentication
+ * level is "Packet privacy", meaning the payload is
+ * encrypted; attempt to decrypt it.
+ */
+ dcerpc_auth_subdissector_fns *auth_fns;
+
+ /* Start out assuming we won't succeed in decrypting. */
+ decrypted_tvb = NULL;
+
+ if ((auth_fns = get_auth_subdissector_fns(
+ auth_info->auth_level, auth_info->auth_type))) {
+ tvbuff_t *result;
+
+ result = decode_encrypted_data(
+ payload_tvb, pinfo, auth_fns,
+ hdr->ptype == PDU_REQ, auth_info);
+
+ if (result) {
+ if (dcerpc_tree)
+ proto_tree_add_text(
+ dcerpc_tree, payload_tvb, 0, -1,
+ "Encrypted stub data (%d byte%s)",
+ tvb_reported_length(payload_tvb),
+
+ plurality(tvb_length(payload_tvb), "", "s"));
+
+ add_new_data_source(
+ pinfo, result, "Decrypted stub data");
+
+ /* We succeeded. */
+ decrypted_tvb = result;
+ }
+ }
+ } else
+ decrypted_tvb = payload_tvb;
+
+ /* if this packet is not fragmented, just dissect it and exit */
+ if(PFC_NOT_FRAGMENTED(hdr)){
+ pinfo->fragmented = FALSE;
+
+ dcerpc_try_handoff(
+ pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
+ hdr->drep, di, auth_info);
+
+ pinfo->fragmented = save_fragmented;
+ return;
+ }
+
+ /* The packet is fragmented. */
+ pinfo->fragmented = TRUE;
+
+ /* if we are not doing reassembly and this is the first fragment
+ then just dissect it and exit
+ XXX - if we're not doing reassembly, can we decrypt an
+ encrypted stub?
+ */
+ if( (!dcerpc_reassemble) && hdr->flags&PFC_FIRST_FRAG ){
+
+ dcerpc_try_handoff(
+ pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
+ hdr->drep, di, auth_info);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
+ }
+ pinfo->fragmented = save_fragmented;
+ return;
+ }
+
+ /* if we have already seen this packet, see if it was reassembled
+ and if so dissect the full pdu.
+ then exit
+ */
+ if(pinfo->fd->flags.visited){
+ fd_head=fragment_get(pinfo, frame, dcerpc_co_reassemble_table);
+ goto end_cn_stub;
+ }
+
+ /* if we are not doing reassembly and it was neither a complete PDU
+ nor the first fragment then there is nothing more we can do
+ so we just have to exit
+ */
+ if( !dcerpc_reassemble )
+ goto end_cn_stub;
+
+ /* if we didnt get 'frame' we dont know where the PDU started and thus
+ it is pointless to continue
+ */
+ if(!frame)
+ goto end_cn_stub;
+
+ /* from now on we must attempt to reassemble the PDU
+ */
+
+ /* if we get here we know it is the first time we see the packet
+ and we also know it is only a fragment and not a full PDU,
+ thus we must reassemble it.
+ */
+
+ /* Do we have any non-encrypted data to reassemble? */
+ if (decrypted_tvb == NULL) {
+ /* No. We can't even try to reassemble. */
+ goto end_cn_stub;
+ }
+
+ /* if this is the first fragment we need to start reassembly
+ */
+ if(hdr->flags&PFC_FIRST_FRAG){
+ fragment_add(decrypted_tvb, 0, pinfo, frame, dcerpc_co_reassemble_table,
+ 0, tvb_length(decrypted_tvb), TRUE);
+ fragment_set_tot_len(pinfo, frame,
+ dcerpc_co_reassemble_table, alloc_hint);
+
+ goto end_cn_stub;
+ }
+
+ /* if this is a middle fragment, just add it and exit */
+ if(!(hdr->flags&PFC_LAST_FRAG)){
+ tot_len = fragment_get_tot_len(pinfo, frame,
+ dcerpc_co_reassemble_table);
+ fragment_add(decrypted_tvb, 0, pinfo, frame,
+ dcerpc_co_reassemble_table,
+ tot_len-alloc_hint, tvb_length(decrypted_tvb),
+ TRUE);
+
+ goto end_cn_stub;
+ }
+
+ /* this was the last fragment add it to reassembly
+ */
+ tot_len = fragment_get_tot_len(pinfo, frame,
+ dcerpc_co_reassemble_table);
+ fd_head = fragment_add(decrypted_tvb, 0, pinfo,
+ frame,
+ dcerpc_co_reassemble_table,
+ tot_len-alloc_hint, tvb_length(decrypted_tvb),
+ TRUE);
+
+end_cn_stub:
+
+ /* if reassembly is complete, dissect the full PDU
+ */
+ if(fd_head && (fd_head->flags&FD_DEFRAGMENTED) ){
+
+ if(pinfo->fd->num==fd_head->reassembled_in){
+ tvbuff_t *next_tvb;
+
+ next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
+ tvb_set_child_real_data_tvbuff(decrypted_tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
+ show_fragment_tree(fd_head, &dcerpc_frag_items,
+ dcerpc_tree, pinfo, next_tvb);
+
+ pinfo->fragmented = FALSE;
+
+ dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
+ next_tvb, hdr->drep, di, auth_info);
+
+ } else {
+ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
+ decrypted_tvb, 0, 0, fd_head->reassembled_in);
+ PROTO_ITEM_SET_GENERATED(pi);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " [DCE/RPC %s fragment, reas: #%u]", fragment_type(hdr->flags), fd_head->reassembled_in);
+ }
+ }
+ } else {
+ /* Reassembly not complete - some fragments
+ are missing. Just show the stub data. */
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
+ }
+
+ if(decrypted_tvb){
+ show_stub_data (decrypted_tvb, 0, tree, auth_info, FALSE);
+ } else {
+ show_stub_data (payload_tvb, 0, tree, auth_info, TRUE);
+ }
+ }
+
+ pinfo->fragmented = save_fragmented;
+}
+
+static void
+dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, proto_tree *tree,
+ e_dce_cn_common_hdr_t *hdr, int transport_type)
+{
+ conversation_t *conv;
+ guint16 ctx_id;
+ guint16 opnum;
+ e_uuid_t obj_id;
+ dcerpc_auth_info auth_info;
+ guint32 alloc_hint;
+ char uuid_str[DCERPC_UUID_STR_LEN];
+ int uuid_str_len;
+ proto_item *pi;
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_alloc_hint, &alloc_hint);
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_ctx_id, &ctx_id);
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_opnum, &opnum);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u ctx_id: %u",
+ opnum, ctx_id);
+ }
+
+ if (hdr->flags & PFC_OBJECT_UUID) {
+ /* XXX - use "dissect_ndr_uuid_t()"? */
+ dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
+ if (dcerpc_tree) {
+ uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ obj_id.Data1, obj_id.Data2, obj_id.Data3,
+ obj_id.Data4[0],
+ obj_id.Data4[1],
+ obj_id.Data4[2],
+ obj_id.Data4[3],
+ obj_id.Data4[4],
+ obj_id.Data4[5],
+ obj_id.Data4[6],
+ obj_id.Data4[7]);
+ if (uuid_str_len >= DCERPC_UUID_STR_LEN)
+ memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
+ proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
+ offset, 16, uuid_str, "Object UUID: %s", uuid_str);
+ }
+ offset += 16;
+ }
+
+ /*
+ * XXX - what if this was set when the connection was set up,
+ * and we just have a security context?
+ */
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
+
+ conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (!conv)
+ show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
+ else {
+ dcerpc_matched_key matched_key, *new_matched_key;
+ dcerpc_call_value *value;
+
+ /* !!! we can NOT check flags.visited here since this will interact
+ badly with when SMB handles (i.e. calls the subdissector)
+ and desegmented pdu's .
+ Instead we check if this pdu is already in the matched table or not
+ */
+ matched_key.frame = pinfo->fd->num;
+ matched_key.call_id = hdr->call_id;
+ value = g_hash_table_lookup(dcerpc_matched, &matched_key);
+ if(!value){
+ dcerpc_bind_key bind_key;
+ dcerpc_bind_value *bind_value;
+
+ bind_key.conv=conv;
+ bind_key.ctx_id=ctx_id;
+ bind_key.smb_fid=get_transport_salt(pinfo, transport_type);
+
+ if((bind_value=g_hash_table_lookup(dcerpc_binds, &bind_key)) ){
+ if(!(hdr->flags&PFC_FIRST_FRAG)){
+ dcerpc_cn_call_key call_key;
+ dcerpc_call_value *call_value;
+
+ call_key.conv=conv;
+ call_key.call_id=hdr->call_id;
+ call_key.smb_fid=get_transport_salt(pinfo, transport_type);
+ if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
+ new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+ *new_matched_key = matched_key;
+ g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
+ value = call_value;
+ }
+ } else {
+ dcerpc_cn_call_key *call_key;
+ dcerpc_call_value *call_value;
+
+ /* We found the binding and it is the first fragment
+ (or a complete PDU) of a dcerpc pdu so just add
+ the call to both the call table and the
+ matched table
+ */
+ call_key=g_mem_chunk_alloc (dcerpc_cn_call_key_chunk);
+ call_key->conv=conv;
+ call_key->call_id=hdr->call_id;
+ call_key->smb_fid=get_transport_salt(pinfo, transport_type);
+
+ /* if there is already a matching call in the table
+ remove it so it is replaced with the new one */
+ if(g_hash_table_lookup(dcerpc_cn_calls, call_key)){
+ g_hash_table_remove(dcerpc_cn_calls, call_key);
+ }
+
+ call_value=g_mem_chunk_alloc (dcerpc_call_value_chunk);
+ call_value->uuid = bind_value->uuid;
+ call_value->ver = bind_value->ver;
+ call_value->opnum = opnum;
+ call_value->req_frame=pinfo->fd->num;
+ call_value->req_time.secs=pinfo->fd->abs_secs;
+ call_value->req_time.nsecs=pinfo->fd->abs_usecs*1000;
+ call_value->rep_frame=0;
+ call_value->max_ptr=0;
+ call_value->private_data = NULL;
+ g_hash_table_insert (dcerpc_cn_calls, call_key, call_value);
+
+ new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+ *new_matched_key = matched_key;
+ g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
+ value = call_value;
+ }
+ }
+ }
+
+ if (value) {
+ dcerpc_info *di;
+
+ di=get_next_di();
+ /* handoff this call */
+ di->conv = conv;
+ di->call_id = hdr->call_id;
+ di->smb_fid = get_transport_salt(pinfo, transport_type);
+ di->ptype = PDU_REQ;
+ di->call_data = value;
+ di->hf_index = -1;
+
+ if(value->rep_frame!=0){
+ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
+ tvb, 0, 0, value->rep_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+
+ dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
+ hdr, di, &auth_info, alloc_hint,
+ value->req_frame);
+ } else
+ show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
+ }
+}
+
+static void
+dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, proto_tree *tree,
+ e_dce_cn_common_hdr_t *hdr, int transport_type)
+{
+ dcerpc_call_value *value = NULL;
+ conversation_t *conv;
+ guint16 ctx_id;
+ dcerpc_auth_info auth_info;
+ guint32 alloc_hint;
+ proto_item *pi;
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_alloc_hint, &alloc_hint);
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_ctx_id, &ctx_id);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, " ctx_id: %u", ctx_id);
+ }
+
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_cancel_count, NULL);
+ /* padding */
+ offset++;
+
+ /*
+ * XXX - what if this was set when the connection was set up,
+ * and we just have a security context?
+ */
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+ dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
+
+ conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if (!conv) {
+ /* no point in creating one here, really */
+ show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
+ } else {
+ dcerpc_matched_key matched_key, *new_matched_key;
+
+ /* !!! we can NOT check flags.visited here since this will interact
+ badly with when SMB handles (i.e. calls the subdissector)
+ and desegmented pdu's .
+ Instead we check if this pdu is already in the matched table or not
+ */
+ matched_key.frame = pinfo->fd->num;
+ matched_key.call_id = hdr->call_id;
+ value=g_hash_table_lookup(dcerpc_matched, &matched_key);
+ if(!value){
+ dcerpc_cn_call_key call_key;
+ dcerpc_call_value *call_value;
+
+ call_key.conv=conv;
+ call_key.call_id=hdr->call_id;
+ call_key.smb_fid=get_transport_salt(pinfo, transport_type);
+
+ if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
+ new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+ *new_matched_key = matched_key;
+ g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
+ value = call_value;
+ if(call_value->rep_frame==0){
+ call_value->rep_frame=pinfo->fd->num;
+ }
+ }
+ }
+
+ if (value) {
+ dcerpc_info *di;
+
+ di=get_next_di();
+ /* handoff this call */
+ di->conv = conv;
+ di->call_id = hdr->call_id;
+ di->smb_fid = get_transport_salt(pinfo, transport_type);
+ di->ptype = PDU_RESP;
+ di->call_data = value;
+
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
+ if(value->req_frame!=0){
+ nstime_t ns;
+ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
+ tvb, 0, 0, value->req_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ ns.secs= pinfo->fd->abs_secs-value->req_time.secs;
+ ns.nsecs=pinfo->fd->abs_usecs*1000-value->req_time.nsecs;
+ if(ns.nsecs<0){
+ ns.nsecs+=1000000000;
+ ns.secs--;
+ }
+ pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+
+ dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
+ hdr, di, &auth_info, alloc_hint,
+ value->rep_frame);
+ } else
+ show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
+ }
+}
+
+static void
+dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
+ int transport_type)
+{
+ dcerpc_call_value *value = NULL;
+ conversation_t *conv;
+ guint16 ctx_id;
+ guint32 status;
+ guint32 alloc_hint;
+ dcerpc_auth_info auth_info;
+ proto_item *pi;
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_alloc_hint, &alloc_hint);
+
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_ctx_id, &ctx_id);
+
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_cancel_count, NULL);
+ /* padding */
+ offset++;
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+ hf_dcerpc_cn_status, &status);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " ctx_id: %u status: %s", ctx_id,
+ val_to_str(status, reject_status_vals,
+ "Unknown (0x%08x)"));
+ }
+
+ /* padding */
+ offset += 4;
+
+ /*
+ * XXX - what if this was set when the connection was set up,
+ * and we just have a security context?
+ */
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
+
+ conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (!conv) {
+ /* no point in creating one here, really */
+ } else {
+ dcerpc_matched_key matched_key, *new_matched_key;
+
+ /* !!! we can NOT check flags.visited here since this will interact
+ badly with when SMB handles (i.e. calls the subdissector)
+ and desegmented pdu's .
+ Instead we check if this pdu is already in the matched table or not
+ */
+ matched_key.frame = pinfo->fd->num;
+ matched_key.call_id = hdr->call_id;
+ value=g_hash_table_lookup(dcerpc_matched, &matched_key);
+ if(!value){
+ dcerpc_cn_call_key call_key;
+ dcerpc_call_value *call_value;
+
+ call_key.conv=conv;
+ call_key.call_id=hdr->call_id;
+ call_key.smb_fid=get_transport_salt(pinfo, transport_type);
+
+ if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
+ new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+ *new_matched_key = matched_key;
+ g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
+ value = call_value;
+ if(call_value->rep_frame==0){
+ call_value->rep_frame=pinfo->fd->num;
+ }
+
+ }
+ }
+
+ if (value) {
+ int length, reported_length, stub_length;
+ dcerpc_info *di;
+
+ di=get_next_di();
+ /* handoff this call */
+ di->conv = conv;
+ di->call_id = hdr->call_id;
+ di->smb_fid = get_transport_salt(pinfo, transport_type);
+ di->ptype = PDU_FAULT;
+ di->call_data = value;
+
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
+ if(value->req_frame!=0){
+ nstime_t ns;
+ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
+ tvb, 0, 0, value->req_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ ns.secs= pinfo->fd->abs_secs-value->req_time.secs;
+ ns.nsecs=pinfo->fd->abs_usecs*1000-value->req_time.nsecs;
+ if(ns.nsecs<0){
+ ns.nsecs+=1000000000;
+ ns.secs--;
+ }
+ pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+
+ length = tvb_length_remaining(tvb, offset);
+ reported_length = tvb_reported_length_remaining(tvb, offset);
+ stub_length = hdr->frag_len - offset - auth_info.auth_size;
+ if (length > stub_length)
+ length = stub_length;
+ if (reported_length > stub_length)
+ reported_length = stub_length;
+
+ /* If we don't have reassembly enabled, or this packet contains
+ the entire PDU, or if we don't have all the data in this
+ fragment, just call the handoff directly if this is the
+ first fragment or the PDU isn't fragmented. */
+ if( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
+ !tvb_bytes_exist(tvb, offset, stub_length) ){
+ if(hdr->flags&PFC_FIRST_FRAG){
+ /* First fragment, possibly the only fragment */
+ /*
+ * XXX - should there be a third routine for each
+ * function in an RPC subdissector, to handle
+ * fault responses? The DCE RPC 1.1 spec says
+ * three's "stub data" here, which I infer means
+ * that it's protocol-specific and call-specific.
+ *
+ * It should probably get passed the status code
+ * as well, as that might be protocol-specific.
+ */
+ if (dcerpc_tree) {
+ if (stub_length > 0) {
+ proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
+ "Fault stub data (%d byte%s)",
+ stub_length,
+ plurality(stub_length, "", "s"));
+ }
+ }
+ } else {
+ /* PDU is fragmented and this isn't the first fragment */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " [DCE/RPC fragment]");
+ }
+ if (dcerpc_tree) {
+ if (stub_length > 0) {
+ proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
+ "Fragment data (%d byte%s)",
+ stub_length,
+ plurality(stub_length, "", "s"));
+ }
+ }
+ }
+ } else {
+ /* Reassembly is enabled, the PDU is fragmented, and
+ we have all the data in the fragment; the first two
+ of those mean we should attempt reassembly, and the
+ third means we can attempt reassembly. */
+ if (dcerpc_tree) {
+ if (length > 0) {
+ proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
+ "Fragment data (%d byte%s)",
+ stub_length,
+ plurality(stub_length, "", "s"));
+ }
+ }
+ if(hdr->flags&PFC_FIRST_FRAG){ /* FIRST fragment */
+ if( (!pinfo->fd->flags.visited) && value->rep_frame ){
+ fragment_add(tvb, offset, pinfo, value->rep_frame,
+ dcerpc_co_reassemble_table,
+ 0,
+ stub_length,
+ TRUE);
+ fragment_set_tot_len(pinfo, value->rep_frame,
+ dcerpc_co_reassemble_table, alloc_hint);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " [DCE/RPC fragment]");
+ }
+ } else if(hdr->flags&PFC_LAST_FRAG){ /* LAST fragment */
+ if( value->rep_frame ){
+ fragment_data *fd_head;
+ guint32 tot_len;
+
+ tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
+ dcerpc_co_reassemble_table);
+ fd_head = fragment_add(tvb, offset, pinfo,
+ value->rep_frame,
+ dcerpc_co_reassemble_table,
+ tot_len-alloc_hint,
+ stub_length,
+ TRUE);
+
+ if(fd_head){
+ /* We completed reassembly */
+ tvbuff_t *next_tvb;
+
+ next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
+ show_fragment_tree(fd_head, &dcerpc_frag_items,
+ dcerpc_tree, pinfo, next_tvb);
+
+ /*
+ * XXX - should there be a third routine for each
+ * function in an RPC subdissector, to handle
+ * fault responses? The DCE RPC 1.1 spec says
+ * three's "stub data" here, which I infer means
+ * that it's protocol-specific and call-specific.
+ *
+ * It should probably get passed the status code
+ * as well, as that might be protocol-specific.
+ */
+ if (dcerpc_tree) {
+ if (length > 0) {
+ proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
+ "Fault stub data (%d byte%s)",
+ stub_length,
+ plurality(stub_length, "", "s"));
+ }
+ }
+ } else {
+ /* Reassembly not complete - some fragments
+ are missing */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " [DCE/RPC fragment]");
+ }
+ }
+ }
+ } else { /* MIDDLE fragment(s) */
+ if( (!pinfo->fd->flags.visited) && value->rep_frame ){
+ guint32 tot_len;
+ tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
+ dcerpc_co_reassemble_table);
+ fragment_add(tvb, offset, pinfo, value->rep_frame,
+ dcerpc_co_reassemble_table,
+ tot_len-alloc_hint,
+ stub_length,
+ TRUE);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " [DCE/RPC fragment]");
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * DCERPC dissector for connection oriented calls.
+ * We use transport type to later multiplex between what kind of
+ * pinfo->private_data structure to expect.
+ */
+static gboolean
+dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, gboolean can_desegment, int *pkt_len,
+ int transport_type)
+{
+ static const guint8 nulls[4] = { 0 };
+ int start_offset;
+ int padding = 0;
+ proto_item *ti = NULL;
+ proto_item *tf = NULL;
+ proto_tree *dcerpc_tree = NULL;
+ proto_tree *cn_flags_tree = NULL;
+ proto_tree *drep_tree = NULL;
+ e_dce_cn_common_hdr_t hdr;
+ dcerpc_auth_info auth_info;
+
+ /*
+ * when done over nbt, dcerpc requests are padded with 4 bytes of null
+ * data for some reason.
+ *
+ * XXX - if that's always the case, the right way to do this would
+ * be to have a "dissect_dcerpc_cn_nb" routine which strips off
+ * the 4 bytes of null padding, and make that the dissector
+ * used for "netbios".
+ */
+ if (tvb_memeql (tvb, offset, nulls, 4) == 0) {
+
+ /*
+ * Skip the padding.
+ */
+ offset += 4;
+ padding += 4;
+ }
+
+ /*
+ * Check if this looks like a C/O DCERPC call
+ */
+ if (!tvb_bytes_exist (tvb, offset, sizeof (hdr))) {
+ return FALSE; /* not enough information to check */
+ }
+ start_offset = offset;
+ hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
+ if (hdr.rpc_ver != 5)
+ return FALSE;
+ hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
+ if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
+ return FALSE;
+ hdr.ptype = tvb_get_guint8 (tvb, offset++);
+ if (hdr.ptype > 19)
+ return FALSE;
+
+ hdr.flags = tvb_get_guint8 (tvb, offset++);
+ tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
+ offset += sizeof (hdr.drep);
+
+ hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
+ offset += 2;
+ hdr.auth_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
+ offset += 2;
+ hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
+ offset += 4;
+
+ if (can_desegment && pinfo->can_desegment
+ && !tvb_bytes_exist(tvb, start_offset, hdr.frag_len)) {
+ pinfo->desegment_offset = start_offset;
+ pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, start_offset);
+ *pkt_len = 0; /* desegmentation required */
+ return TRUE;
+ }
+
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_add_fstr (pinfo->cinfo, COL_INFO, "%s: call_id: %u",
+ pckt_vals[hdr.ptype].strptr, hdr.call_id);
+
+ if (tree) {
+ offset = start_offset;
+ ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
+ if (ti) {
+ dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
+ }
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset++, 1, hdr.rpc_ver_minor);
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
+ tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
+ cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
+ if (cn_flags_tree) {
+ proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
+ proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
+ proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
+ proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
+ proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
+ proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
+ proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
+ proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
+ }
+ offset++;
+
+ tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, 4, hdr.drep);
+ drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
+ if (drep_tree) {
+ proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
+ proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
+ proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
+ }
+ offset += sizeof (hdr.drep);
+
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
+ offset += 2;
+
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
+ offset += 2;
+
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
+ offset += 4;
+ }
+
+ /*
+ * None of the stuff done above should throw an exception, because
+ * we would have rejected this as "not DCE RPC" if we didn't have all
+ * of it. (XXX - perhaps we should request reassembly if we have
+ * enough of the header to consider it DCE RPC but not enough to
+ * get the fragment length; in that case the stuff still wouldn't
+ * throw an exception.)
+ *
+ * The rest of the stuff might, so return the PDU length to our caller.
+ * XXX - should we construct a tvbuff containing only the PDU and
+ * use that? Or should we have separate "is this a DCE RPC PDU",
+ * "how long is it", and "dissect it" routines - which might let us
+ * do most of the work in "tcp_dissect_pdus()"?
+ */
+ if (pkt_len != NULL)
+ *pkt_len = hdr.frag_len + padding;
+
+ /*
+ * Packet type specific stuff is next.
+ */
+ switch (hdr.ptype) {
+ case PDU_BIND:
+ case PDU_ALTER:
+ dissect_dcerpc_cn_bind (tvb, offset, pinfo, dcerpc_tree, &hdr, transport_type);
+ break;
+
+ case PDU_BIND_ACK:
+ case PDU_ALTER_ACK:
+ dissect_dcerpc_cn_bind_ack (tvb, offset, pinfo, dcerpc_tree, &hdr);
+ break;
+
+ case PDU_AUTH3:
+ /*
+ * Nothing after the common header other than credentials.
+ */
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, &hdr, TRUE,
+ &auth_info);
+ break;
+
+ case PDU_REQ:
+ dissect_dcerpc_cn_rqst (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, transport_type);
+ break;
+
+ case PDU_RESP:
+ dissect_dcerpc_cn_resp (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, transport_type);
+ break;
+
+ case PDU_FAULT:
+ dissect_dcerpc_cn_fault (tvb, offset, pinfo, dcerpc_tree, &hdr, transport_type);
+ break;
+
+ case PDU_BIND_NAK:
+ dissect_dcerpc_cn_bind_nak (tvb, offset, pinfo, dcerpc_tree, &hdr);
+ break;
+
+ case PDU_CO_CANCEL:
+ case PDU_ORPHANED:
+ /*
+ * Nothing after the common header other than an authentication
+ * verifier.
+ */
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
+ &auth_info);
+ break;
+
+ case PDU_SHUTDOWN:
+ /*
+ * Nothing after the common header, not even an authentication
+ * verifier.
+ */
+ break;
+
+ default:
+ /* might as well dissect the auth info */
+ dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
+ &auth_info);
+ break;
+ }
+ return TRUE;
+}
+
+/*
+ * DCERPC dissector for connection oriented calls over packet-oriented
+ * transports
+ */
+static gboolean
+dissect_dcerpc_cn_pk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /*
+ * Only one PDU per transport packet, and only one transport
+ * packet per PDU.
+ */
+ if (!dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE, NULL, DCE_TRANSPORT_UNKNOWN)) {
+ /*
+ * It wasn't a DCERPC PDU.
+ */
+ return FALSE;
+ } else {
+ /*
+ * It was.
+ */
+ return TRUE;
+ }
+}
+
+/*
+ * DCERPC dissector for connection oriented calls over byte-stream
+ * transports.
+ * we need to distinguish here between SMB and non-TCP (more in the future?)
+ * to be able to know what kind of private_data structure to expect.
+ */
+static gboolean
+dissect_dcerpc_cn_bs_body (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int transport_type)
+{
+ volatile int offset = 0;
+ int pdu_len;
+ volatile gboolean is_dcerpc_pdu;
+ volatile gboolean ret = FALSE;
+
+ /*
+ * There may be multiple PDUs per transport packet; keep
+ * processing them.
+ */
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * Catch ReportedBoundsError, so that even if the stub data is bad,
+ * we don't abort the full DCE RPC dissection - there might be more
+ * than one DCE RPC PDU in the data being dissected.
+ *
+ * If we get BoundsError, it means the frame was cut short by a
+ * snapshot length, so there's nothing more to dissect; just
+ * re-throw that exception.
+ */
+ is_dcerpc_pdu = FALSE;
+ TRY {
+ is_dcerpc_pdu = dissect_dcerpc_cn (tvb, offset, pinfo, tree,
+ dcerpc_cn_desegment, &pdu_len,
+ transport_type);
+ } CATCH(BoundsError) {
+ RETHROW;
+ } CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ } ENDTRY;
+
+ if (!is_dcerpc_pdu) {
+ /*
+ * Not a DCERPC PDU.
+ */
+ break;
+ }
+
+ /*
+ * Well, we've seen at least one DCERPC PDU.
+ */
+ ret = TRUE;
+
+ if (pdu_len == 0) {
+ /*
+ * Desegmentation required - bail now.
+ */
+ break;
+ }
+
+ /*
+ * Step to the next PDU.
+ */
+ offset += pdu_len;
+ }
+ return ret;
+}
+
+static gboolean
+dissect_dcerpc_cn_bs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree, DCE_TRANSPORT_UNKNOWN);
+}
+
+static gboolean
+dissect_dcerpc_cn_smbpipe (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree, DCE_CN_TRANSPORT_SMBPIPE);
+}
+
+
+
+static void
+dissect_dcerpc_dg_auth (tvbuff_t *tvb, int offset, proto_tree *dcerpc_tree,
+ e_dce_dg_common_hdr_t *hdr, int *auth_level_p)
+{
+ proto_item *ti = NULL;
+ proto_tree *auth_tree = NULL;
+ guint8 protection_level;
+
+ /*
+ * Initially set "*auth_level_p" to -1 to indicate that we haven't
+ * yet seen any authentication level information.
+ */
+ if (auth_level_p != NULL)
+ *auth_level_p = -1;
+
+ /*
+ * The authentication information is at the *end* of the PDU; in
+ * request and response PDUs, the request and response stub data
+ * come before it.
+ *
+ * If the full packet is here, and there's data past the end of the
+ * packet body, then dissect the auth info.
+ */
+ offset += hdr->frag_len;
+ if (tvb_length_remaining(tvb, offset) > 0) {
+ switch (hdr->auth_proto) {
+
+ case DCE_C_RPC_AUTHN_PROTOCOL_KRB5:
+ ti = proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Kerberos authentication verifier");
+ auth_tree = proto_item_add_subtree (ti, ett_dcerpc_krb5_auth_verf);
+ protection_level = tvb_get_guint8 (tvb, offset);
+ if (auth_level_p != NULL)
+ *auth_level_p = protection_level;
+ proto_tree_add_uint (auth_tree, hf_dcerpc_krb5_av_prot_level, tvb, offset, 1, protection_level);
+ offset++;
+ proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_vers_num, tvb, offset, 1, FALSE);
+ offset++;
+ if (protection_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY)
+ offset += 6; /* 6 bytes of padding */
+ else
+ offset += 2; /* 6 bytes of padding */
+ proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_auth_verifier, tvb, offset, 16, FALSE);
+ offset += 16;
+ break;
+
+ default:
+ proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Authentication verifier");
+ break;
+ }
+ }
+}
+
+static void
+dissect_dcerpc_dg_cancel_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree,
+ e_dce_dg_common_hdr_t *hdr)
+{
+ guint32 version;
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_cancel_vers,
+ &version);
+
+ switch (version) {
+
+ case 0:
+ /* The only version we know about */
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_cancel_id,
+ NULL);
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
+ NULL);
+ break;
+ }
+}
+
+static void
+dissect_dcerpc_dg_cancel (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree,
+ e_dce_dg_common_hdr_t *hdr)
+{
+ guint32 version;
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_cancel_vers,
+ &version);
+
+ switch (version) {
+
+ case 0:
+ /* The only version we know about */
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_cancel_id,
+ NULL);
+ /* XXX - are NDR booleans 32 bits? */
+
+ /* XXX - the RPC reference in chapter: "the cancel PDU" doesn't mention
+ the accepting_cancels field (it's only in the cancel_ack PDU)! */
+ /*offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
+ NULL);*/
+ break;
+ }
+}
+
+static void
+dissect_dcerpc_dg_fack (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree,
+ e_dce_dg_common_hdr_t *hdr)
+{
+ guint8 version;
+ guint16 serial_num;
+ guint16 selack_len;
+ guint i;
+
+ offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_fack_vers,
+ &version);
+ /* padding */
+ offset++;
+
+ switch (version) {
+
+ case 0: /* The only version documented in the DCE RPC 1.1 spec */
+ case 1: /* This appears to be the same */
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_fack_window_size,
+ NULL);
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_fack_max_tsdu,
+ NULL);
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_fack_max_frag_size,
+ NULL);
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_fack_serial_num,
+ &serial_num);
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, " serial: %u",
+ serial_num);
+ }
+ offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_fack_selack_len,
+ &selack_len);
+ for (i = 0; i < selack_len; i++) {
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_fack_selack,
+ NULL);
+ }
+
+ break;
+ }
+}
+
+static void
+dissect_dcerpc_dg_reject_fault (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree,
+ e_dce_dg_common_hdr_t *hdr)
+{
+ guint32 status;
+
+ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
+ hdr->drep, hf_dcerpc_dg_status,
+ &status);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ ": status: %s",
+ val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
+ }
+}
+
+static void
+dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, proto_tree *tree,
+ e_dce_dg_common_hdr_t *hdr, dcerpc_info *di)
+{
+ int length, reported_length, stub_length;
+ gboolean save_fragmented;
+ fragment_data *fd_head;
+ tvbuff_t *next_tvb;
+ proto_item *pi;
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u len: %u",
+ di->call_data->opnum, hdr->frag_len );
+
+ length = tvb_length_remaining (tvb, offset);
+ reported_length = tvb_reported_length_remaining (tvb, offset);
+ stub_length = hdr->frag_len;
+ if (length > stub_length)
+ length = stub_length;
+ if (reported_length > stub_length)
+ reported_length = stub_length;
+
+ save_fragmented = pinfo->fragmented;
+
+ /* If we don't have reassembly enabled, or this packet contains
+ the entire PDU, or if this is a short frame (or a frame
+ not reassembled at a lower layer) that doesn't include all
+ the data in the fragment, just call the handoff directly if
+ this is the first fragment or the PDU isn't fragmented. */
+ if( (!dcerpc_reassemble) || !(hdr->flags1 & PFCL1_FRAG) ||
+ !tvb_bytes_exist(tvb, offset, stub_length) ){
+ if(hdr->frag_num == 0) {
+
+
+ /* First fragment, possibly the only fragment */
+
+ /*
+ * XXX - authentication info?
+ */
+ pinfo->fragmented = (hdr->flags1 & PFCL1_FRAG);
+ next_tvb = tvb_new_subset (tvb, offset, length,
+ reported_length);
+ dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
+ next_tvb, hdr->drep, di, NULL);
+ } else {
+ /* PDU is fragmented and this isn't the first fragment */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
+ }
+ if (dcerpc_tree) {
+ if (length > 0) {
+ proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
+ "Fragment data (%d byte%s)",
+ stub_length,
+ plurality(stub_length, "", "s"));
+ }
+ }
+ }
+ } else {
+ /* Reassembly is enabled, the PDU is fragmented, and
+ we have all the data in the fragment; the first two
+ of those mean we should attempt reassembly, and the
+ third means we can attempt reassembly. */
+ if (dcerpc_tree) {
+ if (length > 0) {
+ proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
+ "Fragment data (%d byte%s)", stub_length,
+ plurality(stub_length, "", "s"));
+ }
+ }
+
+ fd_head = fragment_add_dcerpc(tvb, offset, pinfo,
+ hdr->seqnum, &hdr->act_id, dcerpc_cl_reassemble_table,
+ hdr->frag_num, stub_length,
+ !(hdr->flags1 & PFCL1_LASTFRAG));
+ if (fd_head != NULL) {
+ /* We completed reassembly... */
+ if(pinfo->fd->num==fd_head->reassembled_in) {
+ /* ...and this is the reassembled RPC PDU */
+ next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
+ show_fragment_seq_tree(fd_head, &dcerpc_frag_items,
+ dcerpc_tree, pinfo, next_tvb);
+
+ /*
+ * XXX - authentication info?
+ */
+ pinfo->fragmented = FALSE;
+ dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
+ next_tvb, hdr->drep, di, NULL);
+ } else {
+ /* ...and this isn't the reassembled RPC PDU */
+ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
+ tvb, 0, 0, fd_head->reassembled_in);
+ PROTO_ITEM_SET_GENERATED(pi);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " [DCE/RPC fragment, reas: #%u]", fd_head->reassembled_in);
+ }
+ }
+ } else {
+ /* Reassembly isn't completed yet */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
+ }
+ }
+ }
+ pinfo->fragmented = save_fragmented;
+}
+
+static void
+dissect_dcerpc_dg_rqst (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, proto_tree *tree,
+ e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
+{
+ dcerpc_info *di;
+ dcerpc_call_value *value, v;
+ dcerpc_matched_key matched_key, *new_matched_key;
+ proto_item *pi;
+
+ di=get_next_di();
+ if(!(pinfo->fd->flags.visited)){
+ dcerpc_call_value *call_value;
+ dcerpc_dg_call_key *call_key;
+
+ call_key=g_mem_chunk_alloc (dcerpc_dg_call_key_chunk);
+ call_key->conv=conv;
+ call_key->seqnum=hdr->seqnum;
+ call_key->act_id=hdr->act_id;
+
+ call_value=g_mem_chunk_alloc (dcerpc_call_value_chunk);
+ call_value->uuid = hdr->if_id;
+ call_value->ver = hdr->if_ver;
+ call_value->opnum = hdr->opnum;
+ call_value->req_frame=pinfo->fd->num;
+ call_value->req_time.secs=pinfo->fd->abs_secs;
+ call_value->req_time.nsecs=pinfo->fd->abs_usecs*1000;
+ call_value->rep_frame=0;
+ call_value->max_ptr=0;
+ call_value->private_data = NULL;
+ g_hash_table_insert (dcerpc_dg_calls, call_key, call_value);
+
+ new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+ new_matched_key->frame = pinfo->fd->num;
+ new_matched_key->call_id = hdr->seqnum;
+ g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
+ }
+
+ matched_key.frame = pinfo->fd->num;
+ matched_key.call_id = hdr->seqnum;
+ value=g_hash_table_lookup(dcerpc_matched, &matched_key);
+ if (!value) {
+ v.uuid = hdr->if_id;
+ v.ver = hdr->if_ver;
+ v.opnum = hdr->opnum;
+ v.req_frame = pinfo->fd->num;
+ v.rep_frame = 0;
+ v.max_ptr = 0;
+ v.private_data=NULL;
+ value = &v;
+ }
+
+ di->conv = conv;
+ di->call_id = hdr->seqnum;
+ di->smb_fid = -1;
+ di->ptype = PDU_REQ;
+ di->call_data = value;
+
+ if(value->rep_frame!=0){
+ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
+ tvb, 0, 0, value->rep_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
+}
+
+static void
+dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *dcerpc_tree, proto_tree *tree,
+ e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
+{
+ dcerpc_info *di;
+ dcerpc_call_value *value, v;
+ dcerpc_matched_key matched_key, *new_matched_key;
+ proto_item *pi;
+
+ di=get_next_di();
+ if(!(pinfo->fd->flags.visited)){
+ dcerpc_call_value *call_value;
+ dcerpc_dg_call_key call_key;
+
+ call_key.conv=conv;
+ call_key.seqnum=hdr->seqnum;
+ call_key.act_id=hdr->act_id;
+
+ if((call_value=g_hash_table_lookup(dcerpc_dg_calls, &call_key))){
+ new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
+ new_matched_key->frame = pinfo->fd->num;
+ new_matched_key->call_id = hdr->seqnum;
+ g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
+ if(call_value->rep_frame==0){
+ call_value->rep_frame=pinfo->fd->num;
+ }
+ }
+ }
+
+ matched_key.frame = pinfo->fd->num;
+ matched_key.call_id = hdr->seqnum;
+ value=g_hash_table_lookup(dcerpc_matched, &matched_key);
+ if (!value) {
+ v.uuid = hdr->if_id;
+ v.ver = hdr->if_ver;
+ v.opnum = hdr->opnum;
+ v.req_frame=0;
+ v.rep_frame=pinfo->fd->num;
+ v.private_data=NULL;
+ value = &v;
+ }
+
+ di->conv = conv;
+ di->call_id = 0;
+ di->smb_fid = -1;
+ di->ptype = PDU_RESP;
+ di->call_data = value;
+
+ if(value->req_frame!=0){
+ nstime_t ns;
+ pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
+ tvb, 0, 0, value->req_frame);
+ PROTO_ITEM_SET_GENERATED(pi);
+ ns.secs= pinfo->fd->abs_secs-value->req_time.secs;
+ ns.nsecs=pinfo->fd->abs_usecs*1000-value->req_time.nsecs;
+ if(ns.nsecs<0){
+ ns.nsecs+=1000000000;
+ ns.secs--;
+ }
+ pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
+ PROTO_ITEM_SET_GENERATED(pi);
+ }
+ dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
+}
+
+/*
+ * DCERPC dissector for connectionless calls
+ */
+static gboolean
+dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti = NULL;
+ proto_item *tf = NULL;
+ proto_tree *dcerpc_tree = NULL;
+ proto_tree *dg_flags1_tree = NULL;
+ proto_tree *dg_flags2_tree = NULL;
+ proto_tree *drep_tree = NULL;
+ e_dce_dg_common_hdr_t hdr;
+ int offset = 0;
+ conversation_t *conv;
+ int auth_level;
+ char uuid_str[DCERPC_UUID_STR_LEN];
+ int uuid_str_len;
+
+ /*
+ * Check if this looks like a CL DCERPC call. All dg packets
+ * have an 80 byte header on them. Which starts with
+ * version (4), pkt_type.
+ */
+ if (!tvb_bytes_exist (tvb, 0, sizeof (hdr))) {
+ return FALSE;
+ }
+ hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
+ if (hdr.rpc_ver != 4)
+ return FALSE;
+ hdr.ptype = tvb_get_guint8 (tvb, offset++);
+ if (hdr.ptype > 19)
+ return FALSE;
+
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_add_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
+
+ hdr.flags1 = tvb_get_guint8 (tvb, offset++);
+ hdr.flags2 = tvb_get_guint8 (tvb, offset++);
+ tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
+ offset += sizeof (hdr.drep);
+ hdr.serial_hi = tvb_get_guint8 (tvb, offset++);
+ dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.obj_id);
+ offset += 16;
+ dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.if_id);
+ offset += 16;
+ dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.act_id);
+ offset += 16;
+ hdr.server_boot = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
+ offset += 4;
+ hdr.if_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
+ offset += 4;
+ hdr.seqnum = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
+ offset += 4;
+ hdr.opnum = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
+ offset += 2;
+ hdr.ihint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
+ offset += 2;
+ hdr.ahint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
+ offset += 2;
+ hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
+ offset += 2;
+ hdr.frag_num = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
+ offset += 2;
+ hdr.auth_proto = tvb_get_guint8 (tvb, offset++);
+ hdr.serial_lo = tvb_get_guint8 (tvb, offset++);
+
+ if (tree) {
+ ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, -1, FALSE);
+ if (ti) {
+ dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
+ }
+ }
+ offset = 0;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
+ offset++;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
+ offset++;
+
+ if (tree) {
+ tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags1, tvb, offset, 1, hdr.flags1);
+ dg_flags1_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags1);
+ if (dg_flags1_tree) {
+ proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_80, tvb, offset, 1, hdr.flags1);
+ proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_broadcast, tvb, offset, 1, hdr.flags1);
+ proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_idempotent, tvb, offset, 1, hdr.flags1);
+ proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_maybe, tvb, offset, 1, hdr.flags1);
+ proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_nofack, tvb, offset, 1, hdr.flags1);
+ proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, hdr.flags1);
+ proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, hdr.flags1);
+ proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, hdr.flags1);
+ }
+ }
+ offset++;
+
+ if (tree) {
+ tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags2, tvb, offset, 1, hdr.flags2);
+ dg_flags2_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags2);
+ if (dg_flags2_tree) {
+ proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_80, tvb, offset, 1, hdr.flags2);
+ proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_40, tvb, offset, 1, hdr.flags2);
+ proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_20, tvb, offset, 1, hdr.flags2);
+ proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_10, tvb, offset, 1, hdr.flags2);
+ proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_08, tvb, offset, 1, hdr.flags2);
+ proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, hdr.flags2);
+ proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, hdr.flags2);
+ proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, hdr.flags2);
+ }
+ }
+ offset++;
+
+ if (tree) {
+ tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, sizeof (hdr.drep), hdr.drep);
+ drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
+ if (drep_tree) {
+ proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
+ proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
+ proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
+ }
+ }
+ offset += sizeof (hdr.drep);
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_hi, tvb, offset, 1, hdr.serial_hi);
+ offset++;
+
+ if (tree) {
+ /* XXX - use "dissect_ndr_uuid_t()"? */
+ uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ hdr.obj_id.Data1, hdr.obj_id.Data2, hdr.obj_id.Data3,
+ hdr.obj_id.Data4[0],
+ hdr.obj_id.Data4[1],
+ hdr.obj_id.Data4[2],
+ hdr.obj_id.Data4[3],
+ hdr.obj_id.Data4[4],
+ hdr.obj_id.Data4[5],
+ hdr.obj_id.Data4[6],
+ hdr.obj_id.Data4[7]);
+ if (uuid_str_len >= DCERPC_UUID_STR_LEN)
+ memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
+ proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
+ offset, 16, uuid_str, "Object UUID: %s", uuid_str);
+ }
+ offset += 16;
+
+ if (tree) {
+ /* XXX - use "dissect_ndr_uuid_t()"? */
+ uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ hdr.if_id.Data1, hdr.if_id.Data2, hdr.if_id.Data3,
+ hdr.if_id.Data4[0],
+ hdr.if_id.Data4[1],
+ hdr.if_id.Data4[2],
+ hdr.if_id.Data4[3],
+ hdr.if_id.Data4[4],
+ hdr.if_id.Data4[5],
+ hdr.if_id.Data4[6],
+ hdr.if_id.Data4[7]);
+ if (uuid_str_len >= DCERPC_UUID_STR_LEN)
+ memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
+ proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
+ offset, 16, uuid_str, "Interface: %s", uuid_str);
+ }
+ offset += 16;
+
+ if (tree) {
+ /* XXX - use "dissect_ndr_uuid_t()"? */
+ uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ hdr.act_id.Data1, hdr.act_id.Data2, hdr.act_id.Data3,
+ hdr.act_id.Data4[0],
+ hdr.act_id.Data4[1],
+ hdr.act_id.Data4[2],
+ hdr.act_id.Data4[3],
+ hdr.act_id.Data4[4],
+ hdr.act_id.Data4[5],
+ hdr.act_id.Data4[6],
+ hdr.act_id.Data4[7]);
+ if (uuid_str_len >= DCERPC_UUID_STR_LEN)
+ memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
+ proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
+ offset, 16, uuid_str, "Activity: %s", uuid_str);
+ }
+ offset += 16;
+
+ if (tree) {
+ nstime_t server_boot;
+
+ server_boot.secs = hdr.server_boot;
+ server_boot.nsecs = 0;
+
+ if (hdr.server_boot == 0)
+ proto_tree_add_time_format (dcerpc_tree, hf_dcerpc_dg_server_boot,
+ tvb, offset, 4, &server_boot,
+ "Server boot time: Unknown (0)");
+ else
+ proto_tree_add_time (dcerpc_tree, hf_dcerpc_dg_server_boot,
+ tvb, offset, 4, &server_boot);
+ }
+ offset += 4;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_if_ver, tvb, offset, 4, hdr.if_ver);
+ offset += 4;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_seqnum, tvb, offset, 4, hdr.seqnum);
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, ": seq: %u", hdr.seqnum);
+ }
+ offset += 4;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, offset, 2, hdr.opnum);
+ offset += 2;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ihint, tvb, offset, 2, hdr.ihint);
+ offset += 2;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ahint, tvb, offset, 2, hdr.ahint);
+ offset += 2;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_len, tvb, offset, 2, hdr.frag_len);
+ offset += 2;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_num, tvb, offset, 2, hdr.frag_num);
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if (hdr.flags1 & PFCL1_FRAG) {
+ /* Fragmented - put the fragment number into the Info column */
+ col_append_fstr (pinfo->cinfo, COL_INFO, " frag: %u",
+ hdr.frag_num);
+ }
+ }
+ offset += 2;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_auth_proto, tvb, offset, 1, hdr.auth_proto);
+ offset++;
+
+ if (tree)
+ proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 1, hdr.serial_lo);
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if (hdr.flags1 & PFCL1_FRAG) {
+ /* Fragmented - put the serial number into the Info column */
+ col_append_fstr (pinfo->cinfo, COL_INFO, " serial: %u",
+ (hdr.serial_hi << 8) | hdr.serial_lo);
+ }
+ }
+ offset++;
+
+ if (tree) {
+ /*
+ * XXX - for Kerberos, we get a protection level; if it's
+ * DCE_C_AUTHN_LEVEL_PKT_PRIVACY, we can't dissect the
+ * stub data.
+ */
+ dissect_dcerpc_dg_auth (tvb, offset, dcerpc_tree, &hdr,
+ &auth_level);
+ }
+
+ /*
+ * keeping track of the conversation shouldn't really be necessary
+ * for connectionless packets, because everything we need to know
+ * to dissect is in the header for each packet. Unfortunately,
+ * Microsoft's implementation is buggy and often puts the
+ * completely wrong if_id in the header. go figure. So, keep
+ * track of the seqnum and use that if possible. Note: that's not
+ * completely correct. It should really be done based on both the
+ * activity_id and seqnum. I haven't seen anywhere that it would
+ * make a difference, but for future reference...
+ */
+ conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (!conv) {
+ conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+
+ /*
+ * Packet type specific stuff is next.
+ */
+
+ switch (hdr.ptype) {
+
+ case PDU_CANCEL_ACK:
+ /* Body is optional */
+ /* XXX - we assume "frag_len" is the length of the body */
+ if (hdr.frag_len != 0)
+ dissect_dcerpc_dg_cancel_ack (tvb, offset, pinfo, dcerpc_tree, &hdr);
+ break;
+
+ case PDU_CL_CANCEL:
+ /*
+ * XXX - The DCE RPC 1.1 spec doesn't say the body is optional,
+ * but in at least one capture none of the Cl_cancel PDUs had a
+ * body.
+ */
+ /* XXX - we assume "frag_len" is the length of the body */
+ if (hdr.frag_len != 0)
+ dissect_dcerpc_dg_cancel (tvb, offset, pinfo, dcerpc_tree, &hdr);
+ break;
+
+ case PDU_NOCALL:
+ /* Body is optional; if present, it's the same as PDU_FACK */
+ /* XXX - we assume "frag_len" is the length of the body */
+ if (hdr.frag_len != 0)
+ dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
+ break;
+
+ case PDU_FACK:
+ dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
+ break;
+
+ case PDU_REJECT:
+ case PDU_FAULT:
+ dissect_dcerpc_dg_reject_fault (tvb, offset, pinfo, dcerpc_tree, &hdr);
+ break;
+
+ case PDU_REQ:
+ dissect_dcerpc_dg_rqst (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
+ break;
+
+ case PDU_RESP:
+ dissect_dcerpc_dg_resp (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
+ break;
+
+ /* these requests have no body */
+ case PDU_ACK:
+ case PDU_PING:
+ case PDU_WORKING:
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+dcerpc_init_protocol (void)
+{
+ /* structures and data for BIND */
+ if (dcerpc_binds){
+ g_hash_table_destroy (dcerpc_binds);
+ }
+ dcerpc_binds = g_hash_table_new (dcerpc_bind_hash, dcerpc_bind_equal);
+
+ if (dcerpc_bind_key_chunk){
+ g_mem_chunk_destroy (dcerpc_bind_key_chunk);
+ }
+ dcerpc_bind_key_chunk = g_mem_chunk_new ("dcerpc_bind_key_chunk",
+ sizeof (dcerpc_bind_key),
+ 200 * sizeof (dcerpc_bind_key),
+ G_ALLOC_ONLY);
+ if (dcerpc_bind_value_chunk){
+ g_mem_chunk_destroy (dcerpc_bind_value_chunk);
+ }
+ dcerpc_bind_value_chunk = g_mem_chunk_new ("dcerpc_bind_value_chunk",
+ sizeof (dcerpc_bind_value),
+ 200 * sizeof (dcerpc_bind_value),
+ G_ALLOC_ONLY);
+ /* structures and data for CALL */
+ if (dcerpc_cn_calls){
+ g_hash_table_destroy (dcerpc_cn_calls);
+ }
+ dcerpc_cn_calls = g_hash_table_new (dcerpc_cn_call_hash, dcerpc_cn_call_equal);
+ if (dcerpc_dg_calls){
+ g_hash_table_destroy (dcerpc_dg_calls);
+ }
+ dcerpc_dg_calls = g_hash_table_new (dcerpc_dg_call_hash, dcerpc_dg_call_equal);
+ if (dcerpc_cn_call_key_chunk){
+ g_mem_chunk_destroy (dcerpc_cn_call_key_chunk);
+ }
+ dcerpc_cn_call_key_chunk = g_mem_chunk_new ("dcerpc_cn_call_key_chunk",
+ sizeof (dcerpc_cn_call_key),
+ 200 * sizeof (dcerpc_cn_call_key),
+ G_ALLOC_ONLY);
+ if (dcerpc_dg_call_key_chunk){
+ g_mem_chunk_destroy (dcerpc_dg_call_key_chunk);
+ }
+ dcerpc_dg_call_key_chunk = g_mem_chunk_new ("dcerpc_dg_call_key_chunk",
+ sizeof (dcerpc_dg_call_key),
+ 200 * sizeof (dcerpc_dg_call_key),
+ G_ALLOC_ONLY);
+
+ if (dcerpc_call_value_chunk){
+ g_mem_chunk_destroy (dcerpc_call_value_chunk);
+ }
+ dcerpc_call_value_chunk = g_mem_chunk_new ("dcerpc_call_value_chunk",
+ sizeof (dcerpc_call_value),
+ 200 * sizeof (dcerpc_call_value),
+ G_ALLOC_ONLY);
+
+ /* structure and data for MATCHED */
+ if (dcerpc_matched){
+ g_hash_table_destroy (dcerpc_matched);
+ }
+ dcerpc_matched = g_hash_table_new (dcerpc_matched_hash, dcerpc_matched_equal);
+ if (dcerpc_matched_key_chunk){
+ g_mem_chunk_destroy (dcerpc_matched_key_chunk);
+ }
+ dcerpc_matched_key_chunk = g_mem_chunk_new ("dcerpc_matched_key_chunk",
+ sizeof (dcerpc_matched_key),
+ 200 * sizeof (dcerpc_matched_key),
+ G_ALLOC_ONLY);
+}
+
+void
+proto_register_dcerpc (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_dcerpc_request_in,
+ { "Request in frame", "dcerpc.request_in", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "This packet is a response to the packet with this number", HFILL }},
+ { &hf_dcerpc_response_in,
+ { "Response in frame", "dcerpc.response_in", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "This packet will be responded in the packet with this number", HFILL }},
+ { &hf_dcerpc_referent_id,
+ { "Referent ID", "dcerpc.referent_id", FT_UINT32, BASE_HEX,
+ NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }},
+ { &hf_dcerpc_ver,
+ { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_ver_minor,
+ { "Version (minor)", "dcerpc.ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_packet_type,
+ { "Packet type", "dcerpc.pkt_type", FT_UINT8, BASE_DEC, VALS (pckt_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_flags,
+ { "Packet Flags", "dcerpc.cn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_flags_first_frag,
+ { "First Frag", "dcerpc.cn_flags.first_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_FIRST_FRAG, "", HFILL }},
+ { &hf_dcerpc_cn_flags_last_frag,
+ { "Last Frag", "dcerpc.cn_flags.last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_LAST_FRAG, "", HFILL }},
+ { &hf_dcerpc_cn_flags_cancel_pending,
+ { "Cancel Pending", "dcerpc.cn_flags.cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_PENDING_CANCEL, "", HFILL }},
+ { &hf_dcerpc_cn_flags_reserved,
+ { "Reserved", "dcerpc.cn_flags.reserved", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_RESERVED_1, "", HFILL }},
+ { &hf_dcerpc_cn_flags_mpx,
+ { "Multiplex", "dcerpc.cn_flags.mpx", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_CONC_MPX, "", HFILL }},
+ { &hf_dcerpc_cn_flags_dne,
+ { "Did Not Execute", "dcerpc.cn_flags.dne", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_DID_NOT_EXECUTE, "", HFILL }},
+ { &hf_dcerpc_cn_flags_maybe,
+ { "Maybe", "dcerpc.cn_flags.maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_MAYBE, "", HFILL }},
+ { &hf_dcerpc_cn_flags_object,
+ { "Object", "dcerpc.cn_flags.object", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_OBJECT_UUID, "", HFILL }},
+ { &hf_dcerpc_drep,
+ { "Data Representation", "dcerpc.drep", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_drep_byteorder,
+ { "Byte order", "dcerpc.drep.byteorder", FT_UINT8, BASE_DEC, VALS (drep_byteorder_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_drep_character,
+ { "Character", "dcerpc.drep.character", FT_UINT8, BASE_DEC, VALS (drep_character_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_drep_fp,
+ { "Floating-point", "dcerpc.drep.fp", FT_UINT8, BASE_DEC, VALS (drep_fp_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_frag_len,
+ { "Frag Length", "dcerpc.cn_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_auth_len,
+ { "Auth Length", "dcerpc.cn_auth_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_call_id,
+ { "Call ID", "dcerpc.cn_call_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_max_xmit,
+ { "Max Xmit Frag", "dcerpc.cn_max_xmit", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_max_recv,
+ { "Max Recv Frag", "dcerpc.cn_max_recv", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_assoc_group,
+ { "Assoc Group", "dcerpc.cn_assoc_group", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_num_ctx_items,
+ { "Num Ctx Items", "dcerpc.cn_num_ctx_items", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_ctx_id,
+ { "Context ID", "dcerpc.cn_ctx_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_num_trans_items,
+ { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_bind_if_id,
+ { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_bind_if_ver,
+ { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_bind_if_ver_minor,
+ { "Interface Ver Minor", "dcerpc.cn_bind_if_ver_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_bind_trans_id,
+ { "Transfer Syntax", "dcerpc.cn_bind_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_bind_trans_ver,
+ { "Syntax ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_alloc_hint,
+ { "Alloc hint", "dcerpc.cn_alloc_hint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_sec_addr_len,
+ { "Scndry Addr len", "dcerpc.cn_sec_addr_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_sec_addr,
+ { "Scndry Addr", "dcerpc.cn_sec_addr", FT_STRINGZ, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_num_results,
+ { "Num results", "dcerpc.cn_num_results", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_ack_result,
+ { "Ack result", "dcerpc.cn_ack_result", FT_UINT16, BASE_DEC, VALS(p_cont_result_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_ack_reason,
+ { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, VALS(p_provider_reason_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_ack_trans_id,
+ { "Transfer Syntax", "dcerpc.cn_ack_trans_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_ack_trans_ver,
+ { "Syntax ver", "dcerpc.cn_ack_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_reject_reason,
+ { "Reject reason", "dcerpc.cn_reject_reason", FT_UINT16, BASE_DEC, VALS(reject_reason_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_num_protocols,
+ { "Number of protocols", "dcerpc.cn_num_protocols", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_protocol_ver_major,
+ { "Protocol major version", "dcerpc.cn_protocol_ver_major", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_protocol_ver_minor,
+ { "Protocol minor version", "dcerpc.cn_protocol_ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_cancel_count,
+ { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_cn_status,
+ { "Status", "dcerpc.cn_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_auth_type,
+ { "Auth type", "dcerpc.auth_type", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_auth_level,
+ { "Auth level", "dcerpc.auth_level", FT_UINT8, BASE_DEC, VALS (authn_level_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_auth_pad_len,
+ { "Auth pad len", "dcerpc.auth_pad_len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_auth_rsrvd,
+ { "Auth Rsrvd", "dcerpc.auth_rsrvd", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_auth_ctx_id,
+ { "Auth Context ID", "dcerpc.auth_ctx_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_flags1,
+ { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_flags1_rsrvd_01,
+ { "Reserved", "dcerpc.dg_flags1_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_RESERVED_01, "", HFILL }},
+ { &hf_dcerpc_dg_flags1_last_frag,
+ { "Last Fragment", "dcerpc.dg_flags1_last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_LASTFRAG, "", HFILL }},
+ { &hf_dcerpc_dg_flags1_frag,
+ { "Fragment", "dcerpc.dg_flags1_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_FRAG, "", HFILL }},
+ { &hf_dcerpc_dg_flags1_nofack,
+ { "No Fack", "dcerpc.dg_flags1_nofack", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_NOFACK, "", HFILL }},
+ { &hf_dcerpc_dg_flags1_maybe,
+ { "Maybe", "dcerpc.dg_flags1_maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_MAYBE, "", HFILL }},
+ { &hf_dcerpc_dg_flags1_idempotent,
+ { "Idempotent", "dcerpc.dg_flags1_idempotent", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_IDEMPOTENT, "", HFILL }},
+ { &hf_dcerpc_dg_flags1_broadcast,
+ { "Broadcast", "dcerpc.dg_flags1_broadcast", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_BROADCAST, "", HFILL }},
+ { &hf_dcerpc_dg_flags1_rsrvd_80,
+ { "Reserved", "dcerpc.dg_flags1_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_RESERVED_80, "", HFILL }},
+ { &hf_dcerpc_dg_flags2,
+ { "Flags2", "dcerpc.dg_flags2", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_flags2_rsrvd_01,
+ { "Reserved", "dcerpc.dg_flags2_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_01, "", HFILL }},
+ { &hf_dcerpc_dg_flags2_cancel_pending,
+ { "Cancel Pending", "dcerpc.dg_flags2_cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_CANCEL_PENDING, "", HFILL }},
+ { &hf_dcerpc_dg_flags2_rsrvd_04,
+ { "Reserved", "dcerpc.dg_flags2_rsrvd_04", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_04, "", HFILL }},
+ { &hf_dcerpc_dg_flags2_rsrvd_08,
+ { "Reserved", "dcerpc.dg_flags2_rsrvd_08", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_08, "", HFILL }},
+ { &hf_dcerpc_dg_flags2_rsrvd_10,
+ { "Reserved", "dcerpc.dg_flags2_rsrvd_10", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_10, "", HFILL }},
+ { &hf_dcerpc_dg_flags2_rsrvd_20,
+ { "Reserved", "dcerpc.dg_flags2_rsrvd_20", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_20, "", HFILL }},
+ { &hf_dcerpc_dg_flags2_rsrvd_40,
+ { "Reserved", "dcerpc.dg_flags2_rsrvd_40", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_40, "", HFILL }},
+ { &hf_dcerpc_dg_flags2_rsrvd_80,
+ { "Reserved", "dcerpc.dg_flags2_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_80, "", HFILL }},
+ { &hf_dcerpc_dg_serial_lo,
+ { "Serial Low", "dcerpc.dg_serial_lo", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_serial_hi,
+ { "Serial High", "dcerpc.dg_serial_hi", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_ahint,
+ { "Activity Hint", "dcerpc.dg_ahint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_ihint,
+ { "Interface Hint", "dcerpc.dg_ihint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_frag_len,
+ { "Fragment len", "dcerpc.dg_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_frag_num,
+ { "Fragment num", "dcerpc.dg_frag_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_auth_proto,
+ { "Auth proto", "dcerpc.dg_auth_proto", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_seqnum,
+ { "Sequence num", "dcerpc.dg_seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_server_boot,
+ { "Server boot time", "dcerpc.dg_server_boot", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_if_ver,
+ { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_krb5_av_prot_level,
+ { "Protection Level", "dcerpc.krb5_av.prot_level", FT_UINT8, BASE_DEC, VALS(authn_level_vals), 0x0, "", HFILL }},
+ { &hf_dcerpc_krb5_av_key_vers_num,
+ { "Key Version Number", "dcerpc.krb5_av.key_vers_num", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_krb5_av_key_auth_verifier,
+ { "Authentication Verifier", "dcerpc.krb5_av.auth_verifier", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_obj_id,
+ { "Object", "dcerpc.obj_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_if_id,
+ { "Interface", "dcerpc.dg_if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_dg_act_id,
+ { "Activity", "dcerpc.dg_act_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_dcerpc_opnum,
+ { "Opnum", "dcerpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_cancel_vers,
+ { "Cancel Version", "dcerpc.dg_cancel_vers", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_cancel_id,
+ { "Cancel ID", "dcerpc.dg_cancel_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_server_accepting_cancels,
+ { "Server accepting cancels", "dcerpc.server_accepting_cancels", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_fack_vers,
+ { "FACK Version", "dcerpc.fack_vers", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_fack_window_size,
+ { "Window Size", "dcerpc.fack_window_size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_fack_max_tsdu,
+ { "Max TSDU", "dcerpc.fack_max_tsdu", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_fack_max_frag_size,
+ { "Max Frag Size", "dcerpc.fack_max_frag_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_fack_serial_num,
+ { "Serial Num", "dcerpc.fack_serial_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_fack_selack_len,
+ { "Selective ACK Len", "dcerpc.fack_selack_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_fack_selack,
+ { "Selective ACK", "dcerpc.fack_selack", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_dg_status,
+ { "Status", "dcerpc.dg_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, "", HFILL }},
+
+ { &hf_dcerpc_array_max_count,
+ { "Max Count", "dcerpc.array.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum Count: Number of elements in the array", HFILL }},
+
+ { &hf_dcerpc_array_offset,
+ { "Offset", "dcerpc.array.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "Offset for first element in array", HFILL }},
+
+ { &hf_dcerpc_array_actual_count,
+ { "Actual Count", "dcerpc.array.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Actual Count: Actual number of elements in the array", HFILL }},
+
+ { &hf_dcerpc_array_buffer,
+ { "Buffer", "dcerpc.array.buffer", FT_BYTES, BASE_NONE, NULL, 0x0, "Buffer: Buffer containing elements of the array", HFILL }},
+
+ { &hf_dcerpc_op,
+ { "Operation", "dcerpc.op", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_dcerpc_fragments,
+ { "DCE/RPC Fragments", "dcerpc.fragments", FT_NONE, BASE_NONE,
+ NULL, 0x0, "DCE/RPC Fragments", HFILL }},
+
+ { &hf_dcerpc_fragment,
+ { "DCE/RPC Fragment", "dcerpc.fragment", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "DCE/RPC Fragment", HFILL }},
+
+ { &hf_dcerpc_fragment_overlap,
+ { "Fragment overlap", "dcerpc.fragment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_dcerpc_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "dcerpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_dcerpc_fragment_multiple_tails,
+ { "Multiple tail fragments found", "dcerpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_dcerpc_fragment_too_long_fragment,
+ { "Fragment too long", "dcerpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
+
+ { &hf_dcerpc_fragment_error,
+ { "Defragmentation error", "dcerpc.fragment.error", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
+
+ { &hf_dcerpc_time,
+ { "Time from request", "dcerpc.time", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Time between Request and Response for DCE-RPC calls", HFILL }},
+
+ { &hf_dcerpc_reassembled_in,
+ { "Reassembled PDU in frame", "dcerpc.reassembled_in", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "The DCE/RPC PDU is completely reassembled in the packet with this number", HFILL }},
+
+ { &hf_dcerpc_unknown_if_id,
+ { "Unknown DCERPC interface id", "dcerpc.unknown_if_id", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_dcerpc,
+ &ett_dcerpc_cn_flags,
+ &ett_dcerpc_cn_ctx,
+ &ett_dcerpc_cn_iface,
+ &ett_dcerpc_drep,
+ &ett_dcerpc_dg_flags1,
+ &ett_dcerpc_dg_flags2,
+ &ett_dcerpc_pointer_data,
+ &ett_dcerpc_string,
+ &ett_dcerpc_fragments,
+ &ett_dcerpc_fragment,
+ &ett_dcerpc_krb5_auth_verf,
+ };
+ module_t *dcerpc_module;
+
+ proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
+ proto_register_field_array (proto_dcerpc, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+ register_init_routine (dcerpc_init_protocol);
+ dcerpc_module = prefs_register_protocol (proto_dcerpc, NULL);
+ prefs_register_bool_preference (dcerpc_module,
+ "desegment_dcerpc",
+ "Desegment all DCE/RPC over TCP",
+ "Whether the DCE/RPC dissector should desegment all DCE/RPC over TCP",
+ &dcerpc_cn_desegment);
+ prefs_register_bool_preference (dcerpc_module,
+ "reassemble_dcerpc",
+ "Reassemble DCE/RPC fragments",
+ "Whether the DCE/RPC dissector should reassemble all fragmented PDUs",
+ &dcerpc_reassemble);
+ register_init_routine(dcerpc_reassemble_init);
+ dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
+ dcerpc_tap=register_tap("dcerpc");
+}
+
+void
+proto_reg_handoff_dcerpc (void)
+{
+ heur_dissector_add ("tcp", dissect_dcerpc_cn_bs, proto_dcerpc);
+ heur_dissector_add ("netbios", dissect_dcerpc_cn_pk, proto_dcerpc);
+ heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
+ heur_dissector_add ("smb_transact", dissect_dcerpc_cn_smbpipe, proto_dcerpc);
+ dcerpc_smb_init(proto_dcerpc);
+}
diff --git a/epan/dissectors/packet-dcerpc.h b/epan/dissectors/packet-dcerpc.h
new file mode 100644
index 0000000000..be76c321ae
--- /dev/null
+++ b/epan/dissectors/packet-dcerpc.h
@@ -0,0 +1,346 @@
+/* packet-dcerpc.h
+ * Copyright 2001, Todd Sabin <tas@webspan.net>
+ * Copyright 2003, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DCERPC_H__
+#define __PACKET_DCERPC_H__
+
+#include <epan/conversation.h>
+
+typedef struct _e_uuid_t {
+ guint32 Data1;
+ guint16 Data2;
+ guint16 Data3;
+ guint8 Data4[8];
+} e_uuid_t;
+
+/* %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x */
+#define DCERPC_UUID_STR_LEN 36+1
+
+typedef struct _e_ctx_hnd {
+ guint32 attributes;
+ e_uuid_t uuid;
+} e_ctx_hnd;
+
+typedef struct _e_dce_cn_common_hdr_t {
+ guint8 rpc_ver;
+ guint8 rpc_ver_minor;
+ guint8 ptype;
+ guint8 flags;
+ guint8 drep[4];
+ guint16 frag_len;
+ guint16 auth_len;
+ guint32 call_id;
+} e_dce_cn_common_hdr_t;
+
+typedef struct _e_dce_dg_common_hdr_t {
+ guint8 rpc_ver;
+ guint8 ptype;
+ guint8 flags1;
+ guint8 flags2;
+ guint8 drep[3];
+ guint8 serial_hi;
+ e_uuid_t obj_id;
+ e_uuid_t if_id;
+ e_uuid_t act_id;
+ guint32 server_boot;
+ guint32 if_ver;
+ guint32 seqnum;
+ guint16 opnum;
+ guint16 ihint;
+ guint16 ahint;
+ guint16 frag_len;
+ guint16 frag_num;
+ guint8 auth_proto;
+ guint8 serial_lo;
+} e_dce_dg_common_hdr_t;
+
+typedef struct _dcerpc_auth_info {
+ guint8 auth_pad_len;
+ guint8 auth_level;
+ guint8 auth_type;
+ guint32 auth_size;
+ tvbuff_t *auth_data;
+} dcerpc_auth_info;
+
+#define PDU_REQ 0
+#define PDU_PING 1
+#define PDU_RESP 2
+#define PDU_FAULT 3
+#define PDU_WORKING 4
+#define PDU_NOCALL 5
+#define PDU_REJECT 6
+#define PDU_ACK 7
+#define PDU_CL_CANCEL 8
+#define PDU_FACK 9
+#define PDU_CANCEL_ACK 10
+#define PDU_BIND 11
+#define PDU_BIND_ACK 12
+#define PDU_BIND_NAK 13
+#define PDU_ALTER 14
+#define PDU_ALTER_ACK 15
+#define PDU_AUTH3 16
+#define PDU_SHUTDOWN 17
+#define PDU_CO_CANCEL 18
+#define PDU_ORPHANED 19
+
+
+/*
+ * helpers for packet-dcerpc.c and packet-dcerpc-ndr.c
+ * If you're writing a subdissector, you almost certainly want the
+ * NDR functions below.
+ */
+guint16 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, guint8 *drep);
+guint32 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, guint8 *drep);
+void dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, guint8 *drep, e_uuid_t *uuid);
+int dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint8 *pdata);
+int dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint16 *pdata);
+int dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata);
+int dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, unsigned char *pdata);
+int dissect_dcerpc_float (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, gfloat *pdata);
+int dissect_dcerpc_double (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, gdouble *pdata);
+int dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata);
+/*
+ * NDR routines for subdissectors.
+ */
+int dissect_ndr_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint8 *pdata);
+int dissect_ndr_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint16 *pdata);
+int dissect_ndr_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata);
+int dissect_ndr_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, unsigned char *pdata);
+int dissect_ndr_float (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, gfloat *pdata);
+int dissect_ndr_double (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, gdouble *pdata);
+int dissect_ndr_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, guint32 *pdata);
+int dissect_ndr_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, e_uuid_t *pdata);
+int dissect_ndr_ctx_hnd (tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ int hfindex, e_ctx_hnd *pdata);
+
+typedef int (dcerpc_dissect_fnct_t)(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep);
+
+typedef void (dcerpc_callback_fnct_t)(packet_info *pinfo, proto_tree *tree, proto_item *item, tvbuff_t *tvb, int start_offset, int end_offset, void *callback_args);
+
+#define NDR_POINTER_REF 1
+#define NDR_POINTER_UNIQUE 2
+#define NDR_POINTER_PTR 3
+
+int dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ dcerpc_dissect_fnct_t *fnct, int type, char *text,
+ int hf_index, dcerpc_callback_fnct_t *callback,
+ void *callback_args);
+
+int dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ dcerpc_dissect_fnct_t *fnct, int type, char *text,
+ int hf_index);
+
+/* dissect a NDR unidimensional conformant array */
+int dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ dcerpc_dissect_fnct_t *fnct);
+
+/* dissect a NDR unidimensional conformant and varying array */
+int dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep,
+ dcerpc_dissect_fnct_t *fnct);
+
+int dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep);
+
+int dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, int size_is,
+ int hfinfo, gboolean add_subtree,
+ char **data);
+int dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep);
+int dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep);
+
+typedef struct _dcerpc_sub_dissector {
+ guint16 num;
+ gchar *name;
+ dcerpc_dissect_fnct_t *dissect_rqst;
+ dcerpc_dissect_fnct_t *dissect_resp;
+} dcerpc_sub_dissector;
+
+/* registration function for subdissectors */
+void dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver, dcerpc_sub_dissector *procs, int opnum_hf);
+char *dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver);
+int dcerpc_get_proto_hf_opnum(e_uuid_t *uuid, guint16 ver);
+dcerpc_sub_dissector *dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver);
+
+/* Create a opnum, name value_string from a subdissector list */
+
+value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd);
+
+/* Private data structure to pass to DCERPC dissector. This is used to
+ pass transport specific information down to the dissector from the
+ dissector that parsed this encapsulated calls.
+ When it comes to DCERPC over SMB the only thing we really want to pass
+ on is the FID.
+*/
+
+typedef struct _dcerpc_private_info {
+ guint16 fid;
+} dcerpc_private_info;
+
+/* Private data passed to subdissectors from the main DCERPC dissector. */
+typedef struct _dcerpc_call_value {
+ e_uuid_t uuid;
+ guint16 ver;
+ guint16 opnum;
+ guint32 req_frame;
+ nstime_t req_time;
+ guint32 rep_frame;
+ guint32 max_ptr;
+ void *private_data;
+} dcerpc_call_value;
+
+typedef struct _dcerpc_info {
+ conversation_t *conv; /* Which TCP stream we are in */
+ guint32 call_id; /* Context id for this call */
+ guint16 smb_fid; /* FID for DCERPC over SMB */
+ guint8 ptype; /* packet type: PDU_REQ, PDU_RESP, ... */
+ gboolean conformant_run;
+ gint32 conformant_eaten; /* how many bytes did the conformant run eat?*/
+ guint32 array_max_count; /* max_count for conformant arrays */
+ guint32 array_max_count_offset;
+ guint32 array_offset;
+ guint32 array_offset_offset;
+ guint32 array_actual_count;
+ guint32 array_actual_count_offset;
+ int hf_index;
+ dcerpc_call_value *call_data;
+ void *private_data;
+} dcerpc_info;
+
+
+/* the registered subdissectors. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT GHashTable *dcerpc_uuids;
+
+typedef struct _dcerpc_uuid_key {
+ e_uuid_t uuid;
+ guint16 ver;
+} dcerpc_uuid_key;
+
+typedef struct _dcerpc_uuid_value {
+ protocol_t *proto;
+ int proto_id;
+ int ett;
+ gchar *name;
+ dcerpc_sub_dissector *procs;
+ int opnum_hf;
+} dcerpc_uuid_value;
+
+/* Authenticated pipe registration functions and miscellanea */
+
+typedef tvbuff_t *(dcerpc_decode_data_fnct_t)(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ dcerpc_auth_info *auth_info);
+
+typedef struct _dcerpc_auth_subdissector_fns {
+
+ /* Dissect credentials and verifiers */
+
+ dcerpc_dissect_fnct_t *bind_fn;
+ dcerpc_dissect_fnct_t *bind_ack_fn;
+ dcerpc_dissect_fnct_t *auth3_fn;
+ dcerpc_dissect_fnct_t *req_verf_fn;
+ dcerpc_dissect_fnct_t *resp_verf_fn;
+
+ /* Decrypt encrypted requests/response PDUs */
+
+ dcerpc_decode_data_fnct_t *req_data_fn;
+ dcerpc_decode_data_fnct_t *resp_data_fn;
+
+} dcerpc_auth_subdissector_fns;
+
+void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type,
+ dcerpc_auth_subdissector_fns *fns);
+
+/* Authentication services */
+
+/*
+ * For MS-specific SSPs (Security Service Provider), see
+ *
+ * http://msdn.microsoft.com/library/en-us/rpc/rpc/authentication_level_constants.asp
+ */
+
+#define DCE_C_RPC_AUTHN_PROTOCOL_NONE 0
+#define DCE_C_RPC_AUTHN_PROTOCOL_KRB5 1
+#define DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO 9
+#define DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP 10
+#define DCE_C_RPC_AUTHN_PROTOCOL_GSS_SCHANNEL 14
+#define DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS 16
+#define DCE_C_RPC_AUTHN_PROTOCOL_DPA 17
+#define DCE_C_RPC_AUTHN_PROTOCOL_MSN 18
+#define DCE_C_RPC_AUTHN_PROTOCOL_DIGEST 21
+#define DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN 68
+#define DCE_C_RPC_AUTHN_PROTOCOL_MQ 100
+
+/* Protection levels */
+
+#define DCE_C_AUTHN_LEVEL_NONE 1
+#define DCE_C_AUTHN_LEVEL_CONNECT 2
+#define DCE_C_AUTHN_LEVEL_CALL 3
+#define DCE_C_AUTHN_LEVEL_PKT 4
+#define DCE_C_AUTHN_LEVEL_PKT_INTEGRITY 5
+#define DCE_C_AUTHN_LEVEL_PKT_PRIVACY 6
+
+void
+init_ndr_pointer_list(packet_info *pinfo);
+
+#endif /* packet-dcerpc.h */
diff --git a/epan/dissectors/packet-dcm.c b/epan/dissectors/packet-dcm.c
new file mode 100644
index 0000000000..cb42cf01ce
--- /dev/null
+++ b/epan/dissectors/packet-dcm.c
@@ -0,0 +1,1234 @@
+/* packet-dcm.c
+ * Routines for DICOM dissection
+ * Copyright 2003, Rich Coe <Richard.Coe@med.ge.com>
+ *
+ * DICOM communication protocol
+ * http://medical.nema.org/dicom/2003.html
+ * DICOM Part 8: Network Communication Support for Message Exchange
+ *
+ * (NOTE: you need to turn on 'Allow subdissector to desegment TCP streams'
+ * in Preferences/Protocols/TCP Option menu, in order to view
+ * DICOM packets correctly.
+ * This should probably be documented somewhere besides here.)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/* Notes:
+ * This is my first pass at a Ethereal dissector to display
+ * DICOM (Digital Imaging and Communications in Medicine) packets.
+ *
+ * - It currently displays most of the DICOM packets.
+ *
+ * - I've used it to debug Query/Retrieve, Storage, and Echo protocols.
+ *
+ * - Not all DICOM tags are currently displayed symbolically.
+ * Unknown tags are displayed as '(unknown)'
+ * More known tags might be added in the future.
+ * If the tag data contains a string, it will be displayed.
+ * Even if the tag contains Explicit VR, it is not currently used to
+ * symbolically display the data. Consider this a future enhancement.
+ *
+ * - If the DATA PDU has the 'more' bit set, subsequent packets will
+ * not currently display. Finding out how much 'more' data is coming
+ * currently requires parsing the entire packet.
+ *
+ * - The 'value to string' routines should probably be hash lookups.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include "isprint.h"
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/conversation.h>
+
+#include "packet-tcp.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_dcm = -1;
+static int hf_dcm_pdu = -1,
+ hf_dcm_pdu_len = -1,
+ hf_dcm_pdu_type = -1,
+ hf_dcm_pdi = -1,
+ hf_dcm_pdi_name = -1,
+ hf_dcm_pdi_syntax = -1,
+ hf_dcm_pctxt = -1,
+ hf_dcm_pcres = -1,
+ hf_dcm_pdu_maxlen = -1,
+ hf_dcm_impl = -1,
+ hf_dcm_vers = -1,
+ hf_dcm_data_len = -1,
+ hf_dcm_data_ctx = -1,
+ hf_dcm_data_flags = -1,
+ hf_dcm_data_tag = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_dcm = -1, ett_assoc = -1, ett_dcm_data = -1;
+
+static const value_string dcm_pdu_ids[] = {
+ { 1, "ASSOC Request" },
+ { 2, "ASSOC Accept" },
+ { 3, "ASSOC Reject" },
+ { 4, "Data" },
+ { 5, "RELEASE Request" },
+ { 6, "RELEASE Response" },
+ { 7, "ABORT" },
+ { 0, NULL }
+};
+
+static const value_string dcm_pdi_ids[] = {
+ { 0x10, "Application Context" },
+ { 0x20, "Presentation Context" },
+ { 0x21, "Presentation Context Reply" },
+ { 0x30, "Abstract syntax" },
+ { 0x40, "Transfer syntax" },
+ { 0x50, "User Info" },
+ { 0x51, "Max Length" },
+ { 0, NULL }
+};
+
+struct dcmContext {
+ guint8 id;
+ guint8 result;
+};
+struct dcmItem {
+ struct dcmItem *next, *prev;
+ guint8 id; /* 0x20 Presentation Context */
+ guint8 *abs; /* 0x30 Abstract syntax */
+ guint8 *xfer; /* 0x40 Transfer syntax */
+ guint8 syntax;
+#define DCM_ILE 0x01 /* implicit, little endian */
+#define DCM_EBE 0x02 /* explicit, big endian */
+#define DCM_ELE 0x03 /* explicit, little endian */
+#define DCM_UNK 0xf0
+};
+typedef struct dcmItem dcmItem_t;
+
+struct dcmState {
+ dcmItem_t *first, *last;
+ guint8 pdu; /* protocol data unit */
+ guint32 tlen, clen, rlen; /* length: total, current, remaining */
+ int partial; /* is a partial packet */
+ int coff; /* current offset */
+ /* enum { DCM_NONE, DCM_ASSOC, DCM_ }; */
+#define AEEND 16
+ guint8 orig[1+AEEND], targ[1+AEEND], resp[1+AEEND], source, result, reason;
+};
+typedef struct dcmState dcmState_t;
+
+struct dcmTag {
+ int tag;
+ int dtype;
+ char *desc;
+#define DCM_TSTR 1
+#define DCM_TINT2 2
+#define DCM_TINT4 3
+#define DCM_TFLT 4
+#define DCM_TDBL 5
+#define DCM_TSTAT 6 /* call dcm_rsp2str() on TINT2 */
+#define DCM_TRET 7
+#define DCM_TCMD 8
+};
+typedef struct dcmTag dcmTag_t;
+
+/* static GMemChunk *dcm_assocs = NULL; */
+static GMemChunk *dcm_pdus = NULL;
+static GHashTable *dcm_tagTable = NULL;
+
+dcmItem_t * lookupCtx(dcmState_t *dd, guint8 ctx);
+
+static dcmTag_t tagData[] = {
+ { 0x1, DCM_TRET, "(Ret) Length to End" },
+ { 0x2, DCM_TSTR, "Affected Class" },
+ { 0x3, DCM_TSTR, "Requested Class" },
+ { 0x0010, DCM_TRET, "(Ret) Recognition Code" },
+ { 0x0100, DCM_TCMD, "Command Field" },
+ { 0x0110, DCM_TINT2, "Message ID" },
+ { 0x0120, DCM_TINT2, "Resp Message ID" },
+ { 0x0200, DCM_TRET, "(Ret) Initiator" },
+ { 0x0300, DCM_TRET, "(Ret) Reciever" },
+ { 0x0400, DCM_TRET, "(Ret) Find Location" },
+ { 0x0600, DCM_TSTR, "Dest AE" },
+ { 0x0700, DCM_TINT2, "Priority" },
+ { 0x0800, DCM_TINT2, "Data Set (0x0101 means no data set present)" },
+ { 0x0850, DCM_TRET, "(Ret) Num Matches" },
+ { 0x0860, DCM_TRET, "(Ret) Resp Seq Num" },
+ { 0x0900, DCM_TSTAT, "Status" },
+ { 0x0901, DCM_TSTR, "Offending elm(s)" },
+ { 0x0902, DCM_TSTR, "Error Comment" },
+ { 0x0903, DCM_TINT2, "Error Id" },
+ { 0x1000, DCM_TSTR, "Affected Instance UID" },
+ { 0x1001, DCM_TSTR, "Requested Instance UID" },
+ { 0x1002, DCM_TINT2, "Event Type Id" },
+ { 0x1005, DCM_TSTR, "Attr Id List" },
+ { 0x1008, DCM_TINT2, "Action Type Id" },
+ { 0x1020, DCM_TINT2, "Num Remaining Ops" },
+ { 0x1021, DCM_TINT2, "Num Completed Ops" },
+ { 0x1022, DCM_TINT2, "Num Failed Ops" },
+ { 0x1023, DCM_TINT2, "Num Warning Ops" },
+ { 0x1030, DCM_TSTR, "Move Orig AE" },
+ { 0x1031, DCM_TINT2, "Move Orig Id" },
+ { 0x4000, DCM_TRET, "(Ret) DIALOG Recv'r" },
+ { 0x4010, DCM_TRET, "(Ret) Terminal Type" },
+ { 0x5010, DCM_TRET, "(Ret) Msg Set ID" },
+ { 0x5020, DCM_TRET, "(Ret) End Msg ID" },
+ { 0x5110, DCM_TRET, "(Ret) Display Fmt" },
+ { 0x5120, DCM_TRET, "(Ret) Page Position ID" },
+ { 0x5130, DCM_TRET, "(Ret) Text Fmt ID" },
+ { 0x5140, DCM_TRET, "(Ret) Nor/Rev" },
+ { 0x5150, DCM_TRET, "(Ret) Add Gray Scale" },
+ { 0x5160, DCM_TRET, "(Ret) Borders" },
+ { 0x5170, DCM_TRET, "(Ret) Copies" },
+ { 0x5180, DCM_TRET, "(Ret) Mag Type" },
+ { 0x5190, DCM_TRET, "(Ret) Erase" },
+ { 0x51a0, DCM_TRET, "(Ret) Print" },
+ { 0x080018, DCM_TSTR, "Image UID" },
+ { 0x080020, DCM_TSTR, "Study Date" },
+ { 0x080030, DCM_TSTR, "Study Time" },
+ { 0x080050, DCM_TSTR, "Acc Num" },
+ { 0x080052, DCM_TSTR, "Q/R Level" },
+ { 0x080054, DCM_TSTR, "Retrieve AE" },
+ { 0x080060, DCM_TSTR, "Modality" },
+ { 0x080070, DCM_TSTR, "Manuf" },
+ { 0x081030, DCM_TSTR, "Study Desc" },
+ { 0x08103e, DCM_TSTR, "Series Desc" },
+ { 0x100010, DCM_TSTR, "Patient Name" },
+ { 0x100020, DCM_TSTR, "Patient Id" },
+ { 0x20000d, DCM_TSTR, "Study UID" },
+ { 0x20000e, DCM_TSTR, "Series UID" },
+ { 0x200010, DCM_TSTR, "Study Num" },
+ { 0x200011, DCM_TSTR, "Series Num" },
+ { 0x200012, DCM_TSTR, "Acq Num" },
+ { 0x200013, DCM_TSTR, "Image Num" },
+ { 0xfffee000, DCM_TRET, "Item Begin" },
+ { 0xfffee00d, DCM_TRET, "Item End" },
+ { 0xfffee0dd, DCM_TRET, "Sequence End" },
+};
+
+static void
+dcm_init(void)
+{
+#ifdef notdef
+ if (dcm_assocs) g_mem_chunk_destroy(dcm_assocs);
+ dcm_assocs = g_mem_chunk_new("dcm_assocs", sizeof(struct dcmState),
+ 100 * sizeof(struct dcmState), G_ALLOC_AND_FREE);
+#endif
+ if (dcm_pdus) g_mem_chunk_destroy(dcm_pdus);
+ dcm_pdus = g_mem_chunk_new("dcm_pdus", sizeof(struct dcmItem),
+ 128 * sizeof(struct dcmItem), G_ALLOC_AND_FREE);
+ if (NULL == dcm_tagTable) {
+ unsigned int i;
+ dcm_tagTable = g_hash_table_new(NULL, NULL);
+ for (i = 0; i < sizeof(tagData) / sizeof(dcmTag_t); i++)
+ g_hash_table_insert(dcm_tagTable, (gpointer)tagData[i].tag,
+ (gpointer) (tagData+i));
+ }
+}
+
+dcmState_t *
+mkds()
+{
+ dcmState_t *ds;
+
+ if (NULL == (ds = (dcmState_t *) malloc(sizeof(dcmState_t)))) {
+ return NULL;
+ }
+ ds->pdu = 0;
+ ds->tlen = ds->rlen = 0;
+ ds->partial = 0;
+ memset(ds->orig, 0, sizeof(ds->orig));
+ memset(ds->targ, 0, sizeof(ds->targ));
+ memset(ds->resp, 0, sizeof(ds->resp));
+ ds->first = ds->last = NULL;
+ return ds;
+}
+
+char *
+dcm_pdu2str(guint8 item)
+{
+ char *s = "";
+ switch (item) {
+ case 1: s = "ASSOC Request"; break;
+ case 2: s = "ASSOC Accept"; break;
+ case 3: s = "ASSOC Reject"; break;
+ case 4: s = "Data"; break;
+ case 5: s = "RELEASE Request"; break;
+ case 6: s = "RELEASE Response"; break;
+ case 7: s = "ABORT"; break;
+ case 0x10: s = "Application Context"; break;
+ case 0x20: s = "Presentation Context"; break;
+ case 0x21: s = "Presentation Context Reply"; break;
+ case 0x30: s = "Abstract syntax"; break;
+ case 0x40: s = "Transfer syntax"; break;
+ case 0x50: s = "User Info"; break;
+ case 0x51: s = "Max Length"; break;
+ default: break;
+ }
+ return s;
+}
+
+char *
+dcm_result2str(guint8 result)
+{
+ char *s = "";
+ switch (result) {
+ case 1: s = "Reject Permanent"; break;
+ case 2: s = "Reject Transient"; break;
+ default: break;
+ }
+ return s;
+}
+
+char *
+dcm_source2str(guint8 source)
+{
+ char *s = "";
+ switch (source) {
+ case 1: s = "User"; break;
+ case 2: s = "Provider (ACSE)"; break;
+ case 3: s = "Provider (Presentation)"; break;
+ default: break;
+ }
+ return s;
+}
+
+char *
+dcm_reason2str(guint8 source, guint8 reason)
+{
+ char *s = "";
+ if (1 == source) switch (reason) {
+ case 1: s = "No reason"; break;
+ case 2: s = "App Name not supported"; break;
+ case 3: s = "calling AET not recognized"; break;
+ case 7: s = "called AET not recognized"; break;
+ default: break;
+ } else if (2 == source) switch (reason) {
+ case 1: s = "No reason"; break;
+ case 2: s = "protocol unsupported"; break;
+ default: break;
+ } else if (3 == source) switch (reason) {
+ case 1: s = "temporary congestion"; break;
+ case 2: s = "local limit exceeded"; break;
+ default: break;
+ }
+ return s;
+}
+
+char *
+dcm_abort2str(guint8 reason)
+{
+ char *s = "";
+ switch (reason) {
+ case 0: s = "not specified"; break;
+ case 1: s = "unrecoginized"; break;
+ case 2: s = "unexpected"; break;
+ case 4: s = "unrecognized parameter"; break;
+ case 5: s = "unexpected parameter"; break;
+ case 6: s = "invalid parameter"; break;
+ default: break;
+ }
+ return s;
+}
+
+char *
+dcm_PCresult2str(guint8 result)
+{
+ char *s = "";
+ switch (result) {
+ case 0: s = "accept"; break;
+ case 1: s = "user-reject"; break;
+ case 2: s = "no-reason"; break;
+ case 3: s = "abstract syntax unsupported"; break;
+ case 4: s = "transfer syntax unsupported"; break;
+ default: break;
+ }
+ return s;
+}
+
+char *
+dcm_flags2str(guint8 flags)
+{
+ char *s = "";
+ switch (flags) {
+ case 0: s = "Data, more Fragments"; break; /* 00 */
+ case 1: s = "Command, more Fragments"; break; /* 01 */
+ case 2: s = "Data, last Fragment"; break; /* 10 */
+ case 3: s = "Command, last Fragment"; break; /* 11 */
+ default: break;
+ }
+ return s;
+}
+
+char *
+dcm_cmd2str(guint16 us)
+{
+ char *s = "";
+ /* there should be a better way to do this */
+ switch (us) {
+ case 0x0001: s = "C-STORE-RQ"; break;
+ case 0x8001: s = "C-STORE-RSP"; break;
+ case 0x0010: s = "C-GET-RQ"; break;
+ case 0x8010: s = "C-GET-RSP"; break;
+ case 0x0020: s = "C-FIND-RQ"; break;
+ case 0x8020: s = "C-FIND-RSP"; break;
+ case 0x0021: s = "C-MOVE-RQ"; break;
+ case 0x8021: s = "C-MOVE-RSP"; break;
+ case 0x0030: s = "C-ECHO-RQ"; break;
+ case 0x8030: s = "C-ECHO-RSP"; break;
+ case 0x0100: s = "N-EVENT-REPORT-RQ"; break;
+ case 0x8100: s = "N-EVENT-REPORT-RSP"; break;
+ case 0x0110: s = "N-GET-RQ"; break;
+ case 0x8110: s = "N-GET-RSP"; break;
+ case 0x0120: s = "N-SET-RQ"; break;
+ case 0x8120: s = "N-SET-RSP"; break;
+ case 0x0130: s = "N-ACTION-RQ"; break;
+ case 0x8130: s = "N-ACTION-RSP"; break;
+ case 0x0140: s = "N-CREATE-RQ"; break;
+ case 0x8140: s = "N-CREATE-RSP"; break;
+ case 0x0150: s = "N-DELETE-RQ"; break;
+ case 0x8150: s = "N-DELETE-RSP"; break;
+ case 0x0fff: s = "C-CANCEL-RQ"; break;
+ default: break;
+ }
+ return s;
+}
+
+char *
+dcm_rsp2str(guint16 us)
+{
+ char *s = "";
+ switch (us) {
+ case 0x0000: s = "Success"; break;
+ case 0xa701:
+ case 0xa702: s = "Refused: Out of Resources"; break;
+ case 0xa801: s = "Refused: Move Destination unknown"; break;
+ case 0xa900: s = "Failed: Id does not match Class"; break;
+ case 0xb000: s = "Warning: operations complete -- One or more Failures"; break;
+ case 0xfe00: s = "Cancel: operations terminated by Cancel"; break;
+ case 0xff00: s = "Pending: operations are continuing"; break;
+ default: break;
+ }
+ if (0xC000 == (0xC000 & us)) s = "Failed: Unable to Process";
+ return s;
+}
+
+void
+dcm_setSyntax(dcmItem_t *di, char *name)
+{
+ if (NULL == di) return;
+ di->syntax = 0;
+ if (0 == *name) return;
+ /* this would be faster to skip the common parts, and have a FSA to
+ * find the syntax.
+ * Absent of coding that, this is in descending order of probability */
+ if (0 == strcmp(name, "1.2.840.10008.1.2"))
+ di->syntax = DCM_ILE; /* implicit little endian */
+ else if (0 == strcmp(name, "1.2.840.10008.1.2.1"))
+ di->syntax = DCM_ELE; /* explicit little endian */
+ else if (0 == strcmp(name, "1.2.840.10008.1.2.2"))
+ di->syntax = DCM_EBE; /* explicit big endian */
+ else if (0 == strcmp(name, "1.2.840.113619.5.2"))
+ di->syntax = DCM_ILE; /* implicit little endian, big endian pixels */
+ else if (0 == strcmp(name, "1.2.840.10008.1.2.4.70"))
+ di->syntax = DCM_ELE; /* explicit little endian, jpeg */
+ else if (0 == strncmp(name, "1.2.840.10008.1.2.4", 18))
+ di->syntax = DCM_ELE; /* explicit little endian, jpeg */
+ else if (0 == strcmp(name, "1.2.840.10008.1.2.1.99"))
+ di->syntax = DCM_ELE; /* explicit little endian, deflated */
+}
+
+char *
+dcm_tag2str(guint16 grp, guint16 elm, guint8 syntax, tvbuff_t *tvb, int offset, guint32 len)
+{
+ static char buf[512+1]; /* bad form ??? */
+ const guint8 *vval;
+ char *p;
+ guint32 tag, val32;
+ guint16 val16;
+ dcmTag_t *dtag;
+ static dcmTag_t utag = { 0, 0, "(unknown)" };
+
+ *buf = 0;
+ if (0 == elm) {
+ if (DCM_ILE & syntax)
+ val32 = tvb_get_letohl(tvb, offset);
+ else val32 = tvb_get_ntohl(tvb, offset);
+ snprintf(buf, sizeof(buf), "Group Length 0x%x (%d)", val32, val32);
+ return buf;
+ }
+ tag = (grp << 16) | elm;
+ if (NULL == (dtag = g_hash_table_lookup(dcm_tagTable, (gconstpointer) tag)))
+ dtag = &utag;
+
+ strcpy(buf, dtag->desc);
+ p = buf + strlen(buf);
+
+ switch (dtag->dtype) {
+ case DCM_TSTR:
+ *p++ = ' ';
+ vval = tvb_get_ptr(tvb, offset, len);
+ strncpy(p, vval, len);
+ p += len;
+ *p = 0;
+ break;
+ case DCM_TINT2:
+ if (DCM_ILE & syntax)
+ val16 = tvb_get_letohs(tvb, offset);
+ else val16 = tvb_get_ntohs(tvb, offset);
+ sprintf(p, " 0x%x (%d)", val16, val16);
+ break;
+ case DCM_TINT4:
+ if (DCM_ILE & syntax)
+ val32 = tvb_get_letohl(tvb, offset);
+ else val32 = tvb_get_ntohl(tvb, offset);
+ sprintf(p, " 0x%x (%d)", val32, val32);
+ break;
+ case DCM_TFLT: {
+ gfloat valf;
+ if (DCM_ILE & syntax)
+ valf = tvb_get_letohieee_float(tvb, offset);
+ else valf = tvb_get_ntohieee_float(tvb, offset);
+ sprintf(p, " (%f)", valf);
+ } break;
+ case DCM_TDBL: {
+ gdouble vald;
+ if (DCM_ILE & syntax)
+ vald = tvb_get_letohieee_double(tvb, offset);
+ else vald = tvb_get_ntohieee_double(tvb, offset);
+ sprintf(p, " (%f)", vald);
+ } break;
+ case DCM_TSTAT: /* call dcm_rsp2str() on TINT2 */
+ if (DCM_ILE & syntax)
+ val16 = tvb_get_letohs(tvb, offset);
+ else val16 = tvb_get_ntohs(tvb, offset);
+ sprintf(p, " 0x%x '%s'", val16, dcm_rsp2str(val16));
+ break;
+ case DCM_TCMD: /* call dcm_cmd2str() on TINT2 */
+ if (DCM_ILE & syntax)
+ val16 = tvb_get_letohs(tvb, offset);
+ else val16 = tvb_get_ntohs(tvb, offset);
+ sprintf(p, " 0x%x '%s'", val16, dcm_cmd2str(val16));
+ break;
+ case DCM_TRET: /* Retired */
+ break;
+ default: { /* try ascii */
+ unsigned int i;
+
+ vval = tvb_get_ptr(tvb, offset, len);
+ i = 0;
+ *p++ = ' ';
+ while (i < len && i < 512 && isprint(*(vval+i)))
+ *p++ = *(vval + i++);
+ *p = 0;
+ } break;
+ }
+ return buf;
+}
+
+static guint
+dcm_get_pdu_len(tvbuff_t *tvb, int offset)
+{
+ long len;
+#if 0
+ guint8 pdu_type;
+#endif
+
+ len = tvb_get_ntohl(tvb, 2 + offset);
+#if 0
+ guint8 pdu_type;
+ pdu_type = tvb_get_guint8(tvb, offset);
+ if (4 == pdu_type) {
+ guint8 frag;
+ /* this is a total swamp. We only know how big this
+ fragment is and that more are coming. We have to
+ parse the entire packet to find a clue how much more is
+ coming. this tries to guess .... */
+ frag = tvb_get_guint8(tvb, 11 + offset);
+ if (0 == (0x2 & frag))
+ /* len += tvb_ensure_length_remaining(tvb, offset) - 6; */
+ /* there are more fragments */
+ len++;
+ }
+#endif
+ return len + 6; /* add in fixed header part */
+}
+
+void
+dissect_dcm_assoc(dcmState_t *dcm_data, proto_item *ti, tvbuff_t *tvb, int offset)
+{
+ proto_tree *dcm_tree;
+ dcmItem_t *di = NULL;
+
+ dcm_tree = proto_item_add_subtree(ti, ett_assoc);
+ while (-1 < offset && offset < (int) dcm_data->clen) {
+ guint8 id, *name, result;
+ short len;
+ long mlen;
+ id = tvb_get_guint8(tvb, offset);
+ len = tvb_get_ntohs(tvb, 2 + offset);
+ proto_tree_add_uint_format(dcm_tree, hf_dcm_pdi, tvb,
+ offset, 4+len, id, "Item 0x%x (%s)", id, dcm_pdu2str(id));
+ offset += 4;
+ switch (id) {
+ case 0x10: /* App context */
+ name = g_malloc(1 + len);
+ tvb_memcpy(tvb, name, offset, len);
+ *(name + len) = 0;
+ proto_tree_add_string(dcm_tree, hf_dcm_pdi_name, tvb, offset, len, name);
+ g_free(name);
+ offset += len;
+ break;
+ case 0x30: /* Abstract syntax */
+ dcm_data->last->abs = name = g_malloc(1 + len);
+ tvb_memcpy(tvb, name, offset, len);
+ *(name + len) = 0;
+ proto_tree_add_string(dcm_tree, hf_dcm_pdi_syntax, tvb, offset, len, name);
+ offset += len;
+ break;
+ case 0x40: /* Transfer syntax */
+ dcm_data->last->xfer = name = g_malloc(1 + len);
+ tvb_memcpy(tvb, name, offset, len);
+ *(name + len) = 0;
+ proto_tree_add_string(dcm_tree, hf_dcm_pdi_syntax, tvb, offset, len, name);
+ dcm_setSyntax(di, name);
+ offset += len;
+ break;
+ case 0x20: /* Presentation context */
+ id = tvb_get_guint8(tvb, offset);
+ di = lookupCtx(dcm_data, id);
+ if (DCM_UNK == di->syntax) {
+ di = g_chunk_new(dcmItem_t, dcm_pdus);
+ di->id = id;
+ di->next = di->prev = NULL;
+ if (dcm_data->last) {
+ dcm_data->last->next = di;
+ di->prev = dcm_data->last;
+ dcm_data->last = di;
+ } else
+ dcm_data->first = dcm_data->last = di;
+ }
+ proto_tree_add_item(dcm_tree, hf_dcm_pctxt, tvb, offset, 1, FALSE);
+ offset += 4;
+ break;
+ case 0x21: /* Presentation context reply */
+ id = tvb_get_guint8(tvb, offset);
+ result = tvb_get_guint8(tvb, 2 + offset);
+ proto_tree_add_item(dcm_tree, hf_dcm_pctxt, tvb, offset, 1, FALSE);
+ proto_tree_add_uint_format(dcm_tree, hf_dcm_pcres, tvb,
+ 2 + offset, 1,
+ result, "Result 0x%x (%s)", result, dcm_PCresult2str(result));
+ offset += len;
+ break;
+ case 0x50: /* User Info */
+ break;
+ case 0x51: /* Max length */
+ mlen = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(dcm_tree, hf_dcm_pdu_maxlen, tvb, offset, 4, FALSE);
+ offset += len;
+ break;
+ case 0x52: /* UID? */
+ name = g_malloc(1 + len);
+ tvb_memcpy(tvb, name, offset, len);
+ *(name + len) = 0;
+ proto_tree_add_string(dcm_tree, hf_dcm_impl, tvb, offset, len, name);
+ g_free(name);
+ offset += len;
+ break;
+ case 0x55: /* version? */
+ name = g_malloc(1 + len);
+ tvb_memcpy(tvb, name, offset, len);
+ *(name + len) = 0;
+ proto_tree_add_string(dcm_tree, hf_dcm_vers, tvb, offset, len, name);
+ g_free(name);
+ offset += len;
+ break;
+ default:
+ offset += len;
+ break;
+ }
+ }
+}
+
+dcmItem_t *
+lookupCtx(dcmState_t *dd, guint8 ctx)
+{
+ dcmItem_t *di = dd->first;
+ static dcmItem_t dunk = { NULL, NULL, -1,
+ "not found - click on ASSOC Request",
+ "not found - click on ASSOC Request", DCM_UNK };
+ while (di) {
+ if (ctx == di->id)
+ break;
+ di = di->next;
+ }
+ return di ? di : &dunk;
+}
+
+/*
+04 P-DATA-TF
+ 1 1 reserved
+ 2 4 length
+ - (1+) presentation data value (PDV) items
+ 6 4 length
+10 1 Presentation Context ID (odd ints 1 - 255)
+ - PDV
+11 1 header
+ 0x01 if set, contains Message Command info, else Message Data
+ 0x02 if set, contains last fragment
+ */
+#define D_HEADER 1
+#define D_TAG 2
+#define D_VR 3
+#define D_LEN2 4
+#define D_LEN4 5
+#define D_VALUE 6
+
+void
+dissect_dcm_data(dcmState_t *dcm_data, proto_item *ti, tvbuff_t *tvb)
+{
+ int len, offset, toffset, state;
+ proto_tree *dcm_tree;
+ dcmItem_t *di;
+ guint8 ctx, syntax = DCM_UNK;
+ guint16 grp = 0, elm = 0;
+ guint32 tlen = 0, nlen;
+
+ dcm_tree = proto_item_add_subtree(ti, ett_dcm_data);
+ proto_tree_add_item(dcm_tree, hf_dcm_data_len, tvb, 6, 4, FALSE);
+ ctx = tvb_get_guint8(tvb, 10);
+ di = lookupCtx(dcm_data, ctx);
+ /* proto_tree_add_item(dcm_tree, hf_dcm_data_ctx, tvb, 10, 1, FALSE); */
+ proto_tree_add_uint_format(dcm_tree, hf_dcm_data_ctx, tvb, 10, 1,
+ ctx, "Context 0x%x (%s)", ctx, di->xfer);
+ len = offset = toffset = 11;
+ state = D_HEADER;
+ nlen = 1;
+ while (len + nlen < dcm_data->clen) {
+ switch (state) {
+ case D_HEADER: {
+ guint8 flags;
+ flags = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(dcm_tree, hf_dcm_data_flags, tvb, offset, 1,
+ flags, "Flags 0x%x (%s)", flags, dcm_flags2str(flags));
+ /* proto_tree_add_item(dcm_tree, hf_dcm_data_flags, tvb, offset, 1, FALSE); */
+ len++;
+ offset++;
+ if (0x1 & flags)
+ syntax = DCM_ILE;
+ else if (DCM_UNK == di->syntax) {
+ const guint8 *val;
+ tlen = dcm_data->clen - len;
+ val = tvb_get_ptr(tvb, offset, tlen+8);
+ proto_tree_add_bytes_format(dcm_tree, hf_dcm_data_tag, tvb,
+ offset, tlen, val, "(%04x,%04x) %-8x Unparsed data", 0, 0, tlen);
+ len = dcm_data->clen; /* ends parsing */
+ } else
+ syntax = di->syntax;
+ state = D_TAG;
+ nlen = 4;
+ } break; /* don't fall through -- check length */
+ case D_TAG: {
+ if (DCM_ILE & syntax) {
+ grp = tvb_get_letohs(tvb, offset);
+ elm = tvb_get_letohs(tvb, offset+2);
+ state = (DCM_EBE & syntax) ? D_VR : D_LEN4; /* is Explicit */
+ nlen = (DCM_EBE & syntax) ? 2 : 4; /* is Explicit */
+ } else {
+ grp = tvb_get_ntohs(tvb, offset);
+ elm = tvb_get_ntohs(tvb, offset+2);
+ state = D_VR;
+ nlen = 2;
+ }
+ toffset = offset;
+ if (0xfffe == grp) state = D_LEN4;
+ offset += 4;
+ len += 4;
+ } break; /* don't fall through -- check length */
+ case D_VR: {
+ guint8 V, R;
+ V = tvb_get_guint8(tvb, offset); offset++;
+ R = tvb_get_guint8(tvb, offset); offset++;
+ len += 2;
+ /* 4byte lenghts OB, OW, OF, SQ, UN, UT */
+ state = D_LEN2;
+ nlen = 2;
+ if ((('O' == V) && ('B' == R || 'W' == R || 'F' == R))
+ || (('U' == V) && ('N' == R || 'T' == R))
+ || ('S' == V && 'Q' == R)) {
+ state = D_LEN4;
+ offset += 2; /* skip 00 (2 bytes) */
+ len += 2;
+ nlen = 4;
+ }
+ } break; /* don't fall through -- check length */
+ case D_LEN2: {
+ if (DCM_ILE & syntax) /* is it LE */
+ tlen = tvb_get_letohs(tvb, offset);
+ else
+ tlen = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ len += 2;
+ state = D_VALUE;
+ nlen = tlen;
+ } break;
+ case D_LEN4: {
+ if (DCM_ILE & syntax) /* is it LE */
+ tlen = tvb_get_letohl(tvb, offset);
+ else
+ tlen = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ len += 4;
+ state = D_VALUE;
+ nlen = tlen;
+ } break; /* don't fall through -- check length */
+ case D_VALUE: {
+ const guint8 *val;
+ int totlen = (offset - toffset);
+ if (0xffffffff == tlen || 0xfffe == grp) {
+ val = tvb_get_ptr(tvb, toffset, totlen);
+ proto_tree_add_bytes_format(dcm_tree, hf_dcm_data_tag, tvb,
+ toffset, totlen, val,
+ "(%04x,%04x) %-8x %s", grp, elm, tlen,
+ dcm_tag2str(grp, elm, syntax, tvb, offset, 0));
+ tlen = 0;
+ /* } else if (0xfffe == grp) { */ /* need to make a sub-tree here */
+ } else {
+ totlen += tlen;
+ val = tvb_get_ptr(tvb, toffset, totlen);
+ proto_tree_add_bytes_format(dcm_tree, hf_dcm_data_tag, tvb,
+ toffset, totlen, val,
+ "(%04x,%04x) %-8x %s", grp, elm, tlen,
+ dcm_tag2str(grp, elm, syntax, tvb, offset, tlen));
+ }
+ len += tlen;
+ offset += tlen;
+ state = D_TAG;
+ nlen = 4;
+ } break;
+ }
+ }
+}
+
+/*
+ Originator src:srcport dest:destport
+ Acceptor src:srcport dest:destport
+
+ conn = lookup(src:srcport, dest:destport)
+ if (!conn)
+ look at data payload of packet
+ if no-data return false;
+ if 01 == *p && *p+10 ... *p+42 <= [ 0x20 .. printable ]
+ create conn
+ */
+
+static void dissect_dcm_pdu(tvbuff_t *tvb,packet_info *pinfo,proto_tree *tree);
+
+/* Code to actually dissect the packets */
+static gboolean
+dissect_dcm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ conversation_t *conv;
+ guint8 pdu;
+ guint16 vers;
+ guint32 len, tlen;
+ dcmState_t *dcm_data;
+
+ conv = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+
+ if (NULL == conv) {
+ /* No conversation found.
+ * only look for the first packet of a DICOM conversation.
+ * if we don't get the first packet, we cannot decode the rest
+ * of the session.
+ */
+ if (10 > (tlen = tvb_reported_length(tvb)))
+ return FALSE; /* not long enough */
+ if (1 != (pdu = tvb_get_guint8(tvb, 0)))
+ return FALSE; /* look for the start */
+ if (1 != (vers = tvb_get_ntohs(tvb, 6)))
+ return FALSE; /* not version 1 */
+ len = 6 + tvb_get_ntohl(tvb, 2);
+ if (len < tlen)
+ return FALSE; /* packet is > decl len */
+
+ conv = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (NULL == (dcm_data = mkds()))
+ return FALSE; /* internal error */
+ conversation_add_proto_data(conv, proto_dcm, dcm_data);
+ } else {
+ /*
+ * conversation exists
+ */
+ dcm_data = conversation_get_proto_data(conv, proto_dcm);
+ if (NULL == dcm_data) {
+ /*
+ * This is not a DICOM conversation
+ */
+ return FALSE;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_clear(pinfo->cinfo, COL_PROTOCOL);
+
+ tcp_dissect_pdus(tvb, pinfo, tree, 1, 6, dcm_get_pdu_len, dissect_dcm_pdu);
+
+ return TRUE;
+}
+
+static void
+dissect_dcm_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ dcmState_t *dcm_data;
+ proto_tree *dcm_tree;
+ conversation_t *conv;
+ char *buf;
+ int offset = 0;
+
+ if (NULL == (conv = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0)))
+ return; /* OOPS */
+
+ dcm_data = conversation_get_proto_data(conv, proto_dcm);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCM");
+
+/* This field shows up as the "Info" column in the display; you should make
+ it, if possible, summarize what's in the packet, so that a user looking
+ at the list of packets can tell what type of packet it is. See section 1.5
+ for more information.
+ */
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ dcm_data->pdu = tvb_get_guint8(tvb, 0);
+ dcm_data->tlen = tvb_get_ntohl(tvb, 2) + 6;
+ dcm_data->clen = tvb_reported_length(tvb);
+ /* if (dcm_data->clen < dcm_data->tlen) dcm_data->partial = 1; */
+
+ switch (dcm_data->pdu) {
+ case 1: /* ASSOC Request */
+ tvb_memcpy(tvb, dcm_data->orig, 10, 16);
+ tvb_memcpy(tvb, dcm_data->targ, 26, 16);
+ dcm_data->orig[AEEND] = dcm_data->targ[AEEND] = 0;
+ buf = g_malloc(128);
+ snprintf(buf, 128, "DCM ASSOC Request %s <-- %s",
+ dcm_data->orig, dcm_data->targ);
+ offset = 74;
+ break;
+ case 2: /* ASSOC Accept */
+ tvb_memcpy(tvb, dcm_data->resp, 26, 16);
+ buf = g_malloc(128);
+ snprintf(buf, 128, "DCM ASSOC Accept %s <-- %s (%s)",
+ dcm_data->orig, dcm_data->targ, dcm_data->resp);
+ offset = 74;
+ break;
+ case 3: /* ASSOC Reject */
+ dcm_data->result = tvb_get_guint8(tvb, 7);
+ dcm_data->source = tvb_get_guint8(tvb, 8);
+ dcm_data->reason = tvb_get_guint8(tvb, 9);
+ buf = g_malloc(128);
+ snprintf(buf, 128, "DCM ASSOC Reject %s <-- %s %s %s %s",
+ dcm_data->orig, dcm_data->targ,
+ dcm_result2str(dcm_data->result),
+ dcm_source2str(dcm_data->source),
+ dcm_reason2str(dcm_data->source, dcm_data->reason));
+ offset = 10;
+ break;
+ case 4: /* DATA */
+ offset = 6;
+ buf = g_malloc(128);
+ strcpy(buf, "DCM Data");
+ break;
+ case 5: /* RELEASE Request */
+ buf = g_malloc(128);
+ strcpy(buf, "DCM RELEASE Request");
+ offset = 6;
+ break;
+ case 6: /* RELEASE Response */
+ buf = g_malloc(128);
+ strcpy(buf, "DCM RELEASE Response");
+ offset = 6;
+ break;
+ case 7: /* ABORT */
+ dcm_data->source = tvb_get_guint8(tvb, 8);
+ dcm_data->reason = tvb_get_guint8(tvb, 9);
+ buf = g_malloc(128);
+ snprintf(buf, 128, "DCM ABORT %s <-- %s %s %s",
+ dcm_data->orig, dcm_data->targ,
+ (dcm_data->source == 1) ? "USER" :
+ (dcm_data->source == 2) ? "PROVIDER" : "",
+ dcm_data->source == 1 ? dcm_abort2str(dcm_data->reason) : "");
+ break;
+ default:
+ buf = g_malloc(128);
+ strcpy(buf, "DCM Continuation");
+ offset = -1; /* cannot continue parsing */
+ break;
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, buf);
+
+/* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ proto_item *tf;
+ ti = proto_tree_add_item(tree, proto_dcm, tvb, 0, -1, FALSE);
+ dcm_tree = proto_item_add_subtree(ti, ett_dcm);
+ proto_tree_add_uint_format(dcm_tree, hf_dcm_pdu, tvb, 0, dcm_data->tlen,
+ dcm_data->pdu, "PDU 0x%x (%s)", dcm_data->pdu,
+ dcm_pdu2str(dcm_data->pdu));
+ proto_tree_add_item(dcm_tree, hf_dcm_pdu_len, tvb, 2, 4, FALSE);
+
+ switch (dcm_data->pdu) {
+ case 1: /* ASSOC Request */
+ case 2: /* ASSOC Accept */
+ case 3: /* ASSOC Reject */
+ case 5: /* RELEASE Request */
+ case 6: /* RELEASE Response */
+ case 7: /* ABORT */
+ tf = proto_tree_add_string(dcm_tree, hf_dcm_pdu_type, tvb, 0, dcm_data->tlen, buf);
+ dissect_dcm_assoc(dcm_data, tf, tvb, offset);
+ break;
+ case 4: /* DATA */
+ tf = proto_tree_add_string(dcm_tree, hf_dcm_pdu_type, tvb, 0, dcm_data->tlen, buf);
+ dissect_dcm_data(dcm_data, tf, tvb);
+ break;
+ default:
+ break;
+ }
+
+/* Continue adding tree items to process the packet here */
+ }
+
+/* If this protocol has a sub-dissector call it here, see section 1.8 */
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_dcm(void)
+{
+/* Setup list of header fields See Section 1.6.1 for details*/
+static hf_register_info hf[] = {
+ { &hf_dcm_pdu, { "PDU", "dcm.pdu",
+ FT_UINT8, BASE_HEX, VALS(dcm_pdu_ids), 0, "", HFILL } },
+ { &hf_dcm_pdu_len, { "PDU LENGTH", "dcm.pdu_len",
+ FT_UINT32, BASE_HEX, NULL, 0, "", HFILL } },
+ { &hf_dcm_pdu_type, { "PDU Detail", "dcm.pdu_detail",
+ FT_STRING, BASE_NONE, NULL, 0, "", HFILL } },
+ { &hf_dcm_pdi, { "Item", "dcm.pdu.pdi",
+ FT_UINT8, BASE_HEX, VALS(dcm_pdi_ids), 0, "", HFILL } },
+ { &hf_dcm_pdi_name, { "Application Context", "dcm.pdi.name",
+ FT_STRING, BASE_NONE, NULL, 0, "", HFILL } },
+ { &hf_dcm_pdi_syntax, { "Abstract Syntax", "dcm.pdi.syntax",
+ FT_STRING, BASE_NONE, NULL, 0, "", HFILL } },
+ { &hf_dcm_pctxt, { "Presentation Context", "dcm.pdi.ctxt",
+ FT_UINT8, BASE_HEX, NULL, 0, "", HFILL } },
+ { &hf_dcm_pcres, { "Presentation Context result", "dcm.pdi.result",
+ FT_UINT8, BASE_HEX, VALS(dcm_pdi_ids), 0, "", HFILL } },
+ { &hf_dcm_pdu_maxlen, { "MAX PDU LENGTH", "dcm.max_pdu_len",
+ FT_UINT32, BASE_DEC, NULL, 0, "", HFILL } },
+ { &hf_dcm_impl, { "Implementation", "dcm.pdi.impl",
+ FT_STRING, BASE_NONE, NULL, 0, "", HFILL } },
+ { &hf_dcm_vers, { "Version", "dcm.pdi.version",
+ FT_STRING, BASE_NONE, NULL, 0, "", HFILL } },
+ { &hf_dcm_data_len, { "DATA LENGTH", "dcm.data.len",
+ FT_UINT32, BASE_HEX, NULL, 0, "", HFILL } },
+ { &hf_dcm_data_ctx, { "Data Context", "dcm.data.ctx",
+ FT_UINT8, BASE_HEX, NULL, 0, "", HFILL } },
+ { &hf_dcm_data_flags, { "Flags", "dcm.data.flags",
+ FT_UINT8, BASE_HEX, NULL, 0, "", HFILL } },
+ { &hf_dcm_data_tag, { "Tag", "dcm.data.tag",
+ FT_BYTES, BASE_HEX, NULL, 0, "", HFILL } },
+/*
+ { &hf_dcm_FIELDABBREV, { "FIELDNAME", "dcm.FIELDABBREV",
+ FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK, "FIELDDESCR", HFILL } },
+ */
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_dcm,
+ &ett_assoc,
+ &ett_dcm_data
+ };
+/* Register the protocol name and description */
+ proto_dcm = proto_register_protocol("DICOM", "dicom", "dcm");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_dcm, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine(&dcm_init);
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_dcm(void)
+{
+ heur_dissector_add("tcp", dissect_dcm, proto_dcm);
+}
+
+/*
+
+PDU's
+01 ASSOC-RQ
+ 1 1 reserved
+ 2 4 length
+ 6 2 protocol version (0x0 0x1)
+ 8 2 reserved
+10 16 dest aetitle
+26 16 src aetitle
+42 32 reserved
+74 - presentation data value items
+
+02 A-ASSOC-AC
+ 1 reserved
+ 4 length
+ 2 protocol version (0x0 0x1)
+ 2 reserved
+ 16 dest aetitle (not checked)
+ 16 src aetitle (not checked)
+ 32 reserved
+ - presentation data value items
+
+03 ASSOC-RJ
+ 1 reserved
+ 4 length (4)
+ 1 reserved
+ 1 result (1 reject perm, 2 reject transient)
+ 1 source (1 service user, 2 service provider, 3 service profider)
+ 1 reason
+ 1 == source
+ 1 no reason given
+ 2 application context name not supported
+ 3 calling aetitle not recognized
+ 7 called aetitle not recognized
+ 2 == source
+ 1 no reason given
+ 2 protocol version not supported
+ 3 == source
+ 1 temporary congestion
+ 2 local limit exceeded
+
+04 P-DATA-TF
+ 1 1 reserved
+ 2 4 length
+ - (1+) presentation data value (PDV) items
+ 6 4 length
+10 1 Presentation Context ID (odd ints 1 - 255)
+ - PDV
+11 1 header
+ 0x01 if set, contains Message Command info, else Message Data
+ 0x02 if set, contains last fragment
+
+05 A-RELEASE-RQ
+ 1 reserved
+ 4 length (4)
+ 4 reserved
+
+06 A-RELEASE-RP
+ 1 reserved
+ 4 length (4)
+ 4 reserved
+
+07 A-ABORT
+ 1 reserved
+ 4 length (4)
+ 2 reserved
+ 1 source (0 = user, 1 = provider)
+ 1 reason if 1 == source (0 not spec, 1 unrecognized, 2 unexpected 4 unrecognized param, 5 unexpected param, 6 invalid param)
+
+
+
+ITEM's
+10 Application Context
+ 1 reserved
+ 2 length
+ - name
+
+20 Presentation Context
+ 1 reserved
+ 2 length
+ 1 Presentation context id
+ 3 reserved
+ - (1) abstract and (1+) transfer syntax sub-items
+
+21 Presentation Context (Reply)
+ 1 reserved
+ 2 length
+ 1 ID (odd int's 1-255)
+ 1 reserved
+ 1 result (0 accept, 1 user-reject, 2 no-reason, 3 abstract not supported, 4- transfer syntax not supported)
+ 1 reserved
+ - (1) type 40
+
+30 Abstract syntax
+ 1 reserved
+ 2 length
+ - name (<= 64)
+
+40 Transfer syntax
+ 1 reserved
+ 2 length
+ - name (<= 64)
+
+50 user information
+ 1 reserved
+ 2 length
+ - user data
+
+51 max length
+ 1 reserved
+ 2 length (4)
+ 4 max PDU lengths
+ */
diff --git a/epan/dissectors/packet-ddtp.c b/epan/dissectors/packet-ddtp.c
new file mode 100644
index 0000000000..b5d1c0ddb1
--- /dev/null
+++ b/epan/dissectors/packet-ddtp.c
@@ -0,0 +1,220 @@
+/* packet-ddtp.c
+ * Routines for DDTP (Dynamic DNS Tools Protocol) packet disassembly
+ * see http://ddt.sourceforge.net/
+ * Olivier Abad <oabad@noos.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2000
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ddtp.h"
+
+static int proto_ddtp = -1;
+static int hf_ddtp_version = -1;
+static int hf_ddtp_encrypt = -1;
+static int hf_ddtp_hostid = -1;
+static int hf_ddtp_msgtype = -1;
+static int hf_ddtp_opcode = -1;
+static int hf_ddtp_ipaddr = -1;
+static int hf_ddtp_status = -1;
+
+static int ett_ddtp = -1;
+
+#define UDP_PORT_DDTP 1052
+
+/*
+ * XXX - is 0 an invalid value? If so, should we remove it from this
+ * list, so that putative DDNS packets with a version number of 0 are
+ * rejected?
+ */
+static const value_string vals_ddtp_version[] = {
+ { DDTP_VERSION_ERROR, "Protocol Error" },
+ { DDTP_VERSION_4, "4" },
+ { DDTP_VERSION_5, "5" },
+ { 0, NULL}
+};
+
+static const value_string vals_ddtp_encrypt[] = {
+ { DDTP_ENCRYPT_ERROR, "Encryption Error" },
+ { DDTP_ENCRYPT_PLAINTEXT, "Plain text" },
+ { DDTP_ENCRYPT_BLOWFISH, "Blowfish" },
+ { 0, NULL}
+};
+
+static const value_string vals_ddtp_msgtype[] = {
+ { DDTP_MESSAGE_ERROR, "Message Error" },
+ { DDTP_UPDATE_QUERY, "Update Query" },
+ { DDTP_UPDATE_REPLY, "Update Reply" },
+ { DDTP_ALIVE_QUERY, "Alive Query" },
+ { DDTP_ALIVE_REPLY, "Alive Reply" },
+ { 0, NULL}
+};
+
+static const value_string vals_ddtp_opcode[] = {
+ { DDTP_MARK_ONLINE, "Mark online" },
+ { DDTP_MARK_OFFLINE, "Mark offline" },
+ { 0, NULL}
+};
+
+static const value_string vals_ddtp_status[] = {
+ { DDTP_UPDATE_SUCCEEDED, "Update succeeded" },
+ { DDTP_UPDATE_FAILED, "Update failed" },
+ { DDTP_INVALID_PASSWORD, "Invalid password" },
+ { DDTP_INVALID_ACCOUNT, "Invalid account" },
+ { DDTP_INVALID_OPCODE, "Invalid opcode" },
+ { 0, NULL}
+};
+
+static int
+dissect_ddtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ddtp_tree = NULL;
+ proto_item *ti;
+
+ /*
+ * If we don't recognize the version number, don't dissect this.
+ */
+ if (tvb_bytes_exist(tvb, 0, 4)) {
+ if (match_strval(tvb_get_ntohl(tvb, 0), vals_ddtp_version) == NULL)
+ return 0;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ /* Indicate what kind of message this is. */
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "DDTP");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /* In case we throw an exception below. */
+ col_clear (pinfo->cinfo, COL_INFO);
+ }
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ddtp, tvb, 0, -1, FALSE);
+ ddtp_tree = proto_item_add_subtree(ti, ett_ddtp);
+
+ proto_tree_add_item(ddtp_tree, hf_ddtp_version, tvb, 0, 4, FALSE);
+ proto_tree_add_item(ddtp_tree, hf_ddtp_encrypt, tvb, 4, 4, FALSE);
+ proto_tree_add_item(ddtp_tree, hf_ddtp_hostid, tvb, 8, 4, FALSE);
+ }
+ if (tvb_get_ntohl(tvb, 4) == DDTP_ENCRYPT_PLAINTEXT) {
+ if (tree)
+ proto_tree_add_item(ddtp_tree, hf_ddtp_msgtype, tvb, 12, 4, FALSE);
+ switch (tvb_get_ntohl(tvb, 12)) {
+ case DDTP_MESSAGE_ERROR :
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str (pinfo->cinfo, COL_INFO, "Message Error");
+ break;
+ case DDTP_UPDATE_QUERY :
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str (pinfo->cinfo, COL_INFO, "Update Query");
+ if (tree) {
+ proto_tree_add_item(ddtp_tree, hf_ddtp_opcode, tvb, 16, 4,
+ FALSE);
+ proto_tree_add_item(ddtp_tree, hf_ddtp_ipaddr, tvb, 20, 4,
+ FALSE);
+ }
+ break;
+ case DDTP_UPDATE_REPLY :
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str (pinfo->cinfo, COL_INFO, "Update Reply");
+ if (tree) {
+ proto_tree_add_item(ddtp_tree, hf_ddtp_status, tvb, 16, 4,
+ FALSE);
+ }
+ break;
+ case DDTP_ALIVE_QUERY :
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str (pinfo->cinfo, COL_INFO, "Alive Query");
+ if (tree) {
+ proto_tree_add_text(ddtp_tree, tvb, 16, 4, "Dummy : %u",
+ tvb_get_ntohl(tvb, 16));
+ }
+ break;
+ case DDTP_ALIVE_REPLY :
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str (pinfo->cinfo, COL_INFO, "Alive Reply");
+ if (tree) {
+ proto_tree_add_text(ddtp_tree, tvb, 16, 4, "Dummy : %u",
+ tvb_get_ntohl(tvb, 16));
+ }
+ break;
+ default :
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str (pinfo->cinfo, COL_INFO, "Unknown type");
+ if (tree) {
+ proto_tree_add_text(ddtp_tree, tvb, 12, 4, "Unknown type : %u",
+ tvb_get_ntohl(tvb, 12));
+ }
+ }
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str (pinfo->cinfo, COL_INFO, "Encrypted payload");
+ }
+ return tvb_length(tvb);
+}
+
+void
+proto_register_ddtp(void)
+{
+ static hf_register_info hf_ddtp[] = {
+ { &hf_ddtp_version,
+ { "Version", "ddtp.version", FT_UINT32, BASE_DEC, VALS(vals_ddtp_version), 0x0,
+ "Version", HFILL }},
+ { &hf_ddtp_encrypt,
+ { "Encryption", "ddtp.encrypt", FT_UINT32, BASE_DEC, VALS(vals_ddtp_encrypt), 0x0,
+ "Encryption type", HFILL }},
+ { &hf_ddtp_hostid,
+ { "Hostid", "ddtp.hostid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Host ID", HFILL }},
+ { &hf_ddtp_msgtype,
+ { "Message type", "ddtp.msgtype", FT_UINT32, BASE_DEC, VALS(vals_ddtp_msgtype), 0x0,
+ "Message Type", HFILL }},
+ { &hf_ddtp_opcode,
+ { "Opcode", "ddtp.opcode", FT_UINT32, BASE_DEC, VALS(vals_ddtp_opcode), 0x0,
+ "Update query opcode", HFILL }},
+ { &hf_ddtp_ipaddr,
+ { "IP address", "ddtp.ipaddr", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "IP address", HFILL }},
+ { &hf_ddtp_status,
+ { "Status", "ddtp.status", FT_UINT32, BASE_DEC, VALS(vals_ddtp_status), 0x0,
+ "Update reply status", HFILL }}
+ };
+
+ static gint *ett[] = { &ett_ddtp };
+
+ proto_ddtp = proto_register_protocol("Dynamic DNS Tools Protocol",
+ "DDTP", "ddtp");
+ proto_register_field_array(proto_ddtp, hf_ddtp, array_length(hf_ddtp));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ddtp(void)
+{
+ dissector_handle_t ddtp_handle;
+
+ ddtp_handle = new_create_dissector_handle(dissect_ddtp, proto_ddtp);
+ dissector_add("udp.port", UDP_PORT_DDTP, ddtp_handle);
+}
diff --git a/epan/dissectors/packet-ddtp.h b/epan/dissectors/packet-ddtp.h
new file mode 100644
index 0000000000..599b25c2a1
--- /dev/null
+++ b/epan/dissectors/packet-ddtp.h
@@ -0,0 +1,56 @@
+/* packet-ddtp.h
+ * Routines for DDTP (Dynamic DNS Tools Protocol) packet disassembly
+ * see http://ddt.sourceforge.net/
+ * Olivier Abad <oabad@noos.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 2000
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ */
+
+#ifndef __PACKET_DDTP_H__
+#define __PACKET_DDTP_H__
+
+#define DDTP_VERSION_ERROR 0
+#define DDTP_VERSION_4 1
+#define DDTP_VERSION_5 2
+
+#define DDTP_ENCRYPT_ERROR 0
+#define DDTP_ENCRYPT_PLAINTEXT 1
+#define DDTP_ENCRYPT_BLOWFISH 2
+
+#define DDTP_MESSAGE_ERROR 0
+#define DDTP_UPDATE_QUERY 1
+#define DDTP_UPDATE_REPLY 2
+#define DDTP_ALIVE_QUERY 3
+#define DDTP_ALIVE_REPLY 4
+
+#define DDTP_MARK_ONLINE 0
+#define DDTP_MARK_OFFLINE 1
+
+#define DDTP_UPDATE_SUCCEEDED 0
+#define DDTP_UPDATE_FAILED 1
+#define DDTP_INVALID_PASSWORD 2
+#define DDTP_INVALID_ACCOUNT 3
+#define DDTP_INVALID_OPCODE 4
+
+#endif
diff --git a/epan/dissectors/packet-dec-bpdu.c b/epan/dissectors/packet-dec-bpdu.c
new file mode 100644
index 0000000000..13c4984133
--- /dev/null
+++ b/epan/dissectors/packet-dec-bpdu.c
@@ -0,0 +1,300 @@
+/* packet-dec-bpdu.c
+ * Routines for DEC BPDU (DEC Spanning Tree Protocol) disassembly
+ *
+ * $Id$
+ *
+ * Copyright 2001 Paul Ionescu <paul@acorp.ro>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "etypes.h"
+#include "ppptypes.h"
+
+/* Offsets of fields within a BPDU */
+
+#define BPDU_DEC_CODE 0
+#define BPDU_TYPE 1
+#define BPDU_VERSION 2
+#define BPDU_FLAGS 3
+#define BPDU_ROOT_PRI 4
+#define BPDU_ROOT_MAC 6
+#define BPDU_ROOT_PATH_COST 12
+#define BPDU_BRIDGE_PRI 14
+#define BPDU_BRIDGE_MAC 16
+#define BPDU_PORT_IDENTIFIER 22
+#define BPDU_MESSAGE_AGE 23
+#define BPDU_HELLO_TIME 24
+#define BPDU_MAX_AGE 25
+#define BPDU_FORWARD_DELAY 26
+
+#define DEC_BPDU_SIZE 27
+
+/* Flag bits */
+
+#define BPDU_FLAGS_SHORT_TIMERS 0x80
+#define BPDU_FLAGS_TCACK 0x02
+#define BPDU_FLAGS_TC 0x01
+
+static int proto_dec_bpdu = -1;
+static int hf_dec_bpdu_proto_id = -1;
+static int hf_dec_bpdu_type = -1;
+static int hf_dec_bpdu_version_id = -1;
+static int hf_dec_bpdu_flags = -1;
+static int hf_dec_bpdu_flags_short_timers = -1;
+static int hf_dec_bpdu_flags_tcack = -1;
+static int hf_dec_bpdu_flags_tc = -1;
+static int hf_dec_bpdu_root_pri = -1;
+static int hf_dec_bpdu_root_mac = -1;
+static int hf_dec_bpdu_root_cost = -1;
+static int hf_dec_bpdu_bridge_pri = -1;
+static int hf_dec_bpdu_bridge_mac = -1;
+static int hf_dec_bpdu_port_id = -1;
+static int hf_dec_bpdu_msg_age = -1;
+static int hf_dec_bpdu_hello_time = -1;
+static int hf_dec_bpdu_max_age = -1;
+static int hf_dec_bpdu_forward_delay = -1;
+
+static gint ett_dec_bpdu = -1;
+static gint ett_dec_bpdu_flags = -1;
+
+static const value_string protocol_id_vals[] = {
+ { 0xe1, "DEC Spanning Tree Protocol" },
+ { 0, NULL }
+};
+
+#define BPDU_TYPE_TOPOLOGY_CHANGE 2
+#define BPDU_TYPE_HELLO 25
+
+static const value_string bpdu_type_vals[] = {
+ { BPDU_TYPE_TOPOLOGY_CHANGE, "Topology Change Notification" },
+ { BPDU_TYPE_HELLO, "Hello Packet" },
+ { 0, NULL }
+};
+
+static const char initial_sep[] = " (";
+static const char cont_sep[] = ", ";
+
+#define APPEND_BOOLEAN_FLAG(flag, item, string) \
+ if(flag){ \
+ if(item) \
+ proto_item_append_text(item, string, sep); \
+ sep = cont_sep; \
+ }
+
+static void
+dissect_dec_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 protocol_version;
+ guint8 bpdu_type;
+ guint8 flags;
+ proto_tree *bpdu_tree;
+ proto_tree *flags_tree;
+ proto_item *ti;
+ const char *sep;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DEC_STP");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ bpdu_type = tvb_get_guint8(tvb, BPDU_TYPE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(bpdu_type, bpdu_type_vals,
+ "Unknown BPDU type (%u)"));
+ }
+
+ set_actual_length(tvb, DEC_BPDU_SIZE);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_dec_bpdu, tvb, 0, DEC_BPDU_SIZE,
+ FALSE);
+ bpdu_tree = proto_item_add_subtree(ti, ett_dec_bpdu);
+
+ protocol_version = tvb_get_guint8(tvb, BPDU_VERSION);
+
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_proto_id, tvb,
+ BPDU_DEC_CODE, 1, FALSE);
+
+ proto_tree_add_uint(bpdu_tree, hf_dec_bpdu_type, tvb,
+ BPDU_TYPE, 1, bpdu_type);
+
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_version_id, tvb,
+ BPDU_VERSION, 1, FALSE);
+
+ flags = tvb_get_guint8(tvb, BPDU_FLAGS);
+ ti = proto_tree_add_uint(bpdu_tree, hf_dec_bpdu_flags, tvb,
+ BPDU_FLAGS, 1, flags);
+ flags_tree = proto_item_add_subtree(ti, ett_dec_bpdu_flags);
+ sep = initial_sep;
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_SHORT_TIMERS, ti,
+ "%sUse short timers");
+ proto_tree_add_boolean(flags_tree, hf_dec_bpdu_flags_short_timers, tvb,
+ BPDU_FLAGS, 1, flags);
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TCACK, ti,
+ "%sTopology Change Acknowledgment");
+ proto_tree_add_boolean(flags_tree, hf_dec_bpdu_flags_tcack, tvb,
+ BPDU_FLAGS, 1, flags);
+ APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TC, ti,
+ "%sTopology Change");
+ proto_tree_add_boolean(flags_tree, hf_dec_bpdu_flags_tc, tvb,
+ BPDU_FLAGS, 1, flags);
+ if (sep != initial_sep) {
+ /* We put something in; put in the terminating ")" */
+ proto_item_append_text(ti, ")");
+ }
+
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_root_pri, tvb,
+ BPDU_ROOT_PRI, 2, FALSE);
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_root_mac, tvb,
+ BPDU_ROOT_MAC, 6, FALSE);
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_root_cost, tvb,
+ BPDU_ROOT_PATH_COST, 2, FALSE);
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_bridge_pri, tvb,
+ BPDU_BRIDGE_PRI, 2, FALSE);
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_bridge_mac, tvb,
+ BPDU_BRIDGE_MAC, 6, FALSE);
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_port_id, tvb,
+ BPDU_PORT_IDENTIFIER, 1, FALSE);
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_msg_age, tvb,
+ BPDU_MESSAGE_AGE, 1, FALSE);
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_hello_time, tvb,
+ BPDU_HELLO_TIME, 1, FALSE);
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_max_age, tvb,
+ BPDU_MAX_AGE, 1, FALSE);
+ proto_tree_add_item(bpdu_tree, hf_dec_bpdu_forward_delay, tvb,
+ BPDU_FORWARD_DELAY, 1, FALSE);
+
+ }
+}
+
+static const true_false_string yesno = {
+ "Yes",
+ "No"
+};
+
+void
+proto_register_dec_bpdu(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_dec_bpdu_proto_id,
+ { "Protocol Identifier", "dec_stp.protocol",
+ FT_UINT8, BASE_HEX, VALS(&protocol_id_vals), 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_type,
+ { "BPDU Type", "dec_stp.type",
+ FT_UINT8, BASE_DEC, VALS(&bpdu_type_vals), 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_version_id,
+ { "BPDU Version", "dec_stp.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_flags,
+ { "BPDU flags", "dec_stp.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_flags_short_timers,
+ { "Use short timers", "dec_stp.flags.short_timers",
+ FT_BOOLEAN, 8, TFS(&yesno), BPDU_FLAGS_SHORT_TIMERS,
+ "", HFILL }},
+ { &hf_dec_bpdu_flags_tcack,
+ { "Topology Change Acknowledgment", "dec_stp.flags.tcack",
+ FT_BOOLEAN, 8, TFS(&yesno), BPDU_FLAGS_TCACK,
+ "", HFILL }},
+ { &hf_dec_bpdu_flags_tc,
+ { "Topology Change", "dec_stp.flags.tc",
+ FT_BOOLEAN, 8, TFS(&yesno), BPDU_FLAGS_TC,
+ "", HFILL }},
+ { &hf_dec_bpdu_root_pri,
+ { "Root Priority", "dec_stp.root.pri",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_root_mac,
+ { "Root MAC", "dec_stp.root.mac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_root_cost,
+ { "Root Path Cost", "dec_stp.root.cost",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_bridge_pri,
+ { "Bridge Priority", "dec_stp.bridge.pri",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_bridge_mac,
+ { "Bridge MAC", "dec_stp.bridge.mac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_port_id,
+ { "Port identifier", "dec_stp.port",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_msg_age,
+ { "Message Age", "dec_stp.msg_age",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_hello_time,
+ { "Hello Time", "dec_stp.hello",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_max_age,
+ { "Max Age", "dec_stp.max_age",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dec_bpdu_forward_delay,
+ { "Forward Delay", "dec_stp.forward",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_dec_bpdu,
+ &ett_dec_bpdu_flags,
+ };
+
+ proto_dec_bpdu = proto_register_protocol("DEC Spanning Tree Protocol",
+ "DEC_STP", "dec_stp");
+ proto_register_field_array(proto_dec_bpdu, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dec_bpdu(void)
+{
+ dissector_handle_t dec_bpdu_handle;
+
+ dec_bpdu_handle = create_dissector_handle(dissect_dec_bpdu,
+ proto_dec_bpdu);
+ dissector_add("ethertype", ETHERTYPE_DEC_LB, dec_bpdu_handle);
+ dissector_add("chdlctype", ETHERTYPE_DEC_LB, dec_bpdu_handle);
+ dissector_add("ppp.protocol", PPP_DEC_LB, dec_bpdu_handle);
+}
diff --git a/epan/dissectors/packet-dhcpv6.c b/epan/dissectors/packet-dhcpv6.c
new file mode 100644
index 0000000000..528969277f
--- /dev/null
+++ b/epan/dissectors/packet-dhcpv6.c
@@ -0,0 +1,795 @@
+/* packet-dhpcv6.c
+ * Routines for DHCPv6 packet disassembly
+ * Jun-ichiro itojun Hagino <itojun@iijlab.net>
+ * IItom Tsutomu MIENO <iitom@utouto.com>
+ * SHIRASAKI Yasuhiro <yasuhiro@gnome.gr.jp>
+ * Tony Lindstrom <tony.lindstrom@ericsson.com>
+ *
+ * $Id$
+ *
+ * The information used comes from:
+ * RFC3315.txt
+ * RFC3319.txt
+ * RFC3633.txt
+ * RFC3646.txt
+ * draft-ietf-dhc-dhcpv6-opt-nisconfig-02.txt
+ * draft-ietf-dhc-dhcpv6-opt-timeconfig-02.txt
+ * Note that protocol constants are still subject to change, based on IANA
+ * assignment decisions.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/int-64bit.h>
+#include <epan/packet.h>
+#include <epan/ipv6-utils.h>
+
+static int proto_dhcpv6 = -1;
+static int hf_dhcpv6_msgtype = -1;
+
+static guint ett_dhcpv6 = -1;
+static guint ett_dhcpv6_option = -1;
+
+#define UDP_PORT_DHCPV6_DOWNSTREAM 546
+#define UDP_PORT_DHCPV6_UPSTREAM 547
+
+#define DHCPV6_LEASEDURATION_INFINITY 0xffffffff
+
+#define SOLICIT 1
+#define ADVERTISE 2
+#define REQUEST 3
+#define CONFIRM 4
+#define RENEW 5
+#define REBIND 6
+#define REPLY 7
+#define RELEASE 8
+#define DECLINE 9
+#define RECONFIGURE 10
+#define INFORMATION_REQUEST 11
+#define RELAY_FORW 12
+#define RELAY_REPLY 13
+
+#define OPTION_CLIENTID 1
+#define OPTION_SERVERID 2
+#define OPTION_IA_NA 3
+#define OPTION_IA_TA 4
+#define OPTION_IAADDR 5
+#define OPTION_ORO 6
+#define OPTION_PREFERENCE 7
+#define OPTION_ELAPSED_TIME 8
+#define OPTION_RELAY_MSG 9
+/* #define OPTION_SERVER_MSG 10 */
+#define OPTION_AUTH 11
+#define OPTION_UNICAST 12
+#define OPTION_STATUS_CODE 13
+#define OPTION_RAPID_COMMIT 14
+#define OPTION_USER_CLASS 15
+#define OPTION_VENDOR_CLASS 16
+#define OPTION_VENDOR_OPTS 17
+#define OPTION_INTERFACE_ID 18
+#define OPTION_RECONF_MSG 19
+#define OPTION_RECONF_ACCEPT 20
+#define OPTION_SIP_SERVER_D 21
+#define OPTION_SIP_SERVER_A 22
+#define OPTION_DNS_SERVERS 23
+#define OPTION_DOMAIN_LIST 24
+#define OPTION_IA_PD 25
+#define OPTION_IAPREFIX 26
+
+/*
+ * The followings are unassigned numbers.
+ */
+#define OPTION_NIS_SERVERS 35
+#define OPTION_NISP_SERVERS 36
+#define OPTION_NIS_DOMAIN_NAME 37
+#define OPTION_NISP_DOMAIN_NAME 38
+#define OPTION_NTP_SERVERS 40
+#define OPTION_TIME_ZONE 41
+
+#define DUID_LLT 1
+#define DUID_EN 2
+#define DUID_LL 3
+#define DUID_LL_OLD 4
+
+static const value_string msgtype_vals[] = {
+ { SOLICIT, "Solicit" },
+ { ADVERTISE, "Advertise" },
+ { REQUEST, "Request" },
+ { CONFIRM, "Confirm" },
+ { RENEW, "Renew" },
+ { REBIND, "Rebind" },
+ { REPLY, "Reply" },
+ { RELEASE, "Release" },
+ { DECLINE, "Decline" },
+ { RECONFIGURE, "Reconfigure" },
+ { INFORMATION_REQUEST, "Information-request" },
+ { RELAY_FORW, "Relay-forw" },
+ { RELAY_REPLY, "Relay-reply" },
+ { 0, NULL }
+};
+
+static const value_string opttype_vals[] = {
+ { OPTION_CLIENTID, "Client Identifier" },
+ { OPTION_SERVERID, "Server Identifier" },
+ { OPTION_IA_NA, "Identify Association" },
+ { OPTION_IA_TA, "Identify Association for Temporary Address" },
+ { OPTION_IAADDR, "IA Address" },
+ { OPTION_ORO, "Option Request" },
+ { OPTION_PREFERENCE, "Preference" },
+ { OPTION_ELAPSED_TIME, "Elapsed time" },
+ { OPTION_RELAY_MSG, "Relay Message" },
+/* { OPTION_SERVER_MSG, "Server message" }, */
+ { OPTION_AUTH, "Authentication" },
+ { OPTION_UNICAST, "Server unicast" },
+ { OPTION_STATUS_CODE, "Status code" },
+ { OPTION_RAPID_COMMIT, "Rapid Commit" },
+ { OPTION_USER_CLASS, "User Class" },
+ { OPTION_VENDOR_CLASS, "Vendor Class" },
+ { OPTION_VENDOR_OPTS, "Vendor-specific Information" },
+ { OPTION_INTERFACE_ID, "Interface-Id" },
+ { OPTION_RECONF_MSG, "Reconfigure Message" },
+ { OPTION_RECONF_ACCEPT, "Reconfigure Accept" },
+ { OPTION_SIP_SERVER_D, "SIP Server Domain Name List" },
+ { OPTION_SIP_SERVER_A, "SIP Servers IPv6 Address List" },
+ { OPTION_DNS_SERVERS, "DNS recursive name server" },
+ { OPTION_DOMAIN_LIST, "Domain Search List" },
+ { OPTION_IA_PD, "Identify Association for Prefix Delegation" },
+ { OPTION_IAPREFIX, "IA Prefix" },
+ { OPTION_NIS_SERVERS, "Network Information Server" },
+ { OPTION_NISP_SERVERS, "Network Information Server V2" },
+ { OPTION_NIS_DOMAIN_NAME, "Network Information Server Domain Name" },
+ { OPTION_NISP_DOMAIN_NAME,"Network Information Server V2 Domain Name" },
+ { OPTION_NTP_SERVERS, "Network Time Protocol Server" },
+ { OPTION_TIME_ZONE, "Time zone" },
+ { 0, NULL }
+};
+
+static const value_string statuscode_vals[] =
+{
+ {0, "Success" },
+ {1, "UnspecFail" },
+ {2, "NoAddrAvail" },
+ {3, "NoBinding" },
+ {4, "NotOnLink" },
+ {5, "UseMulticast" },
+ {6, "NoPrefixAvail" },
+ {0, NULL }
+};
+
+static const value_string duidtype_vals[] =
+{
+ { DUID_LLT, "link-layer address plus time" },
+ { DUID_EN, "assigned by vendor based on Enterprise number" },
+ { DUID_LL, "link-layer address" },
+ { DUID_LL_OLD, "link-layer address (old)" },
+ { 0, NULL }
+};
+
+/* Returns the number of bytes consumed by this option. */
+static int
+dhcpv6_option(tvbuff_t *tvb, proto_tree *bp_tree, int off, int eoff,
+ gboolean *at_end)
+{
+ guint16 opttype;
+ guint16 optlen;
+ guint16 temp_optlen = 0;
+ proto_item *ti;
+ proto_tree *subtree;
+ int i;
+ struct e_in6_addr in6;
+ guint16 duidtype;
+
+ /* option type and length must be present */
+ if (eoff - off < 4) {
+ *at_end = TRUE;
+ return 0;
+ }
+
+ opttype = tvb_get_ntohs(tvb, off);
+ optlen = tvb_get_ntohs(tvb, off + 2);
+
+ /* truncated case */
+ if (eoff - off < 4 + optlen) {
+ *at_end = TRUE;
+ return 0;
+ }
+
+ ti = proto_tree_add_text(bp_tree, tvb, off, 4 + optlen,
+ "%s", val_to_str(opttype, opttype_vals, "DHCP option %u"));
+
+ subtree = proto_item_add_subtree(ti, ett_dhcpv6_option);
+ proto_tree_add_text(subtree, tvb, off, 2, "option type: %d", opttype);
+ proto_tree_add_text(subtree, tvb, off + 2, 2, "option length: %d",
+ optlen);
+
+ off += 4;
+ switch (opttype) {
+ case OPTION_CLIENTID:
+ case OPTION_SERVERID:
+ if (optlen < 2) {
+ proto_tree_add_text(subtree, tvb, off, optlen,
+ "DUID: malformed option");
+ break;
+ }
+ duidtype = tvb_get_ntohs(tvb, off);
+ proto_tree_add_text(subtree, tvb, off, 2,
+ "DUID type: %s (%u)",
+ val_to_str(duidtype,
+ duidtype_vals, "Unknown"),
+ duidtype);
+ switch (duidtype) {
+ case DUID_LLT:
+ if (optlen < 8) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "DUID: malformed option");
+ break;
+ }
+ /* XXX seconds since Jan 1 2000 */
+ proto_tree_add_text(subtree, tvb, off + 2, 2,
+ "Hardware type: %u",
+ tvb_get_ntohs(tvb, off + 2));
+ proto_tree_add_text(subtree, tvb, off + 4, 4,
+ "Time: %u", tvb_get_ntohl(tvb, off + 4));
+ if (optlen > 8) {
+ proto_tree_add_text(subtree, tvb, off + 8,
+ optlen - 8, "Link-layer address");
+ }
+ break;
+ case DUID_EN:
+ if (optlen < 6) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "DUID: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off + 2, 4,
+ "enterprise-number");
+ if (optlen > 6) {
+ proto_tree_add_text(subtree, tvb, off + 6,
+ optlen - 6, "identifier");
+ }
+ break;
+ case DUID_LL:
+ case DUID_LL_OLD:
+ if (optlen < 4) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "DUID: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off + 2, 2,
+ "Hardware type: %u",
+ tvb_get_ntohs(tvb, off + 2));
+ if (optlen > 4) {
+ proto_tree_add_text(subtree, tvb, off + 4,
+ optlen - 4, "Link-layer address");
+ }
+ break;
+ }
+ break;
+ case OPTION_IA_NA:
+ case OPTION_IA_PD:
+ if (optlen < 12) {
+ if (opttype == OPTION_IA_NA)
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "IA_NA: malformed option");
+ else
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "IA_PD: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off, 4,
+ "IAID: %u",
+ tvb_get_ntohl(tvb, off));
+ proto_tree_add_text(subtree, tvb, off+4, 4,
+ "T1: %u", tvb_get_ntohl(tvb, off+4));
+ proto_tree_add_text(subtree, tvb, off+8, 4,
+ "T2: %u", tvb_get_ntohl(tvb, off+8));
+
+ temp_optlen = 12;
+ while ((optlen - temp_optlen) > 0) {
+ gboolean at_end_ = FALSE;
+ temp_optlen += dhcpv6_option(tvb, subtree, off+temp_optlen, off + optlen, &at_end_);
+ }
+ break;
+ case OPTION_IA_TA:
+ if (optlen < 4) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "IA_TA: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off, 4,
+ "IAID: %u",
+ tvb_get_ntohl(tvb, off));
+ temp_optlen = 4;
+ while ((optlen - temp_optlen) > 0) {
+ gboolean at_end_;
+ temp_optlen += dhcpv6_option(tvb, subtree, off+temp_optlen, off + optlen, &at_end_);
+ }
+ break;
+ case OPTION_IAADDR:
+ {
+ guint32 preferred_lifetime, valid_lifetime;
+
+ if (optlen < 24) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "IAADDR: malformed option");
+ break;
+ }
+ tvb_memcpy(tvb, (guint8 *)&in6, off, sizeof(in6));
+ proto_tree_add_text(subtree, tvb, off,
+ sizeof(in6), "IPv6 address: %s",
+ ip6_to_str(&in6));
+
+ preferred_lifetime = tvb_get_ntohl(tvb, off + 16);
+ valid_lifetime = tvb_get_ntohl(tvb, off + 20);
+
+ if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
+ proto_tree_add_text(subtree, tvb, off + 16, 4,
+ "Preferred lifetime: infinity");
+ } else {
+ proto_tree_add_text(subtree, tvb, off + 16, 4,
+ "Preferred lifetime: %u", preferred_lifetime);
+ }
+ if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
+ proto_tree_add_text(subtree, tvb, off + 20, 4,
+ "Valid lifetime: infinity");
+ } else {
+ proto_tree_add_text(subtree, tvb, off + 20, 4,
+ "Valid lifetime: %u", valid_lifetime);
+ }
+
+ temp_optlen = 24;
+ while ((optlen - temp_optlen) > 0) {
+ gboolean at_end_;
+ temp_optlen += dhcpv6_option(tvb, subtree, off+temp_optlen, off + optlen, &at_end_);
+ }
+ }
+ break;
+ case OPTION_ORO:
+ for (i = 0; i < optlen; i += 2) {
+ guint16 requested_opt_code;
+ requested_opt_code = tvb_get_ntohs(tvb, off + i);
+ proto_tree_add_text(subtree, tvb, off + i,
+ 2, "Requested Option code: %s (%d)",
+ val_to_str(requested_opt_code,
+ opttype_vals,
+ "Unknown"),
+ requested_opt_code);
+ }
+ break;
+ case OPTION_PREFERENCE:
+ if (optlen != 1) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "PREFERENCE: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off, 1,
+ "pref-value: %d",
+ (guint32)tvb_get_guint8(tvb, off));
+ break;
+ case OPTION_ELAPSED_TIME:
+ if (optlen != 2) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "ELAPSED-TIME: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off, 2,
+ "elapsed-time: %d sec",
+ (guint32)tvb_get_ntohs(tvb, off));
+ break;
+ case OPTION_RELAY_MSG:
+ if (optlen == 0) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "RELAY-MSG: malformed option");
+ break;
+ } else {
+ gboolean at_end_;
+ dhcpv6_option(tvb, subtree, off, off + optlen, &at_end_);
+ }
+ break;
+ case OPTION_AUTH:
+ if (optlen < 15) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "AUTH: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off, 1,
+ "Protocol: %d",
+ (guint32)tvb_get_guint8(tvb, off));
+ proto_tree_add_text(subtree, tvb, off+1, 1,
+ "Algorithm: %d",
+ (guint32)tvb_get_guint8(tvb, off+1));
+ proto_tree_add_text(subtree, tvb, off+2, 1,
+ "RDM: %d",
+ (guint32)tvb_get_guint8(tvb, off+2));
+ proto_tree_add_text(subtree, tvb, off+3, 8,
+ "Reply Detection");
+ proto_tree_add_text(subtree, tvb, off+11, optlen-11,
+ "Authentication Information");
+ break;
+ case OPTION_UNICAST:
+ if (optlen != 16) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "UNICAST: malformed option");
+ break;
+ }
+ tvb_memcpy(tvb, (guint8 *)&in6, off, sizeof(in6));
+ proto_tree_add_text(subtree, tvb, off,
+ sizeof(in6), "IPv6 address: %s",
+ ip6_to_str(&in6));
+ break;
+ case OPTION_STATUS_CODE:
+ {
+ guint16 status_code;
+ char *status_message = 0;
+ status_code = tvb_get_ntohs(tvb, off);
+ proto_tree_add_text(subtree, tvb, off, 2,
+ "Status Code: %s (%d)",
+ val_to_str(status_code, statuscode_vals,
+ "Unknown"),
+ status_code);
+
+ if (optlen - 2 > 0) {
+ status_message = tvb_get_string(tvb, off + 2, optlen - 2);
+ proto_tree_add_text(subtree, tvb, off + 2, optlen - 2,
+ "Status Message: %s",
+ status_message);
+ g_free(status_message);
+ }
+ }
+ break;
+ case OPTION_VENDOR_CLASS:
+ if (optlen < 4) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "VENDOR_CLASS: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off, 4,
+ "enterprise-number: %u",
+ tvb_get_ntohl(tvb, off));
+ if (optlen > 4) {
+ proto_tree_add_text(subtree, tvb, off+4, optlen-4,
+ "vendor-class-data");
+ }
+ break;
+ case OPTION_VENDOR_OPTS:
+ if (optlen < 4) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "VENDOR_OPTS: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off, 4,
+ "enterprise-number: %u",
+ tvb_get_ntohl(tvb, off));
+ if (optlen > 4) {
+ proto_tree_add_text(subtree, tvb, off+4, optlen-4,
+ "option-data");
+ }
+ break;
+ case OPTION_INTERFACE_ID:
+ if (optlen == 0) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "INTERFACE_ID: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off, optlen, "Interface-ID");
+ break;
+ case OPTION_RECONF_MSG:
+ if (optlen != 1) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "RECONF_MSG: malformed option");
+ break;
+ }
+ proto_tree_add_text(subtree, tvb, off, optlen,
+ "Reconfigure-type: %s",
+ val_to_str(tvb_get_guint8(tvb, off),
+ msgtype_vals,
+ "Message Type %u"));
+ break;
+ case OPTION_SIP_SERVER_D:
+ if (optlen > 0) {
+ proto_tree_add_text(subtree, tvb, off, optlen,
+ "SIP Servers Domain Search List");
+ }
+ case OPTION_SIP_SERVER_A:
+ if (optlen % 16) {
+ proto_tree_add_text(subtree, tvb, off, optlen,
+ "SIP servers address: malformed option");
+ break;
+ }
+ for (i = 0; i < optlen; i += 16) {
+ tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
+ proto_tree_add_text(subtree, tvb, off + i,
+ sizeof(in6), "SIP servers address: %s",
+ ip6_to_str(&in6));
+ }
+ break;
+ case OPTION_DNS_SERVERS:
+ if (optlen % 16) {
+ proto_tree_add_text(subtree, tvb, off, optlen,
+ "DNS servers address: malformed option");
+ break;
+ }
+ for (i = 0; i < optlen; i += 16) {
+ tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
+ proto_tree_add_text(subtree, tvb, off + i,
+ sizeof(in6), "DNS servers address: %s",
+ ip6_to_str(&in6));
+ }
+ break;
+ case OPTION_DOMAIN_LIST:
+ if (optlen > 0) {
+ proto_tree_add_text(subtree, tvb, off, optlen, "DNS Domain Search List");
+ }
+ break;
+ case OPTION_NIS_SERVERS:
+ if (optlen % 16) {
+ proto_tree_add_text(subtree, tvb, off, optlen,
+ "NIS servers address: malformed option");
+ break;
+ }
+ for (i = 0; i < optlen; i += 16) {
+ tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
+ proto_tree_add_text(subtree, tvb, off + i,
+ sizeof(in6), "NIS servers address: %s",
+ ip6_to_str(&in6));
+ }
+ break;
+ case OPTION_NISP_SERVERS:
+ if (optlen % 16) {
+ proto_tree_add_text(subtree, tvb, off, optlen,
+ "NISP servers address: malformed option");
+ break;
+ }
+ for (i = 0; i < optlen; i += 16) {
+ tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
+ proto_tree_add_text(subtree, tvb, off + i,
+ sizeof(in6), "NISP servers address: %s",
+ ip6_to_str(&in6));
+ }
+ break;
+ case OPTION_NIS_DOMAIN_NAME:
+ if (optlen > 0) {
+ proto_tree_add_text(subtree, tvb, off, optlen, "nis-domain-name");
+ }
+ break;
+ case OPTION_NISP_DOMAIN_NAME:
+ if (optlen > 0) {
+ proto_tree_add_text(subtree, tvb, off, optlen, "nisp-domain-name");
+ }
+ break;
+ case OPTION_NTP_SERVERS:
+ if (optlen % 16) {
+ proto_tree_add_text(subtree, tvb, off, optlen,
+ "NTP servers address: malformed option");
+ break;
+ }
+ for (i = 0; i < optlen; i += 16) {
+ tvb_memcpy(tvb, (guint8 *)&in6, off + i, sizeof(in6));
+ proto_tree_add_text(subtree, tvb, off + i,
+ sizeof(in6), "NTP servers address: %s",
+ ip6_to_str(&in6));
+ }
+ break;
+ case OPTION_TIME_ZONE:
+ if (optlen > 0) {
+ proto_tree_add_text(subtree, tvb, off, optlen, "time-zone");
+ }
+ break;
+ case OPTION_IAPREFIX:
+ {
+ guint32 preferred_lifetime, valid_lifetime;
+ guint8 prefix_length;
+ struct e_in6_addr in6;
+
+ if (optlen < 25) {
+ proto_tree_add_text(subtree, tvb, off,
+ optlen, "IAPREFIX: malformed option");
+ break;
+ }
+
+ preferred_lifetime = tvb_get_ntohl(tvb, off);
+ valid_lifetime = tvb_get_ntohl(tvb, off + 4);
+ prefix_length = tvb_get_guint8(tvb, off + 8);
+ if (preferred_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
+ proto_tree_add_text(subtree, tvb, off, 4,
+ "Preferred lifetime: infinity");
+ } else {
+ proto_tree_add_text(subtree, tvb, off, 4,
+ "Preferred lifetime: %u", preferred_lifetime);
+ }
+ if (valid_lifetime == DHCPV6_LEASEDURATION_INFINITY) {
+ proto_tree_add_text(subtree, tvb, off + 4, 4,
+ "Valid lifetime: infinity");
+ } else {
+ proto_tree_add_text(subtree, tvb, off + 4, 4,
+ "Valid lifetime: %u", valid_lifetime);
+ }
+ proto_tree_add_text(subtree, tvb, off + 8, 1,
+ "Prefix length: %d", prefix_length);
+ tvb_memcpy(tvb, (guint8 *)&in6, off + 9 , sizeof(in6));
+ proto_tree_add_text(subtree, tvb, off + 9,
+ 16, "Prefix address: %s",
+ ip6_to_str(&in6));
+
+ temp_optlen = 25;
+ while ((optlen - temp_optlen) > 0) {
+ gboolean at_end_;
+ temp_optlen += dhcpv6_option(tvb, subtree, off+temp_optlen, off + optlen, &at_end_);
+ }
+ }
+ break;
+ }
+
+ return 4 + optlen;
+}
+
+
+static void
+dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean downstream)
+{
+ proto_tree *bp_tree = NULL;
+ proto_item *ti;
+ guint8 msgtype, hop_count ;
+ guint32 xid;
+ int off = 0;
+ int eoff;
+ struct e_in6_addr in6;
+ gboolean at_end;
+ gboolean relay_msg_option = FALSE;
+ int length;
+
+ eoff = tvb_reported_length(tvb);
+ downstream = 0; /* feature reserved */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ msgtype = tvb_get_guint8(tvb, off);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_dhcpv6, tvb, 0, -1, FALSE);
+ bp_tree = proto_item_add_subtree(ti, ett_dhcpv6);
+ }
+
+ while (msgtype == RELAY_FORW || msgtype == RELAY_REPLY) {
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str(msgtype,
+ msgtype_vals,
+ "Message Type %u"));
+ }
+
+ proto_tree_add_uint(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, msgtype);
+
+ hop_count = tvb_get_guint8(tvb, off+1);
+ proto_tree_add_text(bp_tree, tvb, off+1, 1, "Hop count: %d", hop_count);
+
+ tvb_memcpy(tvb, (guint8 *)&in6, off+2, sizeof(in6));
+ proto_tree_add_text(bp_tree, tvb, off+2, sizeof(in6),
+ "Link-address: %s",ip6_to_str(&in6));
+
+ tvb_memcpy(tvb, (guint8 *)&in6, off+18, sizeof(in6));
+ proto_tree_add_text(bp_tree, tvb, off+18, sizeof(in6),
+ "Peer-address: %s",ip6_to_str(&in6));
+
+ off += 34;
+ relay_msg_option = FALSE;
+
+ while (!relay_msg_option && off < eoff) {
+ length = dhcpv6_option(tvb, bp_tree, off, eoff, &at_end);
+
+ if (tvb_get_ntohs(tvb, off) == OPTION_RELAY_MSG) {
+ relay_msg_option = TRUE;
+ off += 4;
+ }
+ else {
+ if (length > 0)
+ off += length;
+ else {
+ proto_tree_add_text(bp_tree, tvb, off, eoff, "Message: malformed");
+ return;
+ }
+ }
+ }
+
+ msgtype = tvb_get_guint8(tvb, off);
+ }
+
+ xid = tvb_get_ntohl(tvb, off) & 0x00ffffff;
+
+ if (!off) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str(msgtype,
+ msgtype_vals,
+ "Message Type %u"));
+ }
+ }
+
+ if (tree) {
+ proto_tree_add_uint(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1,
+ msgtype);
+ proto_tree_add_text(bp_tree, tvb, off+1, 3, "Transaction-ID: 0x%08x", xid);
+#if 0
+ tvb_memcpy(tvb, (guint8 *)&in6, 4, sizeof(in6));
+ proto_tree_add_text(bp_tree, tvb, 4, sizeof(in6),
+ "Server address: %s", ip6_to_str(&in6));
+#endif
+ }
+
+ off += 4;
+
+ at_end = FALSE;
+ while (off < eoff && !at_end)
+ off += dhcpv6_option(tvb, bp_tree, off, eoff, &at_end);
+}
+
+static void
+dissect_dhcpv6_downstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_dhcpv6(tvb, pinfo, tree, TRUE);
+}
+
+static void
+dissect_dhcpv6_upstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_dhcpv6(tvb, pinfo, tree, FALSE);
+}
+
+
+void
+proto_register_dhcpv6(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_dhcpv6_msgtype,
+ { "Message type", "dhcpv6.msgtype", FT_UINT8,
+ BASE_DEC, VALS(msgtype_vals), 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_dhcpv6,
+ &ett_dhcpv6_option,
+ };
+
+ proto_dhcpv6 = proto_register_protocol("DHCPv6", "DHCPv6", "dhcpv6");
+ proto_register_field_array(proto_dhcpv6, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dhcpv6(void)
+{
+ dissector_handle_t dhcpv6_handle;
+
+ dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_downstream,
+ proto_dhcpv6);
+ dissector_add("udp.port", UDP_PORT_DHCPV6_DOWNSTREAM, dhcpv6_handle);
+ dhcpv6_handle = create_dissector_handle(dissect_dhcpv6_upstream,
+ proto_dhcpv6);
+ dissector_add("udp.port", UDP_PORT_DHCPV6_UPSTREAM, dhcpv6_handle);
+}
diff --git a/epan/dissectors/packet-diameter-defs.h b/epan/dissectors/packet-diameter-defs.h
new file mode 100644
index 0000000000..0a4d6c96cf
--- /dev/null
+++ b/epan/dissectors/packet-diameter-defs.h
@@ -0,0 +1,807 @@
+/*
+ * Filename: packet-diameter-defs.h
+ *
+ * This file contains the static definitions of the Diameter base protocol
+ * AVPs. If libxml is in the LD_LIBRARY_PATH, and dictionary.xml exists,
+ * then it will not be used.
+ *
+ * $Id$
+ * Generated: Fri Feb 23 13:04:15 2001
+ * References:
+ * http://www.ietf.org/rfc/rfc3588.txt
+ * http://www.iana.org/assignments/radius-types
+ * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-cc-03.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-nasreq-14.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-mobileip-16.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-sip-app-01.txt
+ * http://www.ietf.org/html.charters/aaa-charter.html
+ */
+
+#ifndef _PACKET_DIAMETER_DEFS_H
+#define _PACKET_DIAMETER_DEFS_H
+
+
+/* Type to string table */
+
+/* Attribute to String tables */
+static value_string diameter_service_type_vals[]={
+ {1, "Login"},
+ {2, "Framed"},
+ {3, "Callback-Login"},
+ {4, "Callback-Framed"},
+ {5, "Outbound"},
+ {6, "Administrative"},
+ {7, "NAS-Prompt"},
+ {8, "Authenticate-Only"},
+ {9, "Callback-NAS-Prompt"},
+ {10,"Call Check"},
+ {11,"Callback Administrative"},
+ {12,"Voice"}, /*[Chiba] */
+ {13,"Fax"}, /*[Chiba] */
+ {14,"Modem Relay"}, /*[Chiba] */
+ {15,"IAPP-Register"}, /*[IEEE 802.11f][Kerry] */
+ {16,"IAPP-AP-Check"}, /*[IEEE 802.11f][Kerry] */
+ {17,"Authorize Only"}, /*[RFC3576] */
+ {0, (char *)NULL}
+};
+
+static value_string diameter_framed_protocol_vals[]={
+ {1, "PPP"},
+ {2, "SLIP"},
+ {3, "AppleTalk Remote Access Protocol (ARAP)"},
+ {4, "Gandalf proprietary SingleLink/MultiLink protocol"},
+ {5, "Xylogics proprietary IPX/SLIP"},
+ {6, "X.75 Synchronous"},
+ {7, "GPRS PDP Context"},
+ {261,"FR"},
+ {258,"EUUI"},
+ {255,"Ascend-ARA"},
+ {259,"X25"},
+ {256,"MPP"},
+ {257,"EURAW"},
+ {260,"COMB"},
+ {0, (char *)NULL}
+};
+
+static value_string diameter_framed_routing_vals[]={
+ {0, "None"},
+ {1, "Send routing packets"},
+ {2, "Listen for routing packets"},
+ {3, "Send and Listen"},
+ {0, (char *)NULL}
+};
+
+static value_string diameter_framed_compression_vals[]={
+ {0, "None"},
+ {1, "VJ TCP/IP header compression"},
+ {2, "IPX-Header-Compression"},
+ {3, "Stac-LZS compression"},
+ {0, (char *)NULL}
+};
+
+static value_string diameter_login_service_vals[]={
+ {0, "Telnet"},
+ {1, "Rlogin"},
+ {2, "TCP-Clear"},
+ {3, "PortMaster"},
+ {4, "LAT"},
+ {5, "X25-PAD"},
+ {6, "X25-T3POS"},
+ {7, "(unassigned)"},
+ {8, "TCP Clear Quiet (suppresses any NAS-generated connect string)"},
+ {0, (char *)NULL}
+};
+
+static value_string diameter_vendor_specific_vendors[]= {
+ {0, "None"},
+ {5, "ACC"},
+ {9, "Cisco"},
+ {42, "Sun Microsystems"},
+ {166, "Shiva"},
+ {307, "Livingston"},
+ {429, "3Com"},
+ {529, "Ascend"},
+ {1584, "Bay Networks"},
+ {2636, "Juniper Networks"},
+ {5925, "ipUnplugged"},
+ {10415, "3GPP"},
+ {0,NULL}
+};
+
+static value_string diameter_termination_action_vals[]={
+ {0, "Default"},
+ {1, "RADIUS-Request"},
+ {0, (char *)NULL}
+};
+
+static value_string diameter_acct_status_type_vals[]={
+ {1, "Start"},
+ {2, "Stop"},
+ {3, "Alive"},
+ {4, "Modem-Start"},
+ {5, "Modem-Stop"},
+ {6, "Cancel"},
+ {7, "Accounting-On"},
+ {8, "Accounting-Off"},
+ {9, "Tunnel-Start"}, /*[RFC 2867]*/
+ {10, "Tunnel-Stop"}, /*[RFC 2867]*/
+ {11, "Tunnel-Reject"}, /*[RFC 2867]*/
+ {12, "Tunnel-Link-Start"}, /*[RFC 2867]*/
+ {13, "Tunnel-Link-Stop"}, /*[RFC 2867]*/
+ {14, "Tunnel-Link-Reject"}, /*[RFC 2867]*/
+ {15, "Failed"}, /*[RFC 2866]*/
+
+
+ {0, (char *)NULL}
+};
+
+static value_string diameter_acct_authentic_vals[]={
+ {1, "RADIUS"},
+ {0, "None"},
+ {2, "Local"},
+ {3, "Remote"},
+ {4, "Diameter"},
+ {0, (char *)NULL}
+};
+
+static value_string diameter_acct_terminate_cause_vals[]={
+ {1, "User-Request"},
+ {2, "Lost-Carrier"},
+ {3, "Lost-Service"},
+ {4, "Idle-Timeout"},
+ {5, "Session-Timeout"},
+ {6, "Admin-Reset"},
+ {7, "Admin-Reboot"},
+ {8, "Port-Error"},
+ {9, "NAS-Error"},
+ {10, "NAS-Request"},
+ {11, "NAS-Reboot"},
+ {12, "Port-Unneeded"},
+ {13, "Port-Preempted"},
+ {14, "Port-Suspended"},
+ {15, "Service-Unavailable"},
+ {16, "Callback"},
+ {17, "User-Error"},
+ {18, "Host-Request"},
+ {19, "Supplicant Restart"}, /*[RFC3580]*/
+ {20, "Reauthentication Failure"}, /*[RFC3580]*/
+ {21, "Port Reinitialized"}, /*[RFC3580]*/
+ {22, "Port Administratively Disabled"}, /*[RFC3580]*/
+ {0, (char *)NULL}
+};
+static value_string diameter_nas_port_type_vals[]={
+ {0, "Async"},
+ {1, "Sync"},
+ {2, "ISDN Sync"},
+ {3, "ISDN Async V.120"},
+ {4, "ISDN Async V.110"},
+ {5, "Virtual"},
+ {6, "PIAFS"},
+ {7, "HDLC-Clear-Channel"},
+ {8, "X.25"},
+ {9, "X.75"},
+ {10,"G.3 Fax"},
+ {11,"SDSL - Symmetric DSL"},
+ {12,"ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation"},
+ {13,"ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone"},
+ {14,"IDSL - ISDN Digital Subscriber Line"},
+ {15,"Ethernet"},
+ {16,"xDSL - Digital Subscriber Line of unknown type"},
+ {17,"Cable"},
+ {18,"Wireless - Other"},
+ {19,"Wireless - IEEE 802.11"},
+ {20,"Token-Ring"},
+ {21,"FDDI"},
+ {22,"Wireless - CDMA2000"},
+ {23,"Wireless - UMTS"},
+ {24,"Wireless - 1X-EV"},
+ {25,"IAPP"},
+ {26,"FTTP - Fiber to the Premises"},
+ {0, (char *)NULL}
+};
+
+static value_string diameter_tunnel_type_vals[]= {
+ {1,"PPTP"},
+ {2,"L2F"},
+ {3,"L2TP"},
+ {4,"ATMP"},
+ {5,"VTP"},
+ {6,"AH"},
+ {7,"IP-IP-Encap"},
+ {8,"MIN-IP-IP"},
+ {9,"ESP"},
+ {10,"GRE"},
+ {11,"DVS"},
+ {12,"IP-IP"},
+ {13,"VLAN"},
+ {0,NULL}
+};
+
+static value_string diameter_tunnel_medium_type_vals[]= {
+ {1,"IPv4"},
+ {2,"IPv6"},
+ {3,"NSAP"},
+ {4,"HDLC"},
+ {5,"BBN"},
+ {6,"IEEE-802"},
+ {7,"E-163"},
+ {8,"E-164"},
+ {9,"F-69"},
+ {10,"X-121"},
+ {11,"IPX"},
+ {12,"Appletalk"},
+ {13,"Decnet4"},
+ {14,"Vines"},
+ {15,"E-164-NSAP"},
+ {0,NULL}
+};
+/*
+ *Values for RADIUS Attribute 101, Error-Cause Attribute [RFC3576]:
+ */
+static value_string diameter_error_cause_attribute_vals[]= {
+ {201,"Residual Session Context Removed"},
+ {202,"Invalid EAP Packet (Ignored)"},
+ {401,"Unsupported Attribute"},
+ {402,"Missing Attribute"},
+ {403,"NAS Identification Mismatch"},
+ {404,"Invalid Request"},
+ {405,"Unsupported Service"},
+ {406,"Unsupported Extension"},
+ {501,"Administratively Prohibited"},
+ {502,"Request Not Routable (Proxy)"},
+ {503,"Session Context Not Found"},
+ {504,"Session Context Not Removable"},
+ {505,"Other Proxy Processing Error"},
+ {506,"Resources Unavailable"},
+ {507,"Request Initiated"},
+ {0,NULL}
+};
+
+static value_string diameter_accounting_record_type_vals[]= {
+ {1, "Event Record"},
+ {2, "Start Record"},
+ {3, "Interim Record"},
+ {4, "Stop Record"},
+ {0,NULL}
+};
+
+static value_string diameter_auth_request_type_vals[]= {
+ {1, "Authenticate Only"},
+ {2, "Authorize Only"},
+ {3, "Authorize Authenticate"},
+ {0,NULL}
+};
+
+static value_string diameter_auth_session_state_vals[]= {
+ {0, "State Maintained"},
+ {1, "No State Maintained"},
+ {0,NULL}
+};
+
+static value_string diameter_re_auth_request_type_vals[]= {
+ {0, "Authorize Only"},
+ {1, "Authorize Authenticate"},
+ {0,NULL}
+};
+
+static value_string diameter_disconnect_cause_vals[]= {
+ {0, "Rebooting"},
+ {1, "Busy"},
+ {2, "Do Not Want To Talk To You"},
+ {0,NULL}
+};
+
+static value_string diameter_redirect_host_usage_vals[]= {
+ {0, "Don't Cache"},
+ {1, "All Session"},
+ {2, "All Realm"},
+ {3, "Realm and Application"},
+ {4, "All Application"},
+ {5, "All Host"},
+ {0,NULL}
+};
+
+static value_string diameter_session_server_failover_vals[]= {
+ {0, "Refuse Service"},
+ {1, "Try Again"},
+ {2, "Allow Service"},
+ {3, "Try Again / Allow Service"},
+ {0,NULL}
+};
+
+static value_string diameter_termination_cause_vals[]= {
+ {1, "Logout"},
+ {2, "Service Not Provided"},
+ {3, "Bad Answer"},
+ {4, "Administrative"},
+ {5, "Link Broken"},
+ {0,NULL}
+};
+
+static value_string diameter_mip_algorithm_type[] = {
+ {1, "MD5 Prefix/Suffix"},
+ {2, "HMAC-MD5"},
+ {3, "HMAC-SHA1"},
+ {0, NULL}
+};
+
+static value_string diameter_mip_replay_type[] = {
+ {1, "None"},
+ {2, "Nonce"},
+ {3, "Timestamp"},
+ {0, NULL}
+};
+/* XXX TODO correct these values to IANA assigned ones */
+static value_string diameter_application_id_vals[] = {
+ {1, "Diameter NASREQ Application"},
+ {2, "Diameter Mobile IPv4 Application"},
+ {4, "Diameter Credit-Control Application"},
+/* {x, "Diameter Session Initiation Protocol (SIP) Application"},
+ */
+ {2000, "Diameter EAP Application"},
+ {0, NULL}
+
+};
+/* Diameter Session Initiation Protocol (SIP) Application value strings */
+/* Remove comment when IANA assigned values are avalable
+static value_string SIP_user_data_request_type[] = {
+ {0, "COMPLETE_PROFILE"},
+ {1, "REGISTERED_PROFILE"},
+ {2, "UNREGISTERED_PROFILE"},
+ {0, NULL}
+
+};
+static value_string SIP_user_authorization_type[] = {
+ {0, "REGISTRATION"},
+ {1, "DE_REGISTRATION"},
+ {2, "REGISTRATION_AND_CAPABILITIES"},
+ {0, NULL}
+
+};
+
+static value_string SIP_reason_code_vals[] = {
+ {0, "PERMANENT_TERMINATION"},
+ {1, "NEW_SIP_SERVER_ASSIGNED "},
+ {2, "SIP_SERVER_CHANGE"},
+ {3, "REMOVE_SIP_SERVER"},
+ {0, NULL}
+
+};
+static value_string SIP_user_data_already_available_vals[] = {
+ {0, "USER_DATA_NOT_AVAILABLE"},
+ {1, "USER_DATA_ALREADY_AVAILABLE"},
+ {0, NULL}
+
+};
+
+static value_string SIP_server_assignment_type[] ={
+ {0, "NO_ASSIGNMENT"},
+ {1, "REGISTRATION"},
+ {2, "RE_REGISTRATION"},
+ {3, "UNREGISTERED_USER"},
+ {4, "TIMEOUT_DEREGISTRATION"},
+ {5, "USER_DEREGISTRATION"},
+ {6, "TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME"},
+ {7, "USER_DEREGISTRATION_STORE_SERVER_NAME"},
+ {8, "ADMINISTRATIVE_DEREGISTRATION"},
+ {9, "AUTHENTICATION_FAILURE"},
+ {10, "AUTHENTICATION_TIMEOUT"},
+ {11, "DEREGISTRATION_TOO_MUCH_DATA"},
+ {0, NULL}
+
+};
+
+ Remove comment when IANA assigned values are avalable */
+
+/*
+ * The Result-Code data field contains an IANA-managed 32-bit address
+ * space representing errors (see Section 11.4(RFC3588)). Diameter provides the
+ * following classes of errors, all identified by the thousands digit in
+ * the decimal notation:
+ *
+ * - 1xxx (Informational)
+ * - 2xxx (Success)
+ * - 3xxx (Protocol Errors)
+ * - 4xxx (Transient Failures)
+ * - 5xxx (Permanent Failure)
+ */
+
+static value_string diameter_result_code_vals[] = {
+ /* Informational
+ * Errors that fall within this category are used to inform the
+ * requester that a request could not be satisfied, and additional
+ * action is required on its part before access is granted.
+ */
+ {1001, "DIAMETER_MULTI_ROUND_AUTH "},
+ /* Errors that fall within the Success category are used to inform a peer
+ *that a request has been successfully completed
+ */
+ {2001, "DIAMETER_SUCCESS"},
+ {2002, "DIAMETER_LIMITED_SUCCESS"},
+ /* draft-ietf-aaa-diameter-sip-app-01.txt numbers not yet allocated by IANA
+ {2xx1, "DIAMETER_FIRST_REGISTRATION"},
+ {2xx2, "DIAMETER_SUBSEQUENT_REGISTRATION "},
+ {2xx3, "DIAMETER_UNREGISTERED_SERVICE "},
+ {2xx4, "DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED "},
+ {2xx5, "DIAMETER_SERVER_SELECTION"},
+ {2xx6, "DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED"},
+ {2xx7, "DIAMETER_SUCCESS_SERVER_NOT_STORED"},
+
+ */
+
+ /* Protocol errors */
+ {3001, "DIAMETER_COMMAND_UNSUPPORTED"},
+ {3002, "DIAMETER_UNABLE_TO_DELIVER"},
+ {3003, "DIAMETER_REALM_NOT_SERVED"},
+ {3004, "DIAMETER_TOO_BUSY"},
+ {3005, "DIAMETER_LOOP_DETECTED"},
+ {3006, "DIAMETER_REDIRECT_INDICATION"},
+ {3007, "DIAMETER_APPLICATION_UNSUPPORTED"},
+ {3008, "DIAMETER_INVALID_HDR_BITS"},
+ {3009, "DIAMETER_INVALID_AVP_BITS"},
+ {3010, "DIAMETER_UNKNOWN_PEER"},
+ /* Transient Failures */
+ {4001, "DIAMETER_AUTHENTICATION_REJECTED"},
+ {4002, "DIAMETER_OUT_OF_SPACE"},
+ {4003, "ELECTION_LOST"},
+ /* draft-ietf-aaa-diameter-mobileip-16 */
+ {4005, "DIAMETER_ERROR_MIP_REPLY_FAILURE"},
+ {4006, "DIAMETER_ERROR_HA_NOT_AVAILABLE"},
+ {4007, "DIAMETER_ERROR_BAD_KEY"},
+ {4008, "DIAMETER_ERROR_MIP_FILTER_NOT_SUPPORTED"},
+ /* draft-ietf-aaa-diameter-cc-03.txt */
+ {4010, "DIAMETER_END_USER_SERVICE_DENIED"},
+ {4011, "DIAMETER_CREDIT_CONTROL_NOT_APPLICABLE"},
+ {4012, "DIAMETER_CREDIT_LIMIT_REACHED"},
+ /* draft-ietf-aaa-diameter-sip-app-01.txt numbers not yet allocated by IANA
+
+ {4xx1, "DIAMETER_USER_NAME_REQUIRED"},
+ */
+ /* Permanent Failures */
+ {5001, "DIAMETER_AVP_UNSUPPORTED"},
+ {5002, "DIAMETER_UNKNOWN_SESSION_ID"},
+ {5003, "DIAMETER_AUTHORIZATION_REJECTED"},
+ {5004, "DIAMETER_INVALID_AVP_VALUE"},
+ {5005, "DIAMETER_MISSING_AVP"},
+ {5006, "DIAMETER_RESOURCES_EXCEEDED"},
+ {5007, "DIAMETER_CONTRADICTING_AVPS"},
+ {5008, "DIAMETER_AVP_NOT_ALLOWED"},
+ {5009, "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES"},
+ {5010, "DIAMETER_NO_COMMON_APPLICATION"},
+ {5011, "DIAMETER_UNSUPPORTED_VERSION"},
+ {5012, "DIAMETER_UNABLE_TO_COMPLY"},
+ {5013, "DIAMETER_INVALID_BIT_IN_HEADER"},
+ {5014, "DIAMETER_INVALID_AVP_LENGTH"},
+ {5015, "DIAMETER_INVALID_MESSAGE_LENGTH"},
+ {5016, "DIAMETER_INVALID_AVP_BIT_COMBO"},
+ {5017, "DIAMETER_NO_COMMON_SECURITY"},
+ {5018, "DIAMETER_AVP_NOT_ALLOWED"},
+ {5019, "DIAMETER_AVP_OCCURS_TOO_MANY_TIMES"},
+ /* draft-ietf-aaa-diameter-mobileip-16 */
+ {5024, "DIAMETER_ERROR_NO_FOREIGN_HA_SERVICE"},
+ {5025, "DIAMETER_ERROR_END_TO_END_MIP_KEY_ENCRYPTION"},
+ /* draft-ietf-aaa-diameter-cc-03.txt */
+ {5030, "DIAMETER_USER_UNKNOWN"},
+ {5031, "DIAMETER_RATING_FAILED"},
+ {5032, "DIAMETER_CREDIT_LIMIT_REACHED"},
+
+ /* draft-ietf-aaa-diameter-sip-app-01.txt numbers not yet allocated by IANA
+
+ {5xx1, "DIAMETER_ERROR_USER_UNKNOWN"},
+ {5xx2, "DIAMETER_ERROR_IDENTITIES_DONT_MATCH"},
+ {5xx3, "DIAMETER_ERROR_IDENTITY_NOT_REGISTERED"},
+ {5xx4, "DIAMETER_ERROR_ROAMING_NOT_ALLOWED"},
+ {5xx5, "DIAMETER_ERROR_IDENTITY_ALREADY_REGISTERED"},
+ {5xx6, "DIAMETER_ERROR_USER_UNKNOWN"},
+ {5xx7, "DIAMETER_ERROR_IN_ASSIGNMENT_TYPE"},
+ {5xx8, "DIAMETER_ERROR_TOO_MUCH_DATA"},
+ {5xx9, "DIAMETER_ERROR_NOT_SUPPORTED_USER_DATA"},
+ */
+ {0, NULL}
+};
+
+
+static struct old_avp_info old_diameter_avps[] = {
+ /* Radius Attributes */
+ { 1, "User-Name", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { 2, "User-Password", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 3, "CHAP-Password", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 4, "NAS-IP-Address", DIAMETER_IP_ADDRESS, (value_string *)NULL},
+ { 5, "NAS-Port", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 6, "Service-Type", DIAMETER_ENUMERATED, diameter_service_type_vals},
+ { 7, "Framed-Protocol", DIAMETER_ENUMERATED, diameter_framed_protocol_vals},
+ { 8, "Framed-IP-Address", DIAMETER_IP_ADDRESS, (value_string *)NULL},
+ { 9, "Framed-IP-Netmask", DIAMETER_IP_ADDRESS, (value_string *)NULL},
+ { 10, "Framed-Routing", DIAMETER_ENUMERATED, diameter_framed_routing_vals},
+ { 11, "Filter-Id", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { 12, "Framed-MTU", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 13, "Framed-Compression", DIAMETER_ENUMERATED, diameter_framed_compression_vals},
+ { 14, "Login-IP-Host", DIAMETER_IP_ADDRESS, (value_string *)NULL},
+ { 15, "Login-Service", DIAMETER_ENUMERATED, diameter_login_service_vals},
+ { 16, "Login-TCP-Port", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 17, "Old-Password", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 18, "Reply-Message", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { 19, "Callback-Number", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 20, "Callback-Id", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ /* 21 is Unassigned */
+ { 22, "Framed-Route", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { 23, "Framed-IPX-Network", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 24, "State", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 25, "Class", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 26, "Vendor-Specific", DIAMETER_ENUMERATED, diameter_vendor_specific_vendors},
+ { 27, "Session-Timeout", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 28, "Idle-Timeout", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 29, "Termination-Action", DIAMETER_ENUMERATED, diameter_termination_action_vals},
+ { 30, "Called-Station-Id", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 31, "Calling-Station-Id", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 32, "NAS-Identifier", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 33, "Proxy-State", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 34, "Login-LAT-Service", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 35, "Login-LAT-Node", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 36, "Login-LAT-Group", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 37, "Framed-AppleTalk-Link", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 38, "Framed-AppleTalk-Network", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 39, "Framed-AppleTalk-Zone", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 40, "Acct-Status-Type", DIAMETER_ENUMERATED, diameter_acct_status_type_vals},
+ { 41, "Acct-Delay-Time", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 42, "Acct-Input-Octets", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 43, "Acct-Output-Octets", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 44, "Acct-Session-Id", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 45, "Acct-Authentic", DIAMETER_ENUMERATED, diameter_acct_authentic_vals},
+ { 46, "Acct-Session-Time", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 47, "Acct-Input-Packets", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 48, "Acct-Output-Packets", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 49, "Acct-Terminate-Cause", DIAMETER_ENUMERATED, diameter_acct_terminate_cause_vals},
+ { 50, "Acct-Multi-Session-Id", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 51, "Acct-Link-Count", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 52, "Acct-Input-Gigawords", DIAMETER_INTEGER32, (value_string *)NULL},/*[RFC2869]*/
+ { 53, "Acct-Output-Gigawords", DIAMETER_INTEGER32, (value_string *)NULL},/*[RFC2869]*/
+ { 54, "(unassigned)", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 55, "Event-Timestamp", DIAMETER_TIME, (value_string *)NULL},/*[RFC2869]*/
+ /*
+ * 56-59 (unassigned)
+ *
+ */
+ { 60, "CHAP-Challenge", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 61, "NAS-Port-Type", DIAMETER_ENUMERATED, diameter_nas_port_type_vals},
+ { 62, "Port-Limit", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 63, "Login-LAT-Port", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 64, "Tunnel-Type", DIAMETER_ENUMERATED, diameter_tunnel_type_vals},
+ { 65, "Tunnel-Medium-Type", DIAMETER_ENUMERATED, diameter_tunnel_medium_type_vals},
+ { 66, "Tunnel-Client-Endpoint", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 67, "Tunnel-Server-Endpoint", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 68, "Tunnel-Connection-ID", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 69, "Tunnel-Password", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 70, "ARAP-Password", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 71, "ARAP-Features", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 72, "ARAP-Zone-Access", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 73, "ARAP-Security", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 74, "ARAP-Security-Data", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 75, "Password-Retry", DIAMETER_INTEGER32, (value_string *)NULL},/*[RFC2869]*/
+ { 76, "Prompt", DIAMETER_ENUMERATED, (value_string *)NULL},/*[RFC2869]*/
+ { 77, "Connect-Info", DIAMETER_UTF8STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 78, "Configuration-Token", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 79, "EAP-Message", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 80, "Message-Authenticator", DIAMETER_INTEGER64, (value_string *)NULL},/*[RFC2869]*/
+ { 81, "Tunnel-Private-Group-ID", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2868]*/
+ { 82, "Tunnel-Assignment-Id", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 83, "Tunnel-Preference", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2868]*/
+ { 84, "ARAP-Challenge-Response", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 85, "Acct-Interim-Interval", DIAMETER_INTEGER32, (value_string *)NULL},/*[RFC2869]*/
+ { 86, "Acct-Tunnel-Packets-Lost", DIAMETER_INTEGER32, (value_string *)NULL},/*[RFC2867]*/
+ { 87, "NAS-Port-Id", DIAMETER_UTF8STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 88, "Framed-Pool", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2869]*/
+ { 89, "(unassigned)", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 90, "Tunnel-Client-Auth-ID", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2868]*/
+ { 91, "Tunnel-Server-Auth-ID", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC2868]*/
+ /*
+ * 92-93 (Unassigned)
+ */
+ { 94, "Originating-Line-Info", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[Trifunovic]*/
+ { 95, "NAS-IPv6-Address", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC3162]*/
+ { 96, "Framed-Interface-Id", DIAMETER_INTEGER64, (value_string *)NULL},/*[RFC3162]*/
+ { 97, "Framed-IPv6-Prefix", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC3162]*/
+ { 98, "Login-IPv6-Host", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC3162]*/
+ { 99, "Framed-IPv6-Route", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC3162]*/
+ { 100, "Framed-IPv6-Pool", DIAMETER_OCTET_STRING, (value_string *)NULL},/*[RFC3162]*/
+ { 101, "Error-Cause Attribute", DIAMETER_ENUMERATED, diameter_error_cause_attribute_vals},/*[RFC3576]*/
+/*
+ 192-223 Experimental Use [RFC2058]
+ 224-240 Implementation Specific [RFC2058]
+ 241-255 Reserved [RFC2058]
+*/
+ /* Diameter AVPs */
+ { 482, "Accounting-Interim-Interval", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 483, "Accounting-Realtime-Required",DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 485, "Accounting-Record-Number", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 480, "Accounting-Record-Type", DIAMETER_ENUMERATED, diameter_accounting_record_type_vals},
+ { 287, "Accounting-Sub-Session-Id", DIAMETER_UNSIGNED64, (value_string *)NULL},
+ { 259, "Acct-Application-Id", DIAMETER_UNSIGNED32, diameter_application_id_vals},
+ { 275, "Alternate-Peer", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 258, "Auth-Application-Id", DIAMETER_UNSIGNED32, diameter_application_id_vals},
+ { 274, "Auth-Request-Type", DIAMETER_ENUMERATED, diameter_auth_request_type_vals},
+ { 291, "Authorization-Lifetime", DIAMETER_INTEGER32, (value_string *)NULL},
+ { 276, "Auth-Grace-Period", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 277, "Auth-Session-State", DIAMETER_ENUMERATED, diameter_auth_session_state_vals},
+ { 285, "Re-Auth-Request-Type", DIAMETER_ENUMERATED, diameter_re_auth_request_type_vals},
+ { 293, "Destination-Host", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 283, "Desintation-Realm", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { 273, "Disconnect-Cause", DIAMETER_ENUMERATED, diameter_disconnect_cause_vals},
+ { 281, "Error-Message", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { 294, "Error-Reporting-Host", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 279, "Failed-AVP", DIAMETER_OCTET_STRING,(value_string *)NULL},
+ { 267, "Firmware-Revision", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 257, "Host-IP-Address", DIAMETER_IP_ADDRESS, (value_string *)NULL},
+ { 272, "Multi-Round-Time-Out", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 264, "Origin-Host", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 296, "Origin-Realm", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { 278, "Origin-State-Id", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 269, "Product-Name", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { 280, "Proxy-Host", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 284, "Proxy-Info", DIAMETER_GROUPED, (value_string *)NULL},
+ { 292, "Redirect-Host", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 261, "Redirect-Host-Usage", DIAMETER_ENUMERATED, diameter_redirect_host_usage_vals},
+ { 262, "Redirect-Max-Cache-Time", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 268, "Result-Code", DIAMETER_ENUMERATED, diameter_result_code_vals},
+ { 282, "Route-Record", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 263, "Session-Id", DIAMETER_SESSION_ID, (value_string *)NULL},
+ { 270, "Session-Binding", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 271, "Session-Server-Failover", DIAMETER_ENUMERATED, diameter_session_server_failover_vals},
+ { 286, "Source-Route", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 265, "Supported-Vendor-Id", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 295, "Termination-Cause", DIAMETER_ENUMERATED, diameter_termination_cause_vals},
+ { 266, "Vendor-Id", DIAMETER_ENUMERATED, diameter_vendor_specific_vendors},
+ { 260, "Vendor-Specific-Application-Id", DIAMETER_GROUPED, (value_string *)NULL},
+/* Diameter Mobile IP AVPs */
+ { 318, "MIP-FA-to-HA-SPI", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 319, "MIP-FA-to-MN-SPI", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 320, "MIP-Reg-Request", DIAMETER_MIP_REG_REQ, (value_string *)NULL},
+ { 321, "MIP-Reg-Reply", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 322, "MIP-MN-AAA-Auth", DIAMETER_GROUPED, (value_string *)NULL},
+ { 325, "MIP-MN-to-FA-KEY", DIAMETER_GROUPED, (value_string *)NULL},
+ { 326, "MIP-FA-to-MN-KEY", DIAMETER_GROUPED, (value_string *)NULL},
+ { 328, "MIP-FA-to-HA-KEY", DIAMETER_GROUPED, (value_string *)NULL},
+ { 329, "MIP-HA-to-FA-KEY", DIAMETER_GROUPED, (value_string *)NULL},
+ { 330, "MIP-Foreign-Agent-Host", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 331, "MIP-MN-to-HA-KEY", DIAMETER_GROUPED, (value_string *)NULL},
+ { 333, "MIP-Mobile-Node-Address", DIAMETER_IP_ADDRESS, (value_string *)NULL},
+ { 334, "MIP-Home-Agent-Address", DIAMETER_IP_ADDRESS, (value_string *)NULL},
+ { 335, "MIP-Key-Material", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 336, "MIP-Candidate-Home-Agent-Host", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 337, "MIP-Feature-Vector", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 338, "MIP-Auth-Input-Data-Length", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 339, "MIP-Authenticator-Length", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 340, "MIP-Authenticator-Offset", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 341, "MIP-MN-AAA-SPI", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 342, "MIP-PEER-SPI", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { 343, "MIP-Session-Key", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 344, "MIP-FA-Challenge", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 345, "MIP-Algorithm-Type", DIAMETER_ENUMERATED, diameter_mip_algorithm_type},
+ { 346, "MIP-Algorithm-Type", DIAMETER_ENUMERATED, diameter_mip_replay_type},
+ { 347, "MIP-Filter-Rule", DIAMETER_IP_FILTER_RULE, (value_string *)NULL},
+ { 348, "MIP-Home-Agent-Host", DIAMETER_IDENTITY, (value_string *)NULL},
+ { 398, "MIP-Key-Lifetime", DIAMETER_UNSIGNED32, (value_string *)NULL},
+/* http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-cc-03.txt */
+ { 411, "CC-Correlation-Id", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 412, "CC-Input-Octets", DIAMETER_UNSIGNED64 , (value_string *)NULL},
+ { 413, "CC-Money", DIAMETER_GROUPED , (value_string *)NULL},
+ { 414, "CC-Output-Octets", DIAMETER_UNSIGNED64 , (value_string *)NULL},
+ { 415, "CC-Request-Number", DIAMETER_UNSIGNED32 , (value_string *)NULL},
+ { 416, "CC-Request-Type", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 417, "CC-Service-Specific-Units", DIAMETER_UNSIGNED64 , (value_string *)NULL},
+ { 418, "CC-Session-Failover", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 419, "CC-Sub-Session-Id", DIAMETER_UNSIGNED64 , (value_string *)NULL},
+ { 420, "CC-Time", DIAMETER_UNSIGNED32 , (value_string *)NULL},
+ { 421, "CC-Total-Octets", DIAMETER_UNSIGNED64 , (value_string *)NULL},
+ { 454, "CC-Unit-Type", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 422, "Check-Balance-Result", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 423, "Cost-Information", DIAMETER_GROUPED , (value_string *)NULL},
+ { 424, "Cost-Unit", DIAMETER_UTF8STRING , (value_string *)NULL},
+ { 426, "Credit-Control", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 427, "Credit-Control-Failure-Handling", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 425, "Currency-Code", DIAMETER_UNSIGNED32 , (value_string *)NULL},
+ { 428, "Direct-Debiting-Failure-Handling", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 429, "Exponent", DIAMETER_INTEGER32 , (value_string *)NULL},
+ { 449, "Final-Unit-Action", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 430, "Final-Unit-Indication", DIAMETER_GROUPED , (value_string *)NULL},
+ { 431, "Granted-Service-Unit", DIAMETER_GROUPED , (value_string *)NULL},
+ { 453, "G-S-U-Pool-Identifier", DIAMETER_UNSIGNED32 , (value_string *)NULL},
+ { 457, "G-S-U-Pool-Reference", DIAMETER_GROUPED , (value_string *)NULL},
+ { 456, "Multiple-Services-Credit-Control", DIAMETER_GROUPED , (value_string *)NULL},
+ { 455, "Multiple-Services-Indicator", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 432, "Rating-Group", DIAMETER_UNSIGNED32 , (value_string *)NULL},
+ { 433, "Redirect-Address-Type", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 434, "Redirect-Server", DIAMETER_GROUPED , (value_string *)NULL},
+ { 435, "Redirect-Server-Address", DIAMETER_UTF8STRING , (value_string *)NULL},
+ { 436, "Requested-Action", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 437, "Requested-Service-Unit", DIAMETER_GROUPED , (value_string *)NULL},
+ { 438, "Restriction-Filter-Rule", DIAMETER_IP_FILTER_RULE, (value_string *)NULL},
+ { 439, "Service-Identifier", DIAMETER_UTF8STRING , (value_string *)NULL},
+ { 440, "Service-Parameter-Info", DIAMETER_GROUPED , (value_string *)NULL},
+ { 441, "Service-Parameter-Type", DIAMETER_UNSIGNED32 , (value_string *)NULL},
+ { 442, "Service-Parameter-Value", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { 443, "Subscription-Id", DIAMETER_GROUPED , (value_string *)NULL},
+ { 444, "Subscription-Id-Data", DIAMETER_UTF8STRING , (value_string *)NULL},
+ { 450, "Subscription-Id-Type", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 452, "Tariff-Change-Usage", DIAMETER_ENUMERATED , (value_string *)NULL},
+ { 451, "Tariff-Time-Change", DIAMETER_TIME, (value_string *)NULL},
+ { 445, "Unit-Value", DIAMETER_GROUPED , (value_string *)NULL},
+ { 446, "Used-Service-Unit", DIAMETER_GROUPED , (value_string *)NULL},
+ { 447, "Value-Digits", DIAMETER_INTEGER64 , (value_string *)NULL},
+ { 448, "Validity-Time", DIAMETER_UNSIGNED32 , (value_string *)NULL},
+
+
+/* draft-ietf-aaa-diameter-sip-app-01.txt AVP codes to be allocated
+ { xx01, "SIP-Visited-Network-Id", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { xx02, "SIP-AOR", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { xx03, "SIP-Server-URI", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { xx04, "SIP-Server-Capabilities", DIAMETER_GROUPED, (value_string *)NULL},
+ { xx05, "SIP-Mandatory-Capability", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { xx06, "SIP-Optional-Capability", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { xx07, "SIP-User-Data", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { xx08, "SIP-Number-Auth-Items", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { xx09, "SIP-Auth-Data-Item", DIAMETER_GROUPED, (value_string *)NULL},
+ { xx10, "SIP-Item-Number", DIAMETER_UNSIGNED32, (value_string *)NULL},
+ { xx11, "SIP-Authentication-Scheme", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { xx12, "SIP-Authenticate", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { xx13, "SIP-Authorization", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { xx14, "SIP-Authentication-Info", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { xx15, "SIP-Authentication-Context", DIAMETER_GROUPED, (value_string *)NULL},
+ { xx16, "SIP-Confidentiality-Key", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { xx17, "SIP-Integrity-Key", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ { xx18, "SIP-Server-Assignment-Type", DIAMETER_ENUMERATED, SIP_server_assignment_type},
+ { xx19, "SIP-Deregistration-Reason", DIAMETER_GROUPED, (value_string *)NULL},
+ { xx20, "SIP-Reason-Code", DIAMETER_ENUMERATED, SIP_reason_code_vals},
+ { xx21, "SIP-Reason-Info", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { xx22, "SIP-Accouting-Information", DIAMETER_GROUPED, (value_string *)NULL},
+ { xx23, "SIP-Accounting-Server-URI", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { xx24, "SIP-Credit-Control-Server-URI", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { xx25, "SIP-User-Authorization-Type", DIAMETER_ENUMERATED, SIP_user_authorization_type},
+ { xx26, "SIP-User-Data-Request-Type", DIAMETER_ENUMERATED, SIP_user_data_request_type},
+ { xx27, "SIP-User-Data-Already-Available", DIAMETER_ENUMERATED, SIP_user_data_already_available_vals},
+ { xx28, "SIP-Method", DIAMETER_UTF8STRING, (value_string *)NULL},
+ { xx29, "SIP-Entity-Body-Hash", DIAMETER_OCTET_STRING, (value_string *)NULL},
+ */
+ {0, (char *)NULL, 0, (value_string*)NULL}
+};
+
+
+
+static value_string diameter_command_code_vals[] = {
+
+ /* Base Protocol */
+ {257, "Capabilities-Exchange"},
+ {258, "Re-Auth"},
+ {271, "Accounting"},
+ {274, "Abort-Session"},
+ {275, "Session-Termination"},
+ {280, "Device-Watchdog"},
+ {282, "Disconnect-Peer"},
+ {300, "Test-Auth"},
+ /* Mip Protocol */
+ {260, "AA-Mobile-Node"},
+ {262, "Home-Agent-MIP"},
+ /* Nasreq Protocol */
+ {265, "AA"},
+ {268, "Diameter-EAP"},
+ /* Credit-Control Application */
+ {272, "Credit-Control"},
+ /* draft-ietf-aaa-diameter-cms-sec-04 */
+ {304, "Diameter-Security-Association"},
+ {305, "Proxy-Diameter-Security-Association"},
+ /* Session Initiation Protocol (SIP) Application, numbers not yet assigned by IANA
+ {aaa, "User-Authorization"},
+ {bbb, "Server-Assignment"},
+ {ccc, "Location-Info"},
+ {ddd, "Multimedia-Auth"},
+ {eee, "Registration-Termination"},
+ {fff, "Push-Profile"},
+ */
+
+ {0, (char *)NULL}
+};
+
+
+
+
+#endif /* _PACKET_DIAMETER_H */
diff --git a/epan/dissectors/packet-diameter.c b/epan/dissectors/packet-diameter.c
new file mode 100644
index 0000000000..acb9466014
--- /dev/null
+++ b/epan/dissectors/packet-diameter.c
@@ -0,0 +1,1965 @@
+/* packet-diameter.c
+ * Routines for Diameter packet disassembly
+ *
+ * $Id$
+ *
+ * Copyright (c) 2001 by David Frascone <dave@frascone.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * References:
+ * 2004-03-11
+ * http://www.ietf.org/rfc/rfc3588.txt
+ * http://www.iana.org/assignments/radius-types
+ * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-cc-03.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-nasreq-14.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-mobileip-16.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-sip-app-01.txt
+ * http://www.ietf.org/html.charters/aaa-charter.html
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <glib.h>
+#include <epan/filesystem.h>
+#include "xmlstub.h"
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include <epan/report_err.h>
+#include "prefs.h"
+#include "packet-tcp.h"
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+/* This must be defined before we include packet-diameter-defs.h */
+
+/* Valid data types */
+typedef enum {
+ /* Base Types */
+ DIAMETER_OCTET_STRING = 1,
+ DIAMETER_INTEGER32,
+ DIAMETER_INTEGER64,
+ DIAMETER_UNSIGNED32,
+ DIAMETER_UNSIGNED64,
+ DIAMETER_FLOAT32,
+ DIAMETER_FLOAT64,
+ DIAMETER_FLOAT128,
+ DIAMETER_GROUPED,
+
+ /* Derived Types */
+ DIAMETER_IP_ADDRESS, /* OctetString */
+ DIAMETER_TIME, /* Integer 32 */
+ DIAMETER_UTF8STRING, /* OctetString */
+ DIAMETER_IDENTITY, /* OctetString */
+ DIAMETER_ENUMERATED, /* Integer 32 */
+ DIAMETER_IP_FILTER_RULE, /* OctetString */
+ DIAMETER_QOS_FILTER_RULE, /* OctetString */
+ DIAMETER_MIP_REG_REQ, /* OctetString */
+ DIAMETER_VENDOR_ID, /* Integer32 */
+ DIAMETER_APPLICATION_ID,
+ DIAMETER_URI, /* OctetString */
+ DIAMETER_SESSION_ID /* OctetString */
+
+} diameterDataType;
+
+
+static value_string TypeValues[]={
+ { DIAMETER_OCTET_STRING, "OctetString" },
+ { DIAMETER_INTEGER32, "Integer32" },
+ { DIAMETER_INTEGER64, "Integer64" },
+ { DIAMETER_UNSIGNED32, "Unsigned32" },
+ { DIAMETER_UNSIGNED64, "Unsigned64" },
+ { DIAMETER_FLOAT32, "Float32" },
+ { DIAMETER_FLOAT64, "Float64" },
+ { DIAMETER_FLOAT128, "Float128" },
+ { DIAMETER_GROUPED, "Grouped" },
+ { DIAMETER_IP_ADDRESS, "IpAddress" },
+ { DIAMETER_TIME, "Time" },
+ { DIAMETER_UTF8STRING, "UTF8String" },
+ { DIAMETER_IDENTITY, "DiameterIdentity" },
+ { DIAMETER_ENUMERATED, "Enumerated" },
+ { DIAMETER_IP_FILTER_RULE, "IPFilterRule" },
+ { DIAMETER_QOS_FILTER_RULE, "QOSFilterRule" },
+ { DIAMETER_MIP_REG_REQ, "MIPRegistrationRequest"},
+ { DIAMETER_VENDOR_ID, "VendorId"},
+ { DIAMETER_APPLICATION_ID, "AppId"},
+ { DIAMETER_URI, "DiameterURI"},
+ { DIAMETER_SESSION_ID, "Session-Id"},
+
+ {0, (char *)NULL}
+};
+
+typedef struct value_name {
+ guint32 value;
+ gchar *name;
+ struct value_name *next;
+} ValueName;
+
+typedef struct old_avp_info {
+ guint32 code;
+ gchar *name;
+ diameterDataType type;
+ value_string *values;
+} oldAvpInfo;
+
+typedef struct avp_info {
+ guint32 code;
+ gchar *name;
+ gchar *vendorName;
+ diameterDataType type;
+ ValueName *values;
+ struct avp_info *next;
+} avpInfo;
+
+typedef struct command_code {
+ guint32 code;
+ gchar *name;
+ gchar *vendorName;
+ struct command_code *next;
+} CommandCode;
+
+typedef struct vendor_id {
+ guint32 id;
+ gchar *name;
+ gchar *longName;
+ struct vendor_id *next;
+} VendorId;
+
+typedef struct application_id {
+ guint32 id;
+ gchar *name;
+ struct application_id *next;
+} ApplicationId;
+
+static avpInfo *avpListHead=NULL;
+static VendorId *vendorListHead=NULL;
+static CommandCode *commandListHead=NULL;
+static ApplicationId *ApplicationIdHead=NULL;
+
+
+#include "packet-diameter-defs.h"
+
+#define NTP_TIME_DIFF (2208988800UL)
+
+#define TCP_PORT_DIAMETER 1812
+#define SCTP_PORT_DIAMETER 1812
+
+static const true_false_string reserved_set = {
+ "*** Error! Reserved Bit is Set",
+ "Ok"
+};
+
+static int proto_diameter = -1;
+static int hf_diameter_length = -1;
+static int hf_diameter_code = -1;
+static int hf_diameter_hopbyhopid =-1;
+static int hf_diameter_endtoendid =-1;
+static int hf_diameter_version = -1;
+static int hf_diameter_vendor_id = -1;
+static int hf_diameter_flags = -1;
+static int hf_diameter_flags_request = -1;
+static int hf_diameter_flags_proxyable = -1;
+static int hf_diameter_flags_error = -1;
+static int hf_diameter_flags_T = -1;
+static int hf_diameter_flags_reserved4 = -1;
+static int hf_diameter_flags_reserved5 = -1;
+static int hf_diameter_flags_reserved6 = -1;
+static int hf_diameter_flags_reserved7 = -1;
+
+static int hf_diameter_avp_code = -1;
+static int hf_diameter_avp_length = -1;
+static int hf_diameter_avp_flags = -1;
+static int hf_diameter_avp_flags_vendor_specific = -1;
+static int hf_diameter_avp_flags_mandatory = -1;
+static int hf_diameter_avp_flags_protected = -1;
+static int hf_diameter_avp_flags_reserved3 = -1;
+static int hf_diameter_avp_flags_reserved4 = -1;
+static int hf_diameter_avp_flags_reserved5 = -1;
+static int hf_diameter_avp_flags_reserved6 = -1;
+static int hf_diameter_avp_flags_reserved7 = -1;
+static int hf_diameter_avp_vendor_id = -1;
+
+
+static int hf_diameter_avp_data_uint32 = -1;
+static int hf_diameter_avp_data_int32 = -1;
+static int hf_diameter_avp_data_uint64 = -1;
+static int hf_diameter_avp_data_int64 = -1;
+static int hf_diameter_avp_data_bytes = -1;
+static int hf_diameter_avp_data_string = -1;
+static int hf_diameter_avp_data_v4addr = -1;
+static int hf_diameter_avp_data_v6addr = -1;
+static int hf_diameter_avp_data_time = -1;
+static int hf_diameter_avp_session_id = -1;
+static gint ett_diameter = -1;
+static gint ett_diameter_flags = -1;
+static gint ett_diameter_avp = -1;
+static gint ett_diameter_avp_flags = -1;
+static gint ett_diameter_avpinfo = -1;
+
+static guint gbl_diameterTcpPort=TCP_PORT_DIAMETER;
+static guint gbl_diameterSctpPort=SCTP_PORT_DIAMETER;
+
+/* desegmentation of Diameter over TCP */
+static gboolean gbl_diameter_desegment = TRUE;
+
+/* Allow zero as a valid application ID */
+static gboolean allow_zero_as_app_id = FALSE;
+
+/* Supress console output at unknown AVP:s,Flags etc */
+static gboolean suppress_console_output = TRUE;
+
+#define DICT_FN "diameter/dictionary.xml"
+static gchar *gbl_diameterDictionary;
+
+typedef struct _e_diameterhdr {
+ guint32 versionLength;
+ guint32 flagsCmdCode;
+ guint32 vendorId;
+ guint32 hopByHopId;
+ guint32 endToEndId;
+} e_diameterhdr;
+
+typedef struct _e_avphdr {
+ guint32 avp_code;
+ guint32 avp_flagsLength;
+ guint32 avp_vendorId; /* optional */
+} e_avphdr;
+
+/* Diameter Header Flags */
+/* RPrrrrrrCCCCCCCCCCCCCCCCCCCCCCCC */
+#define DIAM_FLAGS_R 0x80
+#define DIAM_FLAGS_P 0x40
+#define DIAM_FLAGS_E 0x20
+#define DIAM_FLAGS_T 0x10
+#define DIAM_FLAGS_RESERVED4 0x08
+#define DIAM_FLAGS_RESERVED5 0x04
+#define DIAM_FLAGS_RESERVED6 0x02
+#define DIAM_FLAGS_RESERVED7 0x01
+#define DIAM_FLAGS_RESERVED 0x0f
+
+#define DIAM_LENGTH_MASK 0x00ffffffl
+#define DIAM_COMMAND_MASK DIAM_LENGTH_MASK
+#define DIAM_GET_FLAGS(dh) ((dh.flagsCmdCode & ~DIAM_COMMAND_MASK) >> 24)
+#define DIAM_GET_VERSION(dh) ((dh.versionLength & (~DIAM_LENGTH_MASK)) >> 24)
+#define DIAM_GET_COMMAND(dh) (dh.flagsCmdCode & DIAM_COMMAND_MASK)
+#define DIAM_GET_LENGTH(dh) (dh.versionLength & DIAM_LENGTH_MASK)
+
+/* Diameter AVP Flags */
+#define AVP_FLAGS_P 0x20
+#define AVP_FLAGS_V 0x80
+#define AVP_FLAGS_M 0x40
+#define AVP_FLAGS_RESERVED3 0x10
+#define AVP_FLAGS_RESERVED4 0x08
+#define AVP_FLAGS_RESERVED5 0x04
+#define AVP_FLAGS_RESERVED6 0x02
+#define AVP_FLAGS_RESERVED7 0x01
+#define AVP_FLAGS_RESERVED 0x1f /* 00011111 -- V M P X X X X X */
+
+#define MIN_AVP_SIZE (sizeof(e_avphdr) - sizeof(guint32))
+#define MIN_DIAMETER_SIZE (sizeof(e_diameterhdr))
+
+static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+
+/*
+ * This routine will do a push-parse of the passed in
+ * filename. This was taken almost verbatum from
+ * the xmlsoft examples.
+ */
+static xmlDocPtr
+xmlParseFilePush( char *filename, int checkValid) {
+ FILE *f;
+ xmlDocPtr doc=NULL;
+ int valid=0;
+ int res, size = 1024;
+ char chars[1024];
+ xmlParserCtxtPtr ctxt;
+
+ /* I wonder what kind of a performance hit this is? */
+ *XmlStub.xmlDoValidityCheckingDefaultValue = checkValid;
+
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ report_open_failure(filename, errno, FALSE);
+ return NULL;
+ }
+
+ res = fread(chars, 1, 4, f);
+ if (res > 0) {
+ ctxt = XmlStub.xmlCreatePushParserCtxt(NULL, NULL,
+ chars, res, filename);
+ while ((res = fread(chars, 1, size-1, f)) > 0) {
+ XmlStub.xmlParseChunk(ctxt, chars, res, 0);
+ }
+ XmlStub.xmlParseChunk(ctxt, chars, 0, 1);
+ doc = ctxt->myDoc;
+ valid=ctxt->valid;
+ XmlStub.xmlFreeParserCtxt(ctxt);
+ }
+ fclose(f);
+
+ /* Check valid */
+ if (!valid) {
+ report_failure( "Error! Invalid xml in %s! Failed DTD check!",
+ filename);
+ return NULL;
+ }
+ return doc;
+} /* xmlParseFilePush */
+
+/*
+ * This routine will add a static avp to the avp list. It is
+ * only called when the XML dictionary fails to load properly.
+ */
+static int
+addStaticAVP(int code, gchar *name, diameterDataType type, value_string *values)
+{
+ avpInfo *entry;
+ ValueName *vEntry=NULL;
+ int i;
+
+ /* Parse our values array, if we have one */
+ if (values) {
+ for (i=0; values[i].strptr != NULL; i++) {
+ ValueName *ve = NULL;
+
+ ve = g_malloc(sizeof(ValueName));
+ ve->name = strdup(values[i].strptr);
+ ve->value = values[i].value;
+ ve->next = vEntry;
+ vEntry = ve;
+ }
+ } /* if values */
+
+ /* And, create the entry */
+ entry = (avpInfo *)g_malloc(sizeof(avpInfo));
+ entry->name = g_strdup(name);
+ entry->code = code;
+ entry->vendorName = NULL;
+ entry->type = type;
+ entry->values = vEntry;
+ if (vEntry)
+ entry->type = DIAMETER_ENUMERATED;
+
+ /* And, add it to the list */
+ entry->next = avpListHead;
+ avpListHead = entry;
+
+ return (0);
+
+} /* addStaticAVP */
+
+/*
+ * This routine will parse an XML avp entry, and add it to our
+ * avp list. If any values are present in the avp, it will
+ * add them too.
+ */
+static int
+xmlParseAVP(xmlNodePtr cur)
+{
+ char *name=NULL, *description=NULL, *code=NULL, *mayEncrypt=NULL,
+ *mandatory=NULL, *protected=NULL, *vendorBit=NULL, *vendorName = NULL,
+ *constrained=NULL;
+ char *type=NULL;
+ avpInfo *entry;
+ guint32 avpType=0;
+ ValueName *vEntry=NULL;
+ int i;
+
+ /* First, get our properties */
+ name = XmlStub.xmlGetProp(cur, "name");
+ description = XmlStub.xmlGetProp(cur, "description");
+ code = XmlStub.xmlGetProp(cur, "code");
+ mayEncrypt = XmlStub.xmlGetProp(cur, "may-encrypt");
+ mandatory = XmlStub.xmlGetProp(cur, "mandatory");
+ protected = XmlStub.xmlGetProp(cur, "protected");
+ vendorBit = XmlStub.xmlGetProp(cur, "vendor-bit");
+ vendorName = XmlStub.xmlGetProp(cur, "vendor-id");
+ constrained = XmlStub.xmlGetProp(cur, "constrained");
+
+ cur = cur->xmlChildrenNode;
+
+ while (cur != NULL ) {
+ if (strcasecmp(cur->name, "type") == 0) {
+ type = XmlStub.xmlGetProp(cur, "type-name");
+ } else if (strcasecmp(cur->name, "enum") == 0) {
+ char *valueName=NULL, *valueCode=NULL;
+ ValueName *ve = NULL;
+ valueName = XmlStub.xmlGetProp(cur, "name");
+ valueCode = XmlStub.xmlGetProp(cur, "code");
+
+ if (!valueName || !valueCode) {
+ report_failure( "Error, bad value on avp %s", name);
+ return (-1);
+ }
+
+ ve = g_malloc(sizeof(ValueName));
+ ve->name = strdup(valueName);
+ ve->value = atol(valueCode);
+
+ ve->next = vEntry;
+ vEntry = ve;
+ } else if (strcasecmp(cur->name, "grouped") == 0) {
+ /* WORK Recurse here for grouped AVPs */
+ type = "grouped";
+ }
+ cur=cur->next;
+ } /* while */
+
+ /*
+ * Check for the AVP Type.
+ */
+ if (type) {
+ for (i = 0; TypeValues[i].strptr; i++) {
+ if (!strcasecmp(type, TypeValues[i].strptr)) {
+ avpType = TypeValues[i].value;
+ break;
+ }
+ }
+
+ if (TypeValues[i].strptr == NULL) {
+ report_failure( "Invalid Type field in dictionary! avp %s (%s)", name, type);
+ return (-1);
+ }
+ } else if (!vEntry) {
+ report_failure("Missing type/enum field in dictionary avpName=%s",
+ name);
+ return (-1);
+ }
+
+ /* WORK - Handle flags -- for validation later */
+
+
+ /* And, create the entry */
+ entry = (avpInfo *)g_malloc(sizeof(avpInfo));
+ entry->name = g_strdup(name);
+ entry->code = atol(code);
+ if (vendorName)
+ entry->vendorName = g_strdup(vendorName);
+ else
+ entry->vendorName = NULL;
+ entry->type = avpType;
+ entry->values = vEntry;
+ if (vEntry)
+ entry->type = DIAMETER_INTEGER32;
+
+ /* And, add it to the list */
+ entry->next = avpListHead;
+ avpListHead = entry;
+
+ return (0);
+} /* xmlParseAVP */
+
+/*
+ * This routine will add a command to the list of commands.
+ */
+static int
+addCommand(int code, char *name, char *vendorId)
+{
+ CommandCode *entry;
+
+ /*
+ * Allocate the memory required for the dictionary.
+ */
+ entry = (CommandCode *) g_malloc(sizeof (CommandCode));
+
+ if (entry == NULL) {
+ report_failure("Unable to allocate memory");
+ return (-1);
+ }
+
+ /*
+ * Allocate memory for the AVPName and copy the name to the
+ * structure
+ */
+ entry->name = g_strdup(name);
+ entry->code = code;
+ if (vendorId)
+ entry->vendorName = g_strdup(vendorId);
+ else
+ entry->vendorName = "None";
+
+ /* Add the entry to the list */
+ entry->next = commandListHead;
+ commandListHead = entry;
+
+ return 0;
+} /* addCommand */
+
+/*
+ * This routine will parse the XML command, and add it to our
+ * list of commands.
+ */
+static int
+xmlParseCommand(xmlNodePtr cur)
+{
+ char *name, *code, *vendorIdString;
+
+ /*
+ * Get the Attributes
+ */
+ name = XmlStub.xmlGetProp(cur, "name");
+ code = XmlStub.xmlGetProp(cur, "code");
+ if (!name || !code) {
+ report_failure("Invalid command. Name or code missing!");
+ return -1;
+ }
+ vendorIdString = XmlStub.xmlGetProp(cur, "vendor-id");
+
+ if (!vendorIdString || !strcasecmp(vendorIdString, "None")) {
+ vendorIdString = NULL;
+ }
+
+ return (addCommand(atoi(code), name, vendorIdString));
+} /* xmlParseCommand */
+
+/* This routine adds an application to the name<-> id table */
+static int
+dictionaryAddApplication(char *name, int id)
+{
+ ApplicationId *entry;
+
+ if (!name || (id < 0) || (id == 0 && !allow_zero_as_app_id)) {
+ report_failure( "Diameter Error: Invalid application (name=%p, id=%d)",
+ name, id);
+ return (-1);
+ } /* Sanity Checks */
+
+ entry = g_malloc(sizeof(ApplicationId));
+ if (!entry) {
+ report_failure( "Unable to allocate memory");
+ return (-1);
+ }
+
+ entry->name = g_strdup(name);
+ entry->id = id;
+
+ /* Add it to the list */
+ entry->next = ApplicationIdHead;
+ ApplicationIdHead = entry;
+
+ return 0;
+} /* dictionaryAddApplication */
+
+/*
+ * This routine will add a vendor to the vendors list
+ */
+static int
+addVendor(int id, gchar *name, gchar *longName)
+{
+ VendorId *vendor;
+
+ /* add entry */
+ vendor=g_malloc(sizeof(VendorId));
+ if (!vendor) {
+ return (-1);
+ }
+
+ vendor->id = id;
+ vendor->name = g_strdup(name);
+ vendor->longName = g_strdup(longName);
+ vendor->next = vendorListHead;
+ vendorListHead = vendor;
+
+ return 0;
+} /* addVendor */
+
+/*
+ * This routine will pars in a XML vendor entry.
+ */
+static int
+xmlParseVendor(xmlNodePtr cur)
+{
+ char *name=NULL, *code=NULL, *id=NULL;
+
+ /* First, get our properties */
+ id = XmlStub.xmlGetProp(cur, "vendor-id");
+ name = XmlStub.xmlGetProp(cur, "name");
+ code = XmlStub.xmlGetProp(cur, "code");
+
+ if (!id || !name || !code) {
+ report_failure( "Invalid vendor section. vendor-id, name, and code must be specified");
+ return -1;
+ }
+
+ return (addVendor(atoi(code), id, name));
+} /* addVendor */
+
+/*
+ * This routine will either parse in the base protocol, or an application.
+ */
+static int
+xmlDictionaryParseSegment(xmlNodePtr cur, int base)
+{
+ if (!base) {
+ char *name;
+ char *id;
+
+ /* Add our application */
+ id = XmlStub.xmlGetProp(cur, "id");
+ name = XmlStub.xmlGetProp(cur, "name");
+
+ if (!name || !id) {
+ /* ERROR!!! */
+ report_failure("Diameter: Invalid application!: name=\"%s\", id=\"%s\"",
+ name?name:"NULL", id?id:"NULL");
+ return -1;
+ }
+
+ /* Add the application */
+ if (dictionaryAddApplication(name, atol(id)) != 0) {
+ /* ERROR! */
+ return -1;
+ }
+ }
+
+
+ /*
+ * Get segment values
+ */
+ cur = cur->xmlChildrenNode;
+ while (cur != NULL) {
+ if (strcasecmp(cur->name, "avp") == 0) {
+ /* we have an avp!!! */
+ xmlParseAVP(cur);
+ } else if (strcasecmp(cur->name, "vendor") == 0) {
+ /* we have a vendor */
+ xmlParseVendor(cur);
+ /* For now, ignore typedefn and text */
+ } else if (strcasecmp(cur->name, "command") == 0) {
+ /* Found a command */
+ xmlParseCommand(cur);
+ } else if (strcasecmp(cur->name, "text") == 0) {
+ } else if (strcasecmp(cur->name, "comment") == 0) {
+ } else if (strcasecmp(cur->name, "typedefn") == 0) {
+ /* WORK -- parse in valid types . . . */
+ } else {
+ /* IF we got here, we're an error */
+ report_failure("Error! expecting an avp or a typedefn (got \"%s\")",
+ cur->name);
+ return (-1);
+ }
+ cur = cur->next;
+ } /* while */
+ return 0;
+} /* xmlDictionaryParseSegment */
+
+/*
+ * The main xml parse routine. This will walk through an XML
+ * dictionary that has been parsed by libxml.
+ */
+static int
+xmlDictionaryParse(xmlNodePtr cur)
+{
+ /* We should expect a base protocol, followed by multiple applications */
+ while (cur != NULL) {
+ if (strcasecmp(cur->name, "base") == 0) {
+ /* Base protocol. Descend and parse */
+ xmlDictionaryParseSegment(cur, 1);
+ } else if (strcasecmp(cur->name, "application") == 0) {
+ /* Application. Descend and parse */
+ xmlDictionaryParseSegment(cur, 0);
+ } else if (strcasecmp(cur->name, "text") == 0) {
+ /* Ignore text */
+ } else if (strcasecmp(cur->name, "comment") == 0) {
+ /* Ignore text */
+ } else {
+ report_failure( "Diameter: XML Expecting a base or an application (got \"%s\")",
+ cur->name);
+ return (-1);
+ }
+ cur = cur->next;
+ }
+
+ return 0;
+
+} /* xmlDictionaryParse */
+
+/*
+ * This routine will call libxml to parse in the dictionary.
+ */
+static int
+loadXMLDictionary(void)
+{
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+
+ /*
+ * build an XML tree from a the file;
+ */
+ XmlStub.xmlKeepBlanksDefault(0); /* Strip leading and trailing blanks */
+ XmlStub.xmlSubstituteEntitiesDefault(1); /* Substitute entities automagically */
+ doc = xmlParseFilePush(gbl_diameterDictionary, 1); /* Parse the XML (do validity checks)*/
+
+ /* Check for invalid xml */
+ if (doc == NULL) {
+ report_failure("Diameter: Unable to parse xmldictionary %s",
+ gbl_diameterDictionary);
+ return -1;
+ }
+
+ /*
+ * Check the document is of the right kind
+ */
+ cur = XmlStub.xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ report_failure("Diameter: Error: \"%s\": empty document",
+ gbl_diameterDictionary);
+ XmlStub.xmlFreeDoc(doc);
+ return -1;
+ }
+ if (XmlStub.xmlStrcmp(cur->name, (const xmlChar *) "dictionary")) {
+ report_failure("Diameter: Error: \"%s\": document of the wrong type, root node != dictionary",
+ gbl_diameterDictionary);
+ XmlStub.xmlFreeDoc(doc);
+ return -1;
+ }
+
+ /*
+ * Ok, the dictionary has been parsed by libxml, and is valid.
+ * All we have to do now is read in our information.
+ */
+ if (xmlDictionaryParse(cur->xmlChildrenNode) != 0) {
+ /* Error has already been printed */
+ return -1;
+ }
+
+ /* Once we're done parsing, free up the xml memory */
+ XmlStub.xmlFreeDoc(doc);
+
+ return 0;
+
+} /* loadXMLDictionary */
+
+/*
+ * Fallback routine. In the event of ANY error when loading the XML
+ * dictionary, this routine will populate the new avp list structures
+ * with the old static data from packet-diameter-defs.h
+ */
+static void
+initializeDictionaryDefaults(void)
+{
+ int i;
+
+ /* Add static vendors to list */
+ for(i=0; diameter_vendor_specific_vendors[i].strptr; i++) {
+ addVendor(diameter_vendor_specific_vendors[i].value,
+ diameter_vendor_specific_vendors[i].strptr,
+ diameter_vendor_specific_vendors[i].strptr);
+ }
+ /* Add static commands to list. */
+ for(i=0; diameter_command_code_vals[i].strptr; i++) {
+ addCommand(diameter_command_code_vals[i].value,
+ diameter_command_code_vals[i].strptr, NULL);
+ }
+
+ /* Add static AVPs to list */
+ for (i=0; old_diameter_avps[i].name; i++) {
+ addStaticAVP(old_diameter_avps[i].code,
+ old_diameter_avps[i].name,
+ old_diameter_avps[i].type,
+ old_diameter_avps[i].values);
+ }
+
+} /* initializeDictionaryDefaults */
+
+/*
+ * This routine will attempt to load the XML dictionary, and on
+ * failure, will call initializeDictionaryDefaults to load in
+ * our static dictionary.
+ */
+static void
+initializeDictionary(void)
+{
+ /*
+ * Using ugly ordering here. If loadLibXML succeeds, then
+ * loadXMLDictionary will be called. This is one of the few times when
+ * I think this is prettier than the nested if alternative.
+ */
+ if (loadLibXML() ||
+ (loadXMLDictionary() != 0)) {
+ /* Something failed. Use the static dictionary */
+ report_failure("Diameter: Using static dictionary! (Unable to use XML)");
+ initializeDictionaryDefaults();
+ }
+} /* initializeDictionary */
+
+
+
+/*
+ * These routines manipulate the diameter structures.
+ */
+
+/* return vendor string, based on the id */
+static gchar *
+diameter_vendor_to_str(guint32 vendorId, gboolean longName) {
+ VendorId *probe;
+ static gchar buffer[64];
+
+ for (probe=vendorListHead; probe; probe=probe->next) {
+ if (vendorId == probe->id) {
+ if (longName)
+ return probe->longName;
+ else
+ return probe->name;
+ }
+ }
+
+ snprintf(buffer, sizeof(buffer),
+ "Vendor 0x%08x", vendorId);
+ return buffer;
+} /*diameter_vendor_to_str */
+
+/* return command string, based on the code */
+static gchar *
+diameter_command_to_str(guint32 commandCode, guint32 vendorId)
+{
+ CommandCode *probe;
+ static gchar buffer[64];
+ gchar *vendorName=NULL;
+
+ if (vendorId)
+ vendorName = diameter_vendor_to_str(vendorId, FALSE);
+
+ for (probe=commandListHead; probe; probe=probe->next) {
+ if (commandCode == probe->code) {
+ if (vendorId) {
+/* g_warning("Command: Comparing \"%s\" to \"%s\"", */
+/* vendorName?vendorName:"(null)", */
+/* probe->vendorName?probe->vendorName:"(null)"); */
+ /* Now check the vendor name */
+ if (!strcmp(vendorName, probe->vendorName))
+ /* We found it */
+ return probe->name;
+ } else {
+ /* With no vendor id, the Command's entry should be "None" */
+ if (!strcmp(probe->vendorName, "None")) {
+ /* We found it */
+ return probe->name;
+ }
+ }
+ }
+ }
+
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: Unable to find name for command code 0x%08x, Vendor \"%u\"!",
+ commandCode, vendorId);
+ snprintf(buffer, sizeof(buffer),
+ "Cmd-0x%08x", commandCode);
+
+ return buffer;
+}/*diameter_command_to_str */
+
+/* return application string, based on the id */
+static gchar *
+diameter_app_to_str(guint32 vendorId) {
+ ApplicationId *probe;
+ static gchar buffer[64];
+
+ for (probe=ApplicationIdHead; probe; probe=probe->next) {
+ if (vendorId == probe->id) {
+ return probe->name;
+ }
+ }
+
+ snprintf(buffer, sizeof(buffer),
+ "AppId 0x%08x", vendorId);
+ return buffer;
+} /*diameter_app_to_str */
+
+/* return an avp type, based on the code */
+static diameterDataType
+diameter_avp_get_type(guint32 avpCode, guint32 vendorId){
+ avpInfo *probe;
+ gchar *vendorName=NULL;
+
+ if (vendorId)
+ vendorName = diameter_vendor_to_str(vendorId, FALSE);
+
+ for (probe=avpListHead; probe; probe=probe->next) {
+ if (avpCode == probe->code) {
+
+ if (vendorId) {
+/* g_warning("AvpType: Comparing \"%s\" to \"%s\"", */
+/* vendorName?vendorName:"(null)", */
+/* probe->vendorName?probe->vendorName:"(null)"); */
+ /* Now check the vendor name */
+ if (probe->vendorName && (!strcmp(vendorName, probe->vendorName)))
+ /* We found it! */
+ return probe->type;
+ } else {
+ /* No Vendor ID -- vendorName should be null */
+ if (!probe->vendorName)
+ /* We found it! */
+ return probe->type;
+ }
+ }
+ }
+
+ /* If we don't find it, assume it's data */
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: Unable to find type for avpCode %u, Vendor %u!", avpCode,
+ vendorId);
+ return DIAMETER_OCTET_STRING;
+} /* diameter_avp_get_type */
+
+/* return an avp name from the code */
+static gchar *
+diameter_avp_get_name(guint32 avpCode, guint32 vendorId)
+{
+ static gchar buffer[64];
+ avpInfo *probe;
+ gchar *vendorName=NULL;
+
+ if (vendorId)
+ vendorName = diameter_vendor_to_str(vendorId, FALSE);
+
+ for (probe=avpListHead; probe; probe=probe->next) {
+ if (avpCode == probe->code) {
+ if (vendorId) {
+/* g_warning("AvpName: Comparing \"%s\" to \"%s\"", */
+/* vendorName?vendorName:"(null)", */
+/* probe->vendorName?probe->vendorName:"(null)"); */
+ /* Now check the vendor name */
+ if (probe->vendorName && (!strcmp(vendorName, probe->vendorName)))
+ /* We found it! */
+ return probe->name;
+ } else {
+ /* No Vendor ID -- vendorName should be null */
+ if (!probe->vendorName)
+ /* We found it! */
+ return probe->name;
+ }
+ }
+ }
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: Unable to find name for AVP 0x%08x, Vendor %u!",
+ avpCode, vendorId);
+
+ /* If we don't find it, build a name string */
+ sprintf(buffer, "Unknown AVP:0x%08x", avpCode);
+ return buffer;
+} /* diameter_avp_get_name */
+static gchar *
+diameter_avp_get_value(guint32 avpCode, guint32 vendorId, guint32 avpValue)
+{
+ avpInfo *probe;
+ gchar *vendorName=NULL;
+
+ if (vendorId)
+ vendorName = diameter_vendor_to_str(vendorId, FALSE);
+
+ for (probe=avpListHead; probe; probe=probe->next) {
+ if (avpCode == probe->code) {
+ if (vendorId) {
+/* g_warning("AvpValue: Comparing \"%s\" to \"%s\"", */
+/* vendorName?vendorName:"(null)", */
+/* probe->vendorName?probe->vendorName:"(null)"); */
+ /* Now check the vendor name */
+ if (probe->vendorName && (!strcmp(vendorName, probe->vendorName))) {
+ ValueName *vprobe;
+ for(vprobe=probe->values; vprobe; vprobe=vprobe->next) {
+ if (avpValue == vprobe->value) {
+ return vprobe->name;
+ }
+ }
+ return "(Unknown value)";
+ }
+ } else {
+ if (!probe->vendorName) {
+ ValueName *vprobe;
+ for(vprobe=probe->values; vprobe; vprobe=vprobe->next) {
+ if (avpValue == vprobe->value) {
+ return vprobe->name;
+ }
+ }
+ return "(Unknown value)";
+ }
+ }
+ }
+ }
+ /* We didn't find the avp */
+ return "(Unknown AVP)";
+} /* diameter_avp_get_value */
+
+
+/* Code to actually dissect the packets */
+
+static gboolean
+check_diameter(tvbuff_t *tvb)
+{
+ if (!tvb_bytes_exist(tvb, 0, 1))
+ return FALSE; /* not enough bytes to check the version */
+ if (tvb_get_guint8(tvb, 0) != 1)
+ return FALSE; /* not version 1 */
+
+ /* XXX - fetch length and make sure it's at least MIN_DIAMETER_SIZE?
+ Fetch flags and check that none of the DIAM_FLAGS_RESERVED bits
+ are set? */
+ return TRUE;
+}
+
+/*
+ * Main dissector
+ */
+static void
+dissect_diameter_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_item *tf;
+ proto_tree *flags_tree;
+ tvbuff_t *avp_tvb;
+ proto_tree *diameter_tree;
+ e_diameterhdr dh;
+ int offset=0;
+ size_t avplength;
+ proto_tree *avp_tree;
+ proto_item *avptf;
+ int BadPacket = FALSE;
+ guint32 commandCode, pktLength;
+ guint8 version, flags;
+ gchar flagstr[64] = "<None>";
+ gchar *fstr[] = {"RSVD7", "RSVD6", "RSVD5", "RSVD4", "RSVD3", "Error", "Proxyable", "Request" };
+ gchar commandString[64], vendorName[64];
+ gint i;
+ guint bpos;
+ static int initialized=FALSE;
+
+ /*
+ * Only parse in dictionary if there are diameter packets to
+ * dissect.
+ */
+ if (!initialized) {
+ /* Read in our dictionary, if it exists. */
+ initializeDictionary();
+ initialized=TRUE;
+ }
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Diameter");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* Copy our header */
+ tvb_memcpy(tvb, (guint8*) &dh, offset, sizeof(dh));
+
+ /* Fix byte ordering in our static structure */
+ dh.versionLength = g_ntohl(dh.versionLength);
+ dh.flagsCmdCode = g_ntohl(dh.flagsCmdCode);
+ dh.vendorId = g_ntohl(dh.vendorId);
+ dh.hopByHopId = g_ntohl(dh.hopByHopId);
+ dh.endToEndId = g_ntohl(dh.endToEndId);
+
+ if (dh.vendorId) {
+ strcpy(vendorName,
+ diameter_vendor_to_str(dh.vendorId, TRUE));
+ } else {
+ strcpy(vendorName, "None");
+ }
+
+
+ /* Do the bit twiddling */
+ version = DIAM_GET_VERSION(dh);
+ pktLength = DIAM_GET_LENGTH(dh);
+ flags = DIAM_GET_FLAGS(dh);
+ commandCode = DIAM_GET_COMMAND(dh);
+
+ /* Set up our flags */
+ if (check_col(pinfo->cinfo, COL_INFO) || tree) {
+ flagstr[0]=0;
+ for (i = 0; i < 8; i++) {
+ bpos = 1 << i;
+ if (flags & bpos) {
+ if (flagstr[0]) {
+ strcat(flagstr, ", ");
+ }
+ strcat(flagstr, fstr[i]);
+ }
+ }
+ if (strlen(flagstr) == 0) {
+ strcpy(flagstr,"<None>");
+ }
+ }
+
+ /* Set up our commandString */
+ strcpy(commandString, diameter_command_to_str(commandCode, dh.vendorId));
+ if (flags & DIAM_FLAGS_R)
+ strcat(commandString, "-Request");
+ else
+ strcat(commandString, "-Answer");
+
+ /* Short packet. Should have at LEAST one avp */
+ if (pktLength < MIN_DIAMETER_SIZE) {
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: Packet too short: %u bytes less than min size (%lu bytes))",
+ pktLength, (unsigned long)MIN_DIAMETER_SIZE);
+ BadPacket = TRUE;
+ }
+
+ /* And, check our reserved flags/version */
+ if ((flags & DIAM_FLAGS_RESERVED) ||
+ (version != 1)) {
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: Bad packet: Bad Flags(0x%x) or Version(%u)",
+ flags, version);
+ BadPacket = TRUE;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s%s%s%s%s vendor=%s (hop-id=%u) (end-id=%u) RPE=%d%d%d",
+ (BadPacket)?"***** Bad Packet!: ":"",
+ (flags & DIAM_FLAGS_P)?"Proxyable ":"",
+ (flags & DIAM_FLAGS_E)?" Error":"",
+ ((BadPacket ||
+ (flags & (DIAM_FLAGS_P|DIAM_FLAGS_E))) ?
+ ": " : ""),
+ commandString, vendorName,
+ dh.hopByHopId, dh.endToEndId,
+ (flags & DIAM_FLAGS_R)?1:0,
+ (flags & DIAM_FLAGS_P)?1:0,
+ (flags & DIAM_FLAGS_E)?1:0);
+ }
+
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_diameter, tvb, offset,
+ MAX(pktLength,MIN_DIAMETER_SIZE), FALSE);
+ diameter_tree = proto_item_add_subtree(ti, ett_diameter);
+
+ /* Version */
+ proto_tree_add_uint(diameter_tree,
+ hf_diameter_version,
+ tvb, offset, 1,
+ version);
+
+ offset+=1;
+
+ /* Length */
+ proto_tree_add_uint(diameter_tree,
+ hf_diameter_length, tvb,
+ offset, 3, pktLength);
+ offset += 3;
+
+ /* Flags */
+ tf = proto_tree_add_uint_format(diameter_tree, hf_diameter_flags, tvb,
+ offset , 1, flags, "Flags: 0x%02x (%s)", flags,
+ flagstr);
+ flags_tree = proto_item_add_subtree(tf, ett_diameter_avp_flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_flags_request, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_flags_proxyable, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_flags_error, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_flags_T, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_flags_reserved4, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_flags_reserved5, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_flags_reserved6, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_flags_reserved7, tvb, offset, 1, flags);
+
+ offset += 1;
+
+ /* Command Code */
+ proto_tree_add_uint_format(diameter_tree, hf_diameter_code,
+ tvb, offset, 3, commandCode, "Command Code: %s", commandString);
+ offset += 3;
+
+ /* Vendor Id */
+ proto_tree_add_uint_format(diameter_tree,hf_diameter_vendor_id,
+ tvb, offset, 4, dh.vendorId, "Vendor-Id: %s", vendorName);
+ offset += 4;
+
+ /* Hop-by-hop Identifier */
+ proto_tree_add_uint(diameter_tree, hf_diameter_hopbyhopid,
+ tvb, offset, 4, dh.hopByHopId);
+ offset += 4;
+
+ /* End-to-end Identifier */
+ proto_tree_add_uint(diameter_tree, hf_diameter_endtoendid,
+ tvb, offset, 4, dh.endToEndId);
+ offset += 4;
+
+ /* If we have a bad packet, don't bother trying to parse the AVPs */
+ if (BadPacket) {
+ return;
+ }
+
+ /* Start looking at the AVPS */
+ /* Make the next tvbuff */
+
+ /* Update the lengths */
+ avplength= pktLength - sizeof(e_diameterhdr);
+
+ avp_tvb = tvb_new_subset(tvb, offset, avplength, avplength);
+ avptf = proto_tree_add_text(diameter_tree,
+ tvb, offset, avplength,
+ "Attribute Value Pairs");
+
+ avp_tree = proto_item_add_subtree(avptf,
+ ett_diameter_avp);
+ if (avp_tree != NULL) {
+ dissect_avps( avp_tvb, pinfo, avp_tree);
+ }
+ return;
+ }
+} /* dissect_diameter_common */
+
+
+static guint
+get_diameter_pdu_len(tvbuff_t *tvb, int offset)
+{
+ /* Get the length of the Diameter packet. */
+ return tvb_get_ntoh24(tvb, offset + 1);
+}
+
+static int
+dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (!check_diameter(tvb))
+ return 0;
+ dissect_diameter_common(tvb, pinfo, tree);
+ return tvb_length(tvb);
+}
+
+static int
+dissect_diameter_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (!check_diameter(tvb))
+ return 0;
+ tcp_dissect_pdus(tvb, pinfo, tree, gbl_diameter_desegment, 4,
+ get_diameter_pdu_len, dissect_diameter_common);
+ return tvb_length(tvb);
+} /* dissect_diameter_tcp */
+
+/*
+ * Call the mip_dissector, after saving our pinfo variables
+ * so it doesn't write to our column display.
+ */
+static void
+safe_dissect_mip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ size_t offset, size_t length)
+{
+ static dissector_handle_t mip_handle;
+ static int mipInitialized=FALSE;
+ tvbuff_t *mip_tvb;
+ address save_dl_src;
+ address save_dl_dst;
+ address save_net_src;
+ address save_net_dst;
+ address save_src;
+ address save_dst;
+ gboolean save_in_error_pkt;
+
+ if (!mipInitialized) {
+ mip_handle = find_dissector("mip");
+ mipInitialized=TRUE;
+ }
+
+ mip_tvb = tvb_new_subset(tvb, offset,
+ MIN(length, tvb_length(tvb)-offset),
+ length);
+
+ /* The contained packet is a MIP registration request;
+ dissect it with the MIP dissector. */
+ col_set_writable(pinfo->cinfo, FALSE);
+
+ /* Also, save the current values of the addresses, and restore
+ them when we're finished dissecting the contained packet, so
+ that the address columns in the summary don't reflect the
+ contained packet, but reflect this packet instead. */
+ save_dl_src = pinfo->dl_src;
+ save_dl_dst = pinfo->dl_dst;
+ save_net_src = pinfo->net_src;
+ save_net_dst = pinfo->net_dst;
+ save_src = pinfo->src;
+ save_dst = pinfo->dst;
+ save_in_error_pkt = pinfo->in_error_pkt;
+
+ call_dissector(mip_handle, mip_tvb, pinfo, tree);
+
+ /* Restore the "we're inside an error packet" flag. */
+ pinfo->in_error_pkt = save_in_error_pkt;
+ pinfo->dl_src = save_dl_src;
+ pinfo->dl_dst = save_dl_dst;
+ pinfo->net_src = save_net_src;
+ pinfo->net_dst = save_net_dst;
+ pinfo->src = save_src;
+ pinfo->dst = save_dst;
+
+
+} /* safe_dissect_mip */
+
+/*
+ * This function will dissect the AVPs in a diameter packet. It handles
+ * all normal types, and even recursively calls itself for grouped AVPs
+ */
+static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
+{
+ /* adds the attribute value pairs to the tree */
+ e_avphdr avph;
+ gchar avpTypeString[64];
+ gchar avpNameString[64];
+ gchar *valstr;
+ guint32 vendorId=0;
+ gchar vendorName[64];
+ int hdrLength;
+ int fixAmt;
+ proto_tree *avpi_tree;
+ size_t offset = 0;
+ tvbuff_t *group_tvb;
+ proto_tree *group_tree;
+ proto_item *grouptf;
+ proto_item *avptf;
+ char buffer[1024];
+ int BadPacket = FALSE;
+ guint32 avpLength;
+ guint8 flags;
+ proto_item *tf;
+ proto_tree *flags_tree;
+
+ gint32 packetLength;
+ size_t avpDataLength;
+ int avpType;
+ gchar flagstr[64] = "<None>";
+ gchar *fstr[] = {"RSVD7", "RSVD6", "RSVD5", "RSVD4", "RSVD3", "Protected", "Mandatory", "Vendor-Specific" };
+ gint i;
+ guint bpos;
+
+ packetLength = tvb_length(tvb);
+
+ /* Check for invalid packet lengths */
+ if (packetLength <= 0) {
+ proto_tree_add_text(avp_tree, tvb, offset, tvb_length(tvb),
+ "No Attribute Value Pairs Found");
+ return;
+ }
+
+ /* Spin around until we run out of packet */
+ while (packetLength > 0 ) {
+
+ /* Check for short packet */
+ if (packetLength < (long)MIN_AVP_SIZE) {
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: AVP Payload too short: %d bytes less than min size (%ld bytes))",
+ packetLength, (long)MIN_AVP_SIZE);
+ BadPacket = TRUE;
+ /* Don't even bother trying to parse a short packet. */
+ return;
+ }
+
+ /* Copy our header */
+ tvb_memcpy(tvb, (guint8*) &avph, offset, MIN((long)sizeof(avph),packetLength));
+
+ /* Fix the byte ordering */
+ avph.avp_code = g_ntohl(avph.avp_code);
+ avph.avp_flagsLength = g_ntohl(avph.avp_flagsLength);
+
+ flags = (avph.avp_flagsLength & 0xff000000) >> 24;
+ avpLength = avph.avp_flagsLength & 0x00ffffff;
+
+ /* Set up our flags string */
+ if (check_col(pinfo->cinfo, COL_INFO) || avp_tree) {
+ flagstr[0]=0;
+ for (i = 0; i < 8; i++) {
+ bpos = 1 << i;
+ if (flags & bpos) {
+ if (flagstr[0]) {
+ strcat(flagstr, ", ");
+ }
+ strcat(flagstr, fstr[i]);
+ }
+ }
+ if (strlen(flagstr) == 0) {
+ strcpy(flagstr,"<None>");
+ }
+ }
+
+ /* Dissect our vendor id if it exists and set hdr length */
+ if (flags & AVP_FLAGS_V) {
+ vendorId = g_ntohl(avph.avp_vendorId);
+ /* Vendor id */
+ hdrLength = sizeof(e_avphdr);
+ } else {
+ /* No vendor */
+ hdrLength = sizeof(e_avphdr) -
+ sizeof(guint32);
+ vendorId = 0;
+ }
+
+ if (vendorId) {
+ strcpy(vendorName,
+ diameter_vendor_to_str(vendorId, TRUE));
+ } else {
+ vendorName[0]='\0';
+ }
+
+ /* Check for bad length */
+ if (avpLength < MIN_AVP_SIZE ||
+ ((long)avpLength > packetLength)) {
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: AVP payload size invalid: avp_length: %ld bytes, "
+ "min: %ld bytes, packetLen: %d",
+ (long)avpLength, (long)MIN_AVP_SIZE,
+ packetLength);
+ BadPacket = TRUE;
+ }
+
+ /* Check for bad flags */
+ if (flags & AVP_FLAGS_RESERVED) {
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: Invalid AVP: Reserved bit set. flags = 0x%x,"
+ " resFl=0x%x",
+ flags, AVP_FLAGS_RESERVED);
+ /* For now, don't set bad packet, since I'm accidentally setting a wrong bit
+ BadPacket = TRUE;
+ */
+ }
+
+ /*
+ * Compute amount of byte-alignment fix (Diameter AVPs are sent on 4 byte
+ * boundries)
+ */
+ fixAmt = 4 - (avpLength % 4);
+ if (fixAmt == 4) fixAmt = 0;
+
+ /* shrink our packetLength */
+ packetLength = packetLength - (avpLength + fixAmt);
+
+ /* Check for out of bounds */
+ if (packetLength < 0) {
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: Bad AVP: Bad new length (%d bytes) ",
+ packetLength);
+ BadPacket = TRUE;
+ }
+
+ /* Make avp Name & type */
+ strcpy(avpTypeString, val_to_str(diameter_avp_get_type(avph.avp_code,vendorId),
+ TypeValues,
+ "Unknown-Type: 0x%08x"));
+ strcpy(avpNameString, diameter_avp_get_name(avph.avp_code, vendorId));
+
+ avptf = proto_tree_add_text(avp_tree, tvb,
+ offset, avpLength + fixAmt,
+ "%s (%s) l:0x%x (%d bytes) (%d padded bytes)",
+ avpNameString, avpTypeString, avpLength,
+ avpLength, avpLength+fixAmt);
+ avpi_tree = proto_item_add_subtree(avptf,
+ ett_diameter_avpinfo);
+
+ if (avpi_tree !=NULL) {
+ /* Command Code */
+ proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_code,
+ tvb, offset, 4, avph.avp_code, "AVP Code: %s", avpNameString);
+ offset += 4;
+
+ tf = proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_flags, tvb,
+ offset , 1, flags, "Flags: 0x%02x (%s)", flags,
+ flagstr);
+ flags_tree = proto_item_add_subtree(tf, ett_diameter_avp_flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_vendor_specific, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_mandatory, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_protected, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved3, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved4, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved5, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved6, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved7, tvb, offset, 1, flags);
+ offset += 1;
+
+ proto_tree_add_uint(avpi_tree, hf_diameter_avp_length,
+ tvb, offset, 3, avpLength);
+ offset += 3;
+
+ if (flags & AVP_FLAGS_V) {
+ proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_vendor_id,
+ tvb, offset, 4, vendorId, vendorName);
+ offset += 4;
+ }
+
+ avpDataLength = avpLength - hdrLength;
+
+ /*
+ * If we've got a bad packet, just highlight the data. Don't try
+ * to parse it, and, don't move to next AVP.
+ */
+ if (BadPacket) {
+ offset -= hdrLength;
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, tvb_length(tvb) - offset,
+ tvb_get_ptr(tvb, offset, tvb_length(tvb) - offset),
+ "Bad AVP (Suspect Data Not Dissected)");
+ return;
+ }
+
+ avpType=diameter_avp_get_type(avph.avp_code,vendorId);
+
+ switch(avpType) {
+ case DIAMETER_GROUPED:
+ sprintf(buffer, "%s Grouped AVPs", avpNameString);
+ /* Recursively call ourselves */
+ grouptf = proto_tree_add_text(avpi_tree,
+ tvb, offset, tvb_length(tvb),
+ buffer);
+
+ group_tree = proto_item_add_subtree(grouptf,
+ ett_diameter_avp);
+
+ group_tvb = tvb_new_subset(tvb, offset,
+ MIN(avpDataLength, tvb_length(tvb)-offset), avpDataLength);
+ if (group_tree != NULL) {
+ dissect_avps( group_tvb, pinfo, group_tree);
+ }
+ break;
+
+ case DIAMETER_IDENTITY:
+ {
+ const guint8 *data;
+
+ data = tvb_get_ptr(tvb, offset, avpDataLength);
+ proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
+ tvb, offset, avpDataLength, data,
+ "Identity: %*.*s",
+ (int)avpDataLength,
+ (int)avpDataLength, data);
+ }
+ break;
+ case DIAMETER_UTF8STRING:
+ {
+ const guint8 *data;
+
+ data = tvb_get_ptr(tvb, offset, avpDataLength);
+ proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
+ tvb, offset, avpDataLength, data,
+ "UTF8String: %*.*s",
+ (int)avpDataLength,
+ (int)avpDataLength, data);
+ }
+ break;
+ case DIAMETER_IP_ADDRESS:
+ if (avpDataLength == 4) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v4addr,
+ tvb, offset, avpDataLength, FALSE);
+ } else if (avpDataLength == 16) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v6addr,
+ tvb, offset, avpDataLength, FALSE);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Address Length");
+ }
+ break;
+
+ case DIAMETER_INTEGER32:
+ if (avpDataLength == 4) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int32,
+ tvb, offset, avpDataLength, FALSE);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Integer32 Length");
+ }
+ break;
+
+ case DIAMETER_UNSIGNED32:
+ if (avpDataLength == 4) {
+ guint32 data;
+
+ data = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
+ tvb, offset, avpDataLength, data,
+ "Value: 0x%08x (%u)", data, data);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Unsigned32 Length");
+ }
+ break;
+
+ case DIAMETER_INTEGER64:
+ if (avpDataLength == 8) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int64,
+ tvb, offset, 8, FALSE);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Integer64 Length");
+ }
+ break;
+
+ case DIAMETER_UNSIGNED64:
+ if (avpDataLength == 8) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_uint64,
+ tvb, offset, 8, FALSE);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Unsigned64 Length");
+ }
+ break;
+
+ case DIAMETER_TIME:
+ if (avpDataLength == 4) {
+ nstime_t data;
+ gchar buffer[64];
+ struct tm *ltp;
+
+ data.secs = tvb_get_ntohl(tvb, offset);
+ data.secs -= NTP_TIME_DIFF;
+ data.nsecs = 0;
+
+ ltp = localtime(&data.secs);
+ strftime(buffer, 64,
+ "%a, %d %b %Y %H:%M:%S %z", ltp);
+
+ proto_tree_add_time_format(avpi_tree, hf_diameter_avp_data_time,
+ tvb, offset, avpDataLength, &data,
+ "Time: %s", buffer);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Time Length");
+ }
+ break;
+
+ case DIAMETER_ENUMERATED:
+ if (avpDataLength == 4) {
+ guint32 data;
+
+ data = tvb_get_ntohl(tvb, offset);
+ valstr = diameter_avp_get_value(avph.avp_code, vendorId, data);
+ proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
+ tvb, offset, avpDataLength, data,
+ "Value: 0x%08x (%u): %s", data,
+ data, valstr);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Enumerated Length");
+ }
+ break;
+
+ case DIAMETER_VENDOR_ID:
+ if (avpDataLength == 4) {
+ guint32 data;
+
+ data = tvb_get_ntohl(tvb, offset);
+ valstr = diameter_vendor_to_str(data, TRUE);
+ proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
+ tvb, offset, avpDataLength, data,
+ "Vendor ID: %s (0x%08x)", valstr,
+ data);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Vendor ID Length");
+ }
+ break;
+
+ case DIAMETER_APPLICATION_ID:
+ if (avpDataLength == 4) {
+ guint32 data;
+
+ data = tvb_get_ntohl(tvb, offset);
+ valstr = diameter_app_to_str(data);
+ proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
+ tvb, offset, avpDataLength, data,
+ "Application ID: %s (0x%08x)",
+ valstr, data);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Application ID Length");
+ }
+ break;
+
+ case DIAMETER_MIP_REG_REQ:
+ safe_dissect_mip(tvb, pinfo, avpi_tree, offset, avpDataLength);
+ break;
+
+ case DIAMETER_SESSION_ID:
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_session_id,
+ tvb, offset, avpDataLength, FALSE);
+ break;
+
+ default:
+ case DIAMETER_OCTET_STRING:
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Hex Data Highlighted Below");
+ break;
+
+ } /* switch type */
+ } /* avpi_tree != null */
+ offset += (avpLength - hdrLength);
+ offset += fixAmt; /* fix byte alignment */
+ } /* loop */
+} /* dissect_avps */
+
+
+
+void
+proto_reg_handoff_diameter(void)
+{
+ static int Initialized=FALSE;
+ static int TcpPort=0;
+ static int SctpPort=0;
+ static dissector_handle_t diameter_tcp_handle;
+ static dissector_handle_t diameter_handle;
+
+ if (!Initialized) {
+ diameter_tcp_handle = new_create_dissector_handle(dissect_diameter_tcp,
+ proto_diameter);
+ diameter_handle = new_create_dissector_handle(dissect_diameter,
+ proto_diameter);
+ Initialized=TRUE;
+ } else {
+ dissector_delete("tcp.port", TcpPort, diameter_tcp_handle);
+ dissector_delete("sctp.port", SctpPort, diameter_handle);
+ }
+
+ /* set port for future deletes */
+ TcpPort=gbl_diameterTcpPort;
+ SctpPort=gbl_diameterSctpPort;
+
+ /* g_warning ("Diameter: Adding tcp dissector to port %d",
+ gbl_diameterTcpPort); */
+ dissector_add("tcp.port", gbl_diameterTcpPort, diameter_tcp_handle);
+ dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle);
+}
+
+/* registration with the filtering engine */
+void
+proto_register_diameter(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_diameter_version,
+ { "Version", "diameter.version", FT_UINT8, BASE_HEX, NULL, 0x00,
+ "", HFILL }},
+ { &hf_diameter_length,
+ { "Length","diameter.length", FT_UINT24, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_diameter_flags,
+ { "Flags", "diameter.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_diameter_flags_request,
+ { "Request", "diameter.flags.request", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_R,
+ "", HFILL }},
+ { &hf_diameter_flags_proxyable,
+ { "Proxyable", "diameter.flags.proxyable", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_P,
+ "", HFILL }},
+ { &hf_diameter_flags_error,
+ { "Error","diameter.flags.error", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_E,
+ "", HFILL }},
+ { &hf_diameter_flags_T,
+ { "T(Potentially re-transmitted message)","diameter.flags.T", FT_BOOLEAN, 8, TFS(&flags_set_truth),DIAM_FLAGS_T,
+ "", HFILL }},
+ { &hf_diameter_flags_reserved4,
+ { "Reserved","diameter.flags.reserved4", FT_BOOLEAN, 8, TFS(&reserved_set),
+ DIAM_FLAGS_RESERVED4, "", HFILL }},
+ { &hf_diameter_flags_reserved5,
+ { "Reserved","diameter.flags.reserved5", FT_BOOLEAN, 8, TFS(&reserved_set),
+ DIAM_FLAGS_RESERVED5, "", HFILL }},
+ { &hf_diameter_flags_reserved6,
+ { "Reserved","diameter.flags.reserved6", FT_BOOLEAN, 8, TFS(&reserved_set),
+ DIAM_FLAGS_RESERVED6, "", HFILL }},
+ { &hf_diameter_flags_reserved7,
+ { "Reserved","diameter.flags.reserved7", FT_BOOLEAN, 8, TFS(&reserved_set),
+ DIAM_FLAGS_RESERVED7, "", HFILL }},
+
+ { &hf_diameter_code,
+ { "Command Code","diameter.code", FT_UINT24, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_vendor_id,
+ { "VendorId", "diameter.vendorId", FT_UINT32, BASE_DEC, NULL,
+ 0x0,"", HFILL }},
+ { &hf_diameter_hopbyhopid,
+ { "Hop-by-Hop Identifier", "diameter.hopbyhopid", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_diameter_endtoendid,
+ { "End-to-End Identifier", "diameter.endtoendid", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_diameter_avp_code,
+ { "AVP Code","diameter.avp.code", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_length,
+ { "AVP Length","diameter.avp.length", FT_UINT24, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+
+ { &hf_diameter_avp_flags,
+ { "AVP Flags","diameter.avp.flags", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_flags_vendor_specific,
+ { "Vendor-Specific", "diameter.flags.vendorspecific", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_V,
+ "", HFILL }},
+ { &hf_diameter_avp_flags_mandatory,
+ { "Mandatory", "diameter.flags.mandatory", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_M,
+ "", HFILL }},
+ { &hf_diameter_avp_flags_protected,
+ { "Protected","diameter.avp.flags.protected", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_P,
+ "", HFILL }},
+ { &hf_diameter_avp_flags_reserved3,
+ { "Reserved","diameter.avp.flags.reserved3", FT_BOOLEAN, 8, TFS(&reserved_set),
+ AVP_FLAGS_RESERVED3, "", HFILL }},
+ { &hf_diameter_avp_flags_reserved4,
+ { "Reserved","diameter.avp.flags.reserved4", FT_BOOLEAN, 8, TFS(&reserved_set),
+ AVP_FLAGS_RESERVED4, "", HFILL }},
+ { &hf_diameter_avp_flags_reserved5,
+ { "Reserved","diameter.avp.flags.reserved5", FT_BOOLEAN, 8, TFS(&reserved_set),
+ AVP_FLAGS_RESERVED5, "", HFILL }},
+ { &hf_diameter_avp_flags_reserved6,
+ { "Reserved","diameter.avp.flags.reserved6", FT_BOOLEAN, 8, TFS(&reserved_set),
+ AVP_FLAGS_RESERVED6, "", HFILL }},
+ { &hf_diameter_avp_flags_reserved7,
+ { "Reserved","diameter.avp.flags.reserved7", FT_BOOLEAN, 8, TFS(&reserved_set),
+ AVP_FLAGS_RESERVED7, "", HFILL }},
+ { &hf_diameter_avp_vendor_id,
+ { "AVP Vendor Id","diameter.avp.vendorId", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_data_uint64,
+ { "Value","diameter.avp.data.uint64", FT_UINT64, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_data_int64,
+ { "Value","diameter.avp.data.int64", FT_INT64, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_data_uint32,
+ { "Value","diameter.avp.data.uint32", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_data_int32,
+ { "Value","diameter.avp.data.int32", FT_INT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_data_bytes,
+ { "Value","diameter.avp.data.bytes", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_data_string,
+ { "Value","diameter.avp.data.string", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_data_v4addr,
+ { "IPv4 Address","diameter.avp.data.v4addr", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_data_v6addr,
+ { "IPv6 Address","diameter.avp.data.v6addr", FT_IPv6, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_data_time,
+ { "Time","diameter.avp.data.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_diameter_avp_session_id,
+ { "Session ID","diameter.avp.session_id", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_diameter,
+ &ett_diameter_flags,
+ &ett_diameter_avp,
+ &ett_diameter_avp_flags,
+ &ett_diameter_avpinfo
+ };
+ module_t *diameter_module;
+ gchar *default_diameterDictionary;
+
+ proto_diameter = proto_register_protocol ("Diameter Protocol", "Diameter", "diameter");
+ proto_register_field_array(proto_diameter, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register a configuration option for port */
+ diameter_module = prefs_register_protocol(proto_diameter,
+ proto_reg_handoff_diameter);
+ prefs_register_uint_preference(diameter_module, "tcp.port",
+ "Diameter TCP Port",
+ "Set the TCP port for Diameter messages",
+ 10,
+ &gbl_diameterTcpPort);
+ prefs_register_uint_preference(diameter_module, "sctp.port",
+ "Diameter SCTP Port",
+ "Set the SCTP port for Diameter messages",
+ 10,
+ &gbl_diameterSctpPort);
+ /*
+ * Build our default dictionary filename
+ */
+ default_diameterDictionary = get_datafile_path(DICT_FN);
+
+ /*
+ * Now register the dictionary filename as a preference,
+ * so it can be changed.
+ */
+ gbl_diameterDictionary = default_diameterDictionary;
+ prefs_register_string_preference(diameter_module, "dictionary.name",
+ "Diameter XML Dictionary",
+ "Set the dictionary used for Diameter messages",
+ &gbl_diameterDictionary);
+
+ /*
+ * We don't need the default dictionary, so free it (a copy was made
+ * of it in "gbl_diameterDictionary" by
+ * "prefs_register_string_preference()").
+ */
+ g_free(default_diameterDictionary);
+
+ /* Desegmentation */
+ prefs_register_bool_preference(diameter_module, "desegment",
+ "Desegment all Diameter messages\nspanning multiple TCP segments",
+ "Whether the Diameter dissector should desegment all messages spanning multiple TCP segments",
+ &gbl_diameter_desegment);
+ /* Allow zero as valid application ID */
+ prefs_register_bool_preference(diameter_module, "allow_zero_as_app_id",
+ "Allow 0 as valid application ID",
+ "If set, the value 0 (zero) can be used as a valid "
+ "application ID. This is used in experimental cases.",
+ &allow_zero_as_app_id);
+ /* Register some preferences we no longer support, so we can report
+ them as obsolete rather than just illegal. */
+ /* Supress console output or not */
+ prefs_register_bool_preference(diameter_module, "suppress_console_output",
+ "Suppress console output for unknown AVP:s Flags etc.",
+ "If console output for errors should be suppressed or not",
+ &suppress_console_output);
+ /* Register some preferences we no longer support, so we can report
+ them as obsolete rather than just illegal. */
+ prefs_register_obsolete_preference(diameter_module, "udp.port");
+ prefs_register_obsolete_preference(diameter_module, "command_in_header");
+} /* proto_register_diameter */
diff --git a/epan/dissectors/packet-diffserv-mpls-common.c b/epan/dissectors/packet-diffserv-mpls-common.c
new file mode 100644
index 0000000000..7491854239
--- /dev/null
+++ b/epan/dissectors/packet-diffserv-mpls-common.c
@@ -0,0 +1,114 @@
+/* packet-diffserv-mpls-common.c
+ * Routines for the common part of Diffserv MPLS signaling protocols
+ * Author: Endoh Akira (endoh@netmarks.co.jp)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This module defines routines only for the common part of LDP
+ * and RSVP to support for Diffserv MPLS as described in RFC 3270
+ * and RFC 3140. Protocol specific routines of each signaling
+ * protocol are defined in each dissector.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-diffserv-mpls-common.h"
+
+#define hf_map *hfindexes[0]
+#define hf_exp *hfindexes[1]
+#define hf_phbid *hfindexes[2]
+#define hf_phbid_dscp *hfindexes[3]
+#define hf_phbid_code *hfindexes[4]
+#define hf_phbid_bit14 *hfindexes[5]
+#define hf_phbid_bit15 *hfindexes[6]
+#define ett_map *etts[0]
+#define ett_map_phbid *etts[1]
+
+const value_string phbid_bit14_vals[] = {
+ {0, "Single PHB"},
+ {1, "Set of PHBs"},
+ {0, NULL}
+};
+
+const value_string phbid_bit15_vals[] = {
+ {0, "PHBs defined by standards action"},
+ {1, "PHBs not defined by standards action"},
+ {0, NULL}
+};
+
+void
+dissect_diffserv_mpls_common(tvbuff_t *tvb, proto_tree *tree, int type,
+ int offset, int **hfindexes, gint **etts)
+{
+ proto_item *ti = NULL, *sub_ti;
+ proto_tree *tree2 = NULL, *phbid_subtree;
+ int exp;
+ guint16 phbid;
+
+ switch (type) {
+ case 1: /* E-LSP */
+ ti = proto_tree_add_item(tree, hf_map, tvb, offset, 4, FALSE);
+ tree2 = proto_item_add_subtree(ti, ett_map);
+ proto_item_set_text(ti, "MAP: ");
+ offset ++;
+ exp = tvb_get_guint8(tvb, offset) & 7;
+ proto_tree_add_uint(tree2, hf_exp, tvb, offset, 1, exp);
+ proto_item_append_text(ti, "EXP %u, ", exp);
+ offset ++;
+ break;
+ case 2: /* L-LSP */
+ tree2 = tree;
+ break;
+ default:
+ return;
+ }
+
+ /* PHBID subtree */
+ sub_ti = proto_tree_add_item(tree2, hf_phbid, tvb, offset, 2, FALSE);
+ phbid_subtree = proto_item_add_subtree(sub_ti, ett_map_phbid);
+ proto_item_set_text(sub_ti, "%s: ", (type == 1) ? "PHBID" : "PSC");
+ phbid = tvb_get_ntohs(tvb, offset);
+
+ if ((phbid & 1) == 0) {
+ /* Case 1 of RFC 3140 */
+ proto_tree_add_uint(phbid_subtree, hf_phbid_dscp,
+ tvb, offset, 2, phbid);
+ if (type == 1)
+ proto_item_append_text(ti, "DSCP %u", phbid >> 10);
+ proto_item_append_text(sub_ti, "DSCP %u", phbid >> 10);
+ }
+ else {
+ /* Case 2 of RFC 3140 */
+ proto_tree_add_uint(phbid_subtree, hf_phbid_code,
+ tvb, offset, 2, phbid);
+ if (type == 1)
+ proto_item_append_text(ti, "PHB id code %u", phbid >> 4);
+ proto_item_append_text(sub_ti, "PHB id code %u", phbid >> 4);
+ }
+ proto_tree_add_uint(phbid_subtree, hf_phbid_bit14, tvb, offset, 2, phbid);
+ proto_tree_add_uint(phbid_subtree, hf_phbid_bit15, tvb, offset, 2, phbid);
+}
diff --git a/epan/dissectors/packet-diffserv-mpls-common.h b/epan/dissectors/packet-diffserv-mpls-common.h
new file mode 100644
index 0000000000..4294ee06a8
--- /dev/null
+++ b/epan/dissectors/packet-diffserv-mpls-common.h
@@ -0,0 +1,52 @@
+/* packet-diffserv-mpls-common.h
+ * Routines for the common part of Diffserv MPLS signaling protocols
+ * Author: Endoh Akira (endoh@netmarks.co.jp)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DSMPLS_H__
+#define __PACKET_DSMPLS_H__
+
+#define PHBID_DSCP_MASK 0xFC00
+#define PHBID_CODE_MASK 0xFFF0
+#define PHBID_BIT14_MASK 2
+#define PHBID_BIT15_MASK 1
+
+#define MAPNB_DESCRIPTION "Number of MAP entries"
+#define MAP_DESCRIPTION "MAP entry"
+#define EXP_DESCRIPTION "EXP bit code"
+#define PHBID_DESCRIPTION "PHBID"
+#define PHBID_DSCP_DESCRIPTION "DSCP"
+#define PHBID_CODE_DESCRIPTION "PHB id code"
+#define PHBID_BIT14_DESCRIPTION "Bit 14"
+#define PHBID_BIT15_DESCRIPTION "Bit 15"
+
+
+extern const value_string phbid_bit14_vals[];
+
+extern const value_string phbid_bit15_vals[];
+
+void
+dissect_diffserv_mpls_common(tvbuff_t *tvb, proto_tree *tree, int type,
+ int offset, int **hfindexes, gint **etts);
+
+#endif
diff --git a/epan/dissectors/packet-distcc.c b/epan/dissectors/packet-distcc.c
new file mode 100644
index 0000000000..a17e2d2ddd
--- /dev/null
+++ b/epan/dissectors/packet-distcc.c
@@ -0,0 +1,440 @@
+/* packet-distcc.c
+ * Routines for distcc dissection
+ * Copyright 2003, Brad Hards <bradh@frogmouth.net>
+ * Copyright 2003, Ronnie Sahlberg, added TCP desegmentation.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/* This dissector supports version 1 of the DISTCC protocol */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <time.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "prefs.h"
+
+
+static int proto_distcc = -1;
+static int hf_distcc_version = -1;
+static int hf_distcc_argc = -1;
+static int hf_distcc_argv = -1;
+static int hf_distcc_doti_source = -1;
+static int hf_distcc_stat = -1;
+static int hf_distcc_serr = -1;
+static int hf_distcc_sout = -1;
+static int hf_distcc_doto_object = -1;
+
+
+static gint ett_distcc = -1;
+
+static dissector_handle_t data_handle;
+
+
+static gboolean distcc_desegment = TRUE;
+
+
+#define TCP_PORT_DISTCC 3632
+
+static guint glb_distcc_tcp_port = TCP_PORT_DISTCC;
+
+extern void proto_reg_handoff_distcc(void);
+
+#define CHECK_PDU_LEN(x) \
+ if(parameter>tvb_length_remaining(tvb, offset)){\
+ len=tvb_length_remaining(tvb, offset);\
+ if (check_col(pinfo->cinfo, COL_INFO)) {\
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[Short" x " PDU]");\
+ }\
+ }
+
+
+#define DESEGMENT_TCP(x) \
+ if(distcc_desegment && pinfo->can_desegment){\
+ /* only attempt reassembly if whe have the full segment */\
+ if(tvb_length_remaining(tvb, offset)==tvb_reported_length_remaining(tvb, offset)){\
+ if(parameter>tvb_length_remaining(tvb, offset)){\
+ proto_tree_add_text(tree, tvb, offset-12, -1, "[Short " x " PDU]");\
+ pinfo->desegment_offset=offset-12;\
+ pinfo->desegment_len=parameter-tvb_length_remaining(tvb, offset);\
+ return offset+len;\
+ }\
+ }\
+ }
+
+
+
+
+
+static int
+dissect_distcc_dist(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint32 parameter)
+{
+ proto_tree_add_uint_format(tree, hf_distcc_version, tvb, offset-12, 12, parameter, "DIST: %d", parameter);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "DIST:%d ", parameter);
+ }
+
+ return offset;
+}
+
+static int
+dissect_distcc_done(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint32 parameter)
+{
+ proto_tree_add_uint_format(tree, hf_distcc_version, tvb, offset-12, 12, parameter, "DONE: %d", parameter);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "DONE:%d ", parameter);
+ }
+
+ return offset;
+}
+
+static int
+dissect_distcc_stat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint32 parameter)
+{
+ proto_tree_add_uint_format(tree, hf_distcc_stat, tvb, offset-12, 12, parameter, "STAT: %d", parameter);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "STAT:%d ", parameter);
+ }
+
+ return offset;
+}
+
+static int
+dissect_distcc_argc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint32 parameter)
+{
+ proto_tree_add_uint_format(tree, hf_distcc_argc, tvb, offset-12, 12, parameter, "ARGC: %d", parameter);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "ARGC:%d ", parameter);
+ }
+
+ return offset;
+}
+
+static int
+dissect_distcc_argv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gint parameter)
+{
+ char argv[256];
+ int argv_len;
+ gint len=parameter;
+
+
+ CHECK_PDU_LEN("ARGV");
+
+ /* see if we need to desegment the PDU */
+ DESEGMENT_TCP("ARGV");
+
+
+
+ argv_len=len>255?255:len;
+ tvb_memcpy(tvb, argv, offset, argv_len);
+ argv[argv_len]=0;
+
+ proto_tree_add_item(tree, hf_distcc_argv, tvb, offset, len, FALSE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", argv);
+ }
+
+ if(len!=parameter){
+ proto_tree_add_text(tree, tvb, 0, 0, "[Short ARGV PDU]");
+ }
+ return offset+len;
+}
+
+static int
+dissect_distcc_serr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gint parameter)
+{
+ char argv[256];
+ int argv_len;
+ gint len=parameter;
+
+
+ CHECK_PDU_LEN("SERR");
+
+ /* see if we need to desegment the PDU */
+ DESEGMENT_TCP("SERR");
+
+
+
+ argv_len=len>255?255:len;
+ tvb_memcpy(tvb, argv, offset, argv_len);
+ argv[argv_len]=0;
+
+ proto_tree_add_item(tree, hf_distcc_serr, tvb, offset, len, FALSE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "SERR:%s ", argv);
+ }
+
+ if(len!=parameter){
+ proto_tree_add_text(tree, tvb, 0, 0, "[Short SERR PDU]");
+ }
+ return offset+len;
+}
+
+static int
+dissect_distcc_sout(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gint parameter)
+{
+ char argv[256];
+ int argv_len;
+ gint len=parameter;
+
+
+ CHECK_PDU_LEN("SOUT");
+
+ /* see if we need to desegment the PDU */
+ DESEGMENT_TCP("SOUT");
+
+
+
+ argv_len=len>255?255:len;
+ tvb_memcpy(tvb, argv, offset, argv_len);
+ argv[argv_len]=0;
+
+ proto_tree_add_item(tree, hf_distcc_sout, tvb, offset, len, FALSE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "SOUT:%s ", argv);
+ }
+
+ if(len!=parameter){
+ proto_tree_add_text(tree, tvb, 0, 0, "[Short SOUT PDU]");
+ }
+ return offset+len;
+}
+
+
+static int
+dissect_distcc_doti(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, gint parameter)
+{
+ gint len=parameter;
+
+
+ CHECK_PDU_LEN("DOTI");
+
+ /* see if we need to desegment the PDU */
+ DESEGMENT_TCP("DOTI");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "DOTI source ");
+ }
+
+ proto_tree_add_item(tree, hf_distcc_doti_source, tvb, offset, len, FALSE);
+ if(len!=parameter){
+ proto_tree_add_text(tree, tvb, 0, 0, "[Short DOTI PDU]");
+ }
+ return offset+len;
+}
+
+static int
+dissect_distcc_doto(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, gint parameter)
+{
+ gint len=parameter;
+
+
+ CHECK_PDU_LEN("DOTO");
+
+ /* see if we need to desegment the PDU */
+ DESEGMENT_TCP("DOTO");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "DOTO object ");
+ }
+
+ proto_tree_add_item(tree, hf_distcc_doto_object, tvb, offset, len, FALSE);
+ if(len!=parameter){
+ proto_tree_add_text(tree, tvb, 0, 0, "[Short DOTO PDU]");
+ }
+ return offset+len;
+}
+
+
+
+/* Packet dissection routine called by tcp (& udp) when port 3632 detected */
+static void
+dissect_distcc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ int offset=0;
+ proto_tree *tree=NULL;
+ proto_item *item=NULL;
+ char token[4];
+ guint32 parameter;
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DISTCC ");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, proto_distcc, tvb, offset,
+ -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_distcc);
+ }
+
+ while(1){
+ /* we must have at least 12 bytes so we can read the
+ token and the parameter */
+ if(tvb_length_remaining(tvb, offset)<12){
+ return;
+ }
+
+ /* read the token */
+ tvb_memcpy(tvb, token, offset, 4);
+ offset+=4;
+
+ /* read the parameter */
+ sscanf(tvb_get_ptr(tvb, offset, 8), "%08x", &parameter);
+ offset+=8;
+
+ if(!strncmp(token, "DIST", 4)){
+ offset=dissect_distcc_dist(tvb, pinfo, tree, offset, parameter);
+ } else if(!strncmp(token, "ARGC", 4)){
+ offset=dissect_distcc_argc(tvb, pinfo, tree, offset, parameter);
+ } else if(!strncmp(token, "ARGV", 4)){
+ offset=dissect_distcc_argv(tvb, pinfo, tree, offset, parameter);
+ } else if(!strncmp(token, "DOTI", 4)){
+ offset=dissect_distcc_doti(tvb, pinfo, tree, offset, parameter);
+ } else if(!strncmp(token, "DONE", 4)){
+ offset=dissect_distcc_done(tvb, pinfo, tree, offset, parameter);
+ } else if(!strncmp(token, "STAT", 4)){
+ offset=dissect_distcc_stat(tvb, pinfo, tree, offset, parameter);
+ } else if(!strncmp(token, "SERR", 4)){
+ offset=dissect_distcc_serr(tvb, pinfo, tree, offset, parameter);
+ } else if(!strncmp(token, "SOUT", 4)){
+ offset=dissect_distcc_sout(tvb, pinfo, tree, offset, parameter);
+ } else if(!strncmp(token, "DOTO", 4)){
+ offset=dissect_distcc_doto(tvb, pinfo, tree, offset, parameter);
+ } else {
+ call_dissector(data_handle, tvb, pinfo, tree);
+ return;
+ }
+ }
+
+
+}
+
+/* Register protocol with Ethereal. */
+void
+proto_register_distcc(void)
+{
+ static hf_register_info hf[] = {
+ {&hf_distcc_version,
+ {"DISTCC Version", "distcc.version",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "DISTCC Version", HFILL }
+ },
+ {&hf_distcc_argc,
+ {"ARGC", "distcc.argc",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "Number of arguments", HFILL }
+ },
+ {&hf_distcc_argv,
+ {"ARGV", "distcc.argv",
+ FT_STRING, BASE_NONE, NULL, 0x0, "ARGV argument", HFILL }
+ },
+ {&hf_distcc_doti_source,
+ {"Source", "distcc.doti_source",
+ FT_STRING, BASE_NONE, NULL, 0x0, "DOTI Preprocessed Source File (.i)", HFILL }
+ },
+ {&hf_distcc_stat,
+ {"Status", "distcc.status",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "Unix wait status for command completion", HFILL }
+ },
+ {&hf_distcc_serr,
+ {"SERR", "distcc.serr",
+ FT_STRING, BASE_NONE, NULL, 0x0, "STDERR output", HFILL }
+ },
+ {&hf_distcc_sout,
+ {"SOUT", "distcc.sout",
+ FT_STRING, BASE_NONE, NULL, 0x0, "STDOUT output", HFILL }
+ },
+ {&hf_distcc_doto_object,
+ {"Object", "distcc.doto_object",
+ FT_BYTES, BASE_HEX, NULL, 0x0, "DOTO Compiled object file (.o)", HFILL }
+ }
+
+ };
+
+ static gint *ett[] = {
+ &ett_distcc,
+ };
+
+ module_t *distcc_module;
+
+ proto_distcc = proto_register_protocol("Distcc Distributed Compiler",
+ "DISTCC", "distcc");
+ proto_register_field_array(proto_distcc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ distcc_module = prefs_register_protocol(proto_distcc,
+ proto_reg_handoff_distcc);
+ prefs_register_uint_preference(distcc_module, "tcp.port",
+ "DISTCC TCP Port",
+ "Set the TCP port for DISTCC messages",
+ 10,
+ &glb_distcc_tcp_port);
+ prefs_register_bool_preference(distcc_module, "desegment_distcc_over_tcp",
+ "Desegment all DISTCC-over-TCP messages",
+ "Whether the DISTCC dissector should desegment all DISTCC-over-TCP messages",
+ &distcc_desegment);
+}
+
+void
+proto_reg_handoff_distcc(void)
+{
+ static gboolean registered_dissector = FALSE;
+ static int distcc_tcp_port;
+ static dissector_handle_t distcc_handle;
+
+ if (registered_dissector) {
+ /*
+ * We've registered the dissector with a TCP port number
+ * of "distcc_tcp_port"; we might be changing the TCP port
+ * number, so remove that registration.
+ */
+ dissector_delete("tcp.port", distcc_tcp_port, distcc_handle);
+ } else {
+ /*
+ * We haven't registered the dissector yet; get a handle
+ * for it.
+ */
+ distcc_handle = create_dissector_handle(dissect_distcc,
+ proto_distcc);
+ registered_dissector = TRUE;
+ }
+ distcc_tcp_port = glb_distcc_tcp_port;
+ dissector_add("tcp.port", distcc_tcp_port, distcc_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-dlsw.c b/epan/dissectors/packet-dlsw.c
new file mode 100644
index 0000000000..7c7de82851
--- /dev/null
+++ b/epan/dissectors/packet-dlsw.c
@@ -0,0 +1,435 @@
+/* packet-dlsw.c
+ * Routines for DLSw packet dissection (Data Link Switching)
+ * Copyright 2001, Paul Ionescu <paul@acorp.ro>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* DLSw dissector ( RFC 1434, RFC 1795, RFC 2166) */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+static int proto_dlsw = -1;
+
+static gint ett_dlsw = -1;
+static gint ett_dlsw_header = -1;
+static gint ett_dlsw_data = -1;
+static gint ett_dlsw_vector = -1;
+
+#define CANUREACH 0x03
+#define ICANREACH 0x04
+#define REACH_ACK 0x05
+#define DGRMFRAME 0x06
+#define XIDFRAME 0x07
+#define CONTACT 0x08
+#define CONTACTED 0x09
+#define RESTART_DL 0x10
+#define DL_RESTARTED 0x11
+#define ENTER_BUSY 0x0C
+#define EXIT_BUSY 0x0D
+#define INFOFRAME 0x0A
+#define HALT_DL 0x0E
+#define DL_HALTED 0x0F
+#define NETBIOS_NQ 0x12
+#define NETBIOS_NR 0x13
+#define DATAFRAME 0x14
+#define HALT_DL_NOACK 0x19
+#define NETBIOS_ANQ 0x1A
+#define NETBIOS_ANR 0x1B
+#define KEEPALIVE 0x1D
+#define CAP_EXCHANGE 0x20
+#define IFCM 0x21
+#define TEST_CIRCUIT_REQ 0x7A
+#define TEST_CIRCUIT_RSP 0x7B
+
+static const value_string dlsw_type_vals[] = {
+ { CANUREACH , "Can U Reach Station-circuit start" },
+ { ICANREACH , "I Can Reach Station-circuit start" },
+ { REACH_ACK , "Reach Acknowledgment" },
+ { DGRMFRAME , "Datagram Frame" },
+ { XIDFRAME , "XID Frame" },
+ { CONTACT , "Contact Remote Station" },
+ { CONTACTED , "Remote Station Contacted" },
+ { RESTART_DL , "Restart Data Link" },
+ { DL_RESTARTED , "Data Link Restarted" },
+ { ENTER_BUSY , "Enter Busy" },
+ { EXIT_BUSY , "Exit Busy" },
+ { INFOFRAME , "Information (I) Frame" },
+ { HALT_DL , "Halt Data Link" },
+ { DL_HALTED , "Data Link Halted" },
+ { NETBIOS_NQ , "NETBIOS Name Query-circuit setup" },
+ { NETBIOS_NR , "NETBIOS Name Recog-circuit setup" },
+ { DATAFRAME , "Data Frame" },
+ { HALT_DL_NOACK , "Halt Data Link with no Ack" },
+ { NETBIOS_ANQ , "NETBIOS Add Name Query" },
+ { NETBIOS_ANR , "NETBIOS Add Name Response" },
+ { KEEPALIVE , "Transport Keepalive Message" },
+ { CAP_EXCHANGE , "Capabilities Exchange" },
+ { IFCM , "Independent Flow Control Message" },
+ { TEST_CIRCUIT_REQ , "Test Circuit Request" },
+ { TEST_CIRCUIT_RSP , "Test Circuit Response" },
+ { 0 , NULL }
+};
+static const value_string dlsw_version_vals[] = {
+ { 0x31 , "Version 1 (RFC 1795)" },
+ { 0x32 , "Version 2 (RFC 2166)" },
+ { 0x33 , "Vendor Specific" },
+ { 0x34 , "Vendor Specific" },
+ { 0x35 , "Vendor Specific" },
+ { 0x36 , "Vendor Specific" },
+ { 0x37 , "Vendor Specific" },
+ { 0x38 , "Vendor Specific" },
+ { 0x39 , "Vendor Specific" },
+ { 0x3A , "Vendor Specific" },
+ { 0x3B , "Vendor Specific" },
+ { 0x3C , "Vendor Specific" },
+ { 0x3D , "Vendor Specific" },
+ { 0x3E , "Vendor Specific" },
+ { 0x3F , "Vendor Specific" },
+ { 0x4B , "Pre 1 (RFC 1434)" },
+ { 0x00 , NULL }
+};
+
+static const value_string dlsw_vector_vals[] = {
+ { 0x81 , "Vendor ID Control Vector" },
+ { 0x82 , "DLSw Version Control Vector" },
+ { 0x83 , "Initial Pacing Window Control Vector" },
+ { 0x84 , "Version String Control Vector" },
+ { 0x85 , "Mac Address Exclusivity Control Vector" },
+ { 0x86 , "Supported SAP List Control Vector" },
+ { 0x87 , "TCP Connections Control Vector" },
+ { 0x88 , "NetBIOS Name Exclusivity Control Vector" },
+ { 0x89 , "MAC Address List Control Vector" },
+ { 0x8a , "NetBIOS Name List Control Vector" },
+ { 0x8b , "Vendor Context Control Vector" },
+ { 0x8c , "Multicast Capabilities Control Vector" },
+ { 0x8d , "Reserved for future use" },
+ { 0x8e , "Reserved for future use" },
+ { 0x8f , "Reserved for future use" },
+ { 0x90 , "Reserved for future use" },
+ { 0x91 , " Control Vector" },
+ { 0x92 , " Control Vector" },
+ { 0x93 , " Control Vector" },
+ { 0x94 , " Control Vector" },
+ { 0x95 , " Control Vector" },
+ { 0x96 , " Control Vector" },
+ { 0x00 , NULL }
+};
+
+static const value_string dlsw_pri_vals[] = {
+ { 0 , "Unsupported" },
+ { 1 , "Low Priority" },
+ { 2 , "Medium Priority" },
+ { 3 , "High Priority" },
+ { 4 , "Highest Priority" },
+ { 5 , "Reserved" },
+ { 6 , "Reserved" },
+ { 7 , "Reserved" }
+};
+
+
+
+
+#define DLSW_GDSID_SEND 0x1520
+#define DLSW_GDSID_ACK 0x1521
+#define DLSW_GDSID_REF 0x1522
+
+static const value_string dlsw_gds_vals[] = {
+ { DLSW_GDSID_SEND , "Request Capabilities GDS" },
+ { DLSW_GDSID_ACK , "Response Capabilities GDS" },
+ { DLSW_GDSID_REF , "Refuse Capabilities GDS" },
+ { 0 , NULL }
+};
+
+static const value_string dlsw_refuse_vals[] = {
+ { 0x1 , "invalid GDS length for a DLWs Capabilities Exchange Request"},
+ { 0x2 , "invalid GDS id for a DLSw Capabilities Exchange Request"},
+ { 0x3 , "vendor Id control vector is missing"},
+ { 0x4 , "DLSw Version control vector is missing"},
+ { 0x5 , "initial Pacing Window control vector is missing"},
+ { 0x6 , "length of control vectors doewn't correlate to the length of the GDS variable"},
+ { 0x7 , "invalid control vector id"},
+ { 0x8 , "length of control vector invalid"},
+ { 0x9 , "invalid control vector data value"},
+ { 0xa , "duplicate control vector"},
+ { 0xb , "out-of-sequence control vector"},
+ { 0xc , "DLSw Supported SAP List control vector is missing"},
+ { 0xd , "inconsistent DLSw Version, Multicast Capabilities,\
+ and TCP Connections CV received on the inbound Capabilities exchange"},
+ { 0x0 , NULL }
+};
+
+#define UDP_PORT_DLSW 2067
+#define TCP_PORT_DLSW 2065
+#define DLSW_INFO_HEADER 16
+#define DLSW_CMD_HEADER 72
+
+static void
+dissect_dlsw_capex(tvbuff_t *tvb, proto_tree *tree, proto_tree *ti);
+
+static void
+dissect_dlsw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint version,hlen = 0,mlen = 0,mtype,dlchlen = 0,direction;
+ proto_tree *dlsw_tree = NULL, *ti,*ti2, *dlsw_header_tree = NULL;
+ proto_tree *dlsw_data_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DLSw");
+
+ version=tvb_get_guint8(tvb,0);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "DLSw %s",val_to_str(version , dlsw_version_vals, "Unknown Version"));
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_dlsw, tvb, 0, -1, FALSE);
+ dlsw_tree = proto_item_add_subtree(ti, ett_dlsw);
+
+ hlen=tvb_get_guint8(tvb,1);
+
+ ti2 = proto_tree_add_text (dlsw_tree, tvb, 0, hlen,"DLSw header, %s",
+ val_to_str(version , dlsw_version_vals, "Unknown Version"));
+
+ dlsw_header_tree = proto_item_add_subtree(ti2, ett_dlsw_header);
+ proto_tree_add_text (dlsw_header_tree,tvb,0 ,1,"Version = %s",
+ val_to_str(version , dlsw_version_vals, "Unknown Version, dissection may be innacurate"));
+ proto_tree_add_text (dlsw_header_tree,tvb,1 ,1,"Header Length = %u",hlen) ;
+ mlen=tvb_get_ntohs(tvb,2);
+ proto_tree_add_text (dlsw_header_tree,tvb,2 ,2,"Message Length = %u",mlen);
+ proto_tree_add_text (dlsw_header_tree,tvb,4 ,4,"Remote DLC = %u",tvb_get_ntohl(tvb,4)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb,8 ,4,"Remote DLC PID = %u",tvb_get_ntohl(tvb,8)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb,12,2,"Reserved") ;
+ } ;
+
+ mtype=tvb_get_guint8(tvb,14);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",val_to_str(mtype , dlsw_type_vals, "Unknown message Type"));
+ if (tree)
+ {
+ proto_tree_add_text (dlsw_header_tree,tvb,14,1,"Message Type = %s (%d)",
+ val_to_str(mtype , dlsw_type_vals, "Unknown Type"),mtype);
+ proto_tree_add_text (dlsw_header_tree, tvb, 15,1,"Flow ctrl byte = %d",tvb_get_guint8(tvb,15));
+
+ if (hlen != DLSW_INFO_HEADER)
+ {
+ proto_tree_add_text (dlsw_header_tree,tvb, 16,1,"Protocol ID = %d",tvb_get_guint8(tvb,16)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 17,1,"Header Number = %d",tvb_get_guint8(tvb,17)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 18,2,"Reserved") ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 20,1,"Largest Frame size = %d",tvb_get_guint8(tvb,20)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 21,1,"SSP Flags = %d",tvb_get_guint8(tvb,21)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 22,1,"Circuit priority = %s",
+ match_strval((tvb_get_guint8(tvb,22)&7),dlsw_pri_vals)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 23,1,"Old message type = %s (%d)",
+ val_to_str(tvb_get_guint8(tvb,23) , dlsw_type_vals, "Unknown Type"),tvb_get_guint8(tvb,23));
+ if (mtype==CAP_EXCHANGE)
+ {
+ proto_tree_add_text (dlsw_header_tree,tvb, 24 ,14,"Not used for CapEx") ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 38,1,"Frame direction = %s",
+ tvb_get_guint8(tvb,38)==1?"Capabilities request":"Capabilities response") ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 39,33,"Not used for CapEx") ;
+ }
+ else
+ {
+ proto_tree_add_text (dlsw_header_tree,tvb, 24,6,"Target MAC Address = %s",tvb_bytes_to_str(tvb,24,6)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 30,6,"Origin MAC Address = %s",tvb_bytes_to_str(tvb,30,6)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 36,1,"Origin Link SAP = %02x",tvb_get_guint8(tvb,36)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 37,1,"Target Link SAP = %02x",tvb_get_guint8(tvb,37)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 38,1,"Frame direction = %d",tvb_get_guint8(tvb,38)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 39,3,"Reserved") ;
+ dlchlen=tvb_get_ntohs(tvb,42);
+ proto_tree_add_text (dlsw_header_tree,tvb, 42,2,"DLC Header Length = %d",dlchlen) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 44,4,"Origin DLC Port ID = %u",tvb_get_ntohl(tvb,44)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 48,4,"Origin DLC = %u",tvb_get_ntohl(tvb,48)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 52,4,"Origin Transport ID = %u",tvb_get_ntohl(tvb,52)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 56,4,"Target DLC Port ID = %u",tvb_get_ntohl(tvb,56)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 60,4,"Target DLC = %u",tvb_get_ntohl(tvb,60)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 64,4,"Target Transport ID = %u",tvb_get_ntohl(tvb,64)) ;
+ proto_tree_add_text (dlsw_header_tree,tvb, 68,4,"Reserved") ;
+ }
+ direction=tvb_get_guint8(tvb,38);
+ }
+
+/* end of header dissector */
+
+ ti2 = proto_tree_add_text (dlsw_tree, tvb, hlen, mlen,"DLSw data");
+ dlsw_data_tree = proto_item_add_subtree(ti2, ett_dlsw_data);
+
+ switch (mtype)
+ {
+ case CAP_EXCHANGE:
+ dissect_dlsw_capex(tvb_new_subset(tvb, hlen, mlen, -1), dlsw_data_tree,ti2);
+ break;
+ case IFCM:
+ case INFOFRAME:
+ case KEEPALIVE:
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen,mlen,"Data") ;
+ break;
+
+ default:
+ if (dlchlen!=0)
+ {
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen,1,"DLC Header - AC byte : 0x%02x",tvb_get_guint8(tvb,hlen)) ;
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen+1,1,"DLC Header - FC byte : 0x%02x",tvb_get_guint8(tvb,hlen+1)) ;
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen+2,6,"DLC Header - DA : %s",tvb_bytes_to_str(tvb,hlen+2,6)) ;
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen+8,6,"DLC Header - SA : %s",tvb_bytes_to_str(tvb,hlen+8,6)) ;
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen+14,18,"DLC Header - RIF : %s",tvb_bytes_to_str(tvb,hlen+14,18)) ;
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen+32,1,"DLC Header - DSAP : 0x%02x",tvb_get_guint8(tvb,hlen+32)) ;
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen+33,1,"DLC Header - SSAP : 0x%02x",tvb_get_guint8(tvb,hlen+33)) ;
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen+34,1,"DLC Header - Ctrl : 0x%02x",tvb_get_guint8(tvb,hlen+34)) ;
+ }
+ proto_tree_add_text (dlsw_data_tree,tvb,hlen+dlchlen,mlen-dlchlen,"Data") ;
+ }
+
+ }
+}
+
+static void
+dissect_dlsw_capex(tvbuff_t *tvb, proto_tree *tree, proto_tree *ti2)
+{
+ int mlen,vlen,vtype,offset=4,gdsid,sap,i=0;
+ proto_tree *ti,*dlsw_vector_tree;
+ mlen=tvb_get_ntohs(tvb,0);
+ gdsid=tvb_get_ntohs(tvb,2);
+ proto_tree_add_text (tree,tvb,0,2,"Capabilities Length = %d",mlen) ;
+ proto_tree_add_text (tree,tvb,2,2,"%s",val_to_str( gdsid, dlsw_gds_vals, "Invalid GDS ID"));
+ proto_item_append_text(ti2," - %s",val_to_str( gdsid, dlsw_gds_vals, "Invalid GDS ID"));
+ switch (gdsid) {
+ case DLSW_GDSID_ACK:
+ break;
+ case DLSW_GDSID_REF:
+ proto_tree_add_text (tree,tvb,4,2,"Erorr pointer = %d",tvb_get_ntohs(tvb,4));
+ proto_tree_add_text (tree,tvb,6,2,"Erorr cause = %s",
+ val_to_str(tvb_get_ntohs(tvb,6), dlsw_refuse_vals, "Unknown refuse cause"));
+ break;
+ case DLSW_GDSID_SEND:
+ while (offset < mlen){
+ vlen=tvb_get_guint8(tvb,offset);
+ vtype=tvb_get_guint8(tvb,offset+1);
+ ti=proto_tree_add_text (tree,tvb,offset,vlen,"%s",
+ val_to_str(vtype,dlsw_vector_vals,"Unknown vector type"));
+ dlsw_vector_tree = proto_item_add_subtree(ti, ett_dlsw_vector);
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset,1, "Vector Length = %d",vlen);
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+1,1,"Vector Type = %s (0x%02x)",
+ val_to_str(vtype,dlsw_vector_vals,"Unknown vector type"),vtype);
+ switch (vtype){
+ case 0x81:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "OUI = 0x%06x",tvb_get_ntoh24(tvb,offset+2));
+ break;
+ case 0x82:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "DLSw Version = %d.%d",tvb_get_guint8(tvb,offset+2),tvb_get_guint8(tvb,offset+3));
+ break;
+ case 0x83:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "Initial Pacing Window = %d",tvb_get_ntohs(tvb,offset+2));
+ break;
+ case 0x84:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "Version String = %s",tvb_format_text(tvb,offset+2,vlen-2));
+ break;
+ case 0x85:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "MAC Address Exclusivity = %s",tvb_get_guint8(tvb,offset+2)==1?"On":"Off");
+ break;
+ case 0x86:
+ while (i<vlen-2)
+ {
+ sap=tvb_get_guint8(tvb,offset+2+i);
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2+i,1,
+ "SAP List Support = 0x%x0=%s 0x%x2=%s 0x%x4=%s 0x%x6=%s 0x%x8=%s 0x%xa=%s 0x%xc=%s 0x%xe=%s",
+ i,sap&0x80?"on ":"off",i,sap&0x40?"on ":"off",i,sap&0x20?"on ":"off",i,sap&0x10?"on ":"off",
+ i,sap&0x08?"on ":"off",i,sap&0x04?"on ":"off",i,sap&0x02?"on ":"off",i,sap&0x01?"on ":"off");
+ i++;
+ }
+ break;
+ case 0x87:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "TCP connections = %d",tvb_get_guint8(tvb,offset+2));
+ break;
+ case 0x88:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "NetBIOS Name Exclusivity = %s",tvb_get_guint8(tvb,offset+2)==1?"On":"Off");
+ break;
+ case 0x89:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "MAC Address List = %s / %s",tvb_bytes_to_str(tvb,offset+2,6)
+ ,tvb_bytes_to_str(tvb,offset+8,6));
+ break;
+ case 0x8a:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+/* %s */ "NetBIOS name = %s",/* tvb_get_guint8(tvb,offset+2)==0?"Individual":"Group",*/
+ tvb_format_text(tvb,offset+2,vlen-2));
+ break;
+ case 0x8b:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "Vendor OUI = 0x%06x",tvb_get_ntoh24(tvb,offset+2));
+ break;
+ case 0x8c:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,
+ "Multicast Version Number = %d",tvb_get_guint8(tvb,offset+2));
+ break;
+ default:
+ proto_tree_add_text (dlsw_vector_tree,tvb,offset+2,vlen-2,"Vector Data = ???");
+ }
+ offset+=vlen;
+ };
+ break;
+ default:
+ proto_tree_add_text (tree,tvb,4,mlen - 4,"Unknown data");
+ }
+
+}
+
+void
+proto_register_dlsw(void)
+{
+ static gint *ett[] = {
+ &ett_dlsw,
+ &ett_dlsw_header,
+ &ett_dlsw_data,
+ &ett_dlsw_vector,
+ };
+ proto_dlsw = proto_register_protocol("Data Link SWitching", "DLSw", "dlsw");
+/* proto_register_field_array(proto_dlsw, hf, array_length(hf)); */
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_dlsw(void)
+{
+ dissector_handle_t dlsw_handle;
+
+ dlsw_handle = create_dissector_handle(dissect_dlsw, proto_dlsw);
+
+ dissector_add("tcp.port", TCP_PORT_DLSW, dlsw_handle);
+ dissector_add("udp.port", UDP_PORT_DLSW, dlsw_handle);
+}
diff --git a/epan/dissectors/packet-dnp.c b/epan/dissectors/packet-dnp.c
new file mode 100644
index 0000000000..7e58442869
--- /dev/null
+++ b/epan/dissectors/packet-dnp.c
@@ -0,0 +1,775 @@
+/* packet-DNP3.c
+ * Routines for DNP dissection
+ * Copyright 2003, Graham Bloice <graham.bloice@trihedral.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include "reassemble.h"
+
+/* DNP 3.0 constants */
+#define DNP_HDR_LEN 10
+#define TCP_PORT_DNP 20000
+#define DNP3_CTL_DIR 0x80
+#define DNP3_CTL_PRM 0x40
+#define DNP3_CTL_FCB 0x20
+#define DNP3_CTL_FCV 0x10
+#define DNP3_CTL_RES 0x20
+#define DNP3_CTL_DFC 0x10
+#define DNP3_CTL_FUNC 0x0f
+
+#define DNP3_DL_LEN_OFFS 0x02
+#define DNP3_DL_CTL_OFFS 0x03
+#define DNP3_DL_DST_OFFS 0x04
+#define DNP3_DL_SRC_OFFS 0x06
+
+#define DNP3_TR_FIR 0x40
+#define DNP3_TR_FIN 0x80
+#define DNP3_TR_SEQ 0x3f
+
+#define AL_MAX_CHUNK_SIZE 16
+
+#define DNP3_AL_CON 0x20
+#define DNP3_AL_FIN 0x40
+#define DNP3_AL_FIR 0x80
+#define DNP3_AL_SEQ 0x1f
+#define DNP3_AL_FUNC 0xff
+
+#define DNP3_AL_CTL_OFFS 0x0
+#define DNP3_AL_FUNC_OFFS 0x1
+
+/* DL Function codes */
+#define DL_FUNC_RESET_LINK 0x0
+#define DL_FUNC_RESET_PROC 0x1
+#define DL_FUNC_TEST_LINK 0x2
+#define DL_FUNC_USER_DATA 0x3
+#define DL_FUNC_UNC_DATA 0x4
+#define DL_FUNC_LINK_STAT 0x9
+
+#define DL_FUNC_ACK 0x0
+#define DL_FUNC_NACK 0x1
+#define DL_FUNC_STAT_LINK 0xB
+#define DL_FUNC_NO_FUNC 0xE
+#define DL_FUNC_NOT_IMPL 0xF
+
+/* AL Function codes */
+#define DL_AL_FUNC_CONFIRM 0x0
+#define DL_AL_FUNC_READ 0x01
+#define DL_AL_FUNC_WRITE 0x02
+#define DL_AL_FUNC_DIROP 0x05
+#define DL_AL_FUNC_RESPON 0x81
+
+/* Initialize the protocol and registered fields */
+static int proto_dnp3 = -1;
+static int hf_dnp3_start = -1;
+static int hf_dnp3_len = -1;
+static int hf_dnp3_ctl = -1;
+static int hf_dnp3_ctl_prifunc = -1;
+static int hf_dnp3_ctl_secfunc = -1;
+static int hf_dnp3_ctl_dir = -1;
+static int hf_dnp3_ctl_prm = -1;
+static int hf_dnp3_ctl_fcb = -1;
+static int hf_dnp3_ctl_fcv = -1;
+static int hf_dnp3_ctl_dfc = -1;
+static int hf_dnp3_dst = -1;
+static int hf_dnp3_src = -1;
+static int hf_dnp_hdr_CRC = -1;
+static int hf_dnp_hdr_CRC_bad = -1;
+static int hf_dnp3_tr_ctl = -1;
+static int hf_dnp3_tr_fin = -1;
+static int hf_dnp3_tr_fir = -1;
+static int hf_dnp3_tr_seq = -1;
+static int hf_dnp3_al_ctl = -1;
+static int hf_dnp3_al_fir = -1;
+static int hf_dnp3_al_fin = -1;
+static int hf_dnp3_al_con = -1;
+static int hf_dnp3_al_seq = -1;
+static int hf_dnp3_al_func = -1;
+
+/* ************************************************************************* */
+/* Header values for reassembly */
+/* ************************************************************************* */
+static int hf_fragments = -1;
+static int hf_fragment = -1;
+static int hf_fragment_overlap = -1;
+static int hf_fragment_overlap_conflict = -1;
+static int hf_fragment_multiple_tails = -1;
+static int hf_fragment_too_long_fragment = -1;
+static int hf_fragment_error = -1;
+static int hf_fragment_reassembled_in = -1;
+
+/* Control Function Code Values */
+static const value_string dnp3_ctl_func_pri_vals[] = {
+ { DL_FUNC_RESET_LINK, "Reset of remote link" },
+ { DL_FUNC_RESET_PROC, "Reset of user process" },
+ { DL_FUNC_TEST_LINK, "Test function for link" },
+ { DL_FUNC_USER_DATA, "User Data" },
+ { DL_FUNC_UNC_DATA, "Unconfirmed User Data" },
+ { DL_FUNC_LINK_STAT, "Request Link Status" },
+ { 0, NULL }
+};
+
+static const value_string dnp3_ctl_func_sec_vals[] = {
+ { DL_FUNC_ACK, "ACK" },
+ { DL_FUNC_NACK, "NACK" },
+ { DL_FUNC_STAT_LINK, "Status of Link" },
+ { DL_FUNC_NO_FUNC, "Link service not functioning" },
+ { DL_FUNC_NOT_IMPL, "Link service not used or implemented" },
+ { 0, NULL }
+};
+
+static const value_string dnp3_ctl_flags_pri_vals[] = {
+ { DNP3_CTL_DIR, "DIR" },
+ { DNP3_CTL_PRM, "PRM" },
+ { DNP3_CTL_FCB, "FCB" },
+ { DNP3_CTL_FCV, "FCV" },
+ { 0, NULL }
+};
+
+static const value_string dnp3_ctl_flags_sec_vals[] = {
+ { DNP3_CTL_DIR, "DIR" },
+ { DNP3_CTL_PRM, "PRM" },
+ { DNP3_CTL_RES, "RES" },
+ { DNP3_CTL_DFC, "DFC" },
+ { 0, NULL }
+};
+
+static const value_string dnp3_tr_flags_vals[] = {
+ { DNP3_TR_FIN, "FIN" },
+ { DNP3_TR_FIR, "FIR" },
+ { 0, NULL }
+};
+
+static const value_string dnp3_al_flags_vals[] = {
+ { DNP3_AL_FIR, "FIR" },
+ { DNP3_AL_FIN, "FIN" },
+ { DNP3_AL_CON, "CON" },
+ { 0, NULL }
+};
+
+/* Control Function Code Values */
+static const value_string dnp3_al_func_vals[] = {
+ { DL_AL_FUNC_CONFIRM, "Confirm" },
+ { DL_AL_FUNC_READ, "Read" },
+ { DL_AL_FUNC_WRITE, "Write" },
+ { DL_AL_FUNC_DIROP, "Direct Operate" },
+ { DL_AL_FUNC_RESPON, "Response" },
+ { 0, NULL }
+};
+
+/* Initialize the subtree pointers */
+static gint ett_dnp3 = -1;
+static gint ett_dnp3_dl = -1;
+static gint ett_dnp3_dl_ctl = -1;
+static gint ett_dnp3_tr_ctl = -1;
+static gint ett_dnp3_al_data = -1;
+static gint ett_dnp3_al = -1;
+static gint ett_dnp3_al_ctl = -1;
+static gint ett_fragment = -1;
+static gint ett_fragments = -1;
+
+/* Tables for reassembly of fragments. */
+static GHashTable *al_fragment_table = NULL;
+static GHashTable *al_reassembled_table = NULL;
+
+static const fragment_items frag_items = {
+ &ett_fragment,
+ &ett_fragments,
+ &hf_fragments,
+ &hf_fragment,
+ &hf_fragment_overlap,
+ &hf_fragment_overlap_conflict,
+ &hf_fragment_multiple_tails,
+ &hf_fragment_too_long_fragment,
+ &hf_fragment_error,
+ &hf_fragment_reassembled_in,
+ "fragments"
+};
+
+/*****************************************************************/
+/* */
+/* CRC LOOKUP TABLE */
+/* ================ */
+/* The following CRC lookup table was generated automagically */
+/* by the Rocksoft^tm Model CRC Algorithm Table Generation */
+/* Program V1.0 using the following model parameters: */
+/* */
+/* Width : 2 bytes. */
+/* Poly : 0x3D65 */
+/* Reverse : TRUE. */
+/* */
+/* For more information on the Rocksoft^tm Model CRC Algorithm, */
+/* see the document titled "A Painless Guide to CRC Error */
+/* Detection Algorithms" by Ross Williams */
+/* (ross@guest.adelaide.edu.au.). This document is likely to be */
+/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
+/* */
+/*****************************************************************/
+
+static guint16 crctable[256] =
+{
+ 0x0000, 0x365E, 0x6CBC, 0x5AE2, 0xD978, 0xEF26, 0xB5C4, 0x839A,
+ 0xFF89, 0xC9D7, 0x9335, 0xA56B, 0x26F1, 0x10AF, 0x4A4D, 0x7C13,
+ 0xB26B, 0x8435, 0xDED7, 0xE889, 0x6B13, 0x5D4D, 0x07AF, 0x31F1,
+ 0x4DE2, 0x7BBC, 0x215E, 0x1700, 0x949A, 0xA2C4, 0xF826, 0xCE78,
+ 0x29AF, 0x1FF1, 0x4513, 0x734D, 0xF0D7, 0xC689, 0x9C6B, 0xAA35,
+ 0xD626, 0xE078, 0xBA9A, 0x8CC4, 0x0F5E, 0x3900, 0x63E2, 0x55BC,
+ 0x9BC4, 0xAD9A, 0xF778, 0xC126, 0x42BC, 0x74E2, 0x2E00, 0x185E,
+ 0x644D, 0x5213, 0x08F1, 0x3EAF, 0xBD35, 0x8B6B, 0xD189, 0xE7D7,
+ 0x535E, 0x6500, 0x3FE2, 0x09BC, 0x8A26, 0xBC78, 0xE69A, 0xD0C4,
+ 0xACD7, 0x9A89, 0xC06B, 0xF635, 0x75AF, 0x43F1, 0x1913, 0x2F4D,
+ 0xE135, 0xD76B, 0x8D89, 0xBBD7, 0x384D, 0x0E13, 0x54F1, 0x62AF,
+ 0x1EBC, 0x28E2, 0x7200, 0x445E, 0xC7C4, 0xF19A, 0xAB78, 0x9D26,
+ 0x7AF1, 0x4CAF, 0x164D, 0x2013, 0xA389, 0x95D7, 0xCF35, 0xF96B,
+ 0x8578, 0xB326, 0xE9C4, 0xDF9A, 0x5C00, 0x6A5E, 0x30BC, 0x06E2,
+ 0xC89A, 0xFEC4, 0xA426, 0x9278, 0x11E2, 0x27BC, 0x7D5E, 0x4B00,
+ 0x3713, 0x014D, 0x5BAF, 0x6DF1, 0xEE6B, 0xD835, 0x82D7, 0xB489,
+ 0xA6BC, 0x90E2, 0xCA00, 0xFC5E, 0x7FC4, 0x499A, 0x1378, 0x2526,
+ 0x5935, 0x6F6B, 0x3589, 0x03D7, 0x804D, 0xB613, 0xECF1, 0xDAAF,
+ 0x14D7, 0x2289, 0x786B, 0x4E35, 0xCDAF, 0xFBF1, 0xA113, 0x974D,
+ 0xEB5E, 0xDD00, 0x87E2, 0xB1BC, 0x3226, 0x0478, 0x5E9A, 0x68C4,
+ 0x8F13, 0xB94D, 0xE3AF, 0xD5F1, 0x566B, 0x6035, 0x3AD7, 0x0C89,
+ 0x709A, 0x46C4, 0x1C26, 0x2A78, 0xA9E2, 0x9FBC, 0xC55E, 0xF300,
+ 0x3D78, 0x0B26, 0x51C4, 0x679A, 0xE400, 0xD25E, 0x88BC, 0xBEE2,
+ 0xC2F1, 0xF4AF, 0xAE4D, 0x9813, 0x1B89, 0x2DD7, 0x7735, 0x416B,
+ 0xF5E2, 0xC3BC, 0x995E, 0xAF00, 0x2C9A, 0x1AC4, 0x4026, 0x7678,
+ 0x0A6B, 0x3C35, 0x66D7, 0x5089, 0xD313, 0xE54D, 0xBFAF, 0x89F1,
+ 0x4789, 0x71D7, 0x2B35, 0x1D6B, 0x9EF1, 0xA8AF, 0xF24D, 0xC413,
+ 0xB800, 0x8E5E, 0xD4BC, 0xE2E2, 0x6178, 0x5726, 0x0DC4, 0x3B9A,
+ 0xDC4D, 0xEA13, 0xB0F1, 0x86AF, 0x0535, 0x336B, 0x6989, 0x5FD7,
+ 0x23C4, 0x159A, 0x4F78, 0x7926, 0xFABC, 0xCCE2, 0x9600, 0xA05E,
+ 0x6E26, 0x5878, 0x029A, 0x34C4, 0xB75E, 0x8100, 0xDBE2, 0xEDBC,
+ 0x91AF, 0xA7F1, 0xFD13, 0xCB4D, 0x48D7, 0x7E89, 0x246B, 0x1235
+};
+
+/*****************************************************************/
+/* End of CRC Lookup Table */
+/*****************************************************************/
+
+/* calculates crc given a buffer of characters and a length of buffer */
+static guint16
+calculateCRC(const void *buf, guint len) {
+ guint16 crc = 0;
+ const guint8 *p = (const guint8 *)buf;
+ while(len-- > 0)
+ crc = crctable[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ return ~crc;
+}
+
+/* function to print list of bit flags */
+static guint
+flags_to_str(guint8 val, const value_string *vs, gchar *const str)
+{
+ guint i, fpos;
+
+ i = fpos = 0;
+ while (vs[i].strptr) {
+ if (val & vs[i].value) {
+ if (fpos) {
+ strcpy(&str[fpos], ", ");
+ fpos += 2;
+ }
+ strcpy(&str[fpos], vs[i].strptr);
+ fpos += strlen(vs[i].strptr);
+ }
+ i++;
+ }
+ return fpos;
+}
+
+/* Code to actually dissect the packets */
+
+/* Application layer dissector */
+static void
+dissect_dnp3_al(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint8 al_ctl, al_seq, al_func;
+ gboolean al_fir, al_fin, al_con;
+ gchar flags[64] = "<None>";
+ guint fpos = 0;
+ int offset = 0;
+ proto_item *ti = NULL, *tc;
+ proto_tree *al_tree = NULL, *field_tree = NULL;
+ const gchar *func_code_str;
+
+ /* Handle the control byte and function code */
+ al_ctl = tvb_get_guint8(tvb, DNP3_AL_CTL_OFFS);
+ al_seq = al_ctl & DNP3_AL_SEQ;
+ al_fir = al_ctl & DNP3_AL_FIR;
+ al_fin = al_ctl & DNP3_AL_FIN;
+ al_con = al_ctl & DNP3_AL_CON;
+ al_func = tvb_get_guint8(tvb, DNP3_AL_FUNC_OFFS);
+ func_code_str = val_to_str(al_func, dnp3_al_func_vals, "Unknown function (0x%02x)");
+
+ if (tree) {
+ /* format up the text representation */
+
+ fpos = flags_to_str(al_ctl, dnp3_al_flags_vals, flags);
+ if (fpos) {
+ strcpy(&flags[fpos], ", ");
+ fpos += 2;
+ }
+ flags[fpos] = '\0';
+
+ /* Add the al tree branch */
+ ti = proto_tree_add_text(tree, tvb, offset, -1,
+ "Application Layer: (%sSequence %d, %s)",
+ flags, al_seq, func_code_str);
+ al_tree = proto_item_add_subtree(ti, ett_dnp3_al);
+
+ /* al control byte subtree */
+ tc = proto_tree_add_uint_format(al_tree, hf_dnp3_al_ctl, tvb, offset, 1, al_ctl,
+ "Control: 0x%02x (%sSequence %d)", al_ctl, flags, al_seq);
+ field_tree = proto_item_add_subtree(tc, ett_dnp3_al_ctl);
+ proto_tree_add_boolean(field_tree, hf_dnp3_al_fir, tvb, offset, 1, al_ctl);
+ proto_tree_add_boolean(field_tree, hf_dnp3_al_fin, tvb, offset, 1, al_ctl);
+ proto_tree_add_boolean(field_tree, hf_dnp3_al_con, tvb, offset, 1, al_ctl);
+ proto_tree_add_item(field_tree, hf_dnp3_al_seq, tvb, offset, 1, al_ctl);
+ offset += 1;
+
+ /* AL function code byte */
+ proto_tree_add_uint_format(al_tree, hf_dnp3_al_func, tvb, offset, 1, al_func,
+ "Function Code: %s (0x%02x)", func_code_str, al_func);
+ offset += 1;
+ }
+ else
+ offset += 2; /* No tree, correct offset */
+
+
+}
+
+/* Data Link and Transport layer dissector */
+static void
+dissect_dnp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti = NULL, *tdl, *tc, *al_chunks;
+ proto_tree *dnp3_tree = NULL, *dl_tree = NULL, *tr_tree = NULL, *field_tree = NULL, *al_tree = NULL;
+ int offset = 0;
+ gboolean dl_prm, tr_fir, tr_fin;
+ guint8 dl_len, dl_ctl, dl_func, tr_ctl, tr_seq;
+ guint fpos = 0;
+ gchar flags[64] = "<None>";
+ const gchar *func_code_str;
+ guint16 dl_dst, dl_src, dl_crc, calc_dl_crc;
+ guint8 *tmp = NULL, *tmp_ptr;
+ guint8 data_len;
+ gboolean crc_OK = FALSE;
+ tvbuff_t *al_tvb = NULL;
+ guint i;
+ static guint seq_number = 0;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNP 3.0");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ dl_len = tvb_get_guint8(tvb, DNP3_DL_LEN_OFFS);
+ dl_ctl = tvb_get_guint8(tvb, DNP3_DL_CTL_OFFS);
+ dl_dst = tvb_get_letohs(tvb, DNP3_DL_DST_OFFS);
+ dl_src = tvb_get_letohs(tvb, DNP3_DL_SRC_OFFS);
+ dl_func = dl_ctl & DNP3_CTL_FUNC;
+ dl_prm = dl_ctl & DNP3_CTL_PRM;
+ func_code_str = val_to_str(dl_func, dl_prm ? dnp3_ctl_func_pri_vals : dnp3_ctl_func_sec_vals,
+ "Unknown function (0x%02x)");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "len=%d, from %d to %d, %s",
+ dl_len, dl_src, dl_dst, func_code_str);
+
+ if (tree) {
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_dnp3, tvb, offset, -1, FALSE);
+ dnp3_tree = proto_item_add_subtree(ti, ett_dnp3);
+
+ /* format up the text representation of the flags and function code */
+ fpos = flags_to_str(dl_ctl, dl_prm ? dnp3_ctl_flags_pri_vals : dnp3_ctl_flags_sec_vals, flags);
+ if (fpos) {
+ strcpy(&flags[fpos], ", ");
+ fpos += 2;
+ }
+ strcpy(&flags[fpos], func_code_str);
+ fpos += strlen(func_code_str);
+ flags[fpos] = '\0';
+
+ /* create subtree for data link layer */
+ tdl = proto_tree_add_text(dnp3_tree, tvb, offset, DNP_HDR_LEN,
+ "Data Link Layer, Len: %d, From: %d, To: %d, %s",
+ dl_len, dl_src, dl_dst, flags);
+ dl_tree = proto_item_add_subtree(tdl, ett_dnp3_dl);
+
+ /* start bytes */
+ proto_tree_add_item(dl_tree, hf_dnp3_start, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* add length field */
+ proto_tree_add_item(dl_tree, hf_dnp3_len, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* add control byte subtree */
+ tc = proto_tree_add_uint_format(dl_tree, hf_dnp3_ctl, tvb, offset, 1, dl_ctl,
+ "Control: 0x%02x (%s)", dl_ctl, flags);
+ field_tree = proto_item_add_subtree(tc, ett_dnp3_dl_ctl);
+
+ if (dl_prm) {
+ proto_tree_add_boolean(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, dl_ctl);
+ proto_tree_add_boolean(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, dl_ctl);
+ proto_tree_add_boolean(field_tree, hf_dnp3_ctl_fcb, tvb, offset, 1, dl_ctl);
+ proto_tree_add_boolean(field_tree, hf_dnp3_ctl_fcv, tvb, offset, 1, dl_ctl);
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_prifunc, tvb, offset, 1, FALSE);
+ }
+ else {
+ proto_tree_add_boolean(field_tree, hf_dnp3_ctl_dir, tvb, offset, 1, dl_ctl);
+ proto_tree_add_boolean(field_tree, hf_dnp3_ctl_prm, tvb, offset, 1, dl_ctl);
+ proto_tree_add_boolean(field_tree, hf_dnp3_ctl_dfc, tvb, offset, 1, dl_ctl);
+ proto_tree_add_item(field_tree, hf_dnp3_ctl_secfunc, tvb, offset, 1, FALSE);
+ }
+ offset += 1;
+
+ /* add destination and source addresses */
+ proto_tree_add_item(dl_tree, hf_dnp3_dst, tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(dl_tree, hf_dnp3_src, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* and header CRC */
+ dl_crc = tvb_get_letohs(tvb, offset);
+ calc_dl_crc = calculateCRC(tvb_get_ptr(tvb, 0, DNP_HDR_LEN - 2), DNP_HDR_LEN - 2);
+ if (dl_crc == calc_dl_crc)
+ proto_tree_add_uint_format(dl_tree, hf_dnp_hdr_CRC, tvb, offset, 2,
+ dl_crc, "CRC: 0x%04x (correct)", dl_crc);
+ else {
+ proto_tree_add_boolean_hidden(dl_tree, hf_dnp_hdr_CRC_bad, tvb,
+ offset, 2, TRUE);
+ proto_tree_add_uint_format(dl_tree, hf_dnp_hdr_CRC, tvb,
+ offset, 2, dl_crc, "CRC: 0x%04x (incorrect, should be 0x%04x)",
+ dl_crc, calc_dl_crc);
+ }
+ offset += 2;
+ }
+ else
+ offset += 10; /* No tree so correct offset */
+
+ /* get the transport layer byte */
+ tr_ctl = tvb_get_guint8(tvb, offset);
+ tr_seq = tr_ctl & DNP3_TR_SEQ;
+ tr_fir = tr_ctl & DNP3_TR_FIR;
+ tr_fin = tr_ctl & DNP3_TR_FIN;
+
+ if (tree) {
+ /* format up the text representation */
+ strcpy(flags, "<NONE>");
+
+ fpos = flags_to_str(tr_ctl, dnp3_tr_flags_vals, flags);
+ if (fpos) {
+ strcpy(&flags[fpos], ", ");
+ fpos += 2;
+ }
+ flags[fpos] = '\0';
+
+ tc = proto_tree_add_uint_format(dnp3_tree, hf_dnp3_tr_ctl, tvb, offset, 1, tr_ctl,
+ "Transport Layer: 0x%02x (%sSequence %d)", tr_ctl, flags, tr_seq);
+ tr_tree = proto_item_add_subtree(tc, ett_dnp3_tr_ctl);
+ proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fin, tvb, offset, 1, tr_ctl);
+ proto_tree_add_boolean(tr_tree, hf_dnp3_tr_fir, tvb, offset, 1, tr_ctl);
+ proto_tree_add_item(tr_tree, hf_dnp3_tr_seq, tvb, offset, 1, tr_ctl);
+ }
+
+ /* Allocate AL chunk tree */
+ if (tree != NULL) {
+ al_chunks = proto_tree_add_text(tr_tree, tvb, offset + 1, -1, "Application data chunks");
+ al_tree = proto_item_add_subtree(al_chunks, ett_dnp3_al_data);
+ }
+
+ /* extract the application layer data, validating the CRCs */
+
+ data_len = dl_len - 5;
+ tmp = g_malloc(data_len);
+ tmp_ptr = tmp;
+ i = 0;
+ while(data_len > 0) {
+ guint8 chk_size;
+ guint16 calc_crc, act_crc;
+ chk_size = MIN(data_len, AL_MAX_CHUNK_SIZE);
+ tvb_memcpy(tvb, tmp_ptr, offset, chk_size);
+ calc_crc = calculateCRC(tmp_ptr, chk_size);
+ offset += chk_size;
+ tmp_ptr += chk_size;
+ act_crc = tvb_get_letohs(tvb, offset);
+ offset += 2;
+ crc_OK = calc_crc == act_crc;
+ if (crc_OK)
+ {
+ if (tree)
+ proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size,
+ "Application Chunk %d Len: %d CRC 0x%04x",
+ i, chk_size, act_crc);
+ data_len -= chk_size;
+ }
+ else
+ {
+ if (tree)
+ proto_tree_add_text(al_tree, tvb, offset - (chk_size + 2), chk_size,
+ "Application Chunk %d Len: %d Bad CRC got 0x%04x expected 0x%04x",
+ i, chk_size, act_crc, calc_crc);
+ data_len = 0;
+ break;
+ }
+ i++;
+ }
+
+ /* if all crc OK, set up new tvb */
+ if (crc_OK) {
+ al_tvb = tvb_new_real_data(&tmp[1], tmp_ptr-tmp, tmp_ptr-tmp);
+ tvb_set_free_cb(al_tvb, g_free);
+ tvb_set_child_real_data_tvbuff(tvb, al_tvb);
+
+ /* Check for fragmented packet */
+ if (! (tr_fir && tr_fin)) {
+ /* A fragmented packet */
+
+ fragment_data *fd_head;
+
+ /* if first fragment, update sequence id */
+ if (tr_fir) seq_number++;
+
+ /*
+ * If we've already seen this frame, look it up in the
+ * table of reassembled packets, otherwise add it to
+ * whatever reassembly is in progress, if any, and see
+ * if it's done.
+ */
+ fd_head = fragment_add_seq_check(al_tvb, 0, pinfo, seq_number,
+ al_fragment_table,
+ al_reassembled_table,
+ tr_seq,
+ tvb_reported_length(al_tvb),
+ !tr_fin);
+ if (fd_head != NULL) {
+ /* We have the complete payload */
+ al_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
+ tvb_set_child_real_data_tvbuff(tvb, al_tvb);
+ add_new_data_source(pinfo, al_tvb, "Reassembled DNP 3.0 Application Layer message");
+
+ if (tree)
+ /* Show all fragments. */
+ show_fragment_seq_tree(fd_head, &frag_items, tr_tree, pinfo, al_tvb);
+ }
+ else {
+ /* We don't have the complete reassembled payload. */
+ al_tvb = NULL;
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO,
+ " (Application Layer Message unreassembled)");
+ }
+ }
+ else {
+ /* No reassembly required */
+ add_new_data_source(pinfo, al_tvb, "DNP 3.0 Application Layer message");
+ }
+ }
+ else if (tree)
+ proto_tree_add_text(dnp3_tree, tvb, 11, -1,
+ "Application tvb allocation failed %d chunks", i);
+
+ if (!al_tvb && tmp) g_free(tmp);
+
+ if (al_tvb)
+ dissect_dnp3_al(al_tvb, pinfo, dnp3_tree);
+}
+
+static void
+al_defragment_init(void)
+{
+ fragment_table_init(&al_fragment_table);
+ reassembled_table_init(&al_reassembled_table);
+}
+
+/* Register the protocol with Ethereal */
+
+void
+proto_register_dnp3(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_dnp3_start,
+ { "Start Bytes", "dnp3.start", FT_UINT16, BASE_HEX, NULL, 0x0, "Start Bytes", HFILL }},
+
+ { &hf_dnp3_len,
+ { "Length", "dnp3.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Frame Data Length", HFILL }},
+
+ { &hf_dnp3_ctl,
+ { "Control", "dnp3.ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "Frame Control Byte", HFILL }},
+
+ { &hf_dnp3_ctl_prifunc,
+ { "Control Function Code", "dnp3.ctl.prifunc", FT_UINT8, BASE_DEC,
+ VALS(dnp3_ctl_func_pri_vals), DNP3_CTL_FUNC, "Frame Control Function Code", HFILL }},
+
+ { &hf_dnp3_ctl_secfunc,
+ { "Control Function Code", "dnp3.ctl.secfunc", FT_UINT8, BASE_DEC,
+ VALS(dnp3_ctl_func_sec_vals), DNP3_CTL_FUNC, "Frame Control Function Code", HFILL }},
+
+ { &hf_dnp3_ctl_dir,
+ { "Direction", "dnp3.ctl.dir", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_CTL_DIR, "", HFILL }},
+
+ { &hf_dnp3_ctl_prm,
+ { "Primary", "dnp3.ctl.prm", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_CTL_PRM, "", HFILL }},
+
+ { &hf_dnp3_ctl_fcb,
+ { "Frame Count Bit", "dnp3.ctl.fcb", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_CTL_FCB, "", HFILL }},
+
+ { &hf_dnp3_ctl_fcv,
+ { "Frame Count Valid", "dnp3.ctl.fcv", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_CTL_FCV, "", HFILL }},
+
+ { &hf_dnp3_ctl_dfc,
+ { "Data Flow Control", "dnp3.ctl.dfc", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_CTL_DFC, "", HFILL }},
+
+ { &hf_dnp3_dst,
+ { "Destination", "dnp3.dst", FT_UINT16, BASE_DEC, NULL, 0x0, "Destination Address", HFILL }},
+
+ { &hf_dnp3_src,
+ { "Source", "dnp3.src", FT_UINT16, BASE_DEC, NULL, 0x0, "Source Address", HFILL }},
+
+ { &hf_dnp_hdr_CRC,
+ { "CRC", "dnp.hdr.CRC", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_dnp_hdr_CRC_bad,
+ { "Bad CRC", "dnp.hdr.CRC_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_dnp3_tr_ctl,
+ { "Transport Control", "dnp3.tr.ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "Tranport Layer Control Byte", HFILL }},
+
+ { &hf_dnp3_tr_fin,
+ { "Final", "dnp3.tr.fin", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_TR_FIN, "", HFILL }},
+
+ { &hf_dnp3_tr_fir,
+ { "First", "dnp3.tr.fir", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_TR_FIR, "", HFILL }},
+
+ { &hf_dnp3_tr_seq,
+ { "Sequence", "dnp3.tr.seq", FT_UINT8, BASE_DEC, NULL, DNP3_TR_SEQ, "Frame Sequence Number", HFILL }},
+
+ { &hf_dnp3_al_ctl,
+ { "Application Control", "dnp3.al.ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "Application Layer Control Byte", HFILL }},
+
+ { &hf_dnp3_al_fir,
+ { "First", "dnp3.al.fir", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_AL_FIR, "", HFILL }},
+
+ { &hf_dnp3_al_fin,
+ { "Final", "dnp3.al.fin", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_AL_FIN, "", HFILL }},
+
+ { &hf_dnp3_al_con,
+ { "Confirm", "dnp3.al.con", FT_BOOLEAN, 8, TFS(&flags_set_truth), DNP3_AL_CON, "", HFILL }},
+
+ { &hf_dnp3_al_seq,
+ { "Sequence", "dnp3.al.seq", FT_UINT8, BASE_DEC, NULL, DNP3_AL_SEQ, "Frame Sequence Number", HFILL }},
+
+ { &hf_dnp3_al_func,
+ { "Application Layer Function Code", "dnp3.al.func", FT_UINT8, BASE_DEC,
+ VALS(dnp3_al_func_vals), DNP3_AL_FUNC, "Application Function Code", HFILL }},
+
+ { &hf_fragment,
+ { "DNP 3.0 AL Fragment", "al.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "DNP 3.0 Application Layer Fragment", HFILL }},
+
+ { &hf_fragments,
+ { "DNP 3.0 AL Fragments", "al.fragments", FT_NONE, BASE_NONE, NULL, 0x0, "DNP 3.0 Application Layer Fragments", HFILL }},
+
+ { &hf_fragment_overlap,
+ { "Fragment overlap", "al.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "al.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_fragment_multiple_tails,
+ { "Multiple tail fragments found", "al.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_fragment_too_long_fragment,
+ { "Fragment too long", "al.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+
+ { &hf_fragment_error,
+ { "Defragmentation error", "al.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }},
+ { &hf_fragment_reassembled_in,
+ { "Reassembled PDU In Frame", "al.fragment.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This PDU is reassembled in this frame", HFILL }}
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_dnp3,
+ &ett_dnp3_dl,
+ &ett_dnp3_dl_ctl,
+ &ett_dnp3_tr_ctl,
+ &ett_dnp3_al_data,
+ &ett_dnp3_al,
+ &ett_dnp3_al_ctl,
+ &ett_fragment,
+ &ett_fragments
+ };
+
+/* Register the protocol name and description */
+ proto_dnp3 = proto_register_protocol("Distributed Network Protocol 3.0",
+ "DNP 3.0", "dnp3");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_dnp3, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ al_defragment_init();
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_dnp3(void)
+{
+ dissector_handle_t dnp3_handle;
+
+ dnp3_handle = create_dissector_handle(dissect_dnp3, proto_dnp3);
+ dissector_add("tcp.port", TCP_PORT_DNP, dnp3_handle);
+}
diff --git a/epan/dissectors/packet-dns.c b/epan/dissectors/packet-dns.c
new file mode 100644
index 0000000000..bf23288f13
--- /dev/null
+++ b/epan/dissectors/packet-dns.c
@@ -0,0 +1,2513 @@
+/* packet-dns.c
+ * Routines for DNS packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <memory.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <glib.h>
+#include <epan/ipv6-utils.h>
+#include <epan/packet.h>
+#include "ipproto.h"
+#include <epan/resolv.h>
+#include "packet-dns.h"
+#include "packet-tcp.h"
+#include "prefs.h"
+
+static int proto_dns = -1;
+static int hf_dns_length = -1;
+static int hf_dns_flags = -1;
+static int hf_dns_flags_response = -1;
+static int hf_dns_flags_opcode = -1;
+static int hf_dns_flags_authoritative = -1;
+static int hf_dns_flags_truncated = -1;
+static int hf_dns_flags_recdesired = -1;
+static int hf_dns_flags_recavail = -1;
+static int hf_dns_flags_z = -1;
+static int hf_dns_flags_authenticated = -1;
+static int hf_dns_flags_checkdisable = -1;
+static int hf_dns_flags_rcode = -1;
+static int hf_dns_transaction_id = -1;
+static int hf_dns_count_questions = -1;
+static int hf_dns_count_answers = -1;
+static int hf_dns_count_auth_rr = -1;
+static int hf_dns_count_add_rr = -1;
+
+static gint ett_dns = -1;
+static gint ett_dns_qd = -1;
+static gint ett_dns_rr = -1;
+static gint ett_dns_qry = -1;
+static gint ett_dns_ans = -1;
+static gint ett_dns_flags = -1;
+static gint ett_t_key_flags = -1;
+static gint ett_t_key = -1;
+
+/* desegmentation of DNS over TCP */
+static gboolean dns_desegment = TRUE;
+
+/* Dissector handle for GSSAPI */
+static dissector_handle_t gssapi_handle;
+
+/* DNS structs and definitions */
+
+/* Ports used for DNS. */
+#define UDP_PORT_DNS 53
+#define TCP_PORT_DNS 53
+#define UDP_PORT_MDNS 5353
+#define TCP_PORT_MDNS 5353
+
+/* Offsets of fields in the DNS header. */
+#define DNS_ID 0
+#define DNS_FLAGS 2
+#define DNS_QUEST 4
+#define DNS_ANS 6
+#define DNS_AUTH 8
+#define DNS_ADD 10
+
+/* Length of DNS header. */
+#define DNS_HDRLEN 12
+
+/* type values */
+#define T_A 1 /* host address */
+#define T_NS 2 /* authoritative name server */
+#define T_MD 3 /* mail destination (obsolete) */
+#define T_MF 4 /* mail forwarder (obsolete) */
+#define T_CNAME 5 /* canonical name */
+#define T_SOA 6 /* start of authority zone */
+#define T_MB 7 /* mailbox domain name (experimental) */
+#define T_MG 8 /* mail group member (experimental) */
+#define T_MR 9 /* mail rename domain name (experimental) */
+#define T_NULL 10 /* null RR (experimental) */
+#define T_WKS 11 /* well known service */
+#define T_PTR 12 /* domain name pointer */
+#define T_HINFO 13 /* host information */
+#define T_MINFO 14 /* mailbox or mail list information */
+#define T_MX 15 /* mail routing information */
+#define T_TXT 16 /* text strings */
+#define T_RP 17 /* responsible person (RFC 1183) */
+#define T_AFSDB 18 /* AFS data base location (RFC 1183) */
+#define T_X25 19 /* X.25 address (RFC 1183) */
+#define T_ISDN 20 /* ISDN address (RFC 1183) */
+#define T_RT 21 /* route-through (RFC 1183) */
+#define T_NSAP 22 /* OSI NSAP (RFC 1706) */
+#define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
+#define T_SIG 24 /* digital signature (RFC 2535) */
+#define T_KEY 25 /* public key (RFC 2535) */
+#define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
+#define T_GPOS 27 /* geographical position (RFC 1712) */
+#define T_AAAA 28 /* IPv6 address (RFC 1886) */
+#define T_LOC 29 /* geographical location (RFC 1876) */
+#define T_NXT 30 /* "next" name (RFC 2535) */
+#define T_EID 31 /* ??? (Nimrod?) */
+#define T_NIMLOC 32 /* ??? (Nimrod?) */
+#define T_SRV 33 /* service location (RFC 2052) */
+#define T_ATMA 34 /* ??? */
+#define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
+#define T_KX 36 /* Key Exchange (RFC 2230) */
+#define T_CERT 37 /* Certificate (RFC 2538) */
+#define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
+#define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
+#define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
+#define T_DS 43 /* Delegation Signature(RFC 3658) */
+#define T_RRSIG 46 /* future RFC 2535bis */
+#define T_NSEC 47 /* future RFC 2535bis */
+#define T_DNSKEY 48 /* future RFC 2535bis */
+#define T_TKEY 249 /* Transaction Key (RFC 2930) */
+#define T_TSIG 250 /* Transaction Signature (RFC 2845) */
+#define T_WINS 65281 /* Microsoft's WINS RR */
+#define T_WINS_R 65282 /* Microsoft's WINS-R RR */
+
+/* Class values */
+#define C_IN 1 /* the Internet */
+#define C_CS 2 /* CSNET (obsolete) */
+#define C_CH 3 /* CHAOS */
+#define C_HS 4 /* Hesiod */
+#define C_NONE 254 /* none */
+#define C_ANY 255 /* any */
+#define C_FLUSH (1<<15) /* High bit is set for MDNS cache flush */
+
+/* Bit fields in the flags */
+#define F_RESPONSE (1<<15) /* packet is response */
+#define F_OPCODE (0xF<<11) /* query opcode */
+#define OPCODE_SHIFT 11
+#define F_AUTHORITATIVE (1<<10) /* response is authoritative */
+#define F_TRUNCATED (1<<9) /* response is truncated */
+#define F_RECDESIRED (1<<8) /* recursion desired */
+#define F_RECAVAIL (1<<7) /* recursion available */
+#define F_Z (1<<6) /* Z */
+#define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
+#define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
+#define F_RCODE (0xF<<0) /* reply code */
+
+static const true_false_string tfs_flags_response = {
+ "Message is a response",
+ "Message is a query"
+};
+
+static const true_false_string tfs_flags_authoritative = {
+ "Server is an authority for domain",
+ "Server is not an authority for domain"
+};
+
+static const true_false_string tfs_flags_truncated = {
+ "Message is truncated",
+ "Message is not truncated"
+};
+
+static const true_false_string tfs_flags_recdesired = {
+ "Do query recursively",
+ "Don't do query recursively"
+};
+
+static const true_false_string tfs_flags_recavail = {
+ "Server can do recursive queries",
+ "Server can't do recursive queries"
+};
+
+static const true_false_string tfs_flags_z = {
+ "reserved - incorrect!",
+ "reserved (0)"
+};
+
+static const true_false_string tfs_flags_authenticated = {
+ "Answer/authority portion was authenticated by the server",
+ "Answer/authority portion was not authenticated by the server"
+};
+
+static const true_false_string tfs_flags_checkdisable = {
+ "Non-authenticated data is acceptable",
+ "Non-authenticated data is unacceptable"
+};
+
+/* Opcodes */
+#define OPCODE_QUERY 0 /* standard query */
+#define OPCODE_IQUERY 1 /* inverse query */
+#define OPCODE_STATUS 2 /* server status request */
+#define OPCODE_NOTIFY 4 /* zone change notification */
+#define OPCODE_UPDATE 5 /* dynamic update */
+
+static const value_string opcode_vals[] = {
+ { OPCODE_QUERY, "Standard query" },
+ { OPCODE_IQUERY, "Inverse query" },
+ { OPCODE_STATUS, "Server status request" },
+ { OPCODE_NOTIFY, "Zone change notification" },
+ { OPCODE_UPDATE, "Dynamic update" },
+ { 0, NULL } };
+
+/* Reply codes */
+#define RCODE_NOERROR 0
+#define RCODE_FORMERR 1
+#define RCODE_SERVFAIL 2
+#define RCODE_NXDOMAIN 3
+#define RCODE_NOTIMPL 4
+#define RCODE_REFUSED 5
+#define RCODE_YXDOMAIN 6
+#define RCODE_YXRRSET 7
+#define RCODE_NXRRSET 8
+#define RCODE_NOTAUTH 9
+#define RCODE_NOTZONE 10
+
+static const value_string rcode_vals[] = {
+ { RCODE_NOERROR, "No error" },
+ { RCODE_FORMERR, "Format error" },
+ { RCODE_SERVFAIL, "Server failure" },
+ { RCODE_NXDOMAIN, "No such name" },
+ { RCODE_NOTIMPL, "Not implemented" },
+ { RCODE_REFUSED, "Refused" },
+ { RCODE_YXDOMAIN, "Name exists" },
+ { RCODE_YXRRSET, "RRset exists" },
+ { RCODE_NXRRSET, "RRset does not exist" },
+ { RCODE_NOTAUTH, "Not authoritative" },
+ { RCODE_NOTZONE, "Name out of zone" },
+ { 0, NULL } };
+
+/* TSIG/TKEY extended errors */
+#define TSIGERROR_BADSIG (16)
+#define TSIGERROR_BADKEY (17)
+#define TSIGERROR_BADTIME (18)
+#define TSIGERROR_BADMODE (19)
+#define TSIGERROR_BADNAME (20)
+#define TSIGERROR_BADALG (21)
+
+static const value_string tsigerror_vals[] = {
+ { TSIGERROR_BADSIG, "Bad signature" },
+ { TSIGERROR_BADKEY, "Bad key" },
+ { TSIGERROR_BADTIME, "Bad time failure" },
+ { TSIGERROR_BADMODE, "Bad mode such name" },
+ { TSIGERROR_BADNAME, "Bad name implemented" },
+ { TSIGERROR_BADALG, "Bad algorithm" },
+ { 0, NULL } };
+
+#define TKEYMODE_SERVERASSIGNED (1)
+#define TKEYMODE_DIFFIEHELLMAN (2)
+#define TKEYMODE_GSSAPI (3)
+#define TKEYMODE_RESOLVERASSIGNED (4)
+#define TKEYMODE_DELETE (5)
+
+#define TDSDIGEST_RESERVED (0)
+#define TDSDIGEST_SHA1 (1)
+
+/* See RFC 1035 for all RR types for which no RFC is listed, except for
+ the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
+ which one should look at
+
+http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
+
+ and
+
+http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
+
+ which discuss them to some extent. */
+static char *
+dns_type_name (guint type)
+{
+ char *type_names[] = {
+ "unused",
+ "A",
+ "NS",
+ "MD",
+ "MF",
+ "CNAME",
+ "SOA",
+ "MB",
+ "MG",
+ "MR",
+ "NULL",
+ "WKS",
+ "PTR",
+ "HINFO",
+ "MINFO",
+ "MX",
+ "TXT",
+ "RP", /* RFC 1183 */
+ "AFSDB", /* RFC 1183 */
+ "X25", /* RFC 1183 */
+ "ISDN", /* RFC 1183 */
+ "RT", /* RFC 1183 */
+ "NSAP", /* RFC 1706 */
+ "NSAP-PTR", /* RFC 1348 */
+ "SIG", /* RFC 2535 */
+ "KEY", /* RFC 2535 */
+ "PX", /* RFC 1664 */
+ "GPOS", /* RFC 1712 */
+ "AAAA", /* RFC 1886 */
+ "LOC", /* RFC 1876 */
+ "NXT", /* RFC 2535 */
+ "EID",
+ "NIMLOC",
+ "SRV", /* RFC 2052 */
+ "ATMA",
+ "NAPTR", /* RFC 2168 */
+ "KX", /* RFC 2230 */
+ "CERT", /* RFC 2538 */
+ "A6", /* RFC 2874 */
+ "DNAME", /* RFC 2672 */
+ NULL,
+ "OPT", /* RFC 2671 */
+ NULL,
+ "DS", /* RFC 3658 */
+ NULL,
+ NULL,
+ "RRSIG", /* future RFC 2535bis */
+ "NSEC", /* future RFC 2535bis */
+ "DNSKEY" /* future RFC 2535bis */
+ };
+
+ if (type < sizeof(type_names)/sizeof(type_names[0]))
+ return type_names[type] ? type_names[type] : "unknown";
+
+ /* special cases */
+ switch (type)
+ {
+ /* non standard */
+ case 100:
+ return "UINFO";
+ case 101:
+ return "UID";
+ case 102:
+ return "GID";
+ case 103:
+ return "UNSPEC";
+ case T_WINS:
+ return "WINS";
+ case T_WINS_R:
+ return "WINS-R";
+
+ /* meta */
+ case T_TKEY:
+ return "TKEY";
+ case T_TSIG:
+ return "TSIG";
+
+ /* queries */
+ case 251:
+ return "IXFR"; /* RFC 1995 */
+ case 252:
+ return "AXFR";
+ case 253:
+ return "MAILB";
+ case 254:
+ return "MAILA";
+ case 255:
+ return "ANY";
+
+ }
+
+ return "unknown";
+}
+
+
+static char *
+dns_long_type_name (guint type)
+{
+ char *type_names[] = {
+ "unused",
+ "Host address",
+ "Authoritative name server",
+ "Mail destination",
+ "Mail forwarder",
+ "Canonical name for an alias",
+ "Start of zone of authority",
+ "Mailbox domain name",
+ "Mail group member",
+ "Mail rename domain name",
+ "Null resource record",
+ "Well-known service description",
+ "Domain name pointer",
+ "Host information",
+ "Mailbox or mail list information",
+ "Mail exchange",
+ "Text strings",
+ "Responsible person", /* RFC 1183 */
+ "AFS data base location", /* RFC 1183 */
+ "X.25 address", /* RFC 1183 */
+ "ISDN number", /* RFC 1183 */
+ "Route through", /* RFC 1183 */
+ "OSI NSAP", /* RFC 1706 */
+ "OSI NSAP name pointer", /* RFC 1348 */
+ "Signature", /* RFC 2535 */
+ "Public key", /* RFC 2535 */
+ "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
+ "Geographical position", /* RFC 1712 */
+ "IPv6 address", /* RFC 1886 */
+ "Location", /* RFC 1876 */
+ "Next", /* RFC 2535 */
+ "EID",
+ "NIMLOC",
+ "Service location", /* RFC 2052 */
+ "ATMA",
+ "Naming authority pointer", /* RFC 2168 */
+ "Key Exchange", /* RFC 2230 */
+ "Certificate", /* RFC 2538 */
+ "IPv6 address with indirection", /* RFC 2874 */
+ "Non-terminal DNS name redirection", /* RFC 2672 */
+ NULL,
+ "EDNS0 option", /* RFC 2671 */
+ NULL,
+ "Delegation Signer", /* RFC 3658 */
+ NULL,
+ NULL,
+ "RR signature", /* future RFC 2535bis */
+ "Next secured", /* future RFC 2535bis */
+ "DNS public key" /* future RFC 2535bis */
+ };
+ static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%u)" */
+
+ if (type < sizeof(type_names)/sizeof(type_names[0]))
+ return type_names[type] ? type_names[type] : "unknown";
+
+ /* special cases */
+ switch (type)
+ {
+ /* non standard */
+ case 100:
+ return "UINFO";
+ case 101:
+ return "UID";
+ case 102:
+ return "GID";
+ case 103:
+ return "UNSPEC";
+ case T_WINS:
+ return "WINS";
+ case T_WINS_R:
+ return "WINS-R";
+
+ /* meta */
+ case T_TKEY:
+ return "Transaction Key";
+ case T_TSIG:
+ return "Transaction Signature";
+
+ /* queries */
+ case 251:
+ return "Request for incremental zone transfer"; /* RFC 1995 */
+ case 252:
+ return "Request for full zone transfer";
+ case 253:
+ return "Request for mailbox-related records";
+ case 254:
+ return "Request for mail agent resource records";
+ case 255:
+ return "Request for all records";
+ }
+
+ sprintf(unkbuf, "Unknown RR type (%u)", type);
+ return unkbuf;
+}
+
+
+char *
+dns_class_name(int class)
+{
+ char *class_name;
+
+ switch (class) {
+ case C_IN:
+ class_name = "inet";
+ break;
+ case ( C_IN | C_FLUSH ):
+ class_name = "inet (data flush)";
+ break;
+ case C_CS:
+ class_name = "csnet";
+ break;
+ case C_CH:
+ class_name = "chaos";
+ break;
+ case C_HS:
+ class_name = "hesiod";
+ break;
+ case C_NONE:
+ class_name = "none";
+ break;
+ case C_ANY:
+ class_name = "any";
+ break;
+ default:
+ class_name = "unknown";
+ }
+
+ return class_name;
+}
+
+int
+get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
+ char *name, int maxname)
+{
+ int start_offset = offset;
+ char *np = name;
+ int len = -1;
+ int chars_processed = 0;
+ int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
+ int component_len;
+ int indir_offset;
+
+ const int min_len = 1; /* Minimum length of encoded name (for root) */
+ /* If we're about to return a value (probably negative) which is less
+ * than the minimum length, we're looking at bad data and we're liable
+ * to put the dissector into a loop. Instead we throw an exception */
+
+ maxname--; /* reserve space for the trailing '\0' */
+ for (;;) {
+ component_len = tvb_get_guint8(tvb, offset);
+ offset++;
+ if (component_len == 0)
+ break;
+ chars_processed++;
+ switch (component_len & 0xc0) {
+
+ case 0x00:
+ /* Label */
+ if (np != name) {
+ /* Not the first component - put in a '.'. */
+ if (maxname > 0) {
+ *np++ = '.';
+ maxname--;
+ }
+ }
+ while (component_len > 0) {
+ if (maxname > 0) {
+ *np++ = tvb_get_guint8(tvb, offset);
+ maxname--;
+ }
+ component_len--;
+ offset++;
+ chars_processed++;
+ }
+ break;
+
+ case 0x40:
+ /* Extended label (RFC 2673) */
+ switch (component_len & 0x3f) {
+
+ case 0x01:
+ /* Bitstring label */
+ {
+ int bit_count;
+ int label_len;
+ int print_len;
+
+ bit_count = tvb_get_guint8(tvb, offset);
+ offset++;
+ label_len = (bit_count - 1) / 8 + 1;
+
+ if (maxname > 0) {
+ print_len = snprintf(np, maxname + 1, "\\[x");
+ if (print_len != -1 && print_len <= maxname) {
+ /* Some versions of snprintf return -1 if they'd truncate
+ the output. Others return <buf_size> or greater. */
+ np += print_len;
+ maxname -= print_len;
+ } else {
+ /* Nothing printed, as there's no room.
+ Suppress all subsequent printing. */
+ maxname = 0;
+ }
+ }
+ while(label_len--) {
+ if (maxname > 0) {
+ print_len = snprintf(np, maxname + 1, "%02x",
+ tvb_get_guint8(tvb, offset));
+ if (print_len != -1 && print_len <= maxname) {
+ /* Some versions of snprintf return -1 if they'd truncate
+ the output. Others return <buf_size> or greater. */
+ np += print_len;
+ maxname -= print_len;
+ } else {
+ /* Nothing printed, as there's no room.
+ Suppress all subsequent printing. */
+ maxname = 0;
+ }
+ }
+ offset++;
+ }
+ if (maxname > 0) {
+ print_len = snprintf(np, maxname + 1, "/%d]", bit_count);
+ if (print_len != -1 && print_len <= maxname) {
+ /* Some versions of snprintf return -1 if they'd truncate
+ the output. Others return <buf_size> or greater. */
+ np += print_len;
+ maxname -= print_len;
+ } else {
+ /* Nothing printed, as there's no room.
+ Suppress all subsequent printing. */
+ maxname = 0;
+ }
+ }
+ }
+ break;
+
+ default:
+ strcpy(name, "<Unknown extended label>");
+ /* Parsing will propably fail from here on, since the */
+ /* label length is unknown... */
+ len = offset - start_offset;
+ if (len < min_len)
+ THROW(ReportedBoundsError);
+ return len;
+ }
+ break;
+
+ case 0x80:
+ THROW(ReportedBoundsError);
+
+ case 0xc0:
+ /* Pointer. */
+ indir_offset = dns_data_offset +
+ (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
+ offset++;
+ chars_processed++;
+
+ /* If "len" is negative, we are still working on the original name,
+ not something pointed to by a pointer, and so we should set "len"
+ to the length of the original name. */
+ if (len < 0)
+ len = offset - start_offset;
+
+ /* If we've looked at every character in the message, this pointer
+ will make us look at some character again, which means we're
+ looping. */
+ if (chars_processed >= data_size) {
+ strcpy(name, "<Name contains a pointer that loops>");
+ if (len < min_len)
+ THROW(ReportedBoundsError);
+ return len;
+ }
+
+ offset = indir_offset;
+ break; /* now continue processing from there */
+ }
+ }
+
+ *np = '\0';
+ /* If "len" is negative, we haven't seen a pointer, and thus haven't
+ set the length, so set it. */
+ if (len < 0)
+ len = offset - start_offset;
+ /* Zero-length name means "root server" */
+ if (*name == '\0')
+ strcpy(name, "<Root>");
+ if (len < min_len)
+ THROW(ReportedBoundsError);
+ return len;
+}
+
+
+static int
+get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
+ char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
+{
+ int len;
+ int name_len;
+ int type;
+ int class;
+ char name[MAXDNAME];
+ int start_offset = offset;
+
+ name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
+ offset += name_len;
+
+ type = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+
+ class = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+
+ strcpy (name_ret, name);
+ *type_ret = type;
+ *class_ret = class;
+ *name_len_ret = name_len;
+
+ len = offset - start_offset;
+ return len;
+}
+
+static double
+rfc1867_size(tvbuff_t *tvb, int offset)
+{
+ guint8 val;
+ double size;
+ guint32 exponent;
+
+ val = tvb_get_guint8(tvb, offset);
+ size = (val & 0xF0) >> 4;
+ exponent = (val & 0x0F);
+ while (exponent != 0) {
+ size *= 10;
+ exponent--;
+ }
+ return size / 100; /* return size in meters, not cm */
+}
+
+static char *
+rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
+{
+ guint32 angle;
+ char direction;
+ guint32 degrees, minutes, secs, tsecs;
+ /* "%u deg %u min %u.%03u sec %c" */
+ static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
+
+ angle = tvb_get_ntohl(tvb, offset);
+
+ if (angle < 0x80000000U) {
+ angle = 0x80000000U - angle;
+ direction = nsew[1];
+ } else {
+ angle = angle - 0x80000000U;
+ direction = nsew[0];
+ }
+ tsecs = angle % 1000;
+ angle = angle / 1000;
+ secs = angle % 60;
+ angle = angle / 60;
+ minutes = angle % 60;
+ degrees = angle / 60;
+ sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
+ tsecs, direction);
+ return buf;
+}
+
+static int
+dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
+ column_info *cinfo, proto_tree *dns_tree)
+{
+ int len;
+ char name[MAXDNAME];
+ int name_len;
+ int type;
+ int class;
+ char *class_name;
+ char *type_name;
+ char *long_type_name;
+ int data_offset;
+ int data_start;
+ proto_tree *q_tree;
+ proto_item *tq;
+
+ data_start = data_offset = offset;
+
+ len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
+ &type, &class);
+ data_offset += len;
+
+ type_name = dns_type_name(type);
+ class_name = dns_class_name(class);
+ long_type_name = dns_long_type_name(type);
+
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
+ if (dns_tree != NULL) {
+ tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s",
+ name, type_name, class_name);
+ q_tree = proto_item_add_subtree(tq, ett_dns_qd);
+
+ proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
+ offset += name_len;
+
+ proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
+ offset += 2;
+
+ proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
+ offset += 2;
+ }
+
+ return data_offset - data_start;
+}
+
+
+proto_tree *
+add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
+ const char *name, int namelen, const char *type_name, const char *class_name,
+ guint ttl, gushort data_len)
+{
+ proto_tree *rr_tree;
+
+ rr_tree = proto_item_add_subtree(trr, rr_type);
+ proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
+ offset += namelen;
+ proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
+ offset += 2;
+ proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
+ offset += 2;
+ proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
+ time_secs_to_str(ttl));
+ offset += 4;
+ proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
+ return rr_tree;
+}
+
+static proto_tree *
+add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
+ const char *name, int namelen, const char *type_name, int class,
+ guint ttl, gushort data_len)
+{
+ proto_tree *rr_tree, *Z_tree;
+ proto_item *Z_item = NULL;
+
+ rr_tree = proto_item_add_subtree(trr, rr_type);
+ proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
+ offset += namelen;
+ proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
+ offset += 2;
+ proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
+ class & 0xffff);
+ offset += 2;
+ proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
+ (ttl >> 24) & 0xff0);
+ offset++;
+ proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
+ (ttl >> 16) & 0xff);
+ offset++;
+ Z_item = proto_tree_add_text(rr_tree, tvb, offset, 2, "Z: 0x%x", ttl & 0xffff);
+ if (ttl & 0x8000) {
+ Z_tree = proto_item_add_subtree(Z_item, rr_type);
+ proto_tree_add_text(Z_tree, tvb, offset, 2, "Bit 0 (DO bit): 1 (Accepts DNSSEC security RRs)");
+ proto_tree_add_text(Z_tree, tvb, offset, 2, "Bits 1-15: 0x%x (reserved)", (ttl >> 17) & 0xff);
+ }
+ offset += 2;
+ proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
+ return rr_tree;
+}
+
+/*
+ * SIG, KEY, and CERT RR algorithms.
+ */
+#define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
+#define DNS_ALGO_DH 2 /* Diffie-Hellman */
+#define DNS_ALGO_DSA 3 /* DSA */
+#define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
+#define DNS_ALGO_RSASHA1 5 /* RSA/SHA1 */
+#define DNS_ALGO_HMACMD5 157 /* HMAC/MD5 */
+#define DNS_ALGO_INDIRECT 252 /* Indirect key */
+#define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
+#define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
+
+static const value_string algo_vals[] = {
+ { DNS_ALGO_RSAMD5, "RSA/MD5" },
+ { DNS_ALGO_DH, "Diffie-Hellman" },
+ { DNS_ALGO_DSA, "DSA" },
+ { DNS_ALGO_ECC, "Elliptic curve crypto" },
+ { DNS_ALGO_RSASHA1, "RSA/SHA1" },
+ { DNS_ALGO_HMACMD5, "HMAC/MD5" },
+ { DNS_ALGO_INDIRECT, "Indirect key" },
+ { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
+ { DNS_ALGO_PRIVATEOID, "Private, OID" },
+ { 0, NULL }
+};
+
+#define DNS_CERT_PGP 1 /* PGP */
+#define DNS_CERT_PKIX 2 /* PKIX */
+#define DNS_CERT_SPKI 3 /* SPKI */
+#define DNS_CERT_PRIVATEURI 253 /* Private, URI */
+#define DNS_CERT_PRIVATEOID 254 /* Private, OID */
+
+static const value_string cert_vals[] = {
+ { DNS_CERT_PGP, "PGP" },
+ { DNS_CERT_PKIX, "PKIX" },
+ { DNS_CERT_SPKI, "SPKI" },
+ { DNS_CERT_PRIVATEURI, "Private, URI" },
+ { DNS_CERT_PRIVATEOID, "Private, OID" },
+ { 0, NULL }
+};
+
+/**
+ * Compute the key id of a KEY RR depending of the algorithm used.
+ */
+static guint16
+compute_key_id(tvbuff_t *tvb, int offset, int size, guint8 algo)
+{
+ guint32 ac;
+ guint8 c1, c2;
+
+ g_assert(size >= 4);
+
+ switch( algo ) {
+ case DNS_ALGO_RSAMD5:
+ return (guint16)(tvb_get_guint8(tvb, offset + size - 3) << 8) + tvb_get_guint8( tvb, offset + size - 2 );
+ default:
+ for (ac = 0; size > 1; size -= 2, offset += 2) {
+ c1 = tvb_get_guint8( tvb, offset );
+ c2 = tvb_get_guint8( tvb, offset + 1 );
+ ac += (c1 << 8) + c2 ;
+ }
+ if (size > 0) {
+ c1 = tvb_get_guint8( tvb, offset );
+ ac += c1 << 8;
+ }
+ ac += (ac >> 16) & 0xffff;
+ return (guint16)(ac & 0xffff);
+ }
+}
+
+
+static int
+dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
+ column_info *cinfo, proto_tree *dns_tree, packet_info *pinfo)
+{
+ int len;
+ char name[MAXDNAME];
+ int name_len;
+ int type;
+ int class;
+ char *class_name;
+ char *type_name;
+ char *long_type_name;
+ int data_offset;
+ int cur_offset;
+ int data_start;
+ guint ttl;
+ gushort data_len;
+ proto_tree *rr_tree = NULL;
+ proto_item *trr = NULL;
+
+ data_start = data_offset = offset;
+ cur_offset = offset;
+
+ len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
+ &type, &class);
+ data_offset += len;
+ cur_offset += len;
+
+ type_name = dns_type_name(type);
+ class_name = dns_class_name(class);
+ long_type_name = dns_long_type_name(type);
+
+ ttl = tvb_get_ntohl(tvb, data_offset);
+ data_offset += 4;
+ cur_offset += 4;
+
+ data_len = tvb_get_ntohs(tvb, data_offset);
+ data_offset += 2;
+ cur_offset += 2;
+
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", type_name);
+ if (dns_tree != NULL) {
+ trr = proto_tree_add_text(dns_tree, tvb, offset,
+ (data_offset - data_start) + data_len,
+ "%s: type %s, class %s",
+ name, type_name, class_name);
+ if (type != T_OPT) {
+ rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
+ long_type_name, class_name, ttl, data_len);
+ } else {
+ rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
+ long_type_name, class, ttl, data_len);
+ }
+ }
+
+ switch (type) {
+
+ case T_A:
+ {
+ const guint8 *addr;
+ guint32 addr_int;
+
+ addr = tvb_get_ptr(tvb, cur_offset, 4);
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(addr));
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
+ ip_to_str(addr));
+ }
+ if ((class & 0x7f) == C_IN) {
+ memcpy(&addr_int, addr, sizeof(addr_int));
+ add_host_name(addr_int, name);
+ }
+ }
+ break;
+
+ case T_NS:
+ {
+ char ns_name[MAXDNAME];
+ int ns_name_len;
+
+ ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", ns_name);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", ns %s", ns_name);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
+ ns_name);
+ }
+ }
+ break;
+
+ case T_CNAME:
+ {
+ char cname[MAXDNAME];
+ int cname_len;
+
+ cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", cname);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", cname %s", cname);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
+ cname);
+ }
+ }
+ break;
+
+ case T_SOA:
+ {
+ char mname[MAXDNAME];
+ int mname_len;
+ char rname[MAXDNAME];
+ int rname_len;
+ guint32 serial;
+ guint32 refresh;
+ guint32 retry;
+ guint32 expire;
+ guint32 minimum;
+
+ mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", mname);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", mname %s", mname);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
+ mname);
+ cur_offset += mname_len;
+
+ rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
+ proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
+ rname);
+ cur_offset += rname_len;
+
+ serial = tvb_get_ntohl(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
+ serial);
+ cur_offset += 4;
+
+ refresh = tvb_get_ntohl(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
+ time_secs_to_str(refresh));
+ cur_offset += 4;
+
+ retry = tvb_get_ntohl(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
+ time_secs_to_str(retry));
+ cur_offset += 4;
+
+ expire = tvb_get_ntohl(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
+ time_secs_to_str(expire));
+ cur_offset += 4;
+
+ minimum = tvb_get_ntohl(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
+ time_secs_to_str(minimum));
+ }
+ }
+ break;
+
+ case T_PTR:
+ {
+ char pname[MAXDNAME];
+ int pname_len;
+
+ pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", pname);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", %s", pname);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
+ pname);
+ }
+ break;
+ }
+ break;
+
+ case T_WKS:
+ {
+ int rr_len = data_len;
+ const guint8 *wks_addr;
+ guint8 protocol;
+ guint8 bits;
+ int mask;
+ int port_num;
+ int i;
+ static GString *bitnames = NULL;
+
+ if (bitnames == NULL)
+ bitnames = g_string_sized_new(128);
+
+ if (rr_len < 4) {
+ if (dns_tree != NULL)
+ goto bad_rr;
+ break;
+ }
+ wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
+ ip_to_str(wks_addr));
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 1)
+ goto bad_rr;
+ protocol = tvb_get_guint8(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
+ ipprotostr(protocol));
+ cur_offset += 1;
+ rr_len -= 1;
+
+ port_num = 0;
+ while (rr_len != 0) {
+ bits = tvb_get_guint8(tvb, cur_offset);
+ if (bits != 0) {
+ mask = 1<<7;
+ g_string_truncate(bitnames, 0);
+ for (i = 0; i < 8; i++) {
+ if (bits & mask) {
+ if (bitnames->len != 0)
+ g_string_append(bitnames, ", ");
+ switch (protocol) {
+
+ case IP_PROTO_TCP:
+ g_string_append(bitnames, get_tcp_port(port_num));
+ break;
+
+ case IP_PROTO_UDP:
+ g_string_append(bitnames, get_udp_port(port_num));
+ break;
+
+ default:
+ g_string_sprintfa(bitnames, "%u", port_num);
+ break;
+ }
+ }
+ mask >>= 1;
+ port_num++;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
+ "Bits: 0x%02x (%s)", bits, bitnames->str);
+ } else
+ port_num += 8;
+ cur_offset += 1;
+ rr_len -= 1;
+ }
+ }
+ }
+ break;
+
+ case T_HINFO:
+ {
+ int cpu_offset;
+ int cpu_len;
+ const guint8 *cpu;
+ int os_offset;
+ int os_len;
+ const guint8 *os;
+
+ cpu_offset = cur_offset;
+ cpu_len = tvb_get_guint8(tvb, cpu_offset);
+ cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
+ os_offset = cpu_offset + 1 + cpu_len;
+ os_len = tvb_get_guint8(tvb, os_offset);
+ os = tvb_get_ptr(tvb, os_offset + 1, os_len);
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
+ os_len, os);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
+ cpu_len, cpu, os_len, os);
+ proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
+ cpu_len, cpu);
+ proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
+ os_len, os);
+ }
+ break;
+ }
+ break;
+
+ case T_MX:
+ {
+ guint16 preference = 0;
+ char mx_name[MAXDNAME];
+ int mx_name_len;
+
+ preference = tvb_get_ntohs(tvb, cur_offset);
+ mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %u %s", preference, mx_name);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", preference %u, mx %s",
+ preference, mx_name);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
+ proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
+ mx_name);
+ }
+ }
+ break;
+
+ case T_TXT:
+ {
+ int rr_len = data_len;
+ int txt_offset;
+ int txt_len;
+
+ if (dns_tree != NULL) {
+ txt_offset = cur_offset;
+ while (rr_len != 0) {
+ txt_len = tvb_get_guint8(tvb, txt_offset);
+ proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
+ "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
+ txt_offset += 1 + txt_len;
+ rr_len -= 1 + txt_len;
+ }
+ }
+ }
+ break;
+
+ case T_RRSIG:
+ case T_SIG:
+ {
+ int rr_len = data_len;
+ guint16 type_covered;
+ nstime_t nstime;
+ char signer_name[MAXDNAME];
+ int signer_name_len;
+
+ if (dns_tree != NULL) {
+ if (rr_len < 2)
+ goto bad_rr;
+ type_covered = tvb_get_ntohs(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
+ dns_type_name(type_covered),
+ dns_long_type_name(type_covered));
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (rr_len < 1)
+ goto bad_rr;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
+ val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
+ "Unknown (0x%02X)"));
+ cur_offset += 1;
+ rr_len -= 1;
+
+ if (rr_len < 1)
+ goto bad_rr;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
+ tvb_get_guint8(tvb, cur_offset));
+ cur_offset += 1;
+ rr_len -= 1;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
+ time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ nstime.secs = tvb_get_ntohl(tvb, cur_offset);
+ nstime.nsecs = 0;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
+ abs_time_to_str(&nstime));
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ nstime.secs = tvb_get_ntohl(tvb, cur_offset);
+ nstime.nsecs = 0;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
+ abs_time_to_str(&nstime));
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 2)
+ goto bad_rr;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Id of signing key(footprint): %u",
+ tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ rr_len -= 2;
+
+ signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
+ proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
+ "Signer's name: %s", signer_name);
+ cur_offset += signer_name_len;
+ rr_len -= signer_name_len;
+
+ if (rr_len != 0)
+ proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
+ }
+ }
+ break;
+
+ case T_DNSKEY:
+ case T_KEY:
+ {
+ int rr_len = data_len;
+ guint16 flags;
+ proto_item *tf;
+ proto_tree *flags_tree;
+ guint8 algo;
+ guint16 key_id;
+
+ if (dns_tree != NULL) {
+ if (rr_len < 2)
+ goto bad_rr;
+ flags = tvb_get_ntohs(tvb, cur_offset);
+ tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
+ flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
+ proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x8000,
+ 2*8, "Key prohibited for authentication",
+ "Key allowed for authentication"));
+ proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x4000,
+ 2*8, "Key prohibited for confidentiality",
+ "Key allowed for confidentiality"));
+ if ((flags & 0xC000) != 0xC000) {
+ /* We have a key */
+ proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x2000,
+ 2*8, "Key is experimental or optional",
+ "Key is required"));
+ proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0400,
+ 2*8, "Key is associated with a user",
+ "Key is not associated with a user"));
+ proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0200,
+ 2*8, "Key is associated with the named entity",
+ "Key is not associated with the named entity"));
+ proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0100,
+ 2*8, "This is the zone key for the specified zone",
+ "This is not a zone key"));
+ proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0080,
+ 2*8, "Key is valid for use with IPSEC",
+ "Key is not valid for use with IPSEC"));
+ proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0040,
+ 2*8, "Key is valid for use with MIME security multiparts",
+ "Key is not valid for use with MIME security multiparts"));
+ if( type != T_DNSKEY )
+ proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_numeric_bitfield(flags, 0x000F,
+ 2*8, "Signatory = %u"));
+ else proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x0001,
+ 2*8, "Key is a Key Signing Key",
+ "Key is a Zone Signing Key") );
+ }
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (rr_len < 1)
+ goto bad_rr;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
+ tvb_get_guint8(tvb, cur_offset));
+ cur_offset += 1;
+ rr_len -= 1;
+
+ if (rr_len < 1)
+ goto bad_rr;
+ algo = tvb_get_guint8(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
+ val_to_str(algo, algo_vals, "Unknown (0x%02X)"));
+ cur_offset += 1;
+ rr_len -= 1;
+
+ key_id = compute_key_id(tvb, cur_offset-4, rr_len+4, algo);
+ proto_tree_add_text(rr_tree, tvb, 0, 0, "Key id: %u", key_id);
+
+ if (rr_len != 0)
+ proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
+ }
+ }
+ break;
+
+ case T_AAAA:
+ {
+ const guint8 *addr6;
+
+ addr6 = tvb_get_ptr(tvb, cur_offset, 16);
+ if (cinfo != NULL) {
+ col_append_fstr(cinfo, COL_INFO, " %s",
+ ip6_to_str((const struct e_in6_addr *)addr6));
+ }
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", addr %s",
+ ip6_to_str((const struct e_in6_addr *)addr6));
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
+ ip6_to_str((const struct e_in6_addr *)addr6));
+ }
+ }
+ break;
+
+ case T_A6:
+ {
+ unsigned short pre_len;
+ unsigned short suf_len;
+ unsigned short suf_octet_count;
+ char pname[MAXDNAME];
+ int pname_len;
+ int a6_offset;
+ int suf_offset;
+ struct e_in6_addr suffix;
+
+ a6_offset = cur_offset;
+ pre_len = tvb_get_guint8(tvb, cur_offset);
+ cur_offset++;
+ suf_len = 128 - pre_len;
+ suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
+ /* Pad prefix */
+ for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
+ suffix.s6_addr8[suf_offset] = 0;
+ }
+ for (; suf_offset < 16; suf_offset++) {
+ suffix.s6_addr8[suf_offset] = tvb_get_guint8(tvb, cur_offset);
+ cur_offset++;
+ }
+
+ if (pre_len > 0) {
+ pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
+ pname, sizeof(pname));
+ } else {
+ strcpy(pname, "");
+ pname_len = 0;
+ }
+
+ if (cinfo != NULL) {
+ col_append_fstr(cinfo, COL_INFO, " %d %s %s",
+ pre_len,
+ ip6_to_str(&suffix),
+ pname);
+ }
+ if (dns_tree != NULL) {
+ proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
+ "Prefix len: %u", pre_len);
+ a6_offset++;
+ if (suf_len) {
+ proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
+ "Address suffix: %s",
+ ip6_to_str(&suffix));
+ a6_offset += suf_octet_count;
+ }
+ if (pre_len > 0) {
+ proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
+ "Prefix name: %s", pname);
+ }
+ proto_item_append_text(trr, ", addr %d %s %s",
+ pre_len,
+ ip6_to_str(&suffix),
+ pname);
+ }
+ }
+ break;
+
+ case T_DNAME:
+ {
+ char dname[MAXDNAME];
+ int dname_len;
+
+ dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
+ dname, sizeof(dname));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", dname);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", dname %s", dname);
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ dname_len, "Target name: %s", dname);
+ }
+ }
+ break;
+
+ case T_LOC:
+ {
+ guint8 version;
+
+ if (dns_tree != NULL) {
+ version = tvb_get_guint8(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
+ if (version == 0) {
+ /* Version 0, the only version RFC 1876 discusses. */
+ cur_offset++;
+
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
+ rfc1867_size(tvb, cur_offset));
+ cur_offset++;
+
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
+ rfc1867_size(tvb, cur_offset));
+ cur_offset++;
+
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
+ rfc1867_size(tvb, cur_offset));
+ cur_offset++;
+
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
+ rfc1867_angle(tvb, cur_offset, "NS"));
+ cur_offset += 4;
+
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
+ rfc1867_angle(tvb, cur_offset, "EW"));
+ cur_offset += 4;
+
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
+ (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
+ } else
+ proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
+ }
+ }
+ break;
+
+ case T_NSEC:
+ {
+ int rr_len = data_len;
+ char next_domain_name[MAXDNAME];
+ int next_domain_name_len;
+ int rr_type;
+ guint8 bits;
+ int mask, blockbase, blocksize;
+ int i;
+
+ next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
+ next_domain_name, sizeof(next_domain_name));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", next domain name %s",
+ next_domain_name);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
+ "Next domain name: %s", next_domain_name);
+ cur_offset += next_domain_name_len;
+ rr_len -= next_domain_name_len;
+ rr_type = 0;
+ while (rr_len != 0) {
+ blockbase = tvb_get_guint8(tvb, cur_offset);
+ blocksize = tvb_get_guint8(tvb, cur_offset + 1);
+ cur_offset += 2;
+ rr_len -= 2;
+ rr_type = blockbase * 256;
+ for( ; blocksize; blocksize-- ) {
+ bits = tvb_get_guint8(tvb, cur_offset);
+ mask = 1<<7;
+ for (i = 0; i < 8; i++) {
+ if (bits & mask) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
+ "RR type in bit map: %s (%s)",
+ dns_type_name(rr_type),
+ dns_long_type_name(rr_type));
+ }
+ mask >>= 1;
+ rr_type++;
+ }
+ cur_offset += 1;
+ rr_len -= 1;
+ }
+ }
+ }
+ }
+ break;
+
+ case T_NXT:
+ {
+ int rr_len = data_len;
+ char next_domain_name[MAXDNAME];
+ int next_domain_name_len;
+ int rr_type;
+ guint8 bits;
+ int mask;
+ int i;
+
+ next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
+ next_domain_name, sizeof(next_domain_name));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", next domain name %s",
+ next_domain_name);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
+ "Next domain name: %s", next_domain_name);
+ cur_offset += next_domain_name_len;
+ rr_len -= next_domain_name_len;
+ rr_type = 0;
+ while (rr_len != 0) {
+ bits = tvb_get_guint8(tvb, cur_offset);
+ mask = 1<<7;
+ for (i = 0; i < 8; i++) {
+ if (bits & mask) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
+ "RR type in bit map: %s (%s)",
+ dns_type_name(rr_type),
+ dns_long_type_name(rr_type));
+ }
+ mask >>= 1;
+ rr_type++;
+ }
+ cur_offset += 1;
+ rr_len -= 1;
+ }
+ }
+ }
+ break;
+
+ case T_KX:
+ {
+ guint16 preference = 0;
+ char kx_name[MAXDNAME];
+ int kx_name_len;
+
+ preference = tvb_get_ntohs(tvb, cur_offset);
+ kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %u %s", preference, kx_name);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", preference %u, kx %s",
+ preference, kx_name);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
+ proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
+ kx_name);
+ }
+ }
+ break;
+
+ case T_CERT:
+ {
+ guint16 cert_type, cert_keytag;
+ guint8 cert_keyalg;
+ int rr_len = data_len;
+
+ if (dns_tree != NULL) {
+ if (rr_len < 2)
+ goto bad_rr;
+ cert_type = tvb_get_ntohs(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type: %s",
+ val_to_str(cert_type, cert_vals,
+ "Unknown (0x%02X)"));
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (rr_len < 2)
+ goto bad_rr;
+ cert_keytag = tvb_get_ntohs(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
+ cert_keytag);
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (rr_len < 1)
+ goto bad_rr;
+ cert_keyalg = tvb_get_guint8(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
+ val_to_str(cert_keyalg, algo_vals,
+ "Unknown (0x%02X)"));
+ cur_offset += 1;
+ rr_len -= 1;
+
+ if (rr_len != 0)
+ proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
+ }
+ }
+ break;
+
+ case T_OPT:
+ if (dns_tree != NULL)
+ proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
+ break;
+
+ case T_DS:
+ {
+ guint16 keytag, digest_data_size = -1;
+ guint8 ds_algorithm, ds_digest;
+ int rr_len = data_len;
+
+ static const value_string tds_digests[] = {
+ { TDSDIGEST_RESERVED, "Reserved digest" },
+ { TDSDIGEST_SHA1, "SHA-1" },
+ { 0, NULL }
+ };
+
+ if (dns_tree != NULL) {
+ if (rr_len < 2)
+ goto bad_rr;
+ keytag = tvb_get_ntohs(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key id: %04u", keytag);
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (rr_len < 1)
+ goto bad_rr;
+ ds_algorithm = tvb_get_guint8(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s", val_to_str(ds_algorithm, algo_vals,"Unknown (0x%02X)") );
+ cur_offset += 1;
+ rr_len -= 1;
+
+ if (rr_len < 1)
+ goto bad_rr;
+ ds_digest = tvb_get_guint8(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Digest type: %s", val_to_str(ds_digest, tds_digests, "Unknown (0x%02X)"));
+ cur_offset += 1;
+ rr_len -= 1;
+
+ if (ds_digest == TDSDIGEST_SHA1)
+ digest_data_size = 20; /* SHA1 key is always 20 bytes long */
+ if (digest_data_size > 0) {
+ if (rr_len < digest_data_size)
+ goto bad_rr;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, digest_data_size, "Public key");
+ }
+ }
+ }
+ break;
+
+ case T_TKEY:
+ {
+ char tkey_algname[MAXDNAME];
+ int tkey_algname_len;
+ guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
+ int rr_len = data_len;
+ nstime_t nstime;
+ static const value_string tkey_modes[] = {
+ { TKEYMODE_SERVERASSIGNED, "Server assigned" },
+ { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
+ { TKEYMODE_GSSAPI, "GSSAPI" },
+ { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
+ { TKEYMODE_DELETE, "Delete" },
+ { 0, NULL } };
+
+ if (dns_tree != NULL) {
+ proto_tree *key_tree;
+ proto_item *key_item;
+
+ tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
+ proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
+ "Algorithm name: %s", tkey_algname);
+ cur_offset += tkey_algname_len;
+ rr_len -= tkey_algname_len;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ nstime.secs = tvb_get_ntohl(tvb, cur_offset);
+ nstime.nsecs = 0;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
+ abs_time_to_str(&nstime));
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ nstime.secs = tvb_get_ntohl(tvb, cur_offset);
+ nstime.nsecs = 0;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
+ abs_time_to_str(&nstime));
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 2)
+ goto bad_rr;
+ tkey_mode = tvb_get_ntohs(tvb, cur_offset);
+ cur_offset += 2;
+ rr_len -= 2;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Mode: %s",
+ val_to_str(tkey_mode, tkey_modes,
+ "Unknown (0x%04X)"));
+
+ if (rr_len < 2)
+ goto bad_rr;
+ tkey_error = tvb_get_ntohs(tvb, cur_offset);
+ cur_offset += 2;
+ rr_len -= 2;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
+ val_to_str(tkey_error, rcode_vals,
+ val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
+
+ tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key Size: %u",
+ tkey_keylen);
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (tkey_keylen != 0) {
+ key_item = proto_tree_add_text(
+ rr_tree, tvb, cur_offset, tkey_keylen, "Key Data");
+
+ key_tree = proto_item_add_subtree(key_item, ett_t_key);
+
+ switch(tkey_mode) {
+ case TKEYMODE_GSSAPI: {
+ tvbuff_t *gssapi_tvb;
+
+ /*
+ * XXX - in at least one capture, this appears to
+ * be an NTLMSSP blob, with no ASN.1 in it, in
+ * a query.
+ *
+ * See RFC 3645 which might indicate what's going
+ * on here. (The key is an output_token from
+ * GSS_Init_sec_context.)
+ *
+ * How the heck do we know what method is being
+ * used, so we know how to decode the key? Do we
+ * have to look at the algorithm name, e.g.
+ * "gss.microsoft.com"? The SMB dissector
+ * checks whether the security blob begins
+ * with "NTLMSSP" in some cases.
+ */
+ gssapi_tvb = tvb_new_subset(
+ tvb, cur_offset, tkey_keylen, tkey_keylen);
+
+ call_dissector(gssapi_handle, gssapi_tvb, pinfo,
+ key_tree);
+
+ break;
+ }
+ default:
+
+ /* No dissector for this key mode */
+
+ break;
+ }
+
+ cur_offset += tkey_keylen;
+ rr_len -= tkey_keylen;
+ }
+
+ if (rr_len < 2)
+ goto bad_rr;
+ tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Other Size: %u",
+ tkey_otherlen);
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (tkey_otherlen != 0) {
+ if (rr_len < tkey_otherlen)
+ goto bad_rr;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other Data");
+ cur_offset += tkey_otherlen;
+ rr_len -= tkey_otherlen;
+ }
+ }
+ }
+ break;
+
+ case T_TSIG:
+ {
+ guint16 tsig_fudge;
+ guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
+ guint32 tsig_timelo;
+ char tsig_algname[MAXDNAME];
+ int tsig_algname_len;
+ nstime_t nstime;
+ int rr_len = data_len;
+
+ if (dns_tree != NULL) {
+ tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
+ proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
+ "Algorithm name: %s", tsig_algname);
+ cur_offset += tsig_algname_len;
+ rr_len -= tsig_algname_len;
+
+ if (rr_len < 6)
+ goto bad_rr;
+ tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
+ tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
+ nstime.secs = tsig_timelo;
+ nstime.nsecs = 0;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
+ abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
+ cur_offset += 6;
+ rr_len -= 6;
+
+ if (rr_len < 2)
+ goto bad_rr;
+ tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
+ tsig_fudge);
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (rr_len < 2)
+ goto bad_rr;
+ tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (tsig_siglen != 0) {
+ if (rr_len < tsig_siglen)
+ goto bad_rr;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
+ cur_offset += tsig_siglen;
+ rr_len -= tsig_siglen;
+ }
+
+ if (rr_len < 2)
+ goto bad_rr;
+ tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
+ tsig_originalid);
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (rr_len < 2)
+ goto bad_rr;
+ tsig_error = tvb_get_ntohs(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
+ val_to_str(tsig_error, rcode_vals,
+ val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (rr_len < 2)
+ goto bad_rr;
+ tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
+ cur_offset += 2;
+ rr_len -= 2;
+
+ if (tsig_otherlen != 0) {
+ if (rr_len < tsig_otherlen)
+ goto bad_rr;
+ proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
+ cur_offset += tsig_otherlen;
+ rr_len -= tsig_otherlen;
+ }
+ }
+ }
+ break;
+
+ case T_WINS:
+ {
+ int rr_len = data_len;
+ guint32 local_flag;
+ guint32 lookup_timeout;
+ guint32 cache_timeout;
+ guint32 nservers;
+
+ if (dns_tree != NULL) {
+ if (rr_len < 4)
+ goto bad_rr;
+ local_flag = tvb_get_ntohl(tvb, cur_offset);
+ if (dns_tree != NULL) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
+ local_flag ? "true" : "false");
+ }
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
+ if (dns_tree != NULL) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
+ lookup_timeout);
+ }
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ cache_timeout = tvb_get_ntohl(tvb, cur_offset);
+ if (dns_tree != NULL) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
+ cache_timeout);
+ }
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ nservers = tvb_get_ntohl(tvb, cur_offset);
+ if (dns_tree != NULL) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
+ nservers);
+ }
+ cur_offset += 4;
+ rr_len -= 4;
+
+ while (rr_len != 0 && nservers != 0) {
+ if (rr_len < 4)
+ goto bad_rr;
+ if (dns_tree != NULL) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
+ ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
+ }
+ cur_offset += 4;
+ rr_len -= 4;
+ nservers--;
+ }
+ }
+ }
+ break;
+
+ case T_WINS_R:
+ {
+ int rr_len = data_len;
+ guint32 local_flag;
+ guint32 lookup_timeout;
+ guint32 cache_timeout;
+ char dname[MAXDNAME];
+ int dname_len;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ local_flag = tvb_get_ntohl(tvb, cur_offset);
+ if (dns_tree != NULL) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
+ local_flag ? "true" : "false");
+ }
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
+ if (dns_tree != NULL) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
+ lookup_timeout);
+ }
+ cur_offset += 4;
+ rr_len -= 4;
+
+ if (rr_len < 4)
+ goto bad_rr;
+ cache_timeout = tvb_get_ntohl(tvb, cur_offset);
+ if (dns_tree != NULL) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
+ cache_timeout);
+ }
+ cur_offset += 4;
+ rr_len -= 4;
+
+ dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", dname);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", name result domain %s", dname);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
+ dname);
+ }
+ }
+ break;
+
+ case T_SRV:
+ {
+ guint16 priority = 0;
+ guint16 weight = 0;
+ guint16 port = 0;
+ char target[MAXDNAME];
+ int target_len;
+
+ priority = tvb_get_ntohs(tvb, cur_offset);
+ weight = tvb_get_ntohs(tvb, cur_offset+2);
+ port = tvb_get_ntohs(tvb, cur_offset+4);
+
+ target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %u %u %u %s", priority, weight, port, target);
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr,
+ ", priority %u, weight %u, port %u, target %s",
+ priority, weight, port, target);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
+ proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
+ proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
+ proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
+ target);
+ }
+ }
+ break;
+
+ /* TODO: parse more record types */
+
+ default:
+ if (dns_tree != NULL)
+ proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
+ break;
+ }
+
+ data_offset += data_len;
+
+ return data_offset - data_start;
+
+bad_rr:
+ if (dns_tree != NULL) {
+ proto_item_append_text(trr, ", bad RR length %d, too short",
+ data_len);
+ }
+
+ data_offset += data_len;
+
+ return data_offset - data_start;
+}
+
+static int
+dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
+ int count, column_info *cinfo, proto_tree *dns_tree, int isupdate)
+{
+ int start_off, add_off;
+ proto_tree *qatree = NULL;
+ proto_item *ti = NULL;
+
+ start_off = cur_off;
+ if (dns_tree) {
+ char *s = (isupdate ? "Zone" : "Queries");
+ ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, s);
+ qatree = proto_item_add_subtree(ti, ett_dns_qry);
+ }
+ while (count-- > 0) {
+ add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
+ cur_off += add_off;
+ }
+ if (ti)
+ proto_item_set_len(ti, cur_off - start_off);
+
+ return cur_off - start_off;
+}
+
+static int
+dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
+ int count, column_info *cinfo, proto_tree *dns_tree, char *name,
+ packet_info *pinfo)
+{
+ int start_off, add_off;
+ proto_tree *qatree = NULL;
+ proto_item *ti = NULL;
+
+ start_off = cur_off;
+ if (dns_tree) {
+ ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
+ qatree = proto_item_add_subtree(ti, ett_dns_ans);
+ }
+ while (count-- > 0) {
+ add_off = dissect_dns_answer(
+ tvb, cur_off, dns_data_offset, cinfo, qatree, pinfo);
+ cur_off += add_off;
+ }
+ if (ti)
+ proto_item_set_len(ti, cur_off - start_off);
+
+ return cur_off - start_off;
+}
+
+static void
+dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean is_tcp)
+{
+ int offset = is_tcp ? 2 : 0;
+ int dns_data_offset;
+ column_info *cinfo;
+ proto_tree *dns_tree = NULL, *field_tree;
+ proto_item *ti, *tf;
+ guint16 id, flags, opcode, rcode, quest, ans, auth, add;
+ char buf[128+1];
+ int cur_off;
+ int isupdate;
+
+ dns_data_offset = offset;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* To do: check for errs, etc. */
+ id = tvb_get_ntohs(tvb, offset + DNS_ID);
+ flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
+ opcode = (guint16) ((flags & F_OPCODE) >> OPCODE_SHIFT);
+ rcode = (guint16) (flags & F_RCODE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation (%u)"));
+ if (flags & F_RESPONSE) {
+ strcat(buf, " response");
+ if ((flags & F_RCODE) != RCODE_NOERROR) {
+ strcat(buf, ", ");
+ strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
+ "Unknown error (%u)"));
+ }
+ }
+ col_add_str(pinfo->cinfo, COL_INFO, buf);
+ cinfo = pinfo->cinfo;
+ } else {
+ /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query and answer
+ dissectors, as a way of saying that they shouldn't add stuff
+ to the COL_INFO column (a call to "check_col(cinfo, COL_INFO)"
+ is more expensive than a check that a pointer isn't NULL). */
+ cinfo = NULL;
+ }
+ if (opcode == OPCODE_UPDATE)
+ isupdate = 1;
+ else
+ isupdate = 0;
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
+ "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
+
+ dns_tree = proto_item_add_subtree(ti, ett_dns);
+
+ if (is_tcp) {
+ /* Put the length indication into the tree. */
+ proto_tree_add_item(dns_tree, hf_dns_length, tvb, offset - 2, 2, FALSE);
+ }
+
+ proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
+ offset + DNS_ID, 2, id);
+
+ strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation"));
+ if (flags & F_RESPONSE) {
+ strcat(buf, " response");
+ strcat(buf, ", ");
+ strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
+ "Unknown error"));
+ }
+ tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
+ offset + DNS_FLAGS, 2,
+ flags,
+ "Flags: 0x%04x (%s)",
+ flags, buf);
+ field_tree = proto_item_add_subtree(tf, ett_dns_flags);
+ proto_tree_add_item(field_tree, hf_dns_flags_response,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ proto_tree_add_item(field_tree, hf_dns_flags_opcode,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ if (flags & F_RESPONSE) {
+ proto_tree_add_item(field_tree, hf_dns_flags_authoritative,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ }
+ proto_tree_add_item(field_tree, hf_dns_flags_truncated,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ proto_tree_add_item(field_tree, hf_dns_flags_recdesired,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ if (flags & F_RESPONSE) {
+ proto_tree_add_item(field_tree, hf_dns_flags_recavail,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ proto_tree_add_item(field_tree, hf_dns_flags_z,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ proto_tree_add_item(field_tree, hf_dns_flags_authenticated,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ proto_tree_add_item(field_tree, hf_dns_flags_rcode,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ } else {
+ proto_tree_add_item(field_tree, hf_dns_flags_z,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ proto_tree_add_item(field_tree, hf_dns_flags_checkdisable,
+ tvb, offset + DNS_FLAGS, 2, FALSE);
+ }
+ }
+ quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
+ if (tree) {
+ proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
+ offset + DNS_QUEST, 2, quest);
+ }
+ ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
+ if (tree) {
+ proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
+ offset + DNS_ANS, 2, ans);
+ }
+ auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
+ if (tree) {
+ proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
+ offset + DNS_AUTH, 2, auth);
+ }
+ add = tvb_get_ntohs(tvb, offset + DNS_ADD);
+ if (tree) {
+ proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
+ offset + DNS_ADD, 2, add);
+
+ }
+ cur_off = offset + DNS_HDRLEN;
+
+ if (quest > 0) {
+ /* If this is a response, don't add information about the queries
+ to the summary, just add information about the answers. */
+ cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
+ (!(flags & F_RESPONSE) ? cinfo : NULL),
+ dns_tree, isupdate);
+ }
+
+ if (ans > 0) {
+ /* If this is a request, don't add information about the answers
+ to the summary, just add information about the queries. */
+ cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
+ ((flags & F_RESPONSE) ? cinfo : NULL),
+ dns_tree, (isupdate ?
+ "Prerequisites" : "Answers"),
+ pinfo);
+ }
+
+ /* Don't add information about the authoritative name servers, or the
+ additional records, to the summary. */
+ if (auth > 0) {
+ cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
+ NULL, dns_tree,
+ (isupdate ? "Updates" :
+ "Authoritative nameservers"),
+ pinfo);
+ }
+
+ if (add > 0) {
+ cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
+ NULL, dns_tree, "Additional records",
+ pinfo);
+ }
+}
+
+static void
+dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
+
+ dissect_dns_common(tvb, pinfo, tree, FALSE);
+}
+
+static void
+dissect_mdns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDNS");
+
+ dissect_dns_common(tvb, pinfo, tree, FALSE);
+}
+
+
+static guint
+get_dns_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint16 plen;
+
+ /*
+ * Get the length of the DNS packet.
+ */
+ plen = tvb_get_ntohs(tvb, offset);
+
+ /*
+ * That length doesn't include the length field itself; add that in.
+ */
+ return plen + 2;
+}
+
+static void
+dissect_dns_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
+
+ dissect_dns_common(tvb, pinfo, tree, TRUE);
+}
+
+static void
+dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2, get_dns_pdu_len,
+ dissect_dns_tcp_pdu);
+}
+
+void
+proto_register_dns(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_dns_length,
+ { "Length", "dns.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of DNS-over-TCP request or response", HFILL }},
+ { &hf_dns_flags,
+ { "Flags", "dns.flags",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_dns_flags_response,
+ { "Response", "dns.flags.response",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
+ "Is the message a response?", HFILL }},
+ { &hf_dns_flags_opcode,
+ { "Opcode", "dns.flags.opcode",
+ FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
+ "Operation code", HFILL }},
+ { &hf_dns_flags_authoritative,
+ { "Authoritative", "dns.flags.authoritative",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
+ "Is the server is an authority for the domain?", HFILL }},
+ { &hf_dns_flags_truncated,
+ { "Truncated", "dns.flags.truncated",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
+ "Is the message truncated?", HFILL }},
+ { &hf_dns_flags_recdesired,
+ { "Recursion desired", "dns.flags.recdesired",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
+ "Do query recursively?", HFILL }},
+ { &hf_dns_flags_recavail,
+ { "Recursion available", "dns.flags.recavail",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
+ "Can the server do recursive queries?", HFILL }},
+ { &hf_dns_flags_z,
+ { "Z", "dns.flags.z",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_z), F_Z,
+ "Z flag", HFILL }},
+ { &hf_dns_flags_authenticated,
+ { "Answer authenticated", "dns.flags.authenticated",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_authenticated), F_AUTHENTIC,
+ "Was the reply data authenticated by the server?", HFILL }},
+ { &hf_dns_flags_checkdisable,
+ { "Non-authenticated data OK", "dns.flags.checkdisable",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_checkdisable), F_CHECKDISABLE,
+ "Is non-authenticated data acceptable?", HFILL }},
+ { &hf_dns_flags_rcode,
+ { "Reply code", "dns.flags.rcode",
+ FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
+ "Reply code", HFILL }},
+ { &hf_dns_transaction_id,
+ { "Transaction ID", "dns.id",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Identification of transaction", HFILL }},
+ { &hf_dns_count_questions,
+ { "Questions", "dns.count.queries",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of queries in packet", HFILL }},
+ { &hf_dns_count_answers,
+ { "Answer RRs", "dns.count.answers",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of answers in packet", HFILL }},
+ { &hf_dns_count_auth_rr,
+ { "Authority RRs", "dns.count.auth_rr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of authoritative records in packet", HFILL }},
+ { &hf_dns_count_add_rr,
+ { "Additional RRs", "dns.count.add_rr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of additional records in packet", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_dns,
+ &ett_dns_qd,
+ &ett_dns_rr,
+ &ett_dns_qry,
+ &ett_dns_ans,
+ &ett_dns_flags,
+ &ett_t_key_flags,
+ &ett_t_key,
+ };
+ module_t *dns_module;
+
+ proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
+ proto_register_field_array(proto_dns, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ dns_module = prefs_register_protocol(proto_dns, NULL);
+ prefs_register_bool_preference(dns_module, "desegment_dns_messages",
+ "Desegment all DNS messages spanning multiple TCP segments",
+ "Whether the DNS dissector should desegment all messages spanning multiple TCP segments",
+ &dns_desegment);
+}
+
+void
+proto_reg_handoff_dns(void)
+{
+ dissector_handle_t dns_udp_handle;
+ dissector_handle_t dns_tcp_handle;
+ dissector_handle_t mdns_udp_handle;
+
+ dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
+ dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
+ mdns_udp_handle = create_dissector_handle(dissect_mdns_udp, proto_dns);
+
+ dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
+ dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
+ dissector_add("udp.port", UDP_PORT_MDNS, mdns_udp_handle);
+ dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
+
+ gssapi_handle = find_dissector("gssapi");
+}
diff --git a/epan/dissectors/packet-dns.h b/epan/dissectors/packet-dns.h
new file mode 100644
index 0000000000..5f751c7c7d
--- /dev/null
+++ b/epan/dissectors/packet-dns.h
@@ -0,0 +1,40 @@
+/* packet-dns.h
+ * Definitions for packet disassembly structures and routines used both by
+ * DNS and NBNS.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __PACKET_DNS_H__
+#define __PACKET_DNS_H__
+
+char *dns_class_name(int class);
+
+int get_dns_name(tvbuff_t *, int, int, char *, int);
+
+#define MAXDNAME 1025 /* maximum domain name length */
+
+proto_tree *
+add_rr_to_tree(proto_item *, int, tvbuff_t *, int, const char *,
+ int, const char *, const char *, guint, gushort);
+
+#endif /* packet-dns.h */
diff --git a/epan/dissectors/packet-dsi.c b/epan/dissectors/packet-dsi.c
new file mode 100644
index 0000000000..adbc28ed64
--- /dev/null
+++ b/epan/dissectors/packet-dsi.c
@@ -0,0 +1,846 @@
+/* packet-dsi.c
+ * Routines for dsi packet dissection
+ * Copyright 2001, Randy McEoin <rmceoin@pe.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include "prefs.h"
+#include "packet-tcp.h"
+#include "packet-afp.h"
+
+/* The information in this module (DSI) comes from:
+
+ AFP 2.1 & 2.2.pdf contained in AppleShare_IP_6.3_SDK
+ available from http://www.apple.com
+
+ The netatalk source code by Wesley Craig & Adrian Sun
+
+ * What a Data Stream Interface packet looks like:
+ * 0 32
+ * |-------------------------------|
+ * |flags |command| requestID |
+ * |-------------------------------|
+ * |error code/enclosed data offset|
+ * |-------------------------------|
+ * |total data length |
+ * |-------------------------------|
+ * |reserved field |
+ * |-------------------------------|
+ */
+
+static int proto_dsi = -1;
+static int hf_dsi_flags = -1;
+static int hf_dsi_command = -1;
+static int hf_dsi_requestid = -1;
+static int hf_dsi_offset = -1;
+static int hf_dsi_error = -1;
+static int hf_dsi_length = -1;
+static int hf_dsi_reserved = -1;
+
+static gint ett_dsi = -1;
+
+static int hf_dsi_open_type = -1;
+static int hf_dsi_open_len = -1;
+static int hf_dsi_open_quantum = -1;
+static int hf_dsi_open_option = -1;
+
+static int hf_dsi_attn_flag = -1;
+static int hf_dsi_attn_flag_shutdown = -1;
+static int hf_dsi_attn_flag_crash = -1;
+static int hf_dsi_attn_flag_msg = -1;
+static int hf_dsi_attn_flag_reconnect = -1;
+static int hf_dsi_attn_flag_time = -1;
+static int hf_dsi_attn_flag_bitmap = -1;
+
+static gint ett_dsi_open = -1;
+static gint ett_dsi_attn = -1;
+static gint ett_dsi_attn_flag = -1;
+
+static const value_string dsi_attn_flag_vals[] = {
+ {0x0, "Reserved" }, /* 0000 */
+ {0x1, "Reserved" }, /* 0001 */
+ {0x2, "Server message" }, /* 0010 */
+ {0x3, "Server notification, cf. extended bitmap" }, /* 0011 */
+ {0x4, "Server is shutting down, internal error" }, /* 0100 */
+ {0x8, "Server is shutting down" }, /* 1000 */
+ {0x9, "Server disconnects user" }, /* 1001 */
+ {0x10,"Server is shutting down, message" }, /* 1010 */
+ {0x11,"Server is shutting down, message,no reconnect"}, /* 1011 */
+ {0, NULL } };
+
+static const value_string dsi_open_type_vals[] = {
+ {0, "Server quantum" },
+ {1, "Attention quantum" },
+ {0, NULL } };
+
+/* status stuff same for asp and afp */
+static int hf_dsi_server_name = -1;
+static int hf_dsi_utf8_server_name_len = -1;
+static int hf_dsi_utf8_server_name = -1;
+static int hf_dsi_server_type = -1;
+static int hf_dsi_server_vers = -1;
+static int hf_dsi_server_uams = -1;
+static int hf_dsi_server_icon = -1;
+static int hf_dsi_server_directory = -1;
+
+static int hf_dsi_server_flag = -1;
+static int hf_dsi_server_flag_copyfile = -1;
+static int hf_dsi_server_flag_passwd = -1;
+static int hf_dsi_server_flag_no_save_passwd = -1;
+static int hf_dsi_server_flag_srv_msg = -1;
+static int hf_dsi_server_flag_srv_sig = -1;
+static int hf_dsi_server_flag_tcpip = -1;
+static int hf_dsi_server_flag_notify = -1;
+static int hf_dsi_server_flag_reconnect = -1;
+static int hf_dsi_server_flag_directory = -1;
+static int hf_dsi_server_flag_utf8_name = -1;
+static int hf_dsi_server_flag_fast_copy = -1;
+static int hf_dsi_server_signature = -1;
+
+static int hf_dsi_server_addr_len = -1;
+static int hf_dsi_server_addr_type = -1;
+static int hf_dsi_server_addr_value = -1;
+
+static gint ett_dsi_status = -1;
+static gint ett_dsi_uams = -1;
+static gint ett_dsi_vers = -1;
+static gint ett_dsi_addr = -1;
+static gint ett_dsi_addr_line = -1;
+static gint ett_dsi_directory = -1;
+static gint ett_dsi_utf8_name = -1;
+static gint ett_dsi_status_server_flag = -1;
+
+const value_string afp_server_addr_type_vals[] = {
+ {1, "IP address" },
+ {2, "IP+port address" },
+ {3, "DDP address" },
+ {4, "DNS name" },
+ {5, "IP+port ssh tunnel" },
+ {0, NULL } };
+
+/* end status stuff */
+
+/* desegmentation of DSI */
+static gboolean dsi_desegment = TRUE;
+
+static dissector_handle_t data_handle;
+static dissector_handle_t afp_handle;
+
+#define TCP_PORT_DSI 548
+
+#define DSI_BLOCKSIZ 16
+
+/* DSI flags */
+#define DSIFL_REQUEST 0x00
+#define DSIFL_REPLY 0x01
+#define DSIFL_MAX 0x01
+
+/* DSI Commands */
+#define DSIFUNC_CLOSE 1 /* DSICloseSession */
+#define DSIFUNC_CMD 2 /* DSICommand */
+#define DSIFUNC_STAT 3 /* DSIGetStatus */
+#define DSIFUNC_OPEN 4 /* DSIOpenSession */
+#define DSIFUNC_TICKLE 5 /* DSITickle */
+#define DSIFUNC_WRITE 6 /* DSIWrite */
+#define DSIFUNC_ATTN 8 /* DSIAttention */
+#define DSIFUNC_MAX 8 /* largest command */
+
+static const value_string flag_vals[] = {
+ {DSIFL_REQUEST, "Request" },
+ {DSIFL_REPLY, "Reply" },
+ {0, NULL } };
+
+static const value_string func_vals[] = {
+ {DSIFUNC_CLOSE, "CloseSession" },
+ {DSIFUNC_CMD, "Command" },
+ {DSIFUNC_STAT, "GetStatus" },
+ {DSIFUNC_OPEN, "OpenSession" },
+ {DSIFUNC_TICKLE, "Tickle" },
+ {DSIFUNC_WRITE, "Write" },
+ {DSIFUNC_ATTN, "Attention" },
+ {0, NULL } };
+
+static gint
+dissect_dsi_open_session(tvbuff_t *tvb, proto_tree *dsi_tree, gint offset)
+{
+ proto_tree *tree;
+ proto_item *ti;
+ guint8 type;
+ guint8 len;
+
+ ti = proto_tree_add_text(dsi_tree, tvb, offset, -1, "Open Session");
+ tree = proto_item_add_subtree(ti, ett_dsi_open);
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_dsi_open_type, tvb, offset, 1, FALSE);
+ offset++;
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_dsi_open_len, tvb, offset, 1, FALSE);
+ offset++;
+ if (type <= 1) {
+ proto_tree_add_item(tree, hf_dsi_open_quantum, tvb, offset, 4, FALSE);
+ }
+ else {
+ proto_tree_add_item(tree, hf_dsi_open_option, tvb, offset, len, FALSE);
+ }
+ offset += len;
+ return offset;
+}
+
+static gint
+dissect_dsi_attention(tvbuff_t *tvb, proto_tree *dsi_tree, gint offset)
+{
+ proto_tree *tree;
+ proto_item *ti;
+ guint16 flag;
+
+ if (!tvb_reported_length_remaining(tvb,offset))
+ return offset;
+
+ flag = tvb_get_ntohs(tvb, offset);
+ ti = proto_tree_add_text(dsi_tree, tvb, offset, -1, "Attention");
+ tree = proto_item_add_subtree(ti, ett_dsi_attn);
+
+ ti = proto_tree_add_item(tree, hf_dsi_attn_flag, tvb, offset, 2, FALSE);
+ tree = proto_item_add_subtree(ti, ett_dsi_attn_flag);
+ proto_tree_add_item(tree, hf_dsi_attn_flag_shutdown, tvb, offset, 2, FALSE);
+ proto_tree_add_item(tree, hf_dsi_attn_flag_crash, tvb, offset, 2, FALSE);
+ proto_tree_add_item(tree, hf_dsi_attn_flag_msg, tvb, offset, 2, FALSE);
+ proto_tree_add_item(tree, hf_dsi_attn_flag_reconnect, tvb, offset, 2, FALSE);
+ /* FIXME */
+ if ((flag & 0xf000) != 0x3000)
+ proto_tree_add_item(tree, hf_dsi_attn_flag_time, tvb, offset, 2, FALSE);
+ else
+ proto_tree_add_item(tree, hf_dsi_attn_flag_bitmap, tvb, offset, 2, FALSE);
+ offset += 2;
+ return offset;
+}
+
+/* -----------------------------
+ from netatalk/etc/afpd/status.c
+*/
+static gint
+dissect_dsi_reply_get_status(tvbuff_t *tvb, proto_tree *tree, gint offset)
+{
+ proto_tree *sub_tree;
+ proto_item *ti;
+
+ guint16 ofs;
+ guint16 flag;
+ guint16 sign_ofs = 0;
+ guint16 adr_ofs = 0;
+ guint16 dir_ofs = 0;
+ guint16 utf_ofs = 0;
+ guint8 nbe;
+ guint8 len;
+ guint8 i;
+
+ if (!tree)
+ return offset;
+
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "Get Status");
+ tree = proto_item_add_subtree(ti, ett_dsi_status);
+
+ ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
+ proto_tree_add_text(tree, tvb, offset +AFPSTATUS_MACHOFF, 2, "Machine offset: %d", ofs);
+
+ ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
+ proto_tree_add_text(tree, tvb, offset +AFPSTATUS_VERSOFF, 2, "Version offset: %d", ofs);
+
+ ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
+ proto_tree_add_text(tree, tvb, offset +AFPSTATUS_UAMSOFF, 2, "UAMS offset: %d", ofs);
+
+ ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
+ proto_tree_add_text(tree, tvb, offset +AFPSTATUS_ICONOFF, 2, "Icon offset: %d", ofs);
+
+ ofs = offset +AFPSTATUS_FLAGOFF;
+ ti = proto_tree_add_item(tree, hf_dsi_server_flag, tvb, ofs, 2, FALSE);
+ sub_tree = proto_item_add_subtree(ti, ett_dsi_status_server_flag);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_copyfile , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_passwd , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_no_save_passwd, tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_srv_msg , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_srv_sig , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_tcpip , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_notify , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_reconnect , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_directory , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_utf8_name , tvb, ofs, 2, FALSE);
+ proto_tree_add_item(sub_tree, hf_dsi_server_flag_fast_copy , tvb, ofs, 2, FALSE);
+
+ proto_tree_add_item(tree, hf_dsi_server_name, tvb, offset +AFPSTATUS_PRELEN, 1, FALSE);
+
+ flag = tvb_get_ntohs(tvb, ofs);
+ if ((flag & AFPSRVRINFO_SRVSIGNATURE)) {
+ ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN) +1;
+ if ((ofs & 1))
+ ofs++;
+
+ sign_ofs = tvb_get_ntohs(tvb, ofs);
+ proto_tree_add_text(tree, tvb, ofs, 2, "Signature offset: %d", sign_ofs);
+ sign_ofs += offset;
+
+ if ((flag & AFPSRVRINFO_TCPIP)) {
+ ofs += 2;
+ adr_ofs = tvb_get_ntohs(tvb, ofs);
+ proto_tree_add_text(tree, tvb, ofs, 2, "Network address offset: %d", adr_ofs);
+ adr_ofs += offset;
+ }
+
+ if ((flag & AFPSRVRINFO_SRVDIRECTORY)) {
+ ofs += 2;
+ dir_ofs = tvb_get_ntohs(tvb, ofs);
+ proto_tree_add_text(tree, tvb, ofs, 2, "Directory services offset: %d", dir_ofs);
+ dir_ofs += offset;
+ }
+ if ((flag & AFPSRVRINFO_SRVUTF8)) {
+ ofs += 2;
+ utf_ofs = tvb_get_ntohs(tvb, ofs);
+ proto_tree_add_text(tree, tvb, ofs, 2, "UTF8 server name offset: %d", utf_ofs);
+ utf_ofs += offset;
+ }
+ }
+
+ ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
+ if (ofs)
+ proto_tree_add_item(tree, hf_dsi_server_type, tvb, ofs, 1, FALSE);
+
+ ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
+ if (ofs) {
+ nbe = tvb_get_guint8(tvb, ofs);
+ ti = proto_tree_add_text(tree, tvb, ofs, 1, "Version list: %d", nbe);
+ ofs++;
+ sub_tree = proto_item_add_subtree(ti, ett_dsi_vers);
+ for (i = 0; i < nbe; i++) {
+ len = tvb_get_guint8(tvb, ofs);
+ proto_tree_add_item(sub_tree, hf_dsi_server_vers, tvb, ofs, 1, FALSE);
+ ofs += len + 1;
+ }
+ }
+
+ ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
+ if (ofs) {
+ nbe = tvb_get_guint8(tvb, ofs);
+ ti = proto_tree_add_text(tree, tvb, ofs, 1, "UAMS list: %d", nbe);
+ ofs++;
+ sub_tree = proto_item_add_subtree(ti, ett_dsi_uams);
+ for (i = 0; i < nbe; i++) {
+ len = tvb_get_guint8(tvb, ofs);
+ proto_tree_add_item(sub_tree, hf_dsi_server_uams, tvb, ofs, 1, FALSE);
+ ofs += len + 1;
+ }
+ }
+
+ ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
+ if (ofs)
+ proto_tree_add_item(tree, hf_dsi_server_icon, tvb, ofs, 256, FALSE);
+
+ if (sign_ofs) {
+ proto_tree_add_item(tree, hf_dsi_server_signature, tvb, sign_ofs, 16, FALSE);
+ }
+
+ if (adr_ofs) {
+ proto_tree *adr_tree;
+ char *tmp;
+ const guint8 *ip;
+ guint16 net;
+ guint8 node;
+ guint16 port;
+
+ ofs = adr_ofs;
+ nbe = tvb_get_guint8(tvb, ofs);
+ ti = proto_tree_add_text(tree, tvb, ofs, 1, "Address list: %d", nbe);
+ ofs++;
+ adr_tree = proto_item_add_subtree(ti, ett_dsi_addr);
+ for (i = 0; i < nbe; i++) {
+ guint8 type;
+
+ len = tvb_get_guint8(tvb, ofs);
+ type = tvb_get_guint8(tvb, ofs +1);
+ switch (type) {
+ case 1: /* IP */
+ ip = tvb_get_ptr(tvb, ofs+2, 4);
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip: %s", ip_to_str(ip));
+ break;
+ case 2: /* IP + port */
+ ip = tvb_get_ptr(tvb, ofs+2, 4);
+ port = tvb_get_ntohs(tvb, ofs+6);
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip %s:%d",ip_to_str(ip),port);
+ break;
+ case 3: /* DDP, atalk_addr_to_str want host order not network */
+ net = tvb_get_ntohs(tvb, ofs+2);
+ node = tvb_get_guint8(tvb, ofs +4);
+ port = tvb_get_guint8(tvb, ofs +5);
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ddp: %u.%u:%u",
+ net, node, port);
+ break;
+ case 4: /* DNS */
+ case 5: /* SSH tunnel */
+ if (len > 2) {
+ tmp = tvb_get_string(tvb, ofs +2, len -2);
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "%s: %s",
+ (type==4)?"dns":"ssh tunnel", tmp);
+ g_free(tmp);
+ break;
+ }
+ else {
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Malformed address type %d", type);
+ }
+ break;
+ default:
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Unknow type : %d", type);
+ break;
+ }
+ len -= 2;
+ sub_tree = proto_item_add_subtree(ti,ett_dsi_addr_line);
+ proto_tree_add_item(sub_tree, hf_dsi_server_addr_len, tvb, ofs, 1, FALSE);
+ ofs++;
+ proto_tree_add_item(sub_tree, hf_dsi_server_addr_type, tvb, ofs, 1, FALSE);
+ ofs++;
+ proto_tree_add_item(sub_tree, hf_dsi_server_addr_value,tvb, ofs, len, FALSE);
+ ofs += len;
+ }
+ }
+
+ if (dir_ofs) {
+ ofs = dir_ofs;
+ nbe = tvb_get_guint8(tvb, ofs);
+ ti = proto_tree_add_text(tree, tvb, ofs, 1, "Directory services list: %d", nbe);
+ ofs++;
+ sub_tree = proto_item_add_subtree(ti, ett_dsi_directory);
+ for (i = 0; i < nbe; i++) {
+ len = tvb_get_guint8(tvb, ofs);
+ proto_tree_add_item(sub_tree, hf_dsi_server_directory, tvb, ofs, 1, FALSE);
+ ofs += len + 1;
+ }
+ }
+ if (utf_ofs) {
+ guint16 ulen;
+ char *tmp;
+
+ ofs = utf_ofs;
+ ulen = tvb_get_ntohs(tvb, ofs);
+ tmp = tvb_get_string(tvb, ofs + 2, ulen);
+ ti = proto_tree_add_text(tree, tvb, ofs, ulen + 2, "UTF8 server name: %s", tmp);
+ sub_tree = proto_item_add_subtree(ti, ett_dsi_utf8_name);
+ proto_tree_add_uint(sub_tree, hf_dsi_utf8_server_name_len, tvb, ofs, 2, ulen);
+ ofs += 2;
+ proto_tree_add_string(sub_tree, hf_dsi_utf8_server_name, tvb, ofs, ulen, tmp);
+ ofs += ulen;
+ g_free(tmp);
+ }
+
+ return offset;
+}
+
+static void
+dissect_dsi_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *dsi_tree;
+ proto_item *ti;
+ guint8 dsi_flags,dsi_command;
+ guint16 dsi_requestid;
+ gint32 dsi_code;
+ guint32 dsi_length;
+ guint32 dsi_reserved;
+ struct aspinfo aspinfo;
+ gint col_info;
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DSI");
+ col_info = check_col(pinfo->cinfo, COL_INFO);
+ if (col_info)
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ dsi_flags = tvb_get_guint8(tvb, 0);
+ dsi_command = tvb_get_guint8(tvb, 1);
+ dsi_requestid = tvb_get_ntohs(tvb, 2);
+ dsi_code = tvb_get_ntohl(tvb, 4);
+ dsi_length = tvb_get_ntohl(tvb, 8);
+ dsi_reserved = tvb_get_ntohl(tvb, 12);
+
+ if (col_info) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s (%u)",
+ val_to_str(dsi_flags, flag_vals,
+ "Unknown flag (0x%02x)"),
+ val_to_str(dsi_command, func_vals,
+ "Unknown function (0x%02x)"),
+ dsi_requestid);
+ }
+
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_dsi, tvb, 0, -1, FALSE);
+ dsi_tree = proto_item_add_subtree(ti, ett_dsi);
+
+ proto_tree_add_uint(dsi_tree, hf_dsi_flags, tvb,
+ 0, 1, dsi_flags);
+ proto_tree_add_uint(dsi_tree, hf_dsi_command, tvb,
+ 1, 1, dsi_command);
+ proto_tree_add_uint(dsi_tree, hf_dsi_requestid, tvb,
+ 2, 2, dsi_requestid);
+ switch (dsi_flags) {
+
+ case DSIFL_REQUEST:
+ proto_tree_add_int(dsi_tree, hf_dsi_offset, tvb,
+ 4, 4, dsi_code);
+ break;
+
+ case DSIFL_REPLY:
+ proto_tree_add_int(dsi_tree, hf_dsi_error, tvb,
+ 4, 4, dsi_code);
+ break;
+ }
+ proto_tree_add_uint_format(dsi_tree, hf_dsi_length, tvb,
+ 8, 4, dsi_length,
+ "Length: %u bytes", dsi_length);
+ proto_tree_add_uint(dsi_tree, hf_dsi_reserved, tvb,
+ 12, 4, dsi_reserved);
+ }
+ else
+ dsi_tree = tree;
+ switch (dsi_command) {
+ case DSIFUNC_OPEN:
+ if (tree) {
+ dissect_dsi_open_session(tvb, dsi_tree, DSI_BLOCKSIZ);
+ }
+ break;
+ case DSIFUNC_ATTN:
+ if (tree) {
+ dissect_dsi_attention(tvb, dsi_tree, DSI_BLOCKSIZ);
+ }
+ break;
+ case DSIFUNC_STAT:
+ if (tree && (dsi_flags == DSIFL_REPLY)) {
+ dissect_dsi_reply_get_status(tvb, dsi_tree, DSI_BLOCKSIZ);
+ }
+ break;
+ case DSIFUNC_CMD:
+ case DSIFUNC_WRITE:
+ {
+ tvbuff_t *new_tvb;
+ int len = tvb_reported_length_remaining(tvb,DSI_BLOCKSIZ);
+
+ aspinfo.reply = (dsi_flags == DSIFL_REPLY);
+ aspinfo.command = dsi_command;
+ aspinfo.seq = dsi_requestid;
+ aspinfo.code = dsi_code;
+ pinfo->private_data = &aspinfo;
+ proto_item_set_len(dsi_tree, DSI_BLOCKSIZ);
+
+ new_tvb = tvb_new_subset(tvb, DSI_BLOCKSIZ,-1,len);
+ call_dissector(afp_handle, new_tvb, pinfo, tree);
+ }
+ break;
+ default:
+ if (tree) {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, DSI_BLOCKSIZ, -1, -1),
+ pinfo, dsi_tree);
+ }
+ break;
+ }
+}
+
+static guint
+get_dsi_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint32 plen;
+ guint8 dsi_flags,dsi_command;
+
+ dsi_flags = tvb_get_guint8(tvb, offset);
+ dsi_command = tvb_get_guint8(tvb, offset+ 1);
+ if ( dsi_flags > DSIFL_MAX || !dsi_command || dsi_command > DSIFUNC_MAX)
+ {
+ /* it's not a known dsi pdu start sequence */
+ return tvb_length_remaining(tvb, offset);
+ }
+
+ /*
+ * Get the length of the DSI packet.
+ */
+ plen = tvb_get_ntohl(tvb, offset+8);
+
+ /*
+ * That length doesn't include the length of the header itself;
+ * add that in.
+ */
+ return plen + 16;
+}
+
+static void
+dissect_dsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, dsi_desegment, 12,
+ get_dsi_pdu_len, dissect_dsi_packet);
+}
+
+void
+proto_register_dsi(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_dsi_flags,
+ { "Flags", "dsi.flags",
+ FT_UINT8, BASE_HEX, VALS(flag_vals), 0x0,
+ "Indicates request or reply.", HFILL }},
+
+ { &hf_dsi_command,
+ { "Command", "dsi.command",
+ FT_UINT8, BASE_DEC, VALS(func_vals), 0x0,
+ "Represents a DSI command.", HFILL }},
+
+ { &hf_dsi_requestid,
+ { "Request ID", "dsi.requestid",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Keeps track of which request this is. Replies must match a Request. IDs must be generated in sequential order.", HFILL }},
+
+ { &hf_dsi_offset,
+ { "Data offset", "dsi.data_offset",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Data offset", HFILL }},
+
+ { &hf_dsi_error,
+ { "Error code", "dsi.error_code",
+ FT_INT32, BASE_DEC, VALS(asp_error_vals), 0x0,
+ "Error code", HFILL }},
+
+ { &hf_dsi_length,
+ { "Length", "dsi.length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Total length of the data that follows the DSI header.", HFILL }},
+
+ { &hf_dsi_reserved,
+ { "Reserved", "dsi.reserved",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Reserved for future use. Should be set to zero.", HFILL }},
+ /* asp , afp */
+ { &hf_dsi_utf8_server_name_len,
+ { "Length", "dsi.utf8_server_name_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "UTF8 server name length.", HFILL }},
+ { &hf_dsi_utf8_server_name,
+ { "UTF8 Server name", "dsi.utf8_server_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "UTF8 Server name", HFILL }},
+
+ { &hf_dsi_server_name,
+ { "Server name", "dsi.server_name",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "Server name", HFILL }},
+
+ { &hf_dsi_server_type,
+ { "Server type", "dsi.server_type",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "Server type", HFILL }},
+
+ { &hf_dsi_server_vers,
+ { "AFP version", "dsi.server_vers",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "AFP version", HFILL }},
+
+ { &hf_dsi_server_uams,
+ { "UAM", "dsi.server_uams",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "UAM", HFILL }},
+
+ { &hf_dsi_server_icon,
+ { "Icon bitmap", "dsi.server_icon",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Server icon bitmap", HFILL }},
+
+ { &hf_dsi_server_directory,
+ { "Directory service", "dsi.server_directory",
+ FT_UINT_STRING, BASE_NONE, NULL, 0x0,
+ "Server directory service", HFILL }},
+
+ { &hf_dsi_server_signature,
+ { "Server signature", "dsi.server_signature",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Server signature", HFILL }},
+
+ { &hf_dsi_server_flag,
+ { "Flag", "dsi.server_flag",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Server capabilities flag", HFILL }},
+ { &hf_dsi_server_flag_copyfile,
+ { "Support copyfile", "dsi.server_flag.copyfile",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_COPY,
+ "Server support copyfile", HFILL }},
+ { &hf_dsi_server_flag_passwd,
+ { "Support change password", "dsi.server_flag.passwd",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_PASSWD,
+ "Server support change password", HFILL }},
+ { &hf_dsi_server_flag_no_save_passwd,
+ { "Don't allow save password", "dsi.server_flag.no_save_passwd",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_NOSAVEPASSWD,
+ "Don't allow save password", HFILL }},
+ { &hf_dsi_server_flag_srv_msg,
+ { "Support server message", "dsi.server_flag.srv_msg",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVMSGS,
+ "Support server message", HFILL }},
+ { &hf_dsi_server_flag_srv_sig,
+ { "Support server signature", "dsi.server_flag.srv_sig",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVSIGNATURE,
+ "Support server signature", HFILL }},
+ { &hf_dsi_server_flag_tcpip,
+ { "Support TCP/IP", "dsi.server_flag.tcpip",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_TCPIP,
+ "Server support TCP/IP", HFILL }},
+ { &hf_dsi_server_flag_notify,
+ { "Support server notifications", "dsi.server_flag.notify",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVNOTIFY,
+ "Server support notifications", HFILL }},
+ { &hf_dsi_server_flag_reconnect,
+ { "Support server reconnect", "dsi.server_flag.reconnect",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVRECONNECT,
+ "Server support reconnect", HFILL }},
+ { &hf_dsi_server_flag_directory,
+ { "Support directory services", "dsi.server_flag.directory",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVDIRECTORY,
+ "Server support directory services", HFILL }},
+ { &hf_dsi_server_flag_utf8_name,
+ { "Support UTF8 server name", "dsi.server_flag.utf8_name",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVUTF8,
+ "Server support UTF8 server name", HFILL }},
+ { &hf_dsi_server_flag_fast_copy,
+ { "Support fast copy", "dsi.server_flag.fast_copy",
+ FT_BOOLEAN, 16, NULL, AFPSRVRINFO_FASTBOZO,
+ "Server support fast copy", HFILL }},
+
+
+ { &hf_dsi_server_addr_len,
+ { "Length", "dsi.server_addr.len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Address length.", HFILL }},
+
+ { &hf_dsi_server_addr_type,
+ { "Type", "dsi.server_addr.type",
+ FT_UINT8, BASE_DEC, VALS(afp_server_addr_type_vals), 0x0,
+ "Address type.", HFILL }},
+
+ { &hf_dsi_server_addr_value,
+ { "Value", "dsi.server_addr.value",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Address value", HFILL }},
+
+ { &hf_dsi_open_type,
+ { "Flags", "dsi.open_type",
+ FT_UINT8, BASE_DEC, VALS(dsi_open_type_vals), 0x0,
+ "Open session option type.", HFILL }},
+
+ { &hf_dsi_open_len,
+ { "Length", "dsi.open_len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Open session option len", HFILL }},
+
+ { &hf_dsi_open_quantum,
+ { "Quantum", "dsi.open_quantum",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Server/Attention quantum", HFILL }},
+
+ { &hf_dsi_open_option,
+ { "Option", "dsi.open_option",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Open session options (undecoded)", HFILL }},
+
+ { &hf_dsi_attn_flag,
+ { "Flags", "dsi.attn_flag",
+ FT_UINT16, BASE_HEX, VALS(dsi_attn_flag_vals), 0xf000,
+ "Server attention flag", HFILL }},
+ { &hf_dsi_attn_flag_shutdown,
+ { "Shutdown", "dsi.attn_flag.shutdown",
+ FT_BOOLEAN, 16, NULL, 1<<15,
+ "Attention flag, server is shutting down", HFILL }},
+ { &hf_dsi_attn_flag_crash,
+ { "Crash", "dsi.attn_flag.crash",
+ FT_BOOLEAN, 16, NULL, 1<<14,
+ "Attention flag, server crash bit", HFILL }},
+ { &hf_dsi_attn_flag_msg,
+ { "Message", "dsi.attn_flag.msg",
+ FT_BOOLEAN, 16, NULL, 1<<13,
+ "Attention flag, server message bit", HFILL }},
+ { &hf_dsi_attn_flag_reconnect,
+ { "Don't reconnect", "dsi.attn_flag.reconnect",
+ FT_BOOLEAN, 16, NULL, 1<<12,
+ "Attention flag, don't reconnect bit", HFILL }},
+ { &hf_dsi_attn_flag_time,
+ { "Minutes", "dsi.attn_flag.time",
+ FT_UINT16, BASE_DEC, NULL, 0xfff,
+ "Number of minutes", HFILL }},
+ { &hf_dsi_attn_flag_bitmap,
+ { "Bitmap", "dsi.attn_flag.time",
+ FT_UINT16, BASE_HEX, NULL, 0xfff,
+ "Attention extended bitmap", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_dsi,
+ &ett_dsi_open,
+ &ett_dsi_attn,
+ &ett_dsi_attn_flag,
+ /* asp afp */
+ &ett_dsi_status,
+ &ett_dsi_status_server_flag,
+ &ett_dsi_vers,
+ &ett_dsi_uams,
+ &ett_dsi_addr,
+ &ett_dsi_addr_line,
+ &ett_dsi_directory,
+ &ett_dsi_utf8_name,
+ };
+ module_t *dsi_module;
+
+ proto_dsi = proto_register_protocol("Data Stream Interface", "DSI", "dsi");
+ proto_register_field_array(proto_dsi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ dsi_module = prefs_register_protocol(proto_dsi, NULL);
+ prefs_register_bool_preference(dsi_module, "desegment",
+ "Desegment all DSI messages spanning multiple TCP segments",
+ "Whether the DSI dissector should desegment all messages spanning multiple TCP segments",
+ &dsi_desegment);
+}
+
+void
+proto_reg_handoff_dsi(void)
+{
+ static dissector_handle_t dsi_handle;
+
+ dsi_handle = create_dissector_handle(dissect_dsi, proto_dsi);
+ dissector_add("tcp.port", TCP_PORT_DSI, dsi_handle);
+
+ data_handle = find_dissector("data");
+ afp_handle = find_dissector("afp");
+}
diff --git a/epan/dissectors/packet-dvmrp.c b/epan/dissectors/packet-dvmrp.c
new file mode 100644
index 0000000000..9c919385fe
--- /dev/null
+++ b/epan/dissectors/packet-dvmrp.c
@@ -0,0 +1,801 @@
+/* packet-dvmrp.c 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Routines for IGMP/DVMRP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+
+
+ DVMRP DVMRP
+ code v1 v3
+
+ 0x01 * *
+ 0x02 * *
+ 0x03 x
+ 0x04 x
+ 0x07 x
+ 0x08 x
+ 0x09 x
+
+
+ * V3 has len>=8 and byte[6]==0xff and byte[7]==0x03
+
+
+ DVMRP is defined in the following RFCs
+ RFC1075 Version 1
+ draft-ietf-idmr-dvmrp-v3-10.txt Version 3
+
+ V1 and V3 can be distinguished by looking at bytes 6 and 7 in the
+ IGMP/DVMRP header.
+ If header[6]==0xff and header[7]==0x03 we have version 3.
+
+
+ RFC1075 has typos in 3.12.2 and 3.12.4, see if you can spot them.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "ipproto.h"
+#include "packet-igmp.h"
+#include "packet-dvmrp.h"
+
+static int proto_dvmrp = -1;
+static int hf_version = -1;
+static int hf_type = -1;
+static int hf_code_v1 = -1;
+static int hf_checksum = -1;
+static int hf_checksum_bad = -1;
+static int hf_commands = -1;
+static int hf_command = -1;
+static int hf_count = -1;
+static int hf_afi = -1;
+static int hf_netmask = -1;
+static int hf_metric = -1;
+static int hf_dest_unr = -1;
+static int hf_split_horiz = -1;
+static int hf_infinity = -1;
+static int hf_daddr = -1;
+static int hf_maddr = -1;
+static int hf_hold = -1;
+static int hf_code_v3 = -1;
+static int hf_capabilities = -1;
+static int hf_cap_leaf = -1;
+static int hf_cap_prune = -1;
+static int hf_cap_genid = -1;
+static int hf_cap_mtrace = -1;
+static int hf_cap_snmp = -1;
+static int hf_cap_netmask = -1;
+static int hf_min_ver = -1;
+static int hf_maj_ver = -1;
+static int hf_genid = -1;
+static int hf_route = -1;
+static int hf_saddr = -1;
+static int hf_life = -1;
+static int hf_neighbor = -1;
+
+static int ett_dvmrp = -1;
+static int ett_commands = -1;
+static int ett_capabilities = -1;
+static int ett_route = -1;
+
+
+#define DVMRP_TYPE 0x13
+static const value_string dvmrp_type[] = {
+ {DVMRP_TYPE, "DVMRP" },
+ {0, NULL}
+};
+
+#define DVMRP_V1_RESPONSE 1
+#define DVMRP_V1_REQUEST 2
+#define DVMRP_V1_NON_MEMBERSHIP_REPORT 3
+#define DVMRP_V1_NON_MEMBERSHIP_CANCELLATION 4
+static const value_string code_v1[] = {
+ {DVMRP_V1_RESPONSE, "Response" },
+ {DVMRP_V1_REQUEST, "Request" },
+ {DVMRP_V1_NON_MEMBERSHIP_REPORT, "Non-membership report" },
+ {DVMRP_V1_NON_MEMBERSHIP_CANCELLATION, "Non-membership cancellation" },
+ {0, NULL}
+};
+
+#define DVMRP_V3_PROBE 0x1
+#define DVMRP_V3_REPORT 0x2
+#define DVMRP_V3_ASK_NEIGHBORS 0x3
+#define DVMRP_V3_NEIGHBORS 0x4
+#define DVMRP_V3_ASK_NEIGHBORS_2 0x5
+#define DVMRP_V3_NEIGHBORS_2 0x6
+#define DVMRP_V3_PRUNE 0x7
+#define DVMRP_V3_GRAFT 0x8
+#define DVMRP_V3_GRAFT_ACK 0x9
+static const value_string code_v3[] = {
+ {DVMRP_V3_PROBE, "Probe"},
+ {DVMRP_V3_REPORT, "Report"},
+ {DVMRP_V3_ASK_NEIGHBORS, "Ask Neighbors"},
+ {DVMRP_V3_NEIGHBORS, "Neighbors"},
+ {DVMRP_V3_ASK_NEIGHBORS_2, "Ask Neighbors 2"},
+ {DVMRP_V3_NEIGHBORS_2, "Neighbors 2"},
+ {DVMRP_V3_PRUNE, "Prune"},
+ {DVMRP_V3_GRAFT, "Graft"},
+ {DVMRP_V3_GRAFT_ACK, "Graft ACK"},
+ {0, NULL}
+};
+
+#define DVMRP_V3_CAP_LEAF 0x01
+#define DVMRP_V3_CAP_PRUNE 0x02
+#define DVMRP_V3_CAP_GENID 0x04
+#define DVMRP_V3_CAP_MTRACE 0x08
+#define DVMRP_V3_CAP_SNMP 0x10
+#define DVMRP_V3_CAP_NETMASK 0x20
+
+
+#define V1_COMMAND_NULL 0
+#define V1_COMMAND_AFI 2
+#define V1_COMMAND_SUBNETMASK 3
+#define V1_COMMAND_METRIC 4
+#define V1_COMMAND_FLAGS0 5
+#define V1_COMMAND_INFINITY 6
+#define V1_COMMAND_DA 7
+#define V1_COMMAND_RDA 8
+#define V1_COMMAND_NMR 9
+#define V1_COMMAND_NMR_CANCEL 10
+static const value_string command[] = {
+ {V1_COMMAND_NULL, "NULL" },
+ {V1_COMMAND_AFI, "Address Family Indicator"},
+ {V1_COMMAND_SUBNETMASK, "Subnetmask"},
+ {V1_COMMAND_METRIC, "Metric"},
+ {V1_COMMAND_FLAGS0, "Flags0"},
+ {V1_COMMAND_INFINITY, "Infinity"},
+ {V1_COMMAND_DA, "Destination Address"},
+ {V1_COMMAND_RDA, "Requested Destination Address"},
+ {V1_COMMAND_NMR, "Non-Membership Report"},
+ {V1_COMMAND_NMR_CANCEL, "Non-Membership Report Cancel"},
+ {0, NULL}
+};
+
+#define V1_AFI_IP 2
+static const value_string afi[] = {
+ {V1_AFI_IP, "IP v4 Family"},
+ {0, NULL}
+};
+
+static const true_false_string tfs_dest_unreach = {
+ "Destination Unreachable",
+ "NOT Destination Unreachable"
+};
+
+static const true_false_string tfs_split_horiz = {
+ "Split Horizon concealed route",
+ "NOT Split Horizon concealed route"
+};
+
+static const true_false_string tfs_cap_leaf = {
+ "Leaf",
+ "NOT Leaf"
+};
+static const true_false_string tfs_cap_prune = {
+ "Prune capable",
+ "NOT Prune capable"
+};
+static const true_false_string tfs_cap_genid = {
+ "Genid capable",
+ "NOT Genid capable"
+};
+static const true_false_string tfs_cap_mtrace = {
+ "Multicast Traceroute capable",
+ "NOT Multicast Traceroute capable"
+};
+static const true_false_string tfs_cap_snmp = {
+ "SNMP capable",
+ "NOT SNMP capable"
+};
+static const true_false_string tfs_cap_netmask = {
+ "Netmask capable",
+ "NOT Netmask capable"
+};
+
+static int
+dissect_v3_report(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint8 m0,m1,m2,m3;
+ guint8 s0,s1,s2,s3;
+ guint8 metric;
+ guint32 ip;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_tree *tree;
+ proto_item *item;
+ int old_offset = offset;
+
+ item = proto_tree_add_item(parent_tree, hf_route,
+ tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_route);
+
+ m0 = 0xff;
+ /* read the mask */
+ m1 = tvb_get_guint8(tvb, offset);
+ m2 = tvb_get_guint8(tvb, offset+1);
+ m3 = tvb_get_guint8(tvb, offset+2);
+
+ ip = m3;
+ ip = (ip<<8)|m2;
+ ip = (ip<<8)|m1;
+ ip = (ip<<8)|m0;
+ proto_tree_add_ipv4(tree, hf_netmask, tvb, offset, 3, ip);
+
+ offset += 3;
+
+ /* read every srcnet, metric pairs */
+ do {
+ int old_offset = offset;
+ m0 = 0xff;
+
+ s0 = 0;
+ s1 = 0;
+ s2 = 0;
+ s3 = 0;
+
+ s0 = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ if (m1) {
+ s1 = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ }
+ if (m2) {
+ s2 = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ }
+ if (m3) {
+ s3 = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ }
+
+ /* handle special case for default route V3/3.4.3 */
+ if ((!m1)&&(!m2)&&(!m3)&&(!s0)) {
+ m0 = 0;
+ }
+
+ ip = s3;
+ ip = (ip<<8)|s2;
+ ip = (ip<<8)|s1;
+ ip = (ip<<8)|s0;
+ proto_tree_add_ipv4_format(tree, hf_saddr, tvb,
+ old_offset, offset-old_offset, ip,
+ "%s %d.%d.%d.%d (netmask %d.%d.%d.%d)",
+ m0?"Source Network":"Default Route",
+ s0,s1,s2,s3,m0,m1,m2,m3);
+
+ metric = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_metric, tvb,
+ offset, 1, metric&0x7f);
+ offset += 1;
+
+
+ } while (!(metric&0x80));
+
+ proto_item_set_len(item, offset-old_offset);
+ }
+
+ return offset;
+}
+
+static int
+dissect_dvmrp_v3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ guint8 code,count;
+
+ /* version */
+ proto_tree_add_uint(parent_tree, hf_version, tvb, 0, 0, 3);
+
+ /* type of command */
+ proto_tree_add_uint(parent_tree, hf_type, tvb, offset, 1, 0x13);
+ offset += 1;
+
+ /* code */
+ code = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(parent_tree, hf_code_v3, tvb, offset, 1, code);
+ offset += 1;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "V%d %s",3 ,val_to_str(code, code_v3,
+ "Unknown Type:0x%02x"));
+ }
+
+ /* checksum */
+ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ /* skip unused byte */
+ offset += 1;
+
+ /* PROBE and NEIGHBORS 2 packets have capabilities flags, unused
+ for other packets */
+ if (code==DVMRP_V3_PROBE || code==DVMRP_V3_NEIGHBORS_2) {
+ proto_tree *tree;
+ proto_item *item;
+
+ item = proto_tree_add_item(parent_tree, hf_capabilities,
+ tvb, offset, 1, FALSE);
+ tree = proto_item_add_subtree(item, ett_capabilities);
+
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_boolean(tree, hf_cap_netmask, tvb, offset, 1, count);
+ proto_tree_add_boolean(tree, hf_cap_snmp, tvb, offset, 1, count);
+ proto_tree_add_boolean(tree, hf_cap_mtrace, tvb, offset, 1, count);
+ proto_tree_add_boolean(tree, hf_cap_genid, tvb, offset, 1, count);
+ proto_tree_add_boolean(tree, hf_cap_prune, tvb, offset, 1, count);
+ proto_tree_add_boolean(tree, hf_cap_leaf, tvb, offset, 1, count);
+ }
+ offset += 1;
+
+ /* minor version */
+ proto_tree_add_item(parent_tree, hf_min_ver, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* major version */
+ proto_tree_add_item(parent_tree, hf_maj_ver, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ switch (code) {
+ case DVMRP_V3_PROBE:
+ /* generation id */
+ proto_tree_add_item(parent_tree, hf_genid, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_item(parent_tree, hf_neighbor,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ break;
+ case DVMRP_V3_REPORT:
+ offset = dissect_v3_report(tvb, parent_tree, offset);
+ break;
+ case DVMRP_V3_PRUNE:
+ /* source address */
+ proto_tree_add_item(parent_tree, hf_saddr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ /* group address */
+ proto_tree_add_item(parent_tree, hf_maddr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ /* prune lifetime */
+ proto_tree_add_item(parent_tree, hf_life,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ /* source netmask */
+ if (tvb_reported_length_remaining(tvb, offset)>=4) {
+ proto_tree_add_item(parent_tree, hf_netmask,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ break;
+ case DVMRP_V3_GRAFT:
+ /* source address */
+ proto_tree_add_item(parent_tree, hf_saddr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ /* group address */
+ proto_tree_add_item(parent_tree, hf_maddr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ /* source netmask */
+ if (tvb_reported_length_remaining(tvb, offset)>=4) {
+ proto_tree_add_item(parent_tree, hf_netmask,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ break;
+ case DVMRP_V3_GRAFT_ACK:
+ /* source address */
+ proto_tree_add_item(parent_tree, hf_saddr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ /* group address */
+ proto_tree_add_item(parent_tree, hf_maddr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ /* source netmask */
+ if (tvb_reported_length_remaining(tvb, offset)>=4) {
+ proto_tree_add_item(parent_tree, hf_netmask,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ break;
+ case DVMRP_V3_ASK_NEIGHBORS:
+ case DVMRP_V3_NEIGHBORS:
+ /* XXX - obsolete, and the draft doesn't describe them */
+ break;
+ case DVMRP_V3_ASK_NEIGHBORS_2:
+ /* No data */
+ break;
+ case DVMRP_V3_NEIGHBORS_2:
+ /* XXX - fill this in */
+ break;
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_dvmrp_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ guint8 code;
+ guint8 af=2; /* default */
+
+ /* version */
+ proto_tree_add_uint(parent_tree, hf_version, tvb, 0, 0, 1);
+
+ /* type of command */
+ proto_tree_add_uint(parent_tree, hf_type, tvb, offset, 1, 0x13);
+ offset += 1;
+
+ /* code */
+ code = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(parent_tree, hf_code_v1, tvb, offset, 1, code);
+ offset += 1;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "V%d %s",1 ,val_to_str(code, code_v1,
+ "Unknown Type:0x%02x"));
+ }
+
+ /* checksum */
+ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ /* decode all the v1 commands */
+ while (tvb_reported_length_remaining(tvb, offset)) {
+ proto_tree *tree;
+ proto_item *item;
+ guint8 cmd,count;
+ int old_offset = offset;
+
+ item = proto_tree_add_item(parent_tree, hf_commands,
+ tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_commands);
+
+ cmd = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_command, tvb,
+ offset, 1, cmd);
+ offset += 1;
+
+ switch (cmd){
+ case V1_COMMAND_NULL:
+ offset += 1; /* skip ignored/pad byte*/
+ if (item) {
+ proto_item_set_text(item, "Command: NULL");
+ }
+ break;
+ case V1_COMMAND_AFI:
+ af = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_afi, tvb,
+ offset, 1, af);
+ offset += 1;
+ if (item) {
+ proto_item_set_text(item, "%s: %s",
+ val_to_str(cmd, command, "Unknown Command:0x%02x"),
+ val_to_str(af, afi, "Unknown Family:0x%02x")
+ );
+ }
+ break;
+ case V1_COMMAND_SUBNETMASK:
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_count, tvb,
+ offset, 1, count);
+ offset += 1;
+ if (count) { /* must be 0 or 1 */
+ proto_tree_add_item(tree, hf_netmask,
+ tvb, offset, 4, FALSE);
+ if (item) {
+ proto_item_set_text(item, "%s: %d.%d.%d.%d",
+ val_to_str(cmd, command, "Unknown Command:0x%02x"),
+ tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset+1),
+ tvb_get_guint8(tvb, offset+2),
+ tvb_get_guint8(tvb, offset+3));
+ }
+ offset += 4;
+ } else {
+ if (item) {
+ proto_item_set_text(item, "%s: <no mask supplied>",
+ val_to_str(cmd, command, "Unknown Command:0x%02x"));
+ }
+ }
+ break;
+ case V1_COMMAND_METRIC:
+ proto_tree_add_item(tree, hf_metric, tvb,
+ offset, 1, FALSE);
+ if (item) {
+ proto_item_set_text(item, "%s: %d",
+ val_to_str(cmd, command, "Unknown Command:0x%02x"),
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ break;
+ case V1_COMMAND_FLAGS0:
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_boolean(tree, hf_dest_unr, tvb, offset, 1, count);
+ proto_tree_add_boolean(tree, hf_split_horiz, tvb, offset, 1, count);
+ if (item) {
+ proto_item_set_text(item, "%s: 0x%02x",
+ val_to_str(cmd, command, "Unknown Command:0x%02x"), count);
+ }
+ offset += 1;
+ break;
+ case V1_COMMAND_INFINITY:
+ proto_tree_add_item(tree, hf_infinity, tvb,
+ offset, 1, FALSE);
+ if (item) {
+ proto_item_set_text(item, "%s: %d",
+ val_to_str(cmd, command, "Unknown Command:0x%02x"), tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ break;
+ case V1_COMMAND_DA:
+ case V1_COMMAND_RDA: /* same as DA */
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_count, tvb,
+ offset, 1, count);
+ offset += 1;
+ while (count--) {
+ proto_tree_add_item(tree, hf_daddr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ if (item) {
+ proto_item_set_text(item, "%s",
+ val_to_str(cmd, command, "Unknown Command:0x%02x"));
+ }
+ break;
+ case V1_COMMAND_NMR:
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_count, tvb,
+ offset, 1, count);
+ offset += 1;
+ while (count--) {
+ proto_tree_add_item(tree, hf_maddr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_hold, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ }
+ if (item) {
+ proto_item_set_text(item, "%s",
+ val_to_str(cmd, command, "Unknown Command:0x%02x"));
+ }
+ break;
+ case V1_COMMAND_NMR_CANCEL:
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_count, tvb,
+ offset, 1, count);
+ offset += 1;
+ while (count--) {
+ proto_tree_add_item(tree, hf_maddr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ if (item) {
+ proto_item_set_text(item, "%s",
+ val_to_str(cmd, command, "Unknown Command:0x%02x"));
+ }
+ break;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ }
+
+ return offset;
+}
+
+/* This function is only called from the IGMP dissector */
+int
+dissect_dvmrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree;
+ proto_item *item;
+
+ if (!proto_is_protocol_enabled(find_protocol_by_id(proto_dvmrp))) {
+ /* we are not enabled, skip entire packet to be nice
+ to the igmp layer. (so clicking on IGMP will display the data)
+ */
+ return offset+tvb_length_remaining(tvb, offset);
+ }
+
+ item = proto_tree_add_item(parent_tree, proto_dvmrp, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_dvmrp);
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DVMRP");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+
+ if ((tvb_length_remaining(tvb, offset)>=8)
+ && (tvb_get_guint8(tvb, 6)==0xff)
+ && (tvb_get_guint8(tvb, 7)==0x03)) {
+ offset = dissect_dvmrp_v3(tvb, pinfo, tree, offset);
+ proto_item_set_len(item, offset);
+ return offset;
+ }
+
+
+ offset = dissect_dvmrp_v1(tvb, pinfo, tree, offset);
+ proto_item_set_len(item, offset);
+ return offset;
+}
+
+void
+proto_register_dvmrp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_version,
+ { "DVMRP Version", "dvmrp.version", FT_UINT8, BASE_DEC,
+ NULL, 0, "DVMRP Version", HFILL }},
+
+ { &hf_type,
+ { "Type", "dvmrp.type", FT_UINT8, BASE_HEX,
+ VALS(dvmrp_type), 0, "DVMRP Packet Type", HFILL }},
+
+ { &hf_code_v1,
+ { "Code", "dvmrp.v1.code", FT_UINT8, BASE_HEX,
+ VALS(code_v1), 0, "DVMRP Packet Code", HFILL }},
+
+ { &hf_checksum,
+ { "Checksum", "dvmrp.checksum", FT_UINT16, BASE_HEX,
+ NULL, 0, "DVMRP Checksum", HFILL }},
+
+ { &hf_checksum_bad,
+ { "Bad Checksum", "dvmrp.checksum_bad", FT_BOOLEAN, BASE_NONE,
+ NULL, 0, "Bad DVMRP Checksum", HFILL }},
+
+ { &hf_commands,
+ { "Commands", "dvmrp.commands", FT_NONE, BASE_NONE,
+ NULL, 0, "DVMRP V1 Commands", HFILL }},
+
+ { &hf_command,
+ { "Command", "dvmrp.command", FT_UINT8, BASE_HEX,
+ VALS(command), 0, "DVMRP V1 Command", HFILL }},
+
+ { &hf_afi,
+ { "Address Family", "dvmrp.afi", FT_UINT8, BASE_HEX,
+ VALS(afi), 0, "DVMRP Address Family Indicator", HFILL }},
+
+ { &hf_count,
+ { "Count", "dvmrp.count", FT_UINT8, BASE_HEX,
+ NULL, 0, "Count", HFILL }},
+
+ { &hf_netmask,
+ { "Netmask", "igmp.netmask", FT_IPv4, BASE_NONE,
+ NULL, 0, "DVMRP Netmask", HFILL }},
+
+ { &hf_metric,
+ { "Metric", "dvmrp.metric", FT_UINT8, BASE_DEC,
+ NULL, 0, "DVMRP Metric", HFILL }},
+
+ {&hf_dest_unr,
+ { "Destination Unreachable", "dvmrp.dest_unreach", FT_BOOLEAN, 8,
+ TFS(&tfs_dest_unreach), 0x01, "Destination Unreachable", HFILL }},
+
+ {&hf_split_horiz,
+ { "Split Horizon", "dvmrp.split_horiz", FT_BOOLEAN, 8,
+ TFS(&tfs_split_horiz), 0x02, "Split Horizon concealed route", HFILL }},
+
+ { &hf_infinity,
+ { "Infinity", "dvmrp.infinity", FT_UINT8, BASE_DEC,
+ NULL, 0, "DVMRP Infinity", HFILL }},
+
+ { &hf_daddr,
+ { "Dest Addr", "igmp.daddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "DVMRP Destination Address", HFILL }},
+
+ { &hf_maddr,
+ { "Multicast Addr", "igmp.maddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "DVMRP Multicast Address", HFILL }},
+
+ { &hf_hold,
+ { "Hold Time", "dvmrp.hold", FT_UINT32, BASE_DEC,
+ NULL, 0, "DVMRP Hold Time in seconds", HFILL }},
+
+ { &hf_code_v3,
+ { "Code", "dvmrp.v3.code", FT_UINT8, BASE_HEX,
+ VALS(code_v3), 0, "DVMRP Packet Code", HFILL }},
+
+ { &hf_capabilities,
+ { "Capabilities", "dvmrp.capabilities", FT_NONE, BASE_NONE,
+ NULL, 0, "DVMRP V3 Capabilities", HFILL }},
+
+ {&hf_cap_leaf,
+ { "Leaf", "dvmrp.cap.leaf", FT_BOOLEAN, 8,
+ TFS(&tfs_cap_leaf), DVMRP_V3_CAP_LEAF, "Leaf", HFILL }},
+
+ {&hf_cap_prune,
+ { "Prune", "dvmrp.cap.prune", FT_BOOLEAN, 8,
+ TFS(&tfs_cap_prune), DVMRP_V3_CAP_PRUNE, "Prune capability", HFILL }},
+
+ {&hf_cap_genid,
+ { "Genid", "dvmrp.cap.genid", FT_BOOLEAN, 8,
+ TFS(&tfs_cap_genid), DVMRP_V3_CAP_GENID, "Genid capability", HFILL }},
+
+ {&hf_cap_mtrace,
+ { "Mtrace", "dvmrp.cap.mtrace", FT_BOOLEAN, 8,
+ TFS(&tfs_cap_mtrace), DVMRP_V3_CAP_MTRACE, "Mtrace capability", HFILL }},
+
+ {&hf_cap_snmp,
+ { "SNMP", "dvmrp.cap.snmp", FT_BOOLEAN, 8,
+ TFS(&tfs_cap_snmp), DVMRP_V3_CAP_SNMP, "SNMP capability", HFILL }},
+
+ {&hf_cap_netmask,
+ { "Netmask", "dvmrp.cap.netmask", FT_BOOLEAN, 8,
+ TFS(&tfs_cap_netmask), DVMRP_V3_CAP_NETMASK, "Netmask capability", HFILL }},
+
+ { &hf_min_ver,
+ { "Minor Version", "dvmrp.min_ver", FT_UINT8, BASE_HEX,
+ NULL, 0, "DVMRP Minor Version", HFILL }},
+
+ { &hf_maj_ver,
+ { "Major Version", "dvmrp.maj_ver", FT_UINT8, BASE_HEX,
+ NULL, 0, "DVMRP Major Version", HFILL }},
+
+ { &hf_genid,
+ { "Generation ID", "dvmrp.genid", FT_UINT32, BASE_DEC,
+ NULL, 0, "DVMRP Generation ID", HFILL }},
+
+ { &hf_route,
+ { "Route", "dvmrp.route", FT_NONE, BASE_NONE,
+ NULL, 0, "DVMRP V3 Route Report", HFILL }},
+
+ { &hf_saddr,
+ { "Source Addr", "igmp.saddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "DVMRP Source Address", HFILL }},
+
+ { &hf_life,
+ { "Prune lifetime", "dvmrp.lifetime", FT_UINT32, BASE_DEC,
+ NULL, 0, "DVMRP Prune Lifetime", HFILL }},
+
+ { &hf_neighbor,
+ { "Neighbor Addr", "igmp.neighbor", FT_IPv4, BASE_NONE,
+ NULL, 0, "DVMRP Neighbor Address", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_dvmrp,
+ &ett_commands,
+ &ett_capabilities,
+ &ett_route,
+ };
+
+ proto_dvmrp = proto_register_protocol("Distance Vector Multicast Routing Protocol",
+ "DVMRP", "dvmrp");
+ proto_register_field_array(proto_dvmrp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/epan/dissectors/packet-dvmrp.h b/epan/dissectors/packet-dvmrp.h
new file mode 100644
index 0000000000..3e29d614cd
--- /dev/null
+++ b/epan/dissectors/packet-dvmrp.h
@@ -0,0 +1,31 @@
+/* packet-dvmrp.h 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Declarations of routines for IGMP/DVMRP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_DVMRP_H__
+#define __PACKET_DVMRP_H__
+
+int dissect_dvmrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+
+#endif
+
diff --git a/epan/dissectors/packet-e164.c b/epan/dissectors/packet-e164.c
new file mode 100644
index 0000000000..6e449c6be0
--- /dev/null
+++ b/epan/dissectors/packet-e164.c
@@ -0,0 +1,433 @@
+/* packet-e164.c
+ * Routines for output and filtering of E164 numbers common
+ * to many dissectors.
+ * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Ref ITU-T E.164 05/97
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-e164.h"
+
+const value_string E164_country_code_value[] = {
+ { 0x00, "Reserved (Assignment of all 0XX codes will be feasible after 31 December 2000. This question is currently under study.)"},
+ { 0x01, "Americas"},
+ { 0x020,"Egypt"},
+ { 0x0210,"Spare code"},
+ { 0x0211,"Spare code"},
+ { 0x0212,"Morocco"},
+ { 0x0213,"Algeria"},
+ { 0x0214,"spare code"},
+ { 0x0215,"spare code"},
+ { 0x0216,"Tunisia"},
+ { 0x0217,"Spare code"},
+ { 0x0218,"Libya"},
+ { 0x0219,"Spare code"},
+ { 0x0220,"Gambia"},
+ { 0x0221,"Senegal"},
+ { 0x0222,"Mauritania"},
+ { 0x0223,"Mali"},
+ { 0x0224,"Guinea"},
+ { 0x0225,"Ivory Coast"},
+ { 0x0226,"Burkina Faso"},
+ { 0x0227,"Niger"},
+ { 0x0228,"Togolese Republic"},
+ { 0x0229,"Benin"},
+ { 0x0230,"Mauritius"},
+ { 0x0231,"Liberia "},
+ { 0x0232,"Sierra Leone"},
+ { 0x0233,"Ghana"},
+ { 0x0234,"Nigeria"},
+ { 0x0235,"Chad"},
+ { 0x0236,"Central African Republic"},
+ { 0x0237,"Cameroon"},
+ { 0x0238,"Cape Verde"},
+ { 0x0239,"Sao Tome and Principe"},
+ { 0x0240,"Equatorial Guinea"},
+ { 0x0241,"Gabonese Republic"},
+ { 0x0242,"Republic of Congo"},
+ { 0x0243,"Democratic Republic of Congo"},
+ { 0x0244,"Angola"},
+ { 0x0245,"Guinea-Bissau"},
+ { 0x0246,"Diego Garcia"},
+ { 0x0247,"Ascension"},
+ { 0x0248,"Seychelles"},
+ { 0x0249,"Sudan"},
+ { 0x0250,"Rwandese Republic"},
+ { 0x0251,"Ethiopia"},
+ { 0x0252,"Somali"},
+ { 0x0253,"Djibouti"},
+ { 0x0254,"Kenya"},
+ { 0x0255,"Tanzania"},
+ { 0x0256,"Uganda"},
+ { 0x0257,"Burundi"},
+ { 0x0258,"Mozambique"},
+ { 0x0259,"Spare code"},
+ { 0x0260,"Zambia"},
+ { 0x0261,"Madagascar"},
+ { 0x0262,"Reunion Island"},
+ { 0x0263,"Zimbabwe"},
+ { 0x0264,"Namibia"},
+ { 0x0265,"Malawi"},
+ { 0x0266,"Lesotho"},
+ { 0x0267,"Botswana"},
+ { 0x0268,"Swaziland"},
+ { 0x0269,"Comoros Mayotte"},
+ { 0x027,"South Africa"},
+ { 0x0281,"spare code"},
+ { 0x0282,"spare code"},
+ { 0x0283,"spare code"},
+ { 0x0284,"spare code"},
+ { 0x0285,"spare code"},
+ { 0x0286,"spare code"},
+ { 0x0287,"spare code"},
+ { 0x0288,"spare code"},
+ { 0x0289,"spare code"},
+ { 0x0290,"Saint Helena"},
+ { 0x0291,"Eritrea"},
+ { 0x0292,"spare code"},
+ { 0x0293,"spare code"},
+ { 0x0294,"spare code"},
+ { 0x0295,"spare code"},
+ { 0x0296,"spare code"},
+ { 0x0297,"Aruba"},
+ { 0x0298,"Faroe Islands"},
+ { 0x0299,"Greenland"},
+ { 0x030,"Greece"},
+ { 0x031,"Netherlands"},
+ { 0x032,"Belgium"},
+ { 0x033,"France"},
+ { 0x034,"Spain"},
+ { 0x0350,"Gibraltar"},
+ { 0x0351,"Portugal"},
+ { 0x0352,"Luxembourg"},
+ { 0x0353,"Ireland"},
+ { 0x0354,"Iceland"},
+ { 0x0355,"Albania"},
+ { 0x0356,"Malta"},
+ { 0x0357,"Cyprus"},
+ { 0x0358,"Finland"},
+ { 0x0359,"Bulgaria"},
+ { 0x036,"Hungary"},
+ { 0x0370,"Lithuania"},
+ { 0x0371,"Latvia"},
+ { 0x0372,"Estonia"},
+ { 0x0373,"Moldova"},
+ { 0x0374,"Armenia"},
+ { 0x0375,"Belarus"},
+ { 0x0376,"Andorra"},
+ { 0x0377,"Monaco"},
+ { 0x0378,"San Marino"},
+ { 0x0379,"Vatican"},
+ { 0x0380,"Ukraine"},
+ { 0x0381,"Yugoslavia"},
+ { 0x0382,"spare code"},
+ { 0x0383,"spare code"},
+ { 0x0384,"spare code"},
+ { 0x0385,"Croatia"},
+ { 0x0386,"Slovenia"},
+ { 0x0387,"Bosnia and Herzegovina"},
+ { 0x0388,"Groups of contries:"},
+ { 0x0389,"Macedonia"},
+ { 0x039,"Italy"},
+ { 0x040,"Romania"},
+ { 0x041,"Switzerland"},
+ { 0x0420,"Czech Republic"},
+ { 0x0421,"Slovak Republic"},
+ { 0x0422,"Spare code"},
+ { 0x0423,"Liechtenstein"},
+ { 0x0424,"spare code"},
+ { 0x0425,"spare code"},
+ { 0x0426,"spare code"},
+ { 0x0427,"spare code"},
+ { 0x0428,"spare code"},
+ { 0x0429,"spare code"},
+ { 0x043,"Austria"},
+ { 0x044,"United Kingdom"},
+ { 0x045,"Denmark"},
+ { 0x046,"Sweden"},
+ { 0x047,"Norway"},
+ { 0x048,"Poland"},
+ { 0x049,"Germany"},
+ { 0x0500,"Falkland Islands (Malvinas)"},
+ { 0x0501,"Belize"},
+ { 0x0502,"Guatemala"},
+ { 0x0503,"El Salvador"},
+ { 0x0504,"Honduras"},
+ { 0x0505,"Nicaragua"},
+ { 0x0506,"Costa Rica"},
+ { 0x0507,"Panama"},
+ { 0x0508,"Saint Pierre and Miquelon"},
+ { 0x0509,"Haiti"},
+ { 0x051,"Peru"},
+ { 0x052,"Mexico"},
+ { 0x053,"Cuba"},
+ { 0x054,"Argentina"},
+ { 0x055,"Brazil"},
+ { 0x056,"Chile"},
+ { 0x057,"Colombia"},
+ { 0x058,"Venezuela"},
+ { 0x0590,"Guadeloupe"},
+ { 0x0591,"Bolivia"},
+ { 0x0592,"Guyana"},
+ { 0x0593,"Ecuador"},
+ { 0x0594,"French Guiana"},
+ { 0x0595,"Paraguay"},
+ { 0x0596,"Martinique"},
+ { 0x0597,"Suriname"},
+ { 0x0598,"Uruguay"},
+ { 0x0599,"Netherlands Antilles"},
+ { 0x060,"Malaysia"},
+ { 0x061,"Australia"},
+ { 0x062,"Indonesia"},
+ { 0x063,"Philippines"},
+ { 0x064,"New Zealand"},
+ { 0x065,"Singapore"},
+ { 0x066,"Thailand"},
+ { 0x0670,"East Timor"},
+ { 0x0671,"Spare code"},
+ { 0x0672,"Australian External Territories"},
+ { 0x0673,"Brunei Darussalam"},
+ { 0x0674,"Nauru"},
+ { 0x0675,"Papua New Guinea"},
+ { 0x0676,"Tonga"},
+ { 0x0677,"Solomon Islands"},
+ { 0x0678,"Vanuatu"},
+ { 0x0679,"Fiji"},
+ { 0x0680,"Palau"},
+ { 0x0681,"Wallis and Futuna"},
+ { 0x0682,"Cook Islands"},
+ { 0x0683,"Niue"},
+ { 0x0684,"American Samoa"},
+ { 0x0685,"Samoa"},
+ { 0x0686,"Kiribati"},
+ { 0x0687,"New Caledonia"},
+ { 0x0688,"Tuvalu"},
+ { 0x0689,"French Polynesia"},
+ { 0x0690,"Tokelau"},
+ { 0x0691,"Micronesia"},
+ { 0x0692,"Marshall Islands"},
+ { 0x0693,"spare code"},
+ { 0x0694,"spare code"},
+ { 0x0695,"spare code"},
+ { 0x0696,"spare code"},
+ { 0x0697,"spare code"},
+ { 0x0698,"spare code"},
+ { 0x0699,"spare code"},
+ { 0x07,"Russian Federation,Kazakstan"},
+ { 0x0800,"International Freephone Service (see E.169.1)"},
+ { 0x0801,"spare code"},
+ { 0x0802,"spare code"},
+ { 0x0803,"spare code"},
+ { 0x0804,"spare code"},
+ { 0x0805,"spare code"},
+ { 0x0806,"spare code"},
+ { 0x0807,"spare code"},
+ { 0x0808,"Universal International Shared Cost Number (see E.169.3)"},
+ { 0x0809,"Spare code"},
+ { 0x081,"Japan"},
+ { 0x082,"Korea (Republic of)"},
+ { 0x0830,"Spare code"},
+ { 0x0831,"Spare code"},
+ { 0x0832,"Spare code"},
+ { 0x0833,"Spare code"},
+ { 0x0834,"Spare code"},
+ { 0x0835,"Spare code"},
+ { 0x0836,"Spare code"},
+ { 0x0837,"Spare code"},
+ { 0x0838,"Spare code"},
+ { 0x0839,"Spare code"},
+ { 0x084,"Viet Nam"},
+ { 0x0850,"Democratic People's Republic of Korea"},
+ { 0x0851,"Spare code"},
+ { 0x0852,"Hongkong, China"},
+ { 0x0853,"Macau, China"},
+ { 0x0854,"Spare code"},
+ { 0x0855,"Cambodia"},
+ { 0x0856,"Laos"},
+ { 0x0857,"Spare code"},
+ { 0x0858,"Spare code"},
+ { 0x0859,"Spare code"},
+ { 0x086,"China (People's Republic of)"},
+ { 0x0870,"Inmarsat SNAC"},
+ { 0x0871,"Inmarsat (Atlantic Ocean-East)"},
+ { 0x0872,"Inmarsat (Pacific Ocean)"},
+ { 0x0873,"Inmarsat (Indian Ocean)"},
+ { 0x0874,"Inmarsat (Atlantic Ocean-West)"},
+ { 0x0875,"Reserved - Maritime Mobile Service Applications"},
+ { 0x0876,"Reserved - Maritime Mobile Service Applications"},
+ { 0x0877,"Reserved - Maritime Mobile Service Applications"},
+ { 0x0878,"Reserved - Universal Personal Telecommunication Service (UPT)"},
+ { 0x0879,"Reserved for national non-commercial purposes"},
+ { 0x0880,"Bangladesh"},
+ { 0x0881,"Global Mobile Satellite System (GMSS), shared code:"},
+ { 0x0882,"International Networks: (see E.164)"},
+ { 0x0883,"Spare code"},
+ { 0x0884,"Spare code"},
+ { 0x0885,"Spare code"},
+ { 0x0886,"Reserved"},
+ { 0x0887,"Spare code"},
+ { 0x0888,"Reserved for future global services (see E.164)"},
+ { 0x0889,"Spare code"},
+ { 0x0890,"Spare code"},
+ { 0x0891,"Spare code"},
+ { 0x0892,"Spare code"},
+ { 0x0893,"Spare code"},
+ { 0x0894,"Spare code"},
+ { 0x0895,"Spare code"},
+ { 0x0896,"Spare code"},
+ { 0x0897,"Spare code"},
+ { 0x0898,"Spare code"},
+ { 0x0899,"Spare code"},
+ { 0x090,"Turkey"},
+ { 0x091,"India"},
+ { 0x092,"Pakistan"},
+ { 0x093,"Afghanistan"},
+ { 0x094,"Sri Lanka"},
+ { 0x095,"Myanmar"},
+ { 0x0960,"Maldives"},
+ { 0x0961,"Lebanon"},
+ { 0x0962,"Jordan"},
+ { 0x0963,"Syrian Arab Republic"},
+ { 0x0964,"Iraq"},
+ { 0x0965,"Kuwait"},
+ { 0x0966,"Saudi Arabia"},
+ { 0x0967,"Yemen"},
+ { 0x0968,"Oman"},
+ { 0x0969,"Reserved"},
+ { 0x0970,"Reserved"},
+ { 0x0971,"United Arab Emirates"},
+ { 0x0972,"Israel"},
+ { 0x0973,"Bahrain"},
+ { 0x0974,"Qatar"},
+ { 0x0975,"Bhutan"},
+ { 0x0976,"Mongolia"},
+ { 0x0977,"Nepal"},
+ { 0x0978,"Spare code"},
+ { 0x0979,"Universal International Premium Rate Number (see E.169.2)"},
+ { 0x098,"Iran"},
+ { 0x0990,"Spare code"},
+ { 0x0991,"Trial service (see E.164.2)"},
+ { 0x0992,"Tajikstan"},
+ { 0x0993,"Turkmenistan"},
+ { 0x0994,"Azerbaijani Republic"},
+ { 0x0995,"Georgia"},
+ { 0x0996,"Kyrgyz Republic"},
+ { 0x0997,"Spare code"},
+ { 0x0998,"Uzbekistan"},
+ { 0x0999,"Spare code"},
+ { 0, NULL }
+};
+const value_string E164_International_Networks_vals[] = {
+ { 0x10, "British Telecommunications"},
+ { 0x11, "Singapore Telecommunications"},
+ { 0x12, "MCIWorldCom"},
+ { 0x13, "Telespazio"},
+ { 0x14, "GTE"},
+ { 0x15, "Telstra"},
+ { 0x16, "United Arab Emirates"},
+ { 0x17, "AT&T"},
+ { 0x18, "Teledesic"},
+ { 0x19, "Telecom Italia"},
+ { 0x20, "Asia Cellular Satellite"},
+ { 0x21, "Ameritech"},
+ { 0x22, "Cable & Wireless"},
+ { 0x23, "Sita-Equant"},
+ { 0x24, "Telia AB"},
+ { 0x25, "Constellation Communications"},
+ { 0x26, "SBC Communications"},
+ { 0, NULL }
+};
+
+static int proto_e164 = -1;
+static int hf_E164_calling_party_number = -1;
+static int hf_E164_called_party_number = -1;
+
+
+
+void
+dissect_e164_number(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length,e164_info_t e164_info)
+{
+ switch (e164_info.e164_number_type){
+ case CALLING_PARTY_NUMBER :
+ proto_tree_add_string(tree, hf_E164_calling_party_number, tvb, offset,
+ length, e164_info.E164_number_str);
+ break;
+
+ case CALLED_PARTY_NUMBER :
+ proto_tree_add_string(tree, hf_E164_called_party_number, tvb, offset,
+ length, e164_info.E164_number_str);
+ break;
+
+
+ default:;
+ break;
+ }
+
+}
+/*
+ * Register the protocol with Ethereal.
+ *
+ * This format is required because a script is used to build the C function
+ * that calls all the protocol registration.
+ */
+
+void
+proto_register_e164(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details */
+ static hf_register_info hf[] = {
+ { &hf_E164_calling_party_number,
+ { "E.164 Calling party number digits", "e164.calling_party_number.digits",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_E164_called_party_number,
+ { "E.164 Called party number digits", "e164.called_party_number.digits",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ };
+
+ /*
+ * Register the protocol name and description
+ */
+ proto_e164 = proto_register_protocol(
+ "ITU-T E.164 number",
+ "E.164",
+ "e164");
+
+ /*
+ * Required function calls to register
+ * the header fields and subtrees used.
+ */
+ proto_register_field_array(proto_e164, hf, array_length(hf));
+
+}
diff --git a/epan/dissectors/packet-e164.h b/epan/dissectors/packet-e164.h
new file mode 100644
index 0000000000..a9d2ced989
--- /dev/null
+++ b/epan/dissectors/packet-e164.h
@@ -0,0 +1,50 @@
+/* packet-e164.h
+ * E164 tables
+ * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_E164_H__
+#define __PACKET_E164_H__
+
+#include "epan/value_string.h"
+
+extern const value_string E164_country_code_value[];
+extern const value_string E164_International_Networks_vals[];
+
+typedef enum {
+ NONE,
+ CALLING_PARTY_NUMBER,
+ CALLED_PARTY_NUMBER
+ } e164_number_type_t;
+
+typedef struct {
+ e164_number_type_t e164_number_type;
+ guint nature_of_address;
+ char *E164_number_str; /* E164 number string */
+ guint E164_number_length; /* Length of the E164_number string */
+} e164_info_t;
+
+
+extern void dissect_e164_number(tvbuff_t *tvb, proto_tree *tree, int offset, int length,
+ e164_info_t e164_info);
+#endif
diff --git a/epan/dissectors/packet-eap.c b/epan/dissectors/packet-eap.c
new file mode 100644
index 0000000000..d419598a1e
--- /dev/null
+++ b/epan/dissectors/packet-eap.c
@@ -0,0 +1,1166 @@
+/* packet-eap.c
+ * Routines for EAP Extensible Authentication Protocol dissection
+ * RFC 2284, RFC 3748
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "ppptypes.h"
+#include "reassemble.h"
+
+static int proto_eap = -1;
+static int hf_eap_code = -1;
+static int hf_eap_identifier = -1;
+static int hf_eap_len = -1;
+static int hf_eap_type = -1;
+static int hf_eap_type_nak = -1;
+
+static gint ett_eap = -1;
+
+static dissector_handle_t ssl_handle;
+
+#define EAP_REQUEST 1
+#define EAP_RESPONSE 2
+#define EAP_SUCCESS 3
+#define EAP_FAILURE 4
+
+static const value_string eap_code_vals[] = {
+ { EAP_REQUEST, "Request" },
+ { EAP_RESPONSE, "Response" },
+ { EAP_SUCCESS, "Success" },
+ { EAP_FAILURE, "Failure" },
+ { 0, NULL }
+};
+
+/*
+References:
+ 1) http://www.iana.org/assignments/ppp-numbers
+ PPP EAP REQUEST/RESPONSE TYPES
+ 2) http://www.ietf.org/internet-drafts/draft-ietf-pppext-rfc2284bis-02.txt
+ 3) RFC2284
+ 4) RFC3748
+ 5) http://www.iana.org/assignments/eap-numbers EAP registry
+*/
+
+#define EAP_TYPE_ID 1
+#define EAP_TYPE_NOTIFY 2
+#define EAP_TYPE_NAK 3
+#define EAP_TYPE_MD5 4
+#define EAP_TYPE_TLS 13
+#define EAP_TYPE_LEAP 17
+#define EAP_TYPE_SIM 18
+#define EAP_TYPE_TTLS 21
+#define EAP_TYPE_PEAP 25
+#define EAP_TYPE_MSCHAPV2 26
+
+static const value_string eap_type_vals[] = {
+ {EAP_TYPE_ID, "Identity [RFC3748]" },
+ {EAP_TYPE_NOTIFY,"Notification [RFC3748]" },
+ {EAP_TYPE_NAK, "Nak (Response only) [RFC3748]" },
+ {EAP_TYPE_MD5, "MD5-Challenge [RFC3748]" },
+ { 5, "One Time Password (OTP) [RFC2289]" },
+ { 6, "Generic Token Card [RFC3748]" },
+ { 7, "?? RESERVED ?? " }, /* ??? */
+ { 8, "?? RESERVED ?? " }, /* ??? */
+ { 9, "RSA Public Key Authentication [Whelan]" },
+ { 10, "DSS Unilateral [Nace]" },
+ { 11, "KEA [Nace]" },
+ { 12, "KEA-VALIDATE [Nace]" },
+ {EAP_TYPE_TLS, "EAP-TLS [RFC2716] [Aboba]" },
+ { 14, "Defender Token (AXENT) [Rosselli]" },
+ { 15, "RSA Security SecurID EAP [Asnes, Liberman]" },
+ { 16, "Arcot Systems EAP [Jerdonek]" },
+ {EAP_TYPE_LEAP,"EAP-Cisco Wireless (LEAP) [Norman]" },
+ {EAP_TYPE_SIM, "EAP-SIM Nokia IP smart card authentication [Haverinen]" },
+ { 19, "SRP-SHA1 Part 1 [Carlson]" },
+ { 20, "SRP-SHA1 Part 2 [Carlson]" },
+ {EAP_TYPE_TTLS,"EAP-TTLS [Funk]" },
+ { 22, "Remote Access Service [Fields]" },
+ { 23, "UMTS Authentication and Key Agreement [Haverinen]" },
+ { 24, "EAP-3Com Wireless [Young]" },
+ {EAP_TYPE_PEAP,"PEAP [Palekar]" },
+ {EAP_TYPE_MSCHAPV2,"MS-EAP-Authentication [Palekar]" },
+ { 27, "Mutual Authentication w/Key Exchange (MAKE)[Berrendonner]" },
+ { 28, "CRYPTOCard [Webb]" },
+ { 29, "EAP-MSCHAP-V2 [Potter]" },
+ { 30, "DynamID [Merlin]" },
+ { 31, "Rob EAP [Ullah]" },
+ { 32, "SecurID EAP [Josefsson]" },
+ { 33, "MS-Authentication-TLV [Palekar]" },
+ { 34, "SentriNET [Kelleher]" },
+ { 35, "EAP-Actiontec Wireless [Chang]" },
+ { 36, "Cogent Systems Biometrics Authentication EAP [Xiong]" },
+ { 37, "AirFortress EAP [Hibbard]" },
+ { 38, "EAP-HTTP Digest [Tavakoli]" },
+ { 39, "SecureSuite EAP [Clements]" },
+ { 40, "DeviceConnect EAP [Pitard]" },
+ { 41, "EAP-SPEKE [Zick]" },
+ { 42, "EAP-MOBAC [Rixom]" },
+ { 43, "EAP-FAST [Cam-Winget]" },
+ { 44, "ZoneLabs EAP (ZLXEAP) [Bogue]" },
+ { 45, "EAP-Link [Zick]" },
+ { 254, "RESERVED for the Expanded Type [RFC3748]" },
+ { 255, "EXPERIMENTAL [RFC3748]" },
+ { 0, NULL }
+
+};
+
+/*
+ * State information for EAP-TLS (RFC2716) and Lightweight EAP:
+ *
+ * http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
+ *
+ * Attach to all conversations:
+ *
+ * a sequence number to be handed to "fragment_add_seq()" as
+ * the fragment sequence number - if it's -1, no reassembly
+ * is in progress, but if it's not, it's the sequence number
+ * to use for the current fragment;
+ *
+ * a value to be handed to "fragment_add_seq()" as the
+ * reassembly ID - when a reassembly is started, it's set to
+ * the frame number of the current frame, i.e. the frame
+ * that starts the reassembly;
+ *
+ * an indication of the current state of LEAP negotiation,
+ * with -1 meaning no LEAP negotiation is in progress.
+ *
+ * Attach to frames containing fragments of EAP-TLS messages the
+ * reassembly ID for those fragments, so we can find the reassembled
+ * data after the first pass through the packets.
+ *
+ * Attach to LEAP frames the state of the LEAP negotiation when the
+ * frame was processed, so we can properly dissect
+ * the LEAP message after the first pass through the packets.
+ *
+ * Attach to all conversations both pieces of information, to keep
+ * track of EAP-TLS reassembly and the LEAP state machine.
+ */
+static GMemChunk *conv_state_chunk = NULL;
+
+typedef struct {
+ int eap_tls_seq;
+ guint32 eap_reass_cookie;
+ int leap_state;
+} conv_state_t;
+
+static GMemChunk *frame_state_chunk = NULL;
+
+typedef struct {
+ int info; /* interpretation depends on EAP message type */
+} frame_state_t;
+
+/*********************************************************************
+ EAP-TLS
+RFC2716
+**********************************************************************/
+
+/*
+from RFC2716, pg 17
+
+ Flags
+
+ 0 1 2 3 4 5 6 7 8
+ +-+-+-+-+-+-+-+-+
+ |L M S R R Vers |
+ +-+-+-+-+-+-+-+-+
+
+ L = Length included
+ M = More fragments
+ S = EAP-TLS start
+ R = Reserved
+ Vers = PEAP version (Reserved for TLS and TTLS)
+*/
+
+#define EAP_TLS_FLAG_L 0x80 /* Length included */
+#define EAP_TLS_FLAG_M 0x40 /* More fragments */
+#define EAP_TLS_FLAG_S 0x20 /* EAP-TLS start */
+#define EAP_PEAP_FLAG_VERSION 0x07 /* EAP-PEAP version */
+
+/*
+ * reassembly of EAP-TLS
+ */
+static GHashTable *eaptls_fragment_table = NULL;
+
+static int hf_eaptls_fragment = -1;
+static int hf_eaptls_fragments = -1;
+static int hf_eaptls_fragment_overlap = -1;
+static int hf_eaptls_fragment_overlap_conflict = -1;
+static int hf_eaptls_fragment_multiple_tails = -1;
+static int hf_eaptls_fragment_too_long_fragment = -1;
+static int hf_eaptls_fragment_error = -1;
+static gint ett_eaptls_fragment = -1;
+static gint ett_eaptls_fragments = -1;
+static gint ett_eap_sim_attr = -1;
+
+static const fragment_items eaptls_frag_items = {
+ &ett_eaptls_fragment,
+ &ett_eaptls_fragments,
+ &hf_eaptls_fragments,
+ &hf_eaptls_fragment,
+ &hf_eaptls_fragment_overlap,
+ &hf_eaptls_fragment_overlap_conflict,
+ &hf_eaptls_fragment_multiple_tails,
+ &hf_eaptls_fragment_too_long_fragment,
+ &hf_eaptls_fragment_error,
+ NULL,
+ "fragments"
+};
+
+/*********************************************************************
+**********************************************************************/
+
+static gboolean
+test_flag(unsigned char flag, unsigned char mask)
+{
+ return ( ( flag & mask ) != 0 );
+}
+
+static void
+eaptls_defragment_init(void)
+{
+ fragment_table_init(&eaptls_fragment_table);
+}
+
+static void
+eap_init_protocol(void)
+{
+ if (conv_state_chunk != NULL)
+ g_mem_chunk_destroy(conv_state_chunk);
+ if (frame_state_chunk != NULL)
+ g_mem_chunk_destroy(frame_state_chunk);
+
+ conv_state_chunk = g_mem_chunk_new("conv_state_chunk",
+ sizeof (conv_state_t),
+ 10 * sizeof (conv_state_t),
+ G_ALLOC_ONLY);
+
+ frame_state_chunk = g_mem_chunk_new("frame_state_chunk",
+ sizeof (frame_state_t),
+ 100 * sizeof (frame_state_t),
+ G_ALLOC_ONLY);
+}
+
+static void
+dissect_eap_mschapv2(proto_tree *eap_tree, tvbuff_t *tvb, int offset,
+ gint size)
+{
+ gint left = size;
+ gint ms_len;
+ guint8 value_size;
+ enum {
+ MS_CHAPv2_CHALLENGE = 1,
+ MS_CHAPv2_RESPONSE = 2,
+ MS_CHAPv2_SUCCESS = 3,
+ MS_CHAPv2_FAILURE = 4,
+ MS_CHAPv2_CHANGE_PASSWORD = 5
+ } opcode;
+ static const value_string opcodes[] = {
+ { MS_CHAPv2_CHALLENGE, "Challenge" },
+ { MS_CHAPv2_RESPONSE, "Response" },
+ { MS_CHAPv2_SUCCESS, "Success" },
+ { MS_CHAPv2_FAILURE, "Failure" },
+ { MS_CHAPv2_CHANGE_PASSWORD, "Change-Password" },
+ { 0, NULL }
+ };
+
+ /* OpCode (1 byte), MS-CHAPv2-ID (1 byte), MS-Length (2 bytes), Data */
+ opcode = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(eap_tree, tvb, offset, 1,
+ "OpCode: %d (%s)",
+ opcode, val_to_str(opcode, opcodes, "Unknown"));
+ offset++;
+ left--;
+ if (left <= 0)
+ return;
+
+ proto_tree_add_text(eap_tree, tvb, offset, 1, "MS-CHAPv2-ID: %d",
+ tvb_get_guint8(tvb, offset));
+ offset++;
+ left--;
+ if (left <= 0)
+ return;
+
+ ms_len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(eap_tree, tvb, offset, 2, "MS-Length: %d%s",
+ ms_len,
+ ms_len != size ? " (invalid len)" : "");
+ offset += 2;
+ left -= 2;
+
+ switch (opcode) {
+ case MS_CHAPv2_CHALLENGE:
+ if (left <= 0)
+ break;
+ value_size = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(eap_tree, tvb, offset, 1,
+ "Value-Size: %d", value_size);
+ offset++;
+ left--;
+ proto_tree_add_text(eap_tree, tvb, offset, value_size,
+ "Challenge: %s",
+ tvb_bytes_to_str(tvb, offset, value_size));
+ offset += value_size;
+ left -= value_size;
+ if (left <= 0)
+ break;
+ proto_tree_add_text(eap_tree, tvb, offset, left,
+ "Name: %s",
+ tvb_format_text(tvb, offset, left));
+ break;
+ case MS_CHAPv2_RESPONSE:
+ if (left <= 0)
+ break;
+ value_size = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(eap_tree, tvb, offset, 1,
+ "Value-Size: %d", value_size);
+ offset++;
+ left--;
+ if (value_size == 49) {
+ proto_tree_add_text(eap_tree, tvb, offset, 16,
+ "Peer-Challenge: %s",
+ tvb_bytes_to_str(tvb, offset, 16));
+ offset += 16;
+ proto_tree_add_text(eap_tree, tvb, offset, 8,
+ "Reserved, must be zero: %s",
+ tvb_bytes_to_str(tvb, offset, 8));
+ offset += 8;
+ proto_tree_add_text(eap_tree, tvb, offset, 24,
+ "NT-Response: %s",
+ tvb_bytes_to_str(tvb, offset, 24));
+ offset += 24;
+ proto_tree_add_text(eap_tree, tvb, offset, 1,
+ "Flags: %d",
+ tvb_get_guint8(tvb, offset));
+ offset++;
+ left -= value_size;
+ } else {
+ proto_tree_add_text(eap_tree, tvb, offset, value_size,
+ "Response (unknown length): %s",
+ tvb_bytes_to_str(tvb, offset,
+ value_size));
+ offset += value_size;
+ left -= value_size;
+ }
+ if (left <= 0)
+ break;
+ proto_tree_add_text(eap_tree, tvb, offset, left,
+ "Name: %s",
+ tvb_format_text(tvb, offset, left));
+ break;
+ case MS_CHAPv2_SUCCESS:
+ if (left <= 0)
+ break;
+ proto_tree_add_text(eap_tree, tvb, offset, left,
+ "Message: %s",
+ tvb_format_text(tvb, offset, left));
+ break;
+ case MS_CHAPv2_FAILURE:
+ if (left <= 0)
+ break;
+ proto_tree_add_text(eap_tree, tvb, offset, left,
+ "Failure Request: %s",
+ tvb_format_text(tvb, offset, left));
+ break;
+ default:
+ proto_tree_add_text(eap_tree, tvb, offset, left,
+ "Data (%d byte%s) Value: %s",
+ left, plurality(left, "", "s"),
+ tvb_bytes_to_str(tvb, offset, left));
+ break;
+ }
+}
+
+static void
+dissect_eap_sim(proto_tree *eap_tree, tvbuff_t *tvb, int offset, gint size)
+{
+ gint left = size;
+ enum {
+ SIM_START = 10,
+ SIM_CHALLENGE = 11,
+ SIM_NOTIFICATION = 12,
+ SIM_RE_AUTHENTICATION = 13,
+ SIM_CLIENT_ERROR = 14
+ } subtype;
+ static const value_string subtypes[] = {
+ { SIM_START, "Start" },
+ { SIM_CHALLENGE, "Challenge" },
+ { SIM_NOTIFICATION, "Notification" },
+ { SIM_RE_AUTHENTICATION, "Re-authentication" },
+ { SIM_CLIENT_ERROR, "Client-Error" },
+ { 0, NULL }
+ };
+ static const value_string attributes[] = {
+ { 1, "AT_RAND" },
+ { 6, "AT_PADDING" },
+ { 7, "AT_NONCE_MT" },
+ { 10, "AT_PERMANENT_ID_REQ" },
+ { 11, "AT_MAC" },
+ { 12, "AT_NOTIFICATION" },
+ { 13, "AT_ANY_ID_REQ" },
+ { 14, "AT_IDENTITY" },
+ { 15, "AT_VERSION_LIST" },
+ { 16, "AT_SELECTED_VERSION" },
+ { 17, "AT_FULLAUTH_ID_REQ" },
+ { 18, "AT_COUNTER" },
+ { 19, "AT_COUNTER_TOO_SMALL" },
+ { 20, "AT_NONCE_S" },
+ { 21, "AT_CLIENT_ERROR_CODE" },
+ { 129, "AT_IV" },
+ { 130, "AT_ENCR_DATA" },
+ { 132, "AT_NEXT_PSEUDONYM" },
+ { 133, "AT_NEXT_REAUTH_ID" },
+ { 0, NULL }
+ };
+
+ subtype = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(eap_tree, tvb, offset, 1,
+ "subtype: %d (%s)",
+ subtype, val_to_str(subtype, subtypes, "Unknown"));
+
+ offset++;
+ left--;
+
+ if (left < 2)
+ return;
+ proto_tree_add_text(eap_tree, tvb, offset, 2, "Reserved: %d",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ left -= 2;
+
+ /* Rest of EAP-SIM data is in Type-Len-Value format. */
+ while (left >= 2) {
+ guint8 type, length;
+ proto_item *pi;
+ proto_tree *attr_tree;
+ int aoffset;
+ gint aleft;
+ aoffset = offset;
+ type = tvb_get_guint8(tvb, aoffset);
+ length = tvb_get_guint8(tvb, aoffset + 1);
+ aleft = 4 * length;
+
+ pi = proto_tree_add_text(eap_tree, tvb, aoffset, aleft,
+ "Attribute: %s",
+ val_to_str(type, attributes,
+ "Unknown %u"));
+ attr_tree = proto_item_add_subtree(pi, ett_eap_sim_attr);
+ proto_tree_add_text(attr_tree, tvb, aoffset, 1,
+ "Type: %u", type);
+ aoffset++;
+ aleft--;
+
+ if (aleft <= 0)
+ break;
+ proto_tree_add_text(attr_tree, tvb, aoffset, 1,
+ "Length: %d (%d bytes)",
+ length, 4 * length);
+ aoffset++;
+ aleft--;
+ proto_tree_add_text(attr_tree, tvb, aoffset, aleft,
+ "Value: %s",
+ tvb_bytes_to_str(tvb, aoffset, aleft));
+
+ offset += 4 * length;
+ left -= 4 * length;
+ }
+}
+
+static int
+dissect_eap_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean fragmented)
+{
+ guint8 eap_code;
+ guint8 eap_id;
+ guint16 eap_len;
+ guint8 eap_type;
+ gint len;
+ conversation_t *conversation;
+ conv_state_t *conversation_state;
+ frame_state_t *packet_state;
+ int leap_state;
+ proto_tree *ti;
+ proto_tree *eap_tree = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ eap_code = tvb_get_guint8(tvb, 0);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(eap_code, eap_code_vals, "Unknown code (0x%02X)"));
+
+ /*
+ * Find a conversation to which we belong; create one if we don't find
+ * it.
+ *
+ * We use the source and destination addresses, and the *matched* port
+ * number, because if this is running over RADIUS, there's no guarantee
+ * that the source port number for request and the destination port
+ * number for replies will be the same in all messages - the client
+ * may use different port numbers for each request.
+ *
+ * We have to pair up the matched port number with the corresponding
+ * address; we determine which that is by comparing it with the
+ * destination port - if it matches, we matched on the destination
+ * port (this is a request), otherwise we matched on the source port
+ * (this is a reply).
+ *
+ * XXX - what if we're running over a TCP or UDP protocol with a
+ * heuristic dissector, meaning the matched port number won't be set?
+ *
+ * XXX - what if we have a capture file with captures on multiple
+ * PPP interfaces, with LEAP traffic on all of them? How can we
+ * keep them separate? (Or is that not going to happen?)
+ */
+ if (pinfo->destport == pinfo->match_port) {
+ conversation = find_conversation(&pinfo->dst, &pinfo->src,
+ pinfo->ptype, pinfo->destport,
+ 0, NO_PORT_B);
+ } else {
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ 0, NO_PORT_B);
+ }
+ if (conversation == NULL) {
+ if (pinfo->destport == pinfo->match_port) {
+ conversation = conversation_new(&pinfo->dst, &pinfo->src,
+ pinfo->ptype, pinfo->destport,
+ 0, NO_PORT2);
+ } else {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ 0, NO_PORT2);
+ }
+ }
+
+ /*
+ * Get the state information for the conversation; attach some if
+ * we don't find it.
+ */
+ conversation_state = conversation_get_proto_data(conversation, proto_eap);
+ if (conversation_state == NULL) {
+ /*
+ * Attach state information to the conversation.
+ */
+ conversation_state = g_mem_chunk_alloc(conv_state_chunk);
+ conversation_state->eap_tls_seq = -1;
+ conversation_state->eap_reass_cookie = 0;
+ conversation_state->leap_state = -1;
+ conversation_add_proto_data(conversation, proto_eap, conversation_state);
+ }
+
+ /*
+ * Set this now, so that it gets remembered even if we throw an exception
+ * later.
+ */
+ if (eap_code == EAP_FAILURE)
+ conversation_state->leap_state = -1;
+
+ eap_id = tvb_get_guint8(tvb, 1);
+
+ eap_len = tvb_get_ntohs(tvb, 2);
+ len = eap_len;
+
+ if (fragmented) {
+ /*
+ * This is an EAP fragment inside, for example, RADIUS. If we don't
+ * have all of the packet data, return the negative of the amount of
+ * additional data we need.
+ */
+ int reported_len = tvb_reported_length_remaining(tvb, 0);
+
+ if (reported_len < len)
+ return -(len - reported_len);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_eap, tvb, 0, len, FALSE);
+ eap_tree = proto_item_add_subtree(ti, ett_eap);
+
+ proto_tree_add_uint(eap_tree, hf_eap_code, tvb, 0, 1, eap_code);
+ }
+
+ if (tree)
+ proto_tree_add_item(eap_tree, hf_eap_identifier, tvb, 1, 1, FALSE);
+
+ if (tree)
+ proto_tree_add_uint(eap_tree, hf_eap_len, tvb, 2, 2, eap_len);
+
+ switch (eap_code) {
+
+ case EAP_SUCCESS:
+ case EAP_FAILURE:
+ break;
+
+ case EAP_REQUEST:
+ case EAP_RESPONSE:
+ eap_type = tvb_get_guint8(tvb, 4);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(eap_type, eap_type_vals,
+ "Unknown type (0x%02X)"));
+ if (tree)
+ proto_tree_add_uint(eap_tree, hf_eap_type, tvb, 4, 1, eap_type);
+
+ if (len > 5) {
+ int offset = 5;
+ gint size = len - offset;
+
+ switch (eap_type) {
+ /*********************************************************************
+ **********************************************************************/
+ case EAP_TYPE_ID:
+ if (tree) {
+ proto_tree_add_text(eap_tree, tvb, offset, size,
+ "Identity (%d byte%s): %s",
+ size, plurality(size, "", "s"),
+ tvb_format_text(tvb, offset, size));
+ }
+ if(!pinfo->fd->flags.visited)
+ conversation_state->leap_state = 0;
+ break;
+
+ /*********************************************************************
+ **********************************************************************/
+ case EAP_TYPE_NOTIFY:
+ if (tree) {
+ proto_tree_add_text(eap_tree, tvb, offset, size,
+ "Notification (%d byte%s): %s",
+ size, plurality(size, "", "s"),
+ tvb_format_text(tvb, offset, size));
+ }
+ break;
+ /*********************************************************************
+ **********************************************************************/
+ case EAP_TYPE_NAK:
+ if (tree) {
+ proto_tree_add_item(eap_tree, hf_eap_type_nak, tvb,
+ offset, 1, FALSE);
+ }
+ break;
+ /*********************************************************************
+ **********************************************************************/
+ case EAP_TYPE_MD5:
+ if (tree) {
+ guint8 value_size = tvb_get_guint8(tvb, offset);
+ gint extra_len = size - 1 - value_size;
+ proto_tree_add_text(eap_tree, tvb, offset, 1, "Value-Size: %d%s",
+ value_size,
+ value_size > size - 1 ? " (overflow)": "");
+ if (value_size > size - 1)
+ value_size = size - 1;
+ offset++;
+ proto_tree_add_text(eap_tree, tvb, offset, value_size,
+ "Value: %s",
+ tvb_bytes_to_str(tvb, offset, value_size));
+ offset += value_size;
+ if (extra_len > 0) {
+ proto_tree_add_text(eap_tree, tvb, offset, extra_len,
+ "Extra data (%d byte%s): %s", extra_len,
+ plurality(extra_len, "", "s"),
+ tvb_bytes_to_str(tvb, offset, extra_len));
+ }
+ }
+ break;
+ /*********************************************************************
+ EAP-TLS
+ **********************************************************************/
+ case EAP_TYPE_PEAP:
+ case EAP_TYPE_TTLS:
+ case EAP_TYPE_TLS:
+ {
+ guint8 flags = tvb_get_guint8(tvb, offset);
+ gboolean more_fragments;
+ gboolean has_length;
+ guint32 length;
+ int eap_tls_seq = -1;
+ guint32 eap_reass_cookie = 0;
+ gboolean needs_reassembly = FALSE;
+
+ more_fragments = test_flag(flags,EAP_TLS_FLAG_M);
+ has_length = test_flag(flags,EAP_TLS_FLAG_L);
+
+ /* Flags field, 1 byte */
+ if (tree) {
+ proto_tree_add_text(eap_tree, tvb, offset, 1, "Flags(0x%X): %s%s%s",
+ flags,
+ has_length ? "Length ":"",
+ more_fragments ? "More " :"",
+ test_flag(flags,EAP_TLS_FLAG_S) ? "Start " :"");
+ if (eap_type == EAP_TYPE_PEAP) {
+ proto_tree_add_text(eap_tree, tvb, offset, 1,
+ "PEAP version %d",
+ flags & EAP_PEAP_FLAG_VERSION);
+ }
+ }
+ size--;
+ offset++;
+
+ /* Length field, 4 bytes, OPTIONAL. */
+ if ( has_length ) {
+ length = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ proto_tree_add_text(eap_tree, tvb, offset, 4, "Length: %i",length);
+ size -= 4;
+ offset += 4;
+ }
+
+ if (size>0) {
+
+ tvbuff_t *next_tvb;
+ gint tvb_len;
+ gboolean save_fragmented;
+
+ tvb_len = tvb_length_remaining(tvb, offset);
+ if (size < tvb_len)
+ tvb_len = size;
+
+ /*
+ EAP/TLS is weird protocol (it comes from
+ Microsoft after all).
+
+ If we have series of fragmented packets,
+ then there's no way of knowing that from
+ the packet itself, if it is the last packet
+ in series, that is that the packet part of
+ bigger fragmented set of data.
+
+ The only way to know is, by knowing
+ that we are already in defragmentation
+ "mode" and we are expecing packet
+ carrying fragment of data. (either
+ because we have not received expected
+ amount of data, or because the packet before
+ had "F"ragment flag set.)
+
+ The situation is alleviated by fact that it
+ is simple ack/nack protcol so there's no
+ place for out-of-order packets like it is
+ possible with IP.
+
+ Anyway, point of this lengthy essay is that
+ we have to keep state information in the
+ conversation, so that we can put ourselves in
+ defragmenting mode and wait for the last packet,
+ and have to attach state to frames as well, so
+ that we can handle defragmentation after the
+ first pass through the capture.
+ */
+ /* See if we have a remembered defragmentation EAP ID. */
+ packet_state = p_get_proto_data(pinfo->fd, proto_eap);
+ if (packet_state == NULL) {
+ /*
+ * We haven't - does this message require reassembly?
+ */
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * This is the first time we've looked at this frame,
+ * so it wouldn't have any remembered information.
+ *
+ * Therefore, we check whether this conversation has
+ * a reassembly operation in progress, or whether
+ * this frame has the Fragment flag set.
+ */
+ if (conversation_state->eap_tls_seq != -1) {
+ /*
+ * There's a reassembly in progress; the sequence number
+ * of the previous fragment is
+ * "conversation_state->eap_tls_seq", and the reassembly
+ * ID is "conversation_state->eap_reass_cookie".
+ *
+ * We must include this frame in the reassembly.
+ * We advance the sequence number, giving us the
+ * sequence number for this fragment.
+ */
+ needs_reassembly = TRUE;
+ conversation_state->eap_tls_seq++;
+
+ eap_reass_cookie = conversation_state->eap_reass_cookie;
+ eap_tls_seq = conversation_state->eap_tls_seq;
+ } else if (more_fragments && has_length) {
+ /*
+ * This message has the Fragment flag set, so it requires
+ * reassembly. It's the message containing the first
+ * fragment (if it's a later fragment, the sequence
+ * number in the conversation state would not be -1).
+ *
+ * If it doesn't include a length, however, we can't
+ * do reassembly (either the message is in error, as
+ * the first fragment *must* contain a length, or we
+ * didn't capture the first fragment, and this just
+ * happens to be the first fragment we saw), so we
+ * also check that we have a length;
+ */
+ needs_reassembly = TRUE;
+ conversation_state->eap_reass_cookie = pinfo->fd->num;
+
+ /*
+ * Start the reassembly sequence number at 0.
+ */
+ conversation_state->eap_tls_seq = 0;
+
+ eap_tls_seq = conversation_state->eap_tls_seq;
+ eap_reass_cookie = conversation_state->eap_reass_cookie;
+ }
+
+ if (needs_reassembly) {
+ /*
+ * This frame requires reassembly; remember the reassembly
+ * ID for subsequent accesses to it.
+ */
+ packet_state = g_mem_chunk_alloc(frame_state_chunk);
+ packet_state->info = eap_reass_cookie;
+ p_add_proto_data(pinfo->fd, proto_eap, packet_state);
+ }
+ }
+ } else {
+ /*
+ * This frame has a reassembly cookie associated with it, so
+ * it requires reassembly. We've already done the
+ * reassembly in the first pass, so "fragment_add_seq()"
+ * won't look at the sequence number; set it to 0.
+ *
+ * XXX - a frame isn't supposed to have more than one
+ * EAP message in it, but if it includes both an EAP-TLS
+ * message and a LEAP message, we might be mistakenly
+ * concluding it requires reassembly because the "info"
+ * field isn't -1. We could, I guess, pack both EAP-TLS
+ * ID and LEAP state into the structure, but that doesn't
+ * work if you have multiple EAP-TLS or LEAP messages in
+ * the frame.
+ *
+ * But it's not clear how much work we should do to handle
+ * a bogus message such as that; as long as we don't crash
+ * or do something else equally horrible, we may not
+ * have to worry about this at all.
+ */
+ needs_reassembly = TRUE;
+ eap_reass_cookie = packet_state->info;
+ eap_tls_seq = 0;
+ }
+
+ /*
+ We test here to see whether EAP-TLS packet
+ carry fragmented of TLS data.
+
+ If this is the case, we do reasembly below,
+ otherwise we just call dissector.
+ */
+ if (needs_reassembly) {
+ fragment_data *fd_head = NULL;
+
+ /*
+ * Yes, this frame contains a fragment that requires
+ * reassembly.
+ */
+ save_fragmented = pinfo->fragmented;
+ pinfo->fragmented = TRUE;
+ fd_head = fragment_add_seq(tvb, offset, pinfo,
+ eap_reass_cookie,
+ eaptls_fragment_table,
+ eap_tls_seq,
+ size,
+ more_fragments);
+
+ if (fd_head != NULL) /* Reassembled */
+ {
+
+ next_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->len,
+ fd_head->len);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb, "Reassembled EAP-TLS");
+
+ show_fragment_seq_tree(fd_head, &eaptls_frag_items,
+ eap_tree, pinfo, next_tvb);
+
+ call_dissector(ssl_handle, next_tvb, pinfo, eap_tree);
+
+ /*
+ * We're finished reassembing this frame.
+ * Reinitialize the reassembly state.
+ */
+ if (!pinfo->fd->flags.visited)
+ conversation_state->eap_tls_seq = -1;
+ }
+
+ pinfo->fragmented = save_fragmented;
+
+ } else { /* this data is NOT fragmented */
+ next_tvb = tvb_new_subset(tvb, offset, tvb_len, size);
+ call_dissector(ssl_handle, next_tvb, pinfo, eap_tree);
+ }
+ }
+ }
+ break; /* EAP_TYPE_TLS */
+ /*********************************************************************
+ Cisco's Lightweight EAP (LEAP)
+ http://www.missl.cs.umd.edu/wireless/ethereal/leap.txt
+ **********************************************************************/
+ case EAP_TYPE_LEAP:
+ {
+ guint8 field,count,namesize;
+
+ /* Version (byte) */
+ if (tree) {
+ field = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(eap_tree, tvb, offset, 1,
+ "Version: %i",field);
+ }
+ size--;
+ offset++;
+
+ /* Unused (byte) */
+ if (tree) {
+ field = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(eap_tree, tvb, offset, 1,
+ "Reserved: %i",field);
+ }
+ size--;
+ offset++;
+
+ /* Count (byte) */
+ count = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_text(eap_tree, tvb, offset, 1,
+ "Count: %i",count);
+ }
+ size--;
+ offset++;
+
+ /* Data (byte*Count) */
+ /* This part is state-dependent. */
+
+ /* See if we've already remembered the state. */
+ packet_state = p_get_proto_data(pinfo->fd, proto_eap);
+ if (packet_state == NULL) {
+ /*
+ * We haven't - compute the state based on the current
+ * state in the conversation.
+ */
+ leap_state = conversation_state->leap_state;
+
+ /* Advance the state machine. */
+ if (leap_state==0) leap_state = 1; else
+ if (leap_state==1) leap_state = 2; else
+ if (leap_state==2) leap_state = 3; else
+ if (leap_state==3) leap_state = 4; else
+ if (leap_state==4) leap_state = -1;
+
+ /*
+ * Remember the state for subsequent accesses to this
+ * frame.
+ */
+ packet_state = g_mem_chunk_alloc(frame_state_chunk);
+ packet_state->info = leap_state;
+ p_add_proto_data(pinfo->fd, proto_eap, packet_state);
+
+ /*
+ * Update the conversation's state.
+ */
+ conversation_state->leap_state = leap_state;
+ }
+
+ /* Get the remembered state. */
+ leap_state = packet_state->info;
+
+ if (tree) {
+
+ if (leap_state==1) {
+ proto_tree_add_text(eap_tree, tvb, offset, count,
+ "Peer Challenge [8] Random Value:\"%s\"",
+ tvb_bytes_to_str(tvb, offset, count));
+ } else if (leap_state==2) {
+ proto_tree_add_text(eap_tree, tvb, offset, count,
+ "Peer Response [24] NtChallengeResponse(%s)",
+ tvb_bytes_to_str(tvb, offset, count));
+ } else if (leap_state==3) {
+ proto_tree_add_text(eap_tree, tvb, offset, count,
+ "AP Challenge [8] Random Value:\"%s\"",
+ tvb_bytes_to_str(tvb, offset, count));
+ } else if (leap_state==4) {
+ proto_tree_add_text(eap_tree, tvb, offset, count,
+ "AP Response [24] ChallengeResponse(%s)",
+ tvb_bytes_to_str(tvb, offset, count));
+ } else {
+ proto_tree_add_text(eap_tree, tvb, offset, count,
+ "Data (%d byte%s): \"%s\"",
+ count, plurality(count, "", "s"),
+ tvb_bytes_to_str(tvb, offset, count));
+ }
+
+ } /* END: if (tree) */
+
+
+ size -= count;
+ offset += count;
+
+ /* Name (Length-(8+Count)) */
+ namesize = eap_len - (8+count);
+ if (tree) {
+ proto_tree_add_text(eap_tree, tvb, offset, namesize,
+ "Name (%d byte%s): %s",
+ namesize, plurality(count, "", "s"),
+ tvb_format_text(tvb, offset, namesize));
+ }
+ size -= namesize;
+ offset += namesize;
+ }
+
+ break; /* EAP_TYPE_LEAP */
+ /*********************************************************************
+ EAP-MSCHAPv2 - draft-kamath-pppext-eap-mschapv2-00.txt
+ **********************************************************************/
+ case EAP_TYPE_MSCHAPV2:
+ if (tree)
+ dissect_eap_mschapv2(eap_tree, tvb, offset, size);
+ break; /* EAP_TYPE_MSCHAPV2 */
+ /*********************************************************************
+ EAP-SIM - draft-haverinen-pppext-eap-sim-12.txt
+ **********************************************************************/
+ case EAP_TYPE_SIM:
+ if (tree)
+ dissect_eap_sim(eap_tree, tvb, offset, size);
+ break; /* EAP_TYPE_SIM */
+ /*********************************************************************
+ **********************************************************************/
+ default:
+ if (tree) {
+ proto_tree_add_text(eap_tree, tvb, offset, size,
+ "Type-Data (%d byte%s) Value: %s",
+ size, plurality(size, "", "s"),
+ tvb_bytes_to_str(tvb, offset, size));
+ }
+ break;
+ /*********************************************************************
+ **********************************************************************/
+ } /* switch (eap_type) */
+
+ }
+
+ } /* switch (eap_code) */
+
+ return tvb_length(tvb);
+}
+
+static int
+dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_eap_data(tvb, pinfo, tree, FALSE);
+}
+
+static int
+dissect_eap_fragment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_eap_data(tvb, pinfo, tree, TRUE);
+}
+
+void
+proto_register_eap(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_eap_code, {
+ "Code", "eap.code", FT_UINT8, BASE_DEC,
+ VALS(eap_code_vals), 0x0, "", HFILL }},
+ { &hf_eap_identifier, {
+ "Id", "eap.id", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_eap_len, {
+ "Length", "eap.len", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_eap_type, {
+ "Type", "eap.type", FT_UINT8, BASE_DEC,
+ VALS(eap_type_vals), 0x0, "", HFILL }},
+ { &hf_eap_type_nak, {
+ "Desired Auth Type", "eap.desired_type", FT_UINT8, BASE_DEC,
+ VALS(eap_type_vals), 0x0, "", HFILL }},
+ { &hf_eaptls_fragment,
+ { "EAP-TLS Fragment", "eaptls.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "EAP-TLS Fragment", HFILL }},
+ { &hf_eaptls_fragments,
+ { "EAP-TLS Fragments", "eaptls.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "EAP-TLS Fragments", HFILL }},
+ { &hf_eaptls_fragment_overlap,
+ { "Fragment overlap", "eaptls.fragment.overlap",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }},
+ { &hf_eaptls_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "eaptls.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+ { &hf_eaptls_fragment_multiple_tails,
+ { "Multiple tail fragments found", "eaptls.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+ { &hf_eaptls_fragment_too_long_fragment,
+ { "Fragment too long", "eaptls.fragment.toolongfragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+ { &hf_eaptls_fragment_error,
+ { "Defragmentation error", "eaptls.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_eap,
+ &ett_eaptls_fragment,
+ &ett_eaptls_fragments,
+ &ett_eap_sim_attr,
+ };
+
+ proto_eap = proto_register_protocol("Extensible Authentication Protocol",
+ "EAP", "eap");
+ proto_register_field_array(proto_eap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&eap_init_protocol);
+
+ new_register_dissector("eap", dissect_eap, proto_eap);
+ new_register_dissector("eap_fragment", dissect_eap_fragment, proto_eap);
+ register_init_routine(eaptls_defragment_init);
+}
+
+void
+proto_reg_handoff_eap(void)
+{
+ dissector_handle_t eap_handle;
+
+ /*
+ * Get a handle for the SSL/TLS dissector.
+ */
+ ssl_handle = find_dissector("ssl");
+
+ eap_handle = find_dissector("eap");
+ dissector_add("ppp.protocol", PPP_EAP, eap_handle);
+}
diff --git a/epan/dissectors/packet-eapol.c b/epan/dissectors/packet-eapol.c
new file mode 100644
index 0000000000..80a78c6c6c
--- /dev/null
+++ b/epan/dissectors/packet-eapol.c
@@ -0,0 +1,431 @@
+/* packet-eapol.c
+ * Routines for EAPOL 802.1X authentication header disassembly
+ * (From IEEE Draft P802.1X/D11; is there a later draft, or a
+ * final standard? If so, check it.)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ieee80211.h"
+#include "etypes.h"
+
+static int proto_eapol = -1;
+static int hf_eapol_version = -1;
+static int hf_eapol_type = -1;
+static int hf_eapol_len = -1;
+static int hf_eapol_keydes_type = -1;
+static int hf_eapol_keydes_keylen = -1;
+static int hf_eapol_keydes_replay_counter = -1;
+static int hf_eapol_keydes_key_iv = -1;
+static int hf_eapol_keydes_key_index_keytype = -1;
+static int hf_eapol_keydes_key_index_indexnum = -1;
+static int hf_eapol_keydes_key_signature = -1;
+static int hf_eapol_keydes_key = -1;
+
+static int hf_eapol_wpa_keydes_keyinfo = -1;
+static int hf_eapol_wpa_keydes_keyinfo_keydes_ver = -1;
+static int hf_eapol_wpa_keydes_keyinfo_key_type = -1;
+static int hf_eapol_wpa_keydes_keyinfo_key_index = -1;
+static int hf_eapol_wpa_keydes_keyinfo_install = -1;
+static int hf_eapol_wpa_keydes_keyinfo_key_ack = -1;
+static int hf_eapol_wpa_keydes_keyinfo_key_mic = -1;
+static int hf_eapol_wpa_keydes_keyinfo_secure = -1;
+static int hf_eapol_wpa_keydes_keyinfo_error = -1;
+static int hf_eapol_wpa_keydes_keyinfo_request = -1;
+static int hf_eapol_wpa_keydes_keyinfo_encr_key_data = -1;
+static int hf_eapol_wpa_keydes_nonce = -1;
+static int hf_eapol_wpa_keydes_rsc = -1;
+static int hf_eapol_wpa_keydes_id = -1;
+static int hf_eapol_wpa_keydes_mic = -1;
+static int hf_eapol_wpa_keydes_datalen = -1;
+static int hf_eapol_wpa_keydes_data = -1;
+
+static gint ett_eapol = -1;
+static gint ett_eapol_keydes_data = -1;
+static gint ett_eapol_key_index = -1;
+static gint ett_keyinfo = -1;
+
+static dissector_handle_t eap_handle;
+static dissector_handle_t data_handle;
+
+#define EAPOL_HDR_LEN 4
+
+#define EAP_PACKET 0
+#define EAPOL_START 1
+#define EAPOL_LOGOFF 2
+#define EAPOL_KEY 3
+#define EAPOL_ENCAP_ASF_ALERT 4
+
+#define EAPOL_RSN_KEY 2 /* TBD, may change in final IEEE 802.1X-REV
+ */
+#define EAPOL_WPA_KEY 254
+
+static const value_string eapol_type_vals[] = {
+ { EAP_PACKET, "EAP Packet" },
+ { EAPOL_START, "Start" },
+ { EAPOL_LOGOFF, "Logoff" },
+ { EAPOL_KEY, "Key" },
+ { EAPOL_ENCAP_ASF_ALERT, "Encapsulated ASF Alert" },
+ { 0, NULL }
+};
+
+static const value_string eapol_keydes_type_vals[] = {
+ { 1, "RC4 Descriptor" },
+ { EAPOL_RSN_KEY, "EAPOL RSN key" },
+ { EAPOL_WPA_KEY, "EAPOL WPA key" },
+ { 0, NULL }
+};
+
+#define KEY_INFO_KEYDES_VER_MASK 0x0007
+#define KEY_INFO_KEY_TYPE_MASK 0x0008
+#define KEY_INFO_KEY_INDEX_MASK 0x0030
+#define KEY_INFO_INSTALL_MASK 0x0040
+#define KEY_INFO_KEY_ACK_MASK 0x0080
+#define KEY_INFO_KEY_MIC_MASK 0x0100
+#define KEY_INFO_SECURE_MASK 0x0200
+#define KEY_INFO_ERROR_MASK 0x0400
+#define KEY_INFO_REQUEST_MASK 0x0800
+#define KEY_INFO_ENCR_KEY_DATA_MASK 0x1000
+
+static const true_false_string keytype_tfs =
+ { "Unicast", "Broadcast" };
+static const true_false_string tfs_keyinfo_key_type =
+ { "Pairwise key", "Group key" };
+#define KEYDES_VER_TYPE1 0x01
+#define KEYDES_VER_TYPE2 0x02
+static const value_string keydes_ver[] = {
+ { KEYDES_VER_TYPE1, "HMAC-MD5 for MIC and RC4 for encryption" },
+ { KEYDES_VER_TYPE2, "AES-CBC-MAC for MIC and HMAC-SHA1 for encryption" },
+ { 0, NULL }
+};
+
+static void
+dissect_eapol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint8 eapol_type;
+ guint8 keydesc_type;
+ guint16 eapol_len;
+ guint len;
+ guint16 eapol_key_len, eapol_data_len;
+ guint8 key_index;
+ guint16 keyinfo;
+ proto_tree *ti = NULL;
+ proto_tree *eapol_tree = NULL;
+ proto_tree *keyinfo_item = NULL;
+ proto_tree *keyinfo_tree = NULL;
+ proto_tree *key_index_tree, *keydes_tree;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAPOL");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_eapol, tvb, 0, -1, FALSE);
+ eapol_tree = proto_item_add_subtree(ti, ett_eapol);
+
+ proto_tree_add_item(eapol_tree, hf_eapol_version, tvb, offset, 1, FALSE);
+ }
+ offset++;
+
+ eapol_type = tvb_get_guint8(tvb, offset);
+ if (tree)
+ proto_tree_add_uint(eapol_tree, hf_eapol_type, tvb, offset, 1, eapol_type);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(eapol_type, eapol_type_vals, "Unknown type (0x%02X)"));
+ offset++;
+
+ eapol_len = tvb_get_ntohs(tvb, offset);
+ len = EAPOL_HDR_LEN + eapol_len;
+ set_actual_length(tvb, len);
+ if (tree) {
+ proto_item_set_len(ti, len);
+ proto_tree_add_uint(eapol_tree, hf_eapol_len, tvb, offset, 2, eapol_len);
+ }
+ offset += 2;
+
+ switch (eapol_type) {
+
+ case EAP_PACKET:
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(eap_handle, next_tvb, pinfo, eapol_tree);
+ break;
+
+ case EAPOL_KEY:
+ if (tree) {
+ keydesc_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(eapol_tree, hf_eapol_keydes_type, tvb, offset, 1, FALSE);
+ offset += 1;
+ if (keydesc_type == EAPOL_WPA_KEY || keydesc_type == EAPOL_RSN_KEY) {
+ keyinfo = tvb_get_ntohs(tvb, offset);
+ keyinfo_item =
+ proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_keyinfo, tvb,
+ offset, 2, keyinfo);
+
+ keyinfo_tree = proto_item_add_subtree(keyinfo_item, ett_keyinfo);
+ proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_keydes_ver, tvb, offset, 2, keyinfo);
+ proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_type, tvb, offset, 2, keyinfo);
+ proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_index, tvb, offset, 2, keyinfo);
+ proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_install, tvb, offset, 2, keyinfo);
+ proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_ack, tvb, offset, 2, keyinfo);
+ proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_mic, tvb, offset, 2, keyinfo);
+ proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_secure, tvb, offset, 2, keyinfo);
+ proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_error, tvb, offset, 2, keyinfo);
+ proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_request, tvb, offset, 2, keyinfo);
+ proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_encr_key_data, tvb, offset, 2, keyinfo);
+
+ offset += 2;
+ proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset,
+ 2, tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb,
+ offset, 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_nonce, tvb, offset,
+ 32, FALSE);
+ offset += 32;
+ proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb,
+ offset, 16, FALSE);
+ offset += 16;
+ proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_rsc, tvb, offset,
+ 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_id, tvb, offset, 8,
+ FALSE);
+ offset += 8;
+ proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_mic, tvb, offset,
+ 16, FALSE);
+ offset += 16;
+ eapol_data_len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_datalen, tvb,
+ offset, 2, eapol_data_len);
+ offset += 2;
+ if (eapol_data_len != 0) {
+ ti = proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_data,
+ tvb, offset, eapol_data_len, FALSE);
+ if ((keyinfo & KEY_INFO_ENCR_KEY_DATA_MASK) ||
+ !(keyinfo & KEY_INFO_KEY_TYPE_MASK)) {
+ /* RSN: EAPOL-Key Key Data is encrypted.
+ * WPA: Group Keys use encrypted Key Data.
+ * Cannot parse this without knowing the key. */
+ } else {
+ keydes_tree = proto_item_add_subtree(ti, ett_eapol_keydes_data);
+ ieee_80211_add_tagged_parameters(tvb, offset, keydes_tree,
+ eapol_data_len);
+ }
+ }
+ }
+ else {
+ eapol_key_len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset, 2, eapol_key_len);
+ offset += 2;
+ proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb,
+ offset, 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb,
+ offset, 16, FALSE);
+ offset += 16;
+ key_index = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(eapol_tree, tvb, offset, 1,
+ "Key Index: %s, index %u",
+ (key_index & 0x80) ? "unicast" : "broadcast",
+ key_index & 0x7F);
+ key_index_tree = proto_item_add_subtree(ti, ett_eapol_key_index);
+ proto_tree_add_boolean(eapol_tree, hf_eapol_keydes_key_index_keytype,
+ tvb, offset, 1, key_index);
+ proto_tree_add_uint(eapol_tree, hf_eapol_keydes_key_index_indexnum,
+ tvb, offset, 1, key_index);
+ offset += 1;
+ proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_signature, tvb,
+ offset, 16, FALSE);
+ offset += 16;
+ if (eapol_key_len != 0)
+ proto_tree_add_item(eapol_tree, hf_eapol_keydes_key, tvb, offset,
+ eapol_key_len, FALSE);
+ }
+ }
+ break;
+
+ case EAPOL_ENCAP_ASF_ALERT: /* XXX - is this an SNMP trap? */
+ default:
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(data_handle, next_tvb, pinfo, eapol_tree);
+ break;
+ }
+}
+
+void
+proto_register_eapol(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_eapol_version, {
+ "Version", "eapol.version", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_eapol_type, {
+ "Type", "eapol.type", FT_UINT8, BASE_DEC,
+ VALS(eapol_type_vals), 0x0, "", HFILL }},
+ { &hf_eapol_len, {
+ "Length", "eapol.len", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length", HFILL }},
+ { &hf_eapol_keydes_type, {
+ "Descriptor Type", "eapol.keydes.type", FT_UINT8, BASE_DEC,
+ VALS(eapol_keydes_type_vals), 0x0, "Key Descriptor Type", HFILL }},
+ { &hf_eapol_keydes_keylen, {
+ "Key Length", "eapol.keydes.keylen", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Key Length", HFILL }},
+ { &hf_eapol_keydes_replay_counter, {
+ "Replay Counter", "eapol.keydes.replay_counter", FT_UINT64, BASE_DEC,
+ NULL, 0x0, "Replay Counter", HFILL }},
+ { &hf_eapol_keydes_key_iv, {
+ "Key IV", "eapol.keydes.key_iv", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "Key Initialization Vector", HFILL }},
+ { &hf_eapol_keydes_key_index_keytype, {
+ "Key Type", "eapol.keydes.index.keytype", FT_BOOLEAN, 8,
+ TFS(&keytype_tfs), 0x80, "Key Type (unicast/broadcast)", HFILL }},
+ { &hf_eapol_keydes_key_index_indexnum, {
+ "Index Number", "eapol.keydes.index.indexnum", FT_UINT8, BASE_DEC,
+ NULL, 0x7F, "Key Index number", HFILL }},
+ { &hf_eapol_keydes_key_signature, {
+ "Key Signature", "eapol.keydes.key_signature", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "Key Signature", HFILL }},
+ { &hf_eapol_keydes_key, {
+ "Key", "eapol.keydes.key", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "Key", HFILL }},
+
+ { &hf_eapol_wpa_keydes_keyinfo, {
+ "Key Information", "eapol.keydes.key_info", FT_UINT16,
+ BASE_HEX, NULL, 0x0, "WPA key info", HFILL }},
+
+ { &hf_eapol_wpa_keydes_keyinfo_keydes_ver, {
+ "Key Descriptor Version",
+ "eapol.keydes.key_info.keydes_ver",
+ FT_UINT16, BASE_DEC, VALS(&keydes_ver),
+ KEY_INFO_KEYDES_VER_MASK,
+ "Key Descriptor Version Type", HFILL }},
+ { &hf_eapol_wpa_keydes_keyinfo_key_type, {
+ "Key Type",
+ "eapol.keydes.key_info.key_type",
+ FT_BOOLEAN, 16, TFS(&tfs_keyinfo_key_type),
+ KEY_INFO_KEY_TYPE_MASK,
+ "Key Type (Pairwise or Group)", HFILL }},
+ { &hf_eapol_wpa_keydes_keyinfo_key_index, {
+ "Key Index",
+ "eapol.keydes.key_info.key_index",
+ FT_UINT16, BASE_DEC, NULL,
+ KEY_INFO_KEY_INDEX_MASK,
+ "Key Index (0-3) (RSN: Reserved)", HFILL }},
+ { &hf_eapol_wpa_keydes_keyinfo_install, {
+ "Install flag",
+ "eapol.keydes.key_info.install",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth),
+ KEY_INFO_INSTALL_MASK,
+ "Install flag", HFILL }},
+ { &hf_eapol_wpa_keydes_keyinfo_key_ack, {
+ "Key Ack flag",
+ "eapol.keydes.key_info.key_ack",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth),
+ KEY_INFO_KEY_ACK_MASK,
+ "Key Ack flag", HFILL }},
+ { &hf_eapol_wpa_keydes_keyinfo_key_mic, {
+ "Key MIC flag",
+ "eapol.keydes.key_info.key_mic",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth),
+ KEY_INFO_KEY_MIC_MASK,
+ "Key MIC flag", HFILL }},
+ { &hf_eapol_wpa_keydes_keyinfo_secure, {
+ "Secure flag",
+ "eapol.keydes.key_info.secure",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth),
+ KEY_INFO_SECURE_MASK,
+ "Secure flag", HFILL }},
+ { &hf_eapol_wpa_keydes_keyinfo_error, {
+ "Error flag",
+ "eapol.keydes.key_info.error",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth),
+ KEY_INFO_ERROR_MASK,
+ "Error flag", HFILL }},
+ { &hf_eapol_wpa_keydes_keyinfo_request, {
+ "Request flag",
+ "eapol.keydes.key_info.request",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth),
+ KEY_INFO_REQUEST_MASK,
+ "Request flag", HFILL }},
+ { &hf_eapol_wpa_keydes_keyinfo_encr_key_data, {
+ "Encrypted Key Data flag",
+ "eapol.keydes.key_info.encr_key_data",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth),
+ KEY_INFO_ENCR_KEY_DATA_MASK,
+ "Encrypted Key Data flag", HFILL }},
+ { &hf_eapol_wpa_keydes_nonce, {
+ "Nonce", "eapol.keydes.nonce", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "WPA Key Nonce", HFILL }},
+ { &hf_eapol_wpa_keydes_rsc, {
+ "WPA Key RSC", "eapol.keydes.rsc", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "WPA Key Receive Sequence Counter", HFILL }},
+ { &hf_eapol_wpa_keydes_id, {
+ "WPA Key ID", "eapol.keydes.id", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "WPA Key ID(RSN Reserved)", HFILL }},
+ { &hf_eapol_wpa_keydes_mic, {
+ "WPA Key MIC", "eapol.keydes.mic", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "WPA Key Message Integrity Check", HFILL }},
+ { &hf_eapol_wpa_keydes_datalen, {
+ "WPA Key Length", "eapol.keydes.datalen", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "WPA Key Data Length", HFILL }},
+ { &hf_eapol_wpa_keydes_data, {
+ "WPA Key", "eapol.keydes.data", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "WPA Key Data", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_eapol,
+ &ett_eapol_keydes_data,
+ &ett_keyinfo,
+ &ett_eapol_key_index
+ };
+
+ proto_eapol = proto_register_protocol("802.1x Authentication", "EAPOL", "eapol");
+ proto_register_field_array(proto_eapol, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_eapol(void)
+{
+ dissector_handle_t eapol_handle;
+
+ /*
+ * Get handles for the EAP and raw data dissectors.
+ */
+ eap_handle = find_dissector("eap");
+ data_handle = find_dissector("data");
+
+ eapol_handle = create_dissector_handle(dissect_eapol, proto_eapol);
+ dissector_add("ethertype", ETHERTYPE_EAPOL, eapol_handle);
+ dissector_add("ethertype", ETHERTYPE_RSN_PREAUTH, eapol_handle);
+}
diff --git a/epan/dissectors/packet-echo.c b/epan/dissectors/packet-echo.c
new file mode 100644
index 0000000000..b90883041b
--- /dev/null
+++ b/epan/dissectors/packet-echo.c
@@ -0,0 +1,128 @@
+/* packet-echo.c
+ * Routines for ECHO packet disassembly (RFC862)
+ *
+ * Only useful to mark the packets as ECHO in the summary and in the
+ * protocol hierarchy statistics (since not so many fields to decode ;-)
+ *
+ * Laurent Deniel <laurent.deniel@free.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+#define ECHO_PORT 7
+
+static int proto_echo = -1;
+
+static int hf_echo_data = -1;
+static int hf_echo_request = -1;
+static int hf_echo_response = -1;
+
+static gint ett_echo = -1;
+
+static void dissect_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ proto_tree *echo_tree = NULL;
+ proto_item *ti;
+ int offset = 0;
+ gboolean request = FALSE;
+ const char *data = tvb_get_ptr(tvb, offset, -1);
+
+ if (pinfo->destport == ECHO_PORT) {
+ request = TRUE;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_add_str(pinfo->cinfo, COL_PROTOCOL, "ECHO");
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ (request) ? "Request" : "Response");
+ }
+
+ if (tree) {
+
+ ti = proto_tree_add_item(tree, proto_echo, tvb, offset, -1, FALSE);
+ echo_tree = proto_item_add_subtree(ti, ett_echo);
+
+ if (request) {
+ proto_tree_add_boolean_hidden(echo_tree, hf_echo_request, tvb, 0, 0, 1);
+
+ } else {
+ proto_tree_add_boolean_hidden(echo_tree, hf_echo_response, tvb, 0, 0, 1);
+ }
+
+ proto_tree_add_bytes(echo_tree, hf_echo_data, tvb, offset, -1, data);
+
+ }
+
+} /* dissect_echo */
+
+void proto_register_echo(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_echo_data,
+ { "Echo data", "echo.data",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Echo data", HFILL }},
+ { &hf_echo_request,
+ { "Echo request", "echo.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Echo data", HFILL }},
+ { &hf_echo_response,
+ { "Echo response","echo.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Echo data", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_echo
+ };
+
+ proto_echo = proto_register_protocol("Echo", "ECHO", "echo");
+ proto_register_field_array(proto_echo, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void proto_reg_handoff_echo(void)
+{
+
+ dissector_handle_t echo_handle = NULL;
+
+ echo_handle = create_dissector_handle(dissect_echo, proto_echo);
+
+ dissector_add("udp.port", ECHO_PORT, echo_handle);
+ dissector_add("tcp.port", ECHO_PORT, echo_handle);
+
+}
+
diff --git a/epan/dissectors/packet-edonkey.c b/epan/dissectors/packet-edonkey.c
new file mode 100644
index 0000000000..038c224162
--- /dev/null
+++ b/epan/dissectors/packet-edonkey.c
@@ -0,0 +1,1435 @@
+/* packet-edonkey.c
+ * Routines for edonkey dissection
+ * Copyright 2003, Xuan Zhang <xz@aemail4u.com>
+ * eDonkey dissector based on protocol descriptions from mldonkey:
+ * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/edonkey-protocol.txt
+ * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/overnet-protocol.txt
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "packet-edonkey.h"
+
+static int proto_edonkey = -1;
+
+static int hf_edonkey_message = -1;
+static int hf_edonkey_protocol = -1;
+static int hf_edonkey_message_length = -1;
+static int hf_edonkey_message_type = -1;
+static int hf_edonkey_client_hash = -1;
+static int hf_edonkey_server_hash = -1;
+static int hf_edonkey_file_hash = -1;
+static int hf_edonkey_client_id = -1;
+static int hf_edonkey_metatag_namesize = -1;
+static int hf_edonkey_metatag_type = -1;
+static int hf_edonkey_metatag = -1;
+static int hf_edonkey_metatag_name = -1;
+static int hf_edonkey_metatag_id = -1;
+static int hf_edonkey_search = -1;
+static int hf_edonkey_ip = -1;
+static int hf_edonkey_port = -1;
+static int hf_edonkey_hash = -1;
+static int hf_edonkey_directory = -1;
+static int hf_edonkey_string = -1;
+static int hf_edonkey_string_length = -1;
+static int hf_edonkey_fileinfo = -1;
+static int hf_edonkey_clientinfo = -1;
+static int hf_edonkey_serverinfo = -1;
+static int hf_overnet_peer = -1;
+
+static gint ett_edonkey = -1;
+static gint ett_edonkey_message = -1;
+static gint ett_edonkey_metatag = -1;
+static gint ett_edonkey_search = -1;
+static gint ett_edonkey_fileinfo = -1;
+static gint ett_edonkey_serverinfo = -1;
+static gint ett_edonkey_clientinfo = -1;
+static gint ett_overnet_peer = -1;
+
+static const value_string edonkey_protocols[] = {
+ { EDONKEY_PROTO_EDONKEY, "eDonkey" },
+ { EDONKEY_PROTO_EMULE_EXT, "eMule Extensions" },
+ { EDONKEY_PROTO_EMULE_COMP, "eMule Compressed" },
+ { 0, NULL }
+};
+
+static const value_string edonkey_tcp_msgs[] = {
+ { EDONKEY_MSG_HELLO, "Hello" },
+ { EDONKEY_MSG_BAD_PROTO, "Bad Proto" },
+ { EDONKEY_MSG_GET_SERVER_LIST, "Get Server List" },
+ { EDONKEY_MSG_OFFER_FILES, "Offer Files" },
+ { EDONKEY_MSG_SEARCH_FILES, "Search Files" },
+ { EDONKEY_MSG_DISCONNECT, "Disconnect" },
+ { EDONKEY_MSG_GET_SOURCES, "Get Sources" },
+ { EDONKEY_MSG_SEARCH_USER, "Search User" },
+ { EDONKEY_MSG_CLIENT_CB_REQ, "Client Callback Request" },
+ { EDONKEY_MSG_MORE_RESULTS, "More Results" },
+ { EDONKEY_MSG_SERVER_LIST, "Server List" },
+ { EDONKEY_MSG_SEARCH_FILE_RESULTS, "Search File Results" },
+ { EDONKEY_MSG_SERVER_STATUS, "Server Status" },
+ { EDONKEY_MSG_SERVER_CB_REQ, "Server Callback Request" },
+ { EDONKEY_MSG_CALLBACK_FAIL, "Callback Fail" },
+ { EDONKEY_MSG_SERVER_MESSAGE, "Server Message" },
+ { EDONKEY_MSG_ID_CHANGE, "ID Change" },
+ { EDONKEY_MSG_SERVER_INFO_DATA, "Server Info Data" },
+ { EDONKEY_MSG_FOUND_SOURCES, "Found Sources" },
+ { EDONKEY_MSG_SEARCH_USER_RESULTS, "Search User Results" },
+ { EDONKEY_MSG_SENDING_PART, "Sending Part" },
+ { EDONKEY_MSG_REQUEST_PARTS, "Request Parts" },
+ { EDONKEY_MSG_NO_SUCH_FILE, "No Such File" },
+ { EDONKEY_MSG_END_OF_DOWNLOAD, "End of Download" },
+ { EDONKEY_MSG_VIEW_FILES, "View Files" },
+ { EDONKEY_MSG_VIEW_FILES_ANSWER, "View Files Answer" },
+ { EDONKEY_MSG_HELLO_ANSWER, "Hello Answer" },
+ { EDONKEY_MSG_NEW_CLIENT_ID, "New Client ID" },
+ { EDONKEY_MSG_CLIENT_MESSAGE, "Client Message" },
+ { EDONKEY_MSG_FILE_STATUS_REQUEST, "File Status Request" },
+ { EDONKEY_MSG_FILE_STATUS, "File Status" },
+ { EDONKEY_MSG_HASHSET_REQUEST, "Hashset Request" },
+ { EDONKEY_MSG_HASHSET_ANSWER, "Hashset Answer" },
+ { EDONKEY_MSG_SLOT_REQUEST, "Slot Request" },
+ { EDONKEY_MSG_SLOT_GIVEN, "Slot Given" },
+ { EDONKEY_MSG_SLOT_RELEASE, "Slot Release" },
+ { EDONKEY_MSG_SLOT_TAKEN, "Slot Taken" },
+ { EDONKEY_MSG_FILE_REQUEST, "File Request" },
+ { EDONKEY_MSG_FILE_REQUEST_ANSWER, "File Request Answer" },
+ { EDONKEY_MSG_GET_SHARED_DIRS, "Get Shared Directories" },
+ { EDONKEY_MSG_GET_SHARED_FILES, "Get Shared Files" },
+ { EDONKEY_MSG_SHARED_DIRS, "Shared Directores" },
+ { EDONKEY_MSG_SHARED_FILES, "Shared Files" },
+ { EDONKEY_MSG_SHARED_DENIED, "Shared Denied" },
+ { 0, NULL }
+};
+
+static const value_string emule_tcp_msgs[] = {
+ { EMULE_MSG_HELLO, "Hello" },
+ { EMULE_MSG_HELLO_ANSWER, "Hello Answer" },
+ { EMULE_MSG_DATA_COMPRESSED, "Data Compressed" },
+ { EMULE_MSG_QUEUE_RANKING, "Queue Ranking" },
+ { EMULE_MSG_SOURCES_REQUEST, "Sources Request" },
+ { EMULE_MSG_SOURCES_ANSWER, "Sources Answer" },
+ { 0, NULL }
+};
+
+static const value_string edonkey_udp_msgs[] = {
+ { EDONKEY_MSG_UDP_SERVER_STATUS_REQUEST, "Server Status Request" },
+ { EDONKEY_MSG_UDP_SERVER_STATUS, "Server Status" },
+ { EDONKEY_MSG_UDP_SEARCH_FILE, "Search File" },
+ { EDONKEY_MSG_UDP_SEARCH_FILE_RESULTS, "Search File Results" },
+ { EDONKEY_MSG_UDP_GET_SOURCES, "Get Sources" },
+ { EDONKEY_MSG_UDP_FOUND_SOURCES, "Found Sources" },
+ { EDONKEY_MSG_UDP_CALLBACK_REQUEST, "Callback Request" },
+ { EDONKEY_MSG_UDP_CALLBACK_FAIL, "Callback Fail" },
+ { EDONKEY_MSG_UDP_SERVER_LIST, "Server List" },
+ { EDONKEY_MSG_UDP_GET_SERVER_INFO, "Get Server Info" },
+ { EDONKEY_MSG_UDP_SERVER_INFO, "Server Info" },
+ { EDONKEY_MSG_UDP_GET_SERVER_LIST, "Get Server List" },
+
+ /* eMule Extensions */
+ { EMULE_MSG_UDP_REASKFILEPING, "Reask File Ping" },
+ { EMULE_MSG_UDP_REASKACK, "Reask ACK" },
+ { EMULE_MSG_UDP_FILE_NOT_FOUND, "File not found" },
+ { EMULE_MSG_UDP_QUEUE_FULL, "Queue Full" },
+
+ /* Overnet Extensions */
+ { OVERNET_MSG_UDP_CONNECT, "Connect" },
+ { OVERNET_MSG_UDP_CONNECT_REPLY, "Connect Reply" },
+ { OVERNET_MSG_UDP_PUBLICIZE, "Publicize" },
+ { OVERNET_MSG_UDP_PUBLICIZE_ACK, "Publicize ACK" },
+ { OVERNET_MSG_UDP_SEARCH, "Search" },
+ { OVERNET_MSG_UDP_SEARCH_NEXT, "Search Next" },
+ { OVERNET_MSG_UDP_SEARCH_INFO, "Search Info" },
+ { OVERNET_MSG_UDP_SEARCH_RESULT, "Search Result" },
+ { OVERNET_MSG_UDP_SEARCH_END, "Search End" },
+ { OVERNET_MSG_UDP_PUBLISH, "Publish" },
+ { OVERNET_MSG_UDP_PUBLISH_ACK, "Publish ACK" },
+ { OVERNET_MSG_UDP_IDENTIFY_REPLY, "Identify Reply" },
+ { OVERNET_MSG_UDP_IDENTIFY_ACK, "Identify ACK" },
+ { OVERNET_MSG_UDP_FIREWALL_CONNECTION, "Firewall Connection" },
+ { OVERNET_MSG_UDP_FIREWALL_CONNECTION_ACK, "Firewall Connection ACK" },
+ { OVERNET_MSG_UDP_FIREWALL_CONNECTION_NACK, "Firewall Connection NACK" },
+ { OVERNET_MSG_UDP_IP_QUERY, "IP Query" },
+ { OVERNET_MSG_UDP_IP_QUERY_ANSWER, "IP Query Answer" },
+ { OVERNET_MSG_UDP_IP_QUERY_END, "IP Query End" },
+ { OVERNET_MSG_UDP_IDENTIFY, "Identify" },
+ { 0, NULL }
+};
+
+static const value_string edonkey_special_tags[] = {
+ { EDONKEY_STAG_NAME, "Name" },
+ { EDONKEY_STAG_SIZE, "Size" },
+ { EDONKEY_STAG_TYPE, "Type" },
+ { EDONKEY_STAG_FORMAT, "Format" },
+ { EDONKEY_STAG_COLLECTION, "Collection" },
+ { EDONKEY_STAG_PART_PATH, "Part Path" },
+ { EDONKEY_STAG_PART_HASH, "Part Hash" },
+ { EDONKEY_STAG_COPIED, "Copied" },
+ { EDONKEY_STAG_GAP_START, "Gap Start" },
+ { EDONKEY_STAG_GAP_END, "Gap End" },
+ { EDONKEY_STAG_DESCRIPTION, "Description" },
+ { EDONKEY_STAG_PING, "Ping" },
+ { EDONKEY_STAG_FAIL, "Fail" },
+ { EDONKEY_STAG_PREFERENCE, "Preference" },
+ { EDONKEY_STAG_PORT, "Port" },
+ { EDONKEY_STAG_IP, "IP" },
+ { EDONKEY_STAG_VERSION, "Version" },
+ { EDONKEY_STAG_TEMPFILE, "Temporary File" },
+ { EDONKEY_STAG_PRIORITY, "Priority" },
+ { EDONKEY_STAG_STATUS, "Status" },
+ { EDONKEY_STAG_AVAILABILITY, "Availability" },
+ { EDONKEY_STAG_QTIME, "Queue Time" },
+ { EDONKEY_STAG_PARTS, "Parts" },
+ { EMULE_STAG_COMPRESSION, "Compression" },
+ { EMULE_STAG_UDP_CLIENT_PORT, "UDP Client Port" },
+ { EMULE_STAG_UDP_VERSION, "UDP Version" },
+ { EMULE_STAG_SOURCE_EXCHANGE, "Source Exchange" },
+ { EMULE_STAG_COMMENTS, "Comments" },
+ { EMULE_STAG_EXTENDED_REQUEST, "Extended Request" },
+ { EMULE_STAG_COMPATIBLE_CLIENT, "Compatible Client" },
+ { 0, NULL }
+};
+
+static const value_string edonkey_search_ops[] = {
+ { EDONKEY_SEARCH_AND, "AND" },
+ { EDONKEY_SEARCH_OR, "OR" },
+ { EDONKEY_SEARCH_ANDNOT, "AND NOT" },
+ { 0, NULL }
+};
+
+static const value_string edonkey_search_conds[] = {
+ { EDONKEY_SEARCH_MIN, "MIN" },
+ { EDONKEY_SEARCH_MAX, "MAX" },
+ { 0, NULL }
+};
+
+/* Dissects a generic eDonkey list */
+static int dissect_edonkey_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree,
+ int listnum_length, char* listdesc,
+ int (*item_dissector)(tvbuff_t *, packet_info *, int, proto_tree *))
+{
+ /* <List> ::= <List Size> <Item>* */
+ guint32 listnum, i;
+ switch (listnum_length) {
+ case 1:
+ listnum = tvb_get_guint8(tvb, offset);
+ break;
+
+ case 2:
+ listnum = tvb_get_letohs(tvb, offset);
+ break;
+
+ case 4:
+ listnum = tvb_get_letohl(tvb, offset);
+ break;
+
+ default:
+ /* Not Supported */
+ return offset;
+ }
+
+ proto_tree_add_text(tree, tvb, offset, listnum_length, "%s List Size: %u", listdesc, listnum);
+ offset+=listnum_length;
+ for (i=0; i<listnum; i++)
+ {
+ offset = (*item_dissector)(tvb, pinfo, offset, tree);
+ }
+ return offset;
+}
+
+gint lookup_str_index(gchar* str, gint length, const value_string *vs)
+{
+ gint i = 0;
+
+ if (str == NULL) return -1;
+
+ while (vs[i].strptr) {
+ if (strncasecmp(str, vs[i].strptr, length) == 0)
+ return i;
+ i++;
+ }
+
+ return -1;
+}
+
+static guint8 edonkey_metatag_name_get_type(tvbuff_t *tvb, gint start, gint length, guint8 special_tagtype)
+{
+ guchar *tag_name;
+ tag_name = match_strval(special_tagtype, edonkey_special_tags);
+ if (tag_name == NULL) {
+ gint index;
+ tag_name = (guchar*) tvb_get_ptr(tvb, start, length);
+ index = lookup_str_index(tag_name, length, edonkey_special_tags);
+ if (index < 0)
+ return EDONKEY_STAG_UNKNOWN;
+ else return edonkey_special_tags[index].value;
+ }
+ else return special_tagtype;
+
+ return EDONKEY_STAG_UNKNOWN;
+}
+
+static proto_item* edonkey_tree_add_metatag_name(proto_tree *tree, tvbuff_t *tvb,
+ gint start, gint length, guint8 special_tagtype)
+{
+ gchar *tag_name;
+ tag_name = match_strval(special_tagtype, edonkey_special_tags);
+ if (tag_name == NULL) {
+ return proto_tree_add_item(tree, hf_edonkey_metatag_name, tvb, start, length, FALSE);
+ }
+ else {
+ return proto_tree_add_uint_format(tree, hf_edonkey_metatag_id, tvb, start, length,
+ special_tagtype, "Meta Tag Name: %s (0x%02x)",
+ tag_name, special_tagtype);
+ }
+}
+
+/* Dissects the eDonkey meta tag */
+static int dissect_edonkey_metatag(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Meta Tag> ::= <Tag Type (guint8)> <Tag Name> <Tag> */
+ /* <Tag Name> ::= <Tag Name Size (guint16)> <Special Tag> || <String> */
+ proto_item *ti;
+ proto_tree *metatag_tree;
+ guint8 tag_type, special_tagtype;
+ guint16 tag_name_size, string_length;
+ guint32 tag_length, tag_value_guint32;
+ int tag_offset;
+
+ tag_type = tvb_get_guint8(tvb, offset);
+ tag_name_size = tvb_get_letohs(tvb, offset+1);
+ special_tagtype = tvb_get_guint8(tvb, offset+3);
+
+ tag_length = 3 + tag_name_size;
+ tag_offset = offset + tag_length;
+
+ switch (tag_type)
+ {
+ case EDONKEY_MTAG_HASH:
+ /* <Tag> ::= HASH */
+ tag_length += 16;
+ ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
+ metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
+ edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
+ proto_tree_add_item(metatag_tree, hf_edonkey_hash, tvb, tag_offset, 16, FALSE);
+ break;
+
+ case EDONKEY_MTAG_STRING:
+ /* <Tag> ::= <String> */
+ string_length = tvb_get_letohs(tvb, tag_offset);
+ tag_length += 2+string_length;
+ ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
+ metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
+ edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_string_length, tvb, tag_offset, 2, string_length);
+ proto_tree_add_item(metatag_tree, hf_edonkey_string, tvb, tag_offset+2, string_length, FALSE);
+ break;
+
+ case EDONKEY_MTAG_DWORD:
+ /* <Tag> ::= guint32 */
+ tag_length += 4;
+ ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
+ metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
+ edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
+ if (edonkey_metatag_name_get_type(tvb, offset+3, tag_name_size, special_tagtype) == EDONKEY_STAG_IP) {
+ proto_tree_add_item(metatag_tree, hf_edonkey_ip, tvb, tag_offset, 4, FALSE);
+ }
+ else {
+ tag_value_guint32 = tvb_get_letohl(tvb, tag_offset);
+ proto_tree_add_text(metatag_tree, tvb, tag_offset, 4, "Meta Tag Value: %u", tag_value_guint32);
+ }
+ break;
+
+ case EDONKEY_MTAG_FLOAT:
+ /* <Tag> ::= 4 byte float */
+ tag_length += 4;
+ ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
+ metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_type, tvb, offset, 1, tag_type);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
+ edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
+ break;
+
+ case EDONKEY_MTAG_BOOL: /* <Tag> ::= Boolean ?? bytes*/
+ case EDONKEY_MTAG_BOOL_ARRAY: /* <Tag> ::= ?? */
+ case EDONKEY_MTAG_BLOB: /* <Tag> ::= ?? */
+ case EDONKEY_MTAG_UNKNOWN:
+ default:
+ /* Unknown tag type - actual tag length is also unknown */
+ ti = proto_tree_add_item(tree, hf_edonkey_metatag, tvb, offset, tag_length, FALSE);
+ metatag_tree = proto_item_add_subtree(ti, ett_edonkey_metatag);
+ proto_tree_add_text(metatag_tree, tvb, offset, 1, "Unknown Meta Tag Type (0x%02x)", tag_type);
+ proto_tree_add_uint(metatag_tree, hf_edonkey_metatag_namesize, tvb, offset+1, 2, tag_name_size);
+ edonkey_tree_add_metatag_name(metatag_tree, tvb, offset+3, tag_name_size, special_tagtype);
+ break;
+
+ }
+
+ return offset + tag_length;
+}
+
+/* Dissects the eDonkey address */
+static int dissect_edonkey_address(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Address> ::= <IP> <Port> */
+/* guint32 ip = tvb_get_letohl(tvb, offset);
+ proto_tree_add_ipv4(tree, hf_edonkey_ip, tvb, offset, 4, ip); */
+ proto_tree_add_item(tree, hf_edonkey_ip, tvb, offset, 4, FALSE);
+ proto_tree_add_item(tree, hf_edonkey_port, tvb, offset+4, 2, TRUE);
+ return offset+6;
+}
+
+/* Dissects the eDonkey address list */
+static int dissect_edonkey_address_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Address List> ::= <List Size (guint8)> <Address>* */
+ return dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Address", dissect_edonkey_address);
+}
+
+/* Dissects the eMule address list */
+static int dissect_emule_address_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Address List> ::= <List Size (guint16)> <Address>* */
+ return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Address", dissect_edonkey_address);
+}
+
+/* Dissects the eDonkey hash */
+static int dissect_edonkey_hash(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <hash> ::= HASH (16 word MD4 digest) */
+ proto_tree_add_item(tree, hf_edonkey_hash, tvb, offset, 16, FALSE);
+ return offset+16;
+}
+
+
+/* Dissects the eDonkey hash list */
+static int dissect_edonkey_hash_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Hash List> ::= <List Size (guint16)> <Hash>* */
+ return dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Hash", dissect_edonkey_hash);
+}
+
+/* Dissects the eDonkey meta tag list */
+static int dissect_edonkey_metatag_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Meta Tag List> ::= <List Size (guint32)> <Meta tag>* */
+ return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Meta Tag", dissect_edonkey_metatag);
+}
+
+/* Dissects the eDonkey String */
+static int dissect_edonkey_string(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <String> ::= <String length (guint16)> DATA */
+ guint16 string_length = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_edonkey_string_length, tvb, offset, 2, string_length);
+ proto_tree_add_item(tree, hf_edonkey_string, tvb, offset+2, string_length, FALSE);
+ return offset+2+string_length;
+}
+
+/* Dissects the eDonkey Directory */
+static int dissect_edonkey_directory(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Directory> ::= <String> */
+ guint16 string_length = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_edonkey_string_length, tvb, offset, 2, string_length);
+ proto_tree_add_item(tree, hf_edonkey_directory, tvb, offset+2, string_length, FALSE);
+ return offset+2+string_length;
+}
+
+/* Dissects the eDonkey Filename */
+static int dissect_edonkey_file_name(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Filename> ::= <String> */
+ return dissect_edonkey_string(tvb, pinfo, offset, tree);
+}
+
+/* Dissects the eDonkey directory list */
+static int dissect_edonkey_directory_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Directory List> ::= <List Size (guint32)> <Directory>* */
+ return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Directory", dissect_edonkey_directory);
+}
+
+/* Dissects the eDonkey file hash */
+static int dissect_edonkey_file_hash(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <File hash> ::= HASH (16 word MD4 digest) */
+ proto_tree_add_item(tree, hf_edonkey_file_hash, tvb, offset, 16, FALSE);
+ return offset+16;
+}
+
+/* Dissects the eDonkey server hash */
+static int dissect_edonkey_server_hash(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Server hash> ::= HASH (16 word MD4 digest) */
+ proto_tree_add_item(tree, hf_edonkey_server_hash, tvb, offset, 16, FALSE);
+ return offset+16;
+}
+
+/* Dissects the eDonkey client hash */
+static int dissect_edonkey_client_hash(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Client hash> ::= HASH (16 word MD4 digest) */
+ proto_tree_add_item(tree, hf_edonkey_client_hash, tvb, offset, 16, FALSE);
+ return offset+16;
+}
+
+/* Dissects the eDonkey client ID */
+static int dissect_edonkey_client_id(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Client ID> ::= guint32 */
+/* guint32 ip = tvb_get_letohl(tvb, offset);
+ proto_tree_add_ipv4(tree, hf_edonkey_client_id, tvb, offset, 4, ip); */
+ proto_tree_add_item(tree, hf_edonkey_client_id, tvb, offset, 4, FALSE);
+ return offset+4;
+}
+
+/* Dissects the eDonkey port */
+static int dissect_edonkey_port(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Port> ::= guint16 */
+ proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
+ return offset+2;
+}
+
+/* Dissects the eDonkey start offset */
+static int dissect_edonkey_start_offset(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Start Offset> ::= guint32 */
+ guint32 start = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Start Offset: %u", start);
+ return offset+4;
+}
+
+/* Dissects the eDonkey end offset */
+static int dissect_edonkey_end_offset(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <End Offset> ::= guint32 */
+ guint32 end = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "End Offset: %u", end);
+ return offset+4;
+}
+
+/* Dissects the eDonkey client info */
+static int dissect_edonkey_client_info(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Client info> ::= <Client hash> <Client ID> <Port> <Meta tag list> */
+ proto_item *ti;
+ proto_tree *clientinfo_tree;
+ /* Add subtree for client info */
+ ti = proto_tree_add_item(tree, hf_edonkey_clientinfo, tvb, offset, 0, FALSE);
+ clientinfo_tree = proto_item_add_subtree(ti, ett_edonkey_clientinfo);
+ offset = dissect_edonkey_client_hash(tvb, pinfo, offset, clientinfo_tree);
+ offset = dissect_edonkey_client_id(tvb, pinfo, offset, clientinfo_tree);
+ offset = dissect_edonkey_port(tvb, pinfo, offset, clientinfo_tree);
+ offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, clientinfo_tree);
+ return offset;
+}
+
+/* Dissects the eDonkey client info list */
+static int dissect_edonkey_client_info_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Client Info List> ::= <List Size (guint32)> <Client Info>* */
+ return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "Client Info", dissect_edonkey_client_info);
+}
+
+/* Dissects the eDonkey server info */
+static int dissect_edonkey_server_info(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Server info> ::= <Server hash> <Server Address> <Meta tag list> */
+ proto_item *ti;
+ proto_tree *serverinfo_tree;
+ /* Add subtree for server info */
+ ti = proto_tree_add_item(tree, hf_edonkey_serverinfo, tvb, offset, 0, FALSE);
+ serverinfo_tree = proto_item_add_subtree(ti, ett_edonkey_serverinfo);
+ offset = dissect_edonkey_server_hash(tvb, pinfo, offset, serverinfo_tree);
+ offset = dissect_edonkey_address(tvb, pinfo, offset, serverinfo_tree);
+ offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, serverinfo_tree);
+ return offset;
+}
+
+/* Dissects the eDonkey file info */
+static int dissect_edonkey_file_info(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <File info> ::= <File hash> <Client ID> <Port> <Meta tag list> */
+ proto_item *ti;
+ proto_tree *fileinfo_tree;
+ /* Add subtree for file info */
+ ti = proto_tree_add_item(tree, hf_edonkey_fileinfo, tvb, offset, 0, FALSE);
+ fileinfo_tree = proto_item_add_subtree(ti, ett_edonkey_fileinfo);
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, fileinfo_tree);
+ offset = dissect_edonkey_client_id(tvb, pinfo, offset, fileinfo_tree);
+ offset = dissect_edonkey_port(tvb, pinfo, offset, fileinfo_tree);
+ offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, fileinfo_tree);
+ return offset;
+}
+
+/* Dissects the eDonkey file info list */
+static int dissect_edonkey_file_info_list(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <File Info List> ::= <List Size (guint32)> <File Info>* */
+ return dissect_edonkey_list(tvb, pinfo, offset, tree, 4, "File Info", dissect_edonkey_file_info);
+}
+
+/* Dissects the Overnet peer type */
+static int dissect_overnet_peertype(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Peer type> ::= guint8 */
+ guint8 peertype = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Peer Type: %u", peertype);
+ return offset+1;
+}
+
+/* Dissects the Overnet peer */
+static int dissect_overnet_peer(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Peer> ::= <Hash> <Address> <Peer type> */
+ proto_item *ti;
+ proto_tree *peer_tree;
+ ti = proto_tree_add_item(tree, hf_overnet_peer, tvb, offset, 16 + 6 + 1, FALSE);
+ peer_tree = proto_item_add_subtree(ti, ett_overnet_peer);
+ offset = dissect_edonkey_hash(tvb, pinfo, offset, peer_tree);
+ offset = dissect_edonkey_address(tvb, pinfo, offset, peer_tree);
+ offset = dissect_overnet_peertype(tvb, pinfo, offset, peer_tree);
+ return offset;
+}
+
+/* Dissects the eDonkey search query */
+static int dissect_edonkey_search_query(tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, proto_tree *tree)
+{
+ /* <Search Query> ::= <Search Type> <Search> */
+ proto_item *ti;
+ proto_tree *search_tree;
+ guint8 search_type, operator, special_tagtype, limit_type;
+ guint16 tag_name_size, string_length;
+ guint32 search_length, limit;
+ int string_offset, tag_name_offset;
+
+ search_type = tvb_get_guint8(tvb, offset);
+ search_length = 1;
+
+ switch (search_type)
+ {
+ case EDONKEY_SEARCH_BOOL:
+ /* <Search> ::= <Operator> <Search Query> <Search Query> */
+ search_length += 1;
+ operator = tvb_get_guint8(tvb, offset+1);
+
+ /* Add subtree for search entry */
+ ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
+ search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
+
+ /* Add query info */
+ proto_tree_add_text(search_tree, tvb, offset, 2, "Boolean search (0x%02x): %s (0x%02x)",
+ search_type, val_to_str(operator, edonkey_search_ops, "Unknown"), operator);
+
+ offset+=2;
+ offset = dissect_edonkey_search_query(tvb, pinfo, offset, search_tree);
+ offset = dissect_edonkey_search_query(tvb, pinfo, offset, search_tree);
+ break;
+
+ case EDONKEY_SEARCH_NAME:
+ /* <Search> ::= <String> */
+ string_offset = offset + search_length;
+ string_length = tvb_get_letohs(tvb, string_offset);
+ search_length += 2+string_length;
+
+ /* Add subtree for search entry */
+ ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
+ search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
+
+ /* Add query info */
+ proto_tree_add_text(search_tree, tvb, offset, 1, "Search by name (0x%02x)", search_type);
+ proto_tree_add_uint(search_tree, hf_edonkey_string_length, tvb, string_offset, 2, string_length);
+ proto_tree_add_item(search_tree, hf_edonkey_string, tvb, string_offset+2, string_length, FALSE);
+ offset += search_length;
+ break;
+
+ case EDONKEY_SEARCH_META:
+ /* <Search> ::= <String> <Meta tag Name> */
+ string_offset = offset + search_length;
+ string_length = tvb_get_letohs(tvb, offset+1);
+ search_length += 2+string_length;
+
+ tag_name_offset = offset + search_length;
+ tag_name_size = tvb_get_letohs(tvb, tag_name_offset);
+ special_tagtype = tvb_get_guint8(tvb, tag_name_offset+2);
+ search_length += 2 + tag_name_size;
+
+ /* Add subtree for search entry */
+ ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
+ search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
+
+ /* Add query info */
+ proto_tree_add_text(search_tree, tvb, offset, 1, "Search by metadata (0x%02x)", search_type);
+ proto_tree_add_uint(search_tree, hf_edonkey_string_length, tvb, string_offset, 2, string_length);
+ proto_tree_add_item(search_tree, hf_edonkey_string, tvb, string_offset+2, string_length, FALSE);
+ proto_tree_add_uint(search_tree, hf_edonkey_metatag_namesize, tvb, tag_name_offset, 2, tag_name_size);
+ edonkey_tree_add_metatag_name(search_tree, tvb, tag_name_offset+2, tag_name_size, special_tagtype);
+ offset += search_length;
+ break;
+
+ case EDONKEY_SEARCH_LIMIT:
+ /* <Search> ::= <Limit (guint32)> <Minmax> <Meta tag Name> */
+ search_length += 5; /* 4 bytes for the limit, one for the minmax */
+ limit = tvb_get_letohl(tvb, offset+1);
+ limit_type = tvb_get_guint8(tvb, offset+5);
+
+ tag_name_offset = offset + search_length;
+ tag_name_size = tvb_get_letohs(tvb, tag_name_offset);
+ special_tagtype = tvb_get_guint8(tvb, tag_name_offset+2);
+ search_length += 2 + tag_name_size;
+
+ /* Add subtree for search entry */
+ ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
+ search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
+
+ /* Add query info */
+ proto_tree_add_text(search_tree, tvb, offset, 6, "Search by limit (0x%02x): %s %u",
+ search_type, val_to_str(limit_type, edonkey_search_conds, "Unknown"), limit);
+ proto_tree_add_uint(search_tree, hf_edonkey_metatag_namesize, tvb, tag_name_offset, 2, tag_name_size);
+ edonkey_tree_add_metatag_name(search_tree, tvb, tag_name_offset+2, tag_name_size, special_tagtype);
+ offset += search_length;
+ break;
+
+ default:
+ /* Unknown search type - actual search length is also unknown */
+ ti = proto_tree_add_item(tree, hf_edonkey_search, tvb, offset, search_length, FALSE);
+ search_tree = proto_item_add_subtree(ti, ett_edonkey_search);
+ proto_tree_add_text(search_tree, tvb, offset, search_length, "Unknown Search (0x%02x)", search_type);
+ offset += search_length;
+ break;
+ }
+
+ return offset;
+}
+
+static void dissect_edonkey_tcp_message(guint8 msg_type,
+ tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, int length, proto_tree *tree)
+{
+ int msg_start, msg_end, bytes_remaining;
+ guint8 hello, more;
+ guint32 nusers, nfiles;
+
+ if (tree == NULL) return;
+
+ bytes_remaining = tvb_reported_length_remaining(tvb, offset);
+ if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
+ if (length <= 0) return;
+
+ msg_start = offset;
+ msg_end = offset + length;
+
+ switch (msg_type) {
+ case EDONKEY_MSG_HELLO:
+ /* Client to Server: <Client Info> */
+ /* Client to Client: 0x10 <Client Info> */
+ hello = tvb_get_guint8(tvb, offset);
+ if (hello == 0x10) /* Hello Client */
+ offset += 1;
+ offset = dissect_edonkey_client_info(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_HELLO_ANSWER: /* Hello Answer: <Client Info> <Server address> */
+ offset = dissect_edonkey_client_info(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_address(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_SERVER_CB_REQ: /* Server Callback Request: <Client address> */
+ offset = dissect_edonkey_address(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_SERVER_INFO_DATA: /* Server Info Data: <Server Info> */
+ offset = dissect_edonkey_server_info(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_SERVER_LIST: /* Server List: <Address List> */
+ offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_OFFER_FILES: /* Offer Files: <File info List> */
+ case EDONKEY_MSG_VIEW_FILES_ANSWER: /* View Files Answer: <File info list> */
+ offset = dissect_edonkey_file_info_list(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_SEARCH_FILE_RESULTS: /* Search File Results: <File Info list> <More> */
+ offset = dissect_edonkey_file_info_list(tvb, pinfo, offset, tree);
+ more = tvb_get_guint8(tvb, offset);
+ if (more)
+ proto_tree_add_text(tree, tvb, offset, 1, "More: TRUE (0x%02x)", more);
+ else proto_tree_add_text(tree, tvb, offset, 1, "More: FALSE (0x%02x)", more);
+ break;
+
+ case EDONKEY_MSG_SEARCH_FILES: /* Search File: <Search query> */
+ case EDONKEY_MSG_SEARCH_USER: /* Search User: <Search query> */
+ offset = dissect_edonkey_search_query(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_GET_SOURCES: /* Get Sources: <File Hash> */
+ case EDONKEY_MSG_NO_SUCH_FILE: /* No Such File: <File Hash> */
+ case EDONKEY_MSG_END_OF_DOWNLOAD: /* End of Download: <File Hash> */
+ case EDONKEY_MSG_FILE_STATUS_REQUEST: /* File Status Request: <File Hash> */
+ case EDONKEY_MSG_HASHSET_REQUEST: /* Hashset Request: <File Hash> */
+ case EDONKEY_MSG_SLOT_REQUEST: /* Slot Request: <File Hash> */
+ case EDONKEY_MSG_FILE_REQUEST: /* File Request: <File Hash> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_FOUND_SOURCES: /* Found Sources: <File Hash> <Address List> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_CLIENT_CB_REQ: /* Client Callback Request: <Client ID> */
+ case EDONKEY_MSG_CALLBACK_FAIL: /* Callback Fail: <Client ID> */
+ case EDONKEY_MSG_ID_CHANGE: /* ID Change: <Client ID> */
+ offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_NEW_CLIENT_ID: /* New Client ID: <Client ID> <Client ID> */
+ offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_SERVER_MESSAGE: /* Server Message: <String> */
+ case EDONKEY_MSG_CLIENT_MESSAGE: /* Client Message: <String> */
+ offset = dissect_edonkey_string(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_SERVER_STATUS: /* Server Status: <Nusers> <Nfiles> */
+ nusers = tvb_get_letohl(tvb, offset);
+ nfiles = tvb_get_letohl(tvb, offset+4);
+ proto_tree_add_text(tree, tvb, offset, 4, "Number of Users: %u", nusers);
+ proto_tree_add_text(tree, tvb, offset+4, 4, "Number of Files: %u", nfiles);
+ break;
+
+ case EDONKEY_MSG_FILE_REQUEST_ANSWER: /* File Request Answer: <File hash> <File name> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_file_name(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_REQUEST_PARTS: /* Request Parts: <File hash> <Start offset>(3) <End offset>(3) */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_SENDING_PART: /* Sending Part: <File hash> <Start offset> <End offset> DATA */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_end_offset(tvb, pinfo, offset, tree);
+ if (msg_end > offset) {
+ bytes_remaining = msg_end - offset;
+ proto_tree_add_text(tree, tvb, offset, bytes_remaining, "Message Data (%d bytes)", bytes_remaining);
+ }
+ break;
+
+
+ case EDONKEY_MSG_SEARCH_USER_RESULTS: /* Search User Results: <Client info list> */
+ offset = dissect_edonkey_client_info_list(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_GET_SHARED_FILES: /* Get Shared Files: <Directory> */
+ offset = dissect_edonkey_directory(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_SHARED_DIRS: /* Shared Dirs: <Directory List> */
+ offset = dissect_edonkey_directory_list(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_SHARED_FILES: /* Shared Files: <Directory> <File info list> */
+ offset = dissect_edonkey_directory(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_file_info_list(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_HASHSET_ANSWER: /* Hashset Answer: <Hash List> */
+ offset = dissect_edonkey_hash_list(tvb, pinfo, offset, tree);
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length);
+ break;
+ }
+ return;
+}
+
+static void dissect_emule_tcp_message(guint8 msg_type,
+ tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, int length, proto_tree *tree)
+{
+ int msg_start, msg_end, bytes_remaining;
+ guint32 packed_length;
+ guint16 version, rank;
+
+ if (tree == NULL) return;
+
+ bytes_remaining = tvb_reported_length_remaining(tvb, offset);
+ if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
+ if (length <= 0) return;
+
+ msg_start = offset;
+ msg_end = offset + length;
+
+ switch (msg_type) {
+ case EMULE_MSG_HELLO: /* eMule Hello: <eMule Version> <Meta tag list> */
+ case EMULE_MSG_HELLO_ANSWER: /* eMule Hello Answer: <eMule Version> <Meta tag list> */
+ version = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Version: %u", version);
+ offset = dissect_edonkey_metatag_list(tvb, pinfo, offset+2, tree);
+ break;
+
+ case EMULE_MSG_QUEUE_RANKING: /* eMule Queue Ranking: <eMule Rank (guint16)> */
+ rank = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Queue Ranking: %u", rank);
+ break;
+
+ case EMULE_MSG_SOURCES_REQUEST: /* Sources Request: <File Hash> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ break;
+
+ case EMULE_MSG_SOURCES_ANSWER: /* Sources Answer: <File Hash> <Address List> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ offset = dissect_emule_address_list(tvb, pinfo, offset, tree);
+ break;
+
+ case EMULE_MSG_DATA_COMPRESSED: /* Data Compressed: <File Hash> <Start Offset> <Length (guint32)> <DATA> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_start_offset(tvb, pinfo, offset, tree);
+ packed_length = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, packed_length, "Packed Length: %u", packed_length);
+ offset += 4;
+ if (msg_end > offset) {
+ bytes_remaining = msg_end - offset;
+ proto_tree_add_text(tree, tvb, offset, bytes_remaining,
+ "Compressed Message Data (%d bytes)", bytes_remaining);
+ }
+ break;
+
+ default:
+ dissect_edonkey_tcp_message(msg_type, tvb, pinfo, offset, length, tree);
+ break;
+ }
+ return;
+}
+
+static void dissect_edonkey_udp_message(guint8 msg_type,
+ tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, int length, proto_tree *tree)
+{
+ int msg_start, msg_end, bytes_remaining;
+ guint8 type;
+ guint16 min, max;
+ guint32 nusers, nfiles;
+
+ if (tree == NULL) return;
+
+ bytes_remaining = tvb_reported_length_remaining(tvb, offset);
+ if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
+ if (length <= 0) return;
+
+ msg_start = offset;
+ msg_end = offset + length;
+
+ switch (msg_type) {
+ /* EDonkey UDP Messages */
+ case EDONKEY_MSG_UDP_CALLBACK_REQUEST: /* Callback Request: <Address> <Client ID> */
+ offset = dissect_edonkey_address(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_UDP_CALLBACK_FAIL: /* Callback Fail: <Client ID> */
+ offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_UDP_SERVER_INFO: /* Server Info: <String> <String>*/
+ offset = dissect_edonkey_string(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_string(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_UDP_SERVER_LIST: /* Server List: <Address List> */
+ offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_UDP_SEARCH_FILE_RESULTS: /* Search File Result: <File Info> */
+ offset = dissect_edonkey_file_info(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_UDP_SEARCH_FILE: /* Search File: <Search query> */
+ offset = dissect_edonkey_search_query(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_UDP_GET_SOURCES: /* Get Sources: <File Hash> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_UDP_FOUND_SOURCES: /* Found Sources: <File Hash> <Address List> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_address_list(tvb, pinfo, offset, tree);
+ break;
+
+ case EDONKEY_MSG_UDP_SERVER_STATUS: /* Server Status: <guint32> <Nusers> <Nfiles> <Nusersmax> */
+ offset += 4;
+ nusers = tvb_get_letohl(tvb, offset);
+ nfiles = tvb_get_letohl(tvb, offset+4);
+ proto_tree_add_text(tree, tvb, offset, 4, "Number of Users: %u", nusers);
+ proto_tree_add_text(tree, tvb, offset+4, 4, "Number of Files: %u", nfiles);
+ offset += 8;
+ if (offset < msg_end) {
+ nusers = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Max number of Users: %u", nusers);
+ offset += 4;
+ }
+ break;
+
+ /* Overnet UDP Messages */
+ case OVERNET_MSG_UDP_CONNECT: /* Connect: <Peer (sender) > */
+ case OVERNET_MSG_UDP_PUBLICIZE: /* Publicize: <Peer (sender) > */
+ offset = dissect_overnet_peer(tvb, pinfo, offset, tree);
+ break;
+
+ case OVERNET_MSG_UDP_CONNECT_REPLY: /* Connect Reply: <guint16 Peer List> */
+ offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 2, "Overnet Peer", dissect_overnet_peer);
+ break;
+
+ case OVERNET_MSG_UDP_SEARCH: /* Search: <search type (guint8)> <Hash> */
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Search Type: %u", type);
+ offset = dissect_edonkey_hash(tvb, pinfo, offset+1, tree);
+ break;
+
+ case OVERNET_MSG_UDP_SEARCH_INFO:
+ /* Search Info: <Hash> <search type (guint8)> <min (guint16)> <max (guint16)>*/
+ offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
+ type = tvb_get_guint8(tvb, offset);
+ min = tvb_get_letohs(tvb, offset+1);
+ max = tvb_get_letohs(tvb, offset+3);
+ proto_tree_add_text(tree, tvb, offset, 1, "Search Type: %u", type);
+ proto_tree_add_text(tree, tvb, offset+1, 4, "Search Range: Min=%u Max=%u", min, max);
+ break;
+
+ case OVERNET_MSG_UDP_SEARCH_NEXT: /* Search Next: <Hash> <guint8 Peer List> */
+ offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_list(tvb, pinfo, offset, tree, 1, "Overnet Peer", dissect_overnet_peer);
+ break;
+
+ case OVERNET_MSG_UDP_SEARCH_RESULT: /* Search Result: <Hash> <Hash> <Meta tag List> */
+ case OVERNET_MSG_UDP_PUBLISH: /* Publish: <Hash> <Hash> <Meta tag List> */
+ offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_metatag_list(tvb, pinfo, offset, tree);
+ break;
+
+ case OVERNET_MSG_UDP_SEARCH_END: /* Search End: <Hash> */
+ offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
+ break;
+
+ case OVERNET_MSG_UDP_PUBLISH_ACK: /* Publish ACK: <File Hash> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ break;
+
+ case OVERNET_MSG_UDP_IP_QUERY: /* IP Query: <TCP Port> */
+ proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
+ break;
+
+ case OVERNET_MSG_UDP_IP_QUERY_ANSWER: /* IP Query Answer: <IP> */
+ offset = dissect_edonkey_client_id(tvb, pinfo, offset, tree);
+ break;
+
+ case OVERNET_MSG_UDP_IDENTIFY_REPLY: /* Identify Reply: <Contact (sender)> */
+ /* <Contact> ::= <Hash> <Address> */
+ offset = dissect_edonkey_hash(tvb, pinfo, offset, tree);
+ offset = dissect_edonkey_address(tvb, pinfo, offset, tree);
+ break;
+
+ case OVERNET_MSG_UDP_IDENTIFY_ACK: /* Identify Reply: <TCP Port (sender)> */
+ proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
+ break;
+
+ case OVERNET_MSG_UDP_FIREWALL_CONNECTION: /* Firewall Connnection Ack: <Hash> <TCP Port> */
+ offset = dissect_edonkey_client_hash(tvb, pinfo, offset, tree);
+ proto_tree_add_item(tree, hf_edonkey_port, tvb, offset, 2, TRUE);
+ break;
+
+ case OVERNET_MSG_UDP_FIREWALL_CONNECTION_ACK: /* Firewall Connnection Ack: <Hash> */
+ case OVERNET_MSG_UDP_FIREWALL_CONNECTION_NACK: /* Firewall Connnection NAck: <Hash> */
+ offset = dissect_edonkey_client_hash(tvb, pinfo, offset, tree);
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, length, "Message Data (%d bytes)", length);
+ break;
+ }
+ return;
+}
+
+static void dissect_emule_udp_message(guint8 msg_type,
+ tvbuff_t *tvb, packet_info *pinfo _U_,
+ int offset, int length, proto_tree *tree)
+{
+ int msg_start, msg_end, bytes_remaining;
+ guint16 rank;
+
+ bytes_remaining = tvb_reported_length_remaining(tvb, offset);
+ if ((length < 0) || (length > bytes_remaining)) length = bytes_remaining;
+ if (length <= 0) return;
+
+ msg_start = offset;
+ msg_end = offset + length;
+
+ switch (msg_type) {
+ case EMULE_MSG_UDP_REASKFILEPING: /* Reask File Ping: <File Hash> */
+ offset = dissect_edonkey_file_hash(tvb, pinfo, offset, tree);
+ break;
+
+ case EMULE_MSG_UDP_REASKACK: /* Reask ACK: <eMule Rank> */
+ rank = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Queue Ranking: %u", rank);
+ break;
+
+ default:
+ dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, length,tree);
+ break;
+ }
+ return;
+}
+
+static void dissect_edonkey_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL;
+ int offset, bytes, messages;
+ guint8 protocol, msg_type;
+ guint32 msg_len;
+ gchar *protocol_name, *message_name;
+ void (*dissector)(guint8, tvbuff_t*, packet_info*, int, int, proto_tree*);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE);
+ edonkey_tree = proto_item_add_subtree(ti, ett_edonkey);
+ }
+
+ offset = 0;
+ messages = 0;
+ while (tvb_length_remaining(tvb, offset) >= EDONKEY_TCP_HEADER_LENGTH) {
+ protocol = tvb_get_guint8(tvb, offset);
+ msg_len = tvb_get_letohl(tvb, offset+1);
+
+ protocol_name = match_strval(protocol, edonkey_protocols);
+ if (protocol_name == NULL) {
+ /* Not a recognized eDonkey protocol - probably a continuation */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "eDonkey Continuation");
+ if (edonkey_tree) {
+ bytes = tvb_length_remaining(tvb, offset);
+ proto_tree_add_text(edonkey_tree, tvb, 0, -1, "Continuation data (%d bytes)", bytes);
+ }
+ return;
+ }
+
+ /* Add edonkey message tree */
+ if (edonkey_tree) {
+ ti = proto_tree_add_item(edonkey_tree, hf_edonkey_message, tvb,
+ offset, EDONKEY_TCP_HEADER_LENGTH + msg_len, FALSE);
+ edonkey_msg_tree = proto_item_add_subtree(ti, ett_edonkey_message);
+
+ proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_protocol, tvb, offset, 1, protocol,
+ "Protocol: %s (0x%02x)", protocol_name, protocol);
+ proto_tree_add_uint(edonkey_msg_tree, hf_edonkey_message_length, tvb, offset+1, 4, msg_len);
+ }
+
+
+ /* Skip past the EDONKEY Header */
+ offset += EDONKEY_TCP_HEADER_LENGTH;
+
+ if(tvb_reported_length_remaining(tvb, offset) <= 0) {
+ /* There is not enough space for the msg_type - mark as fragment */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (messages == 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP Message Fragment", protocol_name);
+ else col_append_fstr(pinfo->cinfo, COL_INFO, "; %s TCP Message Fragment", protocol_name);
+ }
+ return;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (messages == 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s TCP", protocol_name);
+ else col_append_fstr(pinfo->cinfo, COL_INFO, "; %s TCP", protocol_name);
+ }
+
+ msg_type = tvb_get_guint8(tvb, offset);
+ switch (protocol) {
+ case EDONKEY_PROTO_EDONKEY:
+ message_name = val_to_str(msg_type, edonkey_tcp_msgs, "Unknown");
+ dissector = dissect_edonkey_tcp_message;
+ break;
+
+ case EDONKEY_PROTO_EMULE_EXT:
+ message_name = val_to_str(msg_type, emule_tcp_msgs,
+ val_to_str(msg_type, edonkey_tcp_msgs, "Unknown"));
+ dissector = dissect_emule_tcp_message;
+ break;
+
+ default:
+ message_name = "Unknown";
+ dissector = NULL;
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", message_name);
+ }
+
+
+ if (edonkey_msg_tree) {
+ proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_message_type, tvb, offset, 1, msg_type,
+ "Message Type: %s (0x%02x)", message_name, msg_type);
+ if (dissector && (msg_len > 1))
+ (*dissector)(msg_type, tvb, pinfo, offset+1, msg_len-1, edonkey_msg_tree);
+ }
+
+ offset += msg_len;
+ messages++;
+ }
+}
+
+static void dissect_edonkey_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *edonkey_tree = NULL, *edonkey_msg_tree = NULL;
+ int offset;
+ guint8 protocol, msg_type;
+ gchar *protocol_name, *message_name;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "eDonkey");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "eDonkey UDP Message");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_edonkey, tvb, 0, -1, FALSE);
+ edonkey_tree = proto_item_add_subtree(ti, ett_edonkey);
+ }
+
+ offset = 0;
+ /* eDonkey UDP message - Assume that there is one message per packet */
+ if (tvb_length_remaining(tvb, offset) >= EDONKEY_UDP_HEADER_LENGTH) {
+ protocol = tvb_get_guint8(tvb, offset);
+ msg_type = tvb_get_guint8(tvb, offset+1);
+ protocol_name = val_to_str(protocol, edonkey_protocols, "Unknown");
+ message_name = val_to_str(msg_type, edonkey_udp_msgs, "Unknown");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s UDP: %s", protocol_name, message_name);
+ }
+
+ if (edonkey_tree) {
+ ti = proto_tree_add_item(edonkey_tree, hf_edonkey_message, tvb, offset, -1, FALSE);
+ edonkey_msg_tree = proto_item_add_subtree(ti, ett_edonkey_message);
+
+ proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_protocol, tvb, offset, 1, protocol,
+ "Protocol: %s (0x%02x)", protocol_name, protocol);
+ proto_tree_add_uint_format(edonkey_msg_tree, hf_edonkey_message_type, tvb, offset+1, 1, msg_type,
+ "Message Type: %s (0x%02x)", message_name, msg_type);
+
+ offset += EDONKEY_UDP_HEADER_LENGTH;
+
+ switch (protocol) {
+ case EDONKEY_PROTO_EDONKEY:
+ dissect_edonkey_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree);
+ break;
+
+ case EDONKEY_PROTO_EMULE_EXT:
+ dissect_emule_udp_message(msg_type, tvb, pinfo, offset, -1, edonkey_msg_tree);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void proto_register_edonkey(void) {
+
+ static hf_register_info hf[] = {
+ { &hf_edonkey_message,
+ { "eDonkey Message", "edonkey.message",
+ FT_NONE, BASE_NONE, NULL, 0, "eDonkey Message", HFILL } },
+ { &hf_edonkey_protocol,
+ { "Protocol", "edonkey.protocol",
+ FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Protocol", HFILL } },
+ { &hf_edonkey_message_length,
+ { "Message Length", "edonkey.message.length",
+ FT_UINT32, BASE_DEC, NULL, 0, "eDonkey Message Length", HFILL } },
+ { &hf_edonkey_message_type,
+ { "Message Type", "edonkey.message.type",
+ FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Message Type", HFILL } },
+ { &hf_edonkey_client_hash,
+ { "Client Hash", "edonkey.client_hash",
+ FT_BYTES, BASE_HEX, NULL, 0, "eDonkey Client Hash", HFILL } },
+ { &hf_edonkey_server_hash,
+ { "Server Hash", "edonkey.server_hash",
+ FT_BYTES, BASE_HEX, NULL, 0, "eDonkey Server Hash", HFILL } },
+ { &hf_edonkey_file_hash,
+ { "File Hash", "edonkey.file_hash",
+ FT_BYTES, BASE_HEX, NULL, 0, "eDonkey File Hash", HFILL } },
+ { &hf_edonkey_client_id,
+ { "Client ID", "edonkey.clientid",
+ FT_IPv4, BASE_DEC, NULL, 0, "eDonkey Client ID", HFILL } },
+ { &hf_edonkey_ip,
+ { "IP", "edonkey.ip",
+ FT_IPv4, BASE_DEC, NULL, 0, "eDonkey IP", HFILL } },
+ { &hf_edonkey_port,
+ { "Port", "edonkey.port",
+ FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Port", HFILL } },
+ { &hf_edonkey_metatag,
+ { "eDonkey Meta Tag", "edonkey.metatag",
+ FT_NONE, BASE_NONE, NULL, 0, "eDonkey Meta Tag", HFILL } },
+ { &hf_edonkey_metatag_type,
+ { "Meta Tag Type", "edonkey.metatag.type",
+ FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Meta Tag Type", HFILL } },
+ { &hf_edonkey_metatag_id,
+ { "Meta Tag ID", "edonkey.metatag.id",
+ FT_UINT8, BASE_HEX, NULL, 0, "eDonkey Meta Tag ID", HFILL } },
+ { &hf_edonkey_metatag_name,
+ { "Meta Tag Name", "edonkey.metatag.name",
+ FT_STRING, BASE_NONE, NULL, 0, "eDonkey Meta Tag Name", HFILL } },
+ { &hf_edonkey_metatag_namesize,
+ { "Meta Tag Name Size", "edonkey.metatag.namesize",
+ FT_UINT16, BASE_DEC, NULL, 0, "eDonkey Meta Tag Name Size", HFILL } },
+ { &hf_edonkey_search,
+ { "eDonkey Search", "edonkey.search",
+ FT_NONE, BASE_NONE, NULL, 0, "eDonkey Search", HFILL } },
+ { &hf_edonkey_hash,
+ { "Hash", "edonkey.hash",
+ FT_BYTES, BASE_HEX, NULL, 0, "eDonkey Hash", HFILL } },
+ { &hf_edonkey_string,
+ { "String", "edonkey.string",
+ FT_STRING, BASE_NONE, NULL, 0, "eDonkey String", HFILL } },
+ { &hf_edonkey_string_length,
+ { "String Length", "edonkey.string_length",
+ FT_UINT16, BASE_DEC, NULL, 0, "eDonkey String Length", HFILL } },
+ { &hf_edonkey_directory,
+ { "Directory", "edonkey.directory",
+ FT_STRING, BASE_NONE, NULL, 0, "eDonkey Directory", HFILL } },
+ { &hf_edonkey_fileinfo,
+ { "eDonkey File Info", "edonkey.fileinfo",
+ FT_NONE, BASE_NONE, NULL, 0, "eDonkey File Info", HFILL } },
+ { &hf_edonkey_serverinfo,
+ { "eDonkey Server Info", "edonkey.serverinfo",
+ FT_NONE, BASE_NONE, NULL, 0, "eDonkey Server Info", HFILL } },
+ { &hf_edonkey_clientinfo,
+ { "eDonkey Client Info", "edonkey.clientinfo",
+ FT_NONE, BASE_NONE, NULL, 0, "eDonkey Client Info", HFILL } },
+ { &hf_overnet_peer,
+ { "Overnet Peer", "overnet.peer",
+ FT_NONE, BASE_NONE, NULL, 0, "Overnet Peer", HFILL } },
+ };
+
+ static gint *ett[] = {
+ &ett_edonkey,
+ &ett_edonkey_message,
+ &ett_edonkey_metatag,
+ &ett_edonkey_search,
+ &ett_edonkey_fileinfo,
+ &ett_edonkey_serverinfo,
+ &ett_edonkey_clientinfo,
+ &ett_overnet_peer
+ };
+
+ proto_edonkey = proto_register_protocol("eDonkey Protocol", "EDONKEY", "edonkey");
+
+ proto_register_field_array(proto_edonkey, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("edonkey.tcp", dissect_edonkey_tcp, proto_edonkey);
+ register_dissector("edonkey.udp", dissect_edonkey_udp, proto_edonkey);
+}
+
+void proto_reg_handoff_edonkey(void) {
+ dissector_handle_t edonkey_tcp_handle;
+ dissector_handle_t edonkey_udp_handle;
+
+ edonkey_tcp_handle = find_dissector("edonkey.tcp");
+ edonkey_udp_handle = find_dissector("edonkey.udp");
+
+ dissector_add("tcp.port", 4661, edonkey_tcp_handle);
+ dissector_add("tcp.port", 4662, edonkey_tcp_handle);
+ dissector_add("tcp.port", 4663, edonkey_tcp_handle);
+ dissector_add("udp.port", 4665, edonkey_udp_handle);
+ dissector_add("udp.port", 4672, edonkey_udp_handle);
+}
diff --git a/epan/dissectors/packet-edonkey.h b/epan/dissectors/packet-edonkey.h
new file mode 100644
index 0000000000..21bb2e6c60
--- /dev/null
+++ b/epan/dissectors/packet-edonkey.h
@@ -0,0 +1,209 @@
+/* packet-edonkey.h
+ * Declarations for edonkey dissection
+ * Copyright 2003, Xuan Zhang <xz@aemail4u.com>
+ * eDonkey dissector based on protocol descriptions from mldonkey:
+ * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/edonkey-protocol.txt
+ * http://savannah.nongnu.org/download/mldonkey/docs/Edonkey-Overnet/overnet-protocol.txt
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+void proto_register_edonkey(void);
+
+#define EDONKEY_MAX_SNAP_SIZE 1500
+#define EDONKEY_TCP_HEADER_LENGTH 5
+#define EDONKEY_UDP_HEADER_LENGTH 2
+
+/* Definitions for EDONKEY protocols */
+#define EDONKEY_PROTO_EDONKEY 0xe3 /* eDonkey */
+#define EDONKEY_PROTO_EMULE_EXT 0xc5 /* eMule extensions */
+#define EDONKEY_PROTO_EMULE_COMP 0xd4 /* eMule compressed (data is zlib compressed) */
+
+/* Definitions for EDONKEY messages */
+/* EDONKEY TCP MESSAGES */
+/* Client <-> Server */
+#define EDONKEY_MSG_HELLO 0x01
+#define EDONKEY_MSG_BAD_PROTO 0x05
+#define EDONKEY_MSG_GET_SERVER_LIST 0x14
+#define EDONKEY_MSG_OFFER_FILES 0x15
+#define EDONKEY_MSG_SEARCH_FILES 0x16
+#define EDONKEY_MSG_DISCONNECT 0x18
+#define EDONKEY_MSG_GET_SOURCES 0x19
+#define EDONKEY_MSG_SEARCH_USER 0x1a
+/* define EDONKEY_MSG_UNKNOWN 0x1b */
+#define EDONKEY_MSG_CLIENT_CB_REQ 0x1c
+/* define EDONKEY_MSG_UNKNOWN 0x20 */
+#define EDONKEY_MSG_MORE_RESULTS 0x21
+#define EDONKEY_MSG_SERVER_LIST 0x32
+#define EDONKEY_MSG_SEARCH_FILE_RESULTS 0x33
+#define EDONKEY_MSG_SERVER_STATUS 0x34
+#define EDONKEY_MSG_SERVER_CB_REQ 0x35
+#define EDONKEY_MSG_CALLBACK_FAIL 0x36
+#define EDONKEY_MSG_SERVER_MESSAGE 0x38
+#define EDONKEY_MSG_ID_CHANGE 0x40
+#define EDONKEY_MSG_SERVER_INFO_DATA 0x41
+#define EDONKEY_MSG_FOUND_SOURCES 0x42
+#define EDONKEY_MSG_SEARCH_USER_RESULTS 0x43
+
+/* Client <-> Client */
+#define EDONKEY_MSG_HELLO_CLIENT 0x10 /* 0x01 0x10 */
+#define EDONKEY_MSG_SENDING_PART 0x46
+#define EDONKEY_MSG_REQUEST_PARTS 0x47
+#define EDONKEY_MSG_NO_SUCH_FILE 0x48
+#define EDONKEY_MSG_END_OF_DOWNLOAD 0x49
+#define EDONKEY_MSG_VIEW_FILES 0x4a
+#define EDONKEY_MSG_VIEW_FILES_ANSWER 0x4b
+#define EDONKEY_MSG_HELLO_ANSWER 0x4c
+#define EDONKEY_MSG_NEW_CLIENT_ID 0x4d
+#define EDONKEY_MSG_CLIENT_MESSAGE 0x4e
+#define EDONKEY_MSG_FILE_STATUS_REQUEST 0x4f
+#define EDONKEY_MSG_FILE_STATUS 0x50
+#define EDONKEY_MSG_HASHSET_REQUEST 0x51
+#define EDONKEY_MSG_HASHSET_ANSWER 0x52
+/*#define EDONKEY_MSG_UNKNOWN 0x53 */
+#define EDONKEY_MSG_SLOT_REQUEST 0x54
+#define EDONKEY_MSG_SLOT_GIVEN 0x55
+#define EDONKEY_MSG_SLOT_RELEASE 0x56
+#define EDONKEY_MSG_SLOT_TAKEN 0x57
+#define EDONKEY_MSG_FILE_REQUEST 0x58
+#define EDONKEY_MSG_FILE_REQUEST_ANSWER 0x59
+/*#define EDONKEY_MSG_UNKNOWN 0x5b*/
+#define EDONKEY_MSG_GET_SHARED_DIRS 0x5d
+#define EDONKEY_MSG_GET_SHARED_FILES 0x5e
+#define EDONKEY_MSG_SHARED_DIRS 0x5f
+#define EDONKEY_MSG_SHARED_FILES 0x60
+#define EDONKEY_MSG_SHARED_DENIED 0x61
+
+/* OVERNET EXTENSIONS */
+/*#define OVERNET_MSG_UNKNOWN 0x62*/
+/*#define OVERNET_MSG_UNKNOWN 0x63*/
+
+/* EMULE EXTENSIONS */
+#define EMULE_MSG_HELLO 0x01
+#define EMULE_MSG_HELLO_ANSWER 0x02
+#define EMULE_MSG_DATA_COMPRESSED 0x40
+#define EMULE_MSG_QUEUE_RANKING 0x60
+#define EMULE_MSG_SOURCES_REQUEST 0x81
+#define EMULE_MSG_SOURCES_ANSWER 0x82
+
+/* EDONKEY UDP MESSAGES */
+#define EDONKEY_MSG_UDP_SERVER_STATUS_REQUEST 0x96
+#define EDONKEY_MSG_UDP_SERVER_STATUS 0x97
+#define EDONKEY_MSG_UDP_SEARCH_FILE 0x98
+#define EDONKEY_MSG_UDP_SEARCH_FILE_RESULTS 0x99
+#define EDONKEY_MSG_UDP_GET_SOURCES 0x9a
+#define EDONKEY_MSG_UDP_FOUND_SOURCES 0x9b
+#define EDONKEY_MSG_UDP_CALLBACK_REQUEST 0x9c
+#define EDONKEY_MSG_UDP_CALLBACK_FAIL 0x9e
+/* #define EDONKEY_MSG_UDP_UNKNOWN 0xa0 */
+#define EDONKEY_MSG_UDP_SERVER_LIST 0xa1
+#define EDONKEY_MSG_UDP_GET_SERVER_INFO 0xa2
+#define EDONKEY_MSG_UDP_SERVER_INFO 0xa3
+#define EDONKEY_MSG_UDP_GET_SERVER_LIST 0xa4
+
+/* EMULE UDP EXTENSIONS */
+#define EMULE_MSG_UDP_REASKFILEPING 0x90
+#define EMULE_MSG_UDP_REASKACK 0x91
+#define EMULE_MSG_UDP_FILE_NOT_FOUND 0x92
+#define EMULE_MSG_UDP_QUEUE_FULL 0x93
+
+/* OVERNET UDP EXTENSIONS */
+#define OVERNET_MSG_UDP_CONNECT 0x0a
+#define OVERNET_MSG_UDP_CONNECT_REPLY 0x0b
+#define OVERNET_MSG_UDP_PUBLICIZE 0x0c
+#define OVERNET_MSG_UDP_PUBLICIZE_ACK 0x0d
+#define OVERNET_MSG_UDP_SEARCH 0x0e
+#define OVERNET_MSG_UDP_SEARCH_NEXT 0x0f
+#define OVERNET_MSG_UDP_SEARCH_INFO 0x10
+#define OVERNET_MSG_UDP_SEARCH_RESULT 0x11
+#define OVERNET_MSG_UDP_SEARCH_END 0x12
+#define OVERNET_MSG_UDP_PUBLISH 0x13
+#define OVERNET_MSG_UDP_PUBLISH_ACK 0x14
+#define OVERNET_MSG_UDP_IDENTIFY_REPLY 0x15
+#define OVERNET_MSG_UDP_IDENTIFY_ACK 0x16
+#define OVERNET_MSG_UDP_FIREWALL_CONNECTION 0x18
+#define OVERNET_MSG_UDP_FIREWALL_CONNECTION_ACK 0x19
+#define OVERNET_MSG_UDP_FIREWALL_CONNECTION_NACK 0x1a
+#define OVERNET_MSG_UDP_IP_QUERY 0x1b
+#define OVERNET_MSG_UDP_IP_QUERY_ANSWER 0x1c
+#define OVERNET_MSG_UDP_IP_QUERY_END 0x1d
+#define OVERNET_MSG_UDP_IDENTIFY 0x1e
+/*#define OVERNET_MSG_UDP_UNKNOWN 0x21 */
+
+/* EDONKEY META TAG TYPES */
+#define EDONKEY_MTAG_UNKNOWN 0x00
+#define EDONKEY_MTAG_HASH 0x01
+#define EDONKEY_MTAG_STRING 0x02
+#define EDONKEY_MTAG_DWORD 0x03
+#define EDONKEY_MTAG_FLOAT 0x04
+#define EDONKEY_MTAG_BOOL 0x05
+#define EDONKEY_MTAG_BOOL_ARRAY 0x06
+#define EDONKEY_MTAG_BLOB 0x07
+
+/* EDONKEY SPECIAL TAGS */
+#define EDONKEY_STAG_UNKNOWN 0x00
+#define EDONKEY_STAG_NAME 0x01
+#define EDONKEY_STAG_SIZE 0x02
+#define EDONKEY_STAG_TYPE 0x03
+#define EDONKEY_STAG_FORMAT 0x04
+#define EDONKEY_STAG_COLLECTION 0x05
+#define EDONKEY_STAG_PART_PATH 0x06
+#define EDONKEY_STAG_PART_HASH 0x07
+#define EDONKEY_STAG_COPIED 0x08
+#define EDONKEY_STAG_GAP_START 0x09
+#define EDONKEY_STAG_GAP_END 0x0a
+#define EDONKEY_STAG_DESCRIPTION 0x0b
+#define EDONKEY_STAG_PING 0x0c
+#define EDONKEY_STAG_FAIL 0x0d
+#define EDONKEY_STAG_PREFERENCE 0x0e
+#define EDONKEY_STAG_PORT 0x0f
+#define EDONKEY_STAG_IP 0x10
+#define EDONKEY_STAG_VERSION 0x11
+#define EDONKEY_STAG_TEMPFILE 0x12
+#define EDONKEY_STAG_PRIORITY 0x13
+#define EDONKEY_STAG_STATUS 0x14
+#define EDONKEY_STAG_AVAILABILITY 0x15
+#define EDONKEY_STAG_QTIME 0x16
+#define EDONKEY_STAG_PARTS 0x17
+
+/* EMULE SPECIAL TAGS */
+#define EMULE_STAG_COMPRESSION 0x20
+#define EMULE_STAG_UDP_CLIENT_PORT 0x21
+#define EMULE_STAG_UDP_VERSION 0x22
+#define EMULE_STAG_SOURCE_EXCHANGE 0x23
+#define EMULE_STAG_COMMENTS 0x24
+#define EMULE_STAG_EXTENDED_REQUEST 0x25
+#define EMULE_STAG_COMPATIBLE_CLIENT 0x26
+
+/* EDONKEY SEARCH TYPES */
+#define EDONKEY_SEARCH_BOOL 0x00
+#define EDONKEY_SEARCH_NAME 0x01
+#define EDONKEY_SEARCH_META 0x02
+#define EDONKEY_SEARCH_LIMIT 0x03
+
+/* EDONKEY SEARCH OPERATORS */
+#define EDONKEY_SEARCH_AND 0x00
+#define EDONKEY_SEARCH_OR 0x01
+#define EDONKEY_SEARCH_ANDNOT 0x02
+
+/* EDONKEY SEARCH MIN/MAX */
+#define EDONKEY_SEARCH_MIN 0x01
+#define EDONKEY_SEARCH_MAX 0x02
diff --git a/epan/dissectors/packet-eigrp.c b/epan/dissectors/packet-eigrp.c
new file mode 100644
index 0000000000..70138f71b2
--- /dev/null
+++ b/epan/dissectors/packet-eigrp.c
@@ -0,0 +1,509 @@
+/* packet-eigrp.c
+ * Routines for EIGRP dissection
+ * Copyright 2000, Paul Ionescu <paul@acorp.ro>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+
+#include <epan/atalk-utils.h>
+#include <epan/addr_and_mask.h>
+#include "ipproto.h"
+#include "packet-ipx.h"
+
+/*
+ * See
+ *
+ * http://www.rhyshaden.com/eigrp.htm
+ */
+
+#define EIGRP_UPDATE 0x01
+#define EIGRP_REQUEST 0x02
+#define EIGRP_QUERY 0x03
+#define EIGRP_REPLY 0x04
+#define EIGRP_HELLO 0x05
+#define EIGRP_SAP 0x06
+#define EIGRP_HI 0x20 /* This value is for my own need to make a difference between Hello and Ack */
+#define EIGRP_ACK 0x40 /* This value is for my own need to make a difference between Hello and Ack */
+
+#define TLV_PAR 0x0001
+#define TLV_AUTH 0x0002
+#define TLV_SEQ 0x0003
+#define TLV_SV 0x0004
+#define TLV_NMS 0x0005
+#define TLV_IP_INT 0x0102
+#define TLV_IP_EXT 0x0103
+#define TLV_AT_INT 0x0202
+#define TLV_AT_EXT 0x0203
+#define TLV_AT_CBL 0x0204
+#define TLV_IPX_INT 0x0302
+#define TLV_IPX_EXT 0x0303
+
+#define EIGRP_HEADER_LENGTH 20
+
+static gint proto_eigrp = -1;
+
+static gint hf_eigrp_opcode = -1;
+static gint hf_eigrp_as = -1;
+static gint hf_eigrp_tlv = -1;
+
+static gint ett_eigrp = -1;
+static gint ett_tlv = -1;
+
+static dissector_handle_t ipxsap_handle;
+
+
+static const value_string eigrp_opcode_vals[] = {
+ { EIGRP_HELLO, "Hello/Ack" },
+ { EIGRP_UPDATE, "Update" },
+ { EIGRP_REPLY, "Reply" },
+ { EIGRP_QUERY, "Query" },
+ { EIGRP_REQUEST, "Request" },
+ { EIGRP_SAP, "IPX/SAP Update" },
+ { EIGRP_HI, "Hello" },
+ { EIGRP_ACK, "Acknowledge" },
+ { 0, NULL }
+};
+
+static const value_string eigrp_tlv_vals[] = {
+ { TLV_PAR, "EIGRP Parameters"},
+ { TLV_AUTH, "Authentication data"},
+ { TLV_SEQ , "Sequence"},
+ { TLV_SV, "Software Version"},
+ { TLV_NMS , "Next multicast sequence"},
+ { TLV_IP_INT, "IP internal route"},
+ { TLV_IP_EXT, "IP external route"},
+ { TLV_AT_INT, "AppleTalk internal route"},
+ { TLV_AT_EXT, "AppleTalk external route"},
+ { TLV_AT_CBL, "AppleTalk cable configuration"},
+ { TLV_IPX_INT, "IPX internal route"},
+ { TLV_IPX_EXT, "IPX external route"},
+ { 0, NULL}
+};
+
+static const value_string eigrp_pid_vals[] = {
+ { 1, "IGRP"},
+ { 2, "EIGRP"},
+ { 3, "Static Route"},
+ { 4, "RIP"},
+ { 5, "Hello"},
+ { 6, "OSPF"},
+ { 7, "IS-IS"},
+ { 8, "EGP"},
+ { 9, "BGP"},
+ { 10, "IDRP"},
+ { 11, "Connected link"},
+ { 0, NULL}
+};
+
+
+static void dissect_eigrp_par (tvbuff_t *tvb, proto_tree *tree);
+static void dissect_eigrp_seq (tvbuff_t *tvb, proto_tree *tree);
+static void dissect_eigrp_sv (tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
+static void dissect_eigrp_nms (tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
+
+static void dissect_eigrp_ip_int (tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
+static void dissect_eigrp_ip_ext (tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
+
+static void dissect_eigrp_ipx_int (tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
+static void dissect_eigrp_ipx_ext (tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
+
+static void dissect_eigrp_at_cbl (tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
+static void dissect_eigrp_at_int (tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
+static void dissect_eigrp_at_ext (tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
+
+static void
+dissect_eigrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+
+ proto_tree *eigrp_tree,*tlv_tree;
+ proto_item *ti;
+
+ guint opcode,opcode_tmp;
+ guint16 tlv,size, offset = EIGRP_HEADER_LENGTH;
+ guint32 ack;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "EIGRP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ opcode_tmp=opcode=tvb_get_guint8(tvb,1);
+ ack = tvb_get_ntohl(tvb,12);
+ if (opcode==EIGRP_HELLO) { if (ack == 0) opcode_tmp=EIGRP_HI; else opcode_tmp=EIGRP_ACK; }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(opcode_tmp , eigrp_opcode_vals, "Unknown (0x%04x)"));
+
+
+
+
+ if (tree) {
+
+ ti = proto_tree_add_protocol_format(tree, proto_eigrp, tvb, 0, -1,
+ "Cisco EIGRP");
+
+ eigrp_tree = proto_item_add_subtree(ti, ett_eigrp);
+
+ proto_tree_add_text (eigrp_tree, tvb, 0,1,"Version = %u",tvb_get_guint8(tvb,0)) ;
+ proto_tree_add_uint_format (eigrp_tree, hf_eigrp_opcode, tvb, 1,1,opcode,"Opcode = %u (%s)",opcode,val_to_str(opcode_tmp,eigrp_opcode_vals, "Unknown")) ;
+ proto_tree_add_text (eigrp_tree, tvb, 2,2,"Checksum = 0x%04x",tvb_get_ntohs(tvb,2)) ;
+ proto_tree_add_text (eigrp_tree, tvb, 4,4,"Flags = 0x%08x",tvb_get_ntohl(tvb,4)) ;
+ proto_tree_add_text (eigrp_tree, tvb, 8,4,"Sequence = %u",tvb_get_ntohl(tvb,8)) ;
+ proto_tree_add_text (eigrp_tree, tvb, 12,4,"Acknowledge = %u",tvb_get_ntohl(tvb,12)) ;
+ proto_tree_add_uint (eigrp_tree, hf_eigrp_as, tvb, 16,4,tvb_get_ntohl(tvb,16)) ;
+
+ if (opcode==EIGRP_SAP)
+ {
+ call_dissector(ipxsap_handle, tvb_new_subset(tvb, EIGRP_HEADER_LENGTH, -1, -1), pinfo, eigrp_tree);
+ return;
+ }
+
+ while ( tvb_reported_length_remaining(tvb,offset)>0 ) {
+
+ tlv = tvb_get_ntohs(tvb,offset);
+ size = tvb_get_ntohs(tvb,offset+2);
+ if ( size == 0 )
+ {
+ proto_tree_add_text(eigrp_tree,tvb,offset,-1,"Unknown data (maybe authentication)");
+ return;
+ }
+
+ ti = proto_tree_add_text (eigrp_tree, tvb, offset,size,
+ "%s",val_to_str(tlv, eigrp_tlv_vals, "Unknown (0x%04x)"));
+
+ tlv_tree = proto_item_add_subtree (ti, ett_tlv);
+ proto_tree_add_uint_format (tlv_tree,hf_eigrp_tlv, tvb,offset,2,tlv,"Type = 0x%04x (%s)",tlv,val_to_str(tlv,eigrp_tlv_vals, "Unknown")) ;
+ proto_tree_add_text (tlv_tree,tvb,offset+2,2,"Size = %u bytes",size) ;
+
+
+ switch (tlv){
+ case TLV_PAR:
+ dissect_eigrp_par(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree);
+ break;
+ case TLV_SEQ:
+ dissect_eigrp_seq(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree);
+ break;
+ case TLV_SV:
+ dissect_eigrp_sv(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree, ti);
+ break;
+ case TLV_NMS:
+ dissect_eigrp_nms(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree, ti);
+ break;
+
+ case TLV_IP_INT:
+ dissect_eigrp_ip_int(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree, ti);
+ break;
+ case TLV_IP_EXT:
+ dissect_eigrp_ip_ext(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree, ti);
+ break;
+
+ case TLV_IPX_INT:
+ dissect_eigrp_ipx_int(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree, ti);
+ break;
+ case TLV_IPX_EXT:
+ dissect_eigrp_ipx_ext(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree, ti);
+ break;
+
+ case TLV_AT_CBL:
+ dissect_eigrp_at_cbl(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree, ti);
+ break;
+ case TLV_AT_INT:
+ dissect_eigrp_at_int(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree, ti);
+ break;
+ case TLV_AT_EXT:
+ dissect_eigrp_at_ext(tvb_new_subset(tvb, offset+4, size-4, -1), tlv_tree, ti);
+ break;
+ case TLV_AUTH:
+ proto_tree_add_text(tlv_tree,tvb,offset+4,size-4,"Authentication data");
+ break;
+ }
+
+ offset+=size;
+ }
+
+ }
+}
+
+
+
+static void dissect_eigrp_par (tvbuff_t *tvb, proto_tree *tree) {
+ proto_tree_add_text (tree,tvb,0,1,"K1 = %u",tvb_get_guint8(tvb,0));
+ proto_tree_add_text (tree,tvb,1,1,"K2 = %u",tvb_get_guint8(tvb,1));
+ proto_tree_add_text (tree,tvb,2,1,"K3 = %u",tvb_get_guint8(tvb,2));
+ proto_tree_add_text (tree,tvb,3,1,"K4 = %u",tvb_get_guint8(tvb,3));
+ proto_tree_add_text (tree,tvb,4,1,"K5 = %u",tvb_get_guint8(tvb,4));
+ proto_tree_add_text (tree,tvb,5,1,"Reserved");
+ proto_tree_add_text (tree,tvb,6,2,"Hold Time = %u",tvb_get_ntohs(tvb,6));
+}
+
+static void dissect_eigrp_seq (tvbuff_t *tvb, proto_tree *tree)
+{ guint8 addr_len;
+ addr_len=tvb_get_guint8(tvb,0);
+ proto_tree_add_text (tree,tvb,0,1,"Address length = %u",addr_len);
+ switch (addr_len){
+ case 4:
+ proto_tree_add_text (tree,tvb,1,addr_len,"IP Address = %u.%u.%u.%u",tvb_get_guint8(tvb,1),tvb_get_guint8(tvb,2),tvb_get_guint8(tvb,3),tvb_get_guint8(tvb,4));
+ break;
+ case 10:
+ proto_tree_add_text (tree,tvb,1,addr_len,"IPX Address = %08x.%04x.%04x.%04x",tvb_get_ntohl(tvb,1),tvb_get_ntohs(tvb,5),tvb_get_ntohs(tvb,7),tvb_get_ntohs(tvb,9));
+ break;
+ default:
+ /* nothing */
+ ;
+ }
+}
+
+static void dissect_eigrp_sv (tvbuff_t *tvb, proto_tree *tree, proto_item *ti)
+{
+ guint8 ios_rel_major, ios_rel_minor;
+ guint8 eigrp_rel_major, eigrp_rel_minor;
+
+ ios_rel_major = tvb_get_guint8(tvb,0);
+ ios_rel_minor = tvb_get_guint8(tvb,1);
+ proto_tree_add_text (tree,tvb,0,2," IOS release version = %u.%u",
+ ios_rel_major, ios_rel_minor);
+ proto_item_append_text (ti,": IOS=%u.%u", ios_rel_major, ios_rel_minor);
+
+ eigrp_rel_major = tvb_get_guint8(tvb,2);
+ eigrp_rel_minor = tvb_get_guint8(tvb,3);
+ proto_tree_add_text (tree,tvb,2,2,"EIGRP release version = %u.%u",
+ eigrp_rel_major, eigrp_rel_minor);
+ proto_item_append_text (ti,", EIGRP=%u.%u",
+ eigrp_rel_major, eigrp_rel_minor);
+}
+
+static void dissect_eigrp_nms (tvbuff_t *tvb, proto_tree *tree, proto_item *ti)
+{
+ proto_tree_add_text (tree,tvb,0,4,"Next Multicast Sequence = %u",tvb_get_ntohl(tvb,0));
+ proto_item_append_text (ti,": %u",tvb_get_ntohl(tvb,0));
+}
+
+
+
+static void dissect_eigrp_ip_int (tvbuff_t *tvb, proto_tree *tree, proto_item *ti)
+{
+ guint8 ip_addr[4],length;
+ int addr_len;
+
+ tvb_memcpy(tvb,ip_addr,0,4);
+ proto_tree_add_text (tree,tvb,0,4, "Next Hop = %s",ip_to_str(ip_addr));
+ proto_tree_add_text (tree,tvb,4,4, "Delay = %u",tvb_get_ntohl(tvb,4));
+ proto_tree_add_text (tree,tvb,8,4, "Bandwidth = %u",tvb_get_ntohl(tvb,8));
+ proto_tree_add_text (tree,tvb,12,3,"MTU = %u",tvb_get_ntoh24(tvb,12));
+ proto_tree_add_text (tree,tvb,15,1,"Hop Count = %u",tvb_get_guint8(tvb,15));
+ proto_tree_add_text (tree,tvb,16,1,"Reliability = %u",tvb_get_guint8(tvb,16));
+ proto_tree_add_text (tree,tvb,17,1,"Load = %u",tvb_get_guint8(tvb,17));
+ proto_tree_add_text (tree,tvb,18,2,"Reserved ");
+ length=tvb_get_guint8(tvb,20);
+ /* XXX - the EIGRP page whose URL appears at the top says this
+ field is 24 bits; what if the prefix length is > 24? */
+ addr_len=ipv4_addr_and_mask (tvb,21,ip_addr,length);
+ if (addr_len < 0) {
+ proto_tree_add_text (tree,tvb,20,1,"Prefix length = %u (invalid, must be <= 32)",length);
+ proto_item_append_text (ti," [Invalid prefix length %u > 32]",length);
+ } else {
+ proto_tree_add_text (tree,tvb,20,1,"Prefix Length = %u",length);
+ proto_tree_add_text (tree,tvb,21,addr_len,"Destination = %s",ip_to_str(ip_addr));
+ proto_item_append_text (ti," = %s/%u%s",ip_to_str(ip_addr),length,((tvb_get_ntohl(tvb,4)==0xffffffff)?" - Destination unreachable":""));
+ }
+}
+
+static void dissect_eigrp_ip_ext (tvbuff_t *tvb, proto_tree *tree, proto_item *ti)
+{
+ guint8 ip_addr[4],length;
+ int addr_len;
+
+ tvb_memcpy(tvb,ip_addr,0,4);
+ proto_tree_add_text (tree,tvb,0,4,"Next Hop = %s",ip_to_str(ip_addr));
+ tvb_memcpy(tvb,ip_addr,4,4);
+ proto_tree_add_text (tree,tvb,4,4,"Originating router = %s",ip_to_str(ip_addr));
+ proto_tree_add_text (tree,tvb,8,4,"Originating A.S. = %u",tvb_get_ntohl(tvb,8));
+ proto_tree_add_text (tree,tvb,12,4,"Arbitrary tag = %u",tvb_get_ntohl(tvb,12));
+ proto_tree_add_text (tree,tvb,16,4,"External protocol metric = %u",tvb_get_ntohl(tvb,16));
+ proto_tree_add_text (tree,tvb,20,2,"Reserved");
+ proto_tree_add_text (tree,tvb,22,1,"External protocol ID = %u (%s)",tvb_get_guint8(tvb,22),val_to_str(tvb_get_guint8(tvb,22),eigrp_pid_vals, "Unknown"));
+ proto_tree_add_text (tree,tvb,23,1,"Flags = 0x%0x",tvb_get_guint8(tvb,23));
+
+ proto_tree_add_text (tree,tvb,24,4,"Delay = %u",tvb_get_ntohl(tvb,24));
+ proto_tree_add_text (tree,tvb,28,4,"Bandwidth = %u",tvb_get_ntohl(tvb,28));
+ proto_tree_add_text (tree,tvb,32,3,"MTU = %u",tvb_get_ntoh24(tvb,32));
+ proto_tree_add_text (tree,tvb,35,1,"Hop Count = %u",tvb_get_guint8(tvb,35));
+ proto_tree_add_text (tree,tvb,36,1,"Reliability = %u",tvb_get_guint8(tvb,36));
+ proto_tree_add_text (tree,tvb,37,1,"Load = %u",tvb_get_guint8(tvb,37));
+ proto_tree_add_text (tree,tvb,38,2,"Reserved ");
+ length=tvb_get_guint8(tvb,40);
+ /* XXX - the EIGRP page whose URL appears at the top says this
+ field is 24 bits; what if the prefix length is > 24? */
+ addr_len=ipv4_addr_and_mask (tvb,41,ip_addr,length);
+ if (addr_len < 0) {
+ proto_tree_add_text (tree,tvb,40,1,"Prefix length = %u (invalid, must be <= 32)",length);
+ proto_item_append_text (ti," [Invalid prefix length %u > 32]",length);
+ } else {
+ proto_tree_add_text (tree,tvb,40,1,"Prefix Length = %u",length);
+ proto_tree_add_text (tree,tvb,41,addr_len,"Destination = %s",ip_to_str(ip_addr));
+ proto_item_append_text (ti," = %s/%u%s",ip_to_str(ip_addr),length,((tvb_get_ntohl(tvb,4)==0xffffffff)?" - Destination unreachable":""));
+ }
+}
+
+
+
+static void dissect_eigrp_ipx_int (tvbuff_t *tvb, proto_tree *tree, proto_item *ti)
+{
+ proto_tree_add_text (tree,tvb,0,4,"Next Hop Address = %08x",tvb_get_ntohl(tvb,4));
+ proto_tree_add_text (tree,tvb,4,6,"Next Hop ID = %04x:%04x:%04x",tvb_get_ntohs(tvb,4),tvb_get_ntohs(tvb,6),tvb_get_ntohs(tvb,8));
+ proto_tree_add_text (tree,tvb,10,4,"Delay = %u",tvb_get_ntohl(tvb,10));
+ proto_tree_add_text (tree,tvb,14,4,"Bandwidth = %u",tvb_get_ntohl(tvb,14));
+ proto_tree_add_text (tree,tvb,18,3,"MTU = %u",tvb_get_ntoh24(tvb,18));
+ proto_tree_add_text (tree,tvb,21,1,"Hop Count = %u",tvb_get_guint8(tvb,21));
+ proto_tree_add_text (tree,tvb,22,1,"Reliability = %u",tvb_get_guint8(tvb,22));
+ proto_tree_add_text (tree,tvb,23,1,"Load = %u",tvb_get_guint8(tvb,23));
+ proto_tree_add_text (tree,tvb,24,2,"Reserved ");
+ proto_tree_add_text (tree,tvb,26,4,"Destination Address = %08x",tvb_get_ntohl(tvb,26));
+ proto_item_append_text (ti," = %08x%s",tvb_get_ntohl(tvb,26),((tvb_get_ntohl(tvb,10)==0xffffffff)?" - Destination unreachable":""));
+}
+
+static void dissect_eigrp_ipx_ext (tvbuff_t *tvb, proto_tree *tree, proto_item *ti)
+{
+ proto_tree_add_text (tree,tvb,0,4,"Next Hop Address = %08x",tvb_get_ntohl(tvb,4));
+ proto_tree_add_text (tree,tvb,4,6,"Next Hop ID = %04x:%04x:%04x",tvb_get_ntohs(tvb,4),tvb_get_ntohs(tvb,6),tvb_get_ntohs(tvb,8));
+
+ proto_tree_add_text (tree,tvb,10,6,"Originating router ID = %04x:%04x:%04x",tvb_get_ntohs(tvb,10),tvb_get_ntohs(tvb,12),tvb_get_ntohs(tvb,14));
+ proto_tree_add_text (tree,tvb,16,4,"Originating A.S. = %u",tvb_get_ntohl(tvb,16));
+ proto_tree_add_text (tree,tvb,20,4,"Arbitrary tag = %u",tvb_get_ntohl(tvb,20));
+ proto_tree_add_text (tree,tvb,24,1,"External protocol = %u",tvb_get_guint8(tvb,24));
+ proto_tree_add_text (tree,tvb,25,1,"Reserved");
+ proto_tree_add_text (tree,tvb,26,2,"External metric = %u ",tvb_get_ntohs(tvb,26));
+ proto_tree_add_text (tree,tvb,28,2,"External delay = %u ",tvb_get_ntohs(tvb,28));
+
+ proto_tree_add_text (tree,tvb,30,4,"Delay = %u",tvb_get_ntohl(tvb,30));
+ proto_tree_add_text (tree,tvb,34,4,"Bandwidth = %u",tvb_get_ntohl(tvb,34));
+ proto_tree_add_text (tree,tvb,38,3,"MTU = %u",tvb_get_ntoh24(tvb,38));
+ proto_tree_add_text (tree,tvb,41,1,"Hop Count = %u",tvb_get_guint8(tvb,41));
+ proto_tree_add_text (tree,tvb,42,1,"Reliability = %u",tvb_get_guint8(tvb,42));
+ proto_tree_add_text (tree,tvb,43,1,"Load = %u",tvb_get_guint8(tvb,43));
+ proto_tree_add_text (tree,tvb,44,2,"Reserved ");
+ proto_tree_add_text (tree,tvb,46,4,"Destination Address = %08x",tvb_get_ntohl(tvb,46));
+ proto_item_append_text (ti," = %08x%s",tvb_get_ntohl(tvb,46),((tvb_get_ntohl(tvb,30)==0xffffffff)?" - Destination unreachable":""));
+
+}
+
+
+
+static void dissect_eigrp_at_cbl (tvbuff_t *tvb, proto_tree *tree, proto_item *ti)
+{
+ proto_tree_add_text (tree,tvb,0,4,"AppleTalk Cable Range = %u-%u",tvb_get_ntohs(tvb,0),tvb_get_ntohs(tvb,2));
+ proto_tree_add_text (tree,tvb,4,4,"AppleTalk Router ID = %u",tvb_get_ntohl(tvb,4));
+ proto_item_append_text (ti,": Cable range= %u-%u, Router ID= %u",tvb_get_ntohs(tvb,0),tvb_get_ntohs(tvb,2),tvb_get_ntohl(tvb,4));
+
+}
+
+static void dissect_eigrp_at_int (tvbuff_t *tvb, proto_tree *tree, proto_item *ti)
+{
+ proto_tree_add_text (tree,tvb,0,4,"Next Hop Address = %u.%u",tvb_get_ntohs(tvb,0),tvb_get_ntohs(tvb,2));
+
+ proto_tree_add_text (tree,tvb,4,4,"Delay = %u",tvb_get_ntohl(tvb,4));
+ proto_tree_add_text (tree,tvb,8,4,"Bandwidth = %u",tvb_get_ntohl(tvb,8));
+ proto_tree_add_text (tree,tvb,12,3,"MTU = %u",tvb_get_ntoh24(tvb,12));
+ proto_tree_add_text (tree,tvb,15,1,"Hop Count = %u",tvb_get_guint8(tvb,15));
+ proto_tree_add_text (tree,tvb,16,1,"Reliability = %u",tvb_get_guint8(tvb,16));
+ proto_tree_add_text (tree,tvb,17,1,"Load = %u",tvb_get_guint8(tvb,17));
+ proto_tree_add_text (tree,tvb,18,2,"Reserved ");
+ proto_tree_add_text (tree,tvb,20,4,"Cable range = %u-%u",tvb_get_ntohs(tvb,20),tvb_get_ntohs(tvb,22));
+
+ proto_item_append_text (ti,": %u-%u",tvb_get_ntohs(tvb,20),tvb_get_ntohs(tvb,22));
+
+}
+
+static void dissect_eigrp_at_ext (tvbuff_t *tvb, proto_tree *tree, proto_item *ti)
+{
+ proto_tree_add_text (tree,tvb,0,4,"Next Hop Address = %u.%u",tvb_get_ntohs(tvb,0),tvb_get_ntohs(tvb,2));
+ proto_tree_add_text (tree,tvb,4,4,"Originating router ID = %u",tvb_get_ntohl(tvb,4));
+ proto_tree_add_text (tree,tvb,8,4,"Originating A.S. = %u",tvb_get_ntohl(tvb,8));
+ proto_tree_add_text (tree,tvb,12,4,"Arbitrary tag = %u",tvb_get_ntohl(tvb,12));
+ proto_tree_add_text (tree,tvb,16,1,"External protocol ID = %u ",tvb_get_guint8(tvb,16));
+ proto_tree_add_text (tree,tvb,17,1,"Flags = 0x%0x",tvb_get_guint8(tvb,17));
+ proto_tree_add_text (tree,tvb,18,2,"External protocol metric = %u",tvb_get_ntohs(tvb,18));
+
+ proto_tree_add_text (tree,tvb,20,4,"Delay = %u",tvb_get_ntohl(tvb,20));
+ proto_tree_add_text (tree,tvb,24,4,"Bandwidth = %u",tvb_get_ntohl(tvb,24));
+ proto_tree_add_text (tree,tvb,28,3,"MTU = %u",tvb_get_ntoh24(tvb,28));
+ proto_tree_add_text (tree,tvb,31,1,"Hop Count = %u",tvb_get_guint8(tvb,31));
+ proto_tree_add_text (tree,tvb,32,1,"Reliability = %u",tvb_get_guint8(tvb,32));
+ proto_tree_add_text (tree,tvb,33,1,"Load = %u",tvb_get_guint8(tvb,33));
+ proto_tree_add_text (tree,tvb,34,2,"Reserved ");
+ proto_tree_add_text (tree,tvb,36,4,"Cable range = %u-%u",tvb_get_ntohs(tvb,36),tvb_get_ntohs(tvb,38));
+
+ proto_item_append_text (ti,": %u-%u",tvb_get_ntohs(tvb,36),tvb_get_ntohs(tvb,38));
+}
+
+
+
+
+void
+proto_register_eigrp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_eigrp_opcode,
+ { "Opcode", "eigrp.opcode",
+ FT_UINT8, BASE_DEC, NULL, 0x0 ,
+ "Opcode number", HFILL }
+ },
+ { &hf_eigrp_as,
+ { "Autonomous System ", "eigrp.as",
+ FT_UINT16, BASE_DEC, NULL, 0x0 ,
+ "Autonomous System number", HFILL }
+ },
+ { &hf_eigrp_tlv,
+ { "Entry ", "eigrp.tlv",
+ FT_UINT16, BASE_DEC, NULL, 0x0 ,
+ "Type/Length/Value", HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_eigrp,
+ &ett_tlv,
+ };
+ proto_eigrp = proto_register_protocol("Enhanced Interior Gateway Routing Protocol",
+ "EIGRP", "eigrp");
+ proto_register_field_array(proto_eigrp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_eigrp(void)
+{
+ dissector_handle_t eigrp_handle;
+
+ ipxsap_handle = find_dissector("ipxsap");
+ eigrp_handle = create_dissector_handle(dissect_eigrp, proto_eigrp);
+ dissector_add("ip.proto", IP_PROTO_EIGRP, eigrp_handle);
+ dissector_add("ddp.type", DDP_EIGRP, eigrp_handle);
+ dissector_add("ipx.socket", IPX_SOCKET_EIGRP, eigrp_handle);
+}
diff --git a/epan/dissectors/packet-enc.c b/epan/dissectors/packet-enc.c
new file mode 100644
index 0000000000..e061f454a0
--- /dev/null
+++ b/epan/dissectors/packet-enc.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2003 Markus Friedl. All rights reserved.
+ *
+ * $Id$
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "etypes.h"
+#include <epan/resolv.h>
+#include "packet-ip.h"
+#include "packet-ipv6.h"
+
+#ifndef offsetof
+/* Can't trust stddef.h to be there for us */
+# define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+/* The header in OpenBSD Encapsulating Interface files. */
+
+struct enchdr {
+ guint32 af;
+ guint32 spi;
+ guint32 flags;
+};
+#define ENC_HDRLEN sizeof(struct enchdr)
+
+# define BSD_ENC_INET 2
+# define BSD_ENC_INET6 24
+
+# define BSD_ENC_M_CONF 0x0400 /* payload encrypted */
+# define BSD_ENC_M_AUTH 0x0800 /* payload authenticated */
+# define BSD_ENC_M_COMP 0x1000 /* payload compressed */
+# define BSD_ENC_M_AUTH_AH 0x2000 /* header authenticated */
+
+static dissector_handle_t data_handle, ip_handle, ipv6_handle;
+
+/* header fields */
+static unsigned int proto_enc = -1;
+static unsigned int hf_enc_af = -1;
+static unsigned int hf_enc_spi = -1;
+static unsigned int hf_enc_flags = -1;
+
+static gint ett_enc = -1;
+
+void
+capture_enc(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ struct enchdr ench;
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, (int)ENC_HDRLEN)) {
+ ld->other++;
+ return;
+ }
+
+ offset += ENC_HDRLEN;
+
+ /* Copy out the enc header to insure alignment */
+ memcpy(&ench, pd, sizeof(ench));
+ ench.af = g_ntohl(ench.af);
+
+ switch (ench.af) {
+
+ case BSD_ENC_INET:
+ capture_ip(pd, offset, len, ld);
+ break;
+
+#ifdef notyet
+ case BSD_ENC_INET6:
+ capture_ipv6(pd, offset, len, ld);
+ break;
+#endif
+
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+static const value_string af_vals[] = {
+ { BSD_ENC_INET, "IPv4" },
+ { BSD_ENC_INET6, "IPv6" },
+ { 0, NULL }
+};
+
+static void
+dissect_enc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct enchdr ench;
+ tvbuff_t *next_tvb;
+ proto_tree *enc_tree;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ENC");
+
+ /* Copy out the enc header to insure alignment */
+ tvb_memcpy(tvb, (guint8 *)&ench, 0, sizeof(ench));
+
+ /* Byteswap the header now */
+ ench.spi = g_ntohl(ench.spi);
+ /* ench.af = g_ntohl(ench.af); */
+ /* ench.flags = g_ntohl(ench.flags); */
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_enc, tvb, 0,
+ ENC_HDRLEN,
+ "Enc %s, SPI 0x%8.8x, %s%s%s%s",
+ val_to_str(ench.af, af_vals, "unknown (%u)"),
+ ench.spi,
+ ench.flags ? "" : "unprotected",
+ ench.flags & BSD_ENC_M_AUTH ? "authentic" : "",
+ (ench.flags & (BSD_ENC_M_AUTH|BSD_ENC_M_CONF)) ==
+ (BSD_ENC_M_AUTH|BSD_ENC_M_CONF) ? ", " : "",
+ ench.flags & BSD_ENC_M_CONF ? "confidential" : ""
+ );
+ enc_tree = proto_item_add_subtree(ti, ett_enc);
+
+ proto_tree_add_uint(enc_tree, hf_enc_af, tvb,
+ offsetof(struct enchdr, af), sizeof(ench.af),
+ ench.af);
+ proto_tree_add_uint(enc_tree, hf_enc_spi, tvb,
+ offsetof(struct enchdr, spi), sizeof(ench.spi),
+ ench.spi);
+ proto_tree_add_uint(enc_tree, hf_enc_flags, tvb,
+ offsetof(struct enchdr, flags), sizeof(ench.flags),
+ ench.flags);
+ }
+
+ /* Set the tvbuff for the payload after the header */
+ next_tvb = tvb_new_subset(tvb, ENC_HDRLEN, -1, -1);
+
+ switch (ench.af) {
+
+ case BSD_ENC_INET:
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+ break;
+
+ case BSD_ENC_INET6:
+ call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ break;
+ }
+}
+
+void
+proto_register_enc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_enc_af,
+ { "Address Family", "enc.af", FT_UINT32, BASE_DEC, VALS(af_vals), 0x0,
+ "Protocol (IPv4 vs IPv6)", HFILL }},
+ { &hf_enc_spi,
+ { "SPI", "enc.spi", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Security Parameter Index", HFILL }},
+ { &hf_enc_flags,
+ { "Flags", "enc.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "ENC flags", HFILL }},
+ };
+ static gint *ett[] = { &ett_enc };
+
+ proto_enc = proto_register_protocol("OpenBSD Encapsulating device",
+ "ENC", "enc");
+ proto_register_field_array(proto_enc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_enc(void)
+{
+ dissector_handle_t enc_handle;
+
+ ip_handle = find_dissector("ip");
+ ipv6_handle = find_dissector("ipv6");
+ data_handle = find_dissector("data");
+
+ enc_handle = create_dissector_handle(dissect_enc, proto_enc);
+ dissector_add("wtap_encap", WTAP_ENCAP_ENC, enc_handle);
+}
diff --git a/epan/dissectors/packet-enip.c b/epan/dissectors/packet-enip.c
new file mode 100644
index 0000000000..0ceb080ca5
--- /dev/null
+++ b/epan/dissectors/packet-enip.c
@@ -0,0 +1,2678 @@
+/* packet-enip.c
+ * Routines for EtherNet/IP (Industrial Protocol) dissection
+ * EtherNet/IP Home: www.odva.org
+ *
+ * Copyright 2003-2004
+ * Magnus Hansson <mah@hms.se>
+ * Joakim Wiberg <jow@hms.se>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <prefs.h>
+#include "packet-tcp.h"
+
+/* Defines */
+#define ENIP_ENCAP_PORT 44818 /* EtherNet/IP located on port 44818 */
+#define ENIP_IO_PORT 2222 /* EtherNet/IP IO located on port 2222 */
+
+/* return codes of function classifying packets as query/response */
+#define REQUEST_PACKET 0
+#define RESPONSE_PACKET 1
+#define CANNOT_CLASSIFY 2
+
+/* CIP Encapsulation function codes */
+#define NOP 0x0000
+#define LIST_SERVICES 0x0004
+#define LIST_IDENTITY 0x0063
+#define LIST_INTERFACES 0x0064
+#define REGISTER_SESSION 0x0065
+#define UNREGISTER_SESSION 0x0066
+#define SEND_RR_DATA 0x006F
+#define SEND_UNIT_DATA 0x0070
+#define INDICATE_STATUS 0x0072
+#define CANCEL 0x0073
+
+/* CIP Encapsulation status codes */
+#define SUCCESS 0x0000
+#define INVALID_CMD 0x0001
+#define NO_RESOURCES 0x0002
+#define INCORRECT_DATA 0x0003
+#define INVALID_SESSION 0x0064
+#define INVALID_LENGTH 0x0065
+#define UNSUPPORTED_PROT_REV 0x0069
+
+/* CIP Common Data Format Type IDs */
+#define CDF_NULL 0x0000
+#define LIST_IDENTITY_RESP 0x000C
+#define CONNECTION_BASED 0x00A1
+#define CONNECTION_TRANSPORT 0x00B1
+#define UNCONNECTED_MSG 0x00B2
+#define LIST_SERVICES_RESP 0x0100
+#define SOCK_ADR_INFO_OT 0x8000
+#define SOCK_ADR_INFO_TO 0x8001
+#define SEQ_ADDRESS 0x8002
+
+/* CIP Service Codes */
+#define SC_GET_ATT_ALL 0x01
+#define SC_SET_ATT_ALL 0x02
+#define SC_GET_ATT_LIST 0x03
+#define SC_SET_ATT_LIST 0x04
+#define SC_RESET 0x05
+#define SC_START 0x06
+#define SC_STOP 0x07
+#define SC_CREATE 0x08
+#define SC_DELETE 0x09
+#define SC_MULT_SERV_PACK 0x0A
+#define SC_APPLY_ATTRIBUTES 0x0D
+#define SC_GET_ATT_SINGLE 0x0E
+#define SC_SET_ATT_SINGLE 0x10
+#define SC_FIND_NEXT_OBJ_INST 0x11
+#define SC_RESTOR 0x15
+#define SC_SAVE 0x16
+#define SC_NO_OP 0x17
+#define SC_GET_MEMBER 0x18
+#define SC_SET_MEMBER 0x19
+
+#define SC_FWD_CLOSE 0x4E
+#define SC_UNCON_SEND 0x52
+#define SC_FWD_OPEN 0x54
+
+
+
+/* CIP Genral status codes */
+#define CI_GRC_SUCCESS 0x00
+#define CI_GRC_FAILURE 0x01
+#define CI_GRC_NO_RESOURCE 0x02
+#define CI_GRC_BAD_DATA 0x03
+#define CI_GRC_BAD_PATH 0x04
+#define CI_GRC_BAD_CLASS_INSTANCE 0x05
+#define CI_GRC_PARTIAL_DATA 0x06
+#define CI_GRC_CONN_LOST 0x07
+#define CI_GRC_BAD_SERVICE 0x08
+#define CI_GRC_BAD_ATTR_DATA 0x09
+#define CI_GRC_ATTR_LIST_ERROR 0x0A
+#define CI_GRC_ALREADY_IN_MODE 0x0B
+#define CI_GRC_BAD_OBJ_MODE 0x0C
+#define CI_GRC_OBJ_ALREADY_EXISTS 0x0D
+#define CI_GRC_ATTR_NOT_SETTABLE 0x0E
+#define CI_GRC_PERMISSION_DENIED 0x0F
+#define CI_GRC_DEV_IN_WRONG_STATE 0x10
+#define CI_GRC_REPLY_DATA_TOO_LARGE 0x11
+#define CI_GRC_FRAGMENT_PRIMITIVE 0x12
+#define CI_GRC_CONFIG_TOO_SMALL 0x13
+#define CI_GRC_UNDEFINED_ATTR 0x14
+#define CI_GRC_CONFIG_TOO_BIG 0x15
+#define CI_GRC_OBJ_DOES_NOT_EXIST 0x16
+#define CI_GRC_NO_FRAGMENTATION 0x17
+#define CI_GRC_DATA_NOT_SAVED 0x18
+#define CI_GRC_DATA_WRITE_FAILURE 0x19
+#define CI_GRC_REQUEST_TOO_LARGE 0x1A
+#define CI_GRC_RESPONSE_TOO_LARGE 0x1B
+#define CI_GRC_MISSING_LIST_DATA 0x1C
+#define CI_GRC_INVALID_LIST_STATUS 0x1D
+#define CI_GRC_SERVICE_ERROR 0x1E
+#define CI_GRC_CONN_RELATED_FAILURE 0x1F
+#define CI_GRC_INVALID_PARAMETER 0x20
+#define CI_GRC_WRITE_ONCE_FAILURE 0x21
+#define CI_GRC_INVALID_REPLY 0x22
+#define CI_GRC_BAD_KEY_IN_PATH 0x25
+#define CI_GRC_BAD_PATH_SIZE 0x26
+#define CI_GRC_UNEXPECTED_ATTR 0x27
+#define CI_GRC_INVALID_MEMBER 0x28
+#define CI_GRC_MEMBER_NOT_SETTABLE 0x29
+
+#define CI_GRC_STILL_PROCESSING 0xFF
+
+
+/* IOI Path types */
+#define CI_SEGMENT_TYPE_MASK 0xE0
+
+#define CI_PATH_SEGMENT 0x00
+#define CI_LOGICAL_SEGMENT 0x20
+#define CI_NETWORK_SEGMENT 0x40
+#define CI_SYMBOLIC_SEGMENT 0x60
+#define CI_DATA_SEGMENT 0x80
+
+#define CI_LOGICAL_SEG_TYPE_MASK 0x1C
+#define CI_LOGICAL_SEG_CLASS_ID 0x00
+#define CI_LOGICAL_SEG_INST_ID 0x04
+#define CI_LOGICAL_SEG_MBR_ID 0x08
+#define CI_LOGICAL_SEG_CON_POINT 0x0C
+#define CI_LOGICAL_SEG_ATTR_ID 0x10
+#define CI_LOGICAL_SEG_SPECIAL 0x14
+#define CI_LOGICAL_SEG_SERV_ID 0x18
+#define CI_LOGICAL_SEG_RES_1 0x1C
+
+#define CI_LOGICAL_SEG_FORMAT_MASK 0x03
+#define CI_LOGICAL_SEG_8_BIT 0x00
+#define CI_LOGICAL_SEG_16_BIT 0x01
+#define CI_LOGICAL_SEG_32_BIT 0x02
+#define CI_LOGICAL_SEG_RES_2 0x03
+#define CI_LOGICAL_SEG_E_KEY 0x00
+
+#define CI_E_KEY_FORMAT_VAL 0x04
+
+#define CI_DATA_SEG_SIMPLE 0x80
+#define CI_DATA_SEG_SYMBOL 0x91
+
+#define CI_NETWORK_SEG_TYPE_MASK 0x07
+#define CI_NETWORK_SEG_SCHEDULE 0x01
+#define CI_NETWORK_SEG_FIXED_TAG 0x02
+#define CI_NETWORK_SEG_PROD_INHI 0x03
+
+
+/* Device Profile:s */
+#define DP_GEN_DEV 0x00
+#define DP_AC_DRIVE 0x02
+#define DP_MOTOR_OVERLOAD 0x03
+#define DP_LIMIT_SWITCH 0x04
+#define DP_IND_PROX_SWITCH 0x05
+#define DP_PHOTO_SENSOR 0x06
+#define DP_GENP_DISC_IO 0x07
+#define DP_RESOLVER 0x09
+#define DP_COM_ADAPTER 0x0C
+#define DP_POS_CNT 0x10
+#define DP_DC_DRIVE 0x13
+#define DP_CONTACTOR 0x15
+#define DP_MOTOR_STARTER 0x16
+#define DP_SOFT_START 0x17
+#define DP_HMI 0x18
+#define DP_MASS_FLOW_CNT 0x1A
+#define DP_PNEUM_VALVE 0x1B
+#define DP_VACUUM_PRES_GAUGE 0x1C
+
+
+
+/* Initialize the protocol and registered fields */
+static int proto_cipencap = -1;
+static int hf_enip_command = -1;
+static int hf_enip_ifacehnd = -1;
+
+static int hf_enip_cpf_typeid = -1;
+
+static int hf_enip_ucm_sc = -1;
+static int hf_enip_ucm_rr = -1;
+static int hf_enip_ucm_path = -1;
+static int hf_enip_ucm_genstat = -1;
+static int hf_enip_cpf_lir_sinfamily = -1;
+static int hf_enip_cpf_lir_sinport = -1;
+static int hf_enip_cpf_lir_sinaddr = -1;
+static int hf_enip_cpf_lir_sinzero = -1;
+static int hf_enip_cpf_lir_devtype = -1;
+static int hf_enip_cpf_lir_prodcode = -1;
+static int hf_enip_cpf_lir_status = -1;
+static int hf_enip_cpf_lir_sernbr = -1;
+static int hf_enip_cpf_lir_namelength = -1;
+static int hf_enip_cpf_lir_name = -1;
+static int hf_enip_cpf_lir_state = -1;
+
+static int hf_enip_cpf_sat_connid = -1;
+static int hf_enip_cpf_sat_seqnum = -1;
+
+static int hf_enip_vendors = -1;
+
+static int hf_enip_ucm_fwo_comp = -1;
+static int hf_enip_ucm_fwo_mrev = -1;
+
+static int hf_enip_ucm_fwo_con_size = -1;
+static int hf_enip_ucm_fwo_fixed_var = -1;
+static int hf_enip_ucm_fwo_prio = -1;
+static int hf_enip_ucm_fwo_typ = -1;
+static int hf_enip_ucm_fwo_own = -1;
+
+static int hf_enip_ucm_fwo_dir = -1;
+static int hf_enip_ucm_fwo_trigg = -1;
+static int hf_enip_ucm_fwo_class = -1;
+
+static int hf_enip_cpf_lsr_tcp = -1;
+static int hf_enip_cpf_lsr_udp = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_cipencap = -1;
+static gint ett_cip = -1;
+static gint ett_cpf = -1;
+static gint ett_path = -1;
+static gint ett_ekey_path = -1;
+static gint ett_cia_path = -1;
+static gint ett_data_seg = -1;
+
+static gint ett_cipencaph = -1;
+static gint ett_csf = -1;
+static gint ett_rrsc = -1;
+static gint ett_sockadd = -1;
+static gint ett_mcsc = -1;
+static gint ett_ncp = -1;
+static gint ett_lsrcf = -1;
+static gint ett_mes_req = -1;
+static gint ett_cmd_data = -1;
+static gint ett_port_path = -1;
+static gint ett_mult_ser = -1;
+
+static gboolean cipencap_desegment = TRUE;
+
+/* Translate function to string - Encapsulation commands */
+static const value_string encap_cmd_vals[] = {
+ { NOP, "NOP" },
+ { LIST_SERVICES, "List Services" },
+ { LIST_IDENTITY, "List Identity" },
+ { LIST_INTERFACES, "List Interfaces" },
+ { REGISTER_SESSION, "Register Session" },
+ { UNREGISTER_SESSION,"Unregister Session" },
+ { SEND_RR_DATA, "Send RR Data" },
+ { SEND_UNIT_DATA, "Send Unit Data" },
+ { INDICATE_STATUS, "Indicate Status" },
+ { CANCEL, "Cancel" },
+
+ { 0, NULL }
+};
+
+
+/* Translate function to string - Encapsulation status */
+static const value_string encap_status_vals[] = {
+ { SUCCESS, "Success" },
+ { INVALID_CMD, "Invalid Command" },
+ { NO_RESOURCES, "No Memory Resources" },
+ { INCORRECT_DATA, "Incorrect Data" },
+ { INVALID_SESSION, "Invalid Session Handle" },
+ { INVALID_LENGTH, "Invalid Length" },
+ { UNSUPPORTED_PROT_REV, "Unsupported Protocol Revision" },
+
+ { 0, NULL }
+};
+
+/* Translate function to Common data format values */
+static const value_string cdf_type_vals[] = {
+ { CDF_NULL, "Null Address Item" },
+ { LIST_IDENTITY_RESP, "List Identity Response" },
+ { CONNECTION_BASED, "Connected Address Item" },
+ { CONNECTION_TRANSPORT, "Connected Data Item" },
+ { UNCONNECTED_MSG, "Unconnected Data Item" },
+ { LIST_SERVICES_RESP, "List Services Response" },
+ { SOCK_ADR_INFO_OT, "Socket Address Info O->T" },
+ { SOCK_ADR_INFO_TO, "Socket Address Info T->O" },
+ { SEQ_ADDRESS, "Sequenced Address Item" },
+
+ { 0, NULL }
+};
+
+/* Translate function to string - CIP Service codes */
+static const value_string encap_sc_vals[] = {
+ { SC_GET_ATT_ALL, "Get Attribute All" },
+ { SC_SET_ATT_ALL, "Set Attribute All" },
+ { SC_GET_ATT_LIST, "Get Attribute List" },
+ { SC_SET_ATT_LIST, "Set Attribute List" },
+ { SC_RESET, "Reset" },
+ { SC_START, "Start" },
+ { SC_STOP, "Stop" },
+ { SC_CREATE, "Create" },
+ { SC_DELETE, "Delete" },
+ { SC_APPLY_ATTRIBUTES, "Apply Attributes" },
+ { SC_GET_ATT_SINGLE, "Get Attribute Single" },
+ { SC_SET_ATT_SINGLE, "Set Attribute Single" },
+ { SC_FIND_NEXT_OBJ_INST, "Find Next Object Instance" },
+ { SC_RESTOR, "Restore" },
+ { SC_SAVE, "Save" },
+ { SC_NO_OP, "Nop" },
+ { SC_GET_MEMBER, "Get Member" },
+ { SC_SET_MEMBER, "Set Member" },
+ { SC_MULT_SERV_PACK, "Multiple Service Packet" },
+
+ /* Some class specific services */
+ { SC_FWD_CLOSE, "Forward Close" },
+ { SC_FWD_OPEN, "Forward Open" },
+ { SC_UNCON_SEND, "Unconnected Send" },
+
+ { 0, NULL }
+};
+
+/* Translate function to string - CIP Request/Response */
+static const value_string encap_sc_rr[] = {
+ { 0, "Request" },
+ { 1, "Response" },
+
+ { 0, NULL }
+};
+
+
+/* Translate function to string - Compatibility */
+static const value_string enip_com_bit_vals[] = {
+ { 0, "Bit Cleared" },
+ { 1, "Bit Set" },
+
+ { 0, NULL }
+};
+
+/* Translate function to string - True/False */
+static const value_string enip_true_false_vals[] = {
+ { 0, "False" },
+ { 1, "True" },
+
+ { 0, NULL }
+};
+
+
+/* Translate function to string - Connection priority */
+static const value_string enip_con_prio_vals[] = {
+ { 0, "Low Priority" },
+ { 1, "High Priority" },
+ { 2, "Scheduled" },
+ { 3, "Urgent" },
+
+ { 0, NULL }
+};
+
+
+/* Translate function to string - Connection size fixed or variable */
+static const value_string enip_con_fw_vals[] = {
+ { 0, "Fixed" },
+ { 1, "Variable" },
+
+ { 0, NULL }
+};
+
+
+/* Translate function to string - Connection owner */
+static const value_string enip_con_owner_vals[] = {
+ { 0, "Exclusive" },
+ { 1, "Redundant" },
+
+ { 0, NULL }
+};
+
+/* Translate function to string - Connection direction */
+static const value_string enip_con_dir_vals[] = {
+ { 0, "Client" },
+ { 1, "Server" },
+
+ { 0, NULL }
+};
+
+/* Translate function to string - Production trigger */
+static const value_string enip_con_trigg_vals[] = {
+ { 0, "Cyclic" },
+ { 1, "Change-Of-State" },
+ { 2, "Application Object" },
+
+ { 0, NULL }
+};
+
+/* Translate function to string - Transport class */
+static const value_string enip_con_class_vals[] = {
+ { 0, "0" },
+ { 1, "1" },
+ { 2, "2" },
+ { 3, "3" },
+
+ { 0, NULL }
+};
+
+
+/* Translate function to string - Connection type */
+static const value_string enip_con_type_vals[] = {
+ { 0, "Null" },
+ { 1, "Multicast" },
+ { 2, "Point to Point" },
+ { 3, "Reserved" },
+
+ { 0, NULL }
+};
+
+/* Translate function to string - Timeout Multiplier */
+static const value_string enip_con_time_mult_vals[] = {
+ { 0, "*4" },
+ { 1, "*8" },
+ { 2, "*16" },
+ { 3, "*32" },
+ { 4, "*64" },
+ { 5, "*128" },
+ { 6, "*256" },
+ { 7, "*512" },
+
+ { 0, NULL }
+};
+
+
+/* Translate function to string - CIP General Status codes */
+static const value_string encap_cip_gs_vals[] = {
+ { CI_GRC_SUCCESS, "Success" },
+ { CI_GRC_FAILURE, "Connection failure" },
+ { CI_GRC_NO_RESOURCE, "Resource unavailable" },
+ { CI_GRC_BAD_DATA, "Invalid parameter value" },
+ { CI_GRC_BAD_PATH, "Path segment error" },
+ { CI_GRC_BAD_CLASS_INSTANCE, "Path destination unknown" },
+ { CI_GRC_PARTIAL_DATA, "Partial transfer" },
+ { CI_GRC_CONN_LOST, "Connection lost" },
+ { CI_GRC_BAD_SERVICE, "Service not supported" },
+ { CI_GRC_BAD_ATTR_DATA, "Invalid attribute value" },
+ { CI_GRC_ATTR_LIST_ERROR, "Attribute list error" },
+ { CI_GRC_ALREADY_IN_MODE, "Already in requested mode/state" },
+ { CI_GRC_BAD_OBJ_MODE, "Object state conflict" },
+ { CI_GRC_OBJ_ALREADY_EXISTS, "Object already exists" },
+ { CI_GRC_ATTR_NOT_SETTABLE, "Attribute not settable" },
+ { CI_GRC_PERMISSION_DENIED, "Privilege violation" },
+ { CI_GRC_DEV_IN_WRONG_STATE, "Device state conflict" },
+ { CI_GRC_REPLY_DATA_TOO_LARGE,"Reply data too large" },
+ { CI_GRC_FRAGMENT_PRIMITIVE, "Fragmentation of a primitive value" },
+ { CI_GRC_CONFIG_TOO_SMALL, "Not enough data" },
+ { CI_GRC_UNDEFINED_ATTR, "Attribute not supported" },
+ { CI_GRC_CONFIG_TOO_BIG, "Too much data" },
+ { CI_GRC_OBJ_DOES_NOT_EXIST, "Object does not exist" },
+ { CI_GRC_NO_FRAGMENTATION, "Service fragmentation sequence not in progress" },
+ { CI_GRC_DATA_NOT_SAVED, "No stored attribute data" },
+ { CI_GRC_DATA_WRITE_FAILURE, "Store operation failure" },
+ { CI_GRC_REQUEST_TOO_LARGE, "Routing failure, request packet too large" },
+ { CI_GRC_RESPONSE_TOO_LARGE, "Routing failure, response packet too large" },
+ { CI_GRC_MISSING_LIST_DATA, "Missing attribute list entry data" },
+ { CI_GRC_INVALID_LIST_STATUS, "Invalid attribute value list" },
+ { CI_GRC_SERVICE_ERROR, "Embedded service error" },
+ { CI_GRC_CONN_RELATED_FAILURE,"Vendor specific error" },
+ { CI_GRC_INVALID_PARAMETER, "Invalid parameter" },
+ { CI_GRC_WRITE_ONCE_FAILURE, "Write-once value or medium already written" },
+ { CI_GRC_INVALID_REPLY, "Invalid Reply Received" },
+ { CI_GRC_BAD_KEY_IN_PATH, "Key Failure in path" },
+ { CI_GRC_BAD_PATH_SIZE, "Path Size Invalid" },
+ { CI_GRC_UNEXPECTED_ATTR, "Unexpected attribute in list" },
+ { CI_GRC_INVALID_MEMBER, "Invalid Member ID" },
+ { CI_GRC_MEMBER_NOT_SETTABLE, "Member not settable" },
+
+ { 0, NULL }
+};
+
+
+/* Translate Vendor ID:s */
+static const value_string encap_cip_vendor_vals[] = {
+ { 1, "Rockwell Automation/Allen-Bradley" },
+ { 5, "Rockwell Automation/Reliance Electric" },
+ { 24, "ODVA Special Reserve" },
+ { 26, "Festo Corporation" },
+ { 40, "WAGO Corporation" },
+ { 48, "Turck, Inc." },
+ { 49, "Grayhill Inc." },
+ { 50, "Real Time Automation (C&ID)" },
+ { 52, "Numatics, Inc." },
+ { 57, "Pepperl + Fuchs" },
+ { 81, "IXXAT Automation GmbH" },
+ { 90, "HMS Industrial Networks AB" },
+ { 96, "Digital Electronics Corp" },
+ { 128, "MAC Valves, Inc." },
+ { 133, "Balogh T.A.G., Corporation" },
+ { 170, "Pyramid Solutions, Inc." },
+ { 256, "InterlinkBT LLC" },
+ { 258, "Hardy Instruments, Inc." },
+ { 275, "Lantronix, Inc." },
+ { 283, "Hilscher GmbH" },
+ { 287, "Bosch Rexroth Corporation, Indramat" },
+ { 356, "Fanuc Robotics America" },
+ { 553, "Control Techniques PLC-NA" },
+ { 562, "Phoenix Contact" },
+ { 579, "Applicom international" },
+ { 588, "West Instruments Limited" },
+ { 590, "Delta Computer Systems Inc." },
+ { 596, "Wire-Pro, Inc." },
+ { 635, "The Siemon Company" },
+ { 638, "Woodhead Connectivity" },
+ { 651, "Fife Corporation" },
+ { 668, "Rockwell Automation/Entek IRD Intl." },
+ { 678, "Cognex Corporation" },
+ { 691, "Startco Engineering Ltd" },
+ { 734, "Hakko Electronics Co., Ltd" },
+ { 735, "Tang & Associates" },
+ { 743, "Linux Network Services" },
+ { 748, "DVT Corporation" },
+ { 759, "FLS Automation A/S" },
+ { 768, "CSIRO Mining Automation" },
+ { 778, "Harting, Inc. NA" },
+ { 784, "Ci Technologies Pty Ltd (for Pelamos Industries)" },
+ { 796, "Siemens Energy & Automation, Inc." },
+ { 798, "Tyco Electronics" },
+ { 803, "ICP DAS Co., LTD" },
+ { 805, "Digi International, Inc." },
+ { 808, "SICK AG" },
+ { 809, "Ethernet Peripherals, Inc." },
+ { 812, "Process Control Corporation" },
+ { 832, "Quest Technical Solutions, Inc." },
+ { 841, "Panduit Corporation" },
+ { 850, "Datalogic, Inc." },
+ { 851, "SoftPLC Corporation" },
+ { 854, "Frontline Test Equipment, Inc." },
+ { 857, "RVSI" },
+ { 859, "Tennessee Rand Automation" },
+ { 866, "ATR Industrie-Elektronik GmbH Co." },
+ { 875, "FieldServer Technologies (Div Sierra Monitor Corp)" },
+ { 883, "Automa SRL" },
+
+ { 0, NULL }
+};
+
+/* Translate Device Profile:s */
+static const value_string encap_cip_devtype_vals[] = {
+ { DP_GEN_DEV, "Generic Device" },
+ { DP_AC_DRIVE, "AC Drive" },
+ { DP_MOTOR_OVERLOAD, "Motor Overload" },
+ { DP_LIMIT_SWITCH, "Limit Switch" },
+ { DP_IND_PROX_SWITCH, "Inductive Proximity Switch" },
+ { DP_PHOTO_SENSOR, "Photoelectric Sensor" },
+ { DP_GENP_DISC_IO, "General Purpose Dicrete I/O" },
+ { DP_RESOLVER, "Resolver" },
+ { DP_COM_ADAPTER, "Communications Adapter" },
+ { DP_POS_CNT, "Position Controller", },
+ { DP_DC_DRIVE, "DC Drive" },
+ { DP_CONTACTOR, "Contactor", },
+ { DP_MOTOR_STARTER, "Motor Starter", },
+ { DP_SOFT_START, "Soft Start", },
+ { DP_HMI, "Human-Machine Interface" },
+ { DP_MASS_FLOW_CNT, "Mass Flow Controller" },
+ { DP_PNEUM_VALVE, "Pneumatic Valve" },
+ { DP_VACUUM_PRES_GAUGE, "Vaccuum Pressure Gauge" },
+
+ { 0, NULL }
+};
+
+
+/* Translate class names */
+static const value_string enip_class_names_vals[] = {
+ { 0x01, "Identity Object" },
+ { 0x02, "Message Router" },
+ { 0x03, "DeviceNet Object" },
+ { 0x04, "Assembly Object" },
+ { 0x05, "Connection Object" },
+ { 0x06, "Connection Manager" },
+ { 0x07, "Register Object" },
+ { 0x08, "Discrete Input Point Object" },
+ { 0x09, "Discrete Output Point Object" },
+ { 0x0A, "Analog Input Point Object" },
+ { 0x0B, "Analog Output Point Object" },
+ { 0x0E, "Presence Sensing Object" },
+ { 0x0F, "Parameter Object" },
+ { 0x10, "Parameter Group Object" },
+ { 0x12, "Group Object" },
+ { 0x1D, "Discrete Input Group Object" },
+ { 0x1E, "Discrete Output Group Object" },
+ { 0x1F, "Discrete Group Object" },
+ { 0x20, "Analog Input Group Object" },
+ { 0x21, "Analog Output Group Object" },
+ { 0x22, "Analog Group Object" },
+ { 0x23, "Position Sensor Object" },
+ { 0x24, "Position Controller Supervisor Object" },
+ { 0x25, "Position Controller Object" },
+ { 0x26, "Block Sequencer Object" },
+ { 0x27, "Command Block Object" },
+ { 0x28, "Motor Data Object" },
+ { 0x29, "Control Supervisor Object" },
+ { 0x2A, "AC/DC Drive Object" },
+ { 0x2B, "Acknowledge Handler Object" },
+ { 0x2C, "Overload Object" },
+ { 0x2D, "Softstart Object" },
+ { 0x2E, "Selection Object" },
+ { 0x30, "S-Device Supervisor Object" },
+ { 0x31, "S-Analog Sensor Object" },
+ { 0x32, "S-Analog Actuator Object" },
+ { 0x33, "S-Single Stage Controller Object" },
+ { 0x34, "S-Gas Calibration Object" },
+ { 0x35, "Trip Point Object" },
+ { 0xF0, "ControlNet Object" },
+ { 0xF1, "ControlNet Keeper Object" },
+ { 0xF2, "ControlNet Scheduling Object" },
+ { 0xF3, "Connection Configuration Object" },
+ { 0xF4, "Port Object" },
+ { 0xF5, "TCP/IP Interface Object" },
+ { 0xF6, "EtherNet Link Object" },
+
+ { 0, NULL }
+};
+
+
+
+static proto_item*
+add_byte_array_text_to_proto_tree( proto_tree *tree, tvbuff_t *tvb, gint start, gint length, const char* str )
+{
+ const char *tmp;
+ char *tmp2, *tmp2start;
+ proto_item *pi;
+ int i,tmp_length,tmp2_length;
+ guint32 octet;
+ /* At least one version of Apple's C compiler/linker is buggy, causing
+ a complaint from the linker about the "literal C string section"
+ not ending with '\0' if we initialize a 16-element "char" array with
+ a 16-character string, the fact that initializing such an array with
+ such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
+ '\0' byte in the string nonwithstanding. */
+ static const char my_hex_digits[16] =
+ { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+
+ if( ( length * 2 ) > 32 )
+ {
+ tmp_length = 16;
+ tmp2_length = 36;
+ }
+ else
+ {
+ tmp_length = length;
+ tmp2_length = ( length * 2 ) + 1;
+ }
+
+ tmp = tvb_get_ptr( tvb, start, tmp_length );
+ tmp2 = (char*)g_malloc( tmp2_length );
+
+ tmp2start = tmp2;
+
+ for( i = 0; i < tmp_length; i++ )
+ {
+ octet = tmp[i];
+ octet >>= 4;
+ *tmp2++ = my_hex_digits[octet&0xF];
+ octet = tmp[i];
+ *tmp2++ = my_hex_digits[octet&0xF];
+ }
+
+ if( tmp_length != length )
+ {
+ *tmp2++ = '.';
+ *tmp2++ = '.';
+ *tmp2++ = '.';
+ }
+
+ *tmp2 = 0;
+
+ pi = proto_tree_add_text( tree, tvb, start, length, "%s%s", str, tmp2start );
+
+ g_free( tmp2start );
+
+ return( pi );
+
+} /* end of add_byte_array_text_to_proto_tree() */
+
+
+
+/* Decode and add epath to tree */
+static void
+show_epath( tvbuff_t *tvb, proto_item *pi, int offset, int path_length )
+{
+ int pathpos;
+ int temp_data;
+ int temp_data2;
+ unsigned char segment_type, temp_byte, opt_link_size;
+ proto_tree *path_tree, *port_tree, *net_tree;
+ proto_item *qi, *cia_item, *ds_item;
+ proto_tree *e_key_tree, *cia_tree, *ds_tree;
+ proto_item *mcpi, *temp_item, *port_item, *ext_link_item, *net_item;
+ proto_tree *mc_tree;
+ int seg_size, i, temp_word;
+ char *temp_string;
+
+ /* Create a sub tree for the epath */
+ path_tree = proto_item_add_subtree( pi, ett_path );
+
+ proto_tree_add_item_hidden(path_tree, hf_enip_ucm_path,
+ tvb, offset, path_length, TRUE );
+
+ pathpos = 0;
+
+ while( pathpos < path_length )
+ {
+ /* Get segement type */
+ segment_type = tvb_get_guint8( tvb, offset + pathpos );
+
+ /* Determine the segment type */
+
+ switch( segment_type & CI_SEGMENT_TYPE_MASK )
+ {
+ case CI_PATH_SEGMENT:
+
+ port_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 0, "Port Segment" );
+ port_tree = proto_item_add_subtree( port_item, ett_port_path );
+
+ /* Add port number */
+ proto_tree_add_text( port_tree, tvb, offset+pathpos, 1, "Port Identifier: %d", (segment_type & 0x0F) );
+ proto_item_append_text( pi, ", Port: %d", (segment_type & 0x0F) );
+
+ /* Add Extended Link Address flag */
+ temp_item = proto_tree_add_text( port_tree, tvb, offset+pathpos, 1, "Extended Link Address: " );
+
+ if( segment_type & 0x10 )
+ {
+ proto_item_append_text(temp_item, "TRUE");
+ opt_link_size = tvb_get_guint8( tvb, offset + pathpos + 1 );
+
+ proto_tree_add_text( port_tree, tvb, offset+pathpos+1, 1, "Link Address Size: %d", opt_link_size );
+ ext_link_item = proto_tree_add_text( port_tree, tvb, offset+pathpos+2, opt_link_size, "Link Address: " );
+
+ proto_item_append_text(pi, ", Addess: " );
+
+ /* Add extended link address */
+ for( i=0; i < opt_link_size; i++ )
+ {
+ temp_byte = tvb_get_guint8( tvb, offset + pathpos+2+i );
+ proto_item_append_text(ext_link_item, "%c", temp_byte );
+ proto_item_append_text(pi, "%c", temp_byte );
+ }
+
+ /* Pad byte */
+ if( opt_link_size % 2 )
+ {
+ pathpos = pathpos + 3 + opt_link_size;
+ proto_item_set_len(port_item, 3+opt_link_size);
+ }
+ else
+ {
+ pathpos = pathpos + 2 + opt_link_size;
+ proto_item_set_len(port_item, 2+opt_link_size);
+ }
+
+ }
+ else
+ {
+ proto_item_append_text(pi, ", Address: %d", tvb_get_guint8( tvb, offset + pathpos + 1 ) );
+
+ proto_item_append_text(temp_item, "FALSE");
+ proto_tree_add_text( port_tree, tvb, offset+pathpos+1, 1, "Link Address: %d", tvb_get_guint8( tvb, offset + pathpos + 1 ) );
+ proto_item_set_len(port_item, 2);
+ pathpos += 2;
+ }
+
+ break;
+
+ case CI_LOGICAL_SEGMENT:
+
+ /* Logical segment, determin the logical type */
+
+ switch( segment_type & CI_LOGICAL_SEG_TYPE_MASK )
+ {
+ case CI_LOGICAL_SEG_CLASS_ID:
+
+ /* Logical Class ID, do a format check */
+
+ if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_8_BIT )
+ {
+ temp_data = tvb_get_guint8( tvb, offset + pathpos + 1 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 2, "8-Bit Logical Class Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the class */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 8-bit class number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 1, 1, "Class: %s (0x%02X)", val_to_str( temp_data, enip_class_names_vals , "Unknown class" ), temp_data );
+
+ temp_string = match_strval( temp_data, enip_class_names_vals );
+
+ if( temp_string )
+ {
+ proto_item_append_text(pi, "%s", temp_string );
+ }
+ else
+ {
+ proto_item_append_text(pi, "Class: 0x%02X", temp_data );
+ }
+
+ /* 2 bytes of path used */
+ pathpos += 2;
+ }
+ else if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_16_BIT )
+ {
+ temp_data = tvb_get_letohs( tvb, offset + pathpos + 2 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 3, "16-Bit Logical Class Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the class */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 16-bit class number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 2, 2, "Class: %s (0x%04X)", val_to_str( temp_data, enip_class_names_vals , "Unknown class" ), temp_data );
+ temp_string = match_strval( temp_data, enip_class_names_vals );
+
+ if( temp_string )
+ {
+ proto_item_append_text(pi, "%s", temp_string );
+ }
+ else
+ {
+ proto_item_append_text(pi, "Class: 0x%04X", temp_data );
+ }
+
+ /* 4 bytes of path used */
+ pathpos += 4;
+ }
+ else if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_32_BIT )
+ {
+ temp_data = tvb_get_letohl( tvb, offset + pathpos + 2 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 5, "32-Bit Logical Instance Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the class */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 32-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 2, 4, "Class: %s (0x%08X)", val_to_str( temp_data, enip_class_names_vals , "Unknown class" ), temp_data );
+ temp_string = match_strval( temp_data, enip_class_names_vals );
+
+ if( temp_string )
+ {
+ proto_item_append_text(pi, "%s", temp_string );
+ }
+ else
+ {
+ proto_item_append_text(pi, "Class: 0x%08X", temp_data );
+ }
+
+ /* 6 bytes of path used */
+ pathpos += 6;
+ }
+ else
+ {
+ /* Unsupported logical segment format */
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Logical Segment Format" );
+ return;
+ }
+ break;
+
+
+ case CI_LOGICAL_SEG_INST_ID:
+
+ /* Logical Instance ID, do a format check */
+
+ if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_8_BIT )
+ {
+ temp_data = tvb_get_guint8( tvb, offset + pathpos + 1 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 2, "8-Bit Logical Instance Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the instance */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 8-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 1, 1, "Instance: 0x%02X", temp_data );
+ proto_item_append_text(pi, ", Inst: 0x%02X", temp_data );
+
+ /* 2 bytes of path used */
+ pathpos += 2;
+ }
+ else if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_16_BIT )
+ {
+ temp_data = tvb_get_letohs( tvb, offset + pathpos + 2 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 3, "16-Bit Logical Instance Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the instance */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 16-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 2, 2, "Instance: 0x%04X", temp_data );
+ proto_item_append_text(pi, ", Inst: 0x%04X", temp_data );
+
+ /* 4 bytes of path used */
+ pathpos += 4;
+ }
+ else if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_32_BIT )
+ {
+ temp_data = tvb_get_letohl( tvb, offset + pathpos + 2 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 5, "32-Bit Logical Instance Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the instance */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 16-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 2, 4, "Instance: 0x%08X", temp_data );
+ proto_item_append_text(pi, ", Inst: 0x%08X", temp_data );
+
+ /* 6 bytes of path used */
+ pathpos += 6;
+ }
+ else
+ {
+ /* Unsupported logical segment format */
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Logical Segment Format" );
+ return;
+ }
+ break;
+
+
+ case CI_LOGICAL_SEG_ATTR_ID:
+
+ /* Logical Attribute ID, do a format check */
+
+ if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_8_BIT )
+ {
+ temp_data = tvb_get_guint8( tvb, offset + pathpos + 1 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 2, "8-Bit Logical Attribute Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the attribute */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 8-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 1, 1, "Attribute: 0x%02X", temp_data );
+ proto_item_append_text(pi, ", Att: 0x%02X", temp_data );
+
+ /* 2 bytes of path used */
+ pathpos += 2;
+ }
+ else if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_16_BIT )
+ {
+ temp_data = tvb_get_letohs( tvb, offset + pathpos + 2 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 3, "16-Bit Logical Attribute Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the attribute */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 16-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 2, 2, "Attribute: 0x%04X", temp_data );
+ proto_item_append_text(pi, ", Att: 0x%04X", temp_data );
+
+ /* 4 bytes of path used */
+ pathpos += 4;
+ }
+ else if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_32_BIT )
+ {
+ temp_data = tvb_get_letohl( tvb, offset + pathpos + 2 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 5, "32-Bit Logical Attribute Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the attribute */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 16-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 2, 4, "Attribute: 0x%08X", temp_data );
+ proto_item_append_text(pi, ", Att: 0x%08X", temp_data );
+
+ /* 6 bytes of path used */
+ pathpos += 6;
+ }
+ else
+ {
+ /* Unsupported logical segment format */
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Logical Segment Format" );
+ return;
+ }
+ break;
+
+
+ case CI_LOGICAL_SEG_CON_POINT:
+
+ /* Logical Connection point , do a format check */
+
+ if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_8_BIT )
+ {
+ temp_data = tvb_get_guint8( tvb, offset + pathpos + 1 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 2, "8-Bit Logical Connection Point Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the connection point */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 8-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 1, 1, "Connection Point: 0x%02X", temp_data );
+ proto_item_append_text(pi, ", ConPnt: 0x%02X", temp_data );
+
+ /* 2 bytes of path used */
+ pathpos += 2;
+ }
+ else if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_16_BIT )
+ {
+ temp_data = tvb_get_letohs( tvb, offset + pathpos + 2 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 3, "16-Bit Logical Connection Point Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the connection point */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 16-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 2, 2, "Connection Point: 0x%04X", temp_data );
+ proto_item_append_text(pi, ", ConPnt: 0x%04X", temp_data );
+
+ /* 4 bytes of path used */
+ pathpos += 4;
+ }
+ else if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_32_BIT )
+ {
+ temp_data = tvb_get_letohl( tvb, offset + pathpos + 2 );
+ cia_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 5, "32-Bit Logical Connection Point Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree for the connection point */
+ cia_tree = proto_item_add_subtree( cia_item, ett_cia_path );
+
+ /* Display the 16-bit instance number */
+ proto_tree_add_text( cia_tree, tvb, offset + pathpos + 2, 4, "Connection Point (0x%08X)", temp_data );
+ proto_item_append_text(pi, ", ConPnt: 0x%08X", temp_data );
+
+ /* 6 bytes of path used */
+ pathpos += 6;
+ }
+ else
+ {
+ /* Unsupported logical segment format */
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Logical Segment Format" );
+ return;
+ }
+ break;
+
+
+ case CI_LOGICAL_SEG_SPECIAL:
+
+ /* Logical Special ID, the only logical format sepcifyed is electronic key */
+
+ if( ( segment_type & CI_LOGICAL_SEG_FORMAT_MASK ) == CI_LOGICAL_SEG_E_KEY )
+ {
+
+ /* Get the Key Format */
+
+ temp_data = tvb_get_guint8( tvb, offset + pathpos + 1 );
+
+ if( temp_data == CI_E_KEY_FORMAT_VAL )
+ {
+ qi = proto_tree_add_text( path_tree, tvb, offset + pathpos, 10, "Electronic Key Segment (0x%02X): ",segment_type );
+
+ /* Create a sub tree for the IOI */
+ e_key_tree = proto_item_add_subtree( qi, ett_ekey_path );
+
+ /* Print the key type */
+ proto_tree_add_text( e_key_tree, tvb, offset + pathpos + 1, 1, "Key Format: 0x%02X", temp_data );
+
+ /* Get the Vendor ID */
+ temp_data = tvb_get_letohs( tvb, offset + pathpos + 2 );
+ proto_tree_add_item( e_key_tree, hf_enip_vendors, tvb, offset + pathpos + 2, 2, TRUE);
+ proto_item_append_text( qi, "VendorID: 0x%04X", temp_data );
+
+ /* Get Device Type */
+ temp_data = tvb_get_letohs( tvb, offset + pathpos + 4 );
+ proto_tree_add_item( e_key_tree, hf_enip_cpf_lir_devtype, tvb, offset + pathpos + 4, 2, TRUE);
+ proto_item_append_text( qi, ", DevTyp: 0x%04X", temp_data );
+
+ /* Product Code */
+ temp_data = tvb_get_letohs( tvb, offset + pathpos + 6 );
+ proto_tree_add_text( e_key_tree, tvb, offset + pathpos + 6, 2, "Product Code: 0x%04X", temp_data );
+
+ /* Major revision/Compatibility */
+ temp_data = tvb_get_guint8( tvb, offset + pathpos + 8 );
+
+ /* Add Major revision/Compatibility tree */
+ mcpi = proto_tree_add_text(e_key_tree, tvb, offset + pathpos + 8, 1, "Compatibility ");
+ mc_tree = proto_item_add_subtree(mcpi, ett_mcsc);
+
+ /* Add Compatibility bit info */
+ proto_tree_add_item(mc_tree, hf_enip_ucm_fwo_comp,
+ tvb, offset + pathpos + 8, 1, TRUE );
+
+ proto_item_append_text( mcpi, "%s, Major Revision: %d",
+ val_to_str( ( temp_data & 0x80 )>>7, enip_com_bit_vals , "" ),
+ temp_data & 0x7F );
+
+ /* Major revision */
+ proto_tree_add_item(mc_tree, hf_enip_ucm_fwo_mrev,
+ tvb, offset + pathpos + 8, 1, TRUE );
+
+ /* Minor revision */
+ temp_data2 = tvb_get_guint8( tvb, offset + pathpos + 9 );
+ proto_tree_add_text( e_key_tree, tvb, offset + pathpos + 9, 1, "Minor Revision: %d", temp_data2 );
+
+ proto_item_append_text( qi, ", V.%d.%d", ( temp_data & 0x7F ), temp_data2 );
+
+ /* Increment the path pointer */
+ pathpos += 10;
+
+ }
+ else
+ {
+ /* Unsupported electronic key format */
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Electronic Key Format" );
+ return;
+ }
+
+ }
+ else
+ {
+ /* Unsupported special segment format */
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Special Segment Format" );
+ return;
+ }
+ break;
+
+
+ default:
+
+ /* Unsupported logical segment type */
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Logical Segment Type" );
+ return;
+
+ } /* end of switch( segment_type & CI_LOGICAL_SEG_TYPE_MASK ) */
+ break;
+
+
+ case CI_DATA_SEGMENT:
+
+ /* Data segment, determin the logical type */
+
+ switch( segment_type )
+ {
+
+ case CI_DATA_SEG_SIMPLE:
+
+ /* Simple data segment */
+ ds_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 1, "Simple Data Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree */
+ ds_tree = proto_item_add_subtree( ds_item, ett_data_seg );
+
+ /* Segment size */
+ seg_size = tvb_get_guint8( tvb, offset + pathpos+1 )*2;
+ proto_tree_add_text( ds_tree, tvb, offset + pathpos+1, 1, "Data Size: %d (words)", seg_size/2 );
+
+ /* Segment data */
+ if( seg_size != 0 )
+ {
+ qi = proto_tree_add_text( ds_tree, tvb, offset + pathpos+2, 0, "Data: " );
+
+ for( i=0; i < seg_size/2; i ++ )
+ {
+ temp_word = tvb_get_letohs( tvb, offset + pathpos+2+(i*2) );
+ proto_item_append_text(qi, " 0x%04X", temp_word );
+ }
+
+ proto_item_set_len(qi, seg_size);
+ }
+
+ proto_item_set_len( ds_item, 2 + seg_size );
+ pathpos = pathpos + 2 + seg_size;
+
+ break;
+
+ case CI_DATA_SEG_SYMBOL:
+
+ /* ANSI extended symbol segment */
+ ds_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 1, "Extended Symbol Segment (0x%02X)", segment_type );
+
+ /* Create a sub tree */
+ ds_tree = proto_item_add_subtree( ds_item, ett_data_seg );
+
+ /* Segment size */
+ seg_size = tvb_get_guint8( tvb, offset + pathpos+1 );
+ proto_tree_add_text( ds_tree, tvb, offset + pathpos+1, 1, "Data Size: %d", seg_size );
+
+ /* Segment data */
+ if( seg_size != 0 )
+ {
+ qi = proto_tree_add_text( ds_tree, tvb, offset + pathpos+2, 0, "Data: " );
+
+ for( i=0; i < seg_size; i++ )
+ {
+ temp_byte = tvb_get_guint8( tvb, offset + pathpos+2+i );
+ proto_item_append_text(qi, "%c", temp_byte );
+ }
+
+ proto_item_set_len(qi, seg_size);
+
+ if( seg_size %2 )
+ {
+ /* We have a PAD BYTE */
+ proto_tree_add_text( ds_tree, tvb, offset + pathpos+2+i, 1, "Pad Byte (0x%02X)",
+ tvb_get_guint8( tvb, offset + pathpos+2+i ) );
+ pathpos++;
+ seg_size++;
+ }
+ }
+
+ proto_item_set_len( ds_item, 2 + seg_size );
+ pathpos = pathpos + 2 + seg_size;
+
+ break;
+
+ default:
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Sub-Segment Type" );
+ return;
+
+ } /* End of switch sub-type */
+
+ break;
+
+ case CI_NETWORK_SEGMENT:
+
+ /* Network segment -Determine the segment sub-type */
+
+ switch( segment_type & CI_NETWORK_SEG_TYPE_MASK )
+ {
+ case CI_NETWORK_SEG_SCHEDULE:
+ net_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 2, "Network Segment - Schedule" );
+ net_tree = proto_item_add_subtree( net_item, ett_port_path );
+
+ proto_tree_add_text( net_tree, tvb, offset + pathpos + 1, 1, "Multiplier/Phase: %02X", tvb_get_guint8( tvb, offset + pathpos + 1 ) );
+
+ /* 2 bytes of path used */
+ pathpos += 2;
+ break;
+
+ case CI_NETWORK_SEG_FIXED_TAG:
+ net_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 2, "Network Segment - Fixed Tag" );
+ net_tree = proto_item_add_subtree( net_item, ett_port_path );
+
+ proto_tree_add_text( net_tree, tvb, offset + pathpos + 1, 1, "Fixed Tag: %02X", tvb_get_guint8( tvb, offset + pathpos + 1 ) );
+
+ /* 2 bytes of path used */
+ pathpos += 2;
+ break;
+
+ case CI_NETWORK_SEG_PROD_INHI:
+ net_item = proto_tree_add_text( path_tree, tvb, offset + pathpos, 2, "Network Segment - Production Inhibit" );
+ net_tree = proto_item_add_subtree( net_item, ett_port_path );
+
+ proto_tree_add_text( net_tree, tvb, offset + pathpos + 1, 1, "Production Inhibit Time: %dms", tvb_get_guint8( tvb, offset + pathpos + 1 ) );
+
+ /* 2 bytes of path used */
+ pathpos += 2;
+ break;
+
+ default:
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Sub-Segment Type" );
+ return;
+
+ } /* End of switch sub-type */
+
+ break;
+
+ default:
+
+ /* Unsupported segment type */
+ proto_tree_add_text( path_tree, tvb, 0, 0, "Unsupported Segment Type" );
+ return;
+
+ } /* end of switch( segment_type & CI_SEGMENT_TYPE_MASK ) */
+
+ } /* end of while( pathpos < path_length ) */
+
+} /* end of show_epath() */
+
+
+
+static void
+add_cip_data( proto_tree *item_tree, tvbuff_t *tvb, int offset, int item_length, packet_info *pinfo )
+{
+ proto_item *pi, *rrsci, *ncppi, *ar_item, *temp_item, *temp_item2;
+ proto_tree *temp_tree;
+ proto_tree *rrsci_tree;
+ proto_tree *ncp_tree;
+ proto_tree *cmd_data_tree;
+ int req_path_size, conn_path_size, mr_req_path_size;
+ int temp_data;
+ unsigned char gen_stat;
+ unsigned char add_stat_size;
+ unsigned char temp_byte, route_path_size;
+ unsigned char app_rep_size, i;
+ int msg_req_siz, num_services, serv_offset;
+
+
+ /* Add Service code & Request/Response tree */
+ rrsci = proto_tree_add_text(item_tree, tvb, offset, 1, "Service: ");
+ rrsci_tree = proto_item_add_subtree(rrsci, ett_rrsc);
+
+ /* Add Request/Response */
+ proto_tree_add_item(rrsci_tree, hf_enip_ucm_rr,
+ tvb, offset, 1, TRUE );
+
+ proto_item_append_text( rrsci, "%s (%s)",
+ val_to_str( ( tvb_get_guint8( tvb, offset ) & 0x7F ),
+ encap_sc_vals , "Unknown Service (%x)"),
+ val_to_str( ( tvb_get_guint8( tvb, offset ) & 0x80 )>>7,
+ encap_sc_rr, "") );
+
+
+ /* Add Service code */
+ proto_tree_add_item(rrsci_tree, hf_enip_ucm_sc,
+ tvb, offset, 1, TRUE );
+
+
+ if( tvb_get_guint8( tvb, offset ) & 0x80 )
+ {
+ /* Response message */
+
+ /* Add general status */
+ gen_stat = tvb_get_guint8( tvb, offset+2 );
+
+ proto_tree_add_item(item_tree, hf_enip_ucm_genstat,
+ tvb, offset+2, 1, TRUE );
+
+ /* Add reply status to info column */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr( pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str( ( tvb_get_guint8( tvb, offset+2 ) ),
+ encap_cip_gs_vals , "Unknown Response (%x)") );
+ }
+
+
+ /* Add additional status size */
+ temp_data = tvb_get_guint8( tvb, offset+3 );
+ proto_tree_add_text( item_tree, tvb, offset+3, 1, "Additional Status Size: %d (word)", temp_data );
+
+ add_stat_size = tvb_get_guint8( tvb, offset+3 )*2;
+
+ if( add_stat_size )
+ {
+ /* Add additional status */
+ pi = proto_tree_add_text( item_tree, tvb, offset+4, add_stat_size, "Additional Status:" );
+
+ for( i=0; i < add_stat_size/2; i ++ )
+ {
+ proto_item_append_text( pi, " 0x%04X", tvb_get_letohs( tvb, offset+4+(i*2) ) );
+ }
+ }
+
+ /* If there is any command specific data create a sub-tree for it */
+ if( ( item_length-4-add_stat_size ) != 0 )
+ {
+ pi = proto_tree_add_text( item_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, "Command Specific data" );
+ cmd_data_tree = proto_item_add_subtree( pi, ett_cmd_data );
+
+ if( gen_stat == CI_GRC_SUCCESS )
+ {
+ /* Success responses */
+
+ if( ( tvb_get_guint8( tvb, offset ) & 0x7F ) == SC_FWD_OPEN )
+ {
+ /* Forward open Response (Success) */
+
+ /* Display originator to target connection ID */
+ temp_data = tvb_get_letohl( tvb, offset+4+add_stat_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size, 4, "O->T Network Connection ID: 0x%08X", temp_data );
+
+ /* Display target to originator connection ID */
+ temp_data = tvb_get_letohl( tvb, offset+4+add_stat_size+4 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+4, 4, "T->O Network Connection ID: 0x%08X", temp_data );
+
+ /* Display connection serial number */
+ temp_data = tvb_get_letohs( tvb, offset+4+add_stat_size+8 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+8, 2, "Connection Serial Number: 0x%04X", temp_data );
+
+ /* Display the originator vendor id */
+ proto_tree_add_item( cmd_data_tree, hf_enip_vendors, tvb, offset+4+add_stat_size+10, 2, TRUE);
+
+ /* Display the originator serial number */
+ temp_data = tvb_get_letohl( tvb, offset+4+add_stat_size+12 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+12, 4, "Originator Serial Number: 0x%08X", temp_data );
+
+ /* Display originator to target actual packet interval */
+ temp_data = tvb_get_letohl( tvb, offset+4+add_stat_size+16 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+16, 4, "O->T API: %dms (0x%08X)", temp_data / 1000, temp_data );
+
+ /* Display originator to target actual packet interval */
+ temp_data = tvb_get_letohl( tvb, offset+4+add_stat_size+20 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+20, 4, "T->O API: %dms (0x%08X)", temp_data / 1000, temp_data );
+
+ /* Display the application reply size */
+ app_rep_size = tvb_get_guint8( tvb, offset+4+add_stat_size+24 ) * 2;
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+24, 1, "Application Reply Size: %d (words)", app_rep_size / 2 );
+
+ /* Display the Reserved byte */
+ temp_byte = tvb_get_guint8( tvb, offset+4+add_stat_size+25 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+25, 1, "Reserved: 0x%02X", temp_byte );
+
+ if( app_rep_size != 0 )
+ {
+ /* Display application Reply data */
+ ar_item = proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+26, app_rep_size, "Application Reply:" );
+
+ for( i=0; i < app_rep_size; i++ )
+ {
+ temp_byte = tvb_get_guint8( tvb, offset+4+add_stat_size+26+i );
+ proto_item_append_text(ar_item, " 0x%02X", temp_byte );
+ }
+
+ } /* End of if reply data */
+
+ } /* End of if forward open response */
+ else if( ( tvb_get_guint8( tvb, offset ) & 0x7F ) == SC_FWD_CLOSE )
+ {
+ /* Forward close response (Success) */
+
+ /* Display connection serial number */
+ temp_data = tvb_get_letohs( tvb, offset+4+add_stat_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size, 2, "Connection Serial Number: 0x%04X", temp_data );
+
+ /* Display the originator vendor id */
+ proto_tree_add_item( cmd_data_tree, hf_enip_vendors, tvb, offset+4+add_stat_size+2, 2, TRUE);
+
+ /* Display the originator serial number */
+ temp_data = tvb_get_letohl( tvb, offset+4+add_stat_size+4 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+4, 4, "Originator Serial Number: 0x%08X", temp_data );
+
+ /* Display the application reply size */
+ app_rep_size = tvb_get_guint8( tvb, offset+4+add_stat_size+8 ) * 2;
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+8, 1, "Application Reply Size: %d (words)", app_rep_size / 2 );
+
+ /* Display the Reserved byte */
+ temp_byte = tvb_get_guint8( tvb, offset+4+add_stat_size+9 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+9, 1, "Reserved: 0x%02X", temp_byte );
+
+ if( app_rep_size != 0 )
+ {
+ /* Display application Reply data */
+ ar_item = proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+10, app_rep_size, "Application Reply:" );
+
+ for( i=0; i < app_rep_size; i ++ )
+ {
+ temp_byte = tvb_get_guint8( tvb, offset+4+add_stat_size+10+i );
+ proto_item_append_text(ar_item, " 0x%02X", temp_byte );
+ }
+
+ } /* End of if reply data */
+
+ } /* End of if forward close response */
+ else if( ( tvb_get_guint8( tvb, offset ) & 0x7F ) == SC_UNCON_SEND )
+ {
+ /* Unconnected send response (Success) */
+
+ /* Display service response data */
+ add_byte_array_text_to_proto_tree( cmd_data_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, "Data: " );
+ }
+ else if( ( tvb_get_guint8( tvb, offset ) & 0x7F ) == SC_MULT_SERV_PACK )
+ {
+ /* Multiple Service Reply (Success)*/
+
+ /* Add number of replies */
+ num_services = tvb_get_letohs( tvb, offset+4+add_stat_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size, 2, "Number of Replies: %d", num_services );
+
+ /* Add replies */
+ temp_item = proto_tree_add_text( cmd_data_tree, tvb, offset+2+add_stat_size+4, num_services*2, "Offsets: " );
+
+ for( i=0; i < num_services; i++ )
+ {
+ int serv_length;
+
+ serv_offset = tvb_get_letohs( tvb, offset+6+add_stat_size+(i*2) );
+
+ if( i == (num_services-1) )
+ {
+ /* Last service to add */
+ proto_item_append_text(temp_item, "%d", serv_offset );
+ serv_length = item_length-add_stat_size-serv_offset-4;
+ }
+ else
+ {
+ proto_item_append_text(temp_item, "%d, ", serv_offset );
+ serv_length = tvb_get_letohs( tvb, offset+6+add_stat_size+((i+1)*2) ) - serv_offset;
+ }
+
+ temp_item2 = proto_tree_add_text( cmd_data_tree, tvb, offset+serv_offset+4, serv_length, "Service Reply #%d", i+1 );
+ temp_tree = proto_item_add_subtree( temp_item2, ett_mult_ser );
+ add_cip_data( temp_tree, tvb, offset+serv_offset+4, serv_length, pinfo );
+ }
+ } /* End if Multiple service Packet */
+ else if( ( tvb_get_guint8( tvb, offset ) & 0x7F ) == SC_GET_ATT_LIST )
+ {
+ /* Get Attribute List Reply (Success)*/
+
+ int att_count;
+
+ /* Add Attribute Count */
+ att_count = tvb_get_letohs( tvb, offset+4+add_stat_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size, 2, "Attribute Count: %d", att_count );
+
+ /* Add the data */
+ add_byte_array_text_to_proto_tree( cmd_data_tree, tvb, offset+6+add_stat_size, item_length-6-add_stat_size, "Data: " );
+
+ } /* End if Multiple service Packet */
+ else
+ {
+ /* Add data */
+ add_byte_array_text_to_proto_tree( cmd_data_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, "Data: " );
+ } /* end of check service code */
+
+ }
+ else
+ {
+ /* Error responses */
+
+ if( ( ( tvb_get_guint8( tvb, offset ) & 0x7F ) == SC_FWD_OPEN ) ||
+ ( ( tvb_get_guint8( tvb, offset ) & 0x7F ) == SC_FWD_CLOSE ) )
+ {
+ /* Forward open and forward close error response look the same */
+
+ /* Display connection serial number */
+ temp_data = tvb_get_letohs( tvb, offset+4+add_stat_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size, 2, "Connection Serial Number: 0x%04X", temp_data );
+
+ /* Display the originator vendor id */
+ proto_tree_add_item( cmd_data_tree, hf_enip_vendors, tvb, offset+4+add_stat_size+2, 2, TRUE);
+
+ /* Display the originator serial number */
+ temp_data = tvb_get_letohl( tvb, offset+4+add_stat_size+4 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+4, 4, "Originator Serial Number: 0x%08X", temp_data );
+
+ /* Display remaining path size */
+ temp_data = tvb_get_guint8( tvb, offset+4+add_stat_size+8 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+8, 1, "Remaining Path Size: %d", temp_data );
+
+ /* Display reserved data */
+ temp_data = tvb_get_guint8( tvb, offset+4+add_stat_size+9 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size+9, 1, "Reserved: 0x%02X", temp_data );
+ }
+ else if( ( tvb_get_guint8( tvb, offset ) & 0x7F ) == SC_UNCON_SEND )
+ {
+ /* Unconnected send response (Unsuccess) */
+
+ /* Display remaining path size */
+ temp_data = tvb_get_guint8( tvb, offset+4+add_stat_size);
+ proto_tree_add_text( cmd_data_tree, tvb, offset+4+add_stat_size, 1, "Remaining Path Size: %d", temp_data );
+ }
+ else
+ {
+ /* Add data */
+ add_byte_array_text_to_proto_tree( cmd_data_tree, tvb, offset+4+add_stat_size, item_length-4-add_stat_size, "Data: " );
+ }
+
+ } /* end of if-else( CI_CRC_SUCCESS ) */
+
+ } /* End of if command-specific data present */
+
+ } /* End of if reply */
+ else
+ {
+ /* Request message */
+
+ /* Add service to info column */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr( pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str( ( tvb_get_guint8( tvb, offset ) & 0x7F ),
+ encap_sc_vals , "Unknown Service (%x)") );
+ }
+
+ /* Add path size to tree */
+ req_path_size = tvb_get_guint8( tvb, offset+1 )*2;
+ proto_tree_add_text( item_tree, tvb, offset+1, 1, "Request Path Size: %d (words)", req_path_size/2 );
+
+ /* Add the epath */
+ pi = proto_tree_add_text(item_tree, tvb, offset+2, req_path_size, "Request Path: ");
+ show_epath( tvb, pi, offset+2, req_path_size );
+
+ /* If there is any command specific data creat a sub-tree for it */
+ if( (item_length-req_path_size-2) != 0 )
+ {
+
+ pi = proto_tree_add_text( item_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2, "Command Specific Data" );
+ cmd_data_tree = proto_item_add_subtree( pi, ett_cmd_data );
+
+ /* Check what service code that recived */
+
+ if( tvb_get_guint8( tvb, offset ) == SC_FWD_OPEN )
+ {
+ /* Forward open Request*/
+
+ /* Display the priority/tick timer */
+ temp_byte = tvb_get_guint8( tvb, offset+2+req_path_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size, 1, "Priority/Time_tick: 0x%02X", temp_byte );
+
+ /* Display the time-out ticks */
+ temp_data = tvb_get_guint8( tvb, offset+2+req_path_size+1 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+1, 1, "Time-out_ticks: %d", temp_data );
+
+ /* Display the actual time out */
+ temp_data = ( 1 << ( temp_byte & 0x0F ) ) * temp_data;
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size, 2, "Actual Time Out: %dms", temp_data );
+
+ /* Display originator to taget connection ID */
+ temp_data = tvb_get_letohl( tvb, offset+2+req_path_size+2 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+2, 4, "O->T Network Connection ID: 0x%08X", temp_data );
+
+ /* Display target to originator connection ID */
+ temp_data = tvb_get_letohl( tvb, offset+2+req_path_size+6 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+6, 4, "T->O Network Connection ID: 0x%08X", temp_data );
+
+ /* Display connection serial number */
+ temp_data = tvb_get_letohs( tvb, offset+2+req_path_size+10 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+10, 2, "Connection Serial Number: 0x%04X", temp_data );
+
+ /* Display the originator vendor id */
+ proto_tree_add_item( cmd_data_tree, hf_enip_vendors, tvb, offset+2+req_path_size+12, 2, TRUE);
+
+ /* Display the originator serial number */
+ temp_data = tvb_get_letohl( tvb, offset+2+req_path_size+14 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+14, 4, "Originator Serial Number: 0x%08X", temp_data );
+
+ /* Display the timeout multiplier */
+ temp_data = tvb_get_guint8( tvb, offset+2+req_path_size+18 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+18, 1, "Connection Timeout Multiplier: %s (%d)", val_to_str( temp_data, enip_con_time_mult_vals , "Reserved" ), temp_data );
+
+ /* Put out an indicator for the reserved bytes */
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+19, 3, "Reserved Data" );
+
+ /* Display originator to target requested packet interval */
+ temp_data = tvb_get_letohl( tvb, offset+2+req_path_size+22 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+22, 4, "O->T RPI: %dms (0x%08X)", temp_data / 1000, temp_data );
+
+ /* Display originator to target network connection patameterts, in a tree */
+ temp_data = tvb_get_letohs( tvb, offset+2+req_path_size+26 );
+ ncppi = proto_tree_add_text(cmd_data_tree, tvb, offset+2+req_path_size+26, 2, "O->T Network Connection Parameters: 0x%04X", temp_data );
+ ncp_tree = proto_item_add_subtree(ncppi, ett_ncp);
+
+ /* Add the data to the tree */
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_own,
+ tvb, offset+2+req_path_size+26, 2, TRUE );
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_typ,
+ tvb, offset+2+req_path_size+26, 2, TRUE );
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_prio,
+ tvb, offset+2+req_path_size+26, 2, TRUE );
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_fixed_var,
+ tvb, offset+2+req_path_size+26, 2, TRUE );
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_con_size,
+ tvb, offset+2+req_path_size+26, 2, TRUE );
+
+ /* Display target to originator requested packet interval */
+ temp_data = tvb_get_letohl( tvb, offset+2+req_path_size+28 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+28, 4, "T->O RPI: %dms (0x%08X)", temp_data / 1000, temp_data );
+
+ /* Display target to originator network connection patameterts, in a tree */
+ temp_data = tvb_get_letohs( tvb, offset+2+req_path_size+32 );
+ ncppi = proto_tree_add_text(cmd_data_tree, tvb, offset+2+req_path_size+32, 2, "T->O Network Connection Parameters: 0x%04X", temp_data );
+ ncp_tree = proto_item_add_subtree(ncppi, ett_ncp);
+
+ /* Add the data to the tree */
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_own,
+ tvb, offset+2+req_path_size+32, 2, TRUE );
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_typ,
+ tvb, offset+2+req_path_size+32, 2, TRUE );
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_prio,
+ tvb, offset+2+req_path_size+32, 2, TRUE );
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_fixed_var,
+ tvb, offset+2+req_path_size+32, 2, TRUE );
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_con_size,
+ tvb, offset+2+req_path_size+32, 2, TRUE );
+
+ /* Transport type/trigger in tree*/
+ temp_data = tvb_get_guint8( tvb, offset+2+req_path_size+34 );
+
+ ncppi = proto_tree_add_text(cmd_data_tree, tvb, offset+2+req_path_size+34, 1, "Transport Type/Trigger: 0x%02X", temp_data );
+ ncp_tree = proto_item_add_subtree(ncppi, ett_ncp);
+
+ /* Add the data to the tree */
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_dir,
+ tvb, offset+2+req_path_size+34, 1, TRUE );
+
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_trigg,
+ tvb, offset+2+req_path_size+34, 1, TRUE );
+
+ proto_tree_add_item(ncp_tree, hf_enip_ucm_fwo_class,
+ tvb, offset+2+req_path_size+34, 1, TRUE );
+
+ /* Add path size */
+ conn_path_size = tvb_get_guint8( tvb, offset+2+req_path_size+35 )*2;
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+35, 1, "Connection Path Size: %d (words)", conn_path_size / 2 );
+
+ /* Add the epath */
+ pi = proto_tree_add_text(cmd_data_tree, tvb, offset+2+req_path_size+36, conn_path_size, "Connection Path: ");
+ show_epath( tvb, pi, offset+2+req_path_size+36, conn_path_size );
+ }
+ else if( tvb_get_guint8( tvb, offset ) == SC_FWD_CLOSE )
+ {
+ /* Forward Close Request */
+
+ /* Display the priority/tick timer */
+ temp_byte = tvb_get_guint8( tvb, offset+2+req_path_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size, 1, "Priority/Time_tick: 0x%02X", temp_byte );
+
+ /* Display the time-out ticks */
+ temp_data = tvb_get_guint8( tvb, offset+2+req_path_size+1 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+1, 1, "Time-out_ticks: %d", temp_data );
+
+ /* Display the actual time out */
+ temp_data = ( 1 << ( temp_byte & 0x0F ) ) * temp_data;
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size, 2, "Actual Time Out: %dms", temp_data );
+
+ /* Display connection serial number */
+ temp_data = tvb_get_letohs( tvb, offset+2+req_path_size+2 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+2, 2, "Connection Serial Number: 0x%04X", temp_data );
+
+ /* Display the originator vendor id */
+ proto_tree_add_item( cmd_data_tree, hf_enip_vendors, tvb, offset+2+req_path_size+4, 2, TRUE);
+
+ /* Display the originator serial number */
+ temp_data = tvb_get_letohl( tvb, offset+2+req_path_size+6 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+6, 4, "Originator Serial Number: 0x%08X", temp_data );
+
+ /* Add the path size */
+ conn_path_size = tvb_get_guint8( tvb, offset+2+req_path_size+10 )*2;
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+10, 1, "Connection Path Size: %d (words)", conn_path_size / 2 );
+
+ /* Add the reserved byte */
+ temp_byte = tvb_get_guint8( tvb, offset+2+req_path_size+11 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+11, 1, "Reserved: 0x%02X", temp_byte );
+
+ /* Add the EPATH */
+ pi = proto_tree_add_text(cmd_data_tree, tvb, offset+2+req_path_size+12, conn_path_size, "Connection Path: ");
+ show_epath( tvb, pi, offset+2+req_path_size+12, conn_path_size );
+
+ } /* End of forward close */
+ else if( tvb_get_guint8( tvb, offset ) == SC_UNCON_SEND )
+ {
+ /* Unconnected send */
+
+ /* Display the priority/tick timer */
+ temp_byte = tvb_get_guint8( tvb, offset+2+req_path_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size, 1, "Priority/Time_tick: 0x%02X", temp_byte );
+
+ /* Display the time-out ticks */
+ temp_data = tvb_get_guint8( tvb, offset+2+req_path_size+1 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+1, 1, "Time-out_ticks: %d", temp_data );
+
+ /* Display the actual time out */
+ temp_data = ( 1 << ( temp_byte & 0x0F ) ) * temp_data;
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size, 2, "Actual Time Out: %dms", temp_data );
+
+ /* Message request size */
+ msg_req_siz = tvb_get_letohs( tvb, offset+2+req_path_size+2 );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+2, 2, "Message Request Size: 0x%04X", msg_req_siz );
+
+ /* Message Request */
+ temp_item = proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+4, msg_req_siz, "Message Request" );
+ temp_tree = proto_item_add_subtree(temp_item, ett_mes_req );
+
+ /* MR - Service */
+ temp_data = tvb_get_guint8( tvb, offset+2+req_path_size+4 );
+ proto_tree_add_text( temp_tree, tvb, offset+2+req_path_size+4, 1, "Service: %s (0x%02X)", val_to_str( temp_data, encap_sc_vals , "" ), temp_data );
+
+ /* Add service to info column */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr( pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str( ( temp_data & 0x7F ),
+ encap_sc_vals , ", Unknown Service (%x)") );
+ }
+
+ /* MR - Request path Size */
+ mr_req_path_size = tvb_get_guint8( tvb, offset+2+req_path_size+5 )*2;
+ proto_tree_add_text( temp_tree, tvb, offset+2+req_path_size+5, 1, "Request Path Size: %d (words)", mr_req_path_size/2 );
+
+ /* MR - EPATH */
+ temp_item = proto_tree_add_text(temp_tree, tvb, offset+2+req_path_size+6, mr_req_path_size, "Request Path: ");
+ show_epath( tvb, temp_item, offset+2+req_path_size+6, mr_req_path_size );
+
+ /* MR - Request data */
+ if( ( msg_req_siz-2-mr_req_path_size ) != 0 )
+ {
+ add_byte_array_text_to_proto_tree( temp_tree, tvb, offset+2+req_path_size+6+mr_req_path_size, msg_req_siz-2-mr_req_path_size, "Request Data: " );
+ }
+
+ if( msg_req_siz % 2 )
+ {
+ /* Pad byte */
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+4+msg_req_siz, 1, "Pad Byte (0x%02X)",
+ tvb_get_guint8( tvb, offset+2+req_path_size+4+msg_req_siz ) );
+ msg_req_siz++; /* include the padding */
+ }
+
+ /* Route Path Size */
+ route_path_size = tvb_get_guint8( tvb, offset+2+req_path_size+4+msg_req_siz )*2;
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+4+msg_req_siz, 1, "Route Path Size: %d (words)", route_path_size/2 );
+
+ /* Reserved */
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+5+msg_req_siz, 1, "Reserved (0x%02X)",
+ tvb_get_guint8( tvb, offset+2+req_path_size+5+msg_req_siz ) );
+
+ /* Route Path */
+ temp_item = proto_tree_add_text(cmd_data_tree, tvb, offset+2+req_path_size+6+msg_req_siz, route_path_size, "Route Path");
+ show_epath( tvb, temp_item, offset+2+req_path_size+6+msg_req_siz, route_path_size );
+
+ } /* End if unconnected send */
+ else if( tvb_get_guint8( tvb, offset ) == SC_MULT_SERV_PACK )
+ {
+ /* Multiple service packet */
+
+ /* Add number of services */
+ num_services = tvb_get_letohs( tvb, offset+2+req_path_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size, 2, "Number of Services: %d", num_services );
+
+ /* Add services */
+ temp_item = proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+2, num_services*2, "Offsets: " );
+
+ for( i=0; i < num_services; i++ )
+ {
+ int serv_length;
+
+ serv_offset = tvb_get_letohs( tvb, offset+4+req_path_size+(i*2) );
+
+ if( i == (num_services-1) )
+ {
+ /* Last service to add */
+ serv_length = item_length-2-req_path_size-serv_offset;
+ proto_item_append_text(temp_item, "%d", serv_offset );
+ }
+ else
+ {
+ serv_length = tvb_get_letohs( tvb, offset+4+req_path_size+((i+1)*2) ) - serv_offset;
+ proto_item_append_text(temp_item, "%d, ", serv_offset );
+ }
+
+ temp_item2 = proto_tree_add_text( cmd_data_tree, tvb, offset+serv_offset+6, serv_length, "Service Packet #%d", i+1 );
+ temp_tree = proto_item_add_subtree( temp_item2, ett_mult_ser );
+ add_cip_data( temp_tree, tvb, offset+serv_offset+6, serv_length, pinfo );
+ }
+ } /* End if Multiple service Packet */
+ else if( tvb_get_guint8( tvb, offset ) == SC_GET_ATT_LIST )
+ {
+ /* Get attribute list request */
+
+ int att_count;
+
+ /* Add number of services */
+ att_count = tvb_get_letohs( tvb, offset+2+req_path_size );
+ proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size, 2, "Attribute Count: %d", att_count );
+
+ /* Add Attribute List */
+ temp_item = proto_tree_add_text( cmd_data_tree, tvb, offset+2+req_path_size+2, att_count*2, "Attribute List: " );
+
+ for( i=0; i < att_count; i++ )
+ {
+ if( i == (att_count-1) )
+ proto_item_append_text(temp_item, "%d",tvb_get_letohs( tvb, offset+4+req_path_size+(i*2) ) );
+ else
+ proto_item_append_text(temp_item, "%d, ",tvb_get_letohs( tvb, offset+4+req_path_size+(i*2) ) );
+ }
+
+ } /* End of Get attribute list request */
+ else
+ {
+ /* Add data */
+ add_byte_array_text_to_proto_tree( cmd_data_tree, tvb, offset+2+req_path_size, item_length-req_path_size-2, "Data: " );
+ } /* End of check service code */
+
+ } /* End of if command-specific data present */
+
+ } /* end of if-else( request ) */
+
+} /* end of add_cip_data() */
+
+
+
+static void
+show_cdf( int encap_service, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset )
+{
+ proto_item *temp_item, *ri, *ci;
+ proto_item *sockaddr_item;
+ proto_tree *temp_tree, *cip_tree, *item_tree, *sockaddr_tree;
+ int temp_data, item_count, item_length, item;
+ unsigned char name_length;
+
+ /* Show Common Data Format sub tree */
+ item_count = tvb_get_letohs( tvb, offset );
+ ri = proto_tree_add_text( tree, tvb, offset, 2, "Item Count: %d", item_count );
+ cip_tree = proto_item_add_subtree(ri, ett_cip);
+
+ while( item_count-- )
+ {
+ /* Add item type tree */
+ ci = proto_tree_add_item(cip_tree, hf_enip_cpf_typeid, tvb, offset+2, 2, TRUE );
+ item_tree = proto_item_add_subtree(ci, ett_cpf);
+
+ /* Add length field */
+ temp_data = tvb_get_letohs( tvb, offset+4 );
+ proto_tree_add_text( item_tree, tvb, offset+4, 2, "Length: %d", temp_data );
+
+ item = tvb_get_letohs( tvb, offset+2 );
+ item_length = tvb_get_letohs( tvb, offset+4 );
+
+ if( item_length )
+ {
+ /* Add item data field */
+
+ switch( item )
+ {
+ case CONNECTION_BASED:
+
+ /* Add Connection identifier */
+ proto_tree_add_text( item_tree, tvb, offset+6, 4, "Connection Identifier: 0x%08X", tvb_get_letohl( tvb, offset + 6 ) );
+
+ /* Add Connection ID to Info col */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", CONID: 0x%08X",
+ tvb_get_letohl( tvb, offset+6 ) );
+ }
+
+ break;
+
+ case UNCONNECTED_MSG:
+
+ /* Add CIP data tree*/
+ add_cip_data( item_tree, tvb, offset+6, item_length, pinfo );
+
+ break;
+
+ case CONNECTION_TRANSPORT:
+
+ if( encap_service == SEND_UNIT_DATA )
+ {
+ /*
+ ** If the encapsulation service is SendUnit Data, this is a
+ ** encapsulated connected message
+ */
+
+ /* Add sequence count ( Transport Class 1,2,3 )*/
+ proto_tree_add_text( item_tree, tvb, offset+6, 2, "Sequence Count: 0x%04X", tvb_get_letohs( tvb, offset+6 ) );
+
+ /* Add CIP data tree */
+ add_cip_data( item_tree, tvb, offset+8, item_length-2, pinfo );
+
+ /* Add SEQ Count to Info col */
+
+ /*
+ if(check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", SEQ=0x%04X",
+ tvb_get_letohs( tvb, offset+6 ) );
+ }
+ */
+ }
+ else
+ {
+ /* Display data */
+ add_byte_array_text_to_proto_tree( item_tree, tvb, offset+6, item_length, "Data: " );
+
+ } /* End of if send unit data */
+
+ break;
+
+
+ case LIST_IDENTITY_RESP:
+
+ /* Encapsulation version */
+ temp_data = tvb_get_letohs( tvb, offset+6 );
+ proto_tree_add_text( item_tree, tvb, offset+6, 2, "Encapsulation Version: %d", temp_data );
+
+ /* Socket Address */
+ sockaddr_item = proto_tree_add_text( item_tree, tvb, offset+8, 16, "Socket Address");
+ sockaddr_tree = proto_item_add_subtree( sockaddr_item, ett_sockadd );
+
+ /* Socket address struct - sin_family */
+ proto_tree_add_item(sockaddr_tree, hf_enip_cpf_lir_sinfamily,
+ tvb, offset+8, 2, FALSE );
+
+ /* Socket address struct - sin_port */
+ proto_tree_add_item(sockaddr_tree, hf_enip_cpf_lir_sinport,
+ tvb, offset+10, 2, FALSE );
+
+ /* Socket address struct - sin_address */
+ proto_tree_add_item(sockaddr_tree, hf_enip_cpf_lir_sinaddr,
+ tvb, offset+12, 4, FALSE );
+
+ /* Socket address struct - sin_zero */
+ proto_tree_add_item(sockaddr_tree, hf_enip_cpf_lir_sinzero,
+ tvb, offset+16, 8, FALSE );
+
+ /* Vendor ID */
+ proto_tree_add_item(item_tree, hf_enip_vendors,
+ tvb, offset+24, 2, TRUE );
+
+ /* Device Type */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_devtype,
+ tvb, offset+26, 2, TRUE );
+
+ /* Product Code */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_prodcode,
+ tvb, offset+28, 2, TRUE );
+
+ /* Revision */
+ temp_data = tvb_get_letohs( tvb, offset+30 );
+ proto_tree_add_text( item_tree, tvb, offset+30, 2, "Revision: %d.%02d", temp_data & 0xFF, ( temp_data & 0xFF00 ) >> 8 );
+
+ /* Status */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_status,
+ tvb, offset+32, 2, TRUE );
+
+ /* Serial Number */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_sernbr,
+ tvb, offset+34, 4, TRUE );
+
+ /* Product Name Length */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_namelength,
+ tvb, offset+38, 1, TRUE );
+
+ /* Get the lenth of the name */
+ name_length = tvb_get_guint8( tvb, offset+38 );
+
+ /* Product Name */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_name,
+ tvb, offset+39, name_length, TRUE );
+
+ /* Append product name to info column */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr( pinfo->cinfo, COL_INFO, ", %s",
+ tvb_format_text(tvb, offset+39, name_length));
+ }
+
+ /* State */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_state,
+ tvb, offset+name_length+39, 1, TRUE );
+ break;
+
+
+ case SOCK_ADR_INFO_OT:
+ case SOCK_ADR_INFO_TO:
+
+ /* Socket address struct - sin_family */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_sinfamily,
+ tvb, offset+6, 2, FALSE );
+
+ /* Socket address struct - sin_port */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_sinport,
+ tvb, offset+8, 2, FALSE );
+
+ /* Socket address struct - sin_address */
+ proto_tree_add_item(item_tree, hf_enip_cpf_lir_sinaddr,
+ tvb, offset+10, 4, FALSE );
+
+ /* Socket address struct - sin_zero */
+ proto_tree_add_item( item_tree, hf_enip_cpf_lir_sinzero,
+ tvb, offset+14, 8, FALSE );
+ break;
+
+
+ case SEQ_ADDRESS:
+ proto_tree_add_item(item_tree, hf_enip_cpf_sat_connid,
+ tvb, offset+6, 4, TRUE );
+
+ proto_tree_add_item(item_tree, hf_enip_cpf_sat_seqnum,
+ tvb, offset+10, 4, TRUE );
+
+ /* Add info to column */
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Connection: ID=0x%08X, SEQ=%010d",
+ tvb_get_letohl( tvb, offset+6 ),
+ tvb_get_letohl( tvb, offset+10 ) );
+ }
+
+ break;
+
+ case LIST_SERVICES_RESP:
+
+ /* Encapsulation version */
+ temp_data = tvb_get_letohs( tvb, offset+6 );
+ proto_tree_add_text( item_tree, tvb, offset+6, 2, "Encapsulation Version: %d", temp_data );
+
+ /* Capability flags */
+ temp_data = tvb_get_letohs( tvb, offset+8 );
+ temp_item = proto_tree_add_text(item_tree, tvb, offset+8, 2, "Capability Flags: 0x%04X", temp_data );
+ temp_tree = proto_item_add_subtree(temp_item, ett_lsrcf);
+
+ proto_tree_add_item(temp_tree, hf_enip_cpf_lsr_tcp,
+ tvb, offset+8, 2, TRUE );
+ proto_tree_add_item(temp_tree, hf_enip_cpf_lsr_udp,
+ tvb, offset+8, 2, TRUE );
+
+ /* Name of service */
+ temp_item = proto_tree_add_text( item_tree, tvb, offset+10, 16, "Name Of Service: %s",
+ tvb_format_stringzpad(tvb, offset+10, 16) );
+
+ /* Append service name to info column */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr( pinfo->cinfo, COL_INFO, ", %s",
+ tvb_format_stringzpad(tvb, offset+10, 16) );
+ }
+
+ break;
+
+
+ default:
+
+ add_byte_array_text_to_proto_tree( item_tree, tvb, offset+6, item_length, "Data: " );
+ break;
+
+ } /* end of switch( item type ) */
+
+ } /* end of if( item length ) */
+
+ offset = offset + item_length + 4;
+
+ } /* end of while( item count ) */
+
+} /* end of show_cdf() */
+
+
+
+static int
+classify_packet(packet_info *pinfo)
+{
+ /* see if nature of packets can be derived from src/dst ports */
+ /* if so, return as found */
+ if ( ( ENIP_ENCAP_PORT == pinfo->srcport && ENIP_ENCAP_PORT != pinfo->destport ) ||
+ ( ENIP_ENCAP_PORT != pinfo->srcport && ENIP_ENCAP_PORT == pinfo->destport ) ) {
+ if ( ENIP_ENCAP_PORT == pinfo->srcport )
+ return RESPONSE_PACKET;
+ else if ( ENIP_ENCAP_PORT == pinfo->destport )
+ return REQUEST_PACKET;
+ }
+ /* else, cannot classify */
+ return CANNOT_CLASSIFY;
+}
+
+static guint
+get_cipencap_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint16 plen;
+
+ /*
+ * Get the length of the data from the encapsulation header.
+ */
+ plen = tvb_get_letohs(tvb, offset + 2);
+
+ /*
+ * That length doesn't include the encapsulation header itself;
+ * add that in.
+ */
+ return plen + 24;
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_cipencap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int packet_type;
+ guint16 encap_cmd, encap_data_length;
+ char pkt_type_str[9] = "";
+ guint32 status;
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti, *encaph, *csf;
+ proto_tree *cipencap_tree, *headertree, *csftree;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ENIP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ encap_cmd = tvb_get_letohs( tvb, 0 );
+
+ if( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ packet_type = classify_packet(pinfo);
+
+ switch ( packet_type )
+ {
+ case REQUEST_PACKET:
+ strcpy(pkt_type_str, "Req");
+ break;
+
+ case RESPONSE_PACKET:
+ strcpy(pkt_type_str, "Rsp");
+ break;
+
+ default:
+ strcpy(pkt_type_str, "?");
+ }
+
+ /* Add service and request/response to info column */
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%-20s (%s)",
+ val_to_str(encap_cmd, encap_cmd_vals, "Unknown (0x%04x)"),
+ pkt_type_str );
+
+
+ } /* end of if( col exists ) */
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_cipencap, tvb, 0, -1, FALSE);
+
+ cipencap_tree = proto_item_add_subtree(ti, ett_cipencap);
+
+ /* Add encapsulation header tree */
+ encaph = proto_tree_add_text( cipencap_tree, tvb, 0, 24, "Encapsulation Header");
+ headertree = proto_item_add_subtree(encaph, ett_cipencaph);
+
+ /* CIP header information */
+ proto_tree_add_uint(headertree, hf_enip_command, tvb, 0, 2, encap_cmd);
+
+ encap_data_length = tvb_get_letohs( tvb, 2 );
+ proto_tree_add_text( headertree, tvb, 2, 2, "Length: %u", encap_data_length );
+
+ proto_tree_add_text( headertree, tvb, 4, 4, "Session Handle: 0x%08X",
+ tvb_get_letohl( tvb, 4 ) );
+
+ status = tvb_get_letohl( tvb, 8 );
+ proto_tree_add_text( headertree, tvb, 8, 4, "Status: %s (0x%08X)",
+ val_to_str( status, encap_status_vals,
+ "Unknown Status Code" ),
+ status);
+
+ add_byte_array_text_to_proto_tree( headertree, tvb, 12, 8, "Sender context: " );
+
+ proto_tree_add_text( headertree, tvb, 20, 4, "Options: 0x%08X",
+ tvb_get_letohl( tvb, 20 ) );
+
+ /*
+ ** For some commands we want to add some info to the info column
+ */
+
+ if( check_col( pinfo->cinfo, COL_INFO ) )
+ {
+
+ switch( encap_cmd )
+ {
+ case REGISTER_SESSION:
+ case UNREGISTER_SESSION:
+ col_append_fstr( pinfo->cinfo, COL_INFO, ", Session: 0x%08X",
+ tvb_get_letohl( tvb, 4 ) );
+
+ } /* end of switch() */
+
+ } /* end of id info column */
+
+ /* Command specific data - create tree */
+ if( encap_data_length )
+ {
+ /* The packet have some command specific data, buid a sub tree for it */
+
+ csf = proto_tree_add_text( cipencap_tree, tvb, 24, encap_data_length,
+ "Command Specific Data");
+
+ csftree = proto_item_add_subtree(csf, ett_csf);
+
+ switch( encap_cmd )
+ {
+ case NOP:
+ break;
+
+ case LIST_SERVICES:
+ show_cdf( encap_cmd, tvb, pinfo, csftree, 24 );
+ break;
+
+ case LIST_IDENTITY:
+ show_cdf( encap_cmd, tvb, pinfo, csftree, 24 );
+ break;
+
+ case LIST_INTERFACES:
+ show_cdf( encap_cmd, tvb, pinfo, csftree, 24 );
+ break;
+
+ case REGISTER_SESSION:
+ proto_tree_add_text( csftree, tvb, 24, 2, "Protocol Version: 0x%04X",
+ tvb_get_letohs( tvb, 24 ) );
+
+ proto_tree_add_text( csftree, tvb, 26, 2, "Option Flags: 0x%04X",
+ tvb_get_letohs( tvb, 26 ) );
+
+ break;
+
+ case UNREGISTER_SESSION:
+ break;
+
+ case SEND_RR_DATA:
+ case SEND_UNIT_DATA:
+ proto_tree_add_item(csftree, hf_enip_ifacehnd, tvb, 24, 4, TRUE);
+
+ proto_tree_add_text( csftree, tvb, 28, 2, "Timeout: %u",
+ tvb_get_letohs( tvb, 28 ) );
+
+ show_cdf( encap_cmd, tvb, pinfo, csftree, 30 );
+ break;
+
+ case INDICATE_STATUS:
+ case CANCEL:
+ default:
+
+ /* Can not decode - Just show the data */
+ add_byte_array_text_to_proto_tree( headertree, tvb, 24, encap_data_length, "Encap Data: " );
+ break;
+
+ } /* end of switch() */
+
+ } /* end of if( encapsulated data ) */
+
+ }
+} /* end of dissect_cipencap() */
+
+static int
+dissect_cipencap_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 encap_cmd;
+
+ /* An ENIP packet is at least 4 bytes long - we need the command type. */
+ if (!tvb_bytes_exist(tvb, 0, 4))
+ return 0;
+
+ /* Get the command type and see if it's valid. */
+ encap_cmd = tvb_get_letohs( tvb, 0 );
+ if (match_strval(encap_cmd, encap_cmd_vals) == NULL)
+ return 0; /* not a known command */
+
+ dissect_cipencap_pdu(tvb, pinfo, tree);
+ return tvb_length(tvb);
+}
+
+static int
+dissect_cipencap_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 encap_cmd;
+
+ /* An ENIP packet is at least 4 bytes long - we need the command type. */
+ if (!tvb_bytes_exist(tvb, 0, 4))
+ return 0;
+
+ /* Get the command type and see if it's valid. */
+ encap_cmd = tvb_get_letohs( tvb, 0 );
+ if (match_strval(encap_cmd, encap_cmd_vals) == NULL)
+ return 0; /* not a known command */
+
+ tcp_dissect_pdus(tvb, pinfo, tree, cipencap_desegment, 4,
+ get_cipencap_pdu_len, dissect_cipencap_pdu);
+ return tvb_length(tvb);
+}
+
+/* Code to actually dissect the io packets*/
+static void
+dissect_enipio(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *cipencap_tree;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ENIP");
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree)
+ {
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_cipencap, tvb, 0, -1, FALSE);
+
+ cipencap_tree = proto_item_add_subtree(ti, ett_cipencap);
+
+ show_cdf( 0xFFFF, tvb, pinfo, cipencap_tree, 0 );
+ }
+
+} /* end of dissect_enipio() */
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_cipencap(void)
+{
+
+/* Setup list of header fields lengthSee Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_enip_command,
+ { "Command", "enip.command",
+ FT_UINT16, BASE_HEX, VALS(encap_cmd_vals), 0,
+ "Encapsulation command", HFILL }
+ },
+
+ /* Encapsulated data headers */
+ /* Common Packet Format */
+ { &hf_enip_cpf_typeid,
+ { "Type ID", "enip.cpf.typeid",
+ FT_UINT16, BASE_HEX, VALS(cdf_type_vals), 0,
+ "Type of encapsulated item", HFILL }
+ },
+
+ /* Send RR Data */
+ { &hf_enip_ifacehnd,
+ { "Interface Handle", "enip.cpf.rr.ifacehnd",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Interface handle", HFILL }
+ },
+
+ /* Unconnected message */
+ { &hf_enip_ucm_rr,
+ { "Request/Response", "enip.cip.rr",
+ FT_UINT8, BASE_HEX, VALS(encap_sc_rr), 0x80,
+ "Request or Response message", HFILL }
+ },
+ { &hf_enip_ucm_sc,
+ { "Service", "enip.cip.sc",
+ FT_UINT8, BASE_HEX, VALS(encap_sc_vals), 0x7F,
+ "CIP Service code", HFILL }
+ },
+ { &hf_enip_ucm_path,
+ { "Request Path", "enip.cip.path",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Request path", HFILL }
+ },
+ { &hf_enip_ucm_genstat,
+ { "General Status", "enip.cip.genstat",
+ FT_UINT8, BASE_HEX, VALS(encap_cip_gs_vals), 0,
+ "General Status", HFILL }
+ },
+
+ /* List identity response */
+ { &hf_enip_cpf_lir_sinfamily,
+ { "sin_family", "enip.lir.sinfamily",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Socket Address Sin Family", HFILL }
+ },
+ { &hf_enip_cpf_lir_sinport,
+ { "sin_port", "enip.lir.sinport",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Socket Address Sin Port", HFILL }
+ },
+ { &hf_enip_cpf_lir_sinaddr,
+ { "sin_addr", "enip.lir.sinaddr",
+ FT_IPv4, BASE_HEX, NULL, 0,
+ "Socket Address Sin Addr", HFILL }
+ },
+ { &hf_enip_cpf_lir_sinzero,
+ { "sin_zero", "enip.lir.sinzero",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Socket Address Sin Zero", HFILL }
+ },
+ { &hf_enip_cpf_lir_devtype,
+ { "Device Type", "enip.lir.devtype",
+ FT_UINT16, BASE_DEC, VALS(encap_cip_devtype_vals), 0,
+ "Device Type", HFILL }
+ },
+ { &hf_enip_cpf_lir_prodcode,
+ { "Product Code", "enip.lir.prodcode",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Product Code", HFILL }
+ },
+ { &hf_enip_cpf_lir_status,
+ { "Status", "enip.lir.status",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Status", HFILL }
+ },
+ { &hf_enip_cpf_lir_sernbr,
+ { "Serial Number", "enip.lir.ser",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Serial Number", HFILL }
+ },
+ { &hf_enip_cpf_lir_namelength,
+ { "Product Name Length", "enip.lir.namelength",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Product Name Length", HFILL }
+ },
+ { &hf_enip_cpf_lir_name,
+ { "Product Name", "enip.lir.name",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "Product Name", HFILL }
+ },
+ { &hf_enip_cpf_lir_state,
+ { "State", "enip.lir.state",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "State", HFILL }
+ },
+ /* Vendor ID number */
+ { &hf_enip_vendors,
+ { "Vendor ID", "enip.vnd",
+ FT_UINT16, BASE_HEX, VALS(encap_cip_vendor_vals), 0,
+ "Vendor ID number", HFILL }
+ },
+ { &hf_enip_ucm_fwo_comp,
+ { "Compatibility", "enip.cip.fwo.cmp",
+ FT_UINT8, BASE_HEX, VALS(enip_com_bit_vals), 0x80,
+ "Compatibility bit", HFILL }
+ },
+ { &hf_enip_ucm_fwo_mrev,
+ { "Major Revision", "enip.cip.fwo.mrev",
+ FT_UINT8, BASE_DEC, NULL, 0x7F,
+ "Major Revision", HFILL }
+ },
+ { &hf_enip_ucm_fwo_con_size,
+ { "Connection Size", "enip.cip.fwo.consize",
+ FT_UINT16, BASE_DEC, NULL, 0x01FF,
+ "Connection size", HFILL }
+ },
+ { &hf_enip_ucm_fwo_fixed_var,
+ { "Connection Size Type", "enip.cip.fwo.f_v",
+ FT_UINT16, BASE_DEC, VALS(enip_con_fw_vals), 0x0200,
+ "Fixed or variable connection size", HFILL }
+ },
+ { &hf_enip_ucm_fwo_prio,
+ { "Priority", "enip.cip.fwo.prio",
+ FT_UINT16, BASE_DEC, VALS(enip_con_prio_vals), 0x0C00,
+ "Connection priority", HFILL }
+ },
+ { &hf_enip_ucm_fwo_typ,
+ { "Connection Type", "enip.cip.fwo.typ",
+ FT_UINT16, BASE_DEC, VALS(enip_con_type_vals), 0x6000,
+ "Connection type", HFILL }
+ },
+ { &hf_enip_ucm_fwo_own,
+ { "Owner", "enip.cip.fwo.own",
+ FT_UINT16, BASE_DEC, VALS(enip_con_owner_vals), 0x8000,
+ "Redundant owner bit", HFILL }
+ },
+ { &hf_enip_ucm_fwo_dir,
+ { "Direction", "enip.cip.fwo.dir",
+ FT_UINT8, BASE_DEC, VALS(enip_con_dir_vals), 0x80,
+ "Direction", HFILL }
+ },
+ { &hf_enip_ucm_fwo_trigg,
+ { "Trigger", "enip.cip.fwo.trigg",
+ FT_UINT8, BASE_DEC, VALS(enip_con_trigg_vals), 0x70,
+ "Production trigger", HFILL }
+ },
+ { &hf_enip_ucm_fwo_class,
+ { "Class", "enip.cip.fwo.class",
+ FT_UINT8, BASE_DEC, VALS(enip_con_class_vals), 0x0F,
+ "Transport Class", HFILL }
+ },
+ /* Sequenced Address Type */
+ { &hf_enip_cpf_sat_connid,
+ { "Connection ID", "enip.sat.connid",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Connection ID from forward open reply", HFILL }
+ },
+ { &hf_enip_cpf_sat_seqnum,
+ { "Sequence Number", "enip.sat.seq",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Sequence Number", HFILL }
+ },
+ { &hf_enip_cpf_lsr_tcp,
+ { "Supports CIP Encapsultion via TCP", "enip.ls.tcp",
+ FT_UINT16, BASE_DEC, VALS(enip_true_false_vals), 0x0020,
+ "Supports CIP Encapsultion via TCP", HFILL }
+ },
+ { &hf_enip_cpf_lsr_udp,
+ { "Supports CIP Class 0 or 1 via UDP", "enip.ls.udp",
+ FT_UINT16, BASE_DEC, VALS(enip_true_false_vals), 0x0100,
+ "Supports CIP Class 0 or 1 via UDP", HFILL }
+ }
+
+ };
+
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_cipencap,
+ &ett_cip,
+ &ett_cpf,
+ &ett_path,
+ &ett_ekey_path,
+ &ett_cipencaph,
+ &ett_csf,
+ &ett_rrsc,
+ &ett_sockadd,
+ &ett_mcsc,
+ &ett_ncp,
+ &ett_cia_path,
+ &ett_data_seg,
+ &ett_lsrcf,
+ &ett_mes_req,
+ &ett_cmd_data,
+ &ett_port_path,
+ &ett_mult_ser
+ };
+ module_t *cipencap_module;
+
+/* Register the protocol name and description */
+ proto_cipencap = proto_register_protocol("EtherNet/IP (Industrial Protocol)",
+ "ENIP", "enip");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_cipencap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ cipencap_module = prefs_register_protocol(proto_cipencap, NULL);
+ prefs_register_bool_preference(cipencap_module, "desegment",
+ "Desegment all EtherNet/IP messages spanning multiple TCP segments",
+ "Whether the EtherNet/IP dissector should desegment all messages spanning multiple TCP segments",
+ &cipencap_desegment);
+} /* end of proto_register_cipencap() */
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_cipencap(void)
+{
+ dissector_handle_t cipencap_udp_handle, cipencap_tcp_handle;
+ dissector_handle_t enipio_handle;
+
+ /* Register for encapsulated CIP data, using both TCP/UDP */
+ cipencap_tcp_handle = new_create_dissector_handle(dissect_cipencap_tcp, proto_cipencap);
+ dissector_add("tcp.port", ENIP_ENCAP_PORT, cipencap_tcp_handle);
+ cipencap_udp_handle = new_create_dissector_handle(dissect_cipencap_udp, proto_cipencap);
+ dissector_add("udp.port", ENIP_ENCAP_PORT, cipencap_udp_handle);
+
+ /* Register for IO data over UDP */
+ enipio_handle = create_dissector_handle(dissect_enipio, proto_cipencap);
+ dissector_add("udp.port", ENIP_IO_PORT, enipio_handle);
+
+} /* end of proto_reg_handoff_cipencap() */
diff --git a/epan/dissectors/packet-enrp.c b/epan/dissectors/packet-enrp.c
new file mode 100644
index 0000000000..1aa87c442b
--- /dev/null
+++ b/epan/dissectors/packet-enrp.c
@@ -0,0 +1,904 @@
+/* packet-enrp.c
+ * Routines for Endpoint Name Resolution Protocol (ENRP)
+ * It is hopefully (needs testing) compilant to
+ * http://www.ietf.org/internet-drafts/draft-ietf-rserpool-common-param-06.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-rserpool-enrp-09.txt
+ *
+ * The code is not as simple as possible for the current protocol
+ * but allows to be easily adopted to future versions of the protocol.
+ * I will reconsider this after the protocol is an RFC.
+ *
+ * TODO:
+ * - check message lengths
+ *
+ * Copyright 2004, Michael Tuexen <tuexen [AT] fh-muenster.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include "sctpppids.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_enrp = -1;
+static int hf_cause_code = -1;
+static int hf_cause_length = -1;
+static int hf_cause_info = -1;
+static int hf_cause_padding = -1;
+static int hf_message_type = -1;
+static int hf_message_flags = -1;
+static int hf_message_length = -1;
+static int hf_message_value = -1;
+static int hf_parameter_type = -1;
+static int hf_parameter_length = -1;
+static int hf_parameter_value = -1;
+static int hf_parameter_padding = -1;
+static int hf_parameter_ipv4_address = -1;
+static int hf_parameter_ipv6_address = -1;
+static int hf_sctp_port = -1;
+static int hf_transport_use = -1;
+static int hf_tcp_port = -1;
+static int hf_udp_port = -1;
+static int hf_udp_reserved = -1;
+static int hf_policy_type = -1;
+static int hf_policy_value = -1;
+static int hf_pool_handle = -1;
+static int hf_pe_pe_identifier = -1;
+static int hf_home_enrp_id = -1;
+static int hf_reg_life = -1;
+static int hf_server_identifier = -1;
+static int hf_m_bit = -1;
+static int hf_reserved = -1;
+static int hf_cookie = -1;
+static int hf_pe_identifier = -1;
+static int hf_pe_checksum = -1;
+static int hf_sender_servers_id = -1;
+static int hf_receiver_servers_id = -1;
+static int hf_target_servers_id = -1;
+static int hf_update_action = -1;
+static int hf_pmu_reserved = -1;
+static int hf_reply_required_bit = -1;
+static int hf_own_children_only_bit = -1;
+static int hf_more_to_send_bit = -1;
+static int hf_reject_bit = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_enrp = -1;
+static gint ett_enrp_parameter = -1;
+static gint ett_enrp_cause = -1;
+static gint ett_enrp_flags = -1;
+
+static void
+dissect_parameters(tvbuff_t *, proto_tree *);
+
+#define NETWORK_BYTE_ORDER FALSE
+#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
+
+/* Dissectors for error causes. This is common for ASAP and ENRP. */
+
+#define CAUSE_CODE_LENGTH 2
+#define CAUSE_LENGTH_LENGTH 2
+#define CAUSE_HEADER_LENGTH (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
+
+#define CAUSE_HEADER_OFFSET 0
+#define CAUSE_CODE_OFFSET CAUSE_HEADER_OFFSET
+#define CAUSE_LENGTH_OFFSET (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
+#define CAUSE_INFO_OFFSET (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
+
+static void
+dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
+{
+ guint16 code, length, cause_info_length;
+
+ code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
+ length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
+ cause_info_length = length - CAUSE_HEADER_LENGTH;
+ if (cause_info_length > 0)
+ proto_tree_add_bytes(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length,
+ tvb_get_ptr(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length));
+ proto_item_append_text(cause_item, " (code %u and %u byte%s information)", code, cause_info_length, plurality(cause_info_length, "", "s"));
+}
+
+#define UNRECOGNIZED_PARAMETER_CAUSE_CODE 1
+#define UNRECONGNIZED_MESSAGE_CAUSE_CODE 2
+#define INVALID_VALUES 3
+#define NON_UNIQUE_PE_IDENTIFIER 4
+#define POOLING_POLICY_INCONSISTENT_CAUSE_CODE 5
+#define LACK_OF_RESOURCES_CAUSE_CODE 6
+#define INCONSISTENT_TRANSPORT_TYPE_CAUSE_CODE 7
+#define INCONSISTENT_DATA_CONTROL_CONFIGURATION_CAUSE_CODE 8
+
+static const value_string cause_code_values[] = {
+ { UNRECOGNIZED_PARAMETER_CAUSE_CODE, "Unrecognized parameter" },
+ { UNRECONGNIZED_MESSAGE_CAUSE_CODE, "Unrecognized message" },
+ { INVALID_VALUES, "Invalid values" },
+ { NON_UNIQUE_PE_IDENTIFIER, "Non-unique PE identifier" },
+ { POOLING_POLICY_INCONSISTENT_CAUSE_CODE, "Pooling policy inconsistent" },
+ { LACK_OF_RESOURCES_CAUSE_CODE, "Lack of resources" },
+ { INCONSISTENT_TRANSPORT_TYPE_CAUSE_CODE, "Inconsistent transport type" },
+ { INCONSISTENT_DATA_CONTROL_CONFIGURATION_CAUSE_CODE, "Inconsistent data/control type" },
+ { 0, NULL } };
+
+static void
+dissect_error_cause(tvbuff_t *cause_tvb, proto_tree *parameter_tree)
+{
+ guint16 code, length, padding_length;
+ proto_item *cause_item;
+ proto_tree *cause_tree;
+
+ code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
+ length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
+ padding_length = tvb_length(cause_tvb) - length;
+
+ cause_item = proto_tree_add_text(parameter_tree, cause_tvb, CAUSE_HEADER_OFFSET, tvb_length(cause_tvb), val_to_str(code, cause_code_values, "Unknown error cause"));
+ cause_tree = proto_item_add_subtree(cause_item, ett_enrp_cause);
+
+ proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(code) {
+ default:
+ dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
+ break;
+ }
+ if (padding_length > 0)
+ proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_error_causes(tvbuff_t *error_causes_tvb, proto_tree *parameter_tree)
+{
+ guint16 length, total_length;
+ gint offset;
+ tvbuff_t *error_cause_tvb;
+
+ offset = 0;
+ while(tvb_reported_length_remaining(error_causes_tvb, offset)) {
+ length = tvb_get_ntohs(error_causes_tvb, offset + CAUSE_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ error_cause_tvb = tvb_new_subset(error_causes_tvb, offset , total_length, total_length);
+ dissect_error_cause(error_cause_tvb, parameter_tree);
+ offset += total_length;
+ }
+}
+
+/* Dissectors for parameters. This is common for ASAP and ENRP. */
+
+#define PARAMETER_TYPE_LENGTH 2
+#define PARAMETER_LENGTH_LENGTH 2
+#define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
+
+#define PARAMETER_HEADER_OFFSET 0
+#define PARAMETER_TYPE_OFFSET PARAMETER_HEADER_OFFSET
+#define PARAMETER_LENGTH_OFFSET (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
+#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
+
+#define IPV4_ADDRESS_LENGTH 4
+#define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_parameter_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
+}
+
+#define IPV6_ADDRESS_LENGTH 16
+#define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_parameter_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
+}
+
+#define TRANSPORT_USE_DATA_ONLY 0
+#define TRANSPORT_USE_DATA_PLUS_CONTROL 1
+
+static const value_string transport_use_values[] = {
+ { TRANSPORT_USE_DATA_ONLY, "Data only" },
+ { TRANSPORT_USE_DATA_PLUS_CONTROL, "Data plus control" },
+ { 0, NULL } };
+
+#define SCTP_PORT_LENGTH 2
+#define SCTP_TRANSPORT_USE_LENGTH 2
+#define SCTP_PORT_OFFSET PARAMETER_VALUE_OFFSET
+#define SCTP_TRANSPORT_USE_OFFSET (SCTP_PORT_OFFSET + SCTP_PORT_LENGTH)
+#define SCTP_ADDRESS_OFFSET (SCTP_TRANSPORT_USE_OFFSET + SCTP_TRANSPORT_USE_LENGTH)
+
+static void
+dissect_sctp_transport_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_sctp_port, parameter_tvb, SCTP_PORT_OFFSET, SCTP_PORT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_transport_use, parameter_tvb, SCTP_TRANSPORT_USE_OFFSET, SCTP_TRANSPORT_USE_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, SCTP_ADDRESS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define TCP_PORT_LENGTH 2
+#define TCP_TRANSPORT_USE_LENGTH 2
+#define TCP_PORT_OFFSET PARAMETER_VALUE_OFFSET
+#define TCP_TRANSPORT_USE_OFFSET (TCP_PORT_OFFSET + TCP_PORT_LENGTH)
+#define TCP_ADDRESS_OFFSET (TCP_TRANSPORT_USE_OFFSET + TCP_TRANSPORT_USE_LENGTH)
+
+static void
+dissect_tcp_transport_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_tcp_port, parameter_tvb, TCP_PORT_OFFSET, TCP_PORT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_transport_use, parameter_tvb, TCP_TRANSPORT_USE_OFFSET, TCP_TRANSPORT_USE_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, TCP_ADDRESS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define UDP_PORT_LENGTH 2
+#define UDP_RESERVED_LENGTH 2
+#define UDP_PORT_OFFSET PARAMETER_VALUE_OFFSET
+#define UDP_RESERVED_OFFSET (UDP_PORT_OFFSET + UDP_PORT_LENGTH)
+#define UDP_ADDRESS_OFFSET (UDP_RESERVED_OFFSET + UDP_RESERVED_LENGTH)
+
+static void
+dissect_udp_transport_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_udp_port, parameter_tvb, UDP_PORT_OFFSET, UDP_PORT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_udp_reserved, parameter_tvb, UDP_RESERVED_OFFSET, UDP_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, UDP_ADDRESS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define POLICY_TYPE_LENGTH 1
+#define POLICY_VALUE_LENGTH 3
+
+#define POLICY_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+#define POLICY_VALUE_OFFSET (POLICY_TYPE_OFFSET + POLICY_TYPE_LENGTH)
+
+#define ROUND_ROBIN_POLICY 1
+#define LEAST_USED_POLICY 2
+#define LEAST_USED_WITH_DEG 3
+#define WEIGHTED_ROUND_ROBIN 4
+
+static const value_string policy_type_values[] = {
+ { ROUND_ROBIN_POLICY, "Round robin" },
+ { LEAST_USED_POLICY, "Least used" },
+ { LEAST_USED_WITH_DEG, "Least used with degradation" },
+ { WEIGHTED_ROUND_ROBIN, "Weighted round robin" },
+ { 0, NULL } };
+
+static void
+dissect_pool_member_selection_policy_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_tree_add_item(parameter_tree, hf_policy_type, parameter_tvb, POLICY_TYPE_OFFSET, POLICY_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_policy_value, parameter_tvb, POLICY_VALUE_OFFSET, POLICY_VALUE_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define POOL_HANDLE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_pool_handle_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ guint16 handle_length;
+
+ handle_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_pool_handle, parameter_tvb, POOL_HANDLE_OFFSET, handle_length, NETWORK_BYTE_ORDER);
+}
+
+#define PE_PE_IDENTIFIER_LENGTH 4
+#define HOME_ENRP_INDENTIFIER_LENGTH 4
+#define REGISTRATION_LIFE_LENGTH 4
+
+#define PE_PE_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+#define HOME_ENRP_INDENTIFIER_OFFSET (PE_PE_IDENTIFIER_OFFSET + PE_PE_IDENTIFIER_LENGTH)
+#define REGISTRATION_LIFE_OFFSET (HOME_ENRP_INDENTIFIER_OFFSET + HOME_ENRP_INDENTIFIER_LENGTH)
+#define USER_TRANSPORT_PARAMETER_OFFSET (REGISTRATION_LIFE_OFFSET + REGISTRATION_LIFE_LENGTH)
+
+static void
+dissect_pool_element_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_pe_pe_identifier, parameter_tvb, PE_PE_IDENTIFIER_OFFSET, PE_PE_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_home_enrp_id, parameter_tvb, HOME_ENRP_INDENTIFIER_OFFSET, HOME_ENRP_INDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_reg_life, parameter_tvb, REGISTRATION_LIFE_OFFSET, REGISTRATION_LIFE_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, USER_TRANSPORT_PARAMETER_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define SERVER_ID_LENGTH 4
+#define RESERVED_LENGTH 4
+
+#define SERVER_ID_OFFSET PARAMETER_VALUE_OFFSET
+#define RESERVED_OFFSET (SERVER_ID_OFFSET + SERVER_ID_LENGTH)
+#define SERVER_TRANSPORT_OFFSET (RESERVED_OFFSET + RESERVED_LENGTH)
+
+#define M_BIT_MASK 0x80000000
+#define RESERVED_MASK 0x7fffffff
+
+static void
+dissect_server_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_server_identifier, parameter_tvb, SERVER_ID_OFFSET, SERVER_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_m_bit, parameter_tvb, RESERVED_OFFSET, RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_reserved, parameter_tvb, RESERVED_OFFSET, RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, SERVER_TRANSPORT_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree);
+}
+
+#define ERROR_CAUSES_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_operation_error_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *error_causes_tvb;
+
+ error_causes_tvb = tvb_new_subset(parameter_tvb, ERROR_CAUSES_OFFSET, -1,-1);
+ dissect_error_causes(error_causes_tvb, parameter_tree);
+}
+
+#define COOKIE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 cookie_length;
+
+ cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ if (cookie_length > 0)
+ proto_tree_add_item(parameter_tree, hf_cookie, parameter_tvb, COOKIE_OFFSET, cookie_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", cookie_length, plurality(cookie_length, "", "s"));
+}
+
+#define PE_IDENTIFIER_LENGTH 4
+#define PE_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_pe_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_pe_identifier, parameter_tvb, PE_IDENTIFIER_OFFSET, PE_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (0x%x)", tvb_get_ntohl(parameter_tvb, PE_IDENTIFIER_OFFSET));
+}
+
+#define PE_CHECKSUM_LENGTH 4
+#define PE_CHECKSUM_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_pe_checksum_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_pe_checksum, parameter_tvb, PE_CHECKSUM_OFFSET, PE_CHECKSUM_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (0x%x)", tvb_get_ntohl(parameter_tvb, PE_CHECKSUM_OFFSET));
+}
+
+static void
+dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 type, parameter_value_length;
+
+ type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
+ parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+
+ if (parameter_value_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
+
+ proto_item_append_text(parameter_item, " (type %u and %u byte%s value)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
+}
+
+#define IPV4_ADDRESS_PARAMETER_TYPE 0x01
+#define IPV6_ADDRESS_PARAMETER_TYPE 0x02
+#define SCTP_TRANSPORT_PARAMETER_TYPE 0x03
+#define TCP_TRANSPORT_PARAMETER_TYPE 0x04
+#define UDP_TRANSPORT_PARAMETER_TYPE 0x05
+#define POOL_MEMBER_SELECTION_POLICY_PARAMETER_TYPE 0x06
+#define POOL_HANDLE_PARAMETER_TYPE 0x07
+#define POOL_ELEMENT_PARAMETER_TYPE 0x08
+#define SERVER_INFORMATION_PARAMETER_TYPE 0x09
+#define OPERATION_ERROR_PARAMETER_TYPE 0x0a
+#define COOKIE_PARAMETER_TYPE 0x0b
+#define PE_IDENTIFIER_PARAMETER_TYPE 0x0c
+#define PE_CHECKSUM_PARAMETER_TYPE 0x0d
+
+static const value_string parameter_type_values[] = {
+ { IPV4_ADDRESS_PARAMETER_TYPE, "IPV4 address" },
+ { IPV6_ADDRESS_PARAMETER_TYPE, "IPV6 address" },
+ { SCTP_TRANSPORT_PARAMETER_TYPE, "SCTP transport address" },
+ { TCP_TRANSPORT_PARAMETER_TYPE, "TCP transport address" },
+ { UDP_TRANSPORT_PARAMETER_TYPE, "UDP transport address" },
+ { POOL_MEMBER_SELECTION_POLICY_PARAMETER_TYPE, "Pool member selection policy" },
+ { POOL_HANDLE_PARAMETER_TYPE, "Pool handle" },
+ { POOL_ELEMENT_PARAMETER_TYPE, "Pool element" },
+ { SERVER_INFORMATION_PARAMETER_TYPE, "Server Information" },
+ { OPERATION_ERROR_PARAMETER_TYPE, "Operation error" },
+ { COOKIE_PARAMETER_TYPE, "Cookie" },
+ { PE_IDENTIFIER_PARAMETER_TYPE, "Pool Element identifier" },
+ { PE_CHECKSUM_PARAMETER_TYPE, "PE checksum" },
+ { 0, NULL } };
+
+
+static void
+dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *enrp_tree)
+{
+ guint16 type, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+
+ /* extract tag and length from the parameter */
+ type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = tvb_length(parameter_tvb) - length;
+
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(enrp_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), val_to_str(type, parameter_type_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_enrp_parameter);
+
+ /* add tag and length to the enrp tree */
+ proto_tree_add_item(parameter_tree, hf_parameter_type, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(type) {
+ case IPV4_ADDRESS_PARAMETER_TYPE:
+ dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case IPV6_ADDRESS_PARAMETER_TYPE:
+ dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case SCTP_TRANSPORT_PARAMETER_TYPE:
+ dissect_sctp_transport_parameter(parameter_tvb, parameter_tree);
+ break;
+ case TCP_TRANSPORT_PARAMETER_TYPE:
+ dissect_tcp_transport_parameter(parameter_tvb, parameter_tree);
+ break;
+ case UDP_TRANSPORT_PARAMETER_TYPE:
+ dissect_udp_transport_parameter(parameter_tvb, parameter_tree);
+ break;
+ case POOL_MEMBER_SELECTION_POLICY_PARAMETER_TYPE:
+ dissect_pool_member_selection_policy_parameter(parameter_tvb, parameter_tree);
+ break;
+ case POOL_HANDLE_PARAMETER_TYPE:
+ dissect_pool_handle_parameter(parameter_tvb, parameter_tree);
+ break;
+ case POOL_ELEMENT_PARAMETER_TYPE:
+ dissect_pool_element_parameter(parameter_tvb, parameter_tree);
+ break;
+ case SERVER_INFORMATION_PARAMETER_TYPE:
+ dissect_server_information_parameter(parameter_tvb, parameter_tree);
+ break;
+ case OPERATION_ERROR_PARAMETER_TYPE:
+ dissect_operation_error_parameter(parameter_tvb, parameter_tree);
+ break;
+ case COOKIE_PARAMETER_TYPE:
+ dissect_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PE_IDENTIFIER_PARAMETER_TYPE:
+ dissect_pe_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PE_CHECKSUM_PARAMETER_TYPE:
+ dissect_pe_checksum_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ default:
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ };
+
+ if (padding_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_parameters(tvbuff_t *parameters_tvb, proto_tree *tree)
+{
+ gint offset, length, total_length, remaining_length;
+ tvbuff_t *parameter_tvb;
+
+ offset = 0;
+ while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
+ length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ if (remaining_length >= length)
+ total_length = MIN(total_length, remaining_length);
+ /* create a tvb for the parameter including the padding bytes */
+ parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
+ dissect_parameter(parameter_tvb, tree);
+ /* get rid of the handled parameter */
+ offset += total_length;
+ }
+}
+
+/* Dissectors for messages. This is specific to ENRP */
+
+#define MESSAGE_TYPE_LENGTH 1
+#define MESSAGE_FLAGS_LENGTH 1
+#define MESSAGE_LENGTH_LENGTH 2
+#define MESSAGE_HEADER_LENGTH (MESSAGE_TYPE_LENGTH + MESSAGE_FLAGS_LENGTH + MESSAGE_LENGTH_LENGTH)
+
+#define MESSAGE_TYPE_OFFSET 0
+#define MESSAGE_FLAGS_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
+#define MESSAGE_LENGTH_OFFSET (MESSAGE_FLAGS_OFFSET + MESSAGE_FLAGS_LENGTH)
+#define MESSAGE_VALUE_OFFSET (MESSAGE_LENGTH_OFFSET + MESSAGE_LENGTH_LENGTH)
+
+#define SENDER_SERVERS_ID_LENGTH 4
+#define RECEIVER_SERVERS_ID_LENGTH 4
+
+#define SENDER_SERVERS_ID_OFFSET MESSAGE_VALUE_OFFSET
+#define RECEIVER_SERVERS_ID_OFFSET (SENDER_SERVERS_ID_OFFSET + SENDER_SERVERS_ID_LENGTH)
+#define MESSAGE_PARAMETERS_OFFSET (RECEIVER_SERVERS_ID_OFFSET + RECEIVER_SERVERS_ID_LENGTH)
+
+#define REPLY_REQUIRED_BIT_MASK 0x01
+
+static const true_false_string reply_required_bit_value = {
+ "Reply required",
+ "Reply not required"
+};
+
+static void
+dissect_peer_presence_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(flags_tree, hf_reply_required_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ parameters_tvb = tvb_new_subset(message_tvb, MESSAGE_PARAMETERS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, message_tree);
+}
+
+#define OWN_CHILDREN_ONLY_BIT_MASK 0x01
+
+static const true_false_string own_children_only_bit_value = {
+ "Only information for own PEs",
+ "Information for all PEs"
+};
+
+
+static void
+dissect_peer_name_table_request_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree)
+{
+ /* FIXME: ensure that the length is 12 bytes. */
+ proto_tree_add_item(flags_tree, hf_own_children_only_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define REJECT_BIT_MASK 0x01
+#define MORE_TO_SEND_BIT_MASK 0x02
+
+static const true_false_string reject_bit_value = {
+ "Rejected",
+ "Accepted"
+};
+
+static const true_false_string more_to_send_bit_value = {
+ "More information available",
+ "All information included"
+};
+
+static void
+dissect_peer_name_table_response_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(flags_tree, hf_more_to_send_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(flags_tree, hf_reject_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ parameters_tvb = tvb_new_subset(message_tvb, MESSAGE_PARAMETERS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, message_tree);
+}
+
+#define UPDATE_ACTION_LENGTH 2
+#define PNU_RESERVED_LENGTH 2
+
+#define UPDATE_ACTION_OFFSET (MESSAGE_VALUE_OFFSET + SENDER_SERVERS_ID_LENGTH + RECEIVER_SERVERS_ID_LENGTH)
+#define PNU_RESERVED_OFFSET (UPDATE_ACTION_OFFSET + UPDATE_ACTION_LENGTH)
+#define PNU_MESSAGE_PARAMETERS_OFFSET (PNU_RESERVED_OFFSET + PNU_RESERVED_LENGTH)
+
+static const value_string update_action_values[] = {
+ { 0, "Add pool element" },
+ { 1, "Delete pool element" },
+ { 0, NULL } };
+
+static void
+dissect_peer_name_update_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree _U_)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_update_action, message_tvb, UPDATE_ACTION_OFFSET, UPDATE_ACTION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_pmu_reserved, message_tvb, PNU_RESERVED_OFFSET, PNU_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ parameters_tvb = tvb_new_subset(message_tvb, PNU_MESSAGE_PARAMETERS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, message_tree);
+}
+
+static void
+dissect_peer_list_request_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree _U_)
+{
+ /* FIXME: ensure that the length is 12 bytes. */
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_peer_list_response_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(flags_tree, hf_reject_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ parameters_tvb = tvb_new_subset(message_tvb, MESSAGE_PARAMETERS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, message_tree);
+}
+
+#define TARGET_SERVERS_ID_LENGTH 4
+#define TARGET_SERVERS_ID_OFFSET (RECEIVER_SERVERS_ID_OFFSET + RECEIVER_SERVERS_ID_LENGTH)
+
+static void
+dissect_peer_init_takeover_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree _U_)
+{
+ /* FIXME: ensure that the length is 16 bytes. */
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_target_servers_id, message_tvb, TARGET_SERVERS_ID_OFFSET, TARGET_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_peer_init_takeover_ack_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree _U_)
+{
+ /* FIXME: ensure that the length is 16 bytes. */
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_target_servers_id, message_tvb, TARGET_SERVERS_ID_OFFSET, TARGET_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_peer_init_takeover_server_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree _U_)
+{
+ /* FIXME: ensure that the length is 16 bytes. */
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_target_servers_id, message_tvb, TARGET_SERVERS_ID_OFFSET, TARGET_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_peer_ownership_change_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree _U_)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ parameters_tvb = tvb_new_subset(message_tvb, MESSAGE_PARAMETERS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, message_tree);
+}
+
+static void
+dissect_peer_error_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree _U_)
+{
+ tvbuff_t *parameters_tvb;
+
+ proto_tree_add_item(message_tree, hf_sender_servers_id, message_tvb, SENDER_SERVERS_ID_OFFSET, SENDER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(message_tree, hf_receiver_servers_id, message_tvb, RECEIVER_SERVERS_ID_OFFSET, RECEIVER_SERVERS_ID_LENGTH, NETWORK_BYTE_ORDER);
+ parameters_tvb = tvb_new_subset(message_tvb, MESSAGE_PARAMETERS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, message_tree);
+}
+
+static void
+dissect_unknown_message(tvbuff_t *message_tvb, proto_tree *message_tree, proto_tree *flags_tree _U_)
+{
+ proto_tree_add_item(message_tree, hf_message_value, message_tvb, MESSAGE_VALUE_OFFSET, tvb_length(message_tvb) - MESSAGE_HEADER_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define PEER_PRESENCE_MESSAGE_TYPE 0x01
+#define PEER_NAME_TABLE_REQUEST_MESSAGE_TYPE 0x02
+#define PEER_NAME_TABLE_RESPONSE_MESSAGE_TYPE 0x03
+#define PEER_NAME_UPDATE_MESSAGE_TYPE 0x04
+#define PEER_LIST_REQUEST_MESSAGE_TYPE 0x05
+#define PEER_LIST_RESPONSE_MESSAGE_TYPE 0x06
+#define PEER_INIT_TAKEOVER_MESSAGE_TYPE 0x07
+#define PEER_INIT_TAKEOVER_ACK_MESSAGE_TYPE 0x08
+#define PEER_TAKEOVER_SERVER_MESSAGE_TYPE 0x09
+#define PEER_OWNERSHIP_CHANGE_MESSAGE_TYPE 0x0a
+#define PEER_ERROR_MESSAGE_TYPE 0x0b
+
+static const value_string message_type_values[] = {
+ { PEER_PRESENCE_MESSAGE_TYPE, "Peer presence" },
+ { PEER_NAME_TABLE_REQUEST_MESSAGE_TYPE, "Peer name table request" },
+ { PEER_NAME_TABLE_RESPONSE_MESSAGE_TYPE, "Peer name table response" },
+ { PEER_NAME_UPDATE_MESSAGE_TYPE, "Peer name update" },
+ { PEER_LIST_REQUEST_MESSAGE_TYPE, "Peer list request" },
+ { PEER_LIST_RESPONSE_MESSAGE_TYPE, "Peer list response" },
+ { PEER_INIT_TAKEOVER_MESSAGE_TYPE, "Peer init takeover" },
+ { PEER_INIT_TAKEOVER_ACK_MESSAGE_TYPE, "Peer init takeover ack" },
+ { PEER_TAKEOVER_SERVER_MESSAGE_TYPE, "Peer takeover server" },
+ { PEER_OWNERSHIP_CHANGE_MESSAGE_TYPE, "Peer ownership change" },
+ { PEER_ERROR_MESSAGE_TYPE, "Peer error" },
+ { 0, NULL } };
+
+static void
+dissect_enrp_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *enrp_tree)
+{
+ proto_item *flags_item;
+ proto_tree *flags_tree;
+ guint8 type;
+
+ type = tvb_get_guint8(message_tvb, MESSAGE_TYPE_OFFSET);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, message_type_values, "Unknown ENRP type"));
+
+ if (enrp_tree) {
+ proto_tree_add_item(enrp_tree, hf_message_type, message_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ flags_item = proto_tree_add_item(enrp_tree, hf_message_flags, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ flags_tree = proto_item_add_subtree(flags_item, ett_enrp_flags);
+ proto_tree_add_item(enrp_tree, hf_message_length, message_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ switch (type) {
+ case PEER_PRESENCE_MESSAGE_TYPE:
+ dissect_peer_presence_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_NAME_TABLE_REQUEST_MESSAGE_TYPE:
+ dissect_peer_name_table_request_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_NAME_TABLE_RESPONSE_MESSAGE_TYPE:
+ dissect_peer_name_table_response_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_NAME_UPDATE_MESSAGE_TYPE:
+ dissect_peer_name_update_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_LIST_REQUEST_MESSAGE_TYPE:
+ dissect_peer_list_request_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_LIST_RESPONSE_MESSAGE_TYPE:
+ dissect_peer_list_response_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_INIT_TAKEOVER_MESSAGE_TYPE:
+ dissect_peer_init_takeover_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_INIT_TAKEOVER_ACK_MESSAGE_TYPE:
+ dissect_peer_init_takeover_ack_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_TAKEOVER_SERVER_MESSAGE_TYPE:
+ dissect_peer_init_takeover_server_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_OWNERSHIP_CHANGE_MESSAGE_TYPE:
+ dissect_peer_ownership_change_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ case PEER_ERROR_MESSAGE_TYPE:
+ dissect_peer_error_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ default:
+ dissect_unknown_message(message_tvb, enrp_tree, flags_tree);
+ break;
+ }
+ }
+}
+
+static void
+dissect_enrp(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *enrp_item;
+ proto_tree *enrp_tree;
+
+ /* make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ENRP");
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the enrp protocol tree */
+ enrp_item = proto_tree_add_item(tree, proto_enrp, message_tvb, 0, -1, FALSE);
+ enrp_tree = proto_item_add_subtree(enrp_item, ett_enrp);
+ } else {
+ enrp_tree = NULL;
+ };
+ /* dissect the message */
+ dissect_enrp_message(message_tvb, pinfo, enrp_tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_enrp(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_message_type, { "Type", "enrp.message_type", FT_UINT8, BASE_DEC, VALS(message_type_values), 0x0, "", HFILL } },
+ { &hf_message_flags, { "Flags", "enrp.message_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_message_length, { "Length", "enrp.message_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_message_value, { "Value", "enrp.message_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_cause_code, { "Cause code", "enrp.cause_code", FT_UINT16, BASE_HEX, VALS(cause_code_values), 0x0, "", HFILL } },
+ { &hf_cause_length, { "Cause length", "enrp.cause_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause_info, { "Cause info", "enrp.cause_info", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_cause_padding, { "Padding", "enrp.cause_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_type, { "Parameter Type", "enrp.parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_type_values), 0x0, "", HFILL } },
+ { &hf_parameter_length, { "Parameter length", "enrp.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_value, { "Parameter value", "enrp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_padding, { "Padding", "enrp.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_ipv4_address, { "IP Version 4 address", "enrp.ipv4_address", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_ipv6_address, { "IP Version 6 address", "enrp.ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_sctp_port, { "Port", "enrp.sctp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_transport_use, { "Transport use", "enrp.transport_use", FT_UINT16, BASE_DEC, VALS(transport_use_values), 0x0, "", HFILL } },
+ { &hf_tcp_port, { "Port", "enrp.tcp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_udp_port, { "Port", "enrp.udp_transport_port", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_udp_reserved, { "Reserved", "enrp.udp_transport_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_policy_type, { "Policy type", "enrp.pool_member_slection_policy_type", FT_UINT8, BASE_DEC, VALS(policy_type_values), 0x0, "", HFILL } },
+ { &hf_policy_value, { "Policy value", "enrp.pool_member_slection_policy_value", FT_INT24, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_pool_handle, { "Pool handle", "enrp.pool_handle_pool_handle", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_pe_pe_identifier, { "PE identifier", "enrp.pool_element_pe_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_home_enrp_id, { "Home ENRP server identifier", "enrp.pool_element_home_enrp_server_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_reg_life, { "Registration life", "enrp.pool_element_registration_life", FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_server_identifier, { "Server identifier", "enrp.server_information_server_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_m_bit, { "M-Bit", "enrp.server_information_m_bit", FT_BOOLEAN, 32, NULL, M_BIT_MASK, "", HFILL } },
+ { &hf_reserved, { "Reserved", "enrp.server_information_reserved", FT_UINT32, BASE_HEX, NULL, RESERVED_MASK, "", HFILL } },
+ { &hf_cookie, { "Cookie", "enrp.cookie", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_pe_identifier, { "PE identifier", "enrp.pe_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_pe_checksum, { "PE checksum", "enrp.pe_checksum", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_sender_servers_id, { "Sender server's ID", "enrp.sender_servers_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_receiver_servers_id, { "Receiver server's ID", "enrp.receiver_servers_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_target_servers_id, { "Target server's ID", "enrp.target_servers_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_update_action, { "Update action", "enrp.update_action", FT_UINT16, BASE_DEC, VALS(update_action_values), 0x0, "", HFILL } },
+ { &hf_pmu_reserved, { "Reserved", "enrp.reserved", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_reply_required_bit, { "R bit", "enrp.r_bit", FT_BOOLEAN, 8, TFS(&reply_required_bit_value), REPLY_REQUIRED_BIT_MASK, "", HFILL } },
+ { &hf_own_children_only_bit, { "W bit", "enrp.w_bit", FT_BOOLEAN, 8, TFS(&own_children_only_bit_value), OWN_CHILDREN_ONLY_BIT_MASK, "", HFILL } },
+ { &hf_more_to_send_bit, { "M bit", "enrp.m_bit", FT_BOOLEAN, 8, TFS(&more_to_send_bit_value), MORE_TO_SEND_BIT_MASK, "", HFILL } },
+ { &hf_reject_bit, { "R bit", "enrp.r_bit", FT_BOOLEAN, 8, TFS(&reject_bit_value), REJECT_BIT_MASK, "", HFILL } },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_enrp,
+ &ett_enrp_parameter,
+ &ett_enrp_cause,
+ &ett_enrp_flags,
+ };
+
+ /* Register the protocol name and description */
+ proto_enrp = proto_register_protocol("Endpoint Name Resolution Protocol", "ENRP", "enrp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_enrp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_enrp(void)
+{
+ dissector_handle_t enrp_handle;
+
+ enrp_handle = create_dissector_handle(dissect_enrp, proto_enrp);
+ dissector_add("sctp.ppi", ENRP_PAYLOAD_PROTOCOL_ID, enrp_handle);
+}
diff --git a/epan/dissectors/packet-esis.c b/epan/dissectors/packet-esis.c
new file mode 100644
index 0000000000..b923067719
--- /dev/null
+++ b/epan/dissectors/packet-esis.c
@@ -0,0 +1,452 @@
+/* packet-esis.c
+ * Routines for ISO/OSI End System to Intermediate System
+ * Routing Exchange Protocol ISO 9542.
+ *
+ * $Id$
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "nlpid.h"
+#include "packet-osi.h"
+#include "packet-osi-options.h"
+#include "packet-esis.h"
+
+
+/* esis base header */
+static int proto_esis = -1;
+
+static int hf_esis_nlpi = -1;
+static int hf_esis_length = -1;
+static int hf_esis_version = -1;
+static int hf_esis_reserved = -1;
+static int hf_esis_type = -1;
+static int hf_esis_holdtime = -1;
+static int hf_esis_checksum = -1;
+
+static gint ett_esis = -1;
+static gint ett_esis_area_addr = -1;
+
+static const value_string esis_vals[] = {
+ { ESIS_ESH_PDU, "ES HELLO"},
+ { ESIS_ISH_PDU, "IS HELLO"},
+ { ESIS_RD_PDU, "RD REQUEST"},
+ { 0, NULL} };
+
+/* internal prototypes */
+
+static void esis_dissect_esh_pdu( guint8 len, tvbuff_t *tvb,
+ proto_tree *treepd);
+static void esis_dissect_ish_pdu( guint8 len, tvbuff_t *tvb,
+ proto_tree *tree);
+static void esis_dissect_redirect_pdu( guint8 len, tvbuff_t *tvb,
+ proto_tree *tree);
+
+/* ################## Descriptions ###########################################*/
+/* Parameters for the ESH PDU
+ * Source Address Parameter:
+ *
+ * Octet: Length: Parameter Type:
+ * 10 1 Number of Source Adresses ( NSAPs served by this Network
+ * 11 1 Source Address Length Indicator ( SAL ) # Entity )
+ * 12-m-1 variable Source Address ( NSAP )
+ * m Options, dissected in osi.c
+ *
+ *
+ * Parameter for the ISH PDU:
+ * Network Entity Title Parameter:
+ *
+ * Octet: Length: Parameter Type:
+ * 10 1 Network Entity Title Length Indicator ( NETL )
+ * 11-m-1 variable Network Entity Title ( NET )
+ * m Options, dissected in osi.c
+ *
+ *
+ * Parameter for the RD PDU:
+ * When re-directed to an IS:
+ *
+ * Octet: Length: Parameter Type:
+ * 10 1 Destination Address Length Indicator ( DAL )
+ * 11>m-1 variable Destination Address ( DA )
+ * m 1 Subnetwork Address Length Indicator ( BSNPAL )
+ * m+1>n-1 variable Subnetwork Address ( BSNPA )
+ * n 1 Network Entity Title Length Indicator ( NETL )
+ * n+1>p-1 variable Network Entity Title ( NET )
+ * p Options, dissected in osi.c
+ *
+ *
+ * Parameter for the RD PDU:
+ * When re-directed to an ES:
+ *
+ * Octet: Length: Parameter Type:
+ * 10 1 Destination Address Length Indicator ( DAL )
+ * 11>m-1 variable Destination Address ( DA )
+ * m 1 Subnetwork Address Length Indicator ( BSNPAL )
+ * m+1>n-1 variable Subnetwork Address ( BSNPA )
+ * n 1 Network Entity Title Length Indicator ( NETL ) == 0
+ * n+1 Options, dissected in osi.c
+ *
+ */
+
+/* ############################ Tool Functions ############################## */
+
+
+/* ############################## Dissection Functions ###################### */
+/*
+ * Name: dissect_esis_unknown()
+ *
+ * Description:
+ * There was some error in the protocol and we are in unknown space
+ * here. Add a tree item to cover the error and go on. Note
+ * that we make sure we don't go off the end of the bleedin packet here!
+ *
+ * This is just a copy of isis.c and isis.h, so I keep the stuff also
+ * and adapt the names to cover possible protocol errors! Ive really no
+ * idea wether I need this or not.
+ *
+ * Input
+ * tvbuff_t * : tvbuff with packet data.
+ * proto_tree * : tree of display data. May be NULL.
+ * char * : format text
+ * subsequent args : arguments to format
+ *
+ * Output:
+ * void (may modify proto tree)
+ */
+static void
+esis_dissect_unknown( tvbuff_t *tvb, proto_tree *tree, char *fmat, ...){
+ va_list ap;
+
+ va_start(ap, fmat);
+ proto_tree_add_text_valist(tree, tvb, 0, -1, fmat, ap);
+ va_end(ap);
+}
+
+
+static void
+esis_dissect_esh_pdu( guint8 len, tvbuff_t *tvb, proto_tree *tree) {
+ proto_tree *esis_area_tree;
+ int offset = 0;
+ int no_sa = 0;
+ int sal = 0;
+
+ proto_item *ti;
+
+ if (tree) {
+ offset += ESIS_HDR_FIXED_LENGTH;
+
+ no_sa = tvb_get_guint8(tvb, offset);
+ len -= 1;
+
+ ti = proto_tree_add_text( tree, tvb, offset, -1,
+ "Number of Source Addresses (SA, Format: NSAP) : %u", no_sa );
+ offset++;
+
+ esis_area_tree = proto_item_add_subtree( ti, ett_esis_area_addr );
+ while ( no_sa-- > 0 ) {
+ sal = (int) tvb_get_guint8(tvb, offset);
+ offset++;
+ proto_tree_add_text(esis_area_tree, tvb, offset, 1, "SAL: %2u Octets", sal);
+ proto_tree_add_text(esis_area_tree, tvb, offset + 1, sal,
+ " SA: %s",
+ print_nsap_net( tvb_get_ptr(tvb, offset, sal), sal ) );
+ offset += sal;
+ len -= ( sal + 1 );
+ }
+ dissect_osi_options( len, tvb, offset, tree );
+ }
+} /* esis_dissect_esh_pdu */
+
+static void
+esis_dissect_ish_pdu( guint8 len, tvbuff_t *tvb, proto_tree *tree) {
+
+ int offset = 0;
+ int netl = 0;
+
+ if (tree) {
+ offset += ESIS_HDR_FIXED_LENGTH;
+
+ netl = (int) tvb_get_guint8(tvb, offset);
+ proto_tree_add_text( tree, tvb, offset, netl + 1,
+ "### Network Entity Title Section ###");
+ proto_tree_add_text( tree, tvb, offset++, 1, "NETL: %2u Octets", netl);
+ proto_tree_add_text( tree, tvb, offset, netl,
+ " NET: %s",
+ print_nsap_net( tvb_get_ptr(tvb, offset, netl), netl ) );
+ offset += netl;
+ len -= ( netl + 1 );
+
+ dissect_osi_options( len, tvb, offset, tree );
+ }
+}
+
+static void
+esis_dissect_redirect_pdu( guint8 len, tvbuff_t *tvb, proto_tree *tree) {
+
+ int offset = 0;
+ int tmpl = 0;
+
+ if (tree) {
+ offset += ESIS_HDR_FIXED_LENGTH;
+
+ tmpl = (int) tvb_get_guint8(tvb, offset);
+ proto_tree_add_text( tree, tvb, offset, tmpl + 1,
+ "### Destination Address Section ###" );
+ proto_tree_add_text( tree, tvb, offset++, 1, "DAL: %2u Octets", tmpl);
+ proto_tree_add_text( tree, tvb, offset, tmpl,
+ " DA : %s",
+ print_nsap_net( tvb_get_ptr(tvb, offset, tmpl), tmpl ) );
+ offset += tmpl;
+ len -= ( tmpl + 1 );
+ tmpl = (int) tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text( tree, tvb, offset, tmpl + 1,
+ "### Subnetwork Address Section ###");
+ proto_tree_add_text( tree, tvb, offset++, 1, "BSNPAL: %2u Octets", tmpl);
+ proto_tree_add_text( tree, tvb, offset, tmpl,
+ " BSNPA: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, tmpl), tmpl ) );
+ offset += tmpl;
+ len -= ( tmpl + 1 );
+ tmpl = (int) tvb_get_guint8(tvb, offset);
+
+ if ( 0 == tmpl ) {
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "### No Network Entity Title Section ###" );
+ offset++;
+ len--;
+ }
+ else {
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "### Network Entity Title Section ###" );
+ proto_tree_add_text( tree, tvb, offset++, 1, "NETL: %2u Octets", tmpl );
+ proto_tree_add_text( tree, tvb, offset, tmpl,
+ " NET: %s",
+ print_nsap_net( tvb_get_ptr(tvb, offset, tmpl), tmpl ) );
+ offset += tmpl;
+ len -= ( tmpl + 1 );
+ }
+ dissect_osi_options( len, tvb, offset, tree );
+ }
+}
+
+
+/*
+ * Name: dissect_esis()
+ *
+ * Description:
+ * Main entry area for esis de-mangling. This will build the
+ * main esis tree data and call the sub-protocols as needed.
+ *
+ * Input:
+ * tvbuff * : tvbuff referring to packet data
+ * packet_info * : info for current packet
+ * proto_tree * : tree of display data. May be NULL.
+ *
+ * Output:
+ * void, but we will add to the proto_tree if it is not NULL.
+ */
+static void
+dissect_esis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ char *pdu_type_string = NULL;
+ char *pdu_type_format_string = "PDU Type : %s (R:%s%s%s)";
+ esis_hdr_t ehdr;
+ proto_item *ti;
+ proto_tree *esis_tree = NULL;
+ guint8 variable_len;
+ guint tmp_uint = 0;
+ char *cksum_status;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESIS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb, (guint8 *)&ehdr, 0, sizeof ehdr);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_esis, tvb, 0, -1, FALSE);
+ esis_tree = proto_item_add_subtree(ti, ett_esis);
+
+ if (ehdr.esis_version != ESIS_REQUIRED_VERSION){
+ esis_dissect_unknown(tvb, esis_tree,
+ "Unknown ESIS version (%u vs %u)",
+ ehdr.esis_version, ESIS_REQUIRED_VERSION );
+ return;
+ }
+
+ if (ehdr.esis_length < ESIS_HDR_FIXED_LENGTH) {
+ esis_dissect_unknown(tvb, esis_tree,
+ "Bogus ESIS length (%u, must be >= %u)",
+ ehdr.esis_length, ESIS_HDR_FIXED_LENGTH );
+ return;
+ }
+ proto_tree_add_uint( esis_tree, hf_esis_nlpi, tvb, 0, 1, ehdr.esis_nlpi );
+ proto_tree_add_uint( esis_tree, hf_esis_length, tvb,
+ 1, 1, ehdr.esis_length );
+ proto_tree_add_uint( esis_tree, hf_esis_version, tvb, 2, 1,
+ ehdr.esis_version );
+ proto_tree_add_uint( esis_tree, hf_esis_reserved, tvb, 3, 1,
+ ehdr.esis_reserved );
+
+ pdu_type_string = val_to_str(ehdr.esis_type&OSI_PDU_TYPE_MASK,
+ esis_vals, "Unknown (0x%x)");
+
+ proto_tree_add_uint_format( esis_tree, hf_esis_type, tvb, 4, 1,
+ ehdr.esis_type,
+ pdu_type_format_string,
+ pdu_type_string,
+ (ehdr.esis_type&BIT_8) ? "1" : "0",
+ (ehdr.esis_type&BIT_7) ? "1" : "0",
+ (ehdr.esis_type&BIT_6) ? "1" : "0");
+
+ tmp_uint = pntohs( ehdr.esis_holdtime );
+ proto_tree_add_uint_format(esis_tree, hf_esis_holdtime, tvb, 5, 2,
+ tmp_uint, "Holding Time : %u seconds",
+ tmp_uint );
+
+ tmp_uint = pntohs( ehdr.esis_checksum );
+
+ switch (calc_checksum( tvb, 0, ehdr.esis_length, tmp_uint )) {
+
+ case NO_CKSUM:
+ cksum_status = "Not Used";
+ break;
+
+ case DATA_MISSING:
+ cksum_status = "Not checkable - not all of packet was captured";
+ break;
+
+ case CKSUM_OK:
+ cksum_status = "Is good";
+ break;
+
+ case CKSUM_NOT_OK:
+ cksum_status = "Is wrong";
+ break;
+
+ default:
+ cksum_status = NULL;
+ g_assert_not_reached();
+ }
+ proto_tree_add_uint_format( esis_tree, hf_esis_checksum, tvb, 7, 2,
+ tmp_uint, "Checksum : 0x%x ( %s )",
+ tmp_uint, cksum_status );
+ }
+
+
+ /*
+ * Let us make sure we use the same names for all our decodes
+ * here. First, dump the name into info column, and THEN
+ * dispatch the sub-type.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str( ehdr.esis_type&OSI_PDU_TYPE_MASK, esis_vals,
+ "Unknown (0x%x)" ) );
+ }
+
+ variable_len = ehdr.esis_length - ESIS_HDR_FIXED_LENGTH;
+
+ switch (ehdr.esis_type & OSI_PDU_TYPE_MASK) {
+ case ESIS_ESH_PDU:
+ esis_dissect_esh_pdu( variable_len, tvb, esis_tree);
+ break;
+ case ESIS_ISH_PDU:
+ esis_dissect_ish_pdu( variable_len, tvb, esis_tree);
+ break;
+ case ESIS_RD_PDU:
+ esis_dissect_redirect_pdu( variable_len, tvb, esis_tree);
+ break;
+ default:
+ esis_dissect_unknown(tvb, esis_tree,
+ "Unknown ESIS packet type 0x%x",
+ ehdr.esis_type & OSI_PDU_TYPE_MASK );
+ }
+} /* dissect_esis */
+
+
+/*
+ * Name: proto_register_esis()
+ *
+ * Description:
+ * main register for esis protocol set. We register some display
+ * formats and the protocol module variables.
+ *
+ * NOTE: this procedure to autolinked by the makefile process that
+ * builds register.c
+ *
+ * Input:
+ * void
+ *
+ * Output:
+ * void
+ */
+void
+proto_register_esis(void) {
+ static hf_register_info hf[] = {
+ { &hf_esis_nlpi,
+ { "Network Layer Protocol Identifier", "esis.nlpi",
+ FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "", HFILL }},
+ { &hf_esis_length,
+ { "PDU Length ", "esis.length", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_esis_version,
+ { "Version (==1) ", "esis.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_esis_reserved,
+ { "Reserved(==0) ", "esis.res", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_esis_type,
+ { "PDU Type ", "esis.type", FT_UINT8, BASE_DEC, VALS(esis_vals),
+ 0xff, "", HFILL }},
+ { &hf_esis_holdtime,
+ { "Holding Time ", "esis.htime", FT_UINT16, BASE_DEC, NULL, 0x0, " s", HFILL }},
+ { &hf_esis_checksum,
+ { "Checksum ", "esis.chksum", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }}
+ };
+ /*
+ *
+ *
+ */
+ static gint *ett[] = {
+ &ett_esis,
+ &ett_esis_area_addr,
+ };
+
+ proto_esis = proto_register_protocol( PROTO_STRING_ESIS, "ESIS", "esis");
+ proto_register_field_array(proto_esis, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_esis(void)
+{
+ dissector_handle_t esis_handle;
+
+ esis_handle = create_dissector_handle(dissect_esis, proto_esis);
+ register_dissector("esis", dissect_esis, proto_esis);
+ dissector_add("osinl", NLPID_ISO9542_ESIS, esis_handle);
+}
diff --git a/epan/dissectors/packet-esis.h b/epan/dissectors/packet-esis.h
new file mode 100644
index 0000000000..f2231c68db
--- /dev/null
+++ b/epan/dissectors/packet-esis.h
@@ -0,0 +1,60 @@
+/* packet-esis.h
+ * Defines and such for ESIS protocol decode.
+ *
+ * $Id$
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ */
+
+#ifndef _PACKET_ESIS_H
+#define _PACKET_ESIS_H
+
+/* The version we support is 1 */
+#define ESIS_REQUIRED_VERSION 1
+
+/* ESIS PDU types */
+#define ESIS_ESH_PDU 02
+#define ESIS_ISH_PDU 04
+#define ESIS_RD_PDU 06
+
+/* The length of the fixed part */
+#define ESIS_HDR_FIXED_LENGTH 9
+
+/* Inline Defines for masking */
+#define esis_type esis_type_reserved&OSI_PDU_TYPE_MASK
+#define esis_r8 esis_type_reserved&BIT_8
+#define esis_r7 esis_type_reserved&BIT_7
+#define esis_r6 esis_type_reserved&BIT_6
+
+/* The fixed part (9 octets) of the ESIS protocol header */
+typedef struct {
+ guint8 esis_nlpi; /* Network Layer Protocol Identifier == 0x82 */
+ guint8 esis_length; /* Header ( PDU too, NoData ) length in octets */
+ guint8 esis_version; /* ISIS version, must be 0x01 */
+ guint8 esis_reserved; /* reserved byte, must be 0 */
+ guint8 esis_type_reserved; /* packet type & MS-Bits (8-6) reserved */
+ guint8 esis_holdtime[2]; /* Maximum time (sec) this PDU is valid */
+ guint8 esis_checksum[2]; /* Computed on whole PDU Header, 0 means ignore */
+} esis_hdr_t;
+
+#endif /* _PACKET_ESIS_H */
diff --git a/epan/dissectors/packet-eth.c b/epan/dissectors/packet-eth.c
new file mode 100644
index 0000000000..89b49b6d30
--- /dev/null
+++ b/epan/dissectors/packet-eth.c
@@ -0,0 +1,471 @@
+/* packet-eth.c
+ * Routines for ethernet packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "etypes.h"
+#include <epan/resolv.h>
+#include "packet-eth.h"
+#include "packet-ieee8023.h"
+#include "packet-ipx.h"
+#include "packet-isl.h"
+#include "packet-llc.h"
+#include "crc32.h"
+#include "tap.h"
+
+/* Interpret capture file as FW1 monitor file */
+static gboolean eth_interpret_as_fw1_monitor = FALSE;
+
+/* protocols and header fields */
+static int proto_eth = -1;
+static int hf_eth_dst = -1;
+static int hf_eth_src = -1;
+static int hf_eth_len = -1;
+static int hf_eth_type = -1;
+static int hf_eth_addr = -1;
+static int hf_eth_trailer = -1;
+
+static gint ett_ieee8023 = -1;
+static gint ett_ether2 = -1;
+
+static dissector_handle_t isl_handle;
+static dissector_handle_t fw1_handle;
+static heur_dissector_list_t heur_subdissector_list;
+
+static int eth_tap = -1;
+
+#define ETH_HEADER_SIZE 14
+
+/* These are the Netware-ish names for the different Ethernet frame types.
+ EthernetII: The ethernet with a Type field instead of a length field
+ Ethernet802.2: An 802.3 header followed by an 802.2 header
+ Ethernet802.3: A raw 802.3 packet. IPX/SPX can be the only payload.
+ There's no 802.2 hdr in this.
+ EthernetSNAP: Basically 802.2, just with 802.2SNAP. For our purposes,
+ there's no difference between 802.2 and 802.2SNAP, since we just
+ pass it down to the LLC dissector. -- Gilbert
+*/
+#define ETHERNET_II 0
+#define ETHERNET_802_2 1
+#define ETHERNET_802_3 2
+#define ETHERNET_SNAP 3
+
+void
+capture_eth(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ guint16 etype, length;
+ int ethhdr_type; /* the type of ethernet frame */
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, ETH_HEADER_SIZE)) {
+ ld->other++;
+ return;
+ }
+
+ etype = pntohs(&pd[offset+12]);
+
+ /*
+ * If the type/length field is <= the maximum 802.3 length,
+ * and is not zero, this is an 802.3 frame, and it's a length
+ * field; it might be an Novell "raw 802.3" frame, with no
+ * 802.2 LLC header, or it might be a frame with an 802.2 LLC
+ * header.
+ *
+ * If the type/length field is > the maximum 802.3 length,
+ * this is an Ethernet II frame, and it's a type field.
+ *
+ * If the type/length field is zero (ETHERTYPE_UNK), this is
+ * a frame used internally by the Cisco MDS switch to contain
+ * Fibre Channel ("Vegas"). We treat that as an Ethernet II
+ * frame; the dissector for those frames registers itself with
+ * an ethernet type of ETHERTYPE_UNK.
+ */
+ if (etype <= IEEE_802_3_MAX_LEN && etype != ETHERTYPE_UNK) {
+ length = etype;
+
+ /* Is there an 802.2 layer? I can tell by looking at the first 2
+ bytes after the 802.3 header. If they are 0xffff, then what
+ follows the 802.3 header is an IPX payload, meaning no 802.2.
+ (IPX/SPX is they only thing that can be contained inside a
+ straight 802.3 packet). A non-0xffff value means that there's an
+ 802.2 layer inside the 802.3 layer */
+ if (pd[offset+14] == 0xff && pd[offset+15] == 0xff) {
+ ethhdr_type = ETHERNET_802_3;
+ }
+ else {
+ ethhdr_type = ETHERNET_802_2;
+ }
+
+ /* Oh, yuck. Cisco ISL frames require special interpretation of the
+ destination address field; fortunately, they can be recognized by
+ checking the first 5 octets of the destination address, which are
+ 01-00-0C-00-00 for ISL frames. */
+ if (pd[offset] == 0x01 && pd[offset+1] == 0x00 && pd[offset+2] == 0x0C
+ && pd[offset+3] == 0x00 && pd[offset+4] == 0x00) {
+ capture_isl(pd, offset, len, ld);
+ return;
+ }
+
+ /* Convert the LLC length from the 802.3 header to a total
+ frame length, by adding in the size of any data that preceded
+ the Ethernet header, and adding in the Ethernet header size,
+ and set the payload and captured-payload lengths to the minima
+ of the total length and the frame lengths. */
+ length += offset + ETH_HEADER_SIZE;
+ if (len > length)
+ len = length;
+ } else {
+ ethhdr_type = ETHERNET_II;
+ }
+ offset += ETH_HEADER_SIZE;
+
+ switch (ethhdr_type) {
+ case ETHERNET_802_3:
+ capture_ipx(ld);
+ break;
+ case ETHERNET_802_2:
+ capture_llc(pd, offset, len, ld);
+ break;
+ case ETHERNET_II:
+ capture_ethertype(etype, pd, offset, len, ld);
+ break;
+ }
+}
+
+static void
+dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int fcs_len)
+{
+ proto_item *ti;
+ eth_hdr *ehdr;
+ volatile gboolean is_802_2;
+ proto_tree *volatile fh_tree = NULL;
+ const char *src_addr, *dst_addr;
+ static eth_hdr ehdrs[4];
+ static int ehdr_num=0;
+
+ ehdr_num++;
+ if(ehdr_num>=4){
+ ehdr_num=0;
+ }
+ ehdr=&ehdrs[ehdr_num];
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Ethernet");
+
+ src_addr=tvb_get_ptr(tvb, 6, 6);
+ SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src_addr);
+ SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src_addr);
+ SET_ADDRESS(&ehdr->src, AT_ETHER, 6, src_addr);
+ dst_addr=tvb_get_ptr(tvb, 0, 6);
+ SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst_addr);
+ SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst_addr);
+ SET_ADDRESS(&ehdr->dst, AT_ETHER, 6, dst_addr);
+
+ ehdr->type = tvb_get_ntohs(tvb, 12);
+
+ /*
+ * In case the packet is a non-Ethernet packet inside
+ * Ethernet framing, allow heuristic dissectors to take
+ * a first look before we assume that it's actually an
+ * Ethernet packet.
+ */
+ if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree))
+ goto end_of_eth;
+
+ /*
+ * If the type/length field is <= the maximum 802.3 length,
+ * and is not zero, this is an 802.3 frame, and it's a length
+ * field; it might be an Novell "raw 802.3" frame, with no
+ * 802.2 LLC header, or it might be a frame with an 802.2 LLC
+ * header.
+ *
+ * If the type/length field is > the maximum 802.3 length,
+ * this is an Ethernet II frame, and it's a type field.
+ *
+ * If the type/length field is zero (ETHERTYPE_UNK), this is
+ * a frame used internally by the Cisco MDS switch to contain
+ * Fibre Channel ("Vegas"). We treat that as an Ethernet II
+ * frame; the dissector for those frames registers itself with
+ * an ethernet type of ETHERTYPE_UNK.
+ */
+ if (ehdr->type <= IEEE_802_3_MAX_LEN && ehdr->type != ETHERTYPE_UNK) {
+ /* Oh, yuck. Cisco ISL frames require special interpretation of the
+ destination address field; fortunately, they can be recognized by
+ checking the first 5 octets of the destination address, which are
+ 01-00-0C-00-00 for ISL frames. */
+ if ( tvb_get_guint8(tvb, 0) == 0x01 &&
+ tvb_get_guint8(tvb, 1) == 0x00 &&
+ tvb_get_guint8(tvb, 2) == 0x0C &&
+ tvb_get_guint8(tvb, 3) == 0x00 &&
+ tvb_get_guint8(tvb, 4) == 0x00 ) {
+ call_dissector(isl_handle, tvb, pinfo, tree);
+ goto end_of_eth;
+ }
+
+ /* Is there an 802.2 layer? I can tell by looking at the first 2
+ bytes after the 802.3 header. If they are 0xffff, then what
+ follows the 802.3 header is an IPX payload, meaning no 802.2.
+ (IPX/SPX is they only thing that can be contained inside a
+ straight 802.3 packet). A non-0xffff value means that there's an
+ 802.2 layer inside the 802.3 layer */
+ is_802_2 = TRUE;
+ TRY {
+ if (tvb_get_ntohs(tvb, 14) == 0xffff) {
+ is_802_2 = FALSE;
+ }
+ }
+ CATCH2(BoundsError, ReportedBoundsError) {
+ ; /* do nothing */
+
+ }
+ ENDTRY;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "IEEE 802.3 Ethernet %s",
+ (is_802_2 ? "" : "Raw "));
+ }
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
+ "IEEE 802.3 Ethernet %s", (is_802_2 ? "" : "Raw "));
+
+ fh_tree = proto_item_add_subtree(ti, ett_ieee8023);
+ }
+
+ proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr);
+ proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr);
+
+/* add items for eth.addr filter */
+ proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 0, 6, dst_addr);
+ proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 6, 6, src_addr);
+
+ dissect_802_3(ehdr->type, is_802_2, tvb, ETH_HEADER_SIZE, pinfo, tree, fh_tree,
+ hf_eth_len, hf_eth_trailer, fcs_len);
+ } else {
+ if (eth_interpret_as_fw1_monitor) {
+ call_dissector(fw1_handle, tvb, pinfo, tree);
+ goto end_of_eth;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Ethernet II");
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
+ "Ethernet II, Src: %s, Dst: %s",
+ ether_to_str(src_addr), ether_to_str(dst_addr));
+
+ fh_tree = proto_item_add_subtree(ti, ett_ether2);
+ }
+
+ proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr);
+ proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr);
+/* add items for eth.addr filter */
+ proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 0, 6, dst_addr);
+ proto_tree_add_ether_hidden(fh_tree, hf_eth_addr, tvb, 6, 6, src_addr);
+
+ ethertype(ehdr->type, tvb, ETH_HEADER_SIZE, pinfo, tree, fh_tree, hf_eth_type,
+ hf_eth_trailer, fcs_len);
+ }
+
+end_of_eth:
+ tap_queue_packet(eth_tap, pinfo, ehdr);
+ return;
+}
+
+/*
+ * Add an Ethernet trailer - which, for some captures, might be the FCS
+ * rather than a pad-to-60-bytes trailer.
+ *
+ * If fcs_len is 0, we assume the frame has no FCS; if it's 4, we assume
+ * it has an FCS; if it's anything else (such as -1, which means "maybe
+ * it does, maybe it doesn't"), we try to infer whether it has an FCS.
+ */
+void
+add_ethernet_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
+ tvbuff_t *trailer_tvb, int fcs_len)
+{
+ /* If there're some bytes left over, show those bytes as a trailer.
+
+ However, if the Ethernet frame was claimed to have had 64 or more
+ bytes - i.e., it was at least an FCS worth of data longer than
+ the minimum payload size - assume the last 4 bytes of the trailer
+ are an FCS. */
+ if (trailer_tvb && fh_tree) {
+ guint trailer_length, trailer_reported_length;
+ gboolean has_fcs = FALSE;
+
+ trailer_length = tvb_length(trailer_tvb);
+ trailer_reported_length = tvb_reported_length(trailer_tvb);
+ if (fcs_len != 0) {
+ /* If fcs_len is 4, we assume we definitely have an FCS.
+ Otherwise, then, if the frame is big enough that, if we
+ have a trailer, it probably inclues an FCS, and we have
+ enough space in the trailer for the FCS, we assume we
+ have an FCS.
+
+ "Big enough" means 64 bytes or more; any frame that big
+ needs no trailer, as there's no need to pad an Ethernet
+ packet past 60 bytes.
+
+ The trailer must be at least 4 bytes long to have enough
+ space for an FCS. */
+
+ if (fcs_len == 4 || (tvb_reported_length(tvb) >= 64 &&
+ trailer_reported_length >= 4)) {
+ /* Either we know we have an FCS, or we believe we have an FCS. */
+ if (trailer_length < trailer_reported_length) {
+ /* The packet is claimed to have enough data for a 4-byte FCS,
+ but we didn't capture all of the packet.
+ Slice off the 4-byte FCS from the reported length, and
+ trim the captured length so it's no more than the reported
+ length; that will slice off what of the FCS, if any, is
+ in the captured packet. */
+ trailer_reported_length -= 4;
+ if (trailer_length > trailer_reported_length)
+ trailer_length = trailer_reported_length;
+ has_fcs = TRUE;
+ } else {
+ /* We captured all of the packet, including what appears to
+ be a 4-byte FCS. Slice it off. */
+ trailer_length -= 4;
+ trailer_reported_length -= 4;
+ has_fcs = TRUE;
+ }
+ }
+ }
+ if (trailer_length != 0) {
+ proto_tree_add_item(fh_tree, trailer_id, trailer_tvb, 0,
+ trailer_length, FALSE);
+ }
+ if (has_fcs) {
+ guint32 sent_fcs = tvb_get_ntohl(trailer_tvb, trailer_length);
+ guint32 fcs = crc32_802_tvb(tvb, tvb_length(tvb) - 4);
+ if (fcs == sent_fcs) {
+ proto_tree_add_text(fh_tree, trailer_tvb, trailer_length, 4,
+ "Frame check sequence: 0x%08x (correct)",
+ sent_fcs);
+ } else {
+ proto_tree_add_text(fh_tree, trailer_tvb, trailer_length, 4,
+ "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
+ sent_fcs, fcs);
+ }
+ }
+ }
+}
+
+/* Called for the Ethernet Wiretap encapsulation type; pass the FCS length
+ reported to us. */
+static void
+dissect_eth_maybefcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_eth_common(tvb, pinfo, tree, pinfo->pseudo_header->eth.fcs_len);
+}
+
+/* Called by other dissectors - for now, we assume Ethernet encapsulated
+ inside other protocols doesn't include the FCS. */
+static void
+dissect_eth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_eth_common(tvb, pinfo, tree, 0);
+}
+
+void
+proto_register_eth(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_eth_dst,
+ { "Destination", "eth.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Destination Hardware Address", HFILL }},
+
+ { &hf_eth_src,
+ { "Source", "eth.src", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Source Hardware Address", HFILL }},
+
+ { &hf_eth_len,
+ { "Length", "eth.len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ /* registered here but handled in ethertype.c */
+ { &hf_eth_type,
+ { "Type", "eth.type", FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
+ "", HFILL }},
+ { &hf_eth_addr,
+ { "Source or Destination Address", "eth.addr", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Source or Destination Hardware Address", HFILL }},
+
+ { &hf_eth_trailer,
+ { "Trailer", "eth.trailer", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Ethernet Trailer or Checksum", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_ieee8023,
+ &ett_ether2,
+ };
+ module_t *eth_module;
+
+ proto_eth = proto_register_protocol("Ethernet", "Ethernet", "eth");
+ proto_register_field_array(proto_eth, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ register_heur_dissector_list("eth", &heur_subdissector_list);
+
+ /* Register configuration preferences */
+ eth_module = prefs_register_protocol(proto_eth, NULL);
+ prefs_register_bool_preference(eth_module, "interpret_as_fw1_monitor",
+ "Interpret as FireWall-1 monitor file",
+"Whether the capture file should be interpreted as a CheckPoint FireWall-1 monitor file",
+ &eth_interpret_as_fw1_monitor);
+
+ register_dissector("eth", dissect_eth, proto_eth);
+ eth_tap = register_tap("eth");
+}
+
+void
+proto_reg_handoff_eth(void)
+{
+ dissector_handle_t eth_handle, eth_maybefcs_handle;
+
+ /*
+ * Get a handle for the ISL dissector.
+ */
+ isl_handle = find_dissector("isl");
+ fw1_handle = find_dissector("fw1");
+
+ eth_maybefcs_handle = create_dissector_handle(dissect_eth_maybefcs,
+ proto_eth);
+ dissector_add("wtap_encap", WTAP_ENCAP_ETHERNET, eth_maybefcs_handle);
+
+ eth_handle = find_dissector("eth");
+ dissector_add("ethertype", ETHERTYPE_ETHBRIDGE, eth_handle);
+ dissector_add("chdlctype", ETHERTYPE_ETHBRIDGE, eth_handle);
+ dissector_add("gre.proto", ETHERTYPE_ETHBRIDGE, eth_handle);
+}
diff --git a/epan/dissectors/packet-eth.h b/epan/dissectors/packet-eth.h
new file mode 100644
index 0000000000..df190750d9
--- /dev/null
+++ b/epan/dissectors/packet-eth.h
@@ -0,0 +1,38 @@
+/* packet-eth.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_ETH_H__
+#define __PACKET_ETH_H__
+
+typedef struct _eth_hdr {
+ address dst;
+ address src;
+ guint16 type;
+} eth_hdr;
+
+void capture_eth(const guchar *, int, int, packet_counts *);
+
+void add_ethernet_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
+ tvbuff_t *trailer_tvb, int fcs_len);
+
+#endif
diff --git a/epan/dissectors/packet-etherip.c b/epan/dissectors/packet-etherip.c
new file mode 100644
index 0000000000..302a422579
--- /dev/null
+++ b/epan/dissectors/packet-etherip.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2003 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id$
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "ipproto.h"
+
+static int proto_etherip = -1;
+static int hf_etherip_ver = -1;
+
+static gint ett_etherip = -1;
+
+static dissector_handle_t eth_handle;
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+
+/*
+ * RFC 3378: EtherIP: Tunneling Ethernet Frames in IP Datagrams
+ *
+ * Bits 0-3: Protocol version
+ * Bits 4-15: Reserved for future use
+ */
+
+struct etheriphdr {
+ guint8 ver; /* version/reserved */
+ guint8 pad; /* required padding byte */
+};
+
+#define ETHERIP_VERS_MASK 0x0f
+
+
+static void
+dissect_etherip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct etheriphdr etheriph;
+ tvbuff_t *next_tvb;
+ proto_tree *etherip_tree;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ETHERIP");
+
+ /* Copy out the etherip header to insure alignment */
+ tvb_memcpy(tvb, (guint8 *)&etheriph, 0, sizeof(etheriph));
+
+ /* mask out reserved bits */
+ etheriph.ver &= ETHERIP_VERS_MASK;
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_etherip, tvb, 0,
+ sizeof(etheriph),
+ "EtherIP, Version %d",
+ etheriph.ver
+ );
+ etherip_tree = proto_item_add_subtree(ti, ett_etherip);
+
+ proto_tree_add_uint(etherip_tree, hf_etherip_ver, tvb,
+ offsetof(struct etheriphdr, ver), sizeof(etheriph.ver),
+ etheriph.ver);
+ }
+
+ /* Set the tvbuff for the payload after the header */
+ next_tvb = tvb_new_subset(tvb, sizeof(etheriph), -1, -1);
+
+ call_dissector(eth_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_register_etherip(void)
+{
+ static hf_register_info hf_etherip[] = {
+ { &hf_etherip_ver,
+ { "Version", "etherip.ver", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_etherip,
+ };
+
+ proto_etherip = proto_register_protocol("Ethernet over IP",
+ "ETHERIP", "etherip");
+ proto_register_field_array(proto_etherip, hf_etherip, array_length(hf_etherip));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("etherip", dissect_etherip, proto_etherip);
+}
+
+void
+proto_reg_handoff_etherip(void)
+{
+ dissector_handle_t etherip_handle;
+
+ eth_handle = find_dissector("eth");
+ etherip_handle = find_dissector("etherip");
+ dissector_add("ip.proto", IP_PROTO_ETHERIP, etherip_handle);
+}
diff --git a/epan/dissectors/packet-ethertype.c b/epan/dissectors/packet-ethertype.c
new file mode 100644
index 0000000000..ecbc6dc9cb
--- /dev/null
+++ b/epan/dissectors/packet-ethertype.c
@@ -0,0 +1,300 @@
+/* ethertype.c
+ * Routines for calling the right protocol for the ethertype.
+ *
+ * $Id$
+ *
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-eth.h"
+#include "packet-frame.h"
+#include "packet-ip.h"
+#include "packet-ipv6.h"
+#include "packet-ipx.h"
+#include "packet-vlan.h"
+#include "packet-vines.h"
+#include "etypes.h"
+#include "ppptypes.h"
+
+static dissector_table_t ethertype_dissector_table;
+
+static dissector_handle_t data_handle;
+
+const value_string etype_vals[] = {
+ {ETHERTYPE_IP, "IP" },
+ {ETHERTYPE_IPv6, "IPv6" },
+ {ETHERTYPE_X25L3, "X.25 Layer 3" },
+ {ETHERTYPE_ARP, "ARP" },
+ {ETHERTYPE_REVARP, "RARP" },
+ {ETHERTYPE_DEC_LB, "DEC LanBridge" },
+ {ETHERTYPE_ATALK, "Appletalk" },
+ {ETHERTYPE_SNA, "SNA-over-Ethernet" },
+ {ETHERTYPE_AARP, "AARP" },
+ {ETHERTYPE_IPX, "Netware IPX/SPX" },
+ {ETHERTYPE_VINES_IP, "Vines IP" },
+ {ETHERTYPE_VINES_ECHO, "Vines Echo" },
+ {ETHERTYPE_TRAIN, "Netmon Train" },
+ {ETHERTYPE_LOOP, "Loopback" }, /* Ethernet Loopback */
+ {ETHERTYPE_WCP, "Wellfleet Compression Protocol" },
+ {ETHERTYPE_ISMP, "Cabletron Interswitch Message Protocol" },
+ {ETHERTYPE_ISMP_TBFLOOD, "Cabletron SFVLAN 1.8 Tag-Based Flood" },
+ /* for ISMP, see RFC 2641, RFC 2642, RFC 2643 */
+ {ETHERTYPE_PPPOED, "PPPoE Discovery" },
+ {ETHERTYPE_PPPOES, "PPPoE Session" },
+ {ETHERTYPE_INTEL_ANS, "Intel ANS probe" },
+ {ETHERTYPE_MS_NLB_HEARTBEAT, "MS NLB heartbeat" },
+ {ETHERTYPE_VLAN, "802.1Q Virtual LAN" },
+ {ETHERTYPE_EAPOL, "802.1X Authentication" },
+ {ETHERTYPE_RSN_PREAUTH, "802.11i Pre-Authentication" },
+ {ETHERTYPE_MPLS, "MPLS label switched packet" },
+ {ETHERTYPE_MPLS_MULTI, "MPLS multicast label switched packet" },
+ {ETHERTYPE_3C_NBP_DGRAM, "3Com NBP Datagram" },
+ {ETHERTYPE_DEC, "DEC proto" },
+ {ETHERTYPE_DNA_DL, "DEC DNA Dump/Load" },
+ {ETHERTYPE_DNA_RC, "DEC DNA Remote Console" },
+ {ETHERTYPE_DNA_RT, "DEC DNA Routing" },
+ {ETHERTYPE_LAT, "DEC LAT" },
+ {ETHERTYPE_DEC_DIAG, "DEC Diagnostics" },
+ {ETHERTYPE_DEC_CUST, "DEC Customer use" },
+ {ETHERTYPE_DEC_SCA, "DEC LAVC/SCA" },
+ {ETHERTYPE_ETHBRIDGE, "Transparent Ethernet bridging" },
+ {ETHERTYPE_CGMP, "Cisco Group Management Protocol" },
+ {ETHERTYPE_SLOW_PROTOCOLS, "Slow Protocols" },
+ {ETHERTYPE_RTNET, "RTNET Protocol" },
+ {ETHERTYPE_RTCFG, "RTCFG Protocol" },
+ {ETHERTYPE_PROFINET, "PROFInet" },
+
+ /*
+ * NDISWAN on Windows translates Ethernet frames from higher-level
+ * protocols into PPP frames to hand to the PPP driver, and translates
+ * PPP frames from the PPP driver to hand to the higher-level protocols.
+ *
+ * Apparently the PPP driver, on at least some versions of Windows,
+ * passes frames for internal-to-PPP protocols up through NDISWAN;
+ * the protocol type field appears to be passed through unchanged
+ * (unlike what's done with, for example, the protocol type field
+ * for IP, which is mapped from its PPP value to its Ethernet value).
+ *
+ * This means that we may see, on Ethernet captures, frames for
+ * protocols internal to PPP, so we list as "Ethernet" protocol
+ * types the PPP protocol types we've seen.
+ */
+ {PPP_IPCP, "PPP IP Control Protocol" },
+ {PPP_LCP, "PPP Link Control Protocol" },
+ {PPP_PAP, "PPP Password Authentication Protocol" },
+ {PPP_CCP, "PPP Compression Control Protocol" },
+ {0, NULL } };
+
+static void add_dix_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
+ tvbuff_t *next_tvb, int offset_after_etype, guint length_before,
+ gint fcs_len);
+
+void
+capture_ethertype(guint16 etype, const guchar *pd, int offset, int len,
+ packet_counts *ld)
+{
+ switch (etype) {
+ case ETHERTYPE_ARP:
+ ld->arp++;
+ break;
+ case ETHERTYPE_IP:
+ capture_ip(pd, offset, len, ld);
+ break;
+ case ETHERTYPE_IPv6:
+ capture_ipv6(pd, offset, len, ld);
+ break;
+ case ETHERTYPE_IPX:
+ capture_ipx(ld);
+ break;
+ case ETHERTYPE_VLAN:
+ capture_vlan(pd, offset, len, ld);
+ break;
+ case ETHERTYPE_VINES_IP:
+ case ETHERTYPE_VINES_ECHO:
+ capture_vines(ld);
+ break;
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+void
+ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
+ packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
+ int etype_id, int trailer_id, int fcs_len)
+{
+ char *description;
+ tvbuff_t *next_tvb;
+ guint length_before;
+ volatile gboolean dissector_found;
+ const char *saved_proto;
+
+ /* Add the Ethernet type to the protocol tree */
+ if (tree) {
+ proto_tree_add_uint(fh_tree, etype_id, tvb,
+ offset_after_etype - 2, 2, etype);
+ }
+
+ /* Tvbuff for the payload after the Ethernet type. */
+ next_tvb = tvb_new_subset(tvb, offset_after_etype, -1, -1);
+
+ pinfo->ethertype = etype;
+
+ /* Remember how much data there is in it. */
+ length_before = tvb_reported_length(next_tvb);
+
+ /* Look for sub-dissector, and call it if found.
+ Catch exceptions, so that if the reported length of "next_tvb"
+ was reduced by some dissector before an exception was thrown,
+ we can still put in an item for the trailer. */
+ saved_proto = pinfo->current_proto;
+ TRY {
+ dissector_found = dissector_try_port(ethertype_dissector_table,
+ etype, next_tvb, pinfo, tree);
+ }
+ CATCH(BoundsError) {
+ /* Somebody threw BoundsError, which means that:
+
+ 1) a dissector was found, so we don't need to
+ dissect the payload as data or update the
+ protocol or info columns;
+
+ 2) dissecting the payload found that the packet was
+ cut off by a snapshot length before the end of
+ the payload. The trailer comes after the payload,
+ so *all* of the trailer is cut off, and we'll
+ just get another BoundsError if we add the trailer.
+
+ Therefore, we just rethrow the exception so it gets
+ reported; we don't dissect the trailer or do anything
+ else. */
+ RETHROW;
+ }
+ CATCH_ALL {
+ /* Somebody threw an exception other than BoundsError, which
+ means that a dissector was found, so we don't need to
+ dissect the payload as data or update the protocol or info
+ columns. We just show the exception and then drive on
+ to show the trailer, after noting that a dissector was
+ found and restoring the protocol value that was in effect
+ before we called the subdissector. */
+ show_exception(next_tvb, pinfo, tree, EXCEPT_CODE);
+ dissector_found = TRUE;
+ pinfo->current_proto = saved_proto;
+ }
+ ENDTRY;
+
+ if (!dissector_found) {
+ /* No sub-dissector found.
+ Label rest of packet as "Data" */
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+
+ /* Label protocol */
+ switch (etype) {
+
+ case ETHERTYPE_LOOP:
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "LOOP");
+ }
+ break;
+
+ default:
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x",
+ etype);
+ }
+ break;
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ description = match_strval(etype, etype_vals);
+ if (description) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ description);
+ }
+ }
+ }
+
+ add_dix_trailer(fh_tree, trailer_id, tvb, next_tvb, offset_after_etype,
+ length_before, fcs_len);
+}
+
+static void
+add_dix_trailer(proto_tree *fh_tree, int trailer_id, tvbuff_t *tvb,
+ tvbuff_t *next_tvb, int offset_after_etype, guint length_before,
+ gint fcs_len)
+{
+ guint length;
+ tvbuff_t *volatile trailer_tvb;
+
+ if (fh_tree == NULL)
+ return; /* we're not building a protocol tree */
+
+ if (trailer_id == -1)
+ return; /* our caller doesn't care about trailers */
+
+ /* OK, how much is there in that tvbuff now? */
+ length = tvb_reported_length(next_tvb);
+
+ /* If there's less than there was before, what's left is
+ a trailer. */
+ if (length < length_before) {
+ /*
+ * Is any of the padding present in the tvbuff?
+ */
+ if (tvb_offset_exists(tvb, offset_after_etype + length)) {
+ /*
+ * Yes - create a tvbuff for the padding.
+ */
+ trailer_tvb = tvb_new_subset(tvb,
+ offset_after_etype + length, -1, -1);
+ } else {
+ /*
+ * No - don't bother showing the trailer.
+ * XXX - show a Short Frame indication?
+ */
+ trailer_tvb = NULL;
+ }
+ } else
+ trailer_tvb = NULL; /* no trailer */
+
+ add_ethernet_trailer(fh_tree, trailer_id, tvb, trailer_tvb, fcs_len);
+}
+
+void
+proto_register_ethertype(void)
+{
+ /* subdissector code */
+ ethertype_dissector_table = register_dissector_table("ethertype",
+ "Ethertype", FT_UINT16, BASE_HEX);
+}
+
+void
+proto_reg_handoff_ethertype(void)
+{
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-fc.c b/epan/dissectors/packet-fc.c
new file mode 100644
index 0000000000..68253d2965
--- /dev/null
+++ b/epan/dissectors/packet-fc.c
@@ -0,0 +1,1454 @@
+/* packet-fc.c
+ * Routines for Fibre Channel Decoding (FC Header, Link Ctl & Basic Link Svc)
+ * Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
+ * Copyright 2003 Ronnie Sahlberg, exchange first/last matching and
+ * tap listener and misc updates
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include "reassemble.h"
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fclctl.h"
+#include "packet-fcbls.h"
+#include "tap.h"
+
+#define FC_HEADER_SIZE 24
+#define FC_RCTL_EISL 0x50
+#define MDSHDR_TRAILER_SIZE 6
+
+/* Size of various fields in FC header in bytes */
+#define FC_RCTL_SIZE 1
+#define FC_DID_SIZE 3
+#define FC_CSCTL_SIZE 1
+#define FC_SID_SIZE 3
+#define FC_TYPE_SIZE 1
+#define FC_FCTL_SIZE 3
+#define FC_SEQID_SIZE 1
+#define FC_DFCTL_SIZE 1
+#define FC_SEQCNT_SIZE 2
+#define FC_OXID_SIZE 2
+#define FC_RXID_SIZE 2
+#define FC_PARAM_SIZE 4
+
+/* Initialize the protocol and registered fields */
+static int proto_fc = -1;
+static int hf_fc_time = -1;
+static int hf_fc_exchange_first_frame = -1;
+static int hf_fc_exchange_last_frame = -1;
+static int hf_fc_rctl = -1;
+static int hf_fc_did = -1;
+static int hf_fc_csctl = -1;
+static int hf_fc_sid = -1;
+static int hf_fc_id = -1;
+static int hf_fc_type = -1;
+static int hf_fc_fctl = -1;
+static int hf_fc_fctl_exchange_responder = -1;
+static int hf_fc_fctl_seq_recipient = -1;
+static int hf_fc_fctl_exchange_first = -1;
+static int hf_fc_fctl_exchange_last = -1;
+static int hf_fc_fctl_seq_last = -1;
+static int hf_fc_fctl_priority = -1;
+static int hf_fc_fctl_transfer_seq_initiative = -1;
+static int hf_fc_fctl_rexmitted_seq = -1;
+static int hf_fc_fctl_rel_offset = -1;
+static int hf_fc_fctl_abts_ack = -1;
+static int hf_fc_fctl_abts_not_ack = -1;
+static int hf_fc_fctl_last_data_frame = -1;
+static int hf_fc_fctl_ack_0_1 = -1;
+static int hf_fc_seqid = -1;
+static int hf_fc_dfctl = -1;
+static int hf_fc_seqcnt = -1;
+static int hf_fc_oxid = -1;
+static int hf_fc_rxid = -1;
+static int hf_fc_param = -1;
+static int hf_fc_ftype = -1; /* Derived field, non-existent in FC hdr */
+static int hf_fc_reassembled = -1;
+static int hf_fc_eisl = -1;
+
+/* Network_Header fields */
+static int hf_fc_nh_da = -1;
+static int hf_fc_nh_sa = -1;
+
+/* For Basic Link Svc */
+static int hf_fc_bls_seqid_vld = -1;
+static int hf_fc_bls_lastvld_seqid = -1;
+static int hf_fc_bls_oxid = -1;
+static int hf_fc_bls_rxid = -1;
+static int hf_fc_bls_lowseqcnt = -1;
+static int hf_fc_bls_hiseqcnt = -1;
+static int hf_fc_bls_rjtcode = -1;
+static int hf_fc_bls_rjtdetail = -1;
+static int hf_fc_bls_vendor = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_fc = -1;
+static gint ett_fctl = -1;
+static gint ett_fcbls = -1;
+
+static dissector_table_t fcftype_dissector_table;
+static dissector_handle_t data_handle;
+
+static int fc_tap = -1;
+
+/* Reassembly stuff */
+static gboolean fc_reassemble = TRUE;
+static guint32 fc_max_frame_size = 1024;
+static GHashTable *fc_fragment_table = NULL;
+
+typedef struct _fcseq_conv_key {
+ guint32 conv_idx;
+} fcseq_conv_key_t;
+
+typedef struct _fcseq_conv_data {
+ guint32 seq_cnt;
+} fcseq_conv_data_t;
+
+GHashTable *fcseq_req_hash = NULL;
+GMemChunk *fcseq_req_keys = NULL;
+GMemChunk *fcseq_req_vals = NULL;
+guint32 fcseq_init_count = 25;
+
+static GHashTable *fc_exchange_unmatched = NULL;
+static GHashTable *fc_exchange_matched = NULL;
+static GMemChunk *fc_exchange_vals = NULL;
+static guint32 fc_exchange_init_count = 200;
+
+/*
+ * Hash Functions
+ */
+static gint
+fcseq_equal(gconstpointer v, gconstpointer w)
+{
+ fcseq_conv_key_t *v1 = (fcseq_conv_key_t *)v;
+ fcseq_conv_key_t *v2 = (fcseq_conv_key_t *)w;
+
+ return (v1->conv_idx == v2->conv_idx);
+}
+
+static guint
+fcseq_hash (gconstpointer v)
+{
+ fcseq_conv_key_t *key = (fcseq_conv_key_t *)v;
+ guint val;
+
+ val = key->conv_idx;
+
+ return val;
+}
+
+static guint
+fc_exchange_hash_unmatched(gconstpointer v)
+{
+ const fc_exchange_data *fced=(const fc_exchange_data *)v;
+
+ return fced->oxid;
+}
+static gint
+fc_exchange_equal_unmatched(gconstpointer v1, gconstpointer v2)
+{
+ const fc_exchange_data *fced1=(const fc_exchange_data *)v1;
+ const fc_exchange_data *fced2=(const fc_exchange_data *)v2;
+
+ /* oxid must match */
+ if(fced1->oxid!=fced2->oxid){
+ return 0;
+ }
+ /* compare s_id, d_id and treat the fc address
+ s_id==00.00.00 as a wildcard matching anything */
+ if( ((fced1->s_id.data[0]!=0)||(fced1->s_id.data[1]!=0)||(fced1->s_id.data[2]!=0)) && CMP_ADDRESS(&fced1->s_id, &fced2->s_id) ){
+ return 0;
+ }
+ if(CMP_ADDRESS(&fced1->d_id, &fced2->d_id)){
+ return 0;
+ }
+
+ return 1;
+}
+
+static guint
+fc_exchange_hash_matched(gconstpointer v)
+{
+ const fc_exchange_data *fced=(const fc_exchange_data *)v;
+
+ return fced->oxid;
+}
+static gint
+fc_exchange_equal_matched(gconstpointer v1, gconstpointer v2)
+{
+ const fc_exchange_data *fced1=(const fc_exchange_data *)v1;
+ const fc_exchange_data *fced2=(const fc_exchange_data *)v2;
+ guint32 fef1, fef2, lef1, lef2;
+
+ /* oxid must match */
+ if(fced1->oxid!=fced2->oxid){
+ return 0;
+ }
+ fef1=fced1->first_exchange_frame;
+ fef2=fced2->first_exchange_frame;
+ lef1=fced1->last_exchange_frame;
+ lef2=fced2->last_exchange_frame;
+ if(!fef1)fef1=fef2;
+ if(!fef2)fef2=fef1;
+ if(!lef1)lef1=lef2;
+ if(!lef2)lef2=lef1;
+
+ if(fef1!=fef2){
+ return 0;
+ }
+ if(lef1!=lef2){
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+fc_exchange_init_protocol(void)
+{
+ if(fc_exchange_vals){
+ g_mem_chunk_destroy(fc_exchange_vals);
+ fc_exchange_vals=NULL;
+ }
+ if(fc_exchange_unmatched){
+ g_hash_table_destroy(fc_exchange_unmatched);
+ fc_exchange_unmatched=NULL;
+ }
+ if(fc_exchange_matched){
+ g_hash_table_destroy(fc_exchange_matched);
+ fc_exchange_matched=NULL;
+ }
+
+ fc_exchange_unmatched=g_hash_table_new(fc_exchange_hash_unmatched, fc_exchange_equal_unmatched);
+ fc_exchange_matched=g_hash_table_new(fc_exchange_hash_matched, fc_exchange_equal_matched);
+ fc_exchange_vals=g_mem_chunk_new("fc_exchange_vals", sizeof(fc_exchange_data), fc_exchange_init_count*sizeof(fc_exchange_data), G_ALLOC_AND_FREE);
+
+ fragment_table_init(&fc_fragment_table);
+
+ if (fcseq_req_keys)
+ g_mem_chunk_destroy (fcseq_req_keys);
+ if (fcseq_req_vals)
+ g_mem_chunk_destroy (fcseq_req_vals);
+ if (fcseq_req_hash)
+ g_hash_table_destroy(fcseq_req_hash);
+
+ fcseq_req_hash = g_hash_table_new(fcseq_hash, fcseq_equal);
+ fcseq_req_keys = g_mem_chunk_new ("fcseq_req_keys",
+ sizeof(fcseq_conv_key_t),
+ fcseq_init_count *
+ sizeof(fcseq_conv_key_t),
+ G_ALLOC_AND_FREE);
+ fcseq_req_vals = g_mem_chunk_new ("fcseq_req_vals",
+ sizeof(fcseq_conv_data_t),
+ fcseq_init_count *
+ sizeof(fcseq_conv_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+
+const value_string fc_fc4_val[] = {
+ {FC_TYPE_ELS, "Ext Link Svc"},
+ {FC_TYPE_LLCSNAP, "LLC_SNAP"},
+ {FC_TYPE_IP, "IP/FC"},
+ {FC_TYPE_SCSI, "FCP"},
+ {FC_TYPE_FCCT, "FC_CT"},
+ {FC_TYPE_SWILS, "SW_ILS"},
+ {FC_TYPE_AL, "AL"},
+ {FC_TYPE_SNMP, "SNMP"},
+ {FC_TYPE_SB_FROM_CU, "SB-3(CU->Channel)"},
+ {FC_TYPE_SB_TO_CU, "SB-3(Channel->CU)"},
+ {0, NULL},
+};
+
+static const value_string fc_ftype_vals [] = {
+ {FC_FTYPE_UNDEF , "Unknown frame"},
+ {FC_FTYPE_SWILS, "SW_ILS"},
+ {FC_FTYPE_IP , "IP/FC"},
+ {FC_FTYPE_SCSI , "FCP"},
+ {FC_FTYPE_BLS , "Basic Link Svc"},
+ {FC_FTYPE_ELS , "ELS"},
+ {FC_FTYPE_FCCT , "FC_CT"},
+ {FC_FTYPE_LINKDATA, "Link Data"},
+ {FC_FTYPE_VDO, "Video Data"},
+ {FC_FTYPE_LINKCTL, "Link Ctl"},
+ {FC_FTYPE_SBCCS, "SBCCS"},
+ {0, NULL},
+};
+
+static const value_string fc_wka_vals[] = {
+ {FC_WKA_MULTICAST, "Multicast Server"},
+ {FC_WKA_CLKSYNC, "Clock Sync Server"},
+ {FC_WKA_KEYDIST, "Key Distribution Server"},
+ {FC_WKA_ALIAS, "Alias Server"},
+ {FC_WKA_QOSF, "QoS Facilitator"},
+ {FC_WKA_MGMT, "Management Server"},
+ {FC_WKA_TIME, "Time Server"},
+ {FC_WKA_DNS, "Directory Server"},
+ {FC_WKA_FABRIC_CTRLR, "Fabric Ctlr"},
+ {FC_WKA_FPORT, "F_Port Server"},
+ {FC_WKA_BCAST, "Broadcast ID"},
+ {0, NULL},
+};
+
+static const value_string fc_routing_val[] = {
+ {FC_RCTL_DEV_DATA, "Device_Data"},
+ {FC_RCTL_ELS, "Extended Link Services"},
+ {FC_RCTL_LINK_DATA, "FC-4 Link_Data"},
+ {FC_RCTL_VIDEO, "Video_Data"},
+ {FC_RCTL_BLS, "Basic Link Services"},
+ {FC_RCTL_LINK_CTL, "Link_Control Frame"},
+ {0, NULL},
+};
+
+static const value_string fc_iu_val[] = {
+ {FC_IU_UNCATEGORIZED , "Uncategorized Data"},
+ {FC_IU_SOLICITED_DATA , "Solicited Data"},
+ {FC_IU_UNSOLICITED_CTL , "Unsolicited Control"},
+ {FC_IU_SOLICITED_CTL , "Solicited Control"},
+ {FC_IU_UNSOLICITED_DATA, "Solicited Data"},
+ {FC_IU_DATA_DESCRIPTOR , "Data Descriptor"},
+ {FC_IU_UNSOLICITED_CMD , "Unsolicited Command"},
+ {FC_IU_CMD_STATUS , "Command Status"},
+ {0, NULL},
+};
+
+
+static void fc_defragment_init(void)
+{
+ fragment_table_init(&fc_fragment_table);
+}
+
+
+static gchar *
+fctl_to_str (const guint8 *fctl, gchar *str, gboolean is_ack)
+{
+ int stroff = 0;
+ guint8 tmp = 0;
+
+ if (str == NULL)
+ return (str);
+
+ if (fctl[2] & 0x80) {
+ strcpy (str, "Exchange Responder, ");
+ stroff += 20;
+ }
+ else {
+ strcpy (str, "Exchange Originator, ");
+ stroff += 21;
+ }
+
+ if (fctl[2] & 0x40) {
+ strcpy (&str[stroff], "Seq Recipient, ");
+ stroff += 15;
+ }
+ else {
+ strcpy (&str[stroff], "Seq Initiator, ");
+ stroff += 15;
+ }
+
+ if (fctl[2] & 0x20) {
+ strcpy (&str[stroff], "Exchg First, ");
+ stroff += 13;
+ }
+
+ if (fctl[2] & 0x10) {
+ strcpy (&str[stroff], "Exchg Last, ");
+ stroff += 12;
+ }
+
+ if (fctl[2] & 0x8) {
+ strcpy (&str[stroff], "Seq Last, ");
+ stroff += 10;
+ }
+
+ if (fctl[2] & 0x2) {
+ strcpy (&str[stroff], "Priority, ");
+ stroff += 10;
+ }
+ else {
+ strcpy (&str[stroff], "CS_CTL, ");
+ stroff += 8;
+ }
+
+ if (fctl[2] & 0x1) {
+ strcpy (&str[stroff], "Transfer Seq Initiative, ");
+ stroff += 25;
+ }
+
+ if (fctl[1] & 0x30) {
+ strcpy (&str[stroff], "ACK_0 Reqd, ");
+ stroff += 12;
+ }
+ else if (fctl[1] & 0x10) {
+ strcpy (&str[stroff], "ACK_1 Reqd, ");
+ stroff += 12;
+ }
+
+ if (fctl[1] & 0x2) {
+ strcpy (&str[stroff], "Rexmitted Seq, ");
+ stroff += 15;
+ }
+
+ tmp = fctl[0] & 0xC0;
+ switch (tmp) {
+ case 0:
+ strcpy (&str[stroff], "Last Data Frame - No Info, ");
+ stroff += 27;
+ break;
+ case 1:
+ strcpy (&str[stroff], "Last Data Frame - Seq Imm, ");
+ stroff += 27;
+ break;
+ case 2:
+ strcpy (&str[stroff], "Last Data Frame - Seq Soon, ");
+ stroff += 28;
+ break;
+ case 3:
+ strcpy (&str[stroff], "Last Data Frame - Seq Delyd, ");
+ stroff += 29;
+ break;
+ }
+
+ tmp = fctl[0] & 0x30;
+ switch (tmp) {
+ case 0:
+ if (is_ack) {
+ strcpy (&str[stroff], "ABTS - Cont, ");
+ stroff += 13;
+ }
+ else {
+ strcpy (&str[stroff], "ABTS - Abort/MS, ");
+ stroff += 17;
+ }
+ break;
+ case 0x10:
+ if (is_ack) {
+ strcpy (&str[stroff], "ABTS - AbortABTS - Abort, ");
+ stroff += 14;
+ }
+ else {
+ strcpy (&str[stroff], "ABTS - Abort/SS, ");
+ stroff += 17;
+ }
+ break;
+ case 0x20:
+ if (is_ack) {
+ strcpy (&str[stroff], "ABTS - Stop, ");
+ stroff += 13;
+ }
+ else {
+ strcpy (&str[stroff], "ABTS - Process/IB, ");
+ stroff += 19;
+ }
+ break;
+ case 0x30:
+ if (is_ack) {
+ strcpy (&str[stroff], "ABTS - Imm Seq Retx, ");
+ stroff += 21;
+ }
+ else {
+ strcpy (&str[stroff], "ABTS - Discard/MS/Imm Retx, ");
+ stroff += 28;
+ }
+ break;
+ }
+
+ if (fctl[0] & 0x8) {
+ strcpy (&str[stroff], "Rel Offset = 1");
+ stroff += 14;
+ }
+
+ return (str);
+}
+
+/* BA_ACC & BA_RJT are decoded in this file itself instead of a traditional
+ * dedicated file and dissector format because the dissector would require some
+ * fields of the FC_HDR such as param in some cases, type in some others, the
+ * lower 4 bits of r_ctl in some other cases etc. So, we decode BLS & Link Ctl
+ * in this file itself.
+ */
+static void
+dissect_fc_ba_acc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *acc_tree;
+ int offset = 0;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BLS");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "BA_ACC");
+
+ if (tree) {
+ ti = proto_tree_add_text (tree, tvb, 0, tvb_length (tvb), "Basic Link Svc");
+ acc_tree = proto_item_add_subtree (ti, ett_fcbls);
+
+ proto_tree_add_item (acc_tree, hf_fc_bls_seqid_vld, tvb, offset++, 1, FALSE);
+ proto_tree_add_item (acc_tree, hf_fc_bls_lastvld_seqid, tvb, offset++, 1, FALSE);
+ offset += 2; /* Skip reserved field */
+ proto_tree_add_item (acc_tree, hf_fc_bls_oxid, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item (acc_tree, hf_fc_bls_rxid, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item (acc_tree, hf_fc_bls_lowseqcnt, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item (acc_tree, hf_fc_bls_hiseqcnt, tvb, offset, 2, FALSE);
+ }
+}
+
+static void
+dissect_fc_ba_rjt (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *rjt_tree;
+ int offset = 0;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BLS");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "BA_RJT");
+
+ if (tree) {
+ ti = proto_tree_add_text (tree, tvb, 0, tvb_length (tvb), "Basic Link Svc");
+ rjt_tree = proto_item_add_subtree (ti, ett_fcbls);
+
+ proto_tree_add_item (rjt_tree, hf_fc_bls_rjtcode, tvb, offset+1, 1, FALSE);
+ proto_tree_add_item (rjt_tree, hf_fc_bls_rjtdetail, tvb, offset+2, 1, FALSE);
+ proto_tree_add_item (rjt_tree, hf_fc_bls_vendor, tvb, offset+3, 1, FALSE);
+ }
+}
+
+static guint8
+fc_get_ftype (guint8 r_ctl, guint8 type)
+{
+ /* A simple attempt to determine the upper level protocol based on the
+ * r_ctl & type fields.
+ */
+ switch (r_ctl & 0xF0) {
+ case FC_RCTL_DEV_DATA:
+ switch (type) {
+ case FC_TYPE_SWILS:
+ if ((r_ctl == 0x2) || (r_ctl == 0x3))
+ return FC_FTYPE_SWILS;
+ else
+ return FC_FTYPE_UNDEF;
+ case FC_TYPE_IP:
+ return FC_FTYPE_IP;
+ case FC_TYPE_SCSI:
+ return FC_FTYPE_SCSI;
+ case FC_TYPE_FCCT:
+ return FC_FTYPE_FCCT;
+ case FC_TYPE_SB_FROM_CU:
+ case FC_TYPE_SB_TO_CU:
+ return FC_FTYPE_SBCCS;
+ default:
+ return FC_FTYPE_UNDEF;
+ }
+ break;
+ case FC_RCTL_ELS:
+ if (((r_ctl & 0x0F) == 0x2) || ((r_ctl & 0x0F) == 0x3))
+ return FC_FTYPE_ELS;
+ else
+ return FC_FTYPE_UNDEF;
+ break;
+ case FC_RCTL_LINK_DATA:
+ return FC_FTYPE_LINKDATA;
+ break;
+ case FC_RCTL_VIDEO:
+ return FC_FTYPE_VDO;
+ break;
+ case FC_RCTL_BLS:
+ if (type == 0)
+ return FC_FTYPE_BLS;
+ else
+ return FC_FTYPE_UNDEF;
+ break;
+ case FC_RCTL_LINK_CTL:
+ return FC_FTYPE_LINKCTL;
+ break;
+ default:
+ return FC_FTYPE_UNDEF;
+ break;
+ }
+}
+
+static const value_string abts_ack_vals[] = {
+ {0x000000, "ABTS - Cont"},
+ {0x000010, "ABTS - Abort"},
+ {0x000020, "ABTS - Stop"},
+ {0x000030, "ABTS - Imm Seq Retx"},
+ {0,NULL}
+};
+static const value_string abts_not_ack_vals[] = {
+ {0x000000, "ABTS - Abort/MS"},
+ {0x000010, "ABTS - Abort/SS"},
+ {0x000020, "ABTS - Process/IB"},
+ {0x000030, "ABTS - Discard/MS/Imm Retx"},
+ {0,NULL}
+};
+static const value_string last_data_frame_vals[] = {
+ {0x000000, "Last Data Frame - No Info"},
+ {0x004000, "Last Data Frame - Seq Imm"},
+ {0x008000, "Last Data Frame - Seq Soon"},
+ {0x00c000, "Last Data Frame - Seq Delyd"},
+ {0,NULL}
+};
+static const value_string ack_0_1_vals[] = {
+ {0x003000, "ACK_0 Required"},
+ {0x002000, "ACK_0 Required"},
+ {0x001000, "ACK_1 Required"},
+ {0x000000, "no ack required"},
+ {0,NULL}
+};
+static const true_false_string tfs_fc_fctl_exchange_responder = {
+ "Exchange Responder",
+ "Exchange Originator"
+};
+static const true_false_string tfs_fc_fctl_seq_recipient = {
+ "Seq Recipient",
+ "Seq Initiator"
+};
+static const true_false_string tfs_fc_fctl_exchange_first = {
+ "Exchg First",
+ "NOT exchg first"
+};
+static const true_false_string tfs_fc_fctl_exchange_last = {
+ "Exchg Last",
+ "NOT exchg last"
+};
+static const true_false_string tfs_fc_fctl_seq_last = {
+ "Seq Last",
+ "NOT seq last"
+};
+static const true_false_string tfs_fc_fctl_priority = {
+ "Priority",
+ "CS_CTL"
+};
+static const true_false_string tfs_fc_fctl_transfer_seq_initiative = {
+ "Transfer Seq Initiative",
+ "NOT transfer seq initiative"
+};
+static const true_false_string tfs_fc_fctl_rexmitted_seq = {
+ "Retransmitted Sequence",
+ "NOT retransmitted sequence"
+};
+static const true_false_string tfs_fc_fctl_rel_offset = {
+ "Rel Offset SET",
+ "rel offset NOT set"
+};
+
+
+
+
+/* code to dissect the F_CTL bitmask */
+static void
+dissect_fc_fctl(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, gboolean is_ack, guint32 fctl)
+{
+ proto_item *item;
+ proto_tree *tree;
+ gchar str[256];
+
+ item=proto_tree_add_uint(parent_tree, hf_fc_fctl, tvb, offset, 3, fctl);
+ tree=proto_item_add_subtree(item, ett_fctl);
+
+
+ proto_tree_add_boolean(tree, hf_fc_fctl_exchange_responder, tvb, offset, 3, fctl);
+
+ proto_tree_add_boolean(tree, hf_fc_fctl_seq_recipient, tvb, offset, 3, fctl);
+
+ proto_tree_add_boolean(tree, hf_fc_fctl_exchange_first, tvb, offset, 3, fctl);
+
+ proto_tree_add_boolean(tree, hf_fc_fctl_exchange_last, tvb, offset, 3, fctl);
+
+ proto_tree_add_boolean(tree, hf_fc_fctl_seq_last, tvb, offset, 3, fctl);
+
+ proto_tree_add_boolean(tree, hf_fc_fctl_priority, tvb, offset, 3, fctl);
+
+ proto_tree_add_boolean(tree, hf_fc_fctl_transfer_seq_initiative, tvb, offset, 3, fctl);
+
+ proto_tree_add_uint(tree, hf_fc_fctl_last_data_frame, tvb, offset, 3, fctl);
+
+ proto_tree_add_uint(tree, hf_fc_fctl_ack_0_1, tvb, offset, 3, fctl);
+
+
+ proto_tree_add_boolean(tree, hf_fc_fctl_rexmitted_seq, tvb, offset, 3, fctl);
+
+ if(is_ack){
+ proto_tree_add_uint(tree, hf_fc_fctl_abts_ack, tvb, offset, 3, fctl);
+ } else {
+ proto_tree_add_uint(tree, hf_fc_fctl_abts_ack, tvb, offset, 3, fctl);
+ }
+
+ proto_tree_add_boolean(tree, hf_fc_fctl_rel_offset, tvb, offset, 3, fctl);
+
+ fctl_to_str( ((guint8 *)&fctl), str, is_ack);
+ proto_item_append_text(item, " %s", str);
+}
+
+static const value_string fc_bls_proto_val[] = {
+ {FC_BLS_NOP , "NOP"},
+ {FC_BLS_ABTS , "ABTS"},
+ {FC_BLS_RMC , "RMC"},
+ {FC_BLS_BAACC , "BA_ACC"},
+ {FC_BLS_BARJT , "BA_RJT"},
+ {FC_BLS_PRMT , "PRMT"},
+ {0, NULL},
+};
+
+static const value_string fc_els_proto_val[] = {
+ {0x01 , "Solicited Data"},
+ {0x02 , "Request"},
+ {0x03 , "Reply"},
+ {0, NULL},
+};
+
+/* Code to actually dissect the packets */
+static void
+dissect_fc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti=NULL;
+ proto_tree *fc_tree = NULL;
+ tvbuff_t *next_tvb;
+ int offset = 0, next_offset, eisl_offset = -1;
+ gboolean is_lastframe_inseq, is_1frame_inseq, is_valid_frame;
+ gboolean is_exchg_resp = 0;
+ fragment_data *fcfrag_head;
+ guint32 frag_id;
+ guint32 frag_size;
+ guint8 df_ctl, seq_id;
+
+ guint32 param;
+ guint16 real_seqcnt;
+ guint8 ftype;
+ gboolean is_ack;
+
+ static fc_hdr fchdr;
+ fc_exchange_data *fc_ex=NULL;
+
+ conversation_t *conversation;
+ fcseq_conv_data_t *cdata;
+ fcseq_conv_key_t ckey, *req_key;
+
+ fchdr.fced=NULL;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FC");
+
+ fchdr.r_ctl = tvb_get_guint8 (tvb, offset);
+
+ /* If the R_CTL is the EISL field, skip the first 8 bytes to retrieve the
+ * real FC header. EISL is Cisco-proprietary and is not decoded.
+ */
+ if (fchdr.r_ctl == FC_RCTL_EISL) {
+ eisl_offset = offset;
+ offset += 8;
+ fchdr.r_ctl = tvb_get_guint8 (tvb, offset);
+ }
+
+ SET_ADDRESS (&pinfo->dst, AT_FC, 3, tvb_get_ptr(tvb,offset+1,3));
+ SET_ADDRESS (&fchdr.d_id, AT_FC, 3, tvb_get_ptr(tvb,offset+1,3));
+ SET_ADDRESS (&pinfo->src, AT_FC, 3, tvb_get_ptr(tvb,offset+5,3));
+ SET_ADDRESS (&fchdr.s_id, AT_FC, 3, tvb_get_ptr(tvb,offset+5,3));
+ fchdr.cs_ctl = tvb_get_guint8 (tvb, offset+4);
+ fchdr.type = tvb_get_guint8 (tvb, offset+8);
+ fchdr.fctl=tvb_get_ntoh24(tvb,offset+9);
+ fchdr.seqcnt = tvb_get_ntohs (tvb, offset+14);
+ fchdr.oxid=tvb_get_ntohs(tvb,offset+16);
+ fchdr.rxid=tvb_get_ntohs(tvb,offset+18);
+ param = tvb_get_ntohl (tvb, offset+20);
+ seq_id = tvb_get_guint8 (tvb, offset+12);
+
+ pinfo->oxid = fchdr.oxid;
+ pinfo->rxid = fchdr.rxid;
+ pinfo->ptype = PT_EXCHG;
+ pinfo->r_ctl = fchdr.r_ctl;
+
+ is_ack = ((fchdr.r_ctl == 0xC0) || (fchdr.r_ctl == 0xC1));
+
+ /* There are two ways to determine if this is the first frame of a
+ * sequence. Either:
+ * (i) The SOF bits indicate that this is the first frame OR
+ * (ii) This is an SOFf frame and seqcnt is 0.
+ */
+ is_1frame_inseq = (((pinfo->sof_eof & PINFO_SOF_FIRST_FRAME) == PINFO_SOF_FIRST_FRAME) ||
+ (((pinfo->sof_eof & PINFO_SOF_SOFF) == PINFO_SOF_SOFF) &&
+ (fchdr.seqcnt == 0)));
+
+ is_lastframe_inseq = ((pinfo->sof_eof & PINFO_EOF_LAST_FRAME) == PINFO_EOF_LAST_FRAME);
+
+ if ((pinfo->sof_eof & PINFO_SOF_SOFF) == PINFO_SOF_SOFF) {
+ is_lastframe_inseq = fchdr.fctl & FC_FCTL_SEQ_LAST;
+ }
+ is_valid_frame = ((pinfo->sof_eof & 0x40) == 0x40);
+
+ ftype = fc_get_ftype (fchdr.r_ctl, fchdr.type);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_add_str (pinfo->cinfo, COL_INFO, match_strval (ftype, fc_ftype_vals));
+
+ if (ftype == FC_FTYPE_LINKCTL)
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", %s",
+ match_strval ((fchdr.r_ctl & 0x0F),
+ fc_lctl_proto_val));
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fc, tvb, offset,
+ FC_HEADER_SIZE, "Fibre Channel");
+ fc_tree = proto_item_add_subtree (ti, ett_fc);
+ }
+
+ /* Highlight EISL header, if present */
+ if (eisl_offset != -1) {
+ proto_tree_add_item (fc_tree, hf_fc_eisl, tvb, eisl_offset, 8, 0);
+ }
+
+ /* match first exchange with last exchange */
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_FIRST){
+ if(!pinfo->fd->flags.visited){
+ fc_exchange_data fced, *old_fced;
+
+ /* first check if we already have seen this exchange and it
+ is still open/unmatched.
+ */
+ fced.oxid=fchdr.oxid;
+ SET_ADDRESS(&fced.s_id, fchdr.s_id.type, fchdr.s_id.len, fchdr.s_id.data);
+ SET_ADDRESS(&fced.d_id, fchdr.d_id.type, fchdr.d_id.len, fchdr.d_id.data);
+ old_fced=g_hash_table_lookup(fc_exchange_unmatched, &fced);
+ if(old_fced){
+ g_hash_table_remove(fc_exchange_unmatched, old_fced);
+ }
+ old_fced=g_mem_chunk_alloc(fc_exchange_vals);
+ old_fced->oxid=fchdr.oxid;
+ COPY_ADDRESS(&old_fced->s_id, &fchdr.s_id);
+ COPY_ADDRESS(&old_fced->d_id, &fchdr.d_id);
+ old_fced->first_exchange_frame=pinfo->fd->num;
+ old_fced->fc_time.nsecs = pinfo->fd->abs_usecs*1000;
+ old_fced->fc_time.secs = pinfo->fd->abs_secs;
+ g_hash_table_insert(fc_exchange_unmatched, old_fced, old_fced);
+ fc_ex=old_fced;
+ } else {
+ fc_exchange_data fced, *old_fced;
+ fced.oxid=fchdr.oxid;
+ fced.first_exchange_frame=pinfo->fd->num;
+ fced.last_exchange_frame=0;
+ old_fced=g_hash_table_lookup(fc_exchange_matched, &fced);
+ fc_ex=old_fced;
+ }
+ }
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_LAST){
+ if(!pinfo->fd->flags.visited){
+ fc_exchange_data fced, *old_fced;
+
+ fced.oxid=fchdr.oxid;
+ SET_ADDRESS(&fced.s_id, fchdr.d_id.type, fchdr.d_id.len, fchdr.d_id.data);
+ SET_ADDRESS(&fced.d_id, fchdr.s_id.type, fchdr.s_id.len, fchdr.s_id.data);
+ old_fced=g_hash_table_lookup(fc_exchange_unmatched, &fced);
+ if(old_fced){
+ g_hash_table_remove(fc_exchange_unmatched, old_fced);
+ old_fced->last_exchange_frame=pinfo->fd->num;
+ g_hash_table_insert(fc_exchange_matched, old_fced, old_fced);
+ }
+ fc_ex=old_fced;
+ } else {
+ fc_exchange_data fced, *old_fced;
+ fced.oxid=fchdr.oxid;
+ fced.first_exchange_frame=0;
+ fced.last_exchange_frame=pinfo->fd->num;
+ old_fced=g_hash_table_lookup(fc_exchange_matched, &fced);
+ fc_ex=old_fced;
+ }
+ }
+ if(fc_ex){
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_FIRST){
+ proto_tree_add_uint(fc_tree, hf_fc_exchange_last_frame, tvb, 0, 0, fc_ex->last_exchange_frame);
+ }
+ if(fchdr.fctl&FC_FCTL_EXCHANGE_LAST){
+ nstime_t delta_time;
+ proto_tree_add_uint(fc_tree, hf_fc_exchange_first_frame, tvb, 0, 0, fc_ex->first_exchange_frame);
+ delta_time.secs = pinfo->fd->abs_secs - fc_ex->fc_time.secs;
+ delta_time.nsecs = pinfo->fd->abs_usecs*1000 - fc_ex->fc_time.nsecs;
+ if (delta_time.nsecs<0){
+ delta_time.nsecs+=1000000000;
+ delta_time.secs--;
+ }
+ proto_tree_add_time(ti, hf_fc_time, tvb, 0, 0, &delta_time);
+ }
+ }
+ fchdr.fced=fc_ex;
+
+ switch (fchdr.r_ctl & 0xF0) {
+
+ case FC_RCTL_DEV_DATA:
+ case FC_RCTL_LINK_DATA:
+ case FC_RCTL_VIDEO:
+ /* the lower 4 bits of R_CTL are the information category */
+ proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
+ FC_RCTL_SIZE, fchdr.r_ctl,
+ "R_CTL: 0x%x(%s/%s)",
+ fchdr.r_ctl,
+ val_to_str ((fchdr.r_ctl & 0xF0),
+ fc_routing_val, "0x%x"),
+ val_to_str ((fchdr.r_ctl & 0x0F),
+ fc_iu_val, "0x%x"));
+ break;
+
+ case FC_RCTL_LINK_CTL:
+ /* the lower 4 bits of R_CTL indicate the type of link ctl frame */
+ proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
+ FC_RCTL_SIZE, fchdr.r_ctl,
+ "R_CTL: 0x%x(%s/%s)",
+ fchdr.r_ctl,
+ val_to_str ((fchdr.r_ctl & 0xF0),
+ fc_routing_val, "0x%x"),
+ val_to_str ((fchdr.r_ctl & 0x0F),
+ fc_lctl_proto_val, "0x%x"));
+ break;
+
+ case FC_RCTL_BLS:
+ switch (fchdr.type) {
+
+ case 0x00:
+ /* the lower 4 bits of R_CTL indicate the type of BLS frame */
+ proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
+ FC_RCTL_SIZE, fchdr.r_ctl,
+ "R_CTL: 0x%x(%s/%s)",
+ fchdr.r_ctl,
+ val_to_str ((fchdr.r_ctl & 0xF0),
+ fc_routing_val, "0x%x"),
+ val_to_str ((fchdr.r_ctl & 0x0F),
+ fc_bls_proto_val, "0x%x"));
+ break;
+
+ default:
+ proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
+ FC_RCTL_SIZE, fchdr.r_ctl,
+ "R_CTL: 0x%x(%s/0x%x)",
+ fchdr.r_ctl,
+ val_to_str ((fchdr.r_ctl & 0xF0),
+ fc_routing_val, "0x%x"),
+ fchdr.r_ctl & 0x0F);
+ break;
+ }
+ break;
+
+ case FC_RCTL_ELS:
+ switch (fchdr.type) {
+
+ case 0x01:
+ /* the lower 4 bits of R_CTL indicate the type of ELS frame */
+ proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
+ FC_RCTL_SIZE, fchdr.r_ctl,
+ "R_CTL: 0x%x(%s/%s)",
+ fchdr.r_ctl,
+ val_to_str ((fchdr.r_ctl & 0xF0),
+ fc_routing_val, "0x%x"),
+ val_to_str ((fchdr.r_ctl & 0x0F),
+ fc_els_proto_val, "0x%x"));
+ break;
+
+ default:
+ proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
+ FC_RCTL_SIZE, fchdr.r_ctl,
+ "R_CTL: 0x%x(%s/0x%x)",
+ fchdr.r_ctl,
+ val_to_str ((fchdr.r_ctl & 0xF0),
+ fc_routing_val, "0x%x"),
+ fchdr.r_ctl & 0x0F);
+ break;
+ }
+ break;
+
+ default:
+ proto_tree_add_uint_format (fc_tree, hf_fc_rctl, tvb, offset,
+ FC_RCTL_SIZE, fchdr.r_ctl,
+ "R_CTL: 0x%x(%s/0x%x)",
+ fchdr.r_ctl,
+ val_to_str ((fchdr.r_ctl & 0xF0),
+ fc_routing_val, "0x%x"),
+ fchdr.r_ctl & 0x0F);
+ break;
+ }
+
+ proto_tree_add_uint_hidden (fc_tree, hf_fc_ftype, tvb, offset, 1,
+ ftype);
+
+ /* XXX - use "fc_wka_vals[]" on this? */
+ proto_tree_add_string (fc_tree, hf_fc_did, tvb, offset+1, 3,
+ fc_to_str (fchdr.d_id.data));
+ proto_tree_add_string_hidden (fc_tree, hf_fc_id, tvb, offset+1, 3,
+ fc_to_str (fchdr.d_id.data));
+
+ proto_tree_add_uint (fc_tree, hf_fc_csctl, tvb, offset+4, 1, fchdr.cs_ctl);
+
+ /* XXX - use "fc_wka_vals[]" on this? */
+ proto_tree_add_string (fc_tree, hf_fc_sid, tvb, offset+5, 3,
+ fc_to_str (fchdr.s_id.data));
+ proto_tree_add_string_hidden (fc_tree, hf_fc_id, tvb, offset+5, 3,
+ fc_to_str (fchdr.s_id.data));
+
+ if (ftype == FC_FTYPE_LINKCTL) {
+ if (((fchdr.r_ctl & 0x0F) == FC_LCTL_FBSYB) ||
+ ((fchdr.r_ctl & 0x0F) == FC_LCTL_FBSYL)) {
+ /* for F_BSY frames, the upper 4 bits of the type field specify the
+ * reason for the BSY.
+ */
+ proto_tree_add_uint_format (fc_tree, hf_fc_type, tvb,
+ offset+8, FC_TYPE_SIZE,
+ fchdr.type,"Type: 0x%x(%s)", fchdr.type,
+ fclctl_get_typestr ((guint8) (fchdr.r_ctl & 0x0F),
+ fchdr.type));
+ } else {
+ proto_tree_add_item (fc_tree, hf_fc_type, tvb, offset+8, 1, FALSE);
+ }
+ } else {
+ proto_tree_add_item (fc_tree, hf_fc_type, tvb, offset+8, 1, FALSE);
+ }
+
+
+ dissect_fc_fctl(pinfo, fc_tree, tvb, offset+9, is_ack, fchdr.fctl);
+
+
+ proto_tree_add_item (fc_tree, hf_fc_seqid, tvb, offset+12, 1, FALSE);
+
+ df_ctl = tvb_get_guint8(tvb, offset+13);
+
+ proto_tree_add_uint (fc_tree, hf_fc_dfctl, tvb, offset+13, 1, df_ctl);
+ proto_tree_add_uint (fc_tree, hf_fc_seqcnt, tvb, offset+14, 2, fchdr.seqcnt);
+ proto_tree_add_uint (fc_tree, hf_fc_oxid, tvb, offset+16, 2, fchdr.oxid);
+ proto_tree_add_uint (fc_tree, hf_fc_rxid, tvb, offset+18, 2, fchdr.rxid);
+
+ if (ftype == FC_FTYPE_LINKCTL) {
+ if (((fchdr.r_ctl & 0x0F) == FC_LCTL_FRJT) ||
+ ((fchdr.r_ctl & 0x0F) == FC_LCTL_PRJT) ||
+ ((fchdr.r_ctl & 0x0F) == FC_LCTL_PBSY)) {
+ /* In all these cases of Link Ctl frame, the parameter field
+ * encodes the detailed error message
+ */
+ proto_tree_add_uint_format (fc_tree, hf_fc_param, tvb,
+ offset+20, 4, param,
+ "Parameter: 0x%x(%s)", param,
+ fclctl_get_paramstr ((fchdr.r_ctl & 0x0F),
+ param));
+ } else {
+ proto_tree_add_item (fc_tree, hf_fc_param, tvb, offset+20, 4, FALSE);
+ }
+ } else if (ftype == FC_FTYPE_BLS) {
+ if ((fchdr.r_ctl & 0x0F) == FC_BLS_ABTS) {
+ proto_tree_add_uint_format (fc_tree, hf_fc_param, tvb,
+ offset+20, 4, param,
+ "Parameter: 0x%x(%s)", param,
+ ((param & 0x0F) == 1 ? "Abort Sequence" :
+ "Abort Exchange"));
+ } else {
+ proto_tree_add_item (fc_tree, hf_fc_param, tvb, offset+20,
+ 4, FALSE);
+ }
+ } else {
+ proto_tree_add_item (fc_tree, hf_fc_param, tvb, offset+20, 4, FALSE);
+ }
+
+ /* Skip the Frame_Header */
+ next_offset = offset + FC_HEADER_SIZE;
+
+ /* Network_Header present? */
+ if (df_ctl & FC_DFCTL_NH) {
+ /* Yes - dissect it. */
+ if (tree) {
+ proto_tree_add_string (fc_tree, hf_fc_nh_da, tvb, next_offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ proto_tree_add_string (fc_tree, hf_fc_nh_sa, tvb, offset+8, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+8, 8)));
+ }
+ next_offset += 16;
+ }
+
+ /* XXX - handle Association_Header and Device_Header here */
+
+ if (ftype == FC_FTYPE_LINKCTL) {
+ /* ACK_1 frames and other LINK_CTL frames echo the last seq bit if the
+ * packet they're ack'ing did not have it set. So, we'll incorrectly
+ * flag them as being fragmented when they're not. This fixes the
+ * problem
+ */
+ is_lastframe_inseq = TRUE;
+ } else {
+ /* XXX is this right? offset 20, shouldnt it be offset 9? */
+ is_exchg_resp = ((tvb_get_guint8 (tvb, offset+20) & 0x80) == 0x80);
+ }
+
+ frag_size = tvb_reported_length (tvb)-FC_HEADER_SIZE;
+
+ /* If there is an MDS header, we need to subtract the MDS trailer size */
+ if ((pinfo->ethertype == ETHERTYPE_UNK) || (pinfo->ethertype == ETHERTYPE_FCFT)) {
+ frag_size -= MDSHDR_TRAILER_SIZE;
+ } else if (pinfo->ethertype == ETHERTYPE_BRDWALK) {
+ frag_size -= 8; /* 4 byte of FC CRC +
+ 4 bytes of error+EOF = 8 bytes */
+ }
+
+ if (!is_lastframe_inseq) {
+ /* Show this only as a fragmented FC frame */
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_str (pinfo->cinfo, COL_INFO, " (Fragmented)");
+ }
+ }
+
+ /* If this is a fragment, attempt to check if fully reassembled frame is
+ * present, if we're configured to reassemble.
+ */
+ if ((ftype != FC_FTYPE_LINKCTL) && (ftype != FC_FTYPE_BLS) &&
+ (!is_lastframe_inseq || !is_1frame_inseq) && fc_reassemble &&
+ tvb_bytes_exist(tvb, FC_HEADER_SIZE, frag_size) && tree) {
+ /* Add this to the list of fragments */
+
+ /* In certain cases such as FICON, the SEQ_CNT is streaming
+ * i.e. continuously increasing. So, zero does not signify the
+ * first frame of the sequence. To fix this, we need to save the
+ * SEQ_CNT of the first frame in sequence and use this value to
+ * determine the actual offset into a frame.
+ */
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ if (!conversation) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ }
+
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcseq_conv_data_t *)g_hash_table_lookup (fcseq_req_hash,
+ &ckey);
+
+ if (is_1frame_inseq) {
+ if (cdata) {
+ /* Since we never free the memory used by an exchange, this maybe a
+ * case of another request using the same exchange as a previous
+ * req.
+ */
+ cdata->seq_cnt = fchdr.seqcnt;
+ }
+ else {
+ req_key = g_mem_chunk_alloc (fcseq_req_keys);
+ req_key->conv_idx = conversation->index;
+
+ cdata = g_mem_chunk_alloc (fcseq_req_vals);
+ cdata->seq_cnt = fchdr.seqcnt;
+
+ g_hash_table_insert (fcseq_req_hash, req_key, cdata);
+ }
+ real_seqcnt = 0;
+ }
+ else if (cdata != NULL) {
+ real_seqcnt = fchdr.seqcnt - cdata->seq_cnt ;
+ }
+ else {
+ real_seqcnt = fchdr.seqcnt;
+ }
+
+ frag_id = ((pinfo->oxid << 16) ^ seq_id) | is_exchg_resp ;
+
+ /* We assume that all frames are of the same max size */
+ fcfrag_head = fragment_add (tvb, FC_HEADER_SIZE, pinfo, frag_id,
+ fc_fragment_table,
+ real_seqcnt * fc_max_frame_size,
+ frag_size,
+ !is_lastframe_inseq);
+
+ if (fcfrag_head) {
+ next_tvb = tvb_new_real_data (fcfrag_head->data,
+ fcfrag_head->datalen,
+ fcfrag_head->datalen);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+
+ /* Add the defragmented data to the data source list. */
+ add_new_data_source(pinfo, next_tvb, "Reassembled FC");
+
+ if (tree) {
+ proto_tree_add_boolean_hidden (fc_tree, hf_fc_reassembled,
+ tvb, offset+9, 1, 1);
+ }
+ }
+ else {
+ if (tree) {
+ proto_tree_add_boolean_hidden (fc_tree, hf_fc_reassembled,
+ tvb, offset+9, 1, 0);
+ }
+ next_tvb = tvb_new_subset (tvb, next_offset, -1, -1);
+ call_dissector (data_handle, next_tvb, pinfo, tree);
+ return;
+ }
+ } else {
+ if (tree) {
+ proto_tree_add_boolean_hidden (fc_tree, hf_fc_reassembled,
+ tvb, offset+9, 1, 0);
+ }
+ next_tvb = tvb_new_subset (tvb, next_offset, -1, -1);
+ }
+
+ if ((ftype != FC_FTYPE_LINKCTL) && (ftype != FC_FTYPE_BLS)) {
+ if (!dissector_try_port (fcftype_dissector_table, ftype, next_tvb,
+ pinfo, tree)) {
+ call_dissector (data_handle, next_tvb, pinfo, tree);
+ }
+ } else if (ftype == FC_FTYPE_BLS) {
+ if ((fchdr.r_ctl & 0x0F) == FC_BLS_BAACC) {
+ dissect_fc_ba_acc (next_tvb, pinfo, tree);
+ } else if ((fchdr.r_ctl & 0x0F) == FC_BLS_BARJT) {
+ dissect_fc_ba_rjt (next_tvb, pinfo, tree);
+ }
+ }
+
+ tap_queue_packet(fc_tap, pinfo, &fchdr);
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_fc(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_fc_rctl,
+ { "R_CTL", "fc.r_ctl", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "R_CTL", HFILL }},
+ { &hf_fc_ftype,
+ {"Frame type", "fc.ftype", FT_UINT8, BASE_HEX, VALS(fc_ftype_vals),
+ 0x0, "Derived Type", HFILL}},
+ { &hf_fc_did,
+ { "Dest Addr", "fc.d_id", FT_STRING, BASE_HEX, NULL, 0x0,
+ "Destination Address", HFILL}},
+ { &hf_fc_csctl,
+ {"CS_CTL", "fc.cs_ctl", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "CS_CTL", HFILL}},
+ { &hf_fc_sid,
+ {"Src Addr", "fc.s_id", FT_STRING, BASE_HEX, NULL, 0x0,
+ "Source Address", HFILL}},
+ { &hf_fc_id,
+ {"Addr", "fc.id", FT_STRING, BASE_HEX, NULL, 0x0,
+ "Source or Destination Address", HFILL}},
+ { &hf_fc_type,
+ {"Type", "fc.type", FT_UINT8, BASE_HEX, VALS (fc_fc4_val), 0x0,
+ "", HFILL}},
+ { &hf_fc_fctl,
+ {"F_CTL", "fc.f_ctl", FT_UINT24, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fc_seqid,
+ {"SEQ_ID", "fc.seq_id", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Sequence ID", HFILL}},
+ { &hf_fc_dfctl,
+ {"DF_CTL", "fc.df_ctl", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fc_seqcnt,
+ {"SEQ_CNT", "fc.seq_cnt", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Sequence Count", HFILL}},
+ { &hf_fc_oxid,
+ {"OX_ID", "fc.ox_id", FT_UINT16, BASE_HEX, NULL, 0x0, "Originator ID",
+ HFILL}},
+ { &hf_fc_rxid,
+ {"RX_ID", "fc.rx_id", FT_UINT16, BASE_HEX, NULL, 0x0, "Receiver ID",
+ HFILL}},
+ { &hf_fc_param,
+ {"Parameter", "fc.parameter", FT_UINT32, BASE_HEX, NULL, 0x0, "Parameter",
+ HFILL}},
+
+ { &hf_fc_reassembled,
+ {"Reassembled Frame", "fc.reassembled", FT_BOOLEAN, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fc_nh_da,
+ {"Network DA", "fc.nethdr.da", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fc_nh_sa,
+ {"Network SA", "fc.nethdr.sa", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+
+ /* Basic Link Svc field definitions */
+ { &hf_fc_bls_seqid_vld,
+ {"SEQID Valid", "fc.bls_seqidvld", FT_UINT8, BASE_HEX,
+ VALS (fc_bls_seqid_val), 0x0, "", HFILL}},
+ { &hf_fc_bls_lastvld_seqid,
+ {"Last Valid SEQID", "fc.bls_lastseqid", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fc_bls_oxid,
+ {"OXID", "fc.bls_oxid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fc_bls_rxid,
+ {"RXID", "fc.bls_rxid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fc_bls_lowseqcnt,
+ {"Low SEQCNT", "fc.bls_lseqcnt", FT_UINT16, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fc_bls_hiseqcnt,
+ {"High SEQCNT", "fc.bls_hseqcnt", FT_UINT16, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fc_bls_rjtcode,
+ {"Reason", "fc.bls_reason", FT_UINT8, BASE_HEX, VALS(fc_bls_barjt_val),
+ 0x0, "", HFILL}},
+ { &hf_fc_bls_rjtdetail,
+ {"Reason Explanantion", "fc.bls_rjtdetail", FT_UINT8, BASE_HEX,
+ VALS (fc_bls_barjt_det_val), 0x0, "", HFILL}},
+ { &hf_fc_bls_vendor,
+ {"Vendor Unique Reason", "fc.bls_vnduniq", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fc_fctl_exchange_responder,
+ {"ExgRpd", "fc.fctl.exchange_responder", FT_BOOLEAN, 24, TFS(&tfs_fc_fctl_exchange_responder),
+ FC_FCTL_EXCHANGE_RESPONDER, "Exchange Responder?", HFILL}},
+ { &hf_fc_fctl_seq_recipient,
+ {"SeqRec", "fc.fctl.seq_recipient", FT_BOOLEAN, 24, TFS(&tfs_fc_fctl_seq_recipient),
+ FC_FCTL_SEQ_RECIPIENT, "Seq Recipient?", HFILL}},
+ { &hf_fc_fctl_exchange_first,
+ {"ExgFst", "fc.fctl.exchange_first", FT_BOOLEAN, 24, TFS(&tfs_fc_fctl_exchange_first),
+ FC_FCTL_EXCHANGE_FIRST, "First Exchange?", HFILL}},
+ { &hf_fc_fctl_exchange_last,
+ {"ExgLst", "fc.fctl.exchange_last", FT_BOOLEAN, 24, TFS(&tfs_fc_fctl_exchange_last),
+ FC_FCTL_EXCHANGE_LAST, "Last Exchange?", HFILL}},
+ { &hf_fc_fctl_seq_last,
+ {"SeqLst", "fc.fctl.seq_last", FT_BOOLEAN, 24, TFS(&tfs_fc_fctl_seq_last),
+ FC_FCTL_SEQ_LAST, "Last Sequence?", HFILL}},
+ { &hf_fc_fctl_priority,
+ {"Pri", "fc.fctl.priority", FT_BOOLEAN, 24, TFS(&tfs_fc_fctl_priority),
+ FC_FCTL_PRIORITY, "Priority", HFILL}},
+ { &hf_fc_fctl_transfer_seq_initiative,
+ {"TSI", "fc.fctl.transfer_seq_initiative", FT_BOOLEAN, 24, TFS(&tfs_fc_fctl_transfer_seq_initiative),
+ FC_FCTL_TRANSFER_SEQ_INITIATIVE, "Transfer Seq Initiative", HFILL}},
+ { &hf_fc_fctl_rexmitted_seq,
+ {"RetSeq", "fc.fctl.rexmitted_seq", FT_BOOLEAN, 24, TFS(&tfs_fc_fctl_rexmitted_seq),
+ FC_FCTL_REXMITTED_SEQ, "Retransmitted Sequence", HFILL}},
+ { &hf_fc_fctl_rel_offset,
+ {"RelOff", "fc.fctl.rel_offset", FT_BOOLEAN, 24, TFS(&tfs_fc_fctl_rel_offset),
+ FC_FCTL_REL_OFFSET, "rel offset", HFILL}},
+ { &hf_fc_fctl_last_data_frame,
+ {"LDF", "fc.fctl.last_data_frame", FT_UINT24, BASE_HEX, VALS(last_data_frame_vals),
+ FC_FCTL_LAST_DATA_FRAME_MASK, "Last Data Frame?", HFILL}},
+ { &hf_fc_fctl_ack_0_1,
+ {"A01", "fc.fctl.ack_0_1", FT_UINT24, BASE_HEX, VALS(ack_0_1_vals),
+ FC_FCTL_ACK_0_1_MASK, "Ack 0/1 value", HFILL}},
+ { &hf_fc_fctl_abts_ack,
+ {"AA", "fc.fctl.abts_ack", FT_UINT24, BASE_HEX, VALS(abts_ack_vals),
+ FC_FCTL_ABTS_MASK, "ABTS ACK values", HFILL}},
+ { &hf_fc_fctl_abts_not_ack,
+ {"AnA", "fc.fctl.abts_not_ack", FT_UINT24, BASE_HEX, VALS(abts_not_ack_vals),
+ FC_FCTL_ABTS_MASK, "ABTS not ACK vals", HFILL}},
+ { &hf_fc_exchange_first_frame,
+ { "Exchange First In", "fc.exchange_first_frame", FT_FRAMENUM, BASE_NONE, NULL,
+ 0, "The first frame of this exchange is in this frame", HFILL }},
+ { &hf_fc_exchange_last_frame,
+ { "Exchange Last In", "fc.exchange_last_frame", FT_FRAMENUM, BASE_NONE, NULL,
+ 0, "The last frame of this exchange is in this frame", HFILL }},
+ { &hf_fc_time,
+ { "Time from Exchange First", "fc.time", FT_RELATIVE_TIME, BASE_NONE, NULL,
+ 0, "Time since the first frame of the Exchange", HFILL }},
+ { &hf_fc_eisl,
+ {"EISL Header", "fc.eisl", FT_BYTES, BASE_HEX, NULL, 0, "EISL Header", HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fc,
+ &ett_fcbls,
+ &ett_fctl
+ };
+
+ module_t *fc_module;
+
+ /* Register the protocol name and description */
+ proto_fc = proto_register_protocol ("Fibre Channel", "FC", "fc");
+ register_dissector ("fc", dissect_fc, proto_fc);
+ fc_tap = register_tap("fc");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ fcftype_dissector_table = register_dissector_table ("fc.ftype",
+ "FC Frame Type",
+ FT_UINT8, BASE_HEX);
+
+ /* Register preferences */
+ fc_module = prefs_register_protocol (proto_fc, NULL);
+ prefs_register_bool_preference (fc_module,
+ "reassemble",
+ "Reassemble multi-frame sequences",
+ "If enabled, reassembly of multi-frame "
+ "sequences is done",
+ &fc_reassemble);
+ prefs_register_uint_preference (fc_module,
+ "max_frame_size", "Max FC Frame Size",
+ "This is the size of non-last frames in a "
+ "multi-frame sequence", 10,
+ &fc_max_frame_size);
+
+ register_init_routine(fc_defragment_init);
+ register_init_routine (fc_exchange_init_protocol);
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fc (void)
+{
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-fc.h b/epan/dissectors/packet-fc.h
new file mode 100644
index 0000000000..772a9f4ce0
--- /dev/null
+++ b/epan/dissectors/packet-fc.h
@@ -0,0 +1,152 @@
+/* packet-fc.h
+ * Basic Fibre Channel Header definitions
+ * Copyright 2002 Dinesh G Dutt (ddutt@cisco.com)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FC_H_
+#define __PACKET_FC_H_
+
+/* R_CTL upper bits creates a classification tree */
+#define FC_RCTL_DEV_DATA 0x00
+#define FC_RCTL_ELS 0x20
+#define FC_RCTL_LINK_DATA 0x30
+#define FC_RCTL_VIDEO 0x40
+#define FC_RCTL_BLS 0x80
+#define FC_RCTL_LINK_CTL 0xC0
+/* XXX - is 0xF0 Extended Routing? It is in the FC-FS draft on the T11
+ Web site. */
+
+#define FC_TYPE_CMNSVC 0x0 /* Used in PRLI Svc Param Page */
+
+/* TYPE definitions for Basic or Extended Link_Data */
+#define FC_TYPE_ELS 0x1
+
+/* TYPE definitions for FC-4 */
+#define FC_TYPE_LLCSNAP 0x4
+#define FC_TYPE_IP 0x5
+#define FC_TYPE_SCSI 0x8
+#define FC_TYPE_SB_TO_CU 0x1B
+#define FC_TYPE_SB_FROM_CU 0x1C
+#define FC_TYPE_FCCT 0x20
+#define FC_TYPE_SWILS 0x22
+#define FC_TYPE_AL 0x23
+#define FC_TYPE_SNMP 0x24
+
+
+/*
+ * the following allows TAP code access to the messages
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string fc_fc4_val[];
+
+/* DF_CTL bits */
+#define FC_DFCTL_DH 0x03 /* Device_Header type bits: */
+#define FC_DFCTL_DH_NONE 0x00 /* No Device_Header */
+#define FC_DFCTL_DH_16_BYTE 0x01 /* 16 Byte Device_Header */
+#define FC_DFCTL_DH_32_BYTE 0x02 /* 32 Byte Device_Header */
+#define FC_DFCTL_DH_64_BYTE 0x03 /* 64 Byte Device_Header */
+#define FC_DFCTL_AH 0x10 /* Association_Header bit */
+#define FC_DFCTL_NH 0x20 /* Association_Header bit */
+#define FC_DFCTL_SH 0x40 /* reserved for security header */
+
+/* Derived Frame types (used for ULP demux) */
+#define FC_FTYPE_UNDEF 0x0
+#define FC_FTYPE_SWILS 0x1
+#define FC_FTYPE_IP 0x2
+#define FC_FTYPE_SCSI 0x3
+#define FC_FTYPE_BLS 0x4
+#define FC_FTYPE_ELS 0x5
+#define FC_FTYPE_FCCT 0x7
+#define FC_FTYPE_LINKDATA 0x8
+#define FC_FTYPE_VDO 0x9
+#define FC_FTYPE_LINKCTL 0xA
+#define FC_FTYPE_SWILS_RSP 0xB
+#define FC_FTYPE_SBCCS 0xC
+
+/* Well-known Address Definitions (in Network order) */
+#define FC_WKA_MULTICAST 0xFFFFF5
+#define FC_WKA_CLKSYNC 0xFFFFF6
+#define FC_WKA_KEYDIST 0xFFFFF7
+#define FC_WKA_ALIAS 0xFFFFF8
+#define FC_WKA_QOSF 0xFFFFF9
+#define FC_WKA_MGMT 0xFFFFFA
+#define FC_WKA_TIME 0xFFFFFB
+#define FC_WKA_DNS 0xFFFFFC
+#define FC_WKA_FABRIC_CTRLR 0xFFFFFD
+#define FC_WKA_FPORT 0xFFFFFE
+#define FC_WKA_BCAST 0xFFFFFF
+
+/* Well-known Address Definitions (in little endian) */
+
+/* Information Categories for Link Data & Link Control Frames */
+#define FC_IU_UNCATEGORIZED 0x0
+#define FC_IU_SOLICITED_DATA 0x1
+#define FC_IU_UNSOLICITED_CTL 0x2
+#define FC_IU_SOLICITED_CTL 0x3
+#define FC_IU_UNSOLICITED_DATA 0x4
+#define FC_IU_DATA_DESCRIPTOR 0x5
+#define FC_IU_UNSOLICITED_CMD 0x6
+#define FC_IU_CMD_STATUS 0x7
+
+/* FC_CTL bits */
+#define FC_FCTL_EXCHANGE_RESPONDER 0x800000
+#define FC_FCTL_SEQ_RECIPIENT 0x400000
+#define FC_FCTL_EXCHANGE_FIRST 0x200000
+#define FC_FCTL_EXCHANGE_LAST 0x100000
+#define FC_FCTL_SEQ_LAST 0x080000
+#define FC_FCTL_PRIORITY 0x020000
+#define FC_FCTL_TRANSFER_SEQ_INITIATIVE 0x010000
+#define FC_FCTL_LAST_DATA_FRAME_MASK 0x00c000
+#define FC_FCTL_ACK_0_1_MASK 0x003000
+#define FC_FCTL_REXMITTED_SEQ 0x000200
+#define FC_FCTL_ABTS_MASK 0x000030
+#define FC_FCTL_REL_OFFSET 0x000008
+
+/* structure and functions to keep track of first/last exchange
+ frames and time deltas
+*/
+typedef struct _fc_exchange_data {
+ address s_id;
+ address d_id;
+ guint16 oxid;
+ guint32 first_exchange_frame;
+ guint32 last_exchange_frame;
+ nstime_t fc_time;
+} fc_exchange_data;
+
+/* FC header structure */
+typedef struct _fc_hdr {
+ address s_id;
+ address d_id;
+ guint32 fctl;
+ guint8 type;
+ guint16 seqcnt;
+ guint16 oxid;
+ guint16 rxid;
+ guint8 r_ctl;
+ guint8 cs_ctl;
+ fc_exchange_data *fced;
+} fc_hdr;
+
+#endif /* __PACKET_FC_H_ */
diff --git a/epan/dissectors/packet-fcbls.h b/epan/dissectors/packet-fcbls.h
new file mode 100644
index 0000000000..0517cd0aa5
--- /dev/null
+++ b/epan/dissectors/packet-fcbls.h
@@ -0,0 +1,77 @@
+/* packet-fcbls.h
+ * Fibre Channel Basic Link Services header
+ * Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCBLS_H_
+#define __PACKET_FCBLS_H_
+
+#define FC_BLS_NOP 0x00
+#define FC_BLS_ABTS 0x01
+#define FC_BLS_RMC 0x02
+#define FC_BLS_BAACC 0x04
+#define FC_BLS_BARJT 0x05
+#define FC_BLS_PRMT 0x06
+
+#define FC_BLS_BARJT_INVCMDCODE 0x01
+#define FC_BLS_BARJT_LOGERR 0x03
+#define FC_BLS_BARJT_LOGBSY 0x05
+#define FC_BLS_BARJT_PROTERR 0x07
+#define FC_BLS_BARJT_GENFAIL 0x09
+#define FC_BLS_BARJT_VENDOR 0xFF
+
+static const value_string fc_bls_barjt_val[] = {
+ {FC_BLS_BARJT_INVCMDCODE, "Invalid Cmd Code"},
+ {FC_BLS_BARJT_LOGERR , "Logical Error"},
+ {FC_BLS_BARJT_LOGBSY , "Logical Busy"},
+ {FC_BLS_BARJT_PROTERR , "Protocol Error"},
+ {FC_BLS_BARJT_GENFAIL , "Unable to Perform Cmd"},
+ {FC_BLS_BARJT_VENDOR , "Vendor Unique Error"},
+ {0, NULL},
+};
+
+#define FC_BLS_BARJT_DET_NODET 0x01
+#define FC_BLS_BARJT_DET_INVEXCHG 0x03
+#define FC_BLS_BARJT_DET_SEQABT 0x05
+
+static const value_string fc_bls_barjt_det_val[] = {
+ {FC_BLS_BARJT_DET_NODET , "No Details"},
+ {FC_BLS_BARJT_DET_INVEXCHG, "Invalid OXID-RXID Combo"},
+ {FC_BLS_BARJT_DET_SEQABT , "Sequence Aborted"},
+ {0, NULL},
+};
+
+static const value_string fc_bls_seqid_val[] = {
+ {0x80, "Yes"},
+ {0x0, "No"},
+ {0, NULL},
+};
+
+typedef struct _fc_bls_ba_rjt {
+ guint8 rsvd;
+ guint8 reason_code;
+ guint8 rjt_detail;
+ guint8 vendor_uniq;
+} fc_bls_ba_rjt;
+
+#endif
diff --git a/epan/dissectors/packet-fcct.c b/epan/dissectors/packet-fcct.c
new file mode 100644
index 0000000000..269edacd97
--- /dev/null
+++ b/epan/dissectors/packet-fcct.c
@@ -0,0 +1,307 @@
+/* packet-fcct.c
+ * Routines for FC Common Transport Protocol (used by GS3 services)
+ * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fcct.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_fcct = -1;
+static int hf_fcct_revision = -1;
+static int hf_fcct_inid = -1;
+static int hf_fcct_gstype = -1;
+static int hf_fcct_gssubtype = -1;
+static int hf_fcct_options = -1;
+static int hf_fcct_server = -1; /* derived field */
+
+/* Extended preamble fields */
+static int hf_fcct_ext_said = -1;
+static int hf_fcct_ext_tid = -1;
+static int hf_fcct_ext_reqname = -1;
+static int hf_fcct_ext_tstamp = -1;
+static int hf_fcct_ext_authblk = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_fcct = -1;
+static gint ett_fcct_ext = -1; /* for the extended header */
+
+const value_string fc_ct_rjt_code_vals [] = {
+ {FCCT_RJT_INVCMDCODE, "Invalid Cmd Code"},
+ {FCCT_RJT_INVVERSION, "Invalid Version Level"},
+ {FCCT_RJT_LOGICALERR, "Logical Error"},
+ {FCCT_RJT_INVSIZE, "Invalid CT_IU Size"},
+ {FCCT_RJT_LOGICALBSY, "Logical Busy"},
+ {FCCT_RJT_PROTOERR, "Protocol Error"},
+ {FCCT_RJT_GENFAIL, "Unable to Perform Cmd"},
+ {FCCT_RJT_CMDNOTSUPP, "Cmd Not Supported"},
+ {0, NULL},
+};
+
+static const value_string fc_ct_gstype_vals[] = {
+ {FCCT_GSTYPE_KEYSVC, "Key Service"},
+ {FCCT_GSTYPE_ALIASSVC, "Alias Service"},
+ {FCCT_GSTYPE_MGMTSVC, "Management Service"},
+ {FCCT_GSTYPE_TIMESVC, "Time Service"},
+ {FCCT_GSTYPE_DIRSVC, "Directory Service"},
+ {0, NULL},
+};
+
+static const value_string fc_ct_gsserver_vals[] = {
+ {FCCT_GSRVR_DNS, "dNS"},
+ {FCCT_GSRVR_IP, "IP"},
+ {FCCT_GSRVR_FCS, "Fabric Config Server"},
+ {FCCT_GSRVR_UNS, "Unzoned Name Server"},
+ {FCCT_GSRVR_FZS, "Fabric Zone Server"},
+ {FCCT_GSRVR_TS, "Time Server"},
+ {FCCT_GSRVR_KS, "Key Server"},
+ {FCCT_GSRVR_AS, "Alias Server"},
+ {0, NULL},
+};
+
+static dissector_table_t fcct_gserver_table;
+static dissector_handle_t data_handle;
+
+static guint8
+get_gs_server (guint8 gstype, guint8 gssubtype)
+{
+ switch (gstype) {
+ case FCCT_GSTYPE_KEYSVC:
+ return FCCT_GSRVR_KS;
+ case FCCT_GSTYPE_ALIASSVC:
+ if (gssubtype == FCCT_GSSUBTYPE_AS)
+ return FCCT_GSRVR_AS;
+ return FCCT_GSRVR_UNKNOWN;
+ case FCCT_GSTYPE_MGMTSVC:
+ if (gssubtype == FCCT_GSSUBTYPE_FCS)
+ return FCCT_GSRVR_FCS;
+ else if (gssubtype == FCCT_GSSUBTYPE_UNS)
+ return FCCT_GSRVR_UNS;
+ else if (gssubtype == FCCT_GSSUBTYPE_FZS)
+ return FCCT_GSRVR_FZS;
+ else return FCCT_GSRVR_UNKNOWN;
+ case FCCT_GSTYPE_TIMESVC:
+ if (gssubtype == FCCT_GSSUBTYPE_TS)
+ return FCCT_GSRVR_TS;
+ return FCCT_GSRVR_UNKNOWN;
+ case FCCT_GSTYPE_DIRSVC:
+ if (gssubtype == FCCT_GSSUBTYPE_DNS)
+ return FCCT_GSRVR_DNS;
+ else if (gssubtype == FCCT_GSSUBTYPE_IP)
+ return FCCT_GSRVR_IP;
+ return FCCT_GSRVR_UNKNOWN;
+ default:
+ return FCCT_GSRVR_UNKNOWN;
+ }
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_fcct (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *fcct_tree;
+ tvbuff_t *next_tvb;
+ int in_id,
+ offset = 0;
+ guint8 server;
+ fc_ct_preamble cthdr;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FC_CT");
+
+ /*
+ cthdr.revision = tvb_get_guint8 (tvb, offset++);
+ cthdr.in_id = tvb_get_ntoh24 (tvb, offset);
+ offset += 3;
+
+ cthdr.gstype = tvb_get_guint8 (tvb, offset++);
+ cthdr.options = tvb_get_guint8 (tvb, offset++);
+ */
+ tvb_memcpy (tvb, (guint8 *)&cthdr, offset, FCCT_PRMBL_SIZE);
+ cthdr.revision = tvb_get_guint8 (tvb, offset++);
+ cthdr.in_id = tvb_get_ntoh24 (tvb, offset);
+ cthdr.opcode = ntohs (cthdr.opcode);
+ cthdr.maxres_size = ntohs (cthdr.maxres_size);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if (cthdr.opcode < FCCT_MSG_REQ_MAX) {
+ col_append_str (pinfo->cinfo, COL_INFO, " Request");
+ }
+ else if (cthdr.opcode == FCCT_MSG_ACC) {
+ col_append_str (pinfo->cinfo, COL_INFO, " Accept");
+ }
+ else if (cthdr.opcode == FCCT_MSG_RJT) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Reject (%s)",
+ val_to_str (cthdr.rjt_code, fc_ct_rjt_code_vals, "0x%x"));
+ }
+ else {
+ col_append_str (pinfo->cinfo, COL_INFO, " Reserved");
+ }
+ }
+
+ in_id = cthdr.in_id;
+ in_id = htonl (in_id) >> 8;
+
+ /* Determine server */
+ server = get_gs_server (cthdr.gstype, cthdr.gssubtype);
+
+ if (tree) {
+ offset = 0;
+ ti = proto_tree_add_protocol_format (tree, proto_fcct, tvb, 0, FCCT_PRMBL_SIZE,
+ "FC_CT");
+ fcct_tree = proto_item_add_subtree (ti, ett_fcct);
+
+ proto_tree_add_item (fcct_tree, hf_fcct_revision, tvb, offset++,
+ sizeof (guint8), 0);
+ proto_tree_add_string (fcct_tree, hf_fcct_inid, tvb, offset, 3,
+ fc_to_str ((guint8 *)&in_id));
+ offset += 3; /* sizeof FC address */
+
+ proto_tree_add_item (fcct_tree, hf_fcct_gstype, tvb, offset++,
+ sizeof (guint8), 0);
+ proto_tree_add_item (fcct_tree, hf_fcct_gssubtype, tvb, offset,
+ sizeof (guint8), 0);
+ proto_tree_add_uint (fcct_tree, hf_fcct_server, tvb, offset++, 1,
+ server);
+ proto_tree_add_item (fcct_tree, hf_fcct_options, tvb, offset++,
+ sizeof (guint8), 0);
+
+ }
+ /* We do not change the starting offset for the next protocol in the
+ * chain since the fc_ct header is common to the sub-protocols.
+ */
+ next_tvb = tvb_new_subset (tvb, 0, -1, -1);
+ if (!dissector_try_port (fcct_gserver_table, server, next_tvb, pinfo,
+ tree)) {
+ call_dissector (data_handle, next_tvb, pinfo, tree);
+ }
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_fcct(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_fcct_revision,
+ {"Revision", "fcct.revision", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcct_inid,
+ {"IN_ID", "fcct.in_id", FT_STRING, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcct_gstype,
+ {"GS Type", "fcct.gstype", FT_UINT8, BASE_HEX, VALS(fc_ct_gstype_vals),
+ 0x0, "", HFILL}},
+ { &hf_fcct_gssubtype,
+ {"GS Subtype", "fcct.gssubtype", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcct_server,
+ {"Server", "fcct.server", FT_UINT8, BASE_HEX,
+ VALS (fc_ct_gsserver_vals), 0x0,
+ "Derived from GS Type & Subtype fields", HFILL}},
+ { &hf_fcct_options,
+ {"Options", "fcct.options", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcct_ext_said,
+ {"Auth SAID", "fcct.ext_said", FT_UINT32, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcct_ext_tid,
+ {"Transaction ID", "fcct.ext_tid", FT_UINT32, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcct_ext_reqname,
+ {"Requestor Port Name", "fcct_ext_reqnm", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcct_ext_tstamp,
+ {"Timestamp", "fcct_ext_tstamp", FT_BYTES, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcct_ext_authblk,
+ {"Auth Hash Blk", "fcct_ext_authblk", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fcct,
+ &ett_fcct_ext,
+ };
+
+ /* Register the protocol name and description */
+ proto_fcct = proto_register_protocol("Fibre Channel Common Transport", "FC_CT", "fcct");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fcct, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ fcct_gserver_table = register_dissector_table ("fcct.server",
+ "Server",
+ FT_UINT8, BASE_HEX);
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fcct (void)
+{
+ dissector_handle_t fcct_handle;
+
+ fcct_handle = create_dissector_handle (dissect_fcct, proto_fcct);
+ dissector_add("fc.ftype", FC_FTYPE_FCCT, fcct_handle);
+
+ data_handle = find_dissector ("data");
+}
+
+
diff --git a/epan/dissectors/packet-fcct.h b/epan/dissectors/packet-fcct.h
new file mode 100644
index 0000000000..667a8c8a72
--- /dev/null
+++ b/epan/dissectors/packet-fcct.h
@@ -0,0 +1,97 @@
+/* packet-fcct.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCCT_H_
+#define __PACKET_FCCT_H_
+
+/* Well-known GSTYPEs */
+#define FCCT_GSTYPE_KEYSVC 0xF7
+#define FCCT_GSTYPE_ALIASSVC 0xF8
+#define FCCT_GSTYPE_MGMTSVC 0xFA
+#define FCCT_GSTYPE_TIMESVC 0xFB
+#define FCCT_GSTYPE_DIRSVC 0xFC
+
+/* Well-known GSSUBTYPES */
+/* Actual servers serving the directory service type identified by subtype */
+#define FCCT_GSSUBTYPE_DNS 0x02
+#define FCCT_GSSUBTYPE_IP 0x03
+#define FCCT_GSSUBTYPE_FCS 0x01
+#define FCCT_GSSUBTYPE_UNS 0x02
+#define FCCT_GSSUBTYPE_FZS 0x03
+#define FCCT_GSSUBTYPE_AS 0x01
+#define FCCT_GSSUBTYPE_TS 0x01
+
+/* Derived field: Server servicing the request */
+#define FCCT_GSRVR_DNS 0x1
+#define FCCT_GSRVR_IP 0x2
+#define FCCT_GSRVR_FCS 0x3
+#define FCCT_GSRVR_UNS 0x4
+#define FCCT_GSRVR_FZS 0x5
+#define FCCT_GSRVR_AS 0x6
+#define FCCT_GSRVR_TS 0x7
+#define FCCT_GSRVR_KS 0x8
+#define FCCT_GSRVR_UNKNOWN 0xFF
+
+/* Reject code definitions */
+#define FCCT_RJT_INVCMDCODE 0x1
+#define FCCT_RJT_INVVERSION 0x2
+#define FCCT_RJT_LOGICALERR 0x3
+#define FCCT_RJT_INVSIZE 0x4
+#define FCCT_RJT_LOGICALBSY 0x5
+#define FCCT_RJT_PROTOERR 0x7
+#define FCCT_RJT_GENFAIL 0x9
+#define FCCT_RJT_CMDNOTSUPP 0xB
+
+#define FCCT_MSG_REQ_MAX 0x8000 /* All opcodes below this are requests */
+#define FCCT_MSG_RJT 0x8001 /* Reject CT message */
+#define FCCT_MSG_ACC 0x8002 /* Accept CT message */
+
+#define FCCT_PRMBL_SIZE 16
+#define FCCT_EXTPRMBL_SIZE 88
+
+extern const value_string fc_ct_rjt_code_vals [];
+
+typedef struct _fc_ct_preamble {
+ guint32 in_id:24,
+ revision:8;
+ guint8 gstype;
+ guint8 gssubtype;
+ guint8 options;
+ guint8 rsvd1;
+ guint16 opcode;
+ guint16 maxres_size;
+ guint8 rsvd2;
+ guint8 rjt_code;
+ guint8 rjt_code_det;
+ guint8 rjt_code_vendor;
+} fc_ct_preamble;
+
+typedef struct _fc_ct_ext_hdr {
+ guint32 auth_said;
+ guint32 tid;
+ guint32 req_pname[2];
+ guint32 timestamp[2];
+ guint32 auth_hashblk[15];
+} fc_ct_ext_hdr;
+
+#endif
diff --git a/epan/dissectors/packet-fcdns.c b/epan/dissectors/packet-fcdns.c
new file mode 100644
index 0000000000..78c2099ebd
--- /dev/null
+++ b/epan/dissectors/packet-fcdns.c
@@ -0,0 +1,1939 @@
+/* packet-fc-dns.c
+ * Routines for FC distributed Name Server (dNS)
+ * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fcct.h"
+#include "packet-fcdns.h"
+#include "packet-fcswils.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_fcdns = -1;
+static int hf_fcdns_gssubtype = -1;
+static int hf_fcdns_opcode = -1;
+static int hf_fcdns_reason = -1;
+static int hf_fcdns_vendor = -1;
+static int hf_fcdns_req_portid = -1;
+static int hf_fcdns_rply_pname = -1;
+static int hf_fcdns_rply_nname = -1;
+static int hf_fcdns_rply_cos = -1;
+static int hf_fcdns_rply_gft = -1;
+static int hf_fcdns_rply_snamelen = -1;
+static int hf_fcdns_rply_sname = -1;
+static int hf_fcdns_rply_ptype = -1;
+static int hf_fcdns_rply_fpname = -1;
+static int hf_fcdns_fc4type = -1;
+static int hf_fcdns_rply_fc4type = -1;
+static int hf_fcdns_rply_fc4desc = -1;
+static int hf_fcdns_rply_fc4feat = -1;
+static int hf_fcdns_req_pname = -1;
+static int hf_fcdns_rply_portid = -1;
+static int hf_fcdns_req_nname = -1;
+static int hf_fcdns_req_domainscope = -1;
+static int hf_fcdns_req_areascope = -1;
+static int hf_fcdns_req_fc4type = -1;
+static int hf_fcdns_req_ptype = -1;
+static int hf_fcdns_req_fc4feature = -1;
+static int hf_fcdns_req_cos = -1;
+static int hf_fcdns_req_fc4types = -1;
+static int hf_fcdns_req_snamelen = -1;
+static int hf_fcdns_req_sname = -1;
+static int hf_fcdns_rply_spnamelen = -1;
+static int hf_fcdns_rply_spname = -1;
+static int hf_fcdns_req_spnamelen = -1;
+static int hf_fcdns_req_spname = -1;
+static int hf_fcdns_rply_ipa = -1;
+static int hf_fcdns_rply_ipnode = -1;
+static int hf_fcdns_rply_ipport = -1;
+static int hf_fcdns_rply_fc4desclen = -1;
+static int hf_fcdns_rply_hrdaddr = -1;
+static int hf_fcdns_req_fdesclen = -1;
+static int hf_fcdns_req_fdesc = -1;
+static int hf_fcdns_req_ip = -1;
+static int hf_fcdns_rjtdetail = -1;
+static int hf_fcdns_zone_mbrtype = -1;
+static int hf_fcdns_zone_mbrid = -1;
+static int hf_fcdns_zonenm = -1;
+static int hf_fcdns_portip = -1;
+static int hf_fcdns_sw2_objfmt = -1;
+static int hf_fcdns_num_fc4desc = -1;
+static int hf_fcdns_rply_ownerid = -1;
+static int hf_fcdns_maxres_size = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_fcdns = -1;
+
+typedef struct _fcdns_conv_key {
+ guint32 conv_idx;
+} fcdns_conv_key_t;
+
+typedef struct _fcdns_conv_data {
+ guint32 opcode;
+} fcdns_conv_data_t;
+
+GHashTable *fcdns_req_hash = NULL;
+GMemChunk *fcdns_req_keys = NULL;
+GMemChunk *fcdns_req_vals = NULL;
+guint32 fcdns_init_count = 25;
+
+static dissector_handle_t data_handle;
+
+/*
+ * Hash Functions
+ */
+static gint
+fcdns_equal(gconstpointer v, gconstpointer w)
+{
+ fcdns_conv_key_t *v1 = (fcdns_conv_key_t *)v;
+ fcdns_conv_key_t *v2 = (fcdns_conv_key_t *)w;
+
+ return (v1->conv_idx == v2->conv_idx);
+}
+
+static guint
+fcdns_hash (gconstpointer v)
+{
+ fcdns_conv_key_t *key = (fcdns_conv_key_t *)v;
+ guint val;
+
+ val = key->conv_idx;
+
+ return val;
+}
+
+/*
+ * Protocol initialization
+ */
+static void
+fcdns_init_protocol(void)
+{
+ if (fcdns_req_keys)
+ g_mem_chunk_destroy (fcdns_req_keys);
+ if (fcdns_req_vals)
+ g_mem_chunk_destroy (fcdns_req_vals);
+ if (fcdns_req_hash)
+ g_hash_table_destroy(fcdns_req_hash);
+
+ fcdns_req_hash = g_hash_table_new(fcdns_hash, fcdns_equal);
+ fcdns_req_keys = g_mem_chunk_new ("fcdns_req_keys",
+ sizeof(fcdns_conv_key_t),
+ fcdns_init_count *
+ sizeof(fcdns_conv_key_t),
+ G_ALLOC_AND_FREE);
+ fcdns_req_vals = g_mem_chunk_new ("fcdns_req_vals",
+ sizeof(fcdns_conv_data_t),
+ fcdns_init_count *
+ sizeof(fcdns_conv_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+static gchar *
+fccos_to_str (tvbuff_t *tvb, int offset, gchar *cosstr)
+{
+ int stroff = 0,
+ cos = 0;
+
+ if (cosstr == NULL)
+ return NULL;
+
+ cos = tvb_get_ntohl (tvb, offset);
+
+ cosstr[0] = '\0';
+
+ if (cos & 0x1) {
+ strcpy (cosstr, "F, ");
+ stroff += 3;
+ }
+
+ if (cos & 0x2) {
+ strcpy (&cosstr[stroff], "1, ");
+ stroff += 3;
+ }
+
+ if (cos & 0x4) {
+ strcpy (&cosstr[stroff], "2, ");
+ stroff += 3;
+ }
+
+ if (cos & 0x8) {
+ strcpy (&cosstr[stroff], "3, ");
+ stroff += 3;
+ }
+
+ if (cos & 0x10) {
+ strcpy (&cosstr[stroff], "4, ");
+ stroff += 3;
+ }
+
+ if (cos & 0x40) {
+ strcpy (&cosstr[stroff], "6");
+ }
+
+ return (cosstr);
+}
+
+/* The feature routines just decode FCP's FC-4 features field */
+static gchar *
+fc4feature_to_str (guint8 fc4feature, guint8 fc4type, gchar *str)
+{
+ int stroff = 0;
+
+ *str = '\0';
+
+ if (fc4type == FC_TYPE_SCSI) {
+ if (fc4feature & 0x1) {
+ strcpy (str, "T, ");
+ stroff += 3;
+ }
+
+ if (fc4feature & 0x2) {
+ strcpy (&str[stroff], "I");
+ }
+ }
+ else {
+ sprintf (str, "0x%x", fc4feature);
+ }
+ return (str);
+}
+
+static gchar *
+fc4ftrs_to_str (tvbuff_t *tvb, int offset, gchar *str)
+{
+ guint8 fc4feature;
+ int stroff = 0;
+
+ if (str == NULL) {
+ return NULL;
+ }
+
+ *str = '\0';
+ fc4feature = tvb_get_guint8 (tvb, offset+7);
+
+ if (fc4feature & 0x1) {
+ strcpy (str, "T, ");
+ stroff += 3;
+ }
+
+ if (fc4feature & 0x2) {
+ strcpy (&str[stroff], "I");
+ }
+
+ return (str);
+}
+
+/* Decodes LLC/SNAP, IP, FCP, VI, GS, SW_ILS types only */
+/* Max len of str to be allocated by caller is 40 */
+static gchar *
+fc4type_to_str (tvbuff_t *tvb, int offset, gchar *str)
+{
+ guint32 fc4tword;
+ int stroff = 0;
+
+ if (str == NULL) {
+ return NULL;
+ }
+
+ *str = '\0';
+
+ fc4tword = tvb_get_ntohl (tvb, offset);
+
+ if (fc4tword & 0x10) {
+ strcpy (str, "LLC/SNAP, ");
+ stroff += 10;
+ }
+
+ if (fc4tword & 0x20) {
+ strcpy (&str[stroff], "IP, ");
+ stroff += 4;
+ }
+
+ if (fc4tword & 0x0100) {
+ strcpy (&str[stroff], "FCP, ");
+ stroff += 5;
+ }
+
+ fc4tword = tvb_get_ntohl (tvb, offset+4);
+
+ if (fc4tword & 0x1) {
+ strcpy (&str[stroff], "GS3, ");
+ stroff += 5;
+ }
+
+ if (fc4tword & 0x4) {
+ strcpy (&str[stroff], "SNMP, ");
+ stroff += 6;
+ }
+
+ if (fc4tword & 0x10) {
+ strcpy (&str[stroff], "SW_ILS, ");
+ stroff += 8;
+ }
+
+ fc4tword = tvb_get_ntohl (tvb, offset+8);
+ if (fc4tword & 0x1) {
+ strcpy (&str[stroff], "VI, ");
+ stroff += 3;
+ }
+ return (str);
+}
+
+/* Code to actually dissect the packets */
+
+/* A bunch of get routines have a similar req packet format. The first few
+ * routines deal with this decoding. All assume that tree is valid */
+static void
+dissect_fcdns_req_portid (tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ if (tree) {
+ proto_tree_add_string (tree, hf_fcdns_req_portid, tvb, offset, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset, 3)));
+ }
+}
+
+static void
+dissect_fcdns_ganxt (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 len;
+ gchar str[128];
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset+1);
+ }
+ else {
+ proto_tree_add_item (req_tree, hf_fcdns_rply_ptype, tvb, offset,
+ 1, 0);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid, tvb,
+ offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_rply_pname, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+4,
+ 8)));
+ len = tvb_get_guint8 (tvb, offset+12);
+ proto_tree_add_item (req_tree, hf_fcdns_rply_spnamelen, tvb,
+ offset+12, 1, 0);
+ if (!tvb_offset_exists (tvb, 29+len))
+ return;
+
+ if (len) {
+ proto_tree_add_item (req_tree, hf_fcdns_rply_spname, tvb,
+ offset+13, len, 0);
+ }
+
+ if (tvb_offset_exists (tvb, 292)) {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_nname, tvb,
+ offset+268, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+268,
+ 0)));
+ }
+ if (tvb_offset_exists (tvb, 548)) {
+ len = tvb_get_guint8 (tvb, offset+276);
+ proto_tree_add_item (req_tree, hf_fcdns_rply_snamelen, tvb,
+ offset+276, 1, 0);
+ if (len) {
+ proto_tree_add_item (req_tree, hf_fcdns_rply_sname, tvb,
+ offset+277, len, 0);
+ }
+ }
+ if (tvb_offset_exists (tvb, 556)) {
+ proto_tree_add_item (req_tree, hf_fcdns_rply_ipa, tvb,
+ offset+532, 8, 0);
+ }
+ if (tvb_offset_exists (tvb, 572)) {
+ proto_tree_add_item (req_tree, hf_fcdns_rply_ipnode, tvb,
+ offset+540, 16, 0);
+ }
+ if (tvb_offset_exists (tvb, 576)) {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_cos, tvb, offset+556,
+ 4,
+ fccos_to_str (tvb, offset+556, str));
+ }
+ if (tvb_offset_exists (tvb, 608)) {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_gft, tvb, offset+560,
+ 32,
+ fc4type_to_str (tvb, offset+560, str));
+ }
+ if (tvb_offset_exists (tvb, 624)) {
+ proto_tree_add_item (req_tree, hf_fcdns_rply_ipport, tvb,
+ offset+592, 16, 0);
+ }
+ if (tvb_offset_exists (tvb, 632)) {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_fpname, tvb,
+ offset+608, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+608,
+ 8)));
+ }
+ if (tvb_offset_exists (tvb, 635)) {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_hrdaddr, tvb,
+ offset+617, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+617,
+ 3)));
+ }
+ }
+ }
+}
+
+static void
+dissect_fcdns_gpnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset+1);
+ }
+ else {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_pname, tvb, offset,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gnnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset+1);
+ }
+ else {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_nname, tvb,
+ offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gcsid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ gchar cosstr[64];
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset);
+ }
+ else {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_cos, tvb,
+ offset, 4,
+ fccos_to_str (tvb, offset, cosstr));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gftid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ gchar fc4str[64];
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset+1);
+ }
+ else {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_gft, tvb,
+ offset, 32,
+ fc4type_to_str (tvb, offset, fc4str));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gspnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 len;
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset+1);
+ }
+ else {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (req_tree, hf_fcdns_rply_spnamelen,
+ tvb, offset, 1, 0);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_spname, tvb,
+ offset+1, len,
+ tvb_get_ptr (tvb, offset+1, len));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gptid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset+1);
+ }
+ else {
+ proto_tree_add_item (req_tree, hf_fcdns_rply_ptype, tvb,
+ offset, 1, 0);
+ }
+ }
+}
+
+static void
+dissect_fcdns_gfpnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset+1);
+ }
+ else {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_fpname, tvb,
+ offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ }
+ }
+
+}
+
+static void
+dissect_fcdns_gfdid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ gchar fc4str[128];
+ int tot_len, desclen;
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset+1);
+ proto_tree_add_string (req_tree, hf_fcdns_fc4type, tvb, offset+4,
+ 32,
+ fc4type_to_str (tvb, offset+4, fc4str));
+ }
+ else {
+ tot_len = tvb_length (tvb) - offset; /* excluding CT header */
+ while (tot_len > 0) {
+ /* The count of the descriptors is not returned and so we have
+ * to track the display by the length field */
+ desclen = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (req_tree, hf_fcdns_rply_fc4desc, tvb,
+ offset, desclen, 0);
+ tot_len -= 255; /* descriptors are aligned to 255 bytes */
+ offset += 256;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcdns_gffid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ gchar fc4fstr[128];
+
+ if (req_tree) {
+ if (isreq) {
+ dissect_fcdns_req_portid (tvb, req_tree, offset+1);
+ }
+ else {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_fc4feat, tvb,
+ offset, 128,
+ fc4ftrs_to_str (tvb, offset, fc4fstr));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gidpn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_pname, tvb,
+ offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ }
+ else {
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid, tvb,
+ offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gipppn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_pname, tvb,
+ offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ }
+ else {
+ proto_tree_add_item (req_tree, hf_fcdns_rply_ipport, tvb, offset,
+ 16, 0);
+ }
+ }
+}
+
+static void
+dissect_fcdns_gidnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 islast;
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_nname, tvb,
+ offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ }
+ else {
+ do {
+ islast = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ offset += 4;
+ } while (!(islast & 0x80));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gipnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_nname, tvb,
+ offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ }
+ else {
+ proto_tree_add_item (req_tree, hf_fcdns_rply_ipnode, tvb, offset,
+ 16, 0);
+ }
+ }
+}
+
+static void
+dissect_fcdns_gpnnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 islast;
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_nname, tvb,
+ offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ }
+ else {
+ do {
+ islast = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_rply_pname,
+ tvb, offset+8, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+8,
+ 8)));
+ offset += 16;
+ } while (!(islast & 0x80));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gsnnnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 len;
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_nname, tvb,
+ offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ }
+ else {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (req_tree, hf_fcdns_rply_snamelen, tvb,
+ offset, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_rply_sname, tvb,
+ offset+1, len, 0);
+ }
+ }
+}
+
+static void
+dissect_fcdns_gidft (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 islast;
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_item (req_tree, hf_fcdns_req_domainscope,
+ tvb, offset+1, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_areascope,
+ tvb, offset+2, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_fc4type,
+ tvb, offset+3, 1, 0);
+ }
+ else {
+ do {
+ islast = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ offset += 4;
+ } while (!(islast & 0x80));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gpnft (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 islast;
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_item (req_tree, hf_fcdns_req_domainscope,
+ tvb, offset+1, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_areascope,
+ tvb, offset+2, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_fc4type,
+ tvb, offset+3, 1, 0);
+ }
+ else {
+ do {
+ islast = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_rply_pname,
+ tvb, offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+8,
+ 8)));
+ offset += 16;
+ } while (!(islast & 0x80));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gnnft (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 islast;
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_item (req_tree, hf_fcdns_req_domainscope,
+ tvb, offset+1, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_areascope,
+ tvb, offset+2, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_fc4type,
+ tvb, offset+3, 1, 0);
+ }
+ else {
+ do {
+ islast = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_rply_nname,
+ tvb, offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+8,
+ 8)));
+ offset += 16;
+ } while (!(islast & 0x80));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gidpt (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 islast = 0;
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_item (req_tree, hf_fcdns_req_ptype,
+ tvb, offset, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_domainscope,
+ tvb, offset+1, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_areascope,
+ tvb, offset+2, 1, 0);
+ }
+ else {
+ do {
+ islast = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ offset += 4;
+ } while (!(islast & 0x80));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gidipp (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 islast;
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_item (req_tree, hf_fcdns_req_ip, tvb, offset,
+ 16, 0);
+ }
+ else {
+ do {
+ islast = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ offset += 4;
+ } while (!(islast & 0x80));
+ }
+ }
+}
+
+static void
+dissect_fcdns_gidff (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 islast;
+ gchar str[64];
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_item (req_tree, hf_fcdns_req_domainscope, tvb,
+ offset+1, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_areascope, tvb,
+ offset+2, 1, 0);
+ proto_tree_add_string (req_tree, hf_fcdns_req_fc4feature, tvb,
+ offset+6, 1,
+ fc4feature_to_str (tvb_get_guint8 (tvb, offset+6),
+ tvb_get_guint8 (tvb, offset+7),
+ str));
+ proto_tree_add_item (req_tree, hf_fcdns_req_fc4type, tvb,
+ offset+7, 1, 0);
+ }
+ else {
+ do {
+ islast = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_string (req_tree, hf_fcdns_rply_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ offset += 4;
+ } while (!(islast & 0x80));
+ }
+ }
+}
+
+static void
+dissect_fcdns_rpnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_req_pname, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+4,
+ 8)));
+ }
+ }
+}
+
+static void
+dissect_fcdns_rnnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree) {
+ if (isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid,
+ tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_req_nname, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+4,
+ 8)));
+ }
+ }
+}
+
+static void
+dissect_fcdns_rcsid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ gchar cos[64];
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid, tvb,
+ offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_req_cos, tvb,
+ offset+4, 4,
+ fccos_to_str (tvb, offset+4, cos));
+ }
+}
+
+static void
+dissect_fcdns_rptid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid, tvb,
+ offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_item (req_tree, hf_fcdns_req_ptype, tvb,
+ offset+4, 1, 0);
+ }
+}
+
+static void
+dissect_fcdns_rftid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ gchar fc4str[128];
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid, tvb,
+ offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_req_fc4types, tvb,
+ offset+4, 32,
+ fc4type_to_str (tvb, offset+4, fc4str));
+ }
+}
+
+static void
+dissect_fcdns_rspnid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 len;
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid, tvb,
+ offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_item (req_tree, hf_fcdns_req_spnamelen, tvb,
+ offset+4, 1, 0);
+ len = tvb_get_guint8 (tvb, offset+4);
+
+ proto_tree_add_item (req_tree, hf_fcdns_req_spname, tvb, offset+5,
+ len, 0);
+ }
+}
+
+static void
+dissect_fcdns_rippid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid, tvb,
+ offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_item (req_tree, hf_fcdns_req_ip, tvb,
+ offset+4, 16, 0);
+ }
+}
+
+static void
+dissect_fcdns_rfdid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len, dlen;
+ gchar fc4str[128];
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid, tvb,
+ offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_req_fc4types, tvb,
+ offset+4, 32,
+ fc4type_to_str (tvb, offset+4, fc4str));
+
+ len = tvb_length (tvb) - offset - 36;
+ offset += 36;
+
+ while (len > 0) {
+ dlen = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (req_tree, hf_fcdns_req_fdesclen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_fdesc, tvb, offset+1,
+ len, 0);
+ offset += 256;
+ len -= 256;
+ }
+ }
+}
+
+static void
+dissect_fcdns_rffid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ gchar fc4str[64];
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid, tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
+ proto_tree_add_string (req_tree, hf_fcdns_req_fc4feature, tvb,
+ offset+6, 1,
+ fc4feature_to_str (tvb_get_guint8 (tvb,
+ offset+6),
+ tvb_get_guint8 (tvb,
+ offset+7),
+ fc4str));
+ proto_tree_add_item (req_tree, hf_fcdns_req_fc4type, tvb, offset+7,
+ 1, 0);
+ }
+}
+
+static void
+dissect_fcdns_ripnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_nname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ proto_tree_add_item (req_tree, hf_fcdns_req_ip, tvb, offset+8, 16, 0);
+ }
+}
+
+static void
+dissect_fcdns_rsnnnn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ guint8 len;
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_nname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ len = tvb_get_guint8 (tvb, offset+8);
+
+ proto_tree_add_item (req_tree, hf_fcdns_req_snamelen, tvb, offset+8,
+ 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_req_sname, tvb, offset+9,
+ len, 0);
+ }
+}
+
+static void
+dissect_fcdns_daid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (req_tree && isreq) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid, tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
+ }
+}
+
+static gchar *
+zonenm_to_str (tvbuff_t *tvb, gint offset)
+{
+ int len = tvb_get_guint8 (tvb, offset);
+ return ((gchar *)tvb_get_ptr (tvb, offset+4, len));
+}
+
+static void
+dissect_fcdns_zone_mbr (tvbuff_t *tvb, proto_tree *zmbr_tree, int offset)
+{
+ int mbrlen = 4 + tvb_get_guint8 (tvb, offset+3);
+
+ proto_tree_add_item (zmbr_tree, hf_fcdns_zone_mbrtype, tvb,
+ offset, 1, 0);
+ proto_tree_add_text (zmbr_tree, tvb, offset+2, 1, "Flags: 0x%x",
+ tvb_get_guint8 (tvb, offset+2));
+ proto_tree_add_text (zmbr_tree, tvb, offset+3, 1,
+ "Identifier Length: %d",
+ tvb_get_guint8 (tvb, offset+3));
+ switch (tvb_get_guint8 (tvb, offset)) {
+ case FC_SWILS_ZONEMBR_WWN:
+ proto_tree_add_string (zmbr_tree, hf_fcdns_zone_mbrid, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 8)));
+ break;
+ case FC_SWILS_ZONEMBR_DP:
+ proto_tree_add_string_format (zmbr_tree,
+ hf_fcdns_zone_mbrid,
+ tvb, offset+4, 4, " ",
+ "0x%x",
+ tvb_get_ntohl (tvb,
+ offset+4));
+ break;
+ case FC_SWILS_ZONEMBR_FCID:
+ proto_tree_add_string (zmbr_tree, hf_fcdns_zone_mbrid, tvb,
+ offset+4, 4,
+ fc_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 3)));
+ break;
+ case FC_SWILS_ZONEMBR_ALIAS:
+ proto_tree_add_string (zmbr_tree, hf_fcdns_zone_mbrid, tvb,
+ offset+4,
+ tvb_get_guint8 (tvb, offset+3),
+ zonenm_to_str (tvb, offset+4));
+ break;
+ default:
+ proto_tree_add_string (zmbr_tree, hf_fcdns_zone_mbrid, tvb,
+ offset+4, mbrlen,
+ "Unknown member type format");
+
+ }
+}
+
+static void
+dissect_fcdns_swils_entries (tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ int numrec, i, len;
+ guint8 objfmt;
+ gchar str[512];
+
+ numrec = tvb_get_ntohl (tvb, offset);
+
+ if (tree) {
+ proto_tree_add_text (tree, tvb, offset, 4, "Number of Entries: %d",
+ numrec);
+ offset += 4;
+
+ for (i = 0; i < numrec; i++) {
+ objfmt = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_item (tree, hf_fcdns_sw2_objfmt, tvb, offset, 1, 0);
+ proto_tree_add_string (tree, hf_fcdns_rply_ownerid, tvb, offset+1,
+ 3, fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ proto_tree_add_item (tree, hf_fcdns_rply_ptype, tvb, offset+4,
+ 1, 0);
+ proto_tree_add_string (tree, hf_fcdns_rply_portid, tvb, offset+5, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+5, 3)));
+ proto_tree_add_string (tree, hf_fcdns_rply_pname, tvb, offset+8, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+8,
+ 8)));
+ offset += 16;
+ if (!(objfmt & 0x1)) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcdns_rply_spnamelen, tvb,
+ offset, 1, 0);
+ proto_tree_add_item (tree, hf_fcdns_rply_spname, tvb,
+ offset+1, len, 0);
+ offset += 256;
+ }
+ proto_tree_add_string (tree, hf_fcdns_rply_nname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ offset += 8;
+ if (!(objfmt & 0x1)) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcdns_rply_snamelen, tvb,
+ offset, 1, 0);
+ proto_tree_add_item (tree, hf_fcdns_rply_sname, tvb,
+ offset+1, len, 0);
+ offset += 256;
+ }
+ proto_tree_add_item (tree, hf_fcdns_rply_ipa, tvb, offset, 8, 0);
+ proto_tree_add_item (tree, hf_fcdns_rply_ipnode, tvb, offset+8, 16,
+ 0);
+ proto_tree_add_string (tree, hf_fcdns_rply_cos, tvb, offset+24, 4,
+ fccos_to_str (tvb, offset+24, str));
+ proto_tree_add_string (tree, hf_fcdns_rply_gft, tvb, offset+28,
+ 32,
+ fc4type_to_str (tvb, offset+28, str));
+ proto_tree_add_item (tree, hf_fcdns_rply_ipport, tvb, offset+60,
+ 16, 0);
+ proto_tree_add_string (tree, hf_fcdns_rply_fpname, tvb, offset+76,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+76,
+ 8)));
+ proto_tree_add_string (tree, hf_fcdns_rply_hrdaddr, tvb, offset+85,
+ 3, fc_to_str (tvb_get_ptr (tvb, offset+85,
+ 3)));
+ offset += 88;
+ if (objfmt & 0x2) {
+ proto_tree_add_string (tree, hf_fcdns_rply_fc4feat, tvb,
+ offset, 128,
+ fc4ftrs_to_str (tvb, offset, str));
+ if (tvb_get_guint8 (tvb, offset+129)) {
+ proto_tree_add_item (tree, hf_fcdns_rply_fc4type, tvb,
+ offset+128, 1, 0);
+ proto_tree_add_item (tree, hf_fcdns_num_fc4desc, tvb,
+ offset+129, 1, 0);
+ len = tvb_get_guint8 (tvb, offset+132);
+ proto_tree_add_item (tree, hf_fcdns_rply_fc4desclen, tvb,
+ offset+132, 1, 0);
+ proto_tree_add_item (tree, hf_fcdns_rply_fc4desc, tvb,
+ offset+133, len, 0);
+ }
+ else {
+ proto_tree_add_item (tree, hf_fcdns_num_fc4desc, tvb,
+ offset+129, 1, 0);
+ }
+ offset += 388; /* FC4 desc is 260 bytes, maybe padded */
+ }
+ }
+ }
+}
+
+static void
+dissect_fcdns_geid (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (isreq) {
+ if (req_tree) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_portid, tvb, offset+1,
+ 3, fc_to_str (tvb_get_ptr (tvb, offset+1,
+ 3)));
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_gepn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ if (isreq) {
+ if (req_tree) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_pname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_genn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (isreq) {
+ if (req_tree) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_nname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_geip (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (isreq) {
+ if (req_tree) {
+ proto_tree_add_item (req_tree, hf_fcdns_req_ip, tvb, offset, 16, 0);
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_geft (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ gchar str[128];
+
+ if (isreq) {
+ if (req_tree) {
+ proto_tree_add_string (req_tree, hf_fcdns_fc4type, tvb, offset, 32,
+ fc4type_to_str (tvb, offset, str));
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_gept (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (isreq) {
+ if (req_tree) {
+ proto_tree_add_item (req_tree, hf_fcdns_req_ptype, tvb, offset+3,
+ 1, 0);
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_gezm (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (isreq) {
+ if (req_tree) {
+ dissect_fcdns_zone_mbr (tvb, req_tree, offset);
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_gezn (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int strlen;
+
+ if (isreq) {
+ if (req_tree) {
+ strlen = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (req_tree, tvb, offset, 1, "Name Length: %d",
+ strlen);
+ proto_tree_add_string (req_tree, hf_fcdns_zonenm, tvb, offset+3,
+ strlen, tvb_get_ptr (tvb, offset+3, strlen));
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_geipp (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (isreq) {
+ if (req_tree) {
+ proto_tree_add_item (req_tree, hf_fcdns_portip, tvb, offset, 4, 0);
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_geff (tvbuff_t *tvb, proto_tree *req_tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ gchar str[256];
+
+ if (isreq) {
+ if (req_tree) {
+ proto_tree_add_string (req_tree, hf_fcdns_req_fc4feature, tvb, offset,
+ 128, fc4ftrs_to_str (tvb, offset, str));
+ }
+ }
+ else {
+ dissect_fcdns_swils_entries (tvb, req_tree, offset);
+ }
+}
+
+static void
+dissect_fcdns_rjt (tvbuff_t *tvb, proto_tree *req_tree)
+{
+ int offset = 0;
+
+ if (req_tree) {
+ proto_tree_add_item (req_tree, hf_fcdns_reason, tvb, offset+13, 1, 0);
+ proto_tree_add_item (req_tree, hf_fcdns_rjtdetail, tvb, offset+14, 1,
+ 0);
+ proto_tree_add_item (req_tree, hf_fcdns_vendor, tvb, offset+15, 1, 0);
+ }
+}
+
+static void
+dissect_fcdns (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti = NULL;
+ proto_tree *fcdns_tree = NULL;
+ int offset = 0;
+ int opcode,
+ failed_opcode = 0;
+ int isreq = 1;
+ fc_ct_preamble cthdr;
+ conversation_t *conversation;
+ fcdns_conv_data_t *cdata;
+ fcdns_conv_key_t ckey, *req_key;
+
+ tvb_memcpy (tvb, (guint8 *)&cthdr, offset, FCCT_PRMBL_SIZE);
+ cthdr.revision = tvb_get_guint8 (tvb, offset);
+ cthdr.in_id = tvb_get_ntoh24 (tvb, offset+1);
+ cthdr.opcode = ntohs (cthdr.opcode);
+ opcode = cthdr.opcode;
+ cthdr.maxres_size = ntohs (cthdr.maxres_size);
+
+ /* Determine the type of server the request/response is for */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ if (cthdr.gstype == FCCT_GSTYPE_DIRSVC)
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "dNS");
+ else
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "Unzoned NS");
+ }
+
+ if (tree) {
+ if (cthdr.gstype == FCCT_GSTYPE_DIRSVC) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcdns, tvb, 0,
+ tvb_reported_length (tvb),
+ "dNS");
+ fcdns_tree = proto_item_add_subtree (ti, ett_fcdns);
+ }
+ else {
+ ti = proto_tree_add_protocol_format (tree, proto_fcdns, tvb, 0,
+ tvb_reported_length (tvb),
+ "Unzoned NS");
+ fcdns_tree = proto_item_add_subtree (ti, ett_fcdns);
+ }
+ }
+
+ if ((opcode != FCCT_MSG_ACC) && (opcode != FCCT_MSG_RJT)) {
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ if (!conversation) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ }
+
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcdns_conv_data_t *)g_hash_table_lookup (fcdns_req_hash,
+ &ckey);
+ if (cdata) {
+ /* Since we never free the memory used by an exchange, this maybe a
+ * case of another request using the same exchange as a previous
+ * req.
+ */
+ cdata->opcode = opcode;
+ }
+ else {
+ req_key = g_mem_chunk_alloc (fcdns_req_keys);
+ req_key->conv_idx = conversation->index;
+
+ cdata = g_mem_chunk_alloc (fcdns_req_vals);
+ cdata->opcode = opcode;
+
+ g_hash_table_insert (fcdns_req_hash, req_key, cdata);
+ }
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO, val_to_str (opcode, fc_dns_opcode_val,
+ "0x%x"));
+ }
+ }
+ else {
+ /* Opcode is ACC or RJT */
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ isreq = 0;
+ if (!conversation) {
+ if (tree && (opcode == FCCT_MSG_ACC)) {
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO,
+ val_to_str (opcode, fc_dns_opcode_val,
+ "0x%x"));
+ }
+ /* No record of what this accept is for. Can't decode */
+ proto_tree_add_text (fcdns_tree, tvb, 0, tvb_length (tvb),
+ "No record of Exchg. Unable to decode MSG_ACC/RJT");
+ return;
+ }
+ }
+ else {
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcdns_conv_data_t *)g_hash_table_lookup (fcdns_req_hash, &ckey);
+
+ if (cdata != NULL) {
+ if (opcode == FCCT_MSG_ACC) {
+ opcode = cdata->opcode;
+ }
+ else
+ failed_opcode = cdata->opcode;
+ }
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if (opcode != FCCT_MSG_RJT) {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "ACC (%s)",
+ val_to_str (opcode, fc_dns_opcode_val,
+ "0x%x"));
+ }
+ else {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "RJT (%s)",
+ val_to_str (failed_opcode,
+ fc_dns_opcode_val,
+ "0x%x"));
+ }
+ }
+
+ if (tree) {
+ if ((cdata == NULL) && (opcode != FCCT_MSG_RJT)) {
+ /* No record of what this accept is for. Can't decode */
+ proto_tree_add_text (fcdns_tree, tvb, 0, tvb_length (tvb),
+ "No record of Exchg. Unable to decode MSG_ACC/RJT");
+ return;
+ }
+ }
+ }
+ }
+
+ if (tree) {
+ proto_tree_add_item (fcdns_tree, hf_fcdns_opcode, tvb, offset+8, 2, 0);
+ proto_tree_add_item (fcdns_tree, hf_fcdns_maxres_size, tvb, offset+10,
+ 2, 0);
+ }
+
+ switch (opcode) {
+ case FCCT_MSG_RJT:
+ dissect_fcdns_rjt (tvb, fcdns_tree);
+ break;
+ case FCDNS_GA_NXT:
+ dissect_fcdns_ganxt (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GPN_ID:
+ dissect_fcdns_gpnid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GNN_ID:
+ dissect_fcdns_gnnid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GCS_ID:
+ dissect_fcdns_gcsid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GFT_ID:
+ dissect_fcdns_gftid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GSPN_ID:
+ dissect_fcdns_gspnid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GPT_ID:
+ dissect_fcdns_gptid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GFPN_ID:
+ dissect_fcdns_gfpnid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GFD_ID:
+ dissect_fcdns_gfdid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GFF_ID:
+ dissect_fcdns_gffid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GID_PN:
+ dissect_fcdns_gidpn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GIPP_PN:
+ dissect_fcdns_gipppn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GID_NN:
+ dissect_fcdns_gidnn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GPN_NN:
+ dissect_fcdns_gpnnn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GIP_NN:
+ dissect_fcdns_gipnn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GSNN_NN:
+ dissect_fcdns_gsnnnn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GID_FT:
+ dissect_fcdns_gidft (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GPN_FT:
+ dissect_fcdns_gpnft (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GNN_FT:
+ dissect_fcdns_gnnft (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GID_PT:
+ dissect_fcdns_gidpt (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GID_IPP:
+ dissect_fcdns_gidipp (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GID_FF:
+ dissect_fcdns_gidff (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RPN_ID:
+ dissect_fcdns_rpnid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RNN_ID:
+ dissect_fcdns_rnnid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RCS_ID:
+ dissect_fcdns_rcsid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RPT_ID:
+ dissect_fcdns_rptid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RFT_ID:
+ dissect_fcdns_rftid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RSPN_ID:
+ dissect_fcdns_rspnid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RIPP_ID:
+ dissect_fcdns_rippid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RFD_ID:
+ dissect_fcdns_rfdid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RFF_ID:
+ dissect_fcdns_rffid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RIP_NN:
+ dissect_fcdns_ripnn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_RSNN_NN:
+ dissect_fcdns_rsnnnn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_DA_ID:
+ dissect_fcdns_daid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_ID:
+ dissect_fcdns_geid (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_PN:
+ dissect_fcdns_gepn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_NN:
+ dissect_fcdns_genn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_IP:
+ dissect_fcdns_geip (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_FT:
+ dissect_fcdns_geft (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_PT:
+ dissect_fcdns_gept (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_ZM:
+ dissect_fcdns_gezm (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_ZN:
+ dissect_fcdns_gezn (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_IPP:
+ dissect_fcdns_geipp (tvb, fcdns_tree, isreq);
+ break;
+ case FCDNS_GE_FF:
+ dissect_fcdns_geff (tvb, fcdns_tree, isreq);
+ break;
+ default:
+ break;
+ }
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is required because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_fcdns (void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_fcdns_gssubtype,
+ {"GS_Subtype", "fcdns.gssubtype", FT_UINT8, BASE_HEX,
+ VALS (fc_dns_subtype_val), 0x0, "", HFILL}},
+ {&hf_fcdns_opcode,
+ {"Opcode", "fcdns.opcode", FT_UINT16, BASE_HEX, VALS (fc_dns_opcode_val),
+ 0x0, "", HFILL}},
+ { &hf_fcdns_req_portid,
+ {"Port Identifier", "fcdns.req.portid", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcdns_rply_pname,
+ {"Port Name", "fcdns.rply.pname", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcdns_rply_nname,
+ {"Node Name", "fcdns.rply.nname", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcdns_rply_cos,
+ {"Class of Service Supported", "fcdns.rply.cos", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_rply_gft,
+ {"FC-4 Types Supported", "fcdns.rply.fc4type", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_rply_snamelen,
+ {"Symbolic Node Name Length", "fcdns.rply.snamelen", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_rply_sname,
+ {"Symbolic Node Name", "fcdns.rply.sname", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_rply_ptype,
+ {"Port Type", "fcdns.rply.porttype", FT_UINT8, BASE_HEX,
+ VALS (fc_dns_port_type_val), 0x0, "", HFILL}},
+ { &hf_fcdns_rply_fpname,
+ {"Fabric Port Name", "fcdns.rply.fpname", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_fc4type,
+ {"FC-4 Type", "fcdns.req.fc4type", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcdns_rply_fc4feat,
+ {"FC-4 Features", "fcdns.rply.fc4features", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_req_pname,
+ {"Port Name", "fcdns.req.portname", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcdns_rply_portid,
+ {"Port Identifier", "fcdns.rply.portid", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_req_nname,
+ {"Node Name", "fcdns.req.nname", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcdns_req_domainscope,
+ {"Domain ID Scope", "fcdns.req.domainid", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_req_areascope,
+ {"Area ID Scope", "fcdns.req.areaid", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_req_fc4type,
+ {"FC-4 Type", "fcdns.req.fc4type", FT_UINT8, BASE_HEX,
+ VALS (fc_fc4_val), 0x0, "", HFILL}},
+ { &hf_fcdns_req_ptype,
+ {"Port Type", "fcdns.req.porttype", FT_UINT8, BASE_HEX,
+ VALS (fc_dns_port_type_val), 0x0, "", HFILL}},
+ { &hf_fcdns_req_ip,
+ {"IP Address", "fcdns.req.ip", FT_IPv6, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcdns_req_fc4feature,
+ {"FC-4 Feature Bits", "fcdns.req.fc4feature", FT_STRING,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_req_cos,
+ {"Class of Service Supported", "fcdns.req.class", FT_STRING,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_req_fc4types,
+ {"FC-4 TYPEs Supported", "fcdns.req.fc4types", FT_STRING,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_rply_fc4type,
+ {"FC-4 Descriptor Type", "fcdns.rply.fc4type", FT_UINT8, BASE_HEX,
+ VALS (fc_fc4_val), 0x0, "", HFILL}},
+ { &hf_fcdns_req_snamelen,
+ {"Symbolic Name Length", "fcdns.req.snamelen", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_req_sname,
+ {"Symbolic Port Name", "fcdns.req.sname", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_rply_spnamelen,
+ {"Symbolic Port Name Length", "fcdns.rply.spnamelen", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_fcdns_rply_spname,
+ {"Symbolic Port Name", "fcdns.rply.spname", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_rply_ipa,
+ {"Initial Process Associator", "fcdns.rply.ipa", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_rply_ipnode,
+ {"Node IP Address", "fcdns.rply.ipnode", FT_IPv6, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_rply_ipport,
+ {"Port IP Address", "fcdns.rply.ipport", FT_IPv6, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_rply_fc4desclen,
+ {"FC-4 Descriptor Length", "fcdns.rply.fc4desclen", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_rply_fc4desc,
+ {"FC-4 Descriptor", "fcdns.rply.fc4desc", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_rply_hrdaddr,
+ {"Hard Address", "fcdns.rply.hrdaddr", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_req_fdesclen,
+ {"FC-4 Descriptor Length", "fcdns.req.fc4desclen", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_req_fdesc,
+ {"FC-4 Descriptor", "fcdns.req.fc4desc", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_req_spnamelen,
+ {"Symbolic Port Name Length", "fcdns.req.spnamelen", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_req_spname,
+ {"Symbolic Port Name", "fcdns.req.spname", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_reason,
+ {"Reason Code", "fcdns.rply.reason", FT_UINT8, BASE_HEX,
+ VALS (fc_ct_rjt_code_vals), 0x0, "", HFILL}},
+ { &hf_fcdns_rjtdetail,
+ {"Reason Code Explanantion", "fcdns.rply.reasondet", FT_UINT8,
+ BASE_HEX, VALS (fc_dns_rjt_det_code_val), 0x0, "", HFILL}},
+ { &hf_fcdns_vendor,
+ {"Vendor Unique Reject Code", "fcdns.rply.vendor", FT_UINT8,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_zone_mbrtype,
+ {"Zone Member Type", "fcdns.zone.mbrtype", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_zonembr_type_val), 0x0, "", HFILL}},
+ { &hf_fcdns_zone_mbrid,
+ {"Member Identifier", "swils.zone.mbrid", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcdns_zonenm,
+ {"Zone Name", "fcdns.zonename", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcdns_portip,
+ {"Port IP Address", "fcdns.portip", FT_IPv4, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcdns_sw2_objfmt,
+ {"Name Entry Object Format", "fcdns.entry.objfmt", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_num_fc4desc,
+ {"Number of FC4 Descriptors Registered", "fcdns.entry.numfc4desc",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcdns_rply_ownerid,
+ {"Owner Id", "fcdns.rply.ownerid", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcdns_maxres_size,
+ {"Maximum/Residual Size", "fcdns.maxres_size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_fcdns,
+ };
+
+ /* Register the protocol name and description */
+ proto_fcdns = proto_register_protocol("Fibre Channel Name Server",
+ "FC-dNS", "FC-dNS");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fcdns, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine (&fcdns_init_protocol);
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fcdns (void)
+{
+ dissector_handle_t dns_handle;
+
+ dns_handle = create_dissector_handle (dissect_fcdns, proto_fcdns);
+ dissector_add("fcct.server", FCCT_GSRVR_DNS, dns_handle);
+ dissector_add("fcct.server", FCCT_GSRVR_UNS, dns_handle);
+
+ data_handle = find_dissector ("data");
+}
+
+
diff --git a/epan/dissectors/packet-fcdns.h b/epan/dissectors/packet-fcdns.h
new file mode 100644
index 0000000000..d405ab46c5
--- /dev/null
+++ b/epan/dissectors/packet-fcdns.h
@@ -0,0 +1,229 @@
+/* packet-fcdns.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCDNS_H_
+#define __PACKET_FCDNS_H_
+
+/* Opcode definitions */
+#define FCDNS_GA_NXT 0x0100
+#define FCDNS_GID_A 0x0101
+#define FCDNS_GPN_ID 0x0112
+#define FCDNS_GNN_ID 0x0113
+#define FCDNS_GCS_ID 0x0114
+#define FCDNS_GFT_ID 0x0117
+#define FCDNS_GSPN_ID 0x0118
+#define FCDNS_GPT_ID 0x011A
+#define FCDNS_GIPP_ID 0x011B
+#define FCDNS_GFPN_ID 0x011C
+#define FCDNS_GHA_ID 0x011D
+#define FCDNS_GFD_ID 0x011E
+#define FCDNS_GFF_ID 0x011F
+#define FCDNS_GID_PN 0x0121
+#define FCDNS_GIPP_PN 0x012B
+#define FCDNS_GID_NN 0x0131
+#define FCDNS_GPN_NN 0x0132
+#define FCDNS_GIP_NN 0x0135
+#define FCDNS_GIPA_NN 0x0136
+#define FCDNS_GSNN_NN 0x0139
+#define FCDNS_GNN_IP 0x0153
+#define FCDNS_GIPA_IP 0x0156
+#define FCDNS_GID_FT 0x0171
+#define FCDNS_GPN_FT 0x0172
+#define FCDNS_GNN_FT 0x0173
+#define FCDNS_GID_PT 0x01A1
+#define FCDNS_GID_IPP 0x01B1
+#define FCDNS_GPN_IPP 0x01B2
+#define FCDNS_GID_FF 0x01F1
+#define FCDNS_RPN_ID 0x0212
+#define FCDNS_RNN_ID 0x0213
+#define FCDNS_RCS_ID 0x0214
+#define FCDNS_RFT_ID 0x0217
+#define FCDNS_RSPN_ID 0x0218
+#define FCDNS_RPT_ID 0x021A
+#define FCDNS_RIPP_ID 0x021B
+#define FCDNS_RHA_ID 0x021D
+#define FCDNS_RFD_ID 0x021E
+#define FCDNS_RFF_ID 0x021F
+#define FCDNS_RIP_NN 0x0235
+#define FCDNS_RSNN_NN 0x0239
+#define FCDNS_DA_ID 0x0300
+/* dNS messages defined by FC-SW2 */
+#define FCDNS_RA 0x0
+#define FCDNS_GE_ID 0x0410
+#define FCDNS_GE_PN 0x0420
+#define FCDNS_GE_NN 0x0430
+#define FCDNS_GE_IP 0x0450
+#define FCDNS_GE_FT 0x0470
+#define FCDNS_GE_PT 0x04A0
+#define FCDNS_GE_ZM 0x04B0
+#define FCDNS_GE_ZN 0x04C0
+#define FCDNS_GE_IPP 0x04D0
+#define FCDNS_GE_FF 0x04E0
+
+static const value_string fc_dns_opcode_val[] = {
+ {FCDNS_GA_NXT, "GA_NXT" },
+ {FCDNS_GID_A, "GID_A" },
+ {FCDNS_GPN_ID, "GPN_ID" },
+ {FCDNS_GNN_ID, "GNN_ID" },
+ {FCDNS_GCS_ID, "GCS_ID" },
+ {FCDNS_GFT_ID, "GFT_ID" },
+ {FCDNS_GSPN_ID, "GSPN_ID" },
+ {FCDNS_GPT_ID, "GPT_ID" },
+ {FCDNS_GIPP_ID, "GIPP_ID" },
+ {FCDNS_GFPN_ID, "GFPN_ID" },
+ {FCDNS_GHA_ID, "GHA_ID" },
+ {FCDNS_GFD_ID, "GFD_ID" },
+ {FCDNS_GFF_ID, "GFF_ID" },
+ {FCDNS_GID_PN, "GID_PN" },
+ {FCDNS_GIPP_PN, "GIPP_PN" },
+ {FCDNS_GID_NN, "GID_NN" },
+ {FCDNS_GPN_NN, "GPN_NN" },
+ {FCDNS_GIP_NN, "GIP_NN" },
+ {FCDNS_GIPA_NN, "GIPA_NN" },
+ {FCDNS_GSNN_NN, "GSNN_NN" },
+ {FCDNS_GNN_IP, "GNN_IP" },
+ {FCDNS_GIPA_IP, "GIPA_IP" },
+ {FCDNS_GID_FT, "GID_FT" },
+ {FCDNS_GPN_FT, "GPN_FT" },
+ {FCDNS_GNN_FT, "GNN_FT" },
+ {FCDNS_GID_PT, "GID_PT" },
+ {FCDNS_GID_IPP, "GID_IPP" },
+ {FCDNS_GPN_IPP, "GPN_IPP" },
+ {FCDNS_GID_FF, "GID_FF" },
+ {FCDNS_RPN_ID, "RPN_ID" },
+ {FCDNS_RNN_ID, "RNN_ID" },
+ {FCDNS_RCS_ID, "RCS_ID" },
+ {FCDNS_RFT_ID, "RFT_ID" },
+ {FCDNS_RSPN_ID, "RSPN_ID" },
+ {FCDNS_RPT_ID, "RPT_ID" },
+ {FCDNS_RIPP_ID, "RIPP_ID" },
+ {FCDNS_RHA_ID, "RHA_ID" },
+ {FCDNS_RFD_ID, "RFD_ID" },
+ {FCDNS_RFF_ID, "RFF_ID" },
+ {FCDNS_RIP_NN, "RIP_NN" },
+ {FCDNS_RSNN_NN, "RSNN_NN"},
+ {FCDNS_DA_ID, "DA_ID"},
+ {FCDNS_GE_ID, "GE_ID"},
+ {FCDNS_GE_PN, "GE_PN"},
+ {FCDNS_GE_NN, "GE_NN"},
+ {FCDNS_GE_IP, "GE_IP"},
+ {FCDNS_GE_FT, "GE_FT"},
+ {FCDNS_GE_PT, "GE_PT"},
+ {FCDNS_GE_ZM, "GE_ZM"},
+ {FCDNS_GE_ZN, "GE_ZN"},
+ {FCDNS_GE_IPP, "GE_IPP"},
+ {FCDNS_GE_FF, "GE_FF"},
+ {FCCT_MSG_ACC, "MSG_ACC"},
+ {FCCT_MSG_RJT, "MSG_RJT"},
+ {0, NULL},
+};
+
+/* Port type definitions */
+#define FCDNS_PTYPE_UNDEF 0x00
+#define FCDNS_PTYPE_NPORT 0x01
+#define FCDNS_PTYPE_NLPORT 0x02
+#define FCDNS_PTYPE_FNLPORT 0x03
+#define FCDNS_PTYPE_NXPORT 0x7F
+#define FCDNS_PTYPE_FPORT 0x81
+#define FCDNS_PTYPE_FLPORT 0x82
+#define FCDNS_PTYPE_EPORT 0x84
+#define FCDNS_PTYPE_BPORT 0x85
+
+static const value_string fc_dns_port_type_val [] = {
+ {FCDNS_PTYPE_UNDEF , "Undefined Port Type"},
+ {FCDNS_PTYPE_NPORT , "N_Port"},
+ {FCDNS_PTYPE_NLPORT , "NL_Port"},
+ {FCDNS_PTYPE_FNLPORT , "F/NL_Port"},
+ {FCDNS_PTYPE_NXPORT , "Nx_Port"},
+ {FCDNS_PTYPE_FPORT , "F_Port"},
+ {FCDNS_PTYPE_FLPORT , "FL_Port"},
+ {FCDNS_PTYPE_EPORT , "E_Port"},
+ {FCDNS_PTYPE_BPORT , "B_Port"},
+ {0, NULL},
+};
+
+/* Reject Detailed Reason code definitions for dNS */
+#define FCDNS_RJT_NOREASON 0x00
+#define FCDNS_RJT_PIDNOTREG 0x01
+#define FCDNS_RJT_PNAMENOTREG 0x02
+#define FCDNS_RJT_NNAMENOTREG 0x03
+#define FCDNS_RJT_CLASSNOTREG 0x04
+#define FCDNS_RJT_IPNNOTREG 0x05
+#define FCDNS_RJT_IPANOTREG 0x06
+#define FCDNS_RJT_FC4NOTREG 0x07
+#define FCDNS_RJT_SPNAMENOTREG 0x08
+#define FCDNS_RJT_SNNAMENOTREG 0x09
+#define FCDNS_RJT_PTYPENOTREG 0x0A
+#define FCDNS_RJT_IPPNOTREG 0x0B
+#define FCDNS_RJT_FPNAMENOTREG 0x0C
+#define FCDNS_RJT_HRDADDNOTREG 0x0D
+#define FCDNS_RJT_FC4DESNOTREG 0x0E
+#define FCDNS_RJT_FC4FEANOTREG 0x0F
+#define FCDNS_RJT_ACCRJT 0x10
+#define FCDNS_RJT_PTYPEFMT 0x11
+#define FCDNS_RJT_DBEMPTY 0x12
+#define FCDNS_RJT_NOOBJSCOPE 0x13
+#define FCDNS_RJT_AUTHRZN_EXCEPTION 0xF0
+#define FCDNS_RJT_AUTH_EXCEPTION 0xF1
+#define FCDNS_RJT_DB_FULL 0xF2
+#define FCDNS_RJT_DB_EMPTY 0xF3
+
+static const value_string fc_dns_rjt_det_code_val [] = {
+ {FCDNS_RJT_NOREASON , "No Additional Info"},
+ {FCDNS_RJT_PIDNOTREG , "PortID Not Regd."},
+ {FCDNS_RJT_PNAMENOTREG , "PortName Not Regd."},
+ {FCDNS_RJT_NNAMENOTREG , "NodeName Not Regd."},
+ {FCDNS_RJT_CLASSNOTREG , "Class Not Regd."},
+ {FCDNS_RJT_IPNNOTREG , "IP Addr (Node) Not Regd."},
+ {FCDNS_RJT_IPANOTREG , "IPA Not Regd."},
+ {FCDNS_RJT_FC4NOTREG , "FC4 TYPEs Not Regd."},
+ {FCDNS_RJT_SPNAMENOTREG, "Symbolic PortName Not Regd."},
+ {FCDNS_RJT_SNNAMENOTREG, "Symbolic NodeName Not Regd."},
+ {FCDNS_RJT_PTYPENOTREG , "PortType Not Regd."},
+ {FCDNS_RJT_IPPNOTREG , "IP Addr (Port) Not Regd."},
+ {FCDNS_RJT_FPNAMENOTREG, "Fabric Port Name Not Regd."},
+ {FCDNS_RJT_HRDADDNOTREG, "Hard Addr Not Regd."},
+ {FCDNS_RJT_FC4DESNOTREG, "FC4 Descriptors Not Regd."},
+ {FCDNS_RJT_FC4FEANOTREG, "FC4 Features Not Regd."},
+ {FCDNS_RJT_ACCRJT , "Access Denied"},
+ {FCDNS_RJT_PTYPEFMT , "Unacceptable PortId"},
+ {FCDNS_RJT_DBEMPTY , "Database Empty"},
+ {FCDNS_RJT_NOOBJSCOPE , "No Objects Regd. in Scope"},
+ {FCDNS_RJT_AUTHRZN_EXCEPTION, "Authorization Exception"},
+ {FCDNS_RJT_AUTH_EXCEPTION, "Authentication Exception"},
+ {FCDNS_RJT_DB_FULL, "Database Full"},
+ {FCDNS_RJT_DB_EMPTY, "Database Empty"},
+ {0, NULL},
+};
+
+/* Actual servers serving the directory service type identified by subtype */
+#define FCDNS_GSSUBTYPE_DNS 0x02
+#define FCDNS_GSSUBTYPE_IP 0x03
+
+static const value_string fc_dns_subtype_val[] = {
+ {FCDNS_GSSUBTYPE_DNS, "dNS"},
+ {FCDNS_GSSUBTYPE_IP, "IP"},
+ {0, NULL},
+};
+
+#endif
diff --git a/epan/dissectors/packet-fcels.c b/epan/dissectors/packet-fcels.c
new file mode 100644
index 0000000000..a31387038f
--- /dev/null
+++ b/epan/dissectors/packet-fcels.c
@@ -0,0 +1,2003 @@
+/* packet-fcels.c
+ * Routines for FC Extended Link Services
+ * Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * TODO Still (Complete compliance with FC-MI):
+ * - Decode RNID, RLIR
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fcels.h"
+
+#define FC_ELS_RPLY 0
+#define FC_ELS_REQ 1
+
+/* Initialize the protocol and registered fields */
+static int proto_fcels = -1;
+static int hf_fcels_opcode = -1;
+static int hf_fcels_rjtcode = -1;
+static int hf_fcels_rjtdetcode = -1;
+static int hf_fcels_vnduniq = -1;
+static int hf_fcels_b2b = -1;
+static int hf_fcels_cmnfeatures = -1;
+static int hf_fcels_bbscnum = -1;
+static int hf_fcels_rcvsize = -1;
+static int hf_fcels_maxconseq = -1;
+static int hf_fcels_reloffset = -1;
+static int hf_fcels_edtov = -1;
+static int hf_fcels_npname = -1;
+static int hf_fcels_fnname = -1;
+static int hf_fcels_cls1param = -1;
+static int hf_fcels_cls2param = -1;
+static int hf_fcels_cls3param = -1;
+static int hf_fcels_cls4param = -1;
+static int hf_fcels_vendorvers = -1;
+static int hf_fcels_svcavail = -1;
+static int hf_fcels_clsflags = -1;
+static int hf_fcels_initctl = -1;
+static int hf_fcels_rcptctl = -1;
+static int hf_fcels_clsrcvsize = -1;
+static int hf_fcels_conseq = -1;
+static int hf_fcels_e2e = -1;
+static int hf_fcels_openseq = -1;
+static int hf_fcels_nportid = -1;
+static int hf_fcels_oxid = -1;
+static int hf_fcels_rxid = -1;
+static int hf_fcels_recovqual = -1;
+static int hf_fcels_fabricaddr = -1;
+static int hf_fcels_fabricpname = -1;
+static int hf_fcels_failedrcvr = -1;
+static int hf_fcels_flacompliance = -1;
+static int hf_fcels_loopstate = -1;
+static int hf_fcels_publicloop_bmap = -1;
+static int hf_fcels_pvtloop_bmap = -1;
+static int hf_fcels_alpa_map = -1;
+static int hf_fcels_scrregn = -1;
+static int hf_fcels_farp_matchcodept = -1;
+static int hf_fcels_farp_respaction = -1;
+static int hf_fcels_resportid = -1;
+static int hf_fcels_respname = -1;
+static int hf_fcels_respnname = -1;
+static int hf_fcels_reqipaddr = -1;
+static int hf_fcels_respipaddr = -1;
+static int hf_fcels_hardaddr = -1;
+static int hf_fcels_rps_flag = -1;
+static int hf_fcels_rps_portnum = -1;
+static int hf_fcels_rps_portstatus = -1;
+static int hf_fcels_rnft_fc4type = -1;
+static int hf_fcels_rscn_evqual = -1;
+static int hf_fcels_rscn_addrfmt = -1;
+static int hf_fcels_rscn_domain = -1;
+static int hf_fcels_rscn_area = -1;
+static int hf_fcels_rscn_port = -1;
+static int hf_fcels_nodeidfmt = -1;
+static int hf_fcels_spidlen = -1;
+static int hf_fcels_vendoruniq = -1;
+static int hf_fcels_vendorsp = -1;
+static int hf_fcels_asstype = -1;
+static int hf_fcels_physport = -1;
+static int hf_fcels_attnodes = -1;
+static int hf_fcels_nodemgmt = -1;
+static int hf_fcels_ipvers = -1;
+static int hf_fcels_tcpport = -1;
+static int hf_fcels_ip = -1;
+
+static gint ett_fcels;
+static gint ett_fcels_lsrjt;
+static gint ett_fcels_acc;
+static gint ett_fcels_logi;
+static gint ett_fcels_logi_cmnsvc;
+static gint ett_fcels_logi_clssvc;
+static gint ett_fcels_logo;
+static gint ett_fcels_abtx;
+static gint ett_fcels_rsi;
+static gint ett_fcels_rrq;
+static gint ett_fcels_prli;
+static gint ett_fcels_prli_svcpg;
+static gint ett_fcels_adisc;
+static gint ett_fcels_farp;
+static gint ett_fcels_rps;
+static gint ett_fcels_rpl;
+static gint ett_fcels_rplpb;
+static gint ett_fcels_fan;
+static gint ett_fcels_rscn;
+static gint ett_fcels_rscn_rec;
+static gint ett_fcels_scr;
+static gint ett_fcels_rnft;
+static gint ett_fcels_rnft_fc4;
+static gint ett_fcels_lsts;
+static gint ett_fcels_rnid;
+static gint ett_fcels_rlir;
+static gint ett_fcels_lirr;
+static gint ett_fcels_srl;
+static gint ett_fcels_rpsc;
+
+static const value_string fc_prli_fc4_val[] = {
+ {FC_TYPE_SCSI , "FCP"},
+ {FC_TYPE_IP , "IP/FC"},
+ {FC_TYPE_LLCSNAP , "LLC_SNAP"},
+ {FC_TYPE_ELS , "Ext Link Svc"},
+ {FC_TYPE_FCCT , "FC_CT"},
+ {FC_TYPE_SWILS , "SW_ILS"},
+ {FC_TYPE_AL , "AL"},
+ {FC_TYPE_SNMP , "SNMP"},
+ {FC_TYPE_CMNSVC , "Common to all FC-4 Types"},
+ {0, NULL},
+};
+
+typedef struct _fcels_conv_key {
+ guint32 conv_idx;
+} fcels_conv_key_t;
+
+typedef struct _fcels_conv_data {
+ guint32 opcode;
+} fcels_conv_data_t;
+
+GHashTable *fcels_req_hash = NULL;
+GMemChunk *fcels_req_keys = NULL;
+GMemChunk *fcels_req_vals = NULL;
+guint32 fcels_init_count = 25;
+
+static dissector_handle_t data_handle, fcsp_handle;
+
+/*
+ * Hash Functions
+ */
+static gint
+fcels_equal(gconstpointer v, gconstpointer w)
+{
+ fcels_conv_key_t *v1 = (fcels_conv_key_t *)v;
+ fcels_conv_key_t *v2 = (fcels_conv_key_t *)w;
+
+ return (v1->conv_idx == v2->conv_idx);
+}
+
+static guint
+fcels_hash (gconstpointer v)
+{
+ fcels_conv_key_t *key = (fcels_conv_key_t *)v;
+ guint val;
+
+ val = key->conv_idx;
+
+ return val;
+}
+
+/*
+ * Protocol initialization
+ */
+static void
+fcels_init_protocol(void)
+{
+ if (fcels_req_keys)
+ g_mem_chunk_destroy(fcels_req_keys);
+ if (fcels_req_vals)
+ g_mem_chunk_destroy(fcels_req_vals);
+ if (fcels_req_hash)
+ g_hash_table_destroy(fcels_req_hash);
+
+ fcels_req_hash = g_hash_table_new(fcels_hash, fcels_equal);
+ fcels_req_keys = g_mem_chunk_new ("fcels_req_keys",
+ sizeof(fcels_conv_key_t),
+ fcels_init_count *
+ sizeof(fcels_conv_key_t),
+ G_ALLOC_AND_FREE);
+ fcels_req_vals = g_mem_chunk_new ("fcels_req_vals",
+ sizeof(fcels_conv_data_t),
+ fcels_init_count *
+ sizeof(fcels_conv_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+static void
+construct_cmnsvc_string (guint16 flag, gchar *flagstr, guint8 opcode)
+{
+ int stroff = 0;
+ gchar punc[3];
+
+ punc[0] = '\0';
+
+ if (flag & 0x8000) {
+ strcpy (flagstr, "Cont. Incr. Offset Supported");
+ stroff += 28;
+ strcpy (punc, ", ");
+ }
+ if (flag & 0x4000) {
+ sprintf (&flagstr[stroff], "%sRRO Supported", punc);
+ stroff += 15;
+ strcpy (punc, ", ");
+ }
+
+ if (flag & 0x2000) {
+ sprintf (flagstr, "%sValid Vendor Version Level", punc);
+ strcpy (punc, ", ");
+ stroff += 28;
+ }
+
+ if (flag & 0x0800) {
+ sprintf (&flagstr[stroff], "%sAlt B2B Credit Mgmt", punc);
+ strcpy (punc, ", ");
+ stroff += 24;
+ }
+ else {
+ sprintf (&flagstr[stroff], "%sNormal B2B Credit Mgmt", punc);
+ strcpy (punc, ", ");
+ stroff += 22;
+ }
+
+ if ((opcode == FC_ELS_PLOGI) || (opcode == FC_ELS_PDISC)) {
+ if (flag & 0x0400) {
+ strcpy (&flagstr[stroff], ", E_D_TOV Resolution in ns");
+ }
+ else {
+ strcpy (&flagstr[stroff], ", E_D_TOV Resolution in ms");
+ }
+ stroff += 26;
+
+ if (flag & 0x0040) {
+ strcpy (&flagstr[stroff], ", Simplex Dedicated Conn Supported");
+ stroff += 34;
+ }
+ }
+
+ if (flag & 0x0200) {
+ strcpy (&flagstr[stroff], ", Multicast Supported");
+ stroff += 21;
+ }
+
+ if (flag & 0x0100) {
+ strcpy (&flagstr[stroff], ", Broadcast Supported");
+ stroff += 21;
+ }
+
+ if (flag & 0x0020) {
+ strcpy (&flagstr[stroff], ", Security Bit");
+ stroff += 14;
+ }
+
+ if (flag & 0x0010) {
+ strcpy (&flagstr[stroff], ", Clk Sync Prim Capable");
+ stroff += 23;
+ }
+ if (flag & 0x0004) {
+ strcpy (&flagstr[stroff], ", DHD Capable");
+ stroff += 13;
+ }
+
+ if ((opcode == FC_ELS_PLOGI) || (opcode == FC_ELS_PDISC)) {
+ if (flag & 0x0002) {
+ strcpy (&flagstr[stroff], ", Cont. Incr SEQCNT rules");
+ stroff += 25;
+ }
+ else {
+ strcpy (&flagstr[stroff], ", Normal SEQCNT rules");
+ stroff += 21;
+ }
+ }
+
+ if (flag & 0x0001) {
+ sprintf (&flagstr[stroff], ", Payload Len=256 bytes");
+ }
+ else {
+ sprintf (&flagstr[stroff], ", Payload Len=116 bytes");
+ }
+}
+
+/* The next 3 routines decode only Class 2 & Class 3 relevant bits */
+static void
+construct_clssvc_string (guint16 flag, gchar *flagstr, guint8 opcode)
+{
+ int stroff = 0;
+
+ if (!(flag & 0x8000)) {
+ strcpy (flagstr, "Class Not Supported");
+ return;
+ }
+
+ if ((opcode == FC_ELS_FLOGI) || (opcode == FC_ELS_FDISC)) {
+ if (flag & 0x0800) {
+ strcpy (flagstr, "Seq Delivery Requested");
+ stroff += 22;
+ }
+ else {
+ strcpy (flagstr, "Out of Order Delivery Requested");
+ stroff += 31;
+ }
+ }
+
+ if (flag & 0x0080) {
+ strcpy (&flagstr[stroff], ", Priority/preemption supported");
+ stroff += 31;
+ }
+
+ if ((opcode == FC_ELS_PLOGI) || (opcode == FC_ELS_PDISC)) {
+ if (flag & 0x0040) {
+ strcpy (&flagstr[stroff], "Non-zero CS_CTL Tolerated");
+ }
+ else {
+ strcpy (&flagstr[stroff], "Non-zero CS_CTL Maybe Tolerated");
+ }
+ }
+}
+
+static void
+construct_initctl_string (guint16 flag, gchar *flagstr, guint8 opcode)
+{
+ int stroff = 0;
+
+ if ((opcode == FC_ELS_PLOGI) || (opcode == FC_ELS_PDISC)) {
+ switch ((flag & 0x3000)) {
+ case 0x0:
+ strcpy (flagstr, "Initial P_A Not Supported");
+ stroff += 25;
+ break;
+ case 0x1000:
+ strcpy (flagstr, "Initial P_A Supported");
+ stroff += 21;
+ break;
+ case 0x3000:
+ strcpy (flagstr, "Initial P_A Required & Supported");
+ stroff += 32;
+ break;
+ }
+
+ if (flag & 0x0800) {
+ strcpy (&flagstr[stroff], ", ACK0 Capable");
+ stroff += 14;
+ }
+
+ if (flag & 0x0200) {
+ strcpy (&flagstr[stroff], ", ACK Generation Assistance Avail");
+ stroff += 33;
+ }
+ if (flag & 0x0010) {
+ strcpy (&flagstr[stroff], ", Clock Sync ELS Supported");
+ }
+ }
+ else {
+ if (flag & 0x0010) {
+ strcpy (&flagstr[stroff], "Clock Sync ELS Supported");
+ }
+ }
+}
+
+static void
+construct_rcptctl_string (guint16 flag, gchar *flagstr, guint8 opcode)
+{
+ int stroff = 0;
+ gchar punc[3];
+
+ punc[0] = '\0';
+
+ if ((opcode == FC_ELS_PLOGI) || (opcode == FC_ELS_PDISC)) {
+ if (flag & 0x8000) {
+ strcpy (flagstr, "ACK_0 Supported");
+ stroff += 15;
+ }
+ else {
+ strcpy (flagstr, "ACK_0 Not Supported");
+ stroff += 19;
+ }
+
+ if (flag & 0x2000) {
+ strcpy (&flagstr[stroff], ", X_ID Interlock Reqd");
+ stroff += 21;
+ }
+
+ switch (flag & 0x1800) {
+ case 0x0:
+ strcpy (&flagstr[stroff], ", Error Policy: Discard Policy only");
+ stroff += 43;
+ break;
+ case 0x1000:
+ strcpy (&flagstr[stroff], ", Error Policy: Both discard and process policies supported");
+ stroff += 52;
+ break;
+ case 0x0800:
+ strcpy (&flagstr[stroff], ", Error Policy: Reserved");
+ stroff += 41;
+ break;
+ case 0x1800:
+ strcpy (&flagstr[stroff], ", Error Policy: Reserved");
+ stroff += 52;
+ break;
+ }
+
+ switch (flag & 0x0030) {
+ case 0:
+ strcpy (&flagstr[stroff], ", 1 Category/Seq");
+ stroff += 16;
+ break;
+ case 0x0010:
+ strcpy (&flagstr[stroff], ", 2 Categories/Seq");
+ stroff += 18;
+ break;
+ case 0x0030:
+ strcpy (&flagstr[stroff], ", More than 2 Categories/Seq");
+ stroff += 28;
+ break;
+ }
+
+ if (flag & 0x0008) {
+ strcpy (&flagstr[stroff], ", Clk Sync ELS Supported");
+ }
+ }
+ else {
+ if (flag & 0x0008) {
+ strcpy (&flagstr[stroff], "Clk Sync ELS Supported");
+ }
+ }
+}
+
+
+static void
+dissect_fcels_logi (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ proto_item *ti, guint8 opcode)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0,
+ svcvld = 0,
+ class;
+ proto_tree *logi_tree, *cmnsvc_tree;
+ proto_item *subti;
+ gchar flagstr[256];
+ guint16 flag;
+
+ if (tree) {
+ logi_tree = proto_item_add_subtree (ti, ett_fcels_logi);
+ proto_tree_add_item (logi_tree, hf_fcels_opcode, tvb, offset, 1, FALSE);
+
+ subti = proto_tree_add_text (logi_tree, tvb, offset+4, 16,
+ "Common Svc Parameters");
+ cmnsvc_tree = proto_item_add_subtree (subti, ett_fcels_logi_cmnsvc);
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_b2b, tvb, offset+6, 2, FALSE);
+ flag = tvb_get_ntohs (tvb, offset+8);
+
+ if (flag & 0x0001) {
+ svcvld = 1;
+ }
+
+ construct_cmnsvc_string (flag, flagstr, opcode);
+ proto_tree_add_uint_format (cmnsvc_tree, hf_fcels_cmnfeatures, tvb,
+ offset+8, 2, flag,
+ "Common Svc Parameters: 0x%x (%s)",
+ flag, flagstr);
+
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_bbscnum, tvb, offset+10, 1, FALSE);
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_rcvsize, tvb, offset+10, 2, FALSE);
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_maxconseq, tvb, offset+12, 2, FALSE);
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_reloffset, tvb, offset+14, 2, FALSE);
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_edtov, tvb, offset+16, 4, FALSE);
+ proto_tree_add_string (cmnsvc_tree, hf_fcels_npname, tvb, offset+20, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+20, 8)));
+ proto_tree_add_string (cmnsvc_tree, hf_fcels_fnname, tvb, offset+28, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+28, 8)));
+
+ /* Add subtree for class paramters */
+ offset = 36;
+ for (class = 1; class < 5; class++) {
+ subti = proto_tree_add_text (logi_tree, tvb, offset, 16,
+ "Class %d Svc Parameters", class);
+ cmnsvc_tree = proto_item_add_subtree (subti, ett_fcels_logi_cmnsvc);
+
+ flag = tvb_get_ntohs (tvb, offset);
+ construct_clssvc_string (flag, flagstr, opcode);
+ proto_tree_add_uint_format (cmnsvc_tree, hf_fcels_clsflags, tvb,
+ offset, 2, flag,
+ "Service Options: 0x%x(%s)", flag,
+ flagstr);
+ if (flag & 0x8000) {
+ flag = tvb_get_ntohs (tvb, offset+2);
+ construct_initctl_string (flag, flagstr, opcode);
+ proto_tree_add_uint_format (cmnsvc_tree, hf_fcels_initctl, tvb,
+ offset+2, 2, flag,
+ "Initiator Control: 0x%x(%s)", flag,
+ flagstr);
+
+ flag = tvb_get_ntohs (tvb, offset+4);
+ construct_rcptctl_string (flag, flagstr, opcode);
+ proto_tree_add_uint_format (cmnsvc_tree, hf_fcels_initctl, tvb,
+ offset+4, 2, flag,
+ "Recipient Control: 0x%x(%s)", flag,
+ flagstr);
+
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_clsrcvsize, tvb,
+ offset+6, 2, FALSE);
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_conseq, tvb,
+ offset+8, 2, FALSE);
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_e2e, tvb,
+ offset+10, 2, FALSE);
+ proto_tree_add_item (cmnsvc_tree, hf_fcels_openseq, tvb,
+ offset+12, 2, FALSE);
+ }
+ offset += 16;
+ }
+ proto_tree_add_item (logi_tree, hf_fcels_vendorvers, tvb, offset, 16, FALSE);
+ if (svcvld) {
+ proto_tree_add_item (logi_tree, hf_fcels_svcavail, tvb, offset+32, 8, FALSE);
+ }
+ }
+}
+
+static void
+dissect_fcels_plogi (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ dissect_fcels_logi (tvb, pinfo, tree, ti, FC_ELS_PLOGI);
+}
+
+static void
+dissect_fcels_flogi (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ dissect_fcels_logi (tvb, pinfo, tree, ti, FC_ELS_FLOGI);
+}
+
+static void
+dissect_fcels_logout (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 5; /* bypass opcode+rsvd field */
+ proto_tree *logo_tree;
+
+ if (tree) {
+ logo_tree = proto_item_add_subtree (ti, ett_fcels_logo);
+
+ proto_tree_add_item (logo_tree, hf_fcels_opcode, tvb, offset-5, 1, FALSE);
+
+ if (!isreq) {
+ /* Accept has no payload */
+ return;
+ }
+
+ proto_tree_add_string (logo_tree, hf_fcels_nportid, tvb, offset, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset, 3)));
+ proto_tree_add_string (logo_tree, hf_fcels_npname, tvb, offset+3, 6,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+3, 6)));
+ }
+}
+
+static void
+dissect_fcels_abtx (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ proto_tree *abtx_tree;
+
+ if (tree) {
+ abtx_tree = proto_item_add_subtree (ti, ett_fcels_abtx);
+
+ proto_tree_add_item (abtx_tree, hf_fcels_opcode, tvb, offset, 1, FALSE);
+
+ if (!isreq) {
+ return;
+ }
+
+ proto_tree_add_text (abtx_tree, tvb, offset+4, 1,
+ "Recovery Qualifier Status: 0x%x",
+ tvb_get_guint8 (tvb, offset+4));
+ proto_tree_add_string (abtx_tree, hf_fcels_nportid, tvb, offset+5, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+5, 3)));
+ proto_tree_add_item (abtx_tree, hf_fcels_oxid, tvb, offset+8, 2, FALSE);
+ proto_tree_add_item (abtx_tree, hf_fcels_rxid, tvb, offset+10, 2, FALSE);
+ }
+}
+
+static void
+dissect_fcels_rsi (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 4;
+ proto_tree *rsi_tree;
+
+ if (tree) {
+ rsi_tree = proto_item_add_subtree (ti, ett_fcels_rsi);
+
+ proto_tree_add_item (rsi_tree, hf_fcels_opcode, tvb, offset-4, 1, FALSE);
+ if (!isreq)
+ return;
+
+ proto_tree_add_item (rsi_tree, hf_fcels_recovqual, tvb, offset, 1, FALSE);
+ proto_tree_add_string (rsi_tree, hf_fcels_nportid, tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
+ proto_tree_add_item (rsi_tree, hf_fcels_rxid, tvb, offset+4, 2, FALSE);
+ proto_tree_add_item (rsi_tree, hf_fcels_oxid, tvb, offset+6, 2, FALSE);
+ }
+}
+
+static void
+dissect_fcels_rrq (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ proto_tree *rrq_tree;
+
+ if (tree) {
+ rrq_tree = proto_item_add_subtree (ti, ett_fcels_rrq);
+
+ proto_tree_add_item (rrq_tree, hf_fcels_opcode, tvb, offset, 1, FALSE);
+ if (!isreq)
+ return;
+
+ proto_tree_add_string (rrq_tree, hf_fcels_nportid, tvb, offset+5, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+5, 3)));
+ proto_tree_add_item (rrq_tree, hf_fcels_oxid, tvb, offset+8, 2, FALSE);
+ proto_tree_add_item (rrq_tree, hf_fcels_rxid, tvb, offset+10, 2, FALSE);
+ }
+}
+
+static void
+dissect_fcels_pdisc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ dissect_fcels_logi (tvb, pinfo, tree, ti, FC_ELS_PDISC);
+}
+
+static void
+dissect_fcels_fdisc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ dissect_fcels_logi (tvb, pinfo, tree, ti, FC_ELS_FDISC);
+}
+
+static void
+dissect_fcels_adisc (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 5;
+ proto_tree *adisc_tree;
+
+ if (tree) {
+ adisc_tree = proto_item_add_subtree (ti, ett_fcels_adisc);
+
+ proto_tree_add_item (adisc_tree, hf_fcels_opcode, tvb, offset-5, 1, FALSE);
+
+ proto_tree_add_string (adisc_tree, hf_fcels_hardaddr, tvb, offset, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset, 3)));
+ proto_tree_add_string (adisc_tree, hf_fcels_npname, tvb, offset+3, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+3, 8)));
+ proto_tree_add_string (adisc_tree, hf_fcels_fnname, tvb, offset+11, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+11, 8)));
+ proto_tree_add_string (adisc_tree, hf_fcels_nportid, tvb, offset+20, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+20, 3)));
+ }
+
+}
+
+static void
+dissect_fcels_farp (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ proto_item *ti)
+{
+ int offset = 4;
+ proto_tree *farp_tree;
+
+ if (tree) {
+ farp_tree = proto_item_add_subtree (ti, ett_fcels_farp);
+
+ proto_tree_add_item (farp_tree, hf_fcels_opcode, tvb, offset-4, 1, FALSE);
+
+ proto_tree_add_item (farp_tree, hf_fcels_farp_matchcodept,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_string (farp_tree, hf_fcels_nportid, tvb, offset+1,
+ 3, fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
+ proto_tree_add_item (farp_tree, hf_fcels_farp_respaction, tvb,
+ offset+4, 1, FALSE);
+ proto_tree_add_string (farp_tree, hf_fcels_resportid, tvb, offset+5,
+ 3, fc_to_str (tvb_get_ptr (tvb, offset+5, 3)));
+ proto_tree_add_string (farp_tree, hf_fcels_npname, tvb, offset+8,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb, offset+8, 8)));
+ proto_tree_add_string (farp_tree, hf_fcels_fnname, tvb, offset+16,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb, offset+16, 8)));
+ proto_tree_add_string (farp_tree, hf_fcels_respname, tvb, offset+24,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb, offset+24, 8)));
+ proto_tree_add_string (farp_tree, hf_fcels_respnname, tvb, offset+32,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb, offset+32, 8)));
+ proto_tree_add_item (farp_tree, hf_fcels_reqipaddr, tvb, offset+40,
+ 16, FALSE);
+ proto_tree_add_item (farp_tree, hf_fcels_respipaddr, tvb, offset+56,
+ 16, FALSE);
+ }
+}
+
+static void
+dissect_fcels_farp_req (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ dissect_fcels_farp (tvb, pinfo, tree, ti);
+}
+
+static void
+dissect_fcels_farp_rply (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ dissect_fcels_farp (tvb, pinfo, tree, ti);
+}
+
+static void
+dissect_fcels_rps (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 3;
+ guint8 flag;
+ proto_tree *rps_tree;
+
+ flag = tvb_get_guint8 (tvb, offset);
+
+ if (tree) {
+ rps_tree = proto_item_add_subtree (ti, ett_fcels_rps);
+
+ if (isreq) {
+ proto_tree_add_item (rps_tree, hf_fcels_rps_flag, tvb, offset, 1, FALSE);
+
+ proto_tree_add_item (rps_tree, hf_fcels_opcode, tvb, offset-3, 1, FALSE);
+
+ if (flag & 0x2) {
+ proto_tree_add_string (rps_tree, hf_fcels_npname, tvb, offset+1,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+1,
+ 8)));
+ }
+ else if (flag & 0x1) {
+ proto_tree_add_item (rps_tree, hf_fcels_rps_portnum, tvb,
+ offset+5, 3, FALSE);
+ }
+ }
+ else {
+ proto_tree_add_item (rps_tree, hf_fcels_rps_flag, tvb, offset, 1, FALSE);
+ proto_tree_add_item (rps_tree, hf_fcels_rps_portstatus, tvb,
+ offset+3, 2, FALSE);
+ /* Next 6 fields are from Link Error Status Block (LESB) */
+ proto_tree_add_text (rps_tree, tvb, offset+5, 4,
+ "Link Failure Count: %u",
+ tvb_get_ntohl (tvb, offset+5));
+ proto_tree_add_text (rps_tree, tvb, offset+9, 4,
+ "Loss of Sync Count: %u",
+ tvb_get_ntohl (tvb, offset+9));
+ proto_tree_add_text (rps_tree, tvb, offset+13, 4,
+ "Loss of Signal Count: %u",
+ tvb_get_ntohl (tvb, offset+13));
+ proto_tree_add_text (rps_tree, tvb, offset+17, 4,
+ "Primitive Seq Protocol Err: %u",
+ tvb_get_ntohl (tvb, offset+17));
+ proto_tree_add_text (rps_tree, tvb, offset+21, 4,
+ "Invalid Xmission Word: %u",
+ tvb_get_ntohl (tvb, offset+21));
+ proto_tree_add_text (rps_tree, tvb, offset+25, 4,
+ "Invalid CRC Count: %u",
+ tvb_get_ntohl (tvb, offset+25));
+ if (flag & 0x01) {
+ /* Next 6 fields are from L_Port Extension field */
+ proto_tree_add_text (rps_tree, tvb, offset+31, 2,
+ "L_Port Status: 0x%x",
+ tvb_get_ntohs (tvb, offset+31));
+ proto_tree_add_text (rps_tree, tvb, offset+36, 1,
+ "LIP AL_PS: 0x%x",
+ tvb_get_guint8 (tvb, offset+36));
+ proto_tree_add_text (rps_tree, tvb, offset+37, 4,
+ "LIP F7 Initiated Count: %u",
+ tvb_get_ntohl (tvb, offset+37));
+ proto_tree_add_text (rps_tree, tvb, offset+41, 4,
+ "LIP F7 Received Count: %u",
+ tvb_get_ntohl (tvb, offset+41));
+ proto_tree_add_text (rps_tree, tvb, offset+45, 4,
+ "LIP F8 Initiated Count: %u",
+ tvb_get_ntohl (tvb, offset+45));
+ proto_tree_add_text (rps_tree, tvb, offset+49, 4,
+ "LIP F8 Received Count: %u",
+ tvb_get_ntohl (tvb, offset+49));
+ proto_tree_add_text (rps_tree, tvb, offset+53, 4,
+ "LIP Reset Initiated Count: %u",
+ tvb_get_ntohl (tvb, offset+53));
+ proto_tree_add_text (rps_tree, tvb, offset+57, 4,
+ "LIP Reset Received Count: %u",
+ tvb_get_ntohl (tvb, offset+57));
+ }
+ }
+ }
+}
+
+static void
+dissect_fcels_rpl (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ proto_tree *rpl_tree, *pb_tree;
+ proto_item *subti;
+ int loop;
+
+ if (tree) {
+ rpl_tree = proto_item_add_subtree (ti, ett_fcels_rpl);
+
+ proto_tree_add_item (rpl_tree, hf_fcels_opcode, tvb, offset, 1, FALSE);
+
+ if (isreq) {
+ proto_tree_add_text (rpl_tree, tvb, offset+6, 2,
+ "Max Size: %u",
+ tvb_get_ntohs (tvb, offset+6));
+ proto_tree_add_text (rpl_tree, tvb, offset+9, 3,
+ "Index: %u",
+ tvb_get_ntoh24 (tvb, offset+9));
+ }
+ else {
+ /* Reply consists of a header and a number of port blocks */
+ proto_tree_add_text (rpl_tree, tvb, offset+2, 2,
+ "Payload Length: %u",
+ tvb_get_ntohs (tvb, offset+2));
+ proto_tree_add_text (rpl_tree, tvb, offset+5, 3,
+ "List Length: %u",
+ tvb_get_ntoh24 (tvb, offset+5));
+ proto_tree_add_text (rpl_tree, tvb, offset+9, 3,
+ "Index of I Port Block: %u",
+ tvb_get_ntoh24 (tvb, offset+9));
+ offset = 12;
+ /* The following loop is for dissecting the port blocks */
+ for (loop = tvb_get_ntoh24 (tvb, 5); loop > 0; loop--) {
+ subti = proto_tree_add_text (rpl_tree, tvb, offset+12, 16,
+ "Port Block %u", loop);
+ pb_tree = proto_item_add_subtree (subti, ett_fcels_rplpb);
+
+ proto_tree_add_text (pb_tree, tvb, offset, 4,
+ "Physical Port #: %u",
+ tvb_get_ntohl (tvb, offset));
+ proto_tree_add_text (pb_tree, tvb, offset+5, 3,
+ "Port Identifier: %s",
+ fc_to_str (tvb_get_ptr (tvb, offset+5, 3)));
+ proto_tree_add_text (pb_tree, tvb, offset+8, 8,
+ "Port Name: %s",
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+8, 8)));
+ offset += 16;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcels_fan (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 5;
+ proto_tree *fan_tree;
+
+ if (tree) {
+ fan_tree = proto_item_add_subtree (ti, ett_fcels_fan);
+
+ proto_tree_add_item (fan_tree, hf_fcels_opcode, tvb, offset-5, 1, FALSE);
+
+ proto_tree_add_string (fan_tree, hf_fcels_fabricaddr, tvb, offset, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset, 3)));
+ proto_tree_add_string (fan_tree, hf_fcels_fabricpname, tvb, offset+3,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ proto_tree_add_string (fan_tree, hf_fcels_fnname, tvb, offset+11, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+11, 8)));
+ }
+}
+
+static void
+dissect_fcels_rscn (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 1;
+ proto_tree *rscn_tree, *rectree;
+ proto_item *subti;
+ int numrec, plen, i;
+
+ if (tree) {
+ rscn_tree = proto_item_add_subtree (ti, ett_fcels_rscn);
+
+ proto_tree_add_item (rscn_tree, hf_fcels_opcode, tvb, offset-1, 1, FALSE);
+ if (!isreq)
+ return;
+
+ proto_tree_add_text (rscn_tree, tvb, offset, 1,
+ "Page Len: %u", tvb_get_guint8 (tvb, offset));
+ plen = tvb_get_ntohs (tvb, offset+1);
+ proto_tree_add_text (rscn_tree, tvb, offset+1, 2,
+ "Payload Len: %u", plen);
+ numrec = (plen - 4)/4;
+
+ offset = 4;
+ for (i = 0; i < numrec; i++) {
+ subti = proto_tree_add_text (rscn_tree, tvb, offset, 4,
+ "Affected N_Port Page %u", i);
+ rectree = proto_item_add_subtree (subti, ett_fcels_rscn_rec);
+
+ proto_tree_add_item (rectree, hf_fcels_rscn_evqual, tvb, offset,
+ 1, FALSE);
+ proto_tree_add_item (rectree, hf_fcels_rscn_addrfmt, tvb, offset,
+ 1, FALSE);
+ proto_tree_add_item (rectree, hf_fcels_rscn_domain, tvb, offset+1,
+ 1, FALSE);
+ proto_tree_add_item (rectree, hf_fcels_rscn_area, tvb, offset+2,
+ 1, FALSE);
+ proto_tree_add_item (rectree, hf_fcels_rscn_port, tvb, offset+3,
+ 1, FALSE);
+ offset += 4;
+ }
+ }
+}
+
+static void
+dissect_fcels_scr (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 7;
+ proto_tree *scr_tree;
+
+ if (tree) {
+ scr_tree = proto_item_add_subtree (ti, ett_fcels_scr);
+ proto_tree_add_item (scr_tree, hf_fcels_opcode, tvb, offset-7, 1, FALSE);
+ if (isreq)
+ proto_tree_add_item (scr_tree, hf_fcels_scrregn, tvb, offset, 1, FALSE);
+ }
+}
+
+static void
+dissect_fcels_rnft (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ int offset = 0;
+ guint16 numrec, i;
+ proto_tree *rnft_tree, *fc4_tree;
+ proto_item *subti;
+
+ if (tree) {
+ rnft_tree = proto_item_add_subtree (ti, ett_fcels_rnft);
+
+ proto_tree_add_item (rnft_tree, hf_fcels_opcode, tvb, offset, 1, FALSE);
+
+ if (isreq) {
+ proto_tree_add_text (rnft_tree, tvb, offset+2, 2,
+ "Max Size: %u", tvb_get_ntohs (tvb, offset+2));
+ proto_tree_add_text (rnft_tree, tvb, offset+7, 1,
+ "Index: %u", tvb_get_guint8 (tvb, offset+7));
+ }
+ else {
+ proto_tree_add_text (rnft_tree, tvb, offset+2, 2,
+ "Payload Len: %u",
+ tvb_get_ntohs (tvb, offset+2));
+ numrec = tvb_get_guint8 (tvb, offset+5);
+ proto_tree_add_text (rnft_tree, tvb, offset+5, 1,
+ "List Length: %u", numrec);
+ proto_tree_add_text (rnft_tree, tvb, offset+7, 1,
+ "Index of First Rec in List: %u",
+ tvb_get_guint8 (tvb, offset+7));
+ offset = 8;
+ for (i = 0; i < numrec; i++) {
+ subti = proto_tree_add_text (rnft_tree, tvb, offset, 4,
+ "FC-4 Entry #%u", i);
+ fc4_tree = proto_item_add_subtree (subti, ett_fcels_rnft_fc4);
+
+ proto_tree_add_item (fc4_tree, hf_fcels_rnft_fc4type, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_text (fc4_tree, tvb, offset+1, 3,
+ "FC-4 Qualifier 0x%x",
+ tvb_get_ntoh24 (tvb, offset+1));
+ offset += 4;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcels_lsts (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 5;
+ proto_tree *lsts_tree;
+
+ if (tree) {
+ lsts_tree = proto_item_add_subtree (ti, ett_fcels_lsts);
+
+ proto_tree_add_item (lsts_tree, hf_fcels_opcode, tvb, offset-5, 1, FALSE);
+ if (isreq) {
+ /* In case of LSTS, the reply has the meat */
+ return;
+ }
+ proto_tree_add_item (lsts_tree, hf_fcels_failedrcvr, tvb, offset, 1, FALSE);
+ proto_tree_add_item (lsts_tree, hf_fcels_flacompliance, tvb, offset+1,
+ 1, FALSE);
+ proto_tree_add_item (lsts_tree, hf_fcels_loopstate, tvb, offset+2, 1, FALSE);
+ proto_tree_add_item (lsts_tree, hf_fcels_publicloop_bmap, tvb, offset+3,
+ 16, FALSE);
+ proto_tree_add_item (lsts_tree, hf_fcels_pvtloop_bmap, tvb, offset+19,
+ 16, FALSE);
+ proto_tree_add_item (lsts_tree, hf_fcels_alpa_map, tvb, offset+35,
+ 128, FALSE);
+ }
+}
+
+static void
+dissect_fcels_prlilo_payload (tvbuff_t *tvb, packet_info *pinfo _U_,
+ guint8 isreq, proto_item *ti, guint8 opcode)
+{
+ int offset = 0,
+ stroff = 0;
+ guint8 type;
+ proto_tree *prli_tree, *svcpg_tree;
+ int num_svcpg, payload_len, i, flag;
+ proto_item *subti;
+ gchar flagstr[100];
+
+ /* We're assuming that we're invoked only if tree is not NULL i.e.
+ * we don't do the usual "if (tree)" check here, the caller must.
+ */
+ prli_tree = proto_item_add_subtree (ti, ett_fcels_prli);
+
+ proto_tree_add_item (prli_tree, hf_fcels_opcode, tvb, offset, 1, FALSE);
+
+ proto_tree_add_text (prli_tree, tvb, offset+1, 1,
+ "Page Length: %u",
+ tvb_get_guint8 (tvb, offset+1));
+ payload_len = tvb_get_ntohs (tvb, offset+2);
+ proto_tree_add_text (prli_tree, tvb, offset+2, 2,
+ "Payload Length: %u", payload_len);
+ num_svcpg = payload_len/16;
+
+ offset = 4;
+ for (i = 0; i < num_svcpg; i++) {
+ subti = proto_tree_add_text (prli_tree, tvb, offset, 16,
+ "Service Parameter Page %u", i);
+ svcpg_tree = proto_item_add_subtree (subti, ett_fcels_prli_svcpg);
+
+ type = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (svcpg_tree, tvb, offset, 1,
+ "TYPE: %s",
+ val_to_str (type,
+ fc_prli_fc4_val, "0x%x"));
+ proto_tree_add_text (svcpg_tree, tvb, offset+1, 1,
+ "TYPE Code Extension: %u",
+ tvb_get_guint8 (tvb, offset+1));
+
+ flag = tvb_get_guint8 (tvb, offset+2);
+ flagstr[0] = '\0';
+ stroff = 0;
+ if (opcode != FC_ELS_TPRLO) {
+ if (flag & 0x80) {
+ strcpy (flagstr, "Orig PA Valid, ");
+ stroff += 15;
+ }
+ if (flag & 0x40) {
+ strcpy (&flagstr[stroff], "Resp PA Valid, ");
+ stroff += 15;
+ }
+
+ if (opcode == FC_ELS_PRLI) {
+ if (!isreq) {
+ if (flag & 0x20) {
+ strcpy (&flagstr[stroff], "Image Pair Estd., ");
+ stroff += 18;
+ }
+ else {
+ strcpy (&flagstr[stroff], "Image Pair Not Estd., ");
+ stroff += 22;
+ }
+ }
+ else {
+ if (flag & 0x20) {
+ strcpy (&flagstr[stroff], "Est Image Pair & Exchg Svc Param, ");
+ stroff += 34;
+ }
+ else {
+ strcpy (&flagstr[stroff], "Exchange Svc Param Only, ");
+ stroff += 25;
+ }
+ }
+ }
+ }
+ else { /* Assuming opcode is TPRLO */
+ if (flag & 0x80) {
+ strcpy (flagstr, "3rd Party Orig PA Valid, ");
+ stroff += 25;
+ }
+ if (flag & 0x40) {
+ strcpy (&flagstr[stroff], "Resp PA Valid, ");
+ stroff += 15;
+ }
+ if (flag & 0x20) {
+ strcpy (&flagstr[stroff], "3rd Party N_Port Valid, ");
+ stroff += 24;
+ }
+ if (flag & 0x10) {
+ strcpy (&flagstr[stroff], "Global PRLO, ");
+ stroff += 13;
+ }
+ }
+
+ proto_tree_add_text (svcpg_tree, tvb, offset+2, 1,
+ "Flags: %s", flagstr);
+ if (!isreq && (opcode != FC_ELS_TPRLO)) {
+ /* This is valid only for ACC */
+ proto_tree_add_text (svcpg_tree, tvb, offset+2, 1,
+ "Response Code: 0x%x",
+ (tvb_get_guint8 (tvb, offset+2) & 0x0F));
+ }
+ if (opcode != FC_ELS_TPRLO) {
+ proto_tree_add_text (svcpg_tree, tvb, offset+4, 4,
+ "Originator PA: 0x%x",
+ tvb_get_ntohl (tvb, offset+4));
+ }
+ else {
+ proto_tree_add_text (svcpg_tree, tvb, offset+4, 4,
+ "3rd Party Originator PA: 0x%x",
+ tvb_get_ntohl (tvb, offset+4));
+ }
+ proto_tree_add_text (svcpg_tree, tvb, offset+8, 4,
+ "Responder PA: 0x%x",
+ tvb_get_ntohl (tvb, offset+8));
+
+ if (type == FC_TYPE_SCSI) {
+ flag = tvb_get_ntohs (tvb, offset+14);
+ flagstr[0] = '\0';
+ stroff = 0;
+
+ if (flag & 0x2000) {
+ if (isreq) {
+ strcpy (flagstr, "Task Retry Ident Req, ");
+ stroff += 22;
+ }
+ else {
+ strcpy (flagstr, "Task Retry Ident Acc, ");
+ stroff += 22;
+ }
+ }
+ if (flag & 0x1000) {
+ strcpy (&flagstr[stroff], "Retry Possible, ");
+ stroff += 16;
+ }
+ if (flag & 0x0080) {
+ strcpy (&flagstr[stroff], "Confirmed Comp, ");
+ stroff += 16;
+ }
+ if (flag & 0x0040) {
+ strcpy (&flagstr[stroff], "Data Overlay, ");
+ stroff += 14;
+ }
+ if (flag & 0x0020) {
+ strcpy (&flagstr[stroff], "Initiator, ");
+ stroff += 11;
+ }
+ if (flag & 0x0010) {
+ strcpy (&flagstr[stroff], "Target, ");
+ stroff += 8;
+ }
+ if (flag & 0x0002) {
+ strcpy (&flagstr[stroff], "Rd Xfer_Rdy Dis, ");
+ stroff += 17;
+ }
+ if (flag & 0x0001) {
+ strcpy (&flagstr[stroff], "Wr Xfer_Rdy Dis");
+ stroff += 15;
+ }
+ proto_tree_add_text (svcpg_tree, tvb, offset+12, 4,
+ "FCP Flags: 0x%x (%s)", flag,
+ flagstr);
+ }
+ else if ((opcode == FC_ELS_PRLI) && !isreq) {
+ proto_tree_add_text (svcpg_tree, tvb, offset+12, 4,
+ "Service Parameter Response: 0x%x",
+ tvb_get_ntohl (tvb, offset+12));
+ }
+ else if (opcode == FC_ELS_TPRLO) {
+ proto_tree_add_text (svcpg_tree, tvb, offset+13, 3,
+ "3rd Party N_Port Id: %s",
+ fc_to_str (tvb_get_ptr (tvb, offset+13, 3)));
+ }
+ }
+}
+
+static void
+dissect_fcels_prli (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ if (tree) {
+ dissect_fcels_prlilo_payload (tvb, pinfo, isreq, ti, FC_ELS_PRLI);
+ }
+}
+
+static void
+dissect_fcels_prlo (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ if (tree) {
+ dissect_fcels_prlilo_payload (tvb, pinfo, isreq, ti, FC_ELS_PRLO);
+ }
+}
+
+static void
+dissect_fcels_tprlo (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+
+ if (tree) {
+ dissect_fcels_prlilo_payload (tvb, pinfo, isreq, ti, FC_ELS_TPRLO);
+ }
+}
+
+static void
+dissect_fcels_lirr (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 4;
+ proto_tree *lirr_tree;
+ guint8 lirr_fmt;
+
+ if (tree) {
+ lirr_tree = proto_item_add_subtree (ti, ett_fcels_lirr);
+
+ proto_tree_add_item (lirr_tree, hf_fcels_opcode, tvb, offset-4, 1, FALSE);
+
+ proto_tree_add_text (lirr_tree, tvb, offset, 1,
+ "Regn. Function: %s",
+ val_to_str (tvb_get_guint8 (tvb, offset),
+ fc_els_lirr_regfunc_val,
+ "Reserved (0x%x)"));
+ lirr_fmt = tvb_get_guint8 (tvb, offset+1);
+ if (!lirr_fmt) {
+ /* This scheme is resorted to because the value 0 has a string in
+ * the value_string that is not what we want displayed here.
+ */
+ proto_tree_add_text (lirr_tree, tvb, offset, 1,
+ "Regn. Format: Common Format");
+ }
+ else {
+ proto_tree_add_text (lirr_tree, tvb, offset, 1,
+ "Regn. Format: %s",
+ val_to_str (lirr_fmt, fc_fc4_val, "0x%x"));
+ }
+ }
+}
+
+static void
+dissect_fcels_srl (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 4,
+ flag = 0;
+ proto_tree *srl_tree;
+
+ if (tree) {
+ srl_tree = proto_item_add_subtree (ti, ett_fcels_srl);
+
+ proto_tree_add_item (srl_tree, hf_fcels_opcode, tvb, offset-4, 1, FALSE);
+ if (!isreq)
+ return;
+
+ flag = tvb_get_guint8 (tvb, offset);
+ if (flag & 0x1) {
+ proto_tree_add_text (srl_tree, tvb, offset, 1,
+ "Flag: Scan only specified FL Port");
+ }
+ else {
+ proto_tree_add_text (srl_tree, tvb, offset, 1,
+ "Flag: Scan all loops in domain");
+ }
+ proto_tree_add_text (srl_tree, tvb, offset+1, 3,
+ "FL_Port Addr: %s",
+ fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
+ }
+}
+
+static void
+dissect_fcels_rpsc (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 2;
+ int num_entries, i, cap;
+ gchar speed_str[40];
+ int stroff = 0;
+ proto_tree *rpsc_tree;
+
+ if (tree) {
+ rpsc_tree = proto_item_add_subtree (ti, ett_fcels_rpsc);
+
+ proto_tree_add_item (rpsc_tree, hf_fcels_opcode, tvb, offset-2, 1, FALSE);
+ if (isreq)
+ return;
+
+ num_entries = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_text (rpsc_tree, tvb, offset, 2,
+ "Number of Entries: %u", num_entries);
+ offset = 4;
+ for (i = 0; i < num_entries; i++) {
+ cap = tvb_get_ntohs (tvb, offset);
+ speed_str[0] = '\0';
+ stroff = 0;
+ if (cap & 0x8000) {
+ strcpy (speed_str, "1,");
+ stroff += 2;
+ }
+ if (cap & 0x4000) {
+ strcpy (speed_str, "2,");
+ stroff += 2;
+ }
+ if (cap & 0x2000) {
+ strcpy (speed_str, "4,");
+ stroff += 2;
+ }
+ if (cap & 0x1000) {
+ strcpy (speed_str, "10");
+ stroff += 2;
+ }
+ strcpy (&speed_str[stroff], "Gb");
+ proto_tree_add_text (rpsc_tree, tvb, offset, 2,
+ "Port Speed Capabilities (Port %u): %s", i,
+ speed_str);
+ cap = tvb_get_ntohs (tvb, offset+2);
+ proto_tree_add_text (rpsc_tree, tvb, offset+2, 2,
+ "Port Oper Speed: %s",
+ val_to_str (cap, fc_els_portspeed_val,
+ "0x%x"));
+ }
+ }
+}
+
+static void
+dissect_fcels_rnid (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ int clen, slen;
+ proto_tree *rnid_tree;
+
+ if (tree) {
+ rnid_tree = proto_item_add_subtree (ti, ett_fcels_rnid);
+
+ proto_tree_add_item (rnid_tree, hf_fcels_opcode, tvb, offset, 1, FALSE);
+ if (isreq) {
+ proto_tree_add_item (rnid_tree, hf_fcels_nodeidfmt, tvb, offset+4,
+ 1, FALSE);
+ }
+ else {
+ /* We only decode responses to nodeid fmt DF */
+ proto_tree_add_item (rnid_tree, hf_fcels_nodeidfmt, tvb, offset+4,
+ 1, FALSE);
+ clen = tvb_get_guint8 (tvb, offset+5);
+ proto_tree_add_text (rnid_tree, tvb, offset+5, 1,
+ "Common Identification Data Length: %u", clen);
+ slen = tvb_get_guint8 (tvb, offset+7);
+ proto_tree_add_item (rnid_tree, hf_fcels_spidlen, tvb, offset+7,
+ 1, FALSE);
+ if (clen) {
+ proto_tree_add_string (rnid_tree, hf_fcels_npname, tvb,
+ offset+8, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+8,
+ 8)));
+ proto_tree_add_string (rnid_tree, hf_fcels_fnname, tvb,
+ offset+16, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+16,
+ 8)));
+ }
+ if (tvb_get_guint8 (tvb, offset+4) == 0xDF) {
+ /* Decode the Specific Node ID Format as this is known */
+ proto_tree_add_item (rnid_tree, hf_fcels_vendoruniq, tvb,
+ offset+24, 16, FALSE);
+ proto_tree_add_item (rnid_tree, hf_fcels_asstype, tvb,
+ offset+40, 4, FALSE);
+ proto_tree_add_item (rnid_tree, hf_fcels_physport, tvb,
+ offset+44, 4, FALSE);
+ proto_tree_add_item (rnid_tree, hf_fcels_attnodes, tvb,
+ offset+48, 4, FALSE);
+ proto_tree_add_item (rnid_tree, hf_fcels_nodemgmt, tvb,
+ offset+52, 1, FALSE);
+ proto_tree_add_item (rnid_tree, hf_fcels_ipvers, tvb,
+ offset+53, 1, FALSE);
+ proto_tree_add_item (rnid_tree, hf_fcels_tcpport, tvb,
+ offset+54, 2, FALSE);
+ proto_tree_add_item (rnid_tree, hf_fcels_ip, tvb, offset+56,
+ 16, FALSE);
+ proto_tree_add_item (rnid_tree, hf_fcels_vendorsp, tvb,
+ offset+74, 2, FALSE);
+ }
+ }
+ }
+}
+
+static void
+dissect_fcels_rlir (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
+ proto_tree *tree, guint8 isreq _U_,
+ proto_item *ti _U_)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+
+ if (tree) {
+ }
+}
+
+static void
+dissect_fcels_lsrjt (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint8 isreq _U_, proto_item *ti)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 5;
+ proto_tree *lsrjt_tree;
+
+ if (tree) {
+ lsrjt_tree = proto_item_add_subtree (ti, ett_fcels_lsrjt);
+
+ proto_tree_add_item (lsrjt_tree, hf_fcels_opcode, tvb, offset-5, 1, FALSE);
+
+ proto_tree_add_item (lsrjt_tree, hf_fcels_rjtcode, tvb, offset++, 1, FALSE);
+ proto_tree_add_item (lsrjt_tree, hf_fcels_rjtdetcode, tvb, offset++, 1, FALSE);
+ proto_tree_add_item (lsrjt_tree, hf_fcels_vnduniq, tvb, offset, 1, FALSE);
+ }
+}
+
+static void
+dissect_fcels (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti = NULL;
+ proto_tree *acc_tree;
+ guint8 isreq = FC_ELS_REQ;
+ int offset = 0;
+ guint8 opcode,
+ failed_opcode = 0;
+ conversation_t *conversation;
+ fcels_conv_data_t *cdata;
+ fcels_conv_key_t ckey, *req_key;
+ guint options;
+ address dstaddr;
+ guint8 addrdata[3];
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FC ELS");
+
+ /* decoding of this is done by each individual opcode handler */
+ opcode = tvb_get_guint8 (tvb, 0);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcels, tvb, 0,
+ tvb_length (tvb), "FC ELS");
+ }
+
+ /* Register conversation in case this is not a response */
+ if ((opcode != FC_ELS_LSRJT) && (opcode != FC_ELS_ACC)) {
+ if (opcode == FC_ELS_FLOGI) {
+ if (pinfo->src.data[2]) {
+ /* If it is a loop port, we'll need to remember the ALPA */
+ options = NO_PORT2;
+ }
+ else {
+ options = NO_PORT2 | NO_ADDR2;
+ }
+ }
+ else {
+ options = NO_PORT2;
+ }
+ conversation = find_conversation (&pinfo->dst, &pinfo->src,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, options);
+
+ if (!conversation) {
+ conversation = conversation_new (&pinfo->dst, &pinfo->src,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, options);
+ }
+
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcels_conv_data_t *)g_hash_table_lookup (fcels_req_hash,
+ &ckey);
+ if (cdata) {
+ /* Since we never free the memory used by an exchange, this maybe a
+ * case of another request using the same exchange as a previous
+ * req.
+ */
+ cdata->opcode = opcode;
+ }
+ else {
+ req_key = g_mem_chunk_alloc (fcels_req_keys);
+ req_key->conv_idx = conversation->index;
+
+ cdata = g_mem_chunk_alloc (fcels_req_vals);
+ cdata->opcode = opcode;
+
+ g_hash_table_insert (fcels_req_hash, req_key, cdata);
+ }
+ }
+ else {
+ isreq = FC_ELS_RPLY;
+
+ options = NO_PORT2;
+ conversation = find_conversation (&pinfo->dst, &pinfo->src,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, options);
+ if (!conversation) {
+ /* FLOGI has two ways to save state: without the src and using just
+ * the port (ALPA) part of the address. Try both.
+ */
+ addrdata[0] = addrdata[1] = 0;
+ addrdata[2] = pinfo->dst.data[2];
+ SET_ADDRESS (&dstaddr, AT_FC, 3, addrdata);
+ conversation = find_conversation (&dstaddr, &pinfo->src,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, options);
+ }
+
+ if (!conversation) {
+ /* Finally check for FLOGI with both NO_PORT2 and NO_ADDR2 set */
+ options = NO_ADDR2 | NO_PORT2;
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, options);
+ if (!conversation) {
+ if (tree && (opcode == FC_ELS_ACC)) {
+ /* No record of what this accept is for. Can't decode */
+ acc_tree = proto_item_add_subtree (ti, ett_fcels_acc);
+ proto_tree_add_text (acc_tree, tvb, offset, tvb_length (tvb),
+ "No record of Exchange. Unable to decode ACC");
+ return;
+ }
+ failed_opcode = 0;
+ }
+ }
+
+ if (conversation) {
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcels_conv_data_t *)g_hash_table_lookup (fcels_req_hash, &ckey);
+
+ if (cdata != NULL) {
+ if ((options & NO_ADDR2) && (cdata->opcode != FC_ELS_FLOGI)) {
+ /* only FLOGI can have this special check */
+ if (tree && (opcode == FC_ELS_ACC)) {
+ /* No record of what this accept is for. Can't decode */
+ acc_tree = proto_item_add_subtree (ti,
+ ett_fcels_acc);
+ proto_tree_add_text (acc_tree, tvb, offset,
+ tvb_length (tvb),
+ "No record of Exchg. Unable to decode ACC");
+ return;
+ }
+ }
+ if (opcode == FC_ELS_ACC)
+ opcode = cdata->opcode;
+ else
+ failed_opcode = cdata->opcode;
+ }
+
+ if (tree) {
+ if ((cdata == NULL) && (opcode != FC_ELS_LSRJT)) {
+ /* No record of what this accept is for. Can't decode */
+ acc_tree = proto_item_add_subtree (ti, ett_fcels_acc);
+ proto_tree_add_text (acc_tree, tvb, offset, tvb_length (tvb),
+ "No record of ELS Req. Unable to decode ACC");
+ return;
+ }
+ }
+ }
+ }
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if (isreq == FC_ELS_REQ) {
+ col_add_str (pinfo->cinfo, COL_INFO,
+ val_to_str (opcode, fc_els_proto_val, "0x%x"));
+ }
+ else if (opcode == FC_ELS_LSRJT) {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "LS_RJT (%s)",
+ val_to_str (failed_opcode, fc_els_proto_val, "0x%x"));
+ }
+ else {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "ACC (%s)",
+ val_to_str (opcode, fc_els_proto_val, "0x%x"));
+ }
+ }
+
+ switch (opcode) {
+ case FC_ELS_LSRJT:
+ dissect_fcels_lsrjt (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_PLOGI:
+ dissect_fcels_plogi (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_FLOGI:
+ dissect_fcels_flogi (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_LOGOUT:
+ dissect_fcels_logout (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_ABTX:
+ dissect_fcels_abtx (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_RSI:
+ dissect_fcels_rsi (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_RRQ:
+ dissect_fcels_rrq (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_PRLI:
+ dissect_fcels_prli (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_PRLO:
+ dissect_fcels_prlo (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_TPRLO:
+ dissect_fcels_tprlo (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_PDISC:
+ dissect_fcels_pdisc (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_FDISC:
+ dissect_fcels_fdisc (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_ADISC:
+ dissect_fcels_adisc (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_FARP_REQ:
+ dissect_fcels_farp_req (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_FARP_RPLY:
+ dissect_fcels_farp_rply (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_RPS:
+ dissect_fcels_rps (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_RPL:
+ dissect_fcels_rpl (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_FAN:
+ dissect_fcels_fan (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_RSCN:
+ dissect_fcels_rscn (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_SCR:
+ dissect_fcels_scr (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_RNFT:
+ dissect_fcels_rnft (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_LSTS:
+ dissect_fcels_lsts (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_RNID:
+ dissect_fcels_rnid (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_RLIR:
+ dissect_fcels_rlir (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_LIRR:
+ dissect_fcels_lirr (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_SRL:
+ dissect_fcels_srl (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_RPSC:
+ dissect_fcels_rpsc (tvb, pinfo, tree, isreq, ti);
+ break;
+ case FC_ELS_AUTH:
+ if (isreq && fcsp_handle)
+ call_dissector (fcsp_handle, tvb, pinfo, tree);
+ break;
+ default:
+ /* proto_tree_add_text ( */
+ call_dissector (data_handle, tvb, pinfo, tree);
+ break;
+ }
+}
+
+void
+proto_register_fcels (void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_fcels_opcode,
+ {"Cmd Code", "fcels.opcode", FT_UINT8, BASE_HEX,
+ VALS (fc_els_proto_val), 0x0, "", HFILL}},
+ { &hf_fcels_rjtcode,
+ {"Reason Code", "fcels.rjt.reason", FT_UINT8, BASE_HEX,
+ VALS (fc_els_rjt_val), 0x0, "", HFILL}},
+ { &hf_fcels_rjtdetcode,
+ {"Reason Explanation", "fcels.rjt.detail", FT_UINT8, BASE_HEX,
+ VALS (fc_els_rjt_det_val), 0x0, "", HFILL}},
+ { &hf_fcels_vnduniq,
+ {"Vendor Unique", "fcels.rjt.vnduniq", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_b2b,
+ {"B2B Credit", "fcels.logi.b2b", FT_UINT8, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcels_cmnfeatures,
+ {"Common Features", "fcels.logi.cmnfeatures", FT_UINT16, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_bbscnum,
+ {"BB_SC Number", "fcels.logi.bbscnum", FT_UINT8, BASE_DEC, NULL, 0xF0, "",
+ HFILL}},
+ { &hf_fcels_rcvsize,
+ {"Receive Size", "fcels.logi.rcvsize", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "",
+ HFILL}},
+ { &hf_fcels_maxconseq,
+ {"Max Concurrent Seq", "fcels.logi.maxconseq", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_reloffset,
+ {"Relative Offset By Info Cat", "fcels.logi.reloff", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_edtov,
+ {"E_D_TOV", "fcels.edtov", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcels_npname,
+ {"N_Port Port_Name", "fcels.npname", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcels_fnname,
+ {"Fabric/Node Name", "fcels.fnname", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcels_cls1param,
+ {"Class 1 Svc Param", "fcels.logi.cls1param", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcels_cls2param,
+ {"Class 2 Svc Param", "fcels.logi.cls2param", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcels_cls3param,
+ {"Class 3 Svc Param", "fcels.logi.cls3param", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcels_cls4param,
+ {"Class 4 Svc Param", "fcels.logi.cls4param", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcels_vendorvers,
+ {"Vendor Version", "fcels.logi.vendvers", FT_BYTES, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcels_svcavail,
+ {"Services Availability", "fcels.logi.svcavail", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_clsflags,
+ {"Class Flags", "fcels.logi.clsflags", FT_UINT16, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcels_initctl,
+ {"Initiator Ctl", "fcels.logi.initctl", FT_UINT16, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcels_rcptctl,
+ {"Recipient Ctl", "fcels.logi.rcptctl", FT_UINT16, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcels_clsrcvsize,
+ {"Class Recv Size", "fcels.logi.clsrcvsize", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_conseq,
+ {"Total Concurrent Seq", "fcels.logi.totconseq", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_e2e,
+ {"End2End Credit", "fcels.logi.e2e", FT_UINT16, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcels_openseq,
+ {"Open Seq Per Exchg", "fcels.logi.openseq", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcels_nportid,
+ {"Originator S_ID", "fcels.portid", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcels_oxid,
+ {"OXID", "fcels.oxid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcels_rxid,
+ {"RXID", "fcels.rxid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcels_recovqual,
+ {"Recovery Qualifier", "fcels.rcovqual", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_fabricaddr,
+ {"Fabric Address", "fcels.faddr", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcels_fabricpname,
+ {"Fabric Port Name", "fcels.fpname", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcels_failedrcvr,
+ {"Failed Receiver AL_PA", "fcels.faildrcvr", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_flacompliance,
+ {"FC-FLA Compliance", "fcels.flacompliance", FT_UINT8, BASE_HEX,
+ VALS (fc_els_flacompliance_val), 0x0, "", HFILL}},
+ { &hf_fcels_loopstate,
+ {"Loop State", "fcels.loopstate", FT_UINT8, BASE_HEX,
+ VALS (fc_els_loopstate_val), 0x0, "", HFILL}},
+ { &hf_fcels_publicloop_bmap,
+ {"Public Loop Device Bitmap", "fcels.pubdev_bmap", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_pvtloop_bmap,
+ {"Private Loop Device Bitmap", "fcels.pvtdev_bmap", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcels_alpa_map,
+ {"AL_PA Map", "fcels.alpa", FT_BYTES, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcels_scrregn,
+ {"Registration Function", "fcels.scr.regn", FT_UINT8, BASE_HEX,
+ VALS (fc_els_scr_reg_val), 0x0, "", HFILL}},
+ { &hf_fcels_farp_matchcodept,
+ {"Match Address Code Points", "fcels.matchcp", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_farp_respaction,
+ {"Responder Action", "fcels.respaction", FT_UINT8, BASE_HEX,
+ VALS (fc_els_farp_respaction_val), 0x0, "", HFILL}},
+ { &hf_fcels_resportid,
+ {"Responding Port ID", "fcels.resportid", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_respname,
+ {"Responding Port Name", "fcels.respname", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_respnname,
+ {"Responding Node Name", "fcels.respnname", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_reqipaddr,
+ {"Requesting IP Address", "fcels.reqipaddr", FT_IPv6, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_respipaddr,
+ {"Responding IP Address", "fcels.respipaddr", FT_IPv6, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_hardaddr,
+ {"Hard Address of Originator", "fcels.hrdaddr", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_rps_flag,
+ {"Flag", "fcels.flag", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcels_rps_portnum,
+ {"Physical Port Number", "fcels.portnum", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_rps_portstatus,
+ {"Port Status", "fcels.portstatus", FT_UINT16, BASE_HEX,
+ VALS(fc_els_portstatus_val), 0x0, "", HFILL}},
+ { &hf_fcels_rnft_fc4type,
+ {"FC-4 Type", "fcels.rnft.fc4type", FT_UINT8, BASE_HEX,
+ VALS (fc_fc4_val), 0x0, "", HFILL}},
+ { &hf_fcels_rscn_evqual,
+ {"Event Qualifier", "fcels.rscn.evqual", FT_UINT8, BASE_HEX,
+ VALS (fc_els_rscn_evqual_val), 0x3C, "", HFILL}},
+ { &hf_fcels_rscn_addrfmt,
+ {"Address Format", "fcels.rscn.addrfmt", FT_UINT8, BASE_HEX,
+ VALS (fc_els_rscn_addrfmt_val), 0x03, "", HFILL}},
+ { &hf_fcels_rscn_domain,
+ {"Affected Domain", "fcels.rscn.domain", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_rscn_area,
+ {"Affected Area", "fcels.rscn.area", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_rscn_port,
+ {"Affected Port", "fcels.rscn.port", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_nodeidfmt,
+ {"Node Identification Format", "fcels.rnid.nodeidfmt", FT_UINT8,
+ BASE_HEX, VALS (fc_els_nodeid_val), 0x0, "", HFILL}},
+ { &hf_fcels_spidlen,
+ {"Specific Id Length", "fcels.rnid.spidlen", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_vendoruniq,
+ {"Vendor Unique", "fcels.rnid.vendoruniq", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_vendorsp,
+ {"Vendor Specific", "fcels.rnid.vendorsp", FT_UINT16, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcels_asstype,
+ {"Associated Type", "fcels.rnid.asstype", FT_UINT32, BASE_HEX,
+ VALS (fc_els_rnid_asstype_val), 0x0, "", HFILL}},
+ { &hf_fcels_physport,
+ {"Physical Port Number", "fcels.rnid.physport", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_attnodes,
+ {"Number of Attached Nodes", "fcels.rnid.attnodes", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcels_nodemgmt,
+ {"Node Management", "fcels.rnid.nodemgmt", FT_UINT8, BASE_HEX,
+ VALS (fc_els_rnid_mgmt_val), 0x0, "", HFILL}},
+ { &hf_fcels_ipvers,
+ {"IP Version", "fcels.rnid.ipvers", FT_UINT8, BASE_HEX,
+ VALS (fc_els_rnid_ipvers_val), 0x0, "", HFILL}},
+ { &hf_fcels_tcpport,
+ {"TCP/UDP Port Number", "fcels.rnid.tcpport", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcels_ip,
+ {"IP Address", "fcels.rnid.ip", FT_IPv6, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_fcels,
+ &ett_fcels,
+ &ett_fcels_lsrjt,
+ &ett_fcels_acc,
+ &ett_fcels_logi,
+ &ett_fcels_logi_cmnsvc,
+ &ett_fcels_logi_clssvc,
+ &ett_fcels_logo,
+ &ett_fcels_abtx,
+ &ett_fcels_rsi,
+ &ett_fcels_rrq,
+ &ett_fcels_prli,
+ &ett_fcels_prli_svcpg,
+ &ett_fcels_adisc,
+ &ett_fcels_farp,
+ &ett_fcels_rps,
+ &ett_fcels_rpl,
+ &ett_fcels_rplpb,
+ &ett_fcels_fan,
+ &ett_fcels_rscn,
+ &ett_fcels_rscn_rec,
+ &ett_fcels_scr,
+ &ett_fcels_rnft,
+ &ett_fcels_rnft_fc4,
+ &ett_fcels_lsts,
+ &ett_fcels_rnid,
+ &ett_fcels_rlir,
+ &ett_fcels_lirr,
+ &ett_fcels_srl,
+ &ett_fcels_rpsc,
+ };
+
+ /* Register the protocol name and description */
+ proto_fcels = proto_register_protocol("FC Extended Link Svc", "FC ELS", "els");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fcels, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine (&fcels_init_protocol);
+}
+
+void
+proto_reg_handoff_fcels (void)
+{
+ dissector_handle_t els_handle;
+
+ els_handle = create_dissector_handle (dissect_fcels, proto_fcels);
+ dissector_add("fc.ftype", FC_FTYPE_ELS, els_handle);
+
+ data_handle = find_dissector ("data");
+ fcsp_handle = find_dissector ("fcsp");
+}
diff --git a/epan/dissectors/packet-fcels.h b/epan/dissectors/packet-fcels.h
new file mode 100644
index 0000000000..aff03712d3
--- /dev/null
+++ b/epan/dissectors/packet-fcels.h
@@ -0,0 +1,326 @@
+/* packet-fcels.h
+ * Fibre Channel Extended Link Services Definitions (ddutt@cisco.com)
+ * Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCELS_H_
+#define __PACKET_FCELS_H_
+
+#define FC_ELS_LSRJT 0x01
+#define FC_ELS_ACC 0x02
+#define FC_ELS_PLOGI 0x03
+#define FC_ELS_FLOGI 0x04
+#define FC_ELS_LOGOUT 0x05
+#define FC_ELS_ABTX 0x06
+#define FC_ELS_RSI 0x0A
+#define FC_ELS_TEST 0x11
+#define FC_ELS_RRQ 0x12
+#define FC_ELS_PRLI 0x20
+#define FC_ELS_PRLO 0x21
+#define FC_ELS_TPRLO 0x24
+#define FC_ELS_PDISC 0x50
+#define FC_ELS_FDISC 0x51
+#define FC_ELS_ADISC 0x52
+#define FC_ELS_FARP_REQ 0x54
+#define FC_ELS_FARP_RPLY 0x55
+#define FC_ELS_RPS 0x56
+#define FC_ELS_RPL 0x57
+#define FC_ELS_FAN 0x60
+#define FC_ELS_RSCN 0x61
+#define FC_ELS_SCR 0x62
+#define FC_ELS_RNFT 0x63
+#define FC_ELS_LINIT 0x70
+#define FC_ELS_LSTS 0x72
+#define FC_ELS_RNID 0x78
+#define FC_ELS_RLIR 0x79
+#define FC_ELS_LIRR 0x7A
+#define FC_ELS_SRL 0x7B
+#define FC_ELS_RPSC 0x7D
+#define FC_ELS_AUTH 0x90
+
+static const value_string fc_els_proto_val[] = {
+ {FC_ELS_LSRJT , "LS_RJT"},
+ {FC_ELS_ACC , "ACC"},
+ {FC_ELS_PLOGI , "PLOGI"},
+ {FC_ELS_FLOGI , "FLOGI"},
+ {FC_ELS_LOGOUT , "LOGO"},
+ {FC_ELS_ABTX , "ABTX"},
+ {FC_ELS_RSI , "RSI"},
+ {FC_ELS_TEST , "TEST"},
+ {FC_ELS_RRQ , "RRQ"},
+ {FC_ELS_PRLI , "PRLI"},
+ {FC_ELS_PRLO , "PRLO"},
+ {FC_ELS_TPRLO , "TPRLO"},
+ {FC_ELS_PDISC , "PDISC"},
+ {FC_ELS_FDISC , "FDISC"},
+ {FC_ELS_ADISC , "ADISC"},
+ {FC_ELS_FARP_REQ , "FARP-REQ"},
+ {FC_ELS_FARP_RPLY , "FARP-REPLY"},
+ {FC_ELS_RPS , "RPS"},
+ {FC_ELS_RPL , "RPL"},
+ {FC_ELS_FAN , "FAN"},
+ {FC_ELS_RSCN , "RSCN"},
+ {FC_ELS_SCR , "SCR"},
+ {FC_ELS_RNFT , "RNFT"},
+ {FC_ELS_LINIT , "LINIT"},
+ {FC_ELS_LSTS , "LSTS"},
+ {FC_ELS_RNID , "RNID"},
+ {FC_ELS_RLIR , "RLIR"},
+ {FC_ELS_LIRR , "LIRR"},
+ {FC_ELS_SRL , "SRL"},
+ {FC_ELS_RPSC , "RPSC"},
+ {FC_ELS_AUTH , "AUTH"},
+ {0, NULL},
+};
+
+/* Reject Reason Codes */
+#define FC_ELS_RJT_INVCMDCODE 0x01
+#define FC_ELS_RJT_LOGERR 0x03
+#define FC_ELS_RJT_LOGBSY 0x05
+#define FC_ELS_RJT_PROTERR 0x07
+#define FC_ELS_RJT_GENFAIL 0x09
+#define FC_ELS_RJT_CMDNOTSUPP 0x0B
+#define FC_ELS_RJT_GENFAIL2 0x0D
+#define FC_ELS_RJT_CMDINPROG 0x0E
+#define FC_ELS_RJT_VENDOR 0xFF
+
+static const value_string fc_els_rjt_val[] = {
+ {FC_ELS_RJT_INVCMDCODE, "Invalid Cmd Code"},
+ {FC_ELS_RJT_LOGERR , "Logical Error"},
+ {FC_ELS_RJT_LOGBSY , "Logical Busy"},
+ {FC_ELS_RJT_PROTERR , "Protocol Error"},
+ {FC_ELS_RJT_GENFAIL , "Unable to Perform Cmd"},
+ {FC_ELS_RJT_CMDNOTSUPP, "Command Not Supported"},
+ {FC_ELS_RJT_GENFAIL2 , "Unable to Perform Cmd"},
+ {FC_ELS_RJT_CMDINPROG , "Command in Progress Already"},
+ {FC_ELS_RJT_VENDOR , "Vendor Unique Error"},
+ {0, NULL},
+};
+
+#define FC_ELS_RJT_DET_NODET 0x00
+#define FC_ELS_RJT_DET_SVCPARM_OPT 0x01
+#define FC_ELS_RJT_DET_SVCPARM_INITCTL 0x03
+#define FC_ELS_RJT_DET_SVCPARM_RCPTCTL 0x05
+#define FC_ELS_RJT_DET_SVCPARM_RCVSZE 0x07
+#define FC_ELS_RJT_DET_SVCPARM_CSEQ 0x09
+#define FC_ELS_RJT_DET_SVCPARM_CREDIT 0x0B
+#define FC_ELS_RJT_DET_INV_PFNAME 0x0D
+#define FC_ELS_RJT_DET_INV_NFNAME 0x0E
+#define FC_ELS_RJT_DET_INV_CMNSVCPARM 0x0F
+#define FC_ELS_RJT_DET_INV_ASSOCHDR 0x11
+#define FC_ELS_RJT_DET_ASSOCHDR_REQD 0x13
+#define FC_ELS_RJT_DET_INV_OSID 0x15
+#define FC_ELS_RJT_DET_EXCHG_COMBO 0x17
+#define FC_ELS_RJT_DET_CMDINPROG 0x19
+#define FC_ELS_RJT_DET_PLOGI_REQ 0x1E
+#define FC_ELS_RJT_DET_INV_NPID 0x1F
+#define FC_ELS_RJT_DET_INV_SEQID 0x21
+#define FC_ELS_RJT_DET_INV_EXCHG 0x23
+#define FC_ELS_RJT_DET_INACTIVE_EXCHG 0x25
+#define FC_ELS_RJT_DET_RQUAL_REQD 0x27
+#define FC_ELS_RJT_DET_OORSRC 0x29
+#define FC_ELS_RJT_DET_SUPPLYFAIL 0x2A
+#define FC_ELS_RJT_DET_REQNOTSUPP 0x2C
+#define FC_ELS_RJT_DET_INV_PLEN 0x2D
+#define FC_ELS_RJT_DET_INV_ALIASID 0x30
+#define FC_ELS_RJT_DET_OORSRC_ALIASID 0x31
+#define FC_ELS_RJT_DET_INACTIVE_ALIASID 0x32
+#define FC_ELS_RJT_DET_DEACT_ALIAS_FAIL1 0x33
+#define FC_ELS_RJT_DET_DEACT_ALIAS_FAIL2 0x34
+#define FC_ELS_RJT_DET_SVCPARM_CONFLICT 0x35
+#define FC_ELS_RJT_DET_INV_ALIASTOK 0x36
+#define FC_ELS_RJT_DET_UNSUPP_ALIASTOK 0x37
+#define FC_ELS_RJT_DET_GRPFORM_FAIL 0x38
+#define FC_ELS_RJT_DET_QOSPARM_ERR 0x40
+#define FC_ELS_RJT_DET_INV_VCID 0x41
+#define FC_ELS_RJT_DET_OORSRC_C4 0x42
+#define FC_ELS_RJT_DET_INV_PNNAME 0x44
+#define FC_ELS_RJT_DET_AUTH_REQD 0x48
+
+static const value_string fc_els_rjt_det_val[] = {
+ {FC_ELS_RJT_DET_NODET , "No further details"},
+ {FC_ELS_RJT_DET_SVCPARM_OPT , "Svc Param - Options Error"},
+ {FC_ELS_RJT_DET_SVCPARM_INITCTL , "Svc Param - Initiator Ctl Error"},
+ {FC_ELS_RJT_DET_SVCPARM_RCPTCTL , "Svc Param - Recipient Ctl Error"},
+ {FC_ELS_RJT_DET_SVCPARM_RCVSZE , "Svc Param - Recv Size Error"},
+ {FC_ELS_RJT_DET_SVCPARM_CSEQ , "Svc Param - Concurrent Seq Error"},
+ {FC_ELS_RJT_DET_SVCPARM_CREDIT , "Svc Param - Credit Error"},
+ {FC_ELS_RJT_DET_INV_PFNAME , "Invalid N_/F_Port Name"},
+ {FC_ELS_RJT_DET_INV_NFNAME , "Invalid Node/Fabric Name"},
+ {FC_ELS_RJT_DET_INV_CMNSVCPARM , "Invalid Common Svc Param"},
+ {FC_ELS_RJT_DET_INV_ASSOCHDR , "Invalid Association Header"},
+ {FC_ELS_RJT_DET_ASSOCHDR_REQD , "Association Header Reqd"},
+ {FC_ELS_RJT_DET_INV_OSID , "Invalid Orig S_ID"},
+ {FC_ELS_RJT_DET_EXCHG_COMBO , "Invalid OXID-RXID Combo"},
+ {FC_ELS_RJT_DET_CMDINPROG , "Cmd Already in Progress"},
+ {FC_ELS_RJT_DET_PLOGI_REQ , "N_Port Login Required"},
+ {FC_ELS_RJT_DET_INV_NPID , "Invalid N_Port Id"},
+ {FC_ELS_RJT_DET_INV_SEQID , "Invalid SeqID"},
+ {FC_ELS_RJT_DET_INV_EXCHG , "Attempt to Abort Invalid Exchg"},
+ {FC_ELS_RJT_DET_INACTIVE_EXCHG , "Attempt to Abort Inactive Exchg"},
+ {FC_ELS_RJT_DET_RQUAL_REQD , "Resource Qualifier Required"},
+ {FC_ELS_RJT_DET_OORSRC , "Insufficient Resources for Login"},
+ {FC_ELS_RJT_DET_SUPPLYFAIL , "Unable to Supply Req Data"},
+ {FC_ELS_RJT_DET_REQNOTSUPP , "Command Not Supported"},
+ {FC_ELS_RJT_DET_INV_PLEN , "Invalid Payload Length"},
+ {FC_ELS_RJT_DET_INV_ALIASID , "No Alias IDs available"},
+ {FC_ELS_RJT_DET_OORSRC_ALIASID , "Alias_ID Cannot be Activated (Out of Rsrc)"},
+ {FC_ELS_RJT_DET_INACTIVE_ALIASID , "Alias_ID Cannot be Activated (Inv AID)"},
+ {FC_ELS_RJT_DET_DEACT_ALIAS_FAIL1, "Alias_ID Cannot be Deactivated"},
+ {FC_ELS_RJT_DET_DEACT_ALIAS_FAIL2, "Alias_ID Cannot be Deactivated"},
+ {FC_ELS_RJT_DET_SVCPARM_CONFLICT , "Svc Parameter Conflict"},
+ {FC_ELS_RJT_DET_INV_ALIASTOK , "Invalid Alias Token"},
+ {FC_ELS_RJT_DET_UNSUPP_ALIASTOK , "Unsupported Alias Token"},
+ {FC_ELS_RJT_DET_GRPFORM_FAIL , "Alias Grp Cannot be Formed"},
+ {FC_ELS_RJT_DET_QOSPARM_ERR , "QoS Param Error"},
+ {FC_ELS_RJT_DET_INV_VCID , "VC_ID Not Found"},
+ {FC_ELS_RJT_DET_OORSRC_C4 , "No Resources to Support Class 4 Conn"},
+ {FC_ELS_RJT_DET_INV_PNNAME , "Invalid Port/Node Name"},
+ {FC_ELS_RJT_DET_AUTH_REQD , "Authentication Required"},
+ {0, NULL},
+};
+
+static const value_string fc_els_flacompliance_val[] = {
+ {1, "FC-FLA Level 1"},
+ {2, "FC-FLA Level 2"},
+ {0, NULL},
+};
+
+static const value_string fc_els_loopstate_val[] = {
+ {1, "Online"},
+ {2, "Loop Failure"},
+ {3, "Initialization Failure"},
+ {4, "Initializing"},
+ {0, NULL},
+};
+
+static const value_string fc_els_scr_reg_val[] = {
+ {1, "Fabric Detected Regn"},
+ {2, "N_Port Detected Regn"},
+ {3, "Full Regn"},
+ {255, "Clear All Regn"},
+ {0, NULL},
+};
+
+static const value_string fc_els_farp_respaction_val[] = {
+ {0, "No Action"},
+ {1, "Login Using Requesting Port ID"},
+ {2, "Respond with FARP-REPLY"},
+ {3, "Login & send FARP-REPLY"},
+ {0, NULL},
+};
+
+static const value_string fc_els_portstatus_val[] = {
+ {0x20, "Point-to-Point Connection | No Fabric"},
+ {0x10, "AL Connection | No Fabric"},
+ {0x28, "Point-to-Point Connection | Fabric Detected"},
+ {0x2C, "Point-to-Point Connection | Fabric Detected | Loss of Signal"},
+ {0x24, "Point-to-Point Connection | Loss of Signal"},
+ {0x18, "AL Connection | Fabric Detected"},
+ {0x14, "AL Connection | Loss of Signal"},
+ {0x1C, "AL Connection | Fabric Detected | Loss of Signal"},
+ {0x04, "Loss of Signal"},
+ {0x02, "Loss of Synchronization"},
+ {0x01, "Link Reset Protocol in Progress"},
+ {0, NULL},
+};
+
+static const value_string fc_els_portspeed_val[] = {
+ {0x8000, "1 Gb"},
+ {0x4000, "2 Gb"},
+ {0x2000, "4 Gb"},
+ {0x1000, "10 Gb"},
+ {0x0002, "Unknown"},
+ {0x0001, "Speed Not Estd."},
+ {0, NULL}
+};
+
+static const value_string fc_els_lirr_regfunc_val[] = {
+ {0x1, "Set Reg: Conditionally Receive"},
+ {0x2, "Set Reg: Always Receive"},
+ {0xFF, "Clear Reg"},
+ {0, NULL},
+};
+
+static const value_string fc_els_rscn_evqual_val[] = {
+ {0x00, "Event is not specified"},
+ {0x01, "Changed Name Server Object"},
+ {0x02, "Changed Port Attribute"},
+ {0x03, "Changed Service Object"},
+ {0x04, "Changed Switch Config"},
+ {0, NULL},
+};
+
+static const value_string fc_els_rscn_addrfmt_val[] = {
+ {0, "Port Addr (single N/L Port or service)"},
+ {1, "Area Addr Group (area of E/L/N Port addresses)"},
+ {2, "Domain Addr Group"},
+ {3, "Fabric Addr Group"},
+ {0, NULL},
+};
+
+static const value_string fc_els_nodeid_val[] = {
+ {0x00, "Common Identification Data Only"},
+ {0x05, "IP Specific Data"},
+ {0x08, "FCP-Specific Data"},
+ {0x20, "FC_CT Specific Data"},
+ {0x22, "SW_ILS Specific Data"},
+ {0x23, "AL Specific Data"},
+ {0x24, "SNMP Specific Data"},
+ {0xDF, "Common ID Data + General Topology Discovery Format"},
+ {0, NULL},
+};
+
+static const value_string fc_els_rnid_asstype_val[] = {
+ {0x0, "Reserved"},
+ {0x1, "Unknown"},
+ {0x2, "Other"},
+ {0x3, "Hub"},
+ {0x4, "Switch"},
+ {0x5, "Gateway"},
+ {0x6, "Converter"},
+ {0x7, "HBA"},
+ {0x9, "Storage Device"},
+ {0xA, "Host"},
+ {0xB, "Storage Subsystem"},
+ {0xE, "Storage Access Device"},
+ {0x11, "NAS Device"},
+ {0, NULL},
+};
+
+static const value_string fc_els_rnid_mgmt_val[] = {
+ {0, "IP/UDP/SNMP"},
+ {1, "IP/TCP/Telnet"},
+ {2, "IP/TCP/HTTP"},
+ {3, "IP/TCP/HTTPS"},
+ {0, NULL},
+};
+
+static const value_string fc_els_rnid_ipvers_val[] = {
+ {0, "None"},
+ {1, "IPv4"},
+ {2, "IPv6"},
+ {0, NULL},
+};
+
+#endif
diff --git a/epan/dissectors/packet-fcfcs.c b/epan/dissectors/packet-fcfcs.c
new file mode 100644
index 0000000000..179e9f1e66
--- /dev/null
+++ b/epan/dissectors/packet-fcfcs.c
@@ -0,0 +1,1184 @@
+/* packet-fcfcs.c
+ * Routines for FC Fabric Configuration Server
+ * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fcct.h"
+#include "packet-fcfcs.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_fcfcs = -1;
+static int hf_fcs_opcode = -1;
+static int hf_fcs_iename = -1;
+static int hf_fcs_ietype = -1;
+static int hf_fcs_iedomainid = -1;
+static int hf_fcs_mgmtid = -1;
+static int hf_fcs_fabricname = -1;
+static int hf_fcs_mgmtaddr = -1;
+static int hf_fcs_lname = -1;
+static int hf_fcs_vendorname = -1;
+static int hf_fcs_modelname = -1;
+static int hf_fcs_portname = -1;
+static int hf_fcs_portmodtype = -1;
+static int hf_fcs_porttxtype = -1;
+static int hf_fcs_porttype = -1;
+static int hf_fcs_physportnum = -1;
+static int hf_fcs_portflags = -1;
+static int hf_fcs_portstate = -1;
+static int hf_fcs_platformname = -1;
+static int hf_fcs_platformnname = -1;
+static int hf_fcs_platformtype = -1;
+static int hf_fcs_platformaddr = -1;
+static int hf_fcs_reason = -1;
+static int hf_fcs_rjtdetail = -1;
+static int hf_fcs_vendor = -1;
+static int hf_fcs_numcap = -1;
+static int hf_fcs_mgmt_subtype = -1;
+static int hf_fcs_unsmask = -1;
+static int hf_fcs_vnd_capmask = -1;
+static int hf_fcs_fcsmask = -1;
+static int hf_fcs_maxres_size = -1;
+static int hf_fcs_releasecode = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_fcfcs = -1;
+
+typedef struct _fcfcs_conv_key {
+ guint32 conv_idx;
+} fcfcs_conv_key_t;
+
+typedef struct _fcfcs_conv_data {
+ guint32 opcode;
+} fcfcs_conv_data_t;
+
+GHashTable *fcfcs_req_hash = NULL;
+GMemChunk *fcfcs_req_keys = NULL;
+GMemChunk *fcfcs_req_vals = NULL;
+guint32 fcfcs_init_count = 25;
+
+static dissector_handle_t data_handle;
+
+/*
+ * Hash Functions
+ */
+static gint
+fcfcs_equal(gconstpointer v, gconstpointer w)
+{
+ fcfcs_conv_key_t *v1 = (fcfcs_conv_key_t *)v;
+ fcfcs_conv_key_t *v2 = (fcfcs_conv_key_t *)w;
+
+ return (v1->conv_idx == v2->conv_idx);
+}
+
+static guint
+fcfcs_hash (gconstpointer v)
+{
+ fcfcs_conv_key_t *key = (fcfcs_conv_key_t *)v;
+ guint val;
+
+ val = key->conv_idx;
+
+ return val;
+}
+
+/*
+ * Protocol initialization
+ */
+static void
+fcfcs_init_protocol(void)
+{
+ if (fcfcs_req_keys)
+ g_mem_chunk_destroy (fcfcs_req_keys);
+ if (fcfcs_req_vals)
+ g_mem_chunk_destroy (fcfcs_req_vals);
+ if (fcfcs_req_hash)
+ g_hash_table_destroy (fcfcs_req_hash);
+
+ fcfcs_req_hash = g_hash_table_new(fcfcs_hash, fcfcs_equal);
+ fcfcs_req_keys = g_mem_chunk_new ("fcfcs_req_keys",
+ sizeof(fcfcs_conv_key_t),
+ fcfcs_init_count *
+ sizeof(fcfcs_conv_key_t),
+ G_ALLOC_AND_FREE);
+ fcfcs_req_vals = g_mem_chunk_new ("fcfcs_req_vals",
+ sizeof(fcfcs_conv_data_t),
+ fcfcs_init_count *
+ sizeof(fcfcs_conv_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_fcfcs_giel (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the ct header */
+ int numelem, i;
+
+ if (!isreq && tree) {
+ numelem = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_text (tree, tvb, offset, 4, "Number of IE entries: 0x%d",
+ numelem);
+ offset += 4;
+ for (i = 0; i < numelem; i++) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ proto_tree_add_item (tree, hf_fcs_ietype, tvb, offset+11, 1, 0);
+ offset += 12;
+ }
+ }
+}
+
+static void
+dissect_fcfcs_giet (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ proto_tree_add_item (tree, hf_fcs_ietype, tvb, offset+3, 1, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gdid (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ proto_tree_add_item (tree, hf_fcs_iedomainid, tvb, offset+1, 1, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gmid (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ proto_tree_add_string (tree, hf_fcs_mgmtid, tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gfn (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ proto_tree_add_string (tree, hf_fcs_fabricname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gieln (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ proto_tree_add_text (tree, tvb, offset, 1, "Name Length: %d",
+ tvb_get_guint8 (tvb, offset));
+ proto_tree_add_item (tree, hf_fcs_lname, tvb, offset+1,
+ tvb_get_guint8 (tvb, offset), 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gmal (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+ int numelem, i;
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ numelem = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Number of Mgmt. Addresses: 0x%d", numelem);
+
+ offset += 4;
+ for (i = 0; i < numelem; i++) {
+ proto_tree_add_text (tree, tvb, offset, 1, "Name Length: %d",
+ tvb_get_guint8 (tvb, offset));
+ proto_tree_add_item (tree, hf_fcs_mgmtaddr, tvb, offset+1,
+ tvb_get_guint8 (tvb, offset), 0);
+ offset += 256;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gieil (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+ gchar *str;
+ int len, tot_len, prevlen;
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ tot_len = tvb_get_guint8 (tvb, offset+3);
+ proto_tree_add_text (tree, tvb, offset+3, 1, "List Length: %d",
+ tot_len);
+
+ prevlen = 0;
+ str = (gchar *)tvb_get_ptr (tvb, offset+4, tot_len);
+ len = strlen (str);
+ if (len) {
+ proto_tree_add_item (tree, hf_fcs_vendorname, tvb, offset+4,
+ len, 0);
+ }
+
+ prevlen += (len+1);
+ str = (gchar *)tvb_get_ptr (tvb, offset+4+prevlen, tot_len-prevlen);
+ len = strlen (str);
+
+ if (len) {
+ proto_tree_add_item (tree, hf_fcs_modelname, tvb, offset+4+prevlen,
+ len, 0);
+ }
+
+ prevlen += (len+1);
+ str = (gchar *)tvb_get_ptr (tvb, offset+4+prevlen, tot_len-prevlen);
+ len = strlen (str);
+
+ if (len) {
+ proto_tree_add_item (tree, hf_fcs_releasecode, tvb,
+ offset+4+prevlen, len, 0);
+ }
+
+ prevlen += (len+1);
+ offset += (4+prevlen);
+ while (tot_len > prevlen) {
+ str = (gchar *)tvb_get_ptr (tvb, offset, tot_len-prevlen);
+ len = strlen (str);
+ if (len) {
+ proto_tree_add_text (tree, tvb, offset, len,
+ "Vendor-specific Information: %s",
+ str);
+ }
+ prevlen += (len+1);
+ offset += (len+1);
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gpl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+ int numelem, i;
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ numelem = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Number of Port Entries: %d",
+ numelem);
+ offset += 4;
+
+ for (i = 0; i < numelem; i++) {
+ proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ proto_tree_add_item (tree, hf_fcs_portmodtype, tvb, offset+9,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcs_porttxtype, tvb, offset+10,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcs_porttype, tvb, offset+11,
+ 1, 0);
+ offset += 12;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gpt (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ proto_tree_add_item (tree, hf_fcs_porttype, tvb, offset+3, 1, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gppn (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ proto_tree_add_item (tree, hf_fcs_physportnum, tvb, offset, 4, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gapnl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+ int numelem, i;
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ numelem = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Number of Attached Port Entries: %d",
+ numelem);
+ offset += 4;
+ for (i = 0; i < numelem; i++) {
+ proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ proto_tree_add_item (tree, hf_fcs_portflags, tvb, offset+10,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcs_porttype, tvb, offset+11,
+ 1, 0);
+ offset += 12;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gps (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_portname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ proto_tree_add_item (tree, hf_fcs_porttype, tvb, offset+3, 1, 0);
+ proto_tree_add_item (tree, hf_fcs_portstate, tvb, offset+7, 1, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gplnl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+ int numelem, i, len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ }
+ else {
+ numelem = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Number of Platform Node Name Entries: %d",
+ numelem);
+ offset += 4;
+ for (i = 0; i < numelem; i++) {
+ proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset,
+ 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ offset += 8;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gplt (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ }
+ else {
+ proto_tree_add_item (tree, hf_fcs_platformtype, tvb, offset+3,
+ 1, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gplml (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+ int numelem, i, len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ }
+ else {
+ numelem = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Number of Mgmt. Address Entries: %d",
+ numelem);
+ offset += 4;
+ for (i = 0; i < numelem; i++) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Mgmt Address Length: %d",
+ len);
+ proto_tree_add_item (tree, hf_fcs_platformaddr, tvb, offset+1,
+ len, 0);
+ offset += 256;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gnpl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ else {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gpnl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fcct header */
+ int numelem, i, len;
+
+ if (tree) {
+ if (!isreq) {
+ numelem = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Number of Platform Name Entries: %d",
+ numelem);
+ offset += 4;
+ for (i = 0; i < numelem; i++) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d",
+ len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ offset += 256;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfcs_rieln (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_iename, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ len = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_text (tree, tvb, offset+8, 1,
+ "Logical Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_lname, tvb, offset+9, len, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_rpl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int numelem, i, len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ proto_tree_add_item (tree, hf_fcs_platformtype, tvb, offset+256, 4,
+ 0);
+ numelem = tvb_get_ntohl (tvb, offset+260);
+ proto_tree_add_text (tree, tvb, offset+260, 4,
+ "Number of Mgmt. Addr Entries: %d", numelem);
+ offset += 264;
+ for (i = 0; i < numelem; i++) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Mgmt. Addr Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_mgmtaddr, tvb, offset+1,
+ len, 0);
+ offset += 256;
+ }
+
+ numelem = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Number of Platform Node Name Entries: %d",
+ numelem);
+ offset += 4;
+ for (i = 0; i < numelem; i++) {
+ proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset,
+ 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset,
+ 8)));
+ offset += 8;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfcs_rpln (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset+256,
+ 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+256,
+ 8)));
+ }
+ }
+}
+
+static void
+dissect_fcfcs_rplt (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ proto_tree_add_item (tree, hf_fcs_platformtype, tvb, offset+256,
+ 4, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_rplm (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ len = tvb_get_guint8 (tvb, offset+256);
+ proto_tree_add_text (tree, tvb, offset+256, 1,
+ "Platform Mgmt. Address Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformaddr, tvb, offset+257,
+ len, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_dpl (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_dpln (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (tree) {
+ if (isreq) {
+ proto_tree_add_string (tree, hf_fcs_platformnname, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ }
+ }
+}
+
+static void
+dissect_fcfcs_dplml (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Platform Name Length: %d", len);
+ proto_tree_add_item (tree, hf_fcs_platformname, tvb, offset+1,
+ len, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfcs_gcap (tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int numrec, i;
+ guint8 subtype;
+
+ if (tree) {
+ if (!isreq) {
+ numrec = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_item (tree, hf_fcs_numcap, tvb, offset, 4, 0);
+
+ offset += 4;
+ for (i = 0; i < numrec; i++) {
+ proto_tree_add_item (tree, hf_fcs_mgmt_subtype, tvb, offset,
+ 1, 0);
+ subtype = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_item (tree, hf_fcs_vnd_capmask, tvb, offset+1,
+ 3, 0);
+ if (subtype == FCCT_GSSUBTYPE_FCS) {
+ proto_tree_add_item (tree, hf_fcs_fcsmask, tvb, offset+4,
+ 4, 0);
+ }
+ else if (subtype == FCCT_GSSUBTYPE_UNS) {
+ proto_tree_add_item (tree, hf_fcs_unsmask, tvb, offset+4,
+ 4, 0);
+ }
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfcs_rjt (tvbuff_t *tvb, proto_tree *tree)
+{
+ int offset = 0;
+
+ if (tree) {
+ proto_tree_add_item (tree, hf_fcs_reason, tvb, offset+13, 1, 0);
+ proto_tree_add_item (tree, hf_fcs_rjtdetail, tvb, offset+14, 1,
+ 0);
+ proto_tree_add_item (tree, hf_fcs_vendor, tvb, offset+15, 1, 0);
+ }
+
+}
+
+static void
+dissect_fcfcs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ proto_item *ti;
+ proto_tree *fcfcs_tree = NULL;
+ fc_ct_preamble cthdr;
+ gboolean isreq = 1;
+ conversation_t *conversation;
+ fcfcs_conv_data_t *cdata;
+ fcfcs_conv_key_t ckey, *req_key;
+ int opcode,
+ failed_opcode = 0;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FC-FCS");
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcfcs, tvb, 0,
+ tvb_reported_length (tvb),
+ "FCS");
+ fcfcs_tree = proto_item_add_subtree (ti, ett_fcfcs);
+ }
+
+ tvb_memcpy (tvb, (guint8 *)&cthdr, offset, FCCT_PRMBL_SIZE);
+ cthdr.revision = tvb_get_guint8 (tvb, offset);
+ cthdr.in_id = tvb_get_ntoh24 (tvb, offset+1);
+ cthdr.opcode = ntohs (cthdr.opcode);
+ opcode = tvb_get_ntohs (tvb, offset+8);
+ cthdr.maxres_size = ntohs (cthdr.maxres_size);
+
+ if ((opcode != FCCT_MSG_ACC) && (opcode != FCCT_MSG_RJT)) {
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ if (!conversation) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ }
+
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcfcs_conv_data_t *)g_hash_table_lookup (fcfcs_req_hash,
+ &ckey);
+ if (cdata) {
+ /* Since we never free the memory used by an exchange, this maybe a
+ * case of another request using the same exchange as a previous
+ * req.
+ */
+ cdata->opcode = opcode;
+ }
+ else {
+ req_key = g_mem_chunk_alloc (fcfcs_req_keys);
+ req_key->conv_idx = conversation->index;
+
+ cdata = g_mem_chunk_alloc (fcfcs_req_vals);
+ cdata->opcode = opcode;
+
+ g_hash_table_insert (fcfcs_req_hash, req_key, cdata);
+ }
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO,
+ val_to_str (opcode, fc_fcs_opcode_abbrev_val, "0x%x"));
+ }
+ }
+ else {
+ /* Opcode is ACC or RJT */
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ isreq = 0;
+ if (!conversation) {
+ if (tree && (opcode == FCCT_MSG_ACC)) {
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO,
+ val_to_str (opcode, fc_fcs_opcode_abbrev_val,
+ "0x%x"));
+ }
+ /* No record of what this accept is for. Can't decode */
+ proto_tree_add_text (fcfcs_tree, tvb, 0, tvb_length (tvb),
+ "No record of Exchg. Unable to decode MSG_ACC/RJT");
+ return;
+ }
+ }
+ else {
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcfcs_conv_data_t *)g_hash_table_lookup (fcfcs_req_hash,
+ &ckey);
+
+ if (cdata != NULL) {
+ if (opcode == FCCT_MSG_ACC)
+ opcode = cdata->opcode;
+ else
+ failed_opcode = cdata->opcode;
+ }
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if (opcode != FCCT_MSG_RJT) {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "MSG_ACC (%s)",
+ val_to_str (opcode, fc_fcs_opcode_abbrev_val,
+ "0x%x"));
+ }
+ else {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "MSG_RJT (%s)",
+ val_to_str (failed_opcode,
+ fc_fcs_opcode_abbrev_val,
+ "0x%x"));
+ }
+ }
+
+ if (tree) {
+ if ((cdata == NULL) && (opcode != FCCT_MSG_RJT)) {
+ /* No record of what this accept is for. Can't decode */
+ proto_tree_add_text (fcfcs_tree, tvb, 0, tvb_length (tvb),
+ "No record of Exchg. Unable to decode MSG_ACC/RJT");
+ return;
+ }
+ }
+ }
+ }
+
+
+ if (tree) {
+ proto_tree_add_item (fcfcs_tree, hf_fcs_opcode, tvb, offset+8, 2, 0);
+ proto_tree_add_item (fcfcs_tree, hf_fcs_maxres_size, tvb, offset+10,
+ 2, 0);
+ }
+
+ switch (opcode) {
+ case FCCT_MSG_RJT:
+ dissect_fcfcs_rjt (tvb, fcfcs_tree);
+ break;
+ case FCFCS_GIEL:
+ dissect_fcfcs_giel (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GIET:
+ dissect_fcfcs_giet (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GDID:
+ dissect_fcfcs_gdid (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GMID:
+ dissect_fcfcs_gmid (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GFN:
+ dissect_fcfcs_gfn (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GIELN:
+ dissect_fcfcs_gieln (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GMAL:
+ dissect_fcfcs_gmal (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GIEIL:
+ dissect_fcfcs_gieil (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GPL:
+ dissect_fcfcs_gpl (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GPT:
+ dissect_fcfcs_gpt (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GPPN:
+ dissect_fcfcs_gppn (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GAPNL:
+ dissect_fcfcs_gapnl (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GPS:
+ dissect_fcfcs_gps (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GPLNL:
+ dissect_fcfcs_gplnl (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GPLT:
+ dissect_fcfcs_gplt (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GPLML:
+ dissect_fcfcs_gplml (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GNPL:
+ dissect_fcfcs_gnpl (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GPNL:
+ dissect_fcfcs_gpnl (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_RIELN:
+ dissect_fcfcs_rieln (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_RPL:
+ dissect_fcfcs_rpl (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_RPLN:
+ dissect_fcfcs_rpln (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_RPLT:
+ dissect_fcfcs_rplt (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_RPLM:
+ dissect_fcfcs_rplm (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_DPL:
+ dissect_fcfcs_dpl (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_DPLN:
+ dissect_fcfcs_dpln (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_DPLML:
+ dissect_fcfcs_dplml (tvb, fcfcs_tree, isreq);
+ break;
+ case FCFCS_GCAP:
+ dissect_fcfcs_gcap (tvb, fcfcs_tree, isreq);
+ break;
+ default:
+ call_dissector (data_handle, tvb, pinfo, fcfcs_tree);
+ break;
+ }
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_fcfcs (void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_fcs_opcode,
+ {"Opcode", "fcs.opcode", FT_UINT16, BASE_HEX,
+ VALS (fc_fcs_opcode_val), 0x0, "", HFILL}},
+ { &hf_fcs_iename,
+ {"Interconnect Element Name", "fcs.ie.name", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcs_ietype,
+ {"Interconnect Element Type", "fcs.ie.type", FT_UINT8, BASE_HEX,
+ VALS (fc_fcs_ietype_val), 0x0, "", HFILL}},
+ { &hf_fcs_iedomainid,
+ {"Interconnect Element Domain ID", "fcs.ie.domainid", FT_UINT8,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcs_mgmtid,
+ {"Interconnect Element Mgmt. ID", "fcs.ie.mgmtid", FT_STRING,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcs_fabricname,
+ {"Interconnect Element Fabric Name", "fcs.ie.fname", FT_STRING,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcs_mgmtaddr,
+ {"Interconnect Element Mgmt. Address", "fcs.ie.mgmtaddr", FT_STRING,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcs_lname,
+ {"Interconnect Element Logical Name", "fcs.ie.logname", FT_STRING,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcs_vendorname,
+ {"Vendor Name", "fcs.vendorname", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcs_modelname,
+ {"Model Name/Number", "fcs.modelname", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcs_portname,
+ {"Port Name", "fcs.port.name", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcs_portmodtype,
+ {"Port Module Type", "fcs.port.moduletype", FT_UINT8, BASE_HEX,
+ VALS (fc_fcs_port_modtype_val), 0x0, "", HFILL}},
+ { &hf_fcs_porttxtype,
+ {"Port TX Type", "fcs.port.txtype", FT_UINT8, BASE_HEX,
+ VALS (fc_fcs_port_txtype_val), 0x0, "", HFILL}},
+ { &hf_fcs_porttype,
+ {"Port Type", "fcs.port.type", FT_UINT8, BASE_HEX,
+ VALS (fc_fcs_port_type_val), 0x0, "", HFILL}},
+ { &hf_fcs_physportnum,
+ {"Physical Port Number", "fcs.port.physportnum", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcs_portflags,
+ {"Port Flags", "fcs.port.flags", FT_BOOLEAN, BASE_NONE,
+ TFS (&fc_fcs_portflags_tfs), 0x0, "", HFILL}},
+ { &hf_fcs_portstate,
+ {"Port State", "fcs.port.state", FT_UINT8, BASE_HEX,
+ VALS (fc_fcs_port_state_val), 0x0, "", HFILL}},
+ { &hf_fcs_platformname,
+ {"Platform Name", "fcs.platform.name", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcs_platformnname,
+ {"Platform Node Name", "fcs.platform.nodename", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcs_platformtype,
+ {"Platform Type", "fcs.platform.type", FT_UINT8, BASE_HEX,
+ VALS (fc_fcs_plat_type_val), 0x0, "", HFILL}},
+ { &hf_fcs_platformaddr,
+ {"Management Address", "fcs.platform.mgmtaddr", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcs_reason,
+ {"Reason Code", "fcs.reason", FT_UINT8, BASE_HEX,
+ VALS (fc_ct_rjt_code_vals), 0x0, "", HFILL}},
+ { &hf_fcs_rjtdetail,
+ {"Reason Code Explanantion", "fcs.reasondet", FT_UINT8, BASE_HEX,
+ VALS (fc_fcs_rjt_code_val), 0x0, "", HFILL}},
+ { &hf_fcs_vendor,
+ {"Vendor Unique Reject Code", "fcs.err.vendor", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcs_numcap,
+ {"Number of Capabilities", "fcs.numcap", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcs_mgmt_subtype,
+ {"Management GS Subtype", "fcs.gssubtype", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcs_vnd_capmask,
+ {"Vendor Unique Capability Bitmask", "fcs.vbitmask", FT_UINT24,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_fcs_fcsmask,
+ {"Subtype Capability Bitmask", "fcs.fcsmask", FT_UINT32, BASE_HEX,
+ VALS (fc_fcs_fcsmask_val), 0x0, "", HFILL}},
+ { &hf_fcs_unsmask,
+ {"Subtype Capability Bitmask", "fcs.unsmask", FT_UINT32, BASE_HEX,
+ VALS (fc_fcs_unsmask_val), 0x0, "", HFILL}},
+ { &hf_fcs_maxres_size,
+ {"Maximum/Residual Size", "fcs.maxres_size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcs_releasecode,
+ {"Release Code", "fcs.releasecode", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fcfcs,
+ };
+
+ /* Register the protocol name and description */
+ proto_fcfcs = proto_register_protocol("FC Fabric Configuration Server",
+ "FC-FCS", "fcs");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fcfcs, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine (&fcfcs_init_protocol);
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fcfcs (void)
+{
+ dissector_handle_t fcs_handle;
+
+ fcs_handle = create_dissector_handle (dissect_fcfcs, proto_fcfcs);
+
+ dissector_add("fcct.server", FCCT_GSRVR_FCS, fcs_handle);
+
+ data_handle = find_dissector ("data");
+}
+
diff --git a/epan/dissectors/packet-fcfcs.h b/epan/dissectors/packet-fcfcs.h
new file mode 100644
index 0000000000..daca528a9a
--- /dev/null
+++ b/epan/dissectors/packet-fcfcs.h
@@ -0,0 +1,256 @@
+/* packet-fcfcs.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCFCS_H_
+#define __PACKET_FCFCS_H_
+
+#define FCFCS_GTIN 0x100
+#define FCFCS_GIEL 0x101
+#define FCFCS_GIET 0x111
+#define FCFCS_GDID 0x112
+#define FCFCS_GMID 0x113
+#define FCFCS_GFN 0x114
+#define FCFCS_GIELN 0x115
+#define FCFCS_GMAL 0x116
+#define FCFCS_GIEIL 0x117
+#define FCFCS_GPL 0x118
+#define FCFCS_GPT 0x121
+#define FCFCS_GPPN 0x122
+#define FCFCS_GAPNL 0x124
+#define FCFCS_GPS 0x126
+#define FCFCS_GATIN 0x128
+#define FCFCS_GPLNL 0x191
+#define FCFCS_GPLT 0x192
+#define FCFCS_GPLML 0x193
+#define FCFCS_GNPL 0x1A1
+#define FCFCS_GPNL 0x1A2
+#define FCFCS_GNID 0x1B1
+#define FCFCS_RIELN 0x215
+#define FCFCS_RPL 0x280
+#define FCFCS_RPLN 0x291
+#define FCFCS_RPLT 0x292
+#define FCFCS_RPLM 0x293
+#define FCFCS_DPL 0x380
+#define FCFCS_DPLN 0x391
+#define FCFCS_DPLML 0x393
+#define FCFCS_GCAP 0xe020
+
+/* Used in protocol detail window */
+static const value_string fc_fcs_opcode_val[] = {
+ {FCCT_MSG_ACC, "MSG_ACC"},
+ {FCCT_MSG_RJT, "MSG_RJT"},
+ {FCFCS_GTIN, "Get Topology Info"},
+ {FCFCS_GIEL, "Get Interconnect Element List"},
+ {FCFCS_GIET, "Get Interconnect Element Type"},
+ {FCFCS_GDID, "Get Interconnect Element Domain ID"},
+ {FCFCS_GMID, "Get Interconnect Element Mgmt ID"},
+ {FCFCS_GFN, "Get Interconnect Element Fabric Name"},
+ {FCFCS_GIELN, "Get Interconnect Element Logical Name"},
+ {FCFCS_GMAL, "Get Interconnect Element Mgmt Addr List"},
+ {FCFCS_GIEIL, "Get Interconnect Element Info List"},
+ {FCFCS_GPL, "Get Port List"},
+ {FCFCS_GPT, "Get Port Type"},
+ {FCFCS_GPPN, "Get Physical Port Number"},
+ {FCFCS_GAPNL, "Get Physical Port Name List"},
+ {FCFCS_GPS, "Get Port State"},
+ {FCFCS_GATIN, "Get Attached Topology Info"},
+ {FCFCS_GPLNL, "Get Platform Node Name List"},
+ {FCFCS_GPLT, "Get Platform Type"},
+ {FCFCS_GPLML, "Get Platform Mgmt Addr List"},
+ {FCFCS_GNPL, "Get Platform Node Name List"},
+ {FCFCS_GPNL, "Get Platform Name List"},
+ {FCFCS_GNID, "Get Node Identification Data"},
+ {FCFCS_RIELN, "Register Interconnect Element Logical Name"},
+ {FCFCS_RPL, "Register Platform"},
+ {FCFCS_RPLN, "Register Platform Node Name"},
+ {FCFCS_RPLT, "Register Platform Type"},
+ {FCFCS_RPLM, "Register Platform Mgmt. Address"},
+ {FCFCS_DPL, "Deregister Platform"},
+ {FCFCS_DPLN, "Deregister Platform Node Name"},
+ {FCFCS_DPLML, "Deregister Platform Mgmt. Address List"},
+ {FCFCS_GCAP, "Get Capabilities"},
+ {0, NULL},
+};
+
+/* Used in protocol summary window */
+static const value_string fc_fcs_opcode_abbrev_val[] = {
+ {FCCT_MSG_ACC, "MSG_ACC"},
+ {FCCT_MSG_RJT, "MSG_RJT"},
+ {FCFCS_GTIN, "GTIN"},
+ {FCFCS_GIEL, "GIEL"},
+ {FCFCS_GIET, "GIET"},
+ {FCFCS_GDID, "GDID"},
+ {FCFCS_GMID, "GMID"},
+ {FCFCS_GFN, "GFN"},
+ {FCFCS_GIELN, "GIELN"},
+ {FCFCS_GMAL, "GMAL"},
+ {FCFCS_GIEIL, "GIEIL"},
+ {FCFCS_GPL, "GPL"},
+ {FCFCS_GPT, "GPT"},
+ {FCFCS_GPPN, "GPPN"},
+ {FCFCS_GAPNL, "GAPNL"},
+ {FCFCS_GPS, "GPS"},
+ {FCFCS_GATIN, "GATIN"},
+ {FCFCS_GPLNL, "GPLNL"},
+ {FCFCS_GPLT, "GPLT"},
+ {FCFCS_GPLML, "GPLML"},
+ {FCFCS_GNPL, "GNPL"},
+ {FCFCS_GPNL, "GPNL"},
+ {FCFCS_GNID, "GNID"},
+ {FCFCS_RIELN, "RIELN"},
+ {FCFCS_RPL, "RPL"},
+ {FCFCS_RPLN, "RPLN"},
+ {FCFCS_RPLT, "RPLT"},
+ {FCFCS_RPLM, "RPLM"},
+ {FCFCS_DPL, "DPL"},
+ {FCFCS_DPLN, "DPLN"},
+ {FCFCS_DPLML, "DPLML"},
+ {FCFCS_GCAP, "GCAP"},
+ {0, NULL},
+};
+
+static const value_string fc_fcs_ietype_val[] = {
+ {0, "Unknown"},
+ {1, "Switch"},
+ {2, "Hub"},
+ {3, "Bridge"},
+ {0, NULL},
+};
+
+/* Port type definitions, same as in dNS (fcdns.h) */
+#define FCFCS_PTYPE_UNDEF 0x00
+#define FCFCS_PTYPE_NPORT 0x01
+#define FCFCS_PTYPE_NLPORT 0x02
+#define FCFCS_PTYPE_FNLPORT 0x03
+#define FCFCS_PTYPE_NXPORT 0x7F
+#define FCFCS_PTYPE_FPORT 0x81
+#define FCFCS_PTYPE_FLPORT 0x82
+#define FCFCS_PTYPE_EPORT 0x84
+#define FCFCS_PTYPE_BPORT 0x85
+
+static const value_string fc_fcs_port_type_val[] = {
+ {FCFCS_PTYPE_UNDEF , "Undefined Port Type"},
+ {FCFCS_PTYPE_NPORT , "N_Port"},
+ {FCFCS_PTYPE_NLPORT , "NL_Port"},
+ {FCFCS_PTYPE_FNLPORT , "F/NL_Port"},
+ {FCFCS_PTYPE_NXPORT , "Nx_Port"},
+ {FCFCS_PTYPE_FPORT , "F_Port"},
+ {FCFCS_PTYPE_FLPORT , "FL_Port"},
+ {FCFCS_PTYPE_EPORT , "E_Port"},
+ {FCFCS_PTYPE_BPORT , "B_Port"},
+ {0, NULL},
+};
+
+static const value_string fc_fcs_port_txtype_val[] = {
+ {1, "Unknown"},
+ {2, "Long Wave Laser"},
+ {3, "Short Wave Laser"},
+ {4, "Long Wave Laser Cost Reduced"},
+ {5, "Electrical"},
+ {0, NULL},
+};
+
+static const value_string fc_fcs_port_modtype_val[] = {
+ {1, "Unknown"},
+ {2, "Other"},
+ {3, "GBIC"},
+ {4, "Embedded"},
+ {5, "GLM"},
+ {6, "GBIC with Serial ID"},
+ {7, "GBIC without Serial ID"},
+ {8, "SFP with Serial ID"},
+ {9, "SFP without Serial ID"},
+ {0, NULL},
+};
+
+static const value_string fc_fcs_port_state_val[] = {
+ {0, "Unknown"},
+ {1, "Online"},
+ {2, "Offline"},
+ {3, "Testing"},
+ {4, "Fault"},
+ {0, NULL},
+};
+
+static const value_string fc_fcs_plat_type_val[] = {
+ {1, "Unknown"},
+ {2, "Other"},
+ {5, "Gateway"},
+ {6, "Converter"},
+ {7, "HBA"},
+ {8, "Software Proxy Agent"},
+ {9, "Storage Device"},
+ {10, "Host Computer"},
+ {11, "Storage Subsystem"},
+ {12, "Module"},
+ {13, "Software Driver"},
+ {14, "Storage Access Device"},
+ {0, NULL},
+};
+
+static const value_string fc_fcs_rjt_code_val[] = {
+ {0x00, "No Additional Explanation"},
+ {0x01, "Invalid Name_Identifier for Interconnect Element or Port"},
+ {0x10, "Interconnect Element List Not Available"},
+ {0x11, "Interconnect Element Type Not Available"},
+ {0x12, "Domain ID Not Available"},
+ {0x13, "Mgmt. ID Not Available"},
+ {0x14, "Fabric Name Not Available"},
+ {0x15, "Interconnect Element Logical Name Not Available"},
+ {0x16, "Mgmt. Address Not Available"},
+ {0x17, "Interconnect Element Information List Not Available"},
+ {0x30, "Port List Not Available"},
+ {0x31, "Port Type Not Available"},
+ {0x32, "Physical Port Number Not Available"},
+ {0x34, "Attached Port Name List Not Available"},
+ {0x36, "Port State Not Available"},
+ {0x50, "Unable to Register Interconnect Element Logical Name"},
+ {0x60, "Platform Name Does Not Exist"},
+ {0x61, "Platform Name Already Exists"},
+ {0x62, "Platform Node Name Does Not Exist"},
+ {0x63, "Platform Node Name Already Exists"},
+ {0, NULL},
+};
+
+static const true_false_string fc_fcs_portflags_tfs = {
+ "RTIN ELS Supported",
+ "RTIN ELS Not Supported",
+};
+
+static const value_string fc_fcs_fcsmask_val[] = {
+ {1, "Basic Configuration Service"},
+ {2, "Platform Configuration Service"},
+ {3, "Basic+Platform Configuration Service"},
+ {4, "Topology Discovery Configuration Service"},
+ {5, "Basic+Topology Discovery Configuration Service"},
+ {6, "Platform+Topology Discovery Configuration Service"},
+ {7, "Basic+Platform+Topology Discovery Configuration Service"},
+ {0, NULL},
+};
+
+static const value_string fc_fcs_unsmask_val[] = {
+ {1, "Basic Unzoned Name Service"},
+ {0, NULL},
+};
+
+#endif
diff --git a/epan/dissectors/packet-fcfzs.c b/epan/dissectors/packet-fcfzs.c
new file mode 100644
index 0000000000..6a3154d81f
--- /dev/null
+++ b/epan/dissectors/packet-fcfzs.c
@@ -0,0 +1,924 @@
+/* packet-fcfzs.c
+ * Routines for FC Fabric Zone Server
+ * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fcct.h"
+#include "packet-fcfzs.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_fcfzs = -1;
+static int hf_fcfzs_opcode = -1;
+static int hf_fcfzs_gzc_flags = -1;
+static int hf_fcfzs_gzc_vendor = -1;
+static int hf_fcfzs_zone_state = -1;
+static int hf_fcfzs_gest_vendor = -1;
+static int hf_fcfzs_numzoneattrs = -1;
+static int hf_fcfzs_zonesetnmlen = -1;
+static int hf_fcfzs_zonesetname = -1;
+static int hf_fcfzs_numzones = -1;
+static int hf_fcfzs_numzonesetattrs = -1;
+static int hf_fcfzs_zonenmlen = -1;
+static int hf_fcfzs_zonename = -1;
+static int hf_fcfzs_nummbrs = -1;
+static int hf_fcfzs_nummbrentries = -1;
+static int hf_fcfzs_mbrid = -1;
+static int hf_fcfzs_mbridlen = -1;
+static int hf_fcfzs_mbrtype = -1;
+static int hf_fcfzs_reason = -1;
+static int hf_fcfzs_rjtdetail = -1;
+static int hf_fcfzs_rjtvendor = -1;
+static int hf_fcfzs_maxres_size = -1;
+static int hf_fcfzs_mbrid_lun = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_fcfzs = -1;
+
+typedef struct _fcfzs_conv_key {
+ guint32 conv_idx;
+} fcfzs_conv_key_t;
+
+typedef struct _fcfzs_conv_data {
+ guint32 opcode;
+} fcfzs_conv_data_t;
+
+GHashTable *fcfzs_req_hash = NULL;
+GMemChunk *fcfzs_req_keys = NULL;
+GMemChunk *fcfzs_req_vals = NULL;
+guint32 fcfzs_init_count = 25;
+
+static dissector_handle_t data_handle;
+
+/*
+ * Hash Functions
+ */
+static gint
+fcfzs_equal(gconstpointer v, gconstpointer w)
+{
+ fcfzs_conv_key_t *v1 = (fcfzs_conv_key_t *)v;
+ fcfzs_conv_key_t *v2 = (fcfzs_conv_key_t *)w;
+
+ return (v1->conv_idx == v2->conv_idx);
+}
+
+static guint
+fcfzs_hash (gconstpointer v)
+{
+ fcfzs_conv_key_t *key = (fcfzs_conv_key_t *)v;
+ guint val;
+
+ val = key->conv_idx;
+
+ return val;
+}
+
+/*
+ * Protocol initialization
+ */
+static void
+fcfzs_init_protocol(void)
+{
+ if (fcfzs_req_keys)
+ g_mem_chunk_destroy (fcfzs_req_keys);
+ if (fcfzs_req_vals)
+ g_mem_chunk_destroy (fcfzs_req_vals);
+ if (fcfzs_req_hash)
+ g_hash_table_destroy (fcfzs_req_hash);
+
+ fcfzs_req_hash = g_hash_table_new (fcfzs_hash, fcfzs_equal);
+ fcfzs_req_keys = g_mem_chunk_new ("fcfzs_req_keys",
+ sizeof(fcfzs_conv_key_t),
+ fcfzs_init_count *
+ sizeof(fcfzs_conv_key_t),
+ G_ALLOC_AND_FREE);
+ fcfzs_req_vals = g_mem_chunk_new ("fcfzs_req_vals",
+ sizeof(fcfzs_conv_data_t),
+ fcfzs_init_count *
+ sizeof(fcfzs_conv_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_fcfzs_zoneset (tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ int numzones, nummbrs, i, j, len;
+
+ /* The zoneset structure has the following format */
+ /* zoneset name (len[not including pad], name, pad),
+ * number of zones,
+ * for each zone,
+ * Zone name (len[not including pad], name, pad), num zone mbrs
+ * for each zone mbr,
+ * zone mbr id type, zone mbr id (len, name, pad)
+ */
+ if (tree) {
+
+ /* Zoneset Name */
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetnmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetname, tvb, offset+4,
+ len, 0);
+ offset += 4 + len + (4-(len % 4));
+
+
+ /* Number of zones */
+ numzones = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_numzones, tvb, offset, 4, 0);
+ offset += 4;
+
+ /* For each zone... */
+ for (i = 0; i < numzones; i++) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonenmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonename, tvb, offset+4,
+ len, 0);
+ offset += 4 + len + (4-(len % 4));
+
+ nummbrs = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_nummbrentries, tvb, offset,
+ 4, 0);
+
+ offset += 4;
+ for (j = 0; j < nummbrs; j++) {
+ proto_tree_add_item (tree, hf_fcfzs_mbrtype, tvb, offset, 1, 0);
+
+ switch (tvb_get_guint8 (tvb, offset)) {
+ case FC_FZS_ZONEMBR_PWWN:
+ case FC_FZS_ZONEMBR_NWWN:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 8)));
+ break;
+ case FC_FZS_ZONEMBR_DP:
+ proto_tree_add_string_format (tree,
+ hf_fcfzs_mbrid,
+ tvb, offset+4, 3, " ",
+ "0x%x",
+ tvb_get_ntoh24 (tvb,
+ offset+4));
+ break;
+ case FC_FZS_ZONEMBR_FCID:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 4,
+ fc_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 3)));
+ break;
+ case FC_FZS_ZONEMBR_PWWN_LUN:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 8)));
+ proto_tree_add_item (tree, hf_fcfzs_mbrid_lun, tvb,
+ offset+8, 8, 0);
+ break;
+ case FC_FZS_ZONEMBR_DP_LUN:
+ proto_tree_add_string_format (tree,
+ hf_fcfzs_mbrid,
+ tvb, offset+4, 3, " ",
+ "0x%x",
+ tvb_get_ntoh24 (tvb,
+ offset+4));
+ proto_tree_add_item (tree, hf_fcfzs_mbrid_lun, tvb,
+ offset+4, 8, 0);
+ break;
+ case FC_FZS_ZONEMBR_FCID_LUN:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 4,
+ fc_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 3)));
+ proto_tree_add_item (tree, hf_fcfzs_mbrid_lun, tvb,
+ offset+4, 8, 0);
+ break;
+ default:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 8,
+ "Unknown member type format");
+ }
+ offset += 12;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfzs_gzc (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ guint8 flags;
+ gchar str[128];
+ int offset = 16; /* past the fc_ct header */
+ int stroff = 0;
+
+ if (tree) {
+ if (!isreq) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ /* Disect the flags field */
+ str[0] = '\0';
+ if (flags & 0x80) {
+ strcpy (str, "Hard Zones, ");
+ stroff += 12;
+ }
+
+ if (flags & 0x40) {
+ strcpy (&str[stroff], "Soft Zones Supported, ");
+ stroff += 22;
+ }
+
+ if (flags & 0x01) {
+ strcpy (&str[stroff], "ZoneSet Database Available");
+ stroff += 26;
+ }
+
+ proto_tree_add_uint_format (tree, hf_fcfzs_gzc_flags, tvb, offset,
+ 1, flags, "Capabilities: 0x%x (%s)",
+ flags, str);
+ proto_tree_add_item (tree, hf_fcfzs_gzc_vendor, tvb, offset+4, 4, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfzs_gest (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ guint8 flags;
+ gchar str[128];
+ int offset = 16; /* past the fc_ct header */
+ int stroff = 0;
+
+ if (tree) {
+ if (!isreq) {
+ flags = tvb_get_guint8 (tvb, offset);
+ str[0] = '\0';
+
+ /* dissect the flags field */
+ if (flags & 0x80) {
+ strcpy (str, "Soft Zone Set Enforced, ");
+ stroff += 24;
+ }
+
+ if (flags & 0x40) {
+ strcpy (str, "Hard Zone Set Enforced");
+ stroff += 24;
+ }
+
+ proto_tree_add_uint_format (tree, hf_fcfzs_zone_state, tvb, offset,
+ 1, flags, "Zone State: 0x%x (%s)",
+ flags, str);
+ proto_tree_add_item (tree, hf_fcfzs_gest_vendor, tvb, offset+4, 4, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfzs_gzsn (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int numrec, i, len;
+ int offset = 16; /* past the fc_ct header */
+
+ if (tree) {
+ if (!isreq) {
+ numrec = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_item (tree, hf_fcfzs_numzonesetattrs, tvb, offset,
+ 4, 0);
+
+ offset += 4;
+ for (i = 0; i < numrec; i++) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetnmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetname, tvb, offset+1,
+ len, 0);
+ offset += len + 1 + (len % 4);
+ proto_tree_add_item (tree, hf_fcfzs_numzones, tvb, offset,
+ 4, 0);
+ offset += 4;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfzs_gzd (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int numrec, i, len;
+ int offset = 16; /* past the fc_ct header */
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetnmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetname, tvb, offset+1,
+ len, 0);
+ }
+ else {
+ numrec = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_item (tree, hf_fcfzs_numzoneattrs, tvb, offset,
+ 4, 0);
+
+ offset += 4;
+ for (i = 0; i < numrec; i++) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonenmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonename, tvb, offset+1,
+ len, 0);
+ offset += len + 1 + (len % 4);
+ proto_tree_add_item (tree, hf_fcfzs_nummbrs, tvb, offset,
+ 4, 0);
+ offset += 4;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfzs_gzm (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int numrec, i, len;
+ int offset = 16; /* past the fc_ct header */
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonenmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonename, tvb, offset+1,
+ len, 0);
+ }
+ else {
+ numrec = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_item (tree, hf_fcfzs_nummbrentries, tvb, offset,
+ 4, 0);
+ offset += 4;
+ for (i = 0; i < numrec; i++) {
+ proto_tree_add_item (tree, hf_fcfzs_mbrtype, tvb, offset, 1, 0);
+ switch (tvb_get_guint8 (tvb, offset)) {
+ case FC_FZS_ZONEMBR_PWWN:
+ case FC_FZS_ZONEMBR_NWWN:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 8)));
+ break;
+ case FC_FZS_ZONEMBR_DP:
+ proto_tree_add_string_format (tree,
+ hf_fcfzs_mbrid,
+ tvb, offset+4, 3, " ",
+ "0x%x",
+ tvb_get_ntoh24 (tvb,
+ offset+4));
+ break;
+ case FC_FZS_ZONEMBR_FCID:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 4,
+ fc_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 3)));
+ break;
+ default:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 8,
+ "Unknown member type format");
+ }
+ offset += 12;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfzs_gazs (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (tree) {
+ if (!isreq) {
+ dissect_fcfzs_zoneset (tvb, tree, offset);
+ }
+ }
+}
+
+static void
+dissect_fcfzs_gzs (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetnmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetname, tvb, offset+4,
+ len, 0);
+ }
+ else {
+ dissect_fcfzs_zoneset (tvb, tree, offset);
+ }
+ }
+}
+
+static void
+dissect_fcfzs_adzs (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (tree) {
+ if (isreq) {
+ dissect_fcfzs_zoneset (tvb, tree, offset);
+ }
+ }
+}
+
+static void
+dissect_fcfzs_azsd (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+
+ if (tree) {
+ if (isreq) {
+ dissect_fcfzs_zoneset (tvb, tree, offset);
+ }
+ }
+}
+
+static void
+dissect_fcfzs_arzs (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetnmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetname, tvb, offset+4,
+ len, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfzs_dzs (tvbuff_t *tvb _U_, proto_tree *tree _U_, guint8 isreq _U_)
+{
+ /* Both req & successful response contain just the FC_CT header */
+ return;
+}
+
+static void
+dissect_fcfzs_arzm (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int numrec, i, len, plen;
+ int offset = 16; /* past the fc_ct header */
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonenmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonename, tvb, offset+1,
+ len, 0);
+
+ len += (len % 4);
+ plen = tvb_length (tvb) - offset - len;
+
+ numrec = plen/12; /* each mbr rec is 12 bytes long */
+
+ offset += len;
+ for (i = 0; i < numrec; i++) {
+ proto_tree_add_item (tree, hf_fcfzs_mbrtype, tvb, offset, 1, 0);
+ switch (tvb_get_guint8 (tvb, offset)) {
+ case FC_FZS_ZONEMBR_PWWN:
+ case FC_FZS_ZONEMBR_NWWN:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 8)));
+ break;
+ case FC_FZS_ZONEMBR_DP:
+ proto_tree_add_string_format (tree,
+ hf_fcfzs_mbrid,
+ tvb, offset+4, 3, " ",
+ "0x%x",
+ tvb_get_ntoh24 (tvb,
+ offset+4));
+ break;
+ case FC_FZS_ZONEMBR_FCID:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 4,
+ fc_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 3)));
+ break;
+ default:
+ proto_tree_add_string (tree, hf_fcfzs_mbrid, tvb,
+ offset+4, 8,
+ "Unknown member type format");
+ }
+ offset += 12;
+ }
+ }
+ }
+}
+
+static void
+dissect_fcfzs_arzd (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
+{
+ int offset = 16; /* past the fc_ct header */
+ int len;
+
+ if (tree) {
+ if (isreq) {
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetnmlen, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonesetname, tvb, offset+4,
+ len, 0);
+ len += (len % 4);
+ offset += len;
+
+ len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item (tree, hf_fcfzs_zonenmlen, tvb, offset, 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_zonename, tvb, offset+4,
+ len, 0);
+ }
+ }
+}
+
+static void
+dissect_fcfzs_rjt (tvbuff_t *tvb, proto_tree *tree)
+{
+ int offset = 0;
+
+ if (tree) {
+ proto_tree_add_item (tree, hf_fcfzs_reason, tvb, offset+13, 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_rjtdetail, tvb, offset+14, 1, 0);
+ proto_tree_add_item (tree, hf_fcfzs_rjtvendor, tvb, offset+15, 1, 0);
+ }
+}
+
+static void
+dissect_fcfzs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *fcfzs_tree = NULL;
+ int offset = 0;
+ fc_ct_preamble cthdr;
+ int opcode,
+ failed_opcode = 0;
+ conversation_t *conversation;
+ fcfzs_conv_data_t *cdata;
+ fcfzs_conv_key_t ckey, *req_key;
+ guint8 isreq = 1;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Zone Server");
+
+
+ tvb_memcpy (tvb, (guint8 *)&cthdr, offset, FCCT_PRMBL_SIZE);
+ cthdr.revision = tvb_get_guint8 (tvb, offset+1);
+ cthdr.in_id = tvb_get_ntoh24 (tvb, offset);
+ cthdr.opcode = ntohs (cthdr.opcode);
+ opcode = cthdr.opcode;
+ cthdr.maxres_size = ntohs (cthdr.maxres_size);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcfzs, tvb, 0,
+ tvb_length (tvb),
+ "Zone Server");
+ fcfzs_tree = proto_item_add_subtree (ti, ett_fcfzs);
+ proto_tree_add_item (fcfzs_tree, hf_fcfzs_opcode, tvb, offset+8, 2, 0);
+ proto_tree_add_item (fcfzs_tree, hf_fcfzs_maxres_size, tvb, offset+10,
+ 2, 0);
+ }
+
+ if ((opcode != FCCT_MSG_ACC) && (opcode != FCCT_MSG_RJT)) {
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ if (!conversation) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ }
+
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcfzs_conv_data_t *)g_hash_table_lookup (fcfzs_req_hash,
+ &ckey);
+ if (cdata) {
+ /* Since we never free the memory used by an exchange, this maybe a
+ * case of another request using the same exchange as a previous
+ * req.
+ */
+ cdata->opcode = opcode;
+ }
+ else {
+ req_key = g_mem_chunk_alloc (fcfzs_req_keys);
+ req_key->conv_idx = conversation->index;
+
+ cdata = g_mem_chunk_alloc (fcfzs_req_vals);
+ cdata->opcode = opcode;
+
+ g_hash_table_insert (fcfzs_req_hash, req_key, cdata);
+ }
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO, val_to_str (opcode, fc_fzs_opcode_val,
+ "0x%x"));
+ }
+ }
+ else {
+ /* Opcode is ACC or RJT */
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ isreq = 0;
+ if (!conversation) {
+ if (tree && (opcode == FCCT_MSG_ACC)) {
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO,
+ val_to_str (opcode, fc_fzs_opcode_val,
+ "0x%x"));
+ }
+ /* No record of what this accept is for. Can't decode */
+ proto_tree_add_text (fcfzs_tree, tvb, 0, tvb_length (tvb),
+ "No record of Exchg. Unable to decode MSG_ACC");
+ return;
+ }
+ }
+ else {
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcfzs_conv_data_t *)g_hash_table_lookup (fcfzs_req_hash, &ckey);
+
+ if (cdata != NULL) {
+ if (opcode == FCCT_MSG_ACC)
+ opcode = cdata->opcode;
+ else
+ failed_opcode = cdata->opcode;
+ }
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if (opcode != FCCT_MSG_RJT) {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "MSG_ACC (%s)",
+ val_to_str (opcode,
+ fc_fzs_opcode_val, "0x%x"));
+ }
+ else {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "MSG_RJT (%s)",
+ val_to_str (failed_opcode,
+ fc_fzs_opcode_val, "0x%x"));
+ }
+ }
+
+ if (tree) {
+ if ((cdata == NULL) && (opcode != FCCT_MSG_RJT)) {
+ /* No record of what this accept is for. Can't decode */
+ proto_tree_add_text (fcfzs_tree, tvb, 0, tvb_length (tvb),
+ "No record of Exchg. Unable to decode MSG_ACC/RJT");
+ return;
+ }
+ }
+ }
+ }
+
+ switch (opcode) {
+ case FCCT_MSG_RJT:
+ dissect_fcfzs_rjt (tvb, fcfzs_tree);
+ break;
+ case FC_FZS_GZC:
+ dissect_fcfzs_gzc (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_GEST:
+ dissect_fcfzs_gest (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_GZSN:
+ dissect_fcfzs_gzsn (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_GZD:
+ dissect_fcfzs_gzd (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_GZM:
+ dissect_fcfzs_gzm (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_GAZS:
+ dissect_fcfzs_gazs (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_GZS:
+ dissect_fcfzs_gzs (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_ADZS:
+ dissect_fcfzs_adzs (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_AZSD:
+ dissect_fcfzs_azsd (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_AZS:
+ dissect_fcfzs_arzs (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_DZS:
+ dissect_fcfzs_dzs (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_AZM:
+ dissect_fcfzs_arzm (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_AZD:
+ dissect_fcfzs_arzd (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_RZM:
+ dissect_fcfzs_arzm (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_RZD:
+ dissect_fcfzs_arzd (tvb, fcfzs_tree, isreq);
+ break;
+ case FC_FZS_RZS:
+ dissect_fcfzs_arzs (tvb, fcfzs_tree, isreq);
+ break;
+ default:
+ call_dissector (data_handle, tvb, pinfo, tree);
+ break;
+ }
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_fcfzs(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_fcfzs_opcode,
+ {"Opcode", "fcfzs.opcode", FT_UINT16, BASE_HEX,
+ VALS (fc_fzs_opcode_val), 0x0, "", HFILL}},
+ { &hf_fcfzs_gzc_flags,
+ {"Capabilities", "fcfzs.gzc.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcfzs_gzc_vendor,
+ {"Vendor Specific Flags", "fcfzs.gzc.vendor", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_zone_state,
+ {"Zone State", "fcfzs.zone.state", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcfzs_gest_vendor,
+ {"Vendor Specific State", "fcfzs.gest.vendor", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_numzoneattrs,
+ {"Number of Zone Attribute Entries", "fcfzs.zone.numattrs",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_zonesetnmlen,
+ {"Zone Set Name Length", "fcfzs.zoneset.namelen", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_zonesetname,
+ {"Zone Set Name", "fcfzs.zoneset.name", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcfzs_numzones,
+ {"Number of Zones", "fcfzs.zoneset.numzones", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_numzonesetattrs,
+ {"Number of Zone Set Attribute Entries", "fcfzs.zoneset.numattrs",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_zonenmlen,
+ {"Zone Name Length", "fcfzs.zone.namelen", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcfzs_zonename,
+ {"Zone Name", "fcfzs.zone.name", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcfzs_nummbrs,
+ {"Number of Zone Members", "fcfzs.zone.nummbrs", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_nummbrentries,
+ {"Number of Zone Member Attribute Entries", "fcfzs.zonembr.numattrs",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_mbrtype,
+ {"Zone Member Identifier Type", "fcfzs.zonembr.idtype", FT_UINT8,
+ BASE_HEX, VALS (fc_fzs_zonembr_type_val), 0x0, "", HFILL}},
+ { &hf_fcfzs_mbridlen,
+ {"Zone Member Identifier Length", "fcfzs.zonembr.idlen", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_mbrid,
+ {"Zone Member Identifier", "fcfzs.zone.mbrid", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_reason,
+ {"Reason Code", "fcfzs.reason", FT_UINT8, BASE_HEX,
+ VALS (fc_ct_rjt_code_vals), 0x0, "", HFILL}},
+ { &hf_fcfzs_rjtdetail,
+ {"Reason Code Explanation", "fcfzs.rjtdetail", FT_UINT8, BASE_HEX,
+ VALS (fc_fzs_rjt_code_val), 0x0, "", HFILL}},
+ { &hf_fcfzs_rjtvendor,
+ {"Vendor Specific Reason", "fcfzs.rjtvendor", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_maxres_size,
+ {"Maximum/Residual Size", "fcfzs.maxres_size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcfzs_mbrid_lun,
+ {"LUN", "fcfzs.zone.lun", FT_BYTES, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fcfzs,
+ };
+
+ /* Register the protocol name and description */
+ proto_fcfzs = proto_register_protocol("Fibre Channel Fabric Zone Server", "FC FZS", "FZS");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fcfzs, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine (&fcfzs_init_protocol);
+
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fcfzs (void)
+{
+ dissector_handle_t fzs_handle;
+
+ fzs_handle = create_dissector_handle (dissect_fcfzs, proto_fcfzs);
+ dissector_add("fcct.server", FCCT_GSRVR_FZS, fzs_handle);
+
+ data_handle = find_dissector ("data");
+}
+
+
diff --git a/epan/dissectors/packet-fcfzs.h b/epan/dissectors/packet-fcfzs.h
new file mode 100644
index 0000000000..1d8bb82c13
--- /dev/null
+++ b/epan/dissectors/packet-fcfzs.h
@@ -0,0 +1,121 @@
+/* packet-fcfzs.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCFZS_H_
+#define __PACKET_FCFZS_H_
+
+/* Opcode definitions */
+#define FC_FZS_GZC 0x100
+#define FC_FZS_GEST 0x111
+#define FC_FZS_GZSN 0x112
+#define FC_FZS_GZD 0x113
+#define FC_FZS_GZM 0x114
+#define FC_FZS_GAZS 0x115
+#define FC_FZS_GZS 0x116
+#define FC_FZS_ADZS 0x200
+#define FC_FZS_AZSD 0x201
+#define FC_FZS_AZS 0x202
+#define FC_FZS_DZS 0x203
+#define FC_FZS_AZM 0x204
+#define FC_FZS_AZD 0x205
+#define FC_FZS_RZM 0x300
+#define FC_FZS_RZD 0x301
+#define FC_FZS_RZS 0x302
+
+static const value_string fc_fzs_opcode_val[] = {
+ {FC_FZS_GZC , "Get Capabilities"},
+ {FC_FZS_GEST , "Get Enforcement State"},
+ {FC_FZS_GZSN , "Get Zone Set List"},
+ {FC_FZS_GZD , "Get Zone List"},
+ {FC_FZS_GZM , "Get Zone Member List"},
+ {FC_FZS_GAZS , "Get Active Zone Set"},
+ {FC_FZS_GZS , "Get Zone Set"},
+ {FC_FZS_ADZS , "Add Zone Set"},
+ {FC_FZS_AZSD , "Activate Zone Set Direct"},
+ {FC_FZS_AZS , "Activate Zone Set"},
+ {FC_FZS_DZS , "Deactivate Zone Set"},
+ {FC_FZS_AZM , "Add Zone Members"},
+ {FC_FZS_AZD , "Add Zone"},
+ {FC_FZS_RZM , "Remove Zone Members"},
+ {FC_FZS_RZD , "Remove Zone"},
+ {FC_FZS_RZS , "Remove Zone Set"},
+ {FCCT_MSG_ACC , "MSG_ACC"},
+ {FCCT_MSG_RJT , "MSG_RJT"},
+ {0, NULL},
+};
+
+/* Reason code explanantions */
+#define FC_FZS_RJT_NODETAIL 0x0
+#define FC_FZS_RJT_ZONENOTSUPPORTED 0x1
+#define FC_FZS_RJT_ZSNUNKNOWN 0x10
+#define FC_FZS_RJT_NZSACTIVE 0x11
+#define FC_FZS_RJT_ZONEUNKNOWN 0x12
+#define FC_FZS_RJT_ZONESTATEUNKNOWN 0x13
+#define FC_FZS_RJT_INVLDPLEN 0x14
+#define FC_FZS_RJT_ZSTOOLARGE 0x15
+#define FC_FZS_RJT_DZSFAIL 0x16
+#define FC_FZS_RJT_NOTSUPPORTED 0x17
+#define FC_FZS_RJT_CAPNOTSUPPORTED 0x18
+#define FC_FZS_RJT_ZMIDTYPEUNKNOWN 0x19
+#define FC_FZS_RJT_INVLDZSDEF 0x1A
+
+static const value_string fc_fzs_rjt_code_val[] = {
+ {FC_FZS_RJT_NODETAIL , "No Additional Explanantion"},
+ {FC_FZS_RJT_ZONENOTSUPPORTED , "Zones Not Supported"},
+ {FC_FZS_RJT_ZSNUNKNOWN , "Zone Set Name Unknown"},
+ {FC_FZS_RJT_NZSACTIVE , "No Zone Set Active"},
+ {FC_FZS_RJT_ZONEUNKNOWN , "Zone Name Unknown"},
+ {FC_FZS_RJT_ZONESTATEUNKNOWN , "Zone State Unknown"},
+ {FC_FZS_RJT_INVLDPLEN , "Incorrect Payload Length"},
+ {FC_FZS_RJT_ZSTOOLARGE , "Zone Set to be Activated Too Large"},
+ {FC_FZS_RJT_DZSFAIL , "Deactive Zone Set Failed"},
+ {FC_FZS_RJT_NOTSUPPORTED , "Request Not Supported"},
+ {FC_FZS_RJT_CAPNOTSUPPORTED , "Capability Not Supported"},
+ {FC_FZS_RJT_ZMIDTYPEUNKNOWN , "Zone Member Identifier Type Not Supported"},
+ {FC_FZS_RJT_INVLDZSDEF , "Invalid Zone Set Definition"},
+ {0, NULL},
+};
+
+/* Zone Member Identifier Types */
+
+#define FC_FZS_ZONEMBR_PWWN 1
+#define FC_FZS_ZONEMBR_DP 2
+#define FC_FZS_ZONEMBR_FCID 3
+#define FC_FZS_ZONEMBR_NWWN 4
+#define FC_FZS_ZONEMBR_PWWN_LUN 0xE1
+#define FC_FZS_ZONEMBR_DP_LUN 0xE2
+#define FC_FZS_ZONEMBR_FCID_LUN 0xE3
+
+static const value_string fc_fzs_zonembr_type_val[] = {
+ {0, "Reserved"},
+ {FC_FZS_ZONEMBR_PWWN, "N_Port WWN"},
+ {FC_FZS_ZONEMBR_DP, "Domain/Physical Port (0x00ddpppp)"},
+ {FC_FZS_ZONEMBR_FCID, "FC Address"},
+ {FC_FZS_ZONEMBR_NWWN, "Node WWN"},
+ {FC_FZS_ZONEMBR_PWWN_LUN, "N_Port WWN+LUN"},
+ {FC_FZS_ZONEMBR_DP_LUN, "Domain/Physical Port+LUN"},
+ {FC_FZS_ZONEMBR_FCID_LUN, "FC Address+LUN"},
+ {0, NULL},
+};
+
+#endif
diff --git a/epan/dissectors/packet-fcip.c b/epan/dissectors/packet-fcip.c
new file mode 100644
index 0000000000..194ff1c82b
--- /dev/null
+++ b/epan/dissectors/packet-fcip.c
@@ -0,0 +1,680 @@
+/* packet-fcip.c
+ * Routines for FCIP dissection
+ * Copyright 2001, Dinesh G Dutt (ddutt@cisco.com)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "prefs.h"
+
+/*
+ * See:
+ *
+ * draft-ietf-ips-fcovertcpip-12
+ *
+ * draft-ietf-ips-fcencapsulation-08
+ */
+
+#define FCIP_ENCAP_HEADER_LEN 28
+#define FCIP_MIN_HEADER_LEN 16 /* upto frame len field */
+#define FCIP_ENCAP_PROTO_VER 0xFEFE0101
+#define FCIP_IS_SF(pflags) ((pflags & 0x1) == 0x1)
+#define FCIP_IS_CH(pflags) ((pflags & 0x80) == 0x80)
+
+typedef enum {
+ FCIP_EOFn = 0x41,
+ FCIP_EOFt = 0x42,
+ FCIP_EOFrt = 0x44,
+ FCIP_EOFdt = 0x46,
+ FCIP_EOFni = 0x49,
+ FCIP_EOFdti = 0x4E,
+ FCIP_EOFrti = 0x4F,
+ FCIP_EOFa = 0x50
+} fcip_eof_t;
+
+typedef enum {
+ FCIP_SOFf = 0x28,
+ FCIP_SOFi4 = 0x29,
+ FCIP_SOFi2 = 0x2D,
+ FCIP_SOFi3 = 0x2E,
+ FCIP_SOFn4 = 0x31,
+ FCIP_SOFn2 = 0x35,
+ FCIP_SOFn3 = 0x36,
+ FCIP_SOFc4 = 0x39
+} fcip_sof_t;
+
+typedef enum {
+ FCENCAP_PROTO_FCIP = 1,
+ FCENCAP_PROTO_iFCP = 2
+} fcencap_proto_t;
+
+static const value_string fcip_eof_vals[] = {
+ {FCIP_EOFn, "EOFn" },
+ {FCIP_EOFt, "EOFt" },
+ {FCIP_EOFrt, "EOFrt" },
+ {FCIP_EOFdt, "EOFdt" },
+ {FCIP_EOFni, "EOFni" },
+ {FCIP_EOFdti, "EOFdti" },
+ {FCIP_EOFrti, "EOFrti" },
+ {FCIP_EOFa, "EOFa" },
+ {0, NULL},
+};
+
+static const value_string fcip_sof_vals[] = {
+ {FCIP_SOFf, "SOFf" },
+ {FCIP_SOFi4, "SOFi4" },
+ {FCIP_SOFi2, "SOFi2" },
+ {FCIP_SOFi3, "SOFi3" },
+ {FCIP_SOFn4, "SOFn4" },
+ {FCIP_SOFn2, "SOFn2" },
+ {FCIP_SOFn3, "SOFn3" },
+ {FCIP_SOFc4, "SOFc4" },
+ {0, NULL},
+};
+
+static const value_string fcencap_proto_vals[] = {
+ {FCENCAP_PROTO_FCIP, "FCIP"},
+ {FCENCAP_PROTO_iFCP, "iFCP"},
+ {0, NULL},
+};
+
+static guint fcip_header_2_bytes[2] = {FCIP_ENCAP_PROTO_VER,
+ FCIP_ENCAP_PROTO_VER};
+
+static int proto_fcip = -1;
+
+static int hf_fcip_protocol = -1;
+static int hf_fcip_protocol_c = -1;
+static int hf_fcip_version = -1;
+static int hf_fcip_version_c = -1;
+static int hf_fcip_encap_word1 = -1;
+static int hf_fcip_flags = -1;
+static int hf_fcip_flags_c = -1;
+static int hf_fcip_framelen = -1;
+static int hf_fcip_framelen_c = -1;
+static int hf_fcip_tsec = -1;
+static int hf_fcip_tusec = -1;
+static int hf_fcip_encap_crc = -1;
+static int hf_fcip_sof = -1;
+static int hf_fcip_sof_c = -1;
+static int hf_fcip_eof = -1;
+static int hf_fcip_eof_c = -1;
+static int hf_fcip_pflags_changed = -1;
+static int hf_fcip_pflags_special = -1;
+static int hf_fcip_pflags_c = -1;
+static int hf_fcip_src_wwn = -1;
+static int hf_fcip_dst_wwn = -1;
+static int hf_fcip_conn_code = -1;
+static int hf_fcip_katov = -1;
+static int hf_fcip_src_entity_id = -1;
+static int hf_fcip_conn_nonce = -1;
+static int hf_fcip_conn_flags = -1;
+
+static int ett_fcip = -1;
+
+static guint fcip_port = 3225;
+static gboolean fcip_desegment = TRUE;
+
+static dissector_handle_t data_handle;
+static dissector_handle_t fc_handle;
+
+/* This routine attempts to locate the position of the next header in the
+ * provided segment
+ */
+static guint
+get_next_fcip_header_offset (tvbuff_t *tvb, packet_info *pinfo, gint offset)
+{
+ gint bytes_remaining = tvb_length_remaining (tvb, offset);
+ gint frame_len;
+ guint16 flen, flen1;
+ fcip_eof_t eof, eofc;
+
+ /*
+ * As per the FCIP standard, the following tests must PASS:
+ * 1) Frame Length field validation -- 15 < Frame Length < 545;
+ * 2) Comparison of Frame Length field to its ones complement; and
+ * 3) A valid EOF is found in the word preceding the start of the next
+ * FCIP header as indicated by the Frame Length field, to be tested
+ * as follows:
+ * 1) Bits 24-31 and 16-23 contain identical legal EOF values (the
+ * list of legal EOF values is in the FC Frame Encapsulation
+ * [21]); and
+ * 2) Bits 8-15 and 0-7 contain the ones complement of the EOF
+ * value found in bits 24-31.
+ *
+ * As per the FCIP standard, in addition, at least 3 of the following set
+ * of tests must be performed to identify that we've located the start of
+ * an FCIP frame.
+ * a) Protocol# ones complement field (1 test);
+ * b) Version ones complement field (1 test);
+ * c) Replication of encapsulation word 0 in word 1 (1 test);
+ * d) Reserved field and its ones complement (2 tests);
+ * e) Flags field and its ones complement (2 tests);
+ * f) CRC field is equal to zero (1 test);
+ * g) SOF fields and ones complement fields (4 tests);
+ * h) Format and values of FC header (1 test);
+ * i) CRC of FC Frame (2 tests);
+ * j) FC Frame Encapsulation header information in the next FCIP Frame
+ * (1 test).
+ *
+ * At least 3 of the 16 tests listed above SHALL be performed. Failure
+ * of any of the above tests actually performed SHALL indicate an
+ * encapsulation error and the FC Frame SHALL NOT be forwarded on to
+ * the FC Entity.
+ */
+
+NXT_BYTE: while (bytes_remaining) {
+ if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
+ if(fcip_desegment && pinfo->can_desegment) {
+ /*
+ * This frame doesn't have all of the data for
+ * this message, but we can do reassembly on it.
+ *
+ * Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and
+ * how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = FCIP_ENCAP_HEADER_LEN;
+ return -2;
+ }
+ }
+
+ /* I check that we have a valid header before checking for the frame
+ * length and the other initial tests.
+ */
+
+ /*
+ * Tests a, b and c
+ */
+ if (memcmp ((void *)tvb_get_ptr (tvb, offset, 8),
+ (void *)fcip_header_2_bytes, 8) != 0) {
+ offset++;
+ bytes_remaining--;
+ goto NXT_BYTE;
+ }
+
+ flen = (tvb_get_ntohs (tvb, offset+12)) & 0x03FF;
+ frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;
+
+ if ((flen < 15) || (flen > 545)) {
+ /* Frame length check failed. Skip byte and try again */
+ offset++;
+ bytes_remaining--;
+ goto NXT_BYTE;
+ }
+
+ flen1 = (tvb_get_ntohs (tvb, offset+14)) & 0x03FF;
+
+ if ((flen & 0x03FF) != ((~flen1)&0x03FF)) {
+ /* frame_len and its one's complement are not the same */
+ offset++;
+ bytes_remaining--;
+ goto NXT_BYTE;
+ }
+
+ /* Valid EOF check */
+ if (tvb_bytes_exist (tvb, offset+(frame_len-1)*4, 4)) {
+ eof = (fcip_eof_t)tvb_get_guint8 (tvb, offset+(frame_len-1)*4);
+ eofc = (fcip_eof_t)tvb_get_guint8 (tvb, offset+(frame_len-1)*4+2);
+
+ if ((eof != FCIP_EOFn) && (eof != FCIP_EOFt) && (eof != FCIP_EOFrt)
+ && (eof != FCIP_EOFdt) && (eof != FCIP_EOFni) &&
+ (eof != FCIP_EOFdti) && (eof != FCIP_EOFrti) &&
+ (eof != FCIP_EOFa)) {
+ offset++;
+ bytes_remaining--;
+ goto NXT_BYTE;
+ }
+
+ if ((eof != ~eofc) ||
+ (eof != tvb_get_guint8 (tvb, offset+(frame_len-1)*4+1)) ||
+ (eofc != tvb_get_guint8 (tvb, offset+(frame_len-1)*4+3))) {
+ offset++;
+ bytes_remaining--;
+ goto NXT_BYTE;
+ }
+ }
+
+ /* Test d */
+ if ((tvb_get_guint8 (tvb, offset+9) != 0) ||
+ (tvb_get_guint8 (tvb, offset+11) != 0xFF)) {
+ /* Failed */
+ offset++;
+ bytes_remaining--;
+ goto NXT_BYTE;
+ }
+
+ /* Test e */
+
+ /* Test f */
+ if (tvb_get_ntohl (tvb, offset+24)) {
+ /* Failed */
+ offset++;
+ bytes_remaining--;
+ goto NXT_BYTE;
+ }
+
+ if (bytes_remaining >= (frame_len)) {
+ if (tvb_bytes_exist (tvb, offset+frame_len, 8)) {
+ /* The start of the next header matches what we wish to see */
+ if (memcmp ((void *)tvb_get_ptr (tvb, offset+frame_len, 8),
+ (void *)fcip_header_2_bytes, 8) == 0) {
+ return (offset);
+ }
+ else {
+ offset++;
+ bytes_remaining--;
+ goto NXT_BYTE;
+ }
+ }
+ else {
+ return (offset);
+ }
+ }
+ else {
+ if(fcip_desegment && pinfo->can_desegment) {
+ /*
+ * This frame doesn't have all of the data for
+ * this message, but we can do reassembly on it.
+ *
+ * Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and
+ * how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = frame_len - bytes_remaining;
+ return -2;
+ }
+ else {
+ return (offset);
+ }
+ }
+ }
+
+ return (-1); /* Unable to find FCIP header */
+}
+
+static void
+dissect_fcencap_header (tvbuff_t *tvb, proto_tree *tree, gint offset)
+{
+ guint8 protocol = tvb_get_guint8 (tvb, offset);
+
+ if (tree) {
+ proto_tree_add_uint (tree, hf_fcip_protocol, tvb, offset, 1, protocol);
+ proto_tree_add_item (tree, hf_fcip_version, tvb, offset+1, 1, 0);
+ proto_tree_add_item (tree, hf_fcip_protocol_c, tvb, offset+2, 1, 0);
+ proto_tree_add_item (tree, hf_fcip_version_c, tvb, offset+3, 1, 0);
+
+ if (protocol == FCENCAP_PROTO_FCIP) {
+ proto_tree_add_item (tree, hf_fcip_encap_word1, tvb, offset+4,
+ 4, 0);
+ proto_tree_add_item (tree, hf_fcip_pflags_changed, tvb, offset+8,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcip_pflags_special, tvb, offset+8,
+ 1, 0);
+ proto_tree_add_item (tree, hf_fcip_pflags_c, tvb, offset+10, 1, 0);
+ }
+
+ /* XXX - break out CRCV flag. */
+ proto_tree_add_item (tree, hf_fcip_flags, tvb, offset+12, 1, 0);
+ proto_tree_add_item (tree, hf_fcip_framelen, tvb, offset+12, 2, 0);
+ proto_tree_add_item (tree, hf_fcip_flags_c, tvb, offset+14, 1, 0);
+ proto_tree_add_item (tree, hf_fcip_framelen_c, tvb, offset+14, 2, 0);
+ proto_tree_add_item (tree, hf_fcip_tsec, tvb, offset+16, 4, 0);
+ proto_tree_add_item (tree, hf_fcip_tusec, tvb, offset+20, 4, 0);
+ /* XXX - check CRC if CRCV is set? */
+ proto_tree_add_item (tree, hf_fcip_encap_crc, tvb, offset+24, 4, 0);
+ }
+}
+
+static void
+dissect_fcip_sf (tvbuff_t *tvb, proto_tree *tree, gint offset)
+{
+ if (tree) {
+ proto_tree_add_string (tree, hf_fcip_src_wwn, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ proto_tree_add_bytes (tree, hf_fcip_src_entity_id, tvb, offset+8, 8,
+ tvb_get_ptr (tvb, offset+8, 8));
+ proto_tree_add_bytes (tree, hf_fcip_conn_nonce, tvb, offset+16, 8,
+ tvb_get_ptr (tvb, offset+16, 8));
+ /* XXX - break out these flags */
+ proto_tree_add_item (tree, hf_fcip_conn_flags, tvb, offset+24, 1, 0);
+ proto_tree_add_item (tree, hf_fcip_conn_code, tvb, offset+26, 2, 0);
+ proto_tree_add_string (tree, hf_fcip_dst_wwn, tvb, offset+30, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+30, 8)));
+ proto_tree_add_item (tree, hf_fcip_katov, tvb, offset+38, 4, 0);
+ }
+}
+
+static gboolean
+dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean check_port)
+{
+ gint offset = 0,
+ start = 0,
+ frame_len = 0;
+ gint bytes_remaining = tvb_length_remaining (tvb, offset);
+ guint8 pflags, sof = 0, eof = 0;
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *fcip_tree = NULL;
+ tvbuff_t *next_tvb;
+
+ if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
+ return FALSE;
+ }
+
+ if (check_port &&
+ ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) {
+ return FALSE;
+ }
+
+ while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) {
+ if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) {
+ return FALSE;
+ }
+ else if (offset == -2) {
+ /* We need more data to desegment */
+ return (TRUE);
+ }
+
+ start = offset;
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP");
+
+ frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;
+
+ if (bytes_remaining < frame_len) {
+ if(fcip_desegment && pinfo->can_desegment) {
+ /*
+ * This frame doesn't have all of the data for
+ * this message, but we can do reassembly on it.
+ *
+ * Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and
+ * how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = frame_len - bytes_remaining;
+ return (TRUE);
+ }
+ }
+
+ pflags = tvb_get_guint8 (tvb, start+8);
+
+ if (tree) {
+ if (FCIP_IS_SF (pflags)) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
+ FCIP_ENCAP_HEADER_LEN,
+ "FCIP");
+ }
+ else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) {
+ sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);
+ eof = tvb_get_guint8 (tvb, offset+frame_len - 4);
+
+ ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
+ FCIP_ENCAP_HEADER_LEN,
+ "FCIP (%s/%s)",
+ val_to_str (sof, fcip_sof_vals,
+ "0x%x"),
+ val_to_str (eof, fcip_eof_vals,
+ "0x%x"));
+ }
+ else {
+ sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);
+
+ ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
+ FCIP_ENCAP_HEADER_LEN,
+ "FCIP (%s/%s)",
+ val_to_str (sof, fcip_sof_vals,
+ "0x%x"),
+ "NA");
+ }
+ fcip_tree = proto_item_add_subtree (ti, ett_fcip);
+ /* Dissect the Common FC Encap header */
+ dissect_fcencap_header (tvb, fcip_tree, offset);
+
+ offset += FCIP_ENCAP_HEADER_LEN;
+
+ if (!FCIP_IS_SF (pflags)) {
+ /* print SOF */
+ proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, 0);
+ proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, 0);
+ /* print EOF */
+
+ offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4);
+ if (tvb_bytes_exist (tvb, offset, 4)) {
+ proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, 0);
+ proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, 0);
+ }
+ }
+ }
+
+ /* Call the FC Dissector if this is carrying an FC frame */
+ if (!FCIP_IS_SF(pflags)) {
+ /* Set the SOF/EOF flags in the packet_info header */
+ pinfo->sof_eof = 0;
+
+ if (sof) {
+ if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) {
+ pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
+ }
+ else if (sof == FCIP_SOFf) {
+ pinfo->sof_eof = PINFO_SOF_SOFF;
+ }
+
+ if (eof != FCIP_EOFn) {
+ pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
+ }
+ else if (eof != FCIP_EOFt) {
+ pinfo->sof_eof |= PINFO_EOF_INVALID;
+ }
+ }
+
+ /* Special frame bit is not set */
+ next_tvb = tvb_new_subset (tvb, FCIP_ENCAP_HEADER_LEN+4, -1, -1);
+ if (fc_handle) {
+ call_dissector (fc_handle, next_tvb, pinfo, tree);
+ }
+ else if (data_handle) {
+ call_dissector (data_handle, next_tvb, pinfo, tree);
+ }
+ }
+ else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Special Frame");
+ if (FCIP_IS_CH (pflags)) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "(Changed)");
+ }
+
+ dissect_fcip_sf (tvb, fcip_tree, offset+4);
+ }
+
+ bytes_remaining -= frame_len;
+ }
+
+ return (TRUE);
+}
+
+/* This is called for those sessions where we have explicitely said
+ this to be FCIP using "Decode As..."
+ In this case we will not check the port number for sanity and just
+ do as the user said.
+*/
+static void
+dissect_fcip_handle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_fcip (tvb, pinfo, tree, FALSE);
+}
+
+static gboolean
+dissect_fcip_heur (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return (dissect_fcip (tvb, pinfo, tree, TRUE));
+}
+
+void
+proto_register_fcip (void)
+{
+
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_fcip_protocol,
+ { "Protocol", "fcencap.proto", FT_UINT8, BASE_DEC,
+ VALS(fcencap_proto_vals), 0, "Protocol", HFILL }},
+ { &hf_fcip_protocol_c,
+ {"Protocol (1's Complement)", "fcencap.protoc", FT_UINT8, BASE_DEC, NULL,
+ 0, "Protocol (1's Complement)", HFILL}},
+ { &hf_fcip_version,
+ {"Version", "fcencap.version", FT_UINT8, BASE_DEC, NULL, 0, "",
+ HFILL}},
+ { &hf_fcip_version_c,
+ {"Version (1's Complement)", "fcencap.versionc", FT_UINT8, BASE_DEC,
+ NULL, 0, "", HFILL}},
+ { &hf_fcip_encap_word1,
+ {"FCIP Encapsulation Word1", "fcip.word1", FT_UINT32, BASE_HEX, NULL,
+ 0, "", HFILL}},
+ { &hf_fcip_flags,
+ {"Flags", "fcencap.flags", FT_UINT8, BASE_HEX, NULL, 0xFC, "", HFILL}},
+ { &hf_fcip_flags_c,
+ {"Flags (1's Complement)", "fcencap.flagsc", FT_UINT8, BASE_HEX,
+ NULL, 0xFC, "", HFILL}},
+ { &hf_fcip_framelen,
+ {"Frame Length (in Words)", "fcencap.framelen", FT_UINT16, BASE_DEC,
+ NULL, 0x03FF, "", HFILL}},
+ { &hf_fcip_framelen_c,
+ {"Frame Length (1's Complement)", "fcencap.framelenc", FT_UINT16,
+ BASE_DEC, NULL, 0x03FF, "", HFILL}},
+ { &hf_fcip_tsec,
+ {"Time (secs)", "fcencap.tsec", FT_UINT32, BASE_DEC, NULL, 0, "",
+ HFILL}},
+ { &hf_fcip_tusec,
+ {"Time (fraction)", "fcencap.tusec", FT_UINT32, BASE_DEC, NULL, 0,
+ "", HFILL}},
+ { &hf_fcip_encap_crc,
+ {"CRC", "fcencap.crc", FT_UINT32, BASE_HEX, NULL, 0, "", HFILL}},
+ { &hf_fcip_sof,
+ {"SOF", "fcip.sof", FT_UINT8, BASE_HEX, VALS (&fcip_sof_vals), 0,
+ "", HFILL}},
+ { &hf_fcip_sof_c,
+ {"SOF (1's Complement)", "fcip.sofc", FT_UINT8, BASE_HEX, NULL,
+ 0, "", HFILL}},
+ { &hf_fcip_eof,
+ {"EOF", "fcip.eof", FT_UINT8, BASE_HEX, VALS (&fcip_eof_vals), 0,
+ "", HFILL}},
+ { &hf_fcip_eof_c,
+ {"EOF (1's Complement)", "fcip.eofc", FT_UINT8, BASE_HEX, NULL,
+ 0, "", HFILL}},
+ { &hf_fcip_pflags_changed,
+ {"Changed Flag", "fcip.pflags.ch", FT_BOOLEAN, BASE_DEC, NULL, 0x80,
+ "", HFILL}},
+ { &hf_fcip_pflags_special,
+ {"Special Frame Flag", "fcip.pflags.sf", FT_BOOLEAN, BASE_DEC, NULL,
+ 0x1, "", HFILL}},
+ { &hf_fcip_pflags_c,
+ {"Pflags (1's Complement)", "fcip.pflagsc", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcip_src_wwn,
+ {"Source Fabric WWN", "fcip.srcwwn", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcip_dst_wwn,
+ {"Destination Fabric WWN", "fcip.dstwwn", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcip_src_entity_id,
+ {"FC/FCIP Entity Id", "fcip.srcid", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcip_conn_flags,
+ {"Connection Usage Flags", "fcip.connflags", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_fcip_conn_code,
+ {"Connection Usage Code", "fcip.conncode", FT_UINT16, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcip_katov,
+ {"K_A_TOV", "fcip.katov", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcip_conn_nonce,
+ {"Connection Nonce", "fcip.nonce", FT_BYTES, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_fcip,
+ };
+
+ module_t *fcip_module;
+
+ /* Register the protocol name and description */
+ proto_fcip = proto_register_protocol("FCIP", "FCIP", "fcip");
+
+ /* Required function calls to register the header fields and
+ * subtrees used */
+ proto_register_field_array(proto_fcip, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ fcip_module = prefs_register_protocol(proto_fcip, NULL);
+ prefs_register_bool_preference(fcip_module,
+ "desegment",
+ "Desegment FCIP messages",
+ "When enabled, FCIP messages that span multiple TCP segments are desegmented",
+ &fcip_desegment);
+ prefs_register_uint_preference(fcip_module,
+ "target_port",
+ "Target port",
+ "Port number used for FCIP",
+ 10,
+ &fcip_port);
+}
+
+
+/*
+ * If this dissector uses sub-dissector registration add a
+ * registration routine.
+ */
+
+/*
+ * This format is required because a script is used to find these
+ * routines and create the code that calls these routines.
+ */
+void
+proto_reg_handoff_fcip (void)
+{
+ dissector_handle_t fcip_handle;
+
+ heur_dissector_add("tcp", dissect_fcip_heur, proto_fcip);
+
+ fcip_handle = create_dissector_handle(dissect_fcip_handle, proto_fcip);
+ dissector_add_handle("tcp.port", fcip_handle);
+
+ data_handle = find_dissector("data");
+ fc_handle = find_dissector("fc");
+}
diff --git a/epan/dissectors/packet-fclctl.c b/epan/dissectors/packet-fclctl.c
new file mode 100644
index 0000000000..fbb7ecf298
--- /dev/null
+++ b/epan/dissectors/packet-fclctl.c
@@ -0,0 +1,176 @@
+/* packet-fclctl.c
+ * Routines for FC Link Control Frames
+ * Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fclctl.h"
+
+const value_string fc_lctl_proto_val[] = {
+ {FC_LCTL_ACK1 , "ACK1"},
+ {FC_LCTL_ACK0 , "ACK0"},
+ {FC_LCTL_PRJT , "P_RJT"},
+ {FC_LCTL_FRJT , "F_RJT"},
+ {FC_LCTL_PBSY , "P_BSY"},
+ {FC_LCTL_FBSYL , "F_BSY (Data frame)"},
+ {FC_LCTL_FBSYB , "F_BSY (Link Ctl)"},
+ {FC_LCTL_LCR , "LCR"},
+ {FC_LCTL_NTY , "NTY"},
+ {FC_LCTL_END , "END"},
+ {0, NULL},
+};
+
+static const value_string fc_lctl_fbsy_val[] = {
+ {FC_LCTL_FBSY_FBSY, "Fabric Busy"},
+ {FC_LCTL_FBSY_NBSY, "N_Port Busy"},
+ {0, NULL}
+};
+
+static const value_string fc_lctl_pbsy_acode_val[] = {
+ {FC_LCTL_PBSY_ACODE_SEQBSY, "Sequence Marked Busy"},
+ {FC_LCTL_PBSY_ACODE_C2BSY, "Class 2 Frame Busy"},
+ {0, NULL},
+};
+
+static const value_string fc_lctl_pbsy_rjt_val[] = {
+ {FC_LCTL_PBSY_PORTBSY , "Physical N_Port Busy"},
+ {FC_LCTL_PBSY_RSRCBSY , "N_Port Resource Busy"},
+ {FC_LCTL_PBSY_MCASTBSY, "Partial Multicast Busy"},
+ {FC_LCTL_PBSY_VENDBSY , "Vendor unique Busy"},
+ {0, NULL},
+};
+
+static const value_string fc_lctl_rjt_acode_val[] = {
+ {FC_LCTL_RJT_ACODE_RETRY, "Retryable Error"},
+ {FC_LCTL_RJT_ACODE_NORETRY, "Non-retryable Error"},
+ {0, NULL},
+};
+
+static const value_string fc_lctl_rjt_val[] = {
+ {FC_LCTL_RJT_INVSID , "Invalid S_ID"},
+ {FC_LCTL_RJT_INVDID , "Invalid D_ID"},
+ {FC_LCTL_RJT_NPORT_NOTAVAIL_T , "N_Port Not Avail (Temporary)"},
+ {FC_LCTL_RJT_NPORT_NOTAVAIL_P , "N_Port Not Avail (Permanent)"},
+ {FC_LCTL_RJT_CLASS_NOTSUPP , "Class Not Supported"},
+ {FC_LCTL_RJT_DELIM_USERR , "Delimiter Usage Error"},
+ {FC_LCTL_RJT_TYPE_NOTSUPP , "Type Not Supported"},
+ {FC_LCTL_RJT_INV_LCTL , "Invalid Link Ctl Frame"},
+ {FC_LCTL_RJT_INV_RCTL , "Invalid R_CTL"},
+ {FC_LCTL_RJT_INV_FCTL , "Invalid F_CTL"},
+ {FC_LCTL_RJT_INV_OXID , "Invalid OX_ID"},
+ {FC_LCTL_RJT_INV_RXID , "Invalid RX_ID"},
+ {FC_LCTL_RJT_INV_SEQID , "Invalid SEQID"},
+ {FC_LCTL_RJT_INV_DFCTL , "Invalid DF_CTL"},
+ {FC_LCTL_RJT_INV_SEQCNT , "Invalid SEQCNT"},
+ {FC_LCTL_RJT_INV_PARAM , "Invalid Parameter"},
+ {FC_LCTL_RJT_EXCHG_ERR , "Exchange Error"},
+ {FC_LCTL_RJT_PROTO_ERR , "Protocol Error"},
+ {FC_LCTL_RJT_INV_LEN , "Incorrect Length"},
+ {FC_LCTL_RJT_UNEXP_ACK , "Unexpected ACK"},
+ {FC_LCTL_RJT_CLS_NOTSUPP , "Class Not Supported by Entity at 0xFFFFFE"},
+ {FC_LCTL_RJT_LOGI_REQD , "Login Required"},
+ {FC_LCTL_RJT_TOOMANY_SEQ , "Excessive Sequences Attempted"},
+ {FC_LCTL_RJT_EXCHG_NOTESTD , "Exchange Not Established"},
+ {FC_LCTL_RJT_RSVD , "Reserved"},
+ {FC_LCTL_RJT_FPATH_NOTAVAIL , "Fabric Path Not Available"},
+ {FC_LCTL_RJT_INV_VCID , "Invalid VC_ID"},
+ {FC_LCTL_RJT_INV_CSCTL , "Invalid CS_CTL"},
+ {FC_LCTL_RJT_OORSRC , "Insufficient Resources of VC (Class 4)"},
+ {FC_LCTL_RJT_INV_CLASS , "Invalid Class of Service"},
+ {FC_LCTL_RJT_PRMPT_RJT , "Preemption Request Rejected"},
+ {FC_LCTL_RJT_PRMPT_DIS , "Preemption Not Enabled"},
+ {FC_LCTL_RJT_MCAST_ERR , "Multicast Error"},
+ {FC_LCTL_RJT_MCAST_TERM , "Multicast Error Terminate"},
+ {FC_LCTL_RJT_PRLI_REQD , "PRLI Required"},
+ {FC_LCTL_RJT_VEND_ERR , "Vendor Unique Error"},
+ {0, NULL},
+};
+
+static gchar errstr[64];
+
+gchar *
+fclctl_get_typestr (guint8 linkctl_type, guint8 type)
+{
+ if ((linkctl_type == FC_LCTL_FBSYB) ||
+ (linkctl_type == FC_LCTL_FBSYL)) {
+ return (val_to_str ((type & 0xF0), fc_lctl_fbsy_val, "0x%x"));
+ }
+ else return ("\0");
+}
+
+gchar *
+fclctl_get_paramstr (guint32 linkctl_type, guint32 param)
+{
+ int len;
+
+ errstr[0] = '\0';
+
+ if (linkctl_type == FC_LCTL_PBSY) {
+ strcpy (errstr, val_to_str (((param & 0xFF000000) >> 24),
+ fc_lctl_pbsy_acode_val, "0x%x"));
+ len = strlen (errstr);
+ strcpy (&errstr[len], ", ");
+ len = strlen (errstr);
+ strcpy (&errstr[len],
+ val_to_str (((param & 0x00FF0000) >> 16),
+ fc_lctl_pbsy_rjt_val, "0x%x"));
+ }
+ else if ((linkctl_type == FC_LCTL_FRJT) ||
+ (linkctl_type == FC_LCTL_PRJT)) {
+ strcpy (errstr,
+ val_to_str (((param & 0xFF000000) >> 24),
+ fc_lctl_rjt_acode_val, "0x%x"));
+ len = strlen (errstr);
+ strcpy (&errstr[len], ", ");
+ len = strlen (errstr);
+ strcpy (&errstr[len],
+ val_to_str (((param & 0x00FF0000) >> 16), fc_lctl_rjt_val,
+ "%x"));
+ }
+
+ return (errstr);
+}
diff --git a/epan/dissectors/packet-fclctl.h b/epan/dissectors/packet-fclctl.h
new file mode 100644
index 0000000000..67c8bca908
--- /dev/null
+++ b/epan/dissectors/packet-fclctl.h
@@ -0,0 +1,96 @@
+/* packet-fclctl.h
+ * Fibre Channel Link Control definitions
+ * Copyright 2001 Dinesh G Dutt (ddutt@cisco.com)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCLCTL_H_
+#define __PACKET_FCLCTL_H_
+
+#define FC_LCTL_ACK1 0x00
+#define FC_LCTL_ACK0 0x01
+#define FC_LCTL_PRJT 0x02
+#define FC_LCTL_FRJT 0x03
+#define FC_LCTL_PBSY 0x04
+#define FC_LCTL_FBSYL 0x05
+#define FC_LCTL_FBSYB 0x06
+#define FC_LCTL_LCR 0x07
+#define FC_LCTL_NTY 0x08
+#define FC_LCTL_END 0x09
+
+extern const value_string fc_lctl_proto_val[];
+
+#define FC_LCTL_FBSY_FBSY 0x01
+#define FC_LCTL_FBSY_NBSY 0x03
+
+#define FC_LCTL_PBSY_ACODE_SEQBSY 0x01
+#define FC_LCTL_PBSY_ACODE_C2BSY 0x02
+
+#define FC_LCTL_PBSY_PORTBSY 0x01
+#define FC_LCTL_PBSY_RSRCBSY 0x03
+#define FC_LCTL_PBSY_MCASTBSY 0x07
+#define FC_LCTL_PBSY_VENDBSY 0xFF
+
+#define FC_LCTL_RJT_ACODE_RETRY 0x01
+#define FC_LCTL_RJT_ACODE_NORETRY 0x02
+
+#define FC_LCTL_RJT_INVDID 0x01
+#define FC_LCTL_RJT_INVSID 0x02
+#define FC_LCTL_RJT_NPORT_NOTAVAIL_T 0x03
+#define FC_LCTL_RJT_NPORT_NOTAVAIL_P 0x04
+#define FC_LCTL_RJT_CLASS_NOTSUPP 0x05
+#define FC_LCTL_RJT_DELIM_USERR 0x06
+#define FC_LCTL_RJT_TYPE_NOTSUPP 0x07
+#define FC_LCTL_RJT_INV_LCTL 0x08
+#define FC_LCTL_RJT_INV_RCTL 0x09
+#define FC_LCTL_RJT_INV_FCTL 0x0A
+#define FC_LCTL_RJT_INV_OXID 0x0B
+#define FC_LCTL_RJT_INV_RXID 0x0C
+#define FC_LCTL_RJT_INV_SEQID 0x0D
+#define FC_LCTL_RJT_INV_DFCTL 0x0E
+#define FC_LCTL_RJT_INV_SEQCNT 0x0F
+#define FC_LCTL_RJT_INV_PARAM 0x10
+#define FC_LCTL_RJT_EXCHG_ERR 0x11
+#define FC_LCTL_RJT_PROTO_ERR 0x12
+#define FC_LCTL_RJT_INV_LEN 0x13
+#define FC_LCTL_RJT_UNEXP_ACK 0x14
+#define FC_LCTL_RJT_CLS_NOTSUPP 0x15
+#define FC_LCTL_RJT_LOGI_REQD 0x16
+#define FC_LCTL_RJT_TOOMANY_SEQ 0x17
+#define FC_LCTL_RJT_EXCHG_NOTESTD 0x18
+#define FC_LCTL_RJT_RSVD 0x19
+#define FC_LCTL_RJT_FPATH_NOTAVAIL 0x1A
+#define FC_LCTL_RJT_INV_VCID 0x1B
+#define FC_LCTL_RJT_INV_CSCTL 0x1C
+#define FC_LCTL_RJT_OORSRC 0x1D
+#define FC_LCTL_RJT_INV_CLASS 0x1F
+#define FC_LCTL_RJT_PRMPT_RJT 0x20
+#define FC_LCTL_RJT_PRMPT_DIS 0x21
+#define FC_LCTL_RJT_MCAST_ERR 0x22
+#define FC_LCTL_RJT_MCAST_TERM 0x23
+#define FC_LCTL_RJT_PRLI_REQD 0x24
+#define FC_LCTL_RJT_VEND_ERR 0xFF
+
+/* Function definitions */
+gchar *fclctl_get_typestr (guint8 linkctl_type, guint8 type);
+gchar *fclctl_get_paramstr (guint32 linkctl_type, guint32 param);
+#endif
diff --git a/epan/dissectors/packet-fcp.c b/epan/dissectors/packet-fcp.c
new file mode 100644
index 0000000000..b1171e9e9b
--- /dev/null
+++ b/epan/dissectors/packet-fcp.c
@@ -0,0 +1,690 @@
+/* packet-fcp.c
+ * Routines for Fibre Channel Protocol for SCSI (FCP)
+ * Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include "prefs.h"
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fcp.h"
+#include "packet-scsi.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_fcp = -1;
+static int hf_fcp_multilun = -1;
+static int hf_fcp_singlelun = -1;
+static int hf_fcp_crn = -1;
+static int hf_fcp_taskattr = -1;
+static int hf_fcp_taskmgmt = -1;
+static int hf_fcp_addlcdblen = -1;
+static int hf_fcp_rddata = -1;
+static int hf_fcp_wrdata = -1;
+static int hf_fcp_dl = -1;
+static int hf_fcp_data_ro = -1;
+static int hf_fcp_burstlen = -1;
+static int hf_fcp_rspflags = -1;
+static int hf_fcp_resid = -1;
+static int hf_fcp_snslen = -1;
+static int hf_fcp_rsplen = -1;
+static int hf_fcp_rspcode = -1;
+static int hf_fcp_scsistatus = -1;
+static int hf_fcp_type = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_fcp = -1;
+static dissector_table_t fcp_dissector;
+static dissector_handle_t data_handle;
+
+typedef struct _fcp_conv_key {
+ guint32 conv_idx;
+} fcp_conv_key_t;
+
+typedef struct _fcp_conv_data {
+ guint32 fcp_dl;
+ gint32 fcp_lun;
+ guint32 abs_secs;
+ guint32 abs_usecs;
+} fcp_conv_data_t;
+
+GHashTable *fcp_req_hash = NULL;
+GMemChunk *fcp_req_keys = NULL;
+GMemChunk *fcp_req_vals = NULL;
+guint32 fcp_init_count = 25;
+
+/*
+ * Hash Functions
+ */
+static gint
+fcp_equal(gconstpointer v, gconstpointer w)
+{
+ fcp_conv_key_t *v1 = (fcp_conv_key_t *)v;
+ fcp_conv_key_t *v2 = (fcp_conv_key_t *)w;
+
+ return (v1->conv_idx == v2->conv_idx);
+}
+
+static guint
+fcp_hash (gconstpointer v)
+{
+ fcp_conv_key_t *key = (fcp_conv_key_t *)v;
+ guint val;
+
+ val = key->conv_idx;
+
+ return val;
+}
+
+/*
+ * Protocol initialization
+ */
+static void
+fcp_init_protocol(void)
+{
+ if (fcp_req_keys)
+ g_mem_chunk_destroy(fcp_req_keys);
+ if (fcp_req_vals)
+ g_mem_chunk_destroy(fcp_req_vals);
+ if (fcp_req_hash)
+ g_hash_table_destroy(fcp_req_hash);
+
+ fcp_req_hash = g_hash_table_new(fcp_hash, fcp_equal);
+ fcp_req_keys = g_mem_chunk_new("fcp_req_keys",
+ sizeof(fcp_conv_key_t),
+ fcp_init_count * sizeof(fcp_conv_key_t),
+ G_ALLOC_AND_FREE);
+ fcp_req_vals = g_mem_chunk_new("fcp_req_vals",
+ sizeof(fcp_conv_data_t),
+ fcp_init_count * sizeof(fcp_conv_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+static gchar *
+task_mgmt_flags_to_str (guint8 flags, gchar *str)
+{
+ int stroff = 0;
+
+ if (str == NULL)
+ return str;
+
+ *str = '\0';
+
+ if (flags & 0x80) {
+ strcpy (str, "Obsolete, ");
+ stroff += 10;
+ }
+
+ if (flags & 0x40) {
+ strcpy (&str[stroff], "Clear ACA, ");
+ stroff += 11;
+ }
+
+ if (flags & 0x20) {
+ strcpy (&str[stroff], "Target Reset, ");
+ stroff += 14;
+ }
+
+ if (flags & 0x10) {
+ strcpy (&str[stroff], "LU Reset, ");
+ stroff += 10;
+ }
+
+ if (flags & 0x08) {
+ strcpy (&str[stroff], "Rsvd, ");
+ stroff += 6;
+ }
+
+ if (flags & 0x04) {
+ strcpy (&str[stroff], "Clear Task Set, ");
+ stroff += 16;
+ }
+
+ if (flags & 0x02) {
+ strcpy (&str[stroff], "Abort Task Set");
+ stroff += 14;
+ }
+
+ return (str);
+}
+
+static gchar *
+rspflags_to_str (guint8 flags, gchar *str)
+{
+ int stroff = 0;
+
+ if (str == NULL)
+ return (str);
+
+ *str = '\0';
+
+ if (flags & 0x10) {
+ strcpy (str, "FCP_CONF_REQ | ");
+ stroff += 15;
+ }
+ if (flags & 0x08) {
+ strcpy (&str[stroff], "FCP_RESID_UNDER | ");
+ stroff += 18;
+ }
+ if (flags & 0x04) {
+ strcpy (&str[stroff], "FCP_RESID_OVER | ");
+ stroff += 17;
+ }
+ if (flags & 0x02) {
+ strcpy (&str[stroff], "FCP_SNS_LEN_VLD | ");
+ stroff += 18;
+ }
+ if (flags & 0x01) {
+ strcpy (&str[stroff], "FCP_RSP_LEN_VLD | ");
+ }
+
+ return (str);
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_fcp_cmnd (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ int len,
+ add_len = 0;
+ gchar str[128];
+ guint8 flags, lun0;
+ proto_item *ti;
+ proto_tree *fcp_tree = NULL;
+ conversation_t *conversation;
+ fcp_conv_data_t *cdata;
+ fcp_conv_key_t ckey, *req_key;
+ scsi_task_id_t task_key;
+
+ /* Determine the length of the FCP part of the packet */
+ flags = tvb_get_guint8 (tvb, offset+10);
+ if (flags) {
+ add_len = tvb_get_guint8 (tvb, offset+11) & 0x7C;
+ add_len = add_len >> 2;
+
+ len = FCP_DEF_CMND_LEN + add_len;
+ }
+ else {
+ len = FCP_DEF_CMND_LEN;
+ }
+
+ /* We track the conversation to determine how many bytes is required */
+ /* by the data that is sent back or sent next by the initiator as part */
+ /* of this command. The state is destroyed in the response dissector */
+
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ if (!conversation) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ }
+
+ ckey.conv_idx = conversation->index;
+ task_key.conv_id = conversation->index;
+ task_key.task_id = conversation->index;
+ pinfo->private_data = (void *)&task_key;
+
+ cdata = (fcp_conv_data_t *)g_hash_table_lookup (fcp_req_hash,
+ &ckey);
+ if (cdata) {
+ /* Since we never free the memory used by an exchange, this maybe a
+ * case of another request using the same exchange as a previous
+ * req.
+ */
+ cdata->fcp_dl = tvb_get_ntohl (tvb, offset+12+16+add_len);
+ cdata->abs_usecs = pinfo->fd->abs_usecs;
+ cdata->abs_secs = pinfo->fd->abs_secs;
+ }
+ else {
+ req_key = g_mem_chunk_alloc (fcp_req_keys);
+ req_key->conv_idx = conversation->index;
+
+ cdata = g_mem_chunk_alloc (fcp_req_vals);
+ cdata->fcp_dl = tvb_get_ntohl (tvb, offset+12+16+add_len);
+ cdata->abs_usecs = pinfo->fd->abs_usecs;
+ cdata->abs_secs = pinfo->fd->abs_secs;
+
+ g_hash_table_insert (fcp_req_hash, req_key, cdata);
+ }
+
+ dissect_scsi_cdb (tvb, pinfo, fcp_tree, offset+12, 16+add_len,
+ SCSI_DEV_UNKNOWN);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcp, tvb, 0, len,
+ "FCP_CMND");
+ fcp_tree = proto_item_add_subtree (ti, ett_fcp);
+ proto_tree_add_uint_hidden (fcp_tree, hf_fcp_type, tvb, offset, 0, 0);
+
+ lun0 = tvb_get_guint8 (tvb, offset);
+
+ /* Display single-level LUNs in decimal for clarity */
+ /* I'm taking a shortcut here by assuming that if the first byte of the
+ * LUN field is 0, it is a single-level LUN. This is not true. For a
+ * real single-level LUN, all 8 bytes except byte 1 must be 0.
+ */
+ if (lun0) {
+ cdata->fcp_lun = -1;
+ proto_tree_add_item (fcp_tree, hf_fcp_multilun, tvb, offset, 8, 0);
+ }
+ else {
+ cdata->fcp_lun = tvb_get_guint8 (tvb, offset+1);
+ proto_tree_add_item (fcp_tree, hf_fcp_singlelun, tvb, offset+1,
+ 1, 0);
+ }
+
+ proto_tree_add_item (fcp_tree, hf_fcp_crn, tvb, offset+8, 1, 0);
+ proto_tree_add_item (fcp_tree, hf_fcp_taskattr, tvb, offset+9, 1, 0);
+ proto_tree_add_uint_format (fcp_tree, hf_fcp_taskmgmt, tvb, offset+10,
+ 1, flags,
+ "Task Management Flags: 0x%x (%s)",
+ flags,
+ task_mgmt_flags_to_str (flags, str));
+ proto_tree_add_item (fcp_tree, hf_fcp_addlcdblen, tvb, offset+11, 1, 0);
+ proto_tree_add_item (fcp_tree, hf_fcp_rddata, tvb, offset+11, 1, 0);
+ proto_tree_add_item (fcp_tree, hf_fcp_wrdata, tvb, offset+11, 1, 0);
+ dissect_scsi_cdb (tvb, pinfo, tree, offset+12, 16+add_len,
+ SCSI_DEV_UNKNOWN);
+ proto_tree_add_item (fcp_tree, hf_fcp_dl, tvb, offset+12+16+add_len,
+ 4, 0);
+ }
+}
+
+static void
+dissect_fcp_data (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ conversation_t *conversation;
+ fcp_conv_data_t *cdata = NULL;
+ fcp_conv_key_t ckey;
+ proto_item *ti;
+ proto_tree *fcp_tree;
+ scsi_task_id_t task_key;
+
+ /* Retrieve conversation state to determine expected payload */
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ if (conversation) {
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcp_conv_data_t *)g_hash_table_lookup (fcp_req_hash,
+ &ckey);
+ task_key.conv_id = conversation->index;
+ task_key.task_id = conversation->index;
+ pinfo->private_data = (void *)&task_key;
+ }
+ else {
+ pinfo->private_data = NULL;
+ }
+ if (cdata) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcp, tvb, 0, 0,
+ "FCP_DATA");
+ fcp_tree = proto_item_add_subtree (ti, ett_fcp);
+
+ if (cdata->fcp_lun >= 0)
+ proto_tree_add_uint_hidden (fcp_tree, hf_fcp_singlelun, tvb,
+ 0, 0, cdata->fcp_lun);
+
+ dissect_scsi_payload (tvb, pinfo, tree, 0, FALSE, cdata->fcp_dl);
+ }
+ else {
+ dissect_scsi_payload (tvb, pinfo, tree, 0, FALSE, 0);
+ }
+}
+
+static void
+dissect_fcp_rsp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 offset = 0,
+ del_usecs = 0;
+ guint len = 0,
+ add_len = 0,
+ rsplen = 0;
+ gchar str[128];
+ guint8 flags;
+ proto_item *ti;
+ proto_tree *fcp_tree;
+ guint8 status;
+ conversation_t *conversation;
+ fcp_conv_data_t *cdata = NULL;
+ fcp_conv_key_t ckey;
+ scsi_task_id_t task_key;
+
+ status = tvb_get_guint8 (tvb, offset+11);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, " , %s",
+ val_to_str (status, scsi_status_val, "0x%x"));
+ }
+
+ /* Response marks the end of the conversation. So destroy state */
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ if (conversation) {
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcp_conv_data_t *)g_hash_table_lookup (fcp_req_hash,
+ &ckey);
+ task_key.conv_id = task_key.task_id = conversation->index;
+ pinfo->private_data = (void *)&task_key;
+ }
+
+ if (tree) {
+ /* Determine the length of the FCP part of the packet */
+ len = FCP_DEF_RSP_LEN;
+
+ flags = tvb_get_guint8 (tvb, offset+10);
+ if (flags & 0x2) {
+ add_len = tvb_get_ntohl (tvb, offset+20);
+ len += add_len;
+ }
+ if (flags & 0x1) {
+ add_len = tvb_get_ntohl (tvb, offset+16);
+ len += add_len;
+ }
+
+ ti = proto_tree_add_protocol_format (tree, proto_fcp, tvb, 0, len,
+ "FCP_RSP");
+ fcp_tree = proto_item_add_subtree (ti, ett_fcp);
+ proto_tree_add_uint_hidden (fcp_tree, hf_fcp_type, tvb, offset, 0, 0);
+
+ if (cdata) {
+ del_usecs = (pinfo->fd->abs_secs - cdata->abs_secs)* 1000000 +
+ (pinfo->fd->abs_usecs - cdata->abs_usecs);
+ if (del_usecs > 1000)
+ proto_tree_add_text (fcp_tree, tvb, offset, 0,
+ "Cmd Response Time: %d msecs",
+ del_usecs/1000);
+ else
+ proto_tree_add_text (fcp_tree, tvb, offset, 0,
+ "Cmd Response Time: %d usecs",
+ del_usecs);
+ if (cdata->fcp_lun >= 0)
+ proto_tree_add_uint_hidden (fcp_tree, hf_fcp_singlelun, tvb,
+ offset, 0, cdata->fcp_lun);
+ }
+ proto_tree_add_uint_format (fcp_tree, hf_fcp_rspflags, tvb, offset+10,
+ 1, flags, "Flags: 0x%02x (%s)", flags,
+ rspflags_to_str (flags, str));
+ proto_tree_add_item (fcp_tree, hf_fcp_scsistatus, tvb, offset+11, 1, 0);
+ if (flags & 0xC)
+ proto_tree_add_item (fcp_tree, hf_fcp_resid, tvb, offset+12, 4, 0);
+ if (flags & 0x2)
+ proto_tree_add_item (fcp_tree, hf_fcp_snslen, tvb, offset+16, 4, 0);
+ if (flags & 0x1) {
+ rsplen = tvb_get_ntohl (tvb, offset+20);
+ proto_tree_add_item (fcp_tree, hf_fcp_rsplen, tvb, offset+20, 4, 0);
+ proto_tree_add_item (fcp_tree, hf_fcp_rspcode, tvb, offset+27, 1,
+ 0);
+ }
+ if (flags & 0x2) {
+ dissect_scsi_snsinfo (tvb, pinfo, tree, offset+24+rsplen,
+ tvb_get_ntohl (tvb, offset+16));
+ }
+ if (cdata) {
+ g_mem_chunk_free (fcp_req_vals, cdata);
+ g_hash_table_remove (fcp_req_hash, &ckey);
+ }
+ }
+}
+
+static void
+dissect_fcp_xfer_rdy (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_item *ti;
+ proto_tree *fcp_tree;
+ guint del_usecs;
+
+ conversation_t *conversation;
+ fcp_conv_data_t *cdata = NULL;
+ fcp_conv_key_t ckey, *req_key;
+
+ /* Retrieve conversation state to determine expected payload */
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ if (!conversation) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ }
+
+ if (conversation) {
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcp_conv_data_t *)g_hash_table_lookup (fcp_req_hash,
+ &ckey);
+ if (cdata != NULL) {
+ cdata->fcp_dl = tvb_get_ntohl (tvb, offset+4);
+ }
+ else {
+ req_key = g_mem_chunk_alloc (fcp_req_keys);
+ req_key->conv_idx = conversation->index;
+
+ cdata = g_mem_chunk_alloc (fcp_req_vals);
+ cdata->fcp_dl = tvb_get_ntohl (tvb, offset+4);
+ cdata->fcp_lun = -1;
+
+ g_hash_table_insert (fcp_req_hash, req_key, cdata);
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcp, tvb, 0, 12,
+ "FCP_XFER_RDY");
+ fcp_tree = proto_item_add_subtree (ti, ett_fcp);
+ proto_tree_add_uint_hidden (fcp_tree, hf_fcp_type, tvb, offset, 0, 0);
+
+ if (cdata) {
+ del_usecs = (pinfo->fd->abs_secs - cdata->abs_secs)* 1000000 +
+ (pinfo->fd->abs_usecs - cdata->abs_usecs);
+ if (del_usecs > 1000)
+ proto_tree_add_text (fcp_tree, tvb, offset, 0,
+ "Cmd Response Time: %d msecs",
+ del_usecs/1000);
+ else
+ proto_tree_add_text (fcp_tree, tvb, offset, 0,
+ "Cmd Response Time: %d usecs",
+ del_usecs);
+ if (cdata->fcp_lun >= 0)
+ proto_tree_add_uint_hidden (fcp_tree, hf_fcp_singlelun, tvb,
+ offset, 0, cdata->fcp_lun);
+ }
+ proto_tree_add_item (fcp_tree, hf_fcp_data_ro, tvb, offset, 4, 0);
+ proto_tree_add_item (fcp_tree, hf_fcp_burstlen, tvb, offset+4, 4, 0);
+ }
+}
+
+static void
+dissect_fcp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ guint8 r_ctl;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCP");
+
+ r_ctl = pinfo->r_ctl;
+
+ r_ctl &= 0xF;
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO, val_to_str (r_ctl, fcp_iu_val,
+ "0x%x"));
+ }
+
+ switch (r_ctl) {
+ case FCP_IU_DATA:
+ dissect_fcp_data (tvb, pinfo, tree);
+ break;
+ case FCP_IU_CONFIRM:
+ /* Nothing to be done here */
+ break;
+ case FCP_IU_XFER_RDY:
+ dissect_fcp_xfer_rdy (tvb, pinfo, tree);
+ break;
+ case FCP_IU_CMD:
+ dissect_fcp_cmnd (tvb, pinfo, tree);
+ break;
+ case FCP_IU_RSP:
+ dissect_fcp_rsp (tvb, pinfo, tree);
+ break;
+ default:
+ call_dissector (data_handle, tvb, pinfo, tree);
+ break;
+ }
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_fcp (void)
+{
+
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_fcp_type,
+ {"Field to branch off to SCSI", "fcp.type", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ {&hf_fcp_multilun,
+ {"Multi-Level LUN", "fcp.multilun", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_fcp_singlelun,
+ {"LUN", "fcp.lun", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcp_crn,
+ {"Command Ref Num", "fcp.crn", FT_UINT8, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcp_taskattr,
+ {"Task Attribute", "fcp.taskattr", FT_UINT8, BASE_HEX,
+ VALS (fcp_task_attr_val), 0x7, "", HFILL}},
+ { &hf_fcp_taskmgmt,
+ {"Task Management Flags", "fcp.taskmgmt", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_fcp_addlcdblen,
+ {"Additional CDB Length", "fcp.addlcdblen", FT_UINT8, BASE_DEC, NULL,
+ 0xFC, "", HFILL}},
+ { &hf_fcp_rddata,
+ {"RDDATA", "fcp.rddata", FT_BOOLEAN, 8, NULL, 0x02, "", HFILL}},
+ { &hf_fcp_wrdata,
+ {"WRDATA", "fcp.wrdata", FT_BOOLEAN, 8, NULL, 0x01, "", HFILL}},
+ { &hf_fcp_dl,
+ {"FCP_DL", "fcp.dl", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_fcp_data_ro,
+ {"FCP_DATA_RO", "fcp.data_ro", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcp_burstlen,
+ {"Burst Length", "fcp.burstlen", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcp_rspflags,
+ {"FCP_RSP Flags", "fcp.rspflags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcp_resid,
+ {"FCP_RESID", "fcp.resid", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcp_snslen,
+ {"FCP_SNS_LEN", "fcp.snslen", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcp_rsplen,
+ {"FCP_RSP_LEN", "fcp.rsplen", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_fcp_rspcode,
+ {"RSP_CODE", "fcp.rspcode", FT_UINT8, BASE_HEX,
+ VALS (fcp_rsp_code_val), 0x0, "", HFILL}},
+ { &hf_fcp_scsistatus,
+ {"SCSI Status", "fcp.status", FT_UINT8, BASE_HEX,
+ VALS (scsi_status_val), 0x0, "", HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fcp,
+ };
+
+ /* Register the protocol name and description */
+ proto_fcp = proto_register_protocol("Fibre Channel Protocol for SCSI",
+ "FCP", "fcp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ fcp_dissector = register_dissector_table ("fcp.type", "FCP Type", FT_UINT8,
+ BASE_HEX);
+ register_init_routine (&fcp_init_protocol);
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fcp (void)
+{
+ dissector_handle_t fcp_handle;
+
+ fcp_handle = create_dissector_handle (dissect_fcp, proto_fcp);
+ dissector_add("fc.ftype", FC_FTYPE_SCSI, fcp_handle);
+
+ data_handle = find_dissector ("data");
+}
+
+
diff --git a/epan/dissectors/packet-fcp.h b/epan/dissectors/packet-fcp.h
new file mode 100644
index 0000000000..b3770cb977
--- /dev/null
+++ b/epan/dissectors/packet-fcp.h
@@ -0,0 +1,69 @@
+/* packet-fcp.h
+ * Fibre Channel SCSI (FCP) Protocol definitions
+ * Copyright 2001 Dinesh G Dutt (ddutt@cisco.com)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCP_H_
+#define __PACKET_FCP_H_
+
+/* Information Categories based on lower 4 bits of R_CTL */
+#define FCP_IU_DATA 0x1
+#define FCP_IU_CONFIRM 0x3
+#define FCP_IU_XFER_RDY 0x5
+#define FCP_IU_CMD 0x6
+#define FCP_IU_RSP 0x7
+
+static const value_string fcp_iu_val[] = {
+ {FCP_IU_DATA , "FCP_DATA"},
+ {FCP_IU_CONFIRM , "Confirm"},
+ {FCP_IU_XFER_RDY , "XFER_RDY"},
+ {FCP_IU_CMD , "FCP_CMND"},
+ {FCP_IU_RSP , "FCP_RSP"},
+ {0, NULL},
+};
+
+/* Task Attribute Values */
+static const value_string fcp_task_attr_val[] = {
+ {0, "Simple"},
+ {1, "Head of Queue"},
+ {2, "Ordered"},
+ {4, "ACA"},
+ {5, "Untagged"},
+ {0, NULL},
+};
+
+/* RSP Code Definitions (from FCP_RSP_INFO) */
+static const value_string fcp_rsp_code_val[] = {
+ {0, "Task Management Function Complete"},
+ {1, "FCP_DATA length Different from FCP_BURST_LEN"},
+ {2, "FCP_CMND Fields Invalid"},
+ {3, "FCP_DATA Parameter Mismatch With FCP_DATA_RO"},
+ {4, "Task Management Function Rejected"},
+ {5, "Task Management Function Failed"},
+ {0, NULL},
+};
+
+#define FCP_DEF_CMND_LEN 32 /* by default cmnd is 32 bytes */
+#define FCP_DEF_RSP_LEN 24 /* default FCP_RSP len */
+
+#endif
diff --git a/epan/dissectors/packet-fcsb3.c b/epan/dissectors/packet-fcsb3.c
new file mode 100644
index 0000000000..84460e0677
--- /dev/null
+++ b/epan/dissectors/packet-fcsb3.c
@@ -0,0 +1,1001 @@
+/* packet-fc-sb3.c
+ * Routines for Fibre Channel Single Byte Protocol (SBCCS); used in FICON.
+ * This decoder is for FC-SB3 version 1.4
+ * Copyright 2003, Dinesh G Dutt <ddutt@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include "prefs.h"
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fcsb3.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_fc_sbccs = -1;
+static int hf_sbccs_chid = -1;
+static int hf_sbccs_cuid = -1;
+static int hf_sbccs_devaddr = -1;
+static int hf_sbccs_iui = -1;
+static int hf_sbccs_dhflags = -1;
+static int hf_sbccs_ccw = -1;
+static int hf_sbccs_token = -1;
+static int hf_sbccs_dib_iucnt = -1;
+static int hf_sbccs_dib_datacnt = -1;
+static int hf_sbccs_dib_ccw_cmd = -1;
+static int hf_sbccs_dib_ccw_flags = -1;
+static int hf_sbccs_dib_ccw_cnt = -1;
+static int hf_sbccs_dib_statusflags = -1;
+static int hf_sbccs_dib_status = -1;
+static int hf_sbccs_dib_residualcnt = -1;
+static int hf_sbccs_dib_qtuf = -1;
+static int hf_sbccs_dib_qtu = -1;
+static int hf_sbccs_dib_dtuf = -1;
+static int hf_sbccs_dib_dtu = -1;
+static int hf_sbccs_dib_ctlfn = -1;
+static int hf_sbccs_dib_ctlparam = -1;
+static int hf_sbccs_lrc = -1;
+static int hf_sbccs_dib_iupacing = -1;
+static int hf_sbccs_dev_xcp_code = -1;
+static int hf_sbccs_prg_pth_errcode = -1;
+static int hf_sbccs_prg_rsp_errcode = -1;
+static int hf_sbccs_dib_ctccntr = -1;
+static int hf_sbccs_dib_lprcode = -1;
+static int hf_sbccs_dib_tin_imgid_cnt = -1;
+static int hf_sbccs_dib_lrjcode = -1;
+static int hf_sbccs_dib_ioprio = -1;
+static int hf_sbccs_dib_cmdflags = -1;
+static int hf_sbccs_dib_linkctlfn = -1;
+static int hf_sbccs_dib_linkctlinfo = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_fc_sbccs = -1;
+
+static dissector_handle_t data_handle;
+
+typedef struct {
+ guint32 conv_id;
+ guint32 task_id;
+} sb3_task_id_t;
+
+static const value_string fc_sbccs_iu_val[] = {
+ {FC_SBCCS_IU_DATA, "Data"},
+ {FC_SBCCS_IU_CMD_HDR, "Command Header"},
+ {FC_SBCCS_IU_STATUS, "Status"},
+ {FC_SBCCS_IU_CTL, "Control"},
+ {FC_SBCCS_IU_CMD_DATA, "Command Header & Data"},
+ {FC_SBCCS_IU_CMD_LINK_CTL, "Link Control"},
+ {0x6, "Reserved"},
+ {0x7, "Reserved"},
+ {0x0, NULL},
+};
+
+static const value_string fc_sbccs_dib_cmd_val[] = {
+ {0, "Reserved"},
+ {1, "Write"},
+ {2, "Read"},
+ {3, "Control"},
+ {4, "Sense"},
+ {5, "Write (Modifier)"},
+ {6, "Read (Modifier)"},
+ {7, "Control (Modifier)"},
+ {8, "Reserved"},
+ {9, "Write (Modifier)"},
+ {10, "Read (Modifier)"},
+ {11, "Control (Modifier)"},
+ {12, "Read Backward"},
+ {13, "Write (Modifier)"},
+ {14, "Read (Modifier)"},
+ {15, "Control (Modifier)"},
+ {0, NULL},
+};
+
+static const value_string fc_sbccs_dib_ctl_fn_val[] = {
+ {FC_SBCCS_CTL_FN_CTL_END, "Control End"},
+ {FC_SBCCS_CTL_FN_CMD_RSP, "Command Response"},
+ {FC_SBCCS_CTL_FN_STK_STS, "Stack Status"},
+ {FC_SBCCS_CTL_FN_CANCEL, "Cancel"},
+ {FC_SBCCS_CTL_FN_SYS_RST, "System Reset"},
+ {FC_SBCCS_CTL_FN_SEL_RST, "Selective Reset"},
+ {FC_SBCCS_CTL_FN_REQ_STS, "Request Status"},
+ {FC_SBCCS_CTL_FN_DEV_XCP, "Device Level Exception"},
+ {FC_SBCCS_CTL_FN_STS_ACC, "Status Accepted"},
+ {FC_SBCCS_CTL_FN_DEV_ACK, "Device-Level Ack"},
+ {FC_SBCCS_CTL_FN_PRG_PTH, "Purge Path"},
+ {FC_SBCCS_CTL_FN_PRG_RSP, "Purge Path Response"},
+ {0, NULL},
+};
+
+static const value_string fc_sbccs_dib_dev_xcpcode_val[] = {
+ {1, "Address Exception"},
+ {0, NULL},
+};
+
+static const value_string fc_sbccs_dib_purge_path_err_val[] = {
+ {0, "Error Code Xfer Not Supported"},
+ {1, "SB-3 Protocol Timeout"},
+ {2, "SB-3 Link Failure"},
+ {3, "Reserved"},
+ {4, "SB-3 Offline Condition"},
+ {5, "FC-PH Link Failure"},
+ {6, "SB-3 Length Error"},
+ {7, "LRC Error"},
+ {8, "SB-3 CRC Error"},
+ {9, "IU Count Error"},
+ {10, "SB-3 Link Level Protocol Error"},
+ {11, "SB-3 Device Level Protocol Error"},
+ {12, "Receive ABTS"},
+ {13, "Cancel Function Timeout"},
+ {14, "Abnormal Termination of Xchg"},
+ {15, "Reserved"},
+ {0, NULL},
+};
+
+static const value_string fc_sbccs_dib_purge_path_rsp_err_val[] = {
+ {0, "No Errors"},
+ {1, "SB-3 Protocol Timeout"},
+ {2, "SB-3 Link Failure"},
+ {3, "Logical Path Timeout Error"},
+ {4, "SB-3 Offline Condition"},
+ {5, "FC-PH Link Failure"},
+ {6, "SB-3 Length Error"},
+ {7, "LRC Error"},
+ {8, "SB-3 CRC Error"},
+ {9, "IU Count Error"},
+ {10, "SB-3 Link Level Protocol Error"},
+ {11, "SB-3 Device Level Protocol Error"},
+ {12, "Receive ABTS"},
+ {13, "Reserved"},
+ {14, "Abnormal Termination of Xchg"},
+ {15, "Logical Path Not Estd"},
+ {16, "Test Init Result Error"},
+ {0, NULL},
+};
+
+static const value_string fc_sbccs_dib_link_ctl_fn_val[] = {
+ {FC_SBCCS_LINK_CTL_FN_ELP, "ELP"},
+ {FC_SBCCS_LINK_CTL_FN_RLP, "RLP"},
+ {FC_SBCCS_LINK_CTL_FN_TIN, "TIN"},
+ {FC_SBCCS_LINK_CTL_FN_LPE, "LPE"},
+ {FC_SBCCS_LINK_CTL_FN_LPR, "LPR"},
+ {FC_SBCCS_LINK_CTL_FN_TIR, "TIR"},
+ {FC_SBCCS_LINK_CTL_FN_LRJ, "LRJ"},
+ {FC_SBCCS_LINK_CTL_FN_LBY, "LBY"},
+ {FC_SBCCS_LINK_CTL_FN_LACK, "LACK"},
+ {0, NULL},
+};
+
+static const value_string fc_sbccs_dib_lpr_errcode_val[] = {
+ {0x0, "Response to RLP"},
+ {0x1, "Optional Features Conflict"},
+ {0x2, "Out of Resources"},
+ {0x3, "Device Init In Progress"},
+ {0x4, "No CU Image"},
+ {0x0, NULL},
+};
+
+static const value_string fc_sbccs_dib_lrj_errcode_val[] = {
+ {0x6, "Logical Path Not Estd"},
+ {0x9, "Protocol Error"},
+ {0x0, NULL},
+};
+
+static gchar *get_iui_string (guint8 iui, gchar *buffer)
+{
+ guint pos = 0;
+ buffer[0] = '\0';
+
+ if (iui & 0x10) {
+ strcpy (&buffer[pos], "AS, ");
+ pos += 4;
+ }
+
+ if (iui & 0x8) {
+ strcpy (&buffer[pos], "ES, ");
+ pos += 4;
+ }
+
+ strcpy (&buffer[pos], val_to_str (iui & 0x7, fc_sbccs_iu_val, "0x%x"));
+
+ return (buffer);
+}
+
+static gchar *get_dhflags_string (guint8 dhflags, gchar *buffer)
+{
+ guint pos = 0;
+ buffer[0] = '\0';
+
+ if (dhflags & 0x80) {
+ strcpy (&buffer[pos], "End, ");
+ pos += 5;
+ }
+
+ if (dhflags & 0x10) {
+ strcpy (&buffer[pos], "Chaining, ");
+ pos += 10;
+ }
+
+ if (dhflags & 0x8) {
+ strcpy (&buffer[pos], "Early End, ");
+ pos += 11;
+ }
+
+ if (dhflags & 0x4) {
+ strcpy (&buffer[pos], "No CRC");
+ }
+
+ return (buffer);
+}
+
+static gchar *get_ccw_flags_string (guint8 ccw_flags, gchar *buffer)
+{
+ guint pos = 0;
+
+ buffer[0] = '\0';
+
+ if (ccw_flags & 0x80) {
+ strcpy (&buffer[pos], "CD, ");
+ pos += 4;
+ }
+
+ if (ccw_flags & 0x40) {
+ strcpy (&buffer[pos], "CC, ");
+ pos += 4;
+ }
+
+ if (ccw_flags & 0x20) {
+ strcpy (&buffer[pos], "SLI, ");
+ pos += 5;
+ }
+
+ if (ccw_flags & 0x8) {
+ strcpy (&buffer[pos], "CRR");
+ pos += 5;
+ }
+
+ return (buffer);
+}
+
+static gchar *get_cmd_flag_string (guint8 cmd_flag, gchar *buffer)
+{
+ guint pos = 0;
+
+ buffer[0] = '\0';
+
+ if (cmd_flag & 0x10) {
+ strcpy (&buffer[pos], "DU, ");
+ pos += 4;
+ }
+
+ if (cmd_flag & 0x8) {
+ strcpy (&buffer[pos], "COC, ");
+ pos += 4;
+ }
+
+ if (cmd_flag & 0x4) {
+ strcpy (&buffer[pos], "SYR, ");
+ pos += 5;
+ }
+
+ if (cmd_flag & 0x2) {
+ strcpy (&buffer[pos], "REX, ");
+ pos += 5;
+ }
+
+ if (cmd_flag & 0x1) {
+ strcpy (&buffer[pos], "SSS");
+ pos += 5;
+ }
+
+ return (buffer);
+}
+
+static gchar *get_status_flag_string (guint8 status_flag, gchar *buffer)
+{
+ guint pos = 0;
+ guint8 ffc = (status_flag & 0xD0) >> 5;
+
+ buffer[0] = '\0';
+
+ switch (ffc) {
+ case 0:
+ break; /* to avoid the catch clause below */
+ case 1:
+ strcpy (&buffer[pos], "FFC:Queuing Information Valid, ");
+ pos += 31;
+ break;
+ case 2:
+ strcpy (&buffer[pos], "FFC:Resetting Event, ");
+ pos += 21;
+ break;
+ default:
+ strcpy (&buffer[pos], "Reserved");
+ break;
+ }
+
+ if (status_flag & 10) {
+ strcpy (&buffer[pos], "CI, ");
+ pos += 4;
+ }
+
+ if (status_flag & 0x4) {
+ strcpy (&buffer[pos], "CR, ");
+ pos += 4;
+ }
+
+ if (status_flag & 0x2) {
+ strcpy (&buffer[pos], "LRI, ");
+ pos += 5;
+ }
+
+ if (status_flag & 0x1) {
+ strcpy (&buffer[pos], "RV");
+ }
+
+ return (buffer);
+}
+
+static gchar *get_status_string (guint8 status, gchar *buffer)
+{
+ guint pos = 0;
+
+ buffer[0] = '\0';
+
+ if (status & 0x80) {
+ strcpy (&buffer[pos], "Attention, ");
+ pos += 11;
+ }
+
+ if (status & 0x40) {
+ strcpy (&buffer[pos], "Status Modifier, ");
+ pos += 17;
+ }
+
+ if (status & 0x20) {
+ strcpy (&buffer[pos], "Control-Unit End, ");
+ pos += 18;
+ }
+
+ if (status & 0x10) {
+ strcpy (&buffer[pos], "Busy, ");
+ pos += 6;
+ }
+
+ if (status & 0x8) {
+ strcpy (&buffer[pos], "Channel End, ");
+ pos += 12;
+ }
+
+ if (status & 0x4) {
+ strcpy (&buffer[pos], "Device End, ");
+ pos += 12;
+ }
+
+ if (status & 0x2) {
+ strcpy (&buffer[pos], "Unit Check, ");
+ pos += 12;
+ }
+
+ if (status & 0x1) {
+ strcpy (&buffer[pos], "Unit Exception");
+ }
+
+ return (buffer);
+}
+
+static gchar *get_sel_rst_param_string (guint8 ctlparam, gchar *buffer)
+{
+ guint pos = 0;
+
+ buffer[0] = '\0';
+
+ if (ctlparam & 0x80) {
+ strcpy (&buffer[pos], "RC, ");
+ pos += 4;
+ }
+ if (ctlparam & 0x10) {
+ strcpy (&buffer[pos], "RU, ");
+ pos += 4;
+ }
+ if (ctlparam & 0x8) {
+ strcpy (&buffer[pos], "RO");
+ }
+
+ return (buffer);
+}
+
+static void get_fc_sbccs_conv_data (tvbuff_t *tvb, guint offset,
+ guint16 *ch_cu_id, guint16 *dev_addr,
+ guint16 *ccw)
+{
+ *ch_cu_id = *dev_addr = *ccw = 0;
+
+ *ch_cu_id = (tvb_get_guint8 (tvb, offset+1)) << 8;
+ *ch_cu_id |= tvb_get_guint8 (tvb, offset+3);
+ *dev_addr = tvb_get_ntohs (tvb, offset+4);
+ *ccw = tvb_get_ntohs (tvb, offset+10);
+}
+
+/* Decode both the SB-3 and basic IU header */
+static void
+dissect_fc_sbccs_sb3_iu_hdr (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint offset)
+{
+ proto_item *subti;
+ proto_tree *sb3hdr_tree;
+ proto_tree *iuhdr_tree;
+ gchar buffer[256];
+ guint8 iui, dhflags;
+ guint type;
+
+ /* Decode the basic SB3 and IU header and determine type of frame */
+ type = get_fc_sbccs_iu_type (tvb, offset);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO, val_to_str (type, fc_sbccs_iu_val,
+ "0x%x"));
+ }
+
+ if (tree) {
+ /* Dissect SB3 header first */
+ subti = proto_tree_add_text (tree, tvb, offset, FC_SBCCS_SB3_HDR_SIZE,
+ "SB-3 Header");
+ sb3hdr_tree = proto_item_add_subtree (subti, ett_fc_sbccs);
+
+ proto_tree_add_item (sb3hdr_tree, hf_sbccs_chid, tvb, offset+1, 1, 0);
+ proto_tree_add_item (sb3hdr_tree, hf_sbccs_cuid, tvb, offset+3, 1, 0);
+ proto_tree_add_item (sb3hdr_tree, hf_sbccs_devaddr, tvb, offset+4, 2, 0);
+
+ /* Dissect IU Header */
+ subti = proto_tree_add_text (tree, tvb, offset + FC_SBCCS_SB3_HDR_SIZE,
+ FC_SBCCS_IU_HDR_SIZE, "IU Header");
+ iuhdr_tree = proto_item_add_subtree (subti, ett_fc_sbccs);
+ offset += FC_SBCCS_SB3_HDR_SIZE;
+
+ iui = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_uint_format (iuhdr_tree, hf_sbccs_iui, tvb, offset, 1,
+ iui, "Information Unit Identifier: 0x%x (%s)",
+ iui, get_iui_string (iui, buffer));
+ dhflags = tvb_get_guint8 (tvb, offset+1);
+ proto_tree_add_uint_format (iuhdr_tree, hf_sbccs_dhflags, tvb, offset, 1,
+ dhflags, "DH Flags: 0x%x (%s)",
+ dhflags, get_dhflags_string (dhflags, buffer));
+
+ proto_tree_add_item (iuhdr_tree, hf_sbccs_ccw, tvb, offset+2, 2, 0);
+ proto_tree_add_item (iuhdr_tree, hf_sbccs_token, tvb, offset+5, 3, 0);
+ }
+}
+
+static void dissect_fc_sbccs_dib_data_hdr (tvbuff_t *tvb,
+ packet_info *pinfo _U_,
+ proto_tree *tree, guint offset)
+{
+ if (tree) {
+ proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
+ proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
+ proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
+ }
+}
+
+static void dissect_fc_sbccs_dib_cmd_hdr (tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint offset)
+{
+ guint8 flags;
+ gchar buffer[64];
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ ": %s", val_to_str (tvb_get_guint8 (tvb, offset),
+ fc_sbccs_dib_cmd_val,
+ "0x%x"));
+ }
+
+ if (tree) {
+ proto_tree_add_item (tree, hf_sbccs_dib_ccw_cmd, tvb, offset, 1, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+1);
+ proto_tree_add_uint_format (tree, hf_sbccs_dib_ccw_flags, tvb,
+ offset+1, 1, flags,
+ "CCW Control Flags: 0x%x(%s)", flags,
+ get_ccw_flags_string (flags, buffer));
+ proto_tree_add_item (tree, hf_sbccs_dib_ccw_cnt, tvb, offset+2, 2, 0);
+ proto_tree_add_item (tree, hf_sbccs_dib_ioprio, tvb, offset+5, 1, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+7);
+ proto_tree_add_uint_format (tree, hf_sbccs_dib_cmdflags, tvb, offset+7,
+ 1, flags, "Command Flags: 0x%x(%s)", flags,
+ get_cmd_flag_string (flags, buffer));
+ proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
+ proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
+ proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
+
+ }
+}
+
+static void dissect_fc_sbccs_dib_status_hdr (tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint offset)
+{
+ guint8 flags;
+ gboolean rv_valid, qparam_valid;
+ gchar buffer[128];
+ tvbuff_t *next_tvb;
+ guint16 supp_status_cnt = 0;
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ ": %s",
+ get_status_string (tvb_get_guint8 (tvb, offset+1),
+ buffer));
+ }
+
+ if (tree) {
+ flags = tvb_get_guint8 (tvb, offset);
+ rv_valid = flags & 0x1; /* if residual count is valid */
+ qparam_valid = (((flags & 0xD0) >> 5) == 0x1); /* From the FFC field */
+ proto_tree_add_uint_format (tree, hf_sbccs_dib_statusflags, tvb, offset,
+ 1, flags, "Status Flags: 0x%x(%s)",
+ flags, get_status_flag_string (flags,
+ buffer));
+
+ flags = tvb_get_guint8 (tvb, offset+1);
+ proto_tree_add_uint_format (tree, hf_sbccs_dib_status, tvb, offset+1,
+ 1, flags, "Status: 0x%x(%s)", flags,
+ get_status_string (flags, buffer));
+ if (rv_valid) {
+ proto_tree_add_item (tree, hf_sbccs_dib_residualcnt, tvb, offset+2,
+ 2, 0);
+ }
+ else {
+ proto_tree_add_item (tree, hf_sbccs_dib_iupacing, tvb, offset+3,
+ 1, 0);
+ }
+
+ if (qparam_valid) {
+ proto_tree_add_item (tree, hf_sbccs_dib_qtuf, tvb, offset+4, 1, 0);
+ proto_tree_add_item (tree, hf_sbccs_dib_qtu, tvb, offset+4, 2, 0);
+ }
+
+ proto_tree_add_item (tree, hf_sbccs_dib_dtuf, tvb, offset+6, 1, 0);
+ proto_tree_add_item (tree, hf_sbccs_dib_dtu, tvb, offset+6, 2, 0);
+
+ proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
+ proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
+ supp_status_cnt = tvb_get_ntohs (tvb, offset+10);
+ proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
+
+ if (supp_status_cnt) {
+ next_tvb = tvb_new_subset (tvb, offset+FC_SBCCS_DIB_LRC_HDR_SIZE,
+ -1, -1);
+ call_dissector (data_handle, next_tvb, pinfo, tree);
+ }
+ }
+}
+
+static void dissect_fc_sbccs_dib_ctl_hdr (tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint offset)
+{
+ guint8 ctlfn;
+ gchar buffer[128];
+
+ ctlfn = tvb_get_guint8 (tvb, offset);
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ ": %s",
+ val_to_str (ctlfn,
+ fc_sbccs_dib_ctl_fn_val,
+ "0x%x"));
+ }
+ if (tree) {
+ proto_tree_add_item (tree, hf_sbccs_dib_ctlfn, tvb, offset, 1, 0);
+
+ /* Control Function Parameter is to be interpreted in some cases */
+ switch (ctlfn) {
+ case FC_SBCCS_CTL_FN_SEL_RST:
+ proto_tree_add_uint_format (tree, hf_sbccs_dib_ctlparam, tvb,
+ offset+1, 3,
+ tvb_get_ntoh24 (tvb, offset+1),
+ "Control Parameter: 0x%x(%s)",
+ tvb_get_ntoh24 (tvb, offset+1),
+ get_sel_rst_param_string (ctlfn,
+ buffer));
+ break;
+ case FC_SBCCS_CTL_FN_DEV_XCP:
+ proto_tree_add_item (tree, hf_sbccs_dev_xcp_code, tvb, offset+1,
+ 1, 0);
+ break;
+ case FC_SBCCS_CTL_FN_PRG_PTH:
+ proto_tree_add_item (tree, hf_sbccs_prg_pth_errcode, tvb, offset+1,
+ 1, 0);
+ break;
+ default:
+ proto_tree_add_item (tree, hf_sbccs_dib_ctlparam, tvb, offset+1,
+ 3, 0);
+ break;
+ }
+
+ proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
+ proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
+ proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
+
+ if (ctlfn == FC_SBCCS_CTL_FN_PRG_RSP) {
+ /* Need to decode the LESBs */
+ proto_tree_add_item (tree, hf_sbccs_prg_rsp_errcode, tvb, offset+60,
+ 1, 0);
+ }
+ }
+}
+
+static void dissect_fc_sbccs_dib_link_hdr (tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint offset)
+{
+ guint8 link_ctl;
+ guint16 ctl_info;
+ gchar buffer[128];
+ guint link_payload_len, i;
+ gchar *lpath_ptr;
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ ": %s",
+ val_to_str (tvb_get_guint8 (tvb, offset+1),
+ fc_sbccs_dib_link_ctl_fn_val,
+ "0x%x"));
+ }
+
+ if (tree) {
+ link_ctl = tvb_get_guint8 (tvb, offset+1);
+ proto_tree_add_item (tree, hf_sbccs_dib_linkctlfn, tvb, offset+1, 1, 0);
+
+ ctl_info = tvb_get_ntohs (tvb, offset+2);
+ switch (link_ctl) {
+ case FC_SBCCS_LINK_CTL_FN_ELP:
+ case FC_SBCCS_LINK_CTL_FN_LPE:
+ buffer[0] = '\0';
+ if (ctl_info & 0x1) {
+ strcpy (buffer, "Enhanced CRC Gen, ");
+ }
+ if (ctl_info & 0x80) {
+ strcpy (&buffer[18], "CTC Conn");
+ }
+
+ proto_tree_add_uint_format (tree, hf_sbccs_dib_linkctlinfo, tvb,
+ offset+2, 2, ctl_info,
+ "Link Control Info: 0x%x(%s)", ctl_info,
+ buffer);
+ break;
+ case FC_SBCCS_LINK_CTL_FN_LPR:
+ proto_tree_add_item (tree, hf_sbccs_dib_lprcode, tvb, offset+2, 1,
+ 0);
+ break;
+ case FC_SBCCS_LINK_CTL_FN_TIN:
+ proto_tree_add_item (tree, hf_sbccs_dib_tin_imgid_cnt, tvb,
+ offset+3, 1, 0);
+ break;
+ case FC_SBCCS_LINK_CTL_FN_TIR:
+ proto_tree_add_item (tree, hf_sbccs_dib_tin_imgid_cnt, tvb,
+ offset+3, 1, 0);
+ break;
+ case FC_SBCCS_LINK_CTL_FN_LRJ:
+ proto_tree_add_item (tree, hf_sbccs_dib_lrjcode, tvb, offset+2,
+ 1, 0);
+ break;
+ default:
+ /* Do Nothing */
+ break;
+ }
+
+ proto_tree_add_item (tree, hf_sbccs_dib_ctccntr, tvb, offset+4, 2, 0);
+ proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
+ proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
+ proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
+
+ if (link_ctl == FC_SBCCS_LINK_CTL_FN_TIR) {
+ link_payload_len = tvb_get_ntohs (tvb, offset+10);
+ i = 0;
+ offset += 16;
+ lpath_ptr = (gchar *)tvb_get_ptr (tvb, offset, link_payload_len/4);
+
+ while (i < link_payload_len) {
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Logical Paths %d-%d: %x:%x:%x:%x",
+ i*8, ((i+4)*8) - 1, lpath_ptr[i],
+ lpath_ptr[i+1], lpath_ptr[i+2],
+ lpath_ptr[i+3]);
+ i += 4;
+ offset += 4;
+ }
+ }
+ }
+}
+
+static void dissect_fc_sbccs (tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint8 type;
+ guint16 ch_cu_id, dev_addr, ccw;
+ guint offset = 0;
+ proto_item *ti;
+ proto_tree *sb3_tree = NULL,
+ *dib_tree = NULL;
+ tvbuff_t *next_tvb;
+ conversation_t *conversation;
+ sb3_task_id_t task_key;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FC-SB3");
+
+ /* Decode the basic SB3 and IU header and determine type of frame */
+ type = get_fc_sbccs_iu_type (tvb, offset);
+ get_fc_sbccs_conv_data (tvb, offset, &ch_cu_id, &dev_addr, &ccw);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO, val_to_str (type, fc_sbccs_iu_val,
+ "0x%x"));
+ }
+
+ /* Retrieve conversation state to determine expected payload */
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ PT_SBCCS, ch_cu_id, dev_addr, 0);
+
+ if (conversation) {
+ task_key.conv_id = conversation->index;
+ task_key.task_id = ccw;
+ pinfo->private_data = (void *)&task_key;
+
+ }
+ else if ((type == FC_SBCCS_IU_CMD_HDR) ||
+ (type != FC_SBCCS_IU_CMD_DATA)) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ PT_SBCCS, ch_cu_id, dev_addr, 0);
+ task_key.conv_id = conversation->index;
+ task_key.task_id = ccw;
+ pinfo->private_data = (void *)&task_key;
+ }
+ else {
+ pinfo->private_data = NULL;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fc_sbccs, tvb, 0, -1,
+ "FC-SB3");
+ sb3_tree = proto_item_add_subtree (ti, ett_fc_sbccs);
+
+ dissect_fc_sbccs_sb3_iu_hdr (tvb, pinfo, sb3_tree, offset);
+ offset += (FC_SBCCS_SB3_HDR_SIZE + FC_SBCCS_IU_HDR_SIZE);
+
+ ti = proto_tree_add_text (sb3_tree, tvb, offset,
+ FC_SBCCS_DIB_LRC_HDR_SIZE, "DIB Header");
+ dib_tree = proto_item_add_subtree (ti, ett_fc_sbccs);
+ }
+ else {
+ offset += (FC_SBCCS_SB3_HDR_SIZE + FC_SBCCS_IU_HDR_SIZE);
+ }
+
+ switch (type) {
+ case FC_SBCCS_IU_DATA:
+ dissect_fc_sbccs_dib_data_hdr (tvb, pinfo, dib_tree, offset);
+ break;
+ case FC_SBCCS_IU_CMD_HDR:
+ case FC_SBCCS_IU_CMD_DATA:
+ dissect_fc_sbccs_dib_cmd_hdr (tvb, pinfo, dib_tree, offset);
+ break;
+ case FC_SBCCS_IU_STATUS:
+ dissect_fc_sbccs_dib_status_hdr (tvb, pinfo, dib_tree, offset);
+ break;
+ case FC_SBCCS_IU_CTL:
+ dissect_fc_sbccs_dib_ctl_hdr (tvb, pinfo, dib_tree, offset);
+ break;
+ case FC_SBCCS_IU_CMD_LINK_CTL:
+ dissect_fc_sbccs_dib_link_hdr (tvb, pinfo, dib_tree, offset);
+ break;
+ default:
+ next_tvb = tvb_new_subset (tvb, offset, -1, -1);
+ call_dissector (data_handle, next_tvb, pinfo, dib_tree);
+ break;
+ }
+
+ if ((get_fc_sbccs_iu_type (tvb, 0) != FC_SBCCS_IU_CTL) &&
+ (get_fc_sbccs_iu_type (tvb, 0) != FC_SBCCS_IU_CMD_LINK_CTL)) {
+ next_tvb = tvb_new_subset (tvb, offset+FC_SBCCS_DIB_LRC_HDR_SIZE,
+ -1, -1);
+ call_dissector (data_handle, next_tvb, pinfo, tree);
+ }
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is required because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_fcsbccs (void)
+{
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_sbccs_chid,
+ {"Channel Image ID", "sbccs.chid", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sbccs_cuid,
+ {"Control Unit Image ID", "sbccs.cuid", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_sbccs_devaddr,
+ {"Device Address", "sbccs.devaddr", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sbccs_iui,
+ {"Information Unit Identifier", "sbccs.iui", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_sbccs_dhflags,
+ {"DH Flags", "sbccs.dhflags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_sbccs_ccw,
+ {"CCW Number", "sbccs.ccw", FT_UINT16, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_sbccs_token,
+ {"Token", "sbccs.token", FT_UINT24, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_sbccs_dib_iucnt,
+ {"DIB IU Count", "sbccs.iucnt", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sbccs_dib_datacnt,
+ {"DIB Data Byte Count", "sbccs.databytecnt", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_sbccs_dib_ccw_cmd,
+ {"CCW Command", "sbccs.ccwcmd", FT_UINT8, BASE_HEX,
+ VALS (fc_sbccs_dib_cmd_val), 0x0, "", HFILL}},
+ { &hf_sbccs_dib_ccw_flags,
+ {"CCW Control Flags", "sbccs.ccwflags", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_sbccs_dib_ccw_cnt,
+ {"CCW Count", "sbccs.ccwcnt", FT_UINT16, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_sbccs_dib_ioprio,
+ {"I/O Priority", "sbccs.ioprio", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sbccs_dib_cmdflags,
+ {"Command Flags", "sbccs.cmdflags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sbccs_dib_statusflags,
+ {"Status Flags", "sbccs.statusflags", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_sbccs_dib_status,
+ {"Status", "sbccs.status", FT_UINT8, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_sbccs_dib_residualcnt,
+ {"Residual Count", "sbccs.residualcnt", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_sbccs_dib_iupacing,
+ {"IU Pacing", "sbccs.iupacing", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sbccs_dib_qtuf,
+ {"Queue-Time Unit Factor", "sbccs.qtuf", FT_UINT8, BASE_DEC,
+ NULL, 0xF0, "", HFILL}},
+ { &hf_sbccs_dib_qtu,
+ {"Queue-Time Unit", "sbccs.qtu", FT_UINT16, BASE_DEC, NULL, 0xFFF,
+ "", HFILL}},
+ { &hf_sbccs_dib_dtuf,
+ {"Defer-Time Unit Function", "sbccs.dtuf", FT_UINT8, BASE_DEC,
+ NULL, 0xF0, "", HFILL}},
+ { &hf_sbccs_dib_dtu,
+ {"Defer-Time Unit", "sbccs.dtu", FT_UINT16, BASE_DEC, NULL, 0xFFF,
+ "", HFILL}},
+ { &hf_sbccs_dib_ctlfn,
+ {"Control Function", "sbccs.ctlfn", FT_UINT8, BASE_HEX,
+ VALS (fc_sbccs_dib_ctl_fn_val), 0x0, "", HFILL}},
+ { &hf_sbccs_dib_ctlparam,
+ {"Control Parameters", "sbccs.ctlparam", FT_UINT24, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_sbccs_dib_linkctlfn,
+ {"Link Control Function", "sbccs.linkctlfn", FT_UINT8, BASE_HEX,
+ VALS (fc_sbccs_dib_link_ctl_fn_val), 0x0, "", HFILL}},
+ { &hf_sbccs_dib_linkctlinfo,
+ {"Link Control Information", "sbccs.linkctlinfo", FT_UINT16,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_sbccs_dib_ctccntr,
+ {"CTC Counter", "sbccs.ctccntr", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sbccs_lrc,
+ {"LRC", "sbccs.lrc", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_sbccs_dev_xcp_code,
+ {"Device Level Exception Code", "sbccs.dip.xcpcode", FT_UINT8,
+ BASE_DEC, VALS (fc_sbccs_dib_dev_xcpcode_val), 0x0, "", HFILL}},
+ { &hf_sbccs_prg_pth_errcode,
+ {"Purge Path Error Code", "sbccs.purgepathcode", FT_UINT8,
+ BASE_DEC, VALS (fc_sbccs_dib_purge_path_err_val), 0x0, "", HFILL}},
+ { &hf_sbccs_prg_rsp_errcode,
+ {"Purge Path Response Error Code", "sbccs.purgepathrspcode",
+ FT_UINT8, BASE_DEC, VALS (fc_sbccs_dib_purge_path_rsp_err_val),
+ 0x0, "", HFILL}},
+ { &hf_sbccs_dib_lprcode,
+ {"LPR Reason Code", "sbccs.lprcode", FT_UINT8, BASE_DEC,
+ VALS (fc_sbccs_dib_lpr_errcode_val), 0xF, "", HFILL}},
+ { &hf_sbccs_dib_tin_imgid_cnt,
+ {"TIN Image ID", "sbccs.tinimageidcnt", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_sbccs_dib_lrjcode,
+ {"LRJ Reaspn Code", "sbccs.lrjcode", FT_UINT8, BASE_HEX,
+ VALS (fc_sbccs_dib_lrj_errcode_val), 0x7F, "", HFILL}},
+ };
+
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fc_sbccs,
+ };
+
+ /* Register the protocol name and description */
+ proto_fc_sbccs = proto_register_protocol ("Fibre Channel Single Byte Command",
+ "FC-SB3", "sb3");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fc_sbccs, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fcsbccs (void)
+{
+ dissector_handle_t fc_sbccs_handle;
+
+ fc_sbccs_handle = create_dissector_handle (dissect_fc_sbccs,
+ proto_fc_sbccs);
+
+ dissector_add("fc.ftype", FC_FTYPE_SBCCS, fc_sbccs_handle);
+
+ data_handle = find_dissector ("data");
+}
+
+
diff --git a/epan/dissectors/packet-fcsb3.h b/epan/dissectors/packet-fcsb3.h
new file mode 100644
index 0000000000..c7a4301e83
--- /dev/null
+++ b/epan/dissectors/packet-fcsb3.h
@@ -0,0 +1,74 @@
+/* packet-fc-sb3.h
+ * Routines for Fibre Channel Single Byte Protocol (SBCCS); used in FICON.
+ * This decoder is for FC-SB3 version 1.4
+ * Copyright 2003 Dinesh G Dutt (ddutt@cisco.com)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCSB3_H_
+#define __PACKET_FCSB3_H_
+
+/* SB-3 IU Types */
+#define FC_SBCCS_IU_DATA 0x0
+#define FC_SBCCS_IU_CMD_HDR 0x1
+#define FC_SBCCS_IU_STATUS 0x2
+#define FC_SBCCS_IU_CTL 0x3
+#define FC_SBCCS_IU_CMD_DATA 0x4
+#define FC_SBCCS_IU_CMD_LINK_CTL 0x5
+
+/* Control Function Types */
+#define FC_SBCCS_CTL_FN_CTL_END 0x0
+#define FC_SBCCS_CTL_FN_CMD_RSP 0x10
+#define FC_SBCCS_CTL_FN_STK_STS 0x20
+#define FC_SBCCS_CTL_FN_CANCEL 0x30
+#define FC_SBCCS_CTL_FN_SYS_RST 0x40
+#define FC_SBCCS_CTL_FN_SEL_RST 0x50
+#define FC_SBCCS_CTL_FN_REQ_STS 0x70
+#define FC_SBCCS_CTL_FN_DEV_XCP 0x80
+#define FC_SBCCS_CTL_FN_STS_ACC 0xA0
+#define FC_SBCCS_CTL_FN_DEV_ACK 0xB0
+#define FC_SBCCS_CTL_FN_PRG_PTH 0xC1
+#define FC_SBCCS_CTL_FN_PRG_RSP 0xD0
+
+/* Link Control Function Types */
+#define FC_SBCCS_LINK_CTL_FN_ELP 0x41
+#define FC_SBCCS_LINK_CTL_FN_RLP 0x49
+#define FC_SBCCS_LINK_CTL_FN_TIN 0x09
+#define FC_SBCCS_LINK_CTL_FN_LPE 0x51
+#define FC_SBCCS_LINK_CTL_FN_LPR 0x59
+#define FC_SBCCS_LINK_CTL_FN_TIR 0x01
+#define FC_SBCCS_LINK_CTL_FN_LRJ 0x11
+#define FC_SBCCS_LINK_CTL_FN_LBY 0x21
+#define FC_SBCCS_LINK_CTL_FN_LACK 0x61
+
+#define FC_SBCCS_SB3_HDR_SIZE 8
+#define FC_SBCCS_IU_HDR_SIZE 8
+#define FC_SBCCS_DIB_LRC_HDR_SIZE 16
+
+/* Decodes the DIB Type from the IU header and returns type */
+static inline guint get_fc_sbccs_iu_type (tvbuff_t *tvb, guint offset)
+{
+ /* This is in the IUI field of the IU header */
+ return (tvb_get_guint8 (tvb, offset+FC_SBCCS_SB3_HDR_SIZE) & 0x7);
+}
+
+#endif
diff --git a/epan/dissectors/packet-fcsp.c b/epan/dissectors/packet-fcsp.c
new file mode 100644
index 0000000000..df87eea14a
--- /dev/null
+++ b/epan/dissectors/packet-fcsp.c
@@ -0,0 +1,574 @@
+/* packet-fc-sp.c
+ * Routines for Fibre Channel Security Protocol (FC-SP)
+ * This decoder is for FC-SP version 1.1
+ * Copyright 2003, Dinesh G Dutt <ddutt@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include "prefs.h"
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fcsp.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_fcsp = -1;
+static int hf_auth_proto_ver = -1;
+static int hf_auth_msg_code = -1;
+static int hf_auth_flags = -1;
+static int hf_auth_len = -1;
+static int hf_auth_tid = -1;
+static int hf_auth_initiator_wwn = -1;
+static int hf_auth_initiator_name = -1;
+static int hf_auth_usable_proto = -1;
+static int hf_auth_rjt_code = -1;
+static int hf_auth_rjt_codedet = -1;
+static int hf_auth_responder_wwn = -1;
+static int hf_auth_responder_name = -1;
+static int hf_auth_dhchap_groupid = -1;
+static int hf_auth_dhchap_hashid = -1;
+static int hf_auth_dhchap_chal_len = -1;
+static int hf_auth_dhchap_val_len = -1;
+static int hf_auth_dhchap_rsp_len = -1;
+static int hf_auth_initiator_name_type = -1;
+static int hf_auth_initiator_name_len = -1;
+static int hf_auth_responder_name_len = -1;
+static int hf_auth_responder_name_type = -1;
+static int hf_auth_proto_type = -1;
+static int hf_auth_proto_param_len = -1;
+static int hf_auth_dhchap_param_tag = -1;
+static int hf_auth_dhchap_param_len = -1;
+static int hf_auth_dhchap_hash_type = -1;
+static int hf_auth_dhchap_group_type = -1;
+static int hf_auth_dhchap_dhvalue = -1;
+static int hf_auth_dhchap_chal_value = -1;
+static int hf_auth_dhchap_rsp_value = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_fcsp = -1;
+
+static dissector_handle_t data_handle;
+
+static const value_string fcauth_msgcode_vals[] = {
+ {FC_AUTH_MSG_AUTH_REJECT, "AUTH_Reject"},
+ {FC_AUTH_MSG_AUTH_NEGOTIATE, "AUTH_Negotiate"},
+ {FC_AUTH_MSG_AUTH_DONE, "AUTH_Done"},
+ {FC_AUTH_DHCHAP_CHALLENGE, "DHCHAP_Challenge"},
+ {FC_AUTH_DHCHAP_REPLY, "DHCHAP_Reply"},
+ {FC_AUTH_DHCHAP_SUCCESS, "DHCHAP_Success"},
+ {FC_AUTH_FCAP_REQUEST, "FCAP_Request"},
+ {FC_AUTH_FCAP_ACKNOWLEDGE, "FCAP_Acknowledge"},
+ {FC_AUTH_FCAP_CONFIRM, "FCAP_Confirm"},
+ {FC_AUTH_FCPAP_INIT, "FCPAP_Init"},
+ {FC_AUTH_FCPAP_ACCEPT, "FCPAP_Accept"},
+ {FC_AUTH_FCPAP_COMPLETE, "FCPAP_Complete"},
+ {0, NULL},
+};
+
+static const value_string fcauth_rjtcode_vals[] = {
+ {0x01, "Authentication Failure"},
+ {0x02, "Logical Error"},
+ {0, NULL},
+};
+
+static const value_string fcauth_rjtcode_detail_vals[] = {
+ {0x01, "Authentication Mechanism Not Usable"},
+ {0x02, "DH Group Not Usable"},
+ {0x03, "Hash Algorithm Not Usable"},
+ {0x04, "Authentication Protocol Instance Already Started"},
+ {0x05, "Authentication Failed "},
+ {0x06, "Incorrect Payload "},
+ {0x07, "Incorrect Authentication Protocol Message"},
+ {0x08, "Protocol Reset"},
+ {0, NULL},
+};
+
+static const value_string fcauth_dhchap_param_vals[] = {
+ {FC_AUTH_DHCHAP_PARAM_HASHLIST, "HashList"},
+ {FC_AUTH_DHCHAP_PARAM_DHgIDLIST, "DHgIDList"},
+ {0, NULL},
+};
+
+static const value_string fcauth_dhchap_hash_algo_vals[] = {
+ {FC_AUTH_DHCHAP_HASH_MD5, "MD5"},
+ {FC_AUTH_DHCHAP_HASH_SHA1, "SHA-1"},
+ {0, NULL},
+};
+
+static const value_string fcauth_name_type_vals[] = {
+ {FC_AUTH_NAME_TYPE_WWN, "WWN"},
+ {0, NULL},
+};
+
+static const value_string fcauth_proto_type_vals[] = {
+ {FC_AUTH_PROTO_TYPE_DHCHAP, "DHCHAP"},
+ {FC_AUTH_PROTO_TYPE_FCAP, "FCAP"},
+ {0, NULL},
+};
+
+static const value_string fcauth_dhchap_dhgid_vals[] = {
+ {0, "DH NULL"},
+ {1, "DH Group 1024"},
+ {2, "DH Group 1280"},
+ {3, "DH Group 1536"},
+ {4, "DH Group 2048"},
+ {0, NULL},
+};
+
+/* this format is required because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void dissect_fcsp_dhchap_auth_param (tvbuff_t *tvb, proto_tree *tree,
+ int offset, gint32 total_len)
+{
+ guint16 auth_param_tag;
+ guint16 param_len = 0, i;
+
+ if (tree) {
+ auth_param_tag = tvb_get_ntohs (tvb, offset);
+ total_len -= 4;
+
+ while (total_len > 0) {
+ proto_tree_add_item (tree, hf_auth_dhchap_param_tag, tvb, offset,
+ 2, 0);
+ proto_tree_add_item (tree, hf_auth_dhchap_param_len, tvb, offset+2,
+ 2, 0);
+
+ auth_param_tag = tvb_get_ntohs (tvb, offset);
+ param_len = tvb_get_ntohs (tvb, offset+2)*4;
+
+ switch (auth_param_tag) {
+ case FC_AUTH_DHCHAP_PARAM_HASHLIST:
+ offset += 4;
+ total_len -= 4;
+ for (i = 0; i < param_len; i += 4) {
+ proto_tree_add_item (tree, hf_auth_dhchap_hash_type, tvb,
+ offset, 4, 0);
+ offset += 4;
+ }
+ break;
+ case FC_AUTH_DHCHAP_PARAM_DHgIDLIST:
+ offset += 4;
+ total_len -= 4;
+ for (i = 0; i < param_len; i += 4) {
+ proto_tree_add_item (tree, hf_auth_dhchap_group_type, tvb,
+ offset, 4, 0);
+ offset += 4;
+ }
+ break;
+ default:
+ break;
+ }
+
+ total_len -= param_len;
+ }
+ }
+}
+
+void dissect_fcsp_dhchap_challenge (tvbuff_t *tvb, proto_tree *tree)
+{
+ int offset = 12;
+ guint16 name_type;
+ guint16 param_len, name_len;
+
+ if (tree) {
+ proto_tree_add_item (tree, hf_auth_responder_name_type, tvb, offset,
+ 2, 0);
+ name_type = tvb_get_ntohs (tvb, offset);
+
+ proto_tree_add_item (tree, hf_auth_responder_name_len, tvb, offset+2,
+ 2, 0);
+
+ name_len = tvb_get_ntohs (tvb, offset+2);
+
+ if (name_type == FC_AUTH_NAME_TYPE_WWN) {
+ proto_tree_add_string (tree, hf_auth_responder_wwn, tvb, offset+4,
+ 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+4,
+ 8)));
+ }
+ else {
+ proto_tree_add_bytes (tree, hf_auth_responder_name, tvb, offset+4,
+ name_len, tvb_get_ptr (tvb, offset+4, name_len));
+ }
+ offset += (4+name_len);
+
+ proto_tree_add_item (tree, hf_auth_dhchap_hash_type, tvb, offset,
+ 4, 0);
+ proto_tree_add_item (tree, hf_auth_dhchap_group_type, tvb, offset+4,
+ 4, 0);
+ proto_tree_add_item (tree, hf_auth_dhchap_chal_len, tvb, offset+8,
+ 4, 0);
+ param_len = tvb_get_ntohl (tvb, offset+8);
+
+ proto_tree_add_bytes (tree, hf_auth_dhchap_chal_value, tvb, offset+12,
+ param_len,
+ tvb_get_ptr (tvb, offset+12, param_len));
+ offset += (param_len + 12);
+
+ proto_tree_add_item (tree, hf_auth_dhchap_val_len, tvb, offset, 4, 0);
+ param_len = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_bytes (tree, hf_auth_dhchap_dhvalue, tvb, offset+4,
+ param_len,
+ tvb_get_ptr (tvb, offset+4, param_len));
+ }
+}
+
+
+void dissect_fcsp_dhchap_reply (tvbuff_t *tvb, proto_tree *tree)
+{
+ int offset = 12;
+ guint32 param_len;
+
+ if (tree) {
+ proto_tree_add_item (tree, hf_auth_dhchap_rsp_len, tvb, offset, 4, 0);
+ param_len = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_bytes (tree, hf_auth_dhchap_rsp_value, tvb, offset+4,
+ param_len,
+ tvb_get_ptr (tvb, offset+4, param_len));
+ offset += (param_len + 4);
+
+ proto_tree_add_item (tree, hf_auth_dhchap_val_len, tvb, offset, 4, 0);
+ param_len = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_bytes (tree, hf_auth_dhchap_dhvalue, tvb, offset+4,
+ param_len,
+ tvb_get_ptr (tvb, offset+4, param_len));
+ offset += (param_len + 4);
+
+ proto_tree_add_item (tree, hf_auth_dhchap_chal_len, tvb, offset, 4, 0);
+ param_len = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_bytes (tree, hf_auth_dhchap_chal_value, tvb, offset+4,
+ param_len,
+ tvb_get_ptr (tvb, offset+4, param_len));
+ }
+}
+
+void dissect_fcsp_dhchap_success (tvbuff_t *tvb, proto_tree *tree)
+{
+ int offset = 12;
+ guint32 param_len;
+
+ if (tree) {
+ proto_tree_add_item (tree, hf_auth_dhchap_rsp_len, tvb, offset, 4, 0);
+ param_len = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_bytes (tree, hf_auth_dhchap_rsp_value, tvb, offset+4,
+ param_len,
+ tvb_get_ptr (tvb, offset+4, param_len));
+ }
+}
+
+
+void dissect_fcsp_auth_negotiate (tvbuff_t *tvb, proto_tree *tree)
+{
+ int offset = 12;
+ guint16 name_type, name_len, proto_type, param_len;
+ guint32 num_protos, i;
+
+ if (tree) {
+ proto_tree_add_item (tree, hf_auth_initiator_name_type, tvb, offset,
+ 2, 0);
+ name_type = tvb_get_ntohs (tvb, offset);
+
+ proto_tree_add_item (tree, hf_auth_initiator_name_len, tvb, offset+2,
+ 2, 0);
+ name_len = tvb_get_ntohs (tvb, offset+2);
+
+ if (name_type == FC_AUTH_NAME_TYPE_WWN) {
+ proto_tree_add_string (tree, hf_auth_initiator_wwn, tvb, offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
+ }
+ else {
+ proto_tree_add_bytes (tree, hf_auth_initiator_name, tvb, offset+4,
+ name_len, tvb_get_ptr (tvb, offset+4,
+ name_len));
+ }
+
+ offset += (4+name_len);
+
+ proto_tree_add_item (tree, hf_auth_usable_proto, tvb, offset, 4, 0);
+ num_protos = tvb_get_ntohl (tvb, offset);
+ offset += 4;
+
+ for (i = 0; i < num_protos; i++) {
+ proto_tree_add_item (tree, hf_auth_proto_param_len, tvb, offset, 4, 0);
+ param_len = tvb_get_ntohl (tvb, offset);
+ offset += 4;
+
+ if (tvb_bytes_exist (tvb, offset, param_len)) {
+ proto_type = tvb_get_ntohl (tvb, offset);
+
+ proto_tree_add_item (tree, hf_auth_proto_type, tvb, offset, 4, 0);
+ switch (proto_type) {
+ case FC_AUTH_PROTO_TYPE_DHCHAP:
+ dissect_fcsp_dhchap_auth_param (tvb, tree, offset+4, param_len);
+ break;
+ case FC_AUTH_PROTO_TYPE_FCAP:
+ break;
+ default:
+ break;
+ }
+ }
+ offset += param_len;
+ }
+ }
+}
+
+void dissect_fcsp_auth_done (tvbuff_t *tvb _U_, proto_tree *tree _U_)
+{
+}
+
+void dissect_fcsp_auth_rjt (tvbuff_t *tvb, proto_tree *tree)
+{
+ int offset = 12;
+
+ if (tree) {
+ proto_tree_add_item (tree, hf_auth_rjt_code, tvb, offset, 1, 0);
+ proto_tree_add_item (tree, hf_auth_rjt_codedet, tvb, offset+1, 1, 0);
+ }
+}
+
+void dissect_fcsp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti = NULL;
+ guint8 opcode;
+ int offset = 0;
+ proto_tree *fcsp_tree = NULL;
+
+ /* Make entry in the Info column on summary display */
+ opcode = tvb_get_guint8 (tvb, 2);
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_set_str (pinfo->cinfo, COL_INFO,
+ val_to_str (opcode, fcauth_msgcode_vals, "0x%x"));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcsp, tvb, 0,
+ tvb_length (tvb), "FC-SP");
+ fcsp_tree = proto_item_add_subtree (ti, ett_fcsp);
+
+ proto_tree_add_item (fcsp_tree, hf_auth_flags, tvb, offset+1, 1, 0);
+ proto_tree_add_item (fcsp_tree, hf_auth_msg_code, tvb, offset+2, 1, 0);
+ proto_tree_add_item (fcsp_tree, hf_auth_proto_ver, tvb, offset+3, 1,
+ 0);
+ proto_tree_add_item (fcsp_tree, hf_auth_len, tvb, offset+4, 4, 0);
+ proto_tree_add_item (fcsp_tree, hf_auth_tid, tvb, offset+8, 4, 0);
+
+ switch (opcode) {
+ case FC_AUTH_MSG_AUTH_REJECT:
+ dissect_fcsp_auth_rjt (tvb, tree);
+ break;
+ case FC_AUTH_MSG_AUTH_NEGOTIATE:
+ dissect_fcsp_auth_negotiate (tvb, tree);
+ break;
+ case FC_AUTH_MSG_AUTH_DONE:
+ dissect_fcsp_auth_done (tvb, tree);
+ break;
+ case FC_AUTH_DHCHAP_CHALLENGE:
+ dissect_fcsp_dhchap_challenge (tvb, tree);
+ break;
+ case FC_AUTH_DHCHAP_REPLY:
+ dissect_fcsp_dhchap_reply (tvb, tree);
+ break;
+ case FC_AUTH_DHCHAP_SUCCESS:
+ dissect_fcsp_dhchap_success (tvb, tree);
+ break;
+ case FC_AUTH_FCAP_REQUEST:
+ case FC_AUTH_FCAP_ACKNOWLEDGE:
+ case FC_AUTH_FCAP_CONFIRM:
+ case FC_AUTH_FCPAP_INIT:
+ case FC_AUTH_FCPAP_ACCEPT:
+ case FC_AUTH_FCPAP_COMPLETE:
+ proto_tree_add_text (fcsp_tree, tvb, offset+12, tvb_length (tvb),
+ "FCAP Decoding Not Supported");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void
+proto_register_fcsp (void)
+{
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_auth_proto_ver,
+ {"Protocol Version", "fcsp.version", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_auth_msg_code,
+ {"Message Code", "fcsp.opcode", FT_UINT8, BASE_HEX,
+ VALS (fcauth_msgcode_vals), 0x0, "", HFILL}},
+ { &hf_auth_flags,
+ {"Flags", "fcsp.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_auth_len,
+ {"Packet Length", "fcsp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_auth_tid,
+ {"Transaction Identifier", "fcsp.tid", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_auth_initiator_wwn,
+ {"Initiator Name (WWN)", "fcsp.initwwn", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_auth_initiator_name,
+ {"Initiator Name (Unknown Type)", "fcsp.initname", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_auth_initiator_name_type,
+ {"Initiator Name Type", "fcsp.initnametype", FT_UINT16, BASE_HEX,
+ VALS (fcauth_name_type_vals), 0x0, "", HFILL}},
+ { &hf_auth_initiator_name_len,
+ {"Initiator Name Length", "fcsp.initnamelen", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_auth_usable_proto,
+ {"Number of Usable Protocols", "fcsp.usableproto", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_auth_rjt_code,
+ {"Reason Code", "fcsp.rjtcode", FT_UINT8, BASE_DEC,
+ VALS (fcauth_rjtcode_vals), 0x0, "", HFILL}},
+ { &hf_auth_rjt_codedet,
+ {"Reason Code Explanation", "fcsp.rjtcodet", FT_UINT8, BASE_DEC,
+ VALS (fcauth_rjtcode_detail_vals), 0x0, "", HFILL}},
+ { &hf_auth_responder_wwn,
+ {"Responder Name (WWN)", "fcsp.rspwwn", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_auth_responder_name,
+ {"Responder Name (Unknown Type)", "fcsp.rspname", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_auth_responder_name_type,
+ {"Responder Name Type", "fcsp.rspnametype", FT_UINT16, BASE_HEX,
+ VALS (fcauth_name_type_vals), 0x0, "", HFILL}},
+ { &hf_auth_responder_name_len,
+ {"Responder Name Type", "fcsp.rspnamelen", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_auth_dhchap_hashid,
+ {"Hash Identifier", "fcsp.dhchap.hashid", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_auth_dhchap_groupid,
+ {"DH Group Identifier", "fcsp.dhchap.groupid", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_auth_dhchap_chal_len,
+ {"Challenge Value Length", "fcsp.dhchap.challen", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_auth_dhchap_val_len,
+ {"DH Value Length", "fcsp.dhchap.vallen", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_auth_dhchap_rsp_len,
+ {"Response Value Length", "fcsp.dhchap.rsplen", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_auth_proto_type,
+ {"Authentication Protocol Type", "fcsp.proto", FT_UINT32, BASE_DEC,
+ VALS (fcauth_proto_type_vals), 0x0, "", HFILL}},
+ { &hf_auth_proto_param_len,
+ {"Protocol Parameters Length", "fcsp.protoparamlen", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_auth_dhchap_param_tag,
+ {"Parameter Tag", "fcsp.dhchap.paramtype", FT_UINT16, BASE_HEX,
+ VALS (fcauth_dhchap_param_vals), 0x0, "", HFILL}},
+ { &hf_auth_dhchap_param_len,
+ {"Parameter Length", "fcsp.dhchap.paramlen", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_auth_dhchap_hash_type,
+ {"Hash Algorithm", "fcsp.dhchap.hashtype", FT_UINT32, BASE_DEC,
+ VALS (fcauth_dhchap_hash_algo_vals), 0x0, "", HFILL}},
+ { &hf_auth_dhchap_group_type,
+ {"DH Group", "fcsp.dhchap.dhgid", FT_UINT32, BASE_DEC,
+ VALS (fcauth_dhchap_dhgid_vals), 0x0, "", HFILL}},
+ { &hf_auth_dhchap_chal_value,
+ {"Challenge Value", "fcsp.dhchap.chalval", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_auth_dhchap_dhvalue,
+ {"DH Value", "fcsp.dhchap.dhvalue", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_auth_dhchap_rsp_value,
+ {"Response Value", "fcsp.dhchap.rspval", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+
+ };
+
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fcsp,
+ };
+
+ /* Register the protocol name and description */
+ proto_fcsp = proto_register_protocol ("Fibre Channel Security Protocol",
+ "FC-SP", "fcsp");
+
+ register_dissector("fcsp", dissect_fcsp, proto_fcsp);
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fcsp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ data_handle = find_dissector("data");
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fcsp (void)
+{
+ dissector_handle_t fcsp_handle;
+
+ fcsp_handle = create_dissector_handle (dissect_fcsp, proto_fcsp);
+
+ data_handle = find_dissector ("data");
+}
+
diff --git a/epan/dissectors/packet-fcsp.h b/epan/dissectors/packet-fcsp.h
new file mode 100644
index 0000000000..80d1f1f94f
--- /dev/null
+++ b/epan/dissectors/packet-fcsp.h
@@ -0,0 +1,57 @@
+/* packet-fc-sp.h
+ * Routines for Fibre Channel Security Protocol
+ * This decoder is for FC-SP version 1.1
+ * Copyright 2003 Dinesh G Dutt (ddutt@cisco.com)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCSP_H_
+#define __PACKET_FCSP_H_
+
+/* Message Codes */
+#define FC_AUTH_MSG_AUTH_REJECT 0x0A
+#define FC_AUTH_MSG_AUTH_NEGOTIATE 0x0B
+#define FC_AUTH_MSG_AUTH_DONE 0x0C
+#define FC_AUTH_DHCHAP_CHALLENGE 0x10
+#define FC_AUTH_DHCHAP_REPLY 0x11
+#define FC_AUTH_DHCHAP_SUCCESS 0x12
+#define FC_AUTH_FCAP_REQUEST 0x13
+#define FC_AUTH_FCAP_ACKNOWLEDGE 0x14
+#define FC_AUTH_FCAP_CONFIRM 0x15
+#define FC_AUTH_FCPAP_INIT 0x16
+#define FC_AUTH_FCPAP_ACCEPT 0x17
+#define FC_AUTH_FCPAP_COMPLETE 0x18
+
+#define FC_AUTH_NAME_TYPE_WWN 0x1
+
+#define FC_AUTH_PROTO_TYPE_DHCHAP 0x1
+#define FC_AUTH_PROTO_TYPE_FCAP 0x2
+
+#define FC_AUTH_DHCHAP_HASH_MD5 0x5
+#define FC_AUTH_DHCHAP_HASH_SHA1 0x6
+
+#define FC_AUTH_DHCHAP_PARAM_HASHLIST 0x1
+#define FC_AUTH_DHCHAP_PARAM_DHgIDLIST 0x2
+
+void dissect_fcsp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+#endif
diff --git a/epan/dissectors/packet-fcswils.c b/epan/dissectors/packet-fcswils.c
new file mode 100644
index 0000000000..45cf941d37
--- /dev/null
+++ b/epan/dissectors/packet-fcswils.c
@@ -0,0 +1,1923 @@
+/* packet-fcswils
+ * Routines for FC Inter-switch link services
+ * Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-fcswils.h"
+
+#define FC_SWILS_RPLY 0x0
+#define FC_SWILS_REQ 0x1
+#define FC_SWILS_RSCN_DEVENTRY_SIZE 20
+
+/* Zone name has the structure:
+ * name_len (1 byte), rsvd (3 bytes), name (m bytes), fill (n bytes)
+ * name_len excludes the 4 initial bytes before the name
+ */
+#define ZONENAME_LEN(x, y) (tvb_get_guint8(x, y)+4)
+
+/* Initialize the protocol and registered fields */
+static int proto_fcswils = -1;
+static int hf_swils_opcode = -1;
+static int hf_swils_elp_rev = -1;
+static int hf_swils_elp_flags = -1;
+static int hf_swils_elp_r_a_tov = -1;
+static int hf_swils_elp_e_d_tov = -1;
+static int hf_swils_elp_req_epn = -1;
+static int hf_swils_elp_req_esn = -1;
+static int hf_swils_elp_clsf_svcp = -1;
+static int hf_swils_elp_clsf_rcvsz = -1;
+static int hf_swils_elp_clsf_conseq = -1;
+static int hf_swils_elp_clsf_e2e = -1;
+static int hf_swils_elp_clsf_openseq = -1;
+static int hf_swils_elp_cls1_svcp = -1;
+static int hf_swils_elp_cls1_rcvsz = -1;
+static int hf_swils_elp_cls2_svcp = -1;
+static int hf_swils_elp_cls2_rcvsz = -1;
+static int hf_swils_elp_cls3_svcp = -1;
+static int hf_swils_elp_cls3_rcvsz = -1;
+static int hf_swils_elp_isl_fc_mode = -1;
+static int hf_swils_elp_fcplen = -1;
+static int hf_swils_elp_b2bcredit = -1;
+static int hf_swils_elp_compat1 = -1;
+static int hf_swils_elp_compat2 = -1;
+static int hf_swils_elp_compat3 = -1;
+static int hf_swils_elp_compat4 = -1;
+static int hf_swils_efp_rec_type = -1;
+static int hf_swils_efp_dom_id = -1;
+static int hf_swils_efp_switch_name = -1;
+static int hf_swils_efp_mcast_grpno = -1;
+static int hf_swils_efp_alias_token = -1;
+static int hf_swils_efp_payload_len = -1;
+static int hf_swils_efp_pswitch_pri = -1;
+static int hf_swils_efp_pswitch_name = -1;
+static int hf_swils_dia_switch_name = -1;
+static int hf_swils_rdi_payload_len = -1;
+static int hf_swils_rdi_req_sname = -1;
+static int hf_swils_fspfh_cmd = -1;
+static int hf_swils_fspfh_rev = -1;
+static int hf_swils_fspfh_ar_num = -1;
+static int hf_swils_fspfh_auth_type = -1;
+static int hf_swils_fspfh_dom_id = -1;
+static int hf_swils_fspfh_auth = -1;
+static int hf_swils_hlo_options = -1;
+static int hf_swils_hlo_hloint = -1;
+static int hf_swils_hlo_deadint = -1;
+static int hf_swils_hlo_rcv_domid = -1;
+static int hf_swils_hlo_orig_pidx = -1;
+static int hf_swils_ldrec_linkid = -1;
+static int hf_swils_ldrec_out_pidx = -1;
+static int hf_swils_ldrec_nbr_pidx = -1;
+static int hf_swils_ldrec_link_type = -1;
+static int hf_swils_ldrec_link_cost = -1;
+static int hf_swils_lsrh_lsr_type = -1;
+static int hf_swils_lsrh_lsid = -1;
+static int hf_swils_lsrh_adv_domid = -1;
+static int hf_swils_lsrh_ls_incid = -1;
+static int hf_swils_esc_pdesc_vendorid = -1;
+static int hf_swils_esc_swvendorid = -1;
+static int hf_swils_esc_protocolid = -1;
+static int hf_swils_rscn_evtype = -1;
+static int hf_swils_rscn_addrfmt = -1;
+static int hf_swils_rscn_detectfn = -1;
+static int hf_swils_rscn_affectedport = -1;
+static int hf_swils_rscn_portstate = -1;
+static int hf_swils_rscn_portid = -1;
+static int hf_swils_rscn_pwwn = -1;
+static int hf_swils_rscn_nwwn = -1;
+static int hf_swils_zone_activezonenm = -1;
+static int hf_swils_zone_objname = -1;
+static int hf_swils_zone_objtype = -1;
+static int hf_swils_zone_mbrtype = -1;
+static int hf_swils_zone_protocol = -1;
+static int hf_swils_zone_mbrid = -1;
+static int hf_swils_zone_status = -1;
+static int hf_swils_zone_reason = -1;
+static int hf_swils_aca_domainid = -1;
+static int hf_swils_sfc_opcode = -1;
+static int hf_swils_sfc_zonenm = -1;
+static int hf_swils_rjt = -1;
+static int hf_swils_rjtdet = -1;
+static int hf_swils_rjtvendor = -1;
+static int hf_swils_zone_mbrid_lun = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_fcswils = -1;
+static gint ett_fcswils_swacc = -1;
+static gint ett_fcswils_swrjt = -1;
+static gint ett_fcswils_elp = -1;
+static gint ett_fcswils_efp = -1;
+static gint ett_fcswils_efplist = -1;
+static gint ett_fcswils_dia = -1;
+static gint ett_fcswils_rdi = -1;
+static gint ett_fcswils_fspfhdr = -1;
+static gint ett_fcswils_hlo = -1;
+static gint ett_fcswils_lsrec = -1;
+static gint ett_fcswils_lsrechdr = -1;
+static gint ett_fcswils_ldrec = -1;
+static gint ett_fcswils_lsu = -1;
+static gint ett_fcswils_lsa = -1;
+static gint ett_fcswils_bf = -1;
+static gint ett_fcswils_rcf = -1;
+static gint ett_fcswils_rscn = -1;
+static gint ett_fcswils_rscn_dev = -1;
+static gint ett_fcswils_drlir = -1;
+static gint ett_fcswils_mr = -1;
+static gint ett_fcswils_zoneobjlist = -1;
+static gint ett_fcswils_zoneobj = -1;
+static gint ett_fcswils_zonembr = -1;
+static gint ett_fcswils_aca = -1;
+static gint ett_fcswils_rca = -1;
+static gint ett_fcswils_sfc = -1;
+static gint ett_fcswils_ufc = -1;
+static gint ett_fcswils_esc = -1;
+static gint ett_fcswils_esc_pdesc = -1;
+
+static const value_string fc_swils_opcode_key_val[] = {
+ {FC_SWILS_SWRJT , "SW_RJT"},
+ {FC_SWILS_SWACC , "SW_ACC"},
+ {FC_SWILS_ELP , "ELP"},
+ {FC_SWILS_EFP , "EFP"},
+ {FC_SWILS_DIA , "DIA"},
+ {FC_SWILS_RDI , "RDI"},
+ {FC_SWILS_HLO , "HLO"},
+ {FC_SWILS_LSU , "LSU"},
+ {FC_SWILS_LSA , "LSA"},
+ {FC_SWILS_BF , "BF"},
+ {FC_SWILS_RCF , "RCF"},
+ {FC_SWILS_RSCN , "SW_RSCN"},
+ {FC_SWILS_DRLIR , "DRLIR"},
+ {FC_SWILS_DSCN , "DSCN"},
+ {FC_SWILS_LOOPD , "LOOPD"},
+ {FC_SWILS_MR , "MR"},
+ {FC_SWILS_ACA , "ACA"},
+ {FC_SWILS_RCA , "RCA"},
+ {FC_SWILS_SFC , "SFC"},
+ {FC_SWILS_UFC , "UFC"},
+ {FC_SWILS_ESC , "ESC"},
+ {FC_SWILS_AUTH_ILS, "AUTH_ILS"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_rjt_val [] = {
+ {FC_SWILS_RJT_INVCODE , "Invalid Cmd Code"},
+ {FC_SWILS_RJT_INVVER , "Invalid Revision"},
+ {FC_SWILS_RJT_LOGERR , "Logical Error"},
+ {FC_SWILS_RJT_INVSIZE , "Invalid Size"},
+ {FC_SWILS_RJT_LOGBSY , "Logical Busy"},
+ {FC_SWILS_RJT_PROTERR , "Protocol Error"},
+ {FC_SWILS_RJT_GENFAIL , "Unable to Perform"},
+ {FC_SWILS_RJT_CMDNOTSUPP, "Unsupported Cmd"},
+ {FC_SWILS_RJT_VENDUNIQ , "Vendor Unique Err"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_deterr_val [] = {
+ {FC_SWILS_RJT_NODET , "No Additional Details"},
+ {FC_SWILS_RJT_CLSF_ERR , "Class F Svc Param Err"},
+ {FC_SWILS_RJT_CLSN_ERR , "Class N Svc Param Err"},
+ {FC_SWILS_RJT_INVFC_CODE , "Unknown Flow Ctrl Code"},
+ {FC_SWILS_RJT_INVFC_PARM , "Invalid Flow Ctrl Parm"},
+ {FC_SWILS_RJT_INV_PNAME , "Invalid Port Name"},
+ {FC_SWILS_RJT_INV_SNAME , "Invalid Switch Name"},
+ {FC_SWILS_RJT_TOV_MSMTCH , "R_A_/E_D_TOV Mismatch"},
+ {FC_SWILS_RJT_INV_DIDLST, "Invalid Domain ID List"},
+ {FC_SWILS_RJT_CMD_INPROG , "Cmd Already in Progress"},
+ {FC_SWILS_RJT_OORSRC , "Insufficient Resources"},
+ {FC_SWILS_RJT_NO_DID , "Domain ID Unavailable"},
+ {FC_SWILS_RJT_INV_DID, "Invalid Domain ID"},
+ {FC_SWILS_RJT_NO_REQ , "Request Not Supported"},
+ {FC_SWILS_RJT_NOLNK_PARM , "Link Parm Not Estd."},
+ {FC_SWILS_RJT_NO_REQDID , "Group of Domain IDs Unavail"},
+ {FC_SWILS_RJT_EP_ISOL , "E_Port Isolated"},
+ {0, NULL}
+};
+
+static const value_string fcswils_elp_fc_val[] = {
+ {FC_SWILS_ELP_FC_VENDOR, "Vendor Unique"},
+ {FC_SWILS_ELP_FC_RRDY, "R_RDY Flow Ctrl"},
+ {0, NULL},
+};
+
+static const value_string fcswils_rectype_val[] = {
+ {FC_SWILS_LRECTYPE_DOMAIN, "Domain ID List Rec"},
+ {FC_SWILS_LRECTYPE_MCAST, "Multicast ID List Rec"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_link_type_val[] = {
+ {0x01, "P2P Link"},
+ {0xF0, "Vendor Specific"},
+ {0xF1, "Vendor Specific"},
+ {0xF2, "Vendor Specific"},
+ {0xF3, "Vendor Specific"},
+ {0xF4, "Vendor Specific"},
+ {0xF5, "Vendor Specific"},
+ {0xF6, "Vendor Specific"},
+ {0xF7, "Vendor Specific"},
+ {0xF8, "Vendor Specific"},
+ {0xF9, "Vendor Specific"},
+ {0xFA, "Vendor Specific"},
+ {0xFB, "Vendor Specific"},
+ {0xFC, "Vendor Specific"},
+ {0xFD, "Vendor Specific"},
+ {0xFE, "Vendor Specific"},
+ {0xFF, "Vendor Specific"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_fspf_linkrec_val[] = {
+ {FC_SWILS_LSR_SLR, "Switch Link Record"},
+ {FC_SWILS_LSR_ARS, "AR Summary Record"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_fspf_lsrflags_val[] = {
+ {0x0, "LSR is for a Topology Update"},
+ {0x1, "LSR is for Initial DB Sync | Not the last seq in DB sync"},
+ {0x2, "Last Seq in DB Sync. LSU has no LSRs"},
+ {0x3, "LSR is for Initial DB Sync | Last Seq in DB Sync"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_rscn_portstate_val[] = {
+ {0, "No Additional Info"},
+ {1, "Port is online"},
+ {2, "Port is offline"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_rscn_addrfmt_val[] = {
+ {0, "Port Addr Format"},
+ {1, "Area Addr Format"},
+ {2, "Domain Addr Format"},
+ {3, "Fabric Addr Format"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_rscn_detectfn_val[] = {
+ {1, "Fabric Detected"},
+ {2, "N_Port Detected"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_esc_protocol_val[] = {
+ {0, "Reserved"},
+ {1, "FSPF-Backbone Protocol"},
+ {2, "FSPF Protocol"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_zoneobj_type_val[] = {
+ {0, "Reserved"},
+ {FC_SWILS_ZONEOBJ_ZONESET , "Zone Set"},
+ {FC_SWILS_ZONEOBJ_ZONE , "Zone"},
+ {FC_SWILS_ZONEOBJ_ZONEALIAS, "Zone Alias"},
+ {0, NULL},
+};
+
+const value_string fc_swils_zonembr_type_val[] = {
+ {0, "Reserved"},
+ {FC_SWILS_ZONEMBR_WWN, "WWN"},
+ {FC_SWILS_ZONEMBR_DP, "Domain/Physical Port (0x00ddpppp)"},
+ {FC_SWILS_ZONEMBR_FCID, "FC Address"},
+ {FC_SWILS_ZONEMBR_ALIAS, "Zone Alias"},
+ {FC_SWILS_ZONEMBR_WWN_LUN, "WWN+LUN"},
+ {FC_SWILS_ZONEMBR_DP_LUN, "Domain/Physical Port+LUN"},
+ {FC_SWILS_ZONEMBR_FCID_LUN, "FCID+LUN"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_mr_rsp_val[] = {
+ {0, "Successful"},
+ {1, "Fabric Busy"},
+ {2, "Failed"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_mr_reason_val[] = {
+ {0x0, "No Reason"},
+ {0x1, "Invalid Data Length"},
+ {0x2, "Unsupported Command"},
+ {0x3, "Reserved"},
+ {0x4, "Not Authorized"},
+ {0x5, "Invalid Request"},
+ {0x6, "Fabric Changing"},
+ {0x7, "Update Not Staged"},
+ {0x8, "Invalid Zone Set Format"},
+ {0x9, "Invalid Data"},
+ {0xA, "Cannot Merge"},
+ {0, NULL},
+};
+
+static const value_string fc_swils_sfc_op_val[] = {
+ {0, "Reserved"},
+ {1, "Reserved"},
+ {2, "Reserved"},
+ {3, "Activate Zone Set"},
+ {4, "Deactivate Zone Set"},
+ {0, NULL},
+};
+
+typedef struct _zonename {
+ guint32 namelen:8,
+ rsvd:24;
+ gchar *name;
+ gchar *pad;
+} zonename_t;
+
+typedef struct _fcswils_conv_key {
+ guint32 conv_idx;
+} fcswils_conv_key_t;
+
+typedef struct _fcswils_conv_data {
+ guint32 opcode;
+} fcswils_conv_data_t;
+
+GHashTable *fcswils_req_hash = NULL;
+GMemChunk *fcswils_req_keys = NULL;
+GMemChunk *fcswils_req_vals = NULL;
+guint32 fcswils_init_count = 25;
+
+static dissector_handle_t data_handle, fcsp_handle;
+
+static gint get_zoneobj_len (tvbuff_t *tvb, gint offset);
+
+/*
+ * Hash Functions
+ */
+static gint
+fcswils_equal(gconstpointer v, gconstpointer w)
+{
+ fcswils_conv_key_t *v1 = (fcswils_conv_key_t *)v;
+ fcswils_conv_key_t *v2 = (fcswils_conv_key_t *)w;
+
+ return (v1->conv_idx == v2->conv_idx);
+}
+
+static guint
+fcswils_hash (gconstpointer v)
+{
+ fcswils_conv_key_t *key = (fcswils_conv_key_t *)v;
+ guint val;
+
+ val = key->conv_idx;
+
+ return val;
+}
+
+/*
+ * Protocol initialization
+ */
+static void
+fcswils_init_protocol(void)
+{
+ if (fcswils_req_keys)
+ g_mem_chunk_destroy (fcswils_req_keys);
+ if (fcswils_req_vals)
+ g_mem_chunk_destroy (fcswils_req_vals);
+ if (fcswils_req_hash)
+ g_hash_table_destroy (fcswils_req_hash);
+
+ fcswils_req_hash = g_hash_table_new(fcswils_hash, fcswils_equal);
+ fcswils_req_keys = g_mem_chunk_new("fcswils_req_keys",
+ sizeof(fcswils_conv_key_t),
+ fcswils_init_count * sizeof(fcswils_conv_key_t),
+ G_ALLOC_AND_FREE);
+ fcswils_req_vals = g_mem_chunk_new("fcswils_req_vals",
+ sizeof(fcswils_conv_data_t),
+ fcswils_init_count * sizeof(fcswils_conv_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+static gchar *
+zonenm_to_str (tvbuff_t *tvb, gint offset)
+{
+ int len = tvb_get_guint8 (tvb, offset);
+ return ((gchar *)tvb_get_ptr (tvb, offset+4, len));
+}
+
+/* Offset points to the start of the zone object */
+static gint
+get_zoneobj_len (tvbuff_t *tvb, gint offset)
+{
+ gint numrec, numrec1;
+ guint8 objtype;
+ gint i, j, len;
+
+ /* zone object structure is:
+ * type (1 byte), protocol (1 byte), rsvd (2 bytes), obj name (x bytes),
+ * num of zone mbrs (4 bytes ), list of zone members (each member if of
+ * variable length).
+ *
+ * zone member structure is:
+ * type (1 byte), rsvd (1 byte), flags (1 byte), id_len (1 byte),
+ * id (id_len bytes)
+ */
+ objtype = tvb_get_guint8 (tvb, offset);
+ len = 4 + ZONENAME_LEN (tvb, offset+4); /* length upto num_of_mbrs field */
+ numrec = tvb_get_ntohl (tvb, offset+len); /* gets us num of zone mbrs */
+
+ len += 4; /* + num_mbrs */
+ for (i = 0; i < numrec; i++) {
+ if (objtype == FC_SWILS_ZONEOBJ_ZONESET) {
+ len += 4 + ZONENAME_LEN (tvb, offset+4+len); /* length upto num_of_mbrs field */
+ numrec1 = tvb_get_ntohl (tvb, offset+len);
+
+ len += 4;
+ for (j = 0; j < numrec1; j++) {
+ len += 4 + tvb_get_guint8 (tvb, offset+3+len);
+ }
+ }
+ else if (objtype == FC_SWILS_ZONEOBJ_ZONE) {
+ len += 4 + tvb_get_guint8 (tvb, offset+3+len);
+ }
+ }
+
+ return len;
+}
+
+static void
+dissect_swils_elp (tvbuff_t *tvb, proto_tree *elp_tree, guint8 isreq _U_)
+{
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0,
+ stroff = 0;
+ gchar flags[40];
+ fcswils_elp elp;
+
+ /* Response i.e. SW_ACC for an ELP has the same format as the request */
+ /* We skip the initial 4 bytes as we don't care about the opcode */
+ tvb_memcpy (tvb, (guint8 *)&elp, 4, FC_SWILS_ELP_SIZE);
+
+ elp.r_a_tov = ntohl (elp.r_a_tov);
+ elp.e_d_tov = ntohl (elp.e_d_tov);
+ elp.isl_flwctrl_mode = ntohs (elp.isl_flwctrl_mode);
+ elp.flw_ctrl_parmlen = ntohs (elp.flw_ctrl_parmlen);
+
+ if (elp_tree) {
+ offset += 4;
+ proto_tree_add_item (elp_tree, hf_swils_elp_rev, tvb, offset++, 1, 0);
+ proto_tree_add_item (elp_tree, hf_swils_elp_flags, tvb, offset, 2, 0);
+ offset += 3;
+ proto_tree_add_uint_format (elp_tree, hf_swils_elp_r_a_tov, tvb, offset, 4,
+ elp.r_a_tov, "R_A_TOV: %d msecs", elp.r_a_tov);
+ offset += 4;
+ proto_tree_add_uint_format (elp_tree, hf_swils_elp_e_d_tov, tvb, offset, 4,
+ elp.e_d_tov, "E_D_TOV: %d msecs", elp.e_d_tov);
+ offset += 4;
+ proto_tree_add_string (elp_tree, hf_swils_elp_req_epn, tvb, offset, 8,
+ fcwwn_to_str (elp.req_epname));
+ offset += 8;
+ proto_tree_add_string (elp_tree, hf_swils_elp_req_esn, tvb, offset, 8,
+ fcwwn_to_str (elp.req_sname));
+ offset += 8;
+
+ flags[0] = '\0';
+ if (elp.clsf_svcparm[0] & 0x80) {
+ strcpy (flags, "Class F Valid");
+
+ if (elp.clsf_svcparm[4] & 0x20) {
+ strcpy (&flags[13], " | X_ID Interlock");
+ }
+ else {
+ strcpy (&flags[13], " | No X_ID Interlk");
+ }
+ }
+ else {
+ strcpy (flags, "Class F Invld");
+ }
+ proto_tree_add_bytes_format (elp_tree, hf_swils_elp_clsf_svcp, tvb, offset, 6,
+ &elp.clsf_svcparm[0], "Class F Svc Parameters: (%s)", flags);
+ offset += 6;
+
+ proto_tree_add_item (elp_tree, hf_swils_elp_clsf_rcvsz, tvb, offset, 2, 0);
+ offset += 2;
+ proto_tree_add_item (elp_tree, hf_swils_elp_clsf_conseq, tvb, offset, 2, 0);
+ offset += 2;
+ proto_tree_add_item (elp_tree, hf_swils_elp_clsf_e2e, tvb, offset, 2, 0);
+ offset += 2;
+ proto_tree_add_item (elp_tree, hf_swils_elp_clsf_openseq, tvb, offset, 2, 0);
+ offset += 4;
+
+ flags[0] = '\0';
+ stroff = 0;
+ if (elp.cls1_svcparm[0] & 0x80) {
+ strcpy (&flags[stroff], "Class 1 Valid");
+ stroff += 13;
+ if (elp.cls1_svcparm[0] & 0x40) {
+ strcpy (&flags[stroff], " | IMX");
+ stroff += 6;
+ }
+ if (elp.cls1_svcparm[0] & 0x20) {
+ strcpy (&flags[stroff], " | XPS");
+ stroff += 6;
+ }
+ if (elp.cls1_svcparm[0] & 0x10) {
+ strcpy (&flags[stroff], " | LKS");
+ }
+ }
+ else {
+ strcpy (&flags[0], "Class 1 Invalid");
+ }
+
+ proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls1_svcp, tvb, offset, 2,
+ tvb_get_ptr (tvb, offset, 2),
+ "Class 1 Svc Parameters: (%s)", flags);
+ offset += 2;
+ if (elp.cls1_svcparm[0] & 0x80) {
+ proto_tree_add_item (elp_tree, hf_swils_elp_cls1_rcvsz, tvb, offset, 2, 0);
+ }
+ offset += 2;
+
+ flags[0] = '\0';
+ if (elp.cls2_svcparm[0] & 0x80) {
+ strcpy (flags, "Class 2 Valid");
+
+ if (elp.cls2_svcparm[0] & 0x08) {
+ strcpy (&flags[13], " | Seq Delivery");
+ }
+ else {
+ strcpy (&flags[13], " | No Seq Delivery");
+ }
+ }
+ else {
+ strcpy (flags, "Class 2 Invld");
+ }
+
+ proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls2_svcp, tvb, offset, 2,
+ &elp.cls2_svcparm[0],
+ "Class 2 Svc Parameters: (%s)", flags);
+ offset += 2;
+
+ if (elp.cls2_svcparm[0] & 0x80) {
+ proto_tree_add_item (elp_tree, hf_swils_elp_cls2_rcvsz, tvb, offset, 2, 0);
+ }
+ offset += 2;
+
+ flags[0] = '\0';
+ if (elp.cls3_svcparm[0] & 0x80) {
+ strcpy (flags, "Class 3 Valid");
+
+ if (elp.cls3_svcparm[0] & 0x08) {
+ strcpy (&flags[13], " | Seq Delivery");
+ }
+ else {
+ strcpy (&flags[13], " | No Seq Delivery");
+ }
+ }
+ else {
+ strcpy (flags, "Class 3 Invld");
+ }
+ proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls3_svcp, tvb, offset, 2,
+ &elp.cls3_svcparm[0],
+ "Class 3 Svc Parameters: (%s)", flags);
+ offset += 2;
+
+ if (elp.cls3_svcparm[0] & 0x80) {
+ proto_tree_add_item (elp_tree, hf_swils_elp_cls3_rcvsz, tvb, offset, 2, 0);
+ }
+ offset += 22;
+
+ proto_tree_add_string (elp_tree, hf_swils_elp_isl_fc_mode, tvb, offset, 2,
+ val_to_str (elp.isl_flwctrl_mode, fcswils_elp_fc_val, "Vendor Unique"));
+ offset += 2;
+ proto_tree_add_item (elp_tree, hf_swils_elp_fcplen, tvb, offset, 2, 0);
+ offset += 2;
+ proto_tree_add_item (elp_tree, hf_swils_elp_b2bcredit, tvb, offset, 4, 0);
+ offset += 4;
+ proto_tree_add_item (elp_tree, hf_swils_elp_compat1, tvb, offset, 4, 0);
+ offset += 4;
+ proto_tree_add_item (elp_tree, hf_swils_elp_compat2, tvb, offset, 4, 0);
+ offset += 4;
+ proto_tree_add_item (elp_tree, hf_swils_elp_compat3, tvb, offset, 4, 0);
+ offset += 4;
+ proto_tree_add_item (elp_tree, hf_swils_elp_compat4, tvb, offset, 4, 0);
+ }
+
+}
+
+static void
+dissect_swils_efp (tvbuff_t *tvb, proto_tree *efp_tree, guint8 isreq _U_)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *subti;
+ proto_tree *lrec_tree;
+ int num_listrec = 0,
+ offset = 0;
+ fcswils_efp efp;
+ fcswils_efp_listrec *lrec;
+
+ tvb_memcpy (tvb, (guint8 *)&efp, offset, FC_SWILS_EFP_SIZE);
+ efp.payload_len = ntohs (efp.payload_len);
+ efp.listrec = (fcswils_efp_listrec *)tvb_get_ptr (tvb, FC_SWILS_EFP_SIZE,
+ efp.payload_len - FC_SWILS_EFP_SIZE);
+
+ if (efp_tree) {
+ offset += 2;
+ proto_tree_add_item (efp_tree, hf_swils_efp_payload_len, tvb, offset, 2, 0);
+ offset += 5;
+ proto_tree_add_item (efp_tree, hf_swils_efp_pswitch_pri, tvb,
+ offset++, 1, 0);
+ proto_tree_add_string (efp_tree, hf_swils_efp_pswitch_name, tvb, offset,
+ 8, fcwwn_to_str (efp.pswitch_name));
+ offset += 8;
+
+ /* Add List Records now */
+ if (efp.reclen) {
+ num_listrec = (efp.payload_len - FC_SWILS_EFP_SIZE)/efp.reclen;
+ }
+ else {
+ num_listrec = 0;
+ }
+
+ while (num_listrec--) {
+ lrec = (fcswils_efp_listrec *)tvb_get_ptr (tvb, offset, efp.reclen);
+ if (lrec != NULL) {
+ if (lrec->didrec.rec_type == FC_SWILS_LRECTYPE_DOMAIN) {
+ subti = proto_tree_add_text (efp_tree, tvb, offset,
+ (efp.payload_len - FC_SWILS_EFP_SIZE),
+ "Domain ID Record");
+ lrec_tree = proto_item_add_subtree (subti, ett_fcswils_efplist);
+ proto_tree_add_item (lrec_tree, hf_swils_efp_dom_id, tvb, offset+1, 1, 0);
+ proto_tree_add_string (lrec_tree, hf_swils_efp_switch_name, tvb, offset+8, 8,
+ fcwwn_to_str (lrec->didrec.sname));
+ }
+ else if (lrec->didrec.rec_type == FC_SWILS_LRECTYPE_MCAST) {
+ subti = proto_tree_add_text (efp_tree, tvb, offset,
+ (efp.payload_len - FC_SWILS_EFP_SIZE),
+ "Multicast ID Record");
+ lrec_tree = proto_item_add_subtree (subti, ett_fcswils_efplist);
+ proto_tree_add_item (lrec_tree, hf_swils_efp_mcast_grpno, tvb, offset+1, 1, 0);
+ }
+ offset += efp.reclen;
+ }
+ }
+ }
+}
+
+static void
+dissect_swils_dia (tvbuff_t *tvb, proto_tree *dia_tree, guint8 isreq _U_)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+
+ if (dia_tree) {
+ proto_tree_add_string (dia_tree, hf_swils_dia_switch_name, tvb, offset+4,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
+ }
+}
+
+static void
+dissect_swils_rdi (tvbuff_t *tvb, proto_tree *rdi_tree, guint8 isreq)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ int i, plen, numrec;
+
+ if (rdi_tree) {
+ plen = tvb_get_ntohs (tvb, offset+2);
+
+ proto_tree_add_item (rdi_tree, hf_swils_rdi_payload_len, tvb, offset+2, 2, 0);
+ proto_tree_add_string (rdi_tree, hf_swils_rdi_req_sname, tvb, offset+4,
+ 8, fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
+
+ /* 12 is the length of the initial header and 4 is the size of each
+ * domain request record.
+ */
+ numrec = (plen - 12)/4;
+ offset = 12;
+ for (i = 0; i < numrec; i++) {
+ if (isreq) {
+ proto_tree_add_text (rdi_tree, tvb, offset+3, 1,
+ "Requested Domain ID: %d",
+ tvb_get_guint8 (tvb, offset+3));
+ }
+ else {
+ proto_tree_add_text (rdi_tree, tvb, offset+3, 1,
+ "Granted Domain ID: %d",
+ tvb_get_guint8 (tvb, offset+3));
+ }
+ offset += 4;
+ }
+ }
+}
+
+static void
+dissect_swils_fspf_hdr (tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ proto_item *subti;
+ proto_tree *fspfh_tree;
+
+ if (tree) {
+ /* 20 is the size of FSPF header */
+ subti = proto_tree_add_text (tree, tvb, offset, 20, "FSPF Header");
+ fspfh_tree = proto_item_add_subtree (subti, ett_fcswils_fspfhdr);
+
+ proto_tree_add_item (fspfh_tree, hf_swils_fspfh_rev, tvb, offset+4,
+ 1, 0);
+ proto_tree_add_item (fspfh_tree, hf_swils_fspfh_ar_num, tvb,
+ offset+5, 1, 0);
+ proto_tree_add_item (fspfh_tree, hf_swils_fspfh_auth_type, tvb,
+ offset+6, 1, 0);
+ proto_tree_add_item (fspfh_tree, hf_swils_fspfh_dom_id, tvb, offset+11,
+ 1, 0);
+ proto_tree_add_item (fspfh_tree, hf_swils_fspfh_auth, tvb, offset+12,
+ 8, 0);
+ }
+}
+
+static void
+dissect_swils_fspf_lsrechdr (tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ proto_tree_add_item (tree, hf_swils_lsrh_lsr_type, tvb, offset, 1, 0);
+ proto_tree_add_text (tree, tvb, offset+2, 2, "LSR Age: %d secs",
+ tvb_get_ntohs (tvb, offset+2));
+ proto_tree_add_text (tree, tvb, offset+4, 4, "Options : 0x%x",
+ tvb_get_ntohl (tvb, offset+4));
+ proto_tree_add_item (tree, hf_swils_lsrh_lsid, tvb, offset+11, 1, 0);
+ proto_tree_add_item (tree, hf_swils_lsrh_adv_domid, tvb, offset+15, 1, 0);
+ proto_tree_add_item (tree, hf_swils_lsrh_ls_incid, tvb, offset+16, 4, 0);
+ proto_tree_add_text (tree, tvb, offset+20, 2, "Checksum: 0x%x",
+ tvb_get_ntohs (tvb, offset+20));
+ proto_tree_add_text (tree, tvb, offset+22, 2, "LSR Length: %d",
+ tvb_get_ntohs (tvb, offset+22));
+}
+
+static void
+dissect_swils_fspf_ldrec (tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ proto_tree_add_string (tree, hf_swils_ldrec_linkid, tvb, offset, 4,
+ fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
+ proto_tree_add_item (tree, hf_swils_ldrec_out_pidx, tvb, offset+5, 3, 0);
+ proto_tree_add_item (tree, hf_swils_ldrec_nbr_pidx, tvb, offset+9, 3, 0);
+ proto_tree_add_item (tree, hf_swils_ldrec_link_type, tvb, offset+12, 1, 0);
+ proto_tree_add_item (tree, hf_swils_ldrec_link_cost, tvb, offset+14, 2, 0);
+}
+
+static void
+dissect_swils_fspf_lsrec (tvbuff_t *tvb, proto_tree *tree, int offset,
+ int num_lsrec)
+{
+ int i, j, num_ldrec;
+ proto_item *subti1, *subti;
+ proto_tree *lsrec_tree, *ldrec_tree, *lsrechdr_tree;
+
+ if (tree) {
+ for (j = 0; j < num_lsrec; j++) {
+ num_ldrec = tvb_get_ntohs (tvb, offset+26);
+ subti = proto_tree_add_text (tree, tvb, offset, (28+num_ldrec*16),
+ "Link State Record %d (Domain %d)", j,
+ tvb_get_guint8 (tvb, offset+15));
+ lsrec_tree = proto_item_add_subtree (subti, ett_fcswils_lsrec);
+
+ subti = proto_tree_add_text (lsrec_tree, tvb, offset, 24,
+ "Link State Record Header");
+ lsrechdr_tree = proto_item_add_subtree (subti,
+ ett_fcswils_lsrechdr);
+
+ dissect_swils_fspf_lsrechdr (tvb, lsrechdr_tree, offset);
+ proto_tree_add_text (tree, tvb, offset+26, 2, "Number of Links: %d",
+ num_ldrec);
+ offset += 28;
+
+ for (i = 0; i < num_ldrec; i++) {
+ subti1 = proto_tree_add_text (lsrec_tree, tvb, offset, 16,
+ "Link Descriptor %d "
+ "(Neighbor domain %d)", i,
+ tvb_get_guint8 (tvb, offset+3));
+ ldrec_tree = proto_item_add_subtree (subti1, ett_fcswils_ldrec);
+ dissect_swils_fspf_ldrec (tvb, ldrec_tree, offset);
+ offset += 16;
+ }
+ }
+ }
+}
+
+static void
+dissect_swils_hello (tvbuff_t *tvb, proto_tree *hlo_tree, guint8 isreq _U_)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+
+ if (hlo_tree) {
+ dissect_swils_fspf_hdr (tvb, hlo_tree, offset);
+
+ proto_tree_add_item (hlo_tree, hf_swils_hlo_options, tvb, offset+20, 4, 0);
+ proto_tree_add_item (hlo_tree, hf_swils_hlo_hloint, tvb, offset+24, 4, 0);
+ proto_tree_add_item (hlo_tree, hf_swils_hlo_deadint, tvb, offset+28, 4, 0);
+ proto_tree_add_item (hlo_tree, hf_swils_hlo_rcv_domid, tvb, offset+35, 1, 0);
+ proto_tree_add_item (hlo_tree, hf_swils_hlo_orig_pidx, tvb, offset+37, 3, 0);
+ }
+}
+
+static void
+dissect_swils_lsupdate (tvbuff_t *tvb, proto_tree *lsu_tree, guint8 isreq _U_)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ int num_lsrec;
+
+ if (lsu_tree) {
+ dissect_swils_fspf_hdr (tvb, lsu_tree, offset);
+
+ proto_tree_add_text (lsu_tree, tvb, offset+23, 1, "Flags : %s",
+ val_to_str (tvb_get_guint8 (tvb, offset+23),
+ fc_swils_fspf_lsrflags_val, "0x%x"));
+ num_lsrec = tvb_get_ntohl (tvb, offset+24);
+
+ proto_tree_add_text (lsu_tree, tvb, offset+24, 4, "Num of LSRs: %d",
+ num_lsrec);
+
+ offset = 28;
+ dissect_swils_fspf_lsrec (tvb, lsu_tree, offset, num_lsrec);
+ }
+}
+
+static void
+dissect_swils_lsack (tvbuff_t *tvb, proto_tree *lsa_tree, guint8 isreq _U_)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ int num_lsrechdr, i;
+ proto_item *subti;
+ proto_tree *lsrechdr_tree;
+
+ if (lsa_tree) {
+ dissect_swils_fspf_hdr (tvb, lsa_tree, offset);
+
+ proto_tree_add_text (lsa_tree, tvb, offset+23, 1, "Flags : %s",
+ val_to_str (tvb_get_guint8 (tvb, offset+23),
+ fc_swils_fspf_lsrflags_val, "0x%x"));
+ num_lsrechdr = tvb_get_ntohl (tvb, offset+24);
+
+ proto_tree_add_text (lsa_tree, tvb, offset+24, 4, "Num of LSR Headers: %d",
+ num_lsrechdr);
+
+ offset = 28;
+
+ for (i = 0; i < num_lsrechdr; i++) {
+ subti = proto_tree_add_text (lsa_tree, tvb, offset, 24,
+ "Link State Record Header (Domain %d)",
+ tvb_get_guint8 (tvb, offset+15));
+ lsrechdr_tree = proto_item_add_subtree (subti,
+ ett_fcswils_lsrechdr);
+ dissect_swils_fspf_lsrechdr (tvb, lsrechdr_tree, offset);
+ offset += 24;
+ }
+ }
+}
+
+static void
+dissect_swils_rscn (tvbuff_t *tvb, proto_tree *rscn_tree, guint8 isreq)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ proto_tree *dev_tree;
+ int addrfmt, evtype;
+ int numrec, i;
+ proto_item *subti;
+
+ if (rscn_tree) {
+ if (!isreq)
+ return;
+
+ evtype = tvb_get_guint8 (tvb, offset+4);
+ addrfmt = evtype & 0x0F;
+ evtype = evtype >> 4;
+
+ proto_tree_add_item (rscn_tree, hf_swils_rscn_evtype, tvb, offset+4,
+ 1, 0);
+ proto_tree_add_item (rscn_tree, hf_swils_rscn_addrfmt, tvb, offset+4,
+ 1, 0);
+ proto_tree_add_string (rscn_tree, hf_swils_rscn_affectedport, tvb,
+ offset+5, 3, fc_to_str (tvb_get_ptr (tvb,
+ offset+5, 3)));
+ proto_tree_add_item (rscn_tree, hf_swils_rscn_detectfn, tvb,
+ offset+8, 4, 0);
+ numrec = tvb_get_ntohl (tvb, offset+12);
+
+ if (!tvb_bytes_exist (tvb, offset+16, FC_SWILS_RSCN_DEVENTRY_SIZE*numrec)) {
+ /* Some older devices do not include device entry information. */
+ return;
+ }
+
+ proto_tree_add_text (rscn_tree, tvb, offset+12, 4, "Num Entries: %d",
+ numrec);
+
+ offset = 16;
+ for (i = 0; i < numrec; i++) {
+ subti = proto_tree_add_text (rscn_tree, tvb, offset, 20,
+ "Device Entry %d", i);
+ dev_tree = proto_item_add_subtree (rscn_tree, ett_fcswils_rscn_dev);
+
+ proto_tree_add_item (dev_tree, hf_swils_rscn_portstate, tvb, offset, 1, 0);
+ proto_tree_add_string (dev_tree, hf_swils_rscn_portid, tvb, offset+1, 3,
+ fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
+ proto_tree_add_string (dev_tree, hf_swils_rscn_pwwn, tvb, offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
+ proto_tree_add_string (dev_tree, hf_swils_rscn_nwwn, tvb, offset+12, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+12, 8)));
+ offset += 20;
+ }
+ }
+}
+
+/*
+ * Merge Request contains zoning objects organized in the following format:
+ *
+ * Zone Set Object
+ * |
+ * +---------------- Zone Object
+ * | |
+ * +-- +---------------- Zone Member
+ * | | |
+ * +-- +---- +-----
+ *
+ * So the decoding of the zone merge request is based on this structure
+ */
+
+static void
+dissect_swils_zone_mbr (tvbuff_t *tvb, proto_tree *zmbr_tree, int offset)
+{
+ int mbrlen = 4 + tvb_get_guint8 (tvb, offset+3);
+
+ proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrtype, tvb,
+ offset, 1, 0);
+ proto_tree_add_text (zmbr_tree, tvb, offset+2, 1, "Flags: 0x%x",
+ tvb_get_guint8 (tvb, offset+2));
+ proto_tree_add_text (zmbr_tree, tvb, offset+3, 1,
+ "Identifier Length: %d",
+ tvb_get_guint8 (tvb, offset+3));
+ switch (tvb_get_guint8 (tvb, offset)) {
+ case FC_SWILS_ZONEMBR_WWN:
+ proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 8)));
+ break;
+ case FC_SWILS_ZONEMBR_DP:
+ proto_tree_add_string_format (zmbr_tree,
+ hf_swils_zone_mbrid,
+ tvb, offset+4, 4, " ",
+ "0x%x",
+ tvb_get_ntohl (tvb,
+ offset+4));
+ break;
+ case FC_SWILS_ZONEMBR_FCID:
+ proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
+ offset+4, 4,
+ fc_to_str (tvb_get_ptr (tvb,
+ offset+5,
+ 3)));
+ break;
+ case FC_SWILS_ZONEMBR_ALIAS:
+ proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
+ offset+4,
+ tvb_get_guint8 (tvb, offset+3),
+ zonenm_to_str (tvb, offset+4));
+ break;
+ case FC_SWILS_ZONEMBR_WWN_LUN:
+ proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
+ offset+4, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb,
+ offset+4,
+ 8)));
+ proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
+ offset+12, 8, 0);
+ break;
+ case FC_SWILS_ZONEMBR_DP_LUN:
+ proto_tree_add_string_format (zmbr_tree,
+ hf_swils_zone_mbrid,
+ tvb, offset+4, 4, " ",
+ "0x%x",
+ tvb_get_ntohl (tvb,
+ offset+4));
+ proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
+ offset+8, 8, 0);
+ break;
+ case FC_SWILS_ZONEMBR_FCID_LUN:
+ proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
+ offset+4, 4,
+ fc_to_str (tvb_get_ptr (tvb,
+ offset+5,
+ 3)));
+ proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
+ offset+8, 8, 0);
+ break;
+ default:
+ proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
+ offset+4, mbrlen,
+ "Unknown member type format");
+
+ }
+}
+
+static void
+dissect_swils_zone_obj (tvbuff_t *tvb, proto_tree *zobj_tree, int offset)
+{
+ proto_tree *zmbr_tree;
+ int mbrlen, numrec, i, objtype;
+ proto_item *subti;
+
+ objtype = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_item (zobj_tree, hf_swils_zone_objtype, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (zobj_tree, hf_swils_zone_protocol, tvb,
+ offset+1, 1, 0);
+ proto_tree_add_string (zobj_tree, hf_swils_zone_objname, tvb,
+ offset+4, ZONENAME_LEN (tvb, offset+4),
+ zonenm_to_str (tvb, offset+4));
+
+ numrec = tvb_get_ntohl (tvb, offset+4+ZONENAME_LEN (tvb, offset+4));
+ proto_tree_add_text (zobj_tree, tvb,
+ offset+4+ZONENAME_LEN (tvb, offset+4), 4,
+ "Number of Zone Members: %d", numrec);
+
+ offset += 8 + ZONENAME_LEN (tvb, offset+4);
+ for (i = 0; i < numrec; i++) {
+ if (objtype == FC_SWILS_ZONEOBJ_ZONESET) {
+ dissect_swils_zone_obj (tvb, zobj_tree, offset);
+ offset += get_zoneobj_len (tvb, offset);
+ }
+ else {
+ mbrlen = 4 + tvb_get_guint8 (tvb, offset+3);
+ subti = proto_tree_add_text (zobj_tree, tvb, offset, mbrlen,
+ "Zone Member %d", i);
+ zmbr_tree = proto_item_add_subtree (zobj_tree,
+ ett_fcswils_zonembr);
+ dissect_swils_zone_mbr (tvb, zmbr_tree, offset);
+ offset += mbrlen;
+ }
+ }
+}
+
+static void
+dissect_swils_mergereq (tvbuff_t *tvb, proto_tree *mr_tree, guint8 isreq)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ proto_tree *zobjlist_tree, *zobj_tree;
+ int numrec, i, zonesetlen, objlistlen, objlen;
+ proto_item *subti;
+
+ if (mr_tree) {
+ if (isreq) {
+ /* zonesetlen is the size of the zoneset including the zone name */
+ zonesetlen = tvb_get_ntohs (tvb, offset+2);
+ proto_tree_add_text (mr_tree, tvb, offset+2, 2,
+ "Active ZoneSet Length: %d", zonesetlen);
+
+ if (zonesetlen) {
+ proto_tree_add_string (mr_tree, hf_swils_zone_activezonenm, tvb,
+ offset+4, ZONENAME_LEN (tvb, offset+4),
+ zonenm_to_str (tvb, offset+4));
+
+ /* objlistlen gives the size of the active zoneset object list */
+ objlistlen = zonesetlen - ZONENAME_LEN (tvb, offset+4);
+ /* Offset = start of the active zoneset zoning object list */
+ offset = offset + (4 + ZONENAME_LEN (tvb, offset+4));
+ numrec = tvb_get_ntohl (tvb, offset);
+
+ subti = proto_tree_add_text (mr_tree, tvb, offset, objlistlen,
+ "Active Zone Set");
+ zobjlist_tree = proto_item_add_subtree (subti,
+ ett_fcswils_zoneobjlist);
+
+ proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
+ "Number of zoning objects: %d", numrec);
+
+ offset += 4;
+ for (i = 0; i < numrec; i++) {
+ objlen = get_zoneobj_len (tvb, offset);
+ subti = proto_tree_add_text (zobjlist_tree, tvb, offset+4,
+ objlen, "Zone Object %d", i);
+ zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
+ dissect_swils_zone_obj (tvb, zobj_tree, offset);
+ offset += objlen;
+ }
+ }
+ else {
+ offset += 4;
+ }
+
+ zonesetlen = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_text (mr_tree, tvb, offset, 4,
+ "Full Zone Set Length: %d", zonesetlen);
+
+ if (zonesetlen) {
+ objlistlen = zonesetlen;
+ /* Offset = start of the active zoneset zoning object list */
+ offset += 4;
+ numrec = tvb_get_ntohl (tvb, offset);
+
+ subti = proto_tree_add_text (mr_tree, tvb, offset, objlistlen,
+ "Full Zone Set");
+
+ zobjlist_tree = proto_item_add_subtree (subti,
+ ett_fcswils_zoneobjlist);
+ proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
+ "Number of zoning objects: %d", numrec);
+ offset += 4;
+ for (i = 0; i < numrec; i++) {
+ objlen = get_zoneobj_len (tvb, offset);
+ subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
+ objlen, "Zone Object %d", i);
+ zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
+ dissect_swils_zone_obj (tvb, zobj_tree, offset);
+ offset += objlen;
+ }
+ }
+ }
+ else {
+ proto_tree_add_item (mr_tree, hf_swils_zone_status, tvb,
+ offset+5, 1, 0);
+ proto_tree_add_item (mr_tree, hf_swils_zone_reason, tvb,
+ offset+6, 1, 0);
+ proto_tree_add_text (mr_tree, tvb, offset+7, 1,
+ "Vendor Unique: 0x%x",
+ tvb_get_guint8 (tvb, offset+7));
+ }
+ }
+}
+
+static void
+dissect_swils_aca (tvbuff_t *tvb, proto_tree *aca_tree, guint8 isreq)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ int numrec, plen, i;
+
+ if (aca_tree) {
+ if (isreq) {
+ plen = tvb_get_ntohs (tvb, offset+2);
+ proto_tree_add_text (aca_tree, tvb, offset+2, 2,
+ "Domain ID List Length: %d", plen);
+ numrec = plen/4;
+ offset = 4;
+
+ for (i = 0; i < numrec; i++) {
+ proto_tree_add_uint_format (aca_tree, hf_swils_aca_domainid,
+ tvb, offset+3, 1,
+ tvb_get_guint8 (tvb, offset+3),
+ "Domain ID %d: %d", i,
+ tvb_get_guint8 (tvb, offset+3));
+ offset += 4;
+ }
+ }
+ else {
+ proto_tree_add_item (aca_tree, hf_swils_zone_status, tvb,
+ offset+5, 1, 0);
+ proto_tree_add_item (aca_tree, hf_swils_zone_reason, tvb,
+ offset+6, 1, 0);
+ proto_tree_add_text (aca_tree, tvb, offset+7, 1,
+ "Vendor Unique: 0x%x",
+ tvb_get_guint8 (tvb, offset+7));
+ }
+ }
+}
+
+static void
+dissect_swils_rca (tvbuff_t *tvb, proto_tree *rca_tree, guint8 isreq)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+
+ if (rca_tree) {
+ if (!isreq) {
+ proto_tree_add_item (rca_tree, hf_swils_zone_status, tvb,
+ offset+5, 1, 0);
+ proto_tree_add_item (rca_tree, hf_swils_zone_reason, tvb,
+ offset+6, 1, 0);
+ proto_tree_add_text (rca_tree, tvb, offset+7, 1,
+ "Vendor Unique: 0x%x",
+ tvb_get_guint8 (tvb, offset+7));
+ }
+ }
+}
+
+static void
+dissect_swils_sfc (tvbuff_t *tvb, proto_tree *sfc_tree, guint8 isreq)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ proto_tree *zobjlist_tree, *zobj_tree;
+ int numrec, i, zonesetlen, objlistlen, objlen;
+ proto_item *subti;
+
+ if (sfc_tree) {
+ if (isreq) {
+ proto_tree_add_item (sfc_tree, hf_swils_sfc_opcode, tvb, offset+1, 1, 0);
+
+ zonesetlen = tvb_get_ntohs (tvb, offset+2);
+ proto_tree_add_text (sfc_tree, tvb, offset+2, 2,
+ "ZoneSet Length: %d", zonesetlen);
+
+ if (zonesetlen) {
+ proto_tree_add_string (sfc_tree, hf_swils_sfc_zonenm, tvb,
+ offset+4, ZONENAME_LEN (tvb, offset+4),
+ zonenm_to_str (tvb, offset+4));
+
+ /* objlistlen gives the size of the active zoneset object list */
+ objlistlen = zonesetlen - ZONENAME_LEN (tvb, offset+4);
+ /* Offset = start of the active zoneset zoning object list */
+ offset = offset + (4 + ZONENAME_LEN (tvb, offset+4));
+ numrec = tvb_get_ntohl (tvb, offset);
+
+ subti = proto_tree_add_text (sfc_tree, tvb, offset, objlistlen,
+ "Zone Set");
+ zobjlist_tree = proto_item_add_subtree (subti,
+ ett_fcswils_zoneobjlist);
+
+ proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
+ "Number of zoning objects: %d", numrec);
+
+ offset += 4;
+ for (i = 0; i < numrec; i++) {
+ objlen = get_zoneobj_len (tvb, offset);
+ subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
+ objlen, "Zone Object %d", i);
+ zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
+ dissect_swils_zone_obj (tvb, zobj_tree, offset);
+ offset += objlen;
+ }
+ }
+ else {
+ offset += 4;
+ }
+
+ zonesetlen = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_text (sfc_tree, tvb, offset, 4,
+ "Full Zone Set Length: %d", zonesetlen);
+
+ if (zonesetlen) {
+ objlistlen = zonesetlen;
+ /* Offset = start of the active zoneset zoning object list */
+ offset += 4;
+ numrec = tvb_get_ntohl (tvb, offset);
+
+ subti = proto_tree_add_text (sfc_tree, tvb, offset, objlistlen,
+ "Full Zone Set");
+
+ zobjlist_tree = proto_item_add_subtree (subti,
+ ett_fcswils_zoneobjlist);
+ proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
+ "Number of zoning objects: %d", numrec);
+ offset += 4;
+ for (i = 0; i < numrec; i++) {
+ objlen = get_zoneobj_len (tvb, offset);
+ subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
+ objlen, "Zone Object %d", i);
+ zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
+ dissect_swils_zone_obj (tvb, zobj_tree, offset);
+ offset += objlen;
+ }
+ }
+ }
+ else {
+ proto_tree_add_item (sfc_tree, hf_swils_zone_status, tvb,
+ offset+5, 1, 0);
+ proto_tree_add_item (sfc_tree, hf_swils_zone_reason, tvb,
+ offset+6, 1, 0);
+ proto_tree_add_text (sfc_tree, tvb, offset+7, 1,
+ "Vendor Unique: 0x%x",
+ tvb_get_guint8 (tvb, offset+7));
+ }
+ }
+}
+
+static void
+dissect_swils_ufc (tvbuff_t *tvb, proto_tree *ufc_tree, guint8 isreq)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+
+ if (ufc_tree) {
+ if (!isreq) {
+ proto_tree_add_item (ufc_tree, hf_swils_zone_status, tvb,
+ offset+5, 1, 0);
+ proto_tree_add_item (ufc_tree, hf_swils_zone_reason, tvb,
+ offset+6, 1, 0);
+ proto_tree_add_text (ufc_tree, tvb, offset+7, 1,
+ "Vendor Unique: 0x%x",
+ tvb_get_guint8 (tvb, offset+7));
+ }
+ }
+}
+
+static void
+dissect_swils_esc (tvbuff_t *tvb, proto_tree *esc_tree, guint8 isreq)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+ int i, numrec, plen;
+ proto_tree *pdesc_tree;
+ proto_item *subti;
+
+ if (esc_tree) {
+ if (isreq) {
+ plen = tvb_get_ntohs (tvb, offset+2);
+ proto_tree_add_text (esc_tree, tvb, offset+2, 2,
+ "Payload Length: %d", plen);
+ proto_tree_add_item (esc_tree, hf_swils_esc_swvendorid, tvb,
+ offset+4, 8, 0);
+ numrec = (plen - 12)/12;
+ offset = 12;
+
+ for (i = 0; i < numrec; i++) {
+ subti = proto_tree_add_text (esc_tree, tvb, offset, 12,
+ "Protocol Descriptor %d", i);
+ pdesc_tree = proto_item_add_subtree (subti,
+ ett_fcswils_esc_pdesc);
+ proto_tree_add_item (pdesc_tree, hf_swils_esc_pdesc_vendorid, tvb,
+ offset, 8, 0);
+ proto_tree_add_item (pdesc_tree, hf_swils_esc_protocolid,
+ tvb, offset+10, 2, 0);
+ offset += 12;
+ }
+ }
+ else {
+ proto_tree_add_item (esc_tree, hf_swils_esc_swvendorid, tvb,
+ offset+4, 8, 0);
+ subti = proto_tree_add_text (esc_tree, tvb, offset+12, 12,
+ "Accepted Protocol Descriptor");
+ pdesc_tree = proto_item_add_subtree (subti, ett_fcswils_esc_pdesc);
+
+ proto_tree_add_item (pdesc_tree, hf_swils_esc_pdesc_vendorid, tvb,
+ offset+12, 8, 0);
+ proto_tree_add_item (pdesc_tree, hf_swils_esc_protocolid,
+ tvb, offset+22, 2, 0);
+ }
+ }
+}
+
+static void
+dissect_swils_drlir (tvbuff_t *tvb _U_, proto_tree *drlir_tree _U_,
+ guint8 isreq _U_)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ return;
+}
+
+static void
+dissect_swils_swrjt (tvbuff_t *tvb, proto_tree *swrjt_tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ int offset = 0;
+
+ if (swrjt_tree) {
+ proto_tree_add_item (swrjt_tree, hf_swils_rjt, tvb, offset+5, 1, 0);
+ proto_tree_add_item (swrjt_tree, hf_swils_rjtdet, tvb, offset+6, 1, 0);
+ proto_tree_add_item (swrjt_tree, hf_swils_rjtvendor, tvb, offset+7,
+ 1, 0);
+ }
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_fcswils (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti = NULL;
+ guint8 opcode,
+ failed_opcode = 0;
+ int offset = 0;
+ conversation_t *conversation;
+ fcswils_conv_data_t *cdata;
+ fcswils_conv_key_t ckey, *req_key;
+ proto_tree *swils_tree = NULL;
+ guint8 isreq = FC_SWILS_REQ;
+ tvbuff_t *next_tvb;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SW_ILS");
+
+ /* decoding of this is done by each individual opcode handler */
+ opcode = tvb_get_guint8 (tvb, 0);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_fcswils, tvb, 0,
+ tvb_length (tvb), "SW_ILS");
+ swils_tree = proto_item_add_subtree (ti, ett_fcswils);
+ }
+
+ /* Register conversation if this is not a response */
+ if ((opcode != FC_SWILS_SWACC) && (opcode != FC_SWILS_SWRJT)) {
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ if (!conversation) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ }
+
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcswils_conv_data_t *)g_hash_table_lookup (fcswils_req_hash,
+ &ckey);
+ if (cdata) {
+ /* Since we never free the memory used by an exchange, this maybe a
+ * case of another request using the same exchange as a previous
+ * req.
+ */
+ cdata->opcode = opcode;
+ }
+ else {
+ req_key = g_mem_chunk_alloc (fcswils_req_keys);
+ req_key->conv_idx = conversation->index;
+
+ cdata = g_mem_chunk_alloc (fcswils_req_vals);
+ cdata->opcode = opcode;
+
+ g_hash_table_insert (fcswils_req_hash, req_key, cdata);
+ }
+ }
+ else {
+ /* Opcode is ACC or RJT */
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->oxid,
+ pinfo->rxid, NO_PORT2);
+ isreq = FC_SWILS_RPLY;
+ if (!conversation) {
+ if (tree && (opcode == FC_SWILS_SWACC)) {
+ /* No record of what this accept is for. Can't decode */
+ proto_tree_add_text (swils_tree, tvb, 0, tvb_length (tvb),
+ "No record of Exchg. Unable to decode SW_ACC");
+ return;
+ }
+ }
+ else {
+ ckey.conv_idx = conversation->index;
+
+ cdata = (fcswils_conv_data_t *)g_hash_table_lookup (fcswils_req_hash, &ckey);
+
+ if (cdata != NULL) {
+ if (opcode == FC_SWILS_SWACC)
+ opcode = cdata->opcode;
+ else
+ failed_opcode = cdata->opcode;
+ }
+
+ if (tree) {
+ if ((cdata == NULL) && (opcode != FC_SWILS_SWRJT)) {
+ /* No record of what this accept is for. Can't decode */
+ proto_tree_add_text (swils_tree, tvb, 0, tvb_length (tvb),
+ "No record of SW_ILS Req. Unable to decode SW_ACC");
+ return;
+ }
+ }
+ }
+ }
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if (isreq == FC_SWILS_REQ) {
+ col_add_str (pinfo->cinfo, COL_INFO,
+ val_to_str (opcode, fc_swils_opcode_key_val, "0x%x"));
+ }
+ else if (opcode == FC_SWILS_SWRJT) {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "SW_RJT (%s)",
+ val_to_str (failed_opcode, fc_swils_opcode_key_val, "0x%x"));
+ }
+ else {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "SW_ACC (%s)",
+ val_to_str (opcode, fc_swils_opcode_key_val, "0x%x"));
+ }
+ }
+
+ if (tree) {
+ proto_tree_add_item (swils_tree, hf_swils_opcode, tvb, offset, 1, 0);
+ }
+
+ switch (opcode) {
+ case FC_SWILS_SWRJT:
+ dissect_swils_swrjt (tvb, swils_tree);
+ break;
+ case FC_SWILS_ELP:
+ dissect_swils_elp (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_EFP:
+ dissect_swils_efp (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_DIA:
+ dissect_swils_dia (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_RDI:
+ dissect_swils_rdi (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_HLO:
+ dissect_swils_hello (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_LSU:
+ dissect_swils_lsupdate (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_LSA:
+ dissect_swils_lsack (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_BF:
+ case FC_SWILS_RCF:
+ /* Nothing to be displayed for these two commands */
+ break;
+ case FC_SWILS_RSCN:
+ dissect_swils_rscn (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_DRLIR:
+ dissect_swils_drlir (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_MR:
+ dissect_swils_mergereq (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_ACA:
+ dissect_swils_aca (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_RCA:
+ dissect_swils_rca (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_SFC:
+ dissect_swils_sfc (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_UFC:
+ dissect_swils_ufc (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_ESC:
+ dissect_swils_esc (tvb, swils_tree, isreq);
+ break;
+ case FC_SWILS_AUTH_ILS:
+ if (isreq && fcsp_handle)
+ call_dissector (fcsp_handle, tvb, pinfo, swils_tree);
+ break;
+ default:
+ next_tvb = tvb_new_subset (tvb, offset+4, -1, -1);
+ call_dissector (data_handle, next_tvb, pinfo, tree);
+ }
+
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_fcswils (void)
+{
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_swils_opcode,
+ {"Cmd Code", "swils.opcode", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_opcode_key_val), 0x0, "", HFILL}},
+ { &hf_swils_elp_rev,
+ {"Revision", "swils.elp.rev", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_flags,
+ {"Flag", "swils.elp.flag", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_swils_elp_r_a_tov,
+ {"R_A_TOV", "swils.elp.ratov", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_e_d_tov,
+ {"E_D_TOV", "swils.elp.edtov", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_swils_elp_req_epn,
+ {"Req Eport Name", "swils.elp.reqepn", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_elp_req_esn,
+ {"Req Switch Name", "swils.elp.reqesn", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_elp_clsf_svcp,
+ {"Class F Svc Param", "swils.elp.clsfp", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_elp_clsf_rcvsz,
+ {"Max Class F Frame Size", "swils.elp.clsfrsz", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_elp_clsf_conseq,
+ {"Class F Max Concurrent Seq", "swils.elp.clsfcs", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_elp_clsf_e2e,
+ {"Class F E2E Credit", "swils.elp.cfe2e", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_clsf_openseq,
+ {"Class F Max Open Seq", "swils.elp.oseq", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_cls1_svcp,
+ {"Class 1 Svc Param", "swils.elp.cls1p", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_elp_cls1_rcvsz,
+ {"Class 1 Frame Size", "swils.elp.cls1rsz", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_cls2_svcp,
+ {"Class 2 Svc Param", "swils.elp.cls2p", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_elp_cls2_rcvsz,
+ {"Class 2 Frame Size", "swils.elp.cls1rsz", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_cls3_svcp,
+ {"Class 3 Svc Param", "swils.elp.cls3p", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_elp_cls3_rcvsz,
+ {"Class 3 Frame Size", "swils.elp.cls1rsz", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_isl_fc_mode,
+ {"ISL Flow Ctrl Mode", "swils.elp.fcmode", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_fcplen,
+ {"Flow Ctrl Param Len", "swils.elp.fcplen", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_b2bcredit,
+ {"B2B Credit", "swils.elp.b2b", FT_UINT32, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_swils_elp_compat1,
+ {"Compatability Param 1", "swils.elp.compat1", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_compat2,
+ {"Compatability Param 2", "swils.elp.compat2", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_compat3,
+ {"Compatability Param 3", "swils.elp.compat3", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_elp_compat4,
+ {"Compatability Param 4", "swils.elp.compat4", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_efp_rec_type,
+ {"Record Type", "swils.efp.rectype", FT_UINT8, BASE_HEX,
+ VALS (fcswils_rectype_val), 0x0, "", HFILL}},
+ { &hf_swils_efp_dom_id,
+ {"Domain ID", "swils.efp.domid", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_efp_switch_name,
+ {"Switch Name", "swils.efp.sname", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_efp_mcast_grpno,
+ {"Mcast Grp#", "swils.efp.mcastno", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_efp_alias_token,
+ {"Alias Token", "swils.efp.aliastok", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_efp_payload_len,
+ {"Payload Len", "swils.efp.payloadlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_efp_pswitch_pri,
+ {"Principal Switch Priority", "swils.efp.psprio", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_efp_pswitch_name,
+ {"Principal Switch Name", "swils.efp.psname", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_dia_switch_name,
+ {"Switch Name", "swils.dia.sname", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_rdi_payload_len,
+ {"Payload Len", "swils.rdi.len", FT_UINT16, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_swils_rdi_req_sname,
+ {"Req Switch Name", "swils.rdi.reqsn", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_fspfh_cmd,
+ {"Command: ", "swils.fspf.cmd", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_fspfh_rev,
+ {"Version", "swils.fspf.ver", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_swils_fspfh_ar_num,
+ {"AR Number", "swils.fspf.arnum", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_swils_fspfh_auth_type,
+ {"Authentication Type", "swils.fspf.authtype", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_fspfh_dom_id,
+ {"Originating Domain ID", "swils.fspf.origdomid", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_fspfh_auth,
+ {"Authentication", "swils.fspf.auth", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_hlo_options,
+ {"Options", "swils.hlo.options", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_hlo_hloint,
+ {"Hello Interval (secs)", "swils.hlo.hloint", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_hlo_deadint,
+ {"Dead Interval (secs)", "swils.hlo.deadint", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_hlo_rcv_domid,
+ {"Recipient Domain ID", "swils.hlo.rcvdomid", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_hlo_orig_pidx,
+ {"Originating Port Idx", "swils.hlo.origpidx", FT_UINT24, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_lsrh_lsr_type,
+ {"LSR Type", "swils.lsr.type", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_fspf_linkrec_val), 0x0, "", HFILL}},
+ { &hf_swils_lsrh_lsid,
+ {"Link State Id", "swils.ls.id", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_lsrh_adv_domid,
+ {"Advertising Domain Id", "swils.lsr.advdomid", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_lsrh_ls_incid,
+ {"LS Incarnation Number", "swils.lsr.incid", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_ldrec_linkid,
+ {"Link ID", "swils.ldr.linkid", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_ldrec_out_pidx,
+ {"Output Port Idx", "swils.ldr.out_portidx", FT_UINT24, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_ldrec_nbr_pidx,
+ {"Neighbor Port Idx", "swils.ldr.nbr_portidx", FT_UINT24, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_ldrec_link_type,
+ {"Link Type", "swils.ldr.linktype", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_link_type_val), 0x0, "", HFILL}},
+ { &hf_swils_ldrec_link_cost,
+ {"Link Cost", "swils.ldr.linkcost", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_rscn_evtype,
+ {"Event Type", "swils.rscn.evtype", FT_UINT8, BASE_DEC,
+ VALS (fc_swils_rscn_portstate_val), 0xF0, "", HFILL}},
+ { &hf_swils_rscn_addrfmt,
+ {"Address Format", "swils.rscn.addrfmt", FT_UINT8, BASE_DEC,
+ VALS (fc_swils_rscn_addrfmt_val), 0x0F, "", HFILL}},
+ { &hf_swils_rscn_affectedport,
+ {"Affected Port ID", "swils.rscn.affectedport", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_rscn_detectfn,
+ {"Detection Function", "swils.rscn.detectfn", FT_UINT32, BASE_HEX,
+ VALS (fc_swils_rscn_detectfn_val), 0x0, "", HFILL}},
+ { &hf_swils_rscn_portstate,
+ {"Port State", "swils.rscn.portstate", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_rscn_portid,
+ {"Port Id", "swils.rscn.portid", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_swils_rscn_pwwn,
+ {"Port WWN", "swils.rscn.pwwn", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_swils_rscn_nwwn,
+ {"Node WWN", "swils.rscn.nwwn", FT_STRING, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_swils_esc_swvendorid,
+ {"Switch Vendor ID", "swils.esc.swvendor", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_esc_pdesc_vendorid,
+ {"Vendor ID", "swils.esc.vendorid", FT_STRING, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_swils_esc_protocolid,
+ {"Protocol ID", "swils.esc.protocol", FT_UINT16, BASE_HEX,
+ VALS (fc_swils_esc_protocol_val), 0x0, "", HFILL}},
+ { &hf_swils_zone_activezonenm,
+ {"Active Zoneset Name", "swils.mr.activezonesetname", FT_STRING,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_swils_zone_objname,
+ {"Zone Object Name", "swils.zone.zoneobjname", FT_STRING, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_zone_objtype,
+ {"Zone Object Type", "swils.zone.zoneobjtype", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_zoneobj_type_val), 0x0, "", HFILL}},
+ { &hf_swils_zone_mbrtype,
+ {"Zone Member Type", "swils.zone.mbrtype", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_zonembr_type_val), 0x0, "", HFILL}},
+ { &hf_swils_zone_protocol,
+ {"Zone Protocol", "swils.zone.protocol", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_zone_mbrid,
+ {"Member Identifier", "swils.zone.mbrid", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_zone_status,
+ {"Zone Command Status", "swils.zone.status", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_mr_rsp_val), 0x0, "Applies to MR, ACA, RCA, SFC, UFC",
+ HFILL}},
+ { &hf_swils_zone_reason,
+ {"Zone Command Reason Code", "swils.zone.reason", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_mr_reason_val), 0x0, "Applies to MR, ACA, RCA, SFC, UFC",
+ HFILL}},
+ { &hf_swils_aca_domainid,
+ {"Known Domain ID", "swils.aca.domainid", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_sfc_opcode,
+ {"Operation Request", "swils.sfc.opcode", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_sfc_op_val), 0x0, "", HFILL}},
+ { &hf_swils_sfc_zonenm,
+ {"Zone Set Name", "swils.sfc.zonename", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_swils_rjt,
+ {"Reason Code", "swils.rjt.reason", FT_UINT8, BASE_HEX,
+ VALS (fc_swils_rjt_val), 0x0, "", HFILL}},
+ { &hf_swils_rjtdet,
+ {"Reason Code Explanantion", "swils.rjt.reasonexpl", FT_UINT8,
+ BASE_HEX, VALS (fc_swils_deterr_val), 0x0, "", HFILL}},
+ { &hf_swils_rjtvendor,
+ {"Vendor Unique Error Code", "swils.rjt.vendor", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_swils_zone_mbrid_lun,
+ {"LUN", "swils.zone.lun", FT_BYTES, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fcswils,
+ &ett_fcswils_swacc,
+ &ett_fcswils_swrjt,
+ &ett_fcswils_elp,
+ &ett_fcswils_efp,
+ &ett_fcswils_efplist,
+ &ett_fcswils_dia,
+ &ett_fcswils_rdi,
+ &ett_fcswils_fspfhdr,
+ &ett_fcswils_hlo,
+ &ett_fcswils_lsrec,
+ &ett_fcswils_lsrechdr,
+ &ett_fcswils_ldrec,
+ &ett_fcswils_lsu,
+ &ett_fcswils_lsa,
+ &ett_fcswils_bf,
+ &ett_fcswils_rcf,
+ &ett_fcswils_rscn,
+ &ett_fcswils_rscn_dev,
+ &ett_fcswils_drlir,
+ &ett_fcswils_mr,
+ &ett_fcswils_zoneobjlist,
+ &ett_fcswils_zoneobj,
+ &ett_fcswils_zonembr,
+ &ett_fcswils_aca,
+ &ett_fcswils_rca,
+ &ett_fcswils_sfc,
+ &ett_fcswils_ufc,
+ &ett_fcswils_esc,
+ &ett_fcswils_esc_pdesc,
+ };
+
+ /* Register the protocol name and description */
+ proto_fcswils = proto_register_protocol("Fibre Channel SW_ILS", "FC-SWILS", "swils");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fcswils, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&fcswils_init_protocol);
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fcswils (void)
+{
+ dissector_handle_t swils_handle;
+
+ swils_handle = create_dissector_handle (dissect_fcswils, proto_fcswils);
+ dissector_add("fc.ftype", FC_FTYPE_SWILS, swils_handle);
+
+ data_handle = find_dissector ("data");
+ fcsp_handle = find_dissector ("fcsp");
+}
+
+
diff --git a/epan/dissectors/packet-fcswils.h b/epan/dissectors/packet-fcswils.h
new file mode 100644
index 0000000000..729bf4092d
--- /dev/null
+++ b/epan/dissectors/packet-fcswils.h
@@ -0,0 +1,181 @@
+/* packet-fcswils.h
+ * Fibre Channel Switch InterLink Services Definitions
+ * Copyright 2001 Dinesh G Dutt (ddutt@cisco.com)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FCSWILS_H_
+#define __PACKET_FCSWILS_H_
+
+/* Command codes */
+#define FC_SWILS_SWRJT 0x01
+#define FC_SWILS_SWACC 0x02
+#define FC_SWILS_ELP 0x10
+#define FC_SWILS_EFP 0x11
+#define FC_SWILS_DIA 0x12
+#define FC_SWILS_RDI 0x13
+#define FC_SWILS_HLO 0x14
+#define FC_SWILS_LSU 0x15
+#define FC_SWILS_LSA 0x16
+#define FC_SWILS_BF 0x17
+#define FC_SWILS_RCF 0x18
+#define FC_SWILS_RSCN 0x1B
+#define FC_SWILS_DRLIR 0x1E
+#define FC_SWILS_DSCN 0x20
+#define FC_SWILS_LOOPD 0x21
+#define FC_SWILS_MR 0x22
+#define FC_SWILS_ACA 0x23
+#define FC_SWILS_RCA 0x24
+#define FC_SWILS_SFC 0x25
+#define FC_SWILS_UFC 0x26
+#define FC_SWILS_ESC 0x30
+#define FC_SWILS_AUTH_ILS 0x40
+
+/* Reject reason codes */
+
+#define FC_SWILS_RJT_INVCODE 0x01
+#define FC_SWILS_RJT_INVVER 0x02
+#define FC_SWILS_RJT_LOGERR 0x03
+#define FC_SWILS_RJT_INVSIZE 0x04
+#define FC_SWILS_RJT_LOGBSY 0x05
+#define FC_SWILS_RJT_PROTERR 0x07
+#define FC_SWILS_RJT_GENFAIL 0x09
+#define FC_SWILS_RJT_CMDNOTSUPP 0x0B
+#define FC_SWILS_RJT_VENDUNIQ 0xFF
+
+/* Detailed reason code defines */
+#define FC_SWILS_RJT_NODET 0x0
+#define FC_SWILS_RJT_CLSF_ERR 0x1
+#define FC_SWILS_RJT_CLSN_ERR 0x3
+#define FC_SWILS_RJT_INVFC_CODE 0x4
+#define FC_SWILS_RJT_INVFC_PARM 0x5
+#define FC_SWILS_RJT_INV_PNAME 0xD
+#define FC_SWILS_RJT_INV_SNAME 0xE
+#define FC_SWILS_RJT_TOV_MSMTCH 0xF
+#define FC_SWILS_RJT_INV_DIDLST 0x10
+#define FC_SWILS_RJT_CMD_INPROG 0x19
+#define FC_SWILS_RJT_OORSRC 0x29
+#define FC_SWILS_RJT_NO_DID 0x2A
+#define FC_SWILS_RJT_INV_DID 0x2B
+#define FC_SWILS_RJT_NO_REQ 0x2C
+#define FC_SWILS_RJT_NOLNK_PARM 0x2D
+#define FC_SWILS_RJT_NO_REQDID 0x2E
+#define FC_SWILS_RJT_EP_ISOL 0x2F
+
+typedef struct _fcswils_elp {
+ guint8 revision;
+ guint8 flags[2];
+ guint8 rsvd1;
+ guint32 r_a_tov;
+ guint32 e_d_tov;
+ guint8 req_epname[8];
+ guint8 req_sname[8];
+ guint8 clsf_svcparm[6];
+ guint16 clsf_rcvsize;
+ guint16 clsf_conseq;
+ guint16 clsf_e2e;
+ guint16 clsf_openseq;
+ guint16 rsvd;
+ guint8 cls1_svcparm[2];
+ guint16 cls1_rcvsize;
+ guint8 cls2_svcparm[2];
+ guint16 cls2_rcvsize;
+ guint8 cls3_svcparm[2];
+ guint16 cls3_rcvsize;
+ guint8 rsvd2[20];
+ guint16 isl_flwctrl_mode;
+ guint16 flw_ctrl_parmlen;
+ guint32 b2b_credit;
+ guint32 compat_p1;
+ guint32 compat_p2;
+ guint32 compat_p3;
+ guint32 compat_p4;
+} fcswils_elp;
+#define FC_SWILS_ELP_SIZE 100
+
+#define FC_SWILS_ELP_FC_VENDOR 0x1
+#define FC_SWILS_ELP_FC_RRDY 0x2
+
+struct _fcswils_efp_didrec {
+ guint8 rec_type;
+ guint8 dom_id;
+ guint16 rsvd1;
+ guint32 rsvd2;
+ guint8 sname[8];
+};
+struct _fcswils_efp_mcastrec {
+ guint8 rec_type;
+ guint8 mcast_grpnum;
+ guint8 rsvd[14];
+};
+
+typedef union _fcswils_efp_listrec {
+ struct _fcswils_efp_didrec didrec;
+ struct _fcswils_efp_mcastrec mcastrec;
+} fcswils_efp_listrec;
+
+#define FC_SWILS_LRECTYPE_DOMAIN 0x1
+#define FC_SWILS_LRECTYPE_MCAST 0x2
+
+typedef struct _fcswils_efp {
+ guint8 opcode;
+ guint8 reclen;
+ guint16 payload_len;
+ guint8 rsvd1[3];
+ guint8 pswitch_prio;
+ guint8 pswitch_name[8];
+ fcswils_efp_listrec *listrec;
+} fcswils_efp;
+#define FC_SWILS_EFP_SIZE 16 /* not including listrec */
+
+typedef struct _fcswils_dia {
+ guint8 switch_name[8];
+ guint8 rsvd[4];
+} fcswils_dia;
+
+typedef struct _fcswils_rdi_req {
+ guint8 rsvd[3];
+ guint8 domain_id;
+} fcswils_rdi_req;
+#define FC_SWILS_RDIREQ_SIZE 4
+
+#define FC_SWILS_LSR_SLR 0x1 /* switch link record */
+#define FC_SWILS_LSR_ARS 0x2 /* AR Summary record */
+
+#define FC_SWILS_PDESC_FSPF_BB 0x01
+#define FC_SWILS_PDESC_FSPF 0x02
+
+#define FC_SWILS_ZONEOBJ_ZONESET 1
+#define FC_SWILS_ZONEOBJ_ZONE 2
+#define FC_SWILS_ZONEOBJ_ZONEALIAS 3
+
+#define FC_SWILS_ZONEMBR_WWN 1
+#define FC_SWILS_ZONEMBR_DP 2
+#define FC_SWILS_ZONEMBR_FCID 3
+#define FC_SWILS_ZONEMBR_ALIAS 4
+#define FC_SWILS_ZONEMBR_WWN_LUN 0xE1
+#define FC_SWILS_ZONEMBR_DP_LUN 0xE2
+#define FC_SWILS_ZONEMBR_FCID_LUN 0xE3
+
+extern const value_string fc_swils_zonembr_type_val[];
+
+#endif
diff --git a/epan/dissectors/packet-fddi.c b/epan/dissectors/packet-fddi.c
new file mode 100644
index 0000000000..a676f5767d
--- /dev/null
+++ b/epan/dissectors/packet-fddi.c
@@ -0,0 +1,498 @@
+/* packet-fddi.c
+ * Routines for FDDI packet disassembly
+ *
+ * Laurent Deniel <laurent.deniel@free.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/bitswap.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "packet-fddi.h"
+#include "packet-llc.h"
+#include "tap.h"
+
+#include <epan/resolv.h>
+
+static int proto_fddi = -1;
+static int hf_fddi_fc = -1;
+static int hf_fddi_fc_clf = -1;
+static int hf_fddi_fc_prio = -1;
+static int hf_fddi_fc_smt_subtype = -1;
+static int hf_fddi_fc_mac_subtype = -1;
+static int hf_fddi_dst = -1;
+static int hf_fddi_src = -1;
+static int hf_fddi_addr = -1;
+
+static gint ett_fddi = -1;
+static gint ett_fddi_fc = -1;
+
+static int fddi_tap = -1;
+
+static gboolean fddi_padding = FALSE;
+
+#define FDDI_PADDING ((fddi_padding) ? 3 : 0)
+
+/* FDDI Frame Control values */
+
+#define FDDI_FC_VOID 0x00 /* Void frame */
+#define FDDI_FC_NRT 0x80 /* Nonrestricted token */
+#define FDDI_FC_RT 0xc0 /* Restricted token */
+#define FDDI_FC_MAC 0xc0 /* MAC frame */
+#define FDDI_FC_SMT 0x40 /* SMT frame */
+#define FDDI_FC_SMT_INFO 0x41 /* SMT Info */
+#define FDDI_FC_SMT_NSA 0x4F /* SMT Next station adrs */
+#define FDDI_FC_SMT_MIN FDDI_FC_SMT_INFO
+#define FDDI_FC_SMT_MAX FDDI_FC_SMT_NSA
+#define FDDI_FC_MAC_MIN 0xc1
+#define FDDI_FC_MAC_BEACON 0xc2 /* MAC Beacon frame */
+#define FDDI_FC_MAC_CLAIM 0xc3 /* MAC Claim frame */
+#define FDDI_FC_MAC_MAX 0xcf
+#define FDDI_FC_LLC_ASYNC 0x50 /* Async. LLC frame */
+#define FDDI_FC_LLC_ASYNC_MIN FDDI_FC_LLC_ASYNC
+#define FDDI_FC_LLC_ASYNC_DEF 0x54
+#define FDDI_FC_LLC_ASYNC_MAX 0x5f
+#define FDDI_FC_LLC_SYNC 0xd0 /* Sync. LLC frame */
+#define FDDI_FC_LLC_SYNC_MIN FDDI_FC_LLC_SYNC
+#define FDDI_FC_LLC_SYNC_MAX 0xd7
+#define FDDI_FC_IMP_ASYNC 0x60 /* Implementor Async. */
+#define FDDI_FC_IMP_ASYNC_MIN FDDI_FC_IMP_ASYNC
+#define FDDI_FC_IMP_ASYNC_MAX 0x6f
+#define FDDI_FC_IMP_SYNC 0xe0 /* Implementor Synch. */
+
+#define FDDI_FC_CLFF 0xF0 /* Class/Length/Format bits */
+#define FDDI_FC_ZZZZ 0x0F /* Control bits */
+
+/*
+ * Async frame ZZZZ bits:
+ */
+#define FDDI_FC_ASYNC_R 0x08 /* Reserved */
+#define FDDI_FC_ASYNC_PRI 0x07 /* Priority */
+
+#define CLFF_BITS(fc) (((fc) & FDDI_FC_CLFF) >> 4)
+#define ZZZZ_BITS(fc) ((fc) & FDDI_FC_ZZZZ)
+
+static const value_string clf_vals[] = {
+ { CLFF_BITS(FDDI_FC_VOID), "Void" },
+ { CLFF_BITS(FDDI_FC_SMT), "SMT" },
+ { CLFF_BITS(FDDI_FC_LLC_ASYNC), "Async LLC" },
+ { CLFF_BITS(FDDI_FC_IMP_ASYNC), "Implementor Async" },
+ { CLFF_BITS(FDDI_FC_NRT), "Nonrestricted Token" },
+ { CLFF_BITS(FDDI_FC_MAC), "MAC" },
+ { CLFF_BITS(FDDI_FC_LLC_SYNC), "Sync LLC" },
+ { CLFF_BITS(FDDI_FC_IMP_SYNC), "Implementor Sync" },
+ { 0, NULL }
+};
+
+static const value_string smt_subtype_vals[] = {
+ { ZZZZ_BITS(FDDI_FC_SMT_INFO), "Info" },
+ { ZZZZ_BITS(FDDI_FC_SMT_NSA), "Next Station Address" },
+ { 0, NULL }
+};
+
+static const value_string mac_subtype_vals[] = {
+ { ZZZZ_BITS(FDDI_FC_MAC_BEACON), "Beacon" },
+ { ZZZZ_BITS(FDDI_FC_MAC_CLAIM), "Claim" },
+ { 0, NULL }
+};
+
+#define FDDI_HEADER_SIZE 13
+
+/* field positions */
+
+#define FDDI_P_FC 0
+#define FDDI_P_DHOST 1
+#define FDDI_P_SHOST 7
+
+static dissector_handle_t llc_handle;
+static dissector_handle_t data_handle;
+
+static void
+swap_mac_addr(guint8 *swapped_addr, const guint8 *orig_addr)
+{
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ swapped_addr[i] = BIT_SWAP(orig_addr[i]);
+ }
+}
+
+
+void
+capture_fddi(const guchar *pd, int len, packet_counts *ld)
+{
+ int offset = 0, fc;
+
+ if (!BYTES_ARE_IN_FRAME(0, len, FDDI_HEADER_SIZE + FDDI_PADDING)) {
+ ld->other++;
+ return;
+ }
+ offset = FDDI_PADDING + FDDI_HEADER_SIZE;
+
+ fc = (int) pd[FDDI_P_FC+FDDI_PADDING];
+
+ switch (fc) {
+
+ /* From now, only 802.2 SNAP (Async. LCC frame) is supported */
+
+ case FDDI_FC_LLC_ASYNC + 0 :
+ case FDDI_FC_LLC_ASYNC + 1 :
+ case FDDI_FC_LLC_ASYNC + 2 :
+ case FDDI_FC_LLC_ASYNC + 3 :
+ case FDDI_FC_LLC_ASYNC + 4 :
+ case FDDI_FC_LLC_ASYNC + 5 :
+ case FDDI_FC_LLC_ASYNC + 6 :
+ case FDDI_FC_LLC_ASYNC + 7 :
+ case FDDI_FC_LLC_ASYNC + 8 :
+ case FDDI_FC_LLC_ASYNC + 9 :
+ case FDDI_FC_LLC_ASYNC + 10 :
+ case FDDI_FC_LLC_ASYNC + 11 :
+ case FDDI_FC_LLC_ASYNC + 12 :
+ case FDDI_FC_LLC_ASYNC + 13 :
+ case FDDI_FC_LLC_ASYNC + 14 :
+ case FDDI_FC_LLC_ASYNC + 15 :
+ capture_llc(pd, offset, len, ld);
+ return;
+ default :
+ ld->other++;
+ return;
+
+ } /* fc */
+
+} /* capture_fddi */
+
+static gchar *
+fddifc_to_str(int fc)
+{
+ static gchar strbuf[128+1];
+
+ switch (fc) {
+
+ case FDDI_FC_VOID: /* Void frame */
+ return "Void frame";
+
+ case FDDI_FC_NRT: /* Nonrestricted token */
+ return "Nonrestricted token";
+
+ case FDDI_FC_RT: /* Restricted token */
+ return "Restricted token";
+
+ case FDDI_FC_SMT_INFO: /* SMT Info */
+ return "SMT info";
+
+ case FDDI_FC_SMT_NSA: /* SMT Next station adrs */
+ return "SMT Next station address";
+
+ case FDDI_FC_MAC_BEACON: /* MAC Beacon frame */
+ return "MAC beacon";
+
+ case FDDI_FC_MAC_CLAIM: /* MAC Claim frame */
+ return "MAC claim token";
+
+ default:
+ switch (fc & FDDI_FC_CLFF) {
+
+ case FDDI_FC_MAC:
+ sprintf(strbuf, "MAC frame, control %x", fc & FDDI_FC_ZZZZ);
+ return strbuf;
+
+ case FDDI_FC_SMT:
+ sprintf(strbuf, "SMT frame, control %x", fc & FDDI_FC_ZZZZ);
+ return strbuf;
+
+ case FDDI_FC_LLC_ASYNC:
+ if (fc & FDDI_FC_ASYNC_R)
+ sprintf(strbuf, "Async LLC frame, control %x", fc & FDDI_FC_ZZZZ);
+ else
+ sprintf(strbuf, "Async LLC frame, priority %d",
+ fc & FDDI_FC_ASYNC_PRI);
+ return strbuf;
+
+ case FDDI_FC_LLC_SYNC:
+ if (fc & FDDI_FC_ZZZZ) {
+ sprintf(strbuf, "Sync LLC frame, control %x", fc & FDDI_FC_ZZZZ);
+ return strbuf;
+ } else
+ return "Sync LLC frame";
+
+ case FDDI_FC_IMP_ASYNC:
+ sprintf(strbuf, "Implementor async frame, control %x",
+ fc & FDDI_FC_ZZZZ);
+ return strbuf;
+
+ case FDDI_FC_IMP_SYNC:
+ sprintf(strbuf, "Implementor sync frame, control %x",
+ fc & FDDI_FC_ZZZZ);
+ return strbuf;
+ break;
+
+ default:
+ return "Unknown frame type";
+ }
+ }
+}
+
+
+static void
+dissect_fddi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean bitswapped)
+{
+ proto_tree *fh_tree = NULL;
+ proto_item *ti;
+ gchar *fc_str;
+ proto_tree *fc_tree;
+ static guchar src[6], dst[6];
+ guchar src_swapped[6], dst_swapped[6];
+ tvbuff_t *next_tvb;
+ static fddi_hdr fddihdrs[4];
+ static int fddihdr_num=0;
+ fddi_hdr *fddihdr;
+
+ fddihdr_num++;
+ if(fddihdr_num>=4){
+ fddihdr_num=0;
+ }
+ fddihdr=&fddihdrs[fddihdr_num];
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FDDI");
+
+ fddihdr->fc = tvb_get_guint8(tvb, FDDI_P_FC + FDDI_PADDING);
+ fc_str = fddifc_to_str(fddihdr->fc);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, fc_str);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_fddi, tvb, 0, FDDI_HEADER_SIZE+FDDI_PADDING,
+ "Fiber Distributed Data Interface, %s", fc_str);
+ fh_tree = proto_item_add_subtree(ti, ett_fddi);
+ ti = proto_tree_add_uint_format(fh_tree, hf_fddi_fc, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc,
+ "Frame Control: 0x%02x (%s)", fddihdr->fc, fc_str);
+ fc_tree = proto_item_add_subtree(ti, ett_fddi_fc);
+ proto_tree_add_uint(fc_tree, hf_fddi_fc_clf, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc);
+ switch ((fddihdr->fc) & FDDI_FC_CLFF) {
+
+ case FDDI_FC_SMT:
+ proto_tree_add_uint(fc_tree, hf_fddi_fc_smt_subtype, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc);
+ break;
+
+ case FDDI_FC_MAC:
+ if (fddihdr->fc != FDDI_FC_RT)
+ proto_tree_add_uint(fc_tree, hf_fddi_fc_mac_subtype, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc);
+ break;
+
+ case FDDI_FC_LLC_ASYNC:
+ if (!((fddihdr->fc) & FDDI_FC_ASYNC_R))
+ proto_tree_add_uint(fc_tree, hf_fddi_fc_prio, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc);
+ break;
+ }
+ }
+
+ /* Extract the destination address, possibly bit-swapping it. */
+ if (bitswapped)
+ swap_mac_addr(dst, tvb_get_ptr(tvb, FDDI_P_DHOST + FDDI_PADDING, 6));
+ else
+ memcpy(dst, tvb_get_ptr(tvb, FDDI_P_DHOST + FDDI_PADDING, 6), sizeof dst);
+ swap_mac_addr(dst_swapped, tvb_get_ptr(tvb, FDDI_P_DHOST + FDDI_PADDING, 6));
+
+ /* XXX - copy them to some buffer associated with "pi", rather than
+ just making "dst" static? */
+ SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, &dst[0]);
+ SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, &dst[0]);
+ SET_ADDRESS(&fddihdr->dst, AT_ETHER, 6, &dst[0]);
+
+ if (fh_tree) {
+ proto_tree_add_ether(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst);
+ proto_tree_add_ether_hidden(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst);
+
+ /* hide some bit-swapped mac address fields in the proto_tree, just in case */
+ proto_tree_add_ether_hidden(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst_swapped);
+ proto_tree_add_ether_hidden(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst_swapped);
+ }
+
+ /* Extract the source address, possibly bit-swapping it. */
+ if (bitswapped)
+ swap_mac_addr(src, tvb_get_ptr(tvb, FDDI_P_SHOST + FDDI_PADDING, 6));
+ else
+ memcpy(src, tvb_get_ptr(tvb, FDDI_P_SHOST + FDDI_PADDING, 6), sizeof src);
+ swap_mac_addr(src_swapped, tvb_get_ptr(tvb, FDDI_P_SHOST + FDDI_PADDING, 6));
+
+ /* XXX - copy them to some buffer associated with "pi", rather than
+ just making "src" static? */
+ SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, &src[0]);
+ SET_ADDRESS(&pinfo->src, AT_ETHER, 6, &src[0]);
+ SET_ADDRESS(&fddihdr->src, AT_ETHER, 6, &src[0]);
+
+ if (fh_tree) {
+ proto_tree_add_ether(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src);
+ proto_tree_add_ether_hidden(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src);
+
+ /* hide some bit-swapped mac address fields in the proto_tree, just in case */
+ proto_tree_add_ether_hidden(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src_swapped);
+ proto_tree_add_ether_hidden(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src_swapped);
+ }
+
+ next_tvb = tvb_new_subset(tvb, FDDI_HEADER_SIZE + FDDI_PADDING, -1, -1);
+
+
+ tap_queue_packet(fddi_tap, pinfo, fddihdr);
+
+ switch (fddihdr->fc) {
+
+ /* From now, only 802.2 SNAP (Async. LCC frame) is supported */
+
+ case FDDI_FC_LLC_ASYNC + 0 :
+ case FDDI_FC_LLC_ASYNC + 1 :
+ case FDDI_FC_LLC_ASYNC + 2 :
+ case FDDI_FC_LLC_ASYNC + 3 :
+ case FDDI_FC_LLC_ASYNC + 4 :
+ case FDDI_FC_LLC_ASYNC + 5 :
+ case FDDI_FC_LLC_ASYNC + 6 :
+ case FDDI_FC_LLC_ASYNC + 7 :
+ case FDDI_FC_LLC_ASYNC + 8 :
+ case FDDI_FC_LLC_ASYNC + 9 :
+ case FDDI_FC_LLC_ASYNC + 10 :
+ case FDDI_FC_LLC_ASYNC + 11 :
+ case FDDI_FC_LLC_ASYNC + 12 :
+ case FDDI_FC_LLC_ASYNC + 13 :
+ case FDDI_FC_LLC_ASYNC + 14 :
+ case FDDI_FC_LLC_ASYNC + 15 :
+ call_dissector(llc_handle, next_tvb, pinfo, tree);
+ return;
+
+ default :
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ return;
+
+ } /* fc */
+} /* dissect_fddi */
+
+
+static void
+dissect_fddi_bitswapped(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_fddi(tvb, pinfo, tree, TRUE);
+}
+
+static void
+dissect_fddi_not_bitswapped(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_fddi(tvb, pinfo, tree, FALSE);
+}
+
+void
+proto_register_fddi(void)
+{
+ static hf_register_info hf[] = {
+
+ /*
+ * XXX - we want this guy to have his own private formatting
+ * routine, using "fc_to_str()"; if "fc_to_str()" returns
+ * NULL, just show the hex value, else show the string.
+ */
+ { &hf_fddi_fc,
+ { "Frame Control", "fddi.fc", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_fddi_fc_clf,
+ { "Class/Length/Format", "fddi.fc.clf", FT_UINT8, BASE_HEX, VALS(clf_vals), FDDI_FC_CLFF,
+ "", HFILL }},
+
+ { &hf_fddi_fc_prio,
+ { "Priority", "fddi.fc.prio", FT_UINT8, BASE_DEC, NULL, FDDI_FC_ASYNC_PRI,
+ "", HFILL }},
+
+ { &hf_fddi_fc_smt_subtype,
+ { "SMT Subtype", "fddi.fc.smt_subtype", FT_UINT8, BASE_DEC, VALS(smt_subtype_vals), FDDI_FC_ZZZZ,
+ "", HFILL }},
+
+ { &hf_fddi_fc_mac_subtype,
+ { "MAC Subtype", "fddi.fc.mac_subtype", FT_UINT8, BASE_DEC, VALS(mac_subtype_vals), FDDI_FC_ZZZZ,
+ "", HFILL }},
+
+ { &hf_fddi_dst,
+ { "Destination", "fddi.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Destination Hardware Address", HFILL }},
+
+ { &hf_fddi_src,
+ { "Source", "fddi.src", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_fddi_addr,
+ { "Source or Destination Address", "fddi.addr", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Source or Destination Hardware Address", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_fddi,
+ &ett_fddi_fc,
+ };
+
+ module_t *fddi_module;
+
+ proto_fddi = proto_register_protocol("Fiber Distributed Data Interface",
+ "FDDI", "fddi");
+ proto_register_field_array(proto_fddi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /*
+ * Called from various dissectors for encapsulated FDDI frames.
+ * We assume the MAC addresses in them aren't bitswapped.
+ */
+ register_dissector("fddi", dissect_fddi_not_bitswapped, proto_fddi);
+
+ fddi_module = prefs_register_protocol(proto_fddi, NULL);
+ prefs_register_bool_preference(fddi_module, "padding",
+ "Add 3-byte padding to all FDDI packets",
+ "Whether the FDDI dissector should add 3-byte padding to all "
+ "captured FDDI packets (useful with e.g. Tru64 UNIX tcpdump)",
+ &fddi_padding);
+
+ fddi_tap = register_tap("fddi");
+}
+
+void
+proto_reg_handoff_fddi(void)
+{
+ dissector_handle_t fddi_handle, fddi_bitswapped_handle;
+
+ /*
+ * Get a handle for the LLC dissector.
+ */
+ llc_handle = find_dissector("llc");
+ data_handle = find_dissector("data");
+
+ fddi_handle = find_dissector("fddi");
+ dissector_add("wtap_encap", WTAP_ENCAP_FDDI, fddi_handle);
+ fddi_bitswapped_handle =
+ create_dissector_handle(dissect_fddi_bitswapped, proto_fddi);
+ dissector_add("wtap_encap", WTAP_ENCAP_FDDI_BITSWAPPED,
+ fddi_bitswapped_handle);
+}
diff --git a/epan/dissectors/packet-fddi.h b/epan/dissectors/packet-fddi.h
new file mode 100644
index 0000000000..bb2b40e5fc
--- /dev/null
+++ b/epan/dissectors/packet-fddi.h
@@ -0,0 +1,35 @@
+/* packet-fddi.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_FDDI_H__
+#define __PACKET_FDDI_H__
+
+typedef struct _fddi_hdr {
+ guint8 fc;
+ address dst;
+ address src;
+} fddi_hdr;
+
+void capture_fddi(const guchar *, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-fix.c b/epan/dissectors/packet-fix.c
new file mode 100644
index 0000000000..7d8931d60c
--- /dev/null
+++ b/epan/dissectors/packet-fix.c
@@ -0,0 +1,6265 @@
+/* packet-fix.c
+ * Routines for Financial Information eXchange (FIX) Protocol dissection
+ * Copyright 2000, PC Drew <drewpc@ibsncentral.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Documentation: http://www.fixprotocol.org/
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+static const value_string message_types[] = {
+ { 0x30, "Heartbeat" },
+ { 0x31, "Test Request" },
+ { 0x32, "Resend Request" },
+ { 0x33, "Reject" },
+ { 0x34, "Sequence Reset" },
+ { 0x35, "Logout" },
+ { 0x36, "Indication of Interest" },
+ { 0x37, "Advertisement" },
+ { 0x38, "Execution Report" },
+ { 0x39, "Cancel Reject" },
+ { 0x41, "Logon" },
+ { 0x42, "News" },
+ { 0x43, "Email" },
+ { 0x44, "New Order - Single" },
+ { 0x45, "New Order - List" },
+ { 0x46, "Order Cancel Request" },
+ { 0x47, "Order Cancel/Replace Request" },
+ { 0x48, "Order Status Request" },
+ { 0, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_fix = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_fix = -1;
+
+/* message type list */
+static GData *msg_types;
+
+static int hf_fix_Account = -1; /* Tag 1 */
+static int hf_fix_AdvId = -1; /* Tag 2 */
+static int hf_fix_AdvRefID = -1; /* Tag 3 */
+static int hf_fix_AdvSide = -1; /* Tag 4 */
+static int hf_fix_AdvTransType = -1; /* Tag 5 */
+static int hf_fix_AvgPx = -1; /* Tag 6 */
+static int hf_fix_BeginSeqNo = -1; /* Tag 7 */
+static int hf_fix_BeginString = -1; /* Tag 8 */
+static int hf_fix_BodyLength = -1; /* Tag 9 */
+static int hf_fix_CheckSum = -1; /* Tag 10 */
+static int hf_fix_ClOrdID = -1; /* Tag 11 */
+static int hf_fix_Commission = -1; /* Tag 12 */
+static int hf_fix_CommType = -1; /* Tag 13 */
+static int hf_fix_CumQty = -1; /* Tag 14 */
+static int hf_fix_Currency = -1; /* Tag 15 */
+static int hf_fix_EndSeqNo = -1; /* Tag 16 */
+static int hf_fix_ExecID = -1; /* Tag 17 */
+static int hf_fix_ExecInst = -1; /* Tag 18 */
+static int hf_fix_ExecRefID = -1; /* Tag 19 */
+static int hf_fix_ExecTransType = -1; /* Tag 20 */
+static int hf_fix_HandlInst = -1; /* Tag 21 */
+static int hf_fix_SecurityIDSource = -1; /* Tag 22 */
+static int hf_fix_IOIid = -1; /* Tag 23 */
+static int hf_fix_IOIOthSvc = -1; /* Tag 24 */
+static int hf_fix_IOIQltyInd = -1; /* Tag 25 */
+static int hf_fix_IOIRefID = -1; /* Tag 26 */
+static int hf_fix_IOIQty = -1; /* Tag 27 */
+static int hf_fix_IOITransType = -1; /* Tag 28 */
+static int hf_fix_LastCapacity = -1; /* Tag 29 */
+static int hf_fix_LastMkt = -1; /* Tag 30 */
+static int hf_fix_LastPx = -1; /* Tag 31 */
+static int hf_fix_LastQty = -1; /* Tag 32 */
+static int hf_fix_LinesOfText = -1; /* Tag 33 */
+static int hf_fix_MsgSeqNum = -1; /* Tag 34 */
+static int hf_fix_MsgType = -1; /* Tag 35 */
+static int hf_fix_NewSeqNo = -1; /* Tag 36 */
+static int hf_fix_OrderID = -1; /* Tag 37 */
+static int hf_fix_OrderQty = -1; /* Tag 38 */
+static int hf_fix_OrdStatus = -1; /* Tag 39 */
+static int hf_fix_OrdType = -1; /* Tag 40 */
+static int hf_fix_OrigClOrdID = -1; /* Tag 41 */
+static int hf_fix_OrigTime = -1; /* Tag 42 */
+static int hf_fix_PossDupFlag = -1; /* Tag 43 */
+static int hf_fix_Price = -1; /* Tag 44 */
+static int hf_fix_RefSeqNum = -1; /* Tag 45 */
+static int hf_fix_RelatdSym = -1; /* Tag 46 */
+static int hf_fix_Rule80A = -1; /* Tag 47 */
+static int hf_fix_SecurityID = -1; /* Tag 48 */
+static int hf_fix_SenderCompID = -1; /* Tag 49 */
+static int hf_fix_SenderSubID = -1; /* Tag 50 */
+static int hf_fix_SendingDate = -1; /* Tag 51 */
+static int hf_fix_SendingTime = -1; /* Tag 52 */
+static int hf_fix_Quantity = -1; /* Tag 53 */
+static int hf_fix_Side = -1; /* Tag 54 */
+static int hf_fix_Symbol = -1; /* Tag 55 */
+static int hf_fix_TargetCompID = -1; /* Tag 56 */
+static int hf_fix_TargetSubID = -1; /* Tag 57 */
+static int hf_fix_Text = -1; /* Tag 58 */
+static int hf_fix_TimeInForce = -1; /* Tag 59 */
+static int hf_fix_TransactTime = -1; /* Tag 60 */
+static int hf_fix_Urgency = -1; /* Tag 61 */
+static int hf_fix_ValidUntilTime = -1; /* Tag 62 */
+static int hf_fix_SettlmntTyp = -1; /* Tag 63 */
+static int hf_fix_FutSettDate = -1; /* Tag 64 */
+static int hf_fix_SymbolSfx = -1; /* Tag 65 */
+static int hf_fix_ListID = -1; /* Tag 66 */
+static int hf_fix_ListSeqNo = -1; /* Tag 67 */
+static int hf_fix_TotNoOrders = -1; /* Tag 68 */
+static int hf_fix_ListExecInst = -1; /* Tag 69 */
+static int hf_fix_AllocID = -1; /* Tag 70 */
+static int hf_fix_AllocTransType = -1; /* Tag 71 */
+static int hf_fix_RefAllocID = -1; /* Tag 72 */
+static int hf_fix_NoOrders = -1; /* Tag 73 */
+static int hf_fix_AvgPrxPrecision = -1; /* Tag 74 */
+static int hf_fix_TradeDate = -1; /* Tag 75 */
+static int hf_fix_ExecBroker = -1; /* Tag 76 */
+static int hf_fix_PositionEffect = -1; /* Tag 77 */
+static int hf_fix_NoAllocs = -1; /* Tag 78 */
+static int hf_fix_AllocAccount = -1; /* Tag 79 */
+static int hf_fix_AllocQty = -1; /* Tag 80 */
+static int hf_fix_ProcessCode = -1; /* Tag 81 */
+static int hf_fix_NoRpts = -1; /* Tag 82 */
+static int hf_fix_RptSeq = -1; /* Tag 83 */
+static int hf_fix_CxlQty = -1; /* Tag 84 */
+static int hf_fix_NoDlvyInst = -1; /* Tag 85 */
+static int hf_fix_DlvyInst = -1; /* Tag 86 */
+static int hf_fix_AllocStatus = -1; /* Tag 87 */
+static int hf_fix_AllocRejCode = -1; /* Tag 88 */
+static int hf_fix_Signature = -1; /* Tag 89 */
+static int hf_fix_SecureDataLen = -1; /* Tag 90 */
+static int hf_fix_SecureData = -1; /* Tag 91 */
+static int hf_fix_BrokerOfCredit = -1; /* Tag 92 */
+static int hf_fix_SignatureLength = -1; /* Tag 93 */
+static int hf_fix_EmailType = -1; /* Tag 94 */
+static int hf_fix_RawDataLength = -1; /* Tag 95 */
+static int hf_fix_RawData = -1; /* Tag 96 */
+static int hf_fix_PossResend = -1; /* Tag 97 */
+static int hf_fix_EncryptMethod = -1; /* Tag 98 */
+static int hf_fix_StopPx = -1; /* Tag 99 */
+static int hf_fix_ExDestination = -1; /* Tag 100 */
+static int hf_fix_CxlRejReason = -1; /* Tag 102 */
+static int hf_fix_OrdRejReason = -1; /* Tag 103 */
+static int hf_fix_IOIQualifier = -1; /* Tag 104 */
+static int hf_fix_WaveNo = -1; /* Tag 105 */
+static int hf_fix_Issuer = -1; /* Tag 106 */
+static int hf_fix_SecurityDesc = -1; /* Tag 107 */
+static int hf_fix_HeartBtInt = -1; /* Tag 108 */
+static int hf_fix_ClientID = -1; /* Tag 109 */
+static int hf_fix_MinQty = -1; /* Tag 110 */
+static int hf_fix_MaxFloor = -1; /* Tag 111 */
+static int hf_fix_TestReqID = -1; /* Tag 112 */
+static int hf_fix_ReportToExch = -1; /* Tag 113 */
+static int hf_fix_LocateReqd = -1; /* Tag 114 */
+static int hf_fix_OnBehalfOfCompID = -1; /* Tag 115 */
+static int hf_fix_OnBehalfOfSubID = -1; /* Tag 116 */
+static int hf_fix_QuoteID = -1; /* Tag 117 */
+static int hf_fix_NetMoney = -1; /* Tag 118 */
+static int hf_fix_SettlCurrAmt = -1; /* Tag 119 */
+static int hf_fix_SettlCurrency = -1; /* Tag 120 */
+static int hf_fix_ForexReq = -1; /* Tag 121 */
+static int hf_fix_OrigSendingTime = -1; /* Tag 122 */
+static int hf_fix_GapFillFlag = -1; /* Tag 123 */
+static int hf_fix_NoExecs = -1; /* Tag 124 */
+static int hf_fix_CxlType = -1; /* Tag 125 */
+static int hf_fix_ExpireTime = -1; /* Tag 126 */
+static int hf_fix_DKReason = -1; /* Tag 127 */
+static int hf_fix_DeliverToCompID = -1; /* Tag 128 */
+static int hf_fix_DeliverToSubID = -1; /* Tag 129 */
+static int hf_fix_IOINaturalFlag = -1; /* Tag 130 */
+static int hf_fix_QuoteReqID = -1; /* Tag 131 */
+static int hf_fix_BidPx = -1; /* Tag 132 */
+static int hf_fix_OfferPx = -1; /* Tag 133 */
+static int hf_fix_BidSize = -1; /* Tag 134 */
+static int hf_fix_OfferSize = -1; /* Tag 135 */
+static int hf_fix_NoMiscFees = -1; /* Tag 136 */
+static int hf_fix_MiscFeeAmt = -1; /* Tag 137 */
+static int hf_fix_MiscFeeCurr = -1; /* Tag 138 */
+static int hf_fix_MiscFeeType = -1; /* Tag 139 */
+static int hf_fix_PrevClosePx = -1; /* Tag 140 */
+static int hf_fix_ResetSeqNumFlag = -1; /* Tag 141 */
+static int hf_fix_SenderLocationID = -1; /* Tag 142 */
+static int hf_fix_TargetLocationID = -1; /* Tag 143 */
+static int hf_fix_OnBehalfOfLocationID = -1; /* Tag 144 */
+static int hf_fix_DeliverToLocationID = -1; /* Tag 145 */
+static int hf_fix_NoRelatedSym = -1; /* Tag 146 */
+static int hf_fix_Subject = -1; /* Tag 147 */
+static int hf_fix_Headline = -1; /* Tag 148 */
+static int hf_fix_URLLink = -1; /* Tag 149 */
+static int hf_fix_ExecType = -1; /* Tag 150 */
+static int hf_fix_LeavesQty = -1; /* Tag 151 */
+static int hf_fix_CashOrderQty = -1; /* Tag 152 */
+static int hf_fix_AllocAvgPx = -1; /* Tag 153 */
+static int hf_fix_AllocNetMoney = -1; /* Tag 154 */
+static int hf_fix_SettlCurrFxRate = -1; /* Tag 155 */
+static int hf_fix_SettlCurrFxRateCalc = -1; /* Tag 156 */
+static int hf_fix_NumDaysInterest = -1; /* Tag 157 */
+static int hf_fix_AccruedInterestRate = -1; /* Tag 158 */
+static int hf_fix_AccruedInterestAmt = -1; /* Tag 159 */
+static int hf_fix_SettlInstMode = -1; /* Tag 160 */
+static int hf_fix_AllocText = -1; /* Tag 161 */
+static int hf_fix_SettlInstID = -1; /* Tag 162 */
+static int hf_fix_SettlInstTransType = -1; /* Tag 163 */
+static int hf_fix_EmailThreadID = -1; /* Tag 164 */
+static int hf_fix_SettlInstSource = -1; /* Tag 165 */
+static int hf_fix_SettlLocation = -1; /* Tag 166 */
+static int hf_fix_SecurityType = -1; /* Tag 167 */
+static int hf_fix_EffectiveTime = -1; /* Tag 168 */
+static int hf_fix_StandInstDbType = -1; /* Tag 169 */
+static int hf_fix_StandInstDbName = -1; /* Tag 170 */
+static int hf_fix_StandInstDbID = -1; /* Tag 171 */
+static int hf_fix_SettlDeliveryType = -1; /* Tag 172 */
+static int hf_fix_SettlDepositoryCode = -1; /* Tag 173 */
+static int hf_fix_SettlBrkrCode = -1; /* Tag 174 */
+static int hf_fix_SettlInstCode = -1; /* Tag 175 */
+static int hf_fix_SecuritySettlAgentName = -1; /* Tag 176 */
+static int hf_fix_SecuritySettlAgentCode = -1; /* Tag 177 */
+static int hf_fix_SecuritySettlAgentAcctNum = -1; /* Tag 178 */
+static int hf_fix_SecuritySettlAgentAcctName = -1; /* Tag 179 */
+static int hf_fix_SecuritySettlAgentContactName = -1; /* Tag 180 */
+static int hf_fix_SecuritySettlAgentContactPhone = -1; /* Tag 181 */
+static int hf_fix_CashSettlAgentName = -1; /* Tag 182 */
+static int hf_fix_CashSettlAgentCode = -1; /* Tag 183 */
+static int hf_fix_CashSettlAgentAcctNum = -1; /* Tag 184 */
+static int hf_fix_CashSettlAgentAcctName = -1; /* Tag 185 */
+static int hf_fix_CashSettlAgentContactName = -1; /* Tag 186 */
+static int hf_fix_CashSettlAgentContactPhone = -1; /* Tag 187 */
+static int hf_fix_BidSpotRate = -1; /* Tag 188 */
+static int hf_fix_BidForwardPoints = -1; /* Tag 189 */
+static int hf_fix_OfferSpotRate = -1; /* Tag 190 */
+static int hf_fix_OfferForwardPoints = -1; /* Tag 191 */
+static int hf_fix_OrderQty2 = -1; /* Tag 192 */
+static int hf_fix_FutSettDate2 = -1; /* Tag 193 */
+static int hf_fix_LastSpotRate = -1; /* Tag 194 */
+static int hf_fix_LastForwardPoints = -1; /* Tag 195 */
+static int hf_fix_AllocLinkID = -1; /* Tag 196 */
+static int hf_fix_AllocLinkType = -1; /* Tag 197 */
+static int hf_fix_SecondaryOrderID = -1; /* Tag 198 */
+static int hf_fix_NoIOIQualifiers = -1; /* Tag 199 */
+static int hf_fix_MaturityMonthYear = -1; /* Tag 200 */
+static int hf_fix_PutOrCall = -1; /* Tag 201 */
+static int hf_fix_StrikePrice = -1; /* Tag 202 */
+static int hf_fix_CoveredOrUncovered = -1; /* Tag 203 */
+static int hf_fix_CustomerOrFirm = -1; /* Tag 204 */
+static int hf_fix_MaturityDay = -1; /* Tag 205 */
+static int hf_fix_OptAttribute = -1; /* Tag 206 */
+static int hf_fix_SecurityExchange = -1; /* Tag 207 */
+static int hf_fix_NotifyBrokerOfCredit = -1; /* Tag 208 */
+static int hf_fix_AllocHandlInst = -1; /* Tag 209 */
+static int hf_fix_MaxShow = -1; /* Tag 210 */
+static int hf_fix_PegDifference = -1; /* Tag 211 */
+static int hf_fix_XmlDataLen = -1; /* Tag 212 */
+static int hf_fix_XmlData = -1; /* Tag 213 */
+static int hf_fix_SettlInstRefID = -1; /* Tag 214 */
+static int hf_fix_NoRoutingIDs = -1; /* Tag 215 */
+static int hf_fix_RoutingType = -1; /* Tag 216 */
+static int hf_fix_RoutingID = -1; /* Tag 217 */
+static int hf_fix_Spread = -1; /* Tag 218 */
+static int hf_fix_Benchmark = -1; /* Tag 219 */
+static int hf_fix_BenchmarkCurveCurrency = -1; /* Tag 220 */
+static int hf_fix_BenchmarkCurveName = -1; /* Tag 221 */
+static int hf_fix_BenchmarkCurvePoint = -1; /* Tag 222 */
+static int hf_fix_CouponRate = -1; /* Tag 223 */
+static int hf_fix_CouponPaymentDate = -1; /* Tag 224 */
+static int hf_fix_IssueDate = -1; /* Tag 225 */
+static int hf_fix_RepurchaseTerm = -1; /* Tag 226 */
+static int hf_fix_RepurchaseRate = -1; /* Tag 227 */
+static int hf_fix_Factor = -1; /* Tag 228 */
+static int hf_fix_TradeOriginationDate = -1; /* Tag 229 */
+static int hf_fix_ExDate = -1; /* Tag 230 */
+static int hf_fix_ContractMultiplier = -1; /* Tag 231 */
+static int hf_fix_NoStipulations = -1; /* Tag 232 */
+static int hf_fix_StipulationType = -1; /* Tag 233 */
+static int hf_fix_StipulationValue = -1; /* Tag 234 */
+static int hf_fix_YieldType = -1; /* Tag 235 */
+static int hf_fix_Yield = -1; /* Tag 236 */
+static int hf_fix_TotalTakedown = -1; /* Tag 237 */
+static int hf_fix_Concession = -1; /* Tag 238 */
+static int hf_fix_RepoCollateralSecurityType = -1; /* Tag 239 */
+static int hf_fix_RedemptionDate = -1; /* Tag 240 */
+static int hf_fix_UnderlyingCouponPaymentDate = -1; /* Tag 241 */
+static int hf_fix_UnderlyingIssueDate = -1; /* Tag 242 */
+static int hf_fix_UnderlyingRepoCollateralSecurityType = -1; /* Tag 243 */
+static int hf_fix_UnderlyingRepurchaseTerm = -1; /* Tag 244 */
+static int hf_fix_UnderlyingRepurchaseRate = -1; /* Tag 245 */
+static int hf_fix_UnderlyingFactor = -1; /* Tag 246 */
+static int hf_fix_UnderlyingRedemptionDate = -1; /* Tag 247 */
+static int hf_fix_LegCouponPaymentDate = -1; /* Tag 248 */
+static int hf_fix_LegIssueDate = -1; /* Tag 249 */
+static int hf_fix_LegRepoCollateralSecurityType = -1; /* Tag 250 */
+static int hf_fix_LegRepurchaseTerm = -1; /* Tag 251 */
+static int hf_fix_LegRepurchaseRate = -1; /* Tag 252 */
+static int hf_fix_LegFactor = -1; /* Tag 253 */
+static int hf_fix_LegRedemptionDate = -1; /* Tag 254 */
+static int hf_fix_CreditRating = -1; /* Tag 255 */
+static int hf_fix_UnderlyingCreditRating = -1; /* Tag 256 */
+static int hf_fix_LegCreditRating = -1; /* Tag 257 */
+static int hf_fix_TradedFlatSwitch = -1; /* Tag 258 */
+static int hf_fix_BasisFeatureDate = -1; /* Tag 259 */
+static int hf_fix_BasisFeaturePrice = -1; /* Tag 260 */
+static int hf_fix_ReservedAllocated = -1; /* Tag 261 */
+static int hf_fix_MDReqID = -1; /* Tag 262 */
+static int hf_fix_SubscriptionRequestType = -1; /* Tag 263 */
+static int hf_fix_MarketDepth = -1; /* Tag 264 */
+static int hf_fix_MDUpdateType = -1; /* Tag 265 */
+static int hf_fix_AggregatedBook = -1; /* Tag 266 */
+static int hf_fix_NoMDEntryTypes = -1; /* Tag 267 */
+static int hf_fix_NoMDEntries = -1; /* Tag 268 */
+static int hf_fix_MDEntryType = -1; /* Tag 269 */
+static int hf_fix_MDEntryPx = -1; /* Tag 270 */
+static int hf_fix_MDEntrySize = -1; /* Tag 271 */
+static int hf_fix_MDEntryDate = -1; /* Tag 272 */
+static int hf_fix_MDEntryTime = -1; /* Tag 273 */
+static int hf_fix_TickDirection = -1; /* Tag 274 */
+static int hf_fix_MDMkt = -1; /* Tag 275 */
+static int hf_fix_QuoteCondition = -1; /* Tag 276 */
+static int hf_fix_TradeCondition = -1; /* Tag 277 */
+static int hf_fix_MDEntryID = -1; /* Tag 278 */
+static int hf_fix_MDUpdateAction = -1; /* Tag 279 */
+static int hf_fix_MDEntryRefID = -1; /* Tag 280 */
+static int hf_fix_MDReqRejReason = -1; /* Tag 281 */
+static int hf_fix_MDEntryOriginator = -1; /* Tag 282 */
+static int hf_fix_LocationID = -1; /* Tag 283 */
+static int hf_fix_DeskID = -1; /* Tag 284 */
+static int hf_fix_DeleteReason = -1; /* Tag 285 */
+static int hf_fix_OpenCloseSettleFlag = -1; /* Tag 286 */
+static int hf_fix_SellerDays = -1; /* Tag 287 */
+static int hf_fix_MDEntryBuyer = -1; /* Tag 288 */
+static int hf_fix_MDEntrySeller = -1; /* Tag 289 */
+static int hf_fix_MDEntryPositionNo = -1; /* Tag 290 */
+static int hf_fix_FinancialStatus = -1; /* Tag 291 */
+static int hf_fix_CorporateAction = -1; /* Tag 292 */
+static int hf_fix_DefBidSize = -1; /* Tag 293 */
+static int hf_fix_DefOfferSize = -1; /* Tag 294 */
+static int hf_fix_NoQuoteEntries = -1; /* Tag 295 */
+static int hf_fix_NoQuoteSets = -1; /* Tag 296 */
+static int hf_fix_QuoteStatus = -1; /* Tag 297 */
+static int hf_fix_QuoteCancelType = -1; /* Tag 298 */
+static int hf_fix_QuoteEntryID = -1; /* Tag 299 */
+static int hf_fix_QuoteRejectReason = -1; /* Tag 300 */
+static int hf_fix_QuoteResponseLevel = -1; /* Tag 301 */
+static int hf_fix_QuoteSetID = -1; /* Tag 302 */
+static int hf_fix_QuoteRequestType = -1; /* Tag 303 */
+static int hf_fix_TotQuoteEntries = -1; /* Tag 304 */
+static int hf_fix_UnderlyingSecurityIDSource = -1; /* Tag 305 */
+static int hf_fix_UnderlyingIssuer = -1; /* Tag 306 */
+static int hf_fix_UnderlyingSecurityDesc = -1; /* Tag 307 */
+static int hf_fix_UnderlyingSecurityExchange = -1; /* Tag 308 */
+static int hf_fix_UnderlyingSecurityID = -1; /* Tag 309 */
+static int hf_fix_UnderlyingSecurityType = -1; /* Tag 310 */
+static int hf_fix_UnderlyingSymbol = -1; /* Tag 311 */
+static int hf_fix_UnderlyingSymbolSfx = -1; /* Tag 312 */
+static int hf_fix_UnderlyingMaturityMonthYear = -1; /* Tag 313 */
+static int hf_fix_UnderlyingMaturityDay = -1; /* Tag 314 */
+static int hf_fix_UnderlyingPutOrCall = -1; /* Tag 315 */
+static int hf_fix_UnderlyingStrikePrice = -1; /* Tag 316 */
+static int hf_fix_UnderlyingOptAttribute = -1; /* Tag 317 */
+static int hf_fix_Underlying = -1; /* Tag 318 */
+static int hf_fix_RatioQty = -1; /* Tag 319 */
+static int hf_fix_SecurityReqID = -1; /* Tag 320 */
+static int hf_fix_SecurityRequestType = -1; /* Tag 321 */
+static int hf_fix_SecurityResponseID = -1; /* Tag 322 */
+static int hf_fix_SecurityResponseType = -1; /* Tag 323 */
+static int hf_fix_SecurityStatusReqID = -1; /* Tag 324 */
+static int hf_fix_UnsolicitedIndicator = -1; /* Tag 325 */
+static int hf_fix_SecurityTradingStatus = -1; /* Tag 326 */
+static int hf_fix_HaltReason = -1; /* Tag 327 */
+static int hf_fix_InViewOfCommon = -1; /* Tag 328 */
+static int hf_fix_DueToRelated = -1; /* Tag 329 */
+static int hf_fix_BuyVolume = -1; /* Tag 330 */
+static int hf_fix_SellVolume = -1; /* Tag 331 */
+static int hf_fix_HighPx = -1; /* Tag 332 */
+static int hf_fix_LowPx = -1; /* Tag 333 */
+static int hf_fix_Adjustment = -1; /* Tag 334 */
+static int hf_fix_TradSesReqID = -1; /* Tag 335 */
+static int hf_fix_TradingSessionID = -1; /* Tag 336 */
+static int hf_fix_ContraTrader = -1; /* Tag 337 */
+static int hf_fix_TradSesMethod = -1; /* Tag 338 */
+static int hf_fix_TradSesMode = -1; /* Tag 339 */
+static int hf_fix_TradSesStatus = -1; /* Tag 340 */
+static int hf_fix_TradSesStartTime = -1; /* Tag 341 */
+static int hf_fix_TradSesOpenTime = -1; /* Tag 342 */
+static int hf_fix_TradSesPreCloseTime = -1; /* Tag 343 */
+static int hf_fix_TradSesCloseTime = -1; /* Tag 344 */
+static int hf_fix_TradSesEndTime = -1; /* Tag 345 */
+static int hf_fix_NumberOfOrders = -1; /* Tag 346 */
+static int hf_fix_MessageEncoding = -1; /* Tag 347 */
+static int hf_fix_EncodedIssuerLen = -1; /* Tag 348 */
+static int hf_fix_EncodedIssuer = -1; /* Tag 349 */
+static int hf_fix_EncodedSecurityDescLen = -1; /* Tag 350 */
+static int hf_fix_EncodedSecurityDesc = -1; /* Tag 351 */
+static int hf_fix_EncodedListExecInstLen = -1; /* Tag 352 */
+static int hf_fix_EncodedListExecInst = -1; /* Tag 353 */
+static int hf_fix_EncodedTextLen = -1; /* Tag 354 */
+static int hf_fix_EncodedText = -1; /* Tag 355 */
+static int hf_fix_EncodedSubjectLen = -1; /* Tag 356 */
+static int hf_fix_EncodedSubject = -1; /* Tag 357 */
+static int hf_fix_EncodedHeadlineLen = -1; /* Tag 358 */
+static int hf_fix_EncodedHeadline = -1; /* Tag 359 */
+static int hf_fix_EncodedAllocTextLen = -1; /* Tag 360 */
+static int hf_fix_EncodedAllocText = -1; /* Tag 361 */
+static int hf_fix_EncodedUnderlyingIssuerLen = -1; /* Tag 362 */
+static int hf_fix_EncodedUnderlyingIssuer = -1; /* Tag 363 */
+static int hf_fix_EncodedUnderlyingSecurityDescLen = -1; /* Tag 364 */
+static int hf_fix_EncodedUnderlyingSecurityDesc = -1; /* Tag 365 */
+static int hf_fix_AllocPrice = -1; /* Tag 366 */
+static int hf_fix_QuoteSetValidUntilTime = -1; /* Tag 367 */
+static int hf_fix_QuoteEntryRejectReason = -1; /* Tag 368 */
+static int hf_fix_LastMsgSeqNumProcessed = -1; /* Tag 369 */
+static int hf_fix_OnBehalfOfSendingTime = -1; /* Tag 370 */
+static int hf_fix_RefTagID = -1; /* Tag 371 */
+static int hf_fix_RefMsgType = -1; /* Tag 372 */
+static int hf_fix_SessionRejectReason = -1; /* Tag 373 */
+static int hf_fix_BidRequestTransType = -1; /* Tag 374 */
+static int hf_fix_ContraBroker = -1; /* Tag 375 */
+static int hf_fix_ComplianceID = -1; /* Tag 376 */
+static int hf_fix_SolicitedFlag = -1; /* Tag 377 */
+static int hf_fix_ExecRestatementReason = -1; /* Tag 378 */
+static int hf_fix_BusinessRejectRefID = -1; /* Tag 379 */
+static int hf_fix_BusinessRejectReason = -1; /* Tag 380 */
+static int hf_fix_GrossTradeAmt = -1; /* Tag 381 */
+static int hf_fix_NoContraBrokers = -1; /* Tag 382 */
+static int hf_fix_MaxMessageSize = -1; /* Tag 383 */
+static int hf_fix_NoMsgTypes = -1; /* Tag 384 */
+static int hf_fix_MsgDirection = -1; /* Tag 385 */
+static int hf_fix_NoTradingSessions = -1; /* Tag 386 */
+static int hf_fix_TotalVolumeTraded = -1; /* Tag 387 */
+static int hf_fix_DiscretionInst = -1; /* Tag 388 */
+static int hf_fix_DiscretionOffset = -1; /* Tag 389 */
+static int hf_fix_BidID = -1; /* Tag 390 */
+static int hf_fix_ClientBidID = -1; /* Tag 391 */
+static int hf_fix_ListName = -1; /* Tag 392 */
+static int hf_fix_TotalNumSecurities = -1; /* Tag 393 */
+static int hf_fix_BidType = -1; /* Tag 394 */
+static int hf_fix_NumTickets = -1; /* Tag 395 */
+static int hf_fix_SideValue1 = -1; /* Tag 396 */
+static int hf_fix_SideValue2 = -1; /* Tag 397 */
+static int hf_fix_NoBidDescriptors = -1; /* Tag 398 */
+static int hf_fix_BidDescriptorType = -1; /* Tag 399 */
+static int hf_fix_BidDescriptor = -1; /* Tag 400 */
+static int hf_fix_SideValueInd = -1; /* Tag 401 */
+static int hf_fix_LiquidityPctLow = -1; /* Tag 402 */
+static int hf_fix_LiquidityPctHigh = -1; /* Tag 403 */
+static int hf_fix_LiquidityValue = -1; /* Tag 404 */
+static int hf_fix_EFPTrackingError = -1; /* Tag 405 */
+static int hf_fix_FairValue = -1; /* Tag 406 */
+static int hf_fix_OutsideIndexPct = -1; /* Tag 407 */
+static int hf_fix_ValueOfFutures = -1; /* Tag 408 */
+static int hf_fix_LiquidityIndType = -1; /* Tag 409 */
+static int hf_fix_WtAverageLiquidity = -1; /* Tag 410 */
+static int hf_fix_ExchangeForPhysical = -1; /* Tag 411 */
+static int hf_fix_OutMainCntryUIndex = -1; /* Tag 412 */
+static int hf_fix_CrossPercent = -1; /* Tag 413 */
+static int hf_fix_ProgRptReqs = -1; /* Tag 414 */
+static int hf_fix_ProgPeriodInterval = -1; /* Tag 415 */
+static int hf_fix_IncTaxInd = -1; /* Tag 416 */
+static int hf_fix_NumBidders = -1; /* Tag 417 */
+static int hf_fix_TradeType = -1; /* Tag 418 */
+static int hf_fix_BasisPxType = -1; /* Tag 419 */
+static int hf_fix_NoBidComponents = -1; /* Tag 420 */
+static int hf_fix_Country = -1; /* Tag 421 */
+static int hf_fix_TotNoStrikes = -1; /* Tag 422 */
+static int hf_fix_PriceType = -1; /* Tag 423 */
+static int hf_fix_DayOrderQty = -1; /* Tag 424 */
+static int hf_fix_DayCumQty = -1; /* Tag 425 */
+static int hf_fix_DayAvgPx = -1; /* Tag 426 */
+static int hf_fix_GTBookingInst = -1; /* Tag 427 */
+static int hf_fix_NoStrikes = -1; /* Tag 428 */
+static int hf_fix_ListStatusType = -1; /* Tag 429 */
+static int hf_fix_NetGrossInd = -1; /* Tag 430 */
+static int hf_fix_ListOrderStatus = -1; /* Tag 431 */
+static int hf_fix_ExpireDate = -1; /* Tag 432 */
+static int hf_fix_ListExecInstType = -1; /* Tag 433 */
+static int hf_fix_CxlRejResponseTo = -1; /* Tag 434 */
+static int hf_fix_UnderlyingCouponRate = -1; /* Tag 435 */
+static int hf_fix_UnderlyingContractMultiplier = -1; /* Tag 436 */
+static int hf_fix_ContraTradeQty = -1; /* Tag 437 */
+static int hf_fix_ContraTradeTime = -1; /* Tag 438 */
+static int hf_fix_ClearingFirm = -1; /* Tag 439 */
+static int hf_fix_ClearingAccount = -1; /* Tag 440 */
+static int hf_fix_LiquidityNumSecurities = -1; /* Tag 441 */
+static int hf_fix_MultiLegReportingType = -1; /* Tag 442 */
+static int hf_fix_StrikeTime = -1; /* Tag 443 */
+static int hf_fix_ListStatusText = -1; /* Tag 444 */
+static int hf_fix_EncodedListStatusTextLen = -1; /* Tag 445 */
+static int hf_fix_EncodedListStatusText = -1; /* Tag 446 */
+static int hf_fix_PartyIDSource = -1; /* Tag 447 */
+static int hf_fix_PartyID = -1; /* Tag 448 */
+static int hf_fix_TotalVolumeTradedDate = -1; /* Tag 449 */
+static int hf_fix_TotalVolumeTradedTime = -1; /* Tag 450 */
+static int hf_fix_NetChgPrevDay = -1; /* Tag 451 */
+static int hf_fix_PartyRole = -1; /* Tag 452 */
+static int hf_fix_NoPartyIDs = -1; /* Tag 453 */
+static int hf_fix_NoSecurityAltID = -1; /* Tag 454 */
+static int hf_fix_SecurityAltID = -1; /* Tag 455 */
+static int hf_fix_SecurityAltIDSource = -1; /* Tag 456 */
+static int hf_fix_NoUnderlyingSecurityAltID = -1; /* Tag 457 */
+static int hf_fix_UnderlyingSecurityAltID = -1; /* Tag 458 */
+static int hf_fix_UnderlyingSecurityAltIDSource = -1; /* Tag 459 */
+static int hf_fix_Product = -1; /* Tag 460 */
+static int hf_fix_CFICode = -1; /* Tag 461 */
+static int hf_fix_UnderlyingProduct = -1; /* Tag 462 */
+static int hf_fix_UnderlyingCFICode = -1; /* Tag 463 */
+static int hf_fix_TestMessageIndicator = -1; /* Tag 464 */
+static int hf_fix_QuantityType = -1; /* Tag 465 */
+static int hf_fix_BookingRefID = -1; /* Tag 466 */
+static int hf_fix_IndividualAllocID = -1; /* Tag 467 */
+static int hf_fix_RoundingDirection = -1; /* Tag 468 */
+static int hf_fix_RoundingModulus = -1; /* Tag 469 */
+static int hf_fix_CountryOfIssue = -1; /* Tag 470 */
+static int hf_fix_StateOrProvinceOfIssue = -1; /* Tag 471 */
+static int hf_fix_LocaleOfIssue = -1; /* Tag 472 */
+static int hf_fix_NoRegistDtls = -1; /* Tag 473 */
+static int hf_fix_MailingDtls = -1; /* Tag 474 */
+static int hf_fix_InvestorCountryOfResidence = -1; /* Tag 475 */
+static int hf_fix_PaymentRef = -1; /* Tag 476 */
+static int hf_fix_DistribPaymentMethod = -1; /* Tag 477 */
+static int hf_fix_CashDistribCurr = -1; /* Tag 478 */
+static int hf_fix_CommCurrency = -1; /* Tag 479 */
+static int hf_fix_CancellationRights = -1; /* Tag 480 */
+static int hf_fix_MoneyLaunderingStatus = -1; /* Tag 481 */
+static int hf_fix_MailingInst = -1; /* Tag 482 */
+static int hf_fix_TransBkdTime = -1; /* Tag 483 */
+static int hf_fix_ExecPriceType = -1; /* Tag 484 */
+static int hf_fix_ExecPriceAdjustment = -1; /* Tag 485 */
+static int hf_fix_DateOfBirth = -1; /* Tag 486 */
+static int hf_fix_TradeReportTransType = -1; /* Tag 487 */
+static int hf_fix_CardHolderName = -1; /* Tag 488 */
+static int hf_fix_CardNumber = -1; /* Tag 489 */
+static int hf_fix_CardExpDate = -1; /* Tag 490 */
+static int hf_fix_CardIssNo = -1; /* Tag 491 */
+static int hf_fix_PaymentMethod = -1; /* Tag 492 */
+static int hf_fix_RegistAcctType = -1; /* Tag 493 */
+static int hf_fix_Designation = -1; /* Tag 494 */
+static int hf_fix_TaxAdvantageType = -1; /* Tag 495 */
+static int hf_fix_RegistRejReasonText = -1; /* Tag 496 */
+static int hf_fix_FundRenewWaiv = -1; /* Tag 497 */
+static int hf_fix_CashDistribAgentName = -1; /* Tag 498 */
+static int hf_fix_CashDistribAgentCode = -1; /* Tag 499 */
+static int hf_fix_CashDistribAgentAcctNumber = -1; /* Tag 500 */
+static int hf_fix_CashDistribPayRef = -1; /* Tag 501 */
+static int hf_fix_CashDistribAgentAcctName = -1; /* Tag 502 */
+static int hf_fix_CardStartDate = -1; /* Tag 503 */
+static int hf_fix_PaymentDate = -1; /* Tag 504 */
+static int hf_fix_PaymentRemitterID = -1; /* Tag 505 */
+static int hf_fix_RegistStatus = -1; /* Tag 506 */
+static int hf_fix_RegistRejReasonCode = -1; /* Tag 507 */
+static int hf_fix_RegistRefID = -1; /* Tag 508 */
+static int hf_fix_RegistDetls = -1; /* Tag 509 */
+static int hf_fix_NoDistribInsts = -1; /* Tag 510 */
+static int hf_fix_RegistEmail = -1; /* Tag 511 */
+static int hf_fix_DistribPercentage = -1; /* Tag 512 */
+static int hf_fix_RegistID = -1; /* Tag 513 */
+static int hf_fix_RegistTransType = -1; /* Tag 514 */
+static int hf_fix_ExecValuationPoint = -1; /* Tag 515 */
+static int hf_fix_OrderPercent = -1; /* Tag 516 */
+static int hf_fix_OwnershipType = -1; /* Tag 517 */
+static int hf_fix_NoContAmts = -1; /* Tag 518 */
+static int hf_fix_ContAmtType = -1; /* Tag 519 */
+static int hf_fix_ContAmtValue = -1; /* Tag 520 */
+static int hf_fix_ContAmtCurr = -1; /* Tag 521 */
+static int hf_fix_OwnerType = -1; /* Tag 522 */
+static int hf_fix_PartySubID = -1; /* Tag 523 */
+static int hf_fix_NestedPartyID = -1; /* Tag 524 */
+static int hf_fix_NestedPartyIDSource = -1; /* Tag 525 */
+static int hf_fix_SecondaryClOrdID = -1; /* Tag 526 */
+static int hf_fix_SecondaryExecID = -1; /* Tag 527 */
+static int hf_fix_OrderCapacity = -1; /* Tag 528 */
+static int hf_fix_OrderRestrictions = -1; /* Tag 529 */
+static int hf_fix_MassCancelRequestType = -1; /* Tag 530 */
+static int hf_fix_MassCancelResponse = -1; /* Tag 531 */
+static int hf_fix_MassCancelRejectReason = -1; /* Tag 532 */
+static int hf_fix_TotalAffectedOrders = -1; /* Tag 533 */
+static int hf_fix_NoAffectedOrders = -1; /* Tag 534 */
+static int hf_fix_AffectedOrderID = -1; /* Tag 535 */
+static int hf_fix_AffectedSecondaryOrderID = -1; /* Tag 536 */
+static int hf_fix_QuoteType = -1; /* Tag 537 */
+static int hf_fix_NestedPartyRole = -1; /* Tag 538 */
+static int hf_fix_NoNestedPartyIDs = -1; /* Tag 539 */
+static int hf_fix_TotalAccruedInterestAmt = -1; /* Tag 540 */
+static int hf_fix_MaturityDate = -1; /* Tag 541 */
+static int hf_fix_UnderlyingMaturityDate = -1; /* Tag 542 */
+static int hf_fix_InstrRegistry = -1; /* Tag 543 */
+static int hf_fix_CashMargin = -1; /* Tag 544 */
+static int hf_fix_NestedPartySubID = -1; /* Tag 545 */
+static int hf_fix_Scope = -1; /* Tag 546 */
+static int hf_fix_MDImplicitDelete = -1; /* Tag 547 */
+static int hf_fix_CrossID = -1; /* Tag 548 */
+static int hf_fix_CrossType = -1; /* Tag 549 */
+static int hf_fix_CrossPrioritization = -1; /* Tag 550 */
+static int hf_fix_OrigCrossID = -1; /* Tag 551 */
+static int hf_fix_NoSides = -1; /* Tag 552 */
+static int hf_fix_Username = -1; /* Tag 553 */
+static int hf_fix_Password = -1; /* Tag 554 */
+static int hf_fix_NoLegs = -1; /* Tag 555 */
+static int hf_fix_LegCurrency = -1; /* Tag 556 */
+static int hf_fix_TotalNumSecurityTypes = -1; /* Tag 557 */
+static int hf_fix_NoSecurityTypes = -1; /* Tag 558 */
+static int hf_fix_SecurityListRequestType = -1; /* Tag 559 */
+static int hf_fix_SecurityRequestResult = -1; /* Tag 560 */
+static int hf_fix_RoundLot = -1; /* Tag 561 */
+static int hf_fix_MinTradeVol = -1; /* Tag 562 */
+static int hf_fix_MultiLegRptTypeReq = -1; /* Tag 563 */
+static int hf_fix_LegPositionEffect = -1; /* Tag 564 */
+static int hf_fix_LegCoveredOrUncovered = -1; /* Tag 565 */
+static int hf_fix_LegPrice = -1; /* Tag 566 */
+static int hf_fix_TradSesStatusRejReason = -1; /* Tag 567 */
+static int hf_fix_TradeRequestID = -1; /* Tag 568 */
+static int hf_fix_TradeRequestType = -1; /* Tag 569 */
+static int hf_fix_PreviouslyReported = -1; /* Tag 570 */
+static int hf_fix_TradeReportID = -1; /* Tag 571 */
+static int hf_fix_TradeReportRefID = -1; /* Tag 572 */
+static int hf_fix_MatchStatus = -1; /* Tag 573 */
+static int hf_fix_MatchType = -1; /* Tag 574 */
+static int hf_fix_OddLot = -1; /* Tag 575 */
+static int hf_fix_NoClearingInstructions = -1; /* Tag 576 */
+static int hf_fix_ClearingInstruction = -1; /* Tag 577 */
+static int hf_fix_TradeInputSource = -1; /* Tag 578 */
+static int hf_fix_TradeInputDevice = -1; /* Tag 579 */
+static int hf_fix_NoDates = -1; /* Tag 580 */
+static int hf_fix_AccountType = -1; /* Tag 581 */
+static int hf_fix_CustOrderCapacity = -1; /* Tag 582 */
+static int hf_fix_ClOrdLinkID = -1; /* Tag 583 */
+static int hf_fix_MassStatusReqID = -1; /* Tag 584 */
+static int hf_fix_MassStatusReqType = -1; /* Tag 585 */
+static int hf_fix_OrigOrdModTime = -1; /* Tag 586 */
+static int hf_fix_LegSettlmntTyp = -1; /* Tag 587 */
+static int hf_fix_LegFutSettDate = -1; /* Tag 588 */
+static int hf_fix_DayBookingInst = -1; /* Tag 589 */
+static int hf_fix_BookingUnit = -1; /* Tag 590 */
+static int hf_fix_PreallocMethod = -1; /* Tag 591 */
+static int hf_fix_UnderlyingCountryOfIssue = -1; /* Tag 592 */
+static int hf_fix_UnderlyingStateOrProvinceOfIssue = -1; /* Tag 593 */
+static int hf_fix_UnderlyingLocaleOfIssue = -1; /* Tag 594 */
+static int hf_fix_UnderlyingInstrRegistry = -1; /* Tag 595 */
+static int hf_fix_LegCountryOfIssue = -1; /* Tag 596 */
+static int hf_fix_LegStateOrProvinceOfIssue = -1; /* Tag 597 */
+static int hf_fix_LegLocaleOfIssue = -1; /* Tag 598 */
+static int hf_fix_LegInstrRegistry = -1; /* Tag 599 */
+static int hf_fix_LegSymbol = -1; /* Tag 600 */
+static int hf_fix_LegSymbolSfx = -1; /* Tag 601 */
+static int hf_fix_LegSecurityID = -1; /* Tag 602 */
+static int hf_fix_LegSecurityIDSource = -1; /* Tag 603 */
+static int hf_fix_NoLegSecurityAltID = -1; /* Tag 604 */
+static int hf_fix_LegSecurityAltID = -1; /* Tag 605 */
+static int hf_fix_LegSecurityAltIDSource = -1; /* Tag 606 */
+static int hf_fix_LegProduct = -1; /* Tag 607 */
+static int hf_fix_LegCFICode = -1; /* Tag 608 */
+static int hf_fix_LegSecurityType = -1; /* Tag 609 */
+static int hf_fix_LegMaturityMonthYear = -1; /* Tag 610 */
+static int hf_fix_LegMaturityDate = -1; /* Tag 611 */
+static int hf_fix_LegStrikePrice = -1; /* Tag 612 */
+static int hf_fix_LegOptAttribute = -1; /* Tag 613 */
+static int hf_fix_LegContractMultiplier = -1; /* Tag 614 */
+static int hf_fix_LegCouponRate = -1; /* Tag 615 */
+static int hf_fix_LegSecurityExchange = -1; /* Tag 616 */
+static int hf_fix_LegIssuer = -1; /* Tag 617 */
+static int hf_fix_EncodedLegIssuerLen = -1; /* Tag 618 */
+static int hf_fix_EncodedLegIssuer = -1; /* Tag 619 */
+static int hf_fix_LegSecurityDesc = -1; /* Tag 620 */
+static int hf_fix_EncodedLegSecurityDescLen = -1; /* Tag 621 */
+static int hf_fix_EncodedLegSecurityDesc = -1; /* Tag 622 */
+static int hf_fix_LegRatioQty = -1; /* Tag 623 */
+static int hf_fix_LegSide = -1; /* Tag 624 */
+static int hf_fix_TradingSessionSubID = -1; /* Tag 625 */
+static int hf_fix_AllocType = -1; /* Tag 626 */
+static int hf_fix_NoHops = -1; /* Tag 627 */
+static int hf_fix_HopCompID = -1; /* Tag 628 */
+static int hf_fix_HopSendingTime = -1; /* Tag 629 */
+static int hf_fix_HopRefID = -1; /* Tag 630 */
+static int hf_fix_MidPx = -1; /* Tag 631 */
+static int hf_fix_BidYield = -1; /* Tag 632 */
+static int hf_fix_MidYield = -1; /* Tag 633 */
+static int hf_fix_OfferYield = -1; /* Tag 634 */
+static int hf_fix_ClearingFeeIndicator = -1; /* Tag 635 */
+static int hf_fix_WorkingIndicator = -1; /* Tag 636 */
+static int hf_fix_LegLastPx = -1; /* Tag 637 */
+static int hf_fix_PriorityIndicator = -1; /* Tag 638 */
+static int hf_fix_PriceImprovement = -1; /* Tag 639 */
+static int hf_fix_Price2 = -1; /* Tag 640 */
+static int hf_fix_LastForwardPoints2 = -1; /* Tag 641 */
+static int hf_fix_BidForwardPoints2 = -1; /* Tag 642 */
+static int hf_fix_OfferForwardPoints2 = -1; /* Tag 643 */
+static int hf_fix_RFQReqID = -1; /* Tag 644 */
+static int hf_fix_MktBidPx = -1; /* Tag 645 */
+static int hf_fix_MktOfferPx = -1; /* Tag 646 */
+static int hf_fix_MinBidSize = -1; /* Tag 647 */
+static int hf_fix_MinOfferSize = -1; /* Tag 648 */
+static int hf_fix_QuoteStatusReqID = -1; /* Tag 649 */
+static int hf_fix_LegalConfirm = -1; /* Tag 650 */
+static int hf_fix_UnderlyingLastPx = -1; /* Tag 651 */
+static int hf_fix_UnderlyingLastQty = -1; /* Tag 652 */
+static int hf_fix_SecDefStatus = -1; /* Tag 653 */
+static int hf_fix_LegRefID = -1; /* Tag 654 */
+static int hf_fix_ContraLegRefID = -1; /* Tag 655 */
+static int hf_fix_SettlCurrBidFxRate = -1; /* Tag 656 */
+static int hf_fix_SettlCurrOfferFxRate = -1; /* Tag 657 */
+static int hf_fix_QuoteRequestRejectReason = -1; /* Tag 658 */
+static int hf_fix_SideComplianceID = -1; /* Tag 659 */
+
+static void dissect_fix_init(void) {
+ g_datalist_clear(&msg_types);
+
+ g_datalist_init(&msg_types);
+
+ g_datalist_set_data(&msg_types, "0", "Heartbeat");
+ g_datalist_set_data(&msg_types, "1", "Test Request");
+ g_datalist_set_data(&msg_types, "2", "Resend Request");
+ g_datalist_set_data(&msg_types, "3", "Reject");
+ g_datalist_set_data(&msg_types, "4", "Sequence Reset");
+ g_datalist_set_data(&msg_types, "5", "Logout");
+ g_datalist_set_data(&msg_types, "6", "Indication of Interest");
+ g_datalist_set_data(&msg_types, "7", "Advertisement");
+ g_datalist_set_data(&msg_types, "8", "Execution Report");
+ g_datalist_set_data(&msg_types, "9", "Order Cancel Reject");
+ g_datalist_set_data(&msg_types, "A", "Logon");
+ g_datalist_set_data(&msg_types, "B", "News");
+ g_datalist_set_data(&msg_types, "C", "Email");
+ g_datalist_set_data(&msg_types, "D", "Order - Single");
+ g_datalist_set_data(&msg_types, "E", "Order - List");
+ g_datalist_set_data(&msg_types, "F", "Order Cancel Request");
+ g_datalist_set_data(&msg_types, "G", "Order Cancel - Replace Request");
+ g_datalist_set_data(&msg_types, "H", "Order Status Request");
+ g_datalist_set_data(&msg_types, "J", "Allocation");
+ g_datalist_set_data(&msg_types, "K", "List Cancel Request");
+ g_datalist_set_data(&msg_types, "L", "List Execute");
+ g_datalist_set_data(&msg_types, "M", "List Status Request");
+ g_datalist_set_data(&msg_types, "N", "List Status");
+ g_datalist_set_data(&msg_types, "P", "Allocation ACK");
+ g_datalist_set_data(&msg_types, "Q", "Don't Know Trade (DK)");
+ g_datalist_set_data(&msg_types, "R", "Quote Request");
+ g_datalist_set_data(&msg_types, "S", "Quote");
+ g_datalist_set_data(&msg_types, "T", "Settlement Instructions");
+ g_datalist_set_data(&msg_types, "V", "Market Data Request");
+ g_datalist_set_data(&msg_types, "W", "Market Data-Snapshot - Full Refresh");
+ g_datalist_set_data(&msg_types, "X", "Market Data-Incremental Refresh");
+ g_datalist_set_data(&msg_types, "Y", "Market Data Request Reject");
+ g_datalist_set_data(&msg_types, "Z", "Quote Cancel");
+ g_datalist_set_data(&msg_types, "a", "Quote Status Request");
+ g_datalist_set_data(&msg_types, "b", "Mass Quote Acknowledgement");
+ g_datalist_set_data(&msg_types, "c", "Security Definition Request");
+ g_datalist_set_data(&msg_types, "d", "Security Definition");
+ g_datalist_set_data(&msg_types, "e", "Security Status Request");
+ g_datalist_set_data(&msg_types, "f", "Security Status");
+ g_datalist_set_data(&msg_types, "g", "Trading Session Status Request");
+ g_datalist_set_data(&msg_types, "h", "Trading Session Status");
+ g_datalist_set_data(&msg_types, "i", "Mass Quote");
+ g_datalist_set_data(&msg_types, "j", "Business Message Reject");
+ g_datalist_set_data(&msg_types, "k", "Bid Request ");
+ g_datalist_set_data(&msg_types, "l", "Bid Response");
+ g_datalist_set_data(&msg_types, "m", "List Strike Price");
+ g_datalist_set_data(&msg_types, "n", "XML message");
+ g_datalist_set_data(&msg_types, "o", "Registration Instructions");
+ g_datalist_set_data(&msg_types, "p", "Registration Instructions Response");
+ g_datalist_set_data(&msg_types, "q", "Order Mass Cancel Request");
+ g_datalist_set_data(&msg_types, "r", "Order Mass Cancel Report");
+ g_datalist_set_data(&msg_types, "s", "New Order - Cross");
+ g_datalist_set_data(&msg_types, "t", "Cross Order Cancel - Replace Request");
+ g_datalist_set_data(&msg_types, "u", "Cross Order Cancel Request");
+ g_datalist_set_data(&msg_types, "v", "Security Type Request");
+ g_datalist_set_data(&msg_types, "w", "Security Types");
+ g_datalist_set_data(&msg_types, "x", "Security List Request");
+ g_datalist_set_data(&msg_types, "y", "Security List");
+ g_datalist_set_data(&msg_types, "z", "Derivative Security List Request");
+ g_datalist_set_data(&msg_types, "AA", "Derivative Security List");
+ g_datalist_set_data(&msg_types, "AB", "New Order - Multileg");
+ g_datalist_set_data(&msg_types, "AC", "Multileg Order Cancel - Replace");
+ g_datalist_set_data(&msg_types, "AD", "Trade Capture Report Request");
+ g_datalist_set_data(&msg_types, "AE", "Trade Capture Report");
+ g_datalist_set_data(&msg_types, "AF", "Order Mass Status Request");
+ g_datalist_set_data(&msg_types, "AG", "Quote Request Reject");
+ g_datalist_set_data(&msg_types, "AH", "RFQ Request");
+ g_datalist_set_data(&msg_types, "AI", "Quote Status Report");
+
+}
+
+/* Code to actually dissect the packets */
+static gboolean
+dissect_fix(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *fix_tree;
+
+ gint next;
+ int linelen;
+ int offset = 0;
+ int field_offset, value_offset, ctrla_offset, equals;
+ int tag;
+ char *value;
+ char *tag_str;
+ int field_len = 0;
+ int tag_len = 0;
+ int value_len = 0;
+
+ /* get at least the fix version: 8=FIX.x.x */
+ if (tvb_strneql(tvb, 0, "8=FIX.", 6) != 0) {
+ /* not a fix packet */
+ return FALSE;
+ }
+
+ linelen = tvb_find_line_end(tvb, 0, -1, &next, 0);
+
+ /* begin string */
+ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01);
+ if (ctrla_offset == -1) {
+ return FALSE;
+ }
+ offset = ctrla_offset + 1;
+
+ /* msg length */
+ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01);
+ if (ctrla_offset == -1) {
+ return FALSE;
+ }
+ offset = ctrla_offset + 1;
+
+ /* msg type */
+ field_offset = offset;
+ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01);
+ if (ctrla_offset == -1) {
+ return FALSE;
+ }
+
+ field_len = ctrla_offset - field_offset + 1;
+ equals = tvb_find_guint8(tvb, offset, field_len, '=');
+ if (equals == -1) {
+ return FALSE;
+ }
+
+ value_offset = equals + 1;
+ value_len = ctrla_offset - value_offset;
+ if (value_len < 1) {
+ return FALSE;
+ }
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FIX");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ value = tvb_get_string(tvb, value_offset, value_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", (char *)g_datalist_get_data(&msg_types, value));
+ }
+
+ g_free(value);
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree) {
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_fix, tvb, 0, -1, FALSE);
+ fix_tree = proto_item_add_subtree(ti, ett_fix);
+
+ field_offset = offset = 0;
+ ctrla_offset = tvb_find_guint8(tvb, offset, -1, 0x01);
+ if (ctrla_offset == -1) {
+ /* XXX - put an error indication here. It's too late
+ to return FALSE; we've already started dissecting,
+ and if a heuristic dissector starts dissecting
+ (either updating the columns or creating a protocol
+ tree) and then gives up, it leaves crud behind that
+ messes up other dissectors that might process the
+ packet. */
+ return TRUE;
+ }
+
+ while(ctrla_offset != -1 && offset < linelen) {
+ field_len = ctrla_offset - field_offset + 1;
+ if(offset >= linelen) {
+ break;
+ }
+
+ equals = tvb_find_guint8(tvb, offset, field_len, '=');
+ if (equals == -1) {
+ /* XXX - put an error indication here. It's too late
+ to return FALSE; we've already started dissecting,
+ and if a heuristic dissector starts dissecting
+ (either updating the columns or creating a protocol
+ tree) and then gives up, it leaves crud behind that
+ messes up other dissectors that might process the
+ packet. */
+ return TRUE;
+ }
+
+ value_offset = equals + 1;
+ value_len = ctrla_offset - value_offset;
+
+ tag_len = equals - field_offset;
+ if (tag_len < 1 || value_len < 1) {
+ /* XXX - put an error indication here. It's too late
+ to return FALSE; we've already started dissecting,
+ and if a heuristic dissector starts dissecting
+ (either updating the columns or creating a protocol
+ tree) and then gives up, it leaves crud behind that
+ messes up other dissectors that might process the
+ packet. */
+ return TRUE;
+ }
+ tag_str = tvb_get_string(tvb, field_offset, tag_len);
+ tag = atoi(tag_str);
+
+ value = tvb_get_string(tvb, value_offset, value_len);
+
+ switch(tag) {
+ case 1: /* Field Account */
+ proto_tree_add_string(fix_tree, hf_fix_Account, tvb, offset, field_len, value);
+ break;
+ case 2: /* Field AdvId */
+ proto_tree_add_string(fix_tree, hf_fix_AdvId, tvb, offset, field_len, value);
+ break;
+ case 3: /* Field AdvRefID */
+ proto_tree_add_string(fix_tree, hf_fix_AdvRefID, tvb, offset, field_len, value);
+ break;
+ case 4: /* Field AdvSide */
+ proto_tree_add_string(fix_tree, hf_fix_AdvSide, tvb, offset, field_len, value);
+ break;
+ case 5: /* Field AdvTransType */
+ proto_tree_add_string(fix_tree, hf_fix_AdvTransType, tvb, offset, field_len, value);
+ break;
+ case 6: /* Field AvgPx */
+ proto_tree_add_string(fix_tree, hf_fix_AvgPx, tvb, offset, field_len, value);
+ break;
+ case 7: /* Field BeginSeqNo */
+ proto_tree_add_string(fix_tree, hf_fix_BeginSeqNo, tvb, offset, field_len, value);
+ break;
+ case 8: /* Field BeginString */
+ proto_tree_add_string(fix_tree, hf_fix_BeginString, tvb, offset, field_len, value);
+ break;
+ case 9: /* Field BodyLength */
+ proto_tree_add_string(fix_tree, hf_fix_BodyLength, tvb, offset, field_len, value);
+ break;
+ case 10: /* Field CheckSum */
+ proto_tree_add_string(fix_tree, hf_fix_CheckSum, tvb, offset, field_len, value);
+ break;
+ case 11: /* Field ClOrdID */
+ proto_tree_add_string(fix_tree, hf_fix_ClOrdID, tvb, offset, field_len, value);
+ break;
+ case 12: /* Field Commission */
+ proto_tree_add_string(fix_tree, hf_fix_Commission, tvb, offset, field_len, value);
+ break;
+ case 13: /* Field CommType */
+ proto_tree_add_string(fix_tree, hf_fix_CommType, tvb, offset, field_len, value);
+ break;
+ case 14: /* Field CumQty */
+ proto_tree_add_string(fix_tree, hf_fix_CumQty, tvb, offset, field_len, value);
+ break;
+ case 15: /* Field Currency */
+ proto_tree_add_string(fix_tree, hf_fix_Currency, tvb, offset, field_len, value);
+ break;
+ case 16: /* Field EndSeqNo */
+ proto_tree_add_string(fix_tree, hf_fix_EndSeqNo, tvb, offset, field_len, value);
+ break;
+ case 17: /* Field ExecID */
+ proto_tree_add_string(fix_tree, hf_fix_ExecID, tvb, offset, field_len, value);
+ break;
+ case 18: /* Field ExecInst */
+ proto_tree_add_string(fix_tree, hf_fix_ExecInst, tvb, offset, field_len, value);
+ break;
+ case 19: /* Field ExecRefID */
+ proto_tree_add_string(fix_tree, hf_fix_ExecRefID, tvb, offset, field_len, value);
+ break;
+ case 20: /* Field ExecTransType */
+ proto_tree_add_string(fix_tree, hf_fix_ExecTransType, tvb, offset, field_len, value);
+ break;
+ case 21: /* Field HandlInst */
+ proto_tree_add_string(fix_tree, hf_fix_HandlInst, tvb, offset, field_len, value);
+ break;
+ case 22: /* Field SecurityIDSource */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityIDSource, tvb, offset, field_len, value);
+ break;
+ case 23: /* Field IOIid */
+ proto_tree_add_string(fix_tree, hf_fix_IOIid, tvb, offset, field_len, value);
+ break;
+ case 24: /* Field IOIOthSvc */
+ proto_tree_add_string(fix_tree, hf_fix_IOIOthSvc, tvb, offset, field_len, value);
+ break;
+ case 25: /* Field IOIQltyInd */
+ proto_tree_add_string(fix_tree, hf_fix_IOIQltyInd, tvb, offset, field_len, value);
+ break;
+ case 26: /* Field IOIRefID */
+ proto_tree_add_string(fix_tree, hf_fix_IOIRefID, tvb, offset, field_len, value);
+ break;
+ case 27: /* Field IOIQty */
+ proto_tree_add_string(fix_tree, hf_fix_IOIQty, tvb, offset, field_len, value);
+ break;
+ case 28: /* Field IOITransType */
+ proto_tree_add_string(fix_tree, hf_fix_IOITransType, tvb, offset, field_len, value);
+ break;
+ case 29: /* Field LastCapacity */
+ proto_tree_add_string(fix_tree, hf_fix_LastCapacity, tvb, offset, field_len, value);
+ break;
+ case 30: /* Field LastMkt */
+ proto_tree_add_string(fix_tree, hf_fix_LastMkt, tvb, offset, field_len, value);
+ break;
+ case 31: /* Field LastPx */
+ proto_tree_add_string(fix_tree, hf_fix_LastPx, tvb, offset, field_len, value);
+ break;
+ case 32: /* Field LastQty */
+ proto_tree_add_string(fix_tree, hf_fix_LastQty, tvb, offset, field_len, value);
+ break;
+ case 33: /* Field LinesOfText */
+ proto_tree_add_string(fix_tree, hf_fix_LinesOfText, tvb, offset, field_len, value);
+ break;
+ case 34: /* Field MsgSeqNum */
+ proto_tree_add_string(fix_tree, hf_fix_MsgSeqNum, tvb, offset, field_len, value);
+ break;
+ case 35: /* Field MsgType */
+ proto_tree_add_string(fix_tree, hf_fix_MsgType, tvb, offset, field_len, value);
+ break;
+ case 36: /* Field NewSeqNo */
+ proto_tree_add_string(fix_tree, hf_fix_NewSeqNo, tvb, offset, field_len, value);
+ break;
+ case 37: /* Field OrderID */
+ proto_tree_add_string(fix_tree, hf_fix_OrderID, tvb, offset, field_len, value);
+ break;
+ case 38: /* Field OrderQty */
+ proto_tree_add_string(fix_tree, hf_fix_OrderQty, tvb, offset, field_len, value);
+ break;
+ case 39: /* Field OrdStatus */
+ proto_tree_add_string(fix_tree, hf_fix_OrdStatus, tvb, offset, field_len, value);
+ break;
+ case 40: /* Field OrdType */
+ proto_tree_add_string(fix_tree, hf_fix_OrdType, tvb, offset, field_len, value);
+ break;
+ case 41: /* Field OrigClOrdID */
+ proto_tree_add_string(fix_tree, hf_fix_OrigClOrdID, tvb, offset, field_len, value);
+ break;
+ case 42: /* Field OrigTime */
+ proto_tree_add_string(fix_tree, hf_fix_OrigTime, tvb, offset, field_len, value);
+ break;
+ case 43: /* Field PossDupFlag */
+ proto_tree_add_string(fix_tree, hf_fix_PossDupFlag, tvb, offset, field_len, value);
+ break;
+ case 44: /* Field Price */
+ proto_tree_add_string(fix_tree, hf_fix_Price, tvb, offset, field_len, value);
+ break;
+ case 45: /* Field RefSeqNum */
+ proto_tree_add_string(fix_tree, hf_fix_RefSeqNum, tvb, offset, field_len, value);
+ break;
+ case 46: /* Field RelatdSym */
+ proto_tree_add_string(fix_tree, hf_fix_RelatdSym, tvb, offset, field_len, value);
+ break;
+ case 47: /* Field Rule80A */
+ proto_tree_add_string(fix_tree, hf_fix_Rule80A, tvb, offset, field_len, value);
+ break;
+ case 48: /* Field SecurityID */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityID, tvb, offset, field_len, value);
+ break;
+ case 49: /* Field SenderCompID */
+ proto_tree_add_string(fix_tree, hf_fix_SenderCompID, tvb, offset, field_len, value);
+ break;
+ case 50: /* Field SenderSubID */
+ proto_tree_add_string(fix_tree, hf_fix_SenderSubID, tvb, offset, field_len, value);
+ break;
+ case 51: /* Field SendingDate */
+ proto_tree_add_string(fix_tree, hf_fix_SendingDate, tvb, offset, field_len, value);
+ break;
+ case 52: /* Field SendingTime */
+ proto_tree_add_string(fix_tree, hf_fix_SendingTime, tvb, offset, field_len, value);
+ break;
+ case 53: /* Field Quantity */
+ proto_tree_add_string(fix_tree, hf_fix_Quantity, tvb, offset, field_len, value);
+ break;
+ case 54: /* Field Side */
+ proto_tree_add_string(fix_tree, hf_fix_Side, tvb, offset, field_len, value);
+ break;
+ case 55: /* Field Symbol */
+ proto_tree_add_string(fix_tree, hf_fix_Symbol, tvb, offset, field_len, value);
+ break;
+ case 56: /* Field TargetCompID */
+ proto_tree_add_string(fix_tree, hf_fix_TargetCompID, tvb, offset, field_len, value);
+ break;
+ case 57: /* Field TargetSubID */
+ proto_tree_add_string(fix_tree, hf_fix_TargetSubID, tvb, offset, field_len, value);
+ break;
+ case 58: /* Field Text */
+ proto_tree_add_string(fix_tree, hf_fix_Text, tvb, offset, field_len, value);
+ break;
+ case 59: /* Field TimeInForce */
+ proto_tree_add_string(fix_tree, hf_fix_TimeInForce, tvb, offset, field_len, value);
+ break;
+ case 60: /* Field TransactTime */
+ proto_tree_add_string(fix_tree, hf_fix_TransactTime, tvb, offset, field_len, value);
+ break;
+ case 61: /* Field Urgency */
+ proto_tree_add_string(fix_tree, hf_fix_Urgency, tvb, offset, field_len, value);
+ break;
+ case 62: /* Field ValidUntilTime */
+ proto_tree_add_string(fix_tree, hf_fix_ValidUntilTime, tvb, offset, field_len, value);
+ break;
+ case 63: /* Field SettlmntTyp */
+ proto_tree_add_string(fix_tree, hf_fix_SettlmntTyp, tvb, offset, field_len, value);
+ break;
+ case 64: /* Field FutSettDate */
+ proto_tree_add_string(fix_tree, hf_fix_FutSettDate, tvb, offset, field_len, value);
+ break;
+ case 65: /* Field SymbolSfx */
+ proto_tree_add_string(fix_tree, hf_fix_SymbolSfx, tvb, offset, field_len, value);
+ break;
+ case 66: /* Field ListID */
+ proto_tree_add_string(fix_tree, hf_fix_ListID, tvb, offset, field_len, value);
+ break;
+ case 67: /* Field ListSeqNo */
+ proto_tree_add_string(fix_tree, hf_fix_ListSeqNo, tvb, offset, field_len, value);
+ break;
+ case 68: /* Field TotNoOrders */
+ proto_tree_add_string(fix_tree, hf_fix_TotNoOrders, tvb, offset, field_len, value);
+ break;
+ case 69: /* Field ListExecInst */
+ proto_tree_add_string(fix_tree, hf_fix_ListExecInst, tvb, offset, field_len, value);
+ break;
+ case 70: /* Field AllocID */
+ proto_tree_add_string(fix_tree, hf_fix_AllocID, tvb, offset, field_len, value);
+ break;
+ case 71: /* Field AllocTransType */
+ proto_tree_add_string(fix_tree, hf_fix_AllocTransType, tvb, offset, field_len, value);
+ break;
+ case 72: /* Field RefAllocID */
+ proto_tree_add_string(fix_tree, hf_fix_RefAllocID, tvb, offset, field_len, value);
+ break;
+ case 73: /* Field NoOrders */
+ proto_tree_add_string(fix_tree, hf_fix_NoOrders, tvb, offset, field_len, value);
+ break;
+ case 74: /* Field AvgPrxPrecision */
+ proto_tree_add_string(fix_tree, hf_fix_AvgPrxPrecision, tvb, offset, field_len, value);
+ break;
+ case 75: /* Field TradeDate */
+ proto_tree_add_string(fix_tree, hf_fix_TradeDate, tvb, offset, field_len, value);
+ break;
+ case 76: /* Field ExecBroker */
+ proto_tree_add_string(fix_tree, hf_fix_ExecBroker, tvb, offset, field_len, value);
+ break;
+ case 77: /* Field PositionEffect */
+ proto_tree_add_string(fix_tree, hf_fix_PositionEffect, tvb, offset, field_len, value);
+ break;
+ case 78: /* Field NoAllocs */
+ proto_tree_add_string(fix_tree, hf_fix_NoAllocs, tvb, offset, field_len, value);
+ break;
+ case 79: /* Field AllocAccount */
+ proto_tree_add_string(fix_tree, hf_fix_AllocAccount, tvb, offset, field_len, value);
+ break;
+ case 80: /* Field AllocQty */
+ proto_tree_add_string(fix_tree, hf_fix_AllocQty, tvb, offset, field_len, value);
+ break;
+ case 81: /* Field ProcessCode */
+ proto_tree_add_string(fix_tree, hf_fix_ProcessCode, tvb, offset, field_len, value);
+ break;
+ case 82: /* Field NoRpts */
+ proto_tree_add_string(fix_tree, hf_fix_NoRpts, tvb, offset, field_len, value);
+ break;
+ case 83: /* Field RptSeq */
+ proto_tree_add_string(fix_tree, hf_fix_RptSeq, tvb, offset, field_len, value);
+ break;
+ case 84: /* Field CxlQty */
+ proto_tree_add_string(fix_tree, hf_fix_CxlQty, tvb, offset, field_len, value);
+ break;
+ case 85: /* Field NoDlvyInst */
+ proto_tree_add_string(fix_tree, hf_fix_NoDlvyInst, tvb, offset, field_len, value);
+ break;
+ case 86: /* Field DlvyInst */
+ proto_tree_add_string(fix_tree, hf_fix_DlvyInst, tvb, offset, field_len, value);
+ break;
+ case 87: /* Field AllocStatus */
+ proto_tree_add_string(fix_tree, hf_fix_AllocStatus, tvb, offset, field_len, value);
+ break;
+ case 88: /* Field AllocRejCode */
+ proto_tree_add_string(fix_tree, hf_fix_AllocRejCode, tvb, offset, field_len, value);
+ break;
+ case 89: /* Field Signature */
+ proto_tree_add_string(fix_tree, hf_fix_Signature, tvb, offset, field_len, value);
+ break;
+ case 90: /* Field SecureDataLen */
+ proto_tree_add_string(fix_tree, hf_fix_SecureDataLen, tvb, offset, field_len, value);
+ break;
+ case 91: /* Field SecureData */
+ proto_tree_add_string(fix_tree, hf_fix_SecureData, tvb, offset, field_len, value);
+ break;
+ case 92: /* Field BrokerOfCredit */
+ proto_tree_add_string(fix_tree, hf_fix_BrokerOfCredit, tvb, offset, field_len, value);
+ break;
+ case 93: /* Field SignatureLength */
+ proto_tree_add_string(fix_tree, hf_fix_SignatureLength, tvb, offset, field_len, value);
+ break;
+ case 94: /* Field EmailType */
+ proto_tree_add_string(fix_tree, hf_fix_EmailType, tvb, offset, field_len, value);
+ break;
+ case 95: /* Field RawDataLength */
+ proto_tree_add_string(fix_tree, hf_fix_RawDataLength, tvb, offset, field_len, value);
+ break;
+ case 96: /* Field RawData */
+ proto_tree_add_string(fix_tree, hf_fix_RawData, tvb, offset, field_len, value);
+ break;
+ case 97: /* Field PossResend */
+ proto_tree_add_string(fix_tree, hf_fix_PossResend, tvb, offset, field_len, value);
+ break;
+ case 98: /* Field EncryptMethod */
+ proto_tree_add_string(fix_tree, hf_fix_EncryptMethod, tvb, offset, field_len, value);
+ break;
+ case 99: /* Field StopPx */
+ proto_tree_add_string(fix_tree, hf_fix_StopPx, tvb, offset, field_len, value);
+ break;
+ case 100: /* Field ExDestination */
+ proto_tree_add_string(fix_tree, hf_fix_ExDestination, tvb, offset, field_len, value);
+ break;
+ case 102: /* Field CxlRejReason */
+ proto_tree_add_string(fix_tree, hf_fix_CxlRejReason, tvb, offset, field_len, value);
+ break;
+ case 103: /* Field OrdRejReason */
+ proto_tree_add_string(fix_tree, hf_fix_OrdRejReason, tvb, offset, field_len, value);
+ break;
+ case 104: /* Field IOIQualifier */
+ proto_tree_add_string(fix_tree, hf_fix_IOIQualifier, tvb, offset, field_len, value);
+ break;
+ case 105: /* Field WaveNo */
+ proto_tree_add_string(fix_tree, hf_fix_WaveNo, tvb, offset, field_len, value);
+ break;
+ case 106: /* Field Issuer */
+ proto_tree_add_string(fix_tree, hf_fix_Issuer, tvb, offset, field_len, value);
+ break;
+ case 107: /* Field SecurityDesc */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityDesc, tvb, offset, field_len, value);
+ break;
+ case 108: /* Field HeartBtInt */
+ proto_tree_add_string(fix_tree, hf_fix_HeartBtInt, tvb, offset, field_len, value);
+ break;
+ case 109: /* Field ClientID */
+ proto_tree_add_string(fix_tree, hf_fix_ClientID, tvb, offset, field_len, value);
+ break;
+ case 110: /* Field MinQty */
+ proto_tree_add_string(fix_tree, hf_fix_MinQty, tvb, offset, field_len, value);
+ break;
+ case 111: /* Field MaxFloor */
+ proto_tree_add_string(fix_tree, hf_fix_MaxFloor, tvb, offset, field_len, value);
+ break;
+ case 112: /* Field TestReqID */
+ proto_tree_add_string(fix_tree, hf_fix_TestReqID, tvb, offset, field_len, value);
+ break;
+ case 113: /* Field ReportToExch */
+ proto_tree_add_string(fix_tree, hf_fix_ReportToExch, tvb, offset, field_len, value);
+ break;
+ case 114: /* Field LocateReqd */
+ proto_tree_add_string(fix_tree, hf_fix_LocateReqd, tvb, offset, field_len, value);
+ break;
+ case 115: /* Field OnBehalfOfCompID */
+ proto_tree_add_string(fix_tree, hf_fix_OnBehalfOfCompID, tvb, offset, field_len, value);
+ break;
+ case 116: /* Field OnBehalfOfSubID */
+ proto_tree_add_string(fix_tree, hf_fix_OnBehalfOfSubID, tvb, offset, field_len, value);
+ break;
+ case 117: /* Field QuoteID */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteID, tvb, offset, field_len, value);
+ break;
+ case 118: /* Field NetMoney */
+ proto_tree_add_string(fix_tree, hf_fix_NetMoney, tvb, offset, field_len, value);
+ break;
+ case 119: /* Field SettlCurrAmt */
+ proto_tree_add_string(fix_tree, hf_fix_SettlCurrAmt, tvb, offset, field_len, value);
+ break;
+ case 120: /* Field SettlCurrency */
+ proto_tree_add_string(fix_tree, hf_fix_SettlCurrency, tvb, offset, field_len, value);
+ break;
+ case 121: /* Field ForexReq */
+ proto_tree_add_string(fix_tree, hf_fix_ForexReq, tvb, offset, field_len, value);
+ break;
+ case 122: /* Field OrigSendingTime */
+ proto_tree_add_string(fix_tree, hf_fix_OrigSendingTime, tvb, offset, field_len, value);
+ break;
+ case 123: /* Field GapFillFlag */
+ proto_tree_add_string(fix_tree, hf_fix_GapFillFlag, tvb, offset, field_len, value);
+ break;
+ case 124: /* Field NoExecs */
+ proto_tree_add_string(fix_tree, hf_fix_NoExecs, tvb, offset, field_len, value);
+ break;
+ case 125: /* Field CxlType */
+ proto_tree_add_string(fix_tree, hf_fix_CxlType, tvb, offset, field_len, value);
+ break;
+ case 126: /* Field ExpireTime */
+ proto_tree_add_string(fix_tree, hf_fix_ExpireTime, tvb, offset, field_len, value);
+ break;
+ case 127: /* Field DKReason */
+ proto_tree_add_string(fix_tree, hf_fix_DKReason, tvb, offset, field_len, value);
+ break;
+ case 128: /* Field DeliverToCompID */
+ proto_tree_add_string(fix_tree, hf_fix_DeliverToCompID, tvb, offset, field_len, value);
+ break;
+ case 129: /* Field DeliverToSubID */
+ proto_tree_add_string(fix_tree, hf_fix_DeliverToSubID, tvb, offset, field_len, value);
+ break;
+ case 130: /* Field IOINaturalFlag */
+ proto_tree_add_string(fix_tree, hf_fix_IOINaturalFlag, tvb, offset, field_len, value);
+ break;
+ case 131: /* Field QuoteReqID */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteReqID, tvb, offset, field_len, value);
+ break;
+ case 132: /* Field BidPx */
+ proto_tree_add_string(fix_tree, hf_fix_BidPx, tvb, offset, field_len, value);
+ break;
+ case 133: /* Field OfferPx */
+ proto_tree_add_string(fix_tree, hf_fix_OfferPx, tvb, offset, field_len, value);
+ break;
+ case 134: /* Field BidSize */
+ proto_tree_add_string(fix_tree, hf_fix_BidSize, tvb, offset, field_len, value);
+ break;
+ case 135: /* Field OfferSize */
+ proto_tree_add_string(fix_tree, hf_fix_OfferSize, tvb, offset, field_len, value);
+ break;
+ case 136: /* Field NoMiscFees */
+ proto_tree_add_string(fix_tree, hf_fix_NoMiscFees, tvb, offset, field_len, value);
+ break;
+ case 137: /* Field MiscFeeAmt */
+ proto_tree_add_string(fix_tree, hf_fix_MiscFeeAmt, tvb, offset, field_len, value);
+ break;
+ case 138: /* Field MiscFeeCurr */
+ proto_tree_add_string(fix_tree, hf_fix_MiscFeeCurr, tvb, offset, field_len, value);
+ break;
+ case 139: /* Field MiscFeeType */
+ proto_tree_add_string(fix_tree, hf_fix_MiscFeeType, tvb, offset, field_len, value);
+ break;
+ case 140: /* Field PrevClosePx */
+ proto_tree_add_string(fix_tree, hf_fix_PrevClosePx, tvb, offset, field_len, value);
+ break;
+ case 141: /* Field ResetSeqNumFlag */
+ proto_tree_add_string(fix_tree, hf_fix_ResetSeqNumFlag, tvb, offset, field_len, value);
+ break;
+ case 142: /* Field SenderLocationID */
+ proto_tree_add_string(fix_tree, hf_fix_SenderLocationID, tvb, offset, field_len, value);
+ break;
+ case 143: /* Field TargetLocationID */
+ proto_tree_add_string(fix_tree, hf_fix_TargetLocationID, tvb, offset, field_len, value);
+ break;
+ case 144: /* Field OnBehalfOfLocationID */
+ proto_tree_add_string(fix_tree, hf_fix_OnBehalfOfLocationID, tvb, offset, field_len, value);
+ break;
+ case 145: /* Field DeliverToLocationID */
+ proto_tree_add_string(fix_tree, hf_fix_DeliverToLocationID, tvb, offset, field_len, value);
+ break;
+ case 146: /* Field NoRelatedSym */
+ proto_tree_add_string(fix_tree, hf_fix_NoRelatedSym, tvb, offset, field_len, value);
+ break;
+ case 147: /* Field Subject */
+ proto_tree_add_string(fix_tree, hf_fix_Subject, tvb, offset, field_len, value);
+ break;
+ case 148: /* Field Headline */
+ proto_tree_add_string(fix_tree, hf_fix_Headline, tvb, offset, field_len, value);
+ break;
+ case 149: /* Field URLLink */
+ proto_tree_add_string(fix_tree, hf_fix_URLLink, tvb, offset, field_len, value);
+ break;
+ case 150: /* Field ExecType */
+ proto_tree_add_string(fix_tree, hf_fix_ExecType, tvb, offset, field_len, value);
+ break;
+ case 151: /* Field LeavesQty */
+ proto_tree_add_string(fix_tree, hf_fix_LeavesQty, tvb, offset, field_len, value);
+ break;
+ case 152: /* Field CashOrderQty */
+ proto_tree_add_string(fix_tree, hf_fix_CashOrderQty, tvb, offset, field_len, value);
+ break;
+ case 153: /* Field AllocAvgPx */
+ proto_tree_add_string(fix_tree, hf_fix_AllocAvgPx, tvb, offset, field_len, value);
+ break;
+ case 154: /* Field AllocNetMoney */
+ proto_tree_add_string(fix_tree, hf_fix_AllocNetMoney, tvb, offset, field_len, value);
+ break;
+ case 155: /* Field SettlCurrFxRate */
+ proto_tree_add_string(fix_tree, hf_fix_SettlCurrFxRate, tvb, offset, field_len, value);
+ break;
+ case 156: /* Field SettlCurrFxRateCalc */
+ proto_tree_add_string(fix_tree, hf_fix_SettlCurrFxRateCalc, tvb, offset, field_len, value);
+ break;
+ case 157: /* Field NumDaysInterest */
+ proto_tree_add_string(fix_tree, hf_fix_NumDaysInterest, tvb, offset, field_len, value);
+ break;
+ case 158: /* Field AccruedInterestRate */
+ proto_tree_add_string(fix_tree, hf_fix_AccruedInterestRate, tvb, offset, field_len, value);
+ break;
+ case 159: /* Field AccruedInterestAmt */
+ proto_tree_add_string(fix_tree, hf_fix_AccruedInterestAmt, tvb, offset, field_len, value);
+ break;
+ case 160: /* Field SettlInstMode */
+ proto_tree_add_string(fix_tree, hf_fix_SettlInstMode, tvb, offset, field_len, value);
+ break;
+ case 161: /* Field AllocText */
+ proto_tree_add_string(fix_tree, hf_fix_AllocText, tvb, offset, field_len, value);
+ break;
+ case 162: /* Field SettlInstID */
+ proto_tree_add_string(fix_tree, hf_fix_SettlInstID, tvb, offset, field_len, value);
+ break;
+ case 163: /* Field SettlInstTransType */
+ proto_tree_add_string(fix_tree, hf_fix_SettlInstTransType, tvb, offset, field_len, value);
+ break;
+ case 164: /* Field EmailThreadID */
+ proto_tree_add_string(fix_tree, hf_fix_EmailThreadID, tvb, offset, field_len, value);
+ break;
+ case 165: /* Field SettlInstSource */
+ proto_tree_add_string(fix_tree, hf_fix_SettlInstSource, tvb, offset, field_len, value);
+ break;
+ case 166: /* Field SettlLocation */
+ proto_tree_add_string(fix_tree, hf_fix_SettlLocation, tvb, offset, field_len, value);
+ break;
+ case 167: /* Field SecurityType */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityType, tvb, offset, field_len, value);
+ break;
+ case 168: /* Field EffectiveTime */
+ proto_tree_add_string(fix_tree, hf_fix_EffectiveTime, tvb, offset, field_len, value);
+ break;
+ case 169: /* Field StandInstDbType */
+ proto_tree_add_string(fix_tree, hf_fix_StandInstDbType, tvb, offset, field_len, value);
+ break;
+ case 170: /* Field StandInstDbName */
+ proto_tree_add_string(fix_tree, hf_fix_StandInstDbName, tvb, offset, field_len, value);
+ break;
+ case 171: /* Field StandInstDbID */
+ proto_tree_add_string(fix_tree, hf_fix_StandInstDbID, tvb, offset, field_len, value);
+ break;
+ case 172: /* Field SettlDeliveryType */
+ proto_tree_add_string(fix_tree, hf_fix_SettlDeliveryType, tvb, offset, field_len, value);
+ break;
+ case 173: /* Field SettlDepositoryCode */
+ proto_tree_add_string(fix_tree, hf_fix_SettlDepositoryCode, tvb, offset, field_len, value);
+ break;
+ case 174: /* Field SettlBrkrCode */
+ proto_tree_add_string(fix_tree, hf_fix_SettlBrkrCode, tvb, offset, field_len, value);
+ break;
+ case 175: /* Field SettlInstCode */
+ proto_tree_add_string(fix_tree, hf_fix_SettlInstCode, tvb, offset, field_len, value);
+ break;
+ case 176: /* Field SecuritySettlAgentName */
+ proto_tree_add_string(fix_tree, hf_fix_SecuritySettlAgentName, tvb, offset, field_len, value);
+ break;
+ case 177: /* Field SecuritySettlAgentCode */
+ proto_tree_add_string(fix_tree, hf_fix_SecuritySettlAgentCode, tvb, offset, field_len, value);
+ break;
+ case 178: /* Field SecuritySettlAgentAcctNum */
+ proto_tree_add_string(fix_tree, hf_fix_SecuritySettlAgentAcctNum, tvb, offset, field_len, value);
+ break;
+ case 179: /* Field SecuritySettlAgentAcctName */
+ proto_tree_add_string(fix_tree, hf_fix_SecuritySettlAgentAcctName, tvb, offset, field_len, value);
+ break;
+ case 180: /* Field SecuritySettlAgentContactName */
+ proto_tree_add_string(fix_tree, hf_fix_SecuritySettlAgentContactName, tvb, offset, field_len, value);
+ break;
+ case 181: /* Field SecuritySettlAgentContactPhone */
+ proto_tree_add_string(fix_tree, hf_fix_SecuritySettlAgentContactPhone, tvb, offset, field_len, value);
+ break;
+ case 182: /* Field CashSettlAgentName */
+ proto_tree_add_string(fix_tree, hf_fix_CashSettlAgentName, tvb, offset, field_len, value);
+ break;
+ case 183: /* Field CashSettlAgentCode */
+ proto_tree_add_string(fix_tree, hf_fix_CashSettlAgentCode, tvb, offset, field_len, value);
+ break;
+ case 184: /* Field CashSettlAgentAcctNum */
+ proto_tree_add_string(fix_tree, hf_fix_CashSettlAgentAcctNum, tvb, offset, field_len, value);
+ break;
+ case 185: /* Field CashSettlAgentAcctName */
+ proto_tree_add_string(fix_tree, hf_fix_CashSettlAgentAcctName, tvb, offset, field_len, value);
+ break;
+ case 186: /* Field CashSettlAgentContactName */
+ proto_tree_add_string(fix_tree, hf_fix_CashSettlAgentContactName, tvb, offset, field_len, value);
+ break;
+ case 187: /* Field CashSettlAgentContactPhone */
+ proto_tree_add_string(fix_tree, hf_fix_CashSettlAgentContactPhone, tvb, offset, field_len, value);
+ break;
+ case 188: /* Field BidSpotRate */
+ proto_tree_add_string(fix_tree, hf_fix_BidSpotRate, tvb, offset, field_len, value);
+ break;
+ case 189: /* Field BidForwardPoints */
+ proto_tree_add_string(fix_tree, hf_fix_BidForwardPoints, tvb, offset, field_len, value);
+ break;
+ case 190: /* Field OfferSpotRate */
+ proto_tree_add_string(fix_tree, hf_fix_OfferSpotRate, tvb, offset, field_len, value);
+ break;
+ case 191: /* Field OfferForwardPoints */
+ proto_tree_add_string(fix_tree, hf_fix_OfferForwardPoints, tvb, offset, field_len, value);
+ break;
+ case 192: /* Field OrderQty2 */
+ proto_tree_add_string(fix_tree, hf_fix_OrderQty2, tvb, offset, field_len, value);
+ break;
+ case 193: /* Field FutSettDate2 */
+ proto_tree_add_string(fix_tree, hf_fix_FutSettDate2, tvb, offset, field_len, value);
+ break;
+ case 194: /* Field LastSpotRate */
+ proto_tree_add_string(fix_tree, hf_fix_LastSpotRate, tvb, offset, field_len, value);
+ break;
+ case 195: /* Field LastForwardPoints */
+ proto_tree_add_string(fix_tree, hf_fix_LastForwardPoints, tvb, offset, field_len, value);
+ break;
+ case 196: /* Field AllocLinkID */
+ proto_tree_add_string(fix_tree, hf_fix_AllocLinkID, tvb, offset, field_len, value);
+ break;
+ case 197: /* Field AllocLinkType */
+ proto_tree_add_string(fix_tree, hf_fix_AllocLinkType, tvb, offset, field_len, value);
+ break;
+ case 198: /* Field SecondaryOrderID */
+ proto_tree_add_string(fix_tree, hf_fix_SecondaryOrderID, tvb, offset, field_len, value);
+ break;
+ case 199: /* Field NoIOIQualifiers */
+ proto_tree_add_string(fix_tree, hf_fix_NoIOIQualifiers, tvb, offset, field_len, value);
+ break;
+ case 200: /* Field MaturityMonthYear */
+ proto_tree_add_string(fix_tree, hf_fix_MaturityMonthYear, tvb, offset, field_len, value);
+ break;
+ case 201: /* Field PutOrCall */
+ proto_tree_add_string(fix_tree, hf_fix_PutOrCall, tvb, offset, field_len, value);
+ break;
+ case 202: /* Field StrikePrice */
+ proto_tree_add_string(fix_tree, hf_fix_StrikePrice, tvb, offset, field_len, value);
+ break;
+ case 203: /* Field CoveredOrUncovered */
+ proto_tree_add_string(fix_tree, hf_fix_CoveredOrUncovered, tvb, offset, field_len, value);
+ break;
+ case 204: /* Field CustomerOrFirm */
+ proto_tree_add_string(fix_tree, hf_fix_CustomerOrFirm, tvb, offset, field_len, value);
+ break;
+ case 205: /* Field MaturityDay */
+ proto_tree_add_string(fix_tree, hf_fix_MaturityDay, tvb, offset, field_len, value);
+ break;
+ case 206: /* Field OptAttribute */
+ proto_tree_add_string(fix_tree, hf_fix_OptAttribute, tvb, offset, field_len, value);
+ break;
+ case 207: /* Field SecurityExchange */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityExchange, tvb, offset, field_len, value);
+ break;
+ case 208: /* Field NotifyBrokerOfCredit */
+ proto_tree_add_string(fix_tree, hf_fix_NotifyBrokerOfCredit, tvb, offset, field_len, value);
+ break;
+ case 209: /* Field AllocHandlInst */
+ proto_tree_add_string(fix_tree, hf_fix_AllocHandlInst, tvb, offset, field_len, value);
+ break;
+ case 210: /* Field MaxShow */
+ proto_tree_add_string(fix_tree, hf_fix_MaxShow, tvb, offset, field_len, value);
+ break;
+ case 211: /* Field PegDifference */
+ proto_tree_add_string(fix_tree, hf_fix_PegDifference, tvb, offset, field_len, value);
+ break;
+ case 212: /* Field XmlDataLen */
+ proto_tree_add_string(fix_tree, hf_fix_XmlDataLen, tvb, offset, field_len, value);
+ break;
+ case 213: /* Field XmlData */
+ proto_tree_add_string(fix_tree, hf_fix_XmlData, tvb, offset, field_len, value);
+ break;
+ case 214: /* Field SettlInstRefID */
+ proto_tree_add_string(fix_tree, hf_fix_SettlInstRefID, tvb, offset, field_len, value);
+ break;
+ case 215: /* Field NoRoutingIDs */
+ proto_tree_add_string(fix_tree, hf_fix_NoRoutingIDs, tvb, offset, field_len, value);
+ break;
+ case 216: /* Field RoutingType */
+ proto_tree_add_string(fix_tree, hf_fix_RoutingType, tvb, offset, field_len, value);
+ break;
+ case 217: /* Field RoutingID */
+ proto_tree_add_string(fix_tree, hf_fix_RoutingID, tvb, offset, field_len, value);
+ break;
+ case 218: /* Field Spread */
+ proto_tree_add_string(fix_tree, hf_fix_Spread, tvb, offset, field_len, value);
+ break;
+ case 219: /* Field Benchmark */
+ proto_tree_add_string(fix_tree, hf_fix_Benchmark, tvb, offset, field_len, value);
+ break;
+ case 220: /* Field BenchmarkCurveCurrency */
+ proto_tree_add_string(fix_tree, hf_fix_BenchmarkCurveCurrency, tvb, offset, field_len, value);
+ break;
+ case 221: /* Field BenchmarkCurveName */
+ proto_tree_add_string(fix_tree, hf_fix_BenchmarkCurveName, tvb, offset, field_len, value);
+ break;
+ case 222: /* Field BenchmarkCurvePoint */
+ proto_tree_add_string(fix_tree, hf_fix_BenchmarkCurvePoint, tvb, offset, field_len, value);
+ break;
+ case 223: /* Field CouponRate */
+ proto_tree_add_string(fix_tree, hf_fix_CouponRate, tvb, offset, field_len, value);
+ break;
+ case 224: /* Field CouponPaymentDate */
+ proto_tree_add_string(fix_tree, hf_fix_CouponPaymentDate, tvb, offset, field_len, value);
+ break;
+ case 225: /* Field IssueDate */
+ proto_tree_add_string(fix_tree, hf_fix_IssueDate, tvb, offset, field_len, value);
+ break;
+ case 226: /* Field RepurchaseTerm */
+ proto_tree_add_string(fix_tree, hf_fix_RepurchaseTerm, tvb, offset, field_len, value);
+ break;
+ case 227: /* Field RepurchaseRate */
+ proto_tree_add_string(fix_tree, hf_fix_RepurchaseRate, tvb, offset, field_len, value);
+ break;
+ case 228: /* Field Factor */
+ proto_tree_add_string(fix_tree, hf_fix_Factor, tvb, offset, field_len, value);
+ break;
+ case 229: /* Field TradeOriginationDate */
+ proto_tree_add_string(fix_tree, hf_fix_TradeOriginationDate, tvb, offset, field_len, value);
+ break;
+ case 230: /* Field ExDate */
+ proto_tree_add_string(fix_tree, hf_fix_ExDate, tvb, offset, field_len, value);
+ break;
+ case 231: /* Field ContractMultiplier */
+ proto_tree_add_string(fix_tree, hf_fix_ContractMultiplier, tvb, offset, field_len, value);
+ break;
+ case 232: /* Field NoStipulations */
+ proto_tree_add_string(fix_tree, hf_fix_NoStipulations, tvb, offset, field_len, value);
+ break;
+ case 233: /* Field StipulationType */
+ proto_tree_add_string(fix_tree, hf_fix_StipulationType, tvb, offset, field_len, value);
+ break;
+ case 234: /* Field StipulationValue */
+ proto_tree_add_string(fix_tree, hf_fix_StipulationValue, tvb, offset, field_len, value);
+ break;
+ case 235: /* Field YieldType */
+ proto_tree_add_string(fix_tree, hf_fix_YieldType, tvb, offset, field_len, value);
+ break;
+ case 236: /* Field Yield */
+ proto_tree_add_string(fix_tree, hf_fix_Yield, tvb, offset, field_len, value);
+ break;
+ case 237: /* Field TotalTakedown */
+ proto_tree_add_string(fix_tree, hf_fix_TotalTakedown, tvb, offset, field_len, value);
+ break;
+ case 238: /* Field Concession */
+ proto_tree_add_string(fix_tree, hf_fix_Concession, tvb, offset, field_len, value);
+ break;
+ case 239: /* Field RepoCollateralSecurityType */
+ proto_tree_add_string(fix_tree, hf_fix_RepoCollateralSecurityType, tvb, offset, field_len, value);
+ break;
+ case 240: /* Field RedemptionDate */
+ proto_tree_add_string(fix_tree, hf_fix_RedemptionDate, tvb, offset, field_len, value);
+ break;
+ case 241: /* Field UnderlyingCouponPaymentDate */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingCouponPaymentDate, tvb, offset, field_len, value);
+ break;
+ case 242: /* Field UnderlyingIssueDate */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingIssueDate, tvb, offset, field_len, value);
+ break;
+ case 243: /* Field UnderlyingRepoCollateralSecurityType */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingRepoCollateralSecurityType, tvb, offset, field_len, value);
+ break;
+ case 244: /* Field UnderlyingRepurchaseTerm */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingRepurchaseTerm, tvb, offset, field_len, value);
+ break;
+ case 245: /* Field UnderlyingRepurchaseRate */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingRepurchaseRate, tvb, offset, field_len, value);
+ break;
+ case 246: /* Field UnderlyingFactor */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingFactor, tvb, offset, field_len, value);
+ break;
+ case 247: /* Field UnderlyingRedemptionDate */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingRedemptionDate, tvb, offset, field_len, value);
+ break;
+ case 248: /* Field LegCouponPaymentDate */
+ proto_tree_add_string(fix_tree, hf_fix_LegCouponPaymentDate, tvb, offset, field_len, value);
+ break;
+ case 249: /* Field LegIssueDate */
+ proto_tree_add_string(fix_tree, hf_fix_LegIssueDate, tvb, offset, field_len, value);
+ break;
+ case 250: /* Field LegRepoCollateralSecurityType */
+ proto_tree_add_string(fix_tree, hf_fix_LegRepoCollateralSecurityType, tvb, offset, field_len, value);
+ break;
+ case 251: /* Field LegRepurchaseTerm */
+ proto_tree_add_string(fix_tree, hf_fix_LegRepurchaseTerm, tvb, offset, field_len, value);
+ break;
+ case 252: /* Field LegRepurchaseRate */
+ proto_tree_add_string(fix_tree, hf_fix_LegRepurchaseRate, tvb, offset, field_len, value);
+ break;
+ case 253: /* Field LegFactor */
+ proto_tree_add_string(fix_tree, hf_fix_LegFactor, tvb, offset, field_len, value);
+ break;
+ case 254: /* Field LegRedemptionDate */
+ proto_tree_add_string(fix_tree, hf_fix_LegRedemptionDate, tvb, offset, field_len, value);
+ break;
+ case 255: /* Field CreditRating */
+ proto_tree_add_string(fix_tree, hf_fix_CreditRating, tvb, offset, field_len, value);
+ break;
+ case 256: /* Field UnderlyingCreditRating */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingCreditRating, tvb, offset, field_len, value);
+ break;
+ case 257: /* Field LegCreditRating */
+ proto_tree_add_string(fix_tree, hf_fix_LegCreditRating, tvb, offset, field_len, value);
+ break;
+ case 258: /* Field TradedFlatSwitch */
+ proto_tree_add_string(fix_tree, hf_fix_TradedFlatSwitch, tvb, offset, field_len, value);
+ break;
+ case 259: /* Field BasisFeatureDate */
+ proto_tree_add_string(fix_tree, hf_fix_BasisFeatureDate, tvb, offset, field_len, value);
+ break;
+ case 260: /* Field BasisFeaturePrice */
+ proto_tree_add_string(fix_tree, hf_fix_BasisFeaturePrice, tvb, offset, field_len, value);
+ break;
+ case 261: /* Field ReservedAllocated */
+ proto_tree_add_string(fix_tree, hf_fix_ReservedAllocated, tvb, offset, field_len, value);
+ break;
+ case 262: /* Field MDReqID */
+ proto_tree_add_string(fix_tree, hf_fix_MDReqID, tvb, offset, field_len, value);
+ break;
+ case 263: /* Field SubscriptionRequestType */
+ proto_tree_add_string(fix_tree, hf_fix_SubscriptionRequestType, tvb, offset, field_len, value);
+ break;
+ case 264: /* Field MarketDepth */
+ proto_tree_add_string(fix_tree, hf_fix_MarketDepth, tvb, offset, field_len, value);
+ break;
+ case 265: /* Field MDUpdateType */
+ proto_tree_add_string(fix_tree, hf_fix_MDUpdateType, tvb, offset, field_len, value);
+ break;
+ case 266: /* Field AggregatedBook */
+ proto_tree_add_string(fix_tree, hf_fix_AggregatedBook, tvb, offset, field_len, value);
+ break;
+ case 267: /* Field NoMDEntryTypes */
+ proto_tree_add_string(fix_tree, hf_fix_NoMDEntryTypes, tvb, offset, field_len, value);
+ break;
+ case 268: /* Field NoMDEntries */
+ proto_tree_add_string(fix_tree, hf_fix_NoMDEntries, tvb, offset, field_len, value);
+ break;
+ case 269: /* Field MDEntryType */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntryType, tvb, offset, field_len, value);
+ break;
+ case 270: /* Field MDEntryPx */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntryPx, tvb, offset, field_len, value);
+ break;
+ case 271: /* Field MDEntrySize */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntrySize, tvb, offset, field_len, value);
+ break;
+ case 272: /* Field MDEntryDate */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntryDate, tvb, offset, field_len, value);
+ break;
+ case 273: /* Field MDEntryTime */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntryTime, tvb, offset, field_len, value);
+ break;
+ case 274: /* Field TickDirection */
+ proto_tree_add_string(fix_tree, hf_fix_TickDirection, tvb, offset, field_len, value);
+ break;
+ case 275: /* Field MDMkt */
+ proto_tree_add_string(fix_tree, hf_fix_MDMkt, tvb, offset, field_len, value);
+ break;
+ case 276: /* Field QuoteCondition */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteCondition, tvb, offset, field_len, value);
+ break;
+ case 277: /* Field TradeCondition */
+ proto_tree_add_string(fix_tree, hf_fix_TradeCondition, tvb, offset, field_len, value);
+ break;
+ case 278: /* Field MDEntryID */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntryID, tvb, offset, field_len, value);
+ break;
+ case 279: /* Field MDUpdateAction */
+ proto_tree_add_string(fix_tree, hf_fix_MDUpdateAction, tvb, offset, field_len, value);
+ break;
+ case 280: /* Field MDEntryRefID */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntryRefID, tvb, offset, field_len, value);
+ break;
+ case 281: /* Field MDReqRejReason */
+ proto_tree_add_string(fix_tree, hf_fix_MDReqRejReason, tvb, offset, field_len, value);
+ break;
+ case 282: /* Field MDEntryOriginator */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntryOriginator, tvb, offset, field_len, value);
+ break;
+ case 283: /* Field LocationID */
+ proto_tree_add_string(fix_tree, hf_fix_LocationID, tvb, offset, field_len, value);
+ break;
+ case 284: /* Field DeskID */
+ proto_tree_add_string(fix_tree, hf_fix_DeskID, tvb, offset, field_len, value);
+ break;
+ case 285: /* Field DeleteReason */
+ proto_tree_add_string(fix_tree, hf_fix_DeleteReason, tvb, offset, field_len, value);
+ break;
+ case 286: /* Field OpenCloseSettleFlag */
+ proto_tree_add_string(fix_tree, hf_fix_OpenCloseSettleFlag, tvb, offset, field_len, value);
+ break;
+ case 287: /* Field SellerDays */
+ proto_tree_add_string(fix_tree, hf_fix_SellerDays, tvb, offset, field_len, value);
+ break;
+ case 288: /* Field MDEntryBuyer */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntryBuyer, tvb, offset, field_len, value);
+ break;
+ case 289: /* Field MDEntrySeller */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntrySeller, tvb, offset, field_len, value);
+ break;
+ case 290: /* Field MDEntryPositionNo */
+ proto_tree_add_string(fix_tree, hf_fix_MDEntryPositionNo, tvb, offset, field_len, value);
+ break;
+ case 291: /* Field FinancialStatus */
+ proto_tree_add_string(fix_tree, hf_fix_FinancialStatus, tvb, offset, field_len, value);
+ break;
+ case 292: /* Field CorporateAction */
+ proto_tree_add_string(fix_tree, hf_fix_CorporateAction, tvb, offset, field_len, value);
+ break;
+ case 293: /* Field DefBidSize */
+ proto_tree_add_string(fix_tree, hf_fix_DefBidSize, tvb, offset, field_len, value);
+ break;
+ case 294: /* Field DefOfferSize */
+ proto_tree_add_string(fix_tree, hf_fix_DefOfferSize, tvb, offset, field_len, value);
+ break;
+ case 295: /* Field NoQuoteEntries */
+ proto_tree_add_string(fix_tree, hf_fix_NoQuoteEntries, tvb, offset, field_len, value);
+ break;
+ case 296: /* Field NoQuoteSets */
+ proto_tree_add_string(fix_tree, hf_fix_NoQuoteSets, tvb, offset, field_len, value);
+ break;
+ case 297: /* Field QuoteStatus */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteStatus, tvb, offset, field_len, value);
+ break;
+ case 298: /* Field QuoteCancelType */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteCancelType, tvb, offset, field_len, value);
+ break;
+ case 299: /* Field QuoteEntryID */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteEntryID, tvb, offset, field_len, value);
+ break;
+ case 300: /* Field QuoteRejectReason */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteRejectReason, tvb, offset, field_len, value);
+ break;
+ case 301: /* Field QuoteResponseLevel */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteResponseLevel, tvb, offset, field_len, value);
+ break;
+ case 302: /* Field QuoteSetID */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteSetID, tvb, offset, field_len, value);
+ break;
+ case 303: /* Field QuoteRequestType */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteRequestType, tvb, offset, field_len, value);
+ break;
+ case 304: /* Field TotQuoteEntries */
+ proto_tree_add_string(fix_tree, hf_fix_TotQuoteEntries, tvb, offset, field_len, value);
+ break;
+ case 305: /* Field UnderlyingSecurityIDSource */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingSecurityIDSource, tvb, offset, field_len, value);
+ break;
+ case 306: /* Field UnderlyingIssuer */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingIssuer, tvb, offset, field_len, value);
+ break;
+ case 307: /* Field UnderlyingSecurityDesc */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingSecurityDesc, tvb, offset, field_len, value);
+ break;
+ case 308: /* Field UnderlyingSecurityExchange */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingSecurityExchange, tvb, offset, field_len, value);
+ break;
+ case 309: /* Field UnderlyingSecurityID */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingSecurityID, tvb, offset, field_len, value);
+ break;
+ case 310: /* Field UnderlyingSecurityType */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingSecurityType, tvb, offset, field_len, value);
+ break;
+ case 311: /* Field UnderlyingSymbol */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingSymbol, tvb, offset, field_len, value);
+ break;
+ case 312: /* Field UnderlyingSymbolSfx */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingSymbolSfx, tvb, offset, field_len, value);
+ break;
+ case 313: /* Field UnderlyingMaturityMonthYear */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingMaturityMonthYear, tvb, offset, field_len, value);
+ break;
+ case 314: /* Field UnderlyingMaturityDay */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingMaturityDay, tvb, offset, field_len, value);
+ break;
+ case 315: /* Field UnderlyingPutOrCall */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingPutOrCall, tvb, offset, field_len, value);
+ break;
+ case 316: /* Field UnderlyingStrikePrice */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingStrikePrice, tvb, offset, field_len, value);
+ break;
+ case 317: /* Field UnderlyingOptAttribute */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingOptAttribute, tvb, offset, field_len, value);
+ break;
+ case 318: /* Field Underlying */
+ proto_tree_add_string(fix_tree, hf_fix_Underlying, tvb, offset, field_len, value);
+ break;
+ case 319: /* Field RatioQty */
+ proto_tree_add_string(fix_tree, hf_fix_RatioQty, tvb, offset, field_len, value);
+ break;
+ case 320: /* Field SecurityReqID */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityReqID, tvb, offset, field_len, value);
+ break;
+ case 321: /* Field SecurityRequestType */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityRequestType, tvb, offset, field_len, value);
+ break;
+ case 322: /* Field SecurityResponseID */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityResponseID, tvb, offset, field_len, value);
+ break;
+ case 323: /* Field SecurityResponseType */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityResponseType, tvb, offset, field_len, value);
+ break;
+ case 324: /* Field SecurityStatusReqID */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityStatusReqID, tvb, offset, field_len, value);
+ break;
+ case 325: /* Field UnsolicitedIndicator */
+ proto_tree_add_string(fix_tree, hf_fix_UnsolicitedIndicator, tvb, offset, field_len, value);
+ break;
+ case 326: /* Field SecurityTradingStatus */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityTradingStatus, tvb, offset, field_len, value);
+ break;
+ case 327: /* Field HaltReason */
+ proto_tree_add_string(fix_tree, hf_fix_HaltReason, tvb, offset, field_len, value);
+ break;
+ case 328: /* Field InViewOfCommon */
+ proto_tree_add_string(fix_tree, hf_fix_InViewOfCommon, tvb, offset, field_len, value);
+ break;
+ case 329: /* Field DueToRelated */
+ proto_tree_add_string(fix_tree, hf_fix_DueToRelated, tvb, offset, field_len, value);
+ break;
+ case 330: /* Field BuyVolume */
+ proto_tree_add_string(fix_tree, hf_fix_BuyVolume, tvb, offset, field_len, value);
+ break;
+ case 331: /* Field SellVolume */
+ proto_tree_add_string(fix_tree, hf_fix_SellVolume, tvb, offset, field_len, value);
+ break;
+ case 332: /* Field HighPx */
+ proto_tree_add_string(fix_tree, hf_fix_HighPx, tvb, offset, field_len, value);
+ break;
+ case 333: /* Field LowPx */
+ proto_tree_add_string(fix_tree, hf_fix_LowPx, tvb, offset, field_len, value);
+ break;
+ case 334: /* Field Adjustment */
+ proto_tree_add_string(fix_tree, hf_fix_Adjustment, tvb, offset, field_len, value);
+ break;
+ case 335: /* Field TradSesReqID */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesReqID, tvb, offset, field_len, value);
+ break;
+ case 336: /* Field TradingSessionID */
+ proto_tree_add_string(fix_tree, hf_fix_TradingSessionID, tvb, offset, field_len, value);
+ break;
+ case 337: /* Field ContraTrader */
+ proto_tree_add_string(fix_tree, hf_fix_ContraTrader, tvb, offset, field_len, value);
+ break;
+ case 338: /* Field TradSesMethod */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesMethod, tvb, offset, field_len, value);
+ break;
+ case 339: /* Field TradSesMode */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesMode, tvb, offset, field_len, value);
+ break;
+ case 340: /* Field TradSesStatus */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesStatus, tvb, offset, field_len, value);
+ break;
+ case 341: /* Field TradSesStartTime */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesStartTime, tvb, offset, field_len, value);
+ break;
+ case 342: /* Field TradSesOpenTime */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesOpenTime, tvb, offset, field_len, value);
+ break;
+ case 343: /* Field TradSesPreCloseTime */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesPreCloseTime, tvb, offset, field_len, value);
+ break;
+ case 344: /* Field TradSesCloseTime */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesCloseTime, tvb, offset, field_len, value);
+ break;
+ case 345: /* Field TradSesEndTime */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesEndTime, tvb, offset, field_len, value);
+ break;
+ case 346: /* Field NumberOfOrders */
+ proto_tree_add_string(fix_tree, hf_fix_NumberOfOrders, tvb, offset, field_len, value);
+ break;
+ case 347: /* Field MessageEncoding */
+ proto_tree_add_string(fix_tree, hf_fix_MessageEncoding, tvb, offset, field_len, value);
+ break;
+ case 348: /* Field EncodedIssuerLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedIssuerLen, tvb, offset, field_len, value);
+ break;
+ case 349: /* Field EncodedIssuer */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedIssuer, tvb, offset, field_len, value);
+ break;
+ case 350: /* Field EncodedSecurityDescLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedSecurityDescLen, tvb, offset, field_len, value);
+ break;
+ case 351: /* Field EncodedSecurityDesc */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedSecurityDesc, tvb, offset, field_len, value);
+ break;
+ case 352: /* Field EncodedListExecInstLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedListExecInstLen, tvb, offset, field_len, value);
+ break;
+ case 353: /* Field EncodedListExecInst */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedListExecInst, tvb, offset, field_len, value);
+ break;
+ case 354: /* Field EncodedTextLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedTextLen, tvb, offset, field_len, value);
+ break;
+ case 355: /* Field EncodedText */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedText, tvb, offset, field_len, value);
+ break;
+ case 356: /* Field EncodedSubjectLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedSubjectLen, tvb, offset, field_len, value);
+ break;
+ case 357: /* Field EncodedSubject */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedSubject, tvb, offset, field_len, value);
+ break;
+ case 358: /* Field EncodedHeadlineLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedHeadlineLen, tvb, offset, field_len, value);
+ break;
+ case 359: /* Field EncodedHeadline */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedHeadline, tvb, offset, field_len, value);
+ break;
+ case 360: /* Field EncodedAllocTextLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedAllocTextLen, tvb, offset, field_len, value);
+ break;
+ case 361: /* Field EncodedAllocText */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedAllocText, tvb, offset, field_len, value);
+ break;
+ case 362: /* Field EncodedUnderlyingIssuerLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedUnderlyingIssuerLen, tvb, offset, field_len, value);
+ break;
+ case 363: /* Field EncodedUnderlyingIssuer */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedUnderlyingIssuer, tvb, offset, field_len, value);
+ break;
+ case 364: /* Field EncodedUnderlyingSecurityDescLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedUnderlyingSecurityDescLen, tvb, offset, field_len, value);
+ break;
+ case 365: /* Field EncodedUnderlyingSecurityDesc */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedUnderlyingSecurityDesc, tvb, offset, field_len, value);
+ break;
+ case 366: /* Field AllocPrice */
+ proto_tree_add_string(fix_tree, hf_fix_AllocPrice, tvb, offset, field_len, value);
+ break;
+ case 367: /* Field QuoteSetValidUntilTime */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteSetValidUntilTime, tvb, offset, field_len, value);
+ break;
+ case 368: /* Field QuoteEntryRejectReason */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteEntryRejectReason, tvb, offset, field_len, value);
+ break;
+ case 369: /* Field LastMsgSeqNumProcessed */
+ proto_tree_add_string(fix_tree, hf_fix_LastMsgSeqNumProcessed, tvb, offset, field_len, value);
+ break;
+ case 370: /* Field OnBehalfOfSendingTime */
+ proto_tree_add_string(fix_tree, hf_fix_OnBehalfOfSendingTime, tvb, offset, field_len, value);
+ break;
+ case 371: /* Field RefTagID */
+ proto_tree_add_string(fix_tree, hf_fix_RefTagID, tvb, offset, field_len, value);
+ break;
+ case 372: /* Field RefMsgType */
+ proto_tree_add_string(fix_tree, hf_fix_RefMsgType, tvb, offset, field_len, value);
+ break;
+ case 373: /* Field SessionRejectReason */
+ proto_tree_add_string(fix_tree, hf_fix_SessionRejectReason, tvb, offset, field_len, value);
+ break;
+ case 374: /* Field BidRequestTransType */
+ proto_tree_add_string(fix_tree, hf_fix_BidRequestTransType, tvb, offset, field_len, value);
+ break;
+ case 375: /* Field ContraBroker */
+ proto_tree_add_string(fix_tree, hf_fix_ContraBroker, tvb, offset, field_len, value);
+ break;
+ case 376: /* Field ComplianceID */
+ proto_tree_add_string(fix_tree, hf_fix_ComplianceID, tvb, offset, field_len, value);
+ break;
+ case 377: /* Field SolicitedFlag */
+ proto_tree_add_string(fix_tree, hf_fix_SolicitedFlag, tvb, offset, field_len, value);
+ break;
+ case 378: /* Field ExecRestatementReason */
+ proto_tree_add_string(fix_tree, hf_fix_ExecRestatementReason, tvb, offset, field_len, value);
+ break;
+ case 379: /* Field BusinessRejectRefID */
+ proto_tree_add_string(fix_tree, hf_fix_BusinessRejectRefID, tvb, offset, field_len, value);
+ break;
+ case 380: /* Field BusinessRejectReason */
+ proto_tree_add_string(fix_tree, hf_fix_BusinessRejectReason, tvb, offset, field_len, value);
+ break;
+ case 381: /* Field GrossTradeAmt */
+ proto_tree_add_string(fix_tree, hf_fix_GrossTradeAmt, tvb, offset, field_len, value);
+ break;
+ case 382: /* Field NoContraBrokers */
+ proto_tree_add_string(fix_tree, hf_fix_NoContraBrokers, tvb, offset, field_len, value);
+ break;
+ case 383: /* Field MaxMessageSize */
+ proto_tree_add_string(fix_tree, hf_fix_MaxMessageSize, tvb, offset, field_len, value);
+ break;
+ case 384: /* Field NoMsgTypes */
+ proto_tree_add_string(fix_tree, hf_fix_NoMsgTypes, tvb, offset, field_len, value);
+ break;
+ case 385: /* Field MsgDirection */
+ proto_tree_add_string(fix_tree, hf_fix_MsgDirection, tvb, offset, field_len, value);
+ break;
+ case 386: /* Field NoTradingSessions */
+ proto_tree_add_string(fix_tree, hf_fix_NoTradingSessions, tvb, offset, field_len, value);
+ break;
+ case 387: /* Field TotalVolumeTraded */
+ proto_tree_add_string(fix_tree, hf_fix_TotalVolumeTraded, tvb, offset, field_len, value);
+ break;
+ case 388: /* Field DiscretionInst */
+ proto_tree_add_string(fix_tree, hf_fix_DiscretionInst, tvb, offset, field_len, value);
+ break;
+ case 389: /* Field DiscretionOffset */
+ proto_tree_add_string(fix_tree, hf_fix_DiscretionOffset, tvb, offset, field_len, value);
+ break;
+ case 390: /* Field BidID */
+ proto_tree_add_string(fix_tree, hf_fix_BidID, tvb, offset, field_len, value);
+ break;
+ case 391: /* Field ClientBidID */
+ proto_tree_add_string(fix_tree, hf_fix_ClientBidID, tvb, offset, field_len, value);
+ break;
+ case 392: /* Field ListName */
+ proto_tree_add_string(fix_tree, hf_fix_ListName, tvb, offset, field_len, value);
+ break;
+ case 393: /* Field TotalNumSecurities */
+ proto_tree_add_string(fix_tree, hf_fix_TotalNumSecurities, tvb, offset, field_len, value);
+ break;
+ case 394: /* Field BidType */
+ proto_tree_add_string(fix_tree, hf_fix_BidType, tvb, offset, field_len, value);
+ break;
+ case 395: /* Field NumTickets */
+ proto_tree_add_string(fix_tree, hf_fix_NumTickets, tvb, offset, field_len, value);
+ break;
+ case 396: /* Field SideValue1 */
+ proto_tree_add_string(fix_tree, hf_fix_SideValue1, tvb, offset, field_len, value);
+ break;
+ case 397: /* Field SideValue2 */
+ proto_tree_add_string(fix_tree, hf_fix_SideValue2, tvb, offset, field_len, value);
+ break;
+ case 398: /* Field NoBidDescriptors */
+ proto_tree_add_string(fix_tree, hf_fix_NoBidDescriptors, tvb, offset, field_len, value);
+ break;
+ case 399: /* Field BidDescriptorType */
+ proto_tree_add_string(fix_tree, hf_fix_BidDescriptorType, tvb, offset, field_len, value);
+ break;
+ case 400: /* Field BidDescriptor */
+ proto_tree_add_string(fix_tree, hf_fix_BidDescriptor, tvb, offset, field_len, value);
+ break;
+ case 401: /* Field SideValueInd */
+ proto_tree_add_string(fix_tree, hf_fix_SideValueInd, tvb, offset, field_len, value);
+ break;
+ case 402: /* Field LiquidityPctLow */
+ proto_tree_add_string(fix_tree, hf_fix_LiquidityPctLow, tvb, offset, field_len, value);
+ break;
+ case 403: /* Field LiquidityPctHigh */
+ proto_tree_add_string(fix_tree, hf_fix_LiquidityPctHigh, tvb, offset, field_len, value);
+ break;
+ case 404: /* Field LiquidityValue */
+ proto_tree_add_string(fix_tree, hf_fix_LiquidityValue, tvb, offset, field_len, value);
+ break;
+ case 405: /* Field EFPTrackingError */
+ proto_tree_add_string(fix_tree, hf_fix_EFPTrackingError, tvb, offset, field_len, value);
+ break;
+ case 406: /* Field FairValue */
+ proto_tree_add_string(fix_tree, hf_fix_FairValue, tvb, offset, field_len, value);
+ break;
+ case 407: /* Field OutsideIndexPct */
+ proto_tree_add_string(fix_tree, hf_fix_OutsideIndexPct, tvb, offset, field_len, value);
+ break;
+ case 408: /* Field ValueOfFutures */
+ proto_tree_add_string(fix_tree, hf_fix_ValueOfFutures, tvb, offset, field_len, value);
+ break;
+ case 409: /* Field LiquidityIndType */
+ proto_tree_add_string(fix_tree, hf_fix_LiquidityIndType, tvb, offset, field_len, value);
+ break;
+ case 410: /* Field WtAverageLiquidity */
+ proto_tree_add_string(fix_tree, hf_fix_WtAverageLiquidity, tvb, offset, field_len, value);
+ break;
+ case 411: /* Field ExchangeForPhysical */
+ proto_tree_add_string(fix_tree, hf_fix_ExchangeForPhysical, tvb, offset, field_len, value);
+ break;
+ case 412: /* Field OutMainCntryUIndex */
+ proto_tree_add_string(fix_tree, hf_fix_OutMainCntryUIndex, tvb, offset, field_len, value);
+ break;
+ case 413: /* Field CrossPercent */
+ proto_tree_add_string(fix_tree, hf_fix_CrossPercent, tvb, offset, field_len, value);
+ break;
+ case 414: /* Field ProgRptReqs */
+ proto_tree_add_string(fix_tree, hf_fix_ProgRptReqs, tvb, offset, field_len, value);
+ break;
+ case 415: /* Field ProgPeriodInterval */
+ proto_tree_add_string(fix_tree, hf_fix_ProgPeriodInterval, tvb, offset, field_len, value);
+ break;
+ case 416: /* Field IncTaxInd */
+ proto_tree_add_string(fix_tree, hf_fix_IncTaxInd, tvb, offset, field_len, value);
+ break;
+ case 417: /* Field NumBidders */
+ proto_tree_add_string(fix_tree, hf_fix_NumBidders, tvb, offset, field_len, value);
+ break;
+ case 418: /* Field TradeType */
+ proto_tree_add_string(fix_tree, hf_fix_TradeType, tvb, offset, field_len, value);
+ break;
+ case 419: /* Field BasisPxType */
+ proto_tree_add_string(fix_tree, hf_fix_BasisPxType, tvb, offset, field_len, value);
+ break;
+ case 420: /* Field NoBidComponents */
+ proto_tree_add_string(fix_tree, hf_fix_NoBidComponents, tvb, offset, field_len, value);
+ break;
+ case 421: /* Field Country */
+ proto_tree_add_string(fix_tree, hf_fix_Country, tvb, offset, field_len, value);
+ break;
+ case 422: /* Field TotNoStrikes */
+ proto_tree_add_string(fix_tree, hf_fix_TotNoStrikes, tvb, offset, field_len, value);
+ break;
+ case 423: /* Field PriceType */
+ proto_tree_add_string(fix_tree, hf_fix_PriceType, tvb, offset, field_len, value);
+ break;
+ case 424: /* Field DayOrderQty */
+ proto_tree_add_string(fix_tree, hf_fix_DayOrderQty, tvb, offset, field_len, value);
+ break;
+ case 425: /* Field DayCumQty */
+ proto_tree_add_string(fix_tree, hf_fix_DayCumQty, tvb, offset, field_len, value);
+ break;
+ case 426: /* Field DayAvgPx */
+ proto_tree_add_string(fix_tree, hf_fix_DayAvgPx, tvb, offset, field_len, value);
+ break;
+ case 427: /* Field GTBookingInst */
+ proto_tree_add_string(fix_tree, hf_fix_GTBookingInst, tvb, offset, field_len, value);
+ break;
+ case 428: /* Field NoStrikes */
+ proto_tree_add_string(fix_tree, hf_fix_NoStrikes, tvb, offset, field_len, value);
+ break;
+ case 429: /* Field ListStatusType */
+ proto_tree_add_string(fix_tree, hf_fix_ListStatusType, tvb, offset, field_len, value);
+ break;
+ case 430: /* Field NetGrossInd */
+ proto_tree_add_string(fix_tree, hf_fix_NetGrossInd, tvb, offset, field_len, value);
+ break;
+ case 431: /* Field ListOrderStatus */
+ proto_tree_add_string(fix_tree, hf_fix_ListOrderStatus, tvb, offset, field_len, value);
+ break;
+ case 432: /* Field ExpireDate */
+ proto_tree_add_string(fix_tree, hf_fix_ExpireDate, tvb, offset, field_len, value);
+ break;
+ case 433: /* Field ListExecInstType */
+ proto_tree_add_string(fix_tree, hf_fix_ListExecInstType, tvb, offset, field_len, value);
+ break;
+ case 434: /* Field CxlRejResponseTo */
+ proto_tree_add_string(fix_tree, hf_fix_CxlRejResponseTo, tvb, offset, field_len, value);
+ break;
+ case 435: /* Field UnderlyingCouponRate */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingCouponRate, tvb, offset, field_len, value);
+ break;
+ case 436: /* Field UnderlyingContractMultiplier */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingContractMultiplier, tvb, offset, field_len, value);
+ break;
+ case 437: /* Field ContraTradeQty */
+ proto_tree_add_string(fix_tree, hf_fix_ContraTradeQty, tvb, offset, field_len, value);
+ break;
+ case 438: /* Field ContraTradeTime */
+ proto_tree_add_string(fix_tree, hf_fix_ContraTradeTime, tvb, offset, field_len, value);
+ break;
+ case 439: /* Field ClearingFirm */
+ proto_tree_add_string(fix_tree, hf_fix_ClearingFirm, tvb, offset, field_len, value);
+ break;
+ case 440: /* Field ClearingAccount */
+ proto_tree_add_string(fix_tree, hf_fix_ClearingAccount, tvb, offset, field_len, value);
+ break;
+ case 441: /* Field LiquidityNumSecurities */
+ proto_tree_add_string(fix_tree, hf_fix_LiquidityNumSecurities, tvb, offset, field_len, value);
+ break;
+ case 442: /* Field MultiLegReportingType */
+ proto_tree_add_string(fix_tree, hf_fix_MultiLegReportingType, tvb, offset, field_len, value);
+ break;
+ case 443: /* Field StrikeTime */
+ proto_tree_add_string(fix_tree, hf_fix_StrikeTime, tvb, offset, field_len, value);
+ break;
+ case 444: /* Field ListStatusText */
+ proto_tree_add_string(fix_tree, hf_fix_ListStatusText, tvb, offset, field_len, value);
+ break;
+ case 445: /* Field EncodedListStatusTextLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedListStatusTextLen, tvb, offset, field_len, value);
+ break;
+ case 446: /* Field EncodedListStatusText */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedListStatusText, tvb, offset, field_len, value);
+ break;
+ case 447: /* Field PartyIDSource */
+ proto_tree_add_string(fix_tree, hf_fix_PartyIDSource, tvb, offset, field_len, value);
+ break;
+ case 448: /* Field PartyID */
+ proto_tree_add_string(fix_tree, hf_fix_PartyID, tvb, offset, field_len, value);
+ break;
+ case 449: /* Field TotalVolumeTradedDate */
+ proto_tree_add_string(fix_tree, hf_fix_TotalVolumeTradedDate, tvb, offset, field_len, value);
+ break;
+ case 450: /* Field TotalVolumeTradedTime */
+ proto_tree_add_string(fix_tree, hf_fix_TotalVolumeTradedTime, tvb, offset, field_len, value);
+ break;
+ case 451: /* Field NetChgPrevDay */
+ proto_tree_add_string(fix_tree, hf_fix_NetChgPrevDay, tvb, offset, field_len, value);
+ break;
+ case 452: /* Field PartyRole */
+ proto_tree_add_string(fix_tree, hf_fix_PartyRole, tvb, offset, field_len, value);
+ break;
+ case 453: /* Field NoPartyIDs */
+ proto_tree_add_string(fix_tree, hf_fix_NoPartyIDs, tvb, offset, field_len, value);
+ break;
+ case 454: /* Field NoSecurityAltID */
+ proto_tree_add_string(fix_tree, hf_fix_NoSecurityAltID, tvb, offset, field_len, value);
+ break;
+ case 455: /* Field SecurityAltID */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityAltID, tvb, offset, field_len, value);
+ break;
+ case 456: /* Field SecurityAltIDSource */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityAltIDSource, tvb, offset, field_len, value);
+ break;
+ case 457: /* Field NoUnderlyingSecurityAltID */
+ proto_tree_add_string(fix_tree, hf_fix_NoUnderlyingSecurityAltID, tvb, offset, field_len, value);
+ break;
+ case 458: /* Field UnderlyingSecurityAltID */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingSecurityAltID, tvb, offset, field_len, value);
+ break;
+ case 459: /* Field UnderlyingSecurityAltIDSource */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingSecurityAltIDSource, tvb, offset, field_len, value);
+ break;
+ case 460: /* Field Product */
+ proto_tree_add_string(fix_tree, hf_fix_Product, tvb, offset, field_len, value);
+ break;
+ case 461: /* Field CFICode */
+ proto_tree_add_string(fix_tree, hf_fix_CFICode, tvb, offset, field_len, value);
+ break;
+ case 462: /* Field UnderlyingProduct */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingProduct, tvb, offset, field_len, value);
+ break;
+ case 463: /* Field UnderlyingCFICode */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingCFICode, tvb, offset, field_len, value);
+ break;
+ case 464: /* Field TestMessageIndicator */
+ proto_tree_add_string(fix_tree, hf_fix_TestMessageIndicator, tvb, offset, field_len, value);
+ break;
+ case 465: /* Field QuantityType */
+ proto_tree_add_string(fix_tree, hf_fix_QuantityType, tvb, offset, field_len, value);
+ break;
+ case 466: /* Field BookingRefID */
+ proto_tree_add_string(fix_tree, hf_fix_BookingRefID, tvb, offset, field_len, value);
+ break;
+ case 467: /* Field IndividualAllocID */
+ proto_tree_add_string(fix_tree, hf_fix_IndividualAllocID, tvb, offset, field_len, value);
+ break;
+ case 468: /* Field RoundingDirection */
+ proto_tree_add_string(fix_tree, hf_fix_RoundingDirection, tvb, offset, field_len, value);
+ break;
+ case 469: /* Field RoundingModulus */
+ proto_tree_add_string(fix_tree, hf_fix_RoundingModulus, tvb, offset, field_len, value);
+ break;
+ case 470: /* Field CountryOfIssue */
+ proto_tree_add_string(fix_tree, hf_fix_CountryOfIssue, tvb, offset, field_len, value);
+ break;
+ case 471: /* Field StateOrProvinceOfIssue */
+ proto_tree_add_string(fix_tree, hf_fix_StateOrProvinceOfIssue, tvb, offset, field_len, value);
+ break;
+ case 472: /* Field LocaleOfIssue */
+ proto_tree_add_string(fix_tree, hf_fix_LocaleOfIssue, tvb, offset, field_len, value);
+ break;
+ case 473: /* Field NoRegistDtls */
+ proto_tree_add_string(fix_tree, hf_fix_NoRegistDtls, tvb, offset, field_len, value);
+ break;
+ case 474: /* Field MailingDtls */
+ proto_tree_add_string(fix_tree, hf_fix_MailingDtls, tvb, offset, field_len, value);
+ break;
+ case 475: /* Field InvestorCountryOfResidence */
+ proto_tree_add_string(fix_tree, hf_fix_InvestorCountryOfResidence, tvb, offset, field_len, value);
+ break;
+ case 476: /* Field PaymentRef */
+ proto_tree_add_string(fix_tree, hf_fix_PaymentRef, tvb, offset, field_len, value);
+ break;
+ case 477: /* Field DistribPaymentMethod */
+ proto_tree_add_string(fix_tree, hf_fix_DistribPaymentMethod, tvb, offset, field_len, value);
+ break;
+ case 478: /* Field CashDistribCurr */
+ proto_tree_add_string(fix_tree, hf_fix_CashDistribCurr, tvb, offset, field_len, value);
+ break;
+ case 479: /* Field CommCurrency */
+ proto_tree_add_string(fix_tree, hf_fix_CommCurrency, tvb, offset, field_len, value);
+ break;
+ case 480: /* Field CancellationRights */
+ proto_tree_add_string(fix_tree, hf_fix_CancellationRights, tvb, offset, field_len, value);
+ break;
+ case 481: /* Field MoneyLaunderingStatus */
+ proto_tree_add_string(fix_tree, hf_fix_MoneyLaunderingStatus, tvb, offset, field_len, value);
+ break;
+ case 482: /* Field MailingInst */
+ proto_tree_add_string(fix_tree, hf_fix_MailingInst, tvb, offset, field_len, value);
+ break;
+ case 483: /* Field TransBkdTime */
+ proto_tree_add_string(fix_tree, hf_fix_TransBkdTime, tvb, offset, field_len, value);
+ break;
+ case 484: /* Field ExecPriceType */
+ proto_tree_add_string(fix_tree, hf_fix_ExecPriceType, tvb, offset, field_len, value);
+ break;
+ case 485: /* Field ExecPriceAdjustment */
+ proto_tree_add_string(fix_tree, hf_fix_ExecPriceAdjustment, tvb, offset, field_len, value);
+ break;
+ case 486: /* Field DateOfBirth */
+ proto_tree_add_string(fix_tree, hf_fix_DateOfBirth, tvb, offset, field_len, value);
+ break;
+ case 487: /* Field TradeReportTransType */
+ proto_tree_add_string(fix_tree, hf_fix_TradeReportTransType, tvb, offset, field_len, value);
+ break;
+ case 488: /* Field CardHolderName */
+ proto_tree_add_string(fix_tree, hf_fix_CardHolderName, tvb, offset, field_len, value);
+ break;
+ case 489: /* Field CardNumber */
+ proto_tree_add_string(fix_tree, hf_fix_CardNumber, tvb, offset, field_len, value);
+ break;
+ case 490: /* Field CardExpDate */
+ proto_tree_add_string(fix_tree, hf_fix_CardExpDate, tvb, offset, field_len, value);
+ break;
+ case 491: /* Field CardIssNo */
+ proto_tree_add_string(fix_tree, hf_fix_CardIssNo, tvb, offset, field_len, value);
+ break;
+ case 492: /* Field PaymentMethod */
+ proto_tree_add_string(fix_tree, hf_fix_PaymentMethod, tvb, offset, field_len, value);
+ break;
+ case 493: /* Field RegistAcctType */
+ proto_tree_add_string(fix_tree, hf_fix_RegistAcctType, tvb, offset, field_len, value);
+ break;
+ case 494: /* Field Designation */
+ proto_tree_add_string(fix_tree, hf_fix_Designation, tvb, offset, field_len, value);
+ break;
+ case 495: /* Field TaxAdvantageType */
+ proto_tree_add_string(fix_tree, hf_fix_TaxAdvantageType, tvb, offset, field_len, value);
+ break;
+ case 496: /* Field RegistRejReasonText */
+ proto_tree_add_string(fix_tree, hf_fix_RegistRejReasonText, tvb, offset, field_len, value);
+ break;
+ case 497: /* Field FundRenewWaiv */
+ proto_tree_add_string(fix_tree, hf_fix_FundRenewWaiv, tvb, offset, field_len, value);
+ break;
+ case 498: /* Field CashDistribAgentName */
+ proto_tree_add_string(fix_tree, hf_fix_CashDistribAgentName, tvb, offset, field_len, value);
+ break;
+ case 499: /* Field CashDistribAgentCode */
+ proto_tree_add_string(fix_tree, hf_fix_CashDistribAgentCode, tvb, offset, field_len, value);
+ break;
+ case 500: /* Field CashDistribAgentAcctNumber */
+ proto_tree_add_string(fix_tree, hf_fix_CashDistribAgentAcctNumber, tvb, offset, field_len, value);
+ break;
+ case 501: /* Field CashDistribPayRef */
+ proto_tree_add_string(fix_tree, hf_fix_CashDistribPayRef, tvb, offset, field_len, value);
+ break;
+ case 502: /* Field CashDistribAgentAcctName */
+ proto_tree_add_string(fix_tree, hf_fix_CashDistribAgentAcctName, tvb, offset, field_len, value);
+ break;
+ case 503: /* Field CardStartDate */
+ proto_tree_add_string(fix_tree, hf_fix_CardStartDate, tvb, offset, field_len, value);
+ break;
+ case 504: /* Field PaymentDate */
+ proto_tree_add_string(fix_tree, hf_fix_PaymentDate, tvb, offset, field_len, value);
+ break;
+ case 505: /* Field PaymentRemitterID */
+ proto_tree_add_string(fix_tree, hf_fix_PaymentRemitterID, tvb, offset, field_len, value);
+ break;
+ case 506: /* Field RegistStatus */
+ proto_tree_add_string(fix_tree, hf_fix_RegistStatus, tvb, offset, field_len, value);
+ break;
+ case 507: /* Field RegistRejReasonCode */
+ proto_tree_add_string(fix_tree, hf_fix_RegistRejReasonCode, tvb, offset, field_len, value);
+ break;
+ case 508: /* Field RegistRefID */
+ proto_tree_add_string(fix_tree, hf_fix_RegistRefID, tvb, offset, field_len, value);
+ break;
+ case 509: /* Field RegistDetls */
+ proto_tree_add_string(fix_tree, hf_fix_RegistDetls, tvb, offset, field_len, value);
+ break;
+ case 510: /* Field NoDistribInsts */
+ proto_tree_add_string(fix_tree, hf_fix_NoDistribInsts, tvb, offset, field_len, value);
+ break;
+ case 511: /* Field RegistEmail */
+ proto_tree_add_string(fix_tree, hf_fix_RegistEmail, tvb, offset, field_len, value);
+ break;
+ case 512: /* Field DistribPercentage */
+ proto_tree_add_string(fix_tree, hf_fix_DistribPercentage, tvb, offset, field_len, value);
+ break;
+ case 513: /* Field RegistID */
+ proto_tree_add_string(fix_tree, hf_fix_RegistID, tvb, offset, field_len, value);
+ break;
+ case 514: /* Field RegistTransType */
+ proto_tree_add_string(fix_tree, hf_fix_RegistTransType, tvb, offset, field_len, value);
+ break;
+ case 515: /* Field ExecValuationPoint */
+ proto_tree_add_string(fix_tree, hf_fix_ExecValuationPoint, tvb, offset, field_len, value);
+ break;
+ case 516: /* Field OrderPercent */
+ proto_tree_add_string(fix_tree, hf_fix_OrderPercent, tvb, offset, field_len, value);
+ break;
+ case 517: /* Field OwnershipType */
+ proto_tree_add_string(fix_tree, hf_fix_OwnershipType, tvb, offset, field_len, value);
+ break;
+ case 518: /* Field NoContAmts */
+ proto_tree_add_string(fix_tree, hf_fix_NoContAmts, tvb, offset, field_len, value);
+ break;
+ case 519: /* Field ContAmtType */
+ proto_tree_add_string(fix_tree, hf_fix_ContAmtType, tvb, offset, field_len, value);
+ break;
+ case 520: /* Field ContAmtValue */
+ proto_tree_add_string(fix_tree, hf_fix_ContAmtValue, tvb, offset, field_len, value);
+ break;
+ case 521: /* Field ContAmtCurr */
+ proto_tree_add_string(fix_tree, hf_fix_ContAmtCurr, tvb, offset, field_len, value);
+ break;
+ case 522: /* Field OwnerType */
+ proto_tree_add_string(fix_tree, hf_fix_OwnerType, tvb, offset, field_len, value);
+ break;
+ case 523: /* Field PartySubID */
+ proto_tree_add_string(fix_tree, hf_fix_PartySubID, tvb, offset, field_len, value);
+ break;
+ case 524: /* Field NestedPartyID */
+ proto_tree_add_string(fix_tree, hf_fix_NestedPartyID, tvb, offset, field_len, value);
+ break;
+ case 525: /* Field NestedPartyIDSource */
+ proto_tree_add_string(fix_tree, hf_fix_NestedPartyIDSource, tvb, offset, field_len, value);
+ break;
+ case 526: /* Field SecondaryClOrdID */
+ proto_tree_add_string(fix_tree, hf_fix_SecondaryClOrdID, tvb, offset, field_len, value);
+ break;
+ case 527: /* Field SecondaryExecID */
+ proto_tree_add_string(fix_tree, hf_fix_SecondaryExecID, tvb, offset, field_len, value);
+ break;
+ case 528: /* Field OrderCapacity */
+ proto_tree_add_string(fix_tree, hf_fix_OrderCapacity, tvb, offset, field_len, value);
+ break;
+ case 529: /* Field OrderRestrictions */
+ proto_tree_add_string(fix_tree, hf_fix_OrderRestrictions, tvb, offset, field_len, value);
+ break;
+ case 530: /* Field MassCancelRequestType */
+ proto_tree_add_string(fix_tree, hf_fix_MassCancelRequestType, tvb, offset, field_len, value);
+ break;
+ case 531: /* Field MassCancelResponse */
+ proto_tree_add_string(fix_tree, hf_fix_MassCancelResponse, tvb, offset, field_len, value);
+ break;
+ case 532: /* Field MassCancelRejectReason */
+ proto_tree_add_string(fix_tree, hf_fix_MassCancelRejectReason, tvb, offset, field_len, value);
+ break;
+ case 533: /* Field TotalAffectedOrders */
+ proto_tree_add_string(fix_tree, hf_fix_TotalAffectedOrders, tvb, offset, field_len, value);
+ break;
+ case 534: /* Field NoAffectedOrders */
+ proto_tree_add_string(fix_tree, hf_fix_NoAffectedOrders, tvb, offset, field_len, value);
+ break;
+ case 535: /* Field AffectedOrderID */
+ proto_tree_add_string(fix_tree, hf_fix_AffectedOrderID, tvb, offset, field_len, value);
+ break;
+ case 536: /* Field AffectedSecondaryOrderID */
+ proto_tree_add_string(fix_tree, hf_fix_AffectedSecondaryOrderID, tvb, offset, field_len, value);
+ break;
+ case 537: /* Field QuoteType */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteType, tvb, offset, field_len, value);
+ break;
+ case 538: /* Field NestedPartyRole */
+ proto_tree_add_string(fix_tree, hf_fix_NestedPartyRole, tvb, offset, field_len, value);
+ break;
+ case 539: /* Field NoNestedPartyIDs */
+ proto_tree_add_string(fix_tree, hf_fix_NoNestedPartyIDs, tvb, offset, field_len, value);
+ break;
+ case 540: /* Field TotalAccruedInterestAmt */
+ proto_tree_add_string(fix_tree, hf_fix_TotalAccruedInterestAmt, tvb, offset, field_len, value);
+ break;
+ case 541: /* Field MaturityDate */
+ proto_tree_add_string(fix_tree, hf_fix_MaturityDate, tvb, offset, field_len, value);
+ break;
+ case 542: /* Field UnderlyingMaturityDate */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingMaturityDate, tvb, offset, field_len, value);
+ break;
+ case 543: /* Field InstrRegistry */
+ proto_tree_add_string(fix_tree, hf_fix_InstrRegistry, tvb, offset, field_len, value);
+ break;
+ case 544: /* Field CashMargin */
+ proto_tree_add_string(fix_tree, hf_fix_CashMargin, tvb, offset, field_len, value);
+ break;
+ case 545: /* Field NestedPartySubID */
+ proto_tree_add_string(fix_tree, hf_fix_NestedPartySubID, tvb, offset, field_len, value);
+ break;
+ case 546: /* Field Scope */
+ proto_tree_add_string(fix_tree, hf_fix_Scope, tvb, offset, field_len, value);
+ break;
+ case 547: /* Field MDImplicitDelete */
+ proto_tree_add_string(fix_tree, hf_fix_MDImplicitDelete, tvb, offset, field_len, value);
+ break;
+ case 548: /* Field CrossID */
+ proto_tree_add_string(fix_tree, hf_fix_CrossID, tvb, offset, field_len, value);
+ break;
+ case 549: /* Field CrossType */
+ proto_tree_add_string(fix_tree, hf_fix_CrossType, tvb, offset, field_len, value);
+ break;
+ case 550: /* Field CrossPrioritization */
+ proto_tree_add_string(fix_tree, hf_fix_CrossPrioritization, tvb, offset, field_len, value);
+ break;
+ case 551: /* Field OrigCrossID */
+ proto_tree_add_string(fix_tree, hf_fix_OrigCrossID, tvb, offset, field_len, value);
+ break;
+ case 552: /* Field NoSides */
+ proto_tree_add_string(fix_tree, hf_fix_NoSides, tvb, offset, field_len, value);
+ break;
+ case 553: /* Field Username */
+ proto_tree_add_string(fix_tree, hf_fix_Username, tvb, offset, field_len, value);
+ break;
+ case 554: /* Field Password */
+ proto_tree_add_string(fix_tree, hf_fix_Password, tvb, offset, field_len, value);
+ break;
+ case 555: /* Field NoLegs */
+ proto_tree_add_string(fix_tree, hf_fix_NoLegs, tvb, offset, field_len, value);
+ break;
+ case 556: /* Field LegCurrency */
+ proto_tree_add_string(fix_tree, hf_fix_LegCurrency, tvb, offset, field_len, value);
+ break;
+ case 557: /* Field TotalNumSecurityTypes */
+ proto_tree_add_string(fix_tree, hf_fix_TotalNumSecurityTypes, tvb, offset, field_len, value);
+ break;
+ case 558: /* Field NoSecurityTypes */
+ proto_tree_add_string(fix_tree, hf_fix_NoSecurityTypes, tvb, offset, field_len, value);
+ break;
+ case 559: /* Field SecurityListRequestType */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityListRequestType, tvb, offset, field_len, value);
+ break;
+ case 560: /* Field SecurityRequestResult */
+ proto_tree_add_string(fix_tree, hf_fix_SecurityRequestResult, tvb, offset, field_len, value);
+ break;
+ case 561: /* Field RoundLot */
+ proto_tree_add_string(fix_tree, hf_fix_RoundLot, tvb, offset, field_len, value);
+ break;
+ case 562: /* Field MinTradeVol */
+ proto_tree_add_string(fix_tree, hf_fix_MinTradeVol, tvb, offset, field_len, value);
+ break;
+ case 563: /* Field MultiLegRptTypeReq */
+ proto_tree_add_string(fix_tree, hf_fix_MultiLegRptTypeReq, tvb, offset, field_len, value);
+ break;
+ case 564: /* Field LegPositionEffect */
+ proto_tree_add_string(fix_tree, hf_fix_LegPositionEffect, tvb, offset, field_len, value);
+ break;
+ case 565: /* Field LegCoveredOrUncovered */
+ proto_tree_add_string(fix_tree, hf_fix_LegCoveredOrUncovered, tvb, offset, field_len, value);
+ break;
+ case 566: /* Field LegPrice */
+ proto_tree_add_string(fix_tree, hf_fix_LegPrice, tvb, offset, field_len, value);
+ break;
+ case 567: /* Field TradSesStatusRejReason */
+ proto_tree_add_string(fix_tree, hf_fix_TradSesStatusRejReason, tvb, offset, field_len, value);
+ break;
+ case 568: /* Field TradeRequestID */
+ proto_tree_add_string(fix_tree, hf_fix_TradeRequestID, tvb, offset, field_len, value);
+ break;
+ case 569: /* Field TradeRequestType */
+ proto_tree_add_string(fix_tree, hf_fix_TradeRequestType, tvb, offset, field_len, value);
+ break;
+ case 570: /* Field PreviouslyReported */
+ proto_tree_add_string(fix_tree, hf_fix_PreviouslyReported, tvb, offset, field_len, value);
+ break;
+ case 571: /* Field TradeReportID */
+ proto_tree_add_string(fix_tree, hf_fix_TradeReportID, tvb, offset, field_len, value);
+ break;
+ case 572: /* Field TradeReportRefID */
+ proto_tree_add_string(fix_tree, hf_fix_TradeReportRefID, tvb, offset, field_len, value);
+ break;
+ case 573: /* Field MatchStatus */
+ proto_tree_add_string(fix_tree, hf_fix_MatchStatus, tvb, offset, field_len, value);
+ break;
+ case 574: /* Field MatchType */
+ proto_tree_add_string(fix_tree, hf_fix_MatchType, tvb, offset, field_len, value);
+ break;
+ case 575: /* Field OddLot */
+ proto_tree_add_string(fix_tree, hf_fix_OddLot, tvb, offset, field_len, value);
+ break;
+ case 576: /* Field NoClearingInstructions */
+ proto_tree_add_string(fix_tree, hf_fix_NoClearingInstructions, tvb, offset, field_len, value);
+ break;
+ case 577: /* Field ClearingInstruction */
+ proto_tree_add_string(fix_tree, hf_fix_ClearingInstruction, tvb, offset, field_len, value);
+ break;
+ case 578: /* Field TradeInputSource */
+ proto_tree_add_string(fix_tree, hf_fix_TradeInputSource, tvb, offset, field_len, value);
+ break;
+ case 579: /* Field TradeInputDevice */
+ proto_tree_add_string(fix_tree, hf_fix_TradeInputDevice, tvb, offset, field_len, value);
+ break;
+ case 580: /* Field NoDates */
+ proto_tree_add_string(fix_tree, hf_fix_NoDates, tvb, offset, field_len, value);
+ break;
+ case 581: /* Field AccountType */
+ proto_tree_add_string(fix_tree, hf_fix_AccountType, tvb, offset, field_len, value);
+ break;
+ case 582: /* Field CustOrderCapacity */
+ proto_tree_add_string(fix_tree, hf_fix_CustOrderCapacity, tvb, offset, field_len, value);
+ break;
+ case 583: /* Field ClOrdLinkID */
+ proto_tree_add_string(fix_tree, hf_fix_ClOrdLinkID, tvb, offset, field_len, value);
+ break;
+ case 584: /* Field MassStatusReqID */
+ proto_tree_add_string(fix_tree, hf_fix_MassStatusReqID, tvb, offset, field_len, value);
+ break;
+ case 585: /* Field MassStatusReqType */
+ proto_tree_add_string(fix_tree, hf_fix_MassStatusReqType, tvb, offset, field_len, value);
+ break;
+ case 586: /* Field OrigOrdModTime */
+ proto_tree_add_string(fix_tree, hf_fix_OrigOrdModTime, tvb, offset, field_len, value);
+ break;
+ case 587: /* Field LegSettlmntTyp */
+ proto_tree_add_string(fix_tree, hf_fix_LegSettlmntTyp, tvb, offset, field_len, value);
+ break;
+ case 588: /* Field LegFutSettDate */
+ proto_tree_add_string(fix_tree, hf_fix_LegFutSettDate, tvb, offset, field_len, value);
+ break;
+ case 589: /* Field DayBookingInst */
+ proto_tree_add_string(fix_tree, hf_fix_DayBookingInst, tvb, offset, field_len, value);
+ break;
+ case 590: /* Field BookingUnit */
+ proto_tree_add_string(fix_tree, hf_fix_BookingUnit, tvb, offset, field_len, value);
+ break;
+ case 591: /* Field PreallocMethod */
+ proto_tree_add_string(fix_tree, hf_fix_PreallocMethod, tvb, offset, field_len, value);
+ break;
+ case 592: /* Field UnderlyingCountryOfIssue */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingCountryOfIssue, tvb, offset, field_len, value);
+ break;
+ case 593: /* Field UnderlyingStateOrProvinceOfIssue */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingStateOrProvinceOfIssue, tvb, offset, field_len, value);
+ break;
+ case 594: /* Field UnderlyingLocaleOfIssue */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingLocaleOfIssue, tvb, offset, field_len, value);
+ break;
+ case 595: /* Field UnderlyingInstrRegistry */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingInstrRegistry, tvb, offset, field_len, value);
+ break;
+ case 596: /* Field LegCountryOfIssue */
+ proto_tree_add_string(fix_tree, hf_fix_LegCountryOfIssue, tvb, offset, field_len, value);
+ break;
+ case 597: /* Field LegStateOrProvinceOfIssue */
+ proto_tree_add_string(fix_tree, hf_fix_LegStateOrProvinceOfIssue, tvb, offset, field_len, value);
+ break;
+ case 598: /* Field LegLocaleOfIssue */
+ proto_tree_add_string(fix_tree, hf_fix_LegLocaleOfIssue, tvb, offset, field_len, value);
+ break;
+ case 599: /* Field LegInstrRegistry */
+ proto_tree_add_string(fix_tree, hf_fix_LegInstrRegistry, tvb, offset, field_len, value);
+ break;
+ case 600: /* Field LegSymbol */
+ proto_tree_add_string(fix_tree, hf_fix_LegSymbol, tvb, offset, field_len, value);
+ break;
+ case 601: /* Field LegSymbolSfx */
+ proto_tree_add_string(fix_tree, hf_fix_LegSymbolSfx, tvb, offset, field_len, value);
+ break;
+ case 602: /* Field LegSecurityID */
+ proto_tree_add_string(fix_tree, hf_fix_LegSecurityID, tvb, offset, field_len, value);
+ break;
+ case 603: /* Field LegSecurityIDSource */
+ proto_tree_add_string(fix_tree, hf_fix_LegSecurityIDSource, tvb, offset, field_len, value);
+ break;
+ case 604: /* Field NoLegSecurityAltID */
+ proto_tree_add_string(fix_tree, hf_fix_NoLegSecurityAltID, tvb, offset, field_len, value);
+ break;
+ case 605: /* Field LegSecurityAltID */
+ proto_tree_add_string(fix_tree, hf_fix_LegSecurityAltID, tvb, offset, field_len, value);
+ break;
+ case 606: /* Field LegSecurityAltIDSource */
+ proto_tree_add_string(fix_tree, hf_fix_LegSecurityAltIDSource, tvb, offset, field_len, value);
+ break;
+ case 607: /* Field LegProduct */
+ proto_tree_add_string(fix_tree, hf_fix_LegProduct, tvb, offset, field_len, value);
+ break;
+ case 608: /* Field LegCFICode */
+ proto_tree_add_string(fix_tree, hf_fix_LegCFICode, tvb, offset, field_len, value);
+ break;
+ case 609: /* Field LegSecurityType */
+ proto_tree_add_string(fix_tree, hf_fix_LegSecurityType, tvb, offset, field_len, value);
+ break;
+ case 610: /* Field LegMaturityMonthYear */
+ proto_tree_add_string(fix_tree, hf_fix_LegMaturityMonthYear, tvb, offset, field_len, value);
+ break;
+ case 611: /* Field LegMaturityDate */
+ proto_tree_add_string(fix_tree, hf_fix_LegMaturityDate, tvb, offset, field_len, value);
+ break;
+ case 612: /* Field LegStrikePrice */
+ proto_tree_add_string(fix_tree, hf_fix_LegStrikePrice, tvb, offset, field_len, value);
+ break;
+ case 613: /* Field LegOptAttribute */
+ proto_tree_add_string(fix_tree, hf_fix_LegOptAttribute, tvb, offset, field_len, value);
+ break;
+ case 614: /* Field LegContractMultiplier */
+ proto_tree_add_string(fix_tree, hf_fix_LegContractMultiplier, tvb, offset, field_len, value);
+ break;
+ case 615: /* Field LegCouponRate */
+ proto_tree_add_string(fix_tree, hf_fix_LegCouponRate, tvb, offset, field_len, value);
+ break;
+ case 616: /* Field LegSecurityExchange */
+ proto_tree_add_string(fix_tree, hf_fix_LegSecurityExchange, tvb, offset, field_len, value);
+ break;
+ case 617: /* Field LegIssuer */
+ proto_tree_add_string(fix_tree, hf_fix_LegIssuer, tvb, offset, field_len, value);
+ break;
+ case 618: /* Field EncodedLegIssuerLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedLegIssuerLen, tvb, offset, field_len, value);
+ break;
+ case 619: /* Field EncodedLegIssuer */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedLegIssuer, tvb, offset, field_len, value);
+ break;
+ case 620: /* Field LegSecurityDesc */
+ proto_tree_add_string(fix_tree, hf_fix_LegSecurityDesc, tvb, offset, field_len, value);
+ break;
+ case 621: /* Field EncodedLegSecurityDescLen */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedLegSecurityDescLen, tvb, offset, field_len, value);
+ break;
+ case 622: /* Field EncodedLegSecurityDesc */
+ proto_tree_add_string(fix_tree, hf_fix_EncodedLegSecurityDesc, tvb, offset, field_len, value);
+ break;
+ case 623: /* Field LegRatioQty */
+ proto_tree_add_string(fix_tree, hf_fix_LegRatioQty, tvb, offset, field_len, value);
+ break;
+ case 624: /* Field LegSide */
+ proto_tree_add_string(fix_tree, hf_fix_LegSide, tvb, offset, field_len, value);
+ break;
+ case 625: /* Field TradingSessionSubID */
+ proto_tree_add_string(fix_tree, hf_fix_TradingSessionSubID, tvb, offset, field_len, value);
+ break;
+ case 626: /* Field AllocType */
+ proto_tree_add_string(fix_tree, hf_fix_AllocType, tvb, offset, field_len, value);
+ break;
+ case 627: /* Field NoHops */
+ proto_tree_add_string(fix_tree, hf_fix_NoHops, tvb, offset, field_len, value);
+ break;
+ case 628: /* Field HopCompID */
+ proto_tree_add_string(fix_tree, hf_fix_HopCompID, tvb, offset, field_len, value);
+ break;
+ case 629: /* Field HopSendingTime */
+ proto_tree_add_string(fix_tree, hf_fix_HopSendingTime, tvb, offset, field_len, value);
+ break;
+ case 630: /* Field HopRefID */
+ proto_tree_add_string(fix_tree, hf_fix_HopRefID, tvb, offset, field_len, value);
+ break;
+ case 631: /* Field MidPx */
+ proto_tree_add_string(fix_tree, hf_fix_MidPx, tvb, offset, field_len, value);
+ break;
+ case 632: /* Field BidYield */
+ proto_tree_add_string(fix_tree, hf_fix_BidYield, tvb, offset, field_len, value);
+ break;
+ case 633: /* Field MidYield */
+ proto_tree_add_string(fix_tree, hf_fix_MidYield, tvb, offset, field_len, value);
+ break;
+ case 634: /* Field OfferYield */
+ proto_tree_add_string(fix_tree, hf_fix_OfferYield, tvb, offset, field_len, value);
+ break;
+ case 635: /* Field ClearingFeeIndicator */
+ proto_tree_add_string(fix_tree, hf_fix_ClearingFeeIndicator, tvb, offset, field_len, value);
+ break;
+ case 636: /* Field WorkingIndicator */
+ proto_tree_add_string(fix_tree, hf_fix_WorkingIndicator, tvb, offset, field_len, value);
+ break;
+ case 637: /* Field LegLastPx */
+ proto_tree_add_string(fix_tree, hf_fix_LegLastPx, tvb, offset, field_len, value);
+ break;
+ case 638: /* Field PriorityIndicator */
+ proto_tree_add_string(fix_tree, hf_fix_PriorityIndicator, tvb, offset, field_len, value);
+ break;
+ case 639: /* Field PriceImprovement */
+ proto_tree_add_string(fix_tree, hf_fix_PriceImprovement, tvb, offset, field_len, value);
+ break;
+ case 640: /* Field Price2 */
+ proto_tree_add_string(fix_tree, hf_fix_Price2, tvb, offset, field_len, value);
+ break;
+ case 641: /* Field LastForwardPoints2 */
+ proto_tree_add_string(fix_tree, hf_fix_LastForwardPoints2, tvb, offset, field_len, value);
+ break;
+ case 642: /* Field BidForwardPoints2 */
+ proto_tree_add_string(fix_tree, hf_fix_BidForwardPoints2, tvb, offset, field_len, value);
+ break;
+ case 643: /* Field OfferForwardPoints2 */
+ proto_tree_add_string(fix_tree, hf_fix_OfferForwardPoints2, tvb, offset, field_len, value);
+ break;
+ case 644: /* Field RFQReqID */
+ proto_tree_add_string(fix_tree, hf_fix_RFQReqID, tvb, offset, field_len, value);
+ break;
+ case 645: /* Field MktBidPx */
+ proto_tree_add_string(fix_tree, hf_fix_MktBidPx, tvb, offset, field_len, value);
+ break;
+ case 646: /* Field MktOfferPx */
+ proto_tree_add_string(fix_tree, hf_fix_MktOfferPx, tvb, offset, field_len, value);
+ break;
+ case 647: /* Field MinBidSize */
+ proto_tree_add_string(fix_tree, hf_fix_MinBidSize, tvb, offset, field_len, value);
+ break;
+ case 648: /* Field MinOfferSize */
+ proto_tree_add_string(fix_tree, hf_fix_MinOfferSize, tvb, offset, field_len, value);
+ break;
+ case 649: /* Field QuoteStatusReqID */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteStatusReqID, tvb, offset, field_len, value);
+ break;
+ case 650: /* Field LegalConfirm */
+ proto_tree_add_string(fix_tree, hf_fix_LegalConfirm, tvb, offset, field_len, value);
+ break;
+ case 651: /* Field UnderlyingLastPx */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingLastPx, tvb, offset, field_len, value);
+ break;
+ case 652: /* Field UnderlyingLastQty */
+ proto_tree_add_string(fix_tree, hf_fix_UnderlyingLastQty, tvb, offset, field_len, value);
+ break;
+ case 653: /* Field SecDefStatus */
+ proto_tree_add_string(fix_tree, hf_fix_SecDefStatus, tvb, offset, field_len, value);
+ break;
+ case 654: /* Field LegRefID */
+ proto_tree_add_string(fix_tree, hf_fix_LegRefID, tvb, offset, field_len, value);
+ break;
+ case 655: /* Field ContraLegRefID */
+ proto_tree_add_string(fix_tree, hf_fix_ContraLegRefID, tvb, offset, field_len, value);
+ break;
+ case 656: /* Field SettlCurrBidFxRate */
+ proto_tree_add_string(fix_tree, hf_fix_SettlCurrBidFxRate, tvb, offset, field_len, value);
+ break;
+ case 657: /* Field SettlCurrOfferFxRate */
+ proto_tree_add_string(fix_tree, hf_fix_SettlCurrOfferFxRate, tvb, offset, field_len, value);
+ break;
+ case 658: /* Field QuoteRequestRejectReason */
+ proto_tree_add_string(fix_tree, hf_fix_QuoteRequestRejectReason, tvb, offset, field_len, value);
+ break;
+ case 659: /* Field SideComplianceID */
+ proto_tree_add_string(fix_tree, hf_fix_SideComplianceID, tvb, offset, field_len, value);
+ break;
+ default:
+ /* XXX - it could be -1 if the tag isn't a number */
+ proto_tree_add_text(fix_tree, tvb, offset, field_len, "%i: %s", tag, value);
+ break;
+ }
+
+ field_offset = offset = ctrla_offset + 1;
+ ctrla_offset = tvb_find_guint8(tvb, field_offset, -1, 0x01);
+
+ g_free(tag_str);
+ g_free(value);
+ tag_str = NULL;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_fix(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_fix_Account,
+ { "Account (1)", "fix.Account",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Account", HFILL }
+ },
+ { &hf_fix_AdvId,
+ { "AdvId (2)", "fix.AdvId",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AdvId", HFILL }
+ },
+ { &hf_fix_AdvRefID,
+ { "AdvRefID (3)", "fix.AdvRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AdvRefID", HFILL }
+ },
+ { &hf_fix_AdvSide,
+ { "AdvSide (4)", "fix.AdvSide",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AdvSide", HFILL }
+ },
+ { &hf_fix_AdvTransType,
+ { "AdvTransType (5)", "fix.AdvTransType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AdvTransType", HFILL }
+ },
+ { &hf_fix_AvgPx,
+ { "AvgPx (6)", "fix.AvgPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AvgPx", HFILL }
+ },
+ { &hf_fix_BeginSeqNo,
+ { "BeginSeqNo (7)", "fix.BeginSeqNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BeginSeqNo", HFILL }
+ },
+ { &hf_fix_BeginString,
+ { "BeginString (8)", "fix.BeginString",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BeginString", HFILL }
+ },
+ { &hf_fix_BodyLength,
+ { "BodyLength (9)", "fix.BodyLength",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BodyLength", HFILL }
+ },
+ { &hf_fix_CheckSum,
+ { "CheckSum (10)", "fix.CheckSum",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CheckSum", HFILL }
+ },
+ { &hf_fix_ClOrdID,
+ { "ClOrdID (11)", "fix.ClOrdID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ClOrdID", HFILL }
+ },
+ { &hf_fix_Commission,
+ { "Commission (12)", "fix.Commission",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Commission", HFILL }
+ },
+ { &hf_fix_CommType,
+ { "CommType (13)", "fix.CommType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CommType", HFILL }
+ },
+ { &hf_fix_CumQty,
+ { "CumQty (14)", "fix.CumQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CumQty", HFILL }
+ },
+ { &hf_fix_Currency,
+ { "Currency (15)", "fix.Currency",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Currency", HFILL }
+ },
+ { &hf_fix_EndSeqNo,
+ { "EndSeqNo (16)", "fix.EndSeqNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EndSeqNo", HFILL }
+ },
+ { &hf_fix_ExecID,
+ { "ExecID (17)", "fix.ExecID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecID", HFILL }
+ },
+ { &hf_fix_ExecInst,
+ { "ExecInst (18)", "fix.ExecInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecInst", HFILL }
+ },
+ { &hf_fix_ExecRefID,
+ { "ExecRefID (19)", "fix.ExecRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecRefID", HFILL }
+ },
+ { &hf_fix_ExecTransType,
+ { "ExecTransType (20)", "fix.ExecTransType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecTransType", HFILL }
+ },
+ { &hf_fix_HandlInst,
+ { "HandlInst (21)", "fix.HandlInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "HandlInst", HFILL }
+ },
+ { &hf_fix_SecurityIDSource,
+ { "SecurityIDSource (22)", "fix.SecurityIDSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityIDSource", HFILL }
+ },
+ { &hf_fix_IOIid,
+ { "IOIid (23)", "fix.IOIid",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IOIid", HFILL }
+ },
+ { &hf_fix_IOIOthSvc,
+ { "IOIOthSvc (24)", "fix.IOIOthSvc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IOIOthSvc", HFILL }
+ },
+ { &hf_fix_IOIQltyInd,
+ { "IOIQltyInd (25)", "fix.IOIQltyInd",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IOIQltyInd", HFILL }
+ },
+ { &hf_fix_IOIRefID,
+ { "IOIRefID (26)", "fix.IOIRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IOIRefID", HFILL }
+ },
+ { &hf_fix_IOIQty,
+ { "IOIQty (27)", "fix.IOIQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IOIQty", HFILL }
+ },
+ { &hf_fix_IOITransType,
+ { "IOITransType (28)", "fix.IOITransType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IOITransType", HFILL }
+ },
+ { &hf_fix_LastCapacity,
+ { "LastCapacity (29)", "fix.LastCapacity",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LastCapacity", HFILL }
+ },
+ { &hf_fix_LastMkt,
+ { "LastMkt (30)", "fix.LastMkt",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LastMkt", HFILL }
+ },
+ { &hf_fix_LastPx,
+ { "LastPx (31)", "fix.LastPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LastPx", HFILL }
+ },
+ { &hf_fix_LastQty,
+ { "LastQty (32)", "fix.LastQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LastQty", HFILL }
+ },
+ { &hf_fix_LinesOfText,
+ { "LinesOfText (33)", "fix.LinesOfText",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LinesOfText", HFILL }
+ },
+ { &hf_fix_MsgSeqNum,
+ { "MsgSeqNum (34)", "fix.MsgSeqNum",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MsgSeqNum", HFILL }
+ },
+ { &hf_fix_MsgType,
+ { "MsgType (35)", "fix.MsgType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MsgType", HFILL }
+ },
+ { &hf_fix_NewSeqNo,
+ { "NewSeqNo (36)", "fix.NewSeqNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NewSeqNo", HFILL }
+ },
+ { &hf_fix_OrderID,
+ { "OrderID (37)", "fix.OrderID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrderID", HFILL }
+ },
+ { &hf_fix_OrderQty,
+ { "OrderQty (38)", "fix.OrderQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrderQty", HFILL }
+ },
+ { &hf_fix_OrdStatus,
+ { "OrdStatus (39)", "fix.OrdStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrdStatus", HFILL }
+ },
+ { &hf_fix_OrdType,
+ { "OrdType (40)", "fix.OrdType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrdType", HFILL }
+ },
+ { &hf_fix_OrigClOrdID,
+ { "OrigClOrdID (41)", "fix.OrigClOrdID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrigClOrdID", HFILL }
+ },
+ { &hf_fix_OrigTime,
+ { "OrigTime (42)", "fix.OrigTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrigTime", HFILL }
+ },
+ { &hf_fix_PossDupFlag,
+ { "PossDupFlag (43)", "fix.PossDupFlag",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PossDupFlag", HFILL }
+ },
+ { &hf_fix_Price,
+ { "Price (44)", "fix.Price",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Price", HFILL }
+ },
+ { &hf_fix_RefSeqNum,
+ { "RefSeqNum (45)", "fix.RefSeqNum",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RefSeqNum", HFILL }
+ },
+ { &hf_fix_RelatdSym,
+ { "RelatdSym (46)", "fix.RelatdSym",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RelatdSym", HFILL }
+ },
+ { &hf_fix_Rule80A,
+ { "Rule80A (47)", "fix.Rule80A",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Rule80A", HFILL }
+ },
+ { &hf_fix_SecurityID,
+ { "SecurityID (48)", "fix.SecurityID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityID", HFILL }
+ },
+ { &hf_fix_SenderCompID,
+ { "SenderCompID (49)", "fix.SenderCompID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SenderCompID", HFILL }
+ },
+ { &hf_fix_SenderSubID,
+ { "SenderSubID (50)", "fix.SenderSubID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SenderSubID", HFILL }
+ },
+ { &hf_fix_SendingDate,
+ { "SendingDate (51)", "fix.SendingDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SendingDate", HFILL }
+ },
+ { &hf_fix_SendingTime,
+ { "SendingTime (52)", "fix.SendingTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SendingTime", HFILL }
+ },
+ { &hf_fix_Quantity,
+ { "Quantity (53)", "fix.Quantity",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Quantity", HFILL }
+ },
+ { &hf_fix_Side,
+ { "Side (54)", "fix.Side",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Side", HFILL }
+ },
+ { &hf_fix_Symbol,
+ { "Symbol (55)", "fix.Symbol",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Symbol", HFILL }
+ },
+ { &hf_fix_TargetCompID,
+ { "TargetCompID (56)", "fix.TargetCompID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TargetCompID", HFILL }
+ },
+ { &hf_fix_TargetSubID,
+ { "TargetSubID (57)", "fix.TargetSubID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TargetSubID", HFILL }
+ },
+ { &hf_fix_Text,
+ { "Text (58)", "fix.Text",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Text", HFILL }
+ },
+ { &hf_fix_TimeInForce,
+ { "TimeInForce (59)", "fix.TimeInForce",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TimeInForce", HFILL }
+ },
+ { &hf_fix_TransactTime,
+ { "TransactTime (60)", "fix.TransactTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TransactTime", HFILL }
+ },
+ { &hf_fix_Urgency,
+ { "Urgency (61)", "fix.Urgency",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Urgency", HFILL }
+ },
+ { &hf_fix_ValidUntilTime,
+ { "ValidUntilTime (62)", "fix.ValidUntilTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ValidUntilTime", HFILL }
+ },
+ { &hf_fix_SettlmntTyp,
+ { "SettlmntTyp (63)", "fix.SettlmntTyp",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlmntTyp", HFILL }
+ },
+ { &hf_fix_FutSettDate,
+ { "FutSettDate (64)", "fix.FutSettDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "FutSettDate", HFILL }
+ },
+ { &hf_fix_SymbolSfx,
+ { "SymbolSfx (65)", "fix.SymbolSfx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SymbolSfx", HFILL }
+ },
+ { &hf_fix_ListID,
+ { "ListID (66)", "fix.ListID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ListID", HFILL }
+ },
+ { &hf_fix_ListSeqNo,
+ { "ListSeqNo (67)", "fix.ListSeqNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ListSeqNo", HFILL }
+ },
+ { &hf_fix_TotNoOrders,
+ { "TotNoOrders (68)", "fix.TotNoOrders",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotNoOrders", HFILL }
+ },
+ { &hf_fix_ListExecInst,
+ { "ListExecInst (69)", "fix.ListExecInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ListExecInst", HFILL }
+ },
+ { &hf_fix_AllocID,
+ { "AllocID (70)", "fix.AllocID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocID", HFILL }
+ },
+ { &hf_fix_AllocTransType,
+ { "AllocTransType (71)", "fix.AllocTransType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocTransType", HFILL }
+ },
+ { &hf_fix_RefAllocID,
+ { "RefAllocID (72)", "fix.RefAllocID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RefAllocID", HFILL }
+ },
+ { &hf_fix_NoOrders,
+ { "NoOrders (73)", "fix.NoOrders",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoOrders", HFILL }
+ },
+ { &hf_fix_AvgPrxPrecision,
+ { "AvgPrxPrecision (74)", "fix.AvgPrxPrecision",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AvgPrxPrecision", HFILL }
+ },
+ { &hf_fix_TradeDate,
+ { "TradeDate (75)", "fix.TradeDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeDate", HFILL }
+ },
+ { &hf_fix_ExecBroker,
+ { "ExecBroker (76)", "fix.ExecBroker",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecBroker", HFILL }
+ },
+ { &hf_fix_PositionEffect,
+ { "PositionEffect (77)", "fix.PositionEffect",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PositionEffect", HFILL }
+ },
+ { &hf_fix_NoAllocs,
+ { "NoAllocs (78)", "fix.NoAllocs",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoAllocs", HFILL }
+ },
+ { &hf_fix_AllocAccount,
+ { "AllocAccount (79)", "fix.AllocAccount",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocAccount", HFILL }
+ },
+ { &hf_fix_AllocQty,
+ { "AllocQty (80)", "fix.AllocQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocQty", HFILL }
+ },
+ { &hf_fix_ProcessCode,
+ { "ProcessCode (81)", "fix.ProcessCode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ProcessCode", HFILL }
+ },
+ { &hf_fix_NoRpts,
+ { "NoRpts (82)", "fix.NoRpts",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoRpts", HFILL }
+ },
+ { &hf_fix_RptSeq,
+ { "RptSeq (83)", "fix.RptSeq",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RptSeq", HFILL }
+ },
+ { &hf_fix_CxlQty,
+ { "CxlQty (84)", "fix.CxlQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CxlQty", HFILL }
+ },
+ { &hf_fix_NoDlvyInst,
+ { "NoDlvyInst (85)", "fix.NoDlvyInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoDlvyInst", HFILL }
+ },
+ { &hf_fix_DlvyInst,
+ { "DlvyInst (86)", "fix.DlvyInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DlvyInst", HFILL }
+ },
+ { &hf_fix_AllocStatus,
+ { "AllocStatus (87)", "fix.AllocStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocStatus", HFILL }
+ },
+ { &hf_fix_AllocRejCode,
+ { "AllocRejCode (88)", "fix.AllocRejCode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocRejCode", HFILL }
+ },
+ { &hf_fix_Signature,
+ { "Signature (89)", "fix.Signature",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Signature", HFILL }
+ },
+ { &hf_fix_SecureDataLen,
+ { "SecureDataLen (90)", "fix.SecureDataLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecureDataLen", HFILL }
+ },
+ { &hf_fix_SecureData,
+ { "SecureData (91)", "fix.SecureData",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecureData", HFILL }
+ },
+ { &hf_fix_BrokerOfCredit,
+ { "BrokerOfCredit (92)", "fix.BrokerOfCredit",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BrokerOfCredit", HFILL }
+ },
+ { &hf_fix_SignatureLength,
+ { "SignatureLength (93)", "fix.SignatureLength",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SignatureLength", HFILL }
+ },
+ { &hf_fix_EmailType,
+ { "EmailType (94)", "fix.EmailType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EmailType", HFILL }
+ },
+ { &hf_fix_RawDataLength,
+ { "RawDataLength (95)", "fix.RawDataLength",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RawDataLength", HFILL }
+ },
+ { &hf_fix_RawData,
+ { "RawData (96)", "fix.RawData",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RawData", HFILL }
+ },
+ { &hf_fix_PossResend,
+ { "PossResend (97)", "fix.PossResend",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PossResend", HFILL }
+ },
+ { &hf_fix_EncryptMethod,
+ { "EncryptMethod (98)", "fix.EncryptMethod",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncryptMethod", HFILL }
+ },
+ { &hf_fix_StopPx,
+ { "StopPx (99)", "fix.StopPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "StopPx", HFILL }
+ },
+ { &hf_fix_ExDestination,
+ { "ExDestination (100)", "fix.ExDestination",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExDestination", HFILL }
+ },
+ { &hf_fix_CxlRejReason,
+ { "CxlRejReason (102)", "fix.CxlRejReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CxlRejReason", HFILL }
+ },
+ { &hf_fix_OrdRejReason,
+ { "OrdRejReason (103)", "fix.OrdRejReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrdRejReason", HFILL }
+ },
+ { &hf_fix_IOIQualifier,
+ { "IOIQualifier (104)", "fix.IOIQualifier",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IOIQualifier", HFILL }
+ },
+ { &hf_fix_WaveNo,
+ { "WaveNo (105)", "fix.WaveNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WaveNo", HFILL }
+ },
+ { &hf_fix_Issuer,
+ { "Issuer (106)", "fix.Issuer",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Issuer", HFILL }
+ },
+ { &hf_fix_SecurityDesc,
+ { "SecurityDesc (107)", "fix.SecurityDesc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityDesc", HFILL }
+ },
+ { &hf_fix_HeartBtInt,
+ { "HeartBtInt (108)", "fix.HeartBtInt",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "HeartBtInt", HFILL }
+ },
+ { &hf_fix_ClientID,
+ { "ClientID (109)", "fix.ClientID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ClientID", HFILL }
+ },
+ { &hf_fix_MinQty,
+ { "MinQty (110)", "fix.MinQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MinQty", HFILL }
+ },
+ { &hf_fix_MaxFloor,
+ { "MaxFloor (111)", "fix.MaxFloor",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MaxFloor", HFILL }
+ },
+ { &hf_fix_TestReqID,
+ { "TestReqID (112)", "fix.TestReqID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TestReqID", HFILL }
+ },
+ { &hf_fix_ReportToExch,
+ { "ReportToExch (113)", "fix.ReportToExch",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ReportToExch", HFILL }
+ },
+ { &hf_fix_LocateReqd,
+ { "LocateReqd (114)", "fix.LocateReqd",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LocateReqd", HFILL }
+ },
+ { &hf_fix_OnBehalfOfCompID,
+ { "OnBehalfOfCompID (115)", "fix.OnBehalfOfCompID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OnBehalfOfCompID", HFILL }
+ },
+ { &hf_fix_OnBehalfOfSubID,
+ { "OnBehalfOfSubID (116)", "fix.OnBehalfOfSubID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OnBehalfOfSubID", HFILL }
+ },
+ { &hf_fix_QuoteID,
+ { "QuoteID (117)", "fix.QuoteID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteID", HFILL }
+ },
+ { &hf_fix_NetMoney,
+ { "NetMoney (118)", "fix.NetMoney",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NetMoney", HFILL }
+ },
+ { &hf_fix_SettlCurrAmt,
+ { "SettlCurrAmt (119)", "fix.SettlCurrAmt",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlCurrAmt", HFILL }
+ },
+ { &hf_fix_SettlCurrency,
+ { "SettlCurrency (120)", "fix.SettlCurrency",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlCurrency", HFILL }
+ },
+ { &hf_fix_ForexReq,
+ { "ForexReq (121)", "fix.ForexReq",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ForexReq", HFILL }
+ },
+ { &hf_fix_OrigSendingTime,
+ { "OrigSendingTime (122)", "fix.OrigSendingTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrigSendingTime", HFILL }
+ },
+ { &hf_fix_GapFillFlag,
+ { "GapFillFlag (123)", "fix.GapFillFlag",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "GapFillFlag", HFILL }
+ },
+ { &hf_fix_NoExecs,
+ { "NoExecs (124)", "fix.NoExecs",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoExecs", HFILL }
+ },
+ { &hf_fix_CxlType,
+ { "CxlType (125)", "fix.CxlType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CxlType", HFILL }
+ },
+ { &hf_fix_ExpireTime,
+ { "ExpireTime (126)", "fix.ExpireTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExpireTime", HFILL }
+ },
+ { &hf_fix_DKReason,
+ { "DKReason (127)", "fix.DKReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DKReason", HFILL }
+ },
+ { &hf_fix_DeliverToCompID,
+ { "DeliverToCompID (128)", "fix.DeliverToCompID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DeliverToCompID", HFILL }
+ },
+ { &hf_fix_DeliverToSubID,
+ { "DeliverToSubID (129)", "fix.DeliverToSubID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DeliverToSubID", HFILL }
+ },
+ { &hf_fix_IOINaturalFlag,
+ { "IOINaturalFlag (130)", "fix.IOINaturalFlag",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IOINaturalFlag", HFILL }
+ },
+ { &hf_fix_QuoteReqID,
+ { "QuoteReqID (131)", "fix.QuoteReqID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteReqID", HFILL }
+ },
+ { &hf_fix_BidPx,
+ { "BidPx (132)", "fix.BidPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidPx", HFILL }
+ },
+ { &hf_fix_OfferPx,
+ { "OfferPx (133)", "fix.OfferPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OfferPx", HFILL }
+ },
+ { &hf_fix_BidSize,
+ { "BidSize (134)", "fix.BidSize",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidSize", HFILL }
+ },
+ { &hf_fix_OfferSize,
+ { "OfferSize (135)", "fix.OfferSize",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OfferSize", HFILL }
+ },
+ { &hf_fix_NoMiscFees,
+ { "NoMiscFees (136)", "fix.NoMiscFees",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoMiscFees", HFILL }
+ },
+ { &hf_fix_MiscFeeAmt,
+ { "MiscFeeAmt (137)", "fix.MiscFeeAmt",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MiscFeeAmt", HFILL }
+ },
+ { &hf_fix_MiscFeeCurr,
+ { "MiscFeeCurr (138)", "fix.MiscFeeCurr",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MiscFeeCurr", HFILL }
+ },
+ { &hf_fix_MiscFeeType,
+ { "MiscFeeType (139)", "fix.MiscFeeType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MiscFeeType", HFILL }
+ },
+ { &hf_fix_PrevClosePx,
+ { "PrevClosePx (140)", "fix.PrevClosePx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PrevClosePx", HFILL }
+ },
+ { &hf_fix_ResetSeqNumFlag,
+ { "ResetSeqNumFlag (141)", "fix.ResetSeqNumFlag",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ResetSeqNumFlag", HFILL }
+ },
+ { &hf_fix_SenderLocationID,
+ { "SenderLocationID (142)", "fix.SenderLocationID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SenderLocationID", HFILL }
+ },
+ { &hf_fix_TargetLocationID,
+ { "TargetLocationID (143)", "fix.TargetLocationID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TargetLocationID", HFILL }
+ },
+ { &hf_fix_OnBehalfOfLocationID,
+ { "OnBehalfOfLocationID (144)", "fix.OnBehalfOfLocationID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OnBehalfOfLocationID", HFILL }
+ },
+ { &hf_fix_DeliverToLocationID,
+ { "DeliverToLocationID (145)", "fix.DeliverToLocationID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DeliverToLocationID", HFILL }
+ },
+ { &hf_fix_NoRelatedSym,
+ { "NoRelatedSym (146)", "fix.NoRelatedSym",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoRelatedSym", HFILL }
+ },
+ { &hf_fix_Subject,
+ { "Subject (147)", "fix.Subject",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Subject", HFILL }
+ },
+ { &hf_fix_Headline,
+ { "Headline (148)", "fix.Headline",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Headline", HFILL }
+ },
+ { &hf_fix_URLLink,
+ { "URLLink (149)", "fix.URLLink",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "URLLink", HFILL }
+ },
+ { &hf_fix_ExecType,
+ { "ExecType (150)", "fix.ExecType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecType", HFILL }
+ },
+ { &hf_fix_LeavesQty,
+ { "LeavesQty (151)", "fix.LeavesQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LeavesQty", HFILL }
+ },
+ { &hf_fix_CashOrderQty,
+ { "CashOrderQty (152)", "fix.CashOrderQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashOrderQty", HFILL }
+ },
+ { &hf_fix_AllocAvgPx,
+ { "AllocAvgPx (153)", "fix.AllocAvgPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocAvgPx", HFILL }
+ },
+ { &hf_fix_AllocNetMoney,
+ { "AllocNetMoney (154)", "fix.AllocNetMoney",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocNetMoney", HFILL }
+ },
+ { &hf_fix_SettlCurrFxRate,
+ { "SettlCurrFxRate (155)", "fix.SettlCurrFxRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlCurrFxRate", HFILL }
+ },
+ { &hf_fix_SettlCurrFxRateCalc,
+ { "SettlCurrFxRateCalc (156)", "fix.SettlCurrFxRateCalc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlCurrFxRateCalc", HFILL }
+ },
+ { &hf_fix_NumDaysInterest,
+ { "NumDaysInterest (157)", "fix.NumDaysInterest",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NumDaysInterest", HFILL }
+ },
+ { &hf_fix_AccruedInterestRate,
+ { "AccruedInterestRate (158)", "fix.AccruedInterestRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AccruedInterestRate", HFILL }
+ },
+ { &hf_fix_AccruedInterestAmt,
+ { "AccruedInterestAmt (159)", "fix.AccruedInterestAmt",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AccruedInterestAmt", HFILL }
+ },
+ { &hf_fix_SettlInstMode,
+ { "SettlInstMode (160)", "fix.SettlInstMode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlInstMode", HFILL }
+ },
+ { &hf_fix_AllocText,
+ { "AllocText (161)", "fix.AllocText",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocText", HFILL }
+ },
+ { &hf_fix_SettlInstID,
+ { "SettlInstID (162)", "fix.SettlInstID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlInstID", HFILL }
+ },
+ { &hf_fix_SettlInstTransType,
+ { "SettlInstTransType (163)", "fix.SettlInstTransType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlInstTransType", HFILL }
+ },
+ { &hf_fix_EmailThreadID,
+ { "EmailThreadID (164)", "fix.EmailThreadID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EmailThreadID", HFILL }
+ },
+ { &hf_fix_SettlInstSource,
+ { "SettlInstSource (165)", "fix.SettlInstSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlInstSource", HFILL }
+ },
+ { &hf_fix_SettlLocation,
+ { "SettlLocation (166)", "fix.SettlLocation",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlLocation", HFILL }
+ },
+ { &hf_fix_SecurityType,
+ { "SecurityType (167)", "fix.SecurityType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityType", HFILL }
+ },
+ { &hf_fix_EffectiveTime,
+ { "EffectiveTime (168)", "fix.EffectiveTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EffectiveTime", HFILL }
+ },
+ { &hf_fix_StandInstDbType,
+ { "StandInstDbType (169)", "fix.StandInstDbType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "StandInstDbType", HFILL }
+ },
+ { &hf_fix_StandInstDbName,
+ { "StandInstDbName (170)", "fix.StandInstDbName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "StandInstDbName", HFILL }
+ },
+ { &hf_fix_StandInstDbID,
+ { "StandInstDbID (171)", "fix.StandInstDbID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "StandInstDbID", HFILL }
+ },
+ { &hf_fix_SettlDeliveryType,
+ { "SettlDeliveryType (172)", "fix.SettlDeliveryType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlDeliveryType", HFILL }
+ },
+ { &hf_fix_SettlDepositoryCode,
+ { "SettlDepositoryCode (173)", "fix.SettlDepositoryCode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlDepositoryCode", HFILL }
+ },
+ { &hf_fix_SettlBrkrCode,
+ { "SettlBrkrCode (174)", "fix.SettlBrkrCode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlBrkrCode", HFILL }
+ },
+ { &hf_fix_SettlInstCode,
+ { "SettlInstCode (175)", "fix.SettlInstCode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlInstCode", HFILL }
+ },
+ { &hf_fix_SecuritySettlAgentName,
+ { "SecuritySettlAgentName (176)", "fix.SecuritySettlAgentName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecuritySettlAgentName", HFILL }
+ },
+ { &hf_fix_SecuritySettlAgentCode,
+ { "SecuritySettlAgentCode (177)", "fix.SecuritySettlAgentCode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecuritySettlAgentCode", HFILL }
+ },
+ { &hf_fix_SecuritySettlAgentAcctNum,
+ { "SecuritySettlAgentAcctNum (178)", "fix.SecuritySettlAgentAcctNum",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecuritySettlAgentAcctNum", HFILL }
+ },
+ { &hf_fix_SecuritySettlAgentAcctName,
+ { "SecuritySettlAgentAcctName (179)", "fix.SecuritySettlAgentAcctName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecuritySettlAgentAcctName", HFILL }
+ },
+ { &hf_fix_SecuritySettlAgentContactName,
+ { "SecuritySettlAgentContactName (180)", "fix.SecuritySettlAgentContactName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecuritySettlAgentContactName", HFILL }
+ },
+ { &hf_fix_SecuritySettlAgentContactPhone,
+ { "SecuritySettlAgentContactPhone (181)", "fix.SecuritySettlAgentContactPhone",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecuritySettlAgentContactPhone", HFILL }
+ },
+ { &hf_fix_CashSettlAgentName,
+ { "CashSettlAgentName (182)", "fix.CashSettlAgentName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashSettlAgentName", HFILL }
+ },
+ { &hf_fix_CashSettlAgentCode,
+ { "CashSettlAgentCode (183)", "fix.CashSettlAgentCode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashSettlAgentCode", HFILL }
+ },
+ { &hf_fix_CashSettlAgentAcctNum,
+ { "CashSettlAgentAcctNum (184)", "fix.CashSettlAgentAcctNum",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashSettlAgentAcctNum", HFILL }
+ },
+ { &hf_fix_CashSettlAgentAcctName,
+ { "CashSettlAgentAcctName (185)", "fix.CashSettlAgentAcctName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashSettlAgentAcctName", HFILL }
+ },
+ { &hf_fix_CashSettlAgentContactName,
+ { "CashSettlAgentContactName (186)", "fix.CashSettlAgentContactName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashSettlAgentContactName", HFILL }
+ },
+ { &hf_fix_CashSettlAgentContactPhone,
+ { "CashSettlAgentContactPhone (187)", "fix.CashSettlAgentContactPhone",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashSettlAgentContactPhone", HFILL }
+ },
+ { &hf_fix_BidSpotRate,
+ { "BidSpotRate (188)", "fix.BidSpotRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidSpotRate", HFILL }
+ },
+ { &hf_fix_BidForwardPoints,
+ { "BidForwardPoints (189)", "fix.BidForwardPoints",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidForwardPoints", HFILL }
+ },
+ { &hf_fix_OfferSpotRate,
+ { "OfferSpotRate (190)", "fix.OfferSpotRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OfferSpotRate", HFILL }
+ },
+ { &hf_fix_OfferForwardPoints,
+ { "OfferForwardPoints (191)", "fix.OfferForwardPoints",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OfferForwardPoints", HFILL }
+ },
+ { &hf_fix_OrderQty2,
+ { "OrderQty2 (192)", "fix.OrderQty2",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrderQty2", HFILL }
+ },
+ { &hf_fix_FutSettDate2,
+ { "FutSettDate2 (193)", "fix.FutSettDate2",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "FutSettDate2", HFILL }
+ },
+ { &hf_fix_LastSpotRate,
+ { "LastSpotRate (194)", "fix.LastSpotRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LastSpotRate", HFILL }
+ },
+ { &hf_fix_LastForwardPoints,
+ { "LastForwardPoints (195)", "fix.LastForwardPoints",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LastForwardPoints", HFILL }
+ },
+ { &hf_fix_AllocLinkID,
+ { "AllocLinkID (196)", "fix.AllocLinkID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocLinkID", HFILL }
+ },
+ { &hf_fix_AllocLinkType,
+ { "AllocLinkType (197)", "fix.AllocLinkType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocLinkType", HFILL }
+ },
+ { &hf_fix_SecondaryOrderID,
+ { "SecondaryOrderID (198)", "fix.SecondaryOrderID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecondaryOrderID", HFILL }
+ },
+ { &hf_fix_NoIOIQualifiers,
+ { "NoIOIQualifiers (199)", "fix.NoIOIQualifiers",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoIOIQualifiers", HFILL }
+ },
+ { &hf_fix_MaturityMonthYear,
+ { "MaturityMonthYear (200)", "fix.MaturityMonthYear",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MaturityMonthYear", HFILL }
+ },
+ { &hf_fix_PutOrCall,
+ { "PutOrCall (201)", "fix.PutOrCall",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PutOrCall", HFILL }
+ },
+ { &hf_fix_StrikePrice,
+ { "StrikePrice (202)", "fix.StrikePrice",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "StrikePrice", HFILL }
+ },
+ { &hf_fix_CoveredOrUncovered,
+ { "CoveredOrUncovered (203)", "fix.CoveredOrUncovered",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CoveredOrUncovered", HFILL }
+ },
+ { &hf_fix_CustomerOrFirm,
+ { "CustomerOrFirm (204)", "fix.CustomerOrFirm",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CustomerOrFirm", HFILL }
+ },
+ { &hf_fix_MaturityDay,
+ { "MaturityDay (205)", "fix.MaturityDay",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MaturityDay", HFILL }
+ },
+ { &hf_fix_OptAttribute,
+ { "OptAttribute (206)", "fix.OptAttribute",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OptAttribute", HFILL }
+ },
+ { &hf_fix_SecurityExchange,
+ { "SecurityExchange (207)", "fix.SecurityExchange",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityExchange", HFILL }
+ },
+ { &hf_fix_NotifyBrokerOfCredit,
+ { "NotifyBrokerOfCredit (208)", "fix.NotifyBrokerOfCredit",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NotifyBrokerOfCredit", HFILL }
+ },
+ { &hf_fix_AllocHandlInst,
+ { "AllocHandlInst (209)", "fix.AllocHandlInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocHandlInst", HFILL }
+ },
+ { &hf_fix_MaxShow,
+ { "MaxShow (210)", "fix.MaxShow",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MaxShow", HFILL }
+ },
+ { &hf_fix_PegDifference,
+ { "PegDifference (211)", "fix.PegDifference",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PegDifference", HFILL }
+ },
+ { &hf_fix_XmlDataLen,
+ { "XmlDataLen (212)", "fix.XmlDataLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "XmlDataLen", HFILL }
+ },
+ { &hf_fix_XmlData,
+ { "XmlData (213)", "fix.XmlData",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "XmlData", HFILL }
+ },
+ { &hf_fix_SettlInstRefID,
+ { "SettlInstRefID (214)", "fix.SettlInstRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlInstRefID", HFILL }
+ },
+ { &hf_fix_NoRoutingIDs,
+ { "NoRoutingIDs (215)", "fix.NoRoutingIDs",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoRoutingIDs", HFILL }
+ },
+ { &hf_fix_RoutingType,
+ { "RoutingType (216)", "fix.RoutingType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RoutingType", HFILL }
+ },
+ { &hf_fix_RoutingID,
+ { "RoutingID (217)", "fix.RoutingID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RoutingID", HFILL }
+ },
+ { &hf_fix_Spread,
+ { "Spread (218)", "fix.Spread",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Spread", HFILL }
+ },
+ { &hf_fix_Benchmark,
+ { "Benchmark (219)", "fix.Benchmark",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Benchmark", HFILL }
+ },
+ { &hf_fix_BenchmarkCurveCurrency,
+ { "BenchmarkCurveCurrency (220)", "fix.BenchmarkCurveCurrency",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BenchmarkCurveCurrency", HFILL }
+ },
+ { &hf_fix_BenchmarkCurveName,
+ { "BenchmarkCurveName (221)", "fix.BenchmarkCurveName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BenchmarkCurveName", HFILL }
+ },
+ { &hf_fix_BenchmarkCurvePoint,
+ { "BenchmarkCurvePoint (222)", "fix.BenchmarkCurvePoint",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BenchmarkCurvePoint", HFILL }
+ },
+ { &hf_fix_CouponRate,
+ { "CouponRate (223)", "fix.CouponRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CouponRate", HFILL }
+ },
+ { &hf_fix_CouponPaymentDate,
+ { "CouponPaymentDate (224)", "fix.CouponPaymentDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CouponPaymentDate", HFILL }
+ },
+ { &hf_fix_IssueDate,
+ { "IssueDate (225)", "fix.IssueDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IssueDate", HFILL }
+ },
+ { &hf_fix_RepurchaseTerm,
+ { "RepurchaseTerm (226)", "fix.RepurchaseTerm",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RepurchaseTerm", HFILL }
+ },
+ { &hf_fix_RepurchaseRate,
+ { "RepurchaseRate (227)", "fix.RepurchaseRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RepurchaseRate", HFILL }
+ },
+ { &hf_fix_Factor,
+ { "Factor (228)", "fix.Factor",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Factor", HFILL }
+ },
+ { &hf_fix_TradeOriginationDate,
+ { "TradeOriginationDate (229)", "fix.TradeOriginationDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeOriginationDate", HFILL }
+ },
+ { &hf_fix_ExDate,
+ { "ExDate (230)", "fix.ExDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExDate", HFILL }
+ },
+ { &hf_fix_ContractMultiplier,
+ { "ContractMultiplier (231)", "fix.ContractMultiplier",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ContractMultiplier", HFILL }
+ },
+ { &hf_fix_NoStipulations,
+ { "NoStipulations (232)", "fix.NoStipulations",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoStipulations", HFILL }
+ },
+ { &hf_fix_StipulationType,
+ { "StipulationType (233)", "fix.StipulationType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "StipulationType", HFILL }
+ },
+ { &hf_fix_StipulationValue,
+ { "StipulationValue (234)", "fix.StipulationValue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "StipulationValue", HFILL }
+ },
+ { &hf_fix_YieldType,
+ { "YieldType (235)", "fix.YieldType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "YieldType", HFILL }
+ },
+ { &hf_fix_Yield,
+ { "Yield (236)", "fix.Yield",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Yield", HFILL }
+ },
+ { &hf_fix_TotalTakedown,
+ { "TotalTakedown (237)", "fix.TotalTakedown",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotalTakedown", HFILL }
+ },
+ { &hf_fix_Concession,
+ { "Concession (238)", "fix.Concession",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Concession", HFILL }
+ },
+ { &hf_fix_RepoCollateralSecurityType,
+ { "RepoCollateralSecurityType (239)", "fix.RepoCollateralSecurityType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RepoCollateralSecurityType", HFILL }
+ },
+ { &hf_fix_RedemptionDate,
+ { "RedemptionDate (240)", "fix.RedemptionDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RedemptionDate", HFILL }
+ },
+ { &hf_fix_UnderlyingCouponPaymentDate,
+ { "UnderlyingCouponPaymentDate (241)", "fix.UnderlyingCouponPaymentDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingCouponPaymentDate", HFILL }
+ },
+ { &hf_fix_UnderlyingIssueDate,
+ { "UnderlyingIssueDate (242)", "fix.UnderlyingIssueDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingIssueDate", HFILL }
+ },
+ { &hf_fix_UnderlyingRepoCollateralSecurityType,
+ { "UnderlyingRepoCollateralSecurityType (243)", "fix.UnderlyingRepoCollateralSecurityType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingRepoCollateralSecurityType", HFILL }
+ },
+ { &hf_fix_UnderlyingRepurchaseTerm,
+ { "UnderlyingRepurchaseTerm (244)", "fix.UnderlyingRepurchaseTerm",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingRepurchaseTerm", HFILL }
+ },
+ { &hf_fix_UnderlyingRepurchaseRate,
+ { "UnderlyingRepurchaseRate (245)", "fix.UnderlyingRepurchaseRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingRepurchaseRate", HFILL }
+ },
+ { &hf_fix_UnderlyingFactor,
+ { "UnderlyingFactor (246)", "fix.UnderlyingFactor",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingFactor", HFILL }
+ },
+ { &hf_fix_UnderlyingRedemptionDate,
+ { "UnderlyingRedemptionDate (247)", "fix.UnderlyingRedemptionDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingRedemptionDate", HFILL }
+ },
+ { &hf_fix_LegCouponPaymentDate,
+ { "LegCouponPaymentDate (248)", "fix.LegCouponPaymentDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegCouponPaymentDate", HFILL }
+ },
+ { &hf_fix_LegIssueDate,
+ { "LegIssueDate (249)", "fix.LegIssueDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegIssueDate", HFILL }
+ },
+ { &hf_fix_LegRepoCollateralSecurityType,
+ { "LegRepoCollateralSecurityType (250)", "fix.LegRepoCollateralSecurityType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegRepoCollateralSecurityType", HFILL }
+ },
+ { &hf_fix_LegRepurchaseTerm,
+ { "LegRepurchaseTerm (251)", "fix.LegRepurchaseTerm",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegRepurchaseTerm", HFILL }
+ },
+ { &hf_fix_LegRepurchaseRate,
+ { "LegRepurchaseRate (252)", "fix.LegRepurchaseRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegRepurchaseRate", HFILL }
+ },
+ { &hf_fix_LegFactor,
+ { "LegFactor (253)", "fix.LegFactor",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegFactor", HFILL }
+ },
+ { &hf_fix_LegRedemptionDate,
+ { "LegRedemptionDate (254)", "fix.LegRedemptionDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegRedemptionDate", HFILL }
+ },
+ { &hf_fix_CreditRating,
+ { "CreditRating (255)", "fix.CreditRating",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CreditRating", HFILL }
+ },
+ { &hf_fix_UnderlyingCreditRating,
+ { "UnderlyingCreditRating (256)", "fix.UnderlyingCreditRating",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingCreditRating", HFILL }
+ },
+ { &hf_fix_LegCreditRating,
+ { "LegCreditRating (257)", "fix.LegCreditRating",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegCreditRating", HFILL }
+ },
+ { &hf_fix_TradedFlatSwitch,
+ { "TradedFlatSwitch (258)", "fix.TradedFlatSwitch",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradedFlatSwitch", HFILL }
+ },
+ { &hf_fix_BasisFeatureDate,
+ { "BasisFeatureDate (259)", "fix.BasisFeatureDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BasisFeatureDate", HFILL }
+ },
+ { &hf_fix_BasisFeaturePrice,
+ { "BasisFeaturePrice (260)", "fix.BasisFeaturePrice",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BasisFeaturePrice", HFILL }
+ },
+ { &hf_fix_ReservedAllocated,
+ { "ReservedAllocated (261)", "fix.ReservedAllocated",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ReservedAllocated", HFILL }
+ },
+ { &hf_fix_MDReqID,
+ { "MDReqID (262)", "fix.MDReqID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDReqID", HFILL }
+ },
+ { &hf_fix_SubscriptionRequestType,
+ { "SubscriptionRequestType (263)", "fix.SubscriptionRequestType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SubscriptionRequestType", HFILL }
+ },
+ { &hf_fix_MarketDepth,
+ { "MarketDepth (264)", "fix.MarketDepth",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MarketDepth", HFILL }
+ },
+ { &hf_fix_MDUpdateType,
+ { "MDUpdateType (265)", "fix.MDUpdateType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDUpdateType", HFILL }
+ },
+ { &hf_fix_AggregatedBook,
+ { "AggregatedBook (266)", "fix.AggregatedBook",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AggregatedBook", HFILL }
+ },
+ { &hf_fix_NoMDEntryTypes,
+ { "NoMDEntryTypes (267)", "fix.NoMDEntryTypes",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoMDEntryTypes", HFILL }
+ },
+ { &hf_fix_NoMDEntries,
+ { "NoMDEntries (268)", "fix.NoMDEntries",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoMDEntries", HFILL }
+ },
+ { &hf_fix_MDEntryType,
+ { "MDEntryType (269)", "fix.MDEntryType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntryType", HFILL }
+ },
+ { &hf_fix_MDEntryPx,
+ { "MDEntryPx (270)", "fix.MDEntryPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntryPx", HFILL }
+ },
+ { &hf_fix_MDEntrySize,
+ { "MDEntrySize (271)", "fix.MDEntrySize",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntrySize", HFILL }
+ },
+ { &hf_fix_MDEntryDate,
+ { "MDEntryDate (272)", "fix.MDEntryDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntryDate", HFILL }
+ },
+ { &hf_fix_MDEntryTime,
+ { "MDEntryTime (273)", "fix.MDEntryTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntryTime", HFILL }
+ },
+ { &hf_fix_TickDirection,
+ { "TickDirection (274)", "fix.TickDirection",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TickDirection", HFILL }
+ },
+ { &hf_fix_MDMkt,
+ { "MDMkt (275)", "fix.MDMkt",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDMkt", HFILL }
+ },
+ { &hf_fix_QuoteCondition,
+ { "QuoteCondition (276)", "fix.QuoteCondition",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteCondition", HFILL }
+ },
+ { &hf_fix_TradeCondition,
+ { "TradeCondition (277)", "fix.TradeCondition",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeCondition", HFILL }
+ },
+ { &hf_fix_MDEntryID,
+ { "MDEntryID (278)", "fix.MDEntryID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntryID", HFILL }
+ },
+ { &hf_fix_MDUpdateAction,
+ { "MDUpdateAction (279)", "fix.MDUpdateAction",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDUpdateAction", HFILL }
+ },
+ { &hf_fix_MDEntryRefID,
+ { "MDEntryRefID (280)", "fix.MDEntryRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntryRefID", HFILL }
+ },
+ { &hf_fix_MDReqRejReason,
+ { "MDReqRejReason (281)", "fix.MDReqRejReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDReqRejReason", HFILL }
+ },
+ { &hf_fix_MDEntryOriginator,
+ { "MDEntryOriginator (282)", "fix.MDEntryOriginator",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntryOriginator", HFILL }
+ },
+ { &hf_fix_LocationID,
+ { "LocationID (283)", "fix.LocationID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LocationID", HFILL }
+ },
+ { &hf_fix_DeskID,
+ { "DeskID (284)", "fix.DeskID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DeskID", HFILL }
+ },
+ { &hf_fix_DeleteReason,
+ { "DeleteReason (285)", "fix.DeleteReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DeleteReason", HFILL }
+ },
+ { &hf_fix_OpenCloseSettleFlag,
+ { "OpenCloseSettleFlag (286)", "fix.OpenCloseSettleFlag",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OpenCloseSettleFlag", HFILL }
+ },
+ { &hf_fix_SellerDays,
+ { "SellerDays (287)", "fix.SellerDays",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SellerDays", HFILL }
+ },
+ { &hf_fix_MDEntryBuyer,
+ { "MDEntryBuyer (288)", "fix.MDEntryBuyer",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntryBuyer", HFILL }
+ },
+ { &hf_fix_MDEntrySeller,
+ { "MDEntrySeller (289)", "fix.MDEntrySeller",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntrySeller", HFILL }
+ },
+ { &hf_fix_MDEntryPositionNo,
+ { "MDEntryPositionNo (290)", "fix.MDEntryPositionNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDEntryPositionNo", HFILL }
+ },
+ { &hf_fix_FinancialStatus,
+ { "FinancialStatus (291)", "fix.FinancialStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "FinancialStatus", HFILL }
+ },
+ { &hf_fix_CorporateAction,
+ { "CorporateAction (292)", "fix.CorporateAction",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CorporateAction", HFILL }
+ },
+ { &hf_fix_DefBidSize,
+ { "DefBidSize (293)", "fix.DefBidSize",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DefBidSize", HFILL }
+ },
+ { &hf_fix_DefOfferSize,
+ { "DefOfferSize (294)", "fix.DefOfferSize",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DefOfferSize", HFILL }
+ },
+ { &hf_fix_NoQuoteEntries,
+ { "NoQuoteEntries (295)", "fix.NoQuoteEntries",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoQuoteEntries", HFILL }
+ },
+ { &hf_fix_NoQuoteSets,
+ { "NoQuoteSets (296)", "fix.NoQuoteSets",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoQuoteSets", HFILL }
+ },
+ { &hf_fix_QuoteStatus,
+ { "QuoteStatus (297)", "fix.QuoteStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteStatus", HFILL }
+ },
+ { &hf_fix_QuoteCancelType,
+ { "QuoteCancelType (298)", "fix.QuoteCancelType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteCancelType", HFILL }
+ },
+ { &hf_fix_QuoteEntryID,
+ { "QuoteEntryID (299)", "fix.QuoteEntryID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteEntryID", HFILL }
+ },
+ { &hf_fix_QuoteRejectReason,
+ { "QuoteRejectReason (300)", "fix.QuoteRejectReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteRejectReason", HFILL }
+ },
+ { &hf_fix_QuoteResponseLevel,
+ { "QuoteResponseLevel (301)", "fix.QuoteResponseLevel",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteResponseLevel", HFILL }
+ },
+ { &hf_fix_QuoteSetID,
+ { "QuoteSetID (302)", "fix.QuoteSetID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteSetID", HFILL }
+ },
+ { &hf_fix_QuoteRequestType,
+ { "QuoteRequestType (303)", "fix.QuoteRequestType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteRequestType", HFILL }
+ },
+ { &hf_fix_TotQuoteEntries,
+ { "TotQuoteEntries (304)", "fix.TotQuoteEntries",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotQuoteEntries", HFILL }
+ },
+ { &hf_fix_UnderlyingSecurityIDSource,
+ { "UnderlyingSecurityIDSource (305)", "fix.UnderlyingSecurityIDSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingSecurityIDSource", HFILL }
+ },
+ { &hf_fix_UnderlyingIssuer,
+ { "UnderlyingIssuer (306)", "fix.UnderlyingIssuer",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingIssuer", HFILL }
+ },
+ { &hf_fix_UnderlyingSecurityDesc,
+ { "UnderlyingSecurityDesc (307)", "fix.UnderlyingSecurityDesc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingSecurityDesc", HFILL }
+ },
+ { &hf_fix_UnderlyingSecurityExchange,
+ { "UnderlyingSecurityExchange (308)", "fix.UnderlyingSecurityExchange",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingSecurityExchange", HFILL }
+ },
+ { &hf_fix_UnderlyingSecurityID,
+ { "UnderlyingSecurityID (309)", "fix.UnderlyingSecurityID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingSecurityID", HFILL }
+ },
+ { &hf_fix_UnderlyingSecurityType,
+ { "UnderlyingSecurityType (310)", "fix.UnderlyingSecurityType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingSecurityType", HFILL }
+ },
+ { &hf_fix_UnderlyingSymbol,
+ { "UnderlyingSymbol (311)", "fix.UnderlyingSymbol",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingSymbol", HFILL }
+ },
+ { &hf_fix_UnderlyingSymbolSfx,
+ { "UnderlyingSymbolSfx (312)", "fix.UnderlyingSymbolSfx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingSymbolSfx", HFILL }
+ },
+ { &hf_fix_UnderlyingMaturityMonthYear,
+ { "UnderlyingMaturityMonthYear (313)", "fix.UnderlyingMaturityMonthYear",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingMaturityMonthYear", HFILL }
+ },
+ { &hf_fix_UnderlyingMaturityDay,
+ { "UnderlyingMaturityDay (314)", "fix.UnderlyingMaturityDay",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingMaturityDay", HFILL }
+ },
+ { &hf_fix_UnderlyingPutOrCall,
+ { "UnderlyingPutOrCall (315)", "fix.UnderlyingPutOrCall",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingPutOrCall", HFILL }
+ },
+ { &hf_fix_UnderlyingStrikePrice,
+ { "UnderlyingStrikePrice (316)", "fix.UnderlyingStrikePrice",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingStrikePrice", HFILL }
+ },
+ { &hf_fix_UnderlyingOptAttribute,
+ { "UnderlyingOptAttribute (317)", "fix.UnderlyingOptAttribute",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingOptAttribute", HFILL }
+ },
+ { &hf_fix_Underlying,
+ { "Underlying (318)", "fix.Underlying",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Underlying", HFILL }
+ },
+ { &hf_fix_RatioQty,
+ { "RatioQty (319)", "fix.RatioQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RatioQty", HFILL }
+ },
+ { &hf_fix_SecurityReqID,
+ { "SecurityReqID (320)", "fix.SecurityReqID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityReqID", HFILL }
+ },
+ { &hf_fix_SecurityRequestType,
+ { "SecurityRequestType (321)", "fix.SecurityRequestType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityRequestType", HFILL }
+ },
+ { &hf_fix_SecurityResponseID,
+ { "SecurityResponseID (322)", "fix.SecurityResponseID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityResponseID", HFILL }
+ },
+ { &hf_fix_SecurityResponseType,
+ { "SecurityResponseType (323)", "fix.SecurityResponseType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityResponseType", HFILL }
+ },
+ { &hf_fix_SecurityStatusReqID,
+ { "SecurityStatusReqID (324)", "fix.SecurityStatusReqID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityStatusReqID", HFILL }
+ },
+ { &hf_fix_UnsolicitedIndicator,
+ { "UnsolicitedIndicator (325)", "fix.UnsolicitedIndicator",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnsolicitedIndicator", HFILL }
+ },
+ { &hf_fix_SecurityTradingStatus,
+ { "SecurityTradingStatus (326)", "fix.SecurityTradingStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityTradingStatus", HFILL }
+ },
+ { &hf_fix_HaltReason,
+ { "HaltReason (327)", "fix.HaltReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "HaltReason", HFILL }
+ },
+ { &hf_fix_InViewOfCommon,
+ { "InViewOfCommon (328)", "fix.InViewOfCommon",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "InViewOfCommon", HFILL }
+ },
+ { &hf_fix_DueToRelated,
+ { "DueToRelated (329)", "fix.DueToRelated",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DueToRelated", HFILL }
+ },
+ { &hf_fix_BuyVolume,
+ { "BuyVolume (330)", "fix.BuyVolume",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BuyVolume", HFILL }
+ },
+ { &hf_fix_SellVolume,
+ { "SellVolume (331)", "fix.SellVolume",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SellVolume", HFILL }
+ },
+ { &hf_fix_HighPx,
+ { "HighPx (332)", "fix.HighPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "HighPx", HFILL }
+ },
+ { &hf_fix_LowPx,
+ { "LowPx (333)", "fix.LowPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LowPx", HFILL }
+ },
+ { &hf_fix_Adjustment,
+ { "Adjustment (334)", "fix.Adjustment",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Adjustment", HFILL }
+ },
+ { &hf_fix_TradSesReqID,
+ { "TradSesReqID (335)", "fix.TradSesReqID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesReqID", HFILL }
+ },
+ { &hf_fix_TradingSessionID,
+ { "TradingSessionID (336)", "fix.TradingSessionID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradingSessionID", HFILL }
+ },
+ { &hf_fix_ContraTrader,
+ { "ContraTrader (337)", "fix.ContraTrader",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ContraTrader", HFILL }
+ },
+ { &hf_fix_TradSesMethod,
+ { "TradSesMethod (338)", "fix.TradSesMethod",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesMethod", HFILL }
+ },
+ { &hf_fix_TradSesMode,
+ { "TradSesMode (339)", "fix.TradSesMode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesMode", HFILL }
+ },
+ { &hf_fix_TradSesStatus,
+ { "TradSesStatus (340)", "fix.TradSesStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesStatus", HFILL }
+ },
+ { &hf_fix_TradSesStartTime,
+ { "TradSesStartTime (341)", "fix.TradSesStartTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesStartTime", HFILL }
+ },
+ { &hf_fix_TradSesOpenTime,
+ { "TradSesOpenTime (342)", "fix.TradSesOpenTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesOpenTime", HFILL }
+ },
+ { &hf_fix_TradSesPreCloseTime,
+ { "TradSesPreCloseTime (343)", "fix.TradSesPreCloseTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesPreCloseTime", HFILL }
+ },
+ { &hf_fix_TradSesCloseTime,
+ { "TradSesCloseTime (344)", "fix.TradSesCloseTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesCloseTime", HFILL }
+ },
+ { &hf_fix_TradSesEndTime,
+ { "TradSesEndTime (345)", "fix.TradSesEndTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesEndTime", HFILL }
+ },
+ { &hf_fix_NumberOfOrders,
+ { "NumberOfOrders (346)", "fix.NumberOfOrders",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NumberOfOrders", HFILL }
+ },
+ { &hf_fix_MessageEncoding,
+ { "MessageEncoding (347)", "fix.MessageEncoding",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MessageEncoding", HFILL }
+ },
+ { &hf_fix_EncodedIssuerLen,
+ { "EncodedIssuerLen (348)", "fix.EncodedIssuerLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedIssuerLen", HFILL }
+ },
+ { &hf_fix_EncodedIssuer,
+ { "EncodedIssuer (349)", "fix.EncodedIssuer",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedIssuer", HFILL }
+ },
+ { &hf_fix_EncodedSecurityDescLen,
+ { "EncodedSecurityDescLen (350)", "fix.EncodedSecurityDescLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedSecurityDescLen", HFILL }
+ },
+ { &hf_fix_EncodedSecurityDesc,
+ { "EncodedSecurityDesc (351)", "fix.EncodedSecurityDesc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedSecurityDesc", HFILL }
+ },
+ { &hf_fix_EncodedListExecInstLen,
+ { "EncodedListExecInstLen (352)", "fix.EncodedListExecInstLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedListExecInstLen", HFILL }
+ },
+ { &hf_fix_EncodedListExecInst,
+ { "EncodedListExecInst (353)", "fix.EncodedListExecInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedListExecInst", HFILL }
+ },
+ { &hf_fix_EncodedTextLen,
+ { "EncodedTextLen (354)", "fix.EncodedTextLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedTextLen", HFILL }
+ },
+ { &hf_fix_EncodedText,
+ { "EncodedText (355)", "fix.EncodedText",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedText", HFILL }
+ },
+ { &hf_fix_EncodedSubjectLen,
+ { "EncodedSubjectLen (356)", "fix.EncodedSubjectLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedSubjectLen", HFILL }
+ },
+ { &hf_fix_EncodedSubject,
+ { "EncodedSubject (357)", "fix.EncodedSubject",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedSubject", HFILL }
+ },
+ { &hf_fix_EncodedHeadlineLen,
+ { "EncodedHeadlineLen (358)", "fix.EncodedHeadlineLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedHeadlineLen", HFILL }
+ },
+ { &hf_fix_EncodedHeadline,
+ { "EncodedHeadline (359)", "fix.EncodedHeadline",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedHeadline", HFILL }
+ },
+ { &hf_fix_EncodedAllocTextLen,
+ { "EncodedAllocTextLen (360)", "fix.EncodedAllocTextLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedAllocTextLen", HFILL }
+ },
+ { &hf_fix_EncodedAllocText,
+ { "EncodedAllocText (361)", "fix.EncodedAllocText",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedAllocText", HFILL }
+ },
+ { &hf_fix_EncodedUnderlyingIssuerLen,
+ { "EncodedUnderlyingIssuerLen (362)", "fix.EncodedUnderlyingIssuerLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedUnderlyingIssuerLen", HFILL }
+ },
+ { &hf_fix_EncodedUnderlyingIssuer,
+ { "EncodedUnderlyingIssuer (363)", "fix.EncodedUnderlyingIssuer",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedUnderlyingIssuer", HFILL }
+ },
+ { &hf_fix_EncodedUnderlyingSecurityDescLen,
+ { "EncodedUnderlyingSecurityDescLen (364)", "fix.EncodedUnderlyingSecurityDescLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedUnderlyingSecurityDescLen", HFILL }
+ },
+ { &hf_fix_EncodedUnderlyingSecurityDesc,
+ { "EncodedUnderlyingSecurityDesc (365)", "fix.EncodedUnderlyingSecurityDesc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedUnderlyingSecurityDesc", HFILL }
+ },
+ { &hf_fix_AllocPrice,
+ { "AllocPrice (366)", "fix.AllocPrice",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocPrice", HFILL }
+ },
+ { &hf_fix_QuoteSetValidUntilTime,
+ { "QuoteSetValidUntilTime (367)", "fix.QuoteSetValidUntilTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteSetValidUntilTime", HFILL }
+ },
+ { &hf_fix_QuoteEntryRejectReason,
+ { "QuoteEntryRejectReason (368)", "fix.QuoteEntryRejectReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteEntryRejectReason", HFILL }
+ },
+ { &hf_fix_LastMsgSeqNumProcessed,
+ { "LastMsgSeqNumProcessed (369)", "fix.LastMsgSeqNumProcessed",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LastMsgSeqNumProcessed", HFILL }
+ },
+ { &hf_fix_OnBehalfOfSendingTime,
+ { "OnBehalfOfSendingTime (370)", "fix.OnBehalfOfSendingTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OnBehalfOfSendingTime", HFILL }
+ },
+ { &hf_fix_RefTagID,
+ { "RefTagID (371)", "fix.RefTagID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RefTagID", HFILL }
+ },
+ { &hf_fix_RefMsgType,
+ { "RefMsgType (372)", "fix.RefMsgType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RefMsgType", HFILL }
+ },
+ { &hf_fix_SessionRejectReason,
+ { "SessionRejectReason (373)", "fix.SessionRejectReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SessionRejectReason", HFILL }
+ },
+ { &hf_fix_BidRequestTransType,
+ { "BidRequestTransType (374)", "fix.BidRequestTransType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidRequestTransType", HFILL }
+ },
+ { &hf_fix_ContraBroker,
+ { "ContraBroker (375)", "fix.ContraBroker",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ContraBroker", HFILL }
+ },
+ { &hf_fix_ComplianceID,
+ { "ComplianceID (376)", "fix.ComplianceID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ComplianceID", HFILL }
+ },
+ { &hf_fix_SolicitedFlag,
+ { "SolicitedFlag (377)", "fix.SolicitedFlag",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SolicitedFlag", HFILL }
+ },
+ { &hf_fix_ExecRestatementReason,
+ { "ExecRestatementReason (378)", "fix.ExecRestatementReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecRestatementReason", HFILL }
+ },
+ { &hf_fix_BusinessRejectRefID,
+ { "BusinessRejectRefID (379)", "fix.BusinessRejectRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BusinessRejectRefID", HFILL }
+ },
+ { &hf_fix_BusinessRejectReason,
+ { "BusinessRejectReason (380)", "fix.BusinessRejectReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BusinessRejectReason", HFILL }
+ },
+ { &hf_fix_GrossTradeAmt,
+ { "GrossTradeAmt (381)", "fix.GrossTradeAmt",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "GrossTradeAmt", HFILL }
+ },
+ { &hf_fix_NoContraBrokers,
+ { "NoContraBrokers (382)", "fix.NoContraBrokers",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoContraBrokers", HFILL }
+ },
+ { &hf_fix_MaxMessageSize,
+ { "MaxMessageSize (383)", "fix.MaxMessageSize",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MaxMessageSize", HFILL }
+ },
+ { &hf_fix_NoMsgTypes,
+ { "NoMsgTypes (384)", "fix.NoMsgTypes",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoMsgTypes", HFILL }
+ },
+ { &hf_fix_MsgDirection,
+ { "MsgDirection (385)", "fix.MsgDirection",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MsgDirection", HFILL }
+ },
+ { &hf_fix_NoTradingSessions,
+ { "NoTradingSessions (386)", "fix.NoTradingSessions",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoTradingSessions", HFILL }
+ },
+ { &hf_fix_TotalVolumeTraded,
+ { "TotalVolumeTraded (387)", "fix.TotalVolumeTraded",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotalVolumeTraded", HFILL }
+ },
+ { &hf_fix_DiscretionInst,
+ { "DiscretionInst (388)", "fix.DiscretionInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DiscretionInst", HFILL }
+ },
+ { &hf_fix_DiscretionOffset,
+ { "DiscretionOffset (389)", "fix.DiscretionOffset",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DiscretionOffset", HFILL }
+ },
+ { &hf_fix_BidID,
+ { "BidID (390)", "fix.BidID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidID", HFILL }
+ },
+ { &hf_fix_ClientBidID,
+ { "ClientBidID (391)", "fix.ClientBidID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ClientBidID", HFILL }
+ },
+ { &hf_fix_ListName,
+ { "ListName (392)", "fix.ListName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ListName", HFILL }
+ },
+ { &hf_fix_TotalNumSecurities,
+ { "TotalNumSecurities (393)", "fix.TotalNumSecurities",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotalNumSecurities", HFILL }
+ },
+ { &hf_fix_BidType,
+ { "BidType (394)", "fix.BidType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidType", HFILL }
+ },
+ { &hf_fix_NumTickets,
+ { "NumTickets (395)", "fix.NumTickets",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NumTickets", HFILL }
+ },
+ { &hf_fix_SideValue1,
+ { "SideValue1 (396)", "fix.SideValue1",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SideValue1", HFILL }
+ },
+ { &hf_fix_SideValue2,
+ { "SideValue2 (397)", "fix.SideValue2",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SideValue2", HFILL }
+ },
+ { &hf_fix_NoBidDescriptors,
+ { "NoBidDescriptors (398)", "fix.NoBidDescriptors",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoBidDescriptors", HFILL }
+ },
+ { &hf_fix_BidDescriptorType,
+ { "BidDescriptorType (399)", "fix.BidDescriptorType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidDescriptorType", HFILL }
+ },
+ { &hf_fix_BidDescriptor,
+ { "BidDescriptor (400)", "fix.BidDescriptor",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidDescriptor", HFILL }
+ },
+ { &hf_fix_SideValueInd,
+ { "SideValueInd (401)", "fix.SideValueInd",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SideValueInd", HFILL }
+ },
+ { &hf_fix_LiquidityPctLow,
+ { "LiquidityPctLow (402)", "fix.LiquidityPctLow",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LiquidityPctLow", HFILL }
+ },
+ { &hf_fix_LiquidityPctHigh,
+ { "LiquidityPctHigh (403)", "fix.LiquidityPctHigh",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LiquidityPctHigh", HFILL }
+ },
+ { &hf_fix_LiquidityValue,
+ { "LiquidityValue (404)", "fix.LiquidityValue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LiquidityValue", HFILL }
+ },
+ { &hf_fix_EFPTrackingError,
+ { "EFPTrackingError (405)", "fix.EFPTrackingError",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EFPTrackingError", HFILL }
+ },
+ { &hf_fix_FairValue,
+ { "FairValue (406)", "fix.FairValue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "FairValue", HFILL }
+ },
+ { &hf_fix_OutsideIndexPct,
+ { "OutsideIndexPct (407)", "fix.OutsideIndexPct",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OutsideIndexPct", HFILL }
+ },
+ { &hf_fix_ValueOfFutures,
+ { "ValueOfFutures (408)", "fix.ValueOfFutures",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ValueOfFutures", HFILL }
+ },
+ { &hf_fix_LiquidityIndType,
+ { "LiquidityIndType (409)", "fix.LiquidityIndType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LiquidityIndType", HFILL }
+ },
+ { &hf_fix_WtAverageLiquidity,
+ { "WtAverageLiquidity (410)", "fix.WtAverageLiquidity",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WtAverageLiquidity", HFILL }
+ },
+ { &hf_fix_ExchangeForPhysical,
+ { "ExchangeForPhysical (411)", "fix.ExchangeForPhysical",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExchangeForPhysical", HFILL }
+ },
+ { &hf_fix_OutMainCntryUIndex,
+ { "OutMainCntryUIndex (412)", "fix.OutMainCntryUIndex",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OutMainCntryUIndex", HFILL }
+ },
+ { &hf_fix_CrossPercent,
+ { "CrossPercent (413)", "fix.CrossPercent",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CrossPercent", HFILL }
+ },
+ { &hf_fix_ProgRptReqs,
+ { "ProgRptReqs (414)", "fix.ProgRptReqs",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ProgRptReqs", HFILL }
+ },
+ { &hf_fix_ProgPeriodInterval,
+ { "ProgPeriodInterval (415)", "fix.ProgPeriodInterval",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ProgPeriodInterval", HFILL }
+ },
+ { &hf_fix_IncTaxInd,
+ { "IncTaxInd (416)", "fix.IncTaxInd",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IncTaxInd", HFILL }
+ },
+ { &hf_fix_NumBidders,
+ { "NumBidders (417)", "fix.NumBidders",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NumBidders", HFILL }
+ },
+ { &hf_fix_TradeType,
+ { "TradeType (418)", "fix.TradeType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeType", HFILL }
+ },
+ { &hf_fix_BasisPxType,
+ { "BasisPxType (419)", "fix.BasisPxType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BasisPxType", HFILL }
+ },
+ { &hf_fix_NoBidComponents,
+ { "NoBidComponents (420)", "fix.NoBidComponents",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoBidComponents", HFILL }
+ },
+ { &hf_fix_Country,
+ { "Country (421)", "fix.Country",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Country", HFILL }
+ },
+ { &hf_fix_TotNoStrikes,
+ { "TotNoStrikes (422)", "fix.TotNoStrikes",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotNoStrikes", HFILL }
+ },
+ { &hf_fix_PriceType,
+ { "PriceType (423)", "fix.PriceType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PriceType", HFILL }
+ },
+ { &hf_fix_DayOrderQty,
+ { "DayOrderQty (424)", "fix.DayOrderQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DayOrderQty", HFILL }
+ },
+ { &hf_fix_DayCumQty,
+ { "DayCumQty (425)", "fix.DayCumQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DayCumQty", HFILL }
+ },
+ { &hf_fix_DayAvgPx,
+ { "DayAvgPx (426)", "fix.DayAvgPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DayAvgPx", HFILL }
+ },
+ { &hf_fix_GTBookingInst,
+ { "GTBookingInst (427)", "fix.GTBookingInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "GTBookingInst", HFILL }
+ },
+ { &hf_fix_NoStrikes,
+ { "NoStrikes (428)", "fix.NoStrikes",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoStrikes", HFILL }
+ },
+ { &hf_fix_ListStatusType,
+ { "ListStatusType (429)", "fix.ListStatusType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ListStatusType", HFILL }
+ },
+ { &hf_fix_NetGrossInd,
+ { "NetGrossInd (430)", "fix.NetGrossInd",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NetGrossInd", HFILL }
+ },
+ { &hf_fix_ListOrderStatus,
+ { "ListOrderStatus (431)", "fix.ListOrderStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ListOrderStatus", HFILL }
+ },
+ { &hf_fix_ExpireDate,
+ { "ExpireDate (432)", "fix.ExpireDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExpireDate", HFILL }
+ },
+ { &hf_fix_ListExecInstType,
+ { "ListExecInstType (433)", "fix.ListExecInstType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ListExecInstType", HFILL }
+ },
+ { &hf_fix_CxlRejResponseTo,
+ { "CxlRejResponseTo (434)", "fix.CxlRejResponseTo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CxlRejResponseTo", HFILL }
+ },
+ { &hf_fix_UnderlyingCouponRate,
+ { "UnderlyingCouponRate (435)", "fix.UnderlyingCouponRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingCouponRate", HFILL }
+ },
+ { &hf_fix_UnderlyingContractMultiplier,
+ { "UnderlyingContractMultiplier (436)", "fix.UnderlyingContractMultiplier",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingContractMultiplier", HFILL }
+ },
+ { &hf_fix_ContraTradeQty,
+ { "ContraTradeQty (437)", "fix.ContraTradeQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ContraTradeQty", HFILL }
+ },
+ { &hf_fix_ContraTradeTime,
+ { "ContraTradeTime (438)", "fix.ContraTradeTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ContraTradeTime", HFILL }
+ },
+ { &hf_fix_ClearingFirm,
+ { "ClearingFirm (439)", "fix.ClearingFirm",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ClearingFirm", HFILL }
+ },
+ { &hf_fix_ClearingAccount,
+ { "ClearingAccount (440)", "fix.ClearingAccount",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ClearingAccount", HFILL }
+ },
+ { &hf_fix_LiquidityNumSecurities,
+ { "LiquidityNumSecurities (441)", "fix.LiquidityNumSecurities",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LiquidityNumSecurities", HFILL }
+ },
+ { &hf_fix_MultiLegReportingType,
+ { "MultiLegReportingType (442)", "fix.MultiLegReportingType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MultiLegReportingType", HFILL }
+ },
+ { &hf_fix_StrikeTime,
+ { "StrikeTime (443)", "fix.StrikeTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "StrikeTime", HFILL }
+ },
+ { &hf_fix_ListStatusText,
+ { "ListStatusText (444)", "fix.ListStatusText",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ListStatusText", HFILL }
+ },
+ { &hf_fix_EncodedListStatusTextLen,
+ { "EncodedListStatusTextLen (445)", "fix.EncodedListStatusTextLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedListStatusTextLen", HFILL }
+ },
+ { &hf_fix_EncodedListStatusText,
+ { "EncodedListStatusText (446)", "fix.EncodedListStatusText",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedListStatusText", HFILL }
+ },
+ { &hf_fix_PartyIDSource,
+ { "PartyIDSource (447)", "fix.PartyIDSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PartyIDSource", HFILL }
+ },
+ { &hf_fix_PartyID,
+ { "PartyID (448)", "fix.PartyID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PartyID", HFILL }
+ },
+ { &hf_fix_TotalVolumeTradedDate,
+ { "TotalVolumeTradedDate (449)", "fix.TotalVolumeTradedDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotalVolumeTradedDate", HFILL }
+ },
+ { &hf_fix_TotalVolumeTradedTime,
+ { "TotalVolumeTradedTime (450)", "fix.TotalVolumeTradedTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotalVolumeTradedTime", HFILL }
+ },
+ { &hf_fix_NetChgPrevDay,
+ { "NetChgPrevDay (451)", "fix.NetChgPrevDay",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NetChgPrevDay", HFILL }
+ },
+ { &hf_fix_PartyRole,
+ { "PartyRole (452)", "fix.PartyRole",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PartyRole", HFILL }
+ },
+ { &hf_fix_NoPartyIDs,
+ { "NoPartyIDs (453)", "fix.NoPartyIDs",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoPartyIDs", HFILL }
+ },
+ { &hf_fix_NoSecurityAltID,
+ { "NoSecurityAltID (454)", "fix.NoSecurityAltID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoSecurityAltID", HFILL }
+ },
+ { &hf_fix_SecurityAltID,
+ { "SecurityAltID (455)", "fix.SecurityAltID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityAltID", HFILL }
+ },
+ { &hf_fix_SecurityAltIDSource,
+ { "SecurityAltIDSource (456)", "fix.SecurityAltIDSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityAltIDSource", HFILL }
+ },
+ { &hf_fix_NoUnderlyingSecurityAltID,
+ { "NoUnderlyingSecurityAltID (457)", "fix.NoUnderlyingSecurityAltID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoUnderlyingSecurityAltID", HFILL }
+ },
+ { &hf_fix_UnderlyingSecurityAltID,
+ { "UnderlyingSecurityAltID (458)", "fix.UnderlyingSecurityAltID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingSecurityAltID", HFILL }
+ },
+ { &hf_fix_UnderlyingSecurityAltIDSource,
+ { "UnderlyingSecurityAltIDSource (459)", "fix.UnderlyingSecurityAltIDSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingSecurityAltIDSource", HFILL }
+ },
+ { &hf_fix_Product,
+ { "Product (460)", "fix.Product",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Product", HFILL }
+ },
+ { &hf_fix_CFICode,
+ { "CFICode (461)", "fix.CFICode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CFICode", HFILL }
+ },
+ { &hf_fix_UnderlyingProduct,
+ { "UnderlyingProduct (462)", "fix.UnderlyingProduct",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingProduct", HFILL }
+ },
+ { &hf_fix_UnderlyingCFICode,
+ { "UnderlyingCFICode (463)", "fix.UnderlyingCFICode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingCFICode", HFILL }
+ },
+ { &hf_fix_TestMessageIndicator,
+ { "TestMessageIndicator (464)", "fix.TestMessageIndicator",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TestMessageIndicator", HFILL }
+ },
+ { &hf_fix_QuantityType,
+ { "QuantityType (465)", "fix.QuantityType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuantityType", HFILL }
+ },
+ { &hf_fix_BookingRefID,
+ { "BookingRefID (466)", "fix.BookingRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BookingRefID", HFILL }
+ },
+ { &hf_fix_IndividualAllocID,
+ { "IndividualAllocID (467)", "fix.IndividualAllocID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "IndividualAllocID", HFILL }
+ },
+ { &hf_fix_RoundingDirection,
+ { "RoundingDirection (468)", "fix.RoundingDirection",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RoundingDirection", HFILL }
+ },
+ { &hf_fix_RoundingModulus,
+ { "RoundingModulus (469)", "fix.RoundingModulus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RoundingModulus", HFILL }
+ },
+ { &hf_fix_CountryOfIssue,
+ { "CountryOfIssue (470)", "fix.CountryOfIssue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CountryOfIssue", HFILL }
+ },
+ { &hf_fix_StateOrProvinceOfIssue,
+ { "StateOrProvinceOfIssue (471)", "fix.StateOrProvinceOfIssue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "StateOrProvinceOfIssue", HFILL }
+ },
+ { &hf_fix_LocaleOfIssue,
+ { "LocaleOfIssue (472)", "fix.LocaleOfIssue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LocaleOfIssue", HFILL }
+ },
+ { &hf_fix_NoRegistDtls,
+ { "NoRegistDtls (473)", "fix.NoRegistDtls",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoRegistDtls", HFILL }
+ },
+ { &hf_fix_MailingDtls,
+ { "MailingDtls (474)", "fix.MailingDtls",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MailingDtls", HFILL }
+ },
+ { &hf_fix_InvestorCountryOfResidence,
+ { "InvestorCountryOfResidence (475)", "fix.InvestorCountryOfResidence",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "InvestorCountryOfResidence", HFILL }
+ },
+ { &hf_fix_PaymentRef,
+ { "PaymentRef (476)", "fix.PaymentRef",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PaymentRef", HFILL }
+ },
+ { &hf_fix_DistribPaymentMethod,
+ { "DistribPaymentMethod (477)", "fix.DistribPaymentMethod",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DistribPaymentMethod", HFILL }
+ },
+ { &hf_fix_CashDistribCurr,
+ { "CashDistribCurr (478)", "fix.CashDistribCurr",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashDistribCurr", HFILL }
+ },
+ { &hf_fix_CommCurrency,
+ { "CommCurrency (479)", "fix.CommCurrency",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CommCurrency", HFILL }
+ },
+ { &hf_fix_CancellationRights,
+ { "CancellationRights (480)", "fix.CancellationRights",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CancellationRights", HFILL }
+ },
+ { &hf_fix_MoneyLaunderingStatus,
+ { "MoneyLaunderingStatus (481)", "fix.MoneyLaunderingStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MoneyLaunderingStatus", HFILL }
+ },
+ { &hf_fix_MailingInst,
+ { "MailingInst (482)", "fix.MailingInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MailingInst", HFILL }
+ },
+ { &hf_fix_TransBkdTime,
+ { "TransBkdTime (483)", "fix.TransBkdTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TransBkdTime", HFILL }
+ },
+ { &hf_fix_ExecPriceType,
+ { "ExecPriceType (484)", "fix.ExecPriceType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecPriceType", HFILL }
+ },
+ { &hf_fix_ExecPriceAdjustment,
+ { "ExecPriceAdjustment (485)", "fix.ExecPriceAdjustment",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecPriceAdjustment", HFILL }
+ },
+ { &hf_fix_DateOfBirth,
+ { "DateOfBirth (486)", "fix.DateOfBirth",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DateOfBirth", HFILL }
+ },
+ { &hf_fix_TradeReportTransType,
+ { "TradeReportTransType (487)", "fix.TradeReportTransType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeReportTransType", HFILL }
+ },
+ { &hf_fix_CardHolderName,
+ { "CardHolderName (488)", "fix.CardHolderName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CardHolderName", HFILL }
+ },
+ { &hf_fix_CardNumber,
+ { "CardNumber (489)", "fix.CardNumber",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CardNumber", HFILL }
+ },
+ { &hf_fix_CardExpDate,
+ { "CardExpDate (490)", "fix.CardExpDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CardExpDate", HFILL }
+ },
+ { &hf_fix_CardIssNo,
+ { "CardIssNo (491)", "fix.CardIssNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CardIssNo", HFILL }
+ },
+ { &hf_fix_PaymentMethod,
+ { "PaymentMethod (492)", "fix.PaymentMethod",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PaymentMethod", HFILL }
+ },
+ { &hf_fix_RegistAcctType,
+ { "RegistAcctType (493)", "fix.RegistAcctType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RegistAcctType", HFILL }
+ },
+ { &hf_fix_Designation,
+ { "Designation (494)", "fix.Designation",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Designation", HFILL }
+ },
+ { &hf_fix_TaxAdvantageType,
+ { "TaxAdvantageType (495)", "fix.TaxAdvantageType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TaxAdvantageType", HFILL }
+ },
+ { &hf_fix_RegistRejReasonText,
+ { "RegistRejReasonText (496)", "fix.RegistRejReasonText",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RegistRejReasonText", HFILL }
+ },
+ { &hf_fix_FundRenewWaiv,
+ { "FundRenewWaiv (497)", "fix.FundRenewWaiv",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "FundRenewWaiv", HFILL }
+ },
+ { &hf_fix_CashDistribAgentName,
+ { "CashDistribAgentName (498)", "fix.CashDistribAgentName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashDistribAgentName", HFILL }
+ },
+ { &hf_fix_CashDistribAgentCode,
+ { "CashDistribAgentCode (499)", "fix.CashDistribAgentCode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashDistribAgentCode", HFILL }
+ },
+ { &hf_fix_CashDistribAgentAcctNumber,
+ { "CashDistribAgentAcctNumber (500)", "fix.CashDistribAgentAcctNumber",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashDistribAgentAcctNumber", HFILL }
+ },
+ { &hf_fix_CashDistribPayRef,
+ { "CashDistribPayRef (501)", "fix.CashDistribPayRef",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashDistribPayRef", HFILL }
+ },
+ { &hf_fix_CashDistribAgentAcctName,
+ { "CashDistribAgentAcctName (502)", "fix.CashDistribAgentAcctName",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashDistribAgentAcctName", HFILL }
+ },
+ { &hf_fix_CardStartDate,
+ { "CardStartDate (503)", "fix.CardStartDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CardStartDate", HFILL }
+ },
+ { &hf_fix_PaymentDate,
+ { "PaymentDate (504)", "fix.PaymentDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PaymentDate", HFILL }
+ },
+ { &hf_fix_PaymentRemitterID,
+ { "PaymentRemitterID (505)", "fix.PaymentRemitterID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PaymentRemitterID", HFILL }
+ },
+ { &hf_fix_RegistStatus,
+ { "RegistStatus (506)", "fix.RegistStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RegistStatus", HFILL }
+ },
+ { &hf_fix_RegistRejReasonCode,
+ { "RegistRejReasonCode (507)", "fix.RegistRejReasonCode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RegistRejReasonCode", HFILL }
+ },
+ { &hf_fix_RegistRefID,
+ { "RegistRefID (508)", "fix.RegistRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RegistRefID", HFILL }
+ },
+ { &hf_fix_RegistDetls,
+ { "RegistDetls (509)", "fix.RegistDetls",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RegistDetls", HFILL }
+ },
+ { &hf_fix_NoDistribInsts,
+ { "NoDistribInsts (510)", "fix.NoDistribInsts",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoDistribInsts", HFILL }
+ },
+ { &hf_fix_RegistEmail,
+ { "RegistEmail (511)", "fix.RegistEmail",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RegistEmail", HFILL }
+ },
+ { &hf_fix_DistribPercentage,
+ { "DistribPercentage (512)", "fix.DistribPercentage",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DistribPercentage", HFILL }
+ },
+ { &hf_fix_RegistID,
+ { "RegistID (513)", "fix.RegistID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RegistID", HFILL }
+ },
+ { &hf_fix_RegistTransType,
+ { "RegistTransType (514)", "fix.RegistTransType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RegistTransType", HFILL }
+ },
+ { &hf_fix_ExecValuationPoint,
+ { "ExecValuationPoint (515)", "fix.ExecValuationPoint",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ExecValuationPoint", HFILL }
+ },
+ { &hf_fix_OrderPercent,
+ { "OrderPercent (516)", "fix.OrderPercent",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrderPercent", HFILL }
+ },
+ { &hf_fix_OwnershipType,
+ { "OwnershipType (517)", "fix.OwnershipType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OwnershipType", HFILL }
+ },
+ { &hf_fix_NoContAmts,
+ { "NoContAmts (518)", "fix.NoContAmts",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoContAmts", HFILL }
+ },
+ { &hf_fix_ContAmtType,
+ { "ContAmtType (519)", "fix.ContAmtType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ContAmtType", HFILL }
+ },
+ { &hf_fix_ContAmtValue,
+ { "ContAmtValue (520)", "fix.ContAmtValue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ContAmtValue", HFILL }
+ },
+ { &hf_fix_ContAmtCurr,
+ { "ContAmtCurr (521)", "fix.ContAmtCurr",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ContAmtCurr", HFILL }
+ },
+ { &hf_fix_OwnerType,
+ { "OwnerType (522)", "fix.OwnerType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OwnerType", HFILL }
+ },
+ { &hf_fix_PartySubID,
+ { "PartySubID (523)", "fix.PartySubID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PartySubID", HFILL }
+ },
+ { &hf_fix_NestedPartyID,
+ { "NestedPartyID (524)", "fix.NestedPartyID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NestedPartyID", HFILL }
+ },
+ { &hf_fix_NestedPartyIDSource,
+ { "NestedPartyIDSource (525)", "fix.NestedPartyIDSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NestedPartyIDSource", HFILL }
+ },
+ { &hf_fix_SecondaryClOrdID,
+ { "SecondaryClOrdID (526)", "fix.SecondaryClOrdID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecondaryClOrdID", HFILL }
+ },
+ { &hf_fix_SecondaryExecID,
+ { "SecondaryExecID (527)", "fix.SecondaryExecID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecondaryExecID", HFILL }
+ },
+ { &hf_fix_OrderCapacity,
+ { "OrderCapacity (528)", "fix.OrderCapacity",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrderCapacity", HFILL }
+ },
+ { &hf_fix_OrderRestrictions,
+ { "OrderRestrictions (529)", "fix.OrderRestrictions",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrderRestrictions", HFILL }
+ },
+ { &hf_fix_MassCancelRequestType,
+ { "MassCancelRequestType (530)", "fix.MassCancelRequestType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MassCancelRequestType", HFILL }
+ },
+ { &hf_fix_MassCancelResponse,
+ { "MassCancelResponse (531)", "fix.MassCancelResponse",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MassCancelResponse", HFILL }
+ },
+ { &hf_fix_MassCancelRejectReason,
+ { "MassCancelRejectReason (532)", "fix.MassCancelRejectReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MassCancelRejectReason", HFILL }
+ },
+ { &hf_fix_TotalAffectedOrders,
+ { "TotalAffectedOrders (533)", "fix.TotalAffectedOrders",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotalAffectedOrders", HFILL }
+ },
+ { &hf_fix_NoAffectedOrders,
+ { "NoAffectedOrders (534)", "fix.NoAffectedOrders",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoAffectedOrders", HFILL }
+ },
+ { &hf_fix_AffectedOrderID,
+ { "AffectedOrderID (535)", "fix.AffectedOrderID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AffectedOrderID", HFILL }
+ },
+ { &hf_fix_AffectedSecondaryOrderID,
+ { "AffectedSecondaryOrderID (536)", "fix.AffectedSecondaryOrderID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AffectedSecondaryOrderID", HFILL }
+ },
+ { &hf_fix_QuoteType,
+ { "QuoteType (537)", "fix.QuoteType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteType", HFILL }
+ },
+ { &hf_fix_NestedPartyRole,
+ { "NestedPartyRole (538)", "fix.NestedPartyRole",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NestedPartyRole", HFILL }
+ },
+ { &hf_fix_NoNestedPartyIDs,
+ { "NoNestedPartyIDs (539)", "fix.NoNestedPartyIDs",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoNestedPartyIDs", HFILL }
+ },
+ { &hf_fix_TotalAccruedInterestAmt,
+ { "TotalAccruedInterestAmt (540)", "fix.TotalAccruedInterestAmt",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotalAccruedInterestAmt", HFILL }
+ },
+ { &hf_fix_MaturityDate,
+ { "MaturityDate (541)", "fix.MaturityDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MaturityDate", HFILL }
+ },
+ { &hf_fix_UnderlyingMaturityDate,
+ { "UnderlyingMaturityDate (542)", "fix.UnderlyingMaturityDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingMaturityDate", HFILL }
+ },
+ { &hf_fix_InstrRegistry,
+ { "InstrRegistry (543)", "fix.InstrRegistry",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "InstrRegistry", HFILL }
+ },
+ { &hf_fix_CashMargin,
+ { "CashMargin (544)", "fix.CashMargin",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CashMargin", HFILL }
+ },
+ { &hf_fix_NestedPartySubID,
+ { "NestedPartySubID (545)", "fix.NestedPartySubID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NestedPartySubID", HFILL }
+ },
+ { &hf_fix_Scope,
+ { "Scope (546)", "fix.Scope",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Scope", HFILL }
+ },
+ { &hf_fix_MDImplicitDelete,
+ { "MDImplicitDelete (547)", "fix.MDImplicitDelete",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MDImplicitDelete", HFILL }
+ },
+ { &hf_fix_CrossID,
+ { "CrossID (548)", "fix.CrossID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CrossID", HFILL }
+ },
+ { &hf_fix_CrossType,
+ { "CrossType (549)", "fix.CrossType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CrossType", HFILL }
+ },
+ { &hf_fix_CrossPrioritization,
+ { "CrossPrioritization (550)", "fix.CrossPrioritization",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CrossPrioritization", HFILL }
+ },
+ { &hf_fix_OrigCrossID,
+ { "OrigCrossID (551)", "fix.OrigCrossID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrigCrossID", HFILL }
+ },
+ { &hf_fix_NoSides,
+ { "NoSides (552)", "fix.NoSides",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoSides", HFILL }
+ },
+ { &hf_fix_Username,
+ { "Username (553)", "fix.Username",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Username", HFILL }
+ },
+ { &hf_fix_Password,
+ { "Password (554)", "fix.Password",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Password", HFILL }
+ },
+ { &hf_fix_NoLegs,
+ { "NoLegs (555)", "fix.NoLegs",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoLegs", HFILL }
+ },
+ { &hf_fix_LegCurrency,
+ { "LegCurrency (556)", "fix.LegCurrency",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegCurrency", HFILL }
+ },
+ { &hf_fix_TotalNumSecurityTypes,
+ { "TotalNumSecurityTypes (557)", "fix.TotalNumSecurityTypes",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TotalNumSecurityTypes", HFILL }
+ },
+ { &hf_fix_NoSecurityTypes,
+ { "NoSecurityTypes (558)", "fix.NoSecurityTypes",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoSecurityTypes", HFILL }
+ },
+ { &hf_fix_SecurityListRequestType,
+ { "SecurityListRequestType (559)", "fix.SecurityListRequestType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityListRequestType", HFILL }
+ },
+ { &hf_fix_SecurityRequestResult,
+ { "SecurityRequestResult (560)", "fix.SecurityRequestResult",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecurityRequestResult", HFILL }
+ },
+ { &hf_fix_RoundLot,
+ { "RoundLot (561)", "fix.RoundLot",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RoundLot", HFILL }
+ },
+ { &hf_fix_MinTradeVol,
+ { "MinTradeVol (562)", "fix.MinTradeVol",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MinTradeVol", HFILL }
+ },
+ { &hf_fix_MultiLegRptTypeReq,
+ { "MultiLegRptTypeReq (563)", "fix.MultiLegRptTypeReq",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MultiLegRptTypeReq", HFILL }
+ },
+ { &hf_fix_LegPositionEffect,
+ { "LegPositionEffect (564)", "fix.LegPositionEffect",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegPositionEffect", HFILL }
+ },
+ { &hf_fix_LegCoveredOrUncovered,
+ { "LegCoveredOrUncovered (565)", "fix.LegCoveredOrUncovered",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegCoveredOrUncovered", HFILL }
+ },
+ { &hf_fix_LegPrice,
+ { "LegPrice (566)", "fix.LegPrice",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegPrice", HFILL }
+ },
+ { &hf_fix_TradSesStatusRejReason,
+ { "TradSesStatusRejReason (567)", "fix.TradSesStatusRejReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradSesStatusRejReason", HFILL }
+ },
+ { &hf_fix_TradeRequestID,
+ { "TradeRequestID (568)", "fix.TradeRequestID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeRequestID", HFILL }
+ },
+ { &hf_fix_TradeRequestType,
+ { "TradeRequestType (569)", "fix.TradeRequestType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeRequestType", HFILL }
+ },
+ { &hf_fix_PreviouslyReported,
+ { "PreviouslyReported (570)", "fix.PreviouslyReported",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PreviouslyReported", HFILL }
+ },
+ { &hf_fix_TradeReportID,
+ { "TradeReportID (571)", "fix.TradeReportID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeReportID", HFILL }
+ },
+ { &hf_fix_TradeReportRefID,
+ { "TradeReportRefID (572)", "fix.TradeReportRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeReportRefID", HFILL }
+ },
+ { &hf_fix_MatchStatus,
+ { "MatchStatus (573)", "fix.MatchStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MatchStatus", HFILL }
+ },
+ { &hf_fix_MatchType,
+ { "MatchType (574)", "fix.MatchType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MatchType", HFILL }
+ },
+ { &hf_fix_OddLot,
+ { "OddLot (575)", "fix.OddLot",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OddLot", HFILL }
+ },
+ { &hf_fix_NoClearingInstructions,
+ { "NoClearingInstructions (576)", "fix.NoClearingInstructions",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoClearingInstructions", HFILL }
+ },
+ { &hf_fix_ClearingInstruction,
+ { "ClearingInstruction (577)", "fix.ClearingInstruction",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ClearingInstruction", HFILL }
+ },
+ { &hf_fix_TradeInputSource,
+ { "TradeInputSource (578)", "fix.TradeInputSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeInputSource", HFILL }
+ },
+ { &hf_fix_TradeInputDevice,
+ { "TradeInputDevice (579)", "fix.TradeInputDevice",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradeInputDevice", HFILL }
+ },
+ { &hf_fix_NoDates,
+ { "NoDates (580)", "fix.NoDates",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoDates", HFILL }
+ },
+ { &hf_fix_AccountType,
+ { "AccountType (581)", "fix.AccountType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AccountType", HFILL }
+ },
+ { &hf_fix_CustOrderCapacity,
+ { "CustOrderCapacity (582)", "fix.CustOrderCapacity",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "CustOrderCapacity", HFILL }
+ },
+ { &hf_fix_ClOrdLinkID,
+ { "ClOrdLinkID (583)", "fix.ClOrdLinkID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ClOrdLinkID", HFILL }
+ },
+ { &hf_fix_MassStatusReqID,
+ { "MassStatusReqID (584)", "fix.MassStatusReqID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MassStatusReqID", HFILL }
+ },
+ { &hf_fix_MassStatusReqType,
+ { "MassStatusReqType (585)", "fix.MassStatusReqType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MassStatusReqType", HFILL }
+ },
+ { &hf_fix_OrigOrdModTime,
+ { "OrigOrdModTime (586)", "fix.OrigOrdModTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OrigOrdModTime", HFILL }
+ },
+ { &hf_fix_LegSettlmntTyp,
+ { "LegSettlmntTyp (587)", "fix.LegSettlmntTyp",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSettlmntTyp", HFILL }
+ },
+ { &hf_fix_LegFutSettDate,
+ { "LegFutSettDate (588)", "fix.LegFutSettDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegFutSettDate", HFILL }
+ },
+ { &hf_fix_DayBookingInst,
+ { "DayBookingInst (589)", "fix.DayBookingInst",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "DayBookingInst", HFILL }
+ },
+ { &hf_fix_BookingUnit,
+ { "BookingUnit (590)", "fix.BookingUnit",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BookingUnit", HFILL }
+ },
+ { &hf_fix_PreallocMethod,
+ { "PreallocMethod (591)", "fix.PreallocMethod",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PreallocMethod", HFILL }
+ },
+ { &hf_fix_UnderlyingCountryOfIssue,
+ { "UnderlyingCountryOfIssue (592)", "fix.UnderlyingCountryOfIssue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingCountryOfIssue", HFILL }
+ },
+ { &hf_fix_UnderlyingStateOrProvinceOfIssue,
+ { "UnderlyingStateOrProvinceOfIssue (593)", "fix.UnderlyingStateOrProvinceOfIssue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingStateOrProvinceOfIssue", HFILL }
+ },
+ { &hf_fix_UnderlyingLocaleOfIssue,
+ { "UnderlyingLocaleOfIssue (594)", "fix.UnderlyingLocaleOfIssue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingLocaleOfIssue", HFILL }
+ },
+ { &hf_fix_UnderlyingInstrRegistry,
+ { "UnderlyingInstrRegistry (595)", "fix.UnderlyingInstrRegistry",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingInstrRegistry", HFILL }
+ },
+ { &hf_fix_LegCountryOfIssue,
+ { "LegCountryOfIssue (596)", "fix.LegCountryOfIssue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegCountryOfIssue", HFILL }
+ },
+ { &hf_fix_LegStateOrProvinceOfIssue,
+ { "LegStateOrProvinceOfIssue (597)", "fix.LegStateOrProvinceOfIssue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegStateOrProvinceOfIssue", HFILL }
+ },
+ { &hf_fix_LegLocaleOfIssue,
+ { "LegLocaleOfIssue (598)", "fix.LegLocaleOfIssue",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegLocaleOfIssue", HFILL }
+ },
+ { &hf_fix_LegInstrRegistry,
+ { "LegInstrRegistry (599)", "fix.LegInstrRegistry",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegInstrRegistry", HFILL }
+ },
+ { &hf_fix_LegSymbol,
+ { "LegSymbol (600)", "fix.LegSymbol",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSymbol", HFILL }
+ },
+ { &hf_fix_LegSymbolSfx,
+ { "LegSymbolSfx (601)", "fix.LegSymbolSfx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSymbolSfx", HFILL }
+ },
+ { &hf_fix_LegSecurityID,
+ { "LegSecurityID (602)", "fix.LegSecurityID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSecurityID", HFILL }
+ },
+ { &hf_fix_LegSecurityIDSource,
+ { "LegSecurityIDSource (603)", "fix.LegSecurityIDSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSecurityIDSource", HFILL }
+ },
+ { &hf_fix_NoLegSecurityAltID,
+ { "NoLegSecurityAltID (604)", "fix.NoLegSecurityAltID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoLegSecurityAltID", HFILL }
+ },
+ { &hf_fix_LegSecurityAltID,
+ { "LegSecurityAltID (605)", "fix.LegSecurityAltID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSecurityAltID", HFILL }
+ },
+ { &hf_fix_LegSecurityAltIDSource,
+ { "LegSecurityAltIDSource (606)", "fix.LegSecurityAltIDSource",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSecurityAltIDSource", HFILL }
+ },
+ { &hf_fix_LegProduct,
+ { "LegProduct (607)", "fix.LegProduct",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegProduct", HFILL }
+ },
+ { &hf_fix_LegCFICode,
+ { "LegCFICode (608)", "fix.LegCFICode",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegCFICode", HFILL }
+ },
+ { &hf_fix_LegSecurityType,
+ { "LegSecurityType (609)", "fix.LegSecurityType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSecurityType", HFILL }
+ },
+ { &hf_fix_LegMaturityMonthYear,
+ { "LegMaturityMonthYear (610)", "fix.LegMaturityMonthYear",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegMaturityMonthYear", HFILL }
+ },
+ { &hf_fix_LegMaturityDate,
+ { "LegMaturityDate (611)", "fix.LegMaturityDate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegMaturityDate", HFILL }
+ },
+ { &hf_fix_LegStrikePrice,
+ { "LegStrikePrice (612)", "fix.LegStrikePrice",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegStrikePrice", HFILL }
+ },
+ { &hf_fix_LegOptAttribute,
+ { "LegOptAttribute (613)", "fix.LegOptAttribute",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegOptAttribute", HFILL }
+ },
+ { &hf_fix_LegContractMultiplier,
+ { "LegContractMultiplier (614)", "fix.LegContractMultiplier",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegContractMultiplier", HFILL }
+ },
+ { &hf_fix_LegCouponRate,
+ { "LegCouponRate (615)", "fix.LegCouponRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegCouponRate", HFILL }
+ },
+ { &hf_fix_LegSecurityExchange,
+ { "LegSecurityExchange (616)", "fix.LegSecurityExchange",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSecurityExchange", HFILL }
+ },
+ { &hf_fix_LegIssuer,
+ { "LegIssuer (617)", "fix.LegIssuer",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegIssuer", HFILL }
+ },
+ { &hf_fix_EncodedLegIssuerLen,
+ { "EncodedLegIssuerLen (618)", "fix.EncodedLegIssuerLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedLegIssuerLen", HFILL }
+ },
+ { &hf_fix_EncodedLegIssuer,
+ { "EncodedLegIssuer (619)", "fix.EncodedLegIssuer",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedLegIssuer", HFILL }
+ },
+ { &hf_fix_LegSecurityDesc,
+ { "LegSecurityDesc (620)", "fix.LegSecurityDesc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSecurityDesc", HFILL }
+ },
+ { &hf_fix_EncodedLegSecurityDescLen,
+ { "EncodedLegSecurityDescLen (621)", "fix.EncodedLegSecurityDescLen",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedLegSecurityDescLen", HFILL }
+ },
+ { &hf_fix_EncodedLegSecurityDesc,
+ { "EncodedLegSecurityDesc (622)", "fix.EncodedLegSecurityDesc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "EncodedLegSecurityDesc", HFILL }
+ },
+ { &hf_fix_LegRatioQty,
+ { "LegRatioQty (623)", "fix.LegRatioQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegRatioQty", HFILL }
+ },
+ { &hf_fix_LegSide,
+ { "LegSide (624)", "fix.LegSide",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegSide", HFILL }
+ },
+ { &hf_fix_TradingSessionSubID,
+ { "TradingSessionSubID (625)", "fix.TradingSessionSubID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "TradingSessionSubID", HFILL }
+ },
+ { &hf_fix_AllocType,
+ { "AllocType (626)", "fix.AllocType",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "AllocType", HFILL }
+ },
+ { &hf_fix_NoHops,
+ { "NoHops (627)", "fix.NoHops",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "NoHops", HFILL }
+ },
+ { &hf_fix_HopCompID,
+ { "HopCompID (628)", "fix.HopCompID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "HopCompID", HFILL }
+ },
+ { &hf_fix_HopSendingTime,
+ { "HopSendingTime (629)", "fix.HopSendingTime",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "HopSendingTime", HFILL }
+ },
+ { &hf_fix_HopRefID,
+ { "HopRefID (630)", "fix.HopRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "HopRefID", HFILL }
+ },
+ { &hf_fix_MidPx,
+ { "MidPx (631)", "fix.MidPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MidPx", HFILL }
+ },
+ { &hf_fix_BidYield,
+ { "BidYield (632)", "fix.BidYield",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidYield", HFILL }
+ },
+ { &hf_fix_MidYield,
+ { "MidYield (633)", "fix.MidYield",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MidYield", HFILL }
+ },
+ { &hf_fix_OfferYield,
+ { "OfferYield (634)", "fix.OfferYield",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OfferYield", HFILL }
+ },
+ { &hf_fix_ClearingFeeIndicator,
+ { "ClearingFeeIndicator (635)", "fix.ClearingFeeIndicator",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ClearingFeeIndicator", HFILL }
+ },
+ { &hf_fix_WorkingIndicator,
+ { "WorkingIndicator (636)", "fix.WorkingIndicator",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WorkingIndicator", HFILL }
+ },
+ { &hf_fix_LegLastPx,
+ { "LegLastPx (637)", "fix.LegLastPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegLastPx", HFILL }
+ },
+ { &hf_fix_PriorityIndicator,
+ { "PriorityIndicator (638)", "fix.PriorityIndicator",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PriorityIndicator", HFILL }
+ },
+ { &hf_fix_PriceImprovement,
+ { "PriceImprovement (639)", "fix.PriceImprovement",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "PriceImprovement", HFILL }
+ },
+ { &hf_fix_Price2,
+ { "Price2 (640)", "fix.Price2",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Price2", HFILL }
+ },
+ { &hf_fix_LastForwardPoints2,
+ { "LastForwardPoints2 (641)", "fix.LastForwardPoints2",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LastForwardPoints2", HFILL }
+ },
+ { &hf_fix_BidForwardPoints2,
+ { "BidForwardPoints2 (642)", "fix.BidForwardPoints2",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "BidForwardPoints2", HFILL }
+ },
+ { &hf_fix_OfferForwardPoints2,
+ { "OfferForwardPoints2 (643)", "fix.OfferForwardPoints2",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "OfferForwardPoints2", HFILL }
+ },
+ { &hf_fix_RFQReqID,
+ { "RFQReqID (644)", "fix.RFQReqID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RFQReqID", HFILL }
+ },
+ { &hf_fix_MktBidPx,
+ { "MktBidPx (645)", "fix.MktBidPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MktBidPx", HFILL }
+ },
+ { &hf_fix_MktOfferPx,
+ { "MktOfferPx (646)", "fix.MktOfferPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MktOfferPx", HFILL }
+ },
+ { &hf_fix_MinBidSize,
+ { "MinBidSize (647)", "fix.MinBidSize",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MinBidSize", HFILL }
+ },
+ { &hf_fix_MinOfferSize,
+ { "MinOfferSize (648)", "fix.MinOfferSize",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MinOfferSize", HFILL }
+ },
+ { &hf_fix_QuoteStatusReqID,
+ { "QuoteStatusReqID (649)", "fix.QuoteStatusReqID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteStatusReqID", HFILL }
+ },
+ { &hf_fix_LegalConfirm,
+ { "LegalConfirm (650)", "fix.LegalConfirm",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegalConfirm", HFILL }
+ },
+ { &hf_fix_UnderlyingLastPx,
+ { "UnderlyingLastPx (651)", "fix.UnderlyingLastPx",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingLastPx", HFILL }
+ },
+ { &hf_fix_UnderlyingLastQty,
+ { "UnderlyingLastQty (652)", "fix.UnderlyingLastQty",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UnderlyingLastQty", HFILL }
+ },
+ { &hf_fix_SecDefStatus,
+ { "SecDefStatus (653)", "fix.SecDefStatus",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SecDefStatus", HFILL }
+ },
+ { &hf_fix_LegRefID,
+ { "LegRefID (654)", "fix.LegRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "LegRefID", HFILL }
+ },
+ { &hf_fix_ContraLegRefID,
+ { "ContraLegRefID (655)", "fix.ContraLegRefID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "ContraLegRefID", HFILL }
+ },
+ { &hf_fix_SettlCurrBidFxRate,
+ { "SettlCurrBidFxRate (656)", "fix.SettlCurrBidFxRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlCurrBidFxRate", HFILL }
+ },
+ { &hf_fix_SettlCurrOfferFxRate,
+ { "SettlCurrOfferFxRate (657)", "fix.SettlCurrOfferFxRate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SettlCurrOfferFxRate", HFILL }
+ },
+ { &hf_fix_QuoteRequestRejectReason,
+ { "QuoteRequestRejectReason (658)", "fix.QuoteRequestRejectReason",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "QuoteRequestRejectReason", HFILL }
+ },
+ { &hf_fix_SideComplianceID,
+ { "SideComplianceID (659)", "fix.SideComplianceID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SideComplianceID", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fix,
+ };
+
+ /* register re-init routine */
+ register_init_routine(&dissect_fix_init);
+
+ /* Register the protocol name and description */
+ proto_fix = proto_register_protocol("Financial Information eXchange Protocol",
+ "FIX", "fix");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fix, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_fix(void)
+{
+ /*
+ * The first time the function is called let the tcp dissector
+ * know that we're interested in traffic
+ */
+ heur_dissector_add("tcp", dissect_fix, proto_fix);
+}
+
diff --git a/epan/dissectors/packet-fr.c b/epan/dissectors/packet-fr.c
new file mode 100644
index 0000000000..bb99dd18dc
--- /dev/null
+++ b/epan/dissectors/packet-fr.c
@@ -0,0 +1,740 @@
+/* packet-fr.c
+ * Routines for Frame Relay dissection
+ *
+ * Copyright 2001, Paul Ionescu <paul@acorp.ro>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * References:
+ *
+ * http://www.protocols.com/pbook/frame.htm
+ * http://www.mplsforum.org/frame/Approved/FRF.3/FRF.3.2.pdf
+ * ITU Recommendations Q.922 and Q.933
+ * RFC-1490
+ * RFC-2427
+ * Cisco encapsulation
+ * http://www.trillium.com/assets/legacyframe/white_paper/8771019.pdf
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "packet-llc.h"
+#include "packet-chdlc.h"
+#include "xdlc.h"
+#include "etypes.h"
+#include "oui.h"
+#include "nlpid.h"
+#include "greproto.h"
+
+/*
+ * Bits in the address field.
+ */
+#define FRELAY_EA 0x01 /* Address field extension bit */
+
+#define FRELAY_UPPER_DLCI 0xFC /* Upper DLCI */
+#define FRELAY_CR 0x02 /* Command/response bit in first octet */
+
+#define FRELAY_SECOND_DLCI 0xF0 /* DLCI bits in FECN/BECN/DE octet */
+#define FRELAY_FECN 0x08 /* Forward Explicit Congestion Notification */
+#define FRELAY_BECN 0x04 /* Backward Explicit Congestion Notification */
+#define FRELAY_DE 0x02 /* Discard Eligibility */
+
+#define FRELAY_THIRD_DLCI 0xFE /* DLCI bits in third octet, if any */
+
+#define FRELAY_LOWER_DLCI 0xFC /* Lower DLCI */
+#define FRELAY_DC 0x02 /* DLCI or DL-CORE control indicator in last octet */
+
+#define FROM_DCE 0x80 /* for direction setting */
+
+static gint proto_fr = -1;
+static gint ett_fr = -1;
+static gint ett_fr_address = -1;
+static gint ett_fr_control = -1;
+static gint hf_fr_ea = -1;
+static gint hf_fr_upper_dlci = -1;
+static gint hf_fr_cr = -1;
+static gint hf_fr_second_dlci = -1;
+static gint hf_fr_fecn = -1;
+static gint hf_fr_becn = -1;
+static gint hf_fr_de = -1;
+static gint hf_fr_third_dlci = -1;
+static gint hf_fr_dlcore_control = -1;
+static gint hf_fr_lower_dlci = -1;
+static gint hf_fr_dc = -1;
+static gint hf_fr_dlci = -1;
+static gint hf_fr_control = -1;
+static gint hf_fr_n_r = -1;
+static gint hf_fr_n_s = -1;
+static gint hf_fr_p = -1;
+static gint hf_fr_p_ext = -1;
+static gint hf_fr_f = -1;
+static gint hf_fr_f_ext = -1;
+static gint hf_fr_s_ftype = -1;
+static gint hf_fr_u_modifier_cmd = -1;
+static gint hf_fr_u_modifier_resp = -1;
+static gint hf_fr_ftype_i = -1;
+static gint hf_fr_ftype_s_u = -1;
+static gint hf_fr_ftype_s_u_ext = -1;
+static gint hf_fr_nlpid = -1;
+static gint hf_fr_oui = -1;
+static gint hf_fr_pid = -1;
+static gint hf_fr_snaptype = -1;
+static gint hf_fr_chdlctype = -1;
+
+static dissector_handle_t eth_handle;
+static dissector_handle_t gprs_ns_handle;
+static dissector_handle_t data_handle;
+
+static dissector_table_t osinl_subdissector_table;
+
+/*
+ * Encapsulation type.
+ * XXX - this should be per-DLCI as well.
+ */
+#define FRF_3_2 0 /* FRF 3.2 or Cisco HDLC */
+#define GPRS_NS 1 /* GPRS Network Services (3GPP TS 08.16) */
+#define RAW_ETHER 2 /* Raw Ethernet */
+
+static gint fr_encap = FRF_3_2;
+
+static const true_false_string cmd_string = {
+ "Command",
+ "Response"
+ };
+static const true_false_string ctrl_string = {
+ "DLCI Address",
+ "Control"
+ };
+static const true_false_string ea_string = {
+ "Last Octet",
+ "More Follows"
+ };
+
+/*
+ * This isn't the same as "nlpid_vals[]"; 0x08 is Q.933, not Q.931,
+ * and 0x09 is LMI, not Q.2931, and we assume that it's an initial
+ * protocol identifier, so 0x01 is T.70, not X.29.
+ */
+static const value_string fr_nlpid_vals[] = {
+ { NLPID_NULL, "NULL" },
+ { NLPID_IPI_T_70, "T.70" }, /* XXX - IPI, or SPI? */
+ { NLPID_X_633, "X.633" },
+ { NLPID_Q_931, "Q.933" },
+ { NLPID_LMI, "LMI" },
+ { NLPID_Q_2119, "Q.2119" },
+ { NLPID_SNAP, "SNAP" },
+ { NLPID_ISO8473_CLNP, "CLNP" },
+ { NLPID_ISO9542_ESIS, "ESIS" },
+ { NLPID_ISO10589_ISIS, "ISIS" },
+ { NLPID_ISO10747_IDRP, "IDRP" },
+ { NLPID_ISO9542X25_ESIS, "ESIS (X.25)" },
+ { NLPID_ISO10030, "ISO 10030" },
+ { NLPID_ISO11577, "ISO 11577" },
+ { NLPID_COMPRESSED, "Data compression protocol" },
+ { NLPID_IP, "IP" },
+ { NLPID_IP6, "IPv6" },
+ { NLPID_PPP, "PPP" },
+ { 0, NULL },
+};
+
+static dissector_table_t fr_subdissector_table;
+static dissector_table_t fr_osinl_subdissector_table;
+
+static void dissect_fr_nlpid(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_item *ti,
+ proto_tree *fr_tree, guint8 fr_ctrl);
+static void dissect_lapf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static void dissect_fr_xid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/* Used only for U frames */
+static const xdlc_cf_items fr_cf_items = {
+ NULL,
+ NULL,
+ &hf_fr_p,
+ &hf_fr_f,
+ NULL,
+ &hf_fr_u_modifier_cmd,
+ &hf_fr_u_modifier_resp,
+ NULL,
+ &hf_fr_ftype_s_u
+};
+
+/* Used only for I and S frames */
+static const xdlc_cf_items fr_cf_items_ext = {
+ &hf_fr_n_r,
+ &hf_fr_n_s,
+ &hf_fr_p_ext,
+ &hf_fr_f_ext,
+ &hf_fr_s_ftype,
+ NULL,
+ NULL,
+ &hf_fr_ftype_i,
+ &hf_fr_ftype_s_u_ext
+};
+
+static void
+dissect_fr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean has_direction)
+{
+ int offset = 0;
+ proto_item *ti = NULL;
+ proto_tree *fr_tree = NULL;
+ proto_item *octet_item = NULL;
+ proto_tree *octet_tree = NULL;
+ guint8 fr_octet;
+ int is_response = FALSE;
+ guint32 address;
+ guint8 fr_ctrl;
+ guint16 fr_type;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FR");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (has_direction) {
+ if (pinfo->pseudo_header->x25.flags & FROM_DCE) {
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
+ } else {
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
+ }
+ }
+
+ /*
+ * OK, fetch the address field - keep going until we get an EA bit.
+ */
+ fr_octet = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_fr, tvb, 0, -1, "Frame Relay");
+ fr_tree = proto_item_add_subtree(ti, ett_fr);
+ }
+ if (fr_octet & FRELAY_EA) {
+ /*
+ * Bogus! There should be at least 2 octets.
+ * XXX - is this FRF.12 frame relay fragmentation? If so, we
+ * should dissect it as such, if possible.
+ */
+ address = 0;
+ if (tree) {
+ proto_tree_add_text(fr_tree, tvb, offset, 1,
+ "Bogus 1-octet address field");
+ offset++;
+ }
+ } else {
+ /*
+ * The first octet contains the upper 6 bits of the DLCI, as well
+ * as the C/R bit.
+ */
+ address = (fr_octet & FRELAY_UPPER_DLCI) >> 2;
+ is_response = (fr_octet & FRELAY_CR);
+ if (tree) {
+ octet_item = proto_tree_add_text(fr_tree, tvb, offset, 1,
+ "First address octet: 0x%02x", fr_octet);
+ octet_tree = proto_item_add_subtree(octet_item, ett_fr_address);
+ proto_tree_add_uint(octet_tree, hf_fr_upper_dlci, tvb, offset, 1, fr_octet);
+ proto_tree_add_boolean(octet_tree, hf_fr_cr, tvb, offset, 1, fr_octet);
+ proto_tree_add_boolean(octet_tree, hf_fr_ea, tvb, offset, 1, fr_octet);
+ }
+ offset++;
+
+ /*
+ * The second octet contains 4 more bits of DLCI, as well as FECN,
+ * BECN, and DE.
+ */
+ fr_octet = tvb_get_guint8(tvb, offset);
+ address = (address << 4) | ((fr_octet & FRELAY_SECOND_DLCI) >> 4);
+ if (tree) {
+ octet_item = proto_tree_add_text(fr_tree, tvb, offset, 1,
+ "Second address octet: 0x%02x",
+ fr_octet);
+ octet_tree = proto_item_add_subtree(octet_item, ett_fr_address);
+ proto_tree_add_uint(octet_tree, hf_fr_second_dlci, tvb, offset, 1, fr_octet);
+ proto_tree_add_boolean(octet_tree, hf_fr_fecn, tvb, 0, offset, fr_octet);
+ proto_tree_add_boolean(octet_tree, hf_fr_becn, tvb, 0, offset, fr_octet);
+ proto_tree_add_boolean(octet_tree, hf_fr_de, tvb, 0, offset, fr_octet);
+ proto_tree_add_boolean(octet_tree, hf_fr_ea, tvb, offset, 1, fr_octet);
+ }
+ offset++;
+
+ if (!(fr_octet & FRELAY_EA)) {
+ /*
+ * We have 3 or more address octets.
+ *
+ * The third octet contains 7 more bits of DLCI if EA isn't set,
+ * and lower DLCI or DL-CORE control plus the DLCI or DL-CORE
+ * control indicator flag if EA is set.
+ */
+ fr_octet = tvb_get_guint8(tvb, offset);
+ if (!(fr_octet & FRELAY_EA)) {
+ /*
+ * 7 more bits of DLCI.
+ */
+ address = (address << 7) | ((fr_octet & FRELAY_THIRD_DLCI) >> 1);
+ if (tree) {
+ octet_item = proto_tree_add_text(fr_tree, tvb, offset, 1,
+ "Third address octet: 0x%02x",
+ fr_octet);
+ octet_tree = proto_item_add_subtree(octet_item, ett_fr_address);
+ proto_tree_add_uint(octet_tree, hf_fr_third_dlci, tvb, offset, 1, fr_octet);
+ proto_tree_add_boolean(octet_tree, hf_fr_ea, tvb, offset, 1, fr_octet);
+ }
+ offset++;
+ fr_octet = tvb_get_guint8(tvb, offset);
+ while (!(fr_octet & FRELAY_EA)) {
+ /*
+ * Bogus! More than 4 octets of address.
+ */
+ if (tree) {
+ proto_tree_add_text(fr_tree, tvb, offset, 1,
+ "Bogus extra address octet");
+ }
+ offset++;
+ fr_octet = tvb_get_guint8(tvb, offset);
+ }
+ }
+ if (tree) {
+ octet_item = proto_tree_add_text(fr_tree, tvb, offset, 1,
+ "Final address octet: 0x%02x",
+ fr_octet);
+ octet_tree = proto_item_add_subtree(octet_item, ett_fr_address);
+ }
+
+ /*
+ * Last octet - contains lower DLCI or DL-CORE control, DLCI or
+ * DL-CORE control indicator flag.
+ */
+ if (fr_octet & FRELAY_DC) {
+ /*
+ * DL-CORE.
+ */
+ proto_tree_add_uint(octet_tree, hf_fr_dlcore_control, tvb, offset, 1, fr_octet);
+ } else {
+ /*
+ * Last 6 bits of DLCI.
+ */
+ address = (address << 6) | ((fr_octet & FRELAY_LOWER_DLCI) >> 2);
+ proto_tree_add_uint(octet_tree, hf_fr_lower_dlci, tvb, offset, 1, fr_octet);
+ }
+ proto_tree_add_boolean(octet_tree, hf_fr_dc, tvb, offset, 1, fr_octet);
+ proto_tree_add_boolean(octet_tree, hf_fr_ea, tvb, offset, 1, fr_octet);
+ }
+ }
+ if (tree) {
+ /* Put the full DLCI into the protocol tree. */
+ proto_tree_add_uint(fr_tree, hf_fr_dlci, tvb, 0, offset, address);
+ }
+
+ pinfo->ctype = CT_DLCI;
+ pinfo->circuit_id = address;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "DLCI %u", address);
+
+ switch (fr_encap) {
+
+ case FRF_3_2:
+ fr_ctrl = tvb_get_guint8(tvb, offset);
+ if (fr_ctrl == XDLC_U) {
+ dissect_xdlc_control(tvb, offset, pinfo, fr_tree, hf_fr_control,
+ ett_fr_control, &fr_cf_items, &fr_cf_items_ext,
+ NULL, NULL, is_response, TRUE, TRUE);
+ offset++;
+
+ /*
+ * XXX - treat DLCI 0 specially? On DLCI 0, an NLPID of 0x08
+ * means Q.933, but on other circuits it could be the "for
+ * protocols which do not have an NLPID assigned or do not
+ * have a SNAP encapsulation" stuff from RFC 2427.
+ */
+ dissect_fr_nlpid(tvb, offset, pinfo, tree, ti, fr_tree, fr_ctrl);
+ } else {
+ if (address == 0) {
+ /*
+ * This must be some sort of LAPF on DLCI 0 for SVC
+ * because DLCI 0 is reserved for LMI and SVC signaling
+ * encapsulated in LAPF, and LMI is transmitted in
+ * unnumbered information (03), so this must be LAPF
+ * (guessing).
+ *
+ * XXX - but what is it? Is Q.933 carried inside UI
+ * frames or other types of frames or both?
+ */
+ dissect_xdlc_control(tvb, offset, pinfo, fr_tree,
+ hf_fr_control, ett_fr_control,
+ &fr_cf_items, &fr_cf_items_ext,
+ NULL, NULL, is_response, TRUE, TRUE);
+ dissect_lapf(tvb_new_subset(tvb,offset,-1,-1),pinfo,tree);
+ return;
+ }
+ if (fr_ctrl == (XDLC_U|XDLC_XID)) {
+ dissect_xdlc_control(tvb, offset, pinfo, fr_tree,
+ hf_fr_control, ett_fr_control,
+ &fr_cf_items, &fr_cf_items_ext,
+ NULL, NULL, is_response, TRUE, TRUE);
+ dissect_fr_xid(tvb_new_subset(tvb,offset,-1,-1),pinfo,tree);
+ return;
+ }
+
+ /*
+ * If the data does not start with unnumbered information (03) and
+ * the DLCI# is not 0, then there may be Cisco Frame Relay encapsulation.
+ */
+ fr_type = tvb_get_ntohs(tvb, offset);
+ if (ti != NULL) {
+ /* Include the Cisco HDLC type in the top-level protocol
+ tree item. */
+ proto_item_set_end(ti, tvb, offset+2);
+ }
+ chdlctype(fr_type, tvb, offset+2, pinfo, tree, fr_tree, hf_fr_chdlctype);
+ }
+ break;
+
+ case GPRS_NS:
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (address != 0)
+ call_dissector(gprs_ns_handle, next_tvb, pinfo, tree);
+ else
+ dissect_lapf(next_tvb, pinfo, tree);
+ break;
+
+ case RAW_ETHER:
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (address != 0)
+ call_dissector(eth_handle, next_tvb, pinfo, tree);
+ else
+ dissect_lapf(next_tvb, pinfo, tree);
+ break;
+ }
+}
+
+static void
+dissect_fr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_fr_common(tvb, pinfo, tree, FALSE);
+}
+
+static void
+dissect_fr_phdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_fr_common(tvb, pinfo, tree, TRUE);
+}
+
+static void dissect_fr_uncompressed(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_item *ti = NULL;
+ proto_tree *fr_tree = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FR");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_fr, tvb, 0, -1, "Frame Relay");
+ fr_tree = proto_item_add_subtree(ti, ett_fr);
+ }
+ dissect_fr_nlpid(tvb, 0, pinfo, tree, ti, fr_tree, XDLC_U);
+}
+
+static void dissect_fr_nlpid(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_item *ti,
+ proto_tree *fr_tree, guint8 fr_ctrl)
+{
+ guint8 fr_nlpid;
+ tvbuff_t *next_tvb;
+
+ /*
+ * Tentatively set the Frame Relay item not to include the NLPID,
+ * as OSI network layer protocols consider it to be part of
+ * the OSI PDU.
+ */
+ proto_item_set_end(ti, tvb, offset);
+ fr_nlpid = tvb_get_guint8 (tvb,offset);
+ if (fr_nlpid == 0) {
+ if (tree)
+ proto_tree_add_text(fr_tree, tvb, offset, 1, "Padding");
+ offset++;
+ if (ti != NULL) {
+ /* Include the padding in the top-level protocol tree item. */
+ proto_item_set_end(ti, tvb, offset);
+ }
+ fr_nlpid=tvb_get_guint8( tvb,offset);
+ }
+
+ /*
+ * OSI network layer protocols consider the NLPID to be part
+ * of the frame, so we'll pass it as part of the payload and,
+ * if the protocol is one of those, add it as a hidden item here.
+ * We check both the generic OSI NLPID dissector table and
+ * the Frame Relay OSI NLPID dissector table - the latter is for
+ * NLPID's such as 0x08, which is Q.933 in Frame Relay but
+ * other protocols (e.g., Q.931) on other network layers.
+ *
+ * "OSI network layer protocols" includes Q.933.
+ *
+ * XXX - note that an NLPID of 0x08 for Q.933 could either be a
+ * Q.933 signaling message or a message for a protocol
+ * identified by a 2-octet layer 2 protocol type and a
+ * 2-octet layer 3 protocol type, those protocol type
+ * octets having the values from octets 6, 6a, 7, and 7a
+ * of a Q.931 low layer compatibility information element
+ * (section 4.5.19 of Q.931; Q.933 says they have the values
+ * from a Q.933 low layer compatibility information element,
+ * but Q.933 low layer compatibility information elements
+ * don't have protocol values in them).
+ *
+ * Assuming that, as Q.933 seems to imply, that Q.933 messages
+ * look just like Q.931 messages except where it explicitly
+ * says they differ, then the octet after the NLPID would,
+ * in a Q.933 message, have its upper 4 bits zero (that's
+ * the length of the call reference value, in Q.931, and
+ * is limited to 15 or fewer octets). As appears to be the case,
+ * octet 6 of a Q.931 low layer compatibility element has the
+ * 0x40 bit set, so you can distinguish between a Q.933
+ * message and an encapsulated packet by checking whether
+ * the upper 4 bits of the octet after the NLPID are zero.
+ *
+ * Either that, or it's Q.933 iff the DLCI is 0.
+ */
+ next_tvb = tvb_new_subset(tvb,offset,-1,-1);
+ if (dissector_try_port(osinl_subdissector_table, fr_nlpid, next_tvb,
+ pinfo, tree) ||
+ dissector_try_port(fr_osinl_subdissector_table, fr_nlpid, next_tvb,
+ pinfo, tree)) {
+ /*
+ * Yes, we got a match. Add the NLPID as a hidden item,
+ * so you can, at least, filter on it.
+ */
+ if (tree)
+ proto_tree_add_uint_hidden(fr_tree, hf_fr_nlpid,
+ tvb, offset, 1, fr_nlpid );
+ return;
+ }
+
+ /*
+ * All other protocols don't.
+ *
+ * XXX - what about Cisco/Gang-of-Four LMI? Is the 0x09 considered
+ * to be part of the LMI PDU?
+ */
+ if (tree)
+ proto_tree_add_uint(fr_tree, hf_fr_nlpid, tvb, offset, 1, fr_nlpid );
+ offset++;
+
+ switch (fr_nlpid) {
+
+ case NLPID_SNAP:
+ if (ti != NULL) {
+ /* Include the NLPID and SNAP header in the top-level
+ protocol tree item. */
+ proto_item_set_end(ti, tvb, offset+5);
+ }
+ dissect_snap(tvb, offset, pinfo, tree, fr_tree, fr_ctrl,
+ hf_fr_oui, hf_fr_snaptype, hf_fr_pid, 0);
+ return;
+
+ default:
+ if (ti != NULL) {
+ /* Include the NLPID in the top-level protocol tree item. */
+ proto_item_set_end(ti, tvb, offset);
+ }
+ next_tvb = tvb_new_subset(tvb,offset,-1,-1);
+ if (!dissector_try_port(fr_subdissector_table,fr_nlpid,
+ next_tvb, pinfo, tree))
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ break;
+ }
+}
+
+static void dissect_lapf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, 0, 0, "Frame relay lapf not yet implemented");
+ call_dissector(data_handle,tvb_new_subset(tvb,0,-1,-1),pinfo,tree);
+}
+static void dissect_fr_xid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, 0, 0, "Frame relay xid not yet implemented");
+ call_dissector(data_handle,tvb_new_subset(tvb,0,-1,-1),pinfo,tree);
+}
+
+/* Register the protocol with Ethereal */
+void proto_register_fr(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_fr_ea, {
+ "EA", "fr.ea", FT_BOOLEAN, 8, TFS(&ea_string),
+ FRELAY_EA, "Extended Address", HFILL }},
+ { &hf_fr_upper_dlci, {
+ "Upper DLCI", "fr.upper_dlci", FT_UINT8, BASE_HEX,
+ NULL, FRELAY_UPPER_DLCI, "Upper bits of DLCI", HFILL }},
+ { &hf_fr_cr, {
+ "CR", "fr.cr", FT_BOOLEAN, 8, TFS(&cmd_string),
+ FRELAY_CR, "Command/Response", HFILL }},
+ { &hf_fr_second_dlci, {
+ "Second DLCI", "fr.second_dlci", FT_UINT8, BASE_HEX,
+ NULL, FRELAY_SECOND_DLCI, "Bits below upper bits of DLCI", HFILL }},
+ { &hf_fr_fecn, {
+ "FECN", "fr.fecn", FT_BOOLEAN, 8,
+ NULL, FRELAY_FECN, "Forward Explicit Congestion Notification", HFILL }},
+ { &hf_fr_becn, {
+ "BECN", "fr.becn", FT_BOOLEAN, 8,
+ NULL, FRELAY_BECN, "Backward Explicit Congestion Notification", HFILL }},
+ { &hf_fr_de, {
+ "DE", "fr.de", FT_BOOLEAN, 8,
+ NULL, FRELAY_DE, "Discard Eligibility", HFILL }},
+ { &hf_fr_third_dlci, {
+ "Third DLCI", "fr.third_dlci", FT_UINT8, BASE_HEX,
+ NULL, FRELAY_THIRD_DLCI, "Additional bits of DLCI", HFILL }},
+ { &hf_fr_dlcore_control, {
+ "DL-CORE Control", "fr.dlcore_control", FT_UINT8, BASE_HEX,
+ NULL, FRELAY_LOWER_DLCI, "DL-Core control bits", HFILL }},
+ { &hf_fr_lower_dlci, {
+ "Lower DLCI", "fr.lower_dlci", FT_UINT8, BASE_HEX,
+ NULL, FRELAY_LOWER_DLCI, "Lower bits of DLCI", HFILL }},
+ { &hf_fr_dc, {
+ "DC", "fr.dc", FT_BOOLEAN, 16, TFS(&ctrl_string),
+ FRELAY_CR, "Address/Control", HFILL }},
+ { &hf_fr_dlci, {
+ "DLCI", "fr.dlci", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Data-Link Connection Identifier", HFILL }},
+ { &hf_fr_control, {
+ "Control Field", "fr.control", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Control field", HFILL }},
+ { &hf_fr_n_r, {
+ "N(R)", "fr.control.n_r", FT_UINT16, BASE_DEC,
+ NULL, XDLC_N_R_EXT_MASK, "", HFILL }},
+ { &hf_fr_n_s, {
+ "N(S)", "fr.control.n_s", FT_UINT16, BASE_DEC,
+ NULL, XDLC_N_S_EXT_MASK, "", HFILL }},
+ { &hf_fr_p, {
+ "Poll", "fr.control.p", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+ { &hf_fr_p_ext, {
+ "Poll", "fr.control.p", FT_BOOLEAN, 16,
+ TFS(&flags_set_truth), XDLC_P_F_EXT, "", HFILL }},
+ { &hf_fr_f, {
+ "Final", "fr.control.f", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+ { &hf_fr_f_ext, {
+ "Final", "fr.control.f", FT_BOOLEAN, 16,
+ TFS(&flags_set_truth), XDLC_P_F_EXT, "", HFILL }},
+ { &hf_fr_s_ftype, {
+ "Supervisory frame type", "fr.control.s_ftype", FT_UINT16, BASE_HEX,
+ VALS(stype_vals), XDLC_S_FTYPE_MASK, "", HFILL }},
+ { &hf_fr_u_modifier_cmd, {
+ "Command", "lapd.control.u_modifier_cmd", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, "", HFILL }},
+ { &hf_fr_u_modifier_resp, {
+ "Response", "lapd.control.u_modifier_resp", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, "", HFILL }},
+ { &hf_fr_ftype_i, {
+ "Frame type", "fr.control.ftype", FT_UINT16, BASE_HEX,
+ VALS(ftype_vals), XDLC_I_MASK, "", HFILL }},
+ { &hf_fr_ftype_s_u, {
+ "Frame type", "fr.control.ftype", FT_UINT8, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+ { &hf_fr_ftype_s_u_ext, {
+ "Frame type", "fr.control.ftype", FT_UINT16, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+ { &hf_fr_nlpid, {
+ "NLPID", "fr.nlpid", FT_UINT8, BASE_HEX,
+ VALS(fr_nlpid_vals), 0x0, "Frame Relay Encapsulated Protocol NLPID", HFILL }},
+ { &hf_fr_oui, {
+ "Organization Code", "fr.snap.oui", FT_UINT24, BASE_HEX,
+ VALS(oui_vals), 0x0, "", HFILL }},
+ { &hf_fr_pid, {
+ "Protocol ID", "fr.snap.pid", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_fr_snaptype, {
+ "Type", "fr.snaptype", FT_UINT16, BASE_HEX,
+ VALS(etype_vals), 0x0, "Frame Relay SNAP Encapsulated Protocol", HFILL }},
+ { &hf_fr_chdlctype, {
+ "Type", "fr.chdlctype", FT_UINT16, BASE_HEX,
+ VALS(chdlc_vals), 0x0, "Frame Relay Cisco HDLC Encapsulated Protocol", HFILL }},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fr,
+ &ett_fr_address,
+ &ett_fr_control,
+ };
+ static enum_val_t fr_encap_options[] = {
+ { "frf-3.2", "FRF 3.2/Cisco HDLC", FRF_3_2 },
+ { "gprs-ns", "GPRS Network Service", GPRS_NS },
+ { "ethernet", "Raw Ethernet", RAW_ETHER },
+ { NULL, NULL, 0 },
+ };
+ module_t *frencap_module;
+
+ proto_fr = proto_register_protocol("Frame Relay", "FR", "fr");
+ proto_register_field_array(proto_fr, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ fr_subdissector_table = register_dissector_table("fr.ietf",
+ "Frame Relay NLPID", FT_UINT8, BASE_HEX);
+ fr_osinl_subdissector_table = register_dissector_table("fr.osinl",
+ "Frame Relay OSI NLPID", FT_UINT8, BASE_HEX);
+
+ register_dissector("fr_uncompressed", dissect_fr_uncompressed, proto_fr);
+ register_dissector("fr", dissect_fr, proto_fr);
+
+ frencap_module = prefs_register_protocol(proto_fr, NULL);
+ prefs_register_enum_preference(frencap_module, "encap", "Encapsulation",
+ "Encapsulation", &fr_encap,
+ fr_encap_options, FALSE);
+}
+
+void proto_reg_handoff_fr(void)
+{
+ dissector_handle_t fr_handle, fr_phdr_handle;
+
+ fr_handle = create_dissector_handle(dissect_fr, proto_fr);
+ dissector_add("gre.proto", GRE_FR, fr_handle);
+ dissector_add("wtap_encap", WTAP_ENCAP_FRELAY, fr_handle);
+
+ fr_phdr_handle = create_dissector_handle(dissect_fr_phdr, proto_fr);
+ dissector_add("wtap_encap", WTAP_ENCAP_FRELAY_WITH_PHDR, fr_phdr_handle);
+
+ eth_handle = find_dissector("eth");
+ gprs_ns_handle = find_dissector("gprs_ns");
+ data_handle = find_dissector("data");
+
+ osinl_subdissector_table = find_dissector_table("osinl");
+}
diff --git a/epan/dissectors/packet-frame.c b/epan/dissectors/packet-frame.c
new file mode 100644
index 0000000000..5d53b752ef
--- /dev/null
+++ b/epan/dissectors/packet-frame.c
@@ -0,0 +1,342 @@
+/* packet-frame.c
+ *
+ * Top-most dissector. Decides dissector based on Wiretap Encapsulation Type.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2000 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/timestamp.h>
+#include <epan/tvbuff.h>
+#include "packet-frame.h"
+#include "prefs.h"
+#include "tap.h"
+
+int proto_frame = -1;
+int hf_frame_arrival_time = -1;
+static int hf_frame_time_delta = -1;
+static int hf_frame_time_relative = -1;
+int hf_frame_number = -1;
+int hf_frame_packet_len = -1;
+int hf_frame_capture_len = -1;
+static int hf_frame_p2p_dir = -1;
+static int hf_frame_file_off = -1;
+static int hf_frame_marked = -1;
+static int hf_frame_ref_time = -1;
+
+static int proto_short = -1;
+int proto_malformed = -1;
+static int proto_unreassembled = -1;
+
+static gint ett_frame = -1;
+
+static int frame_tap = -1;
+
+static dissector_handle_t data_handle;
+static dissector_handle_t docsis_handle;
+
+/* Preferences */
+static gboolean show_file_off = FALSE;
+static gboolean force_docsis_encap;
+
+static const value_string p2p_dirs[] = {
+ { P2P_DIR_SENT, "Sent" },
+ { P2P_DIR_RECV, "Received" },
+ { 0, NULL }
+};
+
+static dissector_table_t wtap_encap_dissector_table;
+
+static void
+dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *fh_tree;
+ proto_item *ti;
+ nstime_t ts;
+ int cap_len, pkt_len;
+
+ pinfo->current_proto = "Frame";
+
+ if (pinfo->pseudo_header != NULL) {
+ switch (pinfo->fd->lnk_t) {
+
+ case WTAP_ENCAP_WFLEET_HDLC:
+ case WTAP_ENCAP_CHDLC_WITH_PHDR:
+ case WTAP_ENCAP_PPP_WITH_PHDR:
+ case WTAP_ENCAP_SDLC:
+ pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ?
+ P2P_DIR_SENT : P2P_DIR_RECV;
+ break;
+
+ case WTAP_ENCAP_LAPB:
+ case WTAP_ENCAP_FRELAY_WITH_PHDR:
+ pinfo->p2p_dir =
+ (pinfo->pseudo_header->x25.flags & FROM_DCE) ?
+ P2P_DIR_RECV : P2P_DIR_SENT;
+ break;
+
+ case WTAP_ENCAP_ISDN:
+ pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ?
+ P2P_DIR_SENT : P2P_DIR_RECV;
+ break;
+ }
+ }
+
+ if ((force_docsis_encap) && (docsis_handle)) {
+ /*
+ * XXX - setting it here makes it impossible to
+ * turn the "Treat all frames as DOCSIS frames"
+ * option off.
+ *
+ * The TCP Graph code currently uses "fd->lnk_t";
+ * it should eventually just get the information
+ * it needs from a full-blown dissection, so that
+ * can handle any link-layer type.
+ */
+ pinfo->fd->lnk_t = WTAP_ENCAP_DOCSIS;
+ }
+
+ /* Put in frame header information. */
+ if (tree) {
+
+ cap_len = tvb_length(tvb);
+ pkt_len = tvb_reported_length(tvb);
+
+ ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, -1,
+ "Frame %u (%u bytes on wire, %u bytes captured)", pinfo->fd->num, pkt_len, cap_len);
+
+ fh_tree = proto_item_add_subtree(ti, ett_frame);
+
+ proto_tree_add_boolean_hidden(fh_tree, hf_frame_marked, tvb, 0, 0,pinfo->fd->flags.marked);
+
+ if(pinfo->fd->flags.ref_time){
+ proto_tree_add_item(fh_tree, hf_frame_ref_time, tvb, 0, 0, FALSE);
+ }
+
+ ts.secs = pinfo->fd->abs_secs;
+ ts.nsecs = pinfo->fd->abs_usecs*1000;
+
+ proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb,
+ 0, 0, &ts);
+
+ ts.secs = pinfo->fd->del_secs;
+ ts.nsecs = pinfo->fd->del_usecs*1000;
+
+ proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb,
+ 0, 0, &ts);
+
+ ts.secs = pinfo->fd->rel_secs;
+ ts.nsecs = pinfo->fd->rel_usecs*1000;
+
+ proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb,
+ 0, 0, &ts);
+
+ proto_tree_add_uint(fh_tree, hf_frame_number, tvb,
+ 0, 0, pinfo->fd->num);
+
+ proto_tree_add_uint_format(fh_tree, hf_frame_packet_len, tvb,
+ 0, 0, pkt_len, "Packet Length: %d byte%s", pkt_len,
+ plurality(pkt_len, "", "s"));
+
+ proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb,
+ 0, 0, cap_len, "Capture Length: %d byte%s", cap_len,
+ plurality(cap_len, "", "s"));
+
+ /* Check for existences of P2P pseudo header */
+ if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) {
+ proto_tree_add_uint(fh_tree, hf_frame_p2p_dir, tvb,
+ 0, 0, pinfo->p2p_dir);
+ }
+
+ if (show_file_off) {
+ proto_tree_add_int_format(fh_tree, hf_frame_file_off, tvb,
+ 0, 0, pinfo->fd->file_off,
+ "File Offset: %ld (0x%lx)",
+ pinfo->fd->file_off, pinfo->fd->file_off);
+ }
+ }
+
+
+ TRY {
+ if (!dissector_try_port(wtap_encap_dissector_table, pinfo->fd->lnk_t,
+ tvb, pinfo, tree)) {
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %u",
+ pinfo->fd->lnk_t);
+ call_dissector(data_handle,tvb, pinfo, tree);
+ }
+ }
+ CATCH_ALL {
+ show_exception(tvb, pinfo, tree, EXCEPT_CODE);
+ }
+ ENDTRY;
+
+ tap_queue_packet(frame_tap, pinfo, NULL);
+}
+
+void
+show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ unsigned long exception)
+{
+ switch (exception) {
+
+ case BoundsError:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "[Short Frame]");
+ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
+ "[Short Frame: %s]", pinfo->current_proto);
+ break;
+
+ case ReportedBoundsError:
+ show_reported_bounds_error(tvb, pinfo, tree);
+ break;
+ }
+}
+
+void
+show_reported_bounds_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (pinfo->fragmented) {
+ /*
+ * We were dissecting an unreassembled fragmented
+ * packet when the exception was thrown, so the
+ * problem isn't that the dissector expected
+ * something but it wasn't in the packet, the
+ * problem is that the dissector expected something
+ * but it wasn't in the fragment we dissected.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "[Unreassembled Packet%s]",
+ pinfo->noreassembly_reason);
+ proto_tree_add_protocol_format(tree, proto_unreassembled,
+ tvb, 0, 0, "[Unreassembled Packet%s: %s]",
+ pinfo->noreassembly_reason, pinfo->current_proto);
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO,
+ "[Malformed Packet]");
+ proto_tree_add_protocol_format(tree, proto_malformed,
+ tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
+ }
+}
+
+void
+proto_register_frame(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_frame_arrival_time,
+ { "Arrival Time", "frame.time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Absolute time when this frame was captured", HFILL }},
+
+ { &hf_frame_time_delta,
+ { "Time delta from previous packet", "frame.time_delta", FT_RELATIVE_TIME, BASE_NONE, NULL,
+ 0x0,
+ "Time delta since previous diplayed frame", HFILL }},
+
+ { &hf_frame_time_relative,
+ { "Time since reference or first frame", "frame.time_relative", FT_RELATIVE_TIME, BASE_NONE, NULL,
+ 0x0,
+ "Time relative reference or first frame", HFILL }},
+
+ { &hf_frame_number,
+ { "Frame Number", "frame.number", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_frame_packet_len,
+ { "Total Frame Length", "frame.pkt_len", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_frame_capture_len,
+ { "Capture Frame Length", "frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_frame_p2p_dir,
+ { "Point-to-Point Direction", "frame.p2p_dir", FT_UINT8, BASE_DEC, VALS(p2p_dirs), 0x0,
+ "", HFILL }},
+
+ { &hf_frame_file_off,
+ { "File Offset", "frame.file_off", FT_INT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_frame_marked,
+ { "Frame is marked", "frame.marked", FT_BOOLEAN, 8, NULL, 0x0,
+ "Frame is marked in the GUI", HFILL }},
+
+ { &hf_frame_ref_time,
+ { "This is a Ref Time frame", "frame.ref_time", FT_NONE, 0, NULL, 0x0,
+ "This frame is a Reference Time frame", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_frame,
+ };
+ module_t *frame_module;
+
+ wtap_encap_dissector_table = register_dissector_table("wtap_encap",
+ "Wiretap encapsulation type", FT_UINT32, BASE_DEC);
+
+ proto_frame = proto_register_protocol("Frame", "Frame", "frame");
+ proto_register_field_array(proto_frame, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("frame",dissect_frame,proto_frame);
+
+ /* You can't disable dissection of "Frame", as that would be
+ tantamount to not doing any dissection whatsoever. */
+ proto_set_cant_toggle(proto_frame);
+
+ proto_short = proto_register_protocol("Short Frame", "Short frame", "short");
+ proto_malformed = proto_register_protocol("Malformed Packet",
+ "Malformed packet", "malformed");
+ proto_unreassembled = proto_register_protocol(
+ "Unreassembled Fragmented Packet",
+ "Unreassembled fragmented packet", "unreassembled");
+
+ /* "Short Frame", "Malformed Packet", and "Unreassembled Fragmented
+ Packet" aren't really protocols, they're error indications;
+ disabling them makes no sense. */
+ proto_set_cant_toggle(proto_short);
+ proto_set_cant_toggle(proto_malformed);
+ proto_set_cant_toggle(proto_unreassembled);
+
+ /* Our preferences */
+ frame_module = prefs_register_protocol(proto_frame, NULL);
+ prefs_register_bool_preference(frame_module, "show_file_off",
+ "Show File Offset", "Show File Offset", &show_file_off);
+ prefs_register_bool_preference(frame_module, "force_docsis_encap",
+ "Treat all frames as DOCSIS frames", "Treat all frames as DOCSIS Frames", &force_docsis_encap);
+
+ frame_tap=register_tap("frame");
+}
+
+void
+proto_reg_handoff_frame(void)
+{
+ data_handle = find_dissector("data");
+ docsis_handle = find_dissector("docsis");
+}
diff --git a/epan/dissectors/packet-frame.h b/epan/dissectors/packet-frame.h
new file mode 100644
index 0000000000..77fbff6f1f
--- /dev/null
+++ b/epan/dissectors/packet-frame.h
@@ -0,0 +1,49 @@
+/* packet-frame.h
+ *
+ * Top-most dissector. Decides dissector based on Wiretap Encapsulation Type.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2000 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Routine used to add an indication of an arbitrary exception to the tree.
+ */
+void show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ unsigned long exception);
+
+/*
+ * Routine used to add an indication of a ReportedBoundsError exception
+ * to the tree.
+ */
+void
+show_reported_bounds_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/*
+ * "Protocol" used for "malformed frame" errors (other than
+ * ReportedBoundsError exceptions).
+ */
+extern int proto_malformed;
+
+extern int proto_frame;
+extern int hf_frame_arrival_time;
+extern int hf_frame_number;
+extern int hf_frame_packet_len;
+extern int hf_frame_capture_len;
diff --git a/epan/dissectors/packet-ftam.c b/epan/dissectors/packet-ftam.c
new file mode 100644
index 0000000000..504c7fc010
--- /dev/null
+++ b/epan/dissectors/packet-ftam.c
@@ -0,0 +1,3671 @@
+/* packet-ftam.c
+*
+* Routine to dissect OSI ISO 8571 FTAM Protocol packets
+*
+* $Id$
+*
+* Yuriy Sidelnikov <YSidelnikov@hotmail.com>
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+
+#include "packet-frame.h"
+#include "packet-ftam.h"
+#include "prefs.h"
+
+#include <epan/strutil.h>
+
+#include "asn1.h"
+#include "format-oid.h"
+
+#include "packet-ses.h"
+#include "packet-pres.h"
+extern const value_string ses_vals[];
+static struct SESSION_DATA_STRUCTURE* session = NULL;
+
+
+
+/* ftam header fields */
+static int proto_ftam = -1;
+/* ftam fields defining a sub tree */
+static gint ett_ftam = -1;
+static gint ett_ftam_param = -1;
+static gint ett_ftam_rc = -1;
+static gint ett_ftam_ms = -1;
+static gint ett_ftam_itm = -1;
+/* dissector for data */
+static dissector_handle_t data_handle;
+/*
+----------------------------------------------------------------------------------------------------------*/
+static int hf_ftam_type = -1;
+static int hf_cp_type_message_length = -1;
+static int hf_protocol_version = -1;
+
+/* functional units flags */
+static int hf_functional_unit_restart_data_transfer = -1;
+static int hf_functional_unit_recovery = -1;
+static int hf_functional_unit_fadu_locking = -1;
+static int hf_functional_unit_grouping = -1;
+static int hf_functional_unit_limited_file_management = -1;
+static int hf_functional_unit_enhanced_file_management = -1;
+static int hf_functional_unit_file_access = -1;
+static int hf_functional_unit_read = -1;
+static int hf_functional_unit_write = -1;
+/* service classes */
+static int hf_service_class_access_class = -1;
+static int hf_service_class_transfer_and_management_class = -1;
+static int hf_service_class_transfer_class = -1;
+static int hf_service_class_management_class = -1;
+static int hf_service_class_unconstrained_class = -1;
+
+/* attribute groups */
+static int hf_attribute_groups_storage = -1;
+static int hf_attribute_groups_security = -1;
+static int hf_attribute_groups_private = -1;
+/* access */
+static int hf_filename_attribute_read = -1;
+static int hf_filename_attribute_insert = -1;
+static int hf_filename_attribute_replace = -1;
+static int hf_filename_attribute_extend = -1;
+static int hf_filename_attribute_erase = -1;
+static int hf_filename_attribute_read_attribute = -1;
+static int hf_filename_attribute_change_attribute = -1;
+static int hf_filename_attribute_delete_file = -1;
+/* mode */
+static int hf_processing_mode_read = -1;
+static int hf_processing_mode_replace = -1;
+static int hf_processing_mode_insert = -1;
+static int hf_processing_mode_extend = -1;
+static int hf_processing_mode_erase = -1;
+
+static int hf_permitted_action_attribute_read = -1;
+static int hf_permitted_action_attribute_insert = -1;
+static int hf_permitted_action_attribute_replace = -1;
+static int hf_permitted_action_attribute_extend = -1;
+static int hf_permitted_action_attribute_erase = -1;
+static int hf_permitted_action_attribute_read_attribute = -1;
+static int hf_permitted_action_attribute_change_attribute = -1;
+static int hf_permitted_action_attribute_delete_file = -1;
+static int hf_permitted_action_traversal = -1;
+static int hf_permitted_action_reverse_traversal = -1;
+static int hf_permitted_action_random_order = -1;
+
+static int hf_nbs9_read_filename = -1;
+static int hf_nbs9_read_permitted_actions = -1;
+static int hf_nbs9_read_contents_type = -1;
+static int hf_nbs9_read_storage_account = -1;
+static int hf_nbs9_read_date_and_time_of_creation = -1;
+static int hf_nbs9_read_date_and_time_of_last_modification = -1;
+static int hf_nbs9_read_date_and_time_of_read_access = -1;
+static int hf_nbs9_read_date_and_time_of_attribute_modification = -1;
+static int hf_nbs9_read_identity_of_creator = -1;
+static int hf_nbs9_read_identity_of_last_reader = -1;
+static int hf_nbs9_read_identity_of_last_modifier = -1;
+static int hf_nbs9_read_identity_of_last_attribute_modifier = -1;
+static int hf_nbs9_read_file_availability = -1;
+static int hf_nbs9_read_filesize = -1;
+static int hf_nbs9_read_future_filesize = -1;
+static int hf_nbs9_read_access_control = -1;
+static int hf_nbs9_read_legal_qualifications = -1;
+static int hf_nbs9_read_private_use = -1;
+
+static const value_string ftam_data_vals[] =
+{
+ {FTAM_GRAPHIC_STRING, "Graphic String" },
+ {FTAM_TELEX_STRING, "Teletex String" },
+ {FTAM_VIDEO_STRING, "Videotex String" },
+ {FTAM_IA5_STRING, "IA5String" },
+ {FTAM_VISIBLE_STRING, "Visible String" },
+ {FTAM_GENERAL_STRING, "General String" },
+ {FTAM_PRINTABLE_STRING, "Printable String" },
+ {FTAM_OCTET_STRING, "OCTET String" },
+ {FTAM_NODE_DESCRIPTOR_DATA_ELEMENT, "Node Descriptor Data Element" },
+ {FTAM_ENTER_SUBTREE_DATA_ELEMENT, "Enter subtree Data Element" },
+ {FTAM_EXIT_SUBTREE_DATA_ELEMENT, "Exit subtree Data Element" },
+ {FTAM_DATATYPE_NBS9, "Datatype NBS9" },
+};
+static const value_string ftam_pdu_vals[] =
+{
+ {FTAM_F_INITIALIZE_REQUEST, "f-initialize request" },
+ {FTAM_F_INITIALIZE_RESPONSE, "f-initialize response" },
+ {FTAM_F_TERMINATE_REQUEST, "f-terminate request" },
+ {FTAM_F_TERMINATE_RESPONSE, "f-terminate response" },
+ {FTAM_F_U_ABORT_REQUEST, "f-u-abort request" },
+ {FTAM_F_SELECT_REQUEST, "f-select request" },
+ {FTAM_F_SELECT_RESPONSE, "f-select response" },
+ {FTAM_F_DESELECT_REQUEST, "f-deselect request" },
+ {FTAM_F_DESELECT_RESPONSE, "f-deselect response" },
+ {FTAM_F_CREATE_REQUEST, "f-create request" },
+ {FTAM_F_CREATE_RESPONSE, "f-create response" },
+ {FTAM_F_DELETE_REQUEST, "f-delete request" },
+ {FTAM_F_DELETE_RESPONSE, "f-delete response" },
+ {FTAM_F_READ_ATTRIB_REQUEST, "f-read-attrib request" },
+ {FTAM_F_READ_ATTRIB_RESPONSE, "f-read-attrib response" },
+ {FTAM_F_CHANGE_ATTRIB_REQUEST, "f-change-attrib request" },
+ {FTAM_F_CHANGE_ATTRIB_RESPONSE, "f-change-attrib response" },
+ {FTAM_F_OPEN_REQUEST, "f-open request" },
+ {FTAM_F_OPEN_RESPONSE, "f-open response" },
+ {FTAM_F_CLOSE_REQUEST, "f-close request" },
+ {FTAM_F_CLOSE_RESPONSE, "f-close response" },
+ {FTAM_F_BEGIN_GROUP_REQUEST, "f-begin-group request" },
+ {FTAM_F_BEGIN_GROUP_RESPONSE, "f-begin-group response" },
+ {FTAM_F_END_GROUP_REQUEST, "f-end-group request" },
+ {FTAM_F_END_GROUP_RESPONSE, "f-end-group response" },
+ {FTAM_F_RECOVER_REQUEST, "f-recover request" },
+ {FTAM_F_RECOVER_RESPONSE, "f-recover response" },
+ {FTAM_F_LOCATE_REQUEST, "f-locate request" },
+ {FTAM_F_LOCATE_RESPONSE, "f-locate response" },
+ {FTAM_F_ERASE_REQUEST, "f-erase request" },
+ {FTAM_F_ERASE_RESPONSE, "f-erase response" },
+ {FTAM_F_READ_REQUEST, "f-read request" },
+ {FTAM_F_WRITE_REQUEST, "f-write request" },
+ {FTAM_F_DATA_END_REQUEST, "f-data end request" },
+ {FTAM_F_TRANSFER_END_REQUEST, "f-transfer end request" },
+ {FTAM_F_TRANSFER_END_RESPONSE, "f-transfer end response" },
+ {FTAM_F_CANCEL_REQUEST, "f-cancel request" },
+ {FTAM_F_CANCEL_RESPONSE, "f-cancel response" },
+ {FTAM_F_REASTART_REQUEST, "f-restart request" },
+ {FTAM_F_REASTART_RESPONSE, "f-restart response" },
+ {0, NULL }
+};
+static const value_string contents_type_list_vals[] =
+{
+ {FTAM_DOCUMENT_TYPE, "Document type"},
+ {FTAM_ABSTRACT_SYNTAX_NAME, "Abstract syntax name"},
+ {0, NULL}
+};
+
+static const value_string request_sequence_top_vals[] =
+{
+ {FTAM_RESPONSE_STATE_RESULT, "State result"},
+ {FTAM_PROTOCOL_VERSION, "Protocol version"},
+ {FTAM_IMPLEMENTATION_INFORMATION, "Implementation information"},
+ {FTAM_PRESENTATION_CONTEXT_MANAGEMENT, "Presentation context management"},
+ {FTAM_SERVICE_CLASS, "Service class"},
+ {FTAM_FUNCTIONAL_UNITS, "Functional units"},
+ {FTAM_ATTRIBUTE_GROUPS, "Attribute groups"},
+ {FTAM_SHARED_ASE_INFORMATION, "Shared ASE information"},
+ {FTAM_QUALITY_OF_SERVICE, "Ftam quality of service"},
+ {FTAM_CONTENTS_TYPE_LIST, "Contents type list"},
+ {FTAM_INITIATOR_IDENTIFY, "Initiator identity"},
+ {FTAM_ACCOUNT,"Account"},
+ {FTAM_FILESTORE_PASSWORD,"Filestore password"},
+ {FTAM_CHECKPOINT_WINDOW,"Checkpoint window"},
+ {FTAM_RESPONSE_ACTION_RESULT, "Action result"},
+ {FTAM_RESPONSE_DIAGNOSTIC, "Diagnostic"},
+ {FTAM_CHARGING,"Charging"},
+ {0, NULL}
+};
+
+static const value_string diagnostic_sequence_list_vals[] =
+{
+ {FTAM_DIAGNOSTIC_TYPE, "Diagnostic type"},
+ {FTAM_ERROR_IDENTIFIER, "Error identifier"},
+ {FTAM_ERROR_OBSERVER, "Error observer"},
+ {FTAM_ERROR_SOURCE, "Error source"},
+ {FTAM_SUGGESTED_DELAY, "Suggested delay"},
+ {FTAM_FURTHER_DETAILS, "Further details"},
+ {0, NULL}
+};
+static const value_string diag_definition_vals[] =
+{
+ {SEQUENCE, "Sequence"},
+ {0, NULL}
+};
+static const value_string entity_reference_vals[] =
+{
+ {FTAM_NO_CATEGORIZATION_POSSIBLE, "No categorization possible"},
+ {FTAM_INITIATING_FILE_SERVICE_USER, "Initiating file service user"},
+ {FTAM_INITIATING_FILE_PROTOCOL_MASHINE, "Initiating file protocol machine"},
+ {FTAM_SERVICE_SUPPORTING_THE_FILE_PROTOCOL_MACHINE, "Service supporting the file protocol machine"},
+ {FTAM_RESPONDING_FILE_PROTOCOL_MASHINE, "Responding file protocol machine"},
+ {FTAM_RESPONDING_FILE_SERVICE_USER, "Responding file service user"},
+ {0, NULL}
+};
+static const value_string diagnostic_type_vals[] =
+{
+ {FTAM_DIAGNOSTIC_INFORMATIVE, "Informative"},
+ {FTAM_DIAGNOSTIC_TRANSIENT, "Transient"},
+ {FTAM_DIAGNOSTIC_PERMANENT, "Permanent"},
+ {0, NULL}
+};
+static const value_string response_state_vals[] =
+{
+ {FTAM_RESPONSE_STATE_SUCCESS, "Success"},
+ {FTAM_RESPONSE_STATE_FAILURE, "failure"},
+ {0, NULL}
+};
+static const value_string response_action_result_vals[] =
+{
+ {FTAM_RESPONSE_ACTION_RESULT_SUCCESS, "Success"},
+ {FTAM_RESPONSE_ACTION_RESULT_TRANSIENT_ERROR, "Transient error"},
+ {FTAM_RESPONSE_ACTION_RESULT_PERMANENT_ERROR, "Permanent error"},
+ {0, NULL}
+};
+static const value_string select_request_vals[] =
+{
+ {FTAM_SELECT_ATTRIBUTES, "Select attributes"},
+ {FTAM_CREATE_ATTRIBUTES, "Create attributes"},
+ {FTAM_ACCESS_REQUEST, "Access request"},
+ {FTAM_ACCSESS_PASSWORDS, "Access passwords"},
+ {FTAM_SHARED_ASE_INFORMATION, "Shared ASE information"},
+ {FTAM_ACCOUNT,"Account"},
+ {FTAM_OVERRIDE,"Override"},
+ /*no concurrency-control yet */
+ {0, NULL}
+};
+static const value_string select_attribute_vals[] =
+{
+ {FTAM_CREATE_FILENAME_ATTRIBUTES, "File name attributes"},
+ {FTAM_CREATE_PERMITTED_ACTIONS_ATTRIBUTE, "Permitted actions attribute"},
+ {FTAM_CREATE_CONTENTS_TYPE,"Contents type"},
+ {FTAM_CREATE_ACCOUNT_ATTRIBUTE,"Account attribute"},
+ {FTAM_CREATE_FILE_AVAILABILITY_ATTRIBUTE,"File availability attribute"},
+ {FTAM_CREATE_FILESIZE_ATTRIBUTE,"Filesize attribute"},
+ {FTAM_CREATE_ACCESS_CONTROL_ATTRIBUTE,"Access control attribute"},
+ {FTAM_CREATE_ACCESS_LEGAL_AUALIFICATION_ATTRIBUTE,"Legal aualification attribute"},
+ {FTAM_CREATE_ACCESS_PRIVATE_USE_ATTRIBUTE,"Private use attribute"},
+ {0, NULL}
+};
+static const value_string open_request_vals[] =
+{
+ {FTAM_PROCESSING_MODE, "Processing mode"},
+ {FTAM_CONTENTS_TYPE, "Contents type"},
+ {FTAM_CONCURENCY_CONTROL, "Concurrency control"},
+ {FTAM_SHARED_ASE_INFORMATION, "Shared ASE information"},
+ {FTAM_ENABLE_FADU_LOCKING,"Enable fadu locking"},
+ {FTAM_ACTIVITY_IDENTIFIER,"Activity identifier"},
+ {FTAM_RECOVERY_MODE,"Recovery mode"},
+ {FTAM_REMOTE_CONTEXTS,"Remove contexts"},
+ {FTAM_DEFINE_CONTEXTS,"Define contexts"},
+ {0, NULL}
+};
+static const value_string contents_type_vals[] =
+{
+ {FTAM_CONTENTS_TYPE_UNKNOWN, "Unknown"},
+ {FTAM_CONTENTS_TYPE_PROPOSED, "Proposed"},
+ {0, NULL}
+};
+static const value_string contents_type_proposed_vals[] =
+{
+ {FTAM_CONTENTS_TYPE_PROPOSED_DOCUMENT_TYPE, "Document type"},
+ {FTAM_CONTENTS_TYPE_PROPOSED_CONSTRAINT_SET, "Constraint set and abstract syntax"},
+ {0, NULL}
+};
+static const value_string contents_type_proposed_document_type_vals[] =
+{
+ {FTAM_CONTENTS_TYPE_PROPOSED_DOCUMENT_TYPE_NAME, "Document type name"},
+ {FTAM_CONTENTS_TYPE_PROPOSED_DOCUMENT_TYPE_PARAMETER, "Parameter"},
+ {0, NULL}
+};
+static const value_string override_vals[] =
+{
+ {FTAM_CREATE_FAILURE, "Create failure"},
+ {FTAM_SELECT_OLD_FILE, "Select old file"},
+ {FTAM_DELETE_AND_CREATE_WITH_OLD_ATTRIBUTES, "Delete and create with old attributes"},
+ {FTAM_DELETE_AND_CREATE_WITH_NEW_ATTRIBUTES, "Delete and create with new attributes"},
+ {0, NULL}
+};
+static const value_string read_write_vals[] =
+{
+ {FTAM_FILE_ACCESS_DATA_UNIT_IDENTITY, "File access data unit identity"},
+ {FTAM_FILE_ACCESS_CONTEXT, "Access context"},
+ {FTAM_FILE_FADU_LOCK, "Fadu lock"},
+ {FTAM_FILE_ACCESS_DATA_UNIT_OPERATION, "File access data unit operation"},
+ {0, NULL}
+};
+static const value_string fadu_vals[] =
+{
+ {FTAM_FADU_FIRST_LAST, "First/Last"},
+ {FTAM_FADU_RELATIVE, "Relative"},
+ {FTAM_FADU_BEGIN_END, "Begin/End"},
+ {FTAM_FADU_SINGLE_NAME, "Single name"},
+ {FTAM_FADU_NAME_LIST, "Name list"},
+ {FTAM_FADU_FADU_NUMBER, "FADU number"},
+ {0, NULL}
+};
+static const value_string first_last_vals[] =
+{
+ {FTAM_FADU_FIRST, "First"},
+ {FTAM_FADU_LAST, "LAST"},
+ {0, NULL}
+};
+static const value_string relative_vals[] =
+{
+ {FTAM_FADU_PREVIOUS, "Previous"},
+ {FTAM_FADU_CURRENT, "Current"},
+ {FTAM_FADU_NEXT, "Next"},
+ {0, NULL}
+};
+static const value_string begin_end_vals[] =
+{
+ {FTAM_FADU_BEGIN, "Begin"},
+ {FTAM_FADU_END, "End"},
+ {0, NULL}
+};
+static const value_string access_context_vals[] =
+{
+ {FTAM_HIERARCHICAL_ALL_DATA_UNITS, "Hierarchical all data units"},
+ {FTAM_HIERARCHICAL_NO_DATA_UNITS, "Hierarchical no data units"},
+ {FTAM_ALL_DATA_UNITS, "Flat all data units"},
+ {FTAM_ONE_LEVEL_DATA_UNITS, "Flat one level data units"},
+ {FTAM_SINGLE_DATA_UNITS, "Flat single data units"},
+ {FTAM_UNSTRUCTURED_ALL_DATA_UNITS, "Unstructured all data units"},
+ {FTAM_UNSTRUCTURED_SINGLE_DATA_UNITS, "Unstructured single data units"},
+ {0, NULL}
+};
+static const value_string access_data_unit_operation_vals[] =
+{
+ {FTAM_ACCESS_INSERT, "Insert"},
+ {FTAM_ACCESS_REPLACE, "Replace"},
+ {FTAM_ACCESS_EXTEND, "Extend"},
+ {0, NULL}
+};
+
+
+
+static const value_string ftam_parameters_vals[] =
+{
+ {FTAM_UNIVERSAL_CLASS_NUMBER, "Universal class number"},
+ {FTAM_MAXIMUM_STRING_LENGTH, "Maximum string length"},
+ {FTAM_STRING_SIGNIFICANCE, "String significance"},
+ {0, NULL}
+};
+
+static const value_string universal_class_number_vals[] =
+{
+ {FTAM_PRINTABLE_LENGTH, "Printable string"},
+ {FTAM_GRAPHIC_STRING, "Graphic string"},
+ {FTAM_TELEX_STRING, "Teletex string"},
+ {FTAM_VIDEO_STRING, "Video texstring"},
+ {FTAM_IA5_STRING, "ia5string"},
+ {FTAM_VISIBLE_STRING, "Visible string"},
+ {FTAM_GENERAL_STRING, "General string"},
+ {0, NULL}
+};
+
+
+static const value_string string_significance_vals[] =
+{
+ {FTAM_VARIABLE, "Variable"},
+ {FTAM_FIXED, "Fixed"},
+ {FTAM_NOT_SIGNIFICANT, "Not significant"},
+ {0, NULL}
+};
+static const value_string read_attributes_vals[] =
+{
+ {FTAM_READ_ATTRIBUTE_FILENAME, "Filename"},
+ {FTAM_READ_ATTRIBUTE_PERMITTED_ACTIONS, "Permitted actions"},
+ {FTAM_READ_ATTRIBUTE_CONTENTS_TYPE, "Contents type"},
+ {FTAM_READ_ATTRIBUTE_STORAGE_ACCOUNT, "Storage account"},
+ {FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_CREATION, "Date and time of creation"},
+ {FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_LAST_MODIFICATION, "Date and time of last modification"},
+ {FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_LAST_READ_ACCESS, "Date and time of last read access"},
+ {FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_LAST_ATTRIBUTE_MODIFICATION, "Date and time of last attribute modification"},
+ {FTAM_READ_ATTRIBUTE_IDENTITY_OF_CREATOR, "Identity of creator"},
+ {FTAM_READ_ATTRIBUTE_IDENTITY_OF_LAST_MODIFIER, "Identity of last modifier"},
+ {FTAM_READ_ATTRIBUTE_IDENTITY_OF_LAST_READER, "Identity of last reader"},
+ {FTAM_READ_ATTRIBUTE_IDENTITY_OF_LAST_ATTRIBUTE_MODIFIER, "Identity of last attribute modifier"},
+ {FTAM_READ_ATTRIBUTE_FILE_AVAILABILITY, "File availability"},
+ {FTAM_READ_ATTRIBUTE_FILESIZE, "Filesize"},
+ {FTAM_READ_ATTRIBUTE_FUTURE_FILESIZE, "Future filesize"},
+ {FTAM_READ_ATTRIBUTE_ACCESS_CONTROL, "Access control"},
+ {FTAM_READ_ATTRIBUTE_LEGAL_QUALIFICATION, "legal qualification"},
+ {FTAM_READ_ATTRIBUTE_PRIVATE_USE, "Private use"},
+ {0, NULL}
+};
+static const value_string date_and_time_vals[] =
+{
+ {FTAM_DATE_AND_TIME_NO_VALUE_AVAILABLE, "No value available"},
+ {FTAM_DATE_AND_TIME_ACTUAL_VALUE, "actual values"},
+ {0, NULL}
+};
+static const value_string identity_vals[] =
+{
+ {FTAM_DATE_IDENTITY_NO_VALUE_AVAILABLE, "No value available"},
+ {FTAM_USER_IDENTITY, "actual values"},
+ {0, NULL}
+};
+static const value_string read_attribute_vals[] =
+{
+ {FTAM_READ_ATTRIBUTES, "Read attributes"},
+ {0, NULL}
+};
+
+/* function definitions */
+static void
+show_contents_type(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len);
+static void
+show_contents_type_proposed(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len);
+static void
+show_select_create_attributes(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len);
+static void
+show_nbs9_parameters(ASN1_SCK *asn,proto_tree *ftam_tree_itm,tvbuff_t *tvb,int
+*offset,int item_len);
+
+
+static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
+{
+ guint length = 0;
+ gboolean def = FALSE;
+ int start = a->offset;
+ int ret;
+ ret = asn1_length_decode(a, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse length: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+ if (len)
+ *len = length;
+ if (tree && hf_id)
+ proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start,length);
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i, int start, guint length)
+{
+ guint integer = 0;
+ proto_item *temp_item = NULL;
+ int ret;
+
+ ret = asn1_uint32_value_decode(a, length, &integer);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse value: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (i)
+ *i = integer;
+
+ if (tree && hf_id)
+ temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start,a->offset-start, integer);
+
+ if (new_item)
+ *new_item = temp_item;
+
+ return ASN1_ERR_NOERROR;
+}
+
+static void
+show_graphic_string(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *ftam_tree_itm = NULL;
+ proto_item *itm;
+ gint length;
+ gint header_len = (asn->offset -*offset);
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ header_len+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+
+ itm = proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ ftam_tree_itm = proto_item_add_subtree(itm, ett_ftam_itm);
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree_itm, tvb, *offset, item_len,GRAPHIC_STRING);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+show_graphic_string_nameless(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ gint length;
+ gint header_len = (asn->offset -*offset);
+ gint new_item_len;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ header_len+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, ftam_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ return ;
+ }
+
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree, tvb, *offset, new_item_len,GRAPHIC_STRING);
+}
+static void
+show_file_store_password(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *ftam_tree_itm = NULL;
+ proto_item *itm;
+ gint length;
+ gint header_len = (asn->offset -*offset);
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ header_len+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+
+ itm = proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ ftam_tree_itm = proto_item_add_subtree(itm, ett_ftam_itm);
+ *offset = asn->offset;
+ show_graphic_string_nameless(asn,ftam_tree_itm,tvb,offset,item_len-header_len );
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+
+static void
+show_attribute_groups(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *ftam_tree_itm = NULL;
+ proto_item *itm;
+ guint8 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ itm = proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ ftam_tree_itm = proto_item_add_subtree(itm, ett_ftam_itm);
+ *offset = asn->offset;
+ flags = tvb_get_guint8(tvb, (*offset)+1);
+ proto_tree_add_boolean(ftam_tree_itm,hf_attribute_groups_storage, tvb, (*offset)+1,1,flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_attribute_groups_security, tvb, (*offset)+1,1,flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_attribute_groups_private, tvb, (*offset)+1,1,flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+
+static void
+show_create_permitted_actions_attribute(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ guint16 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ *offset = asn->offset+1;
+ flags = tvb_get_ntohs(tvb,*offset);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_attribute_read, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_attribute_insert, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_attribute_replace, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_attribute_extend, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_attribute_erase, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_attribute_read_attribute, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_attribute_change_attribute, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_attribute_delete_file, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_traversal, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_permitted_action_random_order, tvb, (*offset),2,flags);
+
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+show_processing_mode(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ guint16 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ *offset = asn->offset;
+ flags = tvb_get_ntohs(tvb,*offset);
+ proto_tree_add_boolean(ftam_tree,hf_processing_mode_read, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_processing_mode_replace, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_processing_mode_insert, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_processing_mode_extend, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_processing_mode_erase, tvb, (*offset),2,flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+show_access_attributes(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ guint16 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ *offset = asn->offset;
+ flags = tvb_get_ntohs(tvb,*offset);
+ proto_tree_add_boolean(ftam_tree,hf_filename_attribute_read, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_filename_attribute_insert, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_filename_attribute_replace, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_filename_attribute_extend, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_filename_attribute_erase, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_filename_attribute_read_attribute, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_filename_attribute_change_attribute, tvb, (*offset),2,flags);
+ proto_tree_add_boolean(ftam_tree,hf_filename_attribute_delete_file, tvb, (*offset),2,flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+show_service_classes(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *ftam_tree_itm = NULL;
+ proto_item *itm;
+ guint8 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ itm = proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ ftam_tree_itm = proto_item_add_subtree(itm, ett_ftam_itm);
+ *offset = asn->offset;
+ flags = tvb_get_guint8(tvb, (*offset)+1);
+ proto_tree_add_boolean(ftam_tree_itm,hf_service_class_unconstrained_class, tvb, (*offset)+1,1,flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_service_class_management_class, tvb, (*offset)+1,1,flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_service_class_transfer_class, tvb, (*offset)+1,1,flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_service_class_transfer_and_management_class, tvb, (*offset)+1,1,flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_service_class_transfer_and_management_class, tvb, (*offset)+1,1,flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+
+static void
+show_functional_units(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *ftam_tree_itm = NULL;
+ proto_item *itm;
+ guint16 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ itm = proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ ftam_tree_itm = proto_item_add_subtree(itm, ett_ftam_itm);
+ *offset = asn->offset;
+ flags = tvb_get_ntohs(tvb, (*offset)+1);
+ proto_tree_add_boolean(ftam_tree_itm,hf_functional_unit_read, tvb, (*offset)+1,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_functional_unit_write, tvb, (*offset)+1,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_functional_unit_file_access, tvb, (*offset)+1,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_functional_unit_limited_file_management, tvb, (*offset)+1,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_functional_unit_enhanced_file_management, tvb, (*offset)+1,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_functional_unit_grouping, tvb, (*offset)+1,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_functional_unit_fadu_locking, tvb, (*offset)+1,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_functional_unit_recovery, tvb, (*offset)+1,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_functional_unit_restart_data_transfer, tvb, (*offset)+1,2, flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+show_nbs9_parameters(ASN1_SCK *asn,proto_tree *ftam_tree_itm,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ guint16 flags;
+ gint length;
+ guint8 flag;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(ftam_tree_itm, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ *offset = asn->offset;
+ flags = tvb_get_ntohs(tvb, (*offset)+3);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_filename, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_permitted_actions, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_contents_type, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_storage_account, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_date_and_time_of_creation, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_date_and_time_of_last_modification, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_date_and_time_of_read_access, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_date_and_time_of_attribute_modification, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_identity_of_creator, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_identity_of_last_reader, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_identity_of_last_attribute_modifier, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_file_availability, tvb, (*offset)+1,3, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_filesize, tvb, (*offset)+1,3, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_future_filesize, tvb, (*offset)+3,2, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_access_control, tvb, (*offset)+3,2, flags);
+ flag = tvb_get_guint8(tvb, (*offset)+5 );
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_legal_qualifications, tvb, (*offset)+5,1, flags);
+ proto_tree_add_boolean(ftam_tree_itm,hf_nbs9_read_private_use, tvb, (*offset)+5,1, flag);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+show_protocol_version(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *ftam_tree_itm = NULL;
+ proto_item *itm;
+ guint16 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+ (asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+
+ itm = proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset -*offset)+
+ item_len,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ ftam_tree_itm = proto_item_add_subtree(itm, ett_ftam_itm);
+ *offset = asn->offset;
+ flags = tvb_get_ntohs(tvb, *offset);
+ proto_tree_add_boolean(ftam_tree_itm,hf_protocol_version, tvb, *offset,
+ 2, flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+print_oid_value(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ guint ret;
+ subid_t *oid;
+ guint len;
+ gchar *display_string;
+ guint length;
+ guint start=*offset;
+
+ ret = asn1_oid_value_decode (asn, item_len, &oid, &len);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ return ;
+ }
+ length = asn->offset - start;
+ display_string = format_oid(oid, len);
+ proto_tree_add_text(ftam_tree, tvb, *offset,length,"Value:%s",
+ display_string);
+ g_free(display_string);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+contents_type_list_data(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ proto_tree *ftam_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = *offset;
+ guint header_len;
+ int old_offset;
+ /* print seq */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ old_offset = *offset ;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, ftam_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+ new_item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset-1,
+ new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, contents_type_list_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+ *offset = asn->offset;
+ switch(type)
+ {
+ case FTAM_ABSTRACT_SYNTAX_NAME:
+ case FTAM_DOCUMENT_TYPE:
+ print_oid_value(asn,ftam_tree_ms,tvb,offset,new_item_len);
+ break;
+ default:
+ proto_tree_add_text(ftam_tree, tvb, *offset,
+ new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ }
+ *offset = old_offset+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ }
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+contents_type_list(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *ftam_tree_pc = NULL;
+ proto_item *itu;
+ guint start = asn->offset;
+ guint item_length = item_len;
+ guint new_item_len;
+ guint length;
+ itu = proto_tree_add_text(ftam_tree, tvb,
+ *offset,item_len+(asn->offset-*offset),
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ ftam_tree_pc = proto_item_add_subtree(itu, ett_ftam_ms);
+ switch(tag)
+ {
+ case FTAM_CONTENTS_TYPE_LIST:
+ /* get length */
+ (*offset)++;
+ asn->offset = *offset;
+ if (read_length(asn, ftam_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < new_item_len )
+ {
+ proto_tree_add_text(ftam_tree_pc, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+ contents_type_list_data(asn,ftam_tree_pc,tvb,offset,new_item_len);
+ break;
+ default:
+ break;
+ }
+
+
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+
+}
+
+/* if we can't dissect */
+static void
+dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const char *field_name, int ret)
+{
+ char *errstr;
+ errstr = asn1_err_to_str(ret);
+
+ if (tree != NULL)
+ {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "ERROR: Couldn't parse %s: %s", field_name, errstr);
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+}
+
+/* display request top sequence */
+static void
+show_access_context(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ gint length;
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Sequence error %u", ret);
+
+ return;
+ }
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /* align to value */
+ *offset = asn->offset;
+
+ proto_tree_add_text(ftam_tree, tvb,*offset,len1,
+ val_to_str(tvb_get_guint8(tvb,*offset), access_context_vals,"Unknown item (0x%02x)"));
+
+
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+
+}
+
+/* display attribute identity */
+static void
+show_attribute_identity(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ gint length;
+ int offset_save = *offset;
+ proto_item *itm;
+ proto_tree *ftam_tree_ms = NULL;
+
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Sequence error %u", ret);
+ return;
+ }
+ itm = proto_tree_add_text(ftam_tree, tvb,*offset,len1,
+ val_to_str(tag, identity_vals,"Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(itm, ett_ftam_ms);
+
+ switch(tag)
+ {
+ case FTAM_USER_IDENTITY:
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /* align to value */
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree_ms, tvb,*offset,len1,
+ "String");
+ break;
+ default:;
+ }
+
+
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+
+}
+
+/* display attribute date */
+static void
+show_attribute_data_and_time(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ gint length;
+ int offset_save = *offset;
+ proto_item *itm;
+ proto_tree *ftam_tree_ms = NULL;
+
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Sequence error %u", ret);
+ return;
+ }
+ itm = proto_tree_add_text(ftam_tree, tvb,*offset,len1,
+ val_to_str(tag, date_and_time_vals,"Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(itm, ett_ftam_ms);
+
+ switch(tag)
+ {
+ case FTAM_DATE_AND_TIME_ACTUAL_VALUE:
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /* align to value */
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree_ms, tvb,*offset,len1,
+ "Generalized Time");
+ break;
+ default:;
+ }
+
+
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+
+}
+
+
+
+/* display read attribute structure */
+static void
+show_read_attributes(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ gint new_item_len;
+ proto_tree *ftam_tree_ms = NULL;
+
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, ftam_tree,
+ "sequence error", ret);
+ break;
+ }
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ itm = proto_tree_add_text(ftam_tree, tvb, (*offset),(asn->offset-*offset)+ len1,
+ val_to_str(tag, read_attributes_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(itm, ett_ftam_ms);
+
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_CREATE_FILENAME_ATTRIBUTES:
+ /* get length */
+ (*offset)++;
+ asn->offset = *offset;
+ if (read_length(asn, ftam_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < new_item_len )
+ {
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+
+ return ;
+ }
+ *offset = asn->offset;
+ show_graphic_string_nameless(asn,ftam_tree_ms,tvb,offset,new_item_len);
+ break;
+ case FTAM_CREATE_PERMITTED_ACTIONS_ATTRIBUTE:
+ *offset = asn->offset;
+ show_create_permitted_actions_attribute(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+ case FTAM_READ_ATTRIBUTE_IDENTITY_OF_CREATOR:
+ case FTAM_READ_ATTRIBUTE_IDENTITY_OF_LAST_MODIFIER:
+ case FTAM_READ_ATTRIBUTE_IDENTITY_OF_LAST_READER:
+ case FTAM_READ_ATTRIBUTE_IDENTITY_OF_LAST_ATTRIBUTE_MODIFIER:
+ *offset = asn->offset;
+ show_attribute_identity(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+
+ case FTAM_CREATE_CONTENTS_TYPE:
+ *offset = asn->offset;
+ show_contents_type_proposed(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+ case FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_CREATION:
+ case FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_LAST_MODIFICATION:
+ case FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_LAST_READ_ACCESS:
+ case FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_LAST_ATTRIBUTE_MODIFICATION:
+ *offset = asn->offset;
+ show_attribute_data_and_time(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+
+
+ default:
+ if (match_strval(tag, read_attributes_vals) == NULL)
+ {
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+/* display nbs9 structure */
+static void
+show_nbs9(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gboolean def;
+ gint length;
+ proto_item *itm;
+ proto_tree *ftam_tree_ms = NULL;
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, ftam_tree,
+ "sequence error", ret);
+ break;
+ }
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+
+ itm = proto_tree_add_text(ftam_tree, tvb, (*offset),(asn->offset-*offset)+ len1,
+ val_to_str(tag, read_attribute_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(itm, ett_ftam_ms);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_READ_ATTRIBUTES:
+ *offset = asn->offset;
+ show_read_attributes(asn,ftam_tree_ms,tvb,pinfo,offset,len1);
+ break;
+ default:
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+/* display request top sequence */
+static void
+show_request_sequence_top(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, ftam_tree,
+ "sequence error", ret);
+ break;
+ }
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_IMPLEMENTATION_INFORMATION:
+ case FTAM_INITIATOR_IDENTIFY:
+ show_graphic_string(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_FILESTORE_PASSWORD:
+ show_file_store_password(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_FUNCTIONAL_UNITS:
+ show_functional_units(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_ATTRIBUTE_GROUPS:
+ show_attribute_groups(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_SERVICE_CLASS:
+ show_service_classes(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_ACCOUNT:
+ if( con == ASN1_CON)
+ {
+ /* it is FTAM_ACCOUNT */
+ show_graphic_string(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ }
+ /* no,it is FTAM_CHECKPOINT_WINDOW, go below */
+ tag = FTAM_CHECKPOINT_WINDOW;
+
+
+ case FTAM_PRESENTATION_CONTEXT_MANAGEMENT:
+ case FTAM_QUALITY_OF_SERVICE:
+ {
+ proto_tree *ftam_tree_pr = NULL;
+ proto_item *pr;
+ guint ret;
+ guint value;
+ pr = proto_tree_add_text(ftam_tree,tvb,*offset,
+ len1+(asn->offset-*offset),
+ val_to_str(tag ,request_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_pr = proto_item_add_subtree(pr, ett_ftam_ms);
+ ret = read_integer_value(asn,ftam_tree_pr, 0, NULL, &value, asn->offset, len1);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ itm = proto_tree_add_text(ftam_tree_pr, tvb, (*offset)-len1,
+ len1,
+ "Integer value: %u",value);
+ }
+ }
+ break;
+ case FTAM_CONTENTS_TYPE_LIST:
+ contents_type_list(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_PROTOCOL_VERSION:
+ show_protocol_version(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_SHARED_ASE_INFORMATION:
+ proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset -*offset)+len1,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ break;
+ default:
+ proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+static void
+show_error_identifier(ASN1_SCK *asn,proto_tree
+*ftam_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ guint ret;
+ guint value;
+ ret = read_integer_value(asn,ftam_tree, 0, NULL, &value, asn->offset, item_len);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree, tvb, (*offset)-item_len,
+ item_len,
+ "Integer value: %u",value);
+ }
+}
+static void
+show_diagnostic_type(ASN1_SCK *asn,proto_tree
+*ftam_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ guint ret;
+ guint value;
+ ret = read_integer_value(asn,ftam_tree, 0, NULL, &value, asn->offset, item_len);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree, tvb, (*offset)-item_len, item_len,
+ val_to_str(value, diagnostic_type_vals,
+ "Unknown item (0x%02x)"));
+
+ }
+}
+static void
+show_entity_reference(ASN1_SCK *asn,proto_tree
+*ftam_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ guint ret;
+ guint value;
+ ret = read_integer_value(asn,ftam_tree, 0, NULL, &value, asn->offset, item_len);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree, tvb, (*offset)-item_len, item_len,
+ val_to_str(value, entity_reference_vals,
+ "Unknown item (0x%02x)"));
+
+ }
+}
+static void
+show_response_state(ASN1_SCK *asn,proto_tree
+*ftam_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ guint ret;
+ guint value;
+ ret = read_integer_value(asn,ftam_tree, 0, NULL, &value, asn->offset, item_len);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree, tvb, (*offset)-item_len, item_len,
+ val_to_str(value, response_state_vals,
+ "Unknown item (0x%02x)"));
+
+ }
+}
+static void
+show_response_action_result(ASN1_SCK *asn,proto_tree
+*ftam_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ guint ret;
+ guint value;
+ ret = read_integer_value(asn,ftam_tree, 0, NULL, &value, asn->offset, item_len);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree, tvb, (*offset)-item_len, item_len,
+ val_to_str(value, response_action_result_vals,
+ "Unknown item (0x%02x)"));
+
+ }
+}
+
+static void
+show_diagnostic_seq(ASN1_SCK *asn,proto_tree
+*ftam_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ proto_tree *ftam_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = *offset;
+ guint header_len;
+ int old_offset;
+
+ /* print seq */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ old_offset = *offset ;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, ftam_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < new_item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset-1, new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, diagnostic_sequence_list_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+ *offset = asn->offset = (*offset)+1;
+
+
+ switch(type)
+ {
+ case FTAM_FURTHER_DETAILS:
+ (*offset)-=2;
+ show_graphic_string_nameless(asn,ftam_tree_ms,tvb,offset,new_item_len);
+ break;
+ case FTAM_ERROR_IDENTIFIER:
+ show_error_identifier(asn,ftam_tree_ms,tvb,offset,new_item_len);
+ break;
+ case FTAM_DIAGNOSTIC_TYPE:
+ show_diagnostic_type(asn,ftam_tree_ms,tvb,offset,new_item_len);
+ break;
+ case FTAM_ERROR_OBSERVER:
+ case FTAM_ERROR_SOURCE:
+ show_entity_reference(asn,ftam_tree_ms,tvb,offset,new_item_len);
+ break;
+ default:
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset, new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ }
+ *offset = old_offset+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ }
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+
+/* display diagnostic in the f-initiate response */
+static void
+show_diagnostic(ASN1_SCK *asn,proto_tree
+*ftam_tree,tvbuff_t *tvb,int *offset,int item_len,int tag)
+{
+ proto_tree *ftam_tree_ms = NULL;
+ proto_tree *ftam_tree_pc = NULL;
+ proto_item *itm;
+ gint length;
+ guint type;
+ guint header_len;
+ proto_item *ms;
+ gint new_item_len;
+ guint start = asn->offset;
+ guint item_length = item_len;
+
+ itm = proto_tree_add_text(ftam_tree, tvb, *offset,item_len+(asn->offset-*offset),
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ ftam_tree_pc = proto_item_add_subtree(itm, ett_ftam_ms);
+
+/* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree_pc, tvb, *offset, item_len,
+ "Wrong item.Need %u bytes but have %u", item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset =asn->offset;
+ start = *offset;
+ /* read the rest */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ int old_offset = *offset;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, ftam_tree_pc, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < new_item_len )
+ {
+ proto_tree_add_text(ftam_tree_pc, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ ms = proto_tree_add_text(ftam_tree_pc, tvb, *offset-1, new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, diag_definition_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+
+ case SEQUENCE:
+ show_diagnostic_seq(asn,ftam_tree_ms,tvb,offset,new_item_len);
+
+ *offset = old_offset+(new_item_len+header_len);
+ break;
+
+ default:
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset, new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ *offset = old_offset+(new_item_len+header_len);
+ }
+ item_len = item_len - (new_item_len+header_len);
+
+ }
+
+
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+}
+
+/* display response top sequence */
+static void
+show_response_sequence_top(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, ftam_tree,
+ "sequence error", ret);
+ break;
+ }
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_IMPLEMENTATION_INFORMATION:
+ if( con == ASN1_CON)
+ {
+ /* it is FTAM_CONTETS_TYPE */
+ *offset = asn->offset;
+ show_contents_type_proposed(asn,ftam_tree,tvb,offset,len1);
+ break;
+ }
+ /* no, it is implementation information.Just go below */
+
+ case FTAM_INITIATOR_IDENTIFY:
+ show_graphic_string(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_FILESTORE_PASSWORD:
+ show_file_store_password(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_FUNCTIONAL_UNITS:
+ show_functional_units(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_CHARGING:
+ proto_tree_add_text(ftam_tree,tvb,*offset,
+ len1+(asn->offset-*offset),
+ val_to_str(tag ,request_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ break;
+
+ case FTAM_ATTRIBUTE_GROUPS:
+ if( cls == ASN1_APL)
+ {
+ /* it is FTAM_RESPONSE_ACTION_RESULT */
+ proto_tree *ftam_tree_pr = NULL;
+ proto_item *pr;
+ pr = proto_tree_add_text(ftam_tree,tvb,*offset,
+ len1+(asn->offset-*offset),
+ val_to_str(FTAM_RESPONSE_ACTION_RESULT ,request_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_pr = proto_item_add_subtree(pr, ett_ftam_ms);
+ show_response_action_result(asn,ftam_tree_pr,tvb,offset,len1);
+ }
+ else
+ {
+ show_attribute_groups(asn,ftam_tree,tvb,offset,len1,tag);
+ }
+ break;
+ case FTAM_SERVICE_CLASS:
+ show_service_classes(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_CREATE_ATTRIBUTES:
+ *offset = asn->offset;
+ show_select_create_attributes(asn,ftam_tree,tvb,offset,len1);
+ break;
+
+ case FTAM_RESPONSE_STATE_RESULT:
+ {
+ proto_tree *ftam_tree_pr = NULL;
+ proto_item *pr;
+ pr = proto_tree_add_text(ftam_tree,tvb,*offset,
+ len1+(asn->offset-*offset),
+ val_to_str(tag ,request_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_pr = proto_item_add_subtree(pr, ett_ftam_ms);
+ show_response_state(asn,ftam_tree_pr,tvb,offset,len1);
+ }
+ break;
+ case FTAM_ACCOUNT:
+ if( con == ASN1_CON)
+ {
+ /* it is FTAM_ACCOUNT */
+ show_graphic_string(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ }
+ /* no,it is FTAM_CHECKPOINT_WINDOW, go below */
+ tag = FTAM_CHECKPOINT_WINDOW;
+ case FTAM_PRESENTATION_CONTEXT_MANAGEMENT:
+ case FTAM_QUALITY_OF_SERVICE:
+ {
+ proto_tree *ftam_tree_pr = NULL;
+ proto_item *pr;
+ guint ret;
+ guint value;
+ pr = proto_tree_add_text(ftam_tree,tvb,*offset,
+ len1+(asn->offset-*offset),
+ val_to_str(tag ,request_sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_pr = proto_item_add_subtree(pr, ett_ftam_ms);
+ ret = read_integer_value(asn,ftam_tree_pr, 0, NULL, &value, asn->offset, len1);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ itm = proto_tree_add_text(ftam_tree_pr, tvb, (*offset)-len1,
+ len1,
+ "Integer value: %u",value);
+ }
+ }
+ break;
+ case FTAM_CONTENTS_TYPE_LIST:
+ contents_type_list(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_PROTOCOL_VERSION:
+ show_protocol_version(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_SHARED_ASE_INFORMATION:
+ proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset -*offset)+len1,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ break;
+ case FTAM_RESPONSE_DIAGNOSTIC:
+ show_diagnostic(asn,ftam_tree,tvb,offset,len1,tag);
+ break;
+ case FTAM_SELECT_ATTRIBUTES:
+ *offset = asn->offset;
+ show_select_create_attributes(asn,ftam_tree,tvb,offset,len1);
+ break;
+
+ default:
+ itm = proto_tree_add_text(ftam_tree, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+static void
+show_select_create_attributes(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ proto_tree *ftam_tree_pc = NULL;
+ proto_item *itu;
+ guint start = asn->offset;
+ int new_item_len;
+ int length;
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "sequence error %u", ret);
+ break;
+ }
+ type = type & 0x1f;
+
+ itu = proto_tree_add_text(ftam_tree, tvb,*offset,len1+(asn->offset-*offset),
+ val_to_str(type, select_attribute_vals,"Unknown item (0x%02x)"));
+ ftam_tree_pc = proto_item_add_subtree(itu, ett_ftam_ms);
+
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ switch(type)
+ {
+ case FTAM_CREATE_FILENAME_ATTRIBUTES:
+ /* get length */
+ (*offset)++;
+ asn->offset = *offset;
+ if (read_length(asn, ftam_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < new_item_len )
+ {
+ proto_tree_add_text(ftam_tree_pc, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset = asn->offset;
+ show_graphic_string_nameless(asn,ftam_tree_pc,tvb,offset,new_item_len);
+ break;
+ case FTAM_CREATE_PERMITTED_ACTIONS_ATTRIBUTE:
+ *offset = asn->offset;
+ show_create_permitted_actions_attribute(asn,ftam_tree_pc,tvb,offset,len1);
+ break;
+
+ case FTAM_CREATE_CONTENTS_TYPE:
+ *offset = asn->offset;
+ show_contents_type_proposed(asn,ftam_tree_pc,tvb,offset,len1);
+ break;
+
+ default:
+ break;
+ }
+
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+/* display select_request */
+static void
+show_select_request(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ proto_tree *ftam_tree_ms = NULL;
+ proto_item *ms;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, ftam_tree,
+ "sequence error", ret);
+ break;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset, len1+(asn->offset-*offset),
+ val_to_str(tag, select_request_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_OVERRIDE:
+
+ proto_tree_add_text(ftam_tree_ms, tvb, asn->offset,len1,
+ val_to_str(tvb_get_guint8(tvb, asn->offset), override_vals,"Unknown item (0x%02x)"));
+ break;
+ case FTAM_ACCOUNT:
+ show_graphic_string(asn,ftam_tree_ms,tvb,offset,len1,tag);
+ break;
+ case FTAM_SELECT_ATTRIBUTES:
+ case FTAM_CREATE_ATTRIBUTES:
+ *offset = asn->offset;
+ show_select_create_attributes(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+
+ case FTAM_SHARED_ASE_INFORMATION:
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset -*offset)+len1,
+ val_to_str(tag, request_sequence_top_vals,"Unknown item (0x%02x)"));
+ break;
+ case FTAM_ACCESS_REQUEST:
+ show_access_attributes(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+ default:
+ itm = proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+
+/* display select_request */
+static void
+show_ftam_parameters(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ proto_tree *ftam_tree_ms = NULL;
+ proto_item *ms;
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &item_len);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "sequence error %u", ret);
+ return;
+ }
+ *offset = asn->offset;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "sequence error %u", ret);
+ break;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset, len1+(asn->offset-*offset),
+ val_to_str(tag, ftam_parameters_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_UNIVERSAL_CLASS_NUMBER:
+ *offset =asn->offset;
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset, len1,
+ val_to_str(tvb_get_guint8(tvb, *offset),
+ universal_class_number_vals,"Unknown item (0x%02x)"));
+ break;
+ case FTAM_STRING_SIGNIFICANCE:
+ *offset =asn->offset;
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset, len1,
+ val_to_str(tvb_get_guint8(tvb, *offset),
+ string_significance_vals,"Unknown item (0x%02x)"));
+ break;
+
+ default:
+ itm = proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+
+
+/* display contents type proposed document type*/
+static void
+show_contents_type_proposed_document_type(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ proto_tree *ftam_tree_ms = NULL;
+ proto_item *ms;
+ gboolean nbs9 = FALSE;
+ gint tp;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "sequence error %u", ret);
+
+ break;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset, len1+(asn->offset-*offset),
+ val_to_str(tag, contents_type_proposed_document_type_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_CONTENTS_TYPE_PROPOSED_DOCUMENT_TYPE_NAME:
+ if( (tp=tvb_get_guint8(tvb, (*offset)+2)) == NBS9_OID )
+ {
+ nbs9 = TRUE;
+ }
+ print_oid_value(asn,ftam_tree_ms,tvb,offset,len1);
+ *offset = asn->offset;
+ break;
+ case FTAM_CONTENTS_TYPE_PROPOSED_DOCUMENT_TYPE_PARAMETER:
+ if(nbs9)
+ {
+ /* it is NBS9 directory */
+ *offset = asn->offset;
+ show_nbs9_parameters(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+ }
+ else
+ {
+ show_ftam_parameters(asn,ftam_tree_ms,tvb,offset,len1);
+ }
+ default:
+ if (match_strval(tag, contents_type_proposed_document_type_vals) == NULL)
+ {
+ itm = proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+/* display contents type proposed */
+static void
+show_contents_type_proposed(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ proto_tree *ftam_tree_ms = NULL;
+ proto_item *ms;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "sequence error %u", ret);
+
+ break;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset, len1+(asn->offset-*offset),
+ val_to_str(tag, contents_type_proposed_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_CONTENTS_TYPE_PROPOSED_DOCUMENT_TYPE:
+ *offset = asn->offset;
+ show_contents_type_proposed_document_type(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+ default:
+ if (match_strval(tag, contents_type_proposed_vals) == NULL)
+ {
+ itm = proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+/* display FADU indetity type */
+static void
+show_fadu_identity_type(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ proto_tree *ftam_tree_ms = NULL;
+ proto_item *ms;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, len1,
+ "sequence error %u", ret);
+
+ break;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset, len1+(asn->offset-*offset),
+ val_to_str(tag, fadu_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_FADU_FIRST_LAST:
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset, len1,
+ val_to_str(tvb_get_guint8(tvb, *offset), first_last_vals,"Unknown item (0x%02x)"));
+ break;
+ case FTAM_FADU_RELATIVE:
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset, len1,
+ val_to_str(tvb_get_guint8(tvb, *offset), relative_vals,"Unknown item (0x%02x)"));
+ break;
+ case FTAM_FADU_BEGIN_END:
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset, len1,
+ val_to_str(tvb_get_guint8(tvb, *offset), begin_end_vals,"Unknown item (0x%02x)"));
+ break;
+
+ default:
+ if (match_strval(tag, contents_type_vals) == NULL)
+ {
+ itm = proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+
+
+
+/* display contents type */
+static void
+show_contents_type(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ proto_tree *ftam_tree_ms = NULL;
+ proto_item *ms;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, len1,
+ "sequence error %u", ret);
+
+ break;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset, len1+(asn->offset-*offset),
+ val_to_str(tag, contents_type_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_CONTENTS_TYPE_PROPOSED:
+ *offset = asn->offset;
+ show_contents_type_proposed(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+ default:
+ if (match_strval(tag, contents_type_vals) == NULL)
+ {
+ itm = proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+/* display read and write request */
+static void
+show_read_write_request(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ proto_tree *ftam_tree_ms = NULL;
+ proto_item *ms;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, ftam_tree,
+ "sequence error", ret);
+ break;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset, len1+(asn->offset-*offset),
+ val_to_str(tag, read_write_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_FILE_ACCESS_DATA_UNIT_OPERATION:
+ *offset = asn->offset;
+ proto_tree_add_text(ftam_tree_ms, tvb, *offset, len1,
+ val_to_str(tvb_get_guint8(tvb, *offset), access_data_unit_operation_vals,
+ "Unknown item (0x%02x)"));
+
+ break;
+ case FTAM_FILE_ACCESS_DATA_UNIT_IDENTITY:
+ *offset = asn->offset;
+ show_fadu_identity_type(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+ case FTAM_FILE_ACCESS_CONTEXT:
+ *offset = asn->offset;
+ show_access_context(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+
+ default:
+ if (match_strval(tag, ftam_pdu_vals) == NULL)
+ {
+ itm = proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+/* display open_request */
+static void
+show_open_request(ASN1_SCK *asn,proto_tree *ftam_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ proto_tree *ftam_tree_ms = NULL;
+ proto_item *ms;
+
+ while(item_len > 0 )
+ {
+ int offset_save = *offset;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(ftam_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, ftam_tree,
+ "sequence error", ret);
+ break;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, *offset, len1+(asn->offset-*offset),
+ val_to_str(tag, open_request_vals,
+ "Unknown item (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+
+ /* add header */
+ item_len = item_len - (asn->offset - *offset);
+ offset_save += (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case FTAM_PROCESSING_MODE:
+ show_processing_mode(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+ case FTAM_CONTENTS_TYPE:
+ *offset = asn->offset;
+ show_contents_type(asn,ftam_tree_ms,tvb,offset,len1);
+ break;
+ case FTAM_SHARED_ASE_INFORMATION:
+
+ break;
+ default:
+ if (match_strval(tag, ftam_pdu_vals) == NULL)
+ {
+ itm = proto_tree_add_text(ftam_tree_ms, tvb, *offset,(asn->offset-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ }
+ }
+ item_len-=len1;
+ *offset = asn->offset = offset_save+len1;
+ }
+}
+
+/*
+* Dissect a pdu.
+*/
+static int
+dissect_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree
+ *tree)
+{
+ proto_item *ti;
+ proto_tree *ftam_tree = NULL;
+ guint length;
+ guint rest_len;
+ guint s_type;
+ ASN1_SCK asn;
+ guint cp_type_len;
+/* get type of tag */
+ s_type = tvb_get_guint8(tvb, offset);
+ /* is it data bulk pdu ? */
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_ftam, tvb, offset, -1,
+ FALSE);
+ ftam_tree = proto_item_add_subtree(ti, ett_ftam);
+ }
+
+ if(s_type == DATA_BULK_PDU )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(ftam_tree, tvb, offset, 1,
+ "Bulk data Pdu");
+ }
+ /* skip additional data type byte */
+ offset++;
+ /* get type of tag */
+ s_type = tvb_get_guint8(tvb, offset); /*set application bite */
+
+ }
+ offset++;
+/* open asn.1 stream */
+ asn1_open(&asn, tvb, offset);
+
+ /* is it data PDU ? */
+ if( session->abort_type == DATA_BLOCK )
+ {
+ proto_item *ms;
+ proto_tree *ftam_tree_ms = NULL;
+ int save_offset;
+ /* set up type of pdu */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,"FTAM data PDU");
+
+ /* get length */
+ if (read_length(&asn, ftam_tree_ms, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, offset-1, rest_len+(asn.offset-offset)+1,
+ val_to_str(s_type, ftam_data_vals, "Unknown pdu type (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len
+ )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(ftam_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", rest_len,length);
+ }
+ return FALSE;
+ }
+ save_offset = asn.offset;
+
+ switch(s_type)
+ {
+ case FTAM_DATATYPE_NBS9:
+ show_nbs9(&asn,ftam_tree_ms,tvb,pinfo,&offset,rest_len);
+ break;
+ case FTAM_PRINTABLE_LENGTH:
+ case FTAM_GRAPHIC_STRING:
+ case FTAM_TELEX_STRING:
+ case FTAM_IA5_STRING:
+ case FTAM_VISIBLE_STRING:
+ case FTAM_GENERAL_STRING:
+ case FTAM_OCTET_STRING:
+ case FTAM_PRINTABLE_STRING:
+ break;
+ default:
+ {
+ if(tree)
+ {
+ ms = proto_tree_add_text(ftam_tree, tvb, offset, rest_len+(asn.offset-offset),
+ "Unknown pdu type (0x%02x)",s_type);
+ }
+ }
+
+ }
+ offset =rest_len+save_offset;
+ asn.offset=offset;
+ /* close asn.1 stream */
+ asn1_close(&asn, &offset);
+ return offset ;
+ }
+ /* no, it is not data PDU */
+ /* set up type of pdu */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(s_type, ftam_pdu_vals, "Unknown pdu type (0x%02x)"));
+
+ switch(s_type)
+ {
+ case FTAM_F_INITIALIZE_REQUEST:
+ case FTAM_F_INITIALIZE_RESPONSE:
+ case FTAM_F_TERMINATE_REQUEST:
+ case FTAM_F_TERMINATE_RESPONSE:
+ case FTAM_F_U_ABORT_REQUEST:
+ case FTAM_F_P_ABORT_REQUEST:
+ case FTAM_F_DESELECT_RESPONSE:
+ case FTAM_F_DELETE_RESPONSE:
+ case FTAM_F_CLOSE_RESPONSE:
+ case FTAM_F_ERASE_RESPONSE:
+ case FTAM_F_TRANSFER_END_REQUEST:
+ case FTAM_F_CANCEL_REQUEST:
+ case FTAM_F_CANCEL_RESPONSE:
+ case FTAM_F_CREATE_RESPONSE:
+ case FTAM_F_OPEN_RESPONSE:
+ case FTAM_F_SELECT_RESPONSE:
+
+ proto_tree_add_uint(ftam_tree, hf_ftam_type, tvb, offset-1, 1, s_type);
+ if (read_length(&asn, ftam_tree, hf_cp_type_message_length, &cp_type_len)
+ != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
+ )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(ftam_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", cp_type_len,length);
+ }
+ return FALSE;
+ }
+ if(tree)
+ {
+ if(s_type == FTAM_F_INITIALIZE_REQUEST)
+ {
+ show_request_sequence_top(&asn,ftam_tree,tvb,pinfo,&offset,cp_type_len);
+ }
+ else
+ {
+ show_response_sequence_top(&asn,ftam_tree,tvb,pinfo,&offset,cp_type_len);
+ }
+
+ }
+ break;
+ case FTAM_F_SELECT_REQUEST:
+ case FTAM_F_CREATE_REQUEST:
+ proto_tree_add_uint(ftam_tree, hf_ftam_type, tvb, offset-1, 1, s_type);
+ if (read_length(&asn, ftam_tree, hf_cp_type_message_length, &cp_type_len)
+ != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
+ )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(ftam_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", cp_type_len,length);
+ }
+ return FALSE;
+ }
+ if(tree)
+ {
+ show_select_request(&asn,ftam_tree,tvb,pinfo,&offset,cp_type_len);
+ }
+ break;
+ case FTAM_F_OPEN_REQUEST:
+ proto_tree_add_uint(ftam_tree, hf_ftam_type, tvb, offset-1, 1, s_type);
+ if (read_length(&asn, ftam_tree, hf_cp_type_message_length, &cp_type_len)
+ != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
+ )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(ftam_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", cp_type_len,length);
+ }
+ return FALSE;
+ }
+ if(tree)
+ {
+ show_open_request(&asn,ftam_tree,tvb,pinfo,&offset,cp_type_len);
+ }
+ break;
+ case FTAM_F_READ_REQUEST:
+ case FTAM_F_WRITE_REQUEST:
+ proto_tree_add_uint(ftam_tree, hf_ftam_type, tvb, offset-1, 1, s_type);
+ if (read_length(&asn, ftam_tree, hf_cp_type_message_length, &cp_type_len)
+ != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
+ )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(ftam_tree, tvb, offset, -1,
+ "Wrong pdu.Need %u bytes but have %u", cp_type_len,length);
+ }
+ return FALSE;
+ }
+ if(tree)
+ {
+ show_read_write_request(&asn,ftam_tree,tvb,pinfo,&offset,cp_type_len);
+ }
+ break;
+
+ default:
+ {
+ proto_item *ms;
+ proto_tree *ftam_tree_ms = NULL;
+ /* back to type */
+ offset--;
+ /* get length */
+ if (read_length(&asn, ftam_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ ms = proto_tree_add_text(ftam_tree, tvb, offset, rest_len+(asn.offset-offset),
+ val_to_str(s_type, ftam_pdu_vals, "Unknown pdu type (0x%02x)"));
+ ftam_tree_ms = proto_item_add_subtree(ms, ett_ftam_ms);
+ offset+=rest_len+(asn.offset-offset)+1;
+ asn.offset=offset;
+ }
+ }
+/* close asn.1 stream */
+ asn1_close(&asn, &offset);
+
+ return offset;
+}
+
+/*
+* Dissect FTAM PDUs inside a PPDU.
+*/
+static void
+dissect_ftam(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint s_type;
+
+/* first, try to check length */
+/* do we have at least 2 bytes */
+ if (!tvb_bytes_exist(tvb, 0, 2))
+ {
+ proto_tree_add_text(tree, tvb, offset,tvb_reported_length_remaining(tvb,offset),
+ "User data");
+ return; /* no, it isn't a FTAM PDU */
+ }
+
+/* do we have spdu type from the session dissector? */
+ if( !pinfo->private_data )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Internal error:can't get spdu type from session dissector.");
+ return ;
+ }
+ }
+ else
+ {
+ session = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
+ if(session->spdu_type == 0 )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
+ return ;
+ }
+ }
+ }
+
+/* get type of tag */
+ s_type = tvb_get_guint8(tvb, offset);
+
+ /* check PDU type */
+ if(session->abort_type != DATA_BLOCK )
+ {
+ if (match_strval(s_type, ftam_pdu_vals) == NULL)
+ {
+ return ; /* no, it isn't a FTAM PDU */
+ }
+ }
+ else
+ {
+ if (match_strval(s_type, ftam_data_vals) == NULL)
+ {
+ return ; /* no, it isn't a FTAM PDU */
+ }
+ }
+
+ /* we can't make any additional checking here */
+ /* postpone it before dissector will have more information */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FTAM");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0)
+ {
+ offset = dissect_pdu(tvb, offset, pinfo, tree);
+ if(offset == FALSE )
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,"Internal error");
+ offset = tvb_length(tvb);
+ break;
+ }
+ }
+}
+
+void
+proto_register_ftam(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_ftam_type,
+ {
+ "PDU Type",
+ "ftam.type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(ftam_pdu_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_cp_type_message_length,
+ {
+ "Message Length",
+ "cp_type.message_length",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "CP type Message Length",
+ HFILL
+ }
+ },
+ {
+ &hf_protocol_version,
+ {
+ "Protocol version 1",
+ "ftam.protocol.version",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PROTOCOL_VERGION,
+ "Protocol version 1",
+ HFILL
+ }
+ },
+ {
+ &hf_functional_unit_read,
+ {
+ "Read",
+ "ftam.functional.units.read",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_READ,
+ "Read",
+ HFILL
+ }
+ },
+ {
+ &hf_functional_unit_write,
+ {
+ "Write",
+ "ftam.functional.units.write",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_WRITE,
+ "Write",
+ HFILL
+ }
+ },
+ {
+ &hf_functional_unit_file_access,
+ {
+ "File access",
+ "ftam.functional.units.file_access",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_FILE_ACCESS,
+ "File access",
+ HFILL
+ }
+ },
+ {
+ &hf_functional_unit_limited_file_management,
+ {
+ "Limited file management",
+ "ftam.functional.units.limited_file_management",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_LIMITED_FILE_MANAGEMENT,
+ "Limited file management",
+ HFILL
+ }
+ },
+ {
+ &hf_functional_unit_enhanced_file_management,
+ {
+ "Enhanced file management",
+ "ftam.functional.units.enhanced_file_management",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_ENHANCED_FILE_MANAGEMENT,
+ "Enhanced file management",
+ HFILL
+ }
+ },
+ {
+ &hf_functional_unit_grouping,
+ {
+ "Grouping",
+ "ftam.functional.units.grouping",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_GROUPING,
+ "Grouping",
+ HFILL
+ }
+ },
+ {
+ &hf_functional_unit_fadu_locking,
+ {
+ "Fadu locking",
+ "ftam.functional.units.fadu_locking",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FUNCTIONAL_FADU_LOCKING,
+ "Fadu locking",
+ HFILL
+ }
+ },
+ {
+ &hf_functional_unit_recovery,
+ {
+ "Recovery",
+ "ftam.functional.units.recovery",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_RECOVERY,
+ "Recovery",
+ HFILL
+ }
+ },
+ {
+ &hf_functional_unit_restart_data_transfer,
+ {
+ "Restart data transfer",
+ "ftam.functional.units.restart_data_transfer",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_RESTART_DATA_TRANSFER,
+ "Restart data transfer",
+ HFILL
+ }
+ },
+ {
+ &hf_service_class_unconstrained_class,
+ {
+ "Unconstrained class",
+ "ftam.functional.units.unconstrained_class",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_UNCONSTRAINED_CLASS,
+ "Unconstrained class",
+ HFILL
+ }
+ },
+ {
+ &hf_service_class_management_class,
+ {
+ "Management class",
+ "ftam.functional.units.management_class",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_MANAGEMENT_CLASS,
+ "Management class",
+ HFILL
+ }
+ },
+ {
+ &hf_service_class_transfer_class,
+ {
+ "Transfer class",
+ "ftam.functional.units.transfer_class",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_TRANSFER_CLASS,
+ "Transfer class",
+ HFILL
+ }
+ },
+ {
+ &hf_service_class_transfer_and_management_class,
+ {
+ "Transfer and management class",
+ "ftam.functional.units.transfer_and_management_class",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_TRANSFER_AND_MANAGEMENT_CLASS,
+ "Transfer and management class",
+ HFILL
+ }
+ },
+ {
+ &hf_service_class_access_class,
+ {
+ "Access class",
+ "ftam.functional.units.access_class",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_FUNCTIONAL_UNIT_ACESS_CLASS,
+ "access class",
+ HFILL
+ }
+ },
+ {
+ &hf_attribute_groups_storage,
+ {
+ "Storage",
+ "ftam.attribute.group.storage",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_ATTRIBUTE_GROUPS_STORAGE,
+ "Storage",
+ HFILL
+ }
+ },
+ {
+ &hf_attribute_groups_security,
+ {
+ "Security",
+ "ftam.attribute.group.security",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_ATTRIBUTE_GROUPS_SECURITY,
+ "Security",
+ HFILL
+ }
+ },
+ {
+ &hf_attribute_groups_private,
+ {
+ "Private",
+ "ftam.attribute.group.private",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_ATTRIBUTE_GROUPS_PRIVATE,
+ "Private",
+ HFILL
+ }
+ },
+ {
+ &hf_filename_attribute_read,
+ {
+ "Read",
+ "ftam.filename.attribute.read",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FILENAME_ATTRIBUTE_READ,
+ "Read",
+ HFILL
+ }
+ },
+ {
+ &hf_filename_attribute_insert,
+ {
+ "Insert",
+ "ftam.filename.attribute.insert",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FILENAME_ATTRIBUTE_INSERT,
+ "Insert",
+ HFILL
+ }
+ },
+ {
+ &hf_filename_attribute_replace,
+ {
+ "Replace",
+ "ftam.filename.attribute.replace",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FILENAME_ATTRIBUTE_REPLACE,
+ "Replace",
+ HFILL
+ }
+ },
+ {
+ &hf_filename_attribute_extend,
+ {
+ "Extend",
+ "ftam.filename.attribute.extend",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FILENAME_ATTRIBUTE_EXTEND,
+ "Extend",
+ HFILL
+ }
+ },
+ {
+ &hf_filename_attribute_erase,
+ {
+ "Erase",
+ "ftam.filename.attribute.erase",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FILENAME_ATTRIBUTE_ERASE,
+ "Erase",
+ HFILL
+ }
+ },
+ {
+ &hf_filename_attribute_read_attribute,
+ {
+ "Read attribute",
+ "ftam.filename.attribute.read_attribute",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FILENAME_ATTRIBUTE_READ_ATTRIBUTE,
+ "Read attribute",
+ HFILL
+ }
+ },
+ {
+ &hf_filename_attribute_change_attribute,
+ {
+ "Change attribute",
+ "ftam.filename.attribute.change_attribute",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FILENAME_ATTRIBUTE_CHANGE_ATTRIBUTE,
+ "Change attribute",
+ HFILL
+ }
+ },
+ {
+ &hf_filename_attribute_delete_file,
+ {
+ "Delete file",
+ "ftam.filename.attribute.delete_file",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_FILENAME_ATTRIBUTE_DELETE_FILE,
+ "Delete file",
+ HFILL
+ }
+ },
+ {
+ &hf_processing_mode_read,
+ {
+ "f-read",
+ "ftam.processing.mode.read",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PROCESSING_MODE_READ,
+ "f-read",
+ HFILL
+ }
+ },
+ {
+ &hf_processing_mode_replace,
+ {
+ "f-replace",
+ "ftam.processing.mode.replace",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PROCESSING_MODE_REPLACE,
+ "f-replace",
+ HFILL
+ }
+ },
+ {
+ &hf_processing_mode_insert,
+ {
+ "f-insert",
+ "ftam.processing.mode.insert",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PROCESSING_MODE_INSERT,
+ "f-insert",
+ HFILL
+ }
+ },
+ {
+ &hf_processing_mode_extend,
+ {
+ "f-extend",
+ "ftam.processing.mode.extend",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PROCESSING_MODE_EXTEND,
+ "f-extend",
+ HFILL
+ }
+ },
+ {
+ &hf_processing_mode_erase,
+ {
+ "f-erase",
+ "ftam.processing.mode.erase",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PROCESSING_MODE_ERASE,
+ "f-erase",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_attribute_read,
+ {
+ "Read",
+ "ftam.permitted.action.attribute.read",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_READ,
+ "Read",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_attribute_insert,
+ {
+ "Insert",
+ "ftam.permitted.action.attribute.insert",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_INSERT,
+ "Insert",
+ HFILL
+ }
+ },
+
+ {
+ &hf_permitted_action_attribute_replace,
+ {
+ "Replace",
+ "ftam.permitted.action.attribute.replace",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_REPLACE,
+ "Replace",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_attribute_extend,
+ {
+ "Extend",
+ "ftam.permitted.action.attribute.extend",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_EXTEND,
+ "Extend",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_attribute_erase,
+ {
+ "Erase",
+ "ftam.permitted.action.attribute.erase",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_ERASE,
+ "Erase",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_attribute_read_attribute,
+ {
+ "Read attribute",
+ "ftam.permitted.action.attribute.read.attribute",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_READ_ATTRIBUTE,
+ "Read attribute",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_attribute_change_attribute,
+ {
+ "Change attribute",
+ "ftam.permitted.action.attribute.read.attribute",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_CHANGE_ATTRIBUTE,
+ "Change attribute",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_attribute_delete_file,
+ {
+ "Delete file",
+ "ftam.permitted.action.attribute.delete.file",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_DELETE_FILE,
+ "Delete file",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_traversal,
+ {
+ "Traversal",
+ "ftam.permitted.action.attribute.traversal",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_TRAVERSAL,
+ "Traversal",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_reverse_traversal,
+ {
+ "Reverse traversal",
+ "ftam.permitted.action.attribute.reverse.traversal",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_REVERSE_TRAVERSAL,
+ "Reverse raversal",
+ HFILL
+ }
+ },
+ {
+ &hf_permitted_action_random_order,
+ {
+ "Random order",
+ "ftam.permitted.action.attribute.random.order",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_PERMITTED_ACTION_ATTRIBUTE_RANDOM_ORDER,
+ "Random order",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_filename,
+ {
+ "Read filename",
+ "ftam.nbs9.read.filename",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_FILENAME,
+ "Read filename",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_permitted_actions,
+ {
+ "Read permitted actions",
+ "ftam.nbs9.read.permitted.actions",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_PERMITTED_ACTIONS,
+ "Read permitted actions",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_contents_type,
+ {
+ "Read contents type",
+ "ftam.nbs9.read.contents.type",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_CONTENTS_TYPE,
+ "Read contents type",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_storage_account,
+ {
+ "Read storage account",
+ "ftam.nbs9.read.storage.account",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_STORAGE_ACCOUNT,
+ "Read storage account",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_date_and_time_of_creation,
+ {
+ "Read date and time of creation",
+ "ftam.nbs9.read.date.and.time.of.creation",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_DATE_AND_TIME_OF_CREATION,
+ "Read date and time of creation",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_date_and_time_of_last_modification,
+ {
+ "Read date and time of last modification",
+ "ftam.nbs9.read.date.and.time.of.last.modification",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_DATE_AND_TIME_OF_LAST_MODIFICATION,
+ "Read date and time of last modification",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_date_and_time_of_read_access,
+ {
+ "Read date and time of last read access",
+ "ftam.nbs9.read.date.and.time.of.last.read.access",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_DATE_AND_TIME_OF_LAST_READ_ACCESS,
+ "Read date and time of last read access",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_date_and_time_of_attribute_modification,
+ {
+ "Read date and time of last attribute modification",
+ "ftam.nbs9.read.date.and.time.of.last.attribute.modification",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_DATE_AND_TIME_OF_LAST_ATTRIBUTE_MODIFICATION,
+ "Read date and time of last attribute modification",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_identity_of_creator,
+ {
+ "Read identity of creator",
+ "ftam.nbs9.read.identity.of.creator",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_IDENTITY_OF_CREATOR,
+ "Read identity of creator",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_identity_of_last_modifier,
+ {
+ "Read identity of last modifier",
+ "ftam.nbs9.read.identity.of.last.modifier",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_IDENTITY_OF_LAST_MODIFIER,
+ "Read identity of last modifier",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_identity_of_last_reader,
+ {
+ "Read identity of last reader",
+ "ftam.nbs9.read.identity.of.last.reader",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_IDENTITY_OF_LAST_READER,
+ "Read identity of last reader",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_identity_of_last_attribute_modifier,
+ {
+ "Read identity of last attribute modifier",
+ "ftam.nbs9.read.identity.of.last.attribute.modifier",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_IDENTITY_OF_LAST_ATTRIBUTE_MODIFIER,
+ "Read identity of last attribute modifier",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_file_availability,
+ {
+ "Read file availability",
+ "ftam.nbs9.read.file.availability",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_FILE_AVAILABILITY,
+ "Read file availability",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_filesize,
+ {
+ "Read filesize",
+ "ftam.nbs9.read.file.filesize",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_FILESIZE,
+ "Read filesize",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_future_filesize,
+ {
+ "Read future filesize",
+ "ftam.nbs9.read.future.filesize",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_FUTURE_FILESIZE,
+ "Read future filesize",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_access_control,
+ {
+ "Read access control",
+ "ftam.nbs9.read.access_control",
+ FT_BOOLEAN, 16,
+ NULL,
+ FTAM_NBS9_READ_ACCESS_CONTROL,
+ "Read access control",
+ HFILL
+ }
+ },
+ {
+ &hf_nbs9_read_legal_qualifications,
+ {
+ "Read legal qualifications",
+ "ftam.nbs9.read.legal.qualifications",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_NBS9_READ_LEGAL_QUALIFICATIONS,
+ "Read legal qualifications",
+ HFILL
+ }
+ },
+
+ {
+ &hf_nbs9_read_private_use,
+ {
+ "Read private use",
+ "ftam.nbs9.read.private.use",
+ FT_BOOLEAN, 8,
+ NULL,
+ FTAM_NBS9_READ_PRIVATE_USE,
+ "Read private use",
+ HFILL
+ }
+ },
+ };
+ static gint *ett[] =
+ {
+ &ett_ftam,
+ &ett_ftam_param,
+ &ett_ftam_rc,
+ &ett_ftam_ms,
+ &ett_ftam_itm,
+ };
+ module_t *ftam_module;
+ proto_ftam = proto_register_protocol(PROTO_STRING_FTAM, "FTAM", "ftam");
+ proto_register_field_array(proto_ftam, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ftam_module = prefs_register_protocol(proto_ftam, NULL);
+}
+
+void
+proto_reg_handoff_ftam(void)
+{
+ dissector_handle_t ftam_handle;
+
+ /* find data dissector */
+ data_handle = find_dissector("data");
+ ftam_handle = create_dissector_handle(dissect_ftam,proto_ftam);
+ /* Register in acse oid table */
+ dissector_add_string("acse.application_context", "1.0.8571.1.1", ftam_handle);
+}
+
+
+
diff --git a/epan/dissectors/packet-ftam.h b/epan/dissectors/packet-ftam.h
new file mode 100644
index 0000000000..5c9fb8cafd
--- /dev/null
+++ b/epan/dissectors/packet-ftam.h
@@ -0,0 +1,430 @@
+/* packet-ftam.h
+*
+* Routine to dissect OSI ISO 8571 FTAM Protocol packets
+*
+* $Id$
+*
+* Yuriy Sidelnikov <YSidelnikov@hotmail.com>
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define PROTO_STRING_FTAM "OSI ISO 8571 FTAM Protocol"
+#define PROTO_STRING_FTAM_INFO "OSI ISO 8571 FTAM Protocol"
+
+/* asn.1 definitions */
+#define ASN1_CLASS_UNIVERSAL 0x00
+#define ASN1_CLASS_APPLICATION 0x40
+#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80
+#define ASN1_CLASS_Private 0xc0
+#define ASN1_CLASS_PC 0x20
+
+#define INTEGER_ITEM 0x01
+#define BOOLEAN_ITEM 0x01
+
+#define NBS9_OID 0x2b
+
+#define SEQUENCE 0x30
+
+/* sequence top */
+#define TAG_00 0
+#define TAG_01 1
+
+enum
+{
+FTAM_F_INITIALIZE_REQUEST = 0xa0,
+FTAM_F_INITIALIZE_RESPONSE,
+FTAM_F_TERMINATE_REQUEST,
+FTAM_F_TERMINATE_RESPONSE,
+FTAM_F_U_ABORT_REQUEST,
+FTAM_F_P_ABORT_REQUEST,
+FTAM_F_SELECT_REQUEST,
+FTAM_F_SELECT_RESPONSE,
+FTAM_F_DESELECT_REQUEST,
+FTAM_F_DESELECT_RESPONSE,
+FTAM_F_CREATE_REQUEST,
+FTAM_F_CREATE_RESPONSE,
+FTAM_F_DELETE_REQUEST,
+FTAM_F_DELETE_RESPONSE,
+FTAM_F_READ_ATTRIB_REQUEST,
+FTAM_F_READ_ATTRIB_RESPONSE,
+FTAM_F_CHANGE_ATTRIB_REQUEST,
+FTAM_F_CHANGE_ATTRIB_RESPONSE,
+FTAM_F_OPEN_REQUEST,
+FTAM_F_OPEN_RESPONSE,
+FTAM_F_CLOSE_REQUEST,
+FTAM_F_CLOSE_RESPONSE,
+FTAM_F_BEGIN_GROUP_REQUEST,
+FTAM_F_BEGIN_GROUP_RESPONSE,
+FTAM_F_END_GROUP_REQUEST,
+FTAM_F_END_GROUP_RESPONSE,
+FTAM_F_RECOVER_REQUEST,
+FTAM_F_RECOVER_RESPONSE,
+FTAM_F_LOCATE_REQUEST,
+FTAM_F_LOCATE_RESPONSE,
+FTAM_F_ERASE_REQUEST,
+FTAM_F_ERASE_RESPONSE
+};
+enum
+{
+FTAM_F_READ_REQUEST=0x20,
+FTAM_F_WRITE_REQUEST,
+FTAM_F_DATA_END_REQUEST,
+FTAM_F_TRANSFER_END_REQUEST,
+FTAM_F_TRANSFER_END_RESPONSE,
+FTAM_F_CANCEL_REQUEST,
+FTAM_F_CANCEL_RESPONSE,
+FTAM_F_REASTART_REQUEST,
+FTAM_F_REASTART_RESPONSE
+};
+enum
+{
+FTAM_PROTOCOL_VERSION,
+FTAM_IMPLEMENTATION_INFORMATION,
+FTAM_PRESENTATION_CONTEXT_MANAGEMENT,
+FTAM_SERVICE_CLASS,
+FTAM_FUNCTIONAL_UNITS,
+FTAM_ATTRIBUTE_GROUPS,
+FTAM_QUALITY_OF_SERVICE,
+FTAM_CONTENTS_TYPE_LIST
+};
+/* pseudo value */
+#define FTAM_CHECKPOINT_WINDOW 55
+#define FTAM_CHARGING 9
+enum
+{
+FTAM_DIAGNOSTIC_TYPE=0x80,
+FTAM_ERROR_IDENTIFIER,
+FTAM_ERROR_OBSERVER,
+FTAM_ERROR_SOURCE,
+FTAM_SUGGESTED_DELAY,
+FTAM_FURTHER_DETAILS
+};
+enum
+{
+FTAM_NO_CATEGORIZATION_POSSIBLE,
+FTAM_INITIATING_FILE_SERVICE_USER,
+FTAM_INITIATING_FILE_PROTOCOL_MASHINE,
+FTAM_SERVICE_SUPPORTING_THE_FILE_PROTOCOL_MACHINE,
+FTAM_RESPONDING_FILE_PROTOCOL_MASHINE,
+FTAM_RESPONDING_FILE_SERVICE_USER
+};
+enum
+{
+FTAM_DIAGNOSTIC_INFORMATIVE,
+FTAM_DIAGNOSTIC_TRANSIENT,
+FTAM_DIAGNOSTIC_PERMANENT
+};
+enum
+{
+FTAM_RESPONSE_STATE_SUCCESS,
+FTAM_RESPONSE_STATE_FAILURE
+};
+enum
+{
+FTAM_RESPONSE_ACTION_RESULT_SUCCESS,
+FTAM_RESPONSE_ACTION_RESULT_TRANSIENT_ERROR,
+FTAM_RESPONSE_ACTION_RESULT_PERMANENT_ERROR
+};
+enum
+{
+FTAM_PROCESSING_MODE,
+FTAM_CONTENTS_TYPE,
+FTAM_CONCURENCY_CONTROL,
+FTAM_ENABLE_FADU_LOCKING,
+FTAM_ACTIVITY_IDENTIFIER,
+FTAM_RECOVERY_MODE,
+FTAM_REMOTE_CONTEXTS,
+FTAM_DEFINE_CONTEXTS
+};
+enum
+{
+FTAM_CONTENTS_TYPE_UNKNOWN,
+FTAM_CONTENTS_TYPE_PROPOSED
+};
+enum
+{
+FTAM_CONTENTS_TYPE_PROPOSED_DOCUMENT_TYPE,
+FTAM_CONTENTS_TYPE_PROPOSED_CONSTRAINT_SET
+};
+enum
+{
+FTAM_CREATE_FAILURE,
+FTAM_SELECT_OLD_FILE,
+FTAM_DELETE_AND_CREATE_WITH_OLD_ATTRIBUTES,
+FTAM_DELETE_AND_CREATE_WITH_NEW_ATTRIBUTES
+};
+enum
+{
+FTAM_FADU_FIRST_LAST,
+FTAM_FADU_RELATIVE,
+FTAM_FADU_BEGIN_END,
+FTAM_FADU_SINGLE_NAME,
+FTAM_FADU_NAME_LIST,
+FTAM_FADU_FADU_NUMBER
+};
+enum
+{
+FTAM_FADU_FIRST,
+FTAM_FADU_LAST
+};
+enum
+{
+FTAM_FADU_PREVIOUS,
+FTAM_FADU_CURRENT,
+FTAM_FADU_NEXT
+};
+enum
+{
+FTAM_FADU_BEGIN,
+FTAM_FADU_END
+};
+enum
+{
+FTAM_HIERARCHICAL_ALL_DATA_UNITS,
+FTAM_HIERARCHICAL_NO_DATA_UNITS,
+FTAM_ALL_DATA_UNITS,
+FTAM_ONE_LEVEL_DATA_UNITS,
+FTAM_SINGLE_DATA_UNITS,
+FTAM_UNSTRUCTURED_ALL_DATA_UNITS,
+FTAM_UNSTRUCTURED_SINGLE_DATA_UNITS
+};
+enum
+{
+FTAM_ACCESS_INSERT,
+FTAM_ACCESS_REPLACE,
+FTAM_ACCESS_EXTEND
+};
+enum
+{
+FTAM_UNIVERSAL_CLASS_NUMBER,
+FTAM_MAXIMUM_STRING_LENGTH,
+FTAM_STRING_SIGNIFICANCE
+};
+enum
+{
+FTAM_VARIABLE,
+FTAM_FIXED,
+FTAM_NOT_SIGNIFICANT
+};
+enum
+{
+FTAM_READ_ATTRIBUTE_FILENAME,
+FTAM_READ_ATTRIBUTE_PERMITTED_ACTIONS,
+FTAM_READ_ATTRIBUTE_CONTENTS_TYPE,
+FTAM_READ_ATTRIBUTE_STORAGE_ACCOUNT,
+FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_CREATION,
+FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_LAST_MODIFICATION,
+FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_LAST_READ_ACCESS,
+FTAM_READ_ATTRIBUTE_DATA_AND_TIME_OF_LAST_ATTRIBUTE_MODIFICATION,
+FTAM_READ_ATTRIBUTE_IDENTITY_OF_CREATOR,
+FTAM_READ_ATTRIBUTE_IDENTITY_OF_LAST_MODIFIER,
+FTAM_READ_ATTRIBUTE_IDENTITY_OF_LAST_READER,
+FTAM_READ_ATTRIBUTE_IDENTITY_OF_LAST_ATTRIBUTE_MODIFIER,
+FTAM_READ_ATTRIBUTE_FILE_AVAILABILITY,
+FTAM_READ_ATTRIBUTE_FILESIZE,
+FTAM_READ_ATTRIBUTE_FUTURE_FILESIZE,
+FTAM_READ_ATTRIBUTE_ACCESS_CONTROL,
+FTAM_READ_ATTRIBUTE_LEGAL_QUALIFICATION,
+FTAM_READ_ATTRIBUTE_PRIVATE_USE
+};
+
+
+#define FTAM_DATE_AND_TIME_NO_VALUE_AVAILABLE 0x00
+#define FTAM_DATE_AND_TIME_ACTUAL_VALUE 0x01
+
+#define FTAM_DATE_IDENTITY_NO_VALUE_AVAILABLE 0x00
+#define FTAM_DATE_IDENTITY_ACTUAL_VALUE 0x01
+
+
+#define FTAM_USER_IDENTITY 22
+
+#define FTAM_PRINTABLE_LENGTH 19
+#define FTAM_GRAPHIC_STRING 25
+#define FTAM_TELEX_STRING 20
+#define FTAM_VIDEO_STRING 21
+#define FTAM_IA5_STRING 22
+#define FTAM_VISIBLE_STRING 26
+#define FTAM_GENERAL_STRING 27
+#define FTAM_OCTET_STRING 04
+#define FTAM_PRINTABLE_STRING 05
+#define FTAM_NODE_DESCRIPTOR_DATA_ELEMENT 0xa0
+#define FTAM_ENTER_SUBTREE_DATA_ELEMENT 0xa1
+#define FTAM_EXIT_SUBTREE_DATA_ELEMENT 0xa2
+#define FTAM_DATATYPE_NBS9 0xe2
+
+#define FTAM_CONTENTS_TYPE_PROPOSED_DOCUMENT_TYPE_NAME 14
+#define FTAM_CONTENTS_TYPE_PROPOSED_DOCUMENT_TYPE_PARAMETER 0
+
+#define FTAM_PROCESSING_MODE_READ 0x0080
+#define FTAM_PROCESSING_MODE_REPLACE 0x0040
+#define FTAM_PROCESSING_MODE_INSERT 0x0020
+#define FTAM_PROCESSING_MODE_EXTEND 0x0010
+#define FTAM_PROCESSING_MODE_ERASE 0x0008
+
+
+#define FTAM_NBS9_READ_FILENAME 0x8000
+#define FTAM_NBS9_READ_PERMITTED_ACTIONS 0x4000
+#define FTAM_NBS9_READ_CONTENTS_TYPE 0x2000
+#define FTAM_NBS9_READ_STORAGE_ACCOUNT 0x1000
+#define FTAM_NBS9_READ_DATE_AND_TIME_OF_CREATION 0x0800
+#define FTAM_NBS9_READ_DATE_AND_TIME_OF_LAST_MODIFICATION 0x0400
+#define FTAM_NBS9_READ_DATE_AND_TIME_OF_LAST_READ_ACCESS 0x0200
+#define FTAM_NBS9_READ_DATE_AND_TIME_OF_LAST_ATTRIBUTE_MODIFICATION 0x0100
+#define FTAM_NBS9_READ_IDENTITY_OF_CREATOR 0x0080
+#define FTAM_NBS9_READ_IDENTITY_OF_LAST_MODIFIER 0x0040
+#define FTAM_NBS9_READ_IDENTITY_OF_LAST_READER 0x0020
+#define FTAM_NBS9_READ_IDENTITY_OF_LAST_ATTRIBUTE_MODIFIER 0x0010
+#define FTAM_NBS9_READ_FILE_AVAILABILITY 0x0008
+#define FTAM_NBS9_READ_FILESIZE 0x0004
+#define FTAM_NBS9_READ_FUTURE_FILESIZE 0x0002
+#define FTAM_NBS9_READ_ACCESS_CONTROL 0x0001
+#define FTAM_NBS9_READ_LEGAL_QUALIFICATIONS 0x80
+#define FTAM_NBS9_READ_PRIVATE_USE 0x40
+
+
+
+#define FTAM_SELECT_ATTRIBUTES 19
+#define FTAM_CREATE_ATTRIBUTES 12
+#define FTAM_ACCESS_REQUEST 3
+#define FTAM_ACCSESS_PASSWORDS 2
+#define FTAM_OVERRIDE 0
+
+#define FTAM_ACCSESS_PASSWORDS 2
+
+#define FTAM_READ_ATTRIBUTES 18
+
+
+
+#define FTAM_CREATE_FILENAME_ATTRIBUTES 0
+#define FTAM_CREATE_PERMITTED_ACTIONS_ATTRIBUTE 1
+#define FTAM_CREATE_CONTENTS_TYPE 2
+#define FTAM_CREATE_ACCOUNT_ATTRIBUTE 3
+#define FTAM_CREATE_FILE_AVAILABILITY_ATTRIBUTE 12
+#define FTAM_CREATE_FILESIZE_ATTRIBUTE 14
+#define FTAM_CREATE_ACCESS_CONTROL_ATTRIBUTE 15
+#define FTAM_CREATE_ACCESS_LEGAL_AUALIFICATION_ATTRIBUTE 16
+#define FTAM_CREATE_ACCESS_PRIVATE_USE_ATTRIBUTE 17
+
+#define FTAM_FILE_ACCESS_DATA_UNIT_IDENTITY 15
+#define FTAM_FILE_ACCESS_CONTEXT 1
+#define FTAM_FILE_FADU_LOCK 16
+#define FTAM_FILE_ACCESS_DATA_UNIT_OPERATION 0
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_READ 0x8000
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_INSERT 0x4000
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_REPLACE 0x2000
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_EXTEND 0x1000
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_ERASE 0x0800
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_READ_ATTRIBUTE 0x0400
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_CHANGE_ATTRIBUTE 0x0200
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_DELETE_FILE 0x0100
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_TRAVERSAL 0x0080
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_REVERSE_TRAVERSAL 0x0040
+#define FTAM_PERMITTED_ACTION_ATTRIBUTE_RANDOM_ORDER 0x0020
+
+
+#define FTAM_ACCOUNT 8
+#define FTAM_FILESTORE_PASSWORD 17
+#define FTAM_SHARED_ASE_INFORMATION 20
+#define FTAM_INITIATOR_IDENTIFY 22
+#define FTAM_DOCUMENT_TYPE 0x4e
+
+#define FTAM_ABSTRACT_SYNTAX_NAME 0x40
+
+
+/* filename attributes */
+#define FTAM_FILENAME_ATTRIBUTE_READ 0x0080
+#define FTAM_FILENAME_ATTRIBUTE_INSERT 0x0040
+#define FTAM_FILENAME_ATTRIBUTE_REPLACE 0x0020
+#define FTAM_FILENAME_ATTRIBUTE_EXTEND 0x0010
+#define FTAM_FILENAME_ATTRIBUTE_ERASE 0x0008
+#define FTAM_FILENAME_ATTRIBUTE_READ_ATTRIBUTE 0x0004
+#define FTAM_FILENAME_ATTRIBUTE_CHANGE_ATTRIBUTE 0x0002
+#define FTAM_FILENAME_ATTRIBUTE_DELETE_FILE 0x0001
+
+
+
+#define IMPLEMENTATION_INFORMATION 29
+#define USER_INFORMATION 30
+
+#define ftam_EXTERNAL 8
+
+#define FTAM_RESPONSE_STATE_RESULT 21
+/* dummy entry */
+#define FTAM_RESPONSE_ACTION_RESULT 555
+#define FTAM_RESPONSE_SHARED_ASE_INFORMATION 20
+#define FTAM_RESPONSE_DIAGNOSTIC 13
+
+/* definition list **/
+#define PRESENTATION_CONTEXT_IDENTIFIER 2
+#define ABSTRACT_SYNTAX_NAME 6
+#define TRANSFER_SYNTAX_NAMES 0x30
+/* result list */
+#define PRESENTATION_RESULT 0x80
+#define PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME 0x81
+#define PRESENTATION_RESULT_INTEGER 0x82
+
+/* result values */
+#define PRESENTATION_RESULT_ACCEPTANCE 0
+#define PRESENTATION_RESULT_USER_REJECTION 1
+#define PRESENTATION_RESULT_PROVIDER_REJECTION 2
+
+
+/* user data */
+#define SIMPLY_ENCODED_DATA 0x60
+#define FULLY_ENCODED_DATA 0x61
+
+
+
+#define FTAM_PROTOCOL_VERGION 0x0080
+
+/* functional units */
+#define FTAM_FUNCTIONAL_UNIT_READ 0x2000
+#define FTAM_FUNCTIONAL_UNIT_WRITE 0x1000
+#define FTAM_FUNCTIONAL_UNIT_FILE_ACCESS 0x0800
+#define FTAM_FUNCTIONAL_UNIT_LIMITED_FILE_MANAGEMENT 0x0400
+#define FTAM_FUNCTIONAL_UNIT_ENHANCED_FILE_MANAGEMENT 0x0200
+#define FTAM_FUNCTIONAL_UNIT_GROUPING 0x0100
+#define FTAM_FUNCTIONAL_FADU_LOCKING 0x0080
+#define FTAM_FUNCTIONAL_UNIT_RECOVERY 0x0040
+#define FTAM_FUNCTIONAL_UNIT_RESTART_DATA_TRANSFER 0x0020
+
+/* service classes */
+#define FTAM_FUNCTIONAL_UNIT_UNCONSTRAINED_CLASS 0x80
+#define FTAM_FUNCTIONAL_UNIT_MANAGEMENT_CLASS 0x40
+#define FTAM_FUNCTIONAL_UNIT_TRANSFER_CLASS 0x20
+#define FTAM_FUNCTIONAL_UNIT_TRANSFER_AND_MANAGEMENT_CLASS 0x10
+#define FTAM_FUNCTIONAL_UNIT_ACESS_CLASS 0x08
+
+/* attribute group */
+#define FTAM_ATTRIBUTE_GROUPS_STORAGE 0x80
+#define FTAM_ATTRIBUTE_GROUPS_SECURITY 0x40
+#define FTAM_ATTRIBUTE_GROUPS_PRIVATE 0x20
+
+#define DATA_BULK_PDU 0xbf
+#define MAXSTRING 256
+#define ABORT_REASON_LEN 3
+
+
+
+#define GRAPHIC_STRING "Graphic string"
+
+
+
+
diff --git a/epan/dissectors/packet-ftp.c b/epan/dissectors/packet-ftp.c
new file mode 100644
index 0000000000..1084e05720
--- /dev/null
+++ b/epan/dissectors/packet-ftp.c
@@ -0,0 +1,644 @@
+/* packet-ftp.c
+ * Routines for ftp packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ * Copyright 2001, Juan Toledo <toledo@users.sourceforge.net> (Passive FTP)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/conversation.h>
+
+static int proto_ftp = -1;
+static int proto_ftp_data = -1;
+static int hf_ftp_response = -1;
+static int hf_ftp_request = -1;
+static int hf_ftp_request_command = -1;
+static int hf_ftp_request_arg = -1;
+static int hf_ftp_response_code = -1;
+static int hf_ftp_response_arg = -1;
+static int hf_ftp_pasv_ip = -1 ;
+static int hf_ftp_pasv_port = -1;
+static int hf_ftp_pasv_nat = -1;
+static int hf_ftp_active_ip = -1;
+static int hf_ftp_active_port = -1;
+static int hf_ftp_active_nat = -1;
+
+static gint ett_ftp = -1;
+static gint ett_ftp_reqresp = -1;
+static gint ett_ftp_data = -1;
+
+static dissector_handle_t ftpdata_handle;
+
+#define TCP_PORT_FTPDATA 20
+#define TCP_PORT_FTP 21
+
+static const value_string response_table[] = {
+ { 110, "Restart marker reply" },
+ { 120, "Service ready in nnn minutes" },
+ { 125, "Data connection already open; transfer starting" },
+ { 150, "File status okay; about to open data connection" },
+ { 200, "Command okay" },
+ { 202, "Command not implemented, superfluous at this site" },
+ { 211, "System status, or system help reply" },
+ { 212, "Directory status" },
+ { 213, "File status" },
+ { 214, "Help message" },
+ { 215, "NAME system type" },
+ { 220, "Service ready for new user" },
+ { 221, "Service closing control connection" },
+ { 225, "Data connection open; no transfer in progress" },
+ { 226, "Closing data connection" },
+ { 227, "Entering Passive Mode" },
+ { 230, "User logged in, proceed" },
+ { 250, "Requested file action okay, completed" },
+ { 257, "PATHNAME created" },
+ { 331, "User name okay, need password" },
+ { 332, "Need account for login" },
+ { 350, "Requested file action pending further information" },
+ { 421, "Service not available, closing control connection" },
+ { 425, "Can't open data connection" },
+ { 426, "Connection closed; transfer aborted" },
+ { 450, "Requested file action not taken" },
+ { 451, "Requested action aborted: local error in processing" },
+ { 452, "Requested action not taken. Insufficient storage space in system" },
+ { 500, "Syntax error, command unrecognized" },
+ { 501, "Syntax error in parameters or arguments" },
+ { 502, "Command not implemented" },
+ { 503, "Bad sequence of commands" },
+ { 504, "Command not implemented for that parameter" },
+ { 530, "Not logged in" },
+ { 532, "Need account for storing files" },
+ { 550, "Requested action not taken: File unavailable" },
+ { 551, "Requested action aborted: page type unknown" },
+ { 552, "Requested file action aborted: Exceeded storage allocation" },
+ { 553, "Requested action not taken: File name not allowed" },
+ { 0, NULL }
+};
+
+static void
+dissect_ftpdata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/*
+ * Parse the address and port information in a PORT command or in the
+ * response to a PASV command. Return TRUE if we found an address and
+ * port, and supply the address and port; return FALSE if we didn't find
+ * them.
+ *
+ * We ignore the IP address in the reply, and use the address from which
+ * the request came.
+ *
+ * XXX - are there cases where they differ? What if the FTP server is
+ * behind a NAT box, so that the address it puts into the reply isn't
+ * the address at which you should contact it? Do all NAT boxes detect
+ * FTP PASV replies and rewrite the address? (I suspect not.)
+ *
+ * RFC 959 doesn't say much about the syntax of the 227 reply.
+ *
+ * A proposal from Dan Bernstein at
+ *
+ * http://cr.yp.to/ftp/retr.html
+ *
+ * "recommend[s] that clients use the following strategy to parse the
+ * response line: look for the first digit after the initial space; look
+ * for the fourth comma after that digit; read two (possibly negative)
+ * integers, separated by a comma; the TCP port number is p1*256+p2, where
+ * p1 is the first integer modulo 256 and p2 is the second integer modulo
+ * 256."
+ *
+ * wget 1.5.3 looks for a digit, although it doesn't handle negative
+ * integers.
+ *
+ * The FTP code in the source of the cURL library, at
+ *
+ * http://curl.haxx.se/lxr/source/lib/ftp.c
+ *
+ * says that cURL "now scans for a sequence of six comma-separated numbers
+ * and will take them as IP+port indicators"; it loops, doing "sscanf"s
+ * looking for six numbers separated by commas, stepping the start pointer
+ * in the scanf one character at a time - i.e., it tries rather exhaustively.
+ *
+ * An optimization would be to scan for a digit, and start there, and if
+ * the scanf doesn't find six values, scan for the next digit and try
+ * again; this will probably succeed on the first try.
+ *
+ * The cURL code also says that "found reply-strings include":
+ *
+ * "227 Entering Passive Mode (127,0,0,1,4,51)"
+ * "227 Data transfer will passively listen to 127,0,0,1,4,51"
+ * "227 Entering passive mode. 127,0,0,1,4,51"
+ *
+ * so it appears that you can't assume there are parentheses around
+ * the address and port number.
+ */
+static gboolean
+parse_port_pasv(const guchar *line, int linelen, guint32 *ftp_ip,
+ guint16 *ftp_port)
+{
+ char *args;
+ char *p;
+ guchar c;
+ int i;
+ int address[4], port[2];
+ gboolean ret = FALSE;
+
+ /*
+ * Copy the rest of the line into a null-terminated buffer.
+ */
+ args = g_malloc(linelen + 1);
+ memcpy(args, line, linelen);
+ args[linelen] = '\0';
+ p = args;
+
+ for (;;) {
+ /*
+ * Look for a digit.
+ */
+ while ((c = *p) != '\0' && !isdigit(c))
+ p++;
+
+ if (*p == '\0') {
+ /*
+ * We ran out of text without finding anything.
+ */
+ break;
+ }
+
+ /*
+ * See if we have six numbers.
+ */
+ i = sscanf(p, "%d,%d,%d,%d,%d,%d",
+ &address[0], &address[1], &address[2], &address[3],
+ &port[0], &port[1]);
+ if (i == 6) {
+ /*
+ * We have a winner!
+ */
+ *ftp_port = ((port[0] & 0xFF)<<8) | (port[1] & 0xFF);
+ *ftp_ip = g_htonl((address[0] << 24) | (address[1] <<16) | (address[2] <<8) | address[3]);
+ ret = TRUE;
+ break;
+ }
+
+ /*
+ * Well, that didn't work. Skip the first number we found,
+ * and keep trying.
+ */
+ while ((c = *p) != '\0' && isdigit(c))
+ p++;
+ }
+
+ g_free(args);
+ return ret;
+}
+
+static void
+dissect_ftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gboolean is_request;
+ proto_tree *ftp_tree = NULL;
+ proto_tree *reqresp_tree = NULL;
+ proto_item *ti;
+ gint offset = 0;
+ const guchar *line;
+ guint32 code;
+ gchar code_str[4];
+ gboolean is_port_request = FALSE;
+ gboolean is_pasv_response = FALSE;
+ gint next_offset;
+ int linelen;
+ int tokenlen;
+ const guchar *next_token;
+ guint32 pasv_ip;
+ guint32 ftp_ip;
+ guint16 ftp_port;
+ address ftp_ip_address;
+ gboolean ftp_nat;
+ conversation_t *conversation;
+
+ ftp_ip_address = pinfo->src;
+
+ if (pinfo->match_port == pinfo->destport)
+ is_request = TRUE;
+ else
+ is_request = FALSE;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FTP");
+
+ /*
+ * Find the end of the first line.
+ *
+ * Note that "tvb_find_line_end()" will return a value that is
+ * not longer than what's in the buffer, so the "tvb_get_ptr()"
+ * call won't throw an exception.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ line = tvb_get_ptr(tvb, offset, linelen);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary
+ * (but leave out the line terminator).
+ */
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
+ is_request ? "Request" : "Response",
+ format_text(line, linelen));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ftp, tvb, offset, -1,
+ FALSE);
+ ftp_tree = proto_item_add_subtree(ti, ett_ftp);
+
+ if (is_request) {
+ proto_tree_add_boolean_hidden(ftp_tree,
+ hf_ftp_request, tvb, 0, 0, TRUE);
+ proto_tree_add_boolean_hidden(ftp_tree,
+ hf_ftp_response, tvb, 0, 0, FALSE);
+ } else {
+ proto_tree_add_boolean_hidden(ftp_tree,
+ hf_ftp_request, tvb, 0, 0, FALSE);
+ proto_tree_add_boolean_hidden(ftp_tree,
+ hf_ftp_response, tvb, 0, 0, TRUE);
+ }
+
+ /*
+ * Put the line into the protocol tree.
+ */
+ ti = proto_tree_add_text(ftp_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ reqresp_tree = proto_item_add_subtree(ti, ett_ftp_reqresp);
+ }
+
+ if (is_request) {
+ /*
+ * Extract the first token, and, if there is a first
+ * token, add it as the request.
+ */
+ tokenlen = get_token_len(line, line + linelen, &next_token);
+ if (tokenlen != 0) {
+ if (tree) {
+ proto_tree_add_item(reqresp_tree,
+ hf_ftp_request_command, tvb, offset,
+ tokenlen, FALSE);
+ }
+ if (strncmp(line, "PORT", tokenlen) == 0)
+ is_port_request = TRUE;
+ }
+ } else {
+ /*
+ * This is a response; the response code is 3 digits,
+ * followed by a space or hyphen, possibly followed by
+ * text.
+ *
+ * If the line doesn't start with 3 digits, it's part of
+ * a continuation.
+ *
+ * XXX - keep track of state in the first pass, and
+ * treat non-continuation lines not beginning with digits
+ * as errors?
+ */
+ if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1])
+ && isdigit(line[2])) {
+ /*
+ * One-line reply, or first or last line
+ * of a multi-line reply.
+ */
+ tvb_get_nstringz0(tvb, offset, sizeof(code_str), code_str);
+ code = strtoul(code_str, NULL, 10);
+
+ if (tree) {
+ proto_tree_add_uint(reqresp_tree,
+ hf_ftp_response_code, tvb, offset, 3, code);
+ }
+
+ /*
+ * See if it's a passive-mode response.
+ *
+ * XXX - check for "229" responses to EPSV
+ * commands, to handle IPv6, as per RFC 2428?
+ *
+ * XXX - does anybody do FOOBAR, as per RFC
+ * 1639, or has that been supplanted by RFC 2428?
+ */
+ if (code == 227)
+ is_pasv_response = TRUE;
+
+ /*
+ * Skip the 3 digits and, if present, the
+ * space or hyphen.
+ */
+ if (linelen >= 4)
+ next_token = line + 4;
+ else
+ next_token = line + linelen;
+ } else {
+ /*
+ * Line doesn't start with 3 digits; assume it's
+ * a line in the middle of a multi-line reply.
+ */
+ next_token = line;
+ }
+ }
+ offset += next_token - line;
+ linelen -= next_token - line;
+ line = next_token;
+
+ if (tree) {
+ /*
+ * Add the rest of the first line as request or
+ * reply data.
+ */
+ if (linelen != 0) {
+ if (is_request) {
+ proto_tree_add_item(reqresp_tree,
+ hf_ftp_request_arg, tvb, offset,
+ linelen, FALSE);
+ } else {
+ proto_tree_add_item(reqresp_tree,
+ hf_ftp_response_arg, tvb, offset,
+ linelen, FALSE);
+ }
+ }
+ offset = next_offset;
+ }
+
+ /*
+ * If this is a PORT request or a PASV response, handle it.
+ */
+ if (is_port_request) {
+ if (parse_port_pasv(line, linelen, &ftp_ip,
+ &ftp_port)) {
+ if (tree) {
+ proto_tree_add_ipv4(reqresp_tree,
+ hf_ftp_active_ip, tvb, 0, 0,
+ ftp_ip);
+ proto_tree_add_uint(reqresp_tree,
+ hf_ftp_active_port, tvb, 0, 0,
+ ftp_port);
+ }
+ SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4,
+ (const guint8 *)&ftp_ip);
+ ftp_nat = !ADDRESSES_EQUAL(&pinfo->src,
+ &ftp_ip_address);
+ if (ftp_nat) {
+ if (tree) {
+ proto_tree_add_boolean(
+ reqresp_tree,
+ hf_ftp_active_nat, tvb,
+ 0, 0, ftp_nat);
+ }
+ }
+ }
+ }
+
+ if (is_pasv_response) {
+ if (linelen != 0) {
+ /*
+ * This frame contains a PASV response; set up a
+ * conversation for the data.
+ */
+ if (parse_port_pasv(line, linelen, &pasv_ip,
+ &ftp_port)) {
+ if (tree) {
+ proto_tree_add_ipv4(reqresp_tree,
+ hf_ftp_pasv_ip, tvb, 0, 0, pasv_ip);
+ proto_tree_add_uint(reqresp_tree,
+ hf_ftp_pasv_port, tvb, 0, 0,
+ ftp_port);
+ }
+ SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4,
+ (const guint8 *)&pasv_ip);
+ ftp_nat = !ADDRESSES_EQUAL(&pinfo->src,
+ &ftp_ip_address);
+ if (ftp_nat) {
+ if (tree) {
+ proto_tree_add_boolean(reqresp_tree,
+ hf_ftp_pasv_nat, tvb, 0, 0,
+ ftp_nat);
+ }
+ }
+
+ /*
+ * We use "ftp_ip_address", so that if
+ * we're NAT'd we look for the un-NAT'd
+ * connection.
+ *
+ * XXX - should this call to
+ * "find_conversation()" just use
+ * "ftp_ip_address" and "server_port", and
+ * wildcard everything else?
+ */
+ conversation = find_conversation(&ftp_ip_address,
+ &pinfo->dst, PT_TCP, ftp_port, 0,
+ NO_PORT_B);
+ if (conversation == NULL) {
+ /*
+ * XXX - should this call to
+ * "conversation_new()" just use
+ * "ftp_ip_address" and "server_port",
+ * and wildcard everything else?
+ *
+ * XXX - what if we did find a
+ * conversation? As we create it
+ * only on the first pass through
+ * the packets, if we find one, it's
+ * presumably an unrelated conversation.
+ * Should we remove the old one from
+ * the hash table and put this one in
+ * its place? Can the conversation
+ * code handle conversations not in
+ * the hash table? Or should we
+ * make conversations support
+ * start and end frames, as circuits
+ * do, and treat this as an indication
+ * that one conversation was closed
+ * and a new one was opened?
+ */
+ conversation = conversation_new(
+ &ftp_ip_address, &pinfo->dst,
+ PT_TCP, ftp_port, 0, NO_PORT2);
+ conversation_set_dissector(conversation,
+ ftpdata_handle);
+ }
+ }
+ }
+ }
+
+ if (tree) {
+ /*
+ * Show the rest of the request or response as text,
+ * a line at a time.
+ * XXX - only if there's a continuation indicator?
+ */
+ while (tvb_offset_exists(tvb, offset)) {
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1,
+ &next_offset, FALSE);
+
+ /*
+ * Put this line.
+ */
+ proto_tree_add_text(ftp_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ offset = next_offset;
+ }
+ }
+}
+
+static void
+dissect_ftpdata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ti, *ftp_data_tree;
+ int data_length;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FTP-DATA");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "FTP Data: %u bytes",
+ tvb_reported_length(tvb));
+ }
+
+ if (tree) {
+ data_length = tvb_length(tvb);
+
+ ti = proto_tree_add_item(tree, proto_ftp_data, tvb, 0, -1,
+ FALSE);
+ ftp_data_tree = proto_item_add_subtree(ti, ett_ftp_data);
+
+ /*
+ * XXX - if this is binary data, it'll produce
+ * a *really* long line.
+ */
+ proto_tree_add_text(ftp_data_tree, tvb, 0, data_length,
+ "FTP Data: %s", tvb_format_text(tvb, 0, data_length));
+ }
+}
+
+void
+proto_register_ftp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ftp_response,
+ { "Response", "ftp.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if FTP response", HFILL }},
+
+ { &hf_ftp_request,
+ { "Request", "ftp.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if FTP request", HFILL }},
+
+ { &hf_ftp_request_command,
+ { "Request command", "ftp.request.command",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ftp_request_arg,
+ { "Request arg", "ftp.request.arg",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ftp_response_code,
+ { "Response code", "ftp.response.code",
+ FT_UINT32, BASE_DEC, VALS(response_table), 0x0,
+ "", HFILL }},
+
+ { &hf_ftp_response_arg,
+ { "Response arg", "ftp.response.arg",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ftp_pasv_ip,
+ { "Passive IP address", "ftp.passive.ip",
+ FT_IPv4, BASE_NONE, NULL,0x0,
+ "Passive IP address (check NAT)", HFILL}},
+
+ { &hf_ftp_pasv_port,
+ { "Passive port", "ftp.passive.port",
+ FT_UINT16, BASE_DEC, NULL,0x0,
+ "Passive FTP server port", HFILL }},
+
+ { &hf_ftp_pasv_nat,
+ {"Passive IP NAT", "ftp.passive.nat",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "NAT is active SIP and passive IP different", HFILL }},
+
+ { &hf_ftp_active_ip,
+ { "Active IP address", "ftp.active.cip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Active FTP client IP address", HFILL }},
+
+ { &hf_ftp_active_port,
+ {"Active port", "ftp.active.port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Active FTP client port", HFILL }},
+
+ { &hf_ftp_active_nat,
+ { "Active IP NAT", "ftp.active.nat",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "NAT is active", HFILL}}
+
+ };
+ static gint *ett[] = {
+ &ett_ftp,
+ &ett_ftp_reqresp,
+ &ett_ftp_data,
+ };
+
+ proto_ftp = proto_register_protocol("File Transfer Protocol (FTP)", "FTP",
+ "ftp");
+ proto_ftp_data = proto_register_protocol("FTP Data", "FTP-DATA", "ftp-data");
+ proto_register_field_array(proto_ftp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ftpdata_handle = create_dissector_handle(dissect_ftpdata, proto_ftp_data);
+}
+
+void
+proto_reg_handoff_ftp(void)
+{
+ dissector_handle_t ftpdata_handle, ftp_handle;
+
+ ftpdata_handle = create_dissector_handle(dissect_ftpdata, proto_ftp_data);
+ dissector_add("tcp.port", TCP_PORT_FTPDATA, ftpdata_handle);
+ ftp_handle = create_dissector_handle(dissect_ftp, proto_ftp);
+ dissector_add("tcp.port", TCP_PORT_FTP, ftp_handle);
+}
diff --git a/epan/dissectors/packet-fw1.c b/epan/dissectors/packet-fw1.c
new file mode 100644
index 0000000000..d1c35aa67a
--- /dev/null
+++ b/epan/dissectors/packet-fw1.c
@@ -0,0 +1,300 @@
+/* packet-fw1.c
+ * Routines for Ethernet header disassembly of FW1 "monitor" files
+ * Copyright 2002,2003, Alfred Koebler <ako@icon.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Alfred Koebler <ako@icon.de>
+ * Copyright 2002,2003 Alfred Koebler
+ *
+ * To use this dissector use the command line option
+ * -o eth.interpret_as_fw1_monitor:TRUE
+ *
+ * At the moment the way with the option is the best one.
+ * A automatic way is not possible, because the file format isn't different
+ * to the snoop file.
+ *
+ * With "fw monitor" it is possible to collect packets on several places.
+ * The additional information:
+ * - is it a incoming or outgoing packet
+ * - is it before or after the firewall
+ * i incoming before the firewall
+ * I incoming after the firewall
+ * o outcoming before the firewall
+ * O outcoming after the firewall
+ * - the name of the interface
+ *
+ * What's the problem ?
+ * Think about one packet traveling across the firewall.
+ * With ethereal you will see 4 lines in the Top Pane.
+ * To analyze a problem it is helpful to see the additional information
+ * in the protocol tree of the Middle Pane.
+ *
+ * The presentation of the summary line is designed in the following way:
+ * Every time the next selected packet in the Top Pane includes a
+ * "new" interface name the name is added to the list in the summary line.
+ * The interface names are listed one after the other.
+ * The position of the interface names didn't change.
+ *
+ * And who are the 4 places represented ?
+ * The interface name represents the firewall module of the interface.
+ * On the left side of the interface name is the interface module.
+ * On the right side of the interface name is the "IP" module.
+ *
+ * Example for a ping from the firewall to another host:
+ * For the four lines in the Top Pane you will see the according lines
+ * in the Middle Pane:
+ * El90x1 o
+ * O El90x1
+ * i El90x1
+ * El90x1 I
+ *
+ * Example for a packet traversing through the Firewall, first through
+ * the inner side firewall module then through the outer side firewall module:
+ * i El90x1 El90x2
+ * El90x1 I El90x2
+ * El90x1 o E190x2
+ * El90x1 E190x2 O
+ *
+ * 9.12.2002
+ * Add new column with summary of FW-1 interface/direction
+ *
+ * 11.8.2003
+ * Additional interpretation of field Chain Position.
+ * Show the chain position in the interface list.
+ * Support for new format of fw monitor file
+ * writen by option -u | -s for UUID/SUUID.
+ * NOTICE: First paket will have UUID == 0 !
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "etypes.h"
+
+/* Place FW1 summary in proto tree */
+static gboolean fw1_summary_in_tree = TRUE;
+static gboolean fw1_with_uuid = FALSE;
+static gboolean fw1_iflist_with_chain = FALSE;
+
+/* Initialize the protocol and registered fields */
+static int proto_fw1 = -1;
+static int hf_fw1_direction = -1;
+static int hf_fw1_chain = -1;
+static int hf_fw1_interface = -1;
+static int hf_fw1_uuid = -1;
+static int hf_fw1_type = -1;
+static int hf_fw1_trailer = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_fw1 = -1;
+
+#define ETH_HEADER_SIZE 14
+
+static dissector_handle_t eth_handle;
+
+
+#define MAX_INTERFACES 20
+static char *p_interfaces[MAX_INTERFACES];
+static int interface_anzahl=0;
+
+static void
+fw1_init(void)
+{
+ int i;
+
+ for (i=0; i<interface_anzahl; i++) {
+ free(p_interfaces[i]);
+ }
+ interface_anzahl = 0;
+}
+
+static void
+dissect_fw1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *volatile fh_tree = NULL;
+ char direction[3];
+ char chain[3];
+ char interface_name[10+1];
+ guint32 uuid;
+ guint16 etype;
+ char header[1000];
+ char *p_header;
+ int i;
+ gboolean found;
+ static char header1[] = "FW1 Monitor";
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "FW1");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ etype = tvb_get_ntohs(tvb, 12);
+
+ sprintf(header, header1);
+
+ /* fetch info to local variable */
+ direction[0] = tvb_get_guint8(tvb, 0);
+ direction[1] = 0;
+ chain[0] = tvb_get_guint8(tvb, 1);
+ chain[1] = 0;
+
+ if (!fw1_with_uuid) {
+ tvb_get_nstringz0(tvb, 2, 6, interface_name);
+ uuid = 0;
+ } else {
+ tvb_get_nstringz0(tvb, 2, sizeof interface_name, interface_name);
+ uuid = tvb_get_ntohl(tvb, 8);
+ }
+
+ /* Known interface name - if not, remember it */
+ found=FALSE;
+ for (i=0; i<interface_anzahl; i++) {
+ if ( strcmp(p_interfaces[i], interface_name) == 0 ) {
+ found=TRUE;
+ }
+ }
+ if (!found && interface_anzahl < MAX_INTERFACES) {
+ p_interfaces[interface_anzahl] = strdup(interface_name);
+ interface_anzahl++;
+ }
+ /* display all interfaces always in the same order */
+ for (i=0; i<interface_anzahl; i++) {
+ found=FALSE;
+ if ( strcmp(p_interfaces[i], interface_name) == 0 ) {
+ found=TRUE;
+ }
+ p_header = header + strlen(header);
+ if (!fw1_iflist_with_chain) {
+ sprintf(p_header, " %c %s %c",
+ found ? (direction[0]=='i' ? 'i' : (direction[0]=='O' ? 'O' : ' ')) : ' ',
+ p_interfaces[i],
+ found ? (direction[0]=='I' ? 'I' : (direction[0]=='o' ? 'o' : ' ')) : ' '
+ );
+ } else {
+ sprintf(p_header, " %c%c %s %c%c",
+ found ? (direction[0]=='i' ? 'i' : (direction[0]=='O' ? 'O' : ' ')) : ' ',
+ found ? (direction[0]=='i' ? chain[0] : (direction[0]=='O' ? chain[0] : ' ')) : ' ',
+ p_interfaces[i],
+ found ? (direction[0]=='I' ? 'I' : (direction[0]=='o' ? 'o' : ' ')) : ' ',
+ found ? (direction[0]=='I' ? chain[0] : (direction[0]=='o' ? chain[0] : ' ')) : ' '
+ );
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_IF_DIR))
+ col_add_str(pinfo->cinfo, COL_IF_DIR, header + strlen(header1) + 1);
+
+ if (tree) {
+ if (!fw1_summary_in_tree) {
+ /* Do not show the summary in Protocol Tree */
+ sprintf(header, header1);
+ }
+ ti = proto_tree_add_protocol_format(tree, proto_fw1, tvb, 0, ETH_HEADER_SIZE, header);
+
+ /* create display subtree for the protocol */
+ fh_tree = proto_item_add_subtree(ti, ett_fw1);
+
+ proto_tree_add_item(fh_tree, hf_fw1_direction, tvb, 0, 1, FALSE);
+ proto_tree_add_item(fh_tree, hf_fw1_chain, tvb, 1, 1, FALSE);
+
+ if (!fw1_with_uuid) {
+ proto_tree_add_string_format(fh_tree, hf_fw1_interface,
+ tvb, 2, 10,
+ interface_name, "Interface: %s", interface_name);
+ } else {
+ proto_tree_add_string_format(fh_tree, hf_fw1_interface,
+ tvb, 2, 6,
+ interface_name, "Interface: %s", interface_name);
+ proto_tree_add_item(fh_tree, hf_fw1_uuid, tvb, 8, 4, FALSE);
+ }
+ }
+ ethertype(etype, tvb, ETH_HEADER_SIZE, pinfo, tree, fh_tree, hf_fw1_type,
+ hf_fw1_trailer, 0);
+}
+
+void
+proto_register_fw1(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_fw1_direction,
+ { "Direction", "fw1.direction", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Direction", HFILL }},
+ { &hf_fw1_chain,
+ { "Chain Position", "fw1.chain", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Chain Position", HFILL }},
+ { &hf_fw1_interface,
+ { "Interface", "fw1.interface", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Interface", HFILL }},
+ { &hf_fw1_uuid,
+ { "UUID", "fw1.uuid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "UUID", HFILL }},
+ /* registered here but handled in ethertype.c */
+ { &hf_fw1_type,
+ { "Type", "fw1.type", FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
+ "", HFILL }},
+ };
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_fw1,
+ };
+ module_t *fw1_module;
+
+ /* Register the protocol name and description */
+ proto_fw1 = proto_register_protocol("Checkpoint FW-1", "FW-1", "fw1");
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_fw1, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register configuration preferences */
+ fw1_module = prefs_register_protocol(proto_fw1, NULL);
+ prefs_register_bool_preference(fw1_module, "summary_in_tree",
+ "Show FireWall-1 summary in protocol tree",
+ "Whether the FireWall-1 summary line should be shown in the protocol tree",
+ &fw1_summary_in_tree);
+ prefs_register_bool_preference(fw1_module, "with_uuid",
+ "fw monitor file includes UUID",
+ "Whether the fw monitor file includes information of UUID",
+ &fw1_with_uuid);
+ prefs_register_bool_preference(fw1_module, "iflist_with_chain",
+ "Interface list with chain position",
+ "Whether the interface list includes chain position",
+ &fw1_iflist_with_chain);
+
+ register_dissector("fw1", dissect_fw1, proto_fw1);
+
+ register_init_routine(fw1_init);
+}
+
+void
+proto_reg_handoff_fw1(void)
+{
+ /*
+ * Get handles for the Ethernet dissectors.
+ */
+ eth_handle = find_dissector("eth");
+}
diff --git a/epan/dissectors/packet-gift.c b/epan/dissectors/packet-gift.c
new file mode 100644
index 0000000000..1022a637e9
--- /dev/null
+++ b/epan/dissectors/packet-gift.c
@@ -0,0 +1,160 @@
+/* packet-gift.c
+ * Routines for giFT Internet File Transfer dissection
+ * Copyright 2000, Jon Oberheide <jon@oberheide.org>
+ *
+ * See http://www.giftproject.org/
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#define TCP_PORT_GIFT 1213
+
+static int proto_gift = -1;
+static int hf_gift_response = -1;
+static int hf_gift_request = -1;
+
+static gint ett_gift = -1;
+static gint ett_gift_cmd = -1;
+
+static void
+dissect_gift(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *gift_tree, *cmd_tree;
+ gboolean is_request;
+ gint offset = 0;
+ const guchar *line;
+ gint next_offset;
+ int linelen;
+ int tokenlen;
+ const guchar *next_token;
+
+ /* set "Protocol" column text */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "giFT");
+
+ /* determine whether it is a request to or response from the server */
+ if (pinfo->match_port == pinfo->destport)
+ is_request = TRUE;
+ else
+ is_request = FALSE;
+
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ line = tvb_get_ptr(tvb, offset, linelen);
+
+ /* clear the "Info" column */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* set "Info" column text */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
+ is_request ? "Request" : "Response",
+ format_text(line, linelen));
+
+ /* if tree != NULL, build protocol tree */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_gift, tvb, 0, -1, FALSE);
+ gift_tree = proto_item_add_subtree(ti, ett_gift);
+
+ if (is_request) {
+ proto_tree_add_boolean_hidden(gift_tree, hf_gift_request, tvb, 0, 0, TRUE);
+ } else {
+ proto_tree_add_boolean_hidden(gift_tree, hf_gift_response, tvb, 0, 0, TRUE);
+ }
+
+ ti = proto_tree_add_text(gift_tree, tvb, offset, next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ cmd_tree = proto_item_add_subtree(ti, ett_gift_cmd);
+
+ tokenlen = get_token_len(line, line + linelen, &next_token);
+ if (tokenlen != 0) {
+ if (is_request) {
+ proto_tree_add_text(cmd_tree, tvb, offset,
+ tokenlen, "Request Command: %s",
+ format_text(line, tokenlen));
+ } else {
+ proto_tree_add_text(cmd_tree, tvb, offset,
+ tokenlen, "Response Command: %s",
+ format_text(line, tokenlen));
+ }
+ offset += next_token - line;
+ linelen -= next_token - line;
+ line = next_token;
+ }
+
+ if (linelen != 0) {
+ if (is_request) {
+ proto_tree_add_text(cmd_tree, tvb, offset,
+ linelen, "Request Arg: %s",
+ format_text(line, linelen));
+ } else {
+ proto_tree_add_text(cmd_tree, tvb, offset,
+ linelen, "Response Arg: %s",
+ format_text(line, linelen));
+ }
+ }
+ }
+}
+
+void
+proto_register_gift(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_gift_response,
+ { "Response", "gift.response", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "TRUE if giFT response", HFILL }
+ },
+ { &hf_gift_request,
+ { "Request", "gift.request", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "TRUE if giFT request", HFILL }
+ }
+ };
+
+ static gint *ett[] = {
+ &ett_gift,
+ &ett_gift_cmd,
+ };
+
+ proto_gift = proto_register_protocol("giFT Internet File Transfer",
+ "giFT", "gift");
+
+ proto_register_field_array(proto_gift, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_gift(void)
+{
+ dissector_handle_t gift_handle;
+
+ gift_handle = create_dissector_handle(dissect_gift, proto_gift);
+ dissector_add("tcp.port", TCP_PORT_GIFT, gift_handle);
+}
diff --git a/epan/dissectors/packet-giop.c b/epan/dissectors/packet-giop.c
new file mode 100644
index 0000000000..5167ff7d86
--- /dev/null
+++ b/epan/dissectors/packet-giop.c
@@ -0,0 +1,5654 @@
+/* packet-giop.c
+ * Routines for CORBA GIOP/IIOP packet disassembly
+ *
+ * Initial Code by,
+ * Laurent Deniel <laurent.deniel@free.fr>
+ * Craig Rodrigues <rodrigc@attbi.com>
+ *
+ * GIOP API extensions by,
+ * Frank Singleton <frank.singleton@ericsson.com>
+ * Trevor Shepherd <eustrsd@am1.ericsson.se>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+/*
+ * TODO: -- FS
+ * 1. heuristic giop dissector table [started]
+ * 2. GUI options, see 20
+ * 3. Remove unneccessary reply_status in heuristic dissector calls (now
+ * part of MessageHeader) [done]
+ * 4. get_CDR_xxx should be passed an alignment offset value
+ * rather than GIOP_HEADER_SIZE, as alignment can also change in a
+ * octet stream when eg: encapsulation is used [done]
+ * 5. GIOP users should eventually get there own tvbuff, and
+ * not rely on the GIOP tvbuff, more robust
+ * 6. get_CDR_string,wchar,wstring etc should handle different
+ * GIOP versions [started]
+ * 7. Fix situation where req_id is not unique in a logfile [done, use FN/MFN, needs improving.]
+ *
+ * 8. Keep request_1_2 in step with request_1_1 [started]
+ * 9. Explicit module name dissection [done]
+ * 10. Decode IOR and put in a useful struct [IOR decode started]
+ * 11. Fix encapsulation of IOR etc and boundary [done]
+ * 12. handle get_CDR_typeCode() [started]
+ * 13. Handle different IOR profiles
+ * 14. Change printable_string to RETURN a new string, not to modify the old.
+ * or, new function, make_printable_string [done, make_printable_string]
+ *
+ * 15. Handle "TCKind", and forget about eg: enum translation to symbolic values
+ * otherwise need knowledge of sub dissectors data - YUK [done]
+ * 16. Handle multiple RepoId representations, besides IDL:Echo:1.0 (see 13.)
+ * 17. Pass subset of RepoID to explicit dissector.
+ * eg : If IDL:Mod1/Mod2/Int3:1.0 then pass "Mod1/Mode2/Int3" to sub dissector[done]
+ * 18. Better hashing algorithms
+ * 19. Handle hash collision properly .
+ * 20. Allow users to paste a stringified IOR into the GUI, and tie it
+ * to a sub_dissector.
+ * 21. Add complete_request_packet_list and complete_reply_packet_hash.[done]
+ * 22. Handle case where users click in any order, AND try and match
+ * REPLY msg to the correct REQUEST msg when we have a request_id collision.[done]
+ * 23. Clean up memory management for all those g_malloc's etc
+ * 24. register_giop_user_module could return a key for every distinct Module/Interface
+ * the sub_dissector uses. So, instead of strcmp()'s when handling the
+ * namespace of an operation, we could have a lookup table instead.
+ * 25. A few typedefs in the right place.
+ * 26 Improve handling of gchar * and use const gchar * where possible.
+ * 27. Read/write IOR etc to/from file, allows objkey hash to be built from
+ * external data [read done, write incomplete]
+ * 28. Call sub dissector only if tvb_offset_exists(). [Done, this is checked
+ * inside try_explicit_giop_dissector() ]
+ *
+ * 29. Make add/delete routine for objkey hash as it may be useful when say reading
+ * stringified IOR's from a file to add them to our hash. ie: There are other ways
+ * to populate our object key hash besides REPLY's to RESOLVE(request) [done]
+ *
+ * 30. Add routine to encode/decode stringified IOR's [decode done]
+ * 31. Add routine to read IOR's from file [done]
+ * 32. TypeCode -none-, needs decoding.
+ * 33. Complete dissect_data_for_typecode.
+ * 34. For complex TypeCodes need to check final offset against original offset + sequence length.
+ * 35. Update REQUEST/REPLY 1_2 according to IDL (eg; ServiceContextList etc).
+ * 36. Adding decode_ServiceContextList, incomplete.
+ * 37. Helper functions should not ALWAYS rely on header to find current endianess. It should
+ * be passed from user, eg Use stream_is_big_endian. [started]
+ * 38. Remove unwanted/unused function parameters, see decode_IOR [started]
+ * 40. Add sequence <IOP::TaggedComponent> components to IIOP IOR profile. Perhaps
+ * decode_IOP_TaggedComponents as a helper function. [done - NOT helper]
+ *
+ * 41. Make important field searchable from Message header. ie: Remove add_text_
+ * 42. Use sub-tree for decode_ServiceContextList, looks better.
+ * 43. dissect_reply_body, no exception dissector calls
+ * - call subdiss directly, as we already have handle.
+ * - add repoid to heuristic call also.
+ *
+ * 44. typedef using xxx_t in .h file.
+ * 45. Subdissectors should not be passed MessageHeader to find endianness and
+ * version, they should be passed directly ?
+ * 46. get_CDR_wchar and wstring need wide chars decoded (just dumped in
+ * any readable form at present, not handled well at all, suggestions welcome -- FS
+ * 47. Change ...add_text to ...add_xxx (ie use hf fields).
+ *
+ * 48. BUG - file load with a GIOP filter set, causes the FN/MFN data struct to be
+ * not initiated properly. Hit "Reload" as a workaround, til I fix this -- FS
+ *
+ */
+
+
+
+/*
+ * Intended Decode strategy:
+ * =========================
+ *
+ * Initial Pass
+ * ------------
+ * REQUEST: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
+ * and populate complete_request_packet_hash
+ *
+ * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
+ *
+ * User Clicks
+ * -----------
+ *
+ * REQUEST: FN -> giop_sub_handle_t directly (via complete_request_packet_hash)
+ *
+ * REPLY: FN -> MFN (via complete_reply_packet_hash) = Request FN -> giop_sub_handle_t
+ * (via complete_request_packet_hash
+ *
+ *
+ * Limitations.
+ * ============
+ *
+ * 1. Request_ID's are unique only per connection.
+ *
+ * 2. You must be monitoring the network when the client does
+ * a REQUEST(resolve), otherwise I have no knowledge of the
+ * association between object_key and REPOID. I could talk to
+ * a Nameserver, but then I would start "generating" packets.
+ * This is probably not a good thing for a protocol analyser.
+ * Also, how could I decode logfiles offline.
+ *
+ * TODO -- Read stringified IORs from an input file.[done]
+ *
+ * 3. User clicks (REQUEST) is currently handle the same as
+ * the initial pass handling.
+ *
+ * ie: objkey -> Repo_ID -> Module/Interface -> giop_sub_handle_t
+ */
+
+
+/*
+ * Important Data Structures:
+ *
+ * giop_module_hash
+ * ----------------
+ *
+ * This is a hash table that maps IDL Module/Interface Names (Key)
+ * to sub_dissector handles, giop_sub_handle_t. It is populated
+ * by subdissectors, via register_giop_user_module(). This
+ * table is used when we have a REPOID, and explicitly wish to
+ * call the subdissector that has registered responsibility for
+ * that IDL module/interface.
+ *
+ *
+ * giop_sub_list
+ * -------------
+ *
+ * This singly linked list is used to hold entries for
+ * heuristic based subdissectors. It is populated by sub_dissectors
+ * wishing to be called via heuristic mechanisms. They do this
+ * via the register_giop_user() function.
+ *
+ *
+ * giop_objkey_hash
+ * ----------------
+ *
+ * This hash table maps object_key's (key) onto REPOID's (val).
+ * Once a client has REQUEST(resolve) an object , it knows about
+ * an object (interface) via its object_key (see IOR). So in order to follow
+ * packets that contain an object_key only, and to be able to forward it
+ * to the correct explicit subdissector, we need this table.
+ *
+ * So, I listen in on REQUEST(resolve) messages between client and
+ * Nameserver, and store the respones (REPLY/Objkey,Repo_ID) here.
+ *
+ * Also, stringified IOR's can be read from a file "IOR.txt" and used
+ * to populate this hash also.
+ *
+ *
+ * Other Data structures
+ * =======================
+ *
+ * These structures have been added to minimise the possibility
+ * of incorrectly interpreted packets when people click all
+ * over the place, in no particular order, when the request_id's are
+ * not unique as captured. If all request_is'd are unique, as captured, then
+ * we would not have to deal with this problem.
+ *
+ *
+ * When the logfile or packets are initially being processed, I will
+ * build 2 structures. The intent is to be able to map a REPLY message
+ * back to the most recent REQUEST message with the same Request_ID
+ * (TODO and matching port and IP address ??)
+ *
+ * Abbrevs:
+ * --------
+ *
+ * FN - Frame Number
+ * MFN - Matching Frame Number
+ *
+ *
+ * complete_request_packet_list
+ * ----------------------------
+ *
+ * This is a list that contains ALL the FN's that are REQUEST's, along with
+ * operation,request_id and giop_sub_handle_t
+ *
+ * complete_reply_packet_hash
+ * --------------------------
+ *
+ * This is a hash table. It is populated with FN (key) and MFN (val).
+ * This allows me to handle the case, where if you click on any REPLY
+ * message, I can lookup the matching request. This can improve
+ * the match rate between REQUEST and REPLY when people click in
+ * any old fashion, but is NOT foolproof.
+ *
+ * The algorithm I use to populate this hash during initial pass,
+ * is as follows.
+ *
+ * If packet is a REPLY, note the reqid, and then traverse backwards
+ * through the complete_request_packet_list from its tail, looking
+ * for a FN that has the same Request_id. Once found, take the found FN
+ * from complete_reply_packet_hash, and insert it into the MFN field
+ * of the complete_reply_packet_hash.
+ *
+ *
+ * See TODO for improvements to above algorithm.
+ *
+ * So now when people click on a REQUEST packet, I can call lookup the
+ * giop_sub_handle_t directly from complete_request_packet_list.
+ *
+ * And, when they click on a REPLY, I grab the MFN of this FN from
+ * complete_reply_packet_hash, then look that up in the complete_request_packet_list
+ * and call the sub_dissector directly.
+ *
+ * So, how do I differentiate between the initial processing of incoming
+ * packets, and a user clickin on one ? Good question.
+ *
+ * I leverage the pinfo_fd->flags.visited on a per frame
+ * basis.
+ *
+ * To quote from the ever helpful development list
+ *
+ * " When a capture file is initially loaded, all "visited" flags
+ * are 0. Ethereal then makes the first pass through file,
+ * sequentially dissecting each packet. After the packet is
+ * dissected the first time, "visited" is 1. (See the end of
+ * dissect_packet() in epan/packet.c; that's the code that
+ * sets "visited" to 1).
+
+ * By the time a user clicks on a packet, "visited" will already
+ * be 1 because Ethereal will have already done its first pass
+ * through the packets.
+
+ * Reload acts just like a normal Close/Open, except that it
+ * doesn't need to ask for a filename. So yes, the reload button
+ * clears the flags and re-dissects the file, just as if the file
+ * had been "opened". "
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <glib.h>
+#include <math.h>
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include "isprint.h"
+
+#include <epan/packet.h>
+#include "packet-giop.h"
+
+/*
+ * Set to 1 for DEBUG output - TODO make this a runtime option
+ */
+
+#define DEBUG 0
+
+
+
+/*
+ * ------------------------------------------------------------------------------------------+
+ * Private Helper function Declarations
+ * ------------------------------------------------------------------------------------------+
+ */
+
+
+static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
+ guint32 boundary, gboolean new_endianess, gchar *repobuf,
+ gboolean store_flag);
+
+static void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *tree, int *offset,
+ gboolean stream_is_be, guint32 boundary);
+
+static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
+ guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf);
+
+static void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
+ guint32 boundary, gboolean stream_is_big_endian );
+
+static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian,
+ guint32 boundary);
+
+static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary);
+
+static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header);
+
+static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header );
+
+static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary);
+
+static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header);
+
+static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header);
+
+static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header);
+
+static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header);
+
+static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header);
+
+static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header);
+
+static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary);
+
+static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary);
+
+
+static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id );
+
+static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header, guint32 data_type );
+
+
+
+
+/*
+ * ------------------------------------------------------------------------------------------+
+ * Data/Variables/Structs
+ * ------------------------------------------------------------------------------------------+
+ */
+
+
+static int proto_giop = -1;
+static int hf_giop_message_type = -1;
+static int hf_giop_message_size = -1;
+static int hf_giop_repoid = -1;
+static int hf_giop_string_length = -1;
+static int hf_giop_sequence_length = -1;
+static int hf_giop_profile_id = -1;
+static int hf_giop_type_id = -1;
+static int hf_giop_iiop_v_maj = -1;
+static int hf_giop_iiop_v_min = -1;
+static int hf_giop_endianess = -1; /* esp encapsulations */
+static int hf_giop_IOR_tag = -1;
+static int hf_giop_IIOP_tag = -1;
+
+static int hf_giop_TCKind = -1;
+static int hf_giop_typecode_count = -1;
+static int hf_giop_typecode_default_used = -1;
+static int hf_giop_typecode_digits = -1;
+static int hf_giop_typecode_length = -1;
+static int hf_giop_typecode_max_length = -1;
+static int hf_giop_typecode_member_name = -1;
+static int hf_giop_typecode_name = -1;
+static int hf_giop_typecode_scale = -1;
+static int hf_giop_typecode_ValueModifier = -1;
+static int hf_giop_typecode_Visibility = -1;
+
+static int hf_giop_type_boolean = -1;
+static int hf_giop_type_char = -1;
+static int hf_giop_type_double = -1;
+static int hf_giop_type_enum = -1;
+static int hf_giop_type_float = -1;
+static int hf_giop_type_long = -1;
+static int hf_giop_type_octet = -1;
+static int hf_giop_type_short = -1;
+static int hf_giop_type_string = -1;
+static int hf_giop_type_ulong = -1;
+static int hf_giop_type_ushort = -1;
+
+static int hf_giop_iiop_host = -1;
+static int hf_giop_iiop_port = -1;
+static int hf_giop_iop_vscid = -1;
+static int hf_giop_iop_scid = -1;
+
+/*
+ * (sub)Tree declares
+ */
+
+static gint ett_giop = -1;
+static gint ett_giop_reply = -1;
+static gint ett_giop_request = -1;
+static gint ett_giop_cancel_request = -1;
+static gint ett_giop_locate_request = -1;
+static gint ett_giop_locate_reply = -1;
+static gint ett_giop_fragment = -1;
+
+static gint ett_giop_scl = -1; /* ServiceContextList */
+static gint ett_giop_scl_st1 = -1;
+static gint ett_giop_ior = -1; /* IOR */
+
+static dissector_handle_t data_handle;
+/* GIOP endianess */
+
+static const value_string giop_endianess_vals[] = {
+ { 0x0, "Big Endian" },
+ { 0x1, "Little Endian" },
+ { 0, NULL}
+};
+
+static const value_string sync_scope[] = {
+ { 0x0, "SYNC_NONE" },
+ { 0x1, "SYNC_WITH_TRANSPORT"},
+ { 0x2, "SYNC_WITH_SERVER"},
+ { 0x3, "SYNC_WITH_TARGET"},
+ { 0, NULL}
+};
+
+/* Profile ID's */
+
+static const value_string profile_id_vals[] = {
+ { 0x0, "TAG_INTERNET_IOP" },
+ { 0x1, "TAG_MULTIPLE_COMPONENTS"},
+ { 0x2, "TAG_SCCP_IOP"},
+ { 0, NULL}
+};
+
+static const value_string giop_message_types[] = {
+ { 0x0, "Request" },
+ { 0x1, "Reply"},
+ { 0x2, "CancelRequest"},
+ { 0x3, "LocateRequest"},
+ { 0x4, "LocateReply"},
+ { 0x5, "CloseConnection"},
+ { 0x6, "MessageError"},
+ { 0x7, "Fragment"},
+ { 0, NULL}
+};
+
+static const value_string giop_locate_status_types[] = {
+ { 0x0, "Unknown Object" },
+ { 0x1, "Object Here"},
+ { 0x2, "Object Forward"},
+ { 0x3, "Object Forward Perm"},
+ { 0x4, "Loc System Exception"},
+ { 0x5, "Loc Needs Addressing Mode"},
+ { 0, NULL }
+};
+
+static const value_string tckind_vals[] = {
+ { 0, "tk_null"},
+ { 1, "tk_void"},
+ { 2, "tk_short"},
+ { 3, "tk_long"},
+ { 4, "tk_ushort"},
+ { 5, "tk_ulong"},
+ { 6, "tk_float"},
+ { 7, "tk_double"},
+ { 8, "tk_boolean"},
+ { 9, "tk_char"},
+ { 10, "tk_octet"},
+ { 11, "tk_any"},
+ { 12, "tk_TypeCode"},
+ { 13, "tk_Principal"},
+ { 14, "tk_objref"},
+ { 15, "tk_struct"},
+ { 16, "tk_union"},
+ { 17, "tk_enum"},
+ { 18, "tk_string"},
+ { 19, "tk_sequence"},
+ { 20, "tk_array"},
+ { 21, "tk_alias"},
+ { 22, "tk_except"},
+ { 23, "tk_longlong"},
+ { 24, "tk_ulonglong"},
+ { 25, "tk_longdouble"},
+ { 26, "tk_wchar"},
+ { 27, "tk_wstring"},
+ { 28, "tk_fixed"},
+ { 29, "tk_value"},
+ { 30, "tk_value_box"},
+ { 31, "tk_native"},
+ { 32, "tk_abstract_interface"},
+ { 0, NULL }
+};
+
+/*
+ * These values are taken from the CORBA 3.0.2 standard,
+ * section 13.7.1 "Standard Service Contexts".
+ */
+static const guint32 max_service_context_id = 0x10;
+static const value_string service_context_ids[] = {
+ { 0x00, "TransactionService" },
+ { 0x01, "CodeSets"},
+ { 0x02, "ChainBypassCheck"},
+ { 0x03, "ChainBypassInfo"},
+ { 0x04, "LogicalThreadId"},
+ { 0x05, "BI_DIR_IIOP"},
+ { 0x06, "SendingContextRunTime"},
+ { 0x07, "INVOCATION_POLICIES"},
+ { 0x08, "FORWARDED_IDENTITY"},
+ { 0x09, "UnknownExceptionInfo"},
+ { 0x0a, "RTCorbaPriority"},
+ { 0x0b, "RTCorbaPriorityRange"},
+ { 0x0c, "FT_GROUP_VERSION"},
+ { 0x0d, "FT_REQUEST"},
+ { 0x0e, "ExceptionDetailMessage"},
+ { 0x0f, "SecurityAttributeService"},
+ { 0x10, "ActivityService"},
+ { 0, NULL }
+};
+
+
+
+
+#define GIOP_MAGIC "GIOP"
+
+/*
+ * TAGS for IOR Profiles
+ *
+ * Chapter 13 Corba 2.4.2
+ *
+ */
+
+#define IOP_TAG_INTERNET_IOP 0
+#define IOP_TAG_MULTIPLE_COMPONENTS 1
+
+
+/* Max Supported versions */
+
+static const guint GIOP_MAJOR = 1;
+static const guint GIOP_MINOR = 2;
+
+
+static const int KeyAddr = 0;
+static const int ProfileAddr = 1;
+static const int ReferenceAddr = 2;
+
+
+
+static const value_string reply_status_types[] = {
+ { NO_EXCEPTION, "No Exception" } ,
+ { USER_EXCEPTION, "User Exception" } ,
+ { SYSTEM_EXCEPTION, "System Exception" } ,
+ { LOCATION_FORWARD, "Location Forward" } ,
+ { LOCATION_FORWARD_PERM, "Location Forward Perm" } ,
+ { NEEDS_ADDRESSING_MODE, "Needs Addressing Mode" } ,
+ { 0, NULL }
+};
+
+
+
+typedef enum LocateStatusType
+{
+ UNKNOWN_OBJECT,
+ OBJECT_HERE,
+ OBJECT_FORWARD,
+ OBJECT_FORWARD_PERM, /* new value for GIOP 1.2 */
+ LOC_SYSTEM_EXCEPTION, /* new value for GIOP 1.2 */
+ LOC_NEEDS_ADDRESSING_MODE /* new value for GIOP 1.2 */
+}
+LocateStatusType_t;
+
+typedef struct LocateReplyHeader
+{
+ guint32 request_id;
+ guint32 locate_status;
+}
+LocateReplyHeader_t;
+
+
+/*
+ * DATA - complete_request_list
+ */
+
+static GList *giop_complete_request_list;
+
+struct comp_req_list_entry {
+ guint32 fn; /* frame number */
+ gchar * operation; /* echo echoString */
+ giop_sub_handle_t *subh; /* handle to sub dissector */
+ guint32 reqid; /* request id */
+ gchar * repoid; /* repository ID */
+};
+
+typedef struct comp_req_list_entry comp_req_list_entry_t;
+
+
+/*
+ * DATA - complete_reply_hash
+ *
+ * Maps reply FN to request MFN
+ */
+
+static int complete_reply_hash_count = 1000; /* storage size for our permanent data */
+ /* ie: 1000 entries -- needs tweaking -- FS */
+
+struct complete_reply_hash_key {
+ guint32 fn; /* reply frame number */
+};
+
+struct complete_reply_hash_val {
+ guint32 mfn; /* matching frame number (request) */
+};
+
+GHashTable *giop_complete_reply_hash = NULL; /* hash */
+GMemChunk *giop_complete_reply_keys = NULL; /* key storage */
+GMemChunk *giop_complete_reply_vals = NULL; /* val storage */
+
+
+/*
+ * DATA - Module Hash stuff to store data from register_giop_user_module
+ *
+ * ie: module (or interface ?) name, and ptr to sub_dissector handle
+ *
+ * With this knowledge, we can call a sub dissector directly,
+ * by :
+ *
+ * objkey -> repoid -> sub_dissector via registered module/interface
+ *
+ */
+
+
+static int giop_module_init_count = 100; /* storage size for our permanent data */
+ /* ie: 100 entries -- needs tweaking -- FS */
+
+struct giop_module_key {
+ gchar *module; /* module (interface?) name */
+};
+
+struct giop_module_val {
+ giop_sub_handle_t *subh; /* handle to sub dissector */
+};
+
+GHashTable *giop_module_hash = NULL; /* hash */
+GMemChunk *giop_module_keys = NULL; /* key storage */
+GMemChunk *giop_module_vals = NULL; /* val storage */
+
+
+/*
+ * DATA - GSList to store list of function (dissector) pointers.
+ * for heuristic dissection.
+ *
+ */
+
+static GSList *giop_sub_list = NULL;
+
+/*
+ * DATA - Hash stuff to follow request/reply. This is so if we get a REPLY
+ * to a REQUEST (resolve), we can dump/store the RepoId and Object Key.
+ *
+ * With this knowledge, we can call a sub dissector directly later
+ * by :
+ *
+ * objkey -> repoid -> sub_dissector via registered module/interface
+ *
+ * rather than heuristic calls that do not provide operation context.
+ * (unless we pass the RepoID for a given objkey -- hmmm)
+ *
+ */
+
+/*
+ * Interesting operation list, add more if you want to save
+ * interesting data.
+ */
+
+static const char giop_op_resolve[] = "resolve";
+static const char giop_op_bind_new_context[] = "bind_new_context";
+static const char giop_op_bind[] = "bind";
+
+/*
+ * Enums for interesting local operations, that we may need to monitor
+ * with their subsequent replies
+ *
+ */
+
+enum giop_op_val {
+ request_resolve_op_val, /* REQUEST (resolve) to get RepoID etc*/
+ request_bind_new_context_op_val, /* bind_new_context */
+ request_bind_op_val, /* bind */
+ request_get_INIT_op_val /* finding Nameserver */
+
+};
+
+
+/*
+ * hash for mapping object keys onto object namespaces, so
+ * I can call the correct dissector.
+ *
+ *
+ */
+
+/*
+ * Where did I get the IOR from.
+ */
+
+enum ior_src {
+ req_res = 0, /* REQUEST (resolve) */
+ file /* stringified IOR' in a file */
+
+};
+
+typedef enum ior_src ior_src_t;
+
+
+
+/*
+ * Enums for my lists and hash's
+ */
+
+enum collection_data {
+ cd_heuristic_users = 0,
+ cd_module_hash,
+ cd_objkey_hash,
+ cd_complete_request_list,
+ cd_complete_reply_hash
+};
+
+typedef enum collection_data collection_data_t;
+
+
+
+static int giop_objkey_init_count = 100; /* storage size for our permanent data */
+ /* ie: 100 entries -- needs tweaking -- FS */
+
+struct giop_object_key {
+ guint8 *objkey; /* ptr to object key */
+ guint32 objkey_len; /* length */
+};
+
+struct giop_object_val {
+ guint8 *repo_id; /* ptr to Repository ID string */
+ ior_src_t src; /* where did Iget this IOR from */
+};
+
+GHashTable *giop_objkey_hash = NULL; /* hash */
+GMemChunk *giop_objkey_keys = NULL; /* key storage */
+GMemChunk *giop_objkey_vals = NULL; /* val storage */
+
+
+
+/*
+ * ------------------------------------------------------------------------------------------+
+ * Private helper functions
+ * ------------------------------------------------------------------------------------------+
+ */
+
+
+
+/*
+ * Insert FN,reqid,operation and sub handle in list. DOES not check for duplicates yet.
+ */
+
+static GList *insert_in_comp_req_list(GList *list, guint32 fn, guint32 reqid, gchar * op, giop_sub_handle_t *sh ) {
+ GList * newlist_start;
+ comp_req_list_entry_t * entry = NULL;
+ gchar * opn;
+
+ entry = g_malloc(sizeof(comp_req_list_entry_t));
+ opn = g_strdup(op); /* duplicate operation for storage */
+
+ entry->fn = fn;
+ entry->reqid = reqid;
+ entry->subh = sh;
+ entry->operation = opn;
+ entry->repoid = NULL; /* dont have yet */
+
+ newlist_start = g_list_append (list, entry); /* append */
+
+ return newlist_start;
+}
+
+
+/*
+ * Used to find an entry with matching Frame Number FN
+ * in the complete_request_list list.
+ */
+
+static comp_req_list_entry_t * find_fn_in_list(guint32 fn) {
+
+ GList * element; /* entry in list */
+ comp_req_list_entry_t * entry_ptr = NULL;
+
+ element = g_list_last(giop_complete_request_list); /* start from last */
+
+ while(element) { /* valid list entry */
+ entry_ptr = element->data; /* grab data pointer */
+ if (entry_ptr->fn == fn) { /* similar FN */
+ return entry_ptr;
+ }
+ element = g_list_previous(element); /* try next previous */
+ }
+
+ return NULL; /* no match so return NULL */
+}
+
+
+/*
+ * Add/update a sub_dissector handle and repoid to a FN entry in the complete_request_list
+ *
+ * Call this when you know a FN and matching giop_sub_handle_t and repoid
+ *
+ * This is done in say, try_explicit_dissector for example.
+ *
+ */
+
+static void add_sub_handle_repoid_to_comp_req_list(guint32 fn, giop_sub_handle_t *sh, gchar *repoid ) {
+
+ comp_req_list_entry_t * entry = NULL;
+ entry = find_fn_in_list(fn); /* grab FN data entry */
+
+ if (entry) {
+ entry->subh = sh;
+ entry->repoid = g_strdup(repoid); /* copy and store */
+
+ }
+}
+
+
+
+
+/* giop_complete_reply_hash "EQUAL" Functions */
+
+static gint complete_reply_equal_fn(gconstpointer v, gconstpointer w) {
+ const struct complete_reply_hash_key *mk1 = (const struct complete_reply_hash_key *)v;
+ const struct complete_reply_hash_key *mk2 = (const struct complete_reply_hash_key *)w;
+
+ if (mk1->fn == mk2->fn) {
+ return 1;
+ }
+
+ return 0; /* found differences */
+}
+
+/* giop_complete_reply_hash "HASH" Functions */
+
+static guint32 complete_reply_hash_fn(gconstpointer v) {
+ guint32 val; /* init hash value */
+ const struct complete_reply_hash_key *key = (const struct complete_reply_hash_key *)v;
+
+ val = key->fn; /* simple and unique */
+
+ return val;
+}
+
+
+/*
+ * Insert the FN and MFN together in our complete_reply_hash.
+ */
+
+static void insert_in_complete_reply_hash(guint32 fn, guint32 mfn) {
+
+ struct complete_reply_hash_key key, *new_key;
+ struct complete_reply_hash_val *val = NULL;
+
+ key.fn = fn;
+
+ val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
+
+ if (val) {
+ return; /* FN collision */
+ }
+
+ new_key = g_mem_chunk_alloc(giop_complete_reply_keys);
+ new_key->fn = fn; /* save FN */
+
+ val = g_mem_chunk_alloc(giop_complete_reply_vals);
+ val->mfn = mfn; /* and MFN */
+
+ g_hash_table_insert(giop_complete_reply_hash, new_key, val);
+
+}
+
+/*
+ * Find the MFN values from a given FN key.
+ * Assumes the complete_reply_hash is already populated.
+ */
+
+static guint32 get_mfn_from_fn(guint32 fn) {
+
+ struct complete_reply_hash_key key;
+ struct complete_reply_hash_val *val = NULL;
+ guint32 mfn = fn; /* save */
+
+ key.fn = fn;
+ val = (struct complete_reply_hash_val *)g_hash_table_lookup(giop_complete_reply_hash, &key);
+
+ if (val) {
+ mfn = val->mfn; /* grab it */
+ }
+
+ return mfn; /* mfn or fn if not found */
+
+}
+
+/*
+ * Attempt to find the MFN for this FN, and return it.
+ * Return MFN if found, or just FN if not. This is
+ * only used when we are building
+ */
+
+static guint32 get_mfn_from_fn_and_reqid(guint32 fn, guint32 reqid) {
+
+ GList * element; /* last entry in list */
+ comp_req_list_entry_t * entry_ptr = NULL;
+
+ /* Need Some pretty snappy code */
+
+ /* Loop back from current end of complete_request_list looking for */
+ /* a FN with the same reqid -- TODO enhance with port/address checks -- FS */
+
+ /*
+ * As this routine is only called during initial pass of data,
+ * and NOT when a user clicks, it is ok to start from Current
+ * end of complete_request_list when searching for a match.
+ * As that list is bing populated in the same order as FN's
+ * are being read.
+ *
+ * Also, can make check for same reqid more detailed, but I start
+ * with reqid. Could add say port or address checks etc later ??
+ */
+
+
+ element = g_list_last(giop_complete_request_list); /* get last */
+
+ while(element) { /* valid list entry */
+ entry_ptr = element->data; /* grab data pointer */
+ if (entry_ptr->reqid == reqid) { /* similar reqid */
+ return entry_ptr->fn; /* return MFN */
+ }
+ element = g_list_previous(element); /* try next previous */
+ }
+
+ return fn; /* no match so return FN */
+}
+
+
+/* Module Hash "EQUAL" Functions */
+
+static gint giop_hash_module_equal(gconstpointer v, gconstpointer w) {
+ const struct giop_module_key *mk1 = (const struct giop_module_key *)v;
+ const struct giop_module_key *mk2 = (const struct giop_module_key *)w;
+
+ if (strcmp(mk1->module, mk2->module) == 0) {
+ return 1;
+ }
+
+ return 0; /* found differences */
+}
+
+/* Module Hash "HASH" Functions */
+
+static guint32 giop_hash_module_hash(gconstpointer v) {
+
+ int i,len;
+ guint32 val = 0; /* init hash value */
+
+ const struct giop_module_key *key = (const struct giop_module_key *)v;
+
+ /*
+ * Hmm, try this simple hashing scheme for now.
+ * ie: Simple summation, FIX later -- FS
+ *
+ *
+ */
+
+ len = strlen(key->module);
+
+ for (i=0; i<len; i++) {
+ val += (guint8) key->module[i];
+ }
+
+ return val;
+
+}
+
+
+/*
+ * ------------------------------------------------------------------------------------------+
+ * Public Utility functions
+ * ------------------------------------------------------------------------------------------+
+ */
+
+
+
+
+/*
+ * Routine to allow giop users to register their sub dissector function, name, and
+ * IDL module/interface name. Store in giop_module_hash. Also pass along their proto_XXX
+ * value returned from their proto_register_protocol(), so we can enable/disbale it
+ * through the GUI (edit protocols).
+ *
+ * This is used by try_explicit_giop_dissector() to find the
+ * correct sub-dissector.
+ *
+ */
+
+void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name, gchar *module, int sub_proto) {
+
+ struct giop_module_key module_key, *new_module_key;
+ struct giop_module_val *module_val = NULL;
+
+ module_key.module = module; /* module name */
+
+ module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
+
+ if (module_val) {
+ return; /* module name collision */
+ }
+
+ /* So, passed module name should NOT exist in hash at this point.*/
+
+#if DEBUG
+ printf("giop:register_module: Adding Module %s to module hash \n", module);
+ printf("giop:register_module: Module sub dissector name is %s \n", name);
+#endif
+
+ new_module_key = g_mem_chunk_alloc(giop_module_keys);
+ new_module_key->module = module; /* save Module or interface name from IDL */
+
+ module_val = g_mem_chunk_alloc(giop_module_vals);
+
+ module_val->subh = g_malloc(sizeof (giop_sub_handle_t)); /* init subh */
+
+ module_val->subh->sub_name = name; /* save dissector name */
+ module_val->subh->sub_fn = sub; /* save subdissector*/
+ module_val->subh->sub_proto = find_protocol_by_id(sub_proto); /* save protocol_t for subdissector's protocol */
+
+ g_hash_table_insert(giop_module_hash, new_module_key, module_val);
+
+}
+
+
+
+
+/* Object Key Hash "EQUAL" Functions */
+
+static gint giop_hash_objkey_equal(gconstpointer v, gconstpointer w) {
+ const struct giop_object_key *v1 = (const struct giop_object_key *)v;
+ const struct giop_object_key *v2 = (const struct giop_object_key *)w;
+
+ if (v1->objkey_len != v2->objkey_len)
+ return 0; /* no match because different length */
+
+ /* Now do a byte comaprison */
+
+ if (memcmp(v1->objkey,v2->objkey, v1->objkey_len) == 0) {
+ return 1; /* compares ok */
+ }
+
+#if DEBUG
+ printf("giop:giop_hash_objkey_equal: Objkey's DO NOT match");
+#endif
+
+ return 0; /* found differences */
+}
+
+/* Object Key Hash "HASH" Functions */
+
+static guint32 giop_hash_objkey_hash(gconstpointer v) {
+ const struct giop_object_key *key = (const struct giop_object_key *)v;
+
+ guint32 i;
+ guint32 val = 0; /* init hash value */
+
+
+ /*
+ * Hmm, try this simple hashing scheme for now.
+ * ie: Simple summation
+ *
+ *
+ */
+
+#if DEBUG
+ printf("giop:hash_objkey: Key length = %u \n", key->objkey_len );
+#endif
+
+ for (i=0; i< key->objkey_len; i++) {
+ val += (guint8) key->objkey[i];
+ }
+
+ return val;
+
+}
+
+/*
+ * Routine to take an object key octet sequence, and length, and ptr to
+ * a (null terminated )repository ID string, and store them in the obect key hash.
+ *
+ * Blindly Inserts even if it does exist, See TODO at top for reason.
+ */
+
+static void insert_in_objkey_hash(GHashTable *hash, gchar *obj, guint32 len, gchar *repoid, ior_src_t src) {
+
+ struct giop_object_key objkey_key, *new_objkey_key;
+ struct giop_object_val *objkey_val = NULL;
+
+ objkey_key.objkey_len = len; /* length */
+ objkey_key.objkey = obj; /* object key octet sequence */
+
+ /* Look it up to see if it exists */
+
+ objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
+
+ /* CHANGED -- Same reqid, so abandon old entry */
+
+ if (objkey_val) {
+ g_hash_table_remove(hash, &objkey_key);
+ }
+
+ /* So, passed key should NOT exist in hash at this point.*/
+
+ new_objkey_key = g_mem_chunk_alloc(giop_objkey_keys);
+ new_objkey_key->objkey_len = len; /* save it */
+ new_objkey_key->objkey = (guint8 *) g_memdup(obj,len); /* copy from object and allocate ptr */
+
+ objkey_val = g_mem_chunk_alloc(giop_objkey_vals);
+ objkey_val->repo_id = g_strdup(repoid); /* duplicate and store Respository ID string */
+ objkey_val->src = src; /* where IOR came from */
+
+
+#if DEBUG
+ printf("giop: ******* Inserting Objkey with RepoID = %s and key length = %u into hash \n",
+ objkey_val->repo_id, new_objkey_key->objkey_len);
+#endif
+
+ g_hash_table_insert(hash, new_objkey_key, objkey_val);
+
+}
+
+
+
+/*
+ * convert an ascii char representing a hex value,
+ * to a numeric value.
+ *
+ * returns value, or -1 if problem.
+ *
+ */
+
+static gint8 hex_char_to_val(guchar c){
+ gint8 retval ;
+
+ if (!isxdigit(c)) {
+ return -1;
+ }
+ if (isdigit(c)) {
+ retval = c - 48; /* convert digit */
+ return retval;
+ }
+
+ c = toupper(c); /* convert to uppercase */
+ if (c >= 'A' && c <= 'F') {
+ retval = c - 55;
+ return retval;
+ }
+ else {
+ return -1;
+ }
+
+}
+
+/*
+ * Convert from stringified IOR of the kind IOR:af4f7e459f....
+ * to an IOR octet sequence.
+ *
+ * User must free buffer.
+ *
+ * Creates a new tvbuff and call decode_IOR with a NULL tree, just to
+ * grab repoid etc for our objkey hash.
+ *
+ */
+
+static guint32 string_to_IOR(guchar *in, guint32 in_len, guint8 **out){
+ gint8 tmpval_lsb;
+ gint8 tmpval_msb;
+ gint8 tmpval; /* complete value */
+ guint32 i;
+
+ *out = g_new0(guint8, in_len); /* allocate buffer */
+
+ if (*out == NULL) {
+ return 0;
+ }
+
+ /* skip past IOR: and convert character pairs to guint8 */
+
+ for (i=4; i<in_len-1; i+=2) {
+ if ( isxdigit(in[i]) && isxdigit(in[i+1]) ) { /* hex ? */
+
+ if ( (tmpval_msb = hex_char_to_val(in[i])) < 0 ) {
+ g_warning("giop: Invalid value in IOR %i \n", tmpval_msb);
+
+ }
+
+ if ( (tmpval_lsb = hex_char_to_val(in[i+1])) < 0 ) {
+ g_warning("giop: Invalid value in IOR %i \n", tmpval_lsb);
+ }
+
+ tmpval = tmpval_msb << 4;
+ tmpval += tmpval_lsb;
+ (*out)[(i-4)/2] = (guint8) tmpval;
+
+ }
+ else {
+ /* hmm */
+ break;
+ }
+
+ }
+
+ return (i-4)/2; /* length */
+
+}
+
+
+
+/*
+ * Simple "get a line" routine, copied from somewhere :)
+ *
+ */
+
+static int giop_getline(FILE *fp, gchar *line, int maxlen) {
+
+ if (fgets(line,maxlen,fp) == NULL)
+ return 0;
+ else
+ return strlen(line);
+
+}
+
+
+/*
+ * Read a list of stringified IOR's from a named file, convert to IOR's
+ * and store in object key hash
+ */
+
+static void read_IOR_strings_from_file(gchar *name, int max_iorlen) {
+ guchar *buf; /* NOTE reused for every line */
+ int len;
+ int ior_val_len; /* length after unstringifying. */
+ FILE *fp;
+ guint8 *out; /* ptr to unstringified IOR */
+ tvbuff_t *tvb; /* temp tvbuff for dissectin IORs */
+ guint32 my_offset = 0;
+ gboolean stream_is_big_endian;
+
+
+ fp = fopen(name,"r"); /* open read only */
+
+ if (fp == NULL) {
+ if (errno == EACCES)
+ fprintf(stderr, "Error opening file IOR.txt for reading: %s\n",strerror(errno));
+ return;
+ }
+
+ buf = g_malloc0(max_iorlen+1); /* input buf */
+
+ while ((len = giop_getline(fp,buf,max_iorlen+1)) > 0) {
+ my_offset = 0; /* reset for every IOR read */
+
+ ior_val_len = string_to_IOR(buf,len,&out); /* convert */
+
+ if(ior_val_len>0) {
+
+ /* Combination of tvb_new() and tvb_set_real_data().
+ Can throw ReportedBoundsError.
+
+ XXX - can it throw an exception in this case? If so, we
+ need to catch it and clean up, but we really shouldn't allow
+ it - or "get_CDR_octet()", or "decode_IOR()" - to throw an
+ exception. */
+
+ tvb = tvb_new_real_data(out, ior_val_len, ior_val_len);
+
+ stream_is_big_endian = !get_CDR_octet(tvb,&my_offset);
+ decode_IOR(tvb, NULL, NULL, &my_offset, 0, stream_is_big_endian);
+
+ tvb_free(tvb);
+
+ }
+
+ g_free(out);
+
+ }
+
+ fclose(fp); /* be nice */
+
+ g_free(buf);
+}
+
+
+
+/*
+ * Init routine, setup our request hash stuff, or delete old ref's
+ *
+ * Cannot setup the module hash here as my init() may not be called before
+ * users start registering. So I will move the module_hash stuff to
+ * proto_register_giop, as is done with packet-rpc
+ *
+ *
+ *
+ * Also, setup our objectkey/repoid hash here.
+ *
+ */
+
+static void giop_init(void) {
+
+
+ /*
+ * Create objkey/repoid hash, use my "equal" and "hash" functions.
+ *
+ */
+
+ if (giop_objkey_hash)
+ g_hash_table_destroy(giop_objkey_hash);
+ if (giop_objkey_keys)
+ g_mem_chunk_destroy(giop_objkey_keys);
+ if (giop_objkey_vals)
+ g_mem_chunk_destroy(giop_objkey_vals);
+
+
+ /*
+ * Create hash, use my "equal" and "hash" functions.
+ *
+ */
+
+ giop_objkey_hash = g_hash_table_new(giop_hash_objkey_hash, giop_hash_objkey_equal);
+
+ giop_objkey_keys = g_mem_chunk_new("giop_objkey_keys",
+ sizeof(struct giop_object_key),
+ giop_objkey_init_count * sizeof(struct giop_object_key),
+ G_ALLOC_AND_FREE);
+
+ giop_objkey_vals = g_mem_chunk_new("giop_objkey_vals",
+ sizeof(struct giop_object_val),
+ giop_objkey_init_count * sizeof(struct giop_object_val),
+ G_ALLOC_AND_FREE);
+
+
+ /*
+ * Create complete_reply_hash, use my "equal" and "hash" functions.
+ *
+ */
+
+ if (giop_complete_reply_hash)
+ g_hash_table_destroy(giop_complete_reply_hash);
+ if (giop_complete_reply_keys)
+ g_mem_chunk_destroy(giop_complete_reply_keys);
+ if (giop_complete_reply_vals)
+ g_mem_chunk_destroy(giop_complete_reply_vals);
+
+
+ /*
+ * Create hash, use my "equal" and "hash" functions.
+ *
+ */
+
+ giop_complete_reply_hash = g_hash_table_new(complete_reply_hash_fn, complete_reply_equal_fn);
+
+ giop_complete_reply_keys = g_mem_chunk_new("giop_complete_reply_keys",
+ sizeof(struct complete_reply_hash_key),
+ complete_reply_hash_count * sizeof(struct complete_reply_hash_key),
+ G_ALLOC_AND_FREE);
+
+ giop_complete_reply_vals = g_mem_chunk_new("giop_complete_reply_vals",
+ sizeof(struct complete_reply_hash_val),
+ complete_reply_hash_count * sizeof(struct complete_reply_hash_val),
+ G_ALLOC_AND_FREE);
+
+
+
+ read_IOR_strings_from_file("IOR.txt", 600); /* testing */
+
+
+}
+
+
+/*
+ * Insert an entry in the GIOP Heuristic User table.
+ * Uses a GList.
+ * Uses giop_sub_handle_t to wrap giop user info.
+ *
+ */
+
+void register_giop_user(giop_sub_dissector_t *sub, gchar *name, int sub_proto) {
+
+ giop_sub_handle_t *subh;
+
+ subh = g_malloc(sizeof (giop_sub_handle_t));
+
+ subh->sub_name = name;
+ subh->sub_fn = sub;
+ subh->sub_proto = find_protocol_by_id(sub_proto); /* protocol_t for sub dissectors's proto_register_protocol() */
+
+ giop_sub_list = g_slist_append (giop_sub_list, subh);
+
+}
+
+
+/*
+ * Lookup an object key in our object key hash, and return the corresponding
+ * Repo Id.
+ *
+ */
+
+static gchar * get_repoid_from_objkey(GHashTable *hash, guint8 *obj, guint32 len) {
+
+ struct giop_object_key objkey_key;
+ struct giop_object_val *objkey_val = NULL;
+
+ objkey_key.objkey_len = len; /* length */
+ objkey_key.objkey = obj; /* object key octet sequence */
+
+ /* Look it up to see if it exists */
+
+ objkey_val = (struct giop_object_val *)g_hash_table_lookup(hash, &objkey_key);
+
+ if (objkey_val) {
+#if DEBUG
+ printf("Lookup of object key returns RepoId = %s \n",objkey_val->repo_id );
+#endif
+ return objkey_val->repo_id; /* found */
+ }
+
+#if DEBUG
+ printf("FAILED Lookup of object key \n" );
+#endif
+
+ return NULL; /* not found */
+}
+
+
+
+/*
+ * Extract top level module/interface from repoid
+ *
+ * eg from - "IDL:Echo/interface1:1.0"
+ * get "Echo"
+ *
+ * Or, from "IDL:linux.org/Penguin/Teeth:1.0" get
+ * get linux.org/Penguin/Teeth
+ *
+ *
+ * User must free returned ptr after use.
+ *
+ * TODO -- generalize for other Repoid encodings
+ */
+
+static gchar * get_modname_from_repoid(gchar *repoid) {
+
+ gchar *modname = NULL;
+ gchar *saved_repoid = NULL;
+ gchar c = 'a';
+ guint8 stop_mod = 0; /* Index of last character of modname in Repoid */
+ guint8 start_mod = 4; /* Index where Module name starts in repoid */
+ int i;
+
+ saved_repoid = g_strdup(repoid); /* make a copy */
+
+ /* Must start with IDL: , otherwise I get confused */
+
+ if (g_strncasecmp("IDL:",repoid,4))
+ return NULL;
+
+ /* Looks like a RepoID to me, so get Module or interface name */
+
+ /* TODO -- put some code here to get Module name */
+
+ for(i=4; c != '\0'; i++) {
+ c = repoid[i];
+ stop_mod = i; /* save */
+ if (c == ':' ) /* delimiters */
+ break;
+
+ }
+
+ /* Now create a new string based on start and stop and \0 */
+
+ modname = g_strndup(repoid+4, stop_mod - start_mod);
+
+ return modname;
+
+}
+
+/*
+ * DEBUG CODE
+ *
+ */
+
+
+#if DEBUG
+
+/*
+ * Display a "module" hash entry
+ */
+
+static void display_module_hash(gpointer key, gpointer val, gpointer user_data) {
+
+ struct giop_module_val *mv = (struct giop_module_val *) val;
+ struct giop_module_key *mk = (struct giop_module_key *) key;
+
+ printf("giop:module: Key = (%s) , Val = (%s) \n", mk->module, mv->subh->sub_name);
+
+ return;
+
+}
+
+/*
+ * Display a "complete_reply " hash entry
+ */
+
+static void display_complete_reply_hash(gpointer key, gpointer val, gpointer user_data) {
+
+ struct complete_reply_hash_val *mv = (struct complete_reply_hash_val *) val;
+ struct complete_reply_hash_key *mk = (struct complete_reply_hash_key *) key;
+
+ printf("giop:complete_reply: FN (key) = %8u , MFN (val) = %8u \n", mk->fn, mv->mfn);
+
+ return;
+
+}
+
+
+/*
+ * Display an "objkey" hash entry
+ */
+
+static void display_objkey_hash(gpointer key, gpointer val, gpointer user_data) {
+ guint32 i;
+ struct giop_object_val *mv = (struct giop_object_val *) val;
+ struct giop_object_key *mk = (struct giop_object_key *) key;
+
+
+ printf("giop:objkey: Key->objkey_len = %u, Key->objkey ", mk->objkey_len);
+
+ for (i=0; i<mk->objkey_len; i++) {
+ printf("%.2x ", mk->objkey[i]);
+ }
+
+ /*
+ * If read from file, mark it as such..
+ */
+
+ if(mv->src == 0) {
+ printf(", Repo ID = %s \n", mv->repo_id);
+ }
+ else {
+ printf(", Repo ID = %s , (file) \n", mv->repo_id);
+ }
+
+ return;
+
+}
+
+/*
+ * Display all giop_sub_list (GSList) entries
+ */
+
+static void display_heuristic_user_list() {
+ int i;
+ int len;
+ giop_sub_handle_t *subh; /* handle */
+
+ /* Get length of list */
+ len = g_slist_length(giop_sub_list); /* find length */
+
+ if (len == 0)
+ return;
+
+ for (i=0; i<len; i++) {
+ subh = ( giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab entry */
+ printf("giop:heuristic_user: Element = %i, Val (user) = %s \n", i, subh->sub_name);
+ }
+
+}
+
+/*
+ * Display all complete_request_list (GList) entries
+ */
+
+static void display_complete_request_list() {
+ int i;
+ int len;
+ comp_req_list_entry_t *entry;
+
+ /* Get length of list */
+ len = g_list_length(giop_complete_request_list); /* find length */
+
+ if (len == 0)
+ return;
+
+ for (i=0; i<len; i++) {
+ entry = (comp_req_list_entry_t *) g_list_nth_data(giop_complete_request_list,i); /* grab entry */
+ printf("giop:Index = %8i , FN = %8i, reqid = %8u , operation = %20s , repoid = %30s \n", i, entry->fn,
+ entry->reqid,entry->operation, entry->repoid);
+ }
+
+}
+
+
+
+
+/* Dump Hash/List contents
+ *
+ * collection_type specifies the list or hash to dump
+ *
+ */
+
+static void giop_dump_collection(collection_data_t collection_type) {
+
+ switch(collection_type) {
+ case cd_heuristic_users:
+ printf("+----------------------------------------------+ \n");
+ printf("+-------------- Heuristic User (Begin) --------+ \n");
+ printf("+----------------------------------------------+ \n");
+
+ display_heuristic_user_list();
+
+ printf("+----------------------------------------------+ \n");
+ printf("+-------------- Heuristic User (End) ----------+ \n");
+ printf("+----------------------------------------------+ \n");
+
+ break;
+
+ case cd_complete_request_list:
+ printf("+----------------------------------------------+ \n");
+ printf("+------------- Complete Request List (Begin) --+ \n");
+ printf("+----------------------------------------------+ \n");
+
+ display_complete_request_list();
+
+ printf("+----------------------------------------------+ \n");
+ printf("+------------ Complete Request List (End) -----+ \n");
+ printf("+----------------------------------------------+ \n");
+
+ break;
+
+ case cd_module_hash:
+ printf("+----------------------------------------------+ \n");
+ printf("+-------------- Module (Begin) ----------------+ \n");
+ printf("+----------------------------------------------+ \n");
+
+ g_hash_table_foreach(giop_module_hash, display_module_hash, NULL);
+
+ printf("+----------------------------------------------+ \n");
+ printf("+-------------- Module ( End) -----------------+ \n");
+ printf("+----------------------------------------------+ \n\n");
+
+ break;
+
+ case cd_objkey_hash:
+ printf("+----------------------------------------------+ \n");
+ printf("+-------------- Objkey (Begin) ----------------+ \n");
+ printf("+----------------------------------------------+ \n");
+
+ g_hash_table_foreach(giop_objkey_hash, display_objkey_hash,NULL);
+
+ printf("+----------------------------------------------+ \n");
+ printf("+-------------- Objkey (End) ------------------+ \n");
+ printf("+----------------------------------------------+ \n\n");
+
+ break;
+
+ case cd_complete_reply_hash:
+ printf("+----------------------------------------------+ \n");
+ printf("+-------------- Complete_Reply_Hash (Begin) ---+ \n");
+ printf("+----------------------------------------------+ \n");
+
+ g_hash_table_foreach(giop_complete_reply_hash, display_complete_reply_hash, NULL);
+
+ printf("+----------------------------------------------+ \n");
+ printf("+------------- Complete_Reply_Hash (End) ------+ \n");
+ printf("+----------------------------------------------+ \n");
+
+ break;
+
+ default:
+
+ printf("giop: giop_dump_collection: Unknown type \n");
+
+ }
+
+
+}
+
+
+#endif /* DEBUG */
+
+/*
+ * Loop through all subdissectors, and call them until someone
+ * answers (returns TRUE). This function then returns TRUE, otherwise
+ * it return FALSE
+ *
+ * But skip a subdissector if it has been disabled in GUI "edit protocols".
+ */
+
+static gboolean try_heuristic_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
+ MessageHeader *header, gchar *operation ) {
+
+ int i,len;
+ gboolean res = FALSE; /* result of calling a heuristic sub dissector */
+ giop_sub_handle_t *subh = NULL;
+ const char *saved_proto;
+
+ len = g_slist_length(giop_sub_list); /* find length */
+
+ if (len == 0)
+ return FALSE;
+
+ saved_proto = pinfo->current_proto;
+ for (i=0; i<len; i++) {
+ subh = (giop_sub_handle_t *) g_slist_nth_data(giop_sub_list,i); /* grab dissector handle */
+
+ if (proto_is_protocol_enabled(subh->sub_proto)) {
+ pinfo->current_proto =
+ proto_get_protocol_short_name(subh->sub_proto);
+ res = (subh->sub_fn)(tvb,pinfo,tree,offset,header,operation,NULL); /* callit TODO - replace NULL */
+ if (res) {
+ pinfo->current_proto = saved_proto;
+ return TRUE; /* found one, lets return */
+ }
+ } /* protocol_is_enabled */
+ } /* loop */
+
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
+
+ pinfo->current_proto = saved_proto;
+ return res; /* result */
+
+}
+
+
+/*
+ * Find the matching repoid in the module hash and call
+ * the dissector function if offset exists.
+ *
+ *
+ * Repoid is eg IDL:tux.antarctic/Penguin/Teeth:1.0 but subdissectors
+ * will register possibly "tux.antarctic/Penguin" and "tux.antarctic/Penguin/Teeth".
+ *
+ *
+ *
+ */
+
+static gboolean try_explicit_giop_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
+ MessageHeader *header, gchar *operation, gchar *repoid ) {
+
+ giop_sub_handle_t *subdiss = NULL; /* handle */
+ gboolean res = FALSE;
+ gchar *modname = NULL;
+ struct giop_module_key module_key;
+ struct giop_module_val *module_val = NULL;
+ const char *saved_proto;
+
+
+ /*
+ * Get top level module/interface from complete repoid
+ */
+
+ modname = get_modname_from_repoid(repoid);
+ if (modname == NULL) {
+ return res; /* unknown module name */
+ }
+
+
+ /* Search for Module or interface name */
+
+ module_key.module = modname; /* module name */
+ module_val = (struct giop_module_val *)g_hash_table_lookup(giop_module_hash, &module_key);
+
+ if (module_val == NULL) {
+ return res; /* module not registered */
+ }
+
+ subdiss = (giop_sub_handle_t *) module_val->subh; /* grab dissector handle */
+
+ if (subdiss) {
+ /* Add giop_sub_handle_t and repoid into complete_request_list, so REPLY can */
+ /* look it up directly, later ie: FN -> MFN -> giop_sub_handle_t and repoid */
+ /* but only if user not clicking */
+
+ if (!pinfo->fd->flags.visited)
+ add_sub_handle_repoid_to_comp_req_list(pinfo->fd->num,subdiss,repoid);
+
+
+ /* Call subdissector if current offset exists , and dissector is enabled in GUI "edit protocols" */
+
+ if (tvb_offset_exists(tvb, *offset)) {
+#if DEBUG
+ printf("giop:try_explicit_dissector calling sub = %s with module = (%s) \n", subdiss->sub_name , modname);
+#endif
+
+ if (proto_is_protocol_enabled(subdiss->sub_proto)) {
+
+ saved_proto = pinfo->current_proto;
+ pinfo->current_proto =
+ proto_get_protocol_short_name(subdiss->sub_proto);
+ res = (subdiss->sub_fn)(tvb,pinfo,tree,offset,header,operation, modname); /* callit, TODO replace NULL with idlname */
+ pinfo->current_proto = saved_proto;
+
+ } /* protocol_is_enabled */
+ } /* offset exists */
+ } /* subdiss */
+
+ return res; /* return result */
+}
+
+
+
+/* Take in an array of char and create a new string.
+ * Replace non-printable characters with periods.
+ *
+ * The array may contain \0's so dont use strdup
+ * The string is \0 terminated, and thus longer than
+ * the initial sequence.
+ * Caller must free the new string.
+ */
+
+static gchar * make_printable_string (gchar *in, guint32 len) {
+ guint32 i = 0;
+ gchar *print_string = NULL;
+
+ print_string = (gchar * )g_malloc0(len + 1); /* make some space and zero it */
+ memcpy(print_string, in, len); /* and make a copy of input data */
+
+ for(i=0; i < len; i++) {
+ if( !isprint( (unsigned char)print_string[i] ) )
+ print_string[i] = '.';
+ }
+
+ return print_string; /* return ptr */
+}
+
+/* Determine the byte order from the GIOP MessageHeader */
+
+gboolean is_big_endian (MessageHeader * header) {
+ gboolean big_endian = FALSE;
+
+ switch (header->GIOP_version.minor) {
+ case 2:
+ case 1:
+ if (header->flags & 0x01)
+ big_endian = FALSE;
+ else
+ big_endian = TRUE;
+ break;
+ case 0:
+ if (header->flags)
+ big_endian = FALSE;
+ else
+ big_endian = TRUE;
+ break;
+ default:
+ break;
+ }
+ return big_endian;
+}
+
+
+
+/*
+ * Calculate new offset, based on the current offset, and user supplied
+ * "offset delta" value, and the alignment requirement.
+ *
+ *
+ *
+ * eg: Used for GIOP 1.2 where Request and Reply bodies are
+ * aligned on 8 byte boundaries.
+ */
+
+static void set_new_alignment(int *offset, int delta, int alignment) {
+
+ while( ( (*offset + delta) % alignment) != 0)
+ ++(*offset);
+
+
+}
+
+
+
+/*
+ * ------------------------------------------------------------------------------------------+
+ * Public get_CDR_xxx functions.
+ * ------------------------------------------------------------------------------------------+
+ */
+
+
+
+/*
+ * Gets data of type any. This is encoded as a TypeCode
+ * followed by the encoded value.
+ */
+
+void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, int boundary,
+ MessageHeader * header ) {
+
+ guint32 TCKind; /* TypeCode */
+
+ /* get TypeCode of any */
+ TCKind = get_CDR_typeCode(tvb, tree, offset, stream_is_big_endian, boundary, header );
+
+ /* dissect data of type TCKind */
+ dissect_data_for_typecode(tvb, tree, offset, stream_is_big_endian, boundary, header, TCKind );
+}
+
+
+/* Copy a 1 octet sequence from the tvbuff
+ * which represents a boolean value, and convert
+ * it to a boolean value.
+ * Offset is then incremented by 1, to indicate the 1 octet which
+ * has been processed.
+ */
+
+gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset) {
+ guint8 val;
+
+ val = tvb_get_guint8(tvb, *offset); /* easy */
+ (*offset)++;
+ return val;
+}
+
+/* Copy a 1 octet sequence from the tvbuff
+ * which represents a char, and convert
+ * it to an char value.
+ * offset is then incremented by 1, to indicate the 1 octet which
+ * has been processed.
+ */
+
+guint8 get_CDR_char(tvbuff_t *tvb, int *offset) {
+ guint8 val;
+
+ val = tvb_get_guint8(tvb, *offset); /* easy */
+ (*offset)++;
+ return val;
+}
+
+
+
+/*
+ * Floating Point Data Type double IEEE 754-1985
+ *
+ * Copy an 8 octet sequence from the tvbuff
+ * which represents a double value, and convert
+ * it to a double value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for double values.
+ * offset is then incremented by 8, to indicate the 8 octets which
+ * have been processed.
+ */
+
+gdouble get_CDR_double(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
+
+ gdouble val;
+
+ /* double values must be aligned on a 8 byte boundary */
+
+ while( ( (*offset + boundary) % 8) != 0)
+ ++(*offset);
+
+ val = (stream_is_big_endian) ? tvb_get_ntohieee_double (tvb, *offset) :
+ tvb_get_letohieee_double (tvb, *offset);
+
+ *offset += 8;
+ return val;
+
+}
+
+
+/* Copy a 4 octet sequence from the tvbuff
+ * which represents an enum value, and convert
+ * it to an enum value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for an enum (4)
+ * offset is then incremented by 4, to indicate the 4 octets which
+ * have been processed.
+ *
+ * Enum values are encoded as unsigned long.
+ */
+
+
+guint32 get_CDR_enum(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
+
+ return get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary );
+
+}
+
+
+/*
+ * Copy an octet sequence from the tvbuff
+ * which represents a Fixed point decimal type, and create a string representing
+ * a Fixed point decimal type. There are no alignment restrictions.
+ * Size and scale of fixed decimal type is determined by IDL.
+ *
+ * digits - IDL specified number of "digits" for this fixed type
+ * scale - IDL specified "scale" for this fixed type
+ *
+ *
+ * eg: typedef fixed <5,2> fixed_t;
+ * could represent numbers like 123.45, 789.12,
+ *
+ *
+ * As the fixed type could be any size, I will not try to fit it into our
+ * simple types like gdouble or glong etc. I will just create a string buffer holding
+ * a representation (after scale is applied), and with a decimal point or zero padding
+ * inserted at the right place if necessary. The string is null terminated
+ *
+ * so string may look like
+ *
+ *
+ * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
+ *
+ * According to spec, digits <= 31
+ * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
+ * or <4,0> ?
+ *
+ * User must remember to free the buffer
+ *
+ */
+
+
+void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset, guint32 digits, gint32 scale) {
+
+ guint8 sign; /* 0x0c is positive, 0x0d is negative */
+ guint32 i ; /* loop */
+ guint32 slen; /* number of bytes to hold digits + extra 0's if scale <0 */
+ /* this does not include sign, decimal point and \0 */
+ guint32 sindex = 0; /* string index */
+ gchar *tmpbuf; /* temp buff, holds string without scaling */
+ guint8 tval; /* temp val storage */
+
+ /*
+ * how many bytes to hold digits and scale (if scale <0)
+ *
+ * eg: fixed <5,2> = 5 digits
+ * fixed <5,-2> = 7 digits (5 + 2 added 0's)
+ */
+
+#if DEBUG
+ printf("giop:get_CDR_fixed() called , digits = %u, scale = %u \n", digits, scale);
+#endif
+
+ if (scale <0) {
+ slen = digits - scale; /* allow for digits + padding 0's for negative scal */
+ } else {
+ slen = digits; /* digits */
+ }
+
+#if DEBUG
+ printf("giop:get_CDR_fixed(): slen = %.2x \n", slen);
+#endif
+
+ tmpbuf = g_new0(gchar, slen); /* allocate temp buffer */
+
+ /*
+ * Register a cleanup function in case on of our tvbuff accesses
+ * throws an exception. We need to clean up tmpbuf.
+ */
+ CLEANUP_PUSH(g_free, tmpbuf);
+
+ /* If even , grab 1st dig */
+
+ if (!(digits & 0x01)) {
+ tval = get_CDR_octet(tvb,offset);
+#if DEBUG
+ printf("giop:get_CDR_fixed():even: octet = %.2x \n", tval);
+#endif
+ tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert top nibble to ascii */
+ sindex++;
+ }
+
+ /*
+ * Loop, but stop BEFORE we hit last digit and sign
+ * if digits = 1 or 2, then this part is skipped
+ */
+
+ if (digits>2) {
+ for(i=0; i< ((digits-1)/2 ); i++) {
+ tval = get_CDR_octet(tvb,offset);
+#if DEBUG
+ printf("giop:get_CDR_fixed():odd: octet = %.2x \n", tval);
+#endif
+
+ tmpbuf[sindex] = ((tval & 0xf0) >> 4) + 0x30; /* convert top nibble to ascii */
+ sindex++;
+ tmpbuf[sindex] = (tval & 0x0f) + 0x30; /* convert bot nibble to ascii */
+ sindex++;
+
+ }
+ } /* digits > 3 */
+
+#if DEBUG
+ printf("giop:get_CDR_fixed(): before last digit \n");
+#endif
+
+
+ /* Last digit and sign if digits >1, or 1st dig and sign if digits = 1 */
+
+ tval = get_CDR_octet(tvb,offset);
+#if DEBUG
+ printf("giop:get_CDR_fixed(): octet = %.2x \n", tval);
+#endif
+ tmpbuf[sindex] = (( tval & 0xf0)>> 4) + 0x30; /* convert top nibble to ascii */
+ sindex++;
+
+ sign = tval & 0x0f; /* get sign */
+
+ /* So now, we have all digits in an array, and the sign byte
+ * so lets generate a printable string, taking into account the scale
+ * and sign values.
+ */
+
+ sindex = 0; /* reset */
+ *seq = g_new0(gchar, slen + 3); /* allocate temp buffer , including space for sign, decimal point and
+ * \0 -- TODO check slen is reasonable first */
+#if DEBUG
+ printf("giop:get_CDR_fixed(): sign = %.2x \n", sign);
+#endif
+
+ switch(sign) {
+ case 0x0c:
+ (*seq)[sindex] = '+'; /* put sign in first string position */
+ break;
+ case 0x0d:
+ (*seq)[sindex] = '-';
+ break;
+ default:
+ g_warning("giop: Unknown sign value in fixed type %u \n", sign);
+ (*seq)[sindex] = '*'; /* flag as sign unkown */
+ break;
+ }
+
+ sindex++;
+
+ /* Add decimal point or padding 0's, depending if scale is positive or
+ * negative, respectively
+ */
+
+ if (scale>0) {
+ for (i=0; i<digits-scale; i++) {
+ (*seq)[sindex] = tmpbuf[i]; /* digits to the left of the decimal point */
+ sindex++;
+ }
+
+ (*seq)[sindex] = '.'; /* decimal point */
+ sindex++;
+
+ for (i=digits-scale; i<digits; i++) {
+ (*seq)[sindex] = tmpbuf[i]; /* remaining digits to the right of the decimal point */
+ sindex++;
+ }
+
+ (*seq)[sindex] = '\0'; /* string terminator */
+
+ } else {
+
+ /* negative scale, dump digits and pad out with 0's */
+
+ for (i=0; i<digits-scale; i++) {
+ if (i<digits) {
+ (*seq)[sindex] = tmpbuf[i]; /* save digits */
+ } else {
+ (*seq)[sindex] = '0'; /* all digits used up, so pad with 0's */
+ }
+ sindex++;
+ }
+
+ (*seq)[sindex] = '\0'; /* string terminator */
+
+ }
+
+ /*
+ * We're done with tmpbuf, so we can call the cleanup handler to free
+ * it, and then pop the cleanup handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
+#if DEBUG
+ printf("giop:get_CDR_fixed(): value = %s \n", *seq);
+#endif
+
+ return;
+
+}
+
+
+
+/*
+ * Floating Point Data Type float IEEE 754-1985
+ *
+ * Copy an 4 octet sequence from the tvbuff
+ * which represents a float value, and convert
+ * it to a float value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for float values.
+ * offset is then incremented by 4, to indicate the 4 octets which
+ * have been processed.
+ */
+
+gfloat get_CDR_float(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
+
+ gfloat val;
+
+ /* float values must be aligned on a 4 byte boundary */
+
+ while( ( (*offset + boundary) % 4) != 0)
+ ++(*offset);
+
+ val = (stream_is_big_endian) ? tvb_get_ntohieee_float (tvb, *offset) :
+ tvb_get_letohieee_float (tvb, *offset);
+
+ *offset += 4;
+ return val;
+
+}
+
+
+/*
+ * Decode an Interface type, and display it on the tree.
+ */
+
+void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
+ gboolean stream_is_big_endian, int boundary) {
+
+
+ decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
+
+ return;
+}
+
+
+/* Copy a 4 octet sequence from the tvbuff
+ * which represents a signed long value, and convert
+ * it to an signed long vaule, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for long values.
+ * offset is then incremented by 4, to indicate the 4 octets which
+ * have been processed.
+ */
+
+gint32 get_CDR_long(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
+
+ gint32 val;
+
+ /* unsigned long values must be aligned on a 4 byte boundary */
+ while( ( (*offset + boundary) % 4) != 0)
+ ++(*offset);
+
+ val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
+ tvb_get_letohl (tvb, *offset);
+
+ *offset += 4;
+ return val;
+}
+
+/*
+ * Decode an Object type, and display it on the tree.
+ */
+
+void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
+ gboolean stream_is_big_endian, int boundary) {
+
+ decode_IOR(tvb, pinfo, tree, offset, boundary, stream_is_big_endian);
+
+ return;
+}
+
+
+/* Copy a 1 octet sequence from the tvbuff
+ * which represents a octet, and convert
+ * it to an octet value.
+ * offset is then incremented by 1, to indicate the 1 octet which
+ * has been processed.
+ */
+
+guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
+ guint8 val;
+
+ val = tvb_get_guint8(tvb, *offset); /* easy */
+ (*offset)++;
+ return val;
+}
+
+
+/* Copy a sequence of octets from the tvbuff.
+ * Caller of this function must remember to free the
+ * array pointed to by seq.
+ * This function also increments offset by len.
+ */
+
+void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
+
+ /*
+ * Make sure that the entire sequence of octets is in the buffer before
+ * allocating the buffer, so that we don't have to worry about freeing
+ * the buffer, and so that we don't try to allocate a buffer bigger
+ * than the data we'll actually be copying, and thus don't run the risk
+ * of crashing if the buffer is *so* big that we fail to allocate it
+ * and "g_new0()" aborts.
+ */
+ tvb_ensure_bytes_exist(tvb, *offset, len);
+
+ /*
+ * XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
+ * do what we do now, and null-terminate the string (which also means
+ * we don't need to zero out the entire allocation, just the last byte)?
+ */
+ *seq = g_new0(gchar, len + 1);
+ tvb_memcpy( tvb, *seq, *offset, len);
+ *offset += len;
+}
+
+
+/* Copy a 2 octet sequence from the tvbuff
+ * which represents a signed short value, and convert
+ * it to a signed short value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for short values.
+ * offset is then incremented by 2, to indicate the 2 octets which
+ * have been processed.
+ */
+
+gint16 get_CDR_short(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
+
+ gint16 val;
+
+ /* short values must be aligned on a 2 byte boundary */
+ while( ( (*offset + boundary) % 2) != 0)
+ ++(*offset);
+
+ val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
+ tvb_get_letohs (tvb, *offset);
+
+ *offset += 2;
+ return val;
+}
+
+
+
+/* Copy an octet sequence from the tvbuff
+ * which represents a string, and convert
+ * it to an string value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for string values. (begins with an unsigned long LI)
+ *
+ * String sequence is copied to a buffer "seq". This must
+ * be freed by the calling program.
+ * offset is then incremented, to indicate the octets which
+ * have been processed.
+ *
+ * returns number of octets in the sequence
+ *
+ * Note: This function only supports single byte encoding at the
+ * moment until I get a handle on multibyte encoding etc.
+ *
+ */
+
+
+guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
+ int boundary ) {
+
+ guint32 slength;
+
+ slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get length first */
+
+#if 0
+ (*offset)++; /* must step past \0 delimiter */
+#endif
+
+ if (slength > 0) {
+ get_CDR_octet_seq(tvb, seq, offset, slength);
+ } else {
+ *seq = g_strdup(""); /* zero-length string */
+ }
+
+ return slength; /* return length */
+
+}
+
+/* Process a sequence of octets that represent the
+ * Pseudo Object Type "TypeCode". Typecodes are used for example,
+ * by "Any values".
+ * This function also increments offset to the correct position.
+ *
+ * It will parse the TypeCode and output data to the "tree" provided
+ * by the user
+ *
+ * It returns a guint32 representing a TCKind value.
+ */
+
+guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, int boundary,
+ MessageHeader * header ) {
+ guint32 val;
+
+ gint16 s_octet2; /* signed int16 */
+ guint16 u_octet2; /* unsigned int16 */
+ guint32 u_octet4; /* unsigned int32 */
+
+ val = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get TCKind enum */
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_TCKind,tvb,
+ *offset-sizeof(val),4,val);
+ }
+
+ /* Grab the data according to Typecode Table - Corba Chapter 15 */
+
+ switch (val) {
+ case tk_null: /* empty parameter list */
+ break;
+ case tk_void: /* empty parameter list */
+ break;
+ case tk_short: /* empty parameter list */
+ break;
+ case tk_long: /* empty parameter list */
+ break;
+ case tk_ushort: /* empty parameter list */
+ break;
+ case tk_ulong: /* empty parameter list */
+ break;
+ case tk_float: /* empty parameter list */
+ break;
+ case tk_double: /* empty parameter list */
+ break;
+ case tk_boolean: /* empty parameter list */
+ break;
+ case tk_char: /* empty parameter list */
+ break;
+ case tk_octet: /* empty parameter list */
+ break;
+ case tk_any: /* empty parameter list */
+ break;
+ case tk_TypeCode: /* empty parameter list */
+ break;
+ case tk_Principal: /* empty parameter list */
+ break;
+ case tk_objref: /* complex parameter list */
+ dissect_tk_objref_params(tvb, tree, offset, stream_is_big_endian, boundary);
+ break;
+ case tk_struct: /* complex parameter list */
+ dissect_tk_struct_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
+ break;
+ case tk_union: /* complex parameter list */
+ dissect_tk_union_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
+ break;
+ case tk_enum: /* complex parameter list */
+ dissect_tk_enum_params(tvb, tree, offset, stream_is_big_endian, boundary);
+ break;
+
+ case tk_string: /* simple parameter list */
+ u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
+ *offset-sizeof(u_octet4),4,u_octet4);
+ }
+ break;
+
+ case tk_sequence: /* complex parameter list */
+ dissect_tk_sequence_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
+ break;
+ case tk_array: /* complex parameter list */
+ dissect_tk_array_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
+ break;
+ case tk_alias: /* complex parameter list */
+ dissect_tk_alias_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
+ break;
+ case tk_except: /* complex parameter list */
+ dissect_tk_except_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
+ break;
+ case tk_longlong: /* empty parameter list */
+ break;
+ case tk_ulonglong: /* empty parameter list */
+ break;
+ case tk_longdouble: /* empty parameter list */
+ break;
+ case tk_wchar: /* empty parameter list */
+ break;
+ case tk_wstring: /* simple parameter list */
+ u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary); /* get maximum length */
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
+ *offset-sizeof(u_octet4),4,u_octet4);
+ }
+ break;
+
+ case tk_fixed: /* simple parameter list */
+ u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary); /* get digits */
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_digits,tvb,
+ *offset-sizeof(u_octet2),2,u_octet2);
+ }
+
+ s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary); /* get scale */
+ if (tree) {
+ proto_tree_add_int(tree,hf_giop_typecode_scale,tvb,
+ *offset-sizeof(s_octet2),2,s_octet2);
+ }
+ break;
+
+ case tk_value: /* complex parameter list */
+ dissect_tk_value_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
+ break;
+ case tk_value_box: /* complex parameter list */
+ dissect_tk_value_box_params(tvb, tree, offset, stream_is_big_endian, boundary, header );
+ break;
+ case tk_native: /* complex parameter list */
+ dissect_tk_native_params(tvb, tree, offset, stream_is_big_endian, boundary);
+ break;
+ case tk_abstract_interface: /* complex parameter list */
+ dissect_tk_abstract_interface_params(tvb, tree, offset, stream_is_big_endian, boundary );
+ break;
+ default:
+ g_warning("giop: Unknown TCKind %u \n", val);
+ break;
+ } /* val */
+
+ return val;
+}
+
+
+
+/* Copy a 4 octet sequence from the tvbuff
+ * which represents an unsigned long value, and convert
+ * it to an unsigned long vaule, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for unsigned long values.
+ * offset is then incremented by 4, to indicate the 4 octets which
+ * have been processed.
+ */
+
+guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
+
+ guint32 val;
+
+ /* unsigned long values must be aligned on a 4 byte boundary */
+ while( ( (*offset + boundary) % 4) != 0)
+ ++(*offset);
+
+ val = (stream_is_big_endian) ? tvb_get_ntohl (tvb, *offset) :
+ tvb_get_letohl (tvb, *offset);
+
+ *offset += 4;
+ return val;
+}
+
+
+/* Copy a 2 octet sequence from the tvbuff
+ * which represents an unsigned short value, and convert
+ * it to an unsigned short value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for unsigned short values.
+ * offset is then incremented by 2, to indicate the 2 octets which
+ * have been processed.
+ */
+
+guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian, int boundary) {
+
+ guint16 val;
+
+ /* unsigned short values must be aligned on a 2 byte boundary */
+ while( ( (*offset + boundary) % 2) != 0)
+ ++(*offset);
+
+ val = (stream_is_big_endian) ? tvb_get_ntohs (tvb, *offset) :
+ tvb_get_letohs (tvb, *offset);
+
+ *offset += 2;
+ return val;
+}
+
+
+
+/* Copy a wchar from the tvbuff.
+ * Caller of this function must remember to free the
+ * array pointed to by seq.
+ * This function also increments offset according to
+ * the wchar size.
+ *
+ * For GIOP 1.1 read 2 octets and return size -2. The
+ * negation means there is no size element in the packet
+ * and therefore no size to add to the tree.
+ *
+ * For GIOP 1.2 read size of wchar and the size
+ * octets. size is returned as a gint8.
+ *
+ * For both GIOP versions the wchar is returned
+ * as a printable string.
+ *
+ */
+
+/* NOTE: This is very primitive in that it just reads
+ * the wchar as a series of octets and returns them
+ * to the user. No translation is attempted based on
+ * byte orientation, nor on code set. I.e it only
+ * really reads past the wchar and sets the offset
+ * correctly.
+ */
+
+/* The "decoding" is done according to CORBA chapter 15.
+ * Wchar is not supported for GIOP 1.0.
+ */
+
+gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
+
+ gint slength;
+ gchar *raw_wstring;
+
+ /* CORBA chapter 15:
+ * - prior to GIOP 1.2 wchar limited to two octet fixed length.
+ * - GIOP 1.2 wchar is encoded as an unsigned binary octet
+ * followed by the elements of the octet sequence representing
+ * the encoded value of the wchar.
+ */
+
+ *seq = NULL; /* set in case GIOP 1.2 length is 0 */
+ slength = 2; /* set for GIOP 1.1 length in octets */
+
+ if (header->GIOP_version.minor > 1) /* if GIOP 1.2 get length of wchar */
+ slength = get_CDR_octet(tvb,offset);
+
+ if (slength > 0) {
+ /* ??? assume alignment is ok for GIOP 1.1 ??? */
+ get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
+
+ /* now turn octets (wchar) into something that can be printed by the user */
+ *seq = make_printable_string(raw_wstring, slength);
+
+ g_free(raw_wstring);
+ }
+
+ /* if GIOP 1.1 negate length to indicate not an item to add to tree */
+ if (header->GIOP_version.minor < 2)
+ slength = -slength;
+
+ return slength; /* return length */
+
+}
+
+
+/* Copy a wstring from the tvbuff.
+ * Caller of this function must remember to free the
+ * array pointed to by seq.
+ * This function also increments offset, according to
+ * wstring length. length is returned as guint32
+ */
+
+/* NOTE: This is very primitive in that it just reads
+ * the wstring as a series of octets and returns them
+ * to the user. No translation is attempted based on
+ * byte orientation, nor on code set. I.e it only
+ * really reads past the wstring and sets the offset
+ * correctly.
+ */
+
+/* The "decoding" is done according to CORBA chapter 15.
+ * Wstring is not supported for GIOP 1.0.
+ */
+
+
+guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset, gboolean stream_is_big_endian,
+ int boundary, MessageHeader * header) {
+
+ guint32 slength;
+ gchar *raw_wstring;
+
+ /* CORBA chapter 15:
+ * - prior to GIOP 1.2 wstring limited to two octet fixed length.
+ * length and string are NUL terminated (length???).
+ * - GIOP 1.2 length is total number of octets. wstring is NOT NUL
+ * terminated.
+ */
+
+ *seq = NULL; /* set in case GIOP 1.2 length is 0 */
+
+ /* get length, same for all GIOP versions,
+ * although for 1.2 CORBA doesnt say, so assume.
+ */
+ slength = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+
+#ifdef DEBUG
+ if (slength>200) {
+ fprintf(stderr, "giop:get_CDR_wstring, length %u > 200, truncating to 5 \n", slength);
+ slength = 5; /* better than core dumping during debug */
+ }
+#endif
+
+ if (header->GIOP_version.minor < 2) {
+#if 0
+ (*offset)++; /* must step past \0 delimiter */
+#endif
+ /* assume length is number of characters and not octets, spec not clear */
+ slength = slength * 2; /* length in octets is 2 * wstring length */
+ }
+
+ if (slength > 0) {
+ get_CDR_octet_seq(tvb, &raw_wstring, offset, slength);
+
+ /* now turn octets (wstring) into something that can be printed by the user */
+ *seq = make_printable_string(raw_wstring, slength);
+
+ g_free(raw_wstring);
+ }
+
+ return slength; /* return length */
+
+}
+
+
+
+/**
+ * Dissects a TargetAddress which is defined in (CORBA 2.4, section 15.4.2)
+ * GIOP 1.2
+ * typedef short AddressingDisposition;
+ * const short KeyAddr = 0;
+ * const short ProfileAddr = 1;
+ * const short ReferenceAddr = 2;
+ * struct IORAddressingInfo {
+ * unsigned long selected_profile_index;
+ * IOP::IOR ior;
+ * };
+ *
+ * union TargetAddress switch (AddressingDisposition) {
+ * case KeyAddr: sequence <octet> object_key;
+ * case ProfileAddr: IOP::TaggedProfile profile;
+ * case ReferenceAddr: IORAddressingInfo ior;
+ * };
+ */
+
+static void
+dissect_target_address(tvbuff_t * tvb, packet_info *pinfo, int *offset, proto_tree * tree,
+ gboolean stream_is_big_endian)
+{
+ guint16 discriminant;
+ gchar *object_key;
+ gchar *p_object_key;
+ guint32 len = 0;
+ guint32 u_octet4;
+
+ discriminant = get_CDR_ushort(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if(tree)
+ {
+ proto_tree_add_text (tree, tvb, *offset -2, 2,
+ "TargetAddress Discriminant: %u", discriminant);
+ }
+
+ switch (discriminant)
+ {
+ case 0: /* KeyAddr */
+ len = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if(tree)
+ {
+ proto_tree_add_text (tree, tvb, *offset -4, 4,
+ "KeyAddr (object key length): %u", len);
+ }
+
+ if (len > 0) {
+
+ get_CDR_octet_seq(tvb, &object_key, offset, len);
+ p_object_key = make_printable_string( object_key, len );
+
+ if(tree)
+ {
+ proto_tree_add_text (tree, tvb, *offset -len, len,
+ "KeyAddr (object key): %s", p_object_key);
+ }
+ g_free( p_object_key );
+ g_free( object_key );
+ }
+ break;
+ case 1: /* ProfileAddr */
+ decode_TaggedProfile(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE,
+ stream_is_big_endian, NULL);
+ break;
+ case 2: /* ReferenceAddr */
+ u_octet4 = get_CDR_ulong(tvb, offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+
+ if(tree)
+ {
+ proto_tree_add_text (tree, tvb, *offset -len -4, 4,
+ "ReferenceAddr (selected_profile_index): %u", u_octet4);
+ }
+
+ decode_IOR(tvb, pinfo, tree, offset, GIOP_HEADER_SIZE, stream_is_big_endian);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+dissect_reply_body (tvbuff_t *tvb, guint offset, packet_info *pinfo,
+ proto_tree *tree, gboolean stream_is_big_endian,
+ guint32 reply_status, MessageHeader *header, proto_tree *clnp_tree) {
+
+ guint sequence_length;
+ gboolean exres = FALSE; /* result of trying explicit dissectors */
+ gchar * repoid = NULL; /* Repositor ID looked up from objkey */
+
+ /*
+ * comp_req_list stuff
+ */
+
+ comp_req_list_entry_t * entry = NULL; /* data element in our list */
+
+ guint32 mfn;
+
+ switch (reply_status)
+ {
+ case SYSTEM_EXCEPTION:
+
+ decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
+ break;
+
+ case USER_EXCEPTION:
+
+ sequence_length = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+
+ if (tree)
+ {
+ proto_tree_add_text(tree, tvb, offset-4, 4,
+ "Exception length: %u", sequence_length);
+ }
+ if (sequence_length != 0)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, tvb, offset, sequence_length,
+ "Exception id: %s",
+ tvb_format_text(tvb, offset, sequence_length));
+ }
+#if 1
+
+ header->exception_id = g_new0(gchar,sequence_length ); /* allocate buffer */
+
+ /* read exception id from buffer and store in*/
+
+ tvb_get_nstringz0(tvb,offset,sequence_length, header->exception_id );
+
+
+#endif
+
+
+ offset += sequence_length;
+ }
+
+
+
+ /*
+ * Now just fall through to the NO_EXCEPTION part
+ * as this is common .
+ */
+
+
+
+ case NO_EXCEPTION:
+
+
+ /* lookup MFN in hash directly */
+
+ mfn = get_mfn_from_fn(pinfo->fd->num);
+
+ if (mfn == pinfo->fd->num)
+ return; /* no matching frame number, what am I */
+
+ /* get entry for this MFN */
+ entry = find_fn_in_list(mfn); /* get data entry in complete_request_list */
+
+ if (!entry)
+ return; /* no matching entry */
+
+
+ /*
+ * If this packet is a REPLY to a RESOLVE(request)
+ * then decode IOR.
+ * TODO - make this lookup faster -- FS
+ */
+
+ if (!strcmp(giop_op_resolve,entry->operation)) {
+ decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE,stream_is_big_endian);
+ return; /* done */
+ }
+
+ /* TODO -- Put stuff here for other "interesting operations" */
+
+ /*
+ *
+ * Call sub dissector.
+ * First try an find a explicit sub_dissector, then if that
+ * fails, try the heuristic method.
+ */
+
+
+ if(entry->repoid) {
+ exres = try_explicit_giop_dissector(tvb,pinfo,clnp_tree, &offset, header, entry->operation, entry->repoid );
+ }
+
+ /* Only call heuristic if no explicit dixxector was found */
+
+ if(! exres) {
+ try_heuristic_giop_dissector(tvb,pinfo,clnp_tree,&offset,header,entry->operation);
+ }
+
+
+ break;
+
+ case LOCATION_FORWARD:
+ decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
+
+ break;
+
+ case LOCATION_FORWARD_PERM:
+ decode_IOR(tvb, pinfo, tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
+
+ break;
+
+ case NEEDS_ADDRESSING_MODE: {
+ guint16 addr_disp;
+ addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
+ if(tree) {
+ proto_tree_add_text (tree, tvb, offset -2, 2,
+ "AddressingDisposition: %u", addr_disp);
+ }
+
+ break;
+ }
+
+ default:
+
+ g_warning("giop: Unknown reply status %i request_id = %u\n",reply_status, header->req_id);
+
+ break;
+
+ } /* switch */
+
+ g_free(repoid); /* free resource */
+
+ return; /* done */
+
+}
+
+
+
+
+
+/* The format of the Reply Header for GIOP 1.0 and 1.1
+ * is documented in Section 15.4.3.1 of the CORBA 2.4 standard.
+
+ struct ReplyHeader_1_0 {
+ IOP::ServiceContextList service_context;
+ unsigned long request_id;
+ ReplyStatusType_1_0 reply_status;
+ };
+ */
+
+static void dissect_giop_reply (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
+ MessageHeader * header,
+ gboolean stream_is_big_endian) {
+
+ guint32 offset = 0;
+ guint32 request_id;
+ guint32 reply_status;
+ proto_tree *reply_tree = NULL;
+ proto_item *tf;
+ guint32 mfn; /* matching frame number */
+
+ if (tree) {
+ tf = proto_tree_add_text (tree, tvb, offset, -1,
+ "General Inter-ORB Protocol Reply");
+ if (reply_tree == NULL)
+ {
+ reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
+
+ }
+ }
+
+ /*
+ * Decode IOP::ServiceContextList
+ */
+
+ decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
+
+ request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
+ }
+
+ if (tree) {
+ proto_tree_add_text (reply_tree, tvb, offset-4, 4,
+ "Request id: %u", request_id);
+ }
+
+ reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
+ val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
+
+ }
+
+ if (tree) {
+ proto_tree_add_text (reply_tree, tvb, offset-4, 4,
+ "Reply status: %s",
+ val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
+
+ }
+
+ /*
+ * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
+ */
+
+ if (! pinfo->fd->flags.visited) {
+ mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
+ if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
+ insert_in_complete_reply_hash(pinfo->fd->num, mfn);
+ }
+ }
+
+ header->req_id = request_id; /* save for sub dissector */
+ header->rep_status = reply_status; /* save for sub dissector */
+
+ dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
+ reply_status, header,tree);
+
+
+}
+
+/** The format of the GIOP 1.2 Reply header is very similar to the 1.0
+ * and 1.1 header, only the fields have been rearranged. From Section
+ * 15.4.3.1 of the CORBA 2.4 specification:
+ *
+ * struct ReplyHeader_1_2 {
+ * unsigned long request_id;
+ * ReplyStatusType_1_2 reply_status;
+ * IOP:ServiceContextList service_context;
+ * };
+ */
+
+static void dissect_giop_reply_1_2 (tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree,
+ MessageHeader * header,
+ gboolean stream_is_big_endian) {
+
+ guint offset = 0;
+ guint32 request_id;
+ guint32 reply_status;
+ proto_tree *reply_tree = NULL;
+ proto_item *tf;
+ guint32 mfn; /* matching frame number */
+
+ if (tree) {
+ tf = proto_tree_add_text (tree, tvb, offset, -1,
+ "General Inter-ORB Protocol Reply");
+ reply_tree = proto_item_add_subtree (tf, ett_giop_reply);
+ }
+
+ request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
+ }
+
+ if (tree) {
+ proto_tree_add_text (reply_tree, tvb, offset-4, 4,
+ "Request id: %u", request_id);
+ }
+
+ reply_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
+ val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
+
+ }
+
+ if (tree) {
+ proto_tree_add_text (reply_tree, tvb, offset-4, 4,
+ "Reply status: %s",
+ val_to_str(reply_status, reply_status_types, "Unknown (%u)"));
+
+ }
+
+ /*
+ * Decode IOP::ServiceContextList
+ */
+
+ decode_ServiceContextList(tvb, reply_tree, &offset,stream_is_big_endian, GIOP_HEADER_SIZE);
+
+ /*
+ * GIOP 1.2 Reply body must fall on an 8 octet alignment.
+ */
+
+ set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
+
+ /*
+ * Save FN and MFN in complete_reply_hash, only if user is NOT clicking
+ */
+
+ if (! pinfo->fd->flags.visited) {
+ mfn = get_mfn_from_fn_and_reqid(pinfo->fd->num,request_id); /* find MFN for this FN */
+ if (mfn != pinfo->fd->num) { /* if mfn is not fn, good */
+ insert_in_complete_reply_hash(pinfo->fd->num, mfn);
+ }
+ }
+
+ /*
+ * Add header to argument list so sub dissector can get header info.
+ */
+
+ header->req_id = request_id; /* save for sub dissector */
+ header->rep_status = reply_status; /* save for sub dissector */
+
+ dissect_reply_body(tvb, offset, pinfo, reply_tree, stream_is_big_endian,
+ reply_status,header,tree);
+
+}
+
+
+
+static void dissect_giop_cancel_request (tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree,
+ gboolean stream_is_big_endian) {
+
+ guint offset = 0;
+ guint32 request_id;
+ proto_tree *cancel_request_tree = NULL;
+ proto_item *tf;
+
+ if (tree) {
+ tf = proto_tree_add_text (tree, tvb, offset, -1,
+ "General Inter-ORB Protocol CancelRequest");
+ cancel_request_tree = proto_item_add_subtree (tf, ett_giop_cancel_request);
+ }
+
+ request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
+ }
+
+ if (tree) {
+ proto_tree_add_text (cancel_request_tree, tvb, offset-4, 4,
+ "Request id: %u", request_id);
+ }
+
+
+}
+
+/** The formats for GIOP 1.0 and 1.1 Request messages are defined
+ * in section 15.4.2.1 of the CORBA 2.4 specification.
+ *
+ * struct RequestHeader{
+ * IOP::ServiceContextList service_context;
+ * unsigned long request_id;
+ * boolean response_expected;
+ * octet reserved[3]; // Only in GIOP 1.1
+ * sequence<octet> object_key;
+ * string operation;
+ * CORBA::OctetSeq requesting_principal;
+ * }
+ */
+static void
+dissect_giop_request_1_1 (tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree,
+ MessageHeader * header, gboolean stream_is_big_endian)
+{
+ guint32 offset = 0;
+ guint32 request_id;
+ guint32 len = 0;
+
+ guint32 objkey_len = 0; /* object key length */
+ gchar *objkey = NULL; /* object key sequence */
+ gchar *print_objkey; /* printable object key sequence */
+ gboolean exres = FALSE; /* result of trying explicit dissectors */
+
+ gchar *operation;
+ gchar *requesting_principal;
+ gchar *print_requesting_principal;
+ guint8 response_expected;
+ gchar *reserved;
+ proto_tree *request_tree = NULL;
+ proto_item *tf;
+
+ gchar *repoid = NULL; /* from object key lookup in objkey hash */
+
+
+ if (tree)
+ {
+ tf = proto_tree_add_text (tree, tvb, offset, -1,
+ "General Inter-ORB Protocol Request");
+ if (request_tree == NULL)
+ {
+ request_tree = proto_item_add_subtree (tf, ett_giop_request);
+
+ }
+ }
+
+
+
+ /*
+ * Decode IOP::ServiceContextList
+ */
+
+ decode_ServiceContextList(tvb, request_tree, &offset,stream_is_big_endian, 0);
+
+
+ request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
+ }
+ if (tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset-4, 4,
+ "Request id: %u", request_id);
+ }
+
+ response_expected = tvb_get_guint8( tvb, offset );
+ offset += 1;
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
+ response_expected ? "two-way" : "one-way");
+ }
+ if (tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset-1, 1,
+ "Response expected: %u", response_expected);
+ }
+
+ if( header->GIOP_version.minor > 0)
+ {
+ get_CDR_octet_seq( tvb, &reserved, &offset, 3);
+ if (tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset-3, 3,
+ "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
+ }
+ g_free(reserved);
+ }
+
+
+
+ /* Length of object_key sequence */
+ objkey_len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+
+
+ if(tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset-4, 4,
+ /**/ "Object Key length: %u", objkey_len);
+ }
+
+ if (objkey_len > 0)
+ {
+ get_CDR_octet_seq(tvb, &objkey, &offset, objkey_len);
+
+ print_objkey = make_printable_string(objkey, objkey_len);
+
+ if(tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset - objkey_len, objkey_len,
+ /**/ "Object Key: %s", print_objkey);
+
+ }
+
+ g_free( print_objkey );
+ }
+
+ /*
+ * Register a cleanup function in case on of our tvbuff accesses
+ * throws an exception. We need to clean up objkey.
+ */
+ CLEANUP_PUSH(g_free, objkey);
+
+ /* length of operation string and string */
+ len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if(tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset - 4 - len, 4,
+ /**/ "Operation length: %u", len);
+ }
+
+ if( len > 0)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
+ }
+ if(tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset - len, len,
+ /**/ "Operation: %s", operation);
+
+ }
+ }
+
+ /*
+ * Register a cleanup function in case on of our tvbuff accesses
+ * throws an exception. We need to clean up operation.
+ */
+ CLEANUP_PUSH(g_free, operation);
+
+ /* length of requesting_principal string */
+ len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if(tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset-4, 4,
+ /**/ "Requesting Principal Length: %u", len);
+ }
+
+ if( len > 0)
+ {
+ get_CDR_octet_seq(tvb, &requesting_principal, &offset, len);
+
+ print_requesting_principal = make_printable_string(requesting_principal, len);
+
+ if(tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset - len, len,
+ /**/ "Requesting Principal: %s", print_requesting_principal);
+
+ }
+
+ g_free( print_requesting_principal );
+ g_free( requesting_principal );
+ }
+
+
+ /*
+ * Save FN,reqid,and operation for later. Add sub_handle later.
+ * But only if user is NOT clicking.
+ */
+
+ if (! pinfo->fd->flags.visited)
+ giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
+ request_id,operation,NULL);
+
+
+ /*
+ * Call subdissector here before freeing "operation" and "key"
+ * pass request_id also.
+ * First try an find an explicit sub_dissector, then if that
+ * fails, try the heuristic method.
+ *
+ */
+
+
+ header->req_id = request_id; /* save for sub dissector */
+ repoid = get_repoid_from_objkey(giop_objkey_hash,objkey,objkey_len);
+
+
+ if(repoid) {
+ exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
+ }
+
+ /* Only call heuristic if no explicit dissector was found */
+
+ if (! exres) {
+ try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
+ }
+
+
+ /*
+ * We're done with operation, so we can call the cleanup handler to free
+ * it, and then pop the cleanup handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
+ /*
+ * We're done with objkey, so we can call the cleanup handler to free
+ * it, and then pop the cleanup handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
+}
+
+/** The format of a GIOP 1.2 RequestHeader message is
+ * (CORBA 2.4, sec. 15.4.2):
+ *
+ * struct RequestHeader_1_2 {
+ * unsigned long request_id;
+ * octet response_flags;
+ * octet reserved[3];
+ * TargetAddress target;
+ * string operation;
+ * IOP::ServiceContextList service_context;
+ * // requesting_principal not in GIOP 1.2
+ * };
+ */
+static void
+dissect_giop_request_1_2 (tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree,
+ MessageHeader * header, gboolean stream_is_big_endian)
+{
+ guint32 offset = 0;
+ guint32 request_id;
+ guint32 len = 0;
+ guint8 response_flags;
+ gchar *reserved;
+ gchar *operation = NULL;
+ proto_tree *request_tree = NULL;
+ proto_item *tf;
+ gboolean exres = FALSE; /* result of trying explicit dissectors */
+
+ gchar *repoid = NULL;
+
+
+ if (tree)
+ {
+ tf = proto_tree_add_text (tree, tvb, offset, -1,
+ "General Inter-ORB Protocol Request");
+ request_tree = proto_item_add_subtree (tf, ett_giop_reply);
+ }
+
+ request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
+ }
+ if (request_tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset-4, 4,
+ "Request id: %u", request_id);
+ }
+
+ response_flags = tvb_get_guint8( tvb, offset );
+ offset += 1;
+ if (request_tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset-1, 1,
+ "Response flags: %s (%u)",
+ match_strval(response_flags, sync_scope),
+ response_flags);
+ }
+
+ get_CDR_octet_seq( tvb, &reserved, &offset, 3);
+ if (request_tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset-3, 3,
+ "Reserved: %x %x %x", reserved[0], reserved[1], reserved[2]);
+ }
+ g_free(reserved);
+
+ dissect_target_address(tvb, pinfo, &offset, request_tree, stream_is_big_endian);
+
+ /* length of operation string */
+ len = get_CDR_string(tvb, &operation, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if(tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset - len - 4, 4,
+ /**/ "Operation length: %u", len);
+ }
+
+ if( len > 0)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", operation);
+ }
+ if(request_tree)
+ {
+ proto_tree_add_text (request_tree, tvb, offset - len, len,
+ /**/ "Operation: %s", operation);
+
+ }
+
+ }
+
+ /*
+ * Register a cleanup function in case on of our tvbuff accesses
+ * throws an exception. We need to clean up operation.
+ */
+ CLEANUP_PUSH(g_free, operation);
+
+ /*
+ * Decode IOP::ServiceContextList
+ */
+
+ decode_ServiceContextList(tvb, request_tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
+
+ /*
+ * GIOP 1.2 Request body must fall on an 8 octet alignment, taking into
+ * account we are in a new tvbuff, GIOP_HEADER_SIZE octets from the
+ * GIOP octet stream start.
+ */
+
+ set_new_alignment(&offset, GIOP_HEADER_SIZE, 8);
+
+ /*
+ * Save FN,reqid,and operation for later. Add sub_handle later.
+ * But only if user is NOT clicking.
+ */
+
+ if (! pinfo->fd->flags.visited)
+ giop_complete_request_list = insert_in_comp_req_list(giop_complete_request_list,pinfo->fd->num,
+ request_id,operation,NULL);
+
+ /*
+ *
+ * Call sub dissector.
+ * First try an find a explicit sub_dissector, then if that
+ * fails, try the heuristic method.
+ */
+
+
+ if(repoid) {
+ exres = try_explicit_giop_dissector(tvb,pinfo,tree,&offset,header,operation,repoid);
+ }
+
+ /* Only call heuristic if no explicit dissector was found */
+
+ if (! exres) {
+ try_heuristic_giop_dissector(tvb,pinfo,tree,&offset,header,operation);
+ }
+
+
+ /*
+ * We're done with operation, so we can call the cleanup handler to free
+ * it, and then pop the cleanup handler.
+ */
+ CLEANUP_CALL_AND_POP;
+}
+
+static void
+dissect_giop_locate_request( tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree, MessageHeader * header,
+ gboolean stream_is_big_endian)
+{
+ guint32 offset = 0;
+ guint32 request_id;
+ guint32 len = 0;
+ gchar *object_key;
+ gchar *p_object_key;
+ proto_tree *locate_request_tree = NULL;
+ proto_item *tf;
+
+ if (tree)
+ {
+ tf = proto_tree_add_text (tree, tvb, offset, -1,
+ "General Inter-ORB Locate Request");
+ if (locate_request_tree == NULL)
+ {
+ locate_request_tree = proto_item_add_subtree (tf, ett_giop_locate_request);
+
+ }
+ }
+
+ request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
+ }
+ if (locate_request_tree)
+ {
+ proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
+ "Request id: %u", request_id);
+ }
+
+ if(header->GIOP_version.minor < 2)
+ {
+ len = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if (locate_request_tree)
+ {
+ proto_tree_add_text (locate_request_tree, tvb, offset-4, 4,
+ "Object Key length: %u", len);
+ }
+
+ if (len > 0) {
+ get_CDR_octet_seq(tvb, &object_key, &offset, len);
+
+ p_object_key = make_printable_string(object_key, len);
+
+ if(locate_request_tree)
+ {
+
+ proto_tree_add_text (locate_request_tree, tvb, offset-len, len,
+ "Object Key: %s", p_object_key);
+ }
+
+ g_free(p_object_key);
+ g_free(object_key);
+ }
+ }
+ else /* GIOP 1.2 and higher */
+ {
+ dissect_target_address(tvb, pinfo, &offset, locate_request_tree,
+ stream_is_big_endian);
+
+ }
+}
+
+static void
+dissect_giop_locate_reply( tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree, MessageHeader * header,
+ gboolean stream_is_big_endian)
+{
+ guint32 offset = 0;
+ guint32 request_id;
+ guint32 locate_status;
+ guint16 addr_disp;
+
+ proto_tree *locate_reply_tree = NULL;
+ proto_item *tf;
+
+ if (tree)
+ {
+ tf = proto_tree_add_text (tree, tvb, offset, -1,
+ "General Inter-ORB Locate Reply");
+ if (locate_reply_tree == NULL)
+ {
+ locate_reply_tree = proto_item_add_subtree (tf, ett_giop_locate_reply);
+
+ }
+ }
+
+ request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
+ }
+ if (locate_reply_tree)
+ {
+ proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
+ "Request id: %u", request_id);
+ }
+
+ locate_status = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if (locate_reply_tree)
+ {
+ proto_tree_add_text (locate_reply_tree, tvb, offset-4, 4,
+ "Locate status: %s",
+ match_strval(locate_status, giop_locate_status_types)
+ );
+ }
+
+ /* Decode the LocateReply body.
+ *
+ * For GIOP 1.0 and 1.1 body immediately follows header.
+ * For GIOP 1.2 it is aligned on 8 octet boundary so need to
+ * spin up.
+ */
+
+ if (header->GIOP_version.minor > 1) {
+ while( ( (offset + GIOP_HEADER_SIZE) % 8) != 0)
+ ++(offset);
+ }
+
+ switch(locate_status) {
+ case OBJECT_FORWARD: /* fall through to OBJECT_FORWARD_PERM */
+ case OBJECT_FORWARD_PERM:
+ decode_IOR(tvb, pinfo, locate_reply_tree, &offset, GIOP_HEADER_SIZE, stream_is_big_endian);
+ break;
+ case LOC_SYSTEM_EXCEPTION:
+ decode_SystemExceptionReplyBody (tvb, tree, &offset, stream_is_big_endian, GIOP_HEADER_SIZE);
+ break;
+ case LOC_NEEDS_ADDRESSING_MODE:
+ addr_disp = get_CDR_ushort(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if(locate_reply_tree) {
+ proto_tree_add_text (tree, tvb, offset -2, 2,
+ "AddressingDisposition: %u", addr_disp);
+ }
+ break;
+ default: /* others have no reply body */
+ break;
+ }
+
+}
+
+static void
+dissect_giop_fragment( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
+ gboolean stream_is_big_endian)
+{
+ guint32 offset = 0;
+ guint32 request_id;
+ proto_tree *fragment_tree = NULL;
+ proto_item *tf;
+
+ if (tree)
+ {
+ tf = proto_tree_add_text (tree, tvb, offset, -1,
+ "General Inter-ORB Fragment");
+ if (fragment_tree == NULL)
+ {
+ fragment_tree = proto_item_add_subtree (tf, ett_giop_fragment);
+
+ }
+ }
+
+ request_id = get_CDR_ulong(tvb, &offset, stream_is_big_endian,GIOP_HEADER_SIZE);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %u", request_id);
+ }
+ if (fragment_tree )
+ {
+ proto_tree_add_text (fragment_tree, tvb, offset-4, 4,
+ "Request id: %u", request_id);
+ }
+
+}
+
+
+/* Main entry point */
+
+gboolean dissect_giop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) {
+ guint offset = 0;
+ MessageHeader header;
+ tvbuff_t *giop_header_tvb;
+ tvbuff_t *payload_tvb;
+
+ proto_tree *clnp_tree = NULL;
+ proto_item *ti;
+ guint message_size;
+ guint minor_version;
+ gboolean stream_is_big_endian;
+
+
+ /* DEBUG */
+
+#if DEBUG
+ giop_dump_collection(cd_module_hash);
+ giop_dump_collection(cd_objkey_hash);
+ giop_dump_collection(cd_heuristic_users);
+ giop_dump_collection(cd_complete_reply_hash);
+ giop_dump_collection(cd_complete_request_list);
+#endif
+
+ header.exception_id = NULL;
+
+ /* check magic number and version */
+
+
+ /*define END_OF_GIOP_MESSAGE (offset - first_offset - GIOP_HEADER_SIZE) */
+
+ if (tvb_length_remaining(tvb, 0) < GIOP_HEADER_SIZE)
+ {
+ /* Not enough data captured to hold the GIOP header; don't try
+ to interpret it as GIOP. */
+ return FALSE;
+ }
+
+ giop_header_tvb = tvb_new_subset (tvb, 0, GIOP_HEADER_SIZE, -1);
+ payload_tvb = tvb_new_subset (tvb, GIOP_HEADER_SIZE, -1, -1);
+
+ /*
+ * because I have added extra elements in MessageHeader struct
+ * for sub dissectors. -- FS
+ */
+
+ tvb_memcpy (giop_header_tvb, (guint8 *)&header, 0, GIOP_HEADER_SIZE );
+
+ if (memcmp (header.magic, GIOP_MAGIC, sizeof (header.magic)) != 0)
+ {
+ /* Not a GIOP message. */
+
+ return FALSE;
+ }
+
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "GIOP");
+ }
+
+ if (header.GIOP_version.major != GIOP_MAJOR ||
+ ((minor_version = header.GIOP_version.minor) > GIOP_MINOR))
+ {
+ /* Bad version number; should we note that and dissect the rest
+ as data, or should we return FALSE on the theory that it
+ might have been some other packet that happened to begin with
+ "GIOP"? We shouldn't do *both*, so we return TRUE, for now.
+ If we should return FALSE, we should do so *without* setting
+ the "Info" column, *without* setting the "Protocol" column,
+ and *without* adding anything to the protocol tree. */
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "Version %u.%u",
+ header.GIOP_version.major, header.GIOP_version.minor);
+ }
+ if (tree)
+ {
+ ti = proto_tree_add_item (tree, proto_giop, tvb, 0, -1, FALSE);
+ clnp_tree = proto_item_add_subtree (ti, ett_giop);
+ proto_tree_add_text (clnp_tree, giop_header_tvb, 0, -1,
+ "Version %u.%u not supported",
+ header.GIOP_version.major,
+ header.GIOP_version.minor);
+ }
+ call_dissector(data_handle,payload_tvb, pinfo, tree);
+ return TRUE;
+ }
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
+ header.GIOP_version.major, header.GIOP_version.minor,
+ val_to_str(header.message_type, giop_message_types,
+ "Unknown message type (0x%02x)"));
+ }
+
+ stream_is_big_endian = is_big_endian (&header);
+
+ if (stream_is_big_endian)
+ message_size = pntohl (&header.message_size);
+ else
+ message_size = pletohl (&header.message_size);
+
+ if (tree)
+ {
+ ti = proto_tree_add_item (tree, proto_giop, tvb, 0, 12, FALSE);
+ clnp_tree = proto_item_add_subtree (ti, ett_giop);
+ proto_tree_add_text (clnp_tree, giop_header_tvb, offset, 4,
+ "Magic number: %s", GIOP_MAGIC);
+ proto_tree_add_text (clnp_tree, giop_header_tvb, 4, 2,
+ "Version: %u.%u",
+ header.GIOP_version.major,
+ header.GIOP_version.minor);
+ switch (minor_version)
+ {
+ case 2:
+ case 1:
+ proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
+ "Flags: 0x%02x (%s %s)",
+ header.flags,
+ (stream_is_big_endian) ? "big-endian" : "little-endian",
+ (header.flags & 0x02) ? " fragment" : "");
+ break;
+ case 0:
+ proto_tree_add_text (clnp_tree, giop_header_tvb, 6, 1,
+ "Byte ordering: %s-endian",
+ (stream_is_big_endian) ? "big" : "little");
+ break;
+ default:
+ break;
+ } /* minor_version */
+
+ proto_tree_add_uint_format (clnp_tree,
+ hf_giop_message_type,
+ giop_header_tvb, 7, 1,
+ header.message_type,
+ "Message type: %s", match_strval(header.message_type, giop_message_types));
+
+ proto_tree_add_uint (clnp_tree,
+ hf_giop_message_size,
+ giop_header_tvb, 8, 4, message_size);
+
+ } /* tree */
+
+#if 0
+ if (check_col (pinfo->cinfo, COL_INFO))
+ {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "GIOP %u.%u %s",
+ header.GIOP_version.major, header.GIOP_version.minor,
+ match_strval(header.message_type, giop_message_types));
+ }
+#endif
+
+ switch (header.message_type)
+ {
+
+ case Request:
+ if(header.GIOP_version.minor < 2)
+ {
+ dissect_giop_request_1_1 (payload_tvb, pinfo, tree,
+ &header, stream_is_big_endian);
+ }
+ else
+ {
+ dissect_giop_request_1_2 (payload_tvb, pinfo, tree,
+ &header, stream_is_big_endian);
+ }
+
+ break;
+
+
+ case Reply:
+ if(header.GIOP_version.minor < 2)
+ {
+ dissect_giop_reply (payload_tvb, pinfo, tree, &header,
+ stream_is_big_endian);
+ }
+ else
+ {
+ dissect_giop_reply_1_2 (payload_tvb, pinfo, tree,
+ &header, stream_is_big_endian);
+ }
+ break;
+ case CancelRequest:
+ dissect_giop_cancel_request(payload_tvb, pinfo, tree,
+ stream_is_big_endian);
+ break;
+ case LocateRequest:
+ dissect_giop_locate_request(payload_tvb, pinfo, tree, &header,
+ stream_is_big_endian);
+ break;
+ case LocateReply:
+ dissect_giop_locate_reply(payload_tvb, pinfo, tree, &header,
+ stream_is_big_endian);
+ break;
+ case Fragment:
+ dissect_giop_fragment(payload_tvb, pinfo, tree,
+ stream_is_big_endian);
+ break;
+ default:
+ break;
+
+ } /* switch message_type */
+
+
+ /*
+ * XXX - we should catch exceptions here, so that we can free
+ * this if an exception is thrown.
+ * We'd then have to forward the exception.
+ */
+ if (header.exception_id != NULL)
+ g_free(header.exception_id);
+
+ return TRUE;
+}
+
+void
+proto_register_giop (void)
+{
+ static hf_register_info hf[] = {
+ { &hf_giop_message_type,
+ { "Message type", "giop.type",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_message_size,
+ { "Message size", "giop.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_repoid,
+ { "Repository ID", "giop.repoid",
+ FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_string_length,
+ { "String Length", "giop.strlen",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_sequence_length,
+ { "Sequence Length", "giop.seqlen",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_profile_id,
+ { "Profile ID", "giop.profid",
+ FT_UINT32, BASE_DEC, VALS(profile_id_vals), 0x0, "", HFILL }
+ },
+
+
+ { &hf_giop_type_id,
+ { "IOR::type_id", "giop.typeid",
+ FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_iiop_v_maj,
+ { "IIOP Major Version", "giop.iiop_vmaj",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ }
+ ,
+ { &hf_giop_iiop_v_min,
+ { "IIOP Minor Version", "giop.iiop_vmin",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_endianess,
+ { "Endianess", "giop.endianess",
+ FT_UINT8, BASE_DEC, VALS(giop_endianess_vals), 0x0, "", HFILL }
+ },
+
+ { &hf_giop_IIOP_tag,
+ { "IIOP Component TAG", "giop.iioptag",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_IOR_tag,
+ { "IOR Profile TAG", "giop.iortag",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_TCKind,
+ { "TypeCode enum", "giop.TCKind",
+ FT_UINT32, BASE_DEC, VALS(tckind_vals), 0x0, "", HFILL }
+ },
+
+ { &hf_giop_typecode_count,
+ { "TypeCode count", "giop.tccount",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_typecode_default_used,
+ { "default_used", "giop.tcdefault_used",
+ FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_typecode_digits,
+ { "Digits", "giop.tcdigits",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+
+ { &hf_giop_typecode_length,
+ { "Length", "giop.tclength",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_typecode_max_length,
+ { "Maximum length", "giop.tcmaxlen",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_typecode_member_name,
+ { "TypeCode member name", "giop.tcmemname",
+ FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_typecode_name,
+ { "TypeCode name", "giop.tcname",
+ FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_typecode_scale,
+ { "Scale", "giop.tcscale",
+ FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_typecode_ValueModifier,
+ { "ValueModifier", "giop.tcValueModifier",
+ FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_typecode_Visibility,
+ { "Visibility", "giop.tcVisibility",
+ FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+
+
+ { &hf_giop_type_boolean,
+ { "TypeCode boolean data", "giop.tcboolean",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_type_char,
+ { "TypeCode char data", "giop.tcchar",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_type_double,
+ { "TypeCode double data", "giop.tcdouble",
+ FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_type_enum,
+ { "TypeCode enum data", "giop.tcenumdata",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ /*
+ * float as double ?? -- FIX
+ */
+
+ { &hf_giop_type_float,
+ { "TypeCode float data", "giop.tcfloat",
+ FT_DOUBLE, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_type_long,
+ { "TypeCode long data", "giop.tclongdata",
+ FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_type_octet,
+ { "TypeCode octet data", "giop.tcoctet",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_type_short,
+ { "TypeCode short data", "giop.tcshortdata",
+ FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_type_string,
+ { "TypeCode string data", "giop.tcstring",
+ FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_type_ulong,
+ { "TypeCode ulong data", "giop.tculongdata",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ { &hf_giop_type_ushort,
+ { "TypeCode ushort data", "giop.tcushortdata",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ /*
+ * IIOP Module - Chapter 15.10.2
+ */
+
+ { &hf_giop_iiop_host,
+ { "IIOP::Profile_host", "giop.iiop.host",
+ FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
+ }
+ ,
+
+ { &hf_giop_iiop_port,
+ { "IIOP::Profile_port", "giop.iiop.port",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ }
+ ,
+
+ /*
+ * IIOP ServiceContext
+ */
+
+ { &hf_giop_iop_vscid,
+ { "VSCID", "giop.iiop.vscid",
+ FT_UINT32, BASE_HEX, NULL, 0xffffff00, "", HFILL }
+ }
+ ,
+
+ { &hf_giop_iop_scid,
+ { "SCID", "giop.iiop.scid",
+ FT_UINT32, BASE_HEX, NULL, 0x000000ff, "", HFILL }
+ }
+ ,
+
+
+ };
+
+ static gint *ett[] = {
+ &ett_giop,
+ &ett_giop_reply,
+ &ett_giop_request,
+ &ett_giop_cancel_request,
+ &ett_giop_locate_request,
+ &ett_giop_locate_reply,
+ &ett_giop_fragment,
+ &ett_giop_scl,
+ &ett_giop_scl_st1,
+ &ett_giop_ior
+
+ };
+ proto_giop = proto_register_protocol("General Inter-ORB Protocol", "GIOP",
+ "giop");
+ proto_register_field_array (proto_giop, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+
+
+ /* register init routine */
+
+ register_init_routine( &giop_init); /* any init stuff */
+
+ /*
+ * Init the giop user module hash tables here, as giop users
+ * will populate it via register_giop_user_module BEFORE my
+ * own giop_init() is called.
+ */
+
+ giop_module_hash = g_hash_table_new(giop_hash_module_hash, giop_hash_module_equal);
+
+ giop_module_keys = g_mem_chunk_new("giop_module_keys",
+ sizeof(struct giop_module_key),
+ giop_module_init_count * sizeof(struct giop_module_key),
+ G_ALLOC_AND_FREE);
+
+ giop_module_vals = g_mem_chunk_new("giop_module_vals",
+ sizeof(struct giop_module_val),
+ giop_module_init_count * sizeof(struct giop_module_val),
+ G_ALLOC_AND_FREE);
+
+}
+
+
+
+void proto_reg_handoff_giop (void) {
+ data_handle = find_dissector("data");
+ heur_dissector_add("tcp", dissect_giop, proto_giop);
+ /* Support DIOP (GIOP/UDP) */
+ heur_dissector_add("udp", dissect_giop, proto_giop);
+}
+
+
+
+
+/*
+ * Decode IOR
+ *
+ * Ref Corba v2.4.2 Chapter 13
+ *
+ */
+
+/*
+
+module IOP{
+
+ typedef unsigned long ProfileId;
+
+ const ProfileId TAG_INTERNET_IOP = 0;
+ const ProfileId TAG_MULTIPLE_COMPONENTS = 1;
+
+ struct TaggedProfile {
+ ProfileId tag;
+ sequence <octet> profile_data;
+ };
+
+ struct IOR {
+ string type_id;
+ sequence <TaggedProfile> profiles;
+ };
+
+ typedef unsigned long ComponentId;
+
+ struct TaggedComponent {
+ ComponentId tag;
+ sequence <octet> component_data;
+ };
+
+ typedef sequence <TaggedComponent> MultipleComponentProfile;
+
+};
+
+*/
+
+void decode_IOR(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ptree, int *offset,
+ guint32 boundary, gboolean stream_is_big_endian) {
+
+
+ guint32 seqlen_p; /* sequence length of profiles */
+ guint32 u_octet4;
+
+ proto_tree *tree = NULL; /* IOR tree */
+ proto_item *tf;
+
+ gchar *repobuf; /* for repository ID */
+
+ guint32 i;
+
+ /* create a subtree */
+
+ if (ptree) {
+ tf = proto_tree_add_text (ptree, tvb, *offset, -1, "IOR");
+ tree = proto_item_add_subtree (tf, ett_giop_ior);
+ }
+
+
+ /* Get type_id == Repository ID */
+
+ u_octet4 = get_CDR_string(tvb,&repobuf,offset,stream_is_big_endian,boundary);
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_string_length,tvb,
+ *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
+ if (u_octet4 > 0) {
+ proto_tree_add_string(tree,hf_giop_type_id,tvb,
+ *offset-u_octet4,u_octet4,repobuf);
+ }
+ }
+
+ /*
+ * Register a cleanup function in case on of our tvbuff accesses
+ * throws an exception. We need to clean up repobuf.
+ * We can't free it yet, as we must wait until we have the object
+ * key, as we have to add both to the hash table.
+ */
+ CLEANUP_PUSH(g_free, repobuf);
+
+ /* Now get a sequence of profiles */
+ /* Get sequence length (number of elements) */
+
+ seqlen_p = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
+ *offset-sizeof(seqlen_p),4,seqlen_p);
+ }
+
+
+ /* fetch all TaggedProfiles in this sequence */
+
+ for (i=0; i< seqlen_p; i++) { /* for every TaggedProfile */
+ decode_TaggedProfile(tvb, pinfo, tree, offset, boundary, stream_is_big_endian, repobuf);
+ }
+
+ /*
+ * We're done with repobuf, so we can call the cleanup handler to free
+ * it, and then pop the cleanup handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
+}
+
+static void decode_TaggedProfile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
+ guint32 boundary, gboolean stream_is_big_endian, gchar *repobuf) {
+
+ guint32 seqlen_pd; /* sequence length of profile data */
+
+ guint32 pidtag; /* profile ID TAG */
+
+ gchar *profile_data; /* profile_data pointer */
+ gchar *p_profile_data; /* printable profile_data pointer */
+
+ guint32 new_boundary; /* for encapsulations encountered */
+ gboolean new_big_endianess; /* for encapsulations encountered */
+
+ /* Get ProfileId tag */
+
+ pidtag = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_profile_id,tvb,
+ *offset-sizeof(pidtag),4,pidtag);
+ }
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+
+ seqlen_pd = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_big_endianess, &new_boundary);
+
+ /* return if zero length sequence */
+
+ if(seqlen_pd == 0)
+ return;
+
+
+ /*
+ * Lets see what kind of TAG it is. If TAG_INTERNET_IOP then
+ * decode it, otherwise just dump the octet sequence
+ *
+ * also, store IOR in our objectkey hash
+ *
+ * TODO - handle other TAGS
+ */
+
+ switch(pidtag) {
+ case IOP_TAG_INTERNET_IOP:
+
+ decode_IIOP_IOR_profile(tvb, pinfo, tree, offset, new_boundary, new_big_endianess, repobuf, TRUE);
+ break;
+
+ default:
+
+ /* fetch all octets in this sequence , but skip endianess */
+
+ get_CDR_octet_seq(tvb, &profile_data, offset, seqlen_pd -1);
+
+ /* Make a printable string */
+
+ p_profile_data = make_printable_string( profile_data, seqlen_pd -1);
+
+ if(tree) {
+ proto_tree_add_text (tree, tvb, *offset -seqlen_pd + 1, seqlen_pd - 1,
+ "Profile Data: %s", p_profile_data);
+ }
+
+ g_free(p_profile_data);
+
+ g_free(profile_data);
+
+ break;
+
+ }
+
+}
+
+
+
+/*
+ * Decode IIOP IOR Profile
+ * Ref Chap 15.7.2 in Corba Spec
+ */
+
+
+static void decode_IIOP_IOR_profile(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset,
+ guint32 boundary, gboolean stream_is_big_endian, gchar *repo_id_buf,
+ gboolean store_flag) {
+
+ guint32 i; /* loop index */
+
+ guint8 v_major,v_minor; /* IIOP sersion */
+ gchar *buf;
+ guint32 u_octet4; /* u long */
+ guint16 u_octet2; /* u short */
+ guint32 seqlen; /* generic sequence length */
+ guint32 seqlen1; /* generic sequence length */
+ gchar *objkey; /* object key pointer */
+ gchar *p_chars; /* printable characters pointer */
+
+
+ /* Get major/minor version */
+
+ v_major = get_CDR_octet(tvb,offset);
+ v_minor = get_CDR_octet(tvb,offset);
+
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_iiop_v_maj,tvb,
+ *offset-sizeof(v_minor)-sizeof(v_major),1,v_major );
+ proto_tree_add_uint(tree,hf_giop_iiop_v_min,tvb,
+ *offset-sizeof(v_minor),1,v_minor );
+ }
+
+
+ /* host */
+
+ u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_string_length,tvb,
+ *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
+ if (u_octet4 > 0) {
+ proto_tree_add_string(tree,hf_giop_iiop_host,tvb,
+ *offset-u_octet4,u_octet4,buf);
+ }
+ }
+
+ g_free(buf); /* dont forget */
+
+ /* Port */
+
+ u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_iiop_port,tvb,
+ *offset-sizeof(u_octet2),2,u_octet2);
+ }
+
+
+ /* Object Key - sequence<octet> object_key */
+
+ seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
+ *offset-sizeof(seqlen),4,seqlen);
+ }
+
+ if (seqlen > 0) {
+ /* fetch all octets in this sequence */
+ get_CDR_octet_seq(tvb, &objkey, offset, seqlen);
+
+ /*
+ * Now we may have the Repository ID from earlier, as well
+ * as the object key sequence and lengh. So lets store them in
+ * our objectkey hash and free buffers.
+ *
+ * But only insert if user is not clicking and repo id not NULL.
+ *
+ */
+
+ if (repo_id_buf) {
+ if (pinfo) {
+ if(!pinfo->fd->flags.visited)
+ insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,req_res);
+ }
+ else {
+
+ /*
+ * No pinfo, but store anyway if flag set. eg: IOR read from file
+ */
+
+ if (store_flag)
+ insert_in_objkey_hash(giop_objkey_hash,objkey,seqlen,repo_id_buf,file);
+ }
+ }
+
+ /* Make a printable string */
+
+ p_chars = make_printable_string( objkey, seqlen );
+
+ if(tree) {
+ proto_tree_add_text (tree, tvb, *offset -seqlen, seqlen,
+ "Object Key: %s", p_chars);
+ }
+
+ g_free(p_chars);
+ g_free(objkey);
+ }
+
+ /*
+ * Now see if if its v1.1 or 1.2, as they can contain
+ * extra sequence of IOP::TaggedComponents
+ *
+ */
+
+ switch(v_minor) {
+ case 0:
+
+ /* nothing extra */
+ break;
+
+ case 1:
+ case 2:
+
+ /* sequence of IOP::TaggedComponents */
+ /* Ref Chap 13 in Corba Spec */
+
+ /* get sequence length */
+ seqlen = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
+ *offset-sizeof(seqlen),4,seqlen);
+ }
+
+ for (i=0; i< seqlen; i++) {
+ /* get tag */
+ u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_IIOP_tag,tvb,
+ *offset-sizeof(u_octet4),4,u_octet4);
+ }
+
+ /* get component_data */
+ seqlen1 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
+ *offset-sizeof(seqlen1),4,seqlen1);
+ }
+
+ if (seqlen1 > 0) {
+ get_CDR_octet_seq(tvb, &buf, offset, seqlen1);
+
+ if (tree) {
+ /* Make a printable string of data */
+
+ p_chars = make_printable_string(buf, seqlen1);
+
+ proto_tree_add_text (tree, tvb, *offset -seqlen1, seqlen1,
+ "component_data: %s", p_chars);
+
+ g_free(p_chars);
+ }
+
+ g_free(buf);
+ }
+
+ }
+
+
+ break;
+
+ default:
+ g_warning("giop:Invalid v_minor value = %u ", v_minor);
+ break;
+ }
+
+}
+
+/*
+ * From Section 13.10.2.5 of the CORBA 3.0 spec.
+ *
+ * module CONV_FRAME {
+ * typedef unsigned long CodeSetId;
+ * struct CodeSetContext {
+ * CodeSetId char_data;
+ * CodeSetId wchar_data;
+ * };
+ * };
+ *
+ * Code sets are identified by a 32-bit integer id from OSF.
+ * See: ftp://ftp.opengroup.org/pub/code_set_registry
+ */
+static void decode_CodeSets(tvbuff_t *tvb, proto_tree *tree, int *offset,
+ gboolean stream_is_be, guint32 boundary) {
+
+ /* The boundary being passed in is the offset where the context_data
+ * sequence begins. */
+
+ guint32 code_set_id;
+ if(tree) {
+ /* We pass in -boundary, because the alignment is calculated relative to
+ the beginning of the context_data sequence.
+ Inside get_CDR_ulong(), the calculation will be (offset +(- boundary)) % 4
+ to determine the correct alignment of the short. */
+ code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
+
+ proto_tree_add_text (tree, tvb, *offset - 4, 4,
+ "char_data: 0x%08x", code_set_id);
+
+ code_set_id = get_CDR_ulong(tvb, offset, stream_is_be, -((gint32) boundary) );
+
+ proto_tree_add_text (tree, tvb, *offset - 4, 4,
+ "wchar_data: 0x%08x", code_set_id);
+ }
+
+}
+
+/*
+ * From Section 2.7.3 of the Real-time CORBA 1.1 Standard, the CORBA priority
+ * is represented in the GIOP service request as:
+ *
+ * module IOP {
+ * typedef short ServiceId;
+ * const ServiceId RTCorbaPriority = 10;
+ * };
+ *
+ * The RT-CORBA priority is a CDR encoded short value in a sequence<octet>
+ * buffer.
+ */
+static void decode_RTCorbaPriority(tvbuff_t *tvb, proto_tree *tree, int *offset,
+ gboolean stream_is_be, guint32 boundary) {
+
+ /* The boundary being passed in is the offset where the context_data
+ * sequence begins. */
+
+ gint16 rtpriority;
+
+ /* RTCorbaPriority is stored as a CDR encoded short */
+ /* We pass in -boundary, because the alignment is calculated relative to
+ the beginning of the context_data sequence.
+ Inside get_CDR_short(), the calculation will be (offset + (- boundary)) % 2
+ to determine the correct alignment of the short. */
+ rtpriority = get_CDR_short(tvb, offset, stream_is_be, -((gint32) boundary) );
+
+ if(tree) {
+ /* Highlight all of context_data except for the first endian byte */
+ proto_tree_add_text (tree, tvb, *offset - 2, 2,
+ "RTCorbaPriority: %d", rtpriority);
+ }
+
+}
+
+static void decode_UnknownServiceContext(tvbuff_t *tvb, proto_tree *tree, int *offset,
+ gboolean stream_is_be, guint32 boundary) {
+
+ guint32 context_data_len;
+ gchar *p_context_data;
+ gchar *context_data;
+
+ /* get sequence length, and NO encapsulation */
+ context_data_len = get_CDR_ulong(tvb, offset, stream_is_be,boundary);
+
+
+ /* return if zero length sequence */
+ if(context_data_len == 0)
+ return;
+
+ /*
+ * Now decode sequence according to vendor ServiceId, but I dont
+ * have that yet, so just dump it as data.
+ */
+
+ /* fetch all octets in this sequence */
+
+ get_CDR_octet_seq(tvb, &context_data, offset, context_data_len);
+
+ /* Make a printable string */
+
+ p_context_data = make_printable_string( context_data, context_data_len );
+
+ if(tree) {
+ proto_tree_add_text (tree, tvb, *offset - context_data_len , context_data_len,
+ "context_data: %s", p_context_data);
+ }
+
+ g_free(context_data);
+ g_free(p_context_data);
+}
+
+/*
+ * Corba , chp 13.7
+ *
+ *
+ *
+ * typedef unsigned long ServiceID;
+ *
+ * struct ServiceContext {
+ * ServiceID context_id;
+ * sequence <octet> context_data;
+ * };
+ * typedef sequence <ServiceContext> ServiceContextList;
+ *
+ *
+ * Note: Spec says context_data is an encapsulation.
+ *
+ *
+ */
+
+void decode_ServiceContextList(tvbuff_t *tvb, proto_tree *ptree, int *offset,
+ gboolean stream_is_be, guint32 boundary) {
+
+ guint32 seqlen; /* sequence length */
+ guint32 context_data_len; /* context data sequence length */
+
+ proto_tree *tree = NULL; /* ServiceContext tree */
+ proto_tree *sub_tree1 = NULL;
+ proto_item *tf = NULL, *tf_st1;
+
+ guint32 context_id;
+
+ guint32 i;
+ guint32 vscid; /* Vendor Service context id */
+ guint32 scid;
+ const gchar *service_context_name;
+ gboolean encapsulation_is_be;
+ guint32 encapsulation_boundary;
+ int temp_offset, temp_offset1;
+ int start_offset = *offset;
+
+ /* create a subtree */
+
+ if (ptree) {
+ /* set length to 0 now and correct with proto_item_set_len() later */
+ tf = proto_tree_add_text (ptree, tvb, *offset, 0, "ServiceContextList");
+
+ tree = proto_item_add_subtree (tf, ett_giop_scl);
+ }
+
+ /* Get sequence length (number of elements) */
+ seqlen = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
+ *offset-sizeof(seqlen),4,seqlen);
+ }
+
+ /* return if zero length sequence */
+
+ if (seqlen == 0) {
+ if (tf)
+ proto_item_set_len(tf, *offset - start_offset);
+
+ return;
+ }
+
+ /* Loop for all ServiceContext's */
+
+ for (i=0; i<seqlen; i++) {
+
+ context_id = get_CDR_ulong(tvb,offset,stream_is_be,boundary);
+ vscid = (context_id & 0xffffff00) >> 8; /* vendor info, top 24 bits */
+ scid = context_id & 0x000000ff; /* standard service info, lower 8 bits */
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_iop_vscid,tvb,
+ *offset-sizeof(guint32),4,vscid);
+
+ proto_tree_add_uint(tree,hf_giop_iop_scid,tvb,
+ *offset-sizeof(guint32),4,scid);
+
+ }
+
+ if( vscid == 0) { /* OMG specified */
+ service_context_name = match_strval(scid, service_context_ids);
+ } else { /* Proprietary vscid */
+ service_context_name = NULL;
+ }
+
+ if ( service_context_name == NULL ) {
+ service_context_name = "Unknown";
+ }
+
+ if(tree) {
+ proto_tree_add_text (tree, tvb, *offset -sizeof(context_id), 4,
+ "Service Context ID: %s (%u)", service_context_name,
+ context_id);
+ }
+
+ temp_offset1 = *offset;
+ /* The OMG has vscid of 0 reserved */
+ if( vscid != 0 || scid > max_service_context_id ) {
+ decode_UnknownServiceContext(tvb, tree, offset, stream_is_be, boundary);
+ continue;
+ }
+
+ temp_offset = *offset;
+ /* get sequence length, new endianness and boundary for encapsulation */
+ context_data_len = get_CDR_encap_info(tvb, sub_tree1, offset,
+ stream_is_be, boundary,
+ &encapsulation_is_be , &encapsulation_boundary);
+
+ if (tree) {
+ tf_st1 = proto_tree_add_text (tree, tvb, temp_offset, sizeof(context_data_len) + context_data_len , service_context_name);
+ sub_tree1 = proto_item_add_subtree (tf_st1, ett_giop_scl_st1);
+ }
+
+ if (context_data_len == 0)
+ continue;
+
+ /* See CORBA 3.0.2 standard, section Section 15.3.3 "Encapsulation",
+ * for how CDR types can be marshalled into a sequence<octet>.
+ * The first octet in the sequence determines endian order,
+ * 0 == big-endian, 1 == little-endian
+ */
+
+ switch(scid)
+ {
+ case 0x01: /* Codesets */
+ decode_CodeSets(tvb, sub_tree1, offset,
+ encapsulation_is_be, encapsulation_boundary);
+ break;
+ case 0x0a: /* RTCorbaPriority */
+ decode_RTCorbaPriority(tvb, sub_tree1, offset,
+ encapsulation_is_be, encapsulation_boundary);
+ break;
+ default:
+
+ /* Need to fill these in as we learn them */
+ *offset = temp_offset1;
+ decode_UnknownServiceContext(tvb, sub_tree1, offset, stream_is_be,
+ boundary);
+ break;
+ }
+ /* Set the offset to the end of the context_data sequence */
+ *offset = temp_offset1 + sizeof(context_data_len) + context_data_len;
+
+ } /* for seqlen */
+
+ if (tf)
+ proto_item_set_len(tf, *offset - start_offset);
+
+}
+
+/* Decode SystemExceptionReplyBody as defined in the CORBA spec chapter 15.
+ */
+
+static void decode_SystemExceptionReplyBody (tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian,
+ guint32 boundary) {
+
+ guint32 length; /* string length */
+ guint32 minor_code_value;
+ guint32 completion_status;
+
+ gchar *buf; /* pointer to string buffer */
+
+ length = get_CDR_string(tvb, &buf, offset, stream_is_big_endian, boundary);
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, *offset-4, 4,
+ "Exception length: %u", length);
+ if (length > 0) {
+ proto_tree_add_text(tree, tvb, *offset - length, length,
+ "Exception id: %s", buf );
+ }
+ }
+ g_free(buf);
+
+ minor_code_value = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
+ completion_status = get_CDR_ulong(tvb, offset, stream_is_big_endian, boundary);
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, *offset-8, 4,
+ "Minor code value: %u", minor_code_value);
+ proto_tree_add_text(tree, tvb, *offset-4, 4,
+ "Completion Status: %u", completion_status);
+ }
+}
+
+
+/*
+ * Helper functions for dissecting TypeCodes
+ *
+ * These functions decode the complex parameter lists
+ * of TypeCodes as defined in the CORBA spec chapter 15.
+ */
+
+static void dissect_tk_objref_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 seqlen; /* sequence length */
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+}
+
+
+static void dissect_tk_struct_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header ) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 count; /* parameter count (of tuples) */
+ guint32 seqlen; /* sequence length */
+ guint32 i; /* loop index */
+
+ /* get sequence lengt,h new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+ /* get count of tuples */
+ count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
+ *offset-sizeof(count),4,count);
+ }
+
+ /* get all tuples */
+ for (i=0; i< count; i++) {
+ /* get member name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_member_name);
+
+ /* get member type */
+ get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+ }
+
+}
+
+
+static void dissect_tk_union_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 TCKind; /* TypeCode */
+ gint32 s_octet4; /* signed int32 */
+
+ guint32 count; /* parameter count (of tuples) */
+ guint32 seqlen; /* sequence length */
+ guint32 i; /* loop index */
+
+ /* get sequence legnth, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+ /* get discriminant type */
+ TCKind = get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+
+ /* get default used */
+ s_octet4 = get_CDR_long(tvb,offset,new_stream_is_big_endian,new_boundary);
+ if (tree) {
+ proto_tree_add_int(tree,hf_giop_typecode_default_used,tvb,
+ *offset-sizeof(s_octet4),4,s_octet4);
+ }
+ /* get count of tuples */
+ count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
+ *offset-sizeof(count),4,count);
+ }
+
+ /* get all tuples */
+ for (i=0; i< count; i++) {
+ /* get label value, based on TCKind above */
+ dissect_data_for_typecode(tvb, tree, offset, new_stream_is_big_endian, new_boundary, header, TCKind );
+
+ /* get member name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_member_name);
+
+ /* get member type */
+ get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+ }
+
+}
+
+
+static void dissect_tk_enum_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 count; /* parameter count (of tuples) */
+ guint32 seqlen; /* sequence length */
+ guint32 i; /* loop index */
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+ /* get count of tuples */
+ count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
+ *offset-sizeof(count),4,count);
+ }
+
+ /* get all tuples */
+ for (i=0; i< count; i++) {
+ /* get member name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_member_name);
+ }
+
+}
+
+
+static void dissect_tk_sequence_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 u_octet4; /* unsigned int32 */
+
+ guint32 seqlen; /* sequence length */
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get element type */
+ get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+
+ /* get max length */
+ u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_max_length,tvb,
+ *offset-sizeof(u_octet4),4,u_octet4);
+ }
+}
+
+
+static void dissect_tk_array_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 u_octet4; /* unsigned int32 */
+
+ guint32 seqlen; /* sequence length */
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get element type */
+ get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+
+ /* get length */
+ u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_length,tvb,
+ *offset-sizeof(u_octet4),4,u_octet4);
+ }
+}
+
+
+static void dissect_tk_alias_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 seqlen; /* sequence length */
+
+ /* get sequence legnth, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+ /* get ??? (noname) TypeCode */
+ get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+
+}
+
+
+static void dissect_tk_except_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 count; /* parameter count (of tuples) */
+ guint32 seqlen; /* sequence length */
+ guint32 i; /* loop index */
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+ /* get count of tuples */
+ count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
+ *offset-sizeof(count),4,count);
+ }
+
+ /* get all tuples */
+ for (i=0; i< count; i++) {
+ /* get member name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_member_name);
+
+ /* get member type */
+ get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+ }
+
+}
+
+
+static void dissect_tk_value_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ gint16 s_octet2; /* signed int16 */
+
+ guint32 count; /* parameter count (of tuples) */
+ guint32 seqlen; /* sequence length */
+ guint32 i; /* loop index */
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+ /* get ValueModifier */
+ s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_int(tree,hf_giop_typecode_ValueModifier,tvb,
+ *offset-sizeof(s_octet2),2,s_octet2);
+ }
+
+ /* get conrete base */
+ get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+
+ /* get count of tuples */
+ count = get_CDR_ulong(tvb,offset,new_stream_is_big_endian,new_boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_typecode_count,tvb,
+ *offset-sizeof(count),4,count);
+ }
+
+ /* get all tuples */
+ for (i=0; i< count; i++) {
+ /* get member name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_member_name);
+
+ /* get member type */
+ get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+
+ /* get Visibility */
+ s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_int(tree,hf_giop_typecode_Visibility,tvb,
+ *offset-sizeof(s_octet2),2,s_octet2);
+ }
+ }
+
+}
+
+
+static void dissect_tk_value_box_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 seqlen; /* sequence length */
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+ /* get ??? (noname) TypeCode */
+ get_CDR_typeCode(tvb,tree,offset,new_stream_is_big_endian,new_boundary,header);
+}
+
+
+static void dissect_tk_native_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 seqlen; /* sequence length */
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+}
+
+
+static void dissect_tk_abstract_interface_params(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary) {
+
+ guint32 new_boundary; /* new boundary for encapsulation */
+ gboolean new_stream_is_big_endian; /* new endianness for encapsulation */
+
+ guint32 seqlen; /* sequence length */
+
+ /* get sequence length, new endianness and boundary for encapsulation */
+ seqlen = get_CDR_encap_info(tvb, tree, offset,
+ stream_is_big_endian, boundary,
+ &new_stream_is_big_endian, &new_boundary);
+
+ /* get repository ID */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_repoid);
+
+ /* get name */
+ dissect_typecode_string_param(tvb, tree, offset, new_stream_is_big_endian, new_boundary,
+ hf_giop_typecode_name);
+
+}
+
+/* Typecode parameter lists are encoded as encapsulations and
+ * this function gets the encapsulation information; see
+ * CORBA spec chapter 15
+ *
+ *
+ * Renamed to get_CDR_encap_info() for any encapsulation
+ * we come across, useful helper function
+ *
+ * Also, should return immediately if seqlen == 0.
+ * ie: Forget about trying to grab endianess for
+ * zero length sequence.
+ *
+ * Caller must always check seqlen == 0, and not assume its value
+ *
+ *
+ * Note: there seemed to be considerable confusion in corba
+ * circles as to the correct interpretation of encapsulations,
+ * and zero length sequences etc, but this is our best bet at the
+ * moment.
+ *
+ * -- FS
+ *
+ */
+
+guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean old_stream_is_big_endian, guint32 old_boundary,
+ gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr ) {
+
+ guint32 seqlen; /* sequence length */
+ guint8 giop_endianess;
+
+ /* Get sequence length of parameter list */
+ seqlen = get_CDR_ulong(tvb,offset,old_stream_is_big_endian,old_boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_sequence_length,tvb,
+ *offset-sizeof(seqlen),4,seqlen);
+ }
+
+
+
+ /*
+ * seqlen == 0, implies no endianess and no data
+ * so just return. Populate new_boundary_ptr and
+ * new_stream_is_big_endian_ptr with current (old)
+ * values, just to keep everyone happy. -- FS
+ *
+ */
+
+ if (seqlen == 0) {
+
+ *new_boundary_ptr = old_boundary;
+ *new_stream_is_big_endian_ptr = old_stream_is_big_endian;
+
+ return seqlen;
+
+ }
+
+ /* Start of encapsulation of parameter list */
+ *new_boundary_ptr = *offset; /* remember */
+ giop_endianess = get_CDR_octet(tvb,offset);
+
+ *new_stream_is_big_endian_ptr = ! giop_endianess;
+
+ /*
+ * Glib: typedef gint gboolean;
+ * ie: It is not a guint8, so cannot use sizeof to correctly
+ * highlight octet.
+ */
+
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_endianess,tvb,
+ *offset-1,1,giop_endianess);
+ }
+
+
+ return seqlen;
+
+
+}
+
+/*
+ * gets a TypeCode complex string parameter and
+ * displays it in the relevant tree.
+ */
+
+static void dissect_typecode_string_param(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean new_stream_is_big_endian, guint32 new_boundary, int hf_id ) {
+
+ guint32 u_octet4; /* unsigned int32 */
+ gchar *buf; /* ptr to string buffer */
+
+ /* get string */
+ u_octet4 = get_CDR_string(tvb,&buf,offset,new_stream_is_big_endian,new_boundary);
+
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_string_length,tvb,
+ *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
+ if (u_octet4 > 0) {
+ proto_tree_add_string(tree,hf_id,tvb,*offset-u_octet4,u_octet4,buf);
+ }
+ }
+
+ g_free(buf); /* dont forget */
+
+}
+
+/*
+ * For a given data type, given by a TypeCode gets the associated data
+ * and displays it in the relevant tree.
+ */
+
+static void dissect_data_for_typecode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, guint32 boundary,
+ MessageHeader * header, guint32 data_type ) {
+
+ gboolean my_boolean; /* boolean */
+
+ gint8 s_octet1; /* signed int8 */
+ guint8 u_octet1; /* unsigned int8 */
+
+ gint16 s_octet2; /* signed int16 */
+ guint16 u_octet2; /* unsigned int16 */
+
+ gint32 s_octet4; /* signed int32 */
+ guint32 u_octet4; /* unsigned int32 */
+
+ gdouble my_double; /* double */
+ gfloat my_float; /* float */
+
+ gchar *buf = NULL; /* ptr to string buffer */
+
+ /* Grab the data according to data type */
+
+ switch (data_type) {
+ case tk_null:
+ /* nothing to decode */
+ break;
+ case tk_void:
+ /* nothing to decode */
+ break;
+ case tk_short:
+ s_octet2 = get_CDR_short(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_int(tree,hf_giop_type_short,tvb,
+ *offset-sizeof(s_octet2),2,s_octet2);
+ }
+ break;
+ case tk_long:
+ s_octet4 = get_CDR_long(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_int(tree,hf_giop_type_long,tvb,
+ *offset-sizeof(s_octet4),4,s_octet4);
+ }
+ break;
+ case tk_ushort:
+ u_octet2 = get_CDR_ushort(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_type_ushort,tvb,
+ *offset-sizeof(u_octet2),2,u_octet2);
+ }
+ break;
+ case tk_ulong:
+ u_octet4 = get_CDR_ulong(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_type_ulong,tvb,
+ *offset-sizeof(u_octet4),4,u_octet4);
+ }
+ break;
+ case tk_float:
+ my_float = get_CDR_float(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_double(tree,hf_giop_type_float,tvb,
+ *offset-sizeof(my_float),4,my_float);
+ }
+ break;
+ case tk_double:
+ my_double = get_CDR_double(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_double(tree,hf_giop_type_double,tvb,
+ *offset-sizeof(my_double),8,my_double);
+ }
+ break;
+ case tk_boolean:
+ my_boolean = get_CDR_boolean(tvb,offset);
+ if (tree) {
+ proto_tree_add_boolean(tree,hf_giop_type_boolean,tvb,
+ *offset-1,1,my_boolean);
+ }
+ break;
+ case tk_char:
+ u_octet1 = get_CDR_char(tvb,offset);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_type_char,tvb,
+ *offset-sizeof(u_octet1),1,u_octet1);
+ }
+ break;
+ case tk_octet:
+ u_octet1 = get_CDR_octet(tvb,offset);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_type_octet,tvb,
+ *offset-sizeof(u_octet1),1,u_octet1);
+ }
+ break;
+ case tk_any:
+ get_CDR_any(tvb,tree,offset,stream_is_big_endian,boundary,header);
+ break;
+ case tk_TypeCode:
+ get_CDR_typeCode(tvb,tree,offset,stream_is_big_endian,boundary,header);
+ break;
+ case tk_Principal:
+ break;
+ case tk_objref:
+ break;
+ case tk_struct:
+ break;
+ case tk_union:
+ break;
+ case tk_enum:
+ u_octet4 = get_CDR_enum(tvb,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_type_enum,tvb,
+ *offset-sizeof(u_octet4),4,u_octet4);
+ }
+ break;
+ case tk_string:
+ u_octet4 = get_CDR_string(tvb,&buf,offset,stream_is_big_endian,boundary);
+ if (tree) {
+ proto_tree_add_uint(tree,hf_giop_string_length,tvb,
+ *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
+ if (u_octet4 > 0) {
+ proto_tree_add_string(tree,hf_giop_type_string,tvb,
+ *offset-u_octet4,u_octet4,buf);
+ }
+ }
+
+ g_free(buf); /* dont forget */
+ break;
+ case tk_sequence:
+ break;
+ case tk_array:
+ break;
+ case tk_alias:
+ break;
+ case tk_except:
+ break;
+ case tk_longlong:
+ break;
+ case tk_ulonglong:
+ break;
+ case tk_longdouble:
+ break;
+ case tk_wchar:
+ s_octet1 = get_CDR_wchar(tvb,&buf,offset,header);
+ if (tree) {
+ /*
+ * XXX - can any of these throw an exception?
+ * If so, we need to catch the exception and free "buf".
+ */
+ if (s_octet1 < 0) { /* no size to add to tree */
+ proto_tree_add_string(tree,hf_giop_type_string,tvb,
+ *offset+s_octet1,(-s_octet1),buf);
+ } else {
+ proto_tree_add_uint(tree,hf_giop_string_length,tvb,
+ *offset-s_octet1-sizeof(s_octet1),1,s_octet1);
+ proto_tree_add_string(tree,hf_giop_type_string,tvb,
+ *offset-s_octet1,s_octet1,buf);
+ }
+ }
+
+ g_free(buf); /* dont forget */
+ break;
+ case tk_wstring:
+ u_octet4 = get_CDR_wstring(tvb,&buf,offset,stream_is_big_endian,boundary,header);
+ if (tree) {
+ /*
+ * XXX - can any of these throw an exception?
+ * If so, we need to catch the exception and free "buf".
+ */
+ proto_tree_add_uint(tree,hf_giop_string_length,tvb,
+ *offset-u_octet4-sizeof(u_octet4),4,u_octet4);
+ proto_tree_add_string(tree,hf_giop_type_string,tvb,
+ *offset-u_octet4,u_octet4,buf);
+ }
+
+ g_free(buf); /* dont forget */
+ break;
+ case tk_fixed:
+ break;
+ case tk_value:
+ break;
+ case tk_value_box:
+ break;
+ case tk_native:
+ break;
+ case tk_abstract_interface:
+ break;
+ default:
+ g_warning("giop: Unknown typecode data type %u \n", data_type);
+ break;
+ } /* data_type */
+
+}
diff --git a/epan/dissectors/packet-giop.h b/epan/dissectors/packet-giop.h
new file mode 100644
index 0000000000..928bbf6eeb
--- /dev/null
+++ b/epan/dissectors/packet-giop.h
@@ -0,0 +1,603 @@
+/* packet-giop.h
+ * Declaration of routines for GIOP/IIOP (CDR) dissection
+ * Copyright 2000, Frank Singleton <frank.singleton@ericsson.com>
+ *
+ * Based on CORBAv2.4.2 Chapter 15 GIOP Description.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_GIOP_H
+#define PACKET_GIOP_H
+
+/*
+ * Useful visible data/structs
+ */
+
+#define GIOP_HEADER_SIZE 12
+
+typedef struct Version {
+ guint8 major;
+ guint8 minor;
+} Version;
+
+
+/*
+ * Useful data collected from message header. Note, this
+ * struct encapsulates useful data from GIOP header, as well
+ * as request_id and reply_status for use by sub dissectors.
+ */
+
+typedef struct MessageHeader {
+
+ /* Common Data */
+
+ guint8 magic[4];
+ Version GIOP_version;
+ guint8 flags; /* byte_order in 1.0 */
+ guint8 message_type;
+ guint32 message_size;
+ guint32 req_id; /* request id in MSG */
+
+ /* MSG dependant data */
+
+ guint32 rep_status; /* reply status in MSG if available */
+ gchar *exception_id; /* exception string if a USER EXCEPTION occurs */
+
+} MessageHeader;
+
+typedef enum MsgType {
+ Request = 0,
+ Reply,
+ CancelRequest,
+ LocateRequest,
+ LocateReply,
+ CloseConnection,
+ MessageError,
+ Fragment /* GIOP 1.1 only */
+
+} MsgType;
+
+
+
+/*
+ * Reply Status
+ *
+ */
+
+typedef enum ReplyStatusType {
+ NO_EXCEPTION = 0,
+ USER_EXCEPTION,
+ SYSTEM_EXCEPTION,
+ LOCATION_FORWARD,
+ LOCATION_FORWARD_PERM, /* new for GIOP 1.2 */
+ NEEDS_ADDRESSING_MODE /* new for GIOP 1.2 */
+} ReplyStatusType;
+
+/*
+ * Prototype for sub dissector function calls.
+ */
+
+typedef gboolean (giop_sub_dissector_t)(tvbuff_t *, packet_info *, proto_tree *, int *,
+ MessageHeader *, gchar * , gchar *);
+
+/*
+ * Generic Subdissector handle, wraps user info.
+ */
+
+typedef struct giop_sub_handle {
+ giop_sub_dissector_t *sub_fn; /* ptr to sub dissector function */
+ gchar *sub_name; /* subdissector string name */
+ protocol_t *sub_proto; /* protocol_t for subprotocol */
+} giop_sub_handle_t;
+
+/* Main GIOP entry point */
+
+extern gboolean dissect_giop(tvbuff_t *, packet_info *, proto_tree *); /* new interface */
+
+/*
+ * GIOP Users register interest via this function.
+ * This is for heuristic dissection
+ */
+
+extern void register_giop_user(giop_sub_dissector_t *sub, gchar *name,
+ int sub_proto);
+
+/*
+ * GIOP Users remove interest via this function.
+ * This is for heuristic dissection
+ */
+
+extern void delete_giop_user(giop_sub_dissector_t *sub, gchar *name);
+
+
+/*
+ * GIOP Users register their module and interface names via this function.
+ * This is for explicit dissection.
+ */
+
+extern void register_giop_user_module(giop_sub_dissector_t *sub, gchar *name,
+ gchar *module, int sub_proto);
+
+/*
+ * GIOP Users remove their module and interface names via this function.
+ * This is for explicit dissection.
+ */
+
+extern void delete_giop_user_module(giop_sub_dissector_t *sub, gchar *name,
+ gchar *module);
+
+
+/*
+ * General CDR accessors start here. They are listed in alphabetical
+ * order. They may however, belong to 1 of 3 distinct CDR data types.
+ *
+ * - Primitive
+ * - OMG IDL Constructed Types
+ * - Pseudo Object Types
+ *
+ *
+ * Altough some of these look redundant, I have separated them
+ * out for all CDR types, to assist in auto generation of
+ * IDL dissectors later, see idl2eth -- FS
+ *
+ */
+
+
+/*
+ * Gets data of type any. This is encoded as a TypeCode
+ * followed by the encoded value.
+ *
+ * Data is added to tree directly if present.
+ */
+
+extern void get_CDR_any(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, int boundary, MessageHeader * header );
+
+
+/* Copy a 1 octet sequence from the tvbuff
+ * which represents a boolean value, and convert
+ * it to a boolean value.
+ * Offset is then incremented by 1, to indicate the 1 octet which
+ * has been processed.
+ */
+
+extern gboolean get_CDR_boolean(tvbuff_t *tvb, int *offset);
+
+
+/* Copy a 1 octet sequence from the tvbuff
+ * which represents a char, and convert
+ * it to an char value.
+ * offset is then incremented by 1, to indicate the 1 octet which
+ * has been processed.
+ */
+
+extern guint8 get_CDR_char(tvbuff_t *tvb, int *offset);
+
+
+
+/*
+ * Floating Point Data Type double IEEE 754-1985
+ *
+ * Copy an 8 octet sequence from the tvbuff
+ * which represents a double value, and convert
+ * it to a double value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for double values.
+ * offset is then incremented by 8, to indicate the 8 octets which
+ * have been processed.
+ */
+
+extern gdouble get_CDR_double(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+
+
+/* Copy a 4 octet sequence from the tvbuff
+ * which represents an enum value, and convert
+ * it to an enum value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for an enum (4)
+ * offset is then incremented by 4, to indicate the 4 octets which
+ * have been processed.
+ *
+ * Enum values are encoded as unsigned long.
+ */
+
+extern guint32 get_CDR_enum(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+
+
+
+/*
+ * Copy an octet sequence from the tvbuff
+ * which represents a Fixed point decimal type, and create a string representing
+ * a Fixed point decimal type. There are no alignment restrictions.
+ * Size and scale of fixed decimal type is determined by IDL.
+ *
+ * digits - IDL specified number of "digits" for this fixed type
+ * scale - IDL specified "scale" for this fixed type
+ *
+ *
+ * eg: typedef fixed <5,2> fixed_t;
+ * could represent numbers like 123.45, 789.12,
+ *
+ *
+ * As the fixed type could be any size, I will not try to fit it into our
+ * simple types like gdouble or glong etc. I will just create a string buffer holding
+ * a representation (after scale is applied), and with a decimal point or zero padding
+ * inserted at the right place if necessary. The string is null terminated
+ *
+ * so string may look like
+ *
+ *
+ * "+1.234" or "-3456.78" or "1234567309475760377365465897891" or "-2789000000" etc
+ *
+ * According to spec, digits <= 31
+ * and scale is positive (except for constants eg: 1000 has digit=1 and implied scale = -3)
+ * or <4,0> ?
+ *
+ * User must remember to free the buffer
+ *
+ */
+
+extern void get_CDR_fixed(tvbuff_t *tvb, gchar **seq, gint *offset,
+ guint32 digits, gint32 scale);
+
+
+
+/*
+ * Floating Point Data Type float IEEE 754-1985
+ *
+ * Copy a 4 octet sequence from the tvbuff
+ * which represents a float value, and convert
+ * it to a float value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for float values.
+ * offset is then incremented by 4, to indicate the 4 octets which
+ * have been processed.
+ */
+
+extern gfloat get_CDR_float(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+
+
+/*
+ * Decode an Interface type, and display it on the tree.
+ */
+
+extern void get_CDR_interface(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int *offset, gboolean stream_is_big_endian, int boundary);
+
+
+/* Copy a 4 octet sequence from the tvbuff
+ * which represents a signed long value, and convert
+ * it to an signed long vaule, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for long values.
+ * offset is then incremented by 4, to indicate the 4 octets which
+ * have been processed.
+ */
+
+extern gint32 get_CDR_long(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+
+
+
+/* Copy a 16 octet sequence from the tvbuff
+ * which represents a long double value, and convert
+ * it to a long double value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for long double values.
+ * offset is then incremented by 16, to indicate the 16 octets which
+ * have been processed.
+ */
+
+#ifdef G_HAVE_GLONG_DOUBLE
+
+extern glong_double get_CDR_long_double(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+#else
+
+/* FIX -- Cast long double to gdouble until I figure this out -- FS*/
+
+extern gdouble get_CDR_long_double(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+
+#endif
+
+
+/* Copy an 8 octet sequence from the tvbuff
+ * which represents a signed long long value, and convert
+ * it to a signed long long value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for long long values.
+ * offset is then incremented by 8, to indicate the 8 octets which
+ * have been processed.
+ */
+
+#ifdef G_HAVE_GINT64
+extern gint64 get_CDR_long_long(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+#endif
+
+/*
+ * Decode an Object type, and display it on the tree.
+ */
+
+extern void get_CDR_object(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int *offset, gboolean stream_is_big_endian, int boundary);
+
+
+/* Copy a 1 octet sequence from the tvbuff
+ * which represents a octet, and convert
+ * it to an octet value.
+ * offset is then incremented by 1, to indicate the 1 octet which
+ * has been processed.
+ */
+
+extern guint8 get_CDR_octet(tvbuff_t *tvb, int *offset);
+
+
+/* Copy a sequence of octets from the tvbuff.
+ * Caller of this function must remember to free the
+ * array pointed to by seq.
+ * This function also increments offset by len.
+ */
+
+extern void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len);
+
+/* Copy a 2 octet sequence from the tvbuff
+ * which represents a signed short value, and convert
+ * it to a signed short value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for short values.
+ * offset is then incremented by 2, to indicate the 2 octets which
+ * have been processed.
+ */
+
+extern gint16 get_CDR_short(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+
+
+/* Copy an octet sequence from the tvbuff
+ * which represents a string, and convert
+ * it to an string value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for string values. (begins with an unsigned long LI)
+ *
+ * String sequence is copied to a buffer "seq". This must
+ * be freed by the calling program.
+ * offset is then incremented , to indicate the octets which
+ * have been processed.
+ *
+ * returns number of octets in the sequence
+ *
+ * Note: This function only supports single byte encoding at the
+ * moment until I get a handle on multibyte encoding etc.
+ *
+ */
+
+extern guint32 get_CDR_string(tvbuff_t *tvb, gchar **seq, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+
+
+/* Process a sequence of octets that represent the
+ * Pseudo Object Type "TypeCode". Typecodes are used for example,
+ * by "Any values".
+ * This function also increments offset to the correct position.
+ *
+ * It will parse the TypeCode and output data to the "tree" provided
+ * by the user
+ *
+ * It returns a guint32 representing a TCKind value.
+ */
+
+extern guint32 get_CDR_typeCode(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean stream_is_big_endian, int boundary, MessageHeader * header );
+
+/* Copy a 4 octet sequence from the tvbuff
+ * which represents an unsigned long value, and convert
+ * it to an unsigned long value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for unsigned long values.
+ * offset is then incremented by 4, to indicate the 4 octets which
+ * have been processed.
+ */
+
+extern guint32 get_CDR_ulong(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+
+
+/* Copy an 8 octet sequence from the tvbuff
+ * which represents an unsigned long long value, and convert
+ * it to an unsigned long long value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for unsigned long long values.
+ * offset is then incremented by 8, to indicate the 8 octets which
+ * have been processed.
+ */
+
+#ifdef G_HAVE_GINT64
+extern guint64 get_CDR_ulong_long(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+#endif
+
+
+/* Copy a 2 octet sequence from the tvbuff
+ * which represents an unsigned short value, and convert
+ * it to an unsigned short value, taking into account byte order.
+ * offset is first incremented so that it falls on a proper alignment
+ * boundary for unsigned short values.
+ * offset is then incremented by 2, to indicate the 2 octets which
+ * have been processed.
+ */
+
+extern guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset,
+ gboolean stream_is_big_endian, int boundary);
+
+
+/* Copy a wchar from the tvbuff.
+ * Caller of this function must remember to free the
+ * array pointed to by seq.
+ * This function also increments offset according to
+ * the wchar size.
+ *
+ * For GIOP 1.1 read 2 octets and return size -2. The
+ * negation means there is no size element in the packet
+ * and therefore no size to add to the tree.
+ *
+ * For GIOP 1.2 read size of wchar and the size
+ * octets. size is returned as a gint8.
+ *
+ * For both GIOP versions the wchar is returned
+ * as a printable string.
+ *
+ */
+
+/* NOTE: This is very primitive in that it just reads
+ * the wchar as a series of octets and returns them
+ * to the user. No translation is attempted based on
+ * byte orientation, nor on code set. I.e it only
+ * really reads past the wchar and increments the offset
+ * by the length of the octet sequence.
+ */
+
+/* The "decoding" is done according to CORBA chapter 15.
+ * Wchar is not supported for GIOP 1.0.
+ */
+
+extern gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset,
+ MessageHeader * header);
+
+
+/* Copy a wstring from the tvbuff.
+ * Caller of this function must remember to free the
+ * array pointed to by seq.
+ * This function also increments offset, according to
+ * wstring length. length is returned as guint32
+ */
+
+/* NOTE: This is very primitive in that it just reads
+ * the wstring as a series of octets and returns them
+ * to the user. No translation is attempted based on
+ * byte orientation, nor on code set. I.e it only
+ * really reads past the wstring and increments the offset
+ * by the length of the octet sequence.
+ */
+
+/* The "decoding" is done according to CORBA chapter 15.
+ * Wstring is not supported for GIOP 1.0.
+ */
+
+extern guint32 get_CDR_wstring(tvbuff_t *tvb, gchar **seq, int *offset,
+ gboolean stream_is_big_endian, int boundary, MessageHeader * header);
+
+
+
+/*
+ *
+ * End of get_CDR_xxx accessors.
+ *
+ */
+
+
+
+/* Determine the byte order from the GIOP MessageHeader */
+
+extern gboolean is_big_endian (MessageHeader * header);
+
+/*
+ * get_encap_info() for any encapsulation (eg:sequences)
+ * we come across. updates the new boundary and endianess
+ * and *offset, and returns the sequence length.
+ */
+
+extern guint32 get_CDR_encap_info(tvbuff_t *tvb, proto_tree *tree, gint *offset,
+ gboolean old_stream_is_big_endian, guint32 old_boundary,
+ gboolean *new_stream_is_big_endian_ptr, guint32 *new_boundary_ptr );
+
+
+
+/*
+ * Enums for TCkind
+ */
+
+enum TCKind {
+ tk_null = 0,
+ tk_void,
+ tk_short,
+ tk_long,
+ tk_ushort,
+ tk_ulong,
+ tk_float,
+ tk_double,
+ tk_boolean,
+ tk_char,
+ tk_octet,
+ tk_any,
+ tk_TypeCode,
+ tk_Principal,
+ tk_objref,
+ tk_struct,
+ tk_union,
+ tk_enum,
+ tk_string,
+ tk_sequence,
+ tk_array,
+ tk_alias,
+ tk_except,
+ tk_longlong,
+ tk_ulonglong,
+ tk_longdouble,
+ tk_wchar,
+ tk_wstring,
+ tk_fixed,
+ tk_value,
+ tk_value_box,
+ tk_native,
+ tk_abstract_interface
+
+ /* - none - 0xffffffff TODO */
+};
+
+#define tk_none 0xffffffff
+
+typedef enum TCKind TCKind_t;
+
+
+/*
+ * ServiceId's for ServiceContextList
+ *
+ * Chapter 13 Corba 2.4.2
+ */
+
+#define IOP_ServiceId_TransactionService 0
+#define IOP_ServiceId_CodeSets 1
+#define IOP_ServiceId_ChainBypassCheck 2
+#define IOP_ServiceId_ChainBypassInfo 3
+#define IOP_ServiceId_LogicalThreadId 4
+#define IOP_ServiceId_BI_DIR_IIOP 5
+#define IOP_ServiceId_SendingContextRunTime 6
+#define IOP_ServiceId_INVOCATION_POLICIES 7
+#define IOP_ServiceId_FORWARD_IDENTITY 8
+#define IOP_ServiceId_UnknownExceptionInfo 9
+
+#endif /* PACKET_GIOP_H */
diff --git a/epan/dissectors/packet-gmrp.c b/epan/dissectors/packet-gmrp.c
new file mode 100644
index 0000000000..872eb92a08
--- /dev/null
+++ b/epan/dissectors/packet-gmrp.c
@@ -0,0 +1,399 @@
+/* packet-gmrp.c
+ * Routines for GMRP (GARP Multicast Registration Protocol) dissection
+ * Copyright 2001, Markus Seehofer <mseehofe@nt.hirschmann.de>
+ *
+ * Based on the code from packet-gvrp.c (GVRP) from
+ * Kevin Shi <techishi@ms22.hinet.net> Copyright 2000
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "llcsaps.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_gmrp = -1;
+static int hf_gmrp_proto_id = -1;
+static int hf_gmrp_attribute_type = -1;
+static int hf_gmrp_attribute_length = -1;
+static int hf_gmrp_attribute_event = -1;
+static int hf_gmrp_attribute_value_group_membership = -1;
+static int hf_gmrp_attribute_value_service_requirement = -1;
+/*static int hf_gmrp_end_of_mark = -1;*/
+
+/* Initialize the subtree pointers */
+static gint ett_gmrp = -1;
+/*static gint ett_gmrp_message = -1;
+static gint ett_gmrp_attribute_list = -1;
+static gint ett_gmrp_attribute = -1;*/
+
+static dissector_handle_t data_handle;
+
+/* Constant definitions */
+#define GARP_DEFAULT_PROTOCOL_ID 0x0001
+#define GARP_END_OF_MARK 0x00
+
+#define GMRP_ATTRIBUTE_TYPE_GROUP_MEMBERSHIP 0x01
+#define GMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT 0x02
+
+#define GMRP_SERVICE_REQUIREMENT_FORWARD_ALL 0x00
+#define GMRP_SERVICE_REQUIREMENT_FORWARD_ALL_UNREGISTERED 0x01
+
+static const value_string attribute_type_vals[] = {
+ { GMRP_ATTRIBUTE_TYPE_GROUP_MEMBERSHIP ,"Group Membership" },
+ { GMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT ,"Service Requirement" },
+ { 0, NULL }
+};
+
+/* The length of GMRP LeaveAll attribute should be 2 octets (one for length
+ * and the other for event) */
+#define GMRP_LENGTH_LEAVEALL (sizeof(guint8)+sizeof(guint8))
+
+/* The length of GMRP attribute other than LeaveAll should be:
+*
+* 8 bytes for Group Membership (1 for length, 1 for event and 6 for mac address to register)
+* or
+* 3 bytes for Service Requirement (1 for length, 1 for event, 1 for attribute value)
+*
+ */
+#define GMRP_GROUP_MEMBERSHIP_NON_LEAVEALL (sizeof(guint8)+sizeof(guint8)+(6*sizeof(guint8)))
+#define GMRP_SERVICE_REQUIREMENT_NON_LEAVEALL (sizeof(guint8)+sizeof(guint8)+sizeof(guint8))
+
+/* Packet offset definitions */
+#define GARP_PROTOCOL_ID 0
+
+/* Event definitions */
+#define GMRP_EVENT_LEAVEALL 0
+#define GMRP_EVENT_JOINEMPTY 1
+#define GMRP_EVENT_JOININ 2
+#define GMRP_EVENT_LEAVEEMPTY 3
+#define GMRP_EVENT_LEAVEIN 4
+#define GMRP_EVENT_EMPTY 5
+
+static const value_string event_vals[] = {
+ { GMRP_EVENT_LEAVEALL, "Leave All" },
+ { GMRP_EVENT_JOINEMPTY, "Join Empty" },
+ { GMRP_EVENT_JOININ, "Join In" },
+ { GMRP_EVENT_LEAVEEMPTY, "Leave Empty" },
+ { GMRP_EVENT_LEAVEIN, "Leave In" },
+ { GMRP_EVENT_EMPTY, "Empty" },
+ { 0, NULL }
+};
+
+
+/* Code to actually dissect the packets */
+static void
+dissect_gmrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *gmrp_tree;
+ guint16 protocol_id;
+ guint8 octet;
+ guint8 attribute_type;
+ int msg_index, attr_index, offset = 0, length = tvb_reported_length(tvb);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GMRP");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "GMRP");
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_gmrp, tvb, 0, length, FALSE);
+
+ gmrp_tree = proto_item_add_subtree(ti, ett_gmrp);
+
+ /* Read in GARP protocol ID */
+ protocol_id = tvb_get_ntohs(tvb, GARP_PROTOCOL_ID);
+
+ proto_tree_add_uint_format(gmrp_tree, hf_gmrp_proto_id, tvb,
+ GARP_PROTOCOL_ID, sizeof(guint16),
+ protocol_id,
+ "Protocol Identifier: 0x%04x (%s)",
+ protocol_id,
+ protocol_id == GARP_DEFAULT_PROTOCOL_ID ?
+ "GARP Multicast Registration Protocol" :
+ "Unknown Protocol");
+
+ /* Currently only one protocol ID is supported */
+ if (protocol_id != GARP_DEFAULT_PROTOCOL_ID)
+ {
+ proto_tree_add_text(gmrp_tree, tvb, GARP_PROTOCOL_ID, sizeof(guint16),
+ " (Warning: this version of Ethereal only knows about protocol id = 1)");
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, GARP_PROTOCOL_ID + sizeof(guint16), -1, -1),
+ pinfo, tree);
+ return;
+ }
+
+ offset += sizeof(guint16);
+ length -= sizeof(guint16);
+
+ msg_index = 0;
+
+ /* Begin to parse GARP messages */
+ while (length)
+ {
+ proto_item *msg_item;
+ int msg_start = offset;
+
+ /* Read in attribute type. */
+ attribute_type = octet = tvb_get_guint8(tvb, offset);
+
+ /* Check for end of mark */
+ if (octet == GARP_END_OF_MARK)
+ {
+ /* End of GARP PDU */
+ if (msg_index)
+ {
+ proto_tree_add_text(gmrp_tree, tvb, offset, sizeof(guint8),
+ "End of pdu");
+ break;
+ }
+ else
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, tree);
+ return;
+ }
+ }
+
+ offset += sizeof(guint8);
+ length -= sizeof(guint8);
+
+ msg_item = proto_tree_add_text(gmrp_tree, tvb, msg_start, -1,
+ "Message %d", msg_index + 1);
+
+ proto_tree_add_uint(gmrp_tree, hf_gmrp_attribute_type, tvb,
+ msg_start, sizeof(guint8), octet);
+
+ /* GMRP supports Group Membership and Service Requirement as attribute types */
+ if ( (octet != GMRP_ATTRIBUTE_TYPE_GROUP_MEMBERSHIP) && (octet != GMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT) )
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo,
+ tree);
+ return;
+ }
+
+ attr_index = 0;
+
+ while (length)
+ {
+ int attr_start = offset;
+ proto_item *attr_item;
+
+ /* Read in attribute length. */
+ octet = tvb_get_guint8(tvb, offset);
+
+ /* Check for end of mark */
+ if (octet == GARP_END_OF_MARK)
+ {
+ /* If at least one message has been already read,
+ * check for another end of mark.
+ */
+ if (attr_index)
+ {
+ proto_tree_add_text(gmrp_tree, tvb, offset,
+ sizeof(guint8), " End of mark");
+
+ offset += sizeof(guint8);
+ length -= sizeof(guint8);
+
+ proto_item_set_len(msg_item, offset - msg_start);
+ break;
+ }
+ else
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, tree);
+ return;
+ }
+ }
+ else
+ {
+ guint8 event;
+
+ offset += sizeof(guint8);
+ length -= sizeof(guint8);
+
+ attr_item = proto_tree_add_text(gmrp_tree, tvb,
+ attr_start, -1, " Attribute %d", attr_index + 1);
+
+ proto_tree_add_uint(gmrp_tree, hf_gmrp_attribute_length,
+ tvb, attr_start, sizeof(guint8), octet);
+
+ /* Read in attribute event */
+ event = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(gmrp_tree, hf_gmrp_attribute_event,
+ tvb, offset, sizeof(guint8), event);
+
+ offset += sizeof(guint8);
+ length -= sizeof(guint8);
+
+ switch (event) {
+
+ case GMRP_EVENT_LEAVEALL:
+ if (octet != GMRP_LENGTH_LEAVEALL)
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, tree);
+ return;
+ }
+ break;
+
+ case GMRP_EVENT_JOINEMPTY:
+ case GMRP_EVENT_JOININ:
+ case GMRP_EVENT_LEAVEEMPTY:
+ case GMRP_EVENT_LEAVEIN:
+ case GMRP_EVENT_EMPTY:
+ if ( (octet != GMRP_GROUP_MEMBERSHIP_NON_LEAVEALL) && (octet != GMRP_SERVICE_REQUIREMENT_NON_LEAVEALL) )
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, tree);
+ return;
+ }
+
+ /* Show attribute value */
+
+ if ( GMRP_ATTRIBUTE_TYPE_GROUP_MEMBERSHIP == attribute_type )
+ {
+ /* Group Membership */
+ proto_tree_add_item(gmrp_tree, hf_gmrp_attribute_value_group_membership,
+ tvb, offset, (6*sizeof(guint8)), FALSE);
+
+ offset += 6*sizeof(guint8);
+ length -= 6*sizeof(guint8);
+ }
+ else
+ if ( GMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT == attribute_type )
+ {
+ /* Service Requirement */
+ proto_tree_add_item(gmrp_tree, hf_gmrp_attribute_value_service_requirement,
+ tvb, offset, sizeof(guint8), FALSE);
+
+ offset += sizeof(guint8);
+ length -= sizeof(guint8);
+ }
+ else
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, tree);
+ return;
+ }
+
+ break;
+
+ default:
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, tree);
+ return;
+ }
+ }
+
+ proto_item_set_len(attr_item, offset - attr_start);
+
+ attr_index++;
+ }
+
+ msg_index++;
+ }
+ }
+}
+
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_gmrp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_gmrp_proto_id,
+ { "Protocol ID", "garp.protocol_id",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "" , HFILL }
+ },
+ { &hf_gmrp_attribute_type,
+ { "Type", "garp.attribute_type",
+ FT_UINT8, BASE_HEX, VALS(attribute_type_vals), 0x0,
+ "" , HFILL }
+ },
+ { &hf_gmrp_attribute_length,
+ { "Length", "garp.attribute_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "" , HFILL }
+ },
+ { &hf_gmrp_attribute_event,
+ { "Event", "garp.attribute_event",
+ FT_UINT8, BASE_DEC, VALS(event_vals), 0x0,
+ "" , HFILL }
+ },
+ { &hf_gmrp_attribute_value_group_membership,
+ { "Value", "garp.attribute_value_group_membership",
+ FT_ETHER, BASE_HEX, NULL, 0x0,
+ "" , HFILL }
+ },
+ { &hf_gmrp_attribute_value_service_requirement,
+ { "Value", "garp.attribute_value_service_requirement",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "" , HFILL }
+ }
+
+ };
+
+ static gint *ett[] = {
+ &ett_gmrp
+ };
+
+ /* Register the protocol name and description for GMRP */
+ proto_gmrp = proto_register_protocol("GARP Multicast Registration Protocol", "GMRP", "gmrp");
+
+ /* Required function calls to register the header fields and subtrees
+ * used by GMRP */
+ proto_register_field_array(proto_gmrp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("gmrp", dissect_gmrp, proto_gmrp);
+
+}
+
+void
+proto_reg_handoff_gmrp(void){
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-gnutella.c b/epan/dissectors/packet-gnutella.c
new file mode 100644
index 0000000000..a88301eb5d
--- /dev/null
+++ b/epan/dissectors/packet-gnutella.c
@@ -0,0 +1,761 @@
+/* packet-gnutella.c
+ * Routines for gnutella dissection
+ * Copyright 2001, B. Johannessen <bob@havoq.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+
+#include <epan/packet.h>
+#include "packet-gnutella.h"
+
+static int proto_gnutella = -1;
+
+static int hf_gnutella_stream = -1;
+
+static int hf_gnutella_truncated = -1;
+
+static int hf_gnutella_header = -1;
+static int hf_gnutella_header_id = -1;
+static int hf_gnutella_header_payload = -1;
+static int hf_gnutella_header_ttl = -1;
+static int hf_gnutella_header_hops = -1;
+static int hf_gnutella_header_size = -1;
+
+static int hf_gnutella_pong_payload = -1;
+static int hf_gnutella_pong_port = -1;
+static int hf_gnutella_pong_ip = -1;
+static int hf_gnutella_pong_files = -1;
+static int hf_gnutella_pong_kbytes = -1;
+
+static int hf_gnutella_query_payload = -1;
+static int hf_gnutella_query_min_speed = -1;
+static int hf_gnutella_query_search = -1;
+
+static int hf_gnutella_queryhit_payload = -1;
+static int hf_gnutella_queryhit_count = -1;
+static int hf_gnutella_queryhit_port = -1;
+static int hf_gnutella_queryhit_ip = -1;
+static int hf_gnutella_queryhit_speed = -1;
+static int hf_gnutella_queryhit_extra = -1;
+static int hf_gnutella_queryhit_servent_id = -1;
+
+static int hf_gnutella_queryhit_hit = -1;
+static int hf_gnutella_queryhit_hit_index = -1;
+static int hf_gnutella_queryhit_hit_size = -1;
+static int hf_gnutella_queryhit_hit_name = -1;
+static int hf_gnutella_queryhit_hit_extra = -1;
+
+static int hf_gnutella_push_payload = -1;
+static int hf_gnutella_push_servent_id = -1;
+static int hf_gnutella_push_index = -1;
+static int hf_gnutella_push_ip = -1;
+static int hf_gnutella_push_port = -1;
+
+static gint ett_gnutella = -1;
+
+static void dissect_gnutella_pong(tvbuff_t *tvb, guint offset, proto_tree *tree, guint size) {
+
+ if(offset + size > tvb_length(tvb)) {
+ proto_tree_add_item(tree,
+ hf_gnutella_truncated,
+ tvb,
+ offset,
+ size,
+ FALSE);
+ return;
+ }
+
+ proto_tree_add_item(tree,
+ hf_gnutella_pong_port,
+ tvb,
+ offset + GNUTELLA_PONG_PORT_OFFSET,
+ GNUTELLA_PORT_LENGTH,
+ TRUE);
+
+ proto_tree_add_item(tree,
+ hf_gnutella_pong_ip,
+ tvb,
+ offset + GNUTELLA_PONG_IP_OFFSET,
+ GNUTELLA_IP_LENGTH,
+ FALSE);
+
+ proto_tree_add_item(tree,
+ hf_gnutella_pong_files,
+ tvb,
+ offset + GNUTELLA_PONG_FILES_OFFSET,
+ GNUTELLA_LONG_LENGTH,
+ TRUE);
+
+ proto_tree_add_item(tree,
+ hf_gnutella_pong_kbytes,
+ tvb,
+ offset + GNUTELLA_PONG_KBYTES_OFFSET,
+ GNUTELLA_LONG_LENGTH,
+ TRUE);
+
+}
+
+static void dissect_gnutella_query(tvbuff_t *tvb, guint offset, proto_tree *tree, guint size) {
+
+ if(offset + size > tvb_length(tvb)) {
+ proto_tree_add_item(tree,
+ hf_gnutella_truncated,
+ tvb,
+ offset,
+ size,
+ FALSE);
+ return;
+ }
+
+ proto_tree_add_item(tree,
+ hf_gnutella_query_min_speed,
+ tvb,
+ offset + GNUTELLA_QUERY_SPEED_OFFSET,
+ GNUTELLA_SHORT_LENGTH,
+ TRUE);
+
+ if (size > GNUTELLA_SHORT_LENGTH) {
+ proto_tree_add_item(tree,
+ hf_gnutella_query_search,
+ tvb,
+ offset + GNUTELLA_QUERY_SEARCH_OFFSET,
+ size - GNUTELLA_SHORT_LENGTH,
+ FALSE);
+ }
+ else {
+ proto_tree_add_text(tree,
+ tvb,
+ offset + GNUTELLA_QUERY_SEARCH_OFFSET,
+ 0,
+ "Missing data for Query Search.");
+ }
+}
+
+static void dissect_gnutella_queryhit(tvbuff_t *tvb, guint offset, proto_tree *tree, guint size) {
+
+ proto_tree *qhi, *hit_tree;
+ int hit_count, i;
+ int hit_offset;
+ int name_length, extra_length;
+ int idx_at_offset, size_at_offset;
+ int servent_id_at_offset;
+ int name_at_offset, extra_at_offset;
+ int cur_char, remaining, used;
+
+ if(offset + size > tvb_length(tvb)) {
+ proto_tree_add_item(tree,
+ hf_gnutella_truncated,
+ tvb,
+ offset,
+ size,
+ FALSE);
+ return;
+ }
+
+ hit_count = tvb_get_guint8(tvb, offset + GNUTELLA_QUERYHIT_COUNT_OFFSET);
+
+ proto_tree_add_uint(tree,
+ hf_gnutella_queryhit_count,
+ tvb,
+ offset + GNUTELLA_QUERYHIT_COUNT_OFFSET,
+ GNUTELLA_BYTE_LENGTH,
+ hit_count);
+
+ proto_tree_add_item(tree,
+ hf_gnutella_queryhit_port,
+ tvb,
+ offset + GNUTELLA_QUERYHIT_PORT_OFFSET,
+ GNUTELLA_PORT_LENGTH,
+ TRUE);
+
+ proto_tree_add_item(tree,
+ hf_gnutella_queryhit_ip,
+ tvb,
+ offset + GNUTELLA_QUERYHIT_IP_OFFSET,
+ GNUTELLA_IP_LENGTH,
+ FALSE);
+
+ proto_tree_add_item(tree,
+ hf_gnutella_queryhit_speed,
+ tvb,
+ offset + GNUTELLA_QUERYHIT_SPEED_OFFSET,
+ GNUTELLA_LONG_LENGTH,
+ TRUE);
+
+ hit_offset = offset + GNUTELLA_QUERYHIT_FIRST_HIT_OFFSET;
+
+ for(i = 0; i < hit_count; i++) {
+ idx_at_offset = hit_offset;
+ size_at_offset = hit_offset + GNUTELLA_QUERYHIT_HIT_SIZE_OFFSET;
+
+ hit_offset += (GNUTELLA_LONG_LENGTH * 2);
+
+ name_length = 0;
+ extra_length = 0;
+
+ name_at_offset = hit_offset;
+
+ while(hit_offset - offset < size) {
+ cur_char = tvb_get_guint8(tvb, hit_offset);
+ if(cur_char == '\0')
+ break;
+
+ hit_offset++;
+ name_length++;
+ }
+
+ hit_offset++;
+
+ extra_at_offset = hit_offset;
+
+ while(hit_offset - offset < size) {
+ cur_char = tvb_get_guint8(tvb, hit_offset);
+ if(cur_char == '\0')
+ break;
+
+ hit_offset++;
+ extra_length++;
+ }
+
+ hit_offset++;
+
+ qhi = proto_tree_add_item(tree,
+ hf_gnutella_queryhit_hit,
+ tvb,
+ idx_at_offset,
+ (GNUTELLA_LONG_LENGTH * 2) +
+ name_length + extra_length +
+ GNUTELLA_QUERYHIT_END_OF_STRING_LENGTH,
+ FALSE);
+
+ hit_tree = proto_item_add_subtree(qhi, ett_gnutella);
+
+ proto_tree_add_item(hit_tree,
+ hf_gnutella_queryhit_hit_index,
+ tvb,
+ idx_at_offset,
+ GNUTELLA_LONG_LENGTH,
+ TRUE);
+
+ proto_tree_add_item(hit_tree,
+ hf_gnutella_queryhit_hit_size,
+ tvb,
+ size_at_offset,
+ GNUTELLA_LONG_LENGTH,
+ TRUE);
+
+ proto_tree_add_item(hit_tree,
+ hf_gnutella_queryhit_hit_name,
+ tvb,
+ name_at_offset,
+ name_length,
+ FALSE);
+
+ if(extra_length) {
+ proto_tree_add_item(hit_tree,
+ hf_gnutella_queryhit_hit_extra,
+ tvb,
+ extra_at_offset,
+ extra_length,
+ FALSE);
+ }
+ }
+
+ used = hit_offset - offset;
+ remaining = size - used;
+
+ if(remaining > GNUTELLA_SERVENT_ID_LENGTH) {
+ servent_id_at_offset = hit_offset + remaining - GNUTELLA_SERVENT_ID_LENGTH;
+
+ proto_tree_add_item(tree,
+ hf_gnutella_queryhit_extra,
+ tvb,
+ hit_offset,
+ servent_id_at_offset - hit_offset,
+ FALSE);
+ }
+ else {
+ servent_id_at_offset = hit_offset;
+ }
+
+ proto_tree_add_item(tree,
+ hf_gnutella_queryhit_servent_id,
+ tvb,
+ servent_id_at_offset,
+ GNUTELLA_SERVENT_ID_LENGTH,
+ FALSE);
+
+}
+
+static void dissect_gnutella_push(tvbuff_t *tvb, guint offset, proto_tree *tree, guint size) {
+
+ if(offset + size > tvb_length(tvb)) {
+ proto_tree_add_item(tree,
+ hf_gnutella_truncated,
+ tvb,
+ offset,
+ size,
+ FALSE);
+ return;
+ }
+
+ proto_tree_add_item(tree,
+ hf_gnutella_push_servent_id,
+ tvb,
+ offset + GNUTELLA_PUSH_SERVENT_ID_OFFSET,
+ GNUTELLA_SERVENT_ID_LENGTH,
+ FALSE);
+
+ proto_tree_add_item(tree,
+ hf_gnutella_push_index,
+ tvb,
+ offset + GNUTELLA_PUSH_INDEX_OFFSET,
+ GNUTELLA_LONG_LENGTH,
+ TRUE);
+
+ proto_tree_add_item(tree,
+ hf_gnutella_push_ip,
+ tvb,
+ offset + GNUTELLA_PUSH_IP_OFFSET,
+ GNUTELLA_IP_LENGTH,
+ FALSE);
+
+ proto_tree_add_item(tree,
+ hf_gnutella_push_port,
+ tvb,
+ offset + GNUTELLA_PUSH_PORT_OFFSET,
+ GNUTELLA_PORT_LENGTH,
+ TRUE);
+
+}
+
+static void dissect_gnutella(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+
+ proto_item *ti, *hi, *pi;
+ proto_tree *gnutella_tree, *gnutella_header_tree, *gnutella_pong_tree;
+ proto_tree *gnutella_queryhit_tree, *gnutella_push_tree;
+ proto_tree *gnutella_query_tree;
+ int snap_len, payload_descriptor, offset;
+ unsigned int size;
+ char *payload_descriptor_text;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Gnutella");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Gnutella");
+
+ snap_len = tvb_length(tvb);
+
+ if(snap_len < GNUTELLA_HEADER_LENGTH) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %i bytes [INCOMPLETE]", snap_len);
+ return;
+ }
+ else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %i bytes", snap_len);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree,
+ proto_gnutella,
+ tvb,
+ 0,
+ -1,
+ FALSE);
+ gnutella_tree = proto_item_add_subtree(ti, ett_gnutella);
+
+ offset = 0;
+
+ size = tvb_get_letohl(
+ tvb,
+ offset + GNUTELLA_HEADER_SIZE_OFFSET);
+ if(size > GNUTELLA_MAX_SNAP_SIZE) {
+ proto_tree_add_item(gnutella_tree,
+ hf_gnutella_stream,
+ tvb,
+ offset,
+ snap_len,
+ FALSE);
+ return;
+ }
+
+ while(snap_len - offset >= GNUTELLA_HEADER_LENGTH) {
+ payload_descriptor = tvb_get_guint8(
+ tvb,
+ offset +
+ GNUTELLA_HEADER_PAYLOAD_OFFSET);
+ size = tvb_get_letohl(
+ tvb,
+ offset + GNUTELLA_HEADER_SIZE_OFFSET);
+
+ switch(payload_descriptor) {
+ case GNUTELLA_PING:
+ payload_descriptor_text = GNUTELLA_PING_NAME;
+ break;
+ case GNUTELLA_PONG:
+ payload_descriptor_text = GNUTELLA_PONG_NAME;
+ break;
+ case GNUTELLA_PUSH:
+ payload_descriptor_text = GNUTELLA_PUSH_NAME;
+ break;
+ case GNUTELLA_QUERY:
+ payload_descriptor_text = GNUTELLA_QUERY_NAME;
+ break;
+ case GNUTELLA_QUERYHIT:
+ payload_descriptor_text = GNUTELLA_QUERYHIT_NAME;
+ break;
+ default:
+ payload_descriptor_text = GNUTELLA_UNKNOWN_NAME;
+ break;
+ }
+
+ hi = proto_tree_add_item(gnutella_tree,
+ hf_gnutella_header,
+ tvb,
+ offset,
+ GNUTELLA_HEADER_LENGTH,
+ FALSE);
+ gnutella_header_tree = proto_item_add_subtree(hi, ett_gnutella);
+
+ proto_tree_add_item(gnutella_header_tree,
+ hf_gnutella_header_id,
+ tvb,
+ offset + GNUTELLA_HEADER_ID_OFFSET,
+ GNUTELLA_SERVENT_ID_LENGTH,
+ FALSE);
+
+ proto_tree_add_uint_format(gnutella_header_tree,
+ hf_gnutella_header_payload,
+ tvb,
+ offset + GNUTELLA_HEADER_PAYLOAD_OFFSET,
+ GNUTELLA_BYTE_LENGTH,
+ payload_descriptor,
+ "Payload: %i (%s)",
+ payload_descriptor,
+ payload_descriptor_text);
+
+ proto_tree_add_item(gnutella_header_tree,
+ hf_gnutella_header_ttl,
+ tvb,
+ offset + GNUTELLA_HEADER_TTL_OFFSET,
+ GNUTELLA_BYTE_LENGTH,
+ FALSE);
+
+ proto_tree_add_item(gnutella_header_tree,
+ hf_gnutella_header_hops,
+ tvb,
+ offset + GNUTELLA_HEADER_HOPS_OFFSET,
+ GNUTELLA_BYTE_LENGTH,
+ FALSE);
+
+ proto_tree_add_uint(gnutella_header_tree,
+ hf_gnutella_header_size,
+ tvb,
+ offset + GNUTELLA_HEADER_SIZE_OFFSET,
+ GNUTELLA_LONG_LENGTH,
+ size);
+
+ if (size > 0) {
+
+ switch(payload_descriptor) {
+ case GNUTELLA_PONG:
+ pi = proto_tree_add_item(
+ gnutella_header_tree,
+ hf_gnutella_pong_payload,
+ tvb,
+ offset + GNUTELLA_HEADER_LENGTH,
+ size,
+ FALSE);
+ gnutella_pong_tree = proto_item_add_subtree(
+ pi,
+ ett_gnutella);
+ dissect_gnutella_pong(
+ tvb,
+ offset + GNUTELLA_HEADER_LENGTH,
+ gnutella_pong_tree,
+ size);
+ break;
+ case GNUTELLA_PUSH:
+ pi = proto_tree_add_item(
+ gnutella_header_tree,
+ hf_gnutella_push_payload,
+ tvb,
+ offset + GNUTELLA_HEADER_LENGTH,
+ size,
+ FALSE);
+ gnutella_push_tree = proto_item_add_subtree(
+ pi,
+ ett_gnutella);
+ dissect_gnutella_push(
+ tvb,
+ offset + GNUTELLA_HEADER_LENGTH,
+ gnutella_push_tree,
+ size);
+ break;
+ case GNUTELLA_QUERY:
+ pi = proto_tree_add_item(
+ gnutella_header_tree,
+ hf_gnutella_query_payload,
+ tvb,
+ offset + GNUTELLA_HEADER_LENGTH,
+ size,
+ FALSE);
+ gnutella_query_tree = proto_item_add_subtree(
+ pi,
+ ett_gnutella);
+ dissect_gnutella_query(
+ tvb,
+ offset + GNUTELLA_HEADER_LENGTH,
+ gnutella_query_tree,
+ size);
+ break;
+ case GNUTELLA_QUERYHIT:
+ pi = proto_tree_add_item(
+ gnutella_header_tree,
+ hf_gnutella_queryhit_payload,
+ tvb,
+ offset + GNUTELLA_HEADER_LENGTH,
+ size,
+ FALSE);
+ gnutella_queryhit_tree = proto_item_add_subtree(
+ pi,
+ ett_gnutella);
+ dissect_gnutella_queryhit(
+ tvb,
+ offset + GNUTELLA_HEADER_LENGTH,
+ gnutella_queryhit_tree,
+ size);
+ break;
+ }
+ }
+
+ offset = offset + GNUTELLA_HEADER_LENGTH + size;
+ }
+ }
+
+}
+
+
+void proto_register_gnutella(void) {
+
+ static hf_register_info hf[] = {
+ { &hf_gnutella_header,
+ { "Descriptor Header", "gnutella.header",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "Gnutella Descriptor Header", HFILL }
+ },
+ { &hf_gnutella_pong_payload,
+ { "Pong", "gnutella.pong.payload",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "Gnutella Pong Payload", HFILL }
+ },
+ { &hf_gnutella_push_payload,
+ { "Push", "gnutella.push.payload",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "Gnutella Push Payload", HFILL }
+ },
+ { &hf_gnutella_query_payload,
+ { "Query", "gnutella.query.payload",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "Gnutella Query Payload", HFILL }
+ },
+ { &hf_gnutella_queryhit_payload,
+ { "QueryHit", "gnutella.queryhit.payload",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "Gnutella QueryHit Payload", HFILL }
+ },
+ { &hf_gnutella_truncated,
+ { "Truncated Frame", "gnutella.truncated",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "The Gnutella Frame Was Truncated", HFILL }
+ },
+ { &hf_gnutella_stream,
+ { "Gnutella Upload / Download Stream", "gnutella.stream",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "Gnutella Upload / Download Stream", HFILL }
+ },
+ { &hf_gnutella_header_id,
+ { "ID", "gnutella.header.id",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Gnutella Descriptor ID", HFILL }
+ },
+ { &hf_gnutella_header_payload,
+ { "Payload", "gnutella.header.payload",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Gnutella Descriptor Payload", HFILL }
+ },
+ { &hf_gnutella_header_ttl,
+ { "TTL", "gnutella.header.ttl",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Gnutella Descriptor Time To Live", HFILL }
+ },
+ { &hf_gnutella_header_hops,
+ { "Hops", "gnutella.header.hops",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Gnutella Descriptor Hop Count", HFILL }
+ },
+ { &hf_gnutella_header_size,
+ { "Length", "gnutella.header.size",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Gnutella Descriptor Payload Length", HFILL }
+ },
+ { &hf_gnutella_pong_port,
+ { "Port", "gnutella.pong.port",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Gnutella Pong TCP Port", HFILL }
+ },
+ { &hf_gnutella_pong_ip,
+ { "IP", "gnutella.pong.ip",
+ FT_IPv4, BASE_DEC, NULL, 0,
+ "Gnutella Pong IP Address", HFILL }
+ },
+ { &hf_gnutella_pong_files,
+ { "Files Shared", "gnutella.pong.files",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Gnutella Pong Files Shared", HFILL }
+ },
+ { &hf_gnutella_pong_kbytes,
+ { "KBytes Shared", "gnutella.pong.kbytes",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Gnutella Pong KBytes Shared", HFILL }
+ },
+ { &hf_gnutella_query_min_speed,
+ { "Min Speed", "gnutella.query.min_speed",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Gnutella Query Minimum Speed", HFILL }
+ },
+ { &hf_gnutella_query_search,
+ { "Search", "gnutella.query.search",
+ FT_STRINGZ, BASE_NONE, NULL, 0,
+ "Gnutella Query Search", HFILL }
+ },
+ { &hf_gnutella_queryhit_hit,
+ { "Hit", "gnutella.queryhit.hit",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "Gnutella QueryHit", HFILL }
+ },
+ { &hf_gnutella_queryhit_hit_index,
+ { "Index", "gnutella.queryhit.hit.index",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Gnutella QueryHit Index", HFILL }
+ },
+ { &hf_gnutella_queryhit_hit_size,
+ { "Size", "gnutella.queryhit.hit.size",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Gnutella QueryHit Size", HFILL }
+ },
+ { &hf_gnutella_queryhit_hit_name,
+ { "Name", "gnutella.queryhit.hit.name",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "Gnutella Query Name", HFILL }
+ },
+ { &hf_gnutella_queryhit_hit_extra,
+ { "Extra", "gnutella.queryhit.hit.extra",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Gnutella Query Extra", HFILL }
+ },
+ { &hf_gnutella_queryhit_count,
+ { "Count", "gnutella.queryhit.count",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Gnutella QueryHit Count", HFILL }
+ },
+ { &hf_gnutella_queryhit_port,
+ { "Port", "gnutella.queryhit.port",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Gnutella QueryHit Port", HFILL }
+ },
+ { &hf_gnutella_queryhit_ip,
+ { "IP", "gnutella.queryhit.ip",
+ FT_IPv4, BASE_DEC, NULL, 0,
+ "Gnutella QueryHit IP Address", HFILL }
+ },
+ { &hf_gnutella_queryhit_speed,
+ { "Speed", "gnutella.queryhit.speed",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Gnutella QueryHit Speed", HFILL }
+ },
+ { &hf_gnutella_queryhit_extra,
+ { "Extra", "gnutella.queryhit.extra",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Gnutella QueryHit Extra", HFILL }
+ },
+ { &hf_gnutella_queryhit_servent_id,
+ { "Servent ID", "gnutella.queryhit.servent_id",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Gnutella QueryHit Servent ID", HFILL }
+ },
+ { &hf_gnutella_push_servent_id,
+ { "Servent ID", "gnutella.push.servent_id",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Gnutella Push Servent ID", HFILL }
+ },
+ { &hf_gnutella_push_ip,
+ { "IP", "gnutella.push.ip",
+ FT_IPv4, BASE_DEC, NULL, 0,
+ "Gnutella Push IP Address", HFILL }
+ },
+ { &hf_gnutella_push_index,
+ { "Index", "gnutella.push.index",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Gnutella Push Index", HFILL }
+ },
+ { &hf_gnutella_push_port,
+ { "Port", "gnutella.push.port",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Gnutella Push Port", HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_gnutella,
+ };
+
+ proto_gnutella = proto_register_protocol("Gnutella Protocol",
+ "GNUTELLA",
+ "gnutella");
+
+ proto_register_field_array(proto_gnutella, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void proto_reg_handoff_gnutella(void) {
+ dissector_handle_t gnutella_handle;
+
+ gnutella_handle = create_dissector_handle(dissect_gnutella,
+ proto_gnutella);
+ dissector_add("tcp.port", GNUTELLA_TCP_PORT, gnutella_handle);
+}
diff --git a/epan/dissectors/packet-gnutella.h b/epan/dissectors/packet-gnutella.h
new file mode 100644
index 0000000000..f079595827
--- /dev/null
+++ b/epan/dissectors/packet-gnutella.h
@@ -0,0 +1,80 @@
+/* packet-gnutella.h
+ * Declarations for gnutella dissection
+ * Copyright 2001, B. Johannessen <bob@havoq.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+void proto_register_gnutella(void);
+
+#define GNUTELLA_TCP_PORT 6346
+
+#define GNUTELLA_MAX_SNAP_SIZE 1500
+
+#define GNUTELLA_UNKNOWN_NAME "Unknown"
+#define GNUTELLA_PING 0x00
+#define GNUTELLA_PING_NAME "Ping"
+#define GNUTELLA_PONG 0x01
+#define GNUTELLA_PONG_NAME "Pong"
+#define GNUTELLA_PUSH 0x40
+#define GNUTELLA_PUSH_NAME "Push"
+#define GNUTELLA_QUERY 0x80
+#define GNUTELLA_QUERY_NAME "Query"
+#define GNUTELLA_QUERYHIT 0x81
+#define GNUTELLA_QUERYHIT_NAME "QueryHit"
+
+#define GNUTELLA_HEADER_LENGTH 23
+#define GNUTELLA_SERVENT_ID_LENGTH 16
+#define GNUTELLA_PORT_LENGTH 2
+#define GNUTELLA_IP_LENGTH 4
+#define GNUTELLA_LONG_LENGTH 4
+#define GNUTELLA_SHORT_LENGTH 2
+#define GNUTELLA_BYTE_LENGTH 1
+
+#define GNUTELLA_PONG_LENGTH 14
+#define GNUTELLA_PONG_PORT_OFFSET 0
+#define GNUTELLA_PONG_IP_OFFSET 2
+#define GNUTELLA_PONG_FILES_OFFSET 6
+#define GNUTELLA_PONG_KBYTES_OFFSET 10
+
+#define GNUTELLA_QUERY_SPEED_OFFSET 0
+#define GNUTELLA_QUERY_SEARCH_OFFSET 2
+
+#define GNUTELLA_QUERYHIT_HEADER_LENGTH 11
+#define GNUTELLA_QUERYHIT_COUNT_OFFSET 0
+#define GNUTELLA_QUERYHIT_PORT_OFFSET 1
+#define GNUTELLA_QUERYHIT_IP_OFFSET 3
+#define GNUTELLA_QUERYHIT_SPEED_OFFSET 7
+#define GNUTELLA_QUERYHIT_FIRST_HIT_OFFSET 11
+#define GNUTELLA_QUERYHIT_HIT_INDEX_OFFSET 0
+#define GNUTELLA_QUERYHIT_HIT_SIZE_OFFSET 4
+#define GNUTELLA_QUERYHIT_END_OF_STRING_LENGTH 2
+
+#define GNUTELLA_PUSH_SERVENT_ID_OFFSET 0
+#define GNUTELLA_PUSH_INDEX_OFFSET 16
+#define GNUTELLA_PUSH_IP_OFFSET 20
+#define GNUTELLA_PUSH_PORT_OFFSET 24
+
+#define GNUTELLA_HEADER_ID_OFFSET 0
+#define GNUTELLA_HEADER_PAYLOAD_OFFSET 16
+#define GNUTELLA_HEADER_TTL_OFFSET 17
+#define GNUTELLA_HEADER_HOPS_OFFSET 18
+#define GNUTELLA_HEADER_SIZE_OFFSET 19
diff --git a/epan/dissectors/packet-gprs-llc.c b/epan/dissectors/packet-gprs-llc.c
new file mode 100644
index 0000000000..a3837a9221
--- /dev/null
+++ b/epan/dissectors/packet-gprs-llc.c
@@ -0,0 +1,388 @@
+/* packet-llcgprs.c
+ * Routines for Logical Link Control GPRS dissection ETSI 4.64
+ * Copyright 2000, Josef Korelus <jkor@quick.cz>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+/*
+#include "packet-llcgprs.h"
+*/
+#define I_FORMAT 1
+#define S_FORMAT 2
+#define UI_FORMAT 3
+#define U_FORMAT 4
+#define I_SACK 5
+#define S_SACK 6
+#define UI_MASK_FMT 0xe000
+#define UI_MASK_SPB 0x1800
+#define UI_MASK_NU 0x07fc
+#define UI_MASK_E 0x0002
+#define UI_MASK_PM 0x0001
+
+/* Initialize the protocol and registered fields */
+static int proto_llcgprs = -1;
+static int hf_llcgprs_pd = -1;
+static int hf_llcgprs_cr = -1;
+static int hf_llcgprs_sapi = -1;
+static int hf_llcgprs_sapib = -1;
+static int hf_llcgprs_U_fmt = -1;/* 3 upper bits in controlfield (UI format) */
+static int hf_llcgprs_sp_bits = -1; /*Spare bits in control field*/
+static int hf_llcgprs_NU = -1; /*Transmited unconfirmed sequence number*/
+static int hf_llcgprs_E_bit = -1;/* Encryption mode bit*/
+static int hf_llcgprs_PM_bit = -1;
+static int hf_llcgprs_Un = -1;
+static int hf_llcgprs_As = -1;
+static int hf_llcgprs_ucom = -1;
+static int hf_llcgprs_PF = -1;
+static int hf_llcgprs_S_fmt = -1;
+static int hf_llcgprs_NR = -1;
+static int hf_llcgprs_sjsd = -1;
+/*static int hf_llcgprs_pd = -1;
+*/
+/* Initialize the subtree pointers */
+static gint ett_llcgprs = -1;
+static gint ett_llcgprs_adf = -1;
+static gint ett_llcgprs_ctrlf = -1;
+static gint ett_ui = -1;
+static gint ett_llcgprs_sframe = -1;
+
+static dissector_handle_t data_handle;
+static dissector_table_t llcgprs_subdissector_table;
+static const value_string sapi_t[] = {
+ { 0, "Reserved"},
+ { 1, "GPRS Mobility Management" },
+ { 2, "Tunnelling of messages 2" },
+ { 3, "User data 3"},
+ { 4, "Reserved" },
+ { 5, "User data 5" },
+ { 6, "Reserved" },
+ { 7, "SMS" },
+ { 8, "Tunneling of messages 8" },
+ { 9, "User data 9" },
+ { 10, "Reserved" },
+ { 11, "User data 11" },
+ { 12, "Reserved" },
+ { 13, "Reserved" },
+ { 14, "Reserved" },
+ { 15, "Reserved" },
+ { 0, NULL },
+};
+
+static const value_string sapi_abrv[] = {
+ { 0, "0"},
+ { 1, "LLGMM" },
+ { 2, "TOM2" },
+ { 3, "LL3"},
+ { 4, "4" },
+ { 5, "LL5" },
+ { 6, "6" },
+ { 7, "LLSMS" },
+ { 8, "TOM8" },
+ { 9, "LL9" },
+ { 10, "10" },
+ { 11, "LL11" },
+ { 12, "12" },
+ { 13, "13" },
+ { 14, "14" },
+ { 15, "15" },
+ { 0, NULL },
+};
+static const true_false_string a_bit = {
+ "To solicit an acknowledgement from the peer LLE. ",
+ "The peer LLE is not requested to send an acknowledgment."
+};
+
+static const true_false_string pd_bit = {
+ "Invalid frame PD=1",
+ "OK"
+};
+static const true_false_string e_bit = {
+ " encrypted frame",
+ " non encrypted frame"
+};
+static const true_false_string pm_bit = {
+ "FCS covers the frame header and information fields",
+ "FCS covers only the frame header and first N202 octets of the information field"
+};
+static const true_false_string cr_bit = {
+ "DownLink/UpLink = Command/Response",
+ "DownLink/UpLink = Response/Command"
+};
+/* bits are swaped comparing with "Table 3" in ETSI document*/
+static const value_string pme[] = {
+ { 0, "unprotected,non-ciphered information" },
+ { 1, "protected, non-ciphered information" },
+ { 2, "unprotected,ciphered information"},
+ { 3, "protected, ciphered information" },
+ { 0, NULL},
+};
+
+static const value_string cr_formats_unnumb[]= {
+ { 0x1, "DM-response" },
+ { 0x4, "DISC-command" },
+ { 0x6, "UA-response" },
+ { 0x7, "SABM" },
+ { 0x8, "FRMR" },
+ { 0xb, "XID" },
+ { 0, NULL },
+};
+static const value_string cr_formats_ipluss[] = {
+ { 0x0,"RR" },
+ { 0x1,"ACK" },
+ { 0x2,"RNR" },
+ { 0x3,"SACK" },
+ { 0, NULL },
+};
+/* Code to actually dissect the packets */
+static void
+dissect_llcgprs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 addr_fld=0, sapi=0, ctrl_fld_fb=0, frame_format, tmp=0 ;
+ guint16 offset=0 , epm = 0, nu=0,ctrl_fld_ui_s=0,crc_start=0 ;
+ proto_item *ti, *addres_field_item, *ctrl_field_item, *ui_ti;
+ proto_tree *llcgprs_tree=NULL , *ad_f_tree =NULL, *ctrl_f_tree=NULL, *ui_tree=NULL;
+ tvbuff_t *next_tvb;
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-LLC");
+
+ crc_start = tvb_length(tvb)-3;
+ addr_fld = tvb_get_guint8(tvb,offset);
+ offset++;
+ if (addr_fld > 128 ) {
+ if (check_col(pinfo->cinfo,COL_INFO))
+ col_add_str(pinfo->cinfo,COL_INFO,"Invalid packet - Protocol Discriminator bit is set to 1");
+ return;
+ }
+ sapi = addr_fld & 0xF;
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "SAPI: %s", match_strval(sapi,sapi_abrv));
+
+
+
+/* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+
+ ti = proto_tree_add_protocol_format(tree, proto_llcgprs, tvb, 0, -1,"MS-SGSN LLC (Mobile Station - Serving GPRS Support Node Logical Link Control) SAPI: %s", match_strval(sapi,sapi_t));
+
+ llcgprs_tree = proto_item_add_subtree(ti, ett_llcgprs);
+
+/* add an item to the subtree, see section 1.6 for more information */
+ proto_tree_add_text( llcgprs_tree, tvb, crc_start,3, "CRC of LLC layer" );
+ addres_field_item = proto_tree_add_uint_format(llcgprs_tree,hf_llcgprs_sapi,
+ tvb, 0,1, sapi, "Address field SAPI: %s", match_strval(sapi,sapi_abrv));
+ ad_f_tree = proto_item_add_subtree(addres_field_item, ett_llcgprs_adf);
+ proto_tree_add_boolean(ad_f_tree, hf_llcgprs_pd, tvb,0,1, addr_fld );
+ proto_tree_add_boolean(ad_f_tree, hf_llcgprs_cr, tvb,0,1, addr_fld );
+ proto_tree_add_uint(ad_f_tree, hf_llcgprs_sapib, tvb, 0, 1, addr_fld );
+ }
+
+ ctrl_fld_fb = tvb_get_guint8(tvb,offset);
+ if ( ctrl_fld_fb < 0xc0 ){
+ frame_format = ( ctrl_fld_fb < 0x80)? I_FORMAT : S_FORMAT;
+ }
+ else {
+ frame_format = ( ctrl_fld_fb < 0xe0 )? UI_FORMAT : U_FORMAT;
+ }
+ switch (frame_format){
+ case I_FORMAT:
+ if (check_col(pinfo->cinfo,COL_INFO)){
+ col_append_str(pinfo->cinfo,COL_INFO, ", I");
+ }
+
+ break;
+ case S_FORMAT:
+ case UI_FORMAT:
+ nu = ctrl_fld_ui_s = tvb_get_ntohs(tvb, offset);
+ offset +=2;
+ epm = ctrl_fld_ui_s & 0x3;
+ nu = (nu >>2)&0x01FF;
+ if (frame_format == S_FORMAT){
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_str(pinfo->cinfo, COL_INFO, ", S, ");
+ col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm,cr_formats_ipluss));
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", N(R) = %u", nu);
+ }
+ if (tree){
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset-2,2,"Supervisory format: %s: N(R) = %u",match_strval(epm,cr_formats_ipluss), nu);
+ ctrl_f_tree = proto_item_add_subtree( ctrl_field_item, ett_llcgprs_sframe);
+ proto_tree_add_uint( ctrl_f_tree, hf_llcgprs_S_fmt, tvb, offset-2,2, ctrl_fld_ui_s );
+ proto_tree_add_boolean( ctrl_f_tree, hf_llcgprs_As, tvb, offset-2, 2, ctrl_fld_ui_s );
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_NR, tvb, offset-2, 2, ctrl_fld_ui_s );
+ proto_tree_add_uint(ctrl_f_tree, hf_llcgprs_sjsd, tvb, offset-2, 2, ctrl_fld_ui_s );
+ }
+ }else{
+/*UI format*/
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, ", UI, ");
+ col_append_str(pinfo->cinfo, COL_INFO, match_strval(epm, pme ));
+ col_append_fstr(pinfo->cinfo,COL_INFO, ", N(U) = %u", nu);
+ }
+ if (tree){
+ ctrl_field_item = proto_tree_add_text(llcgprs_tree, tvb, offset-2, 2, "Unnumbered Information format - UI, N(U) = %u", nu);
+ ctrl_f_tree = proto_item_add_subtree(ctrl_field_item, ett_llcgprs_ctrlf);
+ proto_tree_add_uint( ctrl_f_tree, hf_llcgprs_U_fmt, tvb, offset-2, 2, ctrl_fld_ui_s);
+ proto_tree_add_uint( ctrl_f_tree, hf_llcgprs_sp_bits, tvb, offset-2,2,ctrl_fld_ui_s);
+ proto_tree_add_uint( ctrl_f_tree, hf_llcgprs_NU, tvb, offset-2, 2, ctrl_fld_ui_s);
+ proto_tree_add_boolean( ctrl_f_tree, hf_llcgprs_E_bit, tvb, offset-2,2,ctrl_fld_ui_s);
+ proto_tree_add_boolean( ctrl_f_tree, hf_llcgprs_PM_bit, tvb, offset-2,2,ctrl_fld_ui_s);
+ }
+
+ next_tvb = tvb_new_subset(tvb, offset,crc_start-3, -1 );
+ if (epm < 2){
+ if (!dissector_try_port(llcgprs_subdissector_table,sapi, next_tvb, pinfo, tree))
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ else call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ break;
+ case U_FORMAT:
+ offset +=1;
+ tmp = 0;
+ tmp = ctrl_fld_fb & 0xf;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, ", U, ");
+ col_append_str(pinfo->cinfo, COL_INFO, val_to_str(tmp, cr_formats_unnumb,"Unknown/invalid code:%X"));
+ }
+ if(tree){
+ ui_ti = proto_tree_add_text(llcgprs_tree,tvb,offset-1,crc_start-1,"Unnumbered frame: %s",val_to_str(tmp,cr_formats_unnumb,"Unknown/invalid code:%X"));
+ ui_tree = proto_item_add_subtree( ui_ti, ett_ui);
+ proto_tree_add_uint( ui_tree, hf_llcgprs_Un, tvb, offset-1, 1, ctrl_fld_fb);
+ proto_tree_add_boolean( ui_tree, hf_llcgprs_PF, tvb, offset-1, 1, ctrl_fld_fb);
+ proto_tree_add_uint( ui_tree, hf_llcgprs_ucom, tvb, offset-1, 1, ctrl_fld_fb);
+ }
+ break;
+/* case I_SACK:
+ break;
+ case S_SACK:
+ break;
+*/
+ }
+/* proto_tree_add_item(llcgprs_tree,
+ hf_llcgprs_FIELDABBREV, tvb, offset, len, FALSE)
+*/
+/* Continue adding tree items to process the packet here */
+
+
+
+/* If this protocol has a sub-dissector call it here, see section 1.8 */
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_llcgprs(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_llcgprs_sapi,
+ { "SAPI", "llcgprs.sapi", FT_UINT8, BASE_DEC, VALS(sapi_abrv), 0x0,"Service Access Point Identifier", HFILL }},
+ { &hf_llcgprs_pd,
+ { "Protocol Discriminator_bit", "llcgprs.pd", FT_BOOLEAN,8, TFS(&pd_bit), 0x80, " Protocol Discriminator bit (should be 0)", HFILL }},
+ {&hf_llcgprs_sjsd,
+ { "Supervisory function bits","llcgprs.s1s2", FT_UINT16, BASE_HEX, VALS(cr_formats_ipluss),0x3, "Supervisory functions bits",HFILL }},
+ { &hf_llcgprs_cr,
+ { "Command/Response bit", "llcgprs.cr", FT_BOOLEAN, 8, TFS(&cr_bit), 0x40, " Command/Response bit", HFILL}},
+ { &hf_llcgprs_sapib,
+ { "SAPI", "llcgprs.sapib", FT_UINT8, BASE_DEC , VALS(sapi_t), 0xf, "Service Access Point Identifier ",HFILL }},
+ { &hf_llcgprs_U_fmt,
+ { "UI format", "llcgprs.ui", FT_UINT16, BASE_HEX, NULL, UI_MASK_FMT, "UI frame format",HFILL}},
+ { &hf_llcgprs_Un,
+ { "U format", "llcgprs.u", FT_UINT8, BASE_DEC, NULL, 0xe0, " U frame format", HFILL}},
+ { &hf_llcgprs_sp_bits,
+ { "Spare bits", "llcgprs.ui_sp_bit", FT_UINT16, BASE_HEX, NULL, UI_MASK_SPB, "Spare bits", HFILL}},
+ { &hf_llcgprs_NU,
+ { "N(U)", "llcgprs.nu", FT_UINT16, BASE_DEC, NULL, UI_MASK_NU, "Transmited unconfirmed sequence number", HFILL}},
+ { &hf_llcgprs_E_bit,
+ { "E bit", "llcgprs.e", FT_BOOLEAN, 16, TFS(&e_bit), UI_MASK_E,"Encryption mode bit",HFILL }},
+ { &hf_llcgprs_PM_bit,
+ { "PM bit", "llcgprs.pm", FT_BOOLEAN, 16, TFS(&pm_bit), UI_MASK_PM, "Protected mode bit",HFILL}},
+ { &hf_llcgprs_As,
+ { "Ackn request bit", "llcgprs.as", FT_BOOLEAN, 16, TFS(&a_bit), 0x2000 ,"Acknowledgement request bit A", HFILL}},
+ { &hf_llcgprs_PF,
+ { "P/F bit", "llcgprs.pf", FT_BOOLEAN, 8, NULL, 0x10,"Poll /Finall bit", HFILL}},
+ { &hf_llcgprs_ucom,
+ { "Command/Response","llcgprs.ucom", FT_UINT8, BASE_HEX, VALS(cr_formats_unnumb),0xf,"Commands and Responses",HFILL }},
+ { &hf_llcgprs_NR,
+ { "Receive sequence number", "llcgprs.nr",FT_UINT16, BASE_DEC, NULL, UI_MASK_NU,"Receive sequence number N(R)",HFILL }},
+ {&hf_llcgprs_S_fmt,
+ { "S format", "llcgprs.s", FT_UINT16, BASE_DEC, NULL, 0xc000,"Supervisory format S", HFILL}}
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_llcgprs,
+ &ett_llcgprs_adf,
+ &ett_llcgprs_ctrlf,
+ &ett_ui,
+ &ett_llcgprs_sframe,
+ };
+
+/* Register the protocol name and description */
+ proto_llcgprs = proto_register_protocol("Logical Link Control GPRS",
+ "GPRS-LLC", "llcgprs");
+ llcgprs_subdissector_table = register_dissector_table("llcgprs.sapi","GPRS LLC SAPI", FT_UINT8,BASE_HEX);
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_llcgprs, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector( "llcgprs", dissect_llcgprs, proto_llcgprs);
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_llcgprs(void)
+{
+ dissector_handle_t llcgprs_handle;
+
+ llcgprs_handle = create_dissector_handle(dissect_llcgprs,
+ proto_llcgprs);
+/* dissector_add("PARENT_SUBFIELD", ID_VALUE, llcgprs_handle);
+*/
+ data_handle = find_dissector("data");
+}
+
diff --git a/epan/dissectors/packet-gprs-ns.c b/epan/dissectors/packet-gprs-ns.c
new file mode 100644
index 0000000000..1a63cb29c8
--- /dev/null
+++ b/epan/dissectors/packet-gprs-ns.c
@@ -0,0 +1,366 @@
+/* packet-gprs-ns.c
+ * Routines for GPRS Network Service (ETSI GSM 08.16 version 6.3.0)
+ * dissection
+ * Copyright 2003, Josef Korelus <jkor@quick.cz>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+/*ETSI GSM08.16 Network Service */
+#define NS_UNITDATA 0x00
+#define NS_RESET 0x02
+#define NS_RESET_ACK 0x03
+#define NS_BLOCK 0x04
+#define NS_BLOCK_ACK 0x05
+#define NS_UNBLOCK 0x06
+#define NS_UNBLOCK_ACK 0x07
+#define NS_STATUS 0x08
+#define NS_ALIVE 0x0a
+#define NS_ALIVE_ACK 0x0b
+
+/*ETSI GSM 08.16 IEI coding */
+#define Cause 0x00
+#define NS_VCI 0x01
+#define NS_PDU 0x02
+#define BVCI 0x03
+#define NSEI 0x04
+
+static int proto_gprs_ns = -1;
+static gint ett_gprs_ns = -1;
+static int hf_gprs_ns_pdutype = -1;
+static int hf_gprs_ns_ie_type = -1;
+static int hf_gprs_ns_ie_length = -1;
+static int hf_gprs_ns_cause = -1;
+static int hf_gprs_ns_vci = -1;
+static int hf_gprs_ns_nsei = -1;
+static int hf_gprs_ns_bvci = -1;
+static int hf_gprs_ns_spare = -1;
+
+static const value_string ns_pdu_type[]= {
+ { NS_UNITDATA, "NS-UNITDATA" },
+ { NS_RESET, "NS-RESET" },
+ { NS_RESET_ACK, "NS-RESET-ACK" },
+ { NS_BLOCK, "NS-BLOCK" },
+ { NS_BLOCK_ACK, "NS-BLOCK-ACK" },
+ { NS_UNBLOCK, "NS-UNBLOCK" },
+ { NS_UNBLOCK_ACK, "NS-UNBLOCK-ACK" },
+ { NS_STATUS, "NS-STATUS" },
+ { NS_ALIVE, "NS-ALIVE" },
+ { NS_ALIVE_ACK, "NS-ALIVE-ACK" },
+ { 0, NULL },
+};
+
+static const value_string ns_ie_type[]= {
+ { Cause, "Cause" },
+ { NS_VCI, "NS-VCI"},
+ { NS_PDU, "NS PDU"},
+ { BVCI, "BVCI"},
+ { NSEI, "NSEI"},
+ { 0, NULL },
+};
+
+static const value_string cause_val[]= {
+ { 0x0, "Transit network failure" },
+ { 0x1, "O&M intervention" },
+ { 0x2, "Equipment failure" },
+ { 0x3, "NS-VC blocked " },
+ { 0x4, "NS-VC unknown" },
+ { 0x5, "NS-VC unknown on that NSE" },
+ { 0x8, "Semantically incorrect PDU" },
+ { 0xa, "PDU not compatible with protocol state" },
+ { 0xb, "Protocol error - unspecified" },
+ { 0xc, "Invalid essential IE" },
+ { 0xd, "Missing essential IE" },
+ { 0, NULL },
+};
+
+static dissector_handle_t bssgp_handle;
+
+static void
+process_tlvs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 type;
+ int length_len;
+ guint16 length;
+ guint8 cause;
+ guint16 nsvc, bvc, nsei;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_gprs_ns_ie_type,
+ tvb, offset, 1, type);
+ offset++;
+
+ length_len = 1;
+ length = tvb_get_guint8(tvb, offset);
+ if (length & 0x80) {
+ /*
+ * This is the final octet of the length.
+ */
+ length &= 0x7F;
+ } else {
+ /*
+ * One more octet.
+ */
+ length_len++;
+ length = (length << 8) | tvb_get_guint8(tvb, offset);
+ }
+ proto_tree_add_uint(tree, hf_gprs_ns_ie_length,
+ tvb, offset, length_len, length);
+ offset += length_len;
+
+ switch (type) {
+
+ case Cause:
+ if (length == 1) {
+ cause = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree,
+ hf_gprs_ns_cause, tvb, offset, 1,
+ cause);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " Cause: %s",
+ val_to_str(cause, cause_val, "Unknown (0x%02x)"));
+ }
+ } else {
+ if (tree) {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "Bad cause length %u, should be 1",
+ length);
+ }
+ }
+ break;
+
+ case NS_VCI:
+ if (length == 2) {
+ nsvc = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree,
+ hf_gprs_ns_vci, tvb, offset, 2,
+ nsvc);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " NSVCI: %u", nsvc);
+ }
+ } else {
+ if (tree) {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "Bad NS-VCI length %u, should be 2",
+ length);
+ }
+ }
+ break;
+
+ case NS_PDU:
+ /*
+ * XXX - dissect as a GPRS NS PDU.
+ * Do the usual "error packet" stuff.
+ */
+ if (tree) {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "Error PDU");
+ }
+ break;
+
+ case BVCI:
+ if (length == 2) {
+ bvc = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree,
+ hf_gprs_ns_bvci, tvb, offset, 2,
+ bvc);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " BVCI: %u", bvc);
+ }
+ } else {
+ if (tree) {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "Bad BVCI length %u, should be 2",
+ length);
+ }
+ }
+ break;
+
+ case NSEI:
+ if (length == 2) {
+ nsei = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree,
+ hf_gprs_ns_nsei, tvb, offset, 2,
+ nsei);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " NSEI: %u", nsei);
+ }
+ } else {
+ if (tree) {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "Bad NSEI length %u, should be 2",
+ length);
+ }
+ }
+ break;
+
+ default:
+ if (tree) {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "Unknown IE contents");
+ }
+ break;
+ }
+ offset += length;
+ }
+}
+
+static void
+dissect_gprs_ns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_item *ti = NULL;
+ proto_tree *gprs_ns_tree = NULL;
+ guint8 nspdu;
+ guint16 bvc;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS NS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ nspdu = tvb_get_guint8(tvb,offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(nspdu, ns_pdu_type, "Unknown PDU type (0x%02x)"));
+ }
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_gprs_ns, tvb, 0, -1, FALSE);
+ gprs_ns_tree = proto_item_add_subtree(ti, ett_gprs_ns);
+ proto_tree_add_uint(gprs_ns_tree, hf_gprs_ns_pdutype, tvb, 0, 1, nspdu);
+ }
+ offset++;
+
+ switch (nspdu) {
+
+ case NS_ALIVE:
+ case NS_ALIVE_ACK:
+ case NS_UNBLOCK:
+ case NS_UNBLOCK_ACK:
+ break;
+
+ case NS_BLOCK:
+ case NS_BLOCK_ACK:
+ case NS_RESET:
+ case NS_RESET_ACK:
+ case NS_STATUS:
+ /*
+ * Process TLVs.
+ */
+ process_tlvs(tvb, offset, pinfo, gprs_ns_tree);
+ break;
+
+ case NS_UNITDATA:
+ if (tree)
+ proto_tree_add_item(gprs_ns_tree, hf_gprs_ns_spare, tvb, offset, 1, FALSE);
+ offset++;
+ bvc = tvb_get_ntohs(tvb,offset);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " BVCI: %u", bvc);
+ if (tree)
+ proto_tree_add_uint(gprs_ns_tree, hf_gprs_ns_bvci, tvb, offset, 2, bvc);
+ offset=offset+2;
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(bssgp_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_gprs_ns(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_gprs_ns_pdutype, {
+ "PDU Type", "gprs_ns.pdutype", FT_UINT8, BASE_HEX,
+ VALS(ns_pdu_type), 0x0, "NS Command", HFILL}},
+ { &hf_gprs_ns_ie_type, {
+ "IE Type", "gprs_ns.ietype", FT_UINT8, BASE_HEX,
+ VALS(ns_ie_type), 0x0, "IE Type", HFILL}},
+ { &hf_gprs_ns_ie_length, {
+ "IE Length", "gprs_ns.ielength", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "IE Length", HFILL}},
+ { &hf_gprs_ns_cause, {
+ "Cause", "gprs_ns.cause", FT_UINT8, BASE_HEX,
+ VALS(cause_val), 0x0, "Cause", HFILL}},
+ { &hf_gprs_ns_vci, {
+ "NSVCI", "gprs_ns.nsvci", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Network Service Virtual Connection id", HFILL}},
+ { &hf_gprs_ns_nsei, {
+ "NSEI", "gprs_ns.nsei", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Network Service Entity Id", HFILL}},
+ { &hf_gprs_ns_bvci, {
+ "BVCI", "gprs_ns.bvci", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Cell ID", HFILL}},
+ { &hf_gprs_ns_spare, {
+ "Spare octet", "gprs_ns.spare", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_gprs_ns,
+ };
+
+ proto_gprs_ns = proto_register_protocol("GPRS Network service",
+ "GPRS NS","gprs_ns");
+ proto_register_field_array(proto_gprs_ns, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("gprs_ns", dissect_gprs_ns, proto_gprs_ns);
+}
+
+void
+proto_reg_handoff_gprs_ns(void)
+{
+ bssgp_handle = find_dissector("bssgp");
+}
diff --git a/epan/dissectors/packet-gre.c b/epan/dissectors/packet-gre.c
new file mode 100644
index 0000000000..b7a29f575c
--- /dev/null
+++ b/epan/dissectors/packet-gre.c
@@ -0,0 +1,388 @@
+/* packet-gre.c
+ * Routines for the Generic Routing Encapsulation (GRE) protocol
+ * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-wccp.h"
+#include "in_cksum.h"
+#include "etypes.h"
+#include "greproto.h"
+#include "ipproto.h"
+#include "llcsaps.h"
+
+/*
+ * See RFC 1701 "Generic Routing Encapsulation (GRE)", RFC 1702
+ * "Generic Routing Encapsulation over IPv4 networks", RFC 2637
+ * "Point-to-Point Tunneling Protocol (PPTP)", RFC 2784 "Generic
+ * Routing Encapsulation (GRE)", RFC 2890 "Key and Sequence
+ * Number Extensions to GRE" and draft-ietf-mpls-in-ip-or-gre-07.txt
+ * "Encapsulating MPLS in IP or Generic Routing Encapsulation (GRE)".
+ */
+
+static int proto_gre = -1;
+static int hf_gre_proto = -1;
+
+static gint ett_gre = -1;
+static gint ett_gre_flags = -1;
+static gint ett_gre_wccp2_redirect_header = -1;
+
+static dissector_table_t gre_dissector_table;
+static dissector_handle_t data_handle;
+
+/* bit positions for flags in header */
+#define GH_B_C 0x8000
+#define GH_B_R 0x4000
+#define GH_B_K 0x2000
+#define GH_B_S 0x1000
+#define GH_B_s 0x0800
+#define GH_B_RECUR 0x0700
+#define GH_P_A 0x0080 /* only in special PPTPized GRE header */
+#define GH_P_FLAGS 0x0078 /* only in special PPTPized GRE header */
+#define GH_R_FLAGS 0x00F8
+#define GH_B_VER 0x0007
+
+static void add_flags_and_ver(proto_tree *, guint16, tvbuff_t *, int, int);
+static void dissect_gre_wccp2_redirect_header(tvbuff_t *, int, proto_tree *);
+
+static const value_string typevals[] = {
+ { ETHERTYPE_PPP, "PPP" },
+ { ETHERTYPE_IP, "IP" },
+ { SAP_OSINL5, "OSI"},
+ { GRE_WCCP, "WCCP"},
+ { ETHERTYPE_IPX, "IPX"},
+ { ETHERTYPE_ETHBRIDGE, "Transparent Ethernet bridging" },
+ { GRE_FR, "Frame Relay"},
+ { ETHERTYPE_IPv6, "IPv6" },
+ { ETHERTYPE_MPLS, "MPLS label switched packet" },
+ { 0, NULL }
+};
+
+static void
+dissect_gre(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint16 flags_and_ver;
+ guint16 type;
+ gboolean is_ppp = FALSE;
+ gboolean is_wccp2 = FALSE;
+ guint len = 4;
+ proto_item *ti;
+ proto_tree *gre_tree = NULL;
+ guint16 sre_af;
+ guint8 sre_length;
+ tvbuff_t *next_tvb;
+
+ flags_and_ver = tvb_get_ntohs(tvb, offset);
+ type = tvb_get_ntohs(tvb, offset + sizeof(flags_and_ver));
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GRE");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Encapsulated %s",
+ val_to_str(type, typevals, "0x%04X (unknown)"));
+ }
+
+ if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R)
+ len += 4;
+ if (flags_and_ver & GH_B_K)
+ len += 4;
+ if (flags_and_ver & GH_B_S)
+ len += 4;
+ switch (type) {
+
+ case ETHERTYPE_PPP:
+ if (flags_and_ver & GH_P_A)
+ len += 4;
+ is_ppp = TRUE;
+ break;
+
+ case GRE_WCCP:
+ /* WCCP2 puts an extra 4 octets into the header, but uses the same
+ encapsulation type; if it looks as if the first octet of the packet
+ isn't the beginning of an IPv4 header, assume it's WCCP2. */
+ if ((tvb_get_guint8(tvb, offset + sizeof(flags_and_ver) + sizeof(type)) & 0xF0) != 0x40) {
+ len += 4;
+ is_wccp2 = TRUE;
+ }
+ break;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_gre, tvb, offset, len,
+ "Generic Routing Encapsulation (%s)",
+ val_to_str(type, typevals, "0x%04X - unknown"));
+ gre_tree = proto_item_add_subtree(ti, ett_gre);
+ add_flags_and_ver(gre_tree, flags_and_ver, tvb, offset, is_ppp);
+ }
+ offset += sizeof(flags_and_ver);
+
+ if (tree) {
+ proto_tree_add_uint(gre_tree, hf_gre_proto, tvb, offset, sizeof(type), type);
+ }
+ offset += sizeof(type);
+
+ if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
+ if (tree) {
+ guint length, reported_length;
+ vec_t cksum_vec[1];
+ guint16 cksum, computed_cksum;
+
+ cksum = tvb_get_ntohs(tvb, offset);
+ length = tvb_length(tvb);
+ reported_length = tvb_reported_length(tvb);
+ if ((flags_and_ver & GH_B_C) && !pinfo->fragmented
+ && length >= reported_length) {
+ /* The Checksum Present bit is set, and the packet isn't part of a
+ fragmented datagram and isn't truncated, so we can checksum it. */
+
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, reported_length);
+ cksum_vec[0].len = reported_length;
+ computed_cksum = in_cksum(cksum_vec, 1);
+ if (computed_cksum == 0) {
+ proto_tree_add_text(gre_tree, tvb, offset, 2,
+ "Checksum: 0x%04x (correct)", cksum);
+ } else {
+ proto_tree_add_text(gre_tree, tvb, offset, 2,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ cksum, in_cksum_shouldbe(cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_text(gre_tree, tvb, offset, 2,
+ "Checksum: 0x%04x", cksum);
+ }
+ }
+ offset += 2;
+ }
+
+ if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
+ if (tree) {
+ proto_tree_add_text(gre_tree, tvb, offset, 2,
+ "Offset: %u", tvb_get_ntohs(tvb, offset));
+ }
+ offset += 2;
+ }
+
+ if (flags_and_ver & GH_B_K) {
+ if (is_ppp) {
+ if (tree) {
+ proto_tree_add_text(gre_tree, tvb, offset, 2,
+ "Payload length: %u", tvb_get_ntohs(tvb, offset));
+ }
+ offset += 2;
+ if (tree) {
+ proto_tree_add_text(gre_tree, tvb, offset, 2,
+ "Call ID: %u", tvb_get_ntohs(tvb, offset));
+ }
+ offset += 2;
+ }
+ else {
+ if (tree) {
+ proto_tree_add_text(gre_tree, tvb, offset, 4,
+ "Key: %u", tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ }
+ }
+
+ if (flags_and_ver & GH_B_S) {
+ if (tree) {
+ proto_tree_add_text(gre_tree, tvb, offset, 4,
+ "Sequence number: %u", tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ }
+
+ if (is_ppp && flags_and_ver & GH_P_A) {
+ if (tree) {
+ proto_tree_add_text(gre_tree, tvb, offset, 4,
+ "Acknowledgement number: %u", tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ }
+
+ if (flags_and_ver & GH_B_R) {
+ for (;;) {
+ sre_af = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_text(gre_tree, tvb, offset, sizeof(guint16),
+ "Address family: %u", sre_af);
+ }
+ offset += sizeof(guint16);
+ if (tree) {
+ proto_tree_add_text(gre_tree, tvb, offset, 1,
+ "SRE offset: %u", tvb_get_guint8(tvb, offset));
+ }
+ offset += sizeof(guint8);
+ sre_length = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_text(gre_tree, tvb, offset, sizeof(guint8),
+ "SRE length: %u", sre_length);
+ }
+ offset += sizeof(guint8);
+ if (sre_af == 0 && sre_length == 0)
+ break;
+ offset += sre_length;
+ }
+ }
+
+ if (type == GRE_WCCP) {
+ if (is_wccp2) {
+ if (tree)
+ dissect_gre_wccp2_redirect_header(tvb, offset, gre_tree);
+ offset += 4;
+ }
+ }
+
+ /* If the S bit is not set, this packet might not have a payload, so
+ check whether there's any data left, first.
+
+ XXX - the S bit isn't in RFC 2784, which deprecates that bit
+ and some other bits in RFC 1701 and says that they should be
+ zero for RFC 2784-compliant GRE; as such, the absence of the
+ S bit doesn't necessarily mean there's no payload. */
+ if (!(flags_and_ver & GH_B_S)) {
+ if (tvb_reported_length_remaining(tvb, offset) <= 0)
+ return; /* no payload */
+ }
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (!dissector_try_port(gre_dissector_table, type, next_tvb, pinfo, tree))
+ call_dissector(data_handle,next_tvb, pinfo, gre_tree);
+}
+
+static void
+add_flags_and_ver(proto_tree *tree, guint16 flags_and_ver, tvbuff_t *tvb,
+ int offset, int is_ppp)
+{
+ proto_item * ti;
+ proto_tree * fv_tree;
+ int nbits = sizeof(flags_and_ver) * 8;
+
+ ti = proto_tree_add_text(tree, tvb, offset, 2,
+ "Flags and version: %#04x", flags_and_ver);
+ fv_tree = proto_item_add_subtree(ti, ett_gre_flags);
+
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_boolean_bitfield(flags_and_ver, GH_B_C, nbits,
+ "Checksum", "No checksum"));
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_boolean_bitfield(flags_and_ver, GH_B_R, nbits,
+ "Routing", "No routing"));
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_boolean_bitfield(flags_and_ver, GH_B_K, nbits,
+ "Key", "No key"));
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_boolean_bitfield(flags_and_ver, GH_B_S, nbits,
+ "Sequence number", "No sequence number"));
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_boolean_bitfield(flags_and_ver, GH_B_s, nbits,
+ "Strict source route", "No strict source route"));
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_numeric_bitfield(flags_and_ver, GH_B_RECUR, nbits,
+ "Recursion control: %u"));
+ if (is_ppp) {
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_boolean_bitfield(flags_and_ver, GH_P_A, nbits,
+ "Acknowledgment number", "No acknowledgment number"));
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_numeric_bitfield(flags_and_ver, GH_P_FLAGS, nbits,
+ "Flags: %u"));
+ }
+ else {
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_numeric_bitfield(flags_and_ver, GH_R_FLAGS, nbits,
+ "Flags: %u"));
+ }
+
+ proto_tree_add_text(fv_tree, tvb, offset, sizeof(flags_and_ver), "%s",
+ decode_numeric_bitfield(flags_and_ver, GH_B_VER, nbits,
+ "Version: %u"));
+ }
+
+static void
+dissect_gre_wccp2_redirect_header(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item * ti;
+ proto_tree * rh_tree;
+ guint8 rh_flags;
+
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "Redirect header");
+ rh_tree = proto_item_add_subtree(ti, ett_gre_wccp2_redirect_header);
+
+ rh_flags = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(rh_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(rh_flags, 0x80, 8,
+ "Dynamic service", "Well-known service"));
+ proto_tree_add_text(rh_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(rh_flags, 0x40, 8,
+ "Alternative bucket used", "Alternative bucket not used"));
+
+ proto_tree_add_text(rh_tree, tvb, offset + 1, 1, "Service ID: %s",
+ val_to_str(tvb_get_guint8(tvb, offset + 1), service_id_vals, "Unknown (0x%02X)"));
+ if (rh_flags & 0x40)
+ proto_tree_add_text(rh_tree, tvb, offset + 2, 1, "Alternative bucket index: %u",
+ tvb_get_guint8(tvb, offset + 2));
+ proto_tree_add_text(rh_tree, tvb, offset + 3, 1, "Primary bucket index: %u",
+ tvb_get_guint8(tvb, offset + 3));
+}
+
+void
+proto_register_gre(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_gre_proto,
+ { "Protocol Type", "gre.proto", FT_UINT16, BASE_HEX, VALS(typevals), 0x0,
+ "The protocol that is GRE encapsulated", HFILL }
+ },
+ };
+ static gint *ett[] = {
+ &ett_gre,
+ &ett_gre_flags,
+ &ett_gre_wccp2_redirect_header,
+ };
+
+ proto_gre = proto_register_protocol("Generic Routing Encapsulation",
+ "GRE", "gre");
+ proto_register_field_array(proto_gre, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ gre_dissector_table = register_dissector_table("gre.proto",
+ "GRE protocol type", FT_UINT16, BASE_HEX);
+}
+
+void
+proto_reg_handoff_gre(void)
+{
+ dissector_handle_t gre_handle;
+
+ gre_handle = create_dissector_handle(dissect_gre, proto_gre);
+ dissector_add("ip.proto", IP_PROTO_GRE, gre_handle);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-gsm_a.c b/epan/dissectors/packet-gsm_a.c
new file mode 100644
index 0000000000..93fd544ac8
--- /dev/null
+++ b/epan/dissectors/packet-gsm_a.c
@@ -0,0 +1,11377 @@
+/* packet-gsm_a.c
+ * Routines for GSM A Interface (BSSMAP/DTAP) dissection
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * Title 3GPP Other
+ *
+ * Reference [1]
+ * Mobile radio interface signalling layer 3;
+ * General Aspects
+ * (3GPP TS 24.007 version 3.9.0 Release 1999)
+ *
+ * Reference [2]
+ * Mobile-services Switching Centre - Base Station System
+ * (MSC - BSS) interface;
+ * Layer 3 specification
+ * (GSM 08.08 version 7.7.0 Release 1998) TS 100 590 v7.7.0
+ *
+ * Reference [3]
+ * Mobile radio interface Layer 3 specification;
+ * Core network protocols;
+ * Stage 3
+ * (3GPP TS 24.008 version 4.7.0 Release 4)
+ *
+ * Reference [4]
+ * Mobile radio interface layer 3 specification;
+ * Radio Resource Control Protocol
+ * (GSM 04.18 version 8.4.1 Release 1999)
+ *
+ * Reference [5]
+ * Point-to-Point (PP) Short Message Service (SMS)
+ * support on mobile radio interface
+ * (3GPP TS 24.011 version 4.1.1 Release 4)
+ *
+ * Reference [6]
+ * Mobile radio Layer 3 supplementary service specification;
+ * Formats and coding
+ * (3GPP TS 24.080 version 4.3.0 Release 4)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+
+#include "epan/packet.h"
+#include "prefs.h"
+#include "tap.h"
+#include "asn1.h"
+
+#include "packet-tcap.h"
+#include "packet-bssap.h"
+#include "packet-gsm_ss.h"
+#include "packet-gsm_a.h"
+
+/* PROTOTYPES/FORWARDS */
+
+const value_string gsm_a_bssmap_msg_strings[] = {
+ { 0x01, "Assignment Request" },
+ { 0x02, "Assignment Complete" },
+ { 0x03, "Assignment Failure" },
+ { 0x10, "Handover Request" },
+ { 0x11, "Handover Required" },
+ { 0x12, "Handover Request Acknowledge" },
+ { 0x13, "Handover Command" },
+ { 0x14, "Handover Complete" },
+ { 0x15, "Handover Succeeded" },
+ { 0x16, "Handover Failure" },
+ { 0x17, "Handover Performed" },
+ { 0x18, "Handover Candidate Enquire" },
+ { 0x19, "Handover Candidate Response" },
+ { 0x1a, "Handover Required Reject" },
+ { 0x1b, "Handover Detect" },
+ { 0x20, "Clear Command" },
+ { 0x21, "Clear Complete" },
+ { 0x22, "Clear Request" },
+ { 0x23, "Reserved" },
+ { 0x24, "Reserved" },
+ { 0x25, "SAPI 'n' Reject" },
+ { 0x26, "Confusion" },
+ { 0x28, "Suspend" },
+ { 0x29, "Resume" },
+ { 0x2a, "Connection Oriented Information" },
+ { 0x2b, "Perform Location Request" },
+ { 0x2c, "LSA Information" },
+ { 0x2d, "Perform Location Response" },
+ { 0x2e, "Perform Location Abort" },
+ { 0x30, "Reset" },
+ { 0x31, "Reset Acknowledge" },
+ { 0x32, "Overload" },
+ { 0x33, "Reserved" },
+ { 0x34, "Reset Circuit" },
+ { 0x35, "Reset Circuit Acknowledge" },
+ { 0x36, "MSC Invoke Trace" },
+ { 0x37, "BSS Invoke Trace" },
+ { 0x3a, "Connectionless Information" },
+ { 0x40, "Block" },
+ { 0x41, "Blocking Acknowledge" },
+ { 0x42, "Unblock" },
+ { 0x43, "Unblocking Acknowledge" },
+ { 0x44, "Circuit Group Block" },
+ { 0x45, "Circuit Group Blocking Acknowledge" },
+ { 0x46, "Circuit Group Unblock" },
+ { 0x47, "Circuit Group Unblocking Acknowledge" },
+ { 0x48, "Unequipped Circuit" },
+ { 0x4e, "Change Circuit" },
+ { 0x4f, "Change Circuit Acknowledge" },
+ { 0x50, "Resource Request" },
+ { 0x51, "Resource Indication" },
+ { 0x52, "Paging" },
+ { 0x53, "Cipher Mode Command" },
+ { 0x54, "Classmark Update" },
+ { 0x55, "Cipher Mode Complete" },
+ { 0x56, "Queuing Indication" },
+ { 0x57, "Complete Layer 3 Information" },
+ { 0x58, "Classmark Request" },
+ { 0x59, "Cipher Mode Reject" },
+ { 0x5a, "Load Indication" },
+ { 0x04, "VGCS/VBS Setup" },
+ { 0x05, "VGCS/VBS Setup Ack" },
+ { 0x06, "VGCS/VBS Setup Refuse" },
+ { 0x07, "VGCS/VBS Assignment Request" },
+ { 0x1c, "VGCS/VBS Assignment Result" },
+ { 0x1d, "VGCS/VBS Assignment Failure" },
+ { 0x1e, "VGCS/VBS Queuing Indication" },
+ { 0x1f, "Uplink Request" },
+ { 0x27, "Uplink Request Acknowledge" },
+ { 0x49, "Uplink Request Confirmation" },
+ { 0x4a, "Uplink Release Indication" },
+ { 0x4b, "Uplink Reject Command" },
+ { 0x4c, "Uplink Release Command" },
+ { 0x4d, "Uplink Seized Command" },
+ { 0, NULL },
+};
+
+const value_string gsm_a_dtap_msg_mm_strings[] = {
+ { 0x01, "IMSI Detach Indication" },
+ { 0x02, "Location Updating Accept" },
+ { 0x04, "Location Updating Reject" },
+ { 0x08, "Location Updating Request" },
+ { 0x11, "Authentication Reject" },
+ { 0x12, "Authentication Request" },
+ { 0x14, "Authentication Response" },
+ { 0x1c, "Authentication Failure" },
+ { 0x18, "Identity Request" },
+ { 0x19, "Identity Response" },
+ { 0x1a, "TMSI Reallocation Command" },
+ { 0x1b, "TMSI Reallocation Complete" },
+ { 0x21, "CM Service Accept" },
+ { 0x22, "CM Service Reject" },
+ { 0x23, "CM Service Abort" },
+ { 0x24, "CM Service Request" },
+ { 0x25, "CM Service Prompt" },
+ { 0x26, "Reserved: was allocated in earlier phases of the protocol" },
+ { 0x28, "CM Re-establishment Request" },
+ { 0x29, "Abort" },
+ { 0x30, "MM Null" },
+ { 0x31, "MM Status" },
+ { 0x32, "MM Information" },
+ { 0, NULL },
+};
+
+const value_string gsm_a_dtap_msg_rr_strings[] = {
+ { 0x3c, "RR Initialisation Request" },
+ { 0x3b, "Additional Assignment" },
+ { 0x3f, "Immediate Assignment" },
+ { 0x39, "Immediate Assignment Extended" },
+ { 0x3a, "Immediate Assignment Reject" },
+
+ { 0x48, "DTM Assignment Failure" },
+ { 0x49, "DTM Reject" },
+ { 0x4a, "DTM Request" },
+ { 0x4b, "Main DCCH Assignment Command" },
+ { 0x4c, "Packet Assignment Command" },
+
+ { 0x35, "Ciphering Mode Command" },
+ { 0x32, "Ciphering Mode Complete" },
+
+ { 0x30, "Configuration Change Command" },
+ { 0x31, "Configuration Change Ack." },
+ { 0x33, "Configuration Change Reject" },
+
+ { 0x2e, "Assignment Command" },
+ { 0x29, "Assignment Complete" },
+ { 0x2f, "Assignment Failure" },
+ { 0x2b, "Handover Command" },
+ { 0x2c, "Handover Complete" },
+ { 0x28, "Handover Failure" },
+ { 0x2d, "Physical Information" },
+ { 0x4d, "DTM Assignment Command" },
+
+ { 0x08, "RR-cell Change Order" },
+ { 0x23, "PDCH Assignment Command" },
+
+ { 0x0d, "Channel Release" },
+ { 0x0a, "Partial Release" },
+ { 0x0f, "Partial Release Complete" },
+
+ { 0x21, "Paging Request Type 1" },
+ { 0x22, "Paging Request Type 2" },
+ { 0x24, "Paging Request Type 3" },
+ { 0x27, "Paging Response" },
+ { 0x20, "Notification/NCH" },
+ { 0x25, "Reserved" },
+ { 0x26, "Notification/Response" },
+
+ { 0x0b, "Reserved" },
+
+/* { 0xc0, "Utran Classmark Change" }, CONFLICTS WITH Handover To UTRAN Command */
+ { 0xc1, "UE RAB Preconfiguration" },
+ { 0xc2, "cdma2000 Classmark Change" },
+
+ { 0x18, "System Information Type 8" },
+ { 0x19, "System Information Type 1" },
+ { 0x1a, "System Information Type 2" },
+ { 0x1b, "System Information Type 3" },
+ { 0x1c, "System Information Type 4" },
+ { 0x1d, "System Information Type 5" },
+ { 0x1e, "System Information Type 6" },
+ { 0x1f, "System Information Type 7" },
+
+ { 0x02, "System Information Type 2bis" },
+ { 0x03, "System Information Type 2ter" },
+ { 0x07, "System Information Type 2quater" },
+ { 0x05, "System Information Type 5bis" },
+ { 0x06, "System Information Type 5ter" },
+ { 0x04, "System Information Type 9" },
+ { 0x00, "System Information Type 13" },
+
+ { 0x3d, "System Information Type 16" },
+ { 0x3e, "System Information Type 17" },
+
+ { 0x40, "System Information Type 18" },
+ { 0x41, "System Information Type 19" },
+ { 0x42, "System Information Type 20" },
+
+ { 0x10, "Channel Mode Modify" },
+ { 0x12, "RR Status" },
+ { 0x17, "Channel Mode Modify Acknowledge" },
+ { 0x14, "Frequency Redefinition" },
+ { 0x15, "Measurement Report" },
+ { 0x16, "Classmark Change" },
+ { 0x13, "Classmark Enquiry" },
+ { 0x36, "Extended Measurement Report" },
+ { 0x37, "Extended Measurement Order" },
+ { 0x34, "GPRS Suspension Request" },
+
+ { 0x09, "VGCS Uplink Grant" },
+ { 0x0e, "Uplink Release" },
+ { 0x0c, "Reserved" },
+ { 0x2a, "Uplink Busy" },
+ { 0x11, "Talker Indication" },
+
+ { 0xc0, "UTRAN Classmark Change/Handover To UTRAN Command" }, /* spec conflict */
+
+ { 0x38, "Application Information" },
+
+ { 0, NULL },
+};
+
+const value_string gsm_a_dtap_msg_cc_strings[] = {
+ { 0x01, "Alerting" },
+ { 0x08, "Call Confirmed" },
+ { 0x02, "Call Proceeding" },
+ { 0x07, "Connect" },
+ { 0x0f, "Connect Acknowledge" },
+ { 0x0e, "Emergency Setup" },
+ { 0x03, "Progress" },
+ { 0x04, "CC-Establishment" },
+ { 0x06, "CC-Establishment Confirmed" },
+ { 0x0b, "Recall" },
+ { 0x09, "Start CC" },
+ { 0x05, "Setup" },
+ { 0x17, "Modify" },
+ { 0x1f, "Modify Complete" },
+ { 0x13, "Modify Reject" },
+ { 0x10, "User Information" },
+ { 0x18, "Hold" },
+ { 0x19, "Hold Acknowledge" },
+ { 0x1a, "Hold Reject" },
+ { 0x1c, "Retrieve" },
+ { 0x1d, "Retrieve Acknowledge" },
+ { 0x1e, "Retrieve Reject" },
+ { 0x25, "Disconnect" },
+ { 0x2d, "Release" },
+ { 0x2a, "Release Complete" },
+ { 0x39, "Congestion Control" },
+ { 0x3e, "Notify" },
+ { 0x3d, "Status" },
+ { 0x34, "Status Enquiry" },
+ { 0x35, "Start DTMF" },
+ { 0x31, "Stop DTMF" },
+ { 0x32, "Stop DTMF Acknowledge" },
+ { 0x36, "Start DTMF Acknowledge" },
+ { 0x37, "Start DTMF Reject" },
+ { 0x3a, "Facility" },
+ { 0, NULL },
+};
+
+const value_string gsm_a_dtap_msg_gmm_strings[] = {
+ { 0x01, "Attach Request" },
+ { 0x02, "Attach Accept" },
+ { 0x03, "Attach Complete" },
+ { 0x04, "Attach Reject" },
+ { 0x05, "Detach Request" },
+ { 0x06, "Detach Accept" },
+ { 0x08, "Routing Area Update Request" },
+ { 0x09, "Routing Area Update Accept" },
+ { 0x0a, "Routing Area Update Complete" },
+ { 0x0b, "Routing Area Update Reject" },
+ { 0x0c, "Service Request" },
+ { 0x0d, "Service Accept" },
+ { 0x0e, "Service Reject" },
+ { 0x10, "P-TMSI Reallocation Command" },
+ { 0x11, "P-TMSI Reallocation Complete" },
+ { 0x12, "Authentication and Ciphering Req" },
+ { 0x13, "Authentication and Ciphering Resp" },
+ { 0x14, "Authentication and Ciphering Rej" },
+ { 0x1c, "Authentication and Ciphering Failure" },
+ { 0x15, "Identity Request" },
+ { 0x16, "Identity Response" },
+ { 0x20, "GMM Status" },
+ { 0x21, "GMM Information" },
+ { 0, NULL },
+};
+
+const value_string gsm_a_dtap_msg_sms_strings[] = {
+ { 0x01, "CP-DATA" },
+ { 0x04, "CP-ACK" },
+ { 0x10, "CP-ERROR" },
+ { 0, NULL },
+};
+
+const value_string gsm_a_dtap_msg_sm_strings[] = {
+ { 0x41, "Activate PDP Context Request" },
+ { 0x42, "Activate PDP Context Accept" },
+ { 0x43, "Activate PDP Context Reject" },
+ { 0x44, "Request PDP Context Activation" },
+ { 0x45, "Request PDP Context Activation rej." },
+ { 0x46, "Deactivate PDP Context Request" },
+ { 0x47, "Deactivate PDP Context Accept" },
+ { 0x48, "Modify PDP Context Request(Network to MS direction)" },
+ { 0x49, "Modify PDP Context Accept (MS to network direction)" },
+ { 0x4a, "Modify PDP Context Request(MS to network direction)" },
+ { 0x4b, "Modify PDP Context Accept (Network to MS direction)" },
+ { 0x4c, "Modify PDP Context Reject" },
+ { 0x4d, "Activate Secondary PDP Context Request" },
+ { 0x4e, "Activate Secondary PDP Context Accept" },
+ { 0x4f, "Activate Secondary PDP Context Reject" },
+ { 0x50, "Reserved: was allocated in earlier phases of the protocol" },
+ { 0x51, "Reserved: was allocated in earlier phases of the protocol" },
+ { 0x52, "Reserved: was allocated in earlier phases of the protocol" },
+ { 0x53, "Reserved: was allocated in earlier phases of the protocol" },
+ { 0x54, "Reserved: was allocated in earlier phases of the protocol" },
+ { 0x55, "SM Status" },
+ { 0, NULL },
+};
+
+const value_string gsm_a_dtap_msg_ss_strings[] = {
+ { 0x2a, "Release Complete" },
+ { 0x3a, "Facility" },
+ { 0x3b, "Register" },
+ { 0, NULL },
+};
+
+static const value_string gsm_rp_msg_strings[] = {
+ { 0x00, "RP-DATA (MS to Network)" },
+ { 0x01, "RP-DATA (Network to MS)" },
+ { 0x02, "RP-ACK (MS to Network)" },
+ { 0x03, "RP-ACK (Network to MS)" },
+ { 0x04, "RP-ERROR (MS to Network)" },
+ { 0x05, "RP-ERROR (Network to MS)" },
+ { 0x06, "RP-SMMA (MS to Network)" },
+ { 0, NULL },
+};
+
+static const value_string gsm_bssmap_elem_strings[] = {
+ { 0x01, "Circuit Identity Code" },
+ { 0x02, "Reserved" },
+ { 0x03, "Resource Available" },
+ { 0x04, "Cause" },
+ { 0x05, "Cell Identifier" },
+ { 0x06, "Priority" },
+ { 0x07, "Layer 3 Header Information" },
+ { 0x08, "IMSI" },
+ { 0x09, "TMSI" },
+ { 0x0a, "Encryption Information" },
+ { 0x0b, "Channel Type" },
+ { 0x0c, "Periodicity" },
+ { 0x0d, "Extended Resource Indicator" },
+ { 0x0e, "Number Of MSs" },
+ { 0x0f, "Reserved" },
+ { 0x10, "Reserved" },
+ { 0x11, "Reserved" },
+ { 0x12, "Classmark Information Type 2" },
+ { 0x13, "Classmark Information Type 3" },
+ { 0x14, "Interference Band To Be Used" },
+ { 0x15, "RR Cause" },
+ { 0x16, "Reserved" },
+ { 0x17, "Layer 3 Information" },
+ { 0x18, "DLCI" },
+ { 0x19, "Downlink DTX Flag" },
+ { 0x1a, "Cell Identifier List" },
+ { 0x1b, "Response Request" },
+ { 0x1c, "Resource Indication Method" },
+ { 0x1d, "Classmark Information Type 1" },
+ { 0x1e, "Circuit Identity Code List" },
+ { 0x1f, "Diagnostic" },
+ { 0x20, "Layer 3 Message Contents" },
+ { 0x21, "Chosen Channel" },
+ { 0x22, "Total Resource Accessible" },
+ { 0x23, "Cipher Response Mode" },
+ { 0x24, "Channel Needed" },
+ { 0x25, "Trace Type" },
+ { 0x26, "TriggerID" },
+ { 0x27, "Trace Reference" },
+ { 0x28, "TransactionID" },
+ { 0x29, "Mobile Identity" },
+ { 0x2a, "OMCID" },
+ { 0x2b, "Forward Indicator" },
+ { 0x2c, "Chosen Encryption Algorithm" },
+ { 0x2d, "Circuit Pool" },
+ { 0x2e, "Circuit Pool List" },
+ { 0x2f, "Time Indication" },
+ { 0x30, "Resource Situation" },
+ { 0x31, "Current Channel Type 1" },
+ { 0x32, "Queueing Indicator" },
+ { 0x40, "Speech Version" },
+ { 0x33, "Assignment Requirement" },
+ { 0x35, "Talker Flag" },
+ { 0x36, "Connection Release Requested" },
+ { 0x37, "Group Call Reference" },
+ { 0x38, "eMLPP Priority" },
+ { 0x39, "Configuration Evolution Indication" },
+ { 0x3a, "Old BSS to New BSS Information" },
+ { 0x3b, "LSA Identifier" },
+ { 0x3c, "LSA Identifier List" },
+ { 0x3d, "LSA Information" },
+ { 0x3e, "LCS QoS" },
+ { 0x3f, "LSA access control suppression" },
+ { 0x43, "LCS Priority" },
+ { 0x44, "Location Type" },
+ { 0x45, "Location Estimate" },
+ { 0x46, "Positioning Data" },
+ { 0x47, "LCS Cause" },
+ { 0x48, "LCS Client Type" },
+ { 0x49, "APDU" },
+ { 0x4a, "Network Element Identity" },
+ { 0x4b, "GPS Assistance Data" },
+ { 0x4c, "Deciphering Keys" },
+ { 0x4d, "Return Error Request" },
+ { 0x4e, "Return Error Cause" },
+ { 0x4f, "Segmentation" },
+ { 0, NULL },
+};
+
+static const value_string gsm_dtap_elem_strings[] = {
+ /* Common Information Elements 10.5.1 */
+ { 0x00, "Cell Identity" },
+ { 0x00, "Ciphering Key Sequence Number" },
+ { 0x00, "Location Area Identification" },
+ { 0x00, "Mobile Identity" },
+ { 0x00, "Mobile Station Classmark 1" },
+ { 0x00, "Mobile Station Classmark 2" },
+ { 0x00, "Mobile Station Classmark 3" },
+ { 0x00, "Descriptive group or broadcast call reference" },
+ { 0x00, "Group Cipher Key Number" },
+ { 0x00, "PD and SAPI $(CCBS)$" },
+ { 0x00, "Priority Level" },
+ { 0x00, "PLMN List" },
+ /* Radio Resource Management Information Elements 10.5.2, most are from 10.5.1 */
+ { 0x00, "RR Cause" },
+ /* Mobility Management Information Elements 10.5.3 */
+ { 0x00, "Authentication Parameter RAND" },
+ { 0x00, "Authentication Parameter AUTN (UMTS authentication challenge only)" },
+ { 0x00, "Authentication Response Parameter" },
+ { 0x00, "Authentication Response Parameter (extension) (UMTS authentication challenge only)" },
+ { 0x00, "Authentication Failure Parameter (UMTS authentication challenge only)" },
+ { 0x00, "CM Service Type" },
+ { 0x00, "Identity Type" },
+ { 0x00, "Location Updating Type" },
+ { 0x00, "Network Name" },
+ { 0x00, "Reject Cause" },
+ { 0x00, "Follow-on Proceed" },
+ { 0x00, "Time Zone" },
+ { 0x00, "Time Zone and Time" },
+ { 0x00, "CTS Permission" },
+ { 0x00, "LSA Identifier" },
+ { 0x00, "Daylight Saving Time" },
+ /* Call Control Information Elements 10.5.4 */
+ { 0x00, "Auxiliary States" },
+ { 0x00, "Bearer Capability" },
+ { 0x00, "Call Control Capabilities" },
+ { 0x00, "Call State" },
+ { 0x00, "Called Party BCD Number" },
+ { 0x00, "Called Party Subaddress" },
+ { 0x00, "Calling Party BCD Number" },
+ { 0x00, "Calling Party Subaddress" },
+ { 0x00, "Cause" },
+ { 0x00, "CLIR Suppression" },
+ { 0x00, "CLIR Invocation" },
+ { 0x00, "Congestion Level" },
+ { 0x00, "Connected Number" },
+ { 0x00, "Connected Subaddress" },
+ { 0x00, "Facility" },
+ { 0x00, "High Layer Compatibility" },
+ { 0x00, "Keypad Facility" },
+ { 0x00, "Low Layer Compatibility" },
+ { 0x00, "More Data" },
+ { 0x00, "Notification Indicator" },
+ { 0x00, "Progress Indicator" },
+ { 0x00, "Recall type $(CCBS)$" },
+ { 0x00, "Redirecting Party BCD Number" },
+ { 0x00, "Redirecting Party Subaddress" },
+ { 0x00, "Repeat Indicator" },
+ { 0x00, "Reverse Call Setup Direction" },
+ { 0x00, "SETUP Container $(CCBS)$" },
+ { 0x00, "Signal" },
+ { 0x00, "SS Version Indicator" },
+ { 0x00, "User-user" },
+ { 0x00, "Alerting Pattern $(NIA)$" },
+ { 0x00, "Allowed Actions $(CCBS)$" },
+ { 0x00, "Stream Identifier" },
+ { 0x00, "Network Call Control Capabilities" },
+ { 0x00, "Cause of No CLI" },
+ { 0x00, "Immediate Modification Indicator" },
+ { 0x00, "Supported Codec List" },
+ { 0x00, "Service Category" },
+ /* GPRS Mobility Management Information Elements 10.5.5 */
+ { 0x00, "Attach Result" },
+ { 0x00, "Attach Type" },
+ { 0x00, "TMSI Status" },
+ { 0x00, "Detach Type" },
+ { 0x00, "DRX Parameter" },
+ { 0x00, "Force to Standby" },
+ { 0x00, "P-TMSI Signature" },
+ { 0x00, "P-TMSI Signature 2" },
+ { 0x00, "Identity Type 2" },
+ { 0x00, "IMEISV Request" },
+ { 0x00, "Receive N-PDU Numbers List" },
+ { 0x00, "MS Network Capability" },
+ { 0x00, "MS Radio Access Capability" },
+ { 0x00, "GMM Cause" },
+ { 0x00, "Routing Area Identification" },
+ { 0x00, "Update Result" },
+ { 0x00, "A&C Reference Number" },
+ { 0x00, "Service Type" },
+ { 0x00, "Cell Notification" },
+ { 0x00, "Network Feature Support" },
+ /* Short Message Service Information Elements [5] 8.1.4 */
+ { 0x00, "CP-User Data" },
+ { 0x00, "CP-Cause" },
+ /* Short Message Service Information Elements [5] 8.2 */
+ { 0x00, "RP-Message Reference" },
+ { 0x00, "RP-Origination Address" },
+ { 0x00, "RP-Destination Address" },
+ { 0x00, "RP-User Data" },
+ { 0x00, "RP-Cause" },
+ /* Session Management Information Elements 10.5.6 */
+ { 0x00, "Access Point Name" },
+ { 0x00, "Network Service Access Point Identifier" },
+ { 0x00, "Protocol Configuration Options" },
+ { 0x00, "Packet Data Protocol Address" },
+ { 0x00, "Quality Of Service" },
+ { 0x00, "SM Cause" },
+ { 0x00, "Linked TI" },
+ { 0x00, "LLC Service Access Point Identifier" },
+ { 0x00, "Tear Down Indicator" },
+ { 0x00, "Packet Flow Identifier" },
+ { 0x00, "Traffic Flow Template" },
+ /* GPRS Common Information Elements 10.5.7 */
+ { 0x00, "PDP Context Status" },
+ { 0x00, "Radio Priority" },
+ { 0x00, "GPRS Timer" },
+ { 0x00, "GPRS Timer 2" },
+ { 0, NULL },
+};
+
+const gchar *gsm_a_pd_str[] = {
+ "Group Call Control",
+ "Broadcast Call Control",
+ "Reserved: was allocated in earlier phases of the protocol",
+ "Call Control; call related SS messages",
+ "GPRS Transparent Transport Protocol (GTTP)",
+ "Mobility Management messages",
+ "Radio Resources Management messages",
+ "Unknown",
+ "GPRS Mobility Management messages",
+ "SMS messages",
+ "GPRS Session Management messages",
+ "Non call related SS messages",
+ "Location Services",
+ "Unknown",
+ "Reserved for extension of the PD to one octet length",
+ "Reserved for tests procedures"
+};
+
+static const value_string bssap_cc_values[] = {
+ { 0x00, "not further specified" },
+ { 0x80, "FACCH or SDCCH" },
+ { 0xc0, "SACCH" },
+ { 0, NULL } };
+
+static const value_string bssap_sapi_values[] = {
+ { 0x00, "RR/MM/CC" },
+ { 0x03, "SMS" },
+ { 0, NULL } };
+
+static const gchar *cell_disc_str[] = {
+ "The whole Cell Global Identification, CGI, is used to identify the cells",
+ "Location Area Code, LAC, and Cell Identify, CI, is used to identify the cells",
+ "Cell Identity, CI, is used to identify the cells",
+ "No cell is associated with the transaction",
+ "Location Area Identification, LAI, is used to identify all cells within a Location Area",
+ "Location Area Code, LAC, is used to identify all cells within a location area",
+ "All cells on the BSS are identified"
+};
+#define NUM_CELL_DISC_STR (sizeof(cell_disc_str)/sizeof(gchar *))
+
+#define DTAP_PD_MASK 0x0f
+#define DTAP_SKIP_MASK 0xf0
+#define DTAP_TI_MASK DTAP_SKIP_MASK
+#define DTAP_TIE_PRES_MASK 0x07 /* after TI shifted to right */
+#define DTAP_TIE_MASK 0x7f
+
+#define DTAP_MM_IEI_MASK 0x3f
+#define DTAP_RR_IEI_MASK 0xff
+#define DTAP_CC_IEI_MASK 0x3f
+#define DTAP_GMM_IEI_MASK 0xff
+#define DTAP_SMS_IEI_MASK 0xff
+#define DTAP_SM_IEI_MASK 0xff
+#define DTAP_SS_IEI_MASK 0x3f
+
+/* Initialize the protocol and registered fields */
+static int proto_a_bssmap = -1;
+static int proto_a_dtap = -1;
+static int proto_a_rp = -1;
+
+static int gsm_a_tap = -1;
+
+static int hf_gsm_a_none = -1;
+static int hf_gsm_a_bssmap_msg_type = -1;
+static int hf_gsm_a_dtap_msg_mm_type = -1;
+static int hf_gsm_a_dtap_msg_rr_type = -1;
+static int hf_gsm_a_dtap_msg_cc_type = -1;
+static int hf_gsm_a_dtap_msg_gmm_type = -1;
+static int hf_gsm_a_dtap_msg_sms_type = -1;
+static int hf_gsm_a_dtap_msg_sm_type = -1;
+static int hf_gsm_a_dtap_msg_ss_type = -1;
+static int hf_gsm_a_rp_msg_type = -1;
+static int hf_gsm_a_length = -1;
+static int hf_gsm_a_bssmap_elem_id = -1;
+static int hf_gsm_a_dtap_elem_id = -1;
+static int hf_gsm_a_imsi = -1;
+static int hf_gsm_a_tmsi = -1;
+static int hf_gsm_a_imei = -1;
+static int hf_gsm_a_imeisv = -1;
+static int hf_gsm_a_cld_party_bcd_num = -1;
+static int hf_gsm_a_clg_party_bcd_num = -1;
+static int hf_gsm_a_cell_ci = -1;
+static int hf_gsm_a_cell_lac = -1;
+static int hf_gsm_a_dlci_cc = -1;
+static int hf_gsm_a_dlci_spare = -1;
+static int hf_gsm_a_dlci_sapi = -1;
+static int hf_gsm_a_bssmap_cause = -1;
+static int hf_gsm_a_dtap_cause = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_bssmap_msg = -1;
+static gint ett_dtap_msg = -1;
+static gint ett_rp_msg = -1;
+static gint ett_elems = -1;
+static gint ett_elem = -1;
+static gint ett_dtap_oct_1 = -1;
+static gint ett_cm_srvc_type = -1;
+static gint ett_gsm_enc_info = -1;
+static gint ett_cell_list = -1;
+static gint ett_dlci = -1;
+static gint ett_bc_oct_3a = -1;
+static gint ett_bc_oct_4 = -1;
+static gint ett_bc_oct_5 = -1;
+static gint ett_bc_oct_5a = -1;
+static gint ett_bc_oct_5b = -1;
+static gint ett_bc_oct_6 = -1;
+static gint ett_bc_oct_6a = -1;
+static gint ett_bc_oct_6b = -1;
+static gint ett_bc_oct_6c = -1;
+static gint ett_bc_oct_6d = -1;
+static gint ett_bc_oct_6e = -1;
+static gint ett_bc_oct_6f = -1;
+static gint ett_bc_oct_6g = -1;
+static gint ett_bc_oct_7 = -1;
+
+static gint ett_tc_component = -1;
+static gint ett_tc_invoke_id = -1;
+static gint ett_tc_linked_id = -1;
+static gint ett_tc_opr_code = -1;
+static gint ett_tc_err_code = -1;
+static gint ett_tc_prob_code = -1;
+static gint ett_tc_sequence = -1;
+
+static char a_bigbuf[1024];
+static gchar a_add_string[1024];
+
+static dissector_handle_t data_handle;
+static dissector_handle_t bssmap_handle;
+static dissector_handle_t dtap_handle;
+static dissector_handle_t rp_handle;
+static dissector_table_t sms_dissector_table; /* SMS TPDU */
+
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
+
+/*
+ * this should be set on a per message basis, if possible
+ */
+#define IS_UPLINK_FALSE 0
+#define IS_UPLINK_TRUE 1
+#define IS_UPLINK_UNKNOWN 2
+static gint is_uplink;
+
+
+typedef struct dgt_set_t
+{
+ unsigned char out[15];
+}
+dgt_set_t;
+
+static dgt_set_t Dgt_mbcd = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','*','#','a','b','c'
+ }
+};
+
+static dgt_set_t Dgt_tbcd = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#'
+ }
+};
+
+static dgt_set_t Dgt_msid = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
+ }
+};
+
+/* FUNCTIONS */
+
+/*
+ * Unpack BCD input pattern into output ASCII pattern
+ *
+ * Input Pattern is supplied using the same format as the digits
+ *
+ * Returns: length of unpacked pattern
+ */
+static int
+my_dgt_tbcd_unpack(
+ char *out, /* ASCII pattern out */
+ guchar *in, /* packed pattern in */
+ int num_octs, /* Number of octets to unpack */
+ dgt_set_t *dgt /* Digit definitions */
+ )
+{
+ int cnt = 0;
+ unsigned char i;
+
+ while (num_octs)
+ {
+ /*
+ * unpack first value in byte
+ */
+ i = *in++;
+ *out++ = dgt->out[i & 0x0f];
+ cnt++;
+
+ /*
+ * unpack second value in byte
+ */
+ i >>= 4;
+
+ if (i == 0x0f) /* odd number bytes - hit filler */
+ break;
+
+ *out++ = dgt->out[i];
+ cnt++;
+ num_octs--;
+ }
+
+ *out = '\0';
+
+ return(cnt);
+}
+
+static gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr)
+ {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+/* ELEMENT FUNCTIONS */
+
+#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
+ if ((edc_len) > (edc_max_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ curr_offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
+ curr_offset += ((edc_len) - (edc_max_len)); \
+ }
+
+#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
+ if ((sdc_len) < (sdc_min_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ curr_offset, (sdc_len), "Short Data (?)"); \
+ curr_offset += (sdc_len); \
+ return(curr_offset - offset); \
+ }
+
+#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
+ if ((edc_len) != (edc_eq_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ curr_offset, (edc_len), "Unexpected Data Length"); \
+ curr_offset += (edc_len); \
+ return(curr_offset - offset); \
+ }
+
+#define NO_MORE_DATA_CHECK(nmdc_len) \
+ if ((nmdc_len) == (curr_offset - offset)) return(nmdc_len);
+
+/*
+ * Decode the MCC/MNC from 3 octets in 'octs'
+ */
+static void
+mcc_mnc_aux(guint8 *octs, gchar *mcc, gchar *mnc)
+{
+ if ((octs[0] & 0x0f) <= 9)
+ {
+ mcc[0] = Dgt_tbcd.out[octs[0] & 0x0f];
+ }
+ else
+ {
+ mcc[0] = (octs[0] & 0x0f) + 55;
+ }
+
+ if (((octs[0] & 0xf0) >> 4) <= 9)
+ {
+ mcc[1] = Dgt_tbcd.out[(octs[0] & 0xf0) >> 4];
+ }
+ else
+ {
+ mcc[1] = ((octs[0] & 0xf0) >> 4) + 55;
+ }
+
+ if ((octs[1] & 0x0f) <= 9)
+ {
+ mcc[2] = Dgt_tbcd.out[octs[1] & 0x0f];
+ }
+ else
+ {
+ mcc[2] = (octs[1] & 0x0f) + 55;
+ }
+
+ mcc[3] = '\0';
+
+ if (((octs[1] & 0xf0) >> 4) <= 9)
+ {
+ mnc[2] = Dgt_tbcd.out[(octs[1] & 0xf0) >> 4];
+ }
+ else
+ {
+ mnc[2] = ((octs[1] & 0xf0) >> 4) + 55;
+ }
+
+ if ((octs[2] & 0x0f) <= 9)
+ {
+ mnc[0] = Dgt_tbcd.out[octs[2] & 0x0f];
+ }
+ else
+ {
+ mnc[0] = (octs[2] & 0x0f) + 55;
+ }
+
+ if (((octs[2] & 0xf0) >> 4) <= 9)
+ {
+ mnc[1] = Dgt_tbcd.out[(octs[2] & 0xf0) >> 4];
+ }
+ else
+ {
+ mnc[1] = ((octs[2] & 0xf0) >> 4) + 55;
+ }
+
+ if (mnc[1] == 'F')
+ {
+ /*
+ * only a 1 digit MNC (very old)
+ */
+ mnc[1] = '\0';
+ }
+ else if (mnc[2] == 'F')
+ {
+ /*
+ * only a 2 digit MNC
+ */
+ mnc[2] = '\0';
+ }
+ else
+ {
+ mnc[3] = '\0';
+ }
+}
+
+typedef enum
+{
+ BE_CIC, /* Circuit Identity Code */
+ BE_RSVD_1, /* Reserved */
+ BE_RES_AVAIL, /* Resource Available */
+ BE_CAUSE, /* Cause */
+ BE_CELL_ID, /* Cell Identifier */
+ BE_PRIO, /* Priority */
+ BE_L3_HEADER_INFO, /* Layer 3 Header Information */
+ BE_IMSI, /* IMSI */
+ BE_TMSI, /* TMSI */
+ BE_ENC_INFO, /* Encryption Information */
+ BE_CHAN_TYPE, /* Channel Type */
+ BE_PERIODICITY, /* Periodicity */
+ BE_EXT_RES_IND, /* Extended Resource Indicator */
+ BE_NUM_MS, /* Number Of MSs */
+ BE_RSVD_2, /* Reserved */
+ BE_RSVD_3, /* Reserved */
+ BE_RSVD_4, /* Reserved */
+ BE_CM_INFO_2, /* Classmark Information Type 2 */
+ BE_CM_INFO_3, /* Classmark Information Type 3 */
+ BE_INT_BAND, /* Interference Band To Be Used */
+ BE_RR_CAUSE, /* RR Cause */
+ BE_RSVD_5, /* Reserved */
+ BE_L3_INFO, /* Layer 3 Information */
+ BE_DLCI, /* DLCI */
+ BE_DOWN_DTX_FLAG, /* Downlink DTX Flag */
+ BE_CELL_ID_LIST, /* Cell Identifier List */
+ BE_RESP_REQ, /* Response Request */
+ BE_RES_IND_METHOD, /* Resource Indication Method */
+ BE_CM_INFO_1, /* Classmark Information Type 1 */
+ BE_CIC_LIST, /* Circuit Identity Code List */
+ BE_DIAG, /* Diagnostic */
+ BE_L3_MSG, /* Layer 3 Message Contents */
+ BE_CHOSEN_CHAN, /* Chosen Channel */
+ BE_TOT_RES_ACC, /* Total Resource Accessible */
+ BE_CIPH_RESP_MODE, /* Cipher Response Mode */
+ BE_CHAN_NEEDED, /* Channel Needed */
+ BE_TRACE_TYPE, /* Trace Type */
+ BE_TRIGGERID, /* TriggerID */
+ BE_TRACE_REF, /* Trace Reference */
+ BE_TRANSID, /* TransactionID */
+ BE_MID, /* Mobile Identity */
+ BE_OMCID, /* OMCID */
+ BE_FOR_IND, /* Forward Indicator */
+ BE_CHOSEN_ENC_ALG, /* Chosen Encryption Algorithm */
+ BE_CCT_POOL, /* Circuit Pool */
+ BE_CCT_POOL_LIST, /* Circuit Pool List */
+ BE_TIME_IND, /* Time Indication */
+ BE_RES_SIT, /* Resource Situation */
+ BE_CURR_CHAN_1, /* Current Channel Type 1 */
+ BE_QUE_IND, /* Queueing Indicator */
+ BE_SPEECH_VER, /* Speech Version */
+ BE_ASS_REQ, /* Assignment Requirement */
+ BE_TALKER_FLAG, /* Talker Flag */
+ BE_CONN_REL_REQ, /* Connection Release Requested */
+ BE_GROUP_CALL_REF, /* Group Call Reference */
+ BE_EMLPP_PRIO, /* eMLPP Priority */
+ BE_CONF_EVO_IND, /* Configuration Evolution Indication */
+ BE_OLD2NEW_INFO, /* Old BSS to New BSS Information */
+ BE_LSA_ID, /* LSA Identifier */
+ BE_LSA_ID_LIST, /* LSA Identifier List */
+ BE_LSA_INFO, /* LSA Information */
+ BE_LCS_QOS, /* LCS QoS */
+ BE_LSA_ACC_CTRL, /* LSA access control suppression */
+ BE_LCS_PRIO, /* LCS Priority */
+ BE_LOC_TYPE, /* Location Type */
+ BE_LOC_EST, /* Location Estimate */
+ BE_POS_DATA, /* Positioning Data */
+ BE_LCS_CAUSE, /* LCS Cause */
+ BE_LCS_CLIENT, /* LCS Client Type */
+ BE_APDU, /* APDU */
+ BE_NE_ID, /* Network Element Identity */
+ BE_GSP_ASSIST_DATA, /* GPS Assistance Data */
+ BE_DECIPH_KEYS, /* Deciphering Keys */
+ BE_RET_ERR_REQ, /* Return Error Request */
+ BE_RET_ERR_CAUSE, /* Return Error Cause */
+ BE_SEG, /* Segmentation */
+ BE_NONE /* NONE */
+}
+bssmap_elem_idx_t;
+
+#define NUM_GSM_BSSMAP_ELEM (sizeof(gsm_bssmap_elem_strings)/sizeof(value_string))
+static gint ett_gsm_bssmap_elem[NUM_GSM_BSSMAP_ELEM];
+
+/*
+ * [2] 3.2.2.2
+ */
+static guint8
+be_cic(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+ guint32 value;
+
+ len = len;
+ curr_offset = offset;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0xffe0, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : PCM Multiplexer: %u",
+ a_bigbuf,
+ (value & 0xffe0) >> 5);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x001f, 16);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 2,
+ "%s : Timeslot: %u",
+ a_bigbuf,
+ value & 0x001f);
+
+ curr_offset += 2;
+
+ sprintf(add_string, " - (%u) (0x%04x)", value, value);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.5
+ */
+static guint8
+be_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ guint32 curr_offset;
+ gchar *str = NULL;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "extended" : "not extended");
+
+ if (oct & 0x80)
+ {
+ /* 2 octet cause */
+
+ if ((oct & 0x0f) == 0x00)
+ {
+ /* national cause */
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "Normal Event"; break;
+ case 1: str = "Normal Event"; break;
+ case 2: str = "Resource Unavailable"; break;
+ case 3: str = "Service or option not available"; break;
+ case 4: str = "Service or option not implemented"; break;
+ case 5: str = "Invalid message (e.g., parameter out of range)"; break;
+ case 6: str = "Protocol error"; break;
+ default:
+ str = "Interworking";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Cause Class: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : National Cause",
+ a_bigbuf);
+
+ curr_offset++;
+
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Cause Value");
+
+ curr_offset++;
+
+ strcpy(add_string, " - (National Cause)");
+ }
+ else
+ {
+ value = tvb_get_guint8(tvb, curr_offset + 1);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Cause (MSB): %u",
+ a_bigbuf,
+ ((oct & 0x7f) << 8) | value);
+
+ curr_offset++;
+
+ other_decode_bitfield_value(a_bigbuf, value, 0xff, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Cause (LSB)",
+ a_bigbuf);
+
+ curr_offset++;
+ }
+ }
+ else
+ {
+ switch (oct)
+ {
+ case 0x00: str = "Radio interface message failure"; break;
+ case 0x01: str = "Radio interface failure"; break;
+ case 0x02: str = "Uplink quality"; break;
+ case 0x03: str = "Uplink strength"; break;
+ case 0x04: str = "Downlink quality"; break;
+ case 0x05: str = "Downlink strength"; break;
+ case 0x06: str = "Distance"; break;
+ case 0x07: str = "O and M intervention"; break;
+ case 0x08: str = "Response to MSC invocation"; break;
+ case 0x09: str = "Call control"; break;
+ case 0x0a: str = "Radio interface failure, reversion to old channel"; break;
+ case 0x0b: str = "Handover successful"; break;
+ case 0x0c: str = "Better Cell"; break;
+ case 0x0d: str = "Directed Retry"; break;
+ case 0x0e: str = "Joined group call channel"; break;
+ case 0x0f: str = "Traffic"; break;
+
+ case 0x20: str = "Equipment failure"; break;
+ case 0x21: str = "No radio resource available"; break;
+ case 0x22: str = "Requested terrestrial resource unavailable"; break;
+ case 0x23: str = "CCCH overload"; break;
+ case 0x24: str = "Processor overload"; break;
+ case 0x25: str = "BSS not equipped"; break;
+ case 0x26: str = "MS not equipped"; break;
+ case 0x27: str = "Invalid cell"; break;
+ case 0x28: str = "Traffic Load"; break;
+ case 0x29: str = "Preemption"; break;
+
+ case 0x30: str = "Requested transcoding/rate adaption unavailable"; break;
+ case 0x31: str = "Circuit pool mismatch"; break;
+ case 0x32: str = "Switch circuit pool"; break;
+ case 0x33: str = "Requested speech version unavailable"; break;
+ case 0x34: str = "LSA not allowed"; break;
+
+ case 0x40: str = "Ciphering algorithm not supported"; break;
+
+ case 0x50: str = "Terrestrial circuit already allocated"; break;
+ case 0x51: str = "Invalid message contents"; break;
+ case 0x52: str = "Information element or field missing"; break;
+ case 0x53: str = "Incorrect value"; break;
+ case 0x54: str = "Unknown Message type"; break;
+ case 0x55: str = "Unknown Information Element"; break;
+
+ case 0x60: str = "Protocol Error between BSS and MSC"; break;
+ case 0x61: str = "VGCS/VBS call non existent"; break;
+
+ default:
+ if ((oct >= 0x10) && (oct <= 0x17)) { str = "Reserved for international use"; }
+ else if ((oct >= 0x18) && (oct <= 0x1f)) { str = "Reserved for national use"; }
+ else if ((oct >= 0x2a) && (oct <= 0x2f)) { str = "Reserved for national use"; }
+ else if ((oct >= 0x35) && (oct <= 0x3f)) { str = "Reserved for international use"; }
+ else if ((oct >= 0x41) && (oct <= 0x47)) { str = "Reserved for international use"; }
+ else if ((oct >= 0x48) && (oct <= 0x4f)) { str = "Reserved for national use"; }
+ else if ((oct >= 0x56) && (oct <= 0x57)) { str = "Reserved for international use"; }
+ else if ((oct >= 0x58) && (oct <= 0x5f)) { str = "Reserved for national use"; }
+ else if ((oct >= 0x62) && (oct <= 0x67)) { str = "Reserved for international use"; }
+ else if ((oct >= 0x68) && (oct <= 0x6f)) { str = "Reserved for national use"; }
+ else if ((oct >= 0x70) && (oct <= 0x77)) { str = "Reserved for international use"; }
+ else if ((oct >= 0x78) && (oct <= 0x7f)) { str = "Reserved for national use"; }
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_uint_format(tree, hf_gsm_a_bssmap_cause,
+ tvb, curr_offset, 1, oct & 0x7f,
+ "%s : Cause: (%u) %s",
+ a_bigbuf,
+ oct & 0x7f,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%u) %s", oct & 0x7f, str);
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.7
+ */
+static guint8
+be_tmsi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+ guint32 value;
+
+ curr_offset = offset;
+
+ value = tvb_get_ntohl(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_gsm_a_tmsi,
+ tvb, curr_offset, 4,
+ value);
+
+ sprintf(add_string, " - (0x%04x)", value);
+
+ curr_offset += 4;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.9
+ */
+static guint8
+be_l3_header_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, DTAP_PD_MASK, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Protocol Discriminator: %s",
+ a_bigbuf,
+ gsm_a_pd_str[oct & DTAP_PD_MASK]);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : TI flag: %s",
+ a_bigbuf,
+ ((oct & 0x08) ? "allocated by receiver" : "allocated by sender"));
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : TIO: %u",
+ a_bigbuf,
+ oct & 0x07);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.10
+ */
+static guint8
+be_enc_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 mask;
+ guint8 alg_id;
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ mask = 0x80;
+ alg_id = 7;
+
+ do
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, mask, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : GSM A5/%u: %spermitted",
+ a_bigbuf,
+ alg_id,
+ (mask & oct) ? "" : "not ");
+
+ mask >>= 1;
+ alg_id--;
+ }
+ while (mask != 0x01);
+
+ other_decode_bitfield_value(a_bigbuf, oct, mask, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : No encryption: %spermitted",
+ a_bigbuf,
+ (mask & oct) ? "" : "not ");
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Key");
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.11
+ */
+static guint8
+be_chan_type(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 sdi;
+ guint8 num_chan;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ sdi = oct & 0x0f;
+ switch (sdi)
+ {
+ case 1: str = "Speech"; break;
+ case 2: str = "Data"; break;
+ case 3: str = "Signalling"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Speech/Data Indicator: %s",
+ a_bigbuf,
+ str);
+
+ sprintf(add_string, " - (%s)", str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (sdi == 0x01)
+ {
+ /* speech */
+
+ switch (oct)
+ {
+ case 0x08: str = "Full rate TCH channel Bm. Prefer full rate TCH"; break;
+ case 0x09: str = "Half rate TCH channel Lm. Prefer half rate TCH"; break;
+ case 0x0a: str = "Full or Half rate channel, Full rate preferred changes allowed after first allocation"; break;
+ case 0x0b: str = "Full or Half rate channel, Half rate preferred changes allowed after first allocation"; break;
+ case 0x1a: str = "Full or Half rate channel, Full rate preferred changes between full and half rate not allowed after first allocation"; break;
+ case 0x1b: str = "Full or Half rate channel, Half rate preferred changes between full and half rate not allowed after first allocation"; break;
+ case 0x0f: str = "Full or Half rate channel, changes allowed after first allocation"; break;
+ case 0x1f: str = "Full or Half rate channel, changes between full and half rate not allowed after first allocation"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Channel Rate and Type: %s",
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ do
+ {
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "extended" : "not extended");
+
+ switch (oct & 0x7f)
+ {
+ case 0x01: str = "GSM speech full rate version 1"; break;
+ case 0x11: str = "GSM speech full rate version 2"; break;
+ case 0x21: str = "GSM speech full rate version 3 (AMR)"; break;
+
+ case 0x05: str = "GSM speech half rate version 1"; break;
+ case 0x15: str = "GSM speech half rate version 2"; break;
+ case 0x25: str = "GSM speech half rate version 3 (AMR)"; break;
+
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Speech version identifier: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+ }
+ while ((len - (curr_offset - offset)) > 0);
+ }
+ else if (sdi == 0x02)
+ {
+ /* data */
+
+ num_chan = 0;
+
+ switch (oct)
+ {
+ case 0x08: str = "Full rate TCH channel Bm"; break;
+ case 0x09: str = "Half rate TCH channel Lm"; break;
+ case 0x0a: str = "Full or Half rate TCH channel, Full rate preferred, changes allowed also after first channel allocation as a result of the request"; break;
+ case 0x0b: str = "Full or Half rate TCH channel, Half rate preferred, changes allowed also after first channel allocation as a result of the request"; break;
+ case 0x1a: str = "Full or Half rate TCH channel, Full rate preferred, changes not allowed after first channel allocation as a result of the request"; break;
+ case 0x1b: str = "Full or Half rate TCH channel. Half rate preferred, changes not allowed after first channel allocation as a result of the request"; break;
+ default:
+ if ((oct >= 0x20) && (oct <= 0x27))
+ {
+ str = "Full rate TCH channels in a multislot configuration, changes by the BSS of the the number of TCHs and if applicable the used radio interface rate per channel allowed after first channel allocation as a result of the request";
+
+ num_chan = (oct - 0x20) + 1;
+ }
+ else if ((oct >= 0x30) && (oct <= 0x37))
+ {
+ str = "Full rate TCH channels in a multislot configuration, changes by the BSS of the number of TCHs or the used radio interface rate per channel not allowed after first channel allocation as a result of the request";
+
+ num_chan = (oct - 0x30) + 1;
+ }
+ else
+ {
+ str = "Reserved";
+ }
+ break;
+ }
+
+ if (num_chan > 0)
+ {
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Channel Rate and Type: Max channels %u, %s",
+ num_chan,
+ str);
+ }
+ else
+ {
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Channel Rate and Type: %s",
+ str);
+ }
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : %sTransparent service",
+ a_bigbuf,
+ (oct & 0x40) ? "Non-" : "");
+
+ if (num_chan == 0)
+ {
+ if (oct & 0x40)
+ {
+ /* non-transparent */
+
+ switch (oct & 0x3f)
+ {
+ case 0x00: str = "12 kbit/s if the channel is a full rate TCH, or 6 kbit/s if the channel is a half rate TCH"; break;
+ case 0x18: str = "14.5 kbit/s"; break;
+ case 0x10: str = "12 kbits/s"; break;
+ case 0x11: str = "6 kbits/s"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+ }
+ else
+ {
+ switch (oct & 0x3f)
+ {
+ case 0x18: str = "14.4 kbit/s"; break;
+ case 0x10: str = "9.6kbit/s"; break;
+ case 0x11: str = "4.8kbit/s"; break;
+ case 0x12: str = "2.4kbit/s"; break;
+ case 0x13: str = "1.2Kbit/s"; break;
+ case 0x14: str = "600 bit/s"; break;
+ case 0x15: str = "1200/75 bit/s (1200 network-to-MS / 75 MS-to-network)"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (oct & 0x40)
+ {
+ /* non-transparent */
+
+ switch (oct & 0x3f)
+ {
+ case 0x16: str = "58 kbit/s (4x14.5 kbit/s)"; break;
+ case 0x14: str = "48.0 / 43.5 kbit/s (4x12 kbit/s or 3x14.5 kbit/s)"; break;
+ case 0x13: str = "36.0 / 29.0 kbit/s (3x12 kbit/s or 2x14.5 kbit/s)"; break;
+ case 0x12: str = "24.0 / 24.0 (4x6 kbit/s or 2x12 kbit/s)"; break;
+ case 0x11: str = "18.0 / 14.5 kbit/s (3x6 kbit/s or 1x14.5 kbit/s)"; break;
+ case 0x10: str = "12.0 / 12.0 kbit/s (2x6 kbit/s or 1x12 kbit/s)"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+ }
+ else
+ {
+ switch (oct & 0x3f)
+ {
+ case 0x1f: str = "64 kbit/s, bit transparent"; break;
+ case 0x1e: str = "56 kbit/s, bit transparent"; break;
+ case 0x1d: str = "56 kbit/s"; break;
+ case 0x1c: str = "48 kbit/s"; break;
+ case 0x1b: str = "38.4 kbit/s"; break;
+ case 0x1a: str = "28.8 kbit/s"; break;
+ case 0x19: str = "19.2 kbit/s"; break;
+ case 0x18: str = "14.4 kbit/s"; break;
+ case 0x10: str = "9.6 kbit/s"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+ }
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Rate: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ if (num_chan == 0)
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : 14.5 kbit/s (TCH/F14.4) %sallowed",
+ a_bigbuf,
+ (oct & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : 12.0 kbit/s (TCH F/9.6) %sallowed",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : 6.0 kbit/s (TCH F/4.8) %sallowed",
+ a_bigbuf,
+ (oct & 0x01) ? "" : "not ");
+ }
+ else
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : 14.5/14.4 kbit/s (TCH/F14.4) %sallowed",
+ a_bigbuf,
+ (oct & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : 12.0/9.6 kbit/s (TCH F/9.6) %sallowed",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : 6.0/4.8 kbit/s (TCH F/4.8) %sallowed",
+ a_bigbuf,
+ (oct & 0x01) ? "" : "not ");
+ }
+
+ curr_offset++;
+ }
+ else if (sdi == 0x03)
+ {
+ /* signalling */
+
+ switch (oct)
+ {
+ case 0x00: str = "SDCCH or Full rate TCH channel Bm or Half rate TCH channel Lm"; break;
+ case 0x01: str = "SDCCH"; break;
+ case 0x02: str = "SDCCH or Full rate TCH channel Bm"; break;
+ case 0x03: str = "SDCCH or Half rate TCH channel Lm"; break;
+ case 0x08: str = "Full rate TCH channel Bm"; break;
+ case 0x09: str = "Half rate TCH channel Lm"; break;
+ case 0x0a: str = "Full or Half rate TCH channel, Full rate preferred, changes allowed also after first channel allocation as a result of the request"; break;
+ case 0x0b: str = "Full or Half rate TCH channel, Half rate preferred, changes allowed also after first channel allocation as a result of the request"; break;
+ case 0x1a: str = "Full or Half rate TCH channel, Full rate preferred, changes not allowed after first channel allocation as a result of the request"; break;
+ case 0x1b: str = "Full or Half rate TCH channel. Half rate preferred, changes not allowed after first channel allocation as a result of the request"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Channel Rate and Type: %s",
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Spare");
+
+ curr_offset += len - (curr_offset - offset);
+ }
+ else
+ {
+ /* unknown format */
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Unknown format");
+
+ curr_offset += len - (curr_offset - offset);
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.17
+ * Formats everything after the discriminator, shared function
+ */
+static guint8
+be_cell_id_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string, guint8 disc)
+{
+ guint8 octs[3];
+ guint32 value;
+ guint32 curr_offset;
+ gchar mcc[4];
+ gchar mnc[4];
+
+ add_string[0] = '\0';
+ curr_offset = offset;
+
+ switch (disc)
+ {
+ case 0x00:
+ /* FALLTHRU */
+
+ case 0x04:
+ octs[0] = tvb_get_guint8(tvb, curr_offset);
+ octs[1] = tvb_get_guint8(tvb, curr_offset + 1);
+ octs[2] = tvb_get_guint8(tvb, curr_offset + 2);
+
+ mcc_mnc_aux(octs, mcc, mnc);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 3,
+ "Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
+ mcc,
+ mnc);
+
+ curr_offset += 3;
+
+ /* FALLTHRU */
+
+ case 0x01:
+ case 0x05:
+
+ /* LAC */
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_gsm_a_cell_lac, tvb,
+ curr_offset, 2, value);
+
+ curr_offset += 2;
+
+ sprintf(add_string, " - LAC (0x%04x)", value);
+
+ if ((disc == 0x04) || (disc == 0x05)) break;
+
+ /* FALLTHRU */
+
+ case 0x02:
+
+ /* CI */
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_gsm_a_cell_ci, tvb,
+ curr_offset, 2, value);
+
+ curr_offset += 2;
+
+ if (add_string[0] == '\0')
+ {
+ sprintf(add_string, " - CI (%u)", value);
+ }
+ else
+ {
+ sprintf(add_string, "%s/CI (%u)", add_string, value);
+ }
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+ "Cell ID - Unknown format");
+
+ curr_offset += (len - 1);
+ break;
+ }
+
+ return(curr_offset - offset);
+}
+
+static guint8
+be_cell_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 disc;
+ guint32 curr_offset;
+ const gchar *str = NULL;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ disc = oct & 0x0f;
+
+ if (disc >= (gint) NUM_CELL_DISC_STR)
+ {
+ str = "Unknown";
+ }
+ else
+ {
+ str = cell_disc_str[disc];
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Cell Identification Discriminator: (%u) %s",
+ a_bigbuf,
+ disc,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ curr_offset +=
+ be_cell_id_aux(tvb, tree, curr_offset, len - (curr_offset - offset), add_string, disc);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.18
+ */
+static guint8
+be_prio(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Preemption Capability Indicator (PCI): this allocation request %s preempt an existing connection",
+ a_bigbuf,
+ (oct & 0x40) ? "may" : "shall not");
+
+ switch ((oct & 0x3c) >> 2)
+ {
+ case 0x00: str = "Spare"; break;
+ case 0x0f: str = "priority not used"; break;
+ default:
+ str = "1 is highest";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3c, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Priority Level: (%u) %s",
+ a_bigbuf,
+ (oct & 0x3c) >> 2,
+ str);
+
+ sprintf(add_string, " - (%u)", (oct & 0x3c) >> 2);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Queuing Allowed Indicator (QA): queuing %sallowed",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Preemption Vulnerability Indicator (PVI): this connection %s be preempted by another allocation request",
+ a_bigbuf,
+ (oct & 0x01) ? "might" : "shall not");
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.24
+ */
+static guint8
+be_l3_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+ tvbuff_t *l3_tvb;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ "Layer 3 Information value");
+
+ /*
+ * dissect the embedded DTAP message
+ */
+ l3_tvb = tvb_new_subset(tvb, curr_offset, len, len);
+
+ call_dissector(dtap_handle, l3_tvb, g_pinfo, g_tree);
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.25
+ */
+static guint8
+be_dlci(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ item =
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "Data Link Connection Identifier");
+
+ subtree = proto_item_add_subtree(item, ett_dlci);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_uint(subtree, hf_gsm_a_dlci_cc, tvb, curr_offset, 1, oct);
+ proto_tree_add_uint(subtree, hf_gsm_a_dlci_spare, tvb, curr_offset, 1, oct);
+ proto_tree_add_uint(subtree, hf_gsm_a_dlci_sapi, tvb, curr_offset, 1, oct);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.26
+ */
+static guint8
+be_down_dtx_flag(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint oct;
+ guint32 curr_offset;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfe, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : BSS is %s to activate DTX in the downlink direction",
+ a_bigbuf,
+ (oct & 0x01) ? "forbidden" : "allowed");
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.27
+ */
+static guint8
+be_cell_id_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 consumed;
+ guint8 disc;
+ guint8 num_cells;
+ guint32 curr_offset;
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+ const gchar *str = NULL;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ disc = oct & 0x0f;
+
+ if (disc >= (gint) NUM_CELL_DISC_STR)
+ {
+ str = "Unknown";
+ }
+ else
+ {
+ str = cell_disc_str[disc];
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Cell Identification Discriminator: (%u) %s",
+ a_bigbuf,
+ disc,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ num_cells = 0;
+ do
+ {
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, -1,
+ "Cell %u",
+ num_cells + 1);
+
+ subtree = proto_item_add_subtree(item, ett_cell_list);
+
+ add_string[0] = '\0';
+ consumed =
+ be_cell_id_aux(tvb, subtree, curr_offset, len - (curr_offset - offset), add_string, disc);
+
+ if (add_string[0] != '\0')
+ {
+ proto_item_append_text(item, add_string);
+ }
+
+ proto_item_set_len(item, consumed);
+
+ curr_offset += consumed;
+
+ num_cells++;
+ }
+ while ((len - (curr_offset - offset)) > 0);
+
+ sprintf(add_string, " - %u cell%s",
+ num_cells, plurality(num_cells, "", "s"));
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.33
+ */
+static guint8
+be_chosen_chan(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str = NULL;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch ((oct & 0xf0) >> 4)
+ {
+ case 0: str = "No channel mode indication"; break;
+ case 9: str = "Speech (full rate or half rate)"; break;
+ case 14: str = "Data, 14.5 kbit/s radio interface rate"; break;
+ case 11: str = "Data, 12.0 kbit/s radio interface rate"; break;
+ case 12: str = "Data, 6.0 kbit/s radio interface rate"; break;
+ case 13: str = "Data, 3.6 kbit/s radio interface rate"; break;
+ case 8: str = "Signalling only"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Channel mode: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x0f)
+ {
+ case 0: str = "None"; break;
+ case 1: str = "SDCCH"; break;
+ case 8: str = "1 Full rate TCH"; break;
+ case 9: str = "1 Half rate TCH"; break;
+ case 10: str = "2 Full Rate TCHs"; break;
+ case 11: str = "3 Full Rate TCHs"; break;
+ case 12: str = "4 Full Rate TCHs"; break;
+ case 13: str = "5 Full Rate TCHs"; break;
+ case 14: str = "6 Full Rate TCHs"; break;
+ case 15: str = "7 Full Rate TCHs"; break;
+ case 4: str = "8 Full Rate TCHs"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Channel: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.34
+ */
+static guint8
+be_ciph_resp_mode(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfe, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : IMEISV must %sbe included by the mobile station",
+ a_bigbuf,
+ (oct & 0x01) ? "" : "not ");
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.35
+ */
+static guint8
+be_l3_msg(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+ tvbuff_t *l3_tvb;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ "Layer 3 Message Contents");
+
+ /*
+ * dissect the embedded DTAP message
+ */
+ l3_tvb = tvb_new_subset(tvb, curr_offset, len, len);
+
+ call_dissector(dtap_handle, l3_tvb, g_pinfo, g_tree);
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.43
+ */
+static guint8
+be_for_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str = NULL;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x0f)
+ {
+ case 1: str = "forward to subsequent BSS, no trace at MSC"; break;
+ case 2: str = "forward to subsequent BSS, and trace at MSC"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.44
+ */
+static guint8
+be_chosen_enc_alg(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str = NULL;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0x01: str = "No encryption used"; break;
+ case 0x02: str = "GSM A5/1"; break;
+ case 0x03: str = "GSM A5/2"; break;
+ case 0x04: str = "GSM A5/3"; break;
+ case 0x05: str = "GSM A5/4"; break;
+ case 0x06: str = "GSM A5/5"; break;
+ case 0x07: str = "GSM A5/6"; break;
+ case 0x08: str = "GSM A5/7"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Algorithm Identifier: %s",
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - %s", str);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.45
+ */
+static guint8
+be_cct_pool(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str = NULL;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct <= 32)
+ {
+ str = "";
+ }
+ else if ((oct >= 0x80) && (oct <= 0x8f))
+ {
+ str = ", for national/local use";
+ }
+ else
+ {
+ str = ", reserved for future international use";
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Circuit pool number: %u%s",
+ oct,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%u)", oct);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.49
+ */
+static guint8
+be_curr_chan_1(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch ((oct & 0xf0) >> 4)
+ {
+ case 0x00: str = "Signalling only"; break;
+ case 0x01: str = "Speech (full rate or half rate)"; break;
+ case 0x06: str = "Data, 14.5 kbit/s radio interface rate"; break;
+ case 0x03: str = "Data, 12.0 kbit/s radio interface rate"; break;
+ case 0x04: str = "Data, 6.0 kbit/s radio interface rate"; break;
+ case 0x05: str = "Data, 3.6 kbit/s radio interface rate"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Channel Mode: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x0f)
+ {
+ case 0x01: str = "SDCCH"; break;
+ case 0x08: str = "1 Full rate TCH"; break;
+ case 0x09: str = "1 Half rate TCH"; break;
+ case 0x0a: str = "2 Full Rate TCHs"; break;
+ case 0x0b: str = "3 Full Rate TCHs"; break;
+ case 0x0c: str = "4 Full Rate TCHs"; break;
+ case 0x0d: str = "5 Full Rate TCHs"; break;
+ case 0x0e: str = "6 Full Rate TCHs"; break;
+ case 0x0f: str = "7 Full Rate TCHs"; break;
+ case 0x04: str = "8 Full Rate TCHs"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Channel: (%u) %s",
+ a_bigbuf,
+ oct & 0x0f,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.50
+ */
+static guint8
+be_que_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : qri: it is recommended %sto allow queuing",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.51
+ */
+static guint8
+be_speech_ver(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str = NULL;
+ gchar *short_str = NULL;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x7f)
+ {
+ case 0x01: str = "GSM speech full rate version 1"; short_str = "FR1"; break;
+ case 0x11: str = "GSM speech full rate version 2"; short_str = "FR2"; break;
+ case 0x21: str = "GSM speech full rate version 3 (AMR)"; short_str = "FR3 (AMR)"; break;
+
+ case 0x05: str = "GSM speech half rate version 1"; short_str = "HR1"; break;
+ case 0x15: str = "GSM speech half rate version 2"; short_str = "HR2"; break;
+ case 0x25: str = "GSM speech half rate version 3 (AMR)"; short_str = "HR3 (AMR)"; break;
+
+ default:
+ str = "Reserved";
+ short_str = str;
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Speech version identifier: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%s)", short_str);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [2] 3.2.2.68
+ */
+static guint8
+be_apdu(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ "APDU");
+
+ /*
+ * dissect the embedded APDU message
+ * if someone writes a TS 09.31 dissector
+ */
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+typedef enum
+{
+ /* Common Information Elements 10.5.1 */
+ DE_CELL_ID, /* Cell Identity */
+ DE_CIPH_KEY_SEQ_NUM, /* Ciphering Key Sequence Number */
+ DE_LAI, /* Location Area Identification */
+ DE_MID, /* Mobile Identity */
+ DE_MS_CM_1, /* Mobile Station Classmark 1 */
+ DE_MS_CM_2, /* Mobile Station Classmark 2 */
+ DE_MS_CM_3, /* Mobile Station Classmark 3 */
+ DE_D_GB_CALL_REF, /* Descriptive group or broadcast call reference */
+ DE_G_CIPH_KEY_NUM, /* Group Cipher Key Number */
+ DE_PD_SAPI, /* PD and SAPI $(CCBS)$ */
+ DE_PRIO, /* Priority Level */
+ DE_PLMN_LIST, /* PLMN List */
+ /* Radio Resource Management Information Elements 10.5.2, most are from 10.5.1 */
+ DE_RR_CAUSE, /* RR Cause */
+ /* Mobility Management Information Elements 10.5.3 */
+ DE_AUTH_PARAM_RAND, /* Authentication Parameter RAND */
+ DE_AUTH_PARAM_AUTN, /* Authentication Parameter AUTN (UMTS authentication challenge only) */
+ DE_AUTH_RESP_PARAM, /* Authentication Response Parameter */
+ DE_AUTH_RESP_PARAM_EXT, /* Authentication Response Parameter (extension) (UMTS authentication challenge only) */
+ DE_AUTH_FAIL_PARAM, /* Authentication Failure Parameter (UMTS authentication challenge only) */
+ DE_CM_SRVC_TYPE, /* CM Service Type */
+ DE_ID_TYPE, /* Identity Type */
+ DE_LOC_UPD_TYPE, /* Location Updating Type */
+ DE_NETWORK_NAME, /* Network Name */
+ DE_REJ_CAUSE, /* Reject Cause */
+ DE_FOP, /* Follow-on Proceed */
+ DE_TIME_ZONE, /* Time Zone */
+ DE_TIME_ZONE_TIME, /* Time Zone and Time */
+ DE_CTS_PERM, /* CTS Permission */
+ DE_LSA_ID, /* LSA Identifier */
+ DE_DAY_SAVING_TIME, /* Daylight Saving Time */
+ /* Call Control Information Elements 10.5.4 */
+ DE_AUX_STATES, /* Auxiliary States */
+ DE_BEARER_CAP, /* Bearer Capability */
+ DE_CC_CAP, /* Call Control Capabilities */
+ DE_CALL_STATE, /* Call State */
+ DE_CLD_PARTY_BCD_NUM, /* Called Party BCD Number */
+ DE_CLD_PARTY_SUB_ADDR, /* Called Party Subaddress */
+ DE_CLG_PARTY_BCD_NUM, /* Calling Party BCD Number */
+ DE_CLG_PARTY_SUB_ADDR, /* Calling Party Subaddress */
+ DE_CAUSE, /* Cause */
+ DE_CLIR_SUP, /* CLIR Suppression */
+ DE_CLIR_INV, /* CLIR Invocation */
+ DE_CONGESTION, /* Congestion Level */
+ DE_CONN_NUM, /* Connected Number */
+ DE_CONN_SUB_ADDR, /* Connected Subaddress */
+ DE_FACILITY, /* Facility */
+ DE_HLC, /* High Layer Compatibility */
+ DE_KEYPAD_FACILITY, /* Keypad Facility */
+ DE_LLC, /* Low Layer Compatibility */
+ DE_MORE_DATA, /* More Data */
+ DE_NOT_IND, /* Notification Indicator */
+ DE_PROG_IND, /* Progress Indicator */
+ DE_RECALL_TYPE, /* Recall type $(CCBS)$ */
+ DE_RED_PARTY_BCD_NUM, /* Redirecting Party BCD Number */
+ DE_RED_PARTY_SUB_ADDR, /* Redirecting Party Subaddress */
+ DE_REPEAT_IND, /* Repeat Indicator */
+ DE_REV_CALL_SETUP_DIR, /* Reverse Call Setup Direction */
+ DE_SETUP_CONTAINER, /* SETUP Container $(CCBS)$ */
+ DE_SIGNAL, /* Signal */
+ DE_SS_VER_IND, /* SS Version Indicator */
+ DE_USER_USER, /* User-user */
+ DE_ALERT_PATTERN, /* Alerting Pattern $(NIA)$ */
+ DE_ALLOWED_ACTIONS, /* Allowed Actions $(CCBS)$ */
+ DE_SI, /* Stream Identifier */
+ DE_NET_CC_CAP, /* Network Call Control Capabilities */
+ DE_CAUSE_NO_CLI, /* Cause of No CLI */
+ DE_IMM_MOD_IND, /* Immediate Modification Indicator */
+ DE_SUP_CODEC_LIST, /* Supported Codec List */
+ DE_SRVC_CAT, /* Service Category */
+ /* GPRS Mobility Management Information Elements 10.5.5 */
+ DE_ATTACH_RES, /* Attach Result */
+ DE_ATTACH_TYPE, /* Attach Type */
+ DE_TMSI_STAT, /* TMSI Status */
+ DE_DETACH_TYPE, /* Detach Type */
+ DE_DRX_PARAM, /* DRX Parameter */
+ DE_FORCE_TO_STAND, /* Force to Standby */
+ DE_P_TMSI_SIG, /* P-TMSI Signature */
+ DE_P_TMSI_SIG_2, /* P-TMSI Signature 2 */
+ DE_ID_TYPE_2, /* Identity Type 2 */
+ DE_IMEISV_REQ, /* IMEISV Request */
+ DE_REC_N_PDU_NUM_LIST, /* Receive N-PDU Numbers List */
+ DE_MS_NET_CAP, /* MS Network Capability */
+ DE_MS_RAD_ACC_CAP, /* MS Radio Access Capability */
+ DE_GMM_CAUSE, /* GMM Cause */
+ DE_RAI, /* Routing Area Identification */
+ DE_UPD_RES, /* Update Result */
+ DE_AC_REF_NUM, /* A&C Reference Number */
+ DE_SRVC_TYPE, /* Service Type */
+ DE_CELL_NOT, /* Cell Notification */
+ DE_NET_FEAT_SUP, /* Network Feature Support */
+ /* Short Message Service Information Elements [5] 8.1.4 */
+ DE_CP_USER_DATA, /* CP-User Data */
+ DE_CP_CAUSE, /* CP-Cause */
+ /* Short Message Service Information Elements [5] 8.2 */
+ DE_RP_MESSAGE_REF, /* RP-Message Reference */
+ DE_RP_ORIG_ADDR, /* RP-Origination Address */
+ DE_RP_DEST_ADDR, /* RP-Destination Address */
+ DE_RP_USER_DATA, /* RP-User Data */
+ DE_RP_CAUSE, /* RP-Cause */
+ /* Session Management Information Elements 10.5.6 */
+ DE_ACC_POINT_NAME, /* Access Point Name */
+ DE_NET_SAPI, /* Network Service Access Point Identifier */
+ DE_PRO_CONF_OPT, /* Protocol Configuration Options */
+ DE_PD_PRO_ADDR, /* Packet Data Protocol Address */
+ DE_QOS, /* Quality Of Service */
+ DE_SM_CAUSE, /* SM Cause */
+ DE_LINKED_TI, /* Linked TI */
+ DE_LLC_SAPI, /* LLC Service Access Point Identifier */
+ DE_TEAR_DOWN_IND, /* Tear Down Indicator */
+ DE_PACKET_FLOW_ID, /* Packet Flow Identifier */
+ DE_TRAFFIC_FLOW_TEMPLATE, /* Traffic Flow Template */
+ /* GPRS Common Information Elements 10.5.7 */
+ DE_PDP_CONTEXT_STAT, /* PDP Context Status */
+ DE_RAD_PRIO, /* Radio Priority */
+ DE_GPRS_TIMER, /* GPRS Timer */
+ DE_GPRS_TIMER_2, /* GPRS Timer 2 */
+ DE_NONE /* NONE */
+}
+dtap_elem_idx_t;
+
+#define NUM_GSM_DTAP_ELEM (sizeof(gsm_dtap_elem_strings)/sizeof(value_string))
+static gint ett_gsm_dtap_elem[NUM_GSM_DTAP_ELEM];
+
+/*
+ * [3] 10.5.1.1
+ */
+static guint8
+de_cell_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ curr_offset = offset;
+
+ curr_offset +=
+ be_cell_id_aux(tvb, tree, offset, len, add_string, 0x02);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.1.3
+ */
+static guint8
+de_lai(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 octs[3];
+ guint16 value;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar mcc[4];
+ gchar mnc[4];
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ octs[0] = tvb_get_guint8(tvb, curr_offset);
+ octs[1] = tvb_get_guint8(tvb, curr_offset + 1);
+ octs[2] = tvb_get_guint8(tvb, curr_offset + 2);
+
+ mcc_mnc_aux(octs, mcc, mnc);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 5,
+ gsm_dtap_elem_strings[DE_LAI].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_LAI]);
+
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 3,
+ "Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
+ mcc,
+ mnc);
+
+ curr_offset += 3;
+
+ value = tvb_get_ntohs(tvb, curr_offset);
+
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 2,
+ "Location Area Code (LAC): 0x%04x (%u)",
+ value,
+ value);
+
+ proto_item_append_text(item, " - LAC (0x%04x)", value);
+
+ curr_offset += 2;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.1.4
+ */
+static guint8
+de_mid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ guint8 *poctets;
+ guint32 value;
+ gboolean odd;
+
+ curr_offset = offset;
+ odd = FALSE;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct & 0x07)
+ {
+ case 0: /* No Identity */
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Unused",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even Indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "ODD" : "EVEN");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: No Identity Code",
+ a_bigbuf);
+
+ strcpy(add_string, " - No Identity Code");
+
+ curr_offset++;
+
+ if (len > 1)
+ {
+ proto_tree_add_text(tree, tvb, curr_offset, len - 1,
+ "Format not supported");
+ }
+
+ curr_offset += len - 1;
+ break;
+
+ case 3: /* IMEISV */
+
+ /* FALLTHRU */
+
+ case 1: /* IMSI */
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Identity Digit 1: %c",
+ a_bigbuf,
+ Dgt_msid.out[(oct & 0xf0) >> 4]);
+
+ odd = oct & 0x08;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even Indicator: %s",
+ a_bigbuf,
+ odd ? "ODD" : "EVEN");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: %s",
+ a_bigbuf,
+ ((oct & 0x07) == 3) ? "IMEISV" : "IMSI");
+
+ a_bigbuf[0] = Dgt_msid.out[(oct & 0xf0) >> 4];
+ curr_offset++;
+
+ poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+ my_dgt_tbcd_unpack(&a_bigbuf[1], poctets, len - (curr_offset - offset),
+ &Dgt_msid);
+ g_free(poctets);
+
+ proto_tree_add_string_format(tree,
+ ((oct & 0x07) == 3) ? hf_gsm_a_imeisv : hf_gsm_a_imsi,
+ tvb, curr_offset, len - (curr_offset - offset),
+ a_bigbuf,
+ "BCD Digits: %s",
+ a_bigbuf);
+
+ sprintf(add_string, " - %s (%s)",
+ ((oct & 0x07) == 3) ? "IMEISV" : "IMSI",
+ a_bigbuf);
+
+ curr_offset += len - (curr_offset - offset);
+
+ if (!odd)
+ {
+ oct = tvb_get_guint8(tvb, curr_offset - 1);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset - 1, 1,
+ "%s : Filler",
+ a_bigbuf);
+ }
+ break;
+
+ case 2: /* IMEI */
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Identity Digit 1: %c",
+ a_bigbuf,
+ Dgt_msid.out[(oct & 0xf0) >> 4]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even Indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "ODD" : "EVEN");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: IMEI",
+ a_bigbuf);
+
+ a_bigbuf[0] = Dgt_msid.out[(oct & 0xf0) >> 4];
+ curr_offset++;
+
+ poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+ my_dgt_tbcd_unpack(&a_bigbuf[1], poctets, len - (curr_offset - offset),
+ &Dgt_msid);
+ g_free(poctets);
+
+ proto_tree_add_string_format(tree,
+ hf_gsm_a_imei,
+ tvb, curr_offset, len - (curr_offset - offset),
+ a_bigbuf,
+ "BCD Digits: %s",
+ a_bigbuf);
+
+ sprintf(add_string, " - IMEI (%s)", a_bigbuf);
+
+ curr_offset += len - (curr_offset - offset);
+ break;
+
+ case 4: /* TMSI/P-TMSI */
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Unused",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even Indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "ODD" : "EVEN");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of Identity: TMSI/P-TMSI",
+ a_bigbuf);
+
+ curr_offset++;
+
+ value = tvb_get_ntohl(tvb, curr_offset);
+
+ proto_tree_add_uint(tree, hf_gsm_a_tmsi,
+ tvb, curr_offset, 4,
+ value);
+
+ sprintf(add_string, " - TMSI/P-TMSI (0x%04x)", value);
+
+ curr_offset += 4;
+ break;
+
+ default: /* Reserved */
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ "Format Unknown");
+
+ strcpy(add_string, " - Format Unknown");
+
+ curr_offset += len;
+ break;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.1.5
+ */
+static guint8
+de_ms_cm_1(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_MS_CM_1].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_MS_CM_1]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0: str = "Reserved for GSM phase 1"; break;
+ case 1: str = "Used by GSM phase 2 mobile stations"; break;
+ case 2: str = "Used by mobile stations supporting R99 or later versions of the protocol"; break;
+ default:
+ str = "Reserved for future use";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Revision Level: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : ES IND: Controlled Early Classmark Sending is %simplemented",
+ a_bigbuf,
+ (oct & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : A5/1: encryption algorithm A5/1 %savailable",
+ a_bigbuf,
+ (oct & 0x08) ? "not " : "");
+
+ switch (oct & 0x07)
+ {
+ case 0: str = "Class 1"; break;
+ case 1: str = "Class 2"; break;
+ case 2: str = "Class 3"; break;
+ case 3: str = "Class 4"; break;
+ case 4: str = "Class 5"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : RF power capability: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.1.6
+ */
+static guint8
+de_ms_cm_2(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0: str = "Reserved for GSM phase 1"; break;
+ case 1: str = "Used by GSM phase 2 mobile stations"; break;
+ case 2: str = "Used by mobile stations supporting R99 or later versions of the protocol"; break;
+ default:
+ str = "Reserved for future use";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Revision Level: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : ES IND: Controlled Early Classmark Sending is %simplemented",
+ a_bigbuf,
+ (oct & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : A5/1: encryption algorithm A5/1 %savailable",
+ a_bigbuf,
+ (oct & 0x08) ? "not " : "");
+
+ switch (oct & 0x07)
+ {
+ case 0: str = "Class 1"; break;
+ case 1: str = "Class 2"; break;
+ case 2: str = "Class 3"; break;
+ case 3: str = "Class 4"; break;
+ case 4: str = "Class 5"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : RF power capability: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : PS capability (pseudo-synchronization capability): %spresent",
+ a_bigbuf,
+ (oct & 0x40) ? "" : "not ");
+
+ switch ((oct & 0x30) >> 4)
+ {
+ case 0: str = "Default value for phase 1"; break;
+ case 1: str = "Capability of handling of ellipsis notation and phase 2 error handling"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : SS Screening Indicator: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : SM capability (MT SMS pt to pt capability): MS %s MT SMS",
+ a_bigbuf,
+ (oct & 0x08) ? "supports" : "does not support");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : VBS notification reception: %s",
+ a_bigbuf,
+ (oct & 0x04) ? "VBS capability and notifications wanted" :
+ "no VBS capability or no notifications wanted");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : VGCS notification reception: %s",
+ a_bigbuf,
+ (oct & 0x02) ? "VGCS capability and notifications wanted" :
+ "no VGCS capability or no notifications wanted");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : FC Frequency Capability",
+ a_bigbuf);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : CM3: %s",
+ a_bigbuf,
+ (oct & 0x80) ?
+ "The MS supports options that are indicated in classmark 3 IE" :
+ "The MS does not support any options that are indicated in CM3");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : LCS VA capability: LCS value added location request notification capability %ssupported",
+ a_bigbuf,
+ (oct & 0x20) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : UCS2 treatment: %s",
+ a_bigbuf,
+ (oct & 0x10) ?
+ "the ME has no preference between the use of the default alphabet and the use of UCS2" :
+ "the ME has a preference for the default alphabet (defined in 3GPP TS 03.38) over UCS2");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : SoLSA: the ME %s SoLSA",
+ a_bigbuf,
+ (oct & 0x08) ? "supports" : "does not support");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : CMSP (CM Service Prompt): %s",
+ a_bigbuf,
+ (oct & 0x04) ?
+ "'Network initiated MO CM connection request' supported for at least one CM protocol" :
+ "'Network initiated MO CM connection request' not supported");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : A5/3: encryption algorithm A5/3 %savailable",
+ a_bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : A5/2: encryption algorithm A5/2 %savailable",
+ a_bigbuf,
+ (oct & 0x01) ? "" : "not ");
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.1.9
+ */
+static guint8
+de_d_gb_call_ref(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 value;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ value = tvb_get_ntohl(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0xffffffe0, 32);
+ proto_tree_add_text(tree, tvb, curr_offset, 4,
+ "%s : Group or Broadcast call reference: %u (0x%04x)",
+ a_bigbuf,
+ (value & 0xffffffe0) >> 5,
+ (value & 0xffffffe0) >> 5);
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x00000010, 32);
+ proto_tree_add_text(tree, tvb, curr_offset, 4,
+ "%s : SF Service Flag: %s",
+ a_bigbuf,
+ (value & 0x00000010) ?
+ "VGCS (Group call reference)" : "VBS (Broadcast call reference)");
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x00000008, 32);
+ proto_tree_add_text(tree, tvb, curr_offset, 4,
+ "%s : AF Acknowledgement Flag: acknowledgment is %srequired",
+ a_bigbuf,
+ (value & 0x00000008) ? "" : "not ");
+
+ switch (value & 0x00000007)
+ {
+ case 1: str = "call priority level 4"; break;
+ case 2: str = "call priority level 3"; break;
+ case 3: str = "call priority level 2"; break;
+ case 4: str = "call priority level 1"; break;
+ case 5: str = "call priority level 0"; break;
+ case 6: str = "call priority level B"; break;
+ case 7: str = "call priority level A"; break;
+ default:
+ str = "no priority applied";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, value, 0x00000007, 32);
+ proto_tree_add_text(tree, tvb, curr_offset, 4,
+ "%s : Call Priority: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset += 4;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Ciphering Information",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree, tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.1.10a
+ */
+static guint8
+de_pd_sapi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_PD_SAPI].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_PD_SAPI]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch ((oct & 0x30) >> 4)
+ {
+ case 0: str = "SAPI 0"; break;
+ case 3: str = "SAPI 3"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : SAPI (Sevice Access Point Identifier): %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree, tvb, curr_offset, 1,
+ "%s : PD (Protocol Discriminator): %s",
+ a_bigbuf,
+ gsm_a_pd_str[oct & 0x0f]);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.1.11
+ */
+static guint8
+de_prio(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x07)
+ {
+ case 1: str = "Call priority level 4"; break;
+ case 2: str = "Call priority level 3"; break;
+ case 3: str = "Call priority level 2"; break;
+ case 4: str = "Call priority level 1"; break;
+ case 5: str = "Call priority level 0"; break;
+ case 6: str = "Call priority level B"; break;
+ case 7: str = "Call priority level A"; break;
+ default:
+ str = "No priority applied";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.1.13
+ */
+static guint8
+de_plmn_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 octs[3];
+ guint32 curr_offset;
+ gchar mcc[4];
+ gchar mnc[4];
+ guint8 num_plmn;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ num_plmn = 0;
+ while ((len - (curr_offset - offset)) >= 3)
+ {
+ octs[0] = tvb_get_guint8(tvb, curr_offset);
+ octs[1] = tvb_get_guint8(tvb, curr_offset + 1);
+ octs[2] = tvb_get_guint8(tvb, curr_offset + 2);
+
+ mcc_mnc_aux(octs, mcc, mnc);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 3,
+ "PLMN[%u] Mobile Country Code (MCC): %s, Mobile Network Code (MNC): %s",
+ num_plmn + 1,
+ mcc,
+ mnc);
+
+ curr_offset += 3;
+
+ num_plmn++;
+ }
+
+ sprintf(add_string, " - %u PLMN%s",
+ num_plmn, plurality(num_plmn, "", "s"));
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.2.31
+ */
+static guint8
+de_rr_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0x00: str = "Normal event"; break;
+ case 0x01: str = "Abnormal release, unspecified"; break;
+ case 0x02: str = "Abnormal release, channel unacceptable"; break;
+ case 0x03: str = "Abnormal release, timer expired"; break;
+ case 0x04: str = "Abnormal release, no activity on the radio path"; break;
+ case 0x05: str = "Preemptive release"; break;
+ case 0x08: str = "Handover impossible, timing advance out of range"; break;
+ case 0x09: str = "Channel mode unacceptable"; break;
+ case 0x0a: str = "Frequency not implemented"; break;
+ case 0x41: str = "Call already cleared"; break;
+ case 0x5f: str = "Semantically incorrect message"; break;
+ case 0x60: str = "Invalid mandatory information"; break;
+ case 0x61: str = "Message type non-existent or not implemented"; break;
+ case 0x62: str = "Message type not compatible with protocol state"; break;
+ case 0x64: str = "Conditional IE error"; break;
+ case 0x65: str = "No cell allocation available"; break;
+ case 0x6f: str = "Protocol error unspecified"; break;
+ default:
+ str = "Reserved, treat as Normal event";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "RR Cause value: 0x%02x (%u) %s",
+ oct,
+ oct,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.1
+ */
+static guint8
+de_auth_param_rand(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+/*
+ * 12 octets == 128 bits
+ */
+#define AUTH_PARAM_RAND_LEN 12
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, AUTH_PARAM_RAND_LEN,
+ "RAND value");
+
+ curr_offset += AUTH_PARAM_RAND_LEN;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.1.1
+ */
+static guint8
+de_auth_param_autn(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len,
+ "AUTN value");
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.2
+ */
+static guint8
+de_auth_resp_param(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+/*
+ * 4 octets == 32 bits
+ */
+#define AUTH_PARAM_RESP_LEN 4
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, AUTH_PARAM_RESP_LEN,
+ "SRES value");
+
+ curr_offset += AUTH_PARAM_RESP_LEN;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.2.1
+ */
+static guint8
+de_auth_resp_param_ext(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len,
+ "RES (extension) value");
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.2.2
+ */
+static guint8
+de_auth_fail_param(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len,
+ "AUTS value");
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.5a
+ */
+static guint8
+de_network_name(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0x00: str = "Cell Broadcast data coding scheme, GSM default alphabet, language unspecified, defined in 3GPP TS 03.38"; break;
+ case 0x01: str = "UCS2 (16 bit)"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Coding Scheme: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Add CI: The MS should %s",
+ a_bigbuf,
+ (oct & 0x08) ?
+ "add the letters for the Country's Initials and a separator (e.g. a space) to the text string" :
+ "The MS should not add the letters for the Country's Initials to the text string");
+
+ switch (oct & 0x07)
+ {
+ case 1: str = "bit 8 is spare and set to '0' in octet n"; break;
+ case 2: str = "bits 7 and 8 are spare and set to '0' in octet n"; break;
+ case 3: str = "bits 6 to 8(inclusive) are spare and set to '0' in octet n"; break;
+ case 4: str = "bits 5 to 8(inclusive) are spare and set to '0' in octet n"; break;
+ case 5: str = "bits 4 to 8(inclusive) are spare and set to '0' in octet n"; break;
+ case 6: str = "bits 3 to 8(inclusive) are spare and set to '0' in octet n"; break;
+ case 7: str = "bits 2 to 8(inclusive) are spare and set to '0' in octet n"; break;
+ default:
+ str = "this field carries no information about the number of spare bits in octet n";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Number of spare bits in last octet: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - 1,
+ "Text string encoded according to Coding Scheme");
+
+ curr_offset += len - 1;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.6
+ */
+static guint8
+de_rej_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0x02: str = "IMSI unknown in HLR"; break;
+ case 0x03: str = "Illegal MS"; break;
+ case 0x04: str = "IMSI unknown in VLR"; break;
+ case 0x05: str = "IMEI not accepted"; break;
+ case 0x06: str = "Illegal ME"; break;
+ case 0x0b: str = "PLMN not allowed"; break;
+ case 0x0c: str = "Location Area not allowed"; break;
+ case 0x0d: str = "Roaming not allowed in this location area"; break;
+ case 0x0f: str = "No Suitable Cells In Location Area"; break;
+ case 0x11: str = "Network failure"; break;
+ case 0x14: str = "MAC failure"; break;
+ case 0x15: str = "Synch failure"; break;
+ case 0x16: str = "Congestion"; break;
+ case 0x17: str = "GSM authentication unacceptable"; break;
+ case 0x20: str = "Service option not supported"; break;
+ case 0x21: str = "Requested service option not subscribed"; break;
+ case 0x22: str = "Service option temporarily out of order"; break;
+ case 0x26: str = "Call cannot be identified"; break;
+ case 0x5f: str = "Semantically incorrect message"; break;
+ case 0x60: str = "Invalid mandatory information"; break;
+ case 0x61: str = "Message type non-existent or not implemented"; break;
+ case 0x62: str = "Message type not compatible with the protocol state"; break;
+ case 0x63: str = "Information element non-existent or not implemented"; break;
+ case 0x64: str = "Conditional IE error"; break;
+ case 0x65: str = "Message not compatible with the protocol state"; break;
+ case 0x6f: str = "Protocol error, unspecified"; break;
+ default:
+ switch (is_uplink)
+ {
+ case IS_UPLINK_FALSE:
+ str = "Service option temporarily out of order";
+ break;
+ default:
+ str = "Protocol error, unspecified";
+ break;
+ }
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Reject Cause value: 0x%02x (%u) %s",
+ oct,
+ oct,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.8
+ */
+static guint8
+de_time_zone(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Time Zone: 0x%02x (%u)",
+ oct,
+ oct);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.9
+ */
+static guint8
+de_time_zone_time(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct, oct2, oct3;
+ guint32 curr_offset;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+ oct2 = tvb_get_guint8(tvb, curr_offset+1);
+ oct3 = tvb_get_guint8(tvb, curr_offset+2);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 3,
+ "Year %u%u, Month %u%u, Day %u%u",
+ oct & 0x0f,
+ (oct & 0xf0) >> 4,
+ oct2 & 0x0f,
+ (oct2 & 0xf0) >> 4,
+ oct3 & 0x0f,
+ (oct3 & 0xf0) >> 4);
+
+ curr_offset += 3;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+ oct2 = tvb_get_guint8(tvb, curr_offset+1);
+ oct3 = tvb_get_guint8(tvb, curr_offset+2);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 3,
+ "Hour %u%u, Minutes %u%u, Seconds %u%u",
+ oct & 0x0f,
+ (oct & 0xf0) >> 4,
+ oct2 & 0x0f,
+ (oct2 & 0xf0) >> 4,
+ oct3 & 0x0f,
+ (oct3 & 0xf0) >> 4);
+
+ curr_offset += 3;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Time Zone: 0x%02x (%u)",
+ oct,
+ oct);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.11
+ */
+static guint8
+de_lsa_id(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len,
+ "LSA ID");
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.3.12
+ */
+static guint8
+de_day_saving_time(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xfc, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x03)
+ {
+ case 0: str = "No adjustment for Daylight Saving Time"; break;
+ case 1: str = "+1 hour adjustment for Daylight Saving Time"; break;
+ case 2: str = "+2 hours adjustment for Daylight Saving Time"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.4
+ */
+static guint8
+de_aux_states(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch ((oct & 0x0c) >> 2)
+ {
+ case 0: str = "Idle"; break;
+ case 1: str = "Hold request"; break;
+ case 2: str = "Call held"; break;
+ default:
+ str = "Retrieve request";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0c, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Hold auxiliary state: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x03)
+ {
+ case 0: str = "Idle"; break;
+ case 1: str = "MPTY request"; break;
+ case 2: str = "Call in MPTY"; break;
+ default:
+ str = "Split request";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Multi party auxiliary state: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.5
+ */
+static guint8
+de_bearer_cap(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 itc;
+ gboolean extended;
+ guint32 curr_offset;
+ guint32 saved_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+
+#define DE_BC_ITC_SPEECH 0x00
+#define DE_BC_ITC_UDI 0x01
+#define DE_BC_ITC_EX_PLMN 0x02
+#define DE_BC_ITC_FASC_G3 0x03
+#define DE_BC_ITC_OTHER_ITC 0x05
+#define DE_BC_ITC_RSVD_NET 0x07
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ /* octet 3 */
+
+ /*
+ * warning, bearer cap uses extended values that
+ * are reversed from other parameters!
+ */
+ extended = (oct & 0x80) ? FALSE : TRUE;
+ itc = oct & 0x07;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ switch (is_uplink)
+ {
+ case IS_UPLINK_FALSE:
+ str = "Spare";
+ break;
+
+ case IS_UPLINK_TRUE:
+ /*
+ * depends on Information transfer capability
+ */
+ switch (itc)
+ {
+ case DE_BC_ITC_SPEECH:
+ if (extended)
+ {
+ switch ((oct & 0x60) >> 5)
+ {
+ case 1: str = "MS supports at least full rate speech version 1 but does not support half rate speech version 1"; break;
+ case 2: str = "MS supports at least full rate speech version 1 and half rate speech version 1. MS has a greater preference for half rate speech version 1 than for full rate speech version 1"; break;
+ case 3: str = "MS supports at least full rate speech version 1 and half rate speech version 1. MS has a greater preference for full rate speech version 1 than for half rate speech version 1"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+ break;
+ }
+ else
+ {
+ switch ((oct & 0x60) >> 5)
+ {
+ case 1: str = "Full rate support only MS/fullrate speech version 1 supported"; break;
+ case 2: str = "Dual rate support MS/half rate speech version 1 preferred, full rate speech version 1 also supported"; break;
+ case 3: str = "Dual rate support MS/full rate speech version 1 preferred, half rate speech version 1 also supported"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+ break;
+ }
+ break;
+
+ default:
+ switch ((oct & 0x60) >> 5)
+ {
+ case 1: str = "Full rate support only MS"; break;
+ case 2: str = "Dual rate support MS/half rate preferred"; break;
+ case 3: str = "Dual rate support MS/full rate preferred"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+ break;
+ }
+ break;
+
+ default:
+ str = "(dissect problem)";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Radio channel requirement: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Coding standard: %s",
+ a_bigbuf,
+ (oct & 0x10) ? "reserved" : "GSM standardized coding");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Transfer mode: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "packet" : "circuit");
+
+ switch (itc)
+ {
+ case DE_BC_ITC_SPEECH: str = "Speech"; break;
+ case DE_BC_ITC_UDI: str = "Unrestricted digital information"; break;
+ case DE_BC_ITC_EX_PLMN: str = "3.1 kHz audio, ex PLMN"; break;
+ case DE_BC_ITC_FASC_G3: str = "Facsimile group 3"; break;
+ case DE_BC_ITC_OTHER_ITC: str = "Other ITC (See Octet 5a)"; break;
+ case DE_BC_ITC_RSVD_NET: str = "Reserved, to be used in the network"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Information transfer capability: %s",
+ a_bigbuf,
+ str);
+
+ sprintf(add_string, " - (%s)", str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ switch (itc)
+ {
+ case DE_BC_ITC_SPEECH:
+ /* octets 3a */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, -1,
+ "Octets 3a - Speech Versions");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_3a);
+
+ saved_offset = curr_offset;
+
+ do
+ {
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Coding: octet used for %s",
+ a_bigbuf,
+ (oct & 0x40) ? "other extension of octet 3" :
+ "extension of information transfer capability");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x0f)
+ {
+ case 0: str = "GSM full rate speech version 1"; break;
+ case 2: str = "GSM full rate speech version 2"; break;
+ case 4: str = "GSM full rate speech version 3"; break;
+ case 1: str = "GSM half rate speech version 1"; break;
+ case 5: str = "GSM half rate speech version 3"; break;
+ default:
+ str = "Speech version TBD";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Speech version indication: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+ }
+ while (extended &&
+ ((len - (curr_offset - offset)) > 0));
+
+ proto_item_set_len(item, curr_offset - saved_offset);
+ break;
+
+ default:
+ /* octet 4 */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 4");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_4);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Compression: data compression %s%s",
+ a_bigbuf,
+ (oct & 0x40) ? "" : "not ",
+ is_uplink ? "allowed" : "possible");
+
+ switch ((oct & 0x30) >> 4)
+ {
+ case 0x00: str = "Service data unit integrity"; break;
+ case 0x03: str = "Unstructured"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x30, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Structure: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Duplex mode: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "Full" : "Half");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Configuration: %s",
+ a_bigbuf,
+ (oct & 0x04) ? "Reserved" : "Point-to-point");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : NIRR: %s",
+ a_bigbuf,
+ (oct & 0x02) ?
+ "Data up to and including 4.8 kb/s, full rate, non-transparent, 6 kb/s radio interface rate is requested" :
+ "No meaning is associated with this value");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Establishment: %s",
+ a_bigbuf,
+ (oct & 0x01) ? "Reserved" : "Demand");
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ /* octet 5 */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 5");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_5);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Access Identity: %s",
+ a_bigbuf,
+ (oct & 0x60) ? "Reserved" : "Octet identifier");
+
+ switch ((oct & 0x18) >> 3)
+ {
+ case 0x00: str = "No rate adaption"; break;
+ case 0x01: str = "V.110, I.460/X.30 rate adaptation"; break;
+ case 0x02: str = "ITU-T X.31 flag stuffing"; break;
+ default:
+ str = "Other rate adaption (see octet 5a)"; break;
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Rate Adaption: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x07)
+ {
+ case 0x01: str = "I.440/450"; break;
+ case 0x02: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ case 0x03: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ case 0x04: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ case 0x05: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ case 0x06: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ default:
+ str = "Reserved"; break;
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Signalling Access Protocol: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (!extended) goto bc_octet_6;
+
+ /* octet 5a */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 5a");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_5a);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Other ITC: %s",
+ a_bigbuf,
+ (oct & 0x60) ? "Reserved" : "Restricted digital information");
+
+ switch ((oct & 0x18) >> 3)
+ {
+ case 0x00: str = "V.120"; break;
+ case 0x01: str = "H.223 & H.245"; break;
+ case 0x02: str = "PIAFS"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x18, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Other Rate Adaption: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (!extended) goto bc_octet_6;
+
+ /* octet 5b */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 5b");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_5b);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Rate Adaption Header: %sincluded",
+ a_bigbuf,
+ (oct & 0x40) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Multiple frame establishment support in data link: %s",
+ a_bigbuf,
+ (oct & 0x20) ? "Supported" : "Not supported, only UI frames allowed");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Mode of operation: %s",
+ a_bigbuf,
+ (oct & 0x10) ? "Protocol sensitive" : "Bit transparent");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Logical link identifier negotiation: %s",
+ a_bigbuf,
+ (oct & 0x08) ? "Full protocol negotiation" : "Default, LLI=256 only");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Assignor/Assignee: Message originator is '%s'",
+ a_bigbuf,
+ (oct & 0x04) ? "assignor only" : "default assignee");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : In band/Out of band negotiation: Negotiation is done %s",
+ a_bigbuf,
+ (oct & 0x02) ?
+ "with USER INFORMATION messages on a temporary signalling connection" :
+ "in-band using logical link zero");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+bc_octet_6:
+
+ /* octet 6 */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 6");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_6);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Layer 1 Identity: %s",
+ a_bigbuf,
+ ((oct & 0x60) == 0x20) ? "Octet identifier" : "Reserved");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1e, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : User information layer 1 protocol: %s",
+ a_bigbuf,
+ (oct & 0x1e) ? "Reserved" : "Default layer 1 protocol");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Synchronous/asynchronous: %s",
+ a_bigbuf,
+ (oct & 0x01) ? "Asynchronous" : "Synchronous");
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (!extended) goto bc_octet_7;
+
+ /* octet 6a */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 6a");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_6a);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Number of Stop Bits: %s",
+ a_bigbuf,
+ (oct & 0x40) ? "2" : "1");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Negotiation: %s",
+ a_bigbuf,
+ (oct & 0x20) ? "Reserved" : "In-band negotiation not possible");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Number of data bits excluding parity bit if present: %s",
+ a_bigbuf,
+ (oct & 0x10) ? "8" : "7");
+
+ switch (oct & 0x0f)
+ {
+ case 0x01: str = "0.3 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x02: str = "1.2 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x03: str = "2.4 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x04: str = "4.8 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x05: str = "9.6 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x06: str = "12.0 kbit/s transparent (non compliance with X.1 and V.110)"; break;
+ case 0x07: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : User rate: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (!extended) goto bc_octet_7;
+
+ /* octet 6b */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 6b");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_6b);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0x02: str = "8 kbit/s"; break;
+ case 0x03: str = "16 kbit/s"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : V.110/X.30 rate adaptation Intermediate rate: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Network independent clock (NIC) on transmission (Tx): %s to send data with network independent clock",
+ a_bigbuf,
+ (oct & 0x10) ? "requires" : "does not require");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Network independent clock (NIC) on reception (Rx): %s accept data with network independent clock",
+ a_bigbuf,
+ (oct & 0x08) ? "can" : "cannot");
+
+ switch (oct & 0x07)
+ {
+ case 0x00: str = "Odd"; break;
+ case 0x02: str = "Even"; break;
+ case 0x03: str = "None"; break;
+ case 0x04: str = "Forced to 0"; break;
+ case 0x05: str = "Forced to 1"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Parity information: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (!extended) goto bc_octet_7;
+
+ /* octet 6c */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 6c");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_6c);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0x01: str = "Non transparent (RLP)"; break;
+ case 0x02: str = "Both, transparent preferred"; break;
+ case 0x03: str = "Both, non transparent preferred"; break;
+ default:
+ str = "Transparent";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Connection element: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x1f)
+ {
+ case 0x00: str = "None"; break;
+ case 0x01: str = "V.21"; break;
+ case 0x02: str = "V.22"; break;
+ case 0x03: str = "V.22 bis"; break;
+ case 0x04: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ case 0x05: str = "V.26 ter"; break;
+ case 0x06: str = "V.32"; break;
+ case 0x07: str = "Modem for undefined interface"; break;
+ case 0x08: str = "Autobauding type 1"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Modem type: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (!extended) goto bc_octet_7;
+
+ /* octet 6d */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 6d");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_6d);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0x00: str = "No other modem type specified in this field"; break;
+ case 0x02: str = "V.34"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Other modem type: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x1f)
+ {
+ case 0x00: str = "Fixed network user rate not applicable/No meaning is associated with this value"; break;
+ case 0x01: str = "9.6 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x02: str = "14.4 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x03: str = "19.2 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x04: str = "28.8 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x05: str = "38.4 kbit/s Recommendation X.1 and V.110"; break;
+ case 0x06: str = "48.0 kbit/s Recommendation X.1 and V.110(synch)"; break;
+ case 0x07: str = "56.0 kbit/s Recommendation X.1 and V.110(synch) /bit transparent"; break;
+ case 0x08: str = "64.0 kbit/s bit transparent"; break;
+ case 0x09: str = "33.6 kbit/s bit transparent"; break;
+ case 0x0a: str = "32.0 kbit/s Recommendation I.460"; break;
+ case 0x0b: str = "31.2 kbit/s Recommendation V.34"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Fixed network user rate: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (!extended) goto bc_octet_7;
+
+ /* octet 6e */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 6e");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_6e);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ if (is_uplink == IS_UPLINK_TRUE)
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Acceptable channel codings: TCH/F14.4 %sacceptable",
+ a_bigbuf,
+ (oct & 0x40) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Acceptable channel codings: Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Acceptable channel codings: TCH/F9.6 %sacceptable",
+ a_bigbuf,
+ (oct & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Acceptable channel codings: TCH/F4.8 %sacceptable",
+ a_bigbuf,
+ (oct & 0x08) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Maximum number of traffic channels: %u TCH",
+ a_bigbuf,
+ (oct & 0x07) + 1);
+ }
+ else
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x78, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Acceptable channel codings: Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Maximum number of traffic channels: Spare",
+ a_bigbuf);
+ }
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (!extended) goto bc_octet_7;
+
+ /* octet 6f */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 6f");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_6f);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0x00: str = "not allowed/required/applicable"; break;
+ case 0x01: str = "up to 1 TCH/F allowed/may be requested"; break;
+ case 0x02: str = "up to 2 TCH/F allowed/may be requested"; break;
+ case 0x03: str = "up to 3 TCH/F allowed/may be requested"; break;
+ case 0x04: str = "up to 4 TCH/F allowed/may be requested"; break;
+ default:
+ str = "up to 4 TCH/F may be requested";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : UIMI, User initiated modification indication: %s",
+ a_bigbuf,
+ str);
+
+ if (is_uplink == IS_UPLINK_TRUE)
+ {
+ switch (oct & 0x0f)
+ {
+ case 0x00: str = "Air interface user rate not applicable/No meaning associated with this value"; break;
+ case 0x01: str = "9.6 kbit/s"; break;
+ case 0x02: str = "14.4 kbit/s"; break;
+ case 0x03: str = "19.2 kbit/s"; break;
+ case 0x05: str = "28.8 kbit/s"; break;
+ case 0x06: str = "38.4 kbit/s"; break;
+ case 0x07: str = "43.2 kbit/s"; break;
+ case 0x08: str = "57.6 kbit/s"; break;
+ case 0x09: str = "interpreted by the network as 38.4 kbit/s in this version of the protocol"; break;
+ case 0x0a: str = "interpreted by the network as 38.4 kbit/s in this version of the protocol"; break;
+ case 0x0b: str = "interpreted by the network as 38.4 kbit/s in this version of the protocol"; break;
+ case 0x0c: str = "interpreted by the network as 38.4 kbit/s in this version of the protocol"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Wanted air interface user rate: %s",
+ a_bigbuf,
+ str);
+ }
+ else
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Wanted air interface user rate: Spare",
+ a_bigbuf);
+ }
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ if (!extended) goto bc_octet_7;
+
+ /* octet 6g */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 6g");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_6g);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ if (is_uplink == IS_UPLINK_TRUE)
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Acceptable channel codings extended: TCH/F28.8 %sacceptable",
+ a_bigbuf,
+ (oct & 0x40) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Acceptable channel codings extended: TCH/F32.0 %sacceptable",
+ a_bigbuf,
+ (oct & 0x20) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Acceptable channel codings extended: TCH/F43.2 %sacceptable",
+ a_bigbuf,
+ (oct & 0x10) ? "" : "not ");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Acceptable channel codings extended: TCH/F43.2 %sacceptable",
+ a_bigbuf,
+ (oct & 0x10) ? "" : "not ");
+
+ switch ((oct & 0x0c) >> 2)
+ {
+ case 0: str = "Channel coding symmetry preferred"; break;
+ case 2: str = "Downlink biased channel coding asymmetry is preferred"; break;
+ case 1: str = "Uplink biased channel coding asymmetry is preferred"; break;
+ default:
+ str = "Unused, treat as Channel coding symmetry preferred";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0c, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Channel Coding Asymmetry Indication: %s",
+ a_bigbuf,
+ str);
+ }
+ else
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7c, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : EDGE Channel Codings: Spare",
+ a_bigbuf);
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+bc_octet_7:
+
+ /* octet 7 */
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Octet 7");
+
+ subtree = proto_item_add_subtree(item, ett_bc_oct_7);
+
+ extended = (oct & 0x80) ? FALSE : TRUE;
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ extended ? "extended" : "not extended");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Layer 2 Identity: %s",
+ a_bigbuf,
+ ((oct & 0x60) == 0x40) ? "Octet identifier" : "Reserved");
+
+ switch (oct & 0x1f)
+ {
+ case 0x06: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ case 0x08: str = "ISO 6429, codeset 0 (DC1/DC3)"; break;
+ case 0x09: str = "Reserved: was allocated but never used in earlier phases of the protocol"; break;
+ case 0x0a: str = "Videotex profile 1"; break;
+ case 0x0c: str = "COPnoFlCt (Character oriented Protocol with no Flow Control mechanism)"; break;
+ case 0x0d: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : User information layer 2 protocol: %s",
+ a_bigbuf,
+ str);
+ break;
+ }
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.5a
+ */
+static guint8
+de_cc_cap(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+
+ switch ((oct & 0xf0) >> 4)
+ {
+ case 0:
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Maximum number of supported bearers: 1",
+ a_bigbuf);
+ break;
+
+ default:
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Maximum number of supported bearers: %u",
+ a_bigbuf,
+ (oct & 0xf0) >> 4);
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0c, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : PCP: the mobile station %s the Prolonged Clearing Procedure",
+ a_bigbuf,
+ (oct & 0x02) ? "supports" : "does not support");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : DTMF: %s",
+ a_bigbuf,
+ (oct & 0x01) ?
+ "the mobile station supports DTMF as specified in subclause 5.5.7 of TS 24.008" :
+ "reserved for earlier versions of the protocol");
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Maximum number of speech bearers: %u",
+ a_bigbuf,
+ oct & 0x0f);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.6
+ */
+static guint8
+de_call_state(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_CALL_STATE].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CALL_STATE]);
+
+ switch ((oct & 0xc0) >> 6)
+ {
+ case 0: str = "Coding as specified in ITU-T Rec. Q.931"; break;
+ case 1: str = "Reserved for other international standards"; break;
+ case 2: str = "National standard"; break;
+ default:
+ str = "Standard defined for the GSM PLMNS";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Coding standard: %s",
+ a_bigbuf,
+ str);
+
+ switch (oct & 0x3f)
+ {
+ case 0x00: str = "UO - null NO - null"; break;
+ case 0x02: str = "U0.1- MM connection pending N0.1- MM connection pending"; break;
+ case 0x22: str = "U0.2- CC prompt present N0.2- CC connection pending"; break;
+ case 0x23: str = "U0.3- Wait for network information N0.3- Network answer pending"; break;
+ case 0x24: str = "U0.4- CC-Establishment present N0.4- CC-Establishment present"; break;
+ case 0x25: str = "U0.5- CC-Establishment confirmed N0.5- CC-Establishment confirmed"; break;
+ case 0x26: str = "U0.6- Recall present N0.6- Recall present"; break;
+ case 0x01: str = "U1 - call initiated N1 - call initiated"; break;
+ case 0x03: str = "U3 - mobile originating call proceeding N3 - mobile originating call proceeding"; break;
+ case 0x04: str = "U4 - call delivered N4 - call delivered"; break;
+ case 0x06: str = "U6 - call present N6 - call present"; break;
+ case 0x07: str = "U7 - call received N7 - call received"; break;
+ case 0x08: str = "U8 - connect request N8 - connect request"; break;
+ case 0x09: str = "U9 - mobile terminating call confirmed N9 - mobile terminating call confirmed"; break;
+ case 0x0a: str = "U10- active N10- active"; break;
+ case 0x0b: str = "U11- disconnect request"; break;
+ case 0x0c: str = "U12- disconnect indication N12-disconnect indication"; break;
+ case 0x13: str = "U19- release request N19- release request"; break;
+ case 0x1a: str = "U26- mobile originating modify N26- mobile originating modify"; break;
+ case 0x1b: str = "U27- mobile terminating modify N27- mobile terminating modify"; break;
+ case 0x1c: str = " N28- connect indication"; break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Call state value: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.7
+ */
+static guint8
+de_cld_party_bcd_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 ton;
+ guint8 *poctets;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ ton = (oct & 0x70) >> 4;
+ switch (ton)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "International number"; break;
+ case 2: str = "National number"; break;
+ case 3: str = "Network specific number"; break;
+ case 4: str = "Dedicated access, short code"; break;
+ case 7: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of number: %s",
+ a_bigbuf,
+ str);
+
+ if ((ton == 0) ||
+ (ton == 1) ||
+ (ton == 2) ||
+ (ton == 4))
+ {
+ switch (oct & 0x0f)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "ISDN/telephony numbering plan (Rec. E.164/E.163)"; break;
+ case 3: str = "Data numbering plan (Recommendation X.121)"; break;
+ case 4: str = "Telex numbering plan (Recommendation F.69)"; break;
+ case 8: str = "National numbering plan"; break;
+ case 9: str = "Private numbering plan"; break;
+ case 11: str = "Reserved for CTS (see 3GPP TS 44.056)"; break;
+ case 15: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+ }
+ else
+ {
+ str = "not applicable";
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Numbering plan identification: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+ my_dgt_tbcd_unpack(a_bigbuf, poctets, len - (curr_offset - offset),
+ &Dgt_mbcd);
+ g_free(poctets);
+
+ proto_tree_add_string_format(tree, hf_gsm_a_cld_party_bcd_num,
+ tvb, curr_offset, len - (curr_offset - offset),
+ a_bigbuf,
+ "BCD Digits: %s",
+ a_bigbuf);
+
+ curr_offset += len - (curr_offset - offset);
+
+ sprintf(add_string, " - (%s)", a_bigbuf);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.8
+ */
+static guint8
+de_cld_party_sub_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "NSAP (X.213/ISO 8348 AD2)"; break;
+ case 2: str = "User specified"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of subaddress: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ?
+ "odd number of address signals" : "even number of address signals");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Subaddress information");
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.9
+ */
+static guint8
+de_clg_party_bcd_num(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 ton;
+ guint8 *poctets;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ ton = (oct & 0x70) >> 4;
+ switch (ton)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "International number"; break;
+ case 2: str = "National number"; break;
+ case 3: str = "Network specific number"; break;
+ case 4: str = "Dedicated access, short code"; break;
+ case 7: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of number: %s",
+ a_bigbuf,
+ str);
+
+ if ((ton == 0) ||
+ (ton == 1) ||
+ (ton == 2) ||
+ (ton == 4))
+ {
+ switch (oct & 0x0f)
+ {
+ case 0: str = "Unknown"; break;
+ case 1: str = "ISDN/telephony numbering plan (Rec. E.164/E.163)"; break;
+ case 3: str = "Data numbering plan (Recommendation X.121)"; break;
+ case 4: str = "Telex numbering plan (Recommendation F.69)"; break;
+ case 8: str = "National numbering plan"; break;
+ case 9: str = "Private numbering plan"; break;
+ case 11: str = "Reserved for CTS (see 3GPP TS 44.056)"; break;
+ case 15: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+ }
+ else
+ {
+ str = "not applicable";
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Numbering plan identification: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0: str = "Presentation allowed"; break;
+ case 1: str = "Presentation restricted"; break;
+ case 2: str = "Number not available due to interworking"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Presentation indicator: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x1c, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x03)
+ {
+ case 0: str = "User-provided, not screened"; break;
+ case 1: str = "User-provided, verified and passed"; break;
+ case 2: str = "User-provided, verified and failed"; break;
+ default:
+ str = "Network provided";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Screening indicator: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ poctets = tvb_get_string(tvb, curr_offset, len - (curr_offset - offset));
+
+ my_dgt_tbcd_unpack(a_bigbuf, poctets, len - (curr_offset - offset),
+ &Dgt_mbcd);
+ g_free(poctets);
+
+ proto_tree_add_string_format(tree, hf_gsm_a_clg_party_bcd_num,
+ tvb, curr_offset, len - (curr_offset - offset),
+ a_bigbuf,
+ "BCD Digits: %s",
+ a_bigbuf);
+
+ curr_offset += len - (curr_offset - offset);
+
+ sprintf(add_string, " - (%s)", a_bigbuf);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.10
+ */
+static guint8
+de_clg_party_sub_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0: str = "NSAP (X.213/ISO 8348 AD2)"; break;
+ case 2: str = "User specified"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Type of subaddress: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Odd/Even indicator: %s",
+ a_bigbuf,
+ (oct & 0x08) ?
+ "odd number of address signals" : "even number of address signals");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ curr_offset++;
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Subaddress information");
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.11
+ */
+static guint8
+de_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint8 cause;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "not extended" : "extended");
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0: str = "Coding as specified in ITU-T Rec. Q.931"; break;
+ case 1: str = "Reserved for other international standards"; break;
+ case 2: str = "National standard"; break;
+ default:
+ str = "Standard defined for the GSM PLMNS";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Coding standard: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x0f)
+ {
+ case 0: str = "User"; break;
+ case 1: str = "Private network serving the local user"; break;
+ case 2: str = "Public network serving the local user"; break;
+ case 3: str = "Transit network"; break;
+ case 4: str = "Public network serving the remote user"; break;
+ case 5: str = "Private network serving the remote user"; break;
+ case 7: str = "International network"; break;
+ case 10: str = "Network beyond interworking point"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Location: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (!(oct & 0x80))
+ {
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Recommendation",
+ a_bigbuf);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ cause = oct & 0x7f;
+ switch (cause)
+ {
+ case 1: str = "Unassigned (unallocated) number"; break;
+ case 3: str = "No route to destination"; break;
+ case 6: str = "Channel unacceptable"; break;
+ case 8: str = "Operator determined barring"; break;
+ case 16: str = "Normal call clearing"; break;
+ case 17: str = "User busy"; break;
+ case 18: str = "No user responding"; break;
+ case 19: str = "User alerting, no answer"; break;
+ case 21: str = "Call rejected"; break;
+ case 22: str = "Number changed"; break;
+ case 25: str = "Pre-emption"; break;
+ case 26: str = "Non selected user clearing"; break;
+ case 27: str = "Destination out of order"; break;
+ case 28: str = "Invalid number format (incomplete number)"; break;
+ case 29: str = "Facility rejected"; break;
+ case 30: str = "Response to STATUS ENQUIRY"; break;
+ case 31: str = "Normal, unspecified"; break;
+ case 34: str = "No circuit/channel available"; break;
+ case 38: str = "Network out of order"; break;
+ case 41: str = "Temporary failure"; break;
+ case 42: str = "Switching equipment congestion"; break;
+ case 43: str = "Access information discarded"; break;
+ case 44: str = "requested circuit/channel not available"; break;
+ case 47: str = "Resources unavailable, unspecified"; break;
+ case 49: str = "Quality of service unavailable"; break;
+ case 50: str = "Requested facility not subscribed"; break;
+ case 55: str = "Incoming calls barred within the CUG"; break;
+ case 57: str = "Bearer capability not authorized"; break;
+ case 58: str = "Bearer capability not presently available"; break;
+ case 63: str = "Service or option not available, unspecified"; break;
+ case 65: str = "Bearer service not implemented"; break;
+ case 68: str = "ACM equal to or greater than ACMmax"; break;
+ case 69: str = "Requested facility not implemented"; break;
+ case 70: str = "Only restricted digital information bearer capability is available"; break;
+ case 79: str = "Service or option not implemented, unspecified"; break;
+ case 81: str = "Invalid transaction identifier value"; break;
+ case 87: str = "User not member of CUG"; break;
+ case 88: str = "Incompatible destination"; break;
+ case 91: str = "Invalid transit network selection"; break;
+ case 95: str = "Semantically incorrect message"; break;
+ case 96: str = "Invalid mandatory information"; break;
+ case 97: str = "Message type non-existent or not implemented"; break;
+ case 98: str = "Message type not compatible with protocol state"; break;
+ case 99: str = "Information element non-existent or not implemented"; break;
+ case 100: str = "Conditional IE error"; break;
+ case 101: str = "Message not compatible with protocol state"; break;
+ case 102: str = "Recovery on timer expiry"; break;
+ case 111: str = "Protocol error, unspecified"; break;
+ case 127: str = "Interworking, unspecified"; break;
+ default:
+ if (cause <= 31) { str = "Treat as Normal, unspecified"; }
+ else if ((cause >= 32) && (cause <= 47)) { str = "Treat as Resources unavailable, unspecified"; }
+ else if ((cause >= 48) && (cause <= 63)) { str = "Treat as Service or option not available, unspecified"; }
+ else if ((cause >= 64) && (cause <= 79)) { str = "Treat as Service or option not implemented, unspecified"; }
+ else if ((cause >= 80) && (cause <= 95)) { str = "Treat as Semantically incorrect message"; }
+ else if ((cause >= 96) && (cause <= 111)) { str = "Treat as Protocol error, unspecified"; }
+ else if ((cause >= 112) && (cause <= 127)) { str = "Treat as Interworking, unspecified"; }
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_uint_format(tree, hf_gsm_a_dtap_cause,
+ tvb, curr_offset, 1, cause,
+ "%s : Cause: (%u) %s",
+ a_bigbuf,
+ cause,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%u) %s", cause, str);
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Diagnostics");
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+
+#define GSM_A_TC_START_SUBTREE(_Gtree, _Gsaved_offset, _Gtag, _Gstr1, _Gett, _Gdef_len_p, _Glen_p, _Gsubtree_p) \
+ { \
+ guint _len_offset; \
+ proto_item *_item; \
+ \
+ _len_offset = asn1->offset; \
+ asn1_length_decode(asn1, _Gdef_len_p, _Glen_p); \
+ \
+ _item = \
+ proto_tree_add_text(_Gtree, asn1->tvb, _Gsaved_offset, -1, _Gstr1); \
+ \
+ _Gsubtree_p = proto_item_add_subtree(_item, _Gett); \
+ \
+ proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
+ _Gsaved_offset, _len_offset - _Gsaved_offset, "Tag: 0x%02x", _Gtag); \
+ \
+ if (*_Gdef_len_p) \
+ { \
+ proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
+ _len_offset, asn1->offset - _len_offset, "Length: %d", *_Glen_p); \
+ } \
+ else \
+ { \
+ proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
+ _len_offset, asn1->offset - _len_offset, "Length: Indefinite"); \
+ \
+ *_Glen_p = tcap_find_eoc(asn1); \
+ } \
+ \
+ proto_item_set_len(_item, (asn1->offset - _Gsaved_offset) + *_Glen_p + \
+ (*_Gdef_len_p ? 0 : TCAP_EOC_LEN)); \
+ }
+
+/*
+ * [6] 3.6
+ */
+static guint8
+de_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ ASN1_SCK asn1_real, *asn1;
+ proto_item *item;
+ proto_tree *subtree, *temp_subtree, *seq_subtree;
+ guint saved_offset, comp_saved_offset, comp_len_offset, comp_data_offset;
+ guint comp_len, temp_len;
+ gboolean def_len[3];
+ guint comp_tag, tag;
+ gchar *str;
+ gint32 int_val;
+
+ add_string = add_string;
+
+ asn1 = &asn1_real;
+ asn1_open(asn1, tvb, offset);
+
+ /* call next dissector for EACH component */
+
+ while ((len - (asn1->offset - offset)) > 0)
+ {
+ comp_saved_offset = asn1->offset;
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &comp_tag);
+
+ comp_len_offset = asn1->offset;
+ comp_len = 0;
+ def_len[0] = FALSE;
+ asn1_length_decode(asn1, &def_len[0], &comp_len);
+ comp_data_offset = asn1->offset;
+
+ if (def_len[0])
+ {
+ temp_len = comp_len + (asn1->offset - saved_offset);
+ }
+ else
+ {
+ comp_len = tcap_find_eoc(asn1);
+ temp_len = comp_len + (asn1->offset - saved_offset) + TCAP_EOC_LEN;
+ }
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, comp_saved_offset, temp_len, "Component");
+
+ subtree = proto_item_add_subtree(item, ett_tc_component);
+
+ str = match_strval((guint32) comp_tag, tcap_component_type_str);
+
+ if (str == NULL)
+ {
+ proto_tree_add_text(subtree, asn1->tvb, comp_saved_offset, temp_len,
+ "Unknown component type tag, ignoring component");
+
+ asn1->offset = comp_saved_offset + temp_len;
+ continue;
+ }
+
+ proto_tree_add_text(subtree, asn1->tvb, comp_saved_offset,
+ comp_len_offset - comp_saved_offset,
+ "%s Type Tag: 0x%02x", str, comp_tag);
+
+ if (def_len[0])
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ comp_len_offset, asn1->offset - comp_len_offset, "Length: %d", comp_len);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ comp_len_offset, asn1->offset - comp_len_offset, "Length: Indefinite");
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Invoke ID",
+ ett_tc_invoke_id, &def_len[1], &temp_len, temp_subtree);
+
+ if (temp_len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, temp_len, &int_val);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, temp_len, "Invoke ID: %d", int_val);
+ }
+
+ if (!def_len[1])
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+
+ switch (comp_tag)
+ {
+ case TCAP_COMP_INVOKE:
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (tag == TCAP_LINKED_ID_TAG)
+ {
+ GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Linked ID",
+ ett_tc_linked_id, &def_len[1], &temp_len, temp_subtree);
+
+ if (temp_len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, temp_len, &int_val);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, temp_len, "Linked ID: %d", int_val);
+ }
+
+ if (!def_len[1])
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+ }
+
+ GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Operation Code",
+ ett_tc_opr_code, &def_len[1], &temp_len, temp_subtree);
+
+ if (temp_len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, temp_len, &int_val);
+
+ str = match_strval(int_val, gsm_ss_opr_code_strings);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, temp_len, "Operation Code: %s (%d)",
+ (str == NULL) ? "Unknown Operation Code" : str,
+ int_val);
+ }
+
+ if (!def_len[1])
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+
+ if ((comp_len - (asn1->offset - comp_data_offset)) > 0)
+ {
+ gsm_ss_dissect(asn1, subtree,
+ comp_len - (asn1->offset - comp_data_offset), int_val, comp_tag);
+ }
+ break;
+
+ case TCAP_COMP_RRL:
+ if ((len - (asn1->offset - offset)) > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Sequence",
+ ett_tc_sequence, &def_len[1], &temp_len, seq_subtree);
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_A_TC_START_SUBTREE(seq_subtree, saved_offset, tag, "Operation Code",
+ ett_tc_opr_code, &def_len[2], &temp_len, temp_subtree);
+
+ if (temp_len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, temp_len, &int_val);
+
+ str = match_strval(int_val, gsm_ss_opr_code_strings);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, temp_len, "Operation Code: %s (%d)",
+ (str == NULL) ? "Unknown Operation Code" : str,
+ int_val);
+ }
+
+ if (!def_len[2])
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+
+ if ((comp_len - (asn1->offset - comp_data_offset)) > 0)
+ {
+ gsm_ss_dissect(asn1, seq_subtree,
+ comp_len - (asn1->offset - comp_data_offset), int_val, comp_tag);
+ }
+
+ if (!def_len[1])
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+ }
+ break;
+
+ case TCAP_COMP_RE:
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ switch (tag)
+ {
+ case 0x02:
+ GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Local Error Code",
+ ett_tc_err_code, &def_len[1], &temp_len, temp_subtree);
+
+ if (temp_len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, temp_len, &int_val);
+
+ str = match_strval(int_val, gsm_ss_err_code_strings);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, temp_len, "Error Code: %s (%d)",
+ (str == NULL) ? "Unknown Error Code" : str,
+ int_val);
+ }
+ break;
+
+ case 0x06:
+ GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Global Error Code",
+ ett_tc_err_code, &def_len[1], &temp_len, temp_subtree);
+
+ if (temp_len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, temp_len, &int_val);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, temp_len, "Error Code: %d",
+ int_val);
+ }
+ break;
+
+ default:
+ GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Unknown Error Code",
+ ett_tc_err_code, &def_len[1], &temp_len, temp_subtree);
+
+ if (temp_len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, temp_len, &int_val);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, temp_len, "Error Code: %d",
+ int_val);
+ }
+ break;
+ }
+
+ if (!def_len[1])
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+
+ if ((comp_len - (asn1->offset - comp_data_offset)) > 0)
+ {
+ /*
+ * XXX need conversations to determine 'opr_code'
+ */
+ gsm_ss_dissect(asn1, subtree,
+ comp_len - (asn1->offset - comp_data_offset), 0, comp_tag);
+ }
+ break;
+
+ case TCAP_COMP_REJECT:
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_A_TC_START_SUBTREE(subtree, saved_offset, tag, "Problem Code",
+ ett_tc_prob_code, &def_len[1], &temp_len, temp_subtree);
+
+ if (temp_len > 0)
+ {
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ asn1->offset, temp_len, "Problem Code");
+
+ asn1->offset += temp_len;
+ }
+
+ if (!def_len[1])
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+ break;
+ }
+
+ if (!def_len[0])
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+ }
+
+ return(len);
+}
+
+/*
+ * [3] 10.5.4.17
+ */
+static guint8
+de_keypad_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Keypad information: %c",
+ a_bigbuf,
+ oct & 0x7f);
+
+ curr_offset++;
+
+ sprintf(add_string, " - %c", oct & 0x7f);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.21
+ */
+static guint8
+de_prog_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "extended" : "not extended");
+
+ switch ((oct & 0x60) >> 5)
+ {
+ case 0: str = "Coding as specified in ITU-T Rec. Q.931"; break;
+ case 1: str = "Reserved for other international standards"; break;
+ case 2: str = "National standard"; break;
+ default:
+ str = "Standard defined for the GSM PLMNS";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x60, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Coding standard: %s",
+ a_bigbuf,
+ str);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x0f)
+ {
+ case 0: str = "User"; break;
+ case 1: str = "Private network serving the local user"; break;
+ case 2: str = "Public network serving the local user"; break;
+ case 4: str = "Public network serving the remote user"; break;
+ case 5: str = "Private network serving the remote user"; break;
+ case 10: str = "Network beyond interworking point"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Location: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "extended" : "not extended");
+
+ switch (oct & 0x7f)
+ {
+ case 1: str = "Call is not end-to-end PLMN/ISDN, further call progress information may be available in-band"; break;
+ case 2: str = "Destination address in non-PLMN/ISDN"; break;
+ case 3: str = "Origination address in non-PLMN/ISDN"; break;
+ case 4: str = "Call has returned to the PLMN/ISDN"; break;
+ case 8: str = "In-band information or appropriate pattern now available"; break;
+ case 32: str = "Call is end-to-end PLMN/ISDN"; break;
+ case 64: str = "Queueing"; break;
+ default:
+ str = "Unspecific";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Progress Description: %s (%d)",
+ a_bigbuf,
+ str,
+ oct & 0x7f);
+
+ sprintf(add_string, " - %d", oct & 0x7f);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [3] 10.5.4.22
+ */
+static guint8
+de_repeat_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct & 0x0f)
+ {
+ case 1: str = "Circular for successive selection 'mode 1 alternate mode 2'"; break;
+ case 2: str = "Support of fallback mode 1 preferred, mode 2 selected if setup of mode 1 fails"; break;
+ case 3: str = "Reserved: was allocated in earlier phases of the protocol"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [6] 3.7.2
+ */
+static guint8
+de_ss_ver_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 0: str = "Phase 2 service, ellipsis notation, and phase 2 error handling is supported"; break;
+ case 1: str = "SS-Protocol version 3 is supported, and phase 2 error handling is supported"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s",
+ str);
+
+ curr_offset++;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [5] 8.1.4.1
+ */
+static guint8
+de_cp_user_data(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+ tvbuff_t *rp_tvb;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ "RPDU");
+
+ /*
+ * dissect the embedded RP message
+ */
+ rp_tvb = tvb_new_subset(tvb, curr_offset, len, len);
+
+ call_dissector(rp_handle, rp_tvb, g_pinfo, g_tree);
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [5] 8.1.4.2
+ */
+static guint8
+de_cp_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ len = len;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ switch (oct)
+ {
+ case 17: str = "Network failure"; break;
+ case 22: str = "Congestion"; break;
+ case 81: str = "Invalid Transaction Identifier value"; break;
+ case 95: str = "Semantically incorrect message"; break;
+ case 96: str = "Invalid mandatory information"; break;
+ case 97: str = "Message type non-existent or not implemented"; break;
+ case 98: str = "Message not compatible with the short message protocol state"; break;
+ case 99: str = "Information element non-existent or not implemented"; break;
+ case 111: str = "Protocol error, unspecified"; break;
+ default:
+ str = "Reserved, treat as Protocol error, unspecified";
+ break;
+ }
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "Cause: (%u) %s",
+ oct,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%u) %s", oct, str);
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [5] 8.2.3
+ */
+static guint8
+de_rp_message_ref(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+
+ len = len;
+ add_string = add_string;
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "RP-Message Reference: 0x%02x (%u)",
+ oct,
+ oct);
+
+ curr_offset++;
+
+ /* no length check possible */
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [5] 8.2.5.1
+ */
+static guint8
+de_rp_orig_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ return(de_cld_party_bcd_num(tvb, tree, offset, len, add_string));
+}
+
+/*
+ * [5] 8.2.5.2
+ */
+static guint8
+de_rp_dest_addr(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ return(de_cld_party_bcd_num(tvb, tree, offset, len, add_string));
+}
+
+/*
+ * [5] 8.2.5.3
+ */
+static guint8
+de_rp_user_data(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint32 curr_offset;
+ tvbuff_t *tpdu_tvb;
+
+ add_string = add_string;
+ curr_offset = offset;
+
+ proto_tree_add_text(tree, tvb, curr_offset, len,
+ "TPDU");
+
+ /*
+ * dissect the embedded TPDU message
+ */
+ tpdu_tvb = tvb_new_subset(tvb, curr_offset, len, len);
+
+ dissector_try_port(sms_dissector_table, 0, tpdu_tvb, g_pinfo, g_tree);
+
+ curr_offset += len;
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+/*
+ * [5] 8.2.5.4
+ */
+static guint8
+de_rp_cause(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ gchar *str;
+
+ curr_offset = offset;
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Extension: %s",
+ a_bigbuf,
+ (oct & 0x80) ? "extended" : "not extended");
+
+ switch (oct & 0x7f)
+ {
+ case 1: str = "Unassigned (unallocated) number"; break;
+ case 8: str = "Operator determined barring"; break;
+ case 10: str = "Call barred"; break;
+ case 11: str = "Reserved"; break;
+ case 21: str = "Short message transfer rejected"; break;
+ case 22: str = "Memory capacity exceeded"; break;
+ case 27: str = "Destination out of order"; break;
+ case 28: str = "Unidentified subscriber"; break;
+ case 29: str = "Facility rejected"; break;
+ case 30: str = "Unknown subscriber"; break;
+ case 38: str = "Network out of order"; break;
+ case 41: str = "Temporary failure"; break;
+ case 42: str = "Congestion"; break;
+ case 47: str = "Resources unavailable, unspecified"; break;
+ case 50: str = "Requested facility not subscribed"; break;
+ case 69: str = "Requested facility not implemented"; break;
+ case 81: str = "Invalid short message transfer reference value"; break;
+ case 95: str = "Semantically incorrect message"; break;
+ case 96: str = "Invalid mandatory information"; break;
+ case 97: str = "Message type non-existent or not implemented"; break;
+ case 98: str = "Message not compatible with short message protocol state"; break;
+ case 99: str = "Information element non-existent or not implemented"; break;
+ case 111: str = "Protocol error, unspecified"; break;
+ case 127: str = "Interworking, unspecified"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Cause: (%u) %s",
+ a_bigbuf,
+ oct & 0x7f,
+ str);
+
+ curr_offset++;
+
+ sprintf(add_string, " - (%u) %s", oct & 0x7f, str);
+
+ NO_MORE_DATA_CHECK(len);
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, len - (curr_offset - offset),
+ "Diagnostic field");
+
+ curr_offset += len - (curr_offset - offset);
+
+ EXTRANEOUS_DATA_CHECK(len, curr_offset - offset);
+
+ return(curr_offset - offset);
+}
+
+static guint8 (*bssmap_elem_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string) = {
+ be_cic, /* Circuit Identity Code */
+ NULL, /* Reserved */
+ NULL, /* Resource Available */
+ be_cause, /* Cause */
+ be_cell_id, /* Cell Identifier */
+ be_prio, /* Priority */
+ be_l3_header_info, /* Layer 3 Header Information */
+ de_mid, /* IMSI */
+ be_tmsi, /* TMSI */
+ be_enc_info, /* Encryption Information */
+ be_chan_type, /* Channel Type */
+ NULL, /* Periodicity */
+ NULL, /* Extended Resource Indicator */
+ NULL, /* Number Of MSs */
+ NULL, /* Reserved */
+ NULL, /* Reserved */
+ NULL, /* Reserved */
+ de_ms_cm_2, /* Classmark Information Type 2 */
+ NULL, /* Classmark Information Type 3 */
+ NULL, /* Interference Band To Be Used */
+ de_rr_cause, /* RR Cause */
+ NULL, /* Reserved */
+ be_l3_info, /* Layer 3 Information */
+ be_dlci, /* DLCI */
+ be_down_dtx_flag, /* Downlink DTX Flag */
+ be_cell_id_list, /* Cell Identifier List */
+ NULL /* no associated data */, /* Response Request */
+ NULL, /* Resource Indication Method */
+ de_ms_cm_1, /* Classmark Information Type 1 */
+ NULL, /* Circuit Identity Code List */
+ NULL, /* Diagnostic */
+ be_l3_msg, /* Layer 3 Message Contents */
+ be_chosen_chan, /* Chosen Channel */
+ NULL, /* Total Resource Accessible */
+ be_ciph_resp_mode, /* Cipher Response Mode */
+ NULL, /* Channel Needed */
+ NULL, /* Trace Type */
+ NULL, /* TriggerID */
+ NULL, /* Trace Reference */
+ NULL, /* TransactionID */
+ de_mid, /* Mobile Identity */
+ NULL, /* OMCID */
+ be_for_ind, /* Forward Indicator */
+ be_chosen_enc_alg, /* Chosen Encryption Algorithm */
+ be_cct_pool, /* Circuit Pool */
+ NULL, /* Circuit Pool List */
+ NULL, /* Time Indication */
+ NULL, /* Resource Situation */
+ be_curr_chan_1, /* Current Channel Type 1 */
+ be_que_ind, /* Queueing Indicator */
+ be_speech_ver, /* Speech Version */
+ NULL, /* Assignment Requirement */
+ NULL /* no associated data */, /* Talker Flag */
+ NULL /* no associated data */, /* Connection Release Requested */
+ NULL, /* Group Call Reference */
+ NULL, /* eMLPP Priority */
+ NULL, /* Configuration Evolution Indication */
+ NULL /* no decode required */, /* Old BSS to New BSS Information */
+ NULL, /* LSA Identifier */
+ NULL, /* LSA Identifier List */
+ NULL, /* LSA Information */
+ NULL, /* LCS QoS */
+ NULL, /* LSA access control suppression */
+ NULL, /* LCS Priority */
+ NULL, /* Location Type */
+ NULL, /* Location Estimate */
+ NULL, /* Positioning Data */
+ NULL, /* LCS Cause */
+ NULL, /* LCS Client Type */
+ be_apdu, /* APDU */
+ NULL, /* Network Element Identity */
+ NULL, /* GPS Assistance Data */
+ NULL, /* Deciphering Keys */
+ NULL, /* Return Error Request */
+ NULL, /* Return Error Cause */
+ NULL, /* Segmentation */
+ NULL, /* NONE */
+};
+
+static guint8 (*dtap_elem_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string) = {
+ /* Common Information Elements 10.5.1 */
+ de_cell_id, /* Cell Identity */
+ NULL /* handled inline */, /* Ciphering Key Sequence Number */
+ de_lai, /* Location Area Identification */
+ de_mid, /* Mobile Identity */
+ de_ms_cm_1, /* Mobile Station Classmark 1 */
+ de_ms_cm_2, /* Mobile Station Classmark 2 */
+ NULL, /* Mobile Station Classmark 3 */
+ de_d_gb_call_ref, /* Descriptive group or broadcast call reference */
+ NULL /* handled inline */, /* Group Cipher Key Number */
+ de_pd_sapi, /* PD and SAPI $(CCBS)$ */
+ de_prio /* handled inline */, /* Priority Level */
+ de_plmn_list, /* PLMN List */
+ /* Radio Resource Management Information Elements 10.5.2, most are from 10.5.1 */
+ de_rr_cause, /* RR Cause */
+ /* Mobility Management Information Elements 10.5.3 */
+ de_auth_param_rand, /* Authentication Parameter RAND */
+ de_auth_param_autn, /* Authentication Parameter AUTN (UMTS authentication challenge only) */
+ de_auth_resp_param, /* Authentication Response Parameter */
+ de_auth_resp_param_ext, /* Authentication Response Parameter (extension) (UMTS authentication challenge only) */
+ de_auth_fail_param, /* Authentication Failure Parameter (UMTS authentication challenge only) */
+ NULL /* handled inline */, /* CM Service Type */
+ NULL /* handled inline */, /* Identity Type */
+ NULL /* handled inline */, /* Location Updating Type */
+ de_network_name, /* Network Name */
+ de_rej_cause, /* Reject Cause */
+ NULL /* no associated data */, /* Follow-on Proceed */
+ de_time_zone, /* Time Zone */
+ de_time_zone_time, /* Time Zone and Time */
+ NULL /* no associated data */, /* CTS Permission */
+ de_lsa_id, /* LSA Identifier */
+ de_day_saving_time, /* Daylight Saving Time */
+ /* Call Control Information Elements 10.5.4 */
+ de_aux_states, /* Auxiliary States */
+ de_bearer_cap, /* Bearer Capability */
+ de_cc_cap, /* Call Control Capabilities */
+ de_call_state, /* Call State */
+ de_cld_party_bcd_num, /* Called Party BCD Number */
+ de_cld_party_sub_addr, /* Called Party Subaddress */
+ de_clg_party_bcd_num, /* Calling Party BCD Number */
+ de_clg_party_sub_addr, /* Calling Party Subaddress */
+ de_cause, /* Cause */
+ NULL /* no associated data */, /* CLIR Suppression */
+ NULL /* no associated data */, /* CLIR Invocation */
+ NULL /* handled inline */, /* Congestion Level */
+ NULL, /* Connected Number */
+ NULL, /* Connected Subaddress */
+ de_facility, /* Facility */
+ NULL, /* High Layer Compatibility */
+ de_keypad_facility, /* Keypad Facility */
+ NULL, /* Low Layer Compatibility */
+ NULL, /* More Data */
+ NULL, /* Notification Indicator */
+ de_prog_ind, /* Progress Indicator */
+ NULL, /* Recall type $(CCBS)$ */
+ NULL, /* Redirecting Party BCD Number */
+ NULL, /* Redirecting Party Subaddress */
+ de_repeat_ind, /* Repeat Indicator */
+ NULL /* no associated data */, /* Reverse Call Setup Direction */
+ NULL, /* SETUP Container $(CCBS)$ */
+ NULL, /* Signal */
+ de_ss_ver_ind, /* SS Version Indicator */
+ NULL, /* User-user */
+ NULL, /* Alerting Pattern $(NIA)$ */
+ NULL, /* Allowed Actions $(CCBS)$ */
+ NULL, /* Stream Identifier */
+ NULL, /* Network Call Control Capabilities */
+ NULL, /* Cause of No CLI */
+ NULL, /* Immediate Modification Indicator */
+ NULL, /* Supported Codec List */
+ NULL, /* Service Category */
+ /* GPRS Mobility Management Information Elements 10.5.5 */
+ NULL, /* Attach Result */
+ NULL, /* Attach Type */
+ NULL, /* TMSI Status */
+ NULL, /* Detach Type */
+ NULL, /* DRX Parameter */
+ NULL, /* Force to Standby */
+ NULL, /* P-TMSI Signature */
+ NULL, /* P-TMSI Signature 2 */
+ NULL, /* Identity Type 2 */
+ NULL, /* IMEISV Request */
+ NULL, /* Receive N-PDU Numbers List */
+ NULL, /* MS Network Capability */
+ NULL, /* MS Radio Access Capability */
+ NULL, /* GMM Cause */
+ NULL, /* Routing Area Identification */
+ NULL, /* Update Result */
+ NULL, /* A&C Reference Number */
+ NULL, /* Service Type */
+ NULL, /* Cell Notification */
+ NULL, /* Network Feature Support */
+ /* Short Message Service Information Elements [5] 8.1.4 */
+ de_cp_user_data, /* CP-User Data */
+ de_cp_cause, /* CP-Cause */
+ /* Short Message Service Information Elements [5] 8.2 */
+ de_rp_message_ref, /* RP-Message Reference */
+ de_rp_orig_addr, /* RP-Origination Address */
+ de_rp_dest_addr, /* RP-Destination Address */
+ de_rp_user_data, /* RP-User Data */
+ de_rp_cause, /* RP-Cause */
+ /* Session Management Information Elements 10.5.6 */
+ NULL, /* Access Point Name */
+ NULL, /* Network Service Access Point Identifier */
+ NULL, /* Protocol Configuration Options */
+ NULL, /* Packet Data Protocol Address */
+ NULL, /* Quality Of Service */
+ NULL, /* SM Cause */
+ NULL, /* Linked TI */
+ NULL, /* LLC Service Access Point Identifier */
+ NULL, /* Tear Down Indicator */
+ NULL, /* Packet Flow Identifier */
+ NULL, /* Traffic Flow Template */
+ /* GPRS Common Information Elements 10.5.7 */
+ NULL, /* PDP Context Status */
+ NULL, /* Radio Priority */
+ NULL, /* GPRS Timer */
+ NULL, /* GPRS Timer 2 */
+ NULL, /* NONE */
+};
+
+#define SET_ELEM_VARS(SEV_pdu_type, SEV_elem_names, SEV_elem_ett, SEV_elem_funcs) \
+ switch (SEV_pdu_type) \
+ { \
+ case BSSAP_PDU_TYPE_BSSMAP: \
+ SEV_elem_names = gsm_bssmap_elem_strings; \
+ SEV_elem_ett = ett_gsm_bssmap_elem; \
+ SEV_elem_funcs = bssmap_elem_fcn; \
+ break; \
+ case BSSAP_PDU_TYPE_DTAP: \
+ SEV_elem_names = gsm_dtap_elem_strings; \
+ SEV_elem_ett = ett_gsm_dtap_elem; \
+ SEV_elem_funcs = dtap_elem_fcn; \
+ break; \
+ default: \
+ proto_tree_add_text(tree, \
+ tvb, curr_offset, -1, \
+ "Unknown PDU type (%u)", SEV_pdu_type); \
+ return(consumed); \
+ }
+
+/*
+ * Type Length Value (TLV) element dissector
+ */
+static guint8
+elem_tlv(tvbuff_t *tvb, proto_tree *tree, guint8 iei, gint pdu_type, int idx, guint32 offset, guint len, gchar *name_add)
+{
+ guint8 oct, parm_len;
+ guint8 consumed;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ const value_string *elem_names;
+ gint *elem_ett;
+ guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
+
+ len = len;
+ curr_offset = offset;
+ consumed = 0;
+
+ SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct == iei)
+ {
+ parm_len = tvb_get_guint8(tvb, curr_offset + 1);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, parm_len + 2,
+ "%s%s",
+ elem_names[idx].strptr,
+ (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+ subtree = proto_item_add_subtree(item, elem_ett[idx]);
+
+ proto_tree_add_uint(subtree,
+ (BSSAP_PDU_TYPE_BSSMAP == pdu_type) ? hf_gsm_a_bssmap_elem_id : hf_gsm_a_dtap_elem_id, tvb,
+ curr_offset, 1, oct);
+
+ proto_tree_add_uint(subtree, hf_gsm_a_length, tvb,
+ curr_offset + 1, 1, parm_len);
+
+ if (parm_len > 0)
+ {
+ if (elem_funcs[idx] == NULL)
+ {
+ proto_tree_add_text(subtree,
+ tvb, curr_offset + 2, parm_len,
+ "Element Value");
+
+ consumed = parm_len;
+ }
+ else
+ {
+ a_add_string[0] = '\0';
+ consumed =
+ (*elem_funcs[idx])(tvb, subtree, curr_offset + 2,
+ parm_len, a_add_string);
+
+ if (a_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, a_add_string);
+ a_add_string[0] = '\0';
+ }
+ }
+ }
+
+ consumed += 2;
+ }
+
+ return(consumed);
+}
+
+/*
+ * Type Value (TV) element dissector
+ *
+ * Length cannot be used in these functions, big problem if a element dissector
+ * is not defined for these.
+ */
+static guint8
+elem_tv(tvbuff_t *tvb, proto_tree *tree, guint8 iei, gint pdu_type, int idx, guint32 offset, gchar *name_add)
+{
+ guint8 oct;
+ guint8 consumed;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ const value_string *elem_names;
+ gint *elem_ett;
+ guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
+
+ curr_offset = offset;
+ consumed = 0;
+
+ SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct == iei)
+ {
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, -1,
+ "%s%s",
+ elem_names[idx].strptr,
+ (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+ subtree = proto_item_add_subtree(item, elem_ett[idx]);
+
+ proto_tree_add_uint(subtree,
+ (BSSAP_PDU_TYPE_BSSMAP == pdu_type) ? hf_gsm_a_bssmap_elem_id : hf_gsm_a_dtap_elem_id, tvb,
+ curr_offset, 1, oct);
+
+ if (elem_funcs[idx] == NULL)
+ {
+ /* BAD THING, CANNOT DETERMINE LENGTH */
+
+ proto_tree_add_text(subtree,
+ tvb, curr_offset + 1, 1,
+ "No element dissector, rest of dissection may be incorrect");
+
+ consumed = 1;
+ }
+ else
+ {
+ a_add_string[0] = '\0';
+ consumed = (*elem_funcs[idx])(tvb, subtree, curr_offset + 1, -1, a_add_string);
+
+ if (a_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, a_add_string);
+ a_add_string[0] = '\0';
+ }
+ }
+
+ consumed++;
+
+ proto_item_set_len(item, consumed);
+ }
+
+ return(consumed);
+}
+
+/*
+ * Type Value (TV) element dissector
+ * Where top half nibble is IEI and bottom half nibble is value.
+ *
+ * Length cannot be used in these functions, big problem if a element dissector
+ * is not defined for these.
+ */
+static guint8
+elem_tv_short(tvbuff_t *tvb, proto_tree *tree, guint8 iei, gint pdu_type, int idx, guint32 offset, gchar *name_add)
+{
+ guint8 oct;
+ guint8 consumed;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ const value_string *elem_names;
+ gint *elem_ett;
+ guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
+
+ curr_offset = offset;
+ consumed = 0;
+
+ SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if ((oct & 0xf0) == (iei & 0xf0))
+ {
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, -1,
+ "%s%s",
+ elem_names[idx].strptr,
+ (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+ subtree = proto_item_add_subtree(item, elem_ett[idx]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Element ID",
+ a_bigbuf);
+
+ if (elem_funcs[idx] == NULL)
+ {
+ /* BAD THING, CANNOT DETERMINE LENGTH */
+
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "No element dissector, rest of dissection may be incorrect");
+
+ consumed++;
+ }
+ else
+ {
+ a_add_string[0] = '\0';
+ consumed = (*elem_funcs[idx])(tvb, subtree, curr_offset, -1, a_add_string);
+
+ if (a_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, a_add_string);
+ a_add_string[0] = '\0';
+ }
+ }
+
+ proto_item_set_len(item, consumed);
+ }
+
+ return(consumed);
+}
+
+/*
+ * Type (T) element dissector
+ */
+static guint8
+elem_t(tvbuff_t *tvb, proto_tree *tree, guint8 iei, gint pdu_type, int idx, guint32 offset, gchar *name_add)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ guint8 consumed;
+ const value_string *elem_names;
+ gint *elem_ett;
+ guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
+
+ curr_offset = offset;
+ consumed = 0;
+
+ SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
+
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ if (oct == iei)
+ {
+ proto_tree_add_uint_format(tree,
+ (BSSAP_PDU_TYPE_BSSMAP == pdu_type) ? hf_gsm_a_bssmap_elem_id : hf_gsm_a_dtap_elem_id, tvb,
+ curr_offset, 1, oct,
+ "%s%s",
+ elem_names[idx].strptr,
+ (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+ consumed = 1;
+ }
+
+ return(consumed);
+}
+
+/*
+ * Length Value (LV) element dissector
+ */
+static guint8
+elem_lv(tvbuff_t *tvb, proto_tree *tree, gint pdu_type, int idx, guint32 offset, guint len, gchar *name_add)
+{
+ guint8 parm_len;
+ guint8 consumed;
+ guint32 curr_offset;
+ proto_tree *subtree;
+ proto_item *item;
+ const value_string *elem_names;
+ gint *elem_ett;
+ guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
+
+ len = len;
+ curr_offset = offset;
+ consumed = 0;
+
+ SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
+
+ parm_len = tvb_get_guint8(tvb, curr_offset);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, parm_len + 1,
+ "%s%s",
+ elem_names[idx].strptr,
+ (name_add == NULL) || (name_add[0] == '\0') ? "" : name_add);
+
+ subtree = proto_item_add_subtree(item, elem_ett[idx]);
+
+ proto_tree_add_uint(subtree, hf_gsm_a_length, tvb,
+ curr_offset, 1, parm_len);
+
+ if (parm_len > 0)
+ {
+ if (elem_funcs[idx] == NULL)
+ {
+ proto_tree_add_text(subtree,
+ tvb, curr_offset + 1, parm_len,
+ "Element Value");
+
+ consumed = parm_len;
+ }
+ else
+ {
+ a_add_string[0] = '\0';
+ consumed =
+ (*elem_funcs[idx])(tvb, subtree, curr_offset + 1,
+ parm_len, a_add_string);
+
+ if (a_add_string[0] != '\0')
+ {
+ proto_item_append_text(item, a_add_string);
+ a_add_string[0] = '\0';
+ }
+ }
+ }
+
+ return(consumed + 1);
+}
+
+/*
+ * Value (V) element dissector
+ *
+ * Length cannot be used in these functions, big problem if a element dissector
+ * is not defined for these.
+ */
+static guint8
+elem_v(tvbuff_t *tvb, proto_tree *tree, gint pdu_type, int idx, guint32 offset)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ const value_string *elem_names;
+ gint *elem_ett;
+ guint8 (**elem_funcs)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string);
+
+ curr_offset = offset;
+ consumed = 0;
+
+ SET_ELEM_VARS(pdu_type, elem_names, elem_ett, elem_funcs);
+
+ if (elem_funcs[idx] == NULL)
+ {
+ /* BAD THING, CANNOT DETERMINE LENGTH */
+
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "No element dissector, rest of dissection may be incorrect");
+
+ consumed = 1;
+ }
+ else
+ {
+ a_add_string[0] = '\0';
+ consumed = (*elem_funcs[idx])(tvb, tree, curr_offset, -1, a_add_string);
+ a_add_string[0] = '\0';
+ }
+
+ return(consumed);
+}
+
+#define ELEM_MAND_TLV(EMT_iei, EMT_pdu_type, EMT_elem_idx, EMT_elem_name_addition) \
+{\
+ if ((consumed = elem_tlv(tvb, tree, (guint8) EMT_iei, EMT_pdu_type, EMT_elem_idx, curr_offset, curr_len, EMT_elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ else \
+ { \
+ proto_tree_add_text(tree, \
+ tvb, curr_offset, 0, \
+ "Missing Mandatory element (0x%02x) %s%s, rest of dissection is suspect", \
+ EMT_iei, \
+ (EMT_pdu_type == BSSAP_PDU_TYPE_BSSMAP) ? \
+ gsm_bssmap_elem_strings[EMT_elem_idx].strptr : gsm_dtap_elem_strings[EMT_elem_idx].strptr, \
+ (EMT_elem_name_addition == NULL) || (EMT_elem_name_addition[0] == '\0') ? "" : EMT_elem_name_addition \
+ ); \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_TLV(EOT_iei, EOT_pdu_type, EOT_elem_idx, EOT_elem_name_addition) \
+{\
+ if ((consumed = elem_tlv(tvb, tree, (guint8) EOT_iei, EOT_pdu_type, EOT_elem_idx, curr_offset, curr_len, EOT_elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_MAND_TV(EMT_iei, EMT_pdu_type, EMT_elem_idx, EMT_elem_name_addition) \
+{\
+ if ((consumed = elem_tv(tvb, tree, (guint8) EMT_iei, EMT_pdu_type, EMT_elem_idx, curr_offset, EMT_elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ else \
+ { \
+ proto_tree_add_text(tree, \
+ tvb, curr_offset, 0, \
+ "Missing Mandatory element (0x%02x) %s%s, rest of dissection is suspect", \
+ EMT_iei, \
+ (EMT_pdu_type == BSSAP_PDU_TYPE_BSSMAP) ? \
+ gsm_bssmap_elem_strings[EMT_elem_idx].strptr : gsm_dtap_elem_strings[EMT_elem_idx].strptr, \
+ (EMT_elem_name_addition == NULL) || (EMT_elem_name_addition[0] == '\0') ? "" : EMT_elem_name_addition \
+ ); \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_TV(EOT_iei, EOT_pdu_type, EOT_elem_idx, EOT_elem_name_addition) \
+{\
+ if ((consumed = elem_tv(tvb, tree, (guint8) EOT_iei, EOT_pdu_type, EOT_elem_idx, curr_offset, EOT_elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_TV_SHORT(EOT_iei, EOT_pdu_type, EOT_elem_idx, EOT_elem_name_addition) \
+{\
+ if ((consumed = elem_tv_short(tvb, tree, EOT_iei, EOT_pdu_type, EOT_elem_idx, curr_offset, EOT_elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_OPT_T(EOT_iei, EOT_pdu_type, EOT_elem_idx, EOT_elem_name_addition) \
+{\
+ if ((consumed = elem_t(tvb, tree, (guint8) EOT_iei, EOT_pdu_type, EOT_elem_idx, curr_offset, EOT_elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_MAND_LV(EML_pdu_type, EML_elem_idx, EML_elem_name_addition) \
+{\
+ if ((consumed = elem_lv(tvb, tree, EML_pdu_type, EML_elem_idx, curr_offset, curr_len, EML_elem_name_addition)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ else \
+ { \
+ /* Mandatory, but nothing we can do */ \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+#define ELEM_MAND_V(EMV_pdu_type, EMV_elem_idx) \
+{\
+ if ((consumed = elem_v(tvb, tree, EMV_pdu_type, EMV_elem_idx, curr_offset)) > 0) \
+ { \
+ curr_offset += consumed; \
+ curr_len -= consumed; \
+ } \
+ else \
+ { \
+ /* Mandatory, but nothing we can do */ \
+ } \
+ if (curr_len <= 0) return; \
+}
+
+
+/* MESSAGE FUNCTIONS */
+
+/*
+ * [2] 3.2.1.1
+ */
+static void
+bssmap_ass_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CHAN_TYPE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHAN_TYPE, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_L3_HEADER_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_HEADER_INFO, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_PRIO].value, BSSAP_PDU_TYPE_BSSMAP, BE_PRIO, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_DOWN_DTX_FLAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_DOWN_DTX_FLAG, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_INT_BAND].value, BSSAP_PDU_TYPE_BSSMAP, BE_INT_BAND, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_2].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_2, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_GROUP_CALL_REF].value, BSSAP_PDU_TYPE_BSSMAP, BE_GROUP_CALL_REF, "");
+
+ ELEM_OPT_T(gsm_bssmap_elem_strings[BE_TALKER_FLAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_TALKER_FLAG, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_LSA_ACC_CTRL].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ACC_CTRL, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.2
+ */
+static void
+bssmap_ass_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_RR_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_RR_CAUSE, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_CHAN].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_CHAN, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CCT_POOL].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Chosen)");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.3
+ */
+static void
+bssmap_ass_failure(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_RR_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_RR_CAUSE, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CCT_POOL].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CCT_POOL_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.4
+ */
+static void
+bssmap_block(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_OPT_T(gsm_bssmap_elem_strings[BE_CONN_REL_REQ].value, BSSAP_PDU_TYPE_BSSMAP, BE_CONN_REL_REQ, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.5
+ */
+static void
+bssmap_block_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.6
+ */
+static void
+bssmap_unblock(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_OPT_T(gsm_bssmap_elem_strings[BE_CONN_REL_REQ].value, BSSAP_PDU_TYPE_BSSMAP, BE_CONN_REL_REQ, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.7
+ */
+static void
+bssmap_unblock_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.8
+ */
+static void
+bssmap_ho_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CHAN_TYPE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHAN_TYPE, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_ENC_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_ENC_INFO, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CM_INFO_1].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_1, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_2].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_2, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, " (Serving)");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_PRIO].value, BSSAP_PDU_TYPE_BSSMAP, BE_PRIO, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_DOWN_DTX_FLAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_DOWN_DTX_FLAG, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, " (Target)");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_INT_BAND].value, BSSAP_PDU_TYPE_BSSMAP, BE_INT_BAND, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_3].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_3, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CURR_CHAN_1].value, BSSAP_PDU_TYPE_BSSMAP, BE_CURR_CHAN_1, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Used)");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_GROUP_CALL_REF].value, BSSAP_PDU_TYPE_BSSMAP, BE_GROUP_CALL_REF, "");
+
+ ELEM_OPT_T(gsm_bssmap_elem_strings[BE_TALKER_FLAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_TALKER_FLAG, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CONF_EVO_IND].value, BSSAP_PDU_TYPE_BSSMAP, BE_CONF_EVO_IND, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, " (Serving)");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_OLD2NEW_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_OLD2NEW_INFO, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_INFO, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_LSA_ACC_CTRL].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ACC_CTRL, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.9
+ */
+static void
+bssmap_ho_reqd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ ELEM_OPT_T(gsm_bssmap_elem_strings[BE_RESP_REQ].value, BSSAP_PDU_TYPE_BSSMAP, BE_RESP_REQ, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID_LIST, " (Preferred)");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CCT_POOL_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL_LIST, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CURR_CHAN_1].value, BSSAP_PDU_TYPE_BSSMAP, BE_CURR_CHAN_1, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Used)");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_QUE_IND].value, BSSAP_PDU_TYPE_BSSMAP, BE_QUE_IND, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_OLD2NEW_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_OLD2NEW_INFO, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.10
+ */
+static void
+bssmap_ho_req_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_L3_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_INFO, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_CHAN].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_CHAN, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CCT_POOL].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Chosen)");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.11
+ */
+static void
+bssmap_ho_cmd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_L3_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_INFO, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.12
+ */
+static void
+bssmap_ho_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_RR_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_RR_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.14
+ */
+static void
+bssmap_ho_cand_enq(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_NUM_MS].value, BSSAP_PDU_TYPE_BSSMAP, BE_NUM_MS, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID_LIST, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.15
+ */
+static void
+bssmap_ho_cand_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_NUM_MS].value, BSSAP_PDU_TYPE_BSSMAP, BE_NUM_MS, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.16
+ */
+static void
+bssmap_ho_failure(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_RR_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_RR_CAUSE, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CCT_POOL].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CCT_POOL_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CCT_POOL_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.19
+ */
+static void
+bssmap_paging(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_IMSI].value, BSSAP_PDU_TYPE_BSSMAP, BE_IMSI, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_TMSI].value, BSSAP_PDU_TYPE_BSSMAP, BE_TMSI, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID_LIST, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CHAN_NEEDED].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHAN_NEEDED, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_EMLPP_PRIO].value, BSSAP_PDU_TYPE_BSSMAP, BE_EMLPP_PRIO, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.20
+ */
+static void
+bssmap_clear_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.21
+ */
+static void
+bssmap_clear_cmd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_L3_HEADER_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_HEADER_INFO, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.23
+ */
+static void
+bssmap_reset(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_UNKNOWN;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.25
+ */
+static void
+bssmap_ho_performed(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_CHAN].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_CHAN, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_SPEECH_VER].value, BSSAP_PDU_TYPE_BSSMAP, BE_SPEECH_VER, " (Chosen)");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.26
+ */
+static void
+bssmap_overload(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.29
+ */
+static void
+bssmap_cm_upd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_2].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_2, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CM_INFO_3].value, BSSAP_PDU_TYPE_BSSMAP, BE_CM_INFO_3, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.30
+ */
+static void
+bssmap_ciph_mode_cmd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_L3_HEADER_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_HEADER_INFO, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_ENC_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_ENC_INFO, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIPH_RESP_MODE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIPH_RESP_MODE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.31
+ */
+static void
+bssmap_ciph_mode_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_L3_MSG].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_MSG, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_ENC_ALG].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_ENC_ALG, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.32
+ */
+static void
+bssmap_cl3_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_L3_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_L3_INFO, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CHOSEN_CHAN].value, BSSAP_PDU_TYPE_BSSMAP, BE_CHOSEN_CHAN, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_LSA_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_ID_LIST, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_APDU].value, BSSAP_PDU_TYPE_BSSMAP, BE_APDU, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.34
+ */
+static void
+bssmap_sapi_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 consumed;
+ guint32 curr_offset;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_DLCI].value, BSSAP_PDU_TYPE_BSSMAP, BE_DLCI, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.37
+ */
+static void
+bssmap_ho_reqd_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.38
+ */
+static void
+bssmap_reset_cct(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.39
+ */
+static void
+bssmap_reset_cct_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.41
+ */
+static void
+bssmap_cct_group_block(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.42
+ */
+static void
+bssmap_cct_group_block_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.43
+ */
+static void
+bssmap_cct_group_unblock(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.44
+ */
+static void
+bssmap_cct_group_unblock_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.45
+ */
+static void
+bssmap_confusion(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_DIAG].value, BSSAP_PDU_TYPE_BSSMAP, BE_DIAG, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.47
+ */
+static void
+bssmap_unequipped_cct(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ ELEM_OPT_TV(gsm_bssmap_elem_strings[BE_CIC_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.48
+ */
+static void
+bssmap_ciph_mode_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.49
+ */
+static void
+bssmap_load_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_TIME_IND].value, BSSAP_PDU_TYPE_BSSMAP, BE_TIME_IND, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID, "");
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CELL_ID_LIST].value, BSSAP_PDU_TYPE_BSSMAP, BE_CELL_ID_LIST, " (Target)");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_RES_SIT].value, BSSAP_PDU_TYPE_BSSMAP, BE_RES_SIT, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.66
+ */
+static void
+bssmap_change_cct(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_CAUSE].value, BSSAP_PDU_TYPE_BSSMAP, BE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.67
+ */
+static void
+bssmap_change_cct_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(gsm_bssmap_elem_strings[BE_CIC].value, BSSAP_PDU_TYPE_BSSMAP, BE_CIC, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.69
+ */
+static void
+bssmap_lsa_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_LSA_INFO].value, BSSAP_PDU_TYPE_BSSMAP, BE_LSA_INFO, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [2] 3.2.1.70
+ */
+static void
+bssmap_conn_oriented(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TLV(gsm_bssmap_elem_strings[BE_APDU].value, BSSAP_PDU_TYPE_BSSMAP, BE_APDU, "");
+
+ ELEM_OPT_TLV(gsm_bssmap_elem_strings[BE_SEG].value, BSSAP_PDU_TYPE_BSSMAP, BE_SEG, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+#define NUM_GSM_BSSMAP_MSG (sizeof(gsm_a_bssmap_msg_strings)/sizeof(value_string))
+static gint ett_gsm_bssmap_msg[NUM_GSM_BSSMAP_MSG];
+static void (*bssmap_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ bssmap_ass_req, /* Assignment Request */
+ bssmap_ass_complete, /* Assignment Complete */
+ bssmap_ass_failure, /* Assignment Failure */
+ bssmap_ho_req, /* Handover Request */
+ bssmap_ho_reqd, /* Handover Required */
+ bssmap_ho_req_ack, /* Handover Request Acknowledge */
+ bssmap_ho_cmd, /* Handover Command */
+ bssmap_ho_complete, /* Handover Complete */
+ NULL /* no associated data */, /* Handover Succeeded */
+ bssmap_ho_failure, /* Handover Failure */
+ bssmap_ho_performed, /* Handover Performed */
+ bssmap_ho_cand_enq, /* Handover Candidate Enquire */
+ bssmap_ho_cand_resp, /* Handover Candidate Response */
+ bssmap_ho_reqd_rej, /* Handover Required Reject */
+ NULL /* no associated data */, /* Handover Detect */
+ bssmap_clear_cmd, /* Clear Command */
+ NULL /* no associated data */, /* Clear Complete */
+ bssmap_clear_req, /* Clear Request */
+ NULL, /* Reserved */
+ NULL, /* Reserved */
+ bssmap_sapi_rej, /* SAPI 'n' Reject */
+ bssmap_confusion, /* Confusion */
+ NULL, /* Suspend */
+ NULL, /* Resume */
+ bssmap_conn_oriented, /* Connection Oriented Information */
+ NULL, /* Perform Location Request */
+ bssmap_lsa_info, /* LSA Information */
+ NULL, /* Perform Location Response */
+ NULL, /* Perform Location Abort */
+ bssmap_reset, /* Reset */
+ NULL /* no associated data */, /* Reset Acknowledge */
+ bssmap_overload, /* Overload */
+ NULL, /* Reserved */
+ bssmap_reset_cct, /* Reset Circuit */
+ bssmap_reset_cct_ack, /* Reset Circuit Acknowledge */
+ NULL, /* MSC Invoke Trace */
+ NULL, /* BSS Invoke Trace */
+ NULL, /* Connectionless Information */
+ bssmap_block, /* Block */
+ bssmap_block_ack, /* Blocking Acknowledge */
+ bssmap_unblock, /* Unblock */
+ bssmap_unblock_ack, /* Unblocking Acknowledge */
+ bssmap_cct_group_block, /* Circuit Group Block */
+ bssmap_cct_group_block_ack, /* Circuit Group Blocking Acknowledge */
+ bssmap_cct_group_unblock, /* Circuit Group Unblock */
+ bssmap_cct_group_unblock_ack, /* Circuit Group Unblocking Acknowledge */
+ bssmap_unequipped_cct, /* Unequipped Circuit */
+ bssmap_change_cct, /* Change Circuit */
+ bssmap_change_cct_ack, /* Change Circuit Acknowledge */
+ NULL, /* Resource Request */
+ NULL, /* Resource Indication */
+ bssmap_paging, /* Paging */
+ bssmap_ciph_mode_cmd, /* Cipher Mode Command */
+ bssmap_cm_upd, /* Classmark Update */
+ bssmap_ciph_mode_complete, /* Cipher Mode Complete */
+ NULL /* no associated data */, /* Queuing Indication */
+ bssmap_cl3_info, /* Complete Layer 3 Information */
+ NULL /* no associated data */, /* Classmark Request */
+ bssmap_ciph_mode_rej, /* Cipher Mode Reject */
+ bssmap_load_ind, /* Load Indication */
+ NULL, /* VGCS/VBS Setup */
+ NULL, /* VGCS/VBS Setup Ack */
+ NULL, /* VGCS/VBS Setup Refuse */
+ NULL, /* VGCS/VBS Assignment Request */
+ NULL, /* VGCS/VBS Assignment Result */
+ NULL, /* VGCS/VBS Assignment Failure */
+ NULL, /* VGCS/VBS Queuing Indication */
+ NULL, /* Uplink Request */
+ NULL, /* Uplink Request Acknowledge */
+ NULL, /* Uplink Request Confirmation */
+ NULL, /* Uplink Release Indication */
+ NULL, /* Uplink Reject Command */
+ NULL, /* Uplink Release Command */
+ NULL, /* Uplink Seized Command */
+ NULL, /* NONE */
+};
+
+/*
+ * [4] 9.2.2
+ */
+static void
+dtap_mm_auth_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+ guint8 oct;
+ proto_tree *subtree;
+ proto_item *item;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ /*
+ * special dissection for Cipher Key Sequence Number
+ */
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+
+ switch (oct & 0x07)
+ {
+ case 0x07:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: No key is available",
+ a_bigbuf);
+ break;
+
+ default:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: %u",
+ a_bigbuf,
+ oct & 0x07);
+ break;
+ }
+
+ curr_offset++;
+ curr_len--;
+
+ if (curr_len <= 0) return;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_AUTH_PARAM_RAND);
+
+ ELEM_OPT_TLV(0x20, BSSAP_PDU_TYPE_DTAP, DE_AUTH_PARAM_AUTN, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.2.3
+ */
+static void
+dtap_mm_auth_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_AUTH_RESP_PARAM);
+
+ ELEM_OPT_TLV(0x21, BSSAP_PDU_TYPE_DTAP, DE_AUTH_RESP_PARAM_EXT, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.2.3a
+ */
+static void
+dtap_mm_auth_fail(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
+
+ ELEM_OPT_TLV(0x22, BSSAP_PDU_TYPE_DTAP, DE_AUTH_FAIL_PARAM, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.4
+ */
+static void
+dtap_mm_cm_reestab_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+ guint8 oct;
+ proto_tree *subtree;
+ proto_item *item;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ /*
+ * special dissection for Cipher Key Sequence Number
+ */
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+
+ switch (oct & 0x07)
+ {
+ case 0x07:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: No key is available",
+ a_bigbuf);
+ break;
+
+ default:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: %u",
+ a_bigbuf,
+ oct & 0x07);
+ break;
+ }
+
+ curr_offset++;
+ curr_len--;
+
+ if (curr_len <= 0) return;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_2, "");
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
+
+ ELEM_OPT_TV(0x13, BSSAP_PDU_TYPE_DTAP, DE_LAI, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.5a
+ */
+static void
+dtap_mm_cm_srvc_prompt(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_PD_SAPI);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.2.6
+ */
+static void
+dtap_mm_cm_srvc_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.2.8
+ */
+static void
+dtap_mm_abort(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.9
+ */
+static void
+dtap_mm_cm_srvc_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+ guint8 oct;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ /*
+ * special dissection for CM Service Type
+ */
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0x07:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: No key is available",
+ a_bigbuf);
+ break;
+
+ default:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: %u",
+ a_bigbuf,
+ (oct & 0x70) >> 4);
+ break;
+ }
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_CM_SRVC_TYPE].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CM_SRVC_TYPE]);
+
+ switch (oct & 0x0f)
+ {
+ case 0x01: str = "Mobile originating call establishment or packet mode connection establishment"; break;
+ case 0x02: str = "Emergency call establishment"; break;
+ case 0x04: str = "Short message service"; break;
+ case 0x08: str = "Supplementary service activation"; break;
+ case 0x09: str = "Voice group call establishment"; break;
+ case 0x0a: str = "Voice broadcast call establishment"; break;
+ case 0x0b: str = "Location Services"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Service Type: (%u) %s",
+ a_bigbuf,
+ oct & 0x0f,
+ str);
+
+ curr_offset++;
+ curr_len--;
+
+ if (curr_len <= 0) return;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_2, "");
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
+
+ ELEM_OPT_TV_SHORT(0x80, BSSAP_PDU_TYPE_DTAP, DE_PRIO, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.10
+ */
+static void
+dtap_mm_id_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint8 oct;
+ guint32 curr_offset;
+ guint curr_len;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ /*
+ * special dissection for Identity Type
+ */
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_ID_TYPE].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_ID_TYPE]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x07)
+ {
+ case 1: str = "IMSI"; break;
+ case 2: str = "IMEI"; break;
+ case 3: str = "IMEISV"; break;
+ case 4: str = "TMSI"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Type of identity: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+ curr_len--;
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.11
+ */
+static void
+dtap_mm_id_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.12
+ */
+static void
+dtap_mm_imsi_det_ind(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_1);
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.13
+ */
+static void
+dtap_mm_loc_upd_acc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_LAI);
+
+ ELEM_OPT_TLV(0x17, BSSAP_PDU_TYPE_DTAP, DE_MID, "");
+
+ ELEM_OPT_T(0xa1, BSSAP_PDU_TYPE_DTAP, DE_FOP, "");
+
+ ELEM_OPT_T(0xa2, BSSAP_PDU_TYPE_DTAP, DE_CTS_PERM, "");
+
+ ELEM_OPT_TLV(0x4a, BSSAP_PDU_TYPE_DTAP, DE_PLMN_LIST, " Equivalent");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.14
+ */
+static void
+dtap_mm_loc_upd_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.15
+ */
+static void
+dtap_mm_loc_upd_req(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+ guint8 oct;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ /*
+ * special dissection for Location Updating Type
+ */
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x70, 8);
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0x07:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: No key is available",
+ a_bigbuf);
+ break;
+
+ default:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: %u",
+ a_bigbuf,
+ (oct & 0x70) >> 4);
+ break;
+ }
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_LOC_UPD_TYPE].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_LOC_UPD_TYPE]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Follow-On Request (FOR): %s",
+ a_bigbuf,
+ (oct & 0x08) ? "Follow-on request pending" : "No follow-on request pending");
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ switch (oct & 0x03)
+ {
+ case 0: str = "Normal"; break;
+ case 1: str = "Periodic"; break;
+ case 2: str = "IMSI attach"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Updating Type: %s",
+ a_bigbuf,
+ str);
+
+ proto_item_append_text(item, " - %s", str);
+
+ curr_offset++;
+ curr_len--;
+
+ if (curr_len <= 0) return;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_LAI);
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_1);
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
+
+ ELEM_OPT_TLV(0x33, BSSAP_PDU_TYPE_DTAP, DE_MS_CM_2, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.1.15a
+ */
+static void
+dtap_mm_mm_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TLV(0x43, BSSAP_PDU_TYPE_DTAP, DE_NETWORK_NAME, " - Full Name");
+
+ ELEM_OPT_TLV(0x45, BSSAP_PDU_TYPE_DTAP, DE_NETWORK_NAME, " - Short Name");
+
+ ELEM_OPT_TV(0x46, BSSAP_PDU_TYPE_DTAP, DE_TIME_ZONE, " - Local");
+
+ ELEM_OPT_TV(0x47, BSSAP_PDU_TYPE_DTAP, DE_TIME_ZONE_TIME, " - Universal Time and Local Time Zone");
+
+ ELEM_OPT_TLV(0x48, BSSAP_PDU_TYPE_DTAP, DE_LSA_ID, "");
+
+ ELEM_OPT_TLV(0x49, BSSAP_PDU_TYPE_DTAP, DE_DAY_SAVING_TIME, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.1.16
+ */
+static void
+dtap_mm_mm_status(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_REJ_CAUSE);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [3] 9.2.17
+ */
+static void
+dtap_mm_tmsi_realloc_cmd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_LAI);
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.1.25
+ */
+static void
+dtap_rr_paging_resp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+ guint8 oct;
+ proto_tree *subtree;
+ proto_item *item;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ /*
+ * special dissection for Cipher Key Sequence Number
+ */
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_CIPH_KEY_SEQ_NUM].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CIPH_KEY_SEQ_NUM]);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x07, 8);
+
+ switch (oct & 0x07)
+ {
+ case 0x07:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: No key is available",
+ a_bigbuf);
+ break;
+
+ default:
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Ciphering Key Sequence Number: %u",
+ a_bigbuf,
+ oct & 0x07);
+ break;
+ }
+
+ curr_offset++;
+ curr_len--;
+
+ if (curr_len <= 0) return;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MS_CM_2, "");
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_MID, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.1.29
+ */
+static void
+dtap_rr_rr_status(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RR_CAUSE);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.1
+ */
+static void
+dtap_cc_alerting(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
+
+ ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
+
+ /* uplink only */
+
+ ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.2
+ */
+static void
+dtap_cc_call_conf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " BC repeat indicator");
+
+ ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 1");
+
+ ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 2");
+
+ ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ ELEM_OPT_TLV(0x15, BSSAP_PDU_TYPE_DTAP, DE_CC_CAP, "");
+
+ ELEM_OPT_TLV(0x2d, BSSAP_PDU_TYPE_DTAP, DE_SI, "");
+
+ ELEM_OPT_TLV(0x40, BSSAP_PDU_TYPE_DTAP, DE_SUP_CODEC_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.3
+ */
+static void
+dtap_cc_call_proceed(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " BC repeat indicator");
+
+ ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 1");
+
+ ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 2");
+
+ ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
+
+ ELEM_OPT_TV_SHORT(0x80, BSSAP_PDU_TYPE_DTAP, DE_PRIO, "");
+
+ ELEM_OPT_TLV(0x2f, BSSAP_PDU_TYPE_DTAP, DE_NET_CC_CAP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.4
+ */
+static void
+dtap_cc_congestion_control(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+ guint8 oct;
+ proto_tree *subtree;
+ proto_item *item;
+ gchar *str;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ /*
+ * special dissection for Congestion Level
+ */
+ oct = tvb_get_guint8(tvb, curr_offset);
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ "%s : Spare",
+ a_bigbuf);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, curr_offset, 1,
+ gsm_dtap_elem_strings[DE_CONGESTION].strptr);
+
+ subtree = proto_item_add_subtree(item, ett_gsm_dtap_elem[DE_CONGESTION]);
+
+ switch (oct & 0x0f)
+ {
+ case 0: str = "Receiver ready"; break;
+ case 15: str = "Receiver not ready"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree,
+ tvb, curr_offset, 1,
+ "%s : Congestion level: %s",
+ a_bigbuf,
+ str);
+
+ curr_offset++;
+ curr_len--;
+
+ if (curr_len <= 0) return;
+
+ ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.5
+ */
+static void
+dtap_cc_connect(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
+
+ ELEM_OPT_TLV(0x4c, BSSAP_PDU_TYPE_DTAP, DE_CONN_NUM, "");
+
+ ELEM_OPT_TLV(0x4d, BSSAP_PDU_TYPE_DTAP, DE_CONN_SUB_ADDR, "");
+
+ ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
+
+ /* uplink only */
+
+ ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
+
+ ELEM_OPT_TLV(0x2d, BSSAP_PDU_TYPE_DTAP, DE_SI, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.7
+ */
+static void
+dtap_cc_disconnect(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
+
+ ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
+
+ ELEM_OPT_TLV(0x7b, BSSAP_PDU_TYPE_DTAP, DE_ALLOWED_ACTIONS, "");
+
+ /* uplink only */
+
+ ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.8
+ */
+static void
+dtap_cc_emerg_setup(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, "");
+
+ ELEM_OPT_TLV(0x2d, BSSAP_PDU_TYPE_DTAP, DE_SI, "");
+
+ ELEM_OPT_TLV(0x40, BSSAP_PDU_TYPE_DTAP, DE_SUP_CODEC_LIST, "");
+
+ ELEM_OPT_TLV(0x2e, BSSAP_PDU_TYPE_DTAP, DE_SRVC_CAT, " Emergency");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.9
+ */
+static void
+dtap_cc_facility(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ /* uplink only */
+
+ ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.12
+ */
+static void
+dtap_cc_hold_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.13
+ */
+static void
+dtap_cc_modify(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, "");
+
+ ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, "");
+
+ ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, "");
+
+ ELEM_OPT_T(0xa3, BSSAP_PDU_TYPE_DTAP, DE_REV_CALL_SETUP_DIR, "");
+
+ ELEM_OPT_T(0xa4, BSSAP_PDU_TYPE_DTAP, DE_IMM_MOD_IND, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.14
+ */
+static void
+dtap_cc_modify_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, "");
+
+ ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, "");
+
+ ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, "");
+
+ ELEM_OPT_T(0xa3, BSSAP_PDU_TYPE_DTAP, DE_REV_CALL_SETUP_DIR, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.15
+ */
+static void
+dtap_cc_modify_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, "");
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, "");
+
+ ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.16
+ */
+static void
+dtap_cc_notify(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_NOT_IND);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.17
+ */
+static void
+dtap_cc_progress(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
+
+ ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.17a
+ */
+static void
+dtap_cc_cc_est(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_SETUP_CONTAINER, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.17b
+ */
+static void
+dtap_cc_cc_est_conf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " Repeat indicator");
+
+ ELEM_MAND_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 1");
+
+ ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 2");
+
+ ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ ELEM_OPT_TLV(0x40, BSSAP_PDU_TYPE_DTAP, DE_SUP_CODEC_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.18
+ */
+static void
+dtap_cc_release(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, " 2");
+
+ ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
+
+ /* uplink only */
+
+ ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.18a
+ */
+static void
+dtap_cc_recall(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RECALL_TYPE);
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.19
+ */
+static void
+dtap_cc_release_complete(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_OPT_TLV(0x08, BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
+
+ /* uplink only */
+
+ ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.22
+ */
+static void
+dtap_cc_retrieve_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.23
+ */
+static void
+dtap_cc_setup(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " BC repeat indicator");
+
+ ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 1");
+
+ ELEM_OPT_TLV(0x04, BSSAP_PDU_TYPE_DTAP, DE_BEARER_CAP, " 2");
+
+ ELEM_OPT_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ ELEM_OPT_TLV(0x1e, BSSAP_PDU_TYPE_DTAP, DE_PROG_IND, "");
+
+ ELEM_OPT_TV(0x34, BSSAP_PDU_TYPE_DTAP, DE_SIGNAL, "");
+
+ ELEM_OPT_TLV(0x5c, BSSAP_PDU_TYPE_DTAP, DE_CLG_PARTY_BCD_NUM, "");
+
+ ELEM_OPT_TLV(0x5d, BSSAP_PDU_TYPE_DTAP, DE_CLG_PARTY_SUB_ADDR, "");
+
+ ELEM_OPT_TLV(0x5e, BSSAP_PDU_TYPE_DTAP, DE_CLD_PARTY_BCD_NUM, "");
+
+ ELEM_OPT_TLV(0x6d, BSSAP_PDU_TYPE_DTAP, DE_CLD_PARTY_SUB_ADDR, "");
+
+ ELEM_OPT_TLV(0x74, BSSAP_PDU_TYPE_DTAP, DE_RED_PARTY_BCD_NUM, "");
+
+ ELEM_OPT_TLV(0x75, BSSAP_PDU_TYPE_DTAP, DE_RED_PARTY_SUB_ADDR, "");
+
+ ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " LLC repeat indicator");
+
+ ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, " 1");
+
+ ELEM_OPT_TLV(0x7c, BSSAP_PDU_TYPE_DTAP, DE_LLC, " 2");
+
+ ELEM_OPT_TV_SHORT(0xd0, BSSAP_PDU_TYPE_DTAP, DE_REPEAT_IND, " HLC repeat indicator");
+
+ ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, " 1");
+
+ ELEM_OPT_TLV(0x7d, BSSAP_PDU_TYPE_DTAP, DE_HLC, " 2");
+
+ ELEM_OPT_TLV(0x7e, BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
+
+ /* downlink only */
+
+ ELEM_OPT_TV_SHORT(0x80, BSSAP_PDU_TYPE_DTAP, DE_PRIO, "");
+
+ ELEM_OPT_TLV(0x19, BSSAP_PDU_TYPE_DTAP, DE_ALERT_PATTERN, "");
+
+ ELEM_OPT_TLV(0x2f, BSSAP_PDU_TYPE_DTAP, DE_NET_CC_CAP, "");
+
+ ELEM_OPT_TLV(0x3a, BSSAP_PDU_TYPE_DTAP, DE_CAUSE_NO_CLI, "");
+
+ /* uplink only */
+
+ ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
+
+ ELEM_OPT_T(0xa1, BSSAP_PDU_TYPE_DTAP, DE_FOP, "");
+
+ ELEM_OPT_T(0xa2, BSSAP_PDU_TYPE_DTAP, DE_CTS_PERM, "");
+
+ ELEM_OPT_TLV(0x15, BSSAP_PDU_TYPE_DTAP, DE_CC_CAP, "");
+
+ ELEM_OPT_TLV(0x1d, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, " $(CCBS)$ (advanced recall alignment)");
+
+ ELEM_OPT_TLV(0x1b, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, " (recall alignment Not essential) $(CCBS)$");
+
+ ELEM_OPT_TLV(0x2d, BSSAP_PDU_TYPE_DTAP, DE_SI, "");
+
+ ELEM_OPT_TLV(0x40, BSSAP_PDU_TYPE_DTAP, DE_SUP_CODEC_LIST, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.23a
+ */
+static void
+dtap_cc_start_cc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_OPT_TLV(0x15, BSSAP_PDU_TYPE_DTAP, DE_CC_CAP, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.24
+ */
+static void
+dtap_cc_start_dtmf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TV(0x2c, BSSAP_PDU_TYPE_DTAP, DE_KEYPAD_FACILITY, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.25
+ */
+static void
+dtap_cc_start_dtmf_ack(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_TV(0x2c, BSSAP_PDU_TYPE_DTAP, DE_KEYPAD_FACILITY, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.26
+ */
+static void
+dtap_cc_start_dtmf_rej(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.27
+ */
+static void
+dtap_cc_status(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CAUSE, "");
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_CALL_STATE);
+
+ ELEM_OPT_TLV(0x24, BSSAP_PDU_TYPE_DTAP, DE_AUX_STATES, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [4] 9.3.31
+ */
+static void
+dtap_cc_user_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_USER_USER, "");
+
+ ELEM_OPT_T(0xa0, BSSAP_PDU_TYPE_DTAP, DE_MORE_DATA, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [6] 2.4.2
+ */
+static void
+dtap_ss_register(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_TLV(0x1c, BSSAP_PDU_TYPE_DTAP, DE_FACILITY, "");
+
+ ELEM_OPT_TLV(0x7f, BSSAP_PDU_TYPE_DTAP, DE_SS_VER_IND, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [5] 7.2.1
+ */
+static void
+dtap_sms_cp_data(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_CP_USER_DATA, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [5] 7.2.3
+ */
+static void
+dtap_sms_cp_error(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_CP_CAUSE);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [5] 7.3.1.1
+ */
+static void
+rp_data_n_ms(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+ g_pinfo->p2p_dir = P2P_DIR_SENT;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_ORIG_ADDR, "");
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_DEST_ADDR, "");
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [5] 7.3.1.2
+ */
+static void
+rp_data_ms_n(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+ g_pinfo->p2p_dir = P2P_DIR_RECV;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_ORIG_ADDR, "");
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_DEST_ADDR, "");
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [5] 7.3.2
+ */
+static void
+rp_smma(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [5] 7.3.3
+ */
+static void
+rp_ack_n_ms(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+ g_pinfo->p2p_dir = P2P_DIR_SENT;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
+
+ ELEM_OPT_TLV(0x41, BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [5] 7.3.3
+ */
+static void
+rp_ack_ms_n(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+ g_pinfo->p2p_dir = P2P_DIR_RECV;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
+
+ ELEM_OPT_TLV(0x41, BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [5] 7.3.4
+ */
+static void
+rp_error_n_ms(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_FALSE;
+ g_pinfo->p2p_dir = P2P_DIR_SENT;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_CAUSE, "");
+
+ ELEM_OPT_TLV(0x41, BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+/*
+ * [5] 7.3.4
+ */
+static void
+rp_error_ms_n(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
+{
+ guint32 curr_offset;
+ guint32 consumed;
+ guint curr_len;
+
+ curr_offset = offset;
+ curr_len = len;
+
+ is_uplink = IS_UPLINK_TRUE;
+ g_pinfo->p2p_dir = P2P_DIR_RECV;
+
+ ELEM_MAND_V(BSSAP_PDU_TYPE_DTAP, DE_RP_MESSAGE_REF);
+
+ ELEM_MAND_LV(BSSAP_PDU_TYPE_DTAP, DE_RP_CAUSE, "");
+
+ ELEM_OPT_TLV(0x41, BSSAP_PDU_TYPE_DTAP, DE_RP_USER_DATA, "");
+
+ EXTRANEOUS_DATA_CHECK(curr_len, 0);
+}
+
+#define NUM_GSM_DTAP_MSG_MM (sizeof(gsm_a_dtap_msg_mm_strings)/sizeof(value_string))
+static gint ett_gsm_dtap_msg_mm[NUM_GSM_DTAP_MSG_MM];
+static void (*dtap_msg_mm_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ dtap_mm_imsi_det_ind, /* IMSI Detach Indication */
+ dtap_mm_loc_upd_acc, /* Location Updating Accept */
+ dtap_mm_loc_upd_rej, /* Location Updating Reject */
+ dtap_mm_loc_upd_req, /* Location Updating Request */
+ NULL /* no associated data */, /* Authentication Reject */
+ dtap_mm_auth_req, /* Authentication Request */
+ dtap_mm_auth_resp, /* Authentication Response */
+ dtap_mm_auth_fail, /* Authentication Failure */
+ dtap_mm_id_req, /* Identity Request */
+ dtap_mm_id_resp, /* Identity Response */
+ dtap_mm_tmsi_realloc_cmd, /* TMSI Reallocation Command */
+ NULL /* no associated data */, /* TMSI Reallocation Complete */
+ NULL /* no associated data */, /* CM Service Accept */
+ dtap_mm_cm_srvc_rej, /* CM Service Reject */
+ NULL /* no associated data */, /* CM Service Abort */
+ dtap_mm_cm_srvc_req, /* CM Service Request */
+ dtap_mm_cm_srvc_prompt, /* CM Service Prompt */
+ NULL, /* Reserved: was allocated in earlier phases of the protocol */
+ dtap_mm_cm_reestab_req, /* CM Re-establishment Request */
+ dtap_mm_abort, /* Abort */
+ NULL /* no associated data */, /* MM Null */
+ dtap_mm_mm_status, /* MM Status */
+ dtap_mm_mm_info, /* MM Information */
+ NULL, /* NONE */
+};
+
+#define NUM_GSM_DTAP_MSG_RR (sizeof(gsm_a_dtap_msg_rr_strings)/sizeof(value_string))
+static gint ett_gsm_dtap_msg_rr[NUM_GSM_DTAP_MSG_RR];
+static void (*dtap_msg_rr_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ NULL, /* RR Initialisation Request */
+ NULL, /* Additional Assignment */
+ NULL, /* Immediate Assignment */
+ NULL, /* Immediate Assignment Extended */
+ NULL, /* Immediate Assignment Reject */
+
+ NULL, /* DTM Assignment Failure */
+ NULL, /* DTM Reject */
+ NULL, /* DTM Request */
+ NULL, /* Main DCCH Assignment Command */
+ NULL, /* Packet Assignment Command */
+
+ NULL, /* Ciphering Mode Command */
+ NULL, /* Ciphering Mode Complete */
+
+ NULL, /* Configuration Change Command */
+ NULL, /* Configuration Change Ack. */
+ NULL, /* Configuration Change Reject */
+
+ NULL, /* Assignment Command */
+ NULL, /* Assignment Complete */
+ NULL, /* Assignment Failure */
+ NULL, /* Handover Command */
+ NULL, /* Handover Complete */
+ NULL, /* Handover Failure */
+ NULL, /* Physical Information */
+ NULL, /* DTM Assignment Command */
+
+ NULL, /* RR-cell Change Order */
+ NULL, /* PDCH Assignment Command */
+
+ NULL, /* Channel Release */
+ NULL, /* Partial Release */
+ NULL, /* Partial Release Complete */
+
+ NULL, /* Paging Request Type 1 */
+ NULL, /* Paging Request Type 2 */
+ NULL, /* Paging Request Type 3 */
+ dtap_rr_paging_resp, /* Paging Response */
+ NULL, /* Notification/NCH */
+ NULL, /* Reserved */
+ NULL, /* Notification/Response */
+
+ NULL, /* Reserved */
+
+/* NULL, * Utran Classmark Change * CONFLICTS WITH Handover To UTRAN Command */
+ NULL, /* UE RAB Preconfiguration */
+ NULL, /* cdma2000 Classmark Change */
+
+ NULL, /* System Information Type 8 */
+ NULL, /* System Information Type 1 */
+ NULL, /* System Information Type 2 */
+ NULL, /* System Information Type 3 */
+ NULL, /* System Information Type 4 */
+ NULL, /* System Information Type 5 */
+ NULL, /* System Information Type 6 */
+ NULL, /* System Information Type 7 */
+
+ NULL, /* System Information Type 2bis */
+ NULL, /* System Information Type 2ter */
+ NULL, /* System Information Type 2quater */
+ NULL, /* System Information Type 5bis */
+ NULL, /* System Information Type 5ter */
+ NULL, /* System Information Type 9 */
+ NULL, /* System Information Type 13 */
+
+ NULL, /* System Information Type 16 */
+ NULL, /* System Information Type 17 */
+
+ NULL, /* System Information Type 18 */
+ NULL, /* System Information Type 19 */
+ NULL, /* System Information Type 20 */
+
+ NULL, /* Channel Mode Modify */
+ dtap_rr_rr_status, /* RR Status */
+ NULL, /* Channel Mode Modify Acknowledge */
+ NULL, /* Frequency Redefinition */
+ NULL, /* Measurement Report */
+ NULL, /* Classmark Change */
+ NULL, /* Classmark Enquiry */
+ NULL, /* Extended Measurement Report */
+ NULL, /* Extended Measurement Order */
+ NULL, /* GPRS Suspension Request */
+
+ NULL, /* VGCS Uplink Grant */
+ NULL, /* Uplink Release */
+ NULL, /* Reserved */
+ NULL, /* Uplink Busy */
+ NULL, /* Talker Indication */
+
+ NULL, /* UTRAN Classmark Change/Handover To UTRAN Command */ /* spec conflict */
+
+ NULL, /* Application Information */
+
+ NULL, /* NONE */
+};
+
+#define NUM_GSM_DTAP_MSG_CC (sizeof(gsm_a_dtap_msg_cc_strings)/sizeof(value_string))
+static gint ett_gsm_dtap_msg_cc[NUM_GSM_DTAP_MSG_CC];
+static void (*dtap_msg_cc_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ dtap_cc_alerting, /* Alerting */
+ dtap_cc_call_conf, /* Call Confirmed */
+ dtap_cc_call_proceed, /* Call Proceeding */
+ dtap_cc_connect, /* Connect */
+ NULL /* no associated data */, /* Connect Acknowledge */
+ dtap_cc_emerg_setup, /* Emergency Setup */
+ dtap_cc_progress, /* Progress */
+ dtap_cc_cc_est, /* CC-Establishment */
+ dtap_cc_cc_est_conf, /* CC-Establishment Confirmed */
+ dtap_cc_recall, /* Recall */
+ dtap_cc_start_cc, /* Start CC */
+ dtap_cc_setup, /* Setup */
+ dtap_cc_modify, /* Modify */
+ dtap_cc_modify_complete, /* Modify Complete */
+ dtap_cc_modify_rej, /* Modify Reject */
+ dtap_cc_user_info, /* User Information */
+ NULL /* no associated data */, /* Hold */
+ NULL /* no associated data */, /* Hold Acknowledge */
+ dtap_cc_hold_rej, /* Hold Reject */
+ NULL /* no associated data */, /* Retrieve */
+ NULL /* no associated data */, /* Retrieve Acknowledge */
+ dtap_cc_retrieve_rej, /* Retrieve Reject */
+ dtap_cc_disconnect, /* Disconnect */
+ dtap_cc_release, /* Release */
+ dtap_cc_release_complete, /* Release Complete */
+ dtap_cc_congestion_control, /* Congestion Control */
+ dtap_cc_notify, /* Notify */
+ dtap_cc_status, /* Status */
+ NULL /* no associated data */, /* Status Enquiry */
+ dtap_cc_start_dtmf, /* Start DTMF */
+ NULL /* no associated data */, /* Stop DTMF */
+ NULL /* no associated data */, /* Stop DTMF Acknowledge */
+ dtap_cc_start_dtmf_ack, /* Start DTMF Acknowledge */
+ dtap_cc_start_dtmf_rej, /* Start DTMF Reject */
+ dtap_cc_facility, /* Facility */
+ NULL, /* NONE */
+};
+
+#define NUM_GSM_DTAP_MSG_GMM (sizeof(gsm_a_dtap_msg_gmm_strings)/sizeof(value_string))
+static gint ett_gsm_dtap_msg_gmm[NUM_GSM_DTAP_MSG_GMM];
+static void (*dtap_msg_gmm_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ NULL, /* Attach Request */
+ NULL, /* Attach Accept */
+ NULL, /* Attach Complete */
+ NULL, /* Attach Reject */
+ NULL, /* Detach Request */
+ NULL, /* Detach Accept */
+ NULL, /* Routing Area Update Request */
+ NULL, /* Routing Area Update Accept */
+ NULL, /* Routing Area Update Complete */
+ NULL, /* Routing Area Update Reject */
+ NULL, /* Service Request */
+ NULL, /* Service Accept */
+ NULL, /* Service Reject */
+ NULL, /* P-TMSI Reallocation Command */
+ NULL, /* P-TMSI Reallocation Complete */
+ NULL, /* Authentication and Ciphering Req */
+ NULL, /* Authentication and Ciphering Resp */
+ NULL, /* Authentication and Ciphering Rej */
+ NULL, /* Authentication and Ciphering Failure */
+ NULL, /* Identity Request */
+ NULL, /* Identity Response */
+ NULL, /* GMM Status */
+ NULL, /* GMM Information */
+ NULL, /* NONE */
+};
+
+#define NUM_GSM_DTAP_MSG_SMS (sizeof(gsm_a_dtap_msg_sms_strings)/sizeof(value_string))
+static gint ett_gsm_dtap_msg_sms[NUM_GSM_DTAP_MSG_SMS];
+static void (*dtap_msg_sms_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ dtap_sms_cp_data, /* CP-DATA */
+ NULL /* no associated data */, /* CP-ACK */
+ dtap_sms_cp_error, /* CP-ERROR */
+ NULL, /* NONE */
+};
+
+#define NUM_GSM_DTAP_MSG_SM (sizeof(gsm_a_dtap_msg_sm_strings)/sizeof(value_string))
+static gint ett_gsm_dtap_msg_sm[NUM_GSM_DTAP_MSG_SM];
+static void (*dtap_msg_sm_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ NULL, /* Activate PDP Context Request */
+ NULL, /* Activate PDP Context Accept */
+ NULL, /* Activate PDP Context Reject */
+ NULL, /* Request PDP Context Activation */
+ NULL, /* Request PDP Context Activation rej. */
+ NULL, /* Deactivate PDP Context Request */
+ NULL, /* Deactivate PDP Context Accept */
+ NULL, /* Modify PDP Context Request(Network to MS direction) */
+ NULL, /* Modify PDP Context Accept (MS to network direction) */
+ NULL, /* Modify PDP Context Request(MS to network direction) */
+ NULL, /* Modify PDP Context Accept (Network to MS direction) */
+ NULL, /* Modify PDP Context Reject */
+ NULL, /* Activate Secondary PDP Context Request */
+ NULL, /* Activate Secondary PDP Context Accept */
+ NULL, /* Activate Secondary PDP Context Reject */
+ NULL, /* Reserved: was allocated in earlier phases of the protocol */
+ NULL, /* Reserved: was allocated in earlier phases of the protocol */
+ NULL, /* Reserved: was allocated in earlier phases of the protocol */
+ NULL, /* Reserved: was allocated in earlier phases of the protocol */
+ NULL, /* Reserved: was allocated in earlier phases of the protocol */
+ NULL, /* SM Status */
+ NULL, /* NONE */
+};
+
+#define NUM_GSM_DTAP_MSG_SS (sizeof(gsm_a_dtap_msg_ss_strings)/sizeof(value_string))
+static gint ett_gsm_dtap_msg_ss[NUM_GSM_DTAP_MSG_SS];
+static void (*dtap_msg_ss_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ dtap_cc_release_complete, /* Release Complete */
+ dtap_cc_facility, /* Facility */
+ dtap_ss_register, /* Register */
+ NULL, /* NONE */
+};
+
+#define NUM_GSM_RP_MSG (sizeof(gsm_rp_msg_strings)/sizeof(value_string))
+static gint ett_gsm_rp_msg[NUM_GSM_RP_MSG];
+static void (*rp_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len) = {
+ rp_data_ms_n, /* RP-DATA (MS to Network) */
+ rp_data_n_ms, /* RP-DATA (Network to MS */
+ rp_ack_ms_n, /* RP-ACK (MS to Network) */
+ rp_ack_n_ms, /* RP-ACK (Network to MS) */
+ rp_error_ms_n, /* RP-ERROR (MS to Network) */
+ rp_error_n_ms, /* RP-ERROR (Network to MS) */
+ rp_smma, /* RP-SMMA (MS to Network) */
+ NULL, /* NONE */
+};
+
+/* GENERIC DISSECTOR FUNCTIONS */
+
+static void
+dissect_rp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 oct;
+ guint32 offset, saved_offset;
+ guint32 len;
+ gint idx;
+ proto_item *rp_item = NULL;
+ proto_tree *rp_tree = NULL;
+ gchar *str;
+
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, "(RP) ");
+ }
+
+ /*
+ * In the interest of speed, if "tree" is NULL, don't do any work
+ * not necessary to generate protocol tree items.
+ */
+ if (!tree)
+ {
+ return;
+ }
+
+ offset = 0;
+ saved_offset = offset;
+
+ g_pinfo = pinfo;
+ g_tree = tree;
+
+ len = tvb_length(tvb);
+
+ /*
+ * add RP message name
+ */
+ oct = tvb_get_guint8(tvb, offset++);
+
+ str = my_match_strval((guint32) oct, gsm_rp_msg_strings, &idx);
+
+ /*
+ * create the protocol tree
+ */
+ if (str == NULL)
+ {
+ rp_item =
+ proto_tree_add_protocol_format(tree, proto_a_rp, tvb, 0, len,
+ "GSM A-I/F RP - Unknown RP Message Type (0x%02x)",
+ oct);
+
+ rp_tree = proto_item_add_subtree(rp_item, ett_rp_msg);
+ }
+ else
+ {
+ rp_item =
+ proto_tree_add_protocol_format(tree, proto_a_rp, tvb, 0, -1,
+ "GSM A-I/F RP - %s",
+ str);
+
+ rp_tree = proto_item_add_subtree(rp_item, ett_gsm_rp_msg[idx]);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
+ }
+ }
+
+ /*
+ * add RP message name
+ */
+ proto_tree_add_uint_format(rp_tree, hf_gsm_a_rp_msg_type,
+ tvb, saved_offset, 1, oct, "Message Type");
+
+ if (str == NULL) return;
+
+ if ((len - offset) <= 0) return;
+
+ /*
+ * decode elements
+ */
+ if (rp_msg_fcn[idx] == NULL)
+ {
+ proto_tree_add_text(rp_tree,
+ tvb, offset, len - offset,
+ "Message Elements");
+ }
+ else
+ {
+ (*rp_msg_fcn[idx])(tvb, rp_tree, offset, len - offset);
+ }
+}
+
+
+static void
+dissect_bssmap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ static gsm_a_tap_rec_t tap_rec[4];
+ static gsm_a_tap_rec_t *tap_p;
+ static int tap_current=0;
+ guint8 oct;
+ guint32 offset, saved_offset;
+ guint32 len;
+ gint idx;
+ proto_item *bssmap_item = NULL;
+ proto_tree *bssmap_tree = NULL;
+ gchar *str;
+
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, "(BSSMAP) ");
+ }
+
+ /*
+ * set tap record pointer
+ */
+ tap_current++;
+ if (tap_current == 4)
+ {
+ tap_current = 0;
+ }
+ tap_p = &tap_rec[tap_current];
+
+
+ offset = 0;
+ saved_offset = offset;
+
+ g_pinfo = pinfo;
+ g_tree = tree;
+
+ len = tvb_length(tvb);
+
+ /*
+ * add BSSMAP message name
+ */
+ oct = tvb_get_guint8(tvb, offset++);
+
+ str = my_match_strval((guint32) oct, gsm_a_bssmap_msg_strings, &idx);
+
+ /*
+ * create the protocol tree
+ */
+ if (str == NULL)
+ {
+ bssmap_item =
+ proto_tree_add_protocol_format(tree, proto_a_bssmap, tvb, 0, len,
+ "GSM A-I/F BSSMAP - Unknown BSSMAP Message Type (0x%02x)",
+ oct);
+
+ bssmap_tree = proto_item_add_subtree(bssmap_item, ett_bssmap_msg);
+ }
+ else
+ {
+ bssmap_item =
+ proto_tree_add_protocol_format(tree, proto_a_bssmap, tvb, 0, -1,
+ "GSM A-I/F BSSMAP - %s",
+ str);
+
+ bssmap_tree = proto_item_add_subtree(bssmap_item, ett_gsm_bssmap_msg[idx]);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
+ }
+ }
+
+ /*
+ * add BSSMAP message name
+ */
+ proto_tree_add_uint_format(bssmap_tree, hf_gsm_a_bssmap_msg_type,
+ tvb, saved_offset, 1, oct, "Message Type");
+
+ tap_p->pdu_type = BSSAP_PDU_TYPE_BSSMAP;
+ tap_p->message_type = oct;
+
+ tap_queue_packet(gsm_a_tap, pinfo, tap_p);
+
+ if (str == NULL) return;
+
+ if ((len - offset) <= 0) return;
+
+ /*
+ * decode elements
+ */
+ if (bssmap_msg_fcn[idx] == NULL)
+ {
+ proto_tree_add_text(bssmap_tree,
+ tvb, offset, len - offset,
+ "Message Elements");
+ }
+ else
+ {
+ (*bssmap_msg_fcn[idx])(tvb, bssmap_tree, offset, len - offset);
+ }
+}
+
+
+static void
+dissect_dtap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ static gsm_a_tap_rec_t tap_rec[4];
+ static gsm_a_tap_rec_t *tap_p;
+ static int tap_current=0;
+ void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len);
+ guint8 oct;
+ guint8 pd;
+ guint32 offset;
+ guint32 len;
+ guint32 oct_1, oct_2;
+ gint idx;
+ proto_item *dtap_item = NULL;
+ proto_tree *dtap_tree = NULL;
+ proto_item *oct_1_item = NULL;
+ proto_tree *pd_tree = NULL;
+ gchar *msg_str;
+ const gchar *str;
+ gint ett_tree;
+ gint ti;
+ int hf_idx;
+ gboolean nsd;
+
+
+ len = tvb_length(tvb);
+
+ if (len < 2)
+ {
+ /*
+ * too short to be DTAP
+ */
+ call_dissector(data_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, "(DTAP) ");
+ }
+
+ /*
+ * set tap record pointer
+ */
+ tap_current++;
+ if (tap_current == 4)
+ {
+ tap_current = 0;
+ }
+ tap_p = &tap_rec[tap_current];
+
+
+ offset = 0;
+ oct_2 = 0;
+
+ g_pinfo = pinfo;
+ g_tree = tree;
+
+ /*
+ * get protocol discriminator
+ */
+ oct_1 = tvb_get_guint8(tvb, offset++);
+
+ if ((((oct_1 & DTAP_TI_MASK) >> 4) & DTAP_TIE_PRES_MASK) == DTAP_TIE_PRES_MASK)
+ {
+ /*
+ * eventhough we don't know if a TI should be in the message yet
+ * we rely on the TI/SKIP indicator to be 0 to avoid taking this
+ * octet
+ */
+ oct_2 = tvb_get_guint8(tvb, offset++);
+ }
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ pd = oct_1 & DTAP_PD_MASK;
+ ti = -1;
+ msg_str = NULL;
+ ett_tree = -1;
+ hf_idx = -1;
+ msg_fcn = NULL;
+ nsd = FALSE;
+
+ /*
+ * octet 1
+ */
+ switch (pd)
+ {
+ case 3:
+ str = gsm_a_pd_str[pd];
+ msg_str = my_match_strval((guint32) (oct & DTAP_CC_IEI_MASK), gsm_a_dtap_msg_cc_strings, &idx);
+ ett_tree = ett_gsm_dtap_msg_cc[idx];
+ hf_idx = hf_gsm_a_dtap_msg_cc_type;
+ msg_fcn = dtap_msg_cc_fcn[idx];
+ ti = (oct_1 & DTAP_TI_MASK) >> 4;
+ nsd = TRUE;
+ break;
+
+ case 5:
+ str = gsm_a_pd_str[pd];
+ msg_str = my_match_strval((guint32) (oct & DTAP_MM_IEI_MASK), gsm_a_dtap_msg_mm_strings, &idx);
+ ett_tree = ett_gsm_dtap_msg_mm[idx];
+ hf_idx = hf_gsm_a_dtap_msg_mm_type;
+ msg_fcn = dtap_msg_mm_fcn[idx];
+ nsd = TRUE;
+ break;
+
+ case 6:
+ str = gsm_a_pd_str[pd];
+ msg_str = my_match_strval((guint32) (oct & DTAP_RR_IEI_MASK), gsm_a_dtap_msg_rr_strings, &idx);
+ ett_tree = ett_gsm_dtap_msg_rr[idx];
+ hf_idx = hf_gsm_a_dtap_msg_rr_type;
+ msg_fcn = dtap_msg_rr_fcn[idx];
+ break;
+
+ case 8:
+ str = gsm_a_pd_str[pd];
+ msg_str = my_match_strval((guint32) (oct & DTAP_GMM_IEI_MASK), gsm_a_dtap_msg_gmm_strings, &idx);
+ ett_tree = ett_gsm_dtap_msg_gmm[idx];
+ hf_idx = hf_gsm_a_dtap_msg_gmm_type;
+ msg_fcn = dtap_msg_gmm_fcn[idx];
+ break;
+
+ case 9:
+ str = gsm_a_pd_str[pd];
+ msg_str = my_match_strval((guint32) (oct & DTAP_SMS_IEI_MASK), gsm_a_dtap_msg_sms_strings, &idx);
+ ett_tree = ett_gsm_dtap_msg_sms[idx];
+ hf_idx = hf_gsm_a_dtap_msg_sms_type;
+ msg_fcn = dtap_msg_sms_fcn[idx];
+ ti = (oct_1 & DTAP_TI_MASK) >> 4;
+ break;
+
+ case 10:
+ str = gsm_a_pd_str[pd];
+ msg_str = my_match_strval((guint32) (oct & DTAP_SM_IEI_MASK), gsm_a_dtap_msg_sm_strings, &idx);
+ ett_tree = ett_gsm_dtap_msg_sm[idx];
+ hf_idx = hf_gsm_a_dtap_msg_sm_type;
+ msg_fcn = dtap_msg_sm_fcn[idx];
+ ti = (oct_1 & DTAP_TI_MASK) >> 4;
+ break;
+
+ case 11:
+ str = gsm_a_pd_str[pd];
+ msg_str = my_match_strval((guint32) (oct & DTAP_SS_IEI_MASK), gsm_a_dtap_msg_ss_strings, &idx);
+ ett_tree = ett_gsm_dtap_msg_ss[idx];
+ hf_idx = hf_gsm_a_dtap_msg_ss_type;
+ msg_fcn = dtap_msg_ss_fcn[idx];
+ ti = (oct_1 & DTAP_TI_MASK) >> 4;
+ nsd = TRUE;
+ break;
+
+ default:
+ str = gsm_a_pd_str[pd];
+ break;
+ }
+
+ /*
+ * create the protocol tree
+ */
+ if (msg_str == NULL)
+ {
+ dtap_item =
+ proto_tree_add_protocol_format(tree, proto_a_dtap, tvb, 0, len,
+ "GSM A-I/F DTAP - Unknown DTAP Message Type (0x%02x)",
+ oct);
+
+ dtap_tree = proto_item_add_subtree(dtap_item, ett_dtap_msg);
+ }
+ else
+ {
+ dtap_item =
+ proto_tree_add_protocol_format(tree, proto_a_dtap, tvb, 0, -1,
+ "GSM A-I/F DTAP - %s",
+ msg_str);
+
+ dtap_tree = proto_item_add_subtree(dtap_item, ett_tree);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", msg_str);
+ }
+ }
+
+ oct_1_item =
+ proto_tree_add_text(dtap_tree,
+ tvb, 0, 1,
+ "Protocol Discriminator: %s",
+ str);
+
+ pd_tree = proto_item_add_subtree(oct_1_item, ett_dtap_oct_1);
+
+ if (ti == -1)
+ {
+ other_decode_bitfield_value(a_bigbuf, oct_1, 0xf0, 8);
+ proto_tree_add_text(pd_tree,
+ tvb, 0, 1,
+ "%s : Skip Indicator",
+ a_bigbuf);
+ }
+ else
+ {
+ other_decode_bitfield_value(a_bigbuf, oct_1, 0x80, 8);
+ proto_tree_add_text(pd_tree,
+ tvb, 0, 1,
+ "%s : TI flag: %s",
+ a_bigbuf,
+ ((oct_1 & 0x80) ? "allocated by receiver" : "allocated by sender"));
+
+ if ((ti & DTAP_TIE_PRES_MASK) == DTAP_TIE_PRES_MASK)
+ {
+ /* ti is extended to next octet */
+
+ other_decode_bitfield_value(a_bigbuf, oct_1, 0x70, 8);
+ proto_tree_add_text(pd_tree,
+ tvb, 0, 1,
+ "%s : TIO: The TI value is given by the TIE in octet 2",
+ a_bigbuf);
+ }
+ else
+ {
+ other_decode_bitfield_value(a_bigbuf, oct_1, 0x70, 8);
+ proto_tree_add_text(pd_tree,
+ tvb, 0, 1,
+ "%s : TIO: %u",
+ a_bigbuf,
+ ti & DTAP_TIE_PRES_MASK);
+ }
+ }
+
+ other_decode_bitfield_value(a_bigbuf, oct_1, DTAP_PD_MASK, 8);
+ proto_tree_add_text(pd_tree,
+ tvb, 0, 1,
+ "%s : Protocol Discriminator: %u",
+ a_bigbuf,
+ pd);
+
+ if ((ti != -1) &&
+ (ti & DTAP_TIE_PRES_MASK) == DTAP_TIE_PRES_MASK)
+ {
+ other_decode_bitfield_value(a_bigbuf, oct_2, 0x80, 8);
+ proto_tree_add_text(pd_tree,
+ tvb, 1, 1,
+ "%s : Extension",
+ a_bigbuf);
+
+ other_decode_bitfield_value(a_bigbuf, oct_2, DTAP_TIE_MASK, 8);
+ proto_tree_add_text(pd_tree,
+ tvb, 1, 1,
+ "%s : TIE: %u",
+ a_bigbuf,
+ oct_2 & DTAP_TIE_MASK);
+ }
+
+ /*
+ * N(SD)
+ */
+ if ((pinfo->p2p_dir == P2P_DIR_RECV) &&
+ nsd)
+ {
+ /* XXX */
+ }
+
+ /*
+ * add DTAP message name
+ */
+ proto_tree_add_uint_format(dtap_tree, hf_idx,
+ tvb, offset, 1, oct,
+ "Message Type");
+
+ offset++;
+
+ tap_p->pdu_type = BSSAP_PDU_TYPE_DTAP;
+ tap_p->message_type = (nsd ? (oct & 0x3f) : oct);
+ tap_p->protocol_disc = pd;
+
+ tap_queue_packet(gsm_a_tap, pinfo, tap_p);
+
+ if (msg_str == NULL) return;
+
+ if ((len - offset) <= 0) return;
+
+ /*
+ * decode elements
+ */
+ if (msg_fcn == NULL)
+ {
+ proto_tree_add_text(dtap_tree,
+ tvb, offset, len - offset,
+ "Message Elements");
+ }
+ else
+ {
+ (*msg_fcn)(tvb, dtap_tree, offset, len - offset);
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_gsm_a(void)
+{
+ guint i;
+ guint last_offset;
+
+ /* Setup list of header fields */
+
+ static hf_register_info hf[] =
+ {
+ { &hf_gsm_a_bssmap_msg_type,
+ { "BSSMAP Message Type", "gsm_a.bssmap_msgtype",
+ FT_UINT8, BASE_HEX, VALS(gsm_a_bssmap_msg_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dtap_msg_mm_type,
+ { "DTAP Mobility Management Message Type", "gsm_a.dtap_msg_mm_type",
+ FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_mm_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dtap_msg_rr_type,
+ { "DTAP Radio Resources Management Message Type", "gsm_a.dtap_msg_rr_type",
+ FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_rr_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dtap_msg_cc_type,
+ { "DTAP Call Control Message Type", "gsm_a.dtap_msg_cc_type",
+ FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_cc_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dtap_msg_gmm_type,
+ { "DTAP GPRS Mobility Management Message Type", "gsm_a.dtap_msg_gmm_type",
+ FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_gmm_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dtap_msg_sms_type,
+ { "DTAP Short Message Service Message Type", "gsm_a.dtap_msg_sms_type",
+ FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_sms_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dtap_msg_sm_type,
+ { "DTAP GPRS Session Management Message Type", "gsm_a.dtap_msg_sm_type",
+ FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_sm_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dtap_msg_ss_type,
+ { "DTAP Non call Supplementary Service Message Type", "gsm_a.dtap_msg_ss_type",
+ FT_UINT8, BASE_HEX, VALS(gsm_a_dtap_msg_ss_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_rp_msg_type,
+ { "RP Message Type", "gsm_a.rp_msg_type",
+ FT_UINT8, BASE_HEX, VALS(gsm_rp_msg_strings), 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_bssmap_elem_id,
+ { "Element ID", "gsm_a_bssmap.elem_id",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dtap_elem_id,
+ { "Element ID", "gsm_a_dtap.elem_id",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_length,
+ { "Length", "gsm_a.len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_none,
+ { "Sub tree", "gsm_a.none",
+ FT_NONE, 0, 0, 0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_imsi,
+ { "IMSI", "gsm_a.imsi",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_tmsi,
+ { "TMSI/P-TMSI", "gsm_a.tmsi",
+ FT_UINT32, BASE_HEX, 0, 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_imei,
+ { "IMEI", "gsm_a.imei",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_imeisv,
+ { "IMEISV", "gsm_a.imeisv",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_cld_party_bcd_num,
+ { "Called Party BCD Number", "gsm_a.cld_party_bcd_num",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_clg_party_bcd_num,
+ { "Calling Party BCD Number", "gsm_a.clg_party_bcd_num",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_cell_ci,
+ { "Cell CI", "gsm_a.cell_ci",
+ FT_UINT16, BASE_HEX, 0, 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_cell_lac,
+ { "Cell LAC", "gsm_a.cell_lac",
+ FT_UINT16, BASE_HEX, 0, 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dlci_cc,
+ { "Control Channel", "bssap.dlci.cc",
+ FT_UINT8, BASE_HEX, VALS(bssap_cc_values), 0xc0,
+ "", HFILL}
+ },
+ { &hf_gsm_a_dlci_spare,
+ { "Spare", "bssap.dlci.spare",
+ FT_UINT8, BASE_HEX, NULL, 0x38,
+ "", HFILL}
+ },
+ { &hf_gsm_a_dlci_sapi,
+ { "SAPI", "bssap.dlci.sapi",
+ FT_UINT8, BASE_HEX, VALS(bssap_sapi_values), 0x07,
+ "", HFILL}
+ },
+ { &hf_gsm_a_bssmap_cause,
+ { "BSSMAP Cause", "gsm_a_bssmap.cause",
+ FT_UINT8, BASE_HEX, 0, 0x0,
+ "", HFILL }
+ },
+ { &hf_gsm_a_dtap_cause,
+ { "DTAP Cause", "gsm_a_dtap.cause",
+ FT_UINT8, BASE_HEX, 0, 0x0,
+ "", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+#define NUM_INDIVIDUAL_ELEMS 31
+ static gint *ett[NUM_INDIVIDUAL_ELEMS + NUM_GSM_BSSMAP_MSG +
+ NUM_GSM_DTAP_MSG_MM + NUM_GSM_DTAP_MSG_RR + NUM_GSM_DTAP_MSG_CC +
+ NUM_GSM_DTAP_MSG_GMM + NUM_GSM_DTAP_MSG_SMS +
+ NUM_GSM_DTAP_MSG_SM + NUM_GSM_DTAP_MSG_SS + NUM_GSM_RP_MSG +
+ NUM_GSM_BSSMAP_ELEM + NUM_GSM_DTAP_ELEM +
+ NUM_GSM_SS_ETT];
+
+ ett[0] = &ett_bssmap_msg;
+ ett[1] = &ett_dtap_msg;
+ ett[2] = &ett_rp_msg;
+ ett[3] = &ett_elems;
+ ett[4] = &ett_elem;
+ ett[5] = &ett_dtap_oct_1;
+ ett[6] = &ett_cm_srvc_type;
+ ett[7] = &ett_gsm_enc_info;
+ ett[8] = &ett_cell_list;
+ ett[9] = &ett_dlci;
+ ett[10] = &ett_bc_oct_3a;
+ ett[11] = &ett_bc_oct_4;
+ ett[12] = &ett_bc_oct_5;
+ ett[13] = &ett_bc_oct_5a;
+ ett[14] = &ett_bc_oct_5b;
+ ett[15] = &ett_bc_oct_6;
+ ett[16] = &ett_bc_oct_6a;
+ ett[17] = &ett_bc_oct_6b;
+ ett[18] = &ett_bc_oct_6c;
+ ett[19] = &ett_bc_oct_6d;
+ ett[20] = &ett_bc_oct_6e;
+ ett[21] = &ett_bc_oct_6f;
+ ett[22] = &ett_bc_oct_6g;
+ ett[23] = &ett_bc_oct_7;
+
+ ett[24] = &ett_tc_component;
+ ett[25] = &ett_tc_invoke_id;
+ ett[26] = &ett_tc_linked_id;
+ ett[27] = &ett_tc_opr_code;
+ ett[28] = &ett_tc_err_code;
+ ett[29] = &ett_tc_prob_code;
+ ett[30] = &ett_tc_sequence;
+
+ last_offset = NUM_INDIVIDUAL_ELEMS;
+
+ for (i=0; i < NUM_GSM_BSSMAP_MSG; i++, last_offset++)
+ {
+ ett_gsm_bssmap_msg[i] = -1;
+ ett[last_offset] = &ett_gsm_bssmap_msg[i];
+ }
+
+ for (i=0; i < NUM_GSM_DTAP_MSG_MM; i++, last_offset++)
+ {
+ ett_gsm_dtap_msg_mm[i] = -1;
+ ett[last_offset] = &ett_gsm_dtap_msg_mm[i];
+ }
+
+ for (i=0; i < NUM_GSM_DTAP_MSG_RR; i++, last_offset++)
+ {
+ ett_gsm_dtap_msg_rr[i] = -1;
+ ett[last_offset] = &ett_gsm_dtap_msg_rr[i];
+ }
+
+ for (i=0; i < NUM_GSM_DTAP_MSG_CC; i++, last_offset++)
+ {
+ ett_gsm_dtap_msg_cc[i] = -1;
+ ett[last_offset] = &ett_gsm_dtap_msg_cc[i];
+ }
+
+ for (i=0; i < NUM_GSM_DTAP_MSG_GMM; i++, last_offset++)
+ {
+ ett_gsm_dtap_msg_gmm[i] = -1;
+ ett[last_offset] = &ett_gsm_dtap_msg_gmm[i];
+ }
+
+ for (i=0; i < NUM_GSM_DTAP_MSG_SMS; i++, last_offset++)
+ {
+ ett_gsm_dtap_msg_sms[i] = -1;
+ ett[last_offset] = &ett_gsm_dtap_msg_sms[i];
+ }
+
+ for (i=0; i < NUM_GSM_DTAP_MSG_SM; i++, last_offset++)
+ {
+ ett_gsm_dtap_msg_sm[i] = -1;
+ ett[last_offset] = &ett_gsm_dtap_msg_sm[i];
+ }
+
+ for (i=0; i < NUM_GSM_DTAP_MSG_SS; i++, last_offset++)
+ {
+ ett_gsm_dtap_msg_ss[i] = -1;
+ ett[last_offset] = &ett_gsm_dtap_msg_ss[i];
+ }
+
+ for (i=0; i < NUM_GSM_RP_MSG; i++, last_offset++)
+ {
+ ett_gsm_rp_msg[i] = -1;
+ ett[last_offset] = &ett_gsm_rp_msg[i];
+ }
+
+ for (i=0; i < NUM_GSM_BSSMAP_ELEM; i++, last_offset++)
+ {
+ ett_gsm_bssmap_elem[i] = -1;
+ ett[last_offset] = &ett_gsm_bssmap_elem[i];
+ }
+
+ for (i=0; i < NUM_GSM_DTAP_ELEM; i++, last_offset++)
+ {
+ ett_gsm_dtap_elem[i] = -1;
+ ett[last_offset] = &ett_gsm_dtap_elem[i];
+ }
+
+ for (i=0; i < NUM_GSM_SS_ETT; i++, last_offset++)
+ {
+ gsm_ss_ett[i] = -1;
+ ett[last_offset] = &gsm_ss_ett[i];
+ }
+
+ /* Register the protocol name and description */
+
+ proto_a_bssmap =
+ proto_register_protocol("GSM A-I/F BSSMAP", "GSM BSSMAP", "gsm_a_bssmap");
+
+ proto_register_field_array(proto_a_bssmap, hf, array_length(hf));
+
+ proto_a_dtap =
+ proto_register_protocol("GSM A-I/F DTAP", "GSM DTAP", "gsm_a_dtap");
+
+ proto_a_rp =
+ proto_register_protocol("GSM A-I/F RP", "GSM RP", "gsm_a_rp");
+
+ sms_dissector_table =
+ register_dissector_table("gsm_a.sms_tpdu", "GSM SMS TPDU",
+ FT_UINT8, BASE_DEC);
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+ gsm_a_tap = register_tap("gsm_a");
+}
+
+
+void
+proto_reg_handoff_gsm_a(void)
+{
+
+ bssmap_handle = create_dissector_handle(dissect_bssmap, proto_a_bssmap);
+ dtap_handle = create_dissector_handle(dissect_dtap, proto_a_dtap);
+ rp_handle = create_dissector_handle(dissect_rp, proto_a_rp);
+
+ dissector_add("bssap.pdu_type", BSSAP_PDU_TYPE_BSSMAP, bssmap_handle);
+ dissector_add("bssap.pdu_type", BSSAP_PDU_TYPE_DTAP, dtap_handle);
+ dissector_add("ranap.nas_pdu", BSSAP_PDU_TYPE_DTAP, dtap_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-gsm_a.h b/epan/dissectors/packet-gsm_a.h
new file mode 100644
index 0000000000..6a6d084315
--- /dev/null
+++ b/epan/dissectors/packet-gsm_a.h
@@ -0,0 +1,77 @@
+/* packet-gsm_a.h
+ *
+ * $Id$
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>,
+ * In association with Telos Technology Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * this enum must be kept in-sync with 'gsm_a_pd_str'
+ * it is used as an index into the array
+ */
+typedef enum
+{
+ PD_GCC = 0,
+ PD_BCC,
+ PD_RSVD_1,
+ PD_CC,
+ PD_GTTP,
+ PD_MM,
+ PD_RR,
+ PD_UNK_1,
+ PD_GMM,
+ PD_SMS,
+ PD_SM,
+ PD_SS,
+ PD_LCS,
+ PD_UNK_2,
+ PD_RSVD_EXT,
+ PD_RSVD_TEST
+}
+gsm_a_pd_str_e;
+
+typedef struct _gsm_a_tap_rec_t {
+ /*
+ * value from packet-bssap.h
+ */
+ guint8 pdu_type;
+ guint8 message_type;
+ gsm_a_pd_str_e protocol_disc;
+} gsm_a_tap_rec_t;
+
+
+/*
+ * the following allows TAP code access to the messages
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string gsm_a_bssmap_msg_strings[];
+ETH_VAR_IMPORT const value_string gsm_a_dtap_msg_mm_strings[];
+ETH_VAR_IMPORT const value_string gsm_a_dtap_msg_rr_strings[];
+ETH_VAR_IMPORT const value_string gsm_a_dtap_msg_cc_strings[];
+ETH_VAR_IMPORT const value_string gsm_a_dtap_msg_gmm_strings[];
+ETH_VAR_IMPORT const value_string gsm_a_dtap_msg_sms_strings[];
+ETH_VAR_IMPORT const value_string gsm_a_dtap_msg_sm_strings[];
+ETH_VAR_IMPORT const value_string gsm_a_dtap_msg_ss_strings[];
+ETH_VAR_IMPORT const gchar *gsm_a_pd_str[];
+
+
diff --git a/epan/dissectors/packet-gsm_map.c b/epan/dissectors/packet-gsm_map.c
new file mode 100644
index 0000000000..2f2bbeb8e9
--- /dev/null
+++ b/epan/dissectors/packet-gsm_map.c
@@ -0,0 +1,3150 @@
+/* packet-gsm_map.c
+ * Routines for GSM Mobile Application Part dissection
+ *
+ * Copyright 2000, Felix Fei <felix.fei [AT] utstar.com>
+ *
+ * Michael Lum <mlum [AT] telostech.com>,
+ * Changed to run on new version of TCAP, many changes for
+ * EOC matching, and parameter separation. (2003)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tcap.c (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "epan/packet.h"
+#include "tap.h"
+#include "asn1.h"
+
+#include "packet-tcap.h"
+#include "packet-gsm_ss.h"
+#include "packet-gsm_map.h"
+
+
+/* OPERATION CODE DEFINITION */
+
+/* LOCATION MANAGEMENT */
+#define MAP_UPD_LOC 2 /* Update Location */
+#define MAP_CANCEL_LOC 3 /* Cancel Location */
+#define MAP_PURGE 67 /* Purge MS */
+#define MAP_SEND_ID 5 /* Send Identification */
+#define MAP_GPRS_UPD_LOC 23 /* GPRS Update Location */
+#define MAP_DET_IMSI 5 /* Detach IMSI */
+#define MAP_NOTE_MM_EVT 89 /* Note MM Event */
+
+/* HANDOVER MANAGEMENT */
+#define MAP_PREP_HO 68 /* Prepare Handover */
+#define MAP_PREP_SUBS_HO 69 /* Prepare Subsequent Handover */
+#define MAP_PERF_HO 28 /* Perform Handover */
+#define MAP_PERF_SUBS_HO 30 /* Perform Subsequent Handover */
+#define MAP_SEND_END_SIG 29 /* Send End Signal */
+#define MAP_PROC_ACC_SIG 33 /* Process Access Signalling */
+#define MAP_FWD_ACC_SIG 34 /* Forward Access Signalling */
+
+/* AUTHENTICATION MANAGEMENT */
+#define MAP_AUTH_INFO 56 /* Send Authintication Info */
+#define MAP_AUTH_FAIL_RPT 15 /* Authentication Failure Report */
+
+/* IDENTIFICATION MANAGEMENT */
+#define MAP_CHK_IMEI 43 /* Check IMEI */
+
+/* FAULT & RECOVERY MANAGEMENT */
+#define MAP_RESET 37 /* Reset */
+#define MAP_RESTORE_DATA 57 /* Restore Data */
+#define MAP_FWD_CHK_SS_IND 38 /* Forward Check SS Indication */
+
+/* OAM MANAGEMENT */
+#define MAP_ACT_TRACE 50 /* Activate Trace */
+#define MAP_DEACT_TRACE 51 /* Deactivate Trace Mode */
+#define MAP_SEND_IMSI 58 /* Send IMSI */
+#define MAP_TRACE_SUBS_ACTV 52 /* Trace Subscriber Activity */
+#define MAP_NOTE_INTER_HO 35 /* Not Internal Handover */
+
+/* CALL MANAGEMENT */
+#define MAP_ROUTE_INFO 22 /* Send Routing Info */
+#define MAP_PROV_ROAM_NUM 4 /* Provide Roaming Number */
+#define MAP_PROV_SIWFS_NUM 31 /* Provide SIWFS Number */
+#define MAP_SIWFS_SIG_MOD 32 /* SIWFS Signalling Modify */
+#define MAP_RES_CALL_HAND 6 /* Resume Call Handling */
+#define MAP_SET_RPT_STATE 73 /* Set Reporting State */
+#define MAP_STAT_RPT 74 /* Status Report */
+#define MAP_REM_USR_FREE 75 /* Remote user free */
+#define MAP_PREP_GRP_CALL 39 /* Prepare Group Call */
+#define MAP_SND_GRP_CALL_END_SIG 40 /* Send Group Call End Signalling */
+#define MAP_PRO_GRP_CALL_SIG 41 /* Process Group Call Signalling */
+#define MAP_FWD_GRP_CALL_SIG 42 /* Forward Group Call Signalling */
+#define MAP_IST_ALERT 87 /* IST Alert */
+#define MAP_IST_COMMAND 88 /* IST Command */
+
+/* SS MANAGEMENT */
+#define MAP_REG_SS 10 /* Register SS */
+#define MAP_ERASE_SS 11 /* Erase SS */
+#define MAP_ACT_SS 12 /* Activate SS */
+#define MAP_DEACT_SS 13 /* Deactivate SS */
+#define MAP_INTER_SS 14 /* Interrogate SS */
+#define MAP_PROC_U_SS_REQ 59 /* Process Unstructured SS Req */
+#define MAP_U_SS_REQ 60 /* Unstructured SS Request */
+#define MAP_U_SS_NOTIFY 61 /* Unstructured SS Notify */
+#define MAP_REG_PASSWD 17 /* Register Password */
+#define MAP_GET_PASSWD 18 /* Get Password */
+#define MAP_REG_CC_ENT 76 /* Register CC Entry */
+#define MAP_ERASE_CC_ENT 77 /* Erase CC Entry */
+#define MAP_BEGIN_SUBS_ACTV 54 /* Begin Subscriber Activity */
+#define MAP_PROC_U_SS_DATA 19 /* Process Unstructured SS Data */
+#define MAP_SS_INV_NOTIFY 72 /* SS Invocation Notify */
+
+/* SMS MANAGEMENT */
+#define MAP_MO_FWD_SM 46 /* Mobile Originated Forward Short Message */
+#define MAP_MT_FWD_SM 44 /* Mobile Terminated Forward Short Message */
+#define MAP_ROUTE_INFO_SM 45 /* Routing Info for SM */
+#define MAP_SM_DEL_STAT 47 /* Report SM Delivery Status */
+#define MAP_INFORM_SC 63 /* Inform Service Center */
+#define MAP_ALERT_SC 64 /* Alert Service Center */
+#define MAP_SM_READY 66 /* Ready for Short Message */
+#define MAP_NOTE_SUB_PRES 48 /* Note Subscriber Present */
+#define MAP_ALERT_SC_W_RES 49 /* Alert SC Without Result */
+
+/* SUBSCRIBER MANAGEMENT */
+#define MAP_INS_SUB_DATA 7 /* Insert Subscriber Data */
+#define MAP_DEL_SUB_DATA 8 /* Delete Subscriber Data */
+#define MAP_PROV_SUB_INFO 70 /* Provide Subscriber Info */
+#define MAP_ANY_TIME_INTER 71 /* Any Time Interrogation */
+#define MAP_SEND_PARAM 9 /* Send Parameters */
+#define MAP_ANY_TIME_SUB_DATA_INTER 62 /* Any Time Subscriber Info Interrogation */
+#define MAP_ANY_TIME_MOD 65 /* Any Time Modification */
+#define MAP_NOTE_SUB_DATA_MOD 5 /* Note Subscriber Data Modified */
+
+/* PDP ACTIVE MANAGEMENT */
+#define MAP_GPRS_ROUTE_INFO 24 /* Rout Info for GPRS */
+#define MAP_FAIL_REP 25 /* Failure Report */
+#define MAP_GPRS_NOTE_MS_PRES 26 /* GPRS NoteMs Present */
+
+/* LOCATION SERVICE */
+#define MAP_PROV_SUB_LOC 83 /* Provide Subscriber Location */
+#define MAP_SEND_ROUTE_INFO_FOR_LCS 85 /* Send Routing Info For LCS */
+#define MAP_SUB_LOC_REP 86 /* Subscriber Location Report */
+
+
+#define MAP_OPR_CODE_TAG 0x02
+#define MAP_GE_PROBLEM_TAG 0x80
+#define MAP_IN_PROBLEM_TAG 0x81
+#define MAP_RR_PROBLEM_TAG 0x82
+#define MAP_RE_PROBLEM_TAG 0x83
+#define MAP_INVALID_TAG 0x00
+
+#define MAP_OK 0x0
+#define MAP_FAIL 0x1
+
+const value_string gsm_map_opr_code_strings[] = {
+
+/* LOCATION MANAGEMENT */
+ { MAP_UPD_LOC, "Update Location"},
+ { MAP_CANCEL_LOC, "Cancel Location"},
+ { MAP_PURGE, "Purge MS"},
+ { MAP_SEND_ID, "Send Identification"},
+ { MAP_GPRS_UPD_LOC, "Update GPRS Location"},
+ { MAP_DET_IMSI, "Detach IMSI"},
+ { MAP_NOTE_MM_EVT, "Note MM Event"},
+
+/* HANDOVER MANAGEMENT */
+ { MAP_PREP_HO, "Prepare Handover"},
+ { MAP_PREP_SUBS_HO, "Prepare Subsequent Handover"},
+ { MAP_PERF_HO, "Perform Handover"},
+ { MAP_PERF_SUBS_HO, "Perform Subsequent Handover"},
+ { MAP_SEND_END_SIG, "Send End Signal"},
+ { MAP_PROC_ACC_SIG, "Process Access Signalling"},
+ { MAP_FWD_ACC_SIG, "Forward Access Signalling"},
+
+/* AUTHENTICATION MANAGEMENT */
+ { MAP_AUTH_INFO, "Send Authentication Info"},
+ { MAP_AUTH_FAIL_RPT, "Authentication Failure Report"},
+
+/* IDENTIFICATION MANAGEMENT */
+ { MAP_CHK_IMEI, "Check IMEI"},
+
+/* FAULT & RECOVERY MANAGEMENT */
+ { MAP_RESET, "Reset"},
+ { MAP_RESTORE_DATA, "Restore Data"},
+ { MAP_FWD_CHK_SS_IND, "Forward Check SS Indication"},
+
+/* OAM MANAGEMENT */
+ { MAP_ACT_TRACE, "Activate Trace Mode"},
+ { MAP_DEACT_TRACE, "Deactivate Trace Mode"},
+ { MAP_SEND_IMSI, "Send IMSI"},
+ { MAP_TRACE_SUBS_ACTV, "Trace Subscriber Activity"},
+ { MAP_NOTE_INTER_HO, "Note Internal Handover"},
+
+/* CALL MANAGEMENT */
+ { MAP_ROUTE_INFO, "Send Routing Info"},
+ { MAP_PROV_ROAM_NUM, "Provide Roaming Number"},
+ { MAP_PROV_SIWFS_NUM, "Provide SIWFS Number"},
+ { MAP_SIWFS_SIG_MOD, "SIWFS Signalling Modify"},
+ { MAP_RES_CALL_HAND, "Resume Call Handling"},
+ { MAP_SET_RPT_STATE, "Set Reporting State"},
+ { MAP_STAT_RPT, "Status Report"},
+ { MAP_REM_USR_FREE, "Remote User Free"},
+ { MAP_PREP_GRP_CALL, "Prepare Group Call"},
+ { MAP_SND_GRP_CALL_END_SIG, "Send Group Call End Signalling"},
+ { MAP_PRO_GRP_CALL_SIG, "Process Group Call Signalling"},
+ { MAP_FWD_GRP_CALL_SIG, "Forward Group Call Signalling"},
+ { MAP_IST_ALERT, "IST Alert"},
+ { MAP_IST_COMMAND, "IST Command"},
+
+/* SS MANAGEMENT */
+ { MAP_REG_SS, "Register SS"},
+ { MAP_ERASE_SS, "Erase SS"},
+ { MAP_ACT_SS, "Activate SS"},
+ { MAP_DEACT_SS, "Deactivate SS"},
+ { MAP_INTER_SS, "Interrogate SS"},
+ { MAP_PROC_U_SS_REQ, "Process Unstructured SS Request"},
+ { MAP_U_SS_REQ, "Unstructured SS Request"},
+ { MAP_U_SS_NOTIFY, "Unstructured SS Notify"},
+ { MAP_REG_PASSWD, "Register Password"},
+ { MAP_GET_PASSWD, "Get Password"},
+ { MAP_REG_CC_ENT, "Register CC Entry"},
+ { MAP_ERASE_CC_ENT, "Erase CC Entry"},
+ { MAP_BEGIN_SUBS_ACTV, "Begin Subscriber Activity"},
+ { MAP_PROC_U_SS_DATA, "Process Unstructured SS Data"},
+ { MAP_SS_INV_NOTIFY, "SS Invocation Notification"},
+
+/* SMS MANAGEMENT */
+ { MAP_MO_FWD_SM, "MO Forward SM"},
+ { MAP_MT_FWD_SM, "MT Forward SM"},
+ { MAP_ROUTE_INFO_SM, "Send Routing Info For SM"},
+ { MAP_SM_DEL_STAT, "Report SM Delivery Status"},
+ { MAP_INFORM_SC, "Inform Service Center"},
+ { MAP_ALERT_SC, "Alert Service Center"},
+ { MAP_SM_READY, "Ready For SM"},
+ { MAP_NOTE_SUB_PRES, "Note Subscriber Present"},
+ { MAP_ALERT_SC_W_RES, "Alert SC Without Result"},
+
+/* SUBSCRIBER MANAGEMENT */
+ { MAP_INS_SUB_DATA, "Insert Subscriber Data"},
+ { MAP_DEL_SUB_DATA, "Delete Subscriber Data"},
+ { MAP_PROV_SUB_INFO, "Provide Subscriber Info"},
+ { MAP_ANY_TIME_INTER, "Any Time Interrogation"},
+ { MAP_SEND_PARAM, "Send Parameters"},
+ { MAP_ANY_TIME_SUB_DATA_INTER, "Any Time Subscription Interrogation"},
+ { MAP_ANY_TIME_MOD, "Any Time Modification"},
+ { MAP_NOTE_SUB_DATA_MOD, "Note Subscriber Data Modified"},
+
+/* PDP ACTIVE MANAGEMENT */
+ { MAP_GPRS_ROUTE_INFO, "Send Routing Info For GPRS"},
+ { MAP_FAIL_REP, "Failure Report"},
+ { MAP_GPRS_NOTE_MS_PRES, "Note MS Present For GPRS"},
+
+/* LOCATION SERVICE */
+ { MAP_PROV_SUB_LOC, "Provide Subscriber Location"},
+ { MAP_SEND_ROUTE_INFO_FOR_LCS, "Send Routing Info For LCS"},
+ { MAP_SUB_LOC_REP, "Subscriber Location Report"},
+
+ { 0, NULL}
+};
+
+/*
+ * Initialize the protocol and registered fields
+ */
+static int proto_map = -1;
+
+static int gsm_map_tap = -1;
+
+static dissector_table_t sms_dissector_table; /* SMS TPDU */
+
+static int gsm_map_app_context = 1; /* XXX should be set from Dialogue */
+
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
+static guint g_opr_code;
+static guint g_comp_type_tag;
+
+static int hf_map_length = -1;
+static int hf_map_opr_code = -1;
+static int hf_map_int = -1;
+static int hf_map_imsi = -1;
+static int hf_map_addrstring = -1;
+static int hf_map_rand = -1;
+static int hf_map_sres = -1;
+static int hf_map_kc = -1;
+static int hf_map_xres = -1;
+static int hf_map_ck = -1;
+static int hf_map_ik = -1;
+static int hf_map_autn = -1;
+
+/* never initialize in field array */
+static int hf_null = -1;
+#define HF_NULL &hf_null
+
+/* Initialize the subtree pointers */
+static gint ett_map = -1;
+static gint ett_component = -1;
+static gint ett_components = -1;
+static gint ett_sequence = -1;
+static gint ett_param = -1;
+static gint ett_params = -1;
+static gint ett_problem = -1;
+static gint ett_opr_code = -1;
+static gint ett_err_code = -1;
+
+typedef struct dgt_set_t
+{
+ unsigned char out[15];
+}
+dgt_set_t;
+
+#ifdef MLUM
+static dgt_set_t Dgt_tbcd = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#'
+ }
+};
+#endif
+
+static dgt_set_t Dgt_msid = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
+ }
+};
+
+
+/* FORWARD DECLARATIONS */
+
+static int dissect_map_eoc(ASN1_SCK *asn1, proto_tree *tree);
+
+/* FUNCTIONS */
+
+/*
+ * Unpack BCD input pattern into output ASCII pattern
+ *
+ * Input Pattern is supplied using the same format as the digits
+ *
+ * Returns: length of unpacked pattern
+ */
+static int
+my_dgt_tbcd_unpack(
+ char *out, /* ASCII pattern out */
+ guchar *in, /* packed pattern in */
+ int num_octs, /* Number of octets to unpack */
+ dgt_set_t *dgt /* Digit definitions */
+ )
+{
+ int cnt = 0;
+ unsigned char i;
+
+ while (num_octs)
+ {
+ /*
+ * unpack first value in byte
+ */
+ i = *in++;
+ *out++ = dgt->out[i & 0x0f];
+ cnt++;
+
+ /*
+ * unpack second value in byte
+ */
+ i >>= 4;
+
+ if (i == 0x0f) /* odd number bytes - hit filler */
+ break;
+
+ *out++ = dgt->out[i];
+ cnt++;
+ num_octs--;
+ }
+
+ *out = '\0';
+
+ return(cnt);
+}
+
+static gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr) {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+#define GSM_MAP_START_SUBTREE(_Gtree, _Gsaved_offset, _Gtag, _Gstr1, _Gett, _Gdef_len_p, _Glen_p, _Gsubtree_p) \
+ { \
+ guint _len_offset; \
+ proto_item *_item; \
+ \
+ _len_offset = asn1->offset; \
+ asn1_length_decode(asn1, _Gdef_len_p, _Glen_p); \
+ \
+ _item = \
+ proto_tree_add_text(_Gtree, asn1->tvb, _Gsaved_offset, -1, _Gstr1); \
+ \
+ _Gsubtree_p = proto_item_add_subtree(_item, _Gett); \
+ \
+ proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
+ _Gsaved_offset, _len_offset - _Gsaved_offset, "Tag: 0x%02x", _Gtag); \
+ \
+ if (*_Gdef_len_p) \
+ { \
+ proto_tree_add_uint(_Gsubtree_p, hf_map_length, asn1->tvb, \
+ _len_offset, asn1->offset - _len_offset, *_Glen_p); \
+ } \
+ else \
+ { \
+ proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
+ _len_offset, asn1->offset - _len_offset, "Length: Indefinite"); \
+ \
+ *_Glen_p = tcap_find_eoc(asn1); \
+ } \
+ \
+ proto_item_set_len(_item, (asn1->offset - _Gsaved_offset) + *_Glen_p + \
+ (*_Gdef_len_p ? 0 : TCAP_EOC_LEN)); \
+ }
+
+static int
+dissect_map_params(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint orig_offset, saved_offset, len_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_item *item;
+ proto_tree *subtree;
+
+ orig_offset = asn1->offset;
+
+ while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
+ (!tcap_check_tag(asn1, 0)))
+ {
+ if ((exp_len != 0) &&
+ ((asn1->offset - orig_offset) >= exp_len))
+ {
+ break;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag))
+ {
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ dissect_map_params(asn1, subtree, len);
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+ continue;
+ }
+
+ len_offset = asn1->offset;
+ asn1_length_decode(asn1, &def_len, &len);
+
+ if (!def_len)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len_offset - saved_offset,
+ "Tag: 0x%02x", tag);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ len_offset, asn1->offset - len_offset, "Length: Indefinite");
+
+ len = tcap_find_eoc(asn1);
+
+ dissect_map_params(asn1, tree, len);
+
+ dissect_map_eoc(asn1, tree);
+ continue;
+ }
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, (asn1->offset - saved_offset) + len, "Parameter");
+
+ subtree = proto_item_add_subtree(item, ett_param);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, len_offset - saved_offset,
+ "Tag: 0x%02x", tag);
+
+ proto_tree_add_uint(subtree, hf_map_length, asn1->tvb,
+ len_offset, asn1->offset - len_offset, len);
+
+ if (len > 0)
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ asn1->offset, len, "Parameter Data");
+
+ asn1->offset += len;
+ }
+ }
+
+ return(MAP_OK);
+}
+
+
+/* PARAMETERS */
+
+static void
+param_bytes(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_bytes(tree, hf_field, asn1->tvb,
+ saved_offset, len, tvb_get_ptr(asn1->tvb, saved_offset, len));
+
+ asn1->offset += len;
+}
+
+static void
+param_imsi(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ guchar *poctets;
+ char bigbuf[1024];
+
+ saved_offset = asn1->offset;
+ asn1_string_value_decode(asn1, len, &poctets);
+
+ my_dgt_tbcd_unpack(bigbuf, poctets, len, &Dgt_msid);
+ g_free(poctets);
+
+ if (hf_field == -1)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len, "IMSI %s", bigbuf);
+ }
+ else
+ {
+ proto_tree_add_string_format(tree, hf_field, asn1->tvb,
+ saved_offset, len, bigbuf, "IMSI %s", bigbuf);
+ }
+}
+
+static void
+param_lmsi(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len, "LMSI 0x%04x", value);
+}
+
+static void
+param_boolean(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len, value ? "TRUE" : "FALSE");
+}
+
+static void
+param_alertReason(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+ gchar *str = NULL;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ switch (value)
+ {
+ case 0x00:
+ str = "ms-Present";
+ break;
+
+ case 0x01:
+ str = "memoryAvailable";
+ break;
+
+ default:
+ str = "Unrecognized value";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len, str);
+}
+
+
+typedef enum
+{
+ GSM_MAP_P_IMSI, /* IMSI */
+ GSM_MAP_P_LMSI, /* LMSI */
+ GSM_MAP_P_MSISDN, /* MSISDN */
+ GSM_MAP_P_SC_ADDR_DA, /* Service Centre Address DA */
+ GSM_MAP_P_SC_ADDR_OA, /* Service Centre Address OA */
+ GSM_MAP_P_SC_ADDR, /* Service Centre Address */
+ GSM_MAP_P_MSC_NUMBER, /* MSC Number */
+ GSM_MAP_P_VLR_NUMBER, /* VLR Number */
+ GSM_MAP_P_HLR_NUMBER, /* HLR Number */
+ GSM_MAP_P_SIG_INFO, /* Signal Info */
+ GSM_MAP_P_BOOL, /* Boolean */
+ GSM_MAP_P_LIWLMSI, /* Location Information with LMSI */
+ GSM_MAP_P_NETNODE_NUM, /* Network Node Number */
+ GSM_MAP_P_ROAMING_NUM, /* Roaming Number */
+ GSM_MAP_P_ALERT_REASON, /* Alert Reason */
+ GSM_MAP_P_GMSC_ADDR, /* GMSC Address */
+ GSM_MAP_P_RAND, /* Rand */
+ GSM_MAP_P_SRES, /* Signed Result */
+ GSM_MAP_P_KC, /* Key Cipher */
+ GSM_MAP_P_XRES, /* Extended Signed Result */
+ GSM_MAP_P_CK, /* Ciphering Key */
+ GSM_MAP_P_IK, /* Integrity Key */
+ GSM_MAP_P_AUTN, /* Authentication Token */
+ GSM_MAP_P_NONE /* NONE */
+}
+param_idx_t;
+
+#define NUM_PARAM_1 (GSM_MAP_P_NONE+1)
+static gint ett_param_1[NUM_PARAM_1];
+static void (*param_1_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = {
+ param_imsi, /* IMSI */
+ param_lmsi, /* LMSI */
+ param_AddressString, /* MSISDN */
+ param_AddressString, /* Service Centre Address DA */
+ param_AddressString, /* Service Centre Address OA */
+ param_AddressString, /* Service Centre Address */
+ param_AddressString, /* MSC Number */
+ param_AddressString, /* VLR Number */
+ param_AddressString, /* HLR Number */
+ NULL, /* Signal Info */
+ param_boolean, /* Boolean */
+ NULL, /* Location Information with LMSI */
+ param_AddressString, /* Network Node Number */
+ param_AddressString, /* Roaming Number */
+ param_alertReason, /* Alert Reason */
+ param_AddressString, /* GMSC Address */
+ param_bytes, /* Rand */
+ param_bytes, /* Signed Result */
+ param_bytes, /* GSM Key Cipher */
+ param_bytes, /* Extended Signed Result */
+ param_bytes, /* UMTS Ciphering Key */
+ param_bytes, /* Integrity Key */
+ param_bytes, /* Authentication Token */
+ NULL /* NONE */
+};
+
+static int *param_1_hf[] = {
+ &hf_map_imsi, /* IMSI */
+ HF_NULL, /* LMSI */
+ &hf_map_addrstring, /* MSISDN */
+ &hf_map_addrstring, /* Service Centre Address DA */
+ &hf_map_addrstring, /* Service Centre Address OA */
+ &hf_map_addrstring, /* Service Centre Address */
+ &hf_map_addrstring, /* MSC Number */
+ &hf_map_addrstring, /* VLR Number */
+ &hf_map_addrstring, /* HLR Number */
+ HF_NULL, /* Signal Info */
+ HF_NULL, /* Boolean */
+ HF_NULL, /* Location Information with LMSI */
+ &hf_map_addrstring, /* Network Node Number */
+ &hf_map_addrstring, /* Roaming Number */
+ HF_NULL, /* Alert Reason */
+ &hf_map_addrstring, /* GMSC Address */
+ &hf_map_rand, /* Rand */
+ &hf_map_sres, /* Signed Result */
+ &hf_map_kc, /* GSM Key Cipher */
+ &hf_map_xres, /* Extended Signed Result */
+ &hf_map_ck, /* UMTS Ciphering Key */
+ &hf_map_ik, /* Integrity Key */
+ &hf_map_autn, /* Authentication Token */
+ NULL /* NONE */
+};
+
+
+#define GSM_MAP_PARAM_DISPLAY(Gtree, Goffset, Gtag, Ga1, Ga2) \
+ { \
+ gint _ett_param_idx; \
+ guint _len; \
+ void (*_param_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = NULL; \
+ int *_param_hf = NULL; \
+ proto_tree *_subtree; \
+ gboolean _def_len; \
+ \
+ if (Ga1 == GSM_MAP_P_NONE) \
+ { \
+ _ett_param_idx = ett_param; \
+ _param_fcn = NULL; \
+ _param_hf = HF_NULL; \
+ } \
+ else \
+ { \
+ _ett_param_idx = ett_param_1[Ga1]; \
+ _param_fcn = param_1_fcn[Ga1]; \
+ _param_hf = param_1_hf[Ga1]; \
+ } \
+ \
+ GSM_MAP_START_SUBTREE(Gtree, Goffset, Gtag, Ga2, _ett_param_idx, &_def_len, &_len, _subtree); \
+ \
+ if (_len > 0) \
+ { \
+ if (Ga1 == GSM_MAP_P_NONE || _param_fcn == NULL) \
+ { \
+ proto_tree_add_text(_subtree, asn1->tvb, \
+ asn1->offset, _len, "Parameter Data"); \
+ \
+ asn1->offset += _len; \
+ } \
+ else \
+ { \
+ (*_param_fcn)(asn1, _subtree, _len, *_param_hf); \
+ } \
+ } \
+ \
+ if (!_def_len) \
+ { \
+ dissect_map_eoc(asn1, Gtree); \
+ } \
+ }
+
+
+static void
+param_Identity(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ switch (tag)
+ {
+ case 0x04: /* IMSI */
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "Identity");
+ break;
+
+ case 0x30: /* IMSI-WithLMSI */
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_LMSI, "LMSI");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+ break;
+
+ default:
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_NONE, "Identity");
+ break;
+ }
+}
+
+static void
+param_TripletList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, orig_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ orig_offset = asn1->offset;
+
+ while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
+ (!tcap_check_tag(asn1, 0)))
+ {
+ if ((exp_len != 0) &&
+ ((asn1->offset - orig_offset) >= exp_len))
+ {
+ break;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_RAND, "RAND");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SRES, "SRES");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_KC, "Kc");
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+ }
+}
+
+static void
+param_QuintupletList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, orig_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ orig_offset = asn1->offset;
+
+ while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
+ (!tcap_check_tag(asn1, 0)))
+ {
+ if ((exp_len != 0) &&
+ ((asn1->offset - orig_offset) >= exp_len))
+ {
+ break;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_RAND, "RAND");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_XRES, "XRES");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_CK, "CK");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IK, "IK");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_AUTN, "AUTN");
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+ }
+}
+
+static void
+param_SM_RP_DA(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset;
+ guint tag;
+ gint idx;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ switch (tag)
+ {
+ case 0x80: /* IMSI */
+ idx = GSM_MAP_P_IMSI;
+ break;
+
+ case 0x81: /* LMSI */
+ idx = GSM_MAP_P_LMSI;
+ break;
+
+ case 0x84: /* AddressString */
+ idx = GSM_MAP_P_SC_ADDR_DA;
+ break;
+
+ default:
+ /*
+ * this occurs in the mobile terminated case for
+ * subsequent messages
+ */
+ idx = GSM_MAP_P_NONE;
+ break;
+ }
+
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, idx, "SM-RP-DA");
+}
+
+static void
+param_SM_RP_OA(ASN1_SCK *asn1, proto_tree *tree, int *direction_p)
+{
+ guint saved_offset;
+ guint tag;
+ gint idx;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ switch (tag)
+ {
+ case 0x82: /* MSISDN */
+ idx = GSM_MAP_P_MSISDN;
+
+ *direction_p = P2P_DIR_RECV;
+ break;
+
+ case 0x84: /* AddressString */
+ idx = GSM_MAP_P_SC_ADDR_OA;
+
+ *direction_p = P2P_DIR_SENT;
+ break;
+
+ default:
+ idx = GSM_MAP_P_NONE;
+
+ /*
+ * this occurs in the mobile terminated case for
+ * subsequent messages
+ */
+ *direction_p = P2P_DIR_SENT;
+ break;
+ }
+
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, idx, "SM-RP-OA");
+}
+
+static void
+param_SM_RP_UI(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+ tvbuff_t *tpdu_tvb;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "SM-RP-UI",
+ ett_param_1[GSM_MAP_P_SIG_INFO],
+ &def_len, &len, subtree);
+
+ proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "TPDU");
+
+ /*
+ * dissect the embedded TPDU message
+ */
+ tpdu_tvb = tvb_new_subset(asn1->tvb, asn1->offset, len, len);
+
+ dissector_try_port(sms_dissector_table, 0, tpdu_tvb, g_pinfo, g_tree);
+
+ asn1->offset += len;
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+param_LWI_LMSI(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "LOCATION INFO WITH LMSI",
+ ett_param_1[GSM_MAP_P_LIWLMSI],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NETNODE_NUM, "NETWORK NODE NUMBER");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+
+/* MESSAGES */
+
+static void
+op_update_loc(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSC_NUMBER, "MSC Number");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_VLR_NUMBER, "VLR Number");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_update_loc_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number");
+
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_cancel_loc(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (tag != 0xa3)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Constructor Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ param_Identity(asn1, subtree);
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_send_auth_info(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Number Of Requested Vectors");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_send_auth_info_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if ((tag != 0x30) &&
+ (tag != 0x31))
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag,
+ (tag == 0x30) ? "TripletList" : "QuintupletList",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ if (tag == 0x30)
+ {
+ param_TripletList(asn1, subtree, len);
+ }
+ else
+ {
+ param_QuintupletList(asn1, subtree, len);
+ }
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_restore_data(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_restore_data_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number");
+
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_HLR_NUMBER, "HLR Number");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_send_rti(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_send_rti_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ /*
+ * spec says [9] but 'real data' show '04' not '89' !
+ */
+ if (tcap_check_tag(asn1, 0x04))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+ }
+
+ if (tcap_check_tag(asn1, 0x04))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_ROAMING_NUM, "Roaming Number");
+ }
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_provide_rn(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSC_NUMBER, "MSC Number");
+
+ if (tcap_check_tag(asn1, 0x82))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
+ }
+
+ if (tcap_check_tag(asn1, 0x84))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_LMSI, "LMSI");
+ }
+
+ if (tcap_check_tag(asn1, 0x85))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "GSM Bearer Capability");
+ }
+
+ if (tcap_check_tag(asn1, 0xa6))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Network Signal Info");
+ }
+
+ if (tcap_check_tag(asn1, 0x87))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Suppression Of Announcement");
+ }
+
+ if (tcap_check_tag(asn1, 0x88))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_GMSC_ADDR, "GMSC Address");
+ }
+
+ if (tcap_check_tag(asn1, 0x89))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Call Reference Number");
+ }
+
+ if (tcap_check_tag(asn1, 0x8a))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "OR Interrogation");
+ }
+
+ if (tcap_check_tag(asn1, 0x8b))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Extension Container");
+ }
+
+ if (tcap_check_tag(asn1, 0x8c))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Alerting Pattern");
+ }
+
+ if (tcap_check_tag(asn1, 0x8d))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "CCBS Call");
+ }
+
+ if (tcap_check_tag(asn1, 0x8f))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Supported Camel Phases In GMSC");
+ }
+
+ if (tcap_check_tag(asn1, 0x8e))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Additional Signal Info");
+ }
+
+ if (tcap_check_tag(asn1, 0x90))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "OR Not Supported In GMSC");
+ }
+
+ if (tcap_check_tag(asn1, 0x91))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Pre-paging Supported");
+ }
+
+ if (tcap_check_tag(asn1, 0x92))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "Long FTN Supported");
+ }
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_provide_rn_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ GSM_MAP_PARAM_DISPLAY(tree, saved_offset, tag, GSM_MAP_P_ROAMING_NUM, "Roaming Number");
+
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_ROAMING_NUM, "Roaming Number");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+/*
+ * Description:
+ * Generic dissector for Supplementary Services
+ */
+static void
+op_ss_generic(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ gsm_ss_dissect(asn1, tree, exp_len, g_opr_code, g_comp_type_tag);
+}
+
+static void
+op_mo_forward_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ param_SM_RP_DA(asn1, subtree);
+
+ param_SM_RP_OA(asn1, subtree, &g_pinfo->p2p_dir);
+
+ param_SM_RP_UI(asn1, subtree);
+
+ /*
+ * older versions of GSM MAP had only one ForwardSM message
+ */
+ if ((tvb_length_remaining(asn1->tvb, asn1->offset) > (def_len ? 0 : TCAP_EOC_LEN)) &&
+ (gsm_map_app_context < 3) &&
+ (g_pinfo->p2p_dir == P2P_DIR_SENT))
+ {
+ /*
+ * 'more messages' for V1 context
+ */
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "More Messages To Send");
+ }
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_mt_forward_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ param_SM_RP_DA(asn1, subtree);
+
+ param_SM_RP_OA(asn1, subtree, &g_pinfo->p2p_dir);
+
+ param_SM_RP_UI(asn1, subtree);
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) > 0)
+ {
+ /*
+ * 'more messages'
+ */
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_NONE, "More Messages To Send");
+ }
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_forward_sm_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ param_SM_RP_UI(asn1, subtree);
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_send_rti_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_BOOL, "SM-RP-PRI");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SC_ADDR, "Service Centre Address");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_send_rti_sm_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ param_LWI_LMSI(asn1, subtree);
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_alert_sc(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SC_ADDR, "Service Centre Address");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_ready_sm(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_IMSI, "IMSI");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_ALERT_REASON, "Alert Reason");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+static void
+op_alert_sc_wr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag) == FALSE)
+ {
+ /*
+ * Hmmm, unexpected
+ */
+ return;
+ }
+
+ GSM_MAP_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_MSISDN, "MSISDN");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_MAP_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_MAP_P_SC_ADDR, "Service Centre Address");
+
+ dissect_map_params(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+}
+
+#define GSM_MAP_NUM_OP (sizeof(gsm_map_opr_code_strings)/sizeof(value_string))
+static gint ett_op[GSM_MAP_NUM_OP];
+static void (*op_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
+ op_update_loc, /* Update Location */
+ op_cancel_loc, /* Cancel Location */
+ NULL, /* Purge MS */
+ NULL, /* Send Identification */
+ NULL, /* Update GPRS Location */
+ NULL, /* Detach IMSI */
+ NULL, /* Note MM Event */
+ NULL, /* Prepare Handover */
+ NULL, /* Prepare Subsequent Handover */
+ NULL, /* Perform Handover */
+ NULL, /* Perform Subsequent Handover */
+ NULL, /* Send End Signal */
+ NULL, /* Process Access Signalling */
+ NULL, /* Forward Access Signalling */
+ op_send_auth_info, /* Send Authentication Info */
+ NULL, /* Authentication Failure Report */
+ NULL, /* Check IMEI */
+ NULL, /* Reset */
+ op_restore_data, /* Restore Data */
+ NULL, /* Forward Check SS Indication */
+ NULL, /* Activate Trace Mode */
+ NULL, /* Deactivate Trace Mode */
+ NULL, /* Send IMSI */
+ NULL, /* Trace Subscriber Activity */
+ NULL, /* Note Internal Handover */
+ op_send_rti, /* Send Routing Info */
+ op_provide_rn, /* Provide Roaming Number */
+ NULL, /* Provide SIWFS Number */
+ NULL, /* SIWFS Signalling Modify */
+ NULL, /* Resume Call Handling */
+ NULL, /* Set Reporting State */
+ NULL, /* Status Report */
+ NULL, /* Remote User Free */
+ NULL, /* Prepare Group Call */
+ NULL, /* Send Group Call End Signalling */
+ NULL, /* Process Group Call Signalling */
+ NULL, /* Forward Group Call Signalling */
+ NULL, /* IST Alert */
+ NULL, /* IST Command */
+ op_ss_generic, /* Register SS */
+ op_ss_generic, /* Erase SS */
+ op_ss_generic, /* Activate SS */
+ op_ss_generic, /* Deactivate SS */
+ op_ss_generic, /* Interrogate SS */
+ op_ss_generic, /* Process Unstructured SS Request */
+ op_ss_generic, /* Unstructured SS Request */
+ op_ss_generic, /* Unstructured SS Notify */
+ op_ss_generic, /* Register Password */
+ op_ss_generic, /* Get Password */
+ op_ss_generic, /* Register CC Entry */
+ op_ss_generic, /* Erase CC Entry */
+ NULL, /* Begin Subscriber Activity */
+ op_ss_generic, /* Process Unstructured SS Data */
+ op_ss_generic, /* SS Invocation Notification */
+ op_mo_forward_sm, /* MO Forward SM */
+ op_mt_forward_sm, /* MT Forward SM */
+ op_send_rti_sm, /* Send Routing Info For SM */
+ NULL, /* Report SM Delivery Status */
+ NULL, /* Inform Service Center */
+ op_alert_sc, /* Alert Service Center */
+ op_ready_sm, /* Ready For SM */
+ NULL, /* Note Subscriber Present */
+ op_alert_sc_wr, /* Alert SC Without Result */
+ NULL, /* Insert Subscriber Data */
+ NULL, /* Delete Subscriber Data */
+ NULL, /* Provide Subscriber Info */
+ NULL, /* Any Time Interrogation */
+ NULL, /* Send Parameters */
+ NULL, /* Any Time Subscription Interrogation */
+ NULL, /* Any Time Modification */
+ NULL, /* Note Subscriber Data Modified */
+ NULL, /* Send Routing Info For GPRS */
+ NULL, /* Failure Report */
+ NULL, /* Note MS Present For GPRS */
+ NULL, /* Provide Subscriber Location */
+ NULL, /* Send Routing Info For LCS */
+ NULL, /* Subscriber Location Report */
+
+ NULL /* NONE */
+};
+
+static gint ett_op_rr[GSM_MAP_NUM_OP];
+static void (*op_fcn_rr[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
+ op_update_loc_rr, /* Update Location */
+ NULL, /* Cancel Location */
+ NULL, /* Purge MS */
+ NULL, /* Send Identification */
+ NULL, /* Update GPRS Location */
+ NULL, /* Detach IMSI */
+ NULL, /* Note MM Event */
+ NULL, /* Prepare Handover */
+ NULL, /* Prepare Subsequent Handover */
+ NULL, /* Perform Handover */
+ NULL, /* Perform Subsequent Handover */
+ NULL, /* Send End Signal */
+ NULL, /* Process Access Signalling */
+ NULL, /* Forward Access Signalling */
+ op_send_auth_info_rr, /* Send Authentication Info */
+ NULL, /* Authentication Failure Report */
+ NULL, /* Check IMEI */
+ NULL, /* Reset */
+ op_restore_data_rr, /* Restore Data */
+ NULL, /* Forward Check SS Indication */
+ NULL, /* Activate Trace Mode */
+ NULL, /* Deactivate Trace Mode */
+ NULL, /* Send IMSI */
+ NULL, /* Trace Subscriber Activity */
+ NULL, /* Note Internal Handover */
+ op_send_rti_rr, /* Send Routing Info */
+ op_provide_rn_rr, /* Provide Roaming Number */
+ NULL, /* Provide SIWFS Number */
+ NULL, /* SIWFS Signalling Modify */
+ NULL, /* Resume Call Handling */
+ NULL, /* Set Reporting State */
+ NULL, /* Status Report */
+ NULL, /* Remote User Free */
+ NULL, /* Prepare Group Call */
+ NULL, /* Send Group Call End Signalling */
+ NULL, /* Process Group Call Signalling */
+ NULL, /* Forward Group Call Signalling */
+ NULL, /* IST Alert */
+ NULL, /* IST Command */
+ op_ss_generic, /* Register SS */
+ op_ss_generic, /* Erase SS */
+ op_ss_generic, /* Activate SS */
+ op_ss_generic, /* Deactivate SS */
+ op_ss_generic, /* Interrogate SS */
+ op_ss_generic, /* Process Unstructured SS Request */
+ op_ss_generic, /* Unstructured SS Request */
+ op_ss_generic, /* Unstructured SS Notify */
+ op_ss_generic, /* Register Password */
+ op_ss_generic, /* Get Password */
+ op_ss_generic, /* Register CC Entry */
+ op_ss_generic, /* Erase CC Entry */
+ NULL, /* Begin Subscriber Activity */
+ op_ss_generic, /* Process Unstructured SS Data */
+ op_ss_generic, /* SS Invocation Notification */
+ op_forward_sm_rr, /* MO Forward SM */
+ op_forward_sm_rr, /* MT Forward SM */
+ op_send_rti_sm_rr, /* Send Routing Info For SM */
+ NULL, /* Report SM Delivery Status */
+ NULL, /* Inform Service Center */
+ NULL, /* Alert Service Center */
+ NULL, /* Ready For SM */
+ NULL, /* Note Subscriber Present */
+ NULL, /* Alert SC Without Result */
+ NULL, /* Insert Subscriber Data */
+ NULL, /* Delete Subscriber Data */
+ NULL, /* Provide Subscriber Info */
+ NULL, /* Any Time Interrogation */
+ NULL, /* Send Parameters */
+ NULL, /* Any Time Subscription Interrogation */
+ NULL, /* Any Time Modification */
+ NULL, /* Note Subscriber Data Modified */
+ NULL, /* Send Routing Info For GPRS */
+ NULL, /* Failure Report */
+ NULL, /* Note MS Present For GPRS */
+ NULL, /* Provide Subscriber Location */
+ NULL, /* Send Routing Info For LCS */
+ NULL, /* Subscriber Location Report */
+
+ NULL /* NONE */
+};
+
+
+/* GENERIC MAP DISSECTOR FUNCTIONS */
+
+static int
+dissect_map_tag(ASN1_SCK *asn1, proto_tree *tree, guint *tag, guchar * str,
+ proto_item **item_p)
+{
+ guint saved_offset, real_tag;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &real_tag);
+
+ if ((*tag != (guint) -1) && (real_tag != *tag))
+ {
+ asn1->offset = saved_offset;
+ return(MAP_FAIL);
+ }
+
+ *item_p =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s: 0x%02x", str, real_tag);
+
+ return(MAP_OK);
+}
+
+
+static int
+dissect_map_len(ASN1_SCK *asn1, proto_tree *tree, gboolean *def_len, guint *len)
+{
+ guint saved_offset;
+
+ saved_offset = asn1->offset;
+ *len = 0;
+ *def_len = FALSE;
+ asn1_length_decode(asn1, def_len, len);
+
+ if (*def_len)
+ {
+ proto_tree_add_uint(tree, hf_map_length, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset, *len);
+ }
+ else
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "Length: Indefinite");
+ }
+
+ return(MAP_OK);
+}
+
+
+static int
+dissect_map_integer(ASN1_SCK *asn1, proto_tree *tree, guint len, guchar * str)
+{
+ guint saved_offset;
+ gint32 invokeId;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &invokeId);
+
+ proto_tree_add_int_format(tree, hf_map_int, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ invokeId, "%s %d", str, invokeId);
+
+ return(MAP_OK);
+}
+
+
+static int
+dissect_map_invokeId(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ proto_item *item, *null_item;
+ proto_tree *subtree;
+ gboolean def_len;
+
+ if (tcap_check_tag(asn1, TCAP_INVOKE_ID_TAG))
+ {
+ saved_offset = asn1->offset;
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, -1, "Invoke Id");
+
+ subtree = proto_item_add_subtree(item, ett_component);
+
+ tag = -1;
+ dissect_map_tag(asn1, subtree, &tag, "Invoke Id Tag", &null_item);
+ dissect_map_len(asn1, subtree, &def_len, &len);
+ dissect_map_integer(asn1, subtree, len, "Invoke Id:");
+
+ proto_item_set_len(item, asn1->offset - saved_offset);
+ }
+
+ return(MAP_OK);
+}
+
+
+static void
+dissect_map_problem(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint orig_offset, saved_offset, len_offset;
+ guint len;
+ guint tag;
+ proto_tree *subtree;
+ proto_item *item = NULL;
+ gchar *str = NULL;
+ gchar *type_str = NULL;
+ gint32 spec;
+ gboolean def_len;
+
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ len_offset = asn1->offset;
+ asn1_length_decode(asn1, &def_len, &len);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Problem Code");
+
+ subtree = proto_item_add_subtree(item, ett_problem);
+
+ if (!def_len)
+ {
+ len = tcap_find_eoc(asn1);
+ }
+
+ proto_item_set_len(item, (asn1->offset - saved_offset) + len +
+ (def_len ? 0 : TCAP_EOC_LEN));
+
+ if (len != 1)
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ asn1->offset, len, "Unknown encoding of Problem Code");
+
+ asn1->offset += len;
+
+ if (!def_len)
+ {
+ asn1_eoc_decode(asn1, -1);
+ }
+
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &spec);
+
+ switch (tag)
+ {
+ case MAP_GE_PROBLEM_TAG:
+ type_str = "General Problem";
+ switch (spec)
+ {
+ case 0: str = "Unrecognized Component"; break;
+ case 1: str = "Mistyped Component"; break;
+ case 2: str = "Badly Structured Component"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case MAP_IN_PROBLEM_TAG:
+ type_str = "Invoke";
+ switch (spec)
+ {
+ case 0: str = "Duplicate Invoke ID"; break;
+ case 1: str = "Unrecognized Operation"; break;
+ case 2: str = "Mistyped Parameter"; break;
+ case 3: str = "Resource Limitation"; break;
+ case 4: str = "Initiating Release"; break;
+ case 5: str = "Unrecognized Linked ID"; break;
+ case 6: str = "Linked Response Unexpected"; break;
+ case 7: str = "Unexpected Linked Operation"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case MAP_RR_PROBLEM_TAG:
+ type_str = "Return Result";
+ switch (spec)
+ {
+ case 0: str = "Unrecognized Invoke ID"; break;
+ case 1: str = "Return Result Unexpected"; break;
+ case 2: str = "Mistyped Parameter"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case MAP_RE_PROBLEM_TAG:
+ type_str = "Return Error";
+ switch (spec)
+ {
+ case 0: str = "Unrecognized Invoke ID"; break;
+ case 1: str = "Return Error Unexpected"; break;
+ case 2: str = "Unrecognized Error"; break;
+ case 3: str = "Unexpected Error"; break;
+ case 4: str = "Mistyped Parameter"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ default:
+ type_str = "Undefined";
+ break;
+ }
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ orig_offset, len_offset - orig_offset,
+ "%s: %02x", type_str, tag);
+
+ if (def_len)
+ {
+ proto_tree_add_uint(subtree, hf_map_length, asn1->tvb,
+ len_offset, saved_offset - len_offset, len);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ len_offset, saved_offset - len_offset, "Length: Indefinite");
+ }
+
+ proto_tree_add_text(subtree, asn1->tvb, saved_offset, 1,
+ "Problem Specifier %s", str);
+}
+
+
+static int
+dissect_map_lnkId(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ proto_item *item, *null_item;
+ proto_tree *subtree;
+ gboolean def_len;
+
+ if (tcap_check_tag(asn1, TCAP_LINKED_ID_TAG))
+ {
+ saved_offset = asn1->offset;
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, -1, "Linked Id");
+
+ subtree = proto_item_add_subtree(item, ett_component);
+
+ tag = -1;
+ dissect_map_tag(asn1, tree, &tag, "Linked Id Tag", &null_item);
+ dissect_map_len(asn1, tree, &def_len, &len);
+ dissect_map_integer(asn1, tree, len, "Linked Id:");
+
+ proto_item_set_len(item, asn1->offset - saved_offset);
+ }
+
+ return(MAP_OK);
+}
+
+
+static int
+dissect_map_opr_code(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree, gint *op_idx_p, guint *opr_code_p)
+{
+ guint opr_offset = 0, saved_offset = 0;
+ guint len;
+ guint tag;
+ gint32 val;
+ gchar *str = NULL;
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean def_len;
+
+ if (tcap_check_tag(asn1, MAP_OPR_CODE_TAG))
+ {
+ opr_offset = asn1->offset;
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, opr_offset, -1,
+ "Operation Code");
+
+ subtree = proto_item_add_subtree(item, ett_opr_code);
+
+ tag = -1;
+ asn1_id_decode1(asn1, &tag);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ opr_offset, asn1->offset - opr_offset,
+ "Operation Code Tag: 0x%02x", tag);
+
+ dissect_map_len(asn1, subtree, &def_len, &len);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &val);
+ proto_tree_add_int(subtree, hf_map_opr_code, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset, val);
+
+ proto_item_set_len(item, asn1->offset - opr_offset);
+
+ str = my_match_strval(val, gsm_map_opr_code_strings, op_idx_p);
+
+ if (NULL == str) return(MAP_FAIL);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
+ }
+
+ *opr_code_p = val;
+ }
+
+ return(MAP_OK);
+}
+
+
+static int
+dissect_map_eoc(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset;
+
+ saved_offset = asn1->offset;
+
+ if (tvb_length_remaining(asn1->tvb, saved_offset) <= 0)
+ {
+ return(MAP_FAIL);
+ }
+
+ if (!asn1_eoc(asn1, -1))
+ {
+ return(MAP_FAIL);
+ }
+
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+
+ return(MAP_OK);
+}
+
+
+static void
+dissect_map_invoke(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *subtree;
+ guint orig_offset, saved_offset;
+ guint len;
+ guint tag;
+ proto_item *item;
+ gint op_idx;
+ gboolean def_len;
+ int ret;
+ int opr_code_sts;
+ static gsm_map_tap_rec_t tap_rec;
+
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
+
+ subtree =
+ proto_item_add_subtree(item, ett_components);
+
+ proto_tree_add_text(subtree, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset,
+ "Invoke Type Tag: 0x%02x", tag);
+
+ dissect_map_len(asn1, subtree, &def_len, &len);
+
+ saved_offset = asn1->offset;
+
+ dissect_map_invokeId(asn1, subtree);
+
+ dissect_map_lnkId(asn1, subtree);
+
+ opr_code_sts = dissect_map_opr_code(asn1, pinfo, subtree, &op_idx, &g_opr_code);
+
+ if (opr_code_sts == MAP_OK)
+ {
+ if (def_len)
+ {
+ len -= asn1->offset - saved_offset;
+ }
+ else
+ {
+ len = tcap_find_eoc(asn1);
+ }
+
+ /*
+ * decode elements
+ */
+ if (op_fcn[op_idx] == NULL)
+ {
+ dissect_map_params(asn1, subtree, len);
+ }
+ else
+ {
+ (*op_fcn[op_idx])(asn1, subtree, len);
+ }
+ }
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(item, asn1->offset - orig_offset);
+
+ if (opr_code_sts == MAP_OK)
+ {
+ tap_rec.invoke = TRUE;
+ tap_rec.opr_code_idx = op_idx;
+ tap_rec.size = asn1->offset - orig_offset;
+
+ tap_queue_packet(gsm_map_tap, pinfo, &tap_rec);
+ }
+}
+
+
+static void
+dissect_map_rr(ASN1_SCK *asn1, packet_info *pinfo, proto_tree *tree, gchar *str)
+{
+ guint tag, len, comp_len;
+ gint op_idx;
+ guint orig_offset, saved_offset;
+ proto_item *item;
+ proto_tree *seq_subtree, *subtree;
+ gboolean def_len;
+ gboolean comp_def_len;
+ int opr_code_sts;
+ static gsm_map_tap_rec_t tap_rec;
+
+ tag = -1;
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
+
+ subtree =
+ proto_item_add_subtree(item, ett_components);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s: %02x", str, tag);
+
+ dissect_map_len(asn1, subtree, &comp_def_len, &comp_len);
+
+ saved_offset = asn1->offset;
+
+ dissect_map_invokeId(asn1, subtree);
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
+ {
+ proto_item_set_len(item, asn1->offset - orig_offset);
+
+ return;
+ }
+
+ saved_offset = asn1->offset;
+
+ tag = -1;
+ asn1_id_decode1(asn1, &tag);
+
+ opr_code_sts = MAP_FAIL;
+
+ if (TCAP_CONSTRUCTOR(tag))
+ {
+ GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Sequence",
+ ett_sequence,
+ &def_len, &len, seq_subtree);
+
+ saved_offset = asn1->offset;
+
+ opr_code_sts = dissect_map_opr_code(asn1, pinfo, seq_subtree, &op_idx, &g_opr_code);
+
+ if (opr_code_sts == MAP_OK)
+ {
+ len -= asn1->offset - saved_offset;
+
+ /*
+ * decode elements
+ */
+ if (op_fcn_rr[op_idx] == NULL)
+ {
+ dissect_map_params(asn1, seq_subtree, len);
+ }
+ else
+ {
+ (*op_fcn_rr[op_idx])(asn1, seq_subtree, len);
+ }
+ }
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, seq_subtree);
+ }
+ }
+
+ if (!comp_def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(item, asn1->offset - orig_offset);
+
+ if (opr_code_sts == MAP_OK)
+ {
+ tap_rec.invoke = FALSE;
+ tap_rec.opr_code_idx = op_idx;
+ tap_rec.size = asn1->offset - orig_offset;
+
+ tap_queue_packet(gsm_map_tap, pinfo, &tap_rec);
+ }
+}
+
+
+static int
+dissect_map_re(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint tag, len, comp_len;
+ guint orig_offset, saved_offset;
+ proto_item *item;
+ proto_tree *subtree, *temp_subtree;
+ gboolean comp_def_len, def_len;
+ gchar *str;
+ gint32 int_val;
+
+ tag = -1;
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
+
+ subtree = proto_item_add_subtree(item, ett_components);
+
+ proto_tree_add_text(subtree, asn1->tvb, saved_offset, asn1->offset - saved_offset,
+ "Return Error Type Tag: 0x%02x", tag);
+
+ dissect_map_len(asn1, subtree, &comp_def_len, &comp_len);
+
+ if (!comp_def_len)
+ {
+ comp_len = tcap_find_eoc(asn1);
+ }
+
+ saved_offset = asn1->offset;
+
+ dissect_map_invokeId(asn1, subtree);
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+#define MAP_LOCAL_ERR_CODE_TAG 0x2
+#define MAP_GBL_ERR_CODE_TAG 0x6
+
+ switch (tag)
+ {
+ case MAP_LOCAL_ERR_CODE_TAG:
+ GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Local Error Code",
+ ett_err_code,
+ &def_len, &len, temp_subtree);
+
+ if (len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &int_val);
+
+ str = match_strval(int_val, gsm_ss_err_code_strings);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, len, "Error Code: %s (%d)",
+ (str == NULL) ? "Unknown Error Code" : str,
+ int_val);
+ }
+ break;
+
+ case MAP_GBL_ERR_CODE_TAG:
+ GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Global Error Code",
+ ett_err_code,
+ &def_len, &len, temp_subtree);
+
+ if (len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &int_val);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, len, "Error Code: %d",
+ int_val);
+ }
+ break;
+
+ default:
+ GSM_MAP_START_SUBTREE(subtree, saved_offset, tag, "Unknown Error Code",
+ ett_err_code,
+ &def_len, &len, temp_subtree);
+
+ if (len > 0)
+ {
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &int_val);
+
+ proto_tree_add_text(temp_subtree, asn1->tvb,
+ saved_offset, len, "Error Code: %d",
+ int_val);
+ }
+ break;
+ }
+
+ dissect_map_params(asn1, subtree, comp_len - (asn1->offset - saved_offset));
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(item, asn1->offset - orig_offset);
+
+ return(MAP_OK);
+}
+
+
+static void
+dissect_map_reject(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint tag, len;
+ guint saved_offset;
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean def_len;
+
+ tag = -1;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
+
+ subtree = proto_item_add_subtree(item, ett_components);
+
+ proto_tree_add_text(subtree, asn1->tvb, saved_offset, asn1->offset - saved_offset,
+ "Reject Type Tag: 0x%02x", tag);
+
+ dissect_map_len(asn1, subtree, &def_len, &len);
+
+ dissect_map_invokeId(asn1, subtree);
+ dissect_map_problem(asn1, subtree);
+
+ if (!def_len)
+ {
+ dissect_map_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(item, asn1->offset - saved_offset);
+}
+
+
+static void
+dissect_map_message(packet_info *pinfo, proto_tree *map_tree, ASN1_SCK *asn1)
+{
+ guint saved_offset;
+ gchar *str = NULL;
+ static int i = 0;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &g_comp_type_tag);
+ asn1->offset = saved_offset;
+
+ str = match_strval(g_comp_type_tag, tcap_component_type_str);
+
+ if (NULL == str) return;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (0 == i)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "& %s ", str);
+ }
+ }
+
+ switch(g_comp_type_tag)
+ {
+ case TCAP_COMP_INVOKE :
+ dissect_map_invoke(asn1, pinfo, map_tree);
+ break;
+
+ case TCAP_COMP_RRL :
+ dissect_map_rr(asn1, pinfo, map_tree, "Return Result(Last) Type Tag");
+ break;
+
+ case TCAP_COMP_RE :
+ dissect_map_re(asn1, map_tree);
+ break;
+
+ case TCAP_COMP_REJECT :
+ dissect_map_reject(asn1, map_tree);
+ break;
+
+ case TCAP_COMP_RRN :
+ dissect_map_rr(asn1, pinfo, map_tree, "Return Result(Not Last) Type Tag");
+ break;
+
+ default:
+ proto_tree_add_text(map_tree, asn1->tvb, saved_offset, -1,
+ "Message type not handled, ignoring");
+ break;
+ }
+}
+
+
+static void
+dissect_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *map_tree;
+ ASN1_SCK asn1;
+ int offset = 0;
+
+ /*
+ * Make entries in Protocol column on summary display
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GSM MAP");
+ }
+
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree)
+ {
+ g_pinfo = pinfo;
+ g_tree = tree;
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_map, tvb, 0, -1, FALSE);
+
+ map_tree = proto_item_add_subtree(ti, ett_map);
+
+ asn1_open(&asn1, tvb, offset);
+
+ dissect_map_message(pinfo, map_tree, &asn1);
+
+ asn1_close(&asn1, &offset);
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+
+void
+proto_register_map(void)
+{
+ guint i;
+ gint last_offset;
+
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] =
+ {
+ { &hf_map_length,
+ { "Length", "map.len",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_map_opr_code,
+ { "Operation Code", "map.oprcode",
+ FT_INT32, BASE_DEC, VALS(gsm_map_opr_code_strings), 0,
+ "", HFILL }
+ },
+ { &hf_map_int,
+ { "Integer Data", "map.data",
+ FT_INT32, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_map_imsi,
+ { "IMSI", "map.imsi",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_map_addrstring,
+ { "AddressString", "map.addrstring",
+ FT_STRING, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ { &hf_map_rand,
+ { "RAND", "map.rand",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ },
+ { &hf_map_sres,
+ { "SRES", "map.sres",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ },
+ { &hf_map_kc,
+ { "Kc", "map.kc",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ },
+ { &hf_map_xres,
+ { "XRES", "map.xres",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ },
+ { &hf_map_ck,
+ { "CK", "map.ck",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ },
+ { &hf_map_ik,
+ { "IK", "map.ik",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ },
+ { &hf_map_autn,
+ { "AUTN", "map.autn",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+#define NUM_INDIVIDUAL_PARAMS 9
+ static gint *ett[NUM_INDIVIDUAL_PARAMS+(GSM_MAP_NUM_OP*2)+NUM_PARAM_1];
+
+ memset((void *) ett, 0, sizeof(ett));
+
+ ett[0] = &ett_map;
+ ett[1] = &ett_opr_code;
+ ett[2] = &ett_component;
+ ett[3] = &ett_components;
+ ett[4] = &ett_sequence;
+ ett[5] = &ett_param;
+ ett[6] = &ett_params;
+ ett[7] = &ett_problem;
+ ett[8] = &ett_err_code;
+
+ last_offset = NUM_INDIVIDUAL_PARAMS;
+
+ for (i=0; i < GSM_MAP_NUM_OP; i++, last_offset++)
+ {
+ ett_op[i] = -1;
+ ett[last_offset] = &ett_op[i];
+ }
+
+ for (i=0; i < GSM_MAP_NUM_OP; i++, last_offset++)
+ {
+ ett_op_rr[i] = -1;
+ ett[last_offset] = &ett_op_rr[i];
+ }
+
+ for (i=0; i < NUM_PARAM_1; i++, last_offset++)
+ {
+ ett_param_1[i] = -1;
+ ett[last_offset] = &ett_param_1[i];
+ }
+
+ /* Register the protocol name and description */
+ proto_map =
+ proto_register_protocol("GSM Mobile Application Part",
+ "GSM MAP", "gsm_map");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_map, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ sms_dissector_table =
+ register_dissector_table("gsm_map.sms_tpdu", "GSM SMS TPDU",
+ FT_UINT8, BASE_DEC);
+
+ gsm_map_tap = register_tap("gsm_map");
+}
+
+void
+proto_reg_handoff_map(void)
+{
+ dissector_handle_t map_handle;
+
+ map_handle = create_dissector_handle(dissect_map, proto_map);
+ dissector_add("tcap.itu_ssn", 6, map_handle);
+ dissector_add("tcap.itu_ssn", 7, map_handle);
+ dissector_add("tcap.itu_ssn", 8, map_handle);
+ dissector_add("tcap.itu_ssn", 9, map_handle);
+}
diff --git a/epan/dissectors/packet-gsm_map.h b/epan/dissectors/packet-gsm_map.h
new file mode 100644
index 0000000000..c313a8f1b8
--- /dev/null
+++ b/epan/dissectors/packet-gsm_map.h
@@ -0,0 +1,42 @@
+/* packet-gsm_map.h
+ *
+ * $Id$
+ *
+ * Copyright 2004, Michael Lum <mlum [AT] telostech.com>,
+ * In association with Telos Technology Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#define GSM_MAP_MAX_NUM_OPR_CODES 256
+
+typedef struct _gsm_map_tap_rec_t {
+ gboolean invoke;
+ guint8 opr_code_idx;
+ guint16 size;
+} gsm_map_tap_rec_t;
+
+
+/*
+ * the following allows TAP code access to the operations
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string gsm_map_opr_code_strings[];
diff --git a/epan/dissectors/packet-gsm_sms.c b/epan/dissectors/packet-gsm_sms.c
new file mode 100644
index 0000000000..2ae4cb7bd1
--- /dev/null
+++ b/epan/dissectors/packet-gsm_sms.c
@@ -0,0 +1,2628 @@
+/* packet-gsm_sms.c
+ * Routines for GSM SMS TPDU (GSM 03.40) dissection
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * TPDU User-Data unpack routines from GNOKII.
+ *
+ * Reference [1]
+ * Universal Mobile Telecommunications System (UMTS);
+ * Technical realization of Short Message Service (SMS)
+ * (3GPP TS 23.040 version 5.4.0 Release 5)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gmodule.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <string.h>
+
+#include "epan/packet.h"
+#include "prefs.h"
+
+#include "packet-gsm_sms.h"
+
+
+/* PROTOTYPES/FORWARDS */
+
+#define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
+ if ((edc_len) > (edc_max_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
+ }
+
+#define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
+ if ((sdc_len) < (sdc_min_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ offset, (sdc_len), "Short Data (?)"); \
+ return; \
+ }
+
+#define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
+ if ((edc_len) != (edc_eq_len)) \
+ { \
+ proto_tree_add_text(tree, tvb, \
+ offset, (edc_len), "Unexpected Data Length"); \
+ return; \
+ }
+
+#define SMS_SHIFTMASK(m_val, m_bitmask, m_sval); \
+ { \
+ int _temp_val = m_val; \
+ int _temp_bm = m_bitmask; \
+ while (_temp_bm && !(_temp_bm & 0x01)) \
+ { \
+ _temp_bm = _temp_bm >> 1; \
+ _temp_val = _temp_val >> 1; \
+ } \
+ m_sval = _temp_val; \
+ }
+
+
+static char *gsm_sms_proto_name = "GSM SMS TPDU (GSM 03.40)";
+static char *gsm_sms_proto_name_short = "GSM SMS";
+
+/* Initialize the subtree pointers */
+static gint ett_gsm_sms = -1;
+static gint ett_pid = -1;
+static gint ett_pi = -1;
+static gint ett_fcs = -1;
+static gint ett_vp = -1;
+static gint ett_scts = -1;
+static gint ett_dt = -1;
+static gint ett_st = -1;
+static gint ett_addr = -1;
+static gint ett_dcs = -1;
+static gint ett_ud = -1;
+static gint ett_udh = -1;
+
+/* Initialize the protocol and registered fields */
+static int proto_gsm_sms = -1;
+
+static char bigbuf[1024];
+static dissector_handle_t data_handle;
+static packet_info *g_pinfo;
+static proto_tree *g_tree;
+
+/*
+ * this is the GSM 03.40 definition with the bit 2
+ * set to 1 for uplink messages
+ */
+static const value_string msg_type_strings[] = {
+ { 0, "SMS-DELIVER" },
+ { 4, "SMS-DELIVER REPORT" },
+ { 5, "SMS-SUBMIT" },
+ { 1, "SMS-SUBMIT REPORT" },
+ { 2, "SMS-STATUS REPORT" },
+ { 6, "SMS-COMMAND" },
+ { 3, "Reserved" },
+ { 7, "Reserved" },
+ { 0, NULL },
+};
+
+#define NUM_UDH_IEIS 256
+static gint ett_udh_ieis[NUM_UDH_IEIS];
+
+/* FUNCTIONS */
+
+gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr) {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+/* 9.2.3.1 */
+#define DIS_FIELD_MTI(m_tree, m_bitmask, m_offset) \
+{ \
+ other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "%s : TP-Message-Type-Indicator", \
+ bigbuf); \
+}
+
+/* 9.2.3.2 */
+#define DIS_FIELD_MMS(m_tree, m_bitmask, m_offset) \
+{ \
+ other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "%s : TP-More-Messages-to-Send: %s messages are waiting for the MS in this SC", \
+ bigbuf, \
+ (oct & m_bitmask) ? "No more" : "More"); \
+}
+
+/* 9.2.3.3 */
+#define DIS_FIELD_VPF(m_tree, m_bitmask, m_offset, m_form) \
+{ \
+ SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, *m_form); \
+ switch (*m_form) \
+ { \
+ case 0: str = "TP-VP field not present"; break; \
+ case 1: str = "TP-VP field present - enhanced format"; break; \
+ case 2: str = "TP-VP field present - relative format"; break; \
+ case 3: str = "TP-VP field present - absolute format"; break; \
+ } \
+ other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "%s : TP-Validity-Period-Format: %s", \
+ bigbuf, \
+ str); \
+}
+
+/* 9.2.3.4 */
+#define DIS_FIELD_SRI(m_tree, m_bitmask, m_offset) \
+{ \
+ other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "%s : TP-Status-Report-Indication: A status report shall %sbe returned to the SME", \
+ bigbuf, \
+ (oct & m_bitmask) ? "" : "not "); \
+}
+
+/* 9.2.3.5 */
+#define DIS_FIELD_SRR(m_tree, m_bitmask, m_offset) \
+{ \
+ other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "%s : TP-Status-Report-Request: A status report is %srequested", \
+ bigbuf, \
+ (oct & m_bitmask) ? "" : "not "); \
+}
+
+/* 9.2.3.6 */
+#define DIS_FIELD_MR(m_tree, m_offset) \
+{ \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "TP-Message-Reference %d", \
+ oct); \
+}
+
+static void
+dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, gchar *title)
+{
+ static gchar digit_table[] = {"0123456789*#abc\0"};
+ proto_item *item;
+ proto_tree *subtree = NULL;
+ gchar *str = NULL;
+ guint8 oct;
+ guint32 offset;
+ guint32 numdigocts;
+ guint32 length;
+ guint32 i, j;
+
+
+ offset = *offset_p;
+
+ oct = tvb_get_guint8(tvb, offset);
+ numdigocts = (oct + 1) / 2;
+
+ length = tvb_length_remaining(tvb, offset);
+
+ if (length <= numdigocts)
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "%s: Short Data (?)",
+ title);
+
+ *offset_p += length;
+ return;
+ }
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, numdigocts + 2,
+ title);
+
+ subtree = proto_item_add_subtree(item, ett_addr);
+
+ proto_tree_add_text(subtree,
+ tvb, offset, 1,
+ "Length: %d address digits",
+ oct);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : %s",
+ bigbuf,
+ (oct & 0x80) ? "No extension" : "Extended");
+
+ switch ((oct & 0x70) >> 4)
+ {
+ case 0x00: str = "Unknown"; break;
+ case 0x01: str = "International"; break;
+ case 0x02: str = "National"; break;
+ case 0x07: str = "Reserved for extension"; break;
+ default: str = "Unknown, reserved (?)"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x70, 8);
+ proto_tree_add_text(subtree,
+ tvb, offset, 1,
+ "%s : Type of number: (%d) %s",
+ bigbuf,
+ (oct & 0x70) >> 4,
+ str);
+
+ switch (oct & 0x0f)
+ {
+ case 0x00: str = "Unknown"; break;
+ case 0x01: str = "ISDN/telephone"; break;
+ case 0x0f: str = "Reserved for extension"; break;
+ default: str = "Unknown, reserved (?)"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
+ proto_tree_add_text(subtree,
+ tvb, offset, 1,
+ "%s : Numbering plan: (%d) %s",
+ bigbuf,
+ oct & 0x0f,
+ str);
+
+ offset++;
+
+ j = 0;
+ for (i = 0; i < numdigocts; i++)
+ {
+ oct = tvb_get_guint8(tvb, offset + i);
+
+ bigbuf[j++] = digit_table[oct & 0x0f];
+ bigbuf[j++] = digit_table[(oct & 0xf0) >> 4];
+ }
+
+ bigbuf[j++] = '\0';
+
+ proto_tree_add_text(subtree,
+ tvb, offset, numdigocts,
+ "Digits: %s",
+ bigbuf);
+
+ proto_item_append_text(item, " - (%s)", bigbuf);
+
+ *offset_p = offset + i;
+}
+
+/* 9.2.3.7 */
+/* use dis_field_addr() */
+
+/* 9.2.3.8 */
+/* use dis_field_addr() */
+
+/* 9.2.3.9 */
+static void
+dis_field_pid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
+{
+ proto_item *item;
+ proto_tree *subtree = NULL;
+ guint8 form;
+ guint8 telematic;
+ gchar *str = NULL;
+
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, 1,
+ "TP-Protocol-Identifier");
+
+ subtree = proto_item_add_subtree(item, ett_pid);
+
+ form = (oct & 0xc0) >> 6;
+
+ switch (form)
+ {
+ case 0:
+ other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : defines formatting for subsequent bits",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : %s",
+ bigbuf,
+ (oct & 0x20) ?
+ "telematic interworking" :
+ "no telematic interworking, but SME-to-SME protocol");
+
+ if (oct & 0x20)
+ {
+ telematic = oct & 0x1f;
+
+ switch (telematic)
+ {
+ case 0x00: str = "implicit - device type is specific to this SC, or can be concluded on the basis of the address"; break;
+ case 0x01: str = "telex (or teletex reduced to telex format)"; break;
+ case 0x02: str = "group 3 telefax"; break;
+ case 0x03: str = "group 4 telefax"; break;
+ case 0x04: str = "voice telephone (i.e. conversion to speech)"; break;
+ case 0x05: str = "ERMES (European Radio Messaging System)"; break;
+ case 0x06: str = "National Paging system (known to the SC)"; break;
+ case 0x07: str = "Videotex (T.100 [20] /T.101 [21])"; break;
+ case 0x08: str = "teletex, carrier unspecified"; break;
+ case 0x09: str = "teletex, in PSPDN"; break;
+ case 0x0a: str = "teletex, in CSPDN"; break;
+ case 0x0b: str = "teletex, in analog PSTN"; break;
+ case 0x0c: str = "teletex, in digital ISDN"; break;
+ case 0x0d: str = "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)"; break;
+ case 0x10: str = "a message handling facility (known to the SC)"; break;
+ case 0x11: str = "any public X.400-based message handling system"; break;
+ case 0x12: str = "Internet Electronic Mail"; break;
+ case 0x1f: str = "A GSM/UMTS mobile station"; break;
+ default:
+ if ((telematic >= 0x18) &&
+ (telematic <= 0x1e))
+ {
+ str = "values specific to each SC";
+ }
+ else
+ {
+ str = "reserved";
+ }
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : device type: (%d) %s",
+ bigbuf,
+ telematic,
+ str);
+ }
+ else
+ {
+ other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : the SM-AL protocol being used between the SME and the MS (%d)",
+ bigbuf,
+ oct & 0x1f);
+ }
+ break;
+
+ case 1:
+ other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : defines formatting for subsequent bits",
+ bigbuf);
+
+ switch (oct & 0x3f)
+ {
+ case 0x00: str = "Short Message Type 0"; break;
+ case 0x01: str = "Replace Short Message Type 1"; break;
+ case 0x02: str = "Replace Short Message Type 2"; break;
+ case 0x03: str = "Replace Short Message Type 3"; break;
+ case 0x04: str = "Replace Short Message Type 4"; break;
+ case 0x05: str = "Replace Short Message Type 5"; break;
+ case 0x06: str = "Replace Short Message Type 6"; break;
+ case 0x07: str = "Replace Short Message Type 7"; break;
+ case 0x1e: str = "Enhanced Message Service (Obsolete)"; break;
+ case 0x1f: str = "Return Call Message"; break;
+ case 0x3c: str = "ANSI-136 R-DATA"; break;
+ case 0x3d: str = "ME Data download"; break;
+ case 0x3e: str = "ME De-personalization Short Message"; break;
+ case 0x3f: str = "(U)SIM Data download"; break;
+ default:
+ str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : (%d) %s",
+ bigbuf,
+ oct & 0x3f,
+ str);
+ break;
+
+ case 2:
+ other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : undefined",
+ bigbuf);
+ break;
+
+ case 3:
+ other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : bits 0-5 for SC specific use",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : SC specific",
+ bigbuf);
+ break;
+ }
+}
+
+/* 9.2.3.10 */
+static void
+dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct,
+ gboolean *seven_bit, gboolean *eight_bit, gboolean *ucs2, gboolean *compressed)
+{
+ proto_item *item;
+ proto_tree *subtree = NULL;
+ guint8 form;
+ gchar *str = NULL;
+ gboolean default_5_bits;
+ gboolean default_3_bits;
+ gboolean default_data;
+
+
+ *seven_bit = FALSE;
+ *eight_bit = FALSE;
+ *ucs2 = FALSE;
+ *compressed = FALSE;
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, 1,
+ "TP-Data-Coding-Scheme (%d)",
+ oct);
+
+ subtree = proto_item_add_subtree(item, ett_dcs);
+
+ if (oct == 0x00)
+ {
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "Special case, GSM 7 bit default alphabet");
+
+ *seven_bit = TRUE;
+ return;
+ }
+
+ default_5_bits = FALSE;
+ default_3_bits = FALSE;
+ default_data = FALSE;
+ form = (oct & 0xc0) >> 6;
+
+ switch (form)
+ {
+ case 0:
+ other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : General Data Coding indication",
+ bigbuf);
+
+ default_5_bits = TRUE;
+ break;
+
+ case 1:
+ other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Message Marked for Automatic Deletion Group",
+ bigbuf);
+
+ default_5_bits = TRUE;
+ break;
+
+ case 2:
+ /* use top four bits */
+ other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Reserved coding groups",
+ bigbuf);
+ return;
+
+ case 3:
+ switch ((oct & 0x30) >> 4)
+ {
+ case 0x00: str = "Message Waiting Indication Group: Discard Message (GSM 7 bit default alphabet)";
+ default_3_bits = TRUE;
+ *seven_bit = TRUE;
+ break;
+ case 0x01: str = "Message Waiting Indication Group: Store Message (GSM 7 bit default alphabet)";
+ default_3_bits = TRUE;
+ *seven_bit = TRUE;
+ break;
+ case 0x02: str = "Message Waiting Indication Group: Store Message (uncompressed UCS2 alphabet)";
+ default_3_bits = TRUE;
+ break;
+ case 0x03: str = "Data coding/message class";
+ default_data = TRUE;
+ break;
+ }
+
+ /* use top four bits */
+ other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : %s",
+ bigbuf,
+ str);
+ break;
+ }
+
+ if (default_5_bits)
+ {
+ other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Text is %scompressed",
+ bigbuf,
+ (oct & 0x20) ? "" : "not ");
+
+ *compressed = (oct & 0x20) >> 5;
+
+ other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : %s",
+ bigbuf,
+ (oct & 0x10) ? "Message class is defined below" :
+ "Reserved, no message class");
+
+ switch ((oct & 0x0c) >> 2)
+ {
+ case 0x00: str = "GSM 7 bit default alphabet";
+ *seven_bit = TRUE;
+ break;
+ case 0x01: str = "8 bit data"; break;
+ case 0x02: str = "UCS2 (16 bit)";
+ *ucs2 = TRUE;
+ break;
+ case 0x03: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x0c, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Character set: %s",
+ bigbuf,
+ str);
+
+ switch (oct & 0x03)
+ {
+ case 0x00: str = "Class 0"; break;
+ case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
+ case 0x02: str = "Class 2 (U)SIM specific message"; break;
+ case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Message Class: %s%s",
+ bigbuf,
+ str,
+ (oct & 0x10) ? "" : " (reserved)");
+ }
+ else if (default_3_bits)
+ {
+ other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Indication Sense: %s",
+ bigbuf,
+ (oct & 0x08) ? "Set Indication Active" : "Set Indication Inactive");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ switch (oct & 0x03)
+ {
+ case 0x00: str = "Voicemail Message Waiting"; break;
+ case 0x01: str = "Fax Message Waiting"; break;
+ case 0x02: str = "Electronic Mail Message Waiting"; break;
+ case 0x03: str = "Other Message Waiting"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : %s",
+ bigbuf,
+ str);
+ }
+ else if (default_data)
+ {
+ other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ *seven_bit = !(*eight_bit = (oct & 0x04) ? TRUE : FALSE);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Message coding: %s",
+ bigbuf,
+ (*eight_bit) ? "8 bit data" : "GSM 7 bit default alphabet");
+
+ switch (oct & 0x03)
+ {
+ case 0x00: str = "Class 0"; break;
+ case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
+ case 0x02: str = "Class 2 (U)SIM specific message"; break;
+ case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Message Class: %s",
+ bigbuf,
+ str);
+ }
+}
+
+static void
+dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+ guint8 oct, oct2, oct3;
+
+
+ oct = tvb_get_guint8(tvb, offset);
+ oct2 = tvb_get_guint8(tvb, offset+1);
+ oct3 = tvb_get_guint8(tvb, offset+2);
+
+ proto_tree_add_text(tree,
+ tvb, offset, 3,
+ "Year %d%d, Month %d%d, Day %d%d",
+ oct & 0x0f,
+ (oct & 0xf0) >> 4,
+ oct2 & 0x0f,
+ (oct2 & 0xf0) >> 4,
+ oct3 & 0x0f,
+ (oct3 & 0xf0) >> 4);
+
+ offset += 3;
+
+ oct = tvb_get_guint8(tvb, offset);
+ oct2 = tvb_get_guint8(tvb, offset+1);
+ oct3 = tvb_get_guint8(tvb, offset+2);
+
+ proto_tree_add_text(tree,
+ tvb, offset, 3,
+ "Hour %d%d, Minutes %d%d, Seconds %d%d",
+ oct & 0x0f,
+ (oct & 0xf0) >> 4,
+ oct2 & 0x0f,
+ (oct2 & 0xf0) >> 4,
+ oct3 & 0x0f,
+ (oct3 & 0xf0) >> 4);
+
+ offset += 3;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text(tree,
+ tvb, offset, 1,
+ "Timezone %d",
+ oct);
+}
+
+/* 9.2.3.11 */
+static void
+dis_field_scts(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
+{
+ proto_item *item;
+ proto_tree *subtree = NULL;
+ guint32 offset;
+ guint32 length;
+
+
+ offset = *offset_p;
+
+ length = tvb_length_remaining(tvb, offset);
+
+ if (length < 7)
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "TP-Service-Centre-Time-Stamp: Short Data (?)");
+
+ *offset_p += length;
+ return;
+ }
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, 7,
+ "TP-Service-Centre-Time-Stamp");
+
+ subtree = proto_item_add_subtree(item, ett_scts);
+
+ dis_field_scts_aux(tvb, subtree, *offset_p);
+
+ *offset_p += 7;
+}
+
+/* 9.2.3.12 */
+static void
+dis_field_vp(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, guint8 vp_form)
+{
+ proto_item *item;
+ proto_tree *subtree = NULL;
+ guint32 offset;
+ guint32 length;
+ guint8 oct, oct2, oct3;
+ guint8 loc_form;
+ guint32 mins, hours;
+ gboolean done;
+
+
+ if (vp_form == 0x00) return;
+
+ offset = *offset_p;
+ subtree = tree;
+
+ done = FALSE;
+ do
+ {
+ switch (vp_form)
+ {
+ case 1:
+ length = tvb_length_remaining(tvb, offset);
+
+ if (length < 7)
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "TP-Validity-Period: Short Data (?)");
+
+ *offset_p += length;
+ return;
+ }
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, 7,
+ "TP-Validity-Period");
+
+ subtree = proto_item_add_subtree(item, ett_vp);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : %s",
+ bigbuf,
+ (oct & 0x80) ? "Extended" : "No extension");
+
+ if (oct & 0x80)
+ {
+ proto_tree_add_text(subtree,
+ tvb, offset + 1, 6,
+ "Extension not implemented, ignored");
+
+ *offset_p += 7;
+ return;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : %s",
+ bigbuf,
+ (oct & 0x40) ? "Single shot SM" : "Not single shot SM");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x38, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ loc_form = oct & 0x7;
+
+ switch (loc_form)
+ {
+ case 0x00:
+ other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : No Validity Period specified",
+ bigbuf);
+
+ done = TRUE;
+ break;
+
+ case 0x01:
+ other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Validity Period Format: relative",
+ bigbuf);
+
+ /* go around again */
+ vp_form = 2;
+ break;
+
+ case 0x02:
+ other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Validity Period Format: relative",
+ bigbuf);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%d seconds",
+ oct);
+
+ done = TRUE;
+ break;
+
+ case 0x03:
+ other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Validity Period Format: relative",
+ bigbuf);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+ oct2 = tvb_get_guint8(tvb, offset+1);
+ oct3 = tvb_get_guint8(tvb, offset+2);
+
+ proto_tree_add_text(subtree,
+ tvb, offset, 3,
+ "Hour %d%d, Minutes %d%d, Seconds %d%d",
+ (oct & 0xf0) >> 4,
+ oct & 0x0f,
+ (oct2 & 0xf0) >> 4,
+ oct2 & 0x0f,
+ (oct3 & 0xf0) >> 4,
+ oct3 & 0x0f);
+
+ done = TRUE;
+ break;
+
+ default:
+ other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Validity Period Format: Reserved",
+ bigbuf);
+
+ done = TRUE;
+ break;
+ }
+ break;
+
+ case 2:
+ oct = tvb_get_guint8(tvb, offset);
+
+ if (oct <= 143)
+ {
+ mins = (oct + 1) * 5;
+ if (mins >= 60)
+ {
+ hours = mins / 60;
+ mins %= 60;
+
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "TP-Validity-Period: %d hours %d minutes",
+ hours,
+ mins);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "TP-Validity-Period: %d minutes",
+ mins);
+ }
+ }
+ else if ((oct >= 144) &&
+ (oct <= 167))
+ {
+ mins = (oct - 143) * 30;
+ hours = 12 + (mins / 60);
+ mins %= 60;
+
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "TP-Validity-Period: %d hours %d minutes",
+ hours,
+ mins);
+ }
+ else if ((oct >= 168) &&
+ (oct <= 196))
+ {
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "TP-Validity-Period: %d day(s)",
+ oct - 166);
+ }
+ else if (oct >= 197)
+ {
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "TP-Validity-Period: %d week(s)",
+ oct - 192);
+ }
+
+ done = TRUE;
+ break;
+
+ case 3:
+ length = tvb_length_remaining(tvb, offset);
+
+ if (length < 7)
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "TP-Validity-Period: Short Data (?)");
+
+ *offset_p += length;
+ return;
+ }
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, 7,
+ "TP-Validity-Period: absolute");
+
+ subtree = proto_item_add_subtree(item, ett_vp);
+
+ dis_field_scts_aux(tvb, subtree, *offset_p);
+
+ done = TRUE;
+ break;
+ }
+ }
+ while (!done);
+
+ if (vp_form == 2)
+ {
+ (*offset_p)++;
+ }
+ else
+ {
+ *offset_p += 7;
+ }
+}
+
+/* 9.2.3.13 */
+static void
+dis_field_dt(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
+{
+ proto_item *item;
+ proto_tree *subtree = NULL;
+ guint32 offset;
+ guint32 length;
+
+
+ offset = *offset_p;
+
+ length = tvb_length_remaining(tvb, offset);
+
+ if (length < 7)
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "TP-Discharge-Time: Short Data (?)");
+
+ *offset_p += length;
+ return;
+ }
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, 7,
+ "TP-Discharge-Time");
+
+ subtree = proto_item_add_subtree(item, ett_dt);
+
+ dis_field_scts_aux(tvb, subtree, *offset_p);
+
+ *offset_p += 7;
+}
+
+/* 9.2.3.14 */
+/* use dis_field_addr() */
+
+/* 9.2.3.15 */
+static void
+dis_field_st(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
+{
+ static gchar *sc_complete = "Short message transaction completed";
+ static gchar *sc_temporary = "Temporary error, SC still trying to transfer SM";
+ static gchar *sc_perm = "Permanent error, SC is not making any more transfer attempts";
+ static gchar *sc_tempfin = "Temporary error, SC is not making any more transfer attempts";
+ proto_item *item;
+ proto_tree *subtree = NULL;
+ guint8 value;
+ gchar *str = NULL;
+ gchar *str2 = NULL;
+
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, 1,
+ "TP-Status");
+
+ subtree = proto_item_add_subtree(item, ett_st);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Definition of bits 0-6: %s",
+ bigbuf,
+ (oct & 0x80) ? "Reserved" : "as follows");
+
+ value = oct & 0x7f;
+
+ switch (value)
+ {
+ case 0x00: str2 = sc_complete; str = "Short message received by the SME"; break;
+ case 0x01: str2 = sc_complete; str = "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
+ case 0x02: str2 = sc_complete; str = "Short message replaced by the SC Reserved values"; break;
+
+ case 0x20: str2 = sc_temporary; str = "Congestion"; break;
+ case 0x21: str2 = sc_temporary; str = "SME busy"; break;
+ case 0x22: str2 = sc_temporary; str = "No response from SME"; break;
+ case 0x23: str2 = sc_temporary; str = "Service rejected"; break;
+ case 0x24: str2 = sc_temporary; str = "Quality of service not available"; break;
+ case 0x25: str2 = sc_temporary; str = "Error in SME"; break;
+
+ case 0x40: str2 = sc_perm; str = "Remote procedure error"; break;
+ case 0x41: str2 = sc_perm; str = "Incompatible destination"; break;
+ case 0x42: str2 = sc_perm; str = "Connection rejected by SME"; break;
+ case 0x43: str2 = sc_perm; str = "Not obtainable"; break;
+ case 0x44: str2 = sc_perm; str = "Quality of service not available"; break;
+ case 0x45: str2 = sc_perm; str = "No interworking available"; break;
+ case 0x46: str2 = sc_perm; str = "SM Validity Period Expired"; break;
+ case 0x47: str2 = sc_perm; str = "SM Deleted by originating SME"; break;
+ case 0x48: str2 = sc_perm; str = "SM Deleted by SC Administration"; break;
+ case 0x49: str2 = sc_perm; str = "SM does not exist (The SM may have previously existed in the SC but the SC no longer has knowledge of it or the SM may never have previously existed in the SC)"; break;
+
+ case 0x60: str2 = sc_tempfin; str = "Congestion"; break;
+ case 0x61: str2 = sc_tempfin; str = "SME busy"; break;
+ case 0x62: str2 = sc_tempfin; str = "No response from SME"; break;
+ case 0x63: str2 = sc_tempfin; str = "Service rejected"; break;
+ case 0x64: str2 = sc_tempfin; str = "Quality of service not available"; break;
+ case 0x65: str2 = sc_tempfin; str = "Error in SME"; break;
+
+ default:
+ if ((value >= 0x03) &&
+ (value <= 0x0f))
+ {
+ str2 = sc_complete;
+ str = "Reserved";
+ }
+ else if ((value >= 0x10) &&
+ (value <= 0x1f))
+ {
+ str2 = sc_complete;
+ str = "Values specific to each SC";
+ }
+ else if ((value >= 0x26) &&
+ (value <= 0x2f))
+ {
+ str2 = sc_temporary;
+ str = "Reserved";
+ }
+ else if ((value >= 0x30) &&
+ (value <= 0x3f))
+ {
+ str2 = sc_temporary;
+ str = "Values specific to each SC";
+ }
+ else if ((value >= 0x4a) &&
+ (value <= 0x4f))
+ {
+ str2 = sc_perm;
+ str = "Reserved";
+ }
+ else if ((value >= 0x50) &&
+ (value <= 0x5f))
+ {
+ str2 = sc_perm;
+ str = "Values specific to each SC";
+ }
+ else if ((value >= 0x66) &&
+ (value <= 0x6f))
+ {
+ str2 = sc_tempfin;
+ str = "Reserved";
+ }
+ else if ((value >= 0x70) &&
+ (value <= 0x7f))
+ {
+ str2 = sc_tempfin;
+ str = "Values specific to each SC";
+ }
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : (%d) %s, %s",
+ bigbuf,
+ value,
+ str2,
+ str);
+}
+
+/* 9.2.3.16 */
+#define DIS_FIELD_UDL(m_tree, m_offset) \
+{ \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "TP-User-Data-Length: (%d) %s", \
+ oct, \
+ oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
+}
+
+/* 9.2.3.17 */
+#define DIS_FIELD_RP(m_tree, m_bitmask, m_offset) \
+{ \
+ other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "%s : TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
+ bigbuf, \
+ (oct & m_bitmask) ? "" : "not "); \
+}
+
+/* 9.2.3.18 */
+#define DIS_FIELD_MN(m_tree, m_offset) \
+{ \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "TP-Message-Number: %d", \
+ oct); \
+}
+
+/* 9.2.3.19 */
+#define DIS_FIELD_CT(m_tree, m_offset) \
+{ \
+ switch (oct) \
+ { \
+ case 0: str = "Enquiry relating to previously submitted short message"; break; \
+ case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
+ case 2: str = "Delete previously submitted Short Message"; break; \
+ case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
+ default: \
+ if ((oct >= 0x04) && \
+ (oct <= 0x1f)) \
+ { \
+ str = "Reserved unspecified"; \
+ } \
+ else if (oct >= 0xe0) \
+ { \
+ str = "Values specific for each SC"; \
+ } \
+ else \
+ { \
+ str = "undefined"; \
+ } \
+ break; \
+ } \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "TP-Command-Type: (%d), %s", \
+ oct, \
+ str); \
+}
+
+/* 9.2.3.20 */
+#define DIS_FIELD_CDL(m_tree, m_offset) \
+{ \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "TP-Command-Data-Length: (%d)%s", \
+ oct, \
+ oct ? "" : " no Command-Data");\
+}
+
+/* 9.2.3.21 */
+/* done in-line in the message functions */
+
+/* 9.2.3.22 */
+static void
+dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
+{
+ proto_item *item;
+ proto_tree *subtree = NULL;
+ gchar *str = NULL;
+
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, 1,
+ "TP-Failure-Cause");
+
+ subtree = proto_item_add_subtree(item, ett_fcs);
+
+ switch (oct)
+ {
+ case 0x80: str = "Telematic interworking not supported"; break;
+ case 0x81: str = "Short message Type 0 not supported"; break;
+ case 0x82: str = "Cannot replace short message"; break;
+ case 0x8F: str = "Unspecified TP-PID error"; break;
+ case 0x90: str = "Data coding scheme (alphabet) not supported"; break;
+ case 0x91: str = "Message class not supported"; break;
+ case 0x9F: str = "Unspecified TP-DCS error"; break;
+ case 0xA0: str = "Command cannot be actioned"; break;
+ case 0xA1: str = "Command unsupported"; break;
+ case 0xAF: str = "Unspecified TP-Command error"; break;
+ case 0xB0: str = "TPDU not supported"; break;
+ case 0xC0: str = "SC busy"; break;
+ case 0xC1: str = "No SC subscription"; break;
+ case 0xC2: str = "SC system failure"; break;
+ case 0xC3: str = "Invalid SME address"; break;
+ case 0xC4: str = "Destination SME barred"; break;
+ case 0xC5: str = "SM Rejected-Duplicate SM"; break;
+ case 0xC6: str = "TP-VPF not supported"; break;
+ case 0xC7: str = "TP-VP not supported"; break;
+ case 0xD0: str = "(U)SIM SMS storage full"; break;
+ case 0xD1: str = "No SMS storage capability in (U)SIM"; break;
+ case 0xD2: str = "Error in MS"; break;
+ case 0xD3: str = "Memory Capacity Exceeded"; break;
+ case 0xD4: str = "(U)SIM Application Toolkit Busy"; break;
+ case 0xD5: str = "(U)SIM data download error"; break;
+ case 0xFF: str = "Unspecified error cause"; break;
+ default:
+ if ((oct >= 0x80) &&
+ (oct <= 0x8F))
+ {
+ str = "TP-PID errors"; break;
+ }
+ else if ((oct >= 0x90) &&
+ (oct <= 0x9F))
+ {
+ str = "TP-DCS errors"; break;
+ }
+ else if ((oct >= 0xA0) &&
+ (oct <= 0xAF))
+ {
+ str = "TP-Command errors"; break;
+ }
+ else if ((oct >= 0xE0) &&
+ (oct <= 0xFE))
+ {
+ str = "Values specific to an application"; break;
+ }
+ else
+ {
+ str = "Reserved"; break;
+ }
+ }
+
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ str);
+}
+
+/* 9.2.3.23 */
+#define DIS_FIELD_UDHI(m_tree, m_bitmask, m_offset, m_udhi) \
+{ \
+ SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, m_udhi); \
+ other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "%s : TP-User-Data-Header-Indicator: %s short message", \
+ bigbuf, \
+ m_udhi ? \
+ "The beginning of the TP-UD field contains a Header in addition to the" : \
+ "The TP-UD field contains only the"); \
+}
+
+/*
+ * FROM GNOKII
+ * gsm-encoding.c
+ * gsm-sms.c
+ */
+#define GN_BYTE_MASK ((1 << bits) - 1)
+
+int
+gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
+ const guint8 *input, unsigned char *output)
+{
+ unsigned char *out_num = output; /* Current pointer to the output buffer */
+ const guint8 *in_num = input; /* Current pointer to the input buffer */
+ unsigned char rest = 0x00;
+ int bits;
+
+ bits = offset ? offset : 7;
+
+ while ((unsigned int)(in_num - input) < in_length)
+ {
+ *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest;
+ rest = *in_num >> bits;
+
+ /* If we don't start from 0th bit, we shouldn't go to the
+ next char. Under *out_num we have now 0 and under Rest -
+ _first_ part of the char. */
+ if ((in_num != input) || (bits == 7)) out_num++;
+ in_num++;
+
+ if ((unsigned int)(out_num - output) >= out_length) break;
+
+ /* After reading 7 octets we have read 7 full characters but
+ we have 7 bits as well. This is the next character */
+ if (bits == 1)
+ {
+ *out_num = rest;
+ out_num++;
+ bits = 7;
+ rest = 0x00;
+ }
+ else
+ {
+ bits--;
+ }
+ }
+
+ return out_num - output;
+}
+
+#define GN_CHAR_ALPHABET_SIZE 128
+
+#define GN_CHAR_ESCAPE 0x1b
+
+static unsigned char gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
+
+ /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
+ /* Characters in hex position 10, [12 to 1a] and 24 are not present on
+ latin1 charset, so we cannot reproduce on the screen, however they are
+ greek symbol not present even on my Nokia */
+
+ '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
+ 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
+ '?', '_', '?', '?', '?', '?', '?', '?',
+ '?', '?', '?', '?', 0xc6, 0xe6, 0xdf, 0xc9,
+ ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
+ '(', ')', '*', '+', ',', '-', '.', '/',
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', ':', ';', '<', '=', '>', '?',
+ 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
+ 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
+};
+
+static gboolean
+char_is_escape(unsigned char value)
+{
+ return (value == GN_CHAR_ESCAPE);
+}
+
+static unsigned char
+char_def_alphabet_ext_decode(unsigned char value)
+{
+ switch (value)
+ {
+ case 0x0a: return 0x0c; break; /* form feed */
+ case 0x14: return '^'; break;
+ case 0x28: return '{'; break;
+ case 0x29: return '}'; break;
+ case 0x2f: return '\\'; break;
+ case 0x3c: return '['; break;
+ case 0x3d: return '~'; break;
+ case 0x3e: return ']'; break;
+ case 0x40: return '|'; break;
+ case 0x65: return 0xa4; break; /* euro */
+ default: return '?'; break; /* invalid character */
+ }
+}
+
+static unsigned char
+char_def_alphabet_decode(unsigned char value)
+{
+ if (value < GN_CHAR_ALPHABET_SIZE)
+ {
+ return gsm_default_alphabet[value];
+ }
+ else
+ {
+ return '?';
+ }
+}
+
+void
+gsm_sms_char_ascii_decode(unsigned char* dest, const unsigned char* src, int len)
+{
+ int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j++)
+ {
+ if (char_is_escape(src[j]))
+ dest[i] = char_def_alphabet_ext_decode(src[++j]);
+ else
+ dest[i] = char_def_alphabet_decode(src[j]);
+ }
+ dest[i] = 0;
+ return;
+}
+
+/*
+ * END FROM GNOKII
+ */
+
+static void
+dis_iei_apa_8bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
+{
+ gchar *str = NULL;
+ guint8 oct;
+
+
+ EXACT_DATA_CHECK(length, 2);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ if (oct < 240)
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = "Available for allocation by applications";
+ }
+
+ proto_tree_add_text(tree,
+ tvb, offset, 1,
+ "Destination port: %d, %s",
+ oct,
+ str);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ if (oct < 240)
+ {
+ str = "Reserved";
+ }
+ else
+ {
+ str = "Available for allocation by applications";
+ }
+
+ proto_tree_add_text(tree,
+ tvb, offset, 1,
+ "Originator port: %d, %s",
+ oct,
+ str);
+}
+
+static void
+dis_iei_apa_16bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
+{
+ gchar *str = NULL;
+ guint32 value;
+
+
+ EXACT_DATA_CHECK(length, 4);
+
+ value = tvb_get_ntohs(tvb, offset);
+
+ if (value < 16000)
+ {
+ str = "As allocated by IANA (http://www.IANA.com/)";
+ }
+ else if (value < 17000)
+ {
+ str = "Available for allocation by applications";
+ }
+ else
+ {
+ str = "Reserved";
+ }
+
+ proto_tree_add_text(tree,
+ tvb, offset, 2,
+ "Destination port: %d, %s",
+ value,
+ str);
+
+ offset += 2;
+ value = tvb_get_ntohs(tvb, offset);
+
+ if (value < 16000)
+ {
+ str = "As allocated by IANA (http://www.IANA.com/)";
+ }
+ else if (value < 17000)
+ {
+ str = "Available for allocation by applications";
+ }
+ else
+ {
+ str = "Reserved";
+ }
+
+ proto_tree_add_text(tree,
+ tvb, offset, 2,
+ "Originator port: %d, %s",
+ value,
+ str);
+}
+
+static void
+dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
+{
+ void (*iei_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length);
+ guint8 oct;
+ proto_item *item;
+ proto_tree *subtree = NULL;
+ gchar *str = NULL;
+ guint8 iei_len;
+
+
+ while (length > 2)
+ {
+ iei_fcn = NULL;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ switch (oct)
+ {
+ case 0x00: str = "Concatenated short messages, 8-bit reference number (SMS Control)"; break;
+ case 0x01: str = "Special SMS Message Indication (SMS Control)"; break;
+ case 0x02: str = "Reserved N/A"; break;
+ case 0x03: str = "Value not used to avoid misinterpretation as <LF> character N/A"; break;
+ case 0x04: str = "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn = dis_iei_apa_8bit; break;
+ case 0x05: str = "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn = dis_iei_apa_16bit; break;
+ case 0x06: str = "SMSC Control Parameters (SMS Control)"; break;
+ case 0x07: str = "UDH Source Indicator (SMS Control)"; break;
+ case 0x08: str = "Concatenated short message, 16-bit reference number (SMS Control)"; break;
+ case 0x09: str = "Wireless Control Message Protocol (SMS Control)"; break;
+ case 0x0A: str = "Text Formatting (EMS Control)"; break;
+ case 0x0B: str = "Predefined Sound (EMS Content)"; break;
+ case 0x0C: str = "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; break;
+ case 0x0D: str = "Predefined Animation (EMS Content)"; break;
+ case 0x0E: str = "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; break;
+ case 0x0F: str = "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; break;
+ case 0x10: str = "Large Picture (32*32 = 128 bytes) (EMS Content)"; break;
+ case 0x11: str = "Small Picture (16*16 = 32 bytes) (EMS Content)"; break;
+ case 0x12: str = "Variable Picture (EMS Content)"; break;
+ case 0x13: str = "User prompt indicator (EMS Control)"; break;
+ case 0x14: str = "Extended Object (EMS Content)"; break;
+ case 0x15: str = "Reused Extended Object (EMS Control)"; break;
+ case 0x16: str = "Compression Control (EMS Control)"; break;
+ case 0x17: str = "Object Distribution Indicator (EMS Control)"; break;
+ case 0x18: str = "Standard WVG object (EMS Content)"; break;
+ case 0x19: str = "Character Size WVG object (EMS Content)"; break;
+ case 0x1A: str = "Extended Object Data Request Command (EMS Control)"; break;
+ case 0x20: str = "RFC 822 E-Mail Header (SMS Control)"; break;
+ case 0x21: str = "Hyperlink format element (SMS Control)"; break;
+ case 0x22: str = "Reply Address Element (SMS Control)"; break;
+ default:
+ if ((oct >= 0x1b) &&
+ (oct <= 0x1f))
+ {
+ str = "Reserved for future EMS features (see subclause 3.10) N/A"; break;
+ }
+ else if ((oct >= 0x23) &&
+ (oct <= 0x6f))
+ {
+ str = "Reserved for future use N/A"; break;
+ }
+ else if ((oct >= 0x70) &&
+ (oct <= 0x7f))
+ {
+ str = "(U)SIM Toolkit Security Headers (SMS Control)"; break;
+ }
+ else if ((oct >= 0x80) &&
+ (oct <= 0x9f))
+ {
+ str = "SME to SME specific use (SMS Control)"; break;
+ }
+ else if ((oct >= 0xa0) &&
+ (oct <= 0xbf))
+ {
+ str = "Reserved for future use N/A"; break;
+ }
+ else if ((oct >= 0xc0) &&
+ (oct <= 0xdf))
+ {
+ str = "SC specific use (SMS Control)"; break;
+ }
+ else
+ {
+ str = "Reserved for future use N/A"; break;
+ }
+ }
+
+ iei_len = tvb_get_guint8(tvb, offset + 1);
+
+ item =
+ proto_tree_add_text(tree,
+ tvb, offset, iei_len + 2,
+ "IE: %s",
+ str);
+
+ subtree = proto_item_add_subtree(item, ett_udh_ieis[oct]);
+
+ proto_tree_add_text(subtree,
+ tvb, offset, 1,
+ "Information Element Identifier: %d",
+ oct);
+
+ offset++;
+
+ proto_tree_add_text(subtree,
+ tvb, offset, 1,
+ "Length: %d",
+ iei_len);
+
+ offset++;
+
+ if (iei_len > 0)
+ {
+ if (iei_fcn == NULL)
+ {
+ proto_tree_add_text(subtree,
+ tvb, offset, iei_len,
+ "IE Data");
+ }
+ else
+ {
+ iei_fcn(tvb, subtree, offset, iei_len);
+ }
+ }
+
+ length -= 2 + iei_len;
+ offset += iei_len;
+ }
+}
+
+/* 9.2.3.24 */
+static void
+dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
+ gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
+{
+ static guint8 fill_bits_mask[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
+ proto_item *item;
+ proto_item *udh_item;
+ proto_tree *subtree = NULL;
+ proto_tree *udh_subtree = NULL;
+ guint8 oct;
+ guint8 fill_bits;
+ guint32 out_len;
+ char *ustr;
+
+ fill_bits = 0;
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, length,
+ "TP-User-Data");
+
+ subtree = proto_item_add_subtree(item, ett_ud);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ if (udhi)
+ {
+ /* step over header */
+
+ udh_item =
+ proto_tree_add_text(subtree, tvb,
+ offset, oct + 1,
+ "User-Data Header");
+
+ udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
+
+ proto_tree_add_text(udh_subtree,
+ tvb, offset, 1,
+ "User Data Header Length (%d)",
+ oct);
+
+ offset++;
+ udl--;
+ length--;
+
+ dis_field_ud_iei(tvb, udh_subtree, offset, oct);
+
+ offset += oct;
+ udl -= oct;
+ length -= oct;
+
+ if (seven_bit)
+ {
+ /* step over fill bits ? */
+
+ fill_bits = 7 - (((oct + 1) * 8) % 7);
+ if (fill_bits != 7)
+ {
+ oct = tvb_get_guint8(tvb, offset);
+
+ other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
+ proto_tree_add_text(udh_subtree,
+ tvb, offset, 1,
+ "%s : Fill bits",
+ bigbuf);
+ }
+ }
+ }
+
+ if (compressed)
+ {
+ proto_tree_add_text(subtree, tvb,
+ offset, length,
+ "Compressed data");
+ }
+ else
+ {
+ if (seven_bit)
+ {
+ out_len =
+ gsm_sms_char_7bit_unpack(fill_bits, length, sizeof(bigbuf),
+ tvb_get_ptr(tvb, offset, length), bigbuf);
+ bigbuf[out_len] = '\0';
+ gsm_sms_char_ascii_decode(bigbuf, bigbuf, out_len);
+ bigbuf[udl] = '\0';
+
+ proto_tree_add_text(subtree, tvb, offset, length, "%s", bigbuf);
+ }
+ else if (eight_bit)
+ {
+ proto_tree_add_text(subtree, tvb, offset, length, "%s",
+ tvb_format_text(tvb, offset, length));
+ }
+ else if (ucs2)
+ {
+ ustr = tvb_fake_unicode(tvb, offset, length, FALSE);
+ proto_tree_add_text(subtree, tvb, offset, length, "%s", ustr);
+ g_free(ustr);
+ }
+ }
+}
+
+/* 9.2.3.25 */
+#define DIS_FIELD_RD(m_tree, m_bitmask, m_offset) \
+{ \
+ other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "%s : TP-Reject-Duplicates: Instruct SC to %s duplicates", \
+ bigbuf, \
+ (oct & m_bitmask) ? \
+ "reject" : \
+ "accept"); \
+}
+
+/* 9.2.3.26 */
+#define DIS_FIELD_SRQ(m_tree, m_bitmask, m_offset) \
+{ \
+ other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
+ proto_tree_add_text(m_tree, tvb, \
+ m_offset, 1, \
+ "%s : TP-Status-Report-Qualifier: The SMS-STATUS-REPORT is the result of %s", \
+ bigbuf, \
+ (oct & m_bitmask) ? \
+ "an SMS-COMMAND e.g. an Enquiry" : \
+ "a SMS-SUBMIT"); \
+}
+
+/* 9.2.3.27 */
+static void
+dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
+{
+ proto_item *item;
+ proto_tree *subtree = NULL;
+
+
+ item =
+ proto_tree_add_text(tree, tvb,
+ offset, 1,
+ "TP-Parameter-Indicator");
+
+ subtree = proto_item_add_subtree(item, ett_pi);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : %s",
+ bigbuf,
+ (oct & 0x80) ? "Extended" : "No extension");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : TP-UDL %spresent",
+ bigbuf,
+ (oct & 0x04) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : TP-DCS %spresent",
+ bigbuf,
+ (oct & 0x02) ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ "%s : TP-PID %spresent",
+ bigbuf,
+ (oct & 0x01) ? "" : "not ");
+}
+
+/*
+ * Ref. GSM 03.40
+ * Section 9.2.2
+ */
+static void
+dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 length;
+ guint8 oct;
+ guint8 udl;
+ gboolean seven_bit;
+ gboolean eight_bit;
+ gboolean ucs2;
+ gboolean compressed;
+ gboolean udhi;
+
+ udl = 0;
+ saved_offset = offset;
+ length = tvb_length_remaining(tvb, offset);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_SRI(tree, 0x20, offset);
+
+ DIS_FIELD_UDHI(tree, 0x10, offset, udhi);
+
+ DIS_FIELD_RP(tree, 0x08, offset);
+
+ DIS_FIELD_MMS(tree, 0x04, offset);
+
+ DIS_FIELD_MTI(tree, 0x03, offset);
+
+ offset++;
+
+ dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_pid(tvb, tree, offset, oct);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
+
+ offset++;
+ dis_field_scts(tvb, tree, &offset);
+
+ oct = tvb_get_guint8(tvb, offset);
+ udl = oct;
+
+ DIS_FIELD_UDL(tree, offset);
+
+ if (udl > 0)
+ {
+ offset++;
+
+ dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
+ seven_bit, eight_bit, ucs2, compressed);
+ }
+}
+
+/*
+ * Ref. GSM 03.40
+ * Section 9.2.2
+ */
+static void
+dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 length;
+ guint8 oct;
+ guint8 pi;
+ guint8 udl;
+ gboolean seven_bit;
+ gboolean eight_bit;
+ gboolean ucs2;
+ gboolean compressed;
+ gboolean udhi;
+
+
+ udl = 0;
+ saved_offset = offset;
+ length = tvb_length_remaining(tvb, offset);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
+
+ DIS_FIELD_MTI(tree, 0x03, offset);
+
+ if (length < 2)
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, length,
+ "Short Data (?)");
+ return;
+ }
+
+ /*
+ * there does not seem to be a way to determine that this
+ * deliver report is from an RP-ERROR or RP-ACK other
+ * than to look at the next octet
+ *
+ * FCS values are 0x80 and higher
+ * PI uses bit 7 as an extension indicator
+ *
+ * will assume that if bit 7 is set then this octet
+ * is an FCS otherwise PI
+ */
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ if (oct & 0x80)
+ {
+ dis_field_fcs(tvb, tree, offset, oct);
+ }
+
+ offset++;
+ pi = tvb_get_guint8(tvb, offset);
+
+ dis_field_pi(tvb, tree, offset, pi);
+
+ if (pi & 0x01)
+ {
+ if (length <= (offset - saved_offset))
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, -1,
+ "Short Data (?)");
+ return;
+ }
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_pid(tvb, tree, offset, oct);
+ }
+
+ if (pi & 0x02)
+ {
+ if (length <= (offset - saved_offset))
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, -1,
+ "Short Data (?)");
+ return;
+ }
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
+ }
+
+ if (pi & 0x04)
+ {
+ if (length <= (offset - saved_offset))
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, -1,
+ "Short Data (?)");
+ return;
+ }
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+ udl = oct;
+
+ DIS_FIELD_UDL(tree, offset);
+ }
+
+ if (udl > 0)
+ {
+ offset++;
+
+ dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
+ seven_bit, eight_bit, ucs2, compressed);
+ }
+}
+
+/*
+ * Ref. GSM 03.40
+ * Section 9.2.2
+ */
+static void
+dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 length;
+ guint8 oct;
+ guint8 vp_form;
+ guint8 udl;
+ gchar *str = NULL;
+ gboolean seven_bit;
+ gboolean eight_bit;
+ gboolean ucs2;
+ gboolean compressed;
+ gboolean udhi;
+
+
+ saved_offset = offset;
+ length = tvb_length_remaining(tvb, offset);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_SRR(tree, 0x80, offset);
+
+ DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
+
+ DIS_FIELD_RP(tree, 0x20, offset);
+
+ DIS_FIELD_VPF(tree, 0x18, offset, &vp_form);
+
+ DIS_FIELD_RD(tree, 0x04, offset);
+
+ DIS_FIELD_MTI(tree, 0x03, offset);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_MR(tree, offset);
+
+ offset++;
+
+ dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_pid(tvb, tree, offset, oct);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
+
+ offset++;
+ dis_field_vp(tvb, tree, &offset, vp_form);
+
+ oct = tvb_get_guint8(tvb, offset);
+ udl = oct;
+
+ DIS_FIELD_UDL(tree, offset);
+
+ if (udl > 0)
+ {
+ offset++;
+
+ dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
+ seven_bit, eight_bit, ucs2, compressed);
+ }
+}
+
+/*
+ * Ref. GSM 03.40
+ * Section 9.2.2
+ */
+static void
+dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 length;
+ guint8 oct;
+ guint8 pi;
+ guint8 udl;
+ gboolean seven_bit;
+ gboolean eight_bit;
+ gboolean ucs2;
+ gboolean compressed;
+ gboolean udhi;
+
+
+ udl = 0;
+ saved_offset = offset;
+ length = tvb_length_remaining(tvb, offset);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
+
+ DIS_FIELD_MTI(tree, 0x03, offset);
+
+ /*
+ * there does not seem to be a way to determine that this
+ * deliver report is from an RP-ERROR or RP-ACK other
+ * than to look at the next octet
+ *
+ * FCS values are 0x80 and higher
+ * PI uses bit 7 as an extension indicator
+ *
+ * will assume that if bit 7 is set then this octet
+ * is an FCS otherwise PI
+ */
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ if (oct & 0x80)
+ {
+ dis_field_fcs(tvb, tree, offset, oct);
+ }
+
+ offset++;
+ pi = tvb_get_guint8(tvb, offset);
+
+ dis_field_pi(tvb, tree, offset, pi);
+
+ offset++;
+ dis_field_scts(tvb, tree, &offset);
+
+ if (pi & 0x02)
+ {
+ if (length <= (offset - saved_offset))
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, -1,
+ "Short Data (?)");
+ return;
+ }
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
+ }
+
+ if (pi & 0x04)
+ {
+ if (length <= (offset - saved_offset))
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, -1,
+ "Short Data (?)");
+ return;
+ }
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+ udl = oct;
+
+ DIS_FIELD_UDL(tree, offset);
+ }
+
+ if (udl > 0)
+ {
+ offset++;
+
+ dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
+ seven_bit, eight_bit, ucs2, compressed);
+ }
+}
+
+/*
+ * Ref. GSM 03.40
+ * Section 9.2.2
+ */
+static void
+dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 length;
+ guint8 oct;
+ guint8 pi;
+ guint8 udl;
+ gboolean seven_bit;
+ gboolean eight_bit;
+ gboolean ucs2;
+ gboolean compressed;
+ gboolean udhi;
+
+
+ udl = 0;
+ saved_offset = offset;
+ length = tvb_length_remaining(tvb, offset);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_SRQ(tree, 0x10, offset);
+
+ DIS_FIELD_MMS(tree, 0x08, offset);
+
+ DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
+
+ DIS_FIELD_MTI(tree, 0x03, offset);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_MR(tree, offset);
+
+ offset++;
+
+ dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
+
+ dis_field_scts(tvb, tree, &offset);
+
+ dis_field_dt(tvb, tree, &offset);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_st(tvb, tree, offset, oct);
+
+ offset++;
+ pi = tvb_get_guint8(tvb, offset);
+
+ dis_field_pi(tvb, tree, offset, pi);
+
+ if (pi & 0x01)
+ {
+ if (length <= (offset - saved_offset))
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, -1,
+ "Short Data (?)");
+ return;
+ }
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_pid(tvb, tree, offset, oct);
+ }
+
+ if (pi & 0x02)
+ {
+ if (length <= (offset - saved_offset))
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, -1,
+ "Short Data (?)");
+ return;
+ }
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
+ }
+
+ if (pi & 0x04)
+ {
+ if (length <= (offset - saved_offset))
+ {
+ proto_tree_add_text(tree,
+ tvb, offset, -1,
+ "Short Data (?)");
+ return;
+ }
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+ udl = oct;
+
+ DIS_FIELD_UDL(tree, offset);
+ }
+
+ if (udl > 0)
+ {
+ offset++;
+
+ dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
+ seven_bit, eight_bit, ucs2, compressed);
+ }
+}
+
+/*
+ * Ref. GSM 03.40
+ * Section 9.2.2
+ */
+static void
+dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+ guint32 saved_offset;
+ guint32 length;
+ guint8 oct;
+ guint8 cdl;
+ gchar *str = NULL;
+ gboolean udhi;
+
+
+ cdl = 0;
+ saved_offset = offset;
+ length = tvb_length_remaining(tvb, offset);
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_SRR(tree, 0x08, offset);
+
+ DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
+
+ DIS_FIELD_MTI(tree, 0x03, offset);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_MR(tree, offset);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ dis_field_pid(tvb, tree, offset, oct);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_CT(tree, offset);
+
+ offset++;
+ oct = tvb_get_guint8(tvb, offset);
+
+ DIS_FIELD_MN(tree, offset);
+
+ offset++;
+
+ dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
+
+ oct = tvb_get_guint8(tvb, offset);
+ cdl = oct;
+
+ DIS_FIELD_CDL(tree, offset);
+
+ if (cdl > 0)
+ {
+ offset++;
+
+ proto_tree_add_text(tree,
+ tvb, offset, cdl,
+ "TP-Command-Data");
+ }
+}
+
+#define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
+static gint ett_msgs[NUM_MSGS];
+static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
+ dis_msg_deliver, /* SMS-DELIVER */
+ dis_msg_deliver_report, /* SMS-DELIVER REPORT */
+ dis_msg_submit, /* SMS-SUBMIT */
+ dis_msg_submit_report, /* SMS-SUBMIT REPORT */
+ dis_msg_status_report, /* SMS-STATUS REPORT */
+ dis_msg_command, /* SMS-COMMAND */
+ NULL, /* Reserved */
+ NULL, /* Reserved */
+ NULL, /* NONE */
+};
+
+/* GENERIC DISSECTOR FUNCTIONS */
+
+static void
+dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
+ proto_item *gsm_sms_item;
+ proto_tree *gsm_sms_tree = NULL;
+ guint32 offset;
+ guint8 msg_type;
+ guint8 oct;
+ gint idx;
+ gchar *str = NULL;
+ gint ett_msg_idx;
+
+
+ g_pinfo = pinfo;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree)
+ {
+ g_tree = tree;
+
+ offset = 0;
+
+ oct = tvb_get_guint8(tvb, offset);
+
+ oct &= 0x03;
+ msg_type = oct;
+
+ /*
+ * convert the 2 bit value to one based on direction
+ */
+ msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
+
+ str = my_match_strval(msg_type, msg_type_strings, &idx);
+
+ /*
+ * create the GSM_SMS protocol tree
+ */
+ gsm_sms_item =
+ proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
+ "%s %s",
+ gsm_sms_proto_name,
+ (str == NULL) ? "Unknown message identifier" : str);
+
+ gsm_sms_tree =
+ proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
+
+ if ((str == NULL) ||
+ (msg_type == 0x03) ||
+ (msg_type == 0x07))
+ {
+ return;
+ }
+ else
+ {
+ ett_msg_idx = ett_msgs[idx];
+ msg_fcn = gsm_sms_msg_fcn[idx];
+ }
+
+ if (msg_fcn == NULL)
+ {
+ proto_tree_add_text(gsm_sms_tree,
+ tvb, offset, -1,
+ "Message dissector not implemented");
+ }
+ else
+ {
+ (*msg_fcn)(tvb, gsm_sms_tree, offset);
+ }
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_gsm_sms(void)
+{
+ guint i;
+ guint last_offset;
+
+#if 0
+ /* Setup list of header fields */
+ static hf_register_info hf[] =
+ {
+ };
+#endif
+
+ /* Setup protocol subtree array */
+#define NUM_INDIVIDUAL_PARMS 12
+ static gint *ett[NUM_INDIVIDUAL_PARMS+NUM_MSGS+NUM_UDH_IEIS];
+
+ ett[0] = &ett_gsm_sms;
+ ett[1] = &ett_pid;
+ ett[2] = &ett_pi;
+ ett[3] = &ett_fcs;
+ ett[4] = &ett_vp;
+ ett[5] = &ett_scts;
+ ett[6] = &ett_dt;
+ ett[7] = &ett_st;
+ ett[8] = &ett_addr;
+ ett[9] = &ett_dcs;
+ ett[10] = &ett_ud;
+ ett[11] = &ett_udh;
+
+ last_offset = NUM_INDIVIDUAL_PARMS;
+
+ for (i=0; i < NUM_MSGS; i++, last_offset++)
+ {
+ ett_msgs[i] = -1;
+ ett[last_offset] = &ett_msgs[i];
+ }
+
+ for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
+ {
+ ett_udh_ieis[i] = -1;
+ ett[last_offset] = &ett_udh_ieis[i];
+ }
+
+ /* Register the protocol name and description */
+
+ proto_gsm_sms =
+ proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
+
+#if 0
+ proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
+#endif
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_gsm_sms(void)
+{
+ dissector_handle_t gsm_sms_handle;
+
+ gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
+
+ dissector_add("gsm_a.sms_tpdu", 0, gsm_sms_handle);
+ dissector_add("gsm_map.sms_tpdu", 0, gsm_sms_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-gsm_sms.h b/epan/dissectors/packet-gsm_sms.h
new file mode 100644
index 0000000000..bb55808543
--- /dev/null
+++ b/epan/dissectors/packet-gsm_sms.h
@@ -0,0 +1,29 @@
+/* packet-gsm_sms.h
+ *
+ * $Id$
+ *
+ * Copyright 2004, Michael Lum <mlum [AT] telostech.com>,
+ * In association with Telos Technology Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+extern int gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
+ const guint8 *input, unsigned char *output);
+extern void gsm_sms_char_ascii_decode(unsigned char* dest, const unsigned char* src, int len);
diff --git a/epan/dissectors/packet-gsm_sms_ud.c b/epan/dissectors/packet-gsm_sms_ud.c
new file mode 100644
index 0000000000..fb9ae7b639
--- /dev/null
+++ b/epan/dissectors/packet-gsm_sms_ud.c
@@ -0,0 +1,639 @@
+/* packet-gsm_sms_ud.c
+ * Routines for GSM SMS TP-UD (GSM 03.40) dissection
+ *
+ * $Id$
+ *
+ * Refer to the AUTHORS file or the AUTHORS section in the man page
+ * for contacting the author(s) of this file.
+ *
+ * Separated from the SMPP dissector by Chris Wilson.
+ *
+ * UDH and WSP dissection of SMS message, Short Message reassembly,
+ * "Decode Short Message with Port Number UDH as CL-WSP" preference,
+ * "Always try subdissection of 1st fragment" preference,
+ * provided by Olivier Biot.
+ *
+ * Note on SMS Message reassembly
+ * ------------------------------
+ * The current Short Message reassembly is possible thanks to the
+ * message identifier (8 or 16 bit identifier). It is able to reassemble
+ * short messages that are sent over either the same SMPP connection or
+ * distinct SMPP connections. Normally the reassembly code is able to deal
+ * with duplicate message identifiers since the fragment_add_seq_check()
+ * call is used.
+ *
+ * The SMS TP-UD preference "always try subdissection of 1st fragment" allows
+ * a subdissector to be called for the first Short Message fragment,
+ * even if reassembly is not possible. This way partial dissection
+ * is still possible. This preference is switched off by default.
+ *
+ * Note on Short Message decoding as CL-WSP
+ * ----------------------------------------
+ * The SMS TP-UD preference "port_number_udh_means_wsp" is switched off
+ * by default. If it is enabled, then any Short Message with a Port Number
+ * UDH will be decoded as CL-WSP if:
+ * - The Short Message is not segmented
+ * - The entire segmented Short Message is reassembled
+ * - It is the 1st segment of an unreassembled Short Message (if the
+ * "always try subdissection of 1st fragment" preference is enabled)
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#include "prefs.h"
+#include "reassemble.h"
+
+static void dissect_gsm_sms_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static int proto_gsm_sms_ud = -1;
+
+/*
+ * Short Message fragment handling
+ */
+static int hf_gsm_sms_ud_fragments = -1;
+static int hf_gsm_sms_ud_fragment = -1;
+static int hf_gsm_sms_ud_fragment_overlap = -1;
+static int hf_gsm_sms_ud_fragment_overlap_conflicts = -1;
+static int hf_gsm_sms_ud_fragment_multiple_tails = -1;
+static int hf_gsm_sms_ud_fragment_too_long_fragment = -1;
+static int hf_gsm_sms_ud_fragment_error = -1;
+static int hf_gsm_sms_ud_reassembled_in = -1;
+/*
+ * User Data Header section
+ */
+static int hf_gsm_sms_udh_length = -1;
+static int hf_gsm_sms_udh_iei = -1;
+static int hf_gsm_sms_udh_multiple_messages = -1;
+static int hf_gsm_sms_udh_multiple_messages_msg_id = -1;
+static int hf_gsm_sms_udh_multiple_messages_msg_parts = -1;
+static int hf_gsm_sms_udh_multiple_messages_msg_part = -1;
+static int hf_gsm_sms_udh_ports = -1;
+static int hf_gsm_sms_udh_ports_src = -1;
+static int hf_gsm_sms_udh_ports_dst = -1;
+
+static gint ett_gsm_sms = -1;
+static gint ett_udh = -1;
+static gint ett_udh_ie = -1;
+static gint ett_gsm_sms_ud_fragment = -1;
+static gint ett_gsm_sms_ud_fragments = -1;
+
+/* Subdissector declarations */
+static dissector_table_t gsm_sms_dissector_table;
+
+/* Short Message reassembly */
+static GHashTable *sm_fragment_table = NULL;
+static GHashTable *sm_reassembled_table = NULL;
+
+static const fragment_items sm_frag_items = {
+ /* Fragment subtrees */
+ &ett_gsm_sms_ud_fragment,
+ &ett_gsm_sms_ud_fragments,
+ /* Fragment fields */
+ &hf_gsm_sms_ud_fragments,
+ &hf_gsm_sms_ud_fragment,
+ &hf_gsm_sms_ud_fragment_overlap,
+ &hf_gsm_sms_ud_fragment_overlap_conflicts,
+ &hf_gsm_sms_ud_fragment_multiple_tails,
+ &hf_gsm_sms_ud_fragment_too_long_fragment,
+ &hf_gsm_sms_ud_fragment_error,
+ /* Reassembled in field */
+ &hf_gsm_sms_ud_reassembled_in,
+ /* Tag */
+ "Short Message fragments"
+};
+
+/* Dissect all SM data as WSP if the UDH contains a Port Number IE */
+static gboolean port_number_udh_means_wsp = FALSE;
+/* Always try dissecting the 1st fragment of a SM,
+ * even if it is not reassembled */
+static gboolean try_dissect_1st_frag = FALSE;
+/* Prevent subdissectors changing column data */
+static gboolean prevent_subdissectors_changing_columns = FALSE;
+
+static dissector_handle_t wsp_handle;
+
+static void
+gsm_sms_ud_defragment_init (void)
+{
+ fragment_table_init (&sm_fragment_table);
+ reassembled_table_init(&sm_reassembled_table);
+}
+
+/*
+ * Value-arrays for field-contents
+ */
+/* 3GPP TS 23.040 V6.1.0 (2003-06) */
+static const value_string vals_udh_iei[] = {
+ { 0x00, "SMS - Concatenated short messages, 8-bit reference number" },
+ { 0x01, "SMS - Special SMS Message Indication" },
+ { 0x02, "Reserved" },
+ { 0x03, "Value not used to avoid misinterpretation as <LF> character" },
+ { 0x04, "SMS - Application port addressing scheme, 8 bit address" },
+ { 0x05, "SMS - Application port addressing scheme, 16 bit address" },
+ { 0x06, "SMS - SMSC Control Parameters" },
+ { 0x07, "SMS - UDH Source Indicator" },
+ { 0x08, "SMS - Concatenated short message, 16-bit reference number" },
+ { 0x09, "SMS - Wireless Control Message Protocol" },
+ { 0x0A, "EMS - Text Formatting" },
+ { 0x0B, "EMS - Predefined Sound" },
+ { 0x0C, "EMS - User Defined Sound (iMelody max 128 bytes)" },
+ { 0x0D, "EMS - Predefined Animation" },
+ { 0x0E, "EMS - Large Animation (16*16 times 4 = 32*4 =128 bytes)" },
+ { 0x0F, "EMS - Small Animation (8*8 times 4 = 8*4 =32 bytes)" },
+ { 0x10, "EMS - Large Picture (32*32 = 128 bytes)" },
+ { 0x11, "EMS - Small Picture (16*16 = 32 bytes)" },
+ { 0x12, "EMS - Variable Picture" },
+ { 0x13, "EMS - User prompt indicator" },
+ { 0x14, "EMS - Extended Object" },
+ { 0x15, "EMS - Reused Extended Object" },
+ { 0x16, "EMS - Compression Control" },
+ { 0x17, "EMS - Object Distribution Indicator" },
+ { 0x18, "EMS - Standard WVG object" },
+ { 0x19, "EMS - Character Size WVG object" },
+ { 0x1A, "EMS - Extended Object Data Request Command" },
+ { 0x20, "SMS - RFC 822 E-Mail Header" },
+ { 0x21, "SMS - Hyperlink format element" },
+ { 0x22, "SMS - Reply Address Element" },
+ { 0x00, NULL }
+};
+
+
+/* Parse Short Message, only if UDH present
+ * (otherwise this function is not called).
+ * Call WSP dissector if port matches WSP traffic.
+ */
+static void
+parse_gsm_sms_ud_message(proto_tree *sm_tree, tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *top_tree)
+{
+ tvbuff_t *sm_tvb = NULL;
+ proto_item *subtree, *tree;
+ guint8 udh_len, udh, len;
+ guint sm_len = tvb_reported_length (tvb);
+ guint sm_data_len;
+ guint32 i = 0;
+ /* Multiple Messages UDH */
+ gboolean is_fragmented = FALSE;
+ fragment_data *fd_sm = NULL;
+ guint16 sm_id = 0, frags = 0, frag = 0;
+ gboolean save_fragmented = FALSE, try_gsm_sms_ud_reassemble = FALSE;
+ /* SMS Message reassembly */
+ gboolean reassembled = FALSE;
+ guint32 reassembled_in = 0;
+ /* Port Number UDH */
+ guint16 p_src = 0, p_dst = 0;
+ gboolean ports_available = FALSE;
+
+ udh_len = tvb_get_guint8(tvb, i++);
+ tree = proto_tree_add_uint(sm_tree, hf_gsm_sms_udh_length, tvb, 0, 1, udh_len);
+ tree = proto_item_add_subtree(tree, ett_udh);
+ while (i < udh_len) {
+ udh = tvb_get_guint8(tvb, i++);
+ len = tvb_get_guint8(tvb, i++);
+ subtree = proto_tree_add_uint(tree, hf_gsm_sms_udh_iei,
+ tvb, i-2, 2+len, udh);
+ switch (udh) {
+ case 0x00: /* Multiple messages - 8-bit message ID */
+ if (len == 3) {
+ sm_id = tvb_get_guint8(tvb, i++);
+ frags = tvb_get_guint8(tvb, i++);
+ frag = tvb_get_guint8(tvb, i++);
+ if (frags > 1)
+ is_fragmented = TRUE;
+ proto_item_append_text(subtree,
+ ": message %u, part %u of %u", sm_id, frag, frags);
+ subtree = proto_item_add_subtree(subtree,
+ ett_udh_ie);
+ proto_tree_add_uint (subtree,
+ hf_gsm_sms_udh_multiple_messages_msg_id,
+ tvb, i-3, 1, sm_id);
+ proto_tree_add_uint (subtree,
+ hf_gsm_sms_udh_multiple_messages_msg_parts,
+ tvb, i-2, 1, frags);
+ proto_tree_add_uint (subtree,
+ hf_gsm_sms_udh_multiple_messages_msg_part,
+ tvb, i-1, 1, frag);
+ } else {
+ proto_item_append_text(subtree, " - Invalid format!");
+ i += len;
+ }
+ break;
+
+ case 0x08: /* Multiple messages - 16-bit message ID */
+ if (len == 4) {
+ sm_id = tvb_get_ntohs(tvb, i); i += 2;
+ frags = tvb_get_guint8(tvb, i++);
+ frag = tvb_get_guint8(tvb, i++);
+ if (frags > 1)
+ is_fragmented = TRUE;
+ proto_item_append_text(subtree,
+ ": message %u, part %u of %u", sm_id, frag, frags);
+ subtree = proto_item_add_subtree(subtree,
+ ett_udh_ie);
+ proto_tree_add_uint (subtree,
+ hf_gsm_sms_udh_multiple_messages_msg_id,
+ tvb, i-4, 2, sm_id);
+ proto_tree_add_uint (subtree,
+ hf_gsm_sms_udh_multiple_messages_msg_parts,
+ tvb, i-2, 1, frags);
+ proto_tree_add_uint (subtree,
+ hf_gsm_sms_udh_multiple_messages_msg_part,
+ tvb, i-1, 1, frag);
+ } else {
+ proto_item_append_text(subtree, " - Invalid format!");
+ i += len;
+ }
+ break;
+
+ case 0x04: /* Port Number UDH - 8-bit address */
+ if (len == 2) { /* Port fields */
+ p_dst = tvb_get_guint8(tvb, i++);
+ p_src = tvb_get_guint8(tvb, i++);
+ proto_item_append_text(subtree,
+ ": source port %u, destination port %u",
+ p_src, p_dst);
+ subtree = proto_item_add_subtree(subtree, ett_udh_ie);
+ proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_dst,
+ tvb, i-2, 1, p_dst);
+ proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_src,
+ tvb, i-1, 1, p_src);
+ ports_available = TRUE;
+ } else {
+ proto_item_append_text(subtree, " - Invalid format!");
+ i += len;
+ }
+ break;
+
+ case 0x05: /* Port Number UDH - 16-bit address */
+ if (len == 4) { /* Port fields */
+ p_dst = tvb_get_ntohs(tvb, i); i += 2;
+ p_src = tvb_get_ntohs(tvb, i); i += 2;
+ proto_item_append_text(subtree,
+ ": source port %u, destination port %u",
+ p_src, p_dst);
+ subtree = proto_item_add_subtree(subtree, ett_udh_ie);
+ proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_dst,
+ tvb, i-4, 2, p_dst);
+ proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_src,
+ tvb, i-2, 2, p_src);
+ ports_available = TRUE;
+ } else {
+ proto_item_append_text(subtree, " - Invalid format!");
+ i += len;
+ }
+ break;
+
+ default:
+ i += len;
+ break;
+ }
+ }
+ if (tvb_reported_length_remaining(tvb, i) <= 0)
+ return; /* No more data */
+
+ /*
+ * XXX - where does the "1" come from? If it weren't there,
+ * "sm_data_len" would, I think, be the same as
+ * "tvb_reported_length_remaining(tvb, i)".
+ *
+ * I think that the above check ensures that "sm_len" won't
+ * be less than or equal to "udh_len", so it ensures that
+ * "sm_len" won't be less than "1 + udh_len", so we don't
+ * have to worry about "sm_data_len" being negative.
+ */
+ sm_data_len = sm_len - (1 + udh_len);
+ if (sm_data_len == 0)
+ return; /* no more data */
+
+ /*
+ * Try reassembling the packets.
+ * XXX - fragment numbers are 1-origin, but the fragment number
+ * field could be 0.
+ * Should we flag a fragmented message with a fragment number field
+ * of 0?
+ * What if the fragment count is 0? Should we flag that as well?
+ */
+ if ( is_fragmented && frag != 0 && frags != 0 &&
+ tvb_bytes_exist (tvb, i, sm_data_len) ) {
+ try_gsm_sms_ud_reassemble = TRUE;
+ save_fragmented = pinfo->fragmented;
+ pinfo->fragmented = TRUE;
+ fd_sm = fragment_add_seq_check (tvb, i, pinfo,
+ sm_id, /* guint32 ID for fragments belonging together */
+ sm_fragment_table, /* list of message fragments */
+ sm_reassembled_table, /* list of reassembled messages */
+ frag-1, /* guint32 fragment sequence number */
+ sm_data_len, /* guint32 fragment length */
+ (frag != frags)); /* More fragments? */
+ if (fd_sm) {
+ reassembled = TRUE;
+ reassembled_in = fd_sm->reassembled_in;
+ }
+ sm_tvb = process_reassembled_data(tvb, i, pinfo,
+ "Reassembled Short Message", fd_sm, &sm_frag_items,
+ NULL, sm_tree);
+ if (reassembled) { /* Reassembled */
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_str (pinfo->cinfo, COL_INFO,
+ " (Short Message Reassembled)");
+ } else {
+ /* Not last packet of reassembled Short Message */
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO,
+ " (Short Message fragment %u of %u)", frag, frags);
+ }
+ } /* Else: not fragmented */
+
+ if (! sm_tvb) /* One single Short Message, or not reassembled */
+ sm_tvb = tvb_new_subset (tvb, i, -1, -1);
+ /* Try calling a subdissector */
+ if (sm_tvb) {
+ if ((reassembled && pinfo->fd->num == reassembled_in)
+ || frag==0 || (frag==1 && try_dissect_1st_frag)) {
+ /* Try calling a subdissector only if:
+ * - the Short Message is reassembled in this very packet,
+ * - the Short Message consists of only one "fragment",
+ * - the preference "Always Try Dissection for 1st SM fragment"
+ * is switched on, and this is the SM's 1st fragment. */
+ if ( ports_available ) {
+ gboolean disallow_write = FALSE; /* TRUE if we changed writability
+ of the columns of the summary */
+ if ( prevent_subdissectors_changing_columns && col_get_writable(pinfo->cinfo) ) {
+ disallow_write = TRUE;
+ col_set_writable(pinfo->cinfo, FALSE);
+ }
+
+ if ( port_number_udh_means_wsp ) {
+ call_dissector (wsp_handle, sm_tvb, pinfo, top_tree);
+ } else {
+ if (! dissector_try_port(gsm_sms_dissector_table, p_src,
+ sm_tvb, pinfo, top_tree)) {
+ if (! dissector_try_port(gsm_sms_dissector_table, p_dst,
+ sm_tvb, pinfo, top_tree)) {
+ if (sm_tree) { /* Only display if needed */
+ proto_tree_add_text (sm_tree, sm_tvb, 0, -1,
+ "Short Message body");
+ }
+ }
+ }
+ }
+
+ if ( disallow_write )
+ col_set_writable(pinfo->cinfo, TRUE);
+ } else { /* No ports IE */
+ proto_tree_add_text (sm_tree, sm_tvb, 0, -1,
+ "Short Message body");
+ }
+ } else {
+ /* The packet is not reassembled,
+ * or it is reassembled in another packet */
+ proto_tree_add_text (sm_tree, sm_tvb, 0, -1,
+ "Unreassembled Short Message fragment %u of %u",
+ frag, frags);
+ }
+ }
+
+ if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
+ pinfo->fragmented = save_fragmented;
+ return;
+}
+
+static void
+dissect_gsm_sms_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *subtree;
+ ti = proto_tree_add_item(tree, proto_gsm_sms_ud, tvb, 0, -1, TRUE);
+ subtree = proto_item_add_subtree(ti, ett_gsm_sms);
+ parse_gsm_sms_ud_message(subtree, tvb, pinfo, tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_gsm_sms_ud(void)
+{
+ module_t *gsm_sms_ud_module; /* Preferences for GSM SMS UD */
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ /*
+ * User Data Header
+ */
+ { &hf_gsm_sms_udh_iei,
+ { "IE Id", "gsm-sms-ud.udh.iei",
+ FT_UINT8, BASE_HEX, VALS(vals_udh_iei), 0x00,
+ "Name of the User Data Header Information Element.",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_udh_length,
+ { "UDH Length", "gsm-sms-ud.udh.len",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Length of the User Data Header (bytes)",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_udh_multiple_messages,
+ { "Multiple messages UDH", "gsm-sms-ud.udh.mm",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Multiple messages User Data Header",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_udh_multiple_messages_msg_id,
+ { "Message identifier", "gsm-sms-ud.udh.mm.msg_id",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Identification of the message",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_udh_multiple_messages_msg_parts,
+ { "Message parts", "gsm-sms-ud.udh.mm.msg_parts",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Total number of message parts (fragments)",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_udh_multiple_messages_msg_part,
+ { "Message part number", "gsm-sms-ud.udh.mm.msg_part",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Message part (fragment) sequence number",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_udh_ports,
+ { "Port number UDH", "gsm-sms-ud.udh.ports",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Port number User Data Header",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_udh_ports_src,
+ { "Source port", "gsm-sms-ud.udh.ports.src",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Source port",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_udh_ports_dst,
+ { "Destination port", "gsm-sms-ud.udh.ports.dst",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Destination port",
+ HFILL
+ }
+ },
+ /*
+ * Short Message fragment reassembly
+ */
+ { &hf_gsm_sms_ud_fragments,
+ { "Short Message fragments", "gsm-sms-ud.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "GSM Short Message fragments",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_ud_fragment,
+ { "Short Message fragment", "gsm-sms-ud.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ "GSM Short Message fragment",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_ud_fragment_overlap,
+ { "Short Message fragment overlap", "gsm-sms-ud.fragment.overlap",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00,
+ "GSM Short Message fragment overlaps with other fragment(s)",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_ud_fragment_overlap_conflicts,
+ { "Short Message fragment overlapping with conflicting data",
+ "gsm-sms-ud.fragment.overlap.conflicts",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00,
+ "GSM Short Message fragment overlaps with conflicting data",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_ud_fragment_multiple_tails,
+ { "Short Message has multiple tail fragments",
+ "gsm-sms-ud.fragment.multiple_tails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00,
+ "GSM Short Message fragment has multiple tail fragments",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_ud_fragment_too_long_fragment,
+ { "Short Message fragment too long",
+ "gsm-sms-ud.fragment.too_long_fragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00,
+ "GSM Short Message fragment data goes beyond the packet end",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_ud_fragment_error,
+ { "Short Message defragmentation error", "gsm-sms-ud.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ "GSM Short Message defragmentation error due to illegal fragments",
+ HFILL
+ }
+ },
+ { &hf_gsm_sms_ud_reassembled_in,
+ { "Reassembled in",
+ "gsm-sms-ud.reassembled.in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00,
+ "GSM Short Message has been reassembled in this packet.", HFILL
+ }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_gsm_sms,
+ &ett_udh,
+ &ett_udh_ie,
+ &ett_gsm_sms_ud_fragment,
+ &ett_gsm_sms_ud_fragments,
+ };
+ /* Register the protocol name and description */
+ proto_gsm_sms_ud = proto_register_protocol(
+ "GSM Short Message Service User Data", /* Name */
+ "GSM SMS UD", /* Short name */
+ "gsm-sms-ud"); /* Filter name */
+
+ /* Required function calls to register header fields and subtrees used */
+ proto_register_field_array(proto_gsm_sms_ud, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Subdissector code */
+ gsm_sms_dissector_table = register_dissector_table("gsm-sms-ud.udh.port",
+ "GSM SMS port IE in UDH", FT_UINT16, BASE_DEC);
+
+ /* Preferences for GSM SMS UD */
+ gsm_sms_ud_module = prefs_register_protocol (proto_gsm_sms_ud, NULL);
+ prefs_register_bool_preference (gsm_sms_ud_module,
+ "port_number_udh_means_wsp",
+ "Port Number IE in UDH always triggers CL-WSP dissection",
+ "Always decode a GSM Short Message as Connectionless WSP "
+ "if a Port Number Information Element is present "
+ "in the SMS User Data Header.",
+ &port_number_udh_means_wsp);
+ prefs_register_bool_preference (gsm_sms_ud_module, "try_dissect_1st_fragment",
+ "Always try subdissection of 1st Short Message fragment",
+ "Always try subdissection of the 1st fragment of a fragmented "
+ "GSM Short Message. If reassembly is possible, the Short Message "
+ "may be dissected twice (once as a short frame, once in its "
+ "entirety).",
+ &try_dissect_1st_frag);
+ prefs_register_bool_preference (gsm_sms_ud_module, "prevent_dissectors_chg_cols",
+ "Prevent sub-dissectors from changing column data",
+ "Prevent sub-dissectors from replacing column data with their "
+ "own. Eg. Prevent WSP dissector overwriting SMPP information.",
+ &prevent_subdissectors_changing_columns);
+
+ register_dissector("gsm-sms-ud", dissect_gsm_sms_ud, proto_gsm_sms_ud);
+
+ /* GSM SMS UD dissector initialization routines */
+ register_init_routine (gsm_sms_ud_defragment_init);
+}
+
+void
+proto_reg_handoff_gsm_sms_ud(void)
+{
+ dissector_handle_t gsm_sms_ud_handle;
+ gsm_sms_ud_handle = create_dissector_handle(dissect_gsm_sms_ud,
+ proto_gsm_sms_ud);
+
+ wsp_handle = find_dissector("wsp-cl");
+ g_assert(wsp_handle);
+}
+
+
+
diff --git a/epan/dissectors/packet-gsm_ss.c b/epan/dissectors/packet-gsm_ss.c
new file mode 100644
index 0000000000..01963aa756
--- /dev/null
+++ b/epan/dissectors/packet-gsm_ss.c
@@ -0,0 +1,2490 @@
+/* packet-gsm_ss.c
+ * Routines for GSM Supplementary Services dissection
+ *
+ * NOTE:
+ * Routines are shared by GSM MAP/GSM A dissectors.
+ * This file provides SHARED routines and is NOT a
+ * standalone dissector.
+ *
+ * Copyright 2004, Michael Lum <mlum [AT] telostech.com>
+ * In association with Telos Technology Inc.
+ *
+ * Title 3GPP Other
+ *
+ * Reference [1]
+ * Mobile radio Layer 3 supplementary service specification;
+ * Formats and coding
+ * (3GPP TS 24.080 version 4.3.0 Release 4)
+ *
+ * Michael Lum <mlum [AT] telostech.com>,
+ * Created (2004).
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-gsm_map.c (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "epan/packet.h"
+#include "tap.h"
+#include "asn1.h"
+
+#include "packet-tcap.h"
+#include "packet-gsm_sms.h"
+#include "packet-gsm_ss.h"
+
+
+const value_string gsm_ss_err_code_strings[] = {
+ { 1, "Unknown Subscriber" },
+ { 3, "Unknown MSC" },
+ { 5, "Unidentified Subscriber" },
+ { 6, "Absent Subscriber SM" },
+ { 7, "Unknown Equipment" },
+ { 8, "Roaming Not Allowed" },
+ { 9, "Illegal Subscriber" },
+ { 10, "Bearer Service Not Provisioned" },
+ { 11, "Teleservice Not Provisioned" },
+ { 12, "Illegal Equipment" },
+ { 13, "Call Barred" },
+ { 14, "Forwarding Violation" },
+ { 15, "CUG Reject" },
+ { 16, "Illegal SS Operation" },
+ { 17, "SS Error Status" },
+ { 18, "SS Not Available" },
+ { 19, "SS Subscription Violation" },
+ { 20, "SS Incompatibility" },
+ { 21, "Facility Not Supported" },
+ { 25, "No Handover Number Available" },
+ { 26, "Subsequent Handover Failure" },
+ { 27, "Absent Subscriber" },
+ { 28, "Incompatible Terminal" },
+ { 29, "Short Term Denial" },
+ { 30, "Long Term Denial" },
+ { 31, "Subscriber Busy For MT SMS" },
+ { 32, "SM Delivery Failure" },
+ { 33, "Message Waiting List Full" },
+ { 34, "System Failure" },
+ { 35, "Data Missing" },
+ { 36, "Unexpected Data Value" },
+ { 37, "PW Registration Failure" },
+ { 38, "Negative PW Check" },
+ { 39, "No Roaming Number Available" },
+ { 40, "Tracing Buffer Full" },
+ { 42, "Target Cell Outside Group Call Area" },
+ { 43, "Number Of PW Attempts Violation" },
+ { 44, "Number Changed" },
+ { 45, "Busy Subscriber" },
+ { 46, "No Subscriber Reply" },
+ { 47, "Forwarding Failed" },
+ { 48, "OR Not Allowed" },
+ { 49, "ATI Not Allowed" },
+ { 50, "No Group Call Number Available" },
+ { 51, "Resource Limitation" },
+ { 52, "Unauthorized Requesting Network" },
+ { 53, "Unauthorized LCS Client" },
+ { 54, "Position Method Failure" },
+ { 58, "Unknown Or Unreachable LCS Client" },
+ { 59, "MM Event Not Supported" },
+ { 60, "ATSI Not Allowed" },
+ { 61, "ATM Not Allowed" },
+ { 62, "Information Not Available" },
+ { 71, "Unknown Alphabet" },
+ { 72, "USSD Busy" },
+ { 120, "Nbr Sb Exceeded" },
+ { 121, "Rejected By User" },
+ { 122, "Rejected By Network" },
+ { 123, "Deflection To Served Subscriber" },
+ { 124, "Special Service Code" },
+ { 125, "Invalid Deflected To Number" },
+ { 126, "Max Number Of MPTY Participants Exceeded" },
+ { 127, "Resources Not Available" },
+ { 0, NULL }
+};
+
+const value_string gsm_ss_opr_code_strings[] = {
+ { 10, "Register SS" },
+ { 11, "Erase SS" },
+ { 12, "Activate SS" },
+ { 13, "Deactivate SS" },
+ { 14, "Interrogate SS" },
+ { 16, "Notify SS" },
+ { 17, "Register Password" },
+ { 18, "Get Password" },
+ { 19, "Process Unstructured SS Data" },
+ { 38, "Forward Check SS Indication" },
+ { 59, "Process Unstructured SS Request" },
+ { 60, "Unstructured SS Request" },
+ { 61, "Unstructured SS Notify" },
+ { 77, "Erase CC Entry" },
+ { 117, "Call Deflection" },
+ { 118, "User User Service" },
+ { 119, "Access Register CC Entry" },
+ { 120, "Forward CUG Info" },
+ { 121, "Split MPTY" },
+ { 122, "Retrieve MPTY" },
+ { 123, "Hold MPTY" },
+ { 124, "Build MPTY" },
+ { 125, "Forward Charge Advice" },
+ { 126, "Explicit CT" },
+ { 116, "LCS Location Notification" },
+ { 115, "LCS MOLR" },
+
+ { 0, NULL }
+};
+
+
+/* never initialize in field array */
+static int hf_null = -1;
+#define HF_NULL &hf_null
+
+gint gsm_ss_ett[NUM_GSM_SS_ETT]; /* initialization is left to users */
+
+static gboolean gsm_ss_seven_bit = FALSE;
+static gboolean gsm_ss_eight_bit = FALSE;
+static gboolean gsm_ss_ucs2 = FALSE;
+static gboolean gsm_ss_compressed = FALSE;
+
+
+typedef struct dgt_set_t
+{
+ unsigned char out[15];
+}
+dgt_set_t;
+
+#ifdef MLUM
+static dgt_set_t Dgt_tbcd = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#'
+ }
+};
+#endif
+
+static dgt_set_t Dgt_msid = {
+ {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e */
+ '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
+ }
+};
+
+
+/* FORWARD DECLARATIONS */
+
+static void op_generic_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len);
+
+
+/* GENERIC HELPER FUNCTIONS */
+
+/*
+ * Unpack BCD input pattern into output ASCII pattern
+ *
+ * Input Pattern is supplied using the same format as the digits
+ *
+ * Returns: length of unpacked pattern
+ */
+static int
+my_dgt_tbcd_unpack(
+ char *out, /* ASCII pattern out */
+ guchar *in, /* packed pattern in */
+ int num_octs, /* Number of octets to unpack */
+ dgt_set_t *dgt /* Digit definitions */
+ )
+{
+ int cnt = 0;
+ unsigned char i;
+
+ while (num_octs)
+ {
+ /*
+ * unpack first value in byte
+ */
+ i = *in++;
+ *out++ = dgt->out[i & 0x0f];
+ cnt++;
+
+ /*
+ * unpack second value in byte
+ */
+ i >>= 4;
+
+ if (i == 0x0f) /* odd number bytes - hit filler */
+ break;
+
+ *out++ = dgt->out[i];
+ cnt++;
+ num_octs--;
+ }
+
+ *out = '\0';
+
+ return(cnt);
+}
+
+static gchar *
+my_match_strval(guint32 val, const value_string *vs, gint *idx)
+{
+ gint i = 0;
+
+ while (vs[i].strptr) {
+ if (vs[i].value == val)
+ {
+ *idx = i;
+ return(vs[i].strptr);
+ }
+
+ i++;
+ }
+
+ *idx = -1;
+ return(NULL);
+}
+
+/* PARAMETER dissection */
+
+void
+param_AddressString(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+ guchar *poctets;
+ gchar *str = NULL;
+ char bigbuf[1024];
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : %sxtension",
+ bigbuf, (value & 0x80) ? "No E" : "E");
+
+ switch ((value & 0x70) >> 4)
+ {
+ case 0x00: str = "unknown"; break;
+ case 0x01: str = "International Number"; break;
+ case 0x02: str = "National Significant Number"; break;
+ case 0x03: str = "Network Specific Number"; break;
+ case 0x04: str = "Subscriber Number"; break;
+ case 0x05: str = "Reserved"; break;
+ case 0x06: str = "Abbreviated Number"; break;
+ case 0x07: str = "Reserved for extension"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x70, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ switch (value & 0x0f)
+ {
+ case 0x00: str = "unknown"; break;
+ case 0x01: str = "ISDN/Telephony Numbering (Rec ITU-T E.164)"; break;
+ case 0x02: str = "spare"; break;
+ case 0x03: str = "Data Numbering (ITU-T Rec. X.121)"; break;
+ case 0x04: str = "Telex Numbering (ITU-T Rec. F.69)"; break;
+ case 0x05: str = "spare"; break;
+ case 0x06: str = "Land Mobile Numbering (ITU-T Rec. E.212)"; break;
+ case 0x07: str = "spare"; break;
+ case 0x08: str = "National Numbering"; break;
+ case 0x09: str = "Private Numbering"; break;
+ case 0x0f: str = "Reserved for extension"; break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ "%s : %s",
+ bigbuf, str);
+
+ saved_offset = asn1->offset;
+ asn1_string_value_decode(asn1, len - 1, &poctets);
+
+ my_dgt_tbcd_unpack(bigbuf, poctets, len - 1, &Dgt_msid);
+ g_free(poctets);
+
+ if (hf_field == -1)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len - 1, "BCD Digits %s", bigbuf);
+ }
+ else
+ {
+ proto_tree_add_string_format(tree, hf_field, asn1->tvb,
+ saved_offset, len - 1, bigbuf, "BCD Digits %s", bigbuf);
+ }
+}
+
+static void
+param_ssCode(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+ gchar *str = NULL;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ switch (value)
+ {
+ case 0x00:
+ str = "allSS - all SS";
+ break;
+
+ case 0x10:
+ str = "allLineIdentificationSS - all line identification SS";
+ break;
+
+ case 0x11:
+ str = "clip - calling line identification presentation";
+ break;
+
+ case 0x12:
+ str = "clir - calling line identification restriction";
+ break;
+
+ case 0x13:
+ str = "colp - connected line identification presentation";
+ break;
+
+ case 0x14:
+ str = "colr - connected line identification restriction";
+ break;
+
+ case 0x15:
+ str = "mci - malicious call identification";
+ break;
+
+ case 0x18:
+ str = "allNameIdentificationSS - all name indentification SS";
+ break;
+
+ case 0x19:
+ str = "cnap - calling name presentation";
+ break;
+
+ case 0x20:
+ str = "allForwardingSS - all forwarding SS";
+ break;
+
+ case 0x21:
+ str = "cfu - call forwarding unconditional";
+ break;
+
+ case 0x28:
+ str = "allCondForwardingSS - all conditional forwarding SS";
+ break;
+
+ case 0x29:
+ str = "cfb - call forwarding busy";
+ break;
+
+ case 0x2a:
+ str = "cfnry - call forwarding on no reply";
+ break;
+
+ case 0x2b:
+ str = "cfnrc - call forwarding on mobile subscriber not reachable";
+ break;
+
+ case 0x24:
+ str = "cd - call deflection";
+ break;
+
+ case 0x30:
+ str = "allCallOfferingSS - all call offering SS includes also all forwarding SS";
+ break;
+
+ case 0x31:
+ str = "ect - explicit call transfer";
+ break;
+
+ case 0x32:
+ str = "mah - mobile access hunting";
+ break;
+
+ case 0x40:
+ str = "allCallCompletionSS - all Call completion SS";
+ break;
+
+ case 0x41:
+ str = "cw - call waiting";
+ break;
+
+ case 0x42:
+ str = "hold - call hold";
+ break;
+
+ case 0x43:
+ str = "ccbs-A - completion of call to busy subscribers, originating side";
+ break;
+
+ case 0x44:
+ str = "ccbs-B - completion of call to busy subscribers, destination side";
+ break;
+
+ case 0x45:
+ str = "mc - multicall";
+ break;
+
+ case 0x50:
+ str = "allMultiPartySS - all multiparty SS";
+ break;
+
+ case 0x51:
+ str = "multiPTY - multiparty";
+ break;
+
+ case 0x60:
+ str = "allCommunityOfInterestSS - all community of interest SS";
+ break;
+
+ case 0x61:
+ str = "cug - closed user group";
+ break;
+
+ case 0x70:
+ str = "allChargingSS - all charging SS";
+ break;
+
+ case 0x71:
+ str = "aoci - advice of charge information";
+ break;
+
+ case 0x72:
+ str = "aocc - advice of charge charging";
+ break;
+
+ case 0x80:
+ str = "allAdditionalInfoTransferSS - all additional information transfer SS";
+ break;
+
+ case 0x81:
+ str = "uus1 - UUS1 user-to-user signalling";
+ break;
+
+ case 0x82:
+ str = "uus2 - UUS2 user-to-user signalling";
+ break;
+
+ case 0x83:
+ str = "uus3 - UUS3 user-to-user signalling";
+ break;
+
+ case 0x90:
+ str = "allBarringSS - all barring SS";
+ break;
+
+ case 0x91:
+ str = "barringOfOutgoingCalls";
+ break;
+
+ case 0x92:
+ str = "baoc - barring of all outgoing calls";
+ break;
+
+ case 0x93:
+ str = "boic - barring of outgoing international calls";
+ break;
+
+ case 0x94:
+ str = "boicExHC - barring of outgoing international calls except those directed to the home PLMN";
+ break;
+
+ case 0x99:
+ str = "barringOfIncomingCalls";
+ break;
+
+ case 0x9a:
+ str = "baic - barring of all incoming calls";
+ break;
+
+ case 0x9b:
+ str = "bicRoam - barring of incoming calls when roaming outside home PLMN Country";
+ break;
+
+ case 0xf0:
+ str = "allPLMN-specificSS";
+ break;
+
+ case 0xa0:
+ str = "allCallPrioritySS - all call priority SS";
+ break;
+
+ case 0xa1:
+ str = "emlpp - enhanced Multilevel Precedence Pre-emption (EMLPP) service";
+ break;
+
+ case 0xb0:
+ str = "allLCSPrivacyException - all LCS Privacy Exception Classes";
+ break;
+
+ case 0xb1:
+ str = "universal - allow location by any LCS client";
+ break;
+
+ case 0xb2:
+ str = "callrelated - allow location by any value added LCS client to which a call is established from the target MS";
+ break;
+
+ case 0xb3:
+ str = "callunrelated - allow location by designated external value added LCS clients";
+ break;
+
+ case 0xb4:
+ str = "plmnoperator - allow location by designated PLMN operator LCS clients";
+ break;
+
+ case 0xc0:
+ str = "allMOLR-SS - all Mobile Originating Location Request Classes";
+ break;
+
+ case 0xc1:
+ str = "basicSelfLocation - allow an MS to request its own location";
+ break;
+
+ case 0xc2:
+ str = "autonomousSelfLocation - allow an MS to perform self location without interaction with the PLMN for a predetermined period of time";
+ break;
+
+ case 0xc3:
+ str = "transferToThirdParty - allow an MS to request transfer of its location to another LCS client";
+ break;
+
+ default:
+ /*
+ * XXX
+ */
+ str = "reserved for future use";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str);
+}
+
+/*
+ * See GSM 03.11
+ */
+static void
+param_ssStatus(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+ char bigbuf[1024];
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Unused",
+ bigbuf);
+
+ /*
+ * Q bit is valid only if A bit is "Active"
+ */
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Q bit: %s",
+ bigbuf,
+ (value & 0x01) ?
+ ((value & 0x08) ? "Quiescent" : "Operative") : "N/A");
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : P bit: %sProvisioned",
+ bigbuf,
+ (value & 0x04) ? "" : "Not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x02, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : R bit: %sRegistered",
+ bigbuf,
+ (value & 0x02) ? "" : "Not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x01, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : A bit: %sActive",
+ bigbuf,
+ (value & 0x01) ? "" : "Not ");
+}
+
+static void
+param_bearerservice(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+ gchar *str = NULL;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ switch (value)
+ {
+ case 0x00: str = "allBearerServices"; break;
+ case 0x10: str = "allDataCDA-Services"; break;
+ case 0x11: str = "dataCDA-300bps"; break;
+ case 0x12: str = "dataCDA-1200bps"; break;
+ case 0x13: str = "dataCDA-1200-75bps"; break;
+ case 0x14: str = "dataCDA-2400bps"; break;
+ case 0x15: str = "dataCDA-4800bps"; break;
+ case 0x16: str = "dataCDA-9600bps"; break;
+ case 0x17: str = "general-dataCDA"; break;
+ case 0x18: str = "allDataCDS-Services"; break;
+ case 0x1a: str = "dataCDS-1200bps"; break;
+ case 0x1c: str = "dataCDS-2400bps"; break;
+ case 0x1d: str = "dataCDS-4800bps"; break;
+ case 0x1e: str = "dataCDS-9600bps"; break;
+ case 0x1f: str = "general-dataCDS"; break;
+
+ case 0x20: str = "allPadAccessCA-Services"; break;
+ case 0x21: str = "padAccessCA-300bps"; break;
+ case 0x22: str = "padAccessCA-1200bps"; break;
+ case 0x23: str = "padAccessCA-1200-75bps"; break;
+ case 0x24: str = "padAccessCA-2400bps"; break;
+ case 0x25: str = "padAccessCA-4800bps"; break;
+ case 0x26: str = "padAccessCA-9600bps"; break;
+ case 0x27: str = "general-padAccessCA"; break;
+ case 0x28: str = "allDataPDS-Services"; break;
+ case 0x2c: str = "dataPDS-2400bps"; break;
+ case 0x2d: str = "dataPDS-4800bps"; break;
+ case 0x2e: str = "dataPDS-9600bps"; break;
+ case 0x2f: str = "general-dataPDS"; break;
+
+ case 0x30: str = "allAlternateSpeech-DataCDA"; break;
+ case 0x38: str = "allAlternateSpeech-DataCDS"; break;
+ case 0x40: str = "allSpeechFollowedByDataCDA"; break;
+ case 0x48: str = "allSpeechFollowedByDataCDS"; break;
+
+ case 0x50: str = "allDataCircuitAsynchronous"; break;
+ case 0x60: str = "allAsynchronousServices"; break;
+ case 0x58: str = "allDataCircuitSynchronous"; break;
+ case 0x68: str = "allSynchronousServices"; break;
+
+ case 0xd0: str = "allPLMN-specificBS"; break;
+ case 0xd1: str = "plmn-specificBS-1"; break;
+ case 0xd2: str = "plmn-specificBS-2"; break;
+ case 0xd3: str = "plmn-specificBS-3"; break;
+ case 0xd4: str = "plmn-specificBS-4"; break;
+ case 0xd5: str = "plmn-specificBS-5"; break;
+ case 0xd6: str = "plmn-specificBS-6"; break;
+ case 0xd7: str = "plmn-specificBS-7"; break;
+ case 0xd8: str = "plmn-specificBS-8"; break;
+ case 0xd9: str = "plmn-specificBS-9"; break;
+ case 0xda: str = "plmn-specificBS-A"; break;
+ case 0xdb: str = "plmn-specificBS-B"; break;
+ case 0xdc: str = "plmn-specificBS-C"; break;
+ case 0xdd: str = "plmn-specificBS-D"; break;
+ case 0xde: str = "plmn-specificBS-E"; break;
+ case 0xdf: str = "plmn-specificBS-F"; break;
+
+ default:
+ str = "Undefined";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str);
+}
+
+static void
+param_teleservice(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+ gchar *str = NULL;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ switch (value)
+ {
+ case 0x00: str = "allTeleservices"; break;
+ case 0x10: str = "allSpeechTransmissionServices"; break;
+ case 0x11: str = "telephony"; break;
+ case 0x12: str = "emergencyCalls"; break;
+ case 0x20: str = "allShortMessageServices"; break;
+ case 0x21: str = "shortMessageMT-PP"; break;
+ case 0x22: str = "shortMessageMO-PP"; break;
+ case 0x60: str = "allFacsimileTransmissionServices"; break;
+ case 0x61: str = "facsimileGroup3AndAlterSpeech"; break;
+ case 0x62: str = "automaticFacsimileGroup3"; break;
+ case 0x63: str = "facsimileGroup4"; break;
+
+ case 0x70: str = "allDataTeleservices"; break;
+ case 0x80: str = "allTeleservices-ExeptSMS"; break;
+
+ case 0x90: str = "allVoiceGroupCallServices"; break;
+ case 0x91: str = "voiceGroupCall"; break;
+ case 0x92: str = "voiceBroadcastCall"; break;
+
+ case 0xd0: str = "allPLMN-specificTS"; break;
+ case 0xd1: str = "plmn-specificTS-1"; break;
+ case 0xd2: str = "plmn-specificTS-2"; break;
+ case 0xd3: str = "plmn-specificTS-3"; break;
+ case 0xd4: str = "plmn-specificTS-4"; break;
+ case 0xd5: str = "plmn-specificTS-5"; break;
+ case 0xd6: str = "plmn-specificTS-6"; break;
+ case 0xd7: str = "plmn-specificTS-7"; break;
+ case 0xd8: str = "plmn-specificTS-8"; break;
+ case 0xd9: str = "plmn-specificTS-9"; break;
+ case 0xda: str = "plmn-specificTS-A"; break;
+ case 0xdb: str = "plmn-specificTS-B"; break;
+ case 0xdc: str = "plmn-specificTS-C"; break;
+ case 0xdd: str = "plmn-specificTS-D"; break;
+ case 0xde: str = "plmn-specificTS-E"; break;
+ case 0xdf: str = "plmn-specificTS-F"; break;
+
+ default:
+ str = "Undefined";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str);
+}
+
+/*
+ * GSM 03.38
+ * Same as Cell Broadcast
+ */
+static void
+param_ussdDCS(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+ gchar *str = NULL;
+ char bigbuf[1024];
+ proto_tree *subtree;
+ proto_item *item;
+
+ hf_field = hf_field;
+
+ gsm_ss_seven_bit = FALSE;
+ gsm_ss_eight_bit = FALSE;
+ gsm_ss_ucs2 = FALSE;
+ gsm_ss_compressed = FALSE;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "Data Coding Scheme (%d)",
+ value);
+
+ subtree = proto_item_add_subtree(item, gsm_ss_ett[GSM_SS_ETT_PARAM]);
+
+ if ((value & 0xf0) == 0x00)
+ {
+ /* 0000.... Language using the default alphabet */
+
+ switch (value & 0x0f)
+ {
+ case 0x00: str = "German"; break;
+ case 0x01: str = "English"; break;
+ case 0x02: str = "Italian"; break;
+ case 0x03: str = "French"; break;
+ case 0x04: str = "Spanish"; break;
+ case 0x05: str = "Dutch"; break;
+ case 0x06: str = "Swedish"; break;
+ case 0x07: str = "Danish"; break;
+ case 0x08: str = "Portuguese"; break;
+ case 0x09: str = "Finnish"; break;
+ case 0x0a: str = "Norwegian"; break;
+ case 0x0b: str = "Greek"; break;
+ case 0x0c: str = "Turkish"; break;
+ case 0x0d: str = "Hungarian"; break;
+ case 0x0e: str = "Polish"; break;
+ case 0x0f: str = "Language unspecified"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0f, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : %s language using default alphabet",
+ bigbuf,
+ str);
+
+ gsm_ss_seven_bit = TRUE;
+ }
+ else if ((value & 0xf0) == 0x10)
+ {
+ switch (value & 0x0f)
+ {
+ case 0x00: str = "Default alphabet; message preceded by language indication"; break;
+ case 0x01: str = "UCS2; message preceded by language indication"; break;
+ default:
+ str = "Reserved for European languages";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : %s",
+ bigbuf,
+ str);
+ }
+ else if ((value & 0xf0) == 0x20)
+ {
+ switch (value & 0x0f)
+ {
+ case 0x00: str = "Czech"; break;
+ default:
+ str = "Reserved for European languages using the default alphabet";
+ break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : %s",
+ bigbuf,
+ str);
+ }
+ else if ((value & 0xf0) == 0x30)
+ {
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Reserved for European Languages using the default alphabet",
+ bigbuf);
+ }
+ else if ((value & 0xc0) == 0x40)
+ {
+ other_decode_bitfield_value(bigbuf, value, 0xc0, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : General Data Coding indication",
+ bigbuf);
+
+ gsm_ss_compressed = (value & 0x20) >> 5;
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Text is %scompressed",
+ bigbuf,
+ gsm_ss_compressed ? "" : "not ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : %s",
+ bigbuf,
+ (value & 0x10) ? "Message class is defined below" :
+ "Reserved, no message class");
+
+ switch ((value & 0x0c) >> 2)
+ {
+ case 0x00: str = "GSM 7 bit default alphabet";
+ gsm_ss_seven_bit = TRUE;
+ break;
+ case 0x01: str = "8 bit data"; break;
+ case 0x02: str = "UCS2 (16 bit)";
+ gsm_ss_ucs2 = TRUE;
+ break;
+ case 0x03: str = "Reserved"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Character set: %s",
+ bigbuf,
+ str);
+
+ switch (value & 0x03)
+ {
+ case 0x00: str = "Class 0"; break;
+ case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
+ case 0x02: str = "Class 2 (U)SIM specific message"; break;
+ case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Message Class: %s%s",
+ bigbuf,
+ str,
+ (value & 0x10) ? "" : " (reserved)");
+ }
+ else if ((value & 0xf0) == 0xf0)
+ {
+ other_decode_bitfield_value(bigbuf, value, 0xf0, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Data Coding / Message Handling",
+ bigbuf);
+
+ other_decode_bitfield_value(bigbuf, value, 0x08, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Reserved",
+ bigbuf);
+
+ gsm_ss_seven_bit = !(gsm_ss_eight_bit = (value & 0x04) ? TRUE : FALSE);
+
+ other_decode_bitfield_value(bigbuf, value, 0x04, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Message coding: %s",
+ bigbuf,
+ gsm_ss_eight_bit ? "8 bit data" : "Default alphabet");
+
+ switch (value & 0x03)
+ {
+ case 0x00: str = "No message class"; break;
+ case 0x01: str = "Class 1 user defined"; break;
+ case 0x02: str = "Class 2 user defined"; break;
+ case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Message Class: %s",
+ bigbuf,
+ str);
+ }
+ else
+ {
+ other_decode_bitfield_value(bigbuf, value, 0xff, 8);
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1,
+ "%s : Reserved coding groups",
+ bigbuf);
+ }
+}
+
+static void
+param_ussdString(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ char bigbuf[1024];
+ guint8 fill_bits;
+ guint32 out_len;
+ char *ustr;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+
+ if (gsm_ss_compressed)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "Compressed data");
+ }
+ else
+ {
+ if (gsm_ss_seven_bit)
+ {
+ fill_bits = 0;
+
+ out_len =
+ gsm_sms_char_7bit_unpack(fill_bits, len, sizeof(bigbuf),
+ tvb_get_ptr(asn1->tvb, saved_offset, len), bigbuf);
+ bigbuf[out_len] = '\0';
+ gsm_sms_char_ascii_decode(bigbuf, bigbuf, out_len);
+
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s", bigbuf);
+ }
+ else if (gsm_ss_eight_bit)
+ {
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s",
+ tvb_format_text(asn1->tvb, saved_offset, len));
+ }
+ else if (gsm_ss_ucs2)
+ {
+ ustr = tvb_fake_unicode(asn1->tvb, saved_offset, len, FALSE);
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s", ustr);
+ g_free(ustr);
+ }
+ else
+ {
+ /* don't know what form it is */
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len,
+ "Parameter Data");
+ }
+ }
+
+ asn1->offset += len;
+}
+
+static void
+param_ia5String(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s",
+ tvb_format_text(asn1->tvb, saved_offset, len));
+
+ asn1->offset += len;
+}
+
+static void
+param_password(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, len, "%s",
+ tvb_format_text(asn1->tvb, saved_offset, len));
+
+ asn1->offset += len;
+}
+
+static void
+param_guidanceInfo(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+ gchar *str = NULL;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ switch (value)
+ {
+ case 0: str = "enterPW"; break;
+ case 1: str = "enterNewPW"; break;
+ case 2: str = "enterNewPW-Again"; break;
+ default:
+ str = "Unknown";
+ break;
+ }
+
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, len, str);
+}
+
+static void
+param_forwardingOpt(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field)
+{
+ guint saved_offset;
+ gint32 value;
+ char bigbuf[1024];
+ gchar *str = NULL;
+
+ hf_field = hf_field;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &value);
+
+ other_decode_bitfield_value(bigbuf, value, 0x80, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : %snotification to forwarding party",
+ bigbuf,
+ (value & 0x80) ? "" : "no ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x40, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : %sredirecting presentation",
+ bigbuf,
+ (value & 0x40) ? "" : "no ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x20, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : %snotification to calling party",
+ bigbuf,
+ (value & 0x20) ? "" : "no ");
+
+ other_decode_bitfield_value(bigbuf, value, 0x10, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : unused",
+ bigbuf);
+
+ switch ((value & 0x0c) >> 2)
+ {
+ case 0x00: str = "MS not reachable"; break;
+ case 0x01: str = "MS busy"; break;
+ case 0x02: str = "No reply"; break;
+ case 0x03: str = "Unconditional (in SRI result) or Deflection"; break;
+ }
+
+ other_decode_bitfield_value(bigbuf, value, 0x0c, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : forwarding reason, %s (%u)",
+ bigbuf,
+ str,
+ (value & 0x0c) >> 2);
+
+ other_decode_bitfield_value(bigbuf, value, 0x03, 8);
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, 1,
+ "%s : unused",
+ bigbuf);
+
+ asn1->offset += len;
+}
+
+
+typedef enum
+{
+ GSM_SS_P_SS_CODE, /* SS-Code */
+ GSM_SS_P_SS_STATUS, /* SS-Status */
+ GSM_SS_P_BEARERSERVICE, /* Bearer Service */
+ GSM_SS_P_TELESERVICE, /* Tele Service */
+ GSM_SS_P_FORWARD_TO_NUM, /* Forward to Number */
+ GSM_SS_P_LONG_FORWARD_TO_NUM, /* Long Forward to Number */
+ GSM_SS_P_USSD_DCS, /* USSD Data Coding Scheme */
+ GSM_SS_P_USSD_STRING, /* USSD String */
+ GSM_SS_P_IA5_STRING, /* IA5 String */
+ GSM_SS_P_PASSWORD, /* Password */
+ GSM_SS_P_GUIDANCE_INFO, /* Guidance Info */
+ GSM_SS_P_FORWARDING_OPT, /* Forwarding Options */
+ GSM_SS_P_NONE /* NONE */
+}
+param_idx_t;
+
+#define NUM_PARAM_1 (GSM_SS_P_NONE+1)
+static gint ett_param_1[NUM_PARAM_1];
+static void (*param_1_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = {
+ param_ssCode, /* SS-Code */
+ param_ssStatus, /* SS-Status */
+ param_bearerservice, /* Bearer Service */
+ param_teleservice, /* Tele Service */
+ param_AddressString, /* Forward to Number */
+ param_AddressString, /* Long Forward to Number */
+ param_ussdDCS, /* USSD Data Coding Scheme */
+ param_ussdString, /* USSD String */
+ param_ia5String, /* IA5 String */
+ param_password, /* Password */
+ param_guidanceInfo, /* Guidance Info */
+ param_forwardingOpt, /* Forwarding Options */
+ NULL /* NONE */
+};
+
+static int *param_1_hf[] = {
+ HF_NULL, /* SS-Code */
+ HF_NULL, /* SS-Status */
+ HF_NULL, /* Bearer Service */
+ HF_NULL, /* Tele Service */
+ HF_NULL, /* Forward to Number */
+ HF_NULL, /* Long Forward to Number */
+ HF_NULL, /* USSD Data Coding Scheme */
+ HF_NULL, /* USSD String */
+ HF_NULL, /* IA5 String */
+ HF_NULL, /* Password */
+ HF_NULL, /* Guidance Info */
+ HF_NULL, /* Forwarding Options */
+ NULL /* NONE */
+};
+
+#define GSM_SS_START_SUBTREE(_Gtree, _Gsaved_offset, _Gtag, _Gstr1, _Gett, _Gdef_len_p, _Glen_p, _Gsubtree_p) \
+ { \
+ guint _len_offset; \
+ proto_item *_item; \
+ \
+ _len_offset = asn1->offset; \
+ asn1_length_decode(asn1, _Gdef_len_p, _Glen_p); \
+ \
+ _item = \
+ proto_tree_add_text(_Gtree, asn1->tvb, _Gsaved_offset, -1, _Gstr1); \
+ \
+ _Gsubtree_p = proto_item_add_subtree(_item, _Gett); \
+ \
+ proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
+ _Gsaved_offset, _len_offset - _Gsaved_offset, "Tag: 0x%02x", _Gtag); \
+ \
+ if (*_Gdef_len_p) \
+ { \
+ proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
+ _len_offset, asn1->offset - _len_offset, "Length: %d", *_Glen_p); \
+ } \
+ else \
+ { \
+ proto_tree_add_text(_Gsubtree_p, asn1->tvb, \
+ _len_offset, asn1->offset - _len_offset, "Length: Indefinite"); \
+ \
+ *_Glen_p = tcap_find_eoc(asn1); \
+ } \
+ \
+ proto_item_set_len(_item, (asn1->offset - _Gsaved_offset) + *_Glen_p + \
+ (*_Gdef_len_p ? 0 : TCAP_EOC_LEN)); \
+ }
+
+#define GSM_SS_PARAM_DISPLAY(Gtree, Goffset, Gtag, Ga1, Ga2) \
+ { \
+ gint _ett_param_idx; \
+ guint _len; \
+ void (*_param_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field) = NULL; \
+ int *_param_hf = NULL; \
+ proto_tree *_subtree; \
+ gboolean _def_len; \
+ \
+ if (Ga1 == GSM_SS_P_NONE) \
+ { \
+ _ett_param_idx = gsm_ss_ett[GSM_SS_ETT_PARAM]; \
+ _param_fcn = NULL; \
+ _param_hf = HF_NULL; \
+ } \
+ else \
+ { \
+ _ett_param_idx = ett_param_1[Ga1]; \
+ _param_fcn = param_1_fcn[Ga1]; \
+ _param_hf = param_1_hf[Ga1]; \
+ } \
+ \
+ GSM_SS_START_SUBTREE(Gtree, Goffset, Gtag, Ga2, _ett_param_idx, &_def_len, &_len, _subtree); \
+ \
+ if (_len > 0) \
+ { \
+ if (Ga1 == GSM_SS_P_NONE || _param_fcn == NULL) \
+ { \
+ proto_tree_add_text(_subtree, asn1->tvb, \
+ asn1->offset, _len, "Parameter Data"); \
+ \
+ asn1->offset += _len; \
+ } \
+ else \
+ { \
+ (*_param_fcn)(asn1, _subtree, _len, *_param_hf); \
+ } \
+ } \
+ \
+ if (!_def_len) \
+ { \
+ guint _saved_offset; \
+ \
+ _saved_offset = asn1->offset; \
+ asn1_eoc_decode(asn1, -1); \
+ \
+ proto_tree_add_text(Gtree, asn1->tvb, \
+ _saved_offset, asn1->offset - _saved_offset, "End of Contents"); \
+ } \
+ }
+
+
+static void
+param_forwardingFeature(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+ guint tag, len;
+ gboolean def_len;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Forwarding Feature",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ if (tcap_check_tag(asn1, 0x82))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice");
+ }
+
+ if (tcap_check_tag(asn1, 0x83))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice");
+ }
+
+ if (tcap_check_tag(asn1, 0x84))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_STATUS, "SS-Status");
+ }
+
+ if (tcap_check_tag(asn1, 0x85))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_FORWARD_TO_NUM, "Forwarded to Number");
+ }
+
+ if (tcap_check_tag(asn1, 0x88))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Forwarded to Subaddress");
+ }
+
+ if (tcap_check_tag(asn1, 0x86))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_FORWARDING_OPT, "Forwarding Options");
+ }
+
+ if (tcap_check_tag(asn1, 0x87))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "No Reply Condition Time");
+ }
+
+ if (tcap_check_tag(asn1, 0x89))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_LONG_FORWARD_TO_NUM, "Long Forward to Number");
+ }
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+}
+
+static void
+param_forwardingFeatureList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len;
+ proto_tree *subtree;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Forwarding Feature List",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
+ (!tcap_check_tag(asn1, 0)))
+ {
+ if ((exp_len != 0) &&
+ ((asn1->offset - saved_offset) >= exp_len))
+ {
+ break;
+ }
+
+ param_forwardingFeature(asn1, subtree, len - (asn1->offset - start_offset));
+ }
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+}
+
+static void
+param_callBarringFeature(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+ guint tag, len;
+ gboolean def_len;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Call Barring Feature",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ if (tcap_check_tag(asn1, 0x82))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice");
+ }
+
+ if (tcap_check_tag(asn1, 0x83))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice");
+ }
+
+ if (tcap_check_tag(asn1, 0x84))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_STATUS, "SS-Status");
+ }
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+}
+
+static void
+param_callBarringFeatureList(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len;
+ proto_tree *subtree;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Call Barring Feature List",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
+ (!tcap_check_tag(asn1, 0)))
+ {
+ if ((exp_len != 0) &&
+ ((asn1->offset - saved_offset) >= exp_len))
+ {
+ break;
+ }
+
+ param_callBarringFeature(asn1, subtree, len - (asn1->offset - start_offset));
+ }
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+}
+
+static void
+param_ssData(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ saved_offset = asn1->offset;
+
+ /* XXX */
+ op_generic_ss(asn1, tree, exp_len);
+}
+
+static void
+param_ssInfo(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset, start_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ switch (tag)
+ {
+ case 0xa0: /* forwardingInfo */
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Forwarding Info",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ if (tcap_check_tag(asn1, 0x04))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
+ }
+
+ param_forwardingFeatureList(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+ break;
+
+ case 0xa1: /* callBarringInfo */
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Call Barring Info",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ if (tcap_check_tag(asn1, 0x04))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
+ }
+
+ param_callBarringFeatureList(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+ break;
+
+ case 0xa3: /* ss-Data */
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "ss-Data",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ param_ssData(asn1, subtree, len - (asn1->offset - start_offset));
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+ break;
+
+ default:
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Unexpected TAG",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ op_generic_ss(asn1, subtree, len);
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+ break;
+ }
+}
+
+static void
+param_ssForBS(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset, start_offset;
+ guint tag, len, rem_len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
+
+ if (tcap_check_tag(asn1, 0x82))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice");
+ }
+
+ if (tcap_check_tag(asn1, 0x83))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice");
+ }
+
+ if (tcap_check_tag(asn1, 0x84))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Long FTN supported");
+ }
+
+ rem_len = len - (asn1->offset - start_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, subtree, rem_len);
+ }
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+}
+
+static void
+param_ussdArg(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset, start_offset;
+ guint tag, len, rem_len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_USSD_DCS, "USSD Data Coding Scheme");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_USSD_STRING, "USSD String");
+
+ rem_len = len - (asn1->offset - start_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, subtree, rem_len);
+ }
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+}
+
+static void
+param_ussdRes(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset, start_offset;
+ guint tag, len, rem_len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_USSD_DCS, "USSD Data Coding Scheme");
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_USSD_STRING, "USSD String");
+
+ rem_len = len - (asn1->offset - start_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, subtree, rem_len);
+ }
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+}
+
+
+/* MESSAGES */
+
+static void
+op_generic_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint orig_offset, saved_offset, len_offset;
+ guint tag, len;
+ gboolean def_len = FALSE;
+ proto_item *item;
+ proto_tree *subtree;
+
+ orig_offset = asn1->offset;
+
+ while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
+ (!tcap_check_tag(asn1, 0)))
+ {
+ if ((exp_len != 0) &&
+ ((asn1->offset - orig_offset) >= exp_len))
+ {
+ break;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag))
+ {
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ op_generic_ss(asn1, subtree, len);
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+ continue;
+ }
+
+ len_offset = asn1->offset;
+ asn1_length_decode(asn1, &def_len, &len);
+
+ if (!def_len)
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, len_offset - saved_offset,
+ "Tag: 0x%02x", tag);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ len_offset, asn1->offset - len_offset, "Length: Indefinite");
+
+ len = tcap_find_eoc(asn1);
+
+ op_generic_ss(asn1, tree, len);
+
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ continue;
+ }
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, (asn1->offset - saved_offset) + len, "Parameter");
+
+ subtree = proto_item_add_subtree(item, gsm_ss_ett[GSM_SS_ETT_PARAM]);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, len_offset - saved_offset,
+ "Tag: 0x%02x", tag);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ len_offset, asn1->offset - len_offset, "Length: %d", len);
+
+ if (len > 0)
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ asn1->offset, len, "Parameter Data");
+
+ asn1->offset += len;
+ }
+ }
+}
+
+static void
+op_register_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset, start_offset;
+ guint tag, len, rem_len;
+ gboolean def_len = FALSE;
+ proto_tree *subtree;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_START_SUBTREE(tree, saved_offset, tag, "Sequence",
+ gsm_ss_ett[GSM_SS_ETT_SEQUENCE],
+ &def_len, &len, subtree);
+
+ start_offset = asn1->offset;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
+
+ if (tcap_check_tag(asn1, 0x82))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_BEARERSERVICE, "Bearerservice");
+ }
+
+ if (tcap_check_tag(asn1, 0x83))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_TELESERVICE, "Teleservice");
+ }
+
+ if (tcap_check_tag(asn1, 0x84))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_FORWARD_TO_NUM, "Forwarded to Number");
+ }
+
+ if (tcap_check_tag(asn1, 0x86))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Forwarded to Subaddress");
+ }
+
+ if (tcap_check_tag(asn1, 0x85))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "No Reply Condition Time");
+ }
+
+ if (tcap_check_tag(asn1, 0x87))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Default Priority");
+ }
+
+ if (tcap_check_tag(asn1, 0x88))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Number Users");
+ }
+
+ if (tcap_check_tag(asn1, 0x89))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(subtree, saved_offset, tag, GSM_SS_P_NONE, "Long FTN supported");
+ }
+
+ rem_len = len - (asn1->offset - start_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, subtree, rem_len);
+ }
+
+ if (!def_len)
+ {
+ saved_offset = asn1->offset;
+ asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+ }
+}
+
+static void
+op_register_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ssInfo(asn1, tree);
+}
+
+static void
+op_erase_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ssForBS(asn1, tree);
+}
+
+static void
+op_erase_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ssInfo(asn1, tree);
+}
+
+static void
+op_activate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ssForBS(asn1, tree);
+}
+
+static void
+op_activate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ssInfo(asn1, tree);
+}
+
+static void
+op_deactivate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ssForBS(asn1, tree);
+}
+
+static void
+op_deactivate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ssInfo(asn1, tree);
+}
+
+static void
+op_interrogate_ss(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ssForBS(asn1, tree);
+}
+
+static void
+op_interrogate_ss_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+ guint tag;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ switch (tag)
+ {
+ case 0x80: /* SS-Status */
+ GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_SS_STATUS, "SS-Status");
+ break;
+
+ case 0x82: /* BasicServiceGroupList */
+ /* XXX */
+ asn1->offset = saved_offset;
+ op_generic_ss(asn1, tree, exp_len);
+ break;
+
+ case 0x83: /* ForwardingFeatureList */
+ asn1->offset = saved_offset;
+ param_forwardingFeatureList(asn1, tree, exp_len);
+ break;
+
+ case 0x84: /* GenericServiceInfo */
+ /* XXX */
+ asn1->offset = saved_offset;
+ op_generic_ss(asn1, tree, exp_len);
+ break;
+
+ default:
+ asn1->offset = saved_offset;
+ op_generic_ss(asn1, tree, exp_len);
+ return;
+ }
+}
+
+static void
+op_reg_password(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+ guint tag, rem_len;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_SS_CODE, "SS-Code");
+
+ rem_len = exp_len - (asn1->offset - saved_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, tree, rem_len);
+ }
+}
+
+static void
+op_reg_password_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+ guint tag, rem_len;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_PASSWORD, "New Password");
+
+ rem_len = exp_len - (asn1->offset - saved_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, tree, rem_len);
+ }
+}
+
+static void
+op_get_password(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+ guint tag, rem_len;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_GUIDANCE_INFO, "Guidance Info");
+
+ rem_len = exp_len - (asn1->offset - saved_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, tree, rem_len);
+ }
+}
+
+static void
+op_get_password_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+ guint tag, rem_len;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_PASSWORD, "Current Password");
+
+ rem_len = exp_len - (asn1->offset - saved_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, tree, rem_len);
+ }
+}
+
+static void
+op_proc_uss_data(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+ guint tag, rem_len;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ if (tcap_check_tag(asn1, 0x16))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_IA5_STRING, "SS-UserData");
+ }
+
+ rem_len = exp_len - (asn1->offset - saved_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, tree, rem_len);
+ }
+}
+
+static void
+op_proc_uss_data_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+ guint tag, rem_len;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ if (tcap_check_tag(asn1, 0x16))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ GSM_SS_PARAM_DISPLAY(tree, saved_offset, tag, GSM_SS_P_IA5_STRING, "SS-UserData");
+ }
+
+ rem_len = exp_len - (asn1->offset - saved_offset);
+
+ if (rem_len > 0)
+ {
+ op_generic_ss(asn1, tree, rem_len);
+ }
+}
+
+static void
+op_proc_uss_req(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ussdArg(asn1, tree);
+}
+
+static void
+op_proc_uss_req_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ussdRes(asn1, tree);
+}
+
+static void
+op_uss_req(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ussdArg(asn1, tree);
+}
+
+static void
+op_uss_req_rr(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ussdRes(asn1, tree);
+}
+
+static void
+op_uss_notify(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint saved_offset;
+
+ exp_len = exp_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0) return;
+
+ saved_offset = asn1->offset;
+
+ param_ussdArg(asn1, tree);
+}
+
+#define GSM_SS_NUM_OP (sizeof(gsm_ss_opr_code_strings)/sizeof(value_string))
+static void (*op_fcn[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
+ op_register_ss, /* RegisterSS */
+ op_erase_ss, /* EraseSS */
+ op_activate_ss, /* ActivateSS */
+ op_deactivate_ss, /* DeactivateSS */
+ op_interrogate_ss, /* InterrogateSS */
+ NULL, /* NotifySS */
+ op_reg_password, /* RegisterPassword */
+ op_get_password, /* GetPassword */
+ op_proc_uss_data, /* ProcessUnstructuredSS-Data */
+ NULL, /* ForwardCheckSS-Indication */
+ op_proc_uss_req, /* ProcessUnstructuredSS-Request */
+ op_uss_req, /* UnstructuredSS-Request */
+ op_uss_notify, /* UnstructuredSS-Notify */
+ NULL, /* EraseCC-Entry */
+ NULL, /* LCS-LocationNotification */
+ NULL, /* LCS-MOLR */
+ NULL, /* AccessRegisterCCEntry */
+ NULL, /* ForwardCUG-Info */
+ NULL /* NO ARGS */, /* SplitMPTY */
+ NULL /* NO ARGS */, /* RetrieveMPTY */
+ NULL /* NO ARGS */, /* HoldMPTY */
+ NULL /* NO ARGS */, /* BuildMPTY */
+ NULL, /* ForwardChargeAdvice */
+ NULL, /* ExplicitCT */
+ NULL, /* LCS-LocationNotification */
+ NULL, /* LCS-MOLR */
+
+ NULL /* NONE */
+};
+
+static void (*op_fcn_rr[])(ASN1_SCK *asn1, proto_tree *tree, guint exp_len) = {
+ op_register_ss_rr, /* RegisterSS */
+ op_erase_ss_rr, /* EraseSS */
+ op_activate_ss_rr, /* ActivateSS */
+ op_deactivate_ss_rr, /* DeactivateSS */
+ op_interrogate_ss_rr, /* InterrogateSS */
+ NULL, /* NotifySS */
+ op_reg_password_rr, /* RegisterPassword */
+ op_get_password_rr, /* GetPassword */
+ op_proc_uss_data_rr, /* ProcessUnstructuredSS-Data */
+ NULL, /* ForwardCheckSS-Indication */
+ op_proc_uss_req_rr, /* ProcessUnstructuredSS-Request */
+ op_uss_req_rr, /* UnstructuredSS-Request */
+ NULL /* NO ARGS */, /* UnstructuredSS-Notify */
+ NULL, /* EraseCC-Entry */
+ NULL, /* LCS Location Notification */
+ NULL, /* LCS MOLR */
+ NULL, /* AccessRegisterCCEntry */
+ NULL, /* ForwardCUG-Info */
+ NULL, /* SplitMPTY */
+ NULL, /* RetrieveMPTY */
+ NULL, /* HoldMPTY */
+ NULL, /* BuildMPTY */
+ NULL /* NO ARGS */, /* ForwardChargeAdvice */
+ NULL, /* ExplicitCT */
+ NULL, /* LCS-LocationNotification */
+ NULL, /* LCS-MOLR */
+
+ NULL /* NONE */
+};
+
+void
+gsm_ss_dissect(ASN1_SCK *asn1, proto_tree *tree, guint exp_len,
+ guint opr_code, guint comp_type_tag)
+{
+ void (*dissect_fcn)(ASN1_SCK *asn1, proto_tree *tree, guint exp_len);
+ gchar *str;
+ gint op_idx;
+
+
+ dissect_fcn = NULL;
+
+ str = my_match_strval(opr_code, gsm_ss_opr_code_strings, &op_idx);
+
+ if (str != NULL)
+ {
+ switch (comp_type_tag)
+ {
+ case TCAP_COMP_INVOKE:
+ dissect_fcn = op_fcn[op_idx];
+ break;
+
+ case TCAP_COMP_RRL:
+ dissect_fcn = op_fcn_rr[op_idx];
+ break;
+
+ case TCAP_COMP_RE:
+ dissect_fcn = NULL;
+ return;
+
+ default:
+ /*
+ * no parameters should be present in the component types
+ * ignore
+ */
+ return;
+ }
+ }
+
+ if (dissect_fcn == NULL)
+ {
+ op_generic_ss(asn1, tree, exp_len);
+ }
+ else
+ {
+ (*dissect_fcn)(asn1, tree, exp_len);
+ }
+}
diff --git a/epan/dissectors/packet-gsm_ss.h b/epan/dissectors/packet-gsm_ss.h
new file mode 100644
index 0000000000..8c6c6f7f49
--- /dev/null
+++ b/epan/dissectors/packet-gsm_ss.h
@@ -0,0 +1,40 @@
+/* packet-gsm_ss.h
+ *
+ * $Id$
+ *
+ * Copyright 2004, Michael Lum <mlum [AT] telostech.com>,
+ * In association with Telos Technology Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+typedef enum
+{
+ GSM_SS_ETT_SEQUENCE,
+ GSM_SS_ETT_PARAM
+}
+gsm_ss_ett_e;
+#define NUM_GSM_SS_ETT sizeof(gsm_ss_ett_e)
+extern gint gsm_ss_ett[];
+
+extern const value_string gsm_ss_opr_code_strings[];
+extern const value_string gsm_ss_err_code_strings[];
+
+extern void param_AddressString(ASN1_SCK *asn1, proto_tree *tree, guint len, int hf_field);
+extern void gsm_ss_dissect(ASN1_SCK *asn1, proto_tree *tree, guint exp_len, guint opr_code, guint comp_type_tag);
diff --git a/epan/dissectors/packet-gssapi.c b/epan/dissectors/packet-gssapi.c
new file mode 100644
index 0000000000..e89eb78c30
--- /dev/null
+++ b/epan/dissectors/packet-gssapi.c
@@ -0,0 +1,479 @@
+/* packet-gssapi.c
+ * Dissector for GSS-API tokens as described in rfc2078, section 3.1
+ * Copyright 2002, Tim Potter <tpot@samba.org>
+ * Copyright 2002, Richard Sharpe <rsharpe@samba.org> Added a few
+ * bits and pieces ...
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include "asn1.h"
+#include "format-oid.h"
+#include <epan/dissectors/packet-dcerpc.h>
+#include <epan/dissectors/packet-gssapi.h>
+#include <epan/dissectors/packet-frame.h>
+#include "epan/conversation.h"
+
+static int proto_gssapi = -1;
+
+static int hf_gssapi = -1;
+
+static gint ett_gssapi = -1;
+
+/*
+ * Subdissectors
+ */
+
+static GHashTable *gssapi_oids;
+
+static gint gssapi_oid_equal(gconstpointer k1, gconstpointer k2)
+{
+ const char *key1 = (const char *)k1;
+ const char *key2 = (const char *)k2;
+
+ return strcmp(key1, key2) == 0;
+}
+
+static guint
+gssapi_oid_hash(gconstpointer k)
+{
+ const char *key = (const char *)k;
+ guint hash = 0, i;
+
+ for (i = 0; i < strlen(key); i++)
+ hash += key[i];
+
+ return hash;
+}
+
+void
+gssapi_init_oid(char *oid, int proto, int ett, dissector_handle_t handle,
+ dissector_handle_t wrap_handle, gchar *comment)
+{
+ char *key = g_strdup(oid);
+ gssapi_oid_value *value = g_malloc(sizeof(*value));
+
+ value->proto = find_protocol_by_id(proto);
+ value->ett = ett;
+ value->handle = handle;
+ value->wrap_handle = wrap_handle;
+ value->comment = comment;
+
+ g_hash_table_insert(gssapi_oids, key, value);
+}
+
+/*
+ * This takes an OID in binary form, not an OID as a text string, as
+ * an argument.
+ */
+gssapi_oid_value *
+gssapi_lookup_oid(subid_t *oid, guint oid_len)
+{
+ gchar *oid_key;
+ gchar *p;
+ unsigned int i;
+ int len;
+ gssapi_oid_value *value;
+
+ /*
+ * Convert the OID to a string, as text strings are used as
+ * keys in the OID hash table.
+ */
+ oid_key = g_malloc(oid_len * 22 + 1);
+ p = oid_key;
+ len = sprintf(p, "%lu", (unsigned long)oid[0]);
+ p += len;
+ for (i = 1; i < oid_len;i++) {
+ len = sprintf(p, ".%lu", (unsigned long)oid[i]);
+ p += len;
+ }
+
+ value = g_hash_table_lookup(gssapi_oids, oid_key);
+ g_free(oid_key);
+ return value;
+}
+
+/* Display an ASN1 parse error. Taken from packet-snmp.c */
+
+static dissector_handle_t data_handle;
+
+static void
+dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const char *field_name, int ret)
+{
+ char *errstr;
+
+ errstr = asn1_err_to_str(ret);
+
+ if (tree != NULL) {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "ERROR: Couldn't parse %s: %s", field_name, errstr);
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+}
+
+static int
+dissect_gssapi_work(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean is_verifier)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ ASN1_SCK hnd;
+ int ret, offset = 0;
+ volatile int return_offset = 0;
+ gboolean def;
+ guint len1, oid_len, cls, con, tag, nbytes;
+ subid_t *oid;
+ gchar *oid_string;
+ gssapi_oid_value *value;
+ volatile dissector_handle_t handle;
+ conversation_t *volatile conversation;
+ tvbuff_t *oid_tvb;
+ int len;
+
+ /*
+ * We need this later, so lets get it now ...
+ */
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+
+ item = proto_tree_add_item(
+ tree, hf_gssapi, tvb, offset, -1, FALSE);
+
+ subtree = proto_item_add_subtree(item, ett_gssapi);
+
+ /*
+ * Catch the ReportedBoundsError exception; the stuff we've been
+ * handed doesn't necessarily run to the end of the packet, it's
+ * an item inside a packet, so if it happens to be malformed (or
+ * we, or a dissector we call, has a bug), so that an exception
+ * is thrown, we want to report the error, but return and let
+ * our caller dissect the rest of the packet.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing more
+ * in the packet after our blob to see, so we just re-throw the
+ * exception.
+ */
+ TRY {
+ /* Read header */
+
+ asn1_open(&hnd, tvb, offset);
+
+ ret = asn1_header_decode(&hnd, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "GSS-API header", ret);
+ return_offset = tvb_length(tvb);
+ goto done;
+ }
+
+ if (!(cls == ASN1_APL && con == ASN1_CON && tag == 0)) {
+ /*
+ * If we do not recognise an Application class,
+ * then we are probably dealing with an inner context
+ * token or a wrap token, and we should retrieve the
+ * gssapi_oid_value pointer from the per-frame data or,
+ * if there is no per-frame data (as would be the case
+ * the first time we dissect this frame), from the
+ * conversation that exists or that we created from
+ * pinfo (and then make it per-frame data).
+ * We need to make it per-frame data as there can be
+ * more than one GSS-API negotiation in a conversation.
+ *
+ * Note! We "cheat". Since we only need the pointer,
+ * we store that as the data. (That's not really
+ * "cheating" - the per-frame data and per-conversation
+ * data code doesn't care what you supply as a data
+ * pointer; it just treats it as an opaque pointer, it
+ * doesn't dereference it or free what it points to.)
+ */
+ value = p_get_proto_data(pinfo->fd, proto_gssapi);
+ if (!value && !pinfo->fd->flags.visited)
+ {
+ /* No handle attached to this frame, but it's the first */
+ /* pass, so it'd be attached to the conversation. */
+ /* If we have a conversation, try to get the handle, */
+ /* and if we get one, attach it to the frame. */
+ if (conversation)
+ {
+ value = conversation_get_proto_data(conversation,
+ proto_gssapi);
+ if (value)
+ p_add_proto_data(pinfo->fd, proto_gssapi, value);
+ }
+ }
+ if (!value)
+ {
+ proto_tree_add_text(subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ return_offset = tvb_length(tvb);
+ goto done;
+ }
+ else
+ {
+ tvbuff_t *oid_tvb;
+
+ /* Naughty ... no way to reset the offset */
+ /* Account for the fact we have consumed part of the */
+ /* ASN.1 and we want to get it back */
+
+ hnd.offset = offset;
+ oid_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (is_verifier)
+ handle = value->wrap_handle;
+ else
+ handle = value->handle;
+ len = call_dissector(handle, oid_tvb, pinfo, subtree);
+ if (len == 0)
+ return_offset = tvb_length(tvb);
+ else
+ return_offset = offset + len;
+ goto done; /* We are finished here */
+ }
+ }
+
+ offset = hnd.offset;
+
+ /* Read oid */
+
+ ret = asn1_oid_decode(&hnd, &oid, &oid_len, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "GSS-API token", ret);
+ return_offset = tvb_length(tvb);
+ goto done;
+ }
+
+ oid_string = format_oid(oid, oid_len);
+
+ /*
+ * Hand off to subdissector.
+ */
+
+ if (((value = gssapi_lookup_oid(oid, oid_len)) == NULL) ||
+ !proto_is_protocol_enabled(value->proto)) {
+
+ proto_tree_add_text(subtree, tvb, offset, nbytes,
+ "OID: %s",
+ oid_string);
+
+ offset += nbytes;
+
+ g_free(oid_string);
+
+ /* No dissector for this oid */
+
+ proto_tree_add_text(subtree, tvb, offset, -1,
+ "Token object");
+
+ return_offset = tvb_length(tvb);
+ goto done;
+ }
+
+ if (value)
+ proto_tree_add_text(subtree, tvb, offset, nbytes,
+ "OID: %s (%s)",
+ oid_string, value->comment);
+ else
+ proto_tree_add_text(subtree, tvb, offset, nbytes, "OID: %s",
+ oid_string);
+
+ offset += nbytes;
+
+ g_free(oid_string);
+
+ /*
+ * This is not needed, as the sub-dissector adds a tree
+ sub_item = proto_tree_add_item(subtree, value->proto, tvb,
+ offset, -1, FALSE);
+
+ oid_subtree = proto_item_add_subtree(sub_item, value->ett);
+ */
+
+ /*
+ * Here we should create a conversation if needed and
+ * save a pointer to the data for that OID for the
+ * GSSAPI protocol.
+ */
+
+ if (!conversation) { /* Create one */
+ conversation = conversation_new(&pinfo->src,
+ &pinfo->dst,
+ pinfo->ptype,
+ pinfo->srcport,
+ pinfo->destport, 0);
+ }
+
+ /*
+ * Now add the proto data ...
+ * but only if it is not already there.
+ */
+
+ if (!conversation_get_proto_data(conversation,
+ proto_gssapi)) {
+ conversation_add_proto_data(conversation,
+ proto_gssapi, value);
+ }
+
+ if (is_verifier) {
+ handle = value->wrap_handle;
+ if (handle != NULL) {
+ oid_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ len = call_dissector(handle, oid_tvb, pinfo,
+ subtree);
+ if (len == 0)
+ return_offset = tvb_length(tvb);
+ else
+ return_offset = offset + len;
+ } else {
+ proto_tree_add_text(subtree, tvb, offset, -1,
+ "Authentication verifier");
+ return_offset = tvb_length(tvb);
+ }
+ } else {
+ handle = value->handle;
+ if (handle != NULL) {
+ oid_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ len = call_dissector(handle, oid_tvb, pinfo,
+ subtree);
+ if (len == 0)
+ return_offset = tvb_length(tvb);
+ else
+ return_offset = offset + len;
+ } else {
+ proto_tree_add_text(subtree, tvb, offset, -1,
+ "Authentication credentials");
+ return_offset = tvb_length(tvb);
+ }
+ }
+
+ done:
+ asn1_close(&hnd, &offset);
+ } CATCH(BoundsError) {
+ RETHROW;
+ } CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ } ENDTRY;
+
+ proto_item_set_len(item, return_offset);
+ return return_offset;
+}
+
+static void
+dissect_gssapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_gssapi_work(tvb, pinfo, tree, FALSE);
+}
+
+static int
+dissect_gssapi_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_gssapi_work(tvb, pinfo, tree, TRUE);
+}
+
+void
+proto_register_gssapi(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_gssapi,
+ { "GSS-API", "gss-api", FT_NONE, BASE_NONE, NULL, 0x0,
+ "GSS-API", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_gssapi,
+ };
+
+ proto_gssapi = proto_register_protocol(
+ "Generic Security Service Application Program Interface",
+ "GSS-API", "gss-api");
+
+ proto_register_field_array(proto_gssapi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("gssapi", dissect_gssapi, proto_gssapi);
+ new_register_dissector("gssapi_verf", dissect_gssapi_verf, proto_gssapi);
+
+ gssapi_oids = g_hash_table_new(gssapi_oid_hash, gssapi_oid_equal);
+}
+
+static int wrap_dissect_gssapi(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ tvbuff_t *auth_tvb;
+
+ auth_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ dissect_gssapi(auth_tvb, pinfo, tree);
+
+ return tvb_length_remaining(tvb, offset);
+}
+
+int wrap_dissect_gssapi_verf(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ tvbuff_t *auth_tvb;
+
+ auth_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ return dissect_gssapi_verf(auth_tvb, pinfo, tree);
+}
+
+static dcerpc_auth_subdissector_fns gssapi_auth_fns = {
+ wrap_dissect_gssapi, /* Bind */
+ wrap_dissect_gssapi, /* Bind ACK */
+ wrap_dissect_gssapi, /* AUTH3 */
+ wrap_dissect_gssapi_verf, /* Request verifier */
+ wrap_dissect_gssapi_verf, /* Response verifier */
+ NULL, /* Request data */
+ NULL /* Response data */
+};
+
+void
+proto_reg_handoff_gssapi(void)
+{
+ data_handle = find_dissector("data");
+
+ register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
+ DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO,
+ &gssapi_auth_fns);
+}
diff --git a/epan/dissectors/packet-gssapi.h b/epan/dissectors/packet-gssapi.h
new file mode 100644
index 0000000000..761b8b4c1d
--- /dev/null
+++ b/epan/dissectors/packet-gssapi.h
@@ -0,0 +1,52 @@
+/* packet-gssapi.h
+ * Dissector for GSS-API tokens as described in rfc2078, section 3.1
+ * Copyright 2002, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_GSSAPI_H
+#define __PACKET_GSSAPI_H
+
+/* Structures needed outside */
+
+typedef struct _gssapi_oid_value {
+ protocol_t *proto;
+ int ett;
+ dissector_handle_t handle;
+ dissector_handle_t wrap_handle;
+ gchar *comment; /* For the comment */
+} gssapi_oid_value;
+
+/* Function prototypes */
+
+void
+gssapi_init_oid(char *oid, int proto, int ett, dissector_handle_t handle,
+ dissector_handle_t wrap_handle, gchar *comment);
+
+gssapi_oid_value *
+gssapi_lookup_oid(subid_t *oid, guint oid_len);
+
+int wrap_dissect_gssapi_verf(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ proto_tree *tree, guint8 *drep);
+
+#endif /* __PACKET_GSSAPI_H */
diff --git a/epan/dissectors/packet-gtp.c b/epan/dissectors/packet-gtp.c
new file mode 100644
index 0000000000..58fa038fd7
--- /dev/null
+++ b/epan/dissectors/packet-gtp.c
@@ -0,0 +1,4600 @@
+/* packet-gtp.c
+ *
+ * Routines for GTP dissection
+ * Copyright 2001, Michal Melerowicz <michal.melerowicz@nokia.com>
+ * Nicolas Balkota <balkota@mac.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include "packet-gtp.h"
+#include "packet-ipv6.h"
+#include "packet-ppp.h"
+
+static dissector_table_t ppp_subdissector_table;
+
+#define GTPv0_PORT 3386
+#define GTPv1C_PORT 2123 /* 3G Control PDU */
+#define GTPv1U_PORT 2152 /* 3G T-PDU */
+
+#define GTPv0_HDR_LENGTH 20
+#define GTPv1_HDR_LENGTH 12
+#define GTP_PRIME_HDR_LENGTH 6
+
+/* to check compliance with ETSI */
+#define GTP_MANDATORY 1
+#define GTP_OPTIONAL 2
+#define GTP_CONDITIONAL 4
+
+static int g_gtpv0_port = GTPv0_PORT;
+static int g_gtpv1c_port = GTPv1C_PORT;
+static int g_gtpv1u_port = GTPv1U_PORT;
+
+void proto_reg_handoff_gtp(void);
+
+static int proto_gtp = -1;
+
+static int hf_gtp_apn = -1;
+static int hf_gtp_cause = -1;
+static int hf_gtp_chrg_char = -1;
+static int hf_gtp_chrg_char_s = -1;
+static int hf_gtp_chrg_char_n = -1;
+static int hf_gtp_chrg_char_p = -1;
+static int hf_gtp_chrg_char_f = -1;
+static int hf_gtp_chrg_char_h = -1;
+static int hf_gtp_chrg_char_r = -1;
+static int hf_gtp_chrg_id = -1;
+static int hf_gtp_chrg_ipv4 = -1;
+static int hf_gtp_chrg_ipv6 = -1;
+static int hf_gtp_ext_flow_label = -1;
+static int hf_gtp_ext_id = -1;
+static int hf_gtp_ext_val = -1;
+static int hf_gtp_flags = -1;
+static int hf_gtp_flags_ver = -1;
+static int hf_gtp_flags_pt = -1;
+static int hf_gtp_flags_spare1 = -1;
+static int hf_gtp_flags_snn = -1;
+static int hf_gtp_flags_spare2 = -1;
+static int hf_gtp_flags_e = -1;
+static int hf_gtp_flags_s = -1;
+static int hf_gtp_flags_pn = -1;
+static int hf_gtp_flow_ii = -1;
+static int hf_gtp_flow_label = -1;
+static int hf_gtp_flow_sig = -1;
+static int hf_gtp_gsn_addr_len = -1;
+static int hf_gtp_gsn_addr_type = -1;
+static int hf_gtp_gsn_ipv4 = -1;
+static int hf_gtp_gsn_ipv6 = -1;
+static int hf_gtp_imsi = -1;
+static int hf_gtp_length = -1;
+static int hf_gtp_map_cause = -1;
+static int hf_gtp_message_type = -1;
+static int hf_gtp_ms_reason = -1;
+static int hf_gtp_ms_valid = -1;
+static int hf_gtp_msisdn = -1;
+static int hf_gtp_next = -1;
+static int hf_gtp_npdu_number = -1;
+static int hf_gtp_node_ipv4 = -1;
+static int hf_gtp_node_ipv6 = -1;
+static int hf_gtp_nsapi = -1;
+static int hf_gtp_ptmsi = -1;
+static int hf_gtp_ptmsi_sig = -1;
+static int hf_gtp_qos_spare1 = -1;
+static int hf_gtp_qos_delay = -1;
+static int hf_gtp_qos_mean = -1;
+static int hf_gtp_qos_peak = -1;
+static int hf_gtp_qos_spare2 = -1;
+static int hf_gtp_qos_precedence = -1;
+static int hf_gtp_qos_spare3 = -1;
+static int hf_gtp_qos_reliability = -1;
+static int hf_gtp_qos_al_ret_priority = -1;
+static int hf_gtp_qos_traf_class = -1;
+static int hf_gtp_qos_del_order = -1;
+static int hf_gtp_qos_del_err_sdu = -1;
+static int hf_gtp_qos_max_sdu_size = -1;
+static int hf_gtp_qos_max_ul = -1;
+static int hf_gtp_qos_max_dl = -1;
+static int hf_gtp_qos_res_ber = -1;
+static int hf_gtp_qos_sdu_err_ratio = -1;
+static int hf_gtp_qos_trans_delay = -1;
+static int hf_gtp_qos_traf_handl_prio = -1;
+static int hf_gtp_qos_guar_ul = -1;
+static int hf_gtp_qos_guar_dl = -1;
+static int hf_gtp_pkt_flow_id = -1;
+static int hf_gtp_rab_gtpu_dn = -1;
+static int hf_gtp_rab_gtpu_up = -1;
+static int hf_gtp_rab_pdu_dn = -1;
+static int hf_gtp_rab_pdu_up = -1;
+static int hf_gtp_rai_mcc = -1;
+static int hf_gtp_rai_mnc = -1;
+static int hf_gtp_rai_rac = -1;
+static int hf_gtp_rai_lac = -1;
+static int hf_gtp_ranap_cause = -1;
+static int hf_gtp_recovery = -1;
+static int hf_gtp_reorder = -1;
+static int hf_gtp_rnc_ipv4 = -1;
+static int hf_gtp_rnc_ipv6 = -1;
+static int hf_gtp_rp = -1;
+static int hf_gtp_rp_nsapi = -1;
+static int hf_gtp_rp_sms = -1;
+static int hf_gtp_rp_spare = -1;
+static int hf_gtp_sel_mode = -1;
+static int hf_gtp_seq_number = -1;
+static int hf_gtp_sndcp_number = -1;
+static int hf_gtp_tear_ind = -1;
+static int hf_gtp_teid = -1;
+static int hf_gtp_teid_cp = -1;
+static int hf_gtp_teid_data = -1;
+static int hf_gtp_teid_ii = -1;
+static int hf_gtp_tft_code = -1;
+static int hf_gtp_tft_spare = -1;
+static int hf_gtp_tft_number = -1;
+static int hf_gtp_tft_eval = -1;
+static int hf_gtp_tid = -1;
+static int hf_gtp_tlli = -1;
+static int hf_gtp_tr_comm = -1;
+static int hf_gtp_trace_ref = -1;
+static int hf_gtp_trace_type = -1;
+static int hf_gtp_unknown = -1;
+static int hf_gtp_user_addr_pdp_org = -1;
+static int hf_gtp_user_addr_pdp_type = -1;
+static int hf_gtp_user_ipv4 = -1;
+static int hf_gtp_user_ipv6 = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_gtp = -1;
+static gint ett_gtp_flags = -1;
+static gint ett_gtp_ext = -1;
+static gint ett_gtp_rai = -1;
+static gint ett_gtp_qos = -1;
+static gint ett_gtp_auth_tri = -1;
+static gint ett_gtp_flow_ii = -1;
+static gint ett_gtp_rab_cntxt = -1;
+static gint ett_gtp_rp = -1;
+static gint ett_gtp_pkt_flow_id = -1;
+static gint ett_gtp_chrg_char = -1;
+static gint ett_gtp_user = -1;
+static gint ett_gtp_mm = -1;
+static gint ett_gtp_trip = -1;
+static gint ett_gtp_quint = -1;
+static gint ett_gtp_pdp = -1;
+static gint ett_gtp_apn = -1;
+static gint ett_gtp_proto = -1;
+static gint ett_gtp_gsn_addr = -1;
+static gint ett_gtp_tft = -1;
+static gint ett_gtp_tft_pf = -1;
+static gint ett_gtp_tft_flags = -1;
+static gint ett_gtp_rab_setup = -1;
+static gint ett_gtp_hdr_list = -1;
+static gint ett_gtp_chrg_addr = -1;
+static gint ett_gtp_node_addr = -1;
+static gint ett_gtp_rel_pack = -1;
+static gint ett_gtp_can_pack = -1;
+static gint ett_gtp_data_resp = -1;
+static gint ett_gtp_priv_ext = -1;
+
+static gboolean gtp_tpdu = TRUE;
+static gboolean gtp_etsi_order = FALSE;
+static int gtpv0_port = 0;
+static int gtpv1c_port = 0;
+static int gtpv1u_port = 0;
+
+/* Definition of flags masks */
+#define GTP_VER_MASK 0xE0
+
+static const value_string ver_types[] = {
+ { 0, "GTP release 97/98 version" },
+ { 1, "GTP release 99 version" },
+ { 2, "None" },
+ { 3, "None" },
+ { 4, "None" },
+ { 5, "None" },
+ { 6, "None" },
+ { 7, "None" },
+ { 0, NULL }
+};
+
+#define GTP_PT_MASK 0x10
+#define GTP_SPARE1_MASK 0x0E
+#define GTP_SPARE2_MASK 0x08
+#define GTP_E_MASK 0x04
+#define GTP_S_MASK 0x02
+#define GTP_SNN_MASK 0x01
+#define GTP_PN_MASK 0x01
+
+/* Definition of 3G charging characteristics masks */
+#define GTP_MASK_CHRG_CHAR_S 0xF000
+#define GTP_MASK_CHRG_CHAR_N 0x0800
+#define GTP_MASK_CHRG_CHAR_P 0x0400
+#define GTP_MASK_CHRG_CHAR_F 0x0200
+#define GTP_MASK_CHRG_CHAR_H 0x0100
+#define GTP_MASK_CHRG_CHAR_R 0x00FF
+
+/* Traffic Flow Templates mask */
+#define GTPv1_TFT_CODE_MASK 0xE0
+#define GTPv1_TFT_SPARE_MASK 0x10
+#define GTPv1_TFT_NUMBER_MASK 0x0F
+
+/* Definition of GSN Address masks */
+#define GTP_EXT_GSN_ADDR_TYPE_MASK 0xC0
+#define GTP_EXT_GSN_ADDR_LEN_MASK 0x3F
+
+/* Definition of QoS masks */
+#define GTP_EXT_QOS_SPARE1_MASK 0xC0
+#define GTP_EXT_QOS_DELAY_MASK 0x38
+#define GTP_EXT_QOS_RELIABILITY_MASK 0x07
+#define GTP_EXT_QOS_PEAK_MASK 0xF0
+#define GTP_EXT_QOS_SPARE2_MASK 0x08
+#define GTP_EXT_QOS_PRECEDENCE_MASK 0x07
+#define GTP_EXT_QOS_SPARE3_MASK 0xE0
+#define GTP_EXT_QOS_MEAN_MASK 0x1F
+#define GTP_EXT_QOS_TRAF_CLASS_MASK 0xE0
+#define GTP_EXT_QOS_DEL_ORDER_MASK 0x18
+#define GTP_EXT_QOS_DEL_ERR_SDU_MASK 0x07
+#define GTP_EXT_QOS_RES_BER_MASK 0xF0
+#define GTP_EXT_QOS_SDU_ERR_RATIO_MASK 0x0F
+#define GTP_EXT_QOS_TRANS_DELAY_MASK 0xFC
+#define GTP_EXT_QOS_TRAF_HANDL_PRIORITY_MASK 0x03
+
+/* Definition of Radio Priority's masks */
+#define GTPv1_EXT_RP_NSAPI_MASK 0xF0
+#define GTPv1_EXT_RP_SPARE_MASK 0x08
+#define GTPv1_EXT_RP_MASK 0x07
+
+/* definitions of GTP messages */
+#define GTP_MSG_UNKNOWN 0x00
+#define GTP_MSG_ECHO_REQ 0x01
+#define GTP_MSG_ECHO_RESP 0x02
+#define GTP_MSG_VER_NOT_SUPP 0x03
+#define GTP_MSG_NODE_ALIVE_REQ 0x04
+#define GTP_MSG_NODE_ALIVE_RESP 0x05
+#define GTP_MSG_REDIR_REQ 0x06
+#define GTP_MSG_REDIR_RESP 0x07
+#define GTP_MSG_CREATE_PDP_REQ 0x10
+#define GTP_MSG_CREATE_PDP_RESP 0x11
+#define GTP_MSG_UPDATE_PDP_REQ 0x12
+#define GTP_MSG_UPDATE_PDP_RESP 0x13
+#define GTP_MSG_DELETE_PDP_REQ 0x14
+#define GTP_MSG_DELETE_PDP_RESP 0x15
+#define GTP_MSG_CREATE_AA_PDP_REQ 0x16 /* 2G */
+#define GTP_MSG_CREATE_AA_PDP_RESP 0x17 /* 2G */
+#define GTP_MSG_DELETE_AA_PDP_REQ 0x18 /* 2G */
+#define GTP_MSG_DELETE_AA_PDP_RESP 0x19 /* 2G */
+#define GTP_MSG_ERR_IND 0x1A
+#define GTP_MSG_PDU_NOTIFY_REQ 0x1B
+#define GTP_MSG_PDU_NOTIFY_RESP 0x1C
+#define GTP_MSG_PDU_NOTIFY_REJ_REQ 0x1D
+#define GTP_MSG_PDU_NOTIFY_REJ_RESP 0x1E
+#define GTP_MSG_SUPP_EXT_HDR 0x1F
+#define GTP_MSG_SEND_ROUT_INFO_REQ 0x20
+#define GTP_MSG_SEND_ROUT_INFO_RESP 0x21
+#define GTP_MSG_FAIL_REP_REQ 0x22
+#define GTP_MSG_FAIL_REP_RESP 0x23
+#define GTP_MSG_MS_PRESENT_REQ 0x24
+#define GTP_MSG_MS_PRESENT_RESP 0x25
+#define GTP_MSG_IDENT_REQ 0x30
+#define GTP_MSG_IDENT_RESP 0x31
+#define GTP_MSG_SGSN_CNTXT_REQ 0x32
+#define GTP_MSG_SGSN_CNTXT_RESP 0x33
+#define GTP_MSG_SGSN_CNTXT_ACK 0x34
+#define GTP_MSG_FORW_RELOC_REQ 0x35
+#define GTP_MSG_FORW_RELOC_RESP 0x36
+#define GTP_MSG_FORW_RELOC_COMP 0x37
+#define GTP_MSG_RELOC_CANCEL_REQ 0x38
+#define GTP_MSG_RELOC_CANCEL_RESP 0x39
+#define GTP_MSG_FORW_SRNS_CNTXT 0x3A
+#define GTP_MSG_FORW_RELOC_ACK 0x3B
+#define GTP_MSG_FORW_SRNS_CNTXT_ACK 0x3C
+#define GTP_MSG_DATA_TRANSF_REQ 0xF0
+#define GTP_MSG_DATA_TRANSF_RESP 0xF1
+#define GTP_MSG_TPDU 0xFF
+
+static const value_string message_type[] = {
+ { GTP_MSG_UNKNOWN, "For future use" },
+ { GTP_MSG_ECHO_REQ, "Echo request" },
+ { GTP_MSG_ECHO_RESP, "Echo response" },
+ { GTP_MSG_VER_NOT_SUPP, "Version not supported" },
+ { GTP_MSG_NODE_ALIVE_REQ, "Node alive request" },
+ { GTP_MSG_NODE_ALIVE_RESP, "Node alive response" },
+ { GTP_MSG_REDIR_REQ, "Redirection request" },
+ { GTP_MSG_REDIR_RESP, "Redirection response" },
+ { GTP_MSG_CREATE_PDP_REQ, "Create PDP context request" },
+ { GTP_MSG_CREATE_PDP_RESP, "Create PDP context response" },
+ { GTP_MSG_UPDATE_PDP_REQ, "Update PDP context request" },
+ { GTP_MSG_UPDATE_PDP_RESP, "Update PDP context response" },
+ { GTP_MSG_DELETE_PDP_REQ, "Delete PDP context request" },
+ { GTP_MSG_DELETE_PDP_RESP, "Delete PDP context response" },
+ { GTP_MSG_CREATE_AA_PDP_REQ, "Create AA PDP Context Request" },
+ { GTP_MSG_CREATE_AA_PDP_RESP, "Create AA PDP Context Response" },
+ { GTP_MSG_DELETE_AA_PDP_REQ, "Delete AA PDP Context Request" },
+ { GTP_MSG_DELETE_AA_PDP_RESP, "Delete AA PDP Context Response" },
+ { GTP_MSG_ERR_IND, "Error indication" },
+ { GTP_MSG_PDU_NOTIFY_REQ, "PDU notification request" },
+ { GTP_MSG_PDU_NOTIFY_RESP, "PDU notification response" },
+ { GTP_MSG_PDU_NOTIFY_REJ_REQ, "PDU notification reject request" },
+ { GTP_MSG_PDU_NOTIFY_REJ_RESP, "PDU notification reject response" },
+ { GTP_MSG_SUPP_EXT_HDR, "Supported extension header notification" },
+ { GTP_MSG_SEND_ROUT_INFO_REQ, "Send routing information for GPRS request" },
+ { GTP_MSG_SEND_ROUT_INFO_RESP, "Send routing information for GPRS response" },
+ { GTP_MSG_FAIL_REP_REQ, "Failure report request" },
+ { GTP_MSG_FAIL_REP_RESP, "Failure report response" },
+ { GTP_MSG_MS_PRESENT_REQ, "Note MS GPRS present request" },
+ { GTP_MSG_MS_PRESENT_RESP, "Note MS GPRS present response" },
+ { GTP_MSG_IDENT_REQ, "Identification request" },
+ { GTP_MSG_IDENT_RESP, "Identification response" },
+ { GTP_MSG_SGSN_CNTXT_REQ, "SGSN context request" },
+ { GTP_MSG_SGSN_CNTXT_RESP, "SGSN context response" },
+ { GTP_MSG_SGSN_CNTXT_ACK, "SGSN context acknowledgement" },
+ { GTP_MSG_FORW_RELOC_REQ, "Forward relocation request" },
+ { GTP_MSG_FORW_RELOC_RESP, "Forward relocation response" },
+ { GTP_MSG_FORW_RELOC_COMP, "Forward relocation complete" },
+ { GTP_MSG_RELOC_CANCEL_REQ, "Relocation cancel request" },
+ { GTP_MSG_RELOC_CANCEL_RESP, "Relocation cancel response" },
+ { GTP_MSG_FORW_SRNS_CNTXT, "Forward SRNS context" },
+ { GTP_MSG_FORW_RELOC_ACK, "Forward relocation complete acknowledge" },
+ { GTP_MSG_FORW_SRNS_CNTXT_ACK, "Forward SRNS context acknowledge" },
+ { GTP_MSG_DATA_TRANSF_REQ, "Data record transfer request" },
+ { GTP_MSG_DATA_TRANSF_RESP, "Data record transfer response" },
+ { GTP_MSG_TPDU, "T-PDU" },
+ { 0, NULL }
+};
+
+/* definitions of fields in extension header */
+#define GTP_EXT_CAUSE 0x01
+#define GTP_EXT_IMSI 0x02
+#define GTP_EXT_RAI 0x03
+#define GTP_EXT_TLLI 0x04
+#define GTP_EXT_PTMSI 0x05
+#define GTP_EXT_QOS_GPRS 0x06
+#define GTP_EXT_REORDER 0x08
+#define GTP_EXT_AUTH_TRI 0x09
+#define GTP_EXT_MAP_CAUSE 0x0B
+#define GTP_EXT_PTMSI_SIG 0x0C
+#define GTP_EXT_MS_VALID 0x0D
+#define GTP_EXT_RECOVER 0x0E
+#define GTP_EXT_SEL_MODE 0x0F
+
+#define GTP_EXT_16 0x10
+#define GTP_EXT_FLOW_LABEL 0x10
+#define GTP_EXT_TEID 0x10 /* 0xFF10 3G */
+
+#define GTP_EXT_17 0x11
+#define GTP_EXT_FLOW_SIG 0x11
+#define GTP_EXT_TEID_CP 0x11 /* 0xFF11 3G */
+
+#define GTP_EXT_18 0x12
+#define GTP_EXT_FLOW_II 0x12
+#define GTP_EXT_TEID_II 0x12 /* 0xFF12 3G*/
+
+#define GTP_EXT_19 0x13
+#define GTP_EXT_MS_REASON 0x13 /* same as 0x1D GTPv1_EXT_MS_REASON */
+#define GTP_EXT_TEAR_IND 0x13 /* 0xFF13 3G*/
+
+#define GTP_EXT_NSAPI 0x14 /* 3G */
+#define GTP_EXT_RANAP_CAUSE 0x15 /* 3G */
+#define GTP_EXT_RAB_CNTXT 0x16 /* 3G */
+#define GTP_EXT_RP_SMS 0x17 /* 3G */
+#define GTP_EXT_RP 0x18 /* 3G */
+#define GTP_EXT_PKT_FLOW_ID 0x19 /* 3G */
+#define GTP_EXT_CHRG_CHAR 0x1A /* 3G */
+#define GTP_EXT_TRACE_REF 0x1B /* 3G */
+#define GTP_EXT_TRACE_TYPE 0x1C /* 3G */
+#define GTPv1_EXT_MS_REASON 0x1D /* 3G */
+#define GTP_EXT_TR_COMM 0x7E /* charging */
+#define GTP_EXT_CHRG_ID 0x7F
+#define GTP_EXT_USER_ADDR 0x80
+#define GTP_EXT_MM_CNTXT 0x81
+#define GTP_EXT_PDP_CNTXT 0x82
+#define GTP_EXT_APN 0x83
+#define GTP_EXT_PROTO_CONF 0x84
+#define GTP_EXT_GSN_ADDR 0x85
+#define GTP_EXT_MSISDN 0x86
+#define GTP_EXT_QOS_UMTS 0x87 /* 3G */
+#define GTP_EXT_AUTH_QUI 0x88 /* 3G */
+#define GTP_EXT_TFT 0x89 /* 3G */
+#define GTP_EXT_TARGET_ID 0x8A /* 3G */
+#define GTP_EXT_UTRAN_CONT 0x8B /* 3G */
+#define GTP_EXT_RAB_SETUP 0x8C /* 3G */
+#define GTP_EXT_HDR_LIST 0x8D /* 3G */
+#define GTP_EXT_TRIGGER_ID 0x8E /* 3G */
+#define GTP_EXT_OMC_ID 0x8F /* 3G */
+#define GTP_EXT_C1 0xC1
+#define GTP_EXT_C2 0xC2
+#define GTP_EXT_REL_PACK 0xF9 /* charging */
+#define GTP_EXT_CAN_PACK 0xFA /* charging */
+#define GTP_EXT_CHRG_ADDR 0xFB
+#define GTP_EXT_DATA_REQ 0xFC /* charging */
+#define GTP_EXT_DATA_RESP 0xFD /* charging */
+#define GTP_EXT_NODE_ADDR 0xFE /* charging */
+#define GTP_EXT_PRIV_EXT 0xFF
+
+static const value_string gtp_val[] = {
+ { GTP_EXT_CAUSE, "Cause of operation" },
+ { GTP_EXT_IMSI, "IMSI" },
+ { GTP_EXT_RAI, "Routing Area Identity" },
+ { GTP_EXT_TLLI, "Temporary Logical Link Identity" },
+ { GTP_EXT_PTMSI, "Packet TMSI" },
+ { GTP_EXT_QOS_GPRS, "Quality of Service" },
+ { GTP_EXT_REORDER, "Reorder required" },
+ { GTP_EXT_AUTH_TRI, "Authentication triplets" },
+ { GTP_EXT_MAP_CAUSE, "MAP cause" },
+ { GTP_EXT_PTMSI_SIG, "P-TMSI signature" },
+ { GTP_EXT_MS_VALID, "MS validated" },
+ { GTP_EXT_RECOVER, "Recovery" },
+ { GTP_EXT_SEL_MODE, "Selection mode" },
+
+ { GTP_EXT_16, "Flow label data I" },
+ { GTP_EXT_FLOW_LABEL, "Flow label data I" },
+ { GTP_EXT_TEID, "Tunnel Endpoint Identifier Data I" }, /* 3G */
+
+ { GTP_EXT_17, "Flow label signalling" },
+ { GTP_EXT_FLOW_SIG, "Flow label signalling" },
+ { GTP_EXT_TEID_CP, "Tunnel Endpoint Identifier Data Control Plane" }, /* 3G */
+
+ { GTP_EXT_18, "Flow label data II" },
+ { GTP_EXT_FLOW_II, "Flow label data II" },
+ { GTP_EXT_TEID_II, "Tunnel Endpoint Identifier Data II" }, /* 3G */
+
+ { GTP_EXT_19, "MS not reachable reason" },
+ { GTP_EXT_MS_REASON, "MS not reachable reason" },
+ { GTP_EXT_TEAR_IND, "Teardown ID" }, /* 3G */
+
+ { GTP_EXT_NSAPI, "NSAPI" }, /* 3G */
+ { GTP_EXT_RANAP_CAUSE, "RANAP cause" }, /* 3G */
+ { GTP_EXT_RAB_CNTXT, "RAB context" }, /* 3G */
+ { GTP_EXT_RP_SMS, "Radio Priority for MO SMS" }, /* 3G */
+ { GTP_EXT_RP, "Radio Priority" }, /* 3G */
+ { GTP_EXT_PKT_FLOW_ID, "Packet Flow ID" }, /* 3G */
+ { GTP_EXT_CHRG_CHAR, "Charging characteristics" }, /* 3G */
+ { GTP_EXT_TRACE_REF, "Trace references" }, /* 3G */
+ { GTP_EXT_TRACE_TYPE, "Trace type" }, /* 3G */
+ { GTPv1_EXT_MS_REASON, "MS not reachable reason" }, /* 3G */
+ { GTP_EXT_TR_COMM, "Packet transfer command" }, /* charging */
+ { GTP_EXT_CHRG_ID, "Charging ID" },
+ { GTP_EXT_USER_ADDR, "End user address" },
+ { GTP_EXT_MM_CNTXT, "MM context" },
+ { GTP_EXT_PDP_CNTXT, "PDP context" },
+ { GTP_EXT_APN, "Access Point Name" },
+ { GTP_EXT_PROTO_CONF, "Protocol configuration options" },
+ { GTP_EXT_GSN_ADDR, "GSN address" },
+ { GTP_EXT_MSISDN, "MS international PSTN/ISDN number" },
+ { GTP_EXT_QOS_UMTS, "Quality of service (UMTS)" }, /* 3G */
+ { GTP_EXT_AUTH_QUI, "Authentication quintuplets" }, /* 3G */
+ { GTP_EXT_TFT, "Traffic Flow Template (TFT)" }, /* 3G */
+ { GTP_EXT_TARGET_ID, "Target (RNC) identification" }, /* 3G */
+ { GTP_EXT_UTRAN_CONT, "UTRAN transparent field" }, /* 3G */
+ { GTP_EXT_RAB_SETUP, "RAB setup information" }, /* 3G */
+ { GTP_EXT_HDR_LIST, "Extension Header Types List" }, /* 3G */
+ { GTP_EXT_TRIGGER_ID, "Trigger Id" }, /* 3G */
+ { GTP_EXT_OMC_ID, "OMC Identity" }, /* 3G */
+ { GTP_EXT_REL_PACK, "Sequence numbers of released packets IE" }, /* charging */
+ { GTP_EXT_CAN_PACK, "Sequence numbers of canceled packets IE" }, /* charging */
+ { GTP_EXT_CHRG_ADDR, "Charging Gateway address" },
+ { GTP_EXT_DATA_REQ, "Data record packet" }, /* charging */
+ { GTP_EXT_DATA_RESP, "Requests responded" }, /* charging */
+ { GTP_EXT_NODE_ADDR, "Address of recommended node" }, /* charging */
+ { GTP_EXT_PRIV_EXT, "Private Extension" },
+ { 0, NULL }
+};
+
+/* GPRS: 9.60 v7.6.0, page 37
+ * UMTS: 29.060 v4.0, page 45
+ */
+static const value_string cause_type[] = {
+ { 0, "Request IMSI" },
+ { 1, "Request IMEI" },
+ { 2, "Request IMSI and IMEI" },
+ { 3, "No identity needed" },
+ { 4, "MS refuses" },
+ { 5, "MS is not GPRS responding" },
+ { 59, "System failure" }, /* charging */
+ { 60, "The transmit buffers are becoming full" }, /* charging */
+ { 61, "The receive buffers are becoming full" }, /* charging */
+ { 62, "Another node is about to go down" }, /* charging */
+ { 63, "This node is about to go down" }, /* charging */
+ { 128, "Request accepted" },
+ { 192, "Non-existent" },
+ { 193, "Invalid message format" },
+ { 194, "IMSI not known" },
+ { 195, "MS is GPRS detached" },
+ { 196, "MS is not GPRS responding" },
+ { 197, "MS refuses" },
+ { 198, "Version not supported" },
+ { 199, "No resource available" },
+ { 200, "Service not supported" },
+ { 201, "Mandatory IE incorrect" },
+ { 202, "Mandatory IE missing" },
+ { 203, "Optional IE incorrect" },
+ { 204, "System failure" },
+ { 205, "Roaming restriction" },
+ { 206, "P-TMSI signature mismatch" },
+ { 207, "GPRS connection suspended" },
+ { 208, "Authentication failure" },
+ { 209, "User authentication failed" },
+ { 210, "Context not found" },
+ { 211, "All PDP dynamic addresses are occupied" },
+ { 212, "No memory is available" },
+ { 213, "Relocation failure" },
+ { 214, "Unknown mandatory extension header" },
+ { 215, "Semantic error in the TFT operation" },
+ { 216, "Syntactic error in the TFT operation" },
+ { 217, "Semantic errors in packet filter(s)" },
+ { 218, "Syntactic errors in packet filter(s)" },
+ { 219, "Missing or unknown APN" },
+ { 220, "Unknown PDP address or PDP type" },
+ { 252, "Request related to possibly duplicated packets already fulfilled" }, /* charging */
+ { 253, "Request already fulfilled" }, /* charging */
+ { 254, "Sequence numbers of released/cancelled packets IE incorrect" }, /* charging */
+ { 255, "Request not fulfilled" }, /* charging */
+ { 0, NULL }
+};
+
+/* GPRS: 9.02 v7.7.0
+ * UMTS: 29.002 v4.2.1, chapter 17.5, page 268
+ * TODO: Check if all map_cause values are included
+ */
+static const value_string map_cause_type[] = {
+ { 1, "Unknown subscriber" },
+ { 8, "Roaming not allowed" },
+ { 10, "Bearer service not provisioned" },
+ { 11, "Teleservice not provisioned" },
+ { 13, "Call barred" },
+ { 21, "Facility not supported" },
+ { 23, "Update GPRS location" },
+ { 24, "Send routing info for GPRS" },
+ { 26, "Note MS present for GPRS" },
+ { 27, "Absent subscriber" },
+ { 34, "System failure" },
+ { 35, "Data missing" },
+ { 36, "Unexpected data value" },
+ { 44, "Number chenged" },
+ { 45, "Busy subscriber" },
+ { 46, "No subscriber reply" },
+ { 48, "Facility not allowed" },
+ { 0, NULL }
+};
+
+static const value_string gsn_addr_type[] = {
+ { 0x00, "IPv4" },
+ { 0x01, "IPv6" },
+ { 0, NULL },
+};
+
+static const value_string pdp_type[] = {
+ { 0x00, "X.25" },
+ { 0x01, "PPP" },
+ { 0x02, "OSP:IHOSS" },
+ { 0x21, "IPv4" },
+ { 0x57, "IPv6" },
+ { 0, NULL }
+};
+
+static const value_string pdp_org_type[] = {
+ { 0, "ETSI" },
+ { 1, "IETF" },
+ { 0, NULL }
+};
+
+static const value_string qos_delay_type[] = {
+ { 0x00, "Subsribed delay class (in MS to network direction)" },
+ { 0x01, "Delay class 1" },
+ { 0x02, "Delay class 2" },
+ { 0x03, "Delay class 3" },
+ { 0x04, "Delay class 4 (best effort)" },
+ { 0x07, "Reserved" },
+ { 0, NULL }
+};
+
+static const value_string qos_reliability_type[] = {
+ { 0x00, "Subscribed reliability class (in MS to network direction)" },
+ { 0x01, "Ack GTP/LLC/RLC, Protected data" },
+ { 0x02, "Unack GTP, Ack LLC/RLC, Protected data" },
+ { 0x03, "Unack GTP/LLC, Ack RLC, Protected data" },
+ { 0x04, "Unack GTP/LLC/RLC, Protected data" },
+ { 0x05, "Unack GTP/LLC/RLC, Unprotected data" },
+ { 0x07, "Reserved" },
+ { 0, NULL }
+};
+
+static const value_string qos_peak_type[] = {
+ { 0x00, "Subscribed peak throughput (in MS to network direction)" },
+ { 0x01, "Up to 1 000 oct/s" },
+ { 0x02, "Up to 2 000 oct/s" },
+ { 0x03, "Up to 4 000 oct/s" },
+ { 0x04, "Up to 8 000 oct/s" },
+ { 0x05, "Up to 16 000 oct/s" },
+ { 0x06, "Up to 32 000 oct/s" },
+ { 0x07, "Up to 64 000 oct/s" },
+ { 0x08, "Up to 128 000 oct/s" },
+ { 0x09, "Up to 256 000 oct/s" },
+/* QoS Peak throughput classes from 0x0A to 0x0F (from 10 to 15) are subscribed */
+ { 0x0A, "Reserved" },
+ { 0x0B, "Reserved" },
+ { 0x0C, "Reserved" },
+ { 0x0D, "Reserved" },
+ { 0x0E, "Reserved" },
+ { 0x0F, "Reserved" },
+ { 0, NULL }
+};
+
+static const value_string qos_precedence_type[] = {
+ { 0x00, "Subscribed precedence (in MS to network direction)" },
+ { 0x01, "High priority" },
+ { 0x02, "Normal priority" },
+ { 0x03, "Low priority" },
+ { 0x07, "Reserved" },
+ { 0, NULL }
+};
+
+static const value_string qos_mean_type[] = {
+ { 0x00, "Subscribed mean throughput (in MS to network direction)" },
+ { 0x01, "100 oct/h" }, /* Class 2 */
+ { 0x02, "200 oct/h" }, /* Class 3 */
+ { 0x03, "500 oct/h" }, /* Class 4 */
+ { 0x04, "1 000 oct/h" }, /* Class 5 */
+ { 0x05, "2 000 oct/h" }, /* Class 6 */
+ { 0x06, "5 000 oct/h" }, /* Class 7 */
+ { 0x07, "10 000 oct/h" }, /* Class 8 */
+ { 0x08, "20 000 oct/h" }, /* Class 9 */
+ { 0x09, "50 000 oct/h" }, /* Class 10 */
+ { 0x0A, "100 000 oct/h" }, /* Class 11 */
+ { 0x0B, "200 000 oct/h" }, /* Class 12 */
+ { 0x0C, "500 000 oct/h" }, /* Class 13 */
+ { 0x0D, "1 000 000 oct/h" }, /* Class 14 */
+ { 0x0E, "2 000 000 oct/h" }, /* Class 15 */
+ { 0x0F, "5 000 000 oct/h" }, /* Class 16 */
+ { 0x10, "10 000 000 oct/h" }, /* Class 17 */
+ { 0x11, "20 000 000 oct/h" }, /* Class 18 */
+ { 0x12, "50 000 000 oct/h" }, /* Class 19 */
+/* QoS Mean throughput classes from 0x13 to 0x1E (from 19 to 30) are subscribed */
+ { 0x13, "Reserved" },
+ { 0x14, "Reserved" },
+ { 0x15, "Reserved" },
+ { 0x16, "Reserved" },
+ { 0x17, "Reserved" },
+ { 0x18, "Reserved" },
+ { 0x19, "Reserved" },
+ { 0x1A, "Reserved" },
+ { 0x1B, "Reserved" },
+ { 0x1C, "Reserved" },
+ { 0x1D, "Reserved" },
+ { 0x1E, "Reserved" },
+ { 0x1F, "Best effort" }, /* Class 1 */
+ { 0, NULL }
+};
+
+static const value_string qos_del_err_sdu[] = {
+ { 0x00, "Subscribed delivery of erroneous SDUs (in MS to network direction)" },
+ { 0x01, "No detect ('-')" },
+ { 0x02, "Erroneous SDUs are delivered ('yes')" },
+ { 0x03, "Erroneous SDUs are not delivered ('no')" },
+ { 0x07, "Reserved" }, /* All other values are reserved */
+ { 0, NULL }
+};
+
+static const value_string qos_del_order[] = {
+ { 0x00, "Subscribed delivery order (in MS to network direction)" },
+ { 0x01, "With delivery order ('yes')" },
+ { 0x02, "Without delivery order ('no')" },
+ { 0x03, "Reserved" }, /* All other values are reserved */
+ { 0, NULL }
+};
+
+static const value_string qos_traf_class[] = {
+ { 0x00, "Subscribed traffic class (in MS to network direction)" },
+ { 0x01, "Conversational class" },
+ { 0x02, "Streaming class" },
+ { 0x03, "Interactive class" },
+ { 0x04, "Background class" },
+ { 0x07, "Reserved" }, /* All other values are reserved */
+ { 0, NULL }
+};
+
+static const value_string qos_max_sdu_size[] = {
+ { 0x00, "Subscribed maximum SDU size (in MS to network direction" },
+ /* For values from 0x01 to 0x96 (from 1 to 150), use a granularity of 10 octets */
+ { 0x97, "1502 octets" },
+ { 0x98, "1510 octets" },
+ { 0x99, "1520 octets" },
+ { 0, NULL } /* All other values are reserved */
+};
+
+static const value_string qos_max_ul[] = {
+ { 0x00, "Subscribed maximum bit rate for uplink (in MS to network direction)" },
+ /* For values from 0x01 to 0x3F (from 1 to 63), use a granularity of 1 kbps */
+ /* For values from 0x40 to 0x7F, value = 64 kbps + (value - 0x40) * 8 kbps */
+ /* For values from 0x80 to 0xFE, value = 576 kbps + (value - 0x80) * 64 kbps */
+ { 0xFF, "0 kbps" },
+ { 0, NULL }
+};
+
+static const value_string qos_max_dl[] = {
+ { 0x00, "Subscribed maximum bit rate for downlink (in MS to network direction)" },
+ /* For values from 0x01 to 0x3F (from 1 to 63), use a granularity of 1 kbps */
+ /* For values from 0x40 to 0x7F, value = 64 kbps + (value - 0x40) * 8 kbps */
+ /* For values from 0x80 to 0xFE, value = 576 kbps + (value - 0x80) * 64 kbps */
+ { 0xFF, "0 kbps" },
+ { 0, NULL }
+};
+
+static const value_string qos_res_ber[] = {
+ { 0x00, "Subscribed residual BER (in MS to network direction)" },
+ { 0x01, "1/20 = 5x10^-2" },
+ { 0x02, "1/100 = 1x10^-2" },
+ { 0x03, "1/200 = 5x10^-3" },
+ { 0x04, "1/250 = 4x10^-3" },
+ { 0x05, "1/1 000 = 1x10^-3" },
+ { 0x06, "1/10 000 = 1x10^-4" },
+ { 0x07, "1/100 000 = 1x10^-5" },
+ { 0x08, "1/1 000 000 = 1x10^-6" },
+ { 0x09, "3/50 000 000 = 6x10^-8" },
+ { 0x0F, "Reserved" }, /* All other values are reserved */
+ { 0, NULL }
+};
+
+static const value_string qos_sdu_err_ratio[] = {
+ { 0x00, "Subscribed SDU error ratio (in MS to network direction)" },
+ { 0x01, "1/100 = 1x10^-2" },
+ { 0x02, "7/1000 = 7x10^-3" },
+ { 0x03, "1/1 000 = 1x10^-3" },
+ { 0x04, "1/10 000 = 1x10^-4" },
+ { 0x05, "1/100 000 = 1x10^-5" },
+ { 0x06, "1/1 000 000 = 1x10^-6" },
+ { 0x07, "1/10 = 1x10^-1" },
+ { 0x0F, "Reserved" }, /* All other values are reserved */
+ { 0, NULL }
+};
+
+static const value_string qos_traf_handl_prio[] = {
+ { 0x00, "Subscribed traffic handling priority (in MS to network direction)" },
+ { 0x01, "Priority level 1" },
+ { 0x02, "Priority level 2" },
+ { 0x03, "Priority level 3" },
+ { 0, NULL }
+};
+
+static const value_string qos_trans_delay[] = {
+ { 0x00, "Subscribed Transfer Delay (in MS to network direction)" },
+ { 0x01, "10 ms" }, /* Using a granularity of 10 ms */
+ { 0x02, "20 ms" },
+ { 0x03, "30 ms" },
+ { 0x04, "40 ms" },
+ { 0x05, "50 ms" },
+ { 0x06, "60 ms" },
+ { 0x07, "70 ms" },
+ { 0x08, "80 ms" },
+ { 0x09, "90 ms" },
+ { 0x0A, "100 ms" },
+ { 0x0B, "110 ms" },
+ { 0x0C, "120 ms" },
+ { 0x0D, "130 ms" },
+ { 0x0E, "140 ms" },
+ { 0x0F, "150 ms" },
+ { 0x10, "200 ms" }, /* (For values from 0x10 to 0x1F, value = 200 ms + (value - 0x10) * 50 ms */
+ { 0x11, "250 ms" },
+ { 0x12, "300 ms" },
+ { 0x13, "350 ms" },
+ { 0x14, "400 ms" },
+ { 0x15, "450 ms" },
+ { 0x16, "500 ms" },
+ { 0x17, "550 ms" },
+ { 0x18, "600 ms" },
+ { 0x19, "650 ms" },
+ { 0x1A, "700 ms" },
+ { 0x1B, "750 ms" },
+ { 0x1C, "800 ms" },
+ { 0x1D, "850 ms" },
+ { 0x1E, "900 ms" },
+ { 0x1F, "950 ms" },
+ { 0x20, "1000 ms" }, /* For values from 0x20 to 0x3E, value = 1000 ms + (value - 0x20) * 100 ms */
+ { 0x21, "1100 ms" },
+ { 0x22, "1200 ms" },
+ { 0x23, "1300 ms" },
+ { 0x24, "1400 ms" },
+ { 0x25, "1500 ms" },
+ { 0x26, "1600 ms" },
+ { 0x27, "1700 ms" },
+ { 0x28, "1800 ms" },
+ { 0x29, "1900 ms" },
+ { 0x2A, "2000 ms" },
+ { 0x2B, "2100 ms" },
+ { 0x2C, "2200 ms" },
+ { 0x2D, "2300 ms" },
+ { 0x2E, "2400 ms" },
+ { 0x2F, "2500 ms" },
+ { 0x30, "2600 ms" },
+ { 0x31, "2700 ms" },
+ { 0x32, "2800 ms" },
+ { 0x33, "2900 ms" },
+ { 0x34, "3000 ms" },
+ { 0x35, "3100 ms" },
+ { 0x36, "3200 ms" },
+ { 0x37, "3300 ms" },
+ { 0x38, "3400 ms" },
+ { 0x39, "3500 ms" },
+ { 0x3A, "3600 ms" },
+ { 0x3B, "3700 ms" },
+ { 0x3C, "3800 ms" },
+ { 0x3D, "3900 ms" },
+ { 0x3E, "4000 ms" },
+ { 0x3F, "Reserved"},
+ { 0, NULL }
+};
+
+static const value_string qos_guar_ul[] = {
+ { 0x00, "Subscribed guaranteed bit rate for uplink (in MS to network direction)" },
+ /* For values from 0x01 to 0x3F (from 1 to 63), use a granularity of 1 kbps */
+ /* For values from 0x40 to 0x7F, value = 64 kbps + (value - 0x40) * 8 kbps */
+ /* For values from 0x80 to 0xFE, value = 576 kbps + (value - 0x80) * 64 kbps */
+ { 0xFF, "0 kbps" },
+ { 0, NULL }
+};
+
+static const value_string qos_guar_dl[] = {
+ { 0x00, "Subscribed guaranteed bit rate for downlink (in MS to network direction)" },
+ /* For values from 0x01 to 0x3F (from 1 to 63), use a granularity of 1 kbps */
+ /* For values from 0x40 to 0x7F, value = 64 kbps + (value - 0x40) * 8 kbps */
+ /* For values from 0x80 to 0xFE, value = 576 kbps + (value - 0x80) * 64 kbps */
+ { 0xFF, "0 kbps" },
+ { 0, NULL }
+};
+
+static const value_string sel_mode_type[] = {
+ { 0, "MS or network provided APN, subscribed verified" },
+ { 1, "MS provided APN, subscription not verified" },
+ { 2, "Network provided APN, subscription not verified" },
+ { 3, "For future use (Network provided APN, subscription not verified" },/* Shall not be sent. If received, shall be sent as value 2 */
+ { 0, NULL }
+};
+
+static const value_string tr_comm_type[] = {
+ { 1, "Send data record packet" },
+ { 2, "Send possibly duplicated data record packet" },
+ { 3, "Cancel data record packet" },
+ { 4, "Release data record packet"},
+ { 0, NULL }
+};
+
+/* TODO: CHeck if all ms_reasons are included */
+static const value_string ms_not_reachable_type[] = {
+ { 0, "No paging response via the MSC" },
+ { 1, "IMSI detached" },
+ { 2, "Roaming restriction" },
+ { 3, "Deregistered in the HLR for non GPRS" },
+ { 4, "MS purge for non GPRS" },
+ { 5, "No paging response via the SGSN" },
+ { 6, "GPRS detached" },
+ { 7, "Deregistered in the HLR for non GPRS" },
+ { 8, "MS purged for GPRS" },
+ { 9, "Unidentified subscriber via the MSC" },
+ { 10, "Unidentified subscriber via the SGSN" },
+ { 0, NULL }
+};
+
+/* UMTS: 25.413 v3.4.0, chapter 9.2.1.4, page 80
+ */
+static const value_string ranap_cause_type[] = {
+/* Radio Network Layer Cause (1-->64) */
+ { 1, "RAB preempted" },
+ { 2, "Trelocoverall Expiry" },
+ { 3, "Trelocprep Expiry" },
+ { 4, "Treloccomplete Expiry" },
+ { 5, "Tqueing Expiry" },
+ { 6, "Relocation Triggered" },
+ { 7, "TRELOCalloc Expiry" },
+ { 8, "Unable to Estabish During Relocation" },
+ { 9, "Unknown Target RNC" },
+ { 10, "Relocation Cancelled" },
+ { 11, "Successful Relocation" },
+ { 12, "Requested Ciphering and/or Integrity Protection Algorithms not Supported" },
+ { 13, "Change of Ciphering and/or Integrity Protection is not supported" },
+ { 14, "Failure in the Radio Interface Procedure" },
+ { 15, "Release due to UTRAN Generated Reason" },
+ { 16, "User Inactivity" },
+ { 17, "Time Critical Relocation" },
+ { 18, "Requested Traffic Class not Available" },
+ { 19, "Invalid RAB Parameters Value" },
+ { 20, "Requested Maximum Bit Rate not Available" },
+ { 21, "Requested Guaranteed Bit Rate not Available" },
+ { 22, "Requested Transfer Delay not Achievable" },
+ { 23, "Invalid RAB Parameters Combination" },
+ { 24, "Condition Violation for SDU Parameters" },
+ { 25, "Condition Violation for Traffic Handling Priority" },
+ { 26, "Condition Violation for Guaranteed Bit Rate" },
+ { 27, "User Plane Versions not Supported" },
+ { 28, "Iu UP Failure" },
+ { 29, "Relocation Failure in Target CN/RNC or Target System" },
+ { 30, "Invalid RAB ID" },
+ { 31, "No Remaining RAB" },
+ { 32, "Interaction with other procedure" },
+ { 33, "Requested Maximum Bit Rate for DL not Available" },
+ { 34, "Requested Maximum Bit Rate for UL not Available" },
+ { 35, "Requested Guaranteed Bit Rate for DL not Available" },
+ { 36, "Requested Guaranteed Bit Rate for UL not Available" },
+ { 37, "Repeated Integrity Checking Failure" },
+ { 38, "Requested Report Type not supported" },
+ { 39, "Request superseded" },
+ { 40, "Release due to UE generated signalling connection release" },
+ { 41, "Resource Optimisation Relocation" },
+ { 42, "Requested Information Not Available" },
+ { 43, "Relocation desirable for radio reasons" },
+ { 44, "Relocation not supported in Target RNC or Target System" },
+ { 45, "Directed Retry" },
+ { 46, "Radio Connection With UE Lost" },
+/* Transport Layer Cause (65-->80) */
+ { 65, "Signalling Transport Resource Failure" },
+ { 66, "Iu Transport Connection Failed to Establish" },
+/* NAS Cause (81-->96) */
+ { 81, "User Restriction Start Indication" },
+ { 82, "User Restriction End Indication" },
+ { 83, "Normal Release" },
+/* Protocol Cause (97-->112) */
+ { 97, "Transfer Syntax Error" },
+ { 98, "Semantic Error" },
+ { 99, "Message not compatible with receiver state" },
+ { 100, "Abstract Syntax Error (Reject)" },
+ { 101, "Abstract Syntax Error (Ignore and Notify)" },
+ { 102, "Abstract Syntax Error (Falsely Constructed Message" },
+/* Miscellaneous Cause (113-->128) */
+ { 113, "O & M Intervention" },
+ { 114, "No Resource Available" },
+ { 115, "Unspecified Failure" },
+ { 116, "Network Opimisation" },
+/* Non-standard Cause (129-->255) */
+ { 0, NULL }
+};
+
+static const value_string mm_sec_modep[] = {
+ { 0, "Used cipher value, UMTS keys and Quintuplets" },
+ { 1, "GSM key and triplets" },
+ { 2, "UMTS key and quintuplets" },
+ { 3, "GSM key and quintuplets" },
+ { 0, NULL }
+};
+
+#define MM_PROTO_GROUP_CALL_CONTROL 0x00
+#define MM_PROTO_BROADCAST_CALL_CONTROL 0x01
+#define MM_PROTO_PDSS1 0x02
+#define MM_PROTO_CALL_CONTROL 0x03
+#define MM_PROTO_PDSS2 0x04
+#define MM_PROTO_MM_NON_GPRS 0x05
+#define MM_PROTO_RR_MGMT 0x06
+#define MM_PROTO_MM_GPRS 0x08
+#define MM_PROTO_SMS 0x09
+#define MM_PROTO_SESSION_MGMT 0x0A
+#define MM_PROTO_NON_CALL_RELATED 0x0B
+
+static const value_string mm_proto_disc[] = {
+ { MM_PROTO_GROUP_CALL_CONTROL, "Group call control" },
+ { MM_PROTO_BROADCAST_CALL_CONTROL, "Broadcast call control" },
+ { MM_PROTO_PDSS1, "PDSS1" },
+ { MM_PROTO_CALL_CONTROL, "Call control; call related SS messages" },
+ { MM_PROTO_PDSS2, "PDSS2" },
+ { MM_PROTO_MM_NON_GPRS, "Mobility Management messages for non-GPRS services" },
+ { MM_PROTO_RR_MGMT, "Radio Resource management messages" },
+ { MM_PROTO_MM_GPRS, "Mobility Management messages for GPRS services" },
+ { MM_PROTO_SMS, "SMS" },
+ { MM_PROTO_SESSION_MGMT, "Session Management messages" },
+ { MM_PROTO_NON_CALL_RELATED, "Non-call related SS messages" },
+ { 0, NULL }
+};
+
+static const value_string mm_rr_mess[] = {
+ { 0x3C, "RR initialization request" },
+ { 0x3B, "Additional assignment" },
+ { 0x3F, "Immediate assignment" },
+ { 0x39, "Immediate assignment extended" },
+ { 0x3A, "Immediate assignment reject" },
+
+ { 0x35, "Ciphering mode command" },
+ { 0x32, "Ciphering mode complete" },
+
+ { 0x30, "Configuration change command" },
+ { 0x31, "Configuration change ack" },
+ { 0x33, "Configuration change reject" },
+
+ { 0x2E, "Assignment command" },
+ { 0x29, "Assignment complete" },
+ { 0x2F, "Assigment failure" },
+ { 0x2B, "Handover command" },
+ { 0x2C, "Handover complete" },
+ { 0x28, "Handover failure" },
+ { 0x2D, "Physical information" },
+
+ { 0x08, "RR-cell change order" },
+ { 0x23, "PDCH assignment command" },
+
+ { 0x0D, "Channel release" },
+ { 0x0A, "Partial release" },
+ { 0x0F, "PArtial release complete" },
+
+ { 0x21, "Paging request type 1" },
+ { 0x22, "Paging request type 2" },
+ { 0x24, "Paging request type 3" },
+ { 0x27, "Paging response" },
+ { 0x20, "Notification/NCH" },
+ { 0x25, "Notification/FACCH" },
+ { 0x26, "Reserved" },
+ { 0x0B, "Reserved" },
+
+ { 0x18, "System information type 8" },
+ { 0x19, "System information type 1" },
+ { 0x1A, "System information type 2" },
+ { 0x1B, "System information type 3" },
+ { 0x1C, "System information type 4" },
+ { 0x1D, "System information type 5" },
+ { 0x1E, "System information type 6" },
+ { 0x1F, "System information type 7" },
+
+ { 0x02, "System information type 2bis" },
+ { 0x03, "System information type 2ter" },
+ { 0x05, "System information type 5bis" },
+ { 0x06, "System information type 5ter" },
+ { 0x04, "System information 9" },
+ { 0x00, "System information 13" },
+ { 0x01, "System information 14" },
+
+ { 0x3D, "System information type 16" },
+ { 0x3E, "System information type 17" },
+
+ { 0x10, "Channel mode modify" },
+ { 0x12, "RR status" },
+ { 0x17, "Channel mode modify ack" },
+ { 0x14, "Frequency redefinition" },
+ { 0x15, "Measurement report" },
+ { 0x16, "Classmark change" },
+ { 0x13, "Classmark enquiry" },
+ { 0x36, "Extended measurement report" },
+ { 0x37, "Extended measurement order" },
+ { 0x34, "GPRS suspension request" },
+
+ { 0x09, "VGCS uplink grant" },
+ { 0x0E, "Uplink release" },
+ { 0x0C, "Uplink free" },
+ { 0x2A, "Uplink busy" },
+ { 0x11, "Talker indication" },
+
+ { 0, NULL }
+};
+
+static const value_string mm_mm_mess[] = {
+ { 0x01, "IMSI DETACH INDICATION" },
+ { 0x02, "LOCATION UPDATING ACCEPT" },
+ { 0x04, "LOCATION UPDATING REJECT" },
+ { 0x08, "LOCATION UPDATING REQUEST" },
+ { 0x11, "AUTHENTICATION REJECT" },
+ { 0x12, "AUTHENTICATION REQUEST" },
+ { 0x14, "AUTHENTICATION RESPONSE" },
+ { 0x18, "IDENTITY REQUEST" },
+ { 0x19, "IDENTITY RESPONSE" },
+ { 0x1A, "TMSI REALLOCATION COMMAND" },
+ { 0x1B, "TMSI REALLOCATION COMPLETE" },
+ { 0x21, "CM SERVICE ACCEPT" },
+ { 0x22, "CM SERVICE REJECT" },
+ { 0x23, "CM SERVICE ABORT" },
+ { 0x24, "CM SERVICE REQUEST" },
+ { 0x25, "CM SERVICE PROMPT" },
+ { 0x26, "NOTIFICATION RESPONSE" },
+ { 0x28, "CM RE-ESTABLISHMENT REQUEST" },
+ { 0x29, "ABORT" },
+ { 0x30, "MM NULL" },
+ { 0x31, "MM STATUS" },
+ { 0x32, "MM INFORMATION" },
+ { 0, NULL }
+};
+
+static const value_string mm_cc_mess[] = {
+ { 0x00, "escape to nationally specific" },
+/*{ 0 x 0 0, "- - - Call establishment messages:" },*/
+ { 0x01, "ALERTING" },
+ { 0x08, "CALL CONFIRMED" },
+ { 0x02, "CALL PROCEEDING" },
+ { 0x07, "CONNECT" },
+ { 0x0F, "CONNECT ACKNOWLEDGE" },
+ { 0x0E, "EMERGENCY SETUP" },
+ { 0x03, "PROGRESS" },
+ { 0x04, "CC-ESTABLISHMENT" },
+ { 0x06, "CC-ESTABLISHMENT CONFIRMED" },
+ { 0x0B, "RECALL" },
+ { 0x09, "START CC" },
+ { 0x05, "SETUP" },
+/*{ 0 x 0 1, "- - - Call information phase messages:" },*/
+ { 0x17, "MODIFY" },
+ { 0x1F, "MODIFY COMPLETE" },
+ { 0x13, "MODIFY REJECT" },
+ { 0x10, "USER INFORMATION" },
+ { 0x18, "HOLD" },
+ { 0x19, "HOLD ACKNOWLEDGE" },
+ { 0x1A, "HOLD REJECT" },
+ { 0x1C, "RETRIEVE" },
+ { 0x1D, "RETRIEVE ACKNOWLEDGE" },
+ { 0x1E, "RETRIEVE REJECT" },
+/*{ 0 x 1 0, "- - - Call clearing messages:" },*/
+ { 0x25, "DISCONNECT" },
+ { 0x2D, "RELEASE" },
+ { 0x2A, "RELEASE COMPLETE" },
+/*{ 0 x 1 1, "- - - Miscellaneous messages:" },*/
+ { 0x39, "CONGESTION CONTROL" },
+ { 0x3E, "NOTIFY" },
+ { 0x3D, "STATUS" },
+ { 0x34, "STATUS ENQUIRY" },
+ { 0x35, "START DTMF" },
+ { 0x31, "STOP DTMF" },
+ { 0x32, "STOP DTMF ACKNOWLEDGE" },
+ { 0x36, "START DTMF ACKNOWLEDGE" },
+ { 0x37, "START DTMF REJECT" },
+ { 0x3A, "FACILITY" },
+ { 0, NULL }
+};
+
+static const value_string mm_gprs_mess[] = {
+ { 0x01, "Attach request" },
+ { 0x02, "Attach accept" },
+ { 0x03, "Attach complete" },
+ { 0x04, "Attach reject" },
+ { 0x05, "Detach request" },
+ { 0x06, "Detach accept" },
+ { 0x08, "Routing area update request" },
+ { 0x09, "Routing area update accept" },
+ { 0x0A, "Routing area update complete" },
+ { 0x0B, "Routing area update reject" },
+ { 0x10, "P-TMSI reallocation command" },
+ { 0x11, "P-TMSI reallocation complete" },
+ { 0x12, "Authentication and ciphering req" },
+ { 0x13, "Authentication and ciphering resp" },
+ { 0x14, "Authentication and ciphering rej" },
+ { 0x15, "Identity request" },
+ { 0x16, "Identity response" },
+ { 0x20, "GMM status" },
+ { 0x21, "GMM information" },
+ { 0, NULL }
+};
+
+static const value_string tft_code_type[] = {
+ { 0, "Spare" },
+ { 1, "Create new TFT" },
+ { 2, "Delete existing TFT" },
+ { 3, "Add packet filters to existing TFT" },
+ { 4, "Replace packet filters in existing TFT" },
+ { 5, "Delete packet filters from existing TFT" },
+ { 6, "Reserved" },
+ { 7, "Reserved" },
+ { 0, NULL }
+};
+
+
+static dissector_handle_t ip_handle;
+static dissector_handle_t ipv6_handle;
+static dissector_handle_t ppp_handle;
+static dissector_handle_t data_handle;
+static dissector_handle_t gtpcdr_handle;
+
+static int decode_gtp_cause (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_imsi (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_rai (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_tlli (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_ptmsi (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_qos_gprs (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_reorder (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_auth_tri (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_map_cause (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_ptmsi_sig (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_ms_valid (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_recovery (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_sel_mode (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_16 (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_17 (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_18 (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_19 (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_nsapi (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_ranap_cause (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_rab_cntxt (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_rp_sms (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_rp (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_pkt_flow_id (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_chrg_char (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_trace_ref (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_trace_type (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_ms_reason (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_tr_comm (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_chrg_id (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_user_addr (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_mm_cntxt (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_pdp_cntxt (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_apn (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_gsn_addr (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_proto_conf (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_msisdn (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_qos_umts (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_auth_qui (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_tft (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_target_id (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_utran_cont (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_rab_setup (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_hdr_list (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_trigger_id (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_omc_id (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_chrg_addr (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_rel_pack (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_can_pack (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_data_req (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_data_resp (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_node_addr (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_priv_ext (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int decode_gtp_unknown (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+typedef struct _gtp_opt {
+ int optcode;
+ int (*decode)(tvbuff_t *, int, packet_info *, proto_tree *);
+} gtp_opt_t;
+
+static const gtp_opt_t gtpopt[] = {
+ { GTP_EXT_CAUSE, decode_gtp_cause },
+ { GTP_EXT_IMSI, decode_gtp_imsi },
+ { GTP_EXT_RAI, decode_gtp_rai },
+ { GTP_EXT_TLLI, decode_gtp_tlli },
+ { GTP_EXT_PTMSI, decode_gtp_ptmsi },
+ { GTP_EXT_QOS_GPRS, decode_gtp_qos_gprs },
+ { GTP_EXT_REORDER, decode_gtp_reorder },
+ { GTP_EXT_AUTH_TRI, decode_gtp_auth_tri },
+ { GTP_EXT_MAP_CAUSE, decode_gtp_map_cause },
+ { GTP_EXT_PTMSI_SIG, decode_gtp_ptmsi_sig },
+ { GTP_EXT_MS_VALID, decode_gtp_ms_valid },
+ { GTP_EXT_RECOVER, decode_gtp_recovery },
+ { GTP_EXT_SEL_MODE, decode_gtp_sel_mode },
+ { GTP_EXT_16, decode_gtp_16 },
+ { GTP_EXT_17, decode_gtp_17 },
+ { GTP_EXT_18, decode_gtp_18 },
+ { GTP_EXT_19, decode_gtp_19 },
+ { GTP_EXT_NSAPI, decode_gtp_nsapi },
+ { GTP_EXT_RANAP_CAUSE, decode_gtp_ranap_cause },
+ { GTP_EXT_RAB_CNTXT, decode_gtp_rab_cntxt },
+ { GTP_EXT_RP_SMS, decode_gtp_rp_sms },
+ { GTP_EXT_RP, decode_gtp_rp },
+ { GTP_EXT_PKT_FLOW_ID, decode_gtp_pkt_flow_id },
+ { GTP_EXT_CHRG_CHAR, decode_gtp_chrg_char },
+ { GTP_EXT_TRACE_REF, decode_gtp_trace_ref },
+ { GTP_EXT_TRACE_TYPE, decode_gtp_trace_type },
+ { GTPv1_EXT_MS_REASON, decode_gtp_ms_reason },
+ { GTP_EXT_TR_COMM, decode_gtp_tr_comm },
+ { GTP_EXT_CHRG_ID, decode_gtp_chrg_id },
+ { GTP_EXT_USER_ADDR, decode_gtp_user_addr },
+ { GTP_EXT_MM_CNTXT, decode_gtp_mm_cntxt },
+ { GTP_EXT_PDP_CNTXT, decode_gtp_pdp_cntxt },
+ { GTP_EXT_APN, decode_gtp_apn },
+ { GTP_EXT_PROTO_CONF, decode_gtp_proto_conf },
+ { GTP_EXT_GSN_ADDR, decode_gtp_gsn_addr },
+ { GTP_EXT_MSISDN, decode_gtp_msisdn },
+ { GTP_EXT_QOS_UMTS, decode_gtp_qos_umts }, /* 3G */
+ { GTP_EXT_AUTH_QUI, decode_gtp_auth_qui }, /* 3G */
+ { GTP_EXT_TFT, decode_gtp_tft }, /* 3G */
+ { GTP_EXT_TARGET_ID, decode_gtp_target_id }, /* 3G */
+ { GTP_EXT_UTRAN_CONT, decode_gtp_utran_cont }, /* 3G */
+ { GTP_EXT_RAB_SETUP, decode_gtp_rab_setup }, /* 3G */
+ { GTP_EXT_HDR_LIST, decode_gtp_hdr_list }, /* 3G */
+ { GTP_EXT_TRIGGER_ID, decode_gtp_trigger_id }, /* 3G */
+ { GTP_EXT_OMC_ID, decode_gtp_omc_id }, /* 3G */
+ { GTP_EXT_REL_PACK, decode_gtp_rel_pack }, /* charging */
+ { GTP_EXT_CAN_PACK, decode_gtp_can_pack }, /* charging */
+ { GTP_EXT_CHRG_ADDR, decode_gtp_chrg_addr },
+ { GTP_EXT_DATA_REQ, decode_gtp_data_req }, /* charging */
+ { GTP_EXT_DATA_RESP, decode_gtp_data_resp }, /* charging */
+ { GTP_EXT_NODE_ADDR, decode_gtp_node_addr },
+ { GTP_EXT_PRIV_EXT, decode_gtp_priv_ext },
+ { 0, decode_gtp_unknown }
+};
+
+struct _gtp_hdr {
+ guint8 flags;
+ guint8 message;
+ guint16 length;
+};
+
+static guint8 gtp_version = 0;
+static char *yesno[] = { "no", "yes" };
+
+static void
+col_append_str_gtp(column_info *cinfo, gint el, gchar *proto_name) {
+
+ int i;
+ int max_len;
+ gchar _tmp[COL_MAX_LEN];
+
+ max_len = COL_MAX_LEN;
+
+ for (i = 0; i < cinfo->num_cols; i++) {
+ if (cinfo->fmt_matx[i][el]) {
+ if (cinfo->col_data[i] != cinfo->col_buf[i]) {
+
+ strncpy(cinfo->col_buf[i], cinfo->col_data[i], max_len);
+ cinfo->col_buf[i][max_len - 1] = '\0';
+ }
+
+ _tmp[0] = '\0';
+ strcat(_tmp, proto_name);
+ strcat(_tmp, " <");
+ strcat(_tmp, cinfo->col_buf[i]);
+ strcat(_tmp, ">");
+ cinfo->col_buf[i][0] = '\0';
+ strcat(cinfo->col_buf[i], _tmp);
+ cinfo->col_data[i] = cinfo->col_buf[i];
+ }
+ }
+}
+
+static gchar *
+id_to_str(const guint8 *ad) {
+
+ static gchar str[17] = " ";
+ guint8 bits8to5, bits4to1;
+ int i, j = 0;
+ static const gchar hex_digits[10] = "0123456789";
+
+ for (i = 0; i < 8; i++) {
+ bits8to5 = (ad[i] >> 4) & 0x0F;
+ bits4to1 = ad[i] & 0x0F;
+ if (bits8to5 < 0xA)
+ str[j++] = hex_digits[bits4to1];
+ if (bits4to1 < 0xA)
+ str[j++] = hex_digits[bits8to5];
+ }
+ str[j] = '\0';
+ return str;
+}
+
+static gchar *
+imsi_to_str(const guint8 *ad) {
+
+ static gchar str[17] = " ";
+ int i, j = 0;
+
+ for (i = 0; i < 8; i++) {
+ if ((ad[i] & 0x0F) <= 9) str[j++] = (ad[i] & 0x0F) + 0x30;
+ if (((ad[i] >> 4) & 0x0F) <= 9) str[j++] = ((ad[i] >> 4) & 0x0F) + 0x30;
+ }
+ str[j] = '\0';
+
+ return str;
+}
+
+static gchar *
+msisdn_to_str(const guint8 *ad, int len) {
+
+ static gchar str[18] = "+ ";
+ guint8 bits8to5, bits4to1;
+ int i, j = 1;
+ static const gchar hex_digits[10] = "0123456789";
+
+ for (i = 1; i < len && i < 9; i++) {
+ bits8to5 = (ad[i] >> 4) & 0x0F;
+ bits4to1 = ad[i] & 0x0F;
+ if (bits4to1 < 0xA)
+ str[j++] = hex_digits[bits4to1];
+ if (bits8to5 < 0xA)
+ str[j++] = hex_digits[bits8to5];
+ }
+ str[j] = '\0';
+
+ return str;
+}
+
+/* Next definitions and function check_field_presence checks if given field
+ * in GTP packet is compliant with ETSI
+ */
+typedef struct _header {
+ guint8 code;
+ guint8 presence;
+} ext_header;
+
+typedef struct _message {
+ guint8 code;
+ ext_header fields[32];
+} _gtp_mess_items;
+
+/* ---------------------
+ * GPRS messages
+ * ---------------------*/
+static _gtp_mess_items gprs_mess_items[] = {
+
+{
+ GTP_MSG_ECHO_REQ, {
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_ECHO_RESP, {
+ { GTP_EXT_RECOVER, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_VER_NOT_SUPP, {
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_NODE_ALIVE_REQ, {
+ { GTP_EXT_NODE_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_NODE_ALIVE_RESP, {
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_REDIR_REQ, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_NODE_ADDR, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_REDIR_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_CREATE_PDP_REQ, {
+ { GTP_EXT_QOS_GPRS, GTP_MANDATORY },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_SEL_MODE, GTP_MANDATORY },
+ { GTP_EXT_FLOW_LABEL, GTP_MANDATORY },
+ { GTP_EXT_FLOW_SIG, GTP_MANDATORY },
+ { GTP_EXT_MSISDN, GTP_MANDATORY },
+ { GTP_EXT_USER_ADDR, GTP_MANDATORY },
+ { GTP_EXT_APN, GTP_MANDATORY },
+ { GTP_EXT_PROTO_CONF, GTP_OPTIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_CREATE_PDP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_QOS_GPRS, GTP_CONDITIONAL },
+ { GTP_EXT_REORDER, GTP_CONDITIONAL },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_FLOW_LABEL, GTP_CONDITIONAL },
+ { GTP_EXT_FLOW_SIG, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ID, GTP_CONDITIONAL },
+ { GTP_EXT_USER_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_PROTO_CONF, GTP_OPTIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ADDR, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_UPDATE_PDP_REQ, {
+ { GTP_EXT_QOS_GPRS, GTP_MANDATORY },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_FLOW_LABEL, GTP_MANDATORY },
+ { GTP_EXT_FLOW_SIG, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 },
+ }
+},
+{
+ GTP_MSG_UPDATE_PDP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_QOS_GPRS, GTP_CONDITIONAL },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_FLOW_LABEL, GTP_CONDITIONAL },
+ { GTP_EXT_FLOW_SIG, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ID, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ADDR, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_DELETE_PDP_REQ, {
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_DELETE_PDP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 },
+ }
+},
+{
+ GTP_MSG_CREATE_AA_PDP_REQ, {
+ { GTP_EXT_QOS_GPRS, GTP_MANDATORY },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_SEL_MODE, GTP_MANDATORY },
+ { GTP_EXT_FLOW_LABEL, GTP_MANDATORY },
+ { GTP_EXT_FLOW_SIG, GTP_MANDATORY },
+ { GTP_EXT_USER_ADDR, GTP_MANDATORY },
+ { GTP_EXT_APN, GTP_MANDATORY },
+ { GTP_EXT_PROTO_CONF, GTP_OPTIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_CREATE_AA_PDP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_QOS_GPRS, GTP_CONDITIONAL },
+ { GTP_EXT_REORDER, GTP_CONDITIONAL },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_FLOW_LABEL, GTP_CONDITIONAL },
+ { GTP_EXT_FLOW_SIG, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ID, GTP_CONDITIONAL },
+ { GTP_EXT_USER_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_PROTO_CONF, GTP_OPTIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ADDR, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_DELETE_AA_PDP_REQ, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_DELETE_AA_PDP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_ERR_IND, {
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_PDU_NOTIFY_REQ, {
+ { GTP_EXT_USER_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_PDU_NOTIFY_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_PDU_NOTIFY_REJ_REQ, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_USER_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_PDU_NOTIFY_REJ_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SEND_ROUT_INFO_REQ, {
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SEND_ROUT_INFO_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_MAP_CAUSE, GTP_OPTIONAL },
+ { GTP_EXT_MS_REASON, GTP_OPTIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FAIL_REP_REQ, {
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FAIL_REP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_MAP_CAUSE, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_MS_PRESENT_REQ, {
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_MS_PRESENT_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_IDENT_REQ, {
+ { GTP_EXT_RAI, GTP_MANDATORY },
+ { GTP_EXT_PTMSI, GTP_MANDATORY },
+ { GTP_EXT_PTMSI_SIG, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_IDENT_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_IMSI, GTP_CONDITIONAL },
+ { GTP_EXT_AUTH_TRI, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SGSN_CNTXT_REQ, {
+ { GTP_EXT_IMSI, GTP_CONDITIONAL },
+ { GTP_EXT_RAI, GTP_MANDATORY },
+ { GTP_EXT_TLLI, GTP_MANDATORY },
+ { GTP_EXT_PTMSI_SIG, GTP_OPTIONAL },
+ { GTP_EXT_MS_VALID, GTP_OPTIONAL },
+ { GTP_EXT_FLOW_SIG, GTP_MANDATORY },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SGSN_CNTXT_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_IMSI, GTP_CONDITIONAL },
+ { GTP_EXT_FLOW_SIG, GTP_CONDITIONAL },
+ { GTP_EXT_MM_CNTXT, GTP_CONDITIONAL },
+ { GTP_EXT_PDP_CNTXT, GTP_CONDITIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SGSN_CNTXT_ACK, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_FLOW_II, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_DATA_TRANSF_REQ, {
+ { GTP_EXT_TR_COMM, GTP_MANDATORY },
+ { GTP_EXT_DATA_REQ, GTP_CONDITIONAL },
+ { GTP_EXT_REL_PACK, GTP_CONDITIONAL },
+ { GTP_EXT_CAN_PACK, GTP_CONDITIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_DATA_TRANSF_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_DATA_RESP, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ 0, {
+ { 0, 0 }
+ }
+}
+};
+
+/* -----------------------------
+ * UMTS messages
+ * -----------------------------*/
+static _gtp_mess_items umts_mess_items[] = {
+
+{
+ GTP_MSG_ECHO_REQ, {
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_ECHO_RESP, {
+ { GTP_EXT_RECOVER, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_VER_NOT_SUPP, {
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_NODE_ALIVE_REQ, {
+ { GTP_EXT_NODE_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_NODE_ALIVE_RESP, {
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_REDIR_REQ, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_NODE_ADDR, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_REDIR_REQ, {
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_CREATE_PDP_REQ, {
+ { GTP_EXT_IMSI, GTP_CONDITIONAL },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_SEL_MODE, GTP_CONDITIONAL },
+ { GTP_EXT_TEID, GTP_MANDATORY },
+ { GTP_EXT_TEID_CP, GTP_CONDITIONAL },
+ { GTP_EXT_NSAPI, GTP_MANDATORY },
+ { GTP_EXT_NSAPI, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_CHAR, GTP_OPTIONAL },
+ { GTP_EXT_TRACE_REF, GTP_OPTIONAL },
+ { GTP_EXT_TRACE_TYPE, GTP_OPTIONAL },
+ { GTP_EXT_USER_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_APN, GTP_CONDITIONAL },
+ { GTP_EXT_PROTO_CONF, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_MSISDN, GTP_CONDITIONAL },
+ { GTP_EXT_QOS_UMTS, GTP_MANDATORY },
+ { GTP_EXT_TFT, GTP_CONDITIONAL },
+ { GTP_EXT_TRIGGER_ID, GTP_OPTIONAL },
+ { GTP_EXT_OMC_ID, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_CREATE_PDP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_REORDER, GTP_CONDITIONAL },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_TEID, GTP_CONDITIONAL },
+ { GTP_EXT_TEID_CP, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ID, GTP_CONDITIONAL },
+ { GTP_EXT_USER_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_PROTO_CONF, GTP_OPTIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_QOS_UMTS, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ADDR, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{ /* checked, SGSN -> GGSN */
+ GTP_MSG_UPDATE_PDP_REQ, {
+ { GTP_EXT_IMSI, GTP_CONDITIONAL },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_TEID, GTP_MANDATORY },
+ { GTP_EXT_TEID_CP, GTP_CONDITIONAL },
+ { GTP_EXT_NSAPI, GTP_MANDATORY },
+ { GTP_EXT_TRACE_REF, GTP_OPTIONAL },
+ { GTP_EXT_TRACE_TYPE, GTP_OPTIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_QOS_UMTS, GTP_MANDATORY },
+ { GTP_EXT_TFT, GTP_OPTIONAL },
+ { GTP_EXT_TRIGGER_ID, GTP_OPTIONAL },
+ { GTP_EXT_OMC_ID, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{ /* checked, GGSN -> SGSN */
+ GTP_MSG_UPDATE_PDP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_RECOVER, GTP_OPTIONAL },
+ { GTP_EXT_TEID, GTP_CONDITIONAL },
+ { GTP_EXT_TEID_CP, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ID, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_QOS_UMTS, GTP_CONDITIONAL },
+ { GTP_EXT_CHRG_ADDR, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_DELETE_PDP_REQ, {
+ { GTP_EXT_TEAR_IND, GTP_CONDITIONAL },
+ { GTP_EXT_NSAPI, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_DELETE_PDP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_ERR_IND, {
+ { GTP_EXT_TEID, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_PDU_NOTIFY_REQ, {
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_TEID_CP, GTP_MANDATORY },
+ { GTP_EXT_USER_ADDR, GTP_MANDATORY },
+ { GTP_EXT_APN, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_PDU_NOTIFY_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_PDU_NOTIFY_REJ_REQ, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_TEID_CP, GTP_MANDATORY },
+ { GTP_EXT_USER_ADDR, GTP_MANDATORY },
+ { GTP_EXT_APN, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_PDU_NOTIFY_REJ_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SUPP_EXT_HDR, {
+ { GTP_EXT_HDR_LIST, GTP_MANDATORY },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SEND_ROUT_INFO_REQ, {
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SEND_ROUT_INFO_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_MAP_CAUSE, GTP_OPTIONAL },
+ { GTPv1_EXT_MS_REASON, GTP_OPTIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FAIL_REP_REQ, {
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FAIL_REP_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_MAP_CAUSE, GTP_OPTIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_MS_PRESENT_REQ, {
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_MS_PRESENT_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_IDENT_REQ, {
+ { GTP_EXT_RAI, GTP_MANDATORY },
+ { GTP_EXT_PTMSI, GTP_MANDATORY },
+ { GTP_EXT_PTMSI_SIG, GTP_CONDITIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_IDENT_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_IMSI, GTP_CONDITIONAL },
+ { GTP_EXT_AUTH_TRI, GTP_CONDITIONAL },
+ { GTP_EXT_AUTH_QUI, GTP_CONDITIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SGSN_CNTXT_REQ, {
+ { GTP_EXT_IMSI, GTP_CONDITIONAL },
+ { GTP_EXT_RAI, GTP_MANDATORY },
+ { GTP_EXT_TLLI, GTP_CONDITIONAL },
+ { GTP_EXT_PTMSI, GTP_CONDITIONAL },
+ { GTP_EXT_PTMSI_SIG, GTP_CONDITIONAL },
+ { GTP_EXT_MS_VALID, GTP_OPTIONAL },
+ { GTP_EXT_TEID_CP, GTP_MANDATORY },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SGSN_CNTXT_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_IMSI, GTP_CONDITIONAL },
+ { GTP_EXT_TEID_CP, GTP_CONDITIONAL },
+ { GTP_EXT_RP_SMS, GTP_OPTIONAL },
+ { GTP_EXT_RP, GTP_OPTIONAL },
+ { GTP_EXT_PKT_FLOW_ID, GTP_OPTIONAL },
+ { GTP_EXT_MM_CNTXT, GTP_CONDITIONAL },
+ { GTP_EXT_PDP_CNTXT, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_SGSN_CNTXT_ACK, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_TEID_II, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FORW_RELOC_REQ, {
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_TEID_CP, GTP_MANDATORY },
+ { GTP_EXT_RANAP_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_MM_CNTXT, GTP_MANDATORY },
+ { GTP_EXT_PDP_CNTXT, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_MANDATORY },
+ { GTP_EXT_TARGET_ID, GTP_MANDATORY },
+ { GTP_EXT_UTRAN_CONT, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FORW_RELOC_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_TEID_CP, GTP_CONDITIONAL },
+ { GTP_EXT_RANAP_CAUSE, GTP_CONDITIONAL },
+ { GTP_EXT_GSN_ADDR, GTP_CONDITIONAL },
+ { GTP_EXT_UTRAN_CONT, GTP_OPTIONAL },
+ { GTP_EXT_RAB_SETUP, GTP_CONDITIONAL },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FORW_RELOC_COMP, {
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_RELOC_CANCEL_REQ, {
+ { GTP_EXT_IMSI, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_RELOC_CANCEL_RESP, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FORW_RELOC_ACK, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FORW_SRNS_CNTXT, {
+ { GTP_EXT_RAB_CNTXT, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ GTP_MSG_FORW_SRNS_CNTXT_ACK, {
+ { GTP_EXT_CAUSE, GTP_MANDATORY },
+ { GTP_EXT_PRIV_EXT, GTP_OPTIONAL },
+ { 0, 0 }
+ }
+},
+{
+ 0, {
+ { 0, 0 }
+ }
+}
+};
+
+static int
+check_field_presence(guint8 message, guint8 field, int *position) {
+
+ guint i = 0;
+ _gtp_mess_items *mess_items;
+
+ switch(gtp_version) {
+ case 0:
+ mess_items = gprs_mess_items;
+ break;
+ case 1:
+ mess_items = umts_mess_items;
+ break;
+ default:
+ return -2;
+ }
+
+ while (mess_items[i].code) {
+ if (mess_items[i].code == message) {
+
+ while (mess_items[i].fields[*position].code) {
+ if (mess_items[i].fields[*position].code == field) {
+ (*position)++;
+ return 0;
+ } else {
+ if (mess_items[i].fields[*position].presence == GTP_MANDATORY) {
+ return mess_items[i].fields[(*position)++].code;
+ } else {
+ (*position)++;
+ }}
+ }
+ return -1;
+ }
+ i++;
+ }
+
+ return -2;
+}
+
+/* Decoders of fields in extension headers, each function returns no of bytes from field */
+
+/* GPRS: 9.60 v7.6.0, chapter
+ * UMTS: 29.060 v4.0, chapter
+ */
+static int
+decode_gtp_cause(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 cause;
+
+ cause = tvb_get_guint8(tvb, offset+1);
+
+ proto_tree_add_uint(tree, hf_gtp_cause, tvb, offset, 2, cause);
+
+ return 2;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.2
+ * UMTS: 29.060 v4.0, chapter 7.7.2
+ */
+static int
+decode_gtp_imsi(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 imsi_val[8];
+ gchar *imsi_str;
+
+ tvb_memcpy(tvb, imsi_val, offset+1, 8);
+ imsi_str = imsi_to_str (imsi_val);
+
+ proto_tree_add_string (tree, hf_gtp_imsi, tvb, offset, 9, imsi_str);
+
+ return 9;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.3
+ * UMTS: 29.060 v4.0, chapter 7.7.3
+ */
+static int
+decode_gtp_rai(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ proto_tree *ext_tree_rai;
+ proto_item *te;
+ guint8 byte[3];
+ guint16 mnc, mcc;
+
+ te = proto_tree_add_text(tree, tvb, offset, 1, val_to_str(GTP_EXT_RAI, gtp_val, "Unknown message"));
+ ext_tree_rai = proto_item_add_subtree(te, ett_gtp_rai);
+
+ byte[0] = tvb_get_guint8 (tvb, offset + 1);
+ byte[1] = tvb_get_guint8 (tvb, offset + 2);
+ byte[2] = tvb_get_guint8 (tvb, offset + 3);
+ mcc = (byte[0] & 0x0F) * 100 + ((byte[0] & 0xF0) >> 4) * 10 + (byte[1] & 0x0F );
+ if ((byte[1] & 0xF0) == 0xF0)
+ mnc = (byte[2] & 0x0F) * 10 + ((byte[2] & 0xF0) >> 4);
+ else
+ mnc = (byte[2] & 0x0F) * 100 + ((byte[2] & 0xF0) >> 4 ) * 10 + ((byte[1] & 0xF0) >> 4);
+
+ proto_tree_add_uint(ext_tree_rai, hf_gtp_rai_mcc, tvb, offset+1, 2, mcc);
+ proto_tree_add_uint(ext_tree_rai, hf_gtp_rai_mnc, tvb, offset+2, 2, mnc);
+ proto_tree_add_uint(ext_tree_rai, hf_gtp_rai_lac, tvb, offset+4, 2, tvb_get_ntohs (tvb, offset+4));
+ proto_tree_add_uint(ext_tree_rai, hf_gtp_rai_rac, tvb, offset+6, 1, tvb_get_guint8 (tvb, offset+6));
+
+ return 7;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.4, page 39
+ * UMTS: 29.060 v4.0, chapter 7.7.4, page 47
+ */
+static int
+decode_gtp_tlli(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint32 tlli;
+
+ tlli = tvb_get_ntohl(tvb, offset+1);
+ proto_tree_add_uint(tree, hf_gtp_tlli, tvb, offset, 5, tlli);
+
+ return 5;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.5, page 39
+ * UMTS: 29.060 v4.0, chapter 7.7.5, page 47
+ */
+static int
+decode_gtp_ptmsi(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint32 ptmsi;
+
+ ptmsi = tvb_get_ntohl (tvb, offset+1);
+ proto_tree_add_uint (tree, hf_gtp_ptmsi, tvb, offset, 5, ptmsi);
+
+ return 5;
+}
+
+/* adjust - how many bytes before offset should be highlighted
+ */
+static int
+decode_qos_gprs(tvbuff_t *tvb, int offset, proto_tree *tree, gchar* qos_str, guint8 adjust) {
+
+ guint8 spare1, delay, reliability, peak, spare2, precedence, spare3, mean;
+ proto_tree *ext_tree_qos;
+ proto_item *te;
+
+ spare1 = tvb_get_guint8(tvb, offset) & 0xC0;
+ delay = tvb_get_guint8(tvb, offset) & 0x38;
+ reliability = tvb_get_guint8(tvb, offset) & 0x07;
+ peak = tvb_get_guint8(tvb, offset+1) & 0xF0;
+ spare2 = tvb_get_guint8(tvb, offset+1) & 0x08;
+ precedence = tvb_get_guint8(tvb, offset+1) & 0x07;
+ spare3 = tvb_get_guint8(tvb, offset+2) & 0xE0;
+ mean = tvb_get_guint8(tvb, offset+2) & 0x1F;
+
+ te = proto_tree_add_text(tree, tvb, offset-adjust, 3+adjust, "%s: delay: %u, reliability: %u, peak: %u, precedence: %u, mean: %u",
+ qos_str, (delay >> 3) & 0x07, reliability, (peak >> 4) & 0x0F, precedence, mean);
+ ext_tree_qos = proto_item_add_subtree(te, ett_gtp_qos);
+
+ if (adjust != 0) {
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_spare1, tvb, offset, 1, spare1);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_delay, tvb, offset, 1, delay);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_reliability, tvb, offset, 1, reliability);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_peak, tvb, offset+1, 1, peak);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_spare2, tvb, offset+1, 1, spare2);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_precedence, tvb, offset+1, 1, precedence);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_spare3, tvb, offset+2, 1, spare3);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_mean, tvb, offset+2, 1, mean);
+ }
+
+ return 3;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.6, page 39
+ * 4.08
+ * 3.60
+ * UMTS: not present
+ * TODO: check if length is included: ETSI 4.08 vs 9.60
+ */
+static int
+decode_gtp_qos_gprs(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ return (1+decode_qos_gprs(tvb, offset+1, tree, "Quality of Service", 1));
+
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.7, page 39
+ * UMTS: 29.060 v4.0, chapter 7.7.6, page 47
+ */
+static int
+decode_gtp_reorder(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 reorder;
+
+ reorder = tvb_get_guint8(tvb, offset+1) & 0x01;
+ proto_tree_add_boolean(tree, hf_gtp_reorder, tvb, offset, 2, reorder);
+
+ return 2;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.8, page 40
+ * 4.08 v7.1.2, chapter 10.5.3.1+
+ * UMTS: 29.060 v4.0, chapter 7.7.7
+ * TODO: Add blurb support by registering items in the protocol registration
+ */
+static int
+decode_gtp_auth_tri(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ proto_tree *ext_tree_auth_tri;
+ proto_item *te;
+
+ te = proto_tree_add_text(tree, tvb, offset, 29, val_to_str(GTP_EXT_AUTH_TRI, gtp_val, "Unknown message"));
+ ext_tree_auth_tri = proto_item_add_subtree(tree, ett_gtp_auth_tri);
+
+ proto_tree_add_text(ext_tree_auth_tri, tvb, offset+1, 16, "RAND: %s", tvb_bytes_to_str(tvb, offset+1, 16));
+ proto_tree_add_text(ext_tree_auth_tri, tvb, offset+17, 4, "SRES: %s", tvb_bytes_to_str(tvb, offset+17, 4));
+ proto_tree_add_text(ext_tree_auth_tri, tvb, offset+21, 8, "Kc: %s", tvb_bytes_to_str(tvb, offset+21, 8));
+
+ return 1+16+4+8;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.9, page 40
+ * 9.02 v7.7.0, page 1090
+ * UMTS: 29.060 v4.0, chapter 7.7.8, page 48
+ * 29.002 v4.2.1, chapter 17.5, page 268
+ */
+static int
+decode_gtp_map_cause(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 map_cause;
+
+ map_cause = tvb_get_guint8(tvb, offset+1);
+ proto_tree_add_uint (tree, hf_gtp_map_cause, tvb, offset, 2, map_cause);
+
+ return 2;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.10, page 41
+ * UMTS: 29.060 v4.0, chapter 7.7.9, page 48
+ */
+static int
+decode_gtp_ptmsi_sig(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint32 ptmsi_sig;
+
+ ptmsi_sig = tvb_get_ntoh24(tvb, offset+1);
+ proto_tree_add_uint(tree, hf_gtp_ptmsi_sig, tvb, offset, 4, ptmsi_sig);
+
+ return 4;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.11, page 41
+ * UMTS: 29.060 v4.0, chapter 7.7.10, page 49
+ */
+static int
+decode_gtp_ms_valid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 ms_valid;
+
+ ms_valid = tvb_get_guint8(tvb, offset+1) & 0x01;
+ proto_tree_add_boolean (tree, hf_gtp_ms_valid, tvb, offset, 2, ms_valid);
+
+ return 2;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.12, page 41
+ * UMTS: 29.060 v4.0, chapter 7.7.11, page 49
+ */
+static int
+decode_gtp_recovery(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 recovery;
+
+ recovery = tvb_get_guint8(tvb, offset+1);
+ proto_tree_add_uint (tree, hf_gtp_recovery, tvb, offset, 2, recovery);
+
+ return 2;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.13, page 42
+ * UMTS: 29.060 v4.0, chapter 7.7.12, page 49
+ */
+static int
+decode_gtp_sel_mode(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 sel_mode;
+
+ sel_mode = tvb_get_guint8(tvb, offset+1) & 0x03;
+ proto_tree_add_uint(tree, hf_gtp_sel_mode, tvb, offset, 2, sel_mode);
+
+ return 2;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.14, page 42
+ * UMTS: 29.060 v4.0, chapter 7.7.13, page 50
+ */
+static int
+decode_gtp_16(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 ext_flow_label;
+ guint32 teid_data;
+
+ switch (gtp_version) {
+ case 0:
+ ext_flow_label = tvb_get_ntohs(tvb, offset+1);
+ proto_tree_add_uint(tree, hf_gtp_ext_flow_label, tvb, offset, 3, ext_flow_label);
+
+ return 3;
+ case 1:
+ teid_data = tvb_get_ntohl(tvb, offset+1);
+ proto_tree_add_uint(tree, hf_gtp_teid_data, tvb, offset, 5, teid_data);
+
+ return 5;
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Flow label/TEID Data I : GTP version not supported");
+
+ return 3;
+ }
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.15, page 42
+ * UMTS: 29.060 v4.0, chapter 7.7.14, page 42
+ */
+static int
+decode_gtp_17(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 flow_sig;
+ guint32 teid_cp;
+
+ switch (gtp_version) {
+ case 0:
+ flow_sig = tvb_get_ntohs(tvb, offset+1);
+ proto_tree_add_uint (tree, hf_gtp_flow_sig, tvb, offset, 3, flow_sig);
+ return 3;
+ case 1:
+ teid_cp = tvb_get_ntohl(tvb, offset+1);
+ proto_tree_add_uint (tree, hf_gtp_teid_cp, tvb, offset, 5, teid_cp);
+ return 5;
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Flow label signalling/TEID control plane : GTP version not supported");
+ return 3;
+ }
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.16, page 42
+ * UMTS: 29.060 v4.0, chapter 7.7.15, page 51
+ */
+static int
+decode_gtp_18(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 flow_ii;
+ guint32 teid_ii;
+ proto_tree *ext_tree_flow_ii;
+ proto_item *te;
+
+ switch (gtp_version) {
+ case 0:
+ te = proto_tree_add_text(tree, tvb, offset, 4, val_to_str(GTP_EXT_FLOW_II, gtp_val, "Unknown message"));
+ ext_tree_flow_ii = proto_item_add_subtree (te, ett_gtp_flow_ii);
+
+ proto_tree_add_uint(ext_tree_flow_ii, hf_gtp_nsapi, tvb, offset+1, 1, tvb_get_guint8(tvb, offset+1) & 0x0F);
+
+ flow_ii = tvb_get_ntohs(tvb, offset+2);
+ proto_tree_add_uint(ext_tree_flow_ii, hf_gtp_flow_ii, tvb, offset+2, 2, flow_ii);
+
+ return 4;
+ case 1:
+ te = proto_tree_add_text (tree, tvb, offset, 6, val_to_str(GTP_EXT_TEID_II, gtp_val, "Unknown message"));
+ ext_tree_flow_ii = proto_item_add_subtree(te, ett_gtp_flow_ii);
+
+ proto_tree_add_uint(ext_tree_flow_ii, hf_gtp_nsapi, tvb, offset+1, 1, tvb_get_guint8(tvb, offset+1) & 0x0F);
+
+
+ teid_ii = tvb_get_ntohl(tvb, offset+2);
+ proto_tree_add_uint(ext_tree_flow_ii, hf_gtp_teid_ii, tvb, offset+2, 4, teid_ii);
+
+ return 6;
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Flow data II/TEID Data II : GTP Version not supported");
+
+ return 4;
+ }
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.16A, page 43
+ * UMTS: 29.060 v4.0, chapter 7.7.16, page 51
+ * Check if all ms_reason types are included
+ */
+static int
+decode_gtp_19(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 field19;
+
+ field19 = tvb_get_guint8(tvb, offset+1);
+
+ switch (gtp_version) {
+ case 0:
+ proto_tree_add_uint(tree, hf_gtp_ms_reason, tvb, offset, 2, field19);
+ break;
+ case 1:
+ proto_tree_add_boolean(tree, hf_gtp_tear_ind, tvb, offset, 2, field19 & 0x01);
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Information Element Type = 19 : GTP Version not supported");
+ break;
+ }
+
+ return 2;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.17, page 51
+ */
+static int
+decode_gtp_nsapi(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 nsapi;
+
+ nsapi = tvb_get_guint8(tvb, offset+1) & 0x0F;
+ proto_tree_add_uint(tree, hf_gtp_nsapi, tvb, offset, 2, nsapi);
+
+ return 2;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.18, page 52
+ */
+static int
+decode_gtp_ranap_cause(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 ranap;
+
+ ranap = tvb_get_guint8(tvb, offset+1);
+
+ if(ranap > 0 && ranap <=64)
+ proto_tree_add_uint_format(tree, hf_gtp_ranap_cause, tvb, offset, 2,
+ ranap, "%s (Radio Network Layer Cause) : %s (%u)",
+ val_to_str(GTP_EXT_RANAP_CAUSE, gtp_val, "Unknown"),
+ val_to_str(ranap, ranap_cause_type, "Unknown RANAP Cause"), ranap);
+
+ if(ranap > 64 && ranap <=80)
+ proto_tree_add_uint_format(tree, hf_gtp_ranap_cause, tvb, offset, 2,
+ ranap, "%s (Transport Layer Cause) : %s (%u)",
+ val_to_str(GTP_EXT_RANAP_CAUSE, gtp_val, "Unknown"),
+ val_to_str(ranap, ranap_cause_type, "Unknown RANAP Cause"), ranap);
+
+ if(ranap > 80 && ranap <=96)
+ proto_tree_add_uint_format(tree, hf_gtp_ranap_cause, tvb, offset, 2,
+ ranap, "%s (NAS Cause) : %s (%u)",
+ val_to_str(GTP_EXT_RANAP_CAUSE, gtp_val, "Unknown"),
+ val_to_str(ranap, ranap_cause_type, "Unknown RANAP Cause"), ranap);
+
+ if(ranap > 96 && ranap <=112)
+ proto_tree_add_uint_format(tree, hf_gtp_ranap_cause, tvb, offset, 2, ranap,
+ "%s (Protocol Cause) : %s (%u)",
+ val_to_str(GTP_EXT_RANAP_CAUSE, gtp_val, "Unknown"),
+ val_to_str(ranap, ranap_cause_type, "Unknown RANAP Cause"), ranap);
+
+ if(ranap > 112 && ranap <=128)
+ proto_tree_add_uint_format(tree, hf_gtp_ranap_cause, tvb, offset, 2, ranap,
+ "%s (Miscellaneous Cause) : %s (%u)",
+ val_to_str(GTP_EXT_RANAP_CAUSE, gtp_val, "Unknown"),
+ val_to_str(ranap, ranap_cause_type, "Unknown RANAP Cause"), ranap);
+
+ if(ranap > 128 /* && ranap <=255 */)
+ proto_tree_add_uint_format(tree, hf_gtp_ranap_cause, tvb, offset, 2, ranap,
+ "%s (Non-standard Cause) : %s (%u)",
+ val_to_str(GTP_EXT_RANAP_CAUSE, gtp_val, "Unknown"),
+ val_to_str(ranap, ranap_cause_type, "Unknown RANAP Cause"), ranap);
+
+ return 2;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.19, page 52
+ */
+static int
+decode_gtp_rab_cntxt(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 nsapi, dl_pdcp_seq, ul_pdcp_seq;
+ guint16 dl_gtpu_seq, ul_gtpu_seq;
+ proto_tree *ext_tree_rab_cntxt;
+ proto_item *te;
+
+ te = proto_tree_add_text(tree, tvb, offset, 8, val_to_str(GTP_EXT_RAB_CNTXT, gtp_val, "Unknown message"));
+ ext_tree_rab_cntxt = proto_item_add_subtree(te, ett_gtp_rab_cntxt);
+
+ nsapi = tvb_get_guint8(tvb, offset+1) & 0x0F;
+ dl_gtpu_seq = tvb_get_ntohs(tvb, offset+2);
+ ul_gtpu_seq = tvb_get_ntohs(tvb, offset+4);
+ dl_pdcp_seq = tvb_get_guint8(tvb, offset+6);
+ ul_pdcp_seq = tvb_get_guint8(tvb, offset+7);
+
+ proto_tree_add_uint (ext_tree_rab_cntxt, hf_gtp_nsapi, tvb, offset+1, 1, nsapi);
+ proto_tree_add_uint(ext_tree_rab_cntxt, hf_gtp_rab_gtpu_dn, tvb, offset+2, 2, dl_gtpu_seq);
+ proto_tree_add_uint(ext_tree_rab_cntxt, hf_gtp_rab_gtpu_up, tvb, offset+4, 2, ul_gtpu_seq);
+ proto_tree_add_uint(ext_tree_rab_cntxt, hf_gtp_rab_pdu_dn, tvb, offset+6, 1, dl_pdcp_seq);
+ proto_tree_add_uint(ext_tree_rab_cntxt, hf_gtp_rab_pdu_up, tvb, offset+7, 1, ul_pdcp_seq);
+
+ return 8;
+}
+
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.20, page 53
+ */
+static int
+decode_gtp_rp_sms(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 rp_sms;
+
+ rp_sms = tvb_get_guint8(tvb, offset+1) & 0x07;
+ proto_tree_add_uint(tree, hf_gtp_rp_sms, tvb, offset, 2, rp_sms);
+
+ return 2;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.21, page 53
+ */
+static int
+decode_gtp_rp(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ proto_tree *ext_tree_rp;
+ proto_item *te;
+ guint8 nsapi, rp, spare;
+
+ nsapi = tvb_get_guint8(tvb, offset+1) & 0xF0;
+ spare = tvb_get_guint8(tvb, offset+1) & 0x08;
+ rp = tvb_get_guint8(tvb, offset+1) & 0x07;
+
+ te = proto_tree_add_uint_format(tree, hf_gtp_rp, tvb, offset, 2, rp, "Radio Priority for NSAPI(%u) : %u", nsapi, rp);
+ ext_tree_rp = proto_item_add_subtree(tree, ett_gtp_rp);
+
+ proto_tree_add_uint(ext_tree_rp, hf_gtp_rp_nsapi, tvb, offset+1, 1, nsapi);
+ proto_tree_add_uint(ext_tree_rp, hf_gtp_rp_spare, tvb, offset+1, 1, spare);
+ proto_tree_add_uint(ext_tree_rp, hf_gtp_rp, tvb, offset+1, 1, rp);
+
+ return 2;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.22, page 53
+ */
+static int
+decode_gtp_pkt_flow_id(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ proto_tree *ext_tree_pkt_flow_id;
+ proto_item *te;
+ guint8 nsapi, pkt_flow_id;
+
+ nsapi = tvb_get_guint8(tvb, offset+1) & 0x0F;
+ pkt_flow_id = tvb_get_guint8(tvb, offset+2);
+
+ te = proto_tree_add_uint_format (tree, hf_gtp_pkt_flow_id, tvb, offset,
+ 3, pkt_flow_id, "Packet Flow ID for NSAPI(%u) : %u", nsapi,
+ pkt_flow_id);
+ ext_tree_pkt_flow_id = proto_item_add_subtree(tree, ett_gtp_pkt_flow_id);
+
+ proto_tree_add_uint(ext_tree_pkt_flow_id, hf_gtp_nsapi, tvb, offset+1, 1, nsapi);
+ proto_tree_add_uint_format(ext_tree_pkt_flow_id, hf_gtp_pkt_flow_id, tvb,
+ offset+2, 1, pkt_flow_id, "%s : %u",
+ val_to_str(GTP_EXT_PKT_FLOW_ID, gtp_val, "Unknown message"),
+ pkt_flow_id);
+
+ return 3;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.23, page 53
+ * TODO: Differenciate these uints?
+ */
+static int
+decode_gtp_chrg_char(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 chrg_char;
+ proto_item *te;
+ proto_tree *ext_tree_chrg_char;
+
+ chrg_char = tvb_get_ntohs(tvb, offset+1);
+
+ te = proto_tree_add_uint (tree, hf_gtp_chrg_char, tvb, offset, 3, chrg_char);
+ /*"%s: %x", val_to_str (GTP_EXT_CHRG_CHAR, gtp_val, "Unknown message"), chrg_char);*/
+ ext_tree_chrg_char = proto_item_add_subtree(te, ett_gtp_chrg_char);
+
+ proto_tree_add_uint (ext_tree_chrg_char, hf_gtp_chrg_char_s, tvb, offset+1, 2, chrg_char);
+ proto_tree_add_uint (ext_tree_chrg_char, hf_gtp_chrg_char_n, tvb, offset+1, 2, chrg_char);
+ proto_tree_add_uint (ext_tree_chrg_char, hf_gtp_chrg_char_p, tvb, offset+1, 2, chrg_char);
+ proto_tree_add_uint (ext_tree_chrg_char, hf_gtp_chrg_char_f, tvb, offset+1, 2, chrg_char);
+ proto_tree_add_uint (ext_tree_chrg_char, hf_gtp_chrg_char_h, tvb, offset+1, 2, chrg_char);
+ proto_tree_add_uint (ext_tree_chrg_char, hf_gtp_chrg_char_r, tvb, offset+1, 2, chrg_char);
+
+ return 3;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.24, page
+ */
+static int
+decode_gtp_trace_ref(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 trace_ref;
+
+ trace_ref = tvb_get_ntohs(tvb, offset+1);
+
+ proto_tree_add_uint (tree, hf_gtp_trace_ref, tvb, offset, 3, trace_ref);
+
+ return 3;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.25, page
+ */
+static int
+decode_gtp_trace_type(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 trace_type;
+
+ trace_type = tvb_get_ntohs(tvb, offset+1);
+
+ proto_tree_add_uint (tree, hf_gtp_trace_type, tvb, offset, 3, trace_type);
+
+ return 3;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.16A
+ * UMTS: 29.060 v4.0, chapter 7.7.25A, page
+ */
+static int
+decode_gtp_ms_reason(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 reason;
+
+ reason = tvb_get_guint8(tvb, offset+1);
+
+ proto_tree_add_uint (tree, hf_gtp_ms_reason, tvb, offset, 2, reason);
+
+ return 2;
+}
+
+
+/* GPRS: 12.15 v7.6.0, chapter 7.3.3, page 45
+ * UMTS: 33.015
+ */
+static int
+decode_gtp_tr_comm(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 tr_command;
+
+ tr_command = tvb_get_guint8(tvb, offset+1);
+
+ proto_tree_add_uint (tree, hf_gtp_tr_comm, tvb, offset, 2, tr_command);
+
+ return 2;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.17, page 43
+ * UMTS: 29.060 v4.0, chapter 7.7.26, page 55
+ */
+static int
+decode_gtp_chrg_id(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint32 chrg_id;
+
+ chrg_id = tvb_get_ntohl(tvb, offset+1);
+ proto_tree_add_uint (tree, hf_gtp_chrg_id, tvb, offset, 5, chrg_id);
+
+ return 5;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.18, page 43
+ * UMTS: 29.060 v4.0, chapter 7.7.27, page 55
+ */
+static int
+decode_gtp_user_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length;
+ guint8 pdp_typ, pdp_org;
+ guint32 addr_ipv4;
+ struct e_in6_addr addr_ipv6;
+ proto_tree *ext_tree_user;
+ proto_item *te;
+
+
+ length = tvb_get_ntohs(tvb, offset+1);
+ pdp_org = tvb_get_guint8(tvb, offset+3) & 0x0F;
+ pdp_typ = tvb_get_guint8(tvb, offset+4);
+
+ te = proto_tree_add_text(tree, tvb, offset, 3+length, "%s (%s/%s)",
+ val_to_str(GTP_EXT_USER_ADDR, gtp_val, "Unknown message"),
+ val_to_str(pdp_org, pdp_org_type, "Unknown PDP Organization"),
+ val_to_str(pdp_typ, pdp_type, "Unknown PDP Type"));
+ ext_tree_user = proto_item_add_subtree(te, ett_gtp_user);
+
+ proto_tree_add_text(ext_tree_user, tvb, offset+1, 2, "Length : %u", length);
+ proto_tree_add_uint(ext_tree_user, hf_gtp_user_addr_pdp_org, tvb, offset+3, 1, pdp_org);
+ proto_tree_add_uint(ext_tree_user, hf_gtp_user_addr_pdp_type, tvb, offset+4, 1, pdp_typ);
+
+ if (length == 2) {
+ if (pdp_org == 0 && pdp_typ == 1)
+ proto_item_append_text(te, " (Point to Point Protocol)");
+ else if (pdp_typ == 2)
+ proto_item_append_text(te, " (Octet Stream Protocol)");
+ } else if (length > 2) {
+ switch (pdp_typ) {
+ case 0x21:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset+5, sizeof addr_ipv4);
+ proto_tree_add_ipv4(ext_tree_user, hf_gtp_user_ipv4, tvb, offset+5, 4, addr_ipv4);
+ proto_item_append_text(te, " : %s", ip_to_str((guint8 *)&addr_ipv4));
+ break;
+ case 0x57:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset+5, sizeof addr_ipv6);
+ proto_tree_add_ipv6 (ext_tree_user, hf_gtp_user_ipv6, tvb, offset+5, 16, (guint8 *)&addr_ipv6);
+ proto_item_append_text(te, " : %s", ip6_to_str((struct e_in6_addr*)&addr_ipv6));
+ break;
+ }
+ } else
+ proto_item_append_text(te, " : empty PDP Address");
+
+ return 3+length;
+}
+
+static int
+decode_triplet(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 count) {
+
+ proto_tree *ext_tree_trip;
+ proto_item *te_trip;
+ guint16 i;
+
+ for (i=0;i<count;i++) {
+ te_trip = proto_tree_add_text(tree, tvb, offset+i*28, 28, "Triplet no%x", i);
+ ext_tree_trip = proto_item_add_subtree(te_trip, ett_gtp_trip);
+
+ proto_tree_add_text(ext_tree_trip, tvb, offset+i*28, 16, "RAND: %s", tvb_bytes_to_str(tvb, offset+i*28, 16));
+ proto_tree_add_text(ext_tree_trip, tvb, offset+i*28+16, 4, "SRES: %s", tvb_bytes_to_str(tvb, offset+i*28+16, 4));
+ proto_tree_add_text(ext_tree_trip, tvb, offset+i*28+20, 8, "Kc: %s", tvb_bytes_to_str(tvb, offset+i*28+20, 8));
+ }
+
+ return count*28;
+}
+
+/* adjust - how many bytes before quintuplet should be highlighted
+ */
+static int
+decode_quintuplet(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 count, guint8 adjust) {
+
+ proto_tree *ext_tree_quint;
+ proto_item *te_quint;
+ guint16 q_len, xres_len, auth_len, q_offset, i;
+
+ q_offset = 0;
+
+ for (i=0;i<count;i++) {
+
+ offset = offset + q_offset;
+
+ q_len = tvb_get_ntohs(tvb, offset);
+
+ te_quint = proto_tree_add_text(tree, tvb, offset-adjust, q_len+adjust, "Quintuplet #%x", i);
+ ext_tree_quint = proto_item_add_subtree(te_quint, ett_gtp_quint);
+
+ proto_tree_add_text(ext_tree_quint, tvb, offset, 2, "Length: %x", q_len);
+ proto_tree_add_text(ext_tree_quint, tvb, offset+2, 16, "RAND: %s", tvb_bytes_to_str(tvb, offset+2, 16));
+ xres_len = tvb_get_ntohs(tvb, offset+18);
+ proto_tree_add_text(ext_tree_quint, tvb, offset+18, 2, "XRES length: %u", xres_len);
+ proto_tree_add_text(ext_tree_quint, tvb, offset+20, xres_len, "XRES: %s", tvb_bytes_to_str(tvb, offset+20, xres_len));
+ proto_tree_add_text(ext_tree_quint, tvb, offset+20+xres_len, 16, "Quintuplet ciphering key: %s", tvb_bytes_to_str(tvb, offset+20+xres_len, 16));
+ proto_tree_add_text(ext_tree_quint, tvb, offset+36+xres_len, 16, "Quintuplet integrity key: %s", tvb_bytes_to_str(tvb, offset+36+xres_len, 16));
+ auth_len = tvb_get_ntohs(tvb, offset+52+xres_len);
+ proto_tree_add_text(ext_tree_quint, tvb, offset+52+xres_len, 2, "Authentication length: %u", auth_len);
+ proto_tree_add_text(ext_tree_quint, tvb, offset+54+xres_len, auth_len, "AUTH: %s", tvb_bytes_to_str(tvb, offset+54+xres_len, auth_len));
+
+ q_offset = q_offset + q_len + 2;
+ }
+
+ return q_offset;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.19 page
+ * UMTS: 29.060 v4.0, chapter 7.7.28 page 57
+ * TODO: - check if for quintuplets first 2 bytes are length, according to AuthQuint
+ * - finish displaying last 3 parameters
+ */
+static int
+decode_gtp_mm_cntxt(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length, quint_len, net_cap, con_len;
+ guint8 cksn, count, sec_mode, cipher, trans_id, proto_disc, message, drx_split, drx_len, drx_ccch, non_drx_timer;
+ proto_tree *ext_tree_mm;
+ proto_item *te;
+
+ te = proto_tree_add_text(tree, tvb, offset, 1, val_to_str(GTP_EXT_MM_CNTXT, gtp_val, "Unknown message"));
+ ext_tree_mm = proto_item_add_subtree(te, ett_gtp_mm);
+
+ length = tvb_get_ntohs(tvb, offset+1);
+ if (length < 1) return 3;
+
+ cksn = tvb_get_guint8(tvb, offset+3) & 0x07;
+ sec_mode = (tvb_get_guint8(tvb, offset+4) >> 6) & 0x03;
+ count = (tvb_get_guint8(tvb, offset+4) >> 3) & 0x07;
+ cipher = tvb_get_guint8(tvb, offset+4) & 0x07;
+
+ proto_tree_add_text(ext_tree_mm, tvb, offset+1, 2, "Length: %x", length);
+ proto_tree_add_text(ext_tree_mm, tvb, offset+3, 1, "Ciphering Key Sequence Number: %u", cksn);
+ if (gtp_version != 0) {
+ proto_tree_add_text(ext_tree_mm, tvb, offset+3, 1, "Security type: %u (%s)", sec_mode,
+ val_to_str(sec_mode, mm_sec_modep, "Unknown"));
+ } else {
+ sec_mode = 1;
+ }
+
+ proto_tree_add_text(ext_tree_mm, tvb, offset+4, 1, "No of triplets: %u", count);
+
+ switch (sec_mode) {
+ case 0:
+ if (cipher == 0) {
+ proto_tree_add_text(ext_tree_mm, tvb, offset+4, 1, "Ciphering: no ciphering");
+ } else {
+ proto_tree_add_text(ext_tree_mm, tvb, offset+4, 1, "Ciphering: GEA/%u", cipher);
+ }
+ proto_tree_add_text(ext_tree_mm, tvb, offset+5, 16, "Ciphering key CK: %s", tvb_bytes_to_str(tvb, offset+5, 16));
+ proto_tree_add_text(ext_tree_mm, tvb, offset+21, 16, "Integrity key CK: %s", tvb_bytes_to_str(tvb, offset+21, 16));
+ quint_len = tvb_get_ntohs(tvb, offset+37);
+ proto_tree_add_text(ext_tree_mm, tvb, offset+37, 2, "Quintuplets length: %x", quint_len);
+
+ offset = offset + decode_quintuplet(tvb, offset+39, ext_tree_mm, count, 0) + 39;
+
+
+ break;
+ case 1:
+ if (cipher == 0) {
+ proto_tree_add_text(ext_tree_mm, tvb, offset+4, 1, "Ciphering: no ciphering");
+ } else {
+ proto_tree_add_text(ext_tree_mm, tvb, offset+4, 1, "Ciphering: GEA/%u", cipher);
+ }
+ proto_tree_add_text(ext_tree_mm, tvb, offset+5, 8, "Ciphering key Kc: %s", tvb_bytes_to_str(tvb, offset+5, 8));
+
+ offset = offset + decode_triplet(tvb, offset+13, ext_tree_mm, count) + 13;
+
+ break;
+ case 2:
+ proto_tree_add_text(ext_tree_mm, tvb, offset+5, 16, "Ciphering key CK: %s", tvb_bytes_to_str(tvb, offset+5, 16));
+ proto_tree_add_text(ext_tree_mm, tvb, offset+21, 16, "Integrity key CK: %s", tvb_bytes_to_str(tvb, offset+21, 16));
+ quint_len = tvb_get_ntohs(tvb, offset+37);
+ proto_tree_add_text(ext_tree_mm, tvb, offset+37, 2, "Quintuplets length: %x", quint_len);
+
+ offset = offset + decode_quintuplet(tvb, offset+39, ext_tree_mm, count, 0) + 39;
+
+ break;
+ case 3:
+ if (cipher == 0) {
+ proto_tree_add_text(ext_tree_mm, tvb, offset+4, 1, "Ciphering: no ciphering");
+ } else {
+ proto_tree_add_text(ext_tree_mm, tvb, offset+4, 1, "Ciphering: GEA/%u", cipher);
+ }
+ proto_tree_add_text(ext_tree_mm, tvb, offset+5, 8, "Ciphering key Kc: %s", tvb_bytes_to_str(tvb, offset+5, 8));
+ quint_len = tvb_get_ntohs(tvb, offset+13);
+ proto_tree_add_text(ext_tree_mm, tvb, offset+13, 2, "Quintuplets length: %x", quint_len);
+
+ offset = offset + decode_quintuplet(tvb, offset+15, ext_tree_mm, count, 0) + 15;
+
+ break;
+ default:
+ break;
+ }
+
+
+ drx_split = tvb_get_guint8(tvb, offset);
+ drx_len = (tvb_get_guint8(tvb, offset+1) >> 4) & 0x0F;
+ drx_ccch = (tvb_get_guint8(tvb, offset+1) >> 3) & 0x01;
+ non_drx_timer = tvb_get_guint8(tvb, offset+1) & 0x07;
+
+ net_cap = tvb_get_ntohs(tvb, offset+2);
+ con_len = tvb_get_ntohs(tvb, offset+4);
+
+ proto_tree_add_text(ext_tree_mm, tvb, offset, 1, "DRX: split PG cycle code: %u", drx_split);
+ proto_tree_add_text(ext_tree_mm, tvb, offset+1, 1, "DRX: CN specific DRX cycle length coefficient: %u", drx_len);
+ proto_tree_add_text(ext_tree_mm, tvb, offset+1, 1, "DRX: split PG cycle on CCCH supported by MS: %s", yesno[drx_ccch]);
+ if (non_drx_timer == 0) {
+ proto_tree_add_text(ext_tree_mm, tvb, offset+1, 1, "DRX: no non-DRX mode after transfer state");
+ } else {
+ proto_tree_add_text(ext_tree_mm, tvb, offset+1, 1, "DRX: max sec non-DRX mode after transfer state: 2^%u", non_drx_timer-1);
+ }
+
+ proto_tree_add_text(ext_tree_mm, tvb, offset+2, 2, "MS network capability: %u", net_cap);
+ proto_tree_add_text(ext_tree_mm, tvb, offset+4, 2, "Container length: %u", con_len);
+
+ if (con_len > 0) {
+ trans_id = (tvb_get_guint8(tvb, offset+6) >> 4) & 0x0F;
+ proto_tree_add_text(ext_tree_mm, tvb, offset+6, 1, "Transaction identifier: 0x%x", trans_id);
+ proto_disc = tvb_get_guint8(tvb, offset+6) & 0x0F;
+ proto_tree_add_text(ext_tree_mm, tvb, offset+6, 1, "Protocol discriminator: 0x%x (%s)", proto_disc,
+ val_to_str(proto_disc, mm_proto_disc, "Unknown"));
+ message = tvb_get_guint8(tvb, offset+7);
+ switch (message) {
+
+ case MM_PROTO_RR_MGMT:
+ proto_tree_add_text(ext_tree_mm, tvb, offset+7, 1, "Message type: 0x%02x (%s)", message,
+ val_to_str(message, mm_rr_mess, "Unknown"));
+ break;
+
+ case MM_PROTO_MM_NON_GPRS:
+ proto_tree_add_text(ext_tree_mm, tvb, offset+7, 1, "Message type: 0x%02x (%s)", message,
+ val_to_str(message, mm_mm_mess, "Unknown"));
+ break;
+
+ case MM_PROTO_CALL_CONTROL:
+ case MM_PROTO_GROUP_CALL_CONTROL:
+ case MM_PROTO_BROADCAST_CALL_CONTROL:
+ proto_tree_add_text(ext_tree_mm, tvb, offset+7, 1, "Message type: 0x%02x (%s)", message,
+ val_to_str(message, mm_cc_mess, "Unknown"));
+ break;
+
+ case MM_PROTO_MM_GPRS:
+ proto_tree_add_text(ext_tree_mm, tvb, offset+7, 1, "Message type: 0x%02x (%s)", message,
+ val_to_str(message, mm_gprs_mess, "Unknown"));
+ break;
+
+ default:
+ proto_tree_add_text(ext_tree_mm, tvb, offset+7, 1, "Message type: 0x%02x", message);
+ break;
+ }
+ /* XXX - dissect additional IEs from GSM L3 message */
+ }
+
+ return 3+length;
+}
+
+/* Function to extract the value of an hexadecimal octet. Only the lower
+ * nybble will be non-zero in the output.
+ * */
+static guint8 hex2dec (guint8 x)
+{
+ if ((x >= 'a') && (x <= 'f'))
+ x = x - 'a' + 10;
+ else if ((x >= 'A') && (x <= 'F'))
+ x = x - 'A' + 10;
+ else if ((x >= '0') && (x <= '9'))
+ x = x - '0';
+ else
+ x = 0;
+ return x;
+}
+
+/* Wrapper function to add UTF-8 decoding for QoS attributes in
+ * RADIUS messages.
+ * */
+static guint8 wrapped_tvb_get_guint8( tvbuff_t *tvb, int offset, int type)
+{
+ if (type == 2)
+ return (hex2dec(tvb_get_guint8(tvb, offset)) << 4
+ | hex2dec(tvb_get_guint8(tvb, offset + 1)));
+ else
+ return tvb_get_guint8(tvb, offset);
+}
+
+ /* WARNING : actually length is coded on 2 octets for QoS profile but on 1 octet for PDP Context!
+ * so type means length of length :-)
+ *
+ * WARNING :) type does not mean length of length any more... see below for
+ * type = 3!
+ */
+int
+decode_qos_umts(tvbuff_t *tvb, int offset, proto_tree *tree, gchar* qos_str, guint8 type) {
+
+ guint length;
+ guint8 al_ret_priority;
+ guint8 delay, reliability, peak, precedence, mean, spare1, spare2, spare3;
+ guint8 traf_class, del_order, del_err_sdu;
+ guint8 max_sdu_size, max_ul, max_dl;
+ guint8 res_ber, sdu_err_ratio;
+ guint8 trans_delay, traf_handl_prio;
+ guint8 guar_ul, guar_dl;
+ proto_tree *ext_tree_qos;
+ proto_item *te;
+ int mss, mu, md, gu, gd;
+
+ /* Will keep if the input is UTF-8 encoded (as in RADIUS messages).
+ * If 1, input is *not* UTF-8 encoded (i.e. each input octet corresponds
+ * to one byte to be dissected).
+ * If 2, input is UTF-8 encoded (i.e. each *couple* of input octets
+ * corresponds to one byte to be dissected)
+ * */
+ guint8 utf8_type = 1;
+
+ /* In RADIUS messages the QoS has a version field of two octets prepended.
+ * As of 29.061 v.3.a.0, there is an hyphen between "Release Indicator" and
+ * <release specific QoS IE UTF-8 encoding>. Even if it sounds rather
+ * inconsistent and unuseful, I will check hyphen presence here and
+ * will signal its presence.
+ * */
+ guint8 version_buffer[2];
+ guint8 hyphen;
+
+ /* Will keep the value that will be returned
+ * */
+ int retval = 0;
+
+ switch (type) {
+ case 1:
+ length = tvb_get_guint8 (tvb, offset);
+ te = proto_tree_add_text (tree, tvb, offset, length + 1, "%s", qos_str);
+ ext_tree_qos = proto_item_add_subtree (te, ett_gtp_qos);
+ proto_tree_add_text (ext_tree_qos, tvb, offset, 1, "Length: %u", length);
+ offset++;
+ retval = length + 1;
+ break;
+ case 2:
+ length = tvb_get_ntohs (tvb, offset + 1);
+ te = proto_tree_add_text(tree, tvb, offset, length + 3, "%s", qos_str);
+ ext_tree_qos = proto_item_add_subtree (te, ett_gtp_qos);
+ proto_tree_add_text (ext_tree_qos, tvb, offset + 1, 2, "Length: %u", length);
+ offset += 3; /* +1 because of first 0x86 byte for UMTS QoS */
+ retval = length + 3;
+ break;
+ case 3:
+ /* For QoS inside RADIUS Client messages from GGSN */
+ utf8_type = 2;
+
+ /* The field in the RADIUS message starts one byte before :) */
+ length = tvb_get_guint8 (tvb, offset);
+ te = proto_tree_add_text (tree, tvb, offset - 1, length, "%s", qos_str);
+
+ ext_tree_qos = proto_item_add_subtree (te, ett_gtp_qos);
+ version_buffer[0] = tvb_get_guint8(tvb, offset + 1);
+ version_buffer[1] = tvb_get_guint8(tvb, offset + 2);
+ proto_tree_add_text (ext_tree_qos, tvb, offset + 1, 2, "Version: %c%c", version_buffer[0], version_buffer[1]);
+
+ /* Hyphen handling */
+ hyphen = tvb_get_guint8(tvb, offset + 3);
+ if (hyphen == ((guint8) '-'))
+ {
+ /* Hyphen is present, put in protocol tree */
+ proto_tree_add_text (ext_tree_qos, tvb, offset + 3, 1, "Hyphen separator: -");
+ offset++; /* "Get rid" of hyphen */
+ }
+
+ /* Now, we modify offset here and in order to use type later
+ * effectively.*/
+ offset += 2;
+ retval = length + 3; /* Actually, will be ignored. */
+ break;
+ default:
+ /* XXX - what should we do with the length here? */
+ length = 0;
+ retval = 0;
+ ext_tree_qos = NULL;
+ break;
+ }
+
+ /* In RADIUS messages there is no allocation-retention priority
+ * so I don't need to wrap the following call to tvb_get_guint8
+ * */
+ al_ret_priority = tvb_get_guint8 (tvb, offset);
+
+ /* All calls are wrapped to take into account the possibility that the
+ * input is UTF-8 encoded. If utf8_type is equal to 1, the final value
+ * of the offset will be the same as in the previous version of this
+ * dissector, and the wrapped function will serve as a dumb wrapper;
+ * otherwise, if utf_8_type is 2, the offset is correctly shifted by
+ * two bytes for needed shift, and the wrapped function will unencode
+ * two values from the input.
+ * */
+ spare1 = wrapped_tvb_get_guint8(tvb, offset+(1 - 1) * utf8_type + 1, utf8_type) & 0xC0;
+ delay = wrapped_tvb_get_guint8(tvb, offset+(1 - 1) * utf8_type + 1, utf8_type) & 0x38;
+ reliability = wrapped_tvb_get_guint8(tvb, offset+(1 - 1) * utf8_type + 1, utf8_type) & 0x07;
+ peak = wrapped_tvb_get_guint8(tvb, offset+(2 - 1) * utf8_type + 1, utf8_type) & 0xF0;
+ spare2 = wrapped_tvb_get_guint8(tvb, offset+(2 - 1) * utf8_type + 1, utf8_type) & 0x08;
+ precedence = wrapped_tvb_get_guint8(tvb, offset+(2 - 1) * utf8_type + 1, utf8_type) & 0x07;
+ spare3 = wrapped_tvb_get_guint8(tvb, offset+(3 - 1) * utf8_type + 1, utf8_type) & 0xE0;
+ mean = wrapped_tvb_get_guint8(tvb, offset+(3 - 1) * utf8_type + 1, utf8_type) & 0x1F;
+
+ /* In RADIUS messages there is no allocation-retention priority */
+ if (type != 3)
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_al_ret_priority, tvb, offset, 1, al_ret_priority);
+
+ /* All additions must take care of the fact that QoS fields in RADIUS
+ * messages are UTF-8 encoded, so we have to use the same trick as above.
+ * */
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_spare1, tvb, offset+(1 - 1) * utf8_type + 1, utf8_type, spare1);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_delay, tvb, offset+(1 - 1) * utf8_type + 1, utf8_type, delay);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_reliability, tvb, offset+(1 - 1) * utf8_type + 1, utf8_type, reliability);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_peak, tvb, offset+(2 - 1) * utf8_type + 1, utf8_type, peak);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_spare2, tvb, offset+(2 - 1) * utf8_type + 1, utf8_type, spare2);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_precedence, tvb, offset+(2 - 1) * utf8_type + 1, utf8_type, precedence);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_spare3, tvb, offset+(3 - 1) * utf8_type + 1, utf8_type, spare3);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_mean, tvb, offset+(3 - 1) * utf8_type + 1, utf8_type, mean);
+
+ if (length > 4) {
+
+ /* See above for the need of wrapping
+ * */
+ traf_class = wrapped_tvb_get_guint8(tvb, offset+(4 - 1) * utf8_type + 1, utf8_type) & 0xE0;
+ del_order = wrapped_tvb_get_guint8(tvb, offset+(4 - 1) * utf8_type + 1, utf8_type) & 0x18;
+ del_err_sdu = wrapped_tvb_get_guint8(tvb, offset+(4 - 1) * utf8_type + 1, utf8_type) & 0x07;
+ max_sdu_size = wrapped_tvb_get_guint8(tvb, offset+(5 - 1) * utf8_type + 1, utf8_type);
+ max_ul = wrapped_tvb_get_guint8(tvb, offset+(6 - 1) * utf8_type + 1, utf8_type);
+ max_dl = wrapped_tvb_get_guint8(tvb, offset+(7 - 1) * utf8_type + 1, utf8_type);
+ res_ber = wrapped_tvb_get_guint8(tvb, offset+(8 - 1) * utf8_type + 1, utf8_type) & 0xF0;
+ sdu_err_ratio = wrapped_tvb_get_guint8(tvb, offset+(8 - 1) * utf8_type + 1, utf8_type) & 0x0F;
+ trans_delay = wrapped_tvb_get_guint8(tvb, offset+(9 - 1) * utf8_type + 1, utf8_type) & 0xFC;
+ traf_handl_prio = wrapped_tvb_get_guint8(tvb, offset+(9 - 1) * utf8_type + 1, utf8_type) & 0x03;
+ guar_ul = wrapped_tvb_get_guint8(tvb, offset+(10 - 1) * utf8_type + 1, utf8_type);
+ guar_dl = wrapped_tvb_get_guint8(tvb, offset+(11 - 1) * utf8_type + 1, utf8_type);
+
+ /* See above comments for the changes
+ * */
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_traf_class, tvb, offset+(4 - 1) * utf8_type + 1, utf8_type, traf_class);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_del_order, tvb, offset+(4 - 1) * utf8_type + 1, utf8_type, del_order);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_del_err_sdu, tvb, offset+(4 - 1) * utf8_type + 1, utf8_type, del_err_sdu);
+ if (max_sdu_size == 0 || max_sdu_size > 150)
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_max_sdu_size, tvb, offset+(5 - 1) * utf8_type + 1, utf8_type, max_sdu_size);
+ if (max_sdu_size > 0 && max_sdu_size <= 150) {
+ mss = max_sdu_size*10;
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_max_sdu_size, tvb, offset+(5 - 1) * utf8_type + 1, utf8_type, mss, "Maximum SDU size : %u octets", mss);
+ }
+
+ if(max_ul == 0 || max_ul == 255)
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_max_ul, tvb, offset+(6 - 1) * utf8_type + 1, utf8_type, max_ul);
+ if(max_ul > 0 && max_ul <= 63)
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_max_ul, tvb, offset+(6 - 1) * utf8_type + 1, utf8_type, max_ul, "Maximum bit rate for uplink : %u kbps", max_ul);
+ if(max_ul > 63 && max_ul <=127) {
+ mu = 64 + ( max_ul - 64 ) * 8;
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_max_ul, tvb, offset+(6 - 1) * utf8_type + 1, utf8_type, mu, "Maximum bit rate for uplink : %u kbps", mu);
+ }
+
+ if(max_ul > 127 && max_ul <=254) {
+ mu = 576 + ( max_ul - 128 ) * 64;
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_max_ul, tvb, offset+(6 - 1) * utf8_type + 1, utf8_type, mu, "Maximum bit rate for uplink : %u kbps", mu);
+ }
+
+ if(max_dl == 0 || max_dl == 255)
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_max_dl, tvb, offset+(7 - 1) * utf8_type + 1, utf8_type, max_dl);
+ if(max_dl > 0 && max_dl <= 63)
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_max_dl, tvb, offset+(7 - 1) * utf8_type + 1, utf8_type, max_dl, "Maximum bit rate for downlink : %u kbps", max_dl);
+ if(max_dl > 63 && max_dl <=127) {
+ md = 64 + ( max_dl - 64 ) * 8;
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_max_dl, tvb, offset+(7 - 1) * utf8_type + 1, utf8_type, md, "Maximum bit rate for downlink : %u kbps", md);
+ }
+ if(max_dl > 127 && max_dl <=254) {
+ md = 576 + ( max_dl - 128 ) * 64;
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_max_dl, tvb, offset+(7 - 1) * utf8_type + 1, utf8_type, md, "Maximum bit rate for downlink : %u kbps", md);
+ }
+
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_res_ber, tvb, offset+(8 - 1) * utf8_type + 1, utf8_type, res_ber);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_sdu_err_ratio, tvb, offset+(8 - 1) * utf8_type + 1, utf8_type, sdu_err_ratio);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_trans_delay, tvb, offset+(9 - 1) * utf8_type + 1, utf8_type, trans_delay);
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_traf_handl_prio, tvb, offset+(9 - 1) * utf8_type + 1, utf8_type, traf_handl_prio);
+
+ if(guar_ul == 0 || guar_ul == 255)
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_guar_ul, tvb, offset+(10 - 1) * utf8_type + 1, utf8_type, guar_ul);
+ if(guar_ul > 0 && guar_ul <= 63)
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_guar_ul, tvb, offset+(10 - 1) * utf8_type + 1, utf8_type, guar_ul, "Guaranteed bit rate for uplink : %u kbps", guar_ul);
+ if(guar_ul > 63 && guar_ul <=127) {
+ gu = 64 + ( guar_ul - 64 ) * 8;
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_guar_ul, tvb, offset+(10 - 1) * utf8_type + 1, utf8_type, gu, "Guaranteed bit rate for uplink : %u kbps", gu);
+ }
+ if(guar_ul > 127 && guar_ul <=254) {
+ gu = 576 + ( guar_ul - 128 ) * 64;
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_guar_ul, tvb, offset+(10 - 1) * utf8_type + 1, utf8_type, gu, "Guaranteed bit rate for uplink : %u kbps", gu);
+ }
+
+ if(guar_dl == 0 || guar_dl == 255)
+ proto_tree_add_uint(ext_tree_qos, hf_gtp_qos_guar_dl, tvb, offset+(11 - 1) * utf8_type + 1, utf8_type, guar_dl);
+ if(guar_dl > 0 && guar_dl <= 63)
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_guar_dl, tvb, offset+(11 - 1) * utf8_type + 1, utf8_type, guar_dl, "Guaranteed bit rate for downlink : %u kbps", guar_dl);
+ if(guar_dl > 63 && guar_dl <=127) {
+ gd = 64 + ( guar_dl - 64 ) * 8;
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_guar_dl, tvb, offset+(11 - 1) * utf8_type + 1, utf8_type, gd, "Guaranteed bit rate for downlink : %u kbps", gd);
+ }
+ if(guar_dl > 127 && guar_dl <=254) {
+ gd = 576 + ( guar_dl - 128 ) * 64;
+ proto_tree_add_uint_format(ext_tree_qos, hf_gtp_qos_guar_dl, tvb, offset+(11 - 1) * utf8_type + 1, utf8_type, gd, "Guaranteed bit rate for downlink : %u kbps", gd);
+ }
+
+ }
+
+ return retval;
+}
+
+static void
+decode_apn(tvbuff_t *tvb, int offset, guint16 length, proto_tree *tree) {
+
+ gchar *apn = NULL;
+ guint8 name_len, tmp;
+
+ if (length > 0) {
+ name_len = tvb_get_guint8 (tvb, offset);
+
+ if (name_len < 0x20) {
+ apn = tvb_get_string(tvb, offset + 1, length - 1);
+ for (;;) {
+ if (name_len >= length - 1) break;
+ tmp = name_len;
+ name_len = name_len + apn[tmp] + 1;
+ apn[tmp] = '.';
+ }
+ } else
+ apn = tvb_get_string(tvb, offset, length);
+
+ proto_tree_add_string (tree, hf_gtp_apn, tvb, offset, length, apn);
+ g_free(apn);
+ }
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.20
+ * UMTS: 29.060 v4.0, chapter 7.7.29
+ * TODO: unify addr functions
+ */
+static int
+decode_gtp_pdp_cntxt(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 ggsn_addr_len, apn_len, trans_id, vaa, order, nsapi, sapi, pdu_send_no, pdu_rec_no, pdp_cntxt_id,
+ pdp_type_org, pdp_type_num, pdp_addr_len;
+ guint16 length, sn_down, sn_up, up_flow;
+ guint32 addr_ipv4, up_teid, up_teid_cp;
+ struct e_in6_addr addr_ipv6;
+ proto_tree *ext_tree_pdp;
+ proto_item *te;
+
+ length = tvb_get_ntohs(tvb, offset+1);
+
+ te = proto_tree_add_text(tree, tvb, offset, length+3, val_to_str(GTP_EXT_PDP_CNTXT, gtp_val, "Unknown message"));
+ ext_tree_pdp = proto_item_add_subtree(te, ett_gtp_pdp);
+
+ vaa = (tvb_get_guint8(tvb, offset+3) >> 6) & 0x01;
+ order = (tvb_get_guint8(tvb, offset+3) >> 4) & 0x01;
+ nsapi = tvb_get_guint8(tvb, offset+3) & 0x0F;
+ sapi = tvb_get_guint8(tvb, offset+4) & 0x0F;
+
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+3, 1, "VPLMN address allowed: %s", yesno[vaa]);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+3, 1, "Reordering required: %s", yesno[order]);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+3, 1, "NSAPI: %u", nsapi);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+4, 1, "SAPI: %u", sapi);
+
+ switch (gtp_version) {
+ case 0:
+ decode_qos_gprs(tvb, offset+5, ext_tree_pdp, "QoS subscribed", 0);
+ decode_qos_gprs(tvb, offset+8, ext_tree_pdp, "QoS requested", 0);
+ decode_qos_gprs(tvb, offset+11, ext_tree_pdp, "QoS negotiated", 0);
+ offset = offset + 14;
+ break;
+ case 1:
+ offset = offset + 5;
+ offset = offset + decode_qos_umts(tvb, offset, ext_tree_pdp, "QoS subscribed", 1);
+ offset = offset + decode_qos_umts(tvb, offset, ext_tree_pdp, "QoS requested", 1);
+ offset = offset + decode_qos_umts(tvb, offset, ext_tree_pdp, "QoS negotiated", 1);
+ break;
+ default:
+ break;
+ }
+
+ sn_down = tvb_get_ntohs(tvb, offset);
+ sn_up = tvb_get_ntohs(tvb, offset+2);
+ pdu_send_no = tvb_get_guint8(tvb, offset+4);
+ pdu_rec_no = tvb_get_guint8(tvb, offset+5);
+
+ proto_tree_add_text(ext_tree_pdp, tvb, offset, 2, "Sequence number down: %u", sn_down);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+2, 2, "Sequence number up: %u", sn_up);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+4, 1, "Send N-PDU number: %u", pdu_send_no);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+5, 1, "Receive N-PDU number: %u", pdu_rec_no);
+
+ switch (gtp_version) {
+ case 0:
+ up_flow = tvb_get_ntohs(tvb, offset+6);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+6, 2, "Uplink flow label signalling: %u", up_flow);
+ offset = offset + 8;
+ break;
+ case 1:
+ up_teid = tvb_get_ntohl(tvb, offset+6);
+ up_teid_cp = tvb_get_ntohl(tvb, offset+10);
+ pdp_cntxt_id = tvb_get_guint8(tvb, offset+14);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+6, 4, "Uplink TEID: %x", up_teid);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+10, 4, "Uplink TEID control plane: %x", up_teid_cp);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+14, 1, "PDP context identifier: %u", pdp_cntxt_id);
+ offset = offset + 15;
+ break;
+ default:
+ break;
+ }
+
+ pdp_type_org = tvb_get_guint8(tvb, offset) & 0x0F;
+ pdp_type_num = tvb_get_guint8(tvb, offset+1);
+ pdp_addr_len = tvb_get_guint8(tvb, offset+2);
+
+ proto_tree_add_text(ext_tree_pdp, tvb, offset, 1, "PDP organization: %s", val_to_str(pdp_type_org, pdp_type, "Unknown PDP org"));
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+1, 1, "PDP type: %s", val_to_str(pdp_type_num, pdp_org_type, "Unknown PDP type"));
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+2, 1, "PDP address length: %u", pdp_addr_len);
+
+ if (pdp_addr_len > 0) {
+ switch (pdp_type_num) {
+ case 0x21:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset+3, sizeof addr_ipv4);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+3, 4, "PDP address: %s", ip_to_str((guint8 *)&addr_ipv4));
+ break;
+ case 0x57:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset+3, sizeof addr_ipv6);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+3, 16, "PDP address: %s", ip6_to_str((struct e_in6_addr*)&addr_ipv6));
+ break;
+ default:
+ break;
+ }
+ }
+
+ offset = offset + 3 + pdp_addr_len;
+
+ ggsn_addr_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset, 1, "GGSN address length: %u", ggsn_addr_len);
+
+ switch (ggsn_addr_len) {
+ case 4:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset+1, sizeof addr_ipv4);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+1, 4, "GGSN address: %s", ip_to_str((guint8 *)&addr_ipv4));
+ break;
+ case 16:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset+1, sizeof addr_ipv6);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+1, 16, "GGSN address: %s", ip6_to_str((struct e_in6_addr*)&addr_ipv6));
+ break;
+ default:
+ break;
+ }
+
+ offset = offset + 1 + ggsn_addr_len;
+
+ if (gtp_version == 1) {
+
+ ggsn_addr_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset, 1, "GGSN 2 address length: %u", ggsn_addr_len);
+
+ switch (ggsn_addr_len) {
+ case 4:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset+1, sizeof addr_ipv4);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+1, 4, "GGSN 2 address: %s", ip_to_str((guint8 *)&addr_ipv4));
+ break;
+ case 16:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset+1, sizeof addr_ipv6);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset+1, 16, "GGSN 2 address: %s", ip6_to_str((struct e_in6_addr*)&addr_ipv6));
+ break;
+ default:
+ break;
+ }
+ offset = offset + 1 + ggsn_addr_len;
+
+ }
+
+ apn_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset, 1, "APN length: %u", apn_len);
+ decode_apn(tvb, offset+1, apn_len, ext_tree_pdp);
+
+ offset = offset + 1 + apn_len;
+
+ trans_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ext_tree_pdp, tvb, offset, 1, "Transaction identifier: %u", trans_id);
+
+ return 3+length;
+}
+
+/* GPRS: 9.60, v7.6.0, chapter 7.9.21
+ * UMTS: 29.060, v4.0, chapter 7.7.30
+ */
+static int
+decode_gtp_apn(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length;
+ proto_tree *ext_tree_apn;
+ proto_item *te;
+
+ length = tvb_get_ntohs(tvb, offset+1);
+
+ te = proto_tree_add_text (tree, tvb, offset, length+3, val_to_str(GTP_EXT_APN, gtp_val, "Unknown field"));
+ ext_tree_apn = proto_item_add_subtree(te, ett_gtp_apn);
+
+ proto_tree_add_text (ext_tree_apn, tvb, offset+1, 2, "APN length : %u", length);
+ decode_apn (tvb, offset+3, length, ext_tree_apn);
+
+ return 3+length;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.22
+ * 4.08 v. 7.1.2, chapter 10.5.6.3 (p.580)
+ * UMTS: 29.060 v4.0, chapter 7.7.31
+ * 24.008, v4.2, chapter 10.5.6.3
+ */
+int
+decode_gtp_proto_conf(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+
+ guint16 length, proto_offset;
+ guint16 proto_id;
+ guint8 conf, proto_len, cnt = 1;
+ tvbuff_t *next_tvb;
+ proto_tree *ext_tree_proto;
+ proto_item *te;
+ gboolean save_writable;
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+
+ te = proto_tree_add_text(tree, tvb, offset, length + 3, val_to_str(GTP_EXT_PROTO_CONF, gtp_val, "Unknown message"));
+ ext_tree_proto = proto_item_add_subtree(te, ett_gtp_proto);
+
+ proto_tree_add_text(ext_tree_proto, tvb, offset + 1, 2, "Length: %u", length);
+
+ if (length < 1) return 3;
+
+ conf = tvb_get_guint8 (tvb, offset + 3) & 0x07;
+ proto_tree_add_text (ext_tree_proto, tvb, offset + 3, 1, "Configuration protocol (00000xxx): %u", conf);
+
+ proto_offset = 1; /* ... 1st byte is conf */
+ offset += 4;
+
+ for (;;) {
+ if (proto_offset >= length) break;
+ proto_id = tvb_get_ntohs (tvb, offset);
+ proto_len = tvb_get_guint8 (tvb, offset + 2);
+ proto_offset += proto_len + 3; /* 3 = proto id + length byte */
+
+ if (proto_len > 0) {
+
+ proto_tree_add_text (ext_tree_proto, tvb, offset, 2, "Protocol %u ID: %s (0x%04x)",
+ cnt, val_to_str(proto_id, ppp_vals, "Unknown"),
+ proto_id);
+ proto_tree_add_text (ext_tree_proto, tvb, offset+2, 1, "Protocol %u length: %u", cnt, proto_len);
+
+ /*
+ * Don't allow the dissector for the configuration
+ * protocol in question to update the columns - this
+ * is GTP, not PPP.
+ */
+ save_writable = col_get_writable(pinfo->cinfo);
+ col_set_writable(pinfo->cinfo, FALSE);
+
+ /*
+ * XXX - should we have our own dissector table,
+ * solely for configuration protocols, so that bogus
+ * values don't cause us to dissect the protocol
+ * data as, for example, IP?
+ */
+ next_tvb = tvb_new_subset (tvb, offset + 3, proto_len, proto_len);
+ if (!dissector_try_port(ppp_subdissector_table,
+ proto_id, next_tvb, pinfo, ext_tree_proto)) {
+ call_dissector(data_handle, next_tvb, pinfo,
+ ext_tree_proto);
+ }
+
+ col_set_writable(pinfo->cinfo, save_writable);
+ }
+
+ offset += proto_len + 3;
+ cnt++;
+ }
+
+ return 3 + length;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.23
+ * UMTS: 29.060 v4.0, chapter 7.7.32
+ */
+static int
+decode_gtp_gsn_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint8 addr_type, addr_len;
+ guint16 length;
+ guint32 addr_ipv4;
+ struct e_in6_addr addr_ipv6;
+ proto_tree *ext_tree_gsn_addr;
+ proto_item *te;
+
+ length = tvb_get_ntohs(tvb, offset+1);
+
+ te = proto_tree_add_text(tree, tvb, offset, 3+length, "GSN address : ");
+ ext_tree_gsn_addr = proto_item_add_subtree(te, ett_gtp_gsn_addr);
+
+ switch (length) {
+ case 4:
+ proto_tree_add_text(ext_tree_gsn_addr, tvb, offset+1, 2, "GSN address length : %u", length);
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset+3, sizeof addr_ipv4);
+ proto_item_append_text(te, "%s", ip_to_str((guint8 *)&addr_ipv4));
+ proto_tree_add_ipv4(ext_tree_gsn_addr, hf_gtp_gsn_ipv4, tvb, offset+3, 4, addr_ipv4);
+ break;
+ case 5:
+ proto_tree_add_text(ext_tree_gsn_addr, tvb, offset+1, 2, "GSN address Information Element length : %u", length);
+ addr_type = tvb_get_guint8(tvb, offset+3) & 0xC0;
+ proto_tree_add_uint(ext_tree_gsn_addr, hf_gtp_gsn_addr_type, tvb, offset+3, 1, addr_type);
+ addr_len = tvb_get_guint8(tvb, offset+3) & 0x3F;
+ proto_tree_add_uint(ext_tree_gsn_addr, hf_gtp_gsn_addr_len, tvb, offset+3, 1, addr_len);
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset+4, sizeof addr_ipv4);
+ proto_item_append_text(te, "%s", ip_to_str((guint8 *)&addr_ipv4));
+ proto_tree_add_ipv4(ext_tree_gsn_addr, hf_gtp_gsn_ipv4, tvb, offset+4, 4, addr_ipv4);
+ break;
+ case 16:
+ proto_tree_add_text(ext_tree_gsn_addr, tvb, offset+1, 2, "GSN address length : %u", length);
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset+3, sizeof addr_ipv6);
+ proto_item_append_text(te, "%s", ip6_to_str((struct e_in6_addr*)&addr_ipv6));
+ proto_tree_add_ipv6(ext_tree_gsn_addr, hf_gtp_gsn_ipv6, tvb, offset+3, 16, (guint8*)&addr_ipv6);
+ break;
+ case 17:
+ proto_tree_add_text(ext_tree_gsn_addr, tvb, offset+1, 2, "GSN address Information Element length : %u", length);
+ addr_type = tvb_get_guint8(tvb, offset+3) & 0xC0;
+ proto_tree_add_uint(ext_tree_gsn_addr, hf_gtp_gsn_addr_type, tvb, offset+3, 1, addr_type);
+ addr_len = tvb_get_guint8(tvb, offset+3) & 0x3F;
+ proto_tree_add_uint(ext_tree_gsn_addr, hf_gtp_gsn_addr_len, tvb, offset+3, 1, addr_len);
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset+4, sizeof addr_ipv6);
+ proto_item_append_text(te, "%s", ip6_to_str((struct e_in6_addr*)&addr_ipv6));
+ proto_tree_add_ipv6(ext_tree_gsn_addr, hf_gtp_gsn_ipv6, tvb, offset+4, 16, (guint8*)&addr_ipv6);
+ break;
+ default:
+ proto_item_append_text(te, "unknown type or wrong length");
+ break;
+ }
+
+ return 3+length;
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.24
+ * UMTS: 29.060 v4.0, chapter 7.7.33
+ */
+static int
+decode_gtp_msisdn(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ const guint8 *msisdn_val;
+ gchar *msisdn_str;
+ guint16 length;
+
+ length = tvb_get_ntohs(tvb, offset+1);
+
+ if (length < 1) return 3;
+
+ msisdn_val = tvb_get_ptr(tvb, offset+3, length);
+ msisdn_str = msisdn_to_str(msisdn_val, length);
+
+ proto_tree_add_string(tree, hf_gtp_msisdn, tvb, offset, 3+length, msisdn_str);
+
+ return 3+length;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.34
+ * 24.008 v4.2, chapter 10.5.6.5
+ */
+static int
+decode_gtp_qos_umts(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ return decode_qos_umts(tvb, offset, tree, "Quality of Service", 2);
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.35
+ */
+static int
+decode_gtp_auth_qui(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ return (1 + decode_quintuplet(tvb, offset+1, tree, 1, 1));
+
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.36
+ * 24.008 v4.2, chapter 10.5.6.12
+ */
+static int
+decode_gtp_tft(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length, port1, port2, tos;
+ guint8 tft_flags, tft_code, no_packet_filters, i, pf_id, pf_eval, pf_len, pf_content_id, proto, spare;
+ guint pf_offset;
+ guint32 mask_ipv4, addr_ipv4, ipsec_id, label;
+ struct e_in6_addr addr_ipv6, mask_ipv6;
+ proto_tree *ext_tree_tft, *ext_tree_tft_pf, *ext_tree_tft_flags;
+ proto_item *te, *tee, *tef;
+
+ length = tvb_get_ntohs(tvb, offset+1);
+
+ te = proto_tree_add_text(tree, tvb, offset, 3+length, "Traffic flow template");
+ ext_tree_tft = proto_item_add_subtree(te, ett_gtp_tft);
+
+ tft_flags = tvb_get_guint8(tvb, offset+3);
+ tft_code = (tft_flags >> 5) & 0x07;
+ spare = (tft_flags >> 4) & 0x01;
+ no_packet_filters = tft_flags & 0x0F;
+
+ proto_tree_add_text(ext_tree_tft, tvb, offset+1, 2, "TFT length: %u", length);
+
+ tef = proto_tree_add_text (ext_tree_tft, tvb, offset + 3, 1, "TFT flags");
+ ext_tree_tft_flags = proto_item_add_subtree (tef, ett_gtp_tft_flags);
+ proto_tree_add_uint (ext_tree_tft_flags, hf_gtp_tft_code, tvb, offset + 3, 1, tft_flags);
+ proto_tree_add_uint (ext_tree_tft_flags, hf_gtp_tft_spare, tvb, offset + 3, 1, tft_flags);
+ proto_tree_add_uint (ext_tree_tft_flags, hf_gtp_tft_number, tvb, offset + 3, 1, tft_flags);
+
+ offset = offset + 4;
+
+ for (i=0;i<no_packet_filters;i++) {
+
+ pf_id = tvb_get_guint8(tvb, offset);
+
+ tee = proto_tree_add_text (ext_tree_tft, tvb, offset, 1, "Packet filter id: %u", pf_id);
+ ext_tree_tft_pf = proto_item_add_subtree (tee, ett_gtp_tft_pf);
+ offset++;
+
+ if (tft_code != 2) {
+
+ pf_eval = tvb_get_guint8(tvb, offset);
+ pf_len = tvb_get_guint8(tvb, offset + 1);
+
+ proto_tree_add_uint (ext_tree_tft_pf, hf_gtp_tft_eval, tvb, offset, 1, pf_eval);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset+1, 1, "Content length: %u", pf_len);
+
+ offset = offset + 2;
+ pf_offset = 0;
+
+ while (pf_offset < pf_len) {
+
+ pf_content_id = tvb_get_guint8 (tvb, offset + pf_offset);
+
+ switch (pf_content_id) {
+ /* address IPv4 and mask = 8 bytes*/
+ case 0x10:
+ tvb_memcpy (tvb, (guint8 *)&addr_ipv4, offset + pf_offset + 1, sizeof addr_ipv4);
+ tvb_memcpy (tvb, (guint8 *)&mask_ipv4, offset + pf_offset + 5, sizeof mask_ipv4);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 9, "ID 0x10: IPv4/mask: %s/%s", ip_to_str ((guint8 *)&addr_ipv4), ip_to_str ((guint8 *)&mask_ipv4));
+ pf_offset = pf_offset + 9;
+ break;
+ /* address IPv6 and mask = 32 bytes*/
+ case 0x20:
+ tvb_memcpy (tvb, (guint8 *)&addr_ipv6, offset+pf_offset+1, sizeof addr_ipv6);
+ tvb_memcpy (tvb, (guint8 *)&mask_ipv6, offset+pf_offset+17, sizeof mask_ipv6);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset+pf_offset, 33, "ID 0x20: IPv6/mask: %s/%s", ip6_to_str ((struct e_in6_addr*)&addr_ipv6), ip6_to_str ((struct e_in6_addr*)&mask_ipv6));
+ pf_offset = pf_offset + 33;
+ break;
+ /* protocol identifier/next header type = 1 byte*/
+ case 0x30:
+ proto = tvb_get_guint8 (tvb, offset + pf_offset + 1);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 2, "ID 0x30: IPv4 protocol identifier/IPv6 next header: %u (%x)", proto, proto);
+ pf_offset = pf_offset + 2;
+ break;
+ /* single destination port type = 2 bytes */
+ case 0x40:
+ port1 = tvb_get_ntohs (tvb, offset + pf_offset + 1);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 3, "ID 0x40: destination port: %u", port1);
+ pf_offset = pf_offset + 3;
+ break;
+ /* destination port range type = 4 bytes */
+ case 0x41:
+ port1 = tvb_get_ntohs (tvb, offset + pf_offset + 1);
+ port2 = tvb_get_ntohs (tvb, offset + pf_offset + 3);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 5, "ID 0x41: destination port range: %u - %u", port1, port2);
+ pf_offset = pf_offset + 5;
+ break;
+ /* single source port type = 2 bytes */
+ case 0x50:
+ port1 = tvb_get_ntohs (tvb, offset + pf_offset + 1);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 3, "ID 0x50: source port: %u", port1);
+ pf_offset = pf_offset + 3;
+ break;
+ /* source port range type = 4 bytes */
+ case 0x51:
+ port1 = tvb_get_ntohs (tvb, offset + pf_offset + 1);
+ port2 = tvb_get_ntohs (tvb, offset + pf_offset + 3);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 5, "ID 0x51: source port range: %u - %u", port1, port2);
+ pf_offset = pf_offset + 5;
+ break;
+ /* security parameter index type = 4 bytes */
+ case 0x60:
+ ipsec_id = tvb_get_ntohl (tvb, offset + pf_offset + 1);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 5, "ID 0x60: security parameter index: %x", ipsec_id);
+ pf_offset = pf_offset + 5;
+ break;
+ /* type of service/traffic class type = 2 bytes */
+ case 0x70:
+ tos = tvb_get_ntohs (tvb, offset + pf_offset + 1);
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 2, "ID 0x70: Type of Service/Traffic Class: %u (%x)", tos, tos);
+ pf_offset = pf_offset + 3;
+ break;
+ /* flow label type = 3 bytes */
+ case 0x80:
+ label = tvb_get_ntoh24(tvb, offset + pf_offset + 1) & 0x0FFFFF;
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 4, "ID 0x80: Flow Label: %u (%x)", label, label);
+ pf_offset = pf_offset + 4;
+ break;
+
+ default:
+ proto_tree_add_text (ext_tree_tft_pf, tvb, offset + pf_offset, 1, "Unknown value: %x ", pf_content_id);
+ pf_offset++; /* to avoid infinite loop */
+ break;
+ }
+ }
+
+ offset = offset + pf_offset;
+ }
+ }
+
+ return 3 + length;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.37
+ * 25.413 v3.4, chapter ???
+ */
+static int
+decode_gtp_target_id(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length;
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+
+ proto_tree_add_text(tree, tvb, offset, 3 + length, "Targer Identification");
+
+ return 3 + length;
+}
+
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.38
+ */
+static int
+decode_gtp_utran_cont(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length;
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+
+ proto_tree_add_text(tree, tvb, offset, 3 + length, "UTRAN transparent field");
+
+ return 3 + length;
+
+}
+
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.39
+ */
+static int
+decode_gtp_rab_setup(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint32 teid, addr_ipv4;
+ guint16 length;
+ guint8 nsapi;
+ struct e_in6_addr addr_ipv6;
+ proto_tree *ext_tree_rab_setup;
+ proto_item *te;
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+ nsapi = tvb_get_guint8(tvb, offset + 3) & 0x0F;
+
+ te = proto_tree_add_text(tree, tvb, offset, 3+length, "Radio Access Bearer Setup Information");
+ ext_tree_rab_setup = proto_item_add_subtree(te, ett_gtp_rab_setup);
+
+ proto_tree_add_text(ext_tree_rab_setup, tvb, offset+1, 2, "RAB setup length : %u", length);
+ proto_tree_add_uint(ext_tree_rab_setup, hf_gtp_nsapi, tvb, offset+3, 1, nsapi);
+
+ if (length > 1) {
+
+ teid = tvb_get_ntohl(tvb, offset + 4);
+
+ proto_tree_add_uint(ext_tree_rab_setup, hf_gtp_teid_data, tvb, offset+4, 4, teid);
+
+ switch (length) {
+ case 12:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset+8, sizeof addr_ipv4);
+ proto_tree_add_ipv4(ext_tree_rab_setup, hf_gtp_rnc_ipv4, tvb, offset+8, 4, addr_ipv4);
+ break;
+ case 24:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset+8, sizeof addr_ipv6);
+ proto_tree_add_ipv6(ext_tree_rab_setup, hf_gtp_rnc_ipv6, tvb, offset+8, 16, (guint8 *)&addr_ipv6);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 3 + length;
+}
+
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.40
+ */
+static int
+decode_gtp_hdr_list(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ int i;
+ guint8 length, hdr;
+ proto_tree *ext_tree_hdr_list;
+ proto_item *te;
+
+ length = tvb_get_guint8(tvb, offset + 1);
+
+ te = proto_tree_add_text(tree, tvb, offset, 2+length, "%s", val_to_str(GTP_EXT_HDR_LIST, gtp_val, "Unknown"));
+ ext_tree_hdr_list = proto_item_add_subtree(te, ett_gtp_hdr_list);
+
+ proto_tree_add_text(ext_tree_hdr_list, tvb, offset+1, 1, "Number of Extension Header Types in list (i.e., length) : %u", length);
+
+ for(i=0 ; i<length ; i++) {
+ hdr = tvb_get_guint8(tvb, offset+2+i);
+
+ proto_tree_add_text(ext_tree_hdr_list, tvb, offset+2+i, 1, "No. %u --> Extension Header Type value : %s (%u)", i+1, val_to_str(hdr, gtp_val, "Unknown Extension Header Type"), hdr);
+ }
+
+ return 2 + length;
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.41
+ * TODO: find TriggerID description
+ */
+static int
+decode_gtp_trigger_id(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length;
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+
+ proto_tree_add_text(tree, tvb, offset, 3+length, "%s length : %u", val_to_str(GTP_EXT_TRIGGER_ID, gtp_val, "Unknown"), length);
+
+ return 3 + length;
+
+}
+
+/* GPRS: not present
+ * UMTS: 29.060 v4.0, chapter 7.7.42
+ * TODO: find OMC-ID description
+ */
+static int
+decode_gtp_omc_id(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length;
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+
+ proto_tree_add_text(tree, tvb, offset, 3+length, "%s length : %u", val_to_str(GTP_EXT_OMC_ID, gtp_val, "Unknown"), length);
+
+ return 3 + length;
+
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.25
+ * UMTS: 29.060 v4.0, chapter 7.7.43
+ */
+static int
+decode_gtp_chrg_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length;
+ guint32 addr_ipv4;
+ struct e_in6_addr addr_ipv6;
+ proto_tree *ext_tree_chrg_addr;
+ proto_item *te;
+
+ length = tvb_get_ntohs(tvb, offset+1);
+
+ te = proto_tree_add_text(tree, tvb, offset, 3+length, "%s : ", val_to_str(GTP_EXT_CHRG_ADDR, gtp_val, "Unknown"));
+ ext_tree_chrg_addr = proto_item_add_subtree(te, ett_gtp_chrg_addr);
+
+ proto_tree_add_text(ext_tree_chrg_addr, tvb, offset+1, 2, "%s length : %u", val_to_str(GTP_EXT_CHRG_ADDR, gtp_val, "Unknown"), length);
+
+ switch (length) {
+ case 4:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset+3, sizeof addr_ipv4);
+ proto_item_append_text(te, "%s", ip_to_str((guint8 *)&addr_ipv4));
+ proto_tree_add_ipv4 (ext_tree_chrg_addr, hf_gtp_chrg_ipv4, tvb, offset+3, 4, addr_ipv4);
+ break;
+ case 16:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset+3, sizeof addr_ipv6);
+ proto_item_append_text(te, "%s", ip6_to_str((struct e_in6_addr*)&addr_ipv6));
+ proto_tree_add_ipv6 (ext_tree_chrg_addr, hf_gtp_chrg_ipv6, tvb, offset+3, 16, (guint8*)&addr_ipv6);
+ break;
+ default:
+ proto_item_append_text(te, "unknown type or wrong length");
+ break;
+ }
+
+ return 3 + length;
+}
+
+/* GPRS: 12.15
+ * UMTS: 33.015
+ */
+static int
+decode_gtp_rel_pack(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length, n, number;
+ proto_tree *ext_tree_rel_pack;
+ proto_item *te;
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+
+ te = proto_tree_add_text(tree, tvb, offset, 3 + length, "Sequence numbers of released packets IE");
+ ext_tree_rel_pack = proto_item_add_subtree(te, ett_gtp_rel_pack);
+
+ n = 0;
+
+ while (n < length) {
+
+ number = tvb_get_ntohs(tvb, offset + 3 + n);
+ proto_tree_add_text(ext_tree_rel_pack, tvb, offset + 3 + n, 2, "%u", number);
+ n = n + 2;
+
+ }
+
+ return 3 + length;
+}
+
+/* GPRS: 12.15
+ * UMTS: 33.015
+ */
+static int
+decode_gtp_can_pack(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length, n, number;
+ proto_tree *ext_tree_can_pack;
+ proto_item *te;
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+
+ te = proto_tree_add_text(tree, tvb, offset, 3 + length, "Sequence numbers of cancelled packets IE");
+ ext_tree_can_pack = proto_item_add_subtree(te, ett_gtp_can_pack);
+
+ n = 0;
+
+ while (n < length) {
+
+ number = tvb_get_ntohs(tvb, offset + 3 + n);
+ proto_tree_add_text(ext_tree_can_pack, tvb, offset + 3 + n, 2, "%u", number);
+ n = n + 2;
+ }
+
+ return 3 + length;
+}
+
+/* CDRs dissector */
+static int
+decode_gtp_data_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length, format_ver;
+ guint8 no, format;
+ proto_tree *ext_tree;
+ proto_item *te;
+ tvbuff_t *next_tvb;
+
+ te = proto_tree_add_text(tree, tvb, offset, 1, val_to_str(GTP_EXT_DATA_REQ, gtp_val, "Unknown message"));
+ ext_tree = proto_item_add_subtree(te, ett_gtp_ext);
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+ no = tvb_get_guint8(tvb, offset + 3);
+ format = tvb_get_guint8(tvb, offset + 4);
+ format_ver = tvb_get_ntohs(tvb, offset + 5);
+
+ proto_tree_add_text(ext_tree, tvb, offset+1, 2, "Length: %u", length);
+ proto_tree_add_text(ext_tree, tvb, offset+3, 1, "Number of data records: %u", no);
+ proto_tree_add_text(ext_tree, tvb, offset+4, 1, "Data record format: %u", format);
+ proto_tree_add_text(ext_tree, tvb, offset+5, 2, "Data record format version: %u", format_ver);
+
+ if (gtpcdr_handle) {
+ next_tvb = tvb_new_subset (tvb, offset, -1, -1);
+ call_dissector (gtpcdr_handle, next_tvb, pinfo, tree);
+ }
+ else
+ proto_tree_add_text (tree, tvb, offset, 0, "Data");
+
+ return 3+length;
+}
+
+/* GPRS: 12.15
+ * UMTS: 33.015
+ */
+static int
+decode_gtp_data_resp(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length, n, number;
+ proto_tree *ext_tree_data_resp;
+ proto_item *te;
+
+ length = tvb_get_ntohs(tvb, offset + 1);
+
+ te = proto_tree_add_text(tree, tvb, offset, 3 + length, "Requests responded");
+ ext_tree_data_resp = proto_item_add_subtree(te, ett_gtp_data_resp);
+
+ n = 0;
+
+ while (n < length) {
+
+ number = tvb_get_ntohs(tvb, offset + 3 + n);
+ proto_tree_add_text(ext_tree_data_resp, tvb, offset + 3 + n, 2, "%u", number);
+ n = n + 2;
+
+ }
+
+ return 3 + length;
+
+}
+
+/* GPRS: 12.15
+ * UMTS: 33.015
+ */
+static int
+decode_gtp_node_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length;
+ guint32 addr_ipv4;
+ struct e_in6_addr addr_ipv6;
+ proto_tree *ext_tree_node_addr;
+ proto_item *te;
+
+ length = tvb_get_ntohs(tvb, offset+1);
+
+ te = proto_tree_add_text(tree, tvb, offset, 3+length, "Node address: ");
+ ext_tree_node_addr = proto_item_add_subtree(te, ett_gtp_node_addr);
+
+ proto_tree_add_text (ext_tree_node_addr, tvb, offset+1, 2, "Node address length: %u", length);
+
+ switch (length) {
+ case 4:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset+3, sizeof addr_ipv4);
+ proto_item_append_text(te, "%s", ip_to_str((guint8 *)&addr_ipv4));
+ proto_tree_add_ipv4 (ext_tree_node_addr, hf_gtp_node_ipv4, tvb, offset+3, 4, addr_ipv4);
+ break;
+ case 16:
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset+3, sizeof addr_ipv6);
+ proto_item_append_text(te, "%s", ip6_to_str((struct e_in6_addr*)&addr_ipv6));
+ proto_tree_add_ipv6 (ext_tree_node_addr, hf_gtp_node_ipv6, tvb, offset+3, 16, (guint8*)&addr_ipv6);
+ break;
+ default:
+ proto_item_append_text(te, "unknown type or wrong length");
+ break;
+ }
+
+ return 3 + length;
+
+}
+
+/* GPRS: 9.60 v7.6.0, chapter 7.9.26
+ * UMTS: 29.060 v4.0, chapter 7.7.44
+ */
+static int
+decode_gtp_priv_ext(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ guint16 length, ext_id;
+ proto_tree *ext_tree_priv_ext;
+ proto_item *te;
+
+ te = proto_tree_add_text(tree, tvb, offset, 1, val_to_str(GTP_EXT_PRIV_EXT, gtp_val, "Unknown message"));
+ ext_tree_priv_ext = proto_item_add_subtree(te, ett_gtp_ext);
+
+ length = tvb_get_ntohs(tvb, offset+1);
+ if (length >= 2) {
+ ext_id = tvb_get_ntohs(tvb, offset+3);
+ proto_tree_add_uint(ext_tree_priv_ext, hf_gtp_ext_id, tvb, offset+3, 2, ext_id);
+
+ /*
+ * XXX - is this always a text string? Or should it be
+ * displayed as hex data?
+ */
+ if (length > 2)
+ proto_tree_add_item(ext_tree_priv_ext, hf_gtp_ext_val, tvb, offset+5, length-2, FALSE);
+ }
+
+ return 3+length;
+}
+
+static int
+decode_gtp_unknown(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) {
+
+ proto_tree_add_text(tree, tvb, offset, 1, "Unknown extension header");
+
+ return tvb_length_remaining(tvb, offset);
+}
+
+static void
+dissect_gtp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct _gtp_hdr gtp_hdr;
+ proto_tree *gtp_tree, *flags_tree;
+ proto_item *ti, *tf;
+ int i, offset, length, gtp_prime, checked_field, mandatory;
+ int seq_no, flow_label;
+ guint8 pdu_no, next_hdr = 0, ext_hdr_val;
+ const guint8 *tid_val;
+ gchar *tid_str;
+ guint32 teid;
+ tvbuff_t *next_tvb;
+ guint8 sub_proto, acfield_len = 0, control_field;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GTP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb, (guint8 *)&gtp_hdr, 0, 4);
+
+ if (!(gtp_hdr.flags & 0x10))
+ gtp_prime = 1;
+ else
+ gtp_prime = 0;
+
+ switch ((gtp_hdr.flags >> 5) & 0x07) {
+ case 0:
+ gtp_version = 0;
+ break;
+ case 1:
+ gtp_version = 1;
+ break;
+ default:
+ gtp_version = 1;
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(gtp_hdr.message, message_type, "Unknown"));
+
+ if (tree) {
+ ti = proto_tree_add_item (tree, proto_gtp, tvb, 0, -1, FALSE);
+ gtp_tree = proto_item_add_subtree(ti, ett_gtp);
+
+ tf = proto_tree_add_uint (gtp_tree, hf_gtp_flags, tvb, 0, 1, gtp_hdr.flags);
+ flags_tree = proto_item_add_subtree (tf, ett_gtp_flags);
+
+ proto_tree_add_uint (flags_tree, hf_gtp_flags_ver, tvb, 0, 1, gtp_hdr.flags);
+ proto_tree_add_uint (flags_tree, hf_gtp_flags_pt, tvb, 0, 1, gtp_hdr.flags);
+
+ switch (gtp_version) {
+ case 0:
+ proto_tree_add_uint (flags_tree, hf_gtp_flags_spare1, tvb, 0, 1, gtp_hdr.flags);
+ proto_tree_add_boolean (flags_tree, hf_gtp_flags_snn, tvb, 0, 1, gtp_hdr.flags);
+ break;
+ case 1:
+ proto_tree_add_uint (flags_tree, hf_gtp_flags_spare2, tvb, 0, 1, gtp_hdr.flags);
+ proto_tree_add_boolean (flags_tree, hf_gtp_flags_e, tvb, 0, 1, gtp_hdr.flags);
+ proto_tree_add_boolean (flags_tree, hf_gtp_flags_s, tvb, 0, 1, gtp_hdr.flags);
+ proto_tree_add_boolean (flags_tree, hf_gtp_flags_pn, tvb, 0, 1, gtp_hdr.flags);
+ break;
+ default:
+ break;
+ }
+
+ proto_tree_add_uint (gtp_tree, hf_gtp_message_type, tvb, 1, 1, gtp_hdr.message);
+
+ gtp_hdr.length = g_ntohs (gtp_hdr.length);
+ proto_tree_add_uint (gtp_tree, hf_gtp_length, tvb, 2, 2, gtp_hdr.length);
+
+ offset = 4;
+
+ if (gtp_prime) {
+ seq_no = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_uint (gtp_tree, hf_gtp_seq_number, tvb, offset, 2, seq_no);
+ offset += 2;
+ } else
+ switch (gtp_version) {
+ case 0:
+ seq_no = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_uint (gtp_tree, hf_gtp_seq_number, tvb, offset, 2, seq_no);
+ offset += 2;
+
+ flow_label = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_uint (gtp_tree, hf_gtp_flow_label, tvb, offset, 2, flow_label);
+ offset += 2;
+
+ pdu_no = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_uint (gtp_tree, hf_gtp_sndcp_number, tvb, offset, 1, pdu_no);
+ offset += 4;
+
+ tid_val = tvb_get_ptr(tvb, offset, 8);
+ tid_str = id_to_str (tid_val);
+ proto_tree_add_string (gtp_tree, hf_gtp_tid, tvb, offset, 8, tid_str);
+ offset += 8;
+ break;
+ case 1:
+ teid = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_uint (gtp_tree, hf_gtp_teid, tvb, offset, 4, teid);
+ offset += 4;
+
+ if (gtp_hdr.flags & 0x07) {
+ seq_no = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_uint (gtp_tree, hf_gtp_seq_number, tvb, offset, 2, seq_no);
+ offset += 2;
+
+ pdu_no = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_uint (gtp_tree, hf_gtp_npdu_number, tvb, offset, 1, pdu_no);
+ offset++;
+
+ next_hdr = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_uint (gtp_tree, hf_gtp_next, tvb, offset, 1, next_hdr);
+ if (!next_hdr)
+ offset++;
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ if (gtp_hdr.message != GTP_MSG_TPDU) {
+ proto_tree_add_text(gtp_tree, tvb, 0, 0, "[--- end of GTP header, beginning of extension headers ---]");
+ length = tvb_length (tvb);
+ mandatory = 0; /* check order of GTP fields against ETSI */
+ for (;;) {
+ if (offset >= length)
+ break;
+ if (next_hdr) {
+ ext_hdr_val = next_hdr;
+ next_hdr = 0;
+ }
+ else
+ ext_hdr_val = tvb_get_guint8 (tvb, offset);
+ if (gtp_etsi_order) {
+ checked_field = check_field_presence (gtp_hdr.message, ext_hdr_val , (int *)&mandatory);
+ switch (checked_field) {
+ case -2: proto_tree_add_text (gtp_tree, tvb, 0, 0, "[WARNING] message not found");
+ break;
+ case -1: proto_tree_add_text (gtp_tree, tvb, 0, 0, "[WARNING] field not present");
+ break;
+ case 0: break;
+ default: proto_tree_add_text (gtp_tree, tvb, offset, 1, "[WARNING] wrong next field, should be: %s", val_to_str(checked_field, gtp_val, "Unknown extension field"));
+ break;
+ }
+ }
+
+ i = -1;
+ while (gtpopt[++i].optcode)
+ if (gtpopt[i].optcode == ext_hdr_val)
+ break;
+ offset = offset + (*gtpopt[i].decode)(tvb, offset, pinfo, gtp_tree);
+ }
+ }
+ }
+
+ if ((gtp_hdr.message == GTP_MSG_TPDU) && gtp_tpdu) {
+
+ if (gtp_prime)
+ offset = 6;
+ else
+ if (gtp_version == 1) {
+ if (gtp_hdr.flags & 0x07) {
+ offset = 11;
+ if (tvb_get_guint8 (tvb, offset) == 0)
+ offset++;
+ }
+ else
+ offset = 8;
+ }
+ else
+ offset = 20;
+
+ sub_proto = tvb_get_guint8 (tvb, offset);
+
+ if ((sub_proto >= 0x45) && (sub_proto <= 0x4e)) {
+ /* this is most likely an IPv4 packet
+ * we can exclude 0x40 - 0x44 because the minimum header size is 20 octets
+ * 0x4f is excluded because PPP protocol type "IPv6 header compression"
+ * with protocol field compression is more likely than a plain IPv4 packet with 60 octet header size */
+
+ next_tvb = tvb_new_subset (tvb, offset, -1, -1);
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+
+ } else
+ if ((sub_proto & 0xf0) == 0x60){
+ /* this is most likely an IPv6 packet */
+ next_tvb = tvb_new_subset (tvb, offset, -1, -1);
+ call_dissector (ipv6_handle, next_tvb, pinfo, tree);
+ } else {
+ /* this seems to be a PPP packet */
+
+ if (sub_proto == 0xff) {
+ /* this might be an address field, even it shouldn't be here */
+ control_field = tvb_get_guint8 (tvb, offset + 1);
+ if (control_field == 0x03)
+ /* now we are pretty sure that address and control field are mistakenly inserted -> ignore it for PPP dissection */
+ acfield_len = 2;
+ }
+
+ next_tvb = tvb_new_subset (tvb, offset + acfield_len, -1, -1);
+ call_dissector (ppp_handle, next_tvb, pinfo, tree);
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_append_str_gtp(pinfo->cinfo, COL_PROTOCOL, "GTP");
+ }
+}
+
+static const true_false_string yes_no_tfs = {
+ "yes" ,
+ "no"
+};
+
+void
+proto_register_gtp(void)
+{
+ static hf_register_info hf_gtp[] = {
+ { &hf_gtp_apn, { "APN", "gtp.apn", FT_STRING, BASE_DEC, NULL, 0, "Access Point Name", HFILL }},
+ { &hf_gtp_cause, { "Cause ", "gtp.cause", FT_UINT8, BASE_DEC, VALS(cause_type), 0, "Cause of operation", HFILL }},
+ { &hf_gtp_chrg_char, { "Charging characteristics", "gtp.chrg_char", FT_UINT16, BASE_DEC, NULL, 0, "Charging characteristics", HFILL }},
+ { &hf_gtp_chrg_char_s, { "Spare", "gtp.chrg_char_s", FT_UINT16, BASE_DEC, NULL, GTP_MASK_CHRG_CHAR_S, "Spare", HFILL }},
+ { &hf_gtp_chrg_char_n, { "Normal charging", "gtp.chrg_char_n", FT_UINT16, BASE_DEC, NULL, GTP_MASK_CHRG_CHAR_N, "Normal charging", HFILL }},
+ { &hf_gtp_chrg_char_p, { "Prepaid charging", "gtp.chrg_char_p", FT_UINT16, BASE_DEC, NULL, GTP_MASK_CHRG_CHAR_P, "Prepaid charging", HFILL }},
+ { &hf_gtp_chrg_char_f, { "Flat rate charging", "gtp.chrg_char_f", FT_UINT16, BASE_DEC, NULL, GTP_MASK_CHRG_CHAR_F, "Flat rate charging", HFILL }},
+ { &hf_gtp_chrg_char_h, { "Hot billing charging", "gtp.chrg_char_h", FT_UINT16, BASE_DEC, NULL, GTP_MASK_CHRG_CHAR_H, "Hot billing charging", HFILL }},
+ { &hf_gtp_chrg_char_r, { "Reserved", "gtp.chrg_char_r", FT_UINT16, BASE_DEC, NULL, GTP_MASK_CHRG_CHAR_R, "Reserved", HFILL }},
+ { &hf_gtp_chrg_id, { "Charging ID", "gtp.chrg_id", FT_UINT32, BASE_HEX, NULL, 0, "Charging ID", HFILL }},
+ { &hf_gtp_chrg_ipv4, { "CG address IPv4", "gtp.chrg_ipv4", FT_IPv4, BASE_DEC, NULL, 0, "Charging Gateway address IPv4", HFILL }},
+ { &hf_gtp_chrg_ipv6, { "CG address IPv6", "gtp.chrg_ipv6", FT_IPv6, BASE_HEX, NULL, 0, "Charging Gateway address IPv6", HFILL }},
+ { &hf_gtp_ext_flow_label, { "Flow Label Data I", "gtp.ext_flow_label", FT_UINT16, BASE_HEX, NULL, 0, "Flow label data", HFILL }},
+ { &hf_gtp_ext_id, { "Extension identifier", "gtp.ext_id", FT_UINT16, BASE_DEC, NULL, 0, "Extension Identifier", HFILL }},
+ { &hf_gtp_ext_val, { "Extension value", "gtp.ext_val", FT_STRING, BASE_DEC, NULL, 0, "Extension Value", HFILL }},
+ { &hf_gtp_flags, { "Flags", "gtp.flags", FT_UINT8, BASE_HEX, NULL, 0, "Ver/PT/Spare...", HFILL }},
+ { &hf_gtp_flags_ver, { "Version", "gtp.flags.version", FT_UINT8, BASE_DEC, VALS(ver_types), GTP_VER_MASK, "GTP Version", HFILL }},
+ { &hf_gtp_flags_pt, { "Protocol type", "gtp.flags.payload", FT_UINT8, BASE_DEC, NULL, GTP_PT_MASK, "Protocol Type", HFILL }},
+ { &hf_gtp_flags_spare1, { "Reserved", "gtp.flags.reserved", FT_UINT8, BASE_DEC, NULL, GTP_SPARE1_MASK, "Reserved (shall be sent as '111' )", HFILL }},
+ { &hf_gtp_flags_snn, { "Is SNDCP N-PDU included?", "gtp.flags.snn", FT_BOOLEAN, 8, TFS(&yes_no_tfs), GTP_SNN_MASK, "Is SNDCP N-PDU LLC Number included? (1 = yes, 0 = no)", HFILL }},
+ { &hf_gtp_flags_spare2, { "Reserved", "gtp.flags.reserved", FT_UINT8, BASE_DEC, NULL, GTP_SPARE2_MASK, "Reserved (shall be sent as '1' )", HFILL }},
+ { &hf_gtp_flags_e, { "Is Next Extension Header present?", "gtp.flags.e", FT_BOOLEAN, 8, TFS(&yes_no_tfs), GTP_E_MASK, "Is Next Extension Header present? (1 = yes, 0 = no)", HFILL }},
+ { &hf_gtp_flags_s, { "Is Sequence Number present?", "gtp.flags.s", FT_BOOLEAN, 8, TFS(&yes_no_tfs), GTP_S_MASK, "Is Sequence Number present? (1 = yes, 0 = no)", HFILL }},
+ { &hf_gtp_flags_pn, { "Is N-PDU number present?", "gtp.flags.pn", FT_BOOLEAN, 8, TFS(&yes_no_tfs), GTP_PN_MASK, "Is N-PDU number present? (1 = yes, 0 = no)", HFILL }},
+ { &hf_gtp_flow_ii, { "Flow Label Data II ", "gtp.flow_ii", FT_UINT16, BASE_DEC, NULL, 0, "Downlink flow label data", HFILL }},
+ { &hf_gtp_flow_label, { "Flow label", "gtp.flow_label", FT_UINT16, BASE_HEX, NULL, 0, "Flow label", HFILL }},
+ { &hf_gtp_flow_sig, { "Flow label Signalling", "gtp.flow_sig", FT_UINT16, BASE_HEX, NULL, 0, "Flow label signalling", HFILL }},
+ { &hf_gtp_gsn_addr_len, { "GSN Address Length", "gtp.gsn_addr_len", FT_UINT8, BASE_DEC, NULL, GTP_EXT_GSN_ADDR_LEN_MASK, "GSN Address Length", HFILL }},
+ { &hf_gtp_gsn_addr_type, { "GSN Address Type", "gtp.gsn_addr_type", FT_UINT8, BASE_DEC, VALS(gsn_addr_type), GTP_EXT_GSN_ADDR_TYPE_MASK, "GSN Address Type", HFILL }},
+ { &hf_gtp_gsn_ipv4, { "GSN address IPv4", "gtp.gsn_ipv4", FT_IPv4, BASE_DEC, NULL, 0, "GSN address IPv4", HFILL }},
+ { &hf_gtp_gsn_ipv6, { "GSN address IPv6", "gtp.gsn_ipv6", FT_IPv6, BASE_DEC, NULL, 0, "GSN address IPv6", HFILL }},
+ { &hf_gtp_imsi, { "IMSI", "gtp.imsi", FT_STRING, BASE_DEC, NULL, 0, "International Mobile Subscriber Identity number", HFILL }},
+ { &hf_gtp_length, { "Length", "gtp.length", FT_UINT16, BASE_DEC, NULL, 0, "Length (i.e. number of octets after TID or TEID)", HFILL }},
+ { &hf_gtp_map_cause, { "MAP cause", "gtp.map_cause", FT_UINT8, BASE_DEC, VALS(map_cause_type), 0, "MAP cause", HFILL }},
+ { &hf_gtp_message_type, { "Message Type", "gtp.message", FT_UINT8, BASE_HEX, VALS(message_type), 0x0, "GTP Message Type", HFILL }},
+ { &hf_gtp_ms_reason, { "MS not reachable reason", "gtp.ms_reason", FT_UINT8, BASE_DEC, VALS(ms_not_reachable_type), 0, "MS Not Reachable Reason", HFILL }},
+ { &hf_gtp_ms_valid, { "MS validated", "gtp.ms_valid", FT_BOOLEAN, BASE_NONE,NULL, 0, "MS validated", HFILL }},
+ { &hf_gtp_msisdn, { "MSISDN", "gtp.msisdn", FT_STRING, BASE_DEC, NULL, 0, "MS international PSTN/ISDN number", HFILL }},
+ { &hf_gtp_next, { "Next extension header type", "gtp.next", FT_UINT8, BASE_HEX, NULL, 0, "Next Extension Header Type", HFILL }},
+ { &hf_gtp_node_ipv4, { "Node address IPv4", "gtp.node_ipv4", FT_IPv4, BASE_DEC, NULL, 0, "Recommended node address IPv4", HFILL }},
+ { &hf_gtp_node_ipv6, { "Node address IPv6", "gtp.node_ipv6", FT_IPv6, BASE_HEX, NULL, 0, "Recommended node address IPv6", HFILL }},
+ { &hf_gtp_npdu_number, { "N-PDU Number", "gtp.npdu_number", FT_UINT8, BASE_HEX, NULL, 0, "N-PDU Number", HFILL }},
+ { &hf_gtp_nsapi, { "NSAPI", "gtp.nsapi", FT_UINT8, BASE_DEC, NULL, 0, "Network layer Service Access Point Identifier", HFILL }},
+ { &hf_gtp_qos_spare1, { "Spare", "gtp.qos_spare1", FT_UINT8, BASE_DEC, NULL, GTP_EXT_QOS_SPARE1_MASK, "Spare (shall be sent as '00' )", HFILL }},
+ { &hf_gtp_qos_delay, { "QoS delay", "gtp.qos_delay", FT_UINT8, BASE_DEC, VALS(qos_delay_type), GTP_EXT_QOS_DELAY_MASK, "Quality of Service Delay Class", HFILL }},
+ { &hf_gtp_qos_reliability, { "QoS reliability", "gtp.qos_reliabilty", FT_UINT8, BASE_DEC, VALS(qos_reliability_type), GTP_EXT_QOS_RELIABILITY_MASK, "Quality of Service Reliability Class", HFILL }},
+ { &hf_gtp_qos_peak, { "QoS peak", "gtp.qos_peak", FT_UINT8, BASE_DEC, VALS(qos_peak_type), GTP_EXT_QOS_PEAK_MASK, "Quality of Service Peak Throughput", HFILL }},
+ { &hf_gtp_qos_spare2, { "Spare", "gtp.qos_spare2",FT_UINT8, BASE_DEC, NULL, GTP_EXT_QOS_SPARE2_MASK, "Spare (shall be sent as 0)", HFILL }},
+ { &hf_gtp_qos_precedence, { "QoS precedence", "gtp.qos_precedence", FT_UINT8, BASE_DEC, VALS(qos_precedence_type), GTP_EXT_QOS_PRECEDENCE_MASK, "Quality of Service Precedence Class", HFILL }},
+ { &hf_gtp_qos_spare3, { "Spare", "gtp.qos_spare3", FT_UINT8, BASE_DEC, NULL, GTP_EXT_QOS_SPARE3_MASK, "Spare (shall be sent as '000' )", HFILL }},
+ { &hf_gtp_qos_mean, { "QoS mean", "gtp.qos_mean", FT_UINT8, BASE_DEC, VALS(qos_mean_type), GTP_EXT_QOS_MEAN_MASK, "Quality of Service Mean Throughput", HFILL }},
+ { &hf_gtp_qos_al_ret_priority, { "Allocation/Retention priority ","gtp.qos_al_ret_priority", FT_UINT8, BASE_DEC, NULL, 0, "Allocation/Retention Priority", HFILL }},
+ { &hf_gtp_qos_traf_class, { "Traffic class", "gtp.qos_traf_class", FT_UINT8, BASE_DEC, VALS(qos_traf_class), GTP_EXT_QOS_TRAF_CLASS_MASK, "Traffic Class", HFILL }},
+ { &hf_gtp_qos_del_order, { "Delivery order", "gtp.qos_del_order", FT_UINT8, BASE_DEC, VALS(qos_del_order), GTP_EXT_QOS_DEL_ORDER_MASK, "Delivery Order", HFILL }},
+ { &hf_gtp_qos_del_err_sdu, { "Delivery of erroneous SDU", "gtp.qos_del_err_sdu", FT_UINT8, BASE_DEC, VALS(qos_del_err_sdu), GTP_EXT_QOS_DEL_ERR_SDU_MASK, "Delivery of Erroneous SDU", HFILL }},
+ { &hf_gtp_qos_max_sdu_size, { "Maximum SDU size", "gtp.qos_max_sdu_size", FT_UINT8, BASE_DEC, VALS(qos_max_sdu_size), 0, "Maximum SDU size", HFILL }},
+ { &hf_gtp_qos_max_ul, { "Maximum bit rate for uplink", "gtp.qos_max_ul", FT_UINT8, BASE_DEC, VALS(qos_max_ul), 0, "Maximum bit rate for uplink", HFILL }},
+ { &hf_gtp_qos_max_dl, { "Maximum bit rate for downlink", "gtp.qos_max_dl", FT_UINT8, BASE_DEC, VALS(qos_max_dl), 0, "Maximum bit rate for downlink", HFILL }},
+ { &hf_gtp_qos_res_ber, { "Residual BER", "gtp.qos_res_ber", FT_UINT8, BASE_DEC, VALS(qos_res_ber), GTP_EXT_QOS_RES_BER_MASK, "Residual Bit Error Rate", HFILL }},
+ { &hf_gtp_qos_sdu_err_ratio, { "SDU Error ratio", "gtp.qos_sdu_err_ratio", FT_UINT8, BASE_DEC, VALS(qos_sdu_err_ratio), GTP_EXT_QOS_SDU_ERR_RATIO_MASK, "SDU Error Ratio", HFILL }},
+ { &hf_gtp_qos_trans_delay, { "Transfer delay", "gtp.qos_trans_delay", FT_UINT8, BASE_DEC, VALS(qos_trans_delay), GTP_EXT_QOS_TRANS_DELAY_MASK, "Transfer Delay", HFILL }},
+ { &hf_gtp_qos_traf_handl_prio, { "Traffic handling priority", "gtp.qos_traf_handl_prio", FT_UINT8, BASE_DEC, VALS(qos_traf_handl_prio), GTP_EXT_QOS_TRAF_HANDL_PRIORITY_MASK, "Traffic Handling Priority", HFILL }},
+ { &hf_gtp_qos_guar_ul, { "Guaranteed bit rate for uplink", "gtp.qos_guar_ul", FT_UINT8, BASE_DEC, VALS(qos_guar_ul), 0, "Guaranteed bit rate for uplink", HFILL }},
+ { &hf_gtp_qos_guar_dl, { "Guaranteed bit rate for downlink", "gtp.qos_guar_dl", FT_UINT8, BASE_DEC, VALS(qos_guar_dl), 0, "Guaranteed bit rate for downlink", HFILL }},
+ { &hf_gtp_pkt_flow_id, { "Packet Flow ID", "gtp.pkt_flow_id", FT_UINT8, BASE_DEC, NULL, 0, "Packet Flow ID", HFILL }},
+ { &hf_gtp_ptmsi, { "P-TMSI", "gtp.ptmsi", FT_UINT32, BASE_HEX, NULL, 0, "Packet-Temporary Mobile Subscriber Identity", HFILL }},
+ { &hf_gtp_ptmsi_sig, { "P-TMSI Signature", "gtp.ptmsi_sig", FT_UINT24, BASE_HEX, NULL, 0, "P-TMSI Signature", HFILL }},
+ { &hf_gtp_rab_gtpu_dn, { "Downlink GTP-U seq number", "gtp.rab_gtp_dn", FT_UINT16, BASE_DEC, NULL, 0, "Downlink GTP-U sequence number", HFILL }},
+ { &hf_gtp_rab_gtpu_up, { "Uplink GTP-U seq number", "gtp.rab_gtp_up", FT_UINT16, BASE_DEC, NULL, 0, "Uplink GTP-U sequence number", HFILL }},
+ { &hf_gtp_rab_pdu_dn, { "Downlink next PDCP-PDU seq number", "gtp.rab_pdu_dn", FT_UINT8, BASE_DEC, NULL, 0, "Downlink next PDCP-PDU sequence number", HFILL }},
+ { &hf_gtp_rab_pdu_up, { "Uplink next PDCP-PDU seq number", "gtp.rab_pdu_up", FT_UINT8, BASE_DEC, NULL, 0, "Uplink next PDCP-PDU sequence number", HFILL }},
+ { &hf_gtp_rai_mcc, { "MCC", "gtp.mcc", FT_UINT16, BASE_DEC, NULL, 0, "Mobile Country Code", HFILL }},
+ { &hf_gtp_rai_mnc, { "MNC", "gtp.mnc", FT_UINT8, BASE_DEC, NULL, 0, "Mobile Network Code", HFILL }},
+ { &hf_gtp_rai_rac, { "RAC", "gtp.rac", FT_UINT8, BASE_DEC, NULL, 0, "Routing Area Code", HFILL }},
+ { &hf_gtp_rai_lac, { "LAC", "gtp.lac", FT_UINT16, BASE_DEC, NULL, 0, "Location Area Code", HFILL }},
+ { &hf_gtp_ranap_cause, { "RANAP cause", "gtp.ranap_cause", FT_UINT8, BASE_DEC, VALS(ranap_cause_type), 0, "RANAP cause", HFILL }},
+ { &hf_gtp_recovery, { "Recovery", "gtp.recovery", FT_UINT8, BASE_DEC, NULL, 0, "Restart counter", HFILL }},
+ { &hf_gtp_reorder, { "Reordering required","gtp.reorder", FT_BOOLEAN, BASE_NONE,NULL, 0, "Reordering required", HFILL }},
+ { &hf_gtp_rnc_ipv4, { "RNC address IPv4", "gtp.rnc_ipv4", FT_IPv4, BASE_DEC, NULL, 0, "Radio Network Controller address IPv4", HFILL }},
+ { &hf_gtp_rnc_ipv6, { "RNC address IPv6", "gtp.rnc_ipv6", FT_IPv6, BASE_HEX, NULL, 0, "Radio Network Controller address IPv6", HFILL }},
+ { &hf_gtp_rp, { "Radio Priority", "gtp.rp", FT_UINT8, BASE_DEC, NULL, GTPv1_EXT_RP_MASK, "Radio Priority for uplink tx", HFILL }},
+ { &hf_gtp_rp_nsapi, { "NSAPI in Radio Priority", "gtp.rp_nsapi", FT_UINT8, BASE_DEC, NULL, GTPv1_EXT_RP_NSAPI_MASK, "Network layer Service Access Point Identifier in Radio Priority", HFILL }},
+ { &hf_gtp_rp_sms, { "Radio Priority SMS", "gtp.rp_sms", FT_UINT8, BASE_DEC, NULL, 0, "Radio Priority for MO SMS", HFILL }},
+ { &hf_gtp_rp_spare, { "Reserved", "gtp.rp_spare", FT_UINT8, BASE_DEC, NULL, GTPv1_EXT_RP_SPARE_MASK, "Spare bit", HFILL }},
+ { &hf_gtp_sel_mode, { "Selection mode", "gtp.sel_mode", FT_UINT8, BASE_DEC, VALS(sel_mode_type), 0, "Selection Mode", HFILL }},
+ { &hf_gtp_seq_number, { "Sequence number", "gtp.seq_number", FT_UINT16, BASE_HEX, NULL, 0, "Sequence Number", HFILL }},
+ { &hf_gtp_sndcp_number, { "SNDCP N-PDU LLC Number", "gtp.sndcp_number", FT_UINT8, BASE_HEX, NULL, 0, "SNDCP N-PDU LLC Number", HFILL }},
+ { &hf_gtp_tear_ind, { "Teardown Indicator", "gtp.tear_ind", FT_BOOLEAN, BASE_NONE,NULL, 0, "Teardown Indicator", HFILL }},
+ { &hf_gtp_teid, { "TEID", "gtp.teid", FT_UINT32, BASE_HEX, NULL, 0, "Tunnel Endpoint Identifier", HFILL }},
+ { &hf_gtp_teid_cp, { "TEID Control Plane", "gtp.teid_cp", FT_UINT32, BASE_HEX, NULL, 0, "Tunnel Endpoint Identifier Control Plane", HFILL }},
+ { &hf_gtp_teid_data, { "TEID Data I", "gtp.teid_data", FT_UINT32, BASE_HEX, NULL, 0, "Tunnel Endpoint Identifier Data I", HFILL }},
+ { &hf_gtp_teid_ii, { "TEID Data II", "gtp.teid_ii", FT_UINT32, BASE_HEX, NULL, 0, "Tunnel Endpoint Identifier Data II", HFILL }},
+ { &hf_gtp_tft_code, { "TFT operation code", "gtp.tft_code", FT_UINT8, BASE_DEC, VALS (tft_code_type), GTPv1_TFT_CODE_MASK, "TFT operation code", HFILL }},
+ { &hf_gtp_tft_spare, { "TFT spare bit", "gtp.tft_spare", FT_UINT8, BASE_DEC, NULL, GTPv1_TFT_SPARE_MASK, "TFT spare bit", HFILL }},
+ { &hf_gtp_tft_number, { "Number of packet filters", "gtp.tft_number", FT_UINT8, BASE_DEC, NULL, GTPv1_TFT_NUMBER_MASK, "Number of packet filters", HFILL }},
+ { &hf_gtp_tft_eval, { "Evaluation precedence", "gtp.tft_eval", FT_UINT8, BASE_DEC, NULL, 0, "Evaluation precedence", HFILL }},
+ { &hf_gtp_tid, { "TID", "gtp.tid", FT_STRING, BASE_DEC, NULL, 0, "Tunnel Identifier", HFILL }},
+ { &hf_gtp_tlli, { "TLLI", "gtp.tlli", FT_UINT32, BASE_HEX, NULL, 0, "Temporary Logical Link Identity", HFILL }},
+ { &hf_gtp_tr_comm, { "Packet transfer command", "gtp.tr_comm", FT_UINT8, BASE_DEC, VALS (tr_comm_type), 0, "Packat transfer command", HFILL }},
+ { &hf_gtp_trace_ref, { "Trace reference", "gtp.trace_ref", FT_UINT16, BASE_HEX, NULL, 0, "Trace reference", HFILL }},
+ { &hf_gtp_trace_type, { "Trace type", "gtp.trace_type", FT_UINT16, BASE_HEX, NULL, 0, "Trace type", HFILL }},
+ { &hf_gtp_unknown, { "Unknown data (length)", "gtp.unknown", FT_UINT16, BASE_DEC, NULL, 0, "Unknown data", HFILL }},
+ { &hf_gtp_user_addr_pdp_org, { "PDP type organization", "gtp.user_addr_pdp_org", FT_UINT8, BASE_DEC, VALS(pdp_org_type), 0, "PDP type organization", HFILL }},
+ { &hf_gtp_user_addr_pdp_type, { "PDP type number", "gtp.user_addr_pdp_type", FT_UINT8, BASE_HEX, VALS (pdp_type), 0, "PDP type", HFILL }},
+ { &hf_gtp_user_ipv4, { "End user address IPv4", "gtp.user_ipv4", FT_IPv4, BASE_DEC, NULL, 0, "End user address IPv4", HFILL }},
+ { &hf_gtp_user_ipv6, { "End user address IPv6", "gtp.user_ipv6", FT_IPv6, BASE_HEX, NULL, 0, "End user address IPv6", HFILL }},
+ };
+
+ static gint *ett_gtp_array[] = {
+ &ett_gtp,
+ &ett_gtp_flags,
+ &ett_gtp_ext,
+ &ett_gtp_rai,
+ &ett_gtp_qos,
+ &ett_gtp_auth_tri,
+ &ett_gtp_flow_ii,
+ &ett_gtp_rab_cntxt,
+ &ett_gtp_rp,
+ &ett_gtp_pkt_flow_id,
+ &ett_gtp_chrg_char,
+ &ett_gtp_user,
+ &ett_gtp_mm,
+ &ett_gtp_trip,
+ &ett_gtp_quint,
+ &ett_gtp_pdp,
+ &ett_gtp_apn,
+ &ett_gtp_proto,
+ &ett_gtp_gsn_addr,
+ &ett_gtp_tft,
+ &ett_gtp_tft_pf,
+ &ett_gtp_tft_flags,
+ &ett_gtp_rab_setup,
+ &ett_gtp_hdr_list,
+ &ett_gtp_chrg_addr,
+ &ett_gtp_node_addr,
+ &ett_gtp_rel_pack,
+ &ett_gtp_can_pack,
+ &ett_gtp_data_resp,
+ &ett_gtp_priv_ext,
+ };
+
+ module_t *gtp_module;
+
+ proto_gtp = proto_register_protocol ("GPRS Tunneling Protocol", "GTP", "gtp");
+ proto_register_field_array (proto_gtp, hf_gtp, array_length (hf_gtp));
+ proto_register_subtree_array (ett_gtp_array, array_length (ett_gtp_array));
+
+ gtp_module = prefs_register_protocol(proto_gtp, proto_reg_handoff_gtp);
+
+ prefs_register_uint_preference(gtp_module, "v0_port", "GTPv0 port", "GTPv0 port (default 3386)", 10, &g_gtpv0_port);
+ prefs_register_uint_preference(gtp_module, "v1c_port", "GTPv1 control plane (GTP-C) port", "GTPv1 control plane port (default 2123)", 10, &g_gtpv1c_port);
+ prefs_register_uint_preference(gtp_module, "v1u_port", "GTPv1 user plane (GTP-U) port", "GTPv1 user plane port (default 2152)", 10, &g_gtpv1u_port);
+ prefs_register_bool_preference(gtp_module, "dissect_tpdu", "Dissect T-PDU", "Dissect T-PDU", &gtp_tpdu);
+ prefs_register_obsolete_preference (gtp_module, "v0_dissect_cdr_as");
+ prefs_register_obsolete_preference (gtp_module, "v0_check_etsi");
+ prefs_register_obsolete_preference (gtp_module, "v1_check_etsi");
+ prefs_register_bool_preference (gtp_module, "check_etsi", "Compare GTP order with ETSI", "GTP ETSI order", &gtp_etsi_order);
+ prefs_register_obsolete_preference(gtp_module, "ppp_reorder");
+
+ register_dissector("gtp", dissect_gtp, proto_gtp);
+}
+
+void
+proto_reg_handoff_gtp(void)
+{
+ static int Initialized = FALSE;
+ static dissector_handle_t gtp_handle;
+
+ if (!Initialized) {
+ gtp_handle = find_dissector("gtp");
+ ppp_subdissector_table = find_dissector_table("ppp.protocol");
+ Initialized = TRUE;
+ } else {
+ dissector_delete ("udp.port", gtpv0_port, gtp_handle);
+ dissector_delete ("tcp.port", gtpv0_port, gtp_handle);
+ dissector_delete ("udp.port", gtpv1c_port, gtp_handle);
+ dissector_delete ("tcp.port", gtpv1c_port, gtp_handle);
+ dissector_delete ("udp.port", gtpv1u_port, gtp_handle);
+ dissector_delete ("tcp.port", gtpv1u_port, gtp_handle);
+ }
+
+ gtpv0_port = g_gtpv0_port;
+ gtpv1c_port = g_gtpv1c_port;
+ gtpv1u_port = g_gtpv1u_port;
+
+ dissector_add ("udp.port", g_gtpv0_port, gtp_handle);
+ dissector_add ("tcp.port", g_gtpv0_port, gtp_handle);
+ dissector_add ("udp.port", g_gtpv1c_port, gtp_handle);
+ dissector_add ("tcp.port", g_gtpv1c_port, gtp_handle);
+ dissector_add ("udp.port", g_gtpv1u_port, gtp_handle);
+ dissector_add ("tcp.port", g_gtpv1u_port, gtp_handle);
+
+ ip_handle = find_dissector("ip");
+ ipv6_handle = find_dissector("ipv6");
+ ppp_handle = find_dissector("ppp");
+ data_handle = find_dissector("data");
+ gtpcdr_handle = find_dissector("gtpcdr");
+}
diff --git a/epan/dissectors/packet-gtp.h b/epan/dissectors/packet-gtp.h
new file mode 100644
index 0000000000..2afccb64b8
--- /dev/null
+++ b/epan/dissectors/packet-gtp.h
@@ -0,0 +1,34 @@
+/* packet-gtp.h
+ *
+ * Declarations of exported routines from GTP dissector
+ * Copyright 2001, Michal Melerowicz <michal.melerowicz@nokia.com>
+ * Nicolas Balkota <balkota@mac.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_GTP_H__
+#define __PACKET_GTP_H__
+
+extern int decode_qos_umts(
+ tvbuff_t *tvb, int offset, proto_tree *tree, gchar* qos_str, guint8 type);
+
+#endif
diff --git a/epan/dissectors/packet-gvrp.c b/epan/dissectors/packet-gvrp.c
new file mode 100644
index 0000000000..80fd96ad05
--- /dev/null
+++ b/epan/dissectors/packet-gvrp.c
@@ -0,0 +1,349 @@
+/* packet-gvrp.c
+ * Routines for GVRP (GARP VLAN Registration Protocol) dissection
+ * Copyright 2000, Kevin Shi <techishi@ms22.hinet.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "llcsaps.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_gvrp = -1;
+static int hf_gvrp_proto_id = -1;
+static int hf_gvrp_attribute_type = -1;
+static int hf_gvrp_attribute_length = -1;
+static int hf_gvrp_attribute_event = -1;
+static int hf_gvrp_attribute_value = -1;
+/*static int hf_gvrp_end_of_mark = -1;*/
+
+/* Initialize the subtree pointers */
+static gint ett_gvrp = -1;
+/*static gint ett_gvrp_message = -1;
+static gint ett_gvrp_attribute_list = -1;
+static gint ett_gvrp_attribute = -1;*/
+
+static dissector_handle_t data_handle;
+
+/* Constant definitions */
+#define GARP_DEFAULT_PROTOCOL_ID 0x0001
+#define GARP_END_OF_MARK 0x00
+
+#define GVRP_ATTRIBUTE_TYPE 0x01
+
+static const value_string attribute_type_vals[] = {
+ { GVRP_ATTRIBUTE_TYPE, "VID" },
+ { 0, NULL }
+};
+
+/* The length of GVRP LeaveAll attribute should be 2 octets (one for length
+ * and the other for event) */
+#define GVRP_LENGTH_LEAVEALL (sizeof(guint8)+sizeof(guint8))
+
+/* The length of GVRP attribute other than LeaveAll should be 4 octets (one
+ * for length, one for event, and the last two for VID value).
+ */
+#define GVRP_LENGTH_NON_LEAVEALL (sizeof(guint8)+sizeof(guint8)+sizeof(guint16))
+
+/* Packet offset definitions */
+#define GARP_PROTOCOL_ID 0
+
+/* Event definitions */
+#define GVRP_EVENT_LEAVEALL 0
+#define GVRP_EVENT_JOINEMPTY 1
+#define GVRP_EVENT_JOININ 2
+#define GVRP_EVENT_LEAVEEMPTY 3
+#define GVRP_EVENT_LEAVEIN 4
+#define GVRP_EVENT_EMPTY 5
+
+static const value_string event_vals[] = {
+ { GVRP_EVENT_LEAVEALL, "Leave All" },
+ { GVRP_EVENT_JOINEMPTY, "Join Empty" },
+ { GVRP_EVENT_JOININ, "Join In" },
+ { GVRP_EVENT_LEAVEEMPTY, "Leave Empty" },
+ { GVRP_EVENT_LEAVEIN, "Leave In" },
+ { GVRP_EVENT_EMPTY, "Empty" },
+ { 0, NULL }
+};
+
+/* Code to actually dissect the packets */
+static void
+dissect_gvrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *gvrp_tree;
+ guint16 protocol_id;
+ guint8 octet;
+ int msg_index, attr_index, offset = 0, length = tvb_reported_length(tvb);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GVRP");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "GVRP");
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_gvrp, tvb, 0, length, FALSE);
+
+ gvrp_tree = proto_item_add_subtree(ti, ett_gvrp);
+
+ /* Read in GARP protocol ID */
+ protocol_id = tvb_get_ntohs(tvb, GARP_PROTOCOL_ID);
+
+ proto_tree_add_uint_format(gvrp_tree, hf_gvrp_proto_id, tvb,
+ GARP_PROTOCOL_ID, sizeof(guint16),
+ protocol_id,
+ "Protocol Identifier: 0x%04x (%s)",
+ protocol_id,
+ protocol_id == GARP_DEFAULT_PROTOCOL_ID ?
+ "GARP VLAN Registration Protocol" :
+ "Unknown Protocol");
+
+ /* Currently only one protocol ID is supported */
+ if (protocol_id != GARP_DEFAULT_PROTOCOL_ID)
+ {
+ proto_tree_add_text(gvrp_tree, tvb, GARP_PROTOCOL_ID, sizeof(guint16),
+ " (Warning: this version of Ethereal only knows about protocol id = 1)");
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, GARP_PROTOCOL_ID + sizeof(guint16), -1, -1),
+ pinfo, tree);
+ return;
+ }
+
+ offset += sizeof(guint16);
+ length -= sizeof(guint16);
+
+ msg_index = 0;
+
+ /* Begin to parse GARP messages */
+ while (length)
+ {
+ proto_item *msg_item;
+ int msg_start = offset;
+
+ /* Read in attribute type. */
+ octet = tvb_get_guint8(tvb, offset);
+
+ /* Check for end of mark */
+ if (octet == GARP_END_OF_MARK)
+ {
+ /* End of GARP PDU */
+ if (msg_index)
+ {
+ proto_tree_add_text(gvrp_tree, tvb, offset, sizeof(guint8),
+ "End of mark");
+ break;
+ }
+ else
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ return;
+ }
+ }
+
+ offset += sizeof(guint8);
+ length -= sizeof(guint8);
+
+ msg_item = proto_tree_add_text(gvrp_tree, tvb, msg_start, -1,
+ "Message %d", msg_index + 1);
+
+ proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_type, tvb,
+ msg_start, sizeof(guint8), octet);
+
+ /* GVRP only supports one attribute type. */
+ if (octet != GVRP_ATTRIBUTE_TYPE)
+ {
+ call_dissector(data_handle, tvb_new_subset(tvb, offset,-1, -1),
+ pinfo, tree);
+ return;
+ }
+
+ attr_index = 0;
+
+ while (length)
+ {
+ int attr_start = offset;
+ proto_item *attr_item;
+
+ /* Read in attribute length. */
+ octet = tvb_get_guint8(tvb, offset);
+
+ /* Check for end of mark */
+ if (octet == GARP_END_OF_MARK)
+ {
+ /* If at least one message has been already read,
+ * check for another end of mark.
+ */
+ if (attr_index)
+ {
+ proto_tree_add_text(gvrp_tree, tvb, offset,
+ sizeof(guint8), " End of mark");
+
+ offset += sizeof(guint8);
+ length -= sizeof(guint8);
+
+ proto_item_set_len(msg_item, offset - msg_start);
+ break;
+ }
+ else
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ return;
+ }
+ }
+ else
+ {
+ guint8 event;
+
+ offset += sizeof(guint8);
+ length -= sizeof(guint8);
+
+ attr_item = proto_tree_add_text(gvrp_tree, tvb,
+ attr_start, -1, " Attribute %d", attr_index + 1);
+
+ proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_length,
+ tvb, attr_start, sizeof(guint8), octet);
+
+ /* Read in attribute event */
+ event = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_event,
+ tvb, offset, sizeof(guint8), event);
+
+ offset += sizeof(guint8);
+ length -= sizeof(guint8);
+
+ switch (event) {
+
+ case GVRP_EVENT_LEAVEALL:
+ if (octet != GVRP_LENGTH_LEAVEALL)
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo,
+ tree);
+ return;
+ }
+ break;
+
+ case GVRP_EVENT_JOINEMPTY:
+ case GVRP_EVENT_JOININ:
+ case GVRP_EVENT_LEAVEEMPTY:
+ case GVRP_EVENT_LEAVEIN:
+ case GVRP_EVENT_EMPTY:
+ if (octet != GVRP_LENGTH_NON_LEAVEALL)
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1),pinfo,
+ tree);
+ return;
+ }
+
+ /* Show attribute value */
+ proto_tree_add_item(gvrp_tree, hf_gvrp_attribute_value,
+ tvb, offset, sizeof(guint16), FALSE);
+
+ offset += sizeof(guint16);
+ length -= sizeof(guint16);
+ break;
+
+ default:
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ return;
+ }
+ }
+
+ proto_item_set_len(attr_item, offset - attr_start);
+
+ attr_index++;
+ }
+
+ msg_index++;
+ }
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_gvrp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_gvrp_proto_id,
+ { "Protocol ID", "garp.protocol_id",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_gvrp_attribute_type,
+ { "Type", "garp.attribute_type",
+ FT_UINT8, BASE_HEX, VALS(attribute_type_vals), 0x0,
+ "", HFILL }
+ },
+ { &hf_gvrp_attribute_length,
+ { "Length", "garp.attribute_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_gvrp_attribute_event,
+ { "Event", "garp.attribute_event",
+ FT_UINT8, BASE_DEC, VALS(event_vals), 0x0,
+ "", HFILL }
+ },
+ { &hf_gvrp_attribute_value,
+ { "Value", "garp.attribute_value",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ }
+ };
+
+ static gint *ett[] = {
+ &ett_gvrp
+ };
+
+ /* Register the protocol name and description for GVRP */
+ proto_gvrp = proto_register_protocol("GARP VLAN Registration Protocol",
+ "GVRP", "gvrp");
+
+ /* Required function calls to register the header fields and subtrees
+ * used by GVRP */
+ proto_register_field_array(proto_gvrp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("gvrp", dissect_gvrp, proto_gvrp);
+}
+
+void
+proto_reg_handoff_gvrp(void){
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-h1.c b/epan/dissectors/packet-h1.c
new file mode 100644
index 0000000000..245dff7c16
--- /dev/null
+++ b/epan/dissectors/packet-h1.c
@@ -0,0 +1,320 @@
+/* packet-h1.c
+ * Routines for Sinec H1 packet disassembly
+ * Gerrit Gehnen <G.Gehnen@atrie.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+
+static int proto_h1 = -1;
+static int hf_h1_header = -1;
+static int hf_h1_len = -1;
+static int hf_h1_opfield = -1;
+static int hf_h1_oplen = -1;
+static int hf_h1_opcode = -1;
+static int hf_h1_requestblock = -1;
+static int hf_h1_requestlen = -1;
+static int hf_h1_dbnr = -1;
+static int hf_h1_dwnr = -1;
+static int hf_h1_dlen = -1;
+static int hf_h1_org = -1;
+static int hf_h1_response = -1;
+static int hf_h1_response_len = -1;
+static int hf_h1_response_value = -1;
+static int hf_h1_empty_len = -1;
+static int hf_h1_empty = -1;
+
+static dissector_handle_t data_handle;
+
+#define EMPTY_BLOCK 0xFF
+#define OPCODE_BLOCK 0x01
+#define REQUEST_BLOCK 0x03
+#define RESPONSE_BLOCK 0x0F
+
+static const value_string opcode_vals[] = {
+ {3, "Write Request"},
+ {4, "Write Response"},
+ {5, "Read Request"},
+ {6, "Read Response"},
+ {0, NULL}
+};
+
+static const value_string org_vals[] = {
+ {0x01, "DB"},
+ {0x02, "MB"},
+ {0x03, "EB"},
+ {0x04, "AB"},
+ {0x05, "PB"},
+ {0x06, "ZB"},
+ {0x07, "TB"},
+ {0x08, "BS"},
+ {0x09, "AS"},
+ {0x0a, "DX"},
+ {0x10, "DE"},
+ {0x11, "QB"},
+ {0, NULL}
+};
+
+static const value_string returncode_vals[] = {
+ {0x00, "No error"},
+ {0x02, "Requested block does not exist"},
+ {0x03, "Requested block too small"},
+ {0xFF, "Error, reason unknown"},
+ {0, NULL}
+};
+
+static gint ett_h1 = -1;
+static gint ett_opcode = -1;
+static gint ett_org = -1;
+static gint ett_response = -1;
+static gint ett_empty = -1;
+
+static gboolean dissect_h1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *next_tvb;
+
+ proto_tree *h1_tree = NULL;
+
+ proto_item *ti;
+ proto_tree *opcode_tree = NULL;
+ proto_tree *org_tree = NULL;
+ proto_tree *response_tree = NULL;
+ proto_tree *empty_tree = NULL;
+
+ unsigned int position = 3;
+ unsigned int offset=0;
+
+ if (tvb_length_remaining(tvb, 0) < 2)
+ {
+ /* Not enough data captured to hold the "S5" header; don't try
+ to interpret it as H1. */
+ return FALSE;
+ }
+
+ if (!(tvb_get_guint8(tvb,offset) == 'S' && tvb_get_guint8(tvb,offset+1) == '5'))
+ {
+ return FALSE;
+ }
+
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "H1");
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_add_str (pinfo->cinfo, COL_INFO, "S5: ");
+ if (tree)
+ {
+ ti = proto_tree_add_item (tree, proto_h1, tvb, offset, 16, FALSE);
+ h1_tree = proto_item_add_subtree (ti, ett_h1);
+ proto_tree_add_uint (h1_tree, hf_h1_header, tvb, offset, 2,
+ tvb_get_ntohs(tvb,offset));
+ proto_tree_add_uint (h1_tree, hf_h1_len, tvb, offset + 2, 1,
+ tvb_get_guint8(tvb,offset+2));
+ }
+
+ while (position < tvb_get_guint8(tvb,offset+2))
+ {
+ switch (tvb_get_guint8(tvb,offset + position))
+ {
+ case OPCODE_BLOCK:
+ if (h1_tree)
+ {
+ ti = proto_tree_add_uint (h1_tree, hf_h1_opfield, tvb,
+ offset + position,
+ tvb_get_guint8(tvb,offset+position+1),
+ tvb_get_guint8(tvb,offset+position));
+ opcode_tree = proto_item_add_subtree (ti, ett_opcode);
+ proto_tree_add_uint (opcode_tree, hf_h1_oplen, tvb,
+ offset + position + 1, 1,
+ tvb_get_guint8(tvb,offset + position + 1));
+ proto_tree_add_uint (opcode_tree, hf_h1_opcode, tvb,
+ offset + position + 2, 1,
+ tvb_get_guint8(tvb,offset + position + 2));
+ }
+ if (check_col (pinfo->cinfo, COL_INFO))
+ {
+ col_append_str (pinfo->cinfo, COL_INFO,
+ val_to_str (tvb_get_guint8(tvb,offset + position + 2),
+ opcode_vals,"Unknown Opcode (0x%2.2x)"));
+ }
+ break;
+ case REQUEST_BLOCK:
+ if (h1_tree)
+ {
+ ti = proto_tree_add_uint (h1_tree, hf_h1_requestblock, tvb,
+ offset + position,
+ tvb_get_guint8(tvb,offset + position + 1),
+ tvb_get_guint8(tvb,offset + position));
+ org_tree = proto_item_add_subtree (ti, ett_org);
+ proto_tree_add_uint (org_tree, hf_h1_requestlen, tvb,
+ offset + position + 1, 1,
+ tvb_get_guint8(tvb,offset + position+1));
+ proto_tree_add_uint (org_tree, hf_h1_org, tvb,
+ offset + position + 2, 1,
+ tvb_get_guint8(tvb,offset + position+2));
+ proto_tree_add_uint (org_tree, hf_h1_dbnr, tvb,
+ offset + position + 3, 1,
+ tvb_get_guint8(tvb,offset + position+3));
+ proto_tree_add_uint (org_tree, hf_h1_dwnr, tvb,
+ offset + position + 4, 2,
+ tvb_get_ntohs(tvb,offset+position+4));
+ proto_tree_add_int (org_tree, hf_h1_dlen, tvb,
+ offset + position + 6, 2,
+ tvb_get_ntohs(tvb,offset+position+6));
+ }
+ if (check_col (pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr (pinfo->cinfo, COL_INFO, " %s %d",
+ val_to_str (tvb_get_guint8(tvb,offset + position + 2),
+ org_vals,"Unknown Type (0x%2.2x)"),
+ tvb_get_guint8(tvb,offset + position + 3));
+ col_append_fstr (pinfo->cinfo, COL_INFO, " DW %d",
+ tvb_get_ntohs(tvb,offset+position+4));
+ col_append_fstr (pinfo->cinfo, COL_INFO, " Count %d",
+ tvb_get_ntohs(tvb,offset+position+6));
+ }
+ break;
+ case RESPONSE_BLOCK:
+ if (h1_tree)
+ {
+ ti = proto_tree_add_uint (h1_tree, hf_h1_response, tvb,
+ offset + position,
+ tvb_get_guint8(tvb,offset + position + 1),
+ tvb_get_guint8(tvb,offset + position));
+ response_tree = proto_item_add_subtree (ti, ett_response);
+ proto_tree_add_uint (response_tree, hf_h1_response_len, tvb,
+ offset + position + 1, 1,
+ tvb_get_guint8(tvb,offset + position+1));
+ proto_tree_add_uint (response_tree, hf_h1_response_value, tvb,
+ offset + position + 2, 1,
+ tvb_get_guint8(tvb,offset + position+2));
+ }
+ if (check_col (pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
+ val_to_str (tvb_get_guint8(tvb,offset + position + 2),
+ returncode_vals,"Unknown Returcode (0x%2.2x"));
+ }
+ break;
+ case EMPTY_BLOCK:
+ if (h1_tree)
+ {
+ ti = proto_tree_add_uint (h1_tree, hf_h1_empty, tvb,
+ offset + position,
+ tvb_get_guint8(tvb,offset + position + 1),
+ tvb_get_guint8(tvb,offset + position));
+ empty_tree = proto_item_add_subtree (ti, ett_empty);
+
+ proto_tree_add_uint (empty_tree, hf_h1_empty_len, tvb,
+ offset + position + 1, 1,
+ tvb_get_guint8(tvb,offset + position+1));
+ }
+ break;
+ default:
+ /* This is not a valid telegram. So cancel dissection
+ and try the next dissector */
+ return FALSE;
+ break;
+ }
+ position += tvb_get_guint8(tvb,offset + position + 1); /* Goto next section */
+ } /* ..while */
+ next_tvb = tvb_new_subset(tvb, offset+tvb_get_guint8(tvb,offset+2), -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+
+ return TRUE;
+}
+
+
+void
+proto_register_h1 (void)
+{
+ static hf_register_info hf[] = {
+ {&hf_h1_header,
+ {"H1-Header", "h1.header", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ {&hf_h1_len,
+ {"Length indicator", "h1.len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&hf_h1_opfield,
+ {"Operation identifier", "h1.opfield", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ {&hf_h1_oplen,
+ {"Operation length", "h1.oplen", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ {&hf_h1_opcode,
+ {"Opcode", "h1.opcode", FT_UINT8, BASE_HEX, VALS (opcode_vals), 0x0,
+ "", HFILL }},
+ {&hf_h1_requestblock,
+ {"Request identifier", "h1.request", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ {&hf_h1_requestlen,
+ {"Request length", "h1.reqlen", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ {&hf_h1_org,
+ {"Memory type", "h1.org", FT_UINT8, BASE_HEX, VALS (org_vals), 0x0,
+ "", HFILL }},
+ {&hf_h1_dbnr,
+ {"Memory block number", "h1.dbnr", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ {&hf_h1_dwnr,
+ {"Address within memory block", "h1.dwnr", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&hf_h1_dlen,
+ {"Length in words", "h1.dlen", FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ {&hf_h1_response,
+ {"Response identifier", "h1.response", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ {&hf_h1_response_len,
+ {"Response length", "h1.reslen", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&hf_h1_response_value,
+ {"Response value", "h1.resvalue", FT_UINT8, BASE_DEC,
+ VALS (returncode_vals), 0x0, "", HFILL }},
+ {&hf_h1_empty,
+ {"Empty field", "h1.empty", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ {&hf_h1_empty_len,
+ {"Empty field length", "h1.empty_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_h1,
+ &ett_opcode,
+ &ett_response,
+ &ett_org,
+ &ett_empty
+ };
+
+ proto_h1 = proto_register_protocol ("Sinec H1 Protocol", "H1", "h1");
+ proto_register_field_array (proto_h1, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_h1(void)
+{
+ heur_dissector_add("cotp_is", dissect_h1, proto_h1);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-h225.c b/epan/dissectors/packet-h225.c
new file mode 100644
index 0000000000..7da3f330cd
--- /dev/null
+++ b/epan/dissectors/packet-h225.c
@@ -0,0 +1,10748 @@
+/* packet-h225.c
+ * Routines for H.225 packet dissection
+ * 2003 Ronnie Sahlberg
+ *
+ * Maintained by Andreas Sikkema (h323@ramdyne.nl)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "prefs.h"
+#include "tap.h"
+#include "packet-tpkt.h"
+#include "packet-per.h"
+#include "packet-h225.h"
+#include "packet-h235.h"
+#include "packet-h245.h"
+#include "t35.h"
+#include "h225-persistentdata.h"
+
+#define UDP_PORT_RAS1 1718
+#define UDP_PORT_RAS2 1719
+#define TCP_PORT_CS 1720
+
+static void reset_h225_packet_info(h225_packet_info *pi);
+static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi);
+
+static h225_packet_info h225_pi;
+
+static dissector_handle_t h225ras_handle;
+static dissector_handle_t H323UserInformation_handle;
+static dissector_handle_t data_handle;
+
+static int h225_tap = -1;
+static int proto_h225 = -1;
+static int hf_h225_cname = -1;
+static int hf_h225_route = -1;
+static int hf_h225_nonStandardUsageTypes = -1;
+static int hf_h225_nonStandardUsageTypes_item = -1;
+static int hf_h225_PresentationIndicator = -1;
+static int hf_h225_CryptoH323Token = -1;
+static int hf_h225_conferenceGoal = -1;
+static int hf_h225_ScnConnectionType = -1;
+static int hf_h225_ScnConnectionAggregation = -1;
+static int hf_h225_FacilityReason = -1;
+static int hf_h225_PublicTypeOfNumber = -1;
+static int hf_h225_PrivateTypeOfNumber = -1;
+static int hf_h225_UseSpecifiedTransport = -1;
+static int hf_h225_SecurityErrors = -1;
+static int hf_h225_SecurityErrors2 = -1;
+static int hf_h225_ServiceControlSession_reason = -1;
+static int hf_h225_billingMode = -1;
+static int hf_h225_CCSCcallStartingPoint = -1;
+static int hf_h225_GatekeeperRejectReason = -1;
+static int hf_h225_UnregRequestReason = -1;
+static int hf_h225_UnregRejectReason = -1;
+static int hf_h225_CallType = -1;
+static int hf_h225_CallModel = -1;
+static int hf_h225_TransportQOS = -1;
+static int hf_h225_BandRejectReason = -1;
+static int hf_h225_DisengageReason = -1;
+static int hf_h225_DisengageRejectReason = -1;
+static int hf_h225_InfoRequestNakReason = -1;
+static int hf_h225_SCRresult = -1;
+static int hf_h225_GatekeeperInfo = -1;
+static int hf_h225_SecurityServiceMode_encryption = -1;
+static int hf_h225_SecurityServiceMode_authentication = -1;
+static int hf_h225_SecurityServiceMode_integrity = -1;
+static int hf_h225_SecurityCapabilities_tls = -1;
+static int hf_h225_SecurityCapabilities_ipsec = -1;
+static int hf_h225_H245Security = -1;
+static int hf_h225_RasUsageInfoTypes = -1;
+static int hf_h225_usageReportingCapability = -1;
+static int hf_h225_BandWidth = -1;
+static int hf_h225_channelRate = -1;
+static int hf_h225_totalBandwidthRestriction = -1;
+static int hf_h225_allowedBandWidth = -1;
+static int hf_h225_channelMultiplier = -1;
+static int hf_h225_DataRate = -1;
+static int hf_h225_gatewayDataRate = -1;
+static int hf_h225_dataRatesSupported = -1;
+static int hf_h225_TerminalInfo = -1;
+static int hf_h225_h248Message = -1;
+static int hf_h225_StimulusControl = -1;
+static int hf_h225_conferenceID = -1;
+static int hf_h225_Generic_nonStandard = -1;
+static int hf_h225_guid = -1;
+static int hf_h225_replaceWithConferenceInvite = -1;
+static int hf_h225_ReleaseCompleteReason = -1;
+static int hf_h225_numberOfScnConnections = -1;
+static int hf_h225_connectionParameters = -1;
+static int hf_h225_RequestSeqNum = -1;
+static int hf_h225_RasUsageSpecification_when = -1;
+static int hf_h225_RasUsageSpecification_callStartingPoint = -1;
+static int hf_h225_RasUsageSpecification = -1;
+static int hf_h225_ipAddress_ip = -1;
+static int hf_h225_ipAddress_port = -1;
+static int hf_h225_ipAddress = -1;
+static int hf_h225_routing = -1;
+static int hf_h225_ipSourceRoute = -1;
+static int hf_h225_ipxNode = -1;
+static int hf_h225_ipxNetnum = -1;
+static int hf_h225_ipxPort = -1;
+static int hf_h225_ipxAddress = -1;
+static int hf_h225_ipv6Address_ip = -1;
+static int hf_h225_ipv6Address_port = -1;
+static int hf_h225_ip6Address = -1;
+static int hf_h225_netBios = -1;
+static int hf_h225_nsap = -1;
+static int hf_h225_TransportAddress = -1;
+static int hf_h225_replyAddress = -1;
+static int hf_h225_rasAddress = -1;
+static int hf_h225_h245Address = -1;
+static int hf_h225_destCallSignalAddress = -1;
+static int hf_h225_sourceCallSignalAddress = -1;
+static int hf_h225_CallSignalAddress2 = -1;
+static int hf_h225_alternativeAddress = -1;
+static int hf_h225_transportID = -1;
+static int hf_h225_sendAddress = -1;
+static int hf_h225_recvAddress = -1;
+static int hf_h225_rtpAddress = -1;
+static int hf_h225_rtcpAddress = -1;
+static int hf_h225_h245 = -1;
+static int hf_h225_callSignaling = -1;
+static int hf_h225_carrierName = -1;
+static int hf_h225_carrierIdentificationCode = -1;
+static int hf_h225_CarrierInfo = -1;
+static int hf_h225_segment = -1;
+static int hf_h225_InfoRequestResponseStatus = -1;
+static int hf_h225_CallIdentifier = -1;
+static int hf_h225_globalCallId = -1;
+static int hf_h225_threadId = -1;
+static int hf_h225_CallLinkage = -1;
+static int hf_h225_tokens = -1;
+static int hf_h225_CryptoH323Tokens = -1;
+static int hf_h225_needToRegister = -1;
+static int hf_h225_priority = -1;
+static int hf_h225_AlternateGK = -1;
+static int hf_h225_alternateGatekeeper = -1;
+static int hf_h225_altGKisPermanent = -1;
+static int hf_h225_AltGKInfo = -1;
+static int hf_h225_annexE = -1;
+static int hf_h225_sctp = -1;
+static int hf_h225_AlternateTransportAddress = -1;
+static int hf_h225_setup_bool = -1;
+static int hf_h225_callProceeding_bool = -1;
+static int hf_h225_connect_bool = -1;
+static int hf_h225_alerting_bool = -1;
+static int hf_h225_information_bool = -1;
+static int hf_h225_releaseComplete_bool = -1;
+static int hf_h225_facility_bool = -1;
+static int hf_h225_progress_bool = -1;
+static int hf_h225_empty_bool = -1;
+static int hf_h225_status_bool = -1;
+static int hf_h225_statusInquiry_bool = -1;
+static int hf_h225_setupAcknowledge_bool = -1;
+static int hf_h225_notify_bool = -1;
+static int hf_h225_UUIEsRequested = -1;
+static int hf_h225_conferenceCalling = -1;
+static int hf_h225_threePartyService = -1;
+static int hf_h225_Q954Details = -1;
+static int hf_h225_q932Full = -1;
+static int hf_h225_q951Full = -1;
+static int hf_h225_q952Full = -1;
+static int hf_h225_q953Full = -1;
+static int hf_h225_q955Full = -1;
+static int hf_h225_q956Full = -1;
+static int hf_h225_q957Full = -1;
+static int hf_h225_QseriesOptions = -1;
+static int hf_h225_ssrc = -1;
+static int hf_h225_RTPsessionId = -1;
+static int hf_h225_associatedSessionIds = -1;
+static int hf_h225_RTPSession = -1;
+static int hf_h225_ProtocolIdentifier = -1;
+static int hf_h225_isoAlgorithm = -1;
+static int hf_h225_iso9797 = -1;
+static int hf_h225_algorithmOID = -1;
+static int hf_h225_hMAC_iso10118_3 = -1;
+static int hf_h225_enterpriseNumber = -1;
+static int hf_h225_Generic_oid = -1;
+static int hf_h225_tunnelledProtocolObjectID = -1;
+static int hf_h225_StatusUUIE = -1;
+static int hf_h225_StatusInquiryUUIE = -1;
+static int hf_h225_SetupAcknowledgeUUIE = -1;
+static int hf_h225_NotifyUUIE = -1;
+static int hf_h225_imsi = -1;
+static int hf_h225_tmsi = -1;
+static int hf_h225_msisdn = -1;
+static int hf_h225_imei = -1;
+static int hf_h225_hplmn = -1;
+static int hf_h225_vplmn = -1;
+static int hf_h225_GSMUIM = -1;
+static int hf_h225_sid = -1;
+static int hf_h225_mid = -1;
+static int hf_h225_systemid = -1;
+static int hf_h225_min = -1;
+static int hf_h225_mdn = -1;
+static int hf_h225_esn = -1;
+static int hf_h225_mscid = -1;
+static int hf_h225_systemMyTypeCode = -1;
+static int hf_h225_systemAccessType = -1;
+static int hf_h225_qualificationInformationCode = -1;
+static int hf_h225_sesn = -1;
+static int hf_h225_soc = -1;
+static int hf_h225_ANSI41UIM = -1;
+static int hf_h225_MobileUIM = -1;
+static int hf_h225_dataPartyNumber = -1;
+static int hf_h225_telexPartyNumber = -1;
+static int hf_h225_nationalStandardPartyNumber = -1;
+static int hf_h225_publicNumberDigits = -1;
+static int hf_h225_privateNumberDigits = -1;
+static int hf_h225_e164Number = -1;
+static int hf_h225_privateNumber = -1;
+static int hf_h225_PartyNumber = -1;
+static int hf_h225_startOfRange = -1;
+static int hf_h225_endOfRange = -1;
+static int hf_h225_protocolType = -1;
+static int hf_h225_protocolVariant = -1;
+static int hf_h225_TunnelledProtocolAlternateIdentifier = -1;
+static int hf_h225_dialedDigits = -1;
+static int hf_h225_urlId = -1;
+static int hf_h225_h323ID = -1;
+static int hf_h225_unicode = -1;
+static int hf_h225_GatekeeperIdentifier = -1;
+static int hf_h225_EndpointIdentifier = -1;
+static int hf_h225_emailId = -1;
+static int hf_h225_AliasAddress = -1;
+static int hf_h225_featureServerAlias = -1;
+static int hf_h225_RemoteExtensionAddress = -1;
+static int hf_h225_conferenceAlias = -1;
+static int hf_h225_wildcard = -1;
+static int hf_h225_prefix = -1;
+static int hf_h225_SupportedPrefix = -1;
+static int hf_h225_SupportedPrefixes = -1;
+static int hf_h225_H310Caps = -1;
+static int hf_h225_H320Caps = -1;
+static int hf_h225_H321Caps = -1;
+static int hf_h225_H322Caps = -1;
+static int hf_h225_H323Caps = -1;
+static int hf_h225_H324Caps = -1;
+static int hf_h225_VoiceCaps = -1;
+static int hf_h225_T120OnlyCaps = -1;
+static int hf_h225_NonStandardProtocol = -1;
+static int hf_h225_SIPCaps = -1;
+static int hf_h225_AddressPattern_range = -1;
+static int hf_h225_AddressPattern = -1;
+static int hf_h225_ConferenceList = -1;
+static int hf_h225_conferences = -1;
+static int hf_h225_T38FaxAnnexbOnlyCaps = -1;
+static int hf_h225_SupportedProtocols = -1;
+static int hf_h225_protocol = -1;
+static int hf_h225_GatewayInfo = -1;
+static int hf_h225_McuInfo = -1;
+static int hf_h225_TunnelledProtocol_id = -1;
+static int hf_h225_TunnelledProtocol_subIdentifier = -1;
+static int hf_h225_TunnelledProtocol = -1;
+static int hf_h225_TunnelledProtocols = -1;
+static int hf_h225_desiredTunnelledProtocol = -1;
+static int hf_h225_CicInfo_cic_item = -1;
+static int hf_h225_CicInfo_pointCode = -1;
+static int hf_h225_CicInfo_cic = -1;
+static int hf_h225_CicInfo = -1;
+static int hf_h225_GroupID_member_item = -1;
+static int hf_h225_GroupID_member = -1;
+static int hf_h225_GroupID_group = -1;
+static int hf_h225_GroupID = -1;
+static int hf_h225_sourceCircuitID = -1;
+static int hf_h225_destinationCircuitID = -1;
+static int hf_h225_Generic_standard = -1;
+static int hf_h225_GenericIdentifier = -1;
+static int hf_h225_EnumeratedParameter = -1;
+static int hf_h225_parameters = -1;
+static int hf_h225_GenericData = -1;
+static int hf_h225_FeatureDescriptor = -1;
+static int hf_h225_Content_raw = -1;
+static int hf_h225_Content_text = -1;
+static int hf_h225_Content = -1;
+static int hf_h225_Content_bool = -1;
+static int hf_h225_Content_number8 = -1;
+static int hf_h225_number16 = -1;
+static int hf_h225_Content_number32 = -1;
+static int hf_h225_Content_compound = -1;
+static int hf_h225_Content_nested = -1;
+static int hf_h225_replacementFeatureSet = -1;
+static int hf_h225_neededFeatures = -1;
+static int hf_h225_desiredFeatures = -1;
+static int hf_h225_supportedFeatures = -1;
+static int hf_h225_FeatureSet = -1;
+static int hf_h225_CallsAvailable_calls = -1;
+static int hf_h225_CallsAvailable_group = -1;
+static int hf_h225_CallsAvailable = -1;
+static int hf_h225_voiceGwCallsAvailable = -1;
+static int hf_h225_h310GwCallsAvailable = -1;
+static int hf_h225_h320GwCallsAvailable = -1;
+static int hf_h225_h321GwCallsAvailable = -1;
+static int hf_h225_h322GwCallsAvailable = -1;
+static int hf_h225_h323GwCallsAvailable = -1;
+static int hf_h225_h324GwCallsAvailable = -1;
+static int hf_h225_t120OnlyGwCallsAvailable = -1;
+static int hf_h225_t38FaxAnnexbOnlyGwCallsAvailable = -1;
+static int hf_h225_terminalCallsAvailable = -1;
+static int hf_h225_mcuCallsAvailable = -1;
+static int hf_h225_sipGwCallsAvailable = -1;
+static int hf_h225_maximumCallCapacity = -1;
+static int hf_h225_currentCallCapacity = -1;
+static int hf_h225_CallCapacity = -1;
+static int hf_h225_productID = -1;
+static int hf_h225_versionID = -1;
+static int hf_h225_VendorIdentifier = -1;
+static int hf_h225_canReportCallCapacity = -1;
+static int hf_h225_CapacityReportingCapability = -1;
+static int hf_h225_canDisplayAmountString = -1;
+static int hf_h225_canEnforceDurationLimit = -1;
+static int hf_h225_CallCreditCapability = -1;
+static int hf_h225_BandwidthDetails_sender = -1;
+static int hf_h225_BandwidthDetails_multicast = -1;
+static int hf_h225_BandwidthDetails = -1;
+static int hf_h225_releaseCompleteCauseIE = -1;
+static int hf_h225_CallTerminationCause = -1;
+static int hf_h225_CircuitInfo = -1;
+static int hf_h225_genericData = -1;
+static int hf_h225_fastStart_item_length = -1;
+static int hf_h225_fastStart = -1;
+static int hf_h225_fastConnectRefused = -1;
+static int hf_h225_InformationUUIE = -1;
+static int hf_h225_routeCallToSCN = -1;
+static int hf_h225_AdmissionRejectReason = -1;
+static int hf_h225_hMAC_iso10118_2_s = -1;
+static int hf_h225_hMAC_iso10118_2_l = -1;
+static int hf_h225_NonIsoIntegrityMechanism = -1;
+static int hf_h225_IntegrityMechanism = -1;
+static int hf_h225_LocationRejectReason = -1;
+static int hf_h225_mc = -1;
+static int hf_h225_undefinedNode = -1;
+static int hf_h225_EndPointType = -1;
+static int hf_h225_terminalType = -1;
+static int hf_h225_sourceInfo = -1;
+static int hf_h225_destinationInfo = -1;
+static int hf_h225_multipleCalls = -1;
+static int hf_h225_maintainConnection = -1;
+static int hf_h225_CallProceedingUUIE = -1;
+static int hf_h225_CapacityReportingSpecification_when = -1;
+static int hf_h225_CapacityReportingSpecification = -1;
+static int hf_h225_ProgressUUIE = -1;
+static int hf_h225_EndPoint = -1;
+static int hf_h225_destinationType = -1;
+static int hf_h225_destExtraCallInfo = -1;
+static int hf_h225_remoteExtensionAddress = -1;
+static int hf_h225_rasAddress_sequence = -1;
+static int hf_h225_callSignalAddress = -1;
+static int hf_h225_ICV = -1;
+static int hf_h225_BandwidthConfirm = -1;
+static int hf_h225_UnregistrationConfirm = -1;
+static int hf_h225_NonStandardMessage = -1;
+static int hf_h225_InfoRequestAck = -1;
+static int hf_h225_InfoRequestNak = -1;
+static int hf_h225_ResourcesAvailableConfirm = -1;
+static int hf_h225_GatekeeperRequest = -1;
+static int hf_h225_integrity = -1;
+static int hf_h225_algorithmOIDs = -1;
+static int hf_h225_alternateEndpoints = -1;
+static int hf_h225_endpointAlias = -1;
+static int hf_h225_ServiceControlResponse = -1;
+static int hf_h225_DisengageReject = -1;
+static int hf_h225_BandwidthReject = -1;
+static int hf_h225_UnregistrationReject = -1;
+static int hf_h225_UnregistrationRequest = -1;
+static int hf_h225_endpointAliasPattern = -1;
+static int hf_h225_RegistrationReject = -1;
+static int hf_h225_invalidTerminalAliases = -1;
+static int hf_h225_terminalAlias = -1;
+static int hf_h225_terminalAliasPattern = -1;
+static int hf_h225_RegistrationRejectReason = -1;
+static int hf_h225_duplicateAlias = -1;
+static int hf_h225_GatekeeperReject = -1;
+static int hf_h225_almostOutOfResources = -1;
+static int hf_h225_ResourcesAvailableIndicate = -1;
+static int hf_h225_protocols = -1;
+static int hf_h225_callDurationLimit = -1;
+static int hf_h225_enforceCallDurationLimit = -1;
+static int hf_h225_CallCreditServiceControl = -1;
+static int hf_h225_ScreeningIndicator = -1;
+static int hf_h225_ExtendedAliasAddress = -1;
+static int hf_h225_messageNotUnderstood = -1;
+static int hf_h225_UnknownMessageResponse = -1;
+static int hf_h225_CallReferenceValue = -1;
+static int hf_h225_AdmissionRequest = -1;
+static int hf_h225_canMapSrcAlias = -1;
+static int hf_h225_desiredProtocols = -1;
+static int hf_h225_willSupplyUUIEs = -1;
+static int hf_h225_destAlternatives = -1;
+static int hf_h225_srcAlternatives = -1;
+static int hf_h225_canMapAlias = -1;
+static int hf_h225_activeMC = -1;
+static int hf_h225_srcInfo = -1;
+static int hf_h225_DestinationInfo = -1;
+static int hf_h225_InfoRequest = -1;
+static int hf_h225_nextSegmentRequested = -1;
+static int hf_h225_delay = -1;
+static int hf_h225_RequestInProgress = -1;
+static int hf_h225_H248SignalsDescriptor = -1;
+static int hf_h225_url = -1;
+static int hf_h225_ServiceControlDescriptor = -1;
+static int hf_h225_ServiceControlSession = -1;
+static int hf_h225_sessionId = -1;
+static int hf_h225_AlertingUUIE = -1;
+static int hf_h225_serviceControl = -1;
+static int hf_h225_alertingAddress = -1;
+static int hf_h225_ReleaseCompleteUUIE = -1;
+static int hf_h225_busyAddress = -1;
+static int hf_h225_FacilityUUIE = -1;
+static int hf_h225_alternativeAliasAddress = -1;
+static int hf_h225_AdmissionReject = -1;
+static int hf_h225_hopCount = -1;
+static int hf_h225_parallelH245Control = -1;
+static int hf_h225_language = -1;
+static int hf_h225_languages = -1;
+static int hf_h225_mediaWaitForConnect = -1;
+static int hf_h225_canOverlapSend = -1;
+static int hf_h225_SetupUUIE = -1;
+static int hf_h225_sourceAddress = -1;
+static int hf_h225_destinationAddress = -1;
+static int hf_h225_destExtraCRV = -1;
+static int hf_h225_h245SecurityCapability = -1;
+static int hf_h225_additionalSourceAddresses = -1;
+static int hf_h225_ConnectUUIE = -1;
+static int hf_h225_connectedAddress = -1;
+static int hf_h225_h323_message_body = -1;
+static int hf_h225_LocationConfirm = -1;
+static int hf_h225_supportedProtocols = -1;
+static int hf_h225_modifiedSrcInfo = -1;
+static int hf_h225_LocationReject = -1;
+static int hf_h225_callSpecific = -1;
+static int hf_h225_answeredCall = -1;
+static int hf_h225_ServiceControlIndication = -1;
+static int hf_h225_RasUsageInformation = -1;
+static int hf_h225_nonStandardUsageFields = -1;
+static int hf_h225_nonStandardUsageFields_item = -1;
+static int hf_h225_TimeToLive = -1;
+static int hf_h225_GatekeeperConfirm = -1;
+static int hf_h225_RegistrationRequest = -1;
+static int hf_h225_discoveryComplete = -1;
+static int hf_h225_keepAlive = -1;
+static int hf_h225_H248PackagesDescriptor = -1;
+static int hf_h225_supportedH248Packages = -1;
+static int hf_h225_DisengageConfirm = -1;
+static int hf_h225_AdmissionConfirm = -1;
+static int hf_h225_irrFrequency = -1;
+static int hf_h225_willRespondToIRR = -1;
+static int hf_h225_usageSpec = -1;
+static int hf_h225_DisengageRequest = -1;
+static int hf_h225_LocationRequest = -1;
+static int hf_h225_SourceInfo = -1;
+static int hf_h225_hopCount255 = -1;
+static int hf_h225_sourceEndpointInfo = -1;
+static int hf_h225_BandwidthRequest = -1;
+static int hf_h225_bandwidthDetails = -1;
+static int hf_h225_admissionConfirmSequence = -1;
+static int hf_h225_tunnelledSignallingMessage = -1;
+static int hf_h225_messageContent_item = -1;
+static int hf_h225_messageContent = -1;
+static int hf_h225_H323_UU_PDU = -1;
+static int hf_h225_h4501SupplementaryService = -1;
+static int hf_h225_h245Tunneling = -1;
+static int hf_h225_h245Control = -1;
+static int hf_h225_nonStandardControl = -1;
+static int hf_h225_nonStandardControl_item = -1;
+static int hf_h225_preGrantedARQ = -1;
+static int hf_h225_makeCall = -1;
+static int hf_h225_useGKCallSignalAddressToMakeCall = -1;
+static int hf_h225_answerCall = -1;
+static int hf_h225_useGKCallSignalAddressToAnswer = -1;
+static int hf_h225_RegistrationConfirm = -1;
+static int hf_h225_pdu_item = -1;
+static int hf_h225_sent = -1;
+static int hf_h225_pdu = -1;
+static int hf_h225_perCallInfo_item = -1;
+static int hf_h225_originator = -1;
+static int hf_h225_audio = -1;
+static int hf_h225_video = -1;
+static int hf_h225_data = -1;
+static int hf_h225_substituteConfIDs = -1;
+static int hf_h225_perCallInfo = -1;
+static int hf_h225_InfoRequestResponse = -1;
+static int hf_h225_needResponse = -1;
+static int hf_h225_unsolicited = -1;
+static int hf_h225_RasMessage = -1;
+static int hf_h225_H323_UserInformation = -1;
+static int hf_h225_user_data = -1;
+static int hf_h225_protocol_discriminator = -1;
+static int hf_h225_user_information = -1;
+static int hf_h225_object = -1;
+static int hf_h225_t35CountryCode = -1;
+static int hf_h225_t35Extension = -1;
+static int hf_h225_manufacturerCode = -1;
+static int hf_h221Manufacturer = -1;
+static int hf_h225_h221NonStandard = -1;
+static int hf_h225_nonStandardIdentifier = -1;
+static int hf_h225_nsp_data = -1;
+static int hf_h225_nonStandardData = -1;
+static int hf_h225_nonStandard = -1;
+static int hf_h225_nonStandardReason = -1;
+static int hf_h225_nonStandardAddress = -1;
+static int hf_h225_aliasAddress_sequence = -1;
+static int hf_h225_ras_req_frame = -1;
+static int hf_h225_ras_rsp_frame = -1;
+static int hf_h225_ras_dup = -1;
+static int hf_h225_ras_deltatime = -1;
+static int hf_h225_cleartoken = -1;
+static int hf_h225_cryptoEPPwdHash = -1; /* T_cryptoEPPwdHash */
+static int hf_h225_cryptoGKPwdHash = -1; /* T_cryptoGKPwdHash */
+static int hf_h225_timeStamp = -1; /* TimeStamp */
+static int hf_h225_token = -1; /* HASHEDxxx */
+static int hf_h225_cryptoEPPwdEncr = -1; /* ENCRYPTEDxxx */
+static int hf_h225_cryptoGKPwdEncr = -1; /* ENCRYPTEDxxx */
+static int hf_h225_cryptoEPCert = -1; /* SIGNEDxxx */
+static int hf_h225_cryptoGKCert = -1; /* SIGNEDxxx */
+static int hf_h225_cryptoFastStart = -1; /* SIGNEDxxx */
+static int hf_h225_nestedcryptoToken = -1; /* CryptoToken */
+static int hf_h225_cryptoTokens_item = -1; /* CryptoH323Token */
+static int hf_h225_authenticationCapability = -1; /* SEQUENCE_OF_AuthenticationMechanism */
+static int hf_h225_authenticationCapability_item = -1; /* AuthenticationMechanism */
+static int hf_h225_authenticationMode = -1; /* AuthenticationMechanism */
+static int hf_h225_alertingTime = -1; /* TimeStamp */
+static int hf_h225_connectTime = -1; /* TimeStamp */
+static int hf_h225_endTimeStamp = -1; /* TimeStamp */
+/*aaa*/
+
+static gint ett_h225 = -1;
+static gint ett_h225_T_nonStandardUsageTypes = -1;
+static gint ett_h225_PresentationIndicator = -1;
+static gint ett_h225_CryptoH323Token = -1;
+static gint ett_h225_conferenceGoal = -1;
+static gint ett_h225_ScnConnectionType = -1;
+static gint ett_h225_ScnConnectionAggregation = -1;
+static gint ett_h225_FacilityReason = -1;
+static gint ett_h225_PublicTypeOfNumber = -1;
+static gint ett_h225_PrivateTypeOfNumber = -1;
+static gint ett_h225_UseSpecifiedTransport = -1;
+static gint ett_h225_SecurityErrors = -1;
+static gint ett_h225_SecurityErrors2 = -1;
+static gint ett_h225_ServiceControlSession_reason = -1;
+static gint ett_h225_billingMode = -1;
+static gint ett_h225_CCSCcallStartingPoint = -1;
+static gint ett_h225_GatekeeperRejectReason = -1;
+static gint ett_h225_UnregRequestReason = -1;
+static gint ett_h225_UnregRejectReason = -1;
+static gint ett_h225_CallType = -1;
+static gint ett_h225_CallModel = -1;
+static gint ett_h225_TransportQOS = -1;
+static gint ett_h225_BandRejectReason = -1;
+static gint ett_h225_DisengageReason = -1;
+static gint ett_h225_DisengageRejectReason = -1;
+static gint ett_h225_InfoRequestNakReason = -1;
+static gint ett_h225_SCRresult = -1;
+static gint ett_h225_GatekeeperInfo = -1;
+static gint ett_h225_SecurityServiceMode_encryption = -1;
+static gint ett_h225_SecurityServiceMode_authentication = -1;
+static gint ett_h225_SecurityServiceMode_integrity = -1;
+static gint ett_h225_SecurityCapabilities_tls = -1;
+static gint ett_h225_SecurityCapabilities_ipsec = -1;
+static gint ett_h225_H245Security = -1;
+static gint ett_h225_RasUsageInfoTypes = -1;
+static gint ett_h225_DataRate = -1;
+static gint ett_h225_dataRatesSupported = -1;
+static gint ett_h225_TerminalInfo = -1;
+static gint ett_h225_StimulusControl = -1;
+static gint ett_h225_ReleaseCompleteReason = -1;
+static gint ett_h225_connectionParameters = -1;
+static gint ett_h225_RasUsageSpecification_when = -1;
+static gint ett_h225_RasUsageSpecification_callStartingPoint = -1;
+static gint ett_h225_RasUsageSpecification = -1;
+static gint ett_h225_ipAddress = -1;
+static gint ett_h225_routing = -1;
+static gint ett_h225_route = -1;
+static gint ett_h225_ipSourceRoute = -1;
+static gint ett_h225_ipxAddress = -1;
+static gint ett_h225_ip6Address = -1;
+static gint ett_h225_TransportAddress = -1;
+static gint ett_h225_TransportChannelInfo = -1;
+static gint ett_h225_CarrierInfo = -1;
+static gint ett_h225_InfoRequestResponseStatus = -1;
+static gint ett_h225_CallIdentifier = -1;
+static gint ett_h225_CallLinkage = -1;
+static gint ett_h225_tokens = -1;
+static gint ett_h225_CryptoH323Tokens = -1;
+static gint ett_h225_AlternateGK = -1;
+static gint ett_h225_alternateGatekeeper = -1;
+static gint ett_h225_AltGKInfo = -1;
+static gint ett_h225_annexE = -1;
+static gint ett_h225_sctp = -1;
+static gint ett_h225_AlternateTransportAddress = -1;
+static gint ett_h225_UUIEsRequested = -1;
+static gint ett_h225_Q954Details = -1;
+static gint ett_h225_QseriesOptions = -1;
+static gint ett_h225_associatedSessionIds = -1;
+static gint ett_h225_RTPSession = -1;
+static gint ett_h225_StatusUUIE = -1;
+static gint ett_h225_StatusInquiryUUIE = -1;
+static gint ett_h225_SetupAcknowledgeUUIE = -1;
+static gint ett_h225_NotifyUUIE = -1;
+static gint ett_h225_GSMUIM = -1;
+static gint ett_h225_systemid = -1;
+static gint ett_h225_ANSI41UIM = -1;
+static gint ett_h225_MobileUIM = -1;
+static gint ett_h225_e164Number = -1;
+static gint ett_h225_privateNumber = -1;
+static gint ett_h225_PartyNumber = -1;
+static gint ett_h225_TunnelledProtocolAlternateIdentifier = -1;
+static gint ett_h225_AliasAddress = -1;
+static gint ett_h225_SupportedPrefix = -1;
+static gint ett_h225_SupportedPrefixes = -1;
+static gint ett_h225_H310Caps = -1;
+static gint ett_h225_H320Caps = -1;
+static gint ett_h225_H321Caps = -1;
+static gint ett_h225_H322Caps = -1;
+static gint ett_h225_H323Caps = -1;
+static gint ett_h225_H324Caps = -1;
+static gint ett_h225_VoiceCaps = -1;
+static gint ett_h225_T120OnlyCaps = -1;
+static gint ett_h225_NonStandardProtocol = -1;
+static gint ett_h225_SIPCaps = -1;
+static gint ett_h225_AddressPattern_range = -1;
+static gint ett_h225_AddressPattern = -1;
+static gint ett_h225_ConferenceList = -1;
+static gint ett_h225_conferences = -1;
+static gint ett_h225_T38FaxAnnexbOnlyCaps = -1;
+static gint ett_h225_SupportedProtocols = -1;
+static gint ett_h225_protocol = -1;
+static gint ett_h225_GatewayInfo = -1;
+static gint ett_h225_McuInfo = -1;
+static gint ett_h225_TunnelledProtocol_id = -1;
+static gint ett_h225_TunnelledProtocol = -1;
+static gint ett_h225_TunnelledProtocols = -1;
+static gint ett_h225_CicInfo_cic = -1;
+static gint ett_h225_CicInfo = -1;
+static gint ett_h225_GroupID_member = -1;
+static gint ett_h225_GroupID = -1;
+static gint ett_h225_CircuitIdentifier = -1;
+static gint ett_h225_GenericIdentifier = -1;
+static gint ett_h225_EnumeratedParameter = -1;
+static gint ett_h225_parameters = -1;
+static gint ett_h225_GenericData = -1;
+static gint ett_h225_Content = -1;
+static gint ett_h225_Content_compound = -1;
+static gint ett_h225_Content_nested = -1;
+static gint ett_h225_neededFeatures = -1;
+static gint ett_h225_desiredFeatures = -1;
+static gint ett_h225_supportedFeatures = -1;
+static gint ett_h225_FeatureSet = -1;
+static gint ett_h225_CallsAvailable = -1;
+static gint ett_h225_voiceGwCallsAvailable = -1;
+static gint ett_h225_h310GwCallsAvailable = -1;
+static gint ett_h225_h320GwCallsAvailable = -1;
+static gint ett_h225_h321GwCallsAvailable = -1;
+static gint ett_h225_h322GwCallsAvailable = -1;
+static gint ett_h225_h323GwCallsAvailable = -1;
+static gint ett_h225_h324GwCallsAvailable = -1;
+static gint ett_h225_t120OnlyGwCallsAvailable = -1;
+static gint ett_h225_t38FaxAnnexbOnlyGwCallsAvailable = -1;
+static gint ett_h225_terminalCallsAvailable = -1;
+static gint ett_h225_mcuCallsAvailable = -1;
+static gint ett_h225_sipGwCallsAvailable = -1;
+static gint ett_h225_CallCapacityInfo = -1;
+static gint ett_h225_CallCapacity = -1;
+static gint ett_h225_VendorIdentifier = -1;
+static gint ett_h225_CapacityReportingCapability = -1;
+static gint ett_h225_CallCreditCapability = -1;
+static gint ett_h225_BandwidthDetails = -1;
+static gint ett_h225_CallTerminationCause = -1;
+static gint ett_h225_CircuitInfo = -1;
+static gint ett_h225_genericData = -1;
+static gint ett_h225_fastStart = -1;
+static gint ett_h225_InformationUUIE = -1;
+static gint ett_h225_routeCallToSCN = -1;
+static gint ett_h225_AdmissionRejectReason = -1;
+static gint ett_h225_EncryptIntAlg = -1;
+static gint ett_h225_NonIsoIntegrityMechanism = -1;
+static gint ett_h225_IntegrityMechanism = -1;
+static gint ett_h225_LocationRejectReason = -1;
+static gint ett_h225_EndPointType = -1;
+static gint ett_h225_CallProceedingUUIE = -1;
+static gint ett_h225_CapacityReportingSpecification_when = -1;
+static gint ett_h225_CapacityReportingSpecification = -1;
+static gint ett_h225_ProgressUUIE = -1;
+static gint ett_h225_EndPoint = -1;
+static gint ett_h225_destExtraCallInfo = -1;
+static gint ett_h225_remoteExtensionAddress = -1;
+static gint ett_h225_rasAddress_sequence = -1;
+static gint ett_h225_callSignalAddress = -1;
+static gint ett_h225_ICV = -1;
+static gint ett_h225_BandwidthConfirm = -1;
+static gint ett_h225_UnregistrationConfirm = -1;
+static gint ett_h225_NonStandardMessage = -1;
+static gint ett_h225_InfoRequestAck = -1;
+static gint ett_h225_InfoRequestNak = -1;
+static gint ett_h225_ResourcesAvailableConfirm = -1;
+static gint ett_h225_GatekeeperRequest = -1;
+static gint ett_h225_integrity = -1;
+static gint ett_h225_algorithmOIDs = -1;
+static gint ett_h225_alternateEndpoints = -1;
+static gint ett_h225_endpointAlias = -1;
+static gint ett_h225_ServiceControlResponse = -1;
+static gint ett_h225_DisengageReject = -1;
+static gint ett_h225_BandwidthReject = -1;
+static gint ett_h225_UnregistrationReject = -1;
+static gint ett_h225_UnregistrationRequest = -1;
+static gint ett_h225_endpointAliasPattern = -1;
+static gint ett_h225_RegistrationReject = -1;
+static gint ett_h225_invalidTerminalAliases = -1;
+static gint ett_h225_terminalAlias = -1;
+static gint ett_h225_terminalAliasPattern = -1;
+static gint ett_h225_RegistrationRejectReason = -1;
+static gint ett_h225_duplicateAlias = -1;
+static gint ett_h225_GatekeeperReject = -1;
+static gint ett_h225_ResourcesAvailableIndicate = -1;
+static gint ett_h225_protocols = -1;
+static gint ett_h225_CallCreditServiceControl = -1;
+static gint ett_h225_ExtendedAliasAddress = -1;
+static gint ett_h225_UnknownMessageResponse = -1;
+static gint ett_h225_AdmissionRequest = -1;
+static gint ett_h225_desiredProtocols = -1;
+static gint ett_h225_destAlternatives = -1;
+static gint ett_h225_srcAlternatives = -1;
+static gint ett_h225_srcInfo = -1;
+static gint ett_h225_DestinationInfo = -1;
+static gint ett_h225_InfoRequest = -1;
+static gint ett_h225_RequestInProgress = -1;
+static gint ett_h225_ServiceControlDescriptor = -1;
+static gint ett_h225_ServiceControlSession = -1;
+static gint ett_h225_AlertingUUIE = -1;
+static gint ett_h225_serviceControl = -1;
+static gint ett_h225_alertingAddress = -1;
+static gint ett_h225_ReleaseCompleteUUIE = -1;
+static gint ett_h225_busyAddress = -1;
+static gint ett_h225_FacilityUUIE = -1;
+static gint ett_h225_alternativeAliasAddress = -1;
+static gint ett_h225_AdmissionReject = -1;
+static gint ett_h225_parallelH245Control = -1;
+static gint ett_h225_languages = -1;
+static gint ett_h225_SetupUUIE = -1;
+static gint ett_h225_sourceAddress = -1;
+static gint ett_h225_destinationAddress = -1;
+static gint ett_h225_destExtraCRV = -1;
+static gint ett_h225_h245SecurityCapability = -1;
+static gint ett_h225_additionalSourceAddresses = -1;
+static gint ett_h225_ConnectUUIE = -1;
+static gint ett_h225_connectedAddress = -1;
+static gint ett_h225_h323_message_body = -1;
+static gint ett_h225_LocationConfirm = -1;
+static gint ett_h225_supportedProtocols = -1;
+static gint ett_h225_modifiedSrcInfo = -1;
+static gint ett_h225_LocationReject = -1;
+static gint ett_h225_callSpecific = -1;
+static gint ett_h225_ServiceControlIndication = -1;
+static gint ett_h225_RasUsageInformation = -1;
+static gint ett_h225_T_nonStandardUsageFields = -1;
+static gint ett_h225_GatekeeperConfirm = -1;
+static gint ett_h225_RegistrationRequest = -1;
+static gint ett_h225_supportedH248Packages = -1;
+static gint ett_h225_DisengageConfirm = -1;
+static gint ett_h225_AdmissionConfirm = -1;
+static gint ett_h225_usageSpec = -1;
+static gint ett_h225_DisengageRequest = -1;
+static gint ett_h225_LocationRequest = -1;
+static gint ett_h225_SourceInfo = -1;
+static gint ett_h225_sourceEndpointInfo = -1;
+static gint ett_h225_BandwidthRequest = -1;
+static gint ett_h225_bandwidthDetails = -1;
+static gint ett_h225_admissionConfirmSequence = -1;
+static gint ett_h225_tunnelledSignallingMessage = -1;
+static gint ett_h225_messageContent = -1;
+static gint ett_h225_H323_UU_PDU = -1;
+static gint ett_h225_h4501SupplementaryService = -1;
+static gint ett_h225_h245Control = -1;
+static gint ett_h225_T_nonStandardControl = -1;
+static gint ett_h225_preGrantedARQ = -1;
+static gint ett_h225_RegistrationConfirm = -1;
+static gint ett_h225_pdu_item = -1;
+static gint ett_h225_pdu = -1;
+static gint ett_h225_perCallInfo_item = -1;
+static gint ett_h225_audio = -1;
+static gint ett_h225_video = -1;
+static gint ett_h225_data = -1;
+static gint ett_h225_substituteConfIDs = -1;
+static gint ett_h225_perCallInfo = -1;
+static gint ett_h225_InfoRequestResponse = -1;
+static gint ett_h225_RasMessage = -1;
+static gint ett_h225_H323_UserInformation = -1;
+static gint ett_h225_user_data = -1;
+static gint ett_h225_H221NonStandard = -1;
+static gint ett_h225_NonStandardIdentifier = -1;
+static gint ett_h225_NonStandardParameter = -1;
+static gint ett_h225_aliasAddress_sequence = -1;
+static gint ett_h225_T_cryptoEPPwdHash = -1;
+static gint ett_h225_T_cryptoGKPwdHash = -1;
+static gint ett_h225_AuthenticationMechanism_sequence_of = -1;
+/*bbb*/
+
+/* Subdissector tables */
+static dissector_table_t nsp_object_dissector_table;
+static dissector_table_t nsp_h221_dissector_table;
+static dissector_table_t tp_dissector_table;
+
+
+static dissector_handle_t h245_handle=NULL;
+static dissector_handle_t h245dg_handle=NULL;
+static dissector_handle_t h4501_handle=NULL;
+
+
+static dissector_handle_t nsp_handle;
+static dissector_handle_t tp_handle;
+
+static guint32 ipv4_address;
+static guint32 ipv4_port;
+static char object[256];
+static guint32 t35CountryCode;
+static guint32 t35Extension;
+static guint32 manufacturerCode;
+static guint32 h221NonStandard;
+static char tpID[256];
+
+static gboolean contains_faststart = FALSE;
+
+static const true_false_string tfs_unsolicited_bit = {
+ "unsolicited bit is SET",
+ "unsolicited bit is NOT set"
+};
+
+static const true_false_string tfs_needResponse_bit = {
+ "needResponse bit is SET",
+ "needResponse bit is NOT set"
+};
+
+static const true_false_string tfs_originator_bit = {
+ "originator bit is SET",
+ "originator bit is NOT set"
+};
+
+static const true_false_string tfs_sent_bit = {
+ "sent bit is SET",
+ "sent bit is NOT set"
+};
+
+static const true_false_string tfs_useGKCallSignalAddressToAnswer_bit = {
+ "useGKCallSignalAddressToAnswer bit is SET",
+ "useGKCallSignalAddressToAnswer bit is NOT set"
+};
+
+static const true_false_string tfs_answerCall_bit = {
+ "answerCall bit is SET",
+ "answerCall bit is NOT set"
+};
+
+static const true_false_string tfs_useGKCallSignalAddressToMakeCall_bit = {
+ "useGKCallSignalAddressToMakeCall bit is SET",
+ "useGKCallSignalAddressToMakeCall bit is NOT set"
+};
+
+static const true_false_string tfs_makeCall_bit = {
+ "makeCall bit is SET",
+ "makeCall bit is NOT set"
+};
+
+static const true_false_string tfs_h245Tunneling_bit = {
+ "h245Tunneling bit is SET",
+ "h245Tunneling bit is NOT set"
+};
+
+static const true_false_string tfs_willRespondToIRR_bit = {
+ "willRespondToIRR bit is SET",
+ "willRespondToIRR bit is NOT set"
+};
+
+static const true_false_string tfs_keepAlive_bit = {
+ "keepAlive bit is SET",
+ "keepAlive bit is NOT set"
+};
+
+static const true_false_string tfs_discoveryComplete_bit = {
+ "discoveryComplete bit is SET",
+ "discoveryComplete bit is NOT set"
+};
+
+static const true_false_string tfs_answeredCall_bit = {
+ "answeredCall bit is SET",
+ "answeredCall bit is NOT set"
+};
+
+static const true_false_string tfs_canOverlapSend_bit = {
+ "canOverlapSend bit is SET",
+ "canOverlapSend bit is NOT set"
+};
+
+static const true_false_string tfs_mediaWaitForConnect_bit = {
+ "mediaWaitForConnect bit is SET",
+ "mediaWaitForConnect bit is NOT set"
+};
+
+static const true_false_string tfs_activeMC_bit = {
+ "activeMC bit is SET",
+ "activeMC bit is NOT set"
+};
+
+static const true_false_string tfs_canMapAlias_bit = {
+ "canMapAlias bit is SET",
+ "canMapAlias bit is NOT set"
+};
+
+static const true_false_string tfs_willSupplyUUIEs_bit = {
+ "willSupplyUUIEs bit is SET",
+ "willSupplyUUIEs bit is NOT set"
+};
+
+static const true_false_string tfs_canMapSrcAlias_bit = {
+ "canMapSrcAlias bit is SET",
+ "canMapSrcAlias bit is NOT set"
+};
+
+static const true_false_string tfs_enforceCallDurationLimit_bit = {
+ "enforceCallDurationLimit bit is SET",
+ "enforceCallDurationLimit bit is NOT set"
+};
+
+static const true_false_string tfs_almostOutOfResources_bit = {
+ "almostOutOfResources bit is SET",
+ "almostOutOfResources bit is NOT set"
+};
+
+static const true_false_string tfs_maintainConnection_bit = {
+ "maintainConnection bit is SET",
+ "maintainConnection bit is NOT set"
+};
+
+static const true_false_string tfs_multipleCalls_bit = {
+ "multipleCalls bit is SET",
+ "multipleCalls bit is NOT set"
+};
+
+static const true_false_string tfs_undefinedNode_bit = {
+ "undefinedNode bit is SET",
+ "undefinedNode bit is NOT set"
+};
+
+static const true_false_string tfs_mc_bit = {
+ "mc bit is SET",
+ "mc bit is NOT set"
+};
+
+
+static const true_false_string tfs_fastConnectRefused_bit = {
+ "fastConnectRefused bit is SET",
+ "fastConnectRefused bit is NOT set"
+};
+
+static const true_false_string tfs_BandwidthDetails_multicast_bit = {
+ "BandwidthDetails_multicast bit is SET",
+ "BandwidthDetails_multicast bit is NOT set"
+};
+
+static const true_false_string tfs_BandwidthDetails_sender_bit = {
+ "BandwidthDetails_sender bit is SET",
+ "BandwidthDetails_sender bit is NOT set"
+};
+
+static const true_false_string tfs_canEnforceDurationLimit_bit = {
+ "canEnforceDurationLimit bit is SET",
+ "canEnforceDurationLimit bit is NOT set"
+};
+
+static const true_false_string tfs_canDisplayAmountString_bit = {
+ "canDisplayAmountString bit is SET",
+ "canDisplayAmountString bit is NOT set"
+};
+
+static const true_false_string tfs_canReportCallCapacity_bit = {
+ "canReportCallCapacity bit is SET",
+ "canReportCallCapacity bit is NOT set"
+};
+
+static const true_false_string tfs_replacementFeatureSet_bit = {
+ "replacementFeatureSet bit is SET",
+ "replacementFeatureSet bit is NOT set"
+};
+
+static const true_false_string tfs_Content_bool_bit = {
+ "Content_bool bit is SET",
+ "Content_bool bit is NOT set"
+};
+
+static const true_false_string tfs_q957Full_bit = {
+ "q957Full bit is SET",
+ "q957Full bit is NOT set"
+};
+
+static const true_false_string tfs_q956Full_bit = {
+ "q956Full bit is SET",
+ "q956Full bit is NOT set"
+};
+
+static const true_false_string tfs_q955Full_bit = {
+ "q955Full bit is SET",
+ "q955Full bit is NOT set"
+};
+
+static const true_false_string tfs_q953Full_bit = {
+ "q953Full bit is SET",
+ "q953Full bit is NOT set"
+};
+
+static const true_false_string tfs_q952Full_bit = {
+ "q952Full bit is SET",
+ "q952Full bit is NOT set"
+};
+
+static const true_false_string tfs_q951Full_bit = {
+ "q951Full bit is SET",
+ "q951Full bit is NOT set"
+};
+
+static const true_false_string tfs_q932Full_bit = {
+ "q932Full bit is SET",
+ "q932Full bit is NOT set"
+};
+
+static const true_false_string tfs_threePartyService_bit = {
+ "threePartyService bit is SET",
+ "threePartyService bit is NOT set"
+};
+
+static const true_false_string tfs_conferenceCalling_bit = {
+ "conferenceCalling bit is SET",
+ "conferenceCalling bit is NOT set"
+};
+
+static const true_false_string tfs_notify_bool_bit = {
+ "notify_bool bit is SET",
+ "notify_bool bit is NOT set"
+};
+
+static const true_false_string tfs_setupAcknowledge_bool_bit = {
+ "setupAcknowledge_bool bit is SET",
+ "setupAcknowledge_bool bit is NOT set"
+};
+
+static const true_false_string tfs_statusInquiry_bool_bit = {
+ "statusInquiry_bool bit is SET",
+ "statusInquiry_bool bit is NOT set"
+};
+
+static const true_false_string tfs_status_bool_bit = {
+ "status_bool bit is SET",
+ "status_bool bit is NOT set"
+};
+
+static const true_false_string tfs_empty_bool_bit = {
+ "empty_bool bit is SET",
+ "empty_bool bit is NOT set"
+};
+
+static const true_false_string tfs_progress_bool_bit = {
+ "progress_bool bit is SET",
+ "progress_bool bit is NOT set"
+};
+
+static const true_false_string tfs_facility_bool_bit = {
+ "facility_bool bit is SET",
+ "facility_bool bit is NOT set"
+};
+
+static const true_false_string tfs_releaseComplete_bool_bit = {
+ "releaseComplete_bool bit is SET",
+ "releaseComplete_bool bit is NOT set"
+};
+
+static const true_false_string tfs_information_bool_bit = {
+ "information_bool bit is SET",
+ "information_bool bit is NOT set"
+};
+
+static const true_false_string tfs_alerting_bool_bit = {
+ "alerting_bool bit is SET",
+ "alerting_bool bit is NOT set"
+};
+
+static const true_false_string tfs_connect_bool_bit = {
+ "connect_bool bit is SET",
+ "connect_bool bit is NOT set"
+};
+
+static const true_false_string tfs_callProceeding_bool_bit = {
+ "callProceeding_bool bit is SET",
+ "callProceeding_bool bit is NOT set"
+};
+
+static const true_false_string tfs_setup_bool_bit = {
+ "setup_bool bit is SET",
+ "setup_bool bit is NOT set"
+};
+
+static const true_false_string tfs_altGKisPermanent_bit = {
+ "altGKisPermanent bit is SET",
+ "altGKisPermanent bit is NOT set"
+};
+
+static const true_false_string tfs_needToRegister_bit = {
+ "needToRegister bit is SET",
+ "needToRegister bit is NOT set"
+};
+
+
+
+static gboolean h225_reassembly = TRUE;
+
+
+
+static int
+dissect_h225_NULL(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_, proto_tree *tree _U_)
+{
+ return offset;
+}
+
+static const value_string PresentationIndicator_vals[] = {
+ { 0, "presentationAllowed" },
+ { 1, "presentationRestricted" },
+ { 2, "addressNotAvailable" },
+ { 0, NULL}
+};
+static per_choice_t PresentationIndicator_choice[] = {
+ { 0, "presentationAllowed", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL},
+ { 1, "presentationRestricted", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL},
+ { 2, "addressNotAvailable", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL},
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_PresentationIndicator(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_PresentationIndicator, ett_h225_PresentationIndicator, PresentationIndicator_choice, "PresentationIndicator", NULL);
+ return offset;
+}
+
+
+static const value_string conferenceGoal_vals[] = {
+ { 0, "create" },
+ { 1, "join" },
+ { 2, "invite" },
+ { 3, "capability-negotiation" },
+ { 4, "callIndependentSupplementaryService" },
+ { 0, NULL}
+};
+static per_choice_t conferenceGoal_choice[] = {
+ { 0, "create", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "join", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "invite", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "capability-negotiation", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "callIndependentSupplementaryService", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_conferenceGoal(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_conferenceGoal, ett_h225_conferenceGoal, conferenceGoal_choice, "conferenceGoal", NULL);
+ return offset;
+}
+
+
+static const value_string ScnConnectionType_vals[] = {
+ { 0, "unknown" },
+ { 1, "bChannel" },
+ { 2, "hybrid2x64" },
+ { 3, "hybrid384" },
+ { 4, "hybrid1536" },
+ { 5, "hybrid1920" },
+ { 6, "multirate" },
+ { 0, NULL}
+};
+static per_choice_t ScnConnectionType_choice[] = {
+ { 0, "unknown", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "bChannel", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "hybrid2x64", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "hybrid384", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "hybrid1536", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "hybrid1920", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 6, "multirate", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_ScnConnectionType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_ScnConnectionType, ett_h225_ScnConnectionType, ScnConnectionType_choice, "ScnConnectionType", NULL);
+ return offset;
+}
+
+
+static const value_string ScnConnectionAggregation_vals[] = {
+ { 0, "auto" },
+ { 1, "none" },
+ { 2, "h221" },
+ { 3, "bonded-mode1" },
+ { 4, "bonded-mode2" },
+ { 5, "bonded-mode3" },
+ { 0, NULL}
+};
+static per_choice_t ScnConnectionAggregation_choice[] = {
+ { 0, "auto", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "none", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "h221", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "bonded-mode1", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "bonded-mode2", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "bonded-mode3", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_ScnConnectionAggregation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_ScnConnectionAggregation, ett_h225_ScnConnectionAggregation, ScnConnectionAggregation_choice, "ScnConnectionAggregation", NULL);
+ return offset;
+}
+
+
+const value_string FacilityReason_vals[] = {
+ { 0, "routeCallToGatekeeper" },
+ { 1, "callForwarded" },
+ { 2, "routeCallToMC" },
+ { 3, "undefinedReason" },
+ { 4, "conferenceListChoice" },
+ { 5, "startH245" },
+ { 6, "noH245" },
+ { 7, "newTokens" },
+ { 8, "featureSetUpdate" },
+ { 9, "forwardedElements" },
+ { 10, "transportedInformation" },
+ { 0, NULL}
+};
+static per_choice_t FacilityReason_choice[] = {
+ { 0, "routeCallToGatekeeper", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "callForwarded", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "routeCallToMC", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "conferenceListChoice", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "startH245", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 6, "noH245", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 7, "newTokens", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 8, "featureSetUpdate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 9, "forwardedElements", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 10, "transportedInformation", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_FacilityReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_FacilityReason, ett_h225_FacilityReason, FacilityReason_choice, "FacilityReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+static const value_string PublicTypeOfNumber_vals[] = {
+ { 0, "unknown" },
+ { 1, "internationalNumber" },
+ { 2, "nationalNumber" },
+ { 3, "networkSpecificNumber" },
+ { 4, "subscriberNumber" },
+ { 5, "abbreviatedNumber" },
+ { 0, NULL}
+};
+static per_choice_t PublicTypeOfNumber_choice[] = {
+ { 0, "unknown", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "internationalNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "nationalNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "networkSpecificNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "subscriberNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "abbreviatedNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_PublicTypeOfNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_PublicTypeOfNumber, ett_h225_PublicTypeOfNumber, PublicTypeOfNumber_choice, "PublicTypeOfNumber", NULL);
+ return offset;
+}
+
+
+
+static const value_string PrivateTypeOfNumber_vals[] = {
+ { 0, "unknown" },
+ { 1, "level2RegionalNumber" },
+ { 2, "level1RegionalNumber" },
+ { 3, "pISNSpecificNumber" },
+ { 4, "localNumber" },
+ { 5, "abbreviatedNumber" },
+ { 0, NULL}
+};
+static per_choice_t PrivateTypeOfNumber_choice[] = {
+ { 0, "unknown", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "level2RegionalNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "level1RegionalNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "pISNSpecificNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "localNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "abbreviatedNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_PrivateTypeOfNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_PrivateTypeOfNumber, ett_h225_PrivateTypeOfNumber, PrivateTypeOfNumber_choice, "PrivateTypeOfNumber", NULL);
+ return offset;
+}
+
+
+static const value_string UseSpecifiedTransport_vals[] = {
+ { 0, "tcp" },
+ { 1, "annexE" },
+ { 2, "sctp" },
+ { 0, NULL}
+};
+static per_choice_t UseSpecifiedTransport_choice[] = {
+ { 0, "tcp", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "annexE", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "sctp", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_UseSpecifiedTransport(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_UseSpecifiedTransport, ett_h225_UseSpecifiedTransport, UseSpecifiedTransport_choice, "UseSpecifiedTransport", NULL);
+ return offset;
+}
+
+
+
+static const value_string SecurityErrors_vals[] = {
+ { 0, "securityWrongSyncTime" },
+ { 1, "securityReplay" },
+ { 2, "securityWrongGeneralID" },
+ { 3, "securityWrongSendersID" },
+ { 4, "securityIntegrityFailed" },
+ { 5, "securityWrongOID" },
+ { 6, "securityDHmismatch" },
+ { 7, "securityCertificateExpired" },
+ { 8, "securityCertificateDateInvalid" },
+ { 9, "securityCertificateRevoked" },
+ { 10, "securityCertificateNotReadable" },
+ { 11, "securityCertificateSignatureInvalid" },
+ { 12, "securityCertificateMissing" },
+ { 13, "securityCertificateIncomplete" },
+ { 14, "securityUnsupportedCertificateAlgOID" },
+ { 15, "securityUnknownCA" },
+ { 0, NULL}
+};
+static per_choice_t SecurityErrors_choice[] = {
+ { 0, "securityWrongSyncTime", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "securityReplay", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "securityWrongGeneralID", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "securityWrongSendersID", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "securityIntegrityFailed", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "securityWrongOID", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 6, "securityDHmismatch", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 7, "securityCertificateExpired", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 8, "securityCertificateDateInvalid", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 9, "securityCertificateRevoked", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 10, "securityCertificateNotReadable", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 11, "securityCertificateSignatureInvalid", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 12, "securityCertificateMissing", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 13, "securityCertificateIncomplete", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 14, "securityUnsupportedCertificateAlgOID", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 15, "securityUnknownCA", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_SecurityErrors(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_SecurityErrors, ett_h225_SecurityErrors, SecurityErrors_choice, "SecurityErrors", NULL);
+ return offset;
+}
+
+
+
+static const value_string SecurityErrors2_vals[] = {
+ { 0, "securityWrongSyncTime" },
+ { 1, "securityReplay" },
+ { 2, "securityWrongGeneralID" },
+ { 3, "securityWrongSendersID" },
+ { 4, "securityIntegrityFailed" },
+ { 5, "securityWrongOID" },
+ { 0, NULL}
+};
+static per_choice_t SecurityErrors2_choice[] = {
+ { 0, "securityWrongSyncTime", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "securityReplay", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "securityWrongGeneralID", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "securityWrongSendersID", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "securityIntegrityFailed", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "securityWrongOID", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_SecurityErrors2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_SecurityErrors2, ett_h225_SecurityErrors2, SecurityErrors2_choice, "SecurityErrors2", NULL);
+ return offset;
+}
+
+
+static const value_string ServiceControlSession_reason_vals[] = {
+ { 0, "open" },
+ { 1, "refresh" },
+ { 2, "close" },
+ { 0, NULL}
+};
+static per_choice_t ServiceControlSession_reason_choice[] = {
+ { 0, "open", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "refresh", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "close", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_ServiceControlSession_reason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_ServiceControlSession_reason, ett_h225_ServiceControlSession_reason, ServiceControlSession_reason_choice, "ServiceControlSession_reason", NULL);
+ return offset;
+}
+
+
+
+static const value_string billingMode_vals[] = {
+ { 0, "credit" },
+ { 1, "debit" },
+ { 0, NULL}
+};
+static per_choice_t billingMode_choice[] = {
+ { 0, "credit", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "debit", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_billingMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_billingMode, ett_h225_billingMode, billingMode_choice, "billingMode", NULL);
+ return offset;
+}
+
+
+
+static const value_string CCSCcallStartingPoint_vals[] = {
+ { 0, "alerting" },
+ { 1, "connect" },
+ { 0, NULL}
+};
+static per_choice_t CCSCcallStartingPoint_choice[] = {
+ { 0, "alerting", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "connect", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_CCSCcallStartingPoint(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_CCSCcallStartingPoint, ett_h225_CCSCcallStartingPoint, CCSCcallStartingPoint_choice, "CCSCcallStartingPoint", NULL);
+ return offset;
+}
+
+
+
+const value_string GatekeeperRejectReason_vals[] = {
+ { 0, "resourceUnavailable" },
+ { 1, "terminalExcluded" },
+ { 2, "invalidRevision" },
+ { 3, "undefinedReason" },
+ { 4, "securityDenial" },
+ { 5, "genericDataReason" },
+ { 6, "neededFeatureNotSupported" },
+ { 7, "securityError" },
+ { 0, NULL}
+};
+static per_choice_t GatekeeperRejectReason_choice[] = {
+ { 0, "resourceUnavailable", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "terminalExcluded", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "invalidRevision", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "securityDenial", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "genericDataReason", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 6, "neededFeatureNotSupported", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 7, "securityError", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_GatekeeperRejectReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_GatekeeperRejectReason, ett_h225_GatekeeperRejectReason, GatekeeperRejectReason_choice, "GatekeeperRejectReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+const value_string UnregRequestReason_vals[] = {
+ { 0, "reregistrationRequired" },
+ { 1, "ttlExpired" },
+ { 2, "securityDenial" },
+ { 3, "undefinedReason" },
+ { 4, "maintenance" },
+ { 5, "securityError" },
+ { 0, NULL}
+};
+static per_choice_t UnregRequestReason_choice[] = {
+ { 0, "reregistrationRequired", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "ttlExpired", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "securityDenial", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "maintenance", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "securityError", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors2 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_UnregRequestReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_UnregRequestReason, ett_h225_UnregRequestReason, UnregRequestReason_choice, "UnregRequestReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+const value_string UnregRejectReason_vals[] = {
+ { 0, "notCurrentlyRegistered" },
+ { 1, "callInProgress" },
+ { 2, "undefinedReason" },
+ { 3, "permissionDenied" },
+ { 4, "securityDenial" },
+ { 5, "securityError" },
+ { 0, NULL}
+};
+static per_choice_t UnregRejectReason_choice[] = {
+ { 0, "notCurrentlyRegistered", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "callInProgress", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "permissionDenied", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "securityDenial", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "securityError", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors2 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_UnregRejectReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_UnregRejectReason, ett_h225_UnregRejectReason, UnregRejectReason_choice, "UnregRejectReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+static const value_string CallType_vals[] = {
+ { 0, "pointToPoint" },
+ { 1, "oneToN" },
+ { 2, "nToOne" },
+ { 3, "nToN" },
+ { 0, NULL}
+};
+static per_choice_t CallType_choice[] = {
+ { 0, "pointToPoint", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "oneToN", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "nToOne", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "nToN", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_CallType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_CallType, ett_h225_CallType, CallType_choice, "CallType", NULL);
+ return offset;
+}
+
+
+static const value_string CallModel_vals[] = {
+ { 0, "direct" },
+ { 1, "gatekeeperRouted" },
+ { 0, NULL}
+};
+static per_choice_t CallModel_choice[] = {
+ { 0, "direct", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "gatekeeperRouted", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_CallModel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_CallModel, ett_h225_CallModel, CallModel_choice, "CallModel", NULL);
+ return offset;
+}
+
+
+
+static const value_string TransportQOS_vals[] = {
+ { 0, "endpointControlled" },
+ { 1, "gatekeeperControlled" },
+ { 2, "noControl" },
+ { 0, NULL}
+};
+static per_choice_t TransportQOS_choice[] = {
+ { 0, "endpointControlled", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "gatekeeperControlled", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "noControl", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_TransportQOS(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_TransportQOS, ett_h225_TransportQOS, TransportQOS_choice, "TransportQOS", NULL);
+ return offset;
+}
+
+
+const value_string BandRejectReason_vals[] = {
+ { 0, "notBound" },
+ { 1, "invalidConferenceID" },
+ { 2, "invalidPermission" },
+ { 3, "insufficientResources" },
+ { 4, "invalidRevision" },
+ { 5, "undefinedReason" },
+ { 6, "securityDenial" },
+ { 7, "securityError" },
+ { 0, NULL}
+};
+static per_choice_t BandRejectReason_choice[] = {
+ { 0, "notBound", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "invalidConferenceID", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "invalidPermission", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "insufficientResources", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "invalidRevision", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 6, "securityDenial", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 7, "securityError", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors2 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_BandRejectReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_BandRejectReason, ett_h225_BandRejectReason, BandRejectReason_choice, "BandRejectReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+const value_string DisengageReason_vals[] = {
+ { 0, "forcedDrop" },
+ { 1, "normalDrop" },
+ { 2, "undefinedReason" },
+ { 0, NULL}
+};
+static per_choice_t DisengageReason_choice[] = {
+ { 0, "forcedDrop", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "normalDrop", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_DisengageReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_DisengageReason, ett_h225_DisengageReason, DisengageReason_choice, "DisengageReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+const value_string DisengageRejectReason_vals[] = {
+ { 0, "notRegistered" },
+ { 1, "requestToDropOther" },
+ { 2, "securityDenial" },
+ { 3, "securityError" },
+ { 0, NULL}
+};
+static per_choice_t DisengageRejectReason_choice[] = {
+ { 0, "notRegistered", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "requestToDropOther", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "securityDenial", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "securityError", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors2 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_DisengageRejectReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_DisengageRejectReason, ett_h225_DisengageRejectReason, DisengageRejectReason_choice, "DisengageRejectReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+
+const value_string InfoRequestNakReason_vals[] = {
+ { 0, "notRegistered" },
+ { 1, "securityDenial" },
+ { 2, "undefinedReason" },
+ { 3, "securityError" },
+ { 0, NULL}
+};
+static per_choice_t InfoRequestNakReason_choice[] = {
+ { 0, "notRegistered", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "securityDenial", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "securityError", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors2 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_InfoRequestNakReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_InfoRequestNakReason, ett_h225_InfoRequestNakReason, InfoRequestNakReason_choice, "InfoRequestNakReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+static const value_string SCRresult_vals[] = {
+ { 0, "started" },
+ { 1, "failed" },
+ { 2, "stopped" },
+ { 3, "notAvailable" },
+ { 4, "neededFeatureNotSupported" },
+ { 0, NULL}
+};
+static per_choice_t SCRresult_choice[] = {
+ { 0, "started", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "failed", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "stopped", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "notAvailable", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "neededFeatureNotSupported", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_SCRresult(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_SCRresult, ett_h225_SCRresult, SCRresult_choice, "SCRresult", NULL);
+ return offset;
+}
+
+static int
+dissect_h225_object(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_object_identifier(tvb, offset, pinfo, tree,
+ hf_h225_object,
+ object);
+ return offset;
+}
+
+static int
+dissect_h225_t35CountryCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h225_t35CountryCode, 0, 255,
+ &t35CountryCode, NULL, FALSE);
+ return offset;
+}
+
+
+static int
+dissect_h225_t35Extension(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h225_t35Extension, 0, 255,
+ &t35Extension, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h225_manufacturerCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h225_manufacturerCode, 0, 65535,
+ &manufacturerCode, NULL, FALSE);
+ return offset;
+}
+
+static per_sequence_t H221NonStandard_sequence[] = {
+ { "t35CountryCode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_t35CountryCode },
+ { "t35Extension", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_t35Extension },
+ { "manufacturerCode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_manufacturerCode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_h221NonStandard(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ t35CountryCode = 0;
+ t35Extension = 0;
+ manufacturerCode = 0;
+
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree,
+ hf_h225_h221NonStandard,
+ ett_h225_H221NonStandard, H221NonStandard_sequence);
+
+ h221NonStandard = ((t35CountryCode * 256) + t35Extension) * 65536 + manufacturerCode;
+
+ proto_tree_add_uint(tree, hf_h221Manufacturer, tvb, (offset>>3)-4,4,h221NonStandard);
+
+ return offset;
+}
+
+static const value_string NonStandardIdentifier_vals[] = {
+ { 0, "object" },
+ { 1, "h221NonStandard" },
+ { 0, NULL }
+};
+static per_choice_t NonStandardIdentifier_choice[] = {
+ { 0, "object", ASN1_EXTENSION_ROOT,
+ dissect_h225_object },
+ { 1, "h221NonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h225_h221NonStandard },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_nonStandardIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ *object = '\0';
+ h221NonStandard = 0;
+
+ offset = dissect_per_choice(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardIdentifier,
+ ett_h225_NonStandardIdentifier, NonStandardIdentifier_choice, "NonStandardIdentifier",
+ &value);
+
+ switch (value) {
+ case 0 : /* object */
+ nsp_handle = dissector_get_string_handle(nsp_object_dissector_table, object);
+ break;
+ case 1 : /* h221NonStandard */
+ nsp_handle = dissector_get_port_handle(nsp_h221_dissector_table, h221NonStandard);
+ break;
+ default :
+ nsp_handle = NULL;
+ }
+
+ return offset;
+}
+
+static int
+dissect_h225_nsp_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value_offset, value_len;
+ tvbuff_t *next_tvb;
+
+ offset = dissect_per_octet_string(tvb, offset, pinfo, tree,
+ hf_h225_nsp_data, -1, -1,
+ &value_offset, &value_len);
+
+ if (value_len > 0) {
+ next_tvb = tvb_new_subset(tvb, value_offset, value_len, value_len);
+ call_dissector((nsp_handle)?nsp_handle:data_handle, next_tvb, pinfo, tree);
+ }
+
+ return offset;
+}
+
+static per_sequence_t NonStandardParameter_sequence[] = {
+ { "nonStandardIdentifier", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_nonStandardIdentifier },
+ { "data", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_nsp_data },
+ { NULL, 0, 0, NULL }
+};
+
+int
+dissect_h225_NonStandardParameter(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index)
+{
+ nsp_handle = NULL;
+
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree,
+ hf_index,
+ ett_h225_NonStandardParameter, NonStandardParameter_sequence);
+
+ return offset;
+}
+
+
+static int
+dissect_h225_nonStandardData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_h225_NonStandardParameter(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardData);
+ return offset;
+}
+
+static per_sequence_t GatekeeperInfo_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_GatekeeperInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_GatekeeperInfo, ett_h225_GatekeeperInfo, GatekeeperInfo_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_nonStandard(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_h225_NonStandardParameter(tvb, offset, pinfo, tree,
+ hf_h225_nonStandard);
+ return offset;
+}
+
+static const value_string SecurityServiceMode_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "none" },
+ { 2, "default" },
+ { 0, NULL}
+};
+static per_choice_t SecurityServiceMode_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h225_nonStandard },
+ { 1, "none", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "default", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_SecurityServiceMode_encryption(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_SecurityServiceMode_encryption, ett_h225_SecurityServiceMode_encryption, SecurityServiceMode_choice, "Encryption", NULL);
+ return offset;
+}
+static int
+dissect_h225_SecurityServiceMode_authentication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_SecurityServiceMode_authentication, ett_h225_SecurityServiceMode_authentication, SecurityServiceMode_choice, "Authentication", NULL);
+ return offset;
+}
+static int
+dissect_h225_SecurityServiceMode_integrity(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_SecurityServiceMode_integrity, ett_h225_SecurityServiceMode_integrity, SecurityServiceMode_choice, "Integrity", NULL);
+ return offset;
+}
+
+
+
+static per_sequence_t SecurityCapabilities_sequence[] = {
+ { "nonStandard", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandard },
+ { "encryption", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SecurityServiceMode_encryption },
+ { "authenticaton", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SecurityServiceMode_authentication },
+ { "integrity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SecurityServiceMode_integrity },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_SecurityCapabilities_tls(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_SecurityCapabilities_tls, ett_h225_SecurityCapabilities_tls, SecurityCapabilities_sequence);
+ return offset;
+}
+static int
+dissect_h225_SecurityCapabilities_ipsec(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_SecurityCapabilities_ipsec, ett_h225_SecurityCapabilities_ipsec, SecurityCapabilities_sequence);
+ return offset;
+}
+
+
+
+
+static const value_string H245Security_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "noSecurity" },
+ { 2, "tls" },
+ { 3, "ipsec" },
+ { 0, NULL}
+};
+static per_choice_t H245Security_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h225_nonStandard },
+ { 1, "noSecurity", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "tls", ASN1_EXTENSION_ROOT,
+ dissect_h225_SecurityCapabilities_tls },
+ { 3, "ipsec", ASN1_EXTENSION_ROOT,
+ dissect_h225_SecurityCapabilities_ipsec },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_H245Security(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_H245Security, ett_h225_H245Security, H245Security_choice, "H245Security", NULL);
+ return offset;
+}
+
+static int
+dissect_h225_nonStandardUsageTypes_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_h225_NonStandardParameter(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardUsageTypes_item);
+ return offset;
+}
+
+static int
+dissect_h225_nonStandardUsageTypes(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_sequence_of(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardUsageTypes,
+ ett_h225_T_nonStandardUsageTypes, dissect_h225_nonStandardUsageTypes_item);
+ return offset;
+}
+
+
+static per_sequence_t RasUsageInfoTypes_sequence[] = {
+ { "nonStandardUsageTypes", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_nonStandardUsageTypes },
+ { "startTime", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "endTime", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "terminationCause", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RasUsageInfoTypes(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RasUsageInfoTypes, ett_h225_RasUsageInfoTypes, RasUsageInfoTypes_sequence);
+ return offset;
+}
+static int
+dissect_h225_usageReportingCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_usageReportingCapability, ett_h225_RasUsageInfoTypes, RasUsageInfoTypes_sequence);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_BandWidth(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_BandWidth, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_channelRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_channelRate, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_totalBandwidthRestriction(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_totalBandwidthRestriction, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static int
+dissect_h225_allowedBandWidth(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_allowedBandWidth, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_channelMultiplier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_channelMultiplier, 1, 256,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static per_sequence_t DataRate_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "channelRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_channelRate },
+ { "channelMultiplier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_channelMultiplier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_DataRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_DataRate, ett_h225_DataRate, DataRate_sequence);
+ return offset;
+}
+static int
+dissect_h225_gatewayDataRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_gatewayDataRate, ett_h225_DataRate, DataRate_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_dataRatesSupported(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_dataRatesSupported, ett_h225_dataRatesSupported, dissect_h225_DataRate );
+ return offset;
+}
+
+
+static per_sequence_t TerminalInfo_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_TerminalInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_TerminalInfo, ett_h225_TerminalInfo, TerminalInfo_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_h248Message(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_h248Message, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+static per_sequence_t StimulusControl_sequence[] = {
+ { "nonStandard", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandard },
+ { "isText", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "h248Message", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h248Message},
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_StimulusControl(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_StimulusControl, ett_h225_StimulusControl, StimulusControl_sequence);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_conferenceID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_conferenceID, 16, 16, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_replaceWithConferenceInvite(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_replaceWithConferenceInvite, 16, 16, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_nonStandardReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_h225_NonStandardParameter(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardReason);
+ return offset;
+}
+
+const value_string ReleaseCompleteReason_vals[] = {
+ { 0, "noBandwidth" },
+ { 1, "gatekeeperResources" },
+ { 2, "unreachableDestination" },
+ { 3, "destinationRejection" },
+ { 4, "invalidRevision" },
+ { 5, "noPermission" },
+ { 6, "unreachableGatekeeper" },
+ { 7, "gatewayResources" },
+ { 8, "badFormatAddress" },
+ { 9, "adaptiveBusy" },
+ { 10, "inConf" },
+ { 11, "undefinedReason" },
+ { 12, "facilityCallDeflection" },
+ { 13, "securityDenied" },
+ { 14, "calledPartyNotRegistered" },
+ { 15, "callerNotRegistered" },
+ { 16, "newConnectionNeeded" },
+ { 17, "nonStandardReason" },
+ { 18, "replaceWithConferenceInvite" },
+ { 19, "genericDataReason" },
+ { 20, "neededFeatureNotSupported" },
+ { 21, "tunnelledSignallingRejected" },
+ { 22, "invalidCID" },
+ { 23, "invalidCID" },
+ { 24, "securityError" },
+ { 25, "hopCountExceeded" },
+ { 0, NULL}
+};
+static per_choice_t ReleaseCompleteReason_choice[] = {
+ { 0, "noBandwidth", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "gatekeeperResources", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "unreachableDestination", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "destinationRejection", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "invalidRevision", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "noPermission", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 6, "unreachableGatekeeper", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 7, "gatewayResources", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 8, "badFormatAddress", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 9, "adaptiveBusy", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 10, "inConf", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 11, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 12, "facilityCallDeflection", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 13, "securityDenied", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 14, "calledPartyNotRegistered", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 15, "callerNotRegistered", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 16, "newConnectionNeeded", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 17, "nonStandardReason", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_nonStandardReason },
+ { 18, "replaceWithConferenceInvite", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_replaceWithConferenceInvite },
+ { 19, "genericDataReason", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 20, "neededFeatureNotSupported", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 21, "tunnelledSignallingRejected", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 22, "invalidCID", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 23, "invalidCID", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 24, "securityError", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors },
+ { 25, "hopCountExceeded", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_ReleaseCompleteReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_ReleaseCompleteReason, ett_h225_ReleaseCompleteReason, ReleaseCompleteReason_choice, "ReleaseCompleteReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+static int
+dissect_h225_numberOfScnConnections(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_numberOfScnConnections, 0, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static per_sequence_t connectionParameters_sequence[] = {
+ { "connectionType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ScnConnectionType },
+ { "numberOfScnConnections", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_numberOfScnConnections },
+ { "connectionAggregation", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ScnConnectionAggregation },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_connectionParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_connectionParameters, ett_h225_connectionParameters, connectionParameters_sequence);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_RequestSeqNum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_RequestSeqNum, 1, 65535,
+ &(h225_pi.requestSeqNum), NULL, FALSE);
+ return offset;
+}
+
+static per_sequence_t RasUsageSpecification_when_sequence[] = {
+ { "start", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "end", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "inIrr", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RasUsageSpecification_when(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RasUsageSpecification_when, ett_h225_RasUsageSpecification_when, RasUsageSpecification_when_sequence);
+ return offset;
+}
+
+
+
+static per_sequence_t RasUsageSpecification_callStartingPoint_sequence[] = {
+ { "alerting", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "connect", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RasUsageSpecification_callStartingPoint(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RasUsageSpecification_callStartingPoint, ett_h225_RasUsageSpecification_callStartingPoint, RasUsageSpecification_callStartingPoint_sequence);
+ return offset;
+}
+
+
+
+
+static per_sequence_t RasUsageSpecification_sequence[] = {
+ { "when", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RasUsageSpecification_when },
+ { "callStartingPoint", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_RasUsageSpecification_callStartingPoint },
+ { "required", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RasUsageInfoTypes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RasUsageSpecification(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RasUsageSpecification, ett_h225_RasUsageSpecification, RasUsageSpecification_sequence);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_ipAddress_ip(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ /* byte aligned */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ tvb_memcpy(tvb, (guint8 *)&ipv4_address, offset>>3, 4);
+ proto_tree_add_ipv4(tree, hf_h225_ipAddress_ip, tvb, offset>>3, 4, ipv4_address);
+ offset+=32;
+ return offset;
+}
+
+
+
+static int
+dissect_h225_ipAddress_port(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_ipAddress_port, 0, 65535,
+ &ipv4_port, NULL, FALSE);
+ return offset;
+}
+
+
+
+static per_sequence_t ipAddress_sequence[] = {
+ { "ip", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_ipAddress_ip },
+ { "port", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_ipAddress_port },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ipAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ipAddress, ett_h225_ipAddress, ipAddress_sequence);
+ return offset;
+}
+
+
+
+static const value_string routing_vals[] = {
+ { 0, "strict" },
+ { 1, "loose" },
+ { 0, NULL}
+};
+static per_choice_t routing_choice[] = {
+ { 0, "strict", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "loose", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_routing(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_routing, ett_h225_routing, routing_choice, "routing", NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_route(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_route, ett_h225_route, dissect_h225_ipAddress_ip );
+ return offset;
+}
+
+static per_sequence_t ipSourceRoute_sequence[] = {
+ { "ip", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ipAddress_ip },
+ { "port", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ipAddress_port },
+ { "route", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_route },
+ { "routing", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_routing },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ipSourceRoute(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ipSourceRoute, ett_h225_ipSourceRoute, ipSourceRoute_sequence);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_ipxNode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_ipxNode, 6, 6, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_ipxNetnum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_ipxNetnum, 4, 4, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_ipxPort(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_ipxPort, 2, 2, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t ipxAddress_sequence[] = {
+ { "node", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_ipxNode },
+ { "netnum", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_ipxNetnum },
+ { "port", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_ipxPort },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ipxAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ipxAddress, ett_h225_ipxAddress, ipxAddress_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_ipv6Address_ip(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_ipv6Address_ip, 16, 16, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_ipv6Address_port(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_ipv6Address_port, 0, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+
+static per_sequence_t ip6Address_sequence[] = {
+ { "ip", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ipv6Address_ip },
+ { "port", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ipv6Address_port },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ip6Address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ip6Address, ett_h225_ip6Address, ip6Address_sequence);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_netBios(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_netBios, 16, 16, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_nsap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_nsap, 1, 20, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_nonStandardAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_h225_NonStandardParameter(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardAddress);
+ return offset;
+}
+
+static const value_string TransportAddress_vals[] = {
+ { 0, "ipAddress" },
+ { 1, "ipSourceRoute" },
+ { 2, "ipxAddress" },
+ { 3, "ip6Address" },
+ { 4, "netBios" },
+ { 5, "nsap" },
+ { 6, "nonStandardAddress" },
+ { 0, NULL}
+};
+static per_choice_t TransportAddress_choice[] = {
+ { 0, "ipAddress", ASN1_EXTENSION_ROOT,
+ dissect_h225_ipAddress },
+ { 1, "ipSourceRoute", ASN1_EXTENSION_ROOT,
+ dissect_h225_ipSourceRoute },
+ { 2, "ipxAddress", ASN1_EXTENSION_ROOT,
+ dissect_h225_ipxAddress },
+ { 3, "ip6Address", ASN1_EXTENSION_ROOT,
+ dissect_h225_ip6Address },
+ { 4, "netBios", ASN1_EXTENSION_ROOT,
+ dissect_h225_netBios },
+ { 5, "nsap", ASN1_EXTENSION_ROOT,
+ dissect_h225_nsap },
+ { 6, "nonStandardAddress", ASN1_EXTENSION_ROOT,
+ dissect_h225_nonStandardAddress },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_transportID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_transportID, ett_h225_TransportAddress, TransportAddress_choice, "transportID", NULL);
+ return offset;
+}
+static int
+dissect_h225_alternativeAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_alternativeAddress, ett_h225_TransportAddress, TransportAddress_choice, "alternativeAddress", NULL);
+ return offset;
+}
+static int
+dissect_h225_sourceCallSignalAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_sourceCallSignalAddress, ett_h225_TransportAddress, TransportAddress_choice, "sourceCallSignalAddress", NULL);
+ return offset;
+}
+static int
+dissect_h225_CallSignalAddress2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_CallSignalAddress2, ett_h225_TransportAddress, TransportAddress_choice, "CallSignalAddress2", NULL);
+ return offset;
+}
+static int
+dissect_h225_destCallSignalAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_destCallSignalAddress, ett_h225_TransportAddress, TransportAddress_choice, "destCallSignalAddress", NULL);
+ return offset;
+}
+
+/* this is an indication of where h245 is spoken, try to pick it up if
+ it was ipv4 and register h245 there */
+static int
+dissect_h225_h245Address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ ipv4_address=0;
+ ipv4_port=0;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_h245Address, ett_h225_TransportAddress, TransportAddress_choice, "h245Address", NULL);
+
+ if((!pinfo->fd->flags.visited) && ipv4_address!=0 && ipv4_port!=0 && h245_handle){
+ address src_addr;
+ conversation_t *conv=NULL;
+
+ src_addr.type=AT_IPv4;
+ src_addr.len=4;
+ src_addr.data=(const guint8 *)&ipv4_address;
+
+ conv=find_conversation(&src_addr, &src_addr, PT_TCP, ipv4_port, ipv4_port, NO_ADDR_B|NO_PORT_B);
+ if(!conv){
+ conv=conversation_new(&src_addr, &src_addr, PT_TCP, ipv4_port, ipv4_port, NO_ADDR2|NO_PORT2);
+ conversation_set_dissector(conv, h245_handle);
+ }
+ }
+ return offset;
+}
+static int
+dissect_h225_sendAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_sendAddress, ett_h225_TransportAddress, TransportAddress_choice, "sendAddress", NULL);
+ return offset;
+}
+static int
+dissect_h225_recvAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_recvAddress, ett_h225_TransportAddress, TransportAddress_choice, "recvAddress", NULL);
+ return offset;
+}
+static int
+dissect_h225_rasAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_rasAddress, ett_h225_TransportAddress, TransportAddress_choice, "rasAddress", NULL);
+ return offset;
+}
+static int
+dissect_h225_replyAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_replyAddress, ett_h225_TransportAddress, TransportAddress_choice, "replyAddress", NULL);
+ return offset;
+}
+int
+dissect_h225_TransportAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_TransportAddress, ett_h225_TransportAddress, TransportAddress_choice, "TransportAddress", NULL);
+ return offset;
+}
+
+
+static per_sequence_t TransportChannelInfo_sequence[] = {
+ { "sendAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_sendAddress },
+ { "recvAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_recvAddress },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_rtpAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_rtpAddress, ett_h225_TransportChannelInfo, TransportChannelInfo_sequence);
+ return offset;
+}
+static int
+dissect_h225_rtcpAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_rtcpAddress, ett_h225_TransportChannelInfo, TransportChannelInfo_sequence);
+ return offset;
+}
+static int
+dissect_h225_h245(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_h245, ett_h225_TransportChannelInfo, TransportChannelInfo_sequence);
+ return offset;
+}
+static int
+dissect_h225_callSignaling(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_callSignaling, ett_h225_TransportChannelInfo, TransportChannelInfo_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_carrierName(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_carrierName, 1, 128);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_carrierIdentificationCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_carrierIdentificationCode, 3, 4, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t CarrierInfo_sequence[] = {
+ { "carrierIdentificationCode", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_carrierIdentificationCode },
+ { "carrierName", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_carrierName },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CarrierInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CarrierInfo, ett_h225_CarrierInfo, CarrierInfo_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_segment(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_segment, 0, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static const value_string InfoRequestResponseStatus_vals[] = {
+ { 0, "complete" },
+ { 1, "incomplete" },
+ { 2, "segment" },
+ { 3, "invalidCall" },
+ { 0, NULL}
+};
+static per_choice_t InfoRequestResponseStatus_choice[] = {
+ { 0, "complete", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "incomplete", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "segment", ASN1_EXTENSION_ROOT,
+ dissect_h225_segment },
+ { 3, "invalidCall", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_InfoRequestResponseStatus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_InfoRequestResponseStatus, ett_h225_InfoRequestResponseStatus, InfoRequestResponseStatus_choice, "InfoRequestResponseStatus", NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_guid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value_length;
+ guint32 value_offset;
+
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_guid, 16, 16, &(value_offset), &(value_length));
+
+ /* save call guid */
+ tvb_memcpy(tvb, h225_pi.guid, value_offset, value_length);
+
+ return offset;
+}
+
+static per_sequence_t CallIdentifier_sequence[] = {
+ { "guid", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_guid },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CallIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CallIdentifier, ett_h225_CallIdentifier, CallIdentifier_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_globalCallId(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_globalCallId, 16, 16, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_algorithmOID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h225_algorithmOID, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_threadId(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_threadId, 16, 16, NULL, NULL);
+ return offset;
+}
+
+
+static per_sequence_t CallLinkage_sequence[] = {
+ { "globalCallId", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_globalCallId },
+ { "threadId", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_threadId },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CallLinkage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CallLinkage, ett_h225_CallLinkage, CallLinkage_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_authenticationCapability_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_AuthenticationMechanism(tvb, offset, pinfo, tree, hf_h225_authenticationCapability_item);
+}
+static int
+dissect_h225_authenticationCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_sequence_of(tvb, offset, pinfo, tree,
+ hf_h225_authenticationCapability,
+ ett_h225_AuthenticationMechanism_sequence_of, dissect_h225_authenticationCapability_item);
+ return offset;
+}
+
+static int
+dissect_h225_GatekeeperIdentifier(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_)
+{
+ offset=dissect_per_BMPString(tvb, offset, pinfo, tree, hf_h225_GatekeeperIdentifier, 1, 128);
+ return offset;
+}
+
+static int
+dissect_h225_cleartoken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_h235_ClearToken(tvb, offset, pinfo, tree, hf_h225_cleartoken);
+ return offset;
+}
+
+static int
+dissect_h225_tokens(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_tokens, ett_h225_tokens, dissect_h225_cleartoken);
+ return offset;
+}
+
+
+static int
+dissect_h225_timeStamp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_TimeStamp(tvb, offset, pinfo, tree, hf_h225_timeStamp);
+}
+
+static int
+dissect_h225_token(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_HASHEDxxx(tvb, offset, pinfo, tree, hf_h225_token);
+}
+
+static per_sequence_t cryptoEPPwdHash_sequence[] = {
+ { "alias", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_AliasAddress },
+ { "timeStamp", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_timeStamp },
+ { "token", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_token },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_cryptoEPPwdHash(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_cryptoEPPwdHash, ett_h225_T_cryptoEPPwdHash, cryptoEPPwdHash_sequence);
+
+ return offset;
+}
+
+static per_sequence_t cryptoGKPwdHash_sequence[] = {
+ { "gatekeeperId", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "timeStamp", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_timeStamp },
+ { "token", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_token },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_cryptoGKPwdHash(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_cryptoGKPwdHash, ett_h225_T_cryptoGKPwdHash, cryptoGKPwdHash_sequence);
+
+ return offset;
+}
+
+static int
+dissect_h225_cryptoEPPwdEncr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_ENCRYPTEDxxx(tvb, offset, pinfo, tree, hf_h225_cryptoEPPwdEncr);
+}
+
+static int
+dissect_h225_cryptoGKPwdEncr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_ENCRYPTEDxxx(tvb, offset, pinfo, tree, hf_h225_cryptoGKPwdEncr);
+}
+
+static int
+dissect_h225_cryptoEPCert(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_SIGNEDxxx(tvb, offset, pinfo, tree, hf_h225_cryptoEPCert);
+}
+
+static int
+dissect_h225_cryptoGKCert(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_SIGNEDxxx(tvb, offset, pinfo, tree, hf_h225_cryptoGKCert);
+}
+
+static int
+dissect_h225_cryptoFastStart(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_SIGNEDxxx(tvb, offset, pinfo, tree, hf_h225_cryptoFastStart);
+}
+
+static int
+dissect_h225_nestedcryptoToken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_CryptoToken(tvb, offset, pinfo, tree, hf_h225_nestedcryptoToken);
+}
+
+static const value_string CryptoH323Token_vals[] = {
+ { 0, "cryptoEPPwdHash" },
+ { 1, "cryptoGKPwdHash" },
+ { 2, "cryptoEPPwdEncr" },
+ { 3, "cryptoGKPwdEncr" },
+ { 4, "cryptoEPCert" },
+ { 5, "cryptoGKCert" },
+ { 6, "cryptoFastStart" },
+ { 7, "nestedcryptoToken" },
+ { 0, NULL}
+};
+static per_choice_t CryptoH323Token_choice[] = {
+ { 0, "cryptoEPPwdHash", ASN1_EXTENSION_ROOT,
+ dissect_h225_cryptoEPPwdHash },
+ { 1, "cryptoGKPwdHash", ASN1_EXTENSION_ROOT,
+ dissect_h225_cryptoGKPwdHash },
+ { 2, "cryptoEPPwdEncr", ASN1_EXTENSION_ROOT,
+ dissect_h225_cryptoEPPwdEncr },
+ { 3, "cryptoGKPwdEncr", ASN1_EXTENSION_ROOT,
+ dissect_h225_cryptoGKPwdEncr },
+ { 4, "cryptoEPCert", ASN1_EXTENSION_ROOT,
+ dissect_h225_cryptoEPCert },
+ { 5, "cryptoGKCert", ASN1_EXTENSION_ROOT,
+ dissect_h225_cryptoGKCert },
+ { 6, "cryptoFastStart", ASN1_EXTENSION_ROOT,
+ dissect_h225_cryptoFastStart },
+ { 7, "nestedcryptoToken", ASN1_EXTENSION_ROOT,
+ dissect_h225_nestedcryptoToken },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_CryptoH323Token(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_CryptoH323Token, ett_h225_CryptoH323Token, CryptoH323Token_choice, "CryptoH323Token", NULL);
+
+ return offset;
+}
+static int
+dissect_h225_CryptoH323Token_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_CryptoH323Tokens, ett_h225_CryptoH323Tokens, dissect_h225_CryptoH323Token);
+
+ return offset;
+}
+
+static int
+dissect_h225_needToRegister(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_needToRegister, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_priority(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_priority, 0, 127,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static per_sequence_t AlternateGK_sequence[] = {
+ { "rasAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_rasAddress },
+ { "gatekeeperIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "needToRegister", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_needToRegister },
+ { "priority", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_priority },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_AlternateGK(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_AlternateGK, ett_h225_AlternateGK, AlternateGK_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_alternateGatekeeper(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_alternateGatekeeper, ett_h225_alternateGatekeeper, dissect_h225_AlternateGK);
+ return offset;
+}
+
+static int
+dissect_h225_altGKisPermanent(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_altGKisPermanent, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t AltGKInfo_sequence[] = {
+ { "alternateGatekeeper", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_alternateGatekeeper },
+ { "altGKisPermanent", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_altGKisPermanent },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_AltGKInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_AltGKInfo, ett_h225_AltGKInfo, AltGKInfo_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_annexE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_annexE, ett_h225_annexE, dissect_h225_TransportAddress);
+ return offset;
+}
+
+static int
+dissect_h225_sctp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_sctp, ett_h225_sctp, dissect_h225_TransportAddress);
+ return offset;
+}
+static per_sequence_t AlternateTransportAddress_sequence[] = {
+ { "annexE", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_annexE },
+ { "sctp", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_sctp },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_AlternateTransportAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_AlternateTransportAddress, ett_h225_AlternateTransportAddress, AlternateTransportAddress_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_callProceeding_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_callProceeding_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_setup_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_setup_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_connect_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_connect_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_alerting_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_alerting_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_information_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_information_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_releaseComplete_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_releaseComplete_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_facility_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_facility_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_progress_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_progress_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_empty_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_empty_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_status_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_status_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_statusInquiry_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_statusInquiry_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_setupAcknowledge_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_setupAcknowledge_bool, NULL, NULL);
+ return offset;
+}
+static int
+dissect_h225_notify_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_notify_bool, NULL, NULL);
+ return offset;
+}
+
+
+static per_sequence_t UUIEsRequested_sequence[] = {
+ { "setup", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_setup_bool },
+ { "callProceeding", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_callProceeding_bool },
+ { "connect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_connect_bool },
+ { "alerting", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_alerting_bool },
+ { "information", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_information_bool },
+ { "releaseComplete", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_releaseComplete_bool },
+ { "facility", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_facility_bool },
+ { "progress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_progress_bool },
+ { "empty", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_empty_bool },
+ { "status", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_status_bool },
+ { "statusInquiry", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_statusInquiry_bool },
+ { "setupAcknowledge", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_setupAcknowledge_bool },
+ { "notify", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_notify_bool },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_UUIEsRequested(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_UUIEsRequested, ett_h225_UUIEsRequested, UUIEsRequested_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_conferenceCalling(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_conferenceCalling, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_threePartyService(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_threePartyService, NULL, NULL);
+ return offset;
+}
+
+
+static per_sequence_t Q954Details_sequence[] = {
+ { "conferenceCalling", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_conferenceCalling },
+ { "threePartyService", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_threePartyService },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_Q954Info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_Q954Details, ett_h225_Q954Details, Q954Details_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_q932Full(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_q932Full, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_q951Full(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_q951Full, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_q952Full(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_q952Full, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_q953Full(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_q953Full, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_q955Full(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_q955Full, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_q956Full(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_q956Full, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_q957Full(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_q957Full, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t QseriesOptions_sequence[] = {
+ { "q932Full", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_q932Full },
+ { "q951Full", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_q951Full },
+ { "q952Full", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_q952Full },
+ { "q953Full", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_q953Full },
+ { "q955Full", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_q955Full },
+ { "q956Full", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_q956Full },
+ { "q957Full", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_q957Full },
+ { "q954Info", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_Q954Info },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_callServices(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_QseriesOptions, ett_h225_QseriesOptions, QseriesOptions_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_cname(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_PrintableString(tvb, offset, pinfo, tree, hf_h225_cname, -1, -1);
+ return offset;
+}
+
+
+static int
+dissect_h225_ssrc(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_ssrc, 1, 4294967295UL,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static int
+dissect_h225_RTPsessionId(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_RTPsessionId, 1, 255,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h225_associatedSessionIds(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_associatedSessionIds, ett_h225_associatedSessionIds, dissect_h225_RTPsessionId);
+ return offset;
+}
+static per_sequence_t RTPSession_sequence[] = {
+ { "rtpAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_rtpAddress },
+ { "rtcpAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_rtcpAddress },
+ { "cname", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_cname },
+ { "ssrc", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ssrc },
+ { "sessionId", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RTPsessionId },
+ { "associatedSessionIds", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_associatedSessionIds },
+ { "multicast", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "bandwidth", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_BandWidth },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RTPSession(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RTPSession, ett_h225_RTPSession, RTPSession_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_ProtocolIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h225_ProtocolIdentifier, NULL);
+ return offset;
+}
+
+static per_sequence_t StatusUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "callIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_StatusUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_StatusUUIE, ett_h225_StatusUUIE, StatusUUIE_sequence);
+ return offset;
+}
+static per_sequence_t StatusInquiryUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "callIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_StatusInquiryUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_StatusInquiryUUIE, ett_h225_StatusInquiryUUIE, StatusInquiryUUIE_sequence);
+ return offset;
+}
+static per_sequence_t SetupAcknowledgeUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "callIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_SetupAcknowledgeUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_SetupAcknowledgeUUIE, ett_h225_SetupAcknowledgeUUIE, SetupAcknowledgeUUIE_sequence);
+ return offset;
+}
+static per_sequence_t NotifyUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "callIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_NotifyUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_NotifyUUIE, ett_h225_NotifyUUIE, NotifyUUIE_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_imsi(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_imsi, 3, 16, "#*0123456789ABC", 15);
+
+ return offset;
+}
+
+
+static int
+dissect_h225_tmsi(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_tmsi, 1, 4, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_msisdn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_msisdn, 3, 16, "#*0123456789ABC", 15);
+
+ return offset;
+}
+
+
+static int
+dissect_h225_imei(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_imei, 15, 16, "#*0123456789ABC", 15);
+
+ return offset;
+}
+
+static int
+dissect_h225_hplmn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_hplmn, 1, 4, "#*0123456789ABC", 15);
+
+ return offset;
+}
+
+static int
+dissect_h225_vplmn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_vplmn, 1, 4, "#*0123456789ABC", 15);
+ return offset;
+}
+
+
+static per_sequence_t GSMUIM_sequence[] = {
+ { "imsi", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_imsi },
+ { "tmsi", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tmsi },
+ { "msisdn", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_msisdn },
+ { "imei", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_imei },
+ { "hplmn", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_hplmn },
+ { "vplmn", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_vplmn },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_GSMUIM(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_GSMUIM, ett_h225_GSMUIM, GSMUIM_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_sid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_sid, 1, 4, "#*0123456789ABC", 15);
+ return offset;
+}
+
+
+static int
+dissect_h225_mid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_mid, 1, 4, "#*0123456789ABC", 15);
+ return offset;
+}
+
+static const value_string systemid_vals[] = {
+ { 0, "sid" },
+ { 1, "mid" },
+ { 0, NULL}
+};
+static per_choice_t systemid_choice[] = {
+ { 0, "sid", ASN1_EXTENSION_ROOT,
+ dissect_h225_sid },
+ { 1, "mid", ASN1_EXTENSION_ROOT,
+ dissect_h225_mid },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_systemid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_systemid, ett_h225_systemid, systemid_choice, "systemid", NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_min(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_mid, 3, 16, "#*0123456789ABC", 15);
+ return offset;
+}
+
+
+static int
+dissect_h225_mdn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_mdn, 3, 16, "#*0123456789ABC", 15);
+ return offset;
+}
+
+static int
+dissect_h225_esn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_esn, 16, 16, "#*0123456789ABC", 15);
+
+ return offset;
+}
+
+static int
+dissect_h225_mscid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_mscid, 3, 16, "#*0123456789ABC", 15);
+
+ return offset;
+}
+
+
+static int
+dissect_h225_systemMyTypeCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_systemMyTypeCode, 1, 1, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_systemAccessType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_systemAccessType, 1, 1, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_qualificationInformationCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_qualificationInformationCode, 1, 1, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_sesn(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_sesn, 16, 16, "#*0123456789ABC", 15);
+ return offset;
+}
+
+
+static int
+dissect_h225_soc(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_soc, 3, 16, "#*0123456789ABC", 15);
+
+ return offset;
+}
+
+static per_sequence_t ANSI41UIM_sequence[] = {
+ { "imsi", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_imsi },
+ { "min", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_min },
+ { "mdn", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_mdn },
+ { "msisdn", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_msisdn },
+ { "esn", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_esn },
+ { "mscid", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_mscid },
+ { "systemid", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_systemid },
+ { "systemMyTypeCode", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_systemMyTypeCode },
+ { "systemAccessType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_systemAccessType },
+ { "qualificationInformationCode", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_qualificationInformationCode },
+ { "sesn", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_sesn },
+ { "soc", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_soc },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ANSI41UIM(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ANSI41UIM, ett_h225_ANSI41UIM, ANSI41UIM_sequence);
+ return offset;
+}
+
+
+static const value_string MobileUIM_vals[] = {
+ { 0, "ansi41uim" },
+ { 1, "gsmuim" },
+ { 0, NULL}
+};
+static per_choice_t MobileUIM_choice[] = {
+ { 0, "ansi41uim", ASN1_EXTENSION_ROOT,
+ dissect_h225_ANSI41UIM },
+ { 1, "gsmuim", ASN1_EXTENSION_ROOT,
+ dissect_h225_GSMUIM },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_MobileUIM(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_MobileUIM, ett_h225_MobileUIM, MobileUIM_choice, "MobileUIM", NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_dataPartyNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_dataPartyNumber, 1, 128, "#*,0123456789", 13);
+
+ return offset;
+}
+
+static int
+dissect_h225_telexPartyNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_telexPartyNumber, 1, 128, "#*,0123456789", 13);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_nationalStandardPartyNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_nationalStandardPartyNumber, 1, 128, "#*,0123456789", 13);
+ return offset;
+}
+
+static int
+dissect_h225_publicNumberDigits(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_publicNumberDigits, 1, 128, "#*,0123456789", 13);
+ return offset;
+}
+
+
+static int
+dissect_h225_privateNumberDigits(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_privateNumberDigits, 1, 128, "#*,0123456789", 13);
+ return offset;
+}
+
+
+static per_sequence_t e164Number_sequence[] = {
+ { "publicTypeOfNumber", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_PublicTypeOfNumber },
+ { "publicNumberDigits", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_publicNumberDigits },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_e164Number(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_e164Number, ett_h225_e164Number, e164Number_sequence);
+ return offset;
+}
+static per_sequence_t privateNumber_sequence[] = {
+ { "privateTypeOfNumber", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_PrivateTypeOfNumber },
+ { "privateNumberDigits", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_privateNumberDigits },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_privateNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_privateNumber, ett_h225_privateNumber, privateNumber_sequence);
+ return offset;
+}
+
+static const value_string PartyNumber_vals[] = {
+ { 0, "e164Number" },
+ { 1, "dataPartyNumber" },
+ { 2, "telexPartyNumber" },
+ { 3, "privateNumber" },
+ { 4, "nationalStandardPartyNumber" },
+ { 0, NULL}
+};
+static per_choice_t PartyNumber_choice[] = {
+ { 0, "e164Number", ASN1_EXTENSION_ROOT,
+ dissect_h225_e164Number },
+ { 1, "dataPartyNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_dataPartyNumber },
+ { 2, "telexPartyNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_telexPartyNumber },
+ { 3, "privateNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_privateNumber },
+ { 4, "nationalStandardPartyNumber", ASN1_EXTENSION_ROOT,
+ dissect_h225_nationalStandardPartyNumber },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_PartyNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_PartyNumber, ett_h225_PartyNumber, PartyNumber_choice, "PartyNumber", NULL);
+ return offset;
+}
+static int
+dissect_h225_startOfRange(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_startOfRange, ett_h225_PartyNumber, PartyNumber_choice, "startOfRange", NULL);
+ return offset;
+}
+static int
+dissect_h225_endOfRange(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_endOfRange, ett_h225_PartyNumber, PartyNumber_choice, "endOfRange", NULL);
+ return offset;
+}
+
+static int
+dissect_h225_protocolType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_protocolType, 1, 64);
+ return offset;
+}
+
+static int
+dissect_h225_protocolVariant(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_protocolVariant, 1, 64);
+ return offset;
+}
+static per_sequence_t TunnelledProtocolAlternateIdentifier_sequence[] = {
+ { "protocolType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_protocolType },
+ { "protocolVariant", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_protocolVariant },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_TunnelledProtocolAlternateIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_TunnelledProtocolAlternateIdentifier, ett_h225_TunnelledProtocolAlternateIdentifier, TunnelledProtocolAlternateIdentifier_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_dialedDigits(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h225_privateNumberDigits, 1, 128, "#,*0123456789", 13);
+
+ return offset;
+}
+
+static int
+dissect_h225_h323Id(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_BMPString(tvb, offset, pinfo, tree, hf_h225_h323ID, 1, 256);
+ return offset;
+}
+
+static int
+dissect_h225_urlId(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_urlId, 1, 512);
+ return offset;
+}
+
+
+static int
+dissect_h225_emailId(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_emailId, 1, 512);
+ return offset;
+}
+
+
+static const value_string AliasAddress_vals[] = {
+ { 0, "dialedDigits" },
+ { 1, "h323ID" },
+ { 2, "urlID" },
+ { 3, "transportID" },
+ { 4, "emailID" },
+ { 5, "partyNumber" },
+ { 6, "mobileUIM" },
+ { 0, NULL}
+};
+static per_choice_t AliasAddress_choice[] = {
+ { 0, "dialedDigits", ASN1_EXTENSION_ROOT,
+ dissect_h225_dialedDigits },
+ { 1, "h323ID", ASN1_EXTENSION_ROOT,
+ dissect_h225_h323Id },
+ { 2, "urlID", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_urlId },
+ { 3, "transportID", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_transportID },
+ { 4, "emailID", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_emailId },
+ { 5, "partyNumber", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_PartyNumber },
+ { 6, "mobileUIM", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_MobileUIM },
+ { 0, NULL, 0, NULL }
+};
+int
+dissect_h225_AliasAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_AliasAddress, ett_h225_AliasAddress, AliasAddress_choice, "AliasAddress", NULL);
+ return offset;
+}
+static int
+dissect_h225_featureServerAlias(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_featureServerAlias, ett_h225_AliasAddress, AliasAddress_choice, "featureServerAlias", NULL);
+ return offset;
+}
+static int
+dissect_h225_RemoteExtensionAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_RemoteExtensionAddress, ett_h225_AliasAddress, AliasAddress_choice, "RemoteExtensionAddress", NULL);
+ return offset;
+}
+static int
+dissect_h225_conferenceAlias(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_conferenceAlias, ett_h225_AliasAddress, AliasAddress_choice, "conferenceAlias", NULL);
+ return offset;
+}
+static int
+dissect_h225_wildcard(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_wildcard, ett_h225_AliasAddress, AliasAddress_choice, "wildcard", NULL);
+ return offset;
+}
+static int
+dissect_h225_prefix(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_prefix, ett_h225_AliasAddress, AliasAddress_choice, "prefix", NULL);
+ return offset;
+}
+
+static per_sequence_t SupportedPrefix_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "prefix", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_prefix },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_SupportedPrefix(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_SupportedPrefix, ett_h225_SupportedPrefix, SupportedPrefix_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_SupportedPrefixes(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_SupportedPrefixes, ett_h225_SupportedPrefixes, dissect_h225_SupportedPrefix);
+ return offset;
+}
+
+
+static per_sequence_t H310Caps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_H310Caps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_H310Caps, ett_h225_H310Caps, H310Caps_sequence);
+ return offset;
+}
+
+
+static per_sequence_t H320Caps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_H320Caps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_H320Caps, ett_h225_H320Caps, H320Caps_sequence);
+ return offset;
+}
+
+
+static per_sequence_t H321Caps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_H321Caps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_H321Caps, ett_h225_H321Caps, H321Caps_sequence);
+ return offset;
+}
+
+
+static per_sequence_t H322Caps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_H322Caps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_H322Caps, ett_h225_H322Caps, H322Caps_sequence);
+ return offset;
+}
+
+
+static per_sequence_t H323Caps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_H323Caps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_H323Caps, ett_h225_H323Caps, H323Caps_sequence);
+ return offset;
+}
+
+
+static per_sequence_t H324Caps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_H324Caps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_H324Caps, ett_h225_H324Caps, H324Caps_sequence);
+ return offset;
+}
+
+
+static per_sequence_t VoiceCaps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_VoiceCaps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_VoiceCaps, ett_h225_VoiceCaps, VoiceCaps_sequence);
+ return offset;
+}
+
+
+static per_sequence_t T120OnlyCaps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_T120OnlyCaps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_T120OnlyCaps, ett_h225_T120OnlyCaps, T120OnlyCaps_sequence);
+ return offset;
+}
+
+static per_sequence_t NonStandardProtocol_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_NonStandardProtocol(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_NonStandardProtocol, ett_h225_NonStandardProtocol, NonStandardProtocol_sequence);
+ return offset;
+}
+
+
+static per_sequence_t SIPCaps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_SIPCaps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_SIPCaps, ett_h225_SIPCaps, SIPCaps_sequence);
+ return offset;
+}
+
+static per_sequence_t AddressPattern_range_sequence[] = {
+ { "startOfRange", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_startOfRange },
+ { "endOfRange", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_endOfRange },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_AddressPattern_range(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_AddressPattern_range, ett_h225_AddressPattern_range, AddressPattern_range_sequence);
+ return offset;
+}
+
+
+static const value_string AddressPattern_vals[] = {
+ { 0, "wildcard" },
+ { 1, "range" },
+ { 0, NULL}
+};
+static per_choice_t AddressPattern_choice[] = {
+ { 0, "wildcard", ASN1_EXTENSION_ROOT,
+ dissect_h225_wildcard },
+ { 0, "range", ASN1_EXTENSION_ROOT,
+ dissect_h225_AddressPattern_range },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_AddressPattern(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_AddressPattern, ett_h225_AddressPattern, AddressPattern_choice, "AddressPattern", NULL);
+ return offset;
+}
+static per_sequence_t ConferenceList_sequence[] = {
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_conferenceID },
+ { "conferenceAlias", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_conferenceAlias },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ConferenceList(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ConferenceList, ett_h225_ConferenceList, ConferenceList_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_conferences(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_conferences, ett_h225_conferences, dissect_h225_ConferenceList);
+ return offset;
+}
+static per_sequence_t T38FaxAnnexbOnlyCaps_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "dataRatesSupported", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_dataRatesSupported },
+ { "supportedPrefixes", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { "t38FaxProtocol", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataProtocolCapability },
+ { "t38FaxProfile", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_T38FaxProfile },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_T38FaxAnnexbOnlyCaps(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_T38FaxAnnexbOnlyCaps, ett_h225_T38FaxAnnexbOnlyCaps, T38FaxAnnexbOnlyCaps_sequence);
+ return offset;
+}
+
+
+static const value_string SupportedProtocols_vals[] = {
+ { 0, "nonStandardData" },
+ { 1, "h310" },
+ { 2, "h320" },
+ { 3, "h321" },
+ { 4, "h322" },
+ { 5, "h323" },
+ { 6, "h324" },
+ { 7, "voice" },
+ { 8, "t120-only" },
+ { 9, "nonStandardProtocol" },
+ { 10, "t38FaxAnnexbOnly" },
+ { 11, "sip" },
+ { 0, NULL}
+};
+static per_choice_t SupportedProtocols_choice[] = {
+ { 0, "nonStandardData", ASN1_EXTENSION_ROOT,
+ dissect_h225_nonStandardData },
+ { 1, "h310", ASN1_EXTENSION_ROOT,
+ dissect_h225_H310Caps },
+ { 2, "h320", ASN1_EXTENSION_ROOT,
+ dissect_h225_H320Caps },
+ { 3, "h321", ASN1_EXTENSION_ROOT,
+ dissect_h225_H321Caps },
+ { 4, "h322", ASN1_EXTENSION_ROOT,
+ dissect_h225_H322Caps },
+ { 5, "h323", ASN1_EXTENSION_ROOT,
+ dissect_h225_H323Caps },
+ { 6, "h324", ASN1_EXTENSION_ROOT,
+ dissect_h225_H324Caps },
+ { 7, "voice", ASN1_EXTENSION_ROOT,
+ dissect_h225_VoiceCaps },
+ { 8, "t120-only", ASN1_EXTENSION_ROOT,
+ dissect_h225_T120OnlyCaps },
+ { 9, "nonStandardProtocol", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NonStandardProtocol },
+ { 10, "t38FaxAnnexbOnly", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_T38FaxAnnexbOnlyCaps },
+ { 11, "sip", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SIPCaps },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_SupportedProtocols(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_SupportedProtocols, ett_h225_SupportedProtocols, SupportedProtocols_choice, "SupportedProtocols", NULL);
+ return offset;
+}
+
+static int
+dissect_h225_protocol(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_protocol, ett_h225_protocol, dissect_h225_SupportedProtocols);
+ return offset;
+}
+
+
+
+static per_sequence_t GatewayInfo_sequence[] = {
+ { "protocol", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_protocol },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_gateway(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_GatewayInfo, ett_h225_GatewayInfo, GatewayInfo_sequence);
+ return offset;
+}
+static per_sequence_t McuInfo_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "protocol", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_protocol },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_mcu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_McuInfo, ett_h225_McuInfo, McuInfo_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_tunnelledProtocolObjectID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h225_tunnelledProtocolObjectID, tpID);
+ return offset;
+}
+
+
+static const value_string TunnelledProtocol_id_vals[] = {
+ { 0, "tunnelledProtocolObjectID" },
+ { 1, "tunnelledProtocolAlternateID" },
+ { 0, NULL }
+};
+static per_choice_t TunnelledProtocol_id_choice[] = {
+ { 0, "tunnelledProtocolObjectID", ASN1_EXTENSION_ROOT,
+ dissect_h225_tunnelledProtocolObjectID },
+ { 1, "tunnelledProtocolAlternateID", ASN1_EXTENSION_ROOT,
+ dissect_h225_TunnelledProtocolAlternateIdentifier },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_TunnelledProtocol_id(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_TunnelledProtocol_id, ett_h225_TunnelledProtocol_id, TunnelledProtocol_id_choice, "id", NULL);
+ return offset;
+}
+
+static int
+dissect_h225_TunnelledProtocol_subIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_TunnelledProtocol_subIdentifier, 1, 64);
+ return offset;
+}
+static per_sequence_t TunnelledProtocol_sequence[] = {
+ { "id", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_TunnelledProtocol_id },
+ { "subIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_TunnelledProtocol_subIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_TunnelledProtocol(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ tpID[0] = '\0';
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_TunnelledProtocol, ett_h225_TunnelledProtocol, TunnelledProtocol_sequence);
+ tp_handle = dissector_get_string_handle(tp_dissector_table, tpID);
+ return offset;
+}
+static int
+dissect_h225_TunnelledProtocols(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_sequence_of(tvb, offset, pinfo, tree,
+ hf_h225_TunnelledProtocols,
+ ett_h225_TunnelledProtocols, dissect_h225_TunnelledProtocol);
+ return offset;
+}
+
+static int
+dissect_h225_desiredTunnelledProtocol(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ tpID[0] = '\0';
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_desiredTunnelledProtocol, ett_h225_TunnelledProtocol, TunnelledProtocol_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_CicInfo_cic_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_CicInfo_cic_item, 2, 4, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_CicInfo_pointCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_CicInfo_pointCode, 2, 5, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_CicInfo_cic(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_CicInfo_cic, ett_h225_CicInfo_cic, dissect_h225_CicInfo_cic_item);
+ return offset;
+}
+
+static per_sequence_t CicInfo_sequence[] = {
+ { "cic", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CicInfo_cic },
+ { "pointCode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CicInfo_pointCode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CicInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CicInfo, ett_h225_CicInfo, CicInfo_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_GroupID_member_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_GroupID_member_item, 0, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h225_GroupID_member(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_GroupID_member, ett_h225_GroupID_member, dissect_h225_GroupID_member_item);
+ return offset;
+}
+
+static int
+dissect_h225_GroupID_group(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_GroupID_group, 1, 128);
+ return offset;
+}
+
+static per_sequence_t GroupID_sequence[] = {
+ { "member", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GroupID_member },
+ { "group", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_GroupID_group },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_GroupID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_GroupID, ett_h225_GroupID, GroupID_sequence);
+ return offset;
+}
+
+static per_sequence_t CircuitIdentifier_sequence[] = {
+ { "cic", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CicInfo },
+ { "group", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GroupID },
+ { "carrier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CarrierInfo },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_sourceCircuitID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_sourceCircuitID, ett_h225_CircuitIdentifier, CircuitIdentifier_sequence);
+ return offset;
+}
+static int
+dissect_h225_destinationCircuitID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_destinationCircuitID, ett_h225_CircuitIdentifier, CircuitIdentifier_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_Generic_standard(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_Generic_standard, 0, 16383,
+ NULL, NULL, TRUE);
+ return offset;
+}
+
+
+static int
+dissect_h225_Generic_oid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h225_Generic_oid, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_Generic_nonStandard(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_Generic_nonStandard, 16, 16, NULL, NULL);
+ return offset;
+}
+
+
+static const value_string GenericIdentifier_vals[] = {
+ { 0, "standard" },
+ { 1, "oid" },
+ { 2, "nonStandard" },
+ { 0, NULL}
+};
+static per_choice_t GenericIdentifier_choice[] = {
+ { 0, "standard", ASN1_EXTENSION_ROOT,
+ dissect_h225_Generic_standard },
+ { 1, "oid", ASN1_EXTENSION_ROOT,
+ dissect_h225_Generic_oid },
+ { 2, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h225_Generic_nonStandard },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_GenericIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_GenericIdentifier, ett_h225_GenericIdentifier, GenericIdentifier_choice, "GenericIdentifier", NULL);
+ return offset;
+}
+
+static int dissect_h225_Content(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static per_sequence_t EnumeratedParameter_sequence[] = {
+ { "id", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_GenericIdentifier },
+ { "content", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_Content },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_EnumeratedParameter(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_EnumeratedParameter, ett_h225_EnumeratedParameter, EnumeratedParameter_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h225_parameters, ett_h225_parameters, dissect_h225_EnumeratedParameter, 1, 512);
+ return offset;
+}
+
+static per_sequence_t GenericData_sequence[] = {
+ { "id", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_GenericIdentifier },
+ { "parameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_parameters },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_GenericData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_GenericData, ett_h225_GenericData, GenericData_sequence);
+ return offset;
+}
+static int
+dissect_h225_genericData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_genericData, ett_h225_genericData, dissect_h225_GenericData);
+ return offset;
+}
+static int
+dissect_h225_FeatureDescriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_FeatureDescriptor, ett_h225_GenericData, GenericData_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_Content_raw(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_Content_raw, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_Content_text(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_Content_text, -1, -1);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_Content_unicode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_BMPString(tvb, offset, pinfo, tree, hf_h225_unicode, -1, -1);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_Content_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_Content_bool, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_Content_number8(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_Content_number8, 0, 255,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h225_number16(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_number16, 0, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h225_Content_number32(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_Content_number32, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h225_Content_compound(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h225_Content_compound, ett_h225_Content_compound, dissect_h225_EnumeratedParameter, 1, 512);
+ return offset;
+}
+
+static int
+dissect_h225_Content_nested(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h225_Content_nested, ett_h225_Content_nested, dissect_h225_GenericData, 1, 16);
+ return offset;
+}
+
+
+
+
+
+static const value_string Content_vals[] = {
+ { 0, "raw" },
+ { 1, "text" },
+ { 2, "unicode" },
+ { 3, "bool" },
+ { 4, "number8" },
+ { 5, "number16" },
+ { 6, "number32" },
+ { 7, "id" },
+ { 8, "alias" },
+ { 9, "transport" },
+ { 10, "compound" },
+ { 11, "nested" },
+ { 0, NULL}
+};
+static per_choice_t Content_choice[] = {
+ { 0, "raw", ASN1_EXTENSION_ROOT,
+ dissect_h225_Content_raw },
+ { 1, "text", ASN1_EXTENSION_ROOT,
+ dissect_h225_Content_text },
+ { 2, "unicode", ASN1_EXTENSION_ROOT,
+ dissect_h225_Content_unicode },
+ { 3, "bool", ASN1_EXTENSION_ROOT,
+ dissect_h225_Content_bool },
+ { 4, "number8", ASN1_EXTENSION_ROOT,
+ dissect_h225_Content_number8 },
+ { 5, "number16", ASN1_EXTENSION_ROOT,
+ dissect_h225_number16 },
+ { 6, "number32", ASN1_EXTENSION_ROOT,
+ dissect_h225_Content_number32 },
+ { 7, "id", ASN1_EXTENSION_ROOT,
+ dissect_h225_GenericIdentifier },
+ { 8, "alias", ASN1_EXTENSION_ROOT,
+ dissect_h225_AliasAddress },
+ { 9, "transport", ASN1_EXTENSION_ROOT,
+ dissect_h225_TransportAddress },
+ { 10, "compound", ASN1_EXTENSION_ROOT,
+ dissect_h225_Content_compound },
+ { 11, "nested", ASN1_EXTENSION_ROOT,
+ dissect_h225_Content_nested },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_Content(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_Content, ett_h225_Content, Content_choice, "Content", NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_replacementFeatureSet(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_replacementFeatureSet, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_neededFeatures(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_neededFeatures, ett_h225_neededFeatures, dissect_h225_FeatureDescriptor);
+ return offset;
+}
+
+static int
+dissect_h225_desiredFeatures(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_desiredFeatures, ett_h225_desiredFeatures, dissect_h225_FeatureDescriptor);
+ return offset;
+}
+
+static int
+dissect_h225_supportedFeatures(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_supportedFeatures, ett_h225_supportedFeatures, dissect_h225_FeatureDescriptor);
+ return offset;
+}
+
+static per_sequence_t FeatureSet_sequence[] = {
+ { "replacementFeatureSet", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_replacementFeatureSet },
+ { "neededFeatures", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_neededFeatures },
+ { "desiredFeatures", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_desiredFeatures },
+ { "supportedFeatures", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_supportedFeatures },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_FeatureSet(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_FeatureSet, ett_h225_FeatureSet, FeatureSet_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_CallsAvailable_calls(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_CallsAvailable_calls, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static int
+dissect_h225_CallsAvailable_group(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_CallsAvailable_group, 1, 128);
+ return offset;
+}
+
+static per_sequence_t CallsAvailable_sequence[] = {
+ { "calls", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallsAvailable_calls },
+ { "group", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallsAvailable_group },
+ { "carrier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CarrierInfo },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CallsAvailable, ett_h225_CallsAvailable, CallsAvailable_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_voiceGwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_voiceGwCallsAvailable, ett_h225_voiceGwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_h310GwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_h310GwCallsAvailable, ett_h225_h310GwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_h320GwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_h320GwCallsAvailable, ett_h225_h320GwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_h321GwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_h321GwCallsAvailable, ett_h225_h321GwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_h322GwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_h322GwCallsAvailable, ett_h225_h322GwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_h323GwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_h323GwCallsAvailable, ett_h225_h323GwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_h324GwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_h324GwCallsAvailable, ett_h225_h324GwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_t120OnlyGwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_t120OnlyGwCallsAvailable, ett_h225_t120OnlyGwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_t38FaxAnnexbOnlyGwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_t38FaxAnnexbOnlyGwCallsAvailable, ett_h225_t38FaxAnnexbOnlyGwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_terminalCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_terminalCallsAvailable, ett_h225_terminalCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_mcuCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_mcuCallsAvailable, ett_h225_mcuCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+
+static int
+dissect_h225_sipGwCallsAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_sipGwCallsAvailable, ett_h225_sipGwCallsAvailable, dissect_h225_CallsAvailable);
+ return offset;
+}
+static per_sequence_t CallCapacityInfo_sequence[] = {
+ { "voiceGwCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_voiceGwCallsAvailable },
+ { "h310GwCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h310GwCallsAvailable },
+ { "h320GwCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h320GwCallsAvailable },
+ { "h321GwCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h321GwCallsAvailable },
+ { "h322GwCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h322GwCallsAvailable },
+ { "h323GwCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h323GwCallsAvailable },
+ { "h324GwCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h324GwCallsAvailable },
+ { "t120OnlyGwCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_t120OnlyGwCallsAvailable },
+ { "t38FaxAnnexbOnlyGwCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_t38FaxAnnexbOnlyGwCallsAvailable },
+ { "terminalCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_terminalCallsAvailable },
+ { "mcuCallsAvailable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_mcuCallsAvailable },
+ { "sipGwCallsAvailable", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_sipGwCallsAvailable },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_maximumCallCapacity(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_maximumCallCapacity, ett_h225_CallCapacityInfo, CallCapacityInfo_sequence);
+ return offset;
+}
+static int
+dissect_h225_currentCallCapacity(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_currentCallCapacity, ett_h225_CallCapacityInfo, CallCapacityInfo_sequence);
+ return offset;
+}
+
+static per_sequence_t CallCapacity_sequence[] = {
+ { "maximumCallCapacity", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_maximumCallCapacity },
+ { "currentCallCapacity", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_currentCallCapacity },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CallCapacity(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CallCapacity, ett_h225_CallCapacity, CallCapacity_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_productID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_productID, 1, 256, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_versionID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_versionID, 1, 256, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_enterpriseNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h225_enterpriseNumber, NULL);
+ return offset;
+}
+
+static per_sequence_t VendorIdentifier_sequence[] = {
+ { "vendor", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_h221NonStandard },
+ { "productId", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_productID },
+ { "versionId", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_versionID },
+ { "enterpriseNumber", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_enterpriseNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_VendorIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_VendorIdentifier, ett_h225_VendorIdentifier, VendorIdentifier_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_canReportCallCapacity(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_canReportCallCapacity, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t CapacityReportingCapability_sequence[] = {
+ { "canReportCallCapacity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_canReportCallCapacity },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CapacityReportingCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CapacityReportingCapability, ett_h225_CapacityReportingCapability, CapacityReportingCapability_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_canDisplayAmountString(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_canDisplayAmountString, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_canEnforceDurationLimit(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_canEnforceDurationLimit, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t CallCreditCapability_sequence[] = {
+ { "canDisplayAmountString", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_canDisplayAmountString },
+ { "canEnforceDurationLimit", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_canEnforceDurationLimit },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CallCreditCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CallCreditCapability, ett_h225_CallCreditCapability, CallCreditCapability_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_BandwidthDetails_sender(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_BandwidthDetails_sender, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_BandwidthDetails_multicast(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_BandwidthDetails_multicast, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t BandwidthDetails_sequence[] = {
+ { "sender", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_BandwidthDetails_sender },
+ { "multicast", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_BandwidthDetails_multicast },
+ { "bandwidth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_BandWidth },
+ { "rtcpAddresses", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_rtcpAddress },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_BandwidthDetails(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_BandwidthDetails, ett_h225_BandwidthDetails, BandwidthDetails_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_releaseCompleteCauseIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_releaseCompleteCauseIE, 2, 32, NULL, NULL);
+ return offset;
+}
+
+static const value_string CallTerminationCause_vals[] = {
+ { 0, "releaseCompleteReason" },
+ { 1, "releaseCompleteCauseIE" },
+ { 0, NULL}
+};
+static per_choice_t CallTerminationCause_choice[] = {
+ { 0, "releaseCompleteReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_ReleaseCompleteReason },
+ { 1, "releaseCompleteCauseIE", ASN1_EXTENSION_ROOT,
+ dissect_h225_releaseCompleteCauseIE },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_CallTerminationCause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_CallTerminationCause, ett_h225_CallTerminationCause, CallTerminationCause_choice, "CallTerminationCause", NULL);
+ return offset;
+}
+
+static per_sequence_t CircuitInfo_sequence[] = {
+ { "sourceCircuitID", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_sourceCircuitID },
+ { "destinationCircuitID", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destinationCircuitID },
+ { "genericData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CircuitInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CircuitInfo, ett_h225_CircuitInfo, CircuitInfo_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_fastStart_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 length;
+ guint32 newoffset;
+
+ offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_h225_fastStart_item_length, &length);
+ newoffset=offset + (length<<3); /* please note that offset is in bits in
+ PER dissectors, but the item length
+ is in octets */
+ offset=dissect_h245_OpenLogicalChannel(tvb, offset, pinfo, tree);
+
+ contains_faststart = TRUE;
+
+ return newoffset;
+}
+
+static int
+dissect_h225_fastStart(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_fastStart, ett_h225_fastStart, dissect_h225_fastStart_item);
+ return offset;
+}
+
+static int
+dissect_h225_fastConnectRefused(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_fastConnectRefused, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t InformationUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "fastStart", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_fastStart },
+ { "fastConnectRefused", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_fastConnectRefused },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_InformationUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_InformationUUIE, ett_h225_InformationUUIE, InformationUUIE_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_routeCallToSCN(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_routeCallToSCN, ett_h225_routeCallToSCN, dissect_h225_PartyNumber);
+ return offset;
+}
+
+const value_string AdmissionRejectReason_vals[] = {
+ { 0, "calledPartyNotRegistered" },
+ { 1, "invalidPermission" },
+ { 2, "requestDenied" },
+ { 3, "undefinedReason" },
+ { 4, "callerNotRegistered" },
+ { 5, "routeCallToGatekeeper" },
+ { 6, "invalidEndpointIdentifier" },
+ { 7, "resourceUnavailable" },
+ { 8, "securityDenial" },
+ { 9, "qosControlNotSupported" },
+ { 10, "incompleteAddress" },
+ { 11, "aliasesInconsistent" },
+ { 12, "routeCallToSCN" },
+ { 13, "exceedsCallCapacity" },
+ { 14, "collectDestination" },
+ { 15, "collectPIN" },
+ { 16, "genericDataReason" },
+ { 17, "neededFeatureNotSupported" },
+ { 18, "securityErrors" },
+ { 19, "securityDHmismatch" },
+ { 20, "noRouteToDestination" },
+ { 21, "unallocatedNumber" },
+ { 0, NULL}
+};
+static per_choice_t AdmissionRejectReason_choice[] = {
+ { 0, "calledPartyNotRegistered", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "invalidPermission", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "requestDenied", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "callerNotRegistered", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "routeCallToGatekeeper", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 6, "invalidEndpointIdentifier", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 7, "resourceUnavailable", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 8, "securityDenial", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 9, "qosControlNotSupported", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 10, "incompleteAddress", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 11, "aliasesInconsistent", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 12, "routeCallToSCN", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_routeCallToSCN },
+ { 13, "exceedsCallCapacity", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 14, "collectDestination", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 15, "collectPIN", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 16, "genericDataReason", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 17, "neededFeatureNotSupported", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 18, "securityErrors", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors2 },
+ { 19, "securityDHmismatch", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 20, "noRouteToDestination", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 21, "unallocatedNumber", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_AdmissionRejectReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_AdmissionRejectReason, ett_h225_AdmissionRejectReason, AdmissionRejectReason_choice, "AdmissionRejectReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+static int
+dissect_h225_isoAlgorithm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h225_isoAlgorithm, NULL);
+ return offset;
+}
+
+static const value_string EncryptIntAlg_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "isoAlgorithm" },
+ { 0, NULL}
+};
+static per_choice_t EncryptIntAlg_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h225_nonStandard },
+ { 1, "isoAlgorithm", ASN1_EXTENSION_ROOT,
+ dissect_h225_isoAlgorithm },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_hMAC_iso10118_2_s(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_hMAC_iso10118_2_s, ett_h225_EncryptIntAlg, EncryptIntAlg_choice, "hMAC_iso10118_2_s", NULL);
+ return offset;
+}
+static int
+dissect_h225_hMAC_iso10118_2_l(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_hMAC_iso10118_2_l, ett_h225_EncryptIntAlg, EncryptIntAlg_choice, "hMAC_iso10118_2_l", NULL);
+ return offset;
+}
+
+static int
+dissect_h225_hMAC_iso10118_3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h225_hMAC_iso10118_3, NULL);
+ return offset;
+}
+
+
+static const value_string NonIsoIntegrityMechanism_vals[] = {
+ { 0, "hMAC-MD5" },
+ { 1, "hMAC_iso10118_2_s" },
+ { 2, "hMAC_iso10118_2_l" },
+ { 3, "hMAC_iso10118_3" },
+ { 0, NULL}
+};
+static per_choice_t NonIsoIntegrityMechanism_choice[] = {
+ { 0, "hMAC-MD5", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "hMAC_iso10118_2_s", ASN1_EXTENSION_ROOT,
+ dissect_h225_hMAC_iso10118_2_s },
+ { 2, "hMAC_iso10118_2_l", ASN1_EXTENSION_ROOT,
+ dissect_h225_hMAC_iso10118_2_l },
+ { 3, "hMAC_iso10118_3", ASN1_EXTENSION_ROOT,
+ dissect_h225_hMAC_iso10118_3 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_NonIsoIntegrityMechanism(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_NonIsoIntegrityMechanism, ett_h225_NonIsoIntegrityMechanism, NonIsoIntegrityMechanism_choice, "NonIsoIntegrityMechanism", NULL);
+ return offset;
+}
+
+static int
+dissect_h225_iso9797(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h225_iso9797, NULL);
+ return offset;
+}
+
+static const value_string IntegrityMechanism_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "digSig" },
+ { 2, "iso9797" },
+ { 3, "nonIsoIM" },
+ { 0, NULL}
+};
+static per_choice_t IntegrityMechanism_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h225_nonStandard },
+ { 1, "digSig", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "iso9797", ASN1_EXTENSION_ROOT,
+ dissect_h225_iso9797 },
+ { 3, "nonIsoIM", ASN1_EXTENSION_ROOT,
+ dissect_h225_NonIsoIntegrityMechanism },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_IntegrityMechanism(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_IntegrityMechanism, ett_h225_IntegrityMechanism, IntegrityMechanism_choice, "IntegrityMechanism", NULL);
+ return offset;
+}
+
+const value_string LocationRejectReason_vals[] = {
+ { 0, "notRegistered" },
+ { 1, "invalidPermission" },
+ { 2, "requestDenied" },
+ { 3, "undefinedReason" },
+ { 4, "securityDenial" },
+ { 5, "aliasesInconsistent" },
+ { 6, "routeCalltoSCN" },
+ { 7, "resourceUnavailable" },
+ { 8, "genericDataReason" },
+ { 9, "neededFeatureNotSupported" },
+ {10, "hopCountExceeded" },
+ {11, "incompleteAddress" },
+ {12, "securityError" },
+ {13, "securityDHmismatch" },
+ {14, "noRouteToDestination" },
+ {15, "unallocatedNumber" },
+ { 0, NULL}
+};
+static per_choice_t LocationRejectReason_choice[] = {
+ { 0, "notRegistered", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "invalidPermission", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "requestDenied", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "securityDenial", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 5, "aliasesInconsistent", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 6, "routeCalltoSCN", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_routeCallToSCN },
+ { 7, "resourceUnavailable", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 8, "genericDataReason", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 9, "neededFeatureNotSupported", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ {10, "hopCountExceeded", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ {11, "incompleteAddress", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ {12, "securityError", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors2 },
+ {13, "securityDHmismatch", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ {14, "noRouteToDestination", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ {15, "unallocatedNumber", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_LocationRejectReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_LocationRejectReason, ett_h225_LocationRejectReason, LocationRejectReason_choice, "LocationRejectReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+static int
+dissect_h225_EndpointType_set(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+PER_NOT_DECODED_YET("EndpointType_set");
+ return offset;
+}
+
+static int
+dissect_h225_mc(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_mc, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_undefinedNode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_undefinedNode, NULL, NULL);
+ return offset;
+}
+
+
+static per_sequence_t EndPointType_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "vendor", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_VendorIdentifier },
+ { "gatekeeper", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperInfo },
+ { "gateway", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_gateway },
+ { "mcu", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_mcu },
+ { "terminal", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_TerminalInfo },
+ { "mc", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_mc },
+ { "undefinedNode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_undefinedNode },
+ { "set", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_EndpointType_set },
+ { "supportedTunnelledProtocols", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_TunnelledProtocols },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_EndPointType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_EndPointType, ett_h225_EndPointType, EndPointType_sequence);
+ return offset;
+}
+static int
+dissect_h225_destinationType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_destinationType, ett_h225_EndPointType, EndPointType_sequence);
+ return offset;
+}
+static int
+dissect_h225_terminalType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_terminalType, ett_h225_EndPointType, EndPointType_sequence);
+ return offset;
+}
+static int
+dissect_h225_sourceInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_sourceInfo, ett_h225_EndPointType, EndPointType_sequence);
+ return offset;
+}
+static int
+dissect_h225_destinationInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_destinationInfo, ett_h225_EndPointType, EndPointType_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_multipleCalls(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_multipleCalls, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_maintainConnection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_maintainConnection, NULL, NULL);
+ return offset;
+}
+static per_sequence_t CallProceedingUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "destinationInfo", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_destinationInfo },
+ { "h245Address", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h245Address },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "h245SecurityMode", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_H245Security },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "fastStart", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_fastStart },
+ { "multipleCalls", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_multipleCalls },
+ { "maintainConnection", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_maintainConnection },
+ { "fastConnectRefused", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CallProceedingUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CallProceedingUUIE, ett_h225_CallProceedingUUIE, CallProceedingUUIE_sequence);
+ return offset;
+}
+
+static per_sequence_t CapacityReportingSpecification_when_sequence[] = {
+ { "callStart", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_NULL },
+ { "callEnd", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CapacityReportingSpecification_when(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CapacityReportingSpecification_when, ett_h225_CapacityReportingSpecification_when, CapacityReportingSpecification_when_sequence);
+ return offset;
+}
+
+static per_sequence_t CapacityReportingSpecification_sequence[] = {
+ { "when", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CapacityReportingSpecification_when },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CapacityReportingSpecification(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CapacityReportingSpecification, ett_h225_CapacityReportingSpecification, CapacityReportingSpecification_sequence);
+ return offset;
+}
+static per_sequence_t ProgressUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "destinationInfo", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_destinationInfo },
+ { "h245Address", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h245Address },
+ { "callIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "h245SecurityMode", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_H245Security },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "fastStart", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_fastStart },
+ { "multipleCalls", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_multipleCalls },
+ { "maintainConnection", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_maintainConnection },
+ { "fastConnectRefused", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ProgressUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ProgressUUIE, ett_h225_ProgressUUIE, ProgressUUIE_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_destExtraCallInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_destExtraCallInfo, ett_h225_destExtraCallInfo, dissect_h225_AliasAddress);
+ return offset;
+}
+
+static int
+dissect_h225_remoteExtensionAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_remoteExtensionAddress, ett_h225_remoteExtensionAddress, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+static int
+dissect_h225_aliasAddress_sequence(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_aliasAddress_sequence, ett_h225_aliasAddress_sequence, dissect_h225_AliasAddress);
+ return offset;
+}
+
+static int
+dissect_h225_rasAddress_sequence(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_rasAddress_sequence, ett_h225_rasAddress_sequence, dissect_h225_TransportAddress);
+ return offset;
+}
+
+static int
+dissect_h225_callSignalAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_callSignalAddress, ett_h225_callSignalAddress, dissect_h225_TransportAddress);
+ return offset;
+}
+
+
+static per_sequence_t EndPoint_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "aliasAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_aliasAddress_sequence },
+ { "callSignalAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_callSignalAddress },
+ { "rasAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_rasAddress_sequence },
+ { "endpointType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_EndPointType },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "priority", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_priority },
+ { "remoteExtensionAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_remoteExtensionAddress },
+ { "destExtraCallInfo", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destExtraCallInfo },
+ { "alternateTransportAddresses", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AlternateTransportAddress },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_EndPoint(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_EndPoint, ett_h225_EndPoint, EndPoint_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_icv(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+PER_NOT_DECODED_YET("icv");
+ return offset;
+}
+
+static per_sequence_t ICV_sequence[] = {
+ { "algorithmOID", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h225_algorithmOID },
+ { "icv", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_icv },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ICV(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ICV, ett_h225_ICV, ICV_sequence);
+ return offset;
+}
+
+static per_sequence_t BandwidthConfirm_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "bandWidth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_BandWidth },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_BandwidthConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_BandwidthConfirm, ett_h225_BandwidthConfirm, BandwidthConfirm_sequence);
+ return offset;
+}
+
+
+static per_sequence_t UnregistrationConfirm_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_UnregistrationConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_UnregistrationConfirm, ett_h225_UnregistrationConfirm, UnregistrationConfirm_sequence);
+ return offset;
+}
+static per_sequence_t NonStandardMessage_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_NonStandardMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_NonStandardMessage, ett_h225_NonStandardMessage, NonStandardMessage_sequence);
+ return offset;
+}
+
+
+static per_sequence_t InfoRequestAck_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_InfoRequestAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_InfoRequestAck, ett_h225_InfoRequestAck, InfoRequestAck_sequence);
+ return offset;
+}
+static per_sequence_t InfoRequestNak_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "nakReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_InfoRequestNakReason },
+ { "altGKInfo", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AltGKInfo },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_InfoRequestNak(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_InfoRequestNak, ett_h225_InfoRequestNak, InfoRequestNak_sequence);
+ return offset;
+}
+
+static per_sequence_t ResourcesAvailableConfirm_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ResourcesAvailableConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ResourcesAvailableConfirm, ett_h225_ResourcesAvailableConfirm, ResourcesAvailableConfirm_sequence);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_integrity(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_integrity, ett_h225_integrity, dissect_h225_IntegrityMechanism);
+ return offset;
+}
+
+
+static int
+dissect_h225_algorithmOIDs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_algorithmOIDs, ett_h225_algorithmOIDs, dissect_h225_algorithmOID);
+ return offset;
+}
+
+
+static int
+dissect_h225_alternateEndpoints(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_alternateEndpoints, ett_h225_alternateEndpoints, dissect_h225_EndPoint);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_endpointAlias(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_endpointAlias, ett_h225_endpointAlias, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+static per_sequence_t GatekeeperRequest_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "rasAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_rasAddress },
+ { "endpointType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_EndPointType },
+ { "gatekeeperIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "callServices", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_callServices },
+ { "endpointAlias", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_endpointAlias },
+ { "alternateEndpoints", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternateEndpoints },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "authenticationCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_authenticationCapability },
+ { "algorithmOIDs", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_algorithmOIDs },
+ { "integrity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_integrity },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "supportsAltGK", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_GatekeeperRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_GatekeeperRequest, ett_h225_GatekeeperRequest, GatekeeperRequest_sequence);
+ return offset;
+}
+
+static per_sequence_t ServiceControlResponse_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "result", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_SCRresult },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "featureSet", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ServiceControlResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ServiceControlResponse, ett_h225_ServiceControlResponse, ServiceControlResponse_sequence);
+ return offset;
+}
+
+
+
+static per_sequence_t DisengageReject_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "rejectReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_DisengageRejectReason },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "altGKInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AltGKInfo },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_DisengageReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_DisengageReject, ett_h225_DisengageReject, DisengageReject_sequence);
+ return offset;
+}
+
+
+
+static per_sequence_t BandwidthReject_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "rejectReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_BandRejectReason },
+ { "allowedBandWidth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_allowedBandWidth },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "altGKInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AltGKInfo },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_BandwidthReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_BandwidthReject, ett_h225_BandwidthReject, BandwidthReject_sequence);
+ return offset;
+}
+
+
+
+static per_sequence_t UnregistrationReject_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "rejectReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_UnregRejectReason },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "altGKInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AltGKInfo },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_UnregistrationReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_UnregistrationReject, ett_h225_UnregistrationReject, UnregistrationReject_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_endpointAliasPattern(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_endpointAliasPattern, ett_h225_endpointAliasPattern, dissect_h225_AddressPattern);
+ return offset;
+}
+
+static int
+dissect_h225_EndpointIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_BMPString(tvb, offset, pinfo, tree, hf_h225_EndpointIdentifier, 1, 128);
+ return offset;
+}
+
+static per_sequence_t UnregistrationRequest_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "callSignalAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_callSignalAddress },
+ { "endpointAlias", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_endpointAlias },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "endpointIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "alternateEndpoints", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternateEndpoints },
+ { "gatekeeperIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "reason", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_UnregRequestReason },
+ { "endpointAliasPattern", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_endpointAliasPattern },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { "alternateGatekeeper", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternateGatekeeper },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_UnregistrationRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_UnregistrationRequest, ett_h225_UnregistrationRequest, UnregistrationRequest_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_terminalAlias(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_terminalAlias, ett_h225_terminalAlias, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_terminalAliasPattern(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_terminalAliasPattern, ett_h225_terminalAliasPattern, dissect_h225_AddressPattern);
+ return offset;
+}
+
+
+static per_sequence_t invalidTerminalAliases_sequence[] = {
+ { "terminalAlias", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_terminalAlias },
+ { "terminalAliasPattern", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_terminalAliasPattern },
+ { "supportedPrefixes", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_invalidTerminalAliases(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_invalidTerminalAliases, ett_h225_invalidTerminalAliases, invalidTerminalAliases_sequence);
+ return offset;
+}
+
+
+
+
+
+
+static int
+dissect_h225_duplicateAlias(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_duplicateAlias, ett_h225_duplicateAlias, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+
+
+
+const value_string RegistrationRejectReason_vals[] = {
+ { 0, "discoveryRequired" },
+ { 1, "invalidRevision" },
+ { 2, "invalidCallSignalAddress" },
+ { 3, "invalidRASAddress" },
+ { 4, "duplicateAlias" },
+ { 5, "invalidTerminalType" },
+ { 6, "undefinedReason" },
+ { 7, "transportNotSupported" },
+ { 8, "transportQOSNotSupported" },
+ { 9, "resourceUnavailable" },
+ { 10, "invalidAlias" },
+ { 11, "securityDenial" },
+ { 12, "fullRegistrationRequired" },
+ { 13, "additiveRegistrationNotSupported" },
+ { 14, "invalidTerminalAliases" },
+ { 15, "genericDataReason" },
+ { 16, "neededFeatureNotSupported" },
+ { 17, "securityError" },
+ { 0, NULL}
+};
+static per_choice_t RegistrationRejectReason_choice[] = {
+ { 0, "discoveryRequired", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 1, "invalidRevision", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 2, "invalidCallSignalAddress", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 3, "invalidRASAddress", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 4, "duplicateAlias", ASN1_EXTENSION_ROOT,
+ dissect_h225_duplicateAlias },
+ { 5, "invalidTerminalType", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 6, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 7, "transportNotSupported", ASN1_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 8, "transportQOSNotSupported", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 9, "resourceUnavailable", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 10, "invalidAlias", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 11, "securityDenial", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 12, "fullRegistrationRequired", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 13, "additiveRegistrationNotSupported", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 14, "invalidTerminalAliases", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_invalidTerminalAliases },
+ { 15, "genericDataReason", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 16, "neededFeatureNotSupported", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 17, "securityError", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SecurityErrors },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_RegistrationRejectReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_RegistrationRejectReason, ett_h225_RegistrationRejectReason, RegistrationRejectReason_choice, "RegistrationRejectReason", &value);
+ h225_pi.reason = value;
+ return offset;
+}
+
+
+
+
+
+
+static per_sequence_t RegistrationReject_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "rejectReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RegistrationRejectReason },
+ { "gatekeeperIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "altGKInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AltGKInfo },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RegistrationReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RegistrationReject, ett_h225_RegistrationReject, RegistrationReject_sequence);
+ return offset;
+}
+
+
+static per_sequence_t GatekeeperReject_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "gatekeeperIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "rejectReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_GatekeeperRejectReason },
+ { "altGKInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AltGKInfo },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_GatekeeperReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_GatekeeperReject, ett_h225_GatekeeperReject, GatekeeperReject_sequence);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_almostOutOfResources(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_almostOutOfResources, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_protocols(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_protocols, ett_h225_protocols, dissect_h225_SupportedProtocols);
+ return offset;
+}
+
+static per_sequence_t ResourcesAvailableIndicate_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "endpointIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "protocols", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_protocols },
+ { "almostOutOfResources", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_almostOutOfResources },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ResourcesAvailableIndicate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ResourcesAvailableIndicate, ett_h225_ResourcesAvailableIndicate, ResourcesAvailableIndicate_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_amountString(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+PER_NOT_DECODED_YET("amountString");
+ return offset;
+}
+
+
+
+static int
+dissect_h225_callDurationLimit(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_callDurationLimit, 1, 4294967295UL,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static int
+dissect_h225_enforceCallDurationLimit(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_enforceCallDurationLimit, NULL, NULL);
+ return offset;
+}
+
+
+static per_sequence_t CallCreditServiceControl_sequence[] = {
+ { "amountString", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_amountString },
+ { "billingMode", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_billingMode },
+ { "callDurationLimit", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_callDurationLimit },
+ { "enforceCallDurationLimit", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_enforceCallDurationLimit },
+ { "callStartingPoint", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CCSCcallStartingPoint },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_CallCreditServiceControl(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_CallCreditServiceControl, ett_h225_CallCreditServiceControl, CallCreditServiceControl_sequence);
+ return offset;
+}
+
+
+
+static const value_string ScreeningIndicator_vals[] = {
+ { 0, "userProvidedNotScreened" },
+ { 1, "userProvidedVerifiedAndPassed" },
+ { 2, "userProvidedVerifiedAndFailed" },
+ { 3, "networkProvided" },
+ { 0, NULL },
+};
+
+static int
+dissect_h225_ScreeningIndicator(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_ScreeningIndicator, 0, 3,
+ NULL, NULL, TRUE);
+ return offset;
+}
+
+static per_sequence_t ExtendedAliasAddress_sequence[] = {
+ { "address", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_AliasAddress },
+ { "presentationIndicator", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_PresentationIndicator },
+ { "screeningIndicator", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ScreeningIndicator },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ExtendedAliasAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ExtendedAliasAddress, ett_h225_ExtendedAliasAddress, ExtendedAliasAddress_sequence);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_messageNotUnderstood(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_messageNotUnderstood, -1, -1, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t UnknownMessageResponse_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "messageNotUnderstood", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_messageNotUnderstood },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_UnknownMessageResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_UnknownMessageResponse, ett_h225_UnknownMessageResponse, UnknownMessageResponse_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_CallReferenceValue(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_CallReferenceValue, 0, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_canMapSrcAlias(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_canMapSrcAlias, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_desiredProtocols(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_desiredProtocols, ett_h225_desiredProtocols, dissect_h225_SupportedProtocols);
+ return offset;
+}
+
+static int
+dissect_h225_willSupplyUUIEs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_willSupplyUUIEs, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_destAlternatives(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_destAlternatives, ett_h225_destAlternatives, dissect_h225_EndPoint);
+ return offset;
+}
+
+static int
+dissect_h225_srcAlternatives(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_srcAlternatives, ett_h225_srcAlternatives, dissect_h225_EndPoint);
+ return offset;
+}
+
+static int
+dissect_h225_canMapAlias(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_canMapAlias, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_answerCall(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_answerCall, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_activeMC(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_activeMC, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_srcInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_srcInfo, ett_h225_srcInfo, dissect_h225_AliasAddress);
+ return offset;
+}
+
+static int
+dissect_h225_DestinationInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_DestinationInfo, ett_h225_DestinationInfo, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+
+
+
+
+static per_sequence_t AdmissionRequest_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "callType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallType },
+ { "callModel", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallModel },
+ { "endpointIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "DestinationInfo", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_DestinationInfo },
+ { "destCallSignalAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destCallSignalAddress },
+ { "destExtraCallInfo", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destExtraCallInfo },
+ { "srcInfo", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_srcInfo },
+ { "sourceCallSignalAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_sourceCallSignalAddress },
+ { "bandWidth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_BandWidth },
+ { "callReferenceValue", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallReferenceValue },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "callServices", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_callServices },
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_conferenceID },
+ { "activeMC", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_activeMC },
+ { "answerCall", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_answerCall },
+ { "canMapAlias", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_canMapAlias },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "srcAlternatives", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_srcAlternatives },
+ { "destAlternatives", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destAlternatives },
+ { "gatekeeperIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "transportQOS", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_TransportQOS },
+ { "willSupplyUUIEs", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_willSupplyUUIEs },
+ { "callLinkage", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallLinkage },
+ { "gatewayDataRate", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_gatewayDataRate },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { "desiredProtocols", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_desiredProtocols },
+ { "desiredTunnelledProtocol", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_desiredTunnelledProtocol },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { "canMapSrcAlias", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_canMapSrcAlias },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_AdmissionRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_AdmissionRequest, ett_h225_AdmissionRequest, AdmissionRequest_sequence);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_nextSegmentRequested(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_nextSegmentRequested, 0, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static per_sequence_t InfoRequest_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "callReferenceValue", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallReferenceValue },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "replyAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_replyAddress },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "uuiesRequested", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_UUIEsRequested },
+ { "callLinkage", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallLinkage },
+ { "usageInfoRequested", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_RasUsageInfoTypes },
+ { "segmentedResponseSupported", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "nextSegmentRequested", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nextSegmentRequested },
+ { "capacityInfoRequested", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_InfoRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_InfoRequest, ett_h225_InfoRequest, InfoRequest_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_delay(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_delay, 1, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static per_sequence_t RequestInProgress_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "delay", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_delay },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RequestInProgress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RequestInProgress, ett_h225_RequestInProgress, RequestInProgress_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_H248SignalsDescriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_H248SignalsDescriptor, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_url(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_url, 0, 512);
+ return offset;
+}
+
+
+static const value_string ServiceControlDescriptor_vals[] = {
+ { 0, "url" },
+ { 1, "signal" },
+ { 2, "nonStandard" },
+ { 3, "callCreditServiceControl" },
+ { 0, NULL}
+};
+static per_choice_t ServiceControlDescriptor_choice[] = {
+ { 0, "url", ASN1_EXTENSION_ROOT,
+ dissect_h225_url },
+ { 1, "signal", ASN1_EXTENSION_ROOT,
+ dissect_h225_H248SignalsDescriptor },
+ { 2, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h225_nonStandard },
+ { 3, "callCreditServiceControl", ASN1_EXTENSION_ROOT,
+ dissect_h225_CallCreditServiceControl },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_ServiceControlDescriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_ServiceControlDescriptor, ett_h225_ServiceControlDescriptor, ServiceControlDescriptor_choice, "ServiceControlDescriptor", NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_sessionId(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_sessionId, 0, 255,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static per_sequence_t ServiceControlSession_sequence[] = {
+ { "sessionId", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_sessionId },
+ { "contents", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ServiceControlDescriptor },
+ { "reason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ServiceControlSession_reason },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ServiceControlSession(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ServiceControlSession, ett_h225_ServiceControlSession, ServiceControlSession_sequence);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_serviceControl(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_serviceControl, ett_h225_serviceControl, dissect_h225_ServiceControlSession);
+ return offset;
+}
+
+
+static int
+dissect_h225_alertingAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_alertingAddress, ett_h225_alertingAddress, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+static per_sequence_t AlertingUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "destinationInfo", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_destinationInfo },
+ { "h245Address", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h245Address },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "h245SecurityMode", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_H245Security },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "fastStart", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_fastStart },
+ { "multipleCalls", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_multipleCalls },
+ { "maintainConnection", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_maintainConnection },
+ { "alertingAddress", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alertingAddress },
+ { "presentationIndicator", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_PresentationIndicator },
+ { "screeningIndicator", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ScreeningIndicator },
+ { "fastConnectRefused", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_AlertingUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_AlertingUUIE, ett_h225_AlertingUUIE, AlertingUUIE_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_busyAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_busyAddress, ett_h225_busyAddress, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+static per_sequence_t ReleaseCompleteUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "reason", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ReleaseCompleteReason },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "busyAddress", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_busyAddress },
+ { "presentationIndicator", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_PresentationIndicator },
+ { "screeningIndicator", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ScreeningIndicator },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ReleaseCompleteUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ReleaseCompleteUUIE, ett_h225_ReleaseCompleteUUIE, ReleaseCompleteUUIE_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_alternativeAliasAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_alternativeAliasAddress, ett_h225_alternativeAliasAddress, dissect_h225_AliasAddress);
+ return offset;
+}
+
+static per_sequence_t FacilityUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "alternativeAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternativeAddress },
+ { "alternativeAliasAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternativeAliasAddress },
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_conferenceID },
+ { "reason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_FacilityReason },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "destExtraCallInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destExtraCallInfo },
+ { "remoteExtensionAddress", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_RemoteExtensionAddress },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "conferences", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_conferences },
+ { "h245Address", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h245Address },
+ { "fastStart", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_fastStart },
+ { "multipleCalls", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_multipleCalls },
+ { "maintainConnection", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_maintainConnection },
+ { "fastConnectRefused", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "destinationInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destinationInfo },
+ { "h245SecurityMode", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_H245Security },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_FacilityUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_FacilityUUIE, ett_h225_FacilityUUIE, FacilityUUIE_sequence);
+ return offset;
+}
+
+static per_sequence_t AdmissionReject_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "rejectReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_AdmissionRejectReason },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "altGKInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AltGKInfo },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "callSignalAddress", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_callSignalAddress },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_AdmissionReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_AdmissionReject, ett_h225_AdmissionReject, AdmissionReject_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_hopCount(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_hopCount, 1, 31,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static int
+dissect_h225_parallelH245Control_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *h245_tvb;
+ guint32 h245_offset=0;
+ guint32 h245_len=0;
+
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, -1, -1, -1, &h245_offset, &h245_len);
+
+ if(h245_len){
+ gboolean save_info;
+
+ /* dont update the INFO or PROTOCOL fields of the summary */
+ save_info=col_get_writable(pinfo->cinfo);
+ col_set_writable(pinfo->cinfo, FALSE);
+ h245_tvb = tvb_new_subset(tvb, h245_offset, h245_len, h245_len);
+ call_dissector(h245dg_handle, h245_tvb, pinfo, tree);
+ col_set_writable(pinfo->cinfo, save_info);
+ }
+
+ return offset;
+}
+
+static int
+dissect_h225_parallelH245Control(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_parallelH245Control, ett_h225_parallelH245Control, dissect_h225_parallelH245Control_item);
+ return offset;
+}
+
+static int
+dissect_h225_language(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h225_language, 1, 32);
+ return offset;
+}
+
+static int
+dissect_h225_languages(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_languages, ett_h225_languages, dissect_h225_language);
+ return offset;
+}
+
+static int
+dissect_h225_mediaWaitForConnect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_mediaWaitForConnect, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_canOverlapSend(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_canOverlapSend, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_sourceAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_sourceAddress, ett_h225_sourceAddress, dissect_h225_AliasAddress);
+ return offset;
+}
+
+static int
+dissect_h225_destinationAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_destinationAddress, ett_h225_destinationAddress, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+static int
+dissect_h225_destExtraCRV(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_destExtraCRV, ett_h225_destExtraCRV, dissect_h225_CallReferenceValue);
+ return offset;
+}
+
+static int
+dissect_h225_h245SecurityCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_h245SecurityCapability, ett_h225_h245SecurityCapability, dissect_h225_H245Security);
+ return offset;
+}
+
+static int
+dissect_h225_additionalSourceAddresses(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_additionalSourceAddresses, ett_h225_additionalSourceAddresses, dissect_h225_ExtendedAliasAddress);
+ return offset;
+}
+
+
+
+static per_sequence_t SetupUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "h245Address", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h245Address },
+ { "sourceAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_sourceAddress },
+ { "sourceInfo", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_sourceInfo },
+ { "destinationAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destinationAddress },
+ { "destCallSignalAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destCallSignalAddress },
+ { "destExtraCallInfo", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destExtraCallInfo },
+ { "destExtraCRV", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destExtraCRV },
+ { "activeMC", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_activeMC },
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_conferenceID },
+ { "conferenceGoal", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_conferenceGoal },
+ { "callServices", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_callServices },
+ { "callType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallType },
+ { "sourceCallSignalAddress", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_sourceCallSignalAddress },
+ { "RemoteExtensionAddress", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_RemoteExtensionAddress },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "h245SecurityCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h245SecurityCapability },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "fastStart", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_fastStart },
+ { "mediaWaitForConnect", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_mediaWaitForConnect },
+ { "canOverlapSend", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_canOverlapSend },
+ { "endpointIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "multipleCalls", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_multipleCalls },
+ { "maintainConnection", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_maintainConnection },
+ { "connectionParameters", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_connectionParameters },
+ { "languages", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_languages },
+ { "presentationIndicator", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_PresentationIndicator },
+ { "screeningIndicator", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ScreeningIndicator },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "symmetricOperationRequired", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { "desiredProtocols", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_desiredProtocols },
+ { "neededFeatures", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_neededFeatures },
+ { "desiredFeatures", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_desiredFeatures },
+ { "supportedFeatures", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_supportedFeatures },
+ { "parallelH245Control", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_parallelH245Control },
+ { "additionalSourceAddresses", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_additionalSourceAddresses },
+ { "hopCount", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_hopCount },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_SetupUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ contains_faststart = FALSE;
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_SetupUUIE, ett_h225_SetupUUIE, SetupUUIE_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_connectedAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_connectedAddress, ett_h225_connectedAddress, dissect_h225_AliasAddress);
+ return offset;
+}
+
+static per_sequence_t ConnectUUIE_sequence[] = {
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "h245Address", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h245Address },
+ { "destinationInfo", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_destinationInfo },
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_conferenceID },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "h245SecurityMode", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_H245Security },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "fastStart", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_fastStart },
+ { "multipleCalls", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_multipleCalls },
+ { "maintainConnection", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_maintainConnection },
+ { "languages", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_languages },
+ { "connectedAddress", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_connectedAddress },
+ { "presentationIndicator", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_PresentationIndicator },
+ { "screeningIndicator", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ScreeningIndicator },
+ { "fastConnectRefused", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ConnectUUIE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ConnectUUIE, ett_h225_ConnectUUIE, ConnectUUIE_sequence);
+ return offset;
+}
+
+
+const value_string h323_message_body_vals[] = {
+ { 0, "setup" },
+ { 1, "callProceeding" },
+ { 2, "connect" },
+ { 3, "alerting" },
+ { 4, "information" },
+ { 5, "releaseComplete" },
+ { 6, "facility" },
+ { 7, "progress" },
+ { 8, "empty" },
+ { 9, "status" },
+ { 10, "statusInquiry" },
+ { 11, "setupAcknowledge" },
+ { 12, "notify" },
+ { 0, NULL}
+};
+static per_choice_t h323_message_body_choice[] = {
+ { 0, "setup", ASN1_EXTENSION_ROOT,
+ dissect_h225_SetupUUIE },
+ { 1, "callProceeding", ASN1_EXTENSION_ROOT,
+ dissect_h225_CallProceedingUUIE },
+ { 2, "connect", ASN1_EXTENSION_ROOT,
+ dissect_h225_ConnectUUIE },
+ { 3, "alerting", ASN1_EXTENSION_ROOT,
+ dissect_h225_AlertingUUIE },
+ { 4, "information", ASN1_EXTENSION_ROOT,
+ dissect_h225_InformationUUIE },
+ { 5, "releaseComplete", ASN1_EXTENSION_ROOT,
+ dissect_h225_ReleaseCompleteUUIE },
+ { 6, "facility", ASN1_EXTENSION_ROOT,
+ dissect_h225_FacilityUUIE },
+ { 7, "progress", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_ProgressUUIE },
+ { 8, "empty", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NULL },
+ { 9, "status", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_StatusUUIE },
+ { 10, "statusInquiry", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_StatusInquiryUUIE },
+ { 11, "setupAcknowledge", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_SetupAcknowledgeUUIE },
+ { 12, "notify", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_NotifyUUIE },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h225_h323_message_body(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ contains_faststart = FALSE;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h225_h323_message_body, ett_h225_h323_message_body, h323_message_body_choice, "h323_message_body", &(value));
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, "CS: %s ",
+ val_to_str(value, h323_message_body_vals, "<unknown>"));
+ }
+
+ if (h225_pi.msg_type == H225_CS) {
+ /* Don't override msg_tag value from IRR */
+ h225_pi.msg_tag = value;
+ }
+
+ if (contains_faststart == TRUE )
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, "OpenLogicalChannel " );
+ }
+ }
+
+ col_set_fence(pinfo->cinfo,COL_INFO);
+
+ return offset;
+}
+
+static int
+dissect_h225_supportedProtocols(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_supportedProtocols, ett_h225_supportedProtocols, dissect_h225_SupportedProtocols);
+ return offset;
+}
+
+static int
+dissect_h225_modifiedSrcInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_modifiedSrcInfo, ett_h225_modifiedSrcInfo, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+static per_sequence_t LocationConfirm_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "callSignalAddress2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallSignalAddress2 },
+ { "rasAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_rasAddress },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "DestinationInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_DestinationInfo },
+ { "destExtraCallInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destExtraCallInfo },
+ { "destinationType", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destinationType },
+ { "remoteExtensionAddress", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_remoteExtensionAddress },
+ { "alternateEndpoints", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternateEndpoints },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "alternateTransportAddresses", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AlternateTransportAddress },
+ { "supportedProtocols", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_supportedProtocols },
+ { "multipleCalls", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_multipleCalls },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "modifiedSrcInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_modifiedSrcInfo },
+ { "bandWidth", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_BandWidth },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_LocationConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_LocationConfirm, ett_h225_LocationConfirm, LocationConfirm_sequence);
+ return offset;
+}
+
+static per_sequence_t LocationReject_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "rejectReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_LocationRejectReason },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "altGKInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AltGKInfo },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_LocationReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_LocationReject, ett_h225_LocationReject, LocationReject_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_answeredCall(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_answeredCall, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t callSpecific_sequence[] = {
+ { "callIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_conferenceID },
+ { "answeredCall", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_answeredCall },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_callSpecific(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_callSpecific, ett_h225_callSpecific, callSpecific_sequence);
+ return offset;
+}
+
+static per_sequence_t ServiceControlIndication_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "serviceControl", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "endpointIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "callSpecific", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_callSpecific },
+ { "tokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "featureSet", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_ServiceControlIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_ServiceControlIndication, ett_h225_ServiceControlIndication, ServiceControlIndication_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_alertingTime(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_TimeStamp(tvb, offset, pinfo, tree, hf_h225_alertingTime);
+ return offset;
+}
+static int
+dissect_h225_connectTime(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_TimeStamp(tvb, offset, pinfo, tree, hf_h225_connectTime);
+ return offset;
+}
+static int
+dissect_h225_endTime(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_h235_TimeStamp(tvb, offset, pinfo, tree, hf_h225_endTimeStamp);
+ return offset;
+}
+
+static int
+dissect_h225_nonStandardUsageFields_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_h225_NonStandardParameter(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardUsageFields_item);
+ return offset;
+}
+
+static int
+dissect_h225_nonStandardUsageFields(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_sequence_of(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardUsageFields,
+ ett_h225_T_nonStandardUsageFields, dissect_h225_nonStandardUsageFields_item);
+ return offset;
+}
+
+
+static per_sequence_t RasUsageInformation_sequence[] = {
+ { "nonStandardUsageFields", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_nonStandardUsageFields },
+ { "alertingTime", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alertingTime },
+ { "connectTime", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_connectTime },
+ { "endTime", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_endTime },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RasUsageInformation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RasUsageInformation, ett_h225_RasUsageInformation, RasUsageInformation_sequence);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_TimeToLive(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_TimeToLive, 1, 4294967295UL,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int dissect_h225_authenticationMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ /* XXX - asn2eth.py should use "int" for offset arguments and return values
+ in more cases. */
+ return dissect_h235_AuthenticationMechanism(tvb, offset, pinfo, tree, hf_h225_authenticationMode);
+}
+
+static per_sequence_t GatekeeperConfirm_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "gatekeeperIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "rasAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_rasAddress },
+ { "alternateGatekeeper", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternateGatekeeper },
+ { "authenticationMode", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_authenticationMode },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "algorithmOID", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_algorithmOID },
+ { "integrity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_integrity },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_GatekeeperConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_GatekeeperConfirm, ett_h225_GatekeeperConfirm, GatekeeperConfirm_sequence);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_discoveryComplete(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_discoveryComplete, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_keepAlive(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_keepAlive, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_H248PackagesDescriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_H248PackagesDescriptor, -1, -1, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_supportedH248Packages(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_supportedH248Packages, ett_h225_supportedH248Packages, dissect_h225_H248PackagesDescriptor);
+ return offset;
+}
+
+
+static per_sequence_t RegistrationRequest_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "discoveryComplete", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_discoveryComplete },
+ { "callSignalAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_callSignalAddress },
+ { "rasAddress_sequence", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_rasAddress_sequence },
+ { "terminalType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_terminalType },
+ { "terminalAlias", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_terminalAlias },
+ { "gatekeeperIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "endpointVendor", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_VendorIdentifier },
+ { "alternateEndpoints", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternateEndpoints },
+ { "timeToLive", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_TimeToLive },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "keepAlive", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_keepAlive },
+ { "endpointIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "willSupplyUUIEs", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_willSupplyUUIEs },
+ { "maintainConnection", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_maintainConnection },
+ { "alternateTransportAddresses", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AlternateTransportAddress },
+ { "additiveRegistration", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "terminalAliasPattern", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_terminalAliasPattern },
+ { "supportsAltGK", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "usageReportingCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_usageReportingCapability },
+ { "multipleCalls", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_multipleCalls },
+ { "supportedH248Packages", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_supportedH248Packages },
+ { "callCreditCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCreditCapability },
+ { "capacityReportingCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CapacityReportingCapability },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { "restart", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "supportsACFSequences", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RegistrationRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RegistrationRequest, ett_h225_RegistrationRequest, RegistrationRequest_sequence);
+ return offset;
+}
+
+
+static per_sequence_t DisengageConfirm_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { "usageInformation", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_RasUsageInformation },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_DisengageConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_DisengageConfirm, ett_h225_DisengageConfirm, DisengageConfirm_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_irrFrequency(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_irrFrequency, 1, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h225_willRespondToIRR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_willRespondToIRR, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_usageSpec(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_usageSpec, ett_h225_usageSpec, dissect_h225_RasUsageSpecification);
+ return offset;
+}
+
+static per_sequence_t AdmissionConfirm_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "bandWidth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_BandWidth },
+ { "callModel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallModel },
+ { "destCallSignalAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_destCallSignalAddress },
+ { "irrFrequency", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_irrFrequency },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "DestinationInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_DestinationInfo },
+ { "destExtraCallInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destExtraCallInfo },
+ { "destinationType", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_destinationType },
+ { "remoteExtensionAddress", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_remoteExtensionAddress },
+ { "alternateEndpoints", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternateEndpoints },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "transportQOS", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_TransportQOS },
+ { "willRespondToIRR", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_willRespondToIRR },
+ { "uuiesRequested", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_UUIEsRequested },
+ { "languages", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_languages },
+ { "alternateTransportAddresses", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AlternateTransportAddress },
+ { "useSpecifiedTransport", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_UseSpecifiedTransport },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { "usageSpec", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_usageSpec },
+ { "supportedProtocols", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_supportedProtocols },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "multipleCalls", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_multipleCalls },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { "modifiedSrcInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_modifiedSrcInfo },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_AdmissionConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_AdmissionConfirm, ett_h225_AdmissionConfirm, AdmissionConfirm_sequence);
+ return offset;
+}
+
+
+static per_sequence_t DisengageRequest_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "endpointIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_conferenceID },
+ { "callReferenceValue", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallReferenceValue },
+ { "disengageReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_DisengageReason },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "gatekeeperIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "answeredCall", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_answeredCall },
+ { "callLinkage", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallLinkage },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { "usageInformation", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_RasUsageInformation },
+ { "terminationCause", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallTerminationCause },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_DisengageRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_DisengageRequest, ett_h225_DisengageRequest, DisengageRequest_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_SourceInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_SourceInfo, ett_h225_SourceInfo, dissect_h225_AliasAddress);
+ return offset;
+}
+
+static int
+dissect_h225_hopCount255(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_hopCount255, 1, 255,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h225_sourceEndpointInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_sourceEndpointInfo, ett_h225_sourceEndpointInfo, dissect_h225_AliasAddress);
+ return offset;
+}
+
+static per_sequence_t LocationRequest_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "endpointIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "DestinationInfo", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_DestinationInfo },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "replyAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_replyAddress },
+ { "SourceInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_SourceInfo },
+ { "canMapAlias", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_canMapAlias },
+ { "gatekeeperIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "desiredProtocols", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_desiredProtocols },
+ { "desiredTunnelledProtocol", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_desiredTunnelledProtocol },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { "hopCount255", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_hopCount255 },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "bandWidth", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_BandWidth },
+ { "sourceEndpointInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_sourceEndpointInfo },
+ { "canMapSrcAlias", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_canMapSrcAlias },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_LocationRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_LocationRequest, ett_h225_LocationRequest, LocationRequest_sequence);
+ return offset;
+}
+
+static int
+dissect_h225_bandwidthDetails(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_bandwidthDetails, ett_h225_bandwidthDetails, dissect_h225_BandwidthDetails);
+ return offset;
+}
+
+static per_sequence_t BandwidthRequest_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "endpointIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_conferenceID },
+ { "callReferenceValue", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallReferenceValue },
+ { "callType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallType },
+ { "bandWidth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_BandWidth },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "gatekeeperIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "answeredCall", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_answeredCall },
+ { "callLinkage", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallLinkage },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "usageInformation", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_RasUsageInformation },
+ { "bandwidthDetails", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_bandwidthDetails },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_BandwidthRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_BandwidthRequest, ett_h225_BandwidthRequest, BandwidthRequest_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_admissionConfirmSequence(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_admissionConfirmSequence, ett_h225_admissionConfirmSequence, dissect_h225_AdmissionConfirm);
+ return offset;
+}
+
+
+static int
+dissect_h225_messageContent_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value_offset, value_len;
+ tvbuff_t *next_tvb;
+
+ offset = dissect_per_octet_string(tvb, offset, pinfo, tree,
+ hf_h225_messageContent_item, -1, -1,
+ &value_offset, &value_len);
+
+ if (value_len > 0) {
+ next_tvb = tvb_new_subset(tvb, value_offset, value_len, value_len);
+ call_dissector((tp_handle)?tp_handle:data_handle, next_tvb, pinfo, tree);
+ }
+ return offset;
+}
+
+
+static int
+dissect_h225_messageContent(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_messageContent, ett_h225_messageContent, dissect_h225_messageContent_item);
+ return offset;
+}
+
+
+static int
+dissect_h225_h4501SupplementaryService_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *h4501_tvb;
+ guint32 h4501_offset=0;
+ guint32 h4501_len=0;
+
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, -1, -1, -1, &h4501_offset, &h4501_len);
+
+ if(h4501_len){
+ h4501_tvb = tvb_new_subset(tvb, h4501_offset, h4501_len, h4501_len);
+ call_dissector(h4501_handle, h4501_tvb, pinfo, tree);
+ }
+ return offset;
+}
+
+static int
+dissect_h225_h4501SupplementaryService(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_h4501SupplementaryService, ett_h225_h4501SupplementaryService, dissect_h225_h4501SupplementaryService_item);
+ return offset;
+}
+
+
+static per_sequence_t tunnelledSignallingMessage_sequence[] = {
+ { "tunnelledProtocolID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_TunnelledProtocol },
+ { "messageContent", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_messageContent },
+ { "tunnellingRequired", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_tunnelledSignallingMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ tp_handle = NULL;
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_tunnelledSignallingMessage, ett_h225_tunnelledSignallingMessage, tunnelledSignallingMessage_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_h245Tunneling(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_h245Tunneling, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_h245Control_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *h245_tvb;
+ guint32 h245_offset=0;
+ guint32 h245_len=0;
+
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, -1, -1, -1, &h245_offset, &h245_len);
+
+ if(h245_len){
+ h245_tvb = tvb_new_subset(tvb, h245_offset, h245_len, h245_len);
+ call_dissector(h245dg_handle, h245_tvb, pinfo, tree);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_h225_h245Control(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_h245Control, ett_h225_h245Control, dissect_h225_h245Control_item);
+ return offset;
+}
+
+
+static int
+dissect_h225_nonStandardControl_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_h225_NonStandardParameter(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardControl_item);
+ return offset;
+}
+
+static int
+dissect_h225_nonStandardControl(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_per_sequence_of(tvb, offset, pinfo, tree,
+ hf_h225_nonStandardControl,
+ ett_h225_T_nonStandardControl, dissect_h225_nonStandardControl_item);
+ return offset;
+}
+
+
+static per_sequence_t H323_UU_PDU_sequence[] = {
+ { "h323_message_body", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_h323_message_body },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "h4501SupplementaryService", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h4501SupplementaryService },
+ { "h245Tunneling", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_h245Tunneling },
+ { "h245Control", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_h245Control },
+ { "nonStandardControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardControl },
+ { "callLinkage", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallLinkage },
+ { "tunnelledSignallingMessage", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tunnelledSignallingMessage },
+ { "provisionalRespToH245Tunneling", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "stimulusControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_StimulusControl },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_H323_UU_PDU(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_H323_UU_PDU, ett_h225_H323_UU_PDU, H323_UU_PDU_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_makeCall(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_makeCall, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_useGKCallSignalAddressToMakeCall(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_useGKCallSignalAddressToMakeCall, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_useGKCallSignalAddressToAnswer(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_useGKCallSignalAddressToAnswer, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t preGrantedARQ_sequence[] = {
+ { "makeCall", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_makeCall },
+ { "useGKCallSignalAddressToMakeCall", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_useGKCallSignalAddressToMakeCall },
+ { "answerCall", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_answerCall },
+ { "useGKCallSignalAddressToAnswer", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_useGKCallSignalAddressToAnswer },
+ { "irrFrequencyInCall", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_irrFrequency },
+ { "totalBandwidthRestriction", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_totalBandwidthRestriction },
+ { "alternateTransportAddresses", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AlternateTransportAddress },
+ { "useSpecifiedTransport", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_UseSpecifiedTransport },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_preGrantedARQ(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_preGrantedARQ, ett_h225_preGrantedARQ, preGrantedARQ_sequence);
+ return offset;
+}
+
+
+
+static per_sequence_t RegistrationConfirm_sequence[] = {
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_ProtocolIdentifier },
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "callSignalAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_callSignalAddress },
+ { "terminalAlias", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_terminalAlias },
+ { "gatekeeperIdentifier", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_GatekeeperIdentifier },
+ { "endpointIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "alternateGatekeeper", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_alternateGatekeeper },
+ { "timeToLive", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_TimeToLive },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "willRespondToIRR", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_willRespondToIRR },
+ { "preGrantedARQ", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_preGrantedARQ },
+ { "maintainConnection", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_maintainConnection },
+ { "serviceControl", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_serviceControl },
+ { "supportsAdditiveRegistration", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_NULL },
+ { "terminalAliasPattern", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_terminalAliasPattern },
+ { "supportedPrefixes", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_SupportedPrefixes },
+ { "usageSpec", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_usageSpec },
+ { "featureServerAlias", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_featureServerAlias },
+ { "capacityReportingSpec", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CapacityReportingSpecification },
+ { "featureSet", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_FeatureSet },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_RegistrationConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_RegistrationConfirm, ett_h225_RegistrationConfirm, RegistrationConfirm_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h225_sent(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_sent, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t pdu_item_sequence[] = {
+ { "h323pdu", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_H323_UU_PDU },
+ { "sent", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h225_sent },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_pdu_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ gboolean save_info;
+
+ /* dont update the INFO or PROTOCOL fields of the summary */
+ save_info=col_get_writable(pinfo->cinfo);
+ col_set_writable(pinfo->cinfo, FALSE);
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_pdu_item, ett_h225_pdu_item, pdu_item_sequence);
+ col_set_writable(pinfo->cinfo, save_info);
+ return offset;
+}
+
+
+static int
+dissect_h225_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_pdu, ett_h225_pdu, dissect_h225_pdu_item);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_originator(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_originator, NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_h225_audio(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_audio, ett_h225_audio, dissect_h225_RTPSession);
+ return offset;
+}
+
+static int
+dissect_h225_video(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_video, ett_h225_video, dissect_h225_RTPSession);
+ return offset;
+}
+
+static int
+dissect_h225_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_data, ett_h225_data, dissect_h225_RTPSession);
+ return offset;
+}
+
+
+static int
+dissect_h225_substituteConfIDs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_substituteConfIDs, ett_h225_substituteConfIDs, dissect_h225_conferenceID);
+ return offset;
+}
+
+
+static per_sequence_t perCallInfo_item_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "callReferenceValue", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallReferenceValue },
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_conferenceID },
+ { "originator", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_originator },
+ { "audio", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_audio },
+ { "video", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_video },
+ { "data", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_data },
+ { "h245", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_h245 },
+ { "callSignaling", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_callSignaling },
+ { "callType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallType },
+ { "bandWidth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_BandWidth },
+ { "callModel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallModel },
+ { "callIdentifier", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_CallIdentifier },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "substituteConfIDs", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_substituteConfIDs },
+ { "pdu", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_pdu },
+ { "callLinkage", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallLinkage },
+ { "usageInformation", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_RasUsageInformation },
+ { "circuitInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CircuitInfo },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_perCallInfo_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_perCallInfo_item, ett_h225_perCallInfo_item, perCallInfo_item_sequence);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h225_perCallInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h225_perCallInfo, ett_h225_perCallInfo, dissect_h225_perCallInfo_item);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_needResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_needResponse, NULL, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h225_unsolicited(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h225_unsolicited, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t InfoRequestResponse_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_nonStandardData },
+ { "requestSeqNum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_RequestSeqNum },
+ { "endpointType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_EndPointType },
+ { "endpointIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_EndpointIdentifier },
+ { "rasAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_rasAddress },
+ { "callSignalAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_callSignalAddress },
+ { "endpointAlias", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_endpointAlias },
+ { "perCallInfo", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_perCallInfo },
+ { "tokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_tokens },
+ { "cryptoTokens", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CryptoH323Token_sequence_of },
+ { "integrityCheckValue", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_ICV },
+ { "needResponse", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_needResponse },
+ { "capacity", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_CallCapacity },
+ { "irrStatus", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_InfoRequestResponseStatus },
+ { "unsolicited", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_unsolicited },
+ { "genericData", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_genericData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_InfoRequestResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_InfoRequestResponse, ett_h225_InfoRequestResponse, InfoRequestResponse_sequence);
+ return offset;
+}
+
+
+
+static int
+dissect_h225_protocol_discriminator(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h225_protocol_discriminator, 0, 255,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h225_user_information(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h225_user_information, 1, 131, NULL, NULL);
+ return offset;
+}
+
+static per_sequence_t user_data_sequence[] = {
+ { "protocol-discriminator", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_protocol_discriminator },
+ { "user-information", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_user_information },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h225_user_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h225_user_data, ett_h225_user_data, user_data_sequence);
+ return offset;
+}
+
+
+
+
+const value_string RasMessage_vals[] = {
+ { 0, "gatekeeperRequest" },
+ { 1, "gatekeeperConfirm" },
+ { 2, "gatekeeperReject" },
+ { 3, "registrationRequest" },
+ { 4, "registrationConfirm" },
+ { 5, "registrationReject" },
+ { 6, "unregistrationRequest" },
+ { 7, "unregistrationConfirm" },
+ { 8, "unregistrationReject" },
+ { 9, "admissionRequest" },
+ {10, "admissionConfirm" },
+ {11, "admissionReject" },
+ {12, "bandwidthRequest" },
+ {13, "bandwidthConfirm" },
+ {14, "bandwidthReject" },
+ {15, "disengageRequest" },
+ {16, "disengageConfirm" },
+ {17, "disengageReject" },
+ {18, "locationRequest" },
+ {19, "locationConfirm" },
+ {20, "locationReject" },
+ {21, "infoRequest" },
+ {22, "infoRequestResponse" },
+ {23, "nonStandardMessage" },
+ {24, "unknownMessageResponse" },
+ {25, "requestInProgress" },
+ {26, "resourcesAvailableIndicate" },
+ {27, "resourcesAvailableConfirm" },
+ {28, "infoRequestAck" },
+ {29, "infoRequestNak" },
+ {30, "serviceControlIndication" },
+ {31, "serviceControlResponse" },
+ {32, "admissionConfirmSequence" },
+ { 0, NULL}
+};
+static per_choice_t RasMessage_choice[] = {
+ { 0, "gatekeeperRequest", ASN1_EXTENSION_ROOT,
+ dissect_h225_GatekeeperRequest },
+ { 1, "gatekeeperConfirm", ASN1_EXTENSION_ROOT,
+ dissect_h225_GatekeeperConfirm },
+ { 2, "gatekeeperReject", ASN1_EXTENSION_ROOT,
+ dissect_h225_GatekeeperReject },
+ { 3, "registrationRequest", ASN1_EXTENSION_ROOT,
+ dissect_h225_RegistrationRequest },
+ { 4, "registrationConfirm", ASN1_EXTENSION_ROOT,
+ dissect_h225_RegistrationConfirm },
+ { 5, "registrationReject", ASN1_EXTENSION_ROOT,
+ dissect_h225_RegistrationReject },
+ { 6, "unregistrationRequest", ASN1_EXTENSION_ROOT,
+ dissect_h225_UnregistrationRequest },
+ { 7, "unregistrationConfirm", ASN1_EXTENSION_ROOT,
+ dissect_h225_UnregistrationConfirm },
+ { 8, "unregistrationReject", ASN1_EXTENSION_ROOT,
+ dissect_h225_UnregistrationReject },
+ { 9, "admissionRequest", ASN1_EXTENSION_ROOT,
+ dissect_h225_AdmissionRequest },
+ {10, "admissionConfirm", ASN1_EXTENSION_ROOT,
+ dissect_h225_AdmissionConfirm },
+ {11, "admissionReject", ASN1_EXTENSION_ROOT,
+ dissect_h225_AdmissionReject },
+ {12, "bandwidthRequest", ASN1_EXTENSION_ROOT,
+ dissect_h225_BandwidthRequest },
+ {13, "bandwidthConfirm", ASN1_EXTENSION_ROOT,
+ dissect_h225_BandwidthConfirm },
+ {14, "bandwidthReject", ASN1_EXTENSION_ROOT,
+ dissect_h225_BandwidthReject },
+ {15, "disengageRequest", ASN1_EXTENSION_ROOT,
+ dissect_h225_DisengageRequest },
+ {16, "disengageConfirm", ASN1_EXTENSION_ROOT,
+ dissect_h225_DisengageConfirm },
+ {17, "disengageReject", ASN1_EXTENSION_ROOT,
+ dissect_h225_DisengageReject },
+ {18, "locationRequest", ASN1_EXTENSION_ROOT,
+ dissect_h225_LocationRequest },
+ {19, "locationConfirm", ASN1_EXTENSION_ROOT,
+ dissect_h225_LocationConfirm },
+ {20, "locationReject", ASN1_EXTENSION_ROOT,
+ dissect_h225_LocationReject },
+ {21, "infoRequest", ASN1_EXTENSION_ROOT,
+ dissect_h225_InfoRequest },
+ {22, "infoRequestResponse", ASN1_EXTENSION_ROOT,
+ dissect_h225_InfoRequestResponse },
+ {23, "nonStandardMessage", ASN1_EXTENSION_ROOT,
+ dissect_h225_NonStandardMessage },
+ {24, "unknownMessageResponse", ASN1_EXTENSION_ROOT,
+ dissect_h225_UnknownMessageResponse },
+ {25, "requestInProgress", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_RequestInProgress },
+ {26, "resourcesAvailableIndicate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_ResourcesAvailableIndicate },
+ {27, "resourcesAvailableConfirm", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_ResourcesAvailableConfirm },
+ {28, "infoRequestAck", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_InfoRequestAck },
+ {29, "infoRequestNak", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_InfoRequestNak },
+ {30, "serviceControlIndication", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_ServiceControlIndication },
+ {31, "serviceControlResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_ServiceControlResponse },
+ {32, "admissionConfirmSequence", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h225_admissionConfirmSequence },
+ { 0, NULL, 0, NULL }
+};
+static void
+dissect_h225_RasMessage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *it;
+ proto_tree *tr;
+ guint32 offset=0;
+ guint32 value;
+
+ /* Init struct for collecting h225_packet_info */
+ reset_h225_packet_info(&(h225_pi));
+ h225_pi.msg_type = H225_RAS;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)){
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0");
+ }
+
+ it=proto_tree_add_protocol_format(tree, proto_h225, tvb, 0, tvb_length(tvb), "H.225.0 RAS");
+ tr=proto_item_add_subtree(it, ett_h225);
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tr, hf_h225_RasMessage, ett_h225_RasMessage, RasMessage_choice, "RasMessage", &value);
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_add_fstr(pinfo->cinfo, COL_INFO, "RAS: %s ",
+ val_to_str(value, RasMessage_vals, "<unknown>"));
+ }
+ h225_pi.msg_tag = value;
+
+ ras_call_matching(tvb, pinfo, tr, &(h225_pi));
+
+ tap_queue_packet(h225_tap, pinfo, &h225_pi);
+}
+
+
+
+
+
+
+static per_sequence_t H323_UserInformation_sequence[] = {
+ { "h323_uu_pdu", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h225_H323_UU_PDU },
+ { "user_data", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_user_data },
+ { NULL, 0, 0, NULL }
+};
+static void
+dissect_h225_H323UserInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *it;
+ proto_tree *tr;
+ guint32 offset=0;
+
+ /* Init struct for collecting h225_packet_info */
+ reset_h225_packet_info(&(h225_pi));
+ h225_pi.msg_type = H225_CS;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)){
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.225.0");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ it=proto_tree_add_protocol_format(tree, proto_h225, tvb, 0, tvb_length(tvb), "H.225.0 CS");
+ tr=proto_item_add_subtree(it, ett_h225);
+
+ offset=dissect_per_sequence(tvb, offset, pinfo, tr, hf_h225_H323_UserInformation, ett_h225_H323_UserInformation, H323_UserInformation_sequence);
+
+ tap_queue_packet(h225_tap, pinfo, &h225_pi);
+}
+
+
+
+void
+dissect_h225ras(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_tpkt_encap(tvb, pinfo, tree, h225_reassembly, h225ras_handle);
+}
+
+
+
+void
+proto_register_h225(void)
+{
+ static hf_register_info hf[] =
+ {
+ { &hf_h225_PresentationIndicator,
+ { "PresentationIndicator", "h225.PresentationIndicator", FT_UINT32, BASE_DEC,
+ VALS(PresentationIndicator_vals), 0, "PresentationIndicator choice", HFILL }},
+ { &hf_h225_CryptoH323Token,
+ { "CryptoH323Token", "h225.CryptoH323Token", FT_UINT32, BASE_DEC,
+ VALS(CryptoH323Token_vals), 0, "CryptoH323Token choice", HFILL }},
+ { &hf_h225_conferenceGoal,
+ { "conferenceGoal", "h225.conferenceGoal", FT_UINT32, BASE_DEC,
+ VALS(conferenceGoal_vals), 0, "conferenceGoal choice", HFILL }},
+ { &hf_h225_ScnConnectionType,
+ { "ScnConnectionType", "h225.ScnConnectionType", FT_UINT32, BASE_DEC,
+ VALS(ScnConnectionType_vals), 0, "ScnConnectionType choice", HFILL }},
+ { &hf_h225_ScnConnectionAggregation,
+ { "ScnConnectionAggregation", "h225.ScnConnectionAggregation", FT_UINT32, BASE_DEC,
+ VALS(ScnConnectionAggregation_vals), 0, "ScnConnectionAggregation choice", HFILL }},
+ { &hf_h225_FacilityReason,
+ { "FacilityReason", "h225.FacilityReason", FT_UINT32, BASE_DEC,
+ VALS(FacilityReason_vals), 0, "FacilityReason choice", HFILL }},
+ { &hf_h225_PublicTypeOfNumber,
+ { "PublicTypeOfNumber", "h225.PublicTypeOfNumber", FT_UINT32, BASE_DEC,
+ VALS(PublicTypeOfNumber_vals), 0, "PublicTypeOfNumber choice", HFILL }},
+ { &hf_h225_PrivateTypeOfNumber,
+ { "PrivateTypeOfNumber", "h225.PrivateTypeOfNumber", FT_UINT32, BASE_DEC,
+ VALS(PrivateTypeOfNumber_vals), 0, "PrivateTypeOfNumber choice", HFILL }},
+ { &hf_h225_UseSpecifiedTransport,
+ { "UseSpecifiedTransport", "h225.UseSpecifiedTransport", FT_UINT32, BASE_DEC,
+ VALS(UseSpecifiedTransport_vals), 0, "UseSpecifiedTransport choice", HFILL }},
+ { &hf_h225_SecurityErrors,
+ { "SecurityErrors", "h225.SecurityErrors", FT_UINT32, BASE_DEC,
+ VALS(SecurityErrors_vals), 0, "SecurityErrors choice", HFILL }},
+ { &hf_h225_SecurityErrors2,
+ { "SecurityErrors2", "h225.SecurityErrors2", FT_UINT32, BASE_DEC,
+ VALS(SecurityErrors2_vals), 0, "SecurityErrors2 choice", HFILL }},
+ { &hf_h225_ServiceControlSession_reason,
+ { "ServiceControlSession_reason", "h225.ServiceControlSession_reason", FT_UINT32, BASE_DEC,
+ VALS(ServiceControlSession_reason_vals), 0, "ServiceControlSession_reason choice", HFILL }},
+ { &hf_h225_billingMode,
+ { "billingMode", "h225.billingMode", FT_UINT32, BASE_DEC,
+ VALS(billingMode_vals), 0, "billingMode choice", HFILL }},
+ { &hf_h225_CCSCcallStartingPoint,
+ { "CCSCcallStartingPoint", "h225.CCSCcallStartingPoint", FT_UINT32, BASE_DEC,
+ VALS(CCSCcallStartingPoint_vals), 0, "CCSCcallStartingPoint choice", HFILL }},
+ { &hf_h225_GatekeeperRejectReason,
+ { "GatekeeperRejectReason", "h225.GatekeeperRejectReason", FT_UINT32, BASE_DEC,
+ VALS(GatekeeperRejectReason_vals), 0, "GatekeeperRejectReason choice", HFILL }},
+ { &hf_h225_UnregRequestReason,
+ { "UnregRequestReason", "h225.UnregRequestReason", FT_UINT32, BASE_DEC,
+ VALS(UnregRequestReason_vals), 0, "UnregRequestReason choice", HFILL }},
+ { &hf_h225_UnregRejectReason,
+ { "UnregRejectReason", "h225.UnregRejectReason", FT_UINT32, BASE_DEC,
+ VALS(UnregRejectReason_vals), 0, "UnregRejectReason choice", HFILL }},
+ { &hf_h225_CallType,
+ { "CallType", "h225.CallType", FT_UINT32, BASE_DEC,
+ VALS(CallType_vals), 0, "CallType choice", HFILL }},
+ { &hf_h225_CallModel,
+ { "CallModel", "h225.CallModel", FT_UINT32, BASE_DEC,
+ VALS(CallModel_vals), 0, "CallModel choice", HFILL }},
+ { &hf_h225_TransportQOS,
+ { "TransportQOS", "h225.TransportQOS", FT_UINT32, BASE_DEC,
+ VALS(TransportQOS_vals), 0, "TransportQOS choice", HFILL }},
+ { &hf_h225_BandRejectReason,
+ { "BandRejectReason", "h225.BandRejectReason", FT_UINT32, BASE_DEC,
+ VALS(BandRejectReason_vals), 0, "BandRejectReason choice", HFILL }},
+ { &hf_h225_DisengageReason,
+ { "DisengageReason", "h225.DisengageReason", FT_UINT32, BASE_DEC,
+ VALS(DisengageReason_vals), 0, "DisengageReason choice", HFILL }},
+ { &hf_h225_DisengageRejectReason,
+ { "DisengageRejectReason", "h225.DisengageRejectReason", FT_UINT32, BASE_DEC,
+ VALS(DisengageRejectReason_vals), 0, "DisengageRejectReason choice", HFILL }},
+ { &hf_h225_InfoRequestNakReason,
+ { "InfoRequestNakReason", "h225.InfoRequestNakReason", FT_UINT32, BASE_DEC,
+ VALS(InfoRequestNakReason_vals), 0, "InfoRequestNakReason choice", HFILL }},
+ { &hf_h225_SCRresult,
+ { "SCRresult", "h225.SCRresult", FT_UINT32, BASE_DEC,
+ VALS(SCRresult_vals), 0, "SCRresult choice", HFILL }},
+ { &hf_h225_GatekeeperInfo,
+ { "GatekeeperInfo", "h225.GatekeeperInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "GatekeeperInfo sequence", HFILL }},
+ { &hf_h225_SecurityServiceMode_encryption,
+ { "Encryption", "h225.SecurityServiceMode_encryption", FT_UINT32, BASE_DEC,
+ VALS(SecurityServiceMode_vals), 0, "Encryption SecurityServiceMode choice", HFILL }},
+ { &hf_h225_SecurityServiceMode_authentication,
+ { "Authentication", "h225.SecurityServiceMode_authentication", FT_UINT32, BASE_DEC,
+ VALS(SecurityServiceMode_vals), 0, "Authentication SecurityServiceMode choice", HFILL }},
+ { &hf_h225_SecurityServiceMode_integrity,
+ { "Integrity", "h225.SecurityServiceMode_integrity", FT_UINT32, BASE_DEC,
+ VALS(SecurityServiceMode_vals), 0, "Integrity SecurityServiceMode choice", HFILL }},
+ { &hf_h225_SecurityCapabilities_tls,
+ { "TLS", "h225.SecurityCapabilities.tls", FT_NONE, BASE_NONE,
+ NULL, 0, "TLS SecurityCapabilities sequence", HFILL }},
+ { &hf_h225_SecurityCapabilities_ipsec,
+ { "IPSec", "h225.SecurityCapabilities.ipsec", FT_NONE, BASE_NONE,
+ NULL, 0, "IPSec SecurityCapabilities sequence", HFILL }},
+ { &hf_h225_H245Security,
+ { "H245Security", "h225.H245Security", FT_UINT32, BASE_DEC,
+ VALS(H245Security_vals), 0, "H245Security choice", HFILL }},
+ { &hf_h225_nonStandardUsageTypes,
+ { "nonStandardUsageTypes", "h225.nonStandardUsageTypes", FT_NONE, BASE_NONE,
+ NULL, 0, "SEQUENCE OF NonStandardParameter", HFILL }},
+ { &hf_h225_nonStandardUsageTypes_item,
+ { "nonStandardUsageTypes", "h225.nonStandardUsageTypes_item", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardParameter", HFILL }},
+ { &hf_h225_route,
+ { "route", "h225.route", FT_NONE, BASE_NONE,
+ NULL, 0, "Source Routing route", HFILL }},
+ { &hf_h225_RasUsageInfoTypes,
+ { "RasUsageInfoTypes", "h225.RasUsageInfoTypes", FT_NONE, BASE_NONE,
+ NULL, 0, "RasUsageInfoTypes sequence", HFILL }},
+ { &hf_h225_usageReportingCapability,
+ { "usageReportingCapability", "h225.usageReportingCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "usageReportingCapability sequence", HFILL }},
+ { &hf_h225_BandWidth,
+ { "BandWidth", "h225.BandWidth", FT_UINT32, BASE_DEC,
+ NULL, 0, "BandWidth in units of 100bits", HFILL }},
+ { &hf_h225_channelRate,
+ { "channelRate", "h225.channelRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "channelRate in units of 100bits", HFILL }},
+ { &hf_h225_totalBandwidthRestriction,
+ { "totalBandwidthRestriction", "h225.totalBandwidthRestriction", FT_UINT32, BASE_DEC,
+ NULL, 0, "totalBandwidthRestriction in units of 100bits", HFILL }},
+ { &hf_h225_allowedBandWidth,
+ { "allowedBandWidth", "h225.allowedBandWidth", FT_UINT32, BASE_DEC,
+ NULL, 0, "allowedBandWidth in units of 100bits", HFILL }},
+ { &hf_h225_channelMultiplier,
+ { "channelMultiplier", "h225.channelMultiplier", FT_UINT32, BASE_DEC,
+ NULL, 0, "channelMultiplier", HFILL }},
+ { &hf_h225_DataRate,
+ { "DataRate", "h225.DataRate", FT_NONE, BASE_NONE,
+ NULL, 0, "DataRate sequence", HFILL }},
+ { &hf_h225_gatewayDataRate,
+ { "gatewayDataRate", "h225.gatewayDataRate", FT_NONE, BASE_NONE,
+ NULL, 0, "gatewayDataRate sequence", HFILL }},
+ { &hf_h225_dataRatesSupported,
+ { "dataRatesSupported", "h225.dataRatesSupported", FT_NONE, BASE_NONE,
+ NULL, 0, "dataRatesSupported sequence of", HFILL }},
+ { &hf_h225_TerminalInfo,
+ { "TerminalInfo", "h225.TerminalInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "TerminalInfo sequence", HFILL }},
+ { &hf_h225_cname,
+ { "cname", "h225.cname", FT_STRING, BASE_NONE,
+ NULL, 0, "cname", HFILL }},
+ { &hf_h225_h248Message,
+ { "h248Message", "h225.h248Message", FT_STRING, BASE_NONE,
+ NULL, 0, "h248Message", HFILL }},
+ { &hf_h225_conferenceID,
+ { "conferenceID", "h225.conferenceID", FT_BYTES, BASE_HEX,
+ NULL, 0, "conferenceID", HFILL }},
+ { &hf_h225_Generic_nonStandard,
+ { "nonStandard", "h225.Generic_nonStandard", FT_BYTES, BASE_HEX,
+ NULL, 0, "Generic_nonStandard", HFILL }},
+ { &hf_h225_guid,
+ { "guid", "h225.guid", FT_BYTES, BASE_HEX,
+ NULL, 0, "guid", HFILL }},
+ { &hf_h225_replaceWithConferenceInvite,
+ { "replaceWithConferenceInvite", "h225.replaceWithConferenceInvite", FT_BYTES, BASE_HEX,
+ NULL, 0, "replaceWithConferenceInvite", HFILL }},
+ { &hf_h225_StimulusControl,
+ { "StimulusControl", "h225.StimulusControl", FT_NONE, BASE_NONE,
+ NULL, 0, "StimulusControl sequence", HFILL }},
+ { &hf_h225_ReleaseCompleteReason,
+ { "ReleaseCompleteReason", "h225.ReleaseCompleteReason", FT_UINT32, BASE_DEC,
+ VALS(ReleaseCompleteReason_vals), 0, "ReleaseCompleteReason choice", HFILL }},
+ { &hf_h225_numberOfScnConnections,
+ { "numberOfScnConnections", "h225.numberOfScnConnections", FT_UINT32, BASE_DEC,
+ NULL, 0, "numberOfScnConnections", HFILL }},
+ { &hf_h225_connectionParameters,
+ { "connectionParameters", "h225.connectionParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "connectionParameters sequence", HFILL }},
+ { &hf_h225_RequestSeqNum,
+ { "RequestSeqNum", "h225.RequestSeqNum", FT_UINT32, BASE_DEC,
+ NULL, 0, "RequestSeqNum", HFILL }},
+ { &hf_h225_RasUsageSpecification_when,
+ { "RasUsageSpecification_when", "h225.RasUsageSpecification_when", FT_NONE, BASE_NONE,
+ NULL, 0, "RasUsageSpecification_when sequence", HFILL }},
+ { &hf_h225_RasUsageSpecification_callStartingPoint,
+ { "RasUsageSpecification_callStartingPoint", "h225.RasUsageSpecification_callStartingPoint", FT_NONE, BASE_NONE,
+ NULL, 0, "RasUsageSpecification_callStartingPoint sequence", HFILL }},
+ { &hf_h225_RasUsageSpecification,
+ { "RasUsageSpecification", "h225.RasUsageSpecification", FT_NONE, BASE_NONE,
+ NULL, 0, "RasUsageSpecification sequence", HFILL }},
+ { &hf_h225_ipAddress_ip,
+ { "IP", "h245.ipAddress.ip", FT_IPv4, BASE_NONE,
+ NULL, 0, "IPv4 Address", HFILL }},
+ { &hf_h225_ipAddress_port,
+ { "Port", "h225.ipAddress.port", FT_UINT16, BASE_DEC,
+ NULL, 0, "Port number", HFILL }},
+ { &hf_h225_ipAddress,
+ { "ipAddress", "h225.ipAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "ipAddress sequence", HFILL }},
+ { &hf_h225_routing,
+ { "routing", "h225.routing", FT_UINT32, BASE_DEC,
+ VALS(routing_vals), 0, "routing choice", HFILL }},
+ { &hf_h225_ipSourceRoute,
+ { "ipSourceRoute", "h225.ipSourceRoute", FT_NONE, BASE_NONE,
+ NULL, 0, "ipSourceRoute sequence", HFILL }},
+ { &hf_h225_ipxNode,
+ { "Node", "h225.ipx.node", FT_BYTES, BASE_HEX,
+ NULL, 0, "ipx node", HFILL }},
+ { &hf_h225_ipxNetnum,
+ { "Netnum", "h225.ipx.netnum", FT_BYTES, BASE_HEX,
+ NULL, 0, "ipx netnum", HFILL }},
+ { &hf_h225_ipxPort,
+ { "Port", "h225.ipx.port", FT_BYTES, BASE_HEX,
+ NULL, 0, "ipx port number", HFILL }},
+ { &hf_h225_ipxAddress,
+ { "ipxAddress", "h225.ipxAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "ipxAddress sequence", HFILL }},
+ { &hf_h225_ipv6Address_ip,
+ { "IP", "h225.ipv6Address.ip", FT_BYTES, BASE_HEX,
+ NULL, 0, "ipv6 address", HFILL }},
+ { &hf_h225_ipv6Address_port,
+ { "Port", "h225.ipv6Address.port", FT_UINT16, BASE_DEC,
+ NULL, 0, "Port number", HFILL }},
+ { &hf_h225_ip6Address,
+ { "ip6Address", "h225.ip6Address", FT_NONE, BASE_NONE,
+ NULL, 0, "ip6Address sequence", HFILL }},
+ { &hf_h225_netBios,
+ { "netBios", "h225.netBios", FT_BYTES, BASE_HEX,
+ NULL, 0, "netBios octet string", HFILL }},
+ { &hf_h225_nsap,
+ { "nsap", "h225.nsap", FT_BYTES, BASE_HEX,
+ NULL, 0, "nsap octet string", HFILL }},
+ { &hf_h225_rasAddress,
+ { "rasAddress", "h225.rasAddress", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "rasAddress choice", HFILL }},
+ { &hf_h225_TransportAddress,
+ { "TransportAddress", "h225.TransportAddress", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "TransportAddress choice", HFILL }},
+ { &hf_h225_replyAddress,
+ { "replyAddress", "h225.replyAddress", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "replyAddress choice", HFILL }},
+ { &hf_h225_h245Address,
+ { "h245Address", "h225.h245Address", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "h245Address choice", HFILL }},
+ { &hf_h225_destCallSignalAddress,
+ { "destCallSignalAddress", "h225.destCallSignalAddress", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "destCallSignalAddress choice", HFILL }},
+ { &hf_h225_sourceCallSignalAddress,
+ { "sourceCallSignalAddress", "h225.sourceCallSignalAddress", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "sourceCallSignalAddress choice", HFILL }},
+ { &hf_h225_CallSignalAddress2,
+ { "CallSignalAddress2", "h225.CallSignalAddress2", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "CallSignalAddress2 choice", HFILL }},
+ { &hf_h225_alternativeAddress,
+ { "alternativeAddress", "h225.alternativeAddress", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "alternativeAddress choice", HFILL }},
+ { &hf_h225_transportID,
+ { "transportID", "h225.transportID", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "transportID choice", HFILL }},
+ { &hf_h225_sendAddress,
+ { "sendAddress", "h225.sendAddress", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "sendAddress choice", HFILL }},
+ { &hf_h225_recvAddress,
+ { "recvAddress", "h225.recvAddress", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "recvAddress choice", HFILL }},
+ { &hf_h225_rtpAddress,
+ { "rtpAddress", "h225.rtpAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "rtpAddress sequence", HFILL }},
+ { &hf_h225_rtcpAddress,
+ { "rtcpAddress", "h225.rtcpAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "rtcpAddress sequence", HFILL }},
+ { &hf_h225_h245,
+ { "h245", "h225.h245", FT_NONE, BASE_NONE,
+ NULL, 0, "h245 sequence", HFILL }},
+ { &hf_h225_callSignaling,
+ { "callSignaling", "h225.callSignaling", FT_NONE, BASE_NONE,
+ NULL, 0, "callSignaling sequence", HFILL }},
+ { &hf_h225_carrierName,
+ { "carrierName", "h225.carrierName", FT_BYTES, BASE_HEX,
+ NULL, 0, "carrierName IA5String", HFILL }},
+ { &hf_h225_carrierIdentificationCode,
+ { "carrierIdentificationCode", "h225.carrierIdentificationCode", FT_BYTES, BASE_HEX,
+ NULL, 0, "carrierIdentificationCode octet string", HFILL }},
+ { &hf_h225_CarrierInfo,
+ { "CarrierInfo", "h225.CarrierInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "CarrierInfo sequence", HFILL }},
+ { &hf_h225_segment,
+ { "segment", "h225.segment", FT_UINT32, BASE_DEC,
+ NULL, 0, "segment", HFILL }},
+ { &hf_h225_InfoRequestResponseStatus,
+ { "InfoRequestResponseStatus", "h225.InfoRequestResponseStatus", FT_UINT32, BASE_DEC,
+ VALS(InfoRequestResponseStatus_vals), 0, "InfoRequestResponseStatus choice", HFILL }},
+ { &hf_h225_CallIdentifier,
+ { "CallIdentifier", "h225.CallIdentifier", FT_NONE, BASE_NONE,
+ NULL, 0, "CallIdentifier sequence", HFILL }},
+ { &hf_h225_globalCallId,
+ { "globalCallId", "h225.globalCallId", FT_BYTES, BASE_HEX,
+ NULL, 0, "globalCallId octet string", HFILL }},
+ { &hf_h225_threadId,
+ { "threadId", "h225.threadId", FT_BYTES, BASE_HEX,
+ NULL, 0, "threadId octet string", HFILL }},
+ { &hf_h225_CallLinkage,
+ { "CallLinkage", "h225.CallLinkage", FT_NONE, BASE_NONE,
+ NULL, 0, "CallLinkage sequence", HFILL }},
+ { &hf_h225_tokens,
+ { "tokens", "h225.tokens", FT_NONE, BASE_NONE,
+ NULL, 0, "tokens sequence of", HFILL }},
+ { &hf_h225_CryptoH323Tokens,
+ { "CryptoH323Tokens", "h225.cryptoh323tokens", FT_NONE, BASE_NONE,
+ NULL, 0, "sequence of cryptoh323tokens", HFILL }},
+ { &hf_h225_needToRegister,
+ { "needToRegister", "h225.needToRegister", FT_BOOLEAN, 8,
+ TFS(&tfs_needToRegister_bit), 0x01, "needToRegister boolean", HFILL }},
+ { &hf_h225_priority,
+ { "priority", "h225.priority", FT_UINT32, BASE_DEC,
+ NULL, 0, "priority", HFILL }},
+ { &hf_h225_AlternateGK,
+ { "AlternateGK", "h225.AlternateGK", FT_NONE, BASE_NONE,
+ NULL, 0, "AlternateGK sequence", HFILL }},
+ { &hf_h225_alternateGatekeeper,
+ { "alternateGatekeeper", "h225.alternateGatekeeper", FT_NONE, BASE_NONE,
+ NULL, 0, "alternateGatekeeper sequence of", HFILL }},
+ { &hf_h225_altGKisPermanent,
+ { "altGKisPermanent", "h225.altGKisPermanent", FT_BOOLEAN, 8,
+ TFS(&tfs_altGKisPermanent_bit), 0x01, "altGKisPermanent boolean", HFILL }},
+ { &hf_h225_AltGKInfo,
+ { "AltGKInfo", "h225.AltGKInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "AltGKInfo sequence", HFILL }},
+ { &hf_h225_annexE,
+ { "annexE", "h225.annexE", FT_NONE, BASE_NONE,
+ NULL, 0, "annexE sequence of", HFILL }},
+ { &hf_h225_sctp,
+ { "sctp", "h225.sctp", FT_NONE, BASE_NONE,
+ NULL, 0, "sctp sequence of", HFILL }},
+ { &hf_h225_AlternateTransportAddress,
+ { "AlternateTransportAddress", "h225.AlternateTransportAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "AlternateTransportAddress sequence", HFILL }},
+ { &hf_h225_setup_bool,
+ { "setup_bool", "h225.setup_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_setup_bool_bit), 0x01, "setup_bool boolean", HFILL }},
+ { &hf_h225_callProceeding_bool,
+ { "callProceeding_bool", "h225.callProceeding_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_callProceeding_bool_bit), 0x01, "callProceeding_bool boolean", HFILL }},
+ { &hf_h225_connect_bool,
+ { "connect_bool", "h225.connect_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_connect_bool_bit), 0x01, "connect_bool boolean", HFILL }},
+ { &hf_h225_alerting_bool,
+ { "alerting_bool", "h225.alerting_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_alerting_bool_bit), 0x01, "alerting_bool boolean", HFILL }},
+ { &hf_h225_information_bool,
+ { "information_bool", "h225.information_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_information_bool_bit), 0x01, "information_bool boolean", HFILL }},
+ { &hf_h225_releaseComplete_bool,
+ { "releaseComplete_bool", "h225.releaseComplete_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_releaseComplete_bool_bit), 0x01, "releaseComplete_bool boolean", HFILL }},
+ { &hf_h225_facility_bool,
+ { "facility_bool", "h225.facility_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_facility_bool_bit), 0x01, "facility_bool boolean", HFILL }},
+ { &hf_h225_progress_bool,
+ { "progress_bool", "h225.progress_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_progress_bool_bit), 0x01, "progress_bool boolean", HFILL }},
+ { &hf_h225_empty_bool,
+ { "empty_bool", "h225.empty_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_empty_bool_bit), 0x01, "empty_bool boolean", HFILL }},
+ { &hf_h225_status_bool,
+ { "status_bool", "h225.status_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_status_bool_bit), 0x01, "status_bool boolean", HFILL }},
+ { &hf_h225_statusInquiry_bool,
+ { "statusInquiry_bool", "h225.statusInquiry_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_statusInquiry_bool_bit), 0x01, "statusInquiry_bool boolean", HFILL }},
+ { &hf_h225_setupAcknowledge_bool,
+ { "setupAcknowledge_bool", "h225.setupAcknowledge_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_setupAcknowledge_bool_bit), 0x01, "setupAcknowledge_bool boolean", HFILL }},
+ { &hf_h225_notify_bool,
+ { "notify_bool", "h225.notify_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_notify_bool_bit), 0x01, "notify_bool boolean", HFILL }},
+ { &hf_h225_UUIEsRequested,
+ { "UUIEsRequested", "h225.UUIEsRequested", FT_NONE, BASE_NONE,
+ NULL, 0, "UUIEsRequested sequence", HFILL }},
+ { &hf_h225_conferenceCalling,
+ { "conferenceCalling", "h225.conferenceCalling", FT_BOOLEAN, 8,
+ TFS(&tfs_conferenceCalling_bit), 0x01, "conferenceCalling boolean", HFILL }},
+ { &hf_h225_threePartyService,
+ { "threePartyService", "h225.threePartyService", FT_BOOLEAN, 8,
+ TFS(&tfs_threePartyService_bit), 0x01, "threePartyService boolean", HFILL }},
+ { &hf_h225_Q954Details,
+ { "Q954Details", "h225.Q954Details", FT_NONE, BASE_NONE,
+ NULL, 0, "Q954Details sequence", HFILL }},
+ { &hf_h225_q932Full,
+ { "q932Full", "h225.q932Full", FT_BOOLEAN, 8,
+ TFS(&tfs_q932Full_bit), 0x01, "q932Full boolean", HFILL }},
+ { &hf_h225_q951Full,
+ { "q951Full", "h225.q951Full", FT_BOOLEAN, 8,
+ TFS(&tfs_q951Full_bit), 0x01, "q951Full boolean", HFILL }},
+ { &hf_h225_q952Full,
+ { "q952Full", "h225.q952Full", FT_BOOLEAN, 8,
+ TFS(&tfs_q952Full_bit), 0x01, "q952Full boolean", HFILL }},
+ { &hf_h225_q953Full,
+ { "q953Full", "h225.q953Full", FT_BOOLEAN, 8,
+ TFS(&tfs_q953Full_bit), 0x01, "q953Full boolean", HFILL }},
+ { &hf_h225_q955Full,
+ { "q955Full", "h225.q955Full", FT_BOOLEAN, 8,
+ TFS(&tfs_q955Full_bit), 0x01, "q955Full boolean", HFILL }},
+ { &hf_h225_q956Full,
+ { "q956Full", "h225.q956Full", FT_BOOLEAN, 8,
+ TFS(&tfs_q956Full_bit), 0x01, "q956Full boolean", HFILL }},
+ { &hf_h225_q957Full,
+ { "q957Full", "h225.q957Full", FT_BOOLEAN, 8,
+ TFS(&tfs_q957Full_bit), 0x01, "q957Full boolean", HFILL }},
+ { &hf_h225_QseriesOptions,
+ { "callServices", "h225.callServices", FT_NONE, BASE_NONE,
+ NULL, 0, "QseriesOptions sequence", HFILL }},
+ { &hf_h225_ssrc,
+ { "ssrc", "h225.ssrc", FT_UINT32, BASE_DEC,
+ NULL, 0, "ssrc", HFILL }},
+ { &hf_h225_RTPsessionId,
+ { "RTPsessionId", "h225.RTPsessionId", FT_UINT32, BASE_DEC,
+ NULL, 0, "RTPsessionId", HFILL }},
+ { &hf_h225_associatedSessionIds,
+ { "associatedSessionIds", "h225.associatedSessionIds", FT_NONE, BASE_NONE,
+ NULL, 0, "associatedSessionIds sequence of", HFILL }},
+ { &hf_h225_RTPSession,
+ { "RTPSession", "h225.RTPSession", FT_NONE, BASE_NONE,
+ NULL, 0, "RTPSession sequence", HFILL }},
+ { &hf_h225_tunnelledProtocolObjectID,
+ { "tunnelledProtocolObjectID", "h225.tunnelledProtocolObjectID", FT_STRING, BASE_NONE,
+ NULL, 0, "tunnelledProtocolObjectID object", HFILL }},
+ { &hf_h225_ProtocolIdentifier,
+ { "ProtocolIdentifier", "h225.ProtocolIdentifier", FT_STRING, BASE_NONE,
+ NULL, 0, "ProtocolIdentifier object", HFILL }},
+ { &hf_h225_isoAlgorithm,
+ { "isoAlgorithm", "h225.isoAlgorithm", FT_STRING, BASE_NONE,
+ NULL, 0, "isoAlgorithm object", HFILL }},
+ { &hf_h225_algorithmOID,
+ { "algorithmOID", "h225.algorithmOID", FT_STRING, BASE_NONE,
+ NULL, 0, "algorithmOID object", HFILL }},
+ { &hf_h225_iso9797,
+ { "iso9797", "h225.iso9797", FT_STRING, BASE_NONE,
+ NULL, 0, "iso9797 object", HFILL }},
+ { &hf_h225_hMAC_iso10118_3,
+ { "hMAC_iso10118_3", "h225.hMAC_iso10118_3", FT_STRING, BASE_NONE,
+ NULL, 0, "hMAC_iso10118_3 object", HFILL }},
+ { &hf_h225_enterpriseNumber,
+ { "enterpriseNumber", "h225.enterpriseNumber", FT_STRING, BASE_NONE,
+ NULL, 0, "enterpriseNumber object", HFILL }},
+ { &hf_h225_Generic_oid,
+ { "OID", "h225.Generic_oid", FT_STRING, BASE_NONE,
+ NULL, 0, "Generic OID object", HFILL }},
+ { &hf_h225_StatusUUIE,
+ { "StatusUUIE", "h225.StatusUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "StatusUUIE sequence", HFILL }},
+ { &hf_h225_StatusInquiryUUIE,
+ { "StatusInquiryUUIE", "h225.StatusInquiryUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "StatusInquiryUUIE sequence", HFILL }},
+ { &hf_h225_SetupAcknowledgeUUIE,
+ { "SetupAcknowledgeUUIE", "h225.SetupAcknowledgeUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "SetupAcknowledgeUUIE sequence", HFILL }},
+ { &hf_h225_NotifyUUIE,
+ { "NotifyUUIE", "h225.NotifyUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "NotifyUUIE sequence", HFILL }},
+ { &hf_h225_imsi,
+ { "imsi", "h225.imsi", FT_STRING, BASE_HEX,
+ NULL, 0, "imsi string", HFILL }},
+ { &hf_h225_tmsi,
+ { "tmsi", "h225.tmsi", FT_BYTES, BASE_HEX,
+ NULL, 0, "tmsi octet string", HFILL }},
+ { &hf_h225_msisdn,
+ { "msisdn", "h225.msisdn", FT_STRING, BASE_HEX,
+ NULL, 0, "msisdn string", HFILL }},
+ { &hf_h225_imei,
+ { "imei", "h225.imei", FT_STRING, BASE_HEX,
+ NULL, 0, "imei string", HFILL }},
+ { &hf_h225_hplmn,
+ { "hplmn", "h225.hplmn", FT_STRING, BASE_HEX,
+ NULL, 0, "hplmn string", HFILL }},
+ { &hf_h225_vplmn,
+ { "vplmn", "h225.vplmn", FT_STRING, BASE_HEX,
+ NULL, 0, "vplmn string", HFILL }},
+ { &hf_h225_GSMUIM,
+ { "GSMUIM", "h225.GSMUIM", FT_NONE, BASE_NONE,
+ NULL, 0, "GSMUIM sequence", HFILL }},
+ { &hf_h225_sid,
+ { "sid", "h225.sid", FT_STRING, BASE_HEX,
+ NULL, 0, "sid string", HFILL }},
+ { &hf_h225_mid,
+ { "mid", "h225.mid", FT_STRING, BASE_HEX,
+ NULL, 0, "mid string", HFILL }},
+ { &hf_h225_systemid,
+ { "systemid", "h225.sustemid", FT_UINT32, BASE_DEC,
+ VALS(systemid_vals), 0, "systemid choice", HFILL }},
+ { &hf_h225_min,
+ { "min", "h225.min", FT_STRING, BASE_HEX,
+ NULL, 0, "min string", HFILL }},
+ { &hf_h225_mdn,
+ { "mdn", "h225.mdn", FT_STRING, BASE_HEX,
+ NULL, 0, "mdn string", HFILL }},
+ { &hf_h225_esn,
+ { "esn", "h225.esn", FT_STRING, BASE_HEX,
+ NULL, 0, "esn string", HFILL }},
+ { &hf_h225_mscid,
+ { "mscid", "h225.mscid", FT_STRING, BASE_HEX,
+ NULL, 0, "mscid string", HFILL }},
+ { &hf_h225_systemMyTypeCode,
+ { "systemMyTypeCode", "h225.systemMyTypeCode", FT_BYTES, BASE_HEX,
+ NULL, 0, "systemMyTypeCode octet string", HFILL }},
+ { &hf_h225_systemAccessType,
+ { "systemAccessType", "h225.systemAccessType", FT_BYTES, BASE_HEX,
+ NULL, 0, "systemAccessType octet string", HFILL }},
+ { &hf_h225_qualificationInformationCode,
+ { "qualificationInformationCode", "h225.qualificationInformationCode", FT_BYTES, BASE_HEX,
+ NULL, 0, "qualificationInformationCode octet string", HFILL }},
+ { &hf_h225_sesn,
+ { "sesn", "h225.sesn", FT_STRING, BASE_HEX,
+ NULL, 0, "sesn string", HFILL }},
+ { &hf_h225_soc,
+ { "soc", "h225.soc", FT_STRING, BASE_HEX,
+ NULL, 0, "soc string", HFILL }},
+ { &hf_h225_ANSI41UIM,
+ { "ANSI41UIM", "h225.ANSI41UIM", FT_NONE, BASE_NONE,
+ NULL, 0, "ANSI41UIM sequence", HFILL }},
+ { &hf_h225_MobileUIM,
+ { "MobileUIM", "h225.MobileUIM", FT_UINT32, BASE_DEC,
+ VALS(MobileUIM_vals), 0, "MobileUIM choice", HFILL }},
+ { &hf_h225_dataPartyNumber,
+ { "dataPartyNumber", "h225.dataPartyNumber", FT_STRING, BASE_HEX,
+ NULL, 0, "dataPartyNumber string", HFILL }},
+ { &hf_h225_telexPartyNumber,
+ { "telexPartyNumber", "h225.telexPartyNumber", FT_STRING, BASE_HEX,
+ NULL, 0, "telexPartyNumber string", HFILL }},
+ { &hf_h225_nationalStandardPartyNumber,
+ { "nationalStandardPartyNumber", "h225.nationalStandardPartyNumber", FT_STRING, BASE_HEX,
+ NULL, 0, "nationalStandardPartyNumber string", HFILL }},
+ { &hf_h225_publicNumberDigits,
+ { "publicNumberDigits", "h225.publicNumberDigits", FT_STRING, BASE_HEX,
+ NULL, 0, "publicNumberDigits string", HFILL }},
+ { &hf_h225_privateNumberDigits,
+ { "privateNumberDigits", "h225.privateNumberDigits", FT_STRING, BASE_HEX,
+ NULL, 0, "privateNumberDigits string", HFILL }},
+ { &hf_h225_e164Number,
+ { "e164Number", "h225.e164Number", FT_NONE, BASE_NONE,
+ NULL, 0, "e164Number sequence", HFILL }},
+ { &hf_h225_privateNumber,
+ { "privateNumber", "h225.privateNumber", FT_NONE, BASE_NONE,
+ NULL, 0, "privateNumber sequence", HFILL }},
+ { &hf_h225_startOfRange,
+ { "startOfRange", "h225.startOfRange", FT_UINT32, BASE_DEC,
+ VALS(PartyNumber_vals), 0, "startOfRange choice", HFILL }},
+ { &hf_h225_endOfRange,
+ { "endOfRange", "h225.endOfRange", FT_UINT32, BASE_DEC,
+ VALS(PartyNumber_vals), 0, "endOfRange choice", HFILL }},
+ { &hf_h225_PartyNumber,
+ { "PartyNumber", "h225.PartyNumber", FT_UINT32, BASE_DEC,
+ VALS(PartyNumber_vals), 0, "PartyNumber choice", HFILL }},
+ { &hf_h225_protocolType,
+ { "protocolType", "h225.protocolType", FT_STRING, BASE_HEX,
+ NULL, 0, "protocolType IA5String", HFILL }},
+ { &hf_h225_protocolVariant,
+ { "protocolVariant", "h225.protocolVariant", FT_STRING, BASE_HEX,
+ NULL, 0, "protocolVariant IA5String", HFILL }},
+ { &hf_h225_TunnelledProtocolAlternateIdentifier,
+ { "TunnelledProtocolAlternateIdentifier", "h225.TunnelledProtocolAlternateIdentifier", FT_NONE, BASE_NONE,
+ NULL, 0, "TunnelledProtocolAlternateIdentifier sequence", HFILL }},
+ { &hf_h225_dialedDigits,
+ { "dialedDigits", "h225.dialedDigits", FT_BYTES, BASE_HEX,
+ NULL, 0, "dialedDigits IA5String", HFILL }},
+ { &hf_h225_urlId,
+ { "urlId", "h225.urlId", FT_BYTES, BASE_HEX,
+ NULL, 0, "urlId IA5String", HFILL }},
+ { &hf_h225_h323ID,
+ { "h323ID", "h225.h323ID", FT_STRING, BASE_HEX,
+ NULL, 0, "h323ID BMPString", HFILL }},
+ { &hf_h225_GatekeeperIdentifier,
+ { "GatekeeperIdentifier", "h225.GatekeeperIdentifier", FT_STRING, BASE_HEX,
+ NULL, 0, "GatekeeperIdentifier BMPString", HFILL }},
+ { &hf_h225_unicode,
+ { "unicode", "h225.unicode", FT_STRING, BASE_HEX,
+ NULL, 0, "unicode BMPString", HFILL }},
+ { &hf_h225_EndpointIdentifier,
+ { "EndpointIdentifier", "h225.EndpointIdentifier", FT_STRING, BASE_HEX,
+ NULL, 0, "EndpointIdentifier BMPString", HFILL }},
+ { &hf_h225_emailId,
+ { "emailId", "h225.emailId", FT_STRING, BASE_NONE,
+ NULL, 0, "emailId IA5String", HFILL }},
+ { &hf_h225_conferenceAlias,
+ { "conferenceAlias", "h225.conferenceAlias", FT_UINT32, BASE_DEC,
+ VALS(AliasAddress_vals), 0, "conferenceAlias choice", HFILL }},
+ { &hf_h225_AliasAddress,
+ { "AliasAddress", "h225.AliasAddress", FT_UINT32, BASE_DEC,
+ VALS(AliasAddress_vals), 0, "AliasAddress choice", HFILL }},
+ { &hf_h225_RemoteExtensionAddress,
+ { "RemoteExtensionAddress", "h225.RemoteExtensionAddress", FT_UINT32, BASE_DEC,
+ VALS(AliasAddress_vals), 0, "RemoteExtensionAddress choice", HFILL }},
+ { &hf_h225_wildcard,
+ { "wildcard", "h225.wildcard", FT_UINT32, BASE_DEC,
+ VALS(AliasAddress_vals), 0, "wildcard choice", HFILL }},
+ { &hf_h225_prefix,
+ { "prefix", "h225.prefix", FT_UINT32, BASE_DEC,
+ VALS(AliasAddress_vals), 0, "prefix choice", HFILL }},
+ { &hf_h225_SupportedPrefix,
+ { "SupportedPrefix", "h225.SupportedPrefix", FT_NONE, BASE_NONE,
+ NULL, 0, "SupportedPrefix sequence", HFILL }},
+ { &hf_h225_SupportedPrefixes,
+ { "SupportedPrefixes", "h225.SupportedPrefixes", FT_NONE, BASE_NONE,
+ NULL, 0, "SupportedPrefixes sequence of", HFILL }},
+ { &hf_h225_H310Caps,
+ { "H310Caps", "h225.H310Caps", FT_NONE, BASE_NONE,
+ NULL, 0, "H310Caps sequence", HFILL }},
+ { &hf_h225_H320Caps,
+ { "H320Caps", "h225.H320Caps", FT_NONE, BASE_NONE,
+ NULL, 0, "H320Caps sequence", HFILL }},
+ { &hf_h225_H321Caps,
+ { "H321Caps", "h225.H321Caps", FT_NONE, BASE_NONE,
+ NULL, 0, "H321Caps sequence", HFILL }},
+ { &hf_h225_H322Caps,
+ { "H322Caps", "h225.H322Caps", FT_NONE, BASE_NONE,
+ NULL, 0, "H322Caps sequence", HFILL }},
+ { &hf_h225_H323Caps,
+ { "H323Caps", "h225.H323Caps", FT_NONE, BASE_NONE,
+ NULL, 0, "H323Caps sequence", HFILL }},
+ { &hf_h225_H324Caps,
+ { "H324Caps", "h225.H324Caps", FT_NONE, BASE_NONE,
+ NULL, 0, "H324Caps sequence", HFILL }},
+ { &hf_h225_VoiceCaps,
+ { "VoiceCaps", "h225.VoiceCaps", FT_NONE, BASE_NONE,
+ NULL, 0, "VoiceCaps sequence", HFILL }},
+ { &hf_h225_T120OnlyCaps,
+ { "T120OnlyCaps", "h225.T120OnlyCaps", FT_NONE, BASE_NONE,
+ NULL, 0, "T120OnlyCaps sequence", HFILL }},
+ { &hf_h225_NonStandardProtocol,
+ { "NonStandardProtocol", "h225.NonStandardProtocol", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardProtocol sequence", HFILL }},
+ { &hf_h225_SIPCaps,
+ { "SIPCaps", "h225.SIPCaps", FT_NONE, BASE_NONE,
+ NULL, 0, "SIPCaps sequence", HFILL }},
+ { &hf_h225_AddressPattern_range,
+ { "AddressPattern_range", "h225.AddressPattern_range", FT_NONE, BASE_NONE,
+ NULL, 0, "AddressPattern_range sequence", HFILL }},
+ { &hf_h225_AddressPattern,
+ { "AddressPattern", "h225.AddressPattern", FT_UINT32, BASE_DEC,
+ VALS(AddressPattern_vals), 0, "AddressPattern choice", HFILL }},
+ { &hf_h225_ConferenceList,
+ { "ConferenceList", "h225.ConferenceList", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceList sequence", HFILL }},
+ { &hf_h225_conferences,
+ { "conferences", "h225.conferences", FT_NONE, BASE_NONE,
+ NULL, 0, "conferences sequence of", HFILL }},
+ { &hf_h225_T38FaxAnnexbOnlyCaps,
+ { "T38FaxAnnexbOnlyCaps", "h225.T38FaxAnnexbOnlyCaps", FT_NONE, BASE_NONE,
+ NULL, 0, "T38FaxAnnexbOnlyCaps sequence", HFILL }},
+ { &hf_h225_SupportedProtocols,
+ { "SupportedProtocols", "h225.SupportedProtocols", FT_UINT32, BASE_DEC,
+ VALS(SupportedProtocols_vals), 0, "SupportedProtocols choice", HFILL }},
+ { &hf_h225_protocol,
+ { "protocol", "h225.protocol", FT_NONE, BASE_NONE,
+ NULL, 0, "protocol sequence of", HFILL }},
+ { &hf_h225_GatewayInfo,
+ { "GatewayInfo", "h225.GatewayInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "GatewayInfo sequence", HFILL }},
+ { &hf_h225_McuInfo,
+ { "McuInfo", "h225.McuInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "McuInfo sequence", HFILL }},
+ { &hf_h225_TunnelledProtocol_id,
+ { "id", "h225.TunnelledProtocol_id", FT_UINT32, BASE_DEC,
+ VALS(TunnelledProtocol_id_vals), 0, "TunnelledProtocol_id choice", HFILL }},
+ { &hf_h225_TunnelledProtocol_subIdentifier,
+ { "subIdentifier", "h225.TunnelledProtocol_subIdentifier", FT_BYTES, BASE_HEX,
+ NULL, 0, "TunnelledProtocol_subIdentifier IA5String", HFILL }},
+ { &hf_h225_TunnelledProtocol,
+ { "TunnelledProtocol", "h225.TunnelledProtocol", FT_NONE, BASE_NONE,
+ NULL, 0, "TunnelledProtocol sequence", HFILL }},
+ { &hf_h225_TunnelledProtocols,
+ { "TunnelledProtocols", "h225.TunnelledProtocols", FT_NONE, BASE_NONE,
+ NULL, 0, "SEQUENCE OF TunnelledProtocol", HFILL }},
+ { &hf_h225_desiredTunnelledProtocol,
+ { "desiredTunnelledProtocol", "h225.desiredTunnelledProtocol", FT_NONE, BASE_NONE,
+ NULL, 0, "desiredTunnelledProtocol sequence", HFILL }},
+ { &hf_h225_CicInfo_cic_item,
+ { "item", "h225.CicInfo_cic_item", FT_BYTES, BASE_HEX,
+ NULL, 0, "CicInfo_cic_item octet string", HFILL }},
+ { &hf_h225_CicInfo_pointCode,
+ { "pointCode", "h225.CicInfo_pointCode", FT_BYTES, BASE_HEX,
+ NULL, 0, "CicInfo_pointCode octet string", HFILL }},
+ { &hf_h225_CicInfo_cic,
+ { "cic", "h225.CicInfo_cic", FT_NONE, BASE_NONE,
+ NULL, 0, "CicInfo_cic sequence of", HFILL }},
+ { &hf_h225_CicInfo,
+ { "CicInfo", "h225.CicInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "CicInfo sequence", HFILL }},
+ { &hf_h225_GroupID_member_item,
+ { "item", "h225.GroupID_member_item", FT_UINT32, BASE_DEC,
+ NULL, 0, "GroupID_member_item", HFILL }},
+ { &hf_h225_GroupID_member,
+ { "member", "h225.GroupID_member", FT_NONE, BASE_NONE,
+ NULL, 0, "GroupID_member sequence of", HFILL }},
+ { &hf_h225_GroupID_group,
+ { "group", "h225.GroupID_group", FT_STRING, BASE_NONE,
+ NULL, 0, "GroupID_group IA5String", HFILL }},
+ { &hf_h225_GroupID,
+ { "GroupID", "h225.GroupID", FT_NONE, BASE_NONE,
+ NULL, 0, "GroupID sequence", HFILL }},
+ { &hf_h225_sourceCircuitID,
+ { "sourceCircuitID", "h225.sourceCircuitID", FT_NONE, BASE_NONE,
+ NULL, 0, "sourceCircuitID sequence", HFILL }},
+ { &hf_h225_destinationCircuitID,
+ { "destinationCircuitID", "h225.destinationCircuitID", FT_NONE, BASE_NONE,
+ NULL, 0, "destinationCircuitID sequence", HFILL }},
+ { &hf_h225_Generic_standard,
+ { "standard", "h225.Generic_standard", FT_UINT32, BASE_DEC,
+ NULL, 0, "Generic_standard", HFILL }},
+ { &hf_h225_GenericIdentifier,
+ { "GenericIdentifier", "h225.GenericIdentifier", FT_UINT32, BASE_DEC,
+ VALS(GenericIdentifier_vals), 0, "GenericIdentifier choice", HFILL }},
+ { &hf_h225_EnumeratedParameter,
+ { "EnumeratedParameter", "h225.EnumeratedParameter", FT_NONE, BASE_NONE,
+ NULL, 0, "EnumeratedParameter sequence", HFILL }},
+ { &hf_h225_parameters,
+ { "parameters", "h225.parameters", FT_NONE, BASE_NONE,
+ NULL, 0, "parameters sequence of", HFILL }},
+ { &hf_h225_GenericData,
+ { "GenericData", "h225.GenericData", FT_NONE, BASE_NONE,
+ NULL, 0, "GenericData sequence", HFILL }},
+ { &hf_h225_FeatureDescriptor,
+ { "FeatureDescriptor", "h225.FeatureDescriptor", FT_NONE, BASE_NONE,
+ NULL, 0, "FeatureDescriptor sequence", HFILL }},
+ { &hf_h225_Content_raw,
+ { "Content_raw", "h225.Content_raw", FT_BYTES, BASE_HEX,
+ NULL, 0, "Content_raw octet string", HFILL }},
+ { &hf_h225_Content_text,
+ { "Content_text", "h225.Content_text", FT_BYTES, BASE_HEX,
+ NULL, 0, "Content_text IA5String", HFILL }},
+ { &hf_h225_Content,
+ { "Content", "h225.Content", FT_UINT32, BASE_DEC,
+ VALS(Content_vals), 0, "Content choice", HFILL }},
+ { &hf_h225_Content_bool,
+ { "Content_bool", "h225.Content_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_Content_bool_bit), 0x01, "Content_bool boolean", HFILL }},
+ { &hf_h225_Content_number8,
+ { "Content_number8", "h225.Content_number8", FT_UINT32, BASE_DEC,
+ NULL, 0, "Content_number8", HFILL }},
+ { &hf_h225_number16,
+ { "number16", "h225.number16", FT_UINT32, BASE_DEC,
+ NULL, 0, "number16", HFILL }},
+ { &hf_h225_Content_number32,
+ { "Content_number32", "h225.Content_number32", FT_UINT32, BASE_DEC,
+ NULL, 0, "Content_number32", HFILL }},
+ { &hf_h225_Content_compound,
+ { "Content_compound", "h225.Content_compound", FT_NONE, BASE_NONE,
+ NULL, 0, "Content_compound sequence of", HFILL }},
+ { &hf_h225_Content_nested,
+ { "Content_nested", "h225.Content_nested", FT_NONE, BASE_NONE,
+ NULL, 0, "Content_nested sequence of", HFILL }},
+ { &hf_h225_replacementFeatureSet,
+ { "replacementFeatureSet", "h225.replacementFeatureSet", FT_BOOLEAN, 8,
+ TFS(&tfs_replacementFeatureSet_bit), 0x01, "replacementFeatureSet boolean", HFILL }},
+ { &hf_h225_neededFeatures,
+ { "neededFeatures", "h225.neededFeatures", FT_NONE, BASE_NONE,
+ NULL, 0, "neededFeatures sequence of", HFILL }},
+ { &hf_h225_desiredFeatures,
+ { "desiredFeatures", "h225.desiredFeatures", FT_NONE, BASE_NONE,
+ NULL, 0, "desiredFeatures sequence of", HFILL }},
+ { &hf_h225_supportedFeatures,
+ { "supportedFeatures", "h225.supportedFeatures", FT_NONE, BASE_NONE,
+ NULL, 0, "supportedFeatures sequence of", HFILL }},
+ { &hf_h225_FeatureSet,
+ { "FeatureSet", "h225.FeatureSet", FT_NONE, BASE_NONE,
+ NULL, 0, "FeatureSet sequence", HFILL }},
+ { &hf_h225_CallsAvailable_calls,
+ { "CallsAvailable_calls", "h225.CallsAvailable_calls", FT_UINT32, BASE_DEC,
+ NULL, 0, "CallsAvailable_calls", HFILL }},
+ { &hf_h225_CallsAvailable_group,
+ { "CallsAvailable_group", "h225.CallsAvailable_group", FT_STRING, BASE_HEX,
+ NULL, 0, "CallsAvailable_group IA5String", HFILL }},
+ { &hf_h225_CallsAvailable,
+ { "CallsAvailable", "h225.CallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "CallsAvailable sequence", HFILL }},
+ { &hf_h225_voiceGwCallsAvailable,
+ { "voiceGwCallsAvailable", "h225.voiceGwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "voiceGwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_h310GwCallsAvailable,
+ { "h310GwCallsAvailable", "h225.h310GwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "h310GwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_h320GwCallsAvailable,
+ { "h320GwCallsAvailable", "h225.h320GwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "h320GwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_h321GwCallsAvailable,
+ { "h321GwCallsAvailable", "h225.h321GwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "h321GwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_h322GwCallsAvailable,
+ { "h322GwCallsAvailable", "h225.h322GwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "h322GwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_h323GwCallsAvailable,
+ { "h323GwCallsAvailable", "h225.h323GwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "h323GwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_h324GwCallsAvailable,
+ { "h324GwCallsAvailable", "h225.h324GwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "h324GwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_t120OnlyGwCallsAvailable,
+ { "t120OnlyGwCallsAvailable", "h225.t120OnlyGwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "t120OnlyGwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_t38FaxAnnexbOnlyGwCallsAvailable,
+ { "t38FaxAnnexbOnlyGwCallsAvailable", "h225.t38FaxAnnexbOnlyGwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "t38FaxAnnexbOnlyGwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_terminalCallsAvailable,
+ { "terminalCallsAvailable", "h225.terminalCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "terminalCallsAvailable sequence of", HFILL }},
+ { &hf_h225_mcuCallsAvailable,
+ { "mcuCallsAvailable", "h225.mcuCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "mcuCallsAvailable sequence of", HFILL }},
+ { &hf_h225_sipGwCallsAvailable,
+ { "sipGwCallsAvailable", "h225.sipGwCallsAvailable", FT_NONE, BASE_NONE,
+ NULL, 0, "sipGwCallsAvailable sequence of", HFILL }},
+ { &hf_h225_maximumCallCapacity,
+ { "maximumCallCapacity", "h225.maximumCallCapacity", FT_NONE, BASE_NONE,
+ NULL, 0, "maximumCallCapacity sequence", HFILL }},
+ { &hf_h225_currentCallCapacity,
+ { "currentCallCapacity", "h225.currentCallCapacity", FT_NONE, BASE_NONE,
+ NULL, 0, "currentCallCapacity sequence", HFILL }},
+ { &hf_h225_CallCapacity,
+ { "CallCapacity", "h225.CallCapacity", FT_NONE, BASE_NONE,
+ NULL, 0, "CallCapacity sequence", HFILL }},
+ { &hf_h225_productID,
+ { "productID", "h225.productID", FT_STRING, BASE_HEX,
+ NULL, 0, "productID octet string", HFILL }},
+ { &hf_h225_versionID,
+ { "versionID", "h225.versionID", FT_STRING, BASE_HEX,
+ NULL, 0, "versionID octet string", HFILL }},
+ { &hf_h225_VendorIdentifier,
+ { "VendorIdentifier", "h225.VendorIdentifier", FT_NONE, BASE_NONE,
+ NULL, 0, "VendorIdentifier sequence", HFILL }},
+ { &hf_h225_canReportCallCapacity,
+ { "canReportCallCapacity", "h225.canReportCallCapacity", FT_BOOLEAN, 8,
+ TFS(&tfs_canReportCallCapacity_bit), 0x01, "canReportCallCapacity boolean", HFILL }},
+ { &hf_h225_CapacityReportingCapability,
+ { "CapacityReportingCapability", "h225.CapacityReportingCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "CapacityReportingCapability sequence", HFILL }},
+ { &hf_h225_canDisplayAmountString,
+ { "canDisplayAmountString", "h225.canDisplayAmountString", FT_BOOLEAN, 8,
+ TFS(&tfs_canDisplayAmountString_bit), 0x01, "canDisplayAmountString boolean", HFILL }},
+ { &hf_h225_canEnforceDurationLimit,
+ { "canEnforceDurationLimit", "h225.canEnforceDurationLimit", FT_BOOLEAN, 8,
+ TFS(&tfs_canEnforceDurationLimit_bit), 0x01, "canEnforceDurationLimit boolean", HFILL }},
+ { &hf_h225_CallCreditCapability,
+ { "CallCreditCapability", "h225.CallCreditCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "CallCreditCapability sequence", HFILL }},
+ { &hf_h225_BandwidthDetails_sender,
+ { "BandwidthDetails_sender", "h225.BandwidthDetails_sender", FT_BOOLEAN, 8,
+ TFS(&tfs_BandwidthDetails_sender_bit), 0x01, "BandwidthDetails_sender boolean", HFILL }},
+ { &hf_h225_BandwidthDetails_multicast,
+ { "BandwidthDetails_multicast", "h225.BandwidthDetails_multicast", FT_BOOLEAN, 8,
+ TFS(&tfs_BandwidthDetails_multicast_bit), 0x01, "BandwidthDetails_multicast boolean", HFILL }},
+ { &hf_h225_BandwidthDetails,
+ { "BandwidthDetails", "h225.BandwidthDetails", FT_NONE, BASE_NONE,
+ NULL, 0, "BandwidthDetails sequence", HFILL }},
+ { &hf_h225_releaseCompleteCauseIE,
+ { "releaseCompleteCauseIE", "h225.releaseCompleteCauseIE", FT_BYTES, BASE_HEX,
+ NULL, 0, "releaseCompleteCauseIE octet string", HFILL }},
+ { &hf_h225_CallTerminationCause,
+ { "CallTerminationCause", "h225.CallTerminationCause", FT_UINT32, BASE_DEC,
+ VALS(CallTerminationCause_vals), 0, "CallTerminationCause choice", HFILL }},
+ { &hf_h225_CircuitInfo,
+ { "CircuitInfo", "h225.CircuitInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "CircuitInfo sequence", HFILL }},
+ { &hf_h225_genericData,
+ { "genericData", "h225.genericData", FT_NONE, BASE_NONE,
+ NULL, 0, "genericData sequence of", HFILL }},
+ { &hf_h225_fastStart_item_length,
+ { "fastStart item length", "h225.fastStart_item_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "fastStart item length", HFILL }},
+ { &hf_h225_fastStart,
+ { "fastStart", "h225.fastStart", FT_NONE, BASE_NONE,
+ NULL, 0, "fastStart sequence of", HFILL }},
+ { &hf_h225_fastConnectRefused,
+ { "fastConnectRefused", "h225.fastConnectRefused", FT_BOOLEAN, 8,
+ TFS(&tfs_fastConnectRefused_bit), 0x01, "fastConnectRefused boolean", HFILL }},
+ { &hf_h225_InformationUUIE,
+ { "InformationUUIE", "h225.InformationUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "InformationUUIE sequence", HFILL }},
+ { &hf_h225_routeCallToSCN,
+ { "routeCallToSCN", "h225.routeCallToSCN", FT_NONE, BASE_NONE,
+ NULL, 0, "routeCallToSCN sequence of", HFILL }},
+ { &hf_h225_AdmissionRejectReason,
+ { "AdmissionRejectReason", "h225.AdmissionRejectReason", FT_UINT32, BASE_DEC,
+ VALS(AdmissionRejectReason_vals), 0, "AdmissionRejectReason choice", HFILL }},
+ { &hf_h225_hMAC_iso10118_2_s,
+ { "hMAC_iso10118_2_s", "h225.hMAC_iso10118_2_s", FT_UINT32, BASE_DEC,
+ VALS(EncryptIntAlg_vals), 0, "hMAC_iso10118_2_s choice", HFILL }},
+ { &hf_h225_hMAC_iso10118_2_l,
+ { "hMAC_iso10118_2_l", "h225.hMAC_iso10118_2_l", FT_UINT32, BASE_DEC,
+ VALS(EncryptIntAlg_vals), 0, "hMAC_iso10118_2_l choice", HFILL }},
+ { &hf_h225_NonIsoIntegrityMechanism,
+ { "NonIsoIntegrityMechanism", "h225.NonIsoIntegrityMechanism", FT_UINT32, BASE_DEC,
+ VALS(NonIsoIntegrityMechanism_vals), 0, "NonIsoIntegrityMechanism choice", HFILL }},
+ { &hf_h225_IntegrityMechanism,
+ { "IntegrityMechanism", "h225.IntegrityMechanism", FT_UINT32, BASE_DEC,
+ VALS(IntegrityMechanism_vals), 0, "IntegrityMechanism choice", HFILL }},
+ { &hf_h225_LocationRejectReason,
+ { "LocationRejectReason", "h225.LocationRejectReason", FT_UINT32, BASE_DEC,
+ VALS(LocationRejectReason_vals), 0, "LocationRejectReason choice", HFILL }},
+ { &hf_h225_mc,
+ { "mc", "h225.mc", FT_BOOLEAN, 8,
+ TFS(&tfs_mc_bit), 0x01, "mc boolean", HFILL }},
+ { &hf_h225_undefinedNode,
+ { "undefinedNode", "h225.undefinedNode", FT_BOOLEAN, 8,
+ TFS(&tfs_undefinedNode_bit), 0x01, "undefinedNode boolean", HFILL }},
+ { &hf_h225_destinationInfo,
+ { "destinationInfo", "h225.destinationInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "destinationInfo sequence", HFILL }},
+ { &hf_h225_EndPointType,
+ { "EndPointType", "h225.EndPointType", FT_NONE, BASE_NONE,
+ NULL, 0, "EndPointType sequence", HFILL }},
+ { &hf_h225_terminalType,
+ { "terminalType", "h225.terminalType", FT_NONE, BASE_NONE,
+ NULL, 0, "terminalType sequence", HFILL }},
+ { &hf_h225_sourceInfo,
+ { "sourceInfo", "h225.sourceInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "sourceInfo sequence", HFILL }},
+ { &hf_h225_multipleCalls,
+ { "multipleCalls", "h225.multipleCalls", FT_BOOLEAN, 8,
+ TFS(&tfs_multipleCalls_bit), 0x01, "multipleCalls boolean", HFILL }},
+ { &hf_h225_maintainConnection,
+ { "maintainConnection", "h225.maintainConnection", FT_BOOLEAN, 8,
+ TFS(&tfs_maintainConnection_bit), 0x01, "maintainConnection boolean", HFILL }},
+ { &hf_h225_CallProceedingUUIE,
+ { "CallProceedingUUIE", "h225.CallProceedingUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "CallProceedingUUIE sequence", HFILL }},
+ { &hf_h225_CapacityReportingSpecification_when,
+ { "CapacityReportingSpecification_when", "h225.CapacityReportingSpecification_when", FT_NONE, BASE_NONE,
+ NULL, 0, "CapacityReportingSpecification_when sequence", HFILL }},
+ { &hf_h225_CapacityReportingSpecification,
+ { "CapacityReportingSpecification", "h225.CapacityReportingSpecification", FT_NONE, BASE_NONE,
+ NULL, 0, "CapacityReportingSpecification sequence", HFILL }},
+ { &hf_h225_ProgressUUIE,
+ { "ProgressUUIE", "h225.ProgressUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "ProgressUUIE sequence", HFILL }},
+ { &hf_h225_EndPoint,
+ { "EndPoint", "h225.EndPoint", FT_NONE, BASE_NONE,
+ NULL, 0, "EndPoint sequence", HFILL }},
+ { &hf_h225_destinationType,
+ { "destinationType", "h225.destinationType", FT_NONE, BASE_NONE,
+ NULL, 0, "destinationType sequence", HFILL }},
+ { &hf_h225_destExtraCallInfo,
+ { "destExtraCallInfo", "h225.destExtraCallInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "destExtraCallInfo sequence of", HFILL }},
+ { &hf_h225_remoteExtensionAddress,
+ { "remoteExtensionAddress", "h225.remoteExtensionAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "remoteExtensionAddress sequence of", HFILL }},
+ { &hf_h225_aliasAddress_sequence,
+ { "aliasAddress_sequence", "h225.aliasAddress_sequence", FT_NONE, BASE_NONE,
+ NULL, 0, "aliasAddress_sequence sequence of", HFILL }},
+ { &hf_h225_rasAddress_sequence,
+ { "rasAddress_sequence", "h225.rasAddress_sequence", FT_NONE, BASE_NONE,
+ NULL, 0, "rasAddress_sequence sequence of", HFILL }},
+ { &hf_h225_callSignalAddress,
+ { "callSignalAddress", "h225.callSignalAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "callSignalAddress sequence of", HFILL }},
+ { &hf_h225_ICV,
+ { "ICV", "h225.ICV", FT_NONE, BASE_NONE,
+ NULL, 0, "ICV sequence", HFILL }},
+ { &hf_h225_BandwidthConfirm,
+ { "BandwidthConfirm", "h225.BandwidthConfirm", FT_NONE, BASE_NONE,
+ NULL, 0, "BandwidthConfirm sequence", HFILL }},
+ { &hf_h225_UnregistrationConfirm,
+ { "UnregistrationConfirm", "h225.UnregistrationConfirm", FT_NONE, BASE_NONE,
+ NULL, 0, "UnregistrationConfirm sequence", HFILL }},
+ { &hf_h225_NonStandardMessage,
+ { "NonStandardMessage", "h225.NonStandardMessage", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardMessage sequence", HFILL }},
+ { &hf_h225_InfoRequestAck,
+ { "InfoRequestAck", "h225.InfoRequestAck", FT_NONE, BASE_NONE,
+ NULL, 0, "InfoRequestAck sequence", HFILL }},
+ { &hf_h225_InfoRequestNak,
+ { "InfoRequestNak", "h225.InfoRequestNak", FT_NONE, BASE_NONE,
+ NULL, 0, "InfoRequestNak sequence", HFILL }},
+ { &hf_h225_ResourcesAvailableConfirm,
+ { "ResourcesAvailableConfirm", "h225.ResourcesAvailableConfirm", FT_NONE, BASE_NONE,
+ NULL, 0, "ResourcesAvailableConfirm sequence", HFILL }},
+ { &hf_h225_GatekeeperRequest,
+ { "GatekeeperRequest", "h225.GatekeeperRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "GatekeeperRequest sequence", HFILL }},
+ { &hf_h225_integrity,
+ { "integrity", "h225.integrity", FT_NONE, BASE_NONE,
+ NULL, 0, "integrity sequence of", HFILL }},
+ { &hf_h225_algorithmOIDs,
+ { "algorithmOIDs", "h225.algorithmOIDs", FT_NONE, BASE_NONE,
+ NULL, 0, "algorithmOIDs sequence of", HFILL }},
+ { &hf_h225_alternateEndpoints,
+ { "alternateEndpoints", "h225.alternateEndpoints", FT_NONE, BASE_NONE,
+ NULL, 0, "alternateEndpoints sequence of", HFILL }},
+ { &hf_h225_endpointAlias,
+ { "endpointAlias", "h225.endpointAlias", FT_NONE, BASE_NONE,
+ NULL, 0, "endpointAlias sequence of", HFILL }},
+ { &hf_h225_ServiceControlResponse,
+ { "ServiceControlResponse", "h225.ServiceControlResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "ServiceControlResponse sequence", HFILL }},
+ { &hf_h225_DisengageReject,
+ { "DisengageReject", "h225.DisengageReject", FT_NONE, BASE_NONE,
+ NULL, 0, "DisengageReject sequence", HFILL }},
+ { &hf_h225_BandwidthReject,
+ { "BandwidthReject", "h225.BandwidthReject", FT_NONE, BASE_NONE,
+ NULL, 0, "BandwidthReject sequence", HFILL }},
+ { &hf_h225_UnregistrationReject,
+ { "UnregistrationReject", "h225.UnregistrationReject", FT_NONE, BASE_NONE,
+ NULL, 0, "UnregistrationReject sequence", HFILL }},
+ { &hf_h225_UnregistrationRequest,
+ { "UnregistrationRequest", "h225.UnregistrationRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "UnregistrationRequest sequence", HFILL }},
+ { &hf_h225_endpointAliasPattern,
+ { "endpointAliasPattern", "h225.endpointAliasPattern", FT_NONE, BASE_NONE,
+ NULL, 0, "endpointAliasPattern sequence of", HFILL }},
+ { &hf_h225_RegistrationReject,
+ { "RegistrationReject", "h225.RegistrationReject", FT_NONE, BASE_NONE,
+ NULL, 0, "RegistrationReject sequence", HFILL }},
+ { &hf_h225_invalidTerminalAliases,
+ { "invalidTerminalAliases", "h225.invalidTerminalAliases", FT_NONE, BASE_NONE,
+ NULL, 0, "invalidTerminalAliases sequence", HFILL }},
+ { &hf_h225_terminalAlias,
+ { "terminalAlias", "h225.terminalAlias", FT_NONE, BASE_NONE,
+ NULL, 0, "terminalAlias sequence of", HFILL }},
+ { &hf_h225_terminalAliasPattern,
+ { "terminalAliasPattern", "h225.terminalAliasPattern", FT_NONE, BASE_NONE,
+ NULL, 0, "terminalAliasPattern sequence of", HFILL }},
+ { &hf_h225_RegistrationRejectReason,
+ { "RegistrationRejectReason", "h225.RegistrationRejectReason", FT_UINT32, BASE_DEC,
+ VALS(RegistrationRejectReason_vals), 0, "RegistrationRejectReason choice", HFILL }},
+ { &hf_h225_duplicateAlias,
+ { "duplicateAlias", "h225.duplicateAlias", FT_NONE, BASE_NONE,
+ NULL, 0, "duplicateAlias sequence of", HFILL }},
+ { &hf_h225_GatekeeperReject,
+ { "GatekeeperReject", "h225.GatekeeperReject", FT_NONE, BASE_NONE,
+ NULL, 0, "GatekeeperReject sequence", HFILL }},
+ { &hf_h225_almostOutOfResources,
+ { "almostOutOfResources", "h225.almostOutOfResources", FT_BOOLEAN, 8,
+ TFS(&tfs_almostOutOfResources_bit), 0x01, "almostOutOfResources boolean", HFILL }},
+ { &hf_h225_ResourcesAvailableIndicate,
+ { "ResourcesAvailableIndicate", "h225.ResourcesAvailableIndicate", FT_NONE, BASE_NONE,
+ NULL, 0, "ResourcesAvailableIndicate sequence", HFILL }},
+ { &hf_h225_protocols,
+ { "protocols", "h225.protocols", FT_NONE, BASE_NONE,
+ NULL, 0, "protocols sequence of", HFILL }},
+ { &hf_h225_callDurationLimit,
+ { "callDurationLimit", "h225.callDurationLimit", FT_UINT32, BASE_DEC,
+ NULL, 0, "callDurationLimit", HFILL }},
+ { &hf_h225_enforceCallDurationLimit,
+ { "enforceCallDurationLimit", "h225.enforceCallDurationLimit", FT_BOOLEAN, 8,
+ TFS(&tfs_enforceCallDurationLimit_bit), 0x01, "enforceCallDurationLimit boolean", HFILL }},
+ { &hf_h225_CallCreditServiceControl,
+ { "CallCreditServiceControl", "h225.CallCreditServiceControl", FT_NONE, BASE_NONE,
+ NULL, 0, "CallCreditServiceControl sequence", HFILL }},
+ { &hf_h225_ScreeningIndicator,
+ { "ScreeningIndicator", "h225.ScreeningIndicator", FT_UINT32, BASE_DEC,
+ VALS(ScreeningIndicator_vals), 0, "ScreeningIndicator", HFILL }},
+ { &hf_h225_ExtendedAliasAddress,
+ { "ExtendedAliasAddress", "h225.ExtendedAliasAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "ExtendedAliasAddress sequence", HFILL }},
+ { &hf_h225_messageNotUnderstood,
+ { "messageNotUnderstood", "h225.messageNotUnderstood", FT_BYTES, BASE_HEX,
+ NULL, 0, "messageNotUnderstood octet string", HFILL }},
+ { &hf_h225_UnknownMessageResponse,
+ { "UnknownMessageResponse", "h225.UnknownMessageResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "UnknownMessageResponse sequence", HFILL }},
+ { &hf_h225_CallReferenceValue,
+ { "CallReferenceValue", "h225.CallReferenceValue", FT_UINT32, BASE_DEC,
+ NULL, 0, "CallReferenceValue", HFILL }},
+ { &hf_h225_AdmissionRequest,
+ { "AdmissionRequest", "h225.AdmissionRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "AdmissionRequest sequence", HFILL }},
+ { &hf_h225_canMapSrcAlias,
+ { "canMapSrcAlias", "h225.canMapSrcAlias", FT_BOOLEAN, 8,
+ TFS(&tfs_canMapSrcAlias_bit), 0x01, "canMapSrcAlias boolean", HFILL }},
+ { &hf_h225_desiredProtocols,
+ { "desiredProtocols", "h225.desiredProtocols", FT_NONE, BASE_NONE,
+ NULL, 0, "desiredProtocols sequence of", HFILL }},
+ { &hf_h225_willSupplyUUIEs,
+ { "willSupplyUUIEs", "h225.willSupplyUUIEs", FT_BOOLEAN, 8,
+ TFS(&tfs_willSupplyUUIEs_bit), 0x01, "willSupplyUUIEs boolean", HFILL }},
+ { &hf_h225_destAlternatives,
+ { "destAlternatives", "h225.destAlternatives", FT_NONE, BASE_NONE,
+ NULL, 0, "destAlternatives sequence of", HFILL }},
+ { &hf_h225_srcAlternatives,
+ { "srcAlternatives", "h225.srcAlternatives", FT_NONE, BASE_NONE,
+ NULL, 0, "srcAlternatives sequence of", HFILL }},
+ { &hf_h225_canMapAlias,
+ { "canMapAlias", "h225.canMapAlias", FT_BOOLEAN, 8,
+ TFS(&tfs_canMapAlias_bit), 0x01, "canMapAlias boolean", HFILL }},
+ { &hf_h225_activeMC,
+ { "activeMC", "h225.activeMC", FT_BOOLEAN, 8,
+ TFS(&tfs_activeMC_bit), 0x01, "activeMC boolean", HFILL }},
+ { &hf_h225_srcInfo,
+ { "srcInfo", "h225.srcInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "srcInfo sequence of", HFILL }},
+ { &hf_h225_DestinationInfo,
+ { "DestinationInfo", "h225.DestinationInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "DestinationInfo sequence of", HFILL }},
+ { &hf_h225_InfoRequest,
+ { "InfoRequest", "h225.InfoRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "InfoRequest sequence", HFILL }},
+ { &hf_h225_nextSegmentRequested,
+ { "nextSegmentRequested", "h225.nextSegmentRequested", FT_UINT32, BASE_DEC,
+ NULL, 0, "nextSegmentRequested", HFILL }},
+ { &hf_h225_delay,
+ { "delay", "h225.delay", FT_UINT32, BASE_DEC,
+ NULL, 0, "delay", HFILL }},
+ { &hf_h225_RequestInProgress,
+ { "RequestInProgress", "h225.RequestInProgress", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestInProgress sequence", HFILL }},
+ { &hf_h225_H248SignalsDescriptor,
+ { "H248SignalsDescriptor", "h225.H248SignalsDescriptor", FT_BYTES, BASE_HEX,
+ NULL, 0, "H248SignalsDescriptor octet string", HFILL }},
+ { &hf_h225_url,
+ { "url", "h225.url", FT_BYTES, BASE_HEX,
+ NULL, 0, "url IA5String", HFILL }},
+ { &hf_h225_ServiceControlDescriptor,
+ { "ServiceControlDescriptor", "h225.ServiceControlDescriptor", FT_UINT32, BASE_DEC,
+ VALS(ServiceControlDescriptor_vals), 0, "ServiceControlDescriptor choice", HFILL }},
+ { &hf_h225_ServiceControlSession,
+ { "ServiceControlSession", "h225.ServiceControlSession", FT_NONE, BASE_NONE,
+ NULL, 0, "ServiceControlSession sequence", HFILL }},
+ { &hf_h225_sessionId,
+ { "sessionId", "h225.sessionId", FT_UINT32, BASE_DEC,
+ NULL, 0, "sessionId", HFILL }},
+ { &hf_h225_AlertingUUIE,
+ { "AlertingUUIE", "h225.AlertingUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "AlertingUUIE sequence", HFILL }},
+ { &hf_h225_serviceControl,
+ { "serviceControl", "h225.serviceControl", FT_NONE, BASE_NONE,
+ NULL, 0, "serviceControl sequence of", HFILL }},
+ { &hf_h225_alertingAddress,
+ { "alertingAddress", "h225.alertingAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "alertingAddress sequence of", HFILL }},
+ { &hf_h225_ReleaseCompleteUUIE,
+ { "ReleaseCompleteUUIE", "h225.ReleaseCompleteUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "ReleaseCompleteUUIE sequence", HFILL }},
+ { &hf_h225_busyAddress,
+ { "busyAddress", "h225.busyAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "busyAddress sequence of", HFILL }},
+ { &hf_h225_FacilityUUIE,
+ { "FacilityUUIE", "h225.FacilityUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "FacilityUUIE sequence", HFILL }},
+ { &hf_h225_alternativeAliasAddress,
+ { "alternativeAliasAddress", "h225.alternativeAliasAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "alternativeAliasAddress sequence of", HFILL }},
+ { &hf_h225_AdmissionReject,
+ { "AdmissionReject", "h225.AdmissionReject", FT_NONE, BASE_NONE,
+ NULL, 0, "AdmissionReject sequence", HFILL }},
+ { &hf_h225_hopCount,
+ { "hopCount", "h225.hopCount", FT_UINT32, BASE_DEC,
+ NULL, 0, "hopCount", HFILL }},
+ { &hf_h225_parallelH245Control,
+ { "parallelH245Control", "h225.parallelH245Control", FT_NONE, BASE_NONE,
+ NULL, 0, "parallelH245Control sequence of", HFILL }},
+ { &hf_h225_language,
+ { "language", "h225.language", FT_BYTES, BASE_HEX,
+ NULL, 0, "language IA5String", HFILL }},
+ { &hf_h225_languages,
+ { "languages", "h225.languages", FT_NONE, BASE_NONE,
+ NULL, 0, "languages sequence of", HFILL }},
+ { &hf_h225_mediaWaitForConnect,
+ { "mediaWaitForConnect", "h225.mediaWaitForConnect", FT_BOOLEAN, 8,
+ TFS(&tfs_mediaWaitForConnect_bit), 0x01, "mediaWaitForConnect boolean", HFILL }},
+ { &hf_h225_canOverlapSend,
+ { "canOverlapSend", "h225.canOverlapSend", FT_BOOLEAN, 8,
+ TFS(&tfs_canOverlapSend_bit), 0x01, "canOverlapSend boolean", HFILL }},
+ { &hf_h225_SetupUUIE,
+ { "SetupUUIE", "h225.SetupUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "SetupUUIE sequence", HFILL }},
+ { &hf_h225_sourceAddress,
+ { "sourceAddress", "h225.sourceAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "sourceAddress sequence of", HFILL }},
+ { &hf_h225_destinationAddress,
+ { "destinationAddress", "h225.destinationAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "destinationAddress sequence of", HFILL }},
+ { &hf_h225_destExtraCRV,
+ { "destExtraCRV", "h225.destExtraCRV", FT_NONE, BASE_NONE,
+ NULL, 0, "destExtraCRV sequence of", HFILL }},
+ { &hf_h225_h245SecurityCapability,
+ { "h245SecurityCapability", "h225.h245SecurityCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "h245SecurityCapability sequence of", HFILL }},
+ { &hf_h225_additionalSourceAddresses,
+ { "additionalSourceAddresses", "h225.additionalSourceAddresses", FT_NONE, BASE_NONE,
+ NULL, 0, "additionalSourceAddresses sequence of", HFILL }},
+ { &hf_h225_ConnectUUIE,
+ { "ConnectUUIE", "h225.ConnectUUIE", FT_NONE, BASE_NONE,
+ NULL, 0, "ConnectUUIE sequence", HFILL }},
+ { &hf_h225_connectedAddress,
+ { "connectedAddress", "h225.connectedAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "connectedAddress sequence of", HFILL }},
+ { &hf_h225_h323_message_body,
+ { "h323_message_body", "h225.h323_message_body", FT_UINT32, BASE_DEC,
+ VALS(h323_message_body_vals), 0, "h323_message_body choice", HFILL }},
+ { &hf_h225_LocationConfirm,
+ { "LocationConfirm", "h225.LocationConfirm", FT_NONE, BASE_NONE,
+ NULL, 0, "LocationConfirm sequence", HFILL }},
+ { &hf_h225_supportedProtocols,
+ { "supportedProtocols", "h225.supportedProtocols", FT_NONE, BASE_NONE,
+ NULL, 0, "supportedProtocols sequence of", HFILL }},
+ { &hf_h225_modifiedSrcInfo,
+ { "modifiedSrcInfo", "h225.modifiedSrcInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "modifiedSrcInfo sequence of", HFILL }},
+ { &hf_h225_LocationReject,
+ { "LocationReject", "h225.LocationReject", FT_NONE, BASE_NONE,
+ NULL, 0, "LocationReject sequence", HFILL }},
+ { &hf_h225_callSpecific,
+ { "callSpecific", "h225.callSpecific", FT_NONE, BASE_NONE,
+ NULL, 0, "callSpecific sequence", HFILL }},
+ { &hf_h225_answeredCall,
+ { "answeredCall", "h225.answeredCall", FT_BOOLEAN, 8,
+ TFS(&tfs_answeredCall_bit), 0x01, "answeredCall boolean", HFILL }},
+ { &hf_h225_ServiceControlIndication,
+ { "ServiceControlIndication", "h225.ServiceControlIndication", FT_NONE, BASE_NONE,
+ NULL, 0, "ServiceControlIndication sequence", HFILL }},
+ { &hf_h225_RasUsageInformation,
+ { "RasUsageInformation", "h225.RasUsageInformation", FT_NONE, BASE_NONE,
+ NULL, 0, "RasUsageInformation sequence", HFILL }},
+ { &hf_h225_nonStandardUsageFields,
+ { "nonStandardUsageFields", "h225.nonStandardUsageFields", FT_NONE, BASE_NONE,
+ NULL, 0, "SEQUENCE OF NonStandardParameter", HFILL }},
+ { &hf_h225_nonStandardUsageFields_item,
+ { "nonStandardUsageFields", "h225.nonStandardUsageFields_item", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardParameter", HFILL }},
+ { &hf_h225_TimeToLive,
+ { "TimeToLive", "h225.TimeToLive", FT_UINT32, BASE_DEC,
+ NULL, 0, "TimeToLive in seconds", HFILL }},
+ { &hf_h225_GatekeeperConfirm,
+ { "GatekeeperConfirm", "h225.GatekeeperConfirm", FT_NONE, BASE_NONE,
+ NULL, 0, "GatekeeperConfirm sequence", HFILL }},
+ { &hf_h225_RegistrationRequest,
+ { "RegistrationRequest", "h225.RegistrationRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "RegistrationRequest sequence", HFILL }},
+ { &hf_h225_discoveryComplete,
+ { "discoveryComplete", "h225.discoveryComplete", FT_BOOLEAN, 8,
+ TFS(&tfs_discoveryComplete_bit), 0x01, "discoveryComplete boolean", HFILL }},
+ { &hf_h225_keepAlive,
+ { "keepAlive", "h225.keepAlive", FT_BOOLEAN, 8,
+ TFS(&tfs_keepAlive_bit), 0x01, "keepAlive boolean", HFILL }},
+ { &hf_h225_H248PackagesDescriptor,
+ { "H248PackagesDescriptor", "h225.H248PackagesDescriptor", FT_BYTES, BASE_HEX,
+ NULL, 0, "H248PackagesDescriptor octet string", HFILL }},
+ { &hf_h225_supportedH248Packages,
+ { "supportedH248Packages", "h225.supportedH248Packages", FT_NONE, BASE_NONE,
+ NULL, 0, "supportedH248Packages sequence of", HFILL }},
+ { &hf_h225_DisengageConfirm,
+ { "DisengageConfirm", "h225.DisengageConfirm", FT_NONE, BASE_NONE,
+ NULL, 0, "DisengageConfirm sequence", HFILL }},
+ { &hf_h225_AdmissionConfirm,
+ { "AdmissionConfirm", "h225.AdmissionConfirm", FT_NONE, BASE_NONE,
+ NULL, 0, "AdmissionConfirm sequence", HFILL }},
+ { &hf_h225_irrFrequency,
+ { "irrFrequency", "h225.irrFrequency", FT_UINT32, BASE_DEC,
+ NULL, 0, "irrFrequency", HFILL }},
+ { &hf_h225_willRespondToIRR,
+ { "willRespondToIRR", "h225.willRespondToIRR", FT_BOOLEAN, 8,
+ TFS(&tfs_willRespondToIRR_bit), 0x01, "willRespondToIRR boolean", HFILL }},
+ { &hf_h225_usageSpec,
+ { "usageSpec", "h225.usageSpec", FT_NONE, BASE_NONE,
+ NULL, 0, "usageSpec sequence of", HFILL }},
+ { &hf_h225_DisengageRequest,
+ { "DisengageRequest", "h225.DisengageRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "DisengageRequest sequence", HFILL }},
+ { &hf_h225_LocationRequest,
+ { "LocationRequest", "h225.LocationRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "LocationRequest sequence", HFILL }},
+ { &hf_h225_SourceInfo,
+ { "SourceInfo", "h225.SourceInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "SourceInfo sequence of", HFILL }},
+ { &hf_h225_hopCount255,
+ { "hopCount255", "h225.hopCount255", FT_UINT32, BASE_DEC,
+ NULL, 0, "hopCount255", HFILL }},
+ { &hf_h225_sourceEndpointInfo,
+ { "sourceEndpointInfo", "h225.sourceEndpointInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "sourceEndpointInfo sequence of", HFILL }},
+ { &hf_h225_BandwidthRequest,
+ { "BandwidthRequest", "h225.BandwidthRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "BandwidthRequest sequence", HFILL }},
+ { &hf_h225_bandwidthDetails,
+ { "bandwidthDetails", "h225.bandwidthDetails", FT_NONE, BASE_NONE,
+ NULL, 0, "bandwidthDetails sequence of", HFILL }},
+ { &hf_h225_admissionConfirmSequence,
+ { "admissionConfirmSequence", "h225.admissionConfirmSequence", FT_NONE, BASE_NONE,
+ NULL, 0, "admissionConfirmSequence sequence of", HFILL }},
+ { &hf_h225_tunnelledSignallingMessage,
+ { "tunnelledSignallingMessage", "h225.tunnelledSignallingMessage", FT_NONE, BASE_NONE,
+ NULL, 0, "tunnelledSignallingMessage sequence", HFILL }},
+ { &hf_h225_messageContent_item,
+ { "messageContent_item", "h225.messageContent_item", FT_BYTES, BASE_HEX,
+ NULL, 0, "messageContent_item octet string", HFILL }},
+ { &hf_h225_messageContent,
+ { "messageContent", "h225.messageContent", FT_NONE, BASE_NONE,
+ NULL, 0, "messageContent sequence of", HFILL }},
+ { &hf_h225_H323_UU_PDU,
+ { "H323_UU_PDU", "h225.H323_UU_PDU", FT_NONE, BASE_NONE,
+ NULL, 0, "H323_UU_PDU sequence", HFILL }},
+ { &hf_h225_h4501SupplementaryService,
+ { "h4501SupplementaryService", "h225.h4501SupplementaryService", FT_NONE, BASE_NONE,
+ NULL, 0, "h4501SupplementaryService sequence of", HFILL }},
+ { &hf_h225_h245Tunneling,
+ { "h245Tunneling", "h225.h245Tunneling", FT_BOOLEAN, 8,
+ TFS(&tfs_h245Tunneling_bit), 0x01, "h245Tunneling boolean", HFILL }},
+ { &hf_h225_h245Control,
+ { "h245Control", "h225.h245Control", FT_NONE, BASE_NONE,
+ NULL, 0, "h245Control sequence of", HFILL }},
+ { &hf_h225_nonStandardControl,
+ { "nonStandardControl", "h225.nonStandardControl", FT_NONE, BASE_NONE,
+ NULL, 0, "SEQUENCE OF NonStandardParameter", HFILL }},
+ { &hf_h225_nonStandardControl_item,
+ { "nonStandardControl", "h225.nonStandardControl_item", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardParameter", HFILL }},
+ { &hf_h225_preGrantedARQ,
+ { "preGrantedARQ", "h225.preGrantedARQ", FT_NONE, BASE_NONE,
+ NULL, 0, "preGrantedARQ sequence", HFILL }},
+ { &hf_h225_makeCall,
+ { "makeCall", "h225.makeCall", FT_BOOLEAN, 8,
+ TFS(&tfs_makeCall_bit), 0x01, "makeCall boolean", HFILL }},
+ { &hf_h225_useGKCallSignalAddressToMakeCall,
+ { "useGKCallSignalAddressToMakeCall", "h225.useGKCallSignalAddressToMakeCall", FT_BOOLEAN, 8,
+ TFS(&tfs_useGKCallSignalAddressToMakeCall_bit), 0x01, "useGKCallSignalAddressToMakeCall boolean", HFILL }},
+ { &hf_h225_answerCall,
+ { "answerCall", "h225.answerCall", FT_BOOLEAN, 8,
+ TFS(&tfs_answerCall_bit), 0x01, "answerCall boolean", HFILL }},
+ { &hf_h225_useGKCallSignalAddressToAnswer,
+ { "useGKCallSignalAddressToAnswer", "h225.useGKCallSignalAddressToAnswer", FT_BOOLEAN, 8,
+ TFS(&tfs_useGKCallSignalAddressToAnswer_bit), 0x01, "useGKCallSignalAddressToAnswer boolean", HFILL }},
+ { &hf_h225_RegistrationConfirm,
+ { "RegistrationConfirm", "h225.RegistrationConfirm", FT_NONE, BASE_NONE,
+ NULL, 0, "RegistrationConfirm sequence", HFILL }},
+ { &hf_h225_pdu_item,
+ { "pdu_item", "h225.pdu_item", FT_NONE, BASE_NONE,
+ NULL, 0, "pdu_item sequence", HFILL }},
+ { &hf_h225_sent,
+ { "sent", "h225.sent", FT_BOOLEAN, 8,
+ TFS(&tfs_sent_bit), 0x01, "sent boolean", HFILL }},
+ { &hf_h225_pdu,
+ { "pdu", "h225.pdu", FT_NONE, BASE_NONE,
+ NULL, 0, "pdu sequence of", HFILL }},
+ { &hf_h225_perCallInfo_item,
+ { "perCallInfo_item", "h225.perCallInfo_item", FT_NONE, BASE_NONE,
+ NULL, 0, "perCallInfo_item sequence", HFILL }},
+ { &hf_h225_originator,
+ { "originator", "h225.originator", FT_BOOLEAN, 8,
+ TFS(&tfs_originator_bit), 0x01, "originator boolean", HFILL }},
+ { &hf_h225_audio,
+ { "audio", "h225.audio", FT_NONE, BASE_NONE,
+ NULL, 0, "audio sequence of", HFILL }},
+ { &hf_h225_video,
+ { "video", "h225.video", FT_NONE, BASE_NONE,
+ NULL, 0, "video sequence of", HFILL }},
+ { &hf_h225_data,
+ { "data", "h225.data", FT_NONE, BASE_NONE,
+ NULL, 0, "data sequence of", HFILL }},
+ { &hf_h225_substituteConfIDs,
+ { "substituteConfIDs", "h225.substituteConfIDs", FT_NONE, BASE_NONE,
+ NULL, 0, "substituteConfIDs sequence of", HFILL }},
+ { &hf_h225_perCallInfo,
+ { "perCallInfo", "h225.perCallInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "perCallInfo sequence of", HFILL }},
+ { &hf_h225_InfoRequestResponse,
+ { "InfoRequestResponse", "h225.InfoRequestResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "InfoRequestResponse sequence", HFILL }},
+ { &hf_h225_needResponse,
+ { "needResponse", "h225.needResponse", FT_BOOLEAN, 8,
+ TFS(&tfs_needResponse_bit), 0x01, "needResponse boolean", HFILL }},
+ { &hf_h225_unsolicited,
+ { "unsolicited", "h225.unsolicited", FT_BOOLEAN, 8,
+ TFS(&tfs_unsolicited_bit), 0x01, "unsolicited boolean", HFILL }},
+ { &hf_h225_RasMessage,
+ { "RasMessage", "h225.RasMessage", FT_UINT32, BASE_DEC,
+ VALS(RasMessage_vals), 0, "RasMessage choice", HFILL }},
+ { &hf_h225_H323_UserInformation,
+ { "H323_UserInformation", "h225.H323_UserInformation", FT_NONE, BASE_NONE,
+ NULL, 0, "H323_UserInformation sequence", HFILL }},
+ { &hf_h225_user_data,
+ { "user_data", "h225.user_data", FT_NONE, BASE_NONE,
+ NULL, 0, "user_data sequence", HFILL }},
+ { &hf_h225_protocol_discriminator,
+ { "protocol_discriminator", "h225.protocol_discriminator", FT_UINT32, BASE_DEC,
+ NULL, 0, "protocol_discriminator", HFILL }},
+ { &hf_h225_user_information,
+ { "user_information", "h225.user_information", FT_BYTES, BASE_HEX,
+ NULL, 0, "user_information octet string", HFILL }},
+ { &hf_h225_object,
+ { "object", "h225.object", FT_STRING, BASE_NONE,
+ NULL, 0, "OBJECT IDENTIFIER", HFILL }},
+ { &hf_h225_t35CountryCode,
+ { "t35CountryCode", "h225.t35CountryCode", FT_UINT32, BASE_DEC,
+ VALS(T35CountryCode_vals), 0, "t35CountryCode value", HFILL }},
+ { &hf_h225_t35Extension,
+ { "t35Extension", "h225.t35Extension", FT_UINT32, BASE_DEC,
+ NULL, 0, "t35Extension value", HFILL }},
+ { &hf_h225_manufacturerCode,
+ { "manufacturerCode", "h225.manufacturerCode", FT_UINT32, BASE_DEC,
+ NULL, 0, "manufacturerCode value", HFILL }},
+
+ { &hf_h221Manufacturer,
+ { "H.221 Manufacturer", "h221.Manufacturer", FT_UINT32, BASE_HEX,
+ VALS(H221ManufacturerCode_vals), 0, "H.221 Manufacturer", HFILL }},
+
+ { &hf_h225_h221NonStandard,
+ { "h221NonStandard", "h225.h221NonStandard", FT_NONE, BASE_NONE,
+ NULL, 0, "H221NonStandard SEQUENCE", HFILL }},
+ { &hf_h225_nonStandardIdentifier,
+ { "nonStandardIdentifier", "h245.NonStandardIdentifier_type", FT_UINT32, BASE_DEC,
+ VALS(NonStandardIdentifier_vals), 0, "NonStandardIdentifier CHOICE", HFILL }},
+ { &hf_h225_nsp_data,
+ { "data", "h225.nsp_data", FT_BYTES, BASE_HEX,
+ NULL, 0, "OCTET STRING", HFILL }},
+ { &hf_h225_nonStandardData,
+ { "nonStandardData", "h225.nonStandardData", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardParameter SEQUENCE", HFILL }},
+ { &hf_h225_nonStandard,
+ { "nonStandard", "h225.nonStandard", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardParameter SEQUENCE", HFILL }},
+ { &hf_h225_nonStandardReason,
+ { "nonStandardReason", "h225.nonStandardReason", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardParameter SEQUENCE", HFILL }},
+ { &hf_h225_nonStandardAddress,
+ { "nonStandardAddress", "h225.nonStandardAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardParameter SEQUENCE", HFILL }},
+ { &hf_h225_ras_req_frame,
+ { "RAS Request Frame", "h225.ras.reqframe", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "RAS Request Frame", HFILL }},
+ { &hf_h225_ras_rsp_frame,
+ { "RAS Response Frame", "h225.ras.rspframe", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "RAS Response Frame", HFILL }},
+ { &hf_h225_ras_dup,
+ { "Duplicate RAS Message", "h225.ras.dup", FT_UINT32, BASE_DEC,
+ NULL, 0, "Duplicate RAS Message", HFILL }},
+ { &hf_h225_ras_deltatime,
+ { "RAS Service Response Time", "h225.ras.timedelta", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Timedelta between RAS-Request and RAS-Response", HFILL }},
+ { &hf_h225_cleartoken,
+ { "cleartoken", "h225.cleartoken", FT_NONE, BASE_NONE,
+ NULL, 0, "ClearToken", HFILL }},
+ { &hf_h225_cryptoEPPwdHash,
+ { "cryptoEPPwdHash", "h225.cryptoEPPwdHash",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoH323Token/cryptoEPPwdHash", HFILL }},
+ { &hf_h225_timeStamp,
+ { "timeStamp", "h225.timeStamp",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_h225_token,
+ { "token", "h225.token",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_h225_cryptoGKPwdHash,
+ { "cryptoGKPwdHash", "h225.cryptoGKPwdHash",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoH323Token/cryptoGKPwdHash", HFILL }},
+ { &hf_h225_cryptoEPPwdEncr,
+ { "cryptoEPPwdEncr", "h225.cryptoEPPwdEncr",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoH323Token/cryptoEPPwdEncr", HFILL }},
+ { &hf_h225_cryptoGKPwdEncr,
+ { "cryptoGKPwdEncr", "h225.cryptoGKPwdEncr",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoH323Token/cryptoGKPwdEncr", HFILL }},
+ { &hf_h225_cryptoEPCert,
+ { "cryptoEPCert", "h225.cryptoEPCert",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoH323Token/cryptoEPCert", HFILL }},
+ { &hf_h225_cryptoGKCert,
+ { "cryptoGKCert", "h225.cryptoGKCert",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoH323Token/cryptoGKCert", HFILL }},
+ { &hf_h225_cryptoFastStart,
+ { "cryptoFastStart", "h225.cryptoFastStart",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoH323Token/cryptoFastStart", HFILL }},
+ { &hf_h225_nestedcryptoToken,
+ { "nestedcryptoToken", "h225.nestedcryptoToken",
+ FT_UINT32, BASE_DEC, VALS(CryptoToken_vals), 0,
+ "CryptoH323Token/nestedcryptoToken", HFILL }},
+ { &hf_h225_cryptoTokens_item,
+ { "CryptoH323Token", "h225.cryptoTokens_item",
+ FT_UINT32, BASE_DEC, VALS(CryptoH323Token_vals), 0,
+ "", HFILL }},
+ { &hf_h225_authenticationCapability,
+ { "authenticationCapability", "h225.authenticationCapability",
+ FT_NONE, BASE_DEC, NULL, 0,
+ "GatekeeperRequest/authenticationCapability", HFILL }},
+ { &hf_h225_authenticationCapability_item,
+ { "authenticationCapability", "h225.authenticationCapability_item",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "GatekeeperRequest/authenticationCapability/_item", HFILL }},
+ { &hf_h225_authenticationMode,
+ { "authenticationMode", "h225.authenticationMode",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "GatekeeperConfirm/authenticationMode", HFILL }},
+ { &hf_h225_alertingTime,
+ { "alertingTime", "h225.alertingTime",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "RasUsageInformation/alertingTime", HFILL }},
+ { &hf_h225_connectTime,
+ { "connectTime", "h225.connectTime",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "RasUsageInformation/connectTime", HFILL }},
+ { &hf_h225_endTimeStamp,
+ { "endTime", "h225.endTime",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "RasUsageInformation/endTime", HFILL }},
+
+/*ddd*/
+ };
+
+ static gint *ett[] =
+ {
+ &ett_h225,
+ &ett_h225_SecurityServiceMode_encryption,
+ &ett_h225_SecurityServiceMode_authentication,
+ &ett_h225_SecurityServiceMode_integrity,
+ &ett_h225_H245Security,
+ &ett_h225_ReleaseCompleteReason,
+ &ett_h225_routing,
+ &ett_h225_TransportAddress,
+ &ett_h225_InfoRequestResponseStatus,
+ &ett_h225_systemid,
+ &ett_h225_MobileUIM,
+ &ett_h225_PartyNumber,
+ &ett_h225_AliasAddress,
+ &ett_h225_AddressPattern,
+ &ett_h225_SupportedProtocols,
+ &ett_h225_GenericIdentifier,
+ &ett_h225_Content,
+ &ett_h225_CallTerminationCause,
+ &ett_h225_AdmissionRejectReason,
+ &ett_h225_EncryptIntAlg,
+ &ett_h225_NonIsoIntegrityMechanism,
+ &ett_h225_IntegrityMechanism,
+ &ett_h225_LocationRejectReason,
+ &ett_h225_RegistrationRejectReason,
+ &ett_h225_ServiceControlDescriptor,
+ &ett_h225_h323_message_body,
+ &ett_h225_RasMessage,
+ &ett_h225_GatekeeperRejectReason,
+ &ett_h225_PresentationIndicator,
+ &ett_h225_CryptoH323Token,
+ &ett_h225_conferenceGoal,
+ &ett_h225_ScnConnectionType,
+ &ett_h225_ScnConnectionAggregation,
+ &ett_h225_FacilityReason,
+ &ett_h225_PublicTypeOfNumber,
+ &ett_h225_PrivateTypeOfNumber,
+ &ett_h225_UseSpecifiedTransport,
+ &ett_h225_SecurityErrors,
+ &ett_h225_SecurityErrors2,
+ &ett_h225_ServiceControlSession_reason,
+ &ett_h225_billingMode,
+ &ett_h225_CCSCcallStartingPoint,
+ &ett_h225_UnregRequestReason,
+ &ett_h225_UnregRejectReason,
+ &ett_h225_CallType,
+ &ett_h225_CallModel,
+ &ett_h225_TransportQOS,
+ &ett_h225_BandRejectReason,
+ &ett_h225_DisengageReason,
+ &ett_h225_DisengageRejectReason,
+ &ett_h225_InfoRequestNakReason,
+ &ett_h225_SCRresult,
+ &ett_h225_GatekeeperInfo,
+ &ett_h225_SecurityCapabilities_tls,
+ &ett_h225_SecurityCapabilities_ipsec,
+ &ett_h225_RasUsageInfoTypes,
+ &ett_h225_T_nonStandardUsageTypes,
+ &ett_h225_DataRate,
+ &ett_h225_dataRatesSupported,
+ &ett_h225_TerminalInfo,
+ &ett_h225_StimulusControl,
+ &ett_h225_connectionParameters,
+ &ett_h225_RasUsageSpecification_when,
+ &ett_h225_RasUsageSpecification_callStartingPoint,
+ &ett_h225_RasUsageSpecification,
+ &ett_h225_ipAddress,
+ &ett_h225_route,
+ &ett_h225_ipSourceRoute,
+ &ett_h225_ipxAddress,
+ &ett_h225_ip6Address,
+ &ett_h225_TransportChannelInfo,
+ &ett_h225_CarrierInfo,
+ &ett_h225_CallIdentifier,
+ &ett_h225_CallLinkage,
+ &ett_h225_tokens,
+ &ett_h225_CryptoH323Tokens,
+ &ett_h225_AlternateGK,
+ &ett_h225_alternateGatekeeper,
+ &ett_h225_AltGKInfo,
+ &ett_h225_annexE,
+ &ett_h225_sctp,
+ &ett_h225_AlternateTransportAddress,
+ &ett_h225_UUIEsRequested,
+ &ett_h225_Q954Details,
+ &ett_h225_QseriesOptions,
+ &ett_h225_associatedSessionIds,
+ &ett_h225_RTPSession,
+ &ett_h225_StatusUUIE,
+ &ett_h225_StatusInquiryUUIE,
+ &ett_h225_SetupAcknowledgeUUIE,
+ &ett_h225_NotifyUUIE,
+ &ett_h225_GSMUIM,
+ &ett_h225_ANSI41UIM,
+ &ett_h225_e164Number,
+ &ett_h225_privateNumber,
+ &ett_h225_TunnelledProtocolAlternateIdentifier,
+ &ett_h225_SupportedPrefix,
+ &ett_h225_SupportedPrefixes,
+ &ett_h225_H310Caps,
+ &ett_h225_H320Caps,
+ &ett_h225_H321Caps,
+ &ett_h225_H322Caps,
+ &ett_h225_H323Caps,
+ &ett_h225_H324Caps,
+ &ett_h225_VoiceCaps,
+ &ett_h225_T120OnlyCaps,
+ &ett_h225_NonStandardProtocol,
+ &ett_h225_SIPCaps,
+ &ett_h225_AddressPattern_range,
+ &ett_h225_ConferenceList,
+ &ett_h225_conferences,
+ &ett_h225_T38FaxAnnexbOnlyCaps,
+ &ett_h225_protocol,
+ &ett_h225_GatewayInfo,
+ &ett_h225_McuInfo,
+ &ett_h225_TunnelledProtocol_id,
+ &ett_h225_TunnelledProtocol,
+ &ett_h225_TunnelledProtocols,
+ &ett_h225_CicInfo_cic,
+ &ett_h225_CicInfo,
+ &ett_h225_GroupID_member,
+ &ett_h225_GroupID,
+ &ett_h225_CircuitIdentifier,
+ &ett_h225_EnumeratedParameter,
+ &ett_h225_parameters,
+ &ett_h225_GenericData,
+ &ett_h225_Content_compound,
+ &ett_h225_Content_nested,
+ &ett_h225_neededFeatures,
+ &ett_h225_desiredFeatures,
+ &ett_h225_supportedFeatures,
+ &ett_h225_FeatureSet,
+ &ett_h225_CallsAvailable,
+ &ett_h225_voiceGwCallsAvailable,
+ &ett_h225_h310GwCallsAvailable,
+ &ett_h225_h320GwCallsAvailable,
+ &ett_h225_h321GwCallsAvailable,
+ &ett_h225_h322GwCallsAvailable,
+ &ett_h225_h323GwCallsAvailable,
+ &ett_h225_h324GwCallsAvailable,
+ &ett_h225_t120OnlyGwCallsAvailable,
+ &ett_h225_t38FaxAnnexbOnlyGwCallsAvailable,
+ &ett_h225_terminalCallsAvailable,
+ &ett_h225_mcuCallsAvailable,
+ &ett_h225_sipGwCallsAvailable,
+ &ett_h225_CallCapacityInfo,
+ &ett_h225_CallCapacity,
+ &ett_h225_VendorIdentifier,
+ &ett_h225_CapacityReportingCapability,
+ &ett_h225_CallCreditCapability,
+ &ett_h225_BandwidthDetails,
+ &ett_h225_CircuitInfo,
+ &ett_h225_genericData,
+ &ett_h225_fastStart,
+ &ett_h225_InformationUUIE,
+ &ett_h225_routeCallToSCN,
+ &ett_h225_EndPointType,
+ &ett_h225_CallProceedingUUIE,
+ &ett_h225_CapacityReportingSpecification_when,
+ &ett_h225_CapacityReportingSpecification,
+ &ett_h225_ProgressUUIE,
+ &ett_h225_EndPoint,
+ &ett_h225_destExtraCallInfo,
+ &ett_h225_remoteExtensionAddress,
+ &ett_h225_rasAddress_sequence,
+ &ett_h225_callSignalAddress,
+ &ett_h225_ICV,
+ &ett_h225_BandwidthConfirm,
+ &ett_h225_UnregistrationConfirm,
+ &ett_h225_NonStandardMessage,
+ &ett_h225_InfoRequestAck,
+ &ett_h225_InfoRequestNak,
+ &ett_h225_ResourcesAvailableConfirm,
+ &ett_h225_GatekeeperRequest,
+ &ett_h225_integrity,
+ &ett_h225_algorithmOIDs,
+ &ett_h225_alternateEndpoints,
+ &ett_h225_endpointAlias,
+ &ett_h225_ServiceControlResponse,
+ &ett_h225_DisengageReject,
+ &ett_h225_BandwidthReject,
+ &ett_h225_UnregistrationReject,
+ &ett_h225_UnregistrationRequest,
+ &ett_h225_endpointAliasPattern,
+ &ett_h225_RegistrationReject,
+ &ett_h225_invalidTerminalAliases,
+ &ett_h225_terminalAlias,
+ &ett_h225_terminalAliasPattern,
+ &ett_h225_duplicateAlias,
+ &ett_h225_GatekeeperReject,
+ &ett_h225_ResourcesAvailableIndicate,
+ &ett_h225_protocols,
+ &ett_h225_CallCreditServiceControl,
+ &ett_h225_ExtendedAliasAddress,
+ &ett_h225_UnknownMessageResponse,
+ &ett_h225_AdmissionRequest,
+ &ett_h225_desiredProtocols,
+ &ett_h225_destAlternatives,
+ &ett_h225_srcAlternatives,
+ &ett_h225_srcInfo,
+ &ett_h225_DestinationInfo,
+ &ett_h225_InfoRequest,
+ &ett_h225_RequestInProgress,
+ &ett_h225_ServiceControlSession,
+ &ett_h225_AlertingUUIE,
+ &ett_h225_serviceControl,
+ &ett_h225_alertingAddress,
+ &ett_h225_ReleaseCompleteUUIE,
+ &ett_h225_busyAddress,
+ &ett_h225_FacilityUUIE,
+ &ett_h225_alternativeAliasAddress,
+ &ett_h225_AdmissionReject,
+ &ett_h225_parallelH245Control,
+ &ett_h225_languages,
+ &ett_h225_SetupUUIE,
+ &ett_h225_sourceAddress,
+ &ett_h225_destinationAddress,
+ &ett_h225_destExtraCRV,
+ &ett_h225_h245SecurityCapability,
+ &ett_h225_additionalSourceAddresses,
+ &ett_h225_ConnectUUIE,
+ &ett_h225_connectedAddress,
+ &ett_h225_LocationConfirm,
+ &ett_h225_supportedProtocols,
+ &ett_h225_modifiedSrcInfo,
+ &ett_h225_LocationReject,
+ &ett_h225_callSpecific,
+ &ett_h225_ServiceControlIndication,
+ &ett_h225_RasUsageInformation,
+ &ett_h225_T_nonStandardUsageFields,
+ &ett_h225_GatekeeperConfirm,
+ &ett_h225_RegistrationRequest,
+ &ett_h225_supportedH248Packages,
+ &ett_h225_DisengageConfirm,
+ &ett_h225_AdmissionConfirm,
+ &ett_h225_usageSpec,
+ &ett_h225_DisengageRequest,
+ &ett_h225_LocationRequest,
+ &ett_h225_SourceInfo,
+ &ett_h225_sourceEndpointInfo,
+ &ett_h225_BandwidthRequest,
+ &ett_h225_bandwidthDetails,
+ &ett_h225_admissionConfirmSequence,
+ &ett_h225_tunnelledSignallingMessage,
+ &ett_h225_messageContent,
+ &ett_h225_H323_UU_PDU,
+ &ett_h225_h4501SupplementaryService,
+ &ett_h225_h245Control,
+ &ett_h225_T_nonStandardControl,
+ &ett_h225_preGrantedARQ,
+ &ett_h225_RegistrationConfirm,
+ &ett_h225_pdu_item,
+ &ett_h225_pdu,
+ &ett_h225_perCallInfo_item,
+ &ett_h225_audio,
+ &ett_h225_video,
+ &ett_h225_data,
+ &ett_h225_substituteConfIDs,
+ &ett_h225_perCallInfo,
+ &ett_h225_InfoRequestResponse,
+ &ett_h225_H323_UserInformation,
+ &ett_h225_user_data,
+ &ett_h225_H221NonStandard,
+ &ett_h225_NonStandardIdentifier,
+ &ett_h225_NonStandardParameter,
+ &ett_h225_T_cryptoEPPwdHash,
+ &ett_h225_T_cryptoGKPwdHash,
+ &ett_h225_aliasAddress_sequence,
+ &ett_h225_AuthenticationMechanism_sequence_of,
+/*eee*/
+ };
+ module_t *h225_module;
+
+ proto_h225 = proto_register_protocol("H225", "H225", "h225");
+ proto_register_field_array(proto_h225, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ h225_module = prefs_register_protocol(proto_h225, NULL);
+ prefs_register_bool_preference(h225_module, "reassembly",
+ "Reassemble H.225 over TCP",
+ "Whether the dissector should reassemble H.225 PDUs spanning multiple TCP segments",
+ &h225_reassembly);
+ register_dissector("h225", dissect_h225_H323UserInformation, proto_h225);
+
+ nsp_object_dissector_table = register_dissector_table("h225.nsp.object", "H.225 NonStandardParameter (object)", FT_STRING, BASE_NONE);
+ nsp_h221_dissector_table = register_dissector_table("h225.nsp.h221", "H.225 NonStandardParameter (h221)", FT_UINT32, BASE_HEX);
+ tp_dissector_table = register_dissector_table("h225.tp", "H.225 TunnelledProtocol", FT_STRING, BASE_NONE);
+
+ register_init_routine(&h225_init_routine);
+ h225_tap = register_tap("h225");
+}
+
+void
+proto_reg_handoff_h225(void)
+{
+ h225ras_handle=create_dissector_handle(dissect_h225_RasMessage, proto_h225);
+ H323UserInformation_handle=create_dissector_handle(dissect_h225_H323UserInformation, proto_h225);
+
+ h245_handle = find_dissector("h245");
+ h245dg_handle = find_dissector("h245dg");
+ h4501_handle = find_dissector("h4501");
+ data_handle = find_dissector("data");
+
+ dissector_add("udp.port", UDP_PORT_RAS1, h225ras_handle);
+ dissector_add("udp.port", UDP_PORT_RAS2, h225ras_handle);
+}
+
+
+static void reset_h225_packet_info(h225_packet_info *pi)
+{
+ if(pi == NULL) {
+ return;
+ }
+
+ pi->msg_type = H225_OTHERS;
+ pi->msg_tag = -1;
+ pi->reason = -1;
+ pi->requestSeqNum = 0;
+ memset(pi->guid,0,16);
+ pi->is_duplicate = FALSE;
+ pi->request_available = FALSE;
+}
+
+/*
+ The following function contains the routines for RAS request/response matching.
+ A RAS response matches with a request, if both messages have the same
+ RequestSequenceNumber, belong to the same IP conversation and belong to the same
+ RAS "category" (e.g. Admission, Registration).
+
+ We use hashtables to access the lists of RAS calls (request/response pairs).
+ We have one hashtable for each RAS category. The hashkeys consist of the
+ non-unique 16-bit RequestSequenceNumber and values representing the conversation.
+
+ In big capture files, we might get different requests with identical keys.
+ These requests aren't necessarily duplicates. They might be valid new requests.
+ At the moment we just use the timedelta between the last valid and the new request
+ to decide if the new request is a duplicate or not. There might be better ways.
+ Two thresholds are defined below.
+
+ However the decision is made, another problem arises. We can't just add those
+ requests to our hashtables. Instead we create lists of RAS calls with identical keys.
+ The hashtables for RAS calls contain now pointers to the first RAS call in a list of
+ RAS calls with identical keys.
+ These lists aren't expected to contain more than 3 items and are usually single item
+ lists. So we don't need an expensive but intelligent way to access these lists
+ (e.g. hashtables). Just walk through such a list.
+*/
+
+#define THRESHOLD_REPEATED_RESPONDED_CALL 300
+#define THRESHOLD_REPEATED_NOT_RESPONDED_CALL 1800
+
+static void ras_call_matching(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, h225_packet_info *pi)
+{
+ conversation_t* conversation = NULL;
+ h225ras_call_info_key h225ras_call_key;
+ h225ras_call_t *h225ras_call = NULL;
+ nstime_t delta;
+ guint msg_category;
+
+ if(pi->msg_type == H225_RAS && pi->msg_tag < 21) {
+ /* make RAS request/response matching only for tags from 0 to 20 for now */
+
+ msg_category = pi->msg_tag / 3;
+ if(pi->msg_tag % 3 == 0) { /* Request Message */
+ conversation = find_conversation(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+
+ if (conversation == NULL) {
+ /* It's not part of any conversation - create a new one. */
+ conversation = conversation_new(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+
+ }
+
+ /* prepare the key data */
+ h225ras_call_key.reqSeqNum = pi->requestSeqNum;
+ h225ras_call_key.conversation = conversation;
+
+ /* look up the request */
+ h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
+
+ if (h225ras_call != NULL) {
+ /* We've seen requests with this reqSeqNum, with the same
+ source and destination, before - do we have
+ *this* request already? */
+ /* Walk through list of ras requests with identical keys */
+ do {
+ if (pinfo->fd->num == h225ras_call->req_num) {
+ /* We have seen this request before -> do nothing */
+ break;
+ }
+
+ /* if end of list is reached, exit loop and decide if request is duplicate or not. */
+ if (h225ras_call->next_call == NULL) {
+ if ( (pinfo->fd->num > h225ras_call->rsp_num && h225ras_call->rsp_num != 0
+ && pinfo->fd->abs_secs > (guint) (h225ras_call->req_time.secs + THRESHOLD_REPEATED_RESPONDED_CALL) )
+ ||(pinfo->fd->num > h225ras_call->req_num && h225ras_call->rsp_num == 0
+ && pinfo->fd->abs_secs > (guint) (h225ras_call->req_time.secs + THRESHOLD_REPEATED_NOT_RESPONDED_CALL) ) )
+ {
+ /* if last request has been responded
+ and this request appears after last response (has bigger frame number)
+ and last request occured more than 300 seconds ago,
+ or if last request hasn't been responded
+ and this request appears after last request (has bigger frame number)
+ and last request occured more than 1800 seconds ago,
+ we decide that we have a new request */
+ /* Append new ras call to list */
+ h225ras_call = append_h225ras_call(h225ras_call, pinfo, pi->guid, msg_category);
+ } else {
+ /* No, so it's a duplicate request.
+ Mark it as such. */
+ pi->is_duplicate = TRUE;
+ proto_tree_add_uint_hidden(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
+ }
+ break;
+ }
+ h225ras_call = h225ras_call->next_call;
+ } while (h225ras_call != NULL );
+ }
+ else {
+ h225ras_call = new_h225ras_call(&h225ras_call_key, pinfo, pi->guid, msg_category);
+ }
+
+ /* add link to response frame, if available */
+ if(h225ras_call->rsp_num != 0){
+ proto_item *ti =
+ proto_tree_add_uint_format(tree, hf_h225_ras_rsp_frame, tvb, 0, 0, h225ras_call->rsp_num,
+ "The response to this request is in frame %u",
+ h225ras_call->rsp_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+
+ /* end of request message handling*/
+ }
+ else { /* Confirm or Reject Message */
+ conversation = find_conversation(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (conversation != NULL) {
+ /* look only for matching request, if
+ matching conversation is available. */
+ h225ras_call_key.reqSeqNum = pi->requestSeqNum;
+ h225ras_call_key.conversation = conversation;
+ h225ras_call = find_h225ras_call(&h225ras_call_key ,msg_category);
+ if(h225ras_call) {
+ /* find matching ras_call in list of ras calls with identical keys */
+ do {
+ if (pinfo->fd->num == h225ras_call->rsp_num) {
+ /* We have seen this response before -> stop now with matching ras call */
+ break;
+ }
+
+ /* Break when list end is reached */
+ if(h225ras_call->next_call == NULL) {
+ break;
+ }
+ h225ras_call = h225ras_call->next_call;
+ } while (h225ras_call != NULL) ;
+
+ /* if this is an ACF, ARJ or DCF, DRJ, give guid to tap and make it filterable */
+ if (msg_category == 3 || msg_category == 5) {
+ memcpy(pi->guid, h225ras_call->guid,16);
+ proto_tree_add_bytes_hidden(tree, hf_h225_guid, tvb, 0, 16, pi->guid);
+ }
+
+ if (h225ras_call->rsp_num == 0) {
+ /* We have not yet seen a response to that call, so
+ this must be the first response; remember its
+ frame number. */
+ h225ras_call->rsp_num = pinfo->fd->num;
+ }
+ else {
+ /* We have seen a response to this call - but was it
+ *this* response? */
+ if (h225ras_call->rsp_num != pinfo->fd->num) {
+ /* No, so it's a duplicate response.
+ Mark it as such. */
+ pi->is_duplicate = TRUE;
+ proto_tree_add_uint_hidden(tree, hf_h225_ras_dup, tvb, 0,0, pi->requestSeqNum);
+ }
+ }
+
+ if(h225ras_call->req_num != 0){
+ proto_item *ti;
+ h225ras_call->responded = TRUE;
+ pi->request_available = TRUE;
+
+ /* Indicate the frame to which this is a reply. */
+ ti = proto_tree_add_uint_format(tree, hf_h225_ras_req_frame, tvb, 0, 0, h225ras_call->req_num,
+ "This is a response to a request in frame %u", h225ras_call->req_num);
+ PROTO_ITEM_SET_GENERATED(ti);
+
+ /* Calculate RAS Service Response Time */
+ delta.secs= pinfo->fd->abs_secs-h225ras_call->req_time.secs;
+ delta.nsecs=pinfo->fd->abs_usecs*1000-h225ras_call->req_time.nsecs;
+ if(delta.nsecs<0){
+ delta.nsecs+=1000000000;
+ delta.secs--;
+ }
+ pi->delta_time.secs = delta.secs; /* give it to tap */
+ pi->delta_time.nsecs = delta.nsecs;
+
+ /* display Ras Service Response Time and make it filterable */
+ ti = proto_tree_add_time(tree, hf_h225_ras_deltatime, tvb, 0, 0, &(pi->delta_time));
+ PROTO_ITEM_SET_GENERATED(ti);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/epan/dissectors/packet-h225.h b/epan/dissectors/packet-h225.h
new file mode 100644
index 0000000000..0b2eb3f834
--- /dev/null
+++ b/epan/dissectors/packet-h225.h
@@ -0,0 +1,70 @@
+/* packet-h225.h
+ * Routines for H.225 packet dissection
+ * 2003 Tomas Kukosa
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_H225_H__
+#define __PACKET_H225_H__
+
+extern int dissect_h225_NonStandardParameter(tvbuff_t*, int, packet_info*, proto_tree*, int);
+
+extern int dissect_h225_AliasAddress(tvbuff_t*, int, packet_info*, proto_tree*);
+
+typedef enum _h225_msg_type {
+ H225_RAS,
+ H225_CS,
+ H225_OTHERS
+} h225_msg_type;
+
+typedef struct _h225_packet_info {
+ h225_msg_type msg_type; /* ras or cs message */
+ gint msg_tag; /* message tag*/
+ gint reason; /* reason tag, if available */
+ guint requestSeqNum; /* request sequence number of ras-message, if available */
+ guint8 guid[16]; /* globally unique call id */
+ gboolean is_duplicate; /* true, if this is a repeated message */
+ gboolean request_available; /* true, if response matches to a request */
+ nstime_t delta_time; /* this is the RAS response time delay */
+} h225_packet_info;
+
+/*
+ * the following allows TAP code access to the messages
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string RasMessage_vals[];
+ETH_VAR_IMPORT const value_string h323_message_body_vals[];
+ETH_VAR_IMPORT const value_string FacilityReason_vals[];
+ETH_VAR_IMPORT const value_string GatekeeperRejectReason_vals[];
+ETH_VAR_IMPORT const value_string UnregRequestReason_vals[];
+ETH_VAR_IMPORT const value_string UnregRejectReason_vals[];
+ETH_VAR_IMPORT const value_string BandRejectReason_vals[];
+ETH_VAR_IMPORT const value_string DisengageReason_vals[];
+ETH_VAR_IMPORT const value_string DisengageRejectReason_vals[];
+ETH_VAR_IMPORT const value_string InfoRequestNakReason_vals[];
+ETH_VAR_IMPORT const value_string ReleaseCompleteReason_vals[];
+ETH_VAR_IMPORT const value_string AdmissionRejectReason_vals[];
+ETH_VAR_IMPORT const value_string LocationRejectReason_vals[];
+ETH_VAR_IMPORT const value_string RegistrationRejectReason_vals[];
+
+#endif /* __PACKET_H225_H__ */
diff --git a/epan/dissectors/packet-h235.c b/epan/dissectors/packet-h235.c
new file mode 100644
index 0000000000..e97be14376
--- /dev/null
+++ b/epan/dissectors/packet-h235.c
@@ -0,0 +1,1232 @@
+/* Do not modify this file. */
+/* It is created automatically by the ASN.1 to Ethereal dissector compiler */
+/* packet-h235.c */
+/* ../../tools/asn2eth.py -X -p h235 -c h235.cnf -s packet-h235-template H235-SECURITY-MESSAGES.asn */
+
+/* Input file: packet-h235-template.c */
+/* Include files: packet-h235-hf.c, packet-h235-ett.c, packet-h235-fn.c, packet-h235-hfarr.c, packet-h235-ettarr.c, packet-h235-val.h */
+
+/* packet-h235.c
+ * Routines for H.235 packet dissection
+ * 2004 Tomas Kukosa
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-per.h"
+#include "packet-h235.h"
+
+#define PNAME "H235-SECURITY-MESSAGES"
+#define PSNAME "H235"
+#define PFNAME "h235"
+
+/* Initialize the protocol and registered fields */
+int proto_h235 = -1;
+
+/*--- Included file: packet-h235-hf.c ---*/
+
+/* Do not modify this file. */
+/* It is created automatically by the ASN.1 to Ethereal dissector compiler */
+/* packet-h235-hf.c */
+/* ../../tools/asn2eth.py -X -p h235 -c h235.cnf -s packet-h235-template H235-SECURITY-MESSAGES.asn */
+
+static int hf_h235_nonStandardIdentifier = -1; /* OBJECT_IDENTIFIER */
+static int hf_h235_data = -1; /* OCTET_STRING */
+static int hf_h235_halfkey = -1; /* BIT_STRING_SIZE_0_2048 */
+static int hf_h235_modSize = -1; /* BIT_STRING_SIZE_0_2048 */
+static int hf_h235_generator = -1; /* BIT_STRING_SIZE_0_2048 */
+static int hf_h235_x = -1; /* BIT_STRING_SIZE_0_511 */
+static int hf_h235_y = -1; /* BIT_STRING_SIZE_0_511 */
+static int hf_h235_eckasdhp = -1; /* T_eckasdhp */
+static int hf_h235_public_key = -1; /* ECpoint */
+static int hf_h235_modulus = -1; /* BIT_STRING_SIZE_0_511 */
+static int hf_h235_base = -1; /* ECpoint */
+static int hf_h235_weierstrassA = -1; /* BIT_STRING_SIZE_0_511 */
+static int hf_h235_weierstrassB = -1; /* BIT_STRING_SIZE_0_511 */
+static int hf_h235_eckasdh2 = -1; /* T_eckasdh2 */
+static int hf_h235_fieldSize = -1; /* BIT_STRING_SIZE_0_511 */
+static int hf_h235_type = -1; /* OBJECT_IDENTIFIER */
+static int hf_h235_certificatedata = -1; /* OCTET_STRING */
+static int hf_h235_default = -1; /* NULL */
+static int hf_h235_radius = -1; /* NULL */
+static int hf_h235_dhExch = -1; /* NULL */
+static int hf_h235_pwdSymEnc = -1; /* NULL */
+static int hf_h235_pwdHash = -1; /* NULL */
+static int hf_h235_certSign = -1; /* NULL */
+static int hf_h235_ipsec = -1; /* NULL */
+static int hf_h235_tls = -1; /* NULL */
+static int hf_h235_nonStandard = -1; /* NonStandardParameter */
+static int hf_h235_authenticationBES = -1; /* AuthenticationBES */
+static int hf_h235_tokenOID = -1; /* OBJECT_IDENTIFIER */
+static int hf_h235_timeStamp = -1; /* TimeStamp */
+static int hf_h235_password = -1; /* Password */
+static int hf_h235_dhkey = -1; /* DHset */
+static int hf_h235_challenge = -1; /* ChallengeString */
+static int hf_h235_random = -1; /* RandomVal */
+static int hf_h235_certificate = -1; /* TypedCertificate */
+static int hf_h235_generalID = -1; /* Identifier */
+static int hf_h235_eckasdhkey = -1; /* ECKASDH */
+static int hf_h235_sendersID = -1; /* Identifier */
+static int hf_h235_h235Key = -1; /* H235Key */
+static int hf_h235_toBeSigned = -1; /* ToBeSigned */
+static int hf_h235_algorithmOID = -1; /* OBJECT_IDENTIFIER */
+static int hf_h235_paramS = -1; /* Params */
+static int hf_h235_signaturedata = -1; /* BIT_STRING */
+static int hf_h235_encryptedData = -1; /* OCTET_STRING */
+static int hf_h235_hash = -1; /* BIT_STRING */
+static int hf_h235_ranInt = -1; /* INTEGER */
+static int hf_h235_iv8 = -1; /* IV8 */
+static int hf_h235_iv16 = -1; /* IV16 */
+static int hf_h235_iv = -1; /* OCTET_STRING */
+static int hf_h235_clearSalt = -1; /* OCTET_STRING */
+static int hf_h235_cryptoEncryptedToken = -1; /* T_cryptoEncryptedToken */
+static int hf_h235_encryptedToken = -1; /* ENCRYPTEDxxx */
+static int hf_h235_cryptoSignedToken = -1; /* T_cryptoSignedToken */
+static int hf_h235_signedToken = -1; /* SIGNEDxxx */
+static int hf_h235_cryptoHashedToken = -1; /* T_cryptoHashedToken */
+static int hf_h235_hashedVals = -1; /* ClearToken */
+static int hf_h235_hashedToken = -1; /* HASHEDxxx */
+static int hf_h235_cryptoPwdEncr = -1; /* ENCRYPTEDxxx */
+static int hf_h235_secureChannel = -1; /* KeyMaterial */
+static int hf_h235_sharedSecret = -1; /* ENCRYPTEDxxx */
+static int hf_h235_certProtectedKey = -1; /* SIGNEDxxx */
+static int hf_h235_secureSharedSecret = -1; /* V3KeySyncMaterial */
+static int hf_h235_encryptedSessionKey = -1; /* OCTET_STRING */
+static int hf_h235_encryptedSaltingKey = -1; /* OCTET_STRING */
+static int hf_h235_clearSaltingKey = -1; /* OCTET_STRING */
+static int hf_h235_paramSsalt = -1; /* Params */
+static int hf_h235_keyDerivationOID = -1; /* OBJECT_IDENTIFIER */
+
+/*--- End of included file: packet-h235-hf.c ---*/
+
+
+/* Initialize the subtree pointers */
+
+/*--- Included file: packet-h235-ett.c ---*/
+
+/* Do not modify this file. */
+/* It is created automatically by the ASN.1 to Ethereal dissector compiler */
+/* packet-h235-ett.c */
+/* ../../tools/asn2eth.py -X -p h235 -c h235.cnf -s packet-h235-template H235-SECURITY-MESSAGES.asn */
+
+static gint ett_h235_NonStandardParameter = -1;
+static gint ett_h235_DHset = -1;
+static gint ett_h235_ECpoint = -1;
+static gint ett_h235_ECKASDH = -1;
+static gint ett_h235_T_eckasdhp = -1;
+static gint ett_h235_T_eckasdh2 = -1;
+static gint ett_h235_TypedCertificate = -1;
+static gint ett_h235_AuthenticationBES = -1;
+static gint ett_h235_AuthenticationMechanism = -1;
+static gint ett_h235_ClearToken = -1;
+static gint ett_h235_SIGNEDxxx = -1;
+static gint ett_h235_ENCRYPTEDxxx = -1;
+static gint ett_h235_HASHEDxxx = -1;
+static gint ett_h235_Params = -1;
+static gint ett_h235_CryptoToken = -1;
+static gint ett_h235_T_cryptoEncryptedToken = -1;
+static gint ett_h235_T_cryptoSignedToken = -1;
+static gint ett_h235_T_cryptoHashedToken = -1;
+static gint ett_h235_H235Key = -1;
+static gint ett_h235_V3KeySyncMaterial = -1;
+
+/*--- End of included file: packet-h235-ett.c ---*/
+
+
+static guint32
+dissect_xxx_ToBeSigned(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index _U_) {
+PER_NOT_DECODED_YET("ToBeSigned");
+ return offset;
+}
+
+
+/*--- Included file: packet-h235-fn.c ---*/
+
+/* Do not modify this file. */
+/* It is created automatically by the ASN.1 to Ethereal dissector compiler */
+/* packet-h235-fn.c */
+/* ../../tools/asn2eth.py -X -p h235 -c h235.cnf -s packet-h235-template H235-SECURITY-MESSAGES.asn */
+
+static int dissect_toBeSigned(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_xxx_ToBeSigned(tvb, offset, pinfo, tree, hf_h235_toBeSigned);
+}
+
+static int
+dissect_h235_ChallengeString(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_octet_string(tvb, offset, pinfo, tree, hf_index,
+ 8, 128,
+ NULL, NULL);
+
+ return offset;
+}
+static int dissect_challenge(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_ChallengeString(tvb, offset, pinfo, tree, hf_h235_challenge);
+}
+
+
+
+int
+dissect_h235_TimeStamp(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_index,
+ 1U, 4294967295U, NULL, NULL, FALSE);
+
+ return offset;
+}
+static int dissect_timeStamp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_TimeStamp(tvb, offset, pinfo, tree, hf_h235_timeStamp);
+}
+
+
+
+static int
+dissect_h235_RandomVal(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_integer(tvb, offset, pinfo, tree, hf_index,
+ NULL, NULL);
+
+ return offset;
+}
+static int dissect_random(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_RandomVal(tvb, offset, pinfo, tree, hf_h235_random);
+}
+
+
+static int
+dissect_h235_Password(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_BMPString(tvb, offset, pinfo, tree, hf_index,
+ 1, 128);
+
+ return offset;
+}
+static int dissect_password(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_Password(tvb, offset, pinfo, tree, hf_h235_password);
+}
+
+
+static int
+dissect_h235_Identifier(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_BMPString(tvb, offset, pinfo, tree, hf_index,
+ 1, 128);
+
+ return offset;
+}
+static int dissect_generalID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_Identifier(tvb, offset, pinfo, tree, hf_h235_generalID);
+}
+static int dissect_sendersID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_Identifier(tvb, offset, pinfo, tree, hf_h235_sendersID);
+}
+
+
+static int
+dissect_h235_KeyMaterial(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_bit_string(tvb, offset, pinfo, tree, hf_index,
+ 1, 2048);
+
+ return offset;
+}
+static int dissect_secureChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_KeyMaterial(tvb, offset, pinfo, tree, hf_h235_secureChannel);
+}
+
+
+static int
+dissect_h235_OBJECT_IDENTIFIER(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_index,
+ NULL);
+
+ return offset;
+}
+static int dissect_nonStandardIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OBJECT_IDENTIFIER(tvb, offset, pinfo, tree, hf_h235_nonStandardIdentifier);
+}
+static int dissect_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OBJECT_IDENTIFIER(tvb, offset, pinfo, tree, hf_h235_type);
+}
+static int dissect_tokenOID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OBJECT_IDENTIFIER(tvb, offset, pinfo, tree, hf_h235_tokenOID);
+}
+static int dissect_algorithmOID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OBJECT_IDENTIFIER(tvb, offset, pinfo, tree, hf_h235_algorithmOID);
+}
+static int dissect_keyDerivationOID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OBJECT_IDENTIFIER(tvb, offset, pinfo, tree, hf_h235_keyDerivationOID);
+}
+
+
+static int
+dissect_h235_OCTET_STRING(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_octet_string(tvb, offset, pinfo, tree, hf_index,
+ -1, -1,
+ NULL, NULL);
+
+ return offset;
+}
+static int dissect_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OCTET_STRING(tvb, offset, pinfo, tree, hf_h235_data);
+}
+static int dissect_certificatedata(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OCTET_STRING(tvb, offset, pinfo, tree, hf_h235_certificatedata);
+}
+static int dissect_encryptedData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OCTET_STRING(tvb, offset, pinfo, tree, hf_h235_encryptedData);
+}
+static int dissect_iv(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OCTET_STRING(tvb, offset, pinfo, tree, hf_h235_iv);
+}
+static int dissect_clearSalt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OCTET_STRING(tvb, offset, pinfo, tree, hf_h235_clearSalt);
+}
+static int dissect_encryptedSessionKey(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OCTET_STRING(tvb, offset, pinfo, tree, hf_h235_encryptedSessionKey);
+}
+static int dissect_encryptedSaltingKey(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OCTET_STRING(tvb, offset, pinfo, tree, hf_h235_encryptedSaltingKey);
+}
+static int dissect_clearSaltingKey(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_OCTET_STRING(tvb, offset, pinfo, tree, hf_h235_clearSaltingKey);
+}
+
+static per_sequence_t NonStandardParameter_sequence[] = {
+ { "nonStandardIdentifier" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_nonStandardIdentifier },
+ { "data" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_data },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_NonStandardParameter(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_NonStandardParameter, NonStandardParameter_sequence);
+
+ return offset;
+}
+static int dissect_nonStandard(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_NonStandardParameter(tvb, offset, pinfo, tree, hf_h235_nonStandard);
+}
+
+
+static int
+dissect_h235_BIT_STRING_SIZE_0_2048(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_bit_string(tvb, offset, pinfo, tree, hf_index,
+ 0, 2048);
+
+ return offset;
+}
+static int dissect_halfkey(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING_SIZE_0_2048(tvb, offset, pinfo, tree, hf_h235_halfkey);
+}
+static int dissect_modSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING_SIZE_0_2048(tvb, offset, pinfo, tree, hf_h235_modSize);
+}
+static int dissect_generator(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING_SIZE_0_2048(tvb, offset, pinfo, tree, hf_h235_generator);
+}
+
+static per_sequence_t DHset_sequence[] = {
+ { "halfkey" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_halfkey },
+ { "modSize" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_modSize },
+ { "generator" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_generator },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_DHset(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_DHset, DHset_sequence);
+
+ return offset;
+}
+static int dissect_dhkey(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_DHset(tvb, offset, pinfo, tree, hf_h235_dhkey);
+}
+
+
+static int
+dissect_h235_BIT_STRING_SIZE_0_511(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_bit_string(tvb, offset, pinfo, tree, hf_index,
+ 0, 511);
+
+ return offset;
+}
+static int dissect_x(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING_SIZE_0_511(tvb, offset, pinfo, tree, hf_h235_x);
+}
+static int dissect_y(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING_SIZE_0_511(tvb, offset, pinfo, tree, hf_h235_y);
+}
+static int dissect_modulus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING_SIZE_0_511(tvb, offset, pinfo, tree, hf_h235_modulus);
+}
+static int dissect_weierstrassA(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING_SIZE_0_511(tvb, offset, pinfo, tree, hf_h235_weierstrassA);
+}
+static int dissect_weierstrassB(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING_SIZE_0_511(tvb, offset, pinfo, tree, hf_h235_weierstrassB);
+}
+static int dissect_fieldSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING_SIZE_0_511(tvb, offset, pinfo, tree, hf_h235_fieldSize);
+}
+
+static per_sequence_t ECpoint_sequence[] = {
+ { "x" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_x },
+ { "y" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_y },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_ECpoint(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_ECpoint, ECpoint_sequence);
+
+ return offset;
+}
+static int dissect_public_key(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_ECpoint(tvb, offset, pinfo, tree, hf_h235_public_key);
+}
+static int dissect_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_ECpoint(tvb, offset, pinfo, tree, hf_h235_base);
+}
+
+static per_sequence_t T_eckasdhp_sequence[] = {
+ { "public-key" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_public_key },
+ { "modulus" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_modulus },
+ { "base" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_base },
+ { "weierstrassA" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_weierstrassA },
+ { "weierstrassB" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_weierstrassB },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_T_eckasdhp(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_T_eckasdhp, T_eckasdhp_sequence);
+
+ return offset;
+}
+static int dissect_eckasdhp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_T_eckasdhp(tvb, offset, pinfo, tree, hf_h235_eckasdhp);
+}
+
+static per_sequence_t T_eckasdh2_sequence[] = {
+ { "public-key" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_public_key },
+ { "fieldSize" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_fieldSize },
+ { "base" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_base },
+ { "weierstrassA" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_weierstrassA },
+ { "weierstrassB" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_weierstrassB },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_T_eckasdh2(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_T_eckasdh2, T_eckasdh2_sequence);
+
+ return offset;
+}
+static int dissect_eckasdh2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_T_eckasdh2(tvb, offset, pinfo, tree, hf_h235_eckasdh2);
+}
+
+
+static const value_string ECKASDH_vals[] = {
+ { 0, "eckasdhp" },
+ { 1, "eckasdh2" },
+ { 0, NULL }
+};
+
+static per_choice_t ECKASDH_choice[] = {
+ { 0, "eckasdhp" , ASN1_EXTENSION_ROOT , dissect_eckasdhp },
+ { 1, "eckasdh2" , ASN1_EXTENSION_ROOT , dissect_eckasdh2 },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_h235_ECKASDH(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_ECKASDH, ECKASDH_choice, "ECKASDH",
+ NULL);
+
+ return offset;
+}
+static int dissect_eckasdhkey(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_ECKASDH(tvb, offset, pinfo, tree, hf_h235_eckasdhkey);
+}
+
+static per_sequence_t TypedCertificate_sequence[] = {
+ { "type" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_type },
+ { "certificate" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_certificatedata },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_TypedCertificate(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_TypedCertificate, TypedCertificate_sequence);
+
+ return offset;
+}
+static int dissect_certificate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_TypedCertificate(tvb, offset, pinfo, tree, hf_h235_certificate);
+}
+
+
+static int
+dissect_h235_NULL(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ { proto_item *ti_tmp;
+ ti_tmp = proto_tree_add_item(tree, hf_index, tvb, offset>>8, 0, FALSE);
+ proto_item_append_text(ti_tmp, ": NULL");
+ }
+
+ return offset;
+}
+static int dissect_default(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_NULL(tvb, offset, pinfo, tree, hf_h235_default);
+}
+static int dissect_radius(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_NULL(tvb, offset, pinfo, tree, hf_h235_radius);
+}
+static int dissect_dhExch(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_NULL(tvb, offset, pinfo, tree, hf_h235_dhExch);
+}
+static int dissect_pwdSymEnc(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_NULL(tvb, offset, pinfo, tree, hf_h235_pwdSymEnc);
+}
+static int dissect_pwdHash(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_NULL(tvb, offset, pinfo, tree, hf_h235_pwdHash);
+}
+static int dissect_certSign(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_NULL(tvb, offset, pinfo, tree, hf_h235_certSign);
+}
+static int dissect_ipsec(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_NULL(tvb, offset, pinfo, tree, hf_h235_ipsec);
+}
+static int dissect_tls(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_NULL(tvb, offset, pinfo, tree, hf_h235_tls);
+}
+
+
+static const value_string AuthenticationBES_vals[] = {
+ { 0, "default" },
+ { 1, "radius" },
+ { 0, NULL }
+};
+
+static per_choice_t AuthenticationBES_choice[] = {
+ { 0, "default" , ASN1_EXTENSION_ROOT , dissect_default },
+ { 1, "radius" , ASN1_EXTENSION_ROOT , dissect_radius },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_h235_AuthenticationBES(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_AuthenticationBES, AuthenticationBES_choice, "AuthenticationBES",
+ NULL);
+
+ return offset;
+}
+static int dissect_authenticationBES(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_AuthenticationBES(tvb, offset, pinfo, tree, hf_h235_authenticationBES);
+}
+
+
+const value_string AuthenticationMechanism_vals[] = {
+ { 0, "dhExch" },
+ { 1, "pwdSymEnc" },
+ { 2, "pwdHash" },
+ { 3, "certSign" },
+ { 4, "ipsec" },
+ { 5, "tls" },
+ { 6, "nonStandard" },
+ { 7, "authenticationBES" },
+ { 0, NULL }
+};
+
+static per_choice_t AuthenticationMechanism_choice[] = {
+ { 0, "dhExch" , ASN1_EXTENSION_ROOT , dissect_dhExch },
+ { 1, "pwdSymEnc" , ASN1_EXTENSION_ROOT , dissect_pwdSymEnc },
+ { 2, "pwdHash" , ASN1_EXTENSION_ROOT , dissect_pwdHash },
+ { 3, "certSign" , ASN1_EXTENSION_ROOT , dissect_certSign },
+ { 4, "ipsec" , ASN1_EXTENSION_ROOT , dissect_ipsec },
+ { 5, "tls" , ASN1_EXTENSION_ROOT , dissect_tls },
+ { 6, "nonStandard" , ASN1_EXTENSION_ROOT , dissect_nonStandard },
+ { 7, "authenticationBES" , ASN1_NOT_EXTENSION_ROOT, dissect_authenticationBES },
+ { 0, NULL, 0, NULL }
+};
+
+int
+dissect_h235_AuthenticationMechanism(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_AuthenticationMechanism, AuthenticationMechanism_choice, "AuthenticationMechanism",
+ NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h235_INTEGER(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_integer(tvb, offset, pinfo, tree, hf_index,
+ NULL, NULL);
+
+ return offset;
+}
+static int dissect_ranInt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_INTEGER(tvb, offset, pinfo, tree, hf_h235_ranInt);
+}
+
+
+static int
+dissect_h235_IV8(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_octet_string(tvb, offset, pinfo, tree, hf_index,
+ 8, 8,
+ NULL, NULL);
+
+ return offset;
+}
+static int dissect_iv8(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_IV8(tvb, offset, pinfo, tree, hf_h235_iv8);
+}
+
+
+static int
+dissect_h235_IV16(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_octet_string(tvb, offset, pinfo, tree, hf_index,
+ 16, 16,
+ NULL, NULL);
+
+ return offset;
+}
+static int dissect_iv16(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_IV16(tvb, offset, pinfo, tree, hf_h235_iv16);
+}
+
+static per_sequence_t Params_sequence[] = {
+ { "ranInt" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_ranInt },
+ { "iv8" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_iv8 },
+ { "iv16" , ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL , dissect_iv16 },
+ { "iv" , ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL , dissect_iv },
+ { "clearSalt" , ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL , dissect_clearSalt },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_Params(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_Params, Params_sequence);
+
+ return offset;
+}
+static int dissect_paramS(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_Params(tvb, offset, pinfo, tree, hf_h235_paramS);
+}
+static int dissect_paramSsalt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_Params(tvb, offset, pinfo, tree, hf_h235_paramSsalt);
+}
+
+static per_sequence_t ENCRYPTEDxxx_sequence[] = {
+ { "algorithmOID" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_algorithmOID },
+ { "paramS" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_paramS },
+ { "encryptedData" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_encryptedData },
+ { NULL, 0, 0, NULL }
+};
+
+int
+dissect_h235_ENCRYPTEDxxx(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ proto_tree_add_item_hidden(tree, proto_h235, tvb, offset, 0, FALSE);
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_ENCRYPTEDxxx, ENCRYPTEDxxx_sequence);
+
+ return offset;
+}
+static int dissect_encryptedToken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_ENCRYPTEDxxx(tvb, offset, pinfo, tree, hf_h235_encryptedToken);
+}
+static int dissect_cryptoPwdEncr(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_ENCRYPTEDxxx(tvb, offset, pinfo, tree, hf_h235_cryptoPwdEncr);
+}
+static int dissect_sharedSecret(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_ENCRYPTEDxxx(tvb, offset, pinfo, tree, hf_h235_sharedSecret);
+}
+
+
+static int
+dissect_h235_BIT_STRING(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_bit_string(tvb, offset, pinfo, tree, hf_index,
+ -1, -1);
+
+ return offset;
+}
+static int dissect_signaturedata(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING(tvb, offset, pinfo, tree, hf_h235_signaturedata);
+}
+static int dissect_hash(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_BIT_STRING(tvb, offset, pinfo, tree, hf_h235_hash);
+}
+
+static per_sequence_t SIGNEDxxx_sequence[] = {
+ { "toBeSigned" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_toBeSigned },
+ { "algorithmOID" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_algorithmOID },
+ { "paramS" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_paramS },
+ { "signature" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_signaturedata },
+ { NULL, 0, 0, NULL }
+};
+
+int
+dissect_h235_SIGNEDxxx(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ proto_tree_add_item_hidden(tree, proto_h235, tvb, offset, 0, FALSE);
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_SIGNEDxxx, SIGNEDxxx_sequence);
+
+ return offset;
+}
+static int dissect_signedToken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_SIGNEDxxx(tvb, offset, pinfo, tree, hf_h235_signedToken);
+}
+static int dissect_certProtectedKey(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_SIGNEDxxx(tvb, offset, pinfo, tree, hf_h235_certProtectedKey);
+}
+
+static per_sequence_t V3KeySyncMaterial_sequence[] = {
+ { "generalID" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_generalID },
+ { "algorithmOID" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_algorithmOID },
+ { "paramS" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_paramS },
+ { "encryptedSessionKey" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_encryptedSessionKey },
+ { "encryptedSaltingKey" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_encryptedSaltingKey },
+ { "clearSaltingKey" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_clearSaltingKey },
+ { "paramSsalt" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_paramSsalt },
+ { "keyDerivationOID" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_keyDerivationOID },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_V3KeySyncMaterial(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_V3KeySyncMaterial, V3KeySyncMaterial_sequence);
+
+ return offset;
+}
+static int dissect_secureSharedSecret(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_V3KeySyncMaterial(tvb, offset, pinfo, tree, hf_h235_secureSharedSecret);
+}
+
+
+static const value_string H235Key_vals[] = {
+ { 0, "secureChannel" },
+ { 1, "sharedSecret" },
+ { 2, "certProtectedKey" },
+ { 3, "secureSharedSecret" },
+ { 0, NULL }
+};
+
+static per_choice_t H235Key_choice[] = {
+ { 0, "secureChannel" , ASN1_EXTENSION_ROOT , dissect_secureChannel },
+ { 1, "sharedSecret" , ASN1_EXTENSION_ROOT , dissect_sharedSecret },
+ { 2, "certProtectedKey" , ASN1_EXTENSION_ROOT , dissect_certProtectedKey },
+ { 3, "secureSharedSecret" , ASN1_NOT_EXTENSION_ROOT, dissect_secureSharedSecret },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_h235_H235Key(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_H235Key, H235Key_choice, "H235Key",
+ NULL);
+
+ return offset;
+}
+static int dissect_h235Key(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_H235Key(tvb, offset, pinfo, tree, hf_h235_h235Key);
+}
+
+static per_sequence_t ClearToken_sequence[] = {
+ { "tokenOID" , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_tokenOID },
+ { "timeStamp" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_timeStamp },
+ { "password" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_password },
+ { "dhkey" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_dhkey },
+ { "challenge" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_challenge },
+ { "random" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_random },
+ { "certificate" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_certificate },
+ { "generalID" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_generalID },
+ { "nonStandard" , ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_nonStandard },
+ { "eckasdhkey" , ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL , dissect_eckasdhkey },
+ { "sendersID" , ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL , dissect_sendersID },
+ { "h235Key" , ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL , dissect_h235Key },
+ { NULL, 0, 0, NULL }
+};
+
+int
+dissect_h235_ClearToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ proto_tree_add_item_hidden(tree, proto_h235, tvb, offset, 0, FALSE);
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_ClearToken, ClearToken_sequence);
+
+ return offset;
+}
+static int dissect_hashedVals(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_ClearToken(tvb, offset, pinfo, tree, hf_h235_hashedVals);
+}
+
+static per_sequence_t HASHEDxxx_sequence[] = {
+ { "algorithmOID" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_algorithmOID },
+ { "paramS" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_paramS },
+ { "hash" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_hash },
+ { NULL, 0, 0, NULL }
+};
+
+int
+dissect_h235_HASHEDxxx(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ proto_tree_add_item_hidden(tree, proto_h235, tvb, offset, 0, FALSE);
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_HASHEDxxx, HASHEDxxx_sequence);
+
+ return offset;
+}
+static int dissect_hashedToken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_HASHEDxxx(tvb, offset, pinfo, tree, hf_h235_hashedToken);
+}
+
+static per_sequence_t T_cryptoEncryptedToken_sequence[] = {
+ { "tokenOID" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_tokenOID },
+ { "token" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_encryptedToken },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_T_cryptoEncryptedToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_T_cryptoEncryptedToken, T_cryptoEncryptedToken_sequence);
+
+ return offset;
+}
+static int dissect_cryptoEncryptedToken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_T_cryptoEncryptedToken(tvb, offset, pinfo, tree, hf_h235_cryptoEncryptedToken);
+}
+
+static per_sequence_t T_cryptoSignedToken_sequence[] = {
+ { "tokenOID" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_tokenOID },
+ { "token" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_signedToken },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_T_cryptoSignedToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_T_cryptoSignedToken, T_cryptoSignedToken_sequence);
+
+ return offset;
+}
+static int dissect_cryptoSignedToken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_T_cryptoSignedToken(tvb, offset, pinfo, tree, hf_h235_cryptoSignedToken);
+}
+
+static per_sequence_t T_cryptoHashedToken_sequence[] = {
+ { "tokenOID" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_tokenOID },
+ { "hashedVals" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_hashedVals },
+ { "token" , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_hashedToken },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_h235_T_cryptoHashedToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ offset = dissect_per_sequence(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_T_cryptoHashedToken, T_cryptoHashedToken_sequence);
+
+ return offset;
+}
+static int dissect_cryptoHashedToken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ return dissect_h235_T_cryptoHashedToken(tvb, offset, pinfo, tree, hf_h235_cryptoHashedToken);
+}
+
+
+const value_string CryptoToken_vals[] = {
+ { 0, "cryptoEncryptedToken" },
+ { 1, "cryptoSignedToken" },
+ { 2, "cryptoHashedToken" },
+ { 3, "cryptoPwdEncr" },
+ { 0, NULL }
+};
+
+static per_choice_t CryptoToken_choice[] = {
+ { 0, "cryptoEncryptedToken" , ASN1_EXTENSION_ROOT , dissect_cryptoEncryptedToken },
+ { 1, "cryptoSignedToken" , ASN1_EXTENSION_ROOT , dissect_cryptoSignedToken },
+ { 2, "cryptoHashedToken" , ASN1_EXTENSION_ROOT , dissect_cryptoHashedToken },
+ { 3, "cryptoPwdEncr" , ASN1_EXTENSION_ROOT , dissect_cryptoPwdEncr },
+ { 0, NULL, 0, NULL }
+};
+
+int
+dissect_h235_CryptoToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index) {
+ proto_tree_add_item_hidden(tree, proto_h235, tvb, offset, 0, FALSE);
+ offset = dissect_per_choice(tvb, offset, pinfo, tree, hf_index,
+ ett_h235_CryptoToken, CryptoToken_choice, "CryptoToken",
+ NULL);
+
+ return offset;
+}
+
+
+/*--- End of included file: packet-h235-fn.c ---*/
+
+
+
+/*--- proto_register_h235 ----------------------------------------------*/
+void proto_register_h235(void) {
+
+ /* List of fields */
+ static hf_register_info hf[] = {
+
+/*--- Included file: packet-h235-hfarr.c ---*/
+
+/* Do not modify this file. */
+/* It is created automatically by the ASN.1 to Ethereal dissector compiler */
+/* packet-h235-hfarr.c */
+/* ../../tools/asn2eth.py -X -p h235 -c h235.cnf -s packet-h235-template H235-SECURITY-MESSAGES.asn */
+
+ { &hf_h235_nonStandardIdentifier,
+ { "nonStandardIdentifier", "h235.nonStandardIdentifier",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "NonStandardParameter/nonStandardIdentifier", HFILL }},
+ { &hf_h235_data,
+ { "data", "h235.data",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "NonStandardParameter/data", HFILL }},
+ { &hf_h235_halfkey,
+ { "halfkey", "h235.halfkey",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "DHset/halfkey", HFILL }},
+ { &hf_h235_modSize,
+ { "modSize", "h235.modSize",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "DHset/modSize", HFILL }},
+ { &hf_h235_generator,
+ { "generator", "h235.generator",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "DHset/generator", HFILL }},
+ { &hf_h235_x,
+ { "x", "h235.x",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "ECpoint/x", HFILL }},
+ { &hf_h235_y,
+ { "y", "h235.y",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "ECpoint/y", HFILL }},
+ { &hf_h235_eckasdhp,
+ { "eckasdhp", "h235.eckasdhp",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "ECKASDH/eckasdhp", HFILL }},
+ { &hf_h235_public_key,
+ { "public-key", "h235.public_key",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_h235_modulus,
+ { "modulus", "h235.modulus",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "ECKASDH/eckasdhp/modulus", HFILL }},
+ { &hf_h235_base,
+ { "base", "h235.base",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_h235_weierstrassA,
+ { "weierstrassA", "h235.weierstrassA",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "", HFILL }},
+ { &hf_h235_weierstrassB,
+ { "weierstrassB", "h235.weierstrassB",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "", HFILL }},
+ { &hf_h235_eckasdh2,
+ { "eckasdh2", "h235.eckasdh2",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "ECKASDH/eckasdh2", HFILL }},
+ { &hf_h235_fieldSize,
+ { "fieldSize", "h235.fieldSize",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "ECKASDH/eckasdh2/fieldSize", HFILL }},
+ { &hf_h235_type,
+ { "type", "h235.type",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "TypedCertificate/type", HFILL }},
+ { &hf_h235_certificatedata,
+ { "certificate", "h235.certificate",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "TypedCertificate/certificate", HFILL }},
+ { &hf_h235_default,
+ { "default", "h235.default",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AuthenticationBES/default", HFILL }},
+ { &hf_h235_radius,
+ { "radius", "h235.radius",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AuthenticationBES/radius", HFILL }},
+ { &hf_h235_dhExch,
+ { "dhExch", "h235.dhExch",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AuthenticationMechanism/dhExch", HFILL }},
+ { &hf_h235_pwdSymEnc,
+ { "pwdSymEnc", "h235.pwdSymEnc",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AuthenticationMechanism/pwdSymEnc", HFILL }},
+ { &hf_h235_pwdHash,
+ { "pwdHash", "h235.pwdHash",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AuthenticationMechanism/pwdHash", HFILL }},
+ { &hf_h235_certSign,
+ { "certSign", "h235.certSign",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AuthenticationMechanism/certSign", HFILL }},
+ { &hf_h235_ipsec,
+ { "ipsec", "h235.ipsec",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AuthenticationMechanism/ipsec", HFILL }},
+ { &hf_h235_tls,
+ { "tls", "h235.tls",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AuthenticationMechanism/tls", HFILL }},
+ { &hf_h235_nonStandard,
+ { "nonStandard", "h235.nonStandard",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_h235_authenticationBES,
+ { "authenticationBES", "h235.authenticationBES",
+ FT_UINT32, BASE_DEC, VALS(AuthenticationBES_vals), 0,
+ "AuthenticationMechanism/authenticationBES", HFILL }},
+ { &hf_h235_tokenOID,
+ { "tokenOID", "h235.tokenOID",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_h235_timeStamp,
+ { "timeStamp", "h235.timeStamp",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0,
+ "ClearToken/timeStamp", HFILL }},
+ { &hf_h235_password,
+ { "password", "h235.password",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "ClearToken/password", HFILL }},
+ { &hf_h235_dhkey,
+ { "dhkey", "h235.dhkey",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "ClearToken/dhkey", HFILL }},
+ { &hf_h235_challenge,
+ { "challenge", "h235.challenge",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "ClearToken/challenge", HFILL }},
+ { &hf_h235_random,
+ { "random", "h235.random",
+ FT_INT32, BASE_DEC, NULL, 0,
+ "ClearToken/random", HFILL }},
+ { &hf_h235_certificate,
+ { "certificate", "h235.certificate",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "ClearToken/certificate", HFILL }},
+ { &hf_h235_generalID,
+ { "generalID", "h235.generalID",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_h235_eckasdhkey,
+ { "eckasdhkey", "h235.eckasdhkey",
+ FT_UINT32, BASE_DEC, VALS(ECKASDH_vals), 0,
+ "ClearToken/eckasdhkey", HFILL }},
+ { &hf_h235_sendersID,
+ { "sendersID", "h235.sendersID",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "ClearToken/sendersID", HFILL }},
+ { &hf_h235_h235Key,
+ { "h235Key", "h235.h235Key",
+ FT_UINT32, BASE_DEC, VALS(H235Key_vals), 0,
+ "ClearToken/h235Key", HFILL }},
+ { &hf_h235_toBeSigned,
+ { "toBeSigned", "h235.toBeSigned",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "SIGNEDxxx/toBeSigned", HFILL }},
+ { &hf_h235_algorithmOID,
+ { "algorithmOID", "h235.algorithmOID",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_h235_paramS,
+ { "paramS", "h235.paramS",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_h235_signaturedata,
+ { "signature", "h235.signature",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "SIGNEDxxx/signature", HFILL }},
+ { &hf_h235_encryptedData,
+ { "encryptedData", "h235.encryptedData",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "ENCRYPTEDxxx/encryptedData", HFILL }},
+ { &hf_h235_hash,
+ { "hash", "h235.hash",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "HASHEDxxx/hash", HFILL }},
+ { &hf_h235_ranInt,
+ { "ranInt", "h235.ranInt",
+ FT_INT32, BASE_DEC, NULL, 0,
+ "Params/ranInt", HFILL }},
+ { &hf_h235_iv8,
+ { "iv8", "h235.iv8",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Params/iv8", HFILL }},
+ { &hf_h235_iv16,
+ { "iv16", "h235.iv16",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Params/iv16", HFILL }},
+ { &hf_h235_iv,
+ { "iv", "h235.iv",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Params/iv", HFILL }},
+ { &hf_h235_clearSalt,
+ { "clearSalt", "h235.clearSalt",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Params/clearSalt", HFILL }},
+ { &hf_h235_cryptoEncryptedToken,
+ { "cryptoEncryptedToken", "h235.cryptoEncryptedToken",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoToken/cryptoEncryptedToken", HFILL }},
+ { &hf_h235_encryptedToken,
+ { "token", "h235.token",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoToken/cryptoEncryptedToken/token", HFILL }},
+ { &hf_h235_cryptoSignedToken,
+ { "cryptoSignedToken", "h235.cryptoSignedToken",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoToken/cryptoSignedToken", HFILL }},
+ { &hf_h235_signedToken,
+ { "token", "h235.token",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoToken/cryptoSignedToken/token", HFILL }},
+ { &hf_h235_cryptoHashedToken,
+ { "cryptoHashedToken", "h235.cryptoHashedToken",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoToken/cryptoHashedToken", HFILL }},
+ { &hf_h235_hashedVals,
+ { "hashedVals", "h235.hashedVals",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoToken/cryptoHashedToken/hashedVals", HFILL }},
+ { &hf_h235_hashedToken,
+ { "token", "h235.token",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoToken/cryptoHashedToken/token", HFILL }},
+ { &hf_h235_cryptoPwdEncr,
+ { "cryptoPwdEncr", "h235.cryptoPwdEncr",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "CryptoToken/cryptoPwdEncr", HFILL }},
+ { &hf_h235_secureChannel,
+ { "secureChannel", "h235.secureChannel",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "H235Key/secureChannel", HFILL }},
+ { &hf_h235_sharedSecret,
+ { "sharedSecret", "h235.sharedSecret",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "H235Key/sharedSecret", HFILL }},
+ { &hf_h235_certProtectedKey,
+ { "certProtectedKey", "h235.certProtectedKey",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "H235Key/certProtectedKey", HFILL }},
+ { &hf_h235_secureSharedSecret,
+ { "secureSharedSecret", "h235.secureSharedSecret",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "H235Key/secureSharedSecret", HFILL }},
+ { &hf_h235_encryptedSessionKey,
+ { "encryptedSessionKey", "h235.encryptedSessionKey",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "V3KeySyncMaterial/encryptedSessionKey", HFILL }},
+ { &hf_h235_encryptedSaltingKey,
+ { "encryptedSaltingKey", "h235.encryptedSaltingKey",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "V3KeySyncMaterial/encryptedSaltingKey", HFILL }},
+ { &hf_h235_clearSaltingKey,
+ { "clearSaltingKey", "h235.clearSaltingKey",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "V3KeySyncMaterial/clearSaltingKey", HFILL }},
+ { &hf_h235_paramSsalt,
+ { "paramSsalt", "h235.paramSsalt",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "V3KeySyncMaterial/paramSsalt", HFILL }},
+ { &hf_h235_keyDerivationOID,
+ { "keyDerivationOID", "h235.keyDerivationOID",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "V3KeySyncMaterial/keyDerivationOID", HFILL }},
+
+/*--- End of included file: packet-h235-hfarr.c ---*/
+
+ };
+
+ /* List of subtrees */
+ static gint *ett[] = {
+
+/*--- Included file: packet-h235-ettarr.c ---*/
+
+/* Do not modify this file. */
+/* It is created automatically by the ASN.1 to Ethereal dissector compiler */
+/* packet-h235-ettarr.c */
+/* ../../tools/asn2eth.py -X -p h235 -c h235.cnf -s packet-h235-template H235-SECURITY-MESSAGES.asn */
+
+ &ett_h235_NonStandardParameter,
+ &ett_h235_DHset,
+ &ett_h235_ECpoint,
+ &ett_h235_ECKASDH,
+ &ett_h235_T_eckasdhp,
+ &ett_h235_T_eckasdh2,
+ &ett_h235_TypedCertificate,
+ &ett_h235_AuthenticationBES,
+ &ett_h235_AuthenticationMechanism,
+ &ett_h235_ClearToken,
+ &ett_h235_SIGNEDxxx,
+ &ett_h235_ENCRYPTEDxxx,
+ &ett_h235_HASHEDxxx,
+ &ett_h235_Params,
+ &ett_h235_CryptoToken,
+ &ett_h235_T_cryptoEncryptedToken,
+ &ett_h235_T_cryptoSignedToken,
+ &ett_h235_T_cryptoHashedToken,
+ &ett_h235_H235Key,
+ &ett_h235_V3KeySyncMaterial,
+
+/*--- End of included file: packet-h235-ettarr.c ---*/
+
+ };
+
+ /* Register protocol */
+ proto_h235 = proto_register_protocol(PNAME, PSNAME, PFNAME);
+
+ /* Register fields and subtrees */
+ proto_register_field_array(proto_h235, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+/*--- proto_reg_handoff_h235 -------------------------------------------*/
+void proto_reg_handoff_h235(void) {
+}
+
diff --git a/epan/dissectors/packet-h235.h b/epan/dissectors/packet-h235.h
new file mode 100644
index 0000000000..e5663d4d5d
--- /dev/null
+++ b/epan/dissectors/packet-h235.h
@@ -0,0 +1,59 @@
+/* Do not modify this file. */
+/* It is created automatically by the ASN.1 to Ethereal dissector compiler */
+/* packet-h235.h */
+/* ../../tools/asn2eth.py -X -p h235 -c h235.cnf -s packet-h235-template H235-SECURITY-MESSAGES.asn */
+
+/* Input file: packet-h235-template.h */
+/* Include files: packet-h235-exp.h, packet-h235-valexp.h */
+
+/* packet-h235.h
+ * Routines for H.235 packet dissection
+ * 2004 Tomas Kukosa
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_H235_H
+#define PACKET_H235_H
+
+
+/*--- Included file: packet-h235-exp.h ---*/
+
+/* Do not modify this file. */
+/* It is created automatically by the ASN.1 to Ethereal dissector compiler */
+/* packet-h235-exp.h */
+/* ../../tools/asn2eth.py -X -p h235 -c h235.cnf -s packet-h235-template H235-SECURITY-MESSAGES.asn */
+
+extern const value_string AuthenticationMechanism_vals[];
+extern const value_string CryptoToken_vals[];
+int dissect_h235_TimeStamp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index);
+int dissect_h235_AuthenticationMechanism(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index);
+int dissect_h235_ClearToken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index);
+int dissect_h235_SIGNEDxxx(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index);
+int dissect_h235_ENCRYPTEDxxx(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index);
+int dissect_h235_HASHEDxxx(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index);
+int dissect_h235_CryptoToken(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index);
+
+/*--- End of included file: packet-h235-exp.h ---*/
+
+
+#endif /* PACKET_H235_H */
+
diff --git a/epan/dissectors/packet-h245.c b/epan/dissectors/packet-h245.c
new file mode 100644
index 0000000000..899dab9fb6
--- /dev/null
+++ b/epan/dissectors/packet-h245.c
@@ -0,0 +1,22458 @@
+/* packet-h245.c
+ * Routines for H.245 packet dissection
+ * 2003 Ronnie Sahlberg
+ * with great support with testing and providing capturefiles
+ * from Martin Regner
+ *
+ * Maintained by Andreas Sikkema (h323@ramdyne.nl)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "prefs.h"
+#include "packet-tpkt.h"
+#include "packet-per.h"
+#include "t35.h"
+#include "packet-rtp.h"
+#include "packet-rtcp.h"
+
+static dissector_handle_t rtp_handle=NULL;
+static dissector_handle_t rtcp_handle=NULL;
+
+static dissector_handle_t h245_handle;
+static dissector_handle_t MultimediaSystemControlMessage_handle;
+
+static int proto_h245 = -1; /* h245 over tpkt */
+static int hf_h245_rfc_number = -1;
+static int hf_h245_pdu_type = -1;
+static int hf_h245_DialingInformationNumber_networkAddress = -1;
+static int hf_h245_signalType = -1;
+static int hf_h245_e164Address = -1;
+static int hf_h245_subAddress = -1;
+static int hf_h245_domainBased = -1;
+static int hf_h245_internationalNumber = -1;
+static int hf_h245_IndicationMessage_type = -1;
+static int hf_h245_RequestMessage_type = -1;
+static int hf_h245_ResponseMessage_type = -1;
+static int hf_h245_CommandMessage_type = -1;
+static int hf_h245_PixelAspectCode = -1;
+static int hf_h245_LogicalChannelNumber = -1;
+static int hf_h245_SequenceNumber = -1;
+static int hf_h245_EndSessionCommand_type = -1;
+static int hf_h245_MobileMultilinkReconfigurationIndication = -1;
+static int hf_h245_FlowControlIndication = -1;
+static int hf_h245_UserInputIndication_extendedAlphanumeric = -1;
+static int hf_h245_UserInputIndication_signalUpdate_rtp = -1;
+static int hf_h245_UserInputIndication_signalUpdate = -1;
+static int hf_h245_UserInputIndication_signal_rtp = -1;
+static int hf_h245_UserInputIndication_signal = -1;
+static int hf_h245_NewATMVCIndication_reverseParameters = -1;
+static int hf_h245_NewATMVCIndication_aal_aal5 = -1;
+static int hf_h245_NewATMVCIndication_aal_aal1 = -1;
+static int hf_h245_NewATMVCIndication_aal = -1;
+static int hf_h245_NewATMVCIndication = -1;
+static int hf_h245_VendorIdentification = -1;
+static int hf_h245_MCLocationIndication = -1;
+static int hf_h245_H2250MaximumSkewIndication = -1;
+static int hf_h245_H223SkewIndication = -1;
+static int hf_h245_JitterIndication = -1;
+static int hf_h245_MiscellaneousIndication_type_videoNotDecodedMBs = -1;
+static int hf_h245_MiscellaneousIndication = -1;
+static int hf_h245_VideoIndicateCompose = -1;
+static int hf_h245_TerminalYouAreSeeingInSubPictureNumber = -1;
+static int hf_h245_FunctionNotSupported = -1;
+static int hf_h245_MobileMultilinkReconfigurationCommand = -1;
+static int hf_h245_NewATMVCCommand_reverseParameters = -1;
+static int hf_h245_NewATMVCCommand = -1;
+static int hf_h245_NewATMVCCommand_aal_aal5 = -1;
+static int hf_h245_NewATMVCCommand_aal_aal1 = -1;
+static int hf_h245_EncryptionUpdateRequest = -1;
+static int hf_h245_KeyProtectionMethod = -1;
+static int hf_h245_MiscellaneousCommand_type_lostPartialPicture = -1;
+static int hf_h245_MiscellaneousCommand_type_videoBadMBs = -1;
+static int hf_h245_MiscellaneousCommand_type_progressiveRefinementStart = -1;
+static int hf_h245_MiscellaneousCommand_type_videoFastUpdateMB = -1;
+static int hf_h245_MiscellaneousCommand_type_videoFastUpdateGOB = -1;
+static int hf_h245_MiscellaneousCommand = -1;
+static int hf_h245_SubstituteConferenceIDCommand = -1;
+static int hf_h245_FlowControlCommand = -1;
+static int hf_h245_EncryptionCommand_encryptionAlgorithmID = -1;
+static int hf_h245_SendTerminalCapabilitySet_specificRequest = -1;
+static int hf_h245_LogicalChannelRateRelease = -1;
+static int hf_h245_LogicalChannelRateReject = -1;
+static int hf_h245_LogicalChannelRateAck = -1;
+static int hf_h245_LogicalChannelRateRequest = -1;
+static int hf_h245_ConnectionIdentifier = -1;
+static int hf_h245_DialingInformationNumber = -1;
+static int hf_h245_MultilinkIndication_excessiveError = -1;
+static int hf_h245_MultilinkIndication_crcDesired = -1;
+static int hf_h245_MultilinkResponse_maximumHeaderInterval = -1;
+static int hf_h245_MultilinkResponse_removeConnection = -1;
+static int hf_h245_MultilinkResponse_addConnection = -1;
+static int hf_h245_MultilinkResponse_callInformation = -1;
+static int hf_h245_MultilinkRequest_maximumHeaderInterval = -1;
+static int hf_h245_MultilinkRequest_removeConnection = -1;
+static int hf_h245_MultilinkRequest_addConnection = -1;
+static int hf_h245_MultilinkRequest_callInformation = -1;
+static int hf_h245_TerminalInformation = -1;
+static int hf_h245_RequestAllTerminalIDsResponse = -1;
+static int hf_h245_ConferenceResponse_terminalCertificateResponse = -1;
+static int hf_h245_ConferenceResponse_chairTokenOwnerResponse = -1;
+static int hf_h245_ConferenceResponse_extensionAddressResponse = -1;
+static int hf_h245_ConferenceResponse_passwordResponse = -1;
+static int hf_h245_ConferenceResponse_conferenceIDResponse = -1;
+static int hf_h245_ConferenceResponse_terminalIDResponse = -1;
+static int hf_h245_ConferenceResponse_mCterminalIDResponse = -1;
+static int hf_h245_TerminalLabel = -1;
+static int hf_h245_Criteria = -1;
+static int hf_h245_ConferenceRequest_requestTerminalCertificate = -1;
+static int hf_h245_CommunicationModeTableEntry = -1;
+static int hf_h245_CommunicationModeRequest = -1;
+static int hf_h245_CommunicationModeCommand = -1;
+static int hf_h245_MaintenanceLoopOffCommand = -1;
+static int hf_h245_MaintenanceLoopReject = -1;
+static int hf_h245_MaintenanceLoopAck = -1;
+static int hf_h245_MaintenanceLoopRequest = -1;
+static int hf_h245_RoundTripDelayResponse = -1;
+static int hf_h245_RoundTripDelayRequest = -1;
+static int hf_h245_DataMode_application_t38fax = -1;
+static int hf_h245_DataMode_application_nlpid = -1;
+static int hf_h245_DataMode = -1;
+static int hf_h245_VBDMode = -1;
+static int hf_h245_G7231AnnexCMode_g723AnnexCAudioMode = -1;
+static int hf_h245_G7231AnnexCMode = -1;
+static int hf_h245_IS13818AudioMode = -1;
+static int hf_h245_IS11172AudioMode = -1;
+static int hf_h245_IS11172VideoMode = -1;
+static int hf_h245_H263VideoMode = -1;
+static int hf_h245_H262VideoMode = -1;
+static int hf_h245_H261VideoMode = -1;
+static int hf_h245_RedundancyEncodingMode = -1;
+static int hf_h245_H2250ModeParameters = -1;
+static int hf_h245_H223ModeParameters_adaptationLayerType_al3 = -1;
+static int hf_h245_H223ModeParameters = -1;
+static int hf_h245_FECMode_rfc2733Mode_mode_separateStream_samePort = -1;
+static int hf_h245_FECMode_rfc2733Mode_mode_separateStream_differentPort = -1;
+static int hf_h245_FECMode_rfc2733Mode = -1;
+static int hf_h245_MultiplePayloadStreamElementMode = -1;
+static int hf_h245_MultiplePayloadStreamMode = -1;
+static int hf_h245_RedundancyEncodingDTModeElement = -1;
+static int hf_h245_RedundancyEncodingDTMode = -1;
+static int hf_h245_MultiplexedStreamModeParameters = -1;
+static int hf_h245_H235Mode = -1;
+static int hf_h245_ModeElement = -1;
+static int hf_h245_RequestModeRelease = -1;
+static int hf_h245_RequestModeReject = -1;
+static int hf_h245_RequestModeAck = -1;
+static int hf_h245_RequestMode = -1;
+static int hf_h245_RequestMultiplexEntryRelease = -1;
+static int hf_h245_RequestMultiplexEntryRejectionDescriptions = -1;
+static int hf_h245_RequestMultiplexEntryReject = -1;
+static int hf_h245_RequestMultiplexEntryAck = -1;
+static int hf_h245_RequestMultiplexEntry = -1;
+static int hf_h245_MultiplexEntrySendRelease = -1;
+static int hf_h245_MultiplexEntryRejectionDescriptions = -1;
+static int hf_h245_MultiplexEntrySendReject = -1;
+static int hf_h245_MultiplexEntrySendAck = -1;
+static int hf_h245_MultiplexElement = -1;
+static int hf_h245_MultiplexEntryDescriptor = -1;
+static int hf_h245_MultiplexEntrySend = -1;
+static int hf_h245_RequestChannelCloseRelease = -1;
+static int hf_h245_RequestChannelCloseReject = -1;
+static int hf_h245_RequestChannelCloseAck = -1;
+static int hf_h245_RequestChannelClose = -1;
+static int hf_h245_CloseLogicalChannelAck = -1;
+static int hf_h245_CloseLogicalChannel = -1;
+static int hf_h245_H2250LogicalChannelAckParameters = -1;
+static int hf_h245_OpenLogicalChannelConfirm = -1;
+static int hf_h245_OpenLogicalChannelReject = -1;
+static int hf_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters = -1;
+static int hf_h245_OpenLogicalChannelAck = -1;
+static int hf_h245_EscrowData = -1;
+static int hf_h245_EncryptionSync = -1;
+static int hf_h245_MulticastAddress_iP6Address = -1;
+static int hf_h245_MulticastAddress_iPAddress = -1;
+static int hf_h245_UnicastAddress_iPSourceRouteAddress = -1;
+static int hf_h245_UnicastAddress_iP6Address = -1;
+static int hf_h245_UnicastAddress_iPXAddress = -1;
+static int hf_h245_UnicastAddress_iPAddress = -1;
+static int hf_h245_FECData_rfc2733_mode_separateStream_samePort = -1;
+static int hf_h245_FECData_rfc2733_mode_separateStream_differentPort = -1;
+static int hf_h245_FECData_rfc2733 = -1;
+static int hf_h245_MultiplePayloadStreamElement = -1;
+static int hf_h245_MultiplePayloadStream = -1;
+static int hf_h245_RedundancyEncodingElement = -1;
+static int hf_h245_RedundancyEncoding_rtpRedundancyEncoding = -1;
+static int hf_h245_RedundancyEncoding = -1;
+static int hf_h245_RTPPayloadType = -1;
+static int hf_h245_H2250LogicalChannelParameters = -1;
+static int hf_h245_V76HDLCParameters = -1;
+static int hf_h245_V76LogicalChannelParameters_mode_eRM = -1;
+static int hf_h245_V76LogicalChannelParameters = -1;
+static int hf_h245_H223AnnexCArqParameters = -1;
+static int hf_h245_H223AL3MParameters = -1;
+static int hf_h245_H223AL2MParameters = -1;
+static int hf_h245_H223AL1MParameters = -1;
+static int hf_h245_H223LogicalChannelParameters_adaptionLayerType_al3 = -1;
+static int hf_h245_H223LogicalChannelParameters = -1;
+static int hf_h245_H222LogicalChannelParameters = -1;
+static int hf_h245_MultiplexedStreamParameter = -1;
+static int hf_h245_H235Media = -1;
+static int hf_h245_V75Parameters = -1;
+static int hf_h245_Q2931Address = -1;
+static int hf_h245_NetworkAccessParameters = -1;
+static int hf_h245_reverseLogicalChannelParameters = -1;
+static int hf_h245_forwardLogicalChannelParameters = -1;
+static int hf_h245_OpenLogicalChannel = -1;
+static int hf_h245_FECCapability_rfc2733_separateStream = -1;
+static int hf_h245_FECCapability_rfc2733 = -1;
+static int hf_h245_MultiplePayloadStreamCapability = -1;
+static int hf_h245_NoPTAudioToneCapability = -1;
+static int hf_h245_NoPTAudioTelephonyEventCapability = -1;
+static int hf_h245_AudioToneCapability = -1;
+static int hf_h245_AudioTelephonyEventCapability = -1;
+static int hf_h245_MultiplexedStreamCapability = -1;
+static int hf_h245_GenericParameter = -1;
+static int hf_h245_GenericCapability = -1;
+static int hf_h245_ConferenceCapability = -1;
+static int hf_h245_IntegrityCapability = -1;
+static int hf_h245_AuthenticationCapability = -1;
+static int hf_h245_EncryptionAuthenticationAndIntegrity = -1;
+static int hf_h245_T38FaxTcpOptions = -1;
+static int hf_h245_T38FaxUdpOptions = -1;
+static int hf_h245_T38FaxProfile = -1;
+static int hf_h245_T84Profile_t84Restricted = -1;
+static int hf_h245_V42bis = -1;
+static int hf_h245_DataApplicationCapability_application_t38fax = -1;
+static int hf_h245_DataApplicationCapability_application_nlpid = -1;
+static int hf_h245_DataApplicationCapability_application_t84 = -1;
+static int hf_h245_DataApplicationCapability = -1;
+static int hf_h245_VBDCapability = -1;
+static int hf_h245_GSMAudioCapability = -1;
+static int hf_h245_IS13818AudioCapability = -1;
+static int hf_h245_IS11172AudioCapability = -1;
+static int hf_h245_G7231AnnexCCapability_g723AnnexCAudioMode = -1;
+static int hf_h245_G7231AnnexCCapability = -1;
+static int hf_h245_G729Extensions = -1;
+static int hf_h245_AudioCapability_g7231 = -1;
+static int hf_h245_IS11172VideoCapability = -1;
+static int hf_h245_H263Version3Options = -1;
+static int hf_h245_H263ModeComboFlags = -1;
+static int hf_h245_H263VideoModeCombos = -1;
+static int hf_h245_CustomPictureFormat_pixelAspectInformation_extendedPAR = -1;
+static int hf_h245_CustomPictureFormat_mPI_customPCF = -1;
+static int hf_h245_CustomPictureFormat_mPI = -1;
+static int hf_h245_CustomPictureFormat = -1;
+static int hf_h245_CustomPictureClockFrequency = -1;
+static int hf_h245_RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters = -1;
+static int hf_h245_RefPictureSelection_enhancedReferencePicSelect = -1;
+static int hf_h245_RefPictureSelection_additionalPictureMemory = -1;
+static int hf_h245_RefPictureSelection = -1;
+static int hf_h245_TransperencyParameters = -1;
+static int hf_h245_H263Options = -1;
+static int hf_h245_EnhancementOptions = -1;
+static int hf_h245_BEnhancementParameters = -1;
+static int hf_h245_EnhancementLayerInfo = -1;
+static int hf_h245_H263VideoCapability = -1;
+static int hf_h245_H262VideoCapability = -1;
+static int hf_h245_H261VideoCapability = -1;
+static int hf_h245_MediaDistributionCapability = -1;
+static int hf_h245_MultipointCapability = -1;
+static int hf_h245_receiveMultipointCapability = -1;
+static int hf_h245_transmitMultipointCapability = -1;
+static int hf_h245_receiveAndTransmitMultipointCapability = -1;
+static int hf_h245_RTPH263VideoRedundancyFrameMapping = -1;
+static int hf_h245_RTPH263VideoRedundancyEncoding = -1;
+static int hf_h245_RedundancyEncodingCapability = -1;
+static int hf_h245_TransportCapability = -1;
+static int hf_h245_MediaChannelCapability = -1;
+static int hf_h245_MediaTransportType_AtmAAL5Compressed = -1;
+static int hf_h245_QOSCapability = -1;
+static int hf_h245_ATMParameters = -1;
+static int hf_h245_RSVPParameters = -1;
+static int hf_h245_MediaPacketizationCapability = -1;
+static int hf_h245_H2250Capability_mcCapability = -1;
+static int hf_h245_H2250Capability = -1;
+static int hf_h245_V75Capability = -1;
+static int hf_h245_V76Capability = -1;
+static int hf_h245_H223AnnexCCapability = -1;
+static int hf_h245_H223Capability_mobileMultilinkFrameCapability = -1;
+static int hf_h245_H223Capability_mobileOperationTransmitCapability = -1;
+static int hf_h245_H223Capability_h223MultiplexTableCapability_enhanced = -1;
+static int hf_h245_H223Capability = -1;
+static int hf_h245_VCCapability_aal1ViaGateway = -1;
+static int hf_h245_VCCapability_availableBitRates_rangeOfBitRates = -1;
+static int hf_h245_VCCapability_availableBitRates = -1;
+static int hf_h245_VCCapability_aal5 = -1;
+static int hf_h245_VCCapability_aal1 = -1;
+static int hf_h245_VCCapability = -1;
+static int hf_h245_H222Capability = -1;
+static int hf_h245_H235SecurityCapability = -1;
+static int hf_h245_Capability_h233EncryptionReceiveCapability = -1;
+static int hf_h245_TerminalCapabilitySetRelease = -1;
+static int hf_h245_TerminalCapabilitySetReject = -1;
+static int hf_h245_TerminalCapabilitySetAck = -1;
+static int hf_h245_CapabilityDescriptor = -1;
+static int hf_h245_CapabilityTableEntry = -1;
+static int hf_h245_TerminalCapabilitySet = -1;
+static int hf_h245_MasterSlaveDeterminationRelease = -1;
+static int hf_h245_MasterSlaveDeterminationReject = -1;
+static int hf_h245_MasterSlaveDeterminationAck = -1;
+static int hf_h245_MasterSlaveDetermination = -1;
+static int hf_h245_h221NonStandard = -1;
+static int hf_h245_NonStandardParameter = -1;
+static int hf_h245_NonStandardMessage = -1;
+static int hf_h245_FlowControlIndication_restriction = -1;
+static int hf_h245_FlowControlIndication_scope = -1;
+static int hf_h245_UserInputIndication_userInputSupportIndication = -1;
+static int hf_h245_UserInputIndication = -1;
+static int hf_h245_NewATMVCIndication_reverseParameters_multiplex = -1;
+static int hf_h245_NewATMVCIndication_multiplex = -1;
+static int hf_h245_NewATMVCIndication_aal_aal1_errorCorrection = -1;
+static int hf_h245_NewATMVCIndication_aal_aal1_clockRecovery = -1;
+static int hf_h245_JitterIndication_scope = -1;
+static int hf_h245_MiscellaneousIndication_type = -1;
+static int hf_h245_ConferenceIndication = -1;
+static int hf_h245_FunctionNotSupported_cause = -1;
+static int hf_h245_FunctionNotUnderstood = -1;
+static int hf_h245_MobileMultilinkReconfigurationCommand_status = -1;
+static int hf_h245_NewATMVCCommand_reverseParameters_multiplex = -1;
+static int hf_h245_NewATMVCCommand_multiplex = -1;
+static int hf_h245_NewATMVCCommand_aal_aal1_errorCorrection = -1;
+static int hf_h245_NewATMVCCommand_aal_aal1_clockRecovery = -1;
+static int hf_h245_NewATMVCCommand_aal = -1;
+static int hf_h245_H223MultiplexReconfiguration_h223AnnexADoubleFlag = -1;
+static int hf_h245_H223MultiplexReconfiguration_h223ModeChange = -1;
+static int hf_h245_H223MultiplexReconfiguration = -1;
+static int hf_h245_PictureReference = -1;
+static int hf_h245_MiscellaneousCommand_type_progressiveRefinementStart_repeatCount = -1;
+static int hf_h245_MiscellaneousCommand_type = -1;
+static int hf_h245_ConferenceCommand = -1;
+static int hf_h245_EndSessionCommand_gstnOptions = -1;
+static int hf_h245_EndSessionCommand_isdnOptions = -1;
+static int hf_h245_FlowControlCommand_restriction = -1;
+static int hf_h245_FlowControlCommand_scope = -1;
+static int hf_h245_EncryptionCommand = -1;
+static int hf_h245_SendTerminalCapabilitySet = -1;
+static int hf_h245_LogicalChannelRateRejectReason = -1;
+static int hf_h245_DialingInformationNetworkType = -1;
+static int hf_h245_DialingInformation = -1;
+static int hf_h245_MultilinkIndication = -1;
+static int hf_h245_MultilinkResponse_addConnection_responseCode_rejected = -1;
+static int hf_h245_MultilinkResponse_addConnection_responseCode = -1;
+static int hf_h245_MultilinkResponse = -1;
+static int hf_h245_MultilinkRequest_maximumHeaderInterval_requestType = -1;
+static int hf_h245_MultilinkRequest = -1;
+static int hf_h245_RemoteMCResponse_reject = -1;
+static int hf_h245_RemoteMCResponse = -1;
+static int hf_h245_RemoteMCRequest = -1;
+static int hf_h245_ConferenceResponse_sendThisSourceResponse = -1;
+static int hf_h245_ConferenceResponse_makeTerminalBroadcasterResponse = -1;
+static int hf_h245_ConferenceResponse_broadcastMyLogicalChannelResponse = -1;
+static int hf_h245_ConferenceResponse_makeMeChairResponse = -1;
+static int hf_h245_ConferenceResponse = -1;
+static int hf_h245_ConferenceRequest = -1;
+static int hf_h245_CommunicationModeTableEntry_dataType = -1;
+static int hf_h245_CommunicationModeResponse = -1;
+static int hf_h245_MaintenanceLoopReject_cause = -1;
+static int hf_h245_MaintenanceLoopReject_type = -1;
+static int hf_h245_MaintenanceLoopAck_type = -1;
+static int hf_h245_MaintenanceLoopRequest_type = -1;
+static int hf_h245_EncryptionMode = -1;
+static int hf_h245_DataMode_application = -1;
+static int hf_h245_IS13818AudioMode_multiChannelType = -1;
+static int hf_h245_IS13818AudioMode_audioSampling = -1;
+static int hf_h245_IS13818AudioMode_audioLayer = -1;
+static int hf_h245_IS11172AudioMode_multichannelType = -1;
+static int hf_h245_IS11172AudioMode_audioSampling = -1;
+static int hf_h245_IS11172AudioMode_audioLayer = -1;
+static int hf_h245_AudioMode_g7231 = -1;
+static int hf_h245_AudioMode = -1;
+static int hf_h245_H263VideoMode_resolution = -1;
+static int hf_h245_H262VideoMode_profileAndLevel = -1;
+static int hf_h245_H261VideoMode_resolution = -1;
+static int hf_h245_VideoMode = -1;
+static int hf_h245_RedundancyEncodingMode_secondaryEncoding = -1;
+static int hf_h245_V76ModeParameters = -1;
+static int hf_h245_H223ModeParameters_adaptationLayerType = -1;
+static int hf_h245_FECMode_rfc2733Mode_mode_separateStream = -1;
+static int hf_h245_FECMode_rfc2733Mode_mode = -1;
+static int hf_h245_FECMode = -1;
+static int hf_h245_RedundancyEncodingDTModeElement_type = -1;
+static int hf_h245_H235Mode_mediaMode = -1;
+static int hf_h245_ModeElementType = -1;
+static int hf_h245_RequestModeReject_cause = -1;
+static int hf_h245_RequestMultiplexEntryRejectionDescriptions_cause = -1;
+static int hf_h245_MultiplexEntryRejectionDescriptions_cause = -1;
+static int hf_h245_MultiplexElement_repeatCount = -1;
+static int hf_h245_MultiplexElement_type = -1;
+static int hf_h245_RequestChannelCloseReject_cause = -1;
+static int hf_h245_RequestChannelClose_reason = -1;
+static int hf_h245_CloseLogicalChannel_reason = -1;
+static int hf_h245_CloseLogicalChannel_source = -1;
+static int hf_h245_OpenLogicalChannelReject_cause = -1;
+static int hf_h245_forwardMultiplexAckParameters = -1;
+static int hf_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters = -1;
+static int hf_h245_MulticastAddress = -1;
+static int hf_h245_UnicastAddress_iPSourceRouteAddress_routing = -1;
+static int hf_h245_UnicastAddress = -1;
+static int hf_h245_mediaControlChannel = -1;
+static int hf_h245_localAreaAddress = -1;
+static int hf_h245_mediaChannel = -1;
+static int hf_h245_signalAddress = -1;
+static int hf_h245_FECData_rfc2733_mode_separateStream = -1;
+static int hf_h245_FECData_rfc2733_mode = -1;
+static int hf_h245_FECData = -1;
+static int hf_h245_RTPPayloadType_payloadDescriptor = -1;
+static int hf_h245_H2250LogicalChannelParameters_mediaPacketization = -1;
+static int hf_h245_CRCLength = -1;
+static int hf_h245_V76LogicalChannelParameters_mode_eRM_recovery = -1;
+static int hf_h245_V76LogicalChannelParameters_mode = -1;
+static int hf_h245_V76LogicalChannelParameters_suspendResume = -1;
+static int hf_h245_H223AnnexCArqParameters_numberOfRetransmissions = -1;
+static int hf_h245_H223AL3MParameters_arqType = -1;
+static int hf_h245_H223AL3MParameters_crcLength = -1;
+static int hf_h245_H223AL3MParameters_headerFormat = -1;
+static int hf_h245_H223AL2MParameters_headerFEC = -1;
+static int hf_h245_H223AL1MParameters_arqType = -1;
+static int hf_h245_H223AL1MParameters_crcLength = -1;
+static int hf_h245_H223AL1MParameters_headerFEC = -1;
+static int hf_h245_H223AL1MParameters_transferMode = -1;
+static int hf_h245_H223LogicalChannelParameters_adaptationLayerType = -1;
+static int hf_h245_H235Media_mediaType = -1;
+static int hf_h245_DataType = -1;
+static int hf_h245_Q2931Address_address = -1;
+static int hf_h245_NetworkAccessParameters_t120SetupProcedure = -1;
+static int hf_h245_NetworkAccessParameters_networkAddress = -1;
+static int hf_h245_NetworkAccessParameters_distribution = -1;
+static int hf_h245_reverseLogicalChannelParameters_multiplexParameters = -1;
+static int hf_h245_forwardLogicalChannelParameters_multiplexParameters = -1;
+static int hf_h245_FECCapability = -1;
+static int hf_h245_MultiplexFormat = -1;
+static int hf_h245_ParameterValue = -1;
+static int hf_h245_ParameterIdentifier = -1;
+static int hf_h245_CapabilityIdentifier = -1;
+static int hf_h245_UserInputCapability = -1;
+static int hf_h245_MediaEncryptionAlgorithm = -1;
+static int hf_h245_T38FaxUdpOptions_t38FaxUdpEC = -1;
+static int hf_h245_T38FaxRateManagement = -1;
+static int hf_h245_T84Profile = -1;
+static int hf_h245_CompressionType = -1;
+static int hf_h245_DataProtocolCapability_v76wCompression = -1;
+static int hf_h245_DataProtocolCapability = -1;
+static int hf_h245_DataApplicationCapability_application = -1;
+static int hf_h245_AudioCapability = -1;
+static int hf_h245_CustomPictureFormat_pixelAspectInformation = -1;
+static int hf_h245_RefPictureSelection_videoBackChannelSend = -1;
+static int hf_h245_VideoCapability = -1;
+static int hf_h245_RTPH263VideoRedundancyEncoding_frameToThreadMapping = -1;
+static int hf_h245_RedundancyEncodingMethod = -1;
+static int hf_h245_MediaTransportType = -1;
+static int hf_h245_QOSMode = -1;
+static int hf_h245_H223Capability_h223MultiplexTableCapability = -1;
+static int hf_h245_VCCapability_availableBitRates_type = -1;
+static int hf_h245_MultiplexCapability = -1;
+static int hf_h245_Capability = -1;
+static int hf_h245_TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded = -1;
+static int hf_h245_TerminalCapabilitySetReject_cause = -1;
+static int hf_h245_MasterSlaveDeterminationReject_cause = -1;
+static int hf_h245_MasterSlaveDeterminationAck_decision = -1;
+static int hf_h245_RequestModeAck_response_decision = -1;
+static int hf_h245_NonStandardIdentifier = -1;
+static int hf_h245_h233EncryptionTransmitCapability = -1;
+static int hf_h245_nullClockRecovery = -1;
+static int hf_h245_srtsClockRecovery = -1;
+static int hf_h245_adaptiveClockRecovery = -1;
+static int hf_h245_nullErrorCorrection = -1;
+static int hf_h245_longInterleaver = -1;
+static int hf_h245_shortInterleaver = -1;
+static int hf_h245_errorCorrectionOnly = -1;
+static int hf_h245_structuredDataTransfer = -1;
+static int hf_h245_partiallyFilledCells = -1;
+static int hf_h245_transportStream = -1;
+static int hf_h245_programStream = -1;
+static int hf_h245_transportWithIframes = -1;
+static int hf_h245_videoWithAL1 = -1;
+static int hf_h245_videoWithAL2 = -1;
+static int hf_h245_videoWithAL3 = -1;
+static int hf_h245_audioWithAL1 = -1;
+static int hf_h245_audioWithAL2 = -1;
+static int hf_h245_audioWithAL3 = -1;
+static int hf_h245_dataWithAL1 = -1;
+static int hf_h245_dataWithAL2 = -1;
+static int hf_h245_dataWithAL3 = -1;
+static int hf_h245_maxMUXPDUSizeCapability = -1;
+static int hf_h245_nsrpSupport = -1;
+static int hf_h245_modeChangeCapability = -1;
+static int hf_h245_h223AnnexA = -1;
+static int hf_h245_h223AnnexADoubleFlag_bool = -1;
+static int hf_h245_h223AnnexB = -1;
+static int hf_h245_h223AnnexBwithHeader = -1;
+static int hf_h245_videoWithAL1M = -1;
+static int hf_h245_videoWithAL2M = -1;
+static int hf_h245_videoWithAL3M = -1;
+static int hf_h245_audioWithAL1M = -1;
+static int hf_h245_audioWithAL2M = -1;
+static int hf_h245_audioWithAL3M = -1;
+static int hf_h245_dataWithAL1M = -1;
+static int hf_h245_dataWithAL2M = -1;
+static int hf_h245_dataWithAL3M = -1;
+static int hf_h245_alpduInterleaving = -1;
+static int hf_h245_rsCodeCapability = -1;
+static int hf_h245_suspendResumeCapabilitywAddress = -1;
+static int hf_h245_suspendResumeCapabilitywoAddress = -1;
+static int hf_h245_rejCapability = -1;
+static int hf_h245_sREJCapability = -1;
+static int hf_h245_mREJCapability = -1;
+static int hf_h245_crc8bitCapability = -1;
+static int hf_h245_crc16bitCapability = -1;
+static int hf_h245_crc32bitCapability = -1;
+static int hf_h245_uihCapability = -1;
+static int hf_h245_twoOctetAddressFieldCapability = -1;
+static int hf_h245_loopBackTestCapability = -1;
+static int hf_h245_audioHeader = -1;
+static int hf_h245_centralizedConferenceMC = -1;
+static int hf_h245_decentralizedConferenceMC = -1;
+static int hf_h245_rtcpVideoControlCapability = -1;
+static int hf_h245_logicalChannelSwitchingCapability = -1;
+static int hf_h245_t120DynamicPortCapability = -1;
+static int hf_h245_h261aVideoPacketization = -1;
+static int hf_h245_atmUBR = -1;
+static int hf_h245_atmrtVBR = -1;
+static int hf_h245_atmnrtVBR = -1;
+static int hf_h245_atmABR = -1;
+static int hf_h245_atmCBR = -1;
+static int hf_h245_variableDelta = -1;
+static int hf_h245_multicastCapability = -1;
+static int hf_h245_multiUniCastConference = -1;
+static int hf_h245_centralizedControl = -1;
+static int hf_h245_distributedControl = -1;
+static int hf_h245_centralizedAudio = -1;
+static int hf_h245_distributedAudio = -1;
+static int hf_h245_centralizedVideo = -1;
+static int hf_h245_distributedVideo = -1;
+static int hf_h245_temporalSpatialTradeOffCapability = -1;
+static int hf_h245_stillImageTransmission = -1;
+static int hf_h245_videoBadMBsCap = -1;
+static int hf_h245_profileAndLevelSPatML = -1;
+static int hf_h245_profileAndLevelMPatLL = -1;
+static int hf_h245_profileAndLevelMPatML = -1;
+static int hf_h245_profileAndLevelMPatH14 = -1;
+static int hf_h245_profileAndLevelMPatHL = -1;
+static int hf_h245_profileAndLevelSNRatLL = -1;
+static int hf_h245_profileAndLevelSNRatML = -1;
+static int hf_h245_profileAndLevelSpatialatH14 = -1;
+static int hf_h245_profileAndLevelHPatML = -1;
+static int hf_h245_profileAndLevelHPatH14 = -1;
+static int hf_h245_profileAndLevelHPatHL = -1;
+static int hf_h245_unrestrictedVector = -1;
+static int hf_h245_arithmeticCoding = -1;
+static int hf_h245_advancedPrediction = -1;
+static int hf_h245_pbFrames = -1;
+static int hf_h245_errorCompensation = -1;
+static int hf_h245_baseBitRateConstrained = -1;
+static int hf_h245_advancedIntraCodingMode = -1;
+static int hf_h245_deblockingFilterMode = -1;
+static int hf_h245_improvedPBFramesMode = -1;
+static int hf_h245_unlimitedMotionVectors = -1;
+static int hf_h245_fullPictureFreeze = -1;
+static int hf_h245_partialPictureFreezeAndRelease = -1;
+static int hf_h245_resizingPartPicFreezeAndRelease = -1;
+static int hf_h245_fullPictureSnapshot = -1;
+static int hf_h245_partialPictureSnapshot = -1;
+static int hf_h245_videoSegmentTagging = -1;
+static int hf_h245_progressiveRefinement = -1;
+static int hf_h245_dynamicPictureResizingByFour = -1;
+static int hf_h245_dynamicPictureResizingSixteenthPel = -1;
+static int hf_h245_dynamicWarpingHalfPel = -1;
+static int hf_h245_dynamicWarpingSixteenthPel = -1;
+static int hf_h245_independentSegmentDecoding = -1;
+static int hf_h245_slicesInOrderNonRect = -1;
+static int hf_h245_slicesInOrderRect = -1;
+static int hf_h245_slicesNoOrderNonRect = -1;
+static int hf_h245_slicesNoOrderRect = -1;
+static int hf_h245_alternateInterVLCMode = -1;
+static int hf_h245_modifiedQuantizationMode = -1;
+static int hf_h245_reducedResolutionUpdate = -1;
+static int hf_h245_separateVideoBackChannel = -1;
+static int hf_h245_videoMux = -1;
+static int hf_h245_anyPixelAspectRatio = -1;
+static int hf_h245_referencePicSelect = -1;
+static int hf_h245_enhancedReferencePicSelect_bool = -1;
+static int hf_h245_dataPartitionedSlices = -1;
+static int hf_h245_fixedPointIDCT0 = -1;
+static int hf_h245_interlacedFields = -1;
+static int hf_h245_currentPictureHeaderRepetition = -1;
+static int hf_h245_previousPictureHeaderRepetition = -1;
+static int hf_h245_nextPictureHeaderRepetition = -1;
+static int hf_h245_pictureNumber_bool = -1;
+static int hf_h245_spareReferencePictures = -1;
+static int hf_h245_constrainedBitstream = -1;
+static int hf_h245_silenceSuppression = -1;
+static int hf_h245_annexA = -1;
+static int hf_h245_annexB = -1;
+static int hf_h245_annexD = -1;
+static int hf_h245_annexE = -1;
+static int hf_h245_annexF = -1;
+static int hf_h245_annexG = -1;
+static int hf_h245_annexH = -1;
+static int hf_h245_audioLayer1 = -1;
+static int hf_h245_audioLayer2 = -1;
+static int hf_h245_audioLayer3 = -1;
+static int hf_h245_audioSampling32k = -1;
+static int hf_h245_audioSampling44k1 = -1;
+static int hf_h245_audioSampling48k = -1;
+static int hf_h245_singleChannel = -1;
+static int hf_h245_twoChannels = -1;
+static int hf_h245_audioSampling16k = -1;
+static int hf_h245_audioSampling22k05 = -1;
+static int hf_h245_audioSampling24k = -1;
+static int hf_h245_threeChannels21 = -1;
+static int hf_h245_threeChannels30 = -1;
+static int hf_h245_fourChannels2020 = -1;
+static int hf_h245_fourChannels22 = -1;
+static int hf_h245_fourChannels31 = -1;
+static int hf_h245_fiveChannels3020 = -1;
+static int hf_h245_fiveChannels32 = -1;
+static int hf_h245_lowFrequencyEnhancement = -1;
+static int hf_h245_multilingual = -1;
+static int hf_h245_comfortNoise = -1;
+static int hf_h245_scrambled = -1;
+static int hf_h245_qcif_bool = -1;
+static int hf_h245_cif_bool = -1;
+static int hf_h245_ccir601Seq = -1;
+static int hf_h245_ccir601Prog = -1;
+static int hf_h245_hdtvSeq = -1;
+static int hf_h245_hdtvProg = -1;
+static int hf_h245_g3FacsMH200x100 = -1;
+static int hf_h245_g3FacsMH200x200 = -1;
+static int hf_h245_g4FacsMMR200x100 = -1;
+static int hf_h245_g4FacsMMR200x200 = -1;
+static int hf_h245_jbig200x200Seq = -1;
+static int hf_h245_jbig200x200Prog = -1;
+static int hf_h245_jbig300x300Seq = -1;
+static int hf_h245_jbig300x300Prog = -1;
+static int hf_h245_digPhotoLow = -1;
+static int hf_h245_digPhotoMedSeq = -1;
+static int hf_h245_digPhotoMedProg = -1;
+static int hf_h245_digPhotoHighSeq = -1;
+static int hf_h245_digPhotoHighProg = -1;
+static int hf_h245_fillBitRemoval = -1;
+static int hf_h245_transcodingJBIG = -1;
+static int hf_h245_transcodingMMR = -1;
+static int hf_h245_t38TCPBidirectionalMode = -1;
+static int hf_h245_chairControlCapability = -1;
+static int hf_h245_videoIndicateMixingCapability = -1;
+static int hf_h245_multipointVisualizationCapability = -1;
+static int hf_h245_controlOnMuxStream = -1;
+static int hf_h245_redundancyEncoding_bool = -1;
+static int hf_h245_separatePort = -1;
+static int hf_h245_samePort_bool = -1;
+static int hf_h245_associateConference = -1;
+static int hf_h245_audioHeaderPresent = -1;
+static int hf_h245_segmentableFlag = -1;
+static int hf_h245_alsduSplitting = -1;
+static int hf_h245_uIH = -1;
+static int hf_h245_loopbackTestProcedure = -1;
+static int hf_h245_mediaGuaranteedDelivery = -1;
+static int hf_h245_mediaControlGuaranteedDelivery = -1;
+static int hf_h245_flowControlToZero = -1;
+static int hf_h245_multiplexCapability_bool = -1;
+static int hf_h245_secureChannel = -1;
+static int hf_h245_sharedSecret = -1;
+static int hf_h245_certProtectedKey = -1;
+static int hf_h245_bitRateLockedToPCRClock = -1;
+static int hf_h245_bitRateLockedToNetworkClock = -1;
+static int hf_h245_IS11172_BitRate = -1;
+static int hf_h245_IS13818_BitRate = -1;
+static int hf_h245_ATM_BitRate = -1;
+static int hf_h245_t35CountryCode = -1;
+static int hf_h245_t35Extension = -1;
+static int hf_h245_manufacturerCode = -1;
+static int hf_h245_terminalType = -1;
+static int hf_h245_statusDeterminationNumber = -1;
+static int hf_h245_CapabilityTableEntryNumber = -1;
+static int hf_h245_CapabilityDescriptorNumber = -1;
+static int hf_h245_h233IVResponseTime = -1;
+static int hf_h245_maxPendingReplacementFor = -1;
+static int hf_h245_numberOfVCs = -1;
+static int hf_h245_forwardMaximumSDUSize = -1;
+static int hf_h245_backwardMaximumSDUSize = -1;
+static int hf_h245_singleBitRate = -1;
+static int hf_h245_lowerBitRate = -1;
+static int hf_h245_higherBitRate = -1;
+static int hf_h245_maximumAl2SDUSize = -1;
+static int hf_h245_maximumAl3SDUSize = -1;
+static int hf_h245_maximumDelayJitter = -1;
+static int hf_h245_maximumNestingDepth = -1;
+static int hf_h245_maximumElementListSize = -1;
+static int hf_h245_maximumSubElementListSize = -1;
+static int hf_h245_h223bitRate = -1;
+static int hf_h245_maximumSampleSize = -1;
+static int hf_h245_maximumPayloadLength = -1;
+static int hf_h245_maximumAL1MPDUSize = -1;
+static int hf_h245_maximumAL2MSDUSize = -1;
+static int hf_h245_maximumAL3MSDUSize = -1;
+static int hf_h245_numOfDLCS = -1;
+static int hf_h245_n401Capability = -1;
+static int hf_h245_maxWindowSizeCapability = -1;
+static int hf_h245_maximumAudioDelayJitter = -1;
+static int hf_h245_tokenRate = -1;
+static int hf_h245_bucketSize = -1;
+static int hf_h245_peakRate = -1;
+static int hf_h245_minPoliced = -1;
+static int hf_h245_maxPktSize = -1;
+static int hf_h245_maxNTUSize = -1;
+static int hf_h245_numberOfThreads = -1;
+static int hf_h245_framesBetweenSyncPoints = -1;
+static int hf_h245_threadNumber = -1;
+static int hf_h245_qcifMPI_1_4 = -1;
+static int hf_h245_qcifMPI_1_32 = -1;
+static int hf_h245_qcifMPI_1_2048 = -1;
+static int hf_h245_cifMPI_1_4 = -1;
+static int hf_h245_cifMPI_1_32 = -1;
+static int hf_h245_cifMPI_1_2048 = -1;
+static int hf_h245_videoBitRate = -1;
+static int hf_h245_vbvBufferSize = -1;
+static int hf_h245_samplesPerLine = -1;
+static int hf_h245_linesPerFrame = -1;
+static int hf_h245_framesPerSecond = -1;
+static int hf_h245_luminanceSampleRate = -1;
+static int hf_h245_sqcifMPI_1_32 = -1;
+static int hf_h245_sqcifMPI_1_2048 = -1;
+static int hf_h245_cif4MPI_1_32 = -1;
+static int hf_h245_cif4MPI_1_2048 = -1;
+static int hf_h245_cif16MPI_1_32 = -1;
+static int hf_h245_cif16MPI_1_2048 = -1;
+static int hf_h245_maxBitRate_192400 = -1;
+static int hf_h245_hrd_B = -1;
+static int hf_h245_bppMaxKb = -1;
+static int hf_h245_slowSqcifMPI = -1;
+static int hf_h245_slowQcifMPI = -1;
+static int hf_h245_slowCifMPI = -1;
+static int hf_h245_slowCif4MPI = -1;
+static int hf_h245_slowCif16MPI = -1;
+static int hf_h245_numberOfBPictures = -1;
+static int hf_h245_presentationOrder = -1;
+static int hf_h245_offset_x = -1;
+static int hf_h245_offset_y = -1;
+static int hf_h245_scale_x = -1;
+static int hf_h245_scale_y = -1;
+static int hf_h245_sqcifAdditionalPictureMemory = -1;
+static int hf_h245_qcifAdditionalPictureMemory = -1;
+static int hf_h245_cifAdditionalPictureMemory = -1;
+static int hf_h245_cif4AdditionalPictureMemory = -1;
+static int hf_h245_cif16AdditionalPictureMemory = -1;
+static int hf_h245_bigCpfAdditionalPictureMemory = -1;
+static int hf_h245_mpuHorizMBs = -1;
+static int hf_h245_mpuVertMBs = -1;
+static int hf_h245_mpuTotalNumber = -1;
+static int hf_h245_clockConversionCode = -1;
+static int hf_h245_clockDivisor = -1;
+static int hf_h245_maxCustomPictureWidth = -1;
+static int hf_h245_minCustomPictureWidth = -1;
+static int hf_h245_minCustomPictureHeight = -1;
+static int hf_h245_maxCustomPictureHeight = -1;
+static int hf_h245_standardMPI = -1;
+static int hf_h245_customMPI = -1;
+static int hf_h245_width = -1;
+static int hf_h245_height = -1;
+static int hf_h245_pictureRate = -1;
+static int hf_h245_g711Alaw64k = -1;
+static int hf_h245_g711Alaw56k = -1;
+static int hf_h245_g711Ulaw64k = -1;
+static int hf_h245_g711Ulaw56k = -1;
+static int hf_h245_g722_64k = -1;
+static int hf_h245_g722_56k = -1;
+static int hf_h245_g722_48k = -1;
+static int hf_h245_maxAl_sduAudioFrames = -1;
+static int hf_h245_g728 = -1;
+static int hf_h245_g729 = -1;
+static int hf_h245_g729AnnexA = -1;
+static int hf_h245_g729wAnnexB = -1;
+static int hf_h245_g729AnnexAwAnnexB = -1;
+static int hf_h245_audioUnit = -1;
+static int hf_h245_highRateMode0 = -1;
+static int hf_h245_highRateMode1 = -1;
+static int hf_h245_lowRateMode0 = -1;
+static int hf_h245_lowRateMode1 = -1;
+static int hf_h245_sidMode0 = -1;
+static int hf_h245_sidMode1 = -1;
+static int hf_h245_audioUnitSize = -1;
+static int hf_h245_maxBitRate_4294967295UL = -1;
+static int hf_h245_numberOfCodewords = -1;
+static int hf_h245_maximumStringLength = -1;
+static int hf_h245_version = -1;
+static int hf_h245_standard_0_127 = -1;
+static int hf_h245_booleanArray = -1;
+static int hf_h245_unsignedMin = -1;
+static int hf_h245_unsignedMax = -1;
+static int hf_h245_unsigned32Min = -1;
+static int hf_h245_unsigned32Max = -1;
+static int hf_h245_dynamicRTPPayloadType = -1;
+static int hf_h245_portNumber = -1;
+static int hf_h245_resourceID = -1;
+static int hf_h245_subChannelID = -1;
+static int hf_h245_pcr_pid = -1;
+static int hf_h245_controlFieldOctets = -1;
+static int hf_h245_sendBufferSize = -1;
+static int hf_h245_rcpcCodeRate = -1;
+static int hf_h245_rsCodeCorrection = -1;
+static int hf_h245_finite_0_16 = -1;
+static int hf_h245_windowSize = -1;
+static int hf_h245_n401 = -1;
+static int hf_h245_sessionID_0_255 = -1;
+static int hf_h245_sessionID_1_255 = -1;
+static int hf_h245_associatedSessionID = -1;
+static int hf_h245_payloadType = -1;
+static int hf_h245_protectedSessionID = -1;
+static int hf_h245_protectedPayloadType = -1;
+static int hf_h245_tsapIdentifier = -1;
+static int hf_h245_synchFlag = -1;
+static int hf_h245_finite_1_65535 = -1;
+static int hf_h245_MultiplexTableEntryNumber = -1;
+static int hf_h245_dataModeBitRate = -1;
+static int hf_h245_sessionDependency = -1;
+static int hf_h245_sRandom = -1;
+static int hf_h245_McuNumber = -1;
+static int hf_h245_TerminalNumber = -1;
+static int hf_h245_maxNumberOfAdditionalConnections = -1;
+static int hf_h245_requestedInterval = -1;
+static int hf_h245_callAssociationNumber = -1;
+static int hf_h245_currentInterval = -1;
+static int hf_h245_infoNotAvailable = -1;
+static int hf_h245_channelTag = -1;
+static int hf_h245_ConnectionIDsequenceNumber = -1;
+static int hf_h245_MaximumBitRate = -1;
+static int hf_h245_maximumBitRate_0_16777215 = -1;
+static int hf_h245_firstGOB_0_17 = -1;
+static int hf_h245_numberOfGOBs = -1;
+static int hf_h245_videoTemporalSpatialTradeOff = -1;
+static int hf_h245_firstGOB_0_255 = -1;
+static int hf_h245_firstMB_1_8192 = -1;
+static int hf_h245_firstMB_1_9216 = -1;
+static int hf_h245_numberOfMBs_1_8192 = -1;
+static int hf_h245_numberOfMBs_1_9216 = -1;
+static int hf_h245_maxH223MUXPDUsize = -1;
+static int hf_h245_temporalReference_0_1023 = -1;
+static int hf_h245_temporalReference_0_255 = -1;
+static int hf_h245_pictureNumber = -1;
+static int hf_h245_longTermPictureIndex = -1;
+static int hf_h245_sampleSize = -1;
+static int hf_h245_samplesPerFrame = -1;
+static int hf_h245_sbeNumber = -1;
+static int hf_h245_subPictureNumber = -1;
+static int hf_h245_compositionNumber = -1;
+static int hf_h245_estimatedReceivedJitterMantissa = -1;
+static int hf_h245_estimatedReceivedJitterExponent = -1;
+static int hf_h245_skippedFrameCount = -1;
+static int hf_h245_additionalDecoderBuffer = -1;
+static int hf_h245_skew = -1;
+static int hf_h245_maximumSkew = -1;
+static int hf_h245_duration = -1;
+static int hf_h245_timestamp = -1;
+static int hf_h245_frame = -1;
+static int hf_h245_containedThread = -1;
+static int hf_h245_t38FaxMaxBuffer = -1;
+static int hf_h245_t38FaxMaxDatagram = -1;
+static int hf_h245_expirationTime = -1;
+static int hf_h245_object = -1;
+static int hf_h245_protocolIdentifier = -1;
+static int hf_h245_algorithm = -1;
+static int hf_h245_antiSpamAlgorithm = -1;
+static int hf_h245_standard_object = -1;
+static int hf_h245_oid = -1;
+static int hf_h245_escrowID = -1;
+static int hf_h245_field = -1;
+static int hf_h245_NonStandardParameterData = -1;
+static int hf_h245_nlpidData = -1;
+static int hf_h245_nonCollapsingRaw = -1;
+static int hf_h245_uuid = -1;
+static int hf_h245_octetString = -1;
+static int hf_h245_externalReference = -1;
+static int hf_h245_nsapAddress = -1;
+static int hf_h245_subaddress_1_20 = -1;
+static int hf_h245_programDescriptors = -1;
+static int hf_h245_streamDescriptors = -1;
+static int hf_h245_ipv4network = -1;
+static int hf_h245_ipxNode = -1;
+static int hf_h245_ipxNetnum = -1;
+static int hf_h245_ipv6network = -1;
+static int hf_h245_netBios = -1;
+static int hf_h245_nsap = -1;
+static int hf_h245_h235Key = -1;
+static int hf_h245_value = -1;
+static int hf_h245_certificateResponse = -1;
+static int hf_h245_TerminalID = -1;
+static int hf_h245_ConferenceID = -1;
+static int hf_h245_Password = -1;
+static int hf_h245_encryptionSE = -1;
+static int hf_h245_conferenceIdentifier = -1;
+static int hf_h245_returnedFunction = -1;
+static int hf_h245_productNumber = -1;
+static int hf_h245_versionNumber = -1;
+static int hf_h245_mediaDistributionCapability = -1;
+static int hf_h245_AlternativeCapabilitySet = -1;
+static int hf_h245_frameToThreadMapping_custom = -1;
+static int hf_h245_RedundancyEncodingCapability_sequence_of = -1;
+static int hf_h245_frameSequence = -1;
+static int hf_h245_EncryptionCapability = -1;
+static int hf_h245_escrowentry = -1;
+static int hf_h245_elementList = -1;
+static int hf_h245_subElementList = -1;
+static int hf_h245_requestedModes = -1;
+static int hf_h245_CertSelectionCriteria = -1;
+static int hf_h245_capabilityTable = -1;
+static int hf_h245_capabilityDescriptors = -1;
+static int hf_h245_simultaneousCapabilities = -1;
+static int hf_h245_gatewayAddress = -1;
+static int hf_h245_snrEnhancement = -1;
+static int hf_h245_spatialEnhancement = -1;
+static int hf_h245_bPictureEnhancement = -1;
+static int hf_h245_customPictureClockFrequency = -1;
+static int hf_h245_customPictureFormat = -1;
+static int hf_h245_modeCombos = -1;
+static int hf_h245_customPCF = -1;
+static int hf_h245_pixelAspectCode = -1;
+static int hf_h245_extendedPAR = -1;
+static int hf_h245_h263VideoCoupledModes = -1;
+static int hf_h245_capabilityOnMuxStream = -1;
+static int hf_h245_capabilities = -1;
+static int hf_h245_multiplexEntryDescriptors = -1;
+static int hf_h245_multiplexTableEntryNumber_set_of = -1;
+static int hf_h245_VCCapability_set_of = -1;
+static int hf_h245_rejectionDescriptions = -1;
+static int hf_h245_entryNumbers = -1;
+static int hf_h245_ModeDescription = -1;
+static int hf_h245_communicationModeTable = -1;
+static int hf_h245_terminalListResponse = -1;
+static int hf_h245_differential = -1;
+static int hf_h245_networkType = -1;
+static int hf_h245_capabilityTableEntryNumbers = -1;
+static int hf_h245_capabilityDescriptorNumbers = -1;
+static int hf_h245_qOSCapabilities = -1;
+static int hf_h245_containedThreads = -1;
+static int hf_h245_CapabilityTableEntryNumber_sequence_of = -1;
+static int hf_h245_mediaChannelCapabilities = -1;
+static int hf_h245_rtpPayloadType_sequence_of = -1;
+static int hf_h245_centralizedData = -1;
+static int hf_h245_distributedData = -1;
+static int hf_h245_nonStandardData = -1;
+static int hf_h245_collapsing = -1;
+static int hf_h245_nonCollapsing = -1;
+static int hf_h245_supersedes = -1;
+static int hf_h245_genericParameter = -1;
+static int hf_h245_secondary_REE = -1;
+static int hf_h245_elements_MPSE = -1;
+static int hf_h245_secondary_REDTME = -1;
+static int hf_h245_elements_MPSEM = -1;
+static int hf_h245_TerminalInformationSO = -1;
+static int hf_h245_lostPicture = -1;
+static int hf_h245_recoveryReferencePicture = -1;
+static int hf_h245_iPSourceRouteAddress_route = -1;
+static int hf_h245_audioTelephoneEvent = -1;
+static int hf_h245_alphanumeric = -1;
+static int hf_h245_h221Manufacturer = -1;
+
+
+static gint ett_h245 = -1;
+static gint ett_h245_VCCapability_set_of = -1;
+static gint ett_h245_MultimediaSystemControlMessage = -1;
+static gint ett_h245_RequestMessage = -1;
+static gint ett_h245_ResponseMessage = -1;
+static gint ett_h245_IndicationMessage = -1;
+static gint ett_h245_CommandMessage = -1;
+static gint ett_h245_EndSessionCommand = -1;
+static gint ett_h245_MobileMultilinkReconfigurationIndication = -1;
+static gint ett_h245_FlowControlIndication = -1;
+static gint ett_h245_UserInputIndication_extendedAlphanumeric = -1;
+static gint ett_h245_UserInputIndication_signalUpdate_rtp = -1;
+static gint ett_h245_UserInputIndication_signalUpdate = -1;
+static gint ett_h245_UserInputIndication_signal_rtp = -1;
+static gint ett_h245_UserInputIndication_signal = -1;
+static gint ett_h245_NewATMVCIndication_reverseParameters = -1;
+static gint ett_h245_NewATMVCIndication_aal_aal5 = -1;
+static gint ett_h245_NewATMVCIndication_aal_aal1 = -1;
+static gint ett_h245_NewATMVCIndication_aal = -1;
+static gint ett_h245_NewATMVCIndication = -1;
+static gint ett_h245_VendorIdentification = -1;
+static gint ett_h245_MCLocationIndication = -1;
+static gint ett_h245_H2250MaximumSkewIndication = -1;
+static gint ett_h245_H223SkewIndication = -1;
+static gint ett_h245_JitterIndication = -1;
+static gint ett_h245_AlternativeCapabilitySet = -1;
+static gint ett_h245_MiscellaneousIndication_type_videoNotDecodedMBs = -1;
+static gint ett_h245_MiscellaneousIndication = -1;
+static gint ett_h245_VideoIndicateCompose = -1;
+static gint ett_h245_TerminalYouAreSeeingInSubPictureNumber = -1;
+static gint ett_h245_FunctionNotSupported = -1;
+static gint ett_h245_MobileMultilinkReconfigurationCommand = -1;
+static gint ett_h245_NewATMVCCommand_reverseParameters = -1;
+static gint ett_h245_NewATMVCCommand = -1;
+static gint ett_h245_NewATMVCCommand_aal_aal5 = -1;
+static gint ett_h245_NewATMVCCommand_aal_aal1 = -1;
+static gint ett_h245_EncryptionUpdateRequest = -1;
+static gint ett_h245_KeyProtectionMethod = -1;
+static gint ett_h245_MiscellaneousCommand_type_lostPartialPicture = -1;
+static gint ett_h245_MiscellaneousCommand_type_videoBadMBs = -1;
+static gint ett_h245_MiscellaneousCommand_type_progressiveRefinementStart = -1;
+static gint ett_h245_MiscellaneousCommand_type_videoFastUpdateMB = -1;
+static gint ett_h245_MiscellaneousCommand_type_videoFastUpdateGOB = -1;
+static gint ett_h245_MiscellaneousCommand = -1;
+static gint ett_h245_SubstituteConferenceIDCommand = -1;
+static gint ett_h245_FlowControlCommand = -1;
+static gint ett_h245_EncryptionCommand_encryptionAlgorithmID = -1;
+static gint ett_h245_SendTerminalCapabilitySet_specificRequest = -1;
+static gint ett_h245_LogicalChannelRateRelease = -1;
+static gint ett_h245_LogicalChannelRateReject = -1;
+static gint ett_h245_LogicalChannelRateAck = -1;
+static gint ett_h245_LogicalChannelRateRequest = -1;
+static gint ett_h245_ConnectionIdentifier = -1;
+static gint ett_h245_DialingInformationNumber = -1;
+static gint ett_h245_MultilinkIndication_excessiveError = -1;
+static gint ett_h245_MultilinkIndication_crcDesired = -1;
+static gint ett_h245_MultilinkResponse_maximumHeaderInterval = -1;
+static gint ett_h245_MultilinkResponse_removeConnection = -1;
+static gint ett_h245_MultilinkResponse_addConnection = -1;
+static gint ett_h245_MultilinkResponse_callInformation = -1;
+static gint ett_h245_MultilinkRequest_maximumHeaderInterval = -1;
+static gint ett_h245_MultilinkRequest_removeConnection = -1;
+static gint ett_h245_MultilinkRequest_addConnection = -1;
+static gint ett_h245_MultilinkRequest_callInformation = -1;
+static gint ett_h245_TerminalInformation = -1;
+static gint ett_h245_RequestAllTerminalIDsResponse = -1;
+static gint ett_h245_ConferenceResponse_terminalCertificateResponse = -1;
+static gint ett_h245_ConferenceResponse_chairTokenOwnerResponse = -1;
+static gint ett_h245_ConferenceResponse_extensionAddressResponse = -1;
+static gint ett_h245_ConferenceResponse_passwordResponse = -1;
+static gint ett_h245_ConferenceResponse_conferenceIDResponse = -1;
+static gint ett_h245_ConferenceResponse_terminalIDResponse = -1;
+static gint ett_h245_ConferenceResponse_mCterminalIDResponse = -1;
+static gint ett_h245_TerminalLabel = -1;
+static gint ett_h245_Criteria = -1;
+static gint ett_h245_ConferenceRequest_requestTerminalCertificate = -1;
+static gint ett_h245_CommunicationModeTableEntry = -1;
+static gint ett_h245_CommunicationModeRequest = -1;
+static gint ett_h245_CommunicationModeCommand = -1;
+static gint ett_h245_MaintenanceLoopOffCommand = -1;
+static gint ett_h245_MaintenanceLoopReject = -1;
+static gint ett_h245_MaintenanceLoopAck = -1;
+static gint ett_h245_MaintenanceLoopRequest = -1;
+static gint ett_h245_RoundTripDelayResponse = -1;
+static gint ett_h245_RoundTripDelayRequest = -1;
+static gint ett_h245_DataMode_application_t38fax = -1;
+static gint ett_h245_DataMode_application_nlpid = -1;
+static gint ett_h245_DataMode = -1;
+static gint ett_h245_VBDMode = -1;
+static gint ett_h245_G7231AnnexCMode_g723AnnexCAudioMode = -1;
+static gint ett_h245_G7231AnnexCMode = -1;
+static gint ett_h245_IS13818AudioMode = -1;
+static gint ett_h245_IS11172AudioMode = -1;
+static gint ett_h245_IS11172VideoMode = -1;
+static gint ett_h245_H263VideoMode = -1;
+static gint ett_h245_H262VideoMode = -1;
+static gint ett_h245_H261VideoMode = -1;
+static gint ett_h245_RedundancyEncodingMode = -1;
+static gint ett_h245_H2250ModeParameters = -1;
+static gint ett_h245_H223ModeParameters_adaptationLayerType_al3 = -1;
+static gint ett_h245_H223ModeParameters = -1;
+static gint ett_h245_FECMode_rfc2733Mode_mode_separateStream_samePort = -1;
+static gint ett_h245_FECMode_rfc2733Mode_mode_separateStream_differentPort = -1;
+static gint ett_h245_FECMode_rfc2733Mode = -1;
+static gint ett_h245_MultiplePayloadStreamElementMode = -1;
+static gint ett_h245_MultiplePayloadStreamMode = -1;
+static gint ett_h245_RedundancyEncodingDTModeElement = -1;
+static gint ett_h245_RedundancyEncodingDTMode = -1;
+static gint ett_h245_MultiplexedStreamModeParameters = -1;
+static gint ett_h245_H235Mode = -1;
+static gint ett_h245_ModeElement = -1;
+static gint ett_h245_RequestModeRelease = -1;
+static gint ett_h245_RequestModeReject = -1;
+static gint ett_h245_RequestModeAck = -1;
+static gint ett_h245_RequestMode = -1;
+static gint ett_h245_RequestMultiplexEntryRelease = -1;
+static gint ett_h245_RequestMultiplexEntryRejectionDescriptions = -1;
+static gint ett_h245_RequestMultiplexEntryReject = -1;
+static gint ett_h245_RequestMultiplexEntryAck = -1;
+static gint ett_h245_RequestMultiplexEntry = -1;
+static gint ett_h245_MultiplexEntrySendRelease = -1;
+static gint ett_h245_MultiplexEntryRejectionDescriptions = -1;
+static gint ett_h245_MultiplexEntrySendReject = -1;
+static gint ett_h245_MultiplexEntrySendAck = -1;
+static gint ett_h245_MultiplexElement = -1;
+static gint ett_h245_MultiplexEntryDescriptor = -1;
+static gint ett_h245_MultiplexEntrySend = -1;
+static gint ett_h245_RequestChannelCloseRelease = -1;
+static gint ett_h245_RequestChannelCloseReject = -1;
+static gint ett_h245_RequestChannelCloseAck = -1;
+static gint ett_h245_RequestChannelClose = -1;
+static gint ett_h245_CloseLogicalChannelAck = -1;
+static gint ett_h245_CloseLogicalChannel = -1;
+static gint ett_h245_H2250LogicalChannelAckParameters = -1;
+static gint ett_h245_OpenLogicalChannelConfirm = -1;
+static gint ett_h245_OpenLogicalChannelReject = -1;
+static gint ett_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters = -1;
+static gint ett_h245_OpenLogicalChannelAck = -1;
+static gint ett_h245_EscrowData = -1;
+static gint ett_h245_EncryptionSync = -1;
+static gint ett_h245_MulticastAddress_iP6Address = -1;
+static gint ett_h245_MulticastAddress_iPAddress = -1;
+static gint ett_h245_UnicastAddress_iPSourceRouteAddress = -1;
+static gint ett_h245_UnicastAddress_iP6Address = -1;
+static gint ett_h245_UnicastAddress_iPXAddress = -1;
+static gint ett_h245_UnicastAddress_iPAddress = -1;
+static gint ett_h245_FECData_rfc2733_mode_separateStream_samePort = -1;
+static gint ett_h245_FECData_rfc2733_mode_separateStream_differentPort = -1;
+static gint ett_h245_FECData_rfc2733 = -1;
+static gint ett_h245_MultiplePayloadStreamElement = -1;
+static gint ett_h245_MultiplePayloadStream = -1;
+static gint ett_h245_RedundancyEncodingElement = -1;
+static gint ett_h245_RedundancyEncoding_rtpRedundancyEncoding = -1;
+static gint ett_h245_RedundancyEncoding = -1;
+static gint ett_h245_RTPPayloadType = -1;
+static gint ett_h245_H2250LogicalChannelParameters = -1;
+static gint ett_h245_V76HDLCParameters = -1;
+static gint ett_h245_V76LogicalChannelParameters_mode_eRM = -1;
+static gint ett_h245_V76LogicalChannelParameters = -1;
+static gint ett_h245_H223AnnexCArqParameters = -1;
+static gint ett_h245_H223AL3MParameters = -1;
+static gint ett_h245_H223AL2MParameters = -1;
+static gint ett_h245_H223AL1MParameters = -1;
+static gint ett_h245_H223LogicalChannelParameters_adaptionLayerType_al3 = -1;
+static gint ett_h245_H223LogicalChannelParameters = -1;
+static gint ett_h245_H222LogicalChannelParameters = -1;
+static gint ett_h245_MultiplexedStreamParameter = -1;
+static gint ett_h245_H235Media = -1;
+static gint ett_h245_V75Parameters = -1;
+static gint ett_h245_Q2931Address = -1;
+static gint ett_h245_NetworkAccessParameters = -1;
+static gint ett_h245_reverseLogicalChannelParameters = -1;
+static gint ett_h245_forwardLogicalChannelParameters = -1;
+static gint ett_h245_OpenLogicalChannel = -1;
+static gint ett_h245_FECCapability_rfc2733_separateStream = -1;
+static gint ett_h245_FECCapability_rfc2733 = -1;
+static gint ett_h245_MultiplePayloadStreamCapability = -1;
+static gint ett_h245_NoPTAudioToneCapability = -1;
+static gint ett_h245_NoPTAudioTelephonyEventCapability = -1;
+static gint ett_h245_AudioToneCapability = -1;
+static gint ett_h245_AudioTelephonyEventCapability = -1;
+static gint ett_h245_MultiplexedStreamCapability = -1;
+static gint ett_h245_GenericParameter = -1;
+static gint ett_h245_GenericCapability = -1;
+static gint ett_h245_ConferenceCapability = -1;
+static gint ett_h245_IntegrityCapability = -1;
+static gint ett_h245_AuthenticationCapability = -1;
+static gint ett_h245_EncryptionAuthenticationAndIntegrity = -1;
+static gint ett_h245_T38FaxTcpOptions = -1;
+static gint ett_h245_T38FaxUdpOptions = -1;
+static gint ett_h245_T38FaxProfile = -1;
+static gint ett_h245_T84Profile_t84Restricted = -1;
+static gint ett_h245_V42bis = -1;
+static gint ett_h245_DataApplicationCapability_application_t38fax = -1;
+static gint ett_h245_DataApplicationCapability_application_nlpid = -1;
+static gint ett_h245_DataApplicationCapability_application_t84 = -1;
+static gint ett_h245_DataApplicationCapability = -1;
+static gint ett_h245_VBDCapability = -1;
+static gint ett_h245_GSMAudioCapability = -1;
+static gint ett_h245_IS13818AudioCapability = -1;
+static gint ett_h245_IS11172AudioCapability = -1;
+static gint ett_h245_G7231AnnexCCapability_g723AnnexCAudioMode = -1;
+static gint ett_h245_G7231AnnexCCapability = -1;
+static gint ett_h245_G729Extensions = -1;
+static gint ett_h245_AudioCapability_g7231 = -1;
+static gint ett_h245_IS11172VideoCapability = -1;
+static gint ett_h245_H263Version3Options = -1;
+static gint ett_h245_H263ModeComboFlags = -1;
+static gint ett_h245_H263VideoModeCombos = -1;
+static gint ett_h245_CustomPictureFormat_pixelAspectInformation_extendedPAR = -1;
+static gint ett_h245_CustomPictureFormat_mPI_customPCF = -1;
+static gint ett_h245_CustomPictureFormat_mPI = -1;
+static gint ett_h245_CustomPictureFormat = -1;
+static gint ett_h245_CustomPictureClockFrequency = -1;
+static gint ett_h245_RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters = -1;
+static gint ett_h245_RefPictureSelection_enhancedReferencePicSelect = -1;
+static gint ett_h245_RefPictureSelection_additionalPictureMemory = -1;
+static gint ett_h245_RefPictureSelection = -1;
+static gint ett_h245_TransperencyParameters = -1;
+static gint ett_h245_H263Options = -1;
+static gint ett_h245_EnhancementOptions = -1;
+static gint ett_h245_BEnhancementParameters = -1;
+static gint ett_h245_EnhancementLayerInfo = -1;
+static gint ett_h245_H263VideoCapability = -1;
+static gint ett_h245_H262VideoCapability = -1;
+static gint ett_h245_H261VideoCapability = -1;
+static gint ett_h245_MediaDistributionCapability = -1;
+static gint ett_h245_MultipointCapability = -1;
+static gint ett_h245_RTPH263VideoRedundancyFrameMapping = -1;
+static gint ett_h245_RTPH263VideoRedundancyEncoding = -1;
+static gint ett_h245_RedundancyEncodingCapability = -1;
+static gint ett_h245_TransportCapability = -1;
+static gint ett_h245_MediaChannelCapability = -1;
+static gint ett_h245_MediaTransportType_AtmAAL5Compressed = -1;
+static gint ett_h245_QOSCapability = -1;
+static gint ett_h245_ATMParameters = -1;
+static gint ett_h245_RSVPParameters = -1;
+static gint ett_h245_MediaPacketizationCapability = -1;
+static gint ett_h245_H2250Capability_mcCapability = -1;
+static gint ett_h245_H2250Capability = -1;
+static gint ett_h245_V75Capability = -1;
+static gint ett_h245_V76Capability = -1;
+static gint ett_h245_H223AnnexCCapability = -1;
+static gint ett_h245_H223Capability_mobileMultilinkFrameCapability = -1;
+static gint ett_h245_H223Capability_mobileOperationTransmitCapability = -1;
+static gint ett_h245_H223Capability_h223MultiplexTableCapability_enhanced = -1;
+static gint ett_h245_H223Capability = -1;
+static gint ett_h245_VCCapability_aal1ViaGateway = -1;
+static gint ett_h245_VCCapability_availableBitRates_rangeOfBitRates = -1;
+static gint ett_h245_VCCapability_availableBitRates = -1;
+static gint ett_h245_VCCapability_aal5 = -1;
+static gint ett_h245_VCCapability_aal1 = -1;
+static gint ett_h245_VCCapability = -1;
+static gint ett_h245_H222Capability = -1;
+static gint ett_h245_H235SecurityCapability = -1;
+static gint ett_h245_Capability_h233EncryptionReceiveCapability = -1;
+static gint ett_h245_TerminalCapabilitySetRelease = -1;
+static gint ett_h245_TerminalCapabilitySetReject = -1;
+static gint ett_h245_TerminalCapabilitySetAck = -1;
+static gint ett_h245_CapabilityDescriptor = -1;
+static gint ett_h245_CapabilityTableEntry = -1;
+static gint ett_h245_TerminalCapabilitySet = -1;
+static gint ett_h245_MasterSlaveDeterminationRelease = -1;
+static gint ett_h245_MasterSlaveDeterminationReject = -1;
+static gint ett_h245_MasterSlaveDeterminationAck = -1;
+static gint ett_h245_MasterSlaveDetermination = -1;
+static gint ett_h245_h221NonStandard = -1;
+static gint ett_h245_NonStandardParameter = -1;
+static gint ett_h245_NonStandardMessage = -1;
+static gint ett_h245_FlowControlIndication_restriction = -1;
+static gint ett_h245_FlowControlIndication_scope = -1;
+static gint ett_h245_UserInputIndication_userInputSupportIndication = -1;
+static gint ett_h245_UserInputIndication = -1;
+static gint ett_h245_NewATMVCIndication_reverseParameters_multiplex = -1;
+static gint ett_h245_NewATMVCIndication_multiplex = -1;
+static gint ett_h245_NewATMVCIndication_aal_aal1_errorCorrection = -1;
+static gint ett_h245_NewATMVCIndication_aal_aal1_clockRecovery = -1;
+static gint ett_h245_JitterIndication_scope = -1;
+static gint ett_h245_MiscellaneousIndication_type = -1;
+static gint ett_h245_ConferenceIndication = -1;
+static gint ett_h245_FunctionNotSupported_cause = -1;
+static gint ett_h245_FunctionNotUnderstood = -1;
+static gint ett_h245_MobileMultilinkReconfigurationCommand_status = -1;
+static gint ett_h245_NewATMVCCommand_reverseParameters_multiplex = -1;
+static gint ett_h245_NewATMVCCommand_multiplex = -1;
+static gint ett_h245_NewATMVCCommand_aal_aal1_errorCorrection = -1;
+static gint ett_h245_NewATMVCCommand_aal_aal1_clockRecovery = -1;
+static gint ett_h245_NewATMVCCommand_aal = -1;
+static gint ett_h245_H223MultiplexReconfiguration_h223AnnexADoubleFlag = -1;
+static gint ett_h245_H223MultiplexReconfiguration_h223ModeChange = -1;
+static gint ett_h245_H223MultiplexReconfiguration = -1;
+static gint ett_h245_PictureReference = -1;
+static gint ett_h245_MiscellaneousCommand_type_progressiveRefinementStart_repeatCount = -1;
+static gint ett_h245_MiscellaneousCommand_type = -1;
+static gint ett_h245_ConferenceCommand = -1;
+static gint ett_h245_EndSessionCommand_gstnOptions = -1;
+static gint ett_h245_EndSessionCommand_isdnOptions = -1;
+static gint ett_h245_FlowControlCommand_restriction = -1;
+static gint ett_h245_FlowControlCommand_scope = -1;
+static gint ett_h245_EncryptionCommand = -1;
+static gint ett_h245_SendTerminalCapabilitySet = -1;
+static gint ett_h245_LogicalChannelRateRejectReason = -1;
+static gint ett_h245_DialingInformationNetworkType = -1;
+static gint ett_h245_DialingInformation = -1;
+static gint ett_h245_MultilinkIndication = -1;
+static gint ett_h245_MultilinkResponse_addConnection_responseCode_rejected = -1;
+static gint ett_h245_MultilinkResponse_addConnection_responseCode = -1;
+static gint ett_h245_MultilinkResponse = -1;
+static gint ett_h245_MultilinkRequest_maximumHeaderInterval_requestType = -1;
+static gint ett_h245_MultilinkRequest = -1;
+static gint ett_h245_RemoteMCResponse_reject = -1;
+static gint ett_h245_RemoteMCResponse = -1;
+static gint ett_h245_RemoteMCRequest = -1;
+static gint ett_h245_ConferenceResponse_sendThisSourceResponse = -1;
+static gint ett_h245_ConferenceResponse_makeTerminalBroadcasterResponse = -1;
+static gint ett_h245_ConferenceResponse_broadcastMyLogicalChannelResponse = -1;
+static gint ett_h245_ConferenceResponse_makeMeChairResponse = -1;
+static gint ett_h245_ConferenceResponse = -1;
+static gint ett_h245_ConferenceRequest = -1;
+static gint ett_h245_CommunicationModeTableEntry_dataType = -1;
+static gint ett_h245_CommunicationModeResponse = -1;
+static gint ett_h245_MaintenanceLoopReject_cause = -1;
+static gint ett_h245_MaintenanceLoopReject_type = -1;
+static gint ett_h245_MaintenanceLoopAck_type = -1;
+static gint ett_h245_MaintenanceLoopRequest_type = -1;
+static gint ett_h245_EncryptionMode = -1;
+static gint ett_h245_DataMode_application = -1;
+static gint ett_h245_IS13818AudioMode_multiChannelType = -1;
+static gint ett_h245_IS13818AudioMode_audioSampling = -1;
+static gint ett_h245_IS13818AudioMode_audioLayer = -1;
+static gint ett_h245_IS11172AudioMode_multichannelType = -1;
+static gint ett_h245_IS11172AudioMode_audioSampling = -1;
+static gint ett_h245_IS11172AudioMode_audioLayer = -1;
+static gint ett_h245_AudioMode_g7231 = -1;
+static gint ett_h245_AudioMode = -1;
+static gint ett_h245_H263VideoMode_resolution = -1;
+static gint ett_h245_H262VideoMode_profileAndLevel = -1;
+static gint ett_h245_H261VideoMode_resolution = -1;
+static gint ett_h245_VideoMode = -1;
+static gint ett_h245_RedundancyEncodingMode_secondaryEncoding = -1;
+static gint ett_h245_V76ModeParameters = -1;
+static gint ett_h245_H223ModeParameters_adaptationLayerType = -1;
+static gint ett_h245_FECMode_rfc2733Mode_mode_separateStream = -1;
+static gint ett_h245_FECMode_rfc2733Mode_mode = -1;
+static gint ett_h245_FECMode = -1;
+static gint ett_h245_RedundancyEncodingDTModeElement_type = -1;
+static gint ett_h245_H235Mode_mediaMode = -1;
+static gint ett_h245_ModeElementType = -1;
+static gint ett_h245_RequestModeReject_cause = -1;
+static gint ett_h245_RequestMultiplexEntryRejectionDescriptions_cause = -1;
+static gint ett_h245_MultiplexEntryRejectionDescriptions_cause = -1;
+static gint ett_h245_MultiplexElement_repeatCount = -1;
+static gint ett_h245_MultiplexElement_type = -1;
+static gint ett_h245_RequestChannelCloseReject_cause = -1;
+static gint ett_h245_RequestChannelClose_reason = -1;
+static gint ett_h245_CloseLogicalChannel_reason = -1;
+static gint ett_h245_CloseLogicalChannel_source = -1;
+static gint ett_h245_OpenLogicalChannelReject_cause = -1;
+static gint ett_h245_forwardMultiplexAckParameters = -1;
+static gint ett_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters = -1;
+static gint ett_h245_MulticastAddress = -1;
+static gint ett_h245_UnicastAddress_iPSourceRouteAddress_routing = -1;
+static gint ett_h245_UnicastAddress = -1;
+static gint ett_h245_TransportAddress = -1;
+static gint ett_h245_FECData_rfc2733_mode_separateStream = -1;
+static gint ett_h245_FECData_rfc2733_mode = -1;
+static gint ett_h245_FECData = -1;
+static gint ett_h245_RTPPayloadType_payloadDescriptor = -1;
+static gint ett_h245_H2250LogicalChannelParameters_mediaPacketization = -1;
+static gint ett_h245_CRCLength = -1;
+static gint ett_h245_V76LogicalChannelParameters_mode_eRM_recovery = -1;
+static gint ett_h245_V76LogicalChannelParameters_mode = -1;
+static gint ett_h245_V76LogicalChannelParameters_suspendResume = -1;
+static gint ett_h245_H223AnnexCArqParameters_numberOfRetransmissions = -1;
+static gint ett_h245_H223AL3MParameters_arqType = -1;
+static gint ett_h245_H223AL3MParameters_crcLength = -1;
+static gint ett_h245_H223AL3MParameters_headerFormat = -1;
+static gint ett_h245_H223AL2MParameters_headerFEC = -1;
+static gint ett_h245_H223AL1MParameters_arqType = -1;
+static gint ett_h245_H223AL1MParameters_crcLength = -1;
+static gint ett_h245_H223AL1MParameters_headerFEC = -1;
+static gint ett_h245_H223AL1MParameters_transferMode = -1;
+static gint ett_h245_H223LogicalChannelParameters_adaptationLayerType = -1;
+static gint ett_h245_H235Media_mediaType = -1;
+static gint ett_h245_DataType = -1;
+static gint ett_h245_Q2931Address_address = -1;
+static gint ett_h245_NetworkAccessParameters_t120SetupProcedure = -1;
+static gint ett_h245_NetworkAccessParameters_networkAddress = -1;
+static gint ett_h245_NetworkAccessParameters_distribution = -1;
+static gint ett_h245_reverseLogicalChannelParameters_multiplexParameters = -1;
+static gint ett_h245_forwardLogicalChannelParameters_multiplexParameters = -1;
+static gint ett_h245_FECCapability = -1;
+static gint ett_h245_MultiplexFormat = -1;
+static gint ett_h245_ParameterValue = -1;
+static gint ett_h245_ParameterIdentifier = -1;
+static gint ett_h245_CapabilityIdentifier = -1;
+static gint ett_h245_UserInputCapability = -1;
+static gint ett_h245_MediaEncryptionAlgorithm = -1;
+static gint ett_h245_T38FaxUdpOptions_t38FaxUdpEC = -1;
+static gint ett_h245_T38FaxRateManagement = -1;
+static gint ett_h245_T84Profile = -1;
+static gint ett_h245_CompressionType = -1;
+static gint ett_h245_DataProtocolCapability_v76wCompression = -1;
+static gint ett_h245_DataProtocolCapability = -1;
+static gint ett_h245_DataApplicationCapability_application = -1;
+static gint ett_h245_AudioCapability = -1;
+static gint ett_h245_CustomPictureFormat_pixelAspectInformation = -1;
+static gint ett_h245_RefPictureSelection_videoBackChannelSend = -1;
+static gint ett_h245_VideoCapability = -1;
+static gint ett_h245_RTPH263VideoRedundancyEncoding_frameToThreadMapping = -1;
+static gint ett_h245_RedundancyEncodingMethod = -1;
+static gint ett_h245_MediaTransportType = -1;
+static gint ett_h245_QOSMode = -1;
+static gint ett_h245_H223Capability_h223MultiplexTableCapability = -1;
+static gint ett_h245_VCCapability_availableBitRates_type = -1;
+static gint ett_h245_MultiplexCapability = -1;
+static gint ett_h245_Capability = -1;
+static gint ett_h245_TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded = -1;
+static gint ett_h245_TerminalCapabilitySetReject_cause = -1;
+static gint ett_h245_MasterSlaveDeterminationReject_cause = -1;
+static gint ett_h245_MasterSlaveDeterminationAck_decision = -1;
+static gint ett_h245_RequestModeAck_response_decision = -1;
+static gint ett_h245_NonStandardIdentifier = -1;
+static gint ett_h245_mediaDistributionCapability = -1;
+static gint ett_h245_frameToThreadMapping_custom = -1;
+static gint ett_h245_RedundancyEncodingCapability_sequence_of = -1;
+static gint ett_h245_frameSequence = -1;
+static gint ett_h245_EncryptionCapability = -1;
+static gint ett_h245_escrowentry = -1;
+static gint ett_h245_elementList = -1;
+static gint ett_h245_requestedModes = -1;
+static gint ett_h245_CertSelectionCriteria = -1;
+static gint ett_h245_capabilityTable = -1;
+static gint ett_h245_capabilityDescriptors = -1;
+static gint ett_h245_simultaneousCapabilities = -1;
+static gint ett_h245_gatewayAddress = -1;
+static gint ett_h245_snrEnhancement = -1;
+static gint ett_h245_spatialEnhancement = -1;
+static gint ett_h245_bPictureEnhancement = -1;
+static gint ett_h245_customPictureClockFrequency = -1;
+static gint ett_h245_customPictureFormat = -1;
+static gint ett_h245_modeCombos = -1;
+static gint ett_h245_customPCF = -1;
+static gint ett_h245_pixelAspectCode = -1;
+static gint ett_h245_extendedPAR = -1;
+static gint ett_h245_h263VideoCoupledModes = -1;
+static gint ett_h245_capabilityOnMuxStream = -1;
+static gint ett_h245_capabilities = -1;
+static gint ett_h245_multiplexEntryDescriptors = -1;
+static gint ett_h245_multiplexTableEntryNumber_set_of = -1;
+static gint ett_h245_rejectionDescriptions = -1;
+static gint ett_h245_entryNumbers = -1;
+static gint ett_h245_ModeDescription = -1;
+static gint ett_h245_communicationModeTable = -1;
+static gint ett_h245_terminalListResponse = -1;
+static gint ett_h245_differential = -1;
+static gint ett_h245_networkType = -1;
+static gint ett_h245_capabilityTableEntryNumbers = -1;
+static gint ett_h245_capabilityDescriptorNumbers = -1;
+static gint ett_h245_qOSCapabilities = -1;
+static gint ett_h245_subElementList = -1;
+static gint ett_h245_containedThreads = -1;
+static gint ett_h245_CapabilityTableEntryNumber_sequence_of = -1;
+static gint ett_h245_mediaChannelCapabilities = -1;
+static gint ett_h245_rtpPayloadType_sequence_of = -1;
+static gint ett_h245_centralizedData = -1;
+static gint ett_h245_distributedData = -1;
+static gint ett_h245_nonStandardData = -1;
+static gint ett_h245_collapsing = -1;
+static gint ett_h245_nonCollapsing = -1;
+static gint ett_h245_supersedes = -1;
+static gint ett_h245_genericParameter = -1;
+static gint ett_h245_secondary_REE = -1;
+static gint ett_h245_elements_MPSE = -1;
+static gint ett_h245_secondary_REDTME = -1;
+static gint ett_h245_elements_MPSEM = -1;
+static gint ett_h245_TerminalInformationSO = -1;
+static gint ett_h245_lostPicture = -1;
+static gint ett_h245_recoveryReferencePicture = -1;
+static gint ett_h245_iPSourceRouteAddress_route = -1;
+
+static dissector_table_t nsp_object_dissector_table;
+static dissector_table_t nsp_h221_dissector_table;
+
+static dissector_handle_t nsp_handle;
+
+static guint32 ipv4_address;
+static guint32 ipv4_port;
+static char object[256];
+static guint32 t35CountryCode;
+static guint32 t35Extension;
+static guint32 manufacturerCode;
+static guint32 h221NonStandard;
+
+static gboolean h245_reassembly = TRUE;
+static gboolean h245_shorttypes = FALSE;
+/* To put the codec type only in COL_INFO when
+ an OLC is read */
+char* codec_type = NULL;
+
+static int
+dissect_h245_NULL(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_, proto_tree *tree _U_)
+{
+ return offset;
+}
+
+
+
+
+
+
+
+
+static const value_string MasterSlaveDeterminationAck_decision_vals[] = {
+ { 0, "master" },
+ { 1, "slave" },
+ { 0, NULL }
+};
+static per_choice_t MasterSlaveDeterminationAck_decision_choice[] = {
+ { 0, "master", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "slave", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MasterSlaveDeterminationAck_decision(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDeterminationAck_decision, ett_h245_MasterSlaveDeterminationAck_decision, MasterSlaveDeterminationAck_decision_choice, "Decision", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MasterSlaveDeterminationAck_sequence[] = {
+ { "decision", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MasterSlaveDeterminationAck_decision },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MasterSlaveDeterminationAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDeterminationAck, ett_h245_MasterSlaveDeterminationAck, MasterSlaveDeterminationAck_sequence);
+
+ return offset;
+}
+
+
+static const value_string MasterSlaveDeterminationReject_cause_vals[] = {
+ { 0, "identicalNumbers" },
+ { 0, NULL }
+};
+static per_choice_t MasterSlaveDeterminationReject_cause_choice[] = {
+ { 0, "identicalNumbers", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MasterSlaveDeterminationReject_cause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDeterminationReject_cause, ett_h245_MasterSlaveDeterminationReject_cause, MasterSlaveDeterminationReject_cause_choice, "Cause", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MasterSlaveDeterminationReject_sequence[] = {
+ { "cause", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MasterSlaveDeterminationReject_cause },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MasterSlaveDeterminationReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDeterminationReject, ett_h245_MasterSlaveDeterminationReject, MasterSlaveDeterminationReject_sequence);
+
+ return offset;
+}
+
+
+
+static const value_string QOSMode_vals[] = {
+ { 0, "guaranteedQOS" },
+ { 1, "controlledLoad" },
+ { 0, NULL }
+};
+static per_choice_t QOSMode_choice[] = {
+ { 0, "guaranteedQOS", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "controlledLoad", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_QOSMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_QOSMode, ett_h245_QOSMode, QOSMode_choice, "QOSMode", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string RefPictureSelection_videoBackChannelSend_vals[] = {
+ { 0, "none" },
+ { 1, "ackMessageOnly" },
+ { 2, "nackMessageOnly" },
+ { 3, "ackOrNackMessageOnly" },
+ { 4, "ackAndNackMessage" },
+ { 0, NULL }
+};
+static per_choice_t RefPictureSelection_videoBackChannelSend_choice[] = {
+ { 0, "none", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "ackMessageOnly", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "nackMessageOnly", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "ackOrNackMessageOnly", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "ackAndNackMessage", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RefPictureSelection_videoBackChannelSend(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RefPictureSelection_videoBackChannelSend, ett_h245_RefPictureSelection_videoBackChannelSend, RefPictureSelection_videoBackChannelSend_choice, "videoBackChannelSend", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string T38FaxRateManagement_vals[] = {
+ { 0, "localTCF" },
+ { 1, "transferredTCF" },
+ { 0, NULL }
+};
+static per_choice_t T38FaxRateManagement_choice[] = {
+ { 0, "localTCF", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "transferredTCF", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_T38FaxRateManagement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_T38FaxRateManagement, ett_h245_T38FaxRateManagement, T38FaxRateManagement_choice, "T38FaxRateManagement", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string T38FaxUdpOptions_t38FaxUdpEC_vals[] = {
+ { 0, "t38UDPFEC" },
+ { 1, "t38UDPRedundancy" },
+ { 0, NULL }
+};
+static per_choice_t T38FaxUdpOptions_t38FaxUdpEC_choice[] = {
+ { 0, "t38UDPFEC", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "t38UDPRedundancy", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_T38FaxUdpOptions_t38FaxUdpEC(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_T38FaxUdpOptions_t38FaxUdpEC, ett_h245_T38FaxUdpOptions_t38FaxUdpEC, T38FaxUdpOptions_t38FaxUdpEC_choice, "t38FaxUdpEC", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string NetworkAccessParameters_distribution_vals[] = {
+ { 0, "unicast" },
+ { 1, "multicast" },
+ { 0, NULL }
+};
+static per_choice_t NetworkAccessParameters_distribution_choice[] = {
+ { 0, "unicast", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "multicast", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NetworkAccessParameters_distribution(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NetworkAccessParameters_distribution, ett_h245_NetworkAccessParameters_distribution, NetworkAccessParameters_distribution_choice, "Distribution", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string NetworkAccessParameters_t120SetupProcedure_vals[] = {
+ { 0, "originateCall" },
+ { 1, "waitForCall" },
+ { 2, "issueQuery" },
+ { 0, NULL }
+};
+static per_choice_t NetworkAccessParameters_t120SetupProcedure_choice[] = {
+ { 0, "originateCall", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "waitForCall", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "issueQuery", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NetworkAccessParameters_t120SetupProcedure(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NetworkAccessParameters_t120SetupProcedure, ett_h245_NetworkAccessParameters_t120SetupProcedure, NetworkAccessParameters_t120SetupProcedure_choice, "t120SetupProcedure", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string H223AL1MParameters_transferMode_vals[] = {
+ { 0, "framed" },
+ { 1, "unframed" },
+ { 0, NULL }
+};
+static per_choice_t H223AL1MParameters_transferMode_choice[] = {
+ { 0, "framed", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "unframed", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223AL1MParameters_transferMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223AL1MParameters_transferMode, ett_h245_H223AL1MParameters_transferMode, H223AL1MParameters_transferMode_choice, "transferMode", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string H223AL1MParameters_headerFEC_vals[] = {
+ { 0, "sebch16-7" },
+ { 1, "golay24-12" },
+ { 0, NULL }
+};
+static per_choice_t H223AL1MParameters_headerFEC_choice[] = {
+ { 0, "sebch16-7", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "golay24-12", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223AL1MParameters_headerFEC(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223AL1MParameters_headerFEC, ett_h245_H223AL1MParameters_headerFEC, H223AL1MParameters_headerFEC_choice, "headerFEC", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string H223AL1MParameters_crcLength_vals[] = {
+ { 0, "crc4bit" },
+ { 1, "crc12bit" },
+ { 2, "crc20bit" },
+ { 3, "crc28bit" },
+ { 4, "crc8bit" },
+ { 5, "crc16bit" },
+ { 6, "crc32bit" },
+ { 7, "crcNotUsed" },
+ { 0, NULL }
+};
+static per_choice_t H223AL1MParameters_crcLength_choice[] = {
+ { 0, "crc4bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "crc12bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "crc20bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "crc28bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "crc8bit", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "crc16bit", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "crc32bit", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "crcNotUsed", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223AL1MParameters_crcLength(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223AL1MParameters_crcLength, ett_h245_H223AL1MParameters_crcLength, H223AL1MParameters_crcLength_choice, "crcLength", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string H223AL2MParameters_headerFEC_vals[] = {
+ { 0, "sebch16-5" },
+ { 1, "golay24-12" },
+ { 0, NULL }
+};
+static per_choice_t H223AL2MParameters_headerFEC_choice[] = {
+ { 0, "sebch16-5", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "golay24-12", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223AL2MParameters_headerFEC(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223AL2MParameters_headerFEC, ett_h245_H223AL2MParameters_headerFEC, H223AL2MParameters_headerFEC_choice, "headerFEC", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string H223AL3MParameters_headerFormat_vals[] = {
+ { 0, "sebch16-7" },
+ { 1, "golay24-12" },
+ { 0, NULL }
+};
+static per_choice_t H223AL3MParameters_headerFormat_choice[] = {
+ { 0, "sebch16-7", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "golay24-12", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223AL3MParameters_headerFormat(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223AL3MParameters_headerFormat, ett_h245_H223AL3MParameters_headerFormat, H223AL3MParameters_headerFormat_choice, "headerFormat", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string H223AL3MParameters_crcLength_vals[] = {
+ { 0, "crc4bit" },
+ { 1, "crc12bit" },
+ { 2, "crc20bit" },
+ { 3, "crc28bit" },
+ { 4, "crc8bit" },
+ { 5, "crc16bit" },
+ { 6, "crc32bit" },
+ { 7, "crcNotUsed" },
+ { 0, NULL }
+};
+static per_choice_t H223AL3MParameters_crcLength_choice[] = {
+ { 0, "crc4bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "crc12bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "crc20bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "crc28bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "crc8bit", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "crc16bit", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "crc32bit", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "crcNotUsed", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223AL3MParameters_crcLength(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223AL3MParameters_crcLength, ett_h245_H223AL3MParameters_crcLength, H223AL3MParameters_crcLength_choice, "crcLength", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string V76LogicalChannelParameters_suspendResume_vals[] = {
+ { 0, "noSuspendResume" },
+ { 1, "suspendResumewAddress" },
+ { 2, "suspendResumewoAddress" },
+ { 0, NULL }
+};
+static per_choice_t V76LogicalChannelParameters_suspendResume_choice[] = {
+ { 0, "noSuspendResume", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "suspendResumewAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "suspendResumewoAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_V76LogicalChannelParameters_suspendResume(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_V76LogicalChannelParameters_suspendResume, ett_h245_V76LogicalChannelParameters_suspendResume, V76LogicalChannelParameters_suspendResume_choice, "suspendResume", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string V76LogicalChannelParameters_mode_eRM_recovery_vals[] = {
+ { 0, "rej" },
+ { 1, "sREJ" },
+ { 2, "mSREJ" },
+ { 0, NULL }
+};
+static per_choice_t V76LogicalChannelParameters_mode_eRM_recovery_choice[] = {
+ { 0, "rej", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "sREJ", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "mSREJ", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_V76LogicalChannelParameters_mode_eRM_recovery(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_V76LogicalChannelParameters_mode_eRM_recovery, ett_h245_V76LogicalChannelParameters_mode_eRM_recovery, V76LogicalChannelParameters_mode_eRM_recovery_choice, "recovery", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string CRCLength_vals[] = {
+ { 0, "crc8bit" },
+ { 1, "crc16bit" },
+ { 2, "crc32bit" },
+ { 0, NULL }
+};
+static per_choice_t CRCLength_choice[] = {
+ { 0, "crc8bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "crc16bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "crc32bit", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_CRCLength(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_CRCLength, ett_h245_CRCLength, CRCLength_choice, "CRCLength", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string UnicastAddress_iPSourceRouteAddress_routing_vals[] = {
+ { 0, "strict" },
+ { 1, "loose" },
+ { 0, NULL }
+};
+static per_choice_t UnicastAddress_iPSourceRouteAddress_routing_choice[] = {
+ { 0, "strict", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "loose", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_UnicastAddress_iPSourceRouteAddress_routing(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_UnicastAddress_iPSourceRouteAddress_routing, ett_h245_UnicastAddress_iPSourceRouteAddress_routing, UnicastAddress_iPSourceRouteAddress_routing_choice, "routing", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string OpenLogicalChannelReject_cause_vals[] = {
+ { 0, "unspecified" },
+ { 1, "unsuitableReverseParameters" },
+ { 2, "dataTypeNotSupported" },
+ { 3, "dataTypeNotAvailable" },
+ { 4, "unknownDataType" },
+ { 5, "dataTypeALCombinationNotSupported" },
+ { 6, "multicastChannelNotAllowed" },
+ { 7, "insufficientBandwidth" },
+ { 8, "separateStackEstablishmentFailed" },
+ { 9, "invalidSessionID" },
+ { 10, "masterSlaveConflict" },
+ { 11, "waitForCommunicationMode" },
+ { 12, "invalidDependentChannel" },
+ { 13, "replacementForRejected" },
+ { 0, NULL }
+};
+static per_choice_t OpenLogicalChannelReject_cause_choice[] = {
+ { 0, "unspecified", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "unsuitableReverseParameters", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "dataTypeNotSupported", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "dataTypeNotAvailable", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "unknownDataType", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "dataTypeALCombinationNotSupported", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "multicastChannelNotAllowed", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "insufficientBandwidth", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 8, "separateStackEstablishmentFailed", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 9, "invalidSessionID", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 10, "masterSlaveConflict", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 11, "waitForCommunicationMode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 12, "invalidDependentChannel", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 13, "replacementForRejected", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_OpenLogicalChannelReject_cause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannelReject_cause, ett_h245_OpenLogicalChannelReject_cause, OpenLogicalChannelReject_cause_choice, "cause", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string CloseLogicalChannel_source_vals[] = {
+ { 0, "user" },
+ { 1, "lcse" },
+ { 0, NULL }
+};
+static per_choice_t CloseLogicalChannel_source_choice[] = {
+ { 0, "user", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "lcse", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_CloseLogicalChannel_source(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_CloseLogicalChannel_source, ett_h245_CloseLogicalChannel_source, CloseLogicalChannel_source_choice, "source", NULL);
+
+ return offset;
+}
+
+
+static const value_string CloseLogicalChannel_reason_vals[] = {
+ { 0, "unknown" },
+ { 1, "reopen" },
+ { 2, "reservationFailure" },
+ { 0, NULL }
+};
+static per_choice_t CloseLogicalChannel_reason_choice[] = {
+ { 0, "unknown", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "reopen", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "reservationFailure", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_CloseLogicalChannel_reason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_CloseLogicalChannel_reason, ett_h245_CloseLogicalChannel_reason, CloseLogicalChannel_reason_choice, "reason", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string RequestChannelClose_reason_vals[] = {
+ { 0, "unknown" },
+ { 1, "normal" },
+ { 2, "reopen" },
+ { 3, "reservationFailure" },
+ { 0, NULL }
+};
+static per_choice_t RequestChannelClose_reason_choice[] = {
+ { 0, "unknown", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "normal", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "reopen", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "reservationFailure", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RequestChannelClose_reason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RequestChannelClose_reason, ett_h245_RequestChannelClose_reason, RequestChannelClose_reason_choice, "reason", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string RequestChannelCloseReject_cause_vals[] = {
+ { 0, "unspecified" },
+ { 0, NULL }
+};
+static per_choice_t RequestChannelCloseReject_cause_choice[] = {
+ { 0, "unspecified", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RequestChannelCloseReject_cause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RequestChannelCloseReject_cause, ett_h245_RequestChannelCloseReject_cause, RequestChannelCloseReject_cause_choice, "cause", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string MultiplexEntryRejectionDescriptions_cause_vals[] = {
+ { 0, "unspecifiedCause" },
+ { 1, "descriptorTooComplex" },
+ { 0, NULL }
+};
+static per_choice_t MultiplexEntryRejectionDescriptions_cause_choice[] = {
+ { 0, "unspecifiedCause", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "descriptorTooComplex", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultiplexEntryRejectionDescriptions_cause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultiplexEntryRejectionDescriptions_cause, ett_h245_MultiplexEntryRejectionDescriptions_cause, MultiplexEntryRejectionDescriptions_cause_choice, "cause", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string RequestMultiplexEntryRejectionDescriptions_cause_vals[] = {
+ { 0, "unspecifiedCause" },
+ { 0, NULL }
+};
+static per_choice_t RequestMultiplexEntryRejectionDescriptions_cause_choice[] = {
+ { 0, "unspecifiedCause", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RequestMultiplexEntryRejectionDescriptions_cause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RequestMultiplexEntryRejectionDescriptions_cause, ett_h245_RequestMultiplexEntryRejectionDescriptions_cause, RequestMultiplexEntryRejectionDescriptions_cause_choice, "cause", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string RequestModeReject_cause_vals[] = {
+ { 0, "modeUnavailable" },
+ { 1, "multipointConstraint" },
+ { 2, "requestDenied" },
+ { 0, NULL }
+};
+static per_choice_t RequestModeReject_cause_choice[] = {
+ { 0, "modeUnavailable", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "multipointConstraint", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "requestDenied", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RequestModeReject_cause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RequestModeReject_cause, ett_h245_RequestModeReject_cause, RequestModeReject_cause_choice, "cause", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string V76ModeParameters_vals[] = {
+ { 0, "suspendResumewAddress" },
+ { 1, "suspendResumewoAddress" },
+ { 0, NULL }
+};
+static per_choice_t V76ModeParameters_choice[] = {
+ { 0, "suspendResumewAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "suspendResumewoAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_V76ModeParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_V76ModeParameters, ett_h245_V76ModeParameters, V76ModeParameters_choice, "V76ModeParameters", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string H262VideoMode_profileAndLevel_vals[] = {
+ { 0, "profileAndLevel-SPatML" },
+ { 1, "profileAndLevel-MPatLL" },
+ { 2, "profileAndLevel-MPatML" },
+ { 3, "profileAndLevel-MPatH-14" },
+ { 4, "profileAndLevel-MPatHL" },
+ { 5, "profileAndLevel-SNRatLL" },
+ { 6, "profileAndLevel-SNRatML" },
+ { 7, "profileAndLevel-SpatialH-14" },
+ { 8, "profileAndLevel-HPatML" },
+ { 9, "profileAndLevel-HPatH-14" },
+ { 10, "profileAndLevel-HPatHL" },
+ { 0, NULL }
+};
+static per_choice_t H262VideoMode_profileAndLevel_choice[] = {
+ { 0, "profileAndLevel-SPatML", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "profileAndLevel-MPatLL", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "profileAndLevel-MPatML", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "profileAndLevel-MPatH-14", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "profileAndLevel-MPatHL", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "profileAndLevel-SNRatLL", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "profileAndLevel-SNRatML", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "profileAndLevel-SpatialH-14", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 8, "profileAndLevel-HPatML", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 9, "profileAndLevel-HPatH-14", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 10, "profileAndLevel-HPatHL", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H262VideoMode_profileAndLevel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H262VideoMode_profileAndLevel, ett_h245_H262VideoMode_profileAndLevel, H262VideoMode_profileAndLevel_choice, "profileAndLevel", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string H263VideoMode_resolution_vals[] = {
+ { 0, "sqcif" },
+ { 1, "qcif" },
+ { 2, "cif" },
+ { 3, "cif4" },
+ { 4, "cif16" },
+ { 5, "custom" },
+ { 0, NULL }
+};
+static per_choice_t H263VideoMode_resolution_choice[] = {
+ { 0, "sqcif", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "qcif", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "cif", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "cif4", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "cif16", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "custom", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H263VideoMode_resolution(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H263VideoMode_resolution, ett_h245_H263VideoMode_resolution, H263VideoMode_resolution_choice, "resolution", NULL);
+
+ return offset;
+}
+
+
+static const value_string AudioMode_g7231_vals[] = {
+ { 0, "noSilenceSuppressionLowRate" },
+ { 1, "noSilenceSuppressionHighRate" },
+ { 2, "silenceSuppressionLowRate" },
+ { 3, "silenceSuppressionHighRate" },
+ { 0, NULL }
+};
+static per_choice_t AudioMode_g7231_choice[] = {
+ { 0, "noSilenceSuppressionLowRate", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "noSilenceSuppressionHighRate", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 2, "silenceSuppressionLowRate", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 3, "silenceSuppressionHighRate", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_AudioMode_g7231(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_AudioMode_g7231, ett_h245_AudioMode_g7231, AudioMode_g7231_choice, "g7231", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string IS11172AudioMode_audioLayer_vals[] = {
+ { 0, "audioLayer1" },
+ { 1, "audioLayer2" },
+ { 2, "audioLayer3" },
+ { 0, NULL }
+};
+static per_choice_t IS11172AudioMode_audioLayer_choice[] = {
+ { 0, "audioLayer1", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "audioLayer2", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 2, "audioLayer3", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_IS11172AudioMode_audioLayer(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_IS11172AudioMode_audioLayer, ett_h245_IS11172AudioMode_audioLayer, IS11172AudioMode_audioLayer_choice, "audioLayer", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string IS11172AudioMode_audioSampling_vals[] = {
+ { 0, "audioSampling32k" },
+ { 1, "audioSampling44k1" },
+ { 2, "audioSampling48k" },
+ { 0, NULL }
+};
+static per_choice_t IS11172AudioMode_audioSampling_choice[] = {
+ { 0, "audioSampling32k", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "audioSampling44k1", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 2, "audioSampling48k", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_IS11172AudioMode_audioSampling(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_IS11172AudioMode_audioSampling, ett_h245_IS11172AudioMode_audioSampling, IS11172AudioMode_audioSampling_choice, "audioSampling", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string IS11172AudioMode_multichannelType_vals[] = {
+ { 0, "singleChannel" },
+ { 1, "twoChannelStereo" },
+ { 2, "twoChannelDual" },
+ { 0, NULL }
+};
+static per_choice_t IS11172AudioMode_multichannelType_choice[] = {
+ { 0, "singleChannel", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "twoChannelStereo", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 2, "twoChannelDual", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_IS11172AudioMode_multichannelType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_IS11172AudioMode_multichannelType, ett_h245_IS11172AudioMode_multichannelType, IS11172AudioMode_multichannelType_choice, "multichannelType", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string IS13818AudioMode_audioLayer_vals[] = {
+ { 0, "audioLayer1" },
+ { 1, "audioLayer2" },
+ { 2, "audioLayer3" },
+ { 0, NULL }
+};
+static per_choice_t IS13818AudioMode_audioLayer_choice[] = {
+ { 0, "audioLayer1", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "audioLayer2", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 2, "audioLayer3", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_IS13818AudioMode_audioLayer(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_IS13818AudioMode_audioLayer, ett_h245_IS13818AudioMode_audioLayer, IS13818AudioMode_audioLayer_choice, "audioLayer", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string IS13818AudioMode_audioSampling_vals[] = {
+ { 0, "audioSampling16k" },
+ { 1, "audioSampling22k05" },
+ { 2, "audioSampling24k" },
+ { 3, "audioSampling32k" },
+ { 4, "audioSampling44k1" },
+ { 5, "audioSampling48k" },
+ { 0, NULL }
+};
+static per_choice_t IS13818AudioMode_audioSampling_choice[] = {
+ { 0, "audioSampling16k", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "audioSampling22k05", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 2, "audioSampling24k", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 3, "audioSampling32k", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 4, "audioSampling44k1", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 5, "audioSampling48k", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_IS13818AudioMode_audioSampling(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_IS13818AudioMode_audioSampling, ett_h245_IS13818AudioMode_audioSampling, IS13818AudioMode_audioSampling_choice, "audioSampling", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string IS13818AudioMode_multiChannelType_vals[] = {
+ { 0, "singleChannel" },
+ { 1, "twoChannelStereo" },
+ { 2, "twoChannelDual" },
+ { 3, "threeChannels2-1" },
+ { 4, "threeChannels3-0" },
+ { 5, "fourChannels2-0-2-0" },
+ { 6, "fourChannels2-2" },
+ { 7, "fourChannels3-1" },
+ { 8, "fiveChannels3-0-2-0" },
+ { 9, "fiveChannels3-2" },
+ { 0, NULL }
+};
+static per_choice_t IS13818AudioMode_multiChannelType_choice[] = {
+ { 0, "singleChannel", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "twoChannelStereo", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 2, "twoChannelDual", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 3, "threeChannels2-1", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 4, "threeChannels3-0", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 5, "fourChannels2-0-2-0", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 6, "fourChannels2-2", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 7, "fourChannels3-1", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 8, "fiveChannels3-0-2-0", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 9, "fiveChannels3-2", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_IS13818AudioMode_multiChannelType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_IS13818AudioMode_multiChannelType, ett_h245_IS13818AudioMode_multiChannelType, IS13818AudioMode_multiChannelType_choice, "multiChannelType", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string MaintenanceLoopReject_cause_vals[] = {
+ { 0, "canNotPerformLoop" },
+ { 0, NULL }
+};
+static per_choice_t MaintenanceLoopReject_cause_choice[] = {
+ { 0, "canNotPerformLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MaintenanceLoopReject_cause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MaintenanceLoopReject_cause, ett_h245_MaintenanceLoopReject_cause, MaintenanceLoopReject_cause_choice, "cause", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string ConferenceResponse_makeMeChairResponse_vals[] = {
+ { 0, "grantedChairToken" },
+ { 1, "deniedChairToken" },
+ { 0, NULL }
+};
+static per_choice_t ConferenceResponse_makeMeChairResponse_choice[] = {
+ { 0, "grantedChairToken", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "deniedChairToken", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_makeMeChairResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_makeMeChairResponse, ett_h245_ConferenceResponse_makeMeChairResponse, ConferenceResponse_makeMeChairResponse_choice, "makeMeChairResponse", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string ConferenceResponse_broadcastMyLogicalChannelResponse_vals[] = {
+ { 0, "grantedBroadcastMyLogicalChannel" },
+ { 1, "deniedBroadcastMyLogicalChannel" },
+ { 0, NULL }
+};
+static per_choice_t ConferenceResponse_broadcastMyLogicalChannelResponse_choice[] = {
+ { 0, "grantedBroadcastMyLogicalChannel", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "deniedBroadcastMyLogicalChannel", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_broadcastMyLogicalChannelResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_broadcastMyLogicalChannelResponse, ett_h245_ConferenceResponse_broadcastMyLogicalChannelResponse, ConferenceResponse_broadcastMyLogicalChannelResponse_choice, "broadcastMyLogicalChannelResponse", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string ConferenceResponse_makeTerminalBroadcasterResponse_vals[] = {
+ { 0, "grantedMakeTerminalBroadcaster" },
+ { 1, "deniedMakeTerminalBroadcaster" },
+ { 0, NULL }
+};
+static per_choice_t ConferenceResponse_makeTerminalBroadcasterResponse_choice[] = {
+ { 0, "grantedMakeTerminalBroadcaster", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "deniedMakeTerminalBroadcaster", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_makeTerminalBroadcasterResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_makeTerminalBroadcasterResponse, ett_h245_ConferenceResponse_makeTerminalBroadcasterResponse, ConferenceResponse_makeTerminalBroadcasterResponse_choice, "makeTerminalBroadcasterResponse", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string ConferenceResponse_sendThisSourceResponse_vals[] = {
+ { 0, "grantedSendThisSource" },
+ { 1, "deniedSendThisSource" },
+ { 0, NULL }
+};
+static per_choice_t ConferenceResponse_sendThisSourceResponse_choice[] = {
+ { 0, "grantedSendThisSource", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "deniedSendThisSource", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_sendThisSourceResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_sendThisSourceResponse, ett_h245_ConferenceResponse_sendThisSourceResponse, ConferenceResponse_sendThisSourceResponse_choice, "sendThisSourceResponse", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string RemoteMCRequest_vals[] = {
+ { 0, "masterActivate" },
+ { 1, "slaveActivate" },
+ { 2, "deActivate" },
+ { 0, NULL }
+};
+static per_choice_t RemoteMCRequest_choice[] = {
+ { 0, "masterActivate", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "slaveActivate", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "deActivate", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RemoteMCRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RemoteMCRequest, ett_h245_RemoteMCRequest, RemoteMCRequest_choice, "RemoteMCRequest", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string RemoteMCResponse_reject_vals[] = {
+ { 0, "unspecified" },
+ { 1, "functionNotSupported" },
+ { 0, NULL }
+};
+static per_choice_t RemoteMCResponse_reject_choice[] = {
+ { 0, "unspecified", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "functionNotSupported", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RemoteMCResponse_reject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RemoteMCResponse_reject, ett_h245_RemoteMCResponse_reject, RemoteMCResponse_reject_choice, "reject", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string RemoteMCResponse_vals[] = {
+ { 0, "accept" },
+ { 1, "reject" },
+ { 0, NULL }
+};
+static per_choice_t RemoteMCResponse_choice[] = {
+ { 0, "accept", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "reject", ASN1_EXTENSION_ROOT,
+ dissect_h245_RemoteMCResponse_reject },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RemoteMCResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RemoteMCResponse, ett_h245_RemoteMCResponse, RemoteMCResponse_choice, "RemoteMCResponse", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string MultilinkResponse_addConnection_responseCode_rejected_vals[] = {
+ { 0, "connectionNotAvailable" },
+ { 1, "userRejected" },
+ { 0, NULL }
+};
+static per_choice_t MultilinkResponse_addConnection_responseCode_rejected_choice[] = {
+ { 0, "connectionNotAvailable", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "userRejected", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultilinkResponse_addConnection_responseCode_rejected(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultilinkResponse_addConnection_responseCode_rejected, ett_h245_MultilinkResponse_addConnection_responseCode_rejected, MultilinkResponse_addConnection_responseCode_rejected_choice, "rejected", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string MultilinkResponse_addConnection_responseCode_vals[] = {
+ { 0, "accepted" },
+ { 1, "rejected" },
+ { 0, NULL }
+};
+static per_choice_t MultilinkResponse_addConnection_responseCode_choice[] = {
+ { 0, "accepted", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "rejected", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkResponse_addConnection_responseCode_rejected },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultilinkResponse_addConnection_responseCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultilinkResponse_addConnection_responseCode, ett_h245_MultilinkResponse_addConnection_responseCode, MultilinkResponse_addConnection_responseCode_choice, "responseCode", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string LogicalChannelRateRejectReason_vals[] = {
+ { 0, "undefinedReason" },
+ { 1, "insufficientResources" },
+ { 0, NULL }
+};
+static per_choice_t LogicalChannelRateRejectReason_choice[] = {
+ { 0, "undefinedReason", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "insufficientResources", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_LogicalChannelRateRejectReason(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_LogicalChannelRateRejectReason, ett_h245_LogicalChannelRateRejectReason, LogicalChannelRateRejectReason_choice, "LogicalChannelRateRejectReason", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string EndSessionCommand_gstnOptions_vals[] = {
+ { 0, "telephonyMode" },
+ { 1, "v8bis" },
+ { 2, "v34DSVD" },
+ { 3, "v34DuplexFax" },
+ { 4, "v34H324" },
+ { 0, NULL }
+};
+static per_choice_t EndSessionCommand_gstnOptions_choice[] = {
+ { 0, "telephonyMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "v8bis", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "v34DSVD", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "v34DuplexFax", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "v34H324", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_EndSessionCommand_gstnOptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_EndSessionCommand_gstnOptions, ett_h245_EndSessionCommand_gstnOptions, EndSessionCommand_gstnOptions_choice, "gstnOptions", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string EndSessionCommand_isdnOptions_vals[] = {
+ { 0, "telephonyMode" },
+ { 1, "v140" },
+ { 2, "terminalOnHold" },
+ { 0, NULL }
+};
+static per_choice_t EndSessionCommand_isdnOptions_choice[] = {
+ { 0, "telephonyMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "v140", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "terminalOnHold", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_EndSessionCommand_isdnOptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_EndSessionCommand_isdnOptions, ett_h245_EndSessionCommand_isdnOptions, EndSessionCommand_isdnOptions_choice, "isdnOptions", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string MiscellaneousCommand_type_progressiveRefinementStart_repeatCount_vals[] = {
+ { 0, "doOneProgression" },
+ { 1, "doContinousProgressions" },
+ { 2, "doOneIndependentProgression" },
+ { 3, "doContinousIndependentProgressions" },
+ { 0, NULL }
+};
+static per_choice_t MiscellaneousCommand_type_progressiveRefinementStart_repeatCount_choice[] = {
+ { 0, "doOneProgression", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "doContinousProgressions", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "doOneIndependentProgression", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "doContinousIndependentProgressions", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousCommand_type_progressiveRefinementStart_repeatCount(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MiscellaneousCommand_type_progressiveRefinementStart_repeatCount, ett_h245_MiscellaneousCommand_type_progressiveRefinementStart_repeatCount, MiscellaneousCommand_type_progressiveRefinementStart_repeatCount_choice, "repeatCount", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MiscellaneousCommand_type_progressiveRefinementStart_sequence[] = {
+ { "repeatCount", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MiscellaneousCommand_type_progressiveRefinementStart_repeatCount },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousCommand_type_progressiveRefinementStart(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MiscellaneousCommand_type_progressiveRefinementStart, ett_h245_MiscellaneousCommand_type_progressiveRefinementStart, MiscellaneousCommand_type_progressiveRefinementStart_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string H223MultiplexReconfiguration_h223ModeChange_vals[] = {
+ { 0, "toLevel0" },
+ { 1, "toLevel1" },
+ { 2, "toLevel2" },
+ { 3, "toLevel2WithOptionalHeader" },
+ { 0, NULL }
+};
+static per_choice_t H223MultiplexReconfiguration_h223ModeChange_choice[] = {
+ { 0, "toLevel0", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "toLevel1", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "toLevel2", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "toLevel2WithOptionalHeader", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223MultiplexReconfiguration_h223ModeChange(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223MultiplexReconfiguration_h223ModeChange, ett_h245_H223MultiplexReconfiguration_h223ModeChange, H223MultiplexReconfiguration_h223ModeChange_choice, "h223ModeChange", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string H223MultiplexReconfiguration_h223AnnexADoubleFlag_vals[] = {
+ { 0, "start" },
+ { 1, "stop" },
+ { 0, NULL }
+};
+static per_choice_t H223MultiplexReconfiguration_h223AnnexADoubleFlag_choice[] = {
+ { 0, "start", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "stop", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223MultiplexReconfiguration_h223AnnexADoubleFlag(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223MultiplexReconfiguration_h223AnnexADoubleFlag, ett_h245_H223MultiplexReconfiguration_h223AnnexADoubleFlag, H223MultiplexReconfiguration_h223AnnexADoubleFlag_choice, "h223AnnexADoubleFlag", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string H223MultiplexReconfiguration_vals[] = {
+ { 0, "h233ModeChange" },
+ { 1, "h223AnnexADoubleFlag" },
+ { 0, NULL }
+};
+static per_choice_t H223MultiplexReconfiguration_choice[] = {
+ { 0, "h233ModeChange", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223MultiplexReconfiguration_h223ModeChange },
+ { 1, "h223AnnexADoubleFlag", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223MultiplexReconfiguration_h223AnnexADoubleFlag },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223MultiplexReconfiguration(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223MultiplexReconfiguration, ett_h245_H223MultiplexReconfiguration, H223MultiplexReconfiguration_choice, "H223MultiplexReconfiguration", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string NewATMVCCommand_aal_aal1_clockRecovery_vals[] = {
+ { 0, "nullClockRecovery" },
+ { 1, "srtsClockRecovery" },
+ { 2, "adaptiveClockRecovery" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCCommand_aal_aal1_clockRecovery_choice[] = {
+ { 0, "nullClockRecovery", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "srtsClockRecovery", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "adaptiveClockRecovery", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCCommand_aal_aal1_clockRecovery(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCCommand_aal_aal1_clockRecovery, ett_h245_NewATMVCCommand_aal_aal1_clockRecovery, NewATMVCCommand_aal_aal1_clockRecovery_choice, "clockRecovery", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string NewATMVCCommand_aal_aal1_errorCorrection_vals[] = {
+ { 0, "nullErrorCorrection" },
+ { 1, "longInterleaver" },
+ { 2, "shortInterleaver" },
+ { 3, "errorCorrectionOnly" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCCommand_aal_aal1_errorCorrection_choice[] = {
+ { 0, "nullErrorCorrection", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "longInterleaver", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "shortInterleaver", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "errorCorrectionOnly", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCCommand_aal_aal1_errorCorrection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCCommand_aal_aal1_errorCorrection, ett_h245_NewATMVCCommand_aal_aal1_errorCorrection, NewATMVCCommand_aal_aal1_errorCorrection_choice, "errorCorrection", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string NewATMVCCommand_multiplex_vals[] = {
+ { 0, "noMultiplex" },
+ { 1, "transportStream" },
+ { 2, "programStream" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCCommand_multiplex_choice[] = {
+ { 0, "noMultiplex", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "transportStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "programStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCCommand_multiplex(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCCommand_multiplex, ett_h245_NewATMVCCommand_multiplex, NewATMVCCommand_multiplex_choice, "multiplex", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string NewATMVCCommand_reverseParameters_multiplex_vals[] = {
+ { 0, "noMultiplex" },
+ { 1, "transportStream" },
+ { 2, "programStream" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCCommand_reverseParameters_multiplex_choice[] = {
+ { 0, "noMultiplex", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "transportStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "programStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCCommand_reverseParameters_multiplex(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCCommand_reverseParameters_multiplex, ett_h245_NewATMVCCommand_reverseParameters_multiplex, NewATMVCCommand_reverseParameters_multiplex_choice, "multiplex", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string MobileMultilinkReconfigurationCommand_status_vals[] = {
+ { 0, "synchronized" },
+ { 1, "reconfiguration" },
+ { 0, NULL }
+};
+static per_choice_t MobileMultilinkReconfigurationCommand_status_choice[] = {
+ { 0, "synchronized", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "reconfiguration", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MobileMultilinkReconfigurationCommand_status(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MobileMultilinkReconfigurationCommand_status, ett_h245_MobileMultilinkReconfigurationCommand_status, MobileMultilinkReconfigurationCommand_status_choice, "status", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string FunctionNotSupported_cause_vals[] = {
+ { 0, "syntaxError" },
+ { 1, "semanticError" },
+ { 2, "unknownFunction" },
+ { 0, NULL }
+};
+static per_choice_t FunctionNotSupported_cause_choice[] = {
+ { 0, "syntaxError", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "semanticError", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "unknownFunction", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FunctionNotSupported_cause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FunctionNotSupported_cause, ett_h245_FunctionNotSupported_cause, FunctionNotSupported_cause_choice, "cause", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string NewATMVCIndication_aal_aal1_clockRecovery_vals[] = {
+ { 0, "nullClockRecovery" },
+ { 1, "srtsClockRecovery" },
+ { 2, "adaptiveClockRecovery" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCIndication_aal_aal1_clockRecovery_choice[] = {
+ { 0, "nullClockRecovery", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "srtsClockRecovery", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "adaptiveClockRecovery", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCIndication_aal_aal1_clockRecovery(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCIndication_aal_aal1_clockRecovery, ett_h245_NewATMVCIndication_aal_aal1_clockRecovery, NewATMVCIndication_aal_aal1_clockRecovery_choice, "clockRecovery", NULL);
+
+ return offset;
+}
+
+
+
+static const value_string NewATMVCIndication_aal_aal1_errorCorrection_vals[] = {
+ { 0, "nullErrorCorrection" },
+ { 1, "longInterleaver" },
+ { 2, "shortInterleaver" },
+ { 3, "errorCorrectionOnly" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCIndication_aal_aal1_errorCorrection_choice[] = {
+ { 0, "nullErrorCorrection", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "longInterleaver", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "shortInterleaver", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "errorCorrectionOnly", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCIndication_aal_aal1_errorCorrection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCIndication_aal_aal1_errorCorrection, ett_h245_NewATMVCIndication_aal_aal1_errorCorrection, NewATMVCIndication_aal_aal1_errorCorrection_choice, "errorCorrection", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string NewATMVCIndication_multiplex_vals[] = {
+ { 0, "noMultiplex" },
+ { 1, "transportStream" },
+ { 2, "programStream" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCIndication_multiplex_choice[] = {
+ { 0, "noMultiplex", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "transportStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "programStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCIndication_multiplex(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCIndication_multiplex, ett_h245_NewATMVCIndication_multiplex, NewATMVCIndication_multiplex_choice, "multiplex", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string NewATMVCIndication_reverseParameters_multiplex_vals[] = {
+ { 0, "noMultiplex" },
+ { 1, "transportStream" },
+ { 2, "programStream" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCIndication_reverseParameters_multiplex_choice[] = {
+ { 0, "noMultiplex", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "transportStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "programStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCIndication_reverseParameters_multiplex(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCIndication_reverseParameters_multiplex, ett_h245_NewATMVCIndication_reverseParameters_multiplex, NewATMVCIndication_reverseParameters_multiplex_choice, "multiplex", NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_LogicalChannelNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_LogicalChannelNumber, 1, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+static int
+dissect_h245_logicalChannelNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_LogicalChannelNumber, 0, 65535,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static int
+dissect_h245_SequenceNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_SequenceNumber, 0, 255,
+ NULL, NULL, FALSE);
+ return offset;
+}
+
+
+
+
+static const value_string MaintenanceLoopRequest_type_vals[] = {
+ { 0, "systemLoop" },
+ { 1, "mediaLoop" },
+ { 2, "logicalChannelLoop" },
+ { 0, NULL }
+};
+static per_choice_t MaintenanceLoopRequest_type_choice[] = {
+ { 0, "systemLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "mediaLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelNumber },
+ { 2, "logicalChannelLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelNumber },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MaintenanceLoopRequest_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MaintenanceLoopRequest_type, ett_h245_MaintenanceLoopRequest_type, MaintenanceLoopRequest_type_choice, "type", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string MaintenanceLoopAck_type_vals[] = {
+ { 0, "systemLoop" },
+ { 1, "mediaLoop" },
+ { 2, "logicalChannelLoop" },
+ { 0, NULL }
+};
+static per_choice_t MaintenanceLoopAck_type_choice[] = {
+ { 0, "systemLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "mediaLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelNumber },
+ { 2, "logicalChannelLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelNumber },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MaintenanceLoopAck_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MaintenanceLoopAck_type, ett_h245_MaintenanceLoopAck_type, MaintenanceLoopAck_type_choice, "type", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string MaintenanceLoopReject_type_vals[] = {
+ { 0, "systemLoop" },
+ { 1, "mediaLoop" },
+ { 2, "logicalChannelLoop" },
+ { 0, NULL }
+};
+static per_choice_t MaintenanceLoopReject_type_choice[] = {
+ { 0, "systemLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "mediaLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelNumber },
+ { 2, "logicalChannelLoop", ASN1_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelNumber },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MaintenanceLoopReject_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MaintenanceLoopReject_type, ett_h245_MaintenanceLoopReject_type, MaintenanceLoopReject_type_choice, "type", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t OpenLogicalChannelReject_sequence[] = {
+ { "forwardLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "cause", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_OpenLogicalChannelReject_cause },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_OpenLogicalChannelReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannelReject, ett_h245_OpenLogicalChannelReject, OpenLogicalChannelReject_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t CloseLogicalChannel_sequence[] = {
+ { "forwardLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "source", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_CloseLogicalChannel_source },
+ { "reason", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_CloseLogicalChannel_reason },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CloseLogicalChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CloseLogicalChannel, ett_h245_CloseLogicalChannel, CloseLogicalChannel_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t CloseLogicalChannelAck_sequence[] = {
+ { "forwardLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CloseLogicalChannelAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CloseLogicalChannelAck, ett_h245_CloseLogicalChannelAck, CloseLogicalChannelAck_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RequestChannelCloseAck_sequence[] = {
+ { "forwardLogiclChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestChannelCloseAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestChannelCloseAck, ett_h245_RequestChannelCloseAck, RequestChannelCloseAck_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RequestChannelCloseReject_sequence[] = {
+ { "forwardLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "cause", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RequestChannelCloseReject_cause },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestChannelCloseReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestChannelCloseReject, ett_h245_RequestChannelCloseReject, RequestChannelCloseReject_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RequestChannelCloseRelease_sequence[] = {
+ { "forwardLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestChannelCloseRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestChannelCloseRelease, ett_h245_RequestChannelCloseRelease, RequestChannelCloseRelease_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t MultiplexedStreamModeParameters_sequence[] = {
+ { "logicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexedStreamModeParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexedStreamModeParameters, ett_h245_MultiplexedStreamModeParameters, MultiplexedStreamModeParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MaintenanceLoopRequest_sequence[] = {
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MaintenanceLoopRequest_type },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MaintenanceLoopRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MaintenanceLoopRequest, ett_h245_MaintenanceLoopRequest, MaintenanceLoopRequest_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MaintenanceLoopAck_sequence[] = {
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MaintenanceLoopAck_type },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MaintenanceLoopAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MaintenanceLoopAck, ett_h245_MaintenanceLoopAck, MaintenanceLoopAck_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MaintenanceLoopReject_sequence[] = {
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MaintenanceLoopReject_type },
+ { "cause", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MaintenanceLoopReject_cause },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MaintenanceLoopReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MaintenanceLoopReject, ett_h245_MaintenanceLoopReject, MaintenanceLoopReject_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t UserInputIndication_signalUpdate_rtp_sequence[] = {
+ { "logicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_UserInputIndication_signalUpdate_rtp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_UserInputIndication_signalUpdate_rtp, ett_h245_UserInputIndication_signalUpdate_rtp, UserInputIndication_signalUpdate_rtp_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t OpenLogicalChannelConfirm_sequence[] = {
+ { "forwardLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_OpenLogicalChannelConfirm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannelConfirm, ett_h245_OpenLogicalChannelConfirm, OpenLogicalChannelConfirm_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t TerminalCapabilitySetAck_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_TerminalCapabilitySetAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySetAck, ett_h245_TerminalCapabilitySetAck, TerminalCapabilitySetAck_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t RequestModeReject_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "cause", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RequestModeReject_cause },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestModeReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestModeReject, ett_h245_RequestModeReject, RequestModeReject_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RoundTripDelayRequest_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RoundTripDelayRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RoundTripDelayRequest, ett_h245_RoundTripDelayRequest, RoundTripDelayRequest_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RoundTripDelayResponse_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RoundTripDelayResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RoundTripDelayResponse, ett_h245_RoundTripDelayResponse, RoundTripDelayResponse_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MultilinkResponse_addConnection_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "responseCode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultilinkResponse_addConnection_responseCode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultilinkResponse_addConnection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkResponse_addConnection, ett_h245_MultilinkResponse_addConnection, MultilinkResponse_addConnection_sequence);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_h233EncryptionTransmitCapability_bit = {
+ "h233EncryptionTransmitCapability bit is SET",
+ "h233EncryptionTransmitCapability bit is CLEAR"
+};
+static int
+dissect_h245_h233EncryptionTransmitCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_h233EncryptionTransmitCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+static const true_false_string tfs_nullClockRecovery_bit = {
+ "nullClockRecovery bit is SET",
+ "nullClockRecovery bit is CLEAR"
+};
+static int
+dissect_h245_nullClockRecovery(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_nullClockRecovery, NULL, NULL);
+
+ return offset;
+}
+
+
+static const true_false_string tfs_srtsClockRecovery_bit = {
+ "srtsClockRecovery bit is SET",
+ "srtsClockRecovery bit is CLEAR"
+};
+static int
+dissect_h245_srtsClockRecovery(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_srtsClockRecovery, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static const true_false_string tfs_adaptiveClockRecovery_bit = {
+ "adaptiveClockRecovery bit is SET",
+ "adaptiveClockRecovery bit is CLEAR"
+};
+static int
+dissect_h245_adaptiveClockRecovery(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_adaptiveClockRecovery, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_nullErrorCorrection_bit = {
+ "nullErrorCorrection bit is SET",
+ "nullErrorCorrection bit is CLEAR"
+};
+static int
+dissect_h245_nullErrorCorrection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_nullErrorCorrection, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static const true_false_string tfs_longInterleaver_bit = {
+ "longInterleaver bit is SET",
+ "longInterleaver bit is CLEAR"
+};
+static int
+dissect_h245_longInterleaver(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_longInterleaver, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static const true_false_string tfs_shortInterleaver_bit = {
+ "shortInterleaver bit is SET",
+ "shortInterleaver bit is CLEAR"
+};
+static int
+dissect_h245_shortInterleaver(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_shortInterleaver, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static const true_false_string tfs_errorCorrectionOnly_bit = {
+ "errorCorrectionOnly bit is SET",
+ "errorCorrectionOnly bit is CLEAR"
+};
+static int
+dissect_h245_errorCorrectionOnly(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_errorCorrectionOnly, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_structuredDataTransfer_bit = {
+ "structuredDataTransfer bit is SET",
+ "structuredDataTransfer bit is CLEAR"
+};
+static int
+dissect_h245_structuredDataTransfer(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_structuredDataTransfer, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_partiallyFilledCells_bit = {
+ "partiallyFilledCells bit is SET",
+ "partiallyFilledCells bit is CLEAR"
+};
+static int
+dissect_h245_partiallyFilledCells(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_partiallyFilledCells, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t VCCapability_aal1_sequence[] = {
+ { "nullClockRecovery", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_nullClockRecovery },
+ { "srtsClockRecovery", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_srtsClockRecovery },
+ { "adaptiveClockRecovery", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_adaptiveClockRecovery },
+ { "nullErrorCorrection", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_nullErrorCorrection },
+ { "longInterleaver", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_longInterleaver },
+ { "shortInterleaver", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_shortInterleaver },
+ { "errorCorrectionOnly", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_errorCorrectionOnly },
+ { "structuredDataTransfer", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_structuredDataTransfer },
+ { "partiallyFilledCells", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_partiallyFilledCells },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VCCapability_aal1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VCCapability_aal1, ett_h245_VCCapability_aal1, VCCapability_aal1_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t NewATMVCCommand_aal_aal1_sequence[] = {
+ { "clockRecovery", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCCommand_aal_aal1_clockRecovery },
+ { "errorCorrection", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCCommand_aal_aal1_errorCorrection },
+ { "structuredDataTransfer", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_structuredDataTransfer },
+ { "partiallyFilledCells", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_partiallyFilledCells },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCCommand_aal_aal1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NewATMVCCommand_aal_aal1, ett_h245_NewATMVCCommand_aal_aal1, NewATMVCCommand_aal_aal1_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t NewATMVCIndication_aal_aal1_sequence[] = {
+ { "clockRecovery", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCIndication_aal_aal1_clockRecovery },
+ { "errorCorrection", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCIndication_aal_aal1_errorCorrection },
+ { "structuredDataTransfer", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_structuredDataTransfer },
+ { "partiallyFilledCells", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_partiallyFilledCells },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCIndication_aal_aal1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NewATMVCIndication_aal_aal1, ett_h245_NewATMVCIndication_aal_aal1, NewATMVCIndication_aal_aal1_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_transportStream_bit = {
+ "transportStream bit is SET",
+ "transportStream bit is CLEAR"
+};
+static int
+dissect_h245_transportStream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_transportStream, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_programStream_bit = {
+ "programStream bit is SET",
+ "programStream bit is CLEAR"
+};
+static int
+dissect_h245_programStream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_programStream, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_videoWithAL1_bit = {
+ "videoWithAL1 bit is SET",
+ "videoWithAL1 bit is CLEAR"
+};
+static int
+dissect_h245_videoWithAL1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoWithAL1, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_videoWithAL2_bit = {
+ "videoWithAL2 bit is SET",
+ "videoWithAL2 bit is CLEAR"
+};
+static int
+dissect_h245_videoWithAL2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoWithAL2, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_videoWithAL3_bit = {
+ "videoWithAL3 bit is SET",
+ "videoWithAL3 bit is CLEAR"
+};
+static int
+dissect_h245_videoWithAL3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoWithAL3, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioWithAL1_bit = {
+ "audioWithAL1 bit is SET",
+ "audioWithAL1 bit is CLEAR"
+};
+static int
+dissect_h245_audioWithAL1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioWithAL1, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioWithAL2_bit = {
+ "audioWithAL2 bit is SET",
+ "audioWithAL2 bit is CLEAR"
+};
+static int
+dissect_h245_audioWithAL2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioWithAL2, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioWithAL3_bit = {
+ "audioWithAL3 bit is SET",
+ "audioWithAL3 bit is CLEAR"
+};
+static int
+dissect_h245_audioWithAL3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioWithAL3, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dataWithAL1_bit = {
+ "dataWithAL1 bit is SET",
+ "dataWithAL1 bit is CLEAR"
+};
+static int
+dissect_h245_dataWithAL1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dataWithAL1, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dataWithAL2_bit = {
+ "dataWithAL2 bit is SET",
+ "dataWithAL2 bit is CLEAR"
+};
+static int
+dissect_h245_dataWithAL2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dataWithAL2, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dataWithAL3_bit = {
+ "dataWithAL3 bit is SET",
+ "dataWithAL3 bit is CLEAR"
+};
+static int
+dissect_h245_dataWithAL3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dataWithAL3, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static const true_false_string tfs_maxMUXPDUSizeCapability_bit = {
+ "maxMUXPDUSizeCapability bit is SET",
+ "maxMUXPDUSizeCapability bit is CLEAR"
+};
+static int
+dissect_h245_maxMUXPDUSizeCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_maxMUXPDUSizeCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_nsrpSupport_bit = {
+ "nsrpSupport bit is SET",
+ "nsrpSupport bit is CLEAR"
+};
+static int
+dissect_h245_nsrpSupport(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_nsrpSupport, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_modeChangeCapability_bit = {
+ "modeChangeCapability bit is SET",
+ "modeChangeCapability bit is CLEAR"
+};
+static int
+dissect_h245_modeChangeCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_modeChangeCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_h223AnnexA_bit = {
+ "h223AnnexA bit is SET",
+ "h223AnnexA bit is CLEAR"
+};
+static int
+dissect_h245_h223AnnexA(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_h223AnnexA, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_h223AnnexADoubleFlag_bool_bit = {
+ "h223AnnexADoubleFlag_bool bit is SET",
+ "h223AnnexADoubleFlag_bool bit is CLEAR"
+};
+static int
+dissect_h245_h223AnnexADoubleFlag_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_h223AnnexADoubleFlag_bool, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_h223AnnexB_bit = {
+ "h223AnnexB bit is SET",
+ "h223AnnexB bit is CLEAR"
+};
+static int
+dissect_h245_h223AnnexB(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_h223AnnexB, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_h223AnnexBwithHeader_bit = {
+ "h223AnnexBwithHeader bit is SET",
+ "h223AnnexBwithHeader bit is CLEAR"
+};
+static int
+dissect_h245_h223AnnexBwithHeader(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_h223AnnexBwithHeader, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t H223Capability_mobileOperationTransmitCapability_sequence[] = {
+ { "modeChangeCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_modeChangeCapability },
+ { "h223AnnexA", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h223AnnexA },
+ { "h223AnnexADoubleFlag", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h223AnnexADoubleFlag_bool },
+ { "h223AnnexB", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h223AnnexB },
+ { "h223AnnexBwithHeader", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h223AnnexBwithHeader },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223Capability_mobileOperationTransmitCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223Capability_mobileOperationTransmitCapability, ett_h245_H223Capability_mobileOperationTransmitCapability, H223Capability_mobileOperationTransmitCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_videoWithAL1M_bit = {
+ "videoWithAL1M bit is SET",
+ "videoWithAL1M bit is CLEAR"
+};
+static int
+dissect_h245_videoWithAL1M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoWithAL1M, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_videoWithAL2M_bit = {
+ "videoWithAL2M bit is SET",
+ "videoWithAL2M bit is CLEAR"
+};
+static int
+dissect_h245_videoWithAL2M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoWithAL2M, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_videoWithAL3M_bit = {
+ "videoWithAL3M bit is SET",
+ "videoWithAL3M bit is CLEAR"
+};
+static int
+dissect_h245_videoWithAL3M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoWithAL3M, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioWithAL1M_bit = {
+ "audioWithAL1M bit is SET",
+ "audioWithAL1M bit is CLEAR"
+};
+static int
+dissect_h245_audioWithAL1M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioWithAL1M, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioWithAL2M_bit = {
+ "audioWithAL2M bit is SET",
+ "audioWithAL2M bit is CLEAR"
+};
+static int
+dissect_h245_audioWithAL2M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioWithAL2M, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioWithAL3M_bit = {
+ "audioWithAL3M bit is SET",
+ "audioWithAL3M bit is CLEAR"
+};
+static int
+dissect_h245_audioWithAL3M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioWithAL3M, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dataWithAL1M_bit = {
+ "dataWithAL1M bit is SET",
+ "dataWithAL1M bit is CLEAR"
+};
+static int
+dissect_h245_dataWithAL1M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dataWithAL1M, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dataWithAL2M_bit = {
+ "dataWithAL2M bit is SET",
+ "dataWithAL2M bit is CLEAR"
+};
+static int
+dissect_h245_dataWithAL2M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dataWithAL2M, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dataWithAL3M_bit = {
+ "dataWithAL3M bit is SET",
+ "dataWithAL3M bit is CLEAR"
+};
+static int
+dissect_h245_dataWithAL3M(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dataWithAL3M, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_alpduInterleaving_bit = {
+ "alpduInterleaving bit is SET",
+ "alpduInterleaving bit is CLEAR"
+};
+static int
+dissect_h245_alpduInterleaving(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_alpduInterleaving, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t H223AL2MParameters_sequence[] = {
+ { "headerFEC", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223AL2MParameters_headerFEC },
+ { "alpduInterleaving", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_alpduInterleaving },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223AL2MParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223AL2MParameters, ett_h245_H223AL2MParameters, H223AL2MParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_rsCodeCapability_bit = {
+ "rsCodeCapability bit is SET",
+ "rsCodeCapability bit is CLEAR"
+};
+static int
+dissect_h245_rsCodeCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_rsCodeCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_suspendResumeCapabilitywAddress_bit = {
+ "suspendResumeCapabilitywAddress bit is SET",
+ "suspendResumeCapabilitywAddress bit is CLEAR"
+};
+static int
+dissect_h245_suspendResumeCapabilitywAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_suspendResumeCapabilitywAddress, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_suspendResumeCapabilitywoAddress_bit = {
+ "suspendResumeCapabilitywoAddress bit is SET",
+ "suspendResumeCapabilitywoAddress bit is CLEAR"
+};
+static int
+dissect_h245_suspendResumeCapabilitywoAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_suspendResumeCapabilitywoAddress, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_rejCapability_bit = {
+ "rejCapability bit is SET",
+ "rejCapability bit is CLEAR"
+};
+static int
+dissect_h245_rejCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_rejCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_sREJCapability_bit = {
+ "sREJCapability bit is SET",
+ "sREJCapability bit is CLEAR"
+};
+static int
+dissect_h245_sREJCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_sREJCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_mREJCapability_bit = {
+ "mREJCapability bit is SET",
+ "mREJCapability bit is CLEAR"
+};
+static int
+dissect_h245_mREJCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_mREJCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_crc8bitCapability_bit = {
+ "crc8bitCapability bit is SET",
+ "crc8bitCapability bit is CLEAR"
+};
+static int
+dissect_h245_crc8bitCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_crc8bitCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_crc16bitCapability_bit = {
+ "crc16bitCapability bit is SET",
+ "crc16bitCapability bit is CLEAR"
+};
+static int
+dissect_h245_crc16bitCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_crc16bitCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_crc32bitCapability_bit = {
+ "crc32bitCapability bit is SET",
+ "crc32bitCapability bit is CLEAR"
+};
+static int
+dissect_h245_crc32bitCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_crc32bitCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_uihCapability_bit = {
+ "uihCapability bit is SET",
+ "uihCapability bit is CLEAR"
+};
+static int
+dissect_h245_uihCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_uihCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_twoOctetAddressFieldCapability_bit = {
+ "twoOctetAddressFieldCapability bit is SET",
+ "twoOctetAddressFieldCapability bit is CLEAR"
+};
+static int
+dissect_h245_twoOctetAddressFieldCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_twoOctetAddressFieldCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_loopBackTestCapability_bit = {
+ "loopBackTestCapability bit is SET",
+ "loopBackTestCapability bit is CLEAR"
+};
+static int
+dissect_h245_loopBackTestCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_loopBackTestCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_audioHeader_bit = {
+ "audioHeader bit is SET",
+ "audioHeader bit is CLEAR"
+};
+static int
+dissect_h245_audioHeader(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioHeader, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t V75Capability_sequence[] = {
+ { "audioHeader", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioHeader },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_V75Capability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_V75Capability, ett_h245_V75Capability, V75Capability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_centralizedConferenceMC_bit = {
+ "centralizedConferenceMC bit is SET",
+ "centralizedConferenceMC bit is CLEAR"
+};
+static int
+dissect_h245_centralizedConferenceMC(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_centralizedConferenceMC, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_decentralizedConferenceMC_bit = {
+ "decentralizedConferenceMC bit is SET",
+ "decentralizedConferenceMC bit is CLEAR"
+};
+static int
+dissect_h245_decentralizedConferenceMC(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_decentralizedConferenceMC, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H2250Capability_mcCapability_sequence[] = {
+ { "centralizedConferenceMC", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_centralizedConferenceMC },
+ { "decentralizedConferenceMC", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_decentralizedConferenceMC },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H2250Capability_mcCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H2250Capability_mcCapability, ett_h245_H2250Capability_mcCapability, H2250Capability_mcCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_rtcpVideoControlCapability_bit = {
+ "rtcpVideoControlCapability bit is SET",
+ "rtcpVideoControlCapability bit is CLEAR"
+};
+static int
+dissect_h245_rtcpVideoControlCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_rtcpVideoControlCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_logicalChannelSwitchingCapability_bit = {
+ "logicalChannelSwitchingCapability bit is SET",
+ "logicalChannelSwitchingCapability bit is CLEAR"
+};
+static int
+dissect_h245_logicalChannelSwitchingCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_logicalChannelSwitchingCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_t120DynamicPortCapability_bit = {
+ "t120DynamicPortCapability bit is SET",
+ "t120DynamicPortCapability bit is CLEAR"
+};
+static int
+dissect_h245_t120DynamicPortCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_t120DynamicPortCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_h261aVideoPacketization_bit = {
+ "h261aVideoPacketization bit is SET",
+ "h261aVideoPacketization bit is CLEAR"
+};
+static int
+dissect_h245_h261aVideoPacketization(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_h261aVideoPacketization, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_atmUBR_bit = {
+ "atmUBR bit is SET",
+ "atmUBR bit is CLEAR"
+};
+static int
+dissect_h245_atmUBR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_atmUBR, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_atmrtVBR_bit = {
+ "atmrtVBR bit is SET",
+ "atmrtVBR bit is CLEAR"
+};
+static int
+dissect_h245_atmrtVBR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_atmrtVBR, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_atmnrtVBR_bit = {
+ "atmnrtVBR bit is SET",
+ "atmnrtVBR bit is CLEAR"
+};
+static int
+dissect_h245_atmnrtVBR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_atmnrtVBR, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_atmABR_bit = {
+ "atmABR bit is SET",
+ "atmABR bit is CLEAR"
+};
+static int
+dissect_h245_atmABR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_atmABR, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_atmCBR_bit = {
+ "atmCBR bit is SET",
+ "atmCBR bit is CLEAR"
+};
+static int
+dissect_h245_atmCBR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_atmCBR, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_variableDelta_bit = {
+ "variableDelta bit is SET",
+ "variableDelta bit is CLEAR"
+};
+static int
+dissect_h245_variableDelta(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_variableDelta, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MediaTransportType_AtmAAL5Compressed_sequence[] = {
+ { "variable-delta", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_variableDelta },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MediaTransportType_AtmAAL5Compressed(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MediaTransportType_AtmAAL5Compressed, ett_h245_MediaTransportType_AtmAAL5Compressed, MediaTransportType_AtmAAL5Compressed_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string MediaTransportType_vals[] = {
+ { 0, "ip-UDP" },
+ { 1, "ip-TCP" },
+ { 2, "atm-AAL5-UNIDIR" },
+ { 3, "atm-AAL5-BIDIR" },
+ { 4, "atm-AAL5-compressed" },
+ { 0, NULL }
+};
+static per_choice_t MediaTransportType_choice[] = {
+ { 0, "ip-UDP", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "ip-TCP", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "atm-AAL5-UNIDIR", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "atm-AAL5-BIDIR", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "atm-AAL5-compressed", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MediaTransportType_AtmAAL5Compressed },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MediaTransportType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MediaTransportType, ett_h245_MediaTransportType, MediaTransportType_choice, "MediaTransportType", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MediaChannelCapability_sequence[] = {
+ { "mediaTransport", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_MediaTransportType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MediaChannelCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MediaChannelCapability, ett_h245_MediaChannelCapability, MediaChannelCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_multicastCapability_bit = {
+ "multicastCapability bit is SET",
+ "multicastCapability bit is CLEAR"
+};
+static int
+dissect_h245_multicastCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_multicastCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_multiUniCastConference_bit = {
+ "multiUniCastConference bit is SET",
+ "multiUniCastConference bit is CLEAR"
+};
+static int
+dissect_h245_multiUniCastConference(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_multiUniCastConference, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_centralizedControl_bit = {
+ "centralizedControl bit is SET",
+ "centralizedControl bit is CLEAR"
+};
+static int
+dissect_h245_centralizedControl(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_centralizedControl, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_distributedControl_bit = {
+ "distributedControl bit is SET",
+ "distributedControl bit is CLEAR"
+};
+static int
+dissect_h245_distributedControl(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_distributedControl, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_centralizedAudio_bit = {
+ "centralizedAudio bit is SET",
+ "centralizedAudio bit is CLEAR"
+};
+static int
+dissect_h245_centralizedAudio(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_centralizedAudio, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_distributedAudio_bit = {
+ "distributedAudio bit is SET",
+ "distributedAudio bit is CLEAR"
+};
+static int
+dissect_h245_distributedAudio(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_distributedAudio, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_centralizedVideo_bit = {
+ "centralizedVideo bit is SET",
+ "centralizedVideo bit is CLEAR"
+};
+static int
+dissect_h245_centralizedVideo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_centralizedVideo, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_distributedVideo_bit = {
+ "distributedVideo bit is SET",
+ "distributedVideo bit is CLEAR"
+};
+static int
+dissect_h245_distributedVideo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_distributedVideo, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_temporalSpatialTradeOffCapability_bit = {
+ "temporalSpatialTradeOffCapability bit is SET",
+ "temporalSpatialTradeOffCapability bit is CLEAR"
+};
+static int
+dissect_h245_temporalSpatialTradeOffCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_temporalSpatialTradeOffCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_stillImageTransmission_bit = {
+ "stillImageTransmission bit is SET",
+ "stillImageTransmission bit is CLEAR"
+};
+static int
+dissect_h245_stillImageTransmission(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_stillImageTransmission, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_videoBadMBsCap_bit = {
+ "videoBadMBsCap bit is SET",
+ "videoBadMBsCap bit is CLEAR"
+};
+static int
+dissect_h245_videoBadMBsCap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoBadMBsCap, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelSPatML_bit = {
+ "profileAndLevelSPatML bit is SET",
+ "profileAndLevelSPatML bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelSPatML(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelSPatML, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelMPatLL_bit = {
+ "profileAndLevelMPatLL bit is SET",
+ "profileAndLevelMPatLL bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelMPatLL(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelMPatLL, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelMPatML_bit = {
+ "profileAndLevelMPatML bit is SET",
+ "profileAndLevelMPatML bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelMPatML(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelMPatML, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelMPatH14_bit = {
+ "profileAndLevelMPatH14 bit is SET",
+ "profileAndLevelMPatH14 bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelMPatH14(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelMPatH14, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelMPatHL_bit = {
+ "profileAndLevelMPatHL bit is SET",
+ "profileAndLevelMPatHL bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelMPatHL(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelMPatHL, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelSNRatLL_bit = {
+ "profileAndLevelSNRatLL bit is SET",
+ "profileAndLevelSNRatLL bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelSNRatLL(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelSNRatLL, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelSNRatML_bit = {
+ "profileAndLevelSNRatML bit is SET",
+ "profileAndLevelSNRatML bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelSNRatML(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelSNRatML, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelSpatialatH14_bit = {
+ "profileAndLevelSpatialatH14 bit is SET",
+ "profileAndLevelSpatialatH14 bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelSpatialatH14(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelSpatialatH14, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelHPatML_bit = {
+ "profileAndLevelHPatML bit is SET",
+ "profileAndLevelHPatML bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelHPatML(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelHPatML, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_profileAndLevelHPatH14_bit = {
+ "profileAndLevelHPatH14 bit is SET",
+ "profileAndLevelHPatH14 bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelHPatH14(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelHPatH14, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_profileAndLevelHPatHL_bit = {
+ "profileAndLevelHPatHL bit is SET",
+ "profileAndLevelHPatHL bit is CLEAR"
+};
+static int
+dissect_h245_profileAndLevelHPatHL(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_profileAndLevelHPatHL, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_unrestrictedVector_bit = {
+ "unrestrictedVector bit is SET",
+ "unrestrictedVector bit is CLEAR"
+};
+static int
+dissect_h245_unrestrictedVector(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_unrestrictedVector, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_arithmeticCoding_bit = {
+ "arithmeticCoding bit is SET",
+ "arithmeticCoding bit is CLEAR"
+};
+static int
+dissect_h245_arithmeticCoding(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_arithmeticCoding, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_advancedPrediction_bit = {
+ "advancedPrediction bit is SET",
+ "advancedPrediction bit is CLEAR"
+};
+static int
+dissect_h245_advancedPrediction(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_advancedPrediction, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_pbFrames_bit = {
+ "pbFrames bit is SET",
+ "pbFrames bit is CLEAR"
+};
+static int
+dissect_h245_pbFrames(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_pbFrames, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_errorCompensation_bit = {
+ "errorCompensation bit is SET",
+ "errorCompensation bit is CLEAR"
+};
+static int
+dissect_h245_errorCompensation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_errorCompensation, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_baseBitRateConstrained_bit = {
+ "baseBitRateConstrained bit is SET",
+ "baseBitRateConstrained bit is CLEAR"
+};
+static int
+dissect_h245_baseBitRateConstrained(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_baseBitRateConstrained, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_advancedIntraCodingMode_bit = {
+ "advancedIntraCodingMode bit is SET",
+ "advancedIntraCodingMode bit is CLEAR"
+};
+static int
+dissect_h245_advancedIntraCodingMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_advancedIntraCodingMode, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_deblockingFilterMode_bit = {
+ "deblockingFilterMode bit is SET",
+ "deblockingFilterMode bit is CLEAR"
+};
+static int
+dissect_h245_deblockingFilterMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_deblockingFilterMode, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_improvedPBFramesMode_bit = {
+ "improvedPBFramesMode bit is SET",
+ "improvedPBFramesMode bit is CLEAR"
+};
+static int
+dissect_h245_improvedPBFramesMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_improvedPBFramesMode, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_unlimitedMotionVectors_bit = {
+ "unlimitedMotionVectors bit is SET",
+ "unlimitedMotionVectors bit is CLEAR"
+};
+static int
+dissect_h245_unlimitedMotionVectors(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_unlimitedMotionVectors, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_fullPictureFreeze_bit = {
+ "fullPictureFreeze bit is SET",
+ "fullPictureFreeze bit is CLEAR"
+};
+static int
+dissect_h245_fullPictureFreeze(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_fullPictureFreeze, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_partialPictureFreezeAndRelease_bit = {
+ "partialPictureFreezeAndRelease bit is SET",
+ "partialPictureFreezeAndRelease bit is CLEAR"
+};
+static int
+dissect_h245_partialPictureFreezeAndRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_partialPictureFreezeAndRelease, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_resizingPartPicFreezeAndRelease_bit = {
+ "resizingPartPicFreezeAndRelease bit is SET",
+ "resizingPartPicFreezeAndRelease bit is CLEAR"
+};
+static int
+dissect_h245_resizingPartPicFreezeAndRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_resizingPartPicFreezeAndRelease, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_fullPictureSnapshot_bit = {
+ "fullPictureSnapshot bit is SET",
+ "fullPictureSnapshot bit is CLEAR"
+};
+static int
+dissect_h245_fullPictureSnapshot(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_fullPictureSnapshot, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_partialPictureSnapshot_bit = {
+ "partialPictureSnapshot bit is SET",
+ "partialPictureSnapshot bit is CLEAR"
+};
+static int
+dissect_h245_partialPictureSnapshot(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_partialPictureSnapshot, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_videoSegmentTagging_bit = {
+ "videoSegmentTagging bit is SET",
+ "videoSegmentTagging bit is CLEAR"
+};
+static int
+dissect_h245_videoSegmentTagging(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoSegmentTagging, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_progressiveRefinement_bit = {
+ "progressiveRefinement bit is SET",
+ "progressiveRefinement bit is CLEAR"
+};
+static int
+dissect_h245_progressiveRefinement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_progressiveRefinement, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dynamicPictureResizingByFour_bit = {
+ "dynamicPictureResizingByFour bit is SET",
+ "dynamicPictureResizingByFour bit is CLEAR"
+};
+static int
+dissect_h245_dynamicPictureResizingByFour(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dynamicPictureResizingByFour, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_dynamicPictureResizingSixteenthPel_bit = {
+ "dynamicPictureResizingSixteenthPel bit is SET",
+ "dynamicPictureResizingSixteenthPel bit is CLEAR"
+};
+static int
+dissect_h245_dynamicPictureResizingSixteenthPel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dynamicPictureResizingSixteenthPel, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dynamicWarpingHalfPel_bit = {
+ "dynamicWarpingHalfPel bit is SET",
+ "dynamicWarpingHalfPel bit is CLEAR"
+};
+static int
+dissect_h245_dynamicWarpingHalfPel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dynamicWarpingHalfPel, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dynamicWarpingSixteenthPel_bit = {
+ "dynamicWarpingSixteenthPel bit is SET",
+ "dynamicWarpingSixteenthPel bit is CLEAR"
+};
+static int
+dissect_h245_dynamicWarpingSixteenthPel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dynamicWarpingSixteenthPel, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_independentSegmentDecoding_bit = {
+ "independentSegmentDecoding bit is SET",
+ "independentSegmentDecoding bit is CLEAR"
+};
+static int
+dissect_h245_independentSegmentDecoding(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_independentSegmentDecoding, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_slicesInOrderNonRect_bit = {
+ "slicesInOrderNonRect bit is SET",
+ "slicesInOrderNonRect bit is CLEAR"
+};
+static int
+dissect_h245_slicesInOrderNonRect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_slicesInOrderNonRect, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_slicesInOrderRect_bit = {
+ "slicesInOrderRect bit is SET",
+ "slicesInOrderRect bit is CLEAR"
+};
+static int
+dissect_h245_slicesInOrderRect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_slicesInOrderRect, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_slicesNoOrderNonRect_bit = {
+ "slicesNoOrderNonRect bit is SET",
+ "slicesNoOrderNonRect bit is CLEAR"
+};
+static int
+dissect_h245_slicesNoOrderNonRect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_slicesNoOrderNonRect, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_slicesNoOrderRect_bit = {
+ "slicesNoOrderRect bit is SET",
+ "slicesNoOrderRect bit is CLEAR"
+};
+static int
+dissect_h245_slicesNoOrderRect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_slicesNoOrderRect, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_alternateInterVLCMode_bit = {
+ "alternateInterVLCMode bit is SET",
+ "alternateInterVLCMode bit is CLEAR"
+};
+static int
+dissect_h245_alternateInterVLCMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_alternateInterVLCMode, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_modifiedQuantizationMode_bit = {
+ "modifiedQuantizationMode bit is SET",
+ "modifiedQuantizationMode bit is CLEAR"
+};
+static int
+dissect_h245_modifiedQuantizationMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_modifiedQuantizationMode, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_reducedResolutionUpdate_bit = {
+ "reducedResolutionUpdate bit is SET",
+ "reducedResolutionUpdate bit is CLEAR"
+};
+static int
+dissect_h245_reducedResolutionUpdate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_reducedResolutionUpdate, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_separateVideoBackChannel_bit = {
+ "separateVideoBackChannel bit is SET",
+ "separateVideoBackChannel bit is CLEAR"
+};
+static int
+dissect_h245_separateVideoBackChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_separateVideoBackChannel, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_videoMux_bit = {
+ "videoMux bit is SET",
+ "videoMux bit is CLEAR"
+};
+static int
+dissect_h245_videoMux(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoMux, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_anyPixelAspectRatio_bit = {
+ "anyPixelAspectRatio bit is SET",
+ "anyPixelAspectRatio bit is CLEAR"
+};
+static int
+dissect_h245_anyPixelAspectRatio(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_anyPixelAspectRatio, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_referencePicSelect_bit = {
+ "referencePicSelect bit is SET",
+ "referencePicSelect bit is CLEAR"
+};
+static int
+dissect_h245_referencePicSelect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_referencePicSelect, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_enhancedReferencePicSelect_bool_bit = {
+ "enhancedReferencePicSelect_bool bit is SET",
+ "enhancedReferencePicSelect_bool bit is CLEAR"
+};
+static int
+dissect_h245_enhancedReferencePicSelect_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_enhancedReferencePicSelect_bool, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_dataPartitionedSlices_bit = {
+ "dataPartitionedSlices bit is SET",
+ "dataPartitionedSlices bit is CLEAR"
+};
+static int
+dissect_h245_dataPartitionedSlices(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_dataPartitionedSlices, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_fixedPointIDCT0_bit = {
+ "fixedPointIDCT0 bit is SET",
+ "fixedPointIDCT0 bit is CLEAR"
+};
+static int
+dissect_h245_fixedPointIDCT0(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_fixedPointIDCT0, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_interlacedFields_bit = {
+ "interlacedFields bit is SET",
+ "interlacedFields bit is CLEAR"
+};
+static int
+dissect_h245_interlacedFields(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_interlacedFields, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_currentPictureHeaderRepetition_bit = {
+ "currentPictureHeaderRepetition bit is SET",
+ "currentPictureHeaderRepetition bit is CLEAR"
+};
+static int
+dissect_h245_currentPictureHeaderRepetition(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_currentPictureHeaderRepetition, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_previousPictureHeaderRepetition_bit = {
+ "previousPictureHeaderRepetition bit is SET",
+ "previousPictureHeaderRepetition bit is CLEAR"
+};
+static int
+dissect_h245_previousPictureHeaderRepetition(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_previousPictureHeaderRepetition, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_nextPictureHeaderRepetition_bit = {
+ "nextPictureHeaderRepetition bit is SET",
+ "nextPictureHeaderRepetition bit is CLEAR"
+};
+static int
+dissect_h245_nextPictureHeaderRepetition(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_nextPictureHeaderRepetition, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_pictureNumber_bool_bit = {
+ "pictureNumber_bool bit is SET",
+ "pictureNumber_bool bit is CLEAR"
+};
+static int
+dissect_h245_pictureNumber_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_pictureNumber_bool, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_spareReferencePictures_bit = {
+ "spareReferencePictures bit is SET",
+ "spareReferencePictures bit is CLEAR"
+};
+static int
+dissect_h245_spareReferencePictures(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_spareReferencePictures, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t H263Version3Options_sequence[] = {
+ { "dataPartitionedSlices", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dataPartitionedSlices },
+ { "fixedPointIDCTO", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_fixedPointIDCT0 },
+ { "interlacedFields", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_interlacedFields},
+ { "currentPictureHeaderRepetition", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_currentPictureHeaderRepetition },
+ { "previousPictureHeaderRepetition", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_previousPictureHeaderRepetition },
+ { "nextPictureHeaderRepetition", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_nextPictureHeaderRepetition },
+ { "pictureNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_pictureNumber_bool },
+ { "spareReferencePictures", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_spareReferencePictures },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H263Version3Options(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H263Version3Options, ett_h245_H263Version3Options, H263Version3Options_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H263ModeComboFlags_sequence[] = {
+ { "unrestrictedVector", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_unrestrictedVector },
+ { "arithmeticCoding", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_arithmeticCoding },
+ { "advancedPrediction", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_advancedPrediction },
+ { "pbFrames", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_pbFrames },
+ { "advancedIntraCodingMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_advancedIntraCodingMode },
+ { "deblockingFilterMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_deblockingFilterMode },
+ { "unlimitedMotionVectors", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_unlimitedMotionVectors },
+ { "slicesInOrder-NonRect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_slicesInOrderNonRect },
+ { "slicesInOrder-Rect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_slicesInOrderRect },
+ { "slicesNoOrder-NonRect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_slicesNoOrderNonRect },
+ { "slicesNoOrder-Rect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_slicesNoOrderRect },
+ { "improvedPBFramesMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_improvedPBFramesMode },
+ { "referencePicSelect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_referencePicSelect },
+ { "dynamicPictureResizingByFour", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicPictureResizingByFour },
+ { "dynamicPictureResizingSixteenthPel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicPictureResizingSixteenthPel },
+ { "dynamicWarpingHalfPel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicWarpingHalfPel },
+ { "dynamicWarpingSixteenthPel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicWarpingSixteenthPel },
+ { "reducedResolutionUpdate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_reducedResolutionUpdate },
+ { "independentSegmentDecoding", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_independentSegmentDecoding },
+ { "alternateInterVLCMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_alternateInterVLCMode },
+ { "modifiedQuantizationMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_modifiedQuantizationMode },
+ { "enhancedReferencePicSelect", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_enhancedReferencePicSelect_bool },
+ { "h263Version3Options", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H263Version3Options },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H263ModeComboFlags(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H263ModeComboFlags, ett_h245_H263ModeComboFlags, H263ModeComboFlags_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_constrainedBitstream_bit = {
+ "constrainedBitstream bit is SET",
+ "constrainedBitstream bit is CLEAR"
+};
+static int
+dissect_h245_constrainedBitstream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_constrainedBitstream, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_silenceSuppression_bit = {
+ "silenceSuppression bit is SET",
+ "silenceSuppression bit is CLEAR"
+};
+static int
+dissect_h245_silenceSuppression(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_silenceSuppression, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_annexA_bit = {
+ "annexA bit is SET",
+ "annexA bit is CLEAR"
+};
+static int
+dissect_h245_annexA(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_annexA, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_annexB_bit = {
+ "annexB bit is SET",
+ "annexB bit is CLEAR"
+};
+static int
+dissect_h245_annexB(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_annexB, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_annexD_bit = {
+ "annexD bit is SET",
+ "annexD bit is CLEAR"
+};
+static int
+dissect_h245_annexD(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_annexD, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_annexE_bit = {
+ "annexE bit is SET",
+ "annexE bit is CLEAR"
+};
+static int
+dissect_h245_annexE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_annexE, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_annexF_bit = {
+ "annexF bit is SET",
+ "annexF bit is CLEAR"
+};
+static int
+dissect_h245_annexF(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_annexF, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_annexG_bit = {
+ "annexG bit is SET",
+ "annexG bit is CLEAR"
+};
+static int
+dissect_h245_annexG(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_annexG, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_annexH_bit = {
+ "annexH bit is SET",
+ "annexH bit is CLEAR"
+};
+static int
+dissect_h245_annexH(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_annexH, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioLayer1_bit = {
+ "audioLayer1 bit is SET",
+ "audioLayer1 bit is CLEAR"
+};
+static int
+dissect_h245_audioLayer1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioLayer1, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioLayer2_bit = {
+ "audioLayer2 bit is SET",
+ "audioLayer2 bit is CLEAR"
+};
+static int
+dissect_h245_audioLayer2(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioLayer2, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioLayer3_bit = {
+ "audioLayer3 bit is SET",
+ "audioLayer3 bit is CLEAR"
+};
+static int
+dissect_h245_audioLayer3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioLayer3, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioSampling32k_bit = {
+ "audioSampling32k bit is SET",
+ "audioSampling32k bit is CLEAR"
+};
+static int
+dissect_h245_audioSampling32k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioSampling32k, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioSampling44k1_bit = {
+ "audioSampling44k1 bit is SET",
+ "audioSampling44k1 bit is CLEAR"
+};
+static int
+dissect_h245_audioSampling44k1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioSampling44k1, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioSampling48k_bit = {
+ "audioSampling48k bit is SET",
+ "audioSampling48k bit is CLEAR"
+};
+static int
+dissect_h245_audioSampling48k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioSampling48k, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_singleChannel_bit = {
+ "singleChannel bit is SET",
+ "singleChannel bit is CLEAR"
+};
+static int
+dissect_h245_singleChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_singleChannel, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_twoChannels_bit = {
+ "twoChannels bit is SET",
+ "twoChannels bit is CLEAR"
+};
+static int
+dissect_h245_twoChannels(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_twoChannels, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioSampling16k_bit = {
+ "audioSampling16k bit is SET",
+ "audioSampling16k bit is CLEAR"
+};
+static int
+dissect_h245_audioSampling16k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioSampling16k, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioSampling22k05_bit = {
+ "audioSampling22k05 bit is SET",
+ "audioSampling22k05 bit is CLEAR"
+};
+static int
+dissect_h245_audioSampling22k05(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioSampling22k05, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioSampling24k_bit = {
+ "audioSampling24k bit is SET",
+ "audioSampling24k bit is CLEAR"
+};
+static int
+dissect_h245_audioSampling24k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioSampling24k, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_threeChannels21_bit = {
+ "threeChannels21 bit is SET",
+ "threeChannels21 bit is CLEAR"
+};
+static int
+dissect_h245_threeChannels21(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_threeChannels21, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_threeChannels30_bit = {
+ "threeChannels30 bit is SET",
+ "threeChannels30 bit is CLEAR"
+};
+static int
+dissect_h245_threeChannels30(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_threeChannels30, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_fourChannels2020_bit = {
+ "fourChannels2020 bit is SET",
+ "fourChannels2020 bit is CLEAR"
+};
+static int
+dissect_h245_fourChannels2020(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_fourChannels2020, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_fourChannels22_bit = {
+ "fourChannels22 bit is SET",
+ "fourChannels22 bit is CLEAR"
+};
+static int
+dissect_h245_fourChannels22(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_fourChannels22, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_fourChannels31_bit = {
+ "fourChannels31 bit is SET",
+ "fourChannels31 bit is CLEAR"
+};
+static int
+dissect_h245_fourChannels31(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_fourChannels31, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_fiveChannels3020_bit = {
+ "fiveChannels3020 bit is SET",
+ "fiveChannels3020 bit is CLEAR"
+};
+static int
+dissect_h245_fiveChannels3020(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_fiveChannels3020, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_fiveChannels32_bit = {
+ "fiveChannels32 bit is SET",
+ "fiveChannels32 bit is CLEAR"
+};
+static int
+dissect_h245_fiveChannels32(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_fiveChannels32, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_lowFrequencyEnhancement_bit = {
+ "lowFrequencyEnhancement bit is SET",
+ "lowFrequencyEnhancement bit is CLEAR"
+};
+static int
+dissect_h245_lowFrequencyEnhancement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_lowFrequencyEnhancement, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_multilingual_bit = {
+ "multilingual bit is SET",
+ "multilingual bit is CLEAR"
+};
+static int
+dissect_h245_multilingual(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_multilingual, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_comfortNoise_bit = {
+ "comfortNoise bit is SET",
+ "comfortNoise bit is CLEAR"
+};
+static int
+dissect_h245_comfortNoise(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_comfortNoise, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_scrambled_bit = {
+ "scrambled bit is SET",
+ "scrambled bit is CLEAR"
+};
+static int
+dissect_h245_scrambled(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_scrambled, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_qcif_bool_bit = {
+ "qcif_bool bit is SET",
+ "qcif_bool bit is CLEAR"
+};
+static int
+dissect_h245_qcif_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_qcif_bool, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_cif_bool_bit = {
+ "cif_bool bit is SET",
+ "cif_bool bit is CLEAR"
+};
+static int
+dissect_h245_cif_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_cif_bool, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_ccir601Seq_bit = {
+ "ccir601Seq bit is SET",
+ "ccir601Seq bit is CLEAR"
+};
+static int
+dissect_h245_ccir601Seq(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_ccir601Seq, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_ccir601Prog_bit = {
+ "ccir601Prog bit is SET",
+ "ccir601Prog bit is CLEAR"
+};
+static int
+dissect_h245_ccir601Prog(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_ccir601Prog, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_hdtvSeq_bit = {
+ "hdtvSeq bit is SET",
+ "hdtvSeq bit is CLEAR"
+};
+static int
+dissect_h245_hdtvSeq(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_hdtvSeq, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_hdtvProg_bit = {
+ "hdtvProg bit is SET",
+ "hdtvProg bit is CLEAR"
+};
+static int
+dissect_h245_hdtvProg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_hdtvProg, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_g3FacsMH200x100_bit = {
+ "g3FacsMH200x100 bit is SET",
+ "g3FacsMH200x100 bit is CLEAR"
+};
+static int
+dissect_h245_g3FacsMH200x100(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_g3FacsMH200x100, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_g3FacsMH200x200_bit = {
+ "g3FacsMH200x200 bit is SET",
+ "g3FacsMH200x200 bit is CLEAR"
+};
+static int
+dissect_h245_g3FacsMH200x200(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_g3FacsMH200x200, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_g4FacsMMR200x100_bit = {
+ "g4FacsMMR200x100 bit is SET",
+ "g4FacsMMR200x100 bit is CLEAR"
+};
+static int
+dissect_h245_g4FacsMMR200x100(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_g4FacsMMR200x100, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_g4FacsMMR200x200_bit = {
+ "g4FacsMMR200x200 bit is SET",
+ "g4FacsMMR200x200 bit is CLEAR"
+};
+static int
+dissect_h245_g4FacsMMR200x200(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_g4FacsMMR200x200, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+
+static const true_false_string tfs_jbig200x200Seq_bit = {
+ "jbig200x200Seq bit is SET",
+ "jbig200x200Seq bit is CLEAR"
+};
+static int
+dissect_h245_jbig200x200Seq(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_jbig200x200Seq, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_jbig200x200Prog_bit = {
+ "jbig200x200Prog bit is SET",
+ "jbig200x200Prog bit is CLEAR"
+};
+static int
+dissect_h245_jbig200x200Prog(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_jbig200x200Prog, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_jbig300x300Seq_bit = {
+ "jbig300x300Seq bit is SET",
+ "jbig300x300Seq bit is CLEAR"
+};
+static int
+dissect_h245_jbig300x300Seq(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_jbig300x300Seq, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_jbig300x300Prog_bit = {
+ "jbig300x300Prog bit is SET",
+ "jbig300x300Prog bit is CLEAR"
+};
+static int
+dissect_h245_jbig300x300Prog(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_jbig300x300Prog, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_digPhotoLow_bit = {
+ "digPhotoLow bit is SET",
+ "digPhotoLow bit is CLEAR"
+};
+static int
+dissect_h245_digPhotoLow(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_digPhotoLow, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_digPhotoMedSeq_bit = {
+ "digPhotoMedSeq bit is SET",
+ "digPhotoMedSeq bit is CLEAR"
+};
+static int
+dissect_h245_digPhotoMedSeq(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_digPhotoMedSeq, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_digPhotoMedProg_bit = {
+ "digPhotoMedProg bit is SET",
+ "digPhotoMedProg bit is CLEAR"
+};
+static int
+dissect_h245_digPhotoMedProg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_digPhotoMedProg, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_digPhotoHighSeq_bit = {
+ "digPhotoHighSeq bit is SET",
+ "digPhotoHighSeq bit is CLEAR"
+};
+static int
+dissect_h245_digPhotoHighSeq(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_digPhotoHighSeq, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_digPhotoHighProg_bit = {
+ "digPhotoHighProg bit is SET",
+ "digPhotoHighProg bit is CLEAR"
+};
+static int
+dissect_h245_digPhotoHighProg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_digPhotoHighProg, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t T84Profile_t84Restricted_sequence[] = {
+ { "qcif", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_qcif_bool },
+ { "cif", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_cif_bool },
+ { "ccir601Seq", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ccir601Seq },
+ { "ccir601Prog", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ccir601Prog },
+ { "hdtvSeq", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_hdtvSeq },
+ { "hdtvProg", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_hdtvProg },
+ { "g3FacsMH200x100", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_g3FacsMH200x100 },
+ { "g3FacsMH200x200", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_g3FacsMH200x200 },
+ { "g4FacsMMR200x100", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_g4FacsMMR200x100 },
+ { "g4FacsMMR200x200", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_g4FacsMMR200x200 },
+ { "jbig200x200Seq", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_jbig200x200Seq },
+ { "jbig200x200Prog", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_jbig200x200Prog },
+ { "jbig300x300Seq", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_jbig300x300Seq },
+ { "jbig300x300Prog", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_jbig300x300Prog },
+ { "digPhotoLow", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_digPhotoLow },
+ { "digPhotoMedSeq", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_digPhotoMedSeq },
+ { "digPhotoMedProg", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_digPhotoMedProg },
+ { "digPhotoHighSeq", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_digPhotoHighSeq },
+ { "digPhotoHighProg", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_digPhotoHighProg },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_T84Profile_t84Restricted(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_T84Profile_t84Restricted, ett_h245_T84Profile_t84Restricted, T84Profile_t84Restricted_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string T84Profile_vals[] = {
+ { 0, "t84Unrestricted" },
+ { 1, "t84Restricted" },
+ { 0, NULL }
+};
+static per_choice_t T84Profile_choice[] = {
+ { 0, "t84Unrestricted", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "t84Restricted", ASN1_NO_EXTENSIONS,
+ dissect_h245_T84Profile_t84Restricted },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_T84Profile(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_T84Profile, ett_h245_T84Profile, T84Profile_choice, "T84Profile", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_fillBitRemoval_bit = {
+ "fillBitRemoval bit is SET",
+ "fillBitRemoval bit is CLEAR"
+};
+static int
+dissect_h245_fillBitRemoval(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_fillBitRemoval, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_transcodingJBIG_bit = {
+ "transcodingJBIG bit is SET",
+ "transcodingJBIG bit is CLEAR"
+};
+static int
+dissect_h245_transcodingJBIG(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_transcodingJBIG, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_transcodingMMR_bit = {
+ "transcodingMMR bit is SET",
+ "transcodingMMR bit is CLEAR"
+};
+static int
+dissect_h245_transcodingMMR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_transcodingMMR, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_t38TCPBidirectionalMode_bit = {
+ "t38TCPBidirectionalMode bit is SET",
+ "t38TCPBidirectionalMode bit is CLEAR"
+};
+static int
+dissect_h245_t38TCPBidirectionalMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_t38TCPBidirectionalMode, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t T38FaxTcpOptions_sequence[] = {
+ { "t38TCPBidirectionalMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_t38TCPBidirectionalMode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_T38FaxTcpOptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_T38FaxTcpOptions, ett_h245_T38FaxTcpOptions, T38FaxTcpOptions_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_chairControlCapability_bit = {
+ "chairControlCapability bit is SET",
+ "chairControlCapability bit is CLEAR"
+};
+static int
+dissect_h245_chairControlCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_chairControlCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_videoIndicateMixingCapability_bit = {
+ "videoIndicateMixingCapability bit is SET",
+ "videoIndicateMixingCapability bit is CLEAR"
+};
+static int
+dissect_h245_videoIndicateMixingCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_videoIndicateMixingCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_multipointVisualizationCapability_bit = {
+ "multipointVisualizationCapability bit is SET",
+ "multipointVisualizationCapability bit is CLEAR"
+};
+static int
+dissect_h245_multipointVisualizationCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_multipointVisualizationCapability, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_controlOnMuxStream_bit = {
+ "controlOnMuxStream bit is SET",
+ "controlOnMuxStream bit is CLEAR"
+};
+static int
+dissect_h245_controlOnMuxStream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_controlOnMuxStream, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_redundancyEncoding_bool_bit = {
+ "redundancyEncoding_bool bit is SET",
+ "redundancyEncoding_bool bit is CLEAR"
+};
+static int
+dissect_h245_redundancyEncoding_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_redundancyEncoding_bool, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_separatePort_bit = {
+ "separatePort bit is SET",
+ "separatePort bit is CLEAR"
+};
+static int
+dissect_h245_separatePort(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_separatePort, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_samePort_bool_bit = {
+ "samePort_bool bit is SET",
+ "samePort_bool bit is CLEAR"
+};
+static int
+dissect_h245_samePort_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_samePort_bool, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t FECCapability_rfc2733_separateStream_sequence[] = {
+ { "separatePort", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_separatePort },
+ { "samePort", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_samePort_bool },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FECCapability_rfc2733_separateStream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FECCapability_rfc2733_separateStream, ett_h245_FECCapability_rfc2733_separateStream, FECCapability_rfc2733_separateStream_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t FECCapability_rfc2733_sequence[] = {
+ { "redundancyEncoding", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_redundancyEncoding_bool },
+ { "separateStream", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_FECCapability_rfc2733_separateStream },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FECCapability_rfc2733(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FECCapability_rfc2733, ett_h245_FECCapability_rfc2733, FECCapability_rfc2733_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string FECCapability_vals[] = {
+ { 0, "rfc2733" },
+ { 0, NULL }
+};
+static per_choice_t FECCapability_choice[] = {
+ { 0, "rfc2733", ASN1_EXTENSION_ROOT,
+ dissect_h245_FECCapability_rfc2733 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FECCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FECCapability, ett_h245_FECCapability, FECCapability_choice, "FECCapability", NULL);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string tfs_associateConference_bit = {
+ "associateConference bit is SET",
+ "associateConference bit is CLEAR"
+};
+static int
+dissect_h245_associateConference(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_associateConference, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_audioHeaderPresent_bit = {
+ "audioHeaderPresent bit is SET",
+ "audioHeaderPresent bit is CLEAR"
+};
+static int
+dissect_h245_audioHeaderPresent(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_audioHeaderPresent, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t V75Parameters_sequence[] = {
+ { "audioHeaderPresent", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioHeaderPresent },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_V75Parameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_V75Parameters, ett_h245_V75Parameters, V75Parameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_segmentableFlag_bit = {
+ "segmentableFlag bit is SET",
+ "segmentableFlag bit is CLEAR"
+};
+static int
+dissect_h245_segmentableFlag(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_segmentableFlag, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_alsduSplitting_bit = {
+ "alsduSplitting bit is SET",
+ "alsduSplitting bit is CLEAR"
+};
+static int
+dissect_h245_alsduSplitting(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_alsduSplitting, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_uIH_bit = {
+ "uIH bit is SET",
+ "uIH bit is CLEAR"
+};
+static int
+dissect_h245_uIH(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_uIH, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_loopbackTestProcedure_bit = {
+ "loopbackTestProcedure bit is SET",
+ "loopbackTestProcedure bit is CLEAR"
+};
+static int
+dissect_h245_loopbackTestProcedure(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_loopbackTestProcedure, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_mediaGuaranteedDelivery_bit = {
+ "mediaGuaranteedDelivery bit is SET",
+ "mediaGuaranteedDelivery bit is CLEAR"
+};
+static int
+dissect_h245_mediaGuaranteedDelivery(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_mediaGuaranteedDelivery, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_mediaControlGuaranteedDelivery_bit = {
+ "mediaControlGuaranteedDelivery bit is SET",
+ "mediaControlGuaranteedDelivery bit is CLEAR"
+};
+static int
+dissect_h245_mediaControlGuaranteedDelivery(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_mediaControlGuaranteedDelivery, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_flowControlToZero_bit = {
+ "flowControlToZero bit is SET",
+ "flowControlToZero bit is CLEAR"
+};
+static int
+dissect_h245_flowControlToZero(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_flowControlToZero, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_multiplexCapability_bool_bit = {
+ "multiplexCapability_bool bit is SET",
+ "multiplexCapability_bool bit is CLEAR"
+};
+static int
+dissect_h245_multiplexCapability_bool(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_multiplexCapability_bool, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_secureChannel_bit = {
+ "secureChannel bit is SET",
+ "secureChannel bit is CLEAR"
+};
+static int
+dissect_h245_secureChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_secureChannel, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_sharedSecret_bit = {
+ "sharedSecret bit is SET",
+ "sharedSecret bit is CLEAR"
+};
+static int
+dissect_h245_sharedSecret(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_sharedSecret, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_certProtectedKey_bit = {
+ "certProtectedKey bit is SET",
+ "certProtectedKey bit is CLEAR"
+};
+static int
+dissect_h245_certProtectedKey(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_certProtectedKey, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t KeyProtectionMethod_sequence[] = {
+ { "secureChannel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_secureChannel },
+ { "sharedSecret", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sharedSecret },
+ { "certProtectedKey", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_certProtectedKey },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_KeyProtectionMethod(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_KeyProtectionMethod, ett_h245_KeyProtectionMethod, KeyProtectionMethod_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t EncryptionUpdateRequest_sequence[] = {
+ { "keyProtectionMethod", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_KeyProtectionMethod },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_EncryptionUpdateRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_EncryptionUpdateRequest, ett_h245_EncryptionUpdateRequest, EncryptionUpdateRequest_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const true_false_string tfs_bitRateLockedToPCRClock_bit = {
+ "bitRateLockedToPCRClock bit is SET",
+ "bitRateLockedToPCRClock bit is CLEAR"
+};
+static int
+dissect_h245_bitRateLockedToPCRClock(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_bitRateLockedToPCRClock, NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const true_false_string tfs_bitRateLockedToNetworkClock_bit = {
+ "bitRateLockedToNetworkClock bit is SET",
+ "bitRateLockedToNetworkClock bit is CLEAR"
+};
+static int
+dissect_h245_bitRateLockedToNetworkClock(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_bitRateLockedToNetworkClock, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_IS11172_BitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_IS11172_BitRate, 1, 448,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_IS13818_BitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_IS13818_BitRate, 1, 1130,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t IS11172AudioCapability_sequence[] = {
+ { "audioLayer1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioLayer1 },
+ { "audioLayer2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioLayer2 },
+ { "audioLayer3", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioLayer3 },
+ { "audioSampling32k", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioSampling32k },
+ { "audioSampling44k1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioSampling44k1 },
+ { "audioSampling48k", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioSampling48k },
+ { "singleChannel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_singleChannel },
+ { "twoChannels", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_twoChannels },
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS11172_BitRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_IS11172AudioCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_IS11172AudioCapability, ett_h245_IS11172AudioCapability, IS11172AudioCapability_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t IS11172AudioMode_sequence[] = {
+ { "audioLayer", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS11172AudioMode_audioLayer },
+ { "audioSampling", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS11172AudioMode_audioSampling },
+ { "multichannelType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS11172AudioMode_multichannelType },
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS11172_BitRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_IS11172AudioMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_IS11172AudioMode, ett_h245_IS11172AudioMode, IS11172AudioMode_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t IS13818AudioMode_sequence[] = {
+ { "audioLayer", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS13818AudioMode_audioLayer },
+ { "audioSampling", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS13818AudioMode_audioSampling },
+ { "multiChannelType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS13818AudioMode_multiChannelType },
+ { "lowFrequencyEnhancement", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_lowFrequencyEnhancement },
+ { "multilingual", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_multilingual },
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS13818_BitRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_IS13818AudioMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_IS13818AudioMode, ett_h245_IS13818AudioMode, IS13818AudioMode_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t IS13818AudioCapability_sequence[] = {
+ { "audioLayer1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioLayer1 },
+ { "audioLayer2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioLayer2 },
+ { "audioLayer3", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioLayer3 },
+ { "audioSampling16k", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioSampling16k },
+ { "audioSampling22k05", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioSampling22k05 },
+ { "audioSampling24k", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioSampling24k },
+ { "audioSampling32k", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioSampling32k },
+ { "audioSampling44k1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioSampling44k1 },
+ { "audioSampling48k", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioSampling48k },
+ { "singleChannel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_singleChannel },
+ { "twoChannels", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_twoChannels },
+ { "threeChannels2-1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_threeChannels21 },
+ { "threeChannels3-0", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_threeChannels30 },
+ { "fourChannels2-0-2-0", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_fourChannels2020 },
+ { "fourChannels2-2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_fourChannels22 },
+ { "fourChannels3-1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_fourChannels31 },
+ { "fiveChannels3-0-2-0", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_fiveChannels3020 },
+ { "fiveChannels3-2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_fiveChannels32 },
+ { "lowFrequencyEnhancement", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_lowFrequencyEnhancement },
+ { "multilingual", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_multilingual },
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_IS13818_BitRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_IS13818AudioCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_IS13818AudioCapability, ett_h245_IS13818AudioCapability, IS13818AudioCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_ATM_BitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_ATM_BitRate, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t NewATMVCIndication_reverseParameters_sequence[] = {
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ATM_BitRate },
+ { "bitRateLockedToPCRClock", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_bitRateLockedToPCRClock },
+ { "bitRateLockedToNetworkClock", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_bitRateLockedToNetworkClock },
+ { "multiplex", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCIndication_reverseParameters_multiplex },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCIndication_reverseParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NewATMVCIndication_reverseParameters, ett_h245_NewATMVCIndication_reverseParameters, NewATMVCIndication_reverseParameters_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t NewATMVCCommand_reverseParameters_sequence[] = {
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ATM_BitRate },
+ { "bitRateLockedToPCRClock", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_bitRateLockedToPCRClock },
+ { "bitRateLockedToNetworkClock", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_bitRateLockedToNetworkClock },
+ { "multiplex", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCCommand_reverseParameters_multiplex },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCCommand_reverseParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NewATMVCCommand_reverseParameters, ett_h245_NewATMVCCommand_reverseParameters, NewATMVCCommand_reverseParameters_sequence);
+
+ return offset;
+}
+
+static int
+dissect_h245_t35CountryCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_t35CountryCode, 0, 255,
+ &t35CountryCode, NULL, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_t35Extension(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_t35Extension, 0, 255,
+ &t35Extension, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_manufacturerCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_manufacturerCode, 0, 65535,
+ &manufacturerCode, NULL, FALSE);
+
+ return offset;
+}
+
+
+/* dissect_h245_h221NonStandard is used for H.245 */
+
+static per_sequence_t h221NonStandard_sequence[] = {
+ { "t35CountryCode", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_t35CountryCode },
+ { "t35Extension", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_t35Extension },
+ { "manufacturerCode", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_manufacturerCode },
+ { NULL, 0, 0, NULL }
+};
+int
+dissect_h245_h221NonStandard(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ t35CountryCode = 0;
+ t35Extension = 0;
+ manufacturerCode = 0;
+
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_h221NonStandard, ett_h245_h221NonStandard, h221NonStandard_sequence);
+
+ h221NonStandard = ((t35CountryCode * 256) + t35Extension) * 65536 + manufacturerCode;
+
+ proto_tree_add_uint(tree, hf_h245_h221Manufacturer, tvb, (offset>>3)-4 ,4,h221NonStandard);
+
+ return offset;
+}
+
+static int
+dissect_h245_terminalType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_terminalType, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+static int
+dissect_h245_statusDeterminationNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_statusDeterminationNumber, 0, 16777215,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MasterSlaveDetermination_sequence[] = {
+ { "terminalType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_terminalType },
+ { "statusDeterminationNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_statusDeterminationNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MasterSlaveDetermination(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDetermination, ett_h245_MasterSlaveDetermination, MasterSlaveDetermination_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_CapabilityTableEntryNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_CapabilityTableEntryNumber, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static const value_string TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded_vals[] = {
+ { 0, "highestEntryNumberProcessed" },
+ { 1, "noneProcessed" },
+ { 0, NULL }
+};
+static per_choice_t TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded_choice[] = {
+ { 0, "highestEntryNumberProcessed", ASN1_NO_EXTENSIONS,
+ dissect_h245_CapabilityTableEntryNumber },
+ { 1, "noneProcessed", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded, ett_h245_TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded, TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded_choice, "tableEntryCapacityExceeded", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string TerminalCapabilitySetReject_cause_vals[] = {
+ { 0, "unspecified" },
+ { 1, "undefinedTableEntryUsed" },
+ { 2, "descriptorCapacityExceeded" },
+ { 3, "tableEntryCapacityExceeded" },
+ { 0, NULL }
+};
+static per_choice_t TerminalCapabilitySetReject_cause_choice[] = {
+ { 0, "unspecified", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "undefinedTableEntryUsed", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "descriptorCapacityExceeded", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "tableEntryCapacityExceeded", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_TerminalCapabilitySetReject_cause(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySetReject_cause, ett_h245_TerminalCapabilitySetReject_cause, TerminalCapabilitySetReject_cause_choice, "cause", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t TerminalCapabilitySetReject_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "cause", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalCapabilitySetReject_cause },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_TerminalCapabilitySetReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySetReject, ett_h245_TerminalCapabilitySetReject, TerminalCapabilitySetReject_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_CapabilityDescriptorNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_CapabilityDescriptorNumber, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_h233IVResponseTime(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_h233IVResponseTime, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t Capability_h233EncryptionReceiveCapability_sequence[] = {
+ { "h233IVResponseTime", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h233IVResponseTime },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_Capability_h233EncryptionReceiveCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_Capability_h233EncryptionReceiveCapability, ett_h245_Capability_h233EncryptionReceiveCapability, Capability_h233EncryptionReceiveCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_maxPendingReplacementFor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maxPendingReplacementFor, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_numberOfVCs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_numberOfVCs, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_forwardMaximumSDUSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_forwardMaximumSDUSize, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_backwardMaximumSDUSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_backwardMaximumSDUSize, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t VCCapability_aal5_sequence[] = {
+ { "forwardMaximumSDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_forwardMaximumSDUSize },
+ { "backwardMaximumSDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_backwardMaximumSDUSize },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VCCapability_aal5(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VCCapability_aal5, ett_h245_VCCapability_aal5, VCCapability_aal5_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t NewATMVCCommand_aal_aal5_sequence[] = {
+ { "forwardMaximumSDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_forwardMaximumSDUSize},
+ { "backwardMaximumSDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_backwardMaximumSDUSize },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCCommand_aal_aal5(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NewATMVCCommand_aal_aal5, ett_h245_NewATMVCCommand_aal_aal5, NewATMVCCommand_aal_aal5_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string NewATMVCCommand_aal_vals[] = {
+ { 0, "aal1" },
+ { 1, "aal5" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCCommand_aal_choice[] = {
+ { 0, "aal1", ASN1_EXTENSION_ROOT,
+ dissect_h245_NewATMVCCommand_aal_aal1 },
+ { 1, "aal5", ASN1_EXTENSION_ROOT,
+ dissect_h245_NewATMVCCommand_aal_aal5 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCCommand_aal(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCCommand_aal, ett_h245_NewATMVCCommand_aal, NewATMVCCommand_aal_choice, "aal", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t NewATMVCIndication_aal_aal5_sequence[] = {
+ { "forwardMaximumSDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_forwardMaximumSDUSize },
+ { "backwardMaximumSDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_backwardMaximumSDUSize },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCIndication_aal_aal5(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NewATMVCIndication_aal_aal5, ett_h245_NewATMVCIndication_aal_aal5, NewATMVCIndication_aal_aal5_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string NewATMVCIndication_aal_vals[] = {
+ { 0, "aal1" },
+ { 1, "aal5" },
+ { 0, NULL }
+};
+static per_choice_t NewATMVCIndication_aal_choice[] = {
+ { 0, "aal1", ASN1_EXTENSION_ROOT,
+ dissect_h245_NewATMVCIndication_aal_aal1 },
+ { 1, "aal5", ASN1_EXTENSION_ROOT,
+ dissect_h245_NewATMVCIndication_aal_aal5 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCIndication_aal(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NewATMVCIndication_aal, ett_h245_NewATMVCIndication_aal, NewATMVCIndication_aal_choice, "aal", NULL);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_singleBitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_singleBitRate, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_lowerBitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_lowerBitRate, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_higherBitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_higherBitRate, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t VCCapability_availableBitRates_rangeOfBitRates_sequence[] = {
+ { "lowerBitRate", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_lowerBitRate },
+ { "higherBitRate", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_higherBitRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VCCapability_availableBitRates_rangeOfBitRates(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VCCapability_availableBitRates_rangeOfBitRates, ett_h245_VCCapability_availableBitRates_rangeOfBitRates, VCCapability_availableBitRates_rangeOfBitRates_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string VCCapability_availableBitRates_type_vals[] = {
+ { 0, "singleBitRate" },
+ { 1, "rangeOfBitRates" },
+ { 0, NULL }
+};
+static per_choice_t VCCapability_availableBitRates_type_choice[] = {
+ { 0, "singleBitRate", ASN1_NO_EXTENSIONS,
+ dissect_h245_singleBitRate },
+ { 1, "rangeOfBitRates", ASN1_NO_EXTENSIONS,
+ dissect_h245_VCCapability_availableBitRates_rangeOfBitRates },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_VCCapability_availableBitRates_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_VCCapability_availableBitRates_type, ett_h245_VCCapability_availableBitRates_type, VCCapability_availableBitRates_type_choice, "type", NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_maximumAl2SDUSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumAl2SDUSize, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumAl3SDUSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumAl3SDUSize, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumDelayJitter(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumDelayJitter, 0, 1023,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_maximumNestingDepth(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumNestingDepth, 1, 15,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_maximumElementListSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumElementListSize, 2, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_maximumSubElementListSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumSubElementListSize, 2, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t H223Capability_h223MultiplexTableCapability_enhanced_sequence[] = {
+ { "maximumNestingDepth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumNestingDepth },
+ { "maximumElementListSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumElementListSize },
+ { "maximumSubElementListSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumSubElementListSize },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223Capability_h223MultiplexTableCapability_enhanced(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223Capability_h223MultiplexTableCapability_enhanced, ett_h245_H223Capability_h223MultiplexTableCapability_enhanced, H223Capability_h223MultiplexTableCapability_enhanced_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string H223Capability_h223MultiplexTableCapability_vals[] = {
+ { 0, "basic" },
+ { 1, "enhanced" },
+ { 0, NULL }
+};
+static per_choice_t H223Capability_h223MultiplexTableCapability_choice[] = {
+ { 0, "basic", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "enhanced", ASN1_NO_EXTENSIONS,
+ dissect_h245_H223Capability_h223MultiplexTableCapability_enhanced },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223Capability_h223MultiplexTableCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223Capability_h223MultiplexTableCapability, ett_h245_H223Capability_h223MultiplexTableCapability, H223Capability_h223MultiplexTableCapability_choice, "h223MultiplexTableCapability", NULL);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_h223bitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_h223bitRate, 1, 19200,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumSampleSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumSampleSize, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumPayloadLength(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumPayloadLength, 1, 65025,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H223Capability_mobileMultilinkFrameCapability_sequence[] = {
+ { "maximumSampleSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumSampleSize },
+ { "maximumPayloadLength", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumPayloadLength },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223Capability_mobileMultilinkFrameCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223Capability_mobileMultilinkFrameCapability, ett_h245_H223Capability_mobileMultilinkFrameCapability, H223Capability_mobileMultilinkFrameCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumAL1MPDUSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumAL1MPDUSize, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumAL2MSDUSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumAL2MSDUSize, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumAL3MSDUSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumAL3MSDUSize, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H223AnnexCCapability_sequence[] = {
+ { "videoWithAL1M", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoWithAL1M },
+ { "videoWithAL2M", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoWithAL2M },
+ { "videoWithAL3M", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoWithAL3M },
+ { "audioWithAL1M", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioWithAL1M },
+ { "audioWithAL2M", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioWithAL2M },
+ { "audioWithAL3M", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioWithAL3M },
+ { "dataWithAL1M", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dataWithAL1M },
+ { "dataWithAL2M", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dataWithAL2M },
+ { "dataWithAL3M", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dataWithAL3M },
+ { "alpduInterleaving", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_alpduInterleaving },
+ { "maximumAL1MPDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumAL1MPDUSize },
+ { "maximumAL2MSDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumAL2MSDUSize },
+ { "maximumAL3MSDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumAL3MSDUSize },
+ { "rsCodeCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_rsCodeCapability },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223AnnexCCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223AnnexCCapability, ett_h245_H223AnnexCCapability, H223AnnexCCapability_sequence);
+
+ return offset;
+}
+
+
+
+static const true_false_string tfs_transportWithIframes_bit = {
+ "transportWithIframes bit is SET",
+ "transportWithIframes bit is CLEAR"
+};
+static int
+dissect_h245_transportWithIframes(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h245_transportWithIframes, NULL, NULL);
+
+ return offset;
+}
+
+
+static per_sequence_t H223Capability_sequence[] = {
+ { "transportWithIframes", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_transportWithIframes },
+ { "videoWithAL1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoWithAL1 },
+ { "videoWithAL2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoWithAL2 },
+ { "videoWithAL3", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoWithAL3 },
+ { "audioWithAL1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioWithAL1 },
+ { "audioWithAL2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioWithAL2 },
+ { "audioWithAL3", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioWithAL3 },
+ { "dataWithAL1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dataWithAL1 },
+ { "dataWithAL2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dataWithAL2 },
+ { "dataWithAL3", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dataWithAL3 },
+ { "maximumAL2SDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumAl2SDUSize },
+ { "maximumAL3SDUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumAl3SDUSize },
+ { "maximumDelayJitter", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumDelayJitter },
+ { "h223MultiplexTableCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223Capability_h223MultiplexTableCapability },
+ { "maxMUXPDUSizeCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxMUXPDUSizeCapability },
+ { "nsrpSupport", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_nsrpSupport },
+ { "mobileOperationTransmitCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_H223Capability_mobileOperationTransmitCapability },
+ { "h223AnnexCCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_H223AnnexCCapability },
+ { "bitRate", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_h223bitRate },
+ { "mobileMultilinkFrameCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_H223Capability_mobileMultilinkFrameCapability },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223Capability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223Capability, ett_h245_H223Capability, H223Capability_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_numOfDLCS(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_numOfDLCS, 2, 8191,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_n401Capability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_n401Capability, 1, 4095,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maxWindowSizeCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maxWindowSizeCapability, 1, 127,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t V76Capability_sequence[] = {
+ { "suspendResumeCapabilitywAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_suspendResumeCapabilitywAddress },
+ { "suspendResumeCapabilitywoAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_suspendResumeCapabilitywoAddress },
+ { "rejCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_rejCapability },
+ { "sREJCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sREJCapability },
+ { "mREJCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_mREJCapability },
+ { "crc8bitCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_crc8bitCapability },
+ { "crc16bitCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_crc16bitCapability },
+ { "crc32bitCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_crc32bitCapability },
+ { "uihCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_uihCapability },
+ { "numOfDLCS", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_numOfDLCS },
+ { "twoOctetAddressFieldCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_twoOctetAddressFieldCapability },
+ { "loopBackTestCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_loopBackTestCapability },
+ { "n401Capability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_n401Capability },
+ { "maxWindowSizeCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxWindowSizeCapability },
+ { "v75Capability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_V75Capability },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_V76Capability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_V76Capability, ett_h245_V76Capability, V76Capability_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumAudioDelayJitter(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumAudioDelayJitter, 0, 1023,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_tokenRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_tokenRate, 1, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_bucketSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_bucketSize, 1, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_peakRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_peakRate, 1, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_minPoliced(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_minPoliced, 1, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maxPktSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maxPktSize, 1, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t RSVPParameters_sequence[] = {
+ { "qosMode", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_QOSMode },
+ { "tokenRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_tokenRate },
+ { "bucketSize", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_bucketSize },
+ { "peakRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_peakRate },
+ { "minPoliced", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_minPoliced },
+ { "maxPktSize", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_maxPktSize },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RSVPParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RSVPParameters, ett_h245_RSVPParameters, RSVPParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maxNTUSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maxNTUSize, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t ATMParameters_sequence[] = {
+ { "maxNTUSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxNTUSize },
+ { "atmUBR", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_atmUBR },
+ { "atmrtVBR", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_atmrtVBR },
+ { "atmnrtVBR", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_atmnrtVBR },
+ { "atmABR", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_atmABR },
+ { "atmCBR", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_atmCBR },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ATMParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ATMParameters, ett_h245_ATMParameters, ATMParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_numberOfThreads(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_numberOfThreads, 1, 16,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_framesBetweenSyncPoints(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_framesBetweenSyncPoints, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_threadNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_threadNumber, 0, 15,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_qcifMPI_1_4(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_qcifMPI_1_4, 1, 4,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_qcifMPI_1_32(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_qcifMPI_1_32, 1, 32,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+
+static int
+dissect_h245_qcifMPI_1_2048(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_qcifMPI_1_2048, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_cifMPI_1_4(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cifMPI_1_4, 1, 4,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_cifMPI_1_32(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cifMPI_1_32, 1, 32,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_cifMPI_1_2048(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cifMPI_1_2048, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H261VideoCapability_sequence[] = {
+ { "qcifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_qcifMPI_1_4 },
+ { "cifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cifMPI_1_4 },
+ { "temporalSpatialTradeOffCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_temporalSpatialTradeOffCapability },
+ { "maxBitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h223bitRate },
+ { "stillImageTransmission", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_stillImageTransmission },
+ { "videoBadMBsCap", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoBadMBsCap },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H261VideoCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H261VideoCapability, ett_h245_H261VideoCapability, H261VideoCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_videoBitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_videoBitRate, 0, 1073741823,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_vbvBufferSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_vbvBufferSize, 0, 262143,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_samplesPerLine(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_samplesPerLine, 0, 16383,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_linesPerFrame(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_linesPerFrame, 0, 16383,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_framesPerSecond(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_framesPerSecond, 0, 15,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_luminanceSampleRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_luminanceSampleRate, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H262VideoCapability_sequence[] = {
+ { "profileAndLevel-SPatML", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelSPatML },
+ { "profileAndLevel-MPatLL", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelMPatLL },
+ { "profileAndLevel-MPatML", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelMPatML },
+ { "profileAndLevel-MPatH-14", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelMPatH14 },
+ { "profileAndLevel-MPatHL", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelMPatHL },
+ { "profileAndLevel-SNRatLL", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelSNRatLL },
+ { "profileAndLevel-SNRatML", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelSNRatML },
+ { "profileAndLevel-SpatialatH-14", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelSpatialatH14 },
+ { "profileAndLevel-HPatML", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelHPatML },
+ { "profileAndLevel-HPatH-14", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelHPatH14 },
+ { "profileAndLevel-HPatHL", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_profileAndLevelHPatHL },
+ { "videoBitRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_videoBitRate },
+ { "vbvBufferSize", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_vbvBufferSize },
+ { "samplesPerLine", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_samplesPerLine },
+ { "linesPerFrame", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_linesPerFrame },
+ { "framesPerSecond", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_framesPerSecond },
+ { "luminanceSampleRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_luminanceSampleRate },
+ { "videoBadMBsCap", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoBadMBsCap },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H262VideoCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H262VideoCapability, ett_h245_H262VideoCapability, H262VideoCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H262VideoMode_sequence[] = {
+ { "profileAndLevel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H262VideoMode_profileAndLevel },
+ { "videoBitRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_videoBitRate },
+ { "vbvBufferSize", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_vbvBufferSize },
+ { "samplesPerLine", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_samplesPerLine },
+ { "linesPerFrame", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_linesPerFrame },
+ { "framesPerSecond", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_framesPerSecond },
+ { "luminanceSampleRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_luminanceSampleRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H262VideoMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H262VideoMode, ett_h245_H262VideoMode, H262VideoMode_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_sqcifMPI_1_32(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_sqcifMPI_1_32, 1, 32,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_sqcifMPI_1_2048(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_sqcifMPI_1_2048, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_cif4MPI_1_32(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cif4MPI_1_32, 1, 32,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_cif4MPI_1_2048(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cif4MPI_1_2048, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_cif16MPI_1_32(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cif16MPI_1_32, 1, 32,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_cif16MPI_1_2048(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cif16MPI_1_2048, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_maxBitRate_192400(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maxBitRate_192400, 1, 192400,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_hrd_B(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_hrd_B, 0, 524287,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_bppMaxKb(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_bppMaxKb, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_slowSqcifMPI(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_slowSqcifMPI, 1, 3600,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_slowQcifMPI(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_slowQcifMPI, 1, 3600,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_slowCifMPI(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_slowCifMPI, 1, 3600,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_slowCif4MPI(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_slowCif4MPI, 1, 3600,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_slowCif16MPI(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_slowCif16MPI, 1, 3600,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_numberOfBPictures(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_numberOfBPictures, 1, 64,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_presentationOrder(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_presentationOrder, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_offset_x(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_offset_x, -262144, 262143,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_offset_y(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_offset_y, -262144, 262143,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_scale_x(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_scale_x, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_scale_y(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_scale_y, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t TransperencyParameters_sequence[] = {
+ { "presentationOrder", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_presentationOrder },
+ { "offset-x", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_offset_x },
+ { "offset-y", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_offset_y },
+ { "scale-x", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_scale_x },
+ { "scale-y", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_scale_y },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_TransperencyParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TransperencyParameters, ett_h245_TransperencyParameters, TransperencyParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_sqcifAdditionalPictureMemory(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_sqcifAdditionalPictureMemory, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_qcifAdditionalPictureMemory(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_qcifAdditionalPictureMemory, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_cifAdditionalPictureMemory(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cifAdditionalPictureMemory, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_cif4AdditionalPictureMemory(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cif4AdditionalPictureMemory, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_cif16AdditionalPictureMemory(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_cif16AdditionalPictureMemory, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_bigCpfAdditionalPictureMemory(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_bigCpfAdditionalPictureMemory, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RefPictureSelection_additionalPictureMemory_sequence[] = {
+ { "sqcifAdditionalPictureMemory", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_sqcifAdditionalPictureMemory },
+ { "qcifAdditionalPictureMemory", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_qcifAdditionalPictureMemory },
+ { "cifAdditionalPictureMemory", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cifAdditionalPictureMemory },
+ { "cif4AdditionalPictureMemory", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cif4AdditionalPictureMemory },
+ { "cif16AdditionalPictureMemory", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cif16AdditionalPictureMemory },
+ { "bigCpfAdditionalPictureMemory", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_bigCpfAdditionalPictureMemory},
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RefPictureSelection_additionalPictureMemory(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RefPictureSelection_additionalPictureMemory, ett_h245_RefPictureSelection_additionalPictureMemory, RefPictureSelection_additionalPictureMemory_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_mpuHorizMBs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_mpuHorizMBs, 1, 128,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_mpuVertMBs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_mpuVertMBs, 1, 72,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_mpuTotalNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_mpuTotalNumber, 1, 65536,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters_sequence[] = {
+ { "mpuHorizMBs", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_mpuHorizMBs },
+ { "mpuVertMBs", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_mpuVertMBs},
+ { "mpuTotalNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_mpuTotalNumber},
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters, ett_h245_RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters, RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+static per_sequence_t RefPictureSelection_enhancedReferencePicSelect_sequence[] = {
+ { "subPictureRemovalParameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RefPictureSelection_enhancedReferencePicSelect(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RefPictureSelection_enhancedReferencePicSelect, ett_h245_RefPictureSelection_enhancedReferencePicSelect, RefPictureSelection_enhancedReferencePicSelect_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t RefPictureSelection_sequence[] = {
+ { "additionalPictureMemory", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RefPictureSelection_additionalPictureMemory },
+ { "videoMux", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoMux },
+ { "videoBackChannelSend", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RefPictureSelection_videoBackChannelSend },
+ { "enhancedReferencePicSelect", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RefPictureSelection_enhancedReferencePicSelect },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RefPictureSelection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RefPictureSelection, ett_h245_RefPictureSelection, RefPictureSelection_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_clockConversionCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_clockConversionCode, 1000, 1001,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_clockDivisor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_clockDivisor, 1, 127,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t CustomPictureClockFrequency_sequence[] = {
+ { "clockConversionCode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_clockConversionCode },
+ { "clockDivisor", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_clockDivisor },
+ { "sqcifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_sqcifMPI_1_2048 },
+ { "qcifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_qcifMPI_1_2048 },
+ { "cifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cifMPI_1_2048 },
+ { "cif4MPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cif4MPI_1_2048 },
+ { "cif16MPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cif16MPI_1_2048 },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CustomPictureClockFrequency(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CustomPictureClockFrequency, ett_h245_CustomPictureClockFrequency, CustomPictureClockFrequency_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maxCustomPictureWidth(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maxCustomPictureWidth, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_minCustomPictureWidth(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_minCustomPictureWidth, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_minCustomPictureHeight(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_minCustomPictureHeight, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_maxCustomPictureHeight(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maxCustomPictureHeight, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_standardMPI(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_standardMPI, 1, 31,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_customMPI(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_customMPI, 1, 2048,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t CustomPictureFormat_mPI_customPCF_sequence[] = {
+ { "clockConversionCode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_clockConversionCode },
+ { "clockDivisor", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_clockDivisor },
+ { "customMPI", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_customMPI },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CustomPictureFormat_mPI_customPCF(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CustomPictureFormat_mPI_customPCF, ett_h245_CustomPictureFormat_mPI_customPCF, CustomPictureFormat_mPI_customPCF_sequence);
+
+ return offset;
+}
+
+
+
+static int dissect_h245_customPCF(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static per_sequence_t CustomPictureFormat_mPI_sequence[] = {
+ { "standardMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_standardMPI},
+ { "customPCF", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_customPCF },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CustomPictureFormat_mPI(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CustomPictureFormat_mPI, ett_h245_CustomPictureFormat_mPI, CustomPictureFormat_mPI_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_width(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_width, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_height(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_height, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t CustomPictureFormat_pixelAspectInformation_extendedPAR_sequence[] = {
+ { "width", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_width },
+ { "height", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_height},
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CustomPictureFormat_pixelAspectInformation_extendedPAR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CustomPictureFormat_pixelAspectInformation_extendedPAR, ett_h245_CustomPictureFormat_pixelAspectInformation_extendedPAR, CustomPictureFormat_pixelAspectInformation_extendedPAR_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_pictureRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_pictureRate, 0, 15,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t IS11172VideoMode_sequence[] = {
+ { "constrainedBitstream", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_constrainedBitstream },
+ { "videoBitRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_videoBitRate },
+ { "vbvBufferSize", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_vbvBufferSize },
+ { "samplesPerLine", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_samplesPerLine },
+ { "linesPerFrame", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_linesPerFrame },
+ { "pictureRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_pictureRate},
+ { "luminanceSampleRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_luminanceSampleRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_IS11172VideoMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_IS11172VideoMode, ett_h245_IS11172VideoMode, IS11172VideoMode_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t IS11172VideoCapability_sequence[] = {
+ { "constrainedBitstream", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_constrainedBitstream },
+ { "videoBitRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_videoBitRate },
+ { "vbvBufferSize", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_vbvBufferSize },
+ { "samplesPerLine", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_samplesPerLine },
+ { "linesPerFrame", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_linesPerFrame },
+ { "pictureRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_pictureRate },
+ { "luminanceSampleRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_luminanceSampleRate },
+ { "videoBadMBsCap", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoBadMBsCap },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_IS11172VideoCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_IS11172VideoCapability, ett_h245_IS11172VideoCapability, IS11172VideoCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_g711Alaw64k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g711Alaw64k, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_g711Alaw56k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g711Alaw56k, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_g711Ulaw64k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g711Ulaw64k, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_g711Ulaw56k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g711Ulaw56k, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_g722_64k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g722_64k, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_g722_56k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g722_56k, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_g722_48k(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g722_48k, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_maxAl_sduAudioFrames(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maxAl_sduAudioFrames, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t AudioCapability_g7231_sequence[] = {
+ { "maxAl-sduAudioFrames", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxAl_sduAudioFrames },
+ { "silenceSuppression", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_silenceSuppression },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_AudioCapability_g7231(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_AudioCapability_g7231, ett_h245_AudioCapability_g7231, AudioCapability_g7231_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_g728(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g728, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_g729(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g729, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_g729AnnexA(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g729AnnexA, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_g729wAnnexB(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g729wAnnexB, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_g729AnnexAwAnnexB(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_g729AnnexAwAnnexB, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_audioUnit(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_audioUnit, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t G729Extensions_sequence[] = {
+ { "audioUnit", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_audioUnit },
+ { "annexA", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_annexA },
+ { "annexB", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_annexB },
+ { "annexD", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_annexD },
+ { "annexE", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_annexE },
+ { "annexF", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_annexF },
+ { "annexG", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_annexG },
+ { "annexH", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_annexH },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_G729Extensions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_G729Extensions, ett_h245_G729Extensions, G729Extensions_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_highRateMode0(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_highRateMode0, 27, 78,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_highRateMode1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_highRateMode1, 27, 78,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_lowRateMode0(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_lowRateMode0, 23, 66,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_lowRateMode1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_lowRateMode1, 23, 66,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_sidMode0(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_sidMode0, 6, 17,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_sidMode1(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_sidMode1, 6, 17,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t G7231AnnexCCapability_g723AnnexCAudioMode_sequence[] = {
+ { "highRateMode0", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_highRateMode0 },
+ { "highRateMode1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_highRateMode1 },
+ { "lowRateMode0", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_lowRateMode0 },
+ { "lowRateMode1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_lowRateMode1 },
+ { "sidMode0", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sidMode0 },
+ { "sidMode1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sidMode1 },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_G7231AnnexCCapability_g723AnnexCAudioMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_G7231AnnexCCapability_g723AnnexCAudioMode, ett_h245_G7231AnnexCCapability_g723AnnexCAudioMode, G7231AnnexCCapability_g723AnnexCAudioMode_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t G7231AnnexCCapability_sequence[] = {
+ { "maxAl-sduAudioFrames", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxAl_sduAudioFrames },
+ { "silenceSuppression", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_silenceSuppression },
+ { "g723AnnexCAudioMode", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_G7231AnnexCCapability_g723AnnexCAudioMode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_G7231AnnexCCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_G7231AnnexCCapability, ett_h245_G7231AnnexCCapability, G7231AnnexCCapability_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t G7231AnnexCMode_g723AnnexCAudioMode_sequence[] = {
+ { "highRateMode0", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_highRateMode0 },
+ { "highRateMode1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_highRateMode1 },
+ { "lowRateMode0", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_lowRateMode0 },
+ { "lowRateMode1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_lowRateMode0 },
+ { "sidMode0", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sidMode0 },
+ { "sidMode1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sidMode1 },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_G7231AnnexCMode_g723AnnexCAudioMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_G7231AnnexCMode_g723AnnexCAudioMode, ett_h245_G7231AnnexCMode_g723AnnexCAudioMode, G7231AnnexCMode_g723AnnexCAudioMode_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t G7231AnnexCMode_sequence[] = {
+ { "maxAl-sduAudioFrames", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxAl_sduAudioFrames },
+ { "silenceSupression", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_silenceSuppression },
+ { "g723AnnexCAudioMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_G7231AnnexCMode_g723AnnexCAudioMode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_G7231AnnexCMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_G7231AnnexCMode, ett_h245_G7231AnnexCMode, G7231AnnexCMode_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_audioUnitSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_audioUnitSize, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t GSMAudioCapability_sequence[] = {
+ { "audioUnitSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioUnitSize },
+ { "comfortNoice", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_comfortNoise },
+ { "scrambled", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_scrambled },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_GSMAudioCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_GSMAudioCapability, ett_h245_GSMAudioCapability, GSMAudioCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_maxBitRate_4294967295UL(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* XXX unit is 100bit/s */
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maxBitRate_4294967295UL, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_numberOfCodewords(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_numberOfCodewords, 1, 65536,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumStringLength(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_maximumStringLength, 1, 256,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t V42bis_sequence[] = {
+ { "numberOfCodewords", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_numberOfCodewords },
+ { "maximumStringLength", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumStringLength },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_V42bis(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_V42bis, ett_h245_V42bis, V42bis_sequence);
+
+ return offset;
+}
+
+
+
+static const value_string CompressionType_vals[] = {
+ { 0, "v42bis" },
+ { 0, NULL }
+};
+static per_choice_t CompressionType_choice[] = {
+ { 0, "v42bis", ASN1_EXTENSION_ROOT,
+ dissect_h245_V42bis },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_CompressionType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_CompressionType, ett_h245_CompressionType, CompressionType_choice, "CompressionType", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string DataProtocolCapability_v76wCompression_vals[] = {
+ { 0, "transmitCompression" },
+ { 1, "receiveCompression" },
+ { 2, "transmitAndReceiveCompression" },
+ { 0, NULL }
+};
+static per_choice_t DataProtocolCapability_v76wCompression_choice[] = {
+ { 0, "transmitCompression", ASN1_EXTENSION_ROOT,
+ dissect_h245_CompressionType },
+ { 1, "receiveCompression", ASN1_EXTENSION_ROOT,
+ dissect_h245_CompressionType },
+ { 2, "transmitAndReceiveCompression", ASN1_EXTENSION_ROOT,
+ dissect_h245_CompressionType },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_DataProtocolCapability_v76wCompression(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_DataProtocolCapability_v76wCompression, ett_h245_DataProtocolCapability_v76wCompression, DataProtocolCapability_v76wCompression_choice, "v76wCompression", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_version(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_version, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int dissect_h245_T38FaxUdpOptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static per_sequence_t T38FaxProfile_sequence[] = {
+ { "fillBitRemoval", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_fillBitRemoval },
+ { "transcodingJBIG", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_transcodingJBIG },
+ { "transcodingMMR", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_transcodingMMR },
+ { "version", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_version },
+ { "t38FaxRateManagement", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_T38FaxRateManagement },
+ { "t38FaxUdpOptions", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_T38FaxUdpOptions },
+ { "t38FaxTcpOptions", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_T38FaxTcpOptions },
+ { NULL, 0, 0, NULL }
+};
+int
+dissect_h245_T38FaxProfile(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_T38FaxProfile, ett_h245_T38FaxProfile, T38FaxProfile_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_standard_0_127(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_standard_0_127, 0, 127,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_booleanArray(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_booleanArray, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_unsignedMin(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_unsignedMin, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_unsignedMax(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_unsignedMax, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_unsigned32Min(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_unsigned32Min, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_unsigned32Max(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_unsigned32Max, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_dynamicRTPPayloadType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_dynamicRTPPayloadType, 96, 127,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t AudioToneCapability_sequence[] = {
+ { "dynamicRTPPayloadType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicRTPPayloadType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_AudioToneCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_AudioToneCapability, ett_h245_AudioToneCapability, AudioToneCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t NoPTAudioToneCapability_sequence[] = {
+ { NULL, ASN1_EXTENSION_ROOT, 0, NULL }
+};
+static int
+dissect_h245_NoPTAudioToneCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NoPTAudioToneCapability, ett_h245_NoPTAudioToneCapability, NoPTAudioToneCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_portNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_portNumber, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_resourceID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_resourceID, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static const value_string FlowControlCommand_scope_vals[] = {
+ { 0, "logicalChannelNumber" },
+ { 1, "resourceID" },
+ { 2, "wholeMultiplex" },
+ { 0, NULL }
+};
+static per_choice_t FlowControlCommand_scope_choice[] = {
+ { 0, "logicalChannelNumber", ASN1_NO_EXTENSIONS,
+ dissect_h245_LogicalChannelNumber },
+ { 1, "resourceID", ASN1_NO_EXTENSIONS,
+ dissect_h245_resourceID },
+ { 2, "wholeMultiplex", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FlowControlCommand_scope(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FlowControlCommand_scope, ett_h245_FlowControlCommand_scope, FlowControlCommand_scope_choice, "scope", NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const value_string JitterIndication_scope_vals[] = {
+ { 0, "logicalChannelNumber" },
+ { 1, "resourceID" },
+ { 2, "wholeMultiplex" },
+ { 0, NULL }
+};
+static per_choice_t JitterIndication_scope_choice[] = {
+ { 0, "logicalChannelNumber", ASN1_NO_EXTENSIONS,
+ dissect_h245_LogicalChannelNumber },
+ { 1, "resourceID", ASN1_NO_EXTENSIONS,
+ dissect_h245_resourceID },
+ { 2, "wholeMultiplex", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_JitterIndication_scope(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_JitterIndication_scope, ett_h245_JitterIndication_scope, JitterIndication_scope_choice, "scope", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string FlowControlIndication_scope_vals[] = {
+ { 0, "logicalChannelNumber" },
+ { 1, "resouceID" },
+ { 2, "wholeMultiplex" },
+ { 0, NULL }
+};
+static per_choice_t FlowControlIndication_scope_choice[] = {
+ { 0, "logicalChannelNumber", ASN1_NO_EXTENSIONS,
+ dissect_h245_LogicalChannelNumber },
+ { 1, "resourceID", ASN1_NO_EXTENSIONS,
+ dissect_h245_resourceID },
+ { 2, "wholeMultiplex", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FlowControlIndication_scope(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FlowControlIndication_scope, ett_h245_FlowControlIndication_scope, FlowControlIndication_scope_choice, "scope", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t NewATMVCIndication_sequence[] = {
+ { "resourceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_resourceID },
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ATM_BitRate },
+ { "bitRateLockedToPCRClock", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_bitRateLockedToPCRClock },
+ { "bitRateLockedToNetworkClock", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_bitRateLockedToNetworkClock },
+ { "aal", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCIndication_aal },
+ { "multiplex", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCIndication_multiplex },
+ { "reverseParameters", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCIndication_reverseParameters },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NewATMVCIndication, ett_h245_NewATMVCIndication, NewATMVCIndication_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_subChannelID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_subChannelID, 0, 8191,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_pcr_pid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_pcr_pid, 0, 8191,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_controlFieldOctets(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_controlFieldOctets, 0, 2,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_sendBufferSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_sendBufferSize, 0, 16777215,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H223LogicalChannelParameters_adaptionLayerType_al3_sequence[] = {
+ { "controlFieldOctets", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_controlFieldOctets },
+ { "sendBufferSize", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_sendBufferSize },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223LogicalChannelParameters_adaptionLayerType_al3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223LogicalChannelParameters_adaptionLayerType_al3, ett_h245_H223LogicalChannelParameters_adaptionLayerType_al3, H223LogicalChannelParameters_adaptionLayerType_al3_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t H223ModeParameters_adaptationLayerType_al3_sequence[] = {
+ { "controlFieldOctets", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_controlFieldOctets },
+ { "sendBufferSize", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_sendBufferSize },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223ModeParameters_adaptationLayerType_al3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223ModeParameters_adaptationLayerType_al3, ett_h245_H223ModeParameters_adaptationLayerType_al3, H223ModeParameters_adaptationLayerType_al3_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_rcpcCodeRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_rcpcCodeRate, 8, 32,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_rsCodeCorrection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_rsCodeCorrection, 0, 127,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_finite_0_16(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_finite_0_16, 0, 16,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string H223AnnexCArqParameters_numberOfRetransmissions_vals[] = {
+ { 0, "finite" },
+ { 1, "infinite" },
+ { 0, NULL }
+};
+static per_choice_t H223AnnexCArqParameters_numberOfRetransmissions_choice[] = {
+ { 0, "finite", ASN1_EXTENSION_ROOT,
+ dissect_h245_finite_0_16 },
+ { 1, "infinite", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223AnnexCArqParameters_numberOfRetransmissions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223AnnexCArqParameters_numberOfRetransmissions, ett_h245_H223AnnexCArqParameters_numberOfRetransmissions, H223AnnexCArqParameters_numberOfRetransmissions_choice, "numberOfRetransmissions", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H223AnnexCArqParameters_sequence[] = {
+ { "numberOfRetransmissions", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223AnnexCArqParameters_numberOfRetransmissions },
+ { "sendBufferSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sendBufferSize },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223AnnexCArqParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223AnnexCArqParameters, ett_h245_H223AnnexCArqParameters, H223AnnexCArqParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string H223AL1MParameters_arqType_vals[] = {
+ { 0, "noArq" },
+ { 1, "typeIArq" },
+ { 2, "typeIIArq" },
+ { 0, NULL }
+};
+static per_choice_t H223AL1MParameters_arqType_choice[] = {
+ { 0, "noArq", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "typeIArq", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223AnnexCArqParameters },
+ { 2, "typeIIArq", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223AnnexCArqParameters },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223AL1MParameters_arqType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223AL1MParameters_arqType, ett_h245_H223AL1MParameters_arqType, H223AL1MParameters_arqType_choice, "arqType", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string H223AL3MParameters_arqType_vals[] = {
+ { 0, "noArq" },
+ { 1, "typeIArq" },
+ { 2, "typeIIArq" },
+ { 0, NULL }
+};
+static per_choice_t H223AL3MParameters_arqType_choice[] = {
+ { 0, "noArq", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "typeIArq", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223AnnexCArqParameters },
+ { 2, "typeIIArq", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223AnnexCArqParameters },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223AL3MParameters_arqType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223AL3MParameters_arqType, ett_h245_H223AL3MParameters_arqType, H223AL3MParameters_arqType_choice, "arqType", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H223AL1MParameters_sequence[] = {
+ { "transferMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223AL1MParameters_transferMode },
+ { "headerFEC", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223AL1MParameters_headerFEC },
+ { "crcLength", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223AL1MParameters_crcLength },
+ { "rcpcCodeRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_rcpcCodeRate },
+ { "arqType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223AL1MParameters_arqType },
+ { "alpduInterleaving", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_alpduInterleaving },
+ { "alsduSplitting", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_alsduSplitting },
+ { "rsCodeCorrection", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_rsCodeCorrection },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223AL1MParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223AL1MParameters, ett_h245_H223AL1MParameters, H223AL1MParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H223AL3MParameters_sequence[] = {
+ { "headerFormat", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223AL3MParameters_headerFormat },
+ { "crcLength", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223AL3MParameters_crcLength },
+ { "rcpcCodeRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_rcpcCodeRate },
+ { "arqType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223AL3MParameters_arqType },
+ { "alpduInterleaving", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_alpduInterleaving },
+ { "rsCodeCorrection", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_rsCodeCorrection },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223AL3MParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223AL3MParameters, ett_h245_H223AL3MParameters, H223AL3MParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_windowSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_windowSize, 1, 127,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t V76LogicalChannelParameters_mode_eRM_sequence[] = {
+ { "windowSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_windowSize },
+ { "recovery", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_V76LogicalChannelParameters_mode_eRM_recovery },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_V76LogicalChannelParameters_mode_eRM(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_V76LogicalChannelParameters_mode_eRM, ett_h245_V76LogicalChannelParameters_mode_eRM, V76LogicalChannelParameters_mode_eRM_sequence);
+
+ return offset;
+}
+
+
+
+static const value_string V76LogicalChannelParameters_mode_vals[] = {
+ { 0, "eRM" },
+ { 1, "uNERM" },
+ { 0, NULL }
+};
+static per_choice_t V76LogicalChannelParameters_mode_choice[] = {
+ { 0, "eRM", ASN1_EXTENSION_ROOT,
+ dissect_h245_V76LogicalChannelParameters_mode_eRM },
+ { 1, "uNERM", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_V76LogicalChannelParameters_mode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_V76LogicalChannelParameters_mode, ett_h245_V76LogicalChannelParameters_mode, V76LogicalChannelParameters_mode_choice, "mode", NULL);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_n401(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_n401, 1, 4095,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t V76HDLCParameters_sequence[] = {
+ { "crcLength", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_CRCLength },
+ { "n401", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_n401 },
+ { "loopbackTestProcedure", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_loopbackTestProcedure },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_V76HDLCParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_V76HDLCParameters, ett_h245_V76HDLCParameters, V76HDLCParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t V76LogicalChannelParameters_sequence[] = {
+ { "hdlcParameters", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_V76HDLCParameters },
+ { "suspendResume", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_V76LogicalChannelParameters_suspendResume },
+ { "uIH", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_uIH },
+ { "mode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_V76LogicalChannelParameters_mode },
+ { "v75Parameters", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_V75Parameters },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_V76LogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_V76LogicalChannelParameters, ett_h245_V76LogicalChannelParameters, V76LogicalChannelParameters_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_sessionID_0_255(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_sessionID_0_255, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_sessionID_1_255(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_sessionID_1_255, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_associatedSessionID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_associatedSessionID, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_payloadType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_payloadType, 0, 127,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_protectedSessionID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_protectedSessionID, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_protectedPayloadType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_protectedPayloadType, 0, 127,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t FECData_rfc2733_mode_separateStream_differentPort_sequence[] = {
+ { "protectedSessionID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_protectedSessionID },
+ { "protectedPayloadType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_protectedPayloadType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FECData_rfc2733_mode_separateStream_differentPort(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FECData_rfc2733_mode_separateStream_differentPort, ett_h245_FECData_rfc2733_mode_separateStream_differentPort, FECData_rfc2733_mode_separateStream_differentPort_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t FECData_rfc2733_mode_separateStream_samePort_sequence[] = {
+ { "protectedPayloadType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_protectedPayloadType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FECData_rfc2733_mode_separateStream_samePort(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FECData_rfc2733_mode_separateStream_samePort, ett_h245_FECData_rfc2733_mode_separateStream_samePort, FECData_rfc2733_mode_separateStream_samePort_sequence);
+
+ return offset;
+}
+
+
+
+static const value_string FECData_rfc2733_mode_separateStream_vals[] = {
+ { 0, "differentPort" },
+ { 1, "samePort" },
+ { 0, NULL }
+};
+static per_choice_t FECData_rfc2733_mode_separateStream_choice[] = {
+ { 0, "differentPort", ASN1_EXTENSION_ROOT,
+ dissect_h245_FECData_rfc2733_mode_separateStream_differentPort },
+ { 1, "samePort", ASN1_EXTENSION_ROOT,
+ dissect_h245_FECData_rfc2733_mode_separateStream_samePort },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FECData_rfc2733_mode_separateStream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FECData_rfc2733_mode_separateStream, ett_h245_FECData_rfc2733_mode_separateStream, FECData_rfc2733_mode_separateStream_choice, "separateStream", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string FECData_rfc2733_mode_vals[] = {
+ { 0, "redundancyEncoding" },
+ { 1, "separateStream" },
+ { 0, NULL }
+};
+static per_choice_t FECData_rfc2733_mode_choice[] = {
+ { 0, "redundancyEncoding", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "separateStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_FECData_rfc2733_mode_separateStream },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FECData_rfc2733_mode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FECData_rfc2733_mode, ett_h245_FECData_rfc2733_mode, FECData_rfc2733_mode_choice, "mode", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t FECData_rfc2733_sequence[] = {
+ { "mode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_FECData_rfc2733_mode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FECData_rfc2733(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FECData_rfc2733, ett_h245_FECData_rfc2733, FECData_rfc2733_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string FECData_vals[] = {
+ { 0, "rfc2733" },
+ { 0, NULL }
+};
+static per_choice_t FECData_choice[] = {
+ { 0, "rfc2733", ASN1_NO_EXTENSIONS,
+ dissect_h245_FECData_rfc2733 },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FECData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FECData, ett_h245_FECData, FECData_choice, "FECData", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t FECMode_rfc2733Mode_mode_separateStream_differentPort_sequence[] = {
+ { "protectedSessionID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_protectedSessionID },
+ { "protectedPayloadType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_protectedPayloadType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FECMode_rfc2733Mode_mode_separateStream_differentPort(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FECMode_rfc2733Mode_mode_separateStream_differentPort, ett_h245_FECMode_rfc2733Mode_mode_separateStream_differentPort, FECMode_rfc2733Mode_mode_separateStream_differentPort_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_tsapIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_tsapIdentifier, 0, 65535,
+ &ipv4_port, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_synchFlag(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_synchFlag, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_finite_1_65535(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_finite_1_65535, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static const value_string MultiplexElement_repeatCount_vals[] = {
+ { 0, "finite" },
+ { 1, "untilClosingFlag" },
+ { 0, NULL }
+};
+static per_choice_t MultiplexElement_repeatCount_choice[] = {
+ { 0, "finite", ASN1_NO_EXTENSIONS,
+ dissect_h245_finite_1_65535 },
+ { 1, "untilClosingFlag", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultiplexElement_repeatCount(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultiplexElement_repeatCount, ett_h245_MultiplexElement_repeatCount, MultiplexElement_repeatCount_choice, "repeatCount", NULL);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_MultiplexTableEntryNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_MultiplexTableEntryNumber, 1, 15,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultiplexEntryRejectionDescriptions_sequence[] = {
+ { "multiplexTableEntryNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultiplexTableEntryNumber },
+ { "cause", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultiplexEntryRejectionDescriptions_cause },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexEntryRejectionDescriptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexEntryRejectionDescriptions, ett_h245_MultiplexEntryRejectionDescriptions, MultiplexEntryRejectionDescriptions_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RequestMultiplexEntryRejectionDescriptions_sequence[] = {
+ { "multiplexTableEntryNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultiplexTableEntryNumber },
+ { "cause", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RequestMultiplexEntryRejectionDescriptions_cause},
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestMultiplexEntryRejectionDescriptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestMultiplexEntryRejectionDescriptions, ett_h245_RequestMultiplexEntryRejectionDescriptions, RequestMultiplexEntryRejectionDescriptions_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_dataModeBitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_dataModeBitRate, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_sessionDependency(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_sessionDependency, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_sRandom(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_sRandom, 1, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_McuNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_McuNumber, 0, 192,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_TerminalNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_TerminalNumber, 0, 192,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t TerminalLabel_sequence[] = {
+ { "mcuNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_McuNumber },
+ { "terminalNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_TerminalLabel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalLabel, ett_h245_TerminalLabel, TerminalLabel_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_maxNumberOfAdditionalConnections(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_maxNumberOfAdditionalConnections, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultilinkRequest_callInformation_sequence[] = {
+ { "maxNumberOfAdditionalConnections", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxNumberOfAdditionalConnections },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultilinkRequest_callInformation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkRequest_callInformation, ett_h245_MultilinkRequest_callInformation, MultilinkRequest_callInformation_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_requestedInterval(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_requestedInterval, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static const value_string MultilinkRequest_maximumHeaderInterval_requestType_vals[] = {
+ { 0, "currentIntervalInformation" },
+ { 1, "requestedInterval" },
+ { 0, NULL }
+};
+static per_choice_t MultilinkRequest_maximumHeaderInterval_requestType_choice[] = {
+ { 0, "currentIntervalInformation", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "requestedInterval", ASN1_EXTENSION_ROOT,
+ dissect_h245_requestedInterval },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultilinkRequest_maximumHeaderInterval_requestType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultilinkRequest_maximumHeaderInterval_requestType, ett_h245_MultilinkRequest_maximumHeaderInterval_requestType, MultilinkRequest_maximumHeaderInterval_requestType_choice, "requestType", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultilinkRequest_maximumHeaderInterval_sequence[] = {
+ { "requestType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultilinkRequest_maximumHeaderInterval_requestType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultilinkRequest_maximumHeaderInterval(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkRequest_maximumHeaderInterval, ett_h245_MultilinkRequest_maximumHeaderInterval, MultilinkRequest_maximumHeaderInterval_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_callAssociationNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_callAssociationNumber, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_currentInterval(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_currentInterval, 0, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MultilinkResponse_maximumHeaderInterval_sequence[] = {
+ { "currentInterval", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_currentInterval },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultilinkResponse_maximumHeaderInterval(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkResponse_maximumHeaderInterval, ett_h245_MultilinkResponse_maximumHeaderInterval, MultilinkResponse_maximumHeaderInterval_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_infoNotAvailable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_infoNotAvailable, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_channelTag(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_channelTag, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_ConnectionIDsequenceNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_ConnectionIDsequenceNumber, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t ConnectionIdentifier_sequence[] = {
+ { "channelTag", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_channelTag },
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ConnectionIDsequenceNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConnectionIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConnectionIdentifier, ett_h245_ConnectionIdentifier, ConnectionIdentifier_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultilinkRequest_removeConnection_sequence[] = {
+ { "connectionIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ConnectionIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultilinkRequest_removeConnection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkRequest_removeConnection, ett_h245_MultilinkRequest_removeConnection, MultilinkRequest_removeConnection_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultilinkResponse_removeConnection_sequence[] = {
+ { "connectionIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ConnectionIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultilinkResponse_removeConnection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkResponse_removeConnection, ett_h245_MultilinkResponse_removeConnection, MultilinkResponse_removeConnection_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultilinkIndication_excessiveError_sequence[] = {
+ { "connectionIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ConnectionIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultilinkIndication_excessiveError(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkIndication_excessiveError, ett_h245_MultilinkIndication_excessiveError, MultilinkIndication_excessiveError_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_MaximumBitRate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_MaximumBitRate, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t LogicalChannelRateRequest_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "logicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "maximumBitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MaximumBitRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_LogicalChannelRateRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_LogicalChannelRateRequest, ett_h245_LogicalChannelRateRequest, LogicalChannelRateRequest_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t LogicalChannelRateAck_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "logicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "maximumBitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MaximumBitRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_LogicalChannelRateAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_LogicalChannelRateAck, ett_h245_LogicalChannelRateAck, LogicalChannelRateAck_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t LogicalChannelRateReject_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "logicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "rejectReason", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelRateRejectReason },
+ { "currentMaximumBitRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_MaximumBitRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_LogicalChannelRateReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_LogicalChannelRateReject, ett_h245_LogicalChannelRateReject, LogicalChannelRateReject_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t LogicalChannelRateRelease_sequence[] = {
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_LogicalChannelRateRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_LogicalChannelRateRelease, ett_h245_LogicalChannelRateRelease, LogicalChannelRateRelease_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumBitRate_0_16777215(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_maximumBitRate_0_16777215, 0, 16777215,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static const value_string FlowControlCommand_restriction_vals[] = {
+ { 0, "maximumBitRate" },
+ { 1, "noRestriction" },
+ { 0, NULL }
+};
+static per_choice_t FlowControlCommand_restriction_choice[] = {
+ { 0, "maximumBitRate", ASN1_NO_EXTENSIONS,
+ dissect_h245_maximumBitRate_0_16777215 },
+ { 1, "noRestriction", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FlowControlCommand_restriction(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FlowControlCommand_restriction, ett_h245_FlowControlCommand_restriction, FlowControlCommand_restriction_choice, "restriction", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string FlowControlIndication_restriction_vals[] = {
+ { 0, "maximumBitRate" },
+ { 1, "noRestriction" },
+ { 0, NULL }
+};
+static per_choice_t FlowControlIndication_restriction_choice[] = {
+ { 0, "maximumBitRate", ASN1_NO_EXTENSIONS,
+ dissect_h245_maximumBitRate_0_16777215 },
+ { 1, "noRestrictions", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FlowControlIndication_restriction(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FlowControlIndication_restriction, ett_h245_FlowControlIndication_restriction, FlowControlIndication_restriction_choice, "restriction", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t FlowControlCommand_sequence[] = {
+ { "scope", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_FlowControlCommand_scope },
+ { "restriction", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_FlowControlCommand_restriction },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FlowControlCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FlowControlCommand, ett_h245_FlowControlCommand, FlowControlCommand_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t FlowControlIndication_sequence[] = {
+ { "scope", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_FlowControlIndication_scope },
+ { "restriction", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_FlowControlIndication_restriction },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FlowControlIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FlowControlIndication, ett_h245_FlowControlIndication, FlowControlIndication_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_firstGOB_0_17(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_firstGOB_0_17, 0, 17,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_numberOfGOBs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_numberOfGOBs, 1, 18,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MiscellaneousCommand_type_videoFastUpdateGOB_sequence[] = {
+ { "firstGOB", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_firstGOB_0_17 },
+ { "numberOfGOBs", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_numberOfGOBs },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousCommand_type_videoFastUpdateGOB(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MiscellaneousCommand_type_videoFastUpdateGOB, ett_h245_MiscellaneousCommand_type_videoFastUpdateGOB, MiscellaneousCommand_type_videoFastUpdateGOB_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_videoTemporalSpatialTradeOff(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_videoTemporalSpatialTradeOff, 0, 31,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_firstGOB_0_255(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_firstGOB_0_255, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_firstMB_1_8192(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_firstMB_1_8192, 1, 8192,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_firstMB_1_9216(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_firstMB_1_9216, 1, 9216,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_numberOfMBs_1_8192(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_numberOfMBs_1_8192, 1, 8192,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_numberOfMBs_1_9216(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_numberOfMBs_1_9216, 1, 9216,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MiscellaneousCommand_type_videoFastUpdateMB_sequence[] = {
+ { "firstGOB", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_firstGOB_0_255 },
+ { "firstMB", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_firstMB_1_8192 },
+ { "numberOfMBs", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_numberOfMBs_1_8192 },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousCommand_type_videoFastUpdateMB(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MiscellaneousCommand_type_videoFastUpdateMB, ett_h245_MiscellaneousCommand_type_videoFastUpdateMB, MiscellaneousCommand_type_videoFastUpdateMB_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maxH223MUXPDUsize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_maxH223MUXPDUsize, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_temporalReference_0_1023(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_temporalReference_0_1023, 0, 1023,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+
+static int
+dissect_h245_temporalReference_0_255(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_temporalReference_0_255, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MiscellaneousIndication_type_videoNotDecodedMBs_sequence[] = {
+ { "firstMB", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_firstMB_1_8192 },
+ { "numberOfMBs", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_numberOfMBs_1_8192 },
+ { "temporalReference", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_temporalReference_0_255 },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousIndication_type_videoNotDecodedMBs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MiscellaneousIndication_type_videoNotDecodedMBs, ett_h245_MiscellaneousIndication_type_videoNotDecodedMBs, MiscellaneousIndication_type_videoNotDecodedMBs_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t MiscellaneousCommand_type_videoBadMBs_sequence[] = {
+ { "firstMB", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_firstMB_1_9216 },
+ { "numberOfMBs", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_numberOfMBs_1_9216 },
+ { "temporalReference", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_temporalReference_0_1023 },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousCommand_type_videoBadMBs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MiscellaneousCommand_type_videoBadMBs, ett_h245_MiscellaneousCommand_type_videoBadMBs, MiscellaneousCommand_type_videoBadMBs_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_pictureNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_pictureNumber, 0, 1023,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_longTermPictureIndex(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_longTermPictureIndex, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static const value_string PictureReference_vals[] = {
+ { 0, "pictureNumber" },
+ { 1, "longTermPictureIndex" },
+ { 0, NULL }
+};
+static per_choice_t PictureReference_choice[] = {
+ { 0, "pictureNumber", ASN1_EXTENSION_ROOT,
+ dissect_h245_pictureNumber },
+ { 1, "longTermPictureIndex", ASN1_EXTENSION_ROOT,
+ dissect_h245_longTermPictureIndex },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_PictureReference(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_PictureReference, ett_h245_PictureReference, PictureReference_choice, "PictureReference", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MiscellaneousCommand_type_lostPartialPicture_sequence[] = {
+ { "pictureReference", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_PictureReference },
+ { "firstMB", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_firstMB_1_9216 },
+ { "numberOfMBs", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_numberOfMBs_1_9216 },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousCommand_type_lostPartialPicture(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MiscellaneousCommand_type_lostPartialPicture, ett_h245_MiscellaneousCommand_type_lostPartialPicture, MiscellaneousCommand_type_lostPartialPicture_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_sampleSize(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_sampleSize, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_samplesPerFrame(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_samplesPerFrame, 1, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MobileMultilinkReconfigurationIndication_sequence[] = {
+ { "sampleSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sampleSize },
+ { "samplesPerFrame", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_samplesPerFrame },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MobileMultilinkReconfigurationIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MobileMultilinkReconfigurationIndication, ett_h245_MobileMultilinkReconfigurationIndication, MobileMultilinkReconfigurationIndication_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MobileMultilinkReconfigurationCommand_sequence[] = {
+ { "sampleSize", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sampleSize },
+ { "samplesPerFrame", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_samplesPerFrame },
+ { "status", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MobileMultilinkReconfigurationCommand_status },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MobileMultilinkReconfigurationCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MobileMultilinkReconfigurationCommand, ett_h245_MobileMultilinkReconfigurationCommand, MobileMultilinkReconfigurationCommand_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_sbeNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_sbeNumber, 0, 9,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+
+
+
+static int
+dissect_h245_subPictureNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_subPictureNumber, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t TerminalYouAreSeeingInSubPictureNumber_sequence[] = {
+ { "terminalNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalNumber },
+ { "subPictureNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_subPictureNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_TerminalYouAreSeeingInSubPictureNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalYouAreSeeingInSubPictureNumber, ett_h245_TerminalYouAreSeeingInSubPictureNumber, TerminalYouAreSeeingInSubPictureNumber_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_compositionNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_compositionNumber, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t VideoIndicateCompose_sequence[] = {
+ { "compositionNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_compositionNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VideoIndicateCompose(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VideoIndicateCompose, ett_h245_VideoIndicateCompose, VideoIndicateCompose_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string ConferenceIndication_vals[] = {
+ { 0, "sbeNumber" },
+ { 1, "terminalNumberAssign" },
+ { 2, "terminalJoinedConference" },
+ { 3, "terminalLeftConference" },
+ { 4, "seenByAtLeastOneOther" },
+ { 5, "cancelSeenByAtLeastOneOther" },
+ { 6, "seenByAll" },
+ { 7, "cancelSeenByAll" },
+ { 8, "terminalAreYouSeeing" },
+ { 9, "requestForFloor" },
+ { 10, "withdrawChairToken" },
+ { 11, "floorRequested" },
+ { 12, "terminalAreYouSeeingInSubPictureNumber" },
+ { 13, "videoIndicateCompose" },
+ { 0, NULL }
+};
+static per_choice_t ConferenceIndication_choice[] = {
+ { 0, "sbeNumber", ASN1_EXTENSION_ROOT,
+ dissect_h245_sbeNumber },
+ { 1, "terminalNumberAssign", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 2, "terminalJoinedConference", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 3, "terminalLeftConference", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 4, "seenByAtLeastOneOther", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "cancelSeenByAtLeastOneOther", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "seenByAll", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "cancelSeenByAll", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 8, "terminalAreYouSeeing", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 9, "requestForFloor", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 10, "withdrawChairToken", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 11, "floorRequested", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 12, "terminalAreYouSeeingInSubPictureNumber", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_TerminalYouAreSeeingInSubPictureNumber },
+ { 13, "videoIndicateCompose", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_VideoIndicateCompose },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ConferenceIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ConferenceIndication, ett_h245_ConferenceIndication, ConferenceIndication_choice, "ConferenceIndication", NULL);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_estimatedReceivedJitterMantissa(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_estimatedReceivedJitterMantissa, 0, 3,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_estimatedReceivedJitterExponent(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_estimatedReceivedJitterExponent, 0, 7,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_skippedFrameCount(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_skippedFrameCount, 0, 15,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_additionalDecoderBuffer(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_additionalDecoderBuffer, 0, 262143,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t JitterIndication_sequence[] = {
+ { "scope", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_JitterIndication_scope },
+ { "estimatedReceivedJitterMantissa", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_estimatedReceivedJitterMantissa },
+ { "estimatedReceivedJitterExponent", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_estimatedReceivedJitterExponent },
+ { "skippedFrameCount", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_skippedFrameCount },
+ { "additionalDecoderBuffer", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_additionalDecoderBuffer },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_JitterIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_JitterIndication, ett_h245_JitterIndication, JitterIndication_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_skew(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_skew, 0, 4095,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t H223SkewIndication_sequence[] = {
+ { "logicalChannelNumber1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "logicalChannelNumber2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "skew", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_skew },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223SkewIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223SkewIndication, ett_h245_H223SkewIndication, H223SkewIndication_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_maximumSkew(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_maximumSkew, 0, 4095,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H2250MaximumSkewIndication_sequence[] = {
+ { "logicalChannelNumber1", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "logicalChannelNumber2", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "maximumSkew", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumSkew },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H2250MaximumSkewIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H2250MaximumSkewIndication, ett_h245_H2250MaximumSkewIndication, H2250MaximumSkewIndication_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_duration(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_duration, 1, 65535,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static per_sequence_t UserInputIndication_signalUpdate_sequence[] = {
+ { "duration", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_duration },
+ { "rtp", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_UserInputIndication_signalUpdate_rtp },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_UserInputIndication_signalUpdate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_UserInputIndication_signalUpdate, ett_h245_UserInputIndication_signalUpdate, UserInputIndication_signalUpdate_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_timestamp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_timestamp, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_expirationTime(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_expirationTime, 0, 4294967295UL,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t UserInputIndication_signal_rtp_sequence[] = {
+ { "timestamp", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_timestamp },
+ { "expirationTime", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_expirationTime },
+ { "logicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_UserInputIndication_signal_rtp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_UserInputIndication_signal_rtp, ett_h245_UserInputIndication_signal_rtp, UserInputIndication_signal_rtp_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+static per_sequence_t MasterSlaveDeterminationRelease_sequence[] = {
+ { NULL, ASN1_EXTENSION_ROOT, 0, NULL }
+};
+static int
+dissect_h245_MasterSlaveDeterminationRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MasterSlaveDeterminationRelease, ett_h245_MasterSlaveDeterminationRelease, MasterSlaveDeterminationRelease_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t MultilinkIndication_crcDesired_sequence[] = {
+ { NULL, ASN1_EXTENSION_ROOT, 0, NULL }
+};
+static int
+dissect_h245_MultilinkIndication_crcDesired(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkIndication_crcDesired, ett_h245_MultilinkIndication_crcDesired, MultilinkIndication_crcDesired_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_object(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h245_object, object);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_protocolIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h245_protocolIdentifier, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_algorithm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h245_algorithm, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_antiSpamAlgorithm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h245_antiSpamAlgorithm, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_standard_object(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h245_standard_object, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_oid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h245_oid, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_escrowID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h245_escrowID, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_field(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h245_field, NULL);
+ return offset;
+}
+
+
+
+
+/* dissect_h245_NonStandardIdentifier is used for H.245 */
+
+static const value_string NonStandardIdentifier_vals[] = {
+ { 0, "object" },
+ { 1, "h221NonStandard" },
+ { 0, NULL }
+};
+static per_choice_t NonStandardIdentifier_choice[] = {
+ { 0, "object", ASN1_NO_EXTENSIONS,
+ dissect_h245_object },
+ { 1, "h221NonStandard", ASN1_NO_EXTENSIONS,
+ dissect_h245_h221NonStandard },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NonStandardIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ *object = '\0';
+ h221NonStandard = 0;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NonStandardIdentifier, ett_h245_NonStandardIdentifier, NonStandardIdentifier_choice, "NonStandardIdentifier", &value);
+
+ switch (value) {
+ case 0 : /* object */
+ nsp_handle = dissector_get_string_handle(nsp_object_dissector_table, object);
+ break;
+ case 1 : /* h221NonStandard */
+ nsp_handle = dissector_get_port_handle(nsp_h221_dissector_table, h221NonStandard);
+ break;
+ default :
+ nsp_handle = NULL;
+ }
+
+ return offset;
+}
+
+static int
+dissect_h245_NonStandardParameterData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value_offset, value_len;
+ tvbuff_t *next_tvb;
+
+ if (nsp_handle) {
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, -1, -1, -1, &value_offset, &value_len);
+ next_tvb = tvb_new_subset(tvb, value_offset, value_len, value_len);
+ call_dissector(nsp_handle, next_tvb, pinfo, tree);
+ } else {
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_NonStandardParameterData, -1, -1, NULL, NULL);
+ }
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_nlpidData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_nlpidData, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_nonCollapsingRaw(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_nonCollapsingRaw, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_uuid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_uuid, 16, 16, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_octetString(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_octetString, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_externalReference(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_externalReference, 1, 255, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_nsapAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_nsapAddress, 1, 20, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_subaddress_1_20(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_subaddress_1_20, 1, 20, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_programDescriptors(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_programDescriptors, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_streamDescriptors(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_streamDescriptors, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_ipv4network(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ /* byte aligned */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ tvb_memcpy(tvb, (char *)&ipv4_address, offset>>3, 4);
+ proto_tree_add_ipv4(tree, hf_h245_ipv4network, tvb, offset>>3, 4, ipv4_address);
+
+ offset+=32;
+ return offset;
+}
+
+
+
+static int
+dissect_h245_ipxNode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_ipxNode, 6, 6, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_ipxNetnum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_ipxNetnum, 4, 4, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_ipv6network(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_ipv6network, 16, 16, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_netBios(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_netBios, 16, 16, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_nsap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_nsap, 1, 20, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_h235Key(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_h235Key, 1, 65535, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_value(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_value, 1, 65535, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_certificateResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_certificateResponse, 1, 65535, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_TerminalID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_TerminalID, 1, 128, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_ConferenceID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_ConferenceID, 1, 32, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_Password(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_Password, 1, 32, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_encryptionSE(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_encryptionSE, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+
+static int
+dissect_h245_conferenceIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_conferenceIdentifier, 1, 16, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_returnedFunction(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_returnedFunction, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_productNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_productNumber, 1, 256, NULL, NULL);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_versionNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h245_versionNumber, 1, 256, NULL, NULL);
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H222LogicalChannelParameters_sequence[] = {
+ { "resourceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_resourceID },
+ { "subChannelID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_subChannelID },
+ { "pcr-pid", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_pcr_pid },
+ { "programDescriptors", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_programDescriptors },
+ { "streamDescriptors", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_streamDescriptors },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H222LogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H222LogicalChannelParameters, ett_h245_H222LogicalChannelParameters, H222LogicalChannelParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t UnicastAddress_iPAddress_sequence[] = {
+ { "network", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ipv4network },
+ { "tsapIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_tsapIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_UnicastAddress_iPAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_UnicastAddress_iPAddress, ett_h245_UnicastAddress_iPAddress, UnicastAddress_iPAddress_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t UnicastAddress_iPXAddress_sequence[] = {
+ { "node", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ipxNode },
+ { "netnum", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ipxNetnum },
+ { "tsapIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_tsapIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_UnicastAddress_iPXAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_UnicastAddress_iPXAddress, ett_h245_UnicastAddress_iPXAddress, UnicastAddress_iPXAddress_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t UnicastAddress_iP6Address_sequence[] = {
+ { "network", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ipv6network },
+ { "tsapIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_tsapIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_UnicastAddress_iP6Address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_UnicastAddress_iP6Address, ett_h245_UnicastAddress_iP6Address, UnicastAddress_iP6Address_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t VendorIdentification_sequence[] = {
+ { "vendor", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NonStandardIdentifier },
+ { "productNumber", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_productNumber },
+ { "versionNumber", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_versionNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VendorIdentification(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VendorIdentification, ett_h245_VendorIdentification, VendorIdentification_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MulticastAddress_iPAddress_sequence[] = {
+ { "network", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ipv4network },
+ { "tsapIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_tsapIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MulticastAddress_iPAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MulticastAddress_iPAddress, ett_h245_MulticastAddress_iPAddress, MulticastAddress_iPAddress_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MulticastAddress_iP6Address_sequence[] = {
+ { "network", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ipv6network },
+ { "tsapIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_tsapIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MulticastAddress_iP6Address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MulticastAddress_iP6Address, ett_h245_MulticastAddress_iP6Address, MulticastAddress_iP6Address_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t Criteria_sequence[] = {
+ { "field", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_field },
+ { "value", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_value },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_Criteria(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_Criteria, ett_h245_Criteria, Criteria_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t ConferenceResponse_mCterminalIDResponse_sequence[] = {
+ { "terminalLabel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "terminalID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalID },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_mCterminalIDResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_mCterminalIDResponse, ett_h245_ConferenceResponse_mCterminalIDResponse, ConferenceResponse_mCterminalIDResponse_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t ConferenceResponse_conferenceIDResponse_sequence[] = {
+ { "terminalLabel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "conferenceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ConferenceID },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_conferenceIDResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_conferenceIDResponse, ett_h245_ConferenceResponse_conferenceIDResponse, ConferenceResponse_conferenceIDResponse_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t ConferenceResponse_passwordResponse_sequence[] = {
+ { "terminalLabel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "password", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_Password },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_passwordResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_passwordResponse, ett_h245_ConferenceResponse_passwordResponse, ConferenceResponse_passwordResponse_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t ConferenceResponse_extensionAddressResponse_sequence[] = {
+ { "extensionAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalID },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_extensionAddressResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_extensionAddressResponse, ett_h245_ConferenceResponse_extensionAddressResponse, ConferenceResponse_extensionAddressResponse_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t ConferenceResponse_chairTokenOwnerResponse_sequence[] = {
+ { "terminalLabel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "terminalID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalID },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_chairTokenOwnerResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_chairTokenOwnerResponse, ett_h245_ConferenceResponse_chairTokenOwnerResponse, ConferenceResponse_chairTokenOwnerResponse_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t ConferenceResponse_terminalCertificateResponse_sequence[] = {
+ { "terminalLabel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "certificateResponse", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_certificateResponse },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_terminalCertificateResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_terminalCertificateResponse, ett_h245_ConferenceResponse_terminalCertificateResponse, ConferenceResponse_terminalCertificateResponse_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t TerminalInformation_sequence[] = {
+ { "terminalLabel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "terminalID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalID },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_TerminalInformation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalInformation, ett_h245_TerminalInformation, TerminalInformation_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t SubstituteConferenceIDCommand_sequence[] = {
+ { "conferenceIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_conferenceIdentifier },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_SubstituteConferenceIDCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_SubstituteConferenceIDCommand, ett_h245_SubstituteConferenceIDCommand, SubstituteConferenceIDCommand_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string ConferenceCommand_vals[] = {
+ { 0, "broadcastMyLogicalChannel" },
+ { 1, "cancelBroadcastMyLogicalChannel" },
+ { 2, "makeTerminalBroadcaster" },
+ { 3, "cancelMakeTerminalBroadcaster" },
+ { 4, "sendThisSource" },
+ { 5, "cancelSendThisSource" },
+ { 6, "dropConference" },
+ { 7, "substituteConferenceIDCommand" },
+ { 0, NULL }
+};
+static per_choice_t ConferenceCommand_choice[] = {
+ { 0, "broadcastMyLogicalChannel", ASN1_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelNumber },
+ { 1, "cancelBroadcastMyLogicalChannel", ASN1_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelNumber },
+ { 2, "makeTerminalBroadcaster", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 3, "cancelMakeTerminalBroadcaster", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "sendThisSource", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 5, "cancelSendThisSource", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "dropConference", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "substituteConferenceIDCommand", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_SubstituteConferenceIDCommand },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ConferenceCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ConferenceCommand, ett_h245_ConferenceCommand, ConferenceCommand_choice, "ConferenceCommand", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t FunctionNotSupported_sequence[] = {
+ { "cause", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_FunctionNotSupported_cause },
+ { "returnedFunction", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_returnedFunction },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FunctionNotSupported(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FunctionNotSupported, ett_h245_FunctionNotSupported, FunctionNotSupported_sequence);
+
+ return offset;
+}
+
+
+
+
+/* dissect_h245_NonStandardParameter is used for H.245 */
+
+static per_sequence_t NonStandardParameter_sequence[] = {
+ { "nonStandardIdentifier", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_NonStandardIdentifier },
+ { "data", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_NonStandardParameterData },
+ { NULL, 0, 0, NULL }
+};
+int
+dissect_h245_NonStandardParameter(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ nsp_handle = NULL;
+
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NonStandardParameter, ett_h245_NonStandardParameter, NonStandardParameter_sequence);
+
+ return offset;
+}
+
+static const value_string DataProtocolCapability_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "v14buffered" },
+ { 2, "v42lapm" },
+ { 3, "hdlcFrameTunnelling" },
+ { 4, "h310SeparateVCStack" },
+ { 5, "h310SingleVCStack" },
+ { 6, "transparent" },
+ { 7, "segmentationAndReassembly" },
+ { 8, "hdlcFrameTunnelingwSAR" },
+ { 9, "v120" },
+ { 10, "separateLANStack" },
+ { 11, "v76wCompression" },
+ { 12, "tcp" },
+ { 13, "udp" },
+ { 0, NULL }
+};
+static per_choice_t DataProtocolCapability_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "v14buffered", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "v42lapm", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "hdlcFrameTunnelling", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "h310SeparateVCStack", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "h310SingleVCStack", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "transparent", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "segmentationAndReassembly", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 8, "hdlcFrameTunnelingwSAR", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 9, "v120", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 10, "separateLANStack", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 11, "v76wCompression", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability_v76wCompression },
+ { 12, "tcp", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 13, "udp", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+int
+dissect_h245_DataProtocolCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_DataProtocolCapability, ett_h245_DataProtocolCapability, DataProtocolCapability_choice, "DataProtocolCapability", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string MediaEncryptionAlgorithm_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "algorithm" },
+ { 0, NULL }
+};
+static per_choice_t MediaEncryptionAlgorithm_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "algorithm", ASN1_EXTENSION_ROOT,
+ dissect_h245_algorithm },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MediaEncryptionAlgorithm(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MediaEncryptionAlgorithm, ett_h245_MediaEncryptionAlgorithm, MediaEncryptionAlgorithm_choice, "MediaEncryptionAlgorithm", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string UserInputCapability_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "basicString" },
+ { 2, "iA5String" },
+ { 3, "generalString" },
+ { 4, "dtmf" },
+ { 5, "hookflash" },
+ { 6, "extendedAlphanumeric" },
+ { 0, NULL }
+};
+static per_choice_t UserInputCapability_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "basicString", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "iA5String", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "generalString", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "dtmf", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "hookflash", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "extendedAlphanumeric", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_UserInputCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_UserInputCapability, ett_h245_UserInputCapability, UserInputCapability_choice, "UserInputCapability", NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_domainBased(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h245_domainBased, 1, 64);
+
+ return offset;
+}
+
+
+
+
+static const value_string CapabilityIdentifier_vals[] = {
+ { 0, "standard" },
+ { 1, "h221NonStandard" },
+ { 2, "uuid" },
+ { 3, "domainBased" },
+ { 0, NULL }
+};
+static per_choice_t CapabilityIdentifier_choice[] = {
+ { 0, "standard", ASN1_EXTENSION_ROOT,
+ dissect_h245_standard_object },
+ { 1, "h221NonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 2, "uuid", ASN1_EXTENSION_ROOT,
+ dissect_h245_uuid },
+ { 3, "domainBased", ASN1_EXTENSION_ROOT,
+ dissect_h245_domainBased },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_CapabilityIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_CapabilityIdentifier, ett_h245_CapabilityIdentifier, CapabilityIdentifier_choice, "CapabilityIdentifier", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string ParameterIdentifier_vals[] = {
+ { 0, "standard" },
+ { 1, "h221NonStandard" },
+ { 2, "uuid" },
+ { 3, "domainBased" },
+ { 0, NULL }
+};
+static per_choice_t ParameterIdentifier_choice[] = {
+ { 0, "standard", ASN1_EXTENSION_ROOT,
+ dissect_h245_standard_0_127 },
+ { 1, "h221NonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 2, "uuid", ASN1_EXTENSION_ROOT,
+ dissect_h245_uuid },
+ { 3, "domainBased", ASN1_EXTENSION_ROOT,
+ dissect_h245_domainBased },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ParameterIdentifier(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ParameterIdentifier, ett_h245_ParameterIdentifier, ParameterIdentifier_choice, "ParameterIdentifier", NULL);
+
+ return offset;
+}
+
+
+static const value_string H223LogicalChannelParameters_adaptationLayerType_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "al1Framed" },
+ { 2, "al1NotFramed" },
+ { 3, "al2WithoutSequenceNumbers" },
+ { 4, "al2WithSequenceNumbers" },
+ { 5, "al3" },
+ { 6, "al1M" },
+ { 7, "al2M" },
+ { 8, "al3M" },
+ { 0, NULL }
+};
+static per_choice_t H223LogicalChannelParameters_adaptationLayerType_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "al1Framed", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "al1NotFramed", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "al2WithoutSequenceNumbers", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "al2WithSequenceNumbers", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "al3", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223LogicalChannelParameters_adaptionLayerType_al3 },
+ { 6, "al1M", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H223AL1MParameters },
+ { 7, "al2M", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H223AL2MParameters },
+ { 8, "al3M", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H223AL3MParameters },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223LogicalChannelParameters_adaptationLayerType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223LogicalChannelParameters_adaptationLayerType, ett_h245_H223LogicalChannelParameters_adaptationLayerType, H223LogicalChannelParameters_adaptationLayerType_choice, "adaptationLayerType", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string MulticastAddress_vals[] = {
+ { 0, "iPAddress" },
+ { 1, "iP6Address" },
+ { 2, "nsap" },
+ { 3, "nonStandardAddress" },
+ { 0, NULL }
+};
+static per_choice_t MulticastAddress_choice[] = {
+ { 0, "iPAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_MulticastAddress_iPAddress },
+ { 1, "iP6Address", ASN1_EXTENSION_ROOT,
+ dissect_h245_MulticastAddress_iP6Address },
+ { 2, "nsap", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_nsap },
+ { 3, "nonStandardAddress", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MulticastAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MulticastAddress, ett_h245_MulticastAddress, MulticastAddress_choice, "MulticastAddress", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string H223ModeParameters_adaptationLayerType_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "al1Framed" },
+ { 2, "al1NotFramed" },
+ { 3, "al2WithoutSequenceNumbers" },
+ { 4, "al2WithSequenceNumbers" },
+ { 5, "al3" },
+ { 6, "al1M" },
+ { 7, "al2M" },
+ { 8, "al3M" },
+ { 0, NULL }
+};
+static per_choice_t H223ModeParameters_adaptationLayerType_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "al1Framed", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "al1NotFramed", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "al2WithoutSequenceNumbers", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "al2WithSequenceNumbers", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "al3", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223ModeParameters_adaptationLayerType_al3 },
+ { 6, "al1M", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H223AL1MParameters },
+ { 7, "al2M", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H223AL2MParameters },
+ { 8, "al3M", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H223AL3MParameters },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H223ModeParameters_adaptationLayerType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H223ModeParameters_adaptationLayerType, ett_h245_H223ModeParameters_adaptationLayerType, H223ModeParameters_adaptationLayerType_choice, "Type", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string EncryptionMode_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "h233Encryption" },
+ { 0, NULL }
+};
+static per_choice_t EncryptionMode_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "h233Encryption", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_EncryptionMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_EncryptionMode, ett_h245_EncryptionMode, EncryptionMode_choice, "EncryptionMode", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t NonStandardMessage_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NonStandardParameter },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NonStandardMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NonStandardMessage, ett_h245_NonStandardMessage, NonStandardMessage_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string MultilinkIndication_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "crcDesired" },
+ { 2, "excessiveError" },
+ { 0, NULL }
+};
+static per_choice_t MultilinkIndication_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardMessage },
+ { 1, "crcDesired", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkIndication_crcDesired },
+ { 2, "excessiveError", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkIndication_excessiveError },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultilinkIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultilinkIndication, ett_h245_MultilinkIndication, MultilinkIndication_choice, "MultilinkIndication", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string DialingInformationNetworkType_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "n-isdn" },
+ { 2, "gstn" },
+ { 3, "mobile" },
+ { 0, NULL }
+};
+static per_choice_t DialingInformationNetworkType_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardMessage },
+ { 1, "n-isdn", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "gstn", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "mobile", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_DialingInformationNetworkType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_DialingInformationNetworkType, ett_h245_DialingInformationNetworkType, DialingInformationNetworkType_choice, "DialingInformationNetworkType", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t QOSCapability_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NonStandardParameter },
+ { "rsvpParameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RSVPParameters },
+ { "atmParameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_ATMParameters },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_QOSCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_QOSCapability, ett_h245_QOSCapability, QOSCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t DataApplicationCapability_application_t84_sequence[] = {
+ { "t84Protocol", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataProtocolCapability },
+ { "t84Profile", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_T84Profile },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_DataApplicationCapability_application_t84(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_DataApplicationCapability_application_t84, ett_h245_DataApplicationCapability_application_t84, DataApplicationCapability_application_t84_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t DataApplicationCapability_application_nlpid_sequence[] = {
+ { "nlpidProtocol", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataProtocolCapability },
+ { "nlpidData", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_nlpidData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_DataApplicationCapability_application_nlpid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_DataApplicationCapability_application_nlpid, ett_h245_DataApplicationCapability_application_nlpid, DataApplicationCapability_application_nlpid_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t DataApplicationCapability_application_t38fax_sequence[] = {
+ { "t38FaxProtocol", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataProtocolCapability },
+ { "t38FaxProfile", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_T38FaxProfile },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_DataApplicationCapability_application_t38fax(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_DataApplicationCapability_application_t38fax, ett_h245_DataApplicationCapability_application_t38fax, DataApplicationCapability_application_t38fax_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t AuthenticationCapability_sequence[] = {
+ { "nonStandard", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NonStandardParameter },
+ { "antiSpamAlgorithm", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_antiSpamAlgorithm },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_AuthenticationCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_AuthenticationCapability, ett_h245_AuthenticationCapability, AuthenticationCapability_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t IntegrityCapability_sequence[] = {
+ { "nonStandard", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NonStandardParameter },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_IntegrityCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_IntegrityCapability, ett_h245_IntegrityCapability, IntegrityCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H223LogicalChannelParameters_sequence[] = {
+ { "adaptationLayerType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223LogicalChannelParameters_adaptationLayerType },
+ { "segmentableFlag", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_segmentableFlag },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223LogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223LogicalChannelParameters, ett_h245_H223LogicalChannelParameters, H223LogicalChannelParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RequestChannelClose_sequence[] = {
+ { "forwardLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "qosCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_QOSCapability },
+ { "reason", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RequestChannelClose_reason },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestChannelClose(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestChannelClose, ett_h245_RequestChannelClose, RequestChannelClose_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t DataMode_application_nlpid_sequence[] = {
+ { "nlpidProtocol", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataProtocolCapability },
+ { "nlpidData", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_nlpidData },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_DataMode_application_nlpid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_DataMode_application_nlpid, ett_h245_DataMode_application_nlpid, DataMode_application_nlpid_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t DataMode_application_t38fax_sequence[] = {
+ { "t38FaxProtocol", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataProtocolCapability },
+ { "t38FaxProfile", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_T38FaxProfile },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_DataMode_application_t38fax(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_DataMode_application_t38fax, ett_h245_DataMode_application_t38fax, DataMode_application_t38fax_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t EncryptionCommand_encryptionAlgorithmID_sequence[] = {
+ { "h233AlgorithmIdentifier", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "associatedAlgorithm", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_NonStandardParameter },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_EncryptionCommand_encryptionAlgorithmID(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_EncryptionCommand_encryptionAlgorithmID, ett_h245_EncryptionCommand_encryptionAlgorithmID, EncryptionCommand_encryptionAlgorithmID_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string EncryptionCommand_vals[] = {
+ { 0, "encryptionSE" },
+ { 1, "encryptionIVRequest" },
+ { 2, "encryptionAlgorithmID" },
+ { 0, NULL }
+};
+static per_choice_t EncryptionCommand_choice[] = {
+ { 0, "encryptionSE", ASN1_EXTENSION_ROOT,
+ dissect_h245_encryptionSE },
+ { 1, "encryptionIVRequest", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "encryptionAlgorithmID", ASN1_EXTENSION_ROOT,
+ dissect_h245_EncryptionCommand_encryptionAlgorithmID },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_EncryptionCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_EncryptionCommand, ett_h245_EncryptionCommand, EncryptionCommand_choice, "EncryptionCommand", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string EndSessionCommand_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "disconnect" },
+ { 2, "gstnOptions" },
+ { 3, "isdnOptions" },
+ { 0, NULL }
+};
+static per_choice_t EndSessionCommand_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "disconnect", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "gstnOptions", ASN1_EXTENSION_ROOT,
+ dissect_h245_EndSessionCommand_gstnOptions },
+ { 3, "isdnOptions", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_EndSessionCommand_isdnOptions },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_EndSessionCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_EndSessionCommand_type, ett_h245_EndSessionCommand, EndSessionCommand_choice, "EndSessionCommand", NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static int
+dissect_h245_AudioCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static per_sequence_t VBDCapability_sequence[] = {
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_AudioCapability },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VBDCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VBDCapability, ett_h245_VBDCapability, VBDCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+
+
+static int
+dissect_h245_nonStandardData_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_nonStandardData, ett_h245_nonStandardData, dissect_h245_NonStandardParameter);
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_supersedes_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_supersedes, ett_h245_supersedes, dissect_h245_ParameterIdentifier );
+ return offset;
+}
+
+
+
+
+static const value_string ParameterValue_vals[] = {
+ { 0, "logical" },
+ { 1, "booleanArray" },
+ { 2, "unsignedMin" },
+ { 3, "unsignedMax" },
+ { 4, "unsigned32Min" },
+ { 5, "unsigned32Max" },
+ { 6, "octetString" },
+ { 7, "genericParameter" },
+ { 0, NULL }
+};
+static int dissect_h245_genericParameter_sequence_of(tvbuff_t *, int, packet_info *, proto_tree *);
+static per_choice_t ParameterValue_choice[] = {
+ { 0, "logical", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "booleanArray", ASN1_EXTENSION_ROOT,
+ dissect_h245_booleanArray },
+ { 2, "unsignedMin", ASN1_EXTENSION_ROOT,
+ dissect_h245_unsignedMin },
+ { 3, "unsignedMax", ASN1_EXTENSION_ROOT,
+ dissect_h245_unsignedMax },
+ { 4, "unsigned32Min", ASN1_EXTENSION_ROOT,
+ dissect_h245_unsigned32Min },
+ { 5, "unsigned32Max", ASN1_EXTENSION_ROOT,
+ dissect_h245_unsigned32Max },
+ { 6, "octetString", ASN1_EXTENSION_ROOT,
+ dissect_h245_octetString },
+ { 7, "genericParameter", ASN1_EXTENSION_ROOT,
+ dissect_h245_genericParameter_sequence_of },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ParameterValue(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ParameterValue, ett_h245_ParameterValue, ParameterValue_choice, "ParameterValue", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t GenericParameter_sequence[] = {
+ { "parameterIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ParameterIdentifier },
+ { "parameterValue", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ParameterValue },
+ { "supersedes", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_supersedes_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_GenericParameter(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_GenericParameter, ett_h245_GenericParameter, GenericParameter_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_genericParameter_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_genericParameter, ett_h245_genericParameter, dissect_h245_GenericParameter );
+ return offset;
+}
+
+
+
+static int
+dissect_h245_collapsing_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_collapsing, ett_h245_collapsing, dissect_h245_GenericParameter );
+ return offset;
+}
+
+
+static int
+dissect_h245_nonCollapsing_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_nonCollapsing, ett_h245_nonCollapsing, dissect_h245_GenericParameter );
+ return offset;
+}
+
+
+/* XXX */
+static int dissect_h245_RedundancyEncodingElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_secondary_REE_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_secondary_REE, ett_h245_secondary_REE, dissect_h245_RedundancyEncodingElement );
+ return offset;
+}
+
+
+
+
+/* XXX */
+static int dissect_h245_MultiplePayloadStreamElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_elements_MPSE_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_elements_MPSE, ett_h245_elements_MPSE, dissect_h245_MultiplePayloadStreamElement );
+ return offset;
+}
+
+
+
+
+/* XXX */
+static int dissect_h245_RedundancyEncodingDTModeElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_secondary_REDTME_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_secondary_REDTME, ett_h245_secondary_REDTME, dissect_h245_RedundancyEncodingDTModeElement );
+ return offset;
+}
+
+
+
+
+/* XXX*/
+static int dissect_h245_MultiplePayloadStreamElementMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_elements_MPSEM_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_elements_MPSEM, ett_h245_elements_MPSEM, dissect_h245_MultiplePayloadStreamElementMode );
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_TerminalInformationSO_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_TerminalInformationSO, ett_h245_TerminalInformationSO, dissect_h245_TerminalInformation );
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_lostPicture_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_lostPicture, ett_h245_lostPicture, dissect_h245_PictureReference );
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_recoveryReferencePicture_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_recoveryReferencePicture, ett_h245_recoveryReferencePicture, dissect_h245_PictureReference );
+ return offset;
+}
+
+
+
+
+
+
+
+static per_sequence_t ConferenceCapability_sequence[] = {
+ { "nonStandardData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_nonStandardData_sequence_of },
+ { "chairControlCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_chairControlCapability },
+ { "videoIndicateMixingCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoIndicateMixingCapability },
+ { "multipointVisualizationCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_multipointVisualizationCapability },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConferenceCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConferenceCapability, ett_h245_ConferenceCapability, ConferenceCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t GenericCapability_sequence[] = {
+ { "capabilityIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_CapabilityIdentifier },
+ { "maxBitRate", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_maxBitRate_4294967295UL },
+ { "collapsing", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_collapsing_sequence_of },
+ { "nonCollapsing", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_nonCollapsing_sequence_of },
+ { "nonCollapsingRaw", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_nonCollapsingRaw },
+ { "transport", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_DataProtocolCapability },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_GenericCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_GenericCapability, ett_h245_GenericCapability, GenericCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string DataApplicationCapability_application_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "t120" },
+ { 2, "dsm-cc" },
+ { 3, "userData" },
+ { 4, "t84" },
+ { 5, "t434" },
+ { 6, "h224" },
+ { 7, "nlpid" },
+ { 8, "dsvdControl" },
+ { 9, "h222DataPartitioning" },
+ { 10, "t30fax" },
+ { 11, "t140" },
+ { 12, "t38fax" },
+ { 13, "genericDataCapability" },
+ { 0, NULL }
+};
+static per_choice_t DataApplicationCapability_application_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "t120", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 2, "dsm-cc", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 3, "userData", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 4, "t84", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataApplicationCapability_application_t84 },
+ { 5, "t434", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 6, "h224", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 7, "nlpid", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataApplicationCapability_application_nlpid },
+ { 8, "dsvdControl", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 9, "h222DataPartitioning", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 10, "t30fax", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 11, "t140", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 12, "t38fax", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_DataApplicationCapability_application_t38fax },
+ { 13, "genericDataCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GenericCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_DataApplicationCapability_application(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_DataApplicationCapability_application, ett_h245_DataApplicationCapability_application, DataApplicationCapability_application_choice, "application", &value);
+
+ codec_type = val_to_str(value, DataApplicationCapability_application_vals, "<unknown>");
+
+ return offset;
+}
+
+
+
+
+static const value_string DataMode_application_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "t120" },
+ { 2, "dsm-cc" },
+ { 3, "userData" },
+ { 4, "t84" },
+ { 5, "t434" },
+ { 6, "h224" },
+ { 7, "nlpid" },
+ { 8, "dsvdControl" },
+ { 9, "h222DataPartitioning" },
+ { 10, "t30fax" },
+ { 11, "t140" },
+ { 12, "t38fax" },
+ { 13, "genericDataMode" },
+ { 0, NULL }
+};
+static per_choice_t DataMode_application_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "t120", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 2, "dsm-cc", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 3, "userData", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 4, "t84", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 5, "t434", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 6, "h224", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 7, "nlpid", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataMode_application_nlpid },
+ { 8, "dsvdControl", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 9, "h222DataPartitioning", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 10, "t30fax", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 11, "t140", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_DataProtocolCapability },
+ { 12, "t38fax", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_DataMode_application_t38fax },
+ { 13, "genericDataMode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GenericCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_DataMode_application(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_DataMode_application, ett_h245_DataMode_application, DataMode_application_choice, "application", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t MultiplePayloadStream_sequence[] = {
+ { "elements", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_elements_MPSE_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplePayloadStream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplePayloadStream, ett_h245_MultiplePayloadStream, MultiplePayloadStream_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t MultiplePayloadStreamMode_sequence[] = {
+ { "elements", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_elements_MPSEM_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplePayloadStreamMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplePayloadStreamMode, ett_h245_MultiplePayloadStreamMode, MultiplePayloadStreamMode_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t DataMode_sequence[] = {
+ { "application", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataMode_application },
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dataModeBitRate },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_DataMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_DataMode, ett_h245_DataMode, DataMode_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t RequestAllTerminalIDsResponse_sequence[] = {
+ { "terminalInformation", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalInformationSO_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestAllTerminalIDsResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestAllTerminalIDsResponse, ett_h245_RequestAllTerminalIDsResponse, RequestAllTerminalIDsResponse_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t DataApplicationCapability_sequence[] = {
+ { "application", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataApplicationCapability_application },
+ { "maxBitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxBitRate_4294967295UL },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_DataApplicationCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_DataApplicationCapability, ett_h245_DataApplicationCapability, DataApplicationCapability_sequence);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_iPSourceRouteAddress_route(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_, proto_tree *tree _U_)
+{
+PER_NOT_DECODED_YET("iPSourceRouteAddress");
+/* XXX
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_iPSourceRouteAddress_route, ett_h245_iPSourceRouteAddress_route, dissect_h245_ );
+*/
+ return offset;
+}
+
+
+
+static per_sequence_t UnicastAddress_iPSourceRouteAddress_sequence[] = {
+ { "routing", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_UnicastAddress_iPSourceRouteAddress_routing },
+ { "network", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ipv4network },
+ { "tsapIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_tsapIdentifier },
+ { "route", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_iPSourceRouteAddress_route },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_UnicastAddress_iPSourceRouteAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_UnicastAddress_iPSourceRouteAddress, ett_h245_UnicastAddress_iPSourceRouteAddress, UnicastAddress_iPSourceRouteAddress_sequence);
+
+ return offset;
+}
+
+
+
+static const value_string UnicastAddress_vals[] = {
+ { 0, "iPAddress" },
+ { 1, "iPXAddress" },
+ { 2, "iP6Address" },
+ { 3, "netBios" },
+ { 4, "iPSourceRouteAddress" },
+ { 5, "nsap" },
+ { 6, "nonStandardAddress" },
+ { 0, NULL }
+};
+static per_choice_t UnicastAddress_choice[] = {
+ { 0, "iPAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_UnicastAddress_iPAddress },
+ { 1, "iPXAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_UnicastAddress_iPXAddress },
+ { 2, "iP6Address", ASN1_EXTENSION_ROOT,
+ dissect_h245_UnicastAddress_iP6Address },
+ { 3, "netBios", ASN1_EXTENSION_ROOT,
+ dissect_h245_netBios },
+ { 4, "iPSourceRouteAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_UnicastAddress_iPSourceRouteAddress },
+ { 5, "nsap", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_nsap },
+ { 6, "nonStandardAddress", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_UnicastAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_UnicastAddress, ett_h245_UnicastAddress, UnicastAddress_choice, "UnicastAddress", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string TransportAddress_vals[] = {
+ { 0, "unicastAddress" },
+ { 1, "multicastAddress" },
+ { 0, NULL }
+};
+static per_choice_t TransportAddress_choice[] = {
+ { 0, "unicastAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_UnicastAddress },
+ { 1, "multicastAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_MulticastAddress },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_localAreaAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_localAreaAddress, ett_h245_TransportAddress, TransportAddress_choice, "localAreaAddress", NULL);
+
+ return offset;
+}
+static int
+dissect_h245_mediaChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ ipv4_address=0;
+ ipv4_port=0;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_mediaChannel, ett_h245_TransportAddress, TransportAddress_choice, "mediaChannel", NULL);
+
+ if((!pinfo->fd->flags.visited) && ipv4_address!=0 && ipv4_port!=0 && rtp_handle){
+ address src_addr;
+
+ src_addr.type=AT_IPv4;
+ src_addr.len=4;
+ src_addr.data=(char *)&ipv4_address;
+
+ rtp_add_address(pinfo, (char *)&ipv4_address, ipv4_port, 0, "H245", pinfo->fd->num);
+ }
+ return offset;
+}
+static int
+dissect_h245_mediaControlChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ ipv4_address=0;
+ ipv4_port=0;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_mediaControlChannel, ett_h245_TransportAddress, TransportAddress_choice, "mediaControlChannel", NULL);
+
+ if((!pinfo->fd->flags.visited) && ipv4_address!=0 && ipv4_port!=0 && rtcp_handle){
+ address src_addr;
+
+ src_addr.type=AT_IPv4;
+ src_addr.len=4;
+ src_addr.data=(char *)&ipv4_address;
+
+ rtcp_add_address(pinfo, (char *)&ipv4_address, ipv4_port, 0, "H245", pinfo->fd->num);
+ }
+ return offset;
+}
+static int
+dissect_h245_signalAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_signalAddress, ett_h245_TransportAddress, TransportAddress_choice, "signalAddress", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MCLocationIndication_sequence[] = {
+ { "signalAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_signalAddress },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MCLocationIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MCLocationIndication, ett_h245_MCLocationIndication, MCLocationIndication_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t H2250LogicalChannelAckParameters_sequence[] = {
+ { "nonStandard", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_nonStandardData_sequence_of },
+ { "sessionID", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_sessionID_1_255 },
+ { "mediaChannel", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaChannel },
+ { "mediaControlChannel", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaControlChannel },
+ { "dynamicRTPPayloadType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_dynamicRTPPayloadType },
+ { "flowControlToZero", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_flowControlToZero },
+ { "portNumber", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_portNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H2250LogicalChannelAckParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H2250LogicalChannelAckParameters, ett_h245_H2250LogicalChannelAckParameters, H2250LogicalChannelAckParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string forwardMultiplexAckParameters_vals[] = {
+ { 0, "h2250LogicalChannelAckParameters" },
+ { 0, NULL }
+};
+static per_choice_t forwardMultiplexAckParameters_choice[] = {
+ { 0, "h2250LogicalChannelAckParameters", ASN1_EXTENSION_ROOT,
+ dissect_h245_H2250LogicalChannelAckParameters },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_forwardMultiplexAckParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_forwardMultiplexAckParameters, ett_h245_forwardMultiplexAckParameters, forwardMultiplexAckParameters_choice, "forwardMultiplexAckParameters", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_AlternativeCapabilitySet(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_AlternativeCapabilitySet, ett_h245_AlternativeCapabilitySet, dissect_h245_CapabilityTableEntryNumber, 1, 256 );
+ return offset;
+}
+
+
+
+
+static int dissect_h245_rtpPayloadType_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static per_sequence_t MediaPacketizationCapability_sequence[] = {
+ { "h261aVideoPacketization", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h261aVideoPacketization },
+ { "rtpPayloadType", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_rtpPayloadType_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MediaPacketizationCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MediaPacketizationCapability, ett_h245_MediaPacketizationCapability, MediaPacketizationCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_qOSCapabilities(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_qOSCapabilities, ett_h245_qOSCapabilities, dissect_h245_QOSCapability, 1, 256 );
+ return offset;
+}
+
+
+
+static int
+dissect_h245_mediaChannelCapabilities(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_mediaChannelCapabilities, ett_h245_mediaChannelCapabilities, dissect_h245_MediaChannelCapability, 1, 256 );
+ return offset;
+}
+
+
+static per_sequence_t TransportCapability_sequence[] = {
+ { "nonStandard", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NonStandardParameter },
+ { "qOSCapabilities", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_qOSCapabilities },
+ { "mediaChannelCapabilities", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaChannelCapabilities },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_TransportCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TransportCapability, ett_h245_TransportCapability, TransportCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string MiscellaneousIndication_type_vals[] = {
+ { 0, "logicalChannelActive" },
+ { 1, "logicalChannelInactive" },
+ { 2, "multiportConference" },
+ { 3, "cancelMultiportConference" },
+ { 4, "multipointZeroComm" },
+ { 5, "cancelMultipointZeroComm" },
+ { 6, "multipointSecondryStatus" },
+ { 7, "cancelMultipointSecondryStatus" },
+ { 8, "videoIndicateReadyToActivate" },
+ { 9, "videoTemporalSpatialTradeOff" },
+ { 10, "videoNotDecodedMBs" },
+ { 11, "transportCapability" },
+ { 0, NULL }
+};
+static per_choice_t MiscellaneousIndication_type_choice[] = {
+ { 0, "logicalChannelActive", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "logicalChannelInactive", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "multiportConference", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "cancelMultiportConference", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "multipointZeroComm", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "cancelMultipointZeroComm", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "multipointSecondryStatus", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "cancelMultipointSecondryStatus", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 8, "videoIndicateReadyToActivate", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 9, "videoTemporalSpatialTradeOff", ASN1_EXTENSION_ROOT,
+ dissect_h245_videoTemporalSpatialTradeOff },
+ { 10, "videoNotDecodedMBs", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MiscellaneousIndication_type_videoNotDecodedMBs },
+ { 11, "transportCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_TransportCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousIndication_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MiscellaneousIndication_type, ett_h245_MiscellaneousIndication_type, MiscellaneousIndication_type_choice, "type", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t MiscellaneousIndication_sequence[] = {
+ { "logicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MiscellaneousIndication_type },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MiscellaneousIndication, ett_h245_MiscellaneousIndication, MiscellaneousIndication_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_CapabilityTableEntryNumber_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_CapabilityTableEntryNumber_sequence_of, ett_h245_CapabilityTableEntryNumber_sequence_of, dissect_h245_CapabilityTableEntryNumber, 1, 256 );
+ return offset;
+}
+
+
+
+
+static int dissect_h245_RTPH263VideoRedundancyFrameMapping(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_frameToThreadMapping_custom(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_frameToThreadMapping_custom, ett_h245_frameToThreadMapping_custom, dissect_h245_RTPH263VideoRedundancyFrameMapping, 1, 256 );
+ return offset;
+}
+
+
+
+
+static const value_string RTPH263VideoRedundancyEncoding_frameToThreadMapping_vals[] = {
+ { 0, "roundrobin" },
+ { 1, "custom" },
+ { 0, NULL }
+};
+static per_choice_t RTPH263VideoRedundancyEncoding_frameToThreadMapping_choice[] = {
+ { 0, "roundrobin", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "custom", ASN1_EXTENSION_ROOT,
+ dissect_h245_frameToThreadMapping_custom },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RTPH263VideoRedundancyEncoding_frameToThreadMapping(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RTPH263VideoRedundancyEncoding_frameToThreadMapping, ett_h245_RTPH263VideoRedundancyEncoding_frameToThreadMapping, RTPH263VideoRedundancyEncoding_frameToThreadMapping_choice, "frameToThreadMapping", NULL);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_containedThread(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_containedThread, 0, 15,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_containedThreads(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_containedThreads, ett_h245_containedThreads, dissect_h245_containedThread, 1, 256 );
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t RTPH263VideoRedundancyEncoding_sequence[] = {
+ { "numberOfThreads", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_numberOfThreads },
+ { "framesBetweenSyncPoints", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_framesBetweenSyncPoints },
+ { "frameToThreadMapping", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RTPH263VideoRedundancyEncoding_frameToThreadMapping },
+ { "containedThreads", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_containedThreads },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RTPH263VideoRedundancyEncoding(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RTPH263VideoRedundancyEncoding, ett_h245_RTPH263VideoRedundancyEncoding, RTPH263VideoRedundancyEncoding_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string RedundancyEncodingMethod_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "rtpAudioRedundancyEncoding" },
+ { 2, "rtpH263VideoRedundancyEncoding" },
+ { 0, NULL }
+};
+static per_choice_t RedundancyEncodingMethod_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "rtpAudioRedundancyEncoding", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "rtpH263VideoRedundancyEncoding", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_RTPH263VideoRedundancyEncoding },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncodingMethod(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RedundancyEncodingMethod, ett_h245_RedundancyEncodingMethod, RedundancyEncodingMethod_choice, "RedundancyEncodingMethod", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RedundancyEncodingCapability_sequence[] = {
+ { "redundancyEncodingMethod", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RedundancyEncodingMethod },
+ { "primaryEncoding", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_CapabilityTableEntryNumber },
+ { "secondaryEncoding", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_CapabilityTableEntryNumber_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncodingCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RedundancyEncodingCapability, ett_h245_RedundancyEncodingCapability, RedundancyEncodingCapability_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_RedundancyEncodingCapability_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_RedundancyEncodingCapability_sequence_of, ett_h245_RedundancyEncodingCapability_sequence_of, dissect_h245_RedundancyEncodingCapability, 1, 256 );
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_frame(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree,
+ hf_h245_frame, 0, 255,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_frameSequence(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_frameSequence, ett_h245_frameSequence, dissect_h245_frame, 1, 256 );
+ return offset;
+}
+
+
+
+
+static per_sequence_t RTPH263VideoRedundancyFrameMapping_sequence[] = {
+ { "threadNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_threadNumber },
+ { "frameSequence", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_frameSequence },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RTPH263VideoRedundancyFrameMapping(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RTPH263VideoRedundancyFrameMapping, ett_h245_RTPH263VideoRedundancyFrameMapping, RTPH263VideoRedundancyFrameMapping_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_EncryptionCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_EncryptionCapability, ett_h245_EncryptionCapability, dissect_h245_MediaEncryptionAlgorithm, 1, 256 );
+ return offset;
+}
+
+
+
+
+static per_sequence_t EncryptionAuthenticationAndIntegrity_sequence[] = {
+ { "encryptionCapability", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_EncryptionCapability },
+ { "authenticationCapability", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_AuthenticationCapability },
+ { "integrityCapability", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_IntegrityCapability },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_EncryptionAuthenticationAndIntegrity(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_EncryptionAuthenticationAndIntegrity, ett_h245_EncryptionAuthenticationAndIntegrity, EncryptionAuthenticationAndIntegrity_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t H235SecurityCapability_sequence[] = {
+ { "encryptionAuthenticationAndIntegrity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_EncryptionAuthenticationAndIntegrity },
+ { "mediaCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_CapabilityTableEntryNumber},
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H235SecurityCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H235SecurityCapability, ett_h245_H235SecurityCapability, H235SecurityCapability_sequence);
+
+ return offset;
+}
+
+
+static int dissect_h245_EscrowData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_escrowentry(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_escrowentry, ett_h245_escrowentry, dissect_h245_EscrowData, 1, 256 );
+ return offset;
+}
+
+
+
+
+static per_sequence_t EncryptionSync_sequence[] = {
+ { "nonStandard", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NonStandardParameter },
+ { "synchFlag", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_synchFlag },
+ { "h235Key", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h235Key },
+ { "escrowentry", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_escrowentry },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_EncryptionSync(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_EncryptionSync, ett_h245_EncryptionSync, EncryptionSync_sequence);
+
+ return offset;
+}
+
+
+
+static const value_string MiscellaneousCommand_type_vals[] = {
+ { 0, "equalizeDelay" },
+ { 1, "zeroDelay" },
+ { 2, "multipointModeCommand" },
+ { 3, "cancelMultipointModeCommand" },
+ { 4, "videoFreezePicture" },
+ { 5, "videoFastUpdatePicture" },
+ { 6, "videoFastUpdateGOB" },
+ { 7, "videoTemporalSpatialTradeOff" },
+ { 8, "videoSendSyncEveryGOB" },
+ { 9, "videoSendSyncEveryGOBCancel" },
+ { 10, "videoFastUpdateMB" },
+ { 11, "maxH223MUXPDUSize" },
+ { 12, "encryptionUpdate" },
+ { 13, "encryptionUpdateRequest" },
+ { 14, "switchReceiveMediaOff" },
+ { 15, "switchReceiveMediaOn" },
+ { 16, "progressiveRefinementStart" },
+ { 17, "progressiveRefinementAbortOne" },
+ { 18, "progressiveRefinementAbortContinous" },
+ { 19, "videoBadMBs" },
+ { 20, "lostPicture" },
+ { 21, "lostPartialPicture" },
+ { 22, "recoveryReferencePicture" },
+ { 0, NULL }
+};
+static per_choice_t MiscellaneousCommand_type_choice[] = {
+ { 0, "equalizeDelay", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "zeroDelay", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "multipointModeCommand", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "cancelMultipointModeCommand", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "videoFreezePicture", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "videoFastUpdatePicture", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "videoFastUpdateGOB", ASN1_EXTENSION_ROOT,
+ dissect_h245_MiscellaneousCommand_type_videoFastUpdateGOB },
+ { 7, "videoTemporalSpatialTradeOff", ASN1_EXTENSION_ROOT,
+ dissect_h245_videoTemporalSpatialTradeOff },
+ { 8, "videoSendSyncEveryGOB", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 9, "videoSendSyncEveryGOBCancel", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 10, "videoFastUpdateMB", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MiscellaneousCommand_type_videoFastUpdateMB },
+ { 11, "maxH223MUXPDUSize", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_maxH223MUXPDUsize },
+ { 12, "encryptionUpdate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_EncryptionSync },
+ { 13, "encryptionUpdateRequest", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_EncryptionUpdateRequest },
+ { 14, "switchReceiveMediaOff", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 15, "switchReceiveMediaOn", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 16, "progressiveRefinementStart", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MiscellaneousCommand_type_progressiveRefinementStart },
+ { 17, "progressiveRefinementAbortOne", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 18, "progressiveRefinementAbortContinous", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 19, "videoBadMBs", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MiscellaneousCommand_type_videoBadMBs },
+ { 20, "lostPicture", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_lostPicture_sequence_of },
+ { 21, "lostPartialPicture", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MiscellaneousCommand_type_lostPartialPicture},
+ { 22, "recoveryReferencePicture", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_recoveryReferencePicture_sequence_of },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousCommand_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MiscellaneousCommand_type, ett_h245_MiscellaneousCommand_type, MiscellaneousCommand_type_choice, "type", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MiscellaneousCommand_sequence[] = {
+ { "logicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MiscellaneousCommand_type },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MiscellaneousCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MiscellaneousCommand, ett_h245_MiscellaneousCommand, MiscellaneousCommand_sequence);
+
+ return offset;
+}
+
+
+
+static int dissect_h245_MultiplexElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_elementList(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_elementList, ett_h245_elementList, dissect_h245_MultiplexElement, 1, 256 );
+ return offset;
+}
+
+
+
+static per_sequence_t MultiplexEntryDescriptor_sequence[] = {
+ { "multiplexTableEntryNumber", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultiplexTableEntryNumber },
+ { "elementList", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h245_elementList },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexEntryDescriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexEntryDescriptor, ett_h245_MultiplexEntryDescriptor, MultiplexEntryDescriptor_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_subElementList(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_subElementList, ett_h245_subElementList, dissect_h245_MultiplexElement, 2, 255 );
+ return offset;
+}
+
+
+
+static const value_string MultiplexElement_type_vals[] = {
+ { 0, "logicalChannelNumber" },
+ { 1, "subElementList" },
+ { 0, NULL }
+};
+static per_choice_t MultiplexElement_type_choice[] = {
+ { 0, "logicalChannelNumber", ASN1_NO_EXTENSIONS,
+ dissect_h245_logicalChannelNumber },
+ { 1, "subElementList", ASN1_NO_EXTENSIONS,
+ dissect_h245_subElementList },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultiplexElement_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultiplexElement_type, ett_h245_MultiplexElement_type, MultiplexElement_type_choice, "type", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultiplexElement_sequence[] = {
+ { "type", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultiplexElement_type },
+ { "repeatCount", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultiplexElement_repeatCount },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexElement, ett_h245_MultiplexElement, MultiplexElement_sequence);
+
+ return offset;
+}
+
+
+
+
+static int dissect_h245_ModeDescription(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_requestedModes(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_requestedModes, ett_h245_requestedModes, dissect_h245_ModeDescription, 1, 256 );
+ return offset;
+}
+
+
+
+
+static per_sequence_t RequestMode_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "requestedModes", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_requestedModes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestMode, ett_h245_RequestMode, RequestMode_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_CertSelectionCriteria(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_CertSelectionCriteria, ett_h245_CertSelectionCriteria, dissect_h245_Criteria, 1, 16 );
+ return offset;
+}
+
+
+
+static per_sequence_t ConferenceRequest_requestTerminalCertificate_sequence[] = {
+ { "terminalLabel", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "certSelectionCriteria", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_CertSelectionCriteria },
+ { "sRandom", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_sRandom },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConferenceRequest_requestTerminalCertificate(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConferenceRequest_requestTerminalCertificate, ett_h245_ConferenceRequest_requestTerminalCertificate, ConferenceRequest_requestTerminalCertificate_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string ConferenceRequest_vals[] = {
+ { 0, "terminalListRequest" },
+ { 1, "makeMeChair" },
+ { 2, "cancelMakeMeChair" },
+ { 3, "dropTerminal" },
+ { 4, "requestTerminalID" },
+ { 5, "enterH243Password" },
+ { 6, "enterH243TerminalID" },
+ { 7, "enterH243ConferenceID" },
+ { 8, "enterExtensionAddress" },
+ { 9, "requestChairTokenOwner" },
+ { 10, "requestTerminalCertificate" },
+ { 11, "broadcastMyLogicalChannel" },
+ { 12, "makeTerminalBroadcaster" },
+ { 13, "sendThisSource" },
+ { 14, "requestAllTerminalIDs" },
+ { 15, "remoteMCRequest" },
+ { 0, NULL }
+};
+static per_choice_t ConferenceRequest_choice[] = {
+ { 0, "terminalListRequest", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "makeMeChair", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "cancelMakeMeChair", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "dropTerminal", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 4, "requestTerminalID", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 5, "enterH243Password", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "enterH243TerminalID", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "enterH243ConferenceID", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 8, "enterExtensionAddress", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 9, "requestChairTokenOwner", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 10, "requestTerminalCertificate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceRequest_requestTerminalCertificate },
+ { 11, "broadcastMyLogicalChannel", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelNumber },
+ { 12, "makeTerminalBroadcaster", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 13, "sendThisSource", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_TerminalLabel },
+ { 14, "requestAllTerminalIDs", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 15, "remoteMCRequest", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_RemoteMCRequest },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ConferenceRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ConferenceRequest, ett_h245_ConferenceRequest, ConferenceRequest_choice, "ConferenceRequest", NULL);
+
+ return offset;
+}
+
+static int dissect_h245_CapabilityTableEntry(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_capabilityTable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_capabilityTable, ett_h245_capabilityTable, dissect_h245_CapabilityTableEntry, 1, 256);
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_simultaneousCapabilities(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_simultaneousCapabilities, ett_h245_simultaneousCapabilities, dissect_h245_AlternativeCapabilitySet, 1, 256);
+ return offset;
+}
+
+
+
+
+static per_sequence_t CapabilityDescriptor_sequence[] = {
+ { "capabilityDescriptorNumber", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_CapabilityDescriptorNumber },
+ { "simultaneousCapabilities", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h245_simultaneousCapabilities },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CapabilityDescriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CapabilityDescriptor, ett_h245_CapabilityDescriptor, CapabilityDescriptor_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_capabilityDescriptors(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_capabilityDescriptors, ett_h245_capabilityDescriptors, dissect_h245_CapabilityDescriptor, 1, 256);
+ return offset;
+}
+
+
+
+
+static int dissect_h245_Q2931Address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_gatewayAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_gatewayAddress, ett_h245_gatewayAddress, dissect_h245_Q2931Address, 1, 256);
+ return offset;
+}
+
+
+
+static per_sequence_t VCCapability_aal1ViaGateway_sequence[] = {
+ { "gatewayAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_gatewayAddress },
+ { "nullClockRecovery", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_nullClockRecovery },
+ { "srtsClockRecovery", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_srtsClockRecovery },
+ { "adaptiveClockRecovery", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_adaptiveClockRecovery },
+ { "nullErrorCorrection", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_nullErrorCorrection },
+ { "longInterleaver", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_longInterleaver },
+ { "shortInterleaver", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_shortInterleaver },
+ { "errorCorrectionOnly", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_errorCorrectionOnly },
+ { "structuredDataTransfer", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_structuredDataTransfer },
+ { "partiallyFilledCells", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_partiallyFilledCells },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VCCapability_aal1ViaGateway(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VCCapability_aal1ViaGateway, ett_h245_VCCapability_aal1ViaGateway, VCCapability_aal1ViaGateway_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t VCCapability_availableBitRates_sequence[] = {
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_VCCapability_availableBitRates_type },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VCCapability_availableBitRates(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VCCapability_availableBitRates, ett_h245_VCCapability_availableBitRates, VCCapability_availableBitRates_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t VCCapability_sequence[] = {
+ { "aal1", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_VCCapability_aal1 },
+ { "aal5", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_VCCapability_aal5 },
+ { "transportStream", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_transportStream },
+ { "programStream", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_programStream },
+ { "availableBitRates", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_VCCapability_availableBitRates },
+ { "aal1ViaGateway", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_VCCapability_aal1ViaGateway },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VCCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VCCapability, ett_h245_VCCapability, VCCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int dissect_h245_EnhancementOptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_snrEnhancement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_snrEnhancement, ett_h245_snrEnhancement, dissect_h245_EnhancementOptions, 1, 14);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_spatialEnhancement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_spatialEnhancement, ett_h245_spatialEnhancement, dissect_h245_EnhancementOptions, 1, 14);
+ return offset;
+}
+
+
+
+
+static int dissect_h245_BEnhancementParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_bPictureEnhancement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_bPictureEnhancement, ett_h245_bPictureEnhancement, dissect_h245_BEnhancementParameters, 1, 14);
+ return offset;
+}
+
+
+
+
+static per_sequence_t EnhancementLayerInfo_sequence[] = {
+ { "baseBitRateConstrained", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_baseBitRateConstrained },
+ { "snrEnhancement", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_snrEnhancement },
+ { "spatialEnhancement", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_spatialEnhancement },
+ { "bPictureEnhancement", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_bPictureEnhancement },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_EnhancementLayerInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_EnhancementLayerInfo, ett_h245_EnhancementLayerInfo, EnhancementLayerInfo_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_customPictureClockFrequency(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_customPictureClockFrequency, ett_h245_customPictureClockFrequency, dissect_h245_CustomPictureClockFrequency, 1, 16);
+ return offset;
+}
+
+
+
+
+static int dissect_h245_CustomPictureFormat(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+
+static int
+dissect_h245_customPictureFormat(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_customPictureFormat, ett_h245_customPictureFormat, dissect_h245_CustomPictureFormat, 1, 16);
+ return offset;
+}
+
+
+
+static int dissect_h245_H263VideoModeCombos(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_modeCombos(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_modeCombos, ett_h245_modeCombos, dissect_h245_H263VideoModeCombos, 1, 16);
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H263Options_sequence[] = {
+ { "advancedIntraCodingMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_advancedIntraCodingMode },
+ { "deblockingFilterMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_deblockingFilterMode },
+ { "improvedPBFramesMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_improvedPBFramesMode },
+ { "unlimitedMotionVectors", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_unlimitedMotionVectors },
+ { "fullPictureFreeze", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_fullPictureFreeze },
+ { "partialPictureFreezeAndRelease", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_partialPictureFreezeAndRelease },
+ { "resizingPartPicFreezeAndRelease", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_resizingPartPicFreezeAndRelease },
+ { "fullPictureSnapshot", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_fullPictureSnapshot },
+ { "partialPictureSnapshot", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_partialPictureSnapshot },
+ { "videoSegmentTagging", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoSegmentTagging },
+ { "progressiveRefinement", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_progressiveRefinement },
+ { "dynamicPictureResizingByFour", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicPictureResizingByFour },
+ { "dynamicPictureResizingSixteenthPel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicPictureResizingSixteenthPel },
+ { "dynamicWarpingHalfPel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicWarpingHalfPel },
+ { "dynamicWarpingSixteenthPel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicWarpingSixteenthPel },
+ { "independentSegmentDecoding", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_independentSegmentDecoding },
+ { "slicesInOrder-NonRect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_slicesInOrderNonRect },
+ { "slicesInOrder-Rect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_slicesInOrderRect },
+ { "slicesNoOrder-NonRect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_slicesNoOrderNonRect },
+ { "slicesNoOrder-Rect", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_slicesNoOrderRect },
+ { "alternateInterVLCMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_alternateInterVLCMode },
+ { "modifiedQuantizationMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_modifiedQuantizationMode },
+ { "reducedResolutionUpdate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_reducedResolutionUpdate },
+ { "transparencyParameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_TransperencyParameters },
+ { "separateVideoBackChannel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_separateVideoBackChannel },
+ { "refPictureSelection", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RefPictureSelection },
+ { "customPictureClockFrequence", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_customPictureClockFrequency },
+ { "customPictureFormat", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_customPictureFormat },
+ { "modeCombos", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_modeCombos },
+ { "videoBadMBsCap", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_videoBadMBsCap },
+ { "h263Version3Options", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H263Version3Options },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H263Options(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H263Options, ett_h245_H263Options, H263Options_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H263VideoMode_sequence[] = {
+ { "resolution", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H263VideoMode_resolution },
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h223bitRate },
+ { "unrestrictedVector", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_unrestrictedVector },
+ { "arithmeticCoding", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_arithmeticCoding },
+ { "advancedPrediction", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_advancedPrediction },
+ { "pbFrames", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_pbFrames },
+ { "errorCompensation", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_errorCompensation },
+ { "enhancementLayerInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_EnhancementLayerInfo },
+ { "h263Options", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_H263Options },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H263VideoMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H263VideoMode, ett_h245_H263VideoMode, H263VideoMode_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H263VideoCapability_sequence[] = {
+ { "sqcifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_sqcifMPI_1_32 },
+ { "qcifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_qcifMPI_1_32 },
+ { "cifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cifMPI_1_32 },
+ { "cif4MPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cif4MPI_1_32 },
+ { "cif16MPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cif16MPI_1_32 },
+ { "maxBitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxBitRate_192400 },
+ { "unrestrictedVector", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_unrestrictedVector },
+ { "arithmeticCoding", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_arithmeticCoding },
+ { "advancedPrediction", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_advancedPrediction },
+ { "pbFrames", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_pbFrames },
+ { "temporalSpatialTradeOffCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_temporalSpatialTradeOffCapability },
+ { "hrd-B", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_hrd_B },
+ { "bppMaxKb", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_bppMaxKb },
+ { "slowSqcifMPI", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowSqcifMPI },
+ { "slowQcifMPI", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowQcifMPI },
+ { "slowCifMPI", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowCifMPI },
+ { "slowCif4MPI", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowCif4MPI },
+ { "slowCif16MPI", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowCif16MPI },
+ { "errorCompensation", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_errorCompensation },
+ { "enhancementLayerInfo", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_EnhancementLayerInfo },
+ { "h263Options", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_H263Options },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H263VideoCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H263VideoCapability, ett_h245_H263VideoCapability, H263VideoCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string VideoCapability_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "h261VideoCapability" },
+ { 2, "h262VideoCapability" },
+ { 3, "h263VideoCapability" },
+ { 4, "is11172VideoCapability" },
+ { 5, "genericVideoCapability" },
+ { 0, NULL }
+};
+static per_choice_t VideoCapability_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "h261VideoCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_H261VideoCapability },
+ { 2, "h262VideoCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_H262VideoCapability },
+ { 3, "h263VideoCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_H263VideoCapability },
+ { 4, "is11172VideoCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_IS11172VideoCapability},
+ { 5, "genericVideoCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GenericCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_VideoCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_VideoCapability, ett_h245_VideoCapability, VideoCapability_choice, "VideoCapability", &value );
+
+ codec_type = val_to_str(value, VideoCapability_vals, "<unknown>");
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t EnhancementOptions_sequence[] = {
+ { "sqcifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_sqcifMPI_1_32 },
+ { "qcifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_qcifMPI_1_32 },
+ { "cifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cifMPI_1_32 },
+ { "cif4MPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cif4MPI_1_32 },
+ { "cif16MPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_cif16MPI_1_32 },
+ { "maxBitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxBitRate_192400 },
+ { "unrestrictedVector", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_unrestrictedVector },
+ { "arithmeticCoding", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_arithmeticCoding },
+ { "temporalSpatialTradeOffCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_temporalSpatialTradeOffCapability },
+ { "slowSqcifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowSqcifMPI },
+ { "slowQcifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowQcifMPI },
+ { "slowCifMPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowCifMPI },
+ { "slowCif4MPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowCif4MPI },
+ { "slowCif16MPI", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_slowCif16MPI },
+ { "errorCompensation", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_errorCompensation },
+ { "h263Options", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_H263Options },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_EnhancementOptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_EnhancementOptions, ett_h245_EnhancementOptions, EnhancementOptions_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t BEnhancementParameters_sequence[] = {
+ { "enhancementOptions", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_EnhancementOptions },
+ { "numberOfBPictures", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_numberOfBPictures },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_BEnhancementParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_BEnhancementParameters, ett_h245_BEnhancementParameters, BEnhancementParameters_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_customPCF(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_customPCF, ett_h245_customPCF, dissect_h245_CustomPictureFormat_mPI_customPCF, 1, 16);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_PixelAspectCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_PixelAspectCode, 1, 14,
+ NULL, NULL, FALSE);
+
+ return offset;
+}
+
+static int
+dissect_h245_pixelAspectCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_pixelAspectCode, ett_h245_pixelAspectCode, dissect_h245_PixelAspectCode, 1, 14);
+ return offset;
+}
+
+
+
+static int dissect_h245_extendedPAR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static const value_string CustomPictureFormat_pixelAspectInformation_vals[] = {
+ { 0, "anyPixelAspectRatio" },
+ { 1, "pixelAspectCode" },
+ { 2, "extendedPAR" },
+ { 0, NULL }
+};
+static per_choice_t CustomPictureFormat_pixelAspectInformation_choice[] = {
+ { 0, "anyPixelAspectRatio", ASN1_EXTENSION_ROOT,
+ dissect_h245_anyPixelAspectRatio },
+ { 1, "pixelAspectCode", ASN1_EXTENSION_ROOT,
+ dissect_h245_pixelAspectCode },
+ { 2, "extendedPAR", ASN1_EXTENSION_ROOT,
+ dissect_h245_extendedPAR },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_CustomPictureFormat_pixelAspectInformation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_CustomPictureFormat_pixelAspectInformation, ett_h245_CustomPictureFormat_pixelAspectInformation, CustomPictureFormat_pixelAspectInformation_choice, "pixelAspectInformation", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t CustomPictureFormat_sequence[] = {
+ { "maxCustomPictureWidth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxCustomPictureWidth },
+ { "maxCustomPictureHeight", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maxCustomPictureHeight},
+ { "minCustomPictureWidth", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_minCustomPictureWidth },
+ { "minCustomPictureHeight", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_minCustomPictureHeight },
+ { "mPI", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_CustomPictureFormat_mPI },
+ { "pixelAspectInformation", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_CustomPictureFormat_pixelAspectInformation },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CustomPictureFormat(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CustomPictureFormat, ett_h245_CustomPictureFormat, CustomPictureFormat_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_extendedPAR(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_extendedPAR, ett_h245_extendedPAR, dissect_h245_CustomPictureFormat_pixelAspectInformation_extendedPAR, 1, 256);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_h263VideoCoupledModes(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_h263VideoCoupledModes, ett_h245_h263VideoCoupledModes, dissect_h245_H263ModeComboFlags, 1, 16);
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H263VideoModeCombos_sequence[] = {
+ { "h263VideoUncoupledModes", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H263ModeComboFlags },
+ { "h263VideoCoupledModes", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h263VideoCoupledModes },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H263VideoModeCombos(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H263VideoModeCombos, ett_h245_H263VideoModeCombos, H263VideoModeCombos_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_capabilityOnMuxStream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_capabilityOnMuxStream, ett_h245_capabilityOnMuxStream, dissect_h245_AlternativeCapabilitySet, 1, 256);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_capabilities(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_capabilities, ett_h245_capabilities, dissect_h245_AlternativeCapabilitySet, 1, 256);
+ return offset;
+}
+
+
+
+static per_sequence_t MultiplePayloadStreamCapability_sequence[] = {
+ { "capabilities", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_capabilities },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplePayloadStreamCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplePayloadStreamCapability, ett_h245_MultiplePayloadStreamCapability, MultiplePayloadStreamCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_multiplexEntryDescriptors(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_multiplexEntryDescriptors, ett_h245_multiplexEntryDescriptors, dissect_h245_MultiplexEntryDescriptor, 1, 15);
+ return offset;
+}
+
+
+
+static per_sequence_t MultiplexEntrySend_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "multiplexEntryDescriptors", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_multiplexEntryDescriptors },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexEntrySend(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexEntrySend, ett_h245_MultiplexEntrySend, MultiplexEntrySend_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_multiplexTableEntryNumber_set_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_multiplexTableEntryNumber_set_of, ett_h245_multiplexTableEntryNumber_set_of, dissect_h245_MultiplexTableEntryNumber, 1, 15);
+ return offset;
+}
+
+
+
+static per_sequence_t MultiplexEntrySendRelease_sequence[] = {
+ { "multiplexTableEntryNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_multiplexTableEntryNumber_set_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexEntrySendRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexEntrySendRelease, ett_h245_MultiplexEntrySendRelease, MultiplexEntrySendRelease_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultiplexEntrySendAck_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "multiplexTableEntryNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_multiplexTableEntryNumber_set_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexEntrySendAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexEntrySendAck, ett_h245_MultiplexEntrySendAck, MultiplexEntrySendAck_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_RMErejectionDescriptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_rejectionDescriptions, ett_h245_rejectionDescriptions, dissect_h245_RequestMultiplexEntryRejectionDescriptions, 1, 15);
+ return offset;
+}
+
+
+static int
+dissect_h245_rejectionDescriptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_rejectionDescriptions, ett_h245_rejectionDescriptions, dissect_h245_MultiplexEntryRejectionDescriptions, 1, 15);
+ return offset;
+}
+
+
+
+
+
+
+static per_sequence_t MultiplexEntrySendReject_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "rejectionDescriptions", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_rejectionDescriptions },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexEntrySendReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexEntrySendReject, ett_h245_MultiplexEntrySendReject, MultiplexEntrySendReject_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_entryNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_entryNumbers, ett_h245_entryNumbers, dissect_h245_MultiplexTableEntryNumber, 1, 15);
+ return offset;
+}
+
+
+
+
+static per_sequence_t RequestMultiplexEntry_sequence[] = {
+ { "entryNumbers", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_entryNumbers },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestMultiplexEntry(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestMultiplexEntry, ett_h245_RequestMultiplexEntry, RequestMultiplexEntry_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t RequestMultiplexEntryAck_sequence[] = {
+ { "entryNumbers", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_entryNumbers },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestMultiplexEntryAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestMultiplexEntryAck, ett_h245_RequestMultiplexEntryAck, RequestMultiplexEntryAck_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RequestMultiplexEntryReject_sequence[] = {
+ { "entryNumbers", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_entryNumbers },
+ { "rejectionDescriptions", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RMErejectionDescriptions },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestMultiplexEntryReject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestMultiplexEntryReject, ett_h245_RequestMultiplexEntryReject, RequestMultiplexEntryReject_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t RequestMultiplexEntryRelease_sequence[] = {
+ { "entryNumbers", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_entryNumbers },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestMultiplexEntryRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestMultiplexEntryRelease, ett_h245_RequestMultiplexEntryRelease, RequestMultiplexEntryRelease_sequence);
+
+ return offset;
+}
+
+
+
+static int dissect_h245_ModeElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_ModeDescription(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_ModeDescription, ett_h245_ModeDescription, dissect_h245_ModeElement, 1, 256);
+ return offset;
+}
+
+
+
+
+static int dissect_h245_CommunicationModeTableEntry(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_communicationModeTable(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_communicationModeTable, ett_h245_communicationModeTable, dissect_h245_CommunicationModeTableEntry, 1, 256);
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t CommunicationModeCommand_sequence[] = {
+ { "communicationModeTable", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_communicationModeTable },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CommunicationModeCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CommunicationModeCommand, ett_h245_CommunicationModeCommand, CommunicationModeCommand_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string CommunicationModeResponse_vals[] = {
+ { 0, "communicationModeTable" },
+ { 0, NULL }
+};
+static per_choice_t CommunicationModeResponse_choice[] = {
+ { 0, "communicationModeTable", ASN1_EXTENSION_ROOT,
+ dissect_h245_communicationModeTable },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_CommunicationModeResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_CommunicationModeResponse, ett_h245_CommunicationModeResponse, CommunicationModeResponse_choice, "CommunicationModeResponse", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_terminalListResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_terminalListResponse, ett_h245_terminalListResponse, dissect_h245_TerminalLabel, 1, 256);
+ return offset;
+}
+
+
+
+
+static int dissect_h245_DialingInformationNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static int
+dissect_h245_differential(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_differential, ett_h245_differential, dissect_h245_DialingInformationNumber, 1, 65535);
+ return offset;
+}
+
+
+
+
+
+static const value_string DialingInformation_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "differential" },
+ { 2, "infoNotAvailable" },
+ { 0, NULL }
+};
+static per_choice_t DialingInformation_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardMessage },
+ { 1, "differential", ASN1_EXTENSION_ROOT,
+ dissect_h245_differential },
+ { 2, "infoNotAvailable", ASN1_EXTENSION_ROOT,
+ dissect_h245_infoNotAvailable },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_DialingInformation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_DialingInformation, ett_h245_DialingInformation, DialingInformation_choice, "DialingInformation", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t MultilinkResponse_callInformation_sequence[] = {
+ { "dialingInformation", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DialingInformation },
+ { "callAssociationNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_callAssociationNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultilinkResponse_callInformation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkResponse_callInformation, ett_h245_MultilinkResponse_callInformation, MultilinkResponse_callInformation_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+static const value_string MultilinkResponse_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "callInformation" },
+ { 2, "addConnection" },
+ { 3, "removeConnection" },
+ { 4, "maximumHeaderInterval" },
+ { 0, NULL }
+};
+static per_choice_t MultilinkResponse_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardMessage },
+ { 1, "callInformation", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkResponse_callInformation },
+ { 2, "addConnection", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkResponse_addConnection },
+ { 3, "removeConnection", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkResponse_removeConnection },
+ { 4, "maximumHeaderInterval", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkResponse_maximumHeaderInterval },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultilinkResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultilinkResponse, ett_h245_MultilinkResponse, MultilinkResponse_choice, "MultilinkResponse", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultilinkRequest_addConnection_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "dialingInformation", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DialingInformation },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultilinkRequest_addConnection(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultilinkRequest_addConnection, ett_h245_MultilinkRequest_addConnection, MultilinkRequest_addConnection_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string MultilinkRequest_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "callInformation" },
+ { 2, "addConnection" },
+ { 3, "removeConnection" },
+ { 4, "maximumHeaderInterval" },
+ { 0, NULL }
+};
+static per_choice_t MultilinkRequest_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardMessage },
+ { 1, "callInformation", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkRequest_callInformation },
+ { 2, "addConnection", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkRequest_addConnection },
+ { 3, "removeConnection", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkRequest_removeConnection },
+ { 4, "maximumHeaderInterval", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultilinkRequest_maximumHeaderInterval },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultilinkRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultilinkRequest, ett_h245_MultilinkRequest, MultilinkRequest_choice, "MultilinkRequest", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_networkType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_networkType, ett_h245_networkType, dissect_h245_DialingInformationNetworkType, 1, 255);
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_capabilityTableEntryNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_capabilityTableEntryNumbers, ett_h245_capabilityTableEntryNumbers, dissect_h245_CapabilityTableEntryNumber, 1, 65535);
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_capabilityDescriptorNumbers(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_set_of(tvb, offset, pinfo, tree, hf_h245_capabilityDescriptorNumbers, ett_h245_capabilityDescriptorNumbers, dissect_h245_CapabilityDescriptorNumber, 1, 256);
+ return offset;
+}
+
+
+
+
+static per_sequence_t SendTerminalCapabilitySet_specificRequest_sequence[] = {
+ { "multiplexCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_multiplexCapability_bool },
+ { "capabilityTableEntryNumbers", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_capabilityTableEntryNumbers },
+ { "capabilityDescriptorNumbers", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_capabilityDescriptorNumbers },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_SendTerminalCapabilitySet_specificRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_SendTerminalCapabilitySet_specificRequest, ett_h245_SendTerminalCapabilitySet_specificRequest, SendTerminalCapabilitySet_specificRequest_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string SendTerminalCapabilitySet_vals[] = {
+ { 0, "specificRequest" },
+ { 1, "genericRequest" },
+ { 0, NULL }
+};
+static per_choice_t SendTerminalCapabilitySet_choice[] = {
+ { 0, "specificRequest", ASN1_EXTENSION_ROOT,
+ dissect_h245_SendTerminalCapabilitySet_specificRequest },
+ { 1, "genericRequest", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_SendTerminalCapabilitySet(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_SendTerminalCapabilitySet, ett_h245_SendTerminalCapabilitySet, SendTerminalCapabilitySet_choice, "SendTerminalCapabilitySet", NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static int
+dissect_h245_audioTelephoneEvent(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_GeneralString(tvb, offset, pinfo, tree, hf_h245_audioTelephoneEvent);
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t AudioTelephonyEventCapability_sequence[] = {
+ { "dynamicRTPPayloadType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_dynamicRTPPayloadType },
+ { "audioTelephoneEvent", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioTelephoneEvent },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_AudioTelephonyEventCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_AudioTelephonyEventCapability, ett_h245_AudioTelephonyEventCapability, AudioTelephonyEventCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+static per_sequence_t NoPTAudioTelephonyEventCapability_sequence[] = {
+ { "audioTelephoneEvent", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_audioTelephoneEvent },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NoPTAudioTelephonyEventCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NoPTAudioTelephonyEventCapability, ett_h245_NoPTAudioTelephonyEventCapability, NoPTAudioTelephonyEventCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string AudioCapability_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "g711Alaw64k" },
+ { 2, "g711Alaw56k" },
+ { 3, "g711Ulaw64k" },
+ { 4, "g711Ulaw56k" },
+ { 5, "g722-64k" },
+ { 6, "g722-56k" },
+ { 7, "g722-48k" },
+ { 8, "g7231" },
+ { 9, "g728" },
+ { 10, "g729" },
+ { 11, "g729AnnexA" },
+ { 12, "is11172AudioCapability" },
+ { 13, "is13818AudioCapability" },
+ { 14, "g729wAnnexB" },
+ { 15, "g729AnnexAwAnnexB" },
+ { 16, "g7231AnnexCCapability" },
+ { 17, "gsmFullRate" },
+ { 18, "gsmHalfRate" },
+ { 19, "gsmEnhancedFullRate" },
+ { 20, "genericAudioCapability" },
+ { 21, "g729Extensions" },
+ { 22, "vbd" },
+ { 23, "audioTelephonyEvent" },
+ { 24, "audioTone" },
+ { 0, NULL }
+};
+static per_choice_t AudioCapability_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "g711Alaw64k", ASN1_EXTENSION_ROOT,
+ dissect_h245_g711Alaw64k },
+ { 2, "g711Alaw56k", ASN1_EXTENSION_ROOT,
+ dissect_h245_g711Alaw56k },
+ { 3, "g711Ulaw64k", ASN1_EXTENSION_ROOT,
+ dissect_h245_g711Ulaw64k },
+ { 4, "g711Ulaw56k", ASN1_EXTENSION_ROOT,
+ dissect_h245_g711Ulaw56k },
+ { 5, "g722-64k", ASN1_EXTENSION_ROOT,
+ dissect_h245_g722_64k },
+ { 6, "g722-56k", ASN1_EXTENSION_ROOT,
+ dissect_h245_g722_56k },
+ { 7, "g722-48k", ASN1_EXTENSION_ROOT,
+ dissect_h245_g722_48k },
+ { 8, "g7231", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioCapability_g7231 },
+ { 9, "g728", ASN1_EXTENSION_ROOT,
+ dissect_h245_g728 },
+ { 10, "g729", ASN1_EXTENSION_ROOT,
+ dissect_h245_g729 },
+ { 11, "g729AnnexA", ASN1_EXTENSION_ROOT,
+ dissect_h245_g729AnnexA },
+ { 12, "is11172AudioCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_IS11172AudioCapability },
+ { 13, "is13818AudioCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_IS13818AudioCapability },
+ { 14, "g729wAnnexB", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_g729wAnnexB },
+ { 15, "g729AnnexAwAnnexB", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_g729AnnexAwAnnexB },
+ { 16, "g7231AnnexCCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_G7231AnnexCCapability },
+ { 17, "gsmFullRate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GSMAudioCapability },
+ { 18, "gsmHalfRate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GSMAudioCapability },
+ { 19, "gsmEnhancedFullRate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GSMAudioCapability },
+ { 20, "genericAudioCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GenericCapability },
+ { 21, "g729Extensions", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_G729Extensions },
+ { 22, "vbd", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_VBDCapability },
+ { 23, "audioTelephonyEvent", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NoPTAudioTelephonyEventCapability },
+ { 24, "audioTone", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NoPTAudioToneCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_AudioCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_AudioCapability, ett_h245_AudioCapability, AudioCapability_choice, "AudioCapability", &value);
+
+ codec_type = val_to_str(value, AudioCapability_vals, "<unknown>");
+
+ return offset;
+}
+
+
+
+
+
+static const value_string H235Media_mediaType_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "videoData" },
+ { 2, "audioData" },
+ { 3, "data" },
+ { 0, NULL }
+};
+static per_choice_t H235Media_mediaType_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "videoData", ASN1_EXTENSION_ROOT,
+ dissect_h245_VideoCapability },
+ { 2, "audioData", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioCapability },
+ { 3, "data", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataApplicationCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H235Media_mediaType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H235Media_mediaType, ett_h245_H235Media_mediaType, H235Media_mediaType_choice, "mediaType", NULL);
+
+ return offset;
+}
+
+
+
+
+
+
+static const value_string CommunicationModeTableEntry_dataType_vals[] = {
+ { 0, "videoData" },
+ { 1, "audioData" },
+ { 2, "data" },
+ { 0, NULL }
+};
+static per_choice_t CommunicationModeTableEntry_dataType_choice[] = {
+ { 0, "videoData", ASN1_EXTENSION_ROOT,
+ dissect_h245_VideoCapability },
+ { 1, "audioData", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioCapability },
+ { 2, "data", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataApplicationCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_CommunicationModeTableEntry_dataType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_CommunicationModeTableEntry_dataType, ett_h245_CommunicationModeTableEntry_dataType, CommunicationModeTableEntry_dataType_choice, "dataType", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H235Media_sequence[] = {
+ { "encryptionAuthenticationAndIntegrity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_EncryptionAuthenticationAndIntegrity },
+ { "mediaType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H235Media_mediaType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H235Media(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H235Media, ett_h245_H235Media, H235Media_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_alphanumeric(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_GeneralString(tvb, offset, pinfo, tree, hf_h245_alphanumeric);
+ return offset;
+}
+
+
+
+
+
+
+static const value_string UserInputIndication_userInputSupportIndication_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "basicString" },
+ { 2, "iA5String" },
+ { 3, "generalString" },
+ { 0, NULL }
+};
+static per_choice_t UserInputIndication_userInputSupportIndication_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "basicString", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "iA5String", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "generalString", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_UserInputIndication_userInputSupportIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_UserInputIndication_userInputSupportIndication, ett_h245_UserInputIndication_userInputSupportIndication, UserInputIndication_userInputSupportIndication_choice, "userInputSupportIndication", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t UserInputIndication_extendedAlphanumeric_sequence[] = {
+ { "alphanumeric", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_alphanumeric },
+ { "rtpPayloadIndication", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NULL },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_UserInputIndication_extendedAlphanumeric(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_UserInputIndication_extendedAlphanumeric, ett_h245_UserInputIndication_extendedAlphanumeric, UserInputIndication_extendedAlphanumeric_sequence);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_rfcnumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_h245_rfc_number, 1, 32768,
+ NULL, NULL, TRUE);
+ return offset;
+}
+
+
+
+
+static const value_string RTPPayloadType_payloadDescriptor_vals[] = {
+ { 0, "nonStandardIdentifier" },
+ { 1, "rfc-number" },
+ { 2, "oid" },
+ { 0, NULL }
+};
+static per_choice_t RTPPayloadType_payloadDescriptor_choice[] = {
+ { 0, "nonStandardIdentifier", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "rfc-number", ASN1_EXTENSION_ROOT,
+ dissect_h245_rfcnumber },
+ { 2, "oid", ASN1_EXTENSION_ROOT,
+ dissect_h245_oid },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RTPPayloadType_payloadDescriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RTPPayloadType_payloadDescriptor, ett_h245_RTPPayloadType_payloadDescriptor, RTPPayloadType_payloadDescriptor_choice, "payloadDescriptor", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t RTPPayloadType_sequence[] = {
+ { "payloadDescriptor", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RTPPayloadType_payloadDescriptor },
+ { "payloadType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_payloadType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RTPPayloadType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RTPPayloadType, ett_h245_RTPPayloadType, RTPPayloadType_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+static const value_string H2250LogicalChannelParameters_mediaPacketization_vals[] = {
+ { 0, "h261aVideoPacketization" },
+ { 1, "rtpPayloadType" },
+ { 0, NULL }
+};
+static per_choice_t H2250LogicalChannelParameters_mediaPacketization_choice[] = {
+ { 0, "h261aVideoPacketization", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "rtpPayloadType", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_RTPPayloadType },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H2250LogicalChannelParameters_mediaPacketization(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H2250LogicalChannelParameters_mediaPacketization, ett_h245_H2250LogicalChannelParameters_mediaPacketization, H2250LogicalChannelParameters_mediaPacketization_choice, "mediaPacketization", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static int dissect_h245_mediaDistributionCapability_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static per_sequence_t MultipointCapability_sequence[] = {
+ { "multicastCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_multicastCapability },
+ { "multiUniCastConference", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_multiUniCastConference },
+ { "mediaDistributionCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_mediaDistributionCapability_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_receiveMultipointCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_receiveMultipointCapability, ett_h245_MultipointCapability, MultipointCapability_sequence);
+
+ return offset;
+}
+static int
+dissect_h245_transmitMultipointCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_transmitMultipointCapability, ett_h245_MultipointCapability, MultipointCapability_sequence);
+
+ return offset;
+}
+static int
+dissect_h245_receiveAndTransmitMultipointCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_receiveAndTransmitMultipointCapability, ett_h245_MultipointCapability, MultipointCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H2250Capability_sequence[] = {
+ { "maximumAudioDelayJitter", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_maximumAudioDelayJitter },
+ { "receiveMultipointCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_receiveMultipointCapability },
+ { "transmitMultipointCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_transmitMultipointCapability },
+ { "receiveAndTransmitMultipointCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_receiveAndTransmitMultipointCapability },
+ { "mcCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H2250Capability_mcCapability },
+ { "rtcpVideoControlCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_rtcpVideoControlCapability },
+ { "mediaPacketizationCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MediaPacketizationCapability },
+ { "transportCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_TransportCapability },
+ { "redundancyEncodingCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RedundancyEncodingCapability_sequence_of },
+ { "logicalChannelSwitchingCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_logicalChannelSwitchingCapability },
+ { "t120DynamicPortCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_t120DynamicPortCapability },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H2250Capability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H2250Capability, ett_h245_H2250Capability, H2250Capability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+static int dissect_h245_DataType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static per_sequence_t RedundancyEncodingElement_sequence[] = {
+ { "dataType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataType },
+ { "payloadType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_payloadType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncodingElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RedundancyEncodingElement, ett_h245_RedundancyEncodingElement, RedundancyEncodingElement_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t RedundancyEncoding_rtpRedundancyEncoding_sequence[] = {
+ { "primary", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RedundancyEncodingElement },
+ { "secondary", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_secondary_REE_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncoding_rtpRedundancyEncoding(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RedundancyEncoding_rtpRedundancyEncoding, ett_h245_RedundancyEncoding_rtpRedundancyEncoding, RedundancyEncoding_rtpRedundancyEncoding_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t RedundancyEncoding_sequence[] = {
+ { "redundancyEncodingMethod", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RedundancyEncodingMethod },
+ { "secondaryEncoding", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_DataType },
+ { "rtpRedundancyEncoding", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RedundancyEncoding_rtpRedundancyEncoding },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncoding(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RedundancyEncoding, ett_h245_RedundancyEncoding, RedundancyEncoding_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H2250LogicalChannelParameters_sequence[] = {
+ { "nonStandard", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_nonStandardData_sequence_of },
+ { "sessionID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sessionID_0_255 },
+ { "associatedSessionID", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_associatedSessionID },
+ { "mediaChannel", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaChannel },
+ { "mediaGuaranteedDelivery", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaGuaranteedDelivery },
+ { "mediaControlChannel", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaControlChannel },
+ { "mediaControlGuaranteedDelivery", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaControlGuaranteedDelivery },
+ { "silenceSuppression", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_silenceSuppression },
+ { "destination", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "dynamicRTPPayloadType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_dynamicRTPPayloadType },
+ { "mediaPacketization", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_H2250LogicalChannelParameters_mediaPacketization },
+ { "transportCapability", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_TransportCapability },
+ { "redundancyEncoding", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RedundancyEncoding },
+ { "source", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H2250LogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H2250LogicalChannelParameters, ett_h245_H2250LogicalChannelParameters, H2250LogicalChannelParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string forwardLogicalChannelParameters_multiplexParameters_vals[] = {
+ { 0, "h222LogicalChannelParameters" },
+ { 1, "h223LogicalChannelParameters" },
+ { 2, "v76LogicalChannelParameters" },
+ { 3, "h2250LogicalChannelParameters" },
+ { 4, "none" },
+ { 0, NULL }
+};
+static per_choice_t forwardLogicalChannelParameters_multiplexParameters_choice[] = {
+ { 0, "h222LogicalChannelParameters", ASN1_EXTENSION_ROOT,
+ dissect_h245_H222LogicalChannelParameters },
+ { 1, "h223LogicalChannelParameters", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223LogicalChannelParameters },
+ { 2, "v76LogicalChannelParameters", ASN1_EXTENSION_ROOT,
+ dissect_h245_V76LogicalChannelParameters },
+ { 3, "h2250LogicalChannelParameters", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H2250LogicalChannelParameters },
+ { 4, "none", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_forwardLogicalChannelParameters_multiplexParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_forwardLogicalChannelParameters_multiplexParameters, ett_h245_forwardLogicalChannelParameters_multiplexParameters, forwardLogicalChannelParameters_multiplexParameters_choice, "multiplexParameters", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t MultiplePayloadStreamElement_sequence[] = {
+ { "dataType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataType },
+ { "payloadType", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_payloadType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplePayloadStreamElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplePayloadStreamElement, ett_h245_MultiplePayloadStreamElement, MultiplePayloadStreamElement_sequence);
+
+ return offset;
+}
+
+
+
+static const value_string reverseLogicalChannelParameters_multiplexParameters_vals[] = {
+ { 0, "h223LogicalChannelParameters" },
+ { 1, "v76LogicalChannelParameters" },
+ { 2, "h2250LogicalChannelParameters" },
+ { 0, NULL }
+};
+static per_choice_t reverseLogicalChannelParameters_multiplexParameters_choice[] = {
+ { 0, "h223LogicalChannelParameters", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223LogicalChannelParameters },
+ { 1, "v76LogicalChannelParameters", ASN1_EXTENSION_ROOT,
+ dissect_h245_V76LogicalChannelParameters },
+ { 2, "h2250LogicalChannelParameters", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H2250LogicalChannelParameters },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_reverseLogicalChannelParameters_multiplexParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_reverseLogicalChannelParameters_multiplexParameters, ett_h245_reverseLogicalChannelParameters_multiplexParameters, reverseLogicalChannelParameters_multiplexParameters_choice, "multiplexParameters", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_vals[] = {
+ { 0, "h222LogicalChannelParameters" },
+ { 1, "h2250LogicalChannelParameters" },
+ { 0, NULL }
+};
+static per_choice_t OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_choice[] = {
+ { 0, "h222LogicalChannelParameters", ASN1_EXTENSION_ROOT,
+ dissect_h245_H222LogicalChannelParameters },
+ { 1, "h2250LogicalChannelParameters", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H2250LogicalChannelParameters },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters, ett_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters, OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_choice, "multiplexParameters", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t forwardLogicalChannelParameters_sequence[] = {
+ { "portNumber", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_portNumber },
+ { "dataType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataType },
+ { "multiplexParameters", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_forwardLogicalChannelParameters_multiplexParameters },
+ { "forwardLogicalChannelDependency", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "replacementFor", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_forwardLogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_forwardLogicalChannelParameters, ett_h245_forwardLogicalChannelParameters, forwardLogicalChannelParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t reverseLogicalChannelParameters_sequence[] = {
+ { "dataType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DataType },
+ { "multiplexParameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_reverseLogicalChannelParameters_multiplexParameters },
+ { "reverseLogicalChannelDependency", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "replacementFor", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_reverseLogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_reverseLogicalChannelParameters, ett_h245_reverseLogicalChannelParameters, reverseLogicalChannelParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t OpenLogicalChannelAck_reverseLogicalChannelParameters_sequence[] = {
+ { "reverseLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "portNumber", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_portNumber },
+ { "multiplexParameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters },
+ { "replacementFor", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters, ett_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters, OpenLogicalChannelAck_reverseLogicalChannelParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_VCCapability_set_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_set_of(tvb, offset, pinfo, tree, hf_h245_VCCapability_set_of, ett_h245_VCCapability_set_of, dissect_h245_VCCapability);
+ return offset;
+}
+
+
+
+
+static per_sequence_t H222Capability_sequence[] = {
+ { "numberOfVCs", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_numberOfVCs },
+ { "vcCapability", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_VCCapability_set_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H222Capability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H222Capability, ett_h245_H222Capability, H222Capability_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string MultiplexFormat_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "h222Capability" },
+ { 2, "h223Capability" },
+ { 0, NULL }
+};
+static per_choice_t MultiplexFormat_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "h222Capability", ASN1_EXTENSION_ROOT,
+ dissect_h245_H222Capability },
+ { 2, "h223Capability", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223Capability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultiplexFormat(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultiplexFormat, ett_h245_MultiplexFormat, MultiplexFormat_choice, "MultiplexFormat", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultiplexedStreamCapability_sequence[] = {
+ { "multiplexFormat", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultiplexFormat },
+ { "controlOnMuxStream", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_controlOnMuxStream },
+ { "capabilityOnMuxStream", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_capabilityOnMuxStream },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexedStreamCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexedStreamCapability, ett_h245_MultiplexedStreamCapability, MultiplexedStreamCapability_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string Capability_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "receiveVideoCapability" },
+ { 2, "transmitVideoCapability" },
+ { 3, "receiveAndTransmitVideoCapability" },
+ { 4, "receiveAudioCapability" },
+ { 5, "transmitAudioCapability" },
+ { 6, "receiveAndTransmitAudioCapability" },
+ { 7, "receiveDataApplicationCapability" },
+ { 8, "transmitDataApplicationCapability" },
+ { 9, "receiveAndTransmitDataApplicationCapability" },
+ { 10, "h233EncryptionTransmitCapability" },
+ { 11, "h233EncryptionReceiveCapability" },
+ { 12, "conferenceCapability" },
+ { 13, "h235SecurityCapability" },
+ { 14, "maxPendingReplacementFor" },
+ { 15, "receiveUserInputCapability" },
+ { 16, "transmitUserInputCapability" },
+ { 17, "receiveAndTransmitUserInputCapability" },
+ { 18, "genericControlCapability" },
+ { 19, "receiveMultiplexedStreamCapability" },
+ { 20, "transmitMultiplexedStreamCapability" },
+ { 21, "receiveAndTransmitMultiplexedStreamCapability" },
+ { 22, "receiveRTPAudioTelephonyEventCapability" },
+ { 23, "receiveRTPAudioToneCapability" },
+ { 24, "fecCapability" },
+ { 25, "multiplePayloadStreamCapability" },
+ { 0, NULL }
+};
+static per_choice_t Capability_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "receiveVideoCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_VideoCapability },
+ { 2, "transmitVideoCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_VideoCapability },
+ { 3, "receiveAndTransmitVideoCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_VideoCapability },
+ { 4, "receiveAudioCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioCapability },
+ { 5, "transmitAudioCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioCapability },
+ { 6, "receiveAndTransmitAudioCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioCapability },
+ { 7, "receiveDataApplicationCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataApplicationCapability },
+ { 8, "transmitDataApplicationCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataApplicationCapability },
+ { 9, "receiveAndTransmitDataApplicationCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataApplicationCapability },
+ { 10, "h233EncryptionTransmitCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_h233EncryptionTransmitCapability },
+ { 11, "h233EncryptionReceiveCapability", ASN1_EXTENSION_ROOT,
+ dissect_h245_Capability_h233EncryptionReceiveCapability },
+ { 12, "conferenceCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceCapability },
+ { 13, "h235SecurityCapability" , ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H235SecurityCapability },
+ { 14, "maxPendingReplacementFor", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_maxPendingReplacementFor },
+ { 15, "receiveUserInputCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_UserInputCapability },
+ { 16, "transmitUserInputCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_UserInputCapability },
+ { 17, "receiveAndTransmitUserInputCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_UserInputCapability },
+ { 18, "genericControlCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GenericCapability },
+ { 19, "receiveMultiplexedStreamCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultiplexedStreamCapability },
+ { 20, "transmitMultiplexedStreamCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultiplexedStreamCapability },
+ { 21, "receiveAndTransmitMultiplexedStreamCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultiplexedStreamCapability },
+ { 22, "receiveRTPAudioTelephonyEventCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_AudioTelephonyEventCapability },
+ { 23, "receiveRTPAudioToneCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_AudioToneCapability },
+ { 24, "fecCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_FECCapability },
+ { 25, "multiplePayloadStreamCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultiplePayloadStreamCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_Capability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_Capability, ett_h245_Capability, Capability_choice, "Capability", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t CapabilityTableEntry_sequence[] = {
+ { "capabilityTableEntryNumber", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_CapabilityTableEntryNumber },
+ { "capability", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h245_Capability },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CapabilityTableEntry(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CapabilityTableEntry, ett_h245_CapabilityTableEntry, CapabilityTableEntry_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultiplexedStreamParameter_sequence[] = {
+ { "multiplexFormat", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_MultiplexFormat },
+ { "controlOnMuxStream", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_controlOnMuxStream },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplexedStreamParameter(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplexedStreamParameter, ett_h245_MultiplexedStreamParameter, MultiplexedStreamParameter_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string DataType_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "nullData" },
+ { 2, "videoData" },
+ { 3, "audioData" },
+ { 4, "data" },
+ { 5, "encryptionData" },
+ { 6, "h235Control" },
+ { 7, "h235Media" },
+ { 8, "multiplexedStream" },
+ { 9, "redundancyEncoding" },
+ { 10, "multiplePayloadStream" },
+ { 11, "fec" },
+ { 0, NULL }
+};
+static per_choice_t DataType_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "nullData", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "videoData", ASN1_EXTENSION_ROOT,
+ dissect_h245_VideoCapability },
+ { 3, "audioData", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioCapability },
+ { 4, "data", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataApplicationCapability },
+ { 5, "encryptionData", ASN1_EXTENSION_ROOT,
+ dissect_h245_EncryptionMode },
+ { 6, "h235Control", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 7, "h235Media", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H235Media },
+ { 8, "multiplexedStream", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultiplexedStreamParameter },
+ { 9, "redundancyEncoding", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_RedundancyEncoding },
+ { 10, "multiplePayloadStream", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultiplePayloadStream },
+ { 11, "fec", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_FECData },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_DataType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_DataType, ett_h245_DataType, DataType_choice, "DataType", NULL);
+
+ return offset;
+}
+
+
+
+
+static int dissect_h245_VBDMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static const value_string AudioMode_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "g711Alaw64k" },
+ { 2, "g711Alaw56k" },
+ { 3, "g711Ulaw64k" },
+ { 4, "g711Ulaw56k" },
+ { 5, "g722-64k" },
+ { 6, "g722-56k" },
+ { 7, "g722-48k" },
+ { 8, "g728" },
+ { 9, "g729" },
+ { 10, "g729AnnexA" },
+ { 11, "g7231" },
+ { 12, "is11172AudioMode" },
+ { 13, "is13818AudioMode" },
+ { 14, "g729wAnnexB" },
+ { 15, "g729AnnexAwAnnexB" },
+ { 16, "g7231AnnexCMode" },
+ { 17, "gsmFullRate" },
+ { 18, "gsmHalfRate" },
+ { 19, "gsmEnhancedFullRate" },
+ { 20, "genericAudioMode" },
+ { 21, "g729Extensions" },
+ { 22, "vbd" },
+ { 0, NULL }
+};
+static per_choice_t AudioMode_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "g711Alaw64k", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 2, "g711Alaw56k", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 3, "g711Ulaw64k", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 4, "g711Ulaw56k", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 5, "g722-64k", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "g722-56k", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "g722-48k", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 8, "g728", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 9, "g729", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 10, "g729AnnexA", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 11, "g7231", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioMode_g7231 },
+ { 12, "is11172AudioMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_IS11172AudioMode },
+ { 13, "is13818AudioMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_IS13818AudioMode },
+ { 14, "g729wAnnexB", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_g729wAnnexB },
+ { 15, "g729AnnexAwAnnexB", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_g729AnnexAwAnnexB },
+ { 16, "g7231AnnexCMode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_G7231AnnexCMode },
+ { 17, "gsmFullRate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GSMAudioCapability },
+ { 18, "gsmHalfRate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GSMAudioCapability },
+ { 19, "gsmEnhancedFullRate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GSMAudioCapability },
+ { 20, "genericAudioMode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GenericCapability },
+ { 21, "g729Extensions", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_G729Extensions },
+ { 22, "vbd", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_VBDMode },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_AudioMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_AudioMode, ett_h245_AudioMode, AudioMode_choice, "AudioMode", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string RedundancyEncodingMode_secondaryEncoding_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "audioData" },
+ { 0, NULL }
+};
+static per_choice_t RedundancyEncodingMode_secondaryEncoding_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "audioData", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioMode },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncodingMode_secondaryEncoding(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RedundancyEncodingMode_secondaryEncoding, ett_h245_RedundancyEncodingMode_secondaryEncoding, RedundancyEncodingMode_secondaryEncoding_choice, "secondaryEncoding", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t RedundancyEncodingMode_sequence[] = {
+ { "redundancyEncodingMethod", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RedundancyEncodingMethod },
+ { "secondaryEncoding", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RedundancyEncodingMode_secondaryEncoding },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncodingMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RedundancyEncodingMode, ett_h245_RedundancyEncodingMode, RedundancyEncodingMode_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t H2250ModeParameters_sequence[] = {
+ { "redundancyEncodingMode", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RedundancyEncodingMode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H2250ModeParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H2250ModeParameters, ett_h245_H2250ModeParameters, H2250ModeParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t VBDMode_sequence[] = {
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_AudioMode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_VBDMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_VBDMode, ett_h245_VBDMode, VBDMode_sequence);
+
+ return offset;
+}
+
+
+
+static const value_string MultiplexCapability_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "h222Capability" },
+ { 2, "h223Capability" },
+ { 3, "v76Capability" },
+ { 4, "h2250Capability" },
+ { 5, "genericMultiplexCapability" },
+ { 0, NULL }
+};
+static per_choice_t MultiplexCapability_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "h222Capability", ASN1_EXTENSION_ROOT,
+ dissect_h245_H222Capability },
+ { 2, "h223Capability", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223Capability },
+ { 3, "v76Capability", ASN1_EXTENSION_ROOT,
+ dissect_h245_V76Capability },
+ { 4, "h2250Capability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H2250Capability },
+ { 5, "genericMultiplexCapability", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GenericCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_MultiplexCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_MultiplexCapability, ett_h245_MultiplexCapability, MultiplexCapability_choice, "MultiplexCapability", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t TerminalCapabilitySet_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "protocolIdentifier", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_protocolIdentifier },
+ { "multiplexCapability", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_MultiplexCapability },
+ { "capabilityTable", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_capabilityTable },
+ { "capabilityDescriptors", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_capabilityDescriptors },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_TerminalCapabilitySet(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySet, ett_h245_TerminalCapabilitySet, TerminalCapabilitySet_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+static per_sequence_t ConferenceResponse_terminalIDResponse_sequence[] = {
+ { "terminalLabel", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "terminalID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_TerminalID },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse_terminalIDResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse_terminalIDResponse, ett_h245_ConferenceResponse_terminalIDResponse, ConferenceResponse_terminalIDResponse_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string ConferenceResponse_vals[] = {
+ { 0, "mCTerminalIDResponse" },
+ { 1, "terminalIDResponse" },
+ { 2, "conferenceIDResponse" },
+ { 3, "passwordResponse" },
+ { 4, "terminalListResponse" },
+ { 5, "videoCommandReject" },
+ { 6, "terminalDropReject" },
+ { 7, "makeMeChairResponse" },
+ { 8, "extensionAddressResponse" },
+ { 9, "chairTokenOwnerResponse" },
+ { 10, "terminalCertificateResponse" },
+ { 11, "broadcastMyLogicalChannelResponse" },
+ { 12, "makeTerminalBroadcasterResponse" },
+ { 13, "sendThisSourceResponse" },
+ { 14, "requestAllTerminalIDsResponse" },
+ { 15, "remoteMCResponse" },
+ { 0, NULL }
+};
+static per_choice_t ConferenceResponse_choice[] = {
+ { 0, "mCTerminalIDResponse", ASN1_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_mCterminalIDResponse },
+ { 1, "terminalIDResponse", ASN1_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_terminalIDResponse },
+ { 2, "conferenceIDResponse", ASN1_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_conferenceIDResponse },
+ { 3, "passwordResponse", ASN1_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_passwordResponse },
+ { 4, "terminalListResponse", ASN1_EXTENSION_ROOT,
+ dissect_h245_terminalListResponse },
+ { 5, "videoCommandReject", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 6, "terminalDropReject", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 7, "makeMeChairResponse", ASN1_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_makeMeChairResponse },
+ { 8, "extensionAddressResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_extensionAddressResponse },
+ { 9, "chairTokenOwnerResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_chairTokenOwnerResponse },
+ { 10, "terminalCertificateResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_terminalCertificateResponse },
+ { 11, "broadcastMyLogicalChannelResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_broadcastMyLogicalChannelResponse },
+ { 12, "makeTerminalBroadcasterResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_makeTerminalBroadcasterResponse },
+ { 13, "sendThisSourceResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse_sendThisSourceResponse },
+ { 14, "requestAllTerminalIDsResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_RequestAllTerminalIDsResponse },
+ { 15, "remoteMCResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_RemoteMCResponse },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ConferenceResponse(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ConferenceResponse, ett_h245_ConferenceResponse, ConferenceResponse_choice, "ConferenceResponse", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string H261VideoMode_resolution_vals[] = {
+ { 0, "qcif" },
+ { 1, "cif" },
+ { 0, NULL }
+};
+static per_choice_t H261VideoMode_resolution_choice[] = {
+ { 0, "qcif", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 1, "cif", ASN1_NO_EXTENSIONS,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H261VideoMode_resolution(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H261VideoMode_resolution, ett_h245_H261VideoMode_resolution, H261VideoMode_resolution_choice, "resolution", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H261VideoMode_sequence[] = {
+ { "resolution", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H261VideoMode_resolution },
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_h223bitRate },
+ { "stillImageTransmission", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_stillImageTransmission },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H261VideoMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H261VideoMode, ett_h245_H261VideoMode, H261VideoMode_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string VideoMode_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "h261VideoMode" },
+ { 2, "h262VideoMode" },
+ { 3, "h263VideoMode" },
+ { 4, "is11172VideoMode" },
+ { 5, "genericVideoMode" },
+ { 0, NULL }
+};
+static per_choice_t VideoMode_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "h261VideoMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_H261VideoMode },
+ { 2, "h262VideoMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_H262VideoMode },
+ { 3, "h263VideoMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_H263VideoMode },
+ { 4, "is11172VideoMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_IS11172VideoMode},
+ { 5, "genericVideoMode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_GenericCapability },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_VideoMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_VideoMode, ett_h245_VideoMode, VideoMode_choice, "VideoMode", NULL);
+
+ return offset;
+}
+
+
+
+
+static const value_string H235Mode_mediaMode_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "videoMode" },
+ { 2, "audioMode" },
+ { 3, "dataMode" },
+ { 0, NULL }
+};
+static per_choice_t H235Mode_mediaMode_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "videoMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_VideoMode },
+ { 2, "audioMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioMode },
+ { 3, "dataMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataMode },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_H235Mode_mediaMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_H235Mode_mediaMode, ett_h245_H235Mode_mediaMode, H235Mode_mediaMode_choice, "mediaMode", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t H235Mode_sequence[] = {
+ { "encryptionAuthenticationAndIntegrity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_EncryptionAuthenticationAndIntegrity },
+ { "mediaMode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H235Mode_mediaMode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H235Mode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H235Mode, ett_h245_H235Mode, H235Mode_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string RedundancyEncodingDTModeElement_type_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "videoMode" },
+ { 2, "audioMode" },
+ { 3, "dataMode" },
+ { 4, "encryptionMode" },
+ { 5, "h235Mode" },
+ { 0, NULL }
+};
+static per_choice_t RedundancyEncodingDTModeElement_type_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "videoMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_VideoMode },
+ { 2, "audioMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioMode },
+ { 3, "dataMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataMode },
+ { 4, "encryptionMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_EncryptionMode },
+ { 5, "h235Mode", ASN1_EXTENSION_ROOT,
+ dissect_h245_H235Mode },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncodingDTModeElement_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RedundancyEncodingDTModeElement_type, ett_h245_RedundancyEncodingDTModeElement_type, RedundancyEncodingDTModeElement_type_choice, "type", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RedundancyEncodingDTModeElement_sequence[] = {
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RedundancyEncodingDTModeElement_type },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncodingDTModeElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RedundancyEncodingDTModeElement, ett_h245_RedundancyEncodingDTModeElement, RedundancyEncodingDTModeElement_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t RedundancyEncodingDTMode_sequence[] = {
+ { "redundancyEncodingMethod", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RedundancyEncodingMethod },
+ { "primary", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RedundancyEncodingDTModeElement },
+ { "secondary", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_secondary_REDTME_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RedundancyEncodingDTMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RedundancyEncodingDTMode, ett_h245_RedundancyEncodingDTMode, RedundancyEncodingDTMode_sequence);
+
+ return offset;
+}
+
+
+
+
+static int dissect_h245_FECMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static const value_string ModeElementType_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "videoMode" },
+ { 2, "audioMode" },
+ { 3, "dataMode" },
+ { 4, "encryptionMode" },
+ { 5, "h235Mode" },
+ { 6, "multiplexedStreamMode" },
+ { 7, "redundancyEncodingDTMode" },
+ { 8, "multiplePayloadStreamMode" },
+ { 9, "fecMode" },
+ { 0, NULL }
+};
+static per_choice_t ModeElementType_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "videoMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_VideoMode },
+ { 2, "audioMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_AudioMode },
+ { 3, "dataMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_DataMode },
+ { 4, "encryptionMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_EncryptionMode },
+ { 5, "h235Mode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H235Mode },
+ { 6, "multiplexedStreamMode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultiplexedStreamParameter },
+ { 7, "redundancyEncodingDTMode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_RedundancyEncodingDTMode },
+ { 8, "multiplePayloadStreamMode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultiplePayloadStreamMode },
+ { 9, "fecMode", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_FECMode },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ModeElementType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ModeElementType, ett_h245_ModeElementType, ModeElementType_choice, "ModeElementType", NULL);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t MultiplePayloadStreamElementMode_sequence[] = {
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ModeElementType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MultiplePayloadStreamElementMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MultiplePayloadStreamElementMode, ett_h245_MultiplePayloadStreamElementMode, MultiplePayloadStreamElementMode_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t FECMode_rfc2733Mode_mode_separateStream_samePort_sequence[] = {
+ { "protectedType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ModeElementType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FECMode_rfc2733Mode_mode_separateStream_samePort(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FECMode_rfc2733Mode_mode_separateStream_samePort, ett_h245_FECMode_rfc2733Mode_mode_separateStream_samePort, FECMode_rfc2733Mode_mode_separateStream_samePort_sequence);
+
+ return offset;
+}
+
+
+
+static const value_string FECMode_rfc2733Mode_mode_separateStream_vals[] = {
+ { 0, "differentPort" },
+ { 1, "samePort" },
+ { 0, NULL }
+};
+static per_choice_t FECMode_rfc2733Mode_mode_separateStream_choice[] = {
+ { 0, "differentPort", ASN1_EXTENSION_ROOT,
+ dissect_h245_FECMode_rfc2733Mode_mode_separateStream_differentPort },
+ { 1, "samePort", ASN1_EXTENSION_ROOT,
+ dissect_h245_FECMode_rfc2733Mode_mode_separateStream_samePort },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FECMode_rfc2733Mode_mode_separateStream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FECMode_rfc2733Mode_mode_separateStream, ett_h245_FECMode_rfc2733Mode_mode_separateStream, FECMode_rfc2733Mode_mode_separateStream_choice, "separateStream", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static const value_string FECMode_rfc2733Mode_mode_vals[] = {
+ { 0, "redundancyEncoding" },
+ { 1, "separateStream" },
+ { 0, NULL }
+};
+static per_choice_t FECMode_rfc2733Mode_mode_choice[] = {
+ { 0, "redundancyEncoding", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "separateStream", ASN1_EXTENSION_ROOT,
+ dissect_h245_FECMode_rfc2733Mode_mode_separateStream },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FECMode_rfc2733Mode_mode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FECMode_rfc2733Mode_mode, ett_h245_FECMode_rfc2733Mode_mode, FECMode_rfc2733Mode_mode_choice, "mode", NULL);
+
+ return offset;
+}
+
+
+
+static per_sequence_t FECMode_rfc2733Mode_sequence[] = {
+ { "mode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_FECMode_rfc2733Mode_mode },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_FECMode_rfc2733Mode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_FECMode_rfc2733Mode, ett_h245_FECMode_rfc2733Mode, FECMode_rfc2733Mode_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string FECMode_vals[] = {
+ { 0, "rfc2733Mode" },
+ { 0, NULL }
+};
+static per_choice_t FECMode_choice[] = {
+ { 0, "rfc2733Mode", ASN1_EXTENSION_ROOT,
+ dissect_h245_FECMode_rfc2733Mode },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FECMode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FECMode, ett_h245_FECMode, FECMode_choice, "FECMode", NULL);
+
+ return offset;
+}
+
+
+
+
+static int dissect_h245_RequestMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int dissect_h245_ResponseMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int dissect_h245_CommandMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static const value_string FunctionNotUnderstood_vals[] = {
+ { 0, "request" },
+ { 1, "response" },
+ { 2, "command" },
+ { 0, NULL }
+};
+static per_choice_t FunctionNotUnderstood_choice[] = {
+ { 0, "request", ASN1_NO_EXTENSIONS,
+ dissect_h245_RequestMessage },
+ { 1, "response", ASN1_NO_EXTENSIONS,
+ dissect_h245_ResponseMessage },
+ { 2, "command", ASN1_NO_EXTENSIONS,
+ dissect_h245_CommandMessage },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_FunctionNotUnderstood(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_FunctionNotUnderstood, ett_h245_FunctionNotUnderstood, FunctionNotUnderstood_choice, "FunctionNotUnderstood", NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_signalType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* XXX this is just wrong.
+ * the definition in the ASN.1 file is :
+ * signalType IA5String (SIZE (1) ^ FROM ("0123456789#*ABCD!"))
+ * which means the 17 characters are encoded as 8-bit values
+ * between 0x00 and 0x10
+ *
+ * however, captures from real world applications show that
+ * the field is encoded instead as :
+ * signalType IA5String (SIZE (1))
+ * ie a single character ascii value from 0x00 to 0xff.
+ *
+ * the code is changed under protest.
+ * i still think it is the one commented out that is the correct one
+ */
+ /*offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h245_signalType, 1, 1, "!#*0123456789ABCD", 17);*/
+
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h245_signalType, 1, 1);
+
+
+ return offset;
+}
+
+
+
+
+
+
+
+static per_sequence_t UserInputIndication_signal_sequence[] = {
+ { "signalType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_signalType },
+ { "duration", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_duration },
+ { "rtp", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_UserInputIndication_signal_rtp },
+ { "rtpPayloadIndication", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NULL },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_UserInputIndication_signal(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_UserInputIndication_signal, ett_h245_UserInputIndication_signal, UserInputIndication_signal_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string UserInputIndication_vals[] = {
+ { 0, "nonStandard" },
+ { 1, "alphanumeric" },
+ { 2, "userInputSupportIndication" },
+ { 3, "signal" },
+ { 4, "signalUpdate" },
+ { 5, "extendedAlphanumeric" },
+ { 0, NULL }
+};
+static per_choice_t UserInputIndication_choice[] = {
+ { 0, "nonStandard", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardParameter },
+ { 1, "alphanumeric", ASN1_EXTENSION_ROOT,
+ dissect_h245_alphanumeric },
+ { 2, "userInputSupportIndication", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_UserInputIndication_userInputSupportIndication },
+ { 3, "signal", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_UserInputIndication_signal },
+ { 4, "signalUpdate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_UserInputIndication_signalUpdate },
+ { 5, "extendedAlphanumeric", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_UserInputIndication_extendedAlphanumeric },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_UserInputIndication(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_UserInputIndication, ett_h245_UserInputIndication, UserInputIndication_choice, "UserInputIndication", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t TerminalCapabilitySetRelease_sequence[] = {
+ { NULL, ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL, NULL }
+};
+static int
+dissect_h245_TerminalCapabilitySetRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_TerminalCapabilitySetRelease, ett_h245_TerminalCapabilitySetRelease, TerminalCapabilitySetRelease_sequence);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_internationalNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_NumericString(tvb, offset, pinfo, tree, hf_h245_internationalNumber, 1, 16);
+ return offset;
+}
+
+
+
+
+
+static const value_string Q2931Address_address_vals[] = {
+ { 0, "internationalNumber" },
+ { 1, "nsapAddress" },
+ { 0, NULL }
+};
+static per_choice_t Q2931Address_address_choice[] = {
+ { 0, "internationalNumber", ASN1_EXTENSION_ROOT,
+ dissect_h245_internationalNumber },
+ { 1, "nsapAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_nsapAddress},
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_Q2931Address_address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_Q2931Address_address, ett_h245_Q2931Address_address, Q2931Address_address_choice, "address", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t Q2931Address_sequence[] = {
+ { "address", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_Q2931Address_address },
+ { "subaddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_subaddress_1_20 },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_Q2931Address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_Q2931Address, ett_h245_Q2931Address, Q2931Address_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_e164Address(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_h245_e164Address, 1, 128, "#*,0123456789", 13);
+
+ return offset;
+}
+
+
+
+
+static const value_string NetworkAccessParameters_networkAddress_vals[] = {
+ { 0, "q2931Address" },
+ { 1, "e164Address" },
+ { 2, "localAreaAddress" },
+ { 0, NULL }
+};
+static per_choice_t NetworkAccessParameters_networkAddress_choice[] = {
+ { 0, "q2931Address", ASN1_EXTENSION_ROOT,
+ dissect_h245_Q2931Address },
+ { 1, "e164Address", ASN1_EXTENSION_ROOT,
+ dissect_h245_e164Address },
+ { 2, "localAreaAddress", ASN1_EXTENSION_ROOT,
+ dissect_h245_localAreaAddress },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_NetworkAccessParameters_networkAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_NetworkAccessParameters_networkAddress, ett_h245_NetworkAccessParameters_networkAddress, NetworkAccessParameters_networkAddress_choice, "networkAddress", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t NetworkAccessParameters_sequence[] = {
+ { "distribution", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NetworkAccessParameters_distribution },
+ { "networkAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NetworkAccessParameters_networkAddress },
+ { "associateConference", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_associateConference},
+ { "externalReference", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_externalReference },
+ { "t120SetupProcedure", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NetworkAccessParameters_t120SetupProcedure },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NetworkAccessParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NetworkAccessParameters, ett_h245_NetworkAccessParameters, NetworkAccessParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t OpenLogicalChannel_sequence[] = {
+ { "forwardLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "forwardLogicalChannelParameters", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_forwardLogicalChannelParameters },
+ { "reverseLogicalChannelParameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_reverseLogicalChannelParameters },
+ { "separateStack", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NetworkAccessParameters },
+ { "encryptionSync", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_EncryptionSync },
+ { NULL, 0, 0, NULL }
+};
+int
+dissect_h245_OpenLogicalChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannel, ett_h245_OpenLogicalChannel, OpenLogicalChannel_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t OpenLogicalChannelAck_sequence[] = {
+ { "forwardLogicalChannelNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_LogicalChannelNumber },
+ { "reverseLogicalChannelParameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters },
+ { "separateStack", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_NetworkAccessParameters },
+ { "forwardMultiplexAckParameters", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_forwardMultiplexAckParameters},
+ { "encryptionSync", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_EncryptionSync},
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_OpenLogicalChannelAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_OpenLogicalChannelAck, ett_h245_OpenLogicalChannelAck, OpenLogicalChannelAck_sequence);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_escrowValue(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+PER_NOT_DECODED_YET("escrowValue");
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t EscrowData_sequence[] = {
+ { "escrowID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_escrowID },
+ { "escrowValue", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_escrowValue },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_EscrowData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_EscrowData, ett_h245_EscrowData, EscrowData_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+
+
+
+static const value_string RequestModeAck_response_decision_vals[] = {
+ { 0, "willTransmitMostPreferredMode" },
+ { 1, "willTransmitLessPreferredMode" },
+ { 0, NULL }
+};
+static per_choice_t RequestModeAck_response_decision_choice[] = {
+ { 0, "willTransmitMostPreferredMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 1, "willTransmitLessPreferredMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RequestModeAck_response_decision(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RequestModeAck_response_decision, ett_h245_RequestModeAck_response_decision, RequestModeAck_response_decision_choice, "decision", NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t RequestModeAck_sequence[] = {
+ { "sequenceNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_SequenceNumber },
+ { "response", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_RequestModeAck_response_decision },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_RequestModeAck(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestModeAck, ett_h245_RequestModeAck, RequestModeAck_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t RequestModeRelease_sequence[] = {
+ { NULL, ASN1_EXTENSION_ROOT, 0, NULL }
+};
+static int
+dissect_h245_RequestModeRelease(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_RequestModeRelease, ett_h245_RequestModeRelease, RequestModeRelease_sequence);
+
+ return offset;
+}
+
+
+
+static per_sequence_t MaintenanceLoopOffCommand_sequence[] = {
+ { NULL, ASN1_EXTENSION_ROOT, 0, NULL }
+};
+static int
+dissect_h245_MaintenanceLoopOffCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MaintenanceLoopOffCommand, ett_h245_MaintenanceLoopOffCommand, MaintenanceLoopOffCommand_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t CommunicationModeRequest_sequence[] = {
+ { NULL, ASN1_EXTENSION_ROOT, 0, NULL }
+};
+static int
+dissect_h245_CommunicationModeRequest(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CommunicationModeRequest, ett_h245_CommunicationModeRequest, CommunicationModeRequest_sequence);
+
+ return offset;
+}
+
+
+
+
+static const value_string IndicationMessage_short_vals[] = {
+ { 0, "NSM" },
+ { 1, "FNU" },
+ { 2, "MSDRelease" },
+ { 3, "TCSRelease" },
+ { 4, "OLCConfirm" },
+ { 5, "RCCRelease" },
+ { 6, "MESRelease" },
+ { 7, "RMERelease" },
+ { 8, "RMRelease" },
+ { 9, "MI" },
+ { 10, "JI" },
+ { 11, "H223SI" },
+ { 12, "NATMVCI" },
+ { 13, "UII" },
+ { 14, "H2250MSI" },
+ { 15, "MCLI" },
+ { 16, "CI" },
+ { 17, "VI" },
+ { 18, "FNS" },
+ { 19, "MultilinkIndication" },
+ { 20, "LCRRelease" },
+ { 21, "FCIndication" },
+ { 22, "MMRI" },
+ { 0, NULL }
+};
+
+
+static const value_string IndicationMessage_vals[] = {
+ { 0, "NonStandardMessage" },
+ { 1, "FunctionNotUnderstood" },
+ { 2, "MasterSlaveDeterminationRelease" },
+ { 3, "TerminalCapabilitySetRelease" },
+ { 4, "OpenLogicalChannelConfirm" },
+ { 5, "RequestChannelCloseRelease" },
+ { 6, "MultiplexEntrySendRelease" },
+ { 7, "RequestMultiplexEntryRelease" },
+ { 8, "RequestModeRelease" },
+ { 9, "MiscellaneousIndication" },
+ { 10, "JitterIndication" },
+ { 11, "H223SkewIndication" },
+ { 12, "NewATMVCIndication" },
+ { 13, "UserInputIndication" },
+ { 14, "H2250MaximumSkewIndication" },
+ { 15, "MCLocationIndication" },
+ { 16, "ConferenceIndication" },
+ { 17, "VendorIdentification" },
+ { 18, "FunctionNotSupported" },
+ { 19, "MultilinkIndication" },
+ { 20, "LogicalChannelRateRelease" },
+ { 21, "FlowControlIndication" },
+ { 22, "MobileMultilinkReconfigurationIndication" },
+ { 0, NULL }
+};
+static per_choice_t IndicationMessage_choice[] = {
+ { 0, "NonStandardMessage", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardMessage },
+ { 1, "FunctionNotUnderstood", ASN1_EXTENSION_ROOT,
+ dissect_h245_FunctionNotUnderstood },
+ { 2, "MasterSlaveDeterminationRelease", ASN1_EXTENSION_ROOT,
+ dissect_h245_MasterSlaveDeterminationRelease },
+ { 3, "TerminalCapabilitySetRelease", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalCapabilitySetRelease },
+ { 4, "OpenLogicalChannelConfirm", ASN1_EXTENSION_ROOT,
+ dissect_h245_OpenLogicalChannelConfirm },
+ { 5, "RequestChannelCloseRelease", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestChannelCloseRelease },
+ { 6, "MultiplexEntrySendRelease", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultiplexEntrySendRelease },
+ { 7, "RequestMultiplexEntryRelease", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestMultiplexEntryRelease },
+ { 8, "RequestModeRelease", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestModeRelease },
+ { 9, "MiscellaneousIndication", ASN1_EXTENSION_ROOT,
+ dissect_h245_MiscellaneousIndication },
+ { 10, "JitterIndication", ASN1_EXTENSION_ROOT,
+ dissect_h245_JitterIndication },
+ { 11, "H223SkewIndication", ASN1_EXTENSION_ROOT,
+ dissect_h245_H223SkewIndication },
+ { 12, "NewATMVCIndication", ASN1_EXTENSION_ROOT,
+ dissect_h245_NewATMVCIndication },
+ { 13, "UserInputIndication", ASN1_EXTENSION_ROOT,
+ dissect_h245_UserInputIndication },
+ { 14, "H2250MaximumSkewIndication", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H2250MaximumSkewIndication },
+ { 15, "MCLocationIndication", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MCLocationIndication },
+ { 16, "ConferenceIndication", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceIndication },
+ { 17, "VendorIdentification", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_VendorIdentification },
+ { 18, "FunctionNotSupported", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_FunctionNotSupported },
+ { 19, "MultilinkIndication", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultilinkIndication },
+ { 20, "LogicalChannelRateRelease", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelRateRelease },
+ { 21, "FlowControlIndication", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_FlowControlIndication },
+ { 22, "MobileMultilinkReconfigurationIndication",ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MobileMultilinkReconfigurationIndication },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_IndicationMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_IndicationMessage_type, ett_h245_IndicationMessage, IndicationMessage_choice, "IndicationMessage", &value);
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ if ( h245_shorttypes == TRUE )
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(value, IndicationMessage_short_vals, "<unknown>"));
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(value, IndicationMessage_vals, "<unknown>"));
+ }
+ }
+
+ col_set_fence(pinfo->cinfo,COL_INFO);
+
+ return offset;
+}
+
+
+
+static const value_string RequestMessage_short_vals[] = {
+ { 0, "NSM" },
+ { 1, "MSD" },
+ { 2, "TCS" },
+ { 3, "OLC" },
+ { 4, "CLC" },
+ { 5, "RCC" },
+ { 6, "MES" },
+ { 7, "RME" },
+ { 8, "RM" },
+ { 9, "RTDR" },
+ { 10, "MLR" },
+ { 11, "CMR" },
+ { 12, "CR" },
+ { 13, "MR" },
+ { 14, "LCRR" },
+ { 0, NULL }
+};
+
+
+static const value_string RequestMessage_vals[] = {
+ { 0, "NonStandardMessage" },
+ { 1, "MasterSlaveDetermination" },
+ { 2, "TerminalCapabilitySet" },
+ { 3, "OpenLogicalChannel" },
+ { 4, "CloseLogicalChannel" },
+ { 5, "RequestChannelClose" },
+ { 6, "MultiplexEntrySend" },
+ { 7, "RequestMultiplexEntry" },
+ { 8, "RequestMode" },
+ { 9, "RoundTripDelayRequest" },
+ { 10, "MaintenanceLoopRequest" },
+ { 11, "CommunicationModeRequest" },
+ { 12, "ConferenceRequest" },
+ { 13, "MultilinkRequest" },
+ { 14, "LogicalChannelRateRequest" },
+ { 0, NULL }
+};
+static per_choice_t RequestMessage_choice[] = {
+ { 0, "NonStandardMessage", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardMessage },
+ { 1, "MasterSlaveDetermination", ASN1_EXTENSION_ROOT,
+ dissect_h245_MasterSlaveDetermination },
+ { 2, "TerminalCapabilitySet", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalCapabilitySet },
+ { 3, "OpenLogicalChannel", ASN1_EXTENSION_ROOT,
+ dissect_h245_OpenLogicalChannel },
+ { 4, "CloseLogicalChannel", ASN1_EXTENSION_ROOT,
+ dissect_h245_CloseLogicalChannel },
+ { 5, "RequestChannelClose", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestChannelClose },
+ { 6, "MultiplexEntrySend", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultiplexEntrySend },
+ { 7, "RequestMultiplexEntry", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestMultiplexEntry },
+ { 8, "RequestMode", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestMode },
+ { 9, "RoundTripDelayRequest", ASN1_EXTENSION_ROOT,
+ dissect_h245_RoundTripDelayRequest },
+ { 10, "MaintenanceLoopRequest", ASN1_EXTENSION_ROOT,
+ dissect_h245_MaintenanceLoopRequest },
+ { 11, "CommunicationModeRequest", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_CommunicationModeRequest },
+ { 12, "ConferenceRequest", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceRequest },
+ { 13, "MultilinkRequest", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultilinkRequest },
+ { 14, "LogicalChannelRateRequest", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelRateRequest },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_RequestMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_RequestMessage_type, ett_h245_RequestMessage, RequestMessage_choice, "RequestMessage", &value);
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ if ( h245_shorttypes == TRUE )
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(value, RequestMessage_short_vals, "<unknown>"));
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(value, RequestMessage_vals, "<unknown>"));
+ }
+ }
+
+ if (( check_col(pinfo->cinfo, COL_INFO)) && ( codec_type != NULL ) && ( value == 3) ){
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ", codec_type );
+ }
+
+ col_set_fence(pinfo->cinfo,COL_INFO);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_centralizedData_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_centralizedData, ett_h245_centralizedData, dissect_h245_DataApplicationCapability );
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_distributedData_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_distributedData, ett_h245_distributedData, dissect_h245_DataApplicationCapability );
+ return offset;
+}
+
+
+
+static per_sequence_t MediaDistributionCapability_sequence[] = {
+ { "centralizedControl", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_centralizedControl },
+ { "distributedControl", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_distributedControl },
+ { "centralizedAudio", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_centralizedAudio },
+ { "distributedAudio", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_distributedAudio },
+ { "centralizedVideo", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_centralizedVideo },
+ { "distributedVideo", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_distributedVideo },
+ { "centralizedData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_centralizedData_sequence_of },
+ { "distributedData", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_distributedData_sequence_of },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_MediaDistributionCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_MediaDistributionCapability, ett_h245_MediaDistributionCapability, MediaDistributionCapability_sequence);
+
+ return offset;
+}
+
+
+static int
+dissect_h245_mediaDistributionCapability_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h245_mediaDistributionCapability, ett_h245_mediaDistributionCapability, dissect_h245_MediaDistributionCapability );
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_rtpPayloadType_sequence_of(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, tree, hf_h245_rtpPayloadType_sequence_of, ett_h245_rtpPayloadType_sequence_of, dissect_h245_RTPPayloadType, 1, 256 );
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t H223ModeParameters_sequence[] = {
+ { "adaptationLayerType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_H223ModeParameters_adaptationLayerType },
+ { "segmentableFlag", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_segmentableFlag },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_H223ModeParameters(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_H223ModeParameters, ett_h245_H223ModeParameters, H223ModeParameters_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t ModeElement_sequence[] = {
+ { "type", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ModeElementType },
+ { "h223ModeParameters", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_H223ModeParameters },
+ { "v76ModeParameters", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_V76ModeParameters },
+ { "h2250ModeParameters", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_H2250ModeParameters },
+ { "genericModeParameters", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_GenericCapability },
+ { "multiplexedStreamModeParameters", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_MultiplexedStreamModeParameters },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_ModeElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_ModeElement, ett_h245_ModeElement, ModeElement_sequence);
+
+ return offset;
+}
+
+
+
+
+
+static int
+dissect_h245_t38FaxMaxBuffer(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_integer(tvb, offset, pinfo, tree,
+ hf_h245_t38FaxMaxBuffer,
+ NULL, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_h245_t38FaxMaxDatagram(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_integer(tvb, offset, pinfo, tree,
+ hf_h245_t38FaxMaxDatagram,
+ NULL, NULL);
+
+ return offset;
+}
+
+
+
+
+
+static per_sequence_t T38FaxUdpOptions_sequence[] = {
+ { "t38FaxMaxBuffer", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h245_t38FaxMaxBuffer },
+ { "t38FaxMaxDatagram", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h245_t38FaxMaxDatagram },
+ { "t38FaxUdpEC", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h245_T38FaxUdpOptions_t38FaxUdpEC },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_T38FaxUdpOptions(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_T38FaxUdpOptions, ett_h245_T38FaxUdpOptions, T38FaxUdpOptions_sequence);
+
+ return offset;
+}
+
+
+
+
+
+
+static int
+dissect_h245_sessionDescription(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+PER_NOT_DECODED_YET("sessionDescription");
+ return offset;
+}
+
+
+
+static per_sequence_t CommunicationModeTableEntry_sequence[] = {
+ { "nonStandard", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_nonStandardData_sequence_of },
+ { "sessionID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sessionID_1_255 },
+ { "associatedSessionID", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_associatedSessionID },
+ { "terminalLabel", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { "sessionDescription", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_sessionDescription },
+ { "dataType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_CommunicationModeTableEntry_dataType },
+ { "mediaChannel", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaChannel },
+ { "mediaGuaranteedDelivery", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaGuaranteedDelivery },
+ { "mediaControlChannel", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaControlChannel },
+ { "mediaControlGuaranteedDelivery", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_mediaControlGuaranteedDelivery },
+ { "redundancyEncoding", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_RedundancyEncoding },
+ { "sessionDependency", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_sessionDependency },
+ { "destination", ASN1_NOT_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_TerminalLabel },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_CommunicationModeTableEntry(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_CommunicationModeTableEntry, ett_h245_CommunicationModeTableEntry, CommunicationModeTableEntry_sequence);
+
+ return offset;
+}
+
+
+
+
+static per_sequence_t NewATMVCCommand_sequence[] = {
+ { "resouceID", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_resourceID },
+ { "bitRate", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_ATM_BitRate },
+ { "bitRateLockedToPCRClock", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_bitRateLockedToPCRClock },
+ { "bitRateLockedToNetworkClock", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_bitRateLockedToNetworkClock },
+ { "aal", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCCommand_aal },
+ { "multiplex", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCCommand_multiplex },
+ { "reverseParameters", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_NewATMVCCommand_reverseParameters },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_NewATMVCCommand(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_NewATMVCCommand, ett_h245_NewATMVCCommand, NewATMVCCommand_sequence);
+
+ return offset;
+}
+
+static const value_string CommandMessage_short_vals[] = {
+ { 0, "NSM" },
+ { 1, "MLOC" },
+ { 2, "STCS" },
+ { 3, "EC" },
+ { 4, "FCC" },
+ { 5, "ESC" },
+ { 6, "MC" },
+ { 7, "CMC" },
+ { 8, "CC" },
+ { 9, "H223MR" },
+ { 10, "NATMVCC" },
+ { 11, "MMRC" },
+ { 0, NULL }
+};
+
+
+
+static const value_string CommandMessage_vals[] = {
+ { 0, "NonStandardMessage" },
+ { 1, "MaintenanceLoopOffCommand" },
+ { 2, "SendTerminalCapabilitySet" },
+ { 3, "EncryptionCommand" },
+ { 4, "FlowControlCommand" },
+ { 5, "EndSessionCommand" },
+ { 6, "MiscellaneousCommand" },
+ { 7, "CommunicationModeCommand" },
+ { 8, "ConferenceCommand" },
+ { 9, "H223MultiplexReconfiguration" },
+ { 10, "NewATMVCCommand" },
+ { 11, "MobileMultilinkReconfigurationCommand" },
+ { 0, NULL }
+};
+static per_choice_t CommandMessage_choice[] = {
+ { 0, "NonStandardMessage", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardMessage },
+ { 1, "MaintenanceLoopOffCommand", ASN1_EXTENSION_ROOT,
+ dissect_h245_MaintenanceLoopOffCommand },
+ { 2, "SendTerminalCapabilitySet", ASN1_EXTENSION_ROOT,
+ dissect_h245_SendTerminalCapabilitySet },
+ { 3, "EncryptionCommand", ASN1_EXTENSION_ROOT,
+ dissect_h245_EncryptionCommand },
+ { 4, "FlowControlCommand", ASN1_EXTENSION_ROOT,
+ dissect_h245_FlowControlCommand },
+ { 5, "EndSessionCommand", ASN1_EXTENSION_ROOT,
+ dissect_h245_EndSessionCommand },
+ { 6, "MiscellaneousCommand", ASN1_EXTENSION_ROOT,
+ dissect_h245_MiscellaneousCommand },
+ { 7, "CommunicationModeCommand", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_CommunicationModeCommand },
+ { 8, "ConferenceCommand", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceCommand },
+ { 9, "H223MultiplexReconfiguration", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_H223MultiplexReconfiguration },
+ { 10, "NewATMVCCommand", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_NewATMVCCommand },
+ { 11, "MobileMultilinkReconfigurationCommand",ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MobileMultilinkReconfigurationCommand },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_CommandMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_CommandMessage_type, ett_h245_CommandMessage, CommandMessage_choice, "CommandMessage", &value);
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ if ( h245_shorttypes == TRUE )
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(value, CommandMessage_short_vals, "<unknown>"));
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(value, CommandMessage_vals, "<unknown>"));
+ }
+ }
+
+ col_set_fence(pinfo->cinfo,COL_INFO);
+
+ return offset;
+}
+
+
+
+
+static const value_string ResponseMessage_short_vals[] = {
+ { 0, "NSM" },
+ { 1, "MSDAck" },
+ { 2, "MSDReject" },
+ { 3, "TCSAck" },
+ { 4, "TCSReject" },
+ { 5, "OLCAck" },
+ { 6, "OLCReject" },
+ { 7, "CLCAck" },
+ { 8, "RCCAck" },
+ { 9, "RCCReject" },
+ { 10, "MESAck" },
+ { 11, "MESReject" },
+ { 12, "RMEAck" },
+ { 13, "RMEReject" },
+ { 14, "RMAck" },
+ { 15, "RMReject" },
+ { 16, "RTDResponse" },
+ { 17, "MLAck" },
+ { 18, "MLReject" },
+ { 19, "CMResponse" },
+ { 20, "CResponse" },
+ { 21, "MResponse" },
+ { 22, "LCRAck" },
+ { 23, "LCRReject" },
+ { 0, NULL }
+};
+
+
+static const value_string ResponseMessage_vals[] = {
+ { 0, "NonStandardMessage" },
+ { 1, "MasterSlaveDeterminationAck" },
+ { 2, "MasterSlaveDeterminationReject" },
+ { 3, "TerminalCapabilitySetAck" },
+ { 4, "TerminalCapabilitySetReject" },
+ { 5, "OpenLogicalChannelAck" },
+ { 6, "OpenLogicalChannelReject" },
+ { 7, "CloseLogicalChannelAck" },
+ { 8, "RequestChannelCloseAck" },
+ { 9, "RequestChannelCloseReject" },
+ { 10, "MultiplexEntrySendAck" },
+ { 11, "MultiplexEntrySendReject" },
+ { 12, "RequestMultiplexEntryAck" },
+ { 13, "RequestMultiplexEntryReject" },
+ { 14, "RequestModeAck" },
+ { 15, "RequestModeReject" },
+ { 16, "RoundTripDelayResponse" },
+ { 17, "MaintenanceLoopAck" },
+ { 18, "MaintenanceLoopReject" },
+ { 19, "CommunicationModeResponse" },
+ { 20, "ConferenceResponse" },
+ { 21, "MultilinkResponse" },
+ { 22, "LogicalChannelRateAck" },
+ { 23, "LogicalChannelRateReject" },
+ { 0, NULL }
+};
+static per_choice_t ResponseMessage_choice[] = {
+ { 0, "NonStandardMessage", ASN1_EXTENSION_ROOT,
+ dissect_h245_NonStandardMessage },
+ { 1, "MasterSlaveDeterminationAck", ASN1_EXTENSION_ROOT,
+ dissect_h245_MasterSlaveDeterminationAck },
+ { 2, "MasterSlaveDeterminationReject",ASN1_EXTENSION_ROOT,
+ dissect_h245_MasterSlaveDeterminationReject },
+ { 3, "TerminalCapabilitySetAck", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalCapabilitySetAck },
+ { 4, "TerminalCapabilitySetReject", ASN1_EXTENSION_ROOT,
+ dissect_h245_TerminalCapabilitySetReject },
+ { 5, "OpenLogicalChannelAck", ASN1_EXTENSION_ROOT,
+ dissect_h245_OpenLogicalChannelAck },
+ { 6, "OpenLogicalChannelReject", ASN1_EXTENSION_ROOT,
+ dissect_h245_OpenLogicalChannelReject },
+ { 7, "CloseLogicalChannelAck", ASN1_EXTENSION_ROOT,
+ dissect_h245_CloseLogicalChannelAck },
+ { 8, "RequestChannelCloseAck", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestChannelCloseAck },
+ { 9, "RequestChannelCloseReject", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestChannelCloseReject },
+ { 10, "MultiplexEntrySendAck", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultiplexEntrySendAck },
+ { 11, "MultiplexEntrySendReject", ASN1_EXTENSION_ROOT,
+ dissect_h245_MultiplexEntrySendReject },
+ { 12, "RequestMultiplexEntryAck", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestMultiplexEntryAck },
+ { 13, "RequestMultiplexEntryReject", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestMultiplexEntryReject },
+ { 14, "RequestModeAck", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestModeAck },
+ { 15, "RequestModeReject", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestModeReject },
+ { 16, "RoundTripDelayResponse", ASN1_EXTENSION_ROOT,
+ dissect_h245_RoundTripDelayResponse },
+ { 17, "MaintenanceLoopAck", ASN1_EXTENSION_ROOT,
+ dissect_h245_MaintenanceLoopAck },
+ { 18, "MaintenanceLoopReject", ASN1_EXTENSION_ROOT,
+ dissect_h245_MaintenanceLoopReject },
+ { 19, "CommunicationModeResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_CommunicationModeResponse },
+ { 20, "ConferenceResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_ConferenceResponse },
+ { 21, "MultilinkResponse", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_MultilinkResponse },
+ { 22, "LogicalChannelRateAck", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelRateAck },
+ { 23, "LogicalChannelRateReject", ASN1_NOT_EXTENSION_ROOT,
+ dissect_h245_LogicalChannelRateReject },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h245_ResponseMessage(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value;
+
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h245_ResponseMessage_type, ett_h245_ResponseMessage, ResponseMessage_choice, "ResponseMessage", &value);
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ if ( h245_shorttypes == TRUE )
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(value, ResponseMessage_short_vals, "<unknown>"));
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(value, ResponseMessage_vals, "<unknown>"));
+ }
+ }
+
+ col_set_fence(pinfo->cinfo,COL_INFO);
+
+ return offset;
+}
+
+
+
+
+
+
+static int
+dissect_h245_DialingInformationNumber_networkAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_NumericString(tvb, offset, pinfo, tree, hf_h245_DialingInformationNumber_networkAddress, 0, 40);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_h245_DialingInformationNumber_subAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_IA5String(tvb, offset, pinfo, tree, hf_h245_subAddress, 0, 40);
+
+ return offset;
+}
+
+
+
+static per_sequence_t DialingInformationNumber_sequence[] = {
+ { "networkAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_DialingInformationNumber_networkAddress },
+ { "subAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h245_DialingInformationNumber_subAddress },
+ { "networkType", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h245_networkType },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h245_DialingInformationNumber(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h245_DialingInformationNumber, ett_h245_DialingInformationNumber, DialingInformationNumber_sequence);
+
+ return offset;
+}
+
+
+static const value_string MultimediaSystemControlMessage_vals[] = {
+ { 0, "Request" },
+ { 1, "Response" },
+ { 2, "Command" },
+ { 3, "Indication" },
+ { 0, NULL }
+};
+static per_choice_t MultimediaSystemControlMessage_choice[] = {
+ { 0, "Request", ASN1_EXTENSION_ROOT,
+ dissect_h245_RequestMessage },
+ { 1, "Response", ASN1_EXTENSION_ROOT,
+ dissect_h245_ResponseMessage },
+ { 2, "Command", ASN1_EXTENSION_ROOT,
+ dissect_h245_CommandMessage },
+ { 3, "Indication", ASN1_EXTENSION_ROOT,
+ dissect_h245_IndicationMessage },
+ { 0, NULL, 0, NULL }
+};
+void
+dissect_h245_MultimediaSystemControlMessage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *it;
+ proto_tree *tr;
+ guint32 offset=0;
+ guint32 value;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)){
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.245");
+ }
+
+ it=proto_tree_add_protocol_format(tree, proto_h245, tvb, 0, tvb_length(tvb), "H.245");
+ tr=proto_item_add_subtree(it, ett_h245);
+
+ /* this code is called from at least TPKT (over TCP) and
+ MEGACO. Over MEGACO there is no framing so we just have to assume
+ that as long as we havent run out of TVB data, there is more
+ MSCM PDUsa to decode.
+ */
+ while(tvb_length_remaining(tvb, offset>>3)>0){
+ offset=dissect_per_choice(tvb, offset, pinfo, tr, hf_h245_pdu_type, ett_h245_MultimediaSystemControlMessage, MultimediaSystemControlMessage_choice, "MultimediaSystemControlMessage", &value);
+ /* align next PDU to octet boundary */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ }
+}
+
+
+
+
+
+
+void
+dissect_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_tpkt_encap(tvb, pinfo, tree, h245_reassembly, MultimediaSystemControlMessage_handle);
+}
+
+void
+proto_register_h245(void)
+{
+ static hf_register_info hf[] =
+ {
+ { &hf_h245_pdu_type,
+ { "PDU Type", "h245.pdu_type", FT_UINT32, BASE_DEC,
+ VALS(MultimediaSystemControlMessage_vals), 0, "Type of H.245 PDU", HFILL }},
+ { &hf_h245_IndicationMessage_type,
+ { "Indication Type", "h245.indication_type", FT_UINT32, BASE_DEC,
+ VALS(IndicationMessage_vals), 0, "Type of Indication", HFILL }},
+ { &hf_h245_RequestMessage_type,
+ { "Request Type", "h245.request_type", FT_UINT32, BASE_DEC,
+ VALS(RequestMessage_vals), 0, "Type of Request", HFILL }},
+ { &hf_h245_ResponseMessage_type,
+ { "Response Type", "h245.response_type", FT_UINT32, BASE_DEC,
+ VALS(ResponseMessage_vals), 0, "Type of Response", HFILL }},
+ { &hf_h245_CommandMessage_type,
+ { "Command Type", "h245.command_type", FT_UINT32, BASE_DEC,
+ VALS(CommandMessage_vals), 0, "Type of Command", HFILL }},
+ { &hf_h245_EndSessionCommand_type,
+ { "EndSessionCommand type", "h245.endsessioncommand_type", FT_UINT32, BASE_DEC,
+ VALS(EndSessionCommand_vals), 0, "Type of EndSessionCommand", HFILL }},
+ { &hf_h245_PixelAspectCode,
+ { "PixelAspectCode", "h245.PixelAspectCode", FT_UINT32, BASE_DEC,
+ NULL, 0, "PixelAspectCode", HFILL }},
+ { &hf_h245_LogicalChannelNumber,
+ { "LogicalChannelNumber", "h245.logicalchannelnumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "LogicalChannelNumber", HFILL }},
+ { &hf_h245_SequenceNumber,
+ { "SequenceNumber", "h245.sequencenumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "SequenceNumber", HFILL }},
+ { &hf_h245_OpenLogicalChannelConfirm,
+ { "OpenLogicalChannelConfirm", "h245.openlogicalchannelconfirm", FT_NONE, BASE_NONE,
+ NULL, 0, "OpenLogicalChannelConfirm sequence", HFILL }},
+ { &hf_h245_MobileMultilinkReconfigurationIndication,
+ { "MobileMultilinkReconfigurationIndication", "h245.MobileMultilinkReconfigurationIndication", FT_NONE, BASE_NONE,
+ NULL, 0, "MobileMultilinkReconfigurationIndication sequence", HFILL }},
+ { &hf_h245_FlowControlIndication,
+ { "FlowControlIndication", "h245.FlowControlIndication", FT_NONE, BASE_NONE,
+ NULL, 0, "FlowControlIndication sequence", HFILL }},
+ { &hf_h245_UserInputIndication_extendedAlphanumeric,
+ { "UserInputIndication_extendedAlphanumeric", "h245.UserInputIndication_extendedAlphanumeric", FT_NONE, BASE_NONE,
+ NULL, 0, "UserInputIndication_extendedAlphanumeric sequence", HFILL }},
+ { &hf_h245_UserInputIndication_signalUpdate_rtp,
+ { "UserInputIndication_signalUpdate_rtp", "h245.UserInputIndication_signalUpdate_rtp", FT_NONE, BASE_NONE,
+ NULL, 0, "UserInputIndication_signalUpdate_rtp sequence", HFILL }},
+ { &hf_h245_UserInputIndication_signalUpdate,
+ { "UserInputIndication_signalUpdate", "h245.UserInputIndication_signalUpdate", FT_NONE, BASE_NONE,
+ NULL, 0, "UserInputIndication_signalUpdate sequence", HFILL }},
+ { &hf_h245_UserInputIndication_signal_rtp,
+ { "UserInputIndication_signal_rtp", "h245.UserInputIndication_signal_rtp", FT_NONE, BASE_NONE,
+ NULL, 0, "UserInputIndication_signal_rtp sequence", HFILL }},
+ { &hf_h245_UserInputIndication_signal,
+ { "UserInputIndication_signal", "h245.UserInputIndication_signal", FT_NONE, BASE_NONE,
+ NULL, 0, "UserInputIndication_signal sequence", HFILL }},
+ { &hf_h245_NewATMVCIndication_reverseParameters,
+ { "NewATMVCIndication_reverseParameters", "h245.NewATMVCIndication_reverseParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "NewATMVCIndication_reverseParameters sequence", HFILL }},
+ { &hf_h245_NewATMVCIndication_aal_aal5,
+ { "NewATMVCIndication_aal_aal5", "h245.NewATMVCIndication_aal_aal5", FT_NONE, BASE_NONE,
+ NULL, 0, "NewATMVCIndication_aal_aal5 sequence", HFILL }},
+ { &hf_h245_NewATMVCIndication_aal_aal1,
+ { "NewATMVCIndication_aal_aal1", "h245.NewATMVCIndication_aal_aal1", FT_NONE, BASE_NONE,
+ NULL, 0, "NewATMVCIndication_aal_aal1 sequence", HFILL }},
+ { &hf_h245_NewATMVCIndication,
+ { "NewATMVCIndication", "h245.NewATMVCIndication", FT_NONE, BASE_NONE,
+ NULL, 0, "NewATMVCIndication sequence", HFILL }},
+ { &hf_h245_VendorIdentification,
+ { "VendorIdentification", "h245.VendorIdentification", FT_NONE, BASE_NONE,
+ NULL, 0, "VendorIdentification sequence", HFILL }},
+ { &hf_h245_MCLocationIndication,
+ { "MCLocationIndication", "h245.MCLocationIndication", FT_NONE, BASE_NONE,
+ NULL, 0, "MCLocationIndication sequence", HFILL }},
+ { &hf_h245_H2250MaximumSkewIndication,
+ { "H2250MaximumSkewIndication", "h245.H2250MaximumSkewIndication", FT_NONE, BASE_NONE,
+ NULL, 0, "H2250MaximumSkewIndication sequence", HFILL }},
+ { &hf_h245_H223SkewIndication,
+ { "H223SkewIndication", "h245.H223SkewIndication", FT_NONE, BASE_NONE,
+ NULL, 0, "H223SkewIndication sequence", HFILL }},
+ { &hf_h245_JitterIndication,
+ { "JitterIndication", "h245.JitterIndication", FT_NONE, BASE_NONE,
+ NULL, 0, "JitterIndication sequence", HFILL }},
+ { &hf_h245_MiscellaneousIndication_type_videoNotDecodedMBs,
+ { "MiscellaneousIndication_type_videoNotDecodedMBs", "h245.MiscellaneousIndication_type_videoNotDecodedMBs", FT_NONE, BASE_NONE,
+ NULL, 0, "MiscellaneousIndication_type_videoNotDecodedMBs sequence", HFILL }},
+ { &hf_h245_MiscellaneousIndication,
+ { "MiscellaneousIndication", "h245.MiscellaneousIndication", FT_NONE, BASE_NONE,
+ NULL, 0, "MiscellaneousIndication sequence", HFILL }},
+ { &hf_h245_VideoIndicateCompose,
+ { "VideoIndicateCompose", "h245.VideoIndicateCompose", FT_NONE, BASE_NONE,
+ NULL, 0, "VideoIndicateCompose sequence", HFILL }},
+ { &hf_h245_TerminalYouAreSeeingInSubPictureNumber,
+ { "TerminalYouAreSeeingInSubPictureNumber", "h245.TerminalYouAreSeeingInSubPictureNumber", FT_NONE, BASE_NONE,
+ NULL, 0, "TerminalYouAreSeeingInSubPictureNumber sequence", HFILL }},
+ { &hf_h245_FunctionNotSupported,
+ { "FunctionNotSupported", "h245.FunctionNotSupported", FT_NONE, BASE_NONE,
+ NULL, 0, "FunctionNotSupported sequence", HFILL }},
+ { &hf_h245_MobileMultilinkReconfigurationCommand,
+ { "MobileMultilinkReconfigurationCommand", "h245.MobileMultilinkReconfigurationCommand", FT_NONE, BASE_NONE,
+ NULL, 0, "MobileMultilinkReconfigurationCommand sequence", HFILL }},
+ { &hf_h245_NewATMVCCommand_reverseParameters,
+ { "NewATMVCCommand_reverseParameters", "h245.NewATMVCCommand_reverseParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "NewATMVCCommand_reverseParameters sequence", HFILL }},
+ { &hf_h245_NewATMVCCommand,
+ { "NewATMVCCommand", "h245.NewATMVCCommand", FT_NONE, BASE_NONE,
+ NULL, 0, "NewATMVCCommand sequence", HFILL }},
+ { &hf_h245_NewATMVCCommand_aal_aal5,
+ { "NewATMVCCommand_aal_aal5", "h245.NewATMVCCommand_aal_aal5", FT_NONE, BASE_NONE,
+ NULL, 0, "NewATMVCCommand_aal_aal5 sequence", HFILL }},
+ { &hf_h245_NewATMVCCommand_aal_aal1,
+ { "NewATMVCCommand_aal_aal1", "h245.NewATMVCCommand_aal_aal1", FT_NONE, BASE_NONE,
+ NULL, 0, "NewATMVCCommand_aal_aal1 sequence", HFILL }},
+ { &hf_h245_EncryptionUpdateRequest,
+ { "EncryptionUpdateRequest", "h245.EncryptionUpdateRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "EncryptionUpdateRequest sequence", HFILL }},
+ { &hf_h245_KeyProtectionMethod,
+ { "KeyProtectionMethod", "h245.KeyProtectionMethod", FT_NONE, BASE_NONE,
+ NULL, 0, "KeyProtectionMethod sequence", HFILL }},
+ { &hf_h245_MiscellaneousCommand_type_lostPartialPicture,
+ { "MiscellaneousCommand_type_lostPartialPicture", "h245.MiscellaneousCommand_type_lostPartialPicture", FT_NONE, BASE_NONE,
+ NULL, 0, "MiscellaneousCommand_type_lostPartialPicture sequence", HFILL }},
+ { &hf_h245_MiscellaneousCommand_type_videoBadMBs,
+ { "MiscellaneousCommand_type_videoBadMBs", "h245.MiscellaneousCommand_type_videoBadMBs", FT_NONE, BASE_NONE,
+ NULL, 0, "MiscellaneousCommand_type_videoBadMBs sequence", HFILL }},
+ { &hf_h245_MiscellaneousCommand_type_progressiveRefinementStart,
+ { "MiscellaneousCommand_type_progressiveRefinementStart", "h245.MiscellaneousCommand_type_progressiveRefinementStart", FT_NONE, BASE_NONE,
+ NULL, 0, "MiscellaneousCommand_type_progressiveRefinementStart sequence", HFILL }},
+ { &hf_h245_MiscellaneousCommand_type_videoFastUpdateMB,
+ { "MiscellaneousCommand_type_videoFastUpdateMB", "h245.MiscellaneousCommand_type_videoFastUpdateMB", FT_NONE, BASE_NONE,
+ NULL, 0, "MiscellaneousCommand_type_videoFastUpdateMB sequence", HFILL }},
+ { &hf_h245_MiscellaneousCommand_type_videoFastUpdateGOB,
+ { "MiscellaneousCommand_type_videoFastUpdateGOB", "h245.MiscellaneousCommand_type_videoFastUpdateGOB", FT_NONE, BASE_NONE,
+ NULL, 0, "MiscellaneousCommand_type_videoFastUpdateGOB sequence", HFILL }},
+ { &hf_h245_MiscellaneousCommand,
+ { "MiscellaneousCommand", "h245.MiscellaneousCommand", FT_NONE, BASE_NONE,
+ NULL, 0, "MiscellaneousCommand sequence", HFILL }},
+ { &hf_h245_SubstituteConferenceIDCommand,
+ { "SubstituteConferenceIDCommand", "h245.SubstituteConferenceIDCommand", FT_NONE, BASE_NONE,
+ NULL, 0, "SubstituteConferenceIDCommand sequence", HFILL }},
+ { &hf_h245_FlowControlCommand,
+ { "FlowControlCommand", "h245.FlowControlCommand", FT_NONE, BASE_NONE,
+ NULL, 0, "FlowControlCommand sequence", HFILL }},
+ { &hf_h245_EncryptionCommand_encryptionAlgorithmID,
+ { "EncryptionCommand_encryptionAlgorithmID", "h245.EncryptionCommand_encryptionAlgorithmID", FT_NONE, BASE_NONE,
+ NULL, 0, "EncryptionCommand_encryptionAlgorithmID sequence", HFILL }},
+ { &hf_h245_SendTerminalCapabilitySet_specificRequest,
+ { "SendTerminalCapabilitySet_specificRequest", "h245.SendTerminalCapabilitySet_specificRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "SendTerminalCapabilitySet_specificRequest sequence", HFILL }},
+ { &hf_h245_LogicalChannelRateRelease,
+ { "LogicalChannelRateRelease", "h245.LogicalChannelRateRelease", FT_NONE, BASE_NONE,
+ NULL, 0, "LogicalChannelRateRelease sequence", HFILL }},
+ { &hf_h245_LogicalChannelRateReject,
+ { "LogicalChannelRateReject", "h245.LogicalChannelRateReject", FT_NONE, BASE_NONE,
+ NULL, 0, "LogicalChannelRateReject sequence", HFILL }},
+ { &hf_h245_LogicalChannelRateAck,
+ { "LogicalChannelRateAck", "h245.LogicalChannelRateAck", FT_NONE, BASE_NONE,
+ NULL, 0, "LogicalChannelRateAck sequence", HFILL }},
+ { &hf_h245_LogicalChannelRateRequest,
+ { "LogicalChannelRateRequest", "h245.LogicalChannelRateRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "LogicalChannelRateRequest sequence", HFILL }},
+ { &hf_h245_ConnectionIdentifier,
+ { "ConnectionIdentifier", "h245.ConnectionIdentifier", FT_NONE, BASE_NONE,
+ NULL, 0, "ConnectionIdentifier sequence", HFILL }},
+ { &hf_h245_DialingInformationNumber,
+ { "DialingInformationNumber", "h245.DialingInformationNumber", FT_NONE, BASE_NONE,
+ NULL, 0, "DialingInformationNumber sequence", HFILL }},
+ { &hf_h245_MultilinkIndication_excessiveError,
+ { "MultilinkIndication_excessiveError", "h245.MultilinkIndication_excessiveError", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkIndication_excessiveError sequence", HFILL }},
+ { &hf_h245_MultilinkIndication_crcDesired,
+ { "MultilinkIndication_crcDesired", "h245.MultilinkIndication_crcDesired", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkIndication_crcDesired sequence", HFILL }},
+ { &hf_h245_MultilinkResponse_maximumHeaderInterval,
+ { "MultilinkResponse_maximumHeaderInterval", "h245.MultilinkResponse_maximumHeaderInterval", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkResponse_maximumHeaderInterval sequence", HFILL }},
+ { &hf_h245_MultilinkResponse_removeConnection,
+ { "MultilinkResponse_removeConnection", "h245.MultilinkResponse_removeConnection", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkResponse_removeConnection sequence", HFILL }},
+ { &hf_h245_MultilinkResponse_addConnection,
+ { "MultilinkResponse_addConnection", "h245.MultilinkResponse_addConnection", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkResponse_addConnection sequence", HFILL }},
+ { &hf_h245_MultilinkResponse_callInformation,
+ { "MultilinkResponse_callInformation", "h245.MultilinkResponse_callInformation", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkResponse_callInformation sequence", HFILL }},
+ { &hf_h245_MultilinkRequest_maximumHeaderInterval,
+ { "MultilinkRequest_maximumHeaderInterval", "h245.MultilinkRequest_maximumHeaderInterval", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkRequest_maximumHeaderInterval sequence", HFILL }},
+ { &hf_h245_MultilinkRequest_removeConnection,
+ { "MultilinkRequest_removeConnection", "h245.MultilinkRequest_removeConnection", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkRequest_removeConnection sequence", HFILL }},
+ { &hf_h245_MultilinkRequest_addConnection,
+ { "MultilinkRequest_addConnection", "h245.MultilinkRequest_addConnection", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkRequest_addConnection sequence", HFILL }},
+ { &hf_h245_MultilinkRequest_callInformation,
+ { "MultilinkRequest_callInformation", "h245.MultilinkRequest_callInformation", FT_NONE, BASE_NONE,
+ NULL, 0, "MultilinkRequest_callInformation sequence", HFILL }},
+ { &hf_h245_TerminalInformation,
+ { "TerminalInformation", "h245.TerminalInformation", FT_NONE, BASE_NONE,
+ NULL, 0, "TerminalInformation sequence", HFILL }},
+ { &hf_h245_RequestAllTerminalIDsResponse,
+ { "RequestAllTerminalIDsResponse", "h245.RequestAllTerminalIDsResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestAllTerminalIDsResponse sequence", HFILL }},
+ { &hf_h245_ConferenceResponse_terminalCertificateResponse,
+ { "ConferenceResponse_terminalCertificateResponse", "h245.ConferenceResponse_terminalCertificateResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceResponse_terminalCertificateResponse sequence", HFILL }},
+ { &hf_h245_ConferenceResponse_chairTokenOwnerResponse,
+ { "ConferenceResponse_chairTokenOwnerResponse", "h245.ConferenceResponse_chairTokenOwnerResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceResponse_chairTokenOwnerResponse sequence", HFILL }},
+ { &hf_h245_ConferenceResponse_extensionAddressResponse,
+ { "ConferenceResponse_extensionAddressResponse", "h245.ConferenceResponse_extensionAddressResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceResponse_extensionAddressResponse sequence", HFILL }},
+ { &hf_h245_ConferenceResponse_passwordResponse,
+ { "ConferenceResponse_passwordResponse", "h245.ConferenceResponse_passwordResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceResponse_passwordResponse sequence", HFILL }},
+ { &hf_h245_ConferenceResponse_conferenceIDResponse,
+ { "ConferenceResponse_conferenceIDResponse", "h245.ConferenceResponse_conferenceIDResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceResponse_conferenceIDResponse sequence", HFILL }},
+ { &hf_h245_ConferenceResponse_terminalIDResponse,
+ { "ConferenceResponse_terminalIDResponse", "h245.ConferenceResponse_terminalIDResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceResponse_terminalIDResponse sequence", HFILL }},
+ { &hf_h245_ConferenceResponse_mCterminalIDResponse,
+ { "ConferenceResponse_mCterminalIDResponse", "h245.ConferenceResponse_mCterminalIDResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceResponse_mCterminalIDResponse sequence", HFILL }},
+ { &hf_h245_TerminalLabel,
+ { "TerminalLabel", "h245.TerminalLabel", FT_NONE, BASE_NONE,
+ NULL, 0, "TerminalLabel sequence", HFILL }},
+ { &hf_h245_Criteria,
+ { "Criteria", "h245.Criteria", FT_NONE, BASE_NONE,
+ NULL, 0, "Criteria sequence", HFILL }},
+ { &hf_h245_ConferenceRequest_requestTerminalCertificate,
+ { "ConferenceRequest_requestTerminalCertificate", "h245.ConferenceRequest_requestTerminalCertificate", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceRequest_requestTerminalCertificate sequence", HFILL }},
+ { &hf_h245_CommunicationModeTableEntry,
+ { "CommunicationModeTableEntry", "h245.CommunicationModeTableEntry", FT_NONE, BASE_NONE,
+ NULL, 0, "CommunicationModeTableEntry sequence", HFILL }},
+ { &hf_h245_CommunicationModeRequest,
+ { "CommunicationModeRequest", "h245.CommunicationModeRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "CommunicationModeRequest sequence", HFILL }},
+ { &hf_h245_CommunicationModeCommand,
+ { "CommunicationModeCommand", "h245.CommunicationModeCommand", FT_NONE, BASE_NONE,
+ NULL, 0, "CommunicationModeCommand sequence", HFILL }},
+ { &hf_h245_MaintenanceLoopOffCommand,
+ { "MaintenanceLoopOffCommand", "h245.MaintenanceLoopOffCommand", FT_NONE, BASE_NONE,
+ NULL, 0, "MaintenanceLoopOffCommand sequence", HFILL }},
+ { &hf_h245_MaintenanceLoopReject,
+ { "MaintenanceLoopReject", "h245.MaintenanceLoopReject", FT_NONE, BASE_NONE,
+ NULL, 0, "MaintenanceLoopReject sequence", HFILL }},
+ { &hf_h245_MaintenanceLoopAck,
+ { "MaintenanceLoopAck", "h245.MaintenanceLoopAck", FT_NONE, BASE_NONE,
+ NULL, 0, "MaintenanceLoopAck sequence", HFILL }},
+ { &hf_h245_MaintenanceLoopRequest,
+ { "MaintenanceLoopRequest", "h245.MaintenanceLoopRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "MaintenanceLoopRequest sequence", HFILL }},
+ { &hf_h245_RoundTripDelayResponse,
+ { "RoundTripDelayResponse", "h245.RoundTripDelayResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "RoundTripDelayResponse sequence", HFILL }},
+ { &hf_h245_RoundTripDelayRequest,
+ { "RoundTripDelayRequest", "h245.RoundTripDelayRequest", FT_NONE, BASE_NONE,
+ NULL, 0, "RoundTripDelayRequest sequence", HFILL }},
+ { &hf_h245_DataMode_application_t38fax,
+ { "DataMode_application_t38fax", "h245.DataMode_application_t38fax", FT_NONE, BASE_NONE,
+ NULL, 0, "DataMode_application_t38fax sequence", HFILL }},
+ { &hf_h245_DataMode_application_nlpid,
+ { "DataMode_application_nlpid", "h245.DataMode_application_nlpid", FT_NONE, BASE_NONE,
+ NULL, 0, "DataMode_application_nlpid sequence", HFILL }},
+ { &hf_h245_DataMode,
+ { "DataMode", "h245.DataMode", FT_NONE, BASE_NONE,
+ NULL, 0, "DataMode sequence", HFILL }},
+ { &hf_h245_VBDMode,
+ { "VBDMode", "h245.VBDMode", FT_NONE, BASE_NONE,
+ NULL, 0, "VBDMode sequence", HFILL }},
+ { &hf_h245_G7231AnnexCMode_g723AnnexCAudioMode,
+ { "G7231AnnexCMode_g723AnnexCAudioMode", "h245.G7231AnnexCMode_g723AnnexCAudioMode", FT_NONE, BASE_NONE,
+ NULL, 0, "G7231AnnexCMode_g723AnnexCAudioMode sequence", HFILL }},
+ { &hf_h245_G7231AnnexCMode,
+ { "G7231AnnexCMode", "h245.G7231AnnexCMode", FT_NONE, BASE_NONE,
+ NULL, 0, "G7231AnnexCMode sequence", HFILL }},
+ { &hf_h245_IS13818AudioMode,
+ { "IS13818AudioMode", "h245.IS13818AudioMode", FT_NONE, BASE_NONE,
+ NULL, 0, "IS13818AudioMode sequence", HFILL }},
+ { &hf_h245_IS11172AudioMode,
+ { "IS11172AudioMode", "h245.IS11172AudioMode", FT_NONE, BASE_NONE,
+ NULL, 0, "IS11172AudioMode sequence", HFILL }},
+ { &hf_h245_IS11172VideoMode,
+ { "IS11172VideoMode", "h245.IS11172VideoMode", FT_NONE, BASE_NONE,
+ NULL, 0, "IS11172VideoMode sequence", HFILL }},
+ { &hf_h245_H263VideoMode,
+ { "H263VideoMode", "h245.H263VideoMode", FT_NONE, BASE_NONE,
+ NULL, 0, "H263VideoMode sequence", HFILL }},
+ { &hf_h245_H262VideoMode,
+ { "H262VideoMode", "h245.H262VideoMode", FT_NONE, BASE_NONE,
+ NULL, 0, "H262VideoMode sequence", HFILL }},
+ { &hf_h245_H261VideoMode,
+ { "H261VideoMode", "h245.H261VideoMode", FT_NONE, BASE_NONE,
+ NULL, 0, "H261VideoMode sequence", HFILL }},
+ { &hf_h245_RedundancyEncodingMode,
+ { "RedundancyEncodingMode", "h245.RedundancyEncodingMode", FT_NONE, BASE_NONE,
+ NULL, 0, "RedundancyEncodingMode sequence", HFILL }},
+ { &hf_h245_H2250ModeParameters,
+ { "H2250ModeParameters", "h245.H2250ModeParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H2250ModeParameters sequence", HFILL }},
+ { &hf_h245_H223ModeParameters_adaptationLayerType_al3,
+ { "H223ModeParameters_adaptationLayerType_al3", "h245.H223ModeParameters_adaptationLayerType_al3", FT_NONE, BASE_NONE,
+ NULL, 0, "H223ModeParameters_adaptationLayerType_al3 sequence", HFILL }},
+ { &hf_h245_H223ModeParameters,
+ { "H223ModeParameters", "h245.H223ModeParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H223ModeParameters sequence", HFILL }},
+ { &hf_h245_FECMode_rfc2733Mode_mode_separateStream_samePort,
+ { "FECMode_rfc2733Mode_mode_separateStream_samePort", "h245.FECMode_rfc2733Mode_mode_separateStream_samePort", FT_NONE, BASE_NONE,
+ NULL, 0, "FECMode_rfc2733Mode_mode_separateStream_samePort sequence", HFILL }},
+ { &hf_h245_FECMode_rfc2733Mode_mode_separateStream_differentPort,
+ { "FECMode_rfc2733Mode_mode_separateStream_differentPort", "h245.FECMode_rfc2733Mode_mode_separateStream_differentPort", FT_NONE, BASE_NONE,
+ NULL, 0, "FECMode_rfc2733Mode_mode_separateStream_differentPort sequence", HFILL }},
+ { &hf_h245_FECMode_rfc2733Mode,
+ { "FECMode_rfc2733Mode", "h245.FECMode_rfc2733Mode", FT_NONE, BASE_NONE,
+ NULL, 0, "FECMode_rfc2733Mode sequence", HFILL }},
+ { &hf_h245_MultiplePayloadStreamElementMode,
+ { "MultiplePayloadStreamElementMode", "h245.MultiplePayloadStreamElementMode", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplePayloadStreamElementMode sequence", HFILL }},
+ { &hf_h245_MultiplePayloadStreamMode,
+ { "MultiplePayloadStreamMode", "h245.MultiplePayloadStreamMode", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplePayloadStreamMode sequence", HFILL }},
+ { &hf_h245_RedundancyEncodingDTModeElement,
+ { "RedundancyEncodingDTModeElement", "h245.RedundancyEncodingDTModeElement", FT_NONE, BASE_NONE,
+ NULL, 0, "RedundancyEncodingDTModeElement sequence", HFILL }},
+ { &hf_h245_RedundancyEncodingDTMode,
+ { "RedundancyEncodingDTMode", "h245.RedundancyEncodingDTMode", FT_NONE, BASE_NONE,
+ NULL, 0, "RedundancyEncodingDTMode sequence", HFILL }},
+ { &hf_h245_MultiplexedStreamModeParameters,
+ { "MultiplexedStreamModeParameters", "h245.MultiplexedStreamModeParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexedStreamModeParameters sequence", HFILL }},
+ { &hf_h245_H235Mode,
+ { "H235Mode", "h245.H235Mode", FT_NONE, BASE_NONE,
+ NULL, 0, "H235Mode sequence", HFILL }},
+ { &hf_h245_ModeElement,
+ { "ModeElement", "h245.ModeElement", FT_NONE, BASE_NONE,
+ NULL, 0, "ModeElement sequence", HFILL }},
+ { &hf_h245_RequestModeRelease,
+ { "RequestModeRelease", "h245.RequestModeRelease", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestModeRelease sequence", HFILL }},
+ { &hf_h245_RequestModeReject,
+ { "RequestModeReject", "h245.RequestModeReject", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestModeReject sequence", HFILL }},
+ { &hf_h245_RequestModeAck,
+ { "RequestModeAck", "h245.RequestModeAck", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestModeAck sequence", HFILL }},
+ { &hf_h245_RequestMode,
+ { "RequestMode", "h245.RequestMode", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestMode sequence", HFILL }},
+ { &hf_h245_RequestMultiplexEntryRelease,
+ { "RequestMultiplexEntryRelease", "h245.RequestMultiplexEntryRelease", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestMultiplexEntryRelease sequence", HFILL }},
+ { &hf_h245_RequestMultiplexEntryRejectionDescriptions,
+ { "RequestMultiplexEntryRejectionDescriptions", "h245.RequestMultiplexEntryRejectionDescriptions", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestMultiplexEntryRejectionDescriptions sequence", HFILL }},
+ { &hf_h245_RequestMultiplexEntryReject,
+ { "RequestMultiplexEntryReject", "h245.RequestMultiplexEntryReject", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestMultiplexEntryReject sequence", HFILL }},
+ { &hf_h245_RequestMultiplexEntryAck,
+ { "RequestMultiplexEntryAck", "h245.RequestMultiplexEntryAck", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestMultiplexEntryAck sequence", HFILL }},
+ { &hf_h245_RequestMultiplexEntry,
+ { "RequestMultiplexEntry", "h245.RequestMultiplexEntry", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestMultiplexEntry sequence", HFILL }},
+ { &hf_h245_MultiplexEntrySendRelease,
+ { "MultiplexEntrySendRelease", "h245.MultiplexEntrySendRelease", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexEntrySendRelease sequence", HFILL }},
+ { &hf_h245_MultiplexEntryRejectionDescriptions,
+ { "MultiplexEntryRejectionDescriptions", "h245.MultiplexEntryRejectionDescriptions", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexEntryRejectionDescriptions sequence", HFILL }},
+ { &hf_h245_MultiplexEntrySendReject,
+ { "MultiplexEntrySendReject", "h245.MultiplexEntrySendReject", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexEntrySendReject sequence", HFILL }},
+ { &hf_h245_MultiplexEntrySendAck,
+ { "MultiplexEntrySendAck", "h245.MultiplexEntrySendAck", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexEntrySendAck sequence", HFILL }},
+ { &hf_h245_MultiplexElement,
+ { "MultiplexElement", "h245.MultiplexElement", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexElement sequence", HFILL }},
+ { &hf_h245_MultiplexEntryDescriptor,
+ { "MultiplexEntryDescriptor", "h245.MultiplexEntryDescriptor", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexEntryDescriptor sequence", HFILL }},
+ { &hf_h245_MultiplexEntrySend,
+ { "MultiplexEntrySend", "h245.MultiplexEntrySend", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexEntrySend sequence", HFILL }},
+ { &hf_h245_RequestChannelCloseRelease,
+ { "RequestChannelCloseRelease", "h245.RequestChannelCloseRelease", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestChannelCloseRelease sequence", HFILL }},
+ { &hf_h245_RequestChannelCloseReject,
+ { "RequestChannelCloseReject", "h245.RequestChannelCloseReject", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestChannelCloseReject sequence", HFILL }},
+ { &hf_h245_RequestChannelCloseAck,
+ { "RequestChannelCloseAck", "h245.RequestChannelCloseAck", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestChannelCloseAck sequence", HFILL }},
+ { &hf_h245_RequestChannelClose,
+ { "RequestChannelClose", "h245.RequestChannelClose", FT_NONE, BASE_NONE,
+ NULL, 0, "RequestChannelClose sequence", HFILL }},
+ { &hf_h245_CloseLogicalChannelAck,
+ { "CloseLogicalChannelAck", "h245.CloseLogicalChannelAck", FT_NONE, BASE_NONE,
+ NULL, 0, "CloseLogicalChannelAck sequence", HFILL }},
+ { &hf_h245_CloseLogicalChannel,
+ { "CloseLogicalChannel", "h245.CloseLogicalChannel", FT_NONE, BASE_NONE,
+ NULL, 0, "CloseLogicalChannel sequence", HFILL }},
+ { &hf_h245_H2250LogicalChannelAckParameters,
+ { "H2250LogicalChannelAckParameters", "h245.H2250LogicalChannelAckParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H2250LogicalChannelAckParameters sequence", HFILL }},
+ { &hf_h245_OpenLogicalChannelReject,
+ { "OpenLogicalChannelReject", "h245.OpenLogicalChannelReject", FT_NONE, BASE_NONE,
+ NULL, 0, "OpenLogicalChannelReject sequence", HFILL }},
+ { &hf_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters,
+ { "OpenLogicalChannelAck_reverseLogicalChannelParameters", "h245.OpenLogicalChannelAck_reverseLogicalChannelParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "OpenLogicalChannelAck_reverseLogicalChannelParameters sequence", HFILL }},
+ { &hf_h245_OpenLogicalChannelAck,
+ { "OpenLogicalChannelAck", "h245.OpenLogicalChannelAck", FT_NONE, BASE_NONE,
+ NULL, 0, "OpenLogicalChannelAck sequence", HFILL }},
+ { &hf_h245_EscrowData,
+ { "EscrowData", "h245.EscrowData", FT_NONE, BASE_NONE,
+ NULL, 0, "EscrowData sequence", HFILL }},
+ { &hf_h245_EncryptionSync,
+ { "EncryptionSync", "h245.EncryptionSync", FT_NONE, BASE_NONE,
+ NULL, 0, "EncryptionSync sequence", HFILL }},
+ { &hf_h245_MulticastAddress_iP6Address,
+ { "MulticastAddress_iP6Address", "h245.MulticastAddress_iP6Address", FT_NONE, BASE_NONE,
+ NULL, 0, "MulticastAddress_iP6Address sequence", HFILL }},
+ { &hf_h245_MulticastAddress_iPAddress,
+ { "MulticastAddress_iPAddress", "h245.MulticastAddress_iPAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "MulticastAddress_iPAddress sequence", HFILL }},
+ { &hf_h245_UnicastAddress_iPSourceRouteAddress,
+ { "UnicastAddress_iPSourceRouteAddress", "h245.UnicastAddress_iPSourceRouteAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "UnicastAddress_iPSourceRouteAddress sequence", HFILL }},
+ { &hf_h245_UnicastAddress_iP6Address,
+ { "UnicastAddress_iP6Address", "h245.UnicastAddress_iP6Address", FT_NONE, BASE_NONE,
+ NULL, 0, "UnicastAddress_iP6Address sequence", HFILL }},
+ { &hf_h245_UnicastAddress_iPXAddress,
+ { "UnicastAddress_iPXAddress", "h245.UnicastAddress_iPXAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "UnicastAddress_iPXAddress sequence", HFILL }},
+ { &hf_h245_UnicastAddress_iPAddress,
+ { "UnicastAddress_iPAddress", "h245.UnicastAddress_iPAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "UnicastAddress_iPAddress sequence", HFILL }},
+ { &hf_h245_FECData_rfc2733_mode_separateStream_samePort,
+ { "FECData_rfc2733_mode_separateStream_samePort", "h245.FECData_rfc2733_mode_separateStream_samePort", FT_NONE, BASE_NONE,
+ NULL, 0, "FECData_rfc2733_mode_separateStream_samePort sequence", HFILL }},
+ { &hf_h245_FECData_rfc2733_mode_separateStream_differentPort,
+ { "FECData_rfc2733_mode_separateStream_differentPort", "h245.FECData_rfc2733_mode_separateStream_differentPort", FT_NONE, BASE_NONE,
+ NULL, 0, "FECData_rfc2733_mode_separateStream_differentPort sequence", HFILL }},
+ { &hf_h245_FECData_rfc2733,
+ { "FECData_rfc2733", "h245.FECData_rfc2733", FT_NONE, BASE_NONE,
+ NULL, 0, "FECData_rfc2733 sequence", HFILL }},
+ { &hf_h245_MultiplePayloadStreamElement,
+ { "MultiplePayloadStreamElement", "h245.MultiplePayloadStreamElement", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplePayloadStreamElement sequence", HFILL }},
+ { &hf_h245_MultiplePayloadStream,
+ { "MultiplePayloadStream", "h245.MultiplePayloadStream", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplePayloadStream sequence", HFILL }},
+ { &hf_h245_RedundancyEncodingElement,
+ { "RedundancyEncodingElement", "h245.RedundancyEncodingElement", FT_NONE, BASE_NONE,
+ NULL, 0, "RedundancyEncodingElement sequence", HFILL }},
+ { &hf_h245_RedundancyEncoding_rtpRedundancyEncoding,
+ { "RedundancyEncoding_rtpRedundancyEncoding", "h245.RedundancyEncoding_rtpRedundancyEncoding", FT_NONE, BASE_NONE,
+ NULL, 0, "RedundancyEncoding_rtpRedundancyEncoding sequence", HFILL }},
+ { &hf_h245_RedundancyEncoding,
+ { "RedundancyEncoding", "h245.RedundancyEncoding", FT_NONE, BASE_NONE,
+ NULL, 0, "RedundancyEncoding sequence", HFILL }},
+ { &hf_h245_RTPPayloadType,
+ { "RTPPayloadType", "h245.RTPPayloadType", FT_NONE, BASE_NONE,
+ NULL, 0, "RTPPayloadType sequence", HFILL }},
+ { &hf_h245_H2250LogicalChannelParameters,
+ { "H2250LogicalChannelParameters", "h245.H2250LogicalChannelParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H2250LogicalChannelParameters sequence", HFILL }},
+ { &hf_h245_V76HDLCParameters,
+ { "V76HDLCParameters", "h245.V76HDLCParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "V76HDLCParameters sequence", HFILL }},
+ { &hf_h245_V76LogicalChannelParameters_mode_eRM,
+ { "V76LogicalChannelParameters_mode_eRM", "h245.V76LogicalChannelParameters_mode_eRM", FT_NONE, BASE_NONE,
+ NULL, 0, "V76LogicalChannelParameters_mode_eRM sequence", HFILL }},
+ { &hf_h245_V76LogicalChannelParameters,
+ { "V76LogicalChannelParameters", "h245.V76LogicalChannelParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "V76LogicalChannelParameters sequence", HFILL }},
+ { &hf_h245_H223AnnexCArqParameters,
+ { "H223AnnexCArqParameters", "h245.H223AnnexCArqParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H223AnnexCArqParameters sequence", HFILL }},
+ { &hf_h245_H223AL3MParameters,
+ { "H223AL3MParameters", "h245.H223AL3MParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H223AL3MParameters sequence", HFILL }},
+ { &hf_h245_H223AL2MParameters,
+ { "H223AL2MParameters", "h245.H223AL2MParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H223AL2MParameters sequence", HFILL }},
+ { &hf_h245_H223AL1MParameters,
+ { "H223AL1MParameters", "h245.H223AL1MParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H223AL1MParameters sequence", HFILL }},
+ { &hf_h245_H223LogicalChannelParameters_adaptionLayerType_al3,
+ { "H223LogicalChannelParameters_adaptionLayerType_al3", "h245.H223LogicalChannelParameters_adaptionLayerType_al3", FT_NONE, BASE_NONE,
+ NULL, 0, "H223LogicalChannelParameters_adaptionLayerType_al3 sequence", HFILL }},
+ { &hf_h245_H223LogicalChannelParameters,
+ { "H223LogicalChannelParameters", "h245.H223LogicalChannelParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H223LogicalChannelParameters sequence", HFILL }},
+ { &hf_h245_H222LogicalChannelParameters,
+ { "H222LogicalChannelParameters", "h245.H222LogicalChannelParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "H222LogicalChannelParameters sequence", HFILL }},
+ { &hf_h245_MultiplexedStreamParameter,
+ { "MultiplexedStreamParameter", "h245.MultiplexedStreamParameter", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexedStreamParameter sequence", HFILL }},
+ { &hf_h245_H235Media,
+ { "H235Media", "h245.H235Media", FT_NONE, BASE_NONE,
+ NULL, 0, "H235Media sequence", HFILL }},
+ { &hf_h245_V75Parameters,
+ { "V75Parameters", "h245.V75Parameters", FT_NONE, BASE_NONE,
+ NULL, 0, "V75Parameters sequence", HFILL }},
+ { &hf_h245_Q2931Address,
+ { "Q2931Address", "h245.Q2931Address", FT_NONE, BASE_NONE,
+ NULL, 0, "Q2931Address sequence", HFILL }},
+ { &hf_h245_NetworkAccessParameters,
+ { "NetworkAccessParameters", "h245.NetworkAccessParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "NetworkAccessParameters sequence", HFILL }},
+ { &hf_h245_reverseLogicalChannelParameters,
+ { "reverseLogicalChannelParameters", "h245.reverseLogicalChannelParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "reverseLogicalChannelParameters sequence", HFILL }},
+ { &hf_h245_forwardLogicalChannelParameters,
+ { "forwardLogicalChannelParameters", "h245.forwardLogicalChannelParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "forwardLogicalChannelParameters sequence", HFILL }},
+ { &hf_h245_OpenLogicalChannel,
+ { "OpenLogicalChannel", "h245.OpenLogicalChannel", FT_NONE, BASE_NONE,
+ NULL, 0, "OpenLogicalChannel sequence", HFILL }},
+ { &hf_h245_FECCapability_rfc2733_separateStream,
+ { "FECCapability_rfc2733_separateStream", "h245.FECCapability_rfc2733_separateStream", FT_NONE, BASE_NONE,
+ NULL, 0, "FECCapability_rfc2733_separateStream sequence", HFILL }},
+ { &hf_h245_FECCapability_rfc2733,
+ { "FECCapability_rfc2733", "h245.FECCapability_rfc2733", FT_NONE, BASE_NONE,
+ NULL, 0, "FECCapability_rfc2733 sequence", HFILL }},
+ { &hf_h245_MultiplePayloadStreamCapability,
+ { "MultiplePayloadStreamCapability", "h245.MultiplePayloadStreamCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplePayloadStreamCapability sequence", HFILL }},
+ { &hf_h245_NoPTAudioToneCapability,
+ { "NoPTAudioToneCapability", "h245.NoPTAudioToneCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "NoPTAudioToneCapability sequence", HFILL }},
+ { &hf_h245_NoPTAudioTelephonyEventCapability,
+ { "NoPTAudioTelephonyEventCapability", "h245.NoPTAudioTelephonyEventCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "NoPTAudioTelephonyEventCapability sequence", HFILL }},
+ { &hf_h245_AudioToneCapability,
+ { "AudioToneCapability", "h245.AudioToneCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "AudioToneCapability sequence", HFILL }},
+ { &hf_h245_AudioTelephonyEventCapability,
+ { "AudioTelephonyEventCapability", "h245.AudioTelephonyEventCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "AudioTelephonyEventCapability sequence", HFILL }},
+ { &hf_h245_MultiplexedStreamCapability,
+ { "MultiplexedStreamCapability", "h245.MultiplexedStreamCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "MultiplexedStreamCapability sequence", HFILL }},
+ { &hf_h245_GenericParameter,
+ { "GenericParameter", "h245.GenericParameter", FT_NONE, BASE_NONE,
+ NULL, 0, "GenericParameter sequence", HFILL }},
+ { &hf_h245_GenericCapability,
+ { "GenericCapability", "h245.GenericCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "GenericCapability sequence", HFILL }},
+ { &hf_h245_ConferenceCapability,
+ { "ConferenceCapability", "h245.ConferenceCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "ConferenceCapability sequence", HFILL }},
+ { &hf_h245_IntegrityCapability,
+ { "IntegrityCapability", "h245.IntegrityCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "IntegrityCapability sequence", HFILL }},
+ { &hf_h245_AuthenticationCapability,
+ { "AuthenticationCapability", "h245.AuthenticationCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "AuthenticationCapability sequence", HFILL }},
+ { &hf_h245_EncryptionAuthenticationAndIntegrity,
+ { "EncryptionAuthenticationAndIntegrity", "h245.EncryptionAuthenticationAndIntegrity", FT_NONE, BASE_NONE,
+ NULL, 0, "EncryptionAuthenticationAndIntegrity sequence", HFILL }},
+ { &hf_h245_T38FaxTcpOptions,
+ { "T38FaxTcpOptions", "h245.T38FaxTcpOptions", FT_NONE, BASE_NONE,
+ NULL, 0, "T38FaxTcpOptions sequence", HFILL }},
+ { &hf_h245_T38FaxUdpOptions,
+ { "T38FaxUdpOptions", "h245.T38FaxUdpOptions", FT_NONE, BASE_NONE,
+ NULL, 0, "T38FaxUdpOptions sequence", HFILL }},
+ { &hf_h245_T38FaxProfile,
+ { "T38FaxProfile", "h245.T38FaxProfile", FT_NONE, BASE_NONE,
+ NULL, 0, "T38FaxProfile sequence", HFILL }},
+ { &hf_h245_T84Profile_t84Restricted,
+ { "T84Profile_t84Restricted", "h245.T84Profile_t84Restricted", FT_NONE, BASE_NONE,
+ NULL, 0, "T84Profile_t84Restricted sequence", HFILL }},
+ { &hf_h245_V42bis,
+ { "V42bis", "h245.V42bis", FT_NONE, BASE_NONE,
+ NULL, 0, "V42bis sequence", HFILL }},
+ { &hf_h245_DataApplicationCapability_application_t38fax,
+ { "DataApplicationCapability_application_t38fax", "h245.DataApplicationCapability_application_t38fax", FT_NONE, BASE_NONE,
+ NULL, 0, "DataApplicationCapability_application_t38fax sequence", HFILL }},
+ { &hf_h245_DataApplicationCapability_application_nlpid,
+ { "DataApplicationCapability_application_nlpid", "h245.DataApplicationCapability_application_nlpid", FT_NONE, BASE_NONE,
+ NULL, 0, "DataApplicationCapability_application_nlpid sequence", HFILL }},
+ { &hf_h245_DataApplicationCapability_application_t84,
+ { "DataApplicationCapability_application_t84", "h245.DataApplicationCapability_application_t84", FT_NONE, BASE_NONE,
+ NULL, 0, "DataApplicationCapability_application_t84 sequence", HFILL }},
+ { &hf_h245_DataApplicationCapability,
+ { "DataApplicationCapability", "h245.DataApplicationCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "DataApplicationCapability sequence", HFILL }},
+ { &hf_h245_VBDCapability,
+ { "VBDCapability", "h245.VBDCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "VBDCapability sequence", HFILL }},
+ { &hf_h245_GSMAudioCapability,
+ { "GSMAudioCapability", "h245.GSMAudioCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "GSMAudioCapability sequence", HFILL }},
+ { &hf_h245_IS13818AudioCapability,
+ { "IS13818AudioCapability", "h245.IS13818AudioCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "IS13818AudioCapability sequence", HFILL }},
+ { &hf_h245_IS11172AudioCapability,
+ { "IS11172AudioCapability", "h245.IS11172AudioCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "IS11172AudioCapability sequence", HFILL }},
+ { &hf_h245_G7231AnnexCCapability_g723AnnexCAudioMode,
+ { "G7231AnnexCCapability_g723AnnexCAudioMode", "h245.G7231AnnexCCapability_g723AnnexCAudioMode", FT_NONE, BASE_NONE,
+ NULL, 0, "G7231AnnexCCapability_g723AnnexCAudioMode sequence", HFILL }},
+ { &hf_h245_G7231AnnexCCapability,
+ { "G7231AnnexCCapability", "h245.G7231AnnexCCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "G7231AnnexCCapability sequence", HFILL }},
+ { &hf_h245_G729Extensions,
+ { "G729Extensions", "h245.G729Extensions", FT_NONE, BASE_NONE,
+ NULL, 0, "G729Extensions sequence", HFILL }},
+ { &hf_h245_AudioCapability_g7231,
+ { "AudioCapability_g7231", "h245.AudioCapability_g7231", FT_NONE, BASE_NONE,
+ NULL, 0, "AudioCapability_g7231 sequence", HFILL }},
+ { &hf_h245_IS11172VideoCapability,
+ { "IS11172VideoCapability", "h245.IS11172VideoCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "IS11172VideoCapability sequence", HFILL }},
+ { &hf_h245_H263Version3Options,
+ { "H263Version3Options", "h245.H263Version3Options", FT_NONE, BASE_NONE,
+ NULL, 0, "H263Version3Options sequence", HFILL }},
+ { &hf_h245_H263ModeComboFlags,
+ { "H263ModeComboFlags", "h245.H263ModeComboFlags", FT_NONE, BASE_NONE,
+ NULL, 0, "H263ModeComboFlags sequence", HFILL }},
+ { &hf_h245_H263VideoModeCombos,
+ { "H263VideoModeCombos", "h245.H263VideoModeCombos", FT_NONE, BASE_NONE,
+ NULL, 0, "H263VideoModeCombos sequence", HFILL }},
+ { &hf_h245_CustomPictureFormat_pixelAspectInformation_extendedPAR,
+ { "CustomPictureFormat_pixelAspectInformation_extendedPAR", "h245.CustomPictureFormat_pixelAspectInformation_extendedPAR", FT_NONE, BASE_NONE,
+ NULL, 0, "CustomPictureFormat_pixelAspectInformation_extendedPAR sequence", HFILL }},
+ { &hf_h245_CustomPictureFormat_mPI_customPCF,
+ { "CustomPictureFormat_mPI_customPCF", "h245.CustomPictureFormat_mPI_customPCF", FT_NONE, BASE_NONE,
+ NULL, 0, "CustomPictureFormat_mPI_customPCF sequence", HFILL }},
+ { &hf_h245_CustomPictureFormat_mPI,
+ { "CustomPictureFormat_mPI", "h245.CustomPictureFormat_mPI", FT_NONE, BASE_NONE,
+ NULL, 0, "CustomPictureFormat_mPI sequence", HFILL }},
+ { &hf_h245_CustomPictureFormat,
+ { "CustomPictureFormat", "h245.CustomPictureFormat", FT_NONE, BASE_NONE,
+ NULL, 0, "CustomPictureFormat sequence", HFILL }},
+ { &hf_h245_CustomPictureClockFrequency,
+ { "CustomPictureClockFrequency", "h245.CustomPictureClockFrequency", FT_NONE, BASE_NONE,
+ NULL, 0, "CustomPictureClockFrequency sequence", HFILL }},
+ { &hf_h245_RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters,
+ { "RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters", "h245.RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters sequence", HFILL }},
+ { &hf_h245_RefPictureSelection_enhancedReferencePicSelect,
+ { "RefPictureSelection_enhancedReferencePicSelect", "h245.RefPictureSelection_enhancedReferencePicSelect", FT_NONE, BASE_NONE,
+ NULL, 0, "RefPictureSelection_enhancedReferencePicSelect sequence", HFILL }},
+ { &hf_h245_RefPictureSelection_additionalPictureMemory,
+ { "RefPictureSelection_additionalPictureMemory", "h245.RefPictureSelection_additionalPictureMemory", FT_NONE, BASE_NONE,
+ NULL, 0, "RefPictureSelection_additionalPictureMemory sequence", HFILL }},
+ { &hf_h245_RefPictureSelection,
+ { "RefPictureSelection", "h245.RefPictureSelection", FT_NONE, BASE_NONE,
+ NULL, 0, "RefPictureSelection sequence", HFILL }},
+ { &hf_h245_TransperencyParameters,
+ { "TransperencyParameters", "h245.TransperencyParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "TransperencyParameters sequence", HFILL }},
+ { &hf_h245_H263Options,
+ { "H263Options", "h245.H263Options", FT_NONE, BASE_NONE,
+ NULL, 0, "H263Options sequence", HFILL }},
+ { &hf_h245_EnhancementOptions,
+ { "EnhancementOptions", "h245.EnhancementOptions", FT_NONE, BASE_NONE,
+ NULL, 0, "EnhancementOptions sequence", HFILL }},
+ { &hf_h245_BEnhancementParameters,
+ { "BEnhancementParameters", "h245.BEnhancementParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "BEnhancementParameters sequence", HFILL }},
+ { &hf_h245_EnhancementLayerInfo,
+ { "EnhancementLayerInfo", "h245.EnhancementLayerInfo", FT_NONE, BASE_NONE,
+ NULL, 0, "EnhancementLayerInfo sequence", HFILL }},
+ { &hf_h245_H263VideoCapability,
+ { "H263VideoCapability", "h245.H263VideoCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "H263VideoCapability sequence", HFILL }},
+ { &hf_h245_H262VideoCapability,
+ { "H262VideoCapability", "h245.H262VideoCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "H262VideoCapability sequence", HFILL }},
+ { &hf_h245_H261VideoCapability,
+ { "H261VideoCapability", "h245.H261VideoCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "H261VideoCapability sequence", HFILL }},
+ { &hf_h245_MediaDistributionCapability,
+ { "MediaDistributionCapability", "h245.MediaDistributionCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "MediaDistributionCapability sequence", HFILL }},
+ { &hf_h245_MultipointCapability,
+ { "MultipointCapability", "h245.MultipointCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "MultipointCapability sequence", HFILL }},
+ { &hf_h245_receiveMultipointCapability,
+ { "receiveMultipointCapability", "h245.receiveMultipointCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "Receive MultipointCapability sequence", HFILL }},
+ { &hf_h245_transmitMultipointCapability,
+ { "transmitMultipointCapability", "h245.transmitMultipointCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "Transmit MultipointCapability sequence", HFILL }},
+ { &hf_h245_receiveAndTransmitMultipointCapability,
+ { "receiveAndTransmitMultipointCapability", "h245.receiveAndTransmitMultipointCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "Receive And Transmit MultipointCapability sequence", HFILL }},
+ { &hf_h245_RTPH263VideoRedundancyFrameMapping,
+ { "RTPH263VideoRedundancyFrameMapping", "h245.RTPH263VideoRedundancyFrameMapping", FT_NONE, BASE_NONE,
+ NULL, 0, "RTPH263VideoRedundancyFrameMapping sequence", HFILL }},
+ { &hf_h245_RTPH263VideoRedundancyEncoding,
+ { "RTPH263VideoRedundancyEncoding", "h245.RTPH263VideoRedundancyEncoding", FT_NONE, BASE_NONE,
+ NULL, 0, "RTPH263VideoRedundancyEncoding sequence", HFILL }},
+ { &hf_h245_RedundancyEncodingCapability,
+ { "RedundancyEncodingCapability", "h245.RedundancyEncodingCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "RedundancyEncodingCapability sequence", HFILL }},
+ { &hf_h245_TransportCapability,
+ { "TransportCapability", "h245.TransportCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "TransportCapability sequence", HFILL }},
+ { &hf_h245_MediaChannelCapability,
+ { "MediaChannelCapability", "h245.MediaChannelCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "MediaChannelCapability sequence", HFILL }},
+ { &hf_h245_MediaTransportType_AtmAAL5Compressed,
+ { "MediaTransportType_AtmAAL5Compressed", "h245.MediaTransportType_AtmAAL5Compressed", FT_NONE, BASE_NONE,
+ NULL, 0, "MediaTransportType_AtmAAL5Compressed sequence", HFILL }},
+ { &hf_h245_QOSCapability,
+ { "QOSCapability", "h245.QOSCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "QOSCapability sequence", HFILL }},
+ { &hf_h245_ATMParameters,
+ { "ATMParameters", "h245.ATMParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "ATMParameters sequence", HFILL }},
+ { &hf_h245_RSVPParameters,
+ { "RSVPParameters", "h245.RSVPParameters", FT_NONE, BASE_NONE,
+ NULL, 0, "RSVPParameters sequence", HFILL }},
+ { &hf_h245_MediaPacketizationCapability,
+ { "MediaPacketizationCapability", "h245.MediaPacketizationCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "MediaPacketizationCapability sequence", HFILL }},
+ { &hf_h245_H2250Capability_mcCapability,
+ { "H2250Capability_mcCapability", "h245.H2250Capability_mcCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "H2250Capability_mcCapability sequence", HFILL }},
+ { &hf_h245_H2250Capability,
+ { "H2250Capability", "h245.H2250Capability", FT_NONE, BASE_NONE,
+ NULL, 0, "H2250Capability sequence", HFILL }},
+ { &hf_h245_V75Capability,
+ { "V75Capability", "h245.V75Capability", FT_NONE, BASE_NONE,
+ NULL, 0, "V75Capability sequence", HFILL }},
+ { &hf_h245_V76Capability,
+ { "V76Capability", "h245.V76Capability", FT_NONE, BASE_NONE,
+ NULL, 0, "V76Capability sequence", HFILL }},
+ { &hf_h245_H223AnnexCCapability,
+ { "H223AnnexCCapability", "h245.H223AnnexCCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "H223AnnexCCapability sequence", HFILL }},
+ { &hf_h245_H223Capability_mobileMultilinkFrameCapability,
+ { "H223Capability_mobileMultilinkFrameCapability", "h245.H223Capability_mobileMultilinkFrameCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "H223Capability_mobileMultilinkFrameCapability sequence", HFILL }},
+ { &hf_h245_H223Capability_mobileOperationTransmitCapability,
+ { "H223Capability_mobileOperationTransmitCapability", "h245.H223Capability_mobileOperationTransmitCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "H223Capability_mobileOperationTransmitCapability sequence", HFILL }},
+ { &hf_h245_H223Capability_h223MultiplexTableCapability_enhanced,
+ { "H223Capability_h223MultiplexTableCapability_enhanced", "h245.H223Capability_h223MultiplexTableCapability_enhanced", FT_NONE, BASE_NONE,
+ NULL, 0, "H223Capability_h223MultiplexTableCapability_enhanced sequence", HFILL }},
+ { &hf_h245_H223Capability,
+ { "H223Capability", "h245.H223Capability", FT_NONE, BASE_NONE,
+ NULL, 0, "H223Capability sequence", HFILL }},
+ { &hf_h245_VCCapability_aal1ViaGateway,
+ { "VCCapability_aal1ViaGateway", "h245.VCCapability_aal1ViaGateway", FT_NONE, BASE_NONE,
+ NULL, 0, "VCCapability_aal1ViaGateway sequence", HFILL }},
+ { &hf_h245_VCCapability_availableBitRates_rangeOfBitRates,
+ { "VCCapability_availableBitRates_rangeOfBitRates", "h245.VCCapability_availableBitRates_rangeOfBitRates", FT_NONE, BASE_NONE,
+ NULL, 0, "VCCapability_availableBitRates_rangeOfBitRates sequence", HFILL }},
+ { &hf_h245_VCCapability_availableBitRates,
+ { "VCCapability_availableBitRates", "h245.VCCapability_availableBitRates", FT_NONE, BASE_NONE,
+ NULL, 0, "VCCapability_availableBitRates sequence", HFILL }},
+ { &hf_h245_VCCapability_aal5,
+ { "VCCapability_aal5", "h245.VCCapability_aal5", FT_NONE, BASE_NONE,
+ NULL, 0, "VCCapability_aal5 sequence", HFILL }},
+ { &hf_h245_VCCapability_aal1,
+ { "VCCapability_aal1", "h245.VCCapability_aal1", FT_NONE, BASE_NONE,
+ NULL, 0, "VCCapability_aal1 sequence", HFILL }},
+ { &hf_h245_VCCapability,
+ { "VCCapability", "h245.VCCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "VCCapability sequence", HFILL }},
+ { &hf_h245_H222Capability,
+ { "H222Capability", "h245.H222Capability", FT_NONE, BASE_NONE,
+ NULL, 0, "H222Capability sequence", HFILL }},
+ { &hf_h245_H235SecurityCapability,
+ { "H235SecurityCapability", "h245.H235SecurityCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "H235SecurityCapability sequence", HFILL }},
+ { &hf_h245_Capability_h233EncryptionReceiveCapability,
+ { "Capability_h233EncryptionReceiveCapability", "h245.Capability_h233EncryptionReceiveCapability", FT_NONE, BASE_NONE,
+ NULL, 0, "Capability_h233EncryptionReceiveCapability sequence", HFILL }},
+ { &hf_h245_TerminalCapabilitySetRelease,
+ { "TerminalCapabilitySetRelease", "h245.TerminalCapabilitySetRelease", FT_NONE, BASE_NONE,
+ NULL, 0, "TerminalCapabilitySetRelease sequence", HFILL }},
+ { &hf_h245_TerminalCapabilitySetReject,
+ { "TerminalCapabilitySetReject", "h245.TerminalCapabilitySetReject", FT_NONE, BASE_NONE,
+ NULL, 0, "TerminalCapabilitySetReject sequence", HFILL }},
+ { &hf_h245_TerminalCapabilitySetAck,
+ { "TerminalCapabilitySetAck", "h245.TerminalCapabilitySetAck", FT_NONE, BASE_NONE,
+ NULL, 0, "TerminalCapabilitySetAck sequence", HFILL }},
+ { &hf_h245_CapabilityDescriptor,
+ { "CapabilityDescriptor", "h245.CapabilityDescriptor", FT_NONE, BASE_NONE,
+ NULL, 0, "CapabilityDescriptor sequence", HFILL }},
+ { &hf_h245_CapabilityTableEntry,
+ { "CapabilityTableEntry", "h245.CapabilityTableEntry", FT_NONE, BASE_NONE,
+ NULL, 0, "CapabilityTableEntry sequence", HFILL }},
+ { &hf_h245_TerminalCapabilitySet,
+ { "TerminalCapabilitySet", "h245.TerminalCapabilitySet", FT_NONE, BASE_NONE,
+ NULL, 0, "TerminalCapabilitySet sequence", HFILL }},
+ { &hf_h245_MasterSlaveDeterminationRelease,
+ { "MasterSlaveDeterminationRelease", "h245.MasterSlaveDeterminationRelease", FT_NONE, BASE_NONE,
+ NULL, 0, "MasterSlaveDeterminationRelease sequence", HFILL }},
+ { &hf_h245_MasterSlaveDeterminationReject,
+ { "MasterSlaveDeterminationReject", "h245.MasterSlaveDeterminationReject", FT_NONE, BASE_NONE,
+ NULL, 0, "MasterSlaveDeterminationReject sequence", HFILL }},
+ { &hf_h245_MasterSlaveDeterminationAck,
+ { "MasterSlaveDeterminationAck", "h245.MasterSlaveDeterminationAck", FT_NONE, BASE_NONE,
+ NULL, 0, "MasterSlaveDeterminationAck sequence", HFILL }},
+ { &hf_h245_MasterSlaveDetermination,
+ { "MasterSlaveDetermination", "h245.MasterSlaveDetermination", FT_NONE, BASE_NONE,
+ NULL, 0, "MasterSlaveDetermination sequence", HFILL }},
+ { &hf_h245_h221NonStandard,
+ { "h221NonStandard", "h245.h221NonStandard", FT_NONE, BASE_NONE,
+ NULL, 0, "h221NonStandard sequence", HFILL }},
+ { &hf_h245_NonStandardParameter,
+ { "NonStandardParameter", "h245.NonStandardParameter", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardParameter sequence", HFILL }},
+ { &hf_h245_NonStandardMessage,
+ { "NonStandardMessage", "h245.NonStandardMessage", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardMessage sequence", HFILL }},
+ { &hf_h245_FlowControlIndication_restriction,
+ { "FlowControlIndication_restriction", "h245.FlowControlIndication_restriction_type", FT_UINT32, BASE_DEC,
+ VALS(FlowControlIndication_restriction_vals), 0, "FlowControlIndication_restriction choice", HFILL }},
+ { &hf_h245_FlowControlIndication_scope,
+ { "FlowControlIndication_scope", "h245.FlowControlIndication_scope_type", FT_UINT32, BASE_DEC,
+ VALS(FlowControlIndication_scope_vals), 0, "FlowControlIndication_scope choice", HFILL }},
+ { &hf_h245_UserInputIndication_userInputSupportIndication,
+ { "UserInputIndication_userInputSupportIndication type", "h245.UserInputIndication_userInputSupportIndication_type", FT_UINT32, BASE_DEC,
+ VALS(UserInputIndication_userInputSupportIndication_vals), 0, "Type of UserInputIndication_userInputSupportIndication choice", HFILL }},
+ { &hf_h245_UserInputIndication,
+ { "UserInputIndication type", "h245.UserInputIndication_type", FT_UINT32, BASE_DEC,
+ VALS(UserInputIndication_vals), 0, "Type of UserInputIndication choice", HFILL }},
+ { &hf_h245_NewATMVCIndication_reverseParameters_multiplex,
+ { "NewATMVCIndication_reverseParameters_multiplex type", "h245.NewATMVCIndication_reverseParameters_multiplex_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCIndication_reverseParameters_multiplex_vals), 0, "Type of NewATMVCIndication_reverseParameters_multiplex choice", HFILL }},
+ { &hf_h245_NewATMVCIndication_multiplex,
+ { "NewATMVCIndication_multiplex type", "h245.NewATMVCIndication_multiplex_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCIndication_multiplex_vals), 0, "Type of NewATMVCIndication_multiplex choice", HFILL }},
+ { &hf_h245_NewATMVCIndication_aal_aal1_errorCorrection,
+ { "NewATMVCIndication_aal_aal1_errorCorrection type", "h245.NewATMVCIndication_aal_aal1_errorCorrection_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCIndication_aal_aal1_errorCorrection_vals), 0, "Type of NewATMVCIndication_aal_aal1_errorCorrection choice", HFILL }},
+ { &hf_h245_NewATMVCIndication_aal_aal1_clockRecovery,
+ { "NewATMVCIndication_aal_aal1_clockRecovery type", "h245.NewATMVCIndication_aal_aal1_clockRecovery_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCIndication_aal_aal1_clockRecovery_vals), 0, "Type of NewATMVCIndication_aal_aal1_clockRecovery choice", HFILL }},
+ { &hf_h245_NewATMVCIndication_aal,
+ { "NewATMVCIndication_aal type", "h245.NewATMVCIndication_aal_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCIndication_aal_vals), 0, "Type of NewATMVCIndication_aal choice", HFILL }},
+ { &hf_h245_JitterIndication_scope,
+ { "JitterIndication_scope type", "h245.JitterIndication_scope_type", FT_UINT32, BASE_DEC,
+ VALS(JitterIndication_scope_vals), 0, "Type of JitterIndication_scope choice", HFILL }},
+ { &hf_h245_MiscellaneousIndication_type,
+ { "MiscellaneousIndication_type type", "h245.MiscellaneousIndication_type_type", FT_UINT32, BASE_DEC,
+ VALS(MiscellaneousIndication_type_vals), 0, "Type of MiscellaneousIndication_type choice", HFILL }},
+ { &hf_h245_ConferenceIndication,
+ { "ConferenceIndication type", "h245.ConferenceIndication_type", FT_UINT32, BASE_DEC,
+ VALS(ConferenceIndication_vals), 0, "Type of ConferenceIndication choice", HFILL }},
+ { &hf_h245_FunctionNotSupported_cause,
+ { "FunctionNotSupported_cause type", "h245.FunctionNotSupported_cause_type", FT_UINT32, BASE_DEC,
+ VALS(FunctionNotSupported_cause_vals), 0, "Type of FunctionNotSupported_cause choice", HFILL }},
+ { &hf_h245_FunctionNotUnderstood,
+ { "FunctionNotUnderstood type", "h245.FunctionNotUnderstood_type", FT_UINT32, BASE_DEC,
+ VALS(FunctionNotUnderstood_vals), 0, "Type of FunctionNotUnderstood choice", HFILL }},
+ { &hf_h245_MobileMultilinkReconfigurationCommand_status,
+ { "MobileMultilinkReconfigurationCommand_status type", "h245.MobileMultilinkReconfigurationCommand_status_type", FT_UINT32, BASE_DEC,
+ VALS(MobileMultilinkReconfigurationCommand_status_vals), 0, "Type of MobileMultilinkReconfigurationCommand_status choice", HFILL }},
+ { &hf_h245_NewATMVCCommand_reverseParameters_multiplex,
+ { "NewATMVCCommand_reverseParameters_multiplex type", "h245.NewATMVCCommand_reverseParameters_multiplex_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCCommand_reverseParameters_multiplex_vals), 0, "Type of NewATMVCCommand_reverseParameters_multiplex choice", HFILL }},
+ { &hf_h245_NewATMVCCommand_multiplex,
+ { "NewATMVCCommand_multiplex type", "h245.NewATMVCCommand_multiplex_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCCommand_multiplex_vals), 0, "Type of NewATMVCCommand_multiplex choice", HFILL }},
+ { &hf_h245_NewATMVCCommand_aal_aal1_errorCorrection,
+ { "NewATMVCCommand_aal_aal1_errorCorrection type", "h245.NewATMVCCommand_aal_aal1_errorCorrection_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCCommand_aal_aal1_errorCorrection_vals), 0, "Type of NewATMVCCommand_aal_aal1_errorCorrection choice", HFILL }},
+ { &hf_h245_NewATMVCCommand_aal_aal1_clockRecovery,
+ { "NewATMVCCommand_aal_aal1_clockRecovery type", "h245.NewATMVCCommand_aal_aal1_clockRecovery_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCCommand_aal_aal1_clockRecovery_vals), 0, "Type of NewATMVCCommand_aal_aal1_clockRecovery choice", HFILL }},
+ { &hf_h245_NewATMVCCommand_aal,
+ { "NewATMVCCommand_aal type", "h245.NewATMVCCommand_aal_type", FT_UINT32, BASE_DEC,
+ VALS(NewATMVCCommand_aal_vals), 0, "Type of NewATMVCCommand_aal choice", HFILL }},
+ { &hf_h245_H223MultiplexReconfiguration_h223AnnexADoubleFlag,
+ { "H223MultiplexReconfiguration_h223AnnexADoubleFlag type", "h245.H223MultiplexReconfiguration_h223AnnexADoubleFlag_type", FT_UINT32, BASE_DEC,
+ VALS(H223MultiplexReconfiguration_h223AnnexADoubleFlag_vals), 0, "Type of H223MultiplexReconfiguration_h223AnnexADoubleFlag choice", HFILL }},
+ { &hf_h245_H223MultiplexReconfiguration_h223ModeChange,
+ { "H223MultiplexReconfiguration_h223ModeChange type", "h245.H223MultiplexReconfiguration_h223ModeChange_type", FT_UINT32, BASE_DEC,
+ VALS(H223MultiplexReconfiguration_h223ModeChange_vals), 0, "Type of H223MultiplexReconfiguration_h223ModeChange choice", HFILL }},
+ { &hf_h245_H223MultiplexReconfiguration,
+ { "H223MultiplexReconfiguration type", "h245.H223MultiplexReconfiguration_type", FT_UINT32, BASE_DEC,
+ VALS(H223MultiplexReconfiguration_vals), 0, "Type of H223MultiplexReconfiguration choice", HFILL }},
+ { &hf_h245_PictureReference,
+ { "PictureReference type", "h245.PictureReference_type", FT_UINT32, BASE_DEC,
+ VALS(PictureReference_vals), 0, "Type of PictureReference choice", HFILL }},
+ { &hf_h245_MiscellaneousCommand_type_progressiveRefinementStart_repeatCount,
+ { "MiscellaneousCommand_type_progressiveRefinementStart_repeatCount type", "h245.MiscellaneousCommand_type_progressiveRefinementStart_repeatCount_type", FT_UINT32, BASE_DEC,
+ VALS(MiscellaneousCommand_type_progressiveRefinementStart_repeatCount_vals), 0, "Type of MiscellaneousCommand_type_progressiveRefinementStart_repeatCount choice", HFILL }},
+ { &hf_h245_MiscellaneousCommand_type,
+ { "MiscellaneousCommand_type type", "h245.MiscellaneousCommand_type_type", FT_UINT32, BASE_DEC,
+ VALS(MiscellaneousCommand_type_vals), 0, "Type of MiscellaneousCommand_type choice", HFILL }},
+ { &hf_h245_ConferenceCommand,
+ { "ConferenceCommand type", "h245.ConferenceCommand_type", FT_UINT32, BASE_DEC,
+ VALS(ConferenceCommand_vals), 0, "Type of ConferenceCommand choice", HFILL }},
+ { &hf_h245_EndSessionCommand_gstnOptions,
+ { "EndSessionCommand_gstnOptions type", "h245.EndSessionCommand_gstnOptions_type", FT_UINT32, BASE_DEC,
+ VALS(EndSessionCommand_gstnOptions_vals), 0, "Type of EndSessionCommand_gstnOptions choice", HFILL }},
+ { &hf_h245_EndSessionCommand_isdnOptions,
+ { "EndSessionCommand_isdnOptions type", "h245.EndSessionCommand_isdnOptions_type", FT_UINT32, BASE_DEC,
+ VALS(EndSessionCommand_isdnOptions_vals), 0, "Type of EndSessionCommand_isdnOptions choice", HFILL }},
+ { &hf_h245_FlowControlCommand_restriction,
+ { "FlowControlCommand_restriction type", "h245.FlowControlCommand_restriction_type", FT_UINT32, BASE_DEC,
+ VALS(FlowControlCommand_restriction_vals), 0, "Type of FlowControlCommand_restriction choice", HFILL }},
+ { &hf_h245_FlowControlCommand_scope,
+ { "FlowControlCommand_scope type", "h245.FlowControlCommand_scope_type", FT_UINT32, BASE_DEC,
+ VALS(FlowControlCommand_scope_vals), 0, "Type of FlowControlCommand_scope choice", HFILL }},
+ { &hf_h245_EncryptionCommand,
+ { "EncryptionCommand type", "h245.EncryptionCommand_type", FT_UINT32, BASE_DEC,
+ VALS(EncryptionCommand_vals), 0, "Type of EncryptionCommand choice", HFILL }},
+ { &hf_h245_SendTerminalCapabilitySet,
+ { "SendTerminalCapabilitySet type", "h245.SendTerminalCapabilitySet_type", FT_UINT32, BASE_DEC,
+ VALS(SendTerminalCapabilitySet_vals), 0, "Type of SendTerminalCapabilitySet choice", HFILL }},
+ { &hf_h245_LogicalChannelRateRejectReason,
+ { "LogicalChannelRateRejectReason type", "h245.LogicalChannelRateRejectReason_type", FT_UINT32, BASE_DEC,
+ VALS(LogicalChannelRateRejectReason_vals), 0, "Type of LogicalChannelRateRejectReason choice", HFILL }},
+ { &hf_h245_DialingInformationNetworkType,
+ { "DialingInformationNetworkType type", "h245.DialingInformationNetworkType_type", FT_UINT32, BASE_DEC,
+ VALS(DialingInformationNetworkType_vals), 0, "Type of DialingInformationNetworkType choice", HFILL }},
+ { &hf_h245_DialingInformation,
+ { "DialingInformation type", "h245.DialingInformation_type", FT_UINT32, BASE_DEC,
+ VALS(DialingInformation_vals), 0, "Type of DialingInformation choice", HFILL }},
+ { &hf_h245_MultilinkIndication,
+ { "MultilinkIndication type", "h245.MultilinkIndication_type", FT_UINT32, BASE_DEC,
+ VALS(MultilinkIndication_vals), 0, "Type of MultilinkIndication choice", HFILL }},
+ { &hf_h245_MultilinkResponse_addConnection_responseCode_rejected,
+ { "MultilinkResponse_addConnection_responseCode_rejected type", "h245.MultilinkResponse_addConnection_responseCode_rejected_type", FT_UINT32, BASE_DEC,
+ VALS(MultilinkResponse_addConnection_responseCode_rejected_vals), 0, "Type of MultilinkResponse_addConnection_responseCode_rejected choice", HFILL }},
+ { &hf_h245_MultilinkResponse_addConnection_responseCode,
+ { "MultilinkResponse_addConnection_responseCode type", "h245.MultilinkResponse_addConnection_responseCode_type", FT_UINT32, BASE_DEC,
+ VALS(MultilinkResponse_addConnection_responseCode_vals), 0, "Type of MultilinkResponse_addConnection_responseCode choice", HFILL }},
+ { &hf_h245_MultilinkResponse,
+ { "MultilinkResponse type", "h245.MultilinkResponse_type", FT_UINT32, BASE_DEC,
+ VALS(MultilinkResponse_vals), 0, "Type of MultilinkResponse choice", HFILL }},
+ { &hf_h245_MultilinkRequest_maximumHeaderInterval_requestType,
+ { "MultilinkRequest_maximumHeaderInterval_requestType type", "h245.MultilinkRequest_maximumHeaderInterval_requestType_type", FT_UINT32, BASE_DEC,
+ VALS(MultilinkRequest_maximumHeaderInterval_requestType_vals), 0, "Type of MultilinkRequest_maximumHeaderInterval_requestType choice", HFILL }},
+ { &hf_h245_MultilinkRequest,
+ { "MultilinkRequest type", "h245.MultilinkRequest_type", FT_UINT32, BASE_DEC,
+ VALS(MultilinkRequest_vals), 0, "Type of MultilinkRequest choice", HFILL }},
+ { &hf_h245_RemoteMCResponse_reject,
+ { "RemoteMCResponse_reject type", "h245.RemoteMCResponse_reject_type", FT_UINT32, BASE_DEC,
+ VALS(RemoteMCResponse_reject_vals), 0, "Type of RemoteMCResponse_reject choice", HFILL }},
+ { &hf_h245_RemoteMCResponse,
+ { "RemoteMCResponse type", "h245.RemoteMCResponse_type", FT_UINT32, BASE_DEC,
+ VALS(RemoteMCResponse_vals), 0, "Type of RemoteMCResponse choice", HFILL }},
+ { &hf_h245_RemoteMCRequest,
+ { "RemoteMCRequest type", "h245.RemoteMCRequest_type", FT_UINT32, BASE_DEC,
+ VALS(RemoteMCRequest_vals), 0, "Type of RemoteMCRequest choice", HFILL }},
+ { &hf_h245_ConferenceResponse_sendThisSourceResponse,
+ { "ConferenceResponse_sendThisSourceResponse type", "h245.ConferenceResponse_sendThisSourceResponse_type", FT_UINT32, BASE_DEC,
+ VALS(ConferenceResponse_sendThisSourceResponse_vals), 0, "Type of ConferenceResponse_sendThisSourceResponse choice", HFILL }},
+ { &hf_h245_ConferenceResponse_makeTerminalBroadcasterResponse,
+ { "ConferenceResponse_makeTerminalBroadcasterResponse type", "h245.ConferenceResponse_makeTerminalBroadcasterResponse_type", FT_UINT32, BASE_DEC,
+ VALS(ConferenceResponse_makeTerminalBroadcasterResponse_vals), 0, "Type of ConferenceResponse_makeTerminalBroadcasterResponse choice", HFILL }},
+ { &hf_h245_ConferenceResponse_broadcastMyLogicalChannelResponse,
+ { "ConferenceResponse_broadcastMyLogicalChannelResponse type", "h245.ConferenceResponse_broadcastMyLogicalChannelResponse_type", FT_UINT32, BASE_DEC,
+ VALS(ConferenceResponse_broadcastMyLogicalChannelResponse_vals), 0, "Type of ConferenceResponse_broadcastMyLogicalChannelResponse choice", HFILL }},
+ { &hf_h245_ConferenceResponse_makeMeChairResponse,
+ { "ConferenceResponse_makeMeChairResponse type", "h245.ConferenceResponse_makeMeChairResponse_type", FT_UINT32, BASE_DEC,
+ VALS(ConferenceResponse_makeMeChairResponse_vals), 0, "Type of ConferenceResponse_makeMeChairResponse choice", HFILL }},
+ { &hf_h245_ConferenceResponse,
+ { "ConferenceResponse type", "h245.ConferenceResponse_type", FT_UINT32, BASE_DEC,
+ VALS(ConferenceResponse_vals), 0, "Type of ConferenceResponse choice", HFILL }},
+ { &hf_h245_ConferenceRequest,
+ { "ConferenceRequest type", "h245.ConferenceRequest_type", FT_UINT32, BASE_DEC,
+ VALS(ConferenceRequest_vals), 0, "Type of ConferenceRequest choice", HFILL }},
+ { &hf_h245_CommunicationModeTableEntry_dataType,
+ { "CommunicationModeTableEntry_dataType type", "h245.CommunicationModeTableEntry_dataType_type", FT_UINT32, BASE_DEC,
+ VALS(CommunicationModeTableEntry_dataType_vals), 0, "Type of CommunicationModeTableEntry_dataType choice", HFILL }},
+ { &hf_h245_CommunicationModeResponse,
+ { "CommunicationModeResponse type", "h245.CommunicationModeResponse_type", FT_UINT32, BASE_DEC,
+ VALS(CommunicationModeResponse_vals), 0, "Type of CommunicationModeResponse choice", HFILL }},
+ { &hf_h245_MaintenanceLoopReject_cause,
+ { "MaintenanceLoopReject_cause type", "h245.MaintenanceLoopReject_cause_type", FT_UINT32, BASE_DEC,
+ VALS(MaintenanceLoopReject_cause_vals), 0, "Type of MaintenanceLoopReject_cause choice", HFILL }},
+ { &hf_h245_MaintenanceLoopReject_type,
+ { "MaintenanceLoopReject_type type", "h245.MaintenanceLoopReject_type_type", FT_UINT32, BASE_DEC,
+ VALS(MaintenanceLoopReject_type_vals), 0, "Type of MaintenanceLoopReject_type choice", HFILL }},
+ { &hf_h245_MaintenanceLoopAck_type,
+ { "MaintenanceLoopAck_type type", "h245.MaintenanceLoopAck_type_type", FT_UINT32, BASE_DEC,
+ VALS(MaintenanceLoopAck_type_vals), 0, "Type of MaintenanceLoopAck_type choice", HFILL }},
+ { &hf_h245_MaintenanceLoopRequest_type,
+ { "MaintenanceLoopRequest_type type", "h245.MaintenanceLoopRequest_type_type", FT_UINT32, BASE_DEC,
+ VALS(MaintenanceLoopRequest_type_vals), 0, "Type of MaintenanceLoopRequest_type choice", HFILL }},
+ { &hf_h245_EncryptionMode,
+ { "EncryptionMode type", "h245.EncryptionMode_type", FT_UINT32, BASE_DEC,
+ VALS(EncryptionMode_vals), 0, "Type of EncryptionMode choice", HFILL }},
+ { &hf_h245_DataMode_application,
+ { "DataMode_application type", "h245.DataMode_application_type", FT_UINT32, BASE_DEC,
+ VALS(DataMode_application_vals), 0, "Type of DataMode_application choice", HFILL }},
+ { &hf_h245_IS13818AudioMode_multiChannelType,
+ { "IS13818AudioMode_multiChannelType type", "h245.IS13818AudioMode_multiChannelType_type", FT_UINT32, BASE_DEC,
+ VALS(IS13818AudioMode_multiChannelType_vals), 0, "Type of IS13818AudioMode_multiChannelType choice", HFILL }},
+ { &hf_h245_IS13818AudioMode_audioSampling,
+ { "IS13818AudioMode_audioSampling type", "h245.IS13818AudioMode_audioSampling_type", FT_UINT32, BASE_DEC,
+ VALS(IS13818AudioMode_audioSampling_vals), 0, "Type of IS13818AudioMode_audioSampling choice", HFILL }},
+ { &hf_h245_IS13818AudioMode_audioLayer,
+ { "IS13818AudioMode_audioLayer type", "h245.IS13818AudioMode_audioLayer_type", FT_UINT32, BASE_DEC,
+ VALS(IS13818AudioMode_audioLayer_vals), 0, "Type of IS13818AudioMode_audioLayer choice", HFILL }},
+ { &hf_h245_IS11172AudioMode_multichannelType,
+ { "IS11172AudioMode_multichannelType type", "h245.IS11172AudioMode_multichannelType_type", FT_UINT32, BASE_DEC,
+ VALS(IS11172AudioMode_multichannelType_vals), 0, "Type of IS11172AudioMode_multichannelType choice", HFILL }},
+ { &hf_h245_IS11172AudioMode_audioSampling,
+ { "IS11172AudioMode_audioSampling type", "h245.IS11172AudioMode_audioSampling_type", FT_UINT32, BASE_DEC,
+ VALS(IS11172AudioMode_audioSampling_vals), 0, "Type of IS11172AudioMode_audioSampling choice", HFILL }},
+ { &hf_h245_IS11172AudioMode_audioLayer,
+ { "IS11172AudioMode_audioLayer type", "h245.IS11172AudioMode_audioLayer_type", FT_UINT32, BASE_DEC,
+ VALS(IS11172AudioMode_audioLayer_vals), 0, "Type of IS11172AudioMode_audioLayer choice", HFILL }},
+ { &hf_h245_AudioMode_g7231,
+ { "AudioMode_g7231 type", "h245.AudioMode_g7231_type", FT_UINT32, BASE_DEC,
+ VALS(AudioMode_g7231_vals), 0, "Type of AudioMode_g7231 choice", HFILL }},
+ { &hf_h245_AudioMode,
+ { "AudioMode type", "h245.AudioMode_type", FT_UINT32, BASE_DEC,
+ VALS(AudioMode_vals), 0, "Type of AudioMode choice", HFILL }},
+ { &hf_h245_H263VideoMode_resolution,
+ { "H263VideoMode_resolution type", "h245.H263VideoMode_resolution_type", FT_UINT32, BASE_DEC,
+ VALS(H263VideoMode_resolution_vals), 0, "Type of H263VideoMode_resolution choice", HFILL }},
+ { &hf_h245_H262VideoMode_profileAndLevel,
+ { "H262VideoMode_profileAndLevel type", "h245.H262VideoMode_profileAndLevel_type", FT_UINT32, BASE_DEC,
+ VALS(H262VideoMode_profileAndLevel_vals), 0, "Type of H262VideoMode_profileAndLevel choice", HFILL }},
+ { &hf_h245_H261VideoMode_resolution,
+ { "H261VideoMode_resolution type", "h245.H261VideoMode_resolution_type", FT_UINT32, BASE_DEC,
+ VALS(H261VideoMode_resolution_vals), 0, "Type of H261VideoMode_resolution choice", HFILL }},
+ { &hf_h245_VideoMode,
+ { "VideoMode type", "h245.VideoMode_type", FT_UINT32, BASE_DEC,
+ VALS(VideoMode_vals), 0, "Type of VideoMode choice", HFILL }},
+ { &hf_h245_RedundancyEncodingMode_secondaryEncoding,
+ { "RedundancyEncodingMode_secondaryEncoding type", "h245.RedundancyEncodingMode_secondaryEncoding_type", FT_UINT32, BASE_DEC,
+ VALS(RedundancyEncodingMode_secondaryEncoding_vals), 0, "Type of RedundancyEncodingMode_secondaryEncoding choice", HFILL }},
+ { &hf_h245_V76ModeParameters,
+ { "V76ModeParameters type", "h245.V76ModeParameters_type", FT_UINT32, BASE_DEC,
+ VALS(V76ModeParameters_vals), 0, "Type of V76ModeParameters choice", HFILL }},
+ { &hf_h245_H223ModeParameters_adaptationLayerType,
+ { "H223ModeParameters_adaptationLayerType type", "h245.H223ModeParameters_adaptationLayerType_type", FT_UINT32, BASE_DEC,
+ VALS(H223ModeParameters_adaptationLayerType_vals), 0, "Type of H223ModeParameters_adaptationLayerType choice", HFILL }},
+ { &hf_h245_FECMode_rfc2733Mode_mode_separateStream,
+ { "FECMode_rfc2733Mode_mode_separateStream type", "h245.FECMode_rfc2733Mode_mode_separateStream_type", FT_UINT32, BASE_DEC,
+ VALS(FECMode_rfc2733Mode_mode_separateStream_vals), 0, "Type of FECMode_rfc2733Mode_mode_separateStream choice", HFILL }},
+ { &hf_h245_FECMode_rfc2733Mode_mode,
+ { "FECMode_rfc2733Mode_mode type", "h245.FECMode_rfc2733Mode_mode_type", FT_UINT32, BASE_DEC,
+ VALS(FECMode_rfc2733Mode_mode_vals), 0, "Type of FECMode_rfc2733Mode_mode choice", HFILL }},
+ { &hf_h245_FECMode,
+ { "FECMode type", "h245.FECMode_type", FT_UINT32, BASE_DEC,
+ VALS(FECMode_vals), 0, "Type of FECMode choice", HFILL }},
+ { &hf_h245_RedundancyEncodingDTModeElement_type,
+ { "RedundancyEncodingDTModeElement_type type", "h245.RedundancyEncodingDTModeElement_type_type", FT_UINT32, BASE_DEC,
+ VALS(RedundancyEncodingDTModeElement_type_vals), 0, "Type of RedundancyEncodingDTModeElement_type choice", HFILL }},
+ { &hf_h245_H235Mode_mediaMode,
+ { "H235Mode_mediaMode type", "h245.H235Mode_mediaMode_type", FT_UINT32, BASE_DEC,
+ VALS(H235Mode_mediaMode_vals), 0, "Type of H235Mode_mediaMode choice", HFILL }},
+ { &hf_h245_ModeElementType,
+ { "ModeElementType type", "h245.ModeElementType_type", FT_UINT32, BASE_DEC,
+ VALS(ModeElementType_vals), 0, "Type of ModeElementType choice", HFILL }},
+ { &hf_h245_RequestModeReject_cause,
+ { "RequestModeReject_cause type", "h245.RequestModeReject_cause_type", FT_UINT32, BASE_DEC,
+ VALS(RequestModeReject_cause_vals), 0, "Type of RequestModeReject_cause choice", HFILL }},
+ { &hf_h245_RequestMultiplexEntryRejectionDescriptions_cause,
+ { "RequestMultiplexEntryRejectionDescriptions_cause type", "h245.RequestMultiplexEntryRejectionDescriptions_cause_type", FT_UINT32, BASE_DEC,
+ VALS(RequestMultiplexEntryRejectionDescriptions_cause_vals), 0, "Type of RequestMultiplexEntryRejectionDescriptions_cause choice", HFILL }},
+ { &hf_h245_MultiplexEntryRejectionDescriptions_cause,
+ { "MultiplexEntryRejectionDescriptions_cause type", "h245.MultiplexEntryRejectionDescriptions_cause_type", FT_UINT32, BASE_DEC,
+ VALS(MultiplexEntryRejectionDescriptions_cause_vals), 0, "Type of MultiplexEntryRejectionDescriptions_cause choice", HFILL }},
+ { &hf_h245_MultiplexElement_repeatCount,
+ { "MultiplexElement_repeatCount type", "h245.MultiplexElement_repeatCount_type", FT_UINT32, BASE_DEC,
+ VALS(MultiplexElement_repeatCount_vals), 0, "Type of MultiplexElement_repeatCount choice", HFILL }},
+ { &hf_h245_MultiplexElement_type,
+ { "MultiplexElement_type type", "h245.MultiplexElement_type_type", FT_UINT32, BASE_DEC,
+ VALS(MultiplexElement_type_vals), 0, "Type of MultiplexElement_type choice", HFILL }},
+ { &hf_h245_RequestChannelCloseReject_cause,
+ { "RequestChannelCloseReject_cause type", "h245.RequestChannelCloseReject_cause_type", FT_UINT32, BASE_DEC,
+ VALS(RequestChannelCloseReject_cause_vals), 0, "Type of RequestChannelCloseReject_cause choice", HFILL }},
+ { &hf_h245_RequestChannelClose_reason,
+ { "RequestChannelClose_reason type", "h245.RequestChannelClose_reason_type", FT_UINT32, BASE_DEC,
+ VALS(RequestChannelClose_reason_vals), 0, "Type of RequestChannelClose_reason choice", HFILL }},
+ { &hf_h245_CloseLogicalChannel_reason,
+ { "CloseLogicalChannel_reason type", "h245.CloseLogicalChannel_reason_type", FT_UINT32, BASE_DEC,
+ VALS(CloseLogicalChannel_reason_vals), 0, "Type of CloseLogicalChannel_reason choice", HFILL }},
+ { &hf_h245_CloseLogicalChannel_source,
+ { "CloseLogicalChannel_source type", "h245.CloseLogicalChannel_source_type", FT_UINT32, BASE_DEC,
+ VALS(CloseLogicalChannel_source_vals), 0, "Type of CloseLogicalChannel_source choice", HFILL }},
+ { &hf_h245_OpenLogicalChannelReject_cause,
+ { "OpenLogicalChannelReject_cause type", "h245.OpenLogicalChannelReject_cause_type", FT_UINT32, BASE_DEC,
+ VALS(OpenLogicalChannelReject_cause_vals), 0, "Type of OpenLogicalChannelReject_cause choice", HFILL }},
+ { &hf_h245_forwardMultiplexAckParameters,
+ { "forwardMultiplexAckParameters type", "h245.forwardMultiplexAckParameters_type", FT_UINT32, BASE_DEC,
+ VALS(forwardMultiplexAckParameters_vals), 0, "Type of forwardMultiplexAckParameters choice", HFILL }},
+ { &hf_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters,
+ { "OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters type", "h245.OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_type", FT_UINT32, BASE_DEC,
+ VALS(OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_vals), 0, "Type of OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters choice", HFILL }},
+ { &hf_h245_MulticastAddress,
+ { "MulticastAddress type", "h245.MulticastAddress_type", FT_UINT32, BASE_DEC,
+ VALS(MulticastAddress_vals), 0, "Type of MulticastAddress choice", HFILL }},
+ { &hf_h245_UnicastAddress_iPSourceRouteAddress_routing,
+ { "UnicastAddress_iPSourceRouteAddress_routing type", "h245.UnicastAddress_iPSourceRouteAddress_routing_type", FT_UINT32, BASE_DEC,
+ VALS(UnicastAddress_iPSourceRouteAddress_routing_vals), 0, "Type of UnicastAddress_iPSourceRouteAddress_routing choice", HFILL }},
+ { &hf_h245_UnicastAddress,
+ { "UnicastAddress type", "h245.UnicastAddress_type", FT_UINT32, BASE_DEC,
+ VALS(UnicastAddress_vals), 0, "Type of UnicastAddress choice", HFILL }},
+ { &hf_h245_mediaControlChannel,
+ { "mediaControlChannel type", "h245.mediaControlChannel_type", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "Type of mediaControlChannel choice", HFILL }},
+ { &hf_h245_mediaChannel,
+ { "mediaChannel type", "h245.mediaChannel_type", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "Type of mediaChannel choice", HFILL }},
+ { &hf_h245_localAreaAddress,
+ { "localAreaAddress type", "h245.localAreaAddress_type", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "Type of localAreaAddress choice", HFILL }},
+ { &hf_h245_signalAddress,
+ { "signalAddress type", "h245.signalAddress_type", FT_UINT32, BASE_DEC,
+ VALS(TransportAddress_vals), 0, "Type of signalAddress choice", HFILL }},
+ { &hf_h245_FECData_rfc2733_mode_separateStream,
+ { "FECData_rfc2733_mode_separateStream type", "h245.FECData_rfc2733_mode_separateStream_type", FT_UINT32, BASE_DEC,
+ VALS(FECData_rfc2733_mode_separateStream_vals), 0, "Type of FECData_rfc2733_mode_separateStream choice", HFILL }},
+ { &hf_h245_FECData_rfc2733_mode,
+ { "FECData_rfc2733_mode type", "h245.FECData_rfc2733_mode_type", FT_UINT32, BASE_DEC,
+ VALS(FECData_rfc2733_mode_vals), 0, "Type of FECData_rfc2733_mode choice", HFILL }},
+ { &hf_h245_FECData,
+ { "FECData type", "h245.FECData_type", FT_UINT32, BASE_DEC,
+ VALS(FECData_vals), 0, "Type of FECData choice", HFILL }},
+ { &hf_h245_RTPPayloadType_payloadDescriptor,
+ { "RTPPayloadType_payloadDescriptor type", "h245.RTPPayloadType_payloadDescriptor_type", FT_UINT32, BASE_DEC,
+ VALS(RTPPayloadType_payloadDescriptor_vals), 0, "Type of RTPPayloadType_payloadDescriptor choice", HFILL }},
+ { &hf_h245_H2250LogicalChannelParameters_mediaPacketization,
+ { "H2250LogicalChannelParameters_mediaPacketization type", "h245.H2250LogicalChannelParameters_mediaPacketization_type", FT_UINT32, BASE_DEC,
+ VALS(H2250LogicalChannelParameters_mediaPacketization_vals), 0, "Type of H2250LogicalChannelParameters_mediaPacketization choice", HFILL }},
+ { &hf_h245_CRCLength,
+ { "CRCLength type", "h245.CRCLength_type", FT_UINT32, BASE_DEC,
+ VALS(CRCLength_vals), 0, "Type of CRCLength choice", HFILL }},
+ { &hf_h245_V76LogicalChannelParameters_mode_eRM_recovery,
+ { "V76LogicalChannelParameters_mode_eRM_recovery type", "h245.V76LogicalChannelParameters_mode_eRM_recovery_type", FT_UINT32, BASE_DEC,
+ VALS(V76LogicalChannelParameters_mode_eRM_recovery_vals), 0, "Type of V76LogicalChannelParameters_mode_eRM_recovery choice", HFILL }},
+ { &hf_h245_V76LogicalChannelParameters_mode,
+ { "V76LogicalChannelParameters_mode type", "h245.V76LogicalChannelParameters_mode_type", FT_UINT32, BASE_DEC,
+ VALS(V76LogicalChannelParameters_mode_vals), 0, "Type of V76LogicalChannelParameters_mode choice", HFILL }},
+ { &hf_h245_V76LogicalChannelParameters_suspendResume,
+ { "V76LogicalChannelParameters_suspendResume type", "h245.V76LogicalChannelParameters_suspendResume_type", FT_UINT32, BASE_DEC,
+ VALS(V76LogicalChannelParameters_suspendResume_vals), 0, "Type of V76LogicalChannelParameters_suspendResume choice", HFILL }},
+ { &hf_h245_H223AnnexCArqParameters_numberOfRetransmissions,
+ { "H223AnnexCArqParameters_numberOfRetransmissions type", "h245.H223AnnexCArqParameters_numberOfRetransmissions_type", FT_UINT32, BASE_DEC,
+ VALS(H223AnnexCArqParameters_numberOfRetransmissions_vals), 0, "Type of H223AnnexCArqParameters_numberOfRetransmissions choice", HFILL }},
+ { &hf_h245_H223AL3MParameters_arqType,
+ { "H223AL3MParameters_arqType type", "h245.H223AL3MParameters_arqType_type", FT_UINT32, BASE_DEC,
+ VALS(H223AL3MParameters_arqType_vals), 0, "Type of H223AL3MParameters_arqType choice", HFILL }},
+ { &hf_h245_H223AL3MParameters_crcLength,
+ { "H223AL3MParameters_crcLength type", "h245.H223AL3MParameters_crcLength_type", FT_UINT32, BASE_DEC,
+ VALS(H223AL3MParameters_crcLength_vals), 0, "Type of H223AL3MParameters_crcLength choice", HFILL }},
+ { &hf_h245_H223AL3MParameters_headerFormat,
+ { "H223AL3MParameters_headerFormat type", "h245.H223AL3MParameters_headerFormat_type", FT_UINT32, BASE_DEC,
+ VALS(H223AL3MParameters_headerFormat_vals), 0, "Type of H223AL3MParameters_headerFormat choice", HFILL }},
+ { &hf_h245_H223AL2MParameters_headerFEC,
+ { "H223AL2MParameters_headerFEC type", "h245.H223AL2MParameters_headerFEC_type", FT_UINT32, BASE_DEC,
+ VALS(H223AL2MParameters_headerFEC_vals), 0, "Type of H223AL2MParameters_headerFEC choice", HFILL }},
+ { &hf_h245_H223AL1MParameters_arqType,
+ { "H223AL1MParameters_arqType type", "h245.H223AL1MParameters_arqType_type", FT_UINT32, BASE_DEC,
+ VALS(H223AL1MParameters_arqType_vals), 0, "Type of H223AL1MParameters_arqType choice", HFILL }},
+ { &hf_h245_H223AL1MParameters_crcLength,
+ { "H223AL1MParameters_crcLength type", "h245.H223AL1MParameters_crcLength_type", FT_UINT32, BASE_DEC,
+ VALS(H223AL1MParameters_crcLength_vals), 0, "Type of H223AL1MParameters_crcLength choice", HFILL }},
+ { &hf_h245_H223AL1MParameters_headerFEC,
+ { "H223AL1MParameters_headerFEC type", "h245.H223AL1MParameters_headerFEC_type", FT_UINT32, BASE_DEC,
+ VALS(H223AL1MParameters_headerFEC_vals), 0, "Type of H223AL1MParameters_headerFEC choice", HFILL }},
+ { &hf_h245_H223AL1MParameters_transferMode,
+ { "H223AL1MParameters_transferMode type", "h245.H223AL1MParameters_transferMode_type", FT_UINT32, BASE_DEC,
+ VALS(H223AL1MParameters_transferMode_vals), 0, "Type of H223AL1MParameters_transferMode choice", HFILL }},
+ { &hf_h245_H223LogicalChannelParameters_adaptationLayerType,
+ { "H223LogicalChannelParameters_adaptationLayerType type", "h245.H223LogicalChannelParameters_adaptationLayerType_type", FT_UINT32, BASE_DEC,
+ VALS(H223LogicalChannelParameters_adaptationLayerType_vals), 0, "Type of H223LogicalChannelParameters_adaptationLayerType choice", HFILL }},
+ { &hf_h245_H235Media_mediaType,
+ { "H235Media_mediaType type", "h245.H235Media_mediaType_type", FT_UINT32, BASE_DEC,
+ VALS(H235Media_mediaType_vals), 0, "Type of H235Media_mediaType choice", HFILL }},
+ { &hf_h245_DataType,
+ { "DataType type", "h245.DataType_type", FT_UINT32, BASE_DEC,
+ VALS(DataType_vals), 0, "Type of DataType choice", HFILL }},
+ { &hf_h245_Q2931Address_address,
+ { "Q2931Address_address type", "h245.Q2931Address_address_type", FT_UINT32, BASE_DEC,
+ VALS(Q2931Address_address_vals), 0, "Type of Q2931Address_address choice", HFILL }},
+ { &hf_h245_NetworkAccessParameters_t120SetupProcedure,
+ { "NetworkAccessParameters_t120SetupProcedure type", "h245.NetworkAccessParameters_t120SetupProcedure_type", FT_UINT32, BASE_DEC,
+ VALS(NetworkAccessParameters_t120SetupProcedure_vals), 0, "Type of NetworkAccessParameters_t120SetupProcedure choice", HFILL }},
+ { &hf_h245_NetworkAccessParameters_networkAddress,
+ { "NetworkAccessParameters_networkAddress type", "h245.NetworkAccessParameters_networkAddress_type", FT_UINT32, BASE_DEC,
+ VALS(NetworkAccessParameters_networkAddress_vals), 0, "Type of NetworkAccessParameters_networkAddress choice", HFILL }},
+ { &hf_h245_NetworkAccessParameters_distribution,
+ { "NetworkAccessParameters_distribution type", "h245.NetworkAccessParameters_distribution_type", FT_UINT32, BASE_DEC,
+ VALS(NetworkAccessParameters_distribution_vals), 0, "Type of NetworkAccessParameters_distribution choice", HFILL }},
+ { &hf_h245_reverseLogicalChannelParameters_multiplexParameters,
+ { "reverseLogicalChannelParameters_multiplexParameters type", "h245.reverseLogicalChannelParameters_multiplexParameters_type", FT_UINT32, BASE_DEC,
+ VALS(reverseLogicalChannelParameters_multiplexParameters_vals), 0, "Type of reverseLogicalChannelParameters_multiplexParameters choice", HFILL }},
+ { &hf_h245_forwardLogicalChannelParameters_multiplexParameters,
+ { "forwardLogicalChannelParameters_multiplexParameters type", "h245.forwardLogicalChannelParameters_multiplexParameters_type", FT_UINT32, BASE_DEC,
+ VALS(forwardLogicalChannelParameters_multiplexParameters_vals), 0, "Type of forwardLogicalChannelParameters_multiplexParameters choice", HFILL }},
+ { &hf_h245_FECCapability,
+ { "FECCapability type", "h245.FECCapability_type", FT_UINT32, BASE_DEC,
+ VALS(FECCapability_vals), 0, "Type of FECCapability choice", HFILL }},
+ { &hf_h245_MultiplexFormat,
+ { "MultiplexFormat type", "h245.MultiplexFormat_type", FT_UINT32, BASE_DEC,
+ VALS(MultiplexFormat_vals), 0, "Type of MultiplexFormat choice", HFILL }},
+ { &hf_h245_ParameterValue,
+ { "ParameterValue type", "h245.ParameterValue_type", FT_UINT32, BASE_DEC,
+ VALS(ParameterValue_vals), 0, "Type of ParameterValue choice", HFILL }},
+ { &hf_h245_ParameterIdentifier,
+ { "ParameterIdentifier type", "h245.ParameterIdentifier_type", FT_UINT32, BASE_DEC,
+ VALS(ParameterIdentifier_vals), 0, "Type of ParameterIdentifier choice", HFILL }},
+ { &hf_h245_CapabilityIdentifier,
+ { "CapabilityIdentifier type", "h245.CapabilityIdentifier_type", FT_UINT32, BASE_DEC,
+ VALS(CapabilityIdentifier_vals), 0, "Type of CapabilityIdentifier choice", HFILL }},
+ { &hf_h245_UserInputCapability,
+ { "UserInputCapability type", "h245.UserInputCapability_type", FT_UINT32, BASE_DEC,
+ VALS(UserInputCapability_vals), 0, "Type of UserInputCapability choice", HFILL }},
+ { &hf_h245_MediaEncryptionAlgorithm,
+ { "MediaEncryptionAlgorithm type", "h245.MediaEncryptionAlgorithm_type", FT_UINT32, BASE_DEC,
+ VALS(MediaEncryptionAlgorithm_vals), 0, "Type of MediaEncryptionAlgorithm choice", HFILL }},
+ { &hf_h245_T38FaxUdpOptions_t38FaxUdpEC,
+ { "T38FaxUdpOptions_t38FaxUdpEC type", "h245.T38FaxUdpOptions_t38FaxUdpEC_type", FT_UINT32, BASE_DEC,
+ VALS(T38FaxUdpOptions_t38FaxUdpEC_vals), 0, "Type of T38FaxUdpOptions_t38FaxUdpEC choice", HFILL }},
+ { &hf_h245_T38FaxRateManagement,
+ { "T38FaxRateManagement type", "h245.T38FaxRateManagement_type", FT_UINT32, BASE_DEC,
+ VALS(T38FaxRateManagement_vals), 0, "Type of T38FaxRateManagement choice", HFILL }},
+ { &hf_h245_T84Profile,
+ { "T84Profile type", "h245.T84Profile_type", FT_UINT32, BASE_DEC,
+ VALS(T84Profile_vals), 0, "Type of T84Profile choice", HFILL }},
+ { &hf_h245_CompressionType,
+ { "CompressionType type", "h245.CompressionType_type", FT_UINT32, BASE_DEC,
+ VALS(CompressionType_vals), 0, "Type of CompressionType choice", HFILL }},
+ { &hf_h245_DataProtocolCapability_v76wCompression,
+ { "DataProtocolCapability_v76wCompression type", "h245.DataProtocolCapability_v76wCompression_type", FT_UINT32, BASE_DEC,
+ VALS(DataProtocolCapability_v76wCompression_vals), 0, "Type of DataProtocolCapability_v76wCompression choice", HFILL }},
+ { &hf_h245_DataProtocolCapability,
+ { "DataProtocolCapability type", "h245.DataProtocolCapability_type", FT_UINT32, BASE_DEC,
+ VALS(DataProtocolCapability_vals), 0, "Type of DataProtocolCapability choice", HFILL }},
+ { &hf_h245_DataApplicationCapability_application,
+ { "DataApplicationCapability_application type", "h245.DataApplicationCapability_application_type", FT_UINT32, BASE_DEC,
+ VALS(DataApplicationCapability_application_vals), 0, "Type of DataApplicationCapability_application choice", HFILL }},
+ { &hf_h245_AudioCapability,
+ { "AudioCapability type", "h245.AudioCapability_type", FT_UINT32, BASE_DEC,
+ VALS(AudioCapability_vals), 0, "Type of AudioCapability choice", HFILL }},
+ { &hf_h245_CustomPictureFormat_pixelAspectInformation,
+ { "CustomPictureFormat_pixelAspectInformation type", "h245.CustomPictureFormat_pixelAspectInformation_type", FT_UINT32, BASE_DEC,
+ VALS(CustomPictureFormat_pixelAspectInformation_vals), 0, "Type of CustomPictureFormat_pixelAspectInformation choice", HFILL }},
+ { &hf_h245_RefPictureSelection_videoBackChannelSend,
+ { "RefPictureSelection_videoBackChannelSend type", "h245.RefPictureSelection_videoBackChannelSend_type", FT_UINT32, BASE_DEC,
+ VALS(RefPictureSelection_videoBackChannelSend_vals), 0, "Type of RefPictureSelection_videoBackChannelSend choice", HFILL }},
+ { &hf_h245_VideoCapability,
+ { "VideoCapability type", "h245.VideoCapability_type", FT_UINT32, BASE_DEC,
+ VALS(VideoCapability_vals), 0, "Type of VideoCapability choice", HFILL }},
+ { &hf_h245_RTPH263VideoRedundancyEncoding_frameToThreadMapping,
+ { "RTPH263VideoRedundancyEncoding_frameToThreadMapping type", "h245.RTPH263VideoRedundancyEncoding_frameToThreadMapping_type", FT_UINT32, BASE_DEC,
+ VALS(RTPH263VideoRedundancyEncoding_frameToThreadMapping_vals), 0, "Type of RTPH263VideoRedundancyEncoding_frameToThreadMapping choice", HFILL }},
+ { &hf_h245_RedundancyEncodingMethod,
+ { "RedundancyEncodingMethod type", "h245.RedundancyEncodingMethod_type", FT_UINT32, BASE_DEC,
+ VALS(RedundancyEncodingMethod_vals), 0, "Type of RedundancyEncodingMethod choice", HFILL }},
+ { &hf_h245_MediaTransportType,
+ { "MediaTransportType type", "h245.MediaTransportType_type", FT_UINT32, BASE_DEC,
+ VALS(MediaTransportType_vals), 0, "Type of MediaTransportType choice", HFILL }},
+ { &hf_h245_QOSMode,
+ { "QOSMode type", "h245.QOSMode_type", FT_UINT32, BASE_DEC,
+ VALS(QOSMode_vals), 0, "Type of QOSMode choice", HFILL }},
+ { &hf_h245_H223Capability_h223MultiplexTableCapability,
+ { "H223Capability_h223MultiplexTableCapability type", "h245.H223Capability_h223MultiplexTableCapability_type", FT_UINT32, BASE_DEC,
+ VALS(H223Capability_h223MultiplexTableCapability_vals), 0, "Type of H223Capability_h223MultiplexTableCapability choice", HFILL }},
+ { &hf_h245_VCCapability_availableBitRates_type,
+ { "VCCapability_availableBitRates_type type", "h245.VCCapability_availableBitRates_type_type", FT_UINT32, BASE_DEC,
+ VALS(VCCapability_availableBitRates_type_vals), 0, "Type of VCCapability_availableBitRates_type choice", HFILL }},
+ { &hf_h245_MultiplexCapability,
+ { "MultiplexCapability type", "h245.MultiplexCapability_type", FT_UINT32, BASE_DEC,
+ VALS(MultiplexCapability_vals), 0, "Type of MultiplexCapability choice", HFILL }},
+ { &hf_h245_Capability,
+ { "Capability type", "h245.Capability_type", FT_UINT32, BASE_DEC,
+ VALS(Capability_vals), 0, "Type of Capability choice", HFILL }},
+ { &hf_h245_TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded,
+ { "TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded type", "h245.TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded_type", FT_UINT32, BASE_DEC,
+ VALS(TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded_vals), 0, "Type of TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded choice", HFILL }},
+ { &hf_h245_TerminalCapabilitySetReject_cause,
+ { "TerminalCapabilitySetReject_cause type", "h245.TerminalCapabilitySetReject_cause_type", FT_UINT32, BASE_DEC,
+ VALS(TerminalCapabilitySetReject_cause_vals), 0, "Type of TerminalCapabilitySetReject_cause choice", HFILL }},
+ { &hf_h245_MasterSlaveDeterminationReject_cause,
+ { "MasterSlaveDeterminationReject_cause type", "h245.MasterSlaveDeterminationReject_cause_type", FT_UINT32, BASE_DEC,
+ VALS(MasterSlaveDeterminationReject_cause_vals), 0, "Type of MasterSlaveDeterminationReject_cause choice", HFILL }},
+ { &hf_h245_MasterSlaveDeterminationAck_decision,
+ { "MasterSlaveDeterminationAck_decision type", "h245.MasterSlaveDeterminationAck_decision_type", FT_UINT32, BASE_DEC,
+ VALS(MasterSlaveDeterminationAck_decision_vals), 0, "Type of MasterSlaveDeterminationAck_decision choice", HFILL }},
+ { &hf_h245_RequestModeAck_response_decision,
+ { "RequestModeAck_response_decision type", "h245.RequestModeAck_response_decision_type", FT_UINT32, BASE_DEC,
+ VALS(RequestModeAck_response_decision_vals), 0, "Type of RequestModeAck_response_decision choice", HFILL }},
+ { &hf_h245_NonStandardIdentifier,
+ { "NonStandardIdentifier type", "h245.NonStandardIdentifier_type", FT_UINT32, BASE_DEC,
+ VALS(NonStandardIdentifier_vals), 0, "Type of NonStandardIdentifier choice", HFILL }},
+ { &hf_h245_h233EncryptionTransmitCapability,
+ { "h233EncryptionTransmitCapability", "h245.h233EncryptionTransmitCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_h233EncryptionTransmitCapability_bit), 0x01, "The h233EncryptionTransmitCapability bit", HFILL }},
+ { &hf_h245_nullClockRecovery,
+ { "nullClockRecovery", "h245.nullClockRecovery", FT_BOOLEAN, 8,
+ TFS(&tfs_nullClockRecovery_bit), 0x01, "The nullClockRecovery bit", HFILL }},
+ { &hf_h245_srtsClockRecovery,
+ { "srtsClockRecovery", "h245.srtsClockRecovery", FT_BOOLEAN, 8,
+ TFS(&tfs_srtsClockRecovery_bit), 0x01, "The srtsClockRecovery bit", HFILL }},
+ { &hf_h245_adaptiveClockRecovery,
+ { "adaptiveClockRecovery", "h245.adaptiveClockRecovery", FT_BOOLEAN, 8,
+ TFS(&tfs_adaptiveClockRecovery_bit), 0x01, "The adaptiveClockRecovery bit", HFILL }},
+ { &hf_h245_nullErrorCorrection,
+ { "nullErrorCorrection", "h245.nullErrorCorrection", FT_BOOLEAN, 8,
+ TFS(&tfs_nullErrorCorrection_bit), 0x01, "The nullErrorCorrection bit", HFILL }},
+ { &hf_h245_longInterleaver,
+ { "longInterleaver", "h245.longInterleaver", FT_BOOLEAN, 8,
+ TFS(&tfs_longInterleaver_bit), 0x01, "The longInterleaver bit", HFILL }},
+ { &hf_h245_shortInterleaver,
+ { "shortInterleaver", "h245.shortInterleaver", FT_BOOLEAN, 8,
+ TFS(&tfs_shortInterleaver_bit), 0x01, "The shortInterleaver bit", HFILL }},
+ { &hf_h245_errorCorrectionOnly,
+ { "errorCorrectionOnly", "h245.errorCorrectionOnly", FT_BOOLEAN, 8,
+ TFS(&tfs_errorCorrectionOnly_bit), 0x01, "The errorCorrectionOnly bit", HFILL }},
+ { &hf_h245_structuredDataTransfer,
+ { "structuredDataTransfer", "h245.structuredDataTransfer", FT_BOOLEAN, 8,
+ TFS(&tfs_structuredDataTransfer_bit), 0x01, "The structuredDataTransfer bit", HFILL }},
+ { &hf_h245_partiallyFilledCells,
+ { "partiallyFilledCells", "h245.partiallyFilledCells", FT_BOOLEAN, 8,
+ TFS(&tfs_partiallyFilledCells_bit), 0x01, "The partiallyFilledCells bit", HFILL }},
+ { &hf_h245_transportStream,
+ { "transportStream", "h245.transportStream", FT_BOOLEAN, 8,
+ TFS(&tfs_transportStream_bit), 0x01, "The transportStream bit", HFILL }},
+ { &hf_h245_programStream,
+ { "programStream", "h245.programStream", FT_BOOLEAN, 8,
+ TFS(&tfs_programStream_bit), 0x01, "The programStream bit", HFILL }},
+ { &hf_h245_transportWithIframes,
+ { "transportWithIframes", "h245.transportWithIframes", FT_BOOLEAN, 8,
+ TFS(&tfs_transportWithIframes_bit), 0x01, "The transportWithIframes bit", HFILL }},
+ { &hf_h245_videoWithAL1,
+ { "videoWithAL1", "h245.videoWithAL1", FT_BOOLEAN, 8,
+ TFS(&tfs_videoWithAL1_bit), 0x01, "The videoWithAL1 bit", HFILL }},
+ { &hf_h245_videoWithAL2,
+ { "videoWithAL2", "h245.videoWithAL2", FT_BOOLEAN, 8,
+ TFS(&tfs_videoWithAL2_bit), 0x01, "The videoWithAL2 bit", HFILL }},
+ { &hf_h245_videoWithAL3,
+ { "videoWithAL3", "h245.videoWithAL3", FT_BOOLEAN, 8,
+ TFS(&tfs_videoWithAL3_bit), 0x01, "The videoWithAL3 bit", HFILL }},
+ { &hf_h245_audioWithAL1,
+ { "audioWithAL1", "h245.audioWithAL1", FT_BOOLEAN, 8,
+ TFS(&tfs_audioWithAL1_bit), 0x01, "The audioWithAL1 bit", HFILL }},
+ { &hf_h245_audioWithAL2,
+ { "audioWithAL2", "h245.audioWithAL2", FT_BOOLEAN, 8,
+ TFS(&tfs_audioWithAL2_bit), 0x01, "The audioWithAL2 bit", HFILL }},
+ { &hf_h245_audioWithAL3,
+ { "audioWithAL3", "h245.audioWithAL3", FT_BOOLEAN, 8,
+ TFS(&tfs_audioWithAL3_bit), 0x01, "The audioWithAL3 bit", HFILL }},
+ { &hf_h245_dataWithAL1,
+ { "dataWithAL1", "h245.dataWithAL1", FT_BOOLEAN, 8,
+ TFS(&tfs_dataWithAL1_bit), 0x01, "The dataWithAL1 bit", HFILL }},
+ { &hf_h245_dataWithAL2,
+ { "dataWithAL2", "h245.dataWithAL2", FT_BOOLEAN, 8,
+ TFS(&tfs_dataWithAL2_bit), 0x01, "The dataWithAL2 bit", HFILL }},
+ { &hf_h245_dataWithAL3,
+ { "dataWithAL3", "h245.dataWithAL3", FT_BOOLEAN, 8,
+ TFS(&tfs_dataWithAL3_bit), 0x01, "The dataWithAL3 bit", HFILL }},
+ { &hf_h245_maxMUXPDUSizeCapability,
+ { "maxMUXPDUSizeCapability", "h245.maxMUXPDUSizeCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_maxMUXPDUSizeCapability_bit), 0x01, "The maxMUXPDUSizeCapability bit", HFILL }},
+ { &hf_h245_nsrpSupport,
+ { "nsrpSupport", "h245.nsrpSupport", FT_BOOLEAN, 8,
+ TFS(&tfs_nsrpSupport_bit), 0x01, "The nsrpSupport bit", HFILL }},
+ { &hf_h245_modeChangeCapability,
+ { "modeChangeCapability", "h245.modeChangeCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_modeChangeCapability_bit), 0x01, "The modeChangeCapability bit", HFILL }},
+ { &hf_h245_h223AnnexA,
+ { "h223AnnexA", "h245.h223AnnexA", FT_BOOLEAN, 8,
+ TFS(&tfs_h223AnnexA_bit), 0x01, "The h223AnnexA bit", HFILL }},
+ { &hf_h245_h223AnnexADoubleFlag_bool,
+ { "h223AnnexADoubleFlag_bool", "h245.h223AnnexADoubleFlag_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_h223AnnexADoubleFlag_bool_bit), 0x01, "The h223AnnexADoubleFlag_bool bit", HFILL }},
+ { &hf_h245_h223AnnexB,
+ { "h223AnnexB", "h245.h223AnnexB", FT_BOOLEAN, 8,
+ TFS(&tfs_h223AnnexB_bit), 0x01, "The h223AnnexB bit", HFILL }},
+ { &hf_h245_h223AnnexBwithHeader,
+ { "h223AnnexBwithHeader", "h245.h223AnnexBwithHeader", FT_BOOLEAN, 8,
+ TFS(&tfs_h223AnnexBwithHeader_bit), 0x01, "The h223AnnexBwithHeader bit", HFILL }},
+ { &hf_h245_videoWithAL1M,
+ { "videoWithAL1M", "h245.videoWithAL1M", FT_BOOLEAN, 8,
+ TFS(&tfs_videoWithAL1M_bit), 0x01, "The videoWithAL1M bit", HFILL }},
+ { &hf_h245_videoWithAL2M,
+ { "videoWithAL2M", "h245.videoWithAL2M", FT_BOOLEAN, 8,
+ TFS(&tfs_videoWithAL2M_bit), 0x01, "The videoWithAL2M bit", HFILL }},
+ { &hf_h245_videoWithAL3M,
+ { "videoWithAL3M", "h245.videoWithAL3M", FT_BOOLEAN, 8,
+ TFS(&tfs_videoWithAL3M_bit), 0x01, "The videoWithAL3M bit", HFILL }},
+ { &hf_h245_audioWithAL1M,
+ { "audioWithAL1M", "h245.audioWithAL1M", FT_BOOLEAN, 8,
+ TFS(&tfs_audioWithAL1M_bit), 0x01, "The audioWithAL1M bit", HFILL }},
+ { &hf_h245_audioWithAL2M,
+ { "audioWithAL2M", "h245.audioWithAL2M", FT_BOOLEAN, 8,
+ TFS(&tfs_audioWithAL2M_bit), 0x01, "The audioWithAL2M bit", HFILL }},
+ { &hf_h245_audioWithAL3M,
+ { "audioWithAL3M", "h245.audioWithAL3M", FT_BOOLEAN, 8,
+ TFS(&tfs_audioWithAL3M_bit), 0x01, "The audioWithAL3M bit", HFILL }},
+ { &hf_h245_dataWithAL1M,
+ { "dataWithAL1M", "h245.dataWithAL1M", FT_BOOLEAN, 8,
+ TFS(&tfs_dataWithAL1M_bit), 0x01, "The dataWithAL1M bit", HFILL }},
+ { &hf_h245_dataWithAL2M,
+ { "dataWithAL2M", "h245.dataWithAL2M", FT_BOOLEAN, 8,
+ TFS(&tfs_dataWithAL2M_bit), 0x01, "The dataWithAL2M bit", HFILL }},
+ { &hf_h245_dataWithAL3M,
+ { "dataWithAL3M", "h245.dataWithAL3M", FT_BOOLEAN, 8,
+ TFS(&tfs_dataWithAL3M_bit), 0x01, "The dataWithAL3M bit", HFILL }},
+ { &hf_h245_alpduInterleaving,
+ { "alpduInterleaving", "h245.alpduInterleaving", FT_BOOLEAN, 8,
+ TFS(&tfs_alpduInterleaving_bit), 0x01, "The alpduInterleaving bit", HFILL }},
+ { &hf_h245_rsCodeCapability,
+ { "rsCodeCapability", "h245.rsCodeCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_rsCodeCapability_bit), 0x01, "The rsCodeCapability bit", HFILL }},
+ { &hf_h245_suspendResumeCapabilitywAddress,
+ { "suspendResumeCapabilitywAddress", "h245.suspendResumeCapabilitywAddress", FT_BOOLEAN, 8,
+ TFS(&tfs_suspendResumeCapabilitywAddress_bit), 0x01, "The suspendResumeCapabilitywAddress bit", HFILL }},
+ { &hf_h245_suspendResumeCapabilitywoAddress,
+ { "suspendResumeCapabilitywoAddress", "h245.suspendResumeCapabilitywoAddress", FT_BOOLEAN, 8,
+ TFS(&tfs_suspendResumeCapabilitywoAddress_bit), 0x01, "The suspendResumeCapabilitywoAddress bit", HFILL }},
+ { &hf_h245_rejCapability,
+ { "rejCapability", "h245.rejCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_rejCapability_bit), 0x01, "The rejCapability bit", HFILL }},
+ { &hf_h245_sREJCapability,
+ { "sREJCapability", "h245.sREJCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_sREJCapability_bit), 0x01, "The sREJCapability bit", HFILL }},
+ { &hf_h245_mREJCapability,
+ { "mREJCapability", "h245.mREJCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_mREJCapability_bit), 0x01, "The mREJCapability bit", HFILL }},
+ { &hf_h245_crc8bitCapability,
+ { "crc8bitCapability", "h245.crc8bitCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_crc8bitCapability_bit), 0x01, "The crc8bitCapability bit", HFILL }},
+ { &hf_h245_crc16bitCapability,
+ { "crc16bitCapability", "h245.crc16bitCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_crc16bitCapability_bit), 0x01, "The crc16bitCapability bit", HFILL }},
+ { &hf_h245_crc32bitCapability,
+ { "crc32bitCapability", "h245.crc32bitCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_crc32bitCapability_bit), 0x01, "The crc32bitCapability bit", HFILL }},
+ { &hf_h245_uihCapability,
+ { "uihCapability", "h245.uihCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_uihCapability_bit), 0x01, "The uihCapability bit", HFILL }},
+ { &hf_h245_twoOctetAddressFieldCapability,
+ { "twoOctetAddressFieldCapability", "h245.twoOctetAddressFieldCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_twoOctetAddressFieldCapability_bit), 0x01, "The twoOctetAddressFieldCapability bit", HFILL }},
+ { &hf_h245_loopBackTestCapability,
+ { "loopBackTestCapability", "h245.loopBackTestCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_loopBackTestCapability_bit), 0x01, "The loopBackTestCapability bit", HFILL }},
+ { &hf_h245_audioHeader,
+ { "audioHeader", "h245.audioHeader", FT_BOOLEAN, 8,
+ TFS(&tfs_audioHeader_bit), 0x01, "The audioHeader bit", HFILL }},
+ { &hf_h245_centralizedConferenceMC,
+ { "centralizedConferenceMC", "h245.centralizedConferenceMC", FT_BOOLEAN, 8,
+ TFS(&tfs_centralizedConferenceMC_bit), 0x01, "The centralizedConferenceMC bit", HFILL }},
+ { &hf_h245_decentralizedConferenceMC,
+ { "decentralizedConferenceMC", "h245.decentralizedConferenceMC", FT_BOOLEAN, 8,
+ TFS(&tfs_decentralizedConferenceMC_bit), 0x01, "The decentralizedConferenceMC bit", HFILL }},
+ { &hf_h245_rtcpVideoControlCapability,
+ { "rtcpVideoControlCapability", "h245.rtcpVideoControlCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_rtcpVideoControlCapability_bit), 0x01, "The rtcpVideoControlCapability bit", HFILL }},
+ { &hf_h245_logicalChannelSwitchingCapability,
+ { "logicalChannelSwitchingCapability", "h245.logicalChannelSwitchingCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_logicalChannelSwitchingCapability_bit), 0x01, "The logicalChannelSwitchingCapability bit", HFILL }},
+ { &hf_h245_t120DynamicPortCapability,
+ { "t120DynamicPortCapability", "h245.t120DynamicPortCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_t120DynamicPortCapability_bit), 0x01, "The t120DynamicPortCapability bit", HFILL }},
+ { &hf_h245_h261aVideoPacketization,
+ { "h261aVideoPacketization", "h245.h261aVideoPacketization", FT_BOOLEAN, 8,
+ TFS(&tfs_h261aVideoPacketization_bit), 0x01, "The h261aVideoPacketization bit", HFILL }},
+ { &hf_h245_atmUBR,
+ { "atmUBR", "h245.atmUBR", FT_BOOLEAN, 8,
+ TFS(&tfs_atmUBR_bit), 0x01, "The atmUBR bit", HFILL }},
+ { &hf_h245_atmrtVBR,
+ { "atmrtVBR", "h245.atmrtVBR", FT_BOOLEAN, 8,
+ TFS(&tfs_atmrtVBR_bit), 0x01, "The atmrtVBR bit", HFILL }},
+ { &hf_h245_atmnrtVBR,
+ { "atmnrtVBR", "h245.atmnrtVBR", FT_BOOLEAN, 8,
+ TFS(&tfs_atmnrtVBR_bit), 0x01, "The atmnrtVBR bit", HFILL }},
+ { &hf_h245_atmABR,
+ { "atmABR", "h245.atmABR", FT_BOOLEAN, 8,
+ TFS(&tfs_atmABR_bit), 0x01, "The atmABR bit", HFILL }},
+ { &hf_h245_atmCBR,
+ { "atmCBR", "h245.atmCBR", FT_BOOLEAN, 8,
+ TFS(&tfs_atmCBR_bit), 0x01, "The atmCBR bit", HFILL }},
+ { &hf_h245_variableDelta,
+ { "variableDelta", "h245.variableDelta", FT_BOOLEAN, 8,
+ TFS(&tfs_variableDelta_bit), 0x01, "The variableDelta bit", HFILL }},
+ { &hf_h245_multicastCapability,
+ { "multicastCapability", "h245.multicastCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_multicastCapability_bit), 0x01, "The multicastCapability bit", HFILL }},
+ { &hf_h245_multiUniCastConference,
+ { "multiUniCastConference", "h245.multiUniCastConference", FT_BOOLEAN, 8,
+ TFS(&tfs_multiUniCastConference_bit), 0x01, "The multiUniCastConference bit", HFILL }},
+ { &hf_h245_centralizedControl,
+ { "centralizedControl", "h245.centralizedControl", FT_BOOLEAN, 8,
+ TFS(&tfs_centralizedControl_bit), 0x01, "The centralizedControl bit", HFILL }},
+ { &hf_h245_distributedControl,
+ { "distributedControl", "h245.distributedControl", FT_BOOLEAN, 8,
+ TFS(&tfs_distributedControl_bit), 0x01, "The distributedControl bit", HFILL }},
+ { &hf_h245_centralizedAudio,
+ { "centralizedAudio", "h245.centralizedAudio", FT_BOOLEAN, 8,
+ TFS(&tfs_centralizedAudio_bit), 0x01, "The centralizedAudio bit", HFILL }},
+ { &hf_h245_distributedAudio,
+ { "distributedAudio", "h245.distributedAudio", FT_BOOLEAN, 8,
+ TFS(&tfs_distributedAudio_bit), 0x01, "The distributedAudio bit", HFILL }},
+ { &hf_h245_centralizedVideo,
+ { "centralizedVideo", "h245.centralizedVideo", FT_BOOLEAN, 8,
+ TFS(&tfs_centralizedVideo_bit), 0x01, "The centralizedVideo bit", HFILL }},
+ { &hf_h245_distributedVideo,
+ { "distributedVideo", "h245.distributedVideo", FT_BOOLEAN, 8,
+ TFS(&tfs_distributedVideo_bit), 0x01, "The distributedVideo bit", HFILL }},
+ { &hf_h245_temporalSpatialTradeOffCapability,
+ { "temporalSpatialTradeOffCapability", "h245.temporalSpatialTradeOffCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_temporalSpatialTradeOffCapability_bit), 0x01, "The temporalSpatialTradeOffCapability bit", HFILL }},
+ { &hf_h245_stillImageTransmission,
+ { "stillImageTransmission", "h245.stillImageTransmission", FT_BOOLEAN, 8,
+ TFS(&tfs_stillImageTransmission_bit), 0x01, "The stillImageTransmission bit", HFILL }},
+ { &hf_h245_videoBadMBsCap,
+ { "videoBadMBsCap", "h245.videoBadMBsCap", FT_BOOLEAN, 8,
+ TFS(&tfs_videoBadMBsCap_bit), 0x01, "The videoBadMBsCap bit", HFILL }},
+ { &hf_h245_profileAndLevelSPatML,
+ { "profileAndLevelSPatML", "h245.profileAndLevelSPatML", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelSPatML_bit), 0x01, "The profileAndLevelSPatML bit", HFILL }},
+ { &hf_h245_profileAndLevelMPatLL,
+ { "profileAndLevelMPatLL", "h245.profileAndLevelMPatLL", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelMPatLL_bit), 0x01, "The profileAndLevelMPatLL bit", HFILL }},
+ { &hf_h245_profileAndLevelMPatML,
+ { "profileAndLevelMPatML", "h245.profileAndLevelMPatML", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelMPatML_bit), 0x01, "The profileAndLevelMPatML bit", HFILL }},
+ { &hf_h245_profileAndLevelMPatH14,
+ { "profileAndLevelMPatH14", "h245.profileAndLevelMPatH14", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelMPatH14_bit), 0x01, "The profileAndLevelMPatH14 bit", HFILL }},
+ { &hf_h245_profileAndLevelMPatHL,
+ { "profileAndLevelMPatHL", "h245.profileAndLevelMPatHL", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelMPatHL_bit), 0x01, "The profileAndLevelMPatHL bit", HFILL }},
+ { &hf_h245_profileAndLevelSNRatLL,
+ { "profileAndLevelSNRatLL", "h245.profileAndLevelSNRatLL", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelSNRatLL_bit), 0x01, "The profileAndLevelSNRatLL bit", HFILL }},
+ { &hf_h245_profileAndLevelSNRatML,
+ { "profileAndLevelSNRatML", "h245.profileAndLevelSNRatML", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelSNRatML_bit), 0x01, "The profileAndLevelSNRatML bit", HFILL }},
+ { &hf_h245_profileAndLevelSpatialatH14,
+ { "profileAndLevelSpatialatH14", "h245.profileAndLevelSpatialatH14", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelSpatialatH14_bit), 0x01, "The profileAndLevelSpatialatH14 bit", HFILL }},
+ { &hf_h245_profileAndLevelHPatML,
+ { "profileAndLevelHPatML", "h245.profileAndLevelHPatML", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelHPatML_bit), 0x01, "The profileAndLevelHPatML bit", HFILL }},
+ { &hf_h245_profileAndLevelHPatH14,
+ { "profileAndLevelHPatH14", "h245.profileAndLevelHPatH14", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelHPatH14_bit), 0x01, "The profileAndLevelHPatH14 bit", HFILL }},
+ { &hf_h245_profileAndLevelHPatHL,
+ { "profileAndLevelHPatHL", "h245.profileAndLevelHPatHL", FT_BOOLEAN, 8,
+ TFS(&tfs_profileAndLevelHPatHL_bit), 0x01, "The profileAndLevelHPatHL bit", HFILL }},
+ { &hf_h245_unrestrictedVector,
+ { "unrestrictedVector", "h245.unrestrictedVector", FT_BOOLEAN, 8,
+ TFS(&tfs_unrestrictedVector_bit), 0x01, "The unrestrictedVector bit", HFILL }},
+ { &hf_h245_arithmeticCoding,
+ { "arithmeticCoding", "h245.arithmeticCoding", FT_BOOLEAN, 8,
+ TFS(&tfs_arithmeticCoding_bit), 0x01, "The arithmeticCoding bit", HFILL }},
+ { &hf_h245_advancedPrediction,
+ { "advancedPrediction", "h245.advancedPrediction", FT_BOOLEAN, 8,
+ TFS(&tfs_advancedPrediction_bit), 0x01, "The advancedPrediction bit", HFILL }},
+ { &hf_h245_pbFrames,
+ { "pbFrames", "h245.pbFrames", FT_BOOLEAN, 8,
+ TFS(&tfs_pbFrames_bit), 0x01, "The pbFrames bit", HFILL }},
+ { &hf_h245_errorCompensation,
+ { "errorCompensation", "h245.errorCompensation", FT_BOOLEAN, 8,
+ TFS(&tfs_errorCompensation_bit), 0x01, "The errorCompensation bit", HFILL }},
+ { &hf_h245_baseBitRateConstrained,
+ { "baseBitRateConstrained", "h245.baseBitRateConstrained", FT_BOOLEAN, 8,
+ TFS(&tfs_baseBitRateConstrained_bit), 0x01, "The baseBitRateConstrained bit", HFILL }},
+ { &hf_h245_advancedIntraCodingMode,
+ { "advancedIntraCodingMode", "h245.advancedIntraCodingMode", FT_BOOLEAN, 8,
+ TFS(&tfs_advancedIntraCodingMode_bit), 0x01, "The advancedIntraCodingMode bit", HFILL }},
+ { &hf_h245_deblockingFilterMode,
+ { "deblockingFilterMode", "h245.deblockingFilterMode", FT_BOOLEAN, 8,
+ TFS(&tfs_deblockingFilterMode_bit), 0x01, "The deblockingFilterMode bit", HFILL }},
+ { &hf_h245_improvedPBFramesMode,
+ { "improvedPBFramesMode", "h245.improvedPBFramesMode", FT_BOOLEAN, 8,
+ TFS(&tfs_improvedPBFramesMode_bit), 0x01, "The improvedPBFramesMode bit", HFILL }},
+ { &hf_h245_unlimitedMotionVectors,
+ { "unlimitedMotionVectors", "h245.unlimitedMotionVectors", FT_BOOLEAN, 8,
+ TFS(&tfs_unlimitedMotionVectors_bit), 0x01, "The unlimitedMotionVectors bit", HFILL }},
+ { &hf_h245_fullPictureFreeze,
+ { "fullPictureFreeze", "h245.fullPictureFreeze", FT_BOOLEAN, 8,
+ TFS(&tfs_fullPictureFreeze_bit), 0x01, "The fullPictureFreeze bit", HFILL }},
+ { &hf_h245_partialPictureFreezeAndRelease,
+ { "partialPictureFreezeAndRelease", "h245.partialPictureFreezeAndRelease", FT_BOOLEAN, 8,
+ TFS(&tfs_partialPictureFreezeAndRelease_bit), 0x01, "The partialPictureFreezeAndRelease bit", HFILL }},
+ { &hf_h245_resizingPartPicFreezeAndRelease,
+ { "resizingPartPicFreezeAndRelease", "h245.resizingPartPicFreezeAndRelease", FT_BOOLEAN, 8,
+ TFS(&tfs_resizingPartPicFreezeAndRelease_bit), 0x01, "The resizingPartPicFreezeAndRelease bit", HFILL }},
+ { &hf_h245_fullPictureSnapshot,
+ { "fullPictureSnapshot", "h245.fullPictureSnapshot", FT_BOOLEAN, 8,
+ TFS(&tfs_fullPictureSnapshot_bit), 0x01, "The fullPictureSnapshot bit", HFILL }},
+ { &hf_h245_partialPictureSnapshot,
+ { "partialPictureSnapshot", "h245.partialPictureSnapshot", FT_BOOLEAN, 8,
+ TFS(&tfs_partialPictureSnapshot_bit), 0x01, "The partialPictureSnapshot bit", HFILL }},
+ { &hf_h245_videoSegmentTagging,
+ { "videoSegmentTagging", "h245.videoSegmentTagging", FT_BOOLEAN, 8,
+ TFS(&tfs_videoSegmentTagging_bit), 0x01, "The videoSegmentTagging bit", HFILL }},
+ { &hf_h245_progressiveRefinement,
+ { "progressiveRefinement", "h245.progressiveRefinement", FT_BOOLEAN, 8,
+ TFS(&tfs_progressiveRefinement_bit), 0x01, "The progressiveRefinement bit", HFILL }},
+ { &hf_h245_dynamicPictureResizingByFour,
+ { "dynamicPictureResizingByFour", "h245.dynamicPictureResizingByFour", FT_BOOLEAN, 8,
+ TFS(&tfs_dynamicPictureResizingByFour_bit), 0x01, "The dynamicPictureResizingByFour bit", HFILL }},
+ { &hf_h245_dynamicPictureResizingSixteenthPel,
+ { "dynamicPictureResizingSixteenthPel", "h245.dynamicPictureResizingSixteenthPel", FT_BOOLEAN, 8,
+ TFS(&tfs_dynamicPictureResizingSixteenthPel_bit), 0x01, "The dynamicPictureResizingSixteenthPel bit", HFILL }},
+ { &hf_h245_dynamicWarpingHalfPel,
+ { "dynamicWarpingHalfPel", "h245.dynamicWarpingHalfPel", FT_BOOLEAN, 8,
+ TFS(&tfs_dynamicWarpingHalfPel_bit), 0x01, "The dynamicWarpingHalfPel bit", HFILL }},
+ { &hf_h245_dynamicWarpingSixteenthPel,
+ { "dynamicWarpingSixteenthPel", "h245.dynamicWarpingSixteenthPel", FT_BOOLEAN, 8,
+ TFS(&tfs_dynamicWarpingSixteenthPel_bit), 0x01, "The dynamicWarpingSixteenthPel bit", HFILL }},
+ { &hf_h245_independentSegmentDecoding,
+ { "independentSegmentDecoding", "h245.independentSegmentDecoding", FT_BOOLEAN, 8,
+ TFS(&tfs_independentSegmentDecoding_bit), 0x01, "The independentSegmentDecoding bit", HFILL }},
+ { &hf_h245_slicesInOrderNonRect,
+ { "slicesInOrderNonRect", "h245.slicesInOrderNonRect", FT_BOOLEAN, 8,
+ TFS(&tfs_slicesInOrderNonRect_bit), 0x01, "The slicesInOrderNonRect bit", HFILL }},
+ { &hf_h245_slicesInOrderRect,
+ { "slicesInOrderRect", "h245.slicesInOrderRect", FT_BOOLEAN, 8,
+ TFS(&tfs_slicesInOrderRect_bit), 0x01, "The slicesInOrderRect bit", HFILL }},
+ { &hf_h245_slicesNoOrderNonRect,
+ { "slicesNoOrderNonRect", "h245.slicesNoOrderNonRect", FT_BOOLEAN, 8,
+ TFS(&tfs_slicesNoOrderNonRect_bit), 0x01, "The slicesNoOrderNonRect bit", HFILL }},
+ { &hf_h245_slicesNoOrderRect,
+ { "slicesNoOrderRect", "h245.slicesNoOrderRect", FT_BOOLEAN, 8,
+ TFS(&tfs_slicesNoOrderRect_bit), 0x01, "The slicesNoOrderRect bit", HFILL }},
+ { &hf_h245_alternateInterVLCMode,
+ { "alternateInterVLCMode", "h245.alternateInterVLCMode", FT_BOOLEAN, 8,
+ TFS(&tfs_alternateInterVLCMode_bit), 0x01, "The alternateInterVLCMode bit", HFILL }},
+ { &hf_h245_modifiedQuantizationMode,
+ { "modifiedQuantizationMode", "h245.modifiedQuantizationMode", FT_BOOLEAN, 8,
+ TFS(&tfs_modifiedQuantizationMode_bit), 0x01, "The modifiedQuantizationMode bit", HFILL }},
+ { &hf_h245_reducedResolutionUpdate,
+ { "reducedResolutionUpdate", "h245.reducedResolutionUpdate", FT_BOOLEAN, 8,
+ TFS(&tfs_reducedResolutionUpdate_bit), 0x01, "The reducedResolutionUpdate bit", HFILL }},
+ { &hf_h245_separateVideoBackChannel,
+ { "separateVideoBackChannel", "h245.separateVideoBackChannel", FT_BOOLEAN, 8,
+ TFS(&tfs_separateVideoBackChannel_bit), 0x01, "The separateVideoBackChannel bit", HFILL }},
+ { &hf_h245_videoMux,
+ { "videoMux", "h245.videoMux", FT_BOOLEAN, 8,
+ TFS(&tfs_videoMux_bit), 0x01, "The videoMux bit", HFILL }},
+ { &hf_h245_anyPixelAspectRatio,
+ { "anyPixelAspectRatio", "h245.anyPixelAspectRatio", FT_BOOLEAN, 8,
+ TFS(&tfs_anyPixelAspectRatio_bit), 0x01, "The anyPixelAspectRatio bit", HFILL }},
+ { &hf_h245_referencePicSelect,
+ { "referencePicSelect", "h245.referencePicSelect", FT_BOOLEAN, 8,
+ TFS(&tfs_referencePicSelect_bit), 0x01, "The referencePicSelect bit", HFILL }},
+ { &hf_h245_enhancedReferencePicSelect_bool,
+ { "enhancedReferencePicSelect_bool", "h245.enhancedReferencePicSelect_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_enhancedReferencePicSelect_bool_bit), 0x01, "The enhancedReferencePicSelect_bool bit", HFILL }},
+ { &hf_h245_dataPartitionedSlices,
+ { "dataPartitionedSlices", "h245.dataPartitionedSlices", FT_BOOLEAN, 8,
+ TFS(&tfs_dataPartitionedSlices_bit), 0x01, "The dataPartitionedSlices bit", HFILL }},
+ { &hf_h245_fixedPointIDCT0,
+ { "fixedPointIDCT0", "h245.fixedPointIDCT0", FT_BOOLEAN, 8,
+ TFS(&tfs_fixedPointIDCT0_bit), 0x01, "The fixedPointIDCT0 bit", HFILL }},
+ { &hf_h245_interlacedFields,
+ { "interlacedFields", "h245.interlacedFields", FT_BOOLEAN, 8,
+ TFS(&tfs_interlacedFields_bit), 0x01, "The interlacedFields bit", HFILL }},
+ { &hf_h245_currentPictureHeaderRepetition,
+ { "currentPictureHeaderRepetition", "h245.currentPictureHeaderRepetition", FT_BOOLEAN, 8,
+ TFS(&tfs_currentPictureHeaderRepetition_bit), 0x01, "The currentPictureHeaderRepetition bit", HFILL }},
+ { &hf_h245_previousPictureHeaderRepetition,
+ { "previousPictureHeaderRepetition", "h245.previousPictureHeaderRepetition", FT_BOOLEAN, 8,
+ TFS(&tfs_previousPictureHeaderRepetition_bit), 0x01, "The previousPictureHeaderRepetition bit", HFILL }},
+ { &hf_h245_nextPictureHeaderRepetition,
+ { "nextPictureHeaderRepetition", "h245.nextPictureHeaderRepetition", FT_BOOLEAN, 8,
+ TFS(&tfs_nextPictureHeaderRepetition_bit), 0x01, "The nextPictureHeaderRepetition bit", HFILL }},
+ { &hf_h245_pictureNumber_bool,
+ { "pictureNumber_bool", "h245.pictureNumber_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_pictureNumber_bool_bit), 0x01, "The pictureNumber_bool bit", HFILL }},
+ { &hf_h245_spareReferencePictures,
+ { "spareReferencePictures", "h245.spareReferencePictures", FT_BOOLEAN, 8,
+ TFS(&tfs_spareReferencePictures_bit), 0x01, "The spareReferencePictures bit", HFILL }},
+ { &hf_h245_constrainedBitstream,
+ { "constrainedBitstream", "h245.constrainedBitstream", FT_BOOLEAN, 8,
+ TFS(&tfs_constrainedBitstream_bit), 0x01, "The constrainedBitstream bit", HFILL }},
+ { &hf_h245_silenceSuppression,
+ { "silenceSuppression", "h245.silenceSuppression", FT_BOOLEAN, 8,
+ TFS(&tfs_silenceSuppression_bit), 0x01, "The silenceSuppression bit", HFILL }},
+ { &hf_h245_annexA,
+ { "annexA", "h245.annexA", FT_BOOLEAN, 8,
+ TFS(&tfs_annexA_bit), 0x01, "The annexA bit", HFILL }},
+ { &hf_h245_annexB,
+ { "annexB", "h245.annexB", FT_BOOLEAN, 8,
+ TFS(&tfs_annexB_bit), 0x01, "The annexB bit", HFILL }},
+ { &hf_h245_annexD,
+ { "annexD", "h245.annexD", FT_BOOLEAN, 8,
+ TFS(&tfs_annexD_bit), 0x01, "The annexD bit", HFILL }},
+ { &hf_h245_annexE,
+ { "annexE", "h245.annexE", FT_BOOLEAN, 8,
+ TFS(&tfs_annexE_bit), 0x01, "The annexE bit", HFILL }},
+ { &hf_h245_annexF,
+ { "annexF", "h245.annexF", FT_BOOLEAN, 8,
+ TFS(&tfs_annexF_bit), 0x01, "The annexF bit", HFILL }},
+ { &hf_h245_annexG,
+ { "annexG", "h245.annexG", FT_BOOLEAN, 8,
+ TFS(&tfs_annexG_bit), 0x01, "The annexG bit", HFILL }},
+ { &hf_h245_annexH,
+ { "annexH", "h245.annexH", FT_BOOLEAN, 8,
+ TFS(&tfs_annexH_bit), 0x01, "The annexH bit", HFILL }},
+ { &hf_h245_audioLayer1,
+ { "audioLayer1", "h245.audioLayer1", FT_BOOLEAN, 8,
+ TFS(&tfs_audioLayer1_bit), 0x01, "The audioLayer1 bit", HFILL }},
+ { &hf_h245_audioLayer2,
+ { "audioLayer2", "h245.audioLayer2", FT_BOOLEAN, 8,
+ TFS(&tfs_audioLayer2_bit), 0x01, "The audioLayer2 bit", HFILL }},
+ { &hf_h245_audioLayer3,
+ { "audioLayer3", "h245.audioLayer3", FT_BOOLEAN, 8,
+ TFS(&tfs_audioLayer3_bit), 0x01, "The audioLayer3 bit", HFILL }},
+ { &hf_h245_audioSampling32k,
+ { "audioSampling32k", "h245.audioSampling32k", FT_BOOLEAN, 8,
+ TFS(&tfs_audioSampling32k_bit), 0x01, "The audioSampling32k bit", HFILL }},
+ { &hf_h245_audioSampling44k1,
+ { "audioSampling44k1", "h245.audioSampling44k1", FT_BOOLEAN, 8,
+ TFS(&tfs_audioSampling44k1_bit), 0x01, "The audioSampling44k1 bit", HFILL }},
+ { &hf_h245_audioSampling48k,
+ { "audioSampling48k", "h245.audioSampling48k", FT_BOOLEAN, 8,
+ TFS(&tfs_audioSampling48k_bit), 0x01, "The audioSampling48k bit", HFILL }},
+ { &hf_h245_singleChannel,
+ { "singleChannel", "h245.singleChannel", FT_BOOLEAN, 8,
+ TFS(&tfs_singleChannel_bit), 0x01, "The singleChannel bit", HFILL }},
+ { &hf_h245_twoChannels,
+ { "twoChannels", "h245.twoChannels", FT_BOOLEAN, 8,
+ TFS(&tfs_twoChannels_bit), 0x01, "The twoChannels bit", HFILL }},
+ { &hf_h245_audioSampling16k,
+ { "audioSampling16k", "h245.audioSampling16k", FT_BOOLEAN, 8,
+ TFS(&tfs_audioSampling16k_bit), 0x01, "The audioSampling16k bit", HFILL }},
+ { &hf_h245_audioSampling22k05,
+ { "audioSampling22k05", "h245.audioSampling22k05", FT_BOOLEAN, 8,
+ TFS(&tfs_audioSampling22k05_bit), 0x01, "The audioSampling22k05 bit", HFILL }},
+ { &hf_h245_audioSampling24k,
+ { "audioSampling24k", "h245.audioSampling24k", FT_BOOLEAN, 8,
+ TFS(&tfs_audioSampling24k_bit), 0x01, "The audioSampling24k bit", HFILL }},
+ { &hf_h245_threeChannels21,
+ { "threeChannels21", "h245.threeChannels21", FT_BOOLEAN, 8,
+ TFS(&tfs_threeChannels21_bit), 0x01, "The threeChannels21 bit", HFILL }},
+ { &hf_h245_threeChannels30,
+ { "threeChannels30", "h245.threeChannels30", FT_BOOLEAN, 8,
+ TFS(&tfs_threeChannels30_bit), 0x01, "The threeChannels30 bit", HFILL }},
+ { &hf_h245_fourChannels2020,
+ { "fourChannels2020", "h245.fourChannels2020", FT_BOOLEAN, 8,
+ TFS(&tfs_fourChannels2020_bit), 0x01, "The fourChannels2020 bit", HFILL }},
+ { &hf_h245_fourChannels22,
+ { "fourChannels22", "h245.fourChannels22", FT_BOOLEAN, 8,
+ TFS(&tfs_fourChannels22_bit), 0x01, "The fourChannels22 bit", HFILL }},
+ { &hf_h245_fourChannels31,
+ { "fourChannels31", "h245.fourChannels31", FT_BOOLEAN, 8,
+ TFS(&tfs_fourChannels31_bit), 0x01, "The fourChannels31 bit", HFILL }},
+ { &hf_h245_fiveChannels3020,
+ { "fiveChannels3020", "h245.fiveChannels3020", FT_BOOLEAN, 8,
+ TFS(&tfs_fiveChannels3020_bit), 0x01, "The fiveChannels3020 bit", HFILL }},
+ { &hf_h245_fiveChannels32,
+ { "fiveChannels32", "h245.fiveChannels32", FT_BOOLEAN, 8,
+ TFS(&tfs_fiveChannels32_bit), 0x01, "The fiveChannels32 bit", HFILL }},
+ { &hf_h245_lowFrequencyEnhancement,
+ { "lowFrequencyEnhancement", "h245.lowFrequencyEnhancement", FT_BOOLEAN, 8,
+ TFS(&tfs_lowFrequencyEnhancement_bit), 0x01, "The lowFrequencyEnhancement bit", HFILL }},
+ { &hf_h245_multilingual,
+ { "multilingual", "h245.multilingual", FT_BOOLEAN, 8,
+ TFS(&tfs_multilingual_bit), 0x01, "The multilingual bit", HFILL }},
+ { &hf_h245_comfortNoise,
+ { "comfortNoise", "h245.comfortNoise", FT_BOOLEAN, 8,
+ TFS(&tfs_comfortNoise_bit), 0x01, "The comfortNoise bit", HFILL }},
+ { &hf_h245_scrambled,
+ { "scrambled", "h245.scrambled", FT_BOOLEAN, 8,
+ TFS(&tfs_scrambled_bit), 0x01, "The scrambled bit", HFILL }},
+ { &hf_h245_qcif_bool,
+ { "qcif_bool", "h245.qcif_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_qcif_bool_bit), 0x01, "The qcif_bool bit", HFILL }},
+ { &hf_h245_cif_bool,
+ { "cif_bool", "h245.cif_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_cif_bool_bit), 0x01, "The cif_bool bit", HFILL }},
+ { &hf_h245_ccir601Seq,
+ { "ccir601Seq", "h245.ccir601Seq", FT_BOOLEAN, 8,
+ TFS(&tfs_ccir601Seq_bit), 0x01, "The ccir601Seq bit", HFILL }},
+ { &hf_h245_ccir601Prog,
+ { "ccir601Prog", "h245.ccir601Prog", FT_BOOLEAN, 8,
+ TFS(&tfs_ccir601Prog_bit), 0x01, "The ccir601Prog bit", HFILL }},
+ { &hf_h245_hdtvSeq,
+ { "hdtvSeq", "h245.hdtvSeq", FT_BOOLEAN, 8,
+ TFS(&tfs_hdtvSeq_bit), 0x01, "The hdtvSeq bit", HFILL }},
+ { &hf_h245_hdtvProg,
+ { "hdtvProg", "h245.hdtvProg", FT_BOOLEAN, 8,
+ TFS(&tfs_hdtvProg_bit), 0x01, "The hdtvProg bit", HFILL }},
+ { &hf_h245_g3FacsMH200x100,
+ { "g3FacsMH200x100", "h245.g3FacsMH200x100", FT_BOOLEAN, 8,
+ TFS(&tfs_g3FacsMH200x100_bit), 0x01, "The g3FacsMH200x100 bit", HFILL }},
+ { &hf_h245_g3FacsMH200x200,
+ { "g3FacsMH200x200", "h245.g3FacsMH200x200", FT_BOOLEAN, 8,
+ TFS(&tfs_g3FacsMH200x200_bit), 0x01, "The g3FacsMH200x200 bit", HFILL }},
+ { &hf_h245_g4FacsMMR200x100,
+ { "g4FacsMMR200x100", "h245.g4FacsMMR200x100", FT_BOOLEAN, 8,
+ TFS(&tfs_g4FacsMMR200x100_bit), 0x01, "The g4FacsMMR200x100 bit", HFILL }},
+ { &hf_h245_g4FacsMMR200x200,
+ { "g4FacsMMR200x200", "h245.g4FacsMMR200x200", FT_BOOLEAN, 8,
+ TFS(&tfs_g4FacsMMR200x200_bit), 0x01, "The g4FacsMMR200x200 bit", HFILL }},
+ { &hf_h245_jbig200x200Seq,
+ { "jbig200x200Seq", "h245.jbig200x200Seq", FT_BOOLEAN, 8,
+ TFS(&tfs_jbig200x200Seq_bit), 0x01, "The jbig200x200Seq bit", HFILL }},
+ { &hf_h245_jbig200x200Prog,
+ { "jbig200x200Prog", "h245.jbig200x200Prog", FT_BOOLEAN, 8,
+ TFS(&tfs_jbig200x200Prog_bit), 0x01, "The jbig200x200Prog bit", HFILL }},
+ { &hf_h245_jbig300x300Seq,
+ { "jbig300x300Seq", "h245.jbig300x300Seq", FT_BOOLEAN, 8,
+ TFS(&tfs_jbig300x300Seq_bit), 0x01, "The jbig300x300Seq bit", HFILL }},
+ { &hf_h245_jbig300x300Prog,
+ { "jbig300x300Prog", "h245.jbig300x300Prog", FT_BOOLEAN, 8,
+ TFS(&tfs_jbig300x300Prog_bit), 0x01, "The jbig300x300Prog bit", HFILL }},
+ { &hf_h245_digPhotoLow,
+ { "digPhotoLow", "h245.digPhotoLow", FT_BOOLEAN, 8,
+ TFS(&tfs_digPhotoLow_bit), 0x01, "The digPhotoLow bit", HFILL }},
+ { &hf_h245_digPhotoMedSeq,
+ { "digPhotoMedSeq", "h245.digPhotoMedSeq", FT_BOOLEAN, 8,
+ TFS(&tfs_digPhotoMedSeq_bit), 0x01, "The digPhotoMedSeq bit", HFILL }},
+ { &hf_h245_digPhotoMedProg,
+ { "digPhotoMedProg", "h245.digPhotoMedProg", FT_BOOLEAN, 8,
+ TFS(&tfs_digPhotoMedProg_bit), 0x01, "The digPhotoMedProg bit", HFILL }},
+ { &hf_h245_digPhotoHighSeq,
+ { "digPhotoHighSeq", "h245.digPhotoHighSeq", FT_BOOLEAN, 8,
+ TFS(&tfs_digPhotoHighSeq_bit), 0x01, "The digPhotoHighSeq bit", HFILL }},
+ { &hf_h245_digPhotoHighProg,
+ { "digPhotoHighProg", "h245.digPhotoHighProg", FT_BOOLEAN, 8,
+ TFS(&tfs_digPhotoHighProg_bit), 0x01, "The digPhotoHighProg bit", HFILL }},
+ { &hf_h245_fillBitRemoval,
+ { "fillBitRemoval", "h245.fillBitRemoval", FT_BOOLEAN, 8,
+ TFS(&tfs_fillBitRemoval_bit), 0x01, "The fillBitRemoval bit", HFILL }},
+ { &hf_h245_transcodingJBIG,
+ { "transcodingJBIG", "h245.transcodingJBIG", FT_BOOLEAN, 8,
+ TFS(&tfs_transcodingJBIG_bit), 0x01, "The transcodingJBIG bit", HFILL }},
+ { &hf_h245_transcodingMMR,
+ { "transcodingMMR", "h245.transcodingMMR", FT_BOOLEAN, 8,
+ TFS(&tfs_transcodingMMR_bit), 0x01, "The transcodingMMR bit", HFILL }},
+ { &hf_h245_t38TCPBidirectionalMode,
+ { "t38TCPBidirectionalMode", "h245.t38TCPBidirectionalMode", FT_BOOLEAN, 8,
+ TFS(&tfs_t38TCPBidirectionalMode_bit), 0x01, "The t38TCPBidirectionalMode bit", HFILL }},
+ { &hf_h245_chairControlCapability,
+ { "chairControlCapability", "h245.chairControlCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_chairControlCapability_bit), 0x01, "The chairControlCapability bit", HFILL }},
+ { &hf_h245_videoIndicateMixingCapability,
+ { "videoIndicateMixingCapability", "h245.videoIndicateMixingCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_videoIndicateMixingCapability_bit), 0x01, "The videoIndicateMixingCapability bit", HFILL }},
+ { &hf_h245_multipointVisualizationCapability,
+ { "multipointVisualizationCapability", "h245.multipointVisualizationCapability", FT_BOOLEAN, 8,
+ TFS(&tfs_multipointVisualizationCapability_bit), 0x01, "The multipointVisualizationCapability bit", HFILL }},
+ { &hf_h245_controlOnMuxStream,
+ { "controlOnMuxStream", "h245.controlOnMuxStream", FT_BOOLEAN, 8,
+ TFS(&tfs_controlOnMuxStream_bit), 0x01, "The controlOnMuxStream bit", HFILL }},
+ { &hf_h245_redundancyEncoding_bool,
+ { "redundancyEncoding_bool", "h245.redundancyEncoding_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_redundancyEncoding_bool_bit), 0x01, "The redundancyEncoding_bool bit", HFILL }},
+ { &hf_h245_separatePort,
+ { "separatePort", "h245.separatePort", FT_BOOLEAN, 8,
+ TFS(&tfs_separatePort_bit), 0x01, "The separatePort bit", HFILL }},
+ { &hf_h245_samePort_bool,
+ { "samePort_bool", "h245.samePort_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_samePort_bool_bit), 0x01, "The samePort_bool bit", HFILL }},
+ { &hf_h245_associateConference,
+ { "associateConference", "h245.associateConference", FT_BOOLEAN, 8,
+ TFS(&tfs_associateConference_bit), 0x01, "The associateConference bit", HFILL }},
+ { &hf_h245_audioHeaderPresent,
+ { "audioHeaderPresent", "h245.audioHeaderPresent", FT_BOOLEAN, 8,
+ TFS(&tfs_audioHeaderPresent_bit), 0x01, "The audioHeaderPresent bit", HFILL }},
+ { &hf_h245_segmentableFlag,
+ { "segmentableFlag", "h245.segmentableFlag", FT_BOOLEAN, 8,
+ TFS(&tfs_segmentableFlag_bit), 0x01, "The segmentableFlag bit", HFILL }},
+ { &hf_h245_alsduSplitting,
+ { "alsduSplitting", "h245.alsduSplitting", FT_BOOLEAN, 8,
+ TFS(&tfs_alsduSplitting_bit), 0x01, "The alsduSplitting bit", HFILL }},
+ { &hf_h245_uIH,
+ { "uIH", "h245.uIH", FT_BOOLEAN, 8,
+ TFS(&tfs_uIH_bit), 0x01, "The uIH bit", HFILL }},
+ { &hf_h245_loopbackTestProcedure,
+ { "loopbackTestProcedure", "h245.loopbackTestProcedure", FT_BOOLEAN, 8,
+ TFS(&tfs_loopbackTestProcedure_bit), 0x01, "The loopbackTestProcedure bit", HFILL }},
+ { &hf_h245_mediaGuaranteedDelivery,
+ { "mediaGuaranteedDelivery", "h245.mediaGuaranteedDelivery", FT_BOOLEAN, 8,
+ TFS(&tfs_mediaGuaranteedDelivery_bit), 0x01, "The mediaGuaranteedDelivery bit", HFILL }},
+ { &hf_h245_mediaControlGuaranteedDelivery,
+ { "mediaControlGuaranteedDelivery", "h245.mediaControlGuaranteedDelivery", FT_BOOLEAN, 8,
+ TFS(&tfs_mediaControlGuaranteedDelivery_bit), 0x01, "The mediaControlGuaranteedDelivery bit", HFILL }},
+ { &hf_h245_flowControlToZero,
+ { "flowControlToZero", "h245.flowControlToZero", FT_BOOLEAN, 8,
+ TFS(&tfs_flowControlToZero_bit), 0x01, "The flowControlToZero bit", HFILL }},
+ { &hf_h245_multiplexCapability_bool,
+ { "multiplexCapability_bool", "h245.multiplexCapability_bool", FT_BOOLEAN, 8,
+ TFS(&tfs_multiplexCapability_bool_bit), 0x01, "The multiplexCapability_bool bit", HFILL }},
+ { &hf_h245_secureChannel,
+ { "secureChannel", "h245.secureChannel", FT_BOOLEAN, 8,
+ TFS(&tfs_secureChannel_bit), 0x01, "The secureChannel bit", HFILL }},
+ { &hf_h245_sharedSecret,
+ { "sharedSecret", "h245.sharedSecret", FT_BOOLEAN, 8,
+ TFS(&tfs_sharedSecret_bit), 0x01, "The sharedSecret bit", HFILL }},
+ { &hf_h245_certProtectedKey,
+ { "certProtectedKey", "h245.certProtectedKey", FT_BOOLEAN, 8,
+ TFS(&tfs_certProtectedKey_bit), 0x01, "The certProtectedKey bit", HFILL }},
+ { &hf_h245_bitRateLockedToPCRClock,
+ { "bitRateLockedToPCRClock", "h245.bitRateLockedToPCRClock", FT_BOOLEAN, 8,
+ TFS(&tfs_bitRateLockedToPCRClock_bit), 0x01, "The bitRateLockedToPCRClock bit", HFILL }},
+ { &hf_h245_bitRateLockedToNetworkClock,
+ { "bitRateLockedToNetworkClock", "h245.bitRateLockedToNetworkClock", FT_BOOLEAN, 8,
+ TFS(&tfs_bitRateLockedToNetworkClock_bit), 0x01, "The bitRateLockedToNetworkClock bit", HFILL }},
+ { &hf_h245_IS11172_BitRate,
+ { "BitRate", "h245.IS11172_BitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "IS11172 BitRate in kbit/s", HFILL }},
+ { &hf_h245_IS13818_BitRate,
+ { "BitRate", "h245.IS13818_BitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "IS13818 BitRate in kbit/s", HFILL }},
+ { &hf_h245_ATM_BitRate,
+ { "BitRate", "h245.ATM_BitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "ATM BitRate in 64kbit/s units", HFILL }},
+ { &hf_h245_t35CountryCode,
+ { "t35CountryCode", "h245.t35CountryCode", FT_UINT32, BASE_DEC,
+ VALS(T35CountryCode_vals), 0, "t35CountryCode value", HFILL }},
+ { &hf_h245_t35Extension,
+ { "t35Extension", "h245.t35Extension", FT_UINT32, BASE_DEC,
+ NULL, 0, "t35Extension value", HFILL }},
+ { &hf_h245_manufacturerCode,
+ { "manufacturerCode", "h245.manufacturerCode", FT_UINT32, BASE_DEC,
+ NULL, 0, "manufacturerCode value", HFILL }},
+ { &hf_h245_terminalType,
+ { "terminalType", "h245.terminalType", FT_UINT32, BASE_DEC,
+ NULL, 0, "terminalType value", HFILL }},
+ { &hf_h245_statusDeterminationNumber,
+ { "statusDeterminationNumber", "h245.statusDeterminationNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "statusDeterminationNumber value", HFILL }},
+ { &hf_h245_CapabilityTableEntryNumber,
+ { "CapabilityTableEntryNumber", "h245.CapabilityTableEntryNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "CapabilityTableEntryNumber value", HFILL }},
+ { &hf_h245_CapabilityDescriptorNumber,
+ { "CapabilityDescriptorNumber", "h245.CapabilityDescriptorNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "CapabilityDescriptorNumber value", HFILL }},
+ { &hf_h245_h233IVResponseTime,
+ { "h233IVResponseTime", "h245.h233IVResponseTime", FT_UINT32, BASE_DEC,
+ NULL, 0, "h233IVResponseTime value", HFILL }},
+ { &hf_h245_maxPendingReplacementFor,
+ { "maxPendingReplacementFor", "h245.maxPendingReplacementFor", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxPendingReplacementFor value", HFILL }},
+ { &hf_h245_numberOfVCs,
+ { "numberOfVCs", "h245.numberOfVCs", FT_UINT32, BASE_DEC,
+ NULL, 0, "numberOfVCs value", HFILL }},
+ { &hf_h245_forwardMaximumSDUSize,
+ { "forwardMaximumSDUSize", "h245.forwardMaximumSDUSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "forwardMaximumSDUSize value", HFILL }},
+ { &hf_h245_backwardMaximumSDUSize,
+ { "backwardMaximumSDUSize", "h245.backwardMaximumSDUSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "backwardMaximumSDUSize value", HFILL }},
+ { &hf_h245_singleBitRate,
+ { "singleBitRate", "h245.singleBitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "singleBitRate value", HFILL }},
+ { &hf_h245_lowerBitRate,
+ { "lowerBitRate", "h245.lowerBitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "lowerBitRate value", HFILL }},
+ { &hf_h245_higherBitRate,
+ { "higherBitRate", "h245.higherBitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "higherBitRate value", HFILL }},
+ { &hf_h245_maximumAl2SDUSize,
+ { "maximumAl2SDUSize", "h245.maximumAl2SDUSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumAl2SDUSize value", HFILL }},
+ { &hf_h245_maximumAl3SDUSize,
+ { "maximumAl3SDUSize", "h245.maximumAl3SDUSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumAl3SDUSize value", HFILL }},
+ { &hf_h245_maximumDelayJitter,
+ { "maximumDelayJitter", "h245.maximumDelayJitter", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumDelayJitter value", HFILL }},
+ { &hf_h245_maximumNestingDepth,
+ { "maximumNestingDepth", "h245.maximumNestingDepth", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumNestingDepth value", HFILL }},
+ { &hf_h245_maximumElementListSize,
+ { "maximumElementListSize", "h245.maximumElementListSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumElementListSize value", HFILL }},
+ { &hf_h245_maximumSubElementListSize,
+ { "maximumSubElementListSize", "h245.maximumSubElementListSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumSubElementListSize value", HFILL }},
+ { &hf_h245_h223bitRate,
+ { "h223bitRate", "h245.h223bitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "h223bitRate value", HFILL }},
+ { &hf_h245_maximumSampleSize,
+ { "maximumSampleSize", "h245.maximumSampleSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumSampleSize value", HFILL }},
+ { &hf_h245_maximumPayloadLength,
+ { "maximumPayloadLength", "h245.maximumPayloadLength", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumPayloadLength value", HFILL }},
+ { &hf_h245_maximumAL1MPDUSize,
+ { "maximumAL1MPDUSize", "h245.maximumAL1MPDUSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumAL1MPDUSize value", HFILL }},
+ { &hf_h245_maximumAL2MSDUSize,
+ { "maximumAL2MSDUSize", "h245.maximumAL2MSDUSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumAL2MSDUSize value", HFILL }},
+ { &hf_h245_maximumAL3MSDUSize,
+ { "maximumAL3MSDUSize", "h245.maximumAL3MSDUSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumAL3MSDUSize value", HFILL }},
+ { &hf_h245_numOfDLCS,
+ { "numOfDLCS", "h245.numOfDLCS", FT_UINT32, BASE_DEC,
+ NULL, 0, "numOfDLCS value", HFILL }},
+ { &hf_h245_n401Capability,
+ { "n401Capability", "h245.n401Capability", FT_UINT32, BASE_DEC,
+ NULL, 0, "n401Capability value", HFILL }},
+ { &hf_h245_maxWindowSizeCapability,
+ { "maxWindowSizeCapability", "h245.maxWindowSizeCapability", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxWindowSizeCapability value", HFILL }},
+ { &hf_h245_maximumAudioDelayJitter,
+ { "maximumAudioDelayJitter", "h245.maximumAudioDelayJitter", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumAudioDelayJitter value", HFILL }},
+ { &hf_h245_tokenRate,
+ { "tokenRate", "h245.tokenRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "tokenRate value", HFILL }},
+ { &hf_h245_bucketSize,
+ { "bucketSize", "h245.bucketSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "bucketSize value", HFILL }},
+ { &hf_h245_peakRate,
+ { "peakRate", "h245.peakRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "peakRate value", HFILL }},
+ { &hf_h245_minPoliced,
+ { "minPoliced", "h245.minPoliced", FT_UINT32, BASE_DEC,
+ NULL, 0, "minPoliced value", HFILL }},
+ { &hf_h245_maxPktSize,
+ { "maxPktSize", "h245.maxPktSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxPktSize value", HFILL }},
+ { &hf_h245_maxNTUSize,
+ { "maxNTUSize", "h245.maxNTUSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxNTUSize value", HFILL }},
+ { &hf_h245_numberOfThreads,
+ { "numberOfThreads", "h245.numberOfThreads", FT_UINT32, BASE_DEC,
+ NULL, 0, "numberOfThreads value", HFILL }},
+ { &hf_h245_framesBetweenSyncPoints,
+ { "framesBetweenSyncPoints", "h245.framesBetweenSyncPoints", FT_UINT32, BASE_DEC,
+ NULL, 0, "framesBetweenSyncPoints value", HFILL }},
+ { &hf_h245_threadNumber,
+ { "threadNumber", "h245.threadNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "threadNumber value", HFILL }},
+ { &hf_h245_qcifMPI_1_4,
+ { "qcifMPI_1_4", "h245.qcifMPI_1_4", FT_UINT32, BASE_DEC,
+ NULL, 0, "qcifMPI_1_4 value", HFILL }},
+ { &hf_h245_qcifMPI_1_32,
+ { "qcifMPI_1_32", "h245.qcifMPI_1_32", FT_UINT32, BASE_DEC,
+ NULL, 0, "qcifMPI_1_32 value", HFILL }},
+ { &hf_h245_qcifMPI_1_2048,
+ { "qcifMPI_1_2048", "h245.qcifMPI_1_2048", FT_UINT32, BASE_DEC,
+ NULL, 0, "qcifMPI_1_2048 value", HFILL }},
+ { &hf_h245_cifMPI_1_4,
+ { "cifMPI_1_4", "h245.cifMPI_1_4", FT_UINT32, BASE_DEC,
+ NULL, 0, "cifMPI_1_4 value", HFILL }},
+ { &hf_h245_cifMPI_1_32,
+ { "cifMPI_1_32", "h245.cifMPI_1_32", FT_UINT32, BASE_DEC,
+ NULL, 0, "cifMPI_1_32 value", HFILL }},
+ { &hf_h245_cifMPI_1_2048,
+ { "cifMPI_1_2048", "h245.cifMPI_1_2048", FT_UINT32, BASE_DEC,
+ NULL, 0, "cifMPI_1_2048 value", HFILL }},
+ { &hf_h245_videoBitRate,
+ { "videoBitRate", "h245.videoBitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "videoBitRate value (units 400 bit/s)", HFILL }},
+ { &hf_h245_vbvBufferSize,
+ { "vbvBufferSize", "h245.vbvBufferSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "vbvBufferSize value (units 16384 bits)", HFILL }},
+ { &hf_h245_samplesPerLine,
+ { "samplesPerLine", "h245.samplesPerLine", FT_UINT32, BASE_DEC,
+ NULL, 0, "samplesPerLine value", HFILL }},
+ { &hf_h245_linesPerFrame,
+ { "linesPerFrame", "h245.linesPerFrame", FT_UINT32, BASE_DEC,
+ NULL, 0, "linesPerFrame value", HFILL }},
+ { &hf_h245_framesPerSecond,
+ { "framesPerSecond", "h245.framesPerSecond", FT_UINT32, BASE_DEC,
+ NULL, 0, "framesPerSecond value", HFILL }},
+ { &hf_h245_luminanceSampleRate,
+ { "luminanceSampleRate", "h245.luminanceSampleRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "luminanceSampleRate value", HFILL }},
+ { &hf_h245_sqcifMPI_1_32,
+ { "sqcifMPI_1_32", "h245.sqcifMPI_1_32", FT_UINT32, BASE_DEC,
+ NULL, 0, "sqcifMPI_1_32 value", HFILL }},
+ { &hf_h245_sqcifMPI_1_2048,
+ { "sqcifMPI_1_2048", "h245.sqcifMPI_1_2048", FT_UINT32, BASE_DEC,
+ NULL, 0, "sqcifMPI_1_2048 value", HFILL }},
+ { &hf_h245_cif4MPI_1_32,
+ { "cif4MPI_1_32", "h245.cif4MPI_1_32", FT_UINT32, BASE_DEC,
+ NULL, 0, "cif4MPI_1_32 value", HFILL }},
+ { &hf_h245_cif4MPI_1_2048,
+ { "cif4MPI_1_2048", "h245.cif4MPI_1_2048", FT_UINT32, BASE_DEC,
+ NULL, 0, "cif4MPI_1_2048 value", HFILL }},
+ { &hf_h245_cif16MPI_1_32,
+ { "cif16MPI_1_32", "h245.cif16MPI_1_32", FT_UINT32, BASE_DEC,
+ NULL, 0, "cif16MPI_1_32 value", HFILL }},
+ { &hf_h245_cif16MPI_1_2048,
+ { "cif16MPI_1_2048", "h245.cif16MPI_1_2048", FT_UINT32, BASE_DEC,
+ NULL, 0, "cif16MPI_1_2048 value", HFILL }},
+ { &hf_h245_maxBitRate_192400,
+ { "maxBitRate_192400", "h245.maxBitRate_192400", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxBitRate_192400 value", HFILL }},
+ { &hf_h245_hrd_B,
+ { "hrd_B", "h245.hrd_B", FT_UINT32, BASE_DEC,
+ NULL, 0, "hrd_B value", HFILL }},
+ { &hf_h245_bppMaxKb,
+ { "bppMaxKb", "h245.bppMaxKb", FT_UINT32, BASE_DEC,
+ NULL, 0, "bppMaxKb value", HFILL }},
+ { &hf_h245_slowSqcifMPI,
+ { "slowSqcifMPI", "h245.slowSqcifMPI", FT_UINT32, BASE_DEC,
+ NULL, 0, "slowSqcifMPI value", HFILL }},
+ { &hf_h245_slowQcifMPI,
+ { "slowQcifMPI", "h245.slowQcifMPI", FT_UINT32, BASE_DEC,
+ NULL, 0, "slowQcifMPI value", HFILL }},
+ { &hf_h245_slowCifMPI,
+ { "slowCifMPI", "h245.slowCifMPI", FT_UINT32, BASE_DEC,
+ NULL, 0, "slowCifMPI value", HFILL }},
+ { &hf_h245_slowCif4MPI,
+ { "slowCif4MPI", "h245.slowCif4MPI", FT_UINT32, BASE_DEC,
+ NULL, 0, "slowCif4MPI value", HFILL }},
+ { &hf_h245_slowCif16MPI,
+ { "slowCif16MPI", "h245.slowCif16MPI", FT_UINT32, BASE_DEC,
+ NULL, 0, "slowCif16MPI value", HFILL }},
+ { &hf_h245_numberOfBPictures,
+ { "numberOfBPictures", "h245.numberOfBPictures", FT_UINT32, BASE_DEC,
+ NULL, 0, "numberOfBPictures value", HFILL }},
+ { &hf_h245_presentationOrder,
+ { "presentationOrder", "h245.presentationOrder", FT_UINT32, BASE_DEC,
+ NULL, 0, "presentationOrder value", HFILL }},
+ { &hf_h245_offset_x,
+ { "offset_x", "h245.offset_x", FT_UINT32, BASE_DEC,
+ NULL, 0, "offset_x value", HFILL }},
+ { &hf_h245_offset_y,
+ { "offset_y", "h245.offset_y", FT_UINT32, BASE_DEC,
+ NULL, 0, "offset_y value", HFILL }},
+ { &hf_h245_scale_x,
+ { "scale_x", "h245.scale_x", FT_UINT32, BASE_DEC,
+ NULL, 0, "scale_x value", HFILL }},
+ { &hf_h245_scale_y,
+ { "scale_y", "h245.scale_y", FT_UINT32, BASE_DEC,
+ NULL, 0, "scale_y value", HFILL }},
+ { &hf_h245_sqcifAdditionalPictureMemory,
+ { "sqcifAdditionalPictureMemory", "h245.sqcifAdditionalPictureMemory", FT_UINT32, BASE_DEC,
+ NULL, 0, "sqcifAdditionalPictureMemory value", HFILL }},
+ { &hf_h245_qcifAdditionalPictureMemory,
+ { "qcifAdditionalPictureMemory", "h245.qcifAdditionalPictureMemory", FT_UINT32, BASE_DEC,
+ NULL, 0, "qcifAdditionalPictureMemory value", HFILL }},
+ { &hf_h245_cifAdditionalPictureMemory,
+ { "cifAdditionalPictureMemory", "h245.cifAdditionalPictureMemory", FT_UINT32, BASE_DEC,
+ NULL, 0, "cifAdditionalPictureMemory value", HFILL }},
+ { &hf_h245_cif4AdditionalPictureMemory,
+ { "cif4AdditionalPictureMemory", "h245.cif4AdditionalPictureMemory", FT_UINT32, BASE_DEC,
+ NULL, 0, "cif4AdditionalPictureMemory value", HFILL }},
+ { &hf_h245_cif16AdditionalPictureMemory,
+ { "cif16AdditionalPictureMemory", "h245.cif16AdditionalPictureMemory", FT_UINT32, BASE_DEC,
+ NULL, 0, "cif16AdditionalPictureMemory value", HFILL }},
+ { &hf_h245_bigCpfAdditionalPictureMemory,
+ { "bigCpfAdditionalPictureMemory", "h245.bigCpfAdditionalPictureMemory", FT_UINT32, BASE_DEC,
+ NULL, 0, "bigCpfAdditionalPictureMemory value", HFILL }},
+ { &hf_h245_mpuHorizMBs,
+ { "mpuHorizMBs", "h245.mpuHorizMBs", FT_UINT32, BASE_DEC,
+ NULL, 0, "mpuHorizMBs value", HFILL }},
+ { &hf_h245_mpuVertMBs,
+ { "mpuVertMBs", "h245.mpuVertMBs", FT_UINT32, BASE_DEC,
+ NULL, 0, "mpuVertMBs value", HFILL }},
+ { &hf_h245_mpuTotalNumber,
+ { "mpuTotalNumber", "h245.mpuTotalNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "mpuTotalNumber value", HFILL }},
+ { &hf_h245_clockConversionCode,
+ { "clockConversionCode", "h245.clockConversionCode", FT_UINT32, BASE_DEC,
+ NULL, 0, "clockConversionCode value", HFILL }},
+ { &hf_h245_clockDivisor,
+ { "clockDivisor", "h245.clockDivisor", FT_UINT32, BASE_DEC,
+ NULL, 0, "clockDivisor value", HFILL }},
+ { &hf_h245_maxCustomPictureWidth,
+ { "maxCustomPictureWidth", "h245.maxCustomPictureWidth", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxCustomPictureWidth value", HFILL }},
+ { &hf_h245_minCustomPictureWidth,
+ { "minCustomPictureWidth", "h245.minCustomPictureWidth", FT_UINT32, BASE_DEC,
+ NULL, 0, "minCustomPictureWidth value", HFILL }},
+ { &hf_h245_minCustomPictureHeight,
+ { "minCustomPictureHeight", "h245.minCustomPictureHeight", FT_UINT32, BASE_DEC,
+ NULL, 0, "minCustomPictureHeight value", HFILL }},
+ { &hf_h245_maxCustomPictureHeight,
+ { "maxCustomPictureHeight", "h245.maxCustomPictureHeight", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxCustomPictureHeight value", HFILL }},
+ { &hf_h245_standardMPI,
+ { "standardMPI", "h245.standardMPI", FT_UINT32, BASE_DEC,
+ NULL, 0, "standardMPI value", HFILL }},
+ { &hf_h245_customMPI,
+ { "customMPI", "h245.customMPI", FT_UINT32, BASE_DEC,
+ NULL, 0, "customMPI value", HFILL }},
+ { &hf_h245_width,
+ { "width", "h245.width", FT_UINT32, BASE_DEC,
+ NULL, 0, "width value", HFILL }},
+ { &hf_h245_height,
+ { "height", "h245.height", FT_UINT32, BASE_DEC,
+ NULL, 0, "height value", HFILL }},
+ { &hf_h245_pictureRate,
+ { "pictureRate", "h245.pictureRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "pictureRate value", HFILL }},
+ { &hf_h245_g711Alaw64k,
+ { "g711Alaw64k", "h245.g711Alaw64k", FT_UINT32, BASE_DEC,
+ NULL, 0, "g711Alaw64k value", HFILL }},
+ { &hf_h245_g711Alaw56k,
+ { "g711Alaw56k", "h245.g711Alaw56k", FT_UINT32, BASE_DEC,
+ NULL, 0, "g711Alaw56k value", HFILL }},
+ { &hf_h245_g711Ulaw64k,
+ { "g711Ulaw64k", "h245.g711Ulaw64k", FT_UINT32, BASE_DEC,
+ NULL, 0, "g711Ulaw64k value", HFILL }},
+ { &hf_h245_g711Ulaw56k,
+ { "g711Ulaw56k", "h245.g711Ulaw56k", FT_UINT32, BASE_DEC,
+ NULL, 0, "g711Ulaw56k value", HFILL }},
+ { &hf_h245_g722_64k,
+ { "g722_64k", "h245.g722_64k", FT_UINT32, BASE_DEC,
+ NULL, 0, "g722_64k value", HFILL }},
+ { &hf_h245_g722_56k,
+ { "g722_56k", "h245.g722_56k", FT_UINT32, BASE_DEC,
+ NULL, 0, "g722_56k value", HFILL }},
+ { &hf_h245_g722_48k,
+ { "g722_48k", "h245.g722_48k", FT_UINT32, BASE_DEC,
+ NULL, 0, "g722_48k value", HFILL }},
+ { &hf_h245_maxAl_sduAudioFrames,
+ { "maxAl_sduAudioFrames", "h245.maxAl_sduAudioFrames", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxAl_sduAudioFrames value", HFILL }},
+ { &hf_h245_g728,
+ { "g728", "h245.g728", FT_UINT32, BASE_DEC,
+ NULL, 0, "g728 value", HFILL }},
+ { &hf_h245_g729,
+ { "g729", "h245.g729", FT_UINT32, BASE_DEC,
+ NULL, 0, "g729 value", HFILL }},
+ { &hf_h245_g729AnnexA,
+ { "g729AnnexA", "h245.g729AnnexA", FT_UINT32, BASE_DEC,
+ NULL, 0, "g729AnnexA value", HFILL }},
+ { &hf_h245_g729wAnnexB,
+ { "g729wAnnexB", "h245.g729wAnnexB", FT_UINT32, BASE_DEC,
+ NULL, 0, "g729wAnnexB value", HFILL }},
+ { &hf_h245_g729AnnexAwAnnexB,
+ { "g729AnnexAwAnnexB", "h245.g729AnnexAwAnnexB", FT_UINT32, BASE_DEC,
+ NULL, 0, "g729AnnexAwAnnexB value", HFILL }},
+ { &hf_h245_audioUnit,
+ { "audioUnit", "h245.audioUnit", FT_UINT32, BASE_DEC,
+ NULL, 0, "audioUnit value", HFILL }},
+ { &hf_h245_highRateMode0,
+ { "highRateMode0", "h245.highRateMode0", FT_UINT32, BASE_DEC,
+ NULL, 0, "highRateMode0 value", HFILL }},
+ { &hf_h245_highRateMode1,
+ { "highRateMode1", "h245.highRateMode1", FT_UINT32, BASE_DEC,
+ NULL, 0, "highRateMode1 value", HFILL }},
+ { &hf_h245_lowRateMode0,
+ { "lowRateMode0", "h245.lowRateMode0", FT_UINT32, BASE_DEC,
+ NULL, 0, "lowRateMode0 value", HFILL }},
+ { &hf_h245_lowRateMode1,
+ { "lowRateMode1", "h245.lowRateMode1", FT_UINT32, BASE_DEC,
+ NULL, 0, "lowRateMode1 value", HFILL }},
+ { &hf_h245_sidMode0,
+ { "sidMode0", "h245.sidMode0", FT_UINT32, BASE_DEC,
+ NULL, 0, "sidMode0 value", HFILL }},
+ { &hf_h245_sidMode1,
+ { "sidMode1", "h245.sidMode1", FT_UINT32, BASE_DEC,
+ NULL, 0, "sidMode1 value", HFILL }},
+ { &hf_h245_audioUnitSize,
+ { "audioUnitSize", "h245.audioUnitSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "audioUnitSize value", HFILL }},
+ { &hf_h245_maxBitRate_4294967295UL,
+ { "maxBitRate_4294967295UL", "h245.maxBitRate_4294967295UL", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxBitRate value in units of 100bits/s", HFILL }},
+ { &hf_h245_numberOfCodewords,
+ { "numberOfCodewords", "h245.numberOfCodewords", FT_UINT32, BASE_DEC,
+ NULL, 0, "numberOfCodewords value", HFILL }},
+ { &hf_h245_maximumStringLength,
+ { "maximumStringLength", "h245.maximumStringLength", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumStringLength value", HFILL }},
+ { &hf_h245_version,
+ { "version", "h245.version", FT_UINT32, BASE_DEC,
+ NULL, 0, "version value", HFILL }},
+ { &hf_h245_standard_0_127,
+ { "standard_0_127", "h245.standard_0_127", FT_UINT32, BASE_DEC,
+ NULL, 0, "standard_0_127 value", HFILL }},
+ { &hf_h245_booleanArray,
+ { "booleanArray", "h245.booleanArray", FT_UINT32, BASE_DEC,
+ NULL, 0, "booleanArray value", HFILL }},
+ { &hf_h245_unsignedMin,
+ { "unsignedMin", "h245.unsignedMin", FT_UINT32, BASE_DEC,
+ NULL, 0, "unsignedMin value", HFILL }},
+ { &hf_h245_unsignedMax,
+ { "unsignedMax", "h245.unsignedMax", FT_UINT32, BASE_DEC,
+ NULL, 0, "unsignedMax value", HFILL }},
+ { &hf_h245_unsigned32Min,
+ { "unsigned32Min", "h245.unsigned32Min", FT_UINT32, BASE_DEC,
+ NULL, 0, "unsigned32Min value", HFILL }},
+ { &hf_h245_unsigned32Max,
+ { "unsigned32Max", "h245.unsigned32Max", FT_UINT32, BASE_DEC,
+ NULL, 0, "unsigned32Max value", HFILL }},
+ { &hf_h245_dynamicRTPPayloadType,
+ { "dynamicRTPPayloadType", "h245.dynamicRTPPayloadType", FT_UINT32, BASE_DEC,
+ NULL, 0, "dynamicRTPPayloadType value", HFILL }},
+ { &hf_h245_portNumber,
+ { "portNumber", "h245.portNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "portNumber value", HFILL }},
+ { &hf_h245_resourceID,
+ { "resourceID", "h245.resourceID", FT_UINT32, BASE_DEC,
+ NULL, 0, "resourceID value", HFILL }},
+ { &hf_h245_subChannelID,
+ { "subChannelID", "h245.subChannelID", FT_UINT32, BASE_DEC,
+ NULL, 0, "subChannelID value", HFILL }},
+ { &hf_h245_pcr_pid,
+ { "pcr_pid", "h245.pcr_pid", FT_UINT32, BASE_DEC,
+ NULL, 0, "pcr_pid value", HFILL }},
+ { &hf_h245_controlFieldOctets,
+ { "controlFieldOctets", "h245.controlFieldOctets", FT_UINT32, BASE_DEC,
+ NULL, 0, "controlFieldOctets value", HFILL }},
+ { &hf_h245_sendBufferSize,
+ { "sendBufferSize", "h245.sendBufferSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "sendBufferSize value", HFILL }},
+ { &hf_h245_rcpcCodeRate,
+ { "rcpcCodeRate", "h245.rcpcCodeRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "rcpcCodeRate value", HFILL }},
+ { &hf_h245_rsCodeCorrection,
+ { "rsCodeCorrection", "h245.rsCodeCorrection", FT_UINT32, BASE_DEC,
+ NULL, 0, "rsCodeCorrection value", HFILL }},
+ { &hf_h245_finite_0_16,
+ { "finite_0_16", "h245.finite_0_16", FT_UINT32, BASE_DEC,
+ NULL, 0, "finite_0_16 value", HFILL }},
+ { &hf_h245_windowSize,
+ { "windowSize", "h245.windowSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "windowSize value", HFILL }},
+ { &hf_h245_n401,
+ { "n401", "h245.n401", FT_UINT32, BASE_DEC,
+ NULL, 0, "n401 value", HFILL }},
+ { &hf_h245_sessionID_0_255,
+ { "sessionID_0_255", "h245.sessionID_0_255", FT_UINT32, BASE_DEC,
+ NULL, 0, "sessionID_0_255 value", HFILL }},
+ { &hf_h245_sessionID_1_255,
+ { "sessionID_1_255", "h245.sessionID_1_255", FT_UINT32, BASE_DEC,
+ NULL, 0, "sessionID_1_255 value", HFILL }},
+ { &hf_h245_associatedSessionID,
+ { "associatedSessionID", "h245.associatedSessionID", FT_UINT32, BASE_DEC,
+ NULL, 0, "associatedSessionID value", HFILL }},
+ { &hf_h245_payloadType,
+ { "payloadType", "h245.payloadType", FT_UINT32, BASE_DEC,
+ NULL, 0, "payloadType value", HFILL }},
+ { &hf_h245_protectedSessionID,
+ { "protectedSessionID", "h245.protectedSessionID", FT_UINT32, BASE_DEC,
+ NULL, 0, "protectedSessionID value", HFILL }},
+ { &hf_h245_protectedPayloadType,
+ { "protectedPayloadType", "h245.protectedPayloadType", FT_UINT32, BASE_DEC,
+ NULL, 0, "protectedPayloadType value", HFILL }},
+ { &hf_h245_tsapIdentifier,
+ { "tsapIdentifier", "h245.tsapIdentifier", FT_UINT32, BASE_DEC,
+ NULL, 0, "tsapIdentifier value", HFILL }},
+ { &hf_h245_synchFlag,
+ { "synchFlag", "h245.synchFlag", FT_UINT32, BASE_DEC,
+ NULL, 0, "synchFlag value", HFILL }},
+ { &hf_h245_finite_1_65535,
+ { "finite_1_65535", "h245.finite_1_65535", FT_UINT32, BASE_DEC,
+ NULL, 0, "finite_1_65535 value", HFILL }},
+ { &hf_h245_MultiplexTableEntryNumber,
+ { "MultiplexTableEntryNumber", "h245.MultiplexTableEntryNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "MultiplexTableEntryNumber value", HFILL }},
+ { &hf_h245_dataModeBitRate,
+ { "dataModeBitRate", "h245.dataModeBitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "dataModeBitRate value", HFILL }},
+ { &hf_h245_sessionDependency,
+ { "sessionDependency", "h245.sessionDependency", FT_UINT32, BASE_DEC,
+ NULL, 0, "sessionDependency value", HFILL }},
+ { &hf_h245_sRandom,
+ { "sRandom", "h245.sRandom", FT_UINT32, BASE_DEC,
+ NULL, 0, "sRandom value", HFILL }},
+ { &hf_h245_McuNumber,
+ { "McuNumber", "h245.McuNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "McuNumber value", HFILL }},
+ { &hf_h245_TerminalNumber,
+ { "TerminalNumber", "h245.TerminalNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "TerminalNumber value", HFILL }},
+ { &hf_h245_maxNumberOfAdditionalConnections,
+ { "maxNumberOfAdditionalConnections", "h245.maxNumberOfAdditionalConnections", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxNumberOfAdditionalConnections value", HFILL }},
+ { &hf_h245_requestedInterval,
+ { "requestedInterval", "h245.requestedInterval", FT_UINT32, BASE_DEC,
+ NULL, 0, "requestedInterval value", HFILL }},
+ { &hf_h245_callAssociationNumber,
+ { "callAssociationNumber", "h245.callAssociationNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "callAssociationNumber value", HFILL }},
+ { &hf_h245_currentInterval,
+ { "currentInterval", "h245.currentInterval", FT_UINT32, BASE_DEC,
+ NULL, 0, "currentInterval value", HFILL }},
+ { &hf_h245_infoNotAvailable,
+ { "infoNotAvailable", "h245.infoNotAvailable", FT_UINT32, BASE_DEC,
+ NULL, 0, "infoNotAvailable value", HFILL }},
+ { &hf_h245_channelTag,
+ { "channelTag", "h245.channelTag", FT_UINT32, BASE_DEC,
+ NULL, 0, "channelTag value", HFILL }},
+ { &hf_h245_ConnectionIDsequenceNumber,
+ { "ConnectionIDsequenceNumber", "h245.ConnectionIDsequenceNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "ConnectionIDsequenceNumber value", HFILL }},
+ { &hf_h245_MaximumBitRate,
+ { "MaximumBitRate", "h245.MaximumBitRate", FT_UINT32, BASE_DEC,
+ NULL, 0, "MaximumBitRate value", HFILL }},
+ { &hf_h245_maximumBitRate_0_16777215,
+ { "maximumBitRate_0_16777215", "h245.maximumBitRate_0_16777215", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumBitRate_0_16777215 value", HFILL }},
+ { &hf_h245_firstGOB_0_17,
+ { "firstGOB_0_17", "h245.firstGOB_0_17", FT_UINT32, BASE_DEC,
+ NULL, 0, "firstGOB_0_17 value", HFILL }},
+ { &hf_h245_numberOfGOBs,
+ { "numberOfGOBs", "h245.numberOfGOBs", FT_UINT32, BASE_DEC,
+ NULL, 0, "numberOfGOBs value", HFILL }},
+ { &hf_h245_videoTemporalSpatialTradeOff,
+ { "videoTemporalSpatialTradeOff", "h245.videoTemporalSpatialTradeOff", FT_UINT32, BASE_DEC,
+ NULL, 0, "videoTemporalSpatialTradeOff value", HFILL }},
+ { &hf_h245_firstGOB_0_255,
+ { "firstGOB_0_255", "h245.firstGOB_0_255", FT_UINT32, BASE_DEC,
+ NULL, 0, "firstGOB_0_255 value", HFILL }},
+ { &hf_h245_firstMB_1_8192,
+ { "firstMB_1_8192", "h245.firstMB_1_8192", FT_UINT32, BASE_DEC,
+ NULL, 0, "firstMB_1_8192 value", HFILL }},
+ { &hf_h245_firstMB_1_9216,
+ { "firstMB_1_9216", "h245.firstMB_1_9216", FT_UINT32, BASE_DEC,
+ NULL, 0, "firstMB_1_9216 value", HFILL }},
+ { &hf_h245_numberOfMBs_1_8192,
+ { "numberOfMBs_1_8192", "h245.numberOfMBs_1_8192", FT_UINT32, BASE_DEC,
+ NULL, 0, "numberOfMBs_1_8192 value", HFILL }},
+ { &hf_h245_numberOfMBs_1_9216,
+ { "numberOfMBs_1_9216", "h245.numberOfMBs_1_9216", FT_UINT32, BASE_DEC,
+ NULL, 0, "numberOfMBs_1_9216 value", HFILL }},
+ { &hf_h245_maxH223MUXPDUsize,
+ { "maxH223MUXPDUsize", "h245.maxH223MUXPDUsize", FT_UINT32, BASE_DEC,
+ NULL, 0, "maxH223MUXPDUsize value", HFILL }},
+ { &hf_h245_temporalReference_0_1023,
+ { "temporalReference_0_1023", "h245.temporalReference_0_1023", FT_UINT32, BASE_DEC,
+ NULL, 0, "temporalReference_0_1023 value", HFILL }},
+ { &hf_h245_temporalReference_0_255,
+ { "temporalReference_0_255", "h245.temporalReference_0_255", FT_UINT32, BASE_DEC,
+ NULL, 0, "temporalReference_0_255 value", HFILL }},
+ { &hf_h245_pictureNumber,
+ { "pictureNumber", "h245.pictureNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "pictureNumber value", HFILL }},
+ { &hf_h245_longTermPictureIndex,
+ { "longTermPictureIndex", "h245.longTermPictureIndex", FT_UINT32, BASE_DEC,
+ NULL, 0, "longTermPictureIndex value", HFILL }},
+ { &hf_h245_sampleSize,
+ { "sampleSize", "h245.sampleSize", FT_UINT32, BASE_DEC,
+ NULL, 0, "sampleSize value", HFILL }},
+ { &hf_h245_samplesPerFrame,
+ { "samplesPerFrame", "h245.samplesPerFrame", FT_UINT32, BASE_DEC,
+ NULL, 0, "samplesPerFrame value", HFILL }},
+ { &hf_h245_sbeNumber,
+ { "sbeNumber", "h245.sbeNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "sbeNumber value", HFILL }},
+ { &hf_h245_subPictureNumber,
+ { "subPictureNumber", "h245.subPictureNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "subPictureNumber value", HFILL }},
+ { &hf_h245_compositionNumber,
+ { "compositionNumber", "h245.compositionNumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "compositionNumber value", HFILL }},
+ { &hf_h245_estimatedReceivedJitterMantissa,
+ { "estimatedReceivedJitterMantissa", "h245.estimatedReceivedJitterMantissa", FT_UINT32, BASE_DEC,
+ NULL, 0, "estimatedReceivedJitterMantissa value", HFILL }},
+ { &hf_h245_estimatedReceivedJitterExponent,
+ { "estimatedReceivedJitterExponent", "h245.estimatedReceivedJitterExponent", FT_UINT32, BASE_DEC,
+ NULL, 0, "estimatedReceivedJitterExponent value", HFILL }},
+ { &hf_h245_skippedFrameCount,
+ { "skippedFrameCount", "h245.skippedFrameCount", FT_UINT32, BASE_DEC,
+ NULL, 0, "skippedFrameCount value", HFILL }},
+ { &hf_h245_additionalDecoderBuffer,
+ { "additionalDecoderBuffer", "h245.additionalDecoderBuffer", FT_UINT32, BASE_DEC,
+ NULL, 0, "additionalDecoderBuffer value", HFILL }},
+ { &hf_h245_skew,
+ { "skew", "h245.skew", FT_UINT32, BASE_DEC,
+ NULL, 0, "skew value", HFILL }},
+ { &hf_h245_maximumSkew,
+ { "maximumSkew", "h245.maximumSkew", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximumSkew value", HFILL }},
+ { &hf_h245_duration,
+ { "duration", "h245.duration", FT_UINT32, BASE_DEC,
+ NULL, 0, "duration value", HFILL }},
+ { &hf_h245_timestamp,
+ { "timestamp", "h245.timestamp", FT_UINT32, BASE_DEC,
+ NULL, 0, "timestamp value", HFILL }},
+ { &hf_h245_frame,
+ { "frame", "h245.frame", FT_UINT32, BASE_DEC,
+ NULL, 0, "frame", HFILL }},
+ { &hf_h245_containedThread,
+ { "containedThread", "h245.containedThread", FT_UINT32, BASE_DEC,
+ NULL, 0, "containedThread value", HFILL }},
+ { &hf_h245_t38FaxMaxDatagram,
+ { "t38FaxMaxDatagram", "h245.t38FaxMaxDatagram", FT_INT32, BASE_DEC,
+ NULL, 0, "t38FaxMaxDatagram value", HFILL }},
+ { &hf_h245_t38FaxMaxBuffer,
+ { "t38FaxMaxBuffer", "h245.t38FaxMaxBuffer", FT_INT32, BASE_DEC,
+ NULL, 0, "t38FaxMaxBuffer value", HFILL }},
+ { &hf_h245_expirationTime,
+ { "expirationTime", "h245.expirationTime", FT_UINT32, BASE_DEC,
+ NULL, 0, "expirationTime value", HFILL }},
+ { &hf_h245_rfc_number,
+ { "RFC", "h245.rfc_number", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of the RFC where this can be found", HFILL }},
+ { &hf_h245_object,
+ { "Object", "h245.object", FT_STRING, BASE_NONE,
+ NULL, 0, "Object Identifier", HFILL }},
+ { &hf_h245_protocolIdentifier,
+ { "protocolIdentifier", "h245.protocolIdentifier", FT_STRING, BASE_NONE,
+ NULL, 0, "protocolIdentifier object", HFILL }},
+ { &hf_h245_algorithm,
+ { "algorithm", "h245.algorithm", FT_STRING, BASE_NONE,
+ NULL, 0, "algorithm object", HFILL }},
+ { &hf_h245_antiSpamAlgorithm,
+ { "antiSpamAlgorithm", "h245.antiSpamAlgorithm", FT_STRING, BASE_NONE,
+ NULL, 0, "antiSpamAlgorithm object", HFILL }},
+ { &hf_h245_standard_object,
+ { "standard_object", "h245.standard_object", FT_STRING, BASE_NONE,
+ NULL, 0, "standard_object object", HFILL }},
+ { &hf_h245_oid,
+ { "oid", "h245.oid", FT_STRING, BASE_NONE,
+ NULL, 0, "oid object", HFILL }},
+ { &hf_h245_escrowID,
+ { "escrowID", "h245.escrowID", FT_STRING, BASE_NONE,
+ NULL, 0, "escrowID object", HFILL }},
+ { &hf_h245_field,
+ { "field", "h245.field", FT_STRING, BASE_NONE,
+ NULL, 0, "field object", HFILL }},
+ { &hf_h245_NonStandardParameterData,
+ { "data", "h245.NonStandardParameterData", FT_BYTES, BASE_HEX,
+ NULL, 0, "NonStandardParameterData", HFILL }},
+ { &hf_h245_nlpidData,
+ { "nlpidData", "h245.nlpidData", FT_BYTES, BASE_HEX,
+ NULL, 0, "nlpidData octet string", HFILL }},
+ { &hf_h245_nonCollapsingRaw,
+ { "nonCollapsingRaw", "h245.nonCollapsingRaw", FT_BYTES, BASE_HEX,
+ NULL, 0, "nonCollapsingRaw octet string", HFILL }},
+ { &hf_h245_uuid,
+ { "uuid", "h245.uuid", FT_BYTES, BASE_HEX,
+ NULL, 0, "uuid octet string", HFILL }},
+ { &hf_h245_octetString,
+ { "octetString", "h245.octetString", FT_BYTES, BASE_HEX,
+ NULL, 0, "octetString octet string", HFILL }},
+ { &hf_h245_externalReference,
+ { "externalReference", "h245.externalReference", FT_BYTES, BASE_HEX,
+ NULL, 0, "externalReference octet string", HFILL }},
+ { &hf_h245_nsapAddress,
+ { "nsapAddress", "h245.nsapAddress", FT_BYTES, BASE_HEX,
+ NULL, 0, "nsapAddress octet string", HFILL }},
+ { &hf_h245_subaddress_1_20,
+ { "subaddress_1_20", "h245.subaddress_1_20", FT_BYTES, BASE_HEX,
+ NULL, 0, "subaddress_1_20 octet string", HFILL }},
+ { &hf_h245_programDescriptors,
+ { "programDescriptors", "h245.programDescriptors", FT_BYTES, BASE_HEX,
+ NULL, 0, "programDescriptors octet string", HFILL }},
+ { &hf_h245_streamDescriptors,
+ { "streamDescriptors", "h245.streamDescriptors", FT_BYTES, BASE_HEX,
+ NULL, 0, "streamDescriptors octet string", HFILL }},
+ { &hf_h245_ipv4network,
+ { "ipv4network", "h245.ipv4network", FT_IPv4, BASE_NONE,
+ NULL, 0, "IPv4 Address", HFILL }},
+ { &hf_h245_ipxNode,
+ { "ipxNode", "h245.ipxNode", FT_BYTES, BASE_HEX,
+ NULL, 0, "ipxNode octet string", HFILL }},
+ { &hf_h245_ipxNetnum,
+ { "ipxNetnum", "h245.ipxNetnum", FT_BYTES, BASE_HEX,
+ NULL, 0, "ipxNetnum octet string", HFILL }},
+ { &hf_h245_ipv6network,
+ { "ipv6network", "h245.ipv6network", FT_BYTES, BASE_HEX,
+ NULL, 0, "ipv6network octet string", HFILL }},
+ { &hf_h245_netBios,
+ { "netBios", "h245.netBios", FT_BYTES, BASE_HEX,
+ NULL, 0, "netBios octet string", HFILL }},
+ { &hf_h245_nsap,
+ { "nsap", "h245.nsap", FT_BYTES, BASE_HEX,
+ NULL, 0, "nsap octet string", HFILL }},
+ { &hf_h245_h235Key,
+ { "h235Key", "h245.h235Key", FT_BYTES, BASE_HEX,
+ NULL, 0, "h235Key octet string", HFILL }},
+ { &hf_h245_value,
+ { "value", "h245.value", FT_BYTES, BASE_HEX,
+ NULL, 0, "value octet string", HFILL }},
+ { &hf_h245_certificateResponse,
+ { "certificateResponse", "h245.certificateResponse", FT_BYTES, BASE_HEX,
+ NULL, 0, "certificateResponse octet string", HFILL }},
+ { &hf_h245_TerminalID,
+ { "TerminalID", "h245.TerminalID", FT_BYTES, BASE_HEX,
+ NULL, 0, "TerminalID octet string", HFILL }},
+ { &hf_h245_ConferenceID,
+ { "ConferenceID", "h245.ConferenceID", FT_BYTES, BASE_HEX,
+ NULL, 0, "ConferenceID octet string", HFILL }},
+ { &hf_h245_Password,
+ { "Password", "h245.Password", FT_BYTES, BASE_HEX,
+ NULL, 0, "Password octet string", HFILL }},
+ { &hf_h245_encryptionSE,
+ { "encryptionSE", "h245.encryptionSE", FT_BYTES, BASE_HEX,
+ NULL, 0, "encryptionSE octet string", HFILL }},
+ { &hf_h245_conferenceIdentifier,
+ { "conferenceIdentifier", "h245.conferenceIdentifier", FT_BYTES, BASE_HEX,
+ NULL, 0, "conferenceIdentifier octet string", HFILL }},
+ { &hf_h245_returnedFunction,
+ { "returnedFunction", "h245.returnedFunction", FT_BYTES, BASE_HEX,
+ NULL, 0, "returnedFunction octet string", HFILL }},
+ { &hf_h245_productNumber,
+ { "productNumber", "h245.productNumber", FT_BYTES, BASE_HEX,
+ NULL, 0, "productNumber octet string", HFILL }},
+ { &hf_h245_versionNumber,
+ { "versionNumber", "h245.versionNumber", FT_BYTES, BASE_HEX,
+ NULL, 0, "versionNumber octet string", HFILL }},
+ { &hf_h245_mediaDistributionCapability,
+ { "mediaDistributionCapability", "h245.mediaDistributionCapability_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "mediaDistributionCapability sequence of", HFILL }},
+ { &hf_h245_AlternativeCapabilitySet,
+ { "AlternativeCapabilitySet", "h245.AlternativeCapabilitySet", FT_NONE, BASE_NONE,
+ NULL, 0 , "AlternativeCapabilitySet sequence of", HFILL }},
+ { &hf_h245_CapabilityTableEntryNumber_sequence_of,
+ { "CapabilityTableEntryNumber_sequence_of", "h245.CapabilityTableEntryNumber_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "CapabilityTableEntryNumber_sequence_of sequence of", HFILL }},
+ { &hf_h245_frameToThreadMapping_custom,
+ { "frameToThreadMapping_custom", "h245.frameToThreadMapping_custom", FT_NONE, BASE_NONE,
+ NULL, 0 , "frameToThreadMapping_custom sequence of", HFILL }},
+ { &hf_h245_RedundancyEncodingCapability_sequence_of,
+ { "RedundancyEncodingCapability_sequence_of", "h245.RedundancyEncodingCapability_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "RedundancyEncodingCapability_sequence_of sequence of", HFILL }},
+ { &hf_h245_frameSequence,
+ { "frameSequence", "h245.frameSequence", FT_NONE, BASE_NONE,
+ NULL, 0 , "sequence of frames", HFILL }},
+ { &hf_h245_escrowentry,
+ { "escrowentry", "h245.escrowentry", FT_NONE, BASE_NONE,
+ NULL, 0 , "escrowentry sequence of", HFILL }},
+ { &hf_h245_elementList,
+ { "elementList", "h245.elementList", FT_NONE, BASE_NONE,
+ NULL, 0 , "elementList sequence of", HFILL }},
+ { &hf_h245_subElementList,
+ { "subElementList", "h245.subElementList", FT_NONE, BASE_NONE,
+ NULL, 0 , "subElementList sequence of", HFILL }},
+ { &hf_h245_requestedModes,
+ { "requestedModes", "h245.requestedModes", FT_NONE, BASE_NONE,
+ NULL, 0 , "requestedModes sequence of", HFILL }},
+ { &hf_h245_CertSelectionCriteria,
+ { "CertSelectionCriteria", "h245.CertSelectionCriteria", FT_NONE, BASE_NONE,
+ NULL, 0 , "CertSelectionCriteria sequence of", HFILL }},
+ { &hf_h245_capabilityTable,
+ { "capabilityTable", "h245.capabilityTable", FT_NONE, BASE_NONE,
+ NULL, 0, "capabilityTable set of", HFILL }},
+ { &hf_h245_capabilityDescriptors,
+ { "capabilityDescriptors", "h245.capabilityDescriptors", FT_NONE, BASE_NONE,
+ NULL, 0, "capabilityDescriptors set of", HFILL }},
+ { &hf_h245_simultaneousCapabilities,
+ { "simultaneousCapabilities", "h245.simultaneousCapabilities", FT_NONE, BASE_NONE,
+ NULL, 0, "simultaneousCapabilities set of", HFILL }},
+ { &hf_h245_gatewayAddress,
+ { "gatewayAddress", "h245.gatewayAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "gatewayAddress set of", HFILL }},
+ { &hf_h245_snrEnhancement,
+ { "snrEnhancement", "h245.snrEnhancement", FT_NONE, BASE_NONE,
+ NULL, 0, "snrEnhancement set of", HFILL }},
+ { &hf_h245_spatialEnhancement,
+ { "spatialEnhancement", "h245.spatialEnhancement", FT_NONE, BASE_NONE,
+ NULL, 0, "spatialEnhancement set of", HFILL }},
+ { &hf_h245_bPictureEnhancement,
+ { "bPictureEnhancement", "h245.bPictureEnhancement", FT_NONE, BASE_NONE,
+ NULL, 0, "bPictureEnhancement set of", HFILL }},
+ { &hf_h245_customPictureClockFrequency,
+ { "customPictureClockFrequency", "h245.customPictureClockFrequency", FT_NONE, BASE_NONE,
+ NULL, 0, "customPictureClockFrequency set of", HFILL }},
+ { &hf_h245_customPictureFormat,
+ { "customPictureFormat", "h245.customPictureFormat", FT_NONE, BASE_NONE,
+ NULL, 0, "customPictureFormat set of", HFILL }},
+ { &hf_h245_modeCombos,
+ { "modeCombos", "h245.modeCombos", FT_NONE, BASE_NONE,
+ NULL, 0, "modeCombos set of", HFILL }},
+ { &hf_h245_customPCF,
+ { "customPCF", "h245.customPCF", FT_NONE, BASE_NONE,
+ NULL, 0, "customPCF set of", HFILL }},
+ { &hf_h245_pixelAspectCode,
+ { "pixelAspectCode", "h245.pixelAspectCode", FT_NONE, BASE_NONE,
+ NULL, 0, "pixelAspectCode set of", HFILL }},
+ { &hf_h245_extendedPAR,
+ { "extendedPAR", "h245.extendedPAR", FT_NONE, BASE_NONE,
+ NULL, 0, "extendedPAR set of", HFILL }},
+ { &hf_h245_h263VideoCoupledModes,
+ { "h263VideoCoupledModes", "h245.h263VideoCoupledModes", FT_NONE, BASE_NONE,
+ NULL, 0, "h263VideoCoupledModes set of", HFILL }},
+ { &hf_h245_capabilityOnMuxStream,
+ { "capabilityOnMuxStream", "h245.capabilityOnMuxStream", FT_NONE, BASE_NONE,
+ NULL, 0, "capabilityOnMuxStream set of", HFILL }},
+ { &hf_h245_capabilities,
+ { "capabilities", "h245.capabilities", FT_NONE, BASE_NONE,
+ NULL, 0, "capabilities set of", HFILL }},
+ { &hf_h245_multiplexEntryDescriptors,
+ { "multiplexEntryDescriptors", "h245.multiplexEntryDescriptors", FT_NONE, BASE_NONE,
+ NULL, 0, "multiplexEntryDescriptors set of", HFILL }},
+ { &hf_h245_multiplexTableEntryNumber_set_of,
+ { "multiplexTableEntryNumber_set_of", "h245.multiplexTableEntryNumber_set_of", FT_NONE, BASE_NONE,
+ NULL, 0, "multiplexTableEntryNumber_set_of set of", HFILL }},
+ { &hf_h245_VCCapability_set_of,
+ { "VCCapability_set_of", "h245.VCCapability_set_of", FT_NONE, BASE_NONE,
+ NULL, 0, "VCCapability_set_of set of", HFILL }},
+ { &hf_h245_rejectionDescriptions,
+ { "rejectionDescriptions", "h245.rejectionDescriptions", FT_NONE, BASE_NONE,
+ NULL, 0, "rejectionDescriptions set of", HFILL }},
+ { &hf_h245_entryNumbers,
+ { "entryNumbers", "h245.entryNumbers", FT_NONE, BASE_NONE,
+ NULL, 0, "entryNumbers set of", HFILL }},
+ { &hf_h245_ModeDescription,
+ { "ModeDescription", "h245.ModeDescription", FT_NONE, BASE_NONE,
+ NULL, 0, "ModeDescription set of", HFILL }},
+ { &hf_h245_communicationModeTable,
+ { "communicationModeTable", "h245.communicationModeTable", FT_NONE, BASE_NONE,
+ NULL, 0, "communicationModeTable set of", HFILL }},
+ { &hf_h245_terminalListResponse,
+ { "terminalListResponse", "h245.terminalListResponse", FT_NONE, BASE_NONE,
+ NULL, 0, "terminalListResponse set of", HFILL }},
+ { &hf_h245_differential,
+ { "differential", "h245.differential", FT_NONE, BASE_NONE,
+ NULL, 0, "differential set of", HFILL }},
+ { &hf_h245_networkType,
+ { "networkType", "h245.networkType", FT_NONE, BASE_NONE,
+ NULL, 0, "networkType set of", HFILL }},
+ { &hf_h245_capabilityTableEntryNumbers,
+ { "capabilityTableEntryNumbers", "h245.capabilityTableEntryNumbers", FT_NONE, BASE_NONE,
+ NULL, 0, "capabilityTableEntryNumbers set of", HFILL }},
+ { &hf_h245_capabilityDescriptorNumbers,
+ { "capabilityDescriptorNumbers", "h245.capabilityDescriptorNumbers", FT_NONE, BASE_NONE,
+ NULL, 0, "capabilityDescriptorNumbers set of", HFILL }},
+ { &hf_h245_qOSCapabilities,
+ { "qOSCapabilities", "h245.qOSCapabilities", FT_NONE, BASE_NONE,
+ NULL, 0 , "qOSCapabilities sequence of", HFILL }},
+ { &hf_h245_EncryptionCapability,
+ { "EncryptionCapability", "h245.EncryptionCapability", FT_NONE, BASE_NONE,
+ NULL, 0 , "EncryptionCapability sequence of", HFILL }},
+ { &hf_h245_containedThreads,
+ { "containedThreads", "h245.containedThreads", FT_NONE, BASE_NONE,
+ NULL, 0 , "containedThreads sequence of", HFILL }},
+ { &hf_h245_mediaChannelCapabilities,
+ { "mediaChannelCapabilities", "h245.mediaChannelCapabilities", FT_NONE, BASE_NONE,
+ NULL, 0 , "mediaChannelCapabilities sequence of", HFILL }},
+ { &hf_h245_rtpPayloadType_sequence_of,
+ { "rtpPayloadType_sequence_of", "h245.rtpPayloadType_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "rtpPayloadType sequence of", HFILL }},
+ { &hf_h245_centralizedData,
+ { "centralizedData", "h245.centralizedData_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "centralizedData sequence of", HFILL }},
+ { &hf_h245_distributedData,
+ { "distributedData", "h245.distributedData_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "distributedData sequence of", HFILL }},
+ { &hf_h245_nonStandardData,
+ { "nonStandardData", "h245.nonStandardData_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "nonStandardData sequence of", HFILL }},
+ { &hf_h245_collapsing,
+ { "collapsing", "h245.collapsing_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "collapsing sequence of", HFILL }},
+ { &hf_h245_nonCollapsing,
+ { "nonCollapsing", "h245.nonCollapsing_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "nonCollapsing sequence of", HFILL }},
+ { &hf_h245_supersedes,
+ { "supersedes", "h245.supersedes_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "supersedes sequence of", HFILL }},
+ { &hf_h245_genericParameter,
+ { "genericParameter", "h245.genericParameter_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "genericParameter sequence of", HFILL }},
+ { &hf_h245_secondary_REE,
+ { "secondary_REE", "h245.secondary_REE_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "secondary_REE sequence of", HFILL }},
+ { &hf_h245_elements_MPSE,
+ { "elements_MPSE", "h245.elements_MPSE_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "elements_MPSE sequence of", HFILL }},
+ { &hf_h245_secondary_REDTME,
+ { "secondary_REDTME", "h245.secondary_REDTME_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "secondary_REDTME sequence of", HFILL }},
+ { &hf_h245_elements_MPSEM,
+ { "elements_MPSEM", "h245.elements_MPSEM_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "elements_MPSEM sequence of", HFILL }},
+ { &hf_h245_TerminalInformationSO,
+ { "TerminalInformationSO", "h245.TerminalInformationSO_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "TerminalInformationSO sequence of", HFILL }},
+ { &hf_h245_lostPicture,
+ { "lostPicture", "h245.lostPicture_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "lostPicture sequence of", HFILL }},
+ { &hf_h245_recoveryReferencePicture,
+ { "recoveryReferencePicture", "h245.recoveryReferencePicture_sequence_of", FT_NONE, BASE_NONE,
+ NULL, 0 , "recoveryReferencePicture sequence of", HFILL }},
+ { &hf_h245_iPSourceRouteAddress_route,
+ { "iPSourceRouteAddress_route", "h245.iPSourceRouteAddress_route", FT_NONE, BASE_NONE,
+ NULL, 0, "iPSourceRouteAddress_route sequence of", HFILL }},
+ { &hf_h245_audioTelephoneEvent,
+ { "audioTelephoneEvent", "h245.audioTelephoneEvent", FT_STRING, FT_NONE,
+ NULL, 0, "audioTelephoneEvent string", HFILL }},
+ { &hf_h245_alphanumeric,
+ { "alphanumeric", "h245.alphanumeric", FT_STRING, FT_NONE,
+ NULL, 0, "alphanumeric string", HFILL }},
+ { &hf_h245_domainBased,
+ { "domainBased", "h245.domainBased", FT_STRING, FT_NONE,
+ NULL, 0, "String for domainBased", HFILL }},
+ { &hf_h245_subAddress,
+ { "subAddress", "h245.subAddress", FT_STRING, FT_NONE,
+ NULL, 0, "String for subAddress", HFILL }},
+ { &hf_h245_e164Address,
+ { "e164Address", "h245.e164Address", FT_STRING, FT_NONE,
+ NULL, 0, "String for e164Address", HFILL }},
+ { &hf_h245_signalType,
+ { "signalType", "h245.signalType", FT_STRING, FT_NONE,
+ NULL, 0, "String for signalType", HFILL }},
+ { &hf_h245_DialingInformationNumber_networkAddress,
+ { "networkAddress", "h245.DialingInformationNumber_networkAddress", FT_STRING, FT_NONE,
+ NULL, 0, "String for DialingInformationNumber_networkAddress", HFILL }},
+ { &hf_h245_internationalNumber,
+ { "internationalNumber", "h245.internationalNumber", FT_STRING, FT_NONE,
+ NULL, 0, "String for internationalNumber", HFILL }},
+ { &hf_h245_h221Manufacturer,
+ { "H.221 Manufacturer", "h245.h221Manufacturer", FT_UINT32, BASE_HEX,
+ VALS(H221ManufacturerCode_vals), 0, "H.221 Manufacturer", HFILL }},
+ };
+
+ static gint *ett[] =
+ {
+ &ett_h245,
+ &ett_h245_MultimediaSystemControlMessage,
+ &ett_h245_RequestMessage,
+ &ett_h245_ResponseMessage,
+ &ett_h245_IndicationMessage,
+ &ett_h245_CommandMessage,
+ &ett_h245_OpenLogicalChannelConfirm,
+ &ett_h245_EndSessionCommand,
+ &ett_h245_MobileMultilinkReconfigurationIndication,
+ &ett_h245_FlowControlIndication,
+ &ett_h245_UserInputIndication_extendedAlphanumeric,
+ &ett_h245_UserInputIndication_signalUpdate_rtp,
+ &ett_h245_UserInputIndication_signalUpdate,
+ &ett_h245_UserInputIndication_signal_rtp,
+ &ett_h245_UserInputIndication_signal,
+ &ett_h245_NewATMVCIndication_reverseParameters,
+ &ett_h245_NewATMVCIndication_aal_aal5,
+ &ett_h245_NewATMVCIndication_aal_aal1,
+ &ett_h245_NewATMVCIndication_aal,
+ &ett_h245_NewATMVCIndication,
+ &ett_h245_VendorIdentification,
+ &ett_h245_MCLocationIndication,
+ &ett_h245_H2250MaximumSkewIndication,
+ &ett_h245_H223SkewIndication,
+ &ett_h245_JitterIndication,
+ &ett_h245_MiscellaneousIndication_type_videoNotDecodedMBs,
+ &ett_h245_MiscellaneousIndication,
+ &ett_h245_VideoIndicateCompose,
+ &ett_h245_TerminalYouAreSeeingInSubPictureNumber,
+ &ett_h245_FunctionNotSupported,
+ &ett_h245_MobileMultilinkReconfigurationCommand,
+ &ett_h245_NewATMVCCommand_reverseParameters,
+ &ett_h245_NewATMVCCommand,
+ &ett_h245_NewATMVCCommand_aal_aal5,
+ &ett_h245_NewATMVCCommand_aal_aal1,
+ &ett_h245_EncryptionUpdateRequest,
+ &ett_h245_KeyProtectionMethod,
+ &ett_h245_MiscellaneousCommand_type_lostPartialPicture,
+ &ett_h245_MiscellaneousCommand_type_videoBadMBs,
+ &ett_h245_MiscellaneousCommand_type_progressiveRefinementStart,
+ &ett_h245_MiscellaneousCommand_type_videoFastUpdateMB,
+ &ett_h245_MiscellaneousCommand_type_videoFastUpdateGOB,
+ &ett_h245_MiscellaneousCommand,
+ &ett_h245_SubstituteConferenceIDCommand,
+ &ett_h245_FlowControlCommand,
+ &ett_h245_EncryptionCommand_encryptionAlgorithmID,
+ &ett_h245_SendTerminalCapabilitySet_specificRequest,
+ &ett_h245_LogicalChannelRateRelease,
+ &ett_h245_LogicalChannelRateReject,
+ &ett_h245_LogicalChannelRateAck,
+ &ett_h245_LogicalChannelRateRequest,
+ &ett_h245_ConnectionIdentifier,
+ &ett_h245_DialingInformationNumber,
+ &ett_h245_MultilinkIndication_excessiveError,
+ &ett_h245_MultilinkIndication_crcDesired,
+ &ett_h245_MultilinkResponse_maximumHeaderInterval,
+ &ett_h245_MultilinkResponse_removeConnection,
+ &ett_h245_MultilinkResponse_addConnection,
+ &ett_h245_MultilinkResponse_callInformation,
+ &ett_h245_MultilinkRequest_maximumHeaderInterval,
+ &ett_h245_MultilinkRequest_removeConnection,
+ &ett_h245_MultilinkRequest_addConnection,
+ &ett_h245_MultilinkRequest_callInformation,
+ &ett_h245_TerminalInformation,
+ &ett_h245_RequestAllTerminalIDsResponse,
+ &ett_h245_ConferenceResponse_terminalCertificateResponse,
+ &ett_h245_ConferenceResponse_chairTokenOwnerResponse,
+ &ett_h245_ConferenceResponse_extensionAddressResponse,
+ &ett_h245_ConferenceResponse_passwordResponse,
+ &ett_h245_ConferenceResponse_conferenceIDResponse,
+ &ett_h245_ConferenceResponse_terminalIDResponse,
+ &ett_h245_ConferenceResponse_mCterminalIDResponse,
+ &ett_h245_TerminalLabel,
+ &ett_h245_Criteria,
+ &ett_h245_ConferenceRequest_requestTerminalCertificate,
+ &ett_h245_CommunicationModeTableEntry,
+ &ett_h245_CommunicationModeRequest,
+ &ett_h245_CommunicationModeCommand,
+ &ett_h245_MaintenanceLoopOffCommand,
+ &ett_h245_MaintenanceLoopReject,
+ &ett_h245_MaintenanceLoopAck,
+ &ett_h245_MaintenanceLoopRequest,
+ &ett_h245_RoundTripDelayResponse,
+ &ett_h245_RoundTripDelayRequest,
+ &ett_h245_DataMode_application_t38fax,
+ &ett_h245_DataMode_application_nlpid,
+ &ett_h245_DataMode,
+ &ett_h245_VBDMode,
+ &ett_h245_G7231AnnexCMode_g723AnnexCAudioMode,
+ &ett_h245_G7231AnnexCMode,
+ &ett_h245_IS13818AudioMode,
+ &ett_h245_IS11172AudioMode,
+ &ett_h245_IS11172VideoMode,
+ &ett_h245_H263VideoMode,
+ &ett_h245_H262VideoMode,
+ &ett_h245_H261VideoMode,
+ &ett_h245_RedundancyEncodingMode,
+ &ett_h245_H2250ModeParameters,
+ &ett_h245_H223ModeParameters_adaptationLayerType_al3,
+ &ett_h245_H223ModeParameters,
+ &ett_h245_FECMode_rfc2733Mode_mode_separateStream_samePort,
+ &ett_h245_FECMode_rfc2733Mode_mode_separateStream_differentPort,
+ &ett_h245_FECMode_rfc2733Mode,
+ &ett_h245_MultiplePayloadStreamElementMode,
+ &ett_h245_MultiplePayloadStreamMode,
+ &ett_h245_RedundancyEncodingDTModeElement,
+ &ett_h245_RedundancyEncodingDTMode,
+ &ett_h245_MultiplexedStreamModeParameters,
+ &ett_h245_H235Mode,
+ &ett_h245_ModeElement,
+ &ett_h245_RequestModeRelease,
+ &ett_h245_RequestModeReject,
+ &ett_h245_RequestModeAck,
+ &ett_h245_RequestMode,
+ &ett_h245_RequestMultiplexEntryRelease,
+ &ett_h245_RequestMultiplexEntryRejectionDescriptions,
+ &ett_h245_RequestMultiplexEntryReject,
+ &ett_h245_RequestMultiplexEntryAck,
+ &ett_h245_RequestMultiplexEntry,
+ &ett_h245_MultiplexEntrySendRelease,
+ &ett_h245_MultiplexEntryRejectionDescriptions,
+ &ett_h245_MultiplexEntrySendReject,
+ &ett_h245_MultiplexEntrySendAck,
+ &ett_h245_MultiplexElement,
+ &ett_h245_MultiplexEntryDescriptor,
+ &ett_h245_MultiplexEntrySend,
+ &ett_h245_RequestChannelCloseRelease,
+ &ett_h245_RequestChannelCloseReject,
+ &ett_h245_RequestChannelCloseAck,
+ &ett_h245_RequestChannelClose,
+ &ett_h245_CloseLogicalChannelAck,
+ &ett_h245_CloseLogicalChannel,
+ &ett_h245_H2250LogicalChannelAckParameters,
+ &ett_h245_OpenLogicalChannelReject,
+ &ett_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters,
+ &ett_h245_OpenLogicalChannelAck,
+ &ett_h245_EscrowData,
+ &ett_h245_EncryptionSync,
+ &ett_h245_MulticastAddress_iP6Address,
+ &ett_h245_MulticastAddress_iPAddress,
+ &ett_h245_UnicastAddress_iPSourceRouteAddress,
+ &ett_h245_UnicastAddress_iP6Address,
+ &ett_h245_UnicastAddress_iPXAddress,
+ &ett_h245_UnicastAddress_iPAddress,
+ &ett_h245_FECData_rfc2733_mode_separateStream_samePort,
+ &ett_h245_FECData_rfc2733_mode_separateStream_differentPort,
+ &ett_h245_FECData_rfc2733,
+ &ett_h245_MultiplePayloadStreamElement,
+ &ett_h245_MultiplePayloadStream,
+ &ett_h245_RedundancyEncodingElement,
+ &ett_h245_RedundancyEncoding_rtpRedundancyEncoding,
+ &ett_h245_RedundancyEncoding,
+ &ett_h245_RTPPayloadType,
+ &ett_h245_H2250LogicalChannelParameters,
+ &ett_h245_V76HDLCParameters,
+ &ett_h245_V76LogicalChannelParameters_mode_eRM,
+ &ett_h245_V76LogicalChannelParameters,
+ &ett_h245_H223AnnexCArqParameters,
+ &ett_h245_H223AL3MParameters,
+ &ett_h245_H223AL2MParameters,
+ &ett_h245_H223AL1MParameters,
+ &ett_h245_H223LogicalChannelParameters_adaptionLayerType_al3,
+ &ett_h245_H223LogicalChannelParameters,
+ &ett_h245_H222LogicalChannelParameters,
+ &ett_h245_MultiplexedStreamParameter,
+ &ett_h245_H235Media,
+ &ett_h245_V75Parameters,
+ &ett_h245_Q2931Address,
+ &ett_h245_NetworkAccessParameters,
+ &ett_h245_reverseLogicalChannelParameters,
+ &ett_h245_forwardLogicalChannelParameters,
+ &ett_h245_OpenLogicalChannel,
+ &ett_h245_FECCapability_rfc2733_separateStream,
+ &ett_h245_FECCapability_rfc2733,
+ &ett_h245_MultiplePayloadStreamCapability,
+ &ett_h245_NoPTAudioToneCapability,
+ &ett_h245_NoPTAudioTelephonyEventCapability,
+ &ett_h245_AudioToneCapability,
+ &ett_h245_AudioTelephonyEventCapability,
+ &ett_h245_MultiplexedStreamCapability,
+ &ett_h245_GenericParameter,
+ &ett_h245_GenericCapability,
+ &ett_h245_ConferenceCapability,
+ &ett_h245_IntegrityCapability,
+ &ett_h245_AuthenticationCapability,
+ &ett_h245_EncryptionAuthenticationAndIntegrity,
+ &ett_h245_T38FaxTcpOptions,
+ &ett_h245_T38FaxUdpOptions,
+ &ett_h245_T38FaxProfile,
+ &ett_h245_T84Profile_t84Restricted,
+ &ett_h245_V42bis,
+ &ett_h245_DataApplicationCapability_application_t38fax,
+ &ett_h245_DataApplicationCapability_application_nlpid,
+ &ett_h245_DataApplicationCapability_application_t84,
+ &ett_h245_DataApplicationCapability,
+ &ett_h245_VBDCapability,
+ &ett_h245_GSMAudioCapability,
+ &ett_h245_IS13818AudioCapability,
+ &ett_h245_IS11172AudioCapability,
+ &ett_h245_G7231AnnexCCapability_g723AnnexCAudioMode,
+ &ett_h245_G7231AnnexCCapability,
+ &ett_h245_G729Extensions,
+ &ett_h245_AudioCapability_g7231,
+ &ett_h245_IS11172VideoCapability,
+ &ett_h245_H263Version3Options,
+ &ett_h245_H263ModeComboFlags,
+ &ett_h245_H263VideoModeCombos,
+ &ett_h245_CustomPictureFormat_pixelAspectInformation_extendedPAR,
+ &ett_h245_CustomPictureFormat_mPI_customPCF,
+ &ett_h245_CustomPictureFormat_mPI,
+ &ett_h245_CustomPictureFormat,
+ &ett_h245_CustomPictureClockFrequency,
+ &ett_h245_RefPictureSelection_enhancedReferencePicSelect_subPictureRemovalParameters,
+ &ett_h245_RefPictureSelection_enhancedReferencePicSelect,
+ &ett_h245_RefPictureSelection_additionalPictureMemory,
+ &ett_h245_RefPictureSelection,
+ &ett_h245_TransperencyParameters,
+ &ett_h245_H263Options,
+ &ett_h245_EnhancementOptions,
+ &ett_h245_BEnhancementParameters,
+ &ett_h245_EnhancementLayerInfo,
+ &ett_h245_H263VideoCapability,
+ &ett_h245_H262VideoCapability,
+ &ett_h245_H261VideoCapability,
+ &ett_h245_MediaDistributionCapability,
+ &ett_h245_MultipointCapability,
+ &ett_h245_RTPH263VideoRedundancyFrameMapping,
+ &ett_h245_RTPH263VideoRedundancyEncoding,
+ &ett_h245_RedundancyEncodingCapability,
+ &ett_h245_TransportCapability,
+ &ett_h245_MediaChannelCapability,
+ &ett_h245_MediaTransportType_AtmAAL5Compressed,
+ &ett_h245_QOSCapability,
+ &ett_h245_ATMParameters,
+ &ett_h245_RSVPParameters,
+ &ett_h245_MediaPacketizationCapability,
+ &ett_h245_H2250Capability_mcCapability,
+ &ett_h245_H2250Capability,
+ &ett_h245_V75Capability,
+ &ett_h245_V76Capability,
+ &ett_h245_H223AnnexCCapability,
+ &ett_h245_H223Capability_mobileMultilinkFrameCapability,
+ &ett_h245_H223Capability_mobileOperationTransmitCapability,
+ &ett_h245_H223Capability_h223MultiplexTableCapability_enhanced,
+ &ett_h245_H223Capability,
+ &ett_h245_VCCapability_aal1ViaGateway,
+ &ett_h245_VCCapability_availableBitRates_rangeOfBitRates,
+ &ett_h245_VCCapability_availableBitRates,
+ &ett_h245_VCCapability_aal5,
+ &ett_h245_VCCapability_aal1,
+ &ett_h245_VCCapability,
+ &ett_h245_H222Capability,
+ &ett_h245_H235SecurityCapability,
+ &ett_h245_Capability_h233EncryptionReceiveCapability,
+ &ett_h245_TerminalCapabilitySetRelease,
+ &ett_h245_TerminalCapabilitySetReject,
+ &ett_h245_TerminalCapabilitySetAck,
+ &ett_h245_CapabilityDescriptor,
+ &ett_h245_CapabilityTableEntry,
+ &ett_h245_TerminalCapabilitySet,
+ &ett_h245_MasterSlaveDeterminationRelease,
+ &ett_h245_MasterSlaveDeterminationReject,
+ &ett_h245_MasterSlaveDeterminationAck,
+ &ett_h245_MasterSlaveDetermination,
+ &ett_h245_h221NonStandard,
+ &ett_h245_NonStandardParameter,
+ &ett_h245_NonStandardMessage,
+ &ett_h245_FlowControlIndication_restriction,
+ &ett_h245_FlowControlIndication_scope,
+ &ett_h245_UserInputIndication_userInputSupportIndication,
+ &ett_h245_UserInputIndication,
+ &ett_h245_NewATMVCIndication_reverseParameters_multiplex,
+ &ett_h245_NewATMVCIndication_multiplex,
+ &ett_h245_NewATMVCIndication_aal_aal1_errorCorrection,
+ &ett_h245_NewATMVCIndication_aal_aal1_clockRecovery,
+ &ett_h245_JitterIndication_scope,
+ &ett_h245_MiscellaneousIndication_type,
+ &ett_h245_ConferenceIndication,
+ &ett_h245_FunctionNotSupported_cause,
+ &ett_h245_FunctionNotUnderstood,
+ &ett_h245_MobileMultilinkReconfigurationCommand_status,
+ &ett_h245_NewATMVCCommand_reverseParameters_multiplex,
+ &ett_h245_NewATMVCCommand_multiplex,
+ &ett_h245_NewATMVCCommand_aal_aal1_errorCorrection,
+ &ett_h245_NewATMVCCommand_aal_aal1_clockRecovery,
+ &ett_h245_NewATMVCCommand_aal,
+ &ett_h245_H223MultiplexReconfiguration_h223AnnexADoubleFlag,
+ &ett_h245_H223MultiplexReconfiguration_h223ModeChange,
+ &ett_h245_H223MultiplexReconfiguration,
+ &ett_h245_PictureReference,
+ &ett_h245_MiscellaneousCommand_type_progressiveRefinementStart_repeatCount,
+ &ett_h245_MiscellaneousCommand_type,
+ &ett_h245_ConferenceCommand,
+ &ett_h245_EndSessionCommand_gstnOptions,
+ &ett_h245_EndSessionCommand_isdnOptions,
+ &ett_h245_FlowControlCommand_restriction,
+ &ett_h245_FlowControlCommand_scope,
+ &ett_h245_EncryptionCommand,
+ &ett_h245_SendTerminalCapabilitySet,
+ &ett_h245_LogicalChannelRateRejectReason,
+ &ett_h245_DialingInformationNetworkType,
+ &ett_h245_DialingInformation,
+ &ett_h245_MultilinkIndication,
+ &ett_h245_MultilinkResponse_addConnection_responseCode_rejected,
+ &ett_h245_MultilinkResponse_addConnection_responseCode,
+ &ett_h245_MultilinkResponse,
+ &ett_h245_MultilinkRequest_maximumHeaderInterval_requestType,
+ &ett_h245_MultilinkRequest,
+ &ett_h245_RemoteMCResponse_reject,
+ &ett_h245_RemoteMCResponse,
+ &ett_h245_RemoteMCRequest,
+ &ett_h245_ConferenceResponse_sendThisSourceResponse,
+ &ett_h245_ConferenceResponse_makeTerminalBroadcasterResponse,
+ &ett_h245_ConferenceResponse_broadcastMyLogicalChannelResponse,
+ &ett_h245_ConferenceResponse_makeMeChairResponse,
+ &ett_h245_ConferenceResponse,
+ &ett_h245_ConferenceRequest,
+ &ett_h245_CommunicationModeTableEntry_dataType,
+ &ett_h245_CommunicationModeResponse,
+ &ett_h245_MaintenanceLoopReject_cause,
+ &ett_h245_MaintenanceLoopReject_type,
+ &ett_h245_MaintenanceLoopAck_type,
+ &ett_h245_MaintenanceLoopRequest_type,
+ &ett_h245_EncryptionMode,
+ &ett_h245_DataMode_application,
+ &ett_h245_IS13818AudioMode_multiChannelType,
+ &ett_h245_IS13818AudioMode_audioSampling,
+ &ett_h245_IS13818AudioMode_audioLayer,
+ &ett_h245_IS11172AudioMode_multichannelType,
+ &ett_h245_IS11172AudioMode_audioSampling,
+ &ett_h245_IS11172AudioMode_audioLayer,
+ &ett_h245_AudioMode_g7231,
+ &ett_h245_AudioMode,
+ &ett_h245_H263VideoMode_resolution,
+ &ett_h245_H262VideoMode_profileAndLevel,
+ &ett_h245_H261VideoMode_resolution,
+ &ett_h245_VideoMode,
+ &ett_h245_RedundancyEncodingMode_secondaryEncoding,
+ &ett_h245_V76ModeParameters,
+ &ett_h245_H223ModeParameters_adaptationLayerType,
+ &ett_h245_FECMode_rfc2733Mode_mode_separateStream,
+ &ett_h245_FECMode_rfc2733Mode_mode,
+ &ett_h245_FECMode,
+ &ett_h245_RedundancyEncodingDTModeElement_type,
+ &ett_h245_H235Mode_mediaMode,
+ &ett_h245_ModeElementType,
+ &ett_h245_RequestModeReject_cause,
+ &ett_h245_RequestMultiplexEntryRejectionDescriptions_cause,
+ &ett_h245_MultiplexEntryRejectionDescriptions_cause,
+ &ett_h245_MultiplexElement_repeatCount,
+ &ett_h245_MultiplexElement_type,
+ &ett_h245_RequestChannelCloseReject_cause,
+ &ett_h245_RequestChannelClose_reason,
+ &ett_h245_CloseLogicalChannel_reason,
+ &ett_h245_CloseLogicalChannel_source,
+ &ett_h245_OpenLogicalChannelReject_cause,
+ &ett_h245_forwardMultiplexAckParameters,
+ &ett_h245_OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters,
+ &ett_h245_MulticastAddress,
+ &ett_h245_UnicastAddress_iPSourceRouteAddress_routing,
+ &ett_h245_UnicastAddress,
+ &ett_h245_TransportAddress,
+ &ett_h245_FECData_rfc2733_mode_separateStream,
+ &ett_h245_FECData_rfc2733_mode,
+ &ett_h245_FECData,
+ &ett_h245_RTPPayloadType_payloadDescriptor,
+ &ett_h245_H2250LogicalChannelParameters_mediaPacketization,
+ &ett_h245_CRCLength,
+ &ett_h245_V76LogicalChannelParameters_mode_eRM_recovery,
+ &ett_h245_V76LogicalChannelParameters_mode,
+ &ett_h245_V76LogicalChannelParameters_suspendResume,
+ &ett_h245_H223AnnexCArqParameters_numberOfRetransmissions,
+ &ett_h245_H223AL3MParameters_arqType,
+ &ett_h245_H223AL3MParameters_crcLength,
+ &ett_h245_H223AL3MParameters_headerFormat,
+ &ett_h245_H223AL2MParameters_headerFEC,
+ &ett_h245_H223AL1MParameters_arqType,
+ &ett_h245_H223AL1MParameters_crcLength,
+ &ett_h245_H223AL1MParameters_headerFEC,
+ &ett_h245_H223AL1MParameters_transferMode,
+ &ett_h245_H223LogicalChannelParameters_adaptationLayerType,
+ &ett_h245_H235Media_mediaType,
+ &ett_h245_DataType,
+ &ett_h245_Q2931Address_address,
+ &ett_h245_NetworkAccessParameters_t120SetupProcedure,
+ &ett_h245_NetworkAccessParameters_networkAddress,
+ &ett_h245_NetworkAccessParameters_distribution,
+ &ett_h245_reverseLogicalChannelParameters_multiplexParameters,
+ &ett_h245_forwardLogicalChannelParameters_multiplexParameters,
+ &ett_h245_FECCapability,
+ &ett_h245_MultiplexFormat,
+ &ett_h245_ParameterValue,
+ &ett_h245_ParameterIdentifier,
+ &ett_h245_CapabilityIdentifier,
+ &ett_h245_UserInputCapability,
+ &ett_h245_MediaEncryptionAlgorithm,
+ &ett_h245_T38FaxUdpOptions_t38FaxUdpEC,
+ &ett_h245_T38FaxRateManagement,
+ &ett_h245_T84Profile,
+ &ett_h245_CompressionType,
+ &ett_h245_DataProtocolCapability_v76wCompression,
+ &ett_h245_DataProtocolCapability,
+ &ett_h245_DataApplicationCapability_application,
+ &ett_h245_AudioCapability,
+ &ett_h245_CustomPictureFormat_pixelAspectInformation,
+ &ett_h245_RefPictureSelection_videoBackChannelSend,
+ &ett_h245_VideoCapability,
+ &ett_h245_RTPH263VideoRedundancyEncoding_frameToThreadMapping,
+ &ett_h245_RedundancyEncodingMethod,
+ &ett_h245_MediaTransportType,
+ &ett_h245_QOSMode,
+ &ett_h245_H223Capability_h223MultiplexTableCapability,
+ &ett_h245_VCCapability_availableBitRates_type,
+ &ett_h245_MultiplexCapability,
+ &ett_h245_Capability,
+ &ett_h245_TerminalCapabilitySetReject_cause_tableEntryCapacityExceeded,
+ &ett_h245_TerminalCapabilitySetReject_cause,
+ &ett_h245_MasterSlaveDeterminationReject_cause,
+ &ett_h245_MasterSlaveDeterminationAck_decision,
+ &ett_h245_RequestModeAck_response_decision,
+ &ett_h245_NonStandardIdentifier,
+ &ett_h245_mediaDistributionCapability,
+ &ett_h245_AlternativeCapabilitySet,
+ &ett_h245_CapabilityTableEntryNumber_sequence_of,
+ &ett_h245_frameToThreadMapping_custom,
+ &ett_h245_RedundancyEncodingCapability_sequence_of,
+ &ett_h245_frameSequence,
+ &ett_h245_EncryptionCapability,
+ &ett_h245_escrowentry,
+ &ett_h245_elementList,
+ &ett_h245_requestedModes,
+ &ett_h245_CertSelectionCriteria,
+ &ett_h245_capabilityTable,
+ &ett_h245_capabilityDescriptors,
+ &ett_h245_simultaneousCapabilities,
+ &ett_h245_gatewayAddress,
+ &ett_h245_snrEnhancement,
+ &ett_h245_spatialEnhancement,
+ &ett_h245_bPictureEnhancement,
+ &ett_h245_customPictureClockFrequency,
+ &ett_h245_customPictureFormat,
+ &ett_h245_modeCombos,
+ &ett_h245_customPCF,
+ &ett_h245_pixelAspectCode,
+ &ett_h245_extendedPAR,
+ &ett_h245_h263VideoCoupledModes,
+ &ett_h245_capabilityOnMuxStream,
+ &ett_h245_capabilities,
+ &ett_h245_multiplexEntryDescriptors,
+ &ett_h245_multiplexTableEntryNumber_set_of,
+ &ett_h245_VCCapability_set_of,
+ &ett_h245_rejectionDescriptions,
+ &ett_h245_entryNumbers,
+ &ett_h245_ModeDescription,
+ &ett_h245_communicationModeTable,
+ &ett_h245_terminalListResponse,
+ &ett_h245_differential,
+ &ett_h245_networkType,
+ &ett_h245_capabilityTableEntryNumbers,
+ &ett_h245_capabilityDescriptorNumbers,
+ &ett_h245_qOSCapabilities,
+ &ett_h245_subElementList,
+ &ett_h245_containedThreads,
+ &ett_h245_mediaChannelCapabilities,
+ &ett_h245_rtpPayloadType_sequence_of,
+ &ett_h245_centralizedData,
+ &ett_h245_distributedData,
+ &ett_h245_nonStandardData,
+ &ett_h245_collapsing,
+ &ett_h245_nonCollapsing,
+ &ett_h245_supersedes,
+ &ett_h245_genericParameter,
+ &ett_h245_secondary_REE,
+ &ett_h245_elements_MPSE,
+ &ett_h245_secondary_REDTME,
+ &ett_h245_elements_MPSEM,
+ &ett_h245_TerminalInformationSO,
+ &ett_h245_lostPicture,
+ &ett_h245_recoveryReferencePicture,
+ &ett_h245_iPSourceRouteAddress_route,
+ };
+ module_t *h245_module;
+
+ proto_h245 = proto_register_protocol("H245", "H245", "h245");
+ proto_register_field_array(proto_h245, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ h245_module = prefs_register_protocol(proto_h245, NULL);
+ prefs_register_bool_preference(h245_module, "reassembly",
+ "Reassemble H.245 over TCP",
+ "Whether the dissector should reassemble H.245 PDUs spanning multiple TCP segments",
+ &h245_reassembly);
+ prefs_register_bool_preference(h245_module, "shorttypes",
+ "Show short message types",
+ "Whether the dissector should show short names or the long names from the standard",
+ &h245_shorttypes);
+ register_dissector("h245dg", dissect_h245_MultimediaSystemControlMessage, proto_h245);
+ register_dissector("h245", dissect_h245, proto_h245);
+
+ nsp_object_dissector_table = register_dissector_table("h245.nsp.object", "H.245 NonStandardParameter (object)", FT_STRING, BASE_NONE);
+ nsp_h221_dissector_table = register_dissector_table("h245.nsp.h221", "H.245 NonStandardParameter (h221)", FT_UINT32, BASE_HEX);
+}
+
+void
+proto_reg_handoff_h245(void)
+{
+ rtp_handle = find_dissector("rtp");
+ rtcp_handle = find_dissector("rtcp");
+
+ h245_handle=create_dissector_handle(dissect_h245, proto_h245);
+ dissector_add_handle("tcp.port", h245_handle);
+ MultimediaSystemControlMessage_handle=create_dissector_handle(dissect_h245_MultimediaSystemControlMessage, proto_h245);
+ dissector_add_handle("udp.port", MultimediaSystemControlMessage_handle);
+}
diff --git a/epan/dissectors/packet-h245.h b/epan/dissectors/packet-h245.h
new file mode 100644
index 0000000000..288e9925f1
--- /dev/null
+++ b/epan/dissectors/packet-h245.h
@@ -0,0 +1,36 @@
+/* packet-h245.h
+ * Routines for H.245 packet dissection
+ * 2003 Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+extern void dissect_h245_MultimediaSystemControlMessage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+extern int dissect_h245_OpenLogicalChannel(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+extern int dissect_h245_h221NonStandard(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+extern int dissect_h245_NonStandardParameter(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+extern int dissect_h245_T38FaxProfile(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+extern int dissect_h245_DataProtocolCapability(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
diff --git a/epan/dissectors/packet-h261.c b/epan/dissectors/packet-h261.c
new file mode 100644
index 0000000000..8b291d2e9b
--- /dev/null
+++ b/epan/dissectors/packet-h261.c
@@ -0,0 +1,263 @@
+/* packet-h261.c
+ *
+ * Routines for ITU-T Recommendation H.261 dissection
+ *
+ * $Id$
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Andreas Sikkema <h323@ramdyne.nl>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect the H.261 protocol according to Annex C
+ * of ITU-T Recommendation H.225.0 (02/98)
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "rtp_pt.h"
+
+/* H.261 header fields */
+static int proto_h261 = -1;
+static int hf_h261_sbit = -1;
+static int hf_h261_ebit = -1;
+static int hf_h261_ibit = -1;
+static int hf_h261_vbit = -1;
+static int hf_h261_gobn = -1;
+static int hf_h261_mbap = -1;
+static int hf_h261_quant = -1;
+static int hf_h261_hmvd = -1; /* Mislabeled in a figure in section C.3.1 as HMDV */
+static int hf_h261_vmvd = -1;
+static int hf_h261_data = -1;
+
+/* H.261 fields defining a sub tree */
+static gint ett_h261 = -1;
+
+static void
+dissect_h261( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *h261_tree = NULL;
+ unsigned int offset = 0;
+
+ if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) {
+ col_set_str( pinfo->cinfo, COL_PROTOCOL, "H.261" );
+ }
+
+ if ( check_col( pinfo->cinfo, COL_INFO) ) {
+ col_set_str( pinfo->cinfo, COL_INFO, "H.261 message");
+ }
+
+ if ( tree ) {
+ ti = proto_tree_add_item( tree, proto_h261, tvb, offset, -1, FALSE );
+ h261_tree = proto_item_add_subtree( ti, ett_h261 );
+ /* SBIT 1st octet, 3 bits */
+ proto_tree_add_uint( h261_tree, hf_h261_sbit, tvb, offset, 1, tvb_get_guint8( tvb, offset ) >> 5 );
+ /* EBIT 1st octet, 3 bits */
+ proto_tree_add_uint( h261_tree, hf_h261_ebit, tvb, offset, 1, ( tvb_get_guint8( tvb, offset ) << 3 ) >> 5 );
+ /* I flag, 1 bit */
+ proto_tree_add_boolean( h261_tree, hf_h261_ibit, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 2 );
+ /* V flag, 1 bit */
+ proto_tree_add_boolean( h261_tree, hf_h261_vbit, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 1 );
+ offset++;
+
+ /* GOBN 2nd octet, 4 bits */
+ proto_tree_add_uint( h261_tree, hf_h261_gobn, tvb, offset, 1, tvb_get_guint8( tvb, offset ) >> 4 );
+ /* MBAP 2nd octet, 4 bits, 3rd octet 1 bit */
+ proto_tree_add_uint( h261_tree, hf_h261_mbap, tvb, offset, 1,
+ ( tvb_get_guint8( tvb, offset ) & 15 )
+ + ( tvb_get_guint8( tvb, offset + 1 ) >> 7 ) );
+ offset++;
+
+ /* QUANT 3rd octet, 5 bits (starting at bit 2!) */
+ proto_tree_add_uint( h261_tree, hf_h261_quant, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 124 );
+
+ /* HMVD 3rd octet 2 bits, 4th octet 3 bits */
+ proto_tree_add_uint( h261_tree, hf_h261_hmvd, tvb, offset, 2,
+ ( ( tvb_get_guint8( tvb, offset ) & 0x03 ) << 3 )
+ + ( tvb_get_guint8( tvb, offset+1 ) >> 5 ) );
+ offset++;
+
+ /* VMVD 4th octet, last 5 bits */
+ proto_tree_add_uint( h261_tree, hf_h261_vmvd, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 31 );
+ offset++;
+
+ /* The rest of the packet is the H.261 stream */
+ proto_tree_add_item( h261_tree, hf_h261_data, tvb, offset, -1, FALSE );
+ }
+}
+
+void
+proto_register_h261(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_h261_sbit,
+ {
+ "Start bit position",
+ "h261.sbit",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_h261_ebit,
+ {
+ "End bit position",
+ "h261.ebit",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_h261_ibit,
+ {
+ "Intra frame encoded data flag",
+ "h261.i",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_h261_vbit,
+ {
+ "Motion vector flag",
+ "h261.v",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_h261_gobn,
+ {
+ "GOB Number",
+ "h261.gobn",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_h261_mbap,
+ {
+ "Macroblock address predictor",
+ "h261.mbap",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_h261_quant,
+ {
+ "Quantizer",
+ "h261.quant",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_h261_hmvd,
+ {
+ "Horizontal motion vector data",
+ "h261.hmvd",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_h261_vmvd,
+ {
+ "Vertical motion vector data",
+ "h261.vmvd",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_h261_data,
+ {
+ "H.261 stream",
+ "h261.stream",
+ FT_BYTES,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+};
+
+ static gint *ett[] =
+ {
+ &ett_h261,
+ };
+
+
+ proto_h261 = proto_register_protocol("ITU-T Recommendation H.261",
+ "H.261", "h261");
+ proto_register_field_array(proto_h261, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_h261(void)
+{
+ dissector_handle_t h261_handle;
+
+ h261_handle = create_dissector_handle(dissect_h261, proto_h261);
+ dissector_add("rtp.pt", PT_H261, h261_handle);
+}
diff --git a/epan/dissectors/packet-h263.c b/epan/dissectors/packet-h263.c
new file mode 100644
index 0000000000..e0feaf106a
--- /dev/null
+++ b/epan/dissectors/packet-h263.c
@@ -0,0 +1,541 @@
+/* packet-h263.c
+ *
+ * Routines for ITU-T Recommendation H.263 dissection
+ *
+ * Copyright 2003 Niklas Ögren <niklas.ogren@7l.se>
+ * Seven Levels Consultants AB
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied structure from packet-h261.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect the H.263 protocol according to
+ * ITU-T Recommendations and RFC 2190
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "rtp_pt.h"
+#include "iax2_codec_type.h"
+
+/* H.263 header fields */
+static int proto_h263 = -1;
+
+/* Mode A header */
+static int hf_h263_ftype = -1;
+static int hf_h263_pbframes = -1;
+static int hf_h263_sbit = -1;
+static int hf_h263_ebit = -1;
+static int hf_h263_srcformat = -1;
+static int hf_h263_picture_coding_type = -1;
+static int hf_h263_unrestricted_motion_vector = -1;
+static int hf_h263_syntax_based_arithmetic = -1;
+static int hf_h263_advanced_prediction = -1;
+static int hf_h263_r = -1;
+static int hf_h263_rr = -1;
+static int hf_h263_dbq = -1;
+static int hf_h263_trb = -1;
+static int hf_h263_tr = -1;
+/* Additional fields for Mode B or C header */
+static int hf_h263_quant = -1;
+static int hf_h263_gobn = -1;
+static int hf_h263_mba = -1;
+static int hf_h263_hmv1 = -1;
+static int hf_h263_vmv1 = -1;
+static int hf_h263_hmv2 = -1;
+static int hf_h263_vmv2 = -1;
+
+static int hf_h263_data = -1;
+
+/* Source format types */
+#define SRCFORMAT_FORB 0 /* forbidden */
+#define SRCFORMAT_SQCIF 1
+#define SRCFORMAT_QCIF 2
+#define SRCFORMAT_CIF 3
+#define SRCFORMAT_4CIF 4
+#define SRCFORMAT_16CIF 5
+
+static const value_string srcformat_vals[] =
+{
+ { SRCFORMAT_FORB, "forbidden" },
+ { SRCFORMAT_SQCIF, "sub-QCIF 128x96" },
+ { SRCFORMAT_QCIF, "QCIF 176x144" },
+ { SRCFORMAT_CIF, "CIF 352x288" },
+ { SRCFORMAT_4CIF, "4CIF 704x576" },
+ { SRCFORMAT_16CIF, "16CIF 1408x1152" },
+ { 0, NULL },
+};
+
+/* H.263 fields defining a sub tree */
+static gint ett_h263 = -1;
+
+static void
+dissect_h263( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *h263_tree = NULL;
+ unsigned int offset = 0;
+ unsigned int h263_version = 0;
+
+ h263_version = (tvb_get_guint8( tvb, offset ) & 0xc0 ) >> 6;
+
+ if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) {
+ col_set_str( pinfo->cinfo, COL_PROTOCOL, "H.263" );
+ }
+
+ if( h263_version == 0x00) {
+ if ( check_col( pinfo->cinfo, COL_INFO) ) {
+ col_append_str( pinfo->cinfo, COL_INFO, " MODE A");
+ }
+ }
+ else if( h263_version == 0x02) {
+ if ( check_col( pinfo->cinfo, COL_INFO) ) {
+ col_append_str( pinfo->cinfo, COL_INFO, " MODE B");
+ }
+ }
+ else if( h263_version == 0x03) {
+ if ( check_col( pinfo->cinfo, COL_INFO) ) {
+ col_append_str( pinfo->cinfo, COL_INFO, " MODE C");
+ }
+ }
+
+ if ( tree ) {
+ ti = proto_tree_add_item( tree, proto_h263, tvb, offset, -1, FALSE );
+ h263_tree = proto_item_add_subtree( ti, ett_h263 );
+
+ /* FBIT 1st octet, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_ftype, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x80 );
+ /* PBIT 1st octet, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_pbframes, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x40 );
+ /* SBIT 1st octet, 3 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_sbit, tvb, offset, 1, ( tvb_get_guint8( tvb, offset ) & 0x38 ) >> 3 );
+ /* EBIT 1st octet, 3 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_ebit, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x7 );
+
+ offset++;
+
+ /* SRC 2nd octet, 3 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_srcformat, tvb, offset, 1, tvb_get_guint8( tvb, offset ) >> 5 );
+
+ if(h263_version == 0x00) { /* MODE A */
+ /* I flag, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_picture_coding_type, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x10 );
+ /* U flag, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_unrestricted_motion_vector, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x08 );
+ /* S flag, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_syntax_based_arithmetic, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x04 );
+ /* A flag, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_advanced_prediction, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x02 );
+
+ /* Reserved 2nd octect, 1 bit + 3rd octect 3 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_r, tvb, offset, 2, ( ( tvb_get_guint8( tvb, offset ) & 0x1 ) << 3 ) + ( ( tvb_get_guint8( tvb, offset + 1 ) & 0xe0 ) >> 5 ) );
+
+ offset++;
+
+ /* DBQ 3 octect, 2 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_dbq, tvb, offset, 1, ( tvb_get_guint8( tvb, offset ) & 0x18 ) >> 3 );
+ /* TRB 3 octect, 3 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_trb, tvb, offset, 1, ( tvb_get_guint8( tvb, offset ) & 0x07 ) );
+
+ offset++;
+
+ /* TR 4 octect, 8 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_tr, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
+
+ offset++;
+
+ } else { /* MODE B or MODE C */
+
+ /* QUANT 2 octect, 5 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_quant, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x1f );
+
+ offset++;
+
+ /* GOBN 3 octect, 5 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_gobn, tvb, offset, 1, ( tvb_get_guint8( tvb, offset ) & 0xf8 ) >> 3);
+ /* MBA 3 octect, 3 bits + 4 octect 6 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_mba, tvb, offset, 2, ( ( tvb_get_guint8( tvb, offset ) & 0x7 ) << 6 ) + ( ( tvb_get_guint8( tvb, offset + 1 ) & 0xfc ) >> 2 ) );
+
+ offset++;
+
+ /* Reserved 4th octect, 2 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_r, tvb, offset, 1, ( tvb_get_guint8( tvb, offset ) & 0x3 ) );
+
+ offset++;
+
+ /* I flag, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_picture_coding_type, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x80 );
+ /* U flag, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_unrestricted_motion_vector, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x40 );
+ /* S flag, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_syntax_based_arithmetic, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x20 );
+ /* A flag, 1 bit */
+ proto_tree_add_boolean( h263_tree, hf_h263_advanced_prediction, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x10 );
+
+ /* HMV1 5th octect, 4 bits + 6th octect 3 bits*/
+ proto_tree_add_uint( h263_tree, hf_h263_hmv1, tvb, offset, 2,( ( tvb_get_guint8( tvb, offset ) & 0xf ) << 3 ) + ( ( tvb_get_guint8( tvb, offset+1 ) & 0xe0 ) >> 5) );
+
+ offset++;
+
+ /* VMV1 6th octect, 5 bits + 7th octect 2 bits*/
+ proto_tree_add_uint( h263_tree, hf_h263_vmv1, tvb, offset, 2,( ( tvb_get_guint8( tvb, offset ) & 0x1f ) << 2 ) + ( ( tvb_get_guint8( tvb, offset+1 ) & 0xc0 ) >> 6) );
+
+ offset++;
+
+ /* HMV2 7th octect, 6 bits + 8th octect 1 bit*/
+ proto_tree_add_uint( h263_tree, hf_h263_hmv2, tvb, offset, 2,( ( tvb_get_guint8( tvb, offset ) & 0x3f ) << 1 ) + ( ( tvb_get_guint8( tvb, offset+1 ) & 0xf0 ) >> 7) );
+
+ offset++;
+
+ /* VMV2 8th octect, 7 bits*/
+ proto_tree_add_uint( h263_tree, hf_h263_vmv2, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x7f );
+
+ offset++;
+
+ if(h263_version == 0x03) { /* MODE C */
+ /* Reserved 9th to 11th octect, 8 + 8 + 3 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_rr, tvb, offset, 3, ( tvb_get_guint8( tvb, offset ) << 11 ) + ( tvb_get_guint8( tvb, offset + 1 ) << 3 ) + ( ( tvb_get_guint8( tvb, offset + 2 ) & 0xe0 ) >> 5 ) );
+
+ offset+=2;
+
+ /* DBQ 11th octect, 2 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_dbq, tvb, offset, 1, ( tvb_get_guint8( tvb, offset ) & 0x18 ) >>3 );
+ /* TRB 11th octect, 3 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_trb, tvb, offset, 1, tvb_get_guint8( tvb, offset ) & 0x07 );
+
+ offset++;
+
+ /* TR 12th octect, 8 bits */
+ proto_tree_add_uint( h263_tree, hf_h263_tr, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
+
+ offset++;
+ } /* end mode c */
+ } /* end not mode a */
+
+ /* The rest of the packet is the H.263 stream */
+ proto_tree_add_item( h263_tree, hf_h263_data, tvb, offset, -1, FALSE );
+ }
+}
+
+void
+proto_register_h263(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_h263_ftype,
+ {
+ "F",
+ "h263.sbit",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Indicates the mode of the payload header (MODE A or B/C)", HFILL
+ }
+ },
+ {
+ &hf_h263_pbframes,
+ {
+ "p/b frame",
+ "h263.pbframes",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Optional PB-frames mode as defined by H.263 (MODE C)", HFILL
+ }
+ },
+ {
+ &hf_h263_sbit,
+ {
+ "Start bit position",
+ "h263.sbit",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Start bit position specifies number of most significant bits that shall be ignored in the first data byte.", HFILL
+ }
+ },
+ {
+ &hf_h263_ebit,
+ {
+ "End bit position",
+ "h263.ebit",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "End bit position specifies number of least significant bits that shall be ignored in the last data byte.", HFILL
+ }
+ },
+ {
+ &hf_h263_srcformat,
+ {
+ "SRC format",
+ "h263.srcformat",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(srcformat_vals),
+ 0x0,
+ "Source format specifies the resolution of the current picture.", HFILL
+ }
+ },
+ {
+ &hf_h263_picture_coding_type,
+ {
+ "Inter-coded frame",
+ "h263.picture_coding_type",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Picture coding type, intra-coded (false) or inter-coded (true)", HFILL
+ }
+ },
+ {
+ &hf_h263_unrestricted_motion_vector,
+ {
+ "Motion vector",
+ "h263.unrestricted_motion_vector",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Unrestricted Motion Vector option for current picture", HFILL
+ }
+ },
+ {
+ &hf_h263_syntax_based_arithmetic,
+ {
+ "Syntax-based arithmetic coding",
+ "h263.syntax_based_arithmetic",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Syntax-based Arithmetic Coding option for current picture", HFILL
+ }
+ },
+ {
+ &hf_h263_advanced_prediction,
+ {
+ "Advanced prediction option",
+ "h263.advanced_prediction",
+ FT_BOOLEAN,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Advanced Prediction option for current picture", HFILL
+ }
+ },
+ {
+ &hf_h263_dbq,
+ {
+ "Differential quantization parameter",
+ "h263.dbq",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Differential quantization parameter used to calculate quantizer for the B frame based on quantizer for the P frame, when PB-frames option is used.", HFILL
+ }
+ },
+ {
+ &hf_h263_trb,
+ {
+ "Temporal Reference for B frames",
+ "h263.trb",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Temporal Reference for the B frame as defined by H.263", HFILL
+ }
+ },
+ {
+ &hf_h263_tr,
+ {
+ "Temporal Reference for P frames",
+ "h263.tr",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Temporal Reference for the P frame as defined by H.263", HFILL
+ }
+ },
+ {
+ &hf_h263_quant,
+ {
+ "Quantizer",
+ "h263.quant",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Quantization value for the first MB coded at the starting of the packet.", HFILL
+ }
+ },
+ {
+ &hf_h263_gobn,
+ {
+ "GOB Number",
+ "h263.gobn",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "GOB number in effect at the start of the packet.", HFILL
+ }
+ },
+ {
+ &hf_h263_mba,
+ {
+ "Macroblock address",
+ "h263.mba",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "The address within the GOB of the first MB in the packet, counting from zero in scan order.", HFILL
+ }
+ },
+ {
+ &hf_h263_hmv1,
+ {
+ "Horizontal motion vector 1",
+ "h263.hmv1",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Horizontal motion vector predictor for the first MB in this packet ", HFILL
+ }
+ },
+ {
+ &hf_h263_vmv1,
+ {
+ "Vertical motion vector 1",
+ "h263.vmv1",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Vertical motion vector predictor for the first MB in this packet ", HFILL
+ }
+ },
+ {
+ &hf_h263_hmv2,
+ {
+ "Horizontal motion vector 2",
+ "h263.hmv2",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Horizontal motion vector predictor for block number 3 in the first MB in this packet when four motion vectors are used with the advanced prediction option.", HFILL
+ }
+ },
+ {
+ &hf_h263_vmv2,
+ {
+ "Vertical motion vector 2",
+ "h263.vmv2",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Vertical motion vector predictor for block number 3 in the first MB in this packet when four motion vectors are used with the advanced prediction option.", HFILL
+ }
+ },
+ {
+ &hf_h263_r,
+ {
+ "Reserved field",
+ "h263.r",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Reserved field that houls contain zeroes", HFILL
+ }
+ },
+ {
+ &hf_h263_rr,
+ {
+ "Reserved field 2",
+ "h263.rr",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Reserved field that should contain zeroes", HFILL
+ }
+ },
+ {
+ &hf_h263_data,
+ {
+ "H.263 stream",
+ "h263.stream",
+ FT_BYTES,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "The H.263 stream including its Picture, GOB or Macro block start code.", HFILL
+ }
+ },
+};
+
+ static gint *ett[] =
+ {
+ &ett_h263,
+ };
+
+
+ proto_h263 = proto_register_protocol("ITU-T Recommendation H.263 RTP Payload header (RFC2190)",
+ "H.263", "h263");
+ proto_register_field_array(proto_h263, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("h263", dissect_h263, proto_h263);
+}
+
+void
+proto_reg_handoff_h263(void)
+{
+ dissector_handle_t h263_handle;
+
+ h263_handle = find_dissector("h263");
+ dissector_add("rtp.pt", PT_H263, h263_handle);
+ dissector_add("iax2.codec", AST_FORMAT_H263, h263_handle);
+}
diff --git a/epan/dissectors/packet-h450.c b/epan/dissectors/packet-h450.c
new file mode 100644
index 0000000000..fffbd98cda
--- /dev/null
+++ b/epan/dissectors/packet-h450.c
@@ -0,0 +1,1369 @@
+/* packet-h450.c
+ * Routines for H.450 packet dissection
+ * 2003 Graeme Reid (graeme.reid@norwoodsystems.com)
+ *
+ * Copied from packet-h225.c and packet-h245.c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "prefs.h"
+#include "packet-per.h"
+#include "packet-h225.h"
+#include "packet-h245.h"
+
+/* H.450.2 Call Transfer constants */
+#define CallTransferIdentify 7
+#define CallTransferAbandon 8
+#define CallTransferInitiate 9
+#define CallTransferSetup 10
+#define CallTransferUpdate 13
+#define SubaddressTransfer 14
+#define CallTransferComplete 12
+#define CallTransferActive 11
+
+/* H.450.3 Call Diversion constants */
+#define ActivateDiversionQ 15
+#define DeactivateDiversionQ 16
+#define InterrogateDiversionQ 17
+#define CheckRestriction 18
+#define CallRerouting 19
+#define DivertingLegInformation1 20
+#define DivertingLegInformation2 21
+#define DivertingLegInformation3 22
+#define DivertingLegInformation4 100
+#define CfnrDivertedLegFailed 23
+
+/* H.450.4 Call Hold constants */
+#define HoldNotific 101
+#define RetrieveNotific 102
+#define RemoteHold 103
+#define RemoteRetrieve 104
+
+/* H.450.5 Call Park and Pickup constants */
+#define CpRequest 106
+#define CpSetup 107
+#define GroupIndicationOn 108
+#define GroupIndicationOff 109
+#define Pickrequ 110
+#define Pickup 111
+#define PickExe 112
+#define CpNotify 113
+#define CpickupNotify 114
+
+/* H.450.6 Call Waiting constants */
+#define CallWaiting 105
+
+/* H.450.7 Message Waiting Indication constants */
+#define MWIActivate 80
+#define MWIDeactivate 81
+#define MWIInterrogate 82
+
+/* H.450.8 Name Identification constants */
+#define NIcallingName 0
+#define NIalertingName 1
+#define NIconnectedName 2
+#define NIbusyName 3
+
+/* H.450.9 Call Completion constants */
+#define CCBSRequest 40
+#define CCNRRequest 27
+#define CCCancel 28
+#define CCExecPossible 29
+#define CCRingout 31
+#define CCSuspend 32
+#define CCResume 33
+
+/* H.450.10 Call Offer constants */
+#define CallOfferRequest 34
+#define RemoteUserAlerting 115
+#define CFBOverride 49
+
+/* H.450.11 Call Intrusion constants */
+#define CallIntrusionRequest 43
+#define CallIntrusionGetCIPL 44
+#define CallIntrusionIsolate 45
+#define CallIntrusionForcedRelease 46
+#define CallIntrusionWOBRequest 47
+#define CallIntrusionSilentMonitor 116
+#define CallIntrusionNotification 117
+
+/* TODO - define other H.450.x constants here */
+
+static dissector_handle_t h4501_handle;
+
+static int proto_h4501 = -1;
+
+static int hf_h4501 = -1;
+static int hf_h4501_EntityType = -1;
+static int hf_h4501_NetworkFacilityExtension = -1;
+static int hf_h4501_InterpretationApdu = -1;
+static int hf_h4501_constrained_invokeId = -1;
+static int hf_h4501_invokeId = -1;
+static int hf_h4501_localOpcode = -1;
+static int hf_h4501_globalCode = -1;
+static int hf_h4501_opcode = -1;
+static int hf_h4501_destinationAddress = -1;
+static int hf_h4501_EndpointAddress = -1;
+static int hf_h4501_H225InformationElement = -1;
+static int hf_h4501_SubaddressInformation = -1;
+static int hf_h4501_oddCountIndicator = -1;
+static int hf_h4501_UserSpecifiedSubaddress = -1;
+static int hf_h4501_NSAPAddress = -1;
+static int hf_h4501_PartySubaddress = -1;
+static int hf_h4501_argumentExtension = -1;
+static int hf_h4501_argument = -1;
+static int hf_h4501_Invoke = -1;
+static int hf_h4501_resultExtension = -1;
+static int hf_h4501_ReturnResult_result = -1;
+static int hf_h4501_result = -1;
+static int hf_h4501_ReturnResult = -1;
+static int hf_h4501_localErrorCode = -1;
+static int hf_h4501_errorCode = -1;
+static int hf_h4501_parameter = -1;
+static int hf_h4501_ReturnError = -1;
+static int hf_h4501_GeneralProblem = -1;
+static int hf_h4501_InvokeProblem = -1;
+static int hf_h4501_ReturnResultProblem = -1;
+static int hf_h4501_ReturnErrorProblem = -1;
+static int hf_h4501_problem = -1;
+static int hf_h4501_Reject = -1;
+static int hf_h4501_ROS = -1;
+static int hf_h4501_rosApdus = -1;
+static int hf_h4501_ServiceApdus = -1;
+
+static int hf_h4502_nonStandardData = -1;
+static int hf_h4502_DummyArg = -1;
+static int hf_h4502_CallIdentity = -1;
+static int hf_h4502_CTInitiateArg = -1;
+static int hf_h4502_CTSetupArg = -1;
+static int hf_h4502_redirectionInfo = -1;
+static int hf_h4502_CTUpdateArg = -1;
+static int hf_h4502_SubaddressTransferArg = -1;
+static int hf_h4502_EndDesignation = -1;
+static int hf_h4502_CallStatus = -1;
+static int hf_h4502_CTCompleteArg = -1;
+static int hf_h4502_connectedInfo = -1;
+static int hf_h4502_CTActiveArg = -1;
+static int hf_h4502_CTIdentifyRes = -1;
+static int hf_h4502_DummyRes = -1;
+
+static gint ett_h4501 = -1;
+static gint ett_h4501_EntityType = -1;
+static gint ett_h4501_NetworkFacilityExtension = -1;
+static gint ett_h4501_InterpretationApdu = -1;
+static gint ett_h4501_opcode = -1;
+static gint ett_h4501_destinationAddress = -1;
+static gint ett_h4501_EndpointAddress = -1;
+static gint ett_h4501_UserSpecifiedSubaddress = -1;
+static gint ett_h4501_PartySubaddress = -1;
+static gint ett_h4501_argumentExtension = -1;
+static gint ett_h4501_Invoke = -1;
+static gint ett_h4501_resultExtension = -1;
+static gint ett_h4501_result = -1;
+static gint ett_h4501_ReturnResult = -1;
+static gint ett_h4501_errorCode = -1;
+static gint ett_h4501_ReturnError = -1;
+static gint ett_h4501_problem = -1;
+static gint ett_h4501_Reject = -1;
+static gint ett_h4501_ROS = -1;
+static gint ett_h4501_rosApdus = -1;
+static gint ett_h4501_ServiceApdus = -1;
+
+static gint ett_h4502_DummyArg = -1;
+static gint ett_h4502_CTInitiateArg = -1;
+static gint ett_h4502_CTSetupArg = -1;
+static gint ett_h4502_CTUpdateArg = -1;
+static gint ett_h4502_SubaddressTransferArg = -1;
+static gint ett_h4502_CTCompleteArg = -1;
+static gint ett_h4502_CTActiveArg = -1;
+static gint ett_h4502_CTIdentifyRes = -1;
+static gint ett_h4502_DummyRes = -1;
+
+static guint32 localOpcode;
+static guint32 localErrorCode;
+
+static int
+dissect_h4501_NULL(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_, proto_tree *tree _U_)
+{
+ return offset;
+}
+
+
+static const value_string EntityType_vals[] = {
+ { 0, "endpoint" },
+ { 1, "anyEntity" },
+ { 0, NULL}
+};
+static per_choice_t EntityType_choice[] = {
+ { 0, "endpoint", ASN1_EXTENSION_ROOT,
+ dissect_h4501_NULL },
+ { 1, "anyEntity", ASN1_EXTENSION_ROOT,
+ dissect_h4501_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h4501_EntityType(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_EntityType, ett_h4501_EntityType, EntityType_choice, "EntityType", NULL);
+ return offset;
+}
+
+
+static per_sequence_t NetworkFacilityExtension_sequence[] = {
+ { "sourceEntity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_EntityType },
+ { "sourceEntityAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AliasAddress },
+ { "destinationEntity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_EntityType },
+ { "destinationEntityAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AliasAddress },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4501_NetworkFacilityExtension(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4501_NetworkFacilityExtension, ett_h4501_NetworkFacilityExtension, NetworkFacilityExtension_sequence);
+ return offset;
+}
+
+
+static const value_string InterpretationApdu_vals[] = {
+ { 0, "discardAnyUnrecognizedInvokePdu" },
+ { 1, "clearCallIfAnyInvokePduNotRecognized" },
+ { 2, "rejectAnyUnrecognizedInvokePdu" },
+ { 0, NULL}
+};
+static per_choice_t InterpretationApdu_choice[] = {
+ { 0, "discardAnyUnrecognizedInvokePdu", ASN1_EXTENSION_ROOT,
+ dissect_h4501_NULL },
+ { 1, "clearCallIfAnyInvokePduNotRecognized", ASN1_EXTENSION_ROOT,
+ dissect_h4501_NULL },
+ { 2, "rejectAnyUnrecognizedInvokePdu", ASN1_EXTENSION_ROOT,
+ dissect_h4501_NULL },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h4501_InterpretationApdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_InterpretationApdu, ett_h4501_InterpretationApdu, InterpretationApdu_choice, "InterpretationApdu", NULL);
+ return offset;
+}
+
+
+static int
+dissect_h4501_constrained_invokeId(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_h4501_constrained_invokeId, 0, 65535, NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static int
+dissect_h4501_invokeId(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_integer(tvb, offset, pinfo, tree, hf_h4501_invokeId, NULL, NULL);
+ return offset;
+}
+
+
+static const value_string localOpcode_vals[] = {
+ /* H.450.2 Call Transfer opcodes */
+ { CallTransferIdentify, "callTransferIdentify"},
+ { CallTransferAbandon, "callTransferAbandon"},
+ { CallTransferInitiate, "callTransferInitiate"},
+ { CallTransferSetup, "callTransferSetup"},
+ { CallTransferUpdate, "callTransferUpdate"},
+ { SubaddressTransfer, "subaddressTransfer"},
+ { CallTransferComplete, "callTransferComplete"},
+ { CallTransferActive, "callTransferActive"},
+
+ /* H.450.3 Call Diversion opcodes */
+ { ActivateDiversionQ, "activateDiversionQ"},
+ { DeactivateDiversionQ, "deactivateDiversionQ"},
+ { InterrogateDiversionQ, "interrogateDiversionQ"},
+ { CheckRestriction, "checkRestriction"},
+ { CallRerouting, "callRerouting"},
+ { DivertingLegInformation1,"divertingLegInformation1"},
+ { DivertingLegInformation2,"divertingLegInformation2"},
+ { DivertingLegInformation3,"divertingLegInformation3"},
+ { DivertingLegInformation4,"divertingLegInformation4"},
+ { CfnrDivertedLegFailed, "cfnrDivertedLegFailed"},
+
+ /* H.450.4 Call Hold opcodes */
+ { HoldNotific, "holdNotific"},
+ { RetrieveNotific, "retrieveNotific"},
+ { RemoteHold, "remoteHold"},
+ { RemoteRetrieve, "remoteRetrieve"},
+
+ /* H.450.5 Call Park and Pickup opcodes */
+ { CpRequest, "cpRequest"},
+ { CpSetup, "cpSetup"},
+ { GroupIndicationOn, "groupIndicationOn"},
+ { GroupIndicationOff, "groupIndicationOff"},
+ { Pickrequ, "pickrequ"},
+ { Pickup, "pickup"},
+ { PickExe, "pickExe"},
+ { CpNotify, "cpNotify"},
+ { CpickupNotify, "cpickupNotify"},
+
+ /* H.450.6 Call Waiting opcodes */
+ { CallWaiting, "callWaiting"},
+
+ /* H.450.7 Message Waiting Indication constants */
+ { MWIActivate, "mwiActivate"},
+ { MWIDeactivate, "mwiDeactivate"},
+ { MWIInterrogate, "mwiInterrogate"},
+
+ /* H.450.8 Name Identification constants */
+ { NIcallingName, "niCallingName"},
+ { NIalertingName, "niAlertingName"},
+ { NIconnectedName, "niConnectedName"},
+ { NIbusyName, "niBusyName"},
+
+ /* H.450.9 Call Completion constants */
+ { CCBSRequest, "ccbsRequest"},
+ { CCNRRequest, "ccnrRequest"},
+ { CCCancel, "ccCancel"},
+ { CCExecPossible, "ccExecPossible"},
+ { CCRingout, "ccRingout"},
+ { CCSuspend, "ccSuspend"},
+ { CCResume, "ccResume"},
+
+ /* H.450.10 Call Offer constants */
+ { CallOfferRequest, "callOfferRequest"},
+ { RemoteUserAlerting, "remoteUserAlerting"},
+ { CFBOverride, "cfbOverride"},
+
+ /* H.450.11 Call Intrusion constants */
+ { CallIntrusionRequest, "callIntrusionRequest"},
+ { CallIntrusionGetCIPL, "callIntrusionGetCIPL"},
+ { CallIntrusionIsolate, "callIntrusionIsolate"},
+ { CallIntrusionForcedRelease,"callIntrusionForcedRelease"},
+ { CallIntrusionWOBRequest, "callIntrusionWOBRequest"},
+ { CallIntrusionSilentMonitor,"callIntrusionSilentMonitor"},
+ { CallIntrusionNotification, "callIntrusionNotification"},
+
+ /* TODO - add other H.450.x invoke opcodes here */
+
+ { 0, NULL }
+};
+static int
+dissect_h4501_localOpcode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_integer(tvb, offset, pinfo, tree, hf_h4501_localOpcode, &localOpcode, NULL);
+ return offset;
+}
+
+
+static int
+dissect_h4501_globalCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_object_identifier(tvb, offset, pinfo, tree, hf_h4501_globalCode, NULL);
+ return offset;
+}
+
+
+static const value_string opcode_vals[] = {
+ { 0, "local" },
+ { 1, "global" },
+ { 0, NULL}
+};
+static per_choice_t opcode_choice[] = {
+ { 0, "local", ASN1_NO_EXTENSIONS,
+ dissect_h4501_localOpcode },
+ { 1, "global", ASN1_NO_EXTENSIONS,
+ dissect_h4501_globalCode },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h4501_opcode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_opcode, ett_h4501_opcode, opcode_choice, "Opcode", NULL);
+ return offset;
+}
+
+
+static int
+dissect_h4501_ExtensionSeq(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+PER_NOT_DECODED_YET("H.450.1 ExtensionSeq");
+ return offset;
+}
+
+
+static int
+dissect_h4502_nonStandardData(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_h225_NonStandardParameter(tvb, offset, pinfo, tree,
+ hf_h4502_nonStandardData);
+ return offset;
+}
+
+static const value_string Extension_vals[] = {
+ { 0, "extensionSeq" },
+ { 1, "nonStandardData" },
+ { 0, NULL}
+};
+static per_choice_t Extension_choice[] = {
+ { 0, "extensionSeq", ASN1_NO_EXTENSIONS,
+ dissect_h4501_ExtensionSeq },
+ { 1, "nonStandardData", ASN1_NO_EXTENSIONS,
+ dissect_h4502_nonStandardData },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h4502_DummyArg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4502_DummyArg, ett_h4502_DummyArg, Extension_choice, "DummyArg", NULL);
+ return offset;
+}
+
+
+static int
+dissect_h4502_CallIdentity(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_NumericString(tvb, offset, pinfo, tree, hf_h4502_CallIdentity, 0, 4);
+ return offset;
+}
+
+
+static int
+dissect_h4501_destinationAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h4501_destinationAddress, ett_h4501_destinationAddress, dissect_h225_AliasAddress);
+ return offset;
+}
+
+
+static per_sequence_t EndpointAddress_sequence[] = {
+ { "destinationAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_destinationAddress },
+ { "remoteExtensionAddress", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h225_AliasAddress },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4501_EndpointAddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4501_EndpointAddress, ett_h4501_EndpointAddress, EndpointAddress_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h4501_argumentExtension(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_argumentExtension, ett_h4501_argumentExtension, Extension_choice, "argumentExtension", NULL);
+ return offset;
+}
+
+
+static per_sequence_t CTInitiateArg_sequence[] = {
+ { "callIdentity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4502_CallIdentity },
+ { "reroutingNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_EndpointAddress },
+ { "argumentExtension", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_argumentExtension },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4502_CTInitiateArg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4502_CTInitiateArg, ett_h4502_CTInitiateArg, CTInitiateArg_sequence);
+ return offset;
+}
+
+
+static per_sequence_t CTSetupArg_sequence[] = {
+ { "callIdentity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4502_CallIdentity },
+ { "transferringNumber", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_EndpointAddress },
+ { "argumentExtension", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_argumentExtension },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4502_CTSetupArg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4502_CTSetupArg, ett_h4502_CTSetupArg, CTSetupArg_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h4502_redirectionInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_BMPString(tvb, offset, pinfo, tree, hf_h4502_redirectionInfo, 1, 128);
+ return offset;
+}
+
+
+static int
+dissect_h4501_H225InformationElement(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h4501_H225InformationElement, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+static per_sequence_t CTUpdateArg_sequence[] = {
+ { "redirectionNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_EndpointAddress },
+ { "redirectionInfo", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4502_redirectionInfo },
+ { "basicCallInfoElements", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_H225InformationElement },
+ { "argumentExtension", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_argumentExtension },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4502_CTUpdateArg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4502_CTUpdateArg, ett_h4502_CTUpdateArg, CTUpdateArg_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h4501_SubaddressInformation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h4501_SubaddressInformation, 1, 20, NULL, NULL);
+ return offset;
+}
+
+
+static const true_false_string tfs_oddCountIndicator_bit = {
+ "oddCountIndicator bit is SET",
+ "oddCountIndicator bit is CLEAR"
+};
+static int
+dissect_h4501_oddCountIndicator(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_h4501_oddCountIndicator, NULL, NULL);
+ return offset;
+}
+
+
+static per_sequence_t UserSpecifiedSubaddress_sequence[] = {
+ { "subaddressInformation", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_SubaddressInformation },
+ { "oddCountIndicator", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_oddCountIndicator },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4501_UserSpecifiedSubaddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4501_UserSpecifiedSubaddress, ett_h4501_UserSpecifiedSubaddress, UserSpecifiedSubaddress_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h4501_NSAPSubaddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h4501_NSAPAddress, 1, 20, NULL, NULL);
+ return offset;
+}
+
+
+static const value_string PartySubaddress_vals[] = {
+ { 0, "userSpecifiedSubaddress" },
+ { 1, "nsapSubaddress" },
+ { 0, NULL}
+};
+static per_choice_t PartySubaddress_choice[] = {
+ { 0, "userSpecifiedSubaddress", ASN1_EXTENSION_ROOT,
+ dissect_h4501_UserSpecifiedSubaddress },
+ { 1, "nsapSubaddress", ASN1_EXTENSION_ROOT,
+ dissect_h4501_NSAPSubaddress },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h4501_PartySubaddress(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_PartySubaddress, ett_h4501_PartySubaddress, PartySubaddress_choice, "PartySubaddress", NULL);
+ return offset;
+}
+
+
+static per_sequence_t SubaddressTransferArg_sequence[] = {
+ { "redirectionSubaddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_PartySubaddress },
+ { "argumentExtension", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_argumentExtension },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4502_SubaddressTransferArg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4502_SubaddressTransferArg, ett_h4502_SubaddressTransferArg, SubaddressTransferArg_sequence);
+ return offset;
+}
+
+
+static const value_string EndDesignation_vals[] = {
+ { 0, "primaryEnd"},
+ { 1, "secondaryEnd"},
+ { 0, NULL }
+};
+static int
+dissect_h4502_EndDesignation(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_h4502_EndDesignation, 0, 1, NULL, NULL, TRUE);
+ return offset;
+}
+
+
+static const value_string CallStatus_vals[] = {
+ { 0, "answered"},
+ { 1, "alerting"},
+ { 0, NULL }
+};
+static int
+dissect_h4502_CallStatus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_h4502_CallStatus, 0, 1, NULL, NULL, TRUE);
+ return offset;
+}
+
+
+static per_sequence_t CTCompleteArg_sequence[] = {
+ { "endDesignation", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4502_EndDesignation },
+ { "redirectionNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_EndpointAddress },
+ { "basicCallInfoElements", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_H225InformationElement },
+ { "redirectionInfo", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4502_redirectionInfo },
+ { "callStatus", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4502_CallStatus },
+ { "argumentExtension", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_argumentExtension },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4502_CTCompleteArg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4502_CTCompleteArg, ett_h4502_CTCompleteArg, CTCompleteArg_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h4502_connectedInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_BMPString(tvb, offset, pinfo, tree, hf_h4502_connectedInfo, 1, 128);
+ return offset;
+}
+
+
+static per_sequence_t CTActiveArg_sequence[] = {
+ { "connectedAddress", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_EndpointAddress },
+ { "basicCallInfoElements", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_H225InformationElement },
+ { "connectedInfo", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4502_connectedInfo },
+ { "argumentExtension", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_argumentExtension },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4502_CTActiveArg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4502_CTActiveArg, ett_h4502_CTActiveArg, CTActiveArg_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h4501_argument(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *argument_tvb;
+ guint32 argument_offset=0;
+ guint32 argument_len=0;
+
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, -1, -1, -1, &argument_offset, &argument_len);
+
+ if(argument_len){
+ argument_tvb = tvb_new_subset(tvb, argument_offset, argument_len, argument_len);
+
+ switch (localOpcode) {
+ case CallTransferIdentify:
+ case CallTransferAbandon:
+ offset = dissect_h4502_DummyArg(argument_tvb, 0, pinfo, tree);
+ break;
+
+ case CallTransferInitiate:
+ offset = dissect_h4502_CTInitiateArg(argument_tvb, 0, pinfo, tree);
+ break;
+
+ case CallTransferSetup:
+ offset = dissect_h4502_CTSetupArg(argument_tvb, 0, pinfo, tree);
+ break;
+
+ case CallTransferUpdate:
+ offset = dissect_h4502_CTUpdateArg(argument_tvb, 0, pinfo, tree);
+ break;
+
+ case SubaddressTransfer:
+ offset = dissect_h4502_SubaddressTransferArg(argument_tvb, 0, pinfo, tree);
+ break;
+
+ case CallTransferComplete:
+ offset = dissect_h4502_CTCompleteArg(argument_tvb, 0, pinfo, tree);
+ break;
+
+ case CallTransferActive:
+ offset = dissect_h4502_CTActiveArg(argument_tvb, 0, pinfo, tree);
+ break;
+
+ /* TODO - decode other H.450.x invoke arguments here */
+
+ default:
+PER_NOT_DECODED_YET("Unrecognized H.450.x operation");
+ break;
+ }
+ }
+ return offset;
+}
+
+
+static per_sequence_t Invoke_sequence[] = {
+ { "invokeID", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h4501_constrained_invokeId },
+ { "linkedId", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h4501_invokeId },
+ { "opcode", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h4501_opcode },
+ { "argument", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h4501_argument },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4501_Invoke(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4501_Invoke, ett_h4501_Invoke, Invoke_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h4501_resultExtension(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_resultExtension, ett_h4501_resultExtension, Extension_choice, "resultExtension", NULL);
+ return offset;
+}
+
+
+static per_sequence_t CTIdentifyRes_sequence[] = {
+ { "callIdentity", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4502_CallIdentity },
+ { "reroutingNumber", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_EndpointAddress },
+ { "resultExtension", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_resultExtension },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4502_CTIdentifyRes(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4502_CTIdentifyRes, ett_h4502_CTIdentifyRes, CTIdentifyRes_sequence);
+ return offset;
+}
+
+
+static int
+dissect_h4502_DummyRes(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4502_DummyRes, ett_h4502_DummyRes, Extension_choice, "DummyRes", NULL);
+ return offset;
+}
+
+
+static int
+dissect_h4501_ReturnResult_result(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *result_tvb;
+ guint32 result_offset=0;
+ guint32 result_len=0;
+
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, -1, -1, -1, &result_offset, &result_len);
+
+ if(result_len){
+ result_tvb = tvb_new_subset(tvb, result_offset, result_len, result_len);
+
+ switch (localOpcode) {
+ case CallTransferIdentify:
+ offset = dissect_h4502_CTIdentifyRes(result_tvb, 0, pinfo, tree);
+ break;
+
+ case CallTransferInitiate:
+ case CallTransferSetup:
+ offset = dissect_h4502_DummyRes(result_tvb, 0, pinfo, tree);
+ break;
+
+ default:
+PER_NOT_DECODED_YET("Unrecognized H.450.x return result");
+ break;
+ }
+ }
+
+ return offset;
+}
+
+
+static per_sequence_t result_sequence[] = {
+ { "opcode", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_opcode },
+ { "result", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_ReturnResult_result },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4501_result(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4501_result, ett_h4501_result, result_sequence);
+ return offset;
+}
+
+
+static per_sequence_t ReturnResult_sequence[] = {
+ { "invokeID", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h4501_invokeId },
+ { "result", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h4501_result },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4501_ReturnResult(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4501_ReturnResult, ett_h4501_ReturnResult, ReturnResult_sequence);
+ return offset;
+}
+
+
+static const value_string localErrorCode_vals[] = {
+ /* H.450.1 general error list */
+ { 0, "userNotSubscribed"},
+ { 1, "RejectedByNetwork"},
+ { 2, "RejectedByUser"},
+ { 3, "NotAvailable"},
+ { 5, "InsufficientInformation"},
+ { 6, "InvalidServedUserNumber"},
+ { 7, "InvalidCallState"},
+ { 8, "BasicServiceNotProvided"},
+ { 9, "NotIncomingCall"},
+ { 10, "SupplementaryServiceInteractionNotAllowed"},
+ { 11, "ResourceUnavailable"},
+ { 25, "CallFailure"},
+ { 43, "ProceduralError"},
+
+ /* H.450.2 Call Transfer return errors */
+ { 1004, "invalidReroutingNumber"},
+ { 1005, "unrecognizedCallIdentity"},
+ { 1006, "establishmentFailure"},
+ { 1008, "unspecified"},
+
+ /* H.450.4 Call Hold return errors */
+ { 2002, "undefined"},
+
+ /* H.450.5 Call Park and Pickup return errors */
+ { 2000, "callPickupIdInvalid"},
+ { 2001, "callAlreadyPickedUp"},
+
+ /* H.450.7 Message Waiting Indication return errors */
+ { 1018, "invalidMsgCentreId"},
+ { 31, "notActivated"},
+
+ /* H.450.9 Call Completion return errors */
+ { 1010, "shortTermRejection"},
+ { 1011, "longTermRejection"},
+ { 1012, "remoteUserBusyAgain"},
+ { 1013, "failureToMatch"},
+
+ /* H.450.11 Call Intrusion return errors */
+ { 1009, "notBusy"},
+ { 1000, "temporarilyUnavailable"},
+ { 1007, "notAuthorized"},
+
+ /* TODO - add other H.450.x error codes here */
+
+ { 0, NULL }
+};
+static int
+dissect_h4501_localErrorCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_integer(tvb, offset, pinfo, tree, hf_h4501_localErrorCode, &localErrorCode, NULL);
+ return offset;
+}
+
+
+static const value_string errorCode_vals[] = {
+ { 0, "local" },
+ { 1, "global" },
+ { 0, NULL}
+};
+static per_choice_t errorCode_choice[] = {
+ { 0, "local", ASN1_NO_EXTENSIONS,
+ dissect_h4501_localErrorCode },
+ { 1, "global", ASN1_NO_EXTENSIONS,
+ dissect_h4501_globalCode },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h4501_errorCode(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_errorCode, ett_h4501_errorCode, errorCode_choice, "errorCode", NULL);
+ return offset;
+}
+
+
+static int
+dissect_h4501_parameter(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* TODO - decode return error parameter based on localErrorCode */
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_h4501_parameter, -1, -1, NULL, NULL);
+ return offset;
+}
+
+
+static per_sequence_t ReturnError_sequence[] = {
+ { "invokeID", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h4501_invokeId },
+ { "errorCode", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h4501_errorCode },
+ { "parameter", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_h4501_parameter },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4501_ReturnError(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4501_ReturnError, ett_h4501_ReturnError, ReturnError_sequence);
+ return offset;
+}
+
+
+static const value_string GeneralProblem_vals[] = {
+ { 0, "unrecognizedCompenent"},
+ { 1, "mistypedCompenent"},
+ { 2, "badlyStructuredCompenent"},
+ { 0, NULL }
+};
+static int
+dissect_h4501_GeneralProblem(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_h4501_GeneralProblem, 0, 2, NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static const value_string InvokeProblem_vals[] = {
+ { 0, "duplicateInvocation"},
+ { 1, "unrecognizedOperation"},
+ { 2, "mistypedArgument"},
+ { 3, "resourceLimitation"},
+ { 4, "releaseInProgress"},
+ { 5, "unrecognizedLinkedId"},
+ { 6, "linkedResponseUnexpected"},
+ { 7, "unexpectedLinkedOperation"},
+ { 0, NULL }
+};
+static int
+dissect_h4501_InvokeProblem(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_h4501_InvokeProblem, 0, 7, NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static const value_string ReturnResultProblem_vals[] = {
+ { 0, "unrecognizedInvocation"},
+ { 1, "resultResponseUnexpected"},
+ { 2, "mistypedResult"},
+ { 0, NULL }
+};
+static int
+dissect_h4501_ReturnResultProblem(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_h4501_ReturnResultProblem, 0, 2, NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static const value_string ReturnErrorProblem_vals[] = {
+ { 0, "unrecognizedInvocation"},
+ { 1, "errorResponseUnexpected"},
+ { 2, "unrecognizedError"},
+ { 3, "unexpectedError"},
+ { 4, "mistypedParameter"},
+ { 0, NULL }
+};
+static int
+dissect_h4501_ReturnErrorProblem(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo, tree, hf_h4501_ReturnErrorProblem, 0, 4, NULL, NULL, FALSE);
+ return offset;
+}
+
+
+static const value_string problem_vals[] = {
+ { 0, "general" },
+ { 1, "invoke" },
+ { 2, "returnResult" },
+ { 3, "returnError" },
+ { 0, NULL}
+};
+static per_choice_t problem_choice[] = {
+ { 0, "general", ASN1_NO_EXTENSIONS,
+ dissect_h4501_GeneralProblem },
+ { 1, "invoke", ASN1_NO_EXTENSIONS,
+ dissect_h4501_InvokeProblem },
+ { 2, "returnResult", ASN1_NO_EXTENSIONS,
+ dissect_h4501_ReturnResultProblem },
+ { 3, "returnError", ASN1_NO_EXTENSIONS,
+ dissect_h4501_ReturnErrorProblem },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h4501_problem(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_problem, ett_h4501_problem, problem_choice, "problem", NULL);
+ return offset;
+}
+
+
+static per_sequence_t Reject_sequence[] = {
+ { "invokeID", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h4501_invokeId },
+ { "problem", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_h4501_problem },
+ { NULL, 0, 0, NULL }
+};
+static int
+dissect_h4501_Reject(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo, tree, hf_h4501_Reject, ett_h4501_Reject, Reject_sequence);
+ return offset;
+}
+
+
+static const value_string ROS_vals[] = {
+ { 1, "invoke" },
+ { 2, "returnResult" },
+ { 3, "returnError" },
+ { 4, "reject" },
+ { 0, NULL}
+};
+static per_choice_t ROS_choice[] = {
+ { 1, "invoke", ASN1_NO_EXTENSIONS,
+ dissect_h4501_Invoke },
+ { 2, "returnResult", ASN1_NO_EXTENSIONS,
+ dissect_h4501_ReturnResult },
+ { 3, "returnError", ASN1_NO_EXTENSIONS,
+ dissect_h4501_ReturnError },
+ { 4, "reject", ASN1_NO_EXTENSIONS,
+ dissect_h4501_Reject },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h4501_ROS(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_ROS, ett_h4501_ROS, ROS_choice, "ROS", NULL);
+ return offset;
+}
+
+
+static int
+dissect_h4501_rosApdus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, tree, hf_h4501_rosApdus, ett_h4501_rosApdus, dissect_h4501_ROS);
+ return offset;
+}
+
+
+static const value_string ServiceApdus_vals[] = {
+ { 0, "rosApdus" },
+ { 0, NULL}
+};
+static per_choice_t ServiceApdus_choice[] = {
+ { 0, "rosApdus", ASN1_EXTENSION_ROOT,
+ dissect_h4501_rosApdus },
+ { 0, NULL, 0, NULL }
+};
+static int
+dissect_h4501_ServiceApdus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo, tree, hf_h4501_ServiceApdus, ett_h4501_ServiceApdus, ServiceApdus_choice, "ServiceApdus", NULL);
+ return offset;
+}
+
+
+static per_sequence_t H4501_SupplementaryService_sequence[] = {
+ { "networkFacilityExtension", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_NetworkFacilityExtension },
+ { "interpretationApdu", ASN1_EXTENSION_ROOT, ASN1_OPTIONAL,
+ dissect_h4501_InterpretationApdu },
+ { "serviceApdu", ASN1_EXTENSION_ROOT, ASN1_NOT_OPTIONAL,
+ dissect_h4501_ServiceApdus },
+ { NULL, 0, 0, NULL }
+};
+static void
+dissect_h4501(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree)
+{
+ proto_item *it;
+ proto_tree *tr;
+ guint32 offset=0;
+
+ it=proto_tree_add_protocol_format(tree, proto_h4501, tvb, 0, tvb_length(tvb), "H.450.1");
+ tr=proto_item_add_subtree(it, ett_h4501);
+
+ offset=dissect_per_sequence(tvb, offset, pinfo, tr, hf_h4501, ett_h4501, H4501_SupplementaryService_sequence);
+}
+
+
+void
+proto_register_h4501(void)
+{
+ static hf_register_info hf[] =
+ {
+ { &hf_h4501,
+ { "SupplementaryService", "h4501.SupplementaryService", FT_NONE, BASE_NONE,
+ NULL, 0, "SupplementaryService sequence", HFILL }},
+ { &hf_h4501_EntityType,
+ { "EntityType", "h4501.EntityType", FT_UINT32, BASE_DEC,
+ VALS(EntityType_vals), 0, "EntityType choice", HFILL }},
+ { &hf_h4501_NetworkFacilityExtension,
+ { "NetworkFacilityExtension", "h4501.NetworkFacilityExtension", FT_NONE, BASE_NONE,
+ NULL, 0, "NetworkFacilityExtension sequence", HFILL }},
+ { &hf_h4501_InterpretationApdu,
+ { "InterpretationApdu", "h4501.InterpretationApdu", FT_UINT32, BASE_DEC,
+ VALS(InterpretationApdu_vals), 0, "InterpretationApdu choice", HFILL }},
+ { &hf_h4501_constrained_invokeId,
+ { "invokeId", "h4501.invokeId", FT_UINT32, BASE_DEC,
+ NULL, 0, "invokeId", HFILL }},
+ { &hf_h4501_invokeId,
+ { "invokeId", "h4501.invokeId", FT_INT32, BASE_DEC,
+ NULL, 0, "invokeId", HFILL }},
+ { &hf_h4501_localOpcode,
+ { "opcode", "h4501.opcode", FT_INT32, BASE_DEC,
+ VALS(localOpcode_vals), 0, "local", HFILL }},
+ { &hf_h4501_globalCode,
+ { "global", "h4501.global", FT_STRING, BASE_HEX,
+ NULL, 0, "global", HFILL }},
+ { &hf_h4501_opcode,
+ { "opcode", "h4501.opcode", FT_UINT32, BASE_DEC,
+ VALS(opcode_vals), 0, "opcode choice", HFILL }},
+ { &hf_h4502_CallIdentity,
+ { "CallIdentity", "h4502.CallIdentity", FT_STRING, BASE_NONE,
+ NULL, 0, "CallIdentity", HFILL }},
+ { &hf_h4501_destinationAddress,
+ { "destinationAddress", "h4501.destinationAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "destinationAddress sequence of", HFILL }},
+ { &hf_h4501_EndpointAddress,
+ { "EndpointAddress", "h4501.EndpointAddress", FT_NONE, BASE_NONE,
+ NULL, 0, "EndpointAddress sequence of", HFILL }},
+ { &hf_h4501_H225InformationElement,
+ { "H225InformationElement", "h4501.H225InformationElement", FT_BYTES, BASE_HEX,
+ NULL, 0, "H225InformationElement", HFILL }},
+ { &hf_h4502_nonStandardData,
+ { "nonStandardData", "h4502.nonStandardData", FT_NONE, BASE_NONE,
+ NULL, 0, "NonStandardParameter SEQUENCE", HFILL }},
+ { &hf_h4502_DummyArg,
+ { "DummyArg", "h4502.DummyArg", FT_UINT32, BASE_DEC,
+ VALS(Extension_vals), 0, "DummyArg choice", HFILL }},
+ { &hf_h4502_CTInitiateArg,
+ { "CTInitiateArg", "h4502.CTInitiateArg", FT_NONE, BASE_NONE,
+ NULL, 0, "CTInitiateArg sequence of", HFILL }},
+ { &hf_h4502_CTSetupArg,
+ { "CTSetupArg", "h4502.CTSetupArg", FT_NONE, BASE_NONE,
+ NULL, 0, "CTSetupArg sequence of", HFILL }},
+ { &hf_h4502_redirectionInfo,
+ { "redirectionInfo", "h4502.redirectionInfo", FT_STRING, BASE_HEX,
+ NULL, 0, "redirectionInfo BMPString", HFILL }},
+ { &hf_h4502_CTUpdateArg,
+ { "CTUpdateArg", "h4502.CTUpdateArg", FT_NONE, BASE_NONE,
+ NULL, 0, "CTUpdateArg sequence of", HFILL }},
+ { &hf_h4501_SubaddressInformation,
+ { "SubaddressInformation", "h4501.SubaddressInformation", FT_BYTES, BASE_HEX,
+ NULL, 0, "SubaddressInformation octet string", HFILL }},
+ { &hf_h4501_oddCountIndicator,
+ { "oddCountIndicator", "h4501.oddCountIndicator", FT_BOOLEAN, 8,
+ TFS(&tfs_oddCountIndicator_bit), 0x01, "The oddCountIndicator bit", HFILL }},
+ { &hf_h4501_UserSpecifiedSubaddress,
+ { "UserSpecifiedSubaddress", "h4501.UserSpecifiedSubaddress", FT_NONE, BASE_NONE,
+ NULL, 0, "UserSpecifiedSubaddress sequence of", HFILL }},
+ { &hf_h4501_NSAPAddress,
+ { "NSAPAddress", "h4501.NSAPAddress", FT_BYTES, BASE_HEX,
+ NULL, 0, "NSAPAddress octet string", HFILL }},
+ { &hf_h4501_PartySubaddress,
+ { "PartySubaddress", "h4501.PartySubaddress", FT_UINT32, BASE_DEC,
+ VALS(PartySubaddress_vals), 0, "PartySubaddress choice", HFILL }},
+ { &hf_h4502_SubaddressTransferArg,
+ { "SubaddressTransferArg", "h4502.SubaddressTransferArg", FT_NONE, BASE_NONE,
+ NULL, 0, "SubaddressTransferArg sequence of", HFILL }},
+ { &hf_h4502_EndDesignation,
+ { "EndDesignation", "h4502.EndDesignation", FT_UINT32, BASE_DEC,
+ VALS(EndDesignation_vals), 0, "EndDesignation", HFILL }},
+ { &hf_h4502_CallStatus,
+ { "CallStatus", "h4502.CallStatus", FT_UINT32, BASE_DEC,
+ VALS(CallStatus_vals), 0, "CallStatus", HFILL }},
+ { &hf_h4502_CTCompleteArg,
+ { "CTCompleteArg", "h4502.CTCompleteArg", FT_NONE, BASE_NONE,
+ NULL, 0, "CTCompleteArg sequence of", HFILL }},
+ { &hf_h4502_connectedInfo,
+ { "connectedInfo", "h4502.connectedInfo", FT_STRING, BASE_HEX,
+ NULL, 0, "connectedInfo BMPString", HFILL }},
+ { &hf_h4502_CTActiveArg,
+ { "CTActiveArg", "h4502.CTActiveArg", FT_NONE, BASE_NONE,
+ NULL, 0, "CTActiveArg sequence of", HFILL }},
+ { &hf_h4501_argumentExtension,
+ { "argumentExtension", "h4501.argumentExtension", FT_UINT32, BASE_DEC,
+ VALS(Extension_vals), 0, "argumentExtension choice", HFILL }},
+ { &hf_h4501_argument,
+ { "argument", "h4501.argument", FT_BYTES, BASE_HEX,
+ NULL, 0, "argument", HFILL }},
+ { &hf_h4501_Invoke,
+ { "Invoke", "h4501.Invoke", FT_NONE, BASE_NONE,
+ NULL, 0, "Invoke sequence of", HFILL }},
+ { &hf_h4502_CTIdentifyRes,
+ { "CTIdentifyRes", "h4502.CTIdentifyRes", FT_NONE, BASE_NONE,
+ NULL, 0, "CTIdentifyRes sequence of", HFILL }},
+ { &hf_h4502_DummyRes,
+ { "DummyRes", "h4502.DummyRes", FT_UINT32, BASE_DEC,
+ VALS(Extension_vals), 0, "DummyRes Choice", HFILL }},
+ { &hf_h4501_resultExtension,
+ { "resultExtension", "h4501.resultExtension", FT_UINT32, BASE_DEC,
+ VALS(Extension_vals), 0, "resultExtension choice", HFILL }},
+ { &hf_h4501_ReturnResult_result,
+ { "result", "h4501.ReturnResult.result", FT_BYTES, BASE_HEX,
+ NULL, 0, "result", HFILL }},
+ { &hf_h4501_result,
+ { "result", "h4501.result", FT_NONE, BASE_NONE,
+ NULL, 0, "result sequence of", HFILL }},
+ { &hf_h4501_ReturnResult,
+ { "ReturnResult", "h4501.ReturnResult", FT_NONE, BASE_NONE,
+ NULL, 0, "ReturnResult sequence of", HFILL }},
+ { &hf_h4501_localErrorCode,
+ { "errorCode", "h4501.errorCode", FT_INT32, BASE_DEC,
+ VALS(localErrorCode_vals), 0, "local", HFILL }},
+ { &hf_h4501_errorCode,
+ { "errorCode", "h4501.errorCode", FT_UINT32, BASE_DEC,
+ VALS(errorCode_vals), 0, "errorCode", HFILL }},
+ { &hf_h4501_parameter,
+ { "parameter", "h4501.parameter", FT_BYTES, BASE_HEX,
+ NULL, 0, "parameter", HFILL }},
+ { &hf_h4501_ReturnError,
+ { "ReturnError", "h4501.ReturnError", FT_NONE, BASE_NONE,
+ NULL, 0, "ReturnError sequence of", HFILL }},
+ { &hf_h4501_GeneralProblem,
+ { "GeneralProblem", "h4501.GeneralProblem", FT_UINT32, BASE_DEC,
+ VALS(GeneralProblem_vals), 0, "GeneralProblem", HFILL }},
+ { &hf_h4501_InvokeProblem,
+ { "InvokeProblem", "h4501.InvokeProblem", FT_UINT32, BASE_DEC,
+ VALS(InvokeProblem_vals), 0, "InvokeProblem", HFILL }},
+ { &hf_h4501_ReturnResultProblem,
+ { "ReturnResultProblem", "h4501.ReturnResultProblem", FT_UINT32, BASE_DEC,
+ VALS(ReturnResultProblem_vals), 0, "ReturnResultProblem", HFILL }},
+ { &hf_h4501_ReturnErrorProblem,
+ { "ReturnErrorProblem", "h4501.ReturnErrorProblem", FT_UINT32, BASE_DEC,
+ VALS(ReturnErrorProblem_vals), 0, "ReturnErrorProblem", HFILL }},
+ { &hf_h4501_problem,
+ { "problem", "h4501.problem", FT_UINT32, BASE_DEC,
+ VALS(problem_vals), 0, "problem choice", HFILL }},
+ { &hf_h4501_Reject,
+ { "Reject", "h4501.Reject", FT_NONE, BASE_NONE,
+ NULL, 0, "Reject sequence of", HFILL }},
+ { &hf_h4501_ROS,
+ { "ROS", "h4501.ROS", FT_UINT32, BASE_DEC,
+ VALS(ROS_vals), 0, "ROS choice", HFILL }},
+ { &hf_h4501_rosApdus,
+ { "rosApdus", "h4501.rosApdus", FT_NONE, BASE_NONE,
+ NULL, 0, "rosApdus sequence of", HFILL }},
+ { &hf_h4501_ServiceApdus,
+ { "ServiceApdus", "h4501.ServiceApdus", FT_UINT32, BASE_DEC,
+ VALS(ServiceApdus_vals), 0, "ServiceApdus choice", HFILL }}
+ };
+
+ static gint *ett[] =
+ {
+ &ett_h4501,
+ &ett_h4501_EntityType,
+ &ett_h4501_NetworkFacilityExtension,
+ &ett_h4501_InterpretationApdu,
+ &ett_h4501_opcode,
+ &ett_h4501_destinationAddress,
+ &ett_h4501_EndpointAddress,
+ &ett_h4501_PartySubaddress,
+ &ett_h4501_argumentExtension,
+ &ett_h4501_Invoke,
+ &ett_h4501_resultExtension,
+ &ett_h4501_result,
+ &ett_h4501_ReturnResult,
+ &ett_h4501_errorCode,
+ &ett_h4501_ReturnError,
+ &ett_h4501_problem,
+ &ett_h4501_Reject,
+ &ett_h4501_ROS,
+ &ett_h4501_rosApdus,
+ &ett_h4501_ServiceApdus,
+
+ &ett_h4502_DummyArg,
+ &ett_h4502_CTInitiateArg,
+ &ett_h4502_CTSetupArg,
+ &ett_h4502_CTUpdateArg,
+ &ett_h4502_SubaddressTransferArg,
+ &ett_h4502_CTCompleteArg,
+ &ett_h4502_CTActiveArg,
+ &ett_h4502_CTIdentifyRes,
+ &ett_h4502_DummyRes
+ };
+
+ proto_h4501 = proto_register_protocol("H4501", "H4501", "h4501");
+ proto_register_field_array(proto_h4501, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("h4501", dissect_h4501, proto_h4501);
+}
+
+void
+proto_reg_handoff_h4501(void)
+{
+ h4501_handle=create_dissector_handle(dissect_h4501, proto_h4501);
+}
diff --git a/epan/dissectors/packet-hclnfsd.c b/epan/dissectors/packet-hclnfsd.c
new file mode 100644
index 0000000000..1adf5ac57a
--- /dev/null
+++ b/epan/dissectors/packet-hclnfsd.c
@@ -0,0 +1,879 @@
+/* packet-hclnfsd.c
+ * Routines for hclnfsd (Hummingbird NFS Daemon) dissection
+ * Copyright 2001, Mike Frisch <frisch@hummingbird.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-ypserv.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "packet-rpc.h"
+#include "packet-nfs.h"
+#include "packet-hclnfsd.h"
+
+static int proto_hclnfsd = -1;
+static int hf_hclnfsd_procedure_v1 = -1;
+static int hf_hclnfsd_request_type = -1;
+static int hf_hclnfsd_device = -1;
+static int hf_hclnfsd_login = -1;
+static int hf_hclnfsd_lockname = -1;
+static int hf_hclnfsd_unknown_data = -1;
+static int hf_hclnfsd_lockowner = -1;
+static int hf_hclnfsd_printername = -1;
+static int hf_hclnfsd_filename = -1;
+static int hf_hclnfsd_fileext = -1;
+static int hf_hclnfsd_grpname = -1;
+static int hf_hclnfsd_hostname = -1;
+static int hf_hclnfsd_username = -1;
+static int hf_hclnfsd_queuename = -1;
+static int hf_hclnfsd_queuecomment = -1;
+static int hf_hclnfsd_queuestatus = -1;
+static int hf_hclnfsd_numphysicalprinters = -1;
+static int hf_hclnfsd_printqueuenumber = -1;
+static int hf_hclnfsd_printparams = -1;
+static int hf_hclnfsd_status = -1;
+static int hf_hclnfsd_sequence = -1;
+static int hf_hclnfsd_server_ip = -1;
+static int hf_hclnfsd_host_ip = -1;
+static int hf_hclnfsd_gid = -1;
+static int hf_hclnfsd_uid = -1;
+static int hf_hclnfsd_cookie = -1;
+static int hf_hclnfsd_mode = -1;
+static int hf_hclnfsd_access = -1;
+static int hf_hclnfsd_exclusive = -1;
+static int hf_hclnfsd_offset = -1;
+static int hf_hclnfsd_length = -1;
+static int hf_hclnfsd_jobstatus = -1;
+static int hf_hclnfsd_timesubmitted = -1;
+static int hf_hclnfsd_size = -1;
+static int hf_hclnfsd_copies = -1;
+static int hf_hclnfsd_auth_ident_obscure = -1;
+
+static gint ett_hclnfsd = -1;
+static gint ett_hclnfsd_gids = -1;
+static gint ett_hclnfsd_groups = -1;
+static gint ett_hclnfsd_uids = -1;
+static gint ett_hclnfsd_usernames = -1;
+static gint ett_hclnfsd_printqueues = -1;
+static gint ett_hclnfsd_printjob = -1;
+static gint ett_hclnfsd_auth_ident = -1;
+
+static int
+dissect_hclnfsd_gids(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 ngids, ngids_i, gid;
+ proto_tree *gidtree = NULL;
+ proto_item *giditem = NULL;
+
+
+ ngids = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ {
+ giditem = proto_tree_add_text(tree, tvb, offset, 4, "GIDs: %d",
+ ngids);
+ if (giditem)
+ gidtree = proto_item_add_subtree(giditem, ett_hclnfsd_gids);
+ }
+ offset += 4;
+
+ if (gidtree)
+ {
+ for (ngids_i = 0; ngids_i < ngids; ngids_i++)
+ {
+ gid = tvb_get_ntohl(tvb, offset + (4 * ngids_i));
+ proto_tree_add_text(gidtree, tvb, offset + (4 * ngids_i), 4,
+ "GID: %d", gid);
+ }
+ }
+ offset += 4 * ngids;
+
+ return offset;
+}
+
+static int
+dissect_hclnfsd_spool_inquire_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_status, offset);
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "spool filehandle", NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_spool_file_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_printername, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_filename, offset, NULL);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_fileext, offset);
+
+ return offset;
+}
+
+
+static const value_string names_request_type[] = {
+#define HCLNFSD_DISK_REQUEST 4
+ { HCLNFSD_DISK_REQUEST, "DISK" },
+#define HCLNFSD_PRINT_REQUEST 3
+ { HCLNFSD_PRINT_REQUEST, "PRINTER" },
+ { 0, NULL }
+};
+
+static void
+hclnfsd_decode_obscure(char *ident, int ident_len)
+{
+ int j, x, y;
+
+ for (x = -1, j = 0; j < ident_len; j++)
+ {
+ y = *ident;
+ x ^= *ident;
+ *ident++ = x;
+ x = y;
+ }
+}
+
+
+static int
+dissect_hclnfsd_authorize_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 request_type;
+ char *ident = NULL;
+ char *username = NULL;
+ char *password = NULL;
+ int ident_len = 0;
+ int newoffset;
+ proto_item *ident_item = NULL;
+ proto_tree *ident_tree = NULL;
+
+ proto_tree_add_item(tree, hf_hclnfsd_server_ip, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ request_type = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ proto_tree_add_uint(tree, hf_hclnfsd_request_type, tvb, offset,
+ 4, request_type);
+ offset += 4;
+
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_device, offset,
+ NULL);
+
+ if (tree)
+ {
+ ident_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "Authentication Ident");
+
+ if (ident_item)
+ {
+ ident_tree = proto_item_add_subtree(ident_item,
+ ett_hclnfsd_auth_ident);
+
+ if (ident_tree)
+ {
+ newoffset = dissect_rpc_string(tvb, ident_tree,
+ hf_hclnfsd_auth_ident_obscure, offset, &ident);
+
+ if (ident)
+ {
+ ident_len = strlen(ident);
+
+ proto_item_set_len(ident_item, ident_len);
+
+ hclnfsd_decode_obscure(ident, ident_len);
+
+ username = ident + 2;
+ password = username + strlen(username) + 1;
+
+ proto_tree_add_text(ident_tree, tvb, offset, ident_len,
+ "Username: %s", username);
+
+ proto_tree_add_text(ident_tree, tvb, offset, ident_len,
+ "Password: %s", password);
+
+ offset = newoffset;
+
+ g_free(ident);
+ ident = NULL;
+ }
+ }
+ }
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_authorize_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 status;
+
+ status = tvb_get_ntohl(tvb, offset);
+ if (!tree)
+ return offset;
+ offset += 4;
+
+ if (status != 0)
+ return offset;
+
+ proto_tree_add_uint(tree, hf_hclnfsd_status, tvb, offset, 4, status);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_uid, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_gid, offset);
+
+ offset = dissect_hclnfsd_gids(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+static int
+dissect_hclnfsd_grp_name_to_numb_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_grpname, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_hclnfsd_grp_name_to_numb_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_gid, offset);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_grp_to_number_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+
+ offset = dissect_hclnfsd_gids(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_grp_to_number_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ return dissect_rpc_string(tvb, tree, hf_hclnfsd_grpname, offset,
+ NULL);
+}
+
+
+static int
+dissect_hclnfsd_return_host_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_tree_add_item(tree, hf_hclnfsd_host_ip, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_return_host_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_hostname, offset, NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_uid_to_name_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 nuids, nuids_i;
+ proto_tree *uidtree = NULL;
+ proto_item *uiditem = NULL;
+
+ nuids = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ {
+ uiditem = proto_tree_add_text(tree, tvb, offset, 4, "UIDs: %d",
+ nuids);
+
+ if (uiditem)
+ uidtree = proto_item_add_subtree(uiditem, ett_hclnfsd_uids);
+ }
+ offset += 4;
+
+ if (!uidtree)
+ return offset;
+
+ for (nuids_i = 0; nuids_i < nuids; nuids_i++)
+ offset = dissect_rpc_uint32(tvb, uidtree, hf_hclnfsd_uid, offset);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_uid_to_name_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 nusers, nusers_i;
+ proto_tree *usertree = NULL;
+ proto_item *useritem = NULL;
+
+ nusers = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ {
+ useritem = proto_tree_add_text(tree, tvb, offset, 4, "UIDs: %d",
+ nusers);
+
+ if (useritem)
+ usertree = proto_item_add_subtree(useritem, ett_hclnfsd_usernames);
+ }
+ offset += 4;
+
+ if (!usertree)
+ return offset;
+
+ for (nusers_i = 0; nusers_i < nusers; nusers_i++)
+ offset = dissect_rpc_string(tvb, usertree,
+ hf_hclnfsd_username, offset, NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_name_to_uid_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_username, offset, NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_name_to_uid_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_uid, offset);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_share_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 request_type;
+
+ request_type = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ proto_tree_add_uint(tree, hf_hclnfsd_request_type, tvb, offset,
+ 4, request_type);
+ offset += 4;
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_cookie, offset);
+
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_lockname, offset, NULL);
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "Filehandle", NULL);
+
+ offset = dissect_rpc_data(tvb, tree, hf_hclnfsd_unknown_data, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_mode, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_access, offset);
+
+ offset += 4; /* skip last 4 UNUSED bytes */
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_share_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 request_type;
+
+ request_type = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ proto_tree_add_uint(tree, hf_hclnfsd_request_type, tvb, offset,
+ 4, request_type);
+ offset += 4;
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_cookie, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_status, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_sequence, offset);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_unshare_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_hclnfsd_share_call(tvb, offset, pinfo, tree);
+}
+
+
+static int
+dissect_hclnfsd_unshare_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_hclnfsd_share_reply(tvb, offset, pinfo, tree);
+}
+
+
+static int
+dissect_hclnfsd_lock_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_status, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_cookie, offset);
+ offset += 4; /* skip unused uint */
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_exclusive, offset);
+
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_lockname, offset, NULL);
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "Filehandle", NULL);
+
+ offset = dissect_rpc_data(tvb, tree, hf_hclnfsd_lockowner, offset);
+
+ offset += 4; /* unused, skip */
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_offset, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_length, offset);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_lock_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint request_type;
+
+ request_type = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ proto_tree_add_uint(tree, hf_hclnfsd_request_type, tvb, offset,
+ 4, request_type);
+ offset += 4;
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_cookie, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_status, offset);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_lockname, offset, NULL);
+
+ offset += 4; /* skip unused */
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_unlock_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset += 4; /* skip unused */
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_cookie, offset);
+
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_lockname, offset, NULL);
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "Filehandle", NULL);
+
+ offset = dissect_rpc_data(tvb, tree, hf_hclnfsd_unknown_data, offset);
+
+ offset += 4; /* skip unused */
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_offset, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_length, offset);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_unlock_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_hclnfsd_lock_reply(tvb, offset, pinfo, tree);
+}
+
+
+static int
+dissect_hclnfsd_get_printers_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint nqueues, nqueues_i;
+ proto_item *queuesitem = NULL;
+ proto_tree *queuestree = NULL;
+
+ nqueues = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ {
+ queuesitem = proto_tree_add_text(tree, tvb, offset, 4,
+ "Print Queues: %d", nqueues);
+
+ if (queuesitem)
+ queuestree = proto_item_add_subtree(queuesitem,
+ ett_hclnfsd_printqueues);
+ }
+ offset += 4;
+
+ if (!queuestree)
+ return offset;
+
+ for (nqueues_i = 0; nqueues_i < nqueues; nqueues_i++)
+ {
+ /* create new item for print queue */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_hclnfsd_queuename, offset, NULL);
+
+ /* create subtree on new item with print queue comment */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_hclnfsd_queuecomment, offset, NULL);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_get_printq_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_queuename, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_username, offset, NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_hclnfsd_get_printq_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint datafollows, jobid;
+ proto_item *queueitem = NULL;
+ proto_tree *queuetree = NULL;
+ proto_item *jobitem;
+ proto_tree *jobtree;
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_printqueuenumber, offset);
+
+ offset = dissect_rpc_string(tvb, tree, hf_hclnfsd_queuecomment, offset, NULL);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_queuestatus, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_numphysicalprinters, offset);
+
+ datafollows = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ {
+ queueitem = proto_tree_add_text(tree, tvb, offset, 4,
+ "Print Jobs: %d", datafollows);
+ if (queueitem)
+ queuetree = proto_item_add_subtree(queueitem, ett_hclnfsd_printqueues);
+ }
+ offset += 4;
+
+ if (!queuetree)
+ return offset;
+
+ while (datafollows)
+ {
+ jobid = tvb_get_ntohl(tvb, offset);
+ jobitem = proto_tree_add_text(queuetree, tvb, offset, 4, "Job ID: %d",
+ jobid);
+ offset += 4;
+
+ jobtree = proto_item_add_subtree(jobitem, ett_hclnfsd_printjob);
+
+ offset = dissect_rpc_string(tvb, tree,
+ hf_hclnfsd_username, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, tree,
+ hf_hclnfsd_printparams, offset, NULL);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_queuestatus, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_jobstatus, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_timesubmitted, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_size, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_hclnfsd_copies, offset);
+ offset = dissect_rpc_string(tvb, tree,
+ hf_hclnfsd_queuecomment, offset, NULL);
+
+ datafollows = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ }
+
+ return offset;
+}
+
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: take the generic one. */
+
+static const vsff hclnfsd1_proc[] = {
+ { HCLNFSDPROC_NULL, "NULL",
+ NULL, NULL },
+ { HCLNFSDPROC_SPOOL_INQUIRE, "SPOOL_INQUIRE",
+ dissect_hclnfsd_spool_inquire_call, NULL },
+ { HCLNFSDPROC_SPOOL_FILE, "SPOOL_FILE",
+ dissect_hclnfsd_spool_file_call, NULL },
+ { HCLNFSDPROC_AUTHORIZE, "AUTHORIZE",
+ dissect_hclnfsd_authorize_call, dissect_hclnfsd_authorize_reply },
+ { HCLNFSDPROC_GRP_NAME_TO_NUMB, "GRP_NAME_TO_NUMB",
+ dissect_hclnfsd_grp_name_to_numb_call, dissect_hclnfsd_grp_name_to_numb_reply },
+ { HCLNFSDPROC_GRP_TO_NUMBER, "GRP_TO_NUMBER",
+ dissect_hclnfsd_grp_to_number_call, dissect_hclnfsd_grp_to_number_reply },
+ { HCLNFSDPROC_RETURN_HOST, "RETURN_HOST",
+ dissect_hclnfsd_return_host_call, dissect_hclnfsd_return_host_reply },
+ { HCLNFSDPROC_UID_TO_NAME, "UID_TO_NAME",
+ dissect_hclnfsd_uid_to_name_call, dissect_hclnfsd_uid_to_name_reply },
+ { HCLNFSDPROC_NAME_TO_UID, "NAME_TO_UID",
+ dissect_hclnfsd_name_to_uid_call, dissect_hclnfsd_name_to_uid_reply },
+ { HCLNFSDPROC_SHARE, "SHARE",
+ dissect_hclnfsd_share_call, dissect_hclnfsd_share_reply },
+ { HCLNFSDPROC_UNSHARE, "UNSHARE",
+ dissect_hclnfsd_unshare_call, dissect_hclnfsd_unshare_reply },
+ { HCLNFSDPROC_LOCK, "LOCK",
+ dissect_hclnfsd_lock_call, dissect_hclnfsd_lock_reply },
+ { HCLNFSDPROC_REMOVE, "REMOVE",
+ dissect_hclnfsd_remove_call, NULL },
+ { HCLNFSDPROC_UNLOCK, "UNLOCK",
+ dissect_hclnfsd_unlock_call, dissect_hclnfsd_unlock_reply },
+ { HCLNFSDPROC_GET_PRINTERS, "GET_PRINTERS",
+ NULL, dissect_hclnfsd_get_printers_reply },
+ { HCLNFSDPROC_GET_PRINTQ, "GET_PRINTQ",
+ dissect_hclnfsd_get_printq_call, dissect_hclnfsd_get_printq_reply },
+ { HCLNFSDPROC_CANCEL_PRJOB, "CANCEL_PRJOB",
+ NULL, NULL },
+ { HCLNFSDPROC_ZAP_LOCKS, "ZAP_LOCKS",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string hclnfsd1_proc_vals[] = {
+ { HCLNFSDPROC_NULL, "NULL" },
+ { HCLNFSDPROC_SPOOL_INQUIRE, "SPOOL_INQUIRE" },
+ { HCLNFSDPROC_SPOOL_FILE, "SPOOL_FILE" },
+ { HCLNFSDPROC_AUTHORIZE, "AUTHORIZE" },
+ { HCLNFSDPROC_GRP_NAME_TO_NUMB, "GRP_NAME_TO_NUMB" },
+ { HCLNFSDPROC_GRP_TO_NUMBER, "GRP_TO_NUMBER" },
+ { HCLNFSDPROC_RETURN_HOST, "RETURN_HOST" },
+ { HCLNFSDPROC_UID_TO_NAME, "UID_TO_NAME" },
+ { HCLNFSDPROC_NAME_TO_UID, "NAME_TO_UID" },
+ { HCLNFSDPROC_SHARE, "SHARE" },
+ { HCLNFSDPROC_UNSHARE, "UNSHARE" },
+ { HCLNFSDPROC_LOCK, "LOCK" },
+ { HCLNFSDPROC_REMOVE, "REMOVE" },
+ { HCLNFSDPROC_UNLOCK, "UNLOCK" },
+ { HCLNFSDPROC_GET_PRINTERS, "GET_PRINTERS" },
+ { HCLNFSDPROC_GET_PRINTQ, "GET_PRINTQ" },
+ { HCLNFSDPROC_CANCEL_PRJOB, "CANCEL_PRJOB" },
+ { HCLNFSDPROC_ZAP_LOCKS, "ZAP_LOCKS" },
+ { 0, NULL }
+};
+/* end of hclnfsd version 1 */
+
+
+void
+proto_register_hclnfsd(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_hclnfsd_procedure_v1, {
+ "V1 Procedure", "hclnfsd.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(hclnfsd1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_hclnfsd_request_type, {
+ "Request Type", "hclnfsd.request_type", FT_UINT32, BASE_DEC,
+ VALS(names_request_type), 0, "Request Type", HFILL }},
+
+ { &hf_hclnfsd_device, {
+ "Device", "hclnfsd.device", FT_STRING, BASE_DEC,
+ NULL, 0, "Device", HFILL }},
+
+ { &hf_hclnfsd_login, {
+ "Login Text", "hclnfsd.logintext", FT_STRING, BASE_DEC,
+ NULL, 0, "Login Text", HFILL }},
+
+ { &hf_hclnfsd_lockname, {
+ "Lockname", "hclnfsd.lockname", FT_STRING, BASE_DEC,
+ NULL, 0, "Lockname", HFILL }},
+
+ { &hf_hclnfsd_unknown_data, {
+ "Unknown", "hclnfsd.unknown_data", FT_BYTES, BASE_DEC,
+ NULL, 0, "Data", HFILL }},
+
+ { &hf_hclnfsd_lockowner, {
+ "Lockowner", "hclnfsd.lockowner", FT_BYTES, BASE_DEC,
+ NULL, 0, "Lockowner", HFILL }},
+
+ { &hf_hclnfsd_printername, {
+ "Printer Name", "hclnfsd.printername", FT_STRING, BASE_DEC,
+ NULL, 0, "Printer name", HFILL }},
+
+ { &hf_hclnfsd_filename, {
+ "Filename", "hclnfsd.filename", FT_STRING, BASE_DEC,
+ NULL, 0, "Filename", HFILL }},
+
+ { &hf_hclnfsd_fileext, {
+ "File Extension", "hclnfsd.fileext", FT_UINT32, BASE_DEC,
+ NULL, 0, "File Extension", HFILL }},
+
+ { &hf_hclnfsd_grpname, {
+ "Group", "hclnfsd.group", FT_STRING, BASE_DEC,
+ NULL, 0, "Group", HFILL }},
+
+ { &hf_hclnfsd_hostname, {
+ "Hostname", "hclnfsd.hostname", FT_STRING, BASE_DEC,
+ NULL, 0, "Hostname", HFILL }},
+
+ { &hf_hclnfsd_username, {
+ "Username", "hclnfsd.username", FT_STRING, BASE_DEC,
+ NULL, 0, "Username", HFILL }},
+
+ { &hf_hclnfsd_queuename, {
+ "Name", "hclnfsd.printqueuename", FT_STRING, BASE_DEC,
+ NULL, 0, "Print Queue Name", HFILL }},
+
+ { &hf_hclnfsd_queuecomment, {
+ "Comment", "hclnfsd.printqueuecomment", FT_STRING, BASE_DEC,
+ NULL, 0, "Print Queue Comment", HFILL }},
+
+ { &hf_hclnfsd_printparams, {
+ "Print Parameters", "hclnfsd.printparameters", FT_STRING, BASE_DEC,
+ NULL, 0, "Print Parameters", HFILL }},
+
+ { &hf_hclnfsd_status, {
+ "Status", "hclnfsd.status", FT_UINT32, BASE_DEC,
+ NULL, 0, "Status", HFILL }},
+
+ { &hf_hclnfsd_uid, {
+ "UID", "hclnfsd.uid", FT_UINT32, BASE_DEC,
+ NULL, 0, "User ID", HFILL }},
+
+ { &hf_hclnfsd_sequence, {
+ "Sequence", "hclnfsd.sequence", FT_UINT32, BASE_HEX,
+ NULL, 0, "Sequence", HFILL }},
+
+ { &hf_hclnfsd_cookie, {
+ "Cookie", "hclnfsd.cookie", FT_UINT32, BASE_HEX,
+ NULL, 0, "Cookie", HFILL }},
+
+ { &hf_hclnfsd_mode, {
+ "Mode", "hclnfsd.mode", FT_UINT32, BASE_DEC,
+ NULL, 0, "Mode", HFILL }},
+
+ { &hf_hclnfsd_access, {
+ "Access", "hclnfsd.access", FT_UINT32, BASE_DEC,
+ NULL, 0, "Access", HFILL }},
+
+ { &hf_hclnfsd_exclusive, {
+ "Exclusive", "hclnfsd.exclusive", FT_UINT32, BASE_DEC,
+ NULL, 0, "Exclusive", HFILL }},
+
+ { &hf_hclnfsd_offset, {
+ "Offset", "hclnfsd.offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Offset", HFILL }},
+
+ { &hf_hclnfsd_length, {
+ "Length", "hclnfsd.length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length", HFILL }},
+
+ { &hf_hclnfsd_queuestatus, {
+ "Queue Status", "hclnfsd.queuestatus", FT_UINT32, BASE_DEC,
+ NULL, 0, "Queue Status", HFILL }},
+
+ { &hf_hclnfsd_printqueuenumber, {
+ "Print Queue Number", "hclnfsd.pqn", FT_UINT32, BASE_DEC,
+ NULL, 0, "Print Queue Number", HFILL }},
+
+ { &hf_hclnfsd_numphysicalprinters, {
+ "Number of Physical Printers", "hclnfsd.npp", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of Physical Printers", HFILL }},
+
+ { &hf_hclnfsd_jobstatus, {
+ "Job Status", "hclnfsd.jobstatus", FT_UINT32, BASE_DEC,
+ NULL, 0, "Job Status", HFILL }},
+
+ { &hf_hclnfsd_timesubmitted, {
+ "Time Submitted", "hclnfsd.timesubmitted", FT_UINT32, BASE_DEC,
+ NULL, 0, "Time Submitted", HFILL }},
+
+ { &hf_hclnfsd_size, {
+ "Size", "hclnfsd.size", FT_UINT32, BASE_DEC,
+ NULL, 0, "Size", HFILL }},
+
+ { &hf_hclnfsd_copies, {
+ "Copies", "hclnfsd.copies", FT_UINT32, BASE_DEC,
+ NULL, 0, "Copies", HFILL }},
+
+ { &hf_hclnfsd_gid, {
+ "GID", "hclnfsd.gid", FT_UINT32, BASE_DEC,
+ NULL, 0, "Group ID", HFILL }},
+
+ { &hf_hclnfsd_server_ip, {
+ "Server IP", "hclnfsd.server_ip", FT_IPv4, BASE_DEC,
+ NULL, 0, "Server IP", HFILL }},
+
+ { &hf_hclnfsd_host_ip, {
+ "Host IP", "hclnfsd.host_ip", FT_IPv4, BASE_DEC,
+ NULL, 0, "Host IP", HFILL }},
+
+ { &hf_hclnfsd_auth_ident_obscure, {
+ "Obscure Ident", "hclnfsd.authorize.ident.obscure", FT_STRING,
+ BASE_DEC , NULL, 0, "Authentication Obscure Ident", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_hclnfsd,
+ &ett_hclnfsd_gids,
+ &ett_hclnfsd_groups,
+ &ett_hclnfsd_uids,
+ &ett_hclnfsd_usernames,
+ &ett_hclnfsd_printqueues,
+ &ett_hclnfsd_printjob,
+ &ett_hclnfsd_auth_ident
+ };
+
+ proto_hclnfsd = proto_register_protocol("Hummingbird NFS Daemon",
+ "HCLNFSD", "hclnfsd");
+ proto_register_field_array(proto_hclnfsd, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_hclnfsd(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_hclnfsd, HCLNFSD_PROGRAM, ett_hclnfsd);
+
+ /* Register the procedure tables */
+ rpc_init_proc_table(HCLNFSD_PROGRAM, 1, hclnfsd1_proc, hf_hclnfsd_procedure_v1);
+}
diff --git a/epan/dissectors/packet-hclnfsd.h b/epan/dissectors/packet-hclnfsd.h
new file mode 100644
index 0000000000..e42392722c
--- /dev/null
+++ b/epan/dissectors/packet-hclnfsd.h
@@ -0,0 +1,48 @@
+/* packet-hclnfsd.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_HCLNFSD_H
+#define PACKET_HCLNFSD_H
+
+#define HCLNFSD_PROGRAM 0x2f00dbad
+
+#define HCLNFSDPROC_NULL 0
+#define HCLNFSDPROC_SPOOL_INQUIRE 1
+#define HCLNFSDPROC_SPOOL_FILE 2
+#define HCLNFSDPROC_AUTHORIZE 3
+#define HCLNFSDPROC_GRP_NAME_TO_NUMB 4
+#define HCLNFSDPROC_GRP_TO_NUMBER 5
+#define HCLNFSDPROC_RETURN_HOST 6
+#define HCLNFSDPROC_UID_TO_NAME 7
+#define HCLNFSDPROC_NAME_TO_UID 8
+#define HCLNFSDPROC_SHARE 20
+#define HCLNFSDPROC_UNSHARE 21
+#define HCLNFSDPROC_LOCK 22
+#define HCLNFSDPROC_REMOVE 23
+#define HCLNFSDPROC_UNLOCK 24
+#define HCLNFSDPROC_GET_PRINTERS 30
+#define HCLNFSDPROC_GET_PRINTQ 31
+#define HCLNFSDPROC_CANCEL_PRJOB 32
+#define HCLNFSDPROC_ZAP_LOCKS 105
+
+#endif
diff --git a/epan/dissectors/packet-hpext.c b/epan/dissectors/packet-hpext.c
new file mode 100644
index 0000000000..3a14dbb9c3
--- /dev/null
+++ b/epan/dissectors/packet-hpext.c
@@ -0,0 +1,132 @@
+/* packet-hpext.c
+ * Routines for HP extended IEEE 802.2 LLC layer
+ * Jochen Friedrich <jochen@scram.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "xdlc.h"
+#include "etypes.h"
+#include "llcsaps.h"
+#include "packet-hpext.h"
+
+static dissector_table_t subdissector_table;
+
+static dissector_handle_t data_handle;
+
+static int proto_hpext = -1;
+
+static int hf_hpext_dxsap = -1;
+static int hf_hpext_sxsap = -1;
+
+static gint ett_hpext = -1;
+
+const value_string xsap_vals[] = {
+ { HPEXT_DXSAP, "RBOOT Destination Service Access Point" },
+ { HPEXT_SXSAP, "RBOOT Source Service Access Point" },
+ { HPEXT_SNMP, "SNMP" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_hpext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *hpext_tree = NULL;
+ proto_item *ti = NULL;
+ guint16 dxsap, sxsap;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "HPEXT");
+ }
+
+ dxsap = tvb_get_ntohs(tvb, 3);
+ sxsap = tvb_get_ntohs(tvb, 5);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_hpext, tvb, 0, 7, FALSE);
+ hpext_tree = proto_item_add_subtree(ti, ett_hpext);
+ proto_tree_add_text(hpext_tree, tvb, 0, 3, "Reserved");
+ proto_tree_add_uint(hpext_tree, hf_hpext_dxsap, tvb, 3,
+ 2, dxsap);
+ proto_tree_add_uint(hpext_tree, hf_hpext_sxsap, tvb, 5,
+ 2, sxsap);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "; HPEXT; DXSAP %s, SXSAP %s",
+ val_to_str(dxsap, xsap_vals, "%04x"),
+ val_to_str(sxsap, xsap_vals, "%04x"));
+
+ if (tvb_length_remaining(tvb, 7) > 0) {
+ next_tvb = tvb_new_subset(tvb, 7, -1, -1);
+ if (!dissector_try_port(subdissector_table,
+ dxsap, next_tvb, pinfo, tree)) {
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ }
+}
+
+void
+proto_register_hpext(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_hpext_dxsap,
+ { "DXSAP", "hpext.dxsap", FT_UINT16, BASE_HEX,
+ VALS(xsap_vals), 0x0, "", HFILL }},
+
+ { &hf_hpext_sxsap,
+ { "SXSAP", "hpext.sxsap", FT_UINT16, BASE_HEX,
+ VALS(xsap_vals), 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_hpext,
+ };
+
+ proto_hpext = proto_register_protocol(
+ "HP Extended Local-Link Control", "HPEXT", "hpext");
+ proto_register_field_array(proto_hpext, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+/* subdissector code */
+ subdissector_table = register_dissector_table("hpext.dxsap",
+ "HPEXT XSAP", FT_UINT16, BASE_HEX);
+
+ register_dissector("hpext", dissect_hpext, proto_hpext);
+}
+
+void
+proto_reg_handoff_hpext(void)
+{
+ dissector_handle_t hpext_handle;
+
+ data_handle = find_dissector("data");
+
+ hpext_handle = find_dissector("hpext");
+ dissector_add("llc.dsap", SAP_HPEXT, hpext_handle);
+}
diff --git a/epan/dissectors/packet-hpext.h b/epan/dissectors/packet-hpext.h
new file mode 100644
index 0000000000..ec7e148ca2
--- /dev/null
+++ b/epan/dissectors/packet-hpext.h
@@ -0,0 +1,28 @@
+/* packet-hpext.h
+ * Routines for HP extended IEEE 802.2 LLC layer
+ * Jochen Friedrich <jochen@scram.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define HPEXT_DXSAP 0x608
+#define HPEXT_SXSAP 0x609
+#define HPEXT_SNMP 0x165A
diff --git a/epan/dissectors/packet-hsrp.c b/epan/dissectors/packet-hsrp.c
new file mode 100644
index 0000000000..62f20e1f8b
--- /dev/null
+++ b/epan/dissectors/packet-hsrp.c
@@ -0,0 +1,239 @@
+/* packet-hsrp.c
+ * Routines for the Cisco Hot Standby Router Protocol (HSRP)
+ * RFC 2281
+ *
+ * Heikki Vatiainen <hessu@cs.tut.fi>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-vrrp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+static gint proto_hsrp = -1;
+
+static gint hf_hsrp_version = -1;
+static gint hf_hsrp_opcode = -1;
+static gint hf_hsrp_state = -1;
+static gint hf_hsrp_hellotime = -1;
+static gint hf_hsrp_holdtime = -1;
+static gint hf_hsrp_priority = -1;
+static gint hf_hsrp_group = -1;
+static gint hf_hsrp_reserved = -1;
+static gint hf_hsrp_auth_data = -1;
+static gint hf_hsrp_virt_ip_addr = -1;
+
+static gint ett_hsrp = -1;
+
+#define UDP_PORT_HSRP 1985
+
+struct hsrp_packet { /* Multicast to 224.0.0.2, TTL 1, UDP, port 1985 */
+ guint8 version; /* RFC2281 describes version 0 */
+ guint8 opcode;
+ guint8 state;
+#define HSRP_DEFAULT_HELLOTIME 3
+ guint8 hellotime; /* In seconds */
+#define HSRP_DEFAULT_HOLDTIME 10
+ guint8 holdtime; /* In seconds */
+ guint8 priority; /* Higher is stronger, highest IP address tie-breaker */
+ guint8 group; /* Identifies the standby group */
+ guint8 reserved;
+ guint8 auth_data[8]; /* Clear-text password, recommended default is `cisco' */
+ guint32 virt_ip_addr; /* The virtual IP address used by this group */
+};
+
+
+#define HSRP_OPCODE_HELLO 0
+#define HSRP_OPCODE_COUP 1
+#define HSRP_OPCODE_RESIGN 2
+static const value_string hsrp_opcode_vals[] = {
+ {HSRP_OPCODE_HELLO, "Hello"},
+ {HSRP_OPCODE_COUP, "Coup"},
+ {HSRP_OPCODE_RESIGN, "Resign"},
+ {0, NULL},
+};
+
+#define HSRP_STATE_INITIAL 0
+#define HSRP_STATE_LEARN 1
+#define HSRP_STATE_LISTEN 2
+#define HSRP_STATE_SPEAK 4
+#define HSRP_STATE_STANDBY 8
+#define HSRP_STATE_ACTIVE 16
+static const value_string hsrp_state_vals[] = {
+ {HSRP_STATE_INITIAL, "Initial"},
+ {HSRP_STATE_LEARN, "Learn"},
+ {HSRP_STATE_LISTEN, "Listen"},
+ {HSRP_STATE_SPEAK, "Speak"},
+ {HSRP_STATE_STANDBY, "Standby"},
+ {HSRP_STATE_ACTIVE, "Active"},
+ {0, NULL},
+};
+
+static void
+dissect_hsrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 opcode, state;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "HSRP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ opcode = tvb_get_guint8(tvb, 1);
+ state = tvb_get_guint8(tvb, 2);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (state %s)",
+ val_to_str(opcode, hsrp_opcode_vals, "Unknown"),
+ val_to_str(state, hsrp_state_vals, "Unknown"));
+ }
+
+ if (tree) {
+ proto_item *ti;
+ proto_tree *hsrp_tree;
+ int offset;
+ guint8 hellotime, holdtime;
+ guint8 auth_buf[8 + 1];
+
+ offset = 0;
+ ti = proto_tree_add_item(tree, proto_hsrp, tvb, offset, -1, FALSE);
+ hsrp_tree = proto_item_add_subtree(ti, ett_hsrp);
+
+ proto_tree_add_item(hsrp_tree, hf_hsrp_version, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_uint(hsrp_tree, hf_hsrp_opcode, tvb, offset, 1, opcode);
+ offset++;
+ proto_tree_add_uint(hsrp_tree, hf_hsrp_state, tvb, offset, 1, state);
+ offset++;
+ hellotime = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(hsrp_tree, hf_hsrp_hellotime, tvb, offset, 1, hellotime,
+ "Hellotime: %sDefault (%u)",
+ (hellotime == HSRP_DEFAULT_HELLOTIME) ? "" : "Non-",
+ hellotime);
+ offset++;
+ holdtime = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(hsrp_tree, hf_hsrp_holdtime, tvb, offset, 1, holdtime,
+ "Holdtime: %sDefault (%u)",
+ (holdtime == HSRP_DEFAULT_HOLDTIME) ? "" : "Non-",
+ holdtime);
+ offset++;
+ proto_tree_add_item(hsrp_tree, hf_hsrp_priority, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(hsrp_tree, hf_hsrp_group, tvb, offset, 1, FALSE);
+ offset++;
+ proto_tree_add_item(hsrp_tree, hf_hsrp_reserved, tvb, offset, 1, FALSE);
+ offset++;
+ tvb_memcpy(tvb, auth_buf, offset, 8);
+ auth_buf[sizeof auth_buf - 1] = '\0';
+ proto_tree_add_string_format(hsrp_tree, hf_hsrp_auth_data, tvb, offset, 8, auth_buf,
+ "Authentication Data: %sDefault (%s)",
+ (tvb_strneql(tvb, offset, "cisco", strlen("cisco"))) == 0 ? "" : "Non-",
+ auth_buf);
+ offset += 8;
+ proto_tree_add_item(hsrp_tree, hf_hsrp_virt_ip_addr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ }
+
+ return;
+}
+
+void proto_register_hsrp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_hsrp_version,
+ { "Version", "hsrp.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The version of the HSRP messages", HFILL }},
+
+ { &hf_hsrp_opcode,
+ { "Op Code", "hsrp.opcode",
+ FT_UINT8, BASE_DEC, VALS(hsrp_opcode_vals), 0x0,
+ "The type of message contained in this packet", HFILL }},
+
+ { &hf_hsrp_state,
+ { "State", "hsrp.state",
+ FT_UINT8, BASE_DEC, VALS(hsrp_state_vals), 0x0,
+ "The current state of the router sending the message", HFILL }},
+
+ { &hf_hsrp_hellotime,
+ { "Hellotime", "hsrp.hellotime",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The approximate period between the Hello messages that the router sends", HFILL }},
+
+ { &hf_hsrp_holdtime,
+ { "Holdtime", "hsrp.holdtime",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Time that the current Hello message should be considered valid", HFILL }},
+
+ { &hf_hsrp_priority,
+ { "Priority", "hsrp.priority",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Used to elect the active and standby routers. Numerically higher priority wins vote", HFILL }},
+
+ { &hf_hsrp_group,
+ { "Group", "hsrp.group",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "This field identifies the standby group", HFILL }},
+
+ { &hf_hsrp_reserved,
+ { "Reserved", "hsrp.reserved",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Reserved", HFILL }},
+
+ { &hf_hsrp_auth_data,
+ { "Authentication Data", "hsrp.auth_data",
+ FT_STRING, 0, NULL, 0x0,
+ "Contains a clear-text 8 character reused password", HFILL }},
+
+ { &hf_hsrp_virt_ip_addr,
+ { "Virtual IP Address", "hsrp.virt_ip",
+ FT_IPv4, 0, NULL, 0x0,
+ "The virtual IP address used by this group", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_hsrp,
+ };
+
+ proto_hsrp = proto_register_protocol("Cisco Hot Standby Router Protocol",
+ "HSRP", "hsrp");
+ proto_register_field_array(proto_hsrp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ return;
+}
+
+void
+proto_reg_handoff_hsrp(void)
+{
+ dissector_handle_t hsrp_handle;
+
+ hsrp_handle = create_dissector_handle(dissect_hsrp, proto_hsrp);
+ dissector_add("udp.port", UDP_PORT_HSRP, hsrp_handle);
+}
diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c
new file mode 100644
index 0000000000..76f70e289f
--- /dev/null
+++ b/epan/dissectors/packet-http.c
@@ -0,0 +1,1759 @@
+/* packet-http.c
+ * Routines for HTTP packet disassembly
+ * RFC 1945 (HTTP/1.0)
+ * RFC 2616 (HTTP/1.1)
+ *
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * Copyright 2004, Jerry Talkington <jtalkington@users.sourceforge.net>
+ * Copyright 2002, Tim Potter <tpot@samba.org>
+ * Copyright 1999, Andrew Tridgell <tridge@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "util.h"
+#include "req_resp_hdrs.h"
+#include "packet-http.h"
+#include "prefs.h"
+
+typedef enum _http_type {
+ HTTP_REQUEST,
+ HTTP_RESPONSE,
+ HTTP_NOTIFICATION,
+ HTTP_OTHERS
+} http_type_t;
+
+#include "tap.h"
+
+static int http_tap = -1;
+
+static int proto_http = -1;
+static int hf_http_notification = -1;
+static int hf_http_response = -1;
+static int hf_http_request = -1;
+static int hf_http_basic = -1;
+static int hf_http_request_method = -1;
+static int hf_http_response_code = -1;
+static int hf_http_authorization = -1;
+static int hf_http_proxy_authenticate = -1;
+static int hf_http_proxy_authorization = -1;
+static int hf_http_www_authenticate = -1;
+static int hf_http_content_type = -1;
+static int hf_http_content_length = -1;
+static int hf_http_content_encoding = -1;
+static int hf_http_transfer_encoding = -1;
+
+static gint ett_http = -1;
+static gint ett_http_ntlmssp = -1;
+static gint ett_http_request = -1;
+static gint ett_http_chunked_response = -1;
+static gint ett_http_chunk_data = -1;
+static gint ett_http_encoded_entity = -1;
+
+static dissector_handle_t data_handle;
+static dissector_handle_t media_handle;
+static dissector_handle_t http_handle;
+
+/*
+ * desegmentation of HTTP headers
+ * (when we are over TCP or another protocol providing the desegmentation API)
+ */
+static gboolean http_desegment_headers = FALSE;
+
+/*
+ * desegmentation of HTTP bodies
+ * (when we are over TCP or another protocol providing the desegmentation API)
+ * TODO let the user filter on content-type the bodies he wants desegmented
+ */
+static gboolean http_desegment_body = FALSE;
+
+/*
+ * De-chunking of content-encoding: chunk entity bodies.
+ */
+static gboolean http_dechunk_body = TRUE;
+
+/*
+ * Decompression of zlib encoded entities.
+ */
+#ifdef HAVE_LIBZ
+static gboolean http_decompress_body = TRUE;
+#else
+static gboolean http_decompress_body = FALSE;
+#endif
+
+
+#define TCP_PORT_HTTP 80
+#define TCP_PORT_PROXY_HTTP 3128
+#define TCP_PORT_PROXY_ADMIN_HTTP 3132
+#define TCP_ALT_PORT_HTTP 8080
+#define TCP_PORT_HKP 11371
+/*
+ * SSDP is implemented atop HTTP (yes, it really *does* run over UDP).
+ */
+#define TCP_PORT_SSDP 1900
+#define UDP_PORT_SSDP 1900
+
+/*
+ * Protocols implemented atop HTTP.
+ */
+typedef enum {
+ PROTO_HTTP, /* just HTTP */
+ PROTO_SSDP /* Simple Service Discovery Protocol */
+} http_proto_t;
+
+typedef void (*RequestDissector)(tvbuff_t*, proto_tree*, int);
+
+/*
+ * Structure holding information from headers needed by main
+ * HTTP dissector code.
+ */
+typedef struct {
+ char *content_type;
+ char *content_type_parameters;
+ long content_length; /* XXX - make it 64-bit? */
+ char *content_encoding;
+ char *transfer_encoding;
+} headers_t;
+
+static int is_http_request_or_reply(const gchar *data, int linelen, http_type_t *type,
+ RequestDissector *req_dissector, int *req_strlen);
+static int chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
+ proto_tree *tree, int offset);
+static void process_header(tvbuff_t *tvb, int offset, int next_offset,
+ const guchar *line, int linelen, int colon_offset, packet_info *pinfo,
+ proto_tree *tree, headers_t *eh_ptr);
+static gint find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len);
+static gboolean check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb,
+ packet_info *pinfo, gchar *value);
+static gboolean check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb,
+ gchar *value);
+
+static dissector_table_t port_subdissector_table;
+static dissector_table_t media_type_subdissector_table;
+static heur_dissector_list_t heur_subdissector_list;
+
+static dissector_handle_t ntlmssp_handle=NULL;
+
+
+/* Return a tvb that contains the binary representation of a base64
+ string */
+
+static tvbuff_t *
+base64_to_tvb(const char *base64)
+{
+ tvbuff_t *tvb;
+ char *data = g_strdup(base64);
+ size_t len;
+
+ len = epan_base64_decode(data);
+ tvb = tvb_new_real_data((const guint8 *)data, len, len);
+
+ tvb_set_free_cb(tvb, g_free);
+
+ return tvb;
+}
+
+static void
+dissect_http_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const char *line)
+{
+ tvbuff_t *ntlmssp_tvb;
+
+ ntlmssp_tvb = base64_to_tvb(line);
+ tvb_set_child_real_data_tvbuff(tvb, ntlmssp_tvb);
+ add_new_data_source(pinfo, ntlmssp_tvb, "NTLMSSP Data");
+
+ call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, tree);
+}
+
+static void
+cleanup_headers(void *arg)
+{
+ headers_t *headers = arg;
+
+ if (headers->content_type != NULL)
+ g_free(headers->content_type);
+ /*
+ * The content_type_parameters field actually points into the
+ * content_type headers, so don't free it, as that'll double-free
+ * some memory.
+ */
+ if (headers->content_encoding != NULL)
+ g_free(headers->content_encoding);
+ if (headers->transfer_encoding != NULL)
+ g_free(headers->transfer_encoding);
+}
+
+/*
+ * TODO: remove this ugly global variable.
+ *
+ * XXX - we leak "http_info_value_t" structures.
+ * XXX - this gets overwritten if there's more than one HTTP request or
+ * reply in the tvbuff.
+ */
+static http_info_value_t *stat_info;
+
+static int
+dissect_http_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ http_proto_t proto;
+ char *proto_tag;
+ proto_tree *http_tree = NULL;
+ proto_item *ti = NULL;
+ const guchar *line;
+ gint next_offset;
+ const guchar *linep, *lineend;
+ int orig_offset;
+ int first_linelen, linelen;
+ gboolean is_request_or_reply;
+ gboolean saw_req_resp_or_header;
+ guchar c;
+ http_type_t http_type;
+ proto_item *hdr_item;
+ RequestDissector req_dissector;
+ int req_strlen;
+ proto_tree *req_tree;
+ int colon_offset;
+ headers_t headers;
+ int datalen;
+ int reported_datalen;
+ dissector_handle_t handle;
+ gboolean dissected;
+
+ /*
+ * Is this a request or response?
+ *
+ * Note that "tvb_find_line_end()" will return a value that
+ * is not longer than what's in the buffer, so the
+ * "tvb_get_ptr()" call won't throw an exception.
+ */
+ first_linelen = tvb_find_line_end(tvb, offset,
+ tvb_ensure_length_remaining(tvb, offset), &next_offset,
+ FALSE);
+ /*
+ * Is the first line a request or response?
+ */
+ line = tvb_get_ptr(tvb, offset, first_linelen);
+ http_type = HTTP_OTHERS; /* type not known yet */
+ is_request_or_reply = is_http_request_or_reply((const gchar *)line,
+ first_linelen, &http_type, NULL, NULL);
+ if (is_request_or_reply) {
+ /*
+ * Yes, it's a request or response.
+ * Do header desegmentation if we've been told to,
+ * and do body desegmentation if we've been told to and
+ * we find a Content-Length header.
+ */
+ if (!req_resp_hdrs_do_reassembly(tvb, pinfo,
+ http_desegment_headers, http_desegment_body)) {
+ /*
+ * More data needed for desegmentation.
+ */
+ return -1;
+ }
+ }
+
+ stat_info = g_malloc(sizeof(http_info_value_t));
+ stat_info->response_code = 0;
+ stat_info->request_method = NULL;
+
+ switch (pinfo->match_port) {
+
+ case TCP_PORT_SSDP: /* TCP_PORT_SSDP = UDP_PORT_SSDP */
+ proto = PROTO_SSDP;
+ proto_tag = "SSDP";
+ break;
+
+ default:
+ proto = PROTO_HTTP;
+ proto_tag = "HTTP";
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary
+ * if it's an HTTP request or reply (but leave out the
+ * line terminator).
+ * Otherwise, just call it a continuation.
+ *
+ * Note that "tvb_find_line_end()" will return a value that
+ * is not longer than what's in the buffer, so the
+ * "tvb_get_ptr()" call won't throw an exception.
+ */
+ line = tvb_get_ptr(tvb, offset, first_linelen);
+ if (is_request_or_reply)
+ col_add_str(pinfo->cinfo, COL_INFO,
+ format_text(line, first_linelen));
+ else
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+ }
+
+ orig_offset = offset;
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_http, tvb, offset, -1,
+ FALSE);
+ http_tree = proto_item_add_subtree(ti, ett_http);
+ }
+
+ /*
+ * Process the packet data, a line at a time.
+ */
+ http_type = HTTP_OTHERS; /* type not known yet */
+ headers.content_type = NULL; /* content type not known yet */
+ headers.content_type_parameters = NULL; /* content type parameters too */
+ headers.content_length = -1; /* content length not known yet */
+ headers.content_encoding = NULL; /* content encoding not known yet */
+ headers.transfer_encoding = NULL; /* transfer encoding not known yet */
+ saw_req_resp_or_header = FALSE; /* haven't seen anything yet */
+ CLEANUP_PUSH(cleanup_headers, &headers);
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset,
+ tvb_ensure_length_remaining(tvb, offset), &next_offset,
+ FALSE);
+ if (linelen < 0)
+ return -1;
+
+ /*
+ * Get a buffer that refers to the line.
+ */
+ line = tvb_get_ptr(tvb, offset, linelen);
+ lineend = line + linelen;
+ colon_offset = -1;
+
+ /*
+ * OK, does it look like an HTTP request or response?
+ */
+ req_dissector = NULL;
+ is_request_or_reply = is_http_request_or_reply((const gchar *)line,
+ linelen, &http_type, &req_dissector, &req_strlen);
+ if (is_request_or_reply)
+ goto is_http;
+
+ /*
+ * No. Does it look like a blank line (as would appear
+ * at the end of an HTTP request)?
+ */
+ if (linelen == 0)
+ goto is_http; /* Yes. */
+
+ /*
+ * No. Does it look like a header?
+ */
+ linep = line;
+ colon_offset = offset;
+ while (linep < lineend) {
+ c = *linep++;
+
+ /*
+ * This must be a CHAR to be part of a token; that
+ * means it must be ASCII.
+ */
+ if (!isascii(c))
+ break; /* not ASCII, thus not a CHAR */
+
+ /*
+ * This mustn't be a CTL to be part of a token.
+ *
+ * XXX - what about leading LWS on continuation
+ * lines of a header?
+ */
+ if (iscntrl(c))
+ break; /* CTL, not part of a header */
+
+ /*
+ * This mustn't be a SEP to be part of a token;
+ * a ':' ends the token, everything else is an
+ * indication that this isn't a header.
+ */
+ switch (c) {
+
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case '\\':
+ case '"':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+ case '{':
+ case '}':
+ case ' ':
+ /*
+ * It's a separator, so it's not part of a
+ * token, so it's not a field name for the
+ * beginning of a header.
+ *
+ * (We don't have to check for HT; that's
+ * already been ruled out by "iscntrl()".)
+ */
+ goto not_http;
+
+ case ':':
+ /*
+ * This ends the token; we consider this
+ * to be a header.
+ */
+ goto is_http;
+
+ default:
+ colon_offset++;
+ break;
+ }
+ }
+
+ /*
+ * We haven't seen the colon, but everything else looks
+ * OK for a header line.
+ *
+ * If we've already seen an HTTP request or response
+ * line, or a header line, and we're at the end of
+ * the tvbuff, we assume this is an incomplete header
+ * line. (We quit this loop after seeing a blank line,
+ * so if we've seen a request or response line, or a
+ * header line, this is probably more of the request
+ * or response we're presumably seeing. There is some
+ * risk of false positives, but the same applies for
+ * full request or response lines or header lines,
+ * although that's less likely.)
+ *
+ * We throw an exception in that case, by checking for
+ * the existence of the next byte after the last one
+ * in the line. If it exists, "tvb_ensure_bytes_exist()"
+ * throws no exception, and we fall through to the
+ * "not HTTP" case. If it doesn't exist,
+ * "tvb_ensure_bytes_exist()" will throw the appropriate
+ * exception.
+ */
+ if (saw_req_resp_or_header)
+ tvb_ensure_bytes_exist(tvb, offset, linelen + 1);
+
+ not_http:
+ /*
+ * We don't consider this part of an HTTP request or
+ * reply, so we don't display it.
+ * (Yeah, that means we don't display, say, a text/http
+ * page, but you can get that from the data pane.)
+ */
+ break;
+
+ is_http:
+ /*
+ * Process this line.
+ */
+ if (linelen == 0) {
+ /*
+ * This is a blank line, which means that
+ * whatever follows it isn't part of this
+ * request or reply.
+ */
+ proto_tree_add_text(http_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ offset = next_offset;
+ break;
+ }
+
+ /*
+ * Not a blank line - either a request, a reply, or a header
+ * line.
+ */
+ saw_req_resp_or_header = TRUE;
+ if (is_request_or_reply) {
+ if (tree) {
+ hdr_item = proto_tree_add_text(http_tree, tvb,
+ offset, next_offset - offset, "%s",
+ tvb_format_text(tvb, offset,
+ next_offset - offset));
+ if (req_dissector) {
+ req_tree = proto_item_add_subtree(
+ hdr_item, ett_http_request);
+ req_dissector(tvb, req_tree,
+ req_strlen);
+ }
+ }
+ } else {
+ /*
+ * Header.
+ */
+ process_header(tvb, offset, next_offset, line, linelen,
+ colon_offset, pinfo, http_tree, &headers);
+ }
+ offset = next_offset;
+ }
+
+ if (tree) {
+ switch (http_type) {
+
+ case HTTP_NOTIFICATION:
+ proto_tree_add_boolean_hidden(http_tree,
+ hf_http_notification, tvb, 0, 0, 1);
+ break;
+
+ case HTTP_RESPONSE:
+ proto_tree_add_boolean_hidden(http_tree,
+ hf_http_response, tvb, 0, 0, 1);
+ break;
+
+ case HTTP_REQUEST:
+ proto_tree_add_boolean_hidden(http_tree,
+ hf_http_request, tvb, 0, 0, 1);
+ break;
+
+ case HTTP_OTHERS:
+ default:
+ break;
+ }
+ }
+
+ /*
+ * If a content length was supplied, the amount of data to be
+ * processed as HTTP payload is the minimum of the content
+ * length and the amount of data remaining in the frame.
+ *
+ * If no content length was supplied (or if a bad content length
+ * was supplied), the amount of data to be processed is the amount
+ * of data remaining in the frame.
+ *
+ * If there was no Content-Length entity header, we should
+ * accumulate all data until the end of the connection.
+ * That'd require that the TCP dissector call subdissectors
+ * for all frames with FIN, even if they contain no data,
+ * which would require subdissectors to deal intelligently
+ * with empty segments.
+ *
+ * Acccording to RFC 2616, however, 1xx responses, 204 responses,
+ * and 304 responses MUST NOT include a message body; if no
+ * content length is specified for them, we don't attempt to
+ * dissect the body.
+ *
+ * XXX - it says the same about responses to HEAD requests;
+ * unless there's a way to determine from the response
+ * whether it's a response to a HEAD request, we have to
+ * keep information about the request and associate that with
+ * the response in order to handle that.
+ */
+ datalen = tvb_length_remaining(tvb, offset);
+ if (headers.content_length != -1) {
+ if (datalen > headers.content_length)
+ datalen = headers.content_length;
+
+ /*
+ * XXX - limit the reported length in the tvbuff we'll
+ * hand to a subdissector to be no greater than the
+ * content length.
+ *
+ * We really need both unreassembled and "how long it'd
+ * be if it were reassembled" lengths for tvbuffs, so
+ * that we throw the appropriate exceptions for
+ * "not enough data captured" (running past the length),
+ * "packet needed reassembly" (within the length but
+ * running past the unreassembled length), and
+ * "packet is malformed" (running past the reassembled
+ * length).
+ */
+ reported_datalen = tvb_reported_length_remaining(tvb, offset);
+ if (reported_datalen > headers.content_length)
+ reported_datalen = headers.content_length;
+ } else {
+ if ((stat_info->response_code/100) == 1 ||
+ stat_info->response_code == 204 ||
+ stat_info->response_code == 304)
+ datalen = 0; /* no content! */
+ else
+ reported_datalen = -1;
+ }
+
+ if (datalen > 0) {
+ /*
+ * There's stuff left over; process it.
+ */
+ tvbuff_t *next_tvb;
+ void *save_private_data = NULL;
+ gint chunks_decoded = 0;
+
+ /*
+ * Create a tvbuff for the payload.
+ *
+ * The amount of data to be processed that's
+ * available in the tvbuff is "datalen", which
+ * is the minimum of the amount of data left in
+ * the tvbuff and any specified content length.
+ *
+ * The amount of data to be processed that's in
+ * this frame, regardless of whether it was
+ * captured or not, is "reported_datalen",
+ * which, if no content length was specified,
+ * is -1, i.e. "to the end of the frame.
+ */
+ next_tvb = tvb_new_subset(tvb, offset, datalen,
+ reported_datalen);
+ /*
+ * BEWARE - next_tvb is a subset of another tvb,
+ * so we MUST NOT attempt tvb_free(next_tvb);
+ */
+
+ /*
+ * Handle *transfer* encodings other than "identity".
+ */
+ if (headers.transfer_encoding != NULL &&
+ strcasecmp(headers.transfer_encoding, "identity") != 0) {
+ if (http_dechunk_body &&
+ (strcasecmp(headers.transfer_encoding, "chunked")
+ == 0)) {
+
+ chunks_decoded = chunked_encoding_dissector(
+ &next_tvb, pinfo, http_tree, 0);
+
+ if (chunks_decoded <= 0) {
+ /*
+ * The chunks weren't reassembled,
+ * or there was a single zero
+ * length chunk.
+ */
+ goto body_dissected;
+ } else {
+ /*
+ * Add a new data source for the
+ * de-chunked data.
+ */
+ tvb_set_child_real_data_tvbuff(tvb,
+ next_tvb);
+ add_new_data_source(pinfo, next_tvb,
+ "De-chunked entity body");
+ }
+ } else {
+ /*
+ * We currently can't handle, for example,
+ * "gzip", "compress", or "deflate" as
+ * *transfer* encodings; just handle them
+ * as data for now.
+ */
+ call_dissector(data_handle, next_tvb, pinfo,
+ http_tree);
+ goto body_dissected;
+ }
+ }
+ /*
+ * At this point, any chunked *transfer* coding has been removed
+ * (the entity body has been dechunked) so it can be presented
+ * for the following operation (*content* encoding), or it has
+ * been been handed off to the data dissector.
+ *
+ * Handle *content* encodings other than "identity" (which
+ * shouldn't appear in a Content-Encoding header, but
+ * we handle it in any case).
+ */
+ if (headers.content_encoding != NULL &&
+ strcasecmp(headers.content_encoding, "identity") != 0) {
+ /*
+ * We currently can't handle, for example, "compress";
+ * just handle them as data for now.
+ *
+ * After July 7, 2004 the LZW patent expires, so support
+ * might be added then. However, I don't think that
+ * anybody ever really implemented "compress", due to
+ * the aforementioned patent.
+ */
+ tvbuff_t *uncomp_tvb = NULL;
+ proto_item *e_ti = NULL;
+ proto_tree *e_tree = NULL;
+
+ if (http_decompress_body &&
+ (strcasecmp(headers.content_encoding, "gzip") == 0 ||
+ strcasecmp(headers.content_encoding, "deflate")
+ == 0)) {
+
+ uncomp_tvb = tvb_uncompress(next_tvb, 0,
+ tvb_length(next_tvb));
+ }
+
+ /*
+ * Add the encoded entity to the protocol tree
+ */
+ e_ti = proto_tree_add_text(http_tree, next_tvb,
+ 0, tvb_length(next_tvb),
+ "Content-encoded entity body (%s)",
+ headers.content_encoding);
+ e_tree = proto_item_add_subtree(e_ti,
+ ett_http_encoded_entity);
+
+ if (uncomp_tvb != NULL) {
+ /*
+ * Decompression worked
+ */
+
+ /* XXX - Don't free this, since it's possible
+ * that the data was only partially
+ * decompressed, such as when desegmentation
+ * isn't enabled.
+ *
+ tvb_free(next_tvb);
+ */
+ next_tvb = uncomp_tvb;
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb,
+ "Uncompressed entity body");
+ } else {
+ if (chunks_decoded > 1) {
+ tvb_set_child_real_data_tvbuff(tvb,
+ next_tvb);
+ add_new_data_source(pinfo, next_tvb,
+ "Compressed entity body");
+ }
+ call_dissector(data_handle, next_tvb, pinfo,
+ e_tree);
+
+ goto body_dissected;
+ }
+ }
+ /*
+ * Note that a new data source is added for the entity body
+ * only if it was content-encoded and/or transfer-encoded.
+ */
+
+ /*
+ * Do subdissector checks.
+ *
+ * First, check whether some subdissector asked that they
+ * be called if something was on some particular port.
+ */
+ handle = dissector_get_port_handle(port_subdissector_table,
+ pinfo->match_port);
+ if (handle == NULL && headers.content_type != NULL) {
+ /*
+ * We didn't find any subdissector that
+ * registered for the port, and we have a
+ * Content-Type value. Is there any subdissector
+ * for that content type?
+ */
+ save_private_data = pinfo->private_data;
+ /*
+ * XXX - this won't get freed if the subdissector
+ * throws an exception. Do we really need to
+ * strdup it?
+ */
+ if (headers.content_type_parameters)
+ pinfo->private_data = g_strdup(headers.content_type_parameters);
+ else
+ pinfo->private_data = NULL;
+ /*
+ * Calling the string handle for the media type
+ * dissector table will set pinfo->match_string
+ * to headers.content_type for us.
+ */
+ pinfo->match_string = headers.content_type;
+ handle = dissector_get_string_handle(
+ media_type_subdissector_table,
+ headers.content_type);
+ /*
+ * Calling the default media handle otherwise
+ */
+ if (handle == NULL) {
+ handle = media_handle;
+ }
+ }
+ if (handle != NULL) {
+ /*
+ * We have a subdissector - call it.
+ */
+ dissected = call_dissector(handle, next_tvb, pinfo,
+ tree);
+ } else {
+ /*
+ * We don't have a subdissector - try the heuristic
+ * subdissectors.
+ */
+ dissected = dissector_try_heuristic(
+ heur_subdissector_list, next_tvb, pinfo, tree);
+ }
+ if (dissected) {
+ /*
+ * The subdissector dissected the body.
+ * Fix up the top-level item so that it doesn't
+ * include the stuff for that protocol.
+ */
+ if (ti != NULL)
+ proto_item_set_len(ti, offset);
+ } else {
+ call_dissector(data_handle, next_tvb, pinfo,
+ http_tree);
+ }
+
+ body_dissected:
+ /*
+ * Do *not* attempt at freeing the private data;
+ * it may be in use by subdissectors.
+ */
+ if (save_private_data)
+ pinfo->private_data = save_private_data;
+ /*
+ * We've processed "datalen" bytes worth of data
+ * (which may be no data at all); advance the
+ * offset past whatever data we've processed.
+ */
+ offset += datalen;
+ }
+
+ /*
+ * Clean up any header stuff, by calling and popping the cleanup
+ * handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
+ tap_queue_packet(http_tap, pinfo, stat_info);
+
+ return offset - orig_offset;
+}
+
+/* This can be used to dissect an HTTP request until such time
+ * that a more complete dissector is written for that HTTP request.
+ * This simple dissectory only puts http.request_method into a sub-tree.
+ */
+static void
+basic_request_dissector(tvbuff_t *tvb, proto_tree *tree, int req_strlen)
+{
+ proto_tree_add_item(tree, hf_http_request_method, tvb, 0, req_strlen, FALSE);
+}
+
+static void
+basic_response_dissector(tvbuff_t *tvb, proto_tree *tree, int resp_strlen)
+{
+ gchar *data;
+ int minor, major, status_code;
+
+ /* BEWARE - sscanf() only operates on C strings.
+ * The pointer returned by tvb_get_ptr points into the real data,
+ * which is not necessarily NULL terminated. For this reason,
+ * the sscanf() call is only applied to a buffer guaranteed to
+ * only contain a NULL terminated string. */
+ data = g_strndup((const gchar *)tvb_get_ptr(tvb, 5, resp_strlen), resp_strlen);
+ if (sscanf((const gchar *)data, "%d.%d %d", &minor, &major, &status_code) == 3) {
+ proto_tree_add_uint(tree, hf_http_response_code, tvb, 9, 3, status_code);
+ stat_info->response_code = status_code;
+ }
+ g_free(data);
+}
+
+/*
+ * Dissect the http data chunks and add them to the tree.
+ */
+static int
+chunked_encoding_dissector(tvbuff_t **tvb_ptr, packet_info *pinfo,
+ proto_tree *tree, int offset)
+{
+ guint8 *chunk_string = NULL;
+ gint chunk_size = 0;
+ gint chunk_offset = 0;
+ gint datalen = 0;
+ gint linelen = 0;
+ gint chunks_decoded = 0;
+ tvbuff_t *tvb = NULL;
+ tvbuff_t *new_tvb = NULL;
+ gint chunked_data_size = 0;
+ proto_tree *subtree = NULL;
+ proto_item *ti = NULL;
+
+ if (tvb_ptr == NULL || *tvb_ptr == NULL) {
+ return 0;
+ }
+
+ tvb = *tvb_ptr;
+
+ datalen = tvb_reported_length_remaining(tvb, offset);
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, datalen,
+ "HTTP chunked response");
+ subtree = proto_item_add_subtree(ti, ett_http_chunked_response);
+ }
+
+
+ while (datalen != 0) {
+ proto_item *chunk_ti = NULL;
+ proto_tree *chunk_subtree = NULL;
+ tvbuff_t *data_tvb = NULL;
+ gchar *c = NULL;
+
+ linelen = tvb_find_line_end(tvb, offset, -1, &chunk_offset, TRUE);
+
+ if (linelen <= 0) {
+ /* Can't get the chunk size line */
+ break;
+ }
+
+ chunk_string = tvb_get_string(tvb, offset, linelen);
+
+ if (chunk_string == NULL) {
+ /* Can't get the chunk size line */
+ break;
+ }
+
+ c = chunk_string;
+
+ /*
+ * We don't care about the extensions.
+ */
+ if ((c = strchr(c, ';'))) {
+ *c = '\0';
+ }
+
+ if (sscanf(chunk_string, "%x", &chunk_size) != 1) {
+ g_free(chunk_string);
+ break;
+ }
+
+ g_free(chunk_string);
+
+
+ if (chunk_size > datalen) {
+ /*
+ * The chunk size is more than what's in the tvbuff,
+ * so either the user hasn't enabled decoding, or all
+ * of the segments weren't captured.
+ */
+ chunk_size = datalen;
+ }/* else if (new_tvb == NULL) {
+ new_tvb = tvb_new_composite();
+ }
+
+
+
+ if (new_tvb != NULL && chunk_size != 0) {
+ tvbuff_t *chunk_tvb = NULL;
+
+ chunk_tvb = tvb_new_subset(tvb, chunk_offset,
+ chunk_size, datalen);
+
+ tvb_composite_append(new_tvb, chunk_tvb);
+
+ }
+ */
+
+ chunked_data_size += chunk_size;
+
+ if (chunk_size != 0) {
+ guint8 *raw_data = g_malloc(chunked_data_size);
+ gint raw_len = 0;
+
+ if (new_tvb != NULL) {
+ raw_len = tvb_length_remaining(new_tvb, 0);
+ tvb_memcpy(new_tvb, raw_data, 0, raw_len);
+
+ tvb_free(new_tvb);
+ }
+
+ tvb_memcpy(tvb, (guint8 *)(raw_data + raw_len),
+ chunk_offset, chunk_size);
+
+ new_tvb = tvb_new_real_data(raw_data,
+ chunked_data_size, chunked_data_size);
+ tvb_set_free_cb(new_tvb, g_free);
+
+ }
+
+ if (subtree) {
+ if (chunk_size == 0) {
+ chunk_ti = proto_tree_add_text(subtree, tvb,
+ offset,
+ chunk_offset - offset + chunk_size + 2,
+ "Data chunk (last chunk)");
+ } else {
+ chunk_ti = proto_tree_add_text(subtree, tvb,
+ offset,
+ chunk_offset - offset + chunk_size + 2,
+ "Data chunk (%u octets)", chunk_size);
+ }
+
+ chunk_subtree = proto_item_add_subtree(chunk_ti,
+ ett_http_chunk_data);
+
+ proto_tree_add_text(chunk_subtree, tvb, offset,
+ chunk_offset - offset, "Chunk size: %u octets",
+ chunk_size);
+
+ data_tvb = tvb_new_subset(tvb, chunk_offset, chunk_size,
+ datalen);
+
+
+ if (chunk_size > 0) {
+ call_dissector(data_handle, data_tvb, pinfo,
+ chunk_subtree);
+ }
+
+ proto_tree_add_text(chunk_subtree, tvb, chunk_offset +
+ chunk_size, 2, "Chunk boundary");
+ }
+
+ chunks_decoded++;
+ offset = chunk_offset + chunk_size + 2;
+ datalen = tvb_reported_length_remaining(tvb, offset);
+ }
+
+ if (new_tvb != NULL) {
+
+ /* Placeholder for the day that composite tvbuffer's will work.
+ tvb_composite_finalize(new_tvb);
+ / * tvb_set_reported_length(new_tvb, chunked_data_size); * /
+ */
+
+ /*
+ * XXX - Don't free this, since the tvbuffer that was passed
+ * may be used if the data spans multiple frames and reassembly
+ * isn't enabled.
+ *
+ tvb_free(*tvb_ptr);
+ */
+ *tvb_ptr = new_tvb;
+
+ } else {
+ /*
+ * We didn't create a new tvb, so don't allow sub dissectors
+ * try to decode the non-existant entity body.
+ */
+ chunks_decoded = -1;
+ }
+
+ return chunks_decoded;
+
+}
+
+
+/*
+ * XXX - this won't handle HTTP 0.9 replies, but they're all data
+ * anyway.
+ */
+static int
+is_http_request_or_reply(const gchar *data, int linelen, http_type_t *type,
+ RequestDissector *req_dissector, int *req_strlen)
+{
+ int isHttpRequestOrReply = FALSE;
+ int prefix_len = 0;
+
+ /*
+ * From RFC 2774 - An HTTP Extension Framework
+ *
+ * Support the command prefix that identifies the presence of
+ * a "mandatory" header.
+ */
+ if (linelen >= 2 && strncmp(data, "M-", 2) == 0) {
+ data += 2;
+ linelen -= 2;
+ prefix_len = 2;
+ }
+
+ /*
+ * From draft-cohen-gena-client-01.txt, available from the uPnP forum:
+ * NOTIFY, SUBSCRIBE, UNSUBSCRIBE
+ *
+ * From draft-ietf-dasl-protocol-00.txt, a now vanished Microsoft draft:
+ * SEARCH
+ */
+ if (linelen >= 5 && strncmp(data, "HTTP/", 5) == 0) {
+ *type = HTTP_RESPONSE;
+ isHttpRequestOrReply = TRUE; /* response */
+ if (req_dissector) {
+ *req_dissector = basic_response_dissector;
+ *req_strlen = linelen - 5;
+ }
+ } else {
+ const guchar * ptr = (const guchar *)data;
+ int index = 0;
+
+ /* Look for the space following the Method */
+ while (index < linelen) {
+ if (*ptr == ' ')
+ break;
+ else {
+ ptr++;
+ index++;
+ }
+ }
+
+ /* Check the methods that have same length */
+ switch (index) {
+
+ case 3:
+ if (strncmp(data, "GET", index) == 0 ||
+ strncmp(data, "PUT", index) == 0) {
+ *type = HTTP_REQUEST;
+ isHttpRequestOrReply = TRUE;
+ }
+ else if (strncmp(data, "ICY", index) == 0) {
+ *type = HTTP_RESPONSE;
+ isHttpRequestOrReply = TRUE;
+ }
+ break;
+
+ case 4:
+ if (strncmp(data, "COPY", index) == 0 ||
+ strncmp(data, "HEAD", index) == 0 ||
+ strncmp(data, "LOCK", index) == 0 ||
+ strncmp(data, "MOVE", index) == 0 ||
+ strncmp(data, "POLL", index) == 0 ||
+ strncmp(data, "POST", index) == 0) {
+ *type = HTTP_REQUEST;
+ isHttpRequestOrReply = TRUE;
+ }
+ break;
+
+ case 5:
+ if (strncmp(data, "BCOPY", index) == 0 ||
+ strncmp(data, "BMOVE", index) == 0 ||
+ strncmp(data, "MKCOL", index) == 0 ||
+ strncmp(data, "TRACE", index) == 0) {
+ *type = HTTP_REQUEST;
+ isHttpRequestOrReply = TRUE;
+ }
+ break;
+
+ case 6:
+ if (strncmp(data, "DELETE", index) == 0 ||
+ strncmp(data, "SEARCH", index) == 0 ||
+ strncmp(data, "UNLOCK", index) == 0) {
+ *type = HTTP_REQUEST;
+ isHttpRequestOrReply = TRUE;
+ }
+ else if (strncmp(data, "NOTIFY", index) == 0) {
+ *type = HTTP_NOTIFICATION;
+ isHttpRequestOrReply = TRUE;
+ }
+ break;
+
+ case 7:
+ if (strncmp(data, "BDELETE", index) == 0 ||
+ strncmp(data, "CONNECT", index) == 0 ||
+ strncmp(data, "OPTIONS", index) == 0) {
+ *type = HTTP_REQUEST;
+ isHttpRequestOrReply = TRUE;
+ }
+ break;
+
+ case 8:
+ if (strncmp(data, "PROPFIND", index) == 0) {
+ *type = HTTP_REQUEST;
+ isHttpRequestOrReply = TRUE;
+ }
+ break;
+
+ case 9:
+ if (strncmp(data, "SUBSCRIBE", index) == 0) {
+ *type = HTTP_NOTIFICATION;
+ isHttpRequestOrReply = TRUE;
+ } else if (strncmp(data, "PROPPATCH", index) == 0 ||
+ strncmp(data, "BPROPFIND", index) == 0) {
+ *type = HTTP_REQUEST;
+ isHttpRequestOrReply = TRUE;
+ }
+ break;
+
+ case 10:
+ if (strncmp(data, "BPROPPATCH", index) == 0) {
+ *type = HTTP_REQUEST;
+ isHttpRequestOrReply = TRUE;
+ }
+ break;
+
+ case 11:
+ if (strncmp(data, "UNSUBSCRIBE", index) == 0) {
+ *type = HTTP_NOTIFICATION;
+ isHttpRequestOrReply = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (isHttpRequestOrReply && req_dissector) {
+ *req_dissector = basic_request_dissector;
+ *req_strlen = index + prefix_len;
+ }
+ if (isHttpRequestOrReply && req_dissector) {
+ if (!stat_info->request_method)
+ stat_info->request_method = g_malloc( index+1 );
+ strncpy( stat_info->request_method, data, index);
+ stat_info->request_method[index] = '\0';
+ }
+ }
+
+ return isHttpRequestOrReply;
+}
+
+/*
+ * Process headers.
+ */
+typedef struct {
+ char *name;
+ gint *hf;
+ int special;
+} header_info;
+
+#define HDR_NO_SPECIAL 0
+#define HDR_AUTHORIZATION 1
+#define HDR_AUTHENTICATE 2
+#define HDR_CONTENT_TYPE 3
+#define HDR_CONTENT_LENGTH 4
+#define HDR_CONTENT_ENCODING 5
+#define HDR_TRANSFER_ENCODING 6
+
+static const header_info headers[] = {
+ { "Authorization", &hf_http_authorization, HDR_AUTHORIZATION },
+ { "Proxy-Authorization", &hf_http_proxy_authorization, HDR_AUTHORIZATION },
+ { "Proxy-Authenticate", &hf_http_proxy_authenticate, HDR_AUTHENTICATE },
+ { "WWW-Authenticate", &hf_http_www_authenticate, HDR_AUTHENTICATE },
+ { "Content-Type", &hf_http_content_type, HDR_CONTENT_TYPE },
+ { "Content-Length", &hf_http_content_length, HDR_CONTENT_LENGTH },
+ { "Content-Encoding", &hf_http_content_encoding, HDR_CONTENT_ENCODING },
+ { "Transfer-Encoding", &hf_http_transfer_encoding, HDR_TRANSFER_ENCODING },
+};
+
+static void
+process_header(tvbuff_t *tvb, int offset, int next_offset,
+ const guchar *line, int linelen, int colon_offset,
+ packet_info *pinfo, proto_tree *tree, headers_t *eh_ptr)
+{
+ int len;
+ int line_end_offset;
+ int header_len;
+ gint hf_index;
+ guchar c;
+ int value_offset;
+ int value_len;
+ char *value;
+ char *p;
+ guchar *up;
+ proto_item *hdr_item;
+ int i;
+
+ len = next_offset - offset;
+ line_end_offset = offset + linelen;
+ header_len = colon_offset - offset;
+ hf_index = find_header_hf_value(tvb, offset, header_len);
+
+ if (hf_index == -1) {
+ /*
+ * Not a header we know anything about. Just put it into
+ * the tree as text.
+ */
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "%s", format_text(line, len));
+ }
+ } else {
+ /*
+ * Skip whitespace after the colon.
+ */
+ value_offset = colon_offset + 1;
+ while (value_offset < line_end_offset
+ && ((c = line[value_offset - offset]) == ' ' || c == '\t'))
+ value_offset++;
+
+ /*
+ * Fetch the value.
+ */
+ value_len = line_end_offset - value_offset;
+ value = g_malloc(value_len + 1);
+ memcpy(value, &line[value_offset - offset], value_len);
+ value[value_len] = '\0';
+ CLEANUP_PUSH(g_free, value);
+
+ /*
+ * Add it to the protocol tree as a particular field,
+ * but display the line as is.
+ */
+ if (tree) {
+ hdr_item = proto_tree_add_string_format(tree,
+ *headers[hf_index].hf, tvb, offset, len,
+ value, "%s", format_text(line, len));
+ } else
+ hdr_item = NULL;
+
+ /*
+ * Do any special processing that particular headers
+ * require.
+ */
+ switch (headers[hf_index].special) {
+
+ case HDR_AUTHORIZATION:
+ if (check_auth_ntlmssp(hdr_item, tvb, pinfo, value))
+ break; /* dissected NTLMSSP */
+ check_auth_basic(hdr_item, tvb, value);
+ break;
+
+ case HDR_AUTHENTICATE:
+ check_auth_ntlmssp(hdr_item, tvb, pinfo, value);
+ break;
+
+ case HDR_CONTENT_TYPE:
+ if (eh_ptr->content_type != NULL)
+ g_free(eh_ptr->content_type);
+ eh_ptr->content_type = g_malloc(value_len + 1);
+ for (i = 0; i < value_len; i++) {
+ c = value[i];
+ if (c == ';' || isspace(c)) {
+ /*
+ * End of subtype - either
+ * white space or a ";"
+ * separating the subtype from
+ * a parameter.
+ */
+ break;
+ }
+
+ /*
+ * Map the character to lower case;
+ * content types are case-insensitive.
+ */
+ eh_ptr->content_type[i] = tolower(c);
+ }
+ eh_ptr->content_type[i] = '\0';
+ /*
+ * Now find the start of the optional parameters;
+ * skip the optional white space and the semicolon
+ * if this has not been done before.
+ */
+ i++;
+ while (i < value_len) {
+ c = value[i];
+ if (c == ';' || isspace(c))
+ /* Skip till start of parameters */
+ i++;
+ else
+ break;
+ }
+ if (i < value_len)
+ eh_ptr->content_type_parameters = value + i;
+ else
+ eh_ptr->content_type_parameters = NULL;
+ break;
+
+ case HDR_CONTENT_LENGTH:
+ eh_ptr->content_length = strtol(value, &p, 10);
+ up = (guchar *)p;
+ if (eh_ptr->content_length < 0 || p == value ||
+ (*up != '\0' && !isspace(*up)))
+ eh_ptr->content_length = -1; /* not valid */
+ break;
+
+ case HDR_CONTENT_ENCODING:
+ if (eh_ptr->content_encoding != NULL)
+ g_free(eh_ptr->content_encoding);
+ eh_ptr->content_encoding = g_malloc(value_len + 1);
+ memcpy(eh_ptr->content_encoding, value, value_len);
+ eh_ptr->content_encoding[value_len] = '\0';
+ break;
+
+ case HDR_TRANSFER_ENCODING:
+ if (eh_ptr->transfer_encoding != NULL)
+ g_free(eh_ptr->transfer_encoding);
+ eh_ptr->transfer_encoding = g_malloc(value_len + 1);
+ memcpy(eh_ptr->transfer_encoding, value, value_len);
+ eh_ptr->transfer_encoding[value_len] = '\0';
+ break;
+ }
+
+ /*
+ * Free the value, by calling and popping the cleanup
+ * handler for it.
+ */
+ CLEANUP_CALL_AND_POP;
+ }
+}
+
+/* Returns index of header tag in headers */
+static gint
+find_header_hf_value(tvbuff_t *tvb, int offset, guint header_len)
+{
+ guint i;
+
+ for (i = 0; i < array_length(headers); i++) {
+ if (header_len == strlen(headers[i].name) &&
+ tvb_strncaseeql(tvb, offset,
+ headers[i].name, header_len) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+/*
+ * Dissect Microsoft's abomination called NTLMSSP over HTTP.
+ */
+static gboolean
+check_auth_ntlmssp(proto_item *hdr_item, tvbuff_t *tvb, packet_info *pinfo,
+ gchar *value)
+{
+ static const char *ntlm_headers[] = {
+ "NTLM ",
+ "Negotiate ",
+ NULL
+ };
+ const char **header;
+ size_t hdrlen;
+ proto_tree *hdr_tree;
+
+ /*
+ * Check for NTLM credentials and challenge; those can
+ * occur with WWW-Authenticate.
+ */
+ for (header = &ntlm_headers[0]; *header != NULL; header++) {
+ hdrlen = strlen(*header);
+ if (strncmp(value, *header, hdrlen) == 0) {
+ if (hdr_item != NULL) {
+ hdr_tree = proto_item_add_subtree(hdr_item,
+ ett_http_ntlmssp);
+ } else
+ hdr_tree = NULL;
+ value += hdrlen;
+ dissect_http_ntlmssp(tvb, pinfo, hdr_tree, value);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Dissect HTTP Basic authorization.
+ */
+static gboolean
+check_auth_basic(proto_item *hdr_item, tvbuff_t *tvb, gchar *value)
+{
+ static const char *basic_headers[] = {
+ "Basic ",
+ NULL
+ };
+ const char **header;
+ size_t hdrlen;
+ proto_tree *hdr_tree;
+ size_t len;
+
+ for (header = &basic_headers[0]; *header != NULL; header++) {
+ hdrlen = strlen(*header);
+ if (strncmp(value, *header, hdrlen) == 0) {
+ if (hdr_item != NULL) {
+ hdr_tree = proto_item_add_subtree(hdr_item,
+ ett_http_ntlmssp);
+ } else
+ hdr_tree = NULL;
+ value += hdrlen;
+
+ len = epan_base64_decode(value);
+ value[len] = '\0';
+ proto_tree_add_string(hdr_tree, hf_http_basic, tvb,
+ 0, 0, value);
+
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+dissect_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ int len;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ len = dissect_http_message(tvb, offset, pinfo, tree);
+ if (len == -1)
+ break;
+ offset += len;
+
+ /*
+ * OK, we've set the Protocol and Info columns for the
+ * first HTTP message; make the columns non-writable,
+ * so that we don't change it for subsequent HTTP messages.
+ */
+ col_set_writable(pinfo->cinfo, FALSE);
+ }
+}
+
+static void
+dissect_http_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_http_message(tvb, 0, pinfo, tree);
+}
+
+void
+proto_register_http(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_http_notification,
+ { "Notification", "http.notification",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if HTTP notification", HFILL }},
+ { &hf_http_response,
+ { "Response", "http.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if HTTP response", HFILL }},
+ { &hf_http_request,
+ { "Request", "http.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if HTTP request", HFILL }},
+ { &hf_http_basic,
+ { "Credentials", "http.authbasic",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_http_request_method,
+ { "Request Method", "http.request.method",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Request Method", HFILL }},
+ { &hf_http_response_code,
+ { "Response Code", "http.response.code",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "HTTP Response Code", HFILL }},
+ { &hf_http_authorization,
+ { "Authorization", "http.authorization",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Authorization header", HFILL }},
+ { &hf_http_proxy_authenticate,
+ { "Proxy-Authenticate", "http.proxy_authenticate",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Proxy-Authenticate header", HFILL }},
+ { &hf_http_proxy_authorization,
+ { "Proxy-Authorization", "http.proxy_authorization",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Proxy-Authorization header", HFILL }},
+ { &hf_http_www_authenticate,
+ { "WWW-Authenticate", "http.www_authenticate",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP WWW-Authenticate header", HFILL }},
+ { &hf_http_content_type,
+ { "Content-Type", "http.content_type",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Content-Type header", HFILL }},
+ { &hf_http_content_length,
+ { "Content-Length", "http.content_length",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Content-Length header", HFILL }},
+ { &hf_http_content_encoding,
+ { "Content-Encoding", "http.content_encoding",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Content-Encoding header", HFILL }},
+ { &hf_http_transfer_encoding,
+ { "Transfer-Encoding", "http.transfer_encoding",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "HTTP Transfer-Encoding header", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_http,
+ &ett_http_ntlmssp,
+ &ett_http_request,
+ &ett_http_chunked_response,
+ &ett_http_chunk_data,
+ &ett_http_encoded_entity,
+ };
+ module_t *http_module;
+
+ proto_http = proto_register_protocol("Hypertext Transfer Protocol",
+ "HTTP", "http");
+ proto_register_field_array(proto_http, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ http_module = prefs_register_protocol(proto_http, NULL);
+ prefs_register_bool_preference(http_module, "desegment_headers",
+ "Desegment all HTTP headers spanning multiple TCP segments",
+ "Whether the HTTP dissector should desegment all headers "
+ "of a request spanning multiple TCP segments",
+ &http_desegment_headers);
+ prefs_register_bool_preference(http_module, "desegment_body",
+ "Desegment HTTP bodies spanning multiple TCP segments",
+ "Whether the HTTP dissector should use the "
+ "\"Content-length:\" value, if present, to desegment "
+ "the body of a request spanning multiple TCP segments, "
+ "and desegment chunked data spanning multiple TCP segments",
+ &http_desegment_body);
+ prefs_register_bool_preference(http_module, "dechunk_body",
+ "Reassemble chunked transfer-coded bodies",
+ "Whether to reassemble bodies of entities that are transfered "
+ "using the \"Transfer-Encoding: chunked\" method",
+ &http_dechunk_body);
+#ifdef HAVE_LIBZ
+ prefs_register_bool_preference(http_module, "decompress_body",
+ "Uncompress entity bodies",
+ "Whether to uncompress entity bodies that are compressed "
+ "using \"Content-Encoding: \"",
+ &http_decompress_body);
+#endif
+
+ http_handle = create_dissector_handle(dissect_http, proto_http);
+
+ /*
+ * Dissectors shouldn't register themselves in this table;
+ * instead, they should call "http_dissector_add()", and
+ * we'll register the port number they specify as a port
+ * for HTTP, and register them in our subdissector table.
+ *
+ * This only works for protocols such as IPP that run over
+ * HTTP on a specific non-HTTP port.
+ */
+ port_subdissector_table = register_dissector_table("http.port",
+ "TCP port for protocols using HTTP", FT_UINT16, BASE_DEC);
+
+ /*
+ * Dissectors can register themselves in this table.
+ * It's just "media_type", not "http.content_type", because
+ * it's an Internet media type, usable by other protocols as well.
+ */
+ media_type_subdissector_table =
+ register_dissector_table("media_type",
+ "Internet media type", FT_STRING, BASE_NONE);
+
+ /*
+ * Heuristic dissectors SHOULD register themselves in
+ * this table using the standard heur_dissector_add()
+ * function.
+ */
+ register_heur_dissector_list("http", &heur_subdissector_list);
+
+ /*
+ * Register for tapping
+ */
+ http_tap = register_tap("http");
+}
+
+/*
+ * Called by dissectors for protocols that run atop HTTP/TCP.
+ */
+void
+http_dissector_add(guint32 port, dissector_handle_t handle)
+{
+ /*
+ * Register ourselves as the handler for that port number
+ * over TCP.
+ */
+ dissector_add("tcp.port", port, http_handle);
+
+ /*
+ * And register them in *our* table for that port.
+ */
+ dissector_add("http.port", port, handle);
+}
+
+void
+proto_reg_handoff_http(void)
+{
+ dissector_handle_t http_udp_handle;
+
+ data_handle = find_dissector("data");
+ media_handle = find_dissector("media");
+
+ dissector_add("tcp.port", TCP_PORT_HTTP, http_handle);
+ dissector_add("tcp.port", TCP_ALT_PORT_HTTP, http_handle);
+ dissector_add("tcp.port", TCP_PORT_PROXY_HTTP, http_handle);
+ dissector_add("tcp.port", TCP_PORT_PROXY_ADMIN_HTTP, http_handle);
+ dissector_add("tcp.port", TCP_PORT_HKP, http_handle);
+
+ /*
+ * XXX - is there anything to dissect in the body of an SSDP
+ * request or reply? I.e., should there be an SSDP dissector?
+ */
+ dissector_add("tcp.port", TCP_PORT_SSDP, http_handle);
+ http_udp_handle = create_dissector_handle(dissect_http_udp, proto_http);
+ dissector_add("udp.port", UDP_PORT_SSDP, http_udp_handle);
+
+ ntlmssp_handle = find_dissector("ntlmssp");
+}
+
+/*
+ * Content-Type: message/http
+ */
+
+static gint proto_message_http = -1;
+static gint ett_message_http = -1;
+static dissector_handle_t message_http_handle;
+
+static void
+dissect_message_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *subtree;
+ proto_item *ti;
+ gint offset = 0, next_offset;
+ gint len;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " (message/http)");
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_message_http,
+ tvb, 0, -1, FALSE);
+ subtree = proto_item_add_subtree(ti, ett_message_http);
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ len = tvb_find_line_end(tvb, offset,
+ tvb_ensure_length_remaining(tvb, offset),
+ &next_offset, FALSE);
+ if (len == -1)
+ break;
+ proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
+ "%s", tvb_format_text(tvb, offset, len));
+ offset = next_offset;
+ }
+ }
+}
+
+void
+proto_register_message_http(void)
+{
+ static gint *ett[] = {
+ &ett_message_http,
+ };
+
+ proto_message_http = proto_register_protocol(
+ "Media Type: message/http",
+ "message/http",
+ "message-http"
+ );
+ proto_register_subtree_array(ett, array_length(ett));
+ message_http_handle = create_dissector_handle(dissect_message_http,
+ proto_message_http);
+}
+
+void
+proto_reg_handoff_message_http(void)
+{
+ message_http_handle = create_dissector_handle(dissect_message_http,
+ proto_message_http);
+
+ dissector_add_string("media_type", "message/http", message_http_handle);
+}
diff --git a/epan/dissectors/packet-http.h b/epan/dissectors/packet-http.h
new file mode 100644
index 0000000000..e79ffa4e43
--- /dev/null
+++ b/epan/dissectors/packet-http.h
@@ -0,0 +1,37 @@
+/* packet-http.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_HTTP_H__
+#define __PACKET_HTTP_H__
+
+#include <epan/packet.h>
+
+void http_dissector_add(guint32 port, dissector_handle_t handle);
+
+typedef struct _http_info_value_t
+{
+ gchar *request_method;
+ guint response_code;
+} http_info_value_t;
+
+#endif
diff --git a/epan/dissectors/packet-hyperscsi.c b/epan/dissectors/packet-hyperscsi.c
new file mode 100644
index 0000000000..f4ed93349a
--- /dev/null
+++ b/epan/dissectors/packet-hyperscsi.c
@@ -0,0 +1,223 @@
+/* packet-ip.c
+ * Routines for dissassembly of the Hyper SCSI protocol.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ * Copyright 2002 Richard Sharpe <rsharpe@richardsharpe.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+
+static int proto_hyperscsi;
+
+static int hf_hs_cmd = -1;
+static int hf_hs_ver = -1;
+static int hf_hs_res = -1;
+static int hf_hs_tagno = -1;
+static int hf_hs_lastfrag = -1;
+static int hf_hs_fragno = -1;
+
+static gint ett_hyperscsi = -1;
+static gint ett_hs_hdr = -1;
+static gint ett_hs_pdu = -1;
+
+static const true_false_string tfs_lastfrag = {
+ "Last Fragment",
+ "Not Last Fragment"
+};
+
+#define HSCSI_OPCODE_REQUEST 0x00
+#define HSCSI_OPCODE_REPLY 0x01
+#define HSCSI_OPCODE_DEV_DISCOVERY 0x10
+#define HSCSI_OPCODE_ADN_REQUEST 0x11
+#define HSCSI_OPCODE_ADN_REPLY 0x12
+#define HSCSI_OPCODE_DISCONNECT 0x13
+#define HSCSI_OPCODE_ACK_SNR 0x20
+#define HSCSI_OPCODE_ACK_REPLY 0x21
+#define HSCSI_OPCODE_ADDR_REPORT 0x30
+#define HSCSI_OPCODE_ADDR_REPLY 0x31
+#define HSCSI_OPCODE_LOCAL_REQUEST 0x32
+#define HSCSI_OPCODE_LOCAL_REPLY 0x33
+#define HSCSI_OPCODE_REMOTE_REQUEST 0x34
+#define HSCSI_OPCODE_REMOTE_REPLY 0x35
+
+static const value_string hscsi_opcodes[] = {
+ { HSCSI_OPCODE_REQUEST, "Command Block Encap Request"},
+ { HSCSI_OPCODE_REPLY, "Command Block Encap Reply"},
+ { HSCSI_OPCODE_DEV_DISCOVERY, "Device Discovery Reply"},
+ { HSCSI_OPCODE_ADN_REQUEST, "Auth/Device Neg Request"},
+ { HSCSI_OPCODE_ADN_REPLY, "Auth/Device Neg Reply"},
+ { HSCSI_OPCODE_DISCONNECT, "Disconnect Request"},
+ { HSCSI_OPCODE_ACK_SNR, "Flow Control Setup/Ack Request"},
+ { HSCSI_OPCODE_ACK_REPLY, "Flow Control Ack Reply"},
+ { 0, NULL}
+};
+
+#define OPCODE_MASK 0x7F
+
+static void
+dissect_hyperscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint hs_hdr1, hs_hdr2, hs_hdr3;
+ guint8 hs_res;
+ guint16 hs_tagno;
+ guint16 hs_fragno;
+ gint offset = 0;
+ proto_tree *hs_hdr_tree, *hs_pdu_tree;
+ proto_tree *hs_tree = NULL;
+ proto_item *ti;
+ guint8 hs_cmd, hs_ver;
+ char *opcode_str;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "HYPERSCSI");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_hyperscsi, tvb, offset, -1, FALSE);
+ hs_tree = proto_item_add_subtree(ti, ett_hyperscsi);
+ }
+
+ hs_hdr1 = tvb_get_guint8(tvb, offset);
+ offset++;
+ hs_hdr2 = tvb_get_guint8(tvb, offset);
+ offset++;
+ hs_hdr3 = tvb_get_guint8(tvb, offset);
+ offset++;
+
+ hs_res = hs_hdr1 >> 4;
+ hs_tagno = ((hs_hdr1 & 0x0F) << 5 ) | (hs_hdr2 >> 3);
+ hs_fragno = ((hs_hdr2 &0X03) << 8 ) | hs_hdr3;
+
+ /*
+ * Add the header ... three bytes
+ */
+
+ if (tree) {
+ ti = proto_tree_add_text(hs_tree, tvb, 0, 3, "HyperSCSI Header");
+ hs_hdr_tree = proto_item_add_subtree(ti, ett_hs_hdr);
+
+ /*
+ * Now, add the header items
+ */
+
+ proto_tree_add_uint(hs_hdr_tree, hf_hs_res, tvb, 0, 1, hs_res);
+ proto_tree_add_uint(hs_hdr_tree, hf_hs_tagno, tvb, 0, 2, hs_tagno);
+ proto_tree_add_item(hs_hdr_tree, hf_hs_lastfrag, tvb, 1, 1, FALSE);
+ proto_tree_add_uint(hs_hdr_tree, hf_hs_fragno, tvb, 1, 2, hs_fragno);
+
+ }
+
+ /*
+ * Now, add the PDU
+ */
+
+ hs_ver = tvb_get_guint8(tvb, offset++);
+
+ hs_cmd = tvb_get_guint8(tvb, offset++);
+
+ hs_cmd &= OPCODE_MASK;
+
+ opcode_str = match_strval(hs_cmd, hscsi_opcodes);
+
+ if (!opcode_str)
+ opcode_str = "Unknown HyperSCSI Request or Response";
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, (char *)opcode_str);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_text(hs_tree, tvb, 3, -1, "HyperSCSI PDU");
+ hs_pdu_tree = proto_item_add_subtree(ti, ett_hs_pdu);
+
+ proto_tree_add_uint(hs_pdu_tree, hf_hs_ver, tvb, 3, 1, hs_ver);
+
+ proto_tree_add_uint_format(hs_pdu_tree, hf_hs_cmd, tvb, 4, 1, hs_cmd, "HyperSCSI Command: %s", opcode_str);
+ }
+
+}
+
+void
+proto_register_hyperscsi(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_hs_res,
+ { "Reserved", "hyperscsi.reserved", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_hs_tagno,
+ { "Tag No", "hyperscsi.tagno", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_hs_lastfrag,
+ { "Last Fragment", "hyperscsi.lastfrag", FT_BOOLEAN, 8, TFS(&tfs_lastfrag), 0x04, "", HFILL}},
+
+ { &hf_hs_fragno,
+ { "Fragment No", "hyperscsi.fragno", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_hs_ver,
+ { "HyperSCSI Version", "hyperscsi.version", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+
+ { &hf_hs_cmd,
+ { "HyperSCSI Command", "hyperscsi.cmd", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_hyperscsi,
+ &ett_hs_hdr,
+ &ett_hs_pdu,
+ };
+
+ proto_hyperscsi = proto_register_protocol("HyperSCSI", "HyperSCSI", "hyperscsi");
+ proto_register_field_array(proto_hyperscsi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("hyperscsi", dissect_hyperscsi, proto_hyperscsi);
+}
+
+#define ETHERTYPE_HYPERSCSI 0x889A
+
+void
+proto_reg_handoff_hyperscsi(void)
+{
+ dissector_handle_t hs_handle;
+
+ hs_handle = find_dissector("hyperscsi");
+ dissector_add("ethertype", ETHERTYPE_HYPERSCSI, hs_handle);
+
+}
diff --git a/epan/dissectors/packet-iapp.c b/epan/dissectors/packet-iapp.c
new file mode 100644
index 0000000000..4ec7ad94dd
--- /dev/null
+++ b/epan/dissectors/packet-iapp.c
@@ -0,0 +1,554 @@
+/* packet-iapp.c
+ * Routines for IAPP dissection
+ * Copyright 2002, Alfred Arnold <aarnold@elsa.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "oui.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_iapp = -1;
+static int hf_iapp_version = -1;
+static int hf_iapp_type = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_iapp = -1;
+static gint ett_iapp_pdu = -1;
+static gint ett_iapp_cap = -1;
+static gint ett_iapp_auth = -1;
+
+#define UDP_PORT_IAPP 2313
+
+#define IAPP_ANNOUNCE_REQUEST 0
+#define IAPP_ANNOUNCE_RESPONSE 1
+#define IAPP_HANDOVER_REQUEST 2
+#define IAPP_HANDOVER_RESPONSE 3
+
+#define IAPP_PDU_SSID 0
+#define IAPP_PDU_BSSID 1
+#define IAPP_PDU_OLDBSSID 2
+#define IAPP_PDU_MSADDR 3
+#define IAPP_PDU_CAPABILITY 4
+#define IAPP_PDU_ANNOUNCEINT 5
+#define IAPP_PDU_HOTIMEOUT 6
+#define IAPP_PDU_MESSAGEID 7
+#define IAPP_PDU_PHYTYPE 0x10
+#define IAPP_PDU_REGDOMAIN 0x11
+#define IAPP_PDU_CHANNEL 0x12
+#define IAPP_PDU_BEACONINT 0x13
+#define IAPP_PDU_OUIIDENT 0x80
+#define IAPP_PDU_AUTHINFO 0x81
+
+#define IAPP_CAP_FORWARDING 0x40
+#define IAPP_CAP_WEP 0x20
+
+#define IAPP_PHY_PROP 0x00
+#define IAPP_PHY_FHSS 0x01
+#define IAPP_PHY_DSSS 0x02
+#define IAPP_PHY_IR 0x03
+#define IAPP_PHY_OFDM 0x04
+
+#define IAPP_DOM_FCC 0x10
+#define IAPP_DOM_IC 0x20
+#define IAPP_DOM_ETSI 0x30
+#define IAPP_DOM_SPAIN 0x31
+#define IAPP_DOM_FRANCE 0x32
+#define IAPP_DOM_MKK 0x40
+
+#define IAPP_AUTH_STATUS 0x01
+#define IAPP_AUTH_USERNAME 0x02
+#define IAPP_AUTH_PROVNAME 0x03
+#define IAPP_AUTH_RXPKTS 0x04
+#define IAPP_AUTH_TXPKTS 0x05
+#define IAPP_AUTH_RXBYTES 0x06
+#define IAPP_AUTH_TXBYTES 0x07
+#define IAPP_AUTH_LOGINTIME 0x08
+#define IAPP_AUTH_TIMELIMIT 0x09
+#define IAPP_AUTH_VOLLIMIT 0x0a
+#define IAPP_AUTH_ACCCYCLE 0x0b
+#define IAPP_AUTH_RXGWORDS 0x0c
+#define IAPP_AUTH_TXGWORDS 0x0d
+#define IAPP_AUTH_IPADDR 0x0e
+#define IAPP_AUTH_TRAILER 0xff
+
+
+typedef struct _e_iapphdr {
+ guint8 ia_version;
+ guint8 ia_type;
+} e_iapphdr;
+
+typedef struct _e_pduhdr {
+ guint8 pdu_type;
+ guint8 pdu_len_h;
+ guint8 pdu_len_l;
+} e_pduhdr;
+
+static value_string iapp_vals[] = {
+ {IAPP_ANNOUNCE_REQUEST, "Announce Request"},
+ {IAPP_ANNOUNCE_RESPONSE, "Announce Response"},
+ {IAPP_HANDOVER_REQUEST, "Handover Request"},
+ {IAPP_HANDOVER_RESPONSE, "Handover Response"},
+ {0, NULL}};
+
+static value_string iapp_pdu_type_vals[] = {
+ {IAPP_PDU_SSID, "Network Name"},
+ {IAPP_PDU_BSSID, "BSSID"},
+ {IAPP_PDU_OLDBSSID, "Old BSSID"},
+ {IAPP_PDU_MSADDR, "Mobile Station Address"},
+ {IAPP_PDU_CAPABILITY, "Capabilities"},
+ {IAPP_PDU_ANNOUNCEINT, "Announce Interval"},
+ {IAPP_PDU_HOTIMEOUT, "Handover Timeout"},
+ {IAPP_PDU_MESSAGEID, "Message ID"},
+ {IAPP_PDU_PHYTYPE, "PHY Type"},
+ {IAPP_PDU_REGDOMAIN, "Regulatory Domain"},
+ {IAPP_PDU_CHANNEL, "Radio Channel"},
+ {IAPP_PDU_BEACONINT, "Beacon Interval"},
+ {IAPP_PDU_OUIIDENT, "OUI Identifier"},
+ {IAPP_PDU_AUTHINFO, "ELSA Authentication Info"},
+ {0, NULL}};
+
+static value_string iapp_cap_vals[] = {
+ {IAPP_CAP_FORWARDING, "Forwarding"},
+ {IAPP_CAP_WEP, "WEP"},
+ {0, NULL}};
+
+static value_string iapp_phy_vals[] = {
+ {IAPP_PHY_PROP, "Proprietary"},
+ {IAPP_PHY_FHSS, "FHSS"},
+ {IAPP_PHY_DSSS, "DSSS"},
+ {IAPP_PHY_IR, "Infrared"},
+ {IAPP_PHY_OFDM, "OFDM"},
+ {0, NULL}};
+
+static value_string iapp_dom_vals[] = {
+ {IAPP_DOM_FCC, "FCC (USA)"},
+ {IAPP_DOM_IC, "IC (Canada)"},
+ {IAPP_DOM_ETSI, "ETSI (Europe)"},
+ {IAPP_DOM_SPAIN, "Spain"},
+ {IAPP_DOM_FRANCE, "France"},
+ {IAPP_DOM_MKK, "MKK (Japan)"},
+ {0, NULL}};
+
+static value_string iapp_auth_type_vals[] = {
+ {IAPP_AUTH_STATUS, "Status"},
+ {IAPP_AUTH_USERNAME, "User Name"},
+ {IAPP_AUTH_PROVNAME, "Provider Name"},
+ {IAPP_AUTH_RXPKTS, "Received Packets"},
+ {IAPP_AUTH_TXPKTS, "Transmitted Packets"},
+ {IAPP_AUTH_RXBYTES, "Received Octets"},
+ {IAPP_AUTH_TXBYTES, "Transmitted Octets"},
+ {IAPP_AUTH_LOGINTIME, "Session Time"},
+ {IAPP_AUTH_TIMELIMIT, "Time Limit"},
+ {IAPP_AUTH_VOLLIMIT, "Volume Limit"},
+ {IAPP_AUTH_ACCCYCLE, "Accounting Cycle"},
+ {IAPP_AUTH_TRAILER, "Authenticator"},
+ {IAPP_AUTH_RXGWORDS, "Received Gigawords"},
+ {IAPP_AUTH_TXGWORDS, "Transmitted Gigawords"},
+ {IAPP_AUTH_IPADDR, "Client IP Address"},
+ {0, NULL}};
+
+
+static gchar textbuffer[2000];
+
+static gchar*
+iaconvertbufftostr(gchar *dest, tvbuff_t *tvb, int offset, int length)
+{
+/*converts the raw buffer into printable text */
+ guint32 i;
+ guint32 totlen=0;
+ const guint8 *pd = tvb_get_ptr(tvb, offset, length);
+
+ dest[0]='"';
+ dest[1]=0;
+ totlen=1;
+ for (i=0; i < (guint32)length; i++)
+ {
+ if( isalnum((int)pd[i])||ispunct((int)pd[i])
+ ||((int)pd[i]==' ')) {
+ dest[totlen]=(gchar)pd[i];
+ totlen++;
+ }
+ else
+ {
+ sprintf(&(dest[totlen]), "\\%03o", pd[i]);
+ totlen=totlen+strlen(&(dest[totlen]));
+ }
+ }
+ dest[totlen]='"';
+ dest[totlen+1]=0;
+ return dest;
+}
+
+/* dissect a capability bit field */
+
+static void dissect_caps(proto_item *pitem, tvbuff_t *tvb, int offset)
+{
+ proto_tree *captree;
+ int bit, val, z, thisbit;
+ gchar *strval, bitval[20];
+
+ captree = proto_item_add_subtree(pitem, ett_iapp_cap);
+ val = tvb_get_guint8(tvb, offset + 3);
+
+ bitval[8] = '\0';
+ for (bit = 7; bit >= 0; bit--)
+ {
+ strval = match_strval(1 << bit, iapp_cap_vals);
+ if (strval)
+ {
+ thisbit = (val & (1 << bit)) ? 1 : 0;
+ for (z = 0; z < 7; z++)
+ if (z == 7 - bit)
+ bitval[z] = thisbit + '0';
+ else
+ bitval[z] = '.';
+ proto_tree_add_text(captree, tvb, offset + 3, 1, "%s %s: %s",
+ bitval, strval, thisbit ? "Yes" : "No");
+ }
+ }
+}
+
+static gchar*
+authval_to_str(int type, int len, tvbuff_t *tvb, int offset)
+{
+ gchar *run;
+ int z, val;
+
+ run = textbuffer;
+ run += sprintf(run, "Value: ");
+
+ switch (type)
+ {
+ case IAPP_AUTH_STATUS:
+ strcpy(textbuffer, tvb_get_guint8(tvb, offset + 3) ? "Authenticated" : "Not authenticated");
+ break;
+ case IAPP_AUTH_USERNAME:
+ case IAPP_AUTH_PROVNAME:
+ iaconvertbufftostr(run, tvb, offset + 3, len);
+ break;
+ case IAPP_AUTH_RXPKTS:
+ case IAPP_AUTH_TXPKTS:
+ case IAPP_AUTH_RXBYTES:
+ case IAPP_AUTH_TXBYTES:
+ case IAPP_AUTH_RXGWORDS:
+ case IAPP_AUTH_TXGWORDS:
+ case IAPP_AUTH_VOLLIMIT:
+ val = tvb_get_ntohl(tvb, offset + 3);
+ run += sprintf(run, "%d", val);
+ break;
+ case IAPP_AUTH_LOGINTIME:
+ case IAPP_AUTH_TIMELIMIT:
+ case IAPP_AUTH_ACCCYCLE:
+ val = tvb_get_ntohl(tvb, offset + 3);
+ run += sprintf(run, "%d seconds", val);
+ break;
+ case IAPP_AUTH_IPADDR:
+ run += sprintf(run, "%d.%d.%d.%d",
+ tvb_get_guint8(tvb, offset + 3),
+ tvb_get_guint8(tvb, offset + 4),
+ tvb_get_guint8(tvb, offset + 5),
+ tvb_get_guint8(tvb, offset + 6));
+ break;
+ case IAPP_AUTH_TRAILER:
+ for (z = 0; z < len; z++)
+ run += sprintf(run, " %02x", tvb_get_guint8(tvb, offset + 3 + z));
+ break;
+ }
+
+ return textbuffer;
+}
+
+/* dissect authentication info */
+
+static void dissect_authinfo(proto_item *pitem, tvbuff_t *tvb, int offset, int sumlen)
+{
+ proto_tree *authtree;
+ e_pduhdr pduhdr;
+ gchar *authstrval, *valstr;
+ int len;
+
+ authtree = proto_item_add_subtree(pitem, ett_iapp_auth);
+
+ while (sumlen > 0)
+ {
+ tvb_memcpy(tvb, (guint8 *)&pduhdr, offset, sizeof(e_pduhdr));
+ len = (((int)pduhdr.pdu_len_h) << 8) + pduhdr.pdu_len_l;
+
+ authstrval = val_to_str(pduhdr.pdu_type, iapp_auth_type_vals,
+ "Unknown PDU Type");
+ valstr = authval_to_str(pduhdr.pdu_type, len, tvb, offset);
+ proto_tree_add_text(authtree, tvb, offset, len + 3, "%s(%d) %s",
+ authstrval, pduhdr.pdu_type, valstr);
+
+ sumlen -= (len + 3);
+ offset += (len + 3);
+ }
+}
+
+/* get displayable values of PDU contents */
+
+static int is_fhss = 0;
+
+static gchar*
+pduval_to_str(int type, int len, tvbuff_t *tvb, int offset)
+{
+ gchar *run;
+ const guint8 *mac;
+ int z, val;
+ gchar *strval;
+
+ run = textbuffer;
+ run += sprintf(run, "Value: ");
+
+ switch (type)
+ {
+ case IAPP_PDU_SSID:
+ iaconvertbufftostr(run, tvb, offset + 3, len);
+ break;
+ case IAPP_PDU_BSSID:
+ case IAPP_PDU_OLDBSSID:
+ case IAPP_PDU_MSADDR:
+ mac = tvb_get_ptr(tvb, offset + 3, len);
+ for (z = 0; z < len; z++)
+ run += sprintf(run, "%s%02x", z ? ":" : "", mac[z]);
+ break;
+ case IAPP_PDU_CAPABILITY:
+ {
+ int mask, first = 1;
+
+ val = tvb_get_guint8(tvb, offset + 3);
+ run += sprintf(run, "%02x (", val);
+ for (mask = 0x80; mask; mask >>= 1)
+ if (val & mask)
+ {
+ strval = match_strval(mask, iapp_cap_vals);
+ if (strval)
+ {
+ if (!first)
+ run += sprintf(run, " ");
+ run += sprintf(run, strval);
+ }
+ }
+ run += sprintf(run, ")");
+ break;
+ }
+ case IAPP_PDU_ANNOUNCEINT:
+ val = tvb_get_ntohs(tvb, offset + 3);
+ run += sprintf(run, "%d seconds", val);
+ break;
+ case IAPP_PDU_HOTIMEOUT:
+ case IAPP_PDU_BEACONINT:
+ val = tvb_get_ntohs(tvb, offset + 3);
+ run += sprintf(run, "%d Kus", val);
+ break;
+ case IAPP_PDU_MESSAGEID:
+ val = tvb_get_ntohs(tvb, offset + 3);
+ run += sprintf(run, "%d", val);
+ break;
+ case IAPP_PDU_PHYTYPE:
+ val = tvb_get_guint8(tvb, offset + 3);
+ strval = val_to_str(val, iapp_phy_vals, "Unknown");
+ run += sprintf(run, strval);
+ is_fhss = (val == IAPP_PHY_FHSS);
+ break;
+ case IAPP_PDU_REGDOMAIN:
+ val = tvb_get_guint8(tvb, offset + 3);
+ strval = val_to_str(val, iapp_dom_vals, "Unknown");
+ run += sprintf(run, strval);
+ break;
+ case IAPP_PDU_CHANNEL:
+ val = tvb_get_guint8(tvb, offset + 3);
+ if (is_fhss)
+ run += sprintf(run, "Pattern set %d, sequence %d",
+ ((val >> 6) & 3) + 1, (val & 31) + 1);
+ else
+ run += sprintf(run, "%d", val);
+ break;
+ case IAPP_PDU_OUIIDENT:
+ for (val = z = 0; z < 3; z++)
+ val = (val << 8) | tvb_get_guint8(tvb, offset + 3 + z);
+ strval = val_to_str(val, oui_vals, "Unknown");
+ run += sprintf(run, strval);
+ break;
+ }
+
+ return textbuffer;
+}
+
+/* code to dissect a list of PDUs */
+
+static void
+dissect_pdus(tvbuff_t *tvb, int offset, proto_tree *pdutree, int pdulen)
+{
+ e_pduhdr pduhdr;
+ int len;
+ gchar *pdustrval, *valstr;
+ proto_item *ti;
+
+ if (!pdulen)
+ {
+ proto_tree_add_text(pdutree, tvb, offset, 0, "No PDUs found");
+ return;
+ }
+
+ while (pdulen > 0)
+ {
+ tvb_memcpy(tvb, (guint8 *)&pduhdr, offset, sizeof(e_pduhdr));
+ len = (((int)pduhdr.pdu_len_h) << 8) + pduhdr.pdu_len_l;
+
+ pdustrval = val_to_str(pduhdr.pdu_type, iapp_pdu_type_vals,
+ "Unknown PDU Type");
+ valstr = pduval_to_str(pduhdr.pdu_type, len, tvb, offset);
+ ti = proto_tree_add_text(pdutree, tvb, offset, len + 3, "%s(%d) %s",
+ pdustrval, pduhdr.pdu_type, valstr);
+
+ if (pduhdr.pdu_type == IAPP_PDU_CAPABILITY)
+ dissect_caps(ti, tvb, offset);
+
+ if (pduhdr.pdu_type == IAPP_PDU_AUTHINFO)
+ dissect_authinfo(ti, tvb, offset + 3, len);
+
+ pdulen -= (len + 3);
+ offset += (len + 3);
+ }
+}
+
+/* code to dissect an IAPP packet */
+static void
+dissect_iapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti, *pdutf;
+ proto_tree *iapp_tree, *pdutree;
+ e_iapphdr ih;
+ int ia_version;
+ int ia_type;
+ gchar *codestrval;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAPP");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb, (guint8 *)&ih, 0, sizeof(e_iapphdr));
+
+ ia_version = (int)ih.ia_version;
+ ia_type = (int)ih.ia_type;
+ codestrval = val_to_str(ia_type, iapp_vals, "Unknown Packet");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s(%d) (version=%d)",
+ codestrval, ia_type, ia_version);
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_iapp, tvb, 0, -1, FALSE);
+ iapp_tree = proto_item_add_subtree(ti, ett_iapp);
+
+ /* common header for all IAPP frames */
+
+ proto_tree_add_uint(iapp_tree, hf_iapp_version, tvb, 0, 1,
+ ih.ia_version);
+ proto_tree_add_uint_format(iapp_tree, hf_iapp_type, tvb, 1, 1,
+ ih.ia_type, "Type: %s(%d)", codestrval, ia_type);
+
+ pdutf = proto_tree_add_text(iapp_tree, tvb, 2, -1,
+ "Protocol data units");
+ pdutree = proto_item_add_subtree(pdutf, ett_iapp_pdu);
+
+ if (pdutree)
+ {
+ dissect_pdus(tvb, 2, pdutree,
+ tvb_length_remaining(tvb, 2));
+ }
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_iapp(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_iapp_version,
+ { "Version", "iapp.version", FT_UINT8, BASE_DEC, NULL, 0x00, "", HFILL }
+ },
+ { &hf_iapp_type,
+ { "type", "iapp.type", FT_UINT8, BASE_DEC, NULL, 0x00, "", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_iapp,
+ &ett_iapp_pdu,
+ &ett_iapp_cap,
+ &ett_iapp_auth
+ };
+
+/* Register the protocol name and description */
+ proto_iapp = proto_register_protocol("Inter-Access-Point Protocol",
+ "IAPP", "iapp");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_iapp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_iapp(void)
+{
+ dissector_handle_t iapp_handle;
+
+ iapp_handle = create_dissector_handle(dissect_iapp, proto_iapp);
+ dissector_add("udp.port", UDP_PORT_IAPP, iapp_handle);
+}
diff --git a/epan/dissectors/packet-iax2.c b/epan/dissectors/packet-iax2.c
new file mode 100644
index 0000000000..6277a1922a
--- /dev/null
+++ b/epan/dissectors/packet-iax2.c
@@ -0,0 +1,1855 @@
+/*
+ * packet-iax2.c
+ *
+ * Routines for IAX2 packet disassembly
+ * By Alastair Maw <asterisk@almaw.com>
+ * Copyright 2003 Alastair Maw
+ *
+ * IAX2 is a VoIP protocol for the open source PBX Asterisk. Please see
+ * http://www.asterisk.org for more information.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details. You
+ * should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/circuit.h>
+#include <epan/packet.h>
+#include <epan/to_str.h>
+
+#include "packet-iax2.h"
+#include "iax2_codec_type.h"
+
+#define IAX2_PORT 4569
+#define PROTO_TAG_IAX2 "IAX2"
+
+/* #define DEBUG_HASHING */
+
+/* Ethereal ID of the IAX2 protocol */
+static int proto_iax2 = -1;
+
+/* The following hf_* variables are used to hold the ethereal IDs of
+ * our header fields; they are filled out when we call
+ * proto_register_field_array() in proto_register_iax2()
+ */
+static int hf_iax2_packet_type = -1;
+static int hf_iax2_retransmission = -1;
+static int hf_iax2_scallno = -1;
+static int hf_iax2_dcallno = -1;
+static int hf_iax2_ts = -1;
+static int hf_iax2_minits = -1;
+static int hf_iax2_minividts = -1;
+static int hf_iax2_minividmarker = -1;
+static int hf_iax2_oseqno = -1;
+static int hf_iax2_iseqno = -1;
+static int hf_iax2_type = -1;
+static int hf_iax2_csub = -1;
+static int hf_iax2_cmd_csub = -1;
+static int hf_iax2_iax_csub = -1;
+static int hf_iax2_voice_csub = -1;
+static int hf_iax2_voice_codec = -1;
+static int hf_iax2_video_csub = -1;
+static int hf_iax2_video_codec = -1;
+static int hf_iax2_marker = -1;
+
+static int hf_iax2_cap_g723_1 = -1;
+static int hf_iax2_cap_gsm = -1;
+static int hf_iax2_cap_ulaw = -1;
+static int hf_iax2_cap_alaw = -1;
+static int hf_iax2_cap_g726 = -1;
+static int hf_iax2_cap_adpcm = -1;
+static int hf_iax2_cap_slinear = -1;
+static int hf_iax2_cap_lpc10 = -1;
+static int hf_iax2_cap_g729a = -1;
+static int hf_iax2_cap_speex = -1;
+static int hf_iax2_cap_ilbc = -1;
+static int hf_iax2_cap_jpeg = -1;
+static int hf_iax2_cap_png = -1;
+static int hf_iax2_cap_h261 = -1;
+static int hf_iax2_cap_h263 = -1;
+
+static int hf_IAX_IE_APPARENTADDR_SINFAMILY = -1;
+static int hf_IAX_IE_APPARENTADDR_SINPORT = -1;
+static int hf_IAX_IE_APPARENTADDR_SINADDR = -1;
+static int hf_IAX_IE_APPARENTADDR_SINZERO = -1;
+static int hf_IAX_IE_CALLED_NUMBER = -1;
+static int hf_IAX_IE_CALLING_NUMBER = -1;
+static int hf_IAX_IE_CALLING_ANI = -1;
+static int hf_IAX_IE_CALLING_NAME = -1;
+static int hf_IAX_IE_CALLED_CONTEXT = -1;
+static int hf_IAX_IE_USERNAME = -1;
+static int hf_IAX_IE_PASSWORD = -1;
+static int hf_IAX_IE_CAPABILITY = -1;
+static int hf_IAX_IE_FORMAT = -1;
+static int hf_IAX_IE_LANGUAGE = -1;
+static int hf_IAX_IE_VERSION = -1;
+static int hf_IAX_IE_ADSICPE = -1;
+static int hf_IAX_IE_DNID = -1;
+static int hf_IAX_IE_AUTHMETHODS = -1;
+static int hf_IAX_IE_CHALLENGE = -1;
+static int hf_IAX_IE_MD5_RESULT = -1;
+static int hf_IAX_IE_RSA_RESULT = -1;
+static int hf_IAX_IE_REFRESH = -1;
+static int hf_IAX_IE_DPSTATUS = -1;
+static int hf_IAX_IE_CALLNO = -1;
+static int hf_IAX_IE_CAUSE = -1;
+static int hf_IAX_IE_IAX_UNKNOWN = -1;
+static int hf_IAX_IE_MSGCOUNT = -1;
+static int hf_IAX_IE_AUTOANSWER = -1;
+static int hf_IAX_IE_MUSICONHOLD = -1;
+static int hf_IAX_IE_TRANSFERID = -1;
+static int hf_IAX_IE_RDNIS = -1;
+static int hf_IAX_IE_DATAFORMAT = -1;
+static int hf_IAX_IE_UNKNOWN_BYTE = -1;
+static int hf_IAX_IE_UNKNOWN_I16 = -1;
+static int hf_IAX_IE_UNKNOWN_I32 = -1;
+static int hf_IAX_IE_UNKNOWN_BYTES = -1;
+
+/* These are the ids of the subtrees that we may be creating */
+static gint ett_iax2 = -1;
+static gint ett_iax2_full_mini_subtree = -1;
+static gint ett_iax2_type = -1; /* Frame-type specific subtree */
+static gint ett_iax2_ie = -1; /* single IE */
+static gint ett_iax2_codecs = -1; /* capabilities IE */
+static gint ett_iax2_ies_apparent_addr = -1; /* apparent address IE */
+
+static dissector_handle_t data_handle;
+
+/* data-call subdissectors, AST_DATAFORMAT_* */
+static dissector_table_t iax2_dataformat_dissector_table;
+/* voice/video call subdissectors, AST_FORMAT_* */
+static dissector_table_t iax2_codec_dissector_table;
+
+/* IAX2 Full-frame types */
+static const value_string iax_frame_types[] = {
+ {0, "(0?)"},
+ {1, "DTMF"},
+ {2, "Voice"},
+ {3, "Video"},
+ {4, "Control"},
+ {5, "NULL"},
+ {6, "IAX"},
+ {7, "Text"},
+ {8, "Image"},
+ {0,NULL}
+};
+
+/* Subclasses for IAX packets */
+static const value_string iax_iax_subclasses[] = {
+ {0, "(0?)"},
+ {1, "NEW"},
+ {2, "PING"},
+ {3, "PONG"},
+ {4, "ACK"},
+ {5, "HANGUP"},
+ {6, "REJECT"},
+ {7, "ACCEPT"},
+ {8, "AUTHREQ"},
+ {9, "AUTHREP"},
+ {10, "INVAL"},
+ {11, "LAGRQ"},
+ {12, "LAGRP"},
+ {13, "REGREQ"},
+ {14, "REGAUTH"},
+ {15, "REGACK"},
+ {16, "REGREJ"},
+ {17, "REGREL"},
+ {18, "VNAK"},
+ {19, "DPREQ"},
+ {20, "DPREP"},
+ {21, "DIAL"},
+ {22, "TXREQ"},
+ {23, "TXCNT"},
+ {24, "TXACC"},
+ {25, "TXREADY"},
+ {26, "TXREL"},
+ {27, "TXREJ"},
+ {28, "QUELCH"},
+ {29, "UNQULCH"},
+ {30, "POKE"},
+ {31, "PAGE"},
+ {32, "MWI"},
+ {33, "UNSUPPORTED"},
+ {34, "TRANSFER"},
+ {0,NULL}
+};
+
+/* Subclassess for Control packets */
+static const value_string iax_cmd_subclasses[] = {
+ {0, "(0?)"},
+ {1, "HANGUP"},
+ {2, "RING"},
+ {3, "RINGING"},
+ {4, "ANSWER"},
+ {5, "BUSY"},
+ {6, "TKOFFHK"},
+ {7, "OFFHOOK"},
+ {0xFF, "stop sounds"}, /* sent by app_dial, and not much else */
+ {0,NULL}
+};
+
+/* Information elements */
+static const value_string iax_ies_type[] = {
+ {IAX_IE_CALLED_NUMBER, "Number/extension being called"},
+ {IAX_IE_CALLING_NUMBER, "Calling number"},
+ {IAX_IE_CALLING_ANI, "Calling number ANI for billing"},
+ {IAX_IE_CALLING_NAME, "Name of caller"},
+ {IAX_IE_CALLED_CONTEXT, "Context for number"},
+ {IAX_IE_USERNAME, "Username (peer or user) for authentication"},
+ {IAX_IE_PASSWORD, "Password for authentication"},
+ {IAX_IE_CAPABILITY, "Actual codec capability"},
+ {IAX_IE_FORMAT, "Desired codec format"},
+ {IAX_IE_LANGUAGE, "Desired language"},
+ {IAX_IE_VERSION, "Protocol version"},
+ {IAX_IE_ADSICPE, "CPE ADSI capability"},
+ {IAX_IE_DNID, "Originally dialed DNID"},
+ {IAX_IE_AUTHMETHODS, "Authentication method(s)"},
+ {IAX_IE_CHALLENGE, "Challenge data for MD5/RSA"},
+ {IAX_IE_MD5_RESULT, "MD5 challenge result"},
+ {IAX_IE_RSA_RESULT, "RSA challenge result"},
+ {IAX_IE_APPARENT_ADDR, "Apparent address of peer"},
+ {IAX_IE_REFRESH, "When to refresh registration"},
+ {IAX_IE_DPSTATUS, "Dialplan status"},
+ {IAX_IE_CALLNO, "Call number of peer"},
+ {IAX_IE_CAUSE, "Cause"},
+ {IAX_IE_IAX_UNKNOWN, "Unknown IAX command"},
+ {IAX_IE_MSGCOUNT, "How many messages waiting"},
+ {IAX_IE_AUTOANSWER, "Request auto-answering"},
+ {IAX_IE_MUSICONHOLD, "Request musiconhold with QUELCH"},
+ {IAX_IE_TRANSFERID, "Transfer Request Identifier"},
+ {IAX_IE_RDNIS, "Referring DNIS"},
+ {IAX_IE_PROVISIONING, "Provisioning info"},
+ {IAX_IE_AESPROVISIONING, "AES Provisioning info"},
+ {IAX_IE_DATETIME,"Date/Time"},
+ {IAX_IE_DATAFORMAT, "Data call format"},
+ {0,NULL}
+};
+
+static const value_string codec_types[] = {
+ {AST_FORMAT_G723_1, "G.723.1 compression"},
+ {AST_FORMAT_GSM, "GSM compression"},
+ {AST_FORMAT_ULAW, "Raw mu-law data (G.711)"},
+ {AST_FORMAT_ALAW, "Raw A-law data (G.711)"},
+ {AST_FORMAT_G726, "ADPCM (G.726, 32kbps)"},
+ {AST_FORMAT_ADPCM, "ADPCM (IMA)"},
+ {AST_FORMAT_SLINEAR, "Raw 16-bit Signed Linear (8000 Hz) PCM"},
+ {AST_FORMAT_LPC10, "LPC10, 180 samples/frame"},
+ {AST_FORMAT_G729A, "G.729a Audio"},
+ {AST_FORMAT_SPEEX, "SpeeX Free Compression"},
+ {AST_FORMAT_ILBC, "iLBC Free Compression"},
+ {AST_FORMAT_JPEG, "JPEG Images"},
+ {AST_FORMAT_PNG, "PNG Images"},
+ {AST_FORMAT_H261, "H.261 Video"},
+ {AST_FORMAT_H263, "H.263 Video"},
+ {0,NULL}
+};
+
+static const value_string iax_dataformats[] = {
+ {AST_DATAFORMAT_NULL, "N/A (analogue call?)"},
+ {AST_DATAFORMAT_V110, "ITU-T V.110 rate adaption"},
+ {AST_DATAFORMAT_H223_H245,"ITU-T H.223/H.245"},
+ {0,NULL}
+};
+
+typedef enum {
+ IAX2_MINI_VOICE_PACKET,
+ IAX2_FULL_PACKET,
+ IAX2_MINI_VIDEO_PACKET,
+ IAX2_META_PACKET
+} packet_type;
+
+static const value_string iax_packet_types[] = {
+ {IAX2_FULL_PACKET, "Full packet"},
+ {IAX2_MINI_VOICE_PACKET, "Mini voice packet"},
+ {IAX2_MINI_VIDEO_PACKET, "Mini video packet"},
+ {IAX2_META_PACKET, "Meta packet"},
+ {0,NULL}
+};
+
+
+/* ************************************************************************* */
+
+/* In order to track IAX calls, we have a hash table which maps
+ * {addr,port type,port,call} to a unique circuit id.
+ *
+ * Each call has two such circuits associated with it (a forward and a
+ * reverse circuit, where 'forward' is defined as the direction the NEW
+ * packet went in), and we maintain an iax_call_data structure for each
+ * call, attached to both circuits with circuit_add_proto_data.
+ *
+ * Because {addr,port type,port,call} quadruplets can be reused
+ * (Asterisk reuses call numbers), circuit ids aren't unique to
+ * individual calls and we treat NEW packets somewhat specially. When we
+ * get such a packet, we see if there are any calls with a matching
+ * circuit id, and make sure that its circuits are marked as ended
+ * before that packet.
+ *
+ * A second complication is that we only know one quadruplet at the time
+ * the NEW packet is processed: there is therefore cunningness in
+ * iax_lookup_circuit_details() to look for replies to NEW packets and
+ * create the reverse circuit.
+ */
+
+
+/* start with a hash of {addr,port type,port,call}->{id} */
+
+typedef struct {
+ address addr;
+ port_type ptype;
+ guint32 port;
+ guint32 callno;
+} iax_circuit_key;
+
+/* tables */
+static GHashTable *iax_circuit_hashtab = NULL;
+static GMemChunk *iax_circuit_keys = NULL;
+static GMemChunk *iax_circuit_vals = NULL;
+static guint circuitcount = 0;
+
+/* the number of keys and values to reserve space for in each memory chunk.
+ We assume we won't be tracking many calls at once so this is quite low.
+*/
+#define IAX_INIT_PACKET_COUNT 10
+
+#ifdef DEBUG_HASHING
+static gchar *key_to_str( const iax_circuit_key *key )
+{
+ static int i=0;
+ static gchar *strp, str[3][80];
+
+ i++;
+ if(i>=3){
+ i=0;
+ }
+ strp=str[i];
+
+ /* why doesn't address_to_str take a const pointer?
+ cast the warnings into oblivion. */
+
+ sprintf(strp,"{%s:%i,%i}",
+ address_to_str((address *)&key->addr),
+ key->port,
+ key->callno);
+ return strp;
+}
+#endif
+
+/* Hash Functions */
+static gint iax_circuit_equal(gconstpointer v, gconstpointer w)
+{
+ const iax_circuit_key *v1 = (const iax_circuit_key *)v;
+ const iax_circuit_key *v2 = (const iax_circuit_key *)w;
+ gint result;
+
+ result = ( ADDRESSES_EQUAL(&(v1->addr), &(v2->addr)) &&
+ v1->ptype == v2->ptype &&
+ v1->port == v2->port &&
+ v1->callno== v2->callno);
+#ifdef DEBUG_HASHING
+ g_message( "+++ Comparing for equality: %s, %s: %u",key_to_str(v1), key_to_str(v2), result);
+#endif
+
+ return result;;
+}
+
+static guint iax_circuit_hash (gconstpointer v)
+{
+ const iax_circuit_key *key = (const iax_circuit_key *)v;
+ guint hash_val;
+ int i;
+
+ hash_val = 0;
+ for (i = 0; i < key->addr.len; i++)
+ hash_val += (guint)(key->addr.data[i]);
+
+ hash_val += (guint)(key->ptype);
+ hash_val += (guint)(key->port);
+ hash_val += (guint)(key->callno);
+
+#ifdef DEBUG_HASHING
+ g_message( "+++ Hashing key: %s, result %#x", key_to_str(key), hash_val );
+#endif
+
+ return (guint) hash_val;
+}
+
+static guint iax_circuit_lookup(const address *address,
+ port_type ptype,
+ guint32 port,
+ guint32 callno)
+{
+ iax_circuit_key key;
+ guint32 *circuit_id_p;
+
+ key.addr = *address;
+ key.ptype = ptype;
+ key.port = port;
+ key.callno = callno;
+
+#ifdef DEBUG_HASHING
+ g_message( "+++ looking up key: %s", key_to_str(&key));
+#endif
+
+ circuit_id_p = g_hash_table_lookup( iax_circuit_hashtab, &key);
+ if( ! circuit_id_p ) {
+ iax_circuit_key *new_key;
+
+ new_key = g_mem_chunk_alloc(iax_circuit_keys);
+ COPY_ADDRESS(&new_key->addr, address);
+ new_key->ptype = ptype;
+ new_key->port = port;
+ new_key->callno = callno;
+
+ circuit_id_p = g_mem_chunk_alloc(iax_circuit_vals);
+ *circuit_id_p = ++circuitcount;
+
+ g_hash_table_insert(iax_circuit_hashtab, new_key, circuit_id_p);
+ }
+
+#ifdef DEBUG_HASHING
+ g_message( "+++ Id: %u", *circuit_id_p );
+#endif
+
+ return *circuit_id_p;
+}
+
+
+/* ************************************************************************* */
+
+
+/* This is our per-call data structure, which is attached to both the
+ * forward and reverse circuits.
+ */
+typedef struct iax_call_data {
+ /* For this data, src and dst are relative to the original direction under
+ which this call is stored. Obviously if the reversed flag is set true by
+ iax_find_call, src and dst are reversed relative to the direction the
+ actual source and destination of the data.
+
+ if the codec changes mid-call, we update it here; because we store a codec
+ number with each packet too, we handle going back to earlier packets
+ without problem.
+ */
+
+ iax_dataformat_t dataformat;
+ guint32 src_codec, dst_codec;
+ guint32 src_vformat, dst_vformat;
+
+ guint forward_circuit_id;
+ guint reverse_circuit_id;
+
+ guint callno;
+} iax_call_data;
+
+static guint callcount = 0;
+
+static GMemChunk *iax_call_datas = NULL;
+
+static void iax_init_hash( void )
+{
+ if (iax_circuit_hashtab)
+ g_hash_table_destroy(iax_circuit_hashtab);
+
+ if (iax_circuit_keys)
+ g_mem_chunk_destroy(iax_circuit_keys);
+ if (iax_circuit_vals)
+ g_mem_chunk_destroy(iax_circuit_vals);
+ if (iax_call_datas)
+ g_mem_chunk_destroy(iax_call_datas);
+
+ iax_circuit_hashtab = g_hash_table_new(iax_circuit_hash, iax_circuit_equal);
+
+ iax_circuit_keys = g_mem_chunk_create(iax_circuit_key,
+ 2*IAX_INIT_PACKET_COUNT,
+ G_ALLOC_ONLY);
+ iax_circuit_vals = g_mem_chunk_create(iax_circuit_key,
+ 2*IAX_INIT_PACKET_COUNT,
+ G_ALLOC_ONLY);
+
+ iax_call_datas = g_mem_chunk_create(iax_call_data,
+ IAX_INIT_PACKET_COUNT,
+ G_ALLOC_ONLY);
+ circuitcount = 0;
+ callcount = 0;
+}
+
+
+static iax_call_data *iax_lookup_circuit_details_from_dest( guint src_circuit_id,
+ guint dst_circuit_id,
+ guint framenum,
+ gboolean *reversed_p,
+ circuit_t **circuit_p)
+{
+ circuit_t *dst_circuit;
+ iax_call_data * iax_call;
+ gboolean reversed = FALSE;
+
+ dst_circuit = find_circuit( CT_IAX2,
+ dst_circuit_id,
+ framenum );
+
+ if( !dst_circuit ) {
+#ifdef DEBUG_HASHING
+ g_message( "++ destination circuit not found, must have missed NEW packet" );
+#endif
+ return NULL;
+ }
+
+#ifdef DEBUG_HASHING
+ g_message( "++ found destination circuit" );
+#endif
+
+ iax_call = (iax_call_data *)circuit_get_proto_data(dst_circuit,proto_iax2);
+
+ /* there's no way we can create a CT_IAX2 circuit without adding
+ iax call data to it; assert this */
+ g_assert(iax_call);
+
+ if( dst_circuit_id == iax_call -> forward_circuit_id ) {
+#ifdef DEBUG_HASHING
+ g_message( "++ destination circuit matches forward_circuit_id of call, "
+ "therefore packet is reversed" );
+#endif
+
+ reversed = TRUE;
+
+ if( iax_call -> reverse_circuit_id == 0 ) {
+ circuit_t *rev_circuit;
+
+ /* we are going in the reverse direction, and this call
+ doesn't have a reverse circuit associated with it.
+ create one now. */
+#ifdef DEBUG_HASHING
+ g_message( "++ reverse_circuit_id of call is zero, need to create a "
+ "new reverse circuit for this call" );
+#endif
+
+ iax_call -> reverse_circuit_id = src_circuit_id;
+ rev_circuit = circuit_new(CT_IAX2,
+ src_circuit_id,
+ framenum );
+ circuit_add_proto_data(rev_circuit, proto_iax2, iax_call);
+
+ /* we should have already set up a subdissector for the forward
+ * circuit. we'll need to copy it to the reverse circuit. */
+ circuit_set_dissector(rev_circuit, circuit_get_dissector(dst_circuit));
+#ifdef DEBUG_HASHING
+ g_message( "++ done" );
+#endif
+ } else if( iax_call -> reverse_circuit_id != src_circuit_id ) {
+ g_warning( "IAX Packet %u from circuit ids %u->%u"
+ "conflicts with earlier call with circuit ids %u->%u",
+ framenum,
+ src_circuit_id,dst_circuit_id,
+ iax_call->forward_circuit_id,
+ iax_call->reverse_circuit_id);
+ return NULL;
+ }
+ } else if ( dst_circuit_id == iax_call -> reverse_circuit_id ) {
+#ifdef DEBUG_HASHING
+ g_message( "++ destination circuit matches reverse_circuit_id of call, "
+ "therefore packet is forward" );
+#endif
+
+ reversed = FALSE;
+ if( iax_call -> forward_circuit_id != src_circuit_id ) {
+ g_warning( "IAX Packet %u from circuit ids %u->%u"
+ "conflicts with earlier call with circuit ids %u->%u",
+ framenum,
+ src_circuit_id,dst_circuit_id,
+ iax_call->forward_circuit_id,
+ iax_call->reverse_circuit_id);
+ return NULL;
+ }
+ } else {
+ g_assert_not_reached();
+ }
+
+
+ if( circuit_p ) {
+ /* by now we've created a new circuit if one was necessary, or
+ bailed out if it looks like a conflict, and we should be able
+ to look up the source circuit without issue */
+ *circuit_p = find_circuit( CT_IAX2,
+ src_circuit_id,
+ framenum );
+ g_assert(*circuit_p);
+ }
+
+ if( reversed_p )
+ *reversed_p = reversed;
+
+ return iax_call;
+}
+
+
+ /* looks up a circuit_t and an iax_call for this packet */
+static iax_call_data *iax_lookup_circuit_details( packet_info *pinfo,
+ guint32 scallno,
+ guint32 dcallno,
+ gboolean *reversed_p,
+ circuit_t **circuit_p)
+{
+ gboolean reversed = FALSE;
+ iax_call_data *iax_call = NULL;
+ guint src_circuit_id;
+ circuit_t *src_circuit = NULL;
+
+#ifdef DEBUG_HASHING
+ g_message( "++ iax_lookup_circuit_details: Looking up circuit for frame %u, "
+ "from {%s:%u:%u} to {%s:%u:%u}", pinfo->fd->num,
+ address_to_str(&pinfo->src),pinfo->srcport,scallno,
+ address_to_str(&pinfo->dst),pinfo->destport,dcallno);
+#endif
+
+
+ src_circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
+ pinfo->srcport,scallno);
+
+
+ /* the most reliable indicator of call is the destination callno, if
+ we have one */
+ if( dcallno != 0 ) {
+ guint dst_circuit_id;
+#ifdef DEBUG_HASHING
+ g_message( "++ dcallno non-zero, looking up destination circuit" );
+#endif
+
+ dst_circuit_id = iax_circuit_lookup(&pinfo->dst,pinfo->ptype,
+ pinfo->destport,dcallno);
+
+ iax_call = iax_lookup_circuit_details_from_dest(src_circuit_id, dst_circuit_id, pinfo->fd->num, &reversed, &src_circuit);
+ } else {
+
+ /* in all other circumstances, the source circuit should already
+ * exist: its absense indicates that we missed the all-important NEW
+ * packet.
+ */
+
+ src_circuit = find_circuit( CT_IAX2,
+ src_circuit_id,
+ pinfo->fd->num );
+
+ if( src_circuit ) {
+ iax_call = (iax_call_data *)circuit_get_proto_data(src_circuit,proto_iax2);
+
+ /* there's no way we can create a CT_IAX2 circuit without adding
+ iax call data to it; assert this */
+ g_assert(iax_call);
+
+ if( src_circuit_id == iax_call -> forward_circuit_id )
+ reversed = FALSE;
+ else if ( src_circuit_id == iax_call -> reverse_circuit_id )
+ reversed = TRUE;
+ else {
+ /* there's also no way we can attach an iax_call_data to a circuit
+ without the circuit being either the forward or reverse circuit
+ for that call; assert this too.
+ */
+ g_assert_not_reached();
+ }
+ }
+ }
+
+ if(src_circuit && iax_call) {
+ /* info for subdissectors. We always pass on the forward circuit,
+ * and steal the p2p_dir flag to indicate the direction */
+ pinfo -> ctype = CT_IAX2;
+ pinfo -> circuit_id = (guint32)iax_call->forward_circuit_id;
+ pinfo -> p2p_dir = reversed?P2P_DIR_RECV:P2P_DIR_SENT;
+ }
+
+ if(reversed_p)
+ *reversed_p = reversed;
+
+ if(circuit_p)
+ *circuit_p = src_circuit;
+
+#ifdef DEBUG_HASHING
+ if( iax_call ) {
+ g_message( "++ Found call for packet: id %u, reversed=%c", iax_call->callno, reversed?'1':'0' );
+ } else {
+ g_message( "++ Call not found. Must have missed the NEW packet?" );
+ }
+#endif
+
+ return iax_call;
+}
+
+
+/* handles a NEW packet by creating a new iax call and forward circuit.
+ the reverse circuit is not created until the ACK is received and
+ is created by iax_lookup_circuit_details. */
+static iax_call_data *iax_new_circuit_details( packet_info *pinfo,
+ guint32 scallno,
+ circuit_t **circuit_p)
+{
+ circuit_t *circuit;
+ iax_call_data *call;
+ guint circuit_id;
+
+#ifdef DEBUG_HASHING
+ g_message( "+ new_circuit: Handling NEW packet, frame %u", pinfo->fd->num );
+#endif
+
+ circuit_id = iax_circuit_lookup(&pinfo->src,pinfo->ptype,
+ pinfo->srcport,scallno);
+
+ circuit = circuit_new(CT_IAX2,
+ circuit_id,
+ pinfo->fd->num );
+
+
+
+ call = g_mem_chunk_alloc(iax_call_datas);
+ call -> dataformat = 0;
+ call -> src_codec = 0;
+ call -> dst_codec = 0;
+ call -> forward_circuit_id = circuit_id;
+ call -> reverse_circuit_id = 0;
+ call -> callno = ++callcount;
+
+#ifdef DEBUG_HASHING
+ g_message( "+ new_circuit: Added new circuit for new call %u", call -> callno );
+#endif
+
+ circuit_add_proto_data( circuit, proto_iax2, call );
+
+ if( circuit_p )
+ *circuit_p = circuit;
+
+ return call;
+}
+
+
+/* ************************************************************************* */
+
+/* per-packet data */
+typedef struct iax_packet_data {
+ iax_call_data *call_data;
+ guint32 codec;
+} iax_packet_data;
+
+static GMemChunk *iax_packets = NULL;
+
+static iax_packet_data *iax_new_packet_data(iax_call_data *call)
+{
+ iax_packet_data *p = g_mem_chunk_alloc(iax_packets);
+ p->call_data=call;
+ p->codec=0;
+ return p;
+}
+
+
+/* ************************************************************************* */
+
+static guint32 dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
+ guint16 scallno,
+ packet_info * pinfo,
+ proto_tree * iax2_tree,
+ proto_tree * main_tree);
+
+
+static guint32 dissect_minipacket (tvbuff_t * tvb, guint32 offset,
+ guint16 scallno,
+ packet_info * pinfo,
+ proto_tree * iax2_tree,
+ proto_tree * main_tree);
+
+static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
+ guint16 scallno,
+ packet_info * pinfo,
+ proto_tree * iax2_tree,
+ proto_tree * main_tree);
+
+static void dissect_payload(tvbuff_t *tvb, guint32 offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint32 ts, gboolean video,
+ iax_packet_data *iax_packet);
+
+
+
+static void
+dissect_iax2 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ proto_item *iax2_item = NULL;
+ proto_tree *iax2_tree = NULL;
+ proto_tree *full_mini_subtree = NULL;
+ guint32 offset = 0, len;
+ guint16 scallno = 0;
+ guint16 stmp;
+ packet_type type;
+
+ /* set up the protocol and info fields in the summary pane */
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_IAX2);
+ }
+ if (check_col (pinfo->cinfo, COL_INFO))
+ {
+ col_clear (pinfo->cinfo, COL_INFO);
+ }
+
+ /* add the 'iax2' tree to the main tree */
+ if (tree)
+ {
+ iax2_item = proto_tree_add_item (tree, proto_iax2, tvb, offset, -1, FALSE);
+ iax2_tree = proto_item_add_subtree (iax2_item, ett_iax2);
+ }
+
+ stmp = tvb_get_ntohs(tvb, offset);
+ if( stmp == 0 ) {
+ /* starting with 0x0000 indicates either a mini video packet or a 'meta'
+ * packet, whatever that means */
+ offset+=2;
+ stmp = tvb_get_ntohs(tvb, offset);
+ if( stmp & 0x8000 ) {
+ /* mini video packet */
+ type = IAX2_MINI_VIDEO_PACKET;
+ scallno = stmp & 0x7FFF;
+ offset += 2;
+ }
+ else {
+ type = IAX2_META_PACKET;
+ }
+ } else {
+ /* The source call/fullpacket flag is common to both mini and full packets */
+ scallno = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ if( scallno & 0x8000 )
+ type = IAX2_FULL_PACKET;
+ else {
+ type = IAX2_MINI_VOICE_PACKET;
+ }
+ scallno &= 0x7FFF;
+ }
+
+ if( tree ) {
+ proto_item *full_mini_base;
+
+ full_mini_base = proto_tree_add_uint(iax2_tree, hf_iax2_packet_type, tvb, 0, offset, type);
+ full_mini_subtree = proto_item_add_subtree(full_mini_base, ett_iax2_full_mini_subtree);
+
+ if( scallno != 0 )
+ proto_tree_add_item (full_mini_subtree, hf_iax2_scallno, tvb, offset-2, 2, FALSE);
+ }
+
+ switch( type ) {
+ case IAX2_FULL_PACKET:
+ len = dissect_fullpacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
+ break;
+ case IAX2_MINI_VOICE_PACKET:
+ len = dissect_minipacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
+ break;
+ case IAX2_MINI_VIDEO_PACKET:
+ len = dissect_minivideopacket( tvb, offset, scallno, pinfo, full_mini_subtree, tree );
+ break;
+ case IAX2_META_PACKET:
+ /* not implemented yet */
+ len = 0;
+ break;
+ default:
+ len = 0;
+ }
+
+ /* update the 'length' of the main IAX2 header field so that it covers just the headers,
+ not the audio data. */
+ proto_item_set_len(iax2_item, len);
+}
+
+
+/* dissect the information elements in an IAX frame. Returns the updated offset */
+static guint32 dissect_ies (tvbuff_t * tvb, guint32 offset,
+ proto_tree * iax_tree,
+ iax_call_data *iax_call_data )
+{
+ proto_tree *sockaddr_tree = NULL;
+ proto_item *sockaddr_item = 0;
+
+
+ while (offset < tvb_reported_length (tvb)) {
+
+ int ies_type = tvb_get_guint8(tvb, offset);
+ int ies_len = tvb_get_guint8(tvb, offset + 1);
+
+ if( iax_tree ) {
+ proto_item *ti;
+ proto_tree *ies_tree;
+
+ ti = proto_tree_add_text(iax_tree, tvb, offset, ies_len+2,
+ "Information Element: %s (0x%02X)",
+ val_to_str(ies_type, iax_ies_type,
+ "Unknown information element"),
+ ies_type);
+
+
+ ies_tree = proto_item_add_subtree(ti, ett_iax2_ie);
+
+ proto_tree_add_text(ies_tree, tvb, offset, 1, "IE id: %s (0x%02X)",
+ val_to_str(ies_type, iax_ies_type, "Unknown"),
+ ies_type);
+
+ proto_tree_add_text(ies_tree, tvb, offset+1, 1, "Length: %u",ies_len);
+
+
+ switch (ies_type) {
+ case IAX_IE_CALLED_NUMBER:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_CALLED_NUMBER, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_CALLING_NUMBER:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_CALLING_NUMBER,
+ tvb, offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_CALLING_ANI:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_CALLING_ANI, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_CALLING_NAME:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_CALLING_NAME, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_CALLED_CONTEXT:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_CALLED_CONTEXT,
+ tvb, offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_USERNAME:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_USERNAME, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_PASSWORD:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_PASSWORD, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_LANGUAGE:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_LANGUAGE, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_DNID:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_DNID, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_CHALLENGE:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_CHALLENGE, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_MD5_RESULT:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_MD5_RESULT, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_RSA_RESULT:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_RSA_RESULT, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_RDNIS:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_RDNIS, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_CAPABILITY:
+ {
+ proto_tree *codec_tree;
+ proto_item *codec_base;
+
+ codec_base =
+ proto_tree_add_item (ies_tree, hf_IAX_IE_CAPABILITY,
+ tvb, offset + 2, ies_len, FALSE);
+ codec_tree =
+ proto_item_add_subtree (codec_base, ett_iax2_codecs);
+
+ proto_tree_add_item(codec_tree, hf_iax2_cap_g723_1, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_gsm, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_ulaw, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_alaw, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_g726, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_adpcm, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_slinear, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_lpc10, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_g729a, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_speex, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_ilbc, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_jpeg, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_png, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_h261, tvb, offset + 2, ies_len, FALSE );
+ proto_tree_add_item(codec_tree, hf_iax2_cap_h263, tvb, offset + 2, ies_len, FALSE );
+ break;
+ }
+ case IAX_IE_FORMAT:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_FORMAT, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_VERSION:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_VERSION, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_ADSICPE:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_ADSICPE, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_AUTHMETHODS:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_AUTHMETHODS, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_APPARENT_ADDR:
+ sockaddr_item = proto_tree_add_text(ies_tree, tvb, offset + 2, 16, "Apparent Address");
+ sockaddr_tree = proto_item_add_subtree(sockaddr_item, ett_iax2_ies_apparent_addr);
+ proto_tree_add_item(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINADDR, tvb, offset + 6, 4, FALSE);
+ proto_tree_add_item(sockaddr_tree, hf_IAX_IE_APPARENTADDR_SINPORT, tvb, offset + 4, 2, FALSE);
+ break;
+ case IAX_IE_REFRESH:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_REFRESH, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_DPSTATUS:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_DPSTATUS, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_CALLNO:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_CALLNO, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_CAUSE:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_CAUSE, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_IAX_UNKNOWN:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_IAX_UNKNOWN, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_MSGCOUNT:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_MSGCOUNT, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_AUTOANSWER:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_AUTOANSWER, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_MUSICONHOLD:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_MUSICONHOLD, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+ case IAX_IE_TRANSFERID:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_TRANSFERID, tvb,
+ offset + 2, ies_len, FALSE);
+ break;
+
+ case IAX_IE_DATAFORMAT:
+ proto_tree_add_item (ies_tree, hf_IAX_IE_DATAFORMAT, tvb,
+ offset + 2, ies_len, FALSE);
+
+ if( iax_call_data )
+ iax_call_data -> dataformat = tvb_get_ntohl(tvb, offset+2);
+
+ break;
+
+ default:
+ {
+ switch(ies_len) {
+ case 1:
+ proto_tree_add_item( ies_tree, hf_IAX_IE_UNKNOWN_BYTE, tvb, offset+2, ies_len, FALSE );
+ break;
+
+ case 2:
+ proto_tree_add_item( ies_tree, hf_IAX_IE_UNKNOWN_I16, tvb, offset+2, ies_len, FALSE );
+ break;
+
+ case 4:
+ proto_tree_add_item( ies_tree, hf_IAX_IE_UNKNOWN_I32, tvb, offset+2, ies_len, FALSE );
+ break;
+
+ default:
+ proto_tree_add_item( ies_tree, hf_IAX_IE_UNKNOWN_BYTES, tvb, offset+2, ies_len, FALSE );
+ }
+ }
+ }
+ }
+ offset += ies_len + 2;
+ }
+ return offset;
+}
+
+static guint32 uncompress_subclass(guint8 csub)
+{
+ /* If the SC_LOG flag is set, return 2^csub otherwise csub */
+ if (csub & 0x80) {
+ /* special case for 'compressed' -1 */
+ if (csub == 0xff)
+ return (guint32)-1;
+ else
+ return 1 << (csub & 0x1F);
+ }
+ else
+ return (guint32)csub;
+}
+
+
+static guint32
+dissect_fullpacket (tvbuff_t * tvb, guint32 offset,
+ guint16 scallno,
+ packet_info * pinfo, proto_tree * iax2_tree,
+ proto_tree * main_tree)
+{
+ guint32 retransmission = 0;
+ guint16 dcallno;
+ guint32 ts;
+ guint8 type;
+ guint8 csub;
+ guint32 codec;
+
+ proto_tree *packet_type_tree = NULL;
+ iax_call_data *iax_call;
+ iax_packet_data *iax_packet;
+ gboolean reversed;
+ gboolean rtp_marker;
+
+ circuit_t *circuit;
+
+ /*
+ * remove the top bit for retransmission detection
+ */
+ dcallno = tvb_get_ntohs(tvb, offset);
+ retransmission = dcallno & 0x8000;
+ dcallno = dcallno & 0x7FFF;
+ ts = tvb_get_ntohl(tvb, offset+2);
+ type = tvb_get_guint8(tvb, offset + 8);
+ csub = tvb_get_guint8(tvb, offset + 9);
+
+ /* see if we've seen this packet before */
+ iax_packet = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
+ if( !iax_packet ) {
+ /* if not, find or create an iax_call info structure for this IAX session. */
+
+ if( type == AST_FRAME_IAX && csub == IAX_COMMAND_NEW ) {
+ /* NEW packets start a new call */
+ iax_call = iax_new_circuit_details(pinfo,scallno,&circuit);
+ reversed = FALSE;
+ } else {
+ iax_call = iax_lookup_circuit_details(pinfo, scallno, dcallno,
+ &reversed, &circuit);
+ }
+
+ iax_packet = iax_new_packet_data(iax_call);
+ p_add_proto_data(pinfo->fd,proto_iax2,iax_packet);
+ } else {
+ iax_call = iax_packet->call_data;
+ }
+
+ if( iax2_tree ) {
+ proto_item *packet_type_base;
+
+ proto_tree_add_item (iax2_tree, hf_iax2_dcallno, tvb, offset, 2, FALSE );
+ proto_tree_add_boolean(iax2_tree, hf_iax2_retransmission, tvb, offset, 2, FALSE );
+
+ proto_tree_add_uint (iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts);
+
+ proto_tree_add_item (iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
+ FALSE);
+
+ proto_tree_add_item (iax2_tree, hf_iax2_iseqno, tvb, offset+7, 1,
+ FALSE);
+ packet_type_base = proto_tree_add_uint (iax2_tree, hf_iax2_type, tvb,
+ offset+8, 1, type);
+
+ /* add the type-specific subtree */
+ packet_type_tree = proto_item_add_subtree (packet_type_base, ett_iax2_type);
+ }
+
+ /* add frame type to info line */
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "%s, source call# %d, timestamp %ums",
+ val_to_str (type, iax_frame_types, "Unknown (0x%02x)"),
+ scallno, ts);
+ }
+
+ switch( type ) {
+ case AST_FRAME_IAX:
+ /* add the subclass */
+ proto_tree_add_uint (packet_type_tree, hf_iax2_iax_csub, tvb,
+ offset+9, 1, csub);
+ offset += 10;
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
+ val_to_str (csub, iax_iax_subclasses, "unknown (0x%02x)"));
+
+ if (offset < tvb_reported_length (tvb)) {
+ offset += dissect_ies(tvb, offset, packet_type_tree, iax_call);
+ }
+
+ if( csub == IAX_COMMAND_NEW && circuit && iax_call ) {
+ /* if this is a data call, set up a subdissector for the circuit */
+ dissector_handle_t s;
+ s = dissector_get_port_handle(iax2_dataformat_dissector_table, iax_call -> dataformat );
+ circuit_set_dissector( circuit, s );
+ }
+ break;
+
+ case AST_FRAME_DTMF:
+ proto_tree_add_text (packet_type_tree, tvb, offset+9, 1, "DTMF digit: %c", csub);
+ offset += 10;
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " digit %c", csub );
+ break;
+
+ case AST_FRAME_CONTROL:
+ /* add the subclass */
+ proto_tree_add_uint (packet_type_tree, hf_iax2_cmd_csub, tvb,
+ offset+9, 1, csub);
+ offset += 10;
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
+ val_to_str (csub, iax_cmd_subclasses, "unknown (0x%02x)"));
+ break;
+
+ case AST_FRAME_VOICE:
+ /* add the codec */
+ iax_packet -> codec = codec = uncompress_subclass(csub);
+
+ if( packet_type_tree ) {
+ proto_tree_add_item (packet_type_tree, hf_iax2_voice_csub, tvb, offset+9, 1, FALSE);
+ proto_tree_add_uint (packet_type_tree, hf_iax2_voice_codec, tvb, offset+9, 1, codec);
+ }
+
+ offset += 10;
+
+ if( iax_call ) {
+ if( reversed ) {
+ iax_call->dst_codec = codec;
+ } else {
+ iax_call->src_codec = codec;
+ }
+ }
+
+ dissect_payload(tvb, offset, pinfo, main_tree, ts, FALSE,iax_packet);
+ break;
+
+ case AST_FRAME_VIDEO:
+ /* bit 6 of the csub is used to represent the rtp 'marker' bit */
+ rtp_marker = csub & 0x40 ? TRUE:FALSE;
+ iax_packet -> codec = codec = uncompress_subclass((guint8) (csub & ~40));
+
+ if( packet_type_tree ) {
+ proto_tree_add_item (packet_type_tree, hf_iax2_video_csub, tvb, offset+9, 1, FALSE);
+ proto_tree_add_item (packet_type_tree, hf_iax2_marker, tvb, offset+9, 1, FALSE);
+ proto_tree_add_uint (packet_type_tree, hf_iax2_video_codec, tvb, offset+9, 1, codec);
+ }
+
+ offset += 10;
+
+ if( iax_call ) {
+ if( reversed ) {
+ iax_call->dst_vformat = codec;
+ } else {
+ iax_call->src_vformat = codec;
+ }
+ }
+
+ if( rtp_marker && check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", Mark" );
+
+
+ dissect_payload(tvb, offset, pinfo, main_tree, ts, TRUE, iax_packet);
+ break;
+
+
+ default:
+ proto_tree_add_uint (packet_type_tree, hf_iax2_csub, tvb, offset+9,
+ 1, csub);
+ offset += 10;
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, " subclass %d", csub );
+ break;
+ }
+
+ return offset;
+}
+
+static iax_packet_data *iax2_get_packet_data_for_minipacket(packet_info * pinfo,
+ guint16 scallno,
+ gboolean video)
+{
+ /* see if we've seen this packet before */
+ iax_packet_data *p = (iax_packet_data *)p_get_proto_data(pinfo->fd,proto_iax2);
+
+ if( !p ) {
+ /* if not, find or create an iax_call info structure for this IAX session. */
+ gboolean reversed;
+ circuit_t *circuit;
+ iax_call_data *iax_call;
+
+ iax_call = iax_lookup_circuit_details(pinfo, scallno, 0, &reversed, &circuit);
+
+ p = iax_new_packet_data(iax_call);
+ p_add_proto_data(pinfo->fd,proto_iax2,p);
+
+ /* set the codec for this frame to be whatever the last full frame used */
+ if( video )
+ p->codec = reversed ? iax_call -> dst_vformat : iax_call -> src_vformat;
+ else
+ p->codec = reversed ? iax_call -> dst_codec : iax_call -> src_codec;
+ }
+ return p;
+}
+
+
+static guint32 dissect_minivideopacket (tvbuff_t * tvb, guint32 offset,
+ guint16 scallno, packet_info * pinfo,
+ proto_tree * iax2_tree, proto_tree *main_tree)
+{
+ guint32 ts;
+ iax_packet_data *iax_packet;
+ gboolean rtp_marker;
+
+ ts = tvb_get_ntohs(tvb, offset);
+
+ /* bit 15 of the ts is used to represent the rtp 'marker' bit */
+ rtp_marker = ts & 0x8000 ? TRUE:FALSE;
+ ts &= ~0x8000;
+
+
+ if( iax2_tree ) {
+ proto_tree_add_item (iax2_tree, hf_iax2_minividts, tvb, offset, 2, FALSE);
+ proto_tree_add_item (iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, FALSE);
+ }
+
+ offset += 2;
+
+ iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, TRUE);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_add_fstr (pinfo->cinfo, COL_INFO,
+ "Mini video packet, source call# %d, timestamp %ums%s",
+ scallno, ts, rtp_marker?", Mark":"");
+
+
+ dissect_payload(tvb, offset, pinfo, main_tree, ts, TRUE, iax_packet);
+
+ return offset;
+}
+
+static guint32
+dissect_minipacket (tvbuff_t * tvb, guint32 offset, guint16 scallno, packet_info * pinfo, proto_tree * iax2_tree,
+ proto_tree *main_tree)
+{
+ guint32 ts;
+ iax_packet_data *iax_packet;
+
+ ts = tvb_get_ntohs(tvb, offset);
+
+ iax_packet = iax2_get_packet_data_for_minipacket(pinfo, scallno, FALSE);
+
+ proto_tree_add_uint (iax2_tree, hf_iax2_minits, tvb, offset, 2,
+ ts);
+ offset += 2;
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_add_fstr (pinfo->cinfo, COL_INFO,
+ "Mini packet, source call# %d, timestamp %ums",
+ scallno, ts);
+
+
+ /* XXX fix the timestamp logic */
+ dissect_payload(tvb, offset, pinfo, main_tree, ts, FALSE, iax_packet);
+
+
+ return offset;
+}
+
+static void dissect_payload(tvbuff_t *tvb, guint32 offset,
+ packet_info *pinfo, proto_tree *tree,
+ guint32 ts, gboolean video,
+ iax_packet_data *iax_packet)
+{
+ gboolean out_of_order = FALSE;
+ tvbuff_t *sub_tvb;
+ guint32 codec = iax_packet -> codec;
+ iax_call_data *iax_call = iax_packet -> call_data;
+
+ /* keep compiler quiet */
+ ts = ts;
+
+ if( offset >= tvb_reported_length (tvb)) {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", empty frame" );
+ return;
+ }
+
+ sub_tvb = tvb_new_subset(tvb, offset, -1, -1 );
+
+ /* XXX shouldn't pass through out-of-order packets. */
+
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ if( !video && iax_call && iax_call -> dataformat != 0 ) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", data, format %s",
+ val_to_str (iax_call -> dataformat,
+ iax_dataformats, "unknown (0x%02x)"));
+
+ if( out_of_order )
+ col_append_fstr (pinfo->cinfo, COL_INFO, " (out-of-order packet)");
+ } else {
+ col_append_fstr (pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str (codec, codec_types, "unknown (0x%02x)"));
+ }
+ }
+
+ /* pass the rest of the block to a subdissector */
+ if( !video && try_circuit_dissector(pinfo->ctype, pinfo->circuit_id, pinfo->fd->num,
+ sub_tvb, pinfo, tree))
+ return;
+
+ if( codec != 0 && dissector_try_port(iax2_codec_dissector_table, codec, sub_tvb, pinfo, tree ))
+ return;
+
+ /* we don't know how to dissect our data: dissect it as data */
+ call_dissector(data_handle,sub_tvb, pinfo, tree);
+}
+
+/*
+ * Init routines
+ */
+
+/* called at the start of a capture. We should clear out our static, per-capture
+ * data.
+ */
+
+static void
+iax_init_protocol(void)
+{
+ iax_init_hash();
+
+ if (iax_packets)
+ g_mem_chunk_destroy(iax_packets);
+ iax_packets = g_mem_chunk_create(iax_packet_data,128,G_ALLOC_ONLY);
+}
+
+
+void
+proto_register_iax2 (void)
+{
+ /* we use this for displaying which codecs are supported */
+ static const true_false_string supported_strings = {
+ "Supported",
+ "Not supported"
+ };
+
+ /* A header field is something you can search/filter on.
+ *
+ * We create a structure to register our fields. It consists of an
+ * array of hf_register_info structures, each of which are of the format
+ * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
+ */
+
+ static hf_register_info hf[] = {
+
+ {&hf_iax2_packet_type,
+ {"Packet type", "iax2.type", FT_UINT8, BASE_DEC, VALS(iax_packet_types), 0,
+ "Full/minivoice/minivideo/meta packet",
+ HFILL}},
+
+
+ {&hf_iax2_scallno,
+ {"Source call", "iax2.src_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
+ "src_call holds the number of this call at the packet source pbx",
+ HFILL}},
+
+ /* FIXME could this be turned into a FRAMENUM field? */
+ {&hf_iax2_dcallno,
+ {"Destination call", "iax2.dst_call", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
+ "dst_call holds the number of this call at the packet destination",
+ HFILL}},
+
+ {&hf_iax2_retransmission,
+ {"Retransmission", "iax2.retransmission", FT_BOOLEAN, 16,
+ NULL, 0x8000,
+ "retransmission is set if this packet is a retransmission of an earlier "
+ "failed packet", HFILL}},
+
+ {&hf_iax2_ts,
+ {"Timestamp", "iax2.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "timestamp is the time, in ms after the start of this call, at which "
+ "this packet was transmitted",
+ HFILL}},
+
+ {&hf_iax2_minits,
+ {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "timestamp is the time, in ms after the start of this call, at which "
+ "this packet was transmitted",
+ HFILL}},
+
+ {&hf_iax2_minividts,
+ {"Timestamp", "iax2.timestamp", FT_UINT16, BASE_DEC, NULL, 0x7FFF,
+ "timestamp is the time, in ms after the start of this call, at which "
+ "this packet was transmitted",
+ HFILL}},
+
+ {&hf_iax2_minividmarker,
+ {"Marker", "iax2.video.marker", FT_UINT16, BASE_DEC, NULL, 0x8000,
+ "RTP end-of-frame marker",
+ HFILL}},
+
+ {&hf_iax2_oseqno,
+ {"Outbound seq.no.", "iax2.oseqno", FT_UINT16, BASE_DEC, NULL,
+ 0x0,
+ "oseqno is the sequence no of this packet. The first packet has "
+ "oseqno==0, and subsequent packets increment the oseqno by 1",
+ HFILL}},
+
+ {&hf_iax2_iseqno,
+ {"Inbound seq.no.", "iax2.iseqno", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "iseqno is the sequence no of the last successfully recieved packet",
+ HFILL}},
+
+ {&hf_iax2_type,
+ {"Type", "iax2.type", FT_UINT8, BASE_DEC, VALS (iax_frame_types),
+ 0x0,
+ "For full IAX2 frames, type is the type of frame",
+ HFILL}},
+
+ {&hf_iax2_csub,
+ {"Sub-class", "iax2.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "subclass",
+ HFILL}},
+
+ {&hf_iax2_cmd_csub,
+ {"Control subclass", "iax2.control.subclass", FT_UINT8, BASE_DEC,
+ VALS (iax_cmd_subclasses), 0x0,
+ "This gives the command number for a Control packet.", HFILL}},
+
+ {&hf_iax2_iax_csub,
+ {"IAX type", "iax2.iax.subclass", FT_UINT8, BASE_DEC,
+ VALS (iax_iax_subclasses),
+ 0x0,
+ "IAX type gives the command number for IAX signalling packets", HFILL}},
+
+ {&hf_iax2_voice_csub,
+ {"Sub-class", "iax2.voice.subclass", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "subclass",
+ HFILL}},
+
+ {&hf_iax2_voice_codec,
+ {"CODEC", "iax2.voice.codec", FT_UINT32, BASE_HEX, VALS (codec_types),
+ 0x0,
+ "CODEC gives the codec used to encode audio data", HFILL}},
+
+ {&hf_iax2_video_csub,
+ {"Subclass (compressed codec no)", "iax2.video.subclass", FT_UINT8, BASE_DEC, NULL, 0xBF,
+ "Subclass (compressed codec no)",
+ HFILL}},
+
+ {&hf_iax2_marker,
+ {"Marker", "iax2.video.marker", FT_BOOLEAN, 8, NULL, 0x40,
+ "RTP end-of-frame marker",
+ HFILL}},
+
+ {&hf_iax2_video_codec,
+ {"CODEC", "iax2.video.codec", FT_UINT32, BASE_HEX, VALS (codec_types), 0,
+ "The codec used to encode video data", HFILL}},
+
+ /*
+ * Decoding for the ies
+ */
+
+ {&hf_IAX_IE_APPARENTADDR_SINFAMILY,
+ {"Family", "iax2.iax.app_addr.sinfamily", FT_UINT16, BASE_DEC, NULL, 0, "Family", HFILL }},
+ {&hf_IAX_IE_APPARENTADDR_SINPORT,
+ {"Port", "iax2.iax.app_addr.sinport", FT_UINT16, BASE_DEC, NULL, 0, "Port", HFILL }},
+ {&hf_IAX_IE_APPARENTADDR_SINADDR,
+ {"Address", "iax2.iax.app_addr.sinaddr", FT_IPv4, BASE_HEX, NULL, 0, "Address", HFILL }},
+ {&hf_IAX_IE_APPARENTADDR_SINZERO,
+ {"Zero", "iax2.iax.app_addr.sinzero", FT_BYTES, BASE_HEX, NULL, 0, "Zero", HFILL }},
+
+ {&hf_IAX_IE_CALLED_NUMBER,
+ {"Number/extension being called", "iax2.iax.called_number",
+ FT_STRING,
+ BASE_NONE, NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_CALLING_NUMBER,
+ {"Calling number", "iax2.iax.calling_number", FT_STRING,
+ BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_CALLING_ANI,
+ {"Calling number ANI for billing", "iax2.iax.calling_ani",
+ FT_STRING,
+ BASE_NONE, NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_CALLING_NAME,
+ {"Name of caller", "iax2.iax.calling_name", FT_STRING, BASE_NONE,
+ NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_CALLED_CONTEXT,
+ {"Context for number", "iax2.iax.called_context", FT_STRING,
+ BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_USERNAME,
+ {"Username (peer or user) for authentication",
+ "iax2.iax.username",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_PASSWORD,
+ {"Password for authentication", "iax2.iax.password", FT_STRING,
+ BASE_NONE, NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_CAPABILITY,
+ {"Actual codec capability", "iax2.iax.capability", FT_UINT32,
+ BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_FORMAT,
+ {"Desired codec format", "iax2.iax.format", FT_UINT32, BASE_HEX,
+ VALS (codec_types), 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_LANGUAGE,
+ {"Desired language", "iax2.iax.language", FT_STRING, BASE_NONE,
+ NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_VERSION,
+ {"Protocol version", "iax2.iax.version", FT_UINT16, BASE_HEX, NULL,
+ 0x0,
+ "", HFILL}},
+
+ {&hf_IAX_IE_ADSICPE,
+ {"CPE ADSI capability", "iax2.iax.cpe_adsi", FT_UINT16, BASE_HEX,
+ NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_DNID,
+ {"Originally dialed DNID", "iax2.iax.dnid", FT_STRING, BASE_NONE,
+ NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_AUTHMETHODS,
+ {"Authentication method(s)", "iax2.iax.auth.methods", FT_UINT16,
+ BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_CHALLENGE,
+ {"Challenge data for MD5/RSA", "iax2.iax.auth.challenge",
+ FT_STRING,
+ BASE_NONE, NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_MD5_RESULT,
+ {"MD5 challenge result", "iax2.iax.auth.md5", FT_STRING,
+ BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_RSA_RESULT,
+ {"RSA challenge result", "iax2.iax.auth.rsa", FT_STRING,
+ BASE_NONE, NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_REFRESH,
+ {"When to refresh registration", "iax2.iax.refresh", FT_INT16,
+ BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_DPSTATUS,
+ {"Dialplan status", "iax2.iax.dialplan_status", FT_UINT16,
+ BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_CALLNO,
+ {"Call number of peer", "iax2.iax.call_no", FT_INT16, BASE_DEC,
+ NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_CAUSE,
+ {"Cause", "iax2.iax.cause", FT_STRING, BASE_NONE, NULL, 0x0, "",
+ HFILL}},
+
+ {&hf_IAX_IE_IAX_UNKNOWN,
+ {"Unknown IAX command", "iax2.iax.iax_unknown", FT_BYTES,
+ BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_MSGCOUNT,
+ {"How many messages waiting", "iax2.iax.msg_count", FT_INT16,
+ BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_AUTOANSWER,
+ {"Request auto-answering", "iax2.iax.autoanswer", FT_NONE,
+ BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_MUSICONHOLD,
+ {"Request musiconhold with QUELCH", "iax2.iax.moh", FT_NONE,
+ BASE_NONE,
+ NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_TRANSFERID,
+ {"Transfer Request Identifier", "iax2.iax.transferid", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_RDNIS,
+ {"Referring DNIS", "iax2.iax.rdnis", FT_STRING, BASE_NONE, NULL,
+ 0x0, "",
+ HFILL}},
+
+ {&hf_IAX_IE_DATAFORMAT,
+ {"Data call format", "iax2.iax.dataformat", FT_UINT32, BASE_HEX,
+ VALS(iax_dataformats), 0x0, "", HFILL}},
+
+ {&hf_IAX_IE_UNKNOWN_BYTE,
+ {"data", "iax2.iax.unknowndata", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "Raw data for unknown IEs",
+ HFILL}},
+ {&hf_IAX_IE_UNKNOWN_I16,
+ {"data", "iax2.iax.unknowndata", FT_UINT16, BASE_HEX, NULL,
+ 0x0, "Raw data for unknown IEs",
+ HFILL}},
+ {&hf_IAX_IE_UNKNOWN_I32,
+ {"data", "iax2.iax.unknowndata", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "Raw data for unknown IEs",
+ HFILL}},
+ {&hf_IAX_IE_UNKNOWN_BYTES,
+ {"data", "iax2.iax.unknowndata", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "Raw data for unknown IEs",
+ HFILL}},
+
+ /* capablilites */
+ {&hf_iax2_cap_g723_1,
+ {"G.723.1 compression", "iax2.cap.g723_1", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_G723_1,
+ "G.723.1 compression", HFILL }},
+
+ {&hf_iax2_cap_gsm,
+ {"GSM compression", "iax2.cap.gsm", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_GSM,
+ "GSM compression", HFILL }},
+
+ {&hf_iax2_cap_ulaw,
+ {"Raw mu-law data (G.711)", "iax2.cap.ulaw",FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_ULAW,
+ "Raw mu-law data (G.711)", HFILL }},
+
+ {&hf_iax2_cap_alaw,
+ {"Raw A-law data (G.711)", "iax2.cap.alaw",FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_ALAW,
+ "Raw A-law data (G.711)", HFILL }},
+
+ {&hf_iax2_cap_g726,
+ {"G.726 compression", "iax2.cap.g726",FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_G726,
+ "G.726 compression", HFILL }},
+
+ {&hf_iax2_cap_adpcm,
+ {"ADPCM", "iax2.cap.adpcm", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_ADPCM,
+ "ADPCM", HFILL }},
+
+ {&hf_iax2_cap_slinear,
+ {"Raw 16-bit Signed Linear (8000 Hz) PCM", "iax2.cap.slinear",
+ FT_BOOLEAN, 32, TFS(&supported_strings), AST_FORMAT_SLINEAR,
+ "Raw 16-bit Signed Linear (8000 Hz) PCM", HFILL }},
+
+ {&hf_iax2_cap_lpc10,
+ {"LPC10, 180 samples/frame", "iax2.cap.lpc10", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_LPC10,
+ "LPC10, 180 samples/frame", HFILL }},
+
+ {&hf_iax2_cap_g729a,
+ {"G.729a Audio", "iax2.cap.g729a", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_G729A,
+ "G.729a Audio", HFILL }},
+
+ {&hf_iax2_cap_speex,
+ {"SPEEX Audio", "iax2.cap.speex", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_SPEEX,
+ "SPEEX Audio", HFILL }},
+
+ {&hf_iax2_cap_ilbc,
+ {"iLBC Free compressed Audio", "iax2.cap.ilbc", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_ILBC,
+ "iLBC Free compressed Audio", HFILL }},
+
+ {&hf_iax2_cap_jpeg,
+ {"JPEG images", "iax2.cap.jpeg", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_JPEG,
+ "JPEG images", HFILL }},
+
+ {&hf_iax2_cap_png,
+ {"PNG images", "iax2.cap.png", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_PNG,
+ "PNG images", HFILL }},
+
+ {&hf_iax2_cap_h261,
+ {"H.261 video", "iax2.cap.h261", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_H261,
+ "H.261 video", HFILL }},
+
+ {&hf_iax2_cap_h263,
+ {"H.263 video", "iax2.cap.h263", FT_BOOLEAN, 32,
+ TFS(&supported_strings), AST_FORMAT_H263,
+ "H.263 video", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_iax2,
+ &ett_iax2_full_mini_subtree,
+ &ett_iax2_type,
+ &ett_iax2_ie,
+ &ett_iax2_codecs,
+ &ett_iax2_ies_apparent_addr
+ };
+
+ proto_iax2 =
+ proto_register_protocol ("Inter-Asterisk eXchange v2", "IAX2", "iax2");
+ proto_register_field_array (proto_iax2, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+
+ register_dissector("iax2", dissect_iax2, proto_iax2);
+
+ iax2_codec_dissector_table = register_dissector_table(
+ "iax2.codec","IAX codec number", FT_UINT32, BASE_HEX);
+ iax2_dataformat_dissector_table = register_dissector_table(
+ "iax2.dataformat","IAX dataformat number", FT_UINT32, BASE_HEX);
+
+ /* register our init routine to be called at the start of a capture,
+ to clear out our hash tables etc */
+ register_init_routine(&iax_init_protocol);
+}
+
+void
+proto_reg_handoff_iax2 (void)
+{
+ dissector_add("udp.port", IAX2_PORT, find_dissector("iax2"));
+ dissector_add("iax2.dataformat", AST_DATAFORMAT_V110, find_dissector("v110"));
+ data_handle = find_dissector("data");
+}
+
+
+/*
+ * This sets up the indentation style for this file in emacs.
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff --git a/epan/dissectors/packet-iax2.h b/epan/dissectors/packet-iax2.h
new file mode 100644
index 0000000000..96e861f944
--- /dev/null
+++ b/epan/dissectors/packet-iax2.h
@@ -0,0 +1,133 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Implementation of Inter-Asterisk eXchange
+ *
+ * Copyright (C) 2003, Digium
+ *
+ * Mark Spencer <markster@linux-support.net>
+ *
+ * $Id$
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ */
+
+#ifndef _PACKET_IAX2_H
+#define _PACKET_IAX2_H
+
+/* Max version of IAX protocol we support */
+#define IAX_PROTO_VERSION 2
+
+#define IAX_MAX_CALLS 32768
+
+#define IAX_FLAG_FULL 0x8000
+
+#define IAX_FLAG_RETRANS 0x8000
+
+#define IAX_FLAG_SC_LOG 0x80
+
+#define IAX_MAX_SHIFT 0x1F
+
+#define IAX_WINDOW 64
+
+#define AST_FRAME_DTMF 1 /* A DTMF digit, subclass is the digit */
+#define AST_FRAME_VOICE 2 /* Voice data, subclass is AST_FORMAT_* */
+#define AST_FRAME_VIDEO 3 /* Video frame, maybe?? :) */
+#define AST_FRAME_CONTROL 4 /* A control frame, subclass is AST_CONTROL_* */
+#define AST_FRAME_NULL 5 /* An empty, useless frame */
+#define AST_FRAME_IAX 6 /* Inter Aterisk Exchange private frame type */
+#define AST_FRAME_TEXT 7 /* Text messages */
+#define AST_FRAME_IMAGE 8 /* Image Frames */
+#define AST_FRAME_HTML 9 /* HTML Frames */
+
+/* Subclass for AST_FRAME_IAX */
+#define IAX_COMMAND_NEW 1
+#define IAX_COMMAND_PING 2
+#define IAX_COMMAND_PONG 3
+#define IAX_COMMAND_ACK 4
+#define IAX_COMMAND_HANGUP 5
+#define IAX_COMMAND_REJECT 6
+#define IAX_COMMAND_ACCEPT 7
+#define IAX_COMMAND_AUTHREQ 8
+#define IAX_COMMAND_AUTHREP 9
+#define IAX_COMMAND_INVAL 10
+#define IAX_COMMAND_LAGRQ 11
+#define IAX_COMMAND_LAGRP 12
+#define IAX_COMMAND_REGREQ 13 /* Registration request */
+#define IAX_COMMAND_REGAUTH 14 /* Registration authentication required */
+#define IAX_COMMAND_REGACK 15 /* Registration accepted */
+#define IAX_COMMAND_REGREJ 16 /* Registration rejected */
+#define IAX_COMMAND_REGREL 17 /* Force release of registration */
+#define IAX_COMMAND_VNAK 18 /* If we receive voice before valid first voice frame, send this */
+#define IAX_COMMAND_DPREQ 19 /* Request status of a dialplan entry */
+#define IAX_COMMAND_DPREP 20 /* Request status of a dialplan entry */
+#define IAX_COMMAND_DIAL 21 /* Request a dial on channel brought up TBD */
+#define IAX_COMMAND_TXREQ 22 /* Transfer Request */
+#define IAX_COMMAND_TXCNT 23 /* Transfer Connect */
+#define IAX_COMMAND_TXACC 24 /* Transfer Accepted */
+#define IAX_COMMAND_TXREADY 25 /* Transfer ready */
+#define IAX_COMMAND_TXREL 26 /* Transfer release */
+#define IAX_COMMAND_TXREJ 27 /* Transfer reject */
+#define IAX_COMMAND_QUELCH 28 /* Stop audio/video transmission */
+#define IAX_COMMAND_UNQUELCH 29 /* Resume audio/video transmission */
+#define IAX_COMMAND_POKE 30 /* Like ping, but does not require an open connection */
+#define IAX_COMMAND_PAGE 31 /* Paging description */
+#define IAX_COMMAND_MWI 32 /* Stand-alone message waiting indicator */
+#define IAX_COMMAND_UNSUPPORT 33 /* Unsupported message received */
+#define IAX_COMMAND_TRANSFER 34 /* Request remote transfer */
+
+#define IAX_DEFAULT_REG_EXPIRE 60 /* By default require re-registration once per minute */
+
+#define IAX_LINGER_TIMEOUT 10 /* How long to wait before closing bridged call */
+
+#define IAX_DEFAULT_PORTNO 4569
+
+/* IAX Information elements */
+#define IAX_IE_CALLED_NUMBER 1 /* Number/extension being called - string */
+#define IAX_IE_CALLING_NUMBER 2 /* Calling number - string */
+#define IAX_IE_CALLING_ANI 3 /* Calling number ANI for billing - string */
+#define IAX_IE_CALLING_NAME 4 /* Name of caller - string */
+#define IAX_IE_CALLED_CONTEXT 5 /* Context for number - string */
+#define IAX_IE_USERNAME 6 /* Username (peer or user) for authentication - string */
+#define IAX_IE_PASSWORD 7 /* Password for authentication - string */
+#define IAX_IE_CAPABILITY 8 /* Actual codec capability - unsigned int */
+#define IAX_IE_FORMAT 9 /* Desired codec format - unsigned int */
+#define IAX_IE_LANGUAGE 10 /* Desired language - string */
+#define IAX_IE_VERSION 11 /* Protocol version - short */
+#define IAX_IE_ADSICPE 12 /* CPE ADSI capability - short */
+#define IAX_IE_DNID 13 /* Originally dialed DNID - string */
+#define IAX_IE_AUTHMETHODS 14 /* Authentication method(s) - short */
+#define IAX_IE_CHALLENGE 15 /* Challenge data for MD5/RSA - string */
+#define IAX_IE_MD5_RESULT 16 /* MD5 challenge result - string */
+#define IAX_IE_RSA_RESULT 17 /* RSA challenge result - string */
+#define IAX_IE_APPARENT_ADDR 18 /* Apparent address of peer - struct sockaddr_in */
+#define IAX_IE_REFRESH 19 /* When to refresh registration - short */
+#define IAX_IE_DPSTATUS 20 /* Dialplan status - short */
+#define IAX_IE_CALLNO 21 /* Call number of peer - short */
+#define IAX_IE_CAUSE 22 /* Cause - string */
+#define IAX_IE_IAX_UNKNOWN 23 /* Unknown IAX command - byte */
+#define IAX_IE_MSGCOUNT 24 /* How many messages waiting - short */
+#define IAX_IE_AUTOANSWER 25 /* Request auto-answering -- none */
+#define IAX_IE_MUSICONHOLD 26 /* Request musiconhold with QUELCH -- none or string */
+#define IAX_IE_TRANSFERID 27 /* Transfer Request Identifier -- int */
+#define IAX_IE_RDNIS 28 /* Referring DNIS -- string */
+#define IAX_IE_PROVISIONING 29 /* Provisioning info */
+#define IAX_IE_AESPROVISIONING 30 /* AES Provisioning info */
+#define IAX_IE_DATETIME 31 /* Date/Time */
+#define IAX_IE_DATAFORMAT 255 /* Data call format -- iax_dataformat_t */
+
+#define IAX_AUTH_PLAINTEXT (1 << 0)
+#define IAX_AUTH_MD5 (1 << 1)
+#define IAX_AUTH_RSA (1 << 2)
+
+#define IAX_META_TRUNK 1 /* Trunk meta-message */
+#define IAX_META_VIDEO 2 /* Video frame */
+
+#define IAX_DPSTATUS_EXISTS (1 << 0)
+#define IAX_DPSTATUS_CANEXIST (1 << 1)
+#define IAX_DPSTATUS_NONEXISTANT (1 << 2)
+#define IAX_DPSTATUS_IGNOREPAT (1 << 14)
+#define IAX_DPSTATUS_MATCHMORE (1 << 15)
+
+#endif
diff --git a/epan/dissectors/packet-ib.c b/epan/dissectors/packet-ib.c
new file mode 100644
index 0000000000..13fe694897
--- /dev/null
+++ b/epan/dissectors/packet-ib.c
@@ -0,0 +1,239 @@
+/* packet-ib.c
+ * Routines for Interbase dissection
+ *
+ * Erik Kunze <kunze@philosys.de>
+ * Uwe Girlich <Uwe.Girlich@philosys.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-x11.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+
+/* Initialize the protocol and registered fields */
+static int proto_ib = -1;
+
+static int hf_ib_opcode = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_ib = -1;
+
+static dissector_handle_t data_handle;
+
+#define TCP_PORT_IB 3050
+
+/*
+ * Round a length to a multiple of 4 bytes.
+ */
+#define ROUND_LENGTH(n) ((((n) + 3)/4) * 4)
+
+
+static const value_string names_opcode[] = {
+{ 0, "void" },
+{ 1, "connect" },
+{ 2, "exit" },
+{ 3, "accept" },
+{ 4, "reject" },
+{ 5, "protocol" },
+{ 6, "disconnect" },
+{ 7, "credit" },
+{ 8, "continuation" },
+{ 9, "response" },
+{ 10, "open file" },
+{ 11, "create file" },
+{ 12, "close file" },
+{ 13, "read page" },
+{ 14, "write page" },
+{ 15, "lock" },
+{ 16, "convert lock" },
+{ 17, "release lock" },
+{ 18, "blocking" },
+{ 19, "attach" },
+{ 20, "create" },
+{ 21, "detach" },
+{ 22, "compile" },
+{ 23, "start" },
+{ 24, "start and_send" },
+{ 25, "send" },
+{ 26, "receive" },
+{ 27, "unwind" },
+{ 28, "release" },
+{ 29, "transaction" },
+{ 30, "commit" },
+{ 31, "rollback" },
+{ 32, "prepare" },
+{ 33, "reconnect" },
+{ 34, "create blob" },
+{ 35, "open blob" },
+{ 36, "get segment" },
+{ 37, "put segment" },
+{ 38, "cancel blob" },
+{ 39, "close blob" },
+{ 40, "info database" },
+{ 41, "info request" },
+{ 42, "info transaction" },
+{ 43, "info blob" },
+{ 44, "batch segments" },
+{ 45, "mgr set_affinity" },
+{ 46, "mgr clear_affinity" },
+{ 47, "mgr report" },
+{ 48, "que events" },
+{ 49, "cancel events" },
+{ 50, "commit retaining" },
+{ 51, "prepare2" },
+{ 52, "event" },
+{ 53, "connect request" },
+{ 54, "aux connect" },
+{ 55, "ddl" },
+{ 56, "open blob2" },
+{ 57, "create blob2" },
+{ 58, "get slice" },
+{ 59, "put slice" },
+{ 60, "slice" },
+{ 61, "seek blob" },
+{ 62, "allocate statement" },
+{ 63, "execute" },
+{ 64, "exec immediate" },
+{ 65, "fetch" },
+{ 66, "fetch response" },
+{ 67, "free statement" },
+{ 68, "prepare statement" },
+{ 69, "set cursor" },
+{ 70, "info sql" },
+{ 71, "dummy" },
+{ 72, "response piggyback" },
+{ 73, "start and_receive" },
+{ 74, "start send_and_receive" },
+{ 75, "exec immediate2" },
+{ 76, "execute2" },
+{ 77, "insert" },
+{ 78, "sql response" },
+{ 79, "transact" },
+{ 80, "transact response" },
+{ 81, "drop database" },
+{ 82, "service attach" },
+{ 83, "service detach" },
+{ 84, "service info" },
+{ 85, "service start" },
+{ 86, "rollback retaining" },
+{ 0, NULL }
+};
+
+static int
+dissect_ib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 opcode;
+ proto_item *ti = NULL;
+ proto_tree *ib_tree = NULL;
+ int offset;
+ tvbuff_t *next_tvb;
+
+ offset = 0;
+
+ /*
+ * Check that the opcode is one we recognize.
+ */
+ if (!tvb_bytes_exist(tvb, offset, 4)) {
+ /*
+ * We don't have enough bytes for an opcode.
+ */
+ return 0;
+ }
+ opcode = tvb_get_ntohl(tvb, offset + 0);
+ if (match_strval(opcode, names_opcode) == NULL) {
+ /*
+ * This isn't an opcode we recognize.
+ */
+ return 0;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IB");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (pinfo->match_port == pinfo->destport)
+ col_set_str(pinfo->cinfo, COL_INFO, "Request");
+ else
+ col_set_str(pinfo->cinfo, COL_INFO, "Reply");
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ib, tvb, 0, -1, FALSE);
+ }
+ if (ti) {
+ ib_tree = proto_item_add_subtree(ti, ett_ib);
+ }
+
+ if (ib_tree) {
+ proto_tree_add_uint(ib_tree,
+ hf_ib_opcode, tvb, offset + 0, 4, opcode);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ val_to_str(opcode,names_opcode,"%u"));
+ }
+ offset += 4;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ call_dissector(data_handle, next_tvb, pinfo, ib_tree);
+ return tvb_length(tvb);
+}
+
+/* Register the protocol with Ethereal */
+void proto_register_ib(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_ib_opcode,
+ { "Opcode", "ib.opcode",
+ FT_UINT32, BASE_DEC, VALS(names_opcode), 0x0,
+ "packet opcode", HFILL }},
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_ib,
+ };
+
+/* Register the protocol name and description */
+ proto_ib = proto_register_protocol("Interbase", "IB", "ib");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ib, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ib(void)
+{
+ dissector_handle_t ib_handle;
+
+ ib_handle = new_create_dissector_handle(dissect_ib, proto_ib);
+ dissector_add("tcp.port", TCP_PORT_IB, ib_handle);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-icap.c b/epan/dissectors/packet-icap.c
new file mode 100644
index 0000000000..214febaa26
--- /dev/null
+++ b/epan/dissectors/packet-icap.c
@@ -0,0 +1,340 @@
+/* packet-icap.c
+ * Routines for ICAP packet disassembly
+ * RFC 3507
+ *
+ * Srishylam Simharajan simha@netapp.com
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+typedef enum _icap_type {
+ ICAP_OPTIONS,
+ ICAP_REQMOD,
+ ICAP_RESPMOD,
+ ICAP_RESPONSE,
+ ICAP_OTHER
+} icap_type_t;
+
+static int proto_icap = -1;
+static int hf_icap_response = -1;
+static int hf_icap_reqmod = -1;
+static int hf_icap_respmod = -1;
+static int hf_icap_options = -1;
+static int hf_icap_other = -1;
+
+static gint ett_icap = -1;
+
+static dissector_handle_t data_handle;
+
+#define TCP_PORT_ICAP 1344
+static int is_icap_message(const guchar *data, int linelen, icap_type_t *type);
+static void
+dissect_icap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *icap_tree = NULL;
+ proto_item *ti = NULL;
+ gint offset = 0;
+ const guchar *line;
+ gint next_offset;
+ const guchar *linep, *lineend;
+ int linelen;
+ guchar c;
+ icap_type_t icap_type;
+ int datalen;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICAP");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary
+ * if it's an ICAP header (but leave out the
+ * line terminator).
+ * Otherwise, just call it a continuation.
+ *
+ * Note that "tvb_find_line_end()" will return a value that
+ * is not longer than what's in the buffer, so the
+ * "tvb_get_ptr()" call won't throw an exception.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
+ FALSE);
+ line = tvb_get_ptr(tvb, offset, linelen);
+ icap_type = ICAP_OTHER; /* type not known yet */
+ if (is_icap_message(line, linelen, &icap_type))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ format_text(line, linelen));
+ else
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_icap, tvb, offset, -1,
+ FALSE);
+ icap_tree = proto_item_add_subtree(ti, ett_icap);
+ }
+
+ /*
+ * Process the packet data, a line at a time.
+ */
+ icap_type = ICAP_OTHER; /* type not known yet */
+ while (tvb_offset_exists(tvb, offset)) {
+ gboolean is_icap = FALSE;
+ gboolean loop_done = FALSE;
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
+ FALSE);
+
+ /*
+ * Get a buffer that refers to the line.
+ */
+ line = tvb_get_ptr(tvb, offset, linelen);
+ lineend = line + linelen;
+
+ /*
+ * find header format
+ */
+ if (is_icap_message(line, linelen, &icap_type)) {
+ is_icap = TRUE;
+ goto is_icap_header;
+ }
+
+ /*
+ * if it looks like a blank line, end of header perhaps?
+ */
+ if (linelen == 0) {
+ is_icap = TRUE;
+ goto is_icap_header;
+ }
+
+ /*
+ * No. Does it look like a header?
+ */
+ linep = line;
+ loop_done = FALSE;
+ while (linep < lineend && (!loop_done)) {
+ c = *linep++;
+
+ /*
+ * This must be a CHAR to be part of a token; that
+ * means it must be ASCII.
+ */
+ if (!isascii(c)) {
+ is_icap = FALSE;
+ break; /* not ASCII, thus not a CHAR */
+ }
+
+ /*
+ * This mustn't be a CTL to be part of a token.
+ *
+ * XXX - what about leading LWS on continuation
+ * lines of a header?
+ */
+ if (iscntrl(c)) {
+ is_icap = FALSE;
+ break; /* CTL, not part of a header */
+ }
+
+ switch (c) {
+
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case '\\':
+ case '"':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+ case '{':
+ case '}':
+ /*
+ * It's a separator, so it's not part of a
+ * token, so it's not a field name for the
+ * beginning of a header.
+ *
+ * (We don't have to check for HT; that's
+ * already been ruled out by "iscntrl()".)
+ *
+ * XXX - what about ' '? HTTP's checks
+ * check for that.
+ */
+ is_icap = FALSE;
+ loop_done = TRUE;
+ break;
+
+ case ':':
+ /*
+ * This ends the token; we consider this
+ * to be a header.
+ */
+ is_icap = TRUE;
+ goto is_icap_header;
+ break;
+ }
+ }
+
+ /*
+ * We don't consider this part of an ICAP message,
+ * so we don't display it.
+ * (Yeah, that means we don't display, say, a text/icap
+ * page, but you can get that from the data pane.)
+ */
+ if (!is_icap)
+ break;
+is_icap_header:
+ if (tree) {
+ proto_tree_add_text(icap_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset,
+ next_offset - offset)
+ );
+ }
+ offset = next_offset;
+ }
+
+ if (tree) {
+ switch (icap_type) {
+
+ case ICAP_OPTIONS:
+ proto_tree_add_boolean_hidden(icap_tree,
+ hf_icap_options, tvb, 0, 0, 1);
+ break;
+
+ case ICAP_REQMOD:
+ proto_tree_add_boolean_hidden(icap_tree,
+ hf_icap_reqmod, tvb, 0, 0, 1);
+ break;
+
+ case ICAP_RESPMOD:
+ proto_tree_add_boolean_hidden(icap_tree,
+ hf_icap_respmod, tvb, 0, 0, 1);
+ break;
+
+ case ICAP_RESPONSE:
+ proto_tree_add_boolean_hidden(icap_tree,
+ hf_icap_response, tvb, 0, 0, 1);
+ break;
+
+ case ICAP_OTHER:
+ default:
+ break;
+ }
+ }
+
+ datalen = tvb_length_remaining(tvb, offset);
+ if (datalen > 0) {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, icap_tree);
+ }
+}
+
+
+static int
+is_icap_message(const guchar *data, int linelen, icap_type_t *type)
+{
+#define ICAP_COMPARE(string, length, msgtype) { \
+ if (strncmp(data, string, length) == 0) { \
+ if (*type == ICAP_OTHER) \
+ *type = msgtype; \
+ return TRUE; \
+ } \
+}
+ /*
+ * From draft-elson-opes-icap-01(72).txt
+ */
+ if (linelen >= 5) {
+ ICAP_COMPARE("ICAP/", 5, ICAP_RESPONSE); /* response */
+ }
+ if (linelen >= 7) {
+ ICAP_COMPARE("REQMOD ", 7, ICAP_REQMOD); /* request mod */
+ }
+ if (linelen >= 8) {
+ ICAP_COMPARE("OPTIONS ", 8, ICAP_OPTIONS); /* options */
+ ICAP_COMPARE("RESPMOD ", 8, ICAP_RESPMOD); /* response mod */
+ }
+ return FALSE;
+#undef ICAP_COMPARE
+}
+
+void
+proto_register_icap(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_icap_response,
+ { "Response", "icap.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if ICAP response", HFILL }},
+ { &hf_icap_reqmod,
+ { "Reqmod", "icap.reqmod",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if ICAP reqmod", HFILL }},
+ { &hf_icap_respmod,
+ { "Respmod", "icap.respmod",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if ICAP respmod", HFILL }},
+ { &hf_icap_options,
+ { "Options", "icap.options",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if ICAP options", HFILL }},
+ { &hf_icap_other,
+ { "Other", "icap.other",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if ICAP other", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_icap,
+ };
+
+ proto_icap = proto_register_protocol(
+ "Internet Content Adaptation Protocol",
+ "ICAP", "icap");
+ proto_register_field_array(proto_icap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_icap(void)
+{
+ dissector_handle_t icap_handle;
+
+ data_handle = find_dissector("data");
+ icap_handle = create_dissector_handle(dissect_icap, proto_icap);
+ dissector_add("tcp.port", TCP_PORT_ICAP, icap_handle);
+}
diff --git a/epan/dissectors/packet-icmpv6.c b/epan/dissectors/packet-icmpv6.c
new file mode 100644
index 0000000000..d77f7c0ffe
--- /dev/null
+++ b/epan/dissectors/packet-icmpv6.c
@@ -0,0 +1,1661 @@
+/* packet-icmpv6.c
+ * Routines for ICMPv6 packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * MobileIPv6 support added by Tomislav Borosa <tomislav.borosa@siemens.hr>
+ *
+ * HMIPv6 support added by Martti Kuparinen <martti.kuparinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "packet-ipv6.h"
+#include "packet-dns.h"
+#include "in_cksum.h"
+#include <epan/resolv.h>
+#include "ipproto.h"
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+/*
+ * See, under http://www.ietf.org/internet-drafts/
+ *
+ * draft-ietf-mobileip-ipv6-15.txt
+ *
+ * and
+ *
+ * draft-ietf-ipngwg-icmp-name-lookups-08.txt
+ *
+ * and
+ *
+ * draft-ietf-mobileip-hmipv6-05.txt
+ */
+
+static int proto_icmpv6 = -1;
+static int hf_icmpv6_type = -1;
+static int hf_icmpv6_code = -1;
+static int hf_icmpv6_checksum = -1;
+static int hf_icmpv6_checksum_bad = -1;
+static int hf_icmpv6_haad_ha_addrs = -1;
+
+static gint ett_icmpv6 = -1;
+static gint ett_icmpv6opt = -1;
+static gint ett_icmpv6flag = -1;
+static gint ett_nodeinfo_flag = -1;
+static gint ett_nodeinfo_subject4 = -1;
+static gint ett_nodeinfo_subject6 = -1;
+static gint ett_nodeinfo_node4 = -1;
+static gint ett_nodeinfo_node6 = -1;
+static gint ett_nodeinfo_nodebitmap = -1;
+static gint ett_nodeinfo_nodedns = -1;
+static gint ett_multicastRR = -1;
+
+static dissector_handle_t ipv6_handle;
+static dissector_handle_t data_handle;
+
+static const value_string names_nodeinfo_qtype[] = {
+ { NI_QTYPE_NOOP, "NOOP" },
+ { NI_QTYPE_SUPTYPES, "Supported query types" },
+ { NI_QTYPE_DNSNAME, "DNS name" },
+ { NI_QTYPE_NODEADDR, "Node addresses" },
+ { NI_QTYPE_IPV4ADDR, "IPv4 node addresses" },
+ { 0, NULL }
+};
+
+static const value_string names_rrenum_matchcode[] = {
+ { RPM_PCO_ADD, "Add" },
+ { RPM_PCO_CHANGE, "Change" },
+ { RPM_PCO_SETGLOBAL, "Set Global" },
+ { 0, NULL }
+};
+
+static const value_string names_router_pref[] = {
+ { ND_RA_FLAG_RTPREF_HIGH, "High" },
+ { ND_RA_FLAG_RTPREF_MEDIUM, "Medium" },
+ { ND_RA_FLAG_RTPREF_LOW, "Low" },
+ { ND_RA_FLAG_RTPREF_RSV, "Reserved" },
+};
+
+static void
+dissect_contained_icmpv6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ gboolean save_in_error_pkt;
+ tvbuff_t *next_tvb;
+
+ /* Save the current value of the "we're inside an error packet"
+ flag, and set that flag; subdissectors may treat packets
+ that are the payload of error packets differently from
+ "real" packets. */
+ save_in_error_pkt = pinfo->in_error_pkt;
+ pinfo->in_error_pkt = TRUE;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ /* tiny sanity check */
+ if ((tvb_get_guint8(tvb, offset) & 0xf0) == 0x60) {
+ /* The contained packet is an IPv6 datagram; dissect it. */
+ call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+ } else
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+
+ /* Restore the "we're inside an error packet" flag. */
+ pinfo->in_error_pkt = save_in_error_pkt;
+}
+
+static void
+dissect_icmpv6opt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *icmp6opt_tree, *field_tree;
+ proto_item *ti, *tf;
+ struct nd_opt_hdr nd_opt_hdr, *opt;
+ int len;
+ char *typename;
+ static const guint8 nd_redirect_reserved[6] = {0, 0, 0, 0, 0, 0};
+ guint8 nd_redirect_res[6];
+
+ if (!tree)
+ return;
+
+again:
+ if ((int)tvb_reported_length(tvb) <= offset)
+ return; /* No more options left */
+
+ opt = &nd_opt_hdr;
+ tvb_memcpy(tvb, (guint8 *)opt, offset, sizeof *opt);
+ len = opt->nd_opt_len << 3;
+
+ /* !!! specify length */
+ ti = proto_tree_add_text(tree, tvb, offset, len, "ICMPv6 options");
+ icmp6opt_tree = proto_item_add_subtree(ti, ett_icmpv6opt);
+
+ if (len == 0) {
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
+ "Invalid option length: %u",
+ opt->nd_opt_len);
+ return; /* we must not try to decode this */
+ }
+
+ switch (opt->nd_opt_type) {
+ case ND_OPT_SOURCE_LINKADDR:
+ typename = "Source link-layer address";
+ break;
+ case ND_OPT_TARGET_LINKADDR:
+ typename = "Target link-layer address";
+ break;
+ case ND_OPT_PREFIX_INFORMATION:
+ typename = "Prefix information";
+ break;
+ case ND_OPT_REDIRECTED_HEADER:
+ typename = "Redirected header";
+ break;
+ case ND_OPT_MTU:
+ typename = "MTU";
+ break;
+ case ND_OPT_ADVINTERVAL:
+ typename = "Advertisement Interval";
+ break;
+ case ND_OPT_HOMEAGENT_INFO:
+ typename = "Home Agent Information";
+ break;
+ case ND_OPT_MAP:
+ typename = "HMIPv6 MAP option";
+ break;
+ default:
+ typename = "Unknown";
+ break;
+ }
+
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_hdr, nd_opt_type), 1,
+ "Type: %u (%s)", opt->nd_opt_type, typename);
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
+ "Length: %u bytes (%u)", opt->nd_opt_len << 3, opt->nd_opt_len);
+
+ /* decode... */
+ switch (opt->nd_opt_type) {
+ case ND_OPT_SOURCE_LINKADDR:
+ case ND_OPT_TARGET_LINKADDR:
+ {
+ int len, i, p;
+ const guint8 *a;
+ char *t;
+
+ p = offset + sizeof(*opt);
+ len = (opt->nd_opt_len << 3) - sizeof(*opt);
+ a = tvb_get_ptr(tvb, p, len);
+ t = g_malloc(len * 3);
+ memset(t, 0, len * 3);
+ for (i = 0; i < len; i++) {
+ if (i)
+ t[i * 3 - 1] = ':';
+ sprintf(&t[i * 3], "%02x", a[i]);
+ }
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + sizeof(*opt), len, "Link-layer address: %s", t);
+ g_free(t);
+ break;
+ }
+ case ND_OPT_PREFIX_INFORMATION:
+ {
+ struct nd_opt_prefix_info nd_opt_prefix_info, *pi;
+ int flagoff;
+
+ pi = &nd_opt_prefix_info;
+ tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix_len),
+ 1, "Prefix length: %u", pi->nd_opt_pi_prefix_len);
+
+ flagoff = offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved);
+ tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1, "Flags: 0x%02x",
+ tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_flags_reserved)));
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
+ ND_OPT_PI_FLAG_ONLINK, 8, "Onlink", "Not onlink"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
+ ND_OPT_PI_FLAG_AUTO, 8, "Auto", "Not auto"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
+ ND_OPT_PI_FLAG_ROUTER, 8,
+ "Router Address", "Not router address"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(pi->nd_opt_pi_flags_reserved,
+ ND_OPT_PI_FLAG_SITEPREF, 8,
+ "Site prefix", "Not site prefix"));
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_valid_time),
+ 4, "Valid lifetime: 0x%08x",
+ pntohl(&pi->nd_opt_pi_valid_time));
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_preferred_time),
+ 4, "Preferred lifetime: 0x%08x",
+ pntohl(&pi->nd_opt_pi_preferred_time));
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_prefix_info, nd_opt_pi_prefix),
+ 16, "Prefix: %s", ip6_to_str(&pi->nd_opt_pi_prefix));
+ break;
+ }
+ case ND_OPT_REDIRECTED_HEADER:
+ tvb_memcpy(tvb, (guint8 *)&nd_redirect_res, offset + 2, 6);
+ if (memcmp(nd_redirect_res, nd_redirect_reserved, 6) == 0)
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + 2, 6, "Reserved: 0 (correct)");
+ else
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset +2, 6, "Reserved: MUST be 0 (incorrect!)");
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + 8, (opt->nd_opt_len << 3) - 8, "Redirected packet");
+ dissect_contained_icmpv6(tvb, offset + 8, pinfo, icmp6opt_tree);
+ break;
+ case ND_OPT_MTU:
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu), 4,
+ "MTU: %u", tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_mtu, nd_opt_mtu_mtu)));
+ break;
+ case ND_OPT_ADVINTERVAL:
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint), 4,
+ "Advertisement Interval: %u",
+ tvb_get_ntohl(tvb, offset + offsetof(struct nd_opt_adv_int, nd_opt_adv_int_advint)));
+ break;
+ case ND_OPT_HOMEAGENT_INFO:
+ {
+ struct nd_opt_ha_info pibuf, *pi;
+
+ pi = &pibuf;
+ tvb_memcpy(tvb, (guint8 *)pi, offset, sizeof *pi);
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_pref),
+ 2, "Home Agent Preference: %d",
+ (gint16)pntohs(&pi->nd_opt_ha_info_ha_pref));
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_ha_info, nd_opt_ha_info_ha_life),
+ 2, "Home Agent Lifetime: %u",
+ pntohs(&pi->nd_opt_ha_info_ha_life));
+ break;
+ }
+ case ND_OPT_MAP:
+ {
+ struct nd_opt_map_info mapbuf, *map;
+ int flagoff;
+
+ map = &mapbuf;
+ tvb_memcpy(tvb, (guint8 *)map, offset, sizeof *map);
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
+ 1, "Distance: %u", (map->nd_opt_map_dist_and_pref >> 4));
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_map_info, nd_opt_map_dist_and_pref),
+ 1, "Preference: %u", (map->nd_opt_map_dist_and_pref & 0x0F));
+ flagoff = offset + offsetof(struct nd_opt_map_info,
+ nd_opt_map_flags);
+ tf = proto_tree_add_text(icmp6opt_tree, tvb, flagoff, 1,
+ "Flags: 0x%02x",
+ tvb_get_guint8(tvb, offset + offsetof(struct nd_opt_map_info,
+ nd_opt_map_flags)));
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_R, 8, "R", "No R"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_M, 8, "M", "No M"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_I, 8, "I", "No I"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_T, 8, "T", "No T"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_P, 8, "P", "No P"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(map->nd_opt_map_flags,
+ ND_OPT_MAP_FLAG_V, 8, "V", "No V"));
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_map_info, nd_opt_map_lifetime),
+ 4, "Lifetime: %u", pntohl(&map->nd_opt_map_lifetime));
+
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_map_info, nd_opt_map_address), 16,
+#ifdef INET6
+ "Address of MAP: %s (%s)",
+ get_hostname6(&map->nd_opt_map_address),
+#else
+ "Address of MAP: %s",
+#endif
+ ip6_to_str(&map->nd_opt_map_address));
+ break;
+ }
+ case ND_OPT_ROUTE_INFO:
+ {
+ struct nd_opt_route_info ribuf, *ri;
+ struct e_in6_addr in6;
+ int l;
+ guint32 lifetime;
+
+ ri = &ribuf;
+ tvb_memcpy(tvb, (guint8 *)ri, offset, sizeof *ri);
+ memset(&in6, 0, sizeof(in6));
+ switch (ri->nd_opt_rti_len) {
+ case 1:
+ l = 0;
+ break;
+ case 2:
+ tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 8);
+ break;
+ case 3:
+ tvb_memcpy(tvb, (guint8 *)&in6, offset + sizeof(*ri), l = 16);
+ break;
+ default:
+ l = -1;
+ break;
+ }
+ if (l >= 0) {
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_prefixlen),
+ 1, "Prefix length: %u", ri->nd_opt_rti_prefixlen);
+ tf = proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
+ 1, "Flags: 0x%02x", ri->nd_opt_rti_flags);
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_flags),
+ 1, "%s",
+ decode_enumerated_bitfield(ri->nd_opt_rti_flags,
+ ND_RA_FLAG_RTPREF_MASK, 8, names_router_pref,
+ "Router preference: %s"));
+ lifetime = pntohl(&ri->nd_opt_rti_lifetime);
+ if (lifetime == 0xffffffff)
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
+ sizeof(ri->nd_opt_rti_lifetime), "Lifetime: infinity");
+ else
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_route_info, nd_opt_rti_lifetime),
+ sizeof(ri->nd_opt_rti_lifetime), "Lifetime: %u", lifetime);
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + sizeof(*ri), l, "Prefix: %s", ip6_to_str(&in6));
+ } else {
+ proto_tree_add_text(icmp6opt_tree, tvb,
+ offset + offsetof(struct nd_opt_hdr, nd_opt_len), 1,
+ "Invalid option length: %u", opt->nd_opt_len);
+ }
+ break;
+ }
+ }
+
+ offset += (opt->nd_opt_len << 3);
+ goto again;
+}
+
+/*
+ * draft-ietf-ipngwg-icmp-name-lookups-07.txt
+ * Note that the packet format was changed several times in the past.
+ */
+
+static const char *
+bitrange0(guint32 v, int s, char *buf, int buflen)
+{
+ guint32 v0;
+ char *p, *ep;
+ int off;
+ int i, l;
+
+ if (buflen < 1)
+ return NULL;
+ if (buflen == 1) {
+ buf[0] = '\0';
+ return NULL;
+ }
+
+ v0 = v;
+ p = buf;
+ ep = buf + buflen - 1;
+ memset(buf, 0, buflen);
+ off = 0;
+ while (off < 32) {
+ /* shift till we have 0x01 */
+ if ((v & 0x01) == 0) {
+ switch (v & 0x0f) {
+ case 0x00:
+ v >>= 4; off += 4; continue;
+ case 0x08:
+ v >>= 3; off += 3; continue;
+ case 0x04: case 0x0c:
+ v >>= 2; off += 2; continue;
+ default:
+ v >>= 1; off += 1; continue;
+ }
+ }
+
+ /* we have 0x01 with us */
+ for (i = 0; i < 32 - off; i++) {
+ if ((v & (0x01 << i)) == 0)
+ break;
+ }
+ if (i == 1)
+ l = snprintf(p, ep - p, ",%d", s + off);
+ else {
+ l = snprintf(p, ep - p, ",%d-%d", s + off,
+ s + off + i - 1);
+ }
+ if (l == -1 || l > ep - p) {
+ buf[0] = '\0';
+ return NULL;
+ }
+ v >>= i; off += i;
+ }
+
+ return buf;
+}
+
+static const char *
+bitrange(tvbuff_t *tvb, int offset, int l, int s)
+{
+ static char buf[1024];
+ char *q, *eq;
+ int i;
+
+ memset(buf, 0, sizeof(buf));
+ q = buf;
+ eq = buf + sizeof(buf) - 1;
+ for (i = 0; i < l; i++) {
+ if (bitrange0(tvb_get_ntohl(tvb, offset + i * 4), s + i * 4, q, eq - q) == NULL) {
+ if (q != buf && q + 5 < buf + sizeof(buf))
+ strncpy(q, ",...", 5);
+ return buf;
+ }
+ }
+
+ return buf + 1;
+}
+
+static void
+dissect_nodeinfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ struct icmp6_nodeinfo icmp6_nodeinfo, *ni;
+ int off;
+ unsigned int j;
+ int i, n, l, p;
+ guint16 flags;
+ char dname[MAXDNAME];
+ guint8 ipaddr[4];
+
+ ni = &icmp6_nodeinfo;
+ tvb_memcpy(tvb, (guint8 *)ni, offset, sizeof *ni);
+ /* flags */
+ flags = pntohs(&ni->ni_flags);
+ tf = proto_tree_add_text(tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "Flags: 0x%04x", flags);
+ field_tree = proto_item_add_subtree(tf, ett_nodeinfo_flag);
+ switch (pntohs(&ni->ni_qtype)) {
+ case NI_QTYPE_SUPTYPES:
+ if (ni->ni_type == ICMP6_NI_QUERY) {
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "%s",
+ decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
+ "Compressed reply supported",
+ "No compressed reply support"));
+ } else {
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "%s",
+ decode_boolean_bitfield(flags, NI_SUPTYPE_FLAG_COMPRESS, sizeof(flags) * 8,
+ "Compressed", "Not compressed"));
+ }
+ break;
+ case NI_QTYPE_DNSNAME:
+ if (ni->ni_type == ICMP6_NI_REPLY) {
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "%s",
+ decode_boolean_bitfield(flags, NI_FQDN_FLAG_VALIDTTL, sizeof(flags) * 8,
+ "Valid TTL field", "Meaningless TTL field"));
+ }
+ break;
+ case NI_QTYPE_NODEADDR:
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "%s",
+ decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_GLOBAL, sizeof(flags) * 8,
+ "Global address",
+ "Not global address"));
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "%s",
+ decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_SITELOCAL, sizeof(flags) * 8,
+ "Site-local address",
+ "Not site-local address"));
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "%s",
+ decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_LINKLOCAL, sizeof(flags) * 8,
+ "Link-local address",
+ "Not link-local address"));
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "%s",
+ decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_COMPAT, sizeof(flags) * 8,
+ "IPv4 compatible/mapped address",
+ "Not IPv4 compatible/mapped address"));
+ /* fall through */
+ case NI_QTYPE_IPV4ADDR:
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "%s",
+ decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_ALL, sizeof(flags) * 8,
+ "All unicast address",
+ "Unicast addresses on the queried interface"));
+ proto_tree_add_text(field_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_flags),
+ sizeof(ni->ni_flags), "%s",
+ decode_boolean_bitfield(flags, NI_NODEADDR_FLAG_TRUNCATE, sizeof(flags) * 8,
+ "Truncated", "Not truncated"));
+ break;
+ }
+
+ /* nonce */
+ proto_tree_add_text(tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, icmp6_ni_nonce[0]),
+ sizeof(ni->icmp6_ni_nonce), "Nonce: 0x%08x%08x",
+ pntohl(&ni->icmp6_ni_nonce[0]), pntohl(&ni->icmp6_ni_nonce[4]));
+
+ /* offset for "the rest of data" */
+ off = sizeof(*ni);
+
+ /* rest of data */
+ if (!tvb_bytes_exist(tvb, offset, sizeof(*ni)))
+ goto nodata;
+ if (ni->ni_type == ICMP6_NI_QUERY) {
+ switch (ni->ni_code) {
+ case ICMP6_NI_SUBJ_IPV6:
+ n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
+ n /= sizeof(struct e_in6_addr);
+ tf = proto_tree_add_text(tree, tvb,
+ offset + sizeof(*ni), -1, "IPv6 subject addresses");
+ field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject6);
+ p = offset + sizeof *ni;
+ for (i = 0; i < n; i++) {
+ struct e_in6_addr e_in6_addr;
+ tvb_memcpy(tvb, (guint8 *)&e_in6_addr, p, sizeof e_in6_addr);
+ proto_tree_add_text(field_tree, tvb,
+ p, sizeof(struct e_in6_addr),
+ "%s", ip6_to_str(&e_in6_addr));
+ p += sizeof(struct e_in6_addr);
+ }
+ off = tvb_length_remaining(tvb, offset);
+ break;
+ case ICMP6_NI_SUBJ_FQDN:
+ l = get_dns_name(tvb, offset + sizeof(*ni),
+ offset + sizeof(*ni), dname, sizeof(dname));
+ if (tvb_bytes_exist(tvb, offset + sizeof(*ni) + l, 1) &&
+ tvb_get_guint8(tvb, offset + sizeof(*ni) + l) == 0) {
+ l++;
+ proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
+ "DNS label: %s (truncated)", dname);
+ } else {
+ proto_tree_add_text(tree, tvb, offset + sizeof(*ni), l,
+ "DNS label: %s", dname);
+ }
+ off = tvb_length_remaining(tvb, offset + sizeof(*ni) + l);
+ break;
+ case ICMP6_NI_SUBJ_IPV4:
+ n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
+ n /= sizeof(guint32);
+ tf = proto_tree_add_text(tree, tvb,
+ offset + sizeof(*ni), -1, "IPv4 subject addresses");
+ field_tree = proto_item_add_subtree(tf, ett_nodeinfo_subject4);
+ p = offset + sizeof *ni;
+ for (i = 0; i < n; i++) {
+ tvb_memcpy(tvb, ipaddr, p, 4);
+ proto_tree_add_text(field_tree, tvb,
+ p, sizeof(guint32), "%s", ip_to_str(ipaddr));
+ p += sizeof(guint32);
+ }
+ off = tvb_length_remaining(tvb, offset);
+ break;
+ }
+ } else {
+ switch (pntohs(&ni->ni_qtype)) {
+ case NI_QTYPE_NOOP:
+ break;
+ case NI_QTYPE_SUPTYPES:
+ p = offset + sizeof *ni;
+ tf = proto_tree_add_text(tree, tvb,
+ offset + sizeof(*ni), -1,
+ "Supported type bitmap%s",
+ (flags & 0x0001) ? ", compressed" : "");
+ field_tree = proto_item_add_subtree(tf,
+ ett_nodeinfo_nodebitmap);
+ n = 0;
+ while (tvb_bytes_exist(tvb, p, sizeof(guint32))) { /* XXXX Check what? */
+ if ((flags & 0x0001) == 0) {
+ l = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
+ l /= sizeof(guint32);
+ i = 0;
+ } else {
+ l = tvb_get_ntohs(tvb, p);
+ i = tvb_get_ntohs(tvb, p + sizeof(guint16)); /*skip*/
+ }
+ if (n + l * 32 > (1 << 16))
+ break;
+ if (n + (l + i) * 32 > (1 << 16))
+ break;
+ if ((flags & 0x0001) == 0) {
+ proto_tree_add_text(field_tree, tvb, p,
+ l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
+ bitrange(tvb, p, l, n));
+ p += l * 4;
+ } else {
+ proto_tree_add_text(field_tree, tvb, p,
+ 4 + l * 4, "Bitmap (%d to %d): %s", n, n + l * 32 - 1,
+ bitrange(tvb, p + 4, l, n));
+ p += (4 + l * 4);
+ }
+ n += l * 32 + i * 32;
+ }
+ off = tvb_length_remaining(tvb, offset);
+ break;
+ case NI_QTYPE_DNSNAME:
+ proto_tree_add_text(tree, tvb, offset + sizeof(*ni),
+ sizeof(gint32), "TTL: %d", (gint32)tvb_get_ntohl(tvb, offset + sizeof *ni));
+ tf = proto_tree_add_text(tree, tvb,
+ offset + sizeof(*ni) + sizeof(guint32), -1,
+ "DNS labels");
+ field_tree = proto_item_add_subtree(tf, ett_nodeinfo_nodedns);
+ j = offset + sizeof (*ni) + sizeof(guint32);
+ while (j < tvb_reported_length(tvb)) {
+ l = get_dns_name(tvb, j,
+ offset + sizeof (*ni) + sizeof(guint32),
+ dname,sizeof(dname));
+ if (tvb_bytes_exist(tvb, j + l, 1) &&
+ tvb_get_guint8(tvb, j + l) == 0) {
+ l++;
+ proto_tree_add_text(field_tree, tvb, j, l,
+ "DNS label: %s (truncated)", dname);
+ } else {
+ proto_tree_add_text(field_tree, tvb, j, l,
+ "DNS label: %s", dname);
+ }
+ j += l;
+ }
+ off = tvb_length_remaining(tvb, offset);
+ break;
+ case NI_QTYPE_NODEADDR:
+ n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
+ n /= sizeof(gint32) + sizeof(struct e_in6_addr);
+ tf = proto_tree_add_text(tree, tvb,
+ offset + sizeof(*ni), -1, "IPv6 node addresses");
+ field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node6);
+ p = offset + sizeof (*ni);
+ for (i = 0; i < n; i++) {
+ struct e_in6_addr e_in6_addr;
+ gint32 ttl;
+ ttl = (gint32)tvb_get_ntohl(tvb, p);
+ tvb_memcpy(tvb, (guint8 *)&e_in6_addr, p + sizeof ttl, sizeof e_in6_addr);
+ proto_tree_add_text(field_tree, tvb,
+ p, sizeof(struct e_in6_addr) + sizeof(gint32),
+ "%s (TTL %d)", ip6_to_str(&e_in6_addr), ttl);
+ p += sizeof(struct e_in6_addr) + sizeof(gint32);
+ }
+ off = tvb_length_remaining(tvb, offset);
+ break;
+ case NI_QTYPE_IPV4ADDR:
+ n = tvb_reported_length_remaining(tvb, offset + sizeof(*ni));
+ n /= sizeof(gint32) + sizeof(guint32);
+ tf = proto_tree_add_text(tree, tvb,
+ offset + sizeof(*ni), -1, "IPv4 node addresses");
+ field_tree = proto_item_add_subtree(tf, ett_nodeinfo_node4);
+ p = offset + sizeof *ni;
+ for (i = 0; i < n; i++) {
+ tvb_memcpy(tvb, ipaddr, sizeof(gint32) + p, 4);
+ proto_tree_add_text(field_tree, tvb,
+ p, sizeof(guint32), "%s (TTL %d)", ip_to_str(ipaddr), tvb_get_ntohl(tvb, p));
+ p += sizeof(gint32) + sizeof(guint32);
+ }
+ off = tvb_length_remaining(tvb, offset);
+ break;
+ }
+ }
+nodata:;
+
+ /* the rest of data */
+ call_dissector(data_handle,tvb_new_subset(tvb, offset + off, -1, -1), pinfo, tree);
+}
+
+static void
+dissect_rrenum(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *field_tree, *opt_tree;
+ proto_item *tf;
+ struct icmp6_router_renum icmp6_router_renum, *rr;
+ struct rr_pco_match rr_pco_match, *match;
+ struct rr_pco_use rr_pco_use, *use;
+ int flagoff, off;
+ unsigned int l;
+ guint8 flags;
+
+ rr = &icmp6_router_renum;
+ tvb_memcpy(tvb, (guint8 *)rr, offset, sizeof *rr);
+ proto_tree_add_text(tree, tvb,
+ offset + offsetof(struct icmp6_router_renum, rr_seqnum), 4,
+ "Sequence number: 0x%08x", pntohl(&rr->rr_seqnum));
+ proto_tree_add_text(tree, tvb,
+ offset + offsetof(struct icmp6_router_renum, rr_segnum), 1,
+ "Segment number: 0x%02x", rr->rr_segnum);
+
+ flagoff = offset + offsetof(struct icmp6_router_renum, rr_flags);
+ flags = tvb_get_guint8(tvb, flagoff);
+ tf = proto_tree_add_text(tree, tvb, flagoff, 1,
+ "Flags: 0x%02x", flags);
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(flags, 0x80, 8,
+ "Test command", "Not test command"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(flags, 0x40, 8,
+ "Result requested", "Result not requested"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(flags, 0x20, 8,
+ "All interfaces", "Not all interfaces"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(flags, 0x10, 8,
+ "Site specific", "Not site specific"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(flags, 0x08, 8,
+ "Processed previously", "Complete result"));
+
+ proto_tree_add_text(tree, tvb,
+ offset + offsetof(struct icmp6_router_renum, rr_maxdelay), 2,
+ "Max delay: 0x%04x", pntohs(&rr->rr_maxdelay));
+ call_dissector(data_handle,tvb_new_subset(tvb, offset + sizeof(*rr), -1, -1), pinfo, tree); /*XXX*/
+
+ if (rr->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) {
+ off = offset + sizeof(*rr);
+ match = &rr_pco_match;
+ tvb_memcpy(tvb, (guint8 *)match, off, sizeof *match);
+ tf = proto_tree_add_text(tree, tvb, off, sizeof(*match),
+ "Match-Prefix: %s/%u (%u-%u)", ip6_to_str(&match->rpm_prefix),
+ match->rpm_matchlen, match->rpm_minlen, match->rpm_maxlen);
+ opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_match, rpm_code),
+ sizeof(match->rpm_code), "OpCode: %s (%u)",
+ val_to_str(match->rpm_code, names_rrenum_matchcode, "Unknown"),
+ match->rpm_code);
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_match, rpm_len),
+ sizeof(match->rpm_len), "OpLength: %u (%u octets)",
+ match->rpm_len, match->rpm_len * 8);
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_match, rpm_ordinal),
+ sizeof(match->rpm_ordinal), "Ordinal: %u", match->rpm_ordinal);
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_match, rpm_matchlen),
+ sizeof(match->rpm_matchlen), "MatchLen: %u", match->rpm_matchlen);
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_match, rpm_minlen),
+ sizeof(match->rpm_minlen), "MinLen: %u", match->rpm_minlen);
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_match, rpm_maxlen),
+ sizeof(match->rpm_maxlen), "MaxLen: %u", match->rpm_maxlen);
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_match, rpm_prefix),
+ sizeof(match->rpm_prefix), "MatchPrefix: %s",
+ ip6_to_str(&match->rpm_prefix));
+
+ off += sizeof(*match);
+ use = &rr_pco_use;
+ for (l = match->rpm_len * 8 - sizeof(*match);
+ l >= sizeof(*use); l -= sizeof(*use), off += sizeof(*use)) {
+ tvb_memcpy(tvb, (guint8 *)use, off, sizeof *use);
+ tf = proto_tree_add_text(tree, tvb, off, sizeof(*use),
+ "Use-Prefix: %s/%u (keep %u)", ip6_to_str(&use->rpu_prefix),
+ use->rpu_uselen, use->rpu_keeplen);
+ opt_tree = proto_item_add_subtree(tf, ett_icmpv6opt);
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_use, rpu_uselen),
+ sizeof(use->rpu_uselen), "UseLen: %u", use->rpu_uselen);
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_use, rpu_keeplen),
+ sizeof(use->rpu_keeplen), "KeepLen: %u", use->rpu_keeplen);
+ tf = proto_tree_add_text(opt_tree, tvb,
+ flagoff = off + offsetof(struct rr_pco_use, rpu_ramask),
+ sizeof(use->rpu_ramask), "FlagMask: 0x%x", use->rpu_ramask);
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ flags = tvb_get_guint8(tvb, flagoff);
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(flags,
+ ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
+ "Onlink", "Not onlink"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(flags,
+ ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8,
+ "Auto", "Not auto"));
+ tf = proto_tree_add_text(opt_tree, tvb,
+ flagoff = off + offsetof(struct rr_pco_use, rpu_raflags),
+ sizeof(use->rpu_raflags), "RAFlags: 0x%x", use->rpu_raflags);
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ flags = tvb_get_guint8(tvb, flagoff);
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(flags,
+ ICMP6_RR_PCOUSE_RAFLAGS_ONLINK, 8,
+ "Onlink", "Not onlink"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(flags,
+ ICMP6_RR_PCOUSE_RAFLAGS_AUTO, 8, "Auto", "Not auto"));
+ if (pntohl(&use->rpu_vltime) == 0xffffffff)
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_use, rpu_vltime),
+ sizeof(use->rpu_vltime), "Valid Lifetime: infinity");
+ else
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_use, rpu_vltime),
+ sizeof(use->rpu_vltime), "Valid Lifetime: %u",
+ pntohl(&use->rpu_vltime));
+ if (pntohl(&use->rpu_pltime) == 0xffffffff)
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_use, rpu_pltime),
+ sizeof(use->rpu_pltime), "Preferred Lifetime: infinity");
+ else
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_use, rpu_pltime),
+ sizeof(use->rpu_pltime), "Preferred Lifetime: %u",
+ pntohl(&use->rpu_pltime));
+ tf = proto_tree_add_text(opt_tree, tvb,
+ flagoff = off + offsetof(struct rr_pco_use, rpu_flags),
+ sizeof(use->rpu_flags), "Flags: 0x%08x",
+ pntohl(&use->rpu_flags));
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ flags = tvb_get_guint8(tvb, flagoff);
+ proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
+ decode_boolean_bitfield(flags,
+ ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, 32,
+ "Decrement valid lifetime", "No decrement valid lifetime"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
+ decode_boolean_bitfield(flags,
+ ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, 32,
+ "Decrement preferred lifetime",
+ "No decrement preferred lifetime"));
+ proto_tree_add_text(opt_tree, tvb,
+ off + offsetof(struct rr_pco_use, rpu_prefix),
+ sizeof(use->rpu_prefix), "UsePrefix: %s",
+ ip6_to_str(&use->rpu_prefix));
+ }
+
+ }
+}
+
+/*
+ * See I-D draft-vida-mld-v2-08
+ */
+static const value_string mldrv2ModesNames[] = {
+ { 1, "Include" },
+ { 2, "Exclude" },
+ { 3, "Changed to include" },
+ { 4, "Changed to exclude" },
+ { 5, "Allow new sources" },
+ { 6, "Block old sources" },
+ { 0, NULL }
+};
+
+static void
+dissect_mldrv2( tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree )
+{
+ proto_tree *sub_tree;
+ proto_item *tf;
+
+ guint8 recordType, auxDataLen;
+ guint32 sourceNb, recordSize, localOffset;
+ struct e_in6_addr addr;
+
+ for( ; count; count--, offset += recordSize ) {
+ localOffset = offset;
+ recordType = tvb_get_guint8( tvb, localOffset );
+ localOffset += 1;
+ auxDataLen = tvb_get_guint8( tvb, localOffset );
+ localOffset += 1;
+ sourceNb = tvb_get_ntohs( tvb, localOffset );
+ localOffset += 2;
+ recordSize = 4 + 16 + (16 * sourceNb) + (auxDataLen * 4);
+
+ tvb_memcpy(tvb, (guint8 *)&addr, localOffset, sizeof(addr) );
+ tf = proto_tree_add_text( tree, tvb, offset, recordSize,
+#ifdef INET6
+ "%s: %s (%s)", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
+ get_hostname6(&addr), ip6_to_str(&addr)
+#else
+ "%s: %s", val_to_str(recordType, mldrv2ModesNames,"Unknown mode"),
+ ip6_to_str(&addr)
+#endif
+ );
+ sub_tree = proto_item_add_subtree(tf, ett_multicastRR);
+
+ proto_tree_add_text( sub_tree, tvb, offset, 1, "Mode: %s",
+ val_to_str(recordType, mldrv2ModesNames,"Unknown mode") );
+ proto_tree_add_text( sub_tree, tvb, offset+1, 1, "Aux data len: %u", auxDataLen * 4);
+ proto_tree_add_text( sub_tree, tvb, localOffset, 16, "Multicast Address: %s", ip6_to_str(&addr) );
+ localOffset += 16;
+
+ for( ; sourceNb; sourceNb--, localOffset += 16 ) {
+ tvb_memcpy(tvb, (guint8 *)&addr, localOffset, sizeof(addr) );
+ proto_tree_add_text( sub_tree, tvb, localOffset, 16,
+#ifdef INET6
+ "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr) );
+#else
+ "Source Address: %s", ip6_to_str(&addr) );
+#endif
+ }
+ }
+}
+
+static void
+dissect_mldqv2(tvbuff_t *tvb, guint32 offset, guint16 count, proto_tree *tree)
+{
+ struct e_in6_addr addr;
+
+ for ( ; count; count--, offset += 16) {
+ tvb_memcpy(tvb, (guint8 *)&addr, offset, sizeof(addr));
+ proto_tree_add_text(tree, tvb, offset, 16,
+ "Source Address: %s (%s)", get_hostname6(&addr), ip6_to_str(&addr));
+ }
+}
+
+static void
+dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *icmp6_tree, *field_tree;
+ proto_item *ti, *tf = NULL;
+ struct icmp6_hdr icmp6_hdr, *dp;
+ struct icmp6_nodeinfo *ni = NULL;
+ char *codename, *typename;
+ char *colcodename, *coltypename;
+ int len;
+ guint length, reported_length;
+ vec_t cksum_vec[4];
+ guint32 phdr[2];
+ guint16 cksum, computed_cksum;
+ int offset;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMPv6");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ offset = 0;
+ tvb_memcpy(tvb, (guint8 *)&icmp6_hdr, offset, sizeof icmp6_hdr);
+ dp = &icmp6_hdr;
+ codename = typename = colcodename = coltypename = "Unknown";
+ len = sizeof(*dp);
+ switch (dp->icmp6_type) {
+ case ICMP6_DST_UNREACH:
+ typename = coltypename = "Unreachable";
+ switch (dp->icmp6_code) {
+ case ICMP6_DST_UNREACH_NOROUTE:
+ codename = colcodename = "Route unreachable";
+ break;
+ case ICMP6_DST_UNREACH_ADMIN:
+ codename = colcodename = "Administratively prohibited";
+ break;
+ case ICMP6_DST_UNREACH_NOTNEIGHBOR:
+ codename = colcodename = "Not a neighbor";
+ break;
+ case ICMP6_DST_UNREACH_ADDR:
+ codename = colcodename = "Address unreachable";
+ break;
+ case ICMP6_DST_UNREACH_NOPORT:
+ codename = colcodename = "Port unreachable";
+ break;
+ }
+ break;
+ case ICMP6_PACKET_TOO_BIG:
+ typename = coltypename = "Too big";
+ codename = colcodename = NULL;
+ break;
+ case ICMP6_TIME_EXCEEDED:
+ typename = coltypename = "Time exceeded";
+ switch (dp->icmp6_code) {
+ case ICMP6_TIME_EXCEED_TRANSIT:
+ codename = colcodename = "In-transit";
+ break;
+ case ICMP6_TIME_EXCEED_REASSEMBLY:
+ codename = colcodename = "Reassembly";
+ break;
+ }
+ break;
+ case ICMP6_PARAM_PROB:
+ typename = coltypename = "Parameter problem";
+ switch (dp->icmp6_code) {
+ case ICMP6_PARAMPROB_HEADER:
+ codename = colcodename = "Header";
+ break;
+ case ICMP6_PARAMPROB_NEXTHEADER:
+ codename = colcodename = "Next header";
+ break;
+ case ICMP6_PARAMPROB_OPTION:
+ codename = colcodename = "Option";
+ break;
+ }
+ break;
+ case ICMP6_ECHO_REQUEST:
+ typename = coltypename = "Echo request";
+ codename = colcodename = NULL;
+ break;
+ case ICMP6_ECHO_REPLY:
+ typename = coltypename = "Echo reply";
+ codename = colcodename = NULL;
+ break;
+ case ICMP6_MEMBERSHIP_QUERY:
+ typename = coltypename = "Multicast listener query";
+ codename = colcodename = NULL;
+ break;
+ case ICMP6_MEMBERSHIP_REPORT:
+ typename = coltypename = "Multicast listener report";
+ codename = colcodename = NULL;
+ break;
+ case ICMP6_MEMBERSHIP_REDUCTION:
+ typename = coltypename = "Multicast listener done";
+ codename = colcodename = NULL;
+ break;
+ case ND_ROUTER_SOLICIT:
+ typename = coltypename = "Router solicitation";
+ codename = colcodename = NULL;
+ len = sizeof(struct nd_router_solicit);
+ break;
+ case ND_ROUTER_ADVERT:
+ typename = coltypename = "Router advertisement";
+ codename = colcodename = NULL;
+ len = sizeof(struct nd_router_advert);
+ break;
+ case ND_NEIGHBOR_SOLICIT:
+ typename = coltypename = "Neighbor solicitation";
+ codename = colcodename = NULL;
+ len = sizeof(struct nd_neighbor_solicit);
+ break;
+ case ND_NEIGHBOR_ADVERT:
+ typename = coltypename = "Neighbor advertisement";
+ codename = colcodename = NULL;
+ len = sizeof(struct nd_neighbor_advert);
+ break;
+ case ND_REDIRECT:
+ typename = coltypename = "Redirect";
+ codename = colcodename = NULL;
+ len = sizeof(struct nd_redirect);
+ break;
+ case ICMP6_ROUTER_RENUMBERING:
+ typename = coltypename = "Router renumbering";
+ switch (dp->icmp6_code) {
+ case ICMP6_ROUTER_RENUMBERING_COMMAND:
+ codename = colcodename = "Command";
+ break;
+ case ICMP6_ROUTER_RENUMBERING_RESULT:
+ codename = colcodename = "Result";
+ break;
+ case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET:
+ codename = colcodename = "Sequence number reset";
+ break;
+ }
+ len = sizeof(struct icmp6_router_renum);
+ break;
+ case ICMP6_NI_QUERY:
+ case ICMP6_NI_REPLY:
+ ni = (struct icmp6_nodeinfo *)dp;
+ if (ni->ni_type == ICMP6_NI_QUERY) {
+ typename = coltypename = "Node information query";
+ switch (ni->ni_code) {
+ case ICMP6_NI_SUBJ_IPV6:
+ codename = "Query subject = IPv6 addresses";
+ break;
+ case ICMP6_NI_SUBJ_FQDN:
+ if (tvb_bytes_exist(tvb, offset, sizeof(*ni)))
+ codename = "Query subject = DNS name";
+ else
+ codename = "Query subject = empty";
+ break;
+ case ICMP6_NI_SUBJ_IPV4:
+ codename = "Query subject = IPv4 addresses";
+ break;
+ }
+ } else {
+ typename = coltypename = "Node information reply";
+ switch (ni->ni_code) {
+ case ICMP6_NI_SUCCESS:
+ codename = "Successful";
+ break;
+ case ICMP6_NI_REFUSED:
+ codename = "Refused";
+ break;
+ case ICMP6_NI_UNKNOWN:
+ codename = "Unknown query type";
+ break;
+ }
+ }
+ colcodename = val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype,
+ "Unknown");
+ len = sizeof(struct icmp6_nodeinfo);
+ break;
+ case ICMP6_MIP6_DHAAD_REQUEST:
+ typename = coltypename = "Dynamic Home Agent Address Discovery Request";
+ codename = "Should always be zero";
+ colcodename = NULL;
+ break;
+ case ICMP6_MIP6_DHAAD_REPLY:
+ typename = coltypename = "Dynamic Home Agent Address Discovery Reply";
+ codename = "Should always be zero";
+ colcodename = NULL;
+ break;
+ case ICMP6_MIP6_MPS:
+ typename = coltypename = "Mobile Prefix Solicitation";
+ codename = "Should always be zero";
+ colcodename = NULL;
+ break;
+ case ICMP6_MIP6_MPA:
+ typename = coltypename = "Mobile Prefix Advertisement";
+ codename = "Should always be zero";
+ colcodename = NULL;
+ break;
+ case ICMP6_MLDV2_REPORT:
+ typename = coltypename = "Multicast Listener Report Message v2";
+ codename = "Should always be zero";
+ colcodename = NULL;
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ char typebuf[256], codebuf[256];
+
+ if (coltypename && strcmp(coltypename, "Unknown") == 0) {
+ snprintf(typebuf, sizeof(typebuf), "Unknown (0x%02x)",
+ dp->icmp6_type);
+ coltypename = typebuf;
+ }
+ if (colcodename && strcmp(colcodename, "Unknown") == 0) {
+ snprintf(codebuf, sizeof(codebuf), "Unknown (0x%02x)",
+ dp->icmp6_code);
+ colcodename = codebuf;
+ }
+ if (colcodename) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (%s)", coltypename, colcodename);
+ } else {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", coltypename);
+ }
+ }
+
+ if (tree) {
+ /* !!! specify length */
+ ti = proto_tree_add_item(tree, proto_icmpv6, tvb, offset, len, FALSE);
+ icmp6_tree = proto_item_add_subtree(ti, ett_icmpv6);
+
+ proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_type, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_type), 1,
+ dp->icmp6_type,
+ "Type: %u (%s)", dp->icmp6_type, typename);
+ if (codename) {
+ proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
+ dp->icmp6_code,
+ "Code: %u (%s)", dp->icmp6_code, codename);
+ } else {
+ proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_code, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_code), 1,
+ dp->icmp6_code,
+ "Code: %u", dp->icmp6_code);
+ }
+ cksum = (guint16)g_htons(dp->icmp6_cksum);
+ length = tvb_length(tvb);
+ reported_length = tvb_reported_length(tvb);
+ if (!pinfo->fragmented && length >= reported_length) {
+ /* The packet isn't part of a fragmented datagram and isn't
+ truncated, so we can checksum it. */
+
+ /* Set up the fields of the pseudo-header. */
+ cksum_vec[0].ptr = pinfo->src.data;
+ cksum_vec[0].len = pinfo->src.len;
+ cksum_vec[1].ptr = pinfo->dst.data;
+ cksum_vec[1].len = pinfo->dst.len;
+ cksum_vec[2].ptr = (const guint8 *)&phdr;
+ phdr[0] = g_htonl(tvb_reported_length(tvb));
+ phdr[1] = g_htonl(IP_PROTO_ICMPV6);
+ cksum_vec[2].len = 8;
+ cksum_vec[3].len = tvb_reported_length(tvb);
+ cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, cksum_vec[3].len);
+ computed_cksum = in_cksum(cksum_vec, 4);
+ if (computed_cksum == 0) {
+ proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
+ tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
+ cksum,
+ "Checksum: 0x%04x (correct)", cksum);
+ } else {
+ proto_tree_add_boolean_hidden(icmp6_tree, hf_icmpv6_checksum_bad,
+ tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
+ TRUE);
+ proto_tree_add_uint_format(icmp6_tree, hf_icmpv6_checksum,
+ tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
+ cksum,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ cksum, in_cksum_shouldbe(cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_uint(icmp6_tree, hf_icmpv6_checksum, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_cksum), 2,
+ cksum);
+ }
+
+ /* decode... */
+ switch (dp->icmp6_type) {
+ case ICMP6_DST_UNREACH:
+ case ICMP6_TIME_EXCEEDED:
+ dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
+ icmp6_tree);
+ break;
+ case ICMP6_PACKET_TOO_BIG:
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_mtu), 4,
+ "MTU: %u", pntohl(&dp->icmp6_mtu));
+ dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
+ icmp6_tree);
+ break;
+ case ICMP6_PARAM_PROB:
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_pptr), 4,
+ "Problem pointer: 0x%04x", pntohl(&dp->icmp6_pptr));
+ dissect_contained_icmpv6(tvb, offset + sizeof(*dp), pinfo,
+ icmp6_tree);
+ break;
+ case ICMP6_ECHO_REQUEST:
+ case ICMP6_ECHO_REPLY:
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_id), 2,
+ "ID: 0x%04x", (guint16)g_ntohs(dp->icmp6_id));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_seq), 2,
+ "Sequence: 0x%04x", (guint16)g_ntohs(dp->icmp6_seq));
+ next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, icmp6_tree);
+ break;
+ case ICMP6_MEMBERSHIP_QUERY:
+ case ICMP6_MEMBERSHIP_REPORT:
+ case ICMP6_MEMBERSHIP_REDUCTION:
+#define MLDV2_MINLEN 28
+#define MLDV1_MINLEN 24
+ if (dp->icmp6_type == ICMP6_MEMBERSHIP_QUERY) {
+ if (length >= MLDV2_MINLEN) {
+ guint32 mrc;
+ guint16 qqi;
+ guint8 flag;
+ guint16 nsrcs;
+
+ mrc = g_ntohs(dp->icmp6_maxdelay);
+ flag = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16);
+ qqi = tvb_get_guint8(tvb, offset + sizeof(*dp) + 16 + 1);
+ nsrcs = tvb_get_ntohs(tvb, offset + sizeof(*dp) + 16 + 2);
+
+ if (mrc >= 32768)
+ mrc = ((mrc & 0x0fff) | 0x1000) <<
+ (((mrc & 0x7000) >> 12) + 3);
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_maxdelay), 2,
+ "Maximum response delay[ms]: %u", mrc);
+
+ proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp),
+ 16, "Multicast Address: %s",
+ ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb,
+ offset + sizeof *dp, sizeof (struct e_in6_addr)))));
+
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + sizeof(*dp) + 16, 1, "S Flag: %s",
+ flag & 0x08 ? "ON" : "OFF");
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + sizeof(*dp) + 16, 1, "Robustness: %d",
+ flag & 0x07);
+ if (qqi >= 128)
+ qqi = ((qqi & 0x0f) | 0x10) << (((qqi & 0x70) >> 4) + 3);
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + sizeof(*dp) + 17, 1, "QQI: %d", qqi);
+
+ dissect_mldqv2(tvb, offset + sizeof(*dp) + 20, nsrcs,
+ icmp6_tree);
+ break;
+ } else if (length > MLDV1_MINLEN) {
+ next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ break;
+ }
+ /* MLDv1 Query -> FALLTHOUGH */
+ }
+#undef MLDV2_MINLEN
+#undef MLDV1_MINLEN
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct icmp6_hdr, icmp6_maxdelay), 2,
+ "Maximum response delay: %u",
+ (guint16)g_ntohs(dp->icmp6_maxdelay));
+ proto_tree_add_text(icmp6_tree, tvb, offset + sizeof(*dp), 16,
+ "Multicast Address: %s",
+ ip6_to_str((const struct e_in6_addr *)(tvb_get_ptr(tvb, offset + sizeof *dp, sizeof (struct e_in6_addr)))));
+ break;
+ case ND_ROUTER_SOLICIT:
+ dissect_icmpv6opt(tvb, offset + sizeof(*dp), pinfo, icmp6_tree);
+ break;
+ case ICMP6_MLDV2_REPORT: {
+ guint16 nbRecords;
+
+ nbRecords = tvb_get_ntohs( tvb, offset+4+2 );
+ dissect_mldrv2( tvb, offset+4+2+2, nbRecords, icmp6_tree );
+ break;
+ }
+ case ND_ROUTER_ADVERT:
+ {
+ struct nd_router_advert nd_router_advert, *ra;
+ int flagoff;
+ guint32 ra_flags;
+
+ ra = &nd_router_advert;
+ tvb_memcpy(tvb, (guint8 *)ra, offset, sizeof *ra);
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct nd_router_advert, nd_ra_curhoplimit),
+ 1, "Cur hop limit: %u", ra->nd_ra_curhoplimit);
+
+ flagoff = offset + offsetof(struct nd_router_advert, nd_ra_flags_reserved);
+ ra_flags = tvb_get_guint8(tvb, flagoff);
+ tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 1, "Flags: 0x%02x", ra_flags);
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(ra_flags,
+ ND_RA_FLAG_MANAGED, 8, "Managed", "Not managed"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(ra_flags,
+ ND_RA_FLAG_OTHER, 8, "Other", "Not other"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_boolean_bitfield(ra_flags,
+ ND_RA_FLAG_HOME_AGENT, 8,
+ "Home Agent", "Not Home Agent"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 1, "%s",
+ decode_enumerated_bitfield(ra_flags, ND_RA_FLAG_RTPREF_MASK, 8,
+ names_router_pref, "Router preference: %s"));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct nd_router_advert, nd_ra_router_lifetime),
+ 2, "Router lifetime: %u",
+ (guint16)g_ntohs(ra->nd_ra_router_lifetime));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct nd_router_advert, nd_ra_reachable), 4,
+ "Reachable time: %u", pntohl(&ra->nd_ra_reachable));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct nd_router_advert, nd_ra_retransmit), 4,
+ "Retrans time: %u", pntohl(&ra->nd_ra_retransmit));
+ dissect_icmpv6opt(tvb, offset + sizeof(struct nd_router_advert), pinfo, icmp6_tree);
+ break;
+ }
+ case ND_NEIGHBOR_SOLICIT:
+ {
+ struct nd_neighbor_solicit nd_neighbor_solicit, *ns;
+
+ ns = &nd_neighbor_solicit;
+ tvb_memcpy(tvb, (guint8 *)ns, offset, sizeof *ns);
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct nd_neighbor_solicit, nd_ns_target), 16,
+#ifdef INET6
+ "Target: %s (%s)",
+ get_hostname6(&ns->nd_ns_target),
+#else
+ "Target: %s",
+#endif
+ ip6_to_str(&ns->nd_ns_target));
+
+ dissect_icmpv6opt(tvb, offset + sizeof(*ns), pinfo, icmp6_tree);
+ break;
+ }
+ case ND_NEIGHBOR_ADVERT:
+ {
+ int flagoff, targetoff;
+ guint32 na_flags;
+ struct e_in6_addr na_target;
+
+ flagoff = offset + offsetof(struct nd_neighbor_advert, nd_na_flags_reserved);
+ na_flags = tvb_get_ntohl(tvb, flagoff);
+
+ tf = proto_tree_add_text(icmp6_tree, tvb, flagoff, 4, "Flags: 0x%08x", na_flags);
+ field_tree = proto_item_add_subtree(tf, ett_icmpv6flag);
+ proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
+ decode_boolean_bitfield(na_flags,
+ ND_NA_FLAG_ROUTER, 32, "Router", "Not router"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
+ decode_boolean_bitfield(na_flags,
+ ND_NA_FLAG_SOLICITED, 32, "Solicited", "Not adverted"));
+ proto_tree_add_text(field_tree, tvb, flagoff, 4, "%s",
+ decode_boolean_bitfield(na_flags,
+ ND_NA_FLAG_OVERRIDE, 32, "Override", "Not override"));
+
+ targetoff = offset + offsetof(struct nd_neighbor_advert, nd_na_target);
+ tvb_memcpy(tvb, (guint8 *)&na_target, targetoff, sizeof na_target);
+ proto_tree_add_text(icmp6_tree, tvb, targetoff, 16,
+#ifdef INET6
+ "Target: %s (%s)",
+ get_hostname6(&na_target),
+#else
+ "Target: %s",
+#endif
+ ip6_to_str(&na_target));
+
+ dissect_icmpv6opt(tvb, offset + sizeof(struct nd_neighbor_advert), pinfo, icmp6_tree);
+ break;
+ }
+ case ND_REDIRECT:
+ {
+ struct nd_redirect nd_redirect, *rd;
+
+ rd = &nd_redirect;
+ tvb_memcpy(tvb, (guint8 *)rd, offset, sizeof *rd);
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct nd_redirect, nd_rd_target), 16,
+#ifdef INET6
+ "Target: %s (%s)",
+ get_hostname6(&rd->nd_rd_target),
+#else
+ "Target: %s",
+#endif
+ ip6_to_str(&rd->nd_rd_target));
+
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct nd_redirect, nd_rd_dst), 16,
+#ifdef INET6
+ "Destination: %s (%s)",
+ get_hostname6(&rd->nd_rd_dst),
+#else
+ "Destination: %s",
+#endif
+ ip6_to_str(&rd->nd_rd_dst));
+
+ dissect_icmpv6opt(tvb, offset + sizeof(*rd), pinfo, icmp6_tree);
+ break;
+ }
+ case ICMP6_ROUTER_RENUMBERING:
+ dissect_rrenum(tvb, offset, pinfo, icmp6_tree);
+ break;
+ case ICMP6_NI_QUERY:
+ case ICMP6_NI_REPLY:
+ ni = (struct icmp6_nodeinfo *)dp;
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + offsetof(struct icmp6_nodeinfo, ni_qtype),
+ sizeof(ni->ni_qtype),
+ "Query type: 0x%04x (%s)", pntohs(&ni->ni_qtype),
+ val_to_str(pntohs(&ni->ni_qtype), names_nodeinfo_qtype,
+ "Unknown"));
+ dissect_nodeinfo(tvb, offset, pinfo, icmp6_tree);
+ break;
+ case ICMP6_MIP6_DHAAD_REQUEST:
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 4, 2, "Identifier: %d (0x%02x)",
+ tvb_get_ntohs(tvb, offset + 4),
+ tvb_get_ntohs(tvb, offset + 4));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 6, 2, "Reserved: %d",
+ tvb_get_ntohs(tvb, offset + 6));
+ break;
+ case ICMP6_MIP6_DHAAD_REPLY:
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 4, 2, "Identifier: %d (0x%02x)",
+ tvb_get_ntohs(tvb, offset + 4),
+ tvb_get_ntohs(tvb, offset + 4));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 6, 2, "Reserved: %d",
+ tvb_get_ntohs(tvb, offset + 6));
+ /* Show all Home Agent Addresses */
+ {
+ int i, suboffset;
+ int ha_num = (length - 8)/16;
+
+ for (i = 0; i < ha_num; i++) {
+ suboffset = 16 * i;
+ proto_tree_add_ipv6(icmp6_tree, hf_icmpv6_haad_ha_addrs,
+ tvb, offset + 8 + suboffset, 16,
+ tvb_get_ptr(tvb, offset + 8 + suboffset, 16));
+ }
+ }
+ break;
+ case ICMP6_MIP6_MPS:
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 4, 2, "Identifier: %d (0x%02x)",
+ tvb_get_ntohs(tvb, offset + 4),
+ tvb_get_ntohs(tvb, offset + 4));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 6, 2, "Reserved: %d",
+ tvb_get_ntohs(tvb, offset + 6));
+ break;
+ case ICMP6_MIP6_MPA:
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 4, 2, "Identifier: %d (0x%02x)",
+ tvb_get_ntohs(tvb, offset + 4),
+ tvb_get_ntohs(tvb, offset + 4));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 6, 1,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
+ 0x80, 8,
+ "Managed Address Configuration",
+ "No Managed Address Configuration"));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 6, 1,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset + 6),
+ 0x40, 8,
+ "Other Stateful Configuration",
+ "No Other Stateful Configuration"));
+ proto_tree_add_text(icmp6_tree, tvb,
+ offset + 7, 1, "Reserved: %d",
+ tvb_get_guint8(tvb, offset + 7));
+ /* Show all options */
+ dissect_icmpv6opt(tvb, offset + 8, pinfo, icmp6_tree);
+ break;
+ default:
+ next_tvb = tvb_new_subset(tvb, offset + sizeof(*dp), -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ break;
+ }
+ }
+}
+
+void
+proto_register_icmpv6(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_icmpv6_type,
+ { "Type", "icmpv6.type", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_icmpv6_code,
+ { "Code", "icmpv6.code", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_icmpv6_checksum,
+ { "Checksum", "icmpv6.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_icmpv6_checksum_bad,
+ { "Bad Checksum", "icmpv6.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_icmpv6_haad_ha_addrs,
+ { "Home Agent Addresses", "icmpv6.haad.ha_addrs",
+ FT_IPv6, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_icmpv6,
+ &ett_icmpv6opt,
+ &ett_icmpv6flag,
+ &ett_nodeinfo_flag,
+ &ett_nodeinfo_subject4,
+ &ett_nodeinfo_subject6,
+ &ett_nodeinfo_node4,
+ &ett_nodeinfo_node6,
+ &ett_nodeinfo_nodebitmap,
+ &ett_nodeinfo_nodedns,
+ &ett_multicastRR,
+ };
+
+ proto_icmpv6 = proto_register_protocol("Internet Control Message Protocol v6",
+ "ICMPv6", "icmpv6");
+ proto_register_field_array(proto_icmpv6, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_icmpv6(void)
+{
+ dissector_handle_t icmpv6_handle;
+
+ icmpv6_handle = create_dissector_handle(dissect_icmpv6, proto_icmpv6);
+ dissector_add("ip.proto", IP_PROTO_ICMPV6, icmpv6_handle);
+
+ /*
+ * Get a handle for the IPv6 dissector.
+ */
+ ipv6_handle = find_dissector("ipv6");
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-icp.c b/epan/dissectors/packet-icp.c
new file mode 100644
index 0000000000..83eea14ac9
--- /dev/null
+++ b/epan/dissectors/packet-icp.c
@@ -0,0 +1,254 @@
+/* packet-icp.c
+ * Routines for ICP (internet cache protocol) packet disassembly
+ * RFC 2186 && RFC 2187
+ * By Peter Torvals
+ * Copyright 1999 Peter Torvals
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define MAX_TEXTBUF_LENGTH 600
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+
+static int proto_icp=-1;
+static int hf_icp_length=-1;
+static int hf_icp_opcode=-1;
+static int hf_icp_version=-1;
+static int hf_icp_request_nr=-1;
+
+static gint ett_icp = -1;
+static gint ett_icp_payload = -1;
+
+#define UDP_PORT_ICP 3130
+
+#define CODE_ICP_OP_QUERY 1
+#define CODE_ICP_OP_INVALID 0
+#define CODE_ICP_OP_HIT 2
+#define CODE_ICP_OP_MISS 3
+#define CODE_ICP_OP_ERR 4
+#define CODE_ICP_OP_SEND 5
+#define CODE_ICP_OP_SENDA 6
+#define CODE_ICP_OP_DATABEG 7
+#define CODE_ICP_OP_DATA 8
+#define CODE_ICP_OP_DATAEND 9
+#define CODE_ICP_OP_SECHO 10
+#define CODE_ICP_OP_DECHO 11
+#define CODE_ICP_OP_MISS_NOFETCH 21
+#define CODE_ICP_OP_DENIED 22
+#define CODE_ICP_OP_HIT_OBJ 23
+
+static value_string opcode_vals[] = {
+{ CODE_ICP_OP_INVALID , "ICP_INVALID" },
+{ CODE_ICP_OP_QUERY , "ICP_QUERY" },
+{ CODE_ICP_OP_HIT , "ICP_HIT" },
+{ CODE_ICP_OP_MISS , "ICP_MISS" },
+{ CODE_ICP_OP_ERR , "ICP_ERR" },
+{ CODE_ICP_OP_SEND, "ICP_SEND" },
+{ CODE_ICP_OP_SENDA, "ICP_SENDA"},
+{ CODE_ICP_OP_DATABEG, "ICP_DATABEG"},
+{ CODE_ICP_OP_DATA, "ICP_DATA"},
+{ CODE_ICP_OP_DATAEND, "ICP_DATA_END"},
+{ CODE_ICP_OP_SECHO , "ICP_SECHO"},
+{ CODE_ICP_OP_DECHO , "ICP_DECHO"},
+{ CODE_ICP_OP_MISS_NOFETCH , "ICP_MISS_NOFETCH"},
+{ CODE_ICP_OP_DENIED , "ICP_DENIED"},
+{ CODE_ICP_OP_HIT_OBJ , "ICP_HIT_OBJ"},
+{ 0, NULL}
+};
+
+static void dissect_icp_payload(tvbuff_t *tvb, int offset,
+ proto_tree *pload_tree, guint8 opcode)
+{
+ gint stringlength;
+ guint16 objectlength;
+
+ switch(opcode)
+ {
+ case CODE_ICP_OP_QUERY:
+ /* 4 byte requester host address */
+ proto_tree_add_text(pload_tree, tvb,offset,4,
+ "Requester Host Address %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ /* null terminated URL */
+ stringlength = tvb_strsize(tvb, offset);
+ proto_tree_add_text(pload_tree, tvb, offset, stringlength,
+ "URL: %s", tvb_get_ptr(tvb, offset, stringlength));
+ break;
+
+ case CODE_ICP_OP_SECHO:
+ case CODE_ICP_OP_DECHO:
+ case CODE_ICP_OP_HIT:
+ case CODE_ICP_OP_MISS:
+ case CODE_ICP_OP_ERR:
+ case CODE_ICP_OP_MISS_NOFETCH:
+ case CODE_ICP_OP_DENIED:
+ stringlength = tvb_strsize(tvb, offset);
+ proto_tree_add_text(pload_tree, tvb, offset, stringlength,
+ "URL: %s", tvb_get_ptr(tvb, offset, stringlength));
+ break;
+
+ case CODE_ICP_OP_HIT_OBJ:
+ /* null terminated URL */
+ stringlength = tvb_strsize(tvb, offset);
+ proto_tree_add_text(pload_tree, tvb, offset, stringlength,
+ "URL: %s", tvb_get_ptr(tvb, offset, stringlength));
+ offset += stringlength;
+
+ /* 2 byte object size */
+ /* object data not recommended by standard*/
+ objectlength=tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(pload_tree, tvb,offset,2,"Object length: %u", objectlength);
+ offset += 2;
+
+ /* object data not recommended by standard*/
+ proto_tree_add_text(pload_tree, tvb,offset,objectlength,"Object data");
+ if (objectlength > tvb_reported_length_remaining(tvb, offset))
+ {
+ proto_tree_add_text(pload_tree, tvb,offset,0,
+ "Packet is fragmented, rest of object is in next udp packet");
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void dissect_icp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *icp_tree , *payload_tree;
+ proto_item *ti , *payloadtf;
+ guint8 opcode;
+ guint16 message_length;
+ guint32 request_number;
+ guint32 options;
+ guint32 option_data;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ opcode=tvb_get_guint8(tvb, 0);
+ message_length=tvb_get_ntohs(tvb, 2);
+ request_number=tvb_get_ntohl(tvb, 4);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_add_fstr(pinfo->cinfo,COL_INFO,"Opcode: %s (%u), Req Nr: %u",
+ val_to_str(opcode, opcode_vals, "Unknown"), opcode,
+ request_number);
+ }
+
+ if (tree)
+ {
+
+ ti = proto_tree_add_item(tree,proto_icp, tvb, 0, message_length, FALSE);
+ icp_tree = proto_item_add_subtree(ti, ett_icp);
+
+ proto_tree_add_uint(icp_tree,hf_icp_opcode, tvb, 0, 1, opcode);
+
+ proto_tree_add_item(icp_tree,hf_icp_version, tvb, 1, 1, FALSE);
+
+ proto_tree_add_uint(icp_tree,hf_icp_length, tvb, 2, 2, message_length);
+
+ proto_tree_add_uint(icp_tree,hf_icp_request_nr, tvb, 4, 4,
+ request_number);
+
+ options=tvb_get_ntohl(tvb, 8);
+ if ( (opcode == CODE_ICP_OP_QUERY) && ((options & 0x80000000 ) != 0) )
+ {
+ proto_tree_add_text(icp_tree, tvb,8,4,
+ "option: ICP_FLAG_HIT_OBJ");
+ }
+ if ( (opcode == CODE_ICP_OP_QUERY)&& ((options & 0x40000000 ) != 0) )
+ {
+ proto_tree_add_text(icp_tree, tvb,8,4,
+ "option:ICP_FLAG_SRC_RTT");
+ }
+ if ((opcode != CODE_ICP_OP_QUERY)&& ((options & 0x40000000 ) != 0))
+ {
+ option_data=tvb_get_ntohl(tvb, 12);
+ proto_tree_add_text(icp_tree, tvb,8,8,
+ "option: ICP_FLAG_SCR_RTT RTT=%u",
+ option_data & 0x0000ffff);
+ }
+
+ proto_tree_add_text(icp_tree, tvb, 16, 4,
+ "Sender Host IP address %s",
+ ip_to_str(tvb_get_ptr(tvb, 16, 4)));
+
+ payloadtf = proto_tree_add_text(icp_tree, tvb,
+ 20, message_length - 20,
+ "Payload");
+ payload_tree = proto_item_add_subtree(payloadtf, ett_icp_payload);
+ dissect_icp_payload(tvb, 20, payload_tree, opcode);
+ }
+}
+void
+proto_register_icp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_icp_opcode,
+ { "Opcode", "icp.opcode", FT_UINT8, BASE_HEX, VALS(opcode_vals),
+ 0x0, "", HFILL }},
+
+ { &hf_icp_version,
+ { "Version", "icp.version", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_icp_length,
+ { "Length", "icp.length", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_icp_request_nr,
+ { "Request Number", "icp.nr", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_icp,
+ &ett_icp_payload,
+ };
+
+ proto_icp = proto_register_protocol("Internet Cache Protocol",
+ "ICP", "icp");
+ proto_register_field_array(proto_icp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_icp(void)
+{
+ dissector_handle_t icp_handle;
+
+ icp_handle = create_dissector_handle(dissect_icp, proto_icp);
+ dissector_add("udp.port", UDP_PORT_ICP, icp_handle);
+}
diff --git a/epan/dissectors/packet-icq.c b/epan/dissectors/packet-icq.c
new file mode 100644
index 0000000000..407abe431f
--- /dev/null
+++ b/epan/dissectors/packet-icq.c
@@ -0,0 +1,2222 @@
+/* packet-icq.c
+ * Routines for ICQ packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This file: by Kojak <kojak@bigwig.net>
+ *
+ * Decoding code ripped, reference to the original author at the
+ * appropriate place with the code itself.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/resolv.h>
+
+static int proto_icq = -1;
+static int hf_icq_uin = -1;
+static int hf_icq_client_cmd = -1;
+static int hf_icq_server_cmd = -1;
+static int hf_icq_sessionid = -1;
+static int hf_icq_checkcode = -1;
+static int hf_icq_decode = -1;
+static int hf_icq_type = -1;
+
+static gint ett_icq = -1;
+static gint ett_icq_header = -1;
+static gint ett_icq_decode = -1;
+static gint ett_icq_body = -1;
+static gint ett_icq_body_parts = -1;
+
+#define UDP_PORT_ICQ 4000
+
+enum { ICQ5_client, ICQ5_server};
+
+static void dissect_icqv5(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree);
+
+static void
+dissect_icqv5Server(tvbuff_t *tvb,
+ int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ int pktsize);
+
+/* Offsets of fields in the ICQ headers */
+/* Can be 0x0002 or 0x0005 */
+#define ICQ_VERSION 0x00
+/* Is either one (server) or four (client) bytes long */
+/* Client header offsets */
+#define ICQ5_UNKNOWN 0x02
+#define ICQ5_CL_UIN 0x06
+#define ICQ5_CL_SESSIONID 0x0a
+#define ICQ5_CL_CMD 0x0e
+#define ICQ5_CL_SEQNUM1 0x10
+#define ICQ5_CL_SEQNUM2 0x12
+#define ICQ5_CL_CHECKCODE 0x14
+#define ICQ5_CL_PARAM 0x18
+#define ICQ5_CL_HDRSIZE 0x18
+
+/* Server header offsets */
+#define ICQ5_SRV_SESSIONID 0x03
+#define ICQ5_SRV_CMD 0x07
+#define ICQ5_SRV_SEQNUM1 0x09
+#define ICQ5_SRV_SEQNUM2 0x0b
+#define ICQ5_SRV_UIN 0x0d
+#define ICQ5_SRV_CHECKCODE 0x11
+#define ICQ5_SRV_PARAM 0x15
+#define ICQ5_SRV_HDRSIZE 0x15
+
+#define SRV_ACK 0x000a
+
+#define SRV_SILENT_TOO_LONG 0x001e
+
+#define SRV_GO_AWAY 0x0028
+
+#define SRV_NEW_UIN 0x0046
+
+/* LOGIN_REPLY is very scary. It has a lot of fields that are undocumented
+ * Only the IP field makes sense */
+#define SRV_LOGIN_REPLY 0x005a
+#define SRV_LOGIN_REPLY_IP 0x000c
+
+#define SRV_BAD_PASS 0x0064
+
+#define SRV_USER_ONLINE 0x006e
+#define SRV_USER_ONL_UIN 0x0000
+#define SRV_USER_ONL_IP 0x0004
+#define SRV_USER_ONL_PORT 0x0008
+#define SRV_USER_ONL_REALIP 0x000c
+#define SRV_USER_ONL_X1 0x0010
+#define SRV_USER_ONL_STATUS 0x0013
+#define SRV_USER_ONL_X2 0x0015
+
+#define SRV_USER_OFFLINE 0x0078
+#define SRV_USER_OFFLINE_UIN 0x0000
+
+#define SRV_MULTI 0x0212
+#define SRV_MULTI_NUM 0x0000
+
+#define SRV_META_USER 0x03de
+#define SRV_META_USER_SUBCMD 0x0000
+#define SRV_META_USER_RESULT 0x0002
+#define SRV_META_USER_DATA 0x0003
+
+#define SRV_UPDATE_SUCCESS 0x01e0
+
+#define SRV_UPDATE_FAIL 0x01ea
+
+/*
+ * ICQv5 SRV_META_USER subcommands
+ */
+#define META_EX_USER_FOUND 0x0190
+#define META_USER_FOUND 0x019a
+#define META_ABOUT 0x00e6
+#define META_USER_INFO 0x00c8
+
+#define SRV_RECV_MESSAGE 0x00dc
+#define SRV_RECV_MSG_UIN 0x0000
+#define SRV_RECV_MSG_YEAR 0x0004
+#define SRV_RECV_MSG_MONTH 0x0006
+#define SRV_RECV_MSG_DAY 0x0007
+#define SRV_RECV_MSG_HOUR 0x0008
+#define SRV_RECV_MSG_MINUTE 0x0009
+#define SRV_RECV_MSG_MSG_TYPE 0x000a
+
+#define SRV_RAND_USER 0x024e
+#define SRV_RAND_USER_UIN 0x0000
+#define SRV_RAND_USER_IP 0x0004
+#define SRV_RAND_USER_PORT 0x0008
+#define SRV_RAND_USER_REAL_IP 0x000c
+#define SRV_RAND_USER_CLASS 0x0010
+#define SRV_RAND_USER_X1 0x0011
+#define SRV_RAND_USER_STATUS 0x0015
+#define SRV_RAND_USER_TCP_VER 0x0019
+
+/* This message has the same structure as cmd_send_msg */
+#define SRV_SYS_DELIVERED_MESS 0x0104
+
+static const value_string serverMetaSubCmdCode[] = {
+ { META_USER_FOUND, "META_USER_FOUND" },
+ { META_EX_USER_FOUND, "META_EX_USER_FOUND" },
+ { META_ABOUT, "META_ABOUT" },
+ { META_USER_INFO, "META_USER_INFO" },
+ { 0, NULL }
+};
+
+static const value_string serverCmdCode[] = {
+ { SRV_ACK, "SRV_ACK" },
+ { SRV_SILENT_TOO_LONG, "SRV_SILENT_TOO_LONG" },
+ { SRV_GO_AWAY, "SRV_GO_AWAY" },
+ { SRV_NEW_UIN, "SRV_NEW_UIN" },
+ { SRV_LOGIN_REPLY, "SRV_LOGIN_REPLY" },
+ { SRV_BAD_PASS, "SRV_BAD_PASS" },
+ { SRV_USER_ONLINE, "SRV_USER_ONLINE" },
+ { SRV_USER_OFFLINE, "SRV_USER_OFFLINE" },
+ { 130, "SRV_QUERY" },
+ { 140, "SRV_USER_FOUND" },
+ { 160, "SRV_END_OF_SEARCH" },
+ { 180, "SRV_NEW_USER" },
+ { 200, "SRV_UPDATE_EXT" },
+ { SRV_RECV_MESSAGE, "SRV_RECV_MESSAGE" },
+ { 230, "SRV_END_OFFLINE_MESSAGES" },
+ { 240, "SRV_NOT_CONNECTED" },
+ { 250, "SRV_TRY_AGAIN" },
+ { SRV_SYS_DELIVERED_MESS, "SRV_SYS_DELIVERED_MESS" },
+ { 280, "SRV_INFO_REPLY" },
+ { 290, "SRV_EXT_INFO_REPLY" },
+ { 420, "SRV_STATUS_UPDATE" },
+ { 450, "SRV_SYSTEM_MESSAGE" },
+ { SRV_UPDATE_SUCCESS, "SRV_UPDATE_SUCCESS" },
+ { SRV_UPDATE_FAIL, "SRV_UPDATE_FAIL" },
+ { 500, "SRV_AUTH_UPDATE" },
+ { SRV_MULTI, "SRV_MULTI_PACKET" },
+ { 540, "SRV_END_CONTACTLIST_STATUS" },
+ { SRV_RAND_USER, "SRV_RAND_USER" },
+ { SRV_META_USER, "SRV_META_USER" },
+ { 0, NULL }
+};
+
+#define MSG_TEXT 0x0001
+#define MSG_URL 0x0004
+#define MSG_AUTH_REQ 0x0006
+#define MSG_AUTH 0x0008
+#define MSG_USER_ADDED 0x000c
+#define MSG_EMAIL 0x000e
+#define MSG_CONTACTS 0x0013
+
+#define STATUS_ONLINE 0x00000000
+#define STATUS_AWAY 0x00000001
+#define STATUS_DND 0x00000013
+#define STATUS_INVISIBLE 0x00000100
+#define STATUS_OCCUPIED 0x00000010
+#define STATUS_NA 0x00000004
+#define STATUS_CHAT 0x00000020
+
+/* Offsets for all packets measured from the start of the payload; i.e.
+ * with the ICQ header removed
+ */
+#define CMD_ACK 0x000a
+#define CMD_ACK_RANDOM 0x0000
+
+#define CMD_SEND_MSG 0x010E
+#define CMD_SEND_MSG_RECV_UIN 0x0000
+#define CMD_SEND_MSG_MSG_TYPE 0x0004
+#define CMD_SEND_MSG_MSG_LEN 0x0006
+#define CMD_SEND_MSG_MSG_TEXT 0x0008
+/* The rest of the packet should be a null-term string */
+
+#define CMD_LOGIN 0x03E8
+#define CMD_LOGIN_TIME 0x0000
+#define CMD_LOGIN_PORT 0x0004
+#define CMD_LOGIN_PASSLEN 0x0008
+#define CMD_LOGIN_PASSWD 0x000A
+/* The password is variable length; so when we've decoded the passwd,
+ * the structure starts counting at 0 again.
+ */
+#define CMD_LOGIN_IP 0x0004
+#define CMD_LOGIN_STATUS 0x0009
+
+#define CMD_CONTACT_LIST 0x0406
+#define CMD_CONTACT_LIST_NUM 0x0000
+
+#define CMD_USER_META 0x064a
+
+#define CMD_REG_NEW_USER 0x03fc
+
+#define CMD_ACK_MESSAGES 0x0442
+#define CMD_ACK_MESSAGES_RANDOM 0x0000
+
+#define CMD_KEEP_ALIVE 0x042e
+#define CMD_KEEP_ALIVE_RANDOM 0x0000
+
+#define CMD_SEND_TEXT_CODE 0x0438
+#define CMD_SEND_TEXT_CODE_LEN 0x0000
+#define CMD_SEND_TEXT_CODE_TEXT 0x0002
+
+#define CMD_MSG_TO_NEW_USER 0x0456
+
+#define CMD_QUERY_SERVERS 0x04ba
+
+#define CMD_QUERY_ADDONS 0x04c4
+
+#define CMD_STATUS_CHANGE 0x04d8
+#define CMD_STATUS_CHANGE_STATUS 0x0000
+
+#define CMD_ADD_TO_LIST 0x053c
+#define CMD_ADD_TO_LIST_UIN 0x0000
+
+#define CMD_RAND_SEARCH 0x056e
+#define CMD_RAND_SEARCH_GROUP 0x0000
+
+#define CMD_META_USER 0x064a
+
+static const value_string msgTypeCode[] = {
+ { MSG_TEXT, "MSG_TEXT" },
+ { MSG_URL, "MSG_URL" },
+ { MSG_AUTH_REQ, "MSG_AUTH_REQ" },
+ { MSG_AUTH, "MSG_AUTH" },
+ { MSG_USER_ADDED, "MSG_USER_ADDED" },
+ { MSG_EMAIL, "MSG_EMAIL" },
+ { MSG_CONTACTS, "MSG_CONTACTS" },
+ { 0, NULL }
+};
+
+static const value_string statusCode[] = {
+ { STATUS_ONLINE, "ONLINE" },
+ { STATUS_AWAY, "AWAY" },
+ { STATUS_DND, "DND" },
+ { STATUS_INVISIBLE, "INVISIBLE" },
+ { STATUS_OCCUPIED, "OCCUPIED" },
+ { STATUS_NA, "NA" },
+ { STATUS_CHAT, "Free for Chat" },
+ { 0, NULL }
+};
+
+static const value_string clientCmdCode[] = {
+ { CMD_ACK, "CMD_ACK" },
+ { CMD_SEND_MSG, "CMD_SEND_MESSAGE" },
+ { CMD_LOGIN, "CMD_LOGIN" },
+ { CMD_REG_NEW_USER, "CMD_REG_NEW_USER" },
+ { 1030, "CMD_CONTACT_LIST" },
+ { 1050, "CMD_SEARCH_UIN" },
+ { 1060, "CMD_SEARCH_USER" },
+ { 1070, "CMD_KEEP_ALIVE" },
+ { CMD_SEND_TEXT_CODE, "CMD_SEND_TEXT_CODE" },
+ { CMD_ACK_MESSAGES, "CMD_ACK_MESSAGES" },
+ { 1100, "CMD_LOGIN_1" },
+ { CMD_MSG_TO_NEW_USER, "CMD_MSG_TO_NEW_USER" },
+ { 1120, "CMD_INFO_REQ" },
+ { 1130, "CMD_EXT_INFO_REQ" },
+ { 1180, "CMD_CHANGE_PW" },
+ { 1190, "CMD_NEW_USER_INFO" },
+ { 1200, "CMD_UPDATE_EXT_INFO" },
+ { CMD_QUERY_SERVERS, "CMD_QUERY_SERVERS" },
+ { CMD_QUERY_ADDONS, "CMD_QUERY_ADDONS" },
+ { CMD_STATUS_CHANGE, "CMD_STATUS_CHANGE" },
+ { 1260, "CMD_NEW_USER_1" },
+ { 1290, "CMD_UPDATE_INFO" },
+ { 1300, "CMD_AUTH_UPDATE" },
+ { 1310, "CMD_KEEP_ALIVE2" },
+ { 1320, "CMD_LOGIN_2" },
+ { CMD_ADD_TO_LIST, "CMD_ADD_TO_LIST" },
+ { 1380, "CMD_RAND_SET" },
+ { CMD_RAND_SEARCH, "CMD_RAND_SEARCH" },
+ { CMD_META_USER, "CMD_META_USER" },
+ { 1700, "CMD_INVIS_LIST" },
+ { 1710, "CMD_VIS_LIST" },
+ { 1720, "CMD_UPDATE_LIST" },
+ { 0, NULL }
+};
+
+/*
+ * All ICQv5 decryption code thanx to Sebastien Dault (daus01@gel.usherb.ca)
+ */
+static const guchar
+table_v5 [] = {
+ 0x59, 0x60, 0x37, 0x6B, 0x65, 0x62, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x60, 0x57, 0x5B, 0x3D,
+ 0x5E, 0x34, 0x6D, 0x36, 0x50, 0x3F, 0x6F, 0x67, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x47, 0x63, 0x39,
+ 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x43, 0x69, 0x48, 0x33, 0x31, 0x64, 0x35, 0x5A, 0x4A, 0x42,
+ 0x56, 0x40, 0x67, 0x53, 0x41, 0x07, 0x6C, 0x49, 0x58, 0x3B, 0x4D, 0x46, 0x68, 0x43, 0x69, 0x48,
+ 0x33, 0x31, 0x44, 0x65, 0x62, 0x46, 0x48, 0x53, 0x41, 0x07, 0x6C, 0x69, 0x48, 0x33, 0x51, 0x54,
+ 0x5D, 0x4E, 0x6C, 0x49, 0x38, 0x4B, 0x55, 0x4A, 0x62, 0x46, 0x48, 0x33, 0x51, 0x34, 0x6D, 0x36,
+ 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x63, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, 0x35, 0x5A,
+ 0x6A, 0x52, 0x6E, 0x3C, 0x51, 0x34, 0x6D, 0x36, 0x50, 0x5F, 0x5F, 0x3F, 0x4F, 0x37, 0x4B, 0x35,
+ 0x5A, 0x4A, 0x62, 0x66, 0x58, 0x3B, 0x4D, 0x66, 0x58, 0x5B, 0x5D, 0x4E, 0x6C, 0x49, 0x58, 0x3B,
+ 0x4D, 0x66, 0x58, 0x3B, 0x4D, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64,
+ 0x55, 0x6A, 0x32, 0x3E, 0x44, 0x45, 0x52, 0x6E, 0x3C, 0x31, 0x64, 0x55, 0x6A, 0x52, 0x4E, 0x6C,
+ 0x69, 0x48, 0x53, 0x61, 0x4C, 0x39, 0x30, 0x6F, 0x47, 0x63, 0x59, 0x60, 0x57, 0x5B, 0x3D, 0x3E,
+ 0x64, 0x35, 0x3A, 0x3A, 0x5A, 0x6A, 0x52, 0x4E, 0x6C, 0x69, 0x48, 0x53, 0x61, 0x6C, 0x49, 0x58,
+ 0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41,
+ 0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E, 0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F,
+ 0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D, 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00 };
+
+static char*
+findMsgType(int num)
+{
+ return val_to_str(num, msgTypeCode, "Unknown");
+}
+
+static char*
+findSubCmd(int num)
+{
+ return val_to_str(num, serverMetaSubCmdCode, "Unknown (0x%04x)");
+}
+
+static char*
+findClientCmd(int num)
+{
+ return val_to_str(num, clientCmdCode, "Unknown (%u)");
+}
+
+static char*
+findServerCmd(int num)
+{
+ return val_to_str(num, serverCmdCode, "Unknown (%u)");
+}
+
+static char*
+findStatus(int num)
+{
+ return val_to_str(num, statusCode, "Unknown (0x%08x)");
+}
+
+static guint32
+get_v5key(tvbuff_t *tvb, int len)
+{
+ guint32 a1, a2, a3, a4, a5;
+ guint32 code, check, key;
+
+ code = tvb_get_letohl(tvb, ICQ5_CL_CHECKCODE);
+
+ a1 = code & 0x0001f000;
+ a2 = code & 0x07c007c0;
+ a3 = code & 0x003e0001;
+ a4 = code & 0xf8000000;
+ a5 = code & 0x0000083e;
+
+ a1 = a1 >> 0x0c;
+ a2 = a2 >> 0x01;
+ a3 = a3 << 0x0a;
+ a4 = a4 >> 0x10;
+ a5 = a5 << 0x0f;
+
+ check = a5 + a1 + a2 + a3 + a4;
+ key = len * 0x68656C6C;
+ key += check;
+ return key;
+}
+
+static void
+decrypt_v5(guchar *bfr, guint32 size,guint32 key)
+{
+ guint32 i;
+ guint32 k;
+
+ for (i=ICQ5_CL_SESSIONID; i < size; i+=4 ) {
+ k = key+table_v5[i&0xff];
+ if ( i != 0x16 ) {
+ bfr[i] ^= (guchar)(k & 0xff);
+ bfr[i+1] ^= (guchar)((k & 0xff00)>>8);
+ }
+ if ( i != 0x12 ) {
+ bfr[i+2] ^= (guchar)((k & 0xff0000)>>16);
+ bfr[i+3] ^= (guchar)((k & 0xff000000)>>24);
+ }
+ }
+}
+
+static void
+dissect_icqv4(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_tree *icq_tree = NULL;
+ proto_item *ti = NULL;
+
+ /* Not really implemented yet */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICQv4 (UDP)");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "ICQ Version 4 protocol");
+ }
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree,
+ proto_icq,
+ tvb,
+ 0,
+ -1,
+ "ICQv4");
+ icq_tree = proto_item_add_subtree(ti, ett_icq);
+
+ proto_tree_add_text(icq_tree, tvb,
+ ICQ_VERSION,
+ 2,
+ "Version: %u",
+ tvb_get_letohs(tvb, ICQ_VERSION));
+ }
+}
+
+static void
+dissect_icqv3(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_tree *icq_tree = NULL;
+ proto_item *ti = NULL;
+
+ /* Not really implemented yet */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICQv3 (UDP)");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "ICQ Version 3 protocol");
+ }
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree,
+ proto_icq,
+ tvb,
+ 0,
+ -1,
+ "ICQv3");
+ icq_tree = proto_item_add_subtree(ti, ett_icq);
+
+ proto_tree_add_text(icq_tree, tvb,
+ ICQ_VERSION,
+ 2,
+ "Version: %u",
+ tvb_get_letohs(tvb, ICQ_VERSION));
+ }
+}
+
+static void
+dissect_icqv2(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_tree *icq_tree = NULL;
+ proto_item *ti = NULL;
+
+ /* Not really implemented yet */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICQv2 (UDP)");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "ICQ Version 2 protocol");
+ }
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree,
+ proto_icq,
+ tvb,
+ 0,
+ -1,
+ "ICQv2");
+ icq_tree = proto_item_add_subtree(ti, ett_icq);
+
+ proto_tree_add_text(icq_tree, tvb,
+ ICQ_VERSION,
+ 2,
+ "Version: %u",
+ tvb_get_letohs(tvb, ICQ_VERSION));
+ }
+}
+
+/*
+ * The packet has, at offset "offset" a (len, string) pair.
+ * Display the length and string in the tree.
+ *
+ * If anything is wrong, return -1, since -1 is not a valid string
+ * length. Else, return the number of chars processed.
+ */
+static guint16
+proto_add_icq_attr(proto_tree* tree, /* The tree to add to */
+ tvbuff_t *tvb, /* Tvbuff with packet */
+ const int offset, /* Offset from the start of packet of field */
+ char* descr) /* The description to use in the tree */
+{
+ guint16 len;
+
+ len = tvb_get_letohs(tvb, offset);
+ if (len > tvb_reported_length_remaining(tvb, offset))
+ return -1; /* length goes past end of packet */
+ proto_tree_add_text(tree, tvb,
+ offset,
+ sizeof(guint16) + len,
+ "%s[%u]: %.*s", descr, len, len,
+ tvb_get_ptr(tvb, offset + sizeof(guint16), len));
+ return len + sizeof(guint16);
+}
+
+static void
+icqv5_decode_msgType(proto_tree* tree,
+ tvbuff_t *tvb,
+ int offset,
+ int size)
+{
+ proto_item* ti = NULL;
+ proto_tree* subtree = NULL;
+ int left = size;
+ guint16 msgType;
+ gint sep_offset;
+ int sz; /* Size of the current element */
+ unsigned int n;
+ static char* url_field_descr[] = {
+ "Description",
+ "URL",
+ };
+#define N_URL_FIELDS (sizeof url_field_descr / sizeof url_field_descr[0])
+ static char* email_field_descr[] = {
+ "Nickname",
+ "First name",
+ "Last name",
+ "Email address",
+ "Unknown",
+ "Text"
+ };
+#define N_EMAIL_FIELDS (sizeof email_field_descr / sizeof email_field_descr[0])
+ static char* auth_req_field_descr[] = {
+ "Nickname",
+ "First name",
+ "Last name",
+ "Email address",
+ "Unknown",
+ "Reason"
+ };
+#define N_AUTH_REQ_FIELDS (sizeof auth_req_field_descr / sizeof auth_req_field_descr[0])
+ static char* user_added_field_descr[] = {
+ "Nickname",
+ "First name",
+ "Last name",
+ "Email address",
+ };
+#define N_USER_ADDED_FIELDS (sizeof user_added_field_descr / sizeof user_added_field_descr[0])
+
+ msgType = tvb_get_letohs(tvb, offset);
+ ti = proto_tree_add_text(tree, tvb,
+ offset,
+ size,
+ "Message: Type = %u (%s)", msgType, findMsgType(msgType));
+ /* Create a new subtree */
+ subtree = proto_item_add_subtree(ti, ett_icq_body_parts);
+
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 2,
+ "Type: %u (%s)", msgType, findMsgType(msgType));
+ offset += 2;
+ left -= 2;
+ if (msgType != MSG_AUTH) {
+ /*
+ * XXX - does a MSG_AUTH message really have 3 bytes of information
+ * rather than a length field?
+ */
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 2,
+ "Length: %u",
+ tvb_get_letohs(tvb, offset));
+ offset += 2;
+ left -= 2;
+ }
+
+ switch(msgType) {
+ case 0xffff: /* Field unknown */
+ break;
+ default:
+ fprintf(stderr, "Unknown msgType: %u (%04x)\n", msgType, msgType);
+ break;
+ case MSG_TEXT:
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ left,
+ "Msg: %.*s", left-1,
+ tvb_get_ptr(tvb, offset, left));
+ break;
+ case MSG_URL:
+ for (n = 0; n < N_URL_FIELDS; n++) {
+ if (n != N_URL_FIELDS - 1) {
+ sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe);
+ sz = sep_offset - offset + 1;
+ } else
+ sz = left;
+ if (sz != 0) {
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ sz,
+ "%s: %.*s",
+ url_field_descr[n],
+ sz - 1,
+ tvb_get_ptr(tvb, offset, sz));
+ } else {
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 0,
+ "%s: %s", url_field_descr[n], "(empty)");
+ }
+ offset += sz;
+ left -= sz;
+ }
+ break;
+ case MSG_EMAIL:
+ for (n = 0; n < N_EMAIL_FIELDS; n++) {
+ if (n != N_EMAIL_FIELDS - 1) {
+ sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe);
+ sz = sep_offset - offset + 1;
+ } else
+ sz = left;
+ if (sz != 0) {
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ sz,
+ "%s: %.*s",
+ email_field_descr[n],
+ sz - 1,
+ tvb_get_ptr(tvb, offset, sz));
+ } else {
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 0,
+ "%s: %s", email_field_descr[n], "(empty)");
+ }
+ offset += sz;
+ left -= sz;
+ }
+ break;
+
+ case MSG_AUTH:
+ {
+ /* Three bytes, first is a char signifying success */
+ unsigned char auth_suc;
+
+ auth_suc = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 1,
+ "Authorization: (%u) %s",auth_suc,
+ (auth_suc==0)?"Denied":"Allowed");
+ offset++;
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ sizeof(guint16),
+ "x1: 0x%04x",
+ tvb_get_letohs(tvb, offset));
+ break;
+ }
+ case MSG_AUTH_REQ:
+ for (n = 0; n < N_AUTH_REQ_FIELDS; n++) {
+ if (n != N_AUTH_REQ_FIELDS - 1) {
+ sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe);
+ sz = sep_offset - offset + 1;
+ } else
+ sz = left;
+ if (sz != 0) {
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ sz,
+ "%s: %.*s",
+ auth_req_field_descr[n],
+ sz - 1,
+ tvb_get_ptr(tvb, offset, sz));
+ } else {
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 0,
+ "%s: %s", auth_req_field_descr[n], "(empty)");
+ }
+ offset += sz;
+ left -= sz;
+ }
+ break;
+ case MSG_USER_ADDED:
+ for (n = 0; n < N_USER_ADDED_FIELDS; n++) {
+ if (n != N_USER_ADDED_FIELDS - 1) {
+ sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe);
+ sz = sep_offset - offset + 1;
+ } else
+ sz = left;
+ if (sz != 0) {
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ sz,
+ "%s: %.*s",
+ user_added_field_descr[n],
+ sz - 1,
+ tvb_get_ptr(tvb, offset, sz));
+ } else {
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 0,
+ "%s: %s", user_added_field_descr[n], "(empty)");
+ }
+ offset += sz;
+ left -= sz;
+ }
+ break;
+ case MSG_CONTACTS:
+ {
+ gint sep_offset_prev;
+ int sz = 0; /* Size of the current element */
+ int n = 0; /* The nth element */
+ gboolean last = FALSE;
+
+ while (!last) {
+ sep_offset = tvb_find_guint8(tvb, offset, left, 0xfe);
+ if (sep_offset != -1)
+ sz = sep_offset - offset + 1;
+ else {
+ sz = left;
+ last = TRUE;
+ }
+ if (n == 0) {
+ /* The first element is the number of Nick/UIN pairs follow */
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ sz,
+ "Number of pairs: %.*s",
+ sz - 1,
+ tvb_get_ptr(tvb, offset, sz));
+ n++;
+ } else if (!last) {
+ int svsz = sz;
+
+ left -= sz;
+ sep_offset_prev = sep_offset;
+ sep_offset = tvb_find_guint8(tvb, sep_offset_prev, left,
+ 0xfe);
+ if (sep_offset != -1)
+ sz = sep_offset - offset + 1;
+ else {
+ sz = left;
+ last = TRUE;
+ }
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ sz + svsz,
+ "%.*s: %.*s",
+ svsz - 1,
+ tvb_get_ptr(tvb, offset, svsz),
+ sz - 1,
+ tvb_get_ptr(tvb, sep_offset_prev + 1, sz));
+ n += 2;
+ }
+
+ left -= (sz+1);
+ offset = sep_offset + 1;
+ }
+ break;
+ }
+ }
+}
+
+/*********************************
+ *
+ * Client commands
+ *
+ *********************************/
+static void
+icqv5_cmd_ack(proto_tree* tree,/* Tree to put the data in */
+ tvbuff_t *tvb, /* Tvbuff with decrypted packet data */
+ int offset) /* Offset from the start of the packet to the content */
+{
+ proto_tree* subtree;
+ proto_item* ti;
+
+ if (tree){
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ 4,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_ACK_RANDOM,
+ 4,
+ "Random: 0x%08x",
+ tvb_get_letohl(tvb, offset + CMD_ACK_RANDOM));
+ }
+}
+
+static void
+icqv5_cmd_rand_search(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Decrypted packet content */
+ int offset, /* Offset from the start of the packet to the content */
+ int size) /* Number of chars left to do */
+{
+ guint16 group;
+ proto_tree* subtree;
+ proto_item* ti;
+
+ static const char* groups[] = {
+ "Name",
+ "General",
+ "Romance",
+ "Games",
+ "Students",
+ "20 Something",
+ "30 Something",
+ "40 Something",
+ "50 or worse",
+ "Man want women",
+ "Women want men"
+ };
+
+ if (tree){
+ if (size < 4) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body (%d bytes, should be 4)", size);
+ return;
+ }
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ 4,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ group = tvb_get_letohs(tvb, offset + CMD_RAND_SEARCH_GROUP);
+ if (group>0 && (group<=sizeof(groups)/sizeof(const char*)))
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_RAND_SEARCH_GROUP,
+ 4,
+ "Group: (%u) %s", group, groups[group-1]);
+ else
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_RAND_SEARCH_GROUP,
+ 4,
+ "Group: (%u)", group);
+ }
+}
+
+static void
+icqv5_cmd_ack_messages(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Decrypted packet content */
+ int offset) /* Offset from the start of the packet to the content */
+{
+ proto_tree* subtree;
+ proto_item* ti;
+
+ if (tree){
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ 4,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_ACK_MESSAGES_RANDOM,
+ 4,
+ "Random: 0x%08x",
+ tvb_get_letohl(tvb, offset + CMD_ACK_MESSAGES_RANDOM));
+ }
+}
+
+static void
+icqv5_cmd_keep_alive(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Decrypted packet content */
+ int offset) /* Offset from the start of the packet to the content */
+{
+ guint32 random;
+ proto_tree* subtree;
+ proto_item* ti;
+
+ if (tree){
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ 4,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ random = tvb_get_letohl(tvb, offset + CMD_KEEP_ALIVE_RANDOM);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_KEEP_ALIVE_RANDOM,
+ 4,
+ "Random: 0x%08x", random);
+ }
+}
+
+static void
+icqv5_cmd_send_text_code(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Decrypted packet content */
+ int offset, /* Offset from the start of the packet to the content */
+ int size) /* Number of chars left to do */
+{
+ proto_tree* subtree = NULL;
+ proto_item* ti = NULL;
+ guint16 len;
+ guint16 x1;
+
+ if (tree){
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body");
+ }
+
+ len = tvb_get_letohs(tvb, offset+CMD_SEND_TEXT_CODE_LEN);
+ if (tree){
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_SEND_TEXT_CODE_LEN,
+ 2,
+ "Length: %d", len);
+ }
+
+ if (len>0) {
+ if (tree){
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_SEND_TEXT_CODE_TEXT,
+ len,
+ "Text: %.*s",
+ len,
+ tvb_get_ptr(tvb, offset + CMD_SEND_TEXT_CODE_TEXT,
+ len));
+ }
+ }
+
+ x1 = tvb_get_letohs(tvb, offset + CMD_SEND_TEXT_CODE_TEXT + len);
+ if (tree){
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_SEND_TEXT_CODE_TEXT + len,
+ 2,
+ "X1: 0x%04x", x1);
+ }
+}
+
+static void
+icqv5_cmd_add_to_list(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Decrypted packet content */
+ int offset) /* Offset from the start of the packet to the content */
+{
+ guint32 uin;
+ proto_tree* subtree;
+ proto_item* ti;
+
+ if (tree){
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ 4,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ uin = tvb_get_letohl(tvb, offset + CMD_ADD_TO_LIST);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_ADD_TO_LIST_UIN,
+ 4,
+ "UIN: %u", uin);
+ }
+}
+
+static void
+icqv5_cmd_status_change(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Decrypted packet content */
+ int offset) /* Offset from the start of the packet to the content */
+{
+ guint32 status;
+ proto_tree* subtree;
+ proto_item* ti;
+
+ if (tree){
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ 4,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ status = tvb_get_letohl(tvb, offset + CMD_STATUS_CHANGE_STATUS);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_STATUS_CHANGE_STATUS,
+ 4,
+ "Status: %s", findStatus(status));
+ }
+}
+
+static void
+icqv5_cmd_send_msg(proto_tree* tree,
+ tvbuff_t *tvb,
+ int offset,
+ int size)
+{
+ proto_tree* subtree;
+ proto_item* ti;
+ int left = size; /* left chars to do */
+
+ if (tree) {
+ if (size < 4) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body (%d bytes, should be >= 4)", size);
+ return;
+ }
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_SEND_MSG_RECV_UIN,
+ 4,
+ "Receiver UIN: %u",
+ tvb_get_letohl(tvb, offset + CMD_SEND_MSG_RECV_UIN));
+ left -= 4;
+
+ icqv5_decode_msgType(subtree,
+ tvb,
+ offset + CMD_SEND_MSG_MSG_TYPE,
+ left);
+ }
+}
+
+static void
+icqv5_cmd_login(proto_tree* tree,
+ tvbuff_t *tvb,
+ int offset,
+ int size)
+{
+ proto_item* ti;
+ proto_tree* subtree;
+ time_t theTime;
+ char *aTime;
+ guint32 port;
+ guint32 passwdLen;
+ const guchar *ipAddrp;
+ guint32 status;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ theTime = tvb_get_letohl(tvb, offset + CMD_LOGIN_TIME);
+ aTime = ctime(&theTime);
+ aTime[strlen(aTime)-1] = '\0';
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_LOGIN_TIME,
+ 4,
+ "Time: %ld = %s", (long)theTime, aTime);
+ port = tvb_get_letohl(tvb, offset + CMD_LOGIN_PORT);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_LOGIN_PORT,
+ 4,
+ "Port: %u", port);
+ passwdLen = tvb_get_letohs(tvb, offset + CMD_LOGIN_PASSLEN);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_LOGIN_PASSLEN,
+ 2 + passwdLen,
+ "Passwd: %.*s",
+ (int)passwdLen,
+ tvb_get_ptr(tvb, offset + CMD_LOGIN_PASSWD,
+ passwdLen));
+ ipAddrp = tvb_get_ptr(tvb,
+ offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_IP,
+ 4);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_IP,
+ 4,
+ "IP: %s", ip_to_str(ipAddrp));
+ status = tvb_get_letohs(tvb,
+ offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_STATUS);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_STATUS,
+ 4,
+ "Status: %s", findStatus(status));
+ }
+}
+
+static void
+icqv5_cmd_contact_list(proto_tree* tree,
+ tvbuff_t *tvb,
+ int offset,
+ int size)
+{
+ proto_tree* subtree;
+ proto_item* ti;
+ unsigned char num;
+ int i;
+ guint32 uin;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ num = tvb_get_guint8(tvb, offset + CMD_CONTACT_LIST_NUM);
+ proto_tree_add_text(subtree, tvb,
+ offset + CMD_CONTACT_LIST,
+ 1,
+ "Number of uins: %u", num);
+ /*
+ * A sequence of num times UIN follows
+ */
+ offset += (CMD_CONTACT_LIST_NUM + 1);
+ for (i = 0; i < num; i++) {
+ uin = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 4,
+ "UIN[%d]: %u", i ,uin);
+ offset += 4;
+ }
+ }
+}
+
+static void
+icqv5_cmd_no_params(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Decrypted packet content */
+ int offset) /* Offset from the start of the packet to the content */
+{
+ proto_tree* subtree;
+ proto_item* ti;
+
+ if (tree){
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ 0,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 0,
+ "No parameters");
+ }
+}
+
+/**********************
+ *
+ * Server commands
+ *
+ **********************
+ */
+static void
+icqv5_srv_no_params(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Packet content */
+ int offset) /* Offset from the start of the packet to the content */
+{
+ proto_tree* subtree;
+ proto_item* ti;
+
+ if (tree){
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ 0,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ proto_tree_add_text(subtree, tvb,
+ offset,
+ 0,
+ "No Parameters");
+ }
+}
+
+static void
+icqv5_srv_login_reply(proto_tree* tree,/* Tree to put the data in */
+ tvbuff_t *tvb, /* Tvbuff with packet */
+ int offset, /* Offset from the start of the packet to the content */
+ int size) /* Number of chars left to do */
+{
+ proto_tree* subtree;
+ proto_item* ti;
+ const guchar *ipAddrp;
+
+ if (tree) {
+ if (size < SRV_LOGIN_REPLY_IP + 8) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body (%d bytes, should be %d)", size,
+ SRV_LOGIN_REPLY_IP + 8);
+ return;
+ }
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ SRV_LOGIN_REPLY_IP + 8,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ ipAddrp = tvb_get_ptr(tvb, offset + SRV_LOGIN_REPLY_IP, 4);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_LOGIN_REPLY_IP,
+ 4,
+ "IP: %s", ip_to_str(ipAddrp));
+ }
+}
+
+static void
+icqv5_srv_user_online(proto_tree* tree,/* Tree to put the data in */
+ tvbuff_t *tvb, /* Tvbuff with packet */
+ int offset, /* Offset from the start of the packet to the content */
+ int size) /* Number of chars left to do */
+{
+ proto_tree* subtree;
+ proto_item* ti;
+ const guchar *ipAddrp;
+ const guchar *realipAddrp;
+ guint32 status;
+
+ if (tree) {
+ if (size < SRV_LOGIN_REPLY_IP + 8) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body (%d bytes, should be %d)", size,
+ SRV_LOGIN_REPLY_IP + 8);
+ return;
+ }
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ SRV_LOGIN_REPLY_IP + 8,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_USER_ONL_UIN,
+ 4,
+ "UIN: %u",
+ tvb_get_letohl(tvb, offset + SRV_USER_ONL_UIN));
+ ipAddrp = tvb_get_ptr(tvb, offset + SRV_USER_ONL_IP, 4);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_USER_ONL_IP,
+ 4,
+ "IP: %s", ip_to_str(ipAddrp));
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_USER_ONL_PORT,
+ 4,
+ "Port: %u",
+ tvb_get_letohl(tvb, offset + SRV_USER_ONL_PORT));
+ realipAddrp = tvb_get_ptr(tvb, offset + SRV_USER_ONL_REALIP, 4);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_USER_ONL_REALIP,
+ 4,
+ "RealIP: %s", ip_to_str(realipAddrp));
+ status = tvb_get_letohs(tvb, offset + SRV_USER_ONL_STATUS);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_USER_ONL_STATUS,
+ 2,
+ "Status: %s", findStatus(status));
+ /*
+ * Kojak: Hypothesis is that this field might be an encoding for the
+ * version used by the UIN that changed. To test this, I included
+ * this line to the code.
+ */
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_USER_ONL_X2,
+ 4,
+ "Version: %08x",
+ tvb_get_letohl(tvb, offset + SRV_USER_ONL_X2));
+ }
+}
+
+static void
+icqv5_srv_user_offline(proto_tree* tree,/* Tree to put the data in */
+ tvbuff_t *tvb, /* Tvbuff with packet */
+ int offset, /* Offset from the start of the packet to the content */
+ int size) /* Number of chars left to do */
+{
+ proto_tree* subtree;
+ proto_item* ti;
+
+ if (tree) {
+ if (size < SRV_USER_OFFLINE_UIN + 4) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body (%d bytes, should be %d)", size,
+ SRV_USER_OFFLINE_UIN + 4);
+ return;
+ }
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ SRV_USER_OFFLINE_UIN + 4,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_USER_OFFLINE_UIN,
+ 4,
+ "UIN: %u",
+ tvb_get_letohl(tvb, offset + SRV_USER_OFFLINE));
+ }
+}
+
+static void
+icqv5_srv_multi(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Packet content */
+ int offset, /* Offset from the start of the packet to the content */
+ int size, /* Number of chars left to do */
+ packet_info* pinfo)
+{
+ proto_tree* subtree;
+ proto_item* ti;
+ guint8 num;
+ guint16 pktSz;
+ int i;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ num = tvb_get_guint8(tvb, offset + SRV_MULTI_NUM);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_MULTI_NUM,
+ 1,
+ "Number of pkts: %u", num);
+ /*
+ * A sequence of num times ( pktsize, packetData) follows
+ */
+ offset += (SRV_MULTI_NUM + 1);
+ for (i = 0; i < num; i++) {
+ pktSz = tvb_get_letohs(tvb, offset);
+ offset += 2;
+ dissect_icqv5Server(tvb, offset, pinfo, subtree, pktSz);
+ offset += pktSz;
+ }
+ }
+}
+
+static void
+icqv5_srv_meta_user(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Tvbuff with packet */
+ int offset, /* Offset from the start of the packet to the content */
+ int size) /* Number of chars left to do */
+{
+#if 0
+ proto_tree* subtree = NULL;
+#endif
+ proto_tree* sstree = NULL;
+ proto_item* ti = NULL;
+ int left = size;
+ guint16 subcmd;
+ unsigned char result;
+
+ if (tree) {
+#if 0
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ size,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ subcmd = tvb_get_letohs(tvb, offset + SRV_META_USER_SUBCMD);
+ ti = proto_tree_add_text(subtree, tvb,
+ offset + SRV_META_USER_SUBCMD,
+ 2,
+ "%s", findSubCmd(subcmd));
+ result = tvb_get_guint8(tvb, offset + SRV_META_USER_RESULT);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_META_USER_RESULT,
+ 1,
+ "%s", (result==0x0a)?"Success":"Failure");
+ sstree = proto_item_add_subtree(ti, ett_icq_body_parts);
+#else
+ subcmd = tvb_get_letohs(tvb, offset + SRV_META_USER_SUBCMD);
+ ti = proto_tree_add_text(tree, tvb,
+ offset + SRV_META_USER_SUBCMD,
+ 2,
+ "%s", findSubCmd(subcmd));
+ sstree = proto_item_add_subtree(ti, ett_icq_body_parts);
+ result = tvb_get_guint8(tvb, offset + SRV_META_USER_RESULT);
+ proto_tree_add_text(sstree, tvb,
+ offset + SRV_META_USER_RESULT,
+ 1,
+ "%s", (result==0x0a)?"Success":"Failure");
+#endif
+
+ /* Skip the META_USER header */
+ left -= 3;
+ offset += 3;
+
+ switch(subcmd) {
+ case META_EX_USER_FOUND:
+ {
+ /* This is almost the same as META_USER_FOUND,
+ * however, there's an extra length field
+ */
+ guint16 pktLen;
+
+ /* Read the length field */
+ pktLen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(guint16),
+ "Length: %u", pktLen);
+
+ offset += sizeof(guint16); left -= sizeof(guint16);
+ }
+ case META_USER_FOUND:
+ {
+ /* The goto mentioned in this block should be local to this
+ * block if C'd allow it.
+ *
+ * They are used to "implement" a poorman's exception handling
+ */
+ int len = 0;
+ char *descr[] = {
+ "Nick",
+ "First name",
+ "Last name",
+ "Email",
+ NULL};
+ char** d = descr;
+ unsigned char auth;
+ /*
+ * Read UIN
+ */
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(guint32),
+ "UIN: %u",
+ tvb_get_letohl(tvb, offset));
+ offset+=sizeof(guint32);left-=sizeof(guint32);
+
+ for ( ; *d!=NULL; d++) {
+ len = proto_add_icq_attr(sstree,
+ tvb,
+ offset,
+ *d);
+ if (len == -1)
+ return;
+ offset += len; left -= len;
+ }
+ /* Get the authorize setting */
+ auth = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ 1,
+ "authorization: %s", (auth==0x01)?"Neccessary":"Who needs it");
+ offset++; left--;
+ /* Get x2 */
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(guint16),
+ "x2: 0x%04x",
+ tvb_get_letohs(tvb, offset));
+ offset+=sizeof(guint16);left-=sizeof(guint16);
+ /* Get x3 */
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(guint32),
+ "x3: 0x%08x",
+ tvb_get_letohl(tvb, offset));
+ offset+=sizeof(guint32);left-=sizeof(guint32);
+ break;
+ }
+ case META_ABOUT:
+ {
+ int len;
+
+ /* Get the about information */
+ len = tvb_get_letohs(tvb, offset);
+ offset+=sizeof(guint16);left-=sizeof(guint16);
+ proto_tree_add_text(sstree, tvb,
+ offset - sizeof(guint16),
+ sizeof(guint16)+len,
+ "About(%d): %.*s", len,
+ len, tvb_get_ptr(tvb, offset, len));
+ offset+=len;left-=len;
+ break;
+ }
+ case META_USER_INFO:
+ {
+ /* The goto mentioned in this block should be local to this
+ * block if C'd allow it.
+ *
+ * They are used to "implement" a poorman's exception handling
+ */
+ static const char* descr[] = {
+ "Nick",
+ "First name",
+ "Last name",
+ "Primary email",
+ "Secundary email",
+ "Old email",
+ "City",
+ "State",
+ "Phone",
+ "Fax",
+ "Street",
+ "Cellphone",
+ "Zip",
+ NULL};
+ const char** d = descr;
+ guint16 country;
+ guint8 user_timezone;
+ guint8 auth;
+ int len = 0;
+#if 0
+ /* Get the uin */
+ uin = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(guint32),
+ "UIN: %u", uin);
+ offset+=sizeof(guint32);left-=sizeof(guint32);
+#endif
+
+ /*
+ * Get every field from the description
+ */
+ while ((*d)!=NULL) {
+ len = tvb_get_letohs(tvb, offset);
+ offset+=sizeof(guint16);left-=sizeof(guint16);
+ if (len>0) {
+ proto_tree_add_text(sstree, tvb,
+ offset - sizeof(guint16),
+ sizeof(guint16)+len,
+ "%s(%d): %.*s",*d, len,
+ len - 1,
+ tvb_get_ptr(tvb, offset, len - 1));
+ offset+=len;left-=len;
+ }
+ d++;
+ }
+ /* Get country code */
+ country = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(guint16),
+ "Countrycode: %u", country);
+ offset+=sizeof(guint16); left-=sizeof(guint16);
+ /* Get the timezone setting */
+ user_timezone = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(unsigned char),
+ "Timezone: %u", user_timezone);
+ offset++; left--;
+ /* Get the authorize setting */
+ auth = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(unsigned char),
+ "Authorization: (%u) %s",
+ auth, (auth==0)?"No":"Yes");
+ offset++; left--;
+ /* Get the webaware setting */
+ auth = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(unsigned char),
+ "Webaware: (%u) %s",
+ auth, (auth==0)?"No":"Yes");
+ offset++; left--;
+ /* Get the authorize setting */
+ auth = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(sstree, tvb,
+ offset,
+ sizeof(unsigned char),
+ "HideIP: (%u) %s",
+ auth, (auth==0)?"No":"Yes");
+ offset++; left--;
+ break;
+ }
+ default:
+ /* This information is already printed in the tree */
+ fprintf(stderr, "Meta subcmd: %04x\n", subcmd);
+ break;
+ }
+ }
+}
+
+static void
+icqv5_srv_recv_message(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t* tvb, /* Packet content */
+ int offset, /* Offset from the start of the packet to the content */
+ int size) /* Number of chars left to do */
+{
+ proto_tree* subtree = NULL;
+ proto_item* ti = NULL;
+ int left = size;
+ guint16 year;
+ guint8 month;
+ guint8 day;
+ guint8 hour;
+ guint8 minute;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ 4,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ proto_tree_add_item(subtree,
+ hf_icq_uin,
+ tvb,
+ offset + SRV_RECV_MSG_UIN,
+ sizeof(guint32),
+ TRUE);
+ year = tvb_get_letohs(tvb, offset + SRV_RECV_MSG_YEAR);
+ month = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_MONTH);
+ day = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_DAY);
+ hour = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_HOUR);
+ minute = tvb_get_guint8(tvb, offset + SRV_RECV_MSG_MINUTE);
+
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_RECV_MSG_YEAR,
+ sizeof(guint16) + 4*sizeof(unsigned char),
+ "Time: %u-%u-%u %02u:%02u",
+ day, month, year, hour, minute);
+ icqv5_decode_msgType(subtree,
+ tvb,
+ offset + SRV_RECV_MSG_MSG_TYPE,
+ left);
+ }
+}
+
+static void
+icqv5_srv_rand_user(proto_tree* tree, /* Tree to put the data in */
+ tvbuff_t *tvb, /* Tvbuff with packet */
+ int offset) /* Offset from the start of the packet to the content */
+{
+ proto_tree* subtree = NULL;
+ proto_item* ti = NULL;
+ guint32 uin;
+ const unsigned char* IP = NULL;
+ guint32 port;
+ const unsigned char* realIP = NULL;
+ guint8 commClass;
+ guint32 status;
+ guint16 tcpVer;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree,
+ tvb,
+ offset,
+ SRV_RAND_USER_TCP_VER + 2,
+ "Body");
+ subtree = proto_item_add_subtree(ti, ett_icq_body);
+ /* guint32 UIN */
+ uin = tvb_get_letohl(tvb, offset + SRV_RAND_USER_UIN);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_RAND_USER_UIN,
+ sizeof(guint32),
+ "UIN: %u", uin);
+ /* guint32 IP */
+ IP = tvb_get_ptr(tvb, offset + SRV_RAND_USER_IP, 4);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_RAND_USER_IP,
+ sizeof(guint32),
+ "IP: %s",
+ ip_to_str(IP));
+ /* guint16 portNum */
+ /* XXX - 16 bits, or 32 bits? */
+ port = tvb_get_letohs(tvb, offset + SRV_RAND_USER_PORT);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_RAND_USER_UIN,
+ sizeof(guint32),
+ "Port: %u", port);
+ /* guint32 realIP */
+ realIP = tvb_get_ptr(tvb, offset + SRV_RAND_USER_REAL_IP, 4);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_RAND_USER_REAL_IP,
+ sizeof(guint32),
+ "RealIP: %s", ip_to_str(realIP));
+ /* guint8 Communication Class */
+ commClass = tvb_get_guint8(tvb, offset + SRV_RAND_USER_CLASS);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_RAND_USER_CLASS,
+ sizeof(guint8),
+ "Class: %s", (commClass!=4)?"User to User":"Through Server");
+ /* guint32 status */
+ /* XXX - 16 bits, or 32 bits? */
+ status = tvb_get_letohs(tvb, offset + SRV_RAND_USER_STATUS);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_RAND_USER_STATUS,
+ sizeof(guint32),
+ "Status: %s", findStatus(status));
+ /* guint16 tcpVersion */
+ tcpVer = tvb_get_letohs(tvb, offset + SRV_RAND_USER_TCP_VER);
+ proto_tree_add_text(subtree, tvb,
+ offset + SRV_RAND_USER_TCP_VER,
+ sizeof(guint16),
+ "TCPVersion: %u", tcpVer);
+ }
+}
+
+/*
+ * Dissect all the v5 client traffic. This is encrypted, so be careful.
+ */
+static void
+dissect_icqv5Client(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_tree *icq_tree = NULL;
+ proto_tree *icq_header_tree = NULL;
+ proto_item *ti = NULL;
+
+ int pktsize; /* The actual size of the ICQ content */
+ int capturedsize; /* The captured size of the ICQ content */
+ guint32 rounded_size;
+ guint32 key;
+ guint16 cmd;
+ guint8 *decr_pd; /* Decrypted content */
+ tvbuff_t *decr_tvb;
+
+ pktsize = tvb_reported_length(tvb);
+ capturedsize = tvb_length(tvb);
+
+ /* Get the encryption key */
+ key = get_v5key(tvb, pktsize);
+
+ /*
+ * Make a copy of the packet data, and decrypt it.
+ * The decryption processes 4 bytes at a time, and starts at
+ * an offset of ICQ5_CL_SESSIONID (which isn't a multiple of 4),
+ * so we make sure that there are
+ *
+ * (ICQ5_CL_SESSIONID + a multiple of 4)
+ *
+ * bytes in the buffer.
+ */
+ rounded_size = ((((capturedsize - ICQ5_CL_SESSIONID) + 3)/4)*4) + ICQ5_CL_SESSIONID;
+ decr_pd = g_malloc(rounded_size);
+ tvb_memcpy(tvb, decr_pd, 0, capturedsize);
+ decrypt_v5(decr_pd, rounded_size, key);
+
+ /* Allocate a new tvbuff, referring to the decrypted data. */
+ decr_tvb = tvb_new_real_data(decr_pd, capturedsize, pktsize);
+
+ /* Arrange that the allocated packet data copy be freed when the
+ tvbuff is freed. */
+ tvb_set_free_cb(decr_tvb, g_free);
+
+ /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
+ were handed refers, so it'll get cleaned up when that tvbuff
+ is cleaned up. */
+ tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
+
+ /* Add the decrypted data to the data source list. */
+ add_new_data_source(pinfo, decr_tvb, "Decrypted");
+
+ cmd = tvb_get_letohs(decr_tvb, ICQ5_CL_CMD);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "ICQv5 %s", findClientCmd(cmd));
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree,
+ proto_icq,
+ tvb,
+ 0,
+ -1,
+ "ICQv5 %s (len %u)",
+ findClientCmd(cmd),
+ pktsize);
+ icq_tree = proto_item_add_subtree(ti, ett_icq);
+ ti = proto_tree_add_uint_format(icq_tree,
+ hf_icq_type,
+ tvb,
+ 0,
+ ICQ5_CL_HDRSIZE,
+ ICQ5_client,
+ "Header");
+ icq_header_tree = proto_item_add_subtree(ti, ett_icq_header);
+
+ proto_tree_add_text(icq_header_tree, tvb,
+ ICQ_VERSION,
+ 2,
+ "Version: %u",
+ tvb_get_letohs(tvb, ICQ_VERSION));
+ proto_tree_add_item(icq_header_tree,
+ hf_icq_uin,
+ tvb,
+ ICQ5_CL_UIN,
+ 4,
+ TRUE);
+ proto_tree_add_item(icq_header_tree,
+ hf_icq_sessionid,
+ decr_tvb,
+ ICQ5_CL_SESSIONID,
+ 4,
+ TRUE);
+ proto_tree_add_uint_format(icq_header_tree,
+ hf_icq_client_cmd,
+ decr_tvb,
+ ICQ5_CL_CMD,
+ 2,
+ cmd,
+ "Command: %s (%u)",
+ val_to_str(cmd, clientCmdCode, "Unknown"), cmd);
+ proto_tree_add_text(icq_header_tree, decr_tvb,
+ ICQ5_CL_SEQNUM1,
+ 2,
+ "Seq Number 1: 0x%04x",
+ tvb_get_letohs(decr_tvb, ICQ5_CL_SEQNUM1));
+ proto_tree_add_text(icq_header_tree, decr_tvb,
+ ICQ5_CL_SEQNUM2,
+ 2,
+ "Seq Number 2: 0x%04x",
+ tvb_get_letohs(decr_tvb, ICQ5_CL_SEQNUM2));
+ proto_tree_add_uint_format(icq_header_tree,
+ hf_icq_checkcode,
+ tvb,
+ ICQ5_CL_CHECKCODE,
+ 4,
+ key,
+ "Key: 0x%08x",
+ key);
+ switch(cmd) {
+ case CMD_ACK:
+ icqv5_cmd_ack(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_SEND_MSG:
+ case CMD_MSG_TO_NEW_USER:
+ icqv5_cmd_send_msg(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_RAND_SEARCH:
+ icqv5_cmd_rand_search(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_LOGIN:
+ icqv5_cmd_login(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_SEND_TEXT_CODE:
+ icqv5_cmd_send_text_code(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_STATUS_CHANGE:
+ icqv5_cmd_status_change(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_ACK_MESSAGES:
+ icqv5_cmd_ack_messages(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_KEEP_ALIVE:
+ icqv5_cmd_keep_alive(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_ADD_TO_LIST:
+ icqv5_cmd_add_to_list(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_CONTACT_LIST:
+ icqv5_cmd_contact_list(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_META_USER:
+ case CMD_REG_NEW_USER:
+ case CMD_QUERY_SERVERS:
+ case CMD_QUERY_ADDONS:
+ icqv5_cmd_no_params(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE);
+ break;
+ default:
+ proto_tree_add_text(icq_tree,
+ decr_tvb,
+ ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE,
+ "Body");
+ fprintf(stderr,"Missing: %s\n", findClientCmd(cmd));
+ break;
+ }
+ }
+}
+
+static void
+dissect_icqv5Server(tvbuff_t *tvb,
+ int offset,
+ packet_info *pinfo,
+ proto_tree *tree,
+ int pktsize)
+{
+ /* Server traffic is easy, not encrypted */
+ proto_tree *icq_tree = NULL;
+ proto_tree *icq_header_tree = NULL;
+ proto_item *ti = NULL;
+ int changeCol = (pktsize==-1);
+
+ guint16 cmd;
+
+ cmd = tvb_get_letohs(tvb, offset + ICQ5_SRV_CMD);
+ if (changeCol && check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "ICQv5 %s", findServerCmd(cmd));
+
+ if (pktsize == -1)
+ pktsize = tvb_reported_length(tvb);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree,
+ proto_icq,
+ tvb,
+ offset,
+ pktsize,
+ "ICQv5 %s (len %u)",
+ findServerCmd(cmd),
+ pktsize);
+
+ icq_tree = proto_item_add_subtree(ti, ett_icq);
+
+ ti = proto_tree_add_uint_format(icq_tree,
+ hf_icq_type,
+ tvb,
+ offset,
+ ICQ5_SRV_HDRSIZE,
+ ICQ5_server,
+ "Header");
+ icq_header_tree = proto_item_add_subtree(ti, ett_icq_header);
+
+ proto_tree_add_text(icq_header_tree, tvb,
+ offset + ICQ_VERSION,
+ 2,
+ "Version: %u",
+ tvb_get_letohs(tvb, ICQ_VERSION));
+ proto_tree_add_item(icq_header_tree,
+ hf_icq_sessionid,
+ tvb,
+ offset + ICQ5_SRV_SESSIONID,
+ 4,
+ TRUE);
+ proto_tree_add_uint_format(icq_header_tree,
+ hf_icq_server_cmd,
+ tvb,
+ offset + ICQ5_SRV_CMD,
+ 2,
+ cmd,
+ "Command: %s (%u)",
+ val_to_str(cmd, serverCmdCode, "Unknown"), cmd);
+ proto_tree_add_text(icq_header_tree, tvb,
+ offset + ICQ5_SRV_SEQNUM1,
+ 2,
+ "Seq Number 1: 0x%04x",
+ tvb_get_letohs(tvb, offset + ICQ5_SRV_SEQNUM1));
+ proto_tree_add_text(icq_header_tree, tvb,
+ offset + ICQ5_SRV_SEQNUM2,
+ 2,
+ "Seq Number 2: 0x%04x",
+ tvb_get_letohs(tvb, offset + ICQ5_SRV_SEQNUM2));
+ proto_tree_add_item(icq_header_tree,
+ hf_icq_uin,
+ tvb,
+ offset + ICQ5_SRV_UIN,
+ 4,
+ TRUE);
+ proto_tree_add_item(icq_header_tree,
+ hf_icq_checkcode,
+ tvb,
+ offset + ICQ5_SRV_CHECKCODE,
+ 4,
+ TRUE);
+ switch (cmd) {
+ case SRV_RAND_USER:
+ icqv5_srv_rand_user(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_SYS_DELIVERED_MESS:
+ /* The message structures are all the same. Why not run
+ * the same routine? */
+ icqv5_cmd_send_msg(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_USER_ONLINE:
+ icqv5_srv_user_online(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_USER_OFFLINE:
+ icqv5_srv_user_offline(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_LOGIN_REPLY:
+ icqv5_srv_login_reply(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_META_USER:
+ icqv5_srv_meta_user(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_RECV_MESSAGE:
+ icqv5_srv_recv_message(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_MULTI:
+ icqv5_srv_multi(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE,
+ pinfo);
+ break;
+ case SRV_ACK:
+ case SRV_SILENT_TOO_LONG:
+ case SRV_GO_AWAY:
+ case SRV_NEW_UIN:
+ case SRV_BAD_PASS:
+ case SRV_UPDATE_SUCCESS:
+ icqv5_srv_no_params(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE);
+ break;
+ default:
+ proto_tree_add_text(icq_tree,
+ tvb,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE,
+ "Body");
+ fprintf(stderr,"Missing: %s\n", findServerCmd(cmd));
+ break;
+ }
+ }
+}
+
+static void dissect_icqv5(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 unknown;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICQv5 (UDP)");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "ICQv5 packet");
+
+ unknown = tvb_get_letohl(tvb, ICQ5_UNKNOWN);
+
+ if (unknown == 0x0L) {
+ dissect_icqv5Client(tvb, pinfo, tree);
+ } else {
+ dissect_icqv5Server(tvb, 0, pinfo, tree, -1);
+ }
+}
+
+static void dissect_icq(tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree)
+{
+ int version;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICQ");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ version = tvb_get_letohs(tvb, ICQ_VERSION);
+ switch (version) {
+ case 0x0005:
+ dissect_icqv5(tvb, pinfo, tree);
+ break;
+ case 0x0004:
+ dissect_icqv4(tvb, pinfo, tree);
+ break;
+ case 0x0003:
+ dissect_icqv3(tvb, pinfo, tree);
+ break;
+ case 0x0002:
+ dissect_icqv2(tvb, pinfo, tree);
+ break;
+ default:
+ fprintf(stderr, "ICQ: Unknown version (%d)\n", version);
+ break;
+ }
+}
+
+/* registration with the filtering engine */
+void
+proto_register_icq(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_icq_type,
+ {"Type", "icq.type", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_icq_uin,
+ {"UIN", "icq.uin", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_icq_sessionid,
+ {"Session ID", "icq.sessionid", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_icq_client_cmd,
+ {"Client command", "icq.client_cmd", FT_UINT16, BASE_HEX, VALS(clientCmdCode), 0x0, "", HFILL }},
+ { &hf_icq_server_cmd,
+ {"Server command", "icq.server_cmd", FT_UINT16, BASE_DEC, VALS(serverCmdCode), 0x0, "", HFILL }},
+ { &hf_icq_checkcode,
+ {"Checkcode", "icq.checkcode", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_icq_decode,
+ {"Decode", "icq.decode", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_icq,
+ &ett_icq_header,
+ &ett_icq_decode,
+ &ett_icq_body,
+ &ett_icq_body_parts,
+ };
+
+ proto_icq = proto_register_protocol("ICQ Protocol", "ICQ", "icq");
+
+ proto_register_field_array(proto_icq, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_icq(void)
+{
+ dissector_handle_t icq_handle;
+
+ icq_handle = create_dissector_handle(dissect_icq, proto_icq);
+ dissector_add("udp.port", UDP_PORT_ICQ, icq_handle);
+}
diff --git a/epan/dissectors/packet-ieee80211.c b/epan/dissectors/packet-ieee80211.c
new file mode 100644
index 0000000000..d6f86433a8
--- /dev/null
+++ b/epan/dissectors/packet-ieee80211.c
@@ -0,0 +1,3445 @@
+/* packet-ieee80211.c
+ * Routines for Wireless LAN (IEEE 802.11) dissection
+ * Copyright 2000, Axis Communications AB
+ * Inquiries/bugreports should be sent to Johan.Jorgensen@axis.com
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Credits:
+ *
+ * The following people helped me by pointing out bugs etc. Thank you!
+ *
+ * Marco Molteni
+ * Lena-Marie Nilsson
+ * Magnus Hultman-Persson
+ */
+
+/*
+ * 09/12/2003 - Added dissection of country information tag
+ *
+ * Ritchie<at>tipsybottle.com
+ *
+ * 03/22/2004 - Added dissection of RSN IE
+ * Jouni Malinen <jkmaline@cc.hut.fi>
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/bitswap.h>
+#include <epan/proto.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include <epan/strutil.h>
+#include "prefs.h"
+#include "reassemble.h"
+#include "packet-ipx.h"
+#include "packet-llc.h"
+#include "packet-ieee80211.h"
+#include "etypes.h"
+#include "crc32.h"
+
+/* Defragment fragmented 802.11 datagrams */
+static gboolean wlan_defragment = TRUE;
+
+/* Check for the presence of the 802.11 FCS */
+static gboolean wlan_check_fcs = FALSE;
+
+/* Ignore the WEP bit; assume packet is decrypted */
+static gboolean wlan_ignore_wep = FALSE;
+
+/* Tables for reassembly of fragments. */
+static GHashTable *wlan_fragment_table = NULL;
+static GHashTable *wlan_reassembled_table = NULL;
+
+/* Stuff for the WEP decoder */
+static guint num_wepkeys = 0;
+static guint8 **wep_keys = NULL;
+static int *wep_keylens = NULL;
+static void init_wepkeys(void);
+static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
+static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
+#define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
+
+/* #define USE_ENV */
+/* When this is set, an unlimited number of WEP keys can be set in the
+ environment:
+
+ ETHEREAL_WEPKEYNUM=##
+ ETHEREAL_WEPKEY1=aa:bb:cc:dd:...
+ ETHEREAL_WEPKEY2=aa:bab:cc:dd:ee:...
+
+ ... you get the idea.
+
+ otherwise you're limited to specifying four keys in the preference system.
+ */
+
+#ifndef USE_ENV
+static char *wep_keystr[] = {NULL, NULL, NULL, NULL};
+#endif
+
+/* ************************************************************************* */
+/* Miscellaneous Constants */
+/* ************************************************************************* */
+#define SHORT_STR 256
+
+/* ************************************************************************* */
+/* Define some very useful macros that are used to analyze frame types etc. */
+/* ************************************************************************* */
+#define COMPOSE_FRAME_TYPE(x) (((x & 0x0C)<< 2)+((x & 0xF0) >> 4)) /* Create key to (sub)type */
+#define COOK_PROT_VERSION(x) ((x) & 0x3)
+#define COOK_FRAME_TYPE(x) (((x) & 0xC) >> 2)
+#define COOK_FRAME_SUBTYPE(x) (((x) & 0xF0) >> 4)
+#define COOK_ADDR_SELECTOR(x) ((x) & 0x300)
+#define COOK_ASSOC_ID(x) ((x) & 0x3FFF)
+#define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
+#define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
+#define COOK_QOS_PRIORITY(x) ((x) & 0x0007)
+#define COOK_QOS_ACK_POLICY(x) (((x) & 0x0060) >> 5)
+#define COOK_FLAGS(x) (((x) & 0xFF00) >> 8)
+#define COOK_DS_STATUS(x) ((x) & 0x3)
+#define COOK_WEP_KEY(x) (((x) & 0xC0) >> 6)
+
+#define KEY_EXTIV 0x20
+#define EXTIV_LEN 8
+
+#define FLAG_TO_DS 0x01
+#define FLAG_FROM_DS 0x02
+#define FLAG_MORE_FRAGMENTS 0x04
+#define FLAG_RETRY 0x08
+#define FLAG_POWER_MGT 0x10
+#define FLAG_MORE_DATA 0x20
+#define FLAG_WEP 0x40
+#define FLAG_ORDER 0x80
+
+#define IS_TO_DS(x) ((x) & FLAG_TO_DS)
+#define IS_FROM_DS(x) ((x) & FLAG_FROM_DS)
+#define HAVE_FRAGMENTS(x) ((x) & FLAG_MORE_FRAGMENTS)
+#define IS_RETRY(x) ((x) & FLAG_RETRY)
+#define POWER_MGT_STATUS(x) ((x) & FLAG_POWER_MGT)
+#define HAS_MORE_DATA(x) ((x) & FLAG_MORE_DATA)
+#define IS_WEP(x) (!wlan_ignore_wep && ((x) & FLAG_WEP))
+#define IS_STRICTLY_ORDERED(x) ((x) & FLAG_ORDER)
+
+#define MGT_RESERVED_RANGE(x) (((x>=0x06)&&(x<=0x07))||((x>=0x0D)&&(x<=0x0F)))
+#define CTRL_RESERVED_RANGE(x) ((x>=0x10)&&(x<=0x19))
+#define DATA_RESERVED_RANGE(x) ((x>=0x28)&&(x<=0x2f))
+#define SPEC_RESERVED_RANGE(x) ((x>=0x30)&&(x<=0x3f))
+
+
+/* ************************************************************************* */
+/* Constants used to identify cooked frame types */
+/* ************************************************************************* */
+#define MGT_FRAME 0x00 /* Frame type is management */
+#define CONTROL_FRAME 0x01 /* Frame type is control */
+#define DATA_FRAME 0x02 /* Frame type is Data */
+
+#define DATA_SHORT_HDR_LEN 24
+#define DATA_LONG_HDR_LEN 30
+#define MGT_FRAME_HDR_LEN 24 /* Length of Managment frame-headers */
+
+#define MGT_ASSOC_REQ 0x00 /* Management - association request */
+#define MGT_ASSOC_RESP 0x01 /* Management - association response */
+#define MGT_REASSOC_REQ 0x02 /* Management - reassociation request */
+#define MGT_REASSOC_RESP 0x03 /* Management - reassociation response */
+#define MGT_PROBE_REQ 0x04 /* Management - Probe request */
+#define MGT_PROBE_RESP 0x05 /* Management - Probe response */
+#define MGT_BEACON 0x08 /* Management - Beacon frame */
+#define MGT_ATIM 0x09 /* Management - ATIM */
+#define MGT_DISASS 0x0A /* Management - Disassociation */
+#define MGT_AUTHENTICATION 0x0B /* Management - Authentication */
+#define MGT_DEAUTHENTICATION 0x0C /* Management - Deauthentication */
+#define MGT_ACTION 0x0D /* Management - Action */
+
+#define CTRL_PS_POLL 0x1A /* Control - power-save poll */
+#define CTRL_RTS 0x1B /* Control - request to send */
+#define CTRL_CTS 0x1C /* Control - clear to send */
+#define CTRL_ACKNOWLEDGEMENT 0x1D /* Control - acknowledgement */
+#define CTRL_CFP_END 0x1E /* Control - contention-free period end */
+#define CTRL_CFP_ENDACK 0x1F /* Control - contention-free period end/ack */
+
+#define DATA 0x20 /* Data - Data */
+#define DATA_CF_ACK 0x21 /* Data - Data + CF acknowledge */
+#define DATA_CF_POLL 0x22 /* Data - Data + CF poll */
+#define DATA_CF_ACK_POLL 0x23 /* Data - Data + CF acknowledge + CF poll */
+#define DATA_NULL_FUNCTION 0x24 /* Data - Null function (no data) */
+#define DATA_CF_ACK_NOD 0x25 /* Data - CF ack (no data) */
+#define DATA_CF_POLL_NOD 0x26 /* Data - Data + CF poll (No data) */
+#define DATA_CF_ACK_POLL_NOD 0x27 /* Data - CF ack + CF poll (no data) */
+#define DATA_QOS_DATA 0x28 /* Data - QoS Data */
+#define DATA_QOS_NULL 0x2c /* Data - QoS Null */
+
+#define DATA_ADDR_T1 0
+#define DATA_ADDR_T2 (FLAG_FROM_DS << 8)
+#define DATA_ADDR_T3 (FLAG_TO_DS << 8)
+#define DATA_ADDR_T4 ((FLAG_TO_DS|FLAG_FROM_DS) << 8)
+
+
+/* ************************************************************************* */
+/* Macros used to extract information about fixed fields */
+/* ************************************************************************* */
+#define ESS_SET(x) ((x) & 0x0001)
+#define IBSS_SET(x) ((x) & 0x0002)
+
+
+
+/* ************************************************************************* */
+/* Logical field codes (dissector's encoding of fixed fields) */
+/* ************************************************************************* */
+#define FIELD_TIMESTAMP 0x01 /* 64-bit timestamp */
+#define FIELD_BEACON_INTERVAL 0x02 /* 16-bit beacon interval */
+#define FIELD_CAP_INFO 0x03 /* Add capability information tree */
+#define FIELD_AUTH_ALG 0x04 /* Authentication algorithm used */
+#define FIELD_AUTH_TRANS_SEQ 0x05 /* Authentication sequence number */
+#define FIELD_CURRENT_AP_ADDR 0x06
+#define FIELD_LISTEN_IVAL 0x07
+#define FIELD_REASON_CODE 0x08
+#define FIELD_ASSOC_ID 0x09
+#define FIELD_STATUS_CODE 0x0A
+#define FIELD_CATEGORY_CODE 0x0B /* Management action category */
+#define FIELD_ACTION_CODE 0x0C /* Management action code */
+#define FIELD_DIALOG_TOKEN 0x0D /* Management action dialog token */
+#define FIELD_WME_ACTION_CODE 0x0E /* Management notification action code */
+#define FIELD_WME_DIALOG_TOKEN 0x0F /* Management notification dialog token */
+#define FIELD_WME_STATUS_CODE 0x10 /* Management notification setup response status code */
+
+/* ************************************************************************* */
+/* Logical field codes (IEEE 802.11 encoding of tags) */
+/* ************************************************************************* */
+#define TAG_SSID 0x00
+#define TAG_SUPP_RATES 0x01
+#define TAG_FH_PARAMETER 0x02
+#define TAG_DS_PARAMETER 0x03
+#define TAG_CF_PARAMETER 0x04
+#define TAG_TIM 0x05
+#define TAG_IBSS_PARAMETER 0x06
+#define TAG_COUNTRY_INFO 0x07
+#define TAG_FH_HOPPING_PARAMETER 0x08
+#define TAG_FH_HOPPING_TABLE 0x09
+#define TAG_CHALLENGE_TEXT 0x10
+#define TAG_ERP_INFO 0x2A
+#define TAG_ERP_INFO_OLD 0x2F /* IEEE Std 802.11g/D4.0 */
+#define TAG_RSN_IE 0x30
+#define TAG_EXT_SUPP_RATES 0x32
+#define TAG_VENDOR_SPECIFIC_IE 0xDD
+
+#define WPA_OUI "\x00\x50\xF2"
+#define RSN_OUI "\x00\x0F\xAC"
+#define WME_OUI "\x00\x50\xF2"
+
+#define PMKID_LEN 16
+
+/* ************************************************************************* */
+/* Frame types, and their names */
+/* ************************************************************************* */
+static const value_string frame_type_subtype_vals[] = {
+ {MGT_ASSOC_REQ, "Association Request"},
+ {MGT_ASSOC_RESP, "Association Response"},
+ {MGT_REASSOC_REQ, "Reassociation Request"},
+ {MGT_REASSOC_RESP, "Reassociation Response"},
+ {MGT_PROBE_REQ, "Probe Request"},
+ {MGT_PROBE_RESP, "Probe Response"},
+ {MGT_BEACON, "Beacon frame"},
+ {MGT_ATIM, "ATIM"},
+ {MGT_DISASS, "Dissassociate"},
+ {MGT_AUTHENTICATION, "Authentication"},
+ {MGT_DEAUTHENTICATION, "Deauthentication"},
+ {MGT_ACTION, "Action"},
+ {CTRL_PS_POLL, "Power-Save poll"},
+ {CTRL_RTS, "Request-to-send"},
+ {CTRL_CTS, "Clear-to-send"},
+ {CTRL_ACKNOWLEDGEMENT, "Acknowledgement"},
+ {CTRL_CFP_END, "CF-End (Control-frame)"},
+ {CTRL_CFP_ENDACK, "CF-End + CF-Ack (Control-frame)"},
+ {DATA, "Data"},
+ {DATA_CF_ACK, "Data + CF-Acknowledgement"},
+ {DATA_CF_POLL, "Data + CF-Poll"},
+ {DATA_CF_ACK_POLL, "Data + CF-Acknowledgement/Poll"},
+ {DATA_NULL_FUNCTION, "Null function (No data)"},
+ {DATA_CF_ACK_NOD, "Data + Acknowledgement (No data)"},
+ {DATA_CF_POLL_NOD, "Data + CF-Poll (No data)"},
+ {DATA_CF_ACK_POLL_NOD, "Data + CF-Acknowledgement/Poll (No data)"},
+ {DATA_QOS_DATA, "QoS Data"},
+ {DATA_QOS_NULL, "QoS Null (No data)"},
+ {0, NULL}
+};
+
+/* ************************************************************************* */
+/* 802.1D Tag Names */
+/* ************************************************************************* */
+static const char *qos_tags[8] = {
+ "Best Effort",
+ "Background",
+ "Spare",
+ "Excellent Effort",
+ "Controlled Load",
+ "Video",
+ "Voice",
+ "Network Control"
+};
+
+/* ************************************************************************* */
+/* WME Access Category Names (by 802.1D Tag) */
+/* ************************************************************************* */
+static const char *qos_acs[8] = {
+ "Best Effort",
+ "Background",
+ "Background",
+ "Video",
+ "Video",
+ "Video",
+ "Voice",
+ "Voice"
+};
+
+/* ************************************************************************* */
+/* WME Access Category Names (by WME ACI) */
+/* ************************************************************************* */
+static const char *wme_acs[4] = {
+ "Best Effort",
+ "Background",
+ "Video",
+ "Voice",
+};
+
+static int proto_wlan = -1;
+
+/* ************************************************************************* */
+/* Header field info values for radio information */
+/* ************************************************************************* */
+static int hf_data_rate = -1;
+static int hf_channel = -1;
+static int hf_signal_strength = -1;
+
+/* ************************************************************************* */
+/* Header field info values for FC-field */
+/* ************************************************************************* */
+static int hf_fc_field = -1;
+static int hf_fc_proto_version = -1;
+static int hf_fc_frame_type = -1;
+static int hf_fc_frame_subtype = -1;
+static int hf_fc_frame_type_subtype = -1;
+
+static int hf_fc_flags = -1;
+static int hf_fc_to_ds = -1;
+static int hf_fc_from_ds = -1;
+static int hf_fc_data_ds = -1;
+
+static int hf_fc_more_frag = -1;
+static int hf_fc_retry = -1;
+static int hf_fc_pwr_mgt = -1;
+static int hf_fc_more_data = -1;
+static int hf_fc_wep = -1;
+static int hf_fc_order = -1;
+
+
+/* ************************************************************************* */
+/* Header values for Duration/ID field */
+/* ************************************************************************* */
+static int hf_did_duration = -1;
+static int hf_assoc_id = -1;
+
+
+/* ************************************************************************* */
+/* Header values for different address-fields (all 4 of them) */
+/* ************************************************************************* */
+static int hf_addr_da = -1; /* Destination address subfield */
+static int hf_addr_sa = -1; /* Source address subfield */
+static int hf_addr_ra = -1; /* Receiver address subfield */
+static int hf_addr_ta = -1; /* Transmitter address subfield */
+static int hf_addr_bssid = -1; /* address is bssid */
+
+static int hf_addr = -1; /* Source or destination address subfield */
+
+
+/* ************************************************************************* */
+/* Header values for QoS control field */
+/* ************************************************************************* */
+static int hf_qos_priority = -1;
+static int hf_qos_ack_policy = -1;
+
+/* ************************************************************************* */
+/* Header values for sequence number field */
+/* ************************************************************************* */
+static int hf_frag_number = -1;
+static int hf_seq_number = -1;
+
+/* ************************************************************************* */
+/* Header values for Frame Check field */
+/* ************************************************************************* */
+static int hf_fcs = -1;
+
+/* ************************************************************************* */
+/* Header values for reassembly */
+/* ************************************************************************* */
+static int hf_fragments = -1;
+static int hf_fragment = -1;
+static int hf_fragment_overlap = -1;
+static int hf_fragment_overlap_conflict = -1;
+static int hf_fragment_multiple_tails = -1;
+static int hf_fragment_too_long_fragment = -1;
+static int hf_fragment_error = -1;
+static int hf_reassembled_in = -1;
+
+
+static int proto_wlan_mgt = -1;
+/* ************************************************************************* */
+/* Fixed fields found in mgt frames */
+/* ************************************************************************* */
+static int ff_auth_alg = -1; /* Authentication algorithm field */
+static int ff_auth_seq = -1; /* Authentication transaction sequence */
+static int ff_current_ap = -1; /* Current AP MAC address */
+static int ff_listen_ival = -1; /* Listen interval fixed field */
+static int ff_timestamp = -1; /* 64 bit timestamp */
+static int ff_beacon_interval = -1; /* 16 bit Beacon interval */
+static int ff_assoc_id = -1; /* 16 bit AID field */
+static int ff_reason = -1; /* 16 bit reason code */
+static int ff_status_code = -1; /* Status code */
+static int ff_category_code = -1; /* 8 bit Category code */
+static int ff_action_code = -1; /* 8 bit Action code */
+static int ff_dialog_token = -1; /* 8 bit Dialog token */
+static int ff_wme_action_code = -1; /* Management notification action code */
+static int ff_wme_status_code = -1; /* Management notification setup response status code */
+
+/* ************************************************************************* */
+/* Flags found in the capability field (fixed field) */
+/* ************************************************************************* */
+static int ff_capture = -1;
+static int ff_cf_ess = -1;
+static int ff_cf_ibss = -1;
+static int ff_cf_sta_poll = -1; /* CF pollable status for a STA */
+static int ff_cf_ap_poll = -1; /* CF pollable status for an AP */
+static int ff_cf_privacy = -1;
+static int ff_cf_preamble = -1;
+static int ff_cf_pbcc = -1;
+static int ff_cf_agility = -1;
+static int ff_short_slot_time = -1;
+static int ff_dsss_ofdm = -1;
+
+/* ************************************************************************* */
+/* Tagged value format fields */
+/* ************************************************************************* */
+static int tag_number = -1;
+static int tag_length = -1;
+static int tag_interpretation = -1;
+
+
+
+static int hf_fixed_parameters = -1; /* Protocol payload for management frames */
+static int hf_tagged_parameters = -1; /* Fixed payload item */
+static int hf_wep_iv = -1;
+static int hf_tkip_extiv = -1;
+static int hf_ccmp_extiv = -1;
+static int hf_wep_key = -1;
+static int hf_wep_icv = -1;
+
+
+static int rsn_cap = -1;
+static int rsn_cap_preauth = -1;
+static int rsn_cap_no_pairwise = -1;
+static int rsn_cap_ptksa_replay_counter = -1;
+static int rsn_cap_gtksa_replay_counter = -1;
+
+/* ************************************************************************* */
+/* Protocol trees */
+/* ************************************************************************* */
+static gint ett_80211 = -1;
+static gint ett_proto_flags = -1;
+static gint ett_cap_tree = -1;
+static gint ett_fc_tree = -1;
+static gint ett_fragments = -1;
+static gint ett_fragment = -1;
+
+static gint ett_80211_mgt = -1;
+static gint ett_fixed_parameters = -1;
+static gint ett_tagged_parameters = -1;
+static gint ett_qos_parameters = -1;
+static gint ett_wep_parameters = -1;
+
+static gint ett_rsn_cap_tree = -1;
+
+static const fragment_items frag_items = {
+ &ett_fragment,
+ &ett_fragments,
+ &hf_fragments,
+ &hf_fragment,
+ &hf_fragment_overlap,
+ &hf_fragment_overlap_conflict,
+ &hf_fragment_multiple_tails,
+ &hf_fragment_too_long_fragment,
+ &hf_fragment_error,
+ &hf_reassembled_in,
+ "fragments"
+};
+
+static dissector_handle_t llc_handle;
+static dissector_handle_t ipx_handle;
+static dissector_handle_t eth_handle;
+static dissector_handle_t data_handle;
+
+/* ************************************************************************* */
+/* Return the length of the current header (in bytes) */
+/* ************************************************************************* */
+static int
+find_header_length (guint16 fcf)
+{
+ int len;
+
+ switch (COOK_FRAME_TYPE (fcf)) {
+
+ case MGT_FRAME:
+ return MGT_FRAME_HDR_LEN;
+
+ case CONTROL_FRAME:
+ switch (COMPOSE_FRAME_TYPE (fcf)) {
+
+ case CTRL_CTS:
+ case CTRL_ACKNOWLEDGEMENT:
+ return 10;
+
+ case CTRL_RTS:
+ case CTRL_PS_POLL:
+ case CTRL_CFP_END:
+ case CTRL_CFP_ENDACK:
+ return 16;
+ }
+ return 4; /* XXX */
+
+ case DATA_FRAME:
+ len = (COOK_ADDR_SELECTOR(fcf) == DATA_ADDR_T4) ? DATA_LONG_HDR_LEN :
+ DATA_SHORT_HDR_LEN;
+ switch (COMPOSE_FRAME_TYPE (fcf)) {
+
+ case DATA_QOS_DATA:
+ case DATA_QOS_NULL:
+ return len + 2;
+
+ default:
+ return len;
+ }
+ default:
+ return 4; /* XXX */
+ }
+}
+
+
+/* ************************************************************************* */
+/* This is the capture function used to update packet counts */
+/* ************************************************************************* */
+static void
+capture_ieee80211_common (const guchar * pd, int offset, int len,
+ packet_counts * ld, gboolean fixed_length_header)
+{
+ guint16 fcf, hdr_length;
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
+ ld->other++;
+ return;
+ }
+
+ fcf = pletohs (&pd[0]);
+
+ if (IS_WEP(COOK_FLAGS(fcf)))
+ {
+ ld->other++;
+ return;
+ }
+
+ switch (COMPOSE_FRAME_TYPE (fcf))
+ {
+
+ case DATA: /* We got a data frame */
+ case DATA_CF_ACK: /* Data with ACK */
+ case DATA_CF_POLL:
+ case DATA_CF_ACK_POLL:
+ case DATA_QOS_DATA:
+ if (fixed_length_header)
+ hdr_length = DATA_LONG_HDR_LEN;
+ else
+ hdr_length = find_header_length (fcf);
+ /* I guess some bridges take Netware Ethernet_802_3 frames,
+ which are 802.3 frames (with a length field rather than
+ a type field, but with no 802.2 header in the payload),
+ and just stick the payload into an 802.11 frame. I've seen
+ captures that show frames of that sort.
+
+ This means we have to do the same check for Netware 802.3 -
+ or, if you will, "Netware 802.11" - that we do in the
+ Ethernet dissector, i.e. checking for 0xffff as the first
+ four bytes of the payload and, if we find it, treating it
+ as an IPX frame. */
+ if (!BYTES_ARE_IN_FRAME(offset+hdr_length, len, 2)) {
+ ld->other++;
+ return;
+ }
+ if (pd[offset+hdr_length] == 0xff && pd[offset+hdr_length+1] == 0xff) {
+ capture_ipx (ld);
+ }
+ else {
+ capture_llc (pd, offset + hdr_length, len, ld);
+ }
+ break;
+
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+/*
+ * Handle 802.11 with a variable-length link-layer header.
+ */
+void
+capture_ieee80211 (const guchar * pd, int offset, int len, packet_counts * ld)
+{
+ capture_ieee80211_common (pd, offset, len, ld, FALSE);
+}
+
+/*
+ * Handle 802.11 with a fixed-length link-layer header (padded to the
+ * maximum length).
+ */
+void
+capture_ieee80211_fixed (const guchar * pd, int offset, int len, packet_counts * ld)
+{
+ capture_ieee80211_common (pd, offset, len, ld, TRUE);
+}
+
+
+/* ************************************************************************* */
+/* Add the subtree used to store the fixed parameters */
+/* ************************************************************************* */
+static proto_tree *
+get_fixed_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
+{
+ proto_item *fixed_fields;
+ fixed_fields =
+ proto_tree_add_uint_format (tree, hf_fixed_parameters, tvb, start,
+ size, size, "Fixed parameters (%d bytes)",
+ size);
+
+ return proto_item_add_subtree (fixed_fields, ett_fixed_parameters);
+}
+
+
+/* ************************************************************************* */
+/* Add the subtree used to store tagged parameters */
+/* ************************************************************************* */
+static proto_tree *
+get_tagged_parameter_tree (proto_tree * tree, tvbuff_t *tvb, int start, int size)
+{
+ proto_item *tagged_fields;
+
+ tagged_fields = proto_tree_add_uint_format (tree, hf_tagged_parameters,
+ tvb,
+ start,
+ size,
+ size,
+ "Tagged parameters (%d bytes)",
+ size);
+
+ return proto_item_add_subtree (tagged_fields, ett_tagged_parameters);
+}
+
+
+/* ************************************************************************* */
+/* Dissect and add fixed mgmt fields to protocol tree */
+/* ************************************************************************* */
+static void
+add_fixed_field (proto_tree * tree, tvbuff_t * tvb, int offset, int lfcode)
+{
+ const guint8 *dataptr;
+ char out_buff[SHORT_STR];
+ guint16 capability;
+ proto_item *cap_item;
+ static proto_tree *cap_tree;
+ double temp_double;
+
+ switch (lfcode)
+ {
+ case FIELD_TIMESTAMP:
+ dataptr = tvb_get_ptr (tvb, offset, 8);
+ memset (out_buff, 0, SHORT_STR);
+ snprintf (out_buff, SHORT_STR, "0x%02X%02X%02X%02X%02X%02X%02X%02X",
+ dataptr[7],
+ dataptr[6],
+ dataptr[5],
+ dataptr[4],
+ dataptr[3],
+ dataptr[2],
+ dataptr[1],
+ dataptr[0]);
+
+ proto_tree_add_string (tree, ff_timestamp, tvb, offset, 8, out_buff);
+ break;
+
+ case FIELD_BEACON_INTERVAL:
+ temp_double = (double) tvb_get_letohs (tvb, offset);
+ temp_double = temp_double * 1024 / 1000000;
+ proto_tree_add_double_format (tree, ff_beacon_interval, tvb, offset, 2,
+ temp_double,"Beacon Interval: %f [Seconds]",
+ temp_double);
+ break;
+
+
+ case FIELD_CAP_INFO:
+ capability = tvb_get_letohs (tvb, offset);
+
+ cap_item = proto_tree_add_uint_format (tree, ff_capture,
+ tvb, offset, 2,
+ capability,
+ "Capability Information: 0x%04X",
+ capability);
+ cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
+ proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
+ capability);
+ if (ESS_SET (capability) != 0) /* This is an AP */
+ proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
+ capability);
+
+ else /* This is a STA */
+ proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
+ capability);
+ break;
+
+ case FIELD_AUTH_ALG:
+ proto_tree_add_item (tree, ff_auth_alg, tvb, offset, 2, TRUE);
+ break;
+
+ case FIELD_AUTH_TRANS_SEQ:
+ proto_tree_add_item (tree, ff_auth_seq, tvb, offset, 2, TRUE);
+ break;
+
+ case FIELD_CURRENT_AP_ADDR:
+ proto_tree_add_item (tree, ff_current_ap, tvb, offset, 6, FALSE);
+ break;
+
+ case FIELD_LISTEN_IVAL:
+ proto_tree_add_item (tree, ff_listen_ival, tvb, offset, 2, TRUE);
+ break;
+
+ case FIELD_REASON_CODE:
+ proto_tree_add_item (tree, ff_reason, tvb, offset, 2, TRUE);
+ break;
+
+ case FIELD_ASSOC_ID:
+ proto_tree_add_uint(tree, ff_assoc_id, tvb, offset, 2,
+ COOK_ASSOC_ID(tvb_get_letohs(tvb,offset)));
+ /* proto_tree_add_item (tree, ff_assoc_id, tvb, offset, 2, TRUE); */
+ break;
+
+ case FIELD_STATUS_CODE:
+ proto_tree_add_item (tree, ff_status_code, tvb, offset, 2, TRUE);
+ break;
+
+ case FIELD_CATEGORY_CODE:
+ proto_tree_add_item (tree, ff_category_code, tvb, offset, 1, TRUE);
+ break;
+
+ case FIELD_ACTION_CODE:
+ proto_tree_add_item (tree, ff_action_code, tvb, offset, 1, TRUE);
+ break;
+
+ case FIELD_DIALOG_TOKEN:
+ proto_tree_add_item (tree, ff_dialog_token, tvb, offset, 1, TRUE);
+ break;
+
+ case FIELD_WME_ACTION_CODE:
+ proto_tree_add_item (tree, ff_wme_action_code, tvb, offset, 1, TRUE);
+ break;
+
+ case FIELD_WME_STATUS_CODE:
+ proto_tree_add_item (tree, ff_wme_status_code, tvb, offset, 1, TRUE);
+ break;
+ }
+}
+
+static char *wpa_cipher_str[] =
+{
+ "NONE",
+ "WEP (40-bit)",
+ "TKIP",
+ "AES (OCB)",
+ "AES (CCM)",
+ "WEP (104-bit)",
+};
+
+static char *
+wpa_cipher_idx2str(guint idx)
+{
+ if (idx < sizeof(wpa_cipher_str)/sizeof(wpa_cipher_str[0]))
+ return wpa_cipher_str[idx];
+ return "UNKNOWN";
+}
+
+static char *wpa_keymgmt_str[] =
+{
+ "NONE",
+ "WPA",
+ "PSK",
+};
+
+static char *
+wpa_keymgmt_idx2str(guint idx)
+{
+ if (idx < sizeof(wpa_keymgmt_str)/sizeof(wpa_keymgmt_str[0]))
+ return wpa_keymgmt_str[idx];
+ return "UNKNOWN";
+}
+
+static void
+dissect_vendor_specific_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
+ guint32 tag_len, const guint8 *tag_val)
+{
+ guint32 tag_val_off = 0;
+ char out_buff[SHORT_STR], *pos;
+ guint i;
+
+ /* Wi-Fi Protected Access (WPA) Information Element */
+ if (tag_val_off + 6 <= tag_len && !memcmp(tag_val, WPA_OUI"\x01", 4)) {
+ snprintf(out_buff, SHORT_STR, "WPA IE, type %u, version %u",
+ tag_val[tag_val_off + 3], pletohs(&tag_val[tag_val_off + 4]));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
+ offset += 6;
+ tag_val_off += 6;
+ if (tag_val_off + 4 <= tag_len) {
+ /* multicast cipher suite */
+ if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
+ snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
+ wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
+ offset += 4;
+ tag_val_off += 4;
+ /* unicast cipher suites */
+ if (tag_val_off + 2 <= tag_len) {
+ snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u",
+ pletohs(tag_val + tag_val_off));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+ offset += 2;
+ tag_val_off += 2;
+ i = 1;
+ while (tag_val_off + 4 <= tag_len) {
+ if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
+ snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
+ i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
+ offset += 4;
+ tag_val_off += 4;
+ i ++;
+ }
+ else
+ break;
+ }
+ /* authenticated key management suites */
+ if (tag_val_off + 2 <= tag_len) {
+ snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u",
+ pletohs(tag_val + tag_val_off));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+ offset += 2;
+ tag_val_off += 2;
+ i = 1;
+ while (tag_val_off + 4 <= tag_len) {
+ if (!memcmp(&tag_val[tag_val_off], WPA_OUI, 3)) {
+ snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
+ i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
+ offset += 4;
+ tag_val_off += 4;
+ i ++;
+ }
+ else
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (tag_val_off < tag_len)
+ proto_tree_add_string(tree, tag_interpretation, tvb,
+ offset, tag_len - tag_val_off, "Not interpreted");
+ } else if (tag_val_off + 7 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x00", 5)) {
+ /* Wireless Multimedia Enhancements (WME) Information Element */
+ snprintf(out_buff, SHORT_STR, "WME IE: type %u, subtype %u, version %u, parameter set %u",
+ tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
+ tag_val[tag_val_off + 6]);
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
+ } else if (tag_val_off + 24 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x01", 5)) {
+ /* Wireless Multimedia Enhancements (WME) Parameter Element */
+ snprintf(out_buff, SHORT_STR, "WME PE: type %u, subtype %u, version %u, parameter set %u",
+ tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5],
+ tag_val[tag_val_off + 6]);
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 7, out_buff);
+ offset += 8;
+ tag_val_off += 8;
+ for (i = 0; i < 4; i++) {
+ snprintf(out_buff, SHORT_STR, "WME AC Parameters: ACI %u (%s), Admission Control %sMandatory, AIFSN %u, ECWmin %u, ECWmax %u, TXOP %u",
+ (tag_val[tag_val_off] & 0x60) >> 5,
+ wme_acs[(tag_val[tag_val_off] & 0x60) >> 5],
+ (tag_val[tag_val_off] & 0x10) ? "" : "not ",
+ tag_val[tag_val_off] & 0x0f,
+ tag_val[tag_val_off + 1] & 0x0f,
+ (tag_val[tag_val_off + 1] & 0xf0) >> 4,
+ tvb_get_letohs(tvb, offset + 2));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
+ offset += 4;
+ tag_val_off += 4;
+ }
+ } else if (tag_val_off + 56 <= tag_len && !memcmp(tag_val, WME_OUI"\x02\x02", 5)) {
+ /* Wireless Multimedia Enhancements (WME) TSPEC Element */
+ guint16 ts_info, msdu_size, surplus_bandwidth;
+ const char *direction[] = { "Uplink", "Downlink", "Reserved", "Bi-directional" };
+ const value_string fields[] = {
+ {12, "Minimum Service Interval"},
+ {16, "Maximum Service Interval"},
+ {20, "Inactivity Interval"},
+ {24, "Service Start Time"},
+ {28, "Minimum Data Rate"},
+ {32, "Mean Data Rate"},
+ {36, "Maximum Burst Size"},
+ {40, "Minimum PHY Rate"},
+ {44, "Peak Data Rate"},
+ {48, "Delay Bound"},
+ {0, NULL}
+ };
+ char *field;
+
+ snprintf(out_buff, SHORT_STR, "WME TSPEC: type %u, subtype %u, version %u",
+ tag_val[tag_val_off + 3], tag_val[tag_val_off + 4], tag_val[tag_val_off + 5]);
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 6, out_buff);
+ offset += 6;
+ tag_val_off += 6;
+
+ ts_info = tvb_get_letohs(tvb, offset);
+ snprintf(out_buff, SHORT_STR, "WME TS Info: Priority %u (%s) (%s), Contention-based access %sset, %s",
+ (ts_info >> 11) & 0x7, qos_tags[(ts_info >> 11) & 0x7], qos_acs[(ts_info >> 11) & 0x7],
+ (ts_info & 0x0080) ? "" : "not ",
+ direction[(ts_info >> 5) & 0x3]);
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+ offset += 2;
+ tag_val_off += 2;
+
+ msdu_size = tvb_get_letohs(tvb, offset);
+ snprintf(out_buff, SHORT_STR, "WME TSPEC: %s MSDU Size %u",
+ (msdu_size & 0x8000) ? "Fixed" : "Nominal", msdu_size & 0x7fff);
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+ offset += 2;
+ tag_val_off += 2;
+
+ snprintf(out_buff, SHORT_STR, "WME TSPEC: Maximum MSDU Size %u", tvb_get_letohs(tvb, offset));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+ offset += 2;
+ tag_val_off += 2;
+
+ while ((field = val_to_str(tag_val_off, fields, NULL))) {
+ snprintf(out_buff, SHORT_STR, "WME TSPEC: %s %u", field, tvb_get_letohl(tvb, offset));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
+ offset += 4;
+ tag_val_off += 4;
+ if (tag_val_off == 52)
+ break;
+ }
+
+ surplus_bandwidth = tvb_get_letohs(tvb, offset);
+ snprintf(out_buff, SHORT_STR, "WME TSPEC: Surplus Bandwidth Allowance Factor %u.%u",
+ (surplus_bandwidth >> 13) & 0x7, (surplus_bandwidth & 0x1fff));
+ offset += 2;
+ tag_val_off += 2;
+
+ snprintf(out_buff, SHORT_STR, "WME TSPEC: Medium Time %u", tvb_get_letohs(tvb, offset));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+ offset += 2;
+ tag_val_off += 2;
+ } else if (tag_val_off + 4 <= tag_len && !memcmp(tag_val, RSN_OUI"\x04", 4)) {
+ /* IEEE 802.11i / Key Data Encapsulation / Data Type=4 - PMKID.
+ * This is only used within EAPOL-Key frame Key Data. */
+ pos = out_buff;
+ pos += snprintf(pos, out_buff + SHORT_STR - pos, "RSN PMKID: ");
+ if (tag_len - 4 != PMKID_LEN) {
+ pos += snprintf(pos, out_buff + SHORT_STR - pos,
+ "(invalid PMKID len=%d, expected 16) ", tag_len - 4);
+ }
+ for (i = 0; i < tag_len - 4; i++) {
+ pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
+ tag_val[tag_val_off + 4 + i]);
+ }
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset,
+ tag_len, out_buff);
+ } else
+ proto_tree_add_string(tree, tag_interpretation,
+ tvb, offset, tag_len, "Not interpreted");
+}
+
+static void
+dissect_rsn_ie(proto_tree * tree, tvbuff_t * tvb, int offset,
+ guint32 tag_len, const guint8 *tag_val)
+{
+ guint32 tag_val_off = 0;
+ guint16 rsn_capab;
+ char out_buff[SHORT_STR];
+ int i, j, count;
+ proto_item *cap_item;
+ proto_tree *cap_tree;
+
+ if (tag_val_off + 2 > tag_len) {
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, tag_len,
+ "Not interpreted");
+ return;
+ }
+
+ snprintf(out_buff, SHORT_STR, "RSN IE, version %u",
+ pletohs(&tag_val[tag_val_off]));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+
+ offset += 2;
+ tag_val_off += 2;
+
+ if (tag_val_off + 4 > tag_len)
+ goto done;
+
+ /* multicast cipher suite */
+ if (!memcmp(&tag_val[tag_val_off], RSN_OUI, 3)) {
+ snprintf(out_buff, SHORT_STR, "Multicast cipher suite: %s",
+ wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
+ offset += 4;
+ tag_val_off += 4;
+ }
+
+ if (tag_val_off + 2 > tag_len)
+ goto done;
+
+ /* unicast cipher suites */
+ count = pletohs(tag_val + tag_val_off);
+ snprintf(out_buff, SHORT_STR, "# of unicast cipher suites: %u", count);
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+ offset += 2;
+ tag_val_off += 2;
+ i = 1;
+ while (tag_val_off + 4 <= tag_len && i <= count) {
+ if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
+ goto done;
+ snprintf(out_buff, SHORT_STR, "Unicast cipher suite %u: %s",
+ i, wpa_cipher_idx2str(tag_val[tag_val_off + 3]));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
+ offset += 4;
+ tag_val_off += 4;
+ i++;
+ }
+
+ if (i <= count || tag_val_off + 2 > tag_len)
+ goto done;
+
+ /* authenticated key management suites */
+ count = pletohs(tag_val + tag_val_off);
+ snprintf(out_buff, SHORT_STR, "# of auth key management suites: %u", count);
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+ offset += 2;
+ tag_val_off += 2;
+ i = 1;
+ while (tag_val_off + 4 <= tag_len && i <= count) {
+ if (memcmp(&tag_val[tag_val_off], RSN_OUI, 3) != 0)
+ goto done;
+ snprintf(out_buff, SHORT_STR, "auth key management suite %u: %s",
+ i, wpa_keymgmt_idx2str(tag_val[tag_val_off + 3]));
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 4, out_buff);
+ offset += 4;
+ tag_val_off += 4;
+ i++;
+ }
+
+ if (i <= count || tag_val_off + 2 > tag_len)
+ goto done;
+
+ rsn_capab = pletohs(&tag_val[tag_val_off]);
+ snprintf(out_buff, SHORT_STR, "RSN Capabilities 0x%04x", rsn_capab);
+ cap_item = proto_tree_add_uint_format(tree, rsn_cap, tvb,
+ offset, 2, rsn_capab,
+ "RSN Capabilities: 0x%04X", rsn_capab);
+ cap_tree = proto_item_add_subtree(cap_item, ett_rsn_cap_tree);
+ proto_tree_add_boolean(cap_tree, rsn_cap_preauth, tvb, offset, 2,
+ rsn_capab);
+ proto_tree_add_boolean(cap_tree, rsn_cap_no_pairwise, tvb, offset, 2,
+ rsn_capab);
+ proto_tree_add_uint(cap_tree, rsn_cap_ptksa_replay_counter, tvb, offset, 2,
+ rsn_capab);
+ proto_tree_add_uint(cap_tree, rsn_cap_gtksa_replay_counter, tvb, offset, 2,
+ rsn_capab);
+ offset += 2;
+ tag_val_off += 2;
+
+ if (tag_val_off + 2 > tag_len)
+ goto done;
+
+ count = pletohs(tag_val + tag_val_off);
+ snprintf(out_buff, SHORT_STR, "# of PMKIDs: %u", count);
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset, 2, out_buff);
+ offset += 2;
+ tag_val_off += 2;
+
+ /* PMKID List (16 * n octets) */
+ for (i = 0; i < count; i++) {
+ char *pos;
+ if (tag_val_off + PMKID_LEN > tag_len)
+ goto done;
+ pos = out_buff;
+ pos += snprintf(pos, out_buff + SHORT_STR - pos, "PMKID %u: ", i);
+ for (j = 0; j < PMKID_LEN; j++) {
+ pos += snprintf(pos, out_buff + SHORT_STR - pos, "%02X",
+ tag_val[tag_val_off + j]);
+ }
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset,
+ PMKID_LEN, out_buff);
+ offset += PMKID_LEN;
+ tag_val_off += PMKID_LEN;
+ }
+
+ done:
+ if (tag_val_off < tag_len)
+ proto_tree_add_string(tree, tag_interpretation, tvb, offset,
+ tag_len - tag_val_off, "Not interpreted");
+}
+
+/* ************************************************************************* */
+/* Dissect and add tagged (optional) fields to proto tree */
+/* ************************************************************************* */
+
+static const value_string tag_num_vals[] = {
+ { TAG_SSID, "SSID parameter set" },
+ { TAG_SUPP_RATES, "Supported Rates" },
+ { TAG_FH_PARAMETER, "FH Parameter set" },
+ { TAG_DS_PARAMETER, "DS Parameter set" },
+ { TAG_CF_PARAMETER, "CF Parameter set" },
+ { TAG_TIM, "(TIM) Traffic Indication Map" },
+ { TAG_IBSS_PARAMETER, "IBSS Parameter set" },
+ { TAG_COUNTRY_INFO, "Country Information" },
+ { TAG_FH_HOPPING_PARAMETER, "Hopping Pattern Parameters" },
+ { TAG_CHALLENGE_TEXT, "Challenge text" },
+ { TAG_ERP_INFO, "ERP Information" },
+ { TAG_ERP_INFO_OLD, "ERP Information" },
+ { TAG_RSN_IE, "RSN Information" },
+ { TAG_EXT_SUPP_RATES, "Extended Supported Rates" },
+ { TAG_VENDOR_SPECIFIC_IE, "Vendor Specific" },
+ { 0, NULL }
+};
+
+static const value_string environment_vals[] = {
+ { 0x20, "Any" },
+ { 0x4f, "Outdoor" },
+ { 0x49, "Indoor" },
+ { 0, NULL }
+};
+
+static int
+add_tagged_field (proto_tree * tree, tvbuff_t * tvb, int offset)
+{
+ const guint8 *tag_data_ptr;
+ guint32 tag_no, tag_len;
+ unsigned int i;
+ int n, ret;
+ char out_buff[SHORT_STR];
+
+
+ tag_no = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format (tree, tag_number, tvb, offset, 1, tag_no,
+ "Tag Number: %u (%s)",
+ tag_no,
+ val_to_str(tag_no, tag_num_vals,
+ (tag_no >= 17 && tag_no <= 31) ?
+ "Reserved for challenge text" :
+ "Reserved tag number"));
+
+ tag_len = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_uint (tree, tag_length, tvb, offset + 1, 1, tag_len);
+
+ tag_data_ptr = tvb_get_ptr (tvb, offset + 2, tag_len);
+
+ switch (tag_no)
+ {
+
+
+ case TAG_SSID:
+ memset (out_buff, 0, SHORT_STR);
+
+ memcpy (out_buff, tag_data_ptr, (size_t) tag_len);
+ out_buff[tag_len + 1] = 0;
+
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, out_buff);
+ break;
+
+
+
+ case TAG_SUPP_RATES:
+ case TAG_EXT_SUPP_RATES:
+ memset (out_buff, 0, SHORT_STR);
+ strcpy (out_buff, "Supported rates: ");
+ n = strlen (out_buff);
+
+ for (i = 0; i < tag_len && n < SHORT_STR; i++)
+ {
+ ret = snprintf (out_buff + n, SHORT_STR - n, "%2.1f%s ",
+ (tag_data_ptr[i] & 0x7F) * 0.5,
+ (tag_data_ptr[i] & 0x80) ? "(B)" : "");
+ if (ret == -1 || ret >= SHORT_STR - n) {
+ /* Some versions of snprintf return -1 if they'd truncate
+ the output. Others return <buf_size> or greater. */
+ break;
+ }
+ n += ret;
+ }
+ if (n < SHORT_STR)
+ snprintf (out_buff + n, SHORT_STR - n, "[Mbit/sec]");
+
+ out_buff[SHORT_STR-1] = '\0';
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, out_buff);
+ break;
+
+
+
+ case TAG_FH_PARAMETER:
+ memset (out_buff, 0, SHORT_STR);
+
+ snprintf (out_buff, SHORT_STR,
+ "Dwell time 0x%04X, Hop Set %2d, Hop Pattern %2d, "
+ "Hop Index %2d", pletohs (tag_data_ptr), tag_data_ptr[2],
+ tag_data_ptr[3], tag_data_ptr[4]);
+
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, out_buff);
+ break;
+
+
+
+ case TAG_DS_PARAMETER:
+ memset (out_buff, 0, SHORT_STR);
+
+ snprintf (out_buff, SHORT_STR, "Current Channel: %u", tag_data_ptr[0]);
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, out_buff);
+ break;
+
+
+ case TAG_CF_PARAMETER:
+ memset (out_buff, 0, SHORT_STR);
+
+ snprintf (out_buff, SHORT_STR,
+ "CFP count %u, CFP period %u, CFP max duration %u, "
+ "CFP Remaining %u", tag_data_ptr[0], tag_data_ptr[1],
+ pletohs (tag_data_ptr + 2), pletohs (tag_data_ptr + 4));
+
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, out_buff);
+ break;
+
+
+ case TAG_TIM:
+ memset (out_buff, 0, SHORT_STR);
+ snprintf (out_buff, SHORT_STR,
+ "DTIM count %u, DTIM period %u, Bitmap control 0x%X, "
+ "(Bitmap suppressed)", tag_data_ptr[0], tag_data_ptr[1],
+ tag_data_ptr[2]);
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, out_buff);
+ break;
+
+
+
+ case TAG_IBSS_PARAMETER:
+ memset (out_buff, 0, SHORT_STR);
+ snprintf (out_buff, SHORT_STR, "ATIM window 0x%X",
+ pletohs (tag_data_ptr));
+
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, out_buff);
+ break;
+
+
+ case TAG_COUNTRY_INFO:
+ memset (out_buff, 0, SHORT_STR);
+
+ snprintf (out_buff, SHORT_STR, "Country Code: %c%c, %s Environment",
+ tag_data_ptr[0], tag_data_ptr[1],
+ val_to_str(tag_data_ptr[2], environment_vals,"Unknown (0x%02x)"));
+
+ n = strlen (out_buff);
+
+ for (i = 3; (i + 3) <= tag_len && n < SHORT_STR; i += 3)
+ {
+ ret = snprintf(out_buff + n, SHORT_STR - n,
+ ", Start Channel: %u, Channels: %u, Max TX Power: %d dBm",
+ tag_data_ptr[i], tag_data_ptr[i + 1],
+ (gint)tag_data_ptr[i + 2]);
+
+ if (ret == -1 || ret >= SHORT_STR - n) {
+ /* Some versions of snprintf return -1 if they'd truncate
+ the output. Others return <buf_size> or greater. */
+ break;
+ }
+ n += ret;
+ }
+
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,tag_len, out_buff);
+ break;
+
+
+ case TAG_FH_HOPPING_PARAMETER:
+ memset (out_buff, 0, SHORT_STR);
+ snprintf (out_buff, SHORT_STR, "Prime Radix: %u, Number of Channels: %u",
+ tag_data_ptr[0], tag_data_ptr[1]);
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2, tag_len, out_buff);
+
+
+ break;
+
+
+ case TAG_CHALLENGE_TEXT:
+ memset (out_buff, 0, SHORT_STR);
+ snprintf (out_buff, SHORT_STR, "Challenge text: %.47s", tag_data_ptr);
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, out_buff);
+
+ break;
+
+
+
+ case TAG_ERP_INFO:
+ case TAG_ERP_INFO_OLD:
+ memset (out_buff, 0, SHORT_STR);
+
+ snprintf (out_buff, SHORT_STR,
+ "ERP info: 0x%x (%sNon-ERP STAs, %suse protection, %s preambles)",
+ tag_data_ptr[0],
+ tag_data_ptr[0] & 0x01 ? "" : "no ",
+ tag_data_ptr[0] & 0x02 ? "" : "do not ",
+ tag_data_ptr[0] & 0x04 ? "short or long": "long");
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, out_buff);
+
+ break;
+
+ case TAG_VENDOR_SPECIFIC_IE:
+ dissect_vendor_specific_ie(tree, tvb, offset + 2, tag_len,
+ tag_data_ptr);
+ break;
+
+ case TAG_RSN_IE:
+ dissect_rsn_ie(tree, tvb, offset + 2, tag_len, tag_data_ptr);
+ break;
+
+
+ default:
+ proto_tree_add_string (tree, tag_interpretation, tvb, offset + 2,
+ tag_len, "Not interpreted");
+ break;
+ }
+
+ return tag_len + 2;
+}
+
+void
+ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset, proto_tree * tree,
+ int tagged_parameters_len)
+{
+ int next_len;
+
+ while (tagged_parameters_len > 0) {
+ if ((next_len=add_tagged_field (tree, tvb, offset))==0)
+ break;
+ if (next_len > tagged_parameters_len) {
+ /* XXX - flag this as an error? */
+ next_len = tagged_parameters_len;
+ }
+ offset += next_len;
+ tagged_parameters_len -= next_len;
+ }
+}
+
+/* ************************************************************************* */
+/* Dissect 802.11 management frame */
+/* ************************************************************************* */
+static void
+dissect_ieee80211_mgt (guint16 fcf, tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree)
+{
+ proto_item *ti = NULL;
+ proto_tree *mgt_tree;
+ proto_tree *fixed_tree;
+ proto_tree *tagged_tree;
+ int offset;
+ int tagged_parameter_tree_len;
+
+ CHECK_DISPLAY_AS_X(data_handle,proto_wlan_mgt, tvb, pinfo, tree);
+
+ if (tree)
+ {
+ ti = proto_tree_add_item (tree, proto_wlan_mgt, tvb, 0, -1, FALSE);
+ mgt_tree = proto_item_add_subtree (ti, ett_80211_mgt);
+
+ switch (COMPOSE_FRAME_TYPE(fcf))
+ {
+
+ case MGT_ASSOC_REQ:
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 4);
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
+ add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
+
+ offset = 4; /* Size of fixed fields */
+ tagged_parameter_tree_len =
+ tvb_reported_length_remaining(tvb, offset);
+ tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
+ tagged_parameter_tree_len);
+
+ ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+ tagged_parameter_tree_len);
+ break;
+
+
+ case MGT_ASSOC_RESP:
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
+ add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
+ add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
+
+ offset = 6; /* Size of fixed fields */
+
+ tagged_parameter_tree_len =
+ tvb_reported_length_remaining(tvb, offset);
+ tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
+ tagged_parameter_tree_len);
+
+ ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+ tagged_parameter_tree_len);
+ break;
+
+
+ case MGT_REASSOC_REQ:
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
+ add_fixed_field (fixed_tree, tvb, 2, FIELD_LISTEN_IVAL);
+ add_fixed_field (fixed_tree, tvb, 4, FIELD_CURRENT_AP_ADDR);
+
+ offset = 10; /* Size of fixed fields */
+ tagged_parameter_tree_len =
+ tvb_reported_length_remaining(tvb, offset);
+ tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
+ tagged_parameter_tree_len);
+
+ ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+ tagged_parameter_tree_len);
+ break;
+
+ case MGT_REASSOC_RESP:
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 10);
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_CAP_INFO);
+ add_fixed_field (fixed_tree, tvb, 2, FIELD_STATUS_CODE);
+ add_fixed_field (fixed_tree, tvb, 4, FIELD_ASSOC_ID);
+
+ offset = 6; /* Size of fixed fields */
+ tagged_parameter_tree_len =
+ tvb_reported_length_remaining(tvb, offset);
+ tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
+ tagged_parameter_tree_len);
+
+ ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+ tagged_parameter_tree_len);
+ break;
+
+
+ case MGT_PROBE_REQ:
+ offset = 0;
+ tagged_parameter_tree_len =
+ tvb_reported_length_remaining(tvb, offset);
+ tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
+ tagged_parameter_tree_len);
+
+ ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+ tagged_parameter_tree_len);
+ break;
+
+
+ case MGT_PROBE_RESP:
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
+ add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
+ add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
+
+ offset = 12; /* Size of fixed fields */
+ tagged_parameter_tree_len =
+ tvb_reported_length_remaining(tvb, offset);
+ tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
+ tagged_parameter_tree_len);
+
+ ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+ tagged_parameter_tree_len);
+ break;
+
+
+ case MGT_BEACON: /* Dissect protocol payload fields */
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 12);
+
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_TIMESTAMP);
+ add_fixed_field (fixed_tree, tvb, 8, FIELD_BEACON_INTERVAL);
+ add_fixed_field (fixed_tree, tvb, 10, FIELD_CAP_INFO);
+
+ offset = 12; /* Size of fixed fields */
+ tagged_parameter_tree_len =
+ tvb_reported_length_remaining(tvb, offset);
+ tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
+ tagged_parameter_tree_len);
+
+ ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+ tagged_parameter_tree_len);
+ break;
+
+
+ case MGT_ATIM:
+ break;
+
+
+ case MGT_DISASS:
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
+ break;
+
+
+ case MGT_AUTHENTICATION:
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 6);
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_AUTH_ALG);
+ add_fixed_field (fixed_tree, tvb, 2, FIELD_AUTH_TRANS_SEQ);
+ add_fixed_field (fixed_tree, tvb, 4, FIELD_STATUS_CODE);
+
+ offset = 6; /* Size of fixed fields */
+
+ tagged_parameter_tree_len =
+ tvb_reported_length_remaining(tvb, offset);
+ if (tagged_parameter_tree_len != 0)
+ {
+ tagged_tree = get_tagged_parameter_tree (mgt_tree,
+ tvb,
+ offset,
+ tagged_parameter_tree_len);
+
+ ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+ tagged_parameter_tree_len);
+ }
+ break;
+
+
+ case MGT_DEAUTHENTICATION:
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 2);
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_REASON_CODE);
+ break;
+
+
+ case MGT_ACTION:
+ fixed_tree = get_fixed_parameter_tree (mgt_tree, tvb, 0, 3);
+ add_fixed_field (fixed_tree, tvb, 0, FIELD_CATEGORY_CODE);
+
+ switch (tvb_get_guint8(tvb, 0))
+ {
+
+ case 17: /* Management notification frame */
+ add_fixed_field (fixed_tree, tvb, 1, FIELD_WME_ACTION_CODE);
+ add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
+ add_fixed_field (fixed_tree, tvb, 3, FIELD_WME_STATUS_CODE);
+
+ offset = 4; /* Size of fixed fields */
+
+ tagged_parameter_tree_len =
+ tvb_reported_length_remaining(tvb, offset);
+ if (tagged_parameter_tree_len != 0)
+ {
+ tagged_tree = get_tagged_parameter_tree (mgt_tree, tvb, offset,
+ tagged_parameter_tree_len);
+
+ ieee_80211_add_tagged_parameters (tvb, offset, tagged_tree,
+ tagged_parameter_tree_len);
+ }
+ break;
+
+ default: /* Management action frame */
+ add_fixed_field (fixed_tree, tvb, 1, FIELD_ACTION_CODE);
+ add_fixed_field (fixed_tree, tvb, 2, FIELD_DIALOG_TOKEN);
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static void
+set_src_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
+{
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "%s (%s)",
+ get_ether_name(addr), type);
+ if (check_col(pinfo->cinfo, COL_UNRES_DL_SRC))
+ col_add_fstr(pinfo->cinfo, COL_UNRES_DL_SRC, "%s (%s)",
+ ether_to_str(addr), type);
+}
+
+static void
+set_dst_addr_cols(packet_info *pinfo, const guint8 *addr, char *type)
+{
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_add_fstr(pinfo->cinfo, COL_RES_DL_DST, "%s (%s)",
+ get_ether_name(addr), type);
+ if (check_col(pinfo->cinfo, COL_UNRES_DL_DST))
+ col_add_fstr(pinfo->cinfo, COL_UNRES_DL_DST, "%s (%s)",
+ ether_to_str(addr), type);
+}
+
+typedef enum {
+ ENCAP_802_2,
+ ENCAP_IPX,
+ ENCAP_ETHERNET
+} encap_t;
+
+/* ************************************************************************* */
+/* Dissect 802.11 frame */
+/* ************************************************************************* */
+static void
+dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree, gboolean fixed_length_header,
+ gboolean has_radio_information, gint fcs_len,
+ gboolean wlan_broken_fc)
+{
+ guint16 fcf, flags, frame_type_subtype;
+ guint16 seq_control;
+ guint32 seq_number, frag_number;
+ gboolean more_frags;
+ const guint8 *src = NULL, *dst = NULL;
+ proto_item *ti = NULL;
+ proto_item *flag_item;
+ proto_item *fc_item;
+ proto_tree *hdr_tree = NULL;
+ proto_tree *flag_tree;
+ proto_tree *fc_tree;
+ guint16 hdr_len;
+ gboolean has_fcs;
+ gint len, reported_len, ivlen;
+ gboolean save_fragmented;
+ tvbuff_t *volatile next_tvb = NULL;
+ guint32 addr_type;
+ volatile encap_t encap_type;
+ guint8 octet1, octet2;
+ char out_buff[SHORT_STR];
+
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11");
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_clear (pinfo->cinfo, COL_INFO);
+
+ /* Add the radio information, if present, to the column information */
+ if (has_radio_information) {
+ if (check_col(pinfo->cinfo, COL_TX_RATE)) {
+ col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
+ pinfo->pseudo_header->ieee_802_11.data_rate / 2,
+ pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
+ }
+ if (check_col(pinfo->cinfo, COL_RSSI)) {
+ /* XX - this is a percentage, not a dBm or normalized or raw RSSI */
+ col_add_fstr(pinfo->cinfo, COL_RSSI, "%u",
+ pinfo->pseudo_header->ieee_802_11.signal_level);
+ }
+ }
+
+ fcf = tvb_get_letohs (tvb, 0);
+ if (wlan_broken_fc) {
+ /* Swap bytes */
+ fcf = ((fcf & 0xff) << 8) | (((fcf & 0xff00) >> 8) & 0xff);
+ }
+ if (fixed_length_header)
+ hdr_len = DATA_LONG_HDR_LEN;
+ else
+ hdr_len = find_header_length (fcf);
+ frame_type_subtype = COMPOSE_FRAME_TYPE(fcf);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_set_str (pinfo->cinfo, COL_INFO,
+ val_to_str(frame_type_subtype, frame_type_subtype_vals,
+ "Unrecognized (Reserved frame)"));
+
+ flags = COOK_FLAGS (fcf);
+ more_frags = HAVE_FRAGMENTS (flags);
+
+ /* Add the radio information, if present, and the FC to the current tree */
+ if (tree)
+ {
+ ti = proto_tree_add_protocol_format (tree, proto_wlan, tvb, 0, hdr_len,
+ "IEEE 802.11");
+ hdr_tree = proto_item_add_subtree (ti, ett_80211);
+
+ if (has_radio_information) {
+ proto_tree_add_uint_format(hdr_tree, hf_data_rate,
+ tvb, 0, 0,
+ pinfo->pseudo_header->ieee_802_11.data_rate,
+ "Data Rate: %u.%u Mb/s",
+ pinfo->pseudo_header->ieee_802_11.data_rate / 2,
+ pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
+
+ proto_tree_add_uint(hdr_tree, hf_channel,
+ tvb, 0, 0,
+ pinfo->pseudo_header->ieee_802_11.channel);
+
+ proto_tree_add_uint_format(hdr_tree, hf_signal_strength,
+ tvb, 0, 0,
+ pinfo->pseudo_header->ieee_802_11.signal_level,
+ "Signal Strength: %u%%",
+ pinfo->pseudo_header->ieee_802_11.signal_level);
+ }
+
+ proto_tree_add_uint (hdr_tree, hf_fc_frame_type_subtype,
+ tvb,
+ wlan_broken_fc?1:0, 1,
+ frame_type_subtype);
+
+ fc_item = proto_tree_add_uint_format (hdr_tree, hf_fc_field, tvb,
+ 0, 2,
+ fcf,
+ "Frame Control: 0x%04X (%s)",
+ fcf, wlan_broken_fc?"Swapped":"Normal");
+
+ fc_tree = proto_item_add_subtree (fc_item, ett_fc_tree);
+
+
+ proto_tree_add_uint (fc_tree, hf_fc_proto_version, tvb,
+ wlan_broken_fc?1:0, 1,
+ COOK_PROT_VERSION (fcf));
+
+ proto_tree_add_uint (fc_tree, hf_fc_frame_type, tvb,
+ wlan_broken_fc?1:0, 1,
+ COOK_FRAME_TYPE (fcf));
+
+ proto_tree_add_uint (fc_tree, hf_fc_frame_subtype,
+ tvb,
+ wlan_broken_fc?1:0, 1,
+ COOK_FRAME_SUBTYPE (fcf));
+
+ flag_item =
+ proto_tree_add_uint_format (fc_tree, hf_fc_flags, tvb,
+ wlan_broken_fc?0:1, 1,
+ flags, "Flags: 0x%X", flags);
+
+ flag_tree = proto_item_add_subtree (flag_item, ett_proto_flags);
+
+ proto_tree_add_uint (flag_tree, hf_fc_data_ds, tvb,
+ wlan_broken_fc?0:1, 1,
+ COOK_DS_STATUS (flags));
+ proto_tree_add_boolean_hidden (flag_tree, hf_fc_to_ds, tvb, 1, 1,
+ flags);
+ proto_tree_add_boolean_hidden (flag_tree, hf_fc_from_ds, tvb, 1, 1,
+ flags);
+
+ proto_tree_add_boolean (flag_tree, hf_fc_more_frag, tvb,
+ wlan_broken_fc?0:1, 1,
+ flags);
+
+ proto_tree_add_boolean (flag_tree, hf_fc_retry, tvb,
+ wlan_broken_fc?0:1, 1, flags);
+
+ proto_tree_add_boolean (flag_tree, hf_fc_pwr_mgt, tvb,
+ wlan_broken_fc?0:1, 1, flags);
+
+ proto_tree_add_boolean (flag_tree, hf_fc_more_data, tvb,
+ wlan_broken_fc?0:1, 1,
+ flags);
+
+ proto_tree_add_boolean (flag_tree, hf_fc_wep, tvb,
+ wlan_broken_fc?0:1, 1, flags);
+
+ proto_tree_add_boolean (flag_tree, hf_fc_order, tvb,
+ wlan_broken_fc?0:1, 1, flags);
+
+ if (frame_type_subtype == CTRL_PS_POLL)
+ proto_tree_add_uint(hdr_tree, hf_assoc_id,tvb,2,2,
+ COOK_ASSOC_ID(tvb_get_letohs(tvb,2)));
+
+ else
+ proto_tree_add_uint (hdr_tree, hf_did_duration, tvb, 2, 2,
+ tvb_get_letohs (tvb, 2));
+ }
+
+ /*
+ * Decode the part of the frame header that isn't the same for all
+ * frame types.
+ */
+ seq_control = 0;
+ frag_number = 0;
+ seq_number = 0;
+
+ switch (COOK_FRAME_TYPE (fcf))
+ {
+
+ case MGT_FRAME:
+ /*
+ * All management frame types have the same header.
+ */
+ src = tvb_get_ptr (tvb, 10, 6);
+ dst = tvb_get_ptr (tvb, 4, 6);
+
+ SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
+ SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
+ SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
+ SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
+
+ seq_control = tvb_get_letohs(tvb, 22);
+ frag_number = COOK_FRAGMENT_NUMBER(seq_control);
+ seq_number = COOK_SEQUENCE_NUMBER(seq_control);
+
+ if (tree)
+ {
+ proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
+
+ proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
+
+ /* add items for wlan.addr filter */
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
+
+ proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
+ tvb_get_ptr (tvb, 16, 6));
+
+ proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
+ frag_number);
+
+ proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
+ seq_number);
+ }
+ break;
+
+ case CONTROL_FRAME:
+ switch (frame_type_subtype)
+ {
+
+ case CTRL_PS_POLL:
+ src = tvb_get_ptr (tvb, 10, 6);
+ dst = tvb_get_ptr (tvb, 4, 6);
+
+ set_src_addr_cols(pinfo, src, "BSSID");
+ set_dst_addr_cols(pinfo, dst, "BSSID");
+
+ if (tree)
+ {
+ proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6, dst);
+
+ proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
+ }
+ break;
+
+
+ case CTRL_RTS:
+ src = tvb_get_ptr (tvb, 10, 6);
+ dst = tvb_get_ptr (tvb, 4, 6);
+
+ set_src_addr_cols(pinfo, src, "TA");
+ set_dst_addr_cols(pinfo, dst, "RA");
+
+ if (tree)
+ {
+ proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
+
+ proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6, src);
+ }
+ break;
+
+
+ case CTRL_CTS:
+ dst = tvb_get_ptr (tvb, 4, 6);
+
+ set_dst_addr_cols(pinfo, dst, "RA");
+
+ if (tree)
+ proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
+ break;
+
+
+ case CTRL_ACKNOWLEDGEMENT:
+ dst = tvb_get_ptr (tvb, 4, 6);
+
+ set_dst_addr_cols(pinfo, dst, "RA");
+
+ if (tree)
+ proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
+ break;
+
+
+ case CTRL_CFP_END:
+ src = tvb_get_ptr (tvb, 10, 6);
+ dst = tvb_get_ptr (tvb, 4, 6);
+
+ set_src_addr_cols(pinfo, src, "BSSID");
+ set_dst_addr_cols(pinfo, dst, "RA");
+
+ if (tree)
+ {
+ proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
+ proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
+ }
+ break;
+
+
+ case CTRL_CFP_ENDACK:
+ src = tvb_get_ptr (tvb, 10, 6);
+ dst = tvb_get_ptr (tvb, 4, 6);
+
+ set_src_addr_cols(pinfo, src, "BSSID");
+ set_dst_addr_cols(pinfo, dst, "RA");
+
+ if (tree)
+ {
+ proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6, dst);
+
+ proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6, src);
+ }
+ break;
+ }
+ break;
+
+ case DATA_FRAME:
+ addr_type = COOK_ADDR_SELECTOR (fcf);
+
+ /* In order to show src/dst address we must always do the following */
+ switch (addr_type)
+ {
+
+ case DATA_ADDR_T1:
+ src = tvb_get_ptr (tvb, 10, 6);
+ dst = tvb_get_ptr (tvb, 4, 6);
+ break;
+
+
+ case DATA_ADDR_T2:
+ src = tvb_get_ptr (tvb, 16, 6);
+ dst = tvb_get_ptr (tvb, 4, 6);
+ break;
+
+
+ case DATA_ADDR_T3:
+ src = tvb_get_ptr (tvb, 10, 6);
+ dst = tvb_get_ptr (tvb, 16, 6);
+ break;
+
+
+ case DATA_ADDR_T4:
+ src = tvb_get_ptr (tvb, 24, 6);
+ dst = tvb_get_ptr (tvb, 16, 6);
+ break;
+ }
+
+ SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
+ SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
+ SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst);
+ SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst);
+
+ seq_control = tvb_get_letohs(tvb, 22);
+ frag_number = COOK_FRAGMENT_NUMBER(seq_control);
+ seq_number = COOK_SEQUENCE_NUMBER(seq_control);
+
+ /* Now if we have a tree we start adding stuff */
+ if (tree)
+ {
+
+
+ switch (addr_type)
+ {
+
+ case DATA_ADDR_T1:
+ proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
+ proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
+ proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 16, 6,
+ tvb_get_ptr (tvb, 16, 6));
+ proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
+ frag_number);
+ proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
+ seq_number);
+
+ /* add items for wlan.addr filter */
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
+ break;
+
+
+ case DATA_ADDR_T2:
+ proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 4, 6, dst);
+ proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 10, 6,
+ tvb_get_ptr (tvb, 10, 6));
+ proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 16, 6, src);
+ proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
+ frag_number);
+ proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
+ seq_number);
+
+ /* add items for wlan.addr filter */
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 4, 6, dst);
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, src);
+ break;
+
+
+ case DATA_ADDR_T3:
+ proto_tree_add_ether (hdr_tree, hf_addr_bssid, tvb, 4, 6,
+ tvb_get_ptr (tvb, 4, 6));
+ proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 10, 6, src);
+ proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
+
+ proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
+ frag_number);
+ proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
+ seq_number);
+
+ /* add items for wlan.addr filter */
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 10, 6, src);
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
+ break;
+
+
+ case DATA_ADDR_T4:
+ proto_tree_add_ether (hdr_tree, hf_addr_ra, tvb, 4, 6,
+ tvb_get_ptr (tvb, 4, 6));
+ proto_tree_add_ether (hdr_tree, hf_addr_ta, tvb, 10, 6,
+ tvb_get_ptr (tvb, 10, 6));
+ proto_tree_add_ether (hdr_tree, hf_addr_da, tvb, 16, 6, dst);
+ proto_tree_add_uint (hdr_tree, hf_frag_number, tvb, 22, 2,
+ frag_number);
+ proto_tree_add_uint (hdr_tree, hf_seq_number, tvb, 22, 2,
+ seq_number);
+ proto_tree_add_ether (hdr_tree, hf_addr_sa, tvb, 24, 6, src);
+
+ /* add items for wlan.addr filter */
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 16, 6, dst);
+ proto_tree_add_ether_hidden(hdr_tree, hf_addr, tvb, 24, 6, src);
+ break;
+ }
+
+ }
+ break;
+ }
+
+ len = tvb_length_remaining(tvb, hdr_len);
+ reported_len = tvb_reported_length_remaining(tvb, hdr_len);
+
+ switch (fcs_len)
+ {
+ case 0: /* Definitely has no FCS */
+ has_fcs = FALSE;
+ break;
+
+ case 4: /* Definitely has an FCS */
+ has_fcs = TRUE;
+ break;
+
+ default: /* Don't know - use "wlan_check_fcs" */
+ has_fcs = wlan_check_fcs;
+ break;
+ }
+ if (has_fcs)
+ {
+ /*
+ * Well, this packet should, in theory, have an FCS.
+ * Do we have the entire packet, and does it have enough data for
+ * the FCS?
+ */
+ if (reported_len < 4)
+ {
+ /*
+ * The packet is claimed not to even have enough data for a 4-byte
+ * FCS.
+ * Pretend it doesn't have an FCS.
+ */
+ ;
+ }
+ else if (len < reported_len)
+ {
+ /*
+ * The packet is claimed to have enough data for a 4-byte FCS, but
+ * we didn't capture all of the packet.
+ * Slice off the 4-byte FCS from the reported length, and trim the
+ * captured length so it's no more than the reported length; that
+ * will slice off what of the FCS, if any, is in the captured
+ * length.
+ */
+ reported_len -= 4;
+ if (len > reported_len)
+ len = reported_len;
+ }
+ else
+ {
+ /*
+ * We have the entire packet, and it includes a 4-byte FCS.
+ * Slice it off, and put it into the tree.
+ */
+ len -= 4;
+ reported_len -= 4;
+ if (tree)
+ {
+ guint32 fcs = crc32_802_tvb(tvb, hdr_len + len);
+ guint32 sent_fcs = tvb_get_ntohl(tvb, hdr_len + len);
+ if (fcs == sent_fcs)
+ proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
+ hdr_len + len, 4, sent_fcs,
+ "Frame check sequence: 0x%08x (correct)", sent_fcs);
+ else
+ proto_tree_add_uint_format(hdr_tree, hf_fcs, tvb,
+ hdr_len + len, 4, sent_fcs,
+ "Frame check sequence: 0x%08x (incorrect, should be 0x%08x)",
+ sent_fcs, fcs);
+ }
+ }
+ }
+
+ if (tree && (frame_type_subtype == DATA_QOS_DATA || frame_type_subtype == DATA_QOS_NULL)) {
+ proto_item *qos_fields;
+ proto_tree *qos_tree;
+
+ guint16 qos_control, qos_priority, qos_ack_policy;
+
+ qos_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len - 2, 2,
+ "QoS parameters");
+ qos_tree = proto_item_add_subtree (qos_fields, ett_qos_parameters);
+
+ qos_control = tvb_get_letohs(tvb, hdr_len - 2);
+ qos_priority = COOK_QOS_PRIORITY(qos_control);
+ qos_ack_policy = COOK_QOS_ACK_POLICY(qos_control);
+ proto_tree_add_uint_format (qos_tree, hf_qos_priority, tvb,
+ hdr_len - 2, 2, qos_priority,
+ "Priority: %d (%s) (%s)",
+ qos_priority, qos_tags[qos_priority], qos_acs[qos_priority]);
+ proto_tree_add_uint_format (qos_tree, hf_qos_ack_policy, tvb,
+ hdr_len - 2, 2, qos_ack_policy,
+ "Ack Policy: %d (%sAcknowledge)",
+ qos_ack_policy, qos_ack_policy ? "Do not " : "");
+ }
+
+ /*
+ * Only management and data frames have a body, so we don't have
+ * anything more to do for other types of frames.
+ */
+ switch (COOK_FRAME_TYPE (fcf))
+ {
+
+ case MGT_FRAME:
+ break;
+
+ case DATA_FRAME:
+ /*
+ * No-data frames don't have a body.
+ */
+ switch (frame_type_subtype)
+ {
+
+ case DATA_NULL_FUNCTION:
+ case DATA_CF_ACK_NOD:
+ case DATA_CF_POLL_NOD:
+ case DATA_CF_ACK_POLL_NOD:
+ case DATA_QOS_NULL:
+ return;
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ if (IS_WEP(COOK_FLAGS(fcf))) {
+ /*
+ * It's a WEP-encrypted frame; dissect the WEP parameters and decrypt
+ * the data, if we have a matching key. Otherwise display it as data.
+ */
+ gboolean can_decrypt = FALSE;
+ proto_tree *wep_tree = NULL;
+ guint32 iv;
+ guint8 key, keybyte;
+
+ keybyte = tvb_get_guint8(tvb, hdr_len + 3);
+ key = COOK_WEP_KEY(keybyte);
+ if ((keybyte & KEY_EXTIV) && (len >= EXTIV_LEN)) {
+ /* Extended IV; this frame is likely encrypted with TKIP or CCMP */
+ if (tree) {
+ proto_item *extiv_fields;
+
+ extiv_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 8,
+ "TKIP/CCMP parameters");
+ wep_tree = proto_item_add_subtree (extiv_fields, ett_wep_parameters);
+ /* It is unknown whether this is a TKIP or CCMP encrypted packet, so
+ * display both packet number alternatives unless the ExtIV can be
+ * determined to be possible only with one of the encryption protocols.
+ */
+ if (tvb_get_guint8(tvb, hdr_len + 1) & 0x20) {
+ snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
+ tvb_get_letohl(tvb, hdr_len + 4),
+ tvb_get_guint8(tvb, hdr_len),
+ tvb_get_guint8(tvb, hdr_len + 2));
+ proto_tree_add_string(wep_tree, hf_tkip_extiv, tvb, hdr_len,
+ EXTIV_LEN, out_buff);
+ }
+ if (tvb_get_guint8(tvb, hdr_len + 2) == 0) {
+ snprintf(out_buff, SHORT_STR, "0x%08X%02X%02X",
+ tvb_get_letohl(tvb, hdr_len + 4),
+ tvb_get_guint8(tvb, hdr_len + 1),
+ tvb_get_guint8(tvb, hdr_len));
+ proto_tree_add_string(wep_tree, hf_ccmp_extiv, tvb, hdr_len,
+ EXTIV_LEN, out_buff);
+ }
+ proto_tree_add_uint(wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
+ }
+
+ /* Subtract out the length of the IV. */
+ len -= EXTIV_LEN;
+ reported_len -= EXTIV_LEN;
+ ivlen = EXTIV_LEN;
+ /* It is unknown whether this is TKIP or CCMP, so let's not even try to
+ * parse TKIP Michael MIC+ICV or CCMP MIC. */
+ } else {
+ /* No Ext. IV - WEP packet */
+ /*
+ * XXX - pass the IV and key to "try_decrypt_wep()", and have it pass
+ * them to "wep_decrypt()", rather than having "wep_decrypt()" extract
+ * them itself.
+ *
+ * Also, just pass the data *following* the WEP parameters as the
+ * buffer to decrypt.
+ */
+ iv = tvb_get_letoh24(tvb, hdr_len);
+ if (tree) {
+ proto_item *wep_fields;
+
+ wep_fields = proto_tree_add_text(hdr_tree, tvb, hdr_len, 4,
+ "WEP parameters");
+
+ wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
+ proto_tree_add_uint (wep_tree, hf_wep_iv, tvb, hdr_len, 3, iv);
+ }
+ if (tree)
+ proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len + 3, 1, key);
+
+ /* Subtract out the length of the IV. */
+ len -= 4;
+ reported_len -= 4;
+ ivlen = 4;
+
+ /*
+ * Well, this packet should, in theory, have an ICV.
+ * Do we have the entire packet, and does it have enough data for
+ * the ICV?
+ */
+ if (reported_len < 4) {
+ /*
+ * The packet is claimed not to even have enough data for a
+ * 4-byte ICV.
+ * Pretend it doesn't have an ICV.
+ */
+ ;
+ } else if (len < reported_len) {
+ /*
+ * The packet is claimed to have enough data for a 4-byte ICV,
+ * but we didn't capture all of the packet.
+ * Slice off the 4-byte ICV from the reported length, and trim
+ * the captured length so it's no more than the reported length;
+ * that will slice off what of the ICV, if any, is in the
+ * captured length.
+ *
+ */
+ reported_len -= 4;
+ if (len > reported_len)
+ len = reported_len;
+ } else {
+ /*
+ * We have the entire packet, and it includes a 4-byte ICV.
+ * Slice it off, and put it into the tree.
+ *
+ * We only support decrypting if we have the the ICV.
+ *
+ * XXX - the ICV is encrypted; we're putting the encrypted
+ * value, not the decrypted value, into the tree.
+ */
+ len -= 4;
+ reported_len -= 4;
+ can_decrypt = TRUE;
+ }
+ }
+
+ if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len + 8)) == NULL) {
+ /*
+ * WEP decode impossible or failed, treat payload as raw data
+ * and don't attempt fragment reassembly or further dissection.
+ */
+ next_tvb = tvb_new_subset(tvb, hdr_len + ivlen, len, reported_len);
+
+ if (tree && can_decrypt)
+ proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
+ hdr_len + ivlen + len, 4,
+ tvb_get_ntohl(tvb, hdr_len + ivlen + len),
+ "WEP ICV: 0x%08x (not verified)",
+ tvb_get_ntohl(tvb, hdr_len + ivlen + len));
+
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ return;
+ } else {
+
+ if (tree)
+ proto_tree_add_uint_format (wep_tree, hf_wep_icv, tvb,
+ hdr_len + ivlen + len, 4,
+ tvb_get_ntohl(tvb, hdr_len + ivlen + len),
+ "WEP ICV: 0x%08x (correct)",
+ tvb_get_ntohl(tvb, hdr_len + ivlen + len));
+
+ add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
+ }
+
+ /*
+ * WEP decryption successful!
+ *
+ * Use the tvbuff we got back from the decryption; the data starts at
+ * the beginning. The lengths are already correct for the decoded WEP
+ * payload.
+ */
+ hdr_len = 0;
+
+ } else {
+ /*
+ * Not a WEP-encrypted frame; just use the data from the tvbuff
+ * handed to us.
+ *
+ * The payload starts at "hdr_len" (i.e., just past the 802.11
+ * MAC header), the length of data in the tvbuff following the
+ * 802.11 header is "len", and the length of data in the packet
+ * following the 802.11 header is "reported_len".
+ */
+ next_tvb = tvb;
+ }
+
+ /*
+ * Do defragmentation if "wlan_defragment" is true, and we have more
+ * fragments or this isn't the first fragment.
+ *
+ * We have to do some special handling to catch frames that
+ * have the "More Fragments" indicator not set but that
+ * don't show up as reassembled and don't have any other
+ * fragments present. Some networking interfaces appear
+ * to do reassembly even when you're capturing raw packets
+ * *and* show the reassembled packet without the "More
+ * Fragments" indicator set *but* with a non-zero fragment
+ * number.
+ *
+ * "fragment_add_seq_802_11()" handles that; we want to call it
+ * even if we have a short frame, so that it does those checks - if
+ * the frame is short, it doesn't do reassembly on it.
+ *
+ * (This could get some false positives if we really *did* only
+ * capture the last fragment of a fragmented packet, but that's
+ * life.)
+ */
+ save_fragmented = pinfo->fragmented;
+ if (wlan_defragment && (more_frags || frag_number != 0)) {
+ fragment_data *fd_head;
+
+ /*
+ * If we've already seen this frame, look it up in the
+ * table of reassembled packets, otherwise add it to
+ * whatever reassembly is in progress, if any, and see
+ * if it's done.
+ */
+ fd_head = fragment_add_seq_802_11(next_tvb, hdr_len, pinfo, seq_number,
+ wlan_fragment_table,
+ wlan_reassembled_table,
+ frag_number,
+ reported_len,
+ more_frags);
+ next_tvb = process_reassembled_data(tvb, hdr_len, pinfo,
+ "Reassembled 802.11", fd_head,
+ &frag_items, NULL, hdr_tree);
+ } else {
+ /*
+ * If this is the first fragment, dissect its contents, otherwise
+ * just show it as a fragment.
+ */
+ if (frag_number != 0) {
+ /* Not the first fragment - don't dissect it. */
+ next_tvb = NULL;
+ } else {
+ /* First fragment, or not fragmented. Dissect what we have here. */
+
+ /* Get a tvbuff for the payload. */
+ next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
+
+ /*
+ * If this is the first fragment, but not the only fragment,
+ * tell the next protocol that.
+ */
+ if (more_frags)
+ pinfo->fragmented = TRUE;
+ else
+ pinfo->fragmented = FALSE;
+ }
+ }
+
+ if (next_tvb == NULL) {
+ /* Just show this as an incomplete fragment. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Fragmented IEEE 802.11 frame");
+ next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ pinfo->fragmented = save_fragmented;
+ return;
+ }
+
+ switch (COOK_FRAME_TYPE (fcf))
+ {
+
+ case MGT_FRAME:
+ dissect_ieee80211_mgt (fcf, next_tvb, pinfo, tree);
+ break;
+
+
+ case DATA_FRAME:
+ /* I guess some bridges take Netware Ethernet_802_3 frames,
+ which are 802.3 frames (with a length field rather than
+ a type field, but with no 802.2 header in the payload),
+ and just stick the payload into an 802.11 frame. I've seen
+ captures that show frames of that sort.
+
+ We also handle some odd form of encapsulation in which a
+ complete Ethernet frame is encapsulated within an 802.11
+ data frame, with no 802.2 header. This has been seen
+ from some hardware.
+
+ So, if the packet doesn't start with 0xaa 0xaa:
+
+ we first use the same scheme that linux-wlan-ng does to detect
+ those encapsulated Ethernet frames, namely looking to see whether
+ the frame either starts with 6 octets that match the destination
+ address from the 802.11 header or has 6 octets that match the
+ source address from the 802.11 header following the first 6 octets,
+ and, if so, treat it as an encapsulated Ethernet frame;
+
+ otherwise, we use the same scheme that we use in the Ethernet
+ dissector to recognize Netware 802.3 frames, namely checking
+ whether the packet starts with 0xff 0xff and, if so, treat it
+ as an encapsulated IPX frame. */
+ encap_type = ENCAP_802_2;
+ TRY {
+ octet1 = tvb_get_guint8(next_tvb, 0);
+ octet2 = tvb_get_guint8(next_tvb, 1);
+ if (octet1 != 0xaa || octet2 != 0xaa) {
+ src = tvb_get_ptr (next_tvb, 6, 6);
+ dst = tvb_get_ptr (next_tvb, 0, 6);
+ if (memcmp(src, pinfo->dl_src.data, 6) == 0 ||
+ memcmp(dst, pinfo->dl_dst.data, 6) == 0)
+ encap_type = ENCAP_ETHERNET;
+ else if (octet1 == 0xff && octet2 == 0xff)
+ encap_type = ENCAP_IPX;
+ }
+ }
+ CATCH2(BoundsError, ReportedBoundsError) {
+ ; /* do nothing */
+
+ }
+ ENDTRY;
+
+ switch (encap_type) {
+
+ case ENCAP_802_2:
+ call_dissector(llc_handle, next_tvb, pinfo, tree);
+ break;
+
+ case ENCAP_ETHERNET:
+ call_dissector(eth_handle, next_tvb, pinfo, tree);
+ break;
+
+ case ENCAP_IPX:
+ call_dissector(ipx_handle, next_tvb, pinfo, tree);
+ break;
+ }
+ break;
+ }
+ pinfo->fragmented = save_fragmented;
+}
+
+/*
+ * Dissect 802.11 with a variable-length link-layer header.
+ */
+static void
+dissect_ieee80211 (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE,
+ pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
+}
+
+/*
+ * Dissect 802.11 with a variable-length link-layer header and a pseudo-
+ * header containing radio information.
+ */
+static void
+dissect_ieee80211_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, TRUE,
+ pinfo->pseudo_header->ieee_802_11.fcs_len, FALSE);
+}
+
+/*
+ * Dissect 802.11 with a variable-length link-layer header and a byte-swapped
+ * control field (some hardware sends out LWAPP-encapsulated 802.11
+ * packets with the control field byte swapped).
+ */
+static void
+dissect_ieee80211_bsfc (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ dissect_ieee80211_common (tvb, pinfo, tree, FALSE, FALSE, FALSE, TRUE);
+}
+
+/*
+ * Dissect 802.11 with a fixed-length link-layer header (padded to the
+ * maximum length).
+ */
+static void
+dissect_ieee80211_fixed (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ dissect_ieee80211_common (tvb, pinfo, tree, TRUE, FALSE, FALSE, FALSE);
+}
+
+static void
+wlan_defragment_init(void)
+{
+ fragment_table_init(&wlan_fragment_table);
+ reassembled_table_init(&wlan_reassembled_table);
+}
+
+void
+proto_register_ieee80211 (void)
+{
+ static const value_string frame_type[] = {
+ {MGT_FRAME, "Management frame"},
+ {CONTROL_FRAME, "Control frame"},
+ {DATA_FRAME, "Data frame"},
+ {0, NULL}
+ };
+
+ static const value_string tofrom_ds[] = {
+ {0, "Not leaving DS or network is operating in AD-HOC mode (To DS: 0 From DS: 0)"},
+ {FLAG_TO_DS, "Frame is entering DS (To DS: 1 From DS: 0)"},
+ {FLAG_FROM_DS, "Frame is exiting DS (To DS: 0 From DS: 1)"},
+ {FLAG_TO_DS|FLAG_FROM_DS, "Frame part of WDS (To DS: 1 From DS: 1)"},
+ {0, NULL}
+ };
+
+ static const true_false_string tods_flag = {
+ "Frame is entering DS",
+ "Frame is not entering DS"
+ };
+
+ static const true_false_string fromds_flag = {
+ "Frame is exiting DS",
+ "Frame is not exiting DS"
+ };
+
+ static const true_false_string more_frags = {
+ "More fragments follow",
+ "This is the last fragment"
+ };
+
+ static const true_false_string retry_flags = {
+ "Frame is being retransmitted",
+ "Frame is not being retransmitted"
+ };
+
+ static const true_false_string pm_flags = {
+ "STA will go to sleep",
+ "STA will stay up"
+ };
+
+ static const true_false_string md_flags = {
+ "Data is buffered for STA at AP",
+ "No data buffered"
+ };
+
+ static const true_false_string wep_flags = {
+ "WEP is enabled",
+ "WEP is disabled"
+ };
+
+ static const true_false_string order_flags = {
+ "Strictly ordered",
+ "Not strictly ordered"
+ };
+
+ static const true_false_string cf_ess_flags = {
+ "Transmitter is an AP",
+ "Transmitter is a STA"
+ };
+
+
+ static const true_false_string cf_privacy_flags = {
+ "AP/STA can support WEP",
+ "AP/STA cannot support WEP"
+ };
+
+ static const true_false_string cf_preamble_flags = {
+ "Short preamble allowed",
+ "Short preamble not allowed"
+ };
+
+ static const true_false_string cf_pbcc_flags = {
+ "PBCC modulation allowed",
+ "PBCC modulation not allowed"
+ };
+
+ static const true_false_string cf_agility_flags = {
+ "Channel agility in use",
+ "Channel agility not in use"
+ };
+
+ static const true_false_string short_slot_time_flags = {
+ "Short slot time in use",
+ "Short slot time not in use"
+ };
+
+ static const true_false_string dsss_ofdm_flags = {
+ "DSSS-OFDM modulation allowed",
+ "DSSS-OFDM modulation not allowed"
+ };
+
+
+ static const true_false_string cf_ibss_flags = {
+ "Transmitter belongs to an IBSS",
+ "Transmitter belongs to a BSS"
+ };
+
+ static const value_string sta_cf_pollable[] = {
+ {0x00, "Station is not CF-Pollable"},
+ {0x02, "Station is CF-Pollable, "
+ "not requesting to be placed on the CF-polling list"},
+ {0x01, "Station is CF-Pollable, "
+ "requesting to be placed on the CF-polling list"},
+ {0x03, "Station is CF-Pollable, requesting never to be polled"},
+ {0, NULL}
+ };
+
+ static const value_string ap_cf_pollable[] = {
+ {0x00, "No point coordinator at AP"},
+ {0x02, "Point coordinator at AP for delivery only (no polling)"},
+ {0x01, "Point coordinator at AP for delivery and polling"},
+ {0x03, "Reserved"},
+ {0, NULL}
+ };
+
+
+ static const value_string auth_alg[] = {
+ {0x00, "Open System"},
+ {0x01, "Shared key"},
+ {0, NULL}
+ };
+
+ static const value_string reason_codes[] = {
+ {0x00, "Reserved"},
+ {0x01, "Unspecified reason"},
+ {0x02, "Previous authentication no longer valid"},
+ {0x03, "Deauthenticated because sending STA is leaving (has left) "
+ "IBSS or ESS"},
+ {0x04, "Disassociated due to inactivity"},
+ {0x05, "Disassociated because AP is unable to handle all currently "
+ "associated stations"},
+ {0x06, "Class 2 frame received from nonauthenticated station"},
+ {0x07, "Class 3 frame received from nonassociated station"},
+ {0x08, "Disassociated because sending STA is leaving (has left) BSS"},
+ {0x09, "Station requesting (re)association is not authenticated with "
+ "responding station"},
+ {0x0D, "Invalid Information Element"},
+ {0x0E, "Michael MIC failure"},
+ {0x0F, "4-Way Handshake timeout"},
+ {0x10, "Group key update timeout"},
+ {0x11, "Information element in 4-Way Handshake different from "
+ "(Re)Association Request/Probe Response/Beacon"},
+ {0x12, "Group Cipher is not valid"},
+ {0x13, "Pairwise Cipher is not valid"},
+ {0x14, "AKMP is not valid"},
+ {0x15, "Unsupported RSN IE version"},
+ {0x16, "Invalid RSN IE Capabilities"},
+ {0x17, "IEEE 802.1X Authentication failed"},
+ {0x18, "Cipher suite is rejected per security policy"},
+ {0x00, NULL}
+ };
+
+
+ static const value_string status_codes[] = {
+ {0x00, "Successful"},
+ {0x01, "Unspecified failure"},
+ {0x0A, "Cannot support all requested capabilities in the "
+ "Capability information field"},
+ {0x0B, "Reassociation denied due to inability to confirm that "
+ "association exists"},
+ {0x0C, "Association denied due to reason outside the scope of this "
+ "standard"},
+
+ {0x0D, "Responding station does not support the specified authentication "
+ "algorithm"},
+ {0x0E, "Received an Authentication frame with authentication sequence "
+ "transaction sequence number out of expected sequence"},
+ {0x0F, "Authentication rejected because of challenge failure"},
+ {0x10, "Authentication rejected due to timeout waiting for next "
+ "frame in sequence"},
+ {0x11, "Association denied because AP is unable to handle additional "
+ "associated stations"},
+ {0x12, "Association denied due to requesting station not supporting all "
+ "of the datarates in the BSSBasicServiceSet Parameter"},
+ {0x13, "Association denied due to requesting station not supporting "
+ "short preamble operation"},
+ {0x14, "Association denied due to requesting station not supporting "
+ "PBCC encoding"},
+ {0x15, "Association denied due to requesting station not supporting "
+ "channel agility"},
+ {0x19, "Association denied due to requesting station not supporting "
+ "short slot operation"},
+ {0x1A, "Association denied due to requesting station not supporting "
+ "DSSS-OFDM operation"},
+ {0x28, "Invalid Information Element"},
+ {0x29, "Group Cipher is not valid"},
+ {0x2A, "Pairwise Cipher is not valid"},
+ {0x2B, "AKMP is not valid"},
+ {0x2C, "Unsupported RSN IE version"},
+ {0x2D, "Invalid RSN IE Capabilities"},
+ {0x2E, "Cipher suite is rejected per security policy"},
+ {0x00, NULL}
+ };
+
+ static const value_string category_codes[] = {
+ {0x11, "Management notification frame"},
+ {0x00, NULL}
+ };
+
+ static const value_string action_codes[] = {
+ {0x00, NULL}
+ };
+
+ static const value_string wme_action_codes[] = {
+ {0x00, "Setup request"},
+ {0x01, "Setup response"},
+ {0x02, "Teardown"},
+ {0x00, NULL}
+ };
+
+ static const value_string wme_status_codes[] = {
+ {0x00, "Admission accepted"},
+ {0x01, "Invalid parameters"},
+ {0x03, "Refused"},
+ {0x00, NULL}
+ };
+
+ static hf_register_info hf[] = {
+ {&hf_data_rate,
+ {"Data Rate", "wlan.data_rate", FT_UINT8, BASE_DEC, NULL, 0,
+ "Data rate (.5 Mb/s units)", HFILL }},
+
+ {&hf_channel,
+ {"Channel", "wlan.channel", FT_UINT8, BASE_DEC, NULL, 0,
+ "Radio channel", HFILL }},
+
+ {&hf_signal_strength,
+ {"Signal Strength", "wlan.signal_strength", FT_UINT8, BASE_DEC, NULL, 0,
+ "Signal strength (percentage)", HFILL }},
+
+ {&hf_fc_field,
+ {"Frame Control Field", "wlan.fc", FT_UINT16, BASE_HEX, NULL, 0,
+ "MAC Frame control", HFILL }},
+
+ {&hf_fc_proto_version,
+ {"Version", "wlan.fc.version", FT_UINT8, BASE_DEC, NULL, 0,
+ "MAC Protocol version", HFILL }}, /* 0 */
+
+ {&hf_fc_frame_type,
+ {"Type", "wlan.fc.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0,
+ "Frame type", HFILL }},
+
+ {&hf_fc_frame_subtype,
+ {"Subtype", "wlan.fc.subtype", FT_UINT8, BASE_DEC, NULL, 0,
+ "Frame subtype", HFILL }}, /* 2 */
+
+ {&hf_fc_frame_type_subtype,
+ {"Type/Subtype", "wlan.fc.type_subtype", FT_UINT16, BASE_DEC, VALS(frame_type_subtype_vals), 0,
+ "Type and subtype combined", HFILL }},
+
+ {&hf_fc_flags,
+ {"Protocol Flags", "wlan.flags", FT_UINT8, BASE_HEX, NULL, 0,
+ "Protocol flags", HFILL }},
+
+ {&hf_fc_data_ds,
+ {"DS status", "wlan.fc.ds", FT_UINT8, BASE_HEX, VALS (&tofrom_ds), 0,
+ "Data-frame DS-traversal status", HFILL }}, /* 3 */
+
+ {&hf_fc_to_ds,
+ {"To DS", "wlan.fc.tods", FT_BOOLEAN, 8, TFS (&tods_flag), FLAG_TO_DS,
+ "To DS flag", HFILL }}, /* 4 */
+
+ {&hf_fc_from_ds,
+ {"From DS", "wlan.fc.fromds", FT_BOOLEAN, 8, TFS (&fromds_flag), FLAG_FROM_DS,
+ "From DS flag", HFILL }}, /* 5 */
+
+ {&hf_fc_more_frag,
+ {"More Fragments", "wlan.fc.frag", FT_BOOLEAN, 8, TFS (&more_frags), FLAG_MORE_FRAGMENTS,
+ "More Fragments flag", HFILL }}, /* 6 */
+
+ {&hf_fc_retry,
+ {"Retry", "wlan.fc.retry", FT_BOOLEAN, 8, TFS (&retry_flags), FLAG_RETRY,
+ "Retransmission flag", HFILL }},
+
+ {&hf_fc_pwr_mgt,
+ {"PWR MGT", "wlan.fc.pwrmgt", FT_BOOLEAN, 8, TFS (&pm_flags), FLAG_POWER_MGT,
+ "Power management status", HFILL }},
+
+ {&hf_fc_more_data,
+ {"More Data", "wlan.fc.moredata", FT_BOOLEAN, 8, TFS (&md_flags), FLAG_MORE_DATA,
+ "More data flag", HFILL }},
+
+ {&hf_fc_wep,
+ {"WEP flag", "wlan.fc.wep", FT_BOOLEAN, 8, TFS (&wep_flags), FLAG_WEP,
+ "WEP flag", HFILL }},
+
+ {&hf_fc_order,
+ {"Order flag", "wlan.fc.order", FT_BOOLEAN, 8, TFS (&order_flags), FLAG_ORDER,
+ "Strictly ordered flag", HFILL }},
+
+ {&hf_assoc_id,
+ {"Association ID","wlan.aid",FT_UINT16, BASE_DEC,NULL,0,
+ "Association-ID field", HFILL }},
+
+ {&hf_did_duration,
+ {"Duration", "wlan.duration", FT_UINT16, BASE_DEC, NULL, 0,
+ "Duration field", HFILL }},
+
+ {&hf_addr_da,
+ {"Destination address", "wlan.da", FT_ETHER, BASE_NONE, NULL, 0,
+ "Destination Hardware Address", HFILL }},
+
+ {&hf_addr_sa,
+ {"Source address", "wlan.sa", FT_ETHER, BASE_NONE, NULL, 0,
+ "Source Hardware Address", HFILL }},
+
+ { &hf_addr,
+ {"Source or Destination address", "wlan.addr", FT_ETHER, BASE_NONE, NULL, 0,
+ "Source or Destination Hardware Address", HFILL }},
+
+ {&hf_addr_ra,
+ {"Receiver address", "wlan.ra", FT_ETHER, BASE_NONE, NULL, 0,
+ "Receiving Station Hardware Address", HFILL }},
+
+ {&hf_addr_ta,
+ {"Transmitter address", "wlan.ta", FT_ETHER, BASE_NONE, NULL, 0,
+ "Transmitting Station Hardware Address", HFILL }},
+
+ {&hf_addr_bssid,
+ {"BSS Id", "wlan.bssid", FT_ETHER, BASE_NONE, NULL, 0,
+ "Basic Service Set ID", HFILL }},
+
+ {&hf_frag_number,
+ {"Fragment number", "wlan.frag", FT_UINT16, BASE_DEC, NULL, 0,
+ "Fragment number", HFILL }},
+
+ {&hf_seq_number,
+ {"Sequence number", "wlan.seq", FT_UINT16, BASE_DEC, NULL, 0,
+ "Sequence number", HFILL }},
+
+ {&hf_qos_priority,
+ {"Priority", "wlan.qos.priority", FT_UINT16, BASE_DEC, NULL, 0,
+ "802.1D Tag", HFILL }},
+
+ {&hf_qos_ack_policy,
+ {"Ack Policy", "wlan.qos.ack", FT_UINT16, BASE_DEC, NULL, 0,
+ "Ack Policy", HFILL }},
+
+ {&hf_fcs,
+ {"Frame check sequence", "wlan.fcs", FT_UINT32, BASE_HEX,
+ NULL, 0, "FCS", HFILL }},
+
+ {&hf_fragment_overlap,
+ {"Fragment overlap", "wlan.fragment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+
+ {&hf_fragment_overlap_conflict,
+ {"Conflicting data in fragment overlap", "wlan.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+
+ {&hf_fragment_multiple_tails,
+ {"Multiple tail fragments found", "wlan.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+
+ {&hf_fragment_too_long_fragment,
+ {"Fragment too long", "wlan.fragment.toolongfragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+
+ {&hf_fragment_error,
+ {"Defragmentation error", "wlan.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }},
+
+ {&hf_fragment,
+ {"802.11 Fragment", "wlan.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "802.11 Fragment", HFILL }},
+
+ {&hf_fragments,
+ {"802.11 Fragments", "wlan.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
+ "802.11 Fragments", HFILL }},
+
+ {&hf_reassembled_in,
+ {"Reassembled 802.11 in frame", "wlan.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This 802.11 packet is reassembled in this frame", HFILL }},
+
+ {&hf_wep_iv,
+ {"Initialization Vector", "wlan.wep.iv", FT_UINT24, BASE_HEX, NULL, 0,
+ "Initialization Vector", HFILL }},
+
+ {&hf_tkip_extiv,
+ {"TKIP Ext. Initialization Vector", "wlan.tkip.extiv", FT_STRING,
+ BASE_HEX, NULL, 0, "TKIP Extended Initialization Vector", HFILL }},
+
+ {&hf_ccmp_extiv,
+ {"CCMP Ext. Initialization Vector", "wlan.ccmp.extiv", FT_STRING,
+ BASE_HEX, NULL, 0, "CCMP Extended Initialization Vector", HFILL }},
+
+ {&hf_wep_key,
+ {"Key", "wlan.wep.key", FT_UINT8, BASE_DEC, NULL, 0,
+ "Key", HFILL }},
+
+ {&hf_wep_icv,
+ {"WEP ICV", "wlan.wep.icv", FT_UINT32, BASE_HEX, NULL, 0,
+ "WEP ICV", HFILL }},
+ };
+
+ static const true_false_string rsn_preauth_flags = {
+ "Transmitter supports pre-authentication",
+ "Transmitter does not support pre-authentication"
+ };
+
+ static const true_false_string rsn_no_pairwise_flags = {
+ "Transmitter cannot support WEP default key 0 simultaneously with "
+ "Pairwise key",
+ "Transmitter can support WEP default key 0 simultaneously with "
+ "Pairwise key"
+ };
+
+ static const value_string rsn_cap_replay_counter[] = {
+ {0x00, "1 replay counter per PTKSA/GTKSA/STAKeySA"},
+ {0x01, "2 replay counters per PTKSA/GTKSA/STAKeySA"},
+ {0x02, "4 replay counters per PTKSA/GTKSA/STAKeySA"},
+ {0x03, "16 replay counters per PTKSA/GTKSA/STAKeySA"},
+ {0, NULL}
+ };
+
+ static hf_register_info ff[] = {
+ {&ff_timestamp,
+ {"Timestamp", "wlan_mgt.fixed.timestamp", FT_STRING, BASE_NONE,
+ NULL, 0, "", HFILL }},
+
+ {&ff_auth_alg,
+ {"Authentication Algorithm", "wlan_mgt.fixed.auth.alg",
+ FT_UINT16, BASE_DEC, VALS (&auth_alg), 0, "", HFILL }},
+
+ {&ff_beacon_interval,
+ {"Beacon Interval", "wlan_mgt.fixed.beacon", FT_DOUBLE, BASE_DEC, NULL, 0,
+ "", HFILL }},
+
+ {&hf_fixed_parameters,
+ {"Fixed parameters", "wlan_mgt.fixed.all", FT_UINT16, BASE_DEC, NULL, 0,
+ "", HFILL }},
+
+ {&hf_tagged_parameters,
+ {"Tagged parameters", "wlan_mgt.tagged.all", FT_UINT16, BASE_DEC, NULL, 0,
+ "", HFILL }},
+
+ {&ff_capture,
+ {"Capabilities", "wlan_mgt.fixed.capabilities", FT_UINT16, BASE_HEX, NULL, 0,
+ "Capability information", HFILL }},
+
+ {&ff_cf_ess,
+ {"ESS capabilities", "wlan_mgt.fixed.capabilities.ess",
+ FT_BOOLEAN, 16, TFS (&cf_ess_flags), 0x0001, "ESS capabilities", HFILL }},
+
+ {&ff_cf_ibss,
+ {"IBSS status", "wlan_mgt.fixed.capabilities.ibss",
+ FT_BOOLEAN, 16, TFS (&cf_ibss_flags), 0x0002, "IBSS participation", HFILL }},
+
+ {&ff_cf_sta_poll,
+ {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.sta",
+ FT_UINT16, BASE_HEX, VALS (&sta_cf_pollable), 0x000C,
+ "CF-Poll capabilities for a STA", HFILL }},
+
+ {&ff_cf_ap_poll,
+ {"CFP participation capabilities", "wlan_mgt.fixed.capabilities.cfpoll.ap",
+ FT_UINT16, BASE_HEX, VALS (&ap_cf_pollable), 0x000C,
+ "CF-Poll capabilities for an AP", HFILL }},
+
+ {&ff_cf_privacy,
+ {"Privacy", "wlan_mgt.fixed.capabilities.privacy",
+ FT_BOOLEAN, 16, TFS (&cf_privacy_flags), 0x0010, "WEP support", HFILL }},
+
+ {&ff_cf_preamble,
+ {"Short Preamble", "wlan_mgt.fixed.capabilities.preamble",
+ FT_BOOLEAN, 16, TFS (&cf_preamble_flags), 0x0020, "Short Preamble", HFILL }},
+
+ {&ff_cf_pbcc,
+ {"PBCC", "wlan_mgt.fixed.capabilities.pbcc",
+ FT_BOOLEAN, 16, TFS (&cf_pbcc_flags), 0x0040, "PBCC Modulation", HFILL }},
+
+ {&ff_cf_agility,
+ {"Channel Agility", "wlan_mgt.fixed.capabilities.agility",
+ FT_BOOLEAN, 16, TFS (&cf_agility_flags), 0x0080, "Channel Agility", HFILL }},
+
+ {&ff_short_slot_time,
+ {"Short Slot Time", "wlan_mgt.fixed.capabilities.short_slot_time",
+ FT_BOOLEAN, 16, TFS (&short_slot_time_flags), 0x0400, "Short Slot Time",
+ HFILL }},
+
+ {&ff_dsss_ofdm,
+ {"DSSS-OFDM", "wlan_mgt.fixed.capabilities.dsss_ofdm",
+ FT_BOOLEAN, 16, TFS (&dsss_ofdm_flags), 0x2000, "DSSS-OFDM Modulation",
+ HFILL }},
+
+ {&ff_auth_seq,
+ {"Authentication SEQ", "wlan_mgt.fixed.auth_seq",
+ FT_UINT16, BASE_HEX, NULL, 0, "Authentication sequence number", HFILL }},
+
+ {&ff_assoc_id,
+ {"Association ID", "wlan_mgt.fixed.aid",
+ FT_UINT16, BASE_HEX, NULL, 0, "Association ID", HFILL }},
+
+ {&ff_listen_ival,
+ {"Listen Interval", "wlan_mgt.fixed.listen_ival",
+ FT_UINT16, BASE_HEX, NULL, 0, "Listen Interval", HFILL }},
+
+ {&ff_current_ap,
+ {"Current AP", "wlan_mgt.fixed.current_ap",
+ FT_ETHER, BASE_NONE, NULL, 0, "MAC address of current AP", HFILL }},
+
+ {&ff_reason,
+ {"Reason code", "wlan_mgt.fixed.reason_code",
+ FT_UINT16, BASE_HEX, VALS (&reason_codes), 0,
+ "Reason for unsolicited notification", HFILL }},
+
+ {&ff_status_code,
+ {"Status code", "wlan_mgt.fixed.status_code",
+ FT_UINT16, BASE_HEX, VALS (&status_codes), 0,
+ "Status of requested event", HFILL }},
+
+ {&ff_category_code,
+ {"Category code", "wlan_mgt.fixed.category_code",
+ FT_UINT16, BASE_HEX, VALS (&category_codes), 0,
+ "Management action category", HFILL }},
+
+ {&ff_action_code,
+ {"Action code", "wlan_mgt.fixed.action_code",
+ FT_UINT16, BASE_HEX, VALS (&action_codes), 0,
+ "Management action code", HFILL }},
+
+ {&ff_dialog_token,
+ {"Dialog token", "wlan_mgt.fixed.dialog_token",
+ FT_UINT16, BASE_HEX, NULL, 0, "Management action dialog token", HFILL }},
+
+ {&ff_wme_action_code,
+ {"Action code", "wlan_mgt.fixed.action_code",
+ FT_UINT16, BASE_HEX, VALS (&wme_action_codes), 0,
+ "Management notification action code", HFILL }},
+
+ {&ff_wme_status_code,
+ {"Status code", "wlan_mgt.fixed.status_code",
+ FT_UINT16, BASE_HEX, VALS (&wme_status_codes), 0,
+ "Management notification setup response status code", HFILL }},
+
+ {&tag_number,
+ {"Tag", "wlan_mgt.tag.number",
+ FT_UINT8, BASE_DEC, VALS(tag_num_vals), 0,
+ "Element ID", HFILL }},
+
+ {&tag_length,
+ {"Tag length", "wlan_mgt.tag.length",
+ FT_UINT8, BASE_DEC, NULL, 0, "Length of tag", HFILL }},
+
+ {&tag_interpretation,
+ {"Tag interpretation", "wlan_mgt.tag.interpretation",
+ FT_STRING, BASE_NONE, NULL, 0, "Interpretation of tag", HFILL }},
+
+ {&rsn_cap,
+ {"RSN Capabilities", "wlan_mgt.rsn.capabilities", FT_UINT16, BASE_HEX,
+ NULL, 0, "RSN Capability information", HFILL }},
+
+ {&rsn_cap_preauth,
+ {"RSN Pre-Auth capabilities", "wlan_mgt.rsn.capabilities.preauth",
+ FT_BOOLEAN, 16, TFS (&rsn_preauth_flags), 0x0001,
+ "RSN Pre-Auth capabilities", HFILL }},
+
+ {&rsn_cap_no_pairwise,
+ {"RSN No Pairwise capabilities", "wlan_mgt.rsn.capabilities.no_pairwise",
+ FT_BOOLEAN, 16, TFS (&rsn_no_pairwise_flags), 0x0002,
+ "RSN No Pairwise capabilities", HFILL }},
+
+ {&rsn_cap_ptksa_replay_counter,
+ {"RSN PTKSA Replay Counter capabilities",
+ "wlan_mgt.rsn.capabilities.ptksa_replay_counter",
+ FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x000C,
+ "RSN PTKSA Replay Counter capabilities", HFILL }},
+
+ {&rsn_cap_gtksa_replay_counter,
+ {"RSN GTKSA Replay Counter capabilities",
+ "wlan_mgt.rsn.capabilities.gtksa_replay_counter",
+ FT_UINT16, BASE_HEX, VALS (&rsn_cap_replay_counter), 0x0030,
+ "RSN GTKSA Replay Counter capabilities", HFILL }},
+ };
+
+ static gint *tree_array[] = {
+ &ett_80211,
+ &ett_fc_tree,
+ &ett_proto_flags,
+ &ett_fragments,
+ &ett_fragment,
+ &ett_80211_mgt,
+ &ett_fixed_parameters,
+ &ett_tagged_parameters,
+ &ett_qos_parameters,
+ &ett_wep_parameters,
+ &ett_cap_tree,
+ &ett_rsn_cap_tree,
+ };
+ module_t *wlan_module;
+
+ static const enum_val_t wep_keys_options[] = {
+ {"0", "0", 0},
+ {"1", "1", 1},
+ {"2", "2", 2},
+ {"3", "3", 3},
+ {"4", "4", 4},
+ {NULL, NULL, -1},
+ };
+
+
+ proto_wlan = proto_register_protocol ("IEEE 802.11 wireless LAN",
+ "IEEE 802.11", "wlan");
+ proto_register_field_array (proto_wlan, hf, array_length (hf));
+ proto_wlan_mgt = proto_register_protocol ("IEEE 802.11 wireless LAN management frame",
+ "802.11 MGT", "wlan_mgt");
+ proto_register_field_array (proto_wlan_mgt, ff, array_length (ff));
+ proto_register_subtree_array (tree_array, array_length (tree_array));
+
+ register_dissector("wlan", dissect_ieee80211, proto_wlan);
+ register_dissector("wlan_fixed", dissect_ieee80211_fixed, proto_wlan);
+ register_dissector("wlan_bsfc", dissect_ieee80211_bsfc, proto_wlan);
+ register_init_routine(wlan_defragment_init);
+
+ /* Register configuration options */
+ wlan_module = prefs_register_protocol(proto_wlan, init_wepkeys);
+ prefs_register_bool_preference(wlan_module, "defragment",
+ "Reassemble fragmented 802.11 datagrams",
+ "Whether fragmented 802.11 datagrams should be reassembled",
+ &wlan_defragment);
+
+ prefs_register_bool_preference(wlan_module, "check_fcs",
+ "Assume packets have FCS",
+ "Some 802.11 cards include the FCS at the end of a packet, others do not.",
+ &wlan_check_fcs);
+
+ prefs_register_bool_preference(wlan_module, "ignore_wep",
+ "Ignore the WEP bit",
+ "Some 802.11 cards leave the WEP bit set even though the packet is decrypted.",
+ &wlan_ignore_wep);
+
+#ifndef USE_ENV
+ prefs_register_enum_preference(wlan_module, "wep_keys",
+ "WEP key count",
+ "How many WEP keys do we have to choose from? (0 to disable, up to 4)",
+ &num_wepkeys, wep_keys_options, FALSE);
+
+ prefs_register_string_preference(wlan_module, "wep_key1",
+ "WEP key #1",
+ "First WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
+ &wep_keystr[0]);
+ prefs_register_string_preference(wlan_module, "wep_key2",
+ "WEP key #2",
+ "Second WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
+ &wep_keystr[1]);
+ prefs_register_string_preference(wlan_module, "wep_key3",
+ "WEP key #3",
+ "Third WEP key (A:B:C:D:E) [40bit], (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
+ &wep_keystr[2]);
+ prefs_register_string_preference(wlan_module, "wep_key4",
+ "WEP key #4",
+ "Fourth WEP key (A:B:C:D:E) [40bit] (A:B:C:D:E:F:G:H:I:J:K:L:M) [104bit], or whatever key length you're using",
+ &wep_keystr[3]);
+#endif
+}
+
+void
+proto_reg_handoff_ieee80211(void)
+{
+ dissector_handle_t ieee80211_handle;
+ dissector_handle_t ieee80211_radio_handle;
+
+ /*
+ * Get handles for the LLC, IPX and Ethernet dissectors.
+ */
+ llc_handle = find_dissector("llc");
+ ipx_handle = find_dissector("ipx");
+ eth_handle = find_dissector("eth");
+ data_handle = find_dissector("data");
+
+ ieee80211_handle = find_dissector("wlan");
+ dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11, ieee80211_handle);
+ ieee80211_radio_handle = create_dissector_handle(dissect_ieee80211_radio,
+ proto_wlan);
+ dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
+ ieee80211_radio_handle);
+}
+
+static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
+ const guint8 *enc_data;
+ guint8 *tmp = NULL;
+ int i;
+ tvbuff_t *decr_tvb = NULL;
+
+ if (num_wepkeys < 1)
+ return NULL;
+
+ enc_data = tvb_get_ptr(tvb, offset, len);
+
+ if ((tmp = g_malloc(len)) == NULL)
+ return NULL; /* krap! */
+
+ /* try once with the key index in the packet, then look through our list. */
+ for (i = -1; i < (int) num_wepkeys; i++) {
+ /* copy the encrypted data over to the tmp buffer */
+#if 0
+ printf("trying %d\n", i);
+#endif
+ memcpy(tmp, enc_data, len);
+ if (wep_decrypt(tmp, len, i) == 0) {
+
+ /* decrypt successful, let's set up a new data tvb. */
+ decr_tvb = tvb_new_real_data(tmp, len-8, len-8);
+ tvb_set_free_cb(decr_tvb, g_free);
+ tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
+
+ goto done;
+ }
+ }
+
+ done:
+ if ((!decr_tvb) && (tmp)) g_free(tmp);
+
+#if 0
+ printf("de-wep %p\n", decr_tvb);
+#endif
+
+ return decr_tvb;
+}
+
+
+/* de-weps the block. if successful, buf* will point to the data start. */
+static int wep_decrypt(guint8 *buf, guint32 len, int key_override) {
+ guint32 i, j, k, crc, keylen;
+ guint8 s[256], key[128], c_crc[4];
+ guint8 keyidx, *dpos, *cpos;
+
+ /* Needs to be at least 8 bytes of payload */
+ if (len < 8)
+ return -1;
+
+ /* initialize the first bytes of the key from the IV */
+ key[0] = buf[0];
+ key[1] = buf[1];
+ key[2] = buf[2];
+ keyidx = COOK_WEP_KEY(buf[3]);
+
+ if (key_override >= 0)
+ keyidx = key_override;
+
+ if (keyidx >= num_wepkeys)
+ return -1;
+
+ keylen = wep_keylens[keyidx];
+
+ if (keylen == 0)
+ return -1;
+ if (wep_keys[keyidx] == NULL)
+ return -1;
+
+ keylen+=3; /* add in ICV bytes */
+
+ /* copy the rest of the key over from the designated key */
+ memcpy(key+3, wep_keys[keyidx], wep_keylens[keyidx]);
+
+#if 0
+ printf("%d: %02x %02x %02x (%d %d) %02x:%02x:%02x:%02x:%02x\n", len, key[0], key[1], key[2], keyidx, keylen, key[3], key[4], key[5], key[6], key[7]);
+#endif
+
+ /* set up the RC4 state */
+ for (i = 0; i < 256; i++)
+ s[i] = i;
+ j = 0;
+ for (i = 0; i < 256; i++) {
+ j = (j + s[i] + key[i % keylen]) & 0xff;
+ SSWAP(i,j);
+ }
+
+ /* Apply the RC4 to the data, update the CRC32 */
+ cpos = buf+4;
+ dpos = buf;
+ crc = ~0;
+ i = j = 0;
+ for (k = 0; k < (len -8); k++) {
+ i = (i+1) & 0xff;
+ j = (j+s[i]) & 0xff;
+ SSWAP(i,j);
+#if 0
+ printf("%d -- %02x ", k, *dpos);
+#endif
+ *dpos = *cpos++ ^ s[(s[i] + s[j]) & 0xff];
+#if 0
+ printf("%02x\n", *dpos);
+#endif
+ crc = crc32_ccitt_table[(crc ^ *dpos++) & 0xff] ^ (crc >> 8);
+ }
+ crc = ~crc;
+
+ /* now let's check the crc */
+ c_crc[0] = crc;
+ c_crc[1] = crc >> 8;
+ c_crc[2] = crc >> 16;
+ c_crc[3] = crc >> 24;
+
+ for (k = 0; k < 4; k++) {
+ i = (i + 1) & 0xff;
+ j = (j+s[i]) & 0xff;
+ SSWAP(i,j);
+#if 0
+ printf("-- %02x %02x\n", *dpos, c_crc[k]);
+#endif
+ if ((*cpos++ ^ s[(s[i] + s[j]) & 0xff]) != c_crc[k])
+ return -1; /* ICV mismatch */
+ }
+
+ return 0;
+}
+
+static void init_wepkeys(void) {
+ char *tmp;
+ guint i;
+ GByteArray *bytes;
+ gboolean res;
+
+#ifdef USE_ENV
+ guint8 buf[128];
+
+ tmp = getenv("ETHEREAL_WEPKEYNUM");
+ if (!tmp) {
+ num_wepkeys = 0;
+ return;
+ }
+ num_wepkeys = atoi(tmp);
+#else
+ if (num_wepkeys > 4)
+ num_wepkeys = 4;
+#endif
+
+ if (num_wepkeys < 1)
+ return;
+
+ if (wep_keys)
+ g_free(wep_keys);
+
+ if (wep_keylens)
+ g_free(wep_keylens);
+
+ wep_keys = g_malloc(num_wepkeys * sizeof(guint8*));
+ wep_keylens = g_malloc(num_wepkeys * sizeof(int));
+ bytes = g_byte_array_new();
+
+ for (i = 0 ; i < num_wepkeys; i++) {
+ wep_keys[i] = NULL;
+ wep_keylens[i] = 0;
+
+#ifdef USE_ENV
+ sprintf(buf, "ETHEREAL_WEPKEY%d", i+1);
+ tmp = getenv(buf);
+#else
+ tmp = wep_keystr[i];
+#endif
+
+ if (tmp) {
+#if 0
+#ifdef USE_ENV
+ printf("%s -- %s\n", buf, tmp);
+#else
+ printf("%d -- %s\n", i+1, tmp);
+#endif
+#endif
+
+ if (wep_keys[i]) {
+ g_free(wep_keys[i]);
+ }
+
+ res = hex_str_to_bytes(tmp, bytes, FALSE);
+ if (res && bytes->len > 0) {
+ if (bytes->len > 32) {
+ bytes->len = 32;
+ }
+ wep_keys[i] = g_malloc(32 * sizeof(guint8));
+ memset(wep_keys[i], 0, 32 * sizeof(guint8));
+ memcpy(wep_keys[i], bytes->data, bytes->len * sizeof(guint8));
+ wep_keylens[i] = bytes->len;
+#if 0
+ printf("%d: %d bytes\n", i, bytes->len);
+ printf("%d: %s\n", i, bytes_to_str(bytes->data, bytes->len));
+#endif
+ } else {
+#if 0
+ printf("res: %d bytes->len: %d\n", res, bytes->len);
+#endif
+ g_warning("Could not parse WEP key %d: %s", i + 1, tmp);
+ }
+ }
+ }
+ g_byte_array_free(bytes, TRUE);
+}
diff --git a/epan/dissectors/packet-ieee80211.h b/epan/dissectors/packet-ieee80211.h
new file mode 100644
index 0000000000..c6396cb8e4
--- /dev/null
+++ b/epan/dissectors/packet-ieee80211.h
@@ -0,0 +1,34 @@
+/* packet-ieee80211.h
+ * Routines for Wireless LAN (IEEE 802.11) dissection
+ *
+ * Copyright 2000, Axis Communications AB
+ * Inquiries/bugreports should be sent to Johan.Jorgensen@axis.com
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+void capture_ieee80211 (const guchar *, int, int, packet_counts *);
+void capture_ieee80211_fixed (const guchar *, int, int, packet_counts *);
+
+void ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset,
+ proto_tree * tree, int tagged_parameters_len);
diff --git a/epan/dissectors/packet-ieee8023.c b/epan/dissectors/packet-ieee8023.c
new file mode 100644
index 0000000000..5e8f98aa2d
--- /dev/null
+++ b/epan/dissectors/packet-ieee8023.c
@@ -0,0 +1,121 @@
+/* packet-ieee8023.c
+ * Routine for dissecting 802.3 (as opposed to D/I/X Ethernet) packets.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ieee8023.h"
+#include "packet-eth.h"
+#include "packet-frame.h"
+
+static dissector_handle_t ipx_handle;
+static dissector_handle_t llc_handle;
+
+void
+dissect_802_3(int length, gboolean is_802_2, tvbuff_t *tvb,
+ int offset_after_length, packet_info *pinfo, proto_tree *tree,
+ proto_tree *fh_tree, int length_id, int trailer_id,
+ int fcs_len)
+{
+ tvbuff_t *volatile next_tvb;
+ tvbuff_t *volatile trailer_tvb;
+ const char *saved_proto;
+
+ if (fh_tree)
+ proto_tree_add_uint(fh_tree, length_id, tvb, offset_after_length - 2, 2,
+ length);
+
+ /* Give the next dissector only 'length' number of bytes */
+ TRY {
+ next_tvb = tvb_new_subset(tvb, offset_after_length, length, length);
+ trailer_tvb = tvb_new_subset(tvb, offset_after_length + length, -1, -1);
+ }
+ CATCH2(BoundsError, ReportedBoundsError) {
+ /* Either:
+
+ the packet doesn't have "length" bytes worth of
+ captured data left in it - or it may not even have
+ "length" bytes worth of data in it, period -
+ so the "tvb_new_subset()" creating "next_tvb"
+ threw an exception
+
+ or
+
+ the packet has exactly "length" bytes worth of
+ captured data left in it, so the "tvb_new_subset()"
+ creating "trailer_tvb" threw an exception.
+
+ In either case, this means that all the data in the frame
+ is within the length value, so we give all the data to the
+ next protocol and have no trailer. */
+ next_tvb = tvb_new_subset(tvb, offset_after_length, -1, length);
+ trailer_tvb = NULL;
+ }
+ ENDTRY;
+
+ /* Dissect the payload either as IPX or as an LLC frame.
+ Catch BoundsError and ReportedBoundsError, so that if the
+ reported length of "next_tvb" was reduced by some dissector
+ before an exception was thrown, we can still put in an item
+ for the trailer. */
+ saved_proto = pinfo->current_proto;
+ TRY {
+ if (is_802_2)
+ call_dissector(llc_handle, next_tvb, pinfo, tree);
+ else
+ call_dissector(ipx_handle, next_tvb, pinfo, tree);
+ }
+ CATCH(BoundsError) {
+ /* Somebody threw BoundsError, which means that dissecting the payload
+ found that the packet was cut off by a snapshot length before the
+ end of the payload. The trailer comes after the payload, so *all*
+ of the trailer is cut off - don't bother adding the trailer, just
+ rethrow the exception so it gets reported. */
+ RETHROW;
+ }
+ CATCH_ALL {
+ /* Well, somebody threw an exception other than BoundsError.
+ Show the exception, and then drive on to show the trailer,
+ restoring the protocol value that was in effect before we
+ called the subdissector. */
+ show_exception(next_tvb, pinfo, tree, EXCEPT_CODE);
+ pinfo->current_proto = saved_proto;
+ }
+ ENDTRY;
+
+ add_ethernet_trailer(fh_tree, trailer_id, tvb, trailer_tvb, fcs_len);
+}
+
+void
+proto_reg_handoff_ieee802_3(void)
+{
+ /*
+ * Get handles for the IPX and LLC dissectors.
+ */
+ ipx_handle = find_dissector("ipx");
+ llc_handle = find_dissector("llc");
+}
diff --git a/epan/dissectors/packet-ieee8023.h b/epan/dissectors/packet-ieee8023.h
new file mode 100644
index 0000000000..48c1d13548
--- /dev/null
+++ b/epan/dissectors/packet-ieee8023.h
@@ -0,0 +1,34 @@
+/* packet-ieee8023.h
+ * Declaration of routine for dissecting 802.3 (as opposed to D/I/X Ethernet)
+ * packets.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_IEEE8023_H__
+#define __PACKET_IEEE8023_H__
+
+void dissect_802_3(int length, gboolean is_802_2, tvbuff_t *tvb,
+ int offset_after_length, packet_info *pinfo, proto_tree *tree,
+ proto_tree *fh_tree, int length_id, int trailer_id, int fcs_len);
+
+#endif
diff --git a/epan/dissectors/packet-igap.c b/epan/dissectors/packet-igap.c
new file mode 100644
index 0000000000..287b8c451d
--- /dev/null
+++ b/epan/dissectors/packet-igap.c
@@ -0,0 +1,330 @@
+/* packet-igap.c
+ * Routines for IGMP/IGAP packet disassembly
+ * 2003, Endoh Akria (see AUTHORS for email)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ IGAP "Internet Group membership Authentication Protocol"
+ is defined in draft-hayashi-igap-03.txt.
+
+ (Author's memo)
+ Type Subtype Message Msize
+ -----------------------------------------------------
+ ---- 0x02 User password variable
+ ---- 0x03 ---- 00
+ ---- 0x04 Result of MD5 calculation 16
+ 0x41 0x23 Challenge value ??
+ 0x41 0x24 Authentication result code 1
+ 0x41 0x25 Accounting status code 1
+ ---- 0x42 User password variable
+ ---- 0x43 ---- 00
+ ---- 0x44 Result of MD5 calculation 16
+
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "packet-igmp.h"
+#include "packet-igap.h"
+
+
+static int proto_igap = -1;
+static int hf_type = -1;
+static int hf_max_resp = -1;
+static int hf_checksum = -1;
+static int hf_checksum_bad = -1;
+static int hf_maddr = -1;
+static int hf_version = -1;
+static int hf_subtype = -1;
+static int hf_challengeid = -1;
+static int hf_asize = -1;
+static int hf_msize = -1;
+static int hf_account = -1;
+
+static int ett_igap = -1;
+
+
+static const value_string igap_types[] = {
+ {IGMP_IGAP_JOIN, "Membership Report (Join)"},
+ {IGMP_IGAP_QUERY, "Membership Query"},
+ {IGMP_IGAP_LEAVE, "Leave Group"},
+ {0, NULL}
+};
+
+#define IGAP_VERSION_1 0x10
+static const value_string igap_version[] = {
+ {IGAP_VERSION_1, "1"},
+ {0, NULL}
+};
+
+#define IGAP_SUBTYPE_PASSWORD_JOIN 0x02
+#define IGAP_SUBTYPE_CHALLENGE_REQUEST_JOIN 0x03
+#define IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN 0x04
+#define IGAP_SUBTYPE_BASIC_QUERY 0x21
+#define IGAP_SUBTYPE_CHALLENGE 0x23
+#define IGAP_SUBTYPE_AUTH_MESSAGE 0x24
+#define IGAP_SUBTYPE_ACCOUNTING_MESSAGE 0x25
+#define IGAP_SUBTYPE_BASIC_LEAVE 0x41
+#define IGAP_SUBTYPE_PASSWORD_LEAVE 0x42
+#define IGAP_SUBTYPE_CHALLENGE_REQUEST_LEAVE 0x43
+#define IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE 0x44
+static const value_string igap_subtypes[] = {
+ {IGAP_SUBTYPE_PASSWORD_JOIN, "Password Mechanism Join (Password-Join)"},
+ {IGAP_SUBTYPE_CHALLENGE_REQUEST_JOIN, "Challenge-Response Mechanism Join Request (Challenge-Request-Join)"},
+ {IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN, "Challenge-Response Mechanism Join Response (Challenge-Response-Join)"},
+ {IGAP_SUBTYPE_BASIC_QUERY, "Basic Query"},
+ {IGAP_SUBTYPE_CHALLENGE, "Challenge-Response Mechanism Challenge (Challenge)"},
+ {IGAP_SUBTYPE_AUTH_MESSAGE, "Authentication Message"},
+ {IGAP_SUBTYPE_ACCOUNTING_MESSAGE, "Accounting Message"},
+ {IGAP_SUBTYPE_BASIC_LEAVE, "Basic Leave"},
+ {IGAP_SUBTYPE_PASSWORD_LEAVE, "Password Mechanism Leave (Password-Leave)"},
+ {IGAP_SUBTYPE_CHALLENGE_REQUEST_LEAVE, "Challenge-Response Mechanism Leave Challenge Request (Challenge-Request-Leave)"},
+ {IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE, "Challenge-Response Mechanism Response (Challenge-Response-Leave)"},
+ {0, NULL}
+};
+
+#define IGAP_AUTH_SUCCESS 0x11
+#define IGAP_AUTH_FAIL 0x21
+static const value_string igap_auth_result[] = {
+ {IGAP_AUTH_SUCCESS, "Authentication success"},
+ {IGAP_AUTH_FAIL, "Authentication failure"},
+ {0, NULL}
+};
+
+#define IGAP_ACCOUNT_START 0x11
+#define IGAP_ACCOUNT_STOP 0x21
+static const value_string igap_account_status[] = {
+ {IGAP_ACCOUNT_START, "Accounting start"},
+ {IGAP_ACCOUNT_STOP, "Accounting stop"},
+ {0, NULL}
+};
+
+#define ACCOUNT_SIZE 16
+#define MESSAGE_SIZE 64
+
+/* This function is only called from the IGMP dissector */
+int
+dissect_igap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree;
+ proto_item *item;
+ guint8 type, tsecs, subtype, asize, msize;
+ guchar account[ACCOUNT_SIZE+1], message[MESSAGE_SIZE+1];
+
+ if (!proto_is_protocol_enabled(find_protocol_by_id(proto_igap))) {
+ /* we are not enabled, skip entire packet to be nice
+ to the igmp layer. (so clicking on IGMP will display the data)
+ */
+ return offset + tvb_length_remaining(tvb, offset);
+ }
+
+ item = proto_tree_add_item(parent_tree, proto_igap, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_igap);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGAP");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(type, igap_types, "Unknown Type: 0x%02x"));
+ }
+ proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type);
+ offset += 1;
+
+ tsecs = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_max_resp, tvb, offset, 1, tsecs,
+ "Max Response Time: %.1f sec (0x%02x)", tsecs * 0.1, tsecs);
+ offset += 1;
+
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_uint(tree, hf_version, tvb, offset, 1,
+ tvb_get_guint8(tvb, offset));
+ offset += 1;
+
+ subtype = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_subtype, tvb, offset, 1, subtype);
+ offset += 2;
+
+ proto_tree_add_uint(tree, hf_challengeid, tvb, offset, 1,
+ tvb_get_guint8(tvb, offset));
+ offset += 1;
+
+ asize = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_asize, tvb, offset, 1, asize);
+ offset += 1;
+
+ msize = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_msize, tvb, offset, 1, msize);
+ offset += 3;
+
+ if (asize > 0) {
+ if (asize > ACCOUNT_SIZE) {
+ /* Bogus account size.
+ XXX - flag this? */
+ asize = ACCOUNT_SIZE;
+ }
+ tvb_memcpy(tvb, account, offset, asize);
+ account[asize] = '\0';
+ proto_tree_add_string(tree, hf_account, tvb, offset, asize, account);
+ }
+ offset += ACCOUNT_SIZE;
+
+ if (msize > 0) {
+ if (msize > MESSAGE_SIZE) {
+ /* Bogus message size.
+ XXX - flag this? */
+ msize = MESSAGE_SIZE;
+ }
+ tvb_memcpy(tvb, message, offset, msize);
+ switch (subtype) {
+ case IGAP_SUBTYPE_PASSWORD_JOIN:
+ case IGAP_SUBTYPE_PASSWORD_LEAVE:
+ /* Challenge field is user's password */
+ message[msize] = '\0';
+ proto_tree_add_text(tree, tvb, offset, msize,
+ "User password: %s", message);
+ break;
+ case IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN:
+ case IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE:
+ /* Challenge field is the results of MD5 calculation */
+ proto_tree_add_text(tree, tvb, offset, msize,
+ "Result of MD5 calculation: 0x%s",
+ bytes_to_str(message, msize));
+ break;
+ case IGAP_SUBTYPE_CHALLENGE:
+ /* Challenge field is the challenge value */
+ proto_tree_add_text(tree, tvb, offset, msize,
+ "Challenge: 0x%s",
+ bytes_to_str(message, msize));
+ break;
+ case IGAP_SUBTYPE_AUTH_MESSAGE:
+ /* Challenge field indicates the result of the authenticaion */
+ proto_tree_add_text(tree, tvb, offset, msize,
+ "Authentication result: %s (0x%x)",
+ val_to_str(message[0], igap_auth_result,
+ "Unknown"), message[0]);
+ break;
+ case IGAP_SUBTYPE_ACCOUNTING_MESSAGE:
+ /* Challenge field indicates the accounting status */
+ proto_tree_add_text(tree, tvb, offset, msize,
+ "Accounting status: %s (0x%x)",
+ val_to_str(message[0], igap_account_status,
+ "Unknown"), message[0]);
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, msize,
+ "Message: (Unknown)");
+ }
+ }
+ offset += MESSAGE_SIZE;
+
+ if (item) proto_item_set_len(item, offset);
+ return offset;
+}
+
+
+void
+proto_register_igap(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_type,
+ { "Type", "igap.type", FT_UINT8, BASE_HEX,
+ VALS(igap_types), 0, "IGAP Packet Type", HFILL }
+ },
+
+ { &hf_max_resp,
+ { "Max Resp Time", "igap.max_resp", FT_UINT8, BASE_DEC,
+ NULL, 0, "Max Response Time", HFILL }
+ },
+
+ { &hf_checksum,
+ { "Checksum", "igap.checksum", FT_UINT16, BASE_HEX,
+ NULL, 0, "Checksum", HFILL }
+ },
+
+ { &hf_checksum_bad,
+ { "Bad Checksum", "igap.checksum_bad", FT_BOOLEAN, BASE_NONE,
+ NULL, 0, "Bad Checksum", HFILL }
+ },
+
+ { &hf_maddr,
+ { "Multicast group address", "igap.maddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "Multicast group address", HFILL }
+ },
+
+ { &hf_version,
+ { "Version", "igap.version", FT_UINT8, BASE_HEX,
+ VALS(igap_version), 0, "IGAP protocol version", HFILL }
+ },
+
+ { &hf_subtype,
+ { "Subtype", "igap.subtype", FT_UINT8, BASE_HEX,
+ VALS(igap_subtypes), 0, "Subtype", HFILL }
+ },
+
+ { &hf_challengeid,
+ { "Challenge ID", "igap.challengeid", FT_UINT8, BASE_HEX,
+ NULL, 0, "Challenge ID", HFILL }
+ },
+
+ { &hf_asize,
+ { "Account Size", "igap.asize", FT_UINT8, BASE_DEC,
+ NULL, 0, "Length of the User Account field", HFILL }
+ },
+
+ { &hf_msize,
+ { "Message Size", "igap.msize", FT_UINT8, BASE_DEC,
+ NULL, 0, "Length of the Message field", HFILL }
+ },
+
+ { &hf_account,
+ { "User Account", "igap.account", FT_STRING, BASE_NONE,
+ NULL, 0, "User account", HFILL }
+ }
+ };
+
+ static gint *ett[] = {
+ &ett_igap
+ };
+
+ proto_igap = proto_register_protocol
+ ("Internet Group membership Authentication Protocol",
+ "IGAP", "igap");
+ proto_register_field_array(proto_igap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/epan/dissectors/packet-igap.h b/epan/dissectors/packet-igap.h
new file mode 100644
index 0000000000..e8907e7bd0
--- /dev/null
+++ b/epan/dissectors/packet-igap.h
@@ -0,0 +1,35 @@
+/* packet-igap.h
+ * Declarations of routines for IGMP/IGAP packet disassembly
+ * 2003, Endoh Akira <See AUTHORS for email>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_IGAP_H__
+#define __PACKET_IGAP_H__
+
+#define IGMP_IGAP_JOIN 0x40
+#define IGMP_IGAP_QUERY 0x41
+#define IGMP_IGAP_LEAVE 0x42
+
+int dissect_igap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+
+#endif
diff --git a/epan/dissectors/packet-igmp.c b/epan/dissectors/packet-igmp.c
new file mode 100644
index 0000000000..11aaad97a1
--- /dev/null
+++ b/epan/dissectors/packet-igmp.c
@@ -0,0 +1,1097 @@
+/* packet-igmp.c 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Routines for IGMP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ IGMP is defined in the following RFCs
+ RFC988 Version 0 Obsolete
+ RFC1054 Version 1
+ RFC1112 Version 1 (same as RFC1054 as far as we are concerned)
+ RFC2236 Version 2
+ draft-ietf-idmr-igmp-v3-07 Version 3
+
+ Size in bytes for each packet
+ type RFC988 RFC1054 RFC2236 RFC???? DVMRP MRDISC MSNIP IGAP
+ v0 v1 v2 v3 v1/v3
+ 0x01 20
+ 0x02 20
+ 0x03 20
+ 0x04 20
+ 0x05 20
+ 0x06 20
+ 0x07 20
+ 0x08 20
+ 0x11 8* 8* >=12
+ 0x12 8* 8*
+ 0x13 x
+ 0x16 8
+ 0x17 8
+ 0x22 >=8
+ 0x23 >=8b
+ 0x24 >=8a 8b
+ 0x25 4a >=8b
+ 0x26 4a
+ 0x40 ??c
+ 0x41 ??c
+ 0x42 ??c
+
+ * Differs in second byte of protocol. Always 0 in V1
+
+
+ Multicast traceroute was taken from
+ draft-ietf-idmr-traceroute-ipm-07.txt
+
+ Size in bytes for each packet
+ type draft-ietf-idmr-traceroute-ipm-07.ps
+ 0x1e 24 + n*32
+ 0x1f 24 + n*32 (n == 0 for Query)
+
+ x DVMRP Protocol see packet-dvmrp.c
+
+ DVMRP is defined in the following RFCs
+ RFC1075 Version 1
+ draft-ietf-idmr-dvmrp-v3-10.txt Version 3
+
+ V1 and V3 can be distinguished by looking at bytes 6 and 7 in the
+ IGMP header.
+ If header[6]==0xff and header[7]==0x03 we have version 3.
+
+ a MRDISC Protocol see packet-mrdisc.c
+
+ MRDISC : IGMP Multicast Router DISCovery
+ draft-ietf-idmr-igmp-mrdisc-06.txt
+ TTL == 1 and IP.DST==224.0.0.2 for all packets
+
+ b MSNIP Protocol see packet-msnip.c
+
+ MSNIP : Multicast Source Notification of Interest Protocol
+ draft-ietf-idmr-msnip-00.txt
+ 0x23, 0x24 are sent with ip.dst==224.0.0.22
+ 0x25 is sent as unicast.
+
+ c IGAP Protocol see packet-igap.c
+
+ IGAP : Internet Group membership Authentication Protocol
+ draft-hayashi-igap-03.txt
+
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "ipproto.h"
+#include "in_cksum.h"
+#include "packet-dvmrp.h"
+#include "packet-pim.h"
+#include "packet-mrdisc.h"
+#include "packet-msnip.h"
+#include "packet-igap.h"
+
+static int proto_igmp = -1;
+static int hf_type = -1;
+static int hf_version = -1;
+static int hf_group_type = -1;
+static int hf_reply_code = -1;
+static int hf_reply_pending = -1;
+static int hf_checksum = -1;
+static int hf_checksum_bad = -1;
+static int hf_identifier = -1;
+static int hf_access_key = -1;
+static int hf_max_resp = -1;
+static int hf_max_resp_exp = -1;
+static int hf_max_resp_mant = -1;
+static int hf_supress = -1;
+static int hf_qrv = -1;
+static int hf_qqic = -1;
+static int hf_num_src = -1;
+static int hf_saddr = -1;
+static int hf_num_grp_recs = -1;
+static int hf_record_type = -1;
+static int hf_aux_data_len = -1;
+static int hf_maddr = -1;
+static int hf_aux_data = -1;
+static int hf_mtrace_max_hops = -1;
+static int hf_mtrace_saddr = -1;
+static int hf_mtrace_raddr = -1;
+static int hf_mtrace_rspaddr = -1;
+static int hf_mtrace_resp_ttl = -1;
+static int hf_mtrace_q_id = -1;
+static int hf_mtrace_q_arrival = -1;
+static int hf_mtrace_q_inaddr = -1;
+static int hf_mtrace_q_outaddr = -1;
+static int hf_mtrace_q_prevrtr = -1;
+static int hf_mtrace_q_inpkt = -1;
+static int hf_mtrace_q_outpkt = -1;
+static int hf_mtrace_q_total = -1;
+static int hf_mtrace_q_rtg_proto = -1;
+static int hf_mtrace_q_fwd_ttl = -1;
+static int hf_mtrace_q_mbz = -1;
+static int hf_mtrace_q_s = -1;
+static int hf_mtrace_q_src_mask = -1;
+static int hf_mtrace_q_fwd_code = -1;
+
+static int ett_igmp = -1;
+static int ett_group_record = -1;
+static int ett_sqrv_bits = -1;
+static int ett_max_resp = -1;
+static int ett_mtrace_block = -1;
+
+#define MC_ALL_ROUTERS 0xe0000002
+#define MC_ALL_IGMPV3_ROUTERS 0xe0000016
+
+
+#define IGMP_V0_CREATE_GROUP_REQUEST 0x01
+#define IGMP_V0_CREATE_GROUP_REPLY 0x02
+#define IGMP_V0_JOIN_GROUP_REQUEST 0x03
+#define IGMP_V0_JOIN_GROUP_REPLY 0x04
+#define IGMP_V0_LEAVE_GROUP_REQUEST 0x05
+#define IGMP_V0_LEAVE_GROUP_REPLY 0x06
+#define IGMP_V0_CONFIRM_GROUP_REQUEST 0x07
+#define IGMP_V0_CONFIRM_GROUP_REPLY 0x08
+#define IGMP_V1_HOST_MEMBERSHIP_QUERY 0x11
+#define IGMP_V1_HOST_MEMBERSHIP_REPORT 0x12
+#define IGMP_DVMRP 0x13
+#define IGMP_V1_PIM_ROUTING_MESSAGE 0x14
+#define IGMP_V2_MEMBERSHIP_REPORT 0x16
+#define IGMP_V2_LEAVE_GROUP 0x17
+#define IGMP_TRACEROUTE_RESPONSE 0x1e
+#define IGMP_TRACEROUTE_QUERY_REQ 0x1f
+#define IGMP_V3_MEMBERSHIP_REPORT 0x22
+#define IGMP_TYPE_0x23 0x23
+#define IGMP_TYPE_0x24 0x24
+#define IGMP_TYPE_0x25 0x25
+#define IGMP_TYPE_0x26 0x26
+
+#define IGMP_TRACEROUTE_HDR_LEN 24
+#define IGMP_TRACEROUTE_RSP_LEN 32
+
+static const value_string commands[] = {
+ {IGMP_V0_CREATE_GROUP_REQUEST, "Create Group Request" },
+ {IGMP_V0_CREATE_GROUP_REPLY, "Create Group Reply" },
+ {IGMP_V0_JOIN_GROUP_REQUEST, "Join Group Request" },
+ {IGMP_V0_JOIN_GROUP_REPLY, "Join Group Reply" },
+ {IGMP_V0_LEAVE_GROUP_REQUEST, "Leave Group Request" },
+ {IGMP_V0_LEAVE_GROUP_REPLY, "Leave Group Reply" },
+ {IGMP_V0_CONFIRM_GROUP_REQUEST, "Confirm Group Request" },
+ {IGMP_V0_CONFIRM_GROUP_REPLY, "Confirm Group Reply" },
+ {IGMP_V1_HOST_MEMBERSHIP_QUERY, "Membership Query" },
+ {IGMP_V1_HOST_MEMBERSHIP_REPORT,"Membership Report" },
+ {IGMP_DVMRP, "DVMRP Protocol" },
+ {IGMP_V1_PIM_ROUTING_MESSAGE, "PIM Routing Message" },
+ {IGMP_V2_MEMBERSHIP_REPORT, "Membership Report" },
+ {IGMP_V2_LEAVE_GROUP, "Leave Group" },
+ {IGMP_TRACEROUTE_RESPONSE, "Traceroute Response" },
+ {IGMP_TRACEROUTE_QUERY_REQ, "Traceroute Query or Request" },
+ {IGMP_V3_MEMBERSHIP_REPORT, "Membership Report" },
+ {0, NULL}
+};
+
+#define IGMP_V3_S 0x08
+#define IGMP_V3_QRV_MASK 0x07
+
+#define IGMP_MAX_RESP_EXP 0x70
+#define IGMP_MAX_RESP_MANT 0x0f
+
+#define IGMP_V0_GROUP_PUBLIC 0x00
+#define IGMP_V0_GROUP_PRIVATE 0x01
+
+static const value_string vs_group_type[] = {
+ {IGMP_V0_GROUP_PUBLIC, "Public Group" },
+ {IGMP_V0_GROUP_PRIVATE, "Private Group" },
+ {0, NULL}
+};
+
+#define IGMP_V0_REPLY_GRANTED 0x00
+#define IGMP_V0_REPLY_NO_RESOURCES 0x01
+#define IGMP_V0_REPLY_INVALID_CODE 0x02
+#define IGMP_V0_REPLY_INVALID_GROUP 0x03
+#define IGMP_V0_REPLY_INVALID_KEY 0x04
+
+static const value_string vs_reply_code[] = {
+ {IGMP_V0_REPLY_GRANTED, "Request Granted" },
+ {IGMP_V0_REPLY_NO_RESOURCES, "Request Denied, No Resources" },
+ {IGMP_V0_REPLY_INVALID_CODE, "Request Denied, Invalid Code" },
+ {IGMP_V0_REPLY_INVALID_GROUP, "Request Denied, Invalid Group" },
+ {IGMP_V0_REPLY_INVALID_KEY, "Request Denied, Invalid Key" },
+ {0, NULL}
+};
+
+static const true_false_string tfs_s = {
+ "SUPRESS router side processing",
+ "Do not supress router side processing"
+};
+
+#define IGMP_V3_MODE_IS_INCLUDE 1
+#define IGMP_V3_MODE_IS_EXCLUDE 2
+#define IGMP_V3_CHANGE_TO_INCLUDE_MODE 3
+#define IGMP_V3_CHANGE_TO_EXCLUDE_MODE 4
+#define IGMP_V3_ALLOW_NEW_SOURCES 5
+#define IGMP_V3_BLOCK_OLD_SOURCES 6
+
+static const value_string vs_record_type[] = {
+ {IGMP_V3_MODE_IS_INCLUDE, "Mode Is Include" },
+ {IGMP_V3_MODE_IS_EXCLUDE, "Mode Is Exclude" },
+ {IGMP_V3_CHANGE_TO_INCLUDE_MODE,"Change To Include Mode" },
+ {IGMP_V3_CHANGE_TO_EXCLUDE_MODE,"Change To Exclude Mode" },
+ {IGMP_V3_ALLOW_NEW_SOURCES, "Allow New Sources" },
+ {IGMP_V3_BLOCK_OLD_SOURCES, "Block Old Sources" },
+ { 0, NULL}
+};
+
+static const value_string mtrace_rtg_vals[] = {
+ {1, "DVMRP" },
+ {2, "MOSPF" },
+ {3, "PIM" },
+ {4, "CBT" },
+ {5, "PIM using special routing table" },
+ {6, "PIM using a static route" },
+ {7, "DVMRP using a static route" },
+ {8, "PIM using MBGP (aka BGP4+) route" },
+ {9, "CBT using special routing table" },
+ {10, "CBT using a static route" },
+ {11, "PIM using state created by Assert processing" },
+ {0, NULL}
+};
+
+static const value_string mtrace_fwd_code_vals[] = {
+ {0x00, "NO_ERROR" },
+ {0x01, "WRONG_IF" },
+ {0x02, "PRUNE_SENT" },
+ {0x03, "PRUNE_RCVD" },
+ {0x04, "SCOPED" },
+ {0x05, "NO_ROUTE" },
+ {0x06, "WRONG_LAST_HOP" },
+ {0x07, "NOT_FORWARDING" },
+ {0x08, "REACHED_RP" },
+ {0x09, "RPF_IF" },
+ {0x0A, "NO_MULTICAST" },
+ {0x0B, "INFO_HIDDEN" },
+ {0x81, "NO_SPACE" },
+ {0x82, "OLD_ROUTER" },
+ {0x83, "ADMIN_PROHIB" },
+ {0, NULL}
+};
+
+#define PRINT_IGMP_VERSION(version) \
+ if (check_col(pinfo->cinfo, COL_INFO)) { \
+ col_add_fstr(pinfo->cinfo, COL_INFO, \
+ "V%d %s",version,val_to_str(type, commands, \
+ "Unknown Type:0x%02x")); \
+ } \
+ /* version of IGMP protocol */ \
+ proto_tree_add_uint(tree, hf_version, tvb, 0, 0, version); \
+ /* type of command */ \
+ proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); \
+ offset += 1;
+
+void igmp_checksum(proto_tree *tree, tvbuff_t *tvb, int hf_index,
+ int hf_index_bad, packet_info *pinfo, guint len)
+{
+ guint16 cksum, hdrcksum;
+ vec_t cksum_vec[1];
+
+ if (len == 0) {
+ /*
+ * Checksum the entire IGMP packet.
+ */
+ len = tvb_reported_length(tvb);
+ }
+
+ hdrcksum = tvb_get_ntohs(tvb, 2);
+ if (!pinfo->fragmented && tvb_length(tvb) >= len) {
+ /*
+ * The packet isn't part of a fragmented datagram and isn't
+ * truncated, so we can checksum it.
+ */
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, len);
+ cksum_vec[0].len = len;
+
+ cksum = in_cksum(&cksum_vec[0],1);
+
+ if (cksum == 0) {
+ proto_tree_add_uint_format(tree, hf_index,
+ tvb, 2, 2, hdrcksum,
+ "Header checksum: 0x%04x (correct)", hdrcksum);
+ } else {
+ proto_tree_add_boolean_hidden(tree, hf_index_bad,
+ tvb, 2, 2, TRUE);
+ proto_tree_add_uint_format(tree, hf_index,
+ tvb, 2, 2, hdrcksum,
+ "Header checksum: 0x%04x (incorrect, should be 0x%04x)", hdrcksum,in_cksum_shouldbe(hdrcksum,cksum));
+ }
+ } else
+ proto_tree_add_uint(tree, hf_index, tvb, 2, 2, hdrcksum);
+
+ return;
+}
+
+
+/* Unknown IGMP message type */
+static int
+dissect_igmp_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+{
+ int len;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(type, commands, "Unknown Type:0x%02x"));
+ }
+
+ /* type of command */
+ proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type);
+ offset += 1;
+
+ /* Just call the rest of it "data" */
+ len = tvb_length_remaining(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, len, "Data");
+ offset += len;
+
+ return offset;
+}
+
+
+
+/*************************************************************
+ * IGMP Protocol dissectors
+ *************************************************************/
+static int
+dissect_v3_max_resp(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree;
+ proto_item *item;
+ guint8 bits;
+ guint32 tsecs;
+
+ bits = tvb_get_guint8(tvb, offset);
+ if (bits&0x80) {
+ tsecs = ((bits&IGMP_MAX_RESP_MANT)|0x10);
+ tsecs = tsecs << ( ((bits&IGMP_MAX_RESP_EXP)>>4) + 3);
+ } else {
+ tsecs = bits;
+ }
+
+ item = proto_tree_add_uint_format(parent_tree, hf_max_resp, tvb,
+ offset, 1, tsecs, "Max Response Time: %.1f sec (0x%02x)",tsecs*0.1,bits);
+
+ if (bits&0x80) {
+ tree = proto_item_add_subtree(item, ett_max_resp);
+
+ proto_tree_add_uint(tree, hf_max_resp_exp, tvb, offset, 1,
+ bits);
+ proto_tree_add_uint(tree, hf_max_resp_mant, tvb, offset, 1,
+ bits);
+ }
+
+ offset += 1;
+
+ return offset;
+}
+
+static int
+dissect_v3_sqrv_bits(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree;
+ proto_item *item;
+ guint8 bits;
+
+ bits = tvb_get_guint8(tvb, offset);
+
+ item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+ "QRV=%d S=%s", bits&IGMP_V3_QRV_MASK,
+ (bits&IGMP_V3_S)?tfs_s.true_string:tfs_s.false_string);
+ tree = proto_item_add_subtree(item, ett_sqrv_bits);
+
+ /* S flag */
+ proto_tree_add_boolean(tree, hf_supress, tvb, offset, 1, bits);
+ /* QRV */
+ proto_tree_add_uint(tree, hf_qrv, tvb, offset, 1, bits);
+ offset += 1;
+
+ return offset;
+}
+
+static int
+dissect_v3_group_record(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree;
+ proto_item *item;
+ int old_offset = offset;
+ guint8 adl;
+ guint16 num;
+ guint32 ip;
+
+ tvb_memcpy(tvb, (guint8 *)&ip, offset+4, 4);
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "Group Record : %s %s",
+ ip_to_str((gchar*)&ip),
+ val_to_str(tvb_get_guint8(tvb, offset), vs_record_type,"")
+ );
+ tree = proto_item_add_subtree(item, ett_group_record);
+
+ /* record type */
+ proto_tree_add_item(tree, hf_record_type, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* aux data len */
+ adl = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_aux_data_len, tvb, offset, 1, adl);
+ offset += 1;
+
+ /*number of sources*/
+ num = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_num_src, tvb, offset, 2, num);
+ offset += 2;
+
+ /* multicast address */
+ proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* source addresses */
+ while(num--){
+ proto_tree_add_item(tree, hf_saddr, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+
+ /* aux data */
+ if(adl){
+ proto_tree_add_item(tree, hf_aux_data, tvb, offset, adl*4,
+ FALSE);
+ offset += adl*4;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+/* dissectors for version 3, rfc???? */
+static int
+dissect_igmp_v3_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+{
+ guint16 num;
+
+ PRINT_IGMP_VERSION(3);
+
+ /* skip reserved field*/
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ /* skip reserved field */
+ offset += 2;
+
+ /* number of group records */
+ num = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_num_grp_recs, tvb, offset, 2, num);
+ offset += 2;
+
+ while (num--) {
+ offset = dissect_v3_group_record(tvb, tree, offset);
+ }
+
+ return offset;
+}
+
+static int
+dissect_igmp_v3_query(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+{
+ guint16 num;
+
+ PRINT_IGMP_VERSION(3);
+
+ num = tvb_get_ntohs(tvb, offset+9);
+ /* max resp code */
+ offset = dissect_v3_max_resp(tvb, tree, offset);
+
+ /* checksum */
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ /* group address */
+ proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
+ offset +=4;
+
+ /* bitmask for S and QRV */
+ offset = dissect_v3_sqrv_bits(tvb, tree, offset);
+
+ /* qqic */
+ proto_tree_add_item(tree, hf_qqic, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /*number of sources*/
+ proto_tree_add_uint(tree, hf_num_src, tvb, offset, 2, num);
+ offset += 2;
+
+ while(num--){
+ proto_tree_add_item(tree, hf_saddr, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+
+ return offset;
+}
+
+/* dissector for version 2, rfc2236 */
+static int
+dissect_igmp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+{
+ guint8 tsecs;
+
+ PRINT_IGMP_VERSION(2);
+
+ /* max resp time */
+ tsecs = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_max_resp, tvb,
+ offset, 1, tsecs, "Max Response Time: %.1f sec (0x%02x)", tsecs*0.1,tsecs);
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 8);
+ offset += 2;
+
+ /* group address */
+ proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
+ offset +=4;
+
+ return offset;
+}
+
+/* dissector for version 1, rfc1054 */
+static int
+dissect_igmp_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+{
+ PRINT_IGMP_VERSION(1);
+
+ /* skip unused byte */
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 8);
+ offset += 2;
+
+ /* group address */
+ proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
+ offset +=4;
+
+ return offset;
+}
+
+/* dissector for version 0, rfc988 */
+static int
+dissect_igmp_v0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+{
+ unsigned char code;
+
+ PRINT_IGMP_VERSION(0);
+
+ /* Code */
+ code = tvb_get_guint8(tvb, offset);
+ if (type==IGMP_V0_CREATE_GROUP_REQUEST) {
+ proto_tree_add_uint(tree, hf_group_type, tvb, offset, 1, code);
+ } else if (!(type&0x01)) {
+ if (code <5) {
+ proto_tree_add_uint(tree, hf_reply_code, tvb, offset, 1, code);
+ } else {
+ proto_tree_add_uint(tree, hf_reply_pending, tvb, offset, 1, code);
+ }
+ }
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 20);
+ offset += 2;
+
+ /* identifier */
+ proto_tree_add_item(tree, hf_identifier, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* group address */
+ proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
+ offset +=4;
+
+ /* access key */
+ proto_tree_add_item(tree, hf_access_key, tvb, offset, 8, FALSE);
+ offset +=8;
+
+ return offset;
+}
+
+/* dissector for multicast traceroute, rfc???? */
+static int
+dissect_igmp_mtrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+{
+ char *typestr, *blocks = NULL;
+ char buf[20];
+
+ /* All multicast traceroute packets (Query, Request and
+ * Response) have the same fixed header. Request and Response
+ * have one or more response data blocks following this fixed
+ * header. Since Query and Request share the same IGMP type,
+ * the method to differentiate between them is to check the
+ * IGMP packet length. Queries are only
+ * IGMP_TRACEROUTE_HDR_LEN bytes long.
+ */
+ if (type == IGMP_TRACEROUTE_RESPONSE) {
+ int i = (tvb_reported_length_remaining(tvb, offset) - IGMP_TRACEROUTE_HDR_LEN) / IGMP_TRACEROUTE_RSP_LEN;
+ snprintf(buf, sizeof buf, ", %d block%s", i, plurality(i, "", "s"));
+ typestr = "Traceroute Response";
+ blocks = buf;
+ } else if (tvb_reported_length_remaining(tvb, offset) == IGMP_TRACEROUTE_HDR_LEN)
+ typestr = "Traceroute Query";
+ else
+ typestr = "Traceroute Request";
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, typestr);
+ if (blocks) col_append_str(pinfo->cinfo, COL_INFO, blocks);
+ }
+
+ proto_tree_add_uint_format(tree, hf_type, tvb, offset, 1, type,
+ "Type: %s (0x%02x)", typestr, type);
+ offset += 1;
+
+ /* maximum number of hops that the requester wants to trace */
+ proto_tree_add_item(tree, hf_mtrace_max_hops, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ /* group address to be traced */
+ proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* address of multicast source for the path being traced */
+ proto_tree_add_item(tree, hf_mtrace_saddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* address of multicast receiver for the path being traced */
+ proto_tree_add_item(tree, hf_mtrace_raddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* address where the completed traceroute response packet gets sent */
+ proto_tree_add_item(tree, hf_mtrace_rspaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* for multicasted responses, TTL at which to multicast the response */
+ proto_tree_add_item(tree, hf_mtrace_resp_ttl, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* unique identifier for this traceroute request (for e.g. duplicate/delay detection) */
+ proto_tree_add_item(tree, hf_mtrace_q_id, tvb, offset, 3, FALSE);
+ offset += 3;
+
+ /* If this was Query, we only had the fixed header */
+ if (tvb_reported_length_remaining(tvb, offset) == 0)
+ return offset;
+
+ /* Loop through the response data blocks */
+ while (tvb_reported_length_remaining(tvb, offset) >= IGMP_TRACEROUTE_RSP_LEN) {
+ proto_item *bi;
+ proto_tree *block_tree;
+
+ bi = proto_tree_add_text(tree, tvb, offset, IGMP_TRACEROUTE_RSP_LEN,
+ "Response data block: %s -> %s, Proto: %s, Forwarding Code: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)),
+ ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)),
+ val_to_str(tvb_get_guint8(tvb, offset + 28), mtrace_rtg_vals, "Unknown"),
+ val_to_str(tvb_get_guint8(tvb, offset + 31), mtrace_fwd_code_vals, "Unknown"));
+ block_tree = proto_item_add_subtree(bi, ett_mtrace_block);
+
+ /* Query Arrival Time */
+ proto_tree_add_item(block_tree, hf_mtrace_q_arrival, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Incoming Interface Address */
+ proto_tree_add_item(block_tree, hf_mtrace_q_inaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Outgoing Interface Address */
+ proto_tree_add_item(block_tree, hf_mtrace_q_outaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Previous-Hop Router Address */
+ proto_tree_add_item(block_tree, hf_mtrace_q_prevrtr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Input packet count on incoming interface */
+ proto_tree_add_item(block_tree, hf_mtrace_q_inpkt, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Output packet count on outgoing interface */
+ proto_tree_add_item(block_tree, hf_mtrace_q_outpkt, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Total number of packets for this source-group pair */
+ proto_tree_add_item(block_tree, hf_mtrace_q_total, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Routing protocol in use between this and previous-hop router */
+ proto_tree_add_item(block_tree, hf_mtrace_q_rtg_proto, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* TTL that a packet is required to be forwarded */
+ proto_tree_add_item(block_tree, hf_mtrace_q_fwd_ttl, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* Must be zeroed and ignored bit, S bit and src network mask length */
+ proto_tree_add_item(block_tree, hf_mtrace_q_mbz, tvb, offset, 1, FALSE);
+ proto_tree_add_item(block_tree, hf_mtrace_q_s, tvb, offset, 1, FALSE);
+ proto_tree_add_item(block_tree, hf_mtrace_q_src_mask, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* Forwarding information/error code */
+ proto_tree_add_item(block_tree, hf_mtrace_q_fwd_code, tvb, offset, 1, FALSE);
+ offset += 1;
+ }
+
+
+ return offset;
+}
+
+static void
+dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ proto_tree *tree;
+ proto_item *item;
+ int offset = 0;
+ unsigned char type;
+ guint32 dst;
+
+ item = proto_tree_add_item(parent_tree, proto_igmp, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_igmp);
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGMP");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+
+ type = tvb_get_guint8(tvb, offset);
+
+
+ /* version 0 */
+ if ((type&0xf0)==0){
+ offset = dissect_igmp_v0(tvb, pinfo, tree, type, offset);
+ }
+
+
+ switch (type) {
+
+ case IGMP_V1_HOST_MEMBERSHIP_QUERY: /* 0x11 v1/v2/v3 */
+ if ( (pinfo->iplen-pinfo->iphdrlen)>=12 ) {
+ /* version 3 */
+ offset = dissect_igmp_v3_query(tvb, pinfo, tree, type, offset);
+ } else {
+ /* v1 and v2 differs in second byte of header */
+ if (tvb_get_guint8(tvb, offset+1)) {
+ offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
+ } else {
+ offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
+ }
+ }
+ break;
+
+ case IGMP_V1_HOST_MEMBERSHIP_REPORT: /* 0x12 v1 only */
+ offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
+ break;
+
+ case IGMP_DVMRP:
+ offset = dissect_dvmrp(tvb, pinfo, parent_tree, offset);
+ break;
+
+ case IGMP_V1_PIM_ROUTING_MESSAGE:
+ offset = dissect_pimv1(tvb, pinfo, parent_tree, offset);
+ break;
+
+ case IGMP_V2_MEMBERSHIP_REPORT:
+ case IGMP_V2_LEAVE_GROUP:
+ offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
+ break;
+
+ case IGMP_TRACEROUTE_RESPONSE:
+ case IGMP_TRACEROUTE_QUERY_REQ:
+ offset = dissect_igmp_mtrace(tvb, pinfo, tree, type, offset);
+ break;
+
+ case IGMP_V3_MEMBERSHIP_REPORT:
+ offset = dissect_igmp_v3_response(tvb, pinfo, tree, type, offset);
+ break;
+
+ case IGMP_TYPE_0x23:
+ dst = g_htonl(MC_ALL_IGMPV3_ROUTERS);
+ if (!memcmp(pinfo->dst.data, &dst, 4)) {
+ offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
+ }
+ break;
+
+ case IGMP_TYPE_0x24:
+ dst = g_htonl(MC_ALL_ROUTERS);
+ if (!memcmp(pinfo->dst.data, &dst, 4)) {
+ offset = dissect_mrdisc(tvb, pinfo, parent_tree, offset);
+ }
+ dst = g_htonl(MC_ALL_IGMPV3_ROUTERS);
+ if (!memcmp(pinfo->dst.data, &dst, 4)) {
+ offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
+ }
+ break;
+
+ case IGMP_TYPE_0x25:
+ if ( (pinfo->iplen-pinfo->iphdrlen)>=8 ) {
+ /* if len of igmp packet>=8 we assume it is MSNIP */
+ offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
+ } else {
+ /* ok its not MSNIP, check if it might be MRDISC */
+ dst = g_htonl(MC_ALL_ROUTERS);
+ if (!memcmp(pinfo->dst.data, &dst, 4)) {
+ offset = dissect_mrdisc(tvb, pinfo, parent_tree, offset);
+ }
+ }
+ break;
+
+ case IGMP_TYPE_0x26:
+ dst = g_htonl(MC_ALL_ROUTERS);
+ if (!memcmp(pinfo->dst.data, &dst, 4)) {
+ offset = dissect_mrdisc(tvb, pinfo, parent_tree, offset);
+ }
+ break;
+
+ case IGMP_IGAP_JOIN:
+ case IGMP_IGAP_QUERY:
+ case IGMP_IGAP_LEAVE:
+ offset = dissect_igap(tvb, pinfo, parent_tree, offset);
+ break;
+
+ default:
+ offset = dissect_igmp_unknown(tvb, pinfo, tree, type, offset);
+ break;
+ }
+
+
+ proto_item_set_len(item, offset);
+}
+
+void
+proto_register_igmp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_type,
+ { "Type", "igmp.type", FT_UINT8, BASE_HEX,
+ VALS(commands), 0, "IGMP Packet Type", HFILL }},
+
+ { &hf_version,
+ { "IGMP Version", "igmp.version", FT_UINT8, BASE_DEC,
+ NULL, 0, "IGMP Version", HFILL }},
+
+ { &hf_group_type,
+ { "Type Of Group", "igmp.group_type", FT_UINT8, BASE_DEC,
+ VALS(vs_group_type), 0, "IGMP V0 Type Of Group", HFILL }},
+
+ { &hf_reply_code,
+ { "Reply", "igmp.reply", FT_UINT8, BASE_DEC,
+ VALS(vs_reply_code), 0, "IGMP V0 Reply", HFILL }},
+
+ { &hf_reply_pending,
+ { "Reply Pending", "igmp.reply.pending", FT_UINT8, BASE_DEC,
+ NULL, 0, "IGMP V0 Reply Pending, Retry in this many seconds", HFILL }},
+
+ { &hf_checksum,
+ { "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX,
+ NULL, 0, "IGMP Checksum", HFILL }},
+
+ { &hf_checksum_bad,
+ { "Bad Checksum", "igmp.checksum_bad", FT_BOOLEAN, BASE_NONE,
+ NULL, 0, "Bad IGMP Checksum", HFILL }},
+
+ { &hf_identifier,
+ { "Identifier", "igmp.identifier", FT_UINT32, BASE_DEC,
+ NULL, 0, "IGMP V0 Identifier", HFILL }},
+
+ { &hf_access_key,
+ { "Access Key", "igmp.access_key", FT_BYTES, BASE_HEX,
+ NULL, 0, "IGMP V0 Access Key", HFILL }},
+
+ { &hf_max_resp,
+ { "Max Resp Time", "igmp.max_resp", FT_UINT8, BASE_DEC,
+ NULL, 0, "Max Response Time", HFILL }},
+
+ { &hf_supress,
+ { "S", "igmp.s", FT_BOOLEAN, 8,
+ TFS(&tfs_s), IGMP_V3_S, "Supress Router Side Processing", HFILL }},
+
+ { &hf_qrv,
+ { "QRV", "igmp.qrv", FT_UINT8, BASE_DEC,
+ NULL, IGMP_V3_QRV_MASK, "Querier's Robustness Value", HFILL }},
+
+ { &hf_qqic,
+ { "QQIC", "igmp.qqic", FT_UINT8, BASE_DEC,
+ NULL, 0, "Querier's Query Interval Code", HFILL }},
+
+ { &hf_num_src,
+ { "Num Src", "igmp.num_src", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number Of Sources", HFILL }},
+
+ { &hf_saddr,
+ { "Source Address", "igmp.saddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "Source Address", HFILL }},
+
+ { &hf_num_grp_recs,
+ { "Num Group Records", "igmp.num_grp_recs", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number Of Group Records", HFILL }},
+
+ { &hf_record_type,
+ { "Record Type", "igmp.record_type", FT_UINT8, BASE_DEC,
+ VALS(vs_record_type), 0, "Record Type", HFILL }},
+
+ { &hf_aux_data_len,
+ { "Aux Data Len", "igmp.aux_data_len", FT_UINT8, BASE_DEC,
+ NULL, 0, "Aux Data Len, In units of 32bit words", HFILL }},
+
+ { &hf_maddr,
+ { "Multicast Address", "igmp.maddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "Multicast Address", HFILL }},
+
+ { &hf_aux_data,
+ { "Aux Data", "igmp.aux_data", FT_BYTES, BASE_HEX,
+ NULL, 0, "IGMP V3 Auxiliary Data", HFILL }},
+
+ { &hf_max_resp_exp,
+ { "Exponent", "igmp.max_resp.exp", FT_UINT8, BASE_HEX,
+ NULL, IGMP_MAX_RESP_EXP, "Maxmimum Response Time, Exponent", HFILL }},
+
+ { &hf_max_resp_mant,
+ { "Mantissa", "igmp.max_resp.mant", FT_UINT8, BASE_HEX,
+ NULL, IGMP_MAX_RESP_MANT, "Maxmimum Response Time, Mantissa", HFILL }},
+
+ { &hf_mtrace_max_hops,
+ { "# hops", "igmp.mtrace.max_hops", FT_UINT8, BASE_DEC,
+ NULL, 0, "Maxmimum Number of Hops to Trace", HFILL }},
+
+ { &hf_mtrace_saddr,
+ { "Source Address", "igmp.mtrace.saddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "Multicast Source for the Path Being Traced", HFILL }},
+
+ { &hf_mtrace_raddr,
+ { "Receiver Address", "igmp.mtrace.raddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "Multicast Receiver for the Path Being Traced", HFILL }},
+
+ { &hf_mtrace_rspaddr,
+ { "Response Address", "igmp.mtrace.rspaddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "Destination of Completed Traceroute Response", HFILL }},
+
+ { &hf_mtrace_resp_ttl,
+ { "Response TTL", "igmp.mtrace.resp_ttl", FT_UINT8, BASE_DEC,
+ NULL, 0, "TTL for Multicasted Responses", HFILL }},
+
+ { &hf_mtrace_q_id,
+ { "Query ID", "igmp.mtrace.q_id", FT_UINT24, BASE_DEC,
+ NULL, 0, "Identifier for this Traceroute Request", HFILL }},
+
+ { &hf_mtrace_q_arrival,
+ { "Query Arrival", "igmp.mtrace.q_arrival", FT_UINT32, BASE_DEC,
+ NULL, 0, "Query Arrival Time", HFILL }},
+
+ { &hf_mtrace_q_inaddr,
+ { "In itf addr", "igmp.mtrace.q_inaddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "Incoming Interface Address", HFILL }},
+
+ { &hf_mtrace_q_outaddr,
+ { "Out itf addr", "igmp.mtrace.q_outaddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "Outgoing Interface Address", HFILL }},
+
+ { &hf_mtrace_q_prevrtr,
+ { "Previous rtr addr", "igmp.mtrace.q_prevrtr", FT_IPv4, BASE_NONE,
+ NULL, 0, "Previous-Hop Router Address", HFILL }},
+
+ { &hf_mtrace_q_inpkt,
+ { "In pkts", "igmp.mtrace.q_inpkt", FT_UINT32, BASE_DEC,
+ NULL, 0, "Input packet count on incoming interface", HFILL }},
+
+ { &hf_mtrace_q_outpkt,
+ { "Out pkts", "igmp.mtrace.q_outpkt", FT_UINT32, BASE_DEC,
+ NULL, 0, "Output packet count on outgoing interface", HFILL }},
+
+ { &hf_mtrace_q_total,
+ { "S,G pkt count", "igmp.mtrace.q_total", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total number of packets for this source-group pair", HFILL }},
+
+ { &hf_mtrace_q_rtg_proto,
+ { "Rtg Protocol", "igmp.mtrace.q_rtg_proto", FT_UINT8, BASE_DEC,
+ VALS(&mtrace_rtg_vals), 0, "Routing protocol between this and previous hop rtr", HFILL }},
+
+ { &hf_mtrace_q_fwd_ttl,
+ { "FwdTTL", "igmp.mtrace.q_fwd_ttl", FT_UINT8, BASE_DEC,
+ NULL, 0, "TTL required for forwarding", HFILL }},
+
+ { &hf_mtrace_q_mbz,
+ { "MBZ", "igmp.mtrace.q_mbz", FT_UINT8, BASE_HEX,
+ NULL, 0x80, "Must be zeroed on transmission and ignored on reception", HFILL }},
+
+ { &hf_mtrace_q_s,
+ { "S", "igmp.mtrace.q_s", FT_UINT8, BASE_HEX,
+ NULL, 0x40, "Set if S,G packet count is for source network", HFILL }},
+
+ { &hf_mtrace_q_src_mask,
+ { "Src Mask", "igmp.mtrace.q_src_mask", FT_UINT8, BASE_HEX,
+ NULL, 0x3F, "Source mask length. 63 when forwarding on group state", HFILL }},
+
+ { &hf_mtrace_q_fwd_code,
+ { "Forwarding Code", "igmp.mtrace.q_fwd_code", FT_UINT8, BASE_HEX,
+ VALS(&mtrace_fwd_code_vals), 0, "Forwarding information/error code", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_igmp,
+ &ett_group_record,
+ &ett_sqrv_bits,
+ &ett_max_resp,
+ &ett_mtrace_block,
+ };
+
+ proto_igmp = proto_register_protocol("Internet Group Management Protocol",
+ "IGMP", "igmp");
+ proto_register_field_array(proto_igmp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_igmp(void)
+{
+ dissector_handle_t igmp_handle;
+
+ igmp_handle = create_dissector_handle(dissect_igmp, proto_igmp);
+ dissector_add("ip.proto", IP_PROTO_IGMP, igmp_handle);
+}
diff --git a/epan/dissectors/packet-igmp.h b/epan/dissectors/packet-igmp.h
new file mode 100644
index 0000000000..b37ac5729e
--- /dev/null
+++ b/epan/dissectors/packet-igmp.h
@@ -0,0 +1,32 @@
+/* packet-igmp.h 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Declarations of routines for IGMP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_MSNIP_H__
+#define __PACKET_MSNIP_H__
+
+void igmp_checksum(proto_tree *tree, tvbuff_t *tvb, int hf_index,
+ int hf_index_bad, packet_info *pinfo, guint len);
+
+#endif
+
diff --git a/epan/dissectors/packet-igrp.c b/epan/dissectors/packet-igrp.c
new file mode 100644
index 0000000000..bbbc4b60be
--- /dev/null
+++ b/epan/dissectors/packet-igrp.c
@@ -0,0 +1,249 @@
+/* packet-igrp.c
+ * Routines for IGRP dissection
+ * Copyright 2000, Paul Ionescu <paul@acorp.ro>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-syslog.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "ipproto.h"
+
+#define IGRP_HEADER_LENGTH 12
+#define IGRP_ENTRY_LENGTH 14
+
+static gint proto_igrp = -1;
+static gint hf_igrp_update = -1;
+static gint hf_igrp_as = -1;
+
+static gint ett_igrp = -1;
+static gint ett_igrp_vektor = -1;
+static gint ett_igrp_net = -1;
+
+static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network);
+
+static void dissect_igrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 ver_and_opcode,version,opcode,update,network;
+ gint offset=IGRP_HEADER_LENGTH;
+ guint16 as,net1,net2,net3;
+ proto_item *ti;
+ proto_tree *igrp_tree, *igrp_vektor_tree;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGRP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ver_and_opcode = tvb_get_guint8(tvb,0);
+ update = tvb_get_guint8(tvb,1);
+ as = tvb_get_ntohs(tvb,2);
+
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ switch (ver_and_opcode) {
+ case 0x11:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Response" );
+ break;
+ case 0x12:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Request" );
+ break;
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown version or opcode");
+ }
+ }
+
+
+
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_igrp, tvb, 0, -1,
+ "Cisco IGRP");
+
+ igrp_tree = proto_item_add_subtree(ti, ett_igrp);
+
+ version = (ver_and_opcode&0xf0)>>4 ; /* version is the fist half of the byte */
+ opcode = ver_and_opcode&0x0f ; /* opcode is the last half of the byte */
+
+ proto_tree_add_text(igrp_tree, tvb, 0,1,"IGRP Version : %d %s",version,(version==1?" ":" - Unknown Version, The dissection may be innacurate"));
+ proto_tree_add_text(igrp_tree, tvb, 0,1,"Command : %d %s",opcode,(opcode==1?"(Response)":"(Request)"));
+ proto_tree_add_uint(igrp_tree, hf_igrp_update, tvb, 1,1, update);
+ proto_tree_add_uint(igrp_tree, hf_igrp_as, tvb, 2,2,as);
+
+ net1 = tvb_get_ntohs(tvb,4);
+ net2 = tvb_get_ntohs(tvb,6);
+ net3 = tvb_get_ntohs(tvb,8);
+
+ /* this is a ugly hack to find the first byte of the IP source address */
+ network = pinfo->net_src.data[0];
+
+ ti = proto_tree_add_text(igrp_tree, tvb, 4,2,"Interior routes : %d",net1);
+ for( ; net1>0 ; net1-- )
+ {
+ igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_vektor);
+ next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
+ dissect_vektor_igrp (next_tvb,igrp_vektor_tree,network);
+ offset+=IGRP_ENTRY_LENGTH;
+ }
+
+ ti = proto_tree_add_text(igrp_tree, tvb, 6,2,"System routes : %d",net2);
+ for( ; net2>0 ; net2-- )
+ {
+ igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_vektor);
+ next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
+ dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
+ offset+=IGRP_ENTRY_LENGTH;
+ }
+
+ ti = proto_tree_add_text(igrp_tree, tvb, 8,2,"Exterior routes : %d",net3);
+ for( ; net3>0 ; net3-- )
+ {
+ igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_vektor);
+ next_tvb = tvb_new_subset(tvb, offset, IGRP_ENTRY_LENGTH, -1);
+ dissect_vektor_igrp (next_tvb,igrp_vektor_tree,0);
+ offset+=IGRP_ENTRY_LENGTH;
+ }
+
+ proto_tree_add_text(igrp_tree, tvb, 10,2,"Checksum = 0x%4x",tvb_get_ntohs(tvb,10));
+
+ }
+ return;
+}
+
+static void dissect_vektor_igrp (tvbuff_t *tvb, proto_tree *igrp_vektor_tree, guint8 network)
+{
+ proto_item *ti;
+ guint8 *ptr_addr,addr[5];
+
+ addr[0]=network;
+ addr[1]=tvb_get_guint8(tvb,0);
+ addr[2]=tvb_get_guint8(tvb,1);
+ addr[3]=tvb_get_guint8(tvb,2);
+ addr[4]=0;
+
+ ptr_addr=addr;
+ if (network==0) ptr_addr=&addr[1];
+
+ ti = proto_tree_add_text (igrp_vektor_tree, tvb, 0 ,14,
+ "Entry for network %s", ip_to_str(ptr_addr)) ;
+ igrp_vektor_tree = proto_item_add_subtree(ti,ett_igrp_net);
+ proto_tree_add_text (igrp_vektor_tree, tvb, 0 ,3,"Network = %s",ip_to_str(ptr_addr)) ;
+ proto_tree_add_text (igrp_vektor_tree, tvb, 3 ,3,"Delay = %d",tvb_get_ntoh24(tvb,3)) ;
+ proto_tree_add_text (igrp_vektor_tree, tvb, 6 ,3,"Bandwidth = %d",tvb_get_ntoh24(tvb,6)) ;
+ proto_tree_add_text (igrp_vektor_tree, tvb, 9 ,2,"MTU = %d bytes",tvb_get_ntohs(tvb,9)) ;
+ proto_tree_add_text (igrp_vektor_tree, tvb, 11,1,"Reliability = %d",tvb_get_guint8(tvb,11)) ;
+ proto_tree_add_text (igrp_vektor_tree, tvb, 12,1,"Load = %d",tvb_get_guint8(tvb,12)) ;
+ proto_tree_add_text (igrp_vektor_tree, tvb, 13,1,"Hop count = %d hops",tvb_get_guint8(tvb,13)) ;
+}
+
+
+/* Register the protocol with Ethereal */
+void proto_register_igrp(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+
+ { &hf_igrp_update,
+ { "Update Release", "igrp.update",
+ FT_UINT8, BASE_DEC, NULL, 0x0 ,
+ "Update Release number", HFILL }
+ },
+ { &hf_igrp_as,
+ { "Autonomous System", "igrp.as",
+ FT_UINT16, BASE_DEC, NULL, 0x0 ,
+ "Autonomous System number", HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_igrp,
+ &ett_igrp_vektor,
+ &ett_igrp_net
+ };
+
+ /* Register the protocol name and description */
+ proto_igrp = proto_register_protocol("Cisco Interior Gateway Routing Protocol",
+ "IGRP", "igrp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_igrp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_igrp(void)
+{
+ dissector_handle_t igrp_handle;
+
+ igrp_handle = create_dissector_handle(dissect_igrp, proto_igrp);
+ dissector_add("ip.proto", IP_PROTO_IGRP, igrp_handle);
+}
+
+/* IGRP Packet structure:
+
+HEADER structure + k * VECTOR structure
+where: k = (Number of Interior routes) + (Number of System routes) + (Number of Exterior routes)
+
+HEADER structure is 12 bytes as follows :
+
+4 bits Version (only version 1 is defined)
+4 bits Opcode (1=Replay, 2=Request)
+8 bits Update Release
+16 bits Autonomous system number
+16 bits Number of Interior routes
+16 bits Number of System routes
+16 bits Number of Exterior routes
+16 bits Checksum
+-------
+12 bytes in header
+
+VECTOR structure is 14 bytes as follows :
+24 bits Network
+24 bits Delay
+24 bits Bandwidth
+16 bits MTU
+8 bits Reliability
+8 bits Load
+8 bits Hop count
+-------
+14 bytes in 1 vector
+
+It is interesting how is coded an ip network address in 3 bytes because IGRP is a classful routing protocol:
+If it is a interior route then this 3 bytes are the final bytes, and the first one is taken from the source ip address of the ip packet
+If it is a system route or a exterior route then this 3 bytes are the first three and the last byte is not important
+
+If the Delay is 0xFFFFFF then the network is unreachable
+
+*/
diff --git a/epan/dissectors/packet-image-gif.c b/epan/dissectors/packet-image-gif.c
new file mode 100644
index 0000000000..c58d5f5a56
--- /dev/null
+++ b/epan/dissectors/packet-image-gif.c
@@ -0,0 +1,711 @@
+/* packet-image-gif.c
+ *
+ * Routines for image/gif media dissection
+ * Copyright 2003, 2004, Olivier Biot.
+ *
+ * $Id$
+ *
+ * Refer to the AUTHORS file or the AUTHORS section in the man page
+ * for contacting the author(s) of this file.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Compuserve GIF media decoding functionality provided by Olivier Biot.
+ *
+ * The two GIF specifications are found at several locations, such as W3C:
+ * http://www.w3.org/Graphics/GIF/spec-gif87.txt
+ * http://www.w3.org/Graphics/GIF/spec-gif89a.txt
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Edit this file with 4-space tabulation */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+
+/* General-purpose debug logger.
+ * Requires double parentheses because of variable arguments of printf().
+ *
+ * Enable debug logging for GIF by defining AM_CFLAGS
+ * so that it contains "-DDEBUG_image_gif" or "-DDEBUG_image"
+ */
+#if (defined(DEBUG_image_gif) || defined(DEBUG_image))
+#define DebugLog(x) \
+ printf("%s:%u: ", __FILE__, __LINE__); \
+ printf x; \
+ fflush(stdout)
+#else
+#define DebugLog(x) ;
+#endif
+
+#define PLURALIZE(x) ((x) == 1 ? "" : "s")
+
+#define IMG_GIF "image-gif"
+
+/************************** Variable declarations **************************/
+
+static const value_string vals_true_false[] = {
+ { 0, "False" },
+ { 1, "True" },
+ { 0, NULL },
+};
+
+static const value_string vals_extensions[] = {
+ { 0xF9, "Graphics Control" },
+ { 0xFE, "Comment" },
+ { 0xFF, "Application" },
+ { 0x01, "Plain Text" },
+ { 0x00, NULL, },
+};
+
+enum {
+ GIF_UNKNOWN = 0,
+ GIF_87a = 0x87,
+ GIF_89a = 0x89,
+ GIF_ERROR = 0xFF
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_gif = -1;
+
+/* header fields */
+/* GIF signature */
+static gint hf_version = -1;
+/* Screen descriptor */
+static gint hf_screen_width = -1;
+static gint hf_screen_height = -1;
+static gint hf_global_color_map_present = -1;
+static gint hf_global_color_resolution = -1;
+static gint hf_global_color_map_ordered = -1; /* GIF89a */
+static gint hf_global_image_bpp = -1;
+/* Only makes sense if the global color map is present: */
+static gint hf_background_color = -1;
+static gint hf_pixel_aspect_ratio = -1; /* GIF89a */
+static gint hf_global_color_map = -1;
+
+/* Image descriptor */
+static gint hf_image_left = -1;
+static gint hf_image_top = -1;
+static gint hf_image_width = -1;
+static gint hf_image_height = -1;
+static gint hf_local_color_map_present = -1;
+static gint hf_local_color_resolution = -1;
+static gint hf_local_color_map_ordered = -1; /* GIF89a */
+static gint hf_local_image_bpp = -1;
+static gint hf_local_color_map = -1;
+
+static gint hf_extension = -1;
+static gint hf_extension_label = -1;
+static gint hf_image = -1;
+static gint hf_image_code_size = -1;
+
+/* Trailer (end of GIF data stream) */
+static gint hf_trailer = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_gif = -1;
+static gint ett_global_flags = -1;
+static gint ett_local_flags = -1;
+static gint ett_extension = -1;
+static gint ett_image = -1;
+
+
+/**************** GIF related declarations and definitions ****************/
+
+
+/************************** Function prototypes **************************/
+
+
+static void
+dissect_gif(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+void
+proto_register_gif(void);
+
+
+/****************** GIF protocol dissection functions ******************/
+
+/* There are two Compuserve GIF standards: GIF87a and GIF89a. GIF image files
+ * always convey their version in the first 6 bytes, written as an US-ASCII
+ * string representation of the version: "GIF87a" or "GIF89a".
+ */
+
+static void
+dissect_gif(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *gif_tree; /* Main GIF tree */
+ proto_tree *subtree; /* Main GIF tree */
+ guint offset = 0, len = 0;
+ guint8 peek;
+ gboolean color_map_present;
+ guint8 color_resolution;
+ guint8 image_bpp;
+ guint tvb_len = tvb_reported_length(tvb);
+ char *str = tvb_get_string(tvb, 0, 6);
+ guint8 version;
+
+ /* Check whether we're processing a GIF object */
+ if (strcmp(str, "GIF87a") == 0) {
+ version = GIF_87a;
+ } else if (strcmp(str, "GIF89a") == 0) {
+ version = GIF_89a;
+ } else if (strncmp(str,"GIF", 3) == 0) {
+ version = GIF_UNKNOWN;
+ } else {
+ /* Not a GIF image! */
+ version = GIF_ERROR;
+ g_free(str);
+ return;
+ }
+ /* Add summary to INFO column if it is enabled */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", str);
+
+ /* In order to speed up dissection, do not add items to the protocol tree
+ * if it is not visible. However, compute the values that are needed for
+ * correct protocol dissection if they have more meaning than just adding
+ * items to the protocol tree.
+ */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_gif, tvb, 0, -1, TRUE);
+ proto_item_append_text(ti, ", Version: %s", str);
+ g_free(str);
+ gif_tree = proto_item_add_subtree(ti, ett_gif);
+ /* GIF signature */
+ ti = proto_tree_add_item(gif_tree, hf_version, tvb, 0, 6, TRUE);
+ if (version == GIF_UNKNOWN) {
+ proto_item_append_text(ti, " <Error: unknown GIF version>");
+ }
+ /* Screen descriptor */
+ proto_tree_add_item(gif_tree, hf_screen_width, tvb, 6, 2, TRUE);
+ proto_tree_add_item(gif_tree, hf_screen_height, tvb, 8, 2, TRUE);
+
+ peek = tvb_get_guint8(tvb, 10);
+ /* Bitfield gccc 0ppp
+ * g... .... : global color map present
+ * .ccc .... : color resolution in bits (add one)
+ * .... 0... : GIF87a - reserved (no use)
+ * GIF89a - ordered (most important color 1st)
+ * .... .ppp : bits per pixel in image (add one)
+ */
+ color_map_present = peek & 0x80;
+ color_resolution = 1 + ((peek & 0x60) >> 4);
+ image_bpp = 1 + (peek & 0x07);
+
+ ti = proto_tree_add_text(gif_tree, tvb, 10, 1,
+ "Global settings:");
+ if (color_map_present)
+ proto_item_append_text(ti, " (Global color table present)");
+ proto_item_append_text(ti,
+ " (%u bit%s per color) (%u bit%s per pixel)",
+ color_resolution, PLURALIZE(color_resolution),
+ image_bpp, PLURALIZE(image_bpp));
+ subtree = proto_item_add_subtree(ti, ett_global_flags);
+ proto_tree_add_item(subtree, hf_global_color_map_present,
+ tvb, 10, 1, TRUE);
+ proto_tree_add_item(subtree, hf_global_color_resolution,
+ tvb, 10, 1, TRUE);
+ if (version == GIF_89a) {
+ proto_tree_add_item(subtree, hf_global_color_map_ordered,
+ tvb, 10, 1, TRUE);
+ }
+ proto_tree_add_item(subtree, hf_global_image_bpp,
+ tvb, 10, 1, TRUE);
+
+ /* Background color */
+ proto_tree_add_item(gif_tree, hf_background_color,
+ tvb, 11, 1, TRUE);
+
+ /* byte at offset 12 is 0x00 - reserved in GIF87a but encodes the
+ * pixel aspect ratio in GIF89a as:
+ * aspect-ratio = (15 + pixel-aspect-ratio) / 64
+ * where the aspect-ratio is not computed if pixel-aspect-ratio == 0
+ */
+ if (version == GIF_89a) {
+ peek = tvb_get_guint8(tvb, 12);
+ if (peek) {
+ /* Only display if different from 0 */
+ proto_tree_add_uint_format(gif_tree, hf_pixel_aspect_ratio,
+ tvb, 12, 1, peek,
+ "%u, yields an aspect ratio of (15 + %u) / 64 = %.2f",
+ peek, peek, (float)(15 + peek) / 64.0);
+ }
+ }
+
+ /* Global color map
+ * If present, it takes 2 ^ (image_bpp) byte tuples (R, G, B)
+ * that contain the Red, Green and Blue intensity of the colors
+ * in the Global Color Map */
+ if (color_map_present) {
+ len = 3 * (1 << image_bpp);
+ proto_tree_add_item(gif_tree, hf_global_color_map,
+ tvb, 13, len, TRUE);
+ } else {
+ len = 0;
+ }
+ offset = 13 + len;
+ /* From now on, a set of images prefixed with the image separator
+ * character 0x2C (',') will appear in the byte stream. Each image
+ * hence consists of:
+ * - The image separator character 0x2C
+ * - Image left (16 bits LSB first): pixels from left border
+ * - Image top (16 bits LSB first): pixels from to border
+ * - Image width (16 bits LSB first)
+ * - Image height (16 bits LSB first)
+ * - A bitfield MI00 0ppp
+ * M... .... : Use global color map if unset (ignore ppp);
+ * if set a local color map will be defined.
+ * .I.. .... : Image formatted in interlaced order if set;
+ * otherwise it is plain sequential order
+ * ..0. .... : GIF87a - Reserved
+ * ..s. .... GIF89a - Set if local color map is ordered
+ * ...0 0... : Reserved
+ * .... .ppp : bits per pixel in image (add one)
+ * - If the local color map bit is set, then a local color table follows
+ * with length = 3 x 2 ^ (1 + bits per pixel)
+ * - The raster data
+ *
+ * NOTE that the GIF specification only requires that:
+ * image left + image width <= screen width
+ * image top + image height <= screen height
+ *
+ * The Raster Data is encoded as follows:
+ * - Code size (1 byte)
+ * - Blocks consisting of
+ * o Byte count (1 byte): number of bytes in the block
+ * o Data bytes: as many as specified in the byte count
+ * End of data is given with an empty block (byte count == 0).
+ *
+ *
+ * GIF terminator
+ * This is a synchronization method, based on the final character 0xB3
+ * (';') at the end of an image
+ *
+ *
+ * GIF extension
+ * This is a block of data encoded as:
+ * - The GIF extension block introducer 0x21 ('!')
+ * - The extension function code (1 byte)
+ * - Blocks consisting of
+ * o Byte count (1 byte): number of bytes in the block
+ * o Data bytes: as many as specified in the byte count
+ * End of data is given with an empty block (byte count == 0).
+ *
+ * NOTE that the GIF extension block can only appear at the following
+ * locations:
+ * - Immediately before an Image Descriptor
+ * - Before the GIF termination character
+ */
+ while (offset < tvb_len) {
+ peek = tvb_get_guint8(tvb, offset);
+ if (peek == 0x21) { /* GIF extension block */
+ guint32 item_len = 2; /* Fixed header consisting of:
+ * 1 byte : 0x21
+ * 1 byte : extension_label
+ */
+
+ ti = proto_tree_add_item(gif_tree, hf_extension,
+ tvb, offset, 1, TRUE);
+ subtree = proto_item_add_subtree(ti, ett_extension);
+ offset++;
+ proto_tree_add_item(subtree, hf_extension_label,
+ tvb, offset, 1, TRUE);
+ peek = tvb_get_guint8(tvb, offset);
+ proto_item_append_text(ti, ": %s",
+ val_to_str(peek, vals_extensions,
+ "<Warning: Unknown extension 0x%02X>"));
+ offset++;
+ do {
+ /* Read length of data block */
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1 + len,
+ "Data block (length = %u)", len);
+ offset += (1 + len);
+ item_len += (1 + len);
+ } while (len > 0);
+ proto_item_set_len(ti, item_len);
+ } else if (peek == 0x2C) { /* Image separator */
+ proto_tree *subtree2;
+ proto_item *ti2;
+ guint32 item_len = 11; /* Fixed header consisting of:
+ * 1 byte : 0x2C
+ * 2 bytes: image_left
+ * 2 bytes: image_top
+ * 2 bytes: image_width
+ * 2 bytes: image height
+ * 1 byte : packed bit field
+ * 1 byte : image code size
+ */
+
+ ti = proto_tree_add_item(gif_tree, hf_image,
+ tvb, offset, 1, TRUE);
+ subtree = proto_item_add_subtree(ti, ett_image);
+ offset++;
+ /* Screen descriptor */
+ proto_tree_add_item(subtree, hf_image_left,
+ tvb, offset, 2, TRUE); offset += 2;
+ proto_tree_add_item(subtree, hf_image_top,
+ tvb, offset, 2, TRUE); offset += 2;
+ proto_tree_add_item(subtree, hf_image_width,
+ tvb, offset, 2, TRUE); offset += 2;
+ proto_tree_add_item(subtree, hf_image_height,
+ tvb, offset, 2, TRUE); offset += 2;
+ /* bit field */
+ peek = tvb_get_guint8(tvb, offset);
+ color_map_present = peek & 0x80;
+ color_resolution = 1 + ((peek & 0x60) >> 4);
+ image_bpp = 1 + (peek & 0x07);
+
+ ti2 = proto_tree_add_text(subtree, tvb, offset, 1,
+ "Local settings:");
+ if (color_map_present)
+ proto_item_append_text(ti2, " (Local color table present)");
+ proto_item_append_text(ti2,
+ " (%u bit%s per color) (%u bit%s per pixel)",
+ color_resolution, PLURALIZE(color_resolution),
+ image_bpp, PLURALIZE(image_bpp));
+ subtree2 = proto_item_add_subtree(ti2, ett_local_flags);
+ proto_tree_add_item(subtree2, hf_local_color_map_present,
+ tvb, offset, 1, TRUE);
+ proto_tree_add_item(subtree2, hf_local_color_resolution,
+ tvb, offset, 1, TRUE);
+ if (version == GIF_89a) {
+ proto_tree_add_item(subtree2, hf_local_color_map_ordered,
+ tvb, offset, 1, TRUE);
+ }
+ proto_tree_add_item(subtree2, hf_global_image_bpp,
+ tvb, offset, 1, TRUE);
+ offset++;
+
+ /* Local color map
+ * If present, it takes 2 ^ (image_bpp) byte tuples (R, G, B)
+ * that contain the Red, Green and Blue intensity of the colors
+ * in the Local Color Map */
+ if (color_map_present) {
+ len = 3 * (1 << image_bpp);
+ proto_tree_add_item(subtree, hf_local_color_map,
+ tvb, offset, len, TRUE);
+ } else {
+ len = 0;
+ }
+ offset += len;
+ item_len += len;
+
+ proto_tree_add_item(subtree, hf_image_code_size,
+ tvb, offset, 1, TRUE);
+ offset++;
+ do {
+ /* Read length of data block */
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1 + len,
+ "Data block (length = %u)", len);
+ offset += 1 + len;
+ item_len += (1 + len);
+ } while (len > 0);
+ proto_item_set_len(ti, item_len);
+ } else {
+ /* GIF processing stops at this very byte */
+ proto_tree_add_item(gif_tree, hf_trailer,
+ tvb, offset, 1, TRUE);
+ break;
+ }
+ } /* while */
+ }
+}
+
+
+/****************** Register the protocol with Ethereal ******************/
+
+
+/* This format is required because a script is used to build the C function
+ * that calls the protocol registration. */
+
+void
+proto_register_gif(void)
+{
+ /*
+ * Setup list of header fields.
+ */
+ static hf_register_info hf[] = {
+ /*
+ * GIF signature and version
+ */
+ { &hf_version,
+ { "Version",
+ IMG_GIF ".version",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "GIF Version",
+ HFILL
+ }
+ },
+
+ /*
+ * Logical screen descriptor
+ */
+ { &hf_screen_width,
+ { "Screen width",
+ IMG_GIF ".screen.width",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Screen width",
+ HFILL
+ }
+ },
+ { &hf_screen_height,
+ { "Screen height",
+ IMG_GIF ".screen.height",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Screen height",
+ HFILL
+ }
+ },
+ { &hf_global_color_map_present,
+ { "Global color map is present",
+ IMG_GIF ".global.color_map.present",
+ FT_UINT8, BASE_DEC, VALS(vals_true_false), 0x80,
+ "Indicates if the global color map is present",
+ HFILL
+ }
+ },
+ { &hf_global_color_resolution,
+ { "Bits per color minus 1",
+ IMG_GIF ".global.color_bpp",
+ FT_UINT8, BASE_DEC, NULL, 0x70,
+ "The number of bits per color is one plus the field value.",
+ HFILL
+ }
+ },
+ { &hf_global_color_map_ordered,
+ { "Global color map is ordered",
+ IMG_GIF ".global.color_map.ordered",
+ FT_UINT8, BASE_DEC, VALS(vals_true_false), 0x08,
+ "Indicates whether the global color map is ordered.",
+ HFILL
+ }
+ },
+ { &hf_global_image_bpp,
+ { "Image bits per pixel minus 1",
+ IMG_GIF ".global.bpp",
+ FT_UINT8, BASE_DEC, NULL, 0x07,
+ "The number of bits per pixel is one plus the field value.",
+ HFILL
+ }
+ },
+ { &hf_background_color,
+ { "Background color index",
+ IMG_GIF ".image_background_index",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Index of the background color in the color map.",
+ HFILL
+ }
+ },
+ { &hf_pixel_aspect_ratio,
+ { "Global pixel aspect ratio",
+ IMG_GIF ".global.pixel_aspect_ratio",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Gives an approximate value of the aspect ratio of the pixels.",
+ HFILL
+ }
+ },
+ { &hf_global_color_map,
+ { "Global color map",
+ IMG_GIF ".global.color_map",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ "Global color map.",
+ HFILL
+ }
+ },
+
+ /*
+ * Local color map (part of image)
+ */
+ { &hf_local_color_map_present,
+ { "Local color map is present",
+ IMG_GIF ".local.color_map.present",
+ FT_UINT8, BASE_DEC, VALS(vals_true_false), 0x80,
+ "Indicates if the local color map is present",
+ HFILL
+ }
+ },
+ { &hf_local_color_resolution,
+ { "Bits per color minus 1",
+ IMG_GIF ".local.color_bpp",
+ FT_UINT8, BASE_DEC, NULL, 0x70,
+ "The number of bits per color is one plus the field value.",
+ HFILL
+ }
+ },
+ { &hf_local_color_map_ordered,
+ { "Local color map is ordered",
+ IMG_GIF ".local.color_map.ordered",
+ FT_UINT8, BASE_DEC, VALS(vals_true_false), 0x08,
+ "Indicates whether the local color map is ordered.",
+ HFILL
+ }
+ },
+ { &hf_local_image_bpp,
+ { "Image bits per pixel minus 1",
+ IMG_GIF ".local.bpp",
+ FT_UINT8, BASE_DEC, NULL, 0x07,
+ "The number of bits per pixel is one plus the field value.",
+ HFILL
+ }
+ },
+ { &hf_local_color_map,
+ { "Local color map",
+ IMG_GIF ".local.color_map",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ "Local color map.",
+ HFILL
+ }
+ },
+
+ /*
+ * Extension
+ */
+ { &hf_extension,
+ { "Extension",
+ IMG_GIF ".extension",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Extension.",
+ HFILL
+ }
+ },
+ { &hf_extension_label,
+ { "Extension label",
+ IMG_GIF ".extension.label",
+ FT_UINT8, BASE_HEX, VALS(vals_extensions), 0x00,
+ "Extension label.",
+ HFILL
+ }
+ },
+
+ /*
+ * Image
+ */
+ { &hf_image,
+ { "Image",
+ IMG_GIF ".image",
+ FT_NONE, BASE_NONE, NULL, 0x80,
+ "Image.",
+ HFILL
+ }
+ },
+ { &hf_image_left,
+ { "Image left position",
+ IMG_GIF ".image.left",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Offset between left of Screen and left of Image.",
+ HFILL
+ }
+ },
+ { &hf_image_top,
+ { "Image top position",
+ IMG_GIF ".image.top",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Offset between top of Screen and top of Image.",
+ HFILL
+ }
+ },
+ { &hf_image_width,
+ { "Image width",
+ IMG_GIF ".image.width",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Image width.",
+ HFILL
+ }
+ },
+ { &hf_image_height,
+ { "Image height",
+ IMG_GIF ".image.height",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Image height.",
+ HFILL
+ }
+ },
+ { &hf_image_code_size,
+ { "LZW minimum code size",
+ IMG_GIF ".image.code_size",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Minimum code size for the LZW compression.",
+ HFILL
+ }
+ },
+ /*
+ * Trailer
+ */
+ { &hf_trailer,
+ { "Trailer (End of the GIF stream)",
+ IMG_GIF ".end",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "This byte tells the decoder that the data stream is finished.",
+ HFILL
+ }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_gif,
+ &ett_global_flags,
+ &ett_local_flags,
+ &ett_extension,
+ &ett_image,
+ };
+
+ /* Register the protocol name and description */
+ proto_gif = proto_register_protocol(
+ "Compuserve GIF",
+ "GIF image",
+ IMG_GIF
+ );
+
+ /* Required function calls to register the header fields
+ * and subtrees used */
+ proto_register_field_array(proto_gif, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("image-gif", dissect_gif, proto_gif);
+}
+
+
+void
+proto_reg_handoff_gif(void)
+{
+ dissector_handle_t gif_handle;
+
+ gif_handle = create_dissector_handle(dissect_gif, proto_gif);
+
+ /* Register the GIF media type */
+ dissector_add_string("media_type", "image/gif", gif_handle);
+}
diff --git a/epan/dissectors/packet-image-jfif.c b/epan/dissectors/packet-image-jfif.c
new file mode 100644
index 0000000000..666584c84d
--- /dev/null
+++ b/epan/dissectors/packet-image-jfif.c
@@ -0,0 +1,1198 @@
+/* packet-image-jfif.c
+ *
+ * Routines for JFIF image/jpeg media dissection
+ * Copyright 2004, Olivier Biot.
+ *
+ * $Id$
+ *
+ * Refer to the AUTHORS file or the AUTHORS section in the man page
+ * for contacting the author(s) of this file.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * JFIF media decoding functionality provided by Olivier Biot.
+ *
+ * The JFIF specifications are found at several locations, such as:
+ * http://www.jpeg.org/public/jfif.pdf
+ * http://www.w3.org/Graphics/JPEG/itu-t81.pdf
+ *
+ * The Exif specifications are found at several locations, such as:
+ * http://www.exif.org/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Edit this file with 4-space tabulation */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+
+/* General-purpose debug logger.
+ * Requires double parentheses because of variable arguments of printf().
+ *
+ * Enable debug logging for JFIF by defining AM_CFLAGS
+ * so that it contains "-DDEBUG_image_jfif" or "-DDEBUG_image"
+ */
+#if (defined(DEBUG_image_jfif) || defined(DEBUG_image))
+#define DebugLog(x) \
+ printf("%s:%u: ", __FILE__, __LINE__); \
+ printf x; \
+ fflush(stdout)
+#else
+#define DebugLog(x) ;
+#endif
+
+#define PLURALIZE(x) ((x) == 1 ? "" : "s")
+
+#define IMG_JFIF "image-jfif"
+
+/************************** Variable declarations **************************/
+
+#define MARKER_TEM 0xFF01
+
+/* 0xFF02 -- 0xFFBF are reserved */
+
+#define MARKER_SOF0 0xFFC0
+#define MARKER_SOF1 0xFFC1
+#define MARKER_SOF2 0xFFC2
+#define MARKER_SOF3 0xFFC3
+
+#define MARKER_DHT 0xFFC4
+
+#define MARKER_SOF5 0xFFC5
+#define MARKER_SOF6 0xFFC6
+#define MARKER_SOF7 0xFFC7
+#define MARKER_SOF8 0xFFC8
+#define MARKER_SOF9 0xFFC9
+#define MARKER_SOF10 0xFFCA
+#define MARKER_SOF11 0xFFCB
+
+#define MARKER_DAC 0xFFCC
+
+#define MARKER_SOF13 0xFFCD
+#define MARKER_SOF14 0xFFCE
+#define MARKER_SOF15 0xFFCF
+
+#define MARKER_RST0 0xFFD0
+#define MARKER_RST1 0xFFD1
+#define MARKER_RST2 0xFFD2
+#define MARKER_RST3 0xFFD3
+#define MARKER_RST4 0xFFD4
+#define MARKER_RST5 0xFFD5
+#define MARKER_RST6 0xFFD6
+#define MARKER_RST7 0xFFD7
+
+#define MARKER_FFDB 0xFFDB
+#define MARKER_SOI 0xFFD8
+#define MARKER_EOI 0xFFD9
+#define MARKER_SOS 0xFFDA
+#define MARKER_DQT 0xFFDB
+#define MARKER_DNL 0xFFDC
+#define MARKER_DRI 0xFFDD
+#define MARKER_DHP 0xFFDE
+#define MARKER_EXP 0xFFDF
+
+#define MARKER_APP0 0xFFE0
+#define MARKER_APP1 0xFFE1
+#define MARKER_APP2 0xFFE2
+#define MARKER_APP3 0xFFE3
+#define MARKER_APP4 0xFFE4
+#define MARKER_APP5 0xFFE5
+#define MARKER_APP6 0xFFE6
+#define MARKER_APP7 0xFFE7
+#define MARKER_APP8 0xFFE8
+#define MARKER_APP9 0xFFE9
+#define MARKER_APP10 0xFFEA
+#define MARKER_APP11 0xFFEB
+#define MARKER_APP12 0xFFEC
+#define MARKER_APP13 0xFFED
+#define MARKER_APP14 0xFFEE
+#define MARKER_APP15 0xFFEF
+
+#define MARKER_JPG0 0xFFF0
+#define MARKER_JPG1 0xFFF1
+#define MARKER_JPG2 0xFFF2
+#define MARKER_JPG3 0xFFF3
+#define MARKER_JPG4 0xFFF4
+#define MARKER_JPG5 0xFFF5
+#define MARKER_JPG6 0xFFF6
+#define MARKER_JPG7 0xFFF7
+#define MARKER_JPG8 0xFFF8
+#define MARKER_JPG9 0xFFF9
+#define MARKER_JPG10 0xFFFA
+#define MARKER_JPG11 0xFFFB
+#define MARKER_JPG12 0xFFFC
+#define MARKER_JPG13 0xFFFD
+
+#define MARKER_COM 0xFFFE
+
+#define marker_has_length(marker) ( ! ( \
+ ((marker) == MARKER_TEM) \
+ || ((marker) == MARKER_SOI) \
+ || ((marker) == MARKER_EOI) \
+ || ( ((marker) >= MARKER_RST0) && ((marker) <= MARKER_RST7) ) \
+ ) )
+
+
+static const value_string vals_marker[] = {
+ { MARKER_TEM, "Reserved - For temporary private use in arithmetic coding" },
+ { MARKER_SOF0, "Start of Frame (non-differential, Huffman coding) - Baseline DCT" },
+ { MARKER_SOF1, "Start of Frame (non-differential, Huffman coding) - Extended sequential DCT" },
+ { MARKER_SOF2, "Start of Frame (non-differential, Huffman coding) - Progressive DCT" },
+ { MARKER_SOF3, "Start of Frame (non-differential, Huffman coding) - Lossless (sequential)" },
+ { MARKER_DHT, "Define Huffman table(s)" },
+ { MARKER_SOF5, "Start of Frame (differential, Huffman coding) - Differential sequential DCT" },
+ { MARKER_SOF6, "Start of Frame (differential, Huffman coding) - Differential progressive DCT" },
+ { MARKER_SOF7, "Start of Frame (differential, Huffman coding) - Differential lossless (sequential)" },
+ { MARKER_SOF8, "Start of Frame (non-differential, arithmetic coding) - Reserved for JPEG extensions" },
+ { MARKER_SOF9, "Start of Frame (non-differential, arithmetic coding) - Extended sequential DCT" },
+ { MARKER_SOF10, "Start of Frame (non-differential, arithmetic coding) - Progressive DCT" },
+ { MARKER_SOF11, "Start of Frame (non-differential, arithmetic coding) - Lossless (sequential)" },
+ { MARKER_DAC, "Define arithmetic coding conditioning(s)" },
+ { MARKER_SOF13, "Start of Frame (differential, arithmetic coding) - Differential sequential DCT" },
+ { MARKER_SOF14, "Start of Frame (differential, arithmetic coding) - Differential progressive DCT" },
+ { MARKER_SOF15, "Start of Frame (differential, arithmetic coding) - Differential lossless (sequential)" },
+ { MARKER_RST0, "Restart interval termination - Restart with modulo 8 count 0" },
+ { MARKER_RST1, "Restart interval termination - Restart with modulo 8 count 1" },
+ { MARKER_RST2, "Restart interval termination - Restart with modulo 8 count 2" },
+ { MARKER_RST3, "Restart interval termination - Restart with modulo 8 count 3" },
+ { MARKER_RST4, "Restart interval termination - Restart with modulo 8 count 4" },
+ { MARKER_RST5, "Restart interval termination - Restart with modulo 8 count 5" },
+ { MARKER_RST6, "Restart interval termination - Restart with modulo 8 count 6" },
+ { MARKER_RST7, "Restart interval termination - Restart with modulo 8 count 7" },
+ { MARKER_SOI, "Start of Image" },
+ { MARKER_EOI, "End of Image" },
+ { MARKER_SOS, "Start of Scan" },
+ { MARKER_DQT, "Define quantization table(s)" },
+ { MARKER_DNL, "Define number of lines" },
+ { MARKER_DRI, "Define restart interval" },
+ { MARKER_DHP, "Define hierarchical progression" },
+ { MARKER_EXP, "Expand reference component(s)" },
+ { MARKER_APP0, "Reserved for application segments - 0" },
+ { MARKER_APP1, "Reserved for application segments - 1" },
+ { MARKER_APP2, "Reserved for application segments - 2" },
+ { MARKER_APP3, "Reserved for application segments - 3" },
+ { MARKER_APP4, "Reserved for application segments - 4" },
+ { MARKER_APP5, "Reserved for application segments - 5" },
+ { MARKER_APP6, "Reserved for application segments - 6" },
+ { MARKER_APP7, "Reserved for application segments - 7" },
+ { MARKER_APP8, "Reserved for application segments - 8" },
+ { MARKER_APP9, "Reserved for application segments - 9" },
+ { MARKER_APP10, "Reserved for application segments - 10" },
+ { MARKER_APP11, "Reserved for application segments - 11" },
+ { MARKER_APP12, "Reserved for application segments - 12" },
+ { MARKER_APP13, "Reserved for application segments - 13" },
+ { MARKER_APP14, "Reserved for application segments - 14" },
+ { MARKER_APP15, "Reserved for application segments - 15" },
+ { MARKER_JPG0, "Reserved for JPEG extensions - 0" },
+ { MARKER_JPG1, "Reserved for JPEG extensions - 1" },
+ { MARKER_JPG2, "Reserved for JPEG extensions - 2" },
+ { MARKER_JPG3, "Reserved for JPEG extensions - 3" },
+ { MARKER_JPG4, "Reserved for JPEG extensions - 4" },
+ { MARKER_JPG5, "Reserved for JPEG extensions - 5" },
+ { MARKER_JPG6, "Reserved for JPEG extensions - 6" },
+ { MARKER_JPG7, "Reserved for JPEG extensions - 7" },
+ { MARKER_JPG8, "Reserved for JPEG extensions - 8" },
+ { MARKER_JPG9, "Reserved for JPEG extensions - 9" },
+ { MARKER_JPG10, "Reserved for JPEG extensions - 10" },
+ { MARKER_JPG11, "Reserved for JPEG extensions - 11" },
+ { MARKER_JPG12, "Reserved for JPEG extensions - 12" },
+ { MARKER_JPG13, "Reserved for JPEG extensions - 13" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_units[] = {
+ { 0, "No units; Xdensity and Ydensity specify the pixel aspect ratio" },
+ { 1, "Dots per inch" },
+ { 2, "Dots per centimeter" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_extension_code[] = {
+ { 0x10, "Thumbnail encoded using JPEG" },
+ { 0x11, "Thumbnail encoded using 1 byte (8 bits) per pixel" },
+ { 0x13, "Thumbnail encoded using 3 bytes (24 bits) per pixel" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_exif_tags[] = {
+ /*
+ * Tags related to image data structure:
+ */
+ { 0x0100, "ImageWidth" },
+ { 0x0101, "ImageLength" },
+ { 0x0102, "BitsPerSample" },
+ { 0x0103, "Compression" },
+ { 0x0106, "PhotometricInterpretation" },
+ { 0x0112, "Orientation" },
+ { 0x0115, "SamplesPerPixel" },
+ { 0x011C, "PlanarConfiguration" },
+ { 0x0212, "YCbCrSubSampling" },
+ { 0x0213, "YCbCrPositioning" },
+ { 0x011A, "XResolution" },
+ { 0x011B, "YResolution" },
+ { 0x0128, "ResolutionUnit" },
+ /*
+ * Tags relating to recording offset:
+ */
+ { 0x0111, "StripOffsets" },
+ { 0x0116, "RowsPerStrip" },
+ { 0x0117, "StripByteCounts" },
+ { 0x0201, "JPEGInterchangeFormat" },
+ { 0x0202, "JPEGInterchangeFormatLength" },
+ /*
+ * Tags relating to image data characteristics:
+ */
+ { 0x012D, "TransferFunction" },
+ { 0x013E, "WhitePoint" },
+ { 0x013F, "PrimaryChromaticities" },
+ { 0x0211, "YCbCrCoefficients" },
+ { 0x0214, "ReferenceBlackWhite" },
+ /*
+ * Other tags:
+ */
+ { 0x0132, "DateTime" },
+ { 0x010E, "ImageDescription" },
+ { 0x010F, "Make" },
+ { 0x0110, "Model" },
+ { 0x0131, "Software" },
+ { 0x013B, "Artist" },
+ { 0x8296, "Copyright" },
+ /*
+ * Exif-specific IFD:
+ */
+ { 0x8769, "Exif IFD Pointer"},
+ { 0x8825, "GPS IFD Pointer"},
+ { 0xA005, "Interoperability IFD Pointer"},
+
+ { 0x0000, NULL }
+};
+
+static const value_string vals_exif_types[] = {
+ { 0x0001, "BYTE" },
+ { 0x0002, "ASCII" },
+ { 0x0003, "SHORT" },
+ { 0x0004, "LONG" },
+ { 0x0005, "RATIONAL" },
+ /* 0x0006 */
+ { 0x0007, "UNDEFINED" },
+ /* 0x0008 */
+ { 0x0009, "SLONG" },
+ { 0x000A, "SRATIONAL" },
+
+ { 0x0000, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_jfif = -1;
+
+/* Marker */
+static gint hf_marker = -1;
+/* Marker segment */
+static gint hf_marker_segment = -1;
+static gint hf_len = -1;
+/* MARKER_APP0 */
+static gint hf_identifier = -1;
+/* MARKER_APP0 - JFIF */
+static gint hf_version = -1;
+static gint hf_version_major = -1;
+static gint hf_version_minor = -1;
+static gint hf_units = -1;
+static gint hf_xdensity = -1;
+static gint hf_ydensity = -1;
+static gint hf_xthumbnail = -1;
+static gint hf_ythumbnail = -1;
+static gint hf_rgb = -1;
+/* MARKER_APP0 - JFXX */
+static gint hf_extension_code = -1;
+/* start of Frame */
+static gint hf_sof_header = -1;
+static gint hf_sof_precision = -1;
+static gint hf_sof_lines = -1;
+static gint hf_sof_samples_per_line = -1;
+static gint hf_sof_nf = -1;
+static gint hf_sof_c_i = -1;
+static gint hf_sof_h_i = -1;
+static gint hf_sof_v_i = -1;
+static gint hf_sof_tq_i = -1;
+
+/* Start of Scan */
+static gint hf_sos_header = -1;
+static gint hf_sos_ns = -1;
+static gint hf_sos_cs_j = -1;
+static gint hf_sos_td_j = -1;
+static gint hf_sos_ta_j = -1;
+static gint hf_sos_ss = -1;
+static gint hf_sos_se = -1;
+static gint hf_sos_ah = -1;
+static gint hf_sos_al = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_jfif = -1;
+static gint ett_marker_segment = -1;
+static gint ett_details = -1;
+
+
+/**************** GIF related declarations and definitions ****************/
+
+
+/************************** Function prototypes **************************/
+
+
+static void
+dissect_jfif(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+void
+proto_register_jfif(void);
+
+
+
+/****************** JFIF protocol dissection functions ******************/
+
+#define ErrorInvalidJFIF "This is not a valid JFIF (JPEG) object"
+
+
+/*
+ * Process a marker segment (with length).
+ */
+static void
+process_marker_segment(proto_tree *tree, tvbuff_t *tvb, guint32 len,
+ guint16 marker, const char *marker_name)
+{
+ proto_item *ti = NULL;
+ proto_tree *subtree = NULL;
+
+ if (! tree)
+ return;
+
+ ti = proto_tree_add_item(tree, hf_marker_segment,
+ tvb, 0, -1, FALSE);
+ subtree = proto_item_add_subtree(ti, ett_marker_segment);
+
+ proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
+ proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_len, tvb, 2, 2, FALSE);
+
+ proto_tree_add_text(subtree, tvb, 4, -1,
+ "Remaining segment data (%u bytes)", len - 2);
+}
+
+/*
+ * Process a Start of Frame header (with length).
+ */
+static void
+process_sof_header(proto_tree *tree, tvbuff_t *tvb, guint32 len _U_,
+ guint16 marker, const char *marker_name)
+{
+ proto_item *ti = NULL;
+ proto_tree *subtree = NULL;
+
+ if (! tree)
+ return;
+
+ ti = proto_tree_add_item(tree, hf_sof_header,
+ tvb, 0, -1, FALSE);
+ subtree = proto_item_add_subtree(ti, ett_marker_segment);
+
+ proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
+ proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_len, tvb, 2, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_sof_precision, tvb, 4, 1, FALSE);
+
+ proto_tree_add_item(subtree, hf_sof_lines, tvb, 5, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_sof_samples_per_line, tvb, 7, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_sof_nf, tvb, 9, 1, FALSE);
+ {
+ guint8 count = tvb_get_guint8(tvb, 9);
+ guint32 offset = 10;
+ while (count > 0) {
+ proto_tree_add_item(subtree, hf_sof_c_i, tvb, offset++, 1, FALSE);
+ proto_tree_add_item(subtree, hf_sof_h_i, tvb, offset, 1, FALSE);
+ proto_tree_add_item(subtree, hf_sof_v_i, tvb, offset++, 1, FALSE);
+ proto_tree_add_item(subtree, hf_sof_tq_i, tvb, offset++, 1, FALSE);
+ count--;
+ }
+ }
+}
+
+/*
+ * Process a Start of Segment header (with length).
+ */
+static void
+process_sos_header(proto_tree *tree, tvbuff_t *tvb, guint32 len _U_,
+ guint16 marker, const char *marker_name)
+{
+ proto_item *ti = NULL;
+ proto_tree *subtree = NULL;
+ guint32 offset;
+
+ if (! tree)
+ return;
+
+ ti = proto_tree_add_item(tree, hf_sos_header,
+ tvb, 0, -1, FALSE);
+ subtree = proto_item_add_subtree(ti, ett_marker_segment);
+
+ proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
+ proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_len, tvb, 2, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_sos_ns, tvb, 4, 1, FALSE);
+ {
+ guint8 count = tvb_get_guint8(tvb, 4);
+ offset = 5;
+ while (count > 0) {
+ proto_tree_add_item(subtree, hf_sos_cs_j, tvb, offset++, 1, FALSE);
+ proto_tree_add_item(subtree, hf_sos_td_j, tvb, offset, 1, FALSE);
+ proto_tree_add_item(subtree, hf_sos_ta_j, tvb, offset++, 1, FALSE);
+ count--;
+ }
+ }
+
+ proto_tree_add_item(subtree, hf_sos_ss, tvb, offset++, 1, FALSE);
+ proto_tree_add_item(subtree, hf_sos_se, tvb, offset++, 1, FALSE);
+
+ proto_tree_add_item(subtree, hf_sos_ah, tvb, offset, 1, FALSE);
+ proto_tree_add_item(subtree, hf_sos_al, tvb, offset++, 1, FALSE);
+}
+
+/* Process an APP0 block.
+ *
+ * XXX - This code only works on US-ASCII systems!!!
+ */
+static void
+process_app0_segment(proto_tree *tree, tvbuff_t *tvb, guint32 len,
+ guint16 marker, const char *marker_name)
+{
+ proto_item *ti = NULL;
+ proto_tree *subtree = NULL;
+ proto_tree *subtree_details = NULL;
+ guint32 offset;
+ char *str;
+ gint str_size;
+
+ if (!tree)
+ return;
+
+ ti = proto_tree_add_item(tree, hf_marker_segment,
+ tvb, 0, -1, FALSE);
+ subtree = proto_item_add_subtree(ti, ett_marker_segment);
+
+ proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
+ proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_len, tvb, 2, 2, FALSE);
+
+ str = tvb_get_stringz(tvb, 4, &str_size);
+ ti = proto_tree_add_item(subtree, hf_identifier, tvb, 4, str_size, FALSE);
+ if (strcmp(str, "JFIF") == 0) {
+ /* Version */
+ ti = proto_tree_add_none_format(subtree, hf_version,
+ tvb, 9, 2, "Version: %u.%u",
+ tvb_get_guint8(tvb, 9),
+ tvb_get_guint8(tvb, 10));
+ subtree_details = proto_item_add_subtree(ti, ett_details);
+ proto_tree_add_item(subtree_details, hf_version_major,
+ tvb, 9, 1, FALSE);
+ proto_tree_add_item(subtree_details, hf_version_minor,
+ tvb, 10, 1, FALSE);
+
+ proto_tree_add_item(subtree, hf_units,
+ tvb, 11, 1, FALSE);
+
+ /* Aspect ratio */
+ proto_tree_add_item(subtree, hf_xdensity,
+ tvb, 12, 2, FALSE);
+ proto_tree_add_item(subtree, hf_ydensity,
+ tvb, 14, 2, FALSE);
+
+ /* Thumbnail */
+ proto_tree_add_item(subtree, hf_xthumbnail,
+ tvb, 16, 1, FALSE);
+ proto_tree_add_item(subtree, hf_ythumbnail,
+ tvb, 17, 1, FALSE);
+ {
+ guint16 x = tvb_get_guint8(tvb, 16);
+ guint16 y = tvb_get_guint8(tvb, 17);
+ if (x || y) {
+ proto_tree_add_item(subtree, hf_rgb,
+ tvb, 18, 3 * (x * y), FALSE);
+ offset = 18 + (3 * (x * y));
+ } else {
+ offset = 18;
+ }
+ }
+ } else if (strcmp(str, "JFXX") == 0) {
+ proto_tree_add_item(subtree, hf_extension_code,
+ tvb, 9, 1, FALSE);
+ {
+ guint8 code = tvb_get_guint8(tvb, 9);
+ switch (code) {
+ case 0x10: /* Thumbnail coded using JPEG */
+ break;
+ case 0x11: /* thumbnail stored using 1 byte per pixel */
+ break;
+ case 0x13: /* thumbnail stored using 3 bytes per pixel */
+ break;
+ default: /* Error */
+ break;
+ }
+ }
+ } else { /* Unknown */
+ proto_item_append_text(ti, " (unknown identifier)");
+ offset = 4 + str_size;
+
+ proto_tree_add_text(subtree, tvb, offset, -1,
+ "Remaining segment data (%u bytes)", len - 2 - str_size);
+ }
+
+ return;
+}
+
+/* Process an APP1 block.
+ *
+ * XXX - This code only works on US-ASCII systems!!!
+ */
+static void
+process_app1_segment(proto_tree *tree, tvbuff_t *tvb, guint32 len,
+ guint16 marker, const char *marker_name)
+{
+ proto_item *ti = NULL;
+ proto_tree *subtree = NULL;
+ proto_tree *subtree_details = NULL;
+ char *str;
+ gint str_size;
+ guint32 offset, tiff_start;
+
+ if (!tree)
+ return;
+
+ ti = proto_tree_add_item(tree, hf_marker_segment,
+ tvb, 0, -1, FALSE);
+ subtree = proto_item_add_subtree(ti, ett_marker_segment);
+
+ proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
+ proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_len, tvb, 2, 2, FALSE);
+
+ str = tvb_get_stringz(tvb, 4, &str_size);
+ ti = proto_tree_add_item(subtree, hf_identifier, tvb, 4, str_size, FALSE);
+ offset = tiff_start = 4 + str_size;
+ if (strcmp(str, "Exif") == 0) {
+ /*
+ * Endianness
+ */
+ gboolean is_little_endian;
+ guint16 val_16;
+ guint32 val_32;
+ guint16 num_fields;
+
+ offset++; /* Skip a byte supposed to be 0x00 */
+
+ val_16 = tvb_get_ntohs(tvb, offset);
+ if (val_16 == 0x4949) {
+ is_little_endian = TRUE;
+ proto_tree_add_text(subtree, tvb, offset, 2, "Endianness: little endian");
+ } else if (val_16 == 0x4D4D) {
+ is_little_endian = FALSE;
+ proto_tree_add_text(subtree, tvb, offset, 2, "Endianness: big endian");
+ } else {
+ /* Error: invalid endianness encoding */
+ proto_tree_add_text(subtree, tvb, offset, 2,
+ "Incorrect endianness encoding - skipping the remainder of this application marker");
+ return;
+ }
+ offset += 2;
+ /*
+ * Fixed value 42 = 0x002a
+ */
+ offset += 2;
+ /*
+ * Offset to IFD
+ */
+ if (is_little_endian) {
+ val_16 = tvb_get_letohs(tvb, offset);
+ } else {
+ val_16 = tvb_get_ntohs(tvb, offset);
+ }
+ proto_tree_add_text(subtree, tvb, offset, 4,
+ "Start offset of IFD starting from the TIFF header start: %u bytes", val_16);
+ offset += 4;
+ /*
+ * Skip the following portion
+ */
+ proto_tree_add_text(subtree, tvb, offset, val_16 + tiff_start - offset,
+ "Skipped data between end of TIFF header and start of IFD (%u bytes)",
+ val_16 + tiff_start - offset);
+ offset = val_16 + tiff_start + 1;
+ /*
+ * Process the "0th" IFD
+ */
+ if (is_little_endian) {
+ num_fields = tvb_get_letohs(tvb, offset);
+ } else {
+ num_fields = tvb_get_ntohs(tvb, offset);
+ }
+ proto_tree_add_text(subtree, tvb, offset, 2, "Number of fields in this IFD: %u", num_fields);
+ offset += 2;
+ while (num_fields-- > 0) {
+ guint16 tag, type;
+ guint32 count, off;
+
+ if (is_little_endian) {
+ tag = tvb_get_letohs(tvb, offset);
+ type = tvb_get_letohs(tvb, offset + 2);
+ count = tvb_get_letohl(tvb, offset + 4);
+ off = tvb_get_letohl(tvb, offset + 8);
+ } else {
+ tag = tvb_get_ntohs(tvb, offset);
+ type = tvb_get_ntohs(tvb, offset + 2);
+ count = tvb_get_ntohl(tvb, offset + 4);
+ off = tvb_get_ntohl(tvb, offset + 8);
+ }
+ /* TODO - refine this */
+ proto_tree_add_text(subtree, tvb, offset, 2,
+ "Exif Tag: 0x%04X (%s), Type: %u (%s), Count: %u, "
+ "Value offset from start of TIFF header: %u",
+ tag, val_to_str(tag, vals_exif_tags, "Unknown Exif tag"),
+ type, val_to_str(type, vals_exif_types, "Unknown Exif type"),
+ count, off);
+ offset += 12;
+ }
+ /*
+ * Offset to the "1st" IFD
+ */
+ if (is_little_endian) {
+ val_32 = tvb_get_letohl(tvb, offset);
+ } else {
+ val_32 = tvb_get_ntohl(tvb, offset);
+ }
+ proto_tree_add_text(subtree, tvb, offset, 4,
+ "Offset to next IFD from start of TIFF header: %u bytes", val_32);
+ /* TODO - Continue parsing the "1th" IFD */
+ offset += 4;
+ proto_tree_add_text(subtree, tvb, offset, -1, "Remainder of APP1 marker skipped");
+ } else {
+ proto_item_append_text(ti, " (Unknown identifier)");
+ }
+}
+
+/* Process an APP2 block.
+ *
+ * XXX - This code only works on US-ASCII systems!!!
+ */
+static void
+process_app2_segment(proto_tree *tree, tvbuff_t *tvb, guint32 len,
+ guint16 marker, const char *marker_name)
+{
+ proto_item *ti = NULL;
+ proto_tree *subtree = NULL;
+ proto_tree *subtree_details = NULL;
+ char *str;
+ gint str_size;
+
+ if (!tree)
+ return;
+
+ ti = proto_tree_add_item(tree, hf_marker_segment,
+ tvb, 0, -1, FALSE);
+ subtree = proto_item_add_subtree(ti, ett_marker_segment);
+
+ proto_item_append_text(ti, ": %s (0x%04X)", marker_name, marker);
+ proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, FALSE);
+
+ proto_tree_add_item(subtree, hf_len, tvb, 2, 2, FALSE);
+
+ str = tvb_get_stringz(tvb, 4, &str_size);
+ ti = proto_tree_add_item(subtree, hf_identifier, tvb, 4, str_size, FALSE);
+ if (strcmp(str, "FPXR") == 0) {
+ proto_tree_add_text(tree, tvb, 0, -1, "Exif FlashPix APP2 application marker");
+ } else {
+ proto_item_append_text(ti, " (Unknown identifier)");
+ }
+}
+
+static void
+dissect_jfif(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_tree *subtree = NULL;
+ proto_item *ti;
+ guint tvb_len = tvb_reported_length(tvb);
+ guint32 offset = 0;
+ tvbuff_t *tmp_tvb;
+ guint32 len;
+ guint16 marker;
+
+ /* Add summary to INFO column if it is enabled */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(JPEG JFIF image)");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_jfif,
+ tvb, 0, -1, FALSE);
+ subtree = proto_item_add_subtree(ti, ett_jfif);
+ }
+
+ marker = tvb_get_ntohs(tvb, 0);
+ if (marker != MARKER_SOI) {
+ if (tree) {
+ proto_tree_add_text(subtree, tvb, 0, 2, ErrorInvalidJFIF);
+ return;
+ }
+ }
+ if (tree)
+ proto_tree_add_item(subtree, hf_marker, tvb, 0, 2, FALSE);
+
+ offset = 2;
+
+ /*
+ * Process the remaining markers and marker segments
+ */
+ while (offset < tvb_len) {
+ char *str;
+ marker = tvb_get_ntohs(tvb, offset);
+ str = match_strval(marker, vals_marker);
+ if (str) { /* Known marker */
+ if (marker_has_length(marker)) { /* Marker segment */
+ /* Length of marker segment = 2 + len */
+ len = tvb_get_ntohs(tvb, offset + 2);
+ tmp_tvb = tvb_new_subset(tvb, offset, 2 + len, 2 + len);
+ switch (marker) {
+ case MARKER_APP0:
+ process_app0_segment(subtree, tmp_tvb, len, marker, str);
+ break;
+ case MARKER_APP1:
+ process_app1_segment(subtree, tmp_tvb, len, marker, str);
+ break;
+ case MARKER_APP2:
+ process_app2_segment(subtree, tmp_tvb, len, marker, str);
+ break;
+ case MARKER_SOF0:
+ case MARKER_SOF1:
+ case MARKER_SOF2:
+ case MARKER_SOF3:
+ case MARKER_SOF5:
+ case MARKER_SOF6:
+ case MARKER_SOF7:
+ case MARKER_SOF8:
+ case MARKER_SOF9:
+ case MARKER_SOF10:
+ case MARKER_SOF11:
+ case MARKER_SOF13:
+ case MARKER_SOF14:
+ case MARKER_SOF15:
+ process_sof_header(subtree, tmp_tvb, len, marker, str);
+ break;
+ case MARKER_SOS:
+ process_sos_header(subtree, tmp_tvb, len, marker, str);
+ /*
+ * TODO - dissect a scan; the scan data is encoded.
+ */
+ proto_tree_add_text(subtree, tvb, offset + 2 + len, -1,
+ "JFIF dissection stops here (dissection of a scan is not yet implemented)");
+ return;
+ break;
+ default:
+ process_marker_segment(subtree, tmp_tvb, len, marker, str);
+ break;
+ }
+ offset += 2 + len;
+ } else { /* Marker but no segment */
+ /* Length = 2 */
+ proto_tree_add_item(subtree, hf_marker,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ } else { /* Reserved! */
+ ti = proto_tree_add_item(subtree, hf_marker,
+ tvb, offset, 2, FALSE);
+ proto_item_append_text(ti, " (Reserved)");
+ return;
+ }
+ }
+
+ return;
+}
+
+
+/****************** Register the protocol with Ethereal ******************/
+
+
+/* This format is required because a script is used to build the C function
+ * that calls the protocol registration. */
+
+void
+proto_register_jfif(void)
+{
+ /*
+ * Setup list of header fields.
+ */
+ static hf_register_info hf[] = {
+ /* Marker */
+ { &hf_marker,
+ { "Marker",
+ IMG_JFIF ".marker",
+ FT_UINT8, BASE_HEX, VALS(vals_marker), 0x00,
+ "JFIF Marker",
+ HFILL
+ }
+ },
+ /* Marker segment */
+ { &hf_marker_segment,
+ { "Marker segment",
+ IMG_JFIF "marker_segment",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Marker segment",
+ HFILL
+ }
+ },
+ { &hf_len,
+ { "Length",
+ IMG_JFIF ".length",
+ FT_UINT16, BASE_DEC, 0, 0x00,
+ "Length of segment (including length field)",
+ HFILL
+ }
+ },
+ /* MARKER_APP0 */
+ { &hf_identifier,
+ { "Identifier",
+ IMG_JFIF ".identifier",
+ FT_STRINGZ, BASE_NONE, NULL, 0x00,
+ "Identifier of the segment",
+ HFILL
+ }
+ },
+ /* MARKER_APP0 - JFIF */
+ { &hf_version,
+ { "Version",
+ IMG_JFIF ".version",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "JFIF Version",
+ HFILL
+ }
+ },
+ { &hf_version_major,
+ { "Major Version",
+ IMG_JFIF ".version.major",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "JFIF Major Version",
+ HFILL
+ }
+ },
+ { &hf_version_minor,
+ { "Minor Version",
+ IMG_JFIF ".version.minor",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "JFIF Minor Version",
+ HFILL
+ }
+ },
+ { &hf_units,
+ { "Units",
+ IMG_JFIF ".units",
+ FT_UINT8, BASE_DEC, VALS(vals_units), 0x00,
+ "Units used in this segment",
+ HFILL
+ }
+ },
+ { &hf_xdensity,
+ { "Xdensity",
+ IMG_JFIF ".Xdensity",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Horizontal pixel density",
+ HFILL
+ }
+ },
+ { &hf_ydensity,
+ { "Ydensity",
+ IMG_JFIF ".Ydensity",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Vertical pixel density",
+ HFILL
+ }
+ },
+ { &hf_xthumbnail,
+ { "Xthumbnail",
+ IMG_JFIF ".Xthumbnail",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Thumbnail horizontal pixel count",
+ HFILL
+ }
+ },
+ { &hf_ythumbnail,
+ { "Ythumbnail",
+ IMG_JFIF ".Ythumbnail",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Thumbnail vertical pixel count",
+ HFILL
+ }
+ },
+ { &hf_rgb,
+ { "RGB values of thumbnail pixels",
+ IMG_JFIF ".RGB",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ "RGB values of the thumbnail pixels (24 bit per pixel, Xthumbnail x Ythumbnail pixels)",
+ HFILL
+ }
+ },
+ /* MARKER_APP0 - JFXX */
+ { &hf_extension_code,
+ { "Extension code",
+ IMG_JFIF ".extension.code",
+ FT_UINT8, BASE_HEX, VALS(vals_extension_code), 0x00,
+ "JFXX extension code for thumbnail encoding",
+ HFILL
+ }
+ },
+ /* Header: Start of Frame (MARKER_SOF) */
+ { &hf_sof_header,
+ { "Start of Frame header",
+ IMG_JFIF ".sof",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Start of Frame header",
+ HFILL
+ }
+ },
+ { &hf_sof_precision,
+ { "Sample Precision (bits)",
+ IMG_JFIF ".sof.precision",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Specifies the precision in bits for the samples of the components in the frame.",
+ HFILL
+ }
+ },
+ { &hf_sof_lines,
+ { "Lines",
+ IMG_JFIF ".sof.lines",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Specifies the maximum number of lines in the source image.",
+ HFILL
+ }
+ },
+ { &hf_sof_samples_per_line,
+ { "Samples per line",
+ IMG_JFIF ".sof.samples_per_line",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Specifies the maximum number of samples per line in the source image.",
+ HFILL
+ }
+ },
+ { &hf_sof_nf,
+ { "Number of image components in frame",
+ IMG_JFIF ".sof.nf",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Specifies the number of source image components in the frame.",
+ HFILL
+ }
+ },
+ { &hf_sof_c_i,
+ { "Component identifier",
+ IMG_JFIF ".sof.c_i",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Assigns a unique label to the ith component in the sequence "
+ "of frame component specification parameters.",
+ HFILL
+ }
+ },
+ { &hf_sof_h_i,
+ { "Horizontal sampling factor",
+ IMG_JFIF ".sof.h_i",
+ FT_UINT8, BASE_DEC, NULL, 0xF0,
+ "Specifies the relationship between the component horizontal "
+ "dimension and maximum image dimension X.",
+ HFILL
+ }
+ },
+ { &hf_sof_v_i,
+ { "Vertical sampling factor",
+ IMG_JFIF ".sof.v_i",
+ FT_UINT8, BASE_DEC, NULL, 0x0F,
+ "Specifies the relationship between the component vertical "
+ "dimension and maximum image dimension Y.",
+ HFILL
+ }
+ },
+ { &hf_sof_tq_i,
+ { "Quantization table destination selector",
+ IMG_JFIF ".sof.tq_i",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Specifies one of four possible quantization table "
+ "destinations from which the quantization table to use "
+ "for dequantization of DCT coefficients of component Ci "
+ "is retrieved.",
+ HFILL
+ }
+ },
+
+ /* Header: Start of Segment (MARKER_SOS) */
+ { &hf_sos_header,
+ { "Start of Segment header",
+ IMG_JFIF ".header.sos",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Start of Segment header",
+ HFILL
+ }
+ },
+ { &hf_sos_ns,
+ { "Number of image components in scan",
+ IMG_JFIF ".sos.ns",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Specifies the number of source image components in the scan.",
+ HFILL
+ }
+ },
+ { &hf_sos_cs_j,
+ { "Scan component selector",
+ IMG_JFIF ".sos.component_selector",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Selects which of the Nf image components specified in the "
+ "frame parameters shall be the jth component in the scan.",
+ HFILL
+ }
+ },
+ { &hf_sos_td_j,
+ { "DC entropy coding table destination selector",
+ IMG_JFIF ".sos.dc_entropy_selector",
+ FT_UINT8, BASE_DEC, NULL, 0xF0,
+ "Specifies one of four possible DC entropy coding table "
+ "destinations from which the entropy table needed "
+ "for decoding of the DC coefficients of component Csj "
+ "is retrieved.",
+ HFILL
+ }
+ },
+ { &hf_sos_ta_j,
+ { "AC entropy coding table destination selector",
+ IMG_JFIF ".sos.ac_entropy_selector",
+ FT_UINT8, BASE_DEC, NULL, 0x0F,
+ "Specifies one of four possible AC entropy coding table "
+ "destinations from which the entropy table needed "
+ "for decoding of the AC coefficients of component Csj "
+ "is retrieved.",
+ HFILL
+ }
+ },
+ { &hf_sos_ss,
+ { "Start of spectral or predictor selection",
+ IMG_JFIF ".sos.ss",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "In the DCT modes of operation, this parameter specifies the "
+ "first DCT coefficient in each block in zig-zag order which "
+ "shall be coded in the scan. This parameter shall be set to "
+ "zero for the sequential DCT processes. "
+ "In the lossless mode of operations this parameter is used "
+ "to select the predictor.",
+ HFILL
+ }
+ },
+ { &hf_sos_se,
+ { "End of spectral selection",
+ IMG_JFIF ".sos.se",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Specifies the last DCT coefficient in each block in zig-zag "
+ "order which shall be coded in the scan. This parameter shall "
+ "be set to 63 for the sequential DCT processes. "
+ "In the lossless mode of operations this parameter has no "
+ "meaning. It shall be set to zero.",
+ HFILL
+ }
+ },
+ { &hf_sos_ah,
+ { "Successive approximation bit position high",
+ IMG_JFIF ".sos.ah",
+ FT_UINT8, BASE_DEC, NULL, 0xF0,
+ "This parameter specifies the point transform used in the "
+ "preceding scan (i.e. successive approximation bit position "
+ "low in the preceding scan) for the band of coefficients "
+ "specified by Ss and Se. This parameter shall be set to zero "
+ "for the first scan of each band of coefficients. "
+ "In the lossless mode of operations this parameter has no "
+ "meaning. It shall be set to zero.",
+ HFILL
+ }
+ },
+ { &hf_sos_al,
+ { "Successive approximation bit position low or point transform",
+ IMG_JFIF ".sos.al",
+ FT_UINT8, BASE_DEC, NULL, 0x0F,
+ "In the DCT modes of operation this parameter specifies the "
+ "point transform, i.e. bit position low, used before coding "
+ "the band of coefficients specified by Ss and Se. "
+ "This parameter shall be set to zero for the sequential DCT "
+ "processes. In the lossless mode of operations, this "
+ "parameter specifies the point transform, Pt.",
+ HFILL
+ }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_jfif,
+ &ett_marker_segment,
+ &ett_details,
+ };
+
+ /* Register the protocol name and description */
+ proto_jfif = proto_register_protocol(
+ "JPEG File Interchange Format",
+ "JFIF (JPEG) image",
+ IMG_JFIF
+ );
+
+ /* Required function calls to register the header fields
+ * and subtrees used */
+ proto_register_field_array(proto_jfif, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("image-jfif", dissect_jfif, proto_jfif);
+}
+
+
+void
+proto_reg_handoff_jfif(void)
+{
+ dissector_handle_t jfif_handle;
+
+ jfif_handle = create_dissector_handle(dissect_jfif, proto_jfif);
+
+ /* Register the GIF media type */
+ dissector_add_string("media_type", "image/jfif", jfif_handle);
+ dissector_add_string("media_type", "image/jpg", jfif_handle);
+ dissector_add_string("media_type", "image/jpeg", jfif_handle);
+}
diff --git a/epan/dissectors/packet-imap.c b/epan/dissectors/packet-imap.c
new file mode 100644
index 0000000000..88075e96d5
--- /dev/null
+++ b/epan/dissectors/packet-imap.c
@@ -0,0 +1,192 @@
+/* packet-imap.c
+ * Routines for imap packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+static int proto_imap = -1;
+static int hf_imap_response = -1;
+static int hf_imap_request = -1;
+
+static gint ett_imap = -1;
+static gint ett_imap_reqresp = -1;
+
+#define TCP_PORT_IMAP 143
+
+static void
+dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gboolean is_request;
+ proto_tree *imap_tree, *reqresp_tree;
+ proto_item *ti;
+ gint offset = 0;
+ const guchar *line;
+ gint next_offset;
+ int linelen;
+ int tokenlen;
+ const guchar *next_token;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IMAP");
+
+ /*
+ * Find the end of the first line.
+ *
+ * Note that "tvb_find_line_end()" will return a value that is
+ * not longer than what's in the buffer, so the "tvb_get_ptr()"
+ * call won't throw an exception.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ line = tvb_get_ptr(tvb, offset, linelen);
+
+ if (pinfo->match_port == pinfo->destport)
+ is_request = TRUE;
+ else
+ is_request = FALSE;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary
+ * (but leave out the line terminator).
+ */
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
+ is_request ? "Request" : "Response",
+ format_text(line, linelen));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_imap, tvb, offset, -1,
+ FALSE);
+ imap_tree = proto_item_add_subtree(ti, ett_imap);
+
+ if (is_request) {
+ proto_tree_add_boolean_hidden(imap_tree,
+ hf_imap_request, tvb, 0, 0, TRUE);
+ } else {
+ proto_tree_add_boolean_hidden(imap_tree,
+ hf_imap_response, tvb, 0, 0, TRUE);
+ }
+
+ /*
+ * Put the line into the protocol tree.
+ */
+ ti = proto_tree_add_text(imap_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ reqresp_tree = proto_item_add_subtree(ti, ett_imap_reqresp);
+
+ /*
+ * Show the first line as tags + requests or replies.
+ */
+
+ /*
+ * Extract the first token, and, if there is a first
+ * token, add it as the request or reply tag.
+ */
+ tokenlen = get_token_len(line, line + linelen, &next_token);
+ if (tokenlen != 0) {
+ if (is_request) {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ tokenlen, "Request Tag: %s",
+ format_text(line, tokenlen));
+ } else {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ tokenlen, "Response Tag: %s",
+ format_text(line, tokenlen));
+ }
+ offset += next_token - line;
+ linelen -= next_token - line;
+ line = next_token;
+ }
+
+ /*
+ * Add the rest of the line as request or reply data.
+ */
+ if (linelen != 0) {
+ if (is_request) {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ linelen, "Request: %s",
+ format_text(line, linelen));
+ } else {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ linelen, "Response: %s",
+ format_text(line, linelen));
+ }
+ }
+
+ /*
+ * XXX - show the rest of the frame; this requires that
+ * we handle literals, quoted strings, continuation
+ * responses, etc..
+ *
+ * This involves a state machine, and attaching
+ * state information to the packets.
+ */
+ }
+}
+
+void
+proto_register_imap(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_imap_response,
+ { "Response", "imap.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if IMAP response", HFILL }},
+
+ { &hf_imap_request,
+ { "Request", "imap.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if IMAP request", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_imap,
+ &ett_imap_reqresp,
+ };
+
+ proto_imap = proto_register_protocol("Internet Message Access Protocol",
+ "IMAP", "imap");
+ proto_register_field_array(proto_imap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_imap(void)
+{
+ dissector_handle_t imap_handle;
+
+ imap_handle = create_dissector_handle(dissect_imap, proto_imap);
+ dissector_add("tcp.port", TCP_PORT_IMAP, imap_handle);
+}
diff --git a/epan/dissectors/packet-ip.c b/epan/dissectors/packet-ip.c
new file mode 100644
index 0000000000..9a5d3e6154
--- /dev/null
+++ b/epan/dissectors/packet-ip.c
@@ -0,0 +1,1897 @@
+/* packet-ip.c
+ * Routines for IP and miscellaneous IP protocol packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "ipproto.h"
+#include "ip_opts.h"
+#include "prefs.h"
+#include "reassemble.h"
+#include "etypes.h"
+#include "greproto.h"
+#include "ppptypes.h"
+#include "llcsaps.h"
+#include "aftypes.h"
+#include "arcnet_pids.h"
+#include "packet-ip.h"
+#include "packet-ipsec.h"
+#include "in_cksum.h"
+#include "nlpid.h"
+#include "tap.h"
+
+static int ip_tap = -1;
+
+static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
+
+/* Decode the old IPv4 TOS field as the DiffServ DS Field */
+static gboolean g_ip_dscp_actif = TRUE;
+
+/* Defragment fragmented IP datagrams */
+static gboolean ip_defragment = FALSE;
+
+/* Place IP summary in proto tree */
+static gboolean ip_summary_in_tree = TRUE;
+
+static int proto_ip = -1;
+static int hf_ip_version = -1;
+static int hf_ip_hdr_len = -1;
+static int hf_ip_dsfield = -1;
+static int hf_ip_dsfield_dscp = -1;
+static int hf_ip_dsfield_ect = -1;
+static int hf_ip_dsfield_ce = -1;
+static int hf_ip_tos = -1;
+static int hf_ip_tos_precedence = -1;
+static int hf_ip_tos_delay = -1;
+static int hf_ip_tos_throughput = -1;
+static int hf_ip_tos_reliability = -1;
+static int hf_ip_tos_cost = -1;
+static int hf_ip_len = -1;
+static int hf_ip_id = -1;
+static int hf_ip_dst = -1;
+static int hf_ip_src = -1;
+static int hf_ip_addr = -1;
+static int hf_ip_flags = -1;
+static int hf_ip_flags_rf = -1;
+static int hf_ip_flags_df = -1;
+static int hf_ip_flags_mf = -1;
+static int hf_ip_frag_offset = -1;
+static int hf_ip_ttl = -1;
+static int hf_ip_proto = -1;
+static int hf_ip_checksum = -1;
+static int hf_ip_checksum_bad = -1;
+static int hf_ip_fragments = -1;
+static int hf_ip_fragment = -1;
+static int hf_ip_fragment_overlap = -1;
+static int hf_ip_fragment_overlap_conflict = -1;
+static int hf_ip_fragment_multiple_tails = -1;
+static int hf_ip_fragment_too_long_fragment = -1;
+static int hf_ip_fragment_error = -1;
+static int hf_ip_reassembled_in = -1;
+
+static gint ett_ip = -1;
+static gint ett_ip_dsfield = -1;
+static gint ett_ip_tos = -1;
+static gint ett_ip_off = -1;
+static gint ett_ip_options = -1;
+static gint ett_ip_option_sec = -1;
+static gint ett_ip_option_route = -1;
+static gint ett_ip_option_timestamp = -1;
+static gint ett_ip_fragments = -1;
+static gint ett_ip_fragment = -1;
+
+static const fragment_items ip_frag_items = {
+ &ett_ip_fragment,
+ &ett_ip_fragments,
+ &hf_ip_fragments,
+ &hf_ip_fragment,
+ &hf_ip_fragment_overlap,
+ &hf_ip_fragment_overlap_conflict,
+ &hf_ip_fragment_multiple_tails,
+ &hf_ip_fragment_too_long_fragment,
+ &hf_ip_fragment_error,
+ &hf_ip_reassembled_in,
+ "fragments"
+};
+
+static dissector_table_t ip_dissector_table;
+
+static dissector_handle_t ip_handle;
+static dissector_handle_t data_handle;
+
+static int proto_icmp = -1;
+static int hf_icmp_type = -1;
+static int hf_icmp_code = -1;
+static int hf_icmp_checksum = -1;
+static int hf_icmp_checksum_bad = -1;
+static int hf_icmp_ident = -1;
+static int hf_icmp_seq_num = -1;
+static int hf_icmp_mtu = -1;
+static int hf_icmp_redir_gw = -1;
+
+
+/* Mobile ip */
+static int hf_icmp_mip_type = -1;
+static int hf_icmp_mip_length = -1;
+static int hf_icmp_mip_prefix_length = -1;
+static int hf_icmp_mip_seq = -1;
+static int hf_icmp_mip_life = -1;
+static int hf_icmp_mip_flags = -1;
+static int hf_icmp_mip_r = -1;
+static int hf_icmp_mip_b = -1;
+static int hf_icmp_mip_h = -1;
+static int hf_icmp_mip_f = -1;
+static int hf_icmp_mip_m = -1;
+static int hf_icmp_mip_g = -1;
+static int hf_icmp_mip_v = -1;
+static int hf_icmp_mip_res = -1;
+static int hf_icmp_mip_reserved = -1;
+static int hf_icmp_mip_coa = -1;
+static int hf_icmp_mip_challenge = -1;
+
+static gint ett_icmp = -1;
+static gint ett_icmp_mip = -1;
+static gint ett_icmp_mip_flags = -1;
+
+/* ICMP definitions */
+
+#define ICMP_ECHOREPLY 0
+#define ICMP_UNREACH 3
+#define ICMP_SOURCEQUENCH 4
+#define ICMP_REDIRECT 5
+#define ICMP_ECHO 8
+#define ICMP_RTRADVERT 9
+#define ICMP_RTRSOLICIT 10
+#define ICMP_TIMXCEED 11
+#define ICMP_PARAMPROB 12
+#define ICMP_TSTAMP 13
+#define ICMP_TSTAMPREPLY 14
+#define ICMP_IREQ 15
+#define ICMP_IREQREPLY 16
+#define ICMP_MASKREQ 17
+#define ICMP_MASKREPLY 18
+
+/* ICMP UNREACHABLE */
+
+#define ICMP_NET_UNREACH 0 /* Network Unreachable */
+#define ICMP_HOST_UNREACH 1 /* Host Unreachable */
+#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */
+#define ICMP_PORT_UNREACH 3 /* Port Unreachable */
+#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
+#define ICMP_SR_FAILED 5 /* Source Route failed */
+#define ICMP_NET_UNKNOWN 6
+#define ICMP_HOST_UNKNOWN 7
+#define ICMP_HOST_ISOLATED 8
+#define ICMP_NET_ANO 9
+#define ICMP_HOST_ANO 10
+#define ICMP_NET_UNR_TOS 11
+#define ICMP_HOST_UNR_TOS 12
+#define ICMP_PKT_FILTERED 13 /* Packet filtered */
+#define ICMP_PREC_VIOLATION 14 /* Precedence violation */
+#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
+
+
+/* IP structs and definitions */
+
+/* Offsets of fields within an IP header. */
+#define IPH_V_HL 0
+#define IPH_TOS 1
+#define IPH_LEN 2
+#define IPH_ID 4
+#define IPH_TTL 6
+#define IPH_OFF 8
+#define IPH_P 9
+#define IPH_SUM 10
+#define IPH_SRC 12
+#define IPH_DST 16
+
+/* Minimum IP header length. */
+#define IPH_MIN_LEN 20
+
+/* IP flags. */
+#define IP_RF 0x8000 /* Flag: "Reserved bit" */
+#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
+#define IP_MF 0x2000 /* Flag: "More Fragments" */
+#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
+
+/* Differentiated Services Field. See RFCs 2474, 2597 and 2598. */
+#define IPDSFIELD_DSCP_MASK 0xFC
+#define IPDSFIELD_ECN_MASK 0x03
+#define IPDSFIELD_DSCP_SHIFT 2
+#define IPDSFIELD_DSCP(dsfield) (((dsfield)&IPDSFIELD_DSCP_MASK)>>IPDSFIELD_DSCP_SHIFT)
+#define IPDSFIELD_ECN(dsfield) ((dsfield)&IPDSFIELD_ECN_MASK)
+#define IPDSFIELD_DSCP_DEFAULT 0x00
+#define IPDSFIELD_DSCP_CS1 0x08
+#define IPDSFIELD_DSCP_CS2 0x10
+#define IPDSFIELD_DSCP_CS3 0x18
+#define IPDSFIELD_DSCP_CS4 0x20
+#define IPDSFIELD_DSCP_CS5 0x28
+#define IPDSFIELD_DSCP_CS6 0x30
+#define IPDSFIELD_DSCP_CS7 0x38
+#define IPDSFIELD_DSCP_AF11 0x0A
+#define IPDSFIELD_DSCP_AF12 0x0C
+#define IPDSFIELD_DSCP_AF13 0x0E
+#define IPDSFIELD_DSCP_AF21 0x12
+#define IPDSFIELD_DSCP_AF22 0x14
+#define IPDSFIELD_DSCP_AF23 0x16
+#define IPDSFIELD_DSCP_AF31 0x1A
+#define IPDSFIELD_DSCP_AF32 0x1C
+#define IPDSFIELD_DSCP_AF33 0x1E
+#define IPDSFIELD_DSCP_AF41 0x22
+#define IPDSFIELD_DSCP_AF42 0x24
+#define IPDSFIELD_DSCP_AF43 0x26
+#define IPDSFIELD_DSCP_EF 0x2E
+#define IPDSFIELD_ECT_MASK 0x02
+#define IPDSFIELD_CE_MASK 0x01
+
+/* IP TOS, superseded by the DS Field, RFC 2474. */
+#define IPTOS_TOS_MASK 0x1E
+#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
+#define IPTOS_NONE 0x00
+#define IPTOS_LOWCOST 0x02
+#define IPTOS_RELIABILITY 0x04
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_SECURITY 0x1E
+
+#define IPTOS_PREC_MASK 0xE0
+#define IPTOS_PREC_SHIFT 5
+#define IPTOS_PREC(tos) (((tos)&IPTOS_PREC_MASK)>>IPTOS_PREC_SHIFT)
+#define IPTOS_PREC_NETCONTROL 7
+#define IPTOS_PREC_INTERNETCONTROL 6
+#define IPTOS_PREC_CRITIC_ECP 5
+#define IPTOS_PREC_FLASHOVERRIDE 4
+#define IPTOS_PREC_FLASH 3
+#define IPTOS_PREC_IMMEDIATE 2
+#define IPTOS_PREC_PRIORITY 1
+#define IPTOS_PREC_ROUTINE 0
+
+/* IP options */
+#define IPOPT_COPY 0x80
+
+#define IPOPT_CONTROL 0x00
+#define IPOPT_RESERVED1 0x20
+#define IPOPT_MEASUREMENT 0x40
+#define IPOPT_RESERVED2 0x60
+
+#define IPOPT_END (0 |IPOPT_CONTROL)
+#define IPOPT_NOOP (1 |IPOPT_CONTROL)
+#define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY)
+#define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY)
+#define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT)
+#define IPOPT_RR (7 |IPOPT_CONTROL)
+#define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY)
+#define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY)
+#define IPOPT_RA (20|IPOPT_CONTROL|IPOPT_COPY)
+
+/* IP option lengths */
+#define IPOLEN_SEC 11
+#define IPOLEN_LSRR_MIN 3
+#define IPOLEN_TIMESTAMP_MIN 5
+#define IPOLEN_RR_MIN 3
+#define IPOLEN_SID 4
+#define IPOLEN_SSRR_MIN 3
+#define IPOLEN_RA 4
+
+#define IPSEC_UNCLASSIFIED 0x0000
+#define IPSEC_CONFIDENTIAL 0xF135
+#define IPSEC_EFTO 0x789A
+#define IPSEC_MMMM 0xBC4D
+#define IPSEC_RESTRICTED 0xAF13
+#define IPSEC_SECRET 0xD788
+#define IPSEC_TOPSECRET 0x6BC5
+#define IPSEC_RESERVED1 0x35E2
+#define IPSEC_RESERVED2 0x9AF1
+#define IPSEC_RESERVED3 0x4D78
+#define IPSEC_RESERVED4 0x24BD
+#define IPSEC_RESERVED5 0x135E
+#define IPSEC_RESERVED6 0x89AF
+#define IPSEC_RESERVED7 0xC4D6
+#define IPSEC_RESERVED8 0xE26B
+
+#define IPOPT_TS_TSONLY 0 /* timestamps only */
+#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
+#define IPOPT_TS_PRESPEC 3 /* specified modules only */
+
+/*
+ * defragmentation of IPv4
+ */
+static GHashTable *ip_fragment_table = NULL;
+static GHashTable *ip_reassembled_table = NULL;
+
+static void
+ip_defragment_init(void)
+{
+ fragment_table_init(&ip_fragment_table);
+ reassembled_table_init(&ip_reassembled_table);
+}
+
+void
+capture_ip(const guchar *pd, int offset, int len, packet_counts *ld) {
+ if (!BYTES_ARE_IN_FRAME(offset, len, IPH_MIN_LEN)) {
+ ld->other++;
+ return;
+ }
+ switch (pd[offset + 9]) {
+ case IP_PROTO_SCTP:
+ ld->sctp++;
+ break;
+ case IP_PROTO_TCP:
+ ld->tcp++;
+ break;
+ case IP_PROTO_UDP:
+ ld->udp++;
+ break;
+ case IP_PROTO_ICMP:
+ case IP_PROTO_ICMPV6: /* XXX - separate counters? */
+ ld->icmp++;
+ break;
+ case IP_PROTO_OSPF:
+ ld->ospf++;
+ break;
+ case IP_PROTO_GRE:
+ ld->gre++;
+ break;
+ case IP_PROTO_VINES:
+ ld->vines++;
+ break;
+ default:
+ ld->other++;
+ }
+}
+
+static void
+dissect_ipopt_security(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint optlen, packet_info *pinfo _U_,
+ proto_tree *opt_tree)
+{
+ proto_tree *field_tree = NULL;
+ proto_item *tf;
+ guint val;
+ static const value_string secl_vals[] = {
+ {IPSEC_UNCLASSIFIED, "Unclassified"},
+ {IPSEC_CONFIDENTIAL, "Confidential"},
+ {IPSEC_EFTO, "EFTO" },
+ {IPSEC_MMMM, "MMMM" },
+ {IPSEC_RESTRICTED, "Restricted" },
+ {IPSEC_SECRET, "Secret" },
+ {IPSEC_TOPSECRET, "Top secret" },
+ {IPSEC_RESERVED1, "Reserved" },
+ {IPSEC_RESERVED2, "Reserved" },
+ {IPSEC_RESERVED3, "Reserved" },
+ {IPSEC_RESERVED4, "Reserved" },
+ {IPSEC_RESERVED5, "Reserved" },
+ {IPSEC_RESERVED6, "Reserved" },
+ {IPSEC_RESERVED7, "Reserved" },
+ {IPSEC_RESERVED8, "Reserved" },
+ {0, NULL } };
+
+ tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2;
+
+ val = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(field_tree, tvb, offset, 2,
+ "Security: %s", val_to_str(val, secl_vals, "Unknown (0x%x)"));
+ offset += 2;
+
+ val = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(field_tree, tvb, offset, 2,
+ "Compartments: %u", val);
+ offset += 2;
+
+ proto_tree_add_text(field_tree, tvb, offset, 2,
+ "Handling restrictions: %c%c",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset + 1));
+ offset += 2;
+
+ proto_tree_add_text(field_tree, tvb, offset, 3,
+ "Transmission control code: %c%c%c",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset + 1),
+ tvb_get_guint8(tvb, offset + 2));
+}
+
+static void
+dissect_ipopt_route(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint optlen, packet_info *pinfo _U_,
+ proto_tree *opt_tree)
+{
+ proto_tree *field_tree = NULL;
+ proto_item *tf;
+ int ptr;
+ int optoffset = 0;
+ guint32 addr;
+
+ tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s (%u bytes)",
+ optp->name, optlen);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ optoffset += 2; /* skip past type and length */
+ optlen -= 2; /* subtract size of type and length */
+
+ ptr = tvb_get_guint8(tvb, offset + optoffset);
+ proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
+ "Pointer: %d%s", ptr,
+ ((ptr < 4) ? " (points before first address)" :
+ ((ptr & 3) ? " (points to middle of address)" : "")));
+ optoffset++;
+ optlen--;
+ ptr--; /* ptr is 1-origin */
+
+ while (optlen > 0) {
+ if (optlen < 4) {
+ proto_tree_add_text(field_tree, tvb, offset, optlen,
+ "(suboption would go past end of option)");
+ break;
+ }
+
+ /* Avoids alignment problems on many architectures. */
+ tvb_memcpy(tvb, (guint8 *)&addr, offset + optoffset, sizeof(addr));
+
+ proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
+ "%s%s",
+ ((addr == 0) ? "-" : (char *)get_hostname(addr)),
+ ((optoffset == ptr) ? " <- (current)" : ""));
+ optoffset += 4;
+ optlen -= 4;
+ }
+}
+
+static void
+dissect_ipopt_sid(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint optlen, packet_info *pinfo _U_,
+ proto_tree *opt_tree)
+{
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: %u", optp->name, tvb_get_ntohs(tvb, offset + 2));
+ return;
+}
+
+static void
+dissect_ipopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
+{
+ proto_tree *field_tree = NULL;
+ proto_item *tf;
+ int ptr;
+ int optoffset = 0;
+ int flg;
+ static const value_string flag_vals[] = {
+ {IPOPT_TS_TSONLY, "Time stamps only" },
+ {IPOPT_TS_TSANDADDR, "Time stamp and address" },
+ {IPOPT_TS_PRESPEC, "Time stamps for prespecified addresses"},
+ {0, NULL } };
+ guint32 addr;
+ guint ts;
+
+ tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ optoffset += 2; /* skip past type and length */
+ optlen -= 2; /* subtract size of type and length */
+
+ ptr = tvb_get_guint8(tvb, offset + optoffset);
+ proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
+ "Pointer: %d%s", ptr,
+ ((ptr < 5) ? " (points before first address)" :
+ (((ptr - 1) & 3) ? " (points to middle of address)" : "")));
+ optoffset++;
+ optlen--;
+ ptr--; /* ptr is 1-origin */
+
+ flg = tvb_get_guint8(tvb, offset + optoffset);
+ proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
+ "Overflow: %u", flg >> 4);
+ flg &= 0xF;
+ proto_tree_add_text(field_tree, tvb, offset + optoffset, 1,
+ "Flag: %s", val_to_str(flg, flag_vals, "Unknown (0x%x)"));
+ optoffset++;
+ optlen--;
+
+ while (optlen > 0) {
+ if (flg == IPOPT_TS_TSANDADDR) {
+ if (optlen < 8) {
+ proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
+ "(suboption would go past end of option)");
+ break;
+ }
+ tvb_memcpy(tvb, (char *)&addr, offset + optoffset, sizeof(addr));
+ ts = tvb_get_ntohl(tvb, offset + optoffset + 4);
+ optlen -= 8;
+ proto_tree_add_text(field_tree, tvb, offset + optoffset, 8,
+ "Address = %s, time stamp = %u",
+ ((addr == 0) ? "-" : (char *)get_hostname(addr)),
+ ts);
+ optoffset += 8;
+ } else {
+ if (optlen < 4) {
+ proto_tree_add_text(field_tree, tvb, offset + optoffset, optlen,
+ "(suboption would go past end of option)");
+ break;
+ }
+ ts = tvb_get_ntohl(tvb, offset + optoffset);
+ optlen -= 4;
+ proto_tree_add_text(field_tree, tvb, offset + optoffset, 4,
+ "Time stamp = %u", ts);
+ optoffset += 4;
+ }
+ }
+}
+
+static void
+dissect_ipopt_ra(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint optlen, packet_info *pinfo _U_, proto_tree *opt_tree)
+{
+ /* Router-Alert, as defined by RFC2113 */
+ int opt = tvb_get_ntohs(tvb, offset + 2);
+ static const value_string ra_opts[] = {
+ {0, "Every router examines packet"},
+ {0, NULL}
+ };
+
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: %s", optp->name, val_to_str(opt, ra_opts, "Unknown (%d)"));
+ return;
+}
+
+static const ip_tcp_opt ipopts[] = {
+ {
+ IPOPT_END,
+ "EOL",
+ NULL,
+ NO_LENGTH,
+ 0,
+ NULL,
+ },
+ {
+ IPOPT_NOOP,
+ "NOP",
+ NULL,
+ NO_LENGTH,
+ 0,
+ NULL,
+ },
+ {
+ IPOPT_SEC,
+ "Security",
+ &ett_ip_option_sec,
+ FIXED_LENGTH,
+ IPOLEN_SEC,
+ dissect_ipopt_security
+ },
+ {
+ IPOPT_SSRR,
+ "Strict source route",
+ &ett_ip_option_route,
+ VARIABLE_LENGTH,
+ IPOLEN_SSRR_MIN,
+ dissect_ipopt_route
+ },
+ {
+ IPOPT_LSRR,
+ "Loose source route",
+ &ett_ip_option_route,
+ VARIABLE_LENGTH,
+ IPOLEN_LSRR_MIN,
+ dissect_ipopt_route
+ },
+ {
+ IPOPT_RR,
+ "Record route",
+ &ett_ip_option_route,
+ VARIABLE_LENGTH,
+ IPOLEN_RR_MIN,
+ dissect_ipopt_route
+ },
+ {
+ IPOPT_SID,
+ "Stream identifier",
+ NULL,
+ FIXED_LENGTH,
+ IPOLEN_SID,
+ dissect_ipopt_sid
+ },
+ {
+ IPOPT_TIMESTAMP,
+ "Time stamp",
+ &ett_ip_option_timestamp,
+ VARIABLE_LENGTH,
+ IPOLEN_TIMESTAMP_MIN,
+ dissect_ipopt_timestamp
+ },
+ {
+ IPOPT_RA,
+ "Router Alert",
+ NULL,
+ FIXED_LENGTH,
+ IPOLEN_RA,
+ dissect_ipopt_ra
+ },
+};
+
+#define N_IP_OPTS (sizeof ipopts / sizeof ipopts[0])
+
+/* Dissect the IP or TCP options in a packet. */
+void
+dissect_ip_tcp_options(tvbuff_t *tvb, int offset, guint length,
+ const ip_tcp_opt *opttab, int nopts, int eol,
+ packet_info *pinfo, proto_tree *opt_tree)
+{
+ guchar opt;
+ const ip_tcp_opt *optp;
+ opt_len_type len_type;
+ unsigned int optlen;
+ char *name;
+ char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
+ void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
+ int, guint, packet_info *, proto_tree *);
+ guint len;
+
+ while (length > 0) {
+ opt = tvb_get_guint8(tvb, offset);
+ for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
+ if (optp->optcode == opt)
+ break;
+ }
+ if (optp == &opttab[nopts]) {
+ /* We assume that the only NO_LENGTH options are EOL and NOP options,
+ so that we can treat unknown options as VARIABLE_LENGTH with a
+ minimum of 2, and at least be able to move on to the next option
+ by using the length in the option. */
+ optp = NULL; /* indicate that we don't know this option */
+ len_type = VARIABLE_LENGTH;
+ optlen = 2;
+ snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
+ name = name_str;
+ dissect = NULL;
+ } else {
+ len_type = optp->len_type;
+ optlen = optp->optlen;
+ name = optp->name;
+ dissect = optp->dissect;
+ }
+ --length; /* account for type byte */
+ if (len_type != NO_LENGTH) {
+ /* Option has a length. Is it in the packet? */
+ if (length == 0) {
+ /* Bogus - packet must at least include option code byte and
+ length byte! */
+ proto_tree_add_text(opt_tree, tvb, offset, 1,
+ "%s (length byte past end of options)", name);
+ return;
+ }
+ len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
+ --length; /* account for length byte */
+ if (len < 2) {
+ /* Bogus - option length is too short to include option code and
+ option length. */
+ proto_tree_add_text(opt_tree, tvb, offset, 2,
+ "%s (with too-short option length = %u byte%s)", name,
+ len, plurality(len, "", "s"));
+ return;
+ } else if (len - 2 > length) {
+ /* Bogus - option goes past the end of the header. */
+ proto_tree_add_text(opt_tree, tvb, offset, length,
+ "%s (option length = %u byte%s says option goes past end of options)",
+ name, len, plurality(len, "", "s"));
+ return;
+ } else if (len_type == FIXED_LENGTH && len != optlen) {
+ /* Bogus - option length isn't what it's supposed to be for this
+ option. */
+ proto_tree_add_text(opt_tree, tvb, offset, len,
+ "%s (with option length = %u byte%s; should be %u)", name,
+ len, plurality(len, "", "s"), optlen);
+ return;
+ } else if (len_type == VARIABLE_LENGTH && len < optlen) {
+ /* Bogus - option length is less than what it's supposed to be for
+ this option. */
+ proto_tree_add_text(opt_tree, tvb, offset, len,
+ "%s (with option length = %u byte%s; should be >= %u)", name,
+ len, plurality(len, "", "s"), optlen);
+ return;
+ } else {
+ if (optp == NULL) {
+ proto_tree_add_text(opt_tree, tvb, offset, len, "%s (%u byte%s)",
+ name, len, plurality(len, "", "s"));
+ } else {
+ if (dissect != NULL) {
+ /* Option has a dissector. */
+ (*dissect)(optp, tvb, offset, len, pinfo, opt_tree);
+ } else {
+ /* Option has no data, hence no dissector. */
+ proto_tree_add_text(opt_tree, tvb, offset, len, "%s", name);
+ }
+ }
+ len -= 2; /* subtract size of type and length */
+ offset += 2 + len;
+ }
+ length -= len;
+ } else {
+ proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
+ offset += 1;
+ }
+ if (opt == eol)
+ break;
+ }
+}
+
+const value_string dscp_vals[] = {
+ { IPDSFIELD_DSCP_DEFAULT, "Default" },
+ { IPDSFIELD_DSCP_CS1, "Class Selector 1" },
+ { IPDSFIELD_DSCP_CS2, "Class Selector 2" },
+ { IPDSFIELD_DSCP_CS3, "Class Selector 3" },
+ { IPDSFIELD_DSCP_CS4, "Class Selector 4" },
+ { IPDSFIELD_DSCP_CS5, "Class Selector 5" },
+ { IPDSFIELD_DSCP_CS6, "Class Selector 6" },
+ { IPDSFIELD_DSCP_CS7, "Class Selector 7" },
+ { IPDSFIELD_DSCP_AF11, "Assured Forwarding 11" },
+ { IPDSFIELD_DSCP_AF12, "Assured Forwarding 12" },
+ { IPDSFIELD_DSCP_AF13, "Assured Forwarding 13" },
+ { IPDSFIELD_DSCP_AF21, "Assured Forwarding 21" },
+ { IPDSFIELD_DSCP_AF22, "Assured Forwarding 22" },
+ { IPDSFIELD_DSCP_AF23, "Assured Forwarding 23" },
+ { IPDSFIELD_DSCP_AF31, "Assured Forwarding 31" },
+ { IPDSFIELD_DSCP_AF32, "Assured Forwarding 32" },
+ { IPDSFIELD_DSCP_AF33, "Assured Forwarding 33" },
+ { IPDSFIELD_DSCP_AF41, "Assured Forwarding 41" },
+ { IPDSFIELD_DSCP_AF42, "Assured Forwarding 42" },
+ { IPDSFIELD_DSCP_AF43, "Assured Forwarding 43" },
+ { IPDSFIELD_DSCP_EF, "Expedited Forwarding" },
+ { 0, NULL } };
+
+static const value_string precedence_vals[] = {
+ { IPTOS_PREC_ROUTINE, "routine" },
+ { IPTOS_PREC_PRIORITY, "priority" },
+ { IPTOS_PREC_IMMEDIATE, "immediate" },
+ { IPTOS_PREC_FLASH, "flash" },
+ { IPTOS_PREC_FLASHOVERRIDE, "flash override" },
+ { IPTOS_PREC_CRITIC_ECP, "CRITIC/ECP" },
+ { IPTOS_PREC_INTERNETCONTROL, "internetwork control" },
+ { IPTOS_PREC_NETCONTROL, "network control" },
+ { 0, NULL } };
+
+static const value_string iptos_vals[] = {
+ { IPTOS_NONE, "None" },
+ { IPTOS_LOWCOST, "Minimize cost" },
+ { IPTOS_RELIABILITY, "Maximize reliability" },
+ { IPTOS_THROUGHPUT, "Maximize throughput" },
+ { IPTOS_LOWDELAY, "Minimize delay" },
+ { IPTOS_SECURITY, "Maximize security" },
+ { 0, NULL }
+};
+
+static const true_false_string tos_set_low = {
+ "Low",
+ "Normal"
+};
+
+static const true_false_string tos_set_high = {
+ "High",
+ "Normal"
+};
+
+static guint16 ip_checksum(const guint8 *ptr, int len)
+{
+ vec_t cksum_vec[1];
+
+ cksum_vec[0].ptr = ptr;
+ cksum_vec[0].len = len;
+ return in_cksum(&cksum_vec[0], 1);
+}
+
+static void
+dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ip_tree = NULL, *field_tree;
+ proto_item *ti = NULL, *tf;
+ guint32 addr;
+ int offset = 0;
+ guint hlen, optlen;
+ guint16 flags;
+ guint8 nxt;
+ guint16 ipsum;
+ fragment_data *ipfd_head=NULL;
+ tvbuff_t *next_tvb;
+ gboolean update_col_info = TRUE;
+ gboolean save_fragmented;
+ static e_ip eip_arr[4];
+ static int eip_current=0;
+ e_ip *iph;
+
+ eip_current++;
+ if(eip_current==4){
+ eip_current=0;
+ }
+ iph=&eip_arr[eip_current];
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ iph->ip_v_hl = tvb_get_guint8(tvb, offset);
+ hlen = lo_nibble(iph->ip_v_hl) * 4; /* IP header length, in bytes */
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ip, tvb, offset, hlen, FALSE);
+ ip_tree = proto_item_add_subtree(ti, ett_ip);
+
+ proto_tree_add_uint(ip_tree, hf_ip_version, tvb, offset, 1,
+ hi_nibble(iph->ip_v_hl));
+ }
+
+ if (hlen < IPH_MIN_LEN) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP header length (%u, must be at least %u)",
+ hlen, IPH_MIN_LEN);
+ if (tree) {
+ proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
+ "Header length: %u bytes (bogus, must be at least %u)", hlen,
+ IPH_MIN_LEN);
+ }
+ goto end_of_ip;
+ }
+
+ if (tree) {
+ proto_tree_add_uint_format(ip_tree, hf_ip_hdr_len, tvb, offset, 1, hlen,
+ "Header length: %u bytes", hlen);
+ }
+
+ iph->ip_tos = tvb_get_guint8(tvb, offset + 1);
+ if (tree) {
+ if (g_ip_dscp_actif) {
+ tf = proto_tree_add_uint_format(ip_tree, hf_ip_dsfield, tvb, offset + 1, 1, iph->ip_tos,
+ "Differentiated Services Field: 0x%02x (DSCP 0x%02x: %s; ECN: 0x%02x)", iph->ip_tos,
+ IPDSFIELD_DSCP(iph->ip_tos), val_to_str(IPDSFIELD_DSCP(iph->ip_tos), dscp_vals,
+ "Unknown DSCP"),IPDSFIELD_ECN(iph->ip_tos));
+
+ field_tree = proto_item_add_subtree(tf, ett_ip_dsfield);
+ proto_tree_add_uint(field_tree, hf_ip_dsfield_dscp, tvb, offset + 1, 1, iph->ip_tos);
+ proto_tree_add_uint(field_tree, hf_ip_dsfield_ect, tvb, offset + 1, 1, iph->ip_tos);
+ proto_tree_add_uint(field_tree, hf_ip_dsfield_ce, tvb, offset + 1, 1, iph->ip_tos);
+ } else {
+ tf = proto_tree_add_uint_format(ip_tree, hf_ip_tos, tvb, offset + 1, 1, iph->ip_tos,
+ "Type of service: 0x%02x (%s)", iph->ip_tos,
+ val_to_str( IPTOS_TOS(iph->ip_tos), iptos_vals, "Unknown") );
+
+ field_tree = proto_item_add_subtree(tf, ett_ip_tos);
+ proto_tree_add_uint(field_tree, hf_ip_tos_precedence, tvb, offset + 1, 1, iph->ip_tos);
+ proto_tree_add_boolean(field_tree, hf_ip_tos_delay, tvb, offset + 1, 1, iph->ip_tos);
+ proto_tree_add_boolean(field_tree, hf_ip_tos_throughput, tvb, offset + 1, 1, iph->ip_tos);
+ proto_tree_add_boolean(field_tree, hf_ip_tos_reliability, tvb, offset + 1, 1, iph->ip_tos);
+ proto_tree_add_boolean(field_tree, hf_ip_tos_cost, tvb, offset + 1, 1, iph->ip_tos);
+ }
+ }
+
+ /* Length of IP datagram.
+ XXX - what if this is greater than the reported length of the
+ tvbuff? This could happen, for example, in an IP datagram
+ inside an ICMP datagram; we need to somehow let the
+ dissector we call know that, as it might want to avoid
+ doing its checksumming. */
+ iph->ip_len = tvb_get_ntohs(tvb, offset + 2);
+
+ /* Adjust the length of this tvbuff to include only the IP datagram. */
+ set_actual_length(tvb, iph->ip_len);
+
+ if (iph->ip_len < hlen) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Bogus IP length (%u, less than header length %u)",
+ iph->ip_len, hlen);
+ if (tree) {
+ proto_tree_add_uint_format(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len,
+ "Total length: %u bytes (bogus, less than header length %u)", iph->ip_len,
+ hlen);
+ }
+ goto end_of_ip;
+ }
+ if (tree)
+ proto_tree_add_uint(ip_tree, hf_ip_len, tvb, offset + 2, 2, iph->ip_len);
+
+ iph->ip_id = tvb_get_ntohs(tvb, offset + 4);
+ if (tree)
+ proto_tree_add_uint_format(ip_tree, hf_ip_id, tvb, offset + 4, 2, iph->ip_id, "Identification: 0x%04x (%d)", iph->ip_id, iph->ip_id);
+
+ iph->ip_off = tvb_get_ntohs(tvb, offset + 6);
+ if (tree) {
+ flags = (iph->ip_off & (IP_RF | IP_DF | IP_MF)) >> 12;
+ tf = proto_tree_add_uint(ip_tree, hf_ip_flags, tvb, offset + 6, 1, flags);
+ field_tree = proto_item_add_subtree(tf, ett_ip_off);
+ proto_tree_add_boolean(field_tree, hf_ip_flags_rf, tvb, offset + 6, 1, flags);
+ if (flags & (IP_DF>>12)) proto_item_append_text(tf, " (Don't Fragment)");
+ proto_tree_add_boolean(field_tree, hf_ip_flags_df, tvb, offset + 6, 1, flags);
+ if (flags & (IP_MF>>12)) proto_item_append_text(tf, " (More Fragments)");
+ proto_tree_add_boolean(field_tree, hf_ip_flags_mf, tvb, offset + 6, 1, flags);
+
+ proto_tree_add_uint(ip_tree, hf_ip_frag_offset, tvb, offset + 6, 2,
+ (iph->ip_off & IP_OFFSET)*8);
+ }
+
+ if (tree)
+ proto_tree_add_item(ip_tree, hf_ip_ttl, tvb, offset + 8, 1, FALSE);
+
+ iph->ip_p = tvb_get_guint8(tvb, offset + 9);
+ if (tree) {
+ proto_tree_add_uint_format(ip_tree, hf_ip_proto, tvb, offset + 9, 1, iph->ip_p,
+ "Protocol: %s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
+ }
+
+ iph->ip_sum = tvb_get_ntohs(tvb, offset + 10);
+
+ /*
+ * If we have the entire IP header available, check the checksum.
+ */
+ if (tvb_bytes_exist(tvb, offset, hlen)) {
+ ipsum = ip_checksum(tvb_get_ptr(tvb, offset, hlen), hlen);
+ if (tree) {
+ if (ipsum == 0) {
+ proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
+ "Header checksum: 0x%04x (correct)", iph->ip_sum);
+ }
+ else {
+ proto_tree_add_boolean_hidden(ip_tree, hf_ip_checksum_bad, tvb, offset + 10, 2, TRUE);
+ proto_tree_add_uint_format(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum,
+ "Header checksum: 0x%04x (incorrect, should be 0x%04x)", iph->ip_sum,
+ in_cksum_shouldbe(iph->ip_sum, ipsum));
+ }
+ }
+ } else {
+ ipsum = 0;
+ if (tree)
+ proto_tree_add_uint(ip_tree, hf_ip_checksum, tvb, offset + 10, 2, iph->ip_sum);
+ }
+
+ SET_ADDRESS(&pinfo->net_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
+ SET_ADDRESS(&pinfo->src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
+ SET_ADDRESS(&iph->ip_src, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_SRC, 4));
+ if (tree) {
+ memcpy(&addr, iph->ip_src.data, 4);
+ if (ip_summary_in_tree) {
+ proto_item_append_text(ti, ", Src Addr: %s (%s)",
+ get_hostname(addr), ip_to_str((guint8 *) iph->ip_src.data));
+ }
+ proto_tree_add_ipv4(ip_tree, hf_ip_src, tvb, offset + 12, 4, addr);
+ proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 12, 4, addr);
+ }
+
+ SET_ADDRESS(&pinfo->net_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
+ SET_ADDRESS(&pinfo->dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
+ SET_ADDRESS(&iph->ip_dst, AT_IPv4, 4, tvb_get_ptr(tvb, offset + IPH_DST, 4));
+
+ if (tree) {
+ memcpy(&addr, iph->ip_dst.data, 4);
+ if (ip_summary_in_tree) {
+ proto_item_append_text(ti, ", Dst Addr: %s (%s)",
+ get_hostname(addr), ip_to_str((guint8 *) iph->ip_dst.data));
+ }
+ proto_tree_add_ipv4(ip_tree, hf_ip_dst, tvb, offset + 16, 4, addr);
+ proto_tree_add_ipv4_hidden(ip_tree, hf_ip_addr, tvb, offset + 16, 4, addr);
+ }
+
+ if (tree) {
+ /* Decode IP options, if any. */
+ if (hlen > IPH_MIN_LEN) {
+ /* There's more than just the fixed-length header. Decode the
+ options. */
+ optlen = hlen - IPH_MIN_LEN; /* length of options, in bytes */
+ tf = proto_tree_add_text(ip_tree, tvb, offset + 20, optlen,
+ "Options: (%u bytes)", optlen);
+ field_tree = proto_item_add_subtree(tf, ett_ip_options);
+ dissect_ip_tcp_options(tvb, offset + 20, optlen,
+ ipopts, N_IP_OPTS, IPOPT_END, pinfo, field_tree);
+ }
+ }
+
+ pinfo->ipproto = iph->ip_p;
+
+ pinfo->iplen = iph->ip_len;
+
+ pinfo->iphdrlen = hlen;
+
+ /* Skip over header + options */
+ offset += hlen;
+ nxt = iph->ip_p; /* XXX - what if this isn't the same for all fragments? */
+
+ /* If ip_defragment is on, this is a fragment, we have all the data
+ * in the fragment, and the header checksum is valid, then just add
+ * the fragment to the hashtable.
+ */
+ save_fragmented = pinfo->fragmented;
+ if (ip_defragment && (iph->ip_off & (IP_MF|IP_OFFSET)) &&
+ tvb_bytes_exist(tvb, offset, pinfo->iplen - pinfo->iphdrlen) &&
+ ipsum == 0) {
+ ipfd_head = fragment_add_check(tvb, offset, pinfo, iph->ip_id,
+ ip_fragment_table,
+ ip_reassembled_table,
+ (iph->ip_off & IP_OFFSET)*8,
+ pinfo->iplen - pinfo->iphdrlen,
+ iph->ip_off & IP_MF);
+
+ next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv4",
+ ipfd_head, &ip_frag_items, &update_col_info, ip_tree);
+ } else {
+ /* If this is the first fragment, dissect its contents, otherwise
+ just show it as a fragment.
+
+ XXX - if we eventually don't save the reassembled contents of all
+ fragmented datagrams, we may want to always reassemble. */
+ if (iph->ip_off & IP_OFFSET) {
+ /* Not the first fragment - don't dissect it. */
+ next_tvb = NULL;
+ } else {
+ /* First fragment, or not fragmented. Dissect what we have here. */
+
+ /* Get a tvbuff for the payload. */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ /*
+ * If this is the first fragment, but not the only fragment,
+ * tell the next protocol that.
+ */
+ if (iph->ip_off & IP_MF)
+ pinfo->fragmented = TRUE;
+ else
+ pinfo->fragmented = FALSE;
+ }
+ }
+
+ if (next_tvb == NULL) {
+ /* Just show this as a fragment. */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented IP protocol (proto=%s 0x%02x, off=%u)",
+ ipprotostr(iph->ip_p), iph->ip_p, (iph->ip_off & IP_OFFSET) * 8);
+ }
+ if( ipfd_head && ipfd_head->reassembled_in != pinfo->fd->num ){
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [Reassembled in #%u]",
+ ipfd_head->reassembled_in);
+ }
+ }
+
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo,
+ tree);
+ pinfo->fragmented = save_fragmented;
+ goto end_of_ip;
+ }
+
+ /* Hand off to the next protocol.
+
+ XXX - setting the columns only after trying various dissectors means
+ that if one of those dissectors throws an exception, the frame won't
+ even be labelled as an IP frame; ideally, if a frame being dissected
+ throws an exception, it'll be labelled as a mangled frame of the
+ type in question. */
+ if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
+ /* Unknown protocol */
+ if (update_col_info) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(iph->ip_p), iph->ip_p);
+ }
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+ pinfo->fragmented = save_fragmented;
+
+end_of_ip:
+ tap_queue_packet(ip_tap, pinfo, iph);
+
+}
+
+#define ICMP_MIP_EXTENSION_PAD 0
+#define ICMP_MIP_MOB_AGENT_ADV 16
+#define ICMP_MIP_PREFIX_LENGTHS 19
+#define ICMP_MIP_CHALLENGE 24
+
+static value_string mip_extensions[] = {
+ { ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */
+ { ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"},
+ /* RFC 2002 */
+ { ICMP_MIP_PREFIX_LENGTHS, "Prefix Lengths Extension"}, /* RFC 2002 */
+ { ICMP_MIP_CHALLENGE, "Challenge Extension"}, /* RFC 3012 */
+ { 0, NULL}
+};
+
+/*
+ * Dissect the mobile ip advertisement extensions.
+ */
+static void
+dissect_mip_extensions(tvbuff_t *tvb, size_t offset, proto_tree *tree)
+{
+ guint8 type;
+ guint8 length;
+ guint8 flags;
+ proto_item *ti;
+ proto_tree *mip_tree=NULL;
+ proto_tree *flags_tree=NULL;
+ gint numCOAs;
+ gint i;
+
+ /* Not much to do if we're not parsing everything */
+ if (!tree) return;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+
+ type = tvb_get_guint8(tvb, offset + 0);
+ if (type)
+ length = tvb_get_guint8(tvb, offset + 1);
+ else
+ length=0;
+
+ ti = proto_tree_add_text(tree, tvb, offset,
+ type?(length + 2):1,
+ "Ext: %s",
+ val_to_str(type, mip_extensions,
+ "Unknown ext %u"));
+ mip_tree = proto_item_add_subtree(ti, ett_icmp_mip);
+
+
+ switch (type) {
+ case ICMP_MIP_EXTENSION_PAD:
+ /* One byte padding extension */
+ /* Add our fields */
+ /* type */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
+ 1, FALSE);
+ offset++;
+ break;
+ case ICMP_MIP_MOB_AGENT_ADV:
+ /* Mobility Agent Advertisement Extension (RFC 2002)*/
+ /* Add our fields */
+ /* type */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
+ 1, FALSE);
+ offset++;
+ /* length */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
+ 1, FALSE);
+ offset++;
+ /* sequence number */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_seq, tvb, offset,
+ 2, FALSE);
+ offset+=2;
+ /* Registration Lifetime */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_life, tvb, offset,
+ 2, FALSE);
+ offset+=2;
+ /* flags */
+ flags = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_item(mip_tree, hf_icmp_mip_flags, tvb, offset,
+ 1, FALSE);
+ flags_tree = proto_item_add_subtree(ti, ett_icmp_mip_flags);
+ proto_tree_add_boolean(flags_tree, hf_icmp_mip_r, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_icmp_mip_b, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_icmp_mip_h, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_icmp_mip_f, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_icmp_mip_m, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_icmp_mip_g, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_icmp_mip_v, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_icmp_mip_res, tvb, offset, 1, flags);
+ offset++;
+
+ /* Reserved */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_reserved, tvb, offset,
+ 1, FALSE);
+ offset++;
+
+ /* COAs */
+ numCOAs = (length - 6) / 4;
+ for (i=0; i<numCOAs; i++) {
+ proto_tree_add_item(mip_tree, hf_icmp_mip_coa, tvb, offset,
+ 4, FALSE);
+ offset+=4;
+ }
+ break;
+ case ICMP_MIP_PREFIX_LENGTHS:
+ /* Prefix-Lengths Extension (RFC 2002)*/
+ /* Add our fields */
+ /* type */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
+ 1, FALSE);
+ offset++;
+ /* length */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
+ 1, FALSE);
+ offset++;
+
+ /* prefix lengths */
+ for(i=0; i<length; i++) {
+ proto_tree_add_item(mip_tree, hf_icmp_mip_prefix_length, tvb, offset,
+ 1, FALSE);
+ offset++;
+ }
+ break;
+ case ICMP_MIP_CHALLENGE:
+ /* Challenge Extension (RFC 3012)*/
+ /* type */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_type, tvb, offset,
+ 1, FALSE);
+ offset++;
+ /* length */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_length, tvb, offset,
+ 1, FALSE);
+ offset++;
+ /* challenge */
+ proto_tree_add_item(mip_tree, hf_icmp_mip_challenge, tvb, offset,
+ length, FALSE);
+ offset+=length;
+
+ break;
+ default:
+ g_warning("Unknown type(%u)! I hope the length is right (%u)",
+ type, length);
+ offset += length + 2;
+ break;
+ } /* switch type */
+ } /* end while */
+
+} /* dissect_mip_extensions */
+
+static const gchar *unreach_str[] = {"Network unreachable",
+ "Host unreachable",
+ "Protocol unreachable",
+ "Port unreachable",
+ "Fragmentation needed",
+ "Source route failed",
+ "Destination network unknown",
+ "Destination host unknown",
+ "Source host isolated",
+ "Network administratively prohibited",
+ "Host administratively prohibited",
+ "Network unreachable for TOS",
+ "Host unreachable for TOS",
+ "Communication administratively filtered",
+ "Host precedence violation",
+ "Precedence cutoff in effect"};
+
+#define N_UNREACH (sizeof unreach_str / sizeof unreach_str[0])
+
+static const gchar *redir_str[] = {"Redirect for network",
+ "Redirect for host",
+ "Redirect for TOS and network",
+ "Redirect for TOS and host"};
+
+#define N_REDIRECT (sizeof redir_str / sizeof redir_str[0])
+
+static const gchar *ttl_str[] = {"Time to live exceeded in transit",
+ "Fragment reassembly time exceeded"};
+
+#define N_TIMXCEED (sizeof ttl_str / sizeof ttl_str[0])
+
+static const gchar *par_str[] = {"IP header bad", "Required option missing"};
+
+#define N_PARAMPROB (sizeof par_str / sizeof par_str[0])
+
+/*
+ * RFC 792 for basic ICMP.
+ * RFC 1191 for ICMP_FRAG_NEEDED (with MTU of next hop).
+ * RFC 1256 for router discovery messages.
+ * RFC 2002 and 3012 for Mobile IP stuff.
+ */
+static void
+dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *icmp_tree;
+ proto_item *ti;
+ guint8 icmp_type;
+ guint8 icmp_code;
+ guint length, reported_length;
+ guint16 cksum, computed_cksum;
+ gchar type_str[64], code_str[64] = "";
+ guint8 num_addrs = 0;
+ guint8 addr_entry_size = 0;
+ int i;
+ gboolean save_in_error_pkt;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ICMP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* To do: check for runts, errs, etc. */
+ icmp_type = tvb_get_guint8(tvb, 0);
+ icmp_code = tvb_get_guint8(tvb, 1);
+ cksum = tvb_get_ntohs(tvb, 2);
+
+ switch (icmp_type) {
+ case ICMP_ECHOREPLY:
+ strcpy(type_str, "Echo (ping) reply");
+ break;
+ case ICMP_UNREACH:
+ strcpy(type_str, "Destination unreachable");
+ if (icmp_code < N_UNREACH) {
+ sprintf(code_str, "(%s)", unreach_str[icmp_code]);
+ } else {
+ strcpy(code_str, "(Unknown - error?)");
+ }
+ break;
+ case ICMP_SOURCEQUENCH:
+ strcpy(type_str, "Source quench (flow control)");
+ break;
+ case ICMP_REDIRECT:
+ strcpy(type_str, "Redirect");
+ if (icmp_code < N_REDIRECT) {
+ sprintf(code_str, "(%s)", redir_str[icmp_code]);
+ } else {
+ strcpy(code_str, "(Unknown - error?)");
+ }
+ break;
+ case ICMP_ECHO:
+ strcpy(type_str, "Echo (ping) request");
+ break;
+ case ICMP_RTRADVERT:
+ switch (icmp_code) {
+ case 16: /* Mobile-Ip */
+ strcpy(type_str, "Mobile IP Advertisement");
+ break;
+ default:
+ strcpy(type_str, "Router advertisement");
+ break;
+ } /* switch icmp_code */
+ break;
+ case ICMP_RTRSOLICIT:
+ strcpy(type_str, "Router solicitation");
+ break;
+ case ICMP_TIMXCEED:
+ strcpy(type_str, "Time-to-live exceeded");
+ if (icmp_code < N_TIMXCEED) {
+ sprintf(code_str, "(%s)", ttl_str[icmp_code]);
+ } else {
+ strcpy(code_str, "(Unknown - error?)");
+ }
+ break;
+ case ICMP_PARAMPROB:
+ strcpy(type_str, "Parameter problem");
+ if (icmp_code < N_PARAMPROB) {
+ sprintf(code_str, "(%s)", par_str[icmp_code]);
+ } else {
+ strcpy(code_str, "(Unknown - error?)");
+ }
+ break;
+ case ICMP_TSTAMP:
+ strcpy(type_str, "Timestamp request");
+ break;
+ case ICMP_TSTAMPREPLY:
+ strcpy(type_str, "Timestamp reply");
+ break;
+ case ICMP_IREQ:
+ strcpy(type_str, "Information request");
+ break;
+ case ICMP_IREQREPLY:
+ strcpy(type_str, "Information reply");
+ break;
+ case ICMP_MASKREQ:
+ strcpy(type_str, "Address mask request");
+ break;
+ case ICMP_MASKREPLY:
+ strcpy(type_str, "Address mask reply");
+ break;
+ default:
+ strcpy(type_str, "Unknown ICMP (obsolete or malformed?)");
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, type_str);
+
+ if (tree) {
+ length = tvb_length(tvb);
+ reported_length = tvb_reported_length(tvb);
+ ti = proto_tree_add_item(tree, proto_icmp, tvb, 0, length, FALSE);
+ icmp_tree = proto_item_add_subtree(ti, ett_icmp);
+ proto_tree_add_uint_format(icmp_tree, hf_icmp_type, tvb, 0, 1,
+ icmp_type,
+ "Type: %u (%s)",
+ icmp_type, type_str);
+ proto_tree_add_uint_format(icmp_tree, hf_icmp_code, tvb, 1, 1,
+ icmp_code,
+ "Code: %u %s",
+ icmp_code, code_str);
+
+ if (!pinfo->fragmented && length >= reported_length) {
+ /* The packet isn't part of a fragmented datagram and isn't
+ truncated, so we can checksum it. */
+
+ computed_cksum = ip_checksum(tvb_get_ptr(tvb, 0, reported_length),
+ reported_length);
+ if (computed_cksum == 0) {
+ proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
+ cksum,
+ "Checksum: 0x%04x (correct)", cksum);
+ } else {
+ proto_tree_add_boolean_hidden(icmp_tree, hf_icmp_checksum_bad,
+ tvb, 2, 2, TRUE);
+ proto_tree_add_uint_format(icmp_tree, hf_icmp_checksum, tvb, 2, 2,
+ cksum,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ cksum, in_cksum_shouldbe(cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_uint(icmp_tree, hf_icmp_checksum, tvb, 2, 2, cksum);
+ }
+
+ /* Decode the second 4 bytes of the packet. */
+ switch (icmp_type) {
+ case ICMP_ECHOREPLY:
+ case ICMP_ECHO:
+ case ICMP_TSTAMP:
+ case ICMP_TSTAMPREPLY:
+ case ICMP_IREQ:
+ case ICMP_IREQREPLY:
+ case ICMP_MASKREQ:
+ case ICMP_MASKREPLY:
+ proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, FALSE);
+ proto_tree_add_item(icmp_tree, hf_icmp_seq_num, tvb, 6, 2, FALSE);
+ break;
+
+ case ICMP_UNREACH:
+ switch (icmp_code) {
+ case ICMP_FRAG_NEEDED:
+ proto_tree_add_item(icmp_tree, hf_icmp_mtu, tvb, 6, 2, FALSE);
+ break;
+ }
+ break;
+
+ case ICMP_RTRADVERT:
+ num_addrs = tvb_get_guint8(tvb, 4);
+ proto_tree_add_text(icmp_tree, tvb, 4, 1, "Number of addresses: %u",
+ num_addrs);
+ addr_entry_size = tvb_get_guint8(tvb, 5);
+ proto_tree_add_text(icmp_tree, tvb, 5, 1, "Address entry size: %u",
+ addr_entry_size);
+ proto_tree_add_text(icmp_tree, tvb, 6, 2, "Lifetime: %s",
+ time_secs_to_str(tvb_get_ntohs(tvb, 6)));
+ break;
+
+ case ICMP_PARAMPROB:
+ proto_tree_add_text(icmp_tree, tvb, 4, 1, "Pointer: %u",
+ tvb_get_guint8(tvb, 4));
+ break;
+
+ case ICMP_REDIRECT:
+ proto_tree_add_item(icmp_tree, hf_icmp_redir_gw, tvb, 4, 4, FALSE);
+ break;
+ }
+
+ /* Decode the additional information in the packet. */
+ switch (icmp_type) {
+ case ICMP_UNREACH:
+ case ICMP_TIMXCEED:
+ case ICMP_PARAMPROB:
+ case ICMP_SOURCEQUENCH:
+ case ICMP_REDIRECT:
+ /* Save the current value of the "we're inside an error packet"
+ flag, and set that flag; subdissectors may treat packets
+ that are the payload of error packets differently from
+ "real" packets. */
+ save_in_error_pkt = pinfo->in_error_pkt;
+ pinfo->in_error_pkt = TRUE;
+
+ /* Decode the IP header and first 64 bits of data from the
+ original datagram. */
+ next_tvb = tvb_new_subset(tvb, 8, -1, -1);
+ call_dissector(ip_handle, next_tvb, pinfo, icmp_tree);
+
+ /* Restore the "we're inside an error packet" flag. */
+ pinfo->in_error_pkt = save_in_error_pkt;
+ break;
+
+ case ICMP_ECHOREPLY:
+ case ICMP_ECHO:
+ call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
+ icmp_tree);
+ break;
+
+ case ICMP_RTRADVERT:
+ if (addr_entry_size == 2) {
+ for (i = 0; i < num_addrs; i++) {
+ proto_tree_add_text(icmp_tree, tvb, 8 + (i*8), 4,
+ "Router address: %s",
+ ip_to_str(tvb_get_ptr(tvb, 8 + (i*8), 4)));
+ proto_tree_add_text(icmp_tree, tvb, 12 + (i*8), 4,
+ "Preference level: %d", tvb_get_ntohl(tvb, 12 + (i*8)));
+ }
+ if (icmp_code == 16) {
+ /* Mobile-Ip */
+ dissect_mip_extensions(tvb, 8 + i*8, icmp_tree);
+ }
+ } else
+ call_dissector(data_handle, tvb_new_subset(tvb, 8, -1, -1), pinfo,
+ icmp_tree);
+ break;
+
+ case ICMP_TSTAMP:
+ case ICMP_TSTAMPREPLY:
+ proto_tree_add_text(icmp_tree, tvb, 8, 4, "Originate timestamp: %u",
+ tvb_get_ntohl(tvb, 8));
+ proto_tree_add_text(icmp_tree, tvb, 12, 4, "Receive timestamp: %u",
+ tvb_get_ntohl(tvb, 12));
+ proto_tree_add_text(icmp_tree, tvb, 16, 4, "Transmit timestamp: %u",
+ tvb_get_ntohl(tvb, 16));
+ break;
+
+ case ICMP_MASKREQ:
+ case ICMP_MASKREPLY:
+ proto_tree_add_text(icmp_tree, tvb, 8, 4, "Address mask: %s (0x%08x)",
+ ip_to_str(tvb_get_ptr(tvb, 8, 4)), tvb_get_ntohl(tvb, 8));
+ break;
+ }
+ }
+}
+
+void
+proto_register_ip(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_ip_version,
+ { "Version", "ip.version", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_hdr_len,
+ { "Header Length", "ip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_dsfield,
+ { "Differentiated Services field", "ip.dsfield", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_dsfield_dscp,
+ { "Differentiated Services Codepoint", "ip.dsfield.dscp", FT_UINT8, BASE_HEX,
+ VALS(dscp_vals), IPDSFIELD_DSCP_MASK,
+ "", HFILL }},
+
+ { &hf_ip_dsfield_ect,
+ { "ECN-Capable Transport (ECT)", "ip.dsfield.ect", FT_UINT8, BASE_DEC, NULL,
+ IPDSFIELD_ECT_MASK,
+ "", HFILL }},
+
+ { &hf_ip_dsfield_ce,
+ { "ECN-CE", "ip.dsfield.ce", FT_UINT8, BASE_DEC, NULL,
+ IPDSFIELD_CE_MASK,
+ "", HFILL }},
+
+ { &hf_ip_tos,
+ { "Type of Service", "ip.tos", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_tos_precedence,
+ { "Precedence", "ip.tos.precedence", FT_UINT8, BASE_DEC, VALS(precedence_vals),
+ IPTOS_PREC_MASK,
+ "", HFILL }},
+
+ { &hf_ip_tos_delay,
+ { "Delay", "ip.tos.delay", FT_BOOLEAN, 8, TFS(&tos_set_low),
+ IPTOS_LOWDELAY,
+ "", HFILL }},
+
+ { &hf_ip_tos_throughput,
+ { "Throughput", "ip.tos.throughput", FT_BOOLEAN, 8, TFS(&tos_set_high),
+ IPTOS_THROUGHPUT,
+ "", HFILL }},
+
+ { &hf_ip_tos_reliability,
+ { "Reliability", "ip.tos.reliability", FT_BOOLEAN, 8, TFS(&tos_set_high),
+ IPTOS_RELIABILITY,
+ "", HFILL }},
+
+ { &hf_ip_tos_cost,
+ { "Cost", "ip.tos.cost", FT_BOOLEAN, 8, TFS(&tos_set_low),
+ IPTOS_LOWCOST,
+ "", HFILL }},
+
+ { &hf_ip_len,
+ { "Total Length", "ip.len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_id,
+ { "Identification", "ip.id", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_dst,
+ { "Destination", "ip.dst", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_src,
+ { "Source", "ip.src", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_addr,
+ { "Source or Destination Address", "ip.addr", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_flags,
+ { "Flags", "ip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_flags_rf,
+ { "Reserved bit", "ip.flags.rb", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_RF >> 12,
+ "", HFILL }},
+
+ { &hf_ip_flags_df,
+ { "Don't fragment", "ip.flags.df", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_DF >> 12,
+ "", HFILL }},
+
+ { &hf_ip_flags_mf,
+ { "More fragments", "ip.flags.mf", FT_BOOLEAN, 4, TFS(&flags_set_truth), IP_MF >> 12,
+ "", HFILL }},
+
+ { &hf_ip_frag_offset,
+ { "Fragment offset", "ip.frag_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_ttl,
+ { "Time to live", "ip.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_proto,
+ { "Protocol", "ip.proto", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_checksum,
+ { "Header checksum", "ip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_checksum_bad,
+ { "Bad Header checksum", "ip.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ip_fragment_overlap,
+ { "Fragment overlap", "ip.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_ip_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "ip.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_ip_fragment_multiple_tails,
+ { "Multiple tail fragments found", "ip.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_ip_fragment_too_long_fragment,
+ { "Fragment too long", "ip.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+
+ { &hf_ip_fragment_error,
+ { "Defragmentation error", "ip.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }},
+
+ { &hf_ip_fragment,
+ { "IP Fragment", "ip.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "IP Fragment", HFILL }},
+
+ { &hf_ip_fragments,
+ { "IP Fragments", "ip.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
+ "IP Fragments", HFILL }},
+
+ { &hf_ip_reassembled_in,
+ { "Reassembled IP in frame", "ip.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This IP packet is reassembled in this frame", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_ip,
+ &ett_ip_dsfield,
+ &ett_ip_tos,
+ &ett_ip_off,
+ &ett_ip_options,
+ &ett_ip_option_sec,
+ &ett_ip_option_route,
+ &ett_ip_option_timestamp,
+ &ett_ip_fragments,
+ &ett_ip_fragment,
+ };
+ module_t *ip_module;
+
+ proto_ip = proto_register_protocol("Internet Protocol", "IP", "ip");
+ proto_register_field_array(proto_ip, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ ip_dissector_table = register_dissector_table("ip.proto",
+ "IP protocol", FT_UINT8, BASE_DEC);
+
+ /* Register configuration options */
+ ip_module = prefs_register_protocol(proto_ip, NULL);
+ prefs_register_bool_preference(ip_module, "decode_tos_as_diffserv",
+ "Decode IPv4 TOS field as DiffServ field",
+ "Whether the IPv4 type-of-service field should be decoded as a Differentiated Services field",
+ &g_ip_dscp_actif);
+ prefs_register_bool_preference(ip_module, "defragment",
+ "Reassemble fragmented IP datagrams",
+ "Whether fragmented IP datagrams should be reassembled",
+ &ip_defragment);
+ prefs_register_bool_preference(ip_module, "summary_in_tree",
+ "Show IP summary in protocol tree",
+ "Whether the IP summary line should be shown in the protocol tree",
+ &ip_summary_in_tree);
+
+ register_dissector("ip", dissect_ip, proto_ip);
+ register_init_routine(ip_defragment_init);
+ ip_tap=register_tap("ip");
+}
+
+void
+proto_reg_handoff_ip(void)
+{
+ dissector_handle_t ip_handle;
+
+ data_handle = find_dissector("data");
+ ip_handle = find_dissector("ip");
+ dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
+ dissector_add("ppp.protocol", PPP_IP, ip_handle);
+ dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
+ dissector_add("gre.proto", ETHERTYPE_IP, ip_handle);
+ dissector_add("gre.proto", GRE_WCCP, ip_handle);
+ dissector_add("llc.dsap", SAP_IP, ip_handle);
+ dissector_add("ip.proto", IP_PROTO_IPIP, ip_handle);
+ dissector_add("null.type", BSD_AF_INET, ip_handle);
+ dissector_add("chdlctype", ETHERTYPE_IP, ip_handle);
+ dissector_add("fr.ietf", NLPID_IP, ip_handle);
+ dissector_add("x.25.spi", NLPID_IP, ip_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1051, ip_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_IP_1201, ip_handle);
+}
+
+void
+proto_register_icmp(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_icmp_type,
+ { "Type", "icmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_icmp_code,
+ { "Code", "icmp.code", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_icmp_checksum,
+ { "Checksum", "icmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_icmp_checksum_bad,
+ { "Bad Checksum", "icmp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_icmp_ident,
+ {"Identifier", "icmp.ident", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_icmp_seq_num,
+ {"Sequence number", "icmp.seq", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_icmp_mtu,
+ {"MTU of next hop", "icmp.mtu", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_icmp_redir_gw,
+ {"Gateway address", "icmp.redir_gw", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_icmp_mip_type,
+ { "Extension Type", "icmp.mip.type", FT_UINT8, BASE_DEC,
+ VALS(mip_extensions), 0x0,"", HFILL}},
+
+ { &hf_icmp_mip_length,
+ { "Length", "icmp.mip.length", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_icmp_mip_prefix_length,
+ { "Prefix Length", "icmp.mip.prefixlength", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_icmp_mip_seq,
+ { "Sequence Number", "icmp.mip.seq", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_icmp_mip_life,
+ { "Registration Lifetime", "icmp.mip.life", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_icmp_mip_flags,
+ { "Flags", "icmp.mip.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_icmp_mip_r,
+ { "Registration Required", "icmp.mip.r", FT_BOOLEAN, 8, NULL, 128,
+ "Registration with this FA is required", HFILL }},
+
+ { &hf_icmp_mip_b,
+ { "Busy", "icmp.mip.b", FT_BOOLEAN, 8, NULL, 64,
+ "This FA will not accept requests at this time", HFILL }},
+
+ { &hf_icmp_mip_h,
+ { "Home Agent", "icmp.mip.h", FT_BOOLEAN, 8, NULL, 32,
+ "Home Agent Services Offered", HFILL }},
+
+ { &hf_icmp_mip_f,
+ { "Foreign Agent", "icmp.mip.f", FT_BOOLEAN, 8, NULL, 16,
+ "Foreign Agent Services Offered", HFILL }},
+
+ { &hf_icmp_mip_m,
+ { "Minimal Encapsulation", "icmp.mip.m", FT_BOOLEAN, 8, NULL, 8,
+ "Minimal encapsulation tunneled datagram support", HFILL }},
+
+ { &hf_icmp_mip_g,
+ { "GRE", "icmp.mip.g", FT_BOOLEAN, 8, NULL, 4,
+ "GRE encapsulated tunneled datagram support", HFILL }},
+
+ { &hf_icmp_mip_v,
+ { "VJ Comp", "icmp.mip.v", FT_BOOLEAN, 8, NULL, 2,
+ "Van Jacobson Header Compression Support", HFILL }},
+
+ { &hf_icmp_mip_res,
+ { "Reserved", "icmp.mip.res", FT_BOOLEAN, 8, NULL, 1,
+ "Reserved", HFILL }},
+
+ { &hf_icmp_mip_reserved,
+ { "Reserved", "icmp.mip.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_icmp_mip_coa,
+ { "Care-Of-Address", "icmp.mip.coa", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_icmp_mip_challenge,
+ { "Challenge", "icmp.mip.challenge", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ };
+ static gint *ett[] = {
+ &ett_icmp,
+ &ett_icmp_mip,
+ &ett_icmp_mip_flags
+ };
+
+ proto_icmp = proto_register_protocol("Internet Control Message Protocol",
+ "ICMP", "icmp");
+ proto_register_field_array(proto_icmp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_icmp(void)
+{
+ dissector_handle_t icmp_handle;
+
+ /*
+ * Get handle for the IP dissector.
+ */
+ ip_handle = find_dissector("ip");
+
+ icmp_handle = create_dissector_handle(dissect_icmp, proto_icmp);
+ dissector_add("ip.proto", IP_PROTO_ICMP, icmp_handle);
+}
diff --git a/epan/dissectors/packet-ip.h b/epan/dissectors/packet-ip.h
new file mode 100644
index 0000000000..43c6f5e5ac
--- /dev/null
+++ b/epan/dissectors/packet-ip.h
@@ -0,0 +1,48 @@
+/* packet-ip.h
+ * Definitions for IP packet disassembly structures and routines
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __PACKET_IP_H__
+#define __PACKET_IP_H__
+
+typedef struct _e_ip
+ {
+ guint8 ip_v_hl; /* combines ip_v and ip_hl */
+ guint8 ip_tos;
+ guint16 ip_len;
+ guint16 ip_id;
+ guint16 ip_off;
+ guint8 ip_ttl;
+ guint8 ip_p;
+ guint16 ip_sum;
+ address ip_src;
+ address ip_dst;
+} e_ip;
+
+void capture_ip(const guchar *, int, int, packet_counts *);
+
+/* Export the DSCP value-string table for other protocols */
+extern const value_string dscp_vals[];
+
+#endif
diff --git a/epan/dissectors/packet-ipdc.c b/epan/dissectors/packet-ipdc.c
new file mode 100644
index 0000000000..e2378ba6e2
--- /dev/null
+++ b/epan/dissectors/packet-ipdc.c
@@ -0,0 +1,442 @@
+/* packet-ipdc.c
+ * Routines for IP Device Control (SS7 over IP) dissection
+ * Copyright Lucent Technologies 2004
+ * Josh Bailey <joshbailey@lucent.com> and Ruud Linders <ruud@lucent.com>
+ *
+ * Using IPDC spec 0.20.2
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <math.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "packet-ipdc.h"
+#include "packet-tcp.h"
+#include <epan/packet.h>
+#include "ipproto.h"
+#include "prefs.h"
+
+static int proto_ipdc = -1;
+static int hf_ipdc_nr = -1;
+static int hf_ipdc_ns = -1;
+static int hf_ipdc_payload_len = -1;
+static int hf_ipdc_protocol_id = -1;
+static int hf_ipdc_trans_id_size = -1;
+static int hf_ipdc_trans_id = -1;
+static int hf_ipdc_message_code = -1;
+
+static gint ett_ipdc = -1;
+static gint ett_ipdc_tag = -1;
+
+static gboolean ipdc_desegment = TRUE;
+static gint ipdc_port_pref = TCP_PORT_IPDC;
+static gboolean new_packet = FALSE;
+
+static dissector_handle_t q931_handle;
+
+void proto_reg_handoff_ipdc(void);
+
+
+static guint
+get_ipdc_pdu_len(tvbuff_t *tvb, int offset)
+{
+ return tvb_get_ntohs(tvb,offset+2)+4;
+}
+
+static void
+dissect_ipdc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *ipdc_tree;
+ proto_item *ipdc_tag;
+ proto_tree *tag_tree;
+ tvbuff_t *q931_tvb;
+
+ char *des;
+ char *enum_val;
+ char *tmp_str;
+ char tmp_tag_text[IPDC_STR_LEN + 1];
+ const value_string *val_ptr;
+ guint32 type;
+ guint len;
+ guint i;
+ guint status;
+ gshort tag;
+ guint32 tmp_tag;
+
+ gshort nr = tvb_get_guint8(tvb,0);
+ gshort ns = tvb_get_guint8(tvb,1);
+ guint16 payload_len = (guint16) get_ipdc_pdu_len(tvb,0);
+
+ gshort protocol_id;
+ gshort trans_id_size;
+ guint32 trans_id;
+ guint16 message_code;
+ guint16 offset;
+
+ /* display IPDC protocol ID */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPDC");
+
+ /* short frame... */
+ if (payload_len < 4)
+ return;
+
+ /* clear info column and display send/receive sequence numbers */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (new_packet == TRUE) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ new_packet = FALSE;
+ }
+ col_append_fstr(pinfo->cinfo, COL_INFO, "r=%u s=%u ",
+ nr, ns);
+ }
+
+ if (payload_len == 4) {
+ if (!tree)
+ return;
+
+ ti = proto_tree_add_item(tree, proto_ipdc, tvb, 0, -1, FALSE);
+ ipdc_tree = proto_item_add_subtree(ti, ett_ipdc);
+ proto_tree_add_item(ipdc_tree, hf_ipdc_nr, tvb, 0, 1, nr);
+ proto_tree_add_item(ipdc_tree, hf_ipdc_ns, tvb, 1, 1, ns);
+ proto_tree_add_uint(ipdc_tree, hf_ipdc_payload_len, tvb, 2, 2,
+ payload_len);
+
+ return;
+ }
+
+ /* IPDC tags present - display message code and trans. ID */
+ protocol_id = tvb_get_guint8(tvb,4);
+ trans_id_size = TRANS_ID_SIZE_IPDC;
+ trans_id = tvb_get_ntohl(tvb,6);
+ message_code = tvb_get_ntohs(tvb,6+trans_id_size);
+ offset = 6 + trans_id_size + 2; /* past message_code */
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "TID=%x %s ",
+ trans_id,
+ val_to_str(message_code, message_code_vals,
+ TEXT_UNDEFINED));
+
+ if (!tree)
+ return;
+
+ ti = proto_tree_add_item(tree, proto_ipdc, tvb, 0, -1, FALSE);
+ ipdc_tree = proto_item_add_subtree(ti, ett_ipdc);
+
+ proto_tree_add_item(ipdc_tree, hf_ipdc_nr, tvb, 0, 1, nr);
+ proto_tree_add_item(ipdc_tree, hf_ipdc_ns, tvb, 1, 1, ns);
+ proto_tree_add_uint(ipdc_tree, hf_ipdc_payload_len, tvb,
+ 2, 2, payload_len);
+
+ proto_tree_add_item(ipdc_tree, hf_ipdc_protocol_id, tvb,
+ 4, 1, protocol_id);
+ proto_tree_add_item(ipdc_tree, hf_ipdc_trans_id_size, tvb,
+ 5, 1, trans_id_size);
+ proto_tree_add_item(ipdc_tree, hf_ipdc_trans_id, tvb,
+ 6, trans_id_size, trans_id);
+ proto_tree_add_item(ipdc_tree, hf_ipdc_message_code, tvb,
+ 6 + trans_id_size + 1, 1, message_code);
+
+ ipdc_tag = proto_tree_add_text(ipdc_tree, tvb, offset,
+ payload_len - offset, "IPDC tags");
+ tag_tree = proto_item_add_subtree(ipdc_tag, ett_ipdc_tag);
+
+ /* iterate through tags. first byte is tag, second is length,
+ in bytes, following is tag data. tag of 0x0 should be
+ end of tags. */
+ for (;;) {
+ tag = tvb_get_guint8(tvb, offset);
+
+ if (tag == 0x0) {
+ if (offset == payload_len - 1) {
+ proto_tree_add_text(tag_tree, tvb,
+ offset, 1, "end of tags");
+ } else {
+ proto_tree_add_text(tag_tree, tvb,
+ offset, 1, "data trailing end of tags");
+ }
+
+ break;
+ }
+
+ len = tvb_get_guint8(tvb,offset+1);
+ des = val_to_str(tag, tag_description, TEXT_UNDEFINED);
+ /* lookup tag type */
+ for (i = 0; (ipdc_tag_types[i].tag != tag &&
+ ipdc_tag_types[i].type != IPDC_UNKNOWN); i++)
+ ;
+ type = ipdc_tag_types[i].type;
+
+ tmp_tag = 0;
+
+ switch (type) {
+ /* simple IPDC_ASCII strings */
+ case IPDC_ASCII:
+ tmp_str = tvb_memdup(tvb, offset + 2, len);
+ strncpy(tmp_tag_text, tmp_str, len);
+ tmp_tag_text[len] = 0;
+ free(tmp_str);
+ proto_tree_add_text(tag_tree, tvb, offset,
+ len + 2, "0x%2.2x: %s: %s", tag, des,
+ tmp_tag_text);
+ break;
+
+ /* unsigned integers, or bytes */
+ case IPDC_UINT:
+ case IPDC_BYTE:
+ for (i = 0; i < len; i++)
+ tmp_tag += tvb_get_guint8(tvb,
+ offset + 2 + i) * (guint32)
+ pow(256, len - (i + 1));
+
+ if (len == 1)
+ enum_val =
+ val_to_str(IPDC_TAG(tag) +
+ tmp_tag,
+ tag_enum_type, TEXT_UNDEFINED);
+
+ if (len == 1 &&
+ strcmp(enum_val, TEXT_UNDEFINED) != 0) {
+ proto_tree_add_text(tag_tree, tvb,
+ offset, len + 2,
+ "0x%2.2x: %s: %s",
+ tag, des, enum_val);
+ } else {
+ proto_tree_add_text(tag_tree, tvb,
+ offset, len + 2,
+ "0x%2.2x: %s: %u",
+ tag, des, tmp_tag);
+ }
+ break;
+
+ /* IP addresses */
+ case IPDC_IPA:
+ switch (len) {
+ case 4:
+ g_snprintf(tmp_tag_text,
+ IPDC_STR_LEN,
+ "%u.%u.%u.%u",
+ tvb_get_guint8(tvb, offset + 2),
+ tvb_get_guint8(tvb, offset + 3),
+ tvb_get_guint8(tvb, offset + 4),
+ tvb_get_guint8(tvb, offset + 5)
+ );
+ break;
+
+ case 6:
+ g_snprintf(tmp_tag_text,
+ IPDC_STR_LEN,
+ "%u.%u.%u.%u:%u",
+ tvb_get_guint8(tvb, offset + 2),
+ tvb_get_guint8(tvb, offset + 3),
+ tvb_get_guint8(tvb, offset + 4),
+ tvb_get_guint8(tvb, offset + 5),
+ tvb_get_ntohs(tvb, offset + 6));
+ break;
+
+ default:
+ g_snprintf(tmp_tag_text,
+ IPDC_STR_LEN,
+ "Invalid IP address length %u",
+ len);
+ }
+
+ proto_tree_add_text(tag_tree, tvb,
+ offset, len + 2,
+ "0x%2.2x: %s: %s",
+ tag, des, tmp_tag_text);
+ break;
+
+ /* Line status arrays */
+ case IPDC_LINESTATUS:
+ case IPDC_CHANNELSTATUS:
+ proto_tree_add_text(tag_tree, tvb, offset,
+ len + 2, "0x%2.2x: %s", tag, des);
+ val_ptr = (type == IPDC_LINESTATUS) ?
+ line_status_vals : channel_status_vals;
+
+ for (i = 0; i < len; i++) {
+ status = tvb_get_guint8(tvb,offset+2+i);
+
+ proto_tree_add_text(tag_tree, tvb,
+ offset + 2 + i, 1,
+ " %.2u: %.2x (%s)",
+ i + 1, status,
+ val_to_str(status,
+ val_ptr,
+ TEXT_UNDEFINED));
+ }
+ break;
+
+ case IPDC_Q931:
+ q931_tvb =
+ tvb_new_subset(tvb, offset+2, len, len);
+ call_dissector(q931_handle,q931_tvb,pinfo,tree);
+ break;
+
+ case IPDC_ENCTYPE:
+ proto_tree_add_text(tag_tree, tvb,
+ offset, len + 2,
+ "0x%2.2x: %s: %s",
+ tag, des, val_to_str(
+ tvb_get_guint8(tvb,offset+2),
+ encoding_type_vals,
+ TEXT_UNDEFINED));
+
+ if (len == 2) {
+ proto_tree_add_text(tag_tree, tvb,
+ offset, len + 2,
+ "0x%2.2x: %s: %u",
+ tag, des,
+ tvb_get_guint8(tvb,offset+3));
+ }
+ break;
+
+ /* default */
+ default:
+ proto_tree_add_text(tag_tree, tvb, offset,
+ len + 2, "0x%2.2x: %s", tag, des);
+ } /* switch */
+
+ offset += len + 2;
+ }
+}
+
+static void
+dissect_ipdc_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_ipdc_common(tvb, pinfo, tree);
+}
+
+static void
+dissect_ipdc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ new_packet = TRUE;
+ tcp_dissect_pdus(tvb, pinfo, tree, ipdc_desegment, 4,
+ get_ipdc_pdu_len, dissect_ipdc_tcp_pdu);
+}
+
+void
+proto_register_ipdc(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_ipdc_nr,
+ { "N(r)", "ipdc.nr",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Receive sequence number", HFILL }
+ },
+
+ { &hf_ipdc_ns,
+ { "N(s)", "ipdc.ns",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Transmit sequence number", HFILL }
+ },
+
+ { &hf_ipdc_payload_len,
+ { "Payload length", "ipdc.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Payload length", HFILL }
+ },
+
+ { &hf_ipdc_protocol_id,
+ { "Protocol ID", "ipdc.protocol_id",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Protocol ID", HFILL }
+ },
+
+ { &hf_ipdc_trans_id_size,
+ { "Transaction ID size", "ipdc.trans_id_size",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Transaction ID size", HFILL }
+ },
+
+ { &hf_ipdc_trans_id,
+ { "Transaction ID", "ipdc.trans_id",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Transaction ID", HFILL }
+ },
+
+ { &hf_ipdc_message_code,
+ { "Message code", "ipdc.message_code",
+ FT_UINT16, BASE_HEX, VALS(message_code_vals), 0x0,
+ "Message Code", HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_ipdc,
+ &ett_ipdc_tag,
+ };
+
+ module_t *ipdc_module;
+
+ proto_ipdc = proto_register_protocol("IP Device Control (SS7 over IP)",
+ "IPDC", "ipdc");
+ proto_register_field_array(proto_ipdc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ipdc_module = prefs_register_protocol(proto_ipdc, proto_reg_handoff_ipdc);
+ prefs_register_bool_preference(ipdc_module, "desegment_ipdc_messages",
+ "Desegment all IPDC messages spanning multiple TCP segments",
+ "Whether the IPDC dissector should desegment all messages spanning multiple TCP segments",
+ &ipdc_desegment);
+ prefs_register_uint_preference(ipdc_module, "tcp.port",
+ "IPDC monitoring port",
+ "Set the IPDC monitoring port", 10,
+ &ipdc_port_pref);
+}
+
+void
+proto_reg_handoff_ipdc(void)
+{
+ static gint last_ipdc_port_pref = 0;
+ static dissector_handle_t ipdc_tcp_handle = NULL;
+
+ if (ipdc_tcp_handle) {
+ dissector_delete("tcp.port", last_ipdc_port_pref,
+ ipdc_tcp_handle);
+ } else {
+ ipdc_tcp_handle =
+ create_dissector_handle(dissect_ipdc_tcp, proto_ipdc);
+ q931_handle = find_dissector("q931");
+ }
+
+ last_ipdc_port_pref = ipdc_port_pref;
+ dissector_add("tcp.port", ipdc_port_pref, ipdc_tcp_handle);
+}
diff --git a/epan/dissectors/packet-ipdc.h b/epan/dissectors/packet-ipdc.h
new file mode 100644
index 0000000000..514b27e682
--- /dev/null
+++ b/epan/dissectors/packet-ipdc.h
@@ -0,0 +1,652 @@
+/* packet-ipdc.h
+ * Routines for IP Device Control (SS7 over IP) dissection
+ * Copyright Lucent Technologies 2004
+ * Josh Bailey <joshbailey@lucent.com> and Ruud Linders <ruud@lucent.com>
+ *
+ * Using IPDC spec 0.20.2
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define TCP_PORT_IPDC 6668
+#define TRANS_ID_SIZE_IPDC 4
+
+#define TEXT_UNDEFINED "UNDEFINED"
+
+#define IPDC_STR_LEN 255
+
+typedef enum {
+ IPDC_UNKNOWN,
+ IPDC_UINT,
+ IPDC_ASCII,
+ IPDC_BYTE,
+ IPDC_OCTET,
+ IPDC_IPA,
+ IPDC_LINESTATUS,
+ IPDC_CHANNELSTATUS,
+ IPDC_Q931,
+ IPDC_ENCTYPE
+} ipdc_tag_type;
+
+static const value_string encoding_type_vals[] = {
+ { 0x00, "PCMU (G.711 mu-law)" },
+ { 0x04, "G.723.1" },
+ { 0x08, "PCMA (G.711 A-law)" },
+ { 0x12, "G.729A" },
+ { 0x60, "Transparent data encoding" },
+ { 0x61, "T.38 fax over UPD" },
+};
+
+static const value_string line_status_vals[] = {
+ { 0x00, "Not present" },
+ { 0x01, "Disabled" },
+ { 0x02, "Red alarm (loss of sync)" },
+ { 0x03, "Yellow alarm" },
+ { 0x04, "Other alarm or error" },
+ { 0x05, "Up" },
+ { 0x06, "Loopback" },
+};
+
+static const value_string channel_status_vals[] = {
+ { 0x00, "Not present" },
+ { 0x01, "Out of service" },
+ { 0x03, "Maintenance (continuity test pending/in progress)" },
+ { 0x04, "Blocked" },
+ { 0x05, "Loopback" },
+ { 0x06, "Idle" },
+ { 0x07, "In use (dialing, ringing, etc.)" },
+ { 0x08, "Connected" },
+ { 0x50, "On hook" },
+ { 0x51, "Off hook" },
+};
+
+static const value_string message_code_vals[] = {
+ { 0x0082, "SS -> GW: ASUP: Acknowledgment to NSUP" },
+ { 0x0084, "SS -> GW: LNK: Link Active" },
+ { 0x0087, "SS -> GW: RCGST: Request Congestion Status" },
+ { 0x00FF, "SS -> GW: MRJ: Message reject." },
+ { 0x0041, "SS -> GW: RMS: Request module status" },
+ { 0x0043, "SS -> GW: RLS: Request line status" },
+ { 0x0045, "SS -> GW: RCS: Request channel status" },
+ { 0x0051, "SS -> GW: SMS: Set a module to a given state" },
+ { 0x0053, "SS -> GW: SLS: Set a line to a given state" },
+ { 0x0055, "SS -> GW: SCS: Set a group of channels to a given state" },
+ { 0x0047, "SS -> GW: RRS: Request RTP port Status" },
+ { 0x0048, "SS -> GW: RARS: Request All RTP port Status" },
+ { 0x0091, "SS -> GW: RSI: Request system information" },
+ { 0x0001, "SS -> GW: RCSI: Request inbound call setup" },
+ { 0x0009, "SS -> GW: RCST: Request pass-through call setup (TDM connection between two channels)" },
+ { 0x0013, "SS -> GW: RCCP: Request packet call setup" },
+ { 0x0015, "SS -> GW: RMPC: Modify/Query request packet call" },
+ { 0x0011, "SS -> GW: RCR: Release channel request" },
+ { 0x0012, "SS -> GW: ACR: Release channel complete" },
+ { 0x0061, "SS -> GW: PCT: Prepare channel for continuity test" },
+ { 0x0063, "SS -> GW: SCT: Start continuity test procedure with far end as loopback (Generate tone and check for received tone)" },
+ { 0x0073, "SS -> GW: STN: Send tones" },
+ { 0x0071, "SS -> GW: LTN: Listen for tones" },
+ { 0x007D, "SS -> GW: RTE: Request Test Echo" },
+ { 0x007E, "SS -> GW: ARTE: Response to Request Test Echo" },
+ { 0x0079, "SS -> GW: NATV: Native Mode Q.931 Signaling Transport" },
+ { 0x007A, "SS -> GW: TUNL: Tunneled Transport of signaling protocol data units" },
+ { 0x0081, "GW -> SS: NSUP: Notify the soft switch that the GW is coming up" },
+ { 0x0083, "GW -> SS: NSDN: Indication that the GW is going down" },
+ { 0x0085, "GW -> SS: ALNK: Acknowledgement to Link Active" },
+ { 0x0086, "GW -> SS: SLNK: Link Status" },
+ { 0x0088, "GW -> SS: CGST: Congestion Status" },
+ { 0x00FF, "GW -> SS: MRJ: Message reject." },
+ { 0x0042, "GW -> SS: NMS: Notify module status" },
+ { 0x0044, "GW -> SS: NLS: Notify line status" },
+ { 0x0046, "GW -> SS: NCS: Notify channel status" },
+ { 0x0056, "GW -> SS: RSCS: Response to SCS" },
+ { 0x0049, "GW -> SS: NRS: Notify RTP port Status" },
+ { 0x004A, "GW -> SS: NARS: Notify All RTP port Status" },
+ { 0x0092, "GW -> SS: NSI: Notify System Information" },
+ { 0x0002, "GW -> SS: ACSI: Accept inbound call setup" },
+ { 0x0003, "GW -> SS: CONI: Connect inbound call (answer)" },
+ { 0x0014, "GW -> SS: ACCP: Accept packet call setup" },
+ { 0x0016, "GW -> SS: AMPC: Accept modify to packet call" },
+ { 0x000A, "GW -> SS: ACST: Accept pass-through call" },
+ { 0x0011, "GW -> SS: RCR: Release channel request" },
+ { 0x0012, "GW -> SS: ACR: Release channel complete" },
+ { 0x0062, "GW -> SS: APCT: Response to PCT" },
+ { 0x0064, "GW -> SS: ASCT: Continuity test result" },
+ { 0x0074, "GW -> SS: ASTN: Completion result of STN command" },
+ { 0x0072, "GW -> SS: ALTN: Response to Listen for tones" },
+ { 0x00F0, "GW -> SS: NTN: Notify ToNe" },
+ { 0x007D, "GW -> SS: RTE: Request Test Echo" },
+ { 0x007E, "GW -> SS: ARTE: Response to Request Test Echo" },
+ { 0x0079, "GW -> SS: NATV: Native Mode Q.931 Signaling Transport" },
+ { 0x007A, "GW -> SS: TUNL: Tunneled Transport of signaling protocol data units" },
+ { 0x0005, "TD -> SS: RCSO: Request outbound call setup" },
+ { 0x0006, "SS -> TD: ACSO: Accept outbound call setup" },
+ { 0x0007, "SS -> TD: CONO: Outbound call connected" },
+ { 0, NULL },
+};
+
+static const value_string tag_description[] = {
+ { 0x01, "Protocol version" },
+ { 0x02, "System ID/ Serial Number" },
+ { 0x03, "System type" },
+ { 0x04, "Maximum number of modules (slot cards) supported" },
+ { 0x05, "Bay number" },
+ { 0x07, "Module number" },
+ { 0x0A, "Module type" },
+ { 0x0C, "Module status" },
+ { 0x0D, "Line number" },
+ { 0x14, "Line status" },
+ { 0x15, "Channel number" },
+ { 0x17, "Bearer capability" },
+ { 0x18, "Calling party number" },
+ { 0x19, "Dialed number" },
+ { 0x1B, "Primary SS IP address" },
+ { 0x1C, "Primary SS TCP port" },
+ { 0x20, "Number of lines in the Line status array" },
+ { 0x21, "Line status array" },
+ { 0x22, "Number of channels in the Channel status array" },
+ { 0x23, "Channel status array" },
+ { 0x24, "Requested module state" },
+ { 0x25, "Requested line state" },
+ { 0x26, "Requested channel status action" },
+ { 0x27, "Set channel status option" },
+ { 0x28, "Channel number first (for grouping)" },
+ { 0x29, "End Channel Number (for grouping)" },
+ { 0x2A, "Set channel status result" },
+ { 0x2B, "Prepare for continuity check result" },
+ { 0x2C, "Continuity timeout (ms)" },
+ { 0x2D, "Continuity test result" },
+ { 0x31, "Maximum time between digits in digits recognition/ tone" \
+ "detection (inter-digit time-out) (ms)" },
+ { 0x32, "Tone string length" },
+ { 0x33, "Tone string" },
+ { 0x34, "Tone to complete collection" },
+ { 0x35, "Tone listen completion status" },
+ { 0x36, "Tone send completion status" },
+ { 0x37, "TDM destination Module" },
+ { 0x38, "TDM destination Line" },
+ { 0x39, "TDM destination channel" },
+ { 0x3A, "DTMF send IP address" },
+ { 0x3B, "DTMF send RTP port number" },
+ { 0x3C, "DTMF send format" },
+ { 0x3D, "DTMF Named Events to Expect" },
+ { 0x3E, "DTMF Payload Indicator" },
+ { 0x40, "Access server Call identifier" },
+ { 0x46, "Maximum time for digit collection (ms)" },
+ { 0x49, "Tone Type" },
+ { 0x4A, "Apply/Cancel Tone" },
+ { 0x5D, "Destination listen IP address" },
+ { 0x5E, "Destination listen RTP port number" },
+ { 0x5F, "Destination send IP address" },
+ { 0x60, "Destination send RTP port number" },
+ { 0x65, "Source port type" },
+ { 0x66, "Destination port type" },
+ { 0x67, "Start RTP Port Number" },
+ { 0x68, "End RTP Port Number" },
+ { 0x69, "Rogue Session Addresses" },
+ { 0x6A, "RTP Port Status" },
+ { 0x6F, "Receive Encoding Type" },
+ { 0x70, "Send Encoding Type" },
+ { 0x71, "Silence Suppression Activation Timer (ms)" },
+ { 0x72, "Comfort Noise Generation" },
+ { 0x73, "Packet Loading (ms)" },
+ { 0x74, "Echo Cancellation" },
+ { 0x75, "Constant DTMF Tone Detection on/off" },
+ { 0x76, "Constant MF Tone Detection on/off" },
+ { 0x77, "Constant Fax tone detection on/off" },
+ { 0x78, "Constant Modem tone detection on/off" },
+ { 0x7B, "Constant Packet Loss Detection on/off" },
+ { 0x7C, "Packet Loss Threshold" },
+ { 0x7D, "Constant Latency Threshold Detection on/off" },
+ { 0x7E, "Latency Threshold (ms)" },
+ { 0x86, "Announcement treatment" },
+ { 0x90, "Packet Statistics Reset Indicator" },
+ { 0x91, "Number of audio packets sent" },
+ { 0x92, "Number of audio packets dropped" },
+ { 0x93, "Number of audio bytes sent" },
+ { 0x94, "Number of audio bytes dropped" },
+ { 0x95, "Number of signaling packets sent" },
+ { 0x96, "Number of signaling packets dropped" },
+ { 0x97, "Number of signaling bytes sent" },
+ { 0x98, "Number of signaling bytes dropped" },
+ { 0x99, "Estimated average latency (ms)" },
+ { 0x9D, "Number of audio packets received" },
+ { 0x9E, "Number of audio bytes received" },
+ { 0x9F, "Number of signaling packets received" },
+ { 0xA0, "Number of signaling bytes received" },
+ { 0xA1, "Protocol Type" },
+ { 0xA2, "PDU Data Block" },
+ { 0xA3, "Jitter estimated (m ticks)" },
+ { 0xA4, "Global call ID" },
+ { 0xA5, "User information line 1 proto" },
+ { 0xA6, "Congestion level indicator" },
+ { 0xA7, "RADIUS Ascend-auth-type" },
+ { 0xB0, "Link status" },
+ { 0xB1, "Action request" },
+ { 0xB2, "Calling Party Info1" },
+ { 0xB3, "Called Party Info2" },
+ { 0xC1, "Country Code" },
+ { 0xC2, "Number of Operational Universal Ports" },
+ { 0xC3, "Number of Operational HDLC-only (digital) ports" },
+ { 0xFE, "Q.850 Cause code" },
+ { 0, NULL },
+};
+
+typedef struct _ipdc_tag_type_val {
+ gint tag;
+ ipdc_tag_type type;
+} ipdc_tag_type_val;
+
+static const ipdc_tag_type_val ipdc_tag_types[] = {
+ { 0x01, IPDC_UINT },
+ { 0x02, IPDC_ASCII },
+ { 0x03, IPDC_ASCII },
+ { 0x04, IPDC_UINT },
+ { 0x05, IPDC_ASCII },
+ { 0x07, IPDC_UINT },
+ { 0x0A, IPDC_BYTE },
+ { 0x0C, IPDC_BYTE },
+ { 0x0D, IPDC_UINT },
+ { 0x14, IPDC_BYTE },
+ { 0x15, IPDC_UINT },
+ { 0x17, IPDC_BYTE },
+ { 0x18, IPDC_ASCII },
+ { 0x19, IPDC_ASCII },
+ { 0x1B, IPDC_IPA },
+ { 0x1C, IPDC_UINT },
+ { 0x20, IPDC_UINT },
+ { 0x21, IPDC_LINESTATUS },
+ { 0x22, IPDC_UINT },
+ { 0x23, IPDC_CHANNELSTATUS },
+ { 0x24, IPDC_BYTE },
+ { 0x25, IPDC_OCTET }, /* TBD */
+ { 0x26, IPDC_BYTE },
+ { 0x27, IPDC_BYTE },
+ { 0x28, IPDC_UINT },
+ { 0x29, IPDC_UINT },
+ { 0x2A, IPDC_BYTE },
+ { 0x2B, IPDC_BYTE },
+ { 0x2C, IPDC_UINT },
+ { 0x2D, IPDC_BYTE },
+ { 0x31, IPDC_UINT },
+ { 0x32, IPDC_UINT },
+ { 0x33, IPDC_ASCII },
+ { 0x34, IPDC_ASCII },
+ { 0x35, IPDC_BYTE },
+ { 0x36, IPDC_UINT },
+ { 0x37, IPDC_UINT },
+ { 0x38, IPDC_UINT },
+ { 0x39, IPDC_UINT },
+ { 0x3A, IPDC_IPA },
+ { 0x3B, IPDC_UINT },
+ { 0x3C, IPDC_BYTE },
+ { 0x3D, IPDC_ASCII },
+ { 0x3E, IPDC_UINT },
+ { 0x40, IPDC_UINT },
+ { 0x46, IPDC_UINT },
+ { 0x49, IPDC_BYTE },
+ { 0x4A, IPDC_BYTE },
+ { 0x5D, IPDC_IPA },
+ { 0x5E, IPDC_UINT },
+ { 0x5F, IPDC_IPA },
+ { 0x60, IPDC_UINT },
+ { 0x65, IPDC_BYTE },
+ { 0x66, IPDC_BYTE },
+ { 0x67, IPDC_UINT },
+ { 0x68, IPDC_UINT },
+ { 0x69, IPDC_IPA },
+ { 0x6A, IPDC_BYTE },
+ { 0x6F, IPDC_ENCTYPE },
+ { 0x70, IPDC_ENCTYPE },
+ { 0x71, IPDC_UINT },
+ { 0x72, IPDC_BYTE },
+ { 0x73, IPDC_UINT },
+ { 0x74, IPDC_BYTE },
+ { 0x75, IPDC_BYTE },
+ { 0x76, IPDC_BYTE },
+ { 0x77, IPDC_BYTE },
+ { 0x78, IPDC_BYTE },
+ { 0x7B, IPDC_BYTE },
+ { 0x7C, IPDC_UINT },
+ { 0x7D, IPDC_BYTE },
+ { 0x7E, IPDC_UINT },
+ { 0x86, IPDC_BYTE },
+ { 0x90, IPDC_BYTE },
+ { 0x91, IPDC_UINT },
+ { 0x92, IPDC_UINT },
+ { 0x93, IPDC_UINT },
+ { 0x94, IPDC_UINT },
+ { 0x95, IPDC_UINT },
+ { 0x96, IPDC_UINT },
+ { 0x97, IPDC_UINT },
+ { 0x98, IPDC_UINT },
+ { 0x99, IPDC_UINT },
+ { 0x9D, IPDC_UINT },
+ { 0x9E, IPDC_UINT },
+ { 0x9F, IPDC_UINT },
+ { 0xA0, IPDC_UINT },
+ { 0xA1, IPDC_UINT },
+ { 0xA2, IPDC_Q931 },
+ { 0xA3, IPDC_BYTE },
+ { 0xA4, IPDC_BYTE },
+ { 0xA5, IPDC_BYTE },
+ { 0xA6, IPDC_UINT },
+ { 0xA7, IPDC_UINT },
+ { 0xB0, IPDC_BYTE },
+ { 0xB1, IPDC_BYTE },
+ { 0xB2, IPDC_OCTET },
+ { 0xB3, IPDC_OCTET },
+ { 0xC1, IPDC_BYTE },
+ { 0xC2, IPDC_UINT },
+ { 0xC3, IPDC_UINT },
+ { 0xFE, IPDC_UINT },
+ { 0xFFFF, IPDC_UNKNOWN },
+};
+
+#define IPDC_TAG(x) (256 * (x))
+
+static const value_string tag_enum_type[] = {
+ /* Protocol Version */
+ { IPDC_TAG(0x01) + 0x00, "Version 0 (Xcom NMI 5.0)" },
+ { IPDC_TAG(0x01) + 0x01, "IPDC Version 0.12" },
+ { IPDC_TAG(0x01) + 0x02, "IPDC Version 0.15" },
+ { IPDC_TAG(0x01) + 0x03, "IPDC Version 0.17" },
+ { IPDC_TAG(0x01) + 0x04, "IPDC Version 0.18" },
+ { IPDC_TAG(0x01) + 0x05, "IPDC Version 0.19" },
+ { IPDC_TAG(0x01) + 0x06, "IPDC Version 0.20" },
+ /* Module type, from Annex B. */
+ { IPDC_TAG(0x0a) + 0x01, "Unknown" },
+ { IPDC_TAG(0x0a) + 0x02, "Shelf" },
+ { IPDC_TAG(0x0a) + 0x03, "Router Card" },
+ { IPDC_TAG(0x0a) + 0x04, "8-line Channelized T1" },
+ { IPDC_TAG(0x0a) + 0x05, "8-line Channelized E1" },
+ { IPDC_TAG(0x0a) + 0x06, "48-modem Card" },
+ { IPDC_TAG(0x0a) + 0x07, "192 HDLC Card" },
+ { IPDC_TAG(0x0a) + 0x08, "4-port Ethernet Card" },
+ { IPDC_TAG(0x0a) + 0x09, "Serial WAN Card" },
+ { IPDC_TAG(0x0a) + 0x0A, "HSSI Card" },
+ { IPDC_TAG(0x0a) + 0x0B, "10-line Unchannelized T1" },
+ { IPDC_TAG(0x0a) + 0x0C, "36-modem (Analog) Card" },
+ { IPDC_TAG(0x0a) + 0x0D, "T3 Card" },
+ { IPDC_TAG(0x0a) + 0x0E, "48-modem 56K Card" },
+ { IPDC_TAG(0x0a) + 0x0F, "Forward" },
+ { IPDC_TAG(0x0a) + 0x10, "SDSL Card" },
+ { IPDC_TAG(0x0a) + 0x11, "CAP ADSL Card" },
+ { IPDC_TAG(0x0a) + 0x12, "DMT ADSL Card" },
+ { IPDC_TAG(0x0a) + 0x13, "Standalone Modem Controller" },
+ { IPDC_TAG(0x0a) + 0x14, "32-port IDSL Card" },
+ { IPDC_TAG(0x0a) + 0x15, "10-line Unchannelized E1" },
+ { IPDC_TAG(0x0a) + 0x16, "36-modem (Analog) 2 Card" },
+ { IPDC_TAG(0x0a) + 0x17, "CSMX Modem Card" },
+ { IPDC_TAG(0x0a) + 0x18, "UDS3 Card" },
+ { IPDC_TAG(0x0a) + 0x19, "DS3 ATM Card" },
+ { IPDC_TAG(0x0a) + 0x1A, "4-port Ethernet 2 Card" },
+ { IPDC_TAG(0x0a) + 0x1B, "192 HDLC 2 Card" },
+ { IPDC_TAG(0x0a) + 0x1C, "SDSL 70 Data Card" },
+ { IPDC_TAG(0x0a) + 0x1D, "MADD Card" },
+ { IPDC_TAG(0x0a) + 0x1E, "SDSL 70 Voice Card" },
+ { IPDC_TAG(0x0a) + 0x1F, "OC3 Daughter Card" },
+ { IPDC_TAG(0x0a) + 0x20, "OC3 ATM Card" },
+ { IPDC_TAG(0x0a) + 0x21, "4-port Ethernet 3 Card" },
+ { IPDC_TAG(0x0a) + 0x22, "SRS Ethernet Card" },
+ { IPDC_TAG(0x0a) + 0x23, "SDSL ATM Card" },
+ { IPDC_TAG(0x0a) + 0x24, "AL DADSL ATM Card" },
+ { IPDC_TAG(0x0a) + 0x25, "CSM3V Modem Card" },
+ { IPDC_TAG(0x0a) + 0x26, "HDLC2EC Card" },
+ { IPDC_TAG(0x0a) + 0x27, "DS3 Daughter Card" },
+ { IPDC_TAG(0x0a) + 0x28, "2-port Ethernet Card" },
+ { IPDC_TAG(0x0a) + 0x2A, "STM0 Card" },
+ { IPDC_TAG(0x0a) + 0x2B, "SDSL Ripper Card" },
+ { IPDC_TAG(0x0a) + 0x2F, "Stinger Terminator Card" },
+ { IPDC_TAG(0x0a) + 0x30, "GS DADSL Ripper Card" },
+ { IPDC_TAG(0x0a) + 0x31, "PCTFIT Card" },
+ { IPDC_TAG(0x0a) + 0x32, "PCTFIE Card" },
+ { IPDC_TAG(0x0a) + 0x33, "CT DADSL GLITE Card" },
+ { IPDC_TAG(0x0a) + 0x34, "DS3 ATM 2 Card" },
+ { IPDC_TAG(0x0a) + 0x35, "E3 ATM Card" },
+ { IPDC_TAG(0x0a) + 0x36, "24-line Stinger IMA T1 Card" },
+ { IPDC_TAG(0x0a) + 0x37, "MADD 2 Card" },
+ { IPDC_TAG(0x0a) + 0x38, "GS HDSL 2 Card" },
+ { IPDC_TAG(0x0a) + 0x39, "32-line Stinger IDSL Card" },
+ { IPDC_TAG(0x0a) + 0x3A, "ANNEXB DADSL ATM Card" },
+ { IPDC_TAG(0x0a) + 0x3B, "24-line Stinger IMA E1 Card" },
+ { IPDC_TAG(0x0a) + 0x3C, "40C CT DADSL ATM Card" },
+ { IPDC_TAG(0x0a) + 0x3D, "4-port Ethernet 3+ Card" },
+ { IPDC_TAG(0x0a) + 0x3E, "CLPMT Card" },
+ { IPDC_TAG(0x0a) + 0x3F, "CLPME Card" },
+ { IPDC_TAG(0x0a) + 0x40, "E3 Daughter Card" },
+ { IPDC_TAG(0x0a) + 0x41, "8-line Stinger IMA T1 Card" },
+ { IPDC_TAG(0x0a) + 0x42, "8-line Stinger IMA E1 Card" },
+ { IPDC_TAG(0x0a) + 0x43, "48A GS DADSL ATM Card" },
+ { IPDC_TAG(0x0a) + 0x44, "48B GS DADSL ATM Card" },
+ { IPDC_TAG(0x0a) + 0x45, "48C GS DADSL ATM Card" },
+ { IPDC_TAG(0x0a) + 0x46, "40A CT DADSL ATM Card" },
+ { IPDC_TAG(0x0a) + 0x47, "OC3 ATM 2 Card" },
+ { IPDC_TAG(0x0a) + 0x48, "4-port Serial WAN 2 Card" },
+ { IPDC_TAG(0x0a) + 0x49, "CDS3 LIM Card" },
+ { IPDC_TAG(0x0a) + 0x4A, "R7000 Card" },
+ { IPDC_TAG(0x0a) + 0x4B, "VPN Card" },
+ { IPDC_TAG(0x0a) + 0x4C, "HSE Card" },
+ { IPDC_TAG(0x0a) + 0x4D, "MADD 3 Card" },
+ { IPDC_TAG(0x0a) + 0x4E, "Stinger CM V2 Card" },
+ { IPDC_TAG(0x0a) + 0x4F, "COC3 LIM Card" },
+ { IPDC_TAG(0x0a) + 0x50, "Stinger SHDSL Card" },
+ { IPDC_TAG(0x0a) + 0x51, "2-port OC34-port DS3 Daughter Card" },
+ { IPDC_TAG(0x0a) + 0x52, "72-line DADSL ATM Card" },
+ { IPDC_TAG(0x0a) + 0x53, "36-line DMT MRT Card" },
+ { IPDC_TAG(0x0a) + 0x54, "24-line T1 Card" },
+ { IPDC_TAG(0x0a) + 0x55, "24-line E1 Card" },
+ { IPDC_TAG(0x0a) + 0x56, "Stinger MRT CM Card" },
+ { IPDC_TAG(0x0a) + 0x57, "CSTM1 LIM Card" },
+ /* Module status */
+ { IPDC_TAG(0x0c) + 0x00, "Not present (empty)" },
+ { IPDC_TAG(0x0c) + 0x01, "Out of service (down)" },
+ { IPDC_TAG(0x0c) + 0x02, "Up" },
+ { IPDC_TAG(0x0c) + 0x03, "Error" },
+ { IPDC_TAG(0x0c) + 0x04, "Does not exist" },
+ /* Line status */
+ { IPDC_TAG(0x14) + 0x00, "Not present" },
+ { IPDC_TAG(0x14) + 0x01, "Disabled" },
+ { IPDC_TAG(0x14) + 0x02, "Red alarm (loss of sync)" },
+ { IPDC_TAG(0x14) + 0x03, "Yellow alarm" },
+ { IPDC_TAG(0x14) + 0x04, "Other alarms or errors" },
+ { IPDC_TAG(0x14) + 0x05, "Up" },
+ { IPDC_TAG(0x14) + 0x06, "Loopback" },
+ /* Bearer capability */
+ { IPDC_TAG(0x17) + 0x00, "Voice call" },
+ { IPDC_TAG(0x17) + 0x08, "64K data call" },
+ { IPDC_TAG(0x17) + 0x09, "56K data call" },
+ { IPDC_TAG(0x17) + 0x10,
+ "Modem call (3.1K Audio call) (applies to RCSI for modem call only)" },
+ /* Line status array */
+ /* { IPDC_TAG(0x21) + 0x0, "" }, */
+ /* Channel status array */
+ /* { IPDC_TAG(0x23) + 0x0, "" }, */
+ /* Requested module state */
+ { IPDC_TAG(0x24) + 0x00, "Out of service" },
+ { IPDC_TAG(0x24) + 0x01, "Initialize (bring up)" },
+ /* Requested line state */
+ { IPDC_TAG(0x25) + 0x00, "Disable" },
+ { IPDC_TAG(0x25) + 0x01, "Enable" },
+ { IPDC_TAG(0x25) + 0x02, "Start loopback" },
+ { IPDC_TAG(0x25) + 0x03, "Terminate loopback" },
+ /* Requested channel status action */
+ { IPDC_TAG(0x26) + 0x00, "Reset to idle" },
+ { IPDC_TAG(0x26) + 0x01, "Reset to out of service" },
+ { IPDC_TAG(0x26) + 0x02, "Start loopback" },
+ { IPDC_TAG(0x26) + 0x03, "Terminate loopback" },
+ /* Set channel status option */
+ { IPDC_TAG(0x27) + 0x00,
+ "Do not perform the indicated action if any of the" \
+ "channels is not in the valid initial state" },
+ { IPDC_TAG(0x27) + 0x01,
+ "Perform the indicated action on channels that are on" \
+ "the valid initial state. Other channels are not affected" },
+ /* Set channel status result */
+ { IPDC_TAG(0x2a) + 0x00,
+ "action successfully performed in all channels" },
+ { IPDC_TAG(0x2a) + 0x01, "at least one channel failed" },
+ /* Prepare for continuity check result */
+ { IPDC_TAG(0x2b) + 0x00, "Resources reserved successfully" },
+ { IPDC_TAG(0x2b) + 0x01, "Resource not available" },
+ /* Continuity test result */
+ { IPDC_TAG(0x2d) + 0x00, "Test completed successfully" },
+ { IPDC_TAG(0x2d) + 0x01, "Test failed" },
+ /* Tone listen completion status */
+ { IPDC_TAG(0x35) + 0x00, "Timeout" },
+ { IPDC_TAG(0x35) + 0x01, "No resources available for this operation" },
+ { IPDC_TAG(0x35) + 0x02, "Operation terminated by the SS" },
+ { IPDC_TAG(0x35) + 0x03, "Tone-to-complete-collection received" },
+ { IPDC_TAG(0x35) + 0x04,
+ "The specified maximum number of tones received" },
+ { IPDC_TAG(0x35) + 0x05, "Wait between successive tones too long" },
+ /* Tone send completion status */
+ { IPDC_TAG(0x36) + 0x00, "Operation succeeded" },
+ { IPDC_TAG(0x36) + 0x01, "Operation failed" },
+ { IPDC_TAG(0x36) + 0x02, "Operation terminated by SS" },
+ { IPDC_TAG(0x36) + 0x03, "Operation started" },
+ { IPDC_TAG(0x36) + 0x04,
+ "Operation terminated by administrative action" },
+ /* DTMF send format */
+ { IPDC_TAG(0x3c) + 0x00, "Tone" },
+ { IPDC_TAG(0x3c) + 0x01, "Event" },
+ { IPDC_TAG(0x3c) + 0x02, "Both (default)" },
+ /* Tone Type */
+ { IPDC_TAG(0x49) + 0x00, "MF Tone" },
+ { IPDC_TAG(0x49) + 0x01, "DTMF Tone" },
+ { IPDC_TAG(0x49) + 0x02, "Analog Test Tone" },
+ { IPDC_TAG(0x49) + 0x03, "Announcement" },
+ { IPDC_TAG(0x49) + 0x04, "Digital Milli-watt tone" },
+ { IPDC_TAG(0x49) + 0x05, "Supplemental tones" },
+ { IPDC_TAG(0x49) + 0x06,
+ "Fax tone (CED, no phase reversal, or V.21 flags)" },
+ { IPDC_TAG(0x49) + 0x07, "Modem tone (CED, phase reversal)" },
+ { IPDC_TAG(0x49) + 0x41, "Ringback tone" },
+ /* Apply/Cancel Tone */
+ { IPDC_TAG(0x4a) + 0x00, "Apply tone" },
+ { IPDC_TAG(0x4a) + 0x01, "Cancel tone" },
+ { IPDC_TAG(0x4a) + 0x02, "Listen for tone" },
+ /* Source port type */
+ { IPDC_TAG(0x65) + 0x00, "SCN channel" },
+ /* Destination port type */
+ { IPDC_TAG(0x66) + 0x01, "RTP port" },
+ /* RTP Port Status */
+ { IPDC_TAG(0x6a) + 0x00, "Idle", },
+ { IPDC_TAG(0x6a) + 0x01, "Active" },
+ /* Receive Encoding Type */
+ { IPDC_TAG(0x6f) + 0x00, "PCMU (G.711 mu-law)" },
+ { IPDC_TAG(0x6f) + 0x04, "G723.1" },
+ { IPDC_TAG(0x6f) + 0x08, "PCMA (G.711 A-law)" },
+ { IPDC_TAG(0x6f) + 0x12, "G729A" },
+ { IPDC_TAG(0x6f) + 0x60, "Transparent data encoding" },
+ { IPDC_TAG(0x6f) + 0x61, "T.38 fax over UPD" },
+ /* Send Encoding Type */
+ { IPDC_TAG(0x70) + 0x00, "PCMU (G.711 mu-law)" },
+ { IPDC_TAG(0x70) + 0x04, "G723.1" },
+ { IPDC_TAG(0x70) + 0x08, "PCMA (G.711 A-law)" },
+ { IPDC_TAG(0x70) + 0x12, "G729A" },
+ { IPDC_TAG(0x70) + 0x60, "Transparent data encoding" },
+ { IPDC_TAG(0x70) + 0x61, "T.38 fax over UPD" },
+ /* Comfort Noise Generation */
+ { IPDC_TAG(0x72) + 0x00, "off" },
+ { IPDC_TAG(0x72) + 0x01, "on" },
+ /* Echo Cancellation */
+ { IPDC_TAG(0x74) + 0x00, "Off" },
+ { IPDC_TAG(0x74) + 0x01, "On, 16 ms tail" },
+ { IPDC_TAG(0x74) + 0x02, "On, 32 ms tail (default)" },
+ { IPDC_TAG(0x74) + 0x03, "On, 64ms tail" },
+ /* Constant DTMF Tone Detection on/off */
+ { IPDC_TAG(0x75) + 0x00, "Off" },
+ { IPDC_TAG(0x75) + 0x01, "On (Default)" },
+ /* Constant MF Tone Detection on/off" */
+ { IPDC_TAG(0x76) + 0x00, "Off (Default)" },
+ { IPDC_TAG(0x76) + 0x01, "On" },
+ /* Constant Fax tone detection on/off */
+ { IPDC_TAG(0x77) + 0x00, "Off" },
+ { IPDC_TAG(0x77) + 0x00, "On (Default)" },
+ /* Constant Modem tone detection on/off */
+ { IPDC_TAG(0x78) + 0x00, "Off" },
+ { IPDC_TAG(0x78) + 0x01, "On (Default)" },
+ /* Constant Packet Loss Detection on/off */
+ { IPDC_TAG(0x7b) + 0x00, "Off" },
+ { IPDC_TAG(0x7b) + 0x01, "On (Default)" },
+ /* Constant Latency Threshold Detection on/off */
+ { IPDC_TAG(0x7d) + 0x00, "Off" },
+ { IPDC_TAG(0x7d) + 0x01, "On (Default)" },
+ /* Announcement treatment */
+ { IPDC_TAG(0x86) + 0x00, "Continuous play" },
+ { IPDC_TAG(0x86) + 0x01, "Play 1 time and terminate the call" },
+ { IPDC_TAG(0x86) + 0x02, "Play 2 times and terminate the call" },
+ { IPDC_TAG(0x86) + 0x03, "Play 3 times and terminate the call" },
+ { IPDC_TAG(0x86) + 0x04, "Play 4 times and terminate the call" },
+ { IPDC_TAG(0x86) + 0x05, "Play 5 times and terminate the call" },
+ /* Packet Statistics Reset Indicator */
+ { IPDC_TAG(0x90) + 0x00, "Do not reset" },
+ { IPDC_TAG(0x90) + 0x01, "Reset (default)" },
+ /* Protocol Type */
+ { IPDC_TAG(0xa1) + 0x01, "ITU-T Q931" },
+ { IPDC_TAG(0xa1) + 0x02, "Nortel-ISDN" },
+ { IPDC_TAG(0xa1) + 0x03, "5ESS-ISDN" },
+ { IPDC_TAG(0xa1) + 0x04, "Euro-ISDN" },
+ /* Global call ID Refer Annex A */
+ /* IPDC_TAG(0xa4) .... */
+ /* User information line 1 proto */
+ /* IPDC_TAG(0xa5) .... */
+ /* Congestion level indicator */
+ { IPDC_TAG(0xa6) + 0x00, "No Congestion" },
+ { IPDC_TAG(0xa6) + 0x01, "Congestion Level 1" },
+ { IPDC_TAG(0xa6) + 0x02, "Congestion Level 2" },
+ /* RADIUS Ascend-auth-type */
+ { IPDC_TAG(0xa7) + 0x00, "None" },
+ { IPDC_TAG(0xa7) + 0x01, "Any" },
+ { IPDC_TAG(0xa7) + 0x02, "PAP (Default)" },
+ { IPDC_TAG(0xa7) + 0x03, "CHAP" },
+ { IPDC_TAG(0xa7) + 0x03, "MS-CHAP" },
+ /* Link status */
+ { IPDC_TAG(0xb0) + 0x00, "Successfully connected" },
+ { IPDC_TAG(0xb0) + 0x01, "Not connected" },
+ /* Action request */
+ { IPDC_TAG(0xb1) + 0x00, "Registration request" },
+ /* Calling Party Info */
+ /* Called Party Info */
+ /* Country Code */
+ { IPDC_TAG(0xc1) + 0x00, "Argentina" },
+ { IPDC_TAG(0xc1) + 0x02, "Australia" },
+ { IPDC_TAG(0xc1) + 0x03, "Belgium" },
+ { IPDC_TAG(0xc1) + 0x04, "China" },
+ { IPDC_TAG(0xc1) + 0x05, "Costa Rica" },
+ { IPDC_TAG(0xc1) + 0x06, "Finland" },
+ { IPDC_TAG(0xc1) + 0x07, "France" },
+ { IPDC_TAG(0xc1) + 0x08, "Germany" },
+ { IPDC_TAG(0xc1) + 0x09, "Hong Kong" },
+ { IPDC_TAG(0xc1) + 0x0a, "Italy" },
+ { IPDC_TAG(0xc1) + 0x0b, "Japan" },
+ { IPDC_TAG(0xc1) + 0x0c, "Korea" },
+ { IPDC_TAG(0xc1) + 0x0d, "Mexico" },
+ { IPDC_TAG(0xc1) + 0x0e, "Netherlands" },
+ { IPDC_TAG(0xc1) + 0x0f, "New Zealand" },
+ { IPDC_TAG(0xc1) + 0x10, "Singapore" },
+ { IPDC_TAG(0xc1) + 0x11, "Spain" },
+ { IPDC_TAG(0xc1) + 0x12, "Sweden" },
+ { IPDC_TAG(0xc1) + 0x13, "Switzerland" },
+ { IPDC_TAG(0xc1) + 0x14, "UK" },
+ { IPDC_TAG(0xc1) + 0x15, "US" },
+ { IPDC_TAG(0xc1) + 0x15, "Brazil" },
+ { 0, NULL },
+};
diff --git a/epan/dissectors/packet-ipfc.c b/epan/dissectors/packet-ipfc.c
new file mode 100644
index 0000000000..2845dfe7ea
--- /dev/null
+++ b/epan/dissectors/packet-ipfc.c
@@ -0,0 +1,140 @@
+/* packet-ipfc.c
+ * Routines for Decoding Network_Header for IP-over-FC when we only
+ * capture the frame starting at the Network_Header (as opposed to
+ * when we have the full FC frame).
+ * See RFC 2625.
+ * Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "etypes.h"
+#include "packet-fc.h"
+#include "packet-ipfc.h"
+#include "packet-llc.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_ipfc = -1;
+static int hf_ipfc_network_da = -1;
+static int hf_ipfc_network_sa = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_ipfc = -1;
+static dissector_handle_t llc_handle;
+
+void
+capture_ipfc (const guchar *pd, int len, packet_counts *ld)
+{
+ if (!BYTES_ARE_IN_FRAME(0, len, 16)) {
+ ld->other++;
+ return;
+ }
+
+ capture_llc(pd, 16, len, ld);
+}
+
+static void
+dissect_ipfc (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *ipfc_tree;
+ int offset = 0;
+ tvbuff_t *next_tvb;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IP/FC");
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_ipfc, tvb, offset, 16,
+ "IP Over FC Network_Header");
+ ipfc_tree = proto_item_add_subtree (ti, ett_ipfc);
+
+ proto_tree_add_string (ipfc_tree, hf_ipfc_network_da, tvb, offset, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset, 8)));
+ proto_tree_add_string (ipfc_tree, hf_ipfc_network_sa, tvb, offset+8, 8,
+ fcwwn_to_str (tvb_get_ptr (tvb, offset+8, 8)));
+ }
+
+ next_tvb = tvb_new_subset (tvb, 16, -1, -1);
+ call_dissector(llc_handle, next_tvb, pinfo, tree);
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_ipfc (void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_ipfc_network_da,
+ {"Network DA", "ipfc.nh.da", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_ipfc_network_sa,
+ {"Network SA", "ipfc.nh.sa", FT_STRING, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_ipfc,
+ };
+
+ /* Register the protocol name and description */
+ proto_ipfc = proto_register_protocol("IP Over FC", "IPFC", "ipfc");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ipfc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_ipfc (void)
+{
+ dissector_handle_t ipfc_handle;
+
+ ipfc_handle = create_dissector_handle (dissect_ipfc, proto_ipfc);
+ dissector_add("wtap_encap", WTAP_ENCAP_IP_OVER_FC, ipfc_handle);
+
+ llc_handle = find_dissector ("llc");
+}
diff --git a/epan/dissectors/packet-ipfc.h b/epan/dissectors/packet-ipfc.h
new file mode 100644
index 0000000000..8a329893d4
--- /dev/null
+++ b/epan/dissectors/packet-ipfc.h
@@ -0,0 +1,29 @@
+/* packet-ipfc.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_IPFC_H__
+#define __PACKET_IPFC_H__
+
+void capture_ipfc(const guchar *, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-ipmi.c b/epan/dissectors/packet-ipmi.c
new file mode 100644
index 0000000000..ea0ff5caa7
--- /dev/null
+++ b/epan/dissectors/packet-ipmi.c
@@ -0,0 +1,656 @@
+/* packet-ipmi.c
+ * Routines for IPMI-over-LAN packet dissection
+ *
+ * Duncan Laurie <duncan@sun.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-rmcp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ *
+ * See the IPMI spec at
+ *
+ * http://www.intel.com/design/servers/ipmi/
+ *
+ * IPMI LAN Message Request
+ * ipmi.session.authtype
+ * ipmi.session.sequence
+ * ipmi.session.id
+ * [ipmi.session.authcode]
+ * ipmi.msg.len
+ * ipmi.msg.rsaddr
+ * ipmi.msg.netfn << 2 | ipmi.msg.rslun
+ * ipmi.msg.csum1
+ * ipmi.msg.rqaddr
+ * ipmi.msg.seq << 2 | ipmi.msg.rqlun
+ * ipmi.msg.cmd
+ * ipmi.msg.DATA
+ * ipmi.msg.csum2
+ *
+ * IPMI LAN Message Response
+ * ipmi.session.authtype
+ * ipmi.session.sequence
+ * ipmi.session.id
+ * [ipmi.session.authcode]
+ * ipmi.msg.len
+ * ipmi.msg.rqaddr
+ * ipmi.msg.netfn << 2 | ipmi.msg.rqlun
+ * ipmi.msg.csum1
+ * ipmi.msg.rsaddr
+ * ipmi.msg.seq << 2 | ipmi.msg.rslun
+ * ipmi.msg.cmd
+ * ipmi.msg.ccode
+ * ipmi.msg.DATA
+ * ipmi.msg.csum2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#define RMCP_CLASS_IPMI 0x07
+
+static dissector_handle_t data_handle;
+static int proto_ipmi = -1;
+
+static gint ett_ipmi = -1;
+static gint ett_ipmi_session = -1;
+static gint ett_ipmi_msg_nlfield = -1;
+static gint ett_ipmi_msg_slfield = -1;
+
+/* IPMI session header */
+static int hf_ipmi_session_id = -1;
+static int hf_ipmi_session_authtype = -1;
+static int hf_ipmi_session_sequence = -1;
+static int hf_ipmi_session_authcode = -1;
+
+/* IPMI message header */
+static int hf_ipmi_msg_len = -1;
+static int hf_ipmi_msg_rsaddr = -1;
+static int hf_ipmi_msg_nlfield = -1;
+static int hf_ipmi_msg_netfn = -1;
+static int hf_ipmi_msg_rqlun = -1;
+static int hf_ipmi_msg_csum1 = -1;
+static int hf_ipmi_msg_rqaddr = -1;
+static int hf_ipmi_msg_slfield = -1;
+static int hf_ipmi_msg_seq = -1;
+static int hf_ipmi_msg_rslun = -1;
+static int hf_ipmi_msg_cmd = -1;
+static int hf_ipmi_msg_ccode = -1;
+static int hf_ipmi_msg_csum2 = -1;
+
+static const value_string ipmi_netfn_vals[] = {
+ { 0x00, "Chassis Request" },
+ { 0x01, "Chassis Response" },
+ { 0x02, "Bridge Request" },
+ { 0x03, "Bridge Response" },
+ { 0x04, "Sensor/Event Request" },
+ { 0x05, "Sensor/Event Response" },
+ { 0x06, "Application Request" },
+ { 0x07, "Application Response" },
+ { 0x08, "Firmware Request" },
+ { 0x09, "Frimware Response" },
+ { 0x0a, "Storage Request" },
+ { 0x0b, "Storage Response" },
+ { 0x0c, "Transport Request" },
+ { 0x0d, "Transport Response" },
+ { 0x2c, "Group Extension Request" },
+ { 0x2d, "Group Extension Response" },
+ { 0x30, "OEM Request" },
+ { 0x31, "OEM Response" },
+ { 0x00, NULL },
+};
+
+static const value_string ipmi_authtype_vals[] = {
+ { 0x00, "NONE" },
+ { 0x01, "MD2" },
+ { 0x02, "MD5" },
+ { 0x04, "PASSWORD" },
+ { 0x05, "OEM" },
+ { 0x00, NULL }
+};
+
+static const value_string ipmi_ccode_vals[] = {
+ { 0x00, "Command completed normally" },
+ { 0xc0, "Node busy" },
+ { 0xc1, "Unrecognized or unsupported command" },
+ { 0xc2, "Command invalid for given LUN" },
+ { 0xc3, "Timeout while processing command" },
+ { 0xc4, "Out of space" },
+ { 0xc5, "Reservation cancelled or invalid reservation ID" },
+ { 0xc6, "Request data truncated" },
+ { 0xc7, "Request data length invalid" },
+ { 0xc8, "Request data field length limit exceeded" },
+ { 0xc9, "Parameter out of range" },
+ { 0xca, "Cannot return number of requested data bytes" },
+ { 0xcb, "Requested sensor, data, or record not present" },
+ { 0xcc, "Invalid data field in request" },
+ { 0xcd, "Command illegal for specified sensor or record type" },
+ { 0xce, "Command response could not be provided" },
+ { 0xcf, "Cannot execute duplicated request" },
+ { 0xd0, "SDR repository in update mode" },
+ { 0xd1, "Device in firmware update mode" },
+ { 0xd2, "BMC initialization or initialization agent running" },
+ { 0xd3, "Destination unavailable" },
+ { 0xd4, "Insufficient privilege level" },
+ { 0xd5, "Command or param not supported in present state" },
+ { 0xff, "Unspecified error" },
+ { 0x00, NULL },
+};
+
+static const value_string ipmi_addr_vals[] = {
+ { 0x20, "BMC Slave Address" },
+ { 0x81, "Remote Console Software ID" },
+ { 0x00, NULL },
+};
+
+static const value_string ipmi_chassis_cmd_vals[] = {
+ /* Chassis Device Commands */
+ { 0x00, "Get Chassis Capabilities" },
+ { 0x01, "Get Chassis Status" },
+ { 0x02, "Chassis Control" },
+ { 0x03, "Chassis Reset" },
+ { 0x04, "Chassis Identify" },
+ { 0x05, "Set Chassis Capabilities" },
+ { 0x06, "Set Power Restore Policy" },
+ { 0x07, "Get System Restart Cause" },
+ { 0x08, "Set System Boot Options" },
+ { 0x09, "Get System Boot Options" },
+ { 0x0f, "Get POH Counter" },
+ { 0x00, NULL },
+};
+
+static const value_string ipmi_bridge_cmd_vals[] = {
+ /* ICMB Bridge Management Commands */
+ { 0x00, "Get Bridge State" },
+ { 0x01, "Set Bridge State" },
+ { 0x02, "Get ICMB Address" },
+ { 0x03, "Set ICMB Address" },
+ { 0x04, "Set Bridge ProxyAddress" },
+ { 0x05, "Get Bridge Statistics" },
+ { 0x06, "Get ICMB Capabilities" },
+ { 0x08, "Clear Bridge Statistics" },
+ { 0x09, "Get Bridge Proxy Address" },
+ { 0x0a, "Get ICMB Connector Info" },
+ { 0x0b, "Get ICMB Connection ID" },
+ { 0x0c, "Send ICMB Connection ID" },
+ /* ICMB Discovery Commands */
+ { 0x10, "Prepare For Discovery" },
+ { 0x11, "Get Addresses" },
+ { 0x12, "Set Discovered" },
+ { 0x13, "Get Chassis Device ID" },
+ { 0x14, "Set Chassis Device ID" },
+ /* ICMB Bridging Commands */
+ { 0x20, "Bridge Request" },
+ { 0x21, "Bridge Message" },
+ /* ICMB Event Commands */
+ { 0x30, "Get Event Count" },
+ { 0x31, "Set Event Destination" },
+ { 0x32, "Set Event Reception State" },
+ { 0x33, "Send ICMB Event Message" },
+ { 0x34, "Get Event Destination" },
+ { 0x35, "Get Event Reception State" },
+ { 0x00, NULL },
+};
+
+static const value_string ipmi_se_cmd_vals[] = {
+ /* Event Commands */
+ { 0x00, "Set Event Receiver" },
+ { 0x01, "Get Event Receiver" },
+ { 0x02, "Platform Event Message" },
+ /* PEF and Alerting Commands */
+ { 0x10, "Get PEF Capabilities" },
+ { 0x11, "Arm PEF Postpone Timer" },
+ { 0x12, "Set PEF Config Params" },
+ { 0x13, "Get PEF Config Params" },
+ { 0x14, "Set Last Processed Event ID" },
+ { 0x15, "Get Last Processed Event ID" },
+ { 0x16, "Alert Immediate" },
+ { 0x17, "PET Acknowledge" },
+ /* Sensor Device Commands */
+ { 0x20, "Get Device SDR Info" },
+ { 0x21, "Get Device SDR" },
+ { 0x22, "Reserve Device SDR Repository" },
+ { 0x23, "Get Sensor Reading Factors" },
+ { 0x24, "Set Sensor Hysteresis" },
+ { 0x25, "Get Sensor Hysteresis" },
+ { 0x26, "Set Sensor Threshold" },
+ { 0x27, "Get Sensor Threshold" },
+ { 0x28, "Set Sensor Event Enable" },
+ { 0x29, "Get Sensor Event Enable" },
+ { 0x2a, "Re-arm Sensor Events" },
+ { 0x2b, "Get Sensor Event Status" },
+ { 0x2d, "Get Sensor Reading" },
+ { 0x2e, "Set Sensor Type" },
+ { 0x2f, "Get Sensor Type" },
+ { 0x00, NULL },
+};
+
+static const value_string ipmi_storage_cmd_vals[] = {
+ /* FRU Device Commands */
+ { 0x10, "Get FRU Inventory Area Info" },
+ { 0x11, "Read FRU Data" },
+ { 0x12, "Write FRU Data" },
+ /* SDR Device Commands */
+ { 0x20, "Get SDR Repository Info" },
+ { 0x21, "Get SDR Repository Allocation Info" },
+ { 0x22, "Reserve SDR Repository" },
+ { 0x23, "Get SDR" },
+ { 0x24, "Add SDR" },
+ { 0x25, "Partial Add SDR" },
+ { 0x26, "Delete SDR" },
+ { 0x27, "Clear SDR Repository" },
+ { 0x28, "Get SDR Repository Time" },
+ { 0x29, "Set SDR Repository Time" },
+ { 0x2a, "Enter SDR Repository Update Mode" },
+ { 0x2b, "Exit SDR Repository Update Mode" },
+ { 0x2c, "Run Initialization Agent" },
+ /* SEL Device Commands */
+ { 0x40, "Get SEL Info" },
+ { 0x41, "Get SEL Allocation Info" },
+ { 0x42, "Reserve SEL" },
+ { 0x43, "Get SEL Entry" },
+ { 0x44, "Add SEL Entry" },
+ { 0x45, "Partial Add SEL Entry" },
+ { 0x46, "Delete SEL Entry" },
+ { 0x47, "Clear SEL" },
+ { 0x48, "Get SEL Time" },
+ { 0x49, "Set SEL Time" },
+ { 0x5a, "Get Auxillary Log Status" },
+ { 0x5b, "Set Auxillary Log Status" },
+ { 0x00, NULL },
+};
+
+static const value_string ipmi_transport_cmd_vals[] = {
+ /* LAN Device Commands */
+ { 0x01, "Set LAN Config Param" },
+ { 0x02, "Get LAN Config Param" },
+ { 0x03, "Suspend BMC ARPs" },
+ { 0x04, "Get IP/UDP/RMCP Statistics" },
+ /* Serial/Modem Device Commands */
+ { 0x10, "Set Serial/Modem Config" },
+ { 0x11, "Get Serial/Modem Config" },
+ { 0x12, "Get Serial/Modem Mux" },
+ { 0x13, "Get TAP Response Codes" },
+ { 0x14, "Set PPP UDP Proxy Transmit Data" },
+ { 0x15, "Get PPP UDP Proxy Transmit Data" },
+ { 0x16, "Send PPP UDP Proxy Packet" },
+ { 0x17, "Get PPP UDP Proxy Data" },
+ { 0x18, "Serial/Modem Connection Active" },
+ { 0x19, "Callback" },
+ { 0x1a, "Set User Callback Options" },
+ { 0x1b, "Get User Callback Options" },
+ { 0x00, NULL },
+};
+
+static const value_string ipmi_app_cmd_vals[] = {
+ /* Device "Global" Commands */
+ { 0x01, "Get Device ID" },
+ { 0x02, "Cold Reset" },
+ { 0x03, "Warm Reset" },
+ { 0x04, "Get Self Test Results" },
+ { 0x05, "Manufacturing Test On" },
+ { 0x06, "Set ACPI Power State" },
+ { 0x07, "Get ACPI Power State" },
+ { 0x08, "Get Device GUID" },
+ /* BMC Watchdog Timer Commands */
+ { 0x22, "Reset Watchdog Timer" },
+ { 0x24, "Set Watchdog Timer" },
+ { 0x25, "Get Watchdog Timer" },
+ /* BMC Device and Messaging Commands */
+ { 0x2e, "Set BMC Global Enables" },
+ { 0x2f, "Get BMC Global Enables" },
+ { 0x30, "Clear Message Flags" },
+ { 0x31, "Get Message Flags" },
+ { 0x32, "Enable Message Channel Receive" },
+ { 0x33, "Get Message" },
+ { 0x34, "Send Message" },
+ { 0x35, "Read Event Message Buffer" },
+ { 0x36, "Get BT Interface Capabilities" },
+ { 0x37, "Get System GUID" },
+ { 0x38, "Get Channel Auth Capabilities" },
+ { 0x39, "Get Session Challenge" },
+ { 0x3a, "Activate Session" },
+ { 0x3b, "Set Session Privilege Level" },
+ { 0x3c, "Close Session" },
+ { 0x3d, "Get Session Info" },
+ { 0x3e, "unassigned" },
+ { 0x3f, "Get AuthCode" },
+ { 0x40, "Set Channel Access" },
+ { 0x41, "Get Channel Access" },
+ { 0x42, "Get Channel Info" },
+ { 0x43, "Set User Access" },
+ { 0x44, "Get User Access" },
+ { 0x45, "Set User Name" },
+ { 0x46, "Get User Name" },
+ { 0x47, "Set User Password" },
+ { 0x52, "Master Write-Read" },
+ { 0x00, NULL },
+};
+
+static const char *
+get_netfn_cmd_text(guint8 netfn, guint8 cmd)
+{
+ switch (netfn) {
+ case 0x00:
+ case 0x01:
+ return val_to_str(cmd, ipmi_chassis_cmd_vals, "Unknown (0x%02x)");
+ case 0x02:
+ case 0x03:
+ return val_to_str(cmd, ipmi_bridge_cmd_vals, "Unknown (0x%02x)");
+ case 0x04:
+ case 0x05:
+ return val_to_str(cmd, ipmi_se_cmd_vals, "Unknown (0x%02x)");
+ case 0x06:
+ case 0x07:
+ return val_to_str(cmd, ipmi_app_cmd_vals, "Unknown (0x%02x)");
+ case 0x0a:
+ case 0x0b:
+ return val_to_str(cmd, ipmi_storage_cmd_vals, "Unknown (0x%02x)");
+ case 0x0c:
+ case 0x0d:
+ return val_to_str(cmd, ipmi_transport_cmd_vals, "Unknown (0x%02x)");
+ default:
+ return (netfn & 1) ? "Unknown Response" : "Unknown Request";
+ }
+}
+
+static void
+dissect_ipmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ipmi_tree = NULL, *field_tree = NULL;
+ proto_item *ti = NULL, *tf;
+ gint offset = 0;
+ tvbuff_t *next_tvb;
+ guint32 session_id;
+ guint8 authtype, netfn, cmd, ccode, len;
+ gint response;
+
+ /* session authtype, 0=no authcode present */
+ authtype = tvb_get_guint8(tvb, 0);
+
+ /* session ID */
+ session_id = tvb_get_letohl(tvb, 5);
+
+ /* network function code */
+ netfn = tvb_get_guint8(tvb, authtype ? 27 : 11) >> 2;
+
+ /* bit 0 of netfn: even=request odd=response */
+ response = netfn & 1;
+
+ /* command */
+ cmd = tvb_get_guint8(tvb, authtype ? 31 : 15);
+
+ /* completion code */
+ ccode = response ? tvb_get_guint8(tvb, authtype ? 32 : 16) : 0;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPMI");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (ccode)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s, %s: %s",
+ get_netfn_cmd_text(netfn, cmd),
+ val_to_str(netfn, ipmi_netfn_vals, "Unknown (0x%02x)"),
+ val_to_str(ccode, ipmi_ccode_vals, "Unknown (0x%02x)"));
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s, %s",
+ get_netfn_cmd_text(netfn, cmd),
+ val_to_str(netfn, ipmi_netfn_vals, "Unknown (0x%02x)"));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_ipmi,
+ tvb, offset, authtype ? 32 : 16,
+ "Intelligent Platform Management Interface, "
+ "NetFn: %s (0x%02x), Cmd: %s (0x%02x)",
+ val_to_str(netfn, ipmi_netfn_vals, "Unknown (0x%02x)"),
+ netfn, get_netfn_cmd_text(netfn, cmd), cmd);
+ ipmi_tree = proto_item_add_subtree(ti, ett_ipmi);
+ }
+
+ /* ipmi session field */
+ if (tree) {
+ tf = proto_tree_add_text(ipmi_tree, tvb, offset,
+ authtype ? 25 : 9,
+ "Session: ID 0x%08x (%d bytes)",
+ session_id, authtype ? 25 : 9);
+ field_tree = proto_item_add_subtree(tf, ett_ipmi_session);
+ proto_tree_add_item(field_tree, hf_ipmi_session_authtype,
+ tvb, offset++, 1, TRUE);
+ proto_tree_add_item(field_tree, hf_ipmi_session_sequence,
+ tvb, offset, 4, TRUE);
+ offset += 4;
+ proto_tree_add_item(field_tree, hf_ipmi_session_id,
+ tvb, offset, 4, TRUE);
+ offset += 4;
+ if (authtype) {
+ proto_tree_add_item(field_tree, hf_ipmi_session_authcode,
+ tvb, offset, 16, TRUE);
+ offset += 16;
+ }
+ }
+
+ /* message length */
+ if (tree) {
+ proto_tree_add_item(ipmi_tree, hf_ipmi_msg_len,
+ tvb, offset++, 1, TRUE);
+ }
+
+ /* r[sq]addr */
+ if (tree) {
+ proto_tree_add_item(ipmi_tree,
+ response ? hf_ipmi_msg_rqaddr : hf_ipmi_msg_rsaddr,
+ tvb, offset++, 1, TRUE);
+ }
+
+ /* netfn/lun */
+ if (tree) {
+ guint8 lun;
+
+ tf = proto_tree_add_text(ipmi_tree, tvb, offset, 1,
+ "NetFn/LUN: %s (0x%02x)", val_to_str(netfn,
+ ipmi_netfn_vals, "Unknown (0x%02x)"),
+ netfn);
+
+ field_tree = proto_item_add_subtree(tf, ett_ipmi_msg_nlfield);
+
+ proto_tree_add_item(field_tree, hf_ipmi_msg_netfn,
+ tvb, offset, 1, TRUE);
+ proto_tree_add_item(field_tree,
+ response ? hf_ipmi_msg_rqlun : hf_ipmi_msg_rslun,
+ tvb, offset, 1, TRUE);
+ lun = tvb_get_guint8(tvb, offset) & 3;
+ proto_item_append_text(tf, ", LUN 0x%02x", lun);
+ offset += 1;
+ }
+
+ /* checksum */
+ if (tree) {
+ proto_tree_add_item(ipmi_tree, hf_ipmi_msg_csum1,
+ tvb, offset++, 1, TRUE);
+ }
+
+ /* r[sq]addr */
+ if (tree) {
+ proto_tree_add_item(ipmi_tree,
+ response ? hf_ipmi_msg_rsaddr : hf_ipmi_msg_rqaddr,
+ tvb, offset++, 1, TRUE);
+ }
+
+ /* seq/lun */
+ if (tree) {
+ guint8 lun;
+
+ tf = proto_tree_add_item(ipmi_tree, hf_ipmi_msg_slfield,
+ tvb, offset, 1, TRUE);
+ field_tree = proto_item_add_subtree(tf, ett_ipmi_msg_slfield);
+
+ proto_tree_add_item(field_tree, hf_ipmi_msg_seq,
+ tvb, offset, 1, TRUE);
+ proto_tree_add_item(field_tree,
+ response ? hf_ipmi_msg_rslun : hf_ipmi_msg_rqlun,
+ tvb, offset, 1, TRUE);
+ lun = tvb_get_guint8(tvb, offset) & 3;
+ proto_item_append_text(tf, ", LUN 0x%02x", lun);
+ offset += 1;
+ }
+
+ /* command */
+ if (tree) {
+ proto_tree_add_text(ipmi_tree, tvb, offset++, 1,
+ "Command: %s (0x%02x)",
+ get_netfn_cmd_text(netfn, cmd), cmd);
+ }
+
+ /* completion code */
+ if (tree && response) {
+ proto_tree_add_item(ipmi_tree, hf_ipmi_msg_ccode,
+ tvb, offset++, 1, TRUE);
+ }
+
+ /* determine data length */
+ len = tvb_get_guint8(tvb, authtype ? 25 : 9) - 7 - (response ? 1 : 0);
+
+ /* dissect the data block */
+ next_tvb = tvb_new_subset(tvb, offset, len, len);
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ offset += len;
+
+ /* checksum 2 */
+ if (tree) {
+ proto_tree_add_item(ipmi_tree, hf_ipmi_msg_csum2,
+ tvb, offset++, 1, TRUE);
+ }
+}
+
+void
+proto_register_ipmi(void)
+{
+ static hf_register_info hf_session[] = {
+ { &hf_ipmi_session_authtype, {
+ "Authentication Type", "ipmi.session.authtype",
+ FT_UINT8, BASE_HEX, VALS(ipmi_authtype_vals), 0,
+ "IPMI Authentication Type", HFILL }},
+ { &hf_ipmi_session_sequence, {
+ "Session Sequence Number", "ipmi.session.sequence",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "IPMI Session Sequence Number", HFILL }},
+ { &hf_ipmi_session_id, {
+ "Session ID", "ipmi.session.id",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "IPMI Session ID", HFILL }},
+ { &hf_ipmi_session_authcode, {
+ "Authentication Code", "ipmi.session.authcode",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "IPMI Message Authentication Code", HFILL }},
+ };
+ static hf_register_info hf_msg[] = {
+ { &hf_ipmi_msg_len, {
+ "Message Length", "ipmi.msg.len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "IPMI Message Length", HFILL }},
+ { &hf_ipmi_msg_rsaddr, {
+ "Response Address", "ipmi.msg.rsaddr",
+ FT_UINT8, BASE_HEX, VALS(ipmi_addr_vals), 0,
+ "Responder's Slave Address", HFILL }},
+ { &hf_ipmi_msg_csum1, {
+ "Checksum 1", "ipmi.msg.csum1",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "2s Complement Checksum", HFILL }},
+ { &hf_ipmi_msg_rqaddr, {
+ "Request Address", "ipmi.msg.rqaddr",
+ FT_UINT8, BASE_HEX, VALS(ipmi_addr_vals), 0,
+ "Requester's Address (SA or SWID)", HFILL }},
+ { &hf_ipmi_msg_cmd, {
+ "Command", "ipmi.msg.cmd",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "IPMI Command Byte", HFILL }},
+ { &hf_ipmi_msg_ccode, {
+ "Completion Code", "ipmi.msg.ccode",
+ FT_UINT8, BASE_HEX, VALS(ipmi_ccode_vals), 0,
+ "Completion Code for Request", HFILL }},
+ { &hf_ipmi_msg_csum2, {
+ "Checksum 2", "ipmi.msg.csum2",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "2s Complement Checksum", HFILL }},
+ };
+ static hf_register_info hf_msg_field[] = {
+ { &hf_ipmi_msg_nlfield, {
+ "NetFn/LUN", "ipmi.msg.nlfield",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Network Function and LUN field", HFILL }},
+ { &hf_ipmi_msg_netfn, {
+ "NetFn", "ipmi.msg.nlfield.netfn",
+ FT_UINT8, BASE_HEX, VALS(ipmi_netfn_vals), 0xfc,
+ "Network Function Code", HFILL }},
+ { &hf_ipmi_msg_rqlun, {
+ "Request LUN", "ipmi.msg.nlfield.rqlun",
+ FT_UINT8, BASE_HEX, NULL, 0x03,
+ "Requester's Logical Unit Number", HFILL }},
+ { &hf_ipmi_msg_slfield, {
+ "Seq/LUN", "ipmi.msg.slfield",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Sequence and LUN field", HFILL }},
+ { &hf_ipmi_msg_seq, {
+ "Sequence", "ipmi.msg.slfield.seq",
+ FT_UINT8, BASE_HEX, NULL, 0xfc,
+ "Sequence Number (requester)", HFILL }},
+ { &hf_ipmi_msg_rslun, {
+ "Response LUN", "ipmi.msg.slfield.rslun",
+ FT_UINT8, BASE_HEX, NULL, 0x03,
+ "Responder's Logical Unit Number", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ipmi,
+ &ett_ipmi_session,
+ &ett_ipmi_msg_nlfield,
+ &ett_ipmi_msg_slfield,
+ };
+
+ proto_ipmi = proto_register_protocol(
+ "Intelligent Platform Management Interface", "IPMI", "ipmi");
+
+ proto_register_field_array(proto_ipmi, hf_session,
+ array_length(hf_session));
+ proto_register_field_array(proto_ipmi, hf_msg,
+ array_length(hf_msg));
+ proto_register_field_array(proto_ipmi, hf_msg_field,
+ array_length(hf_msg_field));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ipmi(void)
+{
+ dissector_handle_t ipmi_handle;
+
+ data_handle = find_dissector("data");
+
+ ipmi_handle = create_dissector_handle(dissect_ipmi, proto_ipmi);
+ dissector_add("rmcp.class", RMCP_CLASS_IPMI, ipmi_handle);
+}
diff --git a/epan/dissectors/packet-ipp.c b/epan/dissectors/packet-ipp.c
new file mode 100644
index 0000000000..4b01e19cd2
--- /dev/null
+++ b/epan/dissectors/packet-ipp.c
@@ -0,0 +1,628 @@
+/* packet-ipp.c
+ * Routines for IPP packet disassembly
+ *
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "packet-http.h"
+
+static int proto_ipp = -1;
+
+static gint ett_ipp = -1;
+static gint ett_ipp_as = -1;
+static gint ett_ipp_attr = -1;
+
+static dissector_handle_t data_handle;
+
+#define PRINT_JOB 0x0002
+#define PRINT_URI 0x0003
+#define VALIDATE_JOB 0x0004
+#define CREATE_JOB 0x0005
+#define SEND_DOCUMENT 0x0006
+#define SEND_URI 0x0007
+#define CANCEL_JOB 0x0008
+#define GET_JOB_ATTRIBUTES 0x0009
+#define GET_JOBS 0x000A
+#define GET_PRINTER_ATTRIBUTES 0x000B
+
+static const value_string operation_vals[] = {
+ { PRINT_JOB, "Print-Job" },
+ { PRINT_URI, "Print-URI" },
+ { VALIDATE_JOB, "Validate-Job" },
+ { CREATE_JOB, "Create-Job" },
+ { SEND_DOCUMENT, "Send-Document" },
+ { SEND_URI, "Send-URI" },
+ { CANCEL_JOB, "Cancel-Job" },
+ { GET_JOB_ATTRIBUTES, "Get-Job-Attributes" },
+ { GET_JOBS, "Get-Jobs" },
+ { GET_PRINTER_ATTRIBUTES, "Get-Printer-Attributes" },
+ { 0, NULL }
+};
+
+#define STATUS_SUCCESSFUL 0x0000
+#define STATUS_INFORMATIONAL 0x0100
+#define STATUS_REDIRECTION 0x0200
+#define STATUS_CLIENT_ERROR 0x0400
+#define STATUS_SERVER_ERROR 0x0500
+
+#define STATUS_TYPE_MASK 0xFF00
+
+#define SUCCESSFUL_OK 0x0000
+#define SUCCESSFUL_OK_IGN_OR_SUB_ATTR 0x0001
+#define SUCCESSFUL_OK_CONFLICTING_ATTR 0x0002
+
+#define CLIENT_ERROR_BAD_REQUEST 0x0400
+#define CLIENT_ERROR_FORBIDDEN 0x0401
+#define CLIENT_ERROR_NOT_AUTHENTICATED 0x0402
+#define CLIENT_ERROR_NOT_AUTHORIZED 0x0403
+#define CLIENT_ERROR_NOT_POSSIBLE 0x0404
+#define CLIENT_ERROR_TIMEOUT 0x0405
+#define CLIENT_ERROR_NOT_FOUND 0x0406
+#define CLIENT_ERROR_GONE 0x0407
+#define CLIENT_ERROR_REQ_ENTITY_TOO_LRG 0x0408
+#define CLIENT_ERROR_REQ_VALUE_TOO_LONG 0x0409
+#define CLIENT_ERROR_DOC_FMT_NOT_SUPP 0x040A
+#define CLIENT_ERROR_ATTR_OR_VAL_NOT_SUPP 0x040B
+#define CLIENT_ERROR_URI_SCHEME_NOT_SUPP 0x040C
+#define CLIENT_ERROR_CHARSET_NOT_SUPP 0x040D
+#define CLIENT_ERROR_CONFLICTING_ATTRS 0x040E
+
+#define SERVER_ERROR_INTERNAL_ERROR 0x0500
+#define SERVER_ERROR_OPERATION_NOT_SUPP 0x0501
+#define SERVER_ERROR_SERVICE_UNAVAIL 0x0502
+#define SERVER_ERROR_VERSION_NOT_SUPP 0x0503
+#define SERVER_ERROR_DEVICE_ERROR 0x0504
+#define SERVER_ERROR_TEMPORARY_ERROR 0x0505
+#define SERVER_ERROR_NOT_ACCEPTING_JOBS 0x0506
+#define SERVER_ERROR_BUSY 0x0507
+#define SERVER_ERROR_JOB_CANCELED 0x0508
+
+static const value_string status_vals[] = {
+ { SUCCESSFUL_OK, "Successful-OK" },
+ { SUCCESSFUL_OK_IGN_OR_SUB_ATTR, "Successful-OK-Ignored-Or-Substituted-Attributes" },
+ { SUCCESSFUL_OK_CONFLICTING_ATTR, "Successful-OK-Conflicting-Attributes" },
+ { CLIENT_ERROR_BAD_REQUEST, "Client-Error-Bad-Request" },
+ { CLIENT_ERROR_FORBIDDEN, "Client-Error-Forbidden" },
+ { CLIENT_ERROR_NOT_AUTHENTICATED, "Client-Error-Not-Authenticated" },
+ { CLIENT_ERROR_NOT_AUTHORIZED, "Client-Error-Not-Authorized" },
+ { CLIENT_ERROR_NOT_POSSIBLE, "Client-Error-Not-Possible" },
+ { CLIENT_ERROR_TIMEOUT, "Client-Error-Timeout" },
+ { CLIENT_ERROR_NOT_FOUND, "Client-Error-Not-Found" },
+ { CLIENT_ERROR_GONE, "Client-Error-Gone" },
+ { CLIENT_ERROR_REQ_ENTITY_TOO_LRG, "Client-Error-Request-Entity-Too-Large" },
+ { CLIENT_ERROR_REQ_VALUE_TOO_LONG, "Client-Error-Request-Value-Too-Long" },
+ { CLIENT_ERROR_DOC_FMT_NOT_SUPP, "Client-Error-Document-Format-Not-Supported" },
+ { CLIENT_ERROR_ATTR_OR_VAL_NOT_SUPP, "Client-Error-Attributes-Or-Values-Not-Supported" },
+ { CLIENT_ERROR_URI_SCHEME_NOT_SUPP, "Client-Error-URI-Scheme-Not-Supported" },
+ { CLIENT_ERROR_CHARSET_NOT_SUPP, "Client-Error-Charset-Not-Supported" },
+ { CLIENT_ERROR_CONFLICTING_ATTRS, "Client-Error-Conflicting-Attributes" },
+ { SERVER_ERROR_INTERNAL_ERROR, "Server-Error-Internal-Error" },
+ { SERVER_ERROR_OPERATION_NOT_SUPP, "Server-Error-Operation-Not-Supported" },
+ { SERVER_ERROR_SERVICE_UNAVAIL, "Server-Error-Service-Unavailable" },
+ { SERVER_ERROR_VERSION_NOT_SUPP, "Server-Error-Version-Not-Supported" },
+ { SERVER_ERROR_DEVICE_ERROR, "Server-Error-Device-Error" },
+ { SERVER_ERROR_TEMPORARY_ERROR, "Server-Error-Temporary-Error" },
+ { SERVER_ERROR_NOT_ACCEPTING_JOBS, "Server-Error-Not-Accepting-Jobs" },
+ { SERVER_ERROR_BUSY, "Server-Error-Busy" },
+ { SERVER_ERROR_JOB_CANCELED, "Server-Error-Job-Canceled" },
+ { 0, NULL }
+};
+
+static int parse_attributes(tvbuff_t *tvb, int offset, proto_tree *tree);
+static proto_tree *add_integer_tree(proto_tree *tree, tvbuff_t *tvb,
+ int offset, int name_length, int value_length, guint8 tag);
+static void add_integer_value(gchar *tag_desc, proto_tree *tree,
+ tvbuff_t *tvb, int offset, int name_length, int value_length, guint8 tag);
+static proto_tree *add_octetstring_tree(proto_tree *tree, tvbuff_t *tvb,
+ int offset, int name_length, int value_length);
+static void add_octetstring_value(gchar *tag_desc, proto_tree *tree,
+ tvbuff_t *tvb, int offset, int name_length, int value_length);
+static proto_tree *add_charstring_tree(proto_tree *tree, tvbuff_t *tvb,
+ int offset, int name_length, int value_length);
+static void add_charstring_value(gchar *tag_desc, proto_tree *tree,
+ tvbuff_t *tvb, int offset, int name_length, int value_length);
+static int add_value_head(gchar *tag_desc, proto_tree *tree, tvbuff_t *tvb,
+ int offset, int name_length, int value_length);
+
+static void
+dissect_ipp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ipp_tree;
+ proto_item *ti;
+ int offset = 0;
+ gboolean is_request = (pinfo->destport == 631);
+ guint16 status_code;
+ gchar *status_fmt;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPP");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (is_request)
+ col_set_str(pinfo->cinfo, COL_INFO, "IPP request");
+ else
+ col_set_str(pinfo->cinfo, COL_INFO, "IPP response");
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ipp, tvb, offset, -1,
+ FALSE);
+ ipp_tree = proto_item_add_subtree(ti, ett_ipp);
+
+ proto_tree_add_text(ipp_tree, tvb, offset, 2, "Version: %u.%u",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset + 1));
+ offset += 2;
+
+ if (is_request) {
+ proto_tree_add_text(ipp_tree, tvb, offset, 2, "Operation-id: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), operation_vals,
+ "Unknown (0x%04x)"));
+ } else {
+ status_code = tvb_get_ntohs(tvb, offset);
+ switch (status_code & STATUS_TYPE_MASK) {
+
+ case STATUS_SUCCESSFUL:
+ status_fmt = "Successful (0x%04x)";
+ break;
+
+ case STATUS_INFORMATIONAL:
+ status_fmt = "Informational (0x%04x)";
+ break;
+
+ case STATUS_REDIRECTION:
+ status_fmt = "Redirection (0x%04x)";
+ break;
+
+ case STATUS_CLIENT_ERROR:
+ status_fmt = "Client error (0x%04x)";
+ break;
+
+ case STATUS_SERVER_ERROR:
+ status_fmt = "Server error (0x%04x)";
+ break;
+
+ default:
+ status_fmt = "Unknown (0x%04x)";
+ break;
+ }
+ proto_tree_add_text(ipp_tree, tvb, offset, 2, "Status-code: %s",
+ val_to_str(status_code, status_vals, status_fmt));
+ }
+ offset += 2;
+
+ proto_tree_add_text(ipp_tree, tvb, offset, 4, "Request ID: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ offset = parse_attributes(tvb, offset, ipp_tree);
+
+ if (tvb_offset_exists(tvb, offset)) {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo,
+ ipp_tree);
+ }
+ }
+}
+
+#define TAG_TYPE(tag) ((tag) & 0xF0)
+#define TAG_TYPE_DELIMITER 0x00
+#define TAG_TYPE_INTEGER 0x20
+#define TAG_TYPE_OCTETSTRING 0x30
+#define TAG_TYPE_CHARSTRING 0x40
+
+#define TAG_END_OF_ATTRIBUTES 0x03
+
+#define TAG_INTEGER 0x21
+#define TAG_BOOLEAN 0x22
+#define TAG_ENUM 0x23
+
+#define TAG_OCTETSTRING 0x30
+#define TAG_DATETIME 0x31
+#define TAG_RESOLUTION 0x32
+#define TAG_RANGEOFINTEGER 0x33
+#define TAG_TEXTWITHLANGUAGE 0x35
+#define TAG_NAMEWITHLANGUAGE 0x36
+
+#define TAG_TEXTWITHOUTLANGUAGE 0x41
+#define TAG_NAMEWITHOUTLANGUAGE 0x42
+#define TAG_KEYWORD 0x44
+#define TAG_URI 0x45
+#define TAG_URISCHEME 0x46
+#define TAG_CHARSET 0x47
+#define TAG_NATURALLANGUAGE 0x48
+#define TAG_MIMEMEDIATYPE 0x49
+
+static const value_string tag_vals[] = {
+ /* Delimiter tags */
+ { 0x01, "Operation attributes" },
+ { 0x02, "Job attributes" },
+ { TAG_END_OF_ATTRIBUTES, "End of attributes" },
+ { 0x04, "Printer attributes" },
+ { 0x05, "Unsupported attributes" },
+
+ /* Value tags */
+ { 0x10, "Unsupported" },
+ { 0x12, "Unknown" },
+ { 0x13, "No value" },
+ { TAG_INTEGER, "Integer" },
+ { TAG_BOOLEAN, "Boolean" },
+ { TAG_ENUM, "Enum" },
+ { TAG_OCTETSTRING, "Octet string" },
+ { TAG_DATETIME, "Date/Time" },
+ { TAG_RESOLUTION, "Resolution" },
+ { TAG_RANGEOFINTEGER, "Range of integer" },
+ { TAG_TEXTWITHLANGUAGE, "Text with language" },
+ { TAG_NAMEWITHLANGUAGE, "Name with language" },
+ { TAG_TEXTWITHOUTLANGUAGE, "Text without language" },
+ { TAG_NAMEWITHOUTLANGUAGE, "Name without language" },
+ { TAG_KEYWORD, "Keyword" },
+ { TAG_URI, "URI" },
+ { TAG_URISCHEME, "URI scheme" },
+ { TAG_CHARSET, "Character set" },
+ { TAG_NATURALLANGUAGE, "Natural language" },
+ { TAG_MIMEMEDIATYPE, "MIME media type" },
+ { 0, NULL }
+};
+
+static int
+parse_attributes(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint8 tag;
+ gchar *tag_desc;
+ int name_length, value_length;
+ proto_tree *as_tree = tree;
+ proto_item *tas = NULL;
+ int start_offset = offset;
+ proto_tree *attr_tree = tree;
+
+ while (tvb_offset_exists(tvb, offset)) {
+ tag = tvb_get_guint8(tvb, offset);
+ tag_desc = val_to_str(tag, tag_vals, "Reserved (0x%02x)");
+ if (TAG_TYPE(tag) == TAG_TYPE_DELIMITER) {
+ /*
+ * If we had an attribute sequence we were
+ * working on, we're done with it; set its
+ * length to the length of all the stuff
+ * we've done so far.
+ */
+ if (tas != NULL)
+ proto_item_set_len(tas, offset - start_offset);
+
+ /*
+ * This tag starts a new attribute sequence;
+ * create a new tree under this tag when we see
+ * a non-delimiter tag, under which to put
+ * those attributes.
+ */
+ as_tree = NULL;
+ attr_tree = tree;
+
+ /*
+ * Remember the offset at which this attribute
+ * sequence started, so we can use it to compute
+ * its length when it's finished.
+ */
+ start_offset = offset;
+
+ /*
+ * Now create a new item for this tag.
+ */
+ tas = proto_tree_add_text(tree, tvb, offset, 1,
+ "%s", tag_desc);
+ offset++;
+ if (tag == TAG_END_OF_ATTRIBUTES) {
+ /*
+ * No more attributes.
+ */
+ break;
+ }
+ } else {
+ /*
+ * Value tag - get the name length.
+ */
+ name_length = tvb_get_ntohs(tvb, offset + 1);
+
+ /*
+ * OK, get the value length.
+ */
+ value_length = tvb_get_ntohs(tvb, offset + 1 + 2 + name_length);
+
+ /*
+ * OK, does the value run past the end of the
+ * frame?
+ */
+ if (as_tree == NULL) {
+ /*
+ * OK, there's an attribute to hang
+ * under a delimiter tag, but we don't
+ * have a tree for that tag yet; create
+ * a tree.
+ */
+ as_tree = proto_item_add_subtree(tas,
+ ett_ipp_as);
+ attr_tree = as_tree;
+ }
+
+ switch (TAG_TYPE(tag)) {
+
+ case TAG_TYPE_INTEGER:
+ if (name_length != 0) {
+ /*
+ * This is an attribute, not
+ * an additional value, so
+ * start a tree for it.
+ */
+ attr_tree = add_integer_tree(as_tree,
+ tvb, offset, name_length,
+ value_length, tag);
+ }
+ add_integer_value(tag_desc, attr_tree, tvb,
+ offset, name_length, value_length, tag);
+ break;
+
+ case TAG_TYPE_OCTETSTRING:
+ if (name_length != 0) {
+ /*
+ * This is an attribute, not
+ * an additional value, so
+ * start a tree for it.
+ */
+ attr_tree = add_octetstring_tree(as_tree,
+ tvb, offset, name_length,
+ value_length);
+ }
+ add_octetstring_value(tag_desc, attr_tree, tvb,
+ offset, name_length, value_length);
+ break;
+
+ case TAG_TYPE_CHARSTRING:
+ if (name_length != 0) {
+ /*
+ * This is an attribute, not
+ * an additional value, so
+ * start a tree for it.
+ */
+ attr_tree = add_charstring_tree(as_tree,
+ tvb, offset, name_length,
+ value_length);
+ }
+ add_charstring_value(tag_desc, attr_tree, tvb,
+ offset, name_length, value_length);
+ break;
+ }
+ offset += 1 + 2 + name_length + 2 + value_length;
+ }
+ }
+
+ return offset;
+}
+
+static const value_string bool_vals[] = {
+ { 0x00, "false" },
+ { 0x01, "true" },
+ { 0, NULL }
+};
+
+static proto_tree *
+add_integer_tree(proto_tree *tree, tvbuff_t *tvb, int offset,
+ int name_length, int value_length, guint8 tag)
+{
+ proto_item *ti;
+ guint8 bool_val;
+
+ switch (tag) {
+
+ case TAG_BOOLEAN:
+ if (value_length != 1) {
+ ti = proto_tree_add_text(tree, tvb, offset,
+ 1 + 2 + name_length + 2 + value_length,
+ "%.*s: Invalid boolean (length is %u, should be 1)",
+ name_length,
+ tvb_get_ptr(tvb, offset + 1 + 2, name_length),
+ value_length);
+ } else {
+ bool_val = tvb_get_guint8(tvb,
+ offset + 1 + 2 + name_length + 2);
+ ti = proto_tree_add_text(tree, tvb, offset,
+ 1 + 2 + name_length + 2 + value_length,
+ "%.*s: %s",
+ name_length,
+ tvb_get_ptr(tvb, offset + 1 + 2, name_length),
+ val_to_str(bool_val, bool_vals, "Unknown (0x%02x)"));
+ }
+ break;
+
+ case TAG_INTEGER:
+ case TAG_ENUM:
+ if (value_length != 4) {
+ ti = proto_tree_add_text(tree, tvb, offset,
+ 1 + 2 + name_length + 2 + value_length,
+ "%.*s: Invalid integer (length is %u, should be 4)",
+ name_length,
+ tvb_get_ptr(tvb, offset + 1 + 2, name_length),
+ value_length);
+ } else {
+ ti = proto_tree_add_text(tree, tvb, offset,
+ 1 + 2 + name_length + 2 + value_length,
+ "%.*s: %u",
+ name_length,
+ tvb_get_ptr(tvb, offset + 1 + 2, name_length),
+ tvb_get_ntohl(tvb, offset + 1 + 2 + name_length + 2));
+ }
+ break;
+
+ default:
+ ti = proto_tree_add_text(tree, tvb, offset,
+ 1 + 2 + name_length + 2 + value_length,
+ "%.*s: Unknown integer type 0x%02x",
+ name_length,
+ tvb_get_ptr(tvb, offset + 1 + 2, name_length),
+ tag);
+ break;
+ }
+ return proto_item_add_subtree(ti, ett_ipp_attr);
+}
+
+static void
+add_integer_value(gchar *tag_desc, proto_tree *tree, tvbuff_t *tvb,
+ int offset, int name_length, int value_length, guint8 tag)
+{
+ guint8 bool_val;
+
+ offset = add_value_head(tag_desc, tree, tvb, offset, name_length,
+ value_length);
+
+ switch (tag) {
+
+ case TAG_BOOLEAN:
+ if (value_length == 1) {
+ bool_val = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, value_length,
+ "Value: %s",
+ val_to_str(bool_val, bool_vals, "Unknown (0x%02x)"));
+ }
+ break;
+
+ case TAG_INTEGER:
+ case TAG_ENUM:
+ if (value_length == 4) {
+ proto_tree_add_text(tree, tvb, offset, value_length,
+ "Value: %u", tvb_get_ntohl(tvb, offset));
+ }
+ break;
+ }
+}
+
+static proto_tree *
+add_octetstring_tree(proto_tree *tree, tvbuff_t *tvb, int offset,
+ int name_length, int value_length)
+{
+ proto_item *ti;
+
+ ti = proto_tree_add_text(tree, tvb, offset,
+ 1 + 2 + name_length + 2 + value_length,
+ "%.*s: %s",
+ name_length,
+ tvb_get_ptr(tvb, offset + 1 + 2, name_length),
+ tvb_bytes_to_str(tvb, offset + 1 + 2 + name_length + 2, value_length));
+ return proto_item_add_subtree(ti, ett_ipp_attr);
+}
+
+static void
+add_octetstring_value(gchar *tag_desc, proto_tree *tree, tvbuff_t *tvb,
+ int offset, int name_length, int value_length)
+{
+ offset = add_value_head(tag_desc, tree, tvb, offset, name_length,
+ value_length);
+ proto_tree_add_text(tree, tvb, offset, value_length,
+ "Value: %s", tvb_bytes_to_str(tvb, offset, value_length));
+}
+
+static proto_tree *
+add_charstring_tree(proto_tree *tree, tvbuff_t *tvb, int offset,
+ int name_length, int value_length)
+{
+ proto_item *ti;
+
+ ti = proto_tree_add_text(tree, tvb, offset,
+ 1 + 2 + name_length + 2 + value_length,
+ "%.*s: %.*s",
+ name_length,
+ tvb_get_ptr(tvb, offset + 1 + 2, name_length),
+ value_length,
+ tvb_get_ptr(tvb, offset + 1 + 2 + name_length + 2, value_length));
+ return proto_item_add_subtree(ti, ett_ipp_attr);
+}
+
+static void
+add_charstring_value(gchar *tag_desc, proto_tree *tree, tvbuff_t *tvb,
+ int offset, int name_length, int value_length)
+{
+ offset = add_value_head(tag_desc, tree, tvb, offset, name_length,
+ value_length);
+ proto_tree_add_text(tree, tvb, offset, value_length,
+ "Value: %.*s", value_length, tvb_get_ptr(tvb, offset, value_length));
+}
+
+static int
+add_value_head(gchar *tag_desc, proto_tree *tree, tvbuff_t *tvb, int offset,
+ int name_length, int value_length)
+{
+ proto_tree_add_text(tree, tvb, offset, 1, "Tag: %s", tag_desc);
+ offset += 1;
+ proto_tree_add_text(tree, tvb, offset, 2, "Name length: %u",
+ name_length);
+ offset += 2;
+ if (name_length != 0) {
+ proto_tree_add_text(tree, tvb, offset, name_length,
+ "Name: %.*s", name_length,
+ tvb_get_ptr(tvb, offset, name_length));
+ }
+ offset += name_length;
+ proto_tree_add_text(tree, tvb, offset, 2, "Value length: %u",
+ value_length);
+ offset += 2;
+ return offset;
+}
+
+void
+proto_register_ipp(void)
+{
+/* static hf_register_info hf[] = {
+ { &variable,
+ { "Name", "ipp.abbreviation", TYPE, VALS_POINTER }},
+ };*/
+ static gint *ett[] = {
+ &ett_ipp,
+ &ett_ipp_as,
+ &ett_ipp_attr,
+ };
+
+ proto_ipp = proto_register_protocol("Internet Printing Protocol",
+ "IPP", "ipp");
+ /* proto_register_field_array(proto_ipp, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ipp(void)
+{
+ dissector_handle_t ipp_handle;
+
+ /*
+ * Register ourselves as running atop HTTP and using port 631.
+ */
+ ipp_handle = create_dissector_handle(dissect_ipp, proto_ipp);
+ http_dissector_add(631, ipp_handle);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ipsec-udp.c b/epan/dissectors/packet-ipsec-udp.c
new file mode 100644
index 0000000000..afb52d0814
--- /dev/null
+++ b/epan/dissectors/packet-ipsec-udp.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2003 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id$
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+static int proto_udpencap = -1;
+static gint ett_udpencap = -1;
+
+static dissector_handle_t esp_handle;
+static dissector_handle_t isakmp_handle;
+
+/*
+ * UDP Encapsulation of IPsec Packets
+ * draft-ietf-ipsec-udp-encaps-06.txt
+ */
+static void
+dissect_udpencap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *next_tvb;
+ proto_tree *udpencap_tree = NULL;
+ proto_item *ti = NULL;
+ guint32 spi;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDPENCAP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_udpencap, tvb, 0, -1, FALSE);
+ udpencap_tree = proto_item_add_subtree(ti, ett_udpencap);
+ }
+
+ /* First byte of 0 iindicates NAT-keepalive */
+ if (tvb_get_guint8(tvb, 0) == 0xff) {
+ if (tree)
+ proto_tree_add_text(udpencap_tree, tvb, 0, 1, "NAT-keepalive packet");
+ } else {
+ /* SPI of zero indicates IKE traffic, otherwise it's ESP */
+ tvb_memcpy(tvb, (guint8 *)&spi, 0, sizeof(spi));
+ if (spi == 0) {
+ if (tree) {
+ proto_tree_add_text(udpencap_tree, tvb, 0, sizeof(spi),
+ "Non-ESP Marker");
+ proto_item_set_len(ti, sizeof(spi));
+ }
+ next_tvb = tvb_new_subset(tvb, sizeof(spi), -1, -1);
+ call_dissector(isakmp_handle, next_tvb, pinfo, tree);
+ } else {
+ if (tree)
+ proto_item_set_len(ti, 0);
+ call_dissector(esp_handle, tvb, pinfo, tree);
+ }
+ }
+}
+
+void
+proto_register_udpencap(void)
+{
+ static gint *ett[] = {
+ &ett_udpencap,
+ };
+
+ proto_udpencap = proto_register_protocol(
+ "UDP Encapsulation of IPsec Packets", "UDPENCAP", "udpencap");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_udpencap(void)
+{
+ dissector_handle_t udpencap_handle;
+
+ esp_handle = find_dissector("esp");
+ isakmp_handle = find_dissector("isakmp");
+
+ udpencap_handle = create_dissector_handle(dissect_udpencap, proto_udpencap);
+ dissector_add("udp.port", 4500, udpencap_handle);
+}
diff --git a/epan/dissectors/packet-ipsec.c b/epan/dissectors/packet-ipsec.c
new file mode 100644
index 0000000000..5ca0ed54dd
--- /dev/null
+++ b/epan/dissectors/packet-ipsec.c
@@ -0,0 +1,359 @@
+/* packet-ipsec.c
+ * Routines for IPsec/IPComp packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ipsec.h"
+#include <epan/resolv.h>
+#include "ipproto.h"
+#include "prefs.h"
+
+/* Place AH payload in sub tree */
+static gboolean g_ah_payload_in_subtree = FALSE;
+
+static int proto_ah = -1;
+static int hf_ah_spi = -1;
+static int hf_ah_sequence = -1;
+static int proto_esp = -1;
+static int hf_esp_spi = -1;
+static int hf_esp_sequence = -1;
+static int proto_ipcomp = -1;
+static int hf_ipcomp_flags = -1;
+static int hf_ipcomp_cpi = -1;
+
+static gint ett_ah = -1;
+static gint ett_esp = -1;
+static gint ett_ipcomp = -1;
+
+static dissector_handle_t data_handle;
+
+static dissector_table_t ip_dissector_table;
+
+struct newah {
+ guint8 ah_nxt; /* Next Header */
+ guint8 ah_len; /* Length of data + 1, in 32bit */
+ guint16 ah_reserve; /* Reserved for future use */
+ guint32 ah_spi; /* Security parameter index */
+ guint32 ah_seq; /* Sequence number field */
+ /* variable size, 32bit bound*/ /* Authentication data */
+};
+
+struct newesp {
+ guint32 esp_spi; /* ESP */
+ guint32 esp_seq; /* Sequence number */
+ /*variable size*/ /* (IV and) Payload data */
+ /*variable size*/ /* padding */
+ /*8bit*/ /* pad size */
+ /*8bit*/ /* next header */
+ /*8bit*/ /* next header */
+ /*variable size, 32bit bound*/ /* Authentication data */
+};
+
+struct ipcomp {
+ guint8 comp_nxt; /* Next Header */
+ guint8 comp_flags; /* Must be zero */
+ guint16 comp_cpi; /* Compression parameter index */
+};
+
+/* well-known algorithm number (in CPI), from RFC2409 */
+#define IPCOMP_OUI 1 /* vendor specific */
+#define IPCOMP_DEFLATE 2 /* RFC2394 */
+#define IPCOMP_LZS 3 /* RFC2395 */
+#define IPCOMP_MAX 4
+
+static const value_string cpi2val[] = {
+ { IPCOMP_OUI, "OUI" },
+ { IPCOMP_DEFLATE, "DEFLATE" },
+ { IPCOMP_LZS, "LZS" },
+ { 0, NULL },
+};
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+static void
+dissect_ah(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *next_tree;
+ guint8 nxt;
+ tvbuff_t *next_tvb;
+ int advance;
+
+ advance = dissect_ah_header(tvb, pinfo, tree, &nxt, &next_tree);
+ next_tvb = tvb_new_subset(tvb, advance, -1, -1);
+
+ if (g_ah_payload_in_subtree) {
+ col_set_writable(pinfo->cinfo, FALSE);
+ }
+
+ /* do lookup with the subdissector table */
+ if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, next_tree)) {
+ call_dissector(data_handle,next_tvb, pinfo, next_tree);
+ }
+}
+
+int
+dissect_ah_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 *nxt_p, proto_tree **next_tree_p)
+{
+ proto_tree *ah_tree;
+ proto_item *ti;
+ struct newah ah;
+ int advance;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AH");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb, (guint8 *)&ah, 0, sizeof(ah));
+ advance = sizeof(ah) + ((ah.ah_len - 1) << 2);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "AH (SPI=0x%08x)",
+ (guint32)g_ntohl(ah.ah_spi));
+ }
+
+ if (tree) {
+ /* !!! specify length */
+ ti = proto_tree_add_item(tree, proto_ah, tvb, 0, advance, FALSE);
+ ah_tree = proto_item_add_subtree(ti, ett_ah);
+
+ proto_tree_add_text(ah_tree, tvb,
+ offsetof(struct newah, ah_nxt), 1,
+ "Next Header: %s (0x%02x)",
+ ipprotostr(ah.ah_nxt), ah.ah_nxt);
+ proto_tree_add_text(ah_tree, tvb,
+ offsetof(struct newah, ah_len), 1,
+ "Length: %u", (ah.ah_len + 2) << 2);
+ proto_tree_add_uint(ah_tree, hf_ah_spi, tvb,
+ offsetof(struct newah, ah_spi), 4,
+ (guint32)g_ntohl(ah.ah_spi));
+ proto_tree_add_uint(ah_tree, hf_ah_sequence, tvb,
+ offsetof(struct newah, ah_seq), 4,
+ (guint32)g_ntohl(ah.ah_seq));
+ proto_tree_add_text(ah_tree, tvb,
+ sizeof(ah), (ah.ah_len - 1) << 2,
+ "ICV");
+
+ if (next_tree_p != NULL) {
+ /* Decide where to place next protocol decode */
+ if (g_ah_payload_in_subtree) {
+ *next_tree_p = ah_tree;
+ }
+ else {
+ *next_tree_p = tree;
+ }
+ }
+ } else {
+ if (next_tree_p != NULL)
+ *next_tree_p = NULL;
+ }
+
+ if (nxt_p != NULL)
+ *nxt_p = ah.ah_nxt;
+
+ /* start of the new header (could be a extension header) */
+ return advance;
+}
+
+static void
+dissect_esp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *esp_tree;
+ proto_item *ti;
+ struct newesp esp;
+
+ /*
+ * load the top pane info. This should be overwritten by
+ * the next protocol in the stack
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb, (guint8 *)&esp, 0, sizeof(esp));
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "ESP (SPI=0x%08x)",
+ (guint32)g_ntohl(esp.esp_spi));
+ }
+
+ /*
+ * populate a tree in the second pane with the status of the link layer
+ * (ie none)
+ */
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_esp, tvb, 0, -1, FALSE);
+ esp_tree = proto_item_add_subtree(ti, ett_esp);
+ proto_tree_add_uint(esp_tree, hf_esp_spi, tvb,
+ offsetof(struct newesp, esp_spi), 4,
+ (guint32)g_ntohl(esp.esp_spi));
+ proto_tree_add_uint(esp_tree, hf_esp_sequence, tvb,
+ offsetof(struct newesp, esp_seq), 4,
+ (guint32)g_ntohl(esp.esp_seq));
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, sizeof(struct newesp), -1, -1),
+ pinfo, esp_tree);
+ }
+}
+
+static void
+dissect_ipcomp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ipcomp_tree;
+ proto_item *ti;
+ struct ipcomp ipcomp;
+ char *p;
+
+ /*
+ * load the top pane info. This should be overwritten by
+ * the next protocol in the stack
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPComp");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb, (guint8 *)&ipcomp, 0, sizeof(ipcomp));
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ p = match_strval(g_ntohs(ipcomp.comp_cpi), cpi2val);
+ if (p == NULL) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "IPComp (CPI=0x%04x)",
+ g_ntohs(ipcomp.comp_cpi));
+ } else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "IPComp (CPI=%s)", p);
+ }
+
+ /*
+ * populate a tree in the second pane with the status of the link layer
+ * (ie none)
+ */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ipcomp, tvb, 0, -1, FALSE);
+ ipcomp_tree = proto_item_add_subtree(ti, ett_ipcomp);
+
+ proto_tree_add_text(ipcomp_tree, tvb,
+ offsetof(struct ipcomp, comp_nxt), 1,
+ "Next Header: %s (0x%02x)",
+ ipprotostr(ipcomp.comp_nxt), ipcomp.comp_nxt);
+ proto_tree_add_uint(ipcomp_tree, hf_ipcomp_flags, tvb,
+ offsetof(struct ipcomp, comp_flags), 1,
+ ipcomp.comp_flags);
+ proto_tree_add_uint(ipcomp_tree, hf_ipcomp_cpi, tvb,
+ offsetof(struct ipcomp, comp_cpi), 2,
+ g_ntohs(ipcomp.comp_cpi));
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, sizeof(struct ipcomp), -1, -1), pinfo,
+ ipcomp_tree);
+ }
+}
+
+void
+proto_register_ipsec(void)
+{
+
+ static hf_register_info hf_ah[] = {
+ { &hf_ah_spi,
+ { "SPI", "ah.spi", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ah_sequence,
+ { "Sequence", "ah.sequence", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }}
+ };
+
+ static hf_register_info hf_esp[] = {
+ { &hf_esp_spi,
+ { "SPI", "esp.spi", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_esp_sequence,
+ { "Sequence", "esp.sequence", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }}
+ };
+
+ static hf_register_info hf_ipcomp[] = {
+ { &hf_ipcomp_flags,
+ { "Flags", "ipcomp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ipcomp_cpi,
+ { "CPI", "ipcomp.cpi", FT_UINT16, BASE_HEX,
+ VALS(cpi2val), 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ah,
+ &ett_esp,
+ &ett_ipcomp,
+ };
+
+ module_t *ah_module;
+
+ proto_ah = proto_register_protocol("Authentication Header", "AH", "ah");
+ proto_register_field_array(proto_ah, hf_ah, array_length(hf_ah));
+
+ proto_esp = proto_register_protocol("Encapsulating Security Payload",
+ "ESP", "esp");
+ proto_register_field_array(proto_esp, hf_esp, array_length(hf_esp));
+
+ proto_ipcomp = proto_register_protocol("IP Payload Compression",
+ "IPComp", "ipcomp");
+ proto_register_field_array(proto_ipcomp, hf_ipcomp, array_length(hf_ipcomp));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register a configuration option for placement of AH payload dissection */
+ ah_module = prefs_register_protocol(proto_ah, NULL);
+ prefs_register_bool_preference(ah_module, "place_ah_payload_in_subtree",
+ "Place AH payload in subtree",
+"Whether the AH payload decode should be placed in a subtree",
+ &g_ah_payload_in_subtree);
+
+ register_dissector("esp", dissect_esp, proto_esp);
+ register_dissector("ah", dissect_ah, proto_ah);
+}
+
+void
+proto_reg_handoff_ipsec(void)
+{
+ dissector_handle_t esp_handle, ah_handle, ipcomp_handle;
+
+ data_handle = find_dissector("data");
+ ah_handle = find_dissector("ah");
+ dissector_add("ip.proto", IP_PROTO_AH, ah_handle);
+ esp_handle = find_dissector("esp");
+ dissector_add("ip.proto", IP_PROTO_ESP, esp_handle);
+ ipcomp_handle = create_dissector_handle(dissect_ipcomp, proto_ipcomp);
+ dissector_add("ip.proto", IP_PROTO_IPCOMP, ipcomp_handle);
+
+ ip_dissector_table = find_dissector_table("ip.proto");
+}
diff --git a/epan/dissectors/packet-ipsec.h b/epan/dissectors/packet-ipsec.h
new file mode 100644
index 0000000000..62d3d58a9f
--- /dev/null
+++ b/epan/dissectors/packet-ipsec.h
@@ -0,0 +1,31 @@
+/* packet-ipsec.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_IPSEC_H__
+#define __PACKET_IPSEC_H__
+
+int dissect_ah_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 *nxt_p, proto_tree **next_tree_p);
+
+#endif
diff --git a/epan/dissectors/packet-ipv6.c b/epan/dissectors/packet-ipv6.c
new file mode 100644
index 0000000000..3c0a2b6572
--- /dev/null
+++ b/epan/dissectors/packet-ipv6.c
@@ -0,0 +1,960 @@
+/* packet-ipv6.c
+ * Routines for IPv6 packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * MobileIPv6 support added by Tomislav Borosa <tomislav.borosa@siemens.hr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ipsec.h"
+#include "packet-ipv6.h"
+#include "ip_opts.h"
+#include <epan/resolv.h>
+#include "prefs.h"
+#include "reassemble.h"
+#include "ipproto.h"
+#include "etypes.h"
+#include "ppptypes.h"
+#include "aftypes.h"
+#include "nlpid.h"
+#include "arcnet_pids.h"
+
+/*
+ * NOTE: ipv6.nxt is not very useful as we will have chained header.
+ * now testing ipv6.final, but it raises SEGV.
+#define TEST_FINALHDR
+ */
+
+static int proto_ipv6 = -1;
+static int hf_ipv6_version = -1;
+static int hf_ipv6_class = -1;
+static int hf_ipv6_flow = -1;
+static int hf_ipv6_plen = -1;
+static int hf_ipv6_nxt = -1;
+static int hf_ipv6_hlim = -1;
+static int hf_ipv6_src = -1;
+static int hf_ipv6_dst = -1;
+static int hf_ipv6_addr = -1;
+#ifdef TEST_FINALHDR
+static int hf_ipv6_final = -1;
+#endif
+static int hf_ipv6_fragments = -1;
+static int hf_ipv6_fragment = -1;
+static int hf_ipv6_fragment_overlap = -1;
+static int hf_ipv6_fragment_overlap_conflict = -1;
+static int hf_ipv6_fragment_multiple_tails = -1;
+static int hf_ipv6_fragment_too_long_fragment = -1;
+static int hf_ipv6_fragment_error = -1;
+static int hf_ipv6_reassembled_in = -1;
+
+static int hf_ipv6_mipv6_type = -1;
+static int hf_ipv6_mipv6_length = -1;
+static int hf_ipv6_mipv6_home_address = -1;
+
+static gint ett_ipv6 = -1;
+static gint ett_ipv6_fragments = -1;
+static gint ett_ipv6_fragment = -1;
+
+static const fragment_items ipv6_frag_items = {
+ &ett_ipv6_fragment,
+ &ett_ipv6_fragments,
+ &hf_ipv6_fragments,
+ &hf_ipv6_fragment,
+ &hf_ipv6_fragment_overlap,
+ &hf_ipv6_fragment_overlap_conflict,
+ &hf_ipv6_fragment_multiple_tails,
+ &hf_ipv6_fragment_too_long_fragment,
+ &hf_ipv6_fragment_error,
+ &hf_ipv6_reassembled_in,
+ "fragments"
+};
+
+static dissector_handle_t data_handle;
+
+static dissector_table_t ip_dissector_table;
+
+/* Reassemble fragmented datagrams */
+static gboolean ipv6_reassemble = FALSE;
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+/*
+ * defragmentation of IPv6
+ */
+static GHashTable *ipv6_fragment_table = NULL;
+static GHashTable *ipv6_reassembled_table = NULL;
+
+void
+capture_ipv6(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ guint8 nxt;
+ int advance;
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, 4+4+16+16)) {
+ ld->other++;
+ return;
+ }
+ nxt = pd[offset+6]; /* get the "next header" value */
+ offset += 4+4+16+16; /* skip past the IPv6 header */
+
+again:
+ switch (nxt) {
+ case IP_PROTO_HOPOPTS:
+ case IP_PROTO_ROUTING:
+ case IP_PROTO_DSTOPTS:
+ if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
+ ld->other++;
+ return;
+ }
+ nxt = pd[offset];
+ advance = (pd[offset+1] + 1) << 3;
+ if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
+ ld->other++;
+ return;
+ }
+ offset += advance;
+ goto again;
+ case IP_PROTO_FRAGMENT:
+ if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
+ ld->other++;
+ return;
+ }
+ nxt = pd[offset];
+ advance = 8;
+ if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
+ ld->other++;
+ return;
+ }
+ offset += advance;
+ goto again;
+ case IP_PROTO_AH:
+ if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
+ ld->other++;
+ return;
+ }
+ nxt = pd[offset];
+ advance = 8 + ((pd[offset+1] - 1) << 2);
+ if (!BYTES_ARE_IN_FRAME(offset, len, advance)) {
+ ld->other++;
+ return;
+ }
+ offset += advance;
+ goto again;
+ }
+
+ switch(nxt) {
+ case IP_PROTO_SCTP:
+ ld->sctp++;
+ break;
+ case IP_PROTO_TCP:
+ ld->tcp++;
+ break;
+ case IP_PROTO_UDP:
+ ld->udp++;
+ break;
+ case IP_PROTO_ICMP:
+ case IP_PROTO_ICMPV6: /* XXX - separate counters? */
+ ld->icmp++;
+ break;
+ case IP_PROTO_OSPF:
+ ld->ospf++;
+ break;
+ case IP_PROTO_GRE:
+ ld->gre++;
+ break;
+ case IP_PROTO_VINES:
+ ld->vines++;
+ break;
+ default:
+ ld->other++;
+ }
+}
+
+static void
+ipv6_reassemble_init(void)
+{
+ fragment_table_init(&ipv6_fragment_table);
+ reassembled_table_init(&ipv6_reassembled_table);
+}
+
+static int
+dissect_routing6(tvbuff_t *tvb, int offset, proto_tree *tree) {
+ struct ip6_rthdr rt;
+ guint len;
+ proto_tree *rthdr_tree;
+ proto_item *ti;
+ char buf[sizeof(struct ip6_rthdr0) + sizeof(struct e_in6_addr) * 23];
+
+ tvb_memcpy(tvb, (guint8 *)&rt, offset, sizeof(rt));
+ len = (rt.ip6r_len + 1) << 3;
+
+ if (tree) {
+ /* !!! specify length */
+ ti = proto_tree_add_text(tree, tvb, offset, len,
+ "Routing Header, Type %u", rt.ip6r_type);
+ rthdr_tree = proto_item_add_subtree(ti, ett_ipv6);
+
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_rthdr, ip6r_nxt), 1,
+ "Next header: %s (0x%02x)", ipprotostr(rt.ip6r_nxt), rt.ip6r_nxt);
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_rthdr, ip6r_len), 1,
+ "Length: %u (%d bytes)", rt.ip6r_len, len);
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_rthdr, ip6r_type), 1,
+ "Type: %u", rt.ip6r_type);
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_rthdr, ip6r_segleft), 1,
+ "Segments left: %u", rt.ip6r_segleft);
+
+ if (rt.ip6r_type == 0 && len <= sizeof(buf)) {
+ struct e_in6_addr *a;
+ int n;
+ struct ip6_rthdr0 *rt0;
+
+ tvb_memcpy(tvb, buf, offset, len);
+ rt0 = (struct ip6_rthdr0 *)buf;
+ for (a = rt0->ip6r0_addr, n = 0;
+ a < (struct e_in6_addr *)(buf + len);
+ a++, n++) {
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_rthdr0, ip6r0_addr) + n * sizeof(struct e_in6_addr),
+ sizeof(struct e_in6_addr),
+#ifdef INET6
+ "address %d: %s (%s)",
+ n, get_hostname6(a), ip6_to_str(a)
+#else
+ "address %d: %s", n, ip6_to_str(a)
+#endif
+ );
+ }
+ }
+ if (rt.ip6r_type == 2) {
+ proto_tree_add_ipv6(rthdr_tree, hf_ipv6_mipv6_home_address,
+ tvb, offset + 8, 16,
+ tvb_get_ptr(tvb, offset + 8, 16));
+ }
+ }
+
+ return len;
+}
+
+static int
+dissect_frag6(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
+ guint16 *offlg, guint32 *ident) {
+ struct ip6_frag frag;
+ int len;
+ proto_item *ti;
+ proto_tree *rthdr_tree;
+
+ tvb_memcpy(tvb, (guint8 *)&frag, offset, sizeof(frag));
+ len = sizeof(frag);
+ frag.ip6f_offlg = g_ntohs(frag.ip6f_offlg);
+ frag.ip6f_ident = g_ntohl(frag.ip6f_ident);
+ *offlg = frag.ip6f_offlg;
+ *ident = frag.ip6f_ident;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "IPv6 fragment (nxt=%s (0x%02x) off=%u id=0x%x)",
+ ipprotostr(frag.ip6f_nxt), frag.ip6f_nxt,
+ frag.ip6f_offlg & IP6F_OFF_MASK, frag.ip6f_ident);
+ }
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, len,
+ "Fragmentation Header");
+ rthdr_tree = proto_item_add_subtree(ti, ett_ipv6);
+
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_frag, ip6f_nxt), 1,
+ "Next header: %s (0x%02x)",
+ ipprotostr(frag.ip6f_nxt), frag.ip6f_nxt);
+
+#if 0
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_frag, ip6f_reserved), 1,
+ "Reserved: %u",
+ frag.ip6f_reserved);
+#endif
+
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_frag, ip6f_offlg), 2,
+ "Offset: %u",
+ frag.ip6f_offlg & IP6F_OFF_MASK);
+
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_frag, ip6f_offlg), 2,
+ "More fragments: %s",
+ frag.ip6f_offlg & IP6F_MORE_FRAG ?
+ "Yes" : "No");
+
+ proto_tree_add_text(rthdr_tree, tvb,
+ offset + offsetof(struct ip6_frag, ip6f_ident), 4,
+ "Identification: 0x%08x",
+ frag.ip6f_ident);
+ }
+ return len;
+}
+
+static int
+dissect_mipv6_hoa(tvbuff_t *tvb, proto_tree *dstopt_tree, int offset)
+{
+ int len = 0;
+
+ proto_tree_add_uint_format(dstopt_tree, hf_ipv6_mipv6_type, tvb,
+ offset + len, 1,
+ tvb_get_guint8(tvb, offset + len),
+ "Option Type: %u (0x%02x) - Home Address Option",
+ tvb_get_guint8(tvb, offset + len),
+ tvb_get_guint8(tvb, offset + len));
+ len += 1;
+
+ proto_tree_add_uint(dstopt_tree, hf_ipv6_mipv6_length, tvb, offset + len,
+ 1, tvb_get_guint8(tvb, offset + len));
+ len += 1;
+
+ proto_tree_add_ipv6(dstopt_tree, hf_ipv6_mipv6_home_address, tvb,
+ offset + len, 16, tvb_get_ptr(tvb, offset + len, 16));
+ len += 16;
+ return len;
+}
+
+static const value_string rtalertvals[] = {
+ { IP6OPT_RTALERT_MLD, "MLD" },
+ { IP6OPT_RTALERT_RSVP, "RSVP" },
+ { 0, NULL },
+};
+
+/* Like "dissect_ip_tcp_options()", but assumes the length of an option
+ *doesn't* include the type and length bytes. */
+void
+dissect_ipv6_options(tvbuff_t *tvb, int offset, guint length,
+ const ip_tcp_opt *opttab, int nopts, int eol,
+ packet_info *pinfo, proto_tree *opt_tree)
+{
+ guchar opt;
+ const ip_tcp_opt *optp;
+ opt_len_type len_type;
+ unsigned int optlen;
+ char *name;
+ char name_str[7+1+1+2+2+1+1]; /* "Unknown (0x%02x)" */
+ void (*dissect)(const struct ip_tcp_opt *, tvbuff_t *,
+ int, guint, packet_info *, proto_tree *);
+ guint len;
+
+ while (length > 0) {
+ opt = tvb_get_guint8(tvb, offset);
+ for (optp = &opttab[0]; optp < &opttab[nopts]; optp++) {
+ if (optp->optcode == opt)
+ break;
+ }
+ if (optp == &opttab[nopts]) {
+ /* We assume that the only NO_LENGTH options are Pad1 options,
+ so that we can treat unknown options as VARIABLE_LENGTH with a
+ minimum of 0, and at least be able to move on to the next option
+ by using the length in the option. */
+ optp = NULL; /* indicate that we don't know this option */
+ len_type = VARIABLE_LENGTH;
+ optlen = 0;
+ snprintf(name_str, sizeof name_str, "Unknown (0x%02x)", opt);
+ name = name_str;
+ dissect = NULL;
+ } else {
+ len_type = optp->len_type;
+ optlen = optp->optlen;
+ name = optp->name;
+ dissect = optp->dissect;
+ }
+ --length; /* account for type byte */
+ if (len_type != NO_LENGTH) {
+ /* Option has a length. Is it in the packet? */
+ if (length == 0) {
+ /* Bogus - packet must at least include option code byte and
+ length byte! */
+ proto_tree_add_text(opt_tree, tvb, offset, 1,
+ "%s (length byte past end of options)", name);
+ return;
+ }
+ len = tvb_get_guint8(tvb, offset + 1); /* total including type, len */
+ --length; /* account for length byte */
+ if (len > length) {
+ /* Bogus - option goes past the end of the header. */
+ proto_tree_add_text(opt_tree, tvb, offset, length,
+ "%s (option length = %u byte%s says option goes past end of options)",
+ name, len, plurality(len, "", "s"));
+ return;
+ } else if (len_type == FIXED_LENGTH && len != optlen) {
+ /* Bogus - option length isn't what it's supposed to be for this
+ option. */
+ proto_tree_add_text(opt_tree, tvb, offset, 2 + len,
+ "%s (with option length = %u byte%s; should be %u)", name,
+ len, plurality(len, "", "s"), optlen);
+ return;
+ } else if (len_type == VARIABLE_LENGTH && len < optlen) {
+ /* Bogus - option length is less than what it's supposed to be for
+ this option. */
+ proto_tree_add_text(opt_tree, tvb, offset, 2 + len,
+ "%s (with option length = %u byte%s; should be >= %u)", name,
+ len, plurality(len, "", "s"), optlen);
+ return;
+ } else {
+ if (optp == NULL) {
+ proto_tree_add_text(opt_tree, tvb, offset, 2 + len, "%s (%u byte%s)",
+ name, len, plurality(len, "", "s"));
+ } else {
+ if (dissect != NULL) {
+ /* Option has a dissector. */
+ (*dissect)(optp, tvb, offset, 2 + len, pinfo, opt_tree);
+ } else {
+ /* Option has no data, hence no dissector. */
+ proto_tree_add_text(opt_tree, tvb, offset, 2 + len, "%s", name);
+ }
+ }
+ offset += 2 + len;
+ }
+ length -= len;
+ } else {
+ proto_tree_add_text(opt_tree, tvb, offset, 1, "%s", name);
+ offset += 1;
+ }
+ if (opt == eol)
+ break;
+ }
+}
+
+static int
+dissect_opts(tvbuff_t *tvb, int offset, proto_tree *tree, char *optname)
+{
+ struct ip6_ext ext;
+ int len;
+ proto_tree *dstopt_tree;
+ proto_item *ti;
+ gint p;
+ guint8 tmp;
+ int mip_offset = 0, delta = 0;
+
+ tvb_memcpy(tvb, (guint8 *)&ext, offset, sizeof(ext));
+ len = (ext.ip6e_len + 1) << 3;
+
+ if (tree) {
+ /* !!! specify length */
+ ti = proto_tree_add_text(tree, tvb, offset, len, "%s Header ", optname);
+
+ dstopt_tree = proto_item_add_subtree(ti, ett_ipv6);
+
+ proto_tree_add_text(dstopt_tree, tvb,
+ offset + offsetof(struct ip6_ext, ip6e_nxt), 1,
+ "Next header: %s (0x%02x)", ipprotostr(ext.ip6e_nxt), ext.ip6e_nxt);
+ proto_tree_add_text(dstopt_tree, tvb,
+ offset + offsetof(struct ip6_ext, ip6e_len), 1,
+ "Length: %u (%d bytes)", ext.ip6e_len, len);
+
+ mip_offset = offset;
+ mip_offset += 2;
+
+ p = offset + 2;
+
+ while (p < offset + len) {
+ switch (tvb_get_guint8(tvb, p)) {
+ case IP6OPT_PAD1:
+ proto_tree_add_text(dstopt_tree, tvb, p, 1, "Pad1");
+ p++;
+ mip_offset++;
+ break;
+ case IP6OPT_PADN:
+ tmp = tvb_get_guint8(tvb, p + 1);
+ proto_tree_add_text(dstopt_tree, tvb, p, tmp + 2,
+ "PadN: %u bytes", tmp + 2);
+ p += tmp;
+ p += 2;
+ mip_offset += tvb_get_guint8(tvb, mip_offset + 1) + 2;
+ break;
+ case IP6OPT_JUMBO:
+ tmp = tvb_get_guint8(tvb, p + 1);
+ if (tmp == 4) {
+ proto_tree_add_text(dstopt_tree, tvb, p, tmp + 2,
+ "Jumbo payload: %u (%u bytes)",
+ tvb_get_ntohl(tvb, p + 2), tmp + 2);
+ } else {
+ proto_tree_add_text(dstopt_tree, tvb, p, tmp + 2,
+ "Jumbo payload: Invalid length (%u bytes)",
+ tmp + 2);
+ }
+ p += tmp;
+ p += 2;
+ mip_offset += tvb_get_guint8(tvb, mip_offset+1)+2;
+ break;
+ case IP6OPT_RTALERT:
+ {
+ char *rta;
+
+ tmp = tvb_get_guint8(tvb, p + 1);
+ if (tmp == 2) {
+ rta = val_to_str(tvb_get_ntohs(tvb, p + 2), rtalertvals,
+ "Unknown");
+ } else
+ rta = "Invalid length";
+ ti = proto_tree_add_text(dstopt_tree, tvb, p , tmp + 2,
+ "Router alert: %s (%u bytes)", rta, tmp + 2);
+ p += tmp;
+ p += 2;
+ mip_offset += tvb_get_guint8(tvb, mip_offset + 1) + 2;
+ break;
+ }
+ case IP6OPT_HOME_ADDRESS:
+ delta = dissect_mipv6_hoa(tvb, dstopt_tree, mip_offset);
+ p += delta;
+ mip_offset += delta;
+ break;
+ default:
+ p = offset + len;
+ break;
+ }
+ }
+
+ /* decode... */
+ }
+ return len;
+}
+
+static int
+dissect_hopopts(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ return dissect_opts(tvb, offset, tree, "Hop-by-hop Option");
+}
+
+static int
+dissect_dstopts(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ return dissect_opts(tvb, offset, tree, "Destination Option");
+}
+
+static void
+dissect_ipv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ipv6_tree = NULL;
+ proto_item *ti;
+ guint8 nxt;
+ int advance;
+ int poffset;
+ guint16 plen;
+ gboolean hopopts, routing, frag, ah, dstopts;
+ guint16 offlg;
+ guint32 ident;
+ int offset;
+ fragment_data *ipfd_head;
+ tvbuff_t *next_tvb;
+ gboolean update_col_info = TRUE;
+ gboolean save_fragmented;
+
+ struct ip6_hdr ipv6;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPv6");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ offset = 0;
+ tvb_memcpy(tvb, (guint8 *)&ipv6, offset, sizeof(ipv6));
+
+ pinfo->ipproto = ipv6.ip6_nxt; /* XXX make work TCP follow (ipproto = 6) */
+
+ /* Get the payload length */
+ plen = g_ntohs(ipv6.ip6_plen);
+
+ /* Adjust the length of this tvbuff to include only the IPv6 datagram. */
+ set_actual_length(tvb, plen + sizeof (struct ip6_hdr));
+
+ SET_ADDRESS(&pinfo->net_src, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_SRC, 16));
+ SET_ADDRESS(&pinfo->src, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_SRC, 16));
+ SET_ADDRESS(&pinfo->net_dst, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_DST, 16));
+ SET_ADDRESS(&pinfo->dst, AT_IPv6, 16, tvb_get_ptr(tvb, offset + IP6H_DST, 16));
+
+ if (tree) {
+ /* !!! specify length */
+ ti = proto_tree_add_item(tree, proto_ipv6, tvb, offset, 40, FALSE);
+ ipv6_tree = proto_item_add_subtree(ti, ett_ipv6);
+
+ /* !!! warning: version also contains 4 Bit priority */
+ proto_tree_add_uint(ipv6_tree, hf_ipv6_version, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_vfc), 1,
+ (ipv6.ip6_vfc >> 4) & 0x0f);
+
+ proto_tree_add_uint(ipv6_tree, hf_ipv6_class, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_flow), 4,
+ (guint8)((g_ntohl(ipv6.ip6_flow) >> 20) & 0xff));
+
+ /*
+ * there should be no alignment problems for ip6_flow, since it's the first
+ * guint32 in the ipv6 struct
+ */
+ proto_tree_add_uint_format(ipv6_tree, hf_ipv6_flow, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_flow), 4,
+ (unsigned long)(g_ntohl(ipv6.ip6_flow) & IPV6_FLOWLABEL_MASK),
+ "Flowlabel: 0x%05lx",
+ (unsigned long)(g_ntohl(ipv6.ip6_flow) & IPV6_FLOWLABEL_MASK));
+
+ proto_tree_add_uint(ipv6_tree, hf_ipv6_plen, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_plen), 2,
+ plen);
+
+ proto_tree_add_uint_format(ipv6_tree, hf_ipv6_nxt, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_nxt), 1,
+ ipv6.ip6_nxt,
+ "Next header: %s (0x%02x)",
+ ipprotostr(ipv6.ip6_nxt), ipv6.ip6_nxt);
+
+ proto_tree_add_uint(ipv6_tree, hf_ipv6_hlim, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_hlim), 1,
+ ipv6.ip6_hlim);
+
+ proto_tree_add_ipv6_hidden(ipv6_tree, hf_ipv6_addr, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_src), 16,
+ ipv6.ip6_src.s6_addr8);
+ proto_tree_add_ipv6_hidden(ipv6_tree, hf_ipv6_addr, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_dst), 16,
+ ipv6.ip6_dst.s6_addr8);
+
+ proto_tree_add_ipv6_format(ipv6_tree, hf_ipv6_src, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_src), 16,
+ (guint8 *)&ipv6.ip6_src,
+#ifdef INET6
+ "Source address: %s (%s)",
+ get_hostname6(&ipv6.ip6_src),
+#else
+ "Source address: %s",
+#endif
+ ip6_to_str(&ipv6.ip6_src));
+
+ proto_tree_add_ipv6_format(ipv6_tree, hf_ipv6_dst, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_dst), 16,
+ (guint8 *)&ipv6.ip6_dst,
+#ifdef INET6
+ "Destination address: %s (%s)",
+ get_hostname6(&ipv6.ip6_dst),
+#else
+ "Destination address: %s",
+#endif
+ ip6_to_str(&ipv6.ip6_dst));
+ }
+
+ /* start of the new header (could be a extension header) */
+ poffset = offset + offsetof(struct ip6_hdr, ip6_nxt);
+ nxt = tvb_get_guint8(tvb, poffset);
+ offset += sizeof(struct ip6_hdr);
+ offlg = 0;
+ ident = 0;
+
+/* start out assuming this isn't fragmented, and has none of the other
+ non-final headers */
+ hopopts = FALSE;
+ routing = FALSE;
+ frag = FALSE;
+ ah = FALSE;
+ dstopts = FALSE;
+
+again:
+ switch (nxt) {
+ case IP_PROTO_HOPOPTS:
+ hopopts = TRUE;
+ advance = dissect_hopopts(tvb, offset, tree);
+ nxt = tvb_get_guint8(tvb, offset);
+ poffset = offset;
+ offset += advance;
+ plen -= advance;
+ goto again;
+ case IP_PROTO_ROUTING:
+ routing = TRUE;
+ advance = dissect_routing6(tvb, offset, tree);
+ nxt = tvb_get_guint8(tvb, offset);
+ poffset = offset;
+ offset += advance;
+ plen -= advance;
+ goto again;
+ case IP_PROTO_FRAGMENT:
+ frag = TRUE;
+ advance = dissect_frag6(tvb, offset, pinfo, tree,
+ &offlg, &ident);
+ nxt = tvb_get_guint8(tvb, offset);
+ poffset = offset;
+ offset += advance;
+ plen -= advance;
+ goto again;
+ case IP_PROTO_AH:
+ ah = TRUE;
+ advance = dissect_ah_header(
+ tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, tree, NULL, NULL);
+ nxt = tvb_get_guint8(tvb, offset);
+ poffset = offset;
+ offset += advance;
+ plen -= advance;
+ goto again;
+ case IP_PROTO_DSTOPTS:
+ dstopts = TRUE;
+ advance = dissect_dstopts(tvb, offset, tree);
+ nxt = tvb_get_guint8(tvb, offset);
+ poffset = offset;
+ offset += advance;
+ plen -= advance;
+ goto again;
+ }
+
+#ifdef TEST_FINALHDR
+ proto_tree_add_uint_hidden(ipv6_tree, hf_ipv6_final, tvb, poffset, 1, nxt);
+#endif
+
+ /* If ipv6_reassemble is on, this is a fragment, and we have all the data
+ * in the fragment, then just add the fragment to the hashtable.
+ */
+ save_fragmented = pinfo->fragmented;
+ if (ipv6_reassemble && frag && tvb_bytes_exist(tvb, offset, plen)) {
+ ipfd_head = fragment_add_check(tvb, offset, pinfo, ident,
+ ipv6_fragment_table,
+ ipv6_reassembled_table,
+ offlg & IP6F_OFF_MASK,
+ plen,
+ offlg & IP6F_MORE_FRAG);
+
+ next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled IPv6",
+ ipfd_head, &ipv6_frag_items, &update_col_info, ipv6_tree);
+ } else {
+ /* If this is the first fragment, dissect its contents, otherwise
+ just show it as a fragment.
+
+ XXX - if we eventually don't save the reassembled contents of all
+ fragmented datagrams, we may want to always reassemble. */
+ if (offlg & IP6F_OFF_MASK) {
+ /* Not the first fragment - don't dissect it. */
+ next_tvb = NULL;
+ } else {
+ /* First fragment, or not fragmented. Dissect what we have here. */
+
+ /* Get a tvbuff for the payload. */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ /*
+ * If this is the first fragment, but not the only fragment,
+ * tell the next protocol that.
+ */
+ if (offlg & IP6F_MORE_FRAG)
+ pinfo->fragmented = TRUE;
+ else
+ pinfo->fragmented = FALSE;
+ }
+ }
+
+ if (next_tvb == NULL) {
+ /* Just show this as a fragment. */
+ /* COL_INFO was filled in by "dissect_frag6()" */
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+
+ /* As we haven't reassembled anything, we haven't changed "pi", so
+ we don't have to restore it. */
+ pinfo->fragmented = save_fragmented;
+ return;
+ }
+
+ /* do lookup with the subdissector table */
+ if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, tree)) {
+ /* Unknown protocol.
+ Handle "no next header" specially. */
+ if (nxt == IP_PROTO_NONE) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /* If we had an Authentication Header, the AH dissector already
+ put something in the Info column; leave it there. */
+ if (!ah) {
+ if (hopopts || routing || dstopts) {
+ char *sep = "IPv6 ";
+ if (hopopts) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%shop-by-hop options",
+ sep);
+ sep = ", ";
+ }
+ if (routing) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%srouting", sep);
+ sep = ", ";
+ }
+ if (dstopts) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%sdestination options",
+ sep);
+ }
+ } else
+ col_set_str(pinfo->cinfo, COL_INFO, "IPv6 no next header");
+ }
+ }
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)", ipprotostr(nxt),nxt);
+ }
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ pinfo->fragmented = save_fragmented;
+}
+
+void
+proto_register_ipv6(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ipv6_version,
+ { "Version", "ipv6.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_ipv6_class,
+ { "Traffic class", "ipv6.class",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ipv6_flow,
+ { "Flowlabel", "ipv6.flow",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ipv6_plen,
+ { "Payload length", "ipv6.plen",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_ipv6_nxt,
+ { "Next header", "ipv6.nxt",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ipv6_hlim,
+ { "Hop limit", "ipv6.hlim",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_ipv6_src,
+ { "Source", "ipv6.src",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Source IPv6 Address", HFILL }},
+ { &hf_ipv6_dst,
+ { "Destination", "ipv6.dst",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Destination IPv6 Address", HFILL }},
+ { &hf_ipv6_addr,
+ { "Address", "ipv6.addr",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Source or Destination IPv6 Address", HFILL }},
+
+ { &hf_ipv6_fragment_overlap,
+ { "Fragment overlap", "ipv6.fragment.overlap",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_ipv6_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "ipv6.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_ipv6_fragment_multiple_tails,
+ { "Multiple tail fragments found", "ipv6.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_ipv6_fragment_too_long_fragment,
+ { "Fragment too long", "ipv6.fragment.toolongfragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+
+ { &hf_ipv6_fragment_error,
+ { "Defragmentation error", "ipv6.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }},
+
+ { &hf_ipv6_fragment,
+ { "IPv6 Fragment", "ipv6.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "IPv6 Fragment", HFILL }},
+
+ { &hf_ipv6_fragments,
+ { "IPv6 Fragments", "ipv6.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "IPv6 Fragments", HFILL }},
+
+ { &hf_ipv6_reassembled_in,
+ { "Reassembled IPv6 in frame", "ipv6.reassembled_in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This IPv6 packet is reassembled in this frame", HFILL }},
+
+ /* Mobile IPv6 */
+ { &hf_ipv6_mipv6_type,
+ { "Option Type ", "ipv6.mipv6_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ipv6_mipv6_length,
+ { "Option Length ", "ipv6.mipv6_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ipv6_mipv6_home_address,
+ { "Home Address ", "ipv6.mipv6_home_address",
+ FT_IPv6, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+#ifdef TEST_FINALHDR
+ { &hf_ipv6_final,
+ { "Final next header", "ipv6.final",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+#endif
+ };
+ static gint *ett[] = {
+ &ett_ipv6,
+ &ett_ipv6_fragments,
+ &ett_ipv6_fragment,
+ };
+ module_t *ipv6_module;
+
+ proto_ipv6 = proto_register_protocol("Internet Protocol Version 6", "IPv6", "ipv6");
+ proto_register_field_array(proto_ipv6, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register configuration options */
+ ipv6_module = prefs_register_protocol(proto_ipv6, NULL);
+ prefs_register_bool_preference(ipv6_module, "defragment",
+ "Reassemble fragmented IPv6 datagrams",
+ "Whether fragmented IPv6 datagrams should be reassembled",
+ &ipv6_reassemble);
+
+ register_dissector("ipv6", dissect_ipv6, proto_ipv6);
+ register_init_routine(ipv6_reassemble_init);
+}
+
+void
+proto_reg_handoff_ipv6(void)
+{
+ dissector_handle_t ipv6_handle;
+
+ data_handle = find_dissector("data");
+ ipv6_handle = find_dissector("ipv6");
+ dissector_add("ethertype", ETHERTYPE_IPv6, ipv6_handle);
+ dissector_add("ppp.protocol", PPP_IPV6, ipv6_handle);
+ dissector_add("ppp.protocol", ETHERTYPE_IPv6, ipv6_handle);
+ dissector_add("gre.proto", ETHERTYPE_IPv6, ipv6_handle);
+ dissector_add("ip.proto", IP_PROTO_IPV6, ipv6_handle);
+ dissector_add("null.type", BSD_AF_INET6_BSD, ipv6_handle);
+ dissector_add("null.type", BSD_AF_INET6_FREEBSD, ipv6_handle);
+ dissector_add("null.type", BSD_AF_INET6_DARWIN, ipv6_handle);
+ dissector_add("chdlctype", ETHERTYPE_IPv6, ipv6_handle);
+ dissector_add("fr.ietf", NLPID_IP6, ipv6_handle);
+ dissector_add("x.25.spi", NLPID_IP6, ipv6_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_IPv6, ipv6_handle);
+
+ ip_dissector_table = find_dissector_table("ip.proto");
+}
diff --git a/epan/dissectors/packet-ipv6.h b/epan/dissectors/packet-ipv6.h
new file mode 100644
index 0000000000..693e8f6543
--- /dev/null
+++ b/epan/dissectors/packet-ipv6.h
@@ -0,0 +1,540 @@
+/* packet-ipv6.h
+ * Definitions for IPv6 packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ *
+ * Copyright 1998 Gerald Combs
+ *
+ * MobileIPv6 support added by Tomislav Borosa <tomislav.borosa@siemens.hr>
+ *
+ * HMIPv6 support added by Martti Kuparinen <martti.kuparinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_IPV6_H_DEFINED__
+#define __PACKET_IPV6_H_DEFINED__
+
+#include <epan/ipv6-utils.h>
+
+#define INET6_ADDRSTRLEN 46
+
+/*
+ * Definition for internet protocol version 6.
+ * RFC 1883
+ */
+struct ip6_hdr {
+ union {
+ struct ip6_hdrctl {
+ guint32 ip6_un1_flow; /* 20 bits of flow-ID */
+ guint16 ip6_un1_plen; /* payload length */
+ guint8 ip6_un1_nxt; /* next header */
+ guint8 ip6_un1_hlim; /* hop limit */
+ } ip6_un1;
+ guint8 ip6_un2_vfc; /* 4 bits version, 4 bits class */
+ } ip6_ctlun;
+ struct e_in6_addr ip6_src; /* source address */
+ struct e_in6_addr ip6_dst; /* destination address */
+};
+
+#define ip6_vfc ip6_ctlun.ip6_un2_vfc
+#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+/* Offsets of fields within an IPv6 header. */
+#define IP6H_CTL 0
+#define IP6H_CTL_FLOW 0
+#define IP6H_CTL_PLEN 4
+#define IP6H_CTL_NXT 6
+#define IP6H_CTL_HLIM 7
+#define IP6H_CTL_VFC 0
+#define IP6H_SRC 8
+#define IP6H_DST 24
+
+#define IPV6_FLOWINFO_MASK 0x0fffffff /* flow info (28 bits) */
+#define IPV6_FLOWLABEL_MASK 0x000fffff /* flow label (20 bits) */
+
+/*
+ * Extension Headers
+ */
+
+struct ip6_ext {
+ guchar ip6e_nxt;
+ guchar ip6e_len;
+};
+
+/* Hop-by-Hop options header */
+/* XXX should we pad it to force alignment on an 8-byte boundary? */
+struct ip6_hbh {
+ guint8 ip6h_nxt; /* next header */
+ guint8 ip6h_len; /* length in units of 8 octets */
+ /* followed by options */
+};
+
+/* Destination options header */
+/* XXX should we pad it to force alignment on an 8-byte boundary? */
+struct ip6_dest {
+ guint8 ip6d_nxt; /* next header */
+ guint8 ip6d_len; /* length in units of 8 octets */
+ /* followed by options */
+};
+
+/* Option types and related macros */
+#define IP6OPT_PAD1 0x00 /* 00 0 00000 */
+#define IP6OPT_PADN 0x01 /* 00 0 00001 */
+#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */
+#define IP6OPT_JUMBO_LEN 6
+#define IP6OPT_RTALERT 0x05 /* 00 0 00101 */
+
+#define IP6OPT_RTALERT_LEN 4
+#define IP6OPT_RTALERT_MLD 0 /* Datagram contains MLD message */
+#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains RSVP message */
+#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */
+#define IP6OPT_MINLEN 2
+
+#define IP6OPT_HOME_ADDRESS 0xC9 /* 11 0 01001 */
+
+#define IP6OPT_TYPE(o) ((o) & 0xC0)
+#define IP6OPT_TYPE_SKIP 0x00
+#define IP6OPT_TYPE_DISCARD 0x40
+#define IP6OPT_TYPE_FORCEICMP 0x80
+#define IP6OPT_TYPE_ICMP 0xC0
+
+#define IP6OPT_MUTABLE 0x20
+
+/* Routing header */
+struct ip6_rthdr {
+ guint8 ip6r_nxt; /* next header */
+ guint8 ip6r_len; /* length in units of 8 octets */
+ guint8 ip6r_type; /* routing type */
+ guint8 ip6r_segleft; /* segments left */
+ /* followed by routing type specific data */
+};
+
+/* Type 0 Routing header */
+struct ip6_rthdr0 {
+ guint8 ip6r0_nxt; /* next header */
+ guint8 ip6r0_len; /* length in units of 8 octets */
+ guint8 ip6r0_type; /* always zero */
+ guint8 ip6r0_segleft; /* segments left */
+ guint8 ip6r0_reserved; /* reserved field */
+ guint8 ip6r0_slmap[3]; /* strict/loose bit map */
+ struct e_in6_addr ip6r0_addr[1]; /* up to 23 addresses */
+};
+
+/* Fragment header */
+struct ip6_frag {
+ guint8 ip6f_nxt; /* next header */
+ guint8 ip6f_reserved; /* reserved field */
+ guint16 ip6f_offlg; /* offset, reserved, and flag */
+ guint32 ip6f_ident; /* identification */
+};
+
+#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */
+
+/*
+ * Definition for ICMPv6.
+ * RFC 1885
+ */
+
+#define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr)
+ - sizeof(struct icmp6_hdr) */
+
+struct icmp6_hdr {
+ guint8 icmp6_type; /* type field */
+ guint8 icmp6_code; /* code field */
+ guint16 icmp6_cksum; /* checksum field */
+ union {
+ guint32 icmp6_un_data32[1]; /* type-specific field */
+ guint16 icmp6_un_data16[2]; /* type-specific field */
+ guint8 icmp6_un_data8[4]; /* type-specific field */
+ } icmp6_dataun;
+};
+
+#define icmp6_data32 icmp6_dataun.icmp6_un_data32
+#define icmp6_data16 icmp6_dataun.icmp6_un_data16
+#define icmp6_data8 icmp6_dataun.icmp6_un_data8
+#define icmp6_pptr icmp6_data32[0] /* parameter prob */
+#define icmp6_mtu icmp6_data32[0] /* packet too big */
+#define icmp6_id icmp6_data16[0] /* echo request/reply */
+#define icmp6_seq icmp6_data16[1] /* echo request/reply */
+#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
+
+#define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */
+#define ICMP6_PACKET_TOO_BIG 2 /* packet too big */
+#define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */
+#define ICMP6_PARAM_PROB 4 /* ip6 header bad */
+
+#define ICMP6_ECHO_REQUEST 128 /* echo service */
+#define ICMP6_ECHO_REPLY 129 /* echo reply */
+#define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */
+#define MLD6_LISTENER_QUERY 130 /* multicast listener query */
+#define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */
+#define MLD6_LISTENER_REPORT 131 /* multicast listener report */
+#define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */
+#define MLD6_LISTENER_DONE 132 /* multicast listener done */
+
+#define ND_ROUTER_SOLICIT 133 /* router solicitation */
+#define ND_ROUTER_ADVERT 134 /* router advertisment */
+#define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */
+#define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisment */
+#define ND_REDIRECT 137 /* redirect */
+
+#define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */
+
+#define ICMP6_WRUREQUEST 139 /* who are you request */
+#define ICMP6_WRUREPLY 140 /* who are you reply */
+#define ICMP6_FQDN_QUERY 139 /* FQDN query */
+#define ICMP6_FQDN_REPLY 140 /* FQDN reply */
+#define ICMP6_NI_QUERY 139 /* node information request */
+#define ICMP6_NI_REPLY 140 /* node information reply */
+#define ICMP6_IND_SOLICIT 141 /* Inverse ND Solicitation */
+#define ICMP6_IND_ADVERT 142 /* Inverse ND advertisement */
+#define ICMP6_MLDV2_REPORT 143 /* MLD v2 report message : draft-vida-mld-v2-08.txt */
+
+#define ICMP6_MIP6_DHAAD_REQUEST 144 /* Mobile IPv6 DHAAD */
+#define ICMP6_MIP6_DHAAD_REPLY 145 /* Mobile IPv6 DHAAD */
+#define ICMP6_MIP6_MPS 146 /* Mobile IPv6 MPS */
+#define ICMP6_MIP6_MPA 147 /* Mobile IPv6 MPA */
+
+#define ICMP6_MAXTYPE 153
+
+#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
+#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */
+#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */
+#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
+#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
+#define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */
+
+#define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */
+#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */
+
+#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
+#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */
+#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */
+
+#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
+
+#define ICMP6_NI_SUBJ_IPV6 0 /* Query Subject is an IPv6 address */
+#define ICMP6_NI_SUBJ_FQDN 1 /* Query Subject is a Domain name */
+#define ICMP6_NI_SUBJ_IPV4 2 /* Query Subject is an IPv4 address */
+
+#define ICMP6_NI_SUCCESS 0 /* node information successful reply */
+#define ICMP6_NI_REFUSED 1 /* node information request is refused */
+#define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */
+
+#define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */
+#define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */
+#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */
+
+/*
+ * Multicast Listener Discovery
+ */
+struct mld6_hdr {
+ struct icmp6_hdr mld6_hdr;
+ struct e_in6_addr mld6_addr; /* multicast address */
+};
+
+#define mld6_type mld6_hdr.icmp6_type
+#define mld6_code mld6_hdr.icmp6_code
+#define mld6_cksum mld6_hdr.icmp6_cksum
+#define mld6_maxdelay mld6_hdr.icmp6_data16[0]
+#define mld6_reserved mld6_hdr.icmp6_data16[1]
+
+/*
+ * Neighbor Discovery
+ */
+
+struct nd_router_solicit { /* router solicitation */
+ struct icmp6_hdr nd_rs_hdr;
+ /* could be followed by options */
+};
+
+#define nd_rs_type nd_rs_hdr.icmp6_type
+#define nd_rs_code nd_rs_hdr.icmp6_code
+#define nd_rs_cksum nd_rs_hdr.icmp6_cksum
+#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
+
+struct nd_router_advert { /* router advertisement */
+ struct icmp6_hdr nd_ra_hdr;
+ guint32 nd_ra_reachable; /* reachable time */
+ guint32 nd_ra_retransmit; /* retransmit timer */
+ /* could be followed by options */
+};
+
+#define nd_ra_type nd_ra_hdr.icmp6_type
+#define nd_ra_code nd_ra_hdr.icmp6_code
+#define nd_ra_cksum nd_ra_hdr.icmp6_cksum
+#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
+#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
+#define ND_RA_FLAG_MANAGED 0x80
+#define ND_RA_FLAG_OTHER 0x40
+#define ND_RA_FLAG_HOME_AGENT 0x20
+
+/*
+ * Router preference values based on draft-draves-ipngwg-router-selection-01.
+ * These are non-standard definitions.
+ */
+#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
+
+#define ND_RA_FLAG_RTPREF_HIGH 0x08 /* 00001000 */
+#define ND_RA_FLAG_RTPREF_MEDIUM 0x00 /* 00000000 */
+#define ND_RA_FLAG_RTPREF_LOW 0x18 /* 00011000 */
+#define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */
+
+#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
+
+struct nd_neighbor_solicit { /* neighbor solicitation */
+ struct icmp6_hdr nd_ns_hdr;
+ struct e_in6_addr nd_ns_target; /*target address */
+ /* could be followed by options */
+};
+
+#define nd_ns_type nd_ns_hdr.icmp6_type
+#define nd_ns_code nd_ns_hdr.icmp6_code
+#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
+#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
+
+struct nd_neighbor_advert { /* neighbor advertisement */
+ struct icmp6_hdr nd_na_hdr;
+ struct e_in6_addr nd_na_target; /* target address */
+ /* could be followed by options */
+};
+
+#define nd_na_type nd_na_hdr.icmp6_type
+#define nd_na_code nd_na_hdr.icmp6_code
+#define nd_na_cksum nd_na_hdr.icmp6_cksum
+#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
+#define ND_NA_FLAG_ROUTER 0x80000000
+#define ND_NA_FLAG_SOLICITED 0x40000000
+#define ND_NA_FLAG_OVERRIDE 0x20000000
+
+struct nd_redirect { /* redirect */
+ struct icmp6_hdr nd_rd_hdr;
+ struct e_in6_addr nd_rd_target; /* target address */
+ struct e_in6_addr nd_rd_dst; /* destination address */
+ /* could be followed by options */
+};
+
+#define nd_rd_type nd_rd_hdr.icmp6_type
+#define nd_rd_code nd_rd_hdr.icmp6_code
+#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
+
+struct nd_opt_hdr { /* Neighbor discovery option header */
+ guint8 nd_opt_type;
+ guint8 nd_opt_len;
+ /* followed by option specific data*/
+};
+
+#define ND_OPT_SOURCE_LINKADDR 1
+#define ND_OPT_TARGET_LINKADDR 2
+#define ND_OPT_PREFIX_INFORMATION 3
+#define ND_OPT_REDIRECTED_HEADER 4
+#define ND_OPT_MTU 5
+#define ND_OPT_ADVINTERVAL 7
+#define ND_OPT_HOMEAGENT_INFO 8
+#define ND_OPT_SOURCE_ADDRLIST 9
+#define ND_OPT_TARGET_ADDRLIST 10
+
+/* draft-ietf-ipngwg-router-preference, not officially assigned yet */
+#define ND_OPT_ROUTE_INFO 200
+/* draft-ietf-mobileip-hmipv6, not officially assigned yet */
+#define ND_OPT_MAP 201
+
+struct nd_opt_prefix_info { /* prefix information */
+ guint8 nd_opt_pi_type;
+ guint8 nd_opt_pi_len;
+ guint8 nd_opt_pi_prefix_len;
+ guint8 nd_opt_pi_flags_reserved;
+ guint32 nd_opt_pi_valid_time;
+ guint32 nd_opt_pi_preferred_time;
+ guint32 nd_opt_pi_reserved2;
+ struct e_in6_addr nd_opt_pi_prefix;
+};
+
+#define ND_OPT_PI_FLAG_ONLINK 0x80
+#define ND_OPT_PI_FLAG_AUTO 0x40
+#define ND_OPT_PI_FLAG_ROUTER 0x20
+#define ND_OPT_PI_FLAG_SITEPREF 0x10
+
+struct nd_opt_rd_hdr { /* redirected header */
+ guint8 nd_opt_rh_type;
+ guint8 nd_opt_rh_len;
+ guint16 nd_opt_rh_reserved1;
+ guint32 nd_opt_rh_reserved2;
+ /* followed by IP header and data */
+};
+
+struct nd_opt_mtu { /* MTU option */
+ guint8 nd_opt_mtu_type;
+ guint8 nd_opt_mtu_len;
+ guint16 nd_opt_mtu_reserved;
+ guint32 nd_opt_mtu_mtu;
+};
+
+struct nd_opt_adv_int { /* Advertisement Interval option */
+ guint8 nd_opt_adv_int_type;
+ guint8 nd_opt_adv_int_len;
+ guint16 nd_opt_adv_int_reserved;
+ guint32 nd_opt_adv_int_advint;
+};
+
+struct nd_opt_ha_info { /* Home Agent Information option */
+ guint8 nd_opt_ha_info_type;
+ guint8 nd_opt_ha_info_len;
+ guint16 nd_opt_ha_info_reserved;
+ guint16 nd_opt_ha_info_ha_pref;
+ guint16 nd_opt_ha_info_ha_life;
+};
+
+struct nd_opt_route_info { /* route info */
+ guint8 nd_opt_rti_type;
+ guint8 nd_opt_rti_len;
+ guint8 nd_opt_rti_prefixlen;
+ guint8 nd_opt_rti_flags;
+ guint32 nd_opt_rti_lifetime;
+ /* prefix follows */
+};
+
+struct nd_opt_map_info { /* HMIPv6 MAP option */
+ guint8 nd_opt_map_type;
+ guint8 nd_opt_map_len;
+ guint8 nd_opt_map_dist_and_pref;
+ guint8 nd_opt_map_flags;
+ guint32 nd_opt_map_lifetime;
+ struct e_in6_addr nd_opt_map_address;
+};
+
+#define ND_OPT_MAP_FLAG_R 0x80
+#define ND_OPT_MAP_FLAG_M 0x40
+#define ND_OPT_MAP_FLAG_I 0x20
+#define ND_OPT_MAP_FLAG_T 0x10
+#define ND_OPT_MAP_FLAG_P 0x08
+#define ND_OPT_MAP_FLAG_V 0x04
+
+/*
+ * icmp6 node information
+ */
+struct icmp6_nodeinfo {
+ struct icmp6_hdr icmp6_ni_hdr;
+ guint8 icmp6_ni_nonce[8];
+ /* could be followed by reply data */
+};
+
+#define ni_type icmp6_ni_hdr.icmp6_type
+#define ni_code icmp6_ni_hdr.icmp6_code
+#define ni_cksum icmp6_ni_hdr.icmp6_cksum
+#define ni_qtype icmp6_ni_hdr.icmp6_data16[0]
+#define ni_flags icmp6_ni_hdr.icmp6_data16[1]
+
+#define NI_QTYPE_NOOP 0 /* NOOP */
+#define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */
+#define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */
+#define NI_QTYPE_DNSNAME 2 /* DNS Name */
+#define NI_QTYPE_NODEADDR 3 /* Node Addresses */
+#define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */
+
+#define NI_SUPTYPE_FLAG_COMPRESS 0x1
+#define NI_FQDN_FLAG_VALIDTTL 0x1
+
+#define NI_NODEADDR_FLAG_TRUNCATE 0x1
+#define NI_NODEADDR_FLAG_ALL 0x2
+#define NI_NODEADDR_FLAG_COMPAT 0x4
+#define NI_NODEADDR_FLAG_LINKLOCAL 0x8
+#define NI_NODEADDR_FLAG_SITELOCAL 0x10
+#define NI_NODEADDR_FLAG_GLOBAL 0x20
+#define NI_NODEADDR_FLAG_ANYCAST 0x40 /* just experimental. not in spec */
+
+struct ni_reply_fqdn {
+ guint32 ni_fqdn_ttl; /* TTL */
+ guint8 ni_fqdn_namelen; /* length in octets of the FQDN */
+ guint8 ni_fqdn_name[3]; /* XXX: alignment */
+};
+
+/*
+ * Router Renumbering. as router-renum-05.txt
+ */
+struct icmp6_router_renum { /* router renumbering header */
+ struct icmp6_hdr rr_hdr;
+ guint8 rr_segnum;
+ guint8 rr_flags;
+ guint16 rr_maxdelay;
+ guint32 rr_reserved;
+};
+
+#define rr_type rr_hdr.icmp6_type
+#define rr_code rr_hdr.icmp6_code
+#define rr_cksum rr_hdr.icmp6_cksum
+#define rr_seqnum rr_hdr.icmp6_data32[0]
+
+struct rr_pco_match { /* match prefix part */
+ guint8 rpm_code;
+ guint8 rpm_len;
+ guint8 rpm_ordinal;
+ guint8 rpm_matchlen;
+ guint8 rpm_minlen;
+ guint8 rpm_maxlen;
+ guint16 rpm_reserved;
+ struct e_in6_addr rpm_prefix;
+};
+
+#define RPM_PCO_ADD 1
+#define RPM_PCO_CHANGE 2
+#define RPM_PCO_SETGLOBAL 3
+#define RPM_PCO_MAX 4
+
+struct rr_pco_use { /* use prefix part */
+ guint8 rpu_uselen;
+ guint8 rpu_keeplen;
+ guint8 rpu_ramask;
+ guint8 rpu_raflags;
+ guint32 rpu_vltime;
+ guint32 rpu_pltime;
+ guint32 rpu_flags;
+ struct e_in6_addr rpu_prefix;
+};
+
+#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80
+#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x40
+
+/* network endian */
+#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000
+#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000
+
+struct rr_result { /* router renumbering result message */
+ guint16 rrr_flags;
+ guint8 rrr_ordinal;
+ guint8 rrr_matchedlen;
+ guint32 rrr_ifid;
+ struct e_in6_addr rrr_prefix;
+};
+
+/* network endian */
+#define ICMP6_RR_RESULT_FLAGS_OOB 0x0002
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001
+
+void capture_ipv6(const guchar *, int, int, packet_counts *);
+
+
+#endif /* __PACKET_IPV6_H_DEFINED__ */
diff --git a/epan/dissectors/packet-ipvs-syncd.c b/epan/dissectors/packet-ipvs-syncd.c
new file mode 100644
index 0000000000..928dcba807
--- /dev/null
+++ b/epan/dissectors/packet-ipvs-syncd.c
@@ -0,0 +1,353 @@
+/* packet-ipvs-syncd.c 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Routines for IGMP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "ipproto.h"
+#include "in_cksum.h"
+
+static int proto_ipvs_syncd = -1;
+static int hf_conn_count = -1;
+static int hf_syncid = -1;
+static int hf_size = -1;
+static int hf_resv8 = -1;
+static int hf_proto = -1;
+static int hf_cport = -1;
+static int hf_vport = -1;
+static int hf_dport = -1;
+static int hf_caddr = -1;
+static int hf_vaddr = -1;
+static int hf_daddr = -1;
+static int hf_flags = -1;
+static int hf_state = -1;
+static int hf_in_seq_init = -1;
+static int hf_in_seq_delta = -1;
+static int hf_in_seq_pdelta = -1;
+static int hf_out_seq_init = -1;
+static int hf_out_seq_delta = -1;
+static int hf_out_seq_pdelta = -1;
+
+static int ett_ipvs_syncd = -1;
+static int ett_conn = -1;
+static int ett_flags = -1;
+
+#define IPVS_SYNCD_MC_GROUP "224.0.0.18"
+#define IPVS_SYNCD_PORT 8848
+
+static const value_string proto_strings[] = {
+ {0x06, "UDP"},
+ {0x11, "TCP"},
+ {0x00, NULL},
+};
+
+static const value_string state_strings[] = {
+ {0x00, "Input"},
+ {0x04, "Output"},
+ {0x08, "Input Only"},
+ {0x00, NULL},
+};
+
+/*
+ * IPVS Connection Flags
+ * Pulled from include/net/ip_vs.h in linux kernel source
+ */
+#define IP_VS_CONN_F_FWD_MASK 0x0007 /* mask for the fwd methods */
+#define IP_VS_CONN_F_MASQ 0x0000 /* masquerading */
+#define IP_VS_CONN_F_LOCALNODE 0x0001 /* local node */
+#define IP_VS_CONN_F_TUNNEL 0x0002 /* tunneling */
+#define IP_VS_CONN_F_DROUTE 0x0003 /* direct routing */
+#define IP_VS_CONN_F_BYPASS 0x0004 /* cache bypass */
+#define IP_VS_CONN_F_HASHED 0x0040 /* hashed entry */
+#define IP_VS_CONN_F_NOOUTPUT 0x0080 /* no output packets */
+#define IP_VS_CONN_F_INACTIVE 0x0100 /* not established */
+#define IP_VS_CONN_F_OUT_SEQ 0x0200 /* must do output seq adjust */
+#define IP_VS_CONN_F_IN_SEQ 0x0400 /* must do input seq adjust */
+#define IP_VS_CONN_F_SEQ_MASK 0x0600 /* in/out sequence mask */
+#define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */
+
+
+static void
+dissect_ipvs_syncd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ proto_tree *tree;
+ proto_item *item;
+ int offset = 0;
+ guint8 cnt = 0;
+ int conn = 0;
+
+ item = proto_tree_add_item(parent_tree, proto_ipvs_syncd, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_ipvs_syncd);
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPVS");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ cnt = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_conn_count, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_syncid, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_size, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ for (conn = 0; conn < cnt; conn++)
+ {
+ proto_tree *ctree, *ti;
+ proto_tree *ftree, *fi;
+ guint16 flags;
+
+ ti = proto_tree_add_text(tree, tvb, offset, 24, "Connection #%d", conn+1);
+ ctree = proto_item_add_subtree(ti, ett_conn);
+
+ proto_tree_add_item(ctree, hf_resv8, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(ctree, hf_proto, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(ctree, hf_cport, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(ctree, hf_vport, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(ctree, hf_dport, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(ctree, hf_caddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ctree, hf_vaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ctree, hf_daddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ flags = tvb_get_ntohs(tvb, offset);
+ fi = proto_tree_add_item(ctree, hf_flags, tvb, offset, 2, FALSE);
+ ftree = proto_item_add_subtree(fi, ett_flags);
+
+ if ( (flags & 0x0F) == IP_VS_CONN_F_MASQ )
+ {
+ proto_tree_add_text(ftree, tvb, offset+1, 1, "Connection Type: Masquerade");
+ }
+ else if ( (flags & 0x0F) == IP_VS_CONN_F_LOCALNODE )
+ {
+ proto_tree_add_text(ftree, tvb, offset+1, 1, "Connection Type: Local Node");
+ }
+ else if ( (flags & 0x0F) == IP_VS_CONN_F_TUNNEL )
+ {
+ proto_tree_add_text(ftree, tvb, offset+1, 1, "Connection Type: Tunnel");
+ }
+ else if ( (flags & 0x0F) == IP_VS_CONN_F_DROUTE )
+ {
+ proto_tree_add_text(ftree, tvb, offset+1, 1, "Connection Type: Direct Routing");
+ }
+ else
+ {
+ proto_tree_add_text(ftree, tvb, offset+1, 1, "Connection Type: Unknown (%d)",
+ flags & IP_VS_CONN_F_FWD_MASK);
+ }
+
+ if ( flags & IP_VS_CONN_F_HASHED )
+ {
+ proto_tree_add_text(ftree, tvb, offset+1, 1, "Hashed Entry");
+ }
+
+ if ( flags & IP_VS_CONN_F_NOOUTPUT )
+ {
+ proto_tree_add_text(ftree, tvb, offset+1, 1, "No Output Packets");
+ }
+
+ if ( flags & IP_VS_CONN_F_INACTIVE )
+ {
+ proto_tree_add_text(ftree, tvb, offset, 1, "Connection Not Established");
+ }
+
+ if ( flags & IP_VS_CONN_F_OUT_SEQ )
+ {
+ proto_tree_add_text(ftree, tvb, offset, 1, "Adjust Output Sequence");
+ }
+
+ if ( flags & IP_VS_CONN_F_IN_SEQ )
+ {
+ proto_tree_add_text(ftree, tvb, offset, 1, "Adjust Input Sequence");
+ }
+
+ if ( flags & IP_VS_CONN_F_NO_CPORT )
+ {
+ proto_tree_add_text(ftree, tvb, offset, 1, "No Client Port Set");
+ }
+
+ offset += 2;
+
+ proto_tree_add_item(ctree, hf_state, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* we have full connection info */
+ if ( flags & IP_VS_CONN_F_SEQ_MASK )
+ {
+ proto_tree_add_item(ctree, hf_in_seq_init, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ctree, hf_in_seq_delta, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ctree, hf_in_seq_pdelta, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ctree, hf_out_seq_init, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ctree, hf_out_seq_delta, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ctree, hf_out_seq_pdelta, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+
+ }
+}
+
+void
+proto_register_ipvs_syncd(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_conn_count,
+ { "Connection Count", "ipvs.conncount", FT_UINT8, BASE_DEC,
+ NULL, 0, "Connection Count", HFILL }},
+
+ { &hf_syncid,
+ { "Synchronization ID", "ipvs.syncid", FT_UINT8, BASE_DEC,
+ NULL, 0, "Syncronization ID", HFILL }},
+
+ { &hf_size,
+ { "Size", "ipvs.size", FT_UINT16, BASE_DEC,
+ NULL, 0, "Size", HFILL }},
+
+ { &hf_resv8,
+ { "Reserved", "ipvs.resv8", FT_UINT8, BASE_HEX,
+ NULL, 0, "Reserved", HFILL }},
+
+ { &hf_proto,
+ { "Protocol", "ipvs.proto", FT_UINT8, BASE_HEX,
+ VALS(&proto_strings), 0, "Protocol", HFILL }},
+
+ { &hf_cport,
+ { "Client Port", "ipvs.cport", FT_UINT16, BASE_DEC,
+ NULL, 0, "Client Port", HFILL }},
+
+ { &hf_vport,
+ { "Virtual Port", "ipvs.vport", FT_UINT16, BASE_DEC,
+ NULL, 0, "Virtual Port", HFILL }},
+
+ { &hf_dport,
+ { "Destination Port", "ipvs.dport", FT_UINT16, BASE_DEC,
+ NULL, 0, "Destination Port", HFILL }},
+
+ { &hf_caddr,
+ { "Client Address", "ipvs.caddr", FT_IPv4, BASE_HEX,
+ NULL, 0, "Client Address", HFILL }},
+
+ { &hf_vaddr,
+ { "Virtual Address", "ipvs.vaddr", FT_IPv4, BASE_HEX,
+ NULL, 0, "Virtual Address", HFILL }},
+
+ { &hf_daddr,
+ { "Destination Address", "ipvs.daddr", FT_IPv4, BASE_HEX,
+ NULL, 0, "Destination Address", HFILL }},
+
+ { &hf_flags,
+ { "Flags", "ipvs.flags", FT_UINT16, BASE_HEX,
+ NULL, 0, "Flags", HFILL }},
+
+ { &hf_state,
+ { "State", "ipvs.state", FT_UINT16, BASE_HEX,
+ VALS(&state_strings), 0, "State", HFILL }},
+
+ { &hf_in_seq_init,
+ { "Input Sequence (Initial)", "ipvs.in_seq.initial", FT_UINT32,
+ BASE_HEX, NULL, 0, "Input Sequence (Initial)", HFILL }},
+
+ { &hf_in_seq_delta,
+ { "Input Sequence (Delta)", "ipvs.in_seq.delta", FT_UINT32,
+ BASE_HEX, NULL, 0, "Input Sequence (Delta)", HFILL }},
+
+ { &hf_in_seq_pdelta,
+ { "Input Sequence (Previous Delta)", "ipvs.in_seq.pdelta", FT_UINT32,
+ BASE_HEX, NULL, 0, "Input Sequence (Previous Delta)", HFILL }},
+
+ { &hf_out_seq_init,
+ { "Output Sequence (Initial)", "ipvs.out_seq.initial", FT_UINT32,
+ BASE_HEX, NULL, 0, "Output Sequence (Initial)", HFILL }},
+
+ { &hf_out_seq_delta,
+ { "Output Sequence (Delta)", "ipvs.out_seq.delta", FT_UINT32,
+ BASE_HEX, NULL, 0, "Output Sequence (Delta)", HFILL }},
+
+ { &hf_out_seq_pdelta,
+ { "Output Sequence (Previous Delta)", "ipvs.out_seq.pdelta", FT_UINT32,
+ BASE_HEX, NULL, 0, "Output Sequence (Previous Delta)", HFILL }},
+
+
+
+
+ };
+ static gint *ett[] = {
+ &ett_ipvs_syncd,
+ &ett_conn,
+ &ett_flags,
+ };
+
+ proto_ipvs_syncd = proto_register_protocol("IP Virtual Services Sync Daemon",
+ "IPVS", "ipvs");
+ proto_register_field_array(proto_ipvs_syncd, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ipvs_syncd(void)
+{
+ dissector_handle_t ipvs_syncd_handle;
+
+ ipvs_syncd_handle = create_dissector_handle(dissect_ipvs_syncd, proto_ipvs_syncd);
+ dissector_add("udp.port", IPVS_SYNCD_PORT, ipvs_syncd_handle);
+}
diff --git a/epan/dissectors/packet-ipx.c b/epan/dissectors/packet-ipx.c
new file mode 100644
index 0000000000..3b851d48ef
--- /dev/null
+++ b/epan/dissectors/packet-ipx.c
@@ -0,0 +1,1580 @@
+/* packet-ipx.c
+ * Routines for NetWare's IPX
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ * NDPS support added by Greg Morris (gmorris@novell.com)
+ *
+ * Portions Copyright (c) 2000-2002 by Gilbert Ramirez.
+ * Portions Copyright (c) Novell, Inc. 2002-2003
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ipx.h"
+#include <epan/resolv.h>
+#include "etypes.h"
+#include "ppptypes.h"
+#include "llcsaps.h"
+#include "aftypes.h"
+#include "arcnet_pids.h"
+#include <epan/conversation.h>
+#include "tap.h"
+
+static int ipx_tap = -1;
+
+#define SPX_PACKET_INIT_COUNT 200
+
+/* The information in this module (IPX, SPX, NCP) comes from:
+ NetWare LAN Analysis, Second Edition
+ Laura A. Chappell and Dan E. Hakes
+ (c) 1994 Novell, Inc.
+ Novell Press, San Jose.
+ ISBN: 0-7821-1362-1
+
+ And from the ncpfs source code by Volker Lendecke
+
+*/
+
+static int proto_ipx = -1;
+static int hf_ipx_checksum = -1;
+static int hf_ipx_len = -1;
+static int hf_ipx_src = -1;
+static int hf_ipx_dst = -1;
+static int hf_ipx_addr = -1;
+static int hf_ipx_hops = -1;
+static int hf_ipx_packet_type = -1;
+static int hf_ipx_dnet = -1;
+static int hf_ipx_dnode = -1;
+static int hf_ipx_dsocket = -1;
+static int hf_ipx_snet = -1;
+static int hf_ipx_snode = -1;
+static int hf_ipx_ssocket = -1;
+static int hf_ipx_net = -1;
+static int hf_ipx_node = -1;
+static int hf_ipx_socket = -1;
+
+static gint ett_ipx = -1;
+
+static dissector_table_t ipx_type_dissector_table;
+static dissector_table_t ipx_socket_dissector_table;
+static dissector_table_t spx_socket_dissector_table;
+
+static int proto_spx = -1;
+static int hf_spx_connection_control = -1;
+static int hf_spx_connection_control_sys = -1;
+static int hf_spx_connection_control_send_ack = -1;
+static int hf_spx_connection_control_attn = -1;
+static int hf_spx_connection_control_eom = -1;
+static int hf_spx_datastream_type = -1;
+static int hf_spx_src_id = -1;
+static int hf_spx_dst_id = -1;
+static int hf_spx_seq_nr = -1;
+static int hf_spx_ack_nr = -1;
+static int hf_spx_all_nr = -1;
+static int hf_spx_rexmt_frame = -1;
+
+static gint ett_spx = -1;
+static gint ett_spx_connctrl = -1;
+
+static int proto_ipxrip = -1;
+static int hf_ipxrip_request = -1;
+static int hf_ipxrip_response = -1;
+
+static gint ett_ipxrip = -1;
+
+static int proto_serialization = -1;
+
+static gint ett_serialization = -1;
+
+static int proto_sap = -1;
+static int hf_sap_request = -1;
+static int hf_sap_response = -1;
+
+static gint ett_ipxsap = -1;
+static gint ett_ipxsap_server = -1;
+
+static gint ett_ipxmsg = -1;
+static int proto_ipxmsg = -1;
+static int hf_msg_conn = -1;
+static int hf_msg_sigchar = -1;
+
+static dissector_handle_t data_handle;
+
+static void
+dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static void
+dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static void
+dissect_serialization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static void
+dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static void
+dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+#define UDP_PORT_IPX 213 /* RFC 1234 */
+
+#define IPX_HEADER_LEN 30 /* It's *always* 30 bytes */
+
+/* ================================================================= */
+/* IPX */
+/* ================================================================= */
+const value_string ipx_socket_vals[] = {
+ { IPX_SOCKET_PING_CISCO, "CISCO PING" },
+ { IPX_SOCKET_NCP, "NCP" },
+ { IPX_SOCKET_SAP, "SAP" },
+ { IPX_SOCKET_IPXRIP, "RIP" },
+ { IPX_SOCKET_NETBIOS, "NetBIOS" },
+ { IPX_SOCKET_DIAGNOSTIC, "Diagnostic" },
+ { IPX_SOCKET_SERIALIZATION, "Serialization" },
+ { IPX_SOCKET_NWLINK_SMB_SERVER, "NWLink SMB Server" },
+ { IPX_SOCKET_NWLINK_SMB_NAMEQUERY, "NWLink SMB Name Query" },
+ { IPX_SOCKET_NWLINK_SMB_REDIR, "NWLink SMB Redirector" },
+ { IPX_SOCKET_NWLINK_SMB_MAILSLOT, "NWLink SMB Mailslot Datagram" },
+ { IPX_SOCKET_NWLINK_SMB_MESSENGER, "NWLink SMB Messenger" },
+ { IPX_SOCKET_NWLINK_SMB_BROWSE, "NWLink SMB Browse" },
+ { IPX_SOCKET_ATTACHMATE_GW, "Attachmate Gateway" },
+ { IPX_SOCKET_IPX_MESSAGE, "IPX Message" },
+ { IPX_SOCKET_IPX_MESSAGE1, "IPX Message" },
+ { IPX_SOCKET_SNMP_AGENT, "SNMP Agent" },
+ { IPX_SOCKET_SNMP_SINK, "SNMP Sink" },
+ { IPX_SOCKET_PING_NOVELL, "Novell PING" },
+ { IPX_SOCKET_UDP_TUNNEL, "UDP Tunnel" },
+ { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
+ { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
+ { IPX_SOCKET_ADSM, "ADSM" },
+ { IPX_SOCKET_EIGRP, "Cisco EIGRP for IPX" },
+ { IPX_SOCKET_NLSP, "NetWare Link Services Protocol" },
+ { IPX_SOCKET_IPXWAN, "IPX WAN" },
+ { SPX_SOCKET_PA, "NDPS Printer Agent/PSM" },
+ { SPX_SOCKET_BROKER, "NDPS Broker" },
+ { SPX_SOCKET_SRS, "NDPS Service Registry Service" },
+ { SPX_SOCKET_ENS, "NDPS Event Notification Service" },
+ { SPX_SOCKET_RMS, "NDPS Remote Management Service" },
+ { SPX_SOCKET_NOTIFY_LISTENER, "NDPS Notify Listener" },
+ { 0xE885, "NT Server-RPC/GW" },
+ { 0x400C, "HP LaserJet/QuickSilver" },
+ { 0x907B, "SMS Testing and Development" },
+ { 0x8F83, "Powerchute UPS Monitoring" },
+ { 0x4006, "NetWare Directory Server" },
+ { 0x8104, "NetWare 386" },
+ { 0x0000, NULL }
+};
+
+static const char*
+socket_text(guint16 socket)
+{
+ return val_to_str(socket, ipx_socket_vals, "Unknown");
+}
+
+static const value_string ipx_packet_type_vals[] = {
+ { IPX_PACKET_TYPE_IPX, "IPX" },
+ { IPX_PACKET_TYPE_RIP, "RIP" },
+ { IPX_PACKET_TYPE_ECHO, "Echo" },
+ { IPX_PACKET_TYPE_ERROR, "Error" },
+ { IPX_PACKET_TYPE_PEP, "PEP" }, /* Packet Exchange Packet */
+ { IPX_PACKET_TYPE_SPX, "SPX" },
+ { 16, "Experimental Protocol" },
+ { IPX_PACKET_TYPE_NCP, "NCP" },
+ { 18, "Experimental Protocol" },
+ { 19, "Experimental Protocol" },
+ { IPX_PACKET_TYPE_WANBCAST, "NetBIOS Broadcast" },
+ { 21, "Experimental Protocol" },
+ { 22, "Experimental Protocol" },
+ { 23, "Experimental Protocol" },
+ { 24, "Experimental Protocol" },
+ { 25, "Experimental Protocol" },
+ { 26, "Experimental Protocol" },
+ { 27, "Experimental Protocol" },
+ { 28, "Experimental Protocol" },
+ { 29, "Experimental Protocol" },
+ { 30, "Experimental Protocol" },
+ { 31, "Experimental Protocol" },
+ { 0, NULL }
+};
+
+static const value_string ipxmsg_sigchar_vals[] = {
+ { '?', "Poll inactive station" },
+ { 'Y', "Station is still using the connection" },
+ { '!', "Broadcast message waiting" },
+ { 0, NULL }
+};
+
+void
+capture_ipx(packet_counts *ld)
+{
+ ld->ipx++;
+}
+
+static void
+dissect_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *next_tvb;
+
+ proto_tree *ipx_tree = NULL;
+ proto_item *ti = NULL;
+
+ const guint8 *src_net_node, *dst_net_node;
+
+ guint8 ipx_hops;
+ char *str;
+ guint16 first_socket, second_socket;
+ guint32 ipx_snet, ipx_dnet;
+ const guint8 *ipx_snode, *ipx_dnode;
+ static ipxhdr_t ipxh_arr[4];
+ static int ipx_current=0;
+ ipxhdr_t *ipxh;
+
+ ipx_current++;
+ if(ipx_current==4){
+ ipx_current=0;
+ }
+ ipxh=&ipxh_arr[ipx_current];
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* Calculate here for use in pinfo and in tree */
+ ipxh->ipx_dsocket = tvb_get_ntohs(tvb, 16);
+ ipxh->ipx_ssocket = tvb_get_ntohs(tvb, 28);
+ ipxh->ipx_type = tvb_get_guint8(tvb, 5);
+ ipxh->ipx_length = tvb_get_ntohs(tvb, 2);
+
+ pinfo->ptype = PT_IPX;
+ pinfo->srcport = ipxh->ipx_ssocket;
+ pinfo->destport = ipxh->ipx_dsocket;
+
+ /* Adjust the tvbuff length to include only the IPX datagram. */
+ set_actual_length(tvb, ipxh->ipx_length);
+
+ src_net_node = tvb_get_ptr(tvb, 18, 10);
+ dst_net_node = tvb_get_ptr(tvb, 6, 10);
+
+ SET_ADDRESS(&pinfo->net_src, AT_IPX, 10, src_net_node);
+ SET_ADDRESS(&pinfo->src, AT_IPX, 10, src_net_node);
+ SET_ADDRESS(&ipxh->ipx_src, AT_IPX, 10, src_net_node);
+ SET_ADDRESS(&pinfo->net_dst, AT_IPX, 10, dst_net_node);
+ SET_ADDRESS(&pinfo->dst, AT_IPX, 10, dst_net_node);
+ SET_ADDRESS(&ipxh->ipx_dst, AT_IPX, 10, dst_net_node);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%04x)",
+ socket_text(ipxh->ipx_dsocket), ipxh->ipx_dsocket);
+
+ if (tree) {
+
+ ti = proto_tree_add_item(tree, proto_ipx, tvb, 0, IPX_HEADER_LEN, FALSE);
+ ipx_tree = proto_item_add_subtree(ti, ett_ipx);
+ }
+
+ str=address_to_str(&pinfo->net_src);
+ proto_tree_add_string_hidden(ipx_tree, hf_ipx_src, tvb, 0, 0, str);
+ proto_tree_add_string_hidden(ipx_tree, hf_ipx_addr, tvb, 0, 0, str);
+ str=address_to_str(&pinfo->net_dst);
+ proto_tree_add_string_hidden(ipx_tree, hf_ipx_dst, tvb, 0, 0, str);
+ proto_tree_add_string_hidden(ipx_tree, hf_ipx_addr, tvb, 0, 0, str);
+
+ proto_tree_add_item(ipx_tree, hf_ipx_checksum, tvb, 0, 2, FALSE);
+ proto_tree_add_uint_format(ipx_tree, hf_ipx_len, tvb, 2, 2, ipxh->ipx_length,
+ "Length: %d bytes", ipxh->ipx_length);
+ ipx_hops = tvb_get_guint8(tvb, 4);
+ proto_tree_add_uint_format(ipx_tree, hf_ipx_hops, tvb, 4, 1, ipx_hops,
+ "Transport Control: %d hops", ipx_hops);
+ proto_tree_add_uint(ipx_tree, hf_ipx_packet_type, tvb, 5, 1, ipxh->ipx_type);
+
+ /* Destination */
+ ipx_dnet = tvb_get_ntohl(tvb, 6);
+ proto_tree_add_ipxnet(ipx_tree, hf_ipx_dnet, tvb, 6, 4,
+ ipx_dnet);
+ proto_tree_add_ipxnet_hidden(ipx_tree, hf_ipx_net, tvb, 6, 4,
+ ipx_dnet);
+ ipx_dnode = tvb_get_ptr(tvb, 10, 6);
+ proto_tree_add_ether(ipx_tree, hf_ipx_dnode, tvb, 10, 6,
+ ipx_dnode);
+ proto_tree_add_ether_hidden(ipx_tree, hf_ipx_node, tvb, 10, 6,
+ ipx_dnode);
+ proto_tree_add_uint(ipx_tree, hf_ipx_dsocket, tvb, 16, 2,
+ ipxh->ipx_dsocket);
+ proto_tree_add_uint_hidden(ipx_tree, hf_ipx_socket, tvb, 16, 2,
+ ipxh->ipx_dsocket);
+
+ /* Source */
+ ipx_snet = tvb_get_ntohl(tvb, 18);
+ proto_tree_add_ipxnet(ipx_tree, hf_ipx_snet, tvb, 18, 4,
+ ipx_snet);
+ proto_tree_add_ipxnet_hidden(ipx_tree, hf_ipx_net, tvb, 18, 4,
+ ipx_snet);
+ ipx_snode = tvb_get_ptr(tvb, 22, 6);
+ proto_tree_add_ether(ipx_tree, hf_ipx_snode, tvb, 22, 6,
+ ipx_snode);
+ proto_tree_add_ether_hidden(ipx_tree, hf_ipx_node, tvb, 22, 6,
+ ipx_snode);
+ proto_tree_add_uint(ipx_tree, hf_ipx_ssocket, tvb, 28, 2,
+ ipxh->ipx_ssocket);
+ proto_tree_add_uint_hidden(ipx_tree, hf_ipx_socket, tvb, 28, 2,
+ ipxh->ipx_ssocket);
+
+ /* Make the next tvbuff */
+ next_tvb = tvb_new_subset(tvb, IPX_HEADER_LEN, -1, -1);
+
+ /*
+ * Let the subdissector know what type of IPX packet this is.
+ */
+ pinfo->ipxptype = ipxh->ipx_type;
+
+ /*
+ * Check the socket numbers before we check the packet type;
+ * we've seen non-NCP packets with a type of NCP and a
+ * destination socket of IPX_SOCKET_IPX_MESSAGE, and SAP
+ * packets with a type of NCP and a destination socket of
+ * IPX_SOCKET_SAP.
+ *
+ * We've seen NCP packets with a type of NCP, a source socket of
+ * IPX_SOCKET_NCP, and a destination socket of IPX_SOCKET_IPX_MESSAGE,
+ * and we've seen NCP packets with a type of NCP, a source socket of
+ * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
+ * IPX_SOCKET_NCP, so testing the destination socket first doesn't
+ * always give the right answer. We've also seen SAP packets with
+ * a source socket of IPX_SOCKET_SAP and a destination socket of
+ * IPX_SOCKET_IPX_MESSAGE.
+ *
+ * Unfortunately, we've also seen packets with a source socket
+ * of IPX_SOCKET_NWLINK_SMB_SERVER and a destination socket
+ * of IPX_SOCKET_NWLINK_SMB_NAMEQUERY that were NMPI packets,
+ * not SMB packets, so testing the lower-valued socket first
+ * also doesn't always give the right answer.
+ *
+ * So we start out assuming we should test the lower-numbered
+ * socket number first, but, if the higher-numbered socket is
+ * IPX_SOCKET_NWLINK_SMB_NAMEQUERY, we assume that it's a
+ * NMPI query, and test only that socket.
+ */
+ if (ipxh->ipx_ssocket > ipxh->ipx_dsocket) {
+ first_socket = ipxh->ipx_dsocket;
+ second_socket = ipxh->ipx_ssocket;
+ } else {
+ first_socket = ipxh->ipx_ssocket;
+ second_socket = ipxh->ipx_dsocket;
+ }
+
+ tap_queue_packet(ipx_tap, pinfo, ipxh);
+
+ if (second_socket != IPX_SOCKET_NWLINK_SMB_NAMEQUERY) {
+ if (dissector_try_port(ipx_socket_dissector_table, first_socket,
+ next_tvb, pinfo, tree))
+ return;
+ }
+ if (dissector_try_port(ipx_socket_dissector_table, second_socket,
+ next_tvb, pinfo, tree))
+ return;
+
+ /*
+ * Neither of them are known; try the packet type, which will
+ * at least let us, for example, dissect SPX packets as SPX.
+ */
+ if (dissector_try_port(ipx_type_dissector_table, ipxh->ipx_type, next_tvb,
+ pinfo, tree))
+ return;
+
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+}
+/* ================================================================= */
+/* SPX Hash Functions */
+/* ================================================================= */
+
+typedef struct {
+ conversation_t *conversation;
+ guint32 spx_src;
+ guint16 spx_seq;
+} spx_hash_key;
+
+typedef struct {
+ guint16 spx_ack;
+ guint16 spx_all;
+ guint32 num;
+} spx_hash_value;
+
+/*
+ * Structure attached to retransmitted SPX frames; it contains the
+ * frame number of the original transmission.
+ */
+typedef struct {
+ guint32 num;
+} spx_rexmit_info;
+
+static GHashTable *spx_hash = NULL;
+static GMemChunk *spx_hash_keys = NULL;
+static GMemChunk *spx_hash_values = NULL;
+static GMemChunk *spx_rexmit_infos = NULL;
+
+/* Hash Functions */
+gint
+spx_equal(gconstpointer v, gconstpointer v2)
+{
+ const spx_hash_key *val1 = (const spx_hash_key*)v;
+ const spx_hash_key *val2 = (const spx_hash_key*)v2;
+
+ if (val1->conversation == val2->conversation &&
+ val1->spx_src == val2->spx_src &&
+ val1->spx_seq == val2->spx_seq) {
+ return 1;
+ }
+ return 0;
+}
+
+guint
+spx_hash_func(gconstpointer v)
+{
+ const spx_hash_key *spx_key = (const spx_hash_key*)v;
+ return GPOINTER_TO_UINT(spx_key->conversation) + spx_key->spx_src;
+}
+
+/* Initializes the hash table and the mem_chunk area each time a new
+ * file is loaded or re-loaded in ethereal */
+static void
+spx_init_protocol(void)
+{
+
+ if (spx_hash)
+ g_hash_table_destroy(spx_hash);
+ if (spx_hash_keys)
+ g_mem_chunk_destroy(spx_hash_keys);
+ if (spx_hash_values)
+ g_mem_chunk_destroy(spx_hash_values);
+ if (spx_rexmit_infos)
+ g_mem_chunk_destroy(spx_rexmit_infos);
+
+ spx_hash = g_hash_table_new(spx_hash_func, spx_equal);
+ spx_hash_keys = g_mem_chunk_new("spx_hash_keys",
+ sizeof(spx_hash_key),
+ SPX_PACKET_INIT_COUNT * sizeof(spx_hash_key),
+ G_ALLOC_ONLY);
+ spx_hash_values = g_mem_chunk_new("spx_hash_values",
+ sizeof(spx_hash_value),
+ SPX_PACKET_INIT_COUNT * sizeof(spx_hash_value),
+ G_ALLOC_ONLY);
+ spx_rexmit_infos = g_mem_chunk_new("spx_rexmit_infos",
+ sizeof(spx_rexmit_infos),
+ SPX_PACKET_INIT_COUNT * sizeof(spx_rexmit_infos),
+ G_ALLOC_ONLY);
+}
+
+/* After the sequential run, we don't need the spx hash table, or
+ * the keys and values, anymore; the lookups have already been done
+ * and the relevant info saved as SPX private data with the frame
+ * if the frame was a retransmission. */
+static void
+spx_postseq_cleanup(void)
+{
+ if (spx_hash) {
+ /* Destroy the hash, but don't clean up request_condition data. */
+ g_hash_table_destroy(spx_hash);
+ spx_hash = NULL;
+ }
+ if (spx_hash_keys) {
+ g_mem_chunk_destroy(spx_hash_keys);
+ spx_hash_keys = NULL;
+ }
+ if (spx_hash_values) {
+ g_mem_chunk_destroy(spx_hash_values);
+ spx_hash_values = NULL;
+ }
+ /* Don't free the spx_rexmit_infos, as they're
+ * needed during random-access processing of the proto_tree.*/
+}
+
+spx_hash_value*
+spx_hash_insert(conversation_t *conversation, guint32 spx_src, guint16 spx_seq)
+{
+ spx_hash_key *key;
+ spx_hash_value *value;
+
+ /* Now remember the packet, so we can find it if we later. */
+ key = g_mem_chunk_alloc(spx_hash_keys);
+ key->conversation = conversation;
+ key->spx_src = spx_src;
+ key->spx_seq = spx_seq;
+
+ value = g_mem_chunk_alloc(spx_hash_values);
+ value->spx_ack = 0;
+ value->spx_all = 0;
+ value->num = 0;
+
+ g_hash_table_insert(spx_hash, key, value);
+
+ return value;
+}
+
+/* Returns the spx_hash_value*, or NULL if not found. */
+spx_hash_value*
+spx_hash_lookup(conversation_t *conversation, guint32 spx_src, guint32 spx_seq)
+{
+ spx_hash_key key;
+
+ key.conversation = conversation;
+ key.spx_src = spx_src;
+ key.spx_seq = spx_seq;
+
+ return g_hash_table_lookup(spx_hash, &key);
+}
+
+/* ================================================================= */
+/* SPX */
+/* ================================================================= */
+
+#define SPX_SYS_PACKET 0x80
+#define SPX_SEND_ACK 0x40
+#define SPX_ATTN 0x20
+#define SPX_EOM 0x10
+
+static const char*
+spx_conn_ctrl(guint8 ctrl)
+{
+ const char *p;
+
+ static const value_string conn_vals[] = {
+ { 0x00, "Data, No Ack Required" },
+ { SPX_EOM, "End-of-Message" },
+ { SPX_ATTN, "Attention" },
+ { SPX_SEND_ACK, "Acknowledgment Required"},
+ { SPX_SEND_ACK|SPX_EOM, "Send Ack: End Message"},
+ { SPX_SYS_PACKET, "System Packet"},
+ { SPX_SYS_PACKET|SPX_SEND_ACK, "System Packet: Send Ack"},
+ { 0x00, NULL }
+ };
+
+ p = match_strval((ctrl & 0xf0), conn_vals );
+
+ if (p) {
+ return p;
+ }
+ else {
+ return "Unknown";
+ }
+}
+
+static const char*
+spx_datastream(guint8 type)
+{
+ switch (type) {
+ case 0xfe:
+ return "End-of-Connection";
+ case 0xff:
+ return "End-of-Connection Acknowledgment";
+ default:
+ return NULL;
+ }
+}
+
+#define SPX_HEADER_LEN 12
+
+static void
+dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *spx_tree = NULL;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+ guint8 conn_ctrl;
+ proto_tree *cc_tree;
+ guint8 datastream_type;
+ const char *datastream_type_string;
+ guint16 spx_seq;
+ const char *spx_msg_string;
+ guint16 low_socket, high_socket;
+ guint32 src;
+ conversation_t *conversation;
+ spx_hash_value *pkt_value;
+ spx_rexmit_info *spx_rexmit_info;
+ spx_info spx_info;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPX");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "SPX");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_spx, tvb, 0, SPX_HEADER_LEN, FALSE);
+ spx_tree = proto_item_add_subtree(ti, ett_spx);
+ }
+
+ conn_ctrl = tvb_get_guint8(tvb, 0);
+ spx_msg_string = spx_conn_ctrl(conn_ctrl);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", spx_msg_string);
+ if (tree) {
+ ti = proto_tree_add_uint_format(spx_tree, hf_spx_connection_control, tvb,
+ 0, 1, conn_ctrl,
+ "Connection Control: %s (0x%02X)",
+ spx_msg_string, conn_ctrl);
+ cc_tree = proto_item_add_subtree(ti, ett_spx_connctrl);
+ proto_tree_add_boolean(cc_tree, hf_spx_connection_control_sys, tvb,
+ 0, 1, conn_ctrl);
+ proto_tree_add_boolean(cc_tree, hf_spx_connection_control_send_ack, tvb,
+ 0, 1, conn_ctrl);
+ proto_tree_add_boolean(cc_tree, hf_spx_connection_control_attn, tvb,
+ 0, 1, conn_ctrl);
+ proto_tree_add_boolean(cc_tree, hf_spx_connection_control_eom, tvb,
+ 0, 1, conn_ctrl);
+ }
+
+ datastream_type = tvb_get_guint8(tvb, 1);
+ datastream_type_string = spx_datastream(datastream_type);
+ if (datastream_type_string != NULL) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
+ datastream_type_string);
+ }
+ if (tree) {
+ if (datastream_type_string != NULL) {
+ proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
+ 1, 1, datastream_type,
+ "Datastream Type: %s (0x%02X)",
+ datastream_type_string,
+ datastream_type);
+ } else {
+ proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
+ 1, 1, datastream_type,
+ "Datastream Type: 0x%02X",
+ datastream_type);
+ }
+ proto_tree_add_item(spx_tree, hf_spx_src_id, tvb, 2, 2, FALSE);
+ proto_tree_add_item(spx_tree, hf_spx_dst_id, tvb, 4, 2, FALSE);
+ }
+ spx_seq = tvb_get_ntohs(tvb, 6);
+ if (tree) {
+ proto_tree_add_uint(spx_tree, hf_spx_seq_nr, tvb, 6, 2, spx_seq);
+ proto_tree_add_item(spx_tree, hf_spx_ack_nr, tvb, 8, 2, FALSE);
+ proto_tree_add_item(spx_tree, hf_spx_all_nr, tvb, 10, 2, FALSE);
+ }
+
+ /*
+ * SPX is Connection Oriented and Delivery Guaranteed.
+ * On the first pass, we need to flag retransmissions by the SPX
+ * protocol, so that subdissectors know whether a packet was
+ * retransmitted.
+ *
+ * We start out by creating a conversation for this direction of the
+ * IPX session; we use "pinfo->srcport" twice, so that we have
+ * separate conversations for the two directions.
+ *
+ * XXX - that might not work correctly if there's more than one
+ * SPX session using that source port; can that happen? If so,
+ * we should probably use the direction, as well as the conversation,
+ * as part of the hash key; if we do that, we can probably just
+ * use PT_IPX as the port type, and possibly get rid of PT_NCP.
+ *
+ * According to
+ *
+ * http://developer.novell.com/research/appnotes/1995/december/03/apv.htm
+ *
+ * the sequence number is not incremented for system packets, so
+ * presumably that means there is no notion of a system packet
+ * being retransmitted; that document also says that system
+ * packets are used as "I'm still here" keepalives and as
+ * acknowledgements (presumably meaning ACK-only packets), which
+ * suggests that they might not be ACKed and thus might not
+ * be retransmitted.
+ */
+ if (conn_ctrl & SPX_SYS_PACKET) {
+ /*
+ * It's a system packet, so it isn't a retransmission.
+ */
+ spx_rexmit_info = NULL;
+ } else {
+ /*
+ * Not a system packet - check for retransmissions.
+ */
+ if (!pinfo->fd->flags.visited) {
+ conversation = find_conversation(&pinfo->src,
+ &pinfo->dst, PT_NCP, pinfo->srcport,
+ pinfo->srcport, 0);
+ if (conversation == NULL) {
+ /*
+ * It's not part of any conversation - create
+ * a new one.
+ */
+ conversation = conversation_new(&pinfo->src,
+ &pinfo->dst, PT_NCP, pinfo->srcport,
+ pinfo->srcport, 0);
+ }
+
+ /*
+ * Now we'll hash the SPX header and use the result
+ * of that, plus the conversation, as a hash key to
+ * identify this packet.
+ *
+ * If we don't find it in the hash table, it's not a
+ * retransmission, otherwise it is. If we don't find
+ * it, we enter it into the hash table, with the
+ * frame number.
+ * If we do, we attach to this frame a structure giving
+ * the frame number of the original transmission, so
+ * that we, and subdissectors, know it's a
+ * retransmission.
+ */
+ src = tvb_get_ntohs(tvb, 0)+tvb_get_ntohs(tvb, 2)+tvb_get_ntohs(tvb, 4)+tvb_get_ntohs(tvb, 6)+tvb_get_ntohs(tvb, 8);
+ pkt_value = spx_hash_lookup(conversation, src, spx_seq);
+ if (pkt_value == NULL) {
+ /*
+ * Not found in the hash table.
+ * Enter it into the hash table.
+ */
+ pkt_value = spx_hash_insert(conversation, src,
+ spx_seq);
+ pkt_value->spx_ack = tvb_get_ntohs(tvb, 8);
+ pkt_value->spx_all = tvb_get_ntohs(tvb, 10);
+ pkt_value->num = pinfo->fd->num;
+
+ /*
+ * This is not a retransmission, so we shouldn't
+ * have any retransmission indicator.
+ */
+ spx_rexmit_info = NULL;
+ } else {
+ /*
+ * Found in the hash table. Mark this frame as
+ * a retransmission.
+ */
+ spx_rexmit_info = g_mem_chunk_alloc(spx_rexmit_infos);
+ spx_rexmit_info->num = pkt_value->num;
+ p_add_proto_data(pinfo->fd, proto_spx,
+ spx_rexmit_info);
+ }
+ } else {
+ /*
+ * Do we have per-packet SPX data for this frame?
+ * If so, it's a retransmission, and the per-packet
+ * data indicates which frame had the original
+ * transmission.
+ */
+ spx_rexmit_info = p_get_proto_data(pinfo->fd,
+ proto_spx);
+ }
+ }
+
+ /*
+ * It's a retransmission if we have a retransmission indicator.
+ * Flag this as a retransmission, but don't pass it to the
+ * subdissector.
+ */
+ if (spx_rexmit_info != NULL) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "[Retransmission] Original Packet %u",
+ spx_rexmit_info->num);
+ }
+ if (tree) {
+ proto_tree_add_uint_format(spx_tree, hf_spx_rexmt_frame,
+ tvb, 0, 0, spx_rexmit_info->num,
+ "This is a retransmission of frame %u",
+ spx_rexmit_info->num);
+ if (tvb_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
+ proto_tree_add_text(spx_tree, tvb,
+ SPX_HEADER_LEN, -1,
+ "Retransmitted data");
+ }
+ }
+ return;
+ }
+
+ if (tvb_reported_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
+ /*
+ * Call subdissectors based on the IPX socket numbers; a
+ * subdissector might have registered with our IPX socket
+ * dissector table rather than the IPX dissector's socket
+ * dissector table.
+ *
+ * Assume the lower-numbered socket number is more likely
+ * to be the right one, along the lines of what we do for
+ * TCP and UDP. We've seen NCP packets with a type of NCP,
+ * a source socket of IPX_SOCKET_NCP, and a destination
+ * socket of IPX_SOCKET_IPX_MESSAGE, and we've seen NCP
+ * packets with a type of NCP, a source socket of
+ * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
+ * IPX_SOCKET_NCP.
+ */
+ if (pinfo->srcport > pinfo->destport) {
+ low_socket = pinfo->destport;
+ high_socket = pinfo->srcport;
+ } else {
+ low_socket = pinfo->srcport;
+ high_socket = pinfo->destport;
+ }
+
+ /*
+ * Pass information to subdissectors.
+ */
+ spx_info.eom = conn_ctrl & SPX_EOM;
+ spx_info.datastream_type = datastream_type;
+ pinfo->private_data = &spx_info;
+
+ next_tvb = tvb_new_subset(tvb, SPX_HEADER_LEN, -1, -1);
+ if (dissector_try_port(spx_socket_dissector_table, low_socket,
+ next_tvb, pinfo, tree))
+ return;
+ if (dissector_try_port(spx_socket_dissector_table, high_socket,
+ next_tvb, pinfo, tree))
+ return;
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+}
+
+/* ================================================================= */
+/* IPX Message */
+/* ================================================================= */
+static void
+dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *msg_tree;
+ proto_item *ti;
+ guint8 conn_number, sig_char;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX MSG");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ conn_number = tvb_get_guint8(tvb, 0);
+ sig_char = tvb_get_guint8(tvb, 1);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s, Connection %d",
+ val_to_str(sig_char, ipxmsg_sigchar_vals, "Unknown Signature Char"), conn_number);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ipxmsg, tvb, 0, -1, FALSE);
+ msg_tree = proto_item_add_subtree(ti, ett_ipxmsg);
+
+ proto_tree_add_uint(msg_tree, hf_msg_conn, tvb, 0, 1, conn_number);
+ proto_tree_add_uint(msg_tree, hf_msg_sigchar, tvb, 1, 1, sig_char);
+ }
+}
+
+
+/* ================================================================= */
+/* IPX RIP */
+/* ================================================================= */
+static void
+dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *rip_tree;
+ proto_item *ti;
+ guint16 operation;
+ struct ipx_rt_def route;
+ int cursor;
+ int available_length;
+
+ static char *rip_type[3] = { "Request", "Response", "Unknown" };
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX RIP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ operation = tvb_get_ntohs(tvb, 0) - 1;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /* rip_types 0 and 1 are valid, anything else becomes 2 or "Unknown" */
+ col_set_str(pinfo->cinfo, COL_INFO, rip_type[MIN(operation, 2)]);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ipxrip, tvb, 0, -1, FALSE);
+ rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
+
+ if (operation < 2) {
+ proto_tree_add_text(rip_tree, tvb, 0, 2,
+ "RIP packet type: %s", rip_type[operation]);
+
+ if (operation == 0) {
+ proto_tree_add_boolean_hidden(rip_tree,
+ hf_ipxrip_request,
+ tvb, 0, 2, 1);
+ } else {
+ proto_tree_add_boolean_hidden(rip_tree,
+ hf_ipxrip_response,
+ tvb, 0, 2, 1);
+ }
+
+ }
+ else {
+ proto_tree_add_text(rip_tree, tvb, 0, 2, "Unknown RIP packet type");
+ }
+
+ available_length = tvb_reported_length(tvb);
+ for (cursor = 2; cursor < available_length; cursor += 8) {
+ tvb_memcpy(tvb, (guint8 *)&route.network, cursor, 4);
+ route.hops = tvb_get_ntohs(tvb, cursor+4);
+ route.ticks = tvb_get_ntohs(tvb, cursor+6);
+
+ if (operation == IPX_RIP_REQUEST - 1) {
+ proto_tree_add_text(rip_tree, tvb, cursor, 8,
+ "Route Vector: %s, %d hop%s, %d tick%s",
+ ipxnet_to_string((guint8*)&route.network),
+ route.hops, route.hops == 1 ? "" : "s",
+ route.ticks, route.ticks == 1 ? "" : "s");
+ }
+ else {
+ proto_tree_add_text(rip_tree, tvb, cursor, 8,
+ "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
+ ipxnet_to_string((guint8*)&route.network),
+ route.hops, route.hops == 1 ? "" : "s",
+ route.ticks, route.ticks == 1 ? "" : "s",
+ route.ticks * 1000 / 18);
+ }
+ }
+ }
+}
+
+/* ================================================================= */
+/* IPX Serialization */
+/* ================================================================= */
+static void
+dissect_serialization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ser_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NW_SERIAL");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_serialization, tvb, 0, -1,
+ FALSE);
+ ser_tree = proto_item_add_subtree(ti, ett_serialization);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Serial number %s",
+ tvb_bytes_to_str(tvb, 0, 6));
+ }
+
+ if (tree) {
+ proto_tree_add_text(ser_tree, tvb, 0, 6,
+ "Serial number: %s", tvb_bytes_to_str(tvb, 0, 6));
+ }
+}
+
+/*
+ * Some of these are from ncpfs, others are from the book,
+ * others are from the page at
+ *
+ * http://www.iana.org/assignments/novell-sap-numbers
+ *
+ * and some from the page at
+ *
+ * http://www.rware.demon.co.uk/ipxsap.htm
+ *
+ * (see also the page at
+ *
+ * http://developer.novell.com/research/appnotes/1998/february/03/06.htm
+ *
+ * which has a huge list - but many of the entries list only the
+ * organization owning the SAP type, not what the type is for).
+ */
+const value_string server_vals[] = {
+ { 0x0000, "Unknown" },
+ { 0x0001, "User" },
+ { 0x0002, "User Group" },
+ { 0x0003, "Print Queue or Print Group" },
+ { 0x0004, "File Server (SLIST source)" },
+ { 0x0005, "Job Server" },
+ { 0x0006, "Gateway" },
+ { 0x0007, "Print Server or Silent Print Server" },
+ { 0x0008, "Archive Queue" },
+ { 0x0009, "Archive Server" },
+ { 0x000a, "Job Queue" },
+ { 0x000b, "Administration" },
+ { 0x000F, "Novell TI-RPC" },
+ { 0x0017, "Diagnostics" },
+ { 0x0020, "NetBIOS" },
+ { 0x0021, "NAS SNA Gateway" },
+ { 0x0023, "NACS Async Gateway or Asynchronous Gateway" },
+ { 0x0024, "Remote Bridge or Routing Service" },
+ { 0x0026, "Bridge Server or Asynchronous Bridge Server" },
+ { 0x0027, "TCP/IP Gateway Server" },
+ { 0x0028, "Point to Point (Eicon) X.25 Bridge Server" },
+ { 0x0029, "Eicon 3270 Gateway" },
+ { 0x002a, "CHI Corp" },
+ { 0x002c, "PC Chalkboard" },
+ { 0x002d, "Time Synchronization Server or Asynchronous Timer" },
+ { 0x002e, "ARCserve 5.0 / Palindrome Backup Director 4.x (PDB4)" },
+ { 0x0045, "DI3270 Gateway" },
+ { 0x0047, "Advertising Print Server" },
+ { 0x004a, "NetBlazer Modems" },
+ { 0x004b, "Btrieve VAP/NLM 5.0" },
+ { 0x004c, "NetWare SQL VAP/NLM Server" },
+ { 0x004d, "Xtree Network Version/NetWare XTree" },
+ { 0x0050, "Btrieve VAP 4.11" },
+ { 0x0052, "QuickLink (Cubix)" },
+ { 0x0053, "Print Queue User" },
+ { 0x0058, "Multipoint X.25 Eicon Router" },
+ { 0x0060, "STLB/NLM" },
+ { 0x0064, "ARCserve" },
+ { 0x0066, "ARCserve 3.0" },
+ { 0x0072, "WAN Copy Utility" },
+ { 0x007a, "TES-NetWare for VMS" },
+ { 0x0092, "WATCOM Debugger or Emerald Tape Backup Server" },
+ { 0x0095, "DDA OBGYN" },
+ { 0x0098, "NetWare Access Server (Asynchronous gateway)" },
+ { 0x009a, "NetWare for VMS II or Named Pipe Server" },
+ { 0x009b, "NetWare Access Server" },
+ { 0x009e, "Portable NetWare Server or SunLink NVT" },
+ { 0x00a1, "Powerchute APC UPS NLM" },
+ { 0x00aa, "LAWserve" },
+ { 0x00ac, "Compaq IDA Status Monitor" },
+ { 0x0100, "PIPE STAIL" },
+ { 0x0102, "LAN Protect Bindery" },
+ { 0x0103, "Oracle DataBase Server" },
+ { 0x0107, "NetWare 386 or RSPX Remote Console" },
+ { 0x010f, "Novell SNA Gateway" },
+ { 0x0111, "Test Server" },
+ { 0x0112, "Print Server (HP)" },
+ { 0x0114, "CSA MUX (f/Communications Executive)" },
+ { 0x0115, "CSA LCA (f/Communications Executive)" },
+ { 0x0116, "CSA CM (f/Communications Executive)" },
+ { 0x0117, "CSA SMA (f/Communications Executive)" },
+ { 0x0118, "CSA DBA (f/Communications Executive)" },
+ { 0x0119, "CSA NMA (f/Communications Executive)" },
+ { 0x011a, "CSA SSA (f/Communications Executive)" },
+ { 0x011b, "CSA STATUS (f/Communications Executive)" },
+ { 0x011e, "CSA APPC (f/Communications Executive)" },
+ { 0x0126, "SNA TEST SSA Profile" },
+ { 0x012a, "CSA TRACE (f/Communications Executive)" },
+ { 0x012b, "NetWare for SAA" },
+ { 0x012e, "IKARUS virus scan utility" },
+ { 0x0130, "Communications Executive" },
+ { 0x0133, "NNS Domain Server or NetWare Naming Services Domain" },
+ { 0x0135, "NetWare Naming Services Profile" },
+ { 0x0137, "NetWare 386 Print Queue or NNS Print Queue" },
+ { 0x0141, "LAN Spool Server (Vap, Intel)" },
+ { 0x0152, "IRMALAN Gateway" },
+ { 0x0154, "Named Pipe Server" },
+ { 0x0166, "NetWare Management" },
+ { 0x0168, "Intel PICKIT Comm Server or Intel CAS Talk Server" },
+ { 0x0173, "Compaq" },
+ { 0x0174, "Compaq SNMP Agent" },
+ { 0x0175, "Compaq" },
+ { 0x0180, "XTree Server or XTree Tools" },
+ { 0x018A, "NASI services broadcast server (Novell)" },
+ { 0x01b0, "GARP Gateway (net research)" },
+ { 0x01b1, "Binfview (Lan Support Group)" },
+ { 0x01bf, "Intel LanDesk Manager" },
+ { 0x01ca, "AXTEC" },
+ { 0x01cb, "Shiva NetModem/E" },
+ { 0x01cc, "Shiva LanRover/E" },
+ { 0x01cd, "Shiva LanRover/T" },
+ { 0x01ce, "Shiva Universal" },
+ { 0x01d8, "Castelle FAXPress Server" },
+ { 0x01da, "Castelle LANPress Print Server" },
+ { 0x01dc, "Castelle FAX/Xerox 7033 Fax Server/Excel Lan Fax" },
+ { 0x01f0, "LEGATO" },
+ { 0x01f5, "LEGATO" },
+ { 0x0233, "NMS Agent or NetWare Management Agent" },
+ { 0x0237, "NMS IPX Discovery or LANtern Read/Write Channel" },
+ { 0x0238, "NMS IP Discovery or LANtern Trap/Alarm Channel" },
+ { 0x023a, "LANtern" },
+ { 0x023c, "MAVERICK" },
+ { 0x023f, "SMS Testing and Development" },
+ { 0x024e, "NetWare Connect" },
+ { 0x024f, "NASI server broadcast (Cisco)" },
+ { 0x026a, "Network Management (NMS) Service Console" },
+ { 0x026b, "Time Synchronization Server (NetWare 4.x)" },
+ { 0x0278, "Directory Server (NetWare 4.x)" },
+ { 0x027b, "NetWare Management Agent" },
+ { 0x0280, "Novell File and Printer Sharing Service for PC" },
+ { 0x0304, "Novell SAA Gateway" },
+ { 0x0308, "COM or VERMED 1" },
+ { 0x030a, "Galacticomm's Worldgroup Server" },
+ { 0x030c, "Intel Netport 2 or HP JetDirect or HP Quicksilver" },
+ { 0x0320, "Attachmate Gateway" },
+ { 0x0327, "Microsoft Diagnostics" },
+ { 0x0328, "WATCOM SQL server" },
+ { 0x0335, "MultiTech Systems Multisynch Comm Server" },
+ { 0x0343, "Xylogics Remote Access Server or LAN Modem" },
+ { 0x0355, "Arcada Backup Exec" },
+ { 0x0358, "MSLCD1" },
+ { 0x0361, "NETINELO" },
+ { 0x037e, "Powerchute UPS Monitoring" },
+ { 0x037f, "ViruSafe Notify" },
+ { 0x0386, "HP Bridge" },
+ { 0x0387, "HP Hub" },
+ { 0x0394, "NetWare SAA Gateway" },
+ { 0x039b, "Lotus Notes" },
+ { 0x03b7, "Certus Anti Virus NLM" },
+ { 0x03c4, "ARCserve 4.0 (Cheyenne)" },
+ { 0x03c7, "LANspool 3.5 (Intel)" },
+ { 0x03d7, "Lexmark printer server (type 4033-011)" },
+ { 0x03d8, "Lexmark XLE printer server (type 4033-301)" },
+ { 0x03dd, "Banyan ENS for NetWare Client NLM" },
+ { 0x03de, "Gupta Sequel Base Server or NetWare SQL" },
+ { 0x03e1, "Univel Unixware" },
+ { 0x03e4, "Univel Unixware" },
+ { 0x03fc, "Intel Netport" },
+ { 0x03fd, "Intel Print Server Queue" },
+ { 0x040A, "ipnServer" },
+ { 0x040D, "LVERRMAN" },
+ { 0x040E, "LVLIC" },
+ { 0x0414, "NET Silicon (DPI)/Kyocera" },
+ { 0x0429, "Site Lock Virus (Brightworks)" },
+ { 0x0432, "UFHELP R" },
+ { 0x0433, "Synoptics 281x Advanced SNMP Agent" },
+ { 0x0444, "Microsoft NT SNA Server" },
+ { 0x0448, "Oracle" },
+ { 0x044c, "ARCserve 5.01" },
+ { 0x0457, "Canon GP55 Running on a Canon GP55 network printer" },
+ { 0x045a, "QMS Printers" },
+ { 0x045b, "Dell SCSI Array (DSA) Monitor" },
+ { 0x0491, "NetBlazer Modems" },
+ { 0x04ac, "On-Time Scheduler NLM" },
+ { 0x04b0, "CD-Net (Meridian)" },
+ { 0x0513, "Emulex NQA" },
+ { 0x0520, "Site Lock Checks" },
+ { 0x0529, "Site Lock Checks (Brightworks)" },
+ { 0x052d, "Citrix OS/2 App Server" },
+ { 0x0535, "Tektronix" },
+ { 0x0536, "Milan" },
+ { 0x055d, "Attachmate SNA gateway" },
+ { 0x056b, "IBM 8235 modem server" },
+ { 0x056c, "Shiva LanRover/E PLUS" },
+ { 0x056d, "Shiva LanRover/T PLUS" },
+ { 0x0580, "McAfee's NetShield anti-virus" },
+ { 0x05B8, "NLM to workstation communication (Revelation Software)" },
+ { 0x05BA, "Compatible Systems Routers" },
+ { 0x05BE, "Cheyenne Hierarchical Storage Manager" },
+ { 0x0606, "JCWatermark Imaging" },
+ { 0x060c, "AXIS Network Printer" },
+ { 0x0610, "Adaptec SCSI Management" },
+ { 0x0621, "IBM AntiVirus NLM" },
+ { 0x0640, "Microsoft Gateway Services for NetWare" },
+/* { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" }, */
+ { 0x064e, "Microsoft Internet Information Server" },
+ { 0x067b, "Microsoft Win95/98 File and Print Sharing for NetWare" },
+ { 0x067c, "Microsoft Win95/98 File and Print Sharing for NetWare" },
+ { 0x076C, "Xerox" },
+ { 0x079b, "Shiva LanRover/E 115" },
+ { 0x079c, "Shiva LanRover/T 115" },
+ { 0x07B4, "Cubix WorldDesk" },
+ { 0x07c2, "Quarterdeck IWare Connect V2.x NLM" },
+ { 0x07c1, "Quarterdeck IWare Connect V3.x NLM" },
+ { 0x0810, "ELAN License Server Demo" },
+ { 0x0824, "Shiva LanRover Access Switch/E" },
+ { 0x086a, "ISSC collector NLMs" },
+ { 0x087f, "ISSC DAS agent for AIX" },
+ { 0x0880, "Intel Netport PRO" },
+ { 0x0881, "Intel Netport PRO" },
+ { 0x0b29, "Site Lock" },
+ { 0x0c29, "Site Lock Applications" },
+ { 0x0c2c, "Licensing Server" },
+ { 0x2101, "Performance Technology Instant Internet" },
+ { 0x2380, "LAI Site Lock" },
+ { 0x238c, "Meeting Maker" },
+ { 0x4808, "Site Lock Server or Site Lock Metering VAP/NLM" },
+ { 0x5555, "Site Lock User" },
+ { 0x6312, "Tapeware" },
+ { 0x6f00, "Rabbit Gateway (3270)" },
+ { 0x7703, "MODEM" },
+ { 0x8002, "NetPort Printers (Intel) or LANport" },
+ { 0x8003, "SEH InterCon Printserver" },
+ { 0x8008, "WordPerfect Network Version" },
+ { 0x85BE, "Cisco Enhanced Interior Routing Protocol (EIGRP)" },
+ { 0x8888, "WordPerfect Network Version or Quick Network Management" },
+ { 0x9000, "McAfee's NetShield anti-virus" },
+ { 0x9604, "CSA-NT_MON" },
+ { 0xb6a8, "Ocean Isle Reachout Remote Control" },
+ { 0xf11f, "Site Lock Metering VAP/NLM" },
+ { 0xf1ff, "Site Lock" },
+ { 0xf503, "Microsoft SQL Server" },
+ { 0xf905, "IBM Time and Place/2 application" },
+ { 0xfbfb, "TopCall III fax server" },
+ { 0xffff, "Any Service or Wildcard" },
+ { 0x0000, NULL }
+};
+
+static void
+dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *sap_tree, *s_tree;
+ proto_item *ti;
+ int cursor;
+ struct sap_query query;
+ guint16 server_type;
+ char server_name[48];
+ guint16 server_port;
+ guint16 intermediate_network;
+
+ static char *sap_type[4] = { "General Query", "General Response",
+ "Nearest Query", "Nearest Response" };
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX SAP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ query.query_type = tvb_get_ntohs(tvb, 0);
+ query.server_type = tvb_get_ntohs(tvb, 2);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (query.query_type >= 1 && query.query_type <= 4) {
+ col_set_str(pinfo->cinfo, COL_INFO, sap_type[query.query_type - 1]);
+ }
+ else {
+ col_set_str(pinfo->cinfo, COL_INFO, "Unknown Packet Type");
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_sap, tvb, 0, -1, FALSE);
+ sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
+
+ if (query.query_type >= 1 && query.query_type <= 4) {
+ proto_tree_add_text(sap_tree, tvb, 0, 2, sap_type[query.query_type - 1]);
+ if ((query.query_type - 1) % 2) {
+ proto_tree_add_boolean_hidden(sap_tree,
+ hf_sap_response,
+ tvb, 0, 2, 1);
+ } else {
+ proto_tree_add_boolean_hidden(sap_tree,
+ hf_sap_request,
+ tvb, 0, 2, 1);
+ }
+ }
+ else {
+ proto_tree_add_text(sap_tree, tvb, 0, 2,
+ "Unknown SAP Packet Type %d", query.query_type);
+ }
+
+ if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
+ query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
+
+ int available_length = tvb_reported_length(tvb);
+ for (cursor = 2; (cursor + 64) <= available_length; cursor += 64) {
+ server_type = tvb_get_ntohs(tvb, cursor);
+ tvb_memcpy(tvb, (guint8 *)server_name,
+ cursor+2, 48);
+
+ ti = proto_tree_add_text(sap_tree, tvb, cursor+2, 48,
+ "Server Name: %.48s", server_name);
+ s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
+
+ proto_tree_add_text(s_tree, tvb, cursor, 2, "Server Type: %s (0x%04X)",
+ val_to_str(server_type, server_vals, "Unknown"),
+ server_type);
+ proto_tree_add_text(s_tree, tvb, cursor+50, 4, "Network: %s",
+ ipxnet_to_string(tvb_get_ptr(tvb, cursor+50, 4)));
+ proto_tree_add_text(s_tree, tvb, cursor+54, 6, "Node: %s",
+ ether_to_str(tvb_get_ptr(tvb, cursor+54, 6)));
+ server_port = tvb_get_ntohs(tvb, cursor+60);
+ proto_tree_add_text(s_tree, tvb, cursor+60, 2, "Socket: %s (0x%04x)",
+ socket_text(server_port),
+ server_port);
+ intermediate_network = tvb_get_ntohs(tvb, cursor+62);
+ proto_tree_add_text(s_tree, tvb, cursor+62, 2,
+ "Intermediate Networks: %d",
+ intermediate_network);
+ }
+ }
+ else { /* queries */
+ proto_tree_add_text(sap_tree, tvb, 2, 2, "Server Type: %s (0x%04X)",
+ val_to_str(query.server_type, server_vals, "Unknown"),
+ query.server_type);
+ }
+ }
+}
+
+void
+proto_register_ipx(void)
+{
+ static hf_register_info hf_ipx[] = {
+ { &hf_ipx_checksum,
+ { "Checksum", "ipx.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_src,
+ { "Source Address", "ipx.src", FT_STRING, BASE_DEC, NULL, 0x0,
+ "Source IPX Address \"network.node\"", HFILL }},
+
+ { &hf_ipx_dst,
+ { "Destination Address", "ipx.dst", FT_STRING, BASE_DEC, NULL, 0x0,
+ "Destination IPX Address \"network.node\"", HFILL }},
+ { &hf_ipx_addr,
+ { "Src/Dst Address", "ipx.addr", FT_STRING, BASE_DEC, NULL, 0x0,
+ "Source or Destination IPX Address \"network.node\"", HFILL }},
+
+ { &hf_ipx_len,
+ { "Length", "ipx.len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_hops,
+ { "Transport Control (Hops)", "ipx.hops", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_packet_type,
+ { "Packet Type", "ipx.packet_type", FT_UINT8, BASE_HEX, VALS(ipx_packet_type_vals),
+ 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_dnet,
+ { "Destination Network","ipx.dst.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_dnode,
+ { "Destination Node", "ipx.dst.node", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_dsocket,
+ { "Destination Socket", "ipx.dst.socket", FT_UINT16, BASE_HEX,
+ VALS(ipx_socket_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_snet,
+ { "Source Network","ipx.src.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_snode,
+ { "Source Node", "ipx.src.node", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_ssocket,
+ { "Source Socket", "ipx.src.socket", FT_UINT16, BASE_HEX,
+ VALS(ipx_socket_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_net,
+ { "Source or Destination Network","ipx.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_node,
+ { "Source or Destination Node", "ipx.node", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_ipx_socket,
+ { "Source or Destination Socket", "ipx.socket", FT_UINT16, BASE_HEX,
+ VALS(ipx_socket_vals), 0x0,
+ "", HFILL }},
+ };
+
+ static hf_register_info hf_spx[] = {
+ { &hf_spx_connection_control,
+ { "Connection Control", "spx.ctl",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_spx_connection_control_sys,
+ { "System Packet", "spx.ctl.sys",
+ FT_BOOLEAN, 8, NULL, SPX_SYS_PACKET,
+ "", HFILL }},
+
+ { &hf_spx_connection_control_send_ack,
+ { "Send Ack", "spx.ctl.send_ack",
+ FT_BOOLEAN, 8, NULL, SPX_SEND_ACK,
+ "", HFILL }},
+
+ { &hf_spx_connection_control_attn,
+ { "Attention", "spx.ctl.attn",
+ FT_BOOLEAN, 8, NULL, SPX_ATTN,
+ "", HFILL }},
+
+ { &hf_spx_connection_control_eom,
+ { "End of Message", "spx.ctl.eom",
+ FT_BOOLEAN, 8, NULL, SPX_EOM,
+ "", HFILL }},
+
+ { &hf_spx_datastream_type,
+ { "Datastream type", "spx.type",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_spx_src_id,
+ { "Source Connection ID", "spx.src",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_spx_dst_id,
+ { "Destination Connection ID", "spx.dst",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_spx_seq_nr,
+ { "Sequence Number", "spx.seq",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_spx_ack_nr,
+ { "Acknowledgment Number", "spx.ack",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_spx_all_nr,
+ { "Allocation Number", "spx.alloc",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_spx_rexmt_frame,
+ { "Retransmitted Frame Number", "spx.rexmt_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ };
+
+ static hf_register_info hf_ipxrip[] = {
+ { &hf_ipxrip_request,
+ { "Request", "ipxrip.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if IPX RIP request", HFILL }},
+
+ { &hf_ipxrip_response,
+ { "Response", "ipxrip.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if IPX RIP response", HFILL }}
+ };
+
+ static hf_register_info hf_sap[] = {
+ { &hf_sap_request,
+ { "Request", "ipxsap.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if SAP request", HFILL }},
+
+ { &hf_sap_response,
+ { "Response", "ipxsap.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if SAP response", HFILL }}
+ };
+
+ static hf_register_info hf_ipxmsg[] = {
+ { &hf_msg_conn,
+ { "Connection Number", "ipxmsg.conn",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Connection Number", HFILL }},
+
+ { &hf_msg_sigchar,
+ { "Signature Char", "ipxmsg.sigchar",
+ FT_UINT8, BASE_DEC, VALS(ipxmsg_sigchar_vals), 0x0,
+ "Signature Char", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_ipx,
+ &ett_spx,
+ &ett_spx_connctrl,
+ &ett_ipxmsg,
+ &ett_ipxrip,
+ &ett_serialization,
+ &ett_ipxsap,
+ &ett_ipxsap_server,
+ };
+
+ proto_ipx = proto_register_protocol("Internetwork Packet eXchange",
+ "IPX", "ipx");
+ proto_register_field_array(proto_ipx, hf_ipx, array_length(hf_ipx));
+
+ register_dissector("ipx", dissect_ipx, proto_ipx);
+
+ proto_spx = proto_register_protocol("Sequenced Packet eXchange",
+ "SPX", "spx");
+ proto_register_field_array(proto_spx, hf_spx, array_length(hf_spx));
+
+ proto_ipxrip = proto_register_protocol("IPX Routing Information Protocol",
+ "IPX RIP", "ipxrip");
+ proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
+
+ proto_serialization = proto_register_protocol("NetWare Serialization Protocol",
+ "NW_SERIAL", "nw_serial");
+
+ proto_ipxmsg = proto_register_protocol("IPX Message", "IPX MSG",
+ "ipxmsg");
+ proto_register_field_array(proto_ipxmsg, hf_ipxmsg, array_length(hf_ipxmsg));
+
+ proto_sap = proto_register_protocol("Service Advertisement Protocol",
+ "IPX SAP", "ipxsap");
+ register_dissector("ipxsap", dissect_ipxsap, proto_sap);
+
+ proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ipx_type_dissector_table = register_dissector_table("ipx.packet_type",
+ "IPX packet type", FT_UINT8, BASE_HEX);
+ ipx_socket_dissector_table = register_dissector_table("ipx.socket",
+ "IPX socket", FT_UINT16, BASE_HEX);
+ spx_socket_dissector_table = register_dissector_table("spx.socket",
+ "SPX socket", FT_UINT16, BASE_HEX);
+
+ register_init_routine(&spx_init_protocol);
+ register_postseq_cleanup_routine(&spx_postseq_cleanup);
+ ipx_tap=register_tap("ipx");
+}
+
+void
+proto_reg_handoff_ipx(void)
+{
+ dissector_handle_t ipx_handle, spx_handle;
+ dissector_handle_t ipxsap_handle, ipxrip_handle;
+ dissector_handle_t serialization_handle, ipxmsg_handle;
+
+ ipx_handle = find_dissector("ipx");
+ dissector_add("udp.port", UDP_PORT_IPX, ipx_handle);
+ dissector_add("ethertype", ETHERTYPE_IPX, ipx_handle);
+ dissector_add("chdlctype", ETHERTYPE_IPX, ipx_handle);
+ dissector_add("ppp.protocol", PPP_IPX, ipx_handle);
+ dissector_add("llc.dsap", SAP_NETWARE1, ipx_handle);
+ dissector_add("llc.dsap", SAP_NETWARE2, ipx_handle);
+ dissector_add("null.type", BSD_AF_IPX, ipx_handle);
+ dissector_add("gre.proto", ETHERTYPE_IPX, ipx_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_IPX, ipx_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_NOVELL_EC, ipx_handle);
+
+ spx_handle = create_dissector_handle(dissect_spx, proto_spx);
+ dissector_add("ipx.packet_type", IPX_PACKET_TYPE_SPX, spx_handle);
+
+ ipxsap_handle = find_dissector("ipxsap");
+ dissector_add("ipx.socket", IPX_SOCKET_SAP, ipxsap_handle);
+
+ ipxrip_handle = create_dissector_handle(dissect_ipxrip, proto_ipxrip);
+ dissector_add("ipx.socket", IPX_SOCKET_IPXRIP, ipxrip_handle);
+
+ serialization_handle = create_dissector_handle(dissect_serialization,
+ proto_serialization);
+ dissector_add("ipx.socket", IPX_SOCKET_SERIALIZATION,
+ serialization_handle);
+
+ ipxmsg_handle = create_dissector_handle(dissect_ipxmsg, proto_ipxmsg);
+ dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE, ipxmsg_handle);
+ dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE1, ipxmsg_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ipx.h b/epan/dissectors/packet-ipx.h
new file mode 100644
index 0000000000..859fd9b09f
--- /dev/null
+++ b/epan/dissectors/packet-ipx.h
@@ -0,0 +1,178 @@
+/* packet-ipx.h
+ * Routines for NetWare's IPX
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ * NDPS support and SPX Defragmentation added by Greg Morris (gmorris@novell.com)
+ *
+ * Portions Copyright (c) by Gilbert Ramirez 2000-2002
+ * Portions Copyright (c) Novell, Inc. 2002-2003
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * ipxlib.h
+ *
+ * Copyright (C) 1995 by Volker Lendecke
+ *
+ */
+
+#ifndef __PACKET_IPX_H__
+#define __PACKET_IPX_H__
+
+#define IPX_NODE_LEN 6
+
+typedef guint32 IPXNet;
+typedef guint16 IPXPort;
+typedef guint8 IPXNode[IPX_NODE_LEN];
+typedef const guint8 CIPXNode[IPX_NODE_LEN];
+
+#define IPX_USER_PTYPE (0x00)
+#define IPX_RIP_PTYPE (0x01)
+#define IPX_SAP_PTYPE (0x04)
+#define IPX_AUTO_PORT (0x0000)
+#define IPX_SAP_PORT (0x0452)
+#define IPX_RIP_PORT (0x0453)
+
+#define IPX_SAP_GENERAL_QUERY (0x0001)
+#define IPX_SAP_GENERAL_RESPONSE (0x0002)
+#define IPX_SAP_NEAREST_QUERY (0x0003)
+#define IPX_SAP_NEAREST_RESPONSE (0x0004)
+
+#define IPX_SAP_FILE_SERVER (0x0004)
+
+struct sap_query
+{
+ guint16 query_type; /* net order */
+ guint16 server_type; /* net order */
+};
+
+#define IPX_RIP_REQUEST (0x1)
+#define IPX_RIP_RESPONSE (0x2)
+
+struct ipx_rip_packet
+{
+ guint16 operation ;
+ struct ipx_rt_def
+ {
+ guint32 network ;
+ guint16 hops ;
+ guint16 ticks ;
+ }
+ rt[1] ;
+};
+
+#define IPX_BROADCAST_NODE ("\xff\xff\xff\xff\xff\xff")
+#define IPX_THIS_NODE ("\0\0\0\0\0\0")
+#define IPX_THIS_NET (0)
+
+#ifndef IPX_NODE_LEN
+#define IPX_NODE_LEN (6)
+#endif
+
+/*
+ * From:
+ *
+ * http://alr.base2co.com:457/netguide/dipxD.ipx_packet_struct.html
+ *
+ * which is part of SCO's "Network Programmer's Guide and Reference".
+ *
+ * It calls type 20 "NetBIOS name packet". Microsoft Network Monitor
+ * calls it "WAN Broadcast"; it's also used for SMB browser announcements,
+ * i.e. NetBIOS (broadcast) datagrams.
+ */
+#define IPX_PACKET_TYPE_IPX 0
+#define IPX_PACKET_TYPE_RIP 1
+#define IPX_PACKET_TYPE_ECHO 2
+#define IPX_PACKET_TYPE_ERROR 3
+#define IPX_PACKET_TYPE_PEP 4
+#define IPX_PACKET_TYPE_SPX 5
+#define IPX_PACKET_TYPE_NCP 17
+#define IPX_PACKET_TYPE_WANBCAST 20 /* propagated NetBIOS packet? */
+
+/* info on these sockets can be found in this listing from Novell:
+
+ http://developer.novell.com/engsup/sample/tids/dsoc1b/dsoc1b.htm
+*/
+
+#define IPX_SOCKET_PING_CISCO 0x0002 /* In cisco this is set with: ipx ping-default cisco */
+#define IPX_SOCKET_NCP 0x0451
+#define IPX_SOCKET_SAP 0x0452
+#define IPX_SOCKET_IPXRIP 0x0453
+#define IPX_SOCKET_NETBIOS 0x0455
+#define IPX_SOCKET_DIAGNOSTIC 0x0456
+#define IPX_SOCKET_SERIALIZATION 0x0457
+#define IPX_SOCKET_NWLINK_SMB_SERVER 0x0550
+#define IPX_SOCKET_NWLINK_SMB_NAMEQUERY 0x0551
+#define IPX_SOCKET_NWLINK_SMB_REDIR 0x0552
+#define IPX_SOCKET_NWLINK_SMB_MAILSLOT 0x0553
+#define IPX_SOCKET_NWLINK_SMB_MESSENGER 0x0554
+#define IPX_SOCKET_NWLINK_SMB_BROWSE 0x0555 /* ? not sure on this
+ but I guessed based on the content of the packet I saw */
+#define IPX_SOCKET_ATTACHMATE_GW 0x055d
+#define IPX_SOCKET_IPX_MESSAGE 0x4001
+#define IPX_SOCKET_IPX_MESSAGE1 0x4003
+#define IPX_SOCKET_ADSM 0x8522 /* www.tivoli.com */
+#define IPX_SOCKET_EIGRP 0x85be /* cisco ipx eigrp */
+#define IPX_SOCKET_NLSP 0x9001 /* NetWare Link Services Protocol */
+#define IPX_SOCKET_IPXWAN 0x9004 /* IPX WAN (RFC 1362, NLSP spec) */
+#define IPX_SOCKET_SNMP_AGENT 0x900F /* RFC 1906 */
+#define IPX_SOCKET_SNMP_SINK 0x9010 /* RFC 1906 */
+#define IPX_SOCKET_PING_NOVELL 0x9086 /* In cisco this is set with: ipx ping-default novell */
+#define IPX_SOCKET_TCP_TUNNEL 0x9091 /* RFC 1791 */
+#define IPX_SOCKET_UDP_TUNNEL 0x9092 /* RFC 1791 */
+#define SPX_SOCKET_PA 0x90b2 /* NDPS Printer Agent */
+#define SPX_SOCKET_BROKER 0x90b3 /* NDPS Broker */
+#define SPX_SOCKET_SRS 0x90b4 /* NDPS Service Registry Service */
+#define SPX_SOCKET_ENS 0x90b5 /* NDPS Event Notification Service */
+#define SPX_SOCKET_RMS 0x90b6 /* NDPS Remote Management Service */
+#define SPX_SOCKET_NOTIFY_LISTENER 0x90b7 /* NDPS Notify Listener */
+
+extern const value_string ipx_socket_vals[];
+
+extern const value_string server_vals[];
+
+void capture_ipx(packet_counts *);
+
+/*
+ * Structure passed to SPX subdissectors, containing information from
+ * the SPX header that might be useful to the subdissector.
+ */
+typedef struct {
+ gboolean eom; /* end-of-message flag in SPX header */
+ guint8 datastream_type; /* datastream type from SPX header */
+} spx_info;
+
+
+
+/* handed off to tap listeners, expand it as is required by what any
+ tap listeners needs */
+typedef struct _ipxhdr_t
+{
+ guint16 ipx_ssocket;
+ guint16 ipx_dsocket;
+ guint16 ipx_length;
+ guint8 ipx_type;
+ address ipx_src;
+ address ipx_dst;
+} ipxhdr_t;
+
+
+#endif
diff --git a/epan/dissectors/packet-ipxwan.c b/epan/dissectors/packet-ipxwan.c
new file mode 100644
index 0000000000..764f9cbc3e
--- /dev/null
+++ b/epan/dissectors/packet-ipxwan.c
@@ -0,0 +1,465 @@
+/* packet-ipxwan.c
+ * Routines for NetWare IPX WAN Protocol
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ipx.h"
+
+/*
+ * See RFC 1362 for version 1 of this protocol; see the NetWare Link
+ * Services Protocol Specification, chapter 3, for version 2.
+ */
+static int proto_ipxwan = -1;
+
+static int hf_ipxwan_identifier = -1;
+static int hf_ipxwan_packet_type = -1;
+static int hf_ipxwan_node_id = -1;
+static int hf_ipxwan_sequence_number = -1;
+static int hf_ipxwan_num_options = -1;
+static int hf_ipxwan_option_num = -1;
+static int hf_ipxwan_accept_option = -1;
+static int hf_ipxwan_option_data_len = -1;
+static int hf_ipxwan_routing_type = -1;
+static int hf_ipxwan_wan_link_delay = -1;
+static int hf_ipxwan_common_network_number = -1;
+static int hf_ipxwan_router_name = -1;
+static int hf_ipxwan_delay = -1;
+static int hf_ipxwan_throughput = -1;
+static int hf_ipxwan_request_size = -1;
+static int hf_ipxwan_delta_time = -1;
+static int hf_ipxwan_extended_node_id = -1;
+static int hf_ipxwan_node_number = -1;
+static int hf_ipxwan_compression_type = -1;
+
+static gint ett_ipxwan = -1;
+static gint ett_ipxwan_option = -1;
+
+static const value_string ipxwan_packet_type_vals[] = {
+ { 0, "Timer Request" },
+ { 1, "Timer Response" },
+ { 2, "Information Request" },
+ { 3, "Information Response" },
+ { 4, "Throughput Request" },
+ { 5, "Throughput Response" },
+ { 6, "Delay Request" },
+ { 7, "Delay Response" },
+ { 0xFF, "NAK" },
+ { 0, NULL }
+};
+
+#define OPT_ROUTING_TYPE 0x00
+#define OPT_RIP_SAP_INFO_EXCHANGE 0x01
+#define OPT_NLSP_INFORMATION 0x02
+#define OPT_NLSP_RAW_THROUGHPUT_DATA 0x03
+#define OPT_EXTENDED_NODE_ID 0x04
+#define OPT_NODE_NUMBER 0x05
+#define OPT_COMPRESSION 0x80
+#define OPT_PAD 0xFF
+
+static const value_string ipxwan_option_num_vals[] = {
+ { OPT_ROUTING_TYPE, "Routing Type" },
+ { OPT_RIP_SAP_INFO_EXCHANGE, "RIP/SAP Info Exchange" },
+ { OPT_NLSP_INFORMATION, "NLSP Information" },
+ { OPT_NLSP_RAW_THROUGHPUT_DATA, "NLSP Raw Throughput Data" },
+ { OPT_EXTENDED_NODE_ID, "Extended Node ID" },
+ { OPT_NODE_NUMBER, "Node Number" },
+ { OPT_COMPRESSION, "Compression" },
+ { OPT_PAD, "Pad" },
+ { 0, NULL }
+};
+
+static const value_string ipxwan_accept_option_vals[] = {
+ { 0, "No" },
+ { 1, "Yes" },
+ { 3, "Not Appplicable" },
+ { 0, NULL }
+};
+
+static const value_string ipxwan_routing_type_vals[] = {
+ { 0, "RIP" },
+ { 1, "NLSP" },
+ { 2, "Unnumbered RIP" },
+ { 3, "On-demand, static routing" },
+ { 4, "Client-router connection" },
+ { 0, NULL }
+};
+
+#define COMP_TYPE_TELEBIT 0
+
+static const value_string ipxwan_compression_type_vals[] = {
+ { COMP_TYPE_TELEBIT, "Telebit" },
+ { 0, NULL }
+};
+
+static void
+dissect_ipxwan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *ipxwan_tree = NULL;
+ int offset = 0;
+ guint8 packet_type;
+ guint8 num_options;
+ guint8 option_number;
+ proto_tree *option_tree;
+ guint16 option_data_len;
+ guint16 wan_link_delay;
+ guint32 delay;
+ guint32 throughput;
+ guint32 delta_time;
+ guint8 compression_type;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX WAN");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ipxwan, tvb, 0, -1,
+ FALSE);
+ ipxwan_tree = proto_item_add_subtree(ti, ett_ipxwan);
+ }
+
+ if (tree) {
+ proto_tree_add_item(ipxwan_tree, hf_ipxwan_identifier, tvb,
+ offset, 4, FALSE);
+ }
+ offset += 4;
+ packet_type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(packet_type, ipxwan_packet_type_vals,
+ "Unknown packet type %u"));
+ }
+ if (tree) {
+ proto_tree_add_uint(ipxwan_tree, hf_ipxwan_packet_type, tvb,
+ offset, 1, packet_type);
+ offset += 1;
+ proto_tree_add_item(ipxwan_tree, hf_ipxwan_node_id, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(ipxwan_tree, hf_ipxwan_sequence_number, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+ num_options = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(ipxwan_tree, hf_ipxwan_num_options, tvb,
+ offset, 1, num_options);
+ offset += 1;
+
+ while (num_options != 0) {
+ option_number = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(ipxwan_tree, tvb, offset, -1,
+ "Option: %s",
+ val_to_str(option_number, ipxwan_option_num_vals,
+ "Unknown (%u)"));
+ option_tree = proto_item_add_subtree(ti,
+ ett_ipxwan_option);
+
+ proto_tree_add_uint(option_tree, hf_ipxwan_option_num,
+ tvb, offset, 1, option_number);
+ offset += 1;
+ proto_tree_add_item(option_tree, hf_ipxwan_accept_option,
+ tvb, offset, 1, FALSE);
+ offset += 1;
+ option_data_len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(option_tree, hf_ipxwan_option_data_len,
+ tvb, offset, 2, option_data_len);
+ offset += 2;
+ proto_item_set_len(ti, option_data_len+4);
+ switch (option_number) {
+
+ case OPT_ROUTING_TYPE:
+ if (option_data_len != 1) {
+ proto_tree_add_text(option_tree,
+ tvb, offset, option_data_len,
+ "Bogus length: %u, should be 1",
+ option_data_len);
+ } else {
+ proto_tree_add_item(option_tree,
+ hf_ipxwan_routing_type, tvb,
+ offset, 1, FALSE);
+ }
+ break;
+
+ case OPT_RIP_SAP_INFO_EXCHANGE:
+ if (option_data_len != 54) {
+ proto_tree_add_text(option_tree,
+ tvb, offset, option_data_len,
+ "Bogus length: %u, should be 54",
+ option_data_len);
+ } else {
+ wan_link_delay = tvb_get_ntohs(tvb,
+ offset);
+ proto_tree_add_uint_format(option_tree,
+ hf_ipxwan_wan_link_delay, tvb,
+ offset, 2, wan_link_delay,
+ "WAN Link Delay: %ums",
+ wan_link_delay);
+ proto_tree_add_item(option_tree,
+ hf_ipxwan_common_network_number,
+ tvb, offset+2, 4, FALSE);
+ proto_tree_add_item(option_tree,
+ hf_ipxwan_router_name, tvb,
+ offset+6, 48, FALSE);
+ }
+ break;
+
+ case OPT_NLSP_INFORMATION:
+ if (option_data_len != 8) {
+ proto_tree_add_text(option_tree,
+ tvb, offset, option_data_len,
+ "Bogus length: %u, should be 8",
+ option_data_len);
+ } else {
+ delay = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(option_tree,
+ hf_ipxwan_delay, tvb,
+ offset, 4, delay,
+ "Delay: %uus", delay);
+ throughput = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(option_tree,
+ hf_ipxwan_throughput, tvb,
+ offset, 4, throughput,
+ "Throughput: %uus",
+ throughput);
+ }
+ break;
+
+ case OPT_NLSP_RAW_THROUGHPUT_DATA:
+ if (option_data_len != 8) {
+ proto_tree_add_text(option_tree,
+ tvb, offset, option_data_len,
+ "Bogus length: %u, should be 8",
+ option_data_len);
+ } else {
+ proto_tree_add_item(option_tree,
+ hf_ipxwan_request_size, tvb,
+ offset, 4, FALSE);
+ delta_time = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(option_tree,
+ hf_ipxwan_delta_time, tvb,
+ offset, 4, delta_time,
+ "Delta Time: %uus",
+ delta_time);
+ }
+ break;
+
+ case OPT_EXTENDED_NODE_ID:
+ if (option_data_len != 4) {
+ proto_tree_add_text(option_tree,
+ tvb, offset, option_data_len,
+ "Bogus length: %u, should be 4",
+ option_data_len);
+ } else {
+ proto_tree_add_item(option_tree,
+ hf_ipxwan_extended_node_id, tvb,
+ offset, 4, FALSE);
+ }
+ break;
+
+ case OPT_NODE_NUMBER:
+ if (option_data_len != 6) {
+ proto_tree_add_text(option_tree,
+ tvb, offset, option_data_len,
+ "Bogus length: %u, should be 6",
+ option_data_len);
+ } else {
+ proto_tree_add_item(option_tree,
+ hf_ipxwan_node_number, tvb,
+ offset, 6, FALSE);
+ }
+ break;
+
+ case OPT_COMPRESSION:
+ if (option_data_len < 1) {
+ proto_tree_add_text(option_tree,
+ tvb, offset, option_data_len,
+ "Bogus length: %u, should be >= 1",
+ option_data_len);
+ } else {
+ compression_type = tvb_get_guint8(tvb,
+ offset);
+ proto_tree_add_uint(option_tree,
+ hf_ipxwan_compression_type, tvb,
+ offset, 1, compression_type);
+ switch (compression_type) {
+
+ case COMP_TYPE_TELEBIT:
+ if (option_data_len < 3) {
+ proto_tree_add_text(option_tree,
+ tvb, offset+1,
+ option_data_len-1,
+ "Bogus length: %u, should be >= 3",
+ option_data_len);
+ } else {
+ proto_tree_add_text(
+ option_tree,
+ tvb, offset+1, 1,
+ "Compression options: 0x%02x",
+ tvb_get_guint8(tvb,
+ offset+1));
+ proto_tree_add_text(
+ option_tree,
+ tvb, offset+2, 1,
+ "Number of compression slots: %u",
+ tvb_get_guint8(tvb,
+ offset+2));
+ }
+ break;
+
+ default:
+ proto_tree_add_text(option_tree,
+ tvb, offset+1,
+ option_data_len-1,
+ "Option parameters");
+ break;
+ }
+ }
+ break;
+
+ case OPT_PAD:
+ proto_tree_add_text(option_tree,
+ tvb, offset, option_data_len,
+ "Padding");
+ break;
+
+ default:
+ proto_tree_add_text(option_tree,
+ tvb, offset, option_data_len,
+ "Option value");
+ break;
+ }
+
+ offset += option_data_len;
+ num_options--;
+ }
+ }
+}
+
+void
+proto_register_ipxwan(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ipxwan_identifier,
+ { "Identifier", "ipxwan.identifier",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_packet_type,
+ { "Packet Type", "ipxwan.packet_type",
+ FT_UINT8, BASE_DEC, VALS(ipxwan_packet_type_vals), 0x0, "",
+ HFILL }},
+
+ { &hf_ipxwan_node_id,
+ { "Node ID", "ipxwan.node_id", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_sequence_number,
+ { "Sequence Number", "ipxwan.sequence_number", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_num_options,
+ { "Number of Options", "ipxwan.num_options", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_option_num,
+ { "Option Number", "ipxwan.option_num", FT_UINT8,
+ BASE_HEX, VALS(ipxwan_option_num_vals), 0x0, "", HFILL }},
+
+ { &hf_ipxwan_accept_option,
+ { "Accept Option", "ipxwan.accept_option", FT_UINT8,
+ BASE_DEC, VALS(ipxwan_accept_option_vals), 0x0, "", HFILL }},
+
+ { &hf_ipxwan_option_data_len,
+ { "Option Data Length", "ipxwan.option_data_len", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_routing_type,
+ { "Routing Type", "ipxwan.routing_type", FT_UINT8,
+ BASE_DEC, VALS(ipxwan_routing_type_vals), 0x0, "", HFILL }},
+
+ { &hf_ipxwan_wan_link_delay,
+ { "WAN Link Delay", "ipxwan.rip_sap_info_exchange.wan_link_delay",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_common_network_number,
+ { "Common Network Number", "ipxwan.rip_sap_info_exchange.common_network_number",
+ FT_IPXNET, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_router_name,
+ { "Router Name", "ipxwan.rip_sap_info_exchange.router_name",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_delay,
+ { "Delay", "ipxwan.nlsp_information.delay",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_throughput,
+ { "Throughput", "ipxwan.nlsp_information.throughput",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_request_size,
+ { "Request Size", "ipxwan.nlsp_raw_throughput_data.request_size",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_delta_time,
+ { "Delta Time", "ipxwan.nlsp_raw_throughput_data.delta_time",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_extended_node_id,
+ { "Extended Node ID", "ipxwan.extended_node_id",
+ FT_IPXNET, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_node_number,
+ { "Node Number", "ipxwan.node_number",
+ FT_ETHER, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_ipxwan_compression_type,
+ { "Compression Type", "ipxwan.compression.type",
+ FT_UINT8, BASE_DEC, VALS(ipxwan_compression_type_vals), 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ipxwan,
+ &ett_ipxwan_option,
+ };
+
+ proto_ipxwan = proto_register_protocol("IPX WAN", "IPX WAN", "ipxwan");
+ proto_register_field_array(proto_ipxwan, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ipxwan(void)
+{
+ dissector_handle_t ipxwan_handle;
+
+ ipxwan_handle = create_dissector_handle(dissect_ipxwan,
+ proto_ipxwan);
+ dissector_add("ipx.socket", IPX_SOCKET_IPXWAN, ipxwan_handle);
+}
diff --git a/epan/dissectors/packet-irc.c b/epan/dissectors/packet-irc.c
new file mode 100644
index 0000000000..66976bed7b
--- /dev/null
+++ b/epan/dissectors/packet-irc.c
@@ -0,0 +1,162 @@
+/* packet-irc.c
+ * Routines for IRC packet dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+static int proto_irc = -1;
+static int hf_irc_request = -1;
+static int hf_irc_response = -1;
+static int hf_irc_command = -1;
+
+static gint ett_irc = -1;
+
+#define TCP_PORT_IRC 6667
+ /* good candidate for dynamic port specification */
+
+static void
+dissect_irc_request(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
+ const char *line, int linelen)
+{
+ proto_tree_add_boolean_hidden(tree, hf_irc_request, tvb, offset, len,
+ TRUE);
+ proto_tree_add_text(tree, tvb, offset, len, "Request Line: %.*s",
+ linelen, line);
+}
+
+static void
+dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
+ const char *line, int linelen)
+{
+ proto_tree_add_boolean_hidden(tree, hf_irc_response, tvb, offset, len,
+ TRUE);
+ proto_tree_add_text(tree, tvb, offset, len, "Response Line: %.*s",
+ linelen, line);
+}
+
+static void
+dissect_irc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *irc_tree, *ti;
+ gint offset = 0;
+ const guchar *line;
+ gint next_offset;
+ int linelen;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IRC");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ (pinfo->match_port == pinfo->destport) ? "Request" : "Response");
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_irc, tvb, 0, -1, FALSE);
+ irc_tree = proto_item_add_subtree(ti, ett_irc);
+
+ /*
+ * Process the packet data, a line at a time.
+ */
+ while (tvb_offset_exists(tvb, offset))
+ {
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1,
+ &next_offset, FALSE);
+
+ /*
+ * Get a buffer that refers to the line (without
+ * the line terminator).
+ */
+ line = tvb_get_ptr(tvb, offset, linelen);
+
+ if (linelen != 0)
+ {
+ if (pinfo->match_port == pinfo->destport)
+ {
+ dissect_irc_request(irc_tree, tvb,
+ offset, next_offset - offset,
+ line, linelen);
+ }
+ else
+ {
+ dissect_irc_response(irc_tree, tvb,
+ offset, next_offset - offset,
+ line, linelen);
+ }
+ }
+ offset = next_offset;
+ }
+ }
+}
+
+void
+proto_register_irc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_irc_response,
+ { "Response", "irc.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if IRC response", HFILL }},
+
+ { &hf_irc_request,
+ { "Request", "irc.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if IRC request", HFILL }},
+
+ { &hf_irc_command,
+ { "Command", "irc.command",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Command associated with request", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_irc,
+ };
+ proto_irc = proto_register_protocol("Internet Relay Chat", "IRC", "irc");
+ proto_register_field_array(proto_irc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_irc(void)
+{
+ dissector_handle_t irc_handle;
+
+ irc_handle = create_dissector_handle(dissect_irc, proto_irc);
+ dissector_add("tcp.port", TCP_PORT_IRC, irc_handle);
+}
diff --git a/epan/dissectors/packet-isakmp.c b/epan/dissectors/packet-isakmp.c
new file mode 100644
index 0000000000..6092c7ef2d
--- /dev/null
+++ b/epan/dissectors/packet-isakmp.c
@@ -0,0 +1,1720 @@
+/* packet-isakmp.c
+ * Routines for the Internet Security Association and Key Management Protocol
+ * (ISAKMP) (RFC 2408) and the Internet IP Security Domain of Interpretation
+ * for ISAKMP (RFC 2407)
+ * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/ipv6-utils.h>
+#include "ipproto.h"
+
+#define isakmp_min(a, b) ((a<b) ? a : b)
+
+static int proto_isakmp = -1;
+
+static gint ett_isakmp = -1;
+static gint ett_isakmp_flags = -1;
+static gint ett_isakmp_payload = -1;
+
+#define UDP_PORT_ISAKMP 500
+#define TCP_PORT_ISAKMP 500
+
+#define NUM_PROTO_TYPES 5
+#define proto2str(t) \
+ ((t < NUM_PROTO_TYPES) ? prototypestr[t] : "UNKNOWN-PROTO-TYPE")
+
+static const char *prototypestr[NUM_PROTO_TYPES] = {
+ "RESERVED",
+ "ISAKMP",
+ "IPSEC_AH",
+ "IPSEC_ESP",
+ "IPCOMP"
+};
+
+#define NUM_P1_ATT_TYPES 17
+#define p1_atttype2str(t) \
+ ((t < NUM_P1_ATT_TYPES) ? p1_atttypestr[t] : "UNKNOWN-ATTRIBUTE-TYPE")
+
+static const char *p1_atttypestr[NUM_P1_ATT_TYPES] = {
+ "UNKNOWN-ATTRIBUTE-TYPE",
+ "Encryption-Algorithm",
+ "Hash-Algorithm",
+ "Authentication-Method",
+ "Group-Description",
+ "Group-Type",
+ "Group-Prime",
+ "Group-Generator-One",
+ "Group-Generator-Two",
+ "Group-Curve-A",
+ "Group-Curve-B",
+ "Life-Type",
+ "Life-Duration",
+ "PRF",
+ "Key-Length",
+ "Field-Size",
+ "Group-Order"
+};
+
+#define NUM_ATT_TYPES 11
+#define atttype2str(t) \
+ ((t < NUM_ATT_TYPES) ? atttypestr[t] : "UNKNOWN-ATTRIBUTE-TYPE")
+
+static const char *atttypestr[NUM_ATT_TYPES] = {
+ "UNKNOWN-ATTRIBUTE-TYPE",
+ "SA-Life-Type",
+ "SA-Life-Duration",
+ "Group-Description",
+ "Encapsulation-Mode",
+ "Authentication-Algorithm",
+ "Key-Length",
+ "Key-Rounds",
+ "Compress-Dictinary-Size",
+ "Compress-Private-Algorithm",
+ "ECN Tunnel"
+};
+
+#define NUM_TRANS_TYPES 2
+#define trans2str(t) \
+ ((t < NUM_TRANS_TYPES) ? transtypestr[t] : "UNKNOWN-TRANS-TYPE")
+
+static const char *transtypestr[NUM_TRANS_TYPES] = {
+ "RESERVED",
+ "KEY_IKE"
+};
+
+#define NUM_AH_TRANS_TYPES 8
+#define ah_trans2str(t) \
+ ((t < NUM_AH_TRANS_TYPES) ? ah_transtypestr[t] : "UNKNOWN-AH-TRANS-TYPE")
+
+static const char *ah_transtypestr[NUM_AH_TRANS_TYPES] = {
+ "RESERVED",
+ "RESERVED",
+ "MD5",
+ "SHA",
+ "DES",
+ "SHA2-256",
+ "SHA2-384",
+ "SHA2-512"
+};
+
+#define NUM_ESP_TRANS_TYPES 13
+#define esp_trans2str(t) \
+ ((t < NUM_ESP_TRANS_TYPES) ? esp_transtypestr[t] : "UNKNOWN-ESP-TRANS-TYPE")
+
+static const char *esp_transtypestr[NUM_ESP_TRANS_TYPES] = {
+ "RESERVED",
+ "DES-IV64",
+ "DES",
+ "3DES",
+ "RC5",
+ "IDEA",
+ "CAST",
+ "BLOWFISH",
+ "3IDEA",
+ "DES-IV32",
+ "RC4",
+ "NULL",
+ "AES"
+};
+
+#define NUM_IPCOMP_TRANS_TYPES 5
+#define ipcomp_trans2str(t) \
+ ((t < NUM_IPCOMP_TRANS_TYPES) ? ipcomp_transtypestr[t] : "UNKNOWN-IPCOMP-TRANS-TYPE")
+
+static const char *ipcomp_transtypestr[NUM_IPCOMP_TRANS_TYPES] = {
+ "RESERVED",
+ "OUI",
+ "DEFLATE",
+ "LZS",
+ "LZJH"
+};
+
+#define NUM_ID_TYPES 12
+#define id2str(t) \
+ ((t < NUM_ID_TYPES) ? idtypestr[t] : "UNKNOWN-ID-TYPE")
+
+static const char *idtypestr[NUM_ID_TYPES] = {
+ "RESERVED",
+ "IPV4_ADDR",
+ "FQDN",
+ "USER_FQDN",
+ "IPV4_ADDR_SUBNET",
+ "IPV6_ADDR",
+ "IPV6_ADDR_SUBNET",
+ "IPV4_ADDR_RANGE",
+ "IPV6_ADDR_RANGE",
+ "DER_ASN1_DN",
+ "DER_ASN1_GN",
+ "KEY_ID"
+};
+
+#define NUM_GRPDESC_TYPES 19
+#define grpdesc2str(t) ((t < NUM_GRPDESC_TYPES) ? grpdescstr[t] : "UNKNOWN-GROUP-DESCRIPTION")
+
+static const char *grpdescstr[NUM_GRPDESC_TYPES] = {
+ "UNDEFINED - 0",
+ "Default 768-bit MODP group",
+ "Alternate 1024-bit MODP group",
+ "EC2N group on GP[2^155] group",
+ "EC2N group on GP[2^185] group",
+ "1536 bit MODP group",
+ "EC2N group over GF[2^163]",
+ "EC2N group over GF[2^163]",
+ "EC2N group over GF[2^283]",
+ "EC2N group over GF[2^283]",
+ "EC2N group over GF[2^409]",
+ "EC2N group over GF[2^409]",
+ "EC2N group over GF[2^571]",
+ "EC2N group over GF[2^571]",
+ "2048 bit MODP group",
+ "3072 bit MODP group",
+ "4096 bit MODP group",
+ "6144 bit MODP group",
+ "8192 bit MODP group",
+};
+
+struct isakmp_hdr {
+ guint8 icookie[8];
+ guint8 rcookie[8];
+ guint8 next_payload;
+ guint8 version;
+ guint8 exch_type;
+ guint8 flags;
+#define E_FLAG 0x01
+#define C_FLAG 0x02
+#define A_FLAG 0x04
+ guint32 message_id;
+ guint32 length;
+};
+
+static proto_tree *dissect_payload_header(tvbuff_t *, int, int, guint8,
+ guint8 *, guint16 *, proto_tree *);
+
+static void dissect_sa(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_proposal(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_transform(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_key_exch(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_id(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_cert(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_certreq(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_hash(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_sig(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_nonce(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_notif(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_delete(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_vid(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_config(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_nat_discovery(tvbuff_t *, int, int, proto_tree *, int);
+static void dissect_nat_original_address(tvbuff_t *, int, int, proto_tree *, int);
+
+static const char *payloadtype2str(guint8);
+static const char *exchtype2str(guint8);
+static const char *doitype2str(guint32);
+static const char *msgtype2str(guint16);
+static const char *situation2str(guint32);
+static const char *value2str(int, guint16, guint32);
+static const char *attrtype2str(guint8);
+static const char *cfgattrident2str(guint16);
+static const char *certtype2str(guint8);
+
+static gboolean get_num(tvbuff_t *, int, guint16, guint32 *);
+
+#define LOAD_TYPE_NONE 0 /* payload type for None */
+#define LOAD_TYPE_PROPOSAL 2 /* payload type for Proposal */
+#define LOAD_TYPE_TRANSFORM 3 /* payload type for Transform */
+#define NUM_LOAD_TYPES 17
+#define loadtype2str(t) \
+ ((t < NUM_LOAD_TYPES) ? strfuncs[t].str : "Unknown payload type")
+
+static struct strfunc {
+ const char * str;
+ void (*func)(tvbuff_t *, int, int, proto_tree *, int);
+} strfuncs[NUM_LOAD_TYPES] = {
+ {"NONE", NULL },
+ {"Security Association", dissect_sa },
+ {"Proposal", dissect_proposal },
+ {"Transform", dissect_transform },
+ {"Key Exchange", dissect_key_exch },
+ {"Identification", dissect_id },
+ {"Certificate", dissect_cert },
+ {"Certificate Request", dissect_certreq },
+ {"Hash", dissect_hash },
+ {"Signature", dissect_sig },
+ {"Nonce", dissect_nonce },
+ {"Notification", dissect_notif },
+ {"Delete", dissect_delete },
+ {"Vendor ID", dissect_vid },
+ {"Attrib", dissect_config },
+ {"NAT-Discovery", dissect_nat_discovery }, /* draft-ietf-ipsec-nat-t-ike */
+ {"NAT-Original Address", dissect_nat_original_address } /* draft-ietf-ipsec-nat-t-ike */
+};
+
+#define VID_LEN 16
+#define VID_MS_LEN 20
+static const guint8 VID_MS_W2K_WXP[VID_MS_LEN] = {0x1E, 0x2B, 0x51, 0x69, 0x5, 0x99, 0x1C, 0x7D, 0x7C, 0x96, 0xFC, 0xBF, 0xB5, 0x87, 0xE4, 0x61, 0x0, 0x0, 0x0, 0x2}; /* according to http://www.microsoft.com/technet/treeview/default.asp?url=/technet/columns/cableguy/cg0602.asp */
+
+#define VID_CP_LEN 20
+static const guint8 VID_CP[VID_CP_LEN] = {0xF4, 0xED, 0x19, 0xE0, 0xC1, 0x14, 0xEB, 0x51, 0x6F, 0xAA, 0xAC, 0x0E, 0xE3, 0x7D, 0xAF, 0x28, 0x7, 0xB4, 0x38, 0x1F};
+
+static const guint8 VID_CYBERGUARD[VID_LEN] = {0x9A, 0xA1, 0xF3, 0xB4, 0x34, 0x72, 0xA4, 0x5D, 0x5F, 0x50, 0x6A, 0xEB, 0x26, 0xC, 0xF2, 0x14};
+
+static const guint8 VID_draft_ietf_ipsec_nat_t_ike_03[VID_LEN] = {0x7D, 0x94, 0x19, 0xA6, 0x53, 0x10, 0xCA, 0x6F, 0x2C, 0x17, 0x9D, 0x92, 0x15, 0x52, 0x9d, 0x56}; /* according to http://www.ietf.org/internet-drafts/draft-ietf-ipsec-nat-t-ike-03.txt */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_1_1_0[VID_LEN] = {0xfB, 0xF4, 0x76, 0x14, 0x98, 0x40, 0x31, 0xFA, 0x8E, 0x3B, 0xB6, 0x19, 0x80, 0x89, 0xB2, 0x23}; /* Ssh Communications Security IPSEC Express version 1.1.0 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_1_1_1[VID_LEN] = {0x19, 0x52, 0xDC, 0x91, 0xAC, 0x20, 0xF6, 0x46, 0xFB, 0x01, 0xCF, 0x42, 0xA3, 0x3A, 0xEE, 0x30}; /* Ssh Communications Security IPSEC Express version 1.1.1 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_1_1_2[VID_LEN] = {0xE8, 0xBF, 0xFA, 0x64, 0x3E, 0x5C, 0x8F, 0x2C, 0xD1, 0x0F, 0xDA, 0x73, 0x70, 0xB6, 0xEB, 0xE5}; /* Ssh Communications Security IPSEC Express version 1.1.2 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_1_2_1[VID_LEN] = {0xC1, 0x11, 0x1B, 0x2D, 0xEE, 0x8C, 0xBC, 0x3D, 0x62, 0x05, 0x73, 0xEC, 0x57, 0xAA, 0xB9, 0xCB}; /* Ssh Communications Security IPSEC Express version 1.2.1 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_1_2_2[VID_LEN] = {0x09, 0xEC, 0x27, 0xBF, 0xBC, 0x09, 0xC7, 0x58, 0x23, 0xCF, 0xEC, 0xBF, 0xFE, 0x56, 0x5A, 0x2E}; /* Ssh Communications Security IPSEC Express version 1.2.2 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_2_0_0[VID_LEN] = {0x7F, 0x21, 0xA5, 0x96, 0xE4, 0xE3, 0x18, 0xF0, 0xB2, 0xF4, 0x94, 0x4C, 0x23, 0x84, 0xCB, 0x84}; /* SSH Communications Security IPSEC Express version 2.0.0 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_2_1_0[VID_LEN] = {0x28, 0x36, 0xD1, 0xFD, 0x28, 0x07, 0xBC, 0x9E, 0x5A, 0xE3, 0x07, 0x86, 0x32, 0x04, 0x51, 0xEC}; /* SSH Communications Security IPSEC Express version 2.1.0 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_2_1_1[VID_LEN] = {0xA6, 0x8D, 0xE7, 0x56, 0xA9, 0xC5, 0x22, 0x9B, 0xAE, 0x66, 0x49, 0x80, 0x40, 0x95, 0x1A, 0xD5}; /* SSH Communications Security IPSEC Express version 2.1.1 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_2_1_2[VID_LEN] = {0x3F, 0x23, 0x72, 0x86, 0x7E, 0x23, 0x7C, 0x1C, 0xD8, 0x25, 0x0A, 0x75, 0x55, 0x9C, 0xAE, 0x20}; /* SSH Communications Security IPSEC Express version 2.1.2 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_3_0_0[VID_LEN] = {0x0E, 0x58, 0xD5, 0x77, 0x4D, 0xF6, 0x02, 0x00, 0x7D, 0x0B, 0x02, 0x44, 0x36, 0x60, 0xF7, 0xEB}; /* SSH Communications Security IPSEC Express version 3.0.0 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_3_0_1[VID_LEN] = {0xF5, 0xCE, 0x31, 0xEB, 0xC2, 0x10, 0xF4, 0x43, 0x50, 0xCF, 0x71, 0x26, 0x5B, 0x57, 0x38, 0x0F}; /* SSH Communications Security IPSEC Express version 3.0.1 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_4_0_0[VID_LEN] = {0xF6, 0x42, 0x60, 0xAF, 0x2E, 0x27, 0x42, 0xDA, 0xDD, 0xD5, 0x69, 0x87, 0x06, 0x8A, 0x99, 0xA0}; /* SSH Communications Security IPSEC Express version 4.0.0 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_4_0_1[VID_LEN] = {0x7A, 0x54, 0xD3, 0xBD, 0xB3, 0xB1, 0xE6, 0xD9, 0x23, 0x89, 0x20, 0x64, 0xBE, 0x2D, 0x98, 0x1C}; /* SSH Communications Security IPSEC Express version 4.0.1 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_4_1_0[VID_LEN] = {0x9A, 0xA1, 0xF3, 0xB4, 0x34, 0x72, 0xA4, 0x5D, 0x5F, 0x50, 0x6A, 0xEB, 0x26, 0x0C, 0xF2, 0x14}; /* SSH Communications Security IPSEC Express version 4.1.0 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_4_1_1[VID_LEN] = {0x89, 0xF7, 0xB7, 0x60, 0xD8, 0x6B, 0x01, 0x2A, 0xCF, 0x26, 0x33, 0x82, 0x39, 0x4D, 0x96, 0x2F}; /* SSH Communications Security IPSEC Express version 4.1.1 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_5_0[VID_LEN] = {0xB0, 0x37, 0xA2, 0x1A, 0xCE, 0xCC, 0xB5, 0x57, 0x0F, 0x60, 0x25, 0x46, 0xF9, 0x7B, 0xDE, 0x8C}; /* SSH Communications Security IPSEC Express version 5.0 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_5_0_0[VID_LEN] = {0x2B, 0x2D, 0xAD, 0x97, 0xC4, 0xD1, 0x40, 0x93, 0x00, 0x53, 0x28, 0x7F, 0x99, 0x68, 0x50, 0xB0}; /* SSH Communications Security IPSEC Express version 5.0.0 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_5_1_0[VID_LEN] = {0x45, 0xE1, 0x7F, 0x3A, 0xBE, 0x93, 0x94, 0x4C, 0xB2, 0x02, 0x91, 0x0C, 0x59, 0xEF, 0x80, 0x6B}; /* SSH Communications Security IPSEC Express version 5.1.0 */
+
+static const guint8 VID_SSH_IPSEC_EXPRESS_5_1_1[VID_LEN] = {0x59, 0x25, 0x85, 0x9F, 0x73, 0x77, 0xED, 0x78, 0x16, 0xD2, 0xFB, 0x81, 0xC0, 0x1F, 0xA5, 0x51}; /* SSH Communications Security IPSEC Express version 5.1.1 */
+
+static const guint8 VID_SSH_SENTINEL[VID_LEN] = {0x05, 0x41, 0x82, 0xA0, 0x7C, 0x7A, 0xE2, 0x06, 0xF9, 0xD2, 0xCF, 0x9D, 0x24, 0x32, 0xC4, 0x82}; /* SSH Sentinel */
+
+static const guint8 VID_SSH_SENTINEL_1_1[VID_LEN] = {0xB9, 0x16, 0x23, 0xE6, 0x93, 0xCA, 0x18, 0xA5, 0x4C, 0x6A, 0x27, 0x78, 0x55, 0x23, 0x05, 0xE8}; /* SSH Sentinel 1.1 */
+
+static const guint8 VID_SSH_SENTINEL_1_2[VID_LEN] = {0x54, 0x30, 0x88, 0x8D, 0xE0, 0x1A, 0x31, 0xA6, 0xFA, 0x8F, 0x60, 0x22, 0x4E, 0x44, 0x99, 0x58}; /* SSH Sentinel 1.2 */
+
+static const guint8 VID_SSH_SENTINEL_1_3[VID_LEN] = {0x7E, 0xE5, 0xCB, 0x85, 0xF7, 0x1C, 0xE2, 0x59, 0xC9, 0x4A, 0x5C, 0x73, 0x1E, 0xE4, 0xE7, 0x52}; /* SSH Sentinel 1.3 */
+
+static const guint8 VID_SSH_QUICKSEC_0_9_0[VID_LEN] = {0x37, 0xEB, 0xA0, 0xC4, 0x13, 0x61, 0x84, 0xE7, 0xDA, 0xF8, 0x56, 0x2A, 0x77, 0x06, 0x0B, 0x4A}; /* SSH Communications Security QuickSec 0.9.0 */
+
+static const guint8 VID_SSH_QUICKSEC_1_1_0[VID_LEN] = {0x5D, 0x72, 0x92, 0x5E, 0x55, 0x94, 0x8A, 0x96, 0x61, 0xA7, 0xFC, 0x48, 0xFD, 0xEC, 0x7F, 0xF9}; /* SSH Communications Security QuickSec 1.1.0 */
+
+static const guint8 VID_SSH_QUICKSEC_1_1_1[VID_LEN] = {0x77, 0x7F, 0xBF, 0x4C, 0x5A, 0xF6, 0xD1, 0xCD, 0xD4, 0xB8, 0x95, 0xA0, 0x5B, 0xF8, 0x25, 0x94}; /* SSH Communications Security QuickSec 1.1.1 */
+
+static const guint8 VID_SSH_QUICKSEC_1_1_2[VID_LEN] = {0x2C, 0xDF, 0x08, 0xE7, 0x12, 0xED, 0xE8, 0xA5, 0x97, 0x87, 0x61, 0x26, 0x7C, 0xD1, 0x9B, 0x91}; /* SSH Communications Security QuickSec 1.1.2 */
+
+static const guint8 VID_SSH_QUICKSEC_1_1_3[VID_LEN] = {0x59, 0xE4, 0x54, 0xA8, 0xC2, 0xCF, 0x02, 0xA3, 0x49, 0x59, 0x12, 0x1F, 0x18, 0x90, 0xBC, 0x87}; /* SSH Communications Security QuickSec 1.1.3 */
+
+static const guint8 VID_draft_huttunen_ipsec_esp_in_udp_01[VID_LEN] = {0x50, 0x76, 0x0F, 0x62, 0x4C, 0x63, 0xE5, 0xC5, 0x3E, 0xEA, 0x38, 0x6C, 0x68, 0x5C, 0xA0, 0x83}; /* draft-huttunen-ipsec-esp-in-udp-01.txt */
+
+static const guint8 VID_draft_stenberg_ipsec_nat_traversal_01[VID_LEN] = {0x27, 0xBA, 0xB5, 0xDC, 0x01, 0xEA, 0x07, 0x60, 0xEA, 0x4E, 0x31, 0x90, 0xAC, 0x27, 0xC0, 0xD0}; /* draft-stenberg-ipsec-nat-traversal-01 */
+
+static const guint8 VID_draft_stenberg_ipsec_nat_traversal_02[VID_LEN]= {0x61, 0x05, 0xC4, 0x22, 0xE7, 0x68, 0x47, 0xE4, 0x3F, 0x96, 0x84, 0x80, 0x12, 0x92, 0xAE, 0xCD}; /* draft-stenberg-ipsec-nat-traversal-02 */
+
+static const guint8 VID_draft_ietf_ipsec_nat_t_ike_00[VID_LEN]= {0x44, 0x85, 0x15, 0x2D, 0x18, 0xB6, 0xBB, 0xCD, 0x0B, 0xE8, 0xA8, 0x46, 0x95, 0x79, 0xDD, 0xCC}; /* draft-ietf-ipsec-nat-t-ike-00 */
+
+static const guint8 VID_draft_ietf_ipsec_nat_t_ike_02a[VID_LEN]= {0xCD, 0x60, 0x46, 0x43, 0x35, 0xDF, 0x21, 0xF8, 0x7C, 0xFD, 0xB2, 0xFC, 0x68, 0xB6, 0xA4, 0x48}; /* draft-ietf-ipsec-nat-t-ike-02 */
+
+static const guint8 VID_draft_ietf_ipsec_nat_t_ike_02b[VID_LEN]= {0x90, 0xCB, 0x80, 0x91, 0x3E, 0xBB, 0x69, 0x6E, 0x08, 0x63, 0x81, 0xB5, 0xEC, 0x42, 0x7B, 0x1F}; /* draft-ietf-ipsec-nat-t-ike-02 */
+
+static const guint8 VID_draft_beaulieu_ike_xauth_02[VID_LEN]= {0x09, 0x00, 0x26, 0x89, 0xDF, 0xD6, 0xB7, 0x12, 0x80, 0xA2, 0x24, 0xDE, 0xC3, 0x3B, 0x81, 0xE5}; /* draft-beaulieu-ike-xauth-02.txt */
+
+
+static const guint8 VID_rfc3706_dpd[VID_LEN]= {0xAF, 0xCA,0xD7, 0x13, 0x68, 0xA1, 0xF1, 0xC9, 0x6B, 0x86, 0x96, 0xFC, 0x77, 0x57, 0x01, 0x00}; /* RFC 3706 */
+
+static const guint8 VID_IKE_CHALLENGE_RESPONSE_1[VID_LEN]= {0xBA, 0x29, 0x04, 0x99, 0xC2, 0x4E, 0x84, 0xE5, 0x3A, 0x1D, 0x83, 0xA0, 0x5E, 0x5F, 0x00, 0xC9}; /* IKE Challenge/Response for Authenticated Cryptographic Keys */
+
+static const guint8 VID_IKE_CHALLENGE_RESPONSE_2[VID_LEN]= {0x0D, 0x33, 0x61, 0x1A, 0x5D, 0x52, 0x1B, 0x5E, 0x3C, 0x9C, 0x03, 0xD2, 0xFC, 0x10, 0x7E, 0x12}; /* IKE Challenge/Response for Authenticated Cryptographic Keys */
+
+static const guint8 VID_IKE_CHALLENGE_RESPONSE_REV_1[VID_LEN]= {0xAD, 0x32, 0x51, 0x04, 0x2C, 0xDC, 0x46, 0x52, 0xC9, 0xE0, 0x73, 0x4C, 0xE5, 0xDE, 0x4C, 0x7D}; /* IKE Challenge/Response for Authenticated Cryptographic Keys (Revised) */
+
+static const guint8 VID_IKE_CHALLENGE_RESPONSE_REV_2[VID_LEN]= {0x01, 0x3F, 0x11, 0x82, 0x3F, 0x96, 0x6F, 0xA9, 0x19, 0x00, 0xF0, 0x24, 0xBA, 0x66, 0xA8, 0x6B}; /* IKE Challenge/Response for Authenticated Cryptographic Keys (Revised) */
+
+static const guint8 VID_MS_L2TP_IPSEC_VPN_CLIENT[VID_LEN]= {0x40, 0x48, 0xB7, 0xD5, 0x6E, 0xBC, 0xE8, 0x85, 0x25, 0xE7, 0xDE, 0x7F, 0x00, 0xD6, 0xC2, 0xD3}; /* Microsoft L2TP/IPSec VPN Client */
+
+static const guint8 VID_GSS_API_1[VID_LEN]= {0xB4, 0x6D, 0x89, 0x14, 0xF3, 0xAA, 0xA3, 0xF2, 0xFE, 0xDE, 0xB7, 0xC7, 0xDB, 0x29, 0x43, 0xCA}; /* A GSS-API Authentication Method for IKE */
+
+static const guint8 VID_GSS_API_2[VID_LEN]= {0xAD, 0x2C, 0x0D, 0xD0, 0xB9, 0xC3, 0x20, 0x83, 0xCC, 0xBA, 0x25, 0xB8, 0x86, 0x1E, 0xC4, 0x55}; /* A GSS-API Authentication Method for IKE */
+
+static const guint8 VID_GSSAPI[VID_LEN]= {0x62, 0x1B, 0x04, 0xBB, 0x09, 0x88, 0x2A, 0xC1, 0xE1, 0x59, 0x35, 0xFE, 0xFA, 0x24, 0xAE, 0xEE}; /* GSSAPI */
+
+static const guint8 VID_MS_NT5_ISAKMPOAKLEY[VID_LEN]= {0x1E, 0x2B, 0x51, 0x69, 0x05, 0x99, 0x1C, 0x7D, 0x7C, 0x96, 0xFC, 0xBF, 0xB5, 0x87, 0xE4, 0x61}; /* MS NT5 ISAKMPOAKLEY */
+
+static const guint8 VID_CISCO_UNITY[VID_LEN]= {0x12, 0xF5, 0xF2, 0x8C, 0x45, 0x71, 0x68, 0xA9, 0x70, 0x2D, 0x9F, 0xE2, 0x74, 0xCC, 0x02, 0xD4}; /* CISCO-UNITY */
+
+#define VID_LEN_8 8
+static const guint8 VID_draft_ietf_ipsec_antireplay_00[VID_LEN_8]= {0x32, 0x5D, 0xF2, 0x9A, 0x23, 0x19, 0xF2, 0xDD}; /* draft-ietf-ipsec-antireplay-00.txt */
+
+static const guint8 VID_draft_ietf_ipsec_heartbeats_00[VID_LEN_8]= {0x8D, 0xB7, 0xA4, 0x18, 0x11, 0x22, 0x16, 0x60}; /* draft-ietf-ipsec-heartbeats-00.txt */
+
+/*
+* Seen in Netscreen. Suppose to be ASCII HeartBeat_Notify - but I don't know the rest yet. I suspect it then proceeds with
+* 8k10, which means every 8K (?), and version 1.0 of the protocol (?). I won't add it to the code, until I know what it really
+* means. ykaul-at-netvision.net.il
+*/
+static const guint8 VID_HeartBeat_Notify[VID_LEN] = {0x48, 0x65, 0x61, 0x72, 0x74, 0x42, 0x65, 0x61, 0x74, 0x5f, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79};
+
+static void
+dissect_payloads(tvbuff_t *tvb, proto_tree *tree, guint8 initial_payload,
+ int offset, int length)
+{
+ guint8 payload, next_payload;
+ guint16 payload_length;
+ proto_tree * ntree;
+
+ for (payload = initial_payload; length != 0; payload = next_payload) {
+ if (payload == LOAD_TYPE_NONE) {
+ /*
+ * What? There's more stuff in this chunk of data, but the
+ * previous payload had a "next payload" type of None?
+ */
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Extra data: %s",
+ tvb_bytes_to_str(tvb, offset, length));
+ break;
+ }
+ ntree = dissect_payload_header(tvb, offset, length, payload,
+ &next_payload, &payload_length, tree);
+ if (ntree == NULL)
+ break;
+ if (payload_length >= 4) { /* XXX = > 4? */
+ if (payload < NUM_LOAD_TYPES && strfuncs[payload].func != NULL) {
+ (*strfuncs[payload].func)(tvb, offset + 4, payload_length - 4, ntree,
+ -1);
+ }
+ else {
+ proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4,
+ "Payload");
+ }
+ }
+ else {
+ proto_tree_add_text(ntree, tvb, offset + 4, 0,
+ "Payload (bogus, length is %u, must be at least 4)",
+ payload_length);
+ payload_length = 4;
+ }
+ offset += payload_length;
+ length -= payload_length;
+ }
+}
+
+static void
+dissect_isakmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ struct isakmp_hdr hdr;
+ proto_item * ti;
+ proto_tree * isakmp_tree = NULL;
+ guint32 len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISAKMP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_isakmp, tvb, offset, -1, FALSE);
+ isakmp_tree = proto_item_add_subtree(ti, ett_isakmp);
+ }
+
+ hdr.length = tvb_get_ntohl(tvb, offset + sizeof(hdr) - sizeof(hdr.length));
+ hdr.exch_type = tvb_get_guint8(tvb, sizeof(hdr.icookie) + sizeof(hdr.rcookie) + sizeof(hdr.next_payload) + sizeof(hdr.version));
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, exchtype2str(hdr.exch_type));
+
+ if (tree) {
+ tvb_memcpy(tvb, (guint8 *)&hdr.icookie, offset, sizeof(hdr.icookie));
+ proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.icookie),
+ "Initiator cookie: 0x%s", tvb_bytes_to_str(tvb, offset, sizeof(hdr.icookie)));
+ offset += sizeof(hdr.icookie);
+
+ tvb_memcpy(tvb, (guint8 *)&hdr.rcookie, offset, sizeof(hdr.rcookie));
+ proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.rcookie),
+ "Responder cookie: 0x%s", tvb_bytes_to_str(tvb, offset, sizeof(hdr.rcookie)));
+ offset += sizeof(hdr.rcookie);
+
+ hdr.next_payload = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.next_payload),
+ "Next payload: %s (%u)",
+ payloadtype2str(hdr.next_payload), hdr.next_payload);
+ offset += sizeof(hdr.next_payload);
+
+ hdr.version = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.version),
+ "Version: %u.%u",
+ hi_nibble(hdr.version), lo_nibble(hdr.version));
+ offset += sizeof(hdr.version);
+
+ hdr.exch_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.exch_type),
+ "Exchange type: %s (%u)",
+ exchtype2str(hdr.exch_type), hdr.exch_type);
+ offset += sizeof(hdr.exch_type);
+
+ {
+ proto_item * fti;
+ proto_tree * ftree;
+
+ hdr.flags = tvb_get_guint8(tvb, offset);
+ fti = proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.flags), "Flags");
+ ftree = proto_item_add_subtree(fti, ett_isakmp_flags);
+
+ proto_tree_add_text(ftree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(hdr.flags, E_FLAG, sizeof(hdr.flags)*8,
+ "Encryption", "No encryption"));
+ proto_tree_add_text(ftree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(hdr.flags, C_FLAG, sizeof(hdr.flags)*8,
+ "Commit", "No commit"));
+ proto_tree_add_text(ftree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(hdr.flags, A_FLAG, sizeof(hdr.flags)*8,
+ "Authentication", "No authentication"));
+ offset += sizeof(hdr.flags);
+ }
+
+ proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.message_id),
+ "Message ID: 0x%s", tvb_bytes_to_str(tvb, offset, sizeof(hdr.message_id)));
+ offset += sizeof(hdr.message_id);
+
+ if (hdr.length < sizeof(hdr)) {
+ proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.length),
+ "Length: (bogus, length is %u, should be at least %lu)",
+ hdr.length, (unsigned long)sizeof(hdr));
+ return;
+ }
+
+ proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr.length),
+ "Length: %u", hdr.length);
+ offset += sizeof(hdr.length);
+
+ len = hdr.length - sizeof(hdr);
+
+ if (hdr.flags & E_FLAG) {
+ if (len && isakmp_tree) {
+ proto_tree_add_text(isakmp_tree, tvb, offset, len,
+ "Encrypted payload (%d byte%s)",
+ len, plurality(len, "", "s"));
+ }
+ } else
+ dissect_payloads(tvb, isakmp_tree, hdr.next_payload, offset, len);
+ }
+}
+
+static proto_tree *
+dissect_payload_header(tvbuff_t *tvb, int offset, int length, guint8 payload,
+ guint8 *next_payload_p, guint16 *payload_length_p, proto_tree *tree)
+{
+ guint8 next_payload;
+ guint16 payload_length;
+ proto_item * ti;
+ proto_tree * ntree;
+
+ if (length < 4) {
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Not enough room in payload for all transforms");
+ return NULL;
+ }
+ next_payload = tvb_get_guint8(tvb, offset);
+ payload_length = tvb_get_ntohs(tvb, offset + 2);
+
+ ti = proto_tree_add_text(tree, tvb, offset, payload_length,
+ "%s payload", loadtype2str(payload));
+ ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
+
+ proto_tree_add_text(ntree, tvb, offset, 1,
+ "Next payload: %s (%u)",
+ payloadtype2str(next_payload), next_payload);
+ proto_tree_add_text(ntree, tvb, offset+2, 2, "Length: %u", payload_length);
+
+ *next_payload_p = next_payload;
+ *payload_length_p = payload_length;
+ return ntree;
+}
+
+static void
+dissect_sa(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint32 doi;
+ guint32 situation;
+
+ if (length < 4) {
+ proto_tree_add_text(tree, tvb, offset, length,
+ "DOI %s (length is %u, should be >= 4)",
+ tvb_bytes_to_str(tvb, offset, length), length);
+ return;
+ }
+ doi = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Domain of interpretation: %s (%u)",
+ doitype2str(doi), doi);
+ offset += 4;
+ length -= 4;
+
+ if (doi == 1) {
+ /* IPSEC */
+ if (length < 4) {
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Situation: %s (length is %u, should be >= 4)",
+ tvb_bytes_to_str(tvb, offset, length), length);
+ return;
+ }
+ situation = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Situation: %s (%u)",
+ situation2str(situation), situation);
+ offset += 4;
+ length -= 4;
+
+ dissect_payloads(tvb, tree, LOAD_TYPE_PROPOSAL, offset, length);
+ } else {
+ /* Unknown */
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Situation: %s",
+ tvb_bytes_to_str(tvb, offset, length));
+ }
+}
+
+static void
+dissect_proposal(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint8 protocol_id;
+ guint8 spi_size;
+ guint8 num_transforms;
+ guint8 next_payload;
+ guint16 payload_length;
+ proto_tree * ntree;
+ guint8 proposal_num;
+
+ proposal_num = tvb_get_guint8(tvb, offset);
+
+ proto_item_append_text(tree, " # %d",proposal_num);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Proposal number: %u", proposal_num);
+ offset += 1;
+ length -= 1;
+
+ protocol_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Protocol ID: %s (%u)",
+ proto2str(protocol_id), protocol_id);
+ offset += 1;
+ length -= 1;
+
+ spi_size = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "SPI size: %u", spi_size);
+ offset += 1;
+ length -= 1;
+
+ num_transforms = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Number of transforms: %u", num_transforms);
+ offset += 1;
+ length -= 1;
+
+ if (spi_size) {
+ proto_tree_add_text(tree, tvb, offset, spi_size, "SPI: %s",
+ tvb_bytes_to_str(tvb, offset, spi_size));
+ offset += spi_size;
+ length -= spi_size;
+ }
+
+ while (num_transforms > 0) {
+ ntree = dissect_payload_header(tvb, offset, length, LOAD_TYPE_TRANSFORM,
+ &next_payload, &payload_length, tree);
+ if (ntree == NULL)
+ break;
+ if (length < payload_length) {
+ proto_tree_add_text(tree, tvb, offset + 4, length,
+ "Not enough room in payload for all transforms");
+ break;
+ }
+ if (payload_length >= 4)
+ dissect_transform(tvb, offset + 4, payload_length - 4, ntree, protocol_id);
+ else
+ proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4, "Payload");
+ offset += payload_length;
+ length -= payload_length;
+ num_transforms--;
+ }
+}
+
+static void
+dissect_transform(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int protocol_id)
+{
+ guint8 transform_id;
+ guint8 transform_num;
+
+ transform_num = tvb_get_guint8(tvb, offset);
+ proto_item_append_text(tree," # %d",transform_num);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Transform number: %u", transform_num);
+ offset += 1;
+ length -= 1;
+
+ transform_id = tvb_get_guint8(tvb, offset);
+ switch (protocol_id) {
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Transform ID: %u", transform_id);
+ break;
+ case 1: /* ISAKMP */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Transform ID: %s (%u)",
+ trans2str(transform_id), transform_id);
+ break;
+ case 2: /* AH */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Transform ID: %s (%u)",
+ ah_trans2str(transform_id), transform_id);
+ break;
+ case 3: /* ESP */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Transform ID: %s (%u)",
+ esp_trans2str(transform_id), transform_id);
+ break;
+ case 4: /* IPCOMP */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Transform ID: %s (%u)",
+ ipcomp_trans2str(transform_id), transform_id);
+ break;
+ }
+ offset += 3;
+ length -= 3;
+
+ while (length>0) {
+ const char *str;
+ int ike_phase1 = 0;
+ guint16 aft = tvb_get_ntohs(tvb, offset);
+ guint16 type = aft & 0x7fff;
+ guint16 len;
+ guint32 val;
+ guint pack_len;
+
+ if (protocol_id == 1 && transform_id == 1) {
+ ike_phase1 = 1;
+ str = p1_atttype2str(type);
+ }
+ else {
+ str = atttype2str(type);
+ }
+
+ if (aft & 0x8000) {
+ val = tvb_get_ntohs(tvb, offset + 2);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "%s (%u): %s (%u)",
+ str, type,
+ value2str(ike_phase1, type, val), val);
+ offset += 4;
+ length -= 4;
+ }
+ else {
+ len = tvb_get_ntohs(tvb, offset + 2);
+ pack_len = 4 + len;
+ if (!get_num(tvb, offset + 4, len, &val)) {
+ proto_tree_add_text(tree, tvb, offset, pack_len,
+ "%s (%u): <too big (%u bytes)>",
+ str, type, len);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, pack_len,
+ "%s (%u): %s (%u)",
+ str, type,
+ value2str(ike_phase1, type, val), val);
+ }
+ offset += pack_len;
+ length -= pack_len;
+ }
+ }
+}
+
+static void
+dissect_key_exch(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "Key Exchange Data");
+}
+
+static void
+dissect_id(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint8 id_type;
+ guint8 protocol_id;
+ guint16 port;
+
+ id_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "ID type: %s (%u)", id2str(id_type), id_type);
+ offset += 1;
+ length -= 1;
+
+ protocol_id = tvb_get_guint8(tvb, offset);
+ if (protocol_id == 0) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Protocol ID: Unused");
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Protocol ID: %s (%u)",
+ ipprotostr(protocol_id), protocol_id);
+ }
+ offset += 1;
+ length -= 1;
+
+ port = tvb_get_ntohs(tvb, offset);
+ if (port == 0)
+ proto_tree_add_text(tree, tvb, offset, 2, "Port: Unused");
+ else
+ proto_tree_add_text(tree, tvb, offset, 2, "Port: %u", port);
+ offset += 2;
+ length -= 2;
+
+ switch (id_type) {
+ case 1:
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Identification data: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ break;
+ case 2:
+ case 3:
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Identification data: %.*s", length,
+ tvb_get_ptr(tvb, offset, length));
+ break;
+ case 4:
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Identification data: %s/%s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)),
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, length, "Identification Data");
+ break;
+ }
+}
+
+static void
+dissect_cert(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint8 cert_enc;
+
+ cert_enc = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Certificate encoding: %u - %s",
+ cert_enc, certtype2str(cert_enc));
+ offset += 1;
+ length -= 1;
+
+ proto_tree_add_text(tree, tvb, offset, length, "Certificate Data");
+}
+
+static void
+dissect_certreq(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint8 cert_type;
+
+ cert_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Certificate type: %u - %s",
+ cert_type, certtype2str(cert_type));
+ offset += 1;
+ length -= 1;
+
+ proto_tree_add_text(tree, tvb, offset, length, "Certificate Authority");
+}
+
+static void
+dissect_hash(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "Hash Data");
+}
+
+static void
+dissect_sig(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "Signature Data");
+}
+
+static void
+dissect_nonce(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "Nonce Data");
+}
+
+static void
+dissect_notif(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint32 doi;
+ guint8 protocol_id;
+ guint8 spi_size;
+ guint16 msgtype;
+
+ doi = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Domain of Interpretation: %s (%u)",
+ doitype2str(doi), doi);
+ offset += 4;
+ length -= 4;
+
+ protocol_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Protocol ID: %s (%u)",
+ proto2str(protocol_id), protocol_id);
+ offset += 1;
+ length -= 1;
+
+ spi_size = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "SPI size: %u", spi_size);
+ offset += 1;
+ length -= 1;
+
+ msgtype = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Message type: %s (%u)", msgtype2str(msgtype), msgtype);
+ offset += 2;
+ length -= 2;
+
+ if (spi_size) {
+ proto_tree_add_text(tree, tvb, offset, spi_size, "Security Parameter Index");
+ offset += spi_size;
+ length -= spi_size;
+ }
+
+ if (length > 0)
+ proto_tree_add_text(tree, tvb, offset, length, "Notification Data");
+}
+
+static void
+dissect_delete(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint32 doi;
+ guint8 protocol_id;
+ guint8 spi_size;
+ guint16 num_spis;
+ guint16 i;
+
+ doi = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Domain of Interpretation: %s (%u)",
+ doitype2str(doi), doi);
+ offset += 4;
+ length -= 4;
+
+ protocol_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Protocol ID: %s (%u)",
+ proto2str(protocol_id), protocol_id);
+ offset += 1;
+ length -= 1;
+
+ spi_size = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "SPI size: %u", spi_size);
+ offset += 1;
+ length -= 1;
+
+ num_spis = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Number of SPIs: %u", num_spis);
+ offset += 2;
+ length -= 2;
+
+ for (i = 0; i < num_spis; ++i) {
+ if (length < spi_size) {
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Not enough room in payload for all SPI's");
+ break;
+ }
+ proto_tree_add_text(tree, tvb, offset, spi_size,
+ "SPI (%d)", i);
+ offset += spi_size;
+ length -= spi_size;
+ }
+}
+
+static void
+dissect_vid(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint32 CPproduct, CPversion;
+ const guint8 * pVID;
+ proto_item * pt;
+ proto_tree * ntree;
+ pVID = tvb_get_ptr(tvb, offset, length);
+ pt = proto_tree_add_text(tree, tvb, offset, length, "Vendor ID: ");
+ if (memcmp(pVID, VID_MS_W2K_WXP, isakmp_min(VID_MS_LEN, length)) == 0)
+ proto_item_append_text(pt, "Microsoft Win2K/WinXP");
+ else
+ if (memcmp(pVID, VID_CP, isakmp_min(VID_CP_LEN, length)) == 0)
+ {
+ proto_item_append_text(pt, "Check Point");
+ offset += VID_CP_LEN;
+ CPproduct = tvb_get_ntohl(tvb, offset);
+ ntree = proto_item_add_subtree(pt, ett_isakmp_payload);
+ pt = proto_tree_add_text(ntree, tvb, offset, sizeof(CPproduct), "Check Point Product: ");
+ switch (CPproduct) {
+ case 1: proto_item_append_text(pt, "VPN-1");
+ break;
+ case 2: proto_item_append_text(pt, "SecuRemote/SecureClient");
+ break;
+ default: proto_item_append_text(pt, "Unknown CP product!");
+ break;
+ }
+ offset += sizeof(CPproduct);
+ CPversion = tvb_get_ntohl(tvb, offset);
+ pt = proto_tree_add_text(ntree, tvb, offset, length, "Version: ");
+ switch (CPversion) {
+ case 2: proto_item_append_text(pt, "4.1");
+ break;
+ case 3: proto_item_append_text(pt, "4.1 SP-1");
+ break;
+ case 4002: proto_item_append_text(pt, "4.1 (SP-2 or above)");
+ break;
+ case 5000: proto_item_append_text(pt, "NG");
+ break;
+ case 5001: proto_item_append_text(pt, "NG Feature Pack 1");
+ break;
+ case 5002: proto_item_append_text(pt, "NG Feature Pack 2");
+ break;
+ case 5003: proto_item_append_text(pt, "NG Feature Pack 3");
+ break;
+ case 5004: proto_item_append_text(pt, "NG with Application Intelligence");
+ break;
+ case 5005: proto_item_append_text(pt, "NG with Application Intelligence R55");
+ break;
+ default: proto_item_append_text(pt, " Unknown CP version!");
+ break;
+ }
+ }
+ else
+ if (memcmp(pVID, VID_CYBERGUARD, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Cyber Guard");
+ else
+ if (memcmp(pVID, VID_draft_ietf_ipsec_nat_t_ike_03, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-03");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_1_1_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.1.0");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_1_1_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.1.1");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_1_1_2, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.1.2");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_1_2_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.2.1");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_1_2_2, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 1.2.2");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_2_0_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.0.0");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_2_1_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.1.0");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_2_1_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.1.1");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_2_1_2, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 2.1.2");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_3_0_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 3.0.0");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_3_0_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 3.0.1");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_4_0_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.0.0");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_4_0_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.0.1");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_4_1_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.1.0");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_4_1_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 4.1.1");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_5_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.0");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_5_0_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.0.0");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_5_1_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.1.0");
+ else
+ if (memcmp(pVID, VID_SSH_IPSEC_EXPRESS_5_1_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Ssh Communications Security IPSEC Express version 5.1.1");
+ else
+ if (memcmp(pVID, VID_SSH_SENTINEL, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "SSH Sentinel");
+ else
+ if (memcmp(pVID, VID_SSH_SENTINEL_1_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "SSH Sentinel 1.1");
+ else
+ if (memcmp(pVID, VID_SSH_SENTINEL_1_2, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "SSH Sentinel 1.2");
+ else
+ if (memcmp(pVID, VID_SSH_SENTINEL_1_3, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "SSH Sentinel 1.3");
+ else
+ if (memcmp(pVID, VID_SSH_QUICKSEC_0_9_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "SSH Communications Security QuickSec 0.9.0");
+ else
+ if (memcmp(pVID, VID_SSH_QUICKSEC_1_1_0, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.0");
+ else
+ if (memcmp(pVID, VID_SSH_QUICKSEC_1_1_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.1");
+ else
+ if (memcmp(pVID, VID_SSH_QUICKSEC_1_1_2, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.2");
+ else
+ if (memcmp(pVID, VID_SSH_QUICKSEC_1_1_3, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "SSH Communications Security QuickSec 1.1.3");
+ else
+ if (memcmp(pVID, VID_draft_huttunen_ipsec_esp_in_udp_01, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "draft-huttunen-ipsec-esp-in-udp-01.txt");
+ else
+ if (memcmp(pVID, VID_draft_stenberg_ipsec_nat_traversal_01, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "draft-stenberg-ipsec-nat-traversal-01");
+ else
+ if (memcmp(pVID, VID_draft_stenberg_ipsec_nat_traversal_02, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "draft-stenberg-ipsec-nat-traversal-02");
+ else
+ if (memcmp(pVID, VID_draft_ietf_ipsec_nat_t_ike_00, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-00");
+ else
+ if (memcmp(pVID, VID_draft_ietf_ipsec_nat_t_ike_02a, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-02");
+ else
+ if (memcmp(pVID, VID_draft_ietf_ipsec_nat_t_ike_02b, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "draft-ietf-ipsec-nat-t-ike-02");
+ else
+ if (memcmp(pVID, VID_draft_beaulieu_ike_xauth_02, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "draft-beaulieu-ike-xauth-02.txt");
+ else
+ if (memcmp(pVID, VID_rfc3706_dpd, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "RFC 3706 Detecting Dead IKE Peers (DPD)");
+ else
+ if (memcmp(pVID, VID_IKE_CHALLENGE_RESPONSE_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys");
+ else
+ if (memcmp(pVID, VID_IKE_CHALLENGE_RESPONSE_2, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys");
+ else
+ if (memcmp(pVID, VID_IKE_CHALLENGE_RESPONSE_REV_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys (Revised)");
+ else
+ if (memcmp(pVID, VID_IKE_CHALLENGE_RESPONSE_REV_2, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "IKE Challenge/Response for Authenticated Cryptographic Keys (Revised)");
+ else
+ if (memcmp(pVID, VID_MS_L2TP_IPSEC_VPN_CLIENT, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "Microsoft L2TP/IPSec VPN Client");
+ else
+ if (memcmp(pVID, VID_GSS_API_1, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "A GSS-API Authentication Method for IKE");
+ else
+ if (memcmp(pVID, VID_GSS_API_2, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "A GSS-API Authentication Method for IKE");
+ else
+ if (memcmp(pVID, VID_GSSAPI, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "GSSAPI");
+ else
+ if (memcmp(pVID, VID_MS_NT5_ISAKMPOAKLEY, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "MS NT5 ISAKMPOAKLEY");
+ else
+ if (memcmp(pVID, VID_CISCO_UNITY, isakmp_min(VID_LEN, length)) == 0)
+ proto_item_append_text(pt, "CISCO-UNITY");
+ else
+ if (memcmp(pVID, VID_draft_ietf_ipsec_antireplay_00, isakmp_min(VID_LEN_8, length)) == 0)
+ proto_item_append_text(pt, "draft-ietf-ipsec-antireplay-00.txt");
+ else
+ if (memcmp(pVID, VID_draft_ietf_ipsec_heartbeats_00, isakmp_min(VID_LEN_8, length)) == 0)
+ proto_item_append_text(pt, "draft-ietf-ipsec-heartbeats-00.txt");
+ else
+ proto_item_append_text(pt, "unknown vendor ID: 0x%s",tvb_bytes_to_str(tvb, offset, length));
+}
+
+static void
+dissect_config(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint8 type;
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Type %s (%u)",attrtype2str(type),type);
+
+ offset += 2;
+ length -= 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Identifier: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ length -= 2;
+
+ while(length>0) {
+ guint16 aft = tvb_get_ntohs(tvb, offset);
+ guint16 type = aft & 0x7fff;
+ guint16 len;
+ guint32 val;
+ guint pack_len;
+
+ if (aft & 0x8000) {
+ val = tvb_get_ntohs(tvb, offset + 2);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "%s (%u)", cfgattrident2str(type), val);
+ offset += 4;
+ length -= 4;
+ }
+ else {
+ len = tvb_get_ntohs(tvb, offset + 2);
+ pack_len = 4 + len;
+ if (!get_num(tvb, offset + 4, len, &val)) {
+ proto_tree_add_text(tree, tvb, offset, pack_len,
+ "%s: <too big (%u bytes)>",
+ cfgattrident2str(type), len);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "%s (%ue)", cfgattrident2str(type),
+ val);
+ }
+ offset += pack_len;
+ length -= pack_len;
+ }
+ }
+}
+
+static void
+dissect_nat_discovery(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Hash of address and port: %s",
+ tvb_bytes_to_str(tvb, offset, length));
+}
+
+static void
+dissect_nat_original_address(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
+ int unused _U_)
+{
+ guint8 id_type;
+ guint32 addr_ipv4;
+ struct e_in6_addr addr_ipv6;
+
+ id_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "ID type: %s (%u)", id2str(id_type), id_type);
+ offset += 1;
+ length -= 1;
+
+ offset += 3; /* reserved */
+ length -= 3;
+
+ switch (id_type) {
+
+ case 1: /* ID_IPV4_ADDR */
+ if (length == 4) {
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv4, offset, length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Original address: %s",
+ ip_to_str((guint8 *)&addr_ipv4));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Original address: bad length, should be 4, is %u",
+ length);
+ }
+ break;
+
+ case 5: /* ID_IPV6_ADDR */
+ if (length == 16) {
+ tvb_memcpy(tvb, (guint8 *)&addr_ipv6, offset, length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Original address: %s",
+ ip6_to_str(&addr_ipv6));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Original address: bad length, should be 16, is %u",
+ length);
+ }
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Original address: bad address type");
+ break;
+ }
+}
+
+static const char *
+payloadtype2str(guint8 type) {
+
+ if (type < NUM_LOAD_TYPES)
+ return strfuncs[type].str;
+ if (type < 128)
+ return "RESERVED";
+ return "Private USE";
+}
+
+static const char *
+exchtype2str(guint8 type) {
+
+#define NUM_EXCHSTRS 7
+ static const char * exchstrs[NUM_EXCHSTRS] = {
+ "NONE",
+ "Base",
+ "Identity Protection (Main Mode)",
+ "Authentication Only",
+ "Aggressive",
+ "Informational",
+ "Transaction (Config Mode)"
+ };
+
+ if (type < NUM_EXCHSTRS) return exchstrs[type];
+ if (type < 32) return "ISAKMP Future Use";
+ switch (type) {
+ case 32:
+ return "Quick Mode";
+ case 33:
+ return "New Group Mode";
+ }
+ if (type < 240)
+ return "DOI Specific Use";
+ return "Private Use";
+}
+
+static const char *
+doitype2str(guint32 type) {
+ if (type == 1) return "IPSEC";
+ return "Unknown DOI Type";
+}
+
+static const char *
+msgtype2str(guint16 type) {
+
+#define NUM_PREDEFINED 31
+ static const char *msgs[NUM_PREDEFINED] = {
+ "<UNKNOWN>",
+ "INVALID-PAYLOAD-TYPE",
+ "DOI-NOT-SUPPORTED",
+ "SITUATION-NOT-SUPPORTED",
+ "INVALID-COOKIE",
+ "INVALID-MAJOR-VERSION",
+ "INVALID-MINOR-VERSION",
+ "INVALID-EXCHANGE-TYPE",
+ "INVALID-FLAGS",
+ "INVALID-MESSAGE-ID",
+ "INVALID-PROTOCOL-ID",
+ "INVALID-SPI",
+ "INVALID-TRANSFORM-ID",
+ "ATTRIBUTES-NOT-SUPPORTED",
+ "NO-PROPOSAL-CHOSEN",
+ "BAD-PROPOSAL-SYNTAX",
+ "PAYLOAD-MALFORMED",
+ "INVALID-KEY-INFORMATION",
+ "INVALID-ID-INFORMATION",
+ "INVALID-CERT-ENCODING",
+ "INVALID-CERTIFICATE",
+ "CERT-TYPE-UNSUPPORTED",
+ "INVALID-CERT-AUTHORITY",
+ "INVALID-HASH-INFORMATION",
+ "AUTHENTICATION-FAILED",
+ "INVALID-SIGNATURE",
+ "ADDRESS-NOTIFICATION",
+ "NOTIFY-SA-LIFETIME",
+ "CERTIFICATE-UNAVAILABLE",
+ "UNSUPPORTED-EXCHANGE-TYPE",
+ "UNEQUAL-PAYLOAD-LENGTHS"
+ };
+
+ if (type < NUM_PREDEFINED) return msgs[type];
+ if (type < 8192) return "RESERVED (Future Use)";
+ if (type < 16384) return "Private Use";
+ if (type < 16385) return "CONNECTED";
+ if (type < 24576) return "RESERVED (Future Use) - status";
+ if (type < 24577) return "RESPONDER-LIFETIME";
+ if (type < 24578) return "REPLAY-STATUS";
+ if (type < 24579) return "INITIAL-CONTACT";
+ if (type < 32768) return "DOI-specific codes";
+ if (type < 40960) return "Private Use - status";
+ if (type < 65535) return "RESERVED (Future Use) - status (2)";
+
+ return "Huh? You should never see this! Shame on you!";
+}
+
+static const char *
+situation2str(guint32 type) {
+
+#define SIT_MSG_NUM 1024
+#define SIT_IDENTITY 0x01
+#define SIT_SECRECY 0x02
+#define SIT_INTEGRITY 0x04
+
+ static char msg[SIT_MSG_NUM];
+ int n = 0;
+ char * sep = "";
+ int ret;
+
+ if (type & SIT_IDENTITY) {
+ ret = snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep);
+ if (ret == -1 || ret >= SIT_MSG_NUM-n) {
+ /* Truncated. */
+ msg[SIT_MSG_NUM-1] = '\0';
+ return msg;
+ }
+ n += ret;
+ sep = " & ";
+ }
+ if (type & SIT_SECRECY) {
+ if (n >= SIT_MSG_NUM) {
+ /* No more room. */
+ return msg;
+ }
+ ret = snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep);
+ if (ret == -1 || ret >= SIT_MSG_NUM-n) {
+ /* Truncated. */
+ msg[SIT_MSG_NUM-1] = '\0';
+ return msg;
+ }
+ n += ret;
+ sep = " & ";
+ }
+ if (type & SIT_INTEGRITY) {
+ if (n >= SIT_MSG_NUM) {
+ /* No more room. */
+ return msg;
+ }
+ ret = snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep);
+ if (ret == -1 || ret >= SIT_MSG_NUM-n) {
+ /* Truncated. */
+ msg[SIT_MSG_NUM-1] = '\0';
+ return msg;
+ }
+ n += ret;
+ sep = " & ";
+ }
+
+ return msg;
+}
+
+static const char *
+value2str(int ike_p1, guint16 att_type, guint32 value) {
+
+ if (value == 0) return "RESERVED";
+
+ if (!ike_p1) {
+ switch (att_type) {
+ case 1:
+ switch (value) {
+ case 0: return "RESERVED";
+ case 1: return "Seconds";
+ case 2: return "Kilobytes";
+ default: return "UNKNOWN-SA-VALUE";
+ }
+ case 2:
+ return "Duration-Value";
+ case 3:
+ return "Group-Value";
+ case 4:
+ switch (value) {
+ case 0: return "RESERVED";
+ case 1: return "Tunnel";
+ case 2: return "Transport";
+ case 3: return "UDP-Encapsulated-Tunnel"; /* http://www.ietf.org/internet-drafts/draft-ietf-ipsec-nat-t-ike-05.txt */
+ case 4: return "UDP-Encapsulated-Transport"; /* http://www.ietf.org/internet-drafts/draft-ietf-ipsec-nat-t-ike-05.txt */
+ case 61440: return "Check Point IPSec UDP Encapsulation";
+ case 61443: return "UDP-Encapsulated-Tunnel (draft)";
+ case 61444: return "UDP-Encapsulated-Transport (draft)";
+ default: return "UNKNOWN-ENCAPSULATION-VALUE";
+ }
+ case 5:
+ switch (value) {
+ case 0: return "RESERVED";
+ case 1: return "HMAC-MD5";
+ case 2: return "HMAC-SHA";
+ case 3: return "DES-MAC";
+ case 4: return "KPDK";
+ case 5: return "HMAC-SHA2-256";
+ case 6: return "HMAC-SHA2-384";
+ case 7: return "HMAC-SHA2-512";
+ default: return "UNKNOWN-AUTHENTICATION-VALUE";
+ }
+ case 6:
+ return "Key-Length";
+ case 7:
+ return "Key-Rounds";
+ case 8:
+ return "Compress-Dictionary-size";
+ case 9:
+ return "Compress Private Algorithm";
+ default: return "UNKNOWN-ATTRIBUTE-TYPE";
+ }
+ }
+ else {
+ switch (att_type) {
+ case 1:
+ switch (value) {
+ case 1: return "DES-CBC";
+ case 2: return "IDEA-CBC";
+ case 3: return "BLOWFISH-CBC";
+ case 4: return "RC5-R16-B64-CBC";
+ case 5: return "3DES-CBC";
+ case 6: return "CAST-CBC";
+ case 7: return "AES-CBC";
+ default: return "UNKNOWN-ENCRYPTION-ALG";
+ }
+ case 2:
+ switch (value) {
+ case 1: return "MD5";
+ case 2: return "SHA";
+ case 3: return "TIGER";
+ case 4: return "SHA2-256";
+ case 5: return "SHA2-384";
+ case 6: return "SHA2-512";
+ default: return "UNKNOWN-HASH-ALG";
+ }
+ case 3:
+ switch (value) {
+ case 1: return "PSK";
+ case 2: return "DSS-SIG";
+ case 3: return "RSA-SIG";
+ case 4: return "RSA-ENC";
+ case 5: return "RSA-Revised-ENC";
+ case 6: return "Encryption with El-Gamal";
+ case 7: return "Revised encryption with El-Gamal";
+ case 8: return "ECDSA signatures";
+ case 9: return "AES-XCBC-MAC";
+ case 64221: return "HybridInitRSA";
+ case 64222: return "HybridRespRSA";
+ case 64223: return "HybridInitDSS";
+ case 64224: return "HybridRespDSS";
+ case 65001: return "XAUTHInitPreShared";
+ case 65002: return "XAUTHRespPreShared";
+ case 65003: return "XAUTHInitDSS";
+ case 65004: return "XAUTHRespDSS";
+ case 65005: return "XAUTHInitRSA";
+ case 65006: return "XAUTHRespRSA";
+ case 65007: return "XAUTHInitRSAEncryption";
+ case 65008: return "XAUTHRespRSAEncryption";
+ case 65009: return "XAUTHInitRSARevisedEncryption";
+ case 65010: return "XAUTHRespRSARevisedEncryption";
+ default: return "UNKNOWN-AUTH-METHOD";
+ }
+ case 4: return grpdesc2str(value);
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 16:
+ return "Group-Value";
+ case 5:
+ switch (value) {
+ case 1: return "MODP";
+ case 2: return "ECP";
+ case 3: return "EC2N";
+ default: return "UNKNOWN-GROUPT-TYPE";
+ }
+ case 11:
+ switch (value) {
+ case 1: return "Seconds";
+ case 2: return "Kilobytes";
+ default: return "UNKNOWN-SA-VALUE";
+ }
+ case 12:
+ return "Duration-Value";
+ case 13:
+ return "PRF-Value";
+ case 14:
+ return "Key-Length";
+ case 15:
+ return "Field-Size";
+ default: return "UNKNOWN-ATTRIBUTE-TYPE";
+ }
+ }
+}
+
+static const char *
+attrtype2str(guint8 type) {
+ switch (type) {
+ case 0: return "Reserved";
+ case 1: return "ISAKMP_CFG_REQUEST";
+ case 2: return "ISAKMP_CFG_REPLY";
+ case 3: return "ISAKMP_CFG_SET";
+ case 4: return "ISAKMP_CFG_ACK";
+ }
+ if(type < 127)
+ return "Future use";
+ return "Private use";
+}
+
+static const char *
+cfgattrident2str(guint16 ident) {
+#define NUM_ATTR_DEFINED 12
+ static const char *msgs[NUM_PREDEFINED] = {
+ "RESERVED",
+ "INTERNAL_IP4_ADDRESS",
+ "INTERNAL_IP4_NETMASK",
+ "INTERNAL_IP4_DNS",
+ "INTERNAL_IP4_NBNS",
+ "INTERNAL_ADDRESS_EXPIREY",
+ "INTERNAL_IP4_DHCP",
+ "APPLICATION_VERSION"
+ "INTERNAL_IP6_ADDRESS",
+ "INTERNAL_IP6_NETMASK",
+ "INTERNAL_IP6_DNS",
+ "INTERNAL_IP6_NBNS",
+ "INTERNAL_IP6_DHCP",
+ };
+ if(ident < NUM_ATTR_DEFINED)
+ return msgs[ident];
+ if(ident < 16383)
+ return "Future use";
+ switch(ident) {
+ case 16520: return "XAUTH_TYPE";
+ case 16521: return "XAUTH_USER_NAME";
+ case 16522: return "XAUTH_USER_PASSWORD";
+ case 16523: return "XAUTH_PASSCODE";
+ case 16524: return "XAUTH_MESSAGE";
+ case 16525: return "XAUTH_CHALLANGE";
+ case 16526: return "XAUTH_DOMAIN";
+ case 16527: return "XAUTH_STATUS";
+ case 16528: return "XAUTH_NEXT_PIN";
+ case 16529: return "XAUTH_ANSWER";
+ default: return "Private use";
+ }
+}
+
+static const char *
+certtype2str(guint8 type) {
+#define NUM_CERTTYPE 11
+ static const char *msgs[NUM_CERTTYPE] = {
+ "NONE",
+ "PKCS #7 wrapped X.509 certificate",
+ "PGP Certificate",
+ "DNS Signed Key",
+ "X.509 Certificate - Signature",
+ "X.509 Certificate - Key Exchange",
+ "Kerberos Tokens",
+ "Certificate Revocation List (CRL)",
+ "Authority Revocation List (ARL)",
+ "SPKI Certificate",
+ "X.509 Certificate - Attribute",
+ };
+ if(type > NUM_CERTTYPE)
+ return "RESERVED";
+ return msgs[type];
+}
+
+static gboolean
+get_num(tvbuff_t *tvb, int offset, guint16 len, guint32 *num_p) {
+
+ switch (len) {
+ case 1:
+ *num_p = tvb_get_guint8(tvb, offset);
+ break;
+ case 2:
+ *num_p = tvb_get_ntohs(tvb, offset);
+ break;
+ case 3:
+ *num_p = tvb_get_ntoh24(tvb, offset);
+ break;
+ case 4:
+ *num_p = tvb_get_ntohl(tvb, offset);
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+proto_register_isakmp(void)
+{
+/* static hf_register_info hf[] = {
+ { &variable,
+ { "Name", "isakmp.abbreviation", TYPE, VALS_POINTER }},
+ };*/
+ static gint *ett[] = {
+ &ett_isakmp,
+ &ett_isakmp_flags,
+ &ett_isakmp_payload,
+ };
+
+ proto_isakmp = proto_register_protocol("Internet Security Association and Key Management Protocol",
+ "ISAKMP", "isakmp");
+/* proto_register_field_array(proto_isakmp, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("isakmp", dissect_isakmp, proto_isakmp);
+}
+
+void
+proto_reg_handoff_isakmp(void)
+{
+ dissector_handle_t isakmp_handle;
+
+ isakmp_handle = find_dissector("isakmp");
+ dissector_add("udp.port", UDP_PORT_ISAKMP, isakmp_handle);
+ dissector_add("tcp.port", TCP_PORT_ISAKMP, isakmp_handle);
+}
diff --git a/epan/dissectors/packet-iscsi.c b/epan/dissectors/packet-iscsi.c
new file mode 100644
index 0000000000..c141535e6c
--- /dev/null
+++ b/epan/dissectors/packet-iscsi.c
@@ -0,0 +1,2511 @@
+/* packet-iscsi.c
+ * Routines for iSCSI dissection
+ * Copyright 2001, Eurologic and Mark Burton <markb@ordern.com>
+ * 2004 Request/Response matching and Service Response Time: ronnie sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include <epan/conversation.h>
+#include "packet-scsi.h"
+#include "epan/nstime.h"
+
+/* the absolute values of these constants don't matter as long as
+ * latter revisions of the protocol are assigned a larger number */
+#define ISCSI_PROTOCOL_DRAFT08 1
+#define ISCSI_PROTOCOL_DRAFT09 2
+#define ISCSI_PROTOCOL_DRAFT11 3
+#define ISCSI_PROTOCOL_DRAFT12 4
+#define ISCSI_PROTOCOL_DRAFT13 5
+
+static enum_val_t iscsi_protocol_versions[] = {
+ { "draft-08", "Draft 08", ISCSI_PROTOCOL_DRAFT08 },
+ { "draft-09", "Draft 09", ISCSI_PROTOCOL_DRAFT09 },
+ { "draft-11", "Draft 11", ISCSI_PROTOCOL_DRAFT11 },
+ { "draft-12", "Draft 12", ISCSI_PROTOCOL_DRAFT12 },
+ { "draft-13", "Draft 13", ISCSI_PROTOCOL_DRAFT13 },
+ { NULL, NULL, 0 }
+};
+
+static gint iscsi_protocol_version = ISCSI_PROTOCOL_DRAFT13;
+
+static gboolean iscsi_desegment = TRUE;
+
+static int demand_good_f_bit = FALSE;
+static int enable_bogosity_filter = TRUE;
+static guint32 bogus_pdu_data_length_threshold = 256 * 1024;
+
+static int enableDataDigests = FALSE;
+static int enableHeaderDigests = FALSE;
+
+static int dataDigestIsCRC32 = TRUE;
+static int headerDigestIsCRC32 = TRUE;
+
+static int dataDigestSize = 4;
+static int headerDigestSize = 4;
+
+static guint iscsi_port = 3260;
+
+/* Initialize the protocol and registered fields */
+static int proto_iscsi = -1;
+static int hf_iscsi_time = -1;
+static int hf_iscsi_request_frame = -1;
+static int hf_iscsi_data_in_frame = -1;
+static int hf_iscsi_data_out_frame = -1;
+static int hf_iscsi_response_frame = -1;
+static int hf_iscsi_AHS = -1;
+static int hf_iscsi_Padding = -1;
+static int hf_iscsi_ping_data = -1;
+static int hf_iscsi_immediate_data = -1;
+static int hf_iscsi_write_data = -1;
+static int hf_iscsi_read_data = -1;
+static int hf_iscsi_error_pdu_data = -1;
+static int hf_iscsi_async_message_data = -1;
+static int hf_iscsi_vendor_specific_data = -1;
+static int hf_iscsi_Opcode = -1;
+static int hf_iscsi_Flags = -1;
+static int hf_iscsi_HeaderDigest = -1;
+static int hf_iscsi_HeaderDigest32 = -1;
+static int hf_iscsi_DataDigest = -1;
+static int hf_iscsi_DataDigest32 = -1;
+/* #ifdef DRAFT08 */
+static int hf_iscsi_X = -1;
+/* #endif */
+static int hf_iscsi_I = -1;
+static int hf_iscsi_SCSICommand_F = -1;
+static int hf_iscsi_SCSICommand_R = -1;
+static int hf_iscsi_SCSICommand_W = -1;
+static int hf_iscsi_SCSICommand_Attr = -1;
+static int hf_iscsi_SCSICommand_CRN = -1;
+static int hf_iscsi_SCSICommand_AddCDB = -1;
+static int hf_iscsi_DataSegmentLength = -1;
+static int hf_iscsi_TotalAHSLength = -1;
+static int hf_iscsi_LUN = -1;
+static int hf_iscsi_InitiatorTaskTag = -1;
+static int hf_iscsi_ExpectedDataTransferLength = -1;
+static int hf_iscsi_CmdSN = -1;
+static int hf_iscsi_ExpStatSN = -1;
+static int hf_iscsi_StatSN = -1;
+static int hf_iscsi_ExpCmdSN = -1;
+static int hf_iscsi_MaxCmdSN = -1;
+static int hf_iscsi_SCSIResponse_o = -1;
+static int hf_iscsi_SCSIResponse_u = -1;
+static int hf_iscsi_SCSIResponse_O = -1;
+static int hf_iscsi_SCSIResponse_U = -1;
+static int hf_iscsi_SCSIResponse_BidiReadResidualCount = -1;
+static int hf_iscsi_SCSIResponse_ResidualCount = -1;
+static int hf_iscsi_SCSIResponse_Response = -1;
+static int hf_iscsi_SCSIResponse_Status = -1;
+static int hf_iscsi_SenseLength = -1;
+static int hf_iscsi_SCSIData_F = -1;
+static int hf_iscsi_SCSIData_A = -1;
+static int hf_iscsi_SCSIData_S = -1;
+static int hf_iscsi_SCSIData_O = -1;
+static int hf_iscsi_SCSIData_U = -1;
+static int hf_iscsi_TargetTransferTag = -1;
+static int hf_iscsi_DataSN = -1;
+static int hf_iscsi_BufferOffset = -1;
+static int hf_iscsi_SCSIData_ResidualCount = -1;
+static int hf_iscsi_VersionMin = -1;
+static int hf_iscsi_VersionMax = -1;
+static int hf_iscsi_VersionActive = -1;
+static int hf_iscsi_CID = -1;
+static int hf_iscsi_ISID8 = -1;
+static int hf_iscsi_ISID = -1;
+/* #if defined(DRAFT09) */
+static int hf_iscsi_ISID_Type = -1;
+static int hf_iscsi_ISID_NamingAuthority = -1;
+static int hf_iscsi_ISID_Qualifier = -1;
+/* #elif !defined(DRAFT08) */
+static int hf_iscsi_ISID_t = -1;
+static int hf_iscsi_ISID_a = -1;
+static int hf_iscsi_ISID_b = -1;
+static int hf_iscsi_ISID_c = -1;
+static int hf_iscsi_ISID_d = -1;
+/* #endif */
+static int hf_iscsi_TSID = -1;
+static int hf_iscsi_TSIH = -1;
+static int hf_iscsi_InitStatSN = -1;
+static int hf_iscsi_InitCmdSN = -1;
+/* #ifdef DRAFT09 */
+static int hf_iscsi_Login_X = -1;
+/* #endif */
+static int hf_iscsi_Login_C = -1;
+static int hf_iscsi_Login_T = -1;
+static int hf_iscsi_Login_CSG = -1;
+static int hf_iscsi_Login_NSG = -1;
+static int hf_iscsi_Login_Status = -1;
+static int hf_iscsi_KeyValue = -1;
+static int hf_iscsi_Text_C = -1;
+static int hf_iscsi_Text_F = -1;
+static int hf_iscsi_ExpDataSN = -1;
+static int hf_iscsi_R2TSN = -1;
+static int hf_iscsi_TaskManagementFunction_ReferencedTaskTag = -1;
+static int hf_iscsi_RefCmdSN = -1;
+static int hf_iscsi_TaskManagementFunction_Function = -1;
+static int hf_iscsi_TaskManagementFunction_Response = -1;
+static int hf_iscsi_Logout_Reason = -1;
+static int hf_iscsi_Logout_Response = -1;
+static int hf_iscsi_Time2Wait = -1;
+static int hf_iscsi_Time2Retain = -1;
+static int hf_iscsi_DesiredDataLength = -1;
+static int hf_iscsi_AsyncEvent = -1;
+static int hf_iscsi_EventVendorCode = -1;
+static int hf_iscsi_Parameter1 = -1;
+static int hf_iscsi_Parameter2 = -1;
+static int hf_iscsi_Parameter3 = -1;
+static int hf_iscsi_Reject_Reason = -1;
+static int hf_iscsi_snack_type = -1;
+static int hf_iscsi_BegRun = -1;
+static int hf_iscsi_RunLength = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_iscsi = -1;
+static gint ett_iscsi_KeyValues = -1;
+static gint ett_iscsi_CDB = -1;
+static gint ett_iscsi_Flags = -1;
+/* #ifndef DRAFT08 */
+static gint ett_iscsi_ISID = -1;
+/* #endif */
+
+
+/* #ifdef DRAFT08 */
+#define X_BIT 0x80
+/* #endif */
+
+#define I_BIT 0x40
+
+#define OPCODE_MASK 0x3f
+
+#define TARGET_OPCODE_BIT 0x20
+
+#define ISCSI_OPCODE_NOP_OUT 0x00
+#define ISCSI_OPCODE_SCSI_COMMAND 0x01
+#define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION 0x02
+#define ISCSI_OPCODE_LOGIN_COMMAND 0x03
+#define ISCSI_OPCODE_TEXT_COMMAND 0x04
+#define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
+#define ISCSI_OPCODE_LOGOUT_COMMAND 0x06
+#define ISCSI_OPCODE_SNACK_REQUEST 0x10
+#define ISCSI_OPCODE_VENDOR_SPECIFIC_I0 0x1c
+#define ISCSI_OPCODE_VENDOR_SPECIFIC_I1 0x1d
+#define ISCSI_OPCODE_VENDOR_SPECIFIC_I2 0x1e
+
+#define ISCSI_OPCODE_NOP_IN 0x20
+#define ISCSI_OPCODE_SCSI_RESPONSE 0x21
+#define ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE 0x22
+#define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
+#define ISCSI_OPCODE_TEXT_RESPONSE 0x24
+#define ISCSI_OPCODE_SCSI_DATA_IN 0x25
+#define ISCSI_OPCODE_LOGOUT_RESPONSE 0x26
+#define ISCSI_OPCODE_R2T 0x31
+#define ISCSI_OPCODE_ASYNC_MESSAGE 0x32
+#define ISCSI_OPCODE_REJECT 0x3f
+#define ISCSI_OPCODE_VENDOR_SPECIFIC_T0 0x3c
+#define ISCSI_OPCODE_VENDOR_SPECIFIC_T1 0x3d
+#define ISCSI_OPCODE_VENDOR_SPECIFIC_T2 0x3e
+
+#define CSG_SHIFT 2
+#define CSG_MASK (0x03 << CSG_SHIFT)
+#define NSG_MASK 0x03
+
+#define ISCSI_CSG_SECURITY_NEGOTIATION (0 << CSG_SHIFT)
+#define ISCSI_CSG_OPERATIONAL_NEGOTIATION (1 << CSG_SHIFT)
+#define ISCSI_CSG_FULL_FEATURE_PHASE (3 << CSG_SHIFT)
+
+#define ISCSI_SCSI_DATA_FLAG_S 0x01
+#define ISCSI_SCSI_DATA_FLAG_U 0x02
+#define ISCSI_SCSI_DATA_FLAG_O 0x04
+#define ISCSI_SCSI_DATA_FLAG_A 0x40
+#define ISCSI_SCSI_DATA_FLAG_F 0x80
+
+static const value_string iscsi_opcodes[] = {
+ { ISCSI_OPCODE_NOP_OUT, "NOP Out" },
+ { ISCSI_OPCODE_SCSI_COMMAND, "SCSI Command" },
+ { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION, "Task Management Function" },
+ { ISCSI_OPCODE_LOGIN_COMMAND, "Login Command" },
+ { ISCSI_OPCODE_TEXT_COMMAND, "Text Command" },
+ { ISCSI_OPCODE_SCSI_DATA_OUT, "SCSI Data Out" },
+ { ISCSI_OPCODE_LOGOUT_COMMAND, "Logout Command" },
+ { ISCSI_OPCODE_SNACK_REQUEST, "SNACK Request" },
+ { ISCSI_OPCODE_VENDOR_SPECIFIC_I0, "Vendor Specific I0" },
+ { ISCSI_OPCODE_VENDOR_SPECIFIC_I1, "Vendor Specific I1" },
+ { ISCSI_OPCODE_VENDOR_SPECIFIC_I2, "Vendor Specific I2" },
+
+ { ISCSI_OPCODE_NOP_IN, "NOP In" },
+ { ISCSI_OPCODE_SCSI_RESPONSE, "SCSI Response" },
+ { ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE, "Task Management Function Response" },
+ { ISCSI_OPCODE_LOGIN_RESPONSE, "Login Response" },
+ { ISCSI_OPCODE_TEXT_RESPONSE, "Text Response" },
+ { ISCSI_OPCODE_SCSI_DATA_IN, "SCSI Data In" },
+ { ISCSI_OPCODE_LOGOUT_RESPONSE, "Logout Response" },
+ { ISCSI_OPCODE_R2T, "Ready To Transfer" },
+ { ISCSI_OPCODE_ASYNC_MESSAGE, "Asynchronous Message" },
+ { ISCSI_OPCODE_REJECT, "Reject"},
+ { ISCSI_OPCODE_VENDOR_SPECIFIC_T0, "Vendor Specific T0" },
+ { ISCSI_OPCODE_VENDOR_SPECIFIC_T1, "Vendor Specific T1" },
+ { ISCSI_OPCODE_VENDOR_SPECIFIC_T2, "Vendor Specific T2" },
+ {0, NULL},
+};
+
+/* #ifdef DRAFT08 */
+static const true_false_string iscsi_meaning_X = {
+ "Retry",
+ "Not retry"
+};
+/* #endif */
+
+/* #ifdef DRAFT09 */
+static const true_false_string iscsi_meaning_login_X = {
+ "Reinstate failed connection",
+ "New connection"
+};
+/* #endif */
+
+static const true_false_string iscsi_meaning_I = {
+ "Immediate delivery",
+ "Queued delivery"
+};
+
+static const true_false_string iscsi_meaning_F = {
+ "Final PDU in sequence",
+ "Not final PDU in sequence"
+};
+
+static const true_false_string iscsi_meaning_A = {
+ "Acknowledge requested",
+ "Acknowledge not requested"
+};
+
+static const true_false_string iscsi_meaning_T = {
+ "Transit to next login stage",
+ "Stay in current login stage"
+};
+
+static const true_false_string iscsi_meaning_C = {
+ "Text is incomplete",
+ "Text is complete"
+};
+
+static const true_false_string iscsi_meaning_S = {
+ "Response contains SCSI status",
+ "Response does not contain SCSI status"
+};
+
+static const true_false_string iscsi_meaning_R = {
+ "Data will be read from target",
+ "No data will be read from target"
+};
+
+static const true_false_string iscsi_meaning_W = {
+ "Data will be written to target",
+ "No data will be written to target"
+};
+
+static const true_false_string iscsi_meaning_o = {
+ "Read part of bi-directional command overflowed",
+ "No overflow of read part of bi-directional command",
+};
+
+static const true_false_string iscsi_meaning_u = {
+ "Read part of bi-directional command underflowed",
+ "No underflow of read part of bi-directional command",
+};
+
+static const true_false_string iscsi_meaning_O = {
+ "Residual overflow occurred",
+ "No residual overflow occurred",
+};
+
+static const true_false_string iscsi_meaning_U = {
+ "Residual underflow occurred",
+ "No residual underflow occurred",
+};
+
+static const value_string iscsi_scsi_responses[] = {
+ { 0, "Command completed at target" },
+ { 1, "Response does not contain SCSI status"},
+ { 0, NULL }
+};
+
+static const value_string iscsi_scsicommand_taskattrs[] = {
+ {0, "Untagged"},
+ {1, "Simple"},
+ {2, "Ordered"},
+ {3, "Head of Queue"},
+ {4, "ACA"},
+ {0, NULL},
+};
+
+static const value_string iscsi_task_management_responses[] = {
+ {0, "Function complete"},
+ {1, "Task not in task set"},
+ {2, "LUN does not exist"},
+ {3, "Task still allegiant"},
+ {4, "Task failover not supported"},
+ {5, "Task management function not supported"},
+ {6, "Authorisation failed"},
+ {255, "Function rejected"},
+ {0, NULL},
+};
+
+static const value_string iscsi_task_management_functions[] = {
+ {1, "Abort Task"},
+ {2, "Abort Task Set"},
+ {3, "Clear ACA"},
+ {4, "Clear Task Set"},
+ {5, "Logical Unit Reset"},
+ {6, "Target Warm Reset"},
+ {7, "Target Cold Reset"},
+ {0, NULL},
+};
+
+static const value_string iscsi_login_status[] = {
+ {0x0000, "Success"},
+ {0x0101, "Target moved temporarily"},
+ {0x0102, "Target moved permanently"},
+ {0x0200, "Initiator error (miscellaneous error)"},
+ {0x0201, "Authentication failed"},
+ {0x0202, "Authorisation failure"},
+ {0x0203, "Target not found"},
+ {0x0204, "Target removed"},
+ {0x0205, "Unsupported version"},
+ {0x0206, "Too many connections"},
+ {0x0207, "Missing parameter"},
+ {0x0208, "Can't include in session"},
+ {0x0209, "Session type not supported"},
+ {0x020a, "Session does not exist"},
+ {0x020b, "Invalid request during login"},
+ {0x0300, "Target error (miscellaneous error)"},
+ {0x0301, "Service unavailable"},
+ {0x0302, "Out of resources"},
+ {0, NULL},
+};
+
+static const value_string iscsi_login_stage[] = {
+ {0, "Security negotiation"},
+ {1, "Operational negotiation"},
+ {3, "Full feature phase"},
+ {0, NULL},
+};
+
+/* #ifndef DRAFT08 */
+static const value_string iscsi_isid_type[] = {
+ {0x00, "IEEE OUI"},
+ {0x01, "IANA Enterprise Number"},
+ {0x02, "Random"},
+ {0, NULL},
+};
+/* #endif */
+
+static const value_string iscsi_logout_reasons[] = {
+ {0, "Close session"},
+ {1, "Close connection"},
+ {2, "Remove connection for recovery"},
+ {0, NULL},
+};
+
+static const value_string iscsi_logout_response[] = {
+ {0, "Connection closed successfully"},
+ {1, "CID not found"},
+ {2, "Connection recovery not supported"},
+ {3, "Cleanup failed for various reasons"},
+ {0, NULL},
+};
+
+static const value_string iscsi_asyncevents[] = {
+ {0, "A SCSI asynchronous event is reported in the sense data"},
+ {1, "Target requests logout"},
+ {2, "Target will/has dropped connection"},
+ {3, "Target will/has dropped all connections"},
+ {4, "Target requests parameter negotiation"},
+ {0, NULL},
+};
+
+static const value_string iscsi_snack_types[] = {
+ {0, "Data/R2T"},
+ {1, "Status"},
+/* #ifndef DRAFT08 */
+ {2, "Data ACK"},
+/* #endif */
+ {3, "R-Data"},
+ {0, NULL}
+};
+
+static const value_string iscsi_reject_reasons[] = {
+/* #ifdef DRAFT08 */
+ {0x01, "Full feature phase command before login"},
+/* #endif */
+ {0x02, "Data (payload) digest error"},
+ {0x03, "Data SNACK reject"},
+ {0x04, "Protocol error"},
+ {0x05, "Command not supported in this session type"},
+ {0x06, "Immediate command reject (too many immediate commands)"},
+ {0x07, "Task in progress"},
+ {0x08, "Invalid Data Ack"},
+ {0x09, "Invalid PDU field"},
+ {0x0a, "Long operation reject"},
+ {0x0b, "Negotiation reset"},
+ {0x0c, "Waiting for logout"},
+ {0, NULL},
+};
+
+/*****************************************************************/
+/* */
+/* CRC LOOKUP TABLE */
+/* ================ */
+/* The following CRC lookup table was generated automagically */
+/* by the Rocksoft^tm Model CRC Algorithm Table Generation */
+/* Program V1.0 using the following model parameters: */
+/* */
+/* Width : 4 bytes. */
+/* Poly : 0x1EDC6F41L */
+/* Reverse : TRUE. */
+/* */
+/* For more information on the Rocksoft^tm Model CRC Algorithm, */
+/* see the document titled "A Painless Guide to CRC Error */
+/* Detection Algorithms" by Ross Williams */
+/* (ross@guest.adelaide.edu.au.). This document is likely to be */
+/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
+/* */
+/*****************************************************************/
+
+static guint32 crc32Table[256] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+ 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+ 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+ 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+ 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+ 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+ 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+ 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+ 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+ 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+ 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+ 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+ 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+ 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+ 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+ 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+ 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+ 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+ 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+ 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+ 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+ 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+ 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+ 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+ 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+ 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+ 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+ 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+ 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+ 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+ 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+ 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+ 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+ 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+ 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+ 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+ 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+ 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+ 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+ 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+ 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+ 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+ 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+ 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+ 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+ 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+ 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+ 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+ 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+ 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+ 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+ 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
+};
+
+#define CRC32C_PRELOAD 0xffffffff
+
+/*
+ * Byte swap fix contributed by Dave Wysochanski <davidw@netapp.com>
+ */
+#define CRC32C_SWAP(crc32c_value) \
+ (((crc32c_value & 0xff000000) >> 24) | \
+ ((crc32c_value & 0x00ff0000) >> 8) | \
+ ((crc32c_value & 0x0000ff00) << 8) | \
+ ((crc32c_value & 0x000000ff) << 24))
+
+static guint32
+calculateCRC32(const void *buf, int len, guint32 crc) {
+ const guint8 *p = (const guint8 *)buf;
+ crc = CRC32C_SWAP(crc);
+ while(len-- > 0)
+ crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ return CRC32C_SWAP(crc);
+}
+
+
+
+
+
+/* structure and functions to keep track of
+ * COMMAND/DATA_IN/DATA_OUT/RESPONSE matching
+ */
+typedef struct _iscsi_conv_data {
+ guint32 conv_idx;
+ guint32 itt;
+ guint32 request_frame;
+ guint32 data_in_frame;
+ guint32 data_out_frame;
+ guint32 response_frame;
+ guint32 iscsi_dl;
+ nstime_t req_time;
+} iscsi_conv_data_t;
+static GHashTable *iscsi_req_unmatched = NULL;
+static GHashTable *iscsi_req_matched = NULL;
+static GMemChunk *iscsi_req_vals = NULL;
+static guint32 iscsi_init_count = 200;
+
+static gint
+iscsi_equal_unmatched(gconstpointer v, gconstpointer w)
+{
+ const iscsi_conv_data_t *v1 = (const iscsi_conv_data_t *)v;
+ const iscsi_conv_data_t *v2 = (const iscsi_conv_data_t *)w;
+
+ return (v1->conv_idx == v2->conv_idx)&&(v1->itt == v2->itt);
+}
+
+static guint
+iscsi_hash_unmatched (gconstpointer v)
+{
+ const iscsi_conv_data_t *key = (const iscsi_conv_data_t *)v;
+ guint val;
+
+ val = key->conv_idx + key->itt;
+
+ return val;
+}
+
+static gint
+iscsi_equal_matched(gconstpointer v, gconstpointer w)
+{
+ const iscsi_conv_data_t *v1 = (const iscsi_conv_data_t *)v;
+ const iscsi_conv_data_t *v2 = (const iscsi_conv_data_t *)w;
+ int check_frame;
+
+ check_frame=0;
+ if (v1->request_frame && (v1->request_frame==v2->request_frame))
+ check_frame=1;
+ if (v1->data_in_frame && (v1->data_in_frame==v2->data_in_frame))
+ check_frame=1;
+ if (v1->data_out_frame && (v1->data_out_frame==v2->data_out_frame))
+ check_frame=1;
+ if (v1->response_frame && (v1->response_frame==v2->response_frame))
+ check_frame=1;
+
+ return check_frame&&(v1->conv_idx == v2->conv_idx)&&(v1->itt == v2->itt);
+}
+
+static guint
+iscsi_hash_matched (gconstpointer v)
+{
+ const iscsi_conv_data_t *key = (const iscsi_conv_data_t *)v;
+ guint val;
+
+ val = key->conv_idx + key->itt;
+
+ return val;
+}
+
+
+
+
+
+
+/*
+ * Protocol initialization
+ */
+static void
+iscsi_init_protocol(void)
+{
+ if (iscsi_req_vals)
+ g_mem_chunk_destroy(iscsi_req_vals);
+ if (iscsi_req_unmatched)
+ g_hash_table_destroy(iscsi_req_unmatched);
+ if (iscsi_req_matched)
+ g_hash_table_destroy(iscsi_req_matched);
+
+ iscsi_req_unmatched = g_hash_table_new(iscsi_hash_unmatched, iscsi_equal_unmatched);
+ iscsi_req_matched = g_hash_table_new(iscsi_hash_matched, iscsi_equal_matched);
+ iscsi_req_vals = g_mem_chunk_new("iscsi_req_vals",
+ sizeof(iscsi_conv_data_t),
+ iscsi_init_count * sizeof(iscsi_conv_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+static int
+iscsi_min(int a, int b) {
+ return (a < b)? a : b;
+}
+
+static gint
+addTextKeys(proto_tree *tt, tvbuff_t *tvb, gint offset, guint32 text_len) {
+ const gint limit = offset + text_len;
+ while(offset < limit) {
+ gint len = tvb_strnlen(tvb, offset, limit - offset);
+ if(len == -1)
+ len = limit - offset;
+ else
+ len = len + 1;
+ proto_tree_add_item(tt, hf_iscsi_KeyValue, tvb, offset, len, FALSE);
+ offset += len;
+ }
+ return offset;
+}
+
+static gint
+handleHeaderDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int headerLen) {
+ int available_bytes = tvb_length_remaining(tvb, offset);
+ if(enableHeaderDigests) {
+ if(headerDigestIsCRC32) {
+ if(available_bytes >= (headerLen + 4)) {
+ guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, headerLen), headerLen, CRC32C_PRELOAD);
+ guint32 sent = tvb_get_ntohl(tvb, offset + headerLen);
+ if(crc == sent) {
+ proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Good CRC32)", sent);
+ }
+ else {
+ proto_tree_add_uint_format(ti, hf_iscsi_HeaderDigest32, tvb, offset + headerLen, 4, sent, "HeaderDigest: 0x%08x (Bad CRC32, should be 0x%08x)", sent, crc);
+ }
+ }
+ return offset + headerLen + 4;
+ }
+ if(available_bytes >= (headerLen + headerDigestSize)) {
+ proto_tree_add_item(ti, hf_iscsi_HeaderDigest, tvb, offset + headerLen, headerDigestSize, FALSE);
+ }
+ return offset + headerLen + headerDigestSize;
+ }
+ return offset + headerLen;
+}
+
+static gint
+handleDataDigest(proto_item *ti, tvbuff_t *tvb, guint offset, int dataLen) {
+ int available_bytes = tvb_length_remaining(tvb, offset);
+ if(enableDataDigests) {
+ if(dataDigestIsCRC32) {
+ if(available_bytes >= (dataLen + 4)) {
+ guint32 crc = ~calculateCRC32(tvb_get_ptr(tvb, offset, dataLen), dataLen, CRC32C_PRELOAD);
+ guint32 sent = tvb_get_ntohl(tvb, offset + dataLen);
+ if(crc == sent) {
+ proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Good CRC32)", sent);
+ }
+ else {
+ proto_tree_add_uint_format(ti, hf_iscsi_DataDigest32, tvb, offset + dataLen, 4, sent, "DataDigest: 0x%08x (Bad CRC32, should be 0x%08x)", sent, crc);
+ }
+ }
+ return offset + dataLen + 4;
+ }
+ if(available_bytes >= (dataLen + dataDigestSize)) {
+ proto_tree_add_item(ti, hf_iscsi_DataDigest, tvb, offset + dataLen, dataDigestSize, FALSE);
+ }
+ return offset + dataLen + dataDigestSize;
+ }
+ return offset + dataLen;
+}
+
+static int
+handleDataSegment(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int hf_id) {
+ if(endOffset > offset) {
+ int dataOffset = offset;
+ int dataLen = iscsi_min(dataSegmentLen, endOffset - offset);
+ if(dataLen > 0) {
+ proto_tree_add_item(ti, hf_id, tvb, offset, dataLen, FALSE);
+ offset += dataLen;
+ }
+ if(offset < endOffset && (offset & 3) != 0) {
+ int padding = 4 - (offset & 3);
+ proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
+ offset += padding;
+ }
+ if(dataSegmentLen > 0 && offset < endOffset)
+ offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
+ }
+
+ return offset;
+}
+
+static int
+handleDataSegmentAsTextKeys(proto_item *ti, tvbuff_t *tvb, guint offset, guint dataSegmentLen, guint endOffset, int digestsActive) {
+ if(endOffset > offset) {
+ int dataOffset = offset;
+ int textLen = iscsi_min(dataSegmentLen, endOffset - offset);
+ if(textLen > 0) {
+ proto_item *tf = proto_tree_add_text(ti, tvb, offset, textLen, "Key/Value Pairs");
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_KeyValues);
+ offset = addTextKeys(tt, tvb, offset, textLen);
+ }
+ if(offset < endOffset && (offset & 3) != 0) {
+ int padding = 4 - (offset & 3);
+ proto_tree_add_item(ti, hf_iscsi_Padding, tvb, offset, padding, FALSE);
+ offset += padding;
+ }
+ if(digestsActive && dataSegmentLen > 0 && offset < endOffset)
+ offset = handleDataDigest(ti, tvb, dataOffset, offset - dataOffset);
+ }
+ return offset;
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_iscsi_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint8 opcode, const char *opcode_str, guint32 data_segment_len) {
+
+ guint original_offset = offset;
+ proto_tree *ti = NULL;
+ guint8 scsi_status = 0;
+ gboolean S_bit=FALSE;
+ guint cdb_offset = offset + 32; /* offset of CDB from start of PDU */
+ guint end_offset = offset + tvb_length_remaining(tvb, offset);
+ conversation_t *conversation = NULL;
+ iscsi_conv_data_t *cdata = NULL;
+ scsi_task_id_t task_key;
+ int paddedDataSegmentLength = data_segment_len;
+ if(paddedDataSegmentLength & 3)
+ paddedDataSegmentLength += 4 - (paddedDataSegmentLength & 3);
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "iSCSI");
+
+ if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
+ opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
+ scsi_status = tvb_get_guint8 (tvb, offset+3);
+ }
+
+ if ((opcode == ISCSI_OPCODE_SCSI_RESPONSE) ||
+ (opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
+ (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (conversation) {
+ if (!pinfo->fd->flags.visited){
+ iscsi_conv_data_t ckey;
+ ckey.conv_idx = conversation->index;
+ ckey.itt = tvb_get_ntohl (tvb, offset+16);
+
+ /* first time we see this packet. check if we can find the request */
+ cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_unmatched, &ckey);
+ if (cdata){
+ if (cdata->data_in_frame+cdata->data_out_frame+cdata->response_frame==0){
+ /* this is the first response to the request, add it to the matched table */
+ g_hash_table_insert (iscsi_req_matched, cdata, cdata);
+ }
+ switch(opcode){
+ case ISCSI_OPCODE_SCSI_RESPONSE:
+ cdata->response_frame=pinfo->fd->num;
+ break;
+ case ISCSI_OPCODE_SCSI_DATA_IN:
+ /* a bit ugly but we need to check the S bit here */
+ if(tvb_get_guint8(tvb, offset+1)&ISCSI_SCSI_DATA_FLAG_S){
+ cdata->response_frame=pinfo->fd->num;
+ }
+ cdata->data_in_frame=pinfo->fd->num;
+ break;
+ case ISCSI_OPCODE_SCSI_DATA_OUT:
+ cdata->data_out_frame=pinfo->fd->num;
+ break;
+ }
+ }
+ } else {
+ iscsi_conv_data_t ckey;
+ ckey.conv_idx = conversation->index;
+ ckey.itt = tvb_get_ntohl (tvb, offset+16);
+ ckey.request_frame=0;
+ ckey.data_in_frame=0;
+ ckey.data_out_frame=0;
+ ckey.response_frame=0;
+ switch(opcode){
+ case ISCSI_OPCODE_SCSI_RESPONSE:
+ ckey.response_frame=pinfo->fd->num;
+ break;
+ case ISCSI_OPCODE_SCSI_DATA_IN:
+ ckey.data_in_frame=pinfo->fd->num;
+ break;
+ case ISCSI_OPCODE_SCSI_DATA_OUT:
+ ckey.data_out_frame=pinfo->fd->num;
+ break;
+ }
+
+ /* we have seen this one before, pick it up from the matched table */
+ cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_matched, &ckey);
+ }
+
+ if (cdata){
+ task_key.conv_id = cdata->conv_idx;
+ task_key.task_id = cdata->itt;
+ pinfo->private_data = &task_key;
+ } else {
+ pinfo->private_data = NULL;
+ }
+ } else {
+ /* no conversation, meaning we didn't see the request */
+ pinfo->private_data = NULL;
+ }
+
+ } else if (opcode == ISCSI_OPCODE_SCSI_COMMAND) {
+ conversation = find_conversation (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (!conversation) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+
+ if (!pinfo->fd->flags.visited){
+ iscsi_conv_data_t ckey;
+
+ /* first time we see this packet. */
+ /*check if we have seen this request before and delete it in that case */
+ ckey.conv_idx = conversation->index;
+ ckey.itt = tvb_get_ntohl (tvb, offset+16);
+ cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_unmatched, &ckey);
+ if (cdata){
+ g_hash_table_remove(iscsi_req_unmatched, &ckey);
+ }
+
+ /* add this new transaction to the unmatched table */
+ cdata = g_mem_chunk_alloc (iscsi_req_vals);
+ cdata->conv_idx = conversation->index;
+ cdata->itt = tvb_get_ntohl (tvb, offset+16);
+ cdata->request_frame=pinfo->fd->num;
+ cdata->data_in_frame=0;
+ cdata->data_out_frame=0;
+ cdata->response_frame=0;
+ cdata->req_time.nsecs = pinfo->fd->abs_usecs*1000;
+ cdata->req_time.secs = pinfo->fd->abs_secs;
+
+ g_hash_table_insert (iscsi_req_unmatched, cdata, cdata);
+ } else {
+ iscsi_conv_data_t ckey;
+ ckey.conv_idx = conversation->index;
+ ckey.itt = tvb_get_ntohl (tvb, offset+16);
+ ckey.request_frame=pinfo->fd->num;
+ ckey.data_in_frame=0;
+ ckey.data_out_frame=0;
+ ckey.response_frame=0;
+
+ /* we have seen this one before, pick it up from the matched table */
+ cdata = (iscsi_conv_data_t *)g_hash_table_lookup (iscsi_req_matched, &ckey);
+ }
+
+
+ if (cdata){
+ /* The SCSI protocol uses this as the key to detect a
+ * SCSI-level conversation. */
+ task_key.conv_id = cdata->conv_idx;
+ task_key.task_id = cdata->itt;
+ pinfo->private_data = &task_key;
+ } else {
+ pinfo->private_data=NULL;
+ }
+ }
+ else {
+ pinfo->private_data = NULL;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+
+ if (opcode != ISCSI_OPCODE_SCSI_COMMAND) {
+
+ col_append_str(pinfo->cinfo, COL_INFO, opcode_str);
+
+ if (opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
+ (opcode == ISCSI_OPCODE_SCSI_DATA_IN &&
+ (tvb_get_guint8(tvb, offset + 1) & ISCSI_SCSI_DATA_FLAG_S))) {
+ col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
+ val_to_str (scsi_status, scsi_status_val, "0x%x"));
+ }
+ else if (opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
+ guint16 login_status = tvb_get_ntohs(tvb, offset+36);
+ col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
+ val_to_str (login_status, iscsi_login_status, "0x%x"));
+ }
+ else if (opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
+ guint8 logoutReason;
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
+ logoutReason = tvb_get_guint8(tvb, offset+11);
+ } else if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
+ logoutReason = tvb_get_guint8(tvb, offset+1) & 0x7f;
+ }
+ else {
+ logoutReason = tvb_get_guint8(tvb, offset+23);
+ }
+ col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
+ val_to_str (logoutReason, iscsi_logout_reasons, "0x%x"));
+ }
+ else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
+ guint8 tmf = tvb_get_guint8(tvb, offset + 1);
+ col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
+ val_to_str (tmf, iscsi_task_management_functions, "0x%x"));
+ }
+ else if (opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
+ guint8 resp = tvb_get_guint8(tvb, offset + 2);
+ col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
+ val_to_str (resp, iscsi_task_management_responses, "0x%x"));
+ }
+ else if (opcode == ISCSI_OPCODE_REJECT) {
+ guint8 reason = tvb_get_guint8(tvb, offset + 2);
+ col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
+ val_to_str (reason, iscsi_reject_reasons, "0x%x"));
+ }
+ else if (opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
+ guint8 asyncEvent = tvb_get_guint8(tvb, offset + 36);
+ col_append_fstr (pinfo->cinfo, COL_INFO, " (%s)",
+ val_to_str (asyncEvent, iscsi_asyncevents, "0x%x"));
+ }
+ }
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any
+ work not necessary to generate protocol tree items. */
+ if (tree) {
+ proto_item *tp;
+ /* create display subtree for the protocol */
+ tp = proto_tree_add_protocol_format(tree, proto_iscsi, tvb,
+ offset, -1, "iSCSI (%s)",
+ opcode_str);
+ ti = proto_item_add_subtree(tp, ett_iscsi);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_Opcode, tvb,
+ offset + 0, 1, opcode);
+ if((opcode & TARGET_OPCODE_BIT) == 0) {
+ /* initiator -> target */
+ gint b = tvb_get_guint8(tvb, offset + 0);
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
+ if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
+ opcode != ISCSI_OPCODE_LOGOUT_COMMAND &&
+ opcode != ISCSI_OPCODE_SNACK_REQUEST)
+ proto_tree_add_boolean(ti, hf_iscsi_X, tvb, offset + 0, 1, b);
+ }
+ if(opcode != ISCSI_OPCODE_SCSI_DATA_OUT &&
+ opcode != ISCSI_OPCODE_LOGIN_COMMAND &&
+ opcode != ISCSI_OPCODE_SNACK_REQUEST)
+ proto_tree_add_boolean(ti, hf_iscsi_I, tvb, offset + 0, 1, b);
+ }
+
+
+ if(opcode == ISCSI_OPCODE_NOP_OUT) {
+ /* NOP Out */
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
+ } else if(opcode == ISCSI_OPCODE_NOP_IN) {
+ /* NOP In */
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_ping_data);
+ } else if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
+ /* SCSI Command */
+ guint32 ahsLen = tvb_get_guint8(tvb, offset + 4) * 4;
+ {
+ gint b = tvb_get_guint8(tvb, offset + 1);
+ proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+
+ proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_F, tvb, offset + 1, 1, b);
+ proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_R, tvb, offset + 1, 1, b);
+ proto_tree_add_boolean(tt, hf_iscsi_SCSICommand_W, tvb, offset + 1, 1, b);
+ proto_tree_add_uint(tt, hf_iscsi_SCSICommand_Attr, tvb, offset + 1, 1, b);
+ }
+ if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
+ proto_tree_add_item(ti, hf_iscsi_SCSICommand_CRN, tvb, offset + 3, 1, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpectedDataTransferLength, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
+ {
+ if(ahsLen > 0) {
+ /* FIXME - disssect AHS? */
+ proto_tree_add_item(ti, hf_iscsi_AHS, tvb, offset + 48, ahsLen, FALSE);
+ }
+ offset = handleHeaderDigest(ti, tvb, offset, 48 + ahsLen);
+ }
+ offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_immediate_data);
+ } else if(opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
+ /* SCSI Response */
+ {
+ gint b = tvb_get_guint8(tvb, offset + 1);
+ proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_o, tvb, offset + 1, 1, b);
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_u, tvb, offset + 1, 1, b);
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_O, tvb, offset + 1, 1, b);
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIResponse_U, tvb, offset + 1, 1, b);
+ }
+ proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Response, tvb, offset + 2, 1, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 20, 4, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
+ if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 44, 4, FALSE);
+ }
+ else {
+ proto_tree_add_item(ti, hf_iscsi_SCSIResponse_BidiReadResidualCount, tvb, offset + 40, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_SCSIResponse_ResidualCount, tvb, offset + 44, 4, FALSE);
+ }
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ /* do not update offset here because the data segment is
+ * dissected below */
+ handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
+ } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION) {
+ /* Task Management Function */
+ proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Function, tvb, offset + 1, 1, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ }
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_RefCmdSN, tvb, offset + 32, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ } else if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE) {
+ /* Task Management Function Response */
+ proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_Response, tvb, offset + 2, 1, FALSE);
+ if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
+ proto_tree_add_item(ti, hf_iscsi_TaskManagementFunction_ReferencedTaskTag, tvb, offset + 20, 4, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ } else if(opcode == ISCSI_OPCODE_LOGIN_COMMAND) {
+ /* Login Command */
+ int digestsActive = 0;
+ {
+ gint b = tvb_get_guint8(tvb, offset + 1);
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
+ if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
+ digestsActive = 1;
+ }
+#if 0
+ proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+#endif
+
+ proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
+ if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
+ proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
+ }
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
+ proto_tree_add_boolean(ti, hf_iscsi_Login_X, tvb, offset + 1, 1, b);
+ }
+ proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
+
+ /* NSG is undefined unless T is set */
+ if(b&0x80){
+ proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
+ }
+ }
+ proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_VersionMin, tvb, offset + 3, 1, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
+ proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
+ }
+ else {
+ proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
+ }
+ else {
+ proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
+ }
+ }
+ if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
+ proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
+ }
+ else {
+ proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
+ proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
+ if(digestsActive)
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ else
+ offset += 48;
+ offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
+ } else if(opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
+ /* Login Response */
+ int digestsActive = 0;
+ {
+ gint b = tvb_get_guint8(tvb, offset + 1);
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
+ if((b & CSG_MASK) >= ISCSI_CSG_OPERATIONAL_NEGOTIATION)
+ digestsActive = 1;
+ }
+#if 0
+ proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+#endif
+
+ proto_tree_add_boolean(ti, hf_iscsi_Login_T, tvb, offset + 1, 1, b);
+ if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
+ proto_tree_add_boolean(ti, hf_iscsi_Login_C, tvb, offset + 1, 1, b);
+ }
+ proto_tree_add_item(ti, hf_iscsi_Login_CSG, tvb, offset + 1, 1, FALSE);
+ /* NSG is undefined unless T is set */
+ if(b&0x80){
+ proto_tree_add_item(ti, hf_iscsi_Login_NSG, tvb, offset + 1, 1, FALSE);
+ }
+ }
+
+ proto_tree_add_item(ti, hf_iscsi_VersionMax, tvb, offset + 2, 1, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_VersionActive, tvb, offset + 3, 1, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
+ proto_tree_add_item(ti, hf_iscsi_ISID8, tvb, offset + 12, 2, FALSE);
+ }
+ else {
+ proto_item *tf = proto_tree_add_item(ti, hf_iscsi_ISID, tvb, offset + 8, 6, FALSE);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_ISID);
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(tt, hf_iscsi_ISID_Type, tvb, offset + 8, 1, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_NamingAuthority, tvb, offset + 9, 3, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_Qualifier, tvb, offset + 12, 2, FALSE);
+ }
+ else {
+ proto_tree_add_item(tt, hf_iscsi_ISID_t, tvb, offset + 8, 1, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_a, tvb, offset + 8, 1, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_b, tvb, offset + 9, 2, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_c, tvb, offset + 11, 1, FALSE);
+ proto_tree_add_item(tt, hf_iscsi_ISID_d, tvb, offset + 12, 2, FALSE);
+ }
+ }
+ if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT12) {
+ proto_tree_add_item(ti, hf_iscsi_TSID, tvb, offset + 14, 2, FALSE);
+ }
+ else {
+ proto_tree_add_item(ti, hf_iscsi_TSIH, tvb, offset + 14, 2, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_Login_Status, tvb, offset + 36, 2, FALSE);
+ if(digestsActive)
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ else
+ offset += 48;
+ offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, digestsActive);
+ } else if(opcode == ISCSI_OPCODE_TEXT_COMMAND) {
+ /* Text Command */
+ {
+ gint b = tvb_get_guint8(tvb, offset + 1);
+ proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+
+ proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
+ if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
+ proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
+ }
+ }
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
+ } else if(opcode == ISCSI_OPCODE_TEXT_RESPONSE) {
+ /* Text Response */
+ {
+ gint b = tvb_get_guint8(tvb, offset + 1);
+ proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+
+ proto_tree_add_boolean(tt, hf_iscsi_Text_F, tvb, offset + 1, 1, b);
+ if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
+ proto_tree_add_boolean(tt, hf_iscsi_Text_C, tvb, offset + 1, 1, b);
+ }
+ }
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ offset = handleDataSegmentAsTextKeys(ti, tvb, offset, data_segment_len, end_offset, TRUE);
+ } else if(opcode == ISCSI_OPCODE_SCSI_DATA_OUT) {
+ /* SCSI Data Out (write) */
+ {
+ gint b = tvb_get_guint8(tvb, offset + 1);
+ proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
+ }
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ /* do not update offset here because the data segment is
+ * dissected below */
+ handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
+ } else if(opcode == ISCSI_OPCODE_SCSI_DATA_IN) {
+ /* SCSI Data In (read) */
+ {
+ gint b = tvb_get_guint8(tvb, offset + 1);
+ proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+
+ if(b&ISCSI_SCSI_DATA_FLAG_S){
+ S_bit=TRUE;
+ }
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIData_F, tvb, offset + 1, 1, b);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIData_A, tvb, offset + 1, 1, b);
+ }
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIData_O, tvb, offset + 1, 1, b);
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIData_U, tvb, offset + 1, 1, b);
+ proto_tree_add_boolean(tt, hf_iscsi_SCSIData_S, tvb, offset + 1, 1, b);
+ }
+ proto_tree_add_item(ti, hf_iscsi_SCSIResponse_Status, tvb, offset + 3, 1, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 20, 4, FALSE);
+ }
+ else {
+ proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_SCSIData_ResidualCount, tvb, offset + 44, 4, FALSE);
+ }
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ /* do not update offset here because the data segment is
+ * dissected below */
+ handleDataDigest(ti, tvb, offset, paddedDataSegmentLength);
+ } else if(opcode == ISCSI_OPCODE_LOGOUT_COMMAND) {
+ /* Logout Command */
+ if(iscsi_protocol_version >= ISCSI_PROTOCOL_DRAFT13) {
+ proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 1, 1, FALSE);
+ }
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ }
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
+ proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 8, 2, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 11, 1, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT08) {
+ proto_tree_add_item(ti, hf_iscsi_CID, tvb, offset + 20, 2, FALSE);
+ if(iscsi_protocol_version < ISCSI_PROTOCOL_DRAFT13) {
+ proto_tree_add_item(ti, hf_iscsi_Logout_Reason, tvb, offset + 23, 1, FALSE);
+ }
+ }
+ proto_tree_add_item(ti, hf_iscsi_CmdSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ } else if(opcode == ISCSI_OPCODE_LOGOUT_RESPONSE) {
+ /* Logout Response */
+ proto_tree_add_item(ti, hf_iscsi_Logout_Response, tvb, offset + 2, 1, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_Time2Wait, tvb, offset + 40, 2, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_Time2Retain, tvb, offset + 42, 2, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ } else if(opcode == ISCSI_OPCODE_SNACK_REQUEST) {
+ /* SNACK Request */
+ {
+ gint b = tvb_get_guint8(tvb, offset + 1);
+#if 0
+ proto_item *tf = proto_tree_add_uint(ti, hf_iscsi_Flags, tvb, offset + 1, 1, b);
+ proto_tree *tt = proto_item_add_subtree(tf, ett_iscsi_Flags);
+#endif
+
+ proto_tree_add_item(ti, hf_iscsi_snack_type, tvb, offset + 1, 1, b);
+ }
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ if(iscsi_protocol_version <= ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpDataSN, tvb, offset + 36, 4, FALSE);
+ }
+ else {
+ proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpStatSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_BegRun, tvb, offset + 40, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_RunLength, tvb, offset + 44, 4, FALSE);
+ }
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ } else if(opcode == ISCSI_OPCODE_R2T) {
+ /* R2T */
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ }
+ proto_tree_add_item(ti, hf_iscsi_InitiatorTaskTag, tvb, offset + 16, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_TargetTransferTag, tvb, offset + 20, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_R2TSN, tvb, offset + 36, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_BufferOffset, tvb, offset + 40, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_DesiredDataLength, tvb, offset + 44, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ } else if(opcode == ISCSI_OPCODE_ASYNC_MESSAGE) {
+ /* Asynchronous Message */
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ proto_tree_add_item(ti, hf_iscsi_LUN, tvb, offset + 8, 8, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_AsyncEvent, tvb, offset + 36, 1, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_EventVendorCode, tvb, offset + 37, 1, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_Parameter1, tvb, offset + 38, 2, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_Parameter2, tvb, offset + 40, 2, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_Parameter3, tvb, offset + 42, 2, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_async_message_data);
+ } else if(opcode == ISCSI_OPCODE_REJECT) {
+ /* Reject */
+ proto_tree_add_item(ti, hf_iscsi_Reject_Reason, tvb, offset + 2, 1, FALSE);
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ proto_tree_add_item(ti, hf_iscsi_StatSN, tvb, offset + 24, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_ExpCmdSN, tvb, offset + 28, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_MaxCmdSN, tvb, offset + 32, 4, FALSE);
+ proto_tree_add_item(ti, hf_iscsi_DataSN, tvb, offset + 36, 4, FALSE);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_error_pdu_data);
+ } else if(opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I0 ||
+ opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I1 ||
+ opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_I2 ||
+ opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T0 ||
+ opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T1 ||
+ opcode == ISCSI_OPCODE_VENDOR_SPECIFIC_T2) {
+ /* Vendor specific opcodes */
+ if(iscsi_protocol_version > ISCSI_PROTOCOL_DRAFT09) {
+ proto_tree_add_item(ti, hf_iscsi_TotalAHSLength, tvb, offset + 4, 1, FALSE);
+ }
+ proto_tree_add_uint(ti, hf_iscsi_DataSegmentLength, tvb, offset + 5, 3, data_segment_len);
+ offset = handleHeaderDigest(ti, tvb, offset, 48);
+ offset = handleDataSegment(ti, tvb, offset, data_segment_len, end_offset, hf_iscsi_vendor_specific_data);
+ }
+
+
+
+ /* handle request/response matching */
+ if (cdata){
+ switch(opcode){
+ case ISCSI_OPCODE_SCSI_RESPONSE:
+ if (cdata->request_frame){
+ nstime_t delta_time;
+ proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
+ delta_time.secs = pinfo->fd->abs_secs - cdata->req_time.secs;
+ delta_time.nsecs = pinfo->fd->abs_usecs*1000 - cdata->req_time.nsecs;
+ if (delta_time.nsecs<0){
+ delta_time.nsecs+=1000000000;
+ delta_time.secs--;
+ }
+ proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
+
+ }
+ if (cdata->data_in_frame)
+ proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
+ if (cdata->data_out_frame)
+ proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
+ break;
+ case ISCSI_OPCODE_SCSI_DATA_IN:
+ /* if we have phase collaps then we might have the
+ response embedded in the last DataIn segment */
+ if(!S_bit){
+ if (cdata->request_frame)
+ proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
+ if (cdata->response_frame)
+ proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->response_frame);
+ } else {
+ if (cdata->request_frame){
+ nstime_t delta_time;
+ proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
+ delta_time.secs = pinfo->fd->abs_secs - cdata->req_time.secs;
+ delta_time.nsecs = pinfo->fd->abs_usecs*1000 - cdata->req_time.nsecs;
+ if (delta_time.nsecs<0){
+ delta_time.nsecs+=1000000000;
+ delta_time.secs--;
+ }
+ proto_tree_add_time(ti, hf_iscsi_time, tvb, 0, 0, &delta_time);
+
+ }
+ }
+ if (cdata->data_out_frame)
+ proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
+ break;
+ case ISCSI_OPCODE_SCSI_DATA_OUT:
+ if (cdata->request_frame)
+ proto_tree_add_uint(ti, hf_iscsi_request_frame, tvb, 0, 0, cdata->request_frame);
+ if (cdata->data_in_frame)
+ proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
+ if (cdata->response_frame)
+ proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->response_frame);
+ break;
+ case ISCSI_OPCODE_SCSI_COMMAND:
+ if (cdata->data_in_frame)
+ proto_tree_add_uint(ti, hf_iscsi_data_in_frame, tvb, 0, 0, cdata->data_in_frame);
+ if (cdata->data_out_frame)
+ proto_tree_add_uint(ti, hf_iscsi_data_out_frame, tvb, 0, 0, cdata->data_out_frame);
+ if (cdata->response_frame)
+ proto_tree_add_uint(ti, hf_iscsi_response_frame, tvb, 0, 0, cdata->response_frame);
+ break;
+ }
+ }
+
+
+
+ proto_item_set_len(ti, offset - original_offset);
+
+ if((opcode & ((iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08)?
+ ~(X_BIT | I_BIT) :
+ ~I_BIT)) == ISCSI_OPCODE_SCSI_COMMAND) {
+ /* SCSI Command */
+ dissect_scsi_cdb (tvb, pinfo, tree, cdb_offset, 16, SCSI_DEV_UNKNOWN);
+ }
+ else if (opcode == ISCSI_OPCODE_SCSI_RESPONSE) {
+ if (scsi_status == 0x2) {
+ /* A SCSI response with Check Condition contains sense data */
+ /* offset is setup correctly by the iscsi code for response above */
+ if((end_offset - offset) >= 2) {
+ int senseLen = tvb_get_ntohs(tvb, offset);
+ if(ti != NULL)
+ proto_tree_add_item(ti, hf_iscsi_SenseLength, tvb, offset, 2, FALSE);
+ offset += 2;
+ if(senseLen > 0)
+ dissect_scsi_snsinfo (tvb, pinfo, tree, offset,
+ iscsi_min (senseLen,
+ end_offset-offset));
+ }
+ }
+ else {
+ dissect_scsi_rsp (tvb, pinfo, tree);
+ }
+ }
+ else if ((opcode == ISCSI_OPCODE_SCSI_DATA_IN) ||
+ (opcode == ISCSI_OPCODE_SCSI_DATA_OUT)) {
+ /* offset is setup correctly by the iscsi code for response above */
+ dissect_scsi_payload (tvb, pinfo, tree, offset, FALSE,
+ iscsi_min (data_segment_len, end_offset-offset));
+ }
+}
+
+static gboolean
+dissect_iscsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean check_port) {
+ /* Set up structures needed to add the protocol subtree and manage it */
+ guint iSCSIPdusDissected = 0;
+ guint offset = 0;
+ guint32 available_bytes = tvb_length_remaining(tvb, offset);
+
+ /* quick check to see if the packet is long enough to contain the
+ * minimum amount of information we need */
+ if (available_bytes < 48 && (!iscsi_desegment || available_bytes < 8)) {
+ /* no, so give up */
+ return FALSE;
+ }
+
+ /* process multiple iSCSI PDUs per packet */
+ while(available_bytes >= 48 || (iscsi_desegment && available_bytes >= 8)) {
+ const char *opcode_str = NULL;
+ guint32 data_segment_len;
+ guint8 opcode = tvb_get_guint8(tvb, offset + 0);
+ guint8 secondPduByte = tvb_get_guint8(tvb, offset + 1);
+ int badPdu = FALSE;
+
+ /* mask out any extra bits in the opcode byte */
+ opcode &= OPCODE_MASK;
+
+ opcode_str = match_strval(opcode, iscsi_opcodes);
+ if(opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION ||
+ opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
+ opcode == ISCSI_OPCODE_R2T ||
+ opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
+ opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
+ opcode == ISCSI_OPCODE_SNACK_REQUEST)
+ data_segment_len = 0;
+ else
+ data_segment_len = tvb_get_ntohl(tvb, offset + 4) & 0x00ffffff;
+
+ if(opcode_str == NULL) {
+ badPdu = TRUE;
+ }
+ else if(check_port && iscsi_port != 0 &&
+ (((opcode & TARGET_OPCODE_BIT) && pinfo->srcport != iscsi_port) ||
+ (!(opcode & TARGET_OPCODE_BIT) && pinfo->destport != iscsi_port))) {
+ badPdu = TRUE;
+ }
+ else if(enable_bogosity_filter) {
+ /* try and distinguish between data and real headers */
+ if(data_segment_len > bogus_pdu_data_length_threshold) {
+ badPdu = TRUE;
+ }
+ else if(demand_good_f_bit &&
+ !(secondPduByte & 0x80) &&
+ (opcode == ISCSI_OPCODE_NOP_OUT ||
+ opcode == ISCSI_OPCODE_NOP_IN ||
+ opcode == ISCSI_OPCODE_LOGOUT_COMMAND ||
+ opcode == ISCSI_OPCODE_LOGOUT_RESPONSE ||
+ opcode == ISCSI_OPCODE_SCSI_RESPONSE ||
+ opcode == ISCSI_OPCODE_TASK_MANAGEMENT_FUNCTION_RESPONSE ||
+ opcode == ISCSI_OPCODE_R2T ||
+ opcode == ISCSI_OPCODE_ASYNC_MESSAGE ||
+ opcode == ISCSI_OPCODE_SNACK_REQUEST ||
+ opcode == ISCSI_OPCODE_REJECT)) {
+ badPdu = TRUE;
+ } else if(opcode==ISCSI_OPCODE_NOP_OUT) {
+ /* TransferTag for NOP-Out should either be -1 or
+ the tag value we want for a response.
+ Assume 0 means we are just inside a big all zero
+ datablock.
+ */
+ if(tvb_get_ntohl(tvb, offset+20)==0){
+ badPdu = TRUE;
+ }
+ }
+ }
+
+ if(badPdu) {
+ return iSCSIPdusDissected > 0;
+ }
+ else {
+ guint32 pduLen = 48;
+ int digestsActive = 1;
+
+ if(opcode == ISCSI_OPCODE_LOGIN_COMMAND ||
+ opcode == ISCSI_OPCODE_LOGIN_RESPONSE) {
+ if(iscsi_protocol_version == ISCSI_PROTOCOL_DRAFT08) {
+ if((secondPduByte & CSG_MASK) < ISCSI_CSG_OPERATIONAL_NEGOTIATION) {
+ /* digests are not yet turned on */
+ digestsActive = 0;
+ }
+ }
+ else {
+ digestsActive = 0;
+ }
+ }
+
+ if(opcode == ISCSI_OPCODE_SCSI_COMMAND) {
+ /* ahsLen */
+ pduLen += tvb_get_guint8(tvb, offset + 4) * 4;
+ }
+
+ pduLen += data_segment_len;
+ if((pduLen & 3) != 0)
+ pduLen += 4 - (pduLen & 3);
+
+ if(digestsActive && enableHeaderDigests) {
+ if(headerDigestIsCRC32)
+ pduLen += 4;
+ else
+ pduLen += headerDigestSize;
+ }
+
+ if(digestsActive && data_segment_len > 0 && enableDataDigests) {
+ if(dataDigestIsCRC32)
+ pduLen += 4;
+ else
+ pduLen += dataDigestSize;
+ }
+
+ /*
+ * Desegmentation check.
+ */
+ if(iscsi_desegment && pinfo->can_desegment) {
+ if(pduLen > available_bytes) {
+ /*
+ * This frame doesn't have all of the data for
+ * this message, but we can do reassembly on it.
+ *
+ * Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and
+ * how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = pduLen - available_bytes;
+ return TRUE;
+ }
+ }
+
+ /* This is to help TCP keep track of PDU boundaries
+ and allows it to find PDUs that are not aligned to
+ the start of a TCP segments.
+ Since it also allows TCP to know what is in the middle
+ of a large PDU, it reduces the probability of a segment
+ in the middle of a large PDU transfer being misdissected as
+ a PDU.
+ */
+ if(!pinfo->fd->flags.visited){
+ if(pduLen>(guint32)tvb_reported_length_remaining(tvb, offset)){
+ pinfo->want_pdu_tracking=2;
+ pinfo->bytes_until_next_pdu=pduLen-tvb_reported_length_remaining(tvb, offset);
+ }
+ }
+
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ if(iSCSIPdusDissected == 0)
+ col_set_str(pinfo->cinfo, COL_INFO, "");
+ else
+ col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ }
+
+ dissect_iscsi_pdu(tvb, pinfo, tree, offset, opcode, opcode_str, data_segment_len);
+ if(pduLen > available_bytes)
+ pduLen = available_bytes;
+ offset += pduLen;
+ available_bytes -= pduLen;
+ ++iSCSIPdusDissected;
+ }
+ }
+
+ return iSCSIPdusDissected > 0;
+}
+
+/* This is called for those sessions where we have explicitely said
+ this to be iSCSI using "Decode As..."
+ In this case we will not check the port number for sanity and just
+ do as the user said.
+*/
+static void
+dissect_iscsi_handle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ dissect_iscsi(tvb, pinfo, tree, FALSE);
+}
+
+/* This is called through the heuristic handler.
+ In this case we also want to check that the port matches the preference
+ setting for iSCSI in order to reduce the number of
+ false positives.
+*/
+static gboolean
+dissect_iscsi_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ return dissect_iscsi(tvb, pinfo, tree, TRUE);
+}
+
+
+/* Register the protocol with Ethereal */
+
+/*
+ * this format is require because a script is used to build the C
+ * function that calls all the protocol registration.
+*/
+
+void
+proto_register_iscsi(void)
+{
+
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_iscsi_request_frame,
+ { "Request in", "iscsi.request_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0,
+ "The request to this transaction is in this frame", HFILL }},
+
+ { &hf_iscsi_time,
+ { "Time from request", "iscsi.time",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
+ "Time between the Command and the Response", HFILL }},
+
+ { &hf_iscsi_data_in_frame,
+ { "Data In in", "iscsi.data_in_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0,
+ "The Data In for this transaction is in this frame", HFILL }},
+
+ { &hf_iscsi_data_out_frame,
+ { "Data Out in", "iscsi.data_out_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0,
+ "The Data Out for this transaction is in this frame", HFILL }},
+
+ { &hf_iscsi_response_frame,
+ { "Response in", "iscsi.response_frame",
+ FT_FRAMENUM, BASE_NONE, NULL, 0,
+ "The response to this transaction is in this frame", HFILL }},
+
+ { &hf_iscsi_AHS,
+ { "AHS", "iscsi.ahs",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Additional header segment", HFILL }
+ },
+ { &hf_iscsi_Padding,
+ { "Padding", "iscsi.padding",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Padding to 4 byte boundary", HFILL }
+ },
+ { &hf_iscsi_ping_data,
+ { "PingData", "iscsi.pingdata",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Ping Data", HFILL }
+ },
+ { &hf_iscsi_immediate_data,
+ { "ImmediateData", "iscsi.immediatedata",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Immediate Data", HFILL }
+ },
+ { &hf_iscsi_write_data,
+ { "WriteData", "iscsi.writedata",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Write Data", HFILL }
+ },
+ { &hf_iscsi_read_data,
+ { "ReadData", "iscsi.readdata",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Read Data", HFILL }
+ },
+ { &hf_iscsi_error_pdu_data,
+ { "ErrorPDUData", "iscsi.errorpdudata",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Error PDU Data", HFILL }
+ },
+ { &hf_iscsi_async_message_data,
+ { "AsyncMessageData", "iscsi.asyncmessagedata",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Async Message Data", HFILL }
+ },
+ { &hf_iscsi_vendor_specific_data,
+ { "VendorSpecificData", "iscsi.vendorspecificdata",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Vendor Specific Data", HFILL }
+ },
+ { &hf_iscsi_HeaderDigest,
+ { "HeaderDigest", "iscsi.headerdigest",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Header Digest", HFILL }
+ },
+ { &hf_iscsi_HeaderDigest32,
+ { "HeaderDigest", "iscsi.headerdigest32",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Header Digest", HFILL }
+ },
+ { &hf_iscsi_DataDigest,
+ { "DataDigest", "iscsi.datadigest",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Data Digest", HFILL }
+ },
+ { &hf_iscsi_DataDigest32,
+ { "DataDigest", "iscsi.datadigest32",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Data Digest", HFILL }
+ },
+ { &hf_iscsi_Opcode,
+ { "Opcode", "iscsi.opcode",
+ FT_UINT8, BASE_HEX, VALS(iscsi_opcodes), 0,
+ "Opcode", HFILL }
+ },
+/* #ifdef DRAFT08 */
+ { &hf_iscsi_X,
+ { "X", "iscsi.X",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_X), 0x80,
+ "Command Retry", HFILL }
+ },
+/* #endif */
+ { &hf_iscsi_I,
+ { "I", "iscsi.I",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_I), 0x40,
+ "Immediate delivery", HFILL }
+ },
+ { &hf_iscsi_Flags,
+ { "Flags", "iscsi.flags",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Opcode specific flags", HFILL }
+ },
+ { &hf_iscsi_SCSICommand_F,
+ { "F", "iscsi.scsicommand.F",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
+ "PDU completes command", HFILL }
+ },
+ { &hf_iscsi_SCSICommand_R,
+ { "R", "iscsi.scsicommand.R",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_R), 0x40,
+ "Command reads from SCSI target", HFILL }
+ },
+ { &hf_iscsi_SCSICommand_W,
+ { "W", "iscsi.scsicommand.W",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_W), 0x20,
+ "Command writes to SCSI target", HFILL }
+ },
+ { &hf_iscsi_SCSICommand_Attr,
+ { "Attr", "iscsi.scsicommand.attr",
+ FT_UINT8, BASE_HEX, VALS(iscsi_scsicommand_taskattrs), 0x07,
+ "SCSI task attributes", HFILL }
+ },
+ { &hf_iscsi_SCSICommand_CRN,
+ { "CRN", "iscsi.scsicommand.crn",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "SCSI command reference number", HFILL }
+ },
+ { &hf_iscsi_SCSICommand_AddCDB,
+ { "AddCDB", "iscsi.scsicommand.addcdb",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Additional CDB length (in 4 byte units)", HFILL }
+ },
+ { &hf_iscsi_DataSegmentLength,
+ { "DataSegmentLength", "iscsi.datasegmentlength",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Data segment length (bytes)", HFILL }
+ },
+ { &hf_iscsi_TotalAHSLength,
+ { "TotalAHSLength", "iscsi.totalahslength",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Total additional header segment length (4 byte words)", HFILL }
+ },
+ { &hf_iscsi_LUN,
+ { "LUN", "iscsi.lun",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Logical Unit Number", HFILL }
+ },
+ { &hf_iscsi_InitiatorTaskTag,
+ { "InitiatorTaskTag", "iscsi.initiatortasktag",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Initiator's task tag", HFILL }
+ },
+ { &hf_iscsi_ExpectedDataTransferLength,
+ { "ExpectedDataTransferLength", "iscsi.scsicommand.expecteddatatransferlength",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Expected length of data transfer", HFILL }
+ },
+ { &hf_iscsi_CmdSN,
+ { "CmdSN", "iscsi.cmdsn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Sequence number for this command", HFILL }
+ },
+ { &hf_iscsi_ExpStatSN,
+ { "ExpStatSN", "iscsi.expstatsn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Next expected status sequence number", HFILL }
+ },
+ { &hf_iscsi_SCSIResponse_ResidualCount,
+ { "ResidualCount", "iscsi.scsiresponse.residualcount",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Residual count", HFILL }
+ },
+ { &hf_iscsi_StatSN,
+ { "StatSN", "iscsi.statsn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Status sequence number", HFILL }
+ },
+ { &hf_iscsi_ExpCmdSN,
+ { "ExpCmdSN", "iscsi.expcmdsn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Next expected command sequence number", HFILL }
+ },
+ { &hf_iscsi_MaxCmdSN,
+ { "MaxCmdSN", "iscsi.maxcmdsn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Maximum acceptable command sequence number", HFILL }
+ },
+ { &hf_iscsi_SCSIResponse_o,
+ { "o", "iscsi.scsiresponse.o",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_o), 0x10,
+ "Bi-directional read residual overflow", HFILL }
+ },
+ { &hf_iscsi_SCSIResponse_u,
+ { "u", "iscsi.scsiresponse.u",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_u), 0x08,
+ "Bi-directional read residual underflow", HFILL }
+ },
+ { &hf_iscsi_SCSIResponse_O,
+ { "O", "iscsi.scsiresponse.O",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), 0x04,
+ "Residual overflow", HFILL }
+ },
+ { &hf_iscsi_SCSIResponse_U,
+ { "U", "iscsi.scsiresponse.U",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), 0x02,
+ "Residual underflow", HFILL }
+ },
+ { &hf_iscsi_SCSIResponse_Status,
+ { "Status", "iscsi.scsiresponse.status",
+ FT_UINT8, BASE_HEX, VALS(scsi_status_val), 0,
+ "SCSI command status value", HFILL }
+ },
+ { &hf_iscsi_SCSIResponse_Response,
+ { "Response", "iscsi.scsiresponse.response",
+ FT_UINT8, BASE_HEX, VALS(iscsi_scsi_responses), 0,
+ "SCSI command response value", HFILL }
+ },
+ { &hf_iscsi_SCSIResponse_BidiReadResidualCount,
+ { "BidiReadResidualCount", "iscsi.scsiresponse.bidireadresidualcount",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Bi-directional read residual count", HFILL }
+ },
+ { &hf_iscsi_SenseLength,
+ { "SenseLength", "iscsi.scsiresponse.senselength",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Sense data length", HFILL }
+ },
+ { &hf_iscsi_SCSIData_F,
+ { "F", "iscsi.scsidata.F",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), ISCSI_SCSI_DATA_FLAG_F,
+ "Final PDU", HFILL }
+ },
+ { &hf_iscsi_SCSIData_A,
+ { "A", "iscsi.scsidata.A",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_A), ISCSI_SCSI_DATA_FLAG_A,
+ "Acknowledge Requested", HFILL }
+ },
+ { &hf_iscsi_SCSIData_S,
+ { "S", "iscsi.scsidata.S",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_S), ISCSI_SCSI_DATA_FLAG_S,
+ "PDU Contains SCSI command status", HFILL }
+ },
+ { &hf_iscsi_SCSIData_U,
+ { "U", "iscsi.scsidata.U",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_U), ISCSI_SCSI_DATA_FLAG_U,
+ "Residual underflow", HFILL }
+ },
+ { &hf_iscsi_SCSIData_O,
+ { "O", "iscsi.scsidata.O",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_O), ISCSI_SCSI_DATA_FLAG_O,
+ "Residual overflow", HFILL }
+ },
+ { &hf_iscsi_TargetTransferTag,
+ { "TargetTransferTag", "iscsi.targettransfertag",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Target transfer tag", HFILL }
+ },
+ { &hf_iscsi_BufferOffset,
+ { "BufferOffset", "iscsi.bufferOffset",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Buffer offset", HFILL }
+ },
+ { &hf_iscsi_SCSIData_ResidualCount,
+ { "ResidualCount", "iscsi.scsidata.readresidualcount",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Residual count", HFILL }
+ },
+ { &hf_iscsi_DataSN,
+ { "DataSN", "iscsi.datasn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Data sequence number", HFILL }
+ },
+ { &hf_iscsi_VersionMax,
+ { "VersionMax", "iscsi.versionmax",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Maximum supported protocol version", HFILL }
+ },
+ { &hf_iscsi_VersionMin,
+ { "VersionMin", "iscsi.versionmin",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Minimum supported protocol version", HFILL }
+ },
+ { &hf_iscsi_VersionActive,
+ { "VersionActive", "iscsi.versionactive",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Negotiated protocol version", HFILL }
+ },
+ { &hf_iscsi_CID,
+ { "CID", "iscsi.cid",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Connection identifier", HFILL }
+ },
+/* #ifdef DRAFT08 */
+ { &hf_iscsi_ISID8,
+ { "ISID", "iscsi.isid",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Initiator part of session identifier", HFILL }
+ },
+/* #else */
+ { &hf_iscsi_ISID,
+ { "ISID", "iscsi.isid",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Initiator part of session identifier", HFILL }
+ },
+/* #ifdef DRAFT09 */
+ { &hf_iscsi_ISID_Type,
+ { "ISID_Type", "iscsi.isid.type",
+ FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0,
+ "Initiator part of session identifier - type", HFILL }
+ },
+ { &hf_iscsi_ISID_NamingAuthority,
+ { "ISID_NamingAuthority", "iscsi.isid.namingauthority",
+ FT_UINT24, BASE_HEX, NULL, 0,
+ "Initiator part of session identifier - naming authority", HFILL }
+ },
+ { &hf_iscsi_ISID_Qualifier,
+ { "ISID_Qualifier", "iscsi.isid.qualifier",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Initiator part of session identifier - qualifier", HFILL }
+ },
+/* #else */
+ { &hf_iscsi_ISID_t,
+ { "ISID_t", "iscsi.isid.t",
+ FT_UINT8, BASE_HEX, VALS(iscsi_isid_type), 0xc0,
+ "Initiator part of session identifier - t", HFILL }
+ },
+ { &hf_iscsi_ISID_a,
+ { "ISID_a", "iscsi.isid.a",
+ FT_UINT8, BASE_HEX, NULL, 0x3f,
+ "Initiator part of session identifier - a", HFILL }
+ },
+ { &hf_iscsi_ISID_b,
+ { "ISID_b", "iscsi.isid.b",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Initiator part of session identifier - b", HFILL }
+ },
+ { &hf_iscsi_ISID_c,
+ { "ISID_c", "iscsi.isid.c",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Initiator part of session identifier - c", HFILL }
+ },
+ { &hf_iscsi_ISID_d,
+ { "ISID_d", "iscsi.isid.d",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Initiator part of session identifier - d", HFILL }
+ },
+/* #endif */
+/* #endif */
+ { &hf_iscsi_TSID,
+ { "TSID", "iscsi.tsid",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Target part of session identifier", HFILL }
+ },
+ { &hf_iscsi_TSIH,
+ { "TSIH", "iscsi.tsih",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Target session identifying handle", HFILL }
+ },
+ { &hf_iscsi_InitStatSN,
+ { "InitStatSN", "iscsi.initstatsn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Initial status sequence number", HFILL }
+ },
+ { &hf_iscsi_InitCmdSN,
+ { "InitCmdSN", "iscsi.initcmdsn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Initial command sequence number", HFILL }
+ },
+ { &hf_iscsi_Login_T,
+ { "T", "iscsi.login.T",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_T), 0x80,
+ "Transit to next login stage", HFILL }
+ },
+ { &hf_iscsi_Login_C,
+ { "C", "iscsi.login.C",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
+ "Text incomplete", HFILL }
+ },
+/* #ifdef DRAFT09 */
+ { &hf_iscsi_Login_X,
+ { "X", "iscsi.login.X",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_login_X), 0x40,
+ "Restart Connection", HFILL }
+ },
+/* #endif */
+ { &hf_iscsi_Login_CSG,
+ { "CSG", "iscsi.login.csg",
+ FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), CSG_MASK,
+ "Current stage", HFILL }
+ },
+ { &hf_iscsi_Login_NSG,
+ { "NSG", "iscsi.login.nsg",
+ FT_UINT8, BASE_HEX, VALS(iscsi_login_stage), NSG_MASK,
+ "Next stage", HFILL }
+ },
+ { &hf_iscsi_Login_Status,
+ { "Status", "iscsi.login.status",
+ FT_UINT16, BASE_HEX, VALS(iscsi_login_status), 0,
+ "Status class and detail", HFILL }
+ },
+ { &hf_iscsi_KeyValue,
+ { "KeyValue", "iscsi.keyvalue",
+ FT_STRING, 0, NULL, 0,
+ "Key/value pair", HFILL }
+ },
+ { &hf_iscsi_Text_F,
+ { "F", "iscsi.text.F",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_F), 0x80,
+ "Final PDU in text sequence", HFILL }
+ },
+ { &hf_iscsi_Text_C,
+ { "C", "iscsi.text.C",
+ FT_BOOLEAN, 8, TFS(&iscsi_meaning_C), 0x40,
+ "Text incomplete", HFILL }
+ },
+ { &hf_iscsi_ExpDataSN,
+ { "ExpDataSN", "iscsi.expdatasn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Next expected data sequence number", HFILL }
+ },
+ { &hf_iscsi_R2TSN,
+ { "R2TSN", "iscsi.r2tsn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "R2T PDU Number", HFILL }
+ },
+ { &hf_iscsi_TaskManagementFunction_Response,
+ { "Response", "iscsi.taskmanfun.response",
+ FT_UINT8, BASE_HEX, VALS(iscsi_task_management_responses), 0,
+ "Response", HFILL }
+ },
+ { &hf_iscsi_TaskManagementFunction_ReferencedTaskTag,
+ { "ReferencedTaskTag", "iscsi.taskmanfun.referencedtasktag",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Referenced task tag", HFILL }
+ },
+ { &hf_iscsi_RefCmdSN,
+ { "RefCmdSN", "iscsi.refcmdsn",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Command sequence number for command to be aborted", HFILL }
+ },
+ { &hf_iscsi_TaskManagementFunction_Function,
+ { "Function", "iscsi.taskmanfun.function",
+ FT_UINT8, BASE_HEX, VALS(iscsi_task_management_functions), 0x7F,
+ "Requested task function", HFILL }
+ },
+ { &hf_iscsi_Logout_Reason,
+ { "Reason", "iscsi.logout.reason",
+ FT_UINT8, BASE_HEX, VALS(iscsi_logout_reasons), 0x7F,
+ "Reason for logout", HFILL }
+ },
+ { &hf_iscsi_Logout_Response,
+ { "Response", "iscsi.logout.response",
+ FT_UINT8, BASE_HEX, VALS(iscsi_logout_response), 0,
+ "Logout response", HFILL }
+ },
+ { &hf_iscsi_Time2Wait,
+ { "Time2Wait", "iscsi.time2wait",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Time2Wait", HFILL }
+ },
+ { &hf_iscsi_Time2Retain,
+ { "Time2Retain", "iscsi.time2retain",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Time2Retain", HFILL }
+ },
+ { &hf_iscsi_DesiredDataLength,
+ { "DesiredDataLength", "iscsi.desireddatalength",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Desired data length (bytes)", HFILL }
+ },
+ { &hf_iscsi_AsyncEvent,
+ { "AsyncEvent", "iscsi.asyncevent",
+ FT_UINT8, BASE_HEX, VALS(iscsi_asyncevents), 0,
+ "Async event type", HFILL }
+ },
+ { &hf_iscsi_EventVendorCode,
+ { "EventVendorCode", "iscsi.eventvendorcode",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Event vendor code", HFILL }
+ },
+ { &hf_iscsi_Parameter1,
+ { "Parameter1", "iscsi.parameter1",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Parameter 1", HFILL }
+ },
+ { &hf_iscsi_Parameter2,
+ { "Parameter2", "iscsi.parameter2",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Parameter 2", HFILL }
+ },
+ { &hf_iscsi_Parameter3,
+ { "Parameter3", "iscsi.parameter3",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Parameter 3", HFILL }
+ },
+ { &hf_iscsi_Reject_Reason,
+ { "Reason", "iscsi.reject.reason",
+ FT_UINT8, BASE_HEX, VALS(iscsi_reject_reasons), 0,
+ "Reason for command rejection", HFILL }
+ },
+ { &hf_iscsi_snack_type,
+ { "S", "iscsi.snack.type",
+ FT_UINT8, BASE_DEC, VALS(iscsi_snack_types), 0x0f,
+ "Type of SNACK requested", HFILL }
+ },
+ { &hf_iscsi_BegRun,
+ { "BegRun", "iscsi.snack.begrun",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "First missed DataSN or StatSN", HFILL }
+ },
+ { &hf_iscsi_RunLength,
+ { "RunLength", "iscsi.snack.runlength",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Number of additional missing status PDUs in this run", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_iscsi,
+ &ett_iscsi_KeyValues,
+ &ett_iscsi_CDB,
+ &ett_iscsi_Flags,
+/* #ifndef DRAFT08 */
+ &ett_iscsi_ISID,
+/* #endif */
+ };
+
+ /* Register the protocol name and description */
+ proto_iscsi = proto_register_protocol("iSCSI", "iSCSI", "iscsi");
+
+ /* Required function calls to register the header fields and
+ * subtrees used */
+ proto_register_field_array(proto_iscsi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine (&iscsi_init_protocol);
+
+ {
+ module_t *iscsi_module = prefs_register_protocol(proto_iscsi, NULL);
+
+ prefs_register_enum_preference(iscsi_module,
+ "protocol_version",
+ "Protocol version",
+ "The iSCSI protocol version",
+ &iscsi_protocol_version,
+ iscsi_protocol_versions,
+ FALSE);
+
+ prefs_register_bool_preference(iscsi_module,
+ "desegment_iscsi_messages",
+ "Desegment iSCSI messages",
+ "When enabled, iSCSI messages that span multiple TCP segments are desegmented",
+ &iscsi_desegment);
+
+ prefs_register_bool_preference(iscsi_module,
+ "bogus_pdu_filter",
+ "Enable bogus pdu filter",
+ "When enabled, packets that appear bogus are ignored",
+ &enable_bogosity_filter);
+
+ prefs_register_bool_preference(iscsi_module,
+ "demand_good_f_bit",
+ "Ignore packets with bad F bit",
+ "Ignore packets that haven't set the F bit when they should have",
+ &demand_good_f_bit);
+
+ prefs_register_uint_preference(iscsi_module,
+ "bogus_pdu_max_data_len",
+ "Bogus pdu max data length threshold",
+ "Treat packets whose data segment length is greater than this value as bogus",
+ 10,
+ &bogus_pdu_data_length_threshold);
+
+
+ prefs_register_uint_preference(iscsi_module,
+ "target_port",
+ "Target port",
+ "Port number of iSCSI target",
+ 10,
+ &iscsi_port);
+
+ prefs_register_bool_preference(iscsi_module,
+ "enable_header_digests",
+ "Enable header digests",
+ "When enabled, pdus are assumed to contain a header digest",
+ &enableHeaderDigests);
+ prefs_register_bool_preference(iscsi_module,
+ "enable_data_digests",
+ "Enable data digests",
+ "When enabled, pdus are assumed to contain a data digest",
+ &enableDataDigests);
+
+ prefs_register_bool_preference(iscsi_module,
+ "header_digest_is_crc32c",
+ "Header digest is CRC32C",
+ "When enabled, header digests are assumed to be CRC32C",
+ &headerDigestIsCRC32);
+ prefs_register_bool_preference(iscsi_module,
+ "data_digest_is_crc32c",
+ "Data digest is CRC32C",
+ "When enabled, data digests are assumed to be CRC32C",
+ &dataDigestIsCRC32);
+
+ prefs_register_uint_preference(iscsi_module,
+ "header_digest_size",
+ "Header digest size",
+ "The size of a header digest (bytes)",
+ 10,
+ &headerDigestSize);
+ prefs_register_uint_preference(iscsi_module,
+ "data_digest_size",
+ "Data digest size",
+ "The size of a data digest (bytes)",
+ 10,
+ &dataDigestSize);
+
+ /* Preference supported in older versions.
+ Register them as obsolete. */
+ prefs_register_obsolete_preference(iscsi_module,
+ "version_03_compatible");
+ prefs_register_obsolete_preference(iscsi_module,
+ "bogus_pdu_max_digest_padding");
+ }
+}
+
+
+/*
+ * If this dissector uses sub-dissector registration add a
+ * registration routine.
+ */
+
+/*
+ * This format is required because a script is used to find these
+ * routines and create the code that calls these routines.
+ */
+void
+proto_reg_handoff_iscsi(void)
+{
+ dissector_handle_t iscsi_handle;
+
+ heur_dissector_add("tcp", dissect_iscsi_heur, proto_iscsi);
+
+ iscsi_handle = create_dissector_handle(dissect_iscsi_handle, proto_iscsi);
+ dissector_add_handle("tcp.port", iscsi_handle);
+}
diff --git a/epan/dissectors/packet-isdn.c b/epan/dissectors/packet-isdn.c
new file mode 100644
index 0000000000..e1c2337cc2
--- /dev/null
+++ b/epan/dissectors/packet-isdn.c
@@ -0,0 +1,216 @@
+/* packet-isdn.c
+ * Routines for ISDN packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/circuit.h>
+
+static int proto_isdn = -1;
+static int hf_isdn_channel = -1;
+
+static gint ett_isdn = -1;
+
+static dissector_handle_t lapd_handle;
+static dissector_handle_t ppp_hdlc_handle;
+static dissector_handle_t v120_handle;
+static dissector_handle_t data_handle;
+
+static const value_string channel_vals[] = {
+ { 0, "D" },
+ { 1, "B1" },
+ { 2, "B2" },
+ { 3, "B3" },
+ { 4, "B4" },
+ { 5, "B5" },
+ { 6, "B6" },
+ { 7, "B7" },
+ { 8, "B8" },
+ { 9, "B9" },
+ { 10, "B10" },
+ { 11, "B11" },
+ { 12, "B12" },
+ { 13, "B13" },
+ { 14, "B14" },
+ { 15, "B15" },
+ { 16, "B16" },
+ { 17, "B17" },
+ { 18, "B19" },
+ { 19, "B19" },
+ { 20, "B20" },
+ { 21, "B21" },
+ { 22, "B22" },
+ { 23, "B23" },
+ { 24, "B24" },
+ { 25, "B25" },
+ { 26, "B26" },
+ { 27, "B27" },
+ { 28, "B29" },
+ { 29, "B29" },
+ { 30, "B30" },
+ { 0, NULL }
+};
+
+static void
+dissect_isdn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *isdn_tree;
+ proto_item *ti;
+ static const guint8 v120_sabme[3] = { 0x08, 0x01, 0x7F };
+ static const guint8 ppp[2] = { 0xFF, 0x03 };
+ circuit_t *circuit;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISDN");
+
+ if (pinfo->pseudo_header->isdn.uton) {
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "Network");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "User");
+ } else {
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "User");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "Network");
+ }
+
+ pinfo->ctype = CT_ISDN;
+ pinfo->circuit_id = pinfo->pseudo_header->isdn.channel;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_isdn, tvb, 0, 0, FALSE);
+ isdn_tree = proto_item_add_subtree(ti, ett_isdn);
+
+ proto_tree_add_uint(isdn_tree, hf_isdn_channel, tvb, 0, 0,
+ pinfo->pseudo_header->isdn.channel);
+ }
+
+ /*
+ * Set up a circuit for this channel, and assign it a dissector.
+ */
+ circuit = find_circuit(pinfo->ctype, pinfo->circuit_id, pinfo->fd->num);
+ if (circuit == NULL)
+ circuit = circuit_new(pinfo->ctype, pinfo->circuit_id,
+ pinfo->fd->num);
+
+ if (circuit_get_dissector(circuit) == NULL) {
+ /*
+ * We don't yet know the type of traffic on the circuit.
+ */
+ switch (pinfo->pseudo_header->isdn.channel) {
+
+ case 0:
+ /*
+ * D-channel. Treat it as LAPD.
+ */
+ circuit_set_dissector(circuit, lapd_handle);
+ break;
+
+ default:
+ /*
+ * B-channel.
+ *
+ * We don't know yet whether the datastream is
+ * V.120 or not; this heuristic tries to figure
+ * that out.
+ *
+ * We cannot glean this from the Q.931 SETUP message,
+ * because no commercial V.120 implementation I've
+ * seen actually sets the V.120 protocol discriminator
+ * (that, or I'm misreading the spec badly).
+ *
+ * TODO: close the circuit after a close on the B
+ * channel is detected.
+ *
+ * -Bert Driehuis (from the i4btrace reader;
+ * this heuristic was moved from there to
+ * here)
+ *
+ * XXX - I don't know that one can guarantee that
+ * the SABME will appear in the first frame on
+ * the channels, so we probably can't just say
+ * "it must be PPP" if we don't immediately see
+ * the V.120 SABME frame, so we do so only if
+ * we see the 0xFF 0x03. Unfortunately, that
+ * won't do the right thing if the PPP-over-HDLC
+ * headers aren't being used....
+ */
+ if (tvb_memeql(tvb, 0, v120_sabme, 3) == 0) {
+ /*
+ * We assume this is V.120.
+ */
+ circuit_set_dissector(circuit, v120_handle);
+ } else if (tvb_memeql(tvb, 0, ppp, 2) == 0) {
+ /*
+ * We assume this is PPP.
+ */
+ circuit_set_dissector(circuit, ppp_hdlc_handle);
+ }
+ break;
+ }
+ }
+
+ if (!try_circuit_dissector(pinfo->ctype, pinfo->circuit_id,
+ pinfo->fd->num, tvb, pinfo, tree))
+ call_dissector(data_handle, tvb, pinfo, tree);
+}
+
+void
+proto_register_isdn(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_isdn_channel,
+ { "Channel", "isdn.channel", FT_UINT8, BASE_DEC,
+ VALS(channel_vals), 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_isdn,
+ };
+ proto_isdn = proto_register_protocol("ISDN", "ISDN", "isdn");
+ proto_register_field_array(proto_isdn, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_isdn(void)
+{
+ dissector_handle_t isdn_handle;
+
+ /*
+ * Get handles for the LAPD, PPP, and V.120 dissectors.
+ */
+ lapd_handle = find_dissector("lapd");
+ ppp_hdlc_handle = find_dissector("ppp_hdlc");
+ v120_handle = find_dissector("v120");
+ data_handle = find_dissector("data");
+
+ isdn_handle = create_dissector_handle(dissect_isdn, proto_isdn);
+
+ dissector_add("wtap_encap", WTAP_ENCAP_ISDN, isdn_handle);
+}
diff --git a/epan/dissectors/packet-isis-clv.c b/epan/dissectors/packet-isis-clv.c
new file mode 100644
index 0000000000..371576118d
--- /dev/null
+++ b/epan/dissectors/packet-isis-clv.c
@@ -0,0 +1,590 @@
+/* packet-isis-clv.c
+ * Common CLV decode routines.
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "packet-osi.h"
+#include "packet-isis.h"
+#include "packet-isis-clv.h"
+#include "nlpid.h"
+
+static void
+free_g_string(void *arg)
+{
+ g_string_free(arg, TRUE);
+}
+
+/*
+ * Name: isis_dissect_area_address_clv()
+ *
+ * Description:
+ * Take an area address CLV and display it pieces. An area address
+ * CLV is n, x byte hex strings.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ int arealen,area_idx;
+ GString *gstr;
+
+ while ( length > 0 ) {
+ arealen = tvb_get_guint8(tvb, offset);
+ length--;
+ if (length<=0) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "short address (no length for payload)");
+ return;
+ }
+ if ( arealen > length) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "short address, packet says %d, we have %d left",
+ arealen, length );
+ return;
+ }
+
+ if ( tree ) {
+ /*
+ * Lets turn the area address into "standard"
+ * xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx format string.
+ * this is a private routine as the print_nsap_net in
+ * epan/osi_utils.c is incomplete and we need only
+ * a subset - actually some nice placing of dots ....
+ *
+ * We pick an initial size of 32 bytes.
+ */
+ gstr = g_string_sized_new(32);
+
+ /*
+ * Free the GString if we throw an exception.
+ */
+ CLEANUP_PUSH(free_g_string, gstr);
+
+ for (area_idx = 0; area_idx < arealen; area_idx++) {
+ g_string_sprintfa(gstr, "%02x",
+ tvb_get_guint8(tvb, offset+area_idx+1));
+ if (((area_idx & 1) == 0) &&
+ (area_idx + 1 < arealen)) {
+ g_string_sprintfa(gstr, ".");
+ }
+ }
+
+ /* and spit it out */
+ proto_tree_add_text ( tree, tvb, offset, arealen + 1,
+ "Area address (%d): %s", arealen, gstr->str );
+
+ /*
+ * We're done with the GString, so delete it and
+ * get rid of the cleanup handler.
+ */
+ CLEANUP_CALL_AND_POP;
+ }
+ offset += arealen + 1;
+ length -= arealen; /* length already adjusted for len fld*/
+ }
+}
+
+
+/*
+ * Name: isis_dissect_authentication_clv()
+ *
+ * Description:
+ * Take apart the CLV that hold authentication information. This
+ * is currently 1 octet auth type.
+ * the two defined authentication types
+ * are 1 for a clear text password and
+ * 54 for a HMAC-MD5 digest
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ guchar pw_type;
+ int auth_unsupported;
+ GString *gstr;
+
+ if ( length <= 0 ) {
+ return;
+ }
+
+ pw_type = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ length--;
+ auth_unsupported = FALSE;
+
+ gstr = g_string_new("");
+
+ /*
+ * Free the GString if we throw an exception.
+ */
+ CLEANUP_PUSH(free_g_string, gstr);
+
+ switch (pw_type) {
+ case 1:
+ g_string_sprintfa(gstr,
+ "clear text (1), password (length %d) = ", length);
+ if ( length > 0 ) {
+ g_string_sprintfa(gstr, "%s",
+ tvb_format_text(tvb, offset, length));
+ } else {
+ g_string_append(gstr, "no clear-text password found!!!");
+ }
+ break;
+ case 54:
+ g_string_sprintfa(gstr,
+ "hmac-md5 (54), password (length %d) = ", length);
+
+ if ( length == 16 ) {
+ g_string_sprintfa(gstr, "0x%02x", tvb_get_guint8(tvb, offset));
+ offset += 1;
+ length--;
+ while (length > 0) {
+ g_string_sprintfa(gstr, "%02x", tvb_get_guint8(tvb, offset));
+ offset += 1;
+ length--;
+ }
+ } else {
+ g_string_append(gstr,
+ "illegal hmac-md5 digest format (must be 16 bytes)");
+ }
+ break;
+ default:
+ g_string_sprintfa(gstr, "type 0x%02x (0x%02x): ", pw_type, length );
+ auth_unsupported=TRUE;
+ break;
+ }
+
+ proto_tree_add_text ( tree, tvb, offset - 1, length + 1, "%s", gstr->str );
+
+ /*
+ * We're done with the GString, so delete it and get rid of
+ * the cleanup handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
+ if ( auth_unsupported ) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "Unknown authentication type" );
+ }
+}
+
+/*
+ * Name: isis_ip_authentication_clv()
+ *
+ * Description:
+ * dump the IP authentication information found in TLV 133
+ * the CLV is standardized in rf1195, however all major
+ * implementations use TLV #10
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+
+
+void
+isis_dissect_ip_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ if ( !tree ) return; /* nothing to do! */
+
+ if ( length != 0 ) {
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "IP Authentication: %.*s", length,
+ tvb_get_ptr(tvb, offset, length) );
+ }
+}
+
+
+/*
+ * Name: isis_dissect_hostname_clv()
+ *
+ * Description:
+ * dump the hostname information found in TLV 137
+ * pls note that the hostname is not null terminated
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+
+
+void
+isis_dissect_hostname_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ if ( !tree ) return; /* nothing to do! */
+
+ if ( length == 0 ) {
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "Hostname: --none--" );
+ } else {
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "Hostname: %.*s", length,
+ tvb_get_ptr(tvb, offset, length) );
+ }
+}
+
+
+
+
+void
+isis_dissect_mt_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length,
+ int tree_id)
+{
+ guint16 mt_block;
+ char mt_desc[60];
+
+ while (length>0) {
+ /* length can only be a multiple of 2, otherwise there is
+ something broken -> so decode down until length is 1 */
+ if (length!=1) {
+ /* fetch two bytes */
+ mt_block=tvb_get_ntohs(tvb, offset);
+
+ /* mask out the lower 12 bits */
+ switch(mt_block&0x0fff) {
+ case 0:
+ strcpy(mt_desc,"IPv4 unicast");
+ break;
+ case 1:
+ strcpy(mt_desc,"In-Band Management");
+ break;
+ case 2:
+ strcpy(mt_desc,"IPv6 unicast");
+ break;
+ case 3:
+ strcpy(mt_desc,"Multicast");
+ break;
+ case 4095:
+ strcpy(mt_desc,"Development, Experimental or Proprietary");
+ break;
+ default:
+ strcpy(mt_desc,"Reserved for IETF Consensus");
+ break;
+ }
+ proto_tree_add_uint_format ( tree, tree_id, tvb, offset, 2,
+ mt_block,
+ "%s Topology (0x%03x)%s%s",
+ mt_desc,
+ mt_block&0xfff,
+ (mt_block&0x8000) ? "" : ", no sub-TLVs present",
+ (mt_block&0x4000) ? ", ATT bit set" : "" );
+ } else {
+ proto_tree_add_text ( tree, tvb, offset, 1,
+ "malformed MT-ID");
+ break;
+ }
+ length=length-2;
+ offset=offset+2;
+ }
+}
+
+
+/*
+ * Name: isis_dissect_ip_int_clv()
+ *
+ * Description:
+ * Take apart the CLV that lists all the IP interfaces. The
+ * meaning of which is slightly different for the different base packet
+ * types, but the display is not different. What we have is n ip
+ * addresses, plain and simple.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ * int : tree id to use for proto tree.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_ip_int_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length, int tree_id)
+{
+ if ( length <= 0 ) {
+ return;
+ }
+
+ while ( length > 0 ) {
+ if ( length < 4 ) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "Short IP interface address (%d vs 4)",length );
+ return;
+ }
+
+ if ( tree ) {
+ proto_tree_add_item(tree, tree_id, tvb, offset, 4, FALSE);
+ }
+ offset += 4;
+ length -= 4;
+ }
+}
+
+/*
+ * Name: isis_dissect_ipv6_int_clv()
+ *
+ * Description:
+ * Take apart the CLV that lists all the IPv6 interfaces. The
+ * meaning of which is slightly different for the different base packet
+ * types, but the display is not different. What we have is n ip
+ * addresses, plain and simple.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ * int : tree id to use for proto tree.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_ipv6_int_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length, int tree_id)
+{
+ guint8 addr [16];
+
+ if ( length <= 0 ) {
+ return;
+ }
+
+ while ( length > 0 ) {
+ if ( length < 16 ) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "Short IPv6 interface address (%d vs 16)",length );
+ return;
+ }
+ tvb_memcpy(tvb, addr, offset, sizeof(addr));
+ if ( tree ) {
+ proto_tree_add_ipv6(tree, tree_id, tvb, offset, 16, addr);
+ }
+ offset += 16;
+ length -= 16;
+ }
+}
+
+
+/*
+ * Name: isis_dissect_te_router_id_clv()
+ *
+ * Description:
+ * Display the Traffic Engineering Router ID TLV #134.
+ * This TLV is like the IP Interface TLV, except that
+ * only _one_ IP address is present
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ * int : tree id to use for proto tree.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_te_router_id_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length, int tree_id)
+{
+ if ( length <= 0 ) {
+ return;
+ }
+
+ if ( length != 4 ) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "malformed Traffic Engineering Router ID (%d vs 4)",length );
+ return;
+ }
+ if ( tree ) {
+ proto_tree_add_item(tree, tree_id, tvb, offset, 4, FALSE);
+ }
+}
+
+/*
+ * Name: isis_dissect_nlpid_clv()
+ *
+ * Description:
+ * Take apart a NLPID packet and display it. The NLPID (for intergrated
+ * ISIS, contains n network layer protocol IDs that the box supports.
+ * Our display buffer we use is upto 255 entries, 6 bytes per (0x00, )
+ * plus 1 for zero termination. We just just 256*6 for simplicity.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length)
+{
+ char sbuf[256*6];
+ char *s = sbuf;
+ int hlen = length;
+ int old_offset = offset;
+
+ if ( !tree ) return; /* nothing to do! */
+
+ while ( length-- > 0 ) {
+ if (s != sbuf ) {
+ s += sprintf ( s, ", " );
+ }
+ s += sprintf ( s, "%s (0x%02x)",
+ val_to_str(tvb_get_guint8(tvb, offset), nlpid_vals,
+ "Unknown"), tvb_get_guint8(tvb, offset));
+ offset++;
+ }
+
+ if ( hlen == 0 ) {
+ sprintf ( sbuf, "--none--" );
+ }
+
+ proto_tree_add_text ( tree, tvb, old_offset, hlen,
+ "NLPID(s): %s", sbuf );
+}
+
+/*
+ * Name: isis_dissect_clvs()
+ *
+ * Description:
+ * Dispatch routine to shred all the CLVs in a packet. We just
+ * walk through the clv entries in the packet. For each one, we
+ * search the passed in valid clv's for this protocol (opts) for
+ * a matching code. If found, we add to the display tree and
+ * then call the dissector. If it is not, we just post an
+ * "unknown" clv entry using the passed in unknown clv tree id.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * isis_clv_handle_t * : NULL dissector terminated array of codes
+ * and handlers (along with tree text and tree id's).
+ * int : length of CLV area.
+ * int : length of IDs in packet.
+ * int : unknown clv tree id
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_clvs(tvbuff_t *tvb, proto_tree *tree, int offset,
+ const isis_clv_handle_t *opts, int len, int id_length,
+ int unknown_tree_id)
+{
+ guint8 code;
+ guint8 length;
+ int q;
+ proto_item *ti;
+ proto_tree *clv_tree;
+ int adj;
+
+ while ( len > 0 ) {
+ code = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ length = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ adj = (sizeof(code) + sizeof(length) + length);
+ len -= adj;
+ if ( len < 0 ) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "Short CLV header (%d vs %d)",
+ adj, len + adj );
+ return;
+ }
+ q = 0;
+ while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
+ q++;
+ }
+ if ( opts[q].dissect ) {
+ if (tree) {
+ /* adjust by 2 for code/len octets */
+ ti = proto_tree_add_text(tree, tvb, offset - 2,
+ length + 2, "%s (%u)",
+ opts[q].tree_text, length );
+ clv_tree = proto_item_add_subtree(ti,
+ *opts[q].tree_id );
+ } else {
+ clv_tree = NULL;
+ }
+ opts[q].dissect(tvb, clv_tree, offset,
+ id_length, length);
+ } else {
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset - 2,
+ length + 2, "Unknown code %u (%u)",
+ code, length);
+ clv_tree = proto_item_add_subtree(ti,
+ unknown_tree_id );
+ } else {
+ clv_tree = NULL;
+ }
+ }
+ offset += length;
+ }
+}
diff --git a/epan/dissectors/packet-isis-clv.h b/epan/dissectors/packet-isis-clv.h
new file mode 100644
index 0000000000..90d4a7bc3e
--- /dev/null
+++ b/epan/dissectors/packet-isis-clv.h
@@ -0,0 +1,114 @@
+/* packet-isis-clv.h
+ * Declares for common clv decoding functions.
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_ISIS_CLV_H
+#define _PACKET_ISIS_CLV_H
+
+/*
+ * A CLV is a tuple of a type, length and a value and is normally used for
+ * encoding information in all sorts of places.
+ * IS-IS uses a uniform CLV code space that is shared across
+ * all PDU Types.
+ *
+ * list taken from rfc3359 plus some memory from veterans ;-)
+ */
+
+#define ISIS_CLV_AREA_ADDRESS 1 /* iso10589 */
+#define ISIS_CLV_IS_REACH 2 /* iso10589 */
+#define ISIS_CLV_ES_NEIGHBORS 3 /* iso10589 */
+#define ISIS_CLV_PARTITION_DIS 4 /* iso10589 */
+#define ISIS_CLV_PREFIX_NEIGHBORS 5 /* iso10589 */
+#define ISIS_CLV_IS_NEIGHBORS 6 /* iso10589 */
+#define ISIS_CLV_IS_NEIGHBORS_VARLEN 7 /* iso10589 */
+#define ISIS_CLV_PADDING 8 /* iso10589 */
+#define ISIS_CLV_LSP_ENTRIES 9 /* iso10589 */
+#define ISIS_CLV_AUTHENTICATION 10 /* iso10589, rfc3567 */
+#define ISIS_CLV_CHECKSUM 12 /* rfc3358 */
+#define ISIS_CLV_LSP_BUFFERSIZE 14 /* iso10589 rev2 */
+#define ISIS_CLV_EXTD_IS_REACH 22 /* draft-ietf-isis-traffic-05 */
+#define ISIS_CLV_IS_ALIAS_ID 24 /* draft-ietf-isis-ext-lsp-frags-02 */
+#define ISIS_CLV_INT_IP_REACH 128 /* rfc1195, rfc2966 */
+#define ISIS_CLV_PROTOCOLS_SUPPORTED 129 /* rfc1195 */
+#define ISIS_CLV_EXT_IP_REACH 130 /* rfc1195, rfc2966 */
+#define ISIS_CLV_IDRP_INFO 131 /* rfc1195 */
+#define ISIS_CLV_IP_ADDR 132 /* rfc1195 */
+#define ISIS_CLV_IP_AUTHENTICATION 133 /* rfc1195, depreciated */
+#define ISIS_CLV_TE_ROUTER_ID 134 /* draft-ietf-isis-traffic-05 */
+#define ISIS_CLV_EXTD_IP_REACH 135 /* draft-ietf-isis-traffic-05 */
+#define ISIS_CLV_HOSTNAME 137 /* rfc2763 */
+#define ISIS_CLV_SHARED_RISK_GROUP 138 /* draft-ietf-isis-gmpls-extensions */
+#define ISIS_CLV_RESTART 211 /* draft-ietf-isis-restart-01 */
+#define ISIS_CLV_MT_IS_REACH 222 /* draft-ietf-isis-wg-multi-topology-05 */
+#define ISIS_CLV_MT_SUPPORTED 229 /* draft-ietf-isis-wg-multi-topology-05 */
+#define ISIS_CLV_IP6_ADDR 232 /* draft-ietf-isis-ipv6-02 */
+#define ISIS_CLV_MT_IP_REACH 235 /* draft-ietf-isis-wg-multi-topology-05 */
+#define ISIS_CLV_IP6_REACH 236 /* draft-ietf-isis-ipv6-02 */
+#define ISIS_CLV_MT_IP6_REACH 237 /* draft-ietf-isis-wg-multi-topology-05 */
+#define ISIS_CLV_PTP_ADJ_STATE 240 /* rfc3373 */
+#define ISIS_CLV_IIH_SEQNR 241 /* draft-shen-isis-iih-sequence-00 */
+#define ISIS_CLV_VENDOR_PRIVATE 250 /* draft-ietf-isis-proprietary-tlv-00 */
+
+/*
+ * Our sub-packet dismantle structure for CLV's
+ */
+typedef struct {
+ int optcode; /* code for option */
+ char *tree_text; /* text for fold out */
+ gint *tree_id; /* id for add_item */
+ void (*dissect)(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int id_length, int length);
+} isis_clv_handle_t;
+
+/*
+ * Published API functions. NOTE, this are "local" API functions and
+ * are only valid from with isis decodes.
+ */
+extern void isis_dissect_clvs(tvbuff_t *tvb, proto_tree *tree, int offset,
+ const isis_clv_handle_t *opts, int len, int id_length,
+ int unknown_tree_id);
+
+extern void isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length);
+extern void isis_dissect_te_router_id_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length, int tree_id);
+extern void isis_dissect_ipv6_int_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length, int tree_id);
+extern void isis_dissect_ip_int_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length, int tree_id);
+extern void isis_dissect_mt_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length, int tree_id);
+extern void isis_dissect_hostname_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length);
+extern void isis_dissect_authentication_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length);
+extern void isis_dissect_ip_authentication_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length);
+extern void isis_dissect_area_address_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length);
+
+extern void isis_dissect_metric(tvbuff_t *tvb, proto_tree *tree, int offset,
+ guint8 value, char *pstr, int force_supported);
+
+#endif /* _PACKET_ISIS_CLV_H */
diff --git a/epan/dissectors/packet-isis-hello.c b/epan/dissectors/packet-isis-hello.c
new file mode 100644
index 0000000000..f7518d5bfa
--- /dev/null
+++ b/epan/dissectors/packet-isis-hello.c
@@ -0,0 +1,928 @@
+/* packet-isis-hello.c
+ * Routines for decoding isis hello packets and their CLVs
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-osi.h"
+#include "packet-isis.h"
+#include "packet-isis-clv.h"
+#include "packet-isis-hello.h"
+#include "epan/resolv.h"
+
+/* hello packets */
+static int hf_isis_hello_circuit_reserved = -1;
+static int hf_isis_hello_source_id = -1;
+static int hf_isis_hello_holding_timer = -1;
+static int hf_isis_hello_pdu_length = -1;
+static int hf_isis_hello_priority_reserved = -1;
+static int hf_isis_hello_lan_id = -1;
+static int hf_isis_hello_local_circuit_id = -1;
+static int hf_isis_hello_clv_ipv4_int_addr = -1;
+static int hf_isis_hello_clv_ipv6_int_addr = -1;
+static int hf_isis_hello_clv_ptp_adj = -1;
+static int hf_isis_hello_clv_mt = -1;
+
+static gint ett_isis_hello = -1;
+static gint ett_isis_hello_clv_area_addr = -1;
+static gint ett_isis_hello_clv_is_neighbors = -1;
+static gint ett_isis_hello_clv_padding = -1;
+static gint ett_isis_hello_clv_unknown = -1;
+static gint ett_isis_hello_clv_nlpid = -1;
+static gint ett_isis_hello_clv_authentication = -1;
+static gint ett_isis_hello_clv_ip_authentication = -1;
+static gint ett_isis_hello_clv_ipv4_int_addr = -1;
+static gint ett_isis_hello_clv_ipv6_int_addr = -1;
+static gint ett_isis_hello_clv_ptp_adj = -1;
+static gint ett_isis_hello_clv_mt = -1;
+static gint ett_isis_hello_clv_restart = -1;
+static gint ett_isis_hello_clv_checksum = -1;
+
+static const value_string isis_hello_circuit_type_vals[] = {
+ { ISIS_HELLO_TYPE_RESERVED, "Reserved 0 (discard PDU)"},
+ { ISIS_HELLO_TYPE_LEVEL_1, "Level 1 only"},
+ { ISIS_HELLO_TYPE_LEVEL_2, "Level 2 only"},
+ { ISIS_HELLO_TYPE_LEVEL_12, "Level 1 and 2"},
+ { 0, NULL} };
+
+/*
+ * Predclare dissectors for use in clv dissection.
+ */
+static void dissect_hello_padding_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_is_neighbors_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_ptp_adj_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_area_address_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_authentication_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_ip_authentication_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_checksum_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_ipv6_int_addr_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_ip_int_addr_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_mt_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_nlpid_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_hello_restart_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+
+
+static const isis_clv_handle_t clv_l1_hello_opts[] = {
+ {
+ ISIS_CLV_AREA_ADDRESS,
+ "Area address(es)",
+ &ett_isis_hello_clv_area_addr,
+ dissect_hello_area_address_clv
+ },
+ {
+ ISIS_CLV_IS_NEIGHBORS,
+ "IS Neighbor(s)",
+ &ett_isis_hello_clv_is_neighbors,
+ dissect_hello_is_neighbors_clv
+ },
+ {
+ ISIS_CLV_PADDING,
+ "Padding",
+ &ett_isis_hello_clv_padding,
+ dissect_hello_padding_clv
+ },
+ {
+ ISIS_CLV_PROTOCOLS_SUPPORTED,
+ "Protocols Supported",
+ &ett_isis_hello_clv_nlpid,
+ dissect_hello_nlpid_clv
+ },
+ {
+ ISIS_CLV_IP_ADDR,
+ "IP Interface address(es)",
+ &ett_isis_hello_clv_ipv4_int_addr,
+ dissect_hello_ip_int_addr_clv
+ },
+ {
+ ISIS_CLV_IP6_ADDR,
+ "IPv6 Interface address(es)",
+ &ett_isis_hello_clv_ipv6_int_addr,
+ dissect_hello_ipv6_int_addr_clv
+ },
+ {
+ ISIS_CLV_RESTART,
+ "Restart Signaling",
+ &ett_isis_hello_clv_restart,
+ dissect_hello_restart_clv
+ },
+ {
+ ISIS_CLV_AUTHENTICATION,
+ "Authentication",
+ &ett_isis_hello_clv_authentication,
+ dissect_hello_authentication_clv
+ },
+ {
+ ISIS_CLV_IP_AUTHENTICATION,
+ "IP Authentication",
+ &ett_isis_hello_clv_ip_authentication,
+ dissect_hello_ip_authentication_clv
+ },
+ {
+ ISIS_CLV_MT_SUPPORTED,
+ "Multi Topology",
+ &ett_isis_hello_clv_mt,
+ dissect_hello_mt_clv
+ },
+ {
+ ISIS_CLV_CHECKSUM,
+ "Checksum",
+ &ett_isis_hello_clv_checksum,
+ dissect_hello_checksum_clv
+ },
+ {
+ 0,
+ "",
+ NULL,
+ NULL
+ }
+};
+
+static const isis_clv_handle_t clv_l2_hello_opts[] = {
+ {
+ ISIS_CLV_AREA_ADDRESS,
+ "Area address(es)",
+ &ett_isis_hello_clv_area_addr,
+ dissect_hello_area_address_clv
+ },
+ {
+ ISIS_CLV_IS_NEIGHBORS,
+ "IS Neighbor(s)",
+ &ett_isis_hello_clv_is_neighbors,
+ dissect_hello_is_neighbors_clv
+ },
+ {
+ ISIS_CLV_PADDING,
+ "Padding",
+ &ett_isis_hello_clv_padding,
+ dissect_hello_padding_clv
+ },
+ {
+ ISIS_CLV_PROTOCOLS_SUPPORTED,
+ "Protocols Supported",
+ &ett_isis_hello_clv_nlpid,
+ dissect_hello_nlpid_clv
+ },
+ {
+ ISIS_CLV_IP_ADDR,
+ "IP Interface address(es)",
+ &ett_isis_hello_clv_ipv4_int_addr,
+ dissect_hello_ip_int_addr_clv
+ },
+ {
+ ISIS_CLV_IP6_ADDR,
+ "IPv6 Interface address(es)",
+ &ett_isis_hello_clv_ipv6_int_addr,
+ dissect_hello_ipv6_int_addr_clv
+ },
+ {
+ ISIS_CLV_AUTHENTICATION,
+ "Authentication",
+ &ett_isis_hello_clv_authentication,
+ dissect_hello_authentication_clv
+ },
+ {
+ ISIS_CLV_IP_AUTHENTICATION,
+ "IP Authentication",
+ &ett_isis_hello_clv_ip_authentication,
+ dissect_hello_ip_authentication_clv
+ },
+ {
+ ISIS_CLV_RESTART,
+ "Restart Signaling",
+ &ett_isis_hello_clv_restart,
+ dissect_hello_restart_clv
+ },
+ {
+ ISIS_CLV_MT_SUPPORTED,
+ "Multi Topology",
+ &ett_isis_hello_clv_mt,
+ dissect_hello_mt_clv
+ },
+ {
+ ISIS_CLV_CHECKSUM,
+ "Checksum",
+ &ett_isis_hello_clv_checksum,
+ dissect_hello_checksum_clv
+ },
+ {
+ 0,
+ "",
+ NULL,
+ NULL
+ }
+};
+
+static const isis_clv_handle_t clv_ptp_hello_opts[] = {
+ {
+ ISIS_CLV_AREA_ADDRESS,
+ "Area address(es)",
+ &ett_isis_hello_clv_area_addr,
+ dissect_hello_area_address_clv
+ },
+ {
+ ISIS_CLV_PADDING,
+ "Padding",
+ &ett_isis_hello_clv_padding,
+ dissect_hello_padding_clv
+ },
+ {
+ ISIS_CLV_PROTOCOLS_SUPPORTED,
+ "Protocols Supported",
+ &ett_isis_hello_clv_nlpid,
+ dissect_hello_nlpid_clv
+ },
+ {
+ ISIS_CLV_IP_ADDR,
+ "IP Interface address(es)",
+ &ett_isis_hello_clv_ipv4_int_addr,
+ dissect_hello_ip_int_addr_clv
+ },
+ {
+ ISIS_CLV_IP6_ADDR,
+ "IPv6 Interface address(es)",
+ &ett_isis_hello_clv_ipv6_int_addr,
+ dissect_hello_ipv6_int_addr_clv
+ },
+ {
+ ISIS_CLV_AUTHENTICATION,
+ "Authentication",
+ &ett_isis_hello_clv_authentication,
+ dissect_hello_authentication_clv
+ },
+ {
+ ISIS_CLV_IP_AUTHENTICATION,
+ "IP Authentication",
+ &ett_isis_hello_clv_ip_authentication,
+ dissect_hello_ip_authentication_clv
+ },
+ {
+ ISIS_CLV_RESTART,
+ "Restart Option",
+ &ett_isis_hello_clv_restart,
+ dissect_hello_restart_clv
+ },
+ {
+ ISIS_CLV_PTP_ADJ_STATE,
+ "Point-to-point Adjacency State",
+ &ett_isis_hello_clv_ptp_adj,
+ dissect_hello_ptp_adj_clv
+ },
+ {
+ ISIS_CLV_MT_SUPPORTED,
+ "Multi Topology",
+ &ett_isis_hello_clv_mt,
+ dissect_hello_mt_clv
+ },
+ {
+ ISIS_CLV_CHECKSUM,
+ "Checksum",
+ &ett_isis_hello_clv_checksum,
+ dissect_hello_checksum_clv
+ },
+ {
+ 0,
+ "",
+ NULL,
+ NULL
+ }
+};
+
+
+/*
+ * Name: dissect_hello_restart_clv()
+ *
+ * Description:
+ * Decode for a restart clv - only found in IIHs
+ * hence no call in the common clv dissector
+ *
+ */
+
+static void
+dissect_hello_restart_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ int restart_options;
+
+ if (length != 3) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "malformed TLV (%d vs 3)",
+ length, 3 );
+ return;
+ }
+
+ restart_options = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text ( tree, tvb, offset, 1,
+ "Restart Request bit %s, "
+ "Restart Acknowledgement bit %s",
+ ISIS_MASK_RESTART_RR(restart_options) ? "set" : "clear",
+ ISIS_MASK_RESTART_RA(restart_options) ? "set" : "clear");
+ proto_tree_add_text ( tree, tvb, offset+1, 2,
+ "Remaining holding time: %us",
+ tvb_get_ntohs(tvb, offset+1) );
+}
+
+/*
+ * Name: dissect_hello_nlpid_clv()
+ *
+ * Description:
+ * Decode for a hello packets NLPID clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_hello_nlpid_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ isis_dissect_nlpid_clv(tvb, tree, offset, length);
+}
+
+/*
+ * Name: dissect_hello_mt_clv()
+ *
+ * Description:
+ * Decode for a hello packets Multi Topology clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+
+static void
+dissect_hello_mt_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ isis_dissect_mt_clv(tvb, tree, offset, length,
+ hf_isis_hello_clv_mt );
+}
+
+/*
+ * Name: dissect_hello_ip_int_addr_clv()
+ *
+ * Description:
+ * Decode for a hello packets ip interface addr clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_hello_ip_int_addr_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ isis_dissect_ip_int_clv(tvb, tree, offset, length,
+ hf_isis_hello_clv_ipv4_int_addr );
+}
+
+/*
+ * Name: dissect_hello_ipv6_int_addr_clv()
+ *
+ * Description:
+ * Decode for a hello packets ipv6 interface addr clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_hello_ipv6_int_addr_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ isis_dissect_ipv6_int_clv(tvb, tree, offset, length,
+ hf_isis_hello_clv_ipv6_int_addr );
+}
+
+/*
+ * Name: dissect_hello_authentication_clv()
+ *
+ * Description:
+ * Decode for a hello packets authenticaion clv.
+ * Calls into the CLV common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_hello_authentication_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ isis_dissect_authentication_clv(tvb, tree, offset, length);
+}
+
+/*
+ * Name: dissect_hello_ip_authentication_clv()
+ *
+ * Description:
+ * Decode for a hello packets IP authenticaion clv.
+ * Calls into the CLV common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_hello_ip_authentication_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ isis_dissect_ip_authentication_clv(tvb, tree, offset, length);
+}
+
+/*
+ * Name: dissect_hello_checksum_clv()
+ *
+ * Description:
+ * dump and verify the optional checksum in TLV 12
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+
+static void
+dissect_hello_checksum_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length) {
+
+ guint16 pdu_length,checksum, cacl_checksum=0;
+
+ if (tree) {
+ if ( length != 2 ) {
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "incorrect checksum length (%u), should be (2)", length );
+ return;
+ }
+
+ checksum = tvb_get_ntohs(tvb, offset);
+
+ /* the check_and_get_checksum() function needs to know how big
+ * the packet is. we can either pass through the pdu-len through several layers
+ * of dissectors and wrappers or extract the PDU length field from the PDU specific header
+ * which is offseted 17 bytes in IIHs (relative to the beginning of the IS-IS packet) */
+
+ pdu_length = tvb_get_ntohs(tvb, 17);
+
+ /* unlike the LSP checksum verification which starts at an offset of 12 we start at offset 0*/
+ switch (check_and_get_checksum(tvb, 0, pdu_length, checksum, offset, &cacl_checksum))
+ {
+
+ case NO_CKSUM :
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "Checksum: 0x%04x (unused)", checksum);
+ break;
+ case DATA_MISSING :
+ isis_dissect_unknown(tvb, tree, offset,
+ "packet length %d went beyond packet",
+ tvb_length_remaining(tvb, 0));
+ break;
+ case CKSUM_NOT_OK :
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ checksum,
+ cacl_checksum);
+ break;
+ case CKSUM_OK :
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "Checksum: 0x%04x (correct)", checksum);
+ break;
+ default :
+ g_message("'check_and_get_checksum' returned an invalid value");
+ }
+ }
+}
+
+
+
+/*
+ * Name: dissect_hello_area_address_clv()
+ *
+ * Description:
+ * Decode for a hello packets area address clv.
+ * Calls into the CLV common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_hello_area_address_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ isis_dissect_area_address_clv(tvb, tree, offset, length);
+}
+
+
+
+static void
+dissect_hello_ptp_adj_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ static const value_string adj_state_vals[] = {
+ { 0, "Up" },
+ { 1, "Initializing" },
+ { 2, "Down" },
+ { 0, NULL }
+ };
+ guint8 adj_state;
+ char *adj_state_str;
+
+ adj_state = tvb_get_guint8(tvb, offset);
+ adj_state_str = val_to_str(adj_state, adj_state_vals, "Unknown (%u)");
+ switch(length) {
+ case 1:
+ proto_tree_add_text ( tree, tvb, offset, 1,
+ "Adjacency State: %s", adj_state_str );
+ break;
+ case 5:
+ proto_tree_add_text ( tree, tvb, offset, 1,
+ "Adjacency State: %s", adj_state_str );
+ proto_tree_add_text ( tree, tvb, offset+1, 4,
+ "Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+1) );
+ break;
+ case 11:
+ proto_tree_add_text ( tree, tvb, offset, 1,
+ "Adjacency State: %s", adj_state_str );
+ proto_tree_add_text ( tree, tvb, offset+1, 4,
+ "Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+1) );
+ proto_tree_add_text ( tree, tvb, offset+5, 6,
+ "Neighbor SystemID: %s", print_system_id( tvb_get_ptr(tvb, offset+5, 6), 6 ) );
+ break;
+ case 15:
+ proto_tree_add_text ( tree, tvb, offset, 1,
+ "Adjacency State: %s", adj_state_str );
+ proto_tree_add_text ( tree, tvb, offset+1, 4,
+ "Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+1) );
+ proto_tree_add_text ( tree, tvb, offset+5, 6,
+ "Neighbor SystemID: %s", print_system_id( tvb_get_ptr(tvb, offset+5, 6), 6 ) );
+ proto_tree_add_text ( tree, tvb, offset+11, 4,
+ "Neighbor Extended Local circuit ID: 0x%08x", tvb_get_ntohl(tvb, offset+11) );
+ break;
+ default:
+ isis_dissect_unknown(tvb, tree, offset,
+ "malformed TLV (%d vs 1,5,11,15)", length );
+ return;
+ }
+}
+
+/*
+ * Name: isis_dissect_is_neighbors_clv()
+ *
+ * Description:
+ * Take apart a IS neighbor packet. A neighbor is n 6 byte packets.
+ * (they tend to be an 802.3 MAC address, but its not required).
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_hello_is_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ while ( length > 0 ) {
+ if (length<6) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "short is neighbor (%d vs 6)", length );
+ return;
+ }
+ /*
+ * Lets turn the area address into "standard" 0000.0000.etc
+ * format string.
+ */
+ if ( tree ) {
+ proto_tree_add_text ( tree, tvb, offset, 6,
+ "IS Neighbor: %s", get_ether_name( tvb_get_ptr(tvb, offset, 6)) );
+ }
+ offset += 6;
+ length -= 6;
+ }
+}
+
+/*
+ * Name: dissect_hello_padding_clv()
+ *
+ * Description:
+ * Decode for a hello packet's padding clv. Padding does nothing,
+ * so we just return.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void
+ */
+static void
+dissect_hello_padding_clv(tvbuff_t *tvb _U_, proto_tree *tree _U_, int offset _U_,
+ int id_length _U_, int length _U_)
+{
+ /* nothing to do here! */
+}
+
+
+/*
+ * Name: isis_dissect_isis_hello()
+ *
+ * Description:
+ * This procedure rips apart the various types of ISIS hellos. L1H and
+ * L2H's are identical for the most part, while the PTP hello has
+ * a shorter header.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to add to. May be NULL.
+ * int offset : our offset into packet data.
+ * int : hello type, a la packet-isis.h ISIS_TYPE_* values
+ * int : header length of packet.
+ * int : length of IDs in packet.
+ *
+ * Output:
+ * void, will modify proto_tree if not NULL.
+ */
+void
+isis_dissect_isis_hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
+ int hello_type, int header_length, int id_length)
+{
+ proto_item *ti;
+ proto_tree *hello_tree = NULL;
+ int len;
+ guint8 octet;
+ const guint8 *source_id;
+ guint16 pdu_length;
+ const guint8 *lan_id;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "ISIS HELLO");
+ hello_tree = proto_item_add_subtree(ti, ett_isis_hello);
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(hello_tree,
+ hf_isis_hello_circuit_reserved,
+ tvb, offset, 1, octet,
+ "Circuit type : %s, reserved(0x%02x == 0)",
+ val_to_str(octet&ISIS_HELLO_CTYPE_MASK,
+ isis_hello_circuit_type_vals,
+ "Unknown (0x%x)"),
+ octet&ISIS_HELLO_CT_RESERVED_MASK
+ );
+ }
+ offset += 1;
+
+ if (tree) {
+ source_id = tvb_get_ptr(tvb, offset, id_length);
+ proto_tree_add_bytes_format(hello_tree, hf_isis_hello_source_id, tvb,
+ offset, id_length, source_id,
+ "System-ID {Sender of PDU} : %s",
+ print_system_id( source_id, id_length ) );
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", System-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length), id_length ) );
+ }
+ offset += id_length;
+
+ if (tree) {
+ proto_tree_add_item(hello_tree, hf_isis_hello_holding_timer, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ pdu_length = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(hello_tree, hf_isis_hello_pdu_length, tvb,
+ offset, 2, pdu_length);
+ }
+ offset += 2;
+
+ if (hello_type == ISIS_TYPE_PTP_HELLO) {
+ if (tree) {
+ proto_tree_add_item(hello_tree, hf_isis_hello_local_circuit_id, tvb,
+ offset, 1, FALSE );
+ }
+ offset += 1;
+ } else {
+ if (tree) {
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(hello_tree, hf_isis_hello_priority_reserved, tvb,
+ offset, 1, octet,
+ "Priority : %d, reserved(0x%02x == 0)",
+ octet&ISIS_HELLO_PRIORITY_MASK,
+ octet&ISIS_HELLO_P_RESERVED_MASK );
+ }
+ offset += 1;
+
+ if (tree) {
+ lan_id = tvb_get_ptr(tvb, offset, id_length+1);
+ proto_tree_add_bytes_format(hello_tree, hf_isis_hello_lan_id, tvb,
+ offset, id_length + 1, lan_id,
+ "System-ID {Designated IS} : %s",
+ print_system_id( lan_id, id_length + 1 ) );
+ }
+ offset += id_length + 1;
+ }
+
+ len = pdu_length;
+ len -= header_length;
+ if (len < 0) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "Packet header length %d went beyond packet",
+ header_length );
+ return;
+ }
+ /*
+ * Now, we need to decode our CLVs. We need to pass in
+ * our list of valid ones!
+ */
+ if (hello_type == ISIS_TYPE_L1_HELLO){
+ isis_dissect_clvs(tvb, hello_tree, offset,
+ clv_l1_hello_opts, len, id_length,
+ ett_isis_hello_clv_unknown);
+ } else if (hello_type == ISIS_TYPE_L2_HELLO) {
+ isis_dissect_clvs(tvb, hello_tree, offset,
+ clv_l2_hello_opts, len, id_length,
+ ett_isis_hello_clv_unknown);
+ } else {
+ isis_dissect_clvs(tvb, hello_tree, offset,
+ clv_ptp_hello_opts, len, id_length,
+ ett_isis_hello_clv_unknown);
+ }
+}
+
+/*
+ * Name: isis_register_hello()
+ *
+ * Description:
+ * Register our protocol sub-sets with protocol manager.
+ *
+ * Input:
+ * int : protocol index for the ISIS protocol
+ *
+ * Output:
+ * void
+ */
+void
+isis_register_hello(int proto_isis) {
+ static hf_register_info hf[] = {
+ { &hf_isis_hello_circuit_reserved,
+ { "Circuit type ", "isis.hello.circuit_type",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_hello_source_id,
+ { "SystemID{ Sender of PDU } ", "isis.hello.source_id",
+ FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_hello_holding_timer,
+ { "Holding timer ", "isis.hello.holding_timer",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_hello_pdu_length,
+ { "PDU length ", "isis.hello.pdu_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_hello_priority_reserved,
+ { "Priority ", "isis.hello.priority",
+ FT_UINT8, BASE_DEC, NULL, ISIS_HELLO_P_RESERVED_MASK, "", HFILL }},
+
+ { &hf_isis_hello_lan_id,
+ { "SystemID{ Designated IS } ", "isis.hello.lan_id",
+ FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_hello_local_circuit_id,
+ { "Local circuit ID ", "isis.hello.local_circuit_id",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_hello_clv_ipv4_int_addr,
+ { "IPv4 interface address ", "isis.hello.clv_ipv4_int_addr",
+ FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_hello_clv_ipv6_int_addr,
+ { "IPv6 interface address ", "isis.hello.clv_ipv6_int_addr",
+ FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_hello_clv_ptp_adj,
+ { "Point-to-point Adjacency ", "isis.hello.clv_ptp_adj",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_hello_clv_mt,
+ { "MT-ID ", "isis.hello.clv_mt",
+ FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_isis_hello,
+ &ett_isis_hello_clv_area_addr,
+ &ett_isis_hello_clv_is_neighbors,
+ &ett_isis_hello_clv_padding,
+ &ett_isis_hello_clv_unknown,
+ &ett_isis_hello_clv_nlpid,
+ &ett_isis_hello_clv_authentication,
+ &ett_isis_hello_clv_ip_authentication,
+ &ett_isis_hello_clv_ipv4_int_addr,
+ &ett_isis_hello_clv_ipv6_int_addr,
+ &ett_isis_hello_clv_ptp_adj,
+ &ett_isis_hello_clv_mt,
+ &ett_isis_hello_clv_restart,
+ &ett_isis_hello_clv_checksum
+ };
+
+ proto_register_field_array(proto_isis, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/epan/dissectors/packet-isis-hello.h b/epan/dissectors/packet-isis-hello.h
new file mode 100644
index 0000000000..31ab933958
--- /dev/null
+++ b/epan/dissectors/packet-isis-hello.h
@@ -0,0 +1,57 @@
+/* packet-isis-hello.h
+ * Declares for hello handling inside isis.
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_ISIS_HELLO_H
+#define _PACKET_ISIS_HELLO_H
+
+/*
+ * Declarations for L1/L2 hello base header.
+ */
+#define ISIS_HELLO_CTYPE_MASK 0x03
+#define ISIS_HELLO_CT_RESERVED_MASK 0xfc
+#define ISIS_HELLO_PRIORITY_MASK 0x7f
+#define ISIS_HELLO_P_RESERVED_MASK 0x80
+
+#define ISIS_HELLO_TYPE_RESERVED 0
+#define ISIS_HELLO_TYPE_LEVEL_1 1
+#define ISIS_HELLO_TYPE_LEVEL_2 2
+#define ISIS_HELLO_TYPE_LEVEL_12 3
+
+/*
+ * misc. bittest macros
+ */
+
+#define ISIS_MASK_RESTART_RR(x) ((x)&0x1)
+#define ISIS_MASK_RESTART_RA(x) ((x)&0x2)
+
+/*
+ * Published API functions. NOTE, this are "local" API functions and
+ * are only valid from with isis decodes.
+ */
+extern void isis_dissect_isis_hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int hello_type, int header_length,int id_length);
+extern void isis_register_hello(int proto_isis);
+
+#endif /* _PACKET_ISIS_HELLO_H */
diff --git a/epan/dissectors/packet-isis-lsp.c b/epan/dissectors/packet-isis-lsp.c
new file mode 100644
index 0000000000..36d975e924
--- /dev/null
+++ b/epan/dissectors/packet-isis-lsp.c
@@ -0,0 +1,2008 @@
+/* packet-isis-lsp.c
+ * Routines for decoding isis lsp packets and their CLVs
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include "epan/ipv4.h"
+#include <epan/packet.h>
+#include "packet-osi.h"
+#include "packet-ipv6.h"
+#include "packet-isis.h"
+#include "packet-isis-clv.h"
+#include "packet-isis-lsp.h"
+#include <epan/resolv.h>
+
+/* lsp packets */
+static int hf_isis_lsp_pdu_length = -1;
+static int hf_isis_lsp_remaining_life = -1;
+static int hf_isis_lsp_sequence_number = -1;
+static int hf_isis_lsp_checksum = -1;
+static int hf_isis_lsp_checksum_bad = -1;
+static int hf_isis_lsp_clv_ipv4_int_addr = -1;
+static int hf_isis_lsp_clv_ipv6_int_addr = -1;
+static int hf_isis_lsp_clv_te_router_id = -1;
+static int hf_isis_lsp_clv_mt = -1;
+static int hf_isis_lsp_p = -1;
+static int hf_isis_lsp_att = -1;
+static int hf_isis_lsp_hippity = -1;
+static int hf_isis_lsp_is_type = -1;
+
+static gint ett_isis_lsp = -1;
+static gint ett_isis_lsp_info = -1;
+static gint ett_isis_lsp_att = -1;
+static gint ett_isis_lsp_clv_area_addr = -1;
+static gint ett_isis_lsp_clv_is_neighbors = -1;
+static gint ett_isis_lsp_clv_ext_is_reachability = -1; /* CLV 22 */
+static gint ett_isis_lsp_part_of_clv_ext_is_reachability = -1;
+static gint ett_isis_lsp_subclv_admin_group = -1;
+static gint ett_isis_lsp_subclv_unrsv_bw = -1;
+static gint ett_isis_lsp_clv_unknown = -1;
+static gint ett_isis_lsp_clv_partition_dis = -1;
+static gint ett_isis_lsp_clv_prefix_neighbors = -1;
+static gint ett_isis_lsp_clv_nlpid = -1;
+static gint ett_isis_lsp_clv_hostname = -1;
+static gint ett_isis_lsp_clv_te_router_id = -1;
+static gint ett_isis_lsp_clv_authentication = -1;
+static gint ett_isis_lsp_clv_ip_authentication = -1;
+static gint ett_isis_lsp_clv_ipv4_int_addr = -1;
+static gint ett_isis_lsp_clv_ipv6_int_addr = -1; /* CLV 232 */
+static gint ett_isis_lsp_clv_ip_reachability = -1;
+static gint ett_isis_lsp_clv_ip_reach_subclv = -1;
+static gint ett_isis_lsp_clv_ext_ip_reachability = -1; /* CLV 135 */
+static gint ett_isis_lsp_part_of_clv_ext_ip_reachability = -1;
+static gint ett_isis_lsp_clv_ipv6_reachability = -1; /* CLV 236 */
+static gint ett_isis_lsp_part_of_clv_ipv6_reachability = -1;
+static gint ett_isis_lsp_clv_mt = -1;
+static gint ett_isis_lsp_clv_mt_is = -1;
+static gint ett_isis_lsp_part_of_clv_mt_is = -1;
+static gint ett_isis_lsp_clv_mt_reachable_IPv4_prefx = -1; /* CLV 235 */
+static gint ett_isis_lsp_clv_mt_reachable_IPv6_prefx = -1; /* CLV 237 */
+
+static const value_string isis_lsp_istype_vals[] = {
+ { ISIS_LSP_TYPE_UNUSED0, "Unused 0x0 (invalid)"},
+ { ISIS_LSP_TYPE_LEVEL_1, "Level 1"},
+ { ISIS_LSP_TYPE_UNUSED2, "Unused 0x2 (invalid)"},
+ { ISIS_LSP_TYPE_LEVEL_2, "Level 2"},
+ { 0, NULL } };
+
+static const true_false_string supported_string = {
+ "Supported",
+ "Unsupported"
+ };
+
+static const true_false_string hippity_string = {
+ "Set",
+ "Unset"
+ };
+
+
+/*
+ * Predclare dissectors for use in clv dissection.
+ */
+static void dissect_lsp_prefix_neighbors_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_partition_dis_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_mt_is_reachability_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_ext_is_reachability_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_l2_is_neighbors_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_l1_es_neighbors_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_l1_is_neighbors_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_area_address_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_authentication_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_ip_authentication_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_ipv6_int_addr_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_ip_int_addr_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_te_router_id_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_hostname_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_mt_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_nlpid_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_ipv6_reachability_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_ext_ip_reachability_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_ip_reachability_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_ipreach_subclv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int clv_code, int clv_len);
+static void dissect_lsp_mt_reachable_IPv4_prefx_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_lsp_mt_reachable_IPv6_prefx_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+
+
+static const isis_clv_handle_t clv_l1_lsp_opts[] = {
+ {
+ ISIS_CLV_AREA_ADDRESS,
+ "Area address(es)",
+ &ett_isis_lsp_clv_area_addr,
+ dissect_lsp_area_address_clv
+ },
+ {
+ ISIS_CLV_IS_REACH,
+ "IS Reachability",
+ &ett_isis_lsp_clv_is_neighbors,
+ dissect_lsp_l1_is_neighbors_clv
+ },
+ {
+ ISIS_CLV_ES_NEIGHBORS,
+ "ES Neighbor(s)",
+ &ett_isis_lsp_clv_is_neighbors,
+ dissect_lsp_l1_es_neighbors_clv
+ },
+ {
+ ISIS_CLV_EXTD_IS_REACH,
+ "Extended IS reachability",
+ &ett_isis_lsp_clv_ext_is_reachability,
+ dissect_lsp_ext_is_reachability_clv
+ },
+ {
+ ISIS_CLV_INT_IP_REACH,
+ "IP Internal reachability",
+ &ett_isis_lsp_clv_ip_reachability,
+ dissect_lsp_ip_reachability_clv
+ },
+ {
+ ISIS_CLV_EXT_IP_REACH,
+ "IP External reachability",
+ &ett_isis_lsp_clv_ip_reachability,
+ dissect_lsp_ip_reachability_clv
+ },
+ {
+ ISIS_CLV_EXTD_IP_REACH,
+ "Extended IP Reachability",
+ &ett_isis_lsp_clv_ext_ip_reachability,
+ dissect_lsp_ext_ip_reachability_clv
+ },
+ {
+ ISIS_CLV_IP6_REACH,
+ "IPv6 reachability",
+ &ett_isis_lsp_clv_ipv6_reachability,
+ dissect_lsp_ipv6_reachability_clv
+ },
+ {
+ ISIS_CLV_PROTOCOLS_SUPPORTED,
+ "Protocols supported",
+ &ett_isis_lsp_clv_nlpid,
+ dissect_lsp_nlpid_clv
+ },
+ {
+ ISIS_CLV_HOSTNAME,
+ "Hostname",
+ &ett_isis_lsp_clv_hostname,
+ dissect_lsp_hostname_clv
+ },
+ {
+ ISIS_CLV_TE_ROUTER_ID,
+ "Traffic Engineering Router ID",
+ &ett_isis_lsp_clv_te_router_id,
+ dissect_lsp_te_router_id_clv
+ },
+ {
+ ISIS_CLV_IP_ADDR,
+ "IP Interface address(es)",
+ &ett_isis_lsp_clv_ipv4_int_addr,
+ dissect_lsp_ip_int_addr_clv
+ },
+ {
+ ISIS_CLV_IP6_ADDR,
+ "IPv6 Interface address(es)",
+ &ett_isis_lsp_clv_ipv6_int_addr,
+ dissect_lsp_ipv6_int_addr_clv
+ },
+ {
+ ISIS_CLV_AUTHENTICATION,
+ "Authentication",
+ &ett_isis_lsp_clv_authentication,
+ dissect_lsp_authentication_clv
+ },
+ {
+ ISIS_CLV_IP_AUTHENTICATION,
+ "IP Authentication",
+ &ett_isis_lsp_clv_ip_authentication,
+ dissect_lsp_ip_authentication_clv
+ },
+ {
+ ISIS_CLV_MT_SUPPORTED,
+ "Multi Topology supported",
+ &ett_isis_lsp_clv_mt,
+ dissect_lsp_mt_clv
+ },
+ {
+ ISIS_CLV_MT_IS_REACH,
+ "Multi Topology IS Reachability",
+ &ett_isis_lsp_clv_mt_is,
+ dissect_lsp_mt_is_reachability_clv
+ },
+ {
+ ISIS_CLV_MT_IP_REACH,
+ "Multi Topology Reachable IPv4 Prefixes",
+ &ett_isis_lsp_clv_mt_reachable_IPv4_prefx,
+ dissect_lsp_mt_reachable_IPv4_prefx_clv
+ },
+ {
+ ISIS_CLV_MT_IP6_REACH,
+ "Multi Topology Reachable IPv6 Prefixes",
+ &ett_isis_lsp_clv_mt_reachable_IPv6_prefx,
+ dissect_lsp_mt_reachable_IPv6_prefx_clv
+ },
+ {
+ 0,
+ "",
+ NULL,
+ NULL
+ }
+};
+
+static const isis_clv_handle_t clv_l2_lsp_opts[] = {
+ {
+ ISIS_CLV_AREA_ADDRESS,
+ "Area address(es)",
+ &ett_isis_lsp_clv_area_addr,
+ dissect_lsp_area_address_clv
+ },
+ {
+ ISIS_CLV_IS_REACH,
+ "IS Reachability",
+ &ett_isis_lsp_clv_is_neighbors,
+ dissect_lsp_l2_is_neighbors_clv
+ },
+ {
+ ISIS_CLV_EXTD_IS_REACH,
+ "Extended IS reachability",
+ &ett_isis_lsp_clv_ext_is_reachability,
+ dissect_lsp_ext_is_reachability_clv
+ },
+ {
+ ISIS_CLV_PARTITION_DIS,
+ "Parition Designated Level 2 IS",
+ &ett_isis_lsp_clv_partition_dis,
+ dissect_lsp_partition_dis_clv
+ },
+ {
+ ISIS_CLV_PREFIX_NEIGHBORS,
+ "Prefix neighbors",
+ &ett_isis_lsp_clv_prefix_neighbors,
+ dissect_lsp_prefix_neighbors_clv
+ },
+ {
+ ISIS_CLV_INT_IP_REACH,
+ "IP Internal reachability",
+ &ett_isis_lsp_clv_ip_reachability,
+ dissect_lsp_ip_reachability_clv
+ },
+ {
+ ISIS_CLV_EXT_IP_REACH,
+ "IP External reachability",
+ &ett_isis_lsp_clv_ip_reachability,
+ dissect_lsp_ip_reachability_clv
+ },
+ {
+ ISIS_CLV_PROTOCOLS_SUPPORTED,
+ "Protocols supported",
+ &ett_isis_lsp_clv_nlpid,
+ dissect_lsp_nlpid_clv
+ },
+ {
+ ISIS_CLV_HOSTNAME,
+ "Hostname",
+ &ett_isis_lsp_clv_hostname,
+ dissect_lsp_hostname_clv
+ },
+ {
+ ISIS_CLV_TE_ROUTER_ID,
+ "Traffic Engineering Router ID",
+ &ett_isis_lsp_clv_te_router_id,
+ dissect_lsp_te_router_id_clv
+ },
+ {
+ ISIS_CLV_EXTD_IP_REACH,
+ "Extended IP Reachability",
+ &ett_isis_lsp_clv_ext_ip_reachability,
+ dissect_lsp_ext_ip_reachability_clv
+ },
+ {
+ ISIS_CLV_IP6_REACH,
+ "IPv6 reachability",
+ &ett_isis_lsp_clv_ipv6_reachability,
+ dissect_lsp_ipv6_reachability_clv
+ },
+ {
+ ISIS_CLV_IP_ADDR,
+ "IP Interface address(es)",
+ &ett_isis_lsp_clv_ipv4_int_addr,
+ dissect_lsp_ip_int_addr_clv
+ },
+ {
+ ISIS_CLV_IP6_ADDR,
+ "IPv6 Interface address(es)",
+ &ett_isis_lsp_clv_ipv6_int_addr,
+ dissect_lsp_ipv6_int_addr_clv
+ },
+ {
+ ISIS_CLV_AUTHENTICATION,
+ "Authentication",
+ &ett_isis_lsp_clv_authentication,
+ dissect_lsp_authentication_clv
+ },
+ {
+ ISIS_CLV_IP_AUTHENTICATION,
+ "IP Authentication",
+ &ett_isis_lsp_clv_ip_authentication,
+ dissect_lsp_ip_authentication_clv
+ },
+ {
+ ISIS_CLV_MT_SUPPORTED,
+ "Multi Topology",
+ &ett_isis_lsp_clv_mt,
+ dissect_lsp_mt_clv
+ },
+ {
+ ISIS_CLV_MT_IS_REACH,
+ "Multi Topology IS Reachability",
+ &ett_isis_lsp_clv_mt_is,
+ dissect_lsp_mt_is_reachability_clv
+ },
+ {
+ ISIS_CLV_MT_IP_REACH,
+ "Multi Topology Reachable IPv4 Prefixes",
+ &ett_isis_lsp_clv_mt_reachable_IPv4_prefx,
+ dissect_lsp_mt_reachable_IPv4_prefx_clv
+ },
+ {
+ ISIS_CLV_MT_IP6_REACH,
+ "Multi Topology Reachable IPv6 Prefixes",
+ &ett_isis_lsp_clv_mt_reachable_IPv6_prefx,
+ dissect_lsp_mt_reachable_IPv6_prefx_clv
+ },
+ {
+ 0,
+ "",
+ NULL,
+ NULL
+ }
+};
+
+/*
+ * Name: dissect_lsp_mt_id()
+ *
+ * Description:
+ * dissect and display the multi-topology ID value
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. CAN'T BE NULL
+ * int : offset into packet data where we are.
+ *
+ * Output:
+ * void, but we will add to proto tree.
+ */
+static void
+dissect_lsp_mt_id(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ int mt_block, mt_id;
+ char mt_desc[60];
+
+ /* fetch two bytes */
+ mt_block = tvb_get_ntohs(tvb, offset);
+
+ proto_tree_add_text ( tree, tvb, offset, 1 ,
+ "4 most significant bits reserved, should be set to 0 (%d)", ISIS_LSP_MT_MSHIP_RES(mt_block));
+
+ mt_id = ISIS_LSP_MT_MSHIP_ID(mt_block);
+ /*mask out the lower 12 bits */
+ switch(mt_id) {
+ case 0:
+ strcpy(mt_desc,"'standard' topology");
+ break;
+ case 1:
+ strcpy(mt_desc,"IPv4 In-Band Management purposes");
+ break;
+ case 2:
+ strcpy(mt_desc,"IPv6 routing topology");
+ break;
+ case 3:
+ strcpy(mt_desc,"IPv4 multicast routing topology");
+ break;
+ case 4:
+ strcpy(mt_desc,"IPv6 multicast routing topology");
+ break;
+ default:
+ strcpy(mt_desc,((mt_block & 0x0fff) < 3996) ? "Reserved for IETF Consensus" : "Development, Experimental and Proprietary features");
+ }
+
+ proto_tree_add_text ( tree, tvb, offset, 2 ,
+ "%s (%d)", mt_desc, mt_id);
+
+}
+
+/*
+ * Name: dissect_metric()
+ *
+ * Description:
+ * Display a metric prefix portion. ISIS has the concept of multple
+ * metric per prefix (default, delay, expense, and error). This
+ * routine assists other dissectors by adding a single one of
+ * these to the display tree..
+ *
+ * The 8th(msbit) bit in the metric octet is the "supported" bit. The
+ * "default" support is required, so we support a "force_supported"
+ * flag that tells us that it MUST be zero (zero==supported,
+ * so it really should be a "not supported" in the boolean sense)
+ * and to display a protocol failure accordingly. Notably,
+ * Cisco IOS 12(6) blows this!
+ * The 7th bit must be zero (reserved).
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * guint8 : value of the metric.
+ * char * : string giving type of the metric.
+ * int : force supported. True is the supported bit MUST be zero.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_metric(tvbuff_t *tvb, proto_tree *tree, int offset, guint8 value,
+ char *pstr, int force_supported )
+{
+ int s;
+
+ if ( !tree ) return;
+
+ s = ISIS_LSP_CLV_METRIC_SUPPORTED(value);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s Metric: %s%s %s%d:%d", pstr,
+ s ? "Not supported" : "Supported",
+ (s && force_supported) ? "(but is required to be)":"",
+ ISIS_LSP_CLV_METRIC_RESERVED(value) ? "(reserved bit != 0)":"",
+ ISIS_LSP_CLV_METRIC_VALUE(value), value );
+}
+
+/*
+ * Name: dissect_lsp_ip_reachability_clv()
+ *
+ * Description:
+ * Decode an IP reachability CLV. This can be either internal or
+ * external (the clv format does not change and which type we are
+ * displaying is put there by the dispatcher). All of these
+ * are a metric block followed by an IP addr and mask.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_ip_reachability_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ proto_item *ti;
+ proto_tree *ntree = NULL;
+ guint32 src, mask, prefix_len;
+
+ guint32 bitmasks[33] = {
+ 0x00000000,
+ 0x00000008, 0x0000000c, 0x0000000e, 0x0000000f,
+ 0x000000f8, 0x000000fc, 0x000000fe, 0x000000ff,
+ 0x000008ff, 0x00000cff, 0x00000eff, 0x00000fff,
+ 0x0000f8ff, 0x0000fcff, 0x0000feff, 0x0000ffff,
+ 0x0008ffff, 0x000cffff, 0x000effff, 0x000fffff,
+ 0x00f8ffff, 0x00fcffff, 0x00feffff, 0x00ffffff,
+ 0x08ffffff, 0x0cffffff, 0x0effffff, 0x0fffffff,
+ 0xf8ffffff, 0xfcffffff, 0xfeffffff, 0xffffffff
+ };
+
+
+ while ( length > 0 ) {
+ if (length<12) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "short IP reachability (%d vs 12)", length );
+ return;
+ }
+ /*
+ * Gotta build a sub-tree for all our pieces
+ */
+ if ( tree ) {
+ tvb_memcpy(tvb, (guint8 *)&src, offset+4, 4);
+ tvb_memcpy(tvb, (guint8 *)&mask, offset+8, 4);
+
+ /* find out if the mask matches one of 33 possible prefix lengths */
+
+ prefix_len=0;
+
+ while(prefix_len<=33) {
+ if (bitmasks[prefix_len++]==mask) {
+ prefix_len--;
+ break;
+ }
+ }
+
+ /* 34 indicates no match -> must be a discontiguous netmask
+ lets dump the mask, otherwise print the prefix_len */
+
+ if(prefix_len==34) {
+ ti = proto_tree_add_text ( tree, tvb, offset, 12,
+ "IPv4 prefix: %s mask %s",
+ ip_to_str((guint8*)&src),
+ ip_to_str((guint8*)&mask));
+ } else {
+ ti = proto_tree_add_text ( tree, tvb, offset, 12,
+ "IPv4 prefix: %s/%d",
+ ip_to_str((guint8*)&src),
+ prefix_len );
+ };
+
+ ntree = proto_item_add_subtree(ti,
+ ett_isis_lsp_clv_ip_reachability);
+
+ proto_tree_add_text (ntree, tvb, offset, 1,
+ "Default Metric: %d, %s, Distribution: %s",
+ ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset)),
+ ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset)) ? "External" : "Internal",
+ ISIS_LSP_CLV_METRIC_UPDOWN(tvb_get_guint8(tvb, offset)) ? "down" : "up");
+
+
+ if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+1))) {
+ proto_tree_add_text (ntree, tvb, offset+1, 1, "Delay Metric: Not supported");
+ } else {
+ proto_tree_add_text (ntree, tvb, offset+1, 1, "Delay Metric: %d, %s",
+ ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+1)),
+ ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+1)) ? "External" : "Internal");
+ }
+
+ if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+2))) {
+ proto_tree_add_text (ntree, tvb, offset+2, 1, "Expense Metric: Not supported");
+ } else {
+ proto_tree_add_text (ntree, tvb, offset+2, 1, "Exense Metric: %d, %s",
+ ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+2)),
+ ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+2)) ? "External" : "Internal");
+ }
+
+ if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+3))) {
+ proto_tree_add_text (ntree, tvb, offset+3, 1, "Error Metric: Not supported");
+ } else {
+ proto_tree_add_text (ntree, tvb, offset+3, 1, "Error Metric: %d, %s",
+ ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+3)),
+ ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+3)) ? "External" : "Internal");
+ }
+ }
+ offset += 12;
+ length -= 12;
+ }
+}
+
+/*
+ * Name: dissect_ipreach_subclv ()
+ *
+ * Description: parses IP reach subTLVs
+ * Called by various IP Reachability dissectors.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out.
+ * int : offset into packet data where we are (beginning of the sub_clv value).
+ *
+ * Output:
+ * void
+ */
+static void
+dissect_ipreach_subclv(tvbuff_t *tvb, proto_tree *tree, int offset, int clv_code, int clv_len)
+{
+
+ switch (clv_code) {
+ case 1:
+ while (clv_len >= 4) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "32-Bit Administrative tag: 0x%08x (=%u)",
+ tvb_get_ntohl(tvb, offset),
+ tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ clv_len-=4;
+ }
+ break;
+ case 2:
+ while (clv_len >= 8) {
+ proto_tree_add_text(tree, tvb, offset, 8,
+ "64-Bit Administrative tag: 0x%08x%08x",
+ tvb_get_ntohl(tvb, offset),
+ tvb_get_ntohl(tvb, offset+4));
+ offset+=8;
+ clv_len-=8;
+ }
+ break;
+
+ default :
+ proto_tree_add_text (tree, tvb, offset, clv_len+2,
+ "Unknown sub-TLV: code %u, length %u",
+ clv_code, clv_len );
+ break;
+ }
+}
+
+
+/*
+ * Name: dissect_lsp_ext_ip_reachability_clv()
+ *
+ * Description: Decode an Extended IP Reachability CLV - code 135.
+ *
+ * The extended IP reachability TLV is an extended version
+ * of the IP reachability TLVs (codes 128 and 130). It encodes
+ * the metric as a 32-bit unsigned interger and allows to add
+ * sub-CLV(s).
+ *
+ * CALLED BY TLV 235 DISSECTOR
+ *
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_ext_ip_reachability_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int id_length _U_, int length)
+{
+ proto_item *pi = NULL;
+ proto_tree *subtree = NULL;
+ proto_tree *subtree2 = NULL;
+ guint8 ctrl_info;
+ guint8 bit_length, byte_length;
+ guint8 prefix [4];
+ guint32 metric;
+ guint8 len,i;
+ guint8 subclvs_len;
+ guint8 clv_code, clv_len;
+
+ if (!tree) return;
+
+ while (length > 0) {
+ memset (prefix, 0, 4);
+ ctrl_info = tvb_get_guint8(tvb, offset+4);
+ bit_length = ctrl_info & 0x3f;
+ byte_length = (bit_length + 7) / 8;
+ if (byte_length > sizeof(prefix)) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "IPv4 prefix has an invalid length: %d bytes", byte_length );
+ return;
+ }
+ tvb_memcpy (tvb, prefix, offset+5, byte_length);
+ metric = tvb_get_ntohl(tvb, offset);
+ subclvs_len = 0;
+ if ((ctrl_info & 0x40) != 0)
+ subclvs_len = 1+tvb_get_guint8(tvb, offset+5+byte_length);
+
+ pi = proto_tree_add_text (tree, tvb, offset, 5+byte_length+subclvs_len,
+ "IPv4 prefix: %s/%d, Metric: %u, Distribution: %s, %ssub-TLVs present",
+ ip_to_str (prefix),
+ bit_length,
+ metric,
+ ((ctrl_info & 0x80) == 0) ? "up" : "down",
+ ((ctrl_info & 0x40) == 0) ? "no " : "" );
+
+ /* open up a new tree per prefix */
+ subtree = proto_item_add_subtree (pi, ett_isis_lsp_part_of_clv_ext_ip_reachability);
+
+ proto_tree_add_text (subtree, tvb, offset+5, byte_length, "IPv4 prefix: %s/%u",
+ ip_to_str (prefix),
+ bit_length);
+
+ proto_tree_add_text (subtree, tvb, offset, 4, "Metric: %u", metric);
+
+ proto_tree_add_text (subtree, tvb, offset+4, 1, "Distribution: %s",
+ ((ctrl_info & 0x80) == 0) ? "up" : "down");
+
+ len = 5 + byte_length;
+ if ((ctrl_info & 0x40) != 0) {
+ subclvs_len = tvb_get_guint8(tvb, offset+len);
+ pi = proto_tree_add_text (subtree, tvb, offset+len, 1, "sub-TLVs present, total length: %u bytes",
+ subclvs_len);
+ proto_item_set_len (pi, subclvs_len+1);
+ /* open up a new tree for the subTLVs */
+ subtree2 = proto_item_add_subtree (pi, ett_isis_lsp_clv_ip_reach_subclv);
+
+ i =0;
+ while (i < subclvs_len) {
+ clv_code = tvb_get_guint8(tvb, offset+len+1); /* skip the total subtlv len indicator */
+ clv_len = tvb_get_guint8(tvb, offset+len+2);
+
+ /*
+ * we pass on now the raw data to the ipreach_subtlv dissector
+ * therefore we need to skip 3 bytes
+ * (total subtlv len, subtlv type, subtlv len)
+ */
+ dissect_ipreach_subclv(tvb, subtree2, offset+len+3, clv_code, clv_len);
+ i += clv_len + 2;
+ }
+ len += 1 + subclvs_len;
+ } else {
+ proto_tree_add_text (subtree, tvb, offset+4, 1, "no sub-TLVs present");
+ proto_item_set_len (pi, len);
+ }
+
+ offset += len;
+ length -= len;
+ }
+}
+
+/*
+ * Name: dissect_lsp_ipv6_reachability_clv()
+ *
+ * Description: Decode an IPv6 reachability CLV - code 236.
+ *
+ * CALLED BY TLV 237 DISSECTOR
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_ipv6_reachability_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ proto_item *pi;
+ proto_tree *subtree = NULL;
+ proto_tree *subtree2 = NULL;
+ guint8 ctrl_info;
+ guint8 bit_length, byte_length;
+ struct e_in6_addr prefix;
+ guint32 metric;
+ guint8 len,i;
+ guint8 subclvs_len;
+ guint8 clv_code, clv_len;
+
+ if (!tree) return;
+
+ while (length > 0) {
+ memset (prefix.s6_addr, 0, 16);
+ ctrl_info = tvb_get_guint8(tvb, offset+4);
+ bit_length = tvb_get_guint8(tvb, offset+5);
+ byte_length = (bit_length + 7) / 8;
+ if (byte_length > sizeof(prefix)) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "IPv6 prefix has an invalid length: %d bytes", byte_length );
+ return;
+ }
+ tvb_memcpy (tvb, prefix.s6_addr, offset+6, byte_length);
+ metric = tvb_get_ntohl(tvb, offset);
+ subclvs_len = 0;
+ if ((ctrl_info & 0x20) != 0)
+ subclvs_len = 1+tvb_get_guint8(tvb, offset+6+byte_length);
+
+ pi = proto_tree_add_text (tree, tvb, offset, 6+byte_length+subclvs_len,
+ "IPv6 prefix: %s/%u, Metric: %u, Distribution: %s, %s, %ssub-TLVs present",
+ ip6_to_str (&prefix),
+ bit_length,
+ metric,
+ ((ctrl_info & 0x80) == 0) ? "up" : "down",
+ ((ctrl_info & 0x40) == 0) ? "internal" : "external",
+ ((ctrl_info & 0x20) == 0) ? "no " : "" );
+
+ subtree = proto_item_add_subtree (pi, ett_isis_lsp_part_of_clv_ipv6_reachability);
+
+ proto_tree_add_text (subtree, tvb, offset+6, byte_length, "IPv6 prefix: %s/%u",
+ ip6_to_str (&prefix),
+ bit_length);
+
+ proto_tree_add_text (subtree, tvb, offset, 4,
+ "Metric: %u", metric);
+
+ proto_tree_add_text (subtree, tvb, offset+4, 1,
+ "Distribution: %s, %s",
+ ((ctrl_info & 0x80) == 0) ? "up" : "down",
+ ((ctrl_info & 0x40) == 0) ? "internal" : "external" );
+
+ if ((ctrl_info & 0x1f) != 0) {
+ proto_tree_add_text (subtree, tvb, offset+4, 1,
+ "Reserved bits: 0x%x",
+ (ctrl_info & 0x1f) );
+ }
+
+ len = 6 + byte_length;
+ if ((ctrl_info & 0x20) != 0) {
+ subclvs_len = tvb_get_guint8(tvb, offset+len);
+ pi = proto_tree_add_text (subtree, tvb, offset+len, 1, "sub-TLVs present, total length: %u bytes",
+ subclvs_len);
+ proto_item_set_len (pi, subclvs_len+1);
+ /* open up a new tree for the subTLVs */
+ subtree2 = proto_item_add_subtree (pi, ett_isis_lsp_clv_ip_reach_subclv);
+
+ i =0;
+ while (i < subclvs_len) {
+ clv_code = tvb_get_guint8(tvb, offset+len+1); /* skip the total subtlv len indicator */
+ clv_len = tvb_get_guint8(tvb, offset+len+2);
+ dissect_ipreach_subclv(tvb, subtree2, offset+len+3, clv_code, clv_len);
+ i += clv_len + 2;
+ }
+ len += 1 + subclvs_len;
+ } else {
+ proto_tree_add_text (subtree, tvb, offset+4, 1, "no sub-TLVs present");
+ proto_item_set_len (pi, len);
+ }
+ offset += len;
+ length -= len;
+ }
+}
+
+/*
+ * Name: dissect_lsp_nlpid_clv()
+ *
+ * Description:
+ * Decode for a lsp packets NLPID clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_nlpid_clv(tvb, tree, offset, length);
+}
+
+/*
+ * Name: dissect_lsp_mt_clv()
+ *
+ * Description: - code 229
+ * Decode for a lsp packets Multi Topology clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * guint : length of this clv
+ * int : length of IDs in packet.
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_mt_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_mt_clv(tvb, tree, offset, length, hf_isis_lsp_clv_mt );
+}
+
+/*
+ * Name: dissect_lsp_hostname_clv()
+ *
+ * Description:
+ * Decode for a lsp packets hostname clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_hostname_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_hostname_clv(tvb, tree, offset, length);
+}
+
+
+/*
+ * Name: dissect_lsp_te_router_id_clv()
+ *
+ * Description:
+ * Decode for a lsp packets Traffic Engineering ID clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_te_router_id_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_te_router_id_clv(tvb, tree, offset, length,
+ hf_isis_lsp_clv_te_router_id );
+}
+
+
+/*
+ * Name: dissect_lsp_ip_int_addr_clv()
+ *
+ * Description:
+ * Decode for a lsp packets ip interface addr clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_ip_int_addr_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_ip_int_clv(tvb, tree, offset, length,
+ hf_isis_lsp_clv_ipv4_int_addr );
+}
+
+/*
+ * Name: dissect_lsp_ipv6_int_addr_clv()
+ *
+ * Description: Decode an IPv6 interface addr CLV - code 232.
+ *
+ * Calls into the clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_ipv6_int_addr_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_ipv6_int_clv(tvb, tree, offset, length,
+ hf_isis_lsp_clv_ipv6_int_addr );
+}
+
+/*
+ * Name: dissect_lsp_authentication_clv()
+ *
+ * Description:
+ * Decode for a lsp packets authenticaion clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_authentication_clv(tvb, tree, offset, length);
+}
+
+/*
+ * Name: dissect_lsp_ip_authentication_clv()
+ *
+ * Description:
+ * Decode for a lsp packets authenticaion clv. Calls into the
+ * clv common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_lsp_ip_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_ip_authentication_clv(tvb, tree, offset, length);
+}
+
+/*
+ * Name: dissect_lsp_area_address_clv()
+ *
+ * Description:
+ * Decode for a lsp packet's area address clv. Call into clv common
+ * one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_area_address_clv(tvb, tree, offset, length);
+}
+
+/*
+ * Name: dissect_lsp_eis_neighbors_clv_inner()
+ *
+ * Description:
+ * Real work horse for showing neighbors. This means we decode the
+ * first octet as either virtual/!virtual (if show_virtual param is
+ * set), or as a must == 0 reserved value.
+ *
+ * Once past that, we decode n neighbor elements. Each neighbor
+ * is comprised of a metric block (is dissect_metric) and the
+ * addresses.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ * int : set to decode first octet as virtual vs reserved == 0
+ * int : set to indicate EIS instead of IS (6 octet per addr instead of 7)
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_eis_neighbors_clv_inner(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length, int id_length, int show_virtual, int is_eis)
+{
+ proto_item *ti;
+ proto_tree *ntree = NULL;
+ int tlen;
+
+ if (!is_eis) {
+ id_length++; /* IDs are one octet longer in IS neighbours */
+ if ( tree ) {
+ if ( show_virtual ) {
+ /* virtual path flag */
+ proto_tree_add_text ( tree, tvb, offset, 1,
+ tvb_get_guint8(tvb, offset) ? "IsVirtual" : "IsNotVirtual" );
+ } else {
+ proto_tree_add_text ( tree, tvb, offset, 1,
+ "Reserved value 0x%02x, must == 0",
+ tvb_get_guint8(tvb, offset) );
+ }
+ }
+ offset++;
+ length--;
+ }
+ tlen = 4 + id_length;
+
+ while ( length > 0 ) {
+ if (length<tlen) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "short E/IS reachability (%d vs %d)", length,
+ tlen );
+ return;
+ }
+ /*
+ * Gotta build a sub-tree for all our pieces
+ */
+ if ( tree ) {
+ if ( is_eis ) {
+ ti = proto_tree_add_text(tree, tvb, offset, tlen,
+ "ES Neighbor: %s",
+ print_system_id( tvb_get_ptr(tvb, offset+4, id_length), id_length ) );
+ } else {
+ ti = proto_tree_add_text(tree, tvb, offset, tlen,
+ "IS Neighbor: %s",
+ print_system_id(tvb_get_ptr(tvb, offset+4, id_length), id_length ) );
+ }
+ ntree = proto_item_add_subtree(ti,
+ ett_isis_lsp_clv_is_neighbors);
+
+
+
+ proto_tree_add_text (ntree, tvb, offset, 1,
+ "Default Metric: %d, %s",
+ ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset)),
+ ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset)) ? "External" : "Internal");
+
+ if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+1))) {
+ proto_tree_add_text (ntree, tvb, offset+1, 1, "Delay Metric: Not supported");
+ } else {
+ proto_tree_add_text (ntree, tvb, offset+1, 1, "Delay Metric: %d, %s",
+ ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+1)),
+ ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+1)) ? "External" : "Internal");
+ }
+
+
+ if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+2))) {
+ proto_tree_add_text (ntree, tvb, offset+2, 1, "Expense Metric: Not supported");
+ } else {
+ proto_tree_add_text (ntree, tvb, offset+2, 1, "Expense Metric: %d, %s",
+ ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+2)),
+ ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+2)) ? "External" : "Internal");
+ }
+
+ if (ISIS_LSP_CLV_METRIC_SUPPORTED(tvb_get_guint8(tvb, offset+3))) {
+ proto_tree_add_text (ntree, tvb, offset+3, 1, "Error Metric: Not supported");
+ } else {
+ proto_tree_add_text (ntree, tvb, offset+3, 1, "Error Metric: %d, %s",
+ ISIS_LSP_CLV_METRIC_VALUE(tvb_get_guint8(tvb, offset+3)),
+ ISIS_LSP_CLV_METRIC_IE(tvb_get_guint8(tvb, offset+3)) ? "External" : "Internal");
+ }
+
+ }
+ offset += tlen;
+ length -= tlen;
+ }
+}
+
+/*
+ * Name: dissect_lsp_l1_is_neighbors_clv()
+ *
+ * Description:
+ * Dispatch a l1 intermediate system neighbor by calling
+ * the inner function with show virtual set to TRUE and is es set to FALSE.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_l1_is_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length, int length)
+{
+ dissect_lsp_eis_neighbors_clv_inner(tvb, tree, offset,
+ length, id_length, TRUE, FALSE);
+}
+
+/*
+ * Name: dissect_lsp_l1_es_neighbors_clv()
+ *
+ * Description:
+ * Dispatch a l1 end or intermediate system neighbor by calling
+ * the inner function with show virtual set to TRUE and es set to TRUE.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_l1_es_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length, int length)
+{
+ dissect_lsp_eis_neighbors_clv_inner(tvb, tree, offset,
+ length, id_length, TRUE, TRUE);
+}
+
+/*
+ * Name: dissect_lsp_l2_is_neighbors_clv()
+ *
+ * Description:
+ * Dispatch a l2 intermediate system neighbor by calling
+ * the inner function with show virtual set to FALSE, and is es set
+ * to FALSE
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_l2_is_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length, int length)
+{
+ dissect_lsp_eis_neighbors_clv_inner(tvb, tree, offset,
+ length, id_length, FALSE, FALSE);
+}
+
+
+/*
+ * Name: dissect_subclv_admin_group ()
+ *
+ * Description: Called by function dissect_lsp_ext_is_reachability_clv().
+ *
+ * This function is called by dissect_lsp_ext_is_reachability_clv()
+ * for dissect the administrive group sub-CLV (code 3).
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out.
+ * int : offset into packet data where we are (beginning of the sub_clv value).
+ *
+ * Output:
+ * void
+ */
+static void
+dissect_subclv_admin_group (tvbuff_t *tvb, proto_tree *tree, int offset) {
+ proto_item *ti;
+ proto_tree *ntree;
+ guint32 clv_value;
+ guint32 mask;
+ int i;
+
+ ti = proto_tree_add_text(tree, tvb, offset-2, 6, "Administrative group(s):");
+ ntree = proto_item_add_subtree (ti, ett_isis_lsp_subclv_admin_group);
+
+ clv_value = tvb_get_ntohl(tvb, offset);
+ mask = 1;
+ for (i = 0 ; i < 32 ; i++) {
+ if ( (clv_value & mask) != 0 ) {
+ proto_tree_add_text (ntree, tvb, offset, 4, "group %d", i);
+ }
+ mask <<= 1;
+ }
+}
+
+/*
+ * Name: dissect_subclv_max_bw ()
+ *
+ * Description: Called by function dissect_lsp_ext_is_reachability_clv().
+ *
+ * This function is called by dissect_lsp_ext_is_reachability_clv()
+ * for dissect the maximum link bandwidth sub-CLV (code 9).
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out.
+ * int : offset into packet data where we are (beginning of the sub_clv value).
+ *
+ * Output:
+ * void
+ */
+static void
+dissect_subclv_max_bw(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ gfloat bw;
+
+ bw = tvb_get_ntohieee_float(tvb, offset);
+ proto_tree_add_text (tree, tvb, offset-2, 6,
+ "Maximum link bandwidth : %.2f Mbps", bw*8/1000000 );
+}
+
+/*
+ * Name: dissect_subclv_rsv_bw ()
+ *
+ * Description: Called by function dissect_lsp_ext_is_reachability_clv().
+ *
+ * This function is called by dissect_lsp_ext_is_reachability_clv()
+ * for dissect the reservable link bandwidth sub-CLV (code 10).
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out.
+ * int : offset into packet data where we are (beginning of the sub_clv value).
+ *
+ * Output:
+ * void
+ */
+static void
+dissect_subclv_rsv_bw(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ gfloat bw;
+
+ bw = tvb_get_ntohieee_float(tvb, offset);
+ proto_tree_add_text (tree, tvb, offset-2, 6,
+ "Reservable link bandwidth: %.2f Mbps", bw*8/1000000 );
+}
+
+/*
+ * Name: dissect_subclv_unrsv_bw ()
+ *
+ * Description: Called by function dissect_lsp_ext_is_reachability_clv().
+ *
+ * This function is called by dissect_lsp_ext_is_reachability_clv()
+ * for dissect the unreserved bandwidth sub-CLV (code 11).
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out.
+ * int : offset into packet data where we are (beginning of the sub_clv value).
+ *
+ * Output:
+ * void
+ */
+static void
+dissect_subclv_unrsv_bw(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ proto_item *ti;
+ proto_tree *ntree;
+ gfloat bw;
+ int i;
+
+ ti = proto_tree_add_text (tree, tvb, offset-2, 34, "Unreserved bandwidth:");
+ ntree = proto_item_add_subtree (ti, ett_isis_lsp_subclv_unrsv_bw);
+
+ for (i = 0 ; i < 8 ; i++) {
+ bw = tvb_get_ntohieee_float(tvb, offset+4*i);
+ proto_tree_add_text (ntree, tvb, offset+4*i, 4,
+ "priority level %d: %.2f Mbps", i, bw*8/1000000 );
+ }
+}
+
+/*
+ * Name: dissect_lsp_ext_is_reachability_clv()
+ *
+ * Description: Decode a Extended IS Reachability CLV - code 22
+ *
+ * The extended IS reachability TLV is an extended version
+ * of the IS reachability TLV (code 2). It encodes the metric
+ * as a 24-bit unsigned interger and allows to add sub-CLV(s).
+ *
+ * CALLED BY TLV 222 DISSECTOR
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_ext_is_reachability_clv(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int id_length _U_, int length)
+{
+ proto_item *ti;
+ proto_tree *ntree = NULL;
+ guint8 subclvs_len;
+ guint8 len, i;
+ guint8 clv_code, clv_len;
+
+ if (!tree) return;
+
+ while (length > 0) {
+ ti = proto_tree_add_text (tree, tvb, offset, -1,
+ "IS neighbor: %s",
+ print_system_id (tvb_get_ptr(tvb, offset, 7), 7) );
+ ntree = proto_item_add_subtree (ti,
+ ett_isis_lsp_part_of_clv_ext_is_reachability );
+
+ proto_tree_add_text (ntree, tvb, offset+7, 3,
+ "Metric: %d", tvb_get_ntoh24(tvb, offset+7) );
+
+ subclvs_len = tvb_get_guint8(tvb, offset+10);
+ if (subclvs_len == 0) {
+ proto_tree_add_text (ntree, tvb, offset+10, 1, "no sub-TLVs present");
+ }
+ else {
+ i = 0;
+ while (i < subclvs_len) {
+ clv_code = tvb_get_guint8(tvb, offset+11+i);
+ clv_len = tvb_get_guint8(tvb, offset+12+i);
+ switch (clv_code) {
+ case 3 :
+ dissect_subclv_admin_group(tvb, ntree, offset+13+i);
+ break;
+ case 6 :
+ proto_tree_add_text (ntree, tvb, offset+11+i, 6,
+ "IPv4 interface address: %s", ip_to_str (tvb_get_ptr(tvb, offset+13+i, 4)) );
+ break;
+ case 8 :
+ proto_tree_add_text (ntree, tvb, offset+11+i, 6,
+ "IPv4 neighbor address: %s", ip_to_str (tvb_get_ptr(tvb, offset+13+i, 4)) );
+ break;
+ case 9 :
+ dissect_subclv_max_bw (tvb, ntree, offset+13+i);
+ break;
+ case 10:
+ dissect_subclv_rsv_bw (tvb, ntree, offset+13+i);
+ break;
+ case 11:
+ dissect_subclv_unrsv_bw (tvb, ntree, offset+13+i);
+ break;
+ case 18:
+ proto_tree_add_text (ntree, tvb, offset+11+i, 5,
+ "Traffic engineering default metric: %d",
+ tvb_get_ntoh24(tvb, offset+13+i) );
+ break;
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ proto_tree_add_text (ntree, tvb, offset+11+i, clv_len+2,
+ "Unknown Cisco specific extensions: code %d, length %d",
+ clv_code, clv_len );
+ break;
+ default :
+ proto_tree_add_text (ntree, tvb, offset+11+i, clv_len+2,
+ "Unknown sub-CLV: code %d, length %d", clv_code, clv_len );
+ break;
+ }
+ i += clv_len + 2;
+ }
+ }
+
+ len = 11 + subclvs_len;
+ proto_item_set_len (ti, len);
+ offset += len;
+ length -= len;
+ }
+}
+
+/*
+ * Name: dissect_lsp_mt_reachable_IPv4_prefx_clv()
+ *
+ * Description: Decode Multi-Topology IPv4 Prefixes - code 235
+ *
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_mt_reachable_IPv4_prefx_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ if (!tree) return;
+ if (length < 2) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "short lsp multi-topology reachable IPv4 prefixes(%d vs %d)", length,
+ 2 );
+ return;
+ }
+ dissect_lsp_mt_id(tvb, tree, offset);
+ dissect_lsp_ext_ip_reachability_clv(tvb, tree, offset+2, 0, length-2);
+}
+
+/*
+ * Name: dissect_lsp_mt_reachable_IPv6_prefx_clv()
+ *
+ * Description: Decode Multi-Topology IPv6 Prefixes - code 237
+ *
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_mt_reachable_IPv6_prefx_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length)
+{
+ if (!tree) return;
+ if (length < 2) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "short lsp multi-topology reachable IPv6 prefixes(%d vs %d)", length,
+ 2 );
+ return;
+ }
+ dissect_lsp_mt_id(tvb, tree, offset);
+ dissect_lsp_ipv6_reachability_clv(tvb, tree, offset+2, 0, length-2);
+}
+
+
+/*
+ * Name: dissect_lsp_mt_is_reachability_clv()
+ *
+ * Description: Decode Multi-Topology Intermediate Systems - code 222
+ *
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : unused
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+
+static void
+dissect_lsp_mt_is_reachability_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ if (!tree) return;
+ if (length < 2) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "short lsp reachability(%d vs %d)", length,
+ 2 );
+ return;
+ }
+
+ /*
+ * the MT ID value dissection is used in other LSPs so we push it
+ * in a function
+ */
+ dissect_lsp_mt_id(tvb, tree, offset);
+ /*
+ * fix here. No need to parse TLV 22 (with bugs) while it is
+ * already done correctly!!
+ */
+ dissect_lsp_ext_is_reachability_clv(tvb, tree, offset+2, 0, length-2);
+}
+
+/*
+ * Name: dissect_lsp_partition_dis_clv()
+ *
+ * Description:
+ * This CLV is used to indicate which system is the designated
+ * IS for partition repair. This means just putting out the
+ * "id_length"-octet IS.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_partition_dis_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length, int length)
+{
+ if ( length < id_length ) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "short lsp partition DIS(%d vs %d)", length,
+ id_length );
+ return;
+ }
+ /*
+ * Gotta build a sub-tree for all our pieces
+ */
+ if ( tree ) {
+ proto_tree_add_text ( tree, tvb, offset, id_length,
+ "Partition designated L2 IS: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length), id_length ) );
+ }
+ length -= id_length;
+ offset += id_length;
+ if ( length > 0 ){
+ isis_dissect_unknown(tvb, tree, offset,
+ "Long lsp partition DIS, %d left over", length );
+ return;
+ }
+}
+
+/*
+ * Name: dissect_lsp_prefix_neighbors_clv()
+ *
+ * Description:
+ * The prefix CLV describes what other (OSI) networks we can reach
+ * and what their cost is. It is built from a metric block
+ * (see dissect_metric) followed by n addresses.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_prefix_neighbors_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ char *sbuf;
+ int mylen;
+
+ if ( length < 4 ) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "Short lsp prefix neighbors (%d vs 4)", length );
+ return;
+ }
+ if ( tree ) {
+ dissect_metric (tvb, tree, offset,
+ tvb_get_guint8(tvb, offset), "Default", TRUE );
+ dissect_metric (tvb, tree, offset+1,
+ tvb_get_guint8(tvb, offset+1), "Delay", FALSE );
+ dissect_metric (tvb, tree, offset+2,
+ tvb_get_guint8(tvb, offset+2), "Expense", FALSE );
+ dissect_metric (tvb, tree, offset+3,
+ tvb_get_guint8(tvb, offset+3), "Error", FALSE );
+ }
+ offset += 4;
+ length -= 4;
+ while ( length > 0 ) {
+ mylen = tvb_get_guint8(tvb, offset);
+ length--;
+ if (length<=0) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "Zero payload space after length in prefix neighbor" );
+ return;
+ }
+ if ( mylen > length) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "Interal length of prefix neighbor too long (%d vs %d)",
+ mylen, length );
+ return;
+ }
+
+ /*
+ * Lets turn the area address into "standard" 0000.0000.etc
+ * format string.
+ */
+ sbuf = print_area( tvb_get_ptr(tvb, offset+1, mylen), mylen );
+ /* and spit it out */
+ if ( tree ) {
+ proto_tree_add_text ( tree, tvb, offset, mylen + 1,
+ "Area address (%d): %s", mylen, sbuf );
+ }
+ offset += mylen + 1;
+ length -= mylen; /* length already adjusted for len fld*/
+ }
+}
+
+/*
+ * Name: isis_dissect_isis_lsp()
+ *
+ * Description:
+ * Print out the LSP part of the main header and then call the CLV
+ * de-mangler with the right list of valid CLVs.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to add to. May be NULL.
+ * int offset : our offset into packet data.
+ * int : LSP type, a la packet-isis.h ISIS_TYPE_* values
+ * int : header length of packet.
+ * int : length of IDs in packet.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_isis_lsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
+ int lsp_type, int header_length, int id_length)
+{
+ proto_item *ti, *to, *ta;
+ proto_tree *lsp_tree = NULL, *info_tree, *att_tree;
+ guint16 pdu_length, checksum, cacl_checksum=0;
+ guint8 lsp_info, lsp_att;
+ int len, offset_checksum;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, -1,
+ PROTO_STRING_LSP);
+ lsp_tree = proto_item_add_subtree(ti, ett_isis_lsp);
+ }
+
+ pdu_length = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(lsp_tree, hf_isis_lsp_pdu_length, tvb,
+ offset, 2, pdu_length);
+ }
+ offset += 2;
+
+ if (tree) {
+ proto_tree_add_text(lsp_tree, tvb, offset, 2,
+ "Remaining Lifetime: %us",
+ tvb_get_ntohs(tvb, offset));
+ }
+ offset += 2;
+ offset_checksum = offset;
+
+ if (tree) {
+ proto_tree_add_text(lsp_tree, tvb, offset, id_length + 2,
+ "LSP-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", LSP-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
+ }
+ offset += id_length + 2;
+
+ if (tree) {
+ proto_tree_add_uint(lsp_tree, hf_isis_lsp_sequence_number, tvb,
+ offset, 4,
+ tvb_get_ntohl(tvb, offset));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Sequence: 0x%08x, Lifetime: %5us",
+ tvb_get_ntohl(tvb, offset),
+ tvb_get_ntohs(tvb, offset - (id_length+2+2)));
+ }
+ offset += 4;
+
+ if (tree) {
+ checksum = tvb_get_ntohs(tvb, offset);
+ switch (check_and_get_checksum(tvb, offset_checksum, pdu_length-12, checksum, offset, &cacl_checksum))
+ {
+
+ case NO_CKSUM :
+ proto_tree_add_uint_format(lsp_tree, hf_isis_lsp_checksum, tvb, offset, 2, checksum,
+ "Checksum: 0x%04x (unused)", checksum);
+ break;
+ case DATA_MISSING :
+ isis_dissect_unknown(tvb, tree, offset,
+ "packet length %d went beyond packet",
+ tvb_length_remaining(tvb, offset_checksum));
+ break;
+ case CKSUM_NOT_OK :
+ proto_tree_add_uint_format(lsp_tree, hf_isis_lsp_checksum, tvb, offset, 2, checksum,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ checksum, cacl_checksum);
+ proto_tree_add_boolean_hidden(lsp_tree, hf_isis_lsp_checksum_bad,
+ tvb, offset, 2, TRUE);
+ break;
+ case CKSUM_OK :
+ proto_tree_add_uint_format(lsp_tree, hf_isis_lsp_checksum, tvb, offset, 2, checksum,
+ "Checksum: 0x%04x (correct)", checksum);
+ proto_tree_add_boolean_hidden(lsp_tree, hf_isis_lsp_checksum_bad,
+ tvb, offset, 2, FALSE);
+ break;
+ default :
+ g_message("'check_and_get_checksum' returned an invalid value");
+ }
+ }
+ offset += 2;
+
+ if (tree) {
+ /*
+ * P | ATT | HIPPITY | IS TYPE description.
+ */
+ lsp_info = tvb_get_guint8(tvb, offset);
+ to = proto_tree_add_text(lsp_tree, tvb, offset, 1,
+ "Type block(0x%02x): Partition Repair:%d, Attached bits:%d, Overload bit:%d, IS type:%d",
+ lsp_info,
+ ISIS_LSP_PARTITION(lsp_info),
+ ISIS_LSP_ATT(lsp_info),
+ ISIS_LSP_HIPPITY(lsp_info),
+ ISIS_LSP_IS_TYPE(lsp_info)
+ );
+
+ info_tree = proto_item_add_subtree(to, ett_isis_lsp_info);
+ proto_tree_add_boolean(info_tree, hf_isis_lsp_p, tvb, offset, 1, lsp_info);
+ ta = proto_tree_add_uint(info_tree, hf_isis_lsp_att, tvb, offset, 1, lsp_info);
+ att_tree = proto_item_add_subtree(ta, ett_isis_lsp_att);
+ lsp_att = ISIS_LSP_ATT(lsp_info);
+ proto_tree_add_text(att_tree, tvb, offset, 1,
+ "%d... = Error metric: %s", ISIS_LSP_ATT_ERROR(lsp_att), ISIS_LSP_ATT_ERROR(lsp_att) ? "Set" : "Unset");
+ proto_tree_add_text(att_tree, tvb, offset, 1,
+ ".%d.. = Expense metric: %s", ISIS_LSP_ATT_EXPENSE(lsp_att), ISIS_LSP_ATT_EXPENSE(lsp_att) ? "Set" : "Unset");
+ proto_tree_add_text(att_tree, tvb, offset, 1,
+ "..%d. = Delay metric: %s", ISIS_LSP_ATT_DELAY(lsp_att), ISIS_LSP_ATT_DELAY(lsp_att) ? "Set" : "Unset");
+ proto_tree_add_text(att_tree, tvb, offset, 1,
+ "...%d = Default metric: %s", ISIS_LSP_ATT_DEFAULT(lsp_att), ISIS_LSP_ATT_DEFAULT(lsp_att) ? "Set" : "Unset");
+ proto_tree_add_boolean(info_tree, hf_isis_lsp_hippity, tvb, offset, 1, lsp_info);
+ proto_tree_add_uint(info_tree, hf_isis_lsp_is_type, tvb, offset, 1, lsp_info);
+ }
+ offset += 1;
+
+ len = pdu_length - header_length;
+ if (len < 0) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "packet header length %d went beyond packet",
+ header_length );
+ return;
+ }
+ /*
+ * Now, we need to decode our CLVs. We need to pass in
+ * our list of valid ones!
+ */
+ if (lsp_type == ISIS_TYPE_L1_LSP){
+ isis_dissect_clvs(tvb, lsp_tree, offset,
+ clv_l1_lsp_opts, len, id_length,
+ ett_isis_lsp_clv_unknown );
+ } else {
+ isis_dissect_clvs(tvb, lsp_tree, offset,
+ clv_l2_lsp_opts, len, id_length,
+ ett_isis_lsp_clv_unknown );
+ }
+}
+/*
+ * Name: isis_register_lsp()
+ *
+ * Description:
+ * Register our protocol sub-sets with protocol manager.
+ *
+ * Input:
+ * int : protocol index for the ISIS protocol
+ *
+ * Output:
+ * void
+ */
+void
+isis_register_lsp(int proto_isis) {
+ static hf_register_info hf[] = {
+ { &hf_isis_lsp_pdu_length,
+ { "PDU length", "isis.lsp.pdu_length", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_lsp_remaining_life,
+ { "Remaining lifetime", "isis.lsp.remaining_life", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_lsp_sequence_number,
+ { "Sequence number", "isis.lsp.sequence_number",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_lsp_checksum,
+ { "Checksum", "isis.lsp.checksum",FT_UINT16,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_lsp_checksum_bad,
+ { "Bad Checksum", "isis.lsp.checksum_bad", FT_BOOLEAN, BASE_NONE,
+ NULL, 0, "Bad IS-IS LSP Checksum", HFILL }},
+
+ { &hf_isis_lsp_clv_ipv4_int_addr,
+ { "IPv4 interface address", "isis.lsp.clv_ipv4_int_addr", FT_IPv4,
+ BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_lsp_clv_ipv6_int_addr,
+ { "IPv6 interface address", "isis.lsp.clv_ipv6_int_addr", FT_IPv6,
+ BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_lsp_clv_te_router_id,
+ { "Traffic Engineering Router ID", "isis.lsp.clv_te_router_id", FT_IPv4,
+ BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_lsp_clv_mt,
+ { "MT-ID ", "isis.lsp.clv_mt",
+ FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_lsp_p,
+ { "Partition Repair", "isis.lsp.partition_repair", FT_BOOLEAN, 8,
+ TFS(&supported_string), ISIS_LSP_PARTITION_MASK,
+ "If set, this router supports the optional Partition Repair function", HFILL }},
+
+ { &hf_isis_lsp_att,
+ { "Attachment", "isis.lsp.att", FT_UINT8, BASE_DEC,
+ NULL, ISIS_LSP_ATT_MASK,
+ "", HFILL }},
+
+ { &hf_isis_lsp_hippity,
+ { "Overload bit", "isis.lsp.overload", FT_BOOLEAN, 8,
+ TFS(&hippity_string), ISIS_LSP_HIPPITY_MASK,
+ "If set, this router will not be used by any decision process to calculate routes", HFILL }},
+
+ { &hf_isis_lsp_is_type,
+ { "Type of Intermediate System", "isis.lsp.is_type", FT_UINT8, BASE_DEC,
+ VALS(isis_lsp_istype_vals), ISIS_LSP_IS_TYPE_MASK,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_isis_lsp,
+ &ett_isis_lsp_info,
+ &ett_isis_lsp_att,
+ &ett_isis_lsp_clv_area_addr,
+ &ett_isis_lsp_clv_is_neighbors,
+ &ett_isis_lsp_clv_ext_is_reachability, /* CLV 22 */
+ &ett_isis_lsp_part_of_clv_ext_is_reachability,
+ &ett_isis_lsp_subclv_admin_group,
+ &ett_isis_lsp_subclv_unrsv_bw,
+ &ett_isis_lsp_clv_unknown,
+ &ett_isis_lsp_clv_partition_dis,
+ &ett_isis_lsp_clv_prefix_neighbors,
+ &ett_isis_lsp_clv_authentication,
+ &ett_isis_lsp_clv_ip_authentication,
+ &ett_isis_lsp_clv_nlpid,
+ &ett_isis_lsp_clv_hostname,
+ &ett_isis_lsp_clv_ipv4_int_addr,
+ &ett_isis_lsp_clv_ipv6_int_addr, /* CLV 232 */
+ &ett_isis_lsp_clv_te_router_id,
+ &ett_isis_lsp_clv_ip_reachability,
+ &ett_isis_lsp_clv_ip_reach_subclv,
+ &ett_isis_lsp_clv_ext_ip_reachability, /* CLV 135 */
+ &ett_isis_lsp_part_of_clv_ext_ip_reachability,
+ &ett_isis_lsp_clv_ipv6_reachability, /* CLV 236 */
+ &ett_isis_lsp_part_of_clv_ipv6_reachability,
+ &ett_isis_lsp_clv_mt,
+ &ett_isis_lsp_clv_mt_is,
+ &ett_isis_lsp_part_of_clv_mt_is,
+ &ett_isis_lsp_clv_mt_reachable_IPv4_prefx,
+ &ett_isis_lsp_clv_mt_reachable_IPv6_prefx,
+ };
+
+ proto_register_field_array(proto_isis, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/epan/dissectors/packet-isis-lsp.h b/epan/dissectors/packet-isis-lsp.h
new file mode 100644
index 0000000000..751dfd5c0d
--- /dev/null
+++ b/epan/dissectors/packet-isis-lsp.h
@@ -0,0 +1,88 @@
+/* packet-isis-lsp.h
+ * Defines and such for LSP and their CLV decodes
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_ISIS_LSP_H
+#define _PACKET_ISIS_LSP_H
+
+/*
+ * Declarations for L1/L2 LSP base header.
+ */
+
+/* P | ATT | HIPPITY | DS FIELD description */
+#define ISIS_LSP_PARTITION_MASK 0x80
+#define ISIS_LSP_PARTITION_SHIFT 7
+#define ISIS_LSP_PARTITION(info) (((info) & ISIS_LSP_PARTITION_MASK) >> ISIS_LSP_PARTITION_SHIFT)
+
+#define ISIS_LSP_ATT_MASK 0x78
+#define ISIS_LSP_ATT_SHIFT 3
+#define ISIS_LSP_ATT(info) (((info) & ISIS_LSP_ATT_MASK) >> ISIS_LSP_ATT_SHIFT)
+
+#define ISIS_LSP_ATT_ERROR(info) ((info) >> 3)
+#define ISIS_LSP_ATT_EXPENSE(info) (((info) >> 2) & 1)
+#define ISIS_LSP_ATT_DELAY(info) (((info) >> 1) & 1)
+#define ISIS_LSP_ATT_DEFAULT(info) ((info) & 1)
+
+#define ISIS_LSP_HIPPITY_MASK 0x04
+#define ISIS_LSP_HIPPITY_SHIFT 2
+#define ISIS_LSP_HIPPITY(info) (((info) & ISIS_LSP_HIPPITY_MASK) >> ISIS_LSP_HIPPITY_SHIFT)
+
+#define ISIS_LSP_IS_TYPE_MASK 0x03
+#define ISIS_LSP_IS_TYPE(info) ((info) & ISIS_LSP_IS_TYPE_MASK)
+
+#define ISIS_LSP_MT_MSHIP_RES_MASK 4
+#define ISIS_LSP_MT_MSHIP_RES_SHIFT 12
+#define ISIS_LSP_MT_MSHIP_RES(info) (((info) >> ISIS_LSP_MT_MSHIP_RES_SHIFT) & ISIS_LSP_MT_MSHIP_RES_MASK)
+
+#define ISIS_LSP_MT_MSHIP_ID_MASK 0x0FFF
+#define ISIS_LSP_MT_MSHIP_ID(info) ((info) & ISIS_LSP_MT_MSHIP_ID_MASK)
+
+
+#define ISIS_LSP_TYPE_UNUSED0 0
+#define ISIS_LSP_TYPE_LEVEL_1 1
+#define ISIS_LSP_TYPE_UNUSED2 2
+#define ISIS_LSP_TYPE_LEVEL_2 3
+
+#define ISIS_LSP_ATTACHED_NONE 0
+#define ISIS_LSP_ATTACHED_DEFAULT 1
+#define ISIS_LSP_ATTACHED_DELAY 2
+#define ISIS_LSP_ATTACHED_EXPENSE 4
+#define ISIS_LSP_ATTACHED_ERROR 8
+
+
+#define ISIS_LSP_CLV_METRIC_SUPPORTED(x) ((x)&0x80)
+#define ISIS_LSP_CLV_METRIC_IE(x) ((x)&0x40)
+#define ISIS_LSP_CLV_METRIC_RESERVED(x) ((x)&0x40)
+#define ISIS_LSP_CLV_METRIC_UPDOWN(x) ((x)&0x80)
+#define ISIS_LSP_CLV_METRIC_VALUE(x) ((x)&0x3f)
+
+/*
+ * Published API functions. NOTE, this are "local" API functions and
+ * are only valid from with isis decodes.
+ */
+extern void isis_dissect_isis_lsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int hello_type, int header_length, int id_length);
+extern void isis_register_lsp(int proto_isis);
+
+#endif /* _PACKET_ISIS_LSP_H */
diff --git a/epan/dissectors/packet-isis-snp.c b/epan/dissectors/packet-isis-snp.c
new file mode 100644
index 0000000000..34b6109961
--- /dev/null
+++ b/epan/dissectors/packet-isis-snp.c
@@ -0,0 +1,595 @@
+/* packet-isis-snp.c
+ * Routines for decoding isis complete & partial SNP and their payload
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-osi.h"
+#include "packet-isis.h"
+#include "packet-isis-clv.h"
+#include "packet-isis-lsp.h"
+#include "packet-isis-snp.h"
+
+/* csnp packets */
+static int hf_isis_csnp_pdu_length = -1;
+static gint ett_isis_csnp = -1;
+static gint ett_isis_csnp_clv_lsp_entries = -1;
+static gint ett_isis_csnp_lsp_entry = -1;
+static gint ett_isis_csnp_clv_authentication = -1;
+static gint ett_isis_csnp_clv_ip_authentication = -1;
+static gint ett_isis_csnp_clv_checksum = -1;
+static gint ett_isis_csnp_clv_unknown = -1;
+
+/* psnp packets */
+static int hf_isis_psnp_pdu_length = -1;
+static gint ett_isis_psnp = -1;
+static gint ett_isis_psnp_clv_lsp_entries = -1;
+static gint ett_isis_psnp_lsp_entry = -1;
+static gint ett_isis_psnp_clv_authentication = -1;
+static gint ett_isis_psnp_clv_ip_authentication = -1;
+static gint ett_isis_psnp_clv_checksum = -1;
+static gint ett_isis_psnp_clv_unknown = -1;
+
+static void dissect_snp_authentication_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_snp_ip_authentication_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_snp_checksum_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+static void dissect_snp_lsp_entries_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length, int length);
+
+static const isis_clv_handle_t clv_l1_csnp_opts[] = {
+ {
+ ISIS_CLV_LSP_ENTRIES,
+ "LSP entries",
+ &ett_isis_csnp_clv_lsp_entries,
+ dissect_snp_lsp_entries_clv
+ },
+ {
+ ISIS_CLV_AUTHENTICATION,
+ "Authentication",
+ &ett_isis_csnp_clv_authentication,
+ dissect_snp_authentication_clv
+ },
+ {
+ ISIS_CLV_IP_AUTHENTICATION,
+ "IP Authentication",
+ &ett_isis_csnp_clv_ip_authentication,
+ dissect_snp_ip_authentication_clv
+ },
+ {
+ ISIS_CLV_CHECKSUM,
+ "Checksum",
+ &ett_isis_csnp_clv_checksum,
+ dissect_snp_checksum_clv
+ },
+ {
+ 0, "", NULL, NULL
+ }
+};
+
+static const isis_clv_handle_t clv_l2_csnp_opts[] = {
+ {
+ ISIS_CLV_LSP_ENTRIES,
+ "LSP entries",
+ &ett_isis_csnp_clv_lsp_entries,
+ dissect_snp_lsp_entries_clv
+ },
+ {
+ ISIS_CLV_AUTHENTICATION,
+ "Authentication",
+ &ett_isis_csnp_clv_authentication,
+ dissect_snp_authentication_clv
+ },
+ {
+ ISIS_CLV_IP_AUTHENTICATION,
+ "IP Authentication",
+ &ett_isis_csnp_clv_ip_authentication,
+ dissect_snp_ip_authentication_clv
+ },
+ {
+ ISIS_CLV_CHECKSUM,
+ "Checksum",
+ &ett_isis_csnp_clv_checksum,
+ dissect_snp_checksum_clv
+ },
+ {
+ 0, "", NULL, NULL
+ }
+};
+
+static const isis_clv_handle_t clv_l1_psnp_opts[] = {
+ {
+ ISIS_CLV_LSP_ENTRIES,
+ "LSP entries",
+ &ett_isis_psnp_clv_lsp_entries,
+ dissect_snp_lsp_entries_clv
+ },
+ {
+ ISIS_CLV_AUTHENTICATION,
+ "Authentication",
+ &ett_isis_psnp_clv_authentication,
+ dissect_snp_authentication_clv
+ },
+ {
+ ISIS_CLV_IP_AUTHENTICATION,
+ "IP Authentication",
+ &ett_isis_psnp_clv_ip_authentication,
+ dissect_snp_ip_authentication_clv
+ },
+ {
+ ISIS_CLV_CHECKSUM,
+ "Checksum",
+ &ett_isis_psnp_clv_checksum,
+ dissect_snp_checksum_clv
+ },
+ {
+ 0, "", NULL, NULL
+ }
+};
+
+static const isis_clv_handle_t clv_l2_psnp_opts[] = {
+ {
+ ISIS_CLV_LSP_ENTRIES,
+ "LSP entries",
+ &ett_isis_psnp_clv_lsp_entries,
+ dissect_snp_lsp_entries_clv
+ },
+ {
+ ISIS_CLV_AUTHENTICATION,
+ "Authentication",
+ &ett_isis_psnp_clv_authentication,
+ dissect_snp_authentication_clv
+ },
+ {
+ ISIS_CLV_IP_AUTHENTICATION,
+ "IP Authentication",
+ &ett_isis_psnp_clv_ip_authentication,
+ dissect_snp_ip_authentication_clv
+ },
+ {
+ ISIS_CLV_CHECKSUM,
+ "Checksum",
+ &ett_isis_psnp_clv_checksum,
+ dissect_snp_checksum_clv
+ },
+ {
+ 0, "", NULL, NULL
+ }
+};
+
+/*
+ * Name: dissect_snp_lsp_entries_clv()
+ *
+ * Description:
+ * All the snp packets use a common payload format. We have up
+ * to n entries (based on length), which are made of:
+ * 2 : remaining life time
+ * id_length : lsp id
+ * 4 : sequence number
+ * 2 : checksum
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of IDs in packet.
+ * int : length of payload to decode.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_snp_lsp_entries_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length, int length)
+{
+ proto_tree *subtree,*ti;
+
+ while ( length > 0 ) {
+ if ( length < 2+id_length+2+4+2 ) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "Short SNP header entry (%d vs %d)", length,
+ 2+id_length+2+4+2 );
+ return;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, 2+id_length+2+4+2,
+ "LSP-ID: %s, Sequence: 0x%08x, Lifetime: %5us, Checksum: 0x%04x",
+ print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ),
+ tvb_get_ntohl(tvb, offset+2+id_length+2),
+ tvb_get_ntohs(tvb, offset),
+ tvb_get_ntohs(tvb, offset+2+id_length+2+4));
+
+ subtree = proto_item_add_subtree(ti,ett_isis_csnp_lsp_entry);
+
+ proto_tree_add_text(subtree, tvb, offset+2, 8,
+ "LSP-ID: : %s",
+ print_system_id( tvb_get_ptr(tvb, offset+2, id_length+2), id_length+2 ));
+
+ proto_tree_add_text(subtree, tvb, offset+2+id_length+2, 4,
+ "LSP Sequence Number : 0x%08x",
+ tvb_get_ntohl(tvb, offset+2+id_length+2));
+
+ proto_tree_add_text(subtree, tvb, offset, 2,
+ "Remaining Lifetime : %us",
+ tvb_get_ntohs(tvb, offset));
+
+ proto_tree_add_text(subtree, tvb, offset+2+id_length+2+4, 2,
+ "LSP checksum : 0x%04x",
+ tvb_get_ntohs(tvb, offset+2+id_length+2+4));
+
+ length -= 2+id_length+2+4+2;
+ offset += 2+id_length+2+4+2;
+ }
+
+}
+
+
+/*
+ * Name: isis_dissect_isis_csnp()
+ *
+ * Description:
+ * Tear apart a L1 or L2 CSNP header and then call into payload dissect
+ * to pull apart the lsp id payload.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to add to. May be NULL.
+ * int offset : our offset into packet data.
+ * int : type (l1 csnp, l2 csnp)
+ * int : header length of packet.
+ * int : length of IDs in packet.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_isis_csnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
+ int type, int header_length, int id_length)
+{
+ proto_item *ti;
+ proto_tree *csnp_tree = NULL;
+ guint16 pdu_length;
+ int len;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, -1,
+ PROTO_STRING_CSNP);
+ csnp_tree = proto_item_add_subtree(ti, ett_isis_csnp);
+ }
+
+ pdu_length = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(csnp_tree, hf_isis_csnp_pdu_length, tvb,
+ offset, 2, pdu_length);
+ }
+ offset += 2;
+
+ if (tree) {
+ proto_tree_add_text(csnp_tree, tvb, offset, id_length + 1,
+ "Source-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length+1 ) );
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Source-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length+1 ) );
+ }
+ offset += id_length + 1;
+
+ if (tree) {
+ proto_tree_add_text(csnp_tree, tvb, offset, id_length + 2,
+ "Start LSP-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Start LSP-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
+ }
+ offset += id_length + 2;
+
+ if (tree) {
+ proto_tree_add_text(csnp_tree, tvb, offset, id_length + 2,
+ "End LSP-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", End LSP-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+2), id_length+2 ) );
+ }
+ offset += id_length + 2;
+
+ len = pdu_length - header_length;
+ if (len < 0) {
+ return;
+ }
+ /* Call into payload dissector */
+ if (type == ISIS_TYPE_L1_CSNP ) {
+ isis_dissect_clvs(tvb, csnp_tree, offset,
+ clv_l1_csnp_opts, len, id_length,
+ ett_isis_csnp_clv_unknown );
+ } else {
+ isis_dissect_clvs(tvb, csnp_tree, offset,
+ clv_l2_csnp_opts, len, id_length,
+ ett_isis_csnp_clv_unknown );
+ }
+}
+
+/*
+ * Name: isis_dissect_isis_psnp()
+ *
+ * Description:
+ * Tear apart a L1 or L2 PSNP header and then call into payload dissect
+ * to pull apart the lsp id payload.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to add to. May be NULL.
+ * int : our offset into packet data
+ * int : type (l1 psnp, l2 psnp)
+ * int : header length of packet.
+ * int : length of IDs in packet.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+void
+isis_dissect_isis_psnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
+ int type, int header_length, int id_length)
+{
+ proto_item *ti;
+ proto_tree *psnp_tree = NULL;
+ guint16 pdu_length;
+ int len;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, -1,
+ PROTO_STRING_PSNP);
+ psnp_tree = proto_item_add_subtree(ti, ett_isis_psnp);
+ }
+
+ pdu_length = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(psnp_tree, hf_isis_psnp_pdu_length, tvb,
+ offset, 2, pdu_length);
+ }
+ offset += 2;
+
+ if (tree) {
+ proto_tree_add_text(psnp_tree, tvb, offset, id_length + 1,
+ "Source-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length + 1 ) );
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Source-ID: %s",
+ print_system_id( tvb_get_ptr(tvb, offset, id_length+1), id_length+1 ) );
+ }
+ offset += id_length + 1;
+
+ len = pdu_length - header_length;
+ if (len < 0) {
+ isis_dissect_unknown(tvb, tree, offset,
+ "packet header length %d went beyond packet",
+ header_length );
+ return;
+ }
+ /* Call into payload dissector */
+ if (type == ISIS_TYPE_L1_PSNP ) {
+ isis_dissect_clvs(tvb, psnp_tree, offset,
+ clv_l1_psnp_opts, len, id_length,
+ ett_isis_psnp_clv_unknown );
+ } else {
+ isis_dissect_clvs(tvb, psnp_tree, offset,
+ clv_l2_psnp_opts, len, id_length,
+ ett_isis_psnp_clv_unknown );
+ }
+}
+
+/*
+ * Name: dissect_snp_authentication_clv()
+ *
+ * Description:
+ * Decode for a snp packets authenticaion clv.
+ * Calls into the CLV common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_snp_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_authentication_clv(tvb, tree, offset, length);
+}
+
+/*
+ * Name: dissect_snp_ip_authentication_clv()
+ *
+ * Description:
+ * Decode for a snp packets authenticaion clv.
+ * Calls into the CLV common one.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : proto tree to build on (may be null)
+ * int : current offset into packet data
+ * int : length of IDs in packet.
+ * int : length of this clv
+ *
+ * Output:
+ * void, will modify proto_tree if not null.
+ */
+static void
+dissect_snp_ip_authentication_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int id_length _U_, int length)
+{
+ isis_dissect_ip_authentication_clv(tvb, tree, offset, length);
+}
+
+/*
+ * Name: dissect_snp_checksum_clv()
+ *
+ * Description:
+ * dump and verify the optional checksum in TLV 12
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+
+static void
+dissect_snp_checksum_clv(tvbuff_t *tvb,
+ proto_tree *tree, int offset, int id_length _U_, int length) {
+
+ guint16 pdu_length,checksum, cacl_checksum=0;
+
+ if (tree) {
+ if ( length != 2 ) {
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "incorrect checksum length (%u), should be (2)", length );
+ return;
+ }
+
+ checksum = tvb_get_ntohs(tvb, offset);
+
+ /* the check_and_get_checksum() function needs to know how big
+ * the packet is. we can either pass through the pdu-len through several layers
+ * of dissectors and wrappers or extract the PDU length field from the PDU specific header
+ * which is offseted 8 bytes (relative to the beginning of the IS-IS packet) in SNPs */
+
+ pdu_length = tvb_get_ntohs(tvb, 8);
+
+ /* unlike the LSP checksum verification which starts at an offset of 12 we start at offset 0*/
+ switch (check_and_get_checksum(tvb, 0, pdu_length, checksum, offset, &cacl_checksum))
+ {
+
+ case NO_CKSUM :
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "Checksum: 0x%04x (unused)", checksum);
+ break;
+ case DATA_MISSING :
+ isis_dissect_unknown(tvb, tree, offset,
+ "packet length %d went beyond packet",
+ tvb_length_remaining(tvb, 0));
+ break;
+ case CKSUM_NOT_OK :
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ checksum,
+ cacl_checksum);
+ break;
+ case CKSUM_OK :
+ proto_tree_add_text ( tree, tvb, offset, length,
+ "Checksum: 0x%04x (correct)", checksum);
+ break;
+ default :
+ g_message("'check_and_get_checksum' returned an invalid value");
+ }
+ }
+}
+
+/*
+ * Name: isis_register_csnp()
+ *
+ * Description:
+ * Register our protocol sub-sets with protocol manager.
+ *
+ * Input:
+ * int : protocol index for the ISIS protocol
+ *
+ * Output:
+ * void
+ */
+void
+isis_register_csnp(int proto_isis) {
+ static hf_register_info hf[] = {
+ { &hf_isis_csnp_pdu_length,
+ { "PDU length", "isis.csnp.pdu_length", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_isis_csnp,
+ &ett_isis_csnp_clv_lsp_entries,
+ &ett_isis_csnp_lsp_entry,
+ &ett_isis_csnp_clv_authentication,
+ &ett_isis_csnp_clv_ip_authentication,
+ &ett_isis_csnp_clv_checksum,
+ &ett_isis_csnp_clv_unknown,
+ };
+
+ proto_register_field_array(proto_isis, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+/*
+ * Name: isis_register_psnp()
+ *
+ * Description:
+ * Register our protocol sub-sets with protocol manager.
+ *
+ * Input:
+ * int : protocol index for the ISIS protocol
+ *
+ * Output:
+ * void
+ */
+void
+isis_register_psnp(int proto_isis) {
+ static hf_register_info hf[] = {
+ { &hf_isis_psnp_pdu_length,
+ { "PDU length", "isis.psnp.pdu_length", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_isis_psnp,
+ &ett_isis_psnp_clv_lsp_entries,
+ &ett_isis_psnp_lsp_entry,
+ &ett_isis_psnp_clv_authentication,
+ &ett_isis_psnp_clv_ip_authentication,
+ &ett_isis_psnp_clv_checksum,
+ &ett_isis_psnp_clv_unknown,
+ };
+
+ proto_register_field_array(proto_isis, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/epan/dissectors/packet-isis-snp.h b/epan/dissectors/packet-isis-snp.h
new file mode 100644
index 0000000000..252f04866c
--- /dev/null
+++ b/epan/dissectors/packet-isis-snp.h
@@ -0,0 +1,40 @@
+/* packet-isis-snp.h
+ * Defines and such for CSNP, PSNP, and their payloads
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_ISIS_SNP_H
+#define _PACKET_ISIS_SNP_H
+
+/*
+ * Published API functions. NOTE, this are "local" API functions and
+ * are only valid from with isis decodes.
+ */
+extern void isis_dissect_isis_csnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int type, int header_length, int id_length);
+extern void isis_register_csnp(int proto_isis);
+extern void isis_dissect_isis_psnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int type, int header_length, int id_length);
+extern void isis_register_psnp(int proto_isis);
+
+#endif /* _PACKET_ISIS_CSNP_H */
diff --git a/epan/dissectors/packet-isis.c b/epan/dissectors/packet-isis.c
new file mode 100644
index 0000000000..47b5a411c6
--- /dev/null
+++ b/epan/dissectors/packet-isis.c
@@ -0,0 +1,329 @@
+/* packet-isis.c
+ * Routines for ISO/OSI network and transport protocol packet disassembly, core
+ * bits.
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "nlpid.h"
+#include "packet-osi.h"
+#include "packet-isis.h"
+#include "packet-isis-lsp.h"
+#include "packet-isis-hello.h"
+#include "packet-isis-snp.h"
+
+
+/* isis base header */
+static int proto_isis = -1;
+
+static int hf_isis_irpd = -1;
+static int hf_isis_header_length = -1;
+static int hf_isis_version = -1;
+static int hf_isis_system_id_length = -1;
+static int hf_isis_type = -1;
+static int hf_isis_version2 = -1;
+static int hf_isis_reserved = -1;
+static int hf_isis_max_area_adr = -1;
+
+static gint ett_isis = -1;
+
+static const value_string isis_vals[] = {
+ { ISIS_TYPE_L1_HELLO, "L1 HELLO"},
+ { ISIS_TYPE_L2_HELLO, "L2 HELLO"},
+ { ISIS_TYPE_PTP_HELLO, "P2P HELLO"},
+ { ISIS_TYPE_L1_LSP, "L1 LSP"},
+ { ISIS_TYPE_L2_LSP, "L2 LSP"},
+ { ISIS_TYPE_L1_CSNP, "L1 CSNP"},
+ { ISIS_TYPE_L2_CSNP, "L2 CSNP"},
+ { ISIS_TYPE_L1_PSNP, "L1 PSNP"},
+ { ISIS_TYPE_L2_PSNP, "L2 PSNP"},
+ { 0, NULL} };
+
+/*
+ * Name: isis_dissect_unknown()
+ *
+ * Description:
+ * There was some error in the protocol and we are in unknown space
+ * here. Add a tree item to cover the error and go on. Note
+ * that we make sure we don't go off the end of the bleedin packet here!
+ *
+ * Input
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : tree of display data. May be NULL.
+ * int : current offset into packet data
+ * char * : format text
+ * subsequent args : arguments to format
+ *
+ * Output:
+ * void (may modify proto tree)
+ */
+void
+isis_dissect_unknown(tvbuff_t *tvb, proto_tree *tree, int offset,
+ char *fmat, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmat);
+ proto_tree_add_text_valist(tree, tvb, offset, -1, fmat, ap);
+ va_end(ap);
+}
+
+/*
+ * Name: dissect_isis()
+ *
+ * Description:
+ * Main entry area for isis de-mangling. This will build the
+ * main isis tree data and call the sub-protocols as needed.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * packet_info * : info for current packet
+ * proto_tree * : tree of display data. May be NULL.
+ *
+ * Output:
+ * void, but we will add to the proto_tree if it is not NULL.
+ */
+static void
+dissect_isis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *isis_tree = NULL;
+ int offset = 0;
+ guint8 isis_version;
+ guint8 isis_header_length;
+ guint8 isis_type_reserved;
+ guint8 isis_type;
+ guint8 isis_system_id_len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISIS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ isis_version = tvb_get_guint8(tvb, 2);
+ if (isis_version != ISIS_REQUIRED_VERSION){
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Unknown ISIS version (%u vs %u)",
+ isis_version, ISIS_REQUIRED_VERSION );
+ }
+ isis_dissect_unknown(tvb, tree, 0,
+ "Unknown ISIS version (%d vs %d)",
+ isis_version, ISIS_REQUIRED_VERSION);
+ return;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_isis, tvb, 0, -1, FALSE);
+ isis_tree = proto_item_add_subtree(ti, ett_isis);
+ }
+
+ if (tree) {
+ proto_tree_add_item(isis_tree, hf_isis_irpd, tvb, offset, 1,
+ FALSE );
+ }
+ offset += 1;
+
+ isis_header_length = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(isis_tree, hf_isis_header_length, tvb,
+ offset, 1, isis_header_length );
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_uint(isis_tree, hf_isis_version, tvb,
+ offset, 1, isis_version );
+ }
+ offset += 1;
+
+ isis_system_id_len = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(isis_tree, hf_isis_system_id_length, tvb,
+ offset, 1, isis_system_id_len );
+ }
+ offset += 1;
+
+ isis_type_reserved = tvb_get_guint8(tvb, offset);
+ isis_type = isis_type_reserved & ISIS_TYPE_MASK;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str ( isis_type, isis_vals, "Unknown (0x%x)" ) );
+ }
+ if (tree) {
+ proto_tree_add_uint_format(isis_tree, hf_isis_type, tvb,
+ offset, 1, isis_type,
+ "PDU Type : %s (R:%s%s%s)",
+ val_to_str(isis_type, isis_vals, "Unknown (0x%x)"),
+ (isis_type_reserved & ISIS_R8_MASK) ? "1" : "0",
+ (isis_type_reserved & ISIS_R7_MASK) ? "1" : "0",
+ (isis_type_reserved & ISIS_R6_MASK) ? "1" : "0");
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_item(isis_tree, hf_isis_version2, tvb, offset, 1,
+ FALSE );
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_item(isis_tree, hf_isis_reserved, tvb, offset, 1,
+ FALSE );
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_item(isis_tree, hf_isis_max_area_adr, tvb, offset, 1,
+ FALSE );
+ }
+ offset += 1;
+
+ /*
+ * Interpret the system ID length.
+ */
+ if (isis_system_id_len == 0)
+ isis_system_id_len = 6; /* zero means 6-octet ID field length */
+ else if (isis_system_id_len == 255) {
+ isis_system_id_len = 0; /* 255 means null ID field */
+ /* XXX - what about the LAN ID? */
+ }
+ /* XXX - otherwise, must be in the range 1 through 8 */
+
+ switch (isis_type) {
+ case ISIS_TYPE_L1_HELLO:
+ case ISIS_TYPE_L2_HELLO:
+ case ISIS_TYPE_PTP_HELLO:
+ isis_dissect_isis_hello(tvb, pinfo, isis_tree, offset,
+ isis_type, isis_header_length, isis_system_id_len);
+ break;
+ case ISIS_TYPE_L1_LSP:
+ case ISIS_TYPE_L2_LSP:
+ isis_dissect_isis_lsp(tvb, pinfo, isis_tree, offset,
+ isis_type, isis_header_length, isis_system_id_len);
+ break;
+ case ISIS_TYPE_L1_CSNP:
+ case ISIS_TYPE_L2_CSNP:
+ isis_dissect_isis_csnp(tvb, pinfo, isis_tree, offset,
+ isis_type, isis_header_length, isis_system_id_len);
+ break;
+ case ISIS_TYPE_L1_PSNP:
+ case ISIS_TYPE_L2_PSNP:
+ isis_dissect_isis_psnp(tvb, pinfo, isis_tree, offset,
+ isis_type, isis_header_length, isis_system_id_len);
+ break;
+ default:
+ isis_dissect_unknown(tvb, tree, offset,
+ "Unknown ISIS packet type");
+ }
+} /* dissect_isis */
+
+
+/*
+ * Name: proto_register_isis()
+ *
+ * Description:
+ * main register for isis protocol set. We register some display
+ * formats and the protocol module variables.
+ *
+ * NOTE: this procedure to autolinked by the makefile process that
+ * builds register.c
+ *
+ * Input:
+ * void
+ *
+ * Output:
+ * void
+ */
+void
+proto_register_isis(void) {
+ static hf_register_info hf[] = {
+ { &hf_isis_irpd,
+ { "Intra Domain Routing Protocol Discriminator", "isis.irpd",
+ FT_UINT8, BASE_HEX, VALS(nlpid_vals), 0x0, "", HFILL }},
+
+ { &hf_isis_header_length,
+ { "PDU Header Length ", "isis.len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_version,
+ { "Version (==1) ", "isis.version", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_system_id_length,
+ { "System ID Length ", "isis.sysid_len",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_isis_type,
+ { "PDU Type ", "isis.type", FT_UINT8, BASE_DEC,
+ VALS(isis_vals), 0xff, "", HFILL }},
+
+ { &hf_isis_version2,
+ { "Version2 (==1) ", "isis.version2", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_isis_reserved,
+ { "Reserved (==0) ", "isis.reserved", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_isis_max_area_adr,
+ { "Max.AREAs: (0==3) ", "isis.max_area_adr", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ };
+ /*
+ * Note, we pull in the unknown CLV handler here, since it
+ * is used by all ISIS packet types.
+ */
+ static gint *ett[] = {
+ &ett_isis,
+ };
+
+ proto_isis = proto_register_protocol(PROTO_STRING_ISIS, "ISIS", "isis");
+ proto_register_field_array(proto_isis, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /*
+ * Call registration routines for other source files in the ISIS
+ * dissector.
+ */
+ isis_register_hello(proto_isis);
+ isis_register_lsp(proto_isis);
+ isis_register_csnp(proto_isis);
+ isis_register_psnp(proto_isis);
+}
+
+void
+proto_reg_handoff_isis(void)
+{
+ dissector_handle_t isis_handle;
+
+ isis_handle = create_dissector_handle(dissect_isis, proto_isis);
+ dissector_add("osinl", NLPID_ISO10589_ISIS, isis_handle);
+}
diff --git a/epan/dissectors/packet-isis.h b/epan/dissectors/packet-isis.h
new file mode 100644
index 0000000000..f4565eced3
--- /dev/null
+++ b/epan/dissectors/packet-isis.h
@@ -0,0 +1,60 @@
+/* packet-isis.h
+ * Defines and such for core isis protcol decode.
+ *
+ * $Id$
+ * Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_ISIS_H
+#define _PACKET_ISIS_H
+
+/*
+ * The version we support is 1
+ */
+#define ISIS_REQUIRED_VERSION 1
+
+/*
+ * ISIS type field values
+ */
+#define ISIS_TYPE_L1_HELLO 15
+#define ISIS_TYPE_L2_HELLO 16
+#define ISIS_TYPE_PTP_HELLO 17
+#define ISIS_TYPE_L1_LSP 18
+#define ISIS_TYPE_L2_LSP 20
+#define ISIS_TYPE_L1_CSNP 24
+#define ISIS_TYPE_L2_CSNP 25
+#define ISIS_TYPE_L1_PSNP 26
+#define ISIS_TYPE_L2_PSNP 27
+
+#define ISIS_TYPE_MASK 0x1f
+#define ISIS_R8_MASK 0x80
+#define ISIS_R7_MASK 0x40
+#define ISIS_R6_MASK 0x20
+
+/*
+ * published API functions
+ */
+
+extern char *isis_address_to_string(tvbuff_t *tvb, int offset, int len);
+extern void isis_dissect_unknown(tvbuff_t *tvb, proto_tree *tree, int offset,
+ char *fmat, ...);
+
+#endif /* _PACKET_ISIS_H */
diff --git a/epan/dissectors/packet-isl.c b/epan/dissectors/packet-isl.c
new file mode 100644
index 0000000000..daf984661d
--- /dev/null
+++ b/epan/dissectors/packet-isl.c
@@ -0,0 +1,341 @@
+/* packet-isl.c
+ * Routines for Cisco ISL Ethernet header disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-isl.h"
+#include "packet-eth.h"
+#include "packet-tr.h"
+#include "etypes.h"
+
+/*
+ * See
+ *
+ * http://www.cisco.com/warp/public/473/741_4.html
+ *
+ * and
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
+ *
+ * for information on ISL.
+ */
+static int proto_isl = -1;
+static int hf_isl_dst = -1;
+static int hf_isl_type = -1;
+static int hf_isl_user_eth = -1;
+static int hf_isl_user = -1;
+static int hf_isl_src = -1;
+static int hf_isl_addr = -1;
+static int hf_isl_len = -1;
+static int hf_isl_hsa = -1;
+static int hf_isl_vlan_id = -1;
+static int hf_isl_bpdu = -1;
+static int hf_isl_index = -1;
+static int hf_isl_crc = -1;
+static int hf_isl_src_vlan_id = -1;
+static int hf_isl_explorer = -1;
+static int hf_isl_dst_route_descriptor = -1;
+static int hf_isl_src_route_descriptor = -1;
+static int hf_isl_fcs_not_incl = -1;
+static int hf_isl_esize = -1;
+
+static gint ett_isl = -1;
+
+#define ISL_HEADER_SIZE 26
+
+#define TYPE_ETHER 0x0
+#define TYPE_TR 0x1
+#define TYPE_FDDI 0x2
+#define TYPE_ATM 0x3
+
+static dissector_handle_t eth_handle;
+static dissector_handle_t tr_handle;
+static dissector_handle_t data_handle;
+
+void
+capture_isl(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ guint8 type;
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, ISL_HEADER_SIZE)) {
+ ld->other++;
+ return;
+ }
+
+ type = (pd[offset+5] >> 4)&0x0F;
+
+ switch (type) {
+
+ case TYPE_ETHER:
+ offset += 14+12; /* skip the header */
+ capture_eth(pd, offset, len, ld);
+ break;
+
+ case TYPE_TR:
+ offset += 14+17; /* skip the header */
+ capture_tr(pd, offset, len, ld);
+ break;
+
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+static const value_string type_vals[] = {
+ {TYPE_ETHER, "Ethernet"},
+ {TYPE_TR, "Token-Ring"},
+ {TYPE_FDDI, "FDDI"},
+ {TYPE_ATM, "ATM"},
+ {0, NULL}
+};
+
+static const value_string ether_user_vals[] = {
+ {0x0, "Normal priority"},
+ {0x1, "Priority 1"},
+ {0x2, "Priority 2"},
+ {0x3, "Highest priority"},
+ {0, NULL}
+};
+
+static const true_false_string bpdu_tfs = {
+ "Yes",
+ "No"
+};
+
+static const true_false_string explorer_tfs = {
+ "Explorer frame",
+ "Data frame"
+};
+
+static void
+dissect_isl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *fh_tree = NULL;
+ proto_item *ti;
+ guint8 type;
+ guint16 length;
+ gint crc_offset;
+ gint captured_length;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISL");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ type = (tvb_get_guint8(tvb, 5) >> 4)&0x0F;
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_isl, tvb, 0, ISL_HEADER_SIZE,
+ "ISL");
+ fh_tree = proto_item_add_subtree(ti, ett_isl);
+ proto_tree_add_item(fh_tree, hf_isl_dst, tvb, 0, 6, FALSE);
+ proto_tree_add_item_hidden(fh_tree, hf_isl_addr, tvb, 0, 6, FALSE);
+ proto_tree_add_item(fh_tree, hf_isl_type, tvb, 5, 1, FALSE);
+ switch (type) {
+
+ case TYPE_ETHER:
+ proto_tree_add_item(fh_tree, hf_isl_user_eth, tvb, 5, 1, FALSE);
+ break;
+
+ default:
+ /* XXX - the spec appears to indicate that the "User" field is
+ used for TYPE_TR to distinguish between types of packets. */
+ proto_tree_add_item(fh_tree, hf_isl_user, tvb, 5, 1, FALSE);
+ break;
+ }
+ proto_tree_add_item(fh_tree, hf_isl_src, tvb, 6, 6, FALSE);
+ proto_tree_add_item_hidden(fh_tree, hf_isl_addr, tvb, 6, 6, FALSE);
+ }
+ length = tvb_get_ntohs(tvb, 12);
+ if (tree) {
+ proto_tree_add_uint(fh_tree, hf_isl_len, tvb, 12, 2, length);
+
+ /* This part looks sort of like a SNAP-encapsulated LLC header... */
+ proto_tree_add_text(fh_tree, tvb, 14, 1, "DSAP: 0x%X", tvb_get_guint8(tvb, 14));
+ proto_tree_add_text(fh_tree, tvb, 15, 1, "SSAP: 0x%X", tvb_get_guint8(tvb, 15));
+ proto_tree_add_text(fh_tree, tvb, 16, 1, "Control: 0x%X", tvb_get_guint8(tvb, 16));
+
+ /* ...but this is the manufacturer's ID portion of the source address
+ field (which is, admittedly, an OUI). */
+ proto_tree_add_item(fh_tree, hf_isl_hsa, tvb, 17, 3, FALSE);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "VLAN ID: 0x%04X",
+ tvb_get_ntohs(tvb, 20) >> 1);
+ if (tree) {
+ proto_tree_add_item(fh_tree, hf_isl_vlan_id, tvb, 20, 2, FALSE);
+ proto_tree_add_item(fh_tree, hf_isl_bpdu, tvb, 20, 2, FALSE);
+ proto_tree_add_item(fh_tree, hf_isl_index, tvb, 22, 2, FALSE);
+
+ /* Now for the encapsulated frame's CRC, which is at the *end* of the
+ packet; "length" is the length of the frame, not including the
+ first 14 bytes of the frame, but including the encapsulated
+ frame's CRC, which is 4 bytes long, so the offset of the
+ encapsulated CRC is "length + 14 - 4".
+
+ We check for the CRC and display it only if we have that data,
+ rather than throwing an exception before we've dissected any
+ of the rest of the frame. */
+ crc_offset = length + 14 - 4;
+ if (tvb_bytes_exist(tvb, crc_offset, 4))
+ proto_tree_add_item(fh_tree, hf_isl_crc, tvb, crc_offset, 4, FALSE);
+ }
+
+ switch (type) {
+
+ case TYPE_ETHER:
+ /* The length of the encapsulated frame is the length from the
+ header, minus 12 bytes for the part of the ISL header that
+ follows the length and 4 bytes for the encapsulated frame
+ CRC. */
+ if (length >= 12+4) {
+ /* Well, we at least had that much data in the frame. Try
+ dissecting what's left as an Ethernet frame. */
+ length -= 12+4;
+
+ /* Trim the captured length. */
+ captured_length = tvb_length_remaining(tvb, ISL_HEADER_SIZE);
+ if (captured_length > 4) {
+ /* Subtract the encapsulated frame CRC. */
+ captured_length -= 4;
+
+ /* Make sure it's not bigger than the actual length. */
+ if (captured_length > length)
+ captured_length = length;
+
+ next_tvb = tvb_new_subset(tvb, ISL_HEADER_SIZE, captured_length, length);
+
+ call_dissector(eth_handle, next_tvb, pinfo, tree);
+ }
+ }
+ break;
+
+ case TYPE_TR:
+ if (tree) {
+ proto_tree_add_item(fh_tree, hf_isl_src_vlan_id, tvb, 24, 2, FALSE);
+ proto_tree_add_item(fh_tree, hf_isl_explorer, tvb, 24, 2, FALSE);
+ proto_tree_add_item(fh_tree, hf_isl_dst_route_descriptor, tvb, 26, 2, FALSE);
+ proto_tree_add_item(fh_tree, hf_isl_src_route_descriptor, tvb, 28, 2, FALSE);
+ proto_tree_add_item(fh_tree, hf_isl_fcs_not_incl, tvb, 30, 1, FALSE);
+ proto_tree_add_item(fh_tree, hf_isl_esize, tvb, 30, 1, FALSE);
+ }
+ next_tvb = tvb_new_subset(tvb, 31, -1, -1);
+ call_dissector(tr_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ next_tvb = tvb_new_subset(tvb, ISL_HEADER_SIZE, -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ break;
+ }
+}
+
+void
+proto_register_isl(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_isl_dst,
+ { "Destination", "isl.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Destination Address", HFILL }},
+ { &hf_isl_type,
+ { "Type", "isl.type", FT_UINT8, BASE_DEC,
+ VALS(type_vals), 0xF0, "Type", HFILL }},
+ { &hf_isl_user_eth,
+ { "User", "isl.user_eth", FT_UINT8, BASE_DEC,
+ VALS(ether_user_vals), 0x0F, "Priority (for Ethernet)", HFILL }},
+ { &hf_isl_user,
+ { "User", "isl.user", FT_UINT8, BASE_HEX, NULL, 0x0F,
+ "User-defined bits", HFILL }},
+ { &hf_isl_src,
+ { "Source", "isl.src", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Source Hardware Address", HFILL }},
+ { &hf_isl_addr,
+ { "Source or Destination Address", "isl.addr", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Source or Destination Hardware Address", HFILL }},
+ { &hf_isl_len,
+ { "Length", "isl.len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_isl_hsa,
+ { "HSA", "isl.hsa", FT_UINT24, BASE_HEX, NULL, 0x0,
+ "High bits of source address", HFILL }},
+ { &hf_isl_vlan_id,
+ { "VLAN ID", "isl.vlan_id", FT_UINT16, BASE_HEX, NULL,
+ 0xFFFE, "Virtual LAN ID", HFILL }},
+ { &hf_isl_bpdu,
+ { "BPDU", "isl.bpdu", FT_BOOLEAN, 16,
+ TFS(&bpdu_tfs), 0x0001, "BPDU indicator", HFILL }},
+ { &hf_isl_index,
+ { "Index", "isl.index", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Port index of packet source", HFILL }},
+ { &hf_isl_crc,
+ { "CRC", "isl.crc", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "CRC field of encapsulated frame", HFILL }},
+ { &hf_isl_src_vlan_id,
+ { "Source VLAN ID", "isl.src_vlan_id", FT_UINT16, BASE_HEX, NULL,
+ 0xFFFE, "Source Virtual LAN ID", HFILL }},
+ { &hf_isl_explorer,
+ { "Explorer", "isl.explorer", FT_BOOLEAN, 16,
+ TFS(&explorer_tfs), 0x0001, "Explorer", HFILL }},
+ { &hf_isl_dst_route_descriptor,
+ { "Destination route descriptor", "isl.dst_route_desc",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Route descriptor to be used for forwarding", HFILL }},
+ { &hf_isl_src_route_descriptor,
+ { "Source-route descriptor", "isl.src_route_desc",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Route descriptor to be used for source learning", HFILL }},
+ { &hf_isl_fcs_not_incl,
+ { "FCS Not Included", "isl.fcs_not_incl", FT_BOOLEAN, 9,
+ NULL, 0x40, "FCS not included", HFILL }},
+ { &hf_isl_esize,
+ { "Esize", "isl.esize", FT_UINT8, BASE_DEC, NULL,
+ 0x3F, "Frame size for frames less than 64 bytes", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_isl,
+ };
+
+ proto_isl = proto_register_protocol("Cisco ISL", "ISL", "isl");
+ proto_register_field_array(proto_isl, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("isl", dissect_isl, proto_isl);
+}
+
+void
+proto_reg_handoff_isl(void)
+{
+ /*
+ * Get handles for the Ethernet and Token Ring dissectors.
+ */
+ eth_handle = find_dissector("eth");
+ tr_handle = find_dissector("tr");
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-isl.h b/epan/dissectors/packet-isl.h
new file mode 100644
index 0000000000..d26417c9f0
--- /dev/null
+++ b/epan/dissectors/packet-isl.h
@@ -0,0 +1,29 @@
+/* packet-isl.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_ISL_H__
+#define __PACKET_ISL_H__
+
+void capture_isl(const guchar *, int, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-ismp.c b/epan/dissectors/packet-ismp.c
new file mode 100644
index 0000000000..2e5da036df
--- /dev/null
+++ b/epan/dissectors/packet-ismp.c
@@ -0,0 +1,874 @@
+/* packet-ismp.c
+ * Routines for ISMP dissection
+ * Enterasys Networks Home: http://www.enterasys.com/
+ * Copyright 2003, Joshua Craig Douglas <jdouglas@enterasys.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "etypes.h"
+
+
+/* Initialize the protocol and registered fields */
+static int proto_ismp = -1;
+static int hf_ismp_version = -1;
+static int hf_ismp_message_type = -1;
+static int hf_ismp_seq_num = -1;
+static int hf_ismp_code_length = -1;
+static int hf_ismp_auth_data = -1;
+
+/* Enterasys/Cabletron Dicovery Protocol fields*/
+static int hf_ismp_edp_version = -1;
+static int hf_ismp_edp_module_ip = -1;
+static int hf_ismp_edp_module_mac = -1;
+static int hf_ismp_edp_module_port = -1;
+static int hf_ismp_edp_chassis_mac =-1;
+static int hf_ismp_edp_chassis_ip = -1;
+static int hf_ismp_edp_device_type = -1;
+static int hf_ismp_edp_module_rev = -1;
+static int hf_ismp_edp_options = -1;
+static int hf_ismp_edp_sfs_option_unused1 = -1;
+static int hf_ismp_edp_sfs_option_sfssup = -1;
+static int hf_ismp_edp_sfs_option_lsp = -1;
+static int hf_ismp_edp_sfs_option_flood = -1;
+static int hf_ismp_edp_sfs_option_resolve = -1;
+static int hf_ismp_edp_sfs_option_unused2 = -1;
+static int hf_ismp_edp_sfs_option_tagflood = -1;
+static int hf_ismp_edp_sfs_option_calltap = -1;
+static int hf_ismp_edp_sfs_option_conmsg = -1;
+static int hf_ismp_edp_sfs_option_redun = -1;
+static int hf_ismp_edp_sfs_option_isolated = -1;
+static int hf_ismp_edp_sfs_option_uplink_switch = -1;
+static int hf_ismp_edp_sfs_option_uplink_core = -1;
+static int hf_ismp_edp_sfs_option_uplink_port = -1;
+static int hf_ismp_edp_sfs_option_uplink_flood = -1;
+static int hf_ismp_edp_rtr_option_ssr = -1;
+static int hf_ismp_edp_rtr_option_igmp = -1;
+static int hf_ismp_edp_rtr_option_rip = -1;
+static int hf_ismp_edp_rtr_option_bgp = -1;
+static int hf_ismp_edp_rtr_option_ospf = -1;
+static int hf_ismp_edp_rtr_option_dvmrp = -1;
+static int hf_ismp_edp_rtr_option_8021q = -1;
+static int hf_ismp_edp_rtr_option_gvrp = -1;
+static int hf_ismp_edp_rtr_option_gmrp = -1;
+static int hf_ismp_edp_rtr_option_igmp_snoop = -1;
+static int hf_ismp_edp_rtr_option_route = -1;
+static int hf_ismp_edp_rtr_option_trans = -1;
+static int hf_ismp_edp_rtr_option_level1 = -1;
+static int hf_ismp_edp_switch_option_8021q = -1;
+static int hf_ismp_edp_switch_option_gvrp = -1;
+static int hf_ismp_edp_switch_option_gmrp = -1;
+static int hf_ismp_edp_switch_option_igmp = -1;
+static int hf_ismp_edp_switch_option_route = -1;
+static int hf_ismp_edp_switch_option_trans = -1;
+static int hf_ismp_edp_switch_option_level1 = -1;
+static int hf_ismp_edp_end_station_option_dhcp = -1;
+static int hf_ismp_edp_end_station_option_dns = -1;
+static int hf_ismp_edp_end_station_option_ad = -1;
+static int hf_ismp_edp_num_neighbors = -1;
+static int hf_ismp_edp_neighbors = -1;
+static int hf_ismp_edp_num_tuples = -1;
+static int hf_ismp_edp_tuples = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_ismp = -1;
+static gint ett_ismp_edp = -1;
+static gint ett_ismp_edp_options = -1;
+static gint ett_ismp_edp_neighbors = -1;
+static gint ett_ismp_edp_neighbors_leaf = -1;
+static gint ett_ismp_edp_tuples = -1;
+static gint ett_ismp_edp_tuples_leaf = -1;
+
+/* ISMP TYPES */
+#define ISMPTYPE_EDP 2
+
+
+/* EDP DEVICE TYPES */
+#define EDP_DEVICE_TYPE_SFS17 1
+#define EDP_DEVICE_TYPE_SFS18 2
+#define EDP_DEVICE_TYPE_ROUTER 3
+#define EDP_DEVICE_TYPE_BRIDGE 4
+#define EDP_DEVICE_TYPE_VLANMAN 5
+#define EDP_DEVICE_TYPE_NTSERVER 6
+#define EDP_DEVICE_TYPE_NTCLIENT 7
+#define EDP_DEVICE_TYPE_WIN95 8
+#define EDP_DEVICE_TYPE_WIN98 9
+#define EDP_DEVICE_TYPE_UNIXSERVER 10
+#define EDP_DEVICE_TYPE_UNIXCLIENT 11
+#define EDP_DEVICE_TYPE_ACCESSPOINT 12
+
+
+static const value_string edp_device_types[] = {
+ { EDP_DEVICE_TYPE_SFS17, "Network Switch running SecureFast version 1.7 or lower" },
+ { EDP_DEVICE_TYPE_SFS18, "Network Switch running SecureFast version 1.8 or greater" },
+ { EDP_DEVICE_TYPE_ROUTER, "Router" },
+ { EDP_DEVICE_TYPE_BRIDGE, "Bridge" },
+ { EDP_DEVICE_TYPE_VLANMAN, "Cabletron VLAN Manager" },
+ { EDP_DEVICE_TYPE_NTSERVER, "Network Server (NT)" },
+ { EDP_DEVICE_TYPE_NTCLIENT, "Network Workstation (NT)" },
+ { EDP_DEVICE_TYPE_WIN95, "Windows95" },
+ { EDP_DEVICE_TYPE_WIN98, "Windows98" },
+ { EDP_DEVICE_TYPE_UNIXSERVER, "UNIX Server" },
+ { EDP_DEVICE_TYPE_UNIXCLIENT, "UNIX Workstation" },
+ { EDP_DEVICE_TYPE_ACCESSPOINT, "Roamabout wireless access point" },
+ { 0, NULL },
+};
+
+
+/* EDP SFS Options */
+#define EDP_SFS_OPTION_UNUSED1 0x1
+#define EDP_SFS_OPTION_SFSSUP 0x2
+#define EDP_SFS_OPTION_LSP 0x4
+#define EDP_SFS_OPTION_FLOOD 0x8
+#define EDP_SFS_OPTION_RESOLVE 0x10
+#define EDP_SFS_OPTION_UNUSED2 0x20
+#define EDP_SFS_OPTION_TAGFLOOD 0x40
+#define EDP_SFS_OPTION_CALLTAP 0x80
+#define EDP_SFS_OPTION_CONMSG 0x100
+#define EDP_SFS_OPTION_REDUN 0x200
+#define EDP_SFS_OPTION_ISOLATED 0x400
+#define EDP_SFS_OPTION_UPLINK_SWITCH 0x800
+#define EDP_SFS_OPTION_UPLINK_CORE 0x1000
+#define EDP_SFS_OPTION_UPLINK_PORT 0x2000
+#define EDP_SFS_OPTION_UPLINK_FLOOD 0x4000
+
+/* EDP Router Options */
+#define EDP_RTR_OPTION_SSR 0x1
+#define EDP_RTR_OPTION_IGMP 0x2
+#define EDP_RTR_OPTION_RIP 0x4
+#define EDP_RTR_OPTION_BGP 0x8
+#define EDP_RTR_OPTION_OSPF 0x10
+#define EDP_RTR_OPTION_DVMRP 0x20
+#define EDP_RTR_OPTION_8021Q 0x40
+#define EDP_RTR_OPTION_GVRP 0x80
+#define EDP_RTR_OPTION_GMRP 0x100
+#define EDP_RTR_OPTION_IGMP_SNOOP 0x200
+#define EDP_RTR_OPTION_ROUTE 0x400
+#define EDP_RTR_OPTION_TRANS 0x800
+#define EDP_RTR_OPTION_LEVEL1 0x1000
+
+/* EDP Switch Options */
+#define EDP_SWITCH_OPTION_8021Q 0x1
+#define EDP_SWITCH_OPTION_GVRP 0x2
+#define EDP_SWITCH_OPTION_GMRP 0x4
+#define EDP_SWITCH_OPTION_IGMP 0x8
+#define EDP_SWITCH_OPTION_ROUTE 0x10
+#define EDP_SWITCH_OPTION_TRANS 0x20
+#define EDP_SWITCH_OPTION_LEVEL1 0x40
+
+/* EDP End Station and Server Options */
+#define EDP_END_STATION_OPTION_DHCP 0x1
+#define EDP_END_STATION_OPTION_DNS 0x2
+#define EDP_END_STATION_OPTION_AD 0x4
+
+/* EDP Tuple Types */
+#define EDP_TUPLE_UNKNOWN 0
+#define EDP_TUPLE_HOLD 1
+#define EDP_TUPLE_INT_NAME 2
+#define EDP_TUPLE_SYS_DESCRIPT 3
+#define EDP_TUPLE_IPX_ADDR 4
+
+static const value_string edp_tuple_types[] =
+{
+ { EDP_TUPLE_UNKNOWN,"Unknown" },
+ { EDP_TUPLE_HOLD,"Hold Time" },
+ { EDP_TUPLE_INT_NAME,"Interface Name" },
+ { EDP_TUPLE_SYS_DESCRIPT,"System Description" },
+ { EDP_TUPLE_IPX_ADDR,"IPX Address" },
+ { 0,NULL }
+};
+
+/* Is value set? */
+static const true_false_string is_set = {
+ "set",
+ "not set"
+};
+
+
+/* Function to dissect EDP portion of ISMP message */
+static void
+dissect_ismp_edp(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *ismp_tree)
+{
+ /* local variables used for EDP dissection */
+ int neighbors_count = 0;
+ int tuples_count = 0;
+ guint16 device_type = 0;
+ guint32 options = 0;
+ guint16 num_neighbors = 0;
+ guint16 num_tuples = 0;
+ guint16 tuple_type = 0;
+ guint16 tuple_length = 0;
+ const guint8 *neighbors_ptr;
+ const guint8 *tuples_ptr;
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *edp_ti;
+ proto_tree *ismp_edp_tree;
+
+ proto_item *edp_options_ti;
+ proto_tree *edp_options_tree;
+
+ proto_item *edp_neighbors_ti;
+ proto_tree *edp_neighbors_tree;
+
+ proto_item *edp_neighbors_leaf_ti;
+ proto_tree *edp_neighbors_leaf_tree;
+
+ proto_item *edp_tuples_ti;
+ proto_tree *edp_tuples_tree;
+
+ proto_item *edp_tuples_leaf_ti;
+ proto_tree *edp_tuples_leaf_tree;
+
+ /* add column iformation marking this as EDP (Enterasys Discover Protocol */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "EDP Message");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* create display subtree for EDP */
+ if (ismp_tree) {
+ edp_ti = proto_tree_add_text(ismp_tree, tvb, offset, 0, "Enterasys Discovery Protocol");
+ ismp_edp_tree = proto_item_add_subtree(edp_ti, ett_ismp_edp);
+
+
+ proto_tree_add_item(ismp_edp_tree, hf_ismp_edp_version, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(ismp_edp_tree, hf_ismp_edp_module_ip, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(ismp_edp_tree, hf_ismp_edp_module_mac, tvb, offset, 6, FALSE);
+ offset += 6;
+ proto_tree_add_item(ismp_edp_tree, hf_ismp_edp_module_port, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(ismp_edp_tree, hf_ismp_edp_chassis_mac, tvb, offset, 6, FALSE);
+ offset += 6;
+ proto_tree_add_item(ismp_edp_tree, hf_ismp_edp_chassis_ip, tvb, offset, 4, FALSE);
+ offset += 4;
+ device_type = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(ismp_edp_tree, hf_ismp_edp_device_type, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_uint_format(ismp_edp_tree, hf_ismp_edp_module_rev, tvb, offset, 4, tvb_get_ntohl(tvb, offset),
+ "Module Firmware Revision: %02x.%02x.%02x.%02x", tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3));
+ offset += 4;
+
+ /* create display subtree for EDP options */
+ options = tvb_get_ntohl(tvb, offset);
+ edp_options_ti = proto_tree_add_uint_format(ismp_edp_tree, hf_ismp_edp_options, tvb, offset, 4,
+ options,"Options: 0x%08x",options);
+ edp_options_tree = proto_item_add_subtree(edp_options_ti, ett_ismp_edp_options);
+
+ /* depending on device_type, show the appropriate options */
+ switch (device_type) {
+ case EDP_DEVICE_TYPE_SFS17:
+ case EDP_DEVICE_TYPE_SFS18:
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_flood, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_port, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_core, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_switch, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_isolated, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_redun, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_conmsg, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_calltap, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_tagflood, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused2, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_resolve, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_flood, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_lsp, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_sfssup, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused1, tvb, offset, 4, FALSE);
+ break;
+ case EDP_DEVICE_TYPE_ROUTER:
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_level1, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_trans, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_route, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp_snoop, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gmrp, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gvrp, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_8021q, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_dvmrp, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ospf, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_bgp, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_rip, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ssr, tvb, offset, 4, FALSE);
+ break;
+ case EDP_DEVICE_TYPE_BRIDGE:
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_level1, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_trans, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_route, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_igmp, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gmrp, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gvrp, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_8021q, tvb, offset, 4, FALSE);
+ break;
+ case EDP_DEVICE_TYPE_VLANMAN:
+ break;
+ case EDP_DEVICE_TYPE_NTSERVER:
+ case EDP_DEVICE_TYPE_NTCLIENT:
+ case EDP_DEVICE_TYPE_WIN95:
+ case EDP_DEVICE_TYPE_WIN98:
+ case EDP_DEVICE_TYPE_UNIXSERVER:
+ case EDP_DEVICE_TYPE_UNIXCLIENT:
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_ad, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dns, tvb, offset, 4, FALSE);
+ proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dhcp, tvb, offset, 4, FALSE);
+ break;
+ case EDP_DEVICE_TYPE_ACCESSPOINT:
+ default:
+ break;
+ }
+ offset += 4;
+
+ /* determine the number of neighbors and create EDP neighbors subtree */
+ num_neighbors = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(ismp_edp_tree, hf_ismp_edp_num_neighbors, tvb, offset, 2, FALSE);
+ offset += 2;
+ if (num_neighbors > 0)
+ {
+ if (tvb_reported_length_remaining(tvb, offset) >= (num_neighbors *10))
+ {
+ neighbors_ptr = tvb_get_ptr( tvb, offset, (num_neighbors*10) );
+ edp_neighbors_ti = proto_tree_add_bytes_format(ismp_edp_tree, hf_ismp_edp_neighbors, tvb,
+ offset, num_neighbors*10, neighbors_ptr, "Neighbors:");
+ }
+ else
+ {
+ neighbors_ptr = tvb_get_ptr( tvb, offset, tvb_reported_length_remaining(tvb, offset) );
+ edp_neighbors_ti = proto_tree_add_bytes_format(ismp_edp_tree, hf_ismp_edp_neighbors, tvb,
+ offset, num_neighbors *10, neighbors_ptr, "Neighbors:");
+ }
+ edp_neighbors_tree = proto_item_add_subtree(edp_neighbors_ti, ett_ismp_edp_neighbors);
+ while ( neighbors_count < num_neighbors && tvb_reported_length_remaining(tvb, offset) >= 10)
+ {
+ edp_neighbors_leaf_ti = proto_tree_add_text(edp_neighbors_tree, tvb, offset, 10,
+ "Neighbor%d", (neighbors_count+1));
+ edp_neighbors_leaf_tree = proto_item_add_subtree(edp_neighbors_leaf_ti, ett_ismp_edp_neighbors_leaf);
+
+ proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 6,
+ "MAC Address: %s", ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 4,
+ "Assigned Neighbor State 0x%04x",tvb_get_ntohl(tvb, offset));
+ offset += 10;
+ neighbors_count++;
+ }
+ if (neighbors_count != num_neighbors)
+ {
+ proto_tree_add_text(ismp_edp_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
+ "MALFORMED PACKET");
+ return;
+ }
+ }
+
+ /* determine data remains, if so, count tuples
+ and create EDP tuples subtree */
+ if (tvb_reported_length_remaining(tvb, offset) != 0 &&
+ tvb_reported_length_remaining(tvb, offset) >= 2)
+ {
+ num_tuples = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(ismp_edp_tree, hf_ismp_edp_num_tuples, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ else if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_text(ismp_edp_tree, tvb, offset,
+ tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET");
+ return;
+ }
+ else
+ {
+ return;
+ }
+
+ /* start populating tuple information */
+ if (num_tuples && tvb_reported_length_remaining(tvb, offset) >= 4)
+ {
+ tuples_ptr = tvb_get_ptr(tvb, offset, tvb_reported_length_remaining(tvb, offset));
+ edp_tuples_ti = proto_tree_add_bytes_format(ismp_edp_tree, hf_ismp_edp_tuples, tvb,
+ offset, tvb_reported_length_remaining(tvb, offset), tuples_ptr, "Tuples:");
+ edp_tuples_tree = proto_item_add_subtree(edp_tuples_ti, ett_ismp_edp_tuples);
+
+ while ( (tuples_count < num_tuples) && (tvb_reported_length_remaining(tvb, offset) >= 4) )
+ {
+
+ tuple_length = tvb_get_ntohs(tvb, offset+2);
+ edp_tuples_leaf_ti = proto_tree_add_text(edp_tuples_tree, tvb, offset, tuple_length,
+ "Tuple%d", tuples_count+1);
+
+ edp_tuples_leaf_tree = proto_item_add_subtree(edp_tuples_leaf_ti, ett_ismp_edp_tuples_leaf);
+
+ tuple_type = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2,
+ "Tuple Type: %s(%d)", val_to_str( tuple_type, edp_tuple_types, "Unknown"), tuple_type );
+ offset += 2;
+ proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2,
+ "Tuple Length: %d", tuple_length);
+ tuple_length -= 4;
+ offset += 2;
+
+ if (tvb_reported_length_remaining(tvb, offset) >= tuple_length)
+ {
+ switch (tuple_type)
+ {
+ case EDP_TUPLE_HOLD:
+ proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
+ "Hold Time = %d", tvb_get_ntohs(tvb, offset));
+ break;
+ case EDP_TUPLE_INT_NAME:
+ proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
+ "Interface Name = %s", tvb_format_text(tvb, offset, tuple_length));
+ break;
+ case EDP_TUPLE_SYS_DESCRIPT:
+ proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
+ "System Description = %s", tvb_format_text(tvb, offset, tuple_length));
+ break;
+ case EDP_TUPLE_IPX_ADDR:
+ proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
+ "Interface IPX_address = %s",
+ ipx_addr_to_str(tvb_get_ntohl(tvb, offset),
+ tvb_get_ptr(tvb, offset+4, tuple_length-4)));
+ break;
+ case EDP_TUPLE_UNKNOWN:
+ default:
+ proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
+ "Unknown Tuple Data %s", tvb_format_text(tvb, offset, tuple_length));
+ break;
+ }
+ }
+ offset += tuple_length;
+
+ tuples_count++;
+ tuple_type = 0;
+ tuple_length = 0;
+ }
+ if (tuples_count != num_tuples)
+ {
+ proto_tree_add_text(ismp_edp_tree, tvb, offset,
+ tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET");
+ return;
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ }
+
+
+}
+
+
+/* Code to actually dissect the packets */
+static void
+dissect_ismp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint16 message_type = 0;
+ guint8 code_length = 0;
+ guint8 weird_stuff[3] = { 0x42, 0x42, 0x03 };
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *ismp_tree;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISMP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /*
+ * XXX - I've seen captures with packets that have the ISMP
+ * Ethernet frame type, but with the payload being 0x42 0x42 0x03
+ * followed by what appears to be an ISMP frame.
+ *
+ * 0x4242 is not a valid ISMP version number.
+ */
+ if (tvb_memeql(tvb, offset, weird_stuff, sizeof weird_stuff) == 0)
+ offset += 3; /* skip the weird stuff, for now */
+ if (tree) {
+ /* create display subtree for ismp */
+ ti = proto_tree_add_item(tree, proto_ismp, tvb, offset, -1, FALSE);
+
+ ismp_tree = proto_item_add_subtree(ti, ett_ismp);
+
+ /* add an items to the subtree */
+ proto_tree_add_item(ismp_tree, hf_ismp_version, tvb, offset, 2, FALSE);
+ offset += 2;
+ message_type = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(ismp_tree, hf_ismp_message_type, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(ismp_tree, hf_ismp_seq_num, tvb, offset, 2, FALSE);
+ offset += 2;
+ code_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(ismp_tree, hf_ismp_code_length, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(ismp_tree, hf_ismp_auth_data, tvb, offset, code_length, FALSE);
+ offset += code_length;
+
+ /* if Enterasys Discover Protocol, dissect it */
+ if(message_type == ISMPTYPE_EDP)
+ dissect_ismp_edp(tvb, pinfo, offset, ismp_tree);
+ }
+
+}
+
+
+/* Register this protocol with Ethereal */
+void
+proto_register_ismp(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_ismp_version,
+ { "Version", "ismp.version",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_message_type,
+ { "Message Type", "ismp.msgtype",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_seq_num,
+ { "Sequence Number", "ismp.seqnum",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_code_length,
+ { "Auth Code Length", "ismp.codelen",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_auth_data,
+ { "Auth Data", "ismp.authdata",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_version,
+ { "Version", "ismp.edp.version",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_module_ip,
+ { "Module IP Address", "ismp.edp.modip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_module_mac,
+ { "Module MAC Address", "ismp.edp.modmac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_module_port,
+ { "Module Port (ifIndex num)", "ismp.edp.modport",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_chassis_mac,
+ { "Chassis MAC Address", "ismp.edp.chassismac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_chassis_ip,
+ { "Chassis IP Address", "ismp.edp.chassisip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_device_type,
+ { "Device Type", "ismp.edp.devtype",
+ FT_UINT16, BASE_DEC, edp_device_types, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_module_rev,
+ { "Module Firmware Revision", "ismp.edp.rev",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_options,
+ { "Device Options", "ismp.edp.opts",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_unused1,
+ { "Unused", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UNUSED1,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_sfssup,
+ { "SFS Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_SFSSUP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_lsp,
+ { "LSP Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_LSP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_flood,
+ { "Flood Path Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_FLOOD,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_resolve,
+ { "Resolve Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_RESOLVE,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_unused2,
+ { "Unused", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UNUSED2,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_tagflood,
+ { "Tagged Flood Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_TAGFLOOD,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_calltap,
+ { "Call Tap Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_CALLTAP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_conmsg,
+ { "Connection Message Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_CONMSG,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_redun,
+ { "Redundant Access Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_REDUN,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_isolated,
+ { "Isolated Switch", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_ISOLATED,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_uplink_switch,
+ { "Uplink Switch", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UPLINK_SWITCH,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_uplink_core,
+ { "Uplink Core", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UPLINK_CORE,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_uplink_port,
+ { "Uplink Port", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UPLINK_PORT,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_sfs_option_uplink_flood,
+ { "Uplink Flood Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UPLINK_FLOOD,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_ssr,
+ { "SSR Type Device", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_SSR,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_igmp,
+ { "IGMP Active", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_IGMP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_rip,
+ { "RIP Active", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_RIP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_bgp,
+ { "BGP Active", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_BGP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_ospf,
+ { "OSPF Active", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_OSPF,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_dvmrp,
+ { "DVMRP Active", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_DVMRP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_8021q,
+ { "802.1Q Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_8021Q,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_gvrp,
+ { "GVRP Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_GVRP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_gmrp,
+ { "GMRP Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_GMRP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_igmp_snoop,
+ { "IGMP Snooping Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_IGMP_SNOOP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_route,
+ { "Route Bridging", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_ROUTE,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_trans,
+ { "Transparent Bridging", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_TRANS,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_rtr_option_level1,
+ { "Level 1 Functionality", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_LEVEL1,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_switch_option_8021q,
+ { "802.1Q Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_8021Q,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_switch_option_gvrp,
+ { "GVRP Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_GVRP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_switch_option_gmrp,
+ { "GMRP Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_GMRP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_switch_option_igmp,
+ { "IGMP Snooping Support", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_IGMP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_switch_option_route,
+ { "Route Bridging", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_ROUTE,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_switch_option_trans,
+ { "Transparent Bridging", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_TRANS,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_switch_option_level1,
+ { "Level 1 Functionality", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_LEVEL1,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_end_station_option_dhcp,
+ { "DHCP Enabled", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_END_STATION_OPTION_DHCP,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_end_station_option_dns,
+ { "DNS Enabled", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_END_STATION_OPTION_DNS,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_end_station_option_ad,
+ { "Active Directory Enabled", "ismp.edp.opts",
+ FT_BOOLEAN, 32, TFS(&is_set), EDP_END_STATION_OPTION_AD,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_num_neighbors,
+ { "Number of Known Neighbors", "ismp.edp.maccount",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_neighbors,
+ { "Neighbors", "ismp.edp.nbrs",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_num_tuples,
+ { "Number of Tuples", "ismp.edp.numtups",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ismp_edp_tuples,
+ { "Number of Tuples", "ismp.edp.tups",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_ismp,
+ &ett_ismp_edp,
+ &ett_ismp_edp_options,
+ &ett_ismp_edp_neighbors,
+ &ett_ismp_edp_neighbors_leaf,
+ &ett_ismp_edp_tuples,
+ &ett_ismp_edp_tuples_leaf,
+ };
+
+/* Register the protocol name and description */
+ proto_ismp = proto_register_protocol("InterSwitch Message Protocol",
+ "ISMP", "ismp");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ismp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_ismp(void)
+{
+ dissector_handle_t ismp_handle;
+
+ ismp_handle = create_dissector_handle(dissect_ismp,
+ proto_ismp);
+ dissector_add("ethertype", ETHERTYPE_ISMP, ismp_handle);
+}
diff --git a/epan/dissectors/packet-isns.c b/epan/dissectors/packet-isns.c
new file mode 100644
index 0000000000..f4fa286494
--- /dev/null
+++ b/epan/dissectors/packet-isns.c
@@ -0,0 +1,1922 @@
+/* XXX fixme can not reassemple multiple isns PDU fragments into one
+ isns PDU
+*/
+
+/* packet-isns.c
+ * Routines for iSNS dissection
+ * Copyright 2003, Elipsan, Gareth Bushell <gbushell@elipsan.com>
+ * (c) 2004 Ronnie Sahlberg updates
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "packet-tcp.h"
+#include "prefs.h"
+
+
+#define ISNS_PROTO_VER 0x1
+#define ISNS_HEADER_SIZE 12
+
+#define ISNS_TCP_PORT 3205
+#define ISNS_UDP_PORT 3205
+
+#define ISNS_OTHER_PORT 0
+#define ISNS_ESI_PORT 1
+#define ISNS_SCN_PORT 2
+
+
+dissector_handle_t isns_tcp_handle;
+dissector_handle_t isns_udp_handle;
+
+static gint ett_isns_flags = -1;
+static gint ett_isns_payload = -1;
+static gint ett_isns_attribute = -1;
+static gint ett_isns_port = -1;
+static gint ett_isns_isnt = -1;
+
+static guint AddAttribute(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
+ guint offset, guint16 function_id);
+
+/* Initialize the protocol and registered fields */
+static int proto_isns = -1;
+
+
+/* Header Stuff */
+static int hf_isns_version = -1;
+static int hf_isns_function_id = -1;
+static int hf_isns_pdu_length = -1;
+static int hf_isns_flags = -1;
+static int hf_isns_transaction_id = -1;
+static int hf_isns_sequence_id = -1;
+static int hf_isns_payload = -1;
+static int hf_isns_first_pdu = -1;
+static int hf_isns_last_pdu = -1;
+static int hf_isns_replace = -1;
+static int hf_isns_auth = -1;
+static int hf_isns_server = -1;
+static int hf_isns_client = -1;
+
+/* Payload stuff */
+static int hf_isns_scn_bitmap = -1;
+static int hf_isns_scn_bitmap_initiator_and_self_information_only = -1;
+static int hf_isns_scn_bitmap_target_and_self_information_only = -1;
+static int hf_isns_scn_bitmap_management_registration_scn = -1;
+static int hf_isns_scn_bitmap_object_removed = -1;
+static int hf_isns_scn_bitmap_object_added = -1;
+static int hf_isns_scn_bitmap_object_updated = -1;
+static int hf_isns_scn_bitmap_dd_dds_member_removed = -1;
+static int hf_isns_scn_bitmap_dd_dds_member_added = -1;
+static int hf_isns_isnt_control = -1;
+static int hf_isns_isnt_initiator = -1;
+static int hf_isns_isnt_target = -1;
+
+static int hf_isns_psb = -1;
+static int hf_isns_psb_tunnel_mode = -1;
+static int hf_isns_psb_transport_mode = -1;
+static int hf_isns_psb_pfs = -1;
+static int hf_isns_psb_aggressive_mode = -1;
+static int hf_isns_psb_main_mode = -1;
+static int hf_isns_psb_ike_ipsec = -1;
+static int hf_isns_psb_bitmap = -1;
+
+static int hf_isns_dd_member_portal_port = -1;
+static int hf_isns_portal_port = -1;
+static int hf_isns_esi_port = -1;
+static int hf_isns_scn_port = -1;
+static int hf_isns_port_type = -1;
+
+static int hf_isns_entity_protocol = -1;
+static int hf_isns_iscsi_node_type = -1;
+static int hf_isns_resp_errorcode = -1;
+static int hf_isns_attr_tag = -1;
+static int hf_isns_attr_len = -1;
+static int hf_isns_heartbeat_ipv6_addr = -1;
+static int hf_isns_heartbeat_udp_port = -1;
+static int hf_isns_heartbeat_tcp_port = -1;
+static int hf_isns_heartbeat_interval = -1;
+static int hf_isns_heartbeat_counter = -1;
+
+static int hf_isns_mgmt_ip_addr = -1;
+static int hf_isns_node_ip_addr = -1;
+static int hf_isns_port_ip_addr = -1;
+static int hf_isns_portal_ip_addr = -1;
+static int hf_isns_dd_member_portal_ip_addr = -1;
+static int hf_isns_iscsi_name = -1;
+static int hf_isns_switch_name = -1;
+static int hf_isns_dd_member_iscsi_name = -1;
+static int hf_isns_virtual_fabric_id = -1;
+static int hf_isns_proxy_iscsi_name = -1;
+static int hf_isns_fc4_descriptor = -1;
+static int hf_isns_iscsi_auth_method = -1;
+static int hf_isns_iscsi_alias = -1;
+static int hf_isns_portal_symbolic_name = -1;
+static int hf_isns_dd_set_symbolic_name = -1;
+static int hf_isns_dd_symbolic_name = -1;
+static int hf_isns_symbolic_port_name = -1;
+static int hf_isns_symbolic_node_name = -1;
+static int hf_isns_entity_identifier = -1;
+static int hf_isns_dd_id_next_id = -1;
+static int hf_isns_member_iscsi_index = -1;
+static int hf_isns_member_portal_index = -1;
+static int hf_isns_member_ifcp_node = -1;
+static int hf_isns_vendor_oui = -1;
+static int hf_isns_preferred_id = -1;
+static int hf_isns_assigned_id = -1;
+static int hf_isns_dd_id = -1;
+static int hf_isns_dd_set_id = -1;
+static int hf_isns_dd_set_next_id = -1;
+static int hf_isns_node_index = -1;
+static int hf_isns_node_next_index = -1;
+static int hf_isns_entity_index = -1;
+static int hf_isns_portal_index = -1;
+static int hf_isns_portal_next_index = -1;
+static int hf_isns_entity_next_index = -1;
+static int hf_isns_timestamp = -1;
+static int hf_isns_esi_interval = -1;
+static int hf_isns_registration_period = -1;
+static int hf_isns_port_id = -1;
+static int hf_isns_hard_address = -1;
+static int hf_isns_wwnn_token = -1;
+static int hf_isns_node_ipa = -1;
+static int hf_isns_fc_port_name_wwpn = -1;
+static int hf_isns_fc_node_name_wwnn = -1;
+static int hf_isns_fabric_port_name = -1;
+static int hf_isns_permanent_port_name = -1;
+static int hf_isns_delimiter = -1;
+static int hf_isns_not_decoded_yet = -1;
+static int hf_isns_portal_group_tag = -1;
+static int hf_isns_pg_portal_ip_addr = -1;
+static int hf_isns_pg_portal_port = -1;
+
+
+
+/* Desegment iSNS over TCP messages */
+static gboolean isns_desegment = TRUE;
+
+/* Function Id's */
+#define ISNS_FUNC_DEVATTRREG 0x0001
+#define ISNS_FUNC_DEVATTRQRY 0x0002
+#define ISNS_FUNC_DEVGETNEXT 0x0003
+#define ISNS_FUNC_DEREGDEV 0x0004
+#define ISNS_FUNC_SCNREG 0x0005
+#define ISNS_FUNC_SCNDEREG 0x0006
+#define ISNS_FUNC_SCNEVENT 0x0007
+#define ISNS_FUNC_SCN 0x0008
+#define ISNS_FUNC_DDREG 0x0009
+#define ISNS_FUNC_DDDEREG 0x000a
+#define ISNS_FUNC_DDSREG 0x000b
+#define ISNS_FUNC_DDSDEREG 0x000c
+#define ISNS_FUNC_ESI 0x000d
+#define ISNS_FUNC_HEARTBEAT 0x000e
+
+#define ISNS_FUNC_RSP_DEVATTRREG 0x8001
+#define ISNS_FUNC_RSP_DEVATTRQRY 0x8002
+#define ISNS_FUNC_RSP_DEVGETNEXT 0x8003
+#define ISNS_FUNC_RSP_DEREGDEV 0x8004
+#define ISNS_FUNC_RSP_SCNREG 0x8005
+#define ISNS_FUNC_RSP_SCNDEREG 0x8006
+#define ISNS_FUNC_RSP_SCNEVENT 0x8007
+#define ISNS_FUNC_RSP_SCN 0x8008
+#define ISNS_FUNC_RSP_DDREG 0x8009
+#define ISNS_FUNC_RSP_DDDEREG 0x800a
+#define ISNS_FUNC_RSP_DDSREG 0x800b
+#define ISNS_FUNC_RSP_DDSDEREG 0x800c
+#define ISNS_FUNC_RSP_ESI 0x800d
+
+static const value_string isns_function_ids[] = {
+/* Requests*/
+ {ISNS_FUNC_DEVATTRREG, "DevAttrReg"},
+ {ISNS_FUNC_DEVATTRQRY, "DevAttrQry"},
+ {ISNS_FUNC_DEVGETNEXT, "DevGetNext"},
+ {ISNS_FUNC_DEREGDEV, "DeregDev"},
+ {ISNS_FUNC_SCNREG, "SCNReg"},
+ {ISNS_FUNC_SCNDEREG, "SCNDereg"},
+ {ISNS_FUNC_SCNEVENT, "SCNEvent"},
+ {ISNS_FUNC_SCN, "SCN"},
+ {ISNS_FUNC_DDREG, "DDReg"},
+ {ISNS_FUNC_DDDEREG, "DDDereg"},
+ {ISNS_FUNC_DDSREG, "DDSReg"},
+ {ISNS_FUNC_DDSDEREG, "DDSDereg"},
+ {ISNS_FUNC_ESI, "ESI"},
+ {ISNS_FUNC_HEARTBEAT, "Heartbeat"},
+
+/* Responses */
+ {ISNS_FUNC_RSP_DEVATTRREG, "DevAttrRegRsp"},
+ {ISNS_FUNC_RSP_DEVATTRQRY, "DevAttrQryRsp"},
+ {ISNS_FUNC_RSP_DEVGETNEXT, "DevGetNextRsp"},
+ {ISNS_FUNC_RSP_DEREGDEV, "DeregDevRsp"},
+ {ISNS_FUNC_RSP_SCNREG, "SCNRegRsp"},
+ {ISNS_FUNC_RSP_SCNDEREG, "SCNDeregRsp"},
+ {ISNS_FUNC_RSP_SCNEVENT, "SCNEventRsp"},
+ {ISNS_FUNC_RSP_SCN, "SCNRsp"},
+ {ISNS_FUNC_RSP_DDREG, "DDRegRsp"},
+ {ISNS_FUNC_RSP_DDDEREG, "DDDeregRsp"},
+ {ISNS_FUNC_RSP_DDSREG, "DDSRegRsp"},
+ {ISNS_FUNC_RSP_DDSDEREG, "DDSDeregRsp"},
+ {ISNS_FUNC_RSP_ESI, "ESIRsp"},
+
+ {0x0,NULL},
+};
+
+#define ISNS_ENTITY_PROTOCOL_NO_PROTOCOL 1
+#define ISNS_ENTITY_PROTOCOL_ISCSI 2
+#define ISNS_ENTITY_PROTOCOL_IFCP 3
+
+
+static const value_string isns_entity_protocol[] = {
+ {ISNS_ENTITY_PROTOCOL_NO_PROTOCOL, "No Protocol"},
+ {ISNS_ENTITY_PROTOCOL_ISCSI, "iSCSI"},
+ {ISNS_ENTITY_PROTOCOL_IFCP, "iFCP"},
+
+ {0x0,NULL},
+};
+
+static const value_string isns_errorcode[] = {
+ { 0,"No Error"},
+ { 1,"Unknown Error"},
+ { 2,"Message Format Error"},
+ { 3,"Invalid Registration"},
+ { 4,"Requested ESI Period Too short"},
+ { 5,"Invalid Query"},
+ { 6,"Authentication Unknown"},
+ { 7,"Authentication Absent"},
+ { 8,"Authentication Failed"},
+ { 9,"No such Entry"},
+ {10,"Version Not Supported"},
+ {11,"Internal Bus Error"},
+ {12,"Busy Now"},
+ {13,"Option Not Understood"},
+ {14,"Invalid Update"},
+ {15,"Message Not supported"},
+ {16,"SCN Event Rejected"},
+ {17,"SCN Registration Rejected"},
+ {18,"Attribute Not Implemented"},
+ {19,"SWITCH_ID Not available"},
+ {20,"SWITCH_ID not allocated"},
+ {21,"ESI Not Available"},
+
+ {0x0,NULL}
+};
+
+
+#define ISNS_ATTR_TAG_DELIMITER 0
+#define ISNS_ATTR_TAG_ENTITY_IDENTIFIER 1
+#define ISNS_ATTR_TAG_ENTITY_PROTOCOL 2
+#define ISNS_ATTR_TAG_MGMT_IP_ADDRESS 3
+#define ISNS_ATTR_TAG_TIMESTAMP 4
+#define ISNS_ATTR_TAG_PROTOCOL_VERSION_RANGE 5
+#define ISNS_ATTR_TAG_REGISTRATION_PERIOD 6
+#define ISNS_ATTR_TAG_ENTITY_INDEX 7
+#define ISNS_ATTR_TAG_ENTITY_NEXT_INDEX 8
+#define ISNS_ATTR_TAG_ENTITY_ISAKMP_PHASE_1 11
+#define ISNS_ATTR_TAG_ENTITY_CERTIFICATE 12
+#define ISNS_ATTR_TAG_PORTAL_IP_ADDRESS 16
+#define ISNS_ATTR_TAG_PORTAL_PORT 17
+#define ISNS_ATTR_TAG_PORTAL_SYMBOLIC_NAME 18
+#define ISNS_ATTR_TAG_ESI_INTERVAL 19
+#define ISNS_ATTR_TAG_ESI_PORT 20
+#define ISNS_ATTR_TAG_PORTAL_GROUP 21
+#define ISNS_ATTR_TAG_PORTAL_INDEX 22
+#define ISNS_ATTR_TAG_SCN_PORT 23
+#define ISNS_ATTR_TAG_PORTAL_NEXT_INDEX 24
+#define ISNS_ATTR_TAG_PORTAL_SECURITY_BITMAP 27
+#define ISNS_ATTR_TAG_PORTAL_ISAKMP_PHASE_1 28
+#define ISNS_ATTR_TAG_PORTAL_ISAKMP_PHASE_2 29
+#define ISNS_ATTR_TAG_PORTAL_CERTIFICATE 31
+#define ISNS_ATTR_TAG_ISCSI_NAME 32
+#define ISNS_ATTR_TAG_ISCSI_NODE_TYPE 33
+#define ISNS_ATTR_TAG_ISCSI_ALIAS 34
+#define ISNS_ATTR_TAG_ISCSI_SCN_BITMAP 35
+#define ISNS_ATTR_TAG_ISCSI_NODE_INDEX 36
+#define ISNS_ATTR_TAG_WWNN_TOKEN 37
+#define ISNS_ATTR_TAG_ISCSI_NODE_NEXT_INDEX 38
+#define ISNS_ATTR_TAG_ISCSI_AUTH_METHOD 42
+#define ISNS_ATTR_TAG_ISCSI_NODE_CERTIFICATE 43
+#define ISNS_ATTR_TAG_PG_PORTAL_IP_ADDR 49
+#define ISNS_ATTR_TAG_PG_PORTAL_PORT 50
+#define ISNS_ATTR_TAG_PORTAL_GROUP_TAG 51
+#define ISNS_ATTR_TAG_FC_PORT_NAME_WWPN 64
+#define ISNS_ATTR_TAG_PORT_ID 65
+#define ISNS_ATTR_TAG_FC_PORT_TYPE 66
+#define ISNS_ATTR_TAG_SYMBOLIC_PORT_NAME 67
+#define ISNS_ATTR_TAG_FABRIC_PORT_NAME 68
+#define ISNS_ATTR_TAG_HARD_ADDRESS 69
+#define ISNS_ATTR_TAG_PORT_IP_ADDRESS 70
+#define ISNS_ATTR_TAG_CLASS_OF_SERVICE 71
+#define ISNS_ATTR_TAG_FC4_TYPES 72
+#define ISNS_ATTR_TAG_FC4_DESCRIPTOR 73
+#define ISNS_ATTR_TAG_FC4_FEATURES 74
+#define ISNS_ATTR_TAG_IFCP_SCN_BITMAP 75
+#define ISNS_ATTR_TAG_PORT_ROLE 76
+#define ISNS_ATTR_TAG_PERMANENT_PORT_NAME 77
+#define ISNS_ATTR_TAG_PORT_CERTIFICATE 83
+#define ISNS_ATTR_TAG_FC4_TYPE_CODE 95
+#define ISNS_ATTR_TAG_FC_NODE_NAME_WWNN 96
+#define ISNS_ATTR_TAG_SYMBOLIC_NODE_NAME 97
+#define ISNS_ATTR_TAG_NODE_IP_ADDRESS 98
+#define ISNS_ATTR_TAG_NODE_IPA 99
+#define ISNS_ATTR_TAG_NODE_CERTIFICATE 100
+#define ISNS_ATTR_TAG_PROXY_ISCSI_NAME 101
+#define ISNS_ATTR_TAG_SWITCH_NAME 128
+#define ISNS_ATTR_TAG_PREFERRED_ID 129
+#define ISNS_ATTR_TAG_ASSIGNED_ID 130
+#define ISNS_ATTR_TAG_VIRTUAL_FABRIC_ID 131
+#define ISNS_ATTR_TAG_VENDOR_OUI 256
+#define ISNS_ATTR_TAG_DD_SET_ID 2049
+#define ISNS_ATTR_TAG_DD_SET_SYMBOLIC_NAME 2050
+#define ISNS_ATTR_TAG_DD_SET_STATUS 2051
+#define ISNS_ATTR_TAG_DD_SET_NEXT_ID 2052
+#define ISNS_ATTR_TAG_DD_ID 2065
+#define ISNS_ATTR_TAG_DD_SYMBOLIC_NAME 2066
+#define ISNS_ATTR_TAG_DD_MEMBER_ISCSI_INDEX 2067
+#define ISNS_ATTR_TAG_DD_MEMBER_ISCSI_NAME 2068
+#define ISNS_ATTR_TAG_DD_MEMBER_IFCP_NODE 2069
+#define ISNS_ATTR_TAG_DD_MEMBER_PORTAL_INDEX 2070
+#define ISNS_ATTR_TAG_DD_MEMBER_PORTAL_IP_ADDRESS 2071
+#define ISNS_ATTR_TAG_DD_MEMBER_PORTAL_PORT 2072
+#define ISNS_ATTR_TAG_DD_FEATURES 2078
+#define ISNS_ATTR_TAG_DD_ID_NEXT_ID 2079
+
+
+static const value_string isns_attribute_tags[] = {
+ {ISNS_ATTR_TAG_DELIMITER, "Delimiter"},
+ {ISNS_ATTR_TAG_ENTITY_IDENTIFIER, "Entity Identifier (EID)"},
+ {ISNS_ATTR_TAG_ENTITY_PROTOCOL, "Entity Protocol"},
+ {ISNS_ATTR_TAG_MGMT_IP_ADDRESS, "Management IP Address"},
+ {ISNS_ATTR_TAG_TIMESTAMP, "Timestamp"},
+ {ISNS_ATTR_TAG_PROTOCOL_VERSION_RANGE, "Protocol Version Range"},
+ {ISNS_ATTR_TAG_REGISTRATION_PERIOD, "Registration Period"},
+ {ISNS_ATTR_TAG_ENTITY_INDEX, "Entity Index"},
+ {ISNS_ATTR_TAG_ENTITY_NEXT_INDEX, "Entity Next Index"},
+ {ISNS_ATTR_TAG_ENTITY_ISAKMP_PHASE_1, "Entity ISAKMP Phase-1"},
+ {ISNS_ATTR_TAG_ENTITY_CERTIFICATE, "Entity Certificate"},
+ {ISNS_ATTR_TAG_PORTAL_IP_ADDRESS, "Portal IP Address"},
+ {ISNS_ATTR_TAG_PORTAL_PORT, "Portal TCP/UDP Port"},
+ {ISNS_ATTR_TAG_PORTAL_SYMBOLIC_NAME, "Portal Symbolic Name"},
+ {ISNS_ATTR_TAG_ESI_INTERVAL, "ESI Interval"},
+ {ISNS_ATTR_TAG_ESI_PORT, "ESI Port"},
+ {ISNS_ATTR_TAG_PORTAL_GROUP, "Portal Group Tag"},
+ {ISNS_ATTR_TAG_PORTAL_INDEX, "Portal Index"},
+ {ISNS_ATTR_TAG_SCN_PORT, "SCN Port"},
+ {ISNS_ATTR_TAG_PORTAL_NEXT_INDEX, "Portal Next Index"},
+ {ISNS_ATTR_TAG_PORTAL_SECURITY_BITMAP, "Portal Security Bitmap"},
+ {ISNS_ATTR_TAG_PORTAL_ISAKMP_PHASE_1, "Portal ISAKMP Phase-1"},
+ {ISNS_ATTR_TAG_PORTAL_ISAKMP_PHASE_2, "Portal ISAKMP Phase-2"},
+ {ISNS_ATTR_TAG_PORTAL_CERTIFICATE, "Portal Certificate"},
+ {ISNS_ATTR_TAG_ISCSI_NAME, "iSCSI Name"},
+ {ISNS_ATTR_TAG_ISCSI_NODE_TYPE, "iSCSI Node Type"},
+ {ISNS_ATTR_TAG_ISCSI_ALIAS, "iSCSI Alias"},
+ {ISNS_ATTR_TAG_ISCSI_SCN_BITMAP, "iSCSI SCN Bitmap"},
+ {ISNS_ATTR_TAG_ISCSI_NODE_INDEX, "iSCSI Node Index"},
+ {ISNS_ATTR_TAG_WWNN_TOKEN, "WWNN Token"},
+ {ISNS_ATTR_TAG_ISCSI_NODE_NEXT_INDEX, "iSCSI Node Next Index"},
+ {ISNS_ATTR_TAG_ISCSI_AUTH_METHOD, "iSCSI AuthMethod"},
+ {ISNS_ATTR_TAG_ISCSI_NODE_CERTIFICATE, "iSCSI Node Certificate"},
+ {ISNS_ATTR_TAG_PG_PORTAL_IP_ADDR, "PG Portal IP Addr"},
+ {ISNS_ATTR_TAG_PG_PORTAL_PORT, "PG Portal Port"},
+ {ISNS_ATTR_TAG_PORTAL_GROUP_TAG, "Portal Group Tag"},
+ {ISNS_ATTR_TAG_FC_PORT_NAME_WWPN, "FC Port Name WWPN"},
+ {ISNS_ATTR_TAG_PORT_ID, "Port ID"},
+ {ISNS_ATTR_TAG_FC_PORT_TYPE, "FC Port Type"},
+ {ISNS_ATTR_TAG_SYMBOLIC_PORT_NAME, "Symbolic Port Name"},
+ {ISNS_ATTR_TAG_FABRIC_PORT_NAME, "Fabric Port Name"},
+ {ISNS_ATTR_TAG_HARD_ADDRESS, "Hard Address"},
+ {ISNS_ATTR_TAG_PORT_IP_ADDRESS, "Port IP-Address"},
+ {ISNS_ATTR_TAG_CLASS_OF_SERVICE, "Class of Service"},
+ {ISNS_ATTR_TAG_FC4_TYPES, "FC-4 Types"},
+ {ISNS_ATTR_TAG_FC4_DESCRIPTOR, "FC-4 Descriptor"},
+ {ISNS_ATTR_TAG_FC4_FEATURES, "FC-4 Features"},
+ {ISNS_ATTR_TAG_IFCP_SCN_BITMAP, "iFCP SCN bitmap"},
+ {ISNS_ATTR_TAG_PORT_ROLE, "Port Role"},
+ {ISNS_ATTR_TAG_PERMANENT_PORT_NAME, "Permanent Port Name"},
+ {ISNS_ATTR_TAG_PORT_CERTIFICATE, "Port Certificate"},
+ {ISNS_ATTR_TAG_FC4_TYPE_CODE, "FC-4 Type Code"},
+ {ISNS_ATTR_TAG_FC_NODE_NAME_WWNN, "FC Node Name WWNN"},
+ {ISNS_ATTR_TAG_SYMBOLIC_NODE_NAME, "Symbolic Node Name"},
+ {ISNS_ATTR_TAG_NODE_IP_ADDRESS, "Node IP-Address"},
+ {ISNS_ATTR_TAG_NODE_IPA, "Node IPA"},
+ {ISNS_ATTR_TAG_NODE_CERTIFICATE, "Node Certificate"},
+ {ISNS_ATTR_TAG_PROXY_ISCSI_NAME, "Proxy iSCSI Name"},
+ {ISNS_ATTR_TAG_SWITCH_NAME, "Switch Name"},
+ {ISNS_ATTR_TAG_PREFERRED_ID, "Preferred ID"},
+ {ISNS_ATTR_TAG_ASSIGNED_ID, "Assigned ID"},
+ {ISNS_ATTR_TAG_VIRTUAL_FABRIC_ID, "Virtual_Fabric_ID"},
+ {ISNS_ATTR_TAG_VENDOR_OUI, "iSNS Server Vendor OUI"},
+ {ISNS_ATTR_TAG_DD_SET_ID, "DD_Set ID"},
+ {ISNS_ATTR_TAG_DD_SET_SYMBOLIC_NAME, "DD_Set Sym Name"},
+ {ISNS_ATTR_TAG_DD_SET_STATUS, "DD_Set Status"},
+ {ISNS_ATTR_TAG_DD_SET_NEXT_ID, "DD_Set_Next_ID"},
+ {ISNS_ATTR_TAG_DD_ID, "DD_ID"},
+ {ISNS_ATTR_TAG_DD_SYMBOLIC_NAME, "DD_Symbolic Name"},
+ {ISNS_ATTR_TAG_DD_MEMBER_ISCSI_INDEX, "DD_Member iSCSI Index"},
+ {ISNS_ATTR_TAG_DD_MEMBER_ISCSI_NAME, "DD_Member iSCSI Name"},
+ {ISNS_ATTR_TAG_DD_MEMBER_IFCP_NODE, "DD_Member iFCP Node"},
+ {ISNS_ATTR_TAG_DD_MEMBER_PORTAL_INDEX, "DD Member Portal Index"},
+ {ISNS_ATTR_TAG_DD_MEMBER_PORTAL_IP_ADDRESS, "DD_Member Portal IP Addr"},
+ {ISNS_ATTR_TAG_DD_MEMBER_PORTAL_PORT, "DD Member Portal TCP/UDP"},
+ {ISNS_ATTR_TAG_DD_FEATURES, "DD_Features"},
+ {ISNS_ATTR_TAG_DD_ID_NEXT_ID, "DD_ID Next ID"},
+
+ {0,NULL}
+};
+
+
+/* iSNS flags */
+#define ISNS_FLAGS_CLIENT 0x8000
+#define ISNS_FLAGS_SERVER 0x4000
+#define ISNS_FLAGS_AUTH 0x2000
+#define ISNS_FLAGS_REPLACE 0x1000
+#define ISNS_FLAGS_LAST_PDU 0x0800
+#define ISNS_FLAGS_FIRST_PDU 0x0400
+
+
+static const true_false_string isns_scn_bitmap_initiator_and_self_information_only = {
+ "True",
+ "False"
+};
+static const true_false_string isns_scn_bitmap_target_and_self_information_only = {
+ "True",
+ "False"
+};
+static const true_false_string isns_scn_bitmap_management_registration_scn = {
+ "True",
+ "False"
+};
+static const true_false_string isns_scn_bitmap_object_removed = {
+ "True",
+ "False"
+};
+static const true_false_string isns_scn_bitmap_object_added = {
+ "True",
+ "False"
+};
+static const true_false_string isns_scn_bitmap_object_updated = {
+ "True",
+ "False"
+};
+static const true_false_string isns_scn_bitmap_dd_dds_member_removed = {
+ "True",
+ "False"
+};
+static const true_false_string isns_scn_bitmap_dd_dds_member_added = {
+ "True",
+ "False"
+};
+
+static const true_false_string isns_psb_tunnel_mode = {
+ "Preferred",
+ "No Preference"
+};
+static const true_false_string isns_psb_transport_mode = {
+ "Preferred",
+ "No Preference"
+};
+static const true_false_string isns_psb_pfs = {
+ "Enabled",
+ "Disabled"
+};
+static const true_false_string isns_psb_aggressive_mode = {
+ "Enabled",
+ "Disabled"
+};
+static const true_false_string isns_psb_main_mode = {
+ "Enabled",
+ "Disabled"
+};
+static const true_false_string isns_psb_ike_ipsec = {
+ "Enabled",
+ "Disabled"
+};
+static const true_false_string isns_psb_bitmap = {
+ "VALID",
+ "INVALID"
+};
+
+static const true_false_string isns_isnt_control = {
+ "Yes",
+ "No"
+};
+static const true_false_string isns_isnt_initiator = {
+ "Yes",
+ "No"
+};
+static const true_false_string isns_isnt_target = {
+ "Yes",
+ "No"
+};
+
+static const true_false_string isns_port_type = {
+ "UDP",
+ "TCP"
+};
+
+static const true_false_string isns_flag_first_pdu = {
+ "First PDU of iSNS Message",
+ "Not the first PDU of iSNS Message"
+};
+
+static const true_false_string isns_flag_last_pdu = {
+ "Last PDU of iSNS Message",
+ "Not the Last PDU of iSNS Message"
+};
+
+static const true_false_string isns_flag_replace = {
+ "Replace",
+ "Don't replace"
+};
+
+static const true_false_string isns_flag_auth = {
+ "Authentication Block is PRESENT",
+ "No authentication block"
+};
+
+static const true_false_string isns_flag_server = {
+ "Sender is iSNS server",
+ "Sender is not iSNS server"
+};
+
+static const true_false_string isns_flag_client = {
+ "Sender is iSNS client",
+ "Sender is not iSNS client"
+};
+
+
+/* Initialize the subtree pointers */
+static gint ett_isns = -1;
+
+
+/* Code to actually dissect the packets */
+static void
+dissect_isns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint offset = 0;
+ guint16 function_id;
+ guint16 isns_protocol_version;
+ guint32 packet_len = tvb_length_remaining(tvb, offset);
+ char * function_id_str;
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti = NULL;
+ proto_tree *isns_tree = NULL;
+
+ if( packet_len < 12 )
+ return;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "isns");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* Get the function id from the packet */
+ function_id = tvb_get_ntohs(tvb, offset + 2);
+ function_id_str = match_strval(function_id, isns_function_ids);
+
+ /* Get the protocol version - only version one at the moment*/
+ isns_protocol_version = tvb_get_ntohs(tvb, offset + 0);
+ if( (function_id_str == NULL) || (isns_protocol_version != ISNS_PROTO_VER) )
+ return;
+
+ /* Add the function name in the info col */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, function_id_str);
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items.
+ */
+ if (tree) {
+ guint16 b;
+ guint16 flags;
+ proto_tree *tt;
+ proto_item *tflags;
+ proto_item *tpayload;
+
+ /* NOTE: The offset and length values in the call to
+ * "proto_tree_add_item()" define what data bytes to highlight in the hex
+ * display window when the line in the protocol tree display
+ * corresponding to that item is selected.
+ * tvb_length(tvb) is a handy way to highlight all data from the offset to
+ * the end of the packet.
+ */
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_isns, tvb, 0, -1, FALSE);
+ isns_tree = proto_item_add_subtree(ti, ett_isns);
+
+ /* OK... Sort out the header */
+ b = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(isns_tree, hf_isns_version, tvb, offset, 2, b);
+
+ b = tvb_get_ntohs(tvb, offset + 2);
+ proto_tree_add_uint(isns_tree, hf_isns_function_id, tvb, offset+2, 2, b);
+
+ b = tvb_get_ntohs(tvb, offset + 4);
+ proto_tree_add_uint(isns_tree, hf_isns_pdu_length, tvb, offset+4, 2, b);
+
+ /*FLAGS*/
+ flags = tvb_get_ntohs(tvb, offset + 6);
+ tflags = proto_tree_add_uint(isns_tree, hf_isns_flags, tvb, offset+6, 2, flags);
+ tt = proto_item_add_subtree(tflags, ett_isns_flags);
+
+ proto_tree_add_boolean(tt, hf_isns_client, tvb, offset+6, 2, flags);
+ proto_tree_add_boolean(tt, hf_isns_server, tvb, offset+6, 2, flags);
+ proto_tree_add_boolean(tt, hf_isns_auth, tvb, offset+6, 2, flags);
+ proto_tree_add_boolean(tt, hf_isns_replace, tvb, offset+6, 2, flags);
+ proto_tree_add_boolean(tt, hf_isns_last_pdu, tvb, offset+6, 2, flags);
+ proto_tree_add_boolean(tt, hf_isns_first_pdu, tvb, offset+6, 2, flags);
+
+ b = tvb_get_ntohs(tvb, offset + 8);
+ proto_tree_add_uint(isns_tree, hf_isns_transaction_id, tvb, offset+8, 2, b);
+
+ b = tvb_get_ntohs(tvb, offset + 10);
+ proto_tree_add_uint(isns_tree, hf_isns_sequence_id, tvb, offset+10, 2, b);
+
+ tpayload = proto_tree_add_item(isns_tree, hf_isns_payload, tvb, offset+12, packet_len - 12 , FALSE);
+ tt = proto_item_add_subtree(tpayload, ett_isns_payload);
+
+ /* Now set the offset to the start of the payload */
+ offset += ISNS_HEADER_SIZE;
+
+ /* Decode those attributes baby - Yeah!*/
+ switch (function_id)
+ {
+ case ISNS_FUNC_HEARTBEAT:
+ {
+ guint8 hb_ipv6[16];
+ guint16 port;
+ guint32 c;
+ tvb_memcpy(tvb,hb_ipv6,offset,16);
+ proto_tree_add_ipv6(tt,hf_isns_heartbeat_ipv6_addr, tvb, offset, 16, hb_ipv6);
+ offset += 16;
+
+ port = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tt,hf_isns_heartbeat_tcp_port, tvb, offset, 2, port);
+ offset += 2;
+
+ port = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tt,hf_isns_heartbeat_udp_port, tvb, offset, 2, port);
+ offset += 2;
+
+ c = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tt,hf_isns_heartbeat_interval, tvb, offset, 4, c);
+ offset += 4;
+
+ c = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tt,hf_isns_heartbeat_counter, tvb, offset, 4, c);
+ offset += 4;
+ break;
+ }
+ /* Responses */
+ case ISNS_FUNC_RSP_DEVATTRREG:
+ case ISNS_FUNC_RSP_DEVATTRQRY:
+ case ISNS_FUNC_RSP_DEVGETNEXT:
+ case ISNS_FUNC_RSP_DEREGDEV:
+ case ISNS_FUNC_RSP_SCNREG:
+ case ISNS_FUNC_RSP_SCNDEREG:
+ case ISNS_FUNC_RSP_SCNEVENT:
+ case ISNS_FUNC_RSP_SCN:
+ case ISNS_FUNC_RSP_DDREG:
+ case ISNS_FUNC_RSP_DDDEREG:
+ case ISNS_FUNC_RSP_DDSREG:
+ case ISNS_FUNC_RSP_DDSDEREG:
+ case ISNS_FUNC_RSP_ESI:
+ {
+ /* Get the Error message of the response */
+ guint32 errorcode = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tt,hf_isns_resp_errorcode, tvb, offset, 4, errorcode);
+ offset += 4;
+ /* Messages */
+ }
+ case ISNS_FUNC_DEVATTRREG:
+ case ISNS_FUNC_DEVATTRQRY:
+ case ISNS_FUNC_DEVGETNEXT:
+ case ISNS_FUNC_DEREGDEV:
+ case ISNS_FUNC_SCNREG:
+ case ISNS_FUNC_SCNDEREG:
+ case ISNS_FUNC_SCNEVENT:
+ case ISNS_FUNC_SCN:
+ case ISNS_FUNC_DDREG:
+ case ISNS_FUNC_DDDEREG:
+ case ISNS_FUNC_DDSREG:
+ case ISNS_FUNC_DDSDEREG:
+ case ISNS_FUNC_ESI:
+ default:
+ /* we can only look at the attributes for the first PDU */
+ if(!(flags&ISNS_FLAGS_FIRST_PDU)){
+ proto_tree_add_text(tt, tvb, offset, packet_len-offset, "This is not the first PDU. The attributes are not decoded");
+ return;
+ }
+
+ while( offset < packet_len )
+ {
+ offset = AddAttribute(pinfo, tvb, tt, offset, function_id);
+ }
+ }
+ }
+
+ return;
+}
+
+static guint
+get_isns_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint16 isns_len;
+
+ isns_len = tvb_get_ntohs(tvb, offset+4);
+ return (isns_len+12);
+}
+
+static void
+dissect_isns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Make entries in Protocol column and Info column on summary display*/
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "isns");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tcp_dissect_pdus(tvb, pinfo, tree, isns_desegment, 12, get_isns_pdu_len,
+ dissect_isns_pdu);
+
+
+}
+
+static void
+dissect_isns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Make entries in Protocol column and Info column on summary display*/
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "isns");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ dissect_isns_pdu(tvb, pinfo, tree);
+}
+
+
+static guint
+dissect_isns_attr_ip_address(tvbuff_t *tvb, guint offset, proto_tree *parent_tree, int hf_index, guint32 tag, guint32 len)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ if(parent_tree){
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset + 8, len, FALSE);
+ tree = proto_item_add_subtree(item, ett_isns_attribute);
+ }
+
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+
+ return offset+8+len;
+}
+
+static guint
+dissect_isns_attr_string(tvbuff_t *tvb, guint offset, proto_tree *parent_tree, int hf_index, guint32 tag, guint32 len)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ if(parent_tree){
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset + 8, len, FALSE);
+ tree = proto_item_add_subtree(item, ett_isns_attribute);
+ }
+
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+
+ return offset+8+len;
+}
+
+static guint
+dissect_isns_attr_integer(tvbuff_t *tvb, guint offset, proto_tree *parent_tree, int hf_index, guint32 tag, guint32 len, guint16 function_id)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ /*
+ * 5.6.5.1
+ * in a DevAttrReg , the PGT (tag 51) may be sent as 0 length
+ * which then means that we wish to register the portal group tag
+ * as NULL.
+ * (At least) some servers will respond with PGT as a 0 length
+ * value in these instances in the DevAttrRegRsp (eventhough I can
+ * not find this mentioned in the standard) so allow it for the
+ * response as well.
+ */
+ if(len){
+ if(parent_tree){
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset + 8, len, FALSE);
+ tree = proto_item_add_subtree(item, ett_isns_attribute);
+ }
+ } else if((tag==ISNS_ATTR_TAG_PORTAL_GROUP_TAG)&&((function_id==ISNS_FUNC_DEVATTRREG)||(function_id==ISNS_FUNC_RSP_DEVATTRREG))){
+ /* 5.6.5.1 */
+ if(parent_tree){
+ item=proto_tree_add_uint_format(parent_tree, hf_isns_portal_group_tag, tvb, offset, 8, 0, "PG Tag: <NULL>");
+ tree = proto_item_add_subtree(item, ett_isns_attribute);
+ }
+ } else {
+ if(parent_tree){
+ item=proto_tree_add_text(parent_tree, tvb, offset, 8, "Oops, you surprised me here. a 0 byte integer.");
+ tree = proto_item_add_subtree(item, ett_isns_attribute);
+ }
+ }
+
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+
+ return offset+8+len;
+}
+
+static guint
+dissect_isns_attr_port(tvbuff_t *tvb, guint offset, proto_tree *parent_tree, int hf_index, guint32 tag, guint32 len,
+ guint16 port_type, packet_info *pinfo)
+{
+ proto_item *tree=NULL;
+ proto_item *item=NULL;
+ guint16 port = tvb_get_ntohs(tvb, offset + 10);
+ guint16 isudp = tvb_get_ntohs(tvb, offset + 8)&0x01;
+ conversation_t *conversation;
+
+ if(parent_tree){
+ item = proto_tree_add_uint(parent_tree, hf_index, tvb, offset+8, 4, port);
+ tree = proto_item_add_subtree(item, ett_isns_port);
+ }
+
+ proto_tree_add_boolean(tree, hf_isns_port_type, tvb, offset+8, 2, isudp);
+
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+
+ if ((port_type == ISNS_ESI_PORT) || (port_type == ISNS_SCN_PORT)) {
+ if (isudp) {
+ conversation = find_conversation (&pinfo->src, &pinfo->dst, PT_UDP,
+ port, 0, NO_PORT_B);
+ if (conversation == NULL) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ PT_UDP, port, 0, NO_PORT2_FORCE);
+ conversation_set_dissector (conversation, isns_udp_handle);
+ }
+ }
+ else {
+ conversation = find_conversation (&pinfo->src, &pinfo->dst, PT_TCP,
+ port, 0, NO_PORT_B);
+ if (conversation == NULL) {
+ conversation = conversation_new (&pinfo->src, &pinfo->dst,
+ PT_TCP, port, 0, NO_PORT2_FORCE);
+ conversation_set_dissector (conversation, isns_tcp_handle);
+ }
+ }
+ }
+
+ return offset+8+len;
+}
+
+static guint
+dissect_isns_attr_none(tvbuff_t *tvb, guint offset, proto_tree *parent_tree, int hf_index, guint32 tag, guint32 len)
+{
+ proto_item *tree=NULL;
+ proto_item *item=NULL;
+
+ if(parent_tree){
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset, 8, FALSE);
+ tree = proto_item_add_subtree(item, ett_isns_port);
+ }
+
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+
+ return offset+8+len;
+}
+
+static guint
+dissect_isns_attr_not_decoded_yet(tvbuff_t *tvb, guint offset, proto_tree *parent_tree, int hf_index, guint32 tag, guint32 len)
+{
+ proto_item *tree=NULL;
+ proto_item *item=NULL;
+
+ if(parent_tree){
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset + 8, len, FALSE);
+ tree = proto_item_add_subtree(item, ett_isns_port);
+ }
+
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+
+ return offset+8+len;
+}
+
+static guint
+dissect_isns_attr_iscsi_node_type(tvbuff_t *tvb, guint offset, proto_tree *parent_tree, int hf_index, guint32 tag, guint32 len)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ guint32 node_type=tvb_get_ntohl(tvb, offset + 8);
+
+ if(parent_tree){
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset + 8, len, FALSE);
+ tree = proto_item_add_subtree(item, ett_isns_attribute);
+ }
+
+ proto_tree_add_boolean(tree, hf_isns_isnt_control, tvb, offset+8, 4, node_type);
+ if(node_type&0x00000004){
+ proto_item_append_text(item, " Control");
+ }
+ proto_tree_add_boolean(tree, hf_isns_isnt_initiator, tvb, offset+8, 4, node_type);
+ if(node_type&0x00000002){
+ proto_item_append_text(item, " Initiator");
+ }
+ proto_tree_add_boolean(tree, hf_isns_isnt_target, tvb, offset+8, 4, node_type);
+ if(node_type&0x00000001){
+ proto_item_append_text(item, " Target");
+ }
+
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+
+ return offset+8+len;
+}
+
+
+
+static guint
+dissect_isns_attr_portal_security_bitmap(tvbuff_t *tvb, guint offset, proto_tree *parent_tree, int hf_index, guint32 tag, guint32 len)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ guint32 psb=tvb_get_ntohl(tvb, offset + 8);
+
+ if(parent_tree){
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset + 8, len, FALSE);
+ tree = proto_item_add_subtree(item, ett_isns_attribute);
+ }
+
+ proto_tree_add_boolean(tree, hf_isns_psb_tunnel_mode, tvb, offset+8, 4, psb);
+ proto_tree_add_boolean(tree, hf_isns_psb_transport_mode, tvb, offset+8, 4, psb);
+ proto_tree_add_boolean(tree, hf_isns_psb_pfs, tvb, offset+8, 4, psb);
+ proto_tree_add_boolean(tree, hf_isns_psb_aggressive_mode, tvb, offset+8, 4, psb);
+ proto_tree_add_boolean(tree, hf_isns_psb_main_mode, tvb, offset+8, 4, psb);
+ proto_tree_add_boolean(tree, hf_isns_psb_ike_ipsec, tvb, offset+8, 4, psb);
+ proto_tree_add_boolean(tree, hf_isns_psb_bitmap, tvb, offset+8, 4, psb);
+
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+
+ return offset+8+len;
+}
+
+
+
+static guint
+dissect_isns_attr_scn_bitmap(tvbuff_t *tvb, guint offset, proto_tree *parent_tree, int hf_index, guint32 tag, guint32 len)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ guint32 scn_bitmap=tvb_get_ntohl(tvb, offset + 8);
+
+ if(parent_tree){
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset + 8, len, FALSE);
+ tree = proto_item_add_subtree(item, ett_isns_attribute);
+ }
+
+
+ /*
+ 24 INITIATOR AND SELF INFORMATION ONLY
+ 25 TARGET AND SELF INFORMATION ONLY
+ 26 MANAGEMENT REGISTRATION/SCN
+ 27 OBJECT REMOVED
+ 28 OBJECT ADDED
+ 29 OBJECT UPDATED
+ 30 DD/DDS MEMBER REMOVED (Mgmt Reg/SCN only)
+ 31 (Lsb) DD/DDS MEMBER ADDED (Mgmt Reg/SCN only)
+ */
+ proto_tree_add_boolean(tree, hf_isns_scn_bitmap_initiator_and_self_information_only, tvb, offset+8, 4, scn_bitmap);
+ proto_tree_add_boolean(tree, hf_isns_scn_bitmap_target_and_self_information_only, tvb, offset+8, 4, scn_bitmap);
+ proto_tree_add_boolean(tree, hf_isns_scn_bitmap_management_registration_scn, tvb, offset+8, 4, scn_bitmap);
+ proto_tree_add_boolean(tree, hf_isns_scn_bitmap_object_removed, tvb, offset+8, 4, scn_bitmap);
+ proto_tree_add_boolean(tree, hf_isns_scn_bitmap_object_added, tvb, offset+8, 4, scn_bitmap);
+ proto_tree_add_boolean(tree, hf_isns_scn_bitmap_object_updated, tvb, offset+8, 4, scn_bitmap);
+ proto_tree_add_boolean(tree, hf_isns_scn_bitmap_dd_dds_member_removed, tvb, offset+8, 4, scn_bitmap);
+ proto_tree_add_boolean(tree, hf_isns_scn_bitmap_dd_dds_member_added, tvb, offset+8, 4, scn_bitmap);
+
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+
+ return offset+8+len;
+}
+
+
+
+
+static guint
+AddAttribute(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, guint offset,
+ guint16 function_id)
+{
+ guint32 tag,len;
+
+
+ /* Get the Tag */
+ tag = tvb_get_ntohl(tvb, offset);
+
+ /* Now the Length */
+ len = tvb_get_ntohl(tvb, offset + 4);
+
+ if (!len) {
+ if (tree) {
+ proto_tree_add_uint(tree, hf_isns_attr_tag, tvb, offset, 4, tag);
+ proto_tree_add_uint(tree, hf_isns_attr_len, tvb, offset+4, 4, len);
+ }
+ return (offset+8);
+ }
+
+ switch( tag )
+ {
+ case ISNS_ATTR_TAG_DELIMITER:
+ offset = dissect_isns_attr_none(tvb, offset, tree, hf_isns_delimiter, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ENTITY_IDENTIFIER:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_entity_identifier, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ENTITY_PROTOCOL:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_entity_protocol, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_MGMT_IP_ADDRESS:
+ offset = dissect_isns_attr_ip_address(tvb, offset, tree, hf_isns_mgmt_ip_addr, tag, len);
+ break;
+ case ISNS_ATTR_TAG_TIMESTAMP:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_timestamp, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_PROTOCOL_VERSION_RANGE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_REGISTRATION_PERIOD:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_registration_period, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_ENTITY_INDEX:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_entity_index, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_ENTITY_NEXT_INDEX:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_entity_next_index, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_ENTITY_ISAKMP_PHASE_1:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ENTITY_CERTIFICATE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_IP_ADDRESS:
+ offset = dissect_isns_attr_ip_address(tvb, offset, tree, hf_isns_portal_ip_addr, tag, len);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_PORT:
+ offset = dissect_isns_attr_port(tvb, offset, tree, hf_isns_portal_port, tag, len, ISNS_OTHER_PORT, pinfo);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_SYMBOLIC_NAME:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_portal_symbolic_name, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ESI_INTERVAL:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_esi_interval, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_ESI_PORT:
+ offset = dissect_isns_attr_port(tvb, offset, tree, hf_isns_esi_port, tag, len, ISNS_ESI_PORT, pinfo);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_GROUP:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_INDEX:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_portal_index, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_SCN_PORT:
+ offset = dissect_isns_attr_port(tvb, offset, tree, hf_isns_scn_port, tag, len, ISNS_SCN_PORT, pinfo);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_NEXT_INDEX:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_portal_next_index, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_SECURITY_BITMAP:
+ offset = dissect_isns_attr_portal_security_bitmap(tvb, offset, tree, hf_isns_psb, tag, len);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_ISAKMP_PHASE_1:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_ISAKMP_PHASE_2:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_CERTIFICATE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ISCSI_NAME:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_iscsi_name, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ISCSI_NODE_TYPE:
+ offset = dissect_isns_attr_iscsi_node_type(tvb, offset, tree, hf_isns_iscsi_node_type, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ISCSI_ALIAS:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_iscsi_alias, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ISCSI_SCN_BITMAP:
+ offset = dissect_isns_attr_scn_bitmap(tvb, offset, tree, hf_isns_scn_bitmap, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ISCSI_NODE_INDEX:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_node_index, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_WWNN_TOKEN:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_wwnn_token, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_ISCSI_NODE_NEXT_INDEX:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_node_next_index, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_ISCSI_AUTH_METHOD:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_iscsi_auth_method, tag, len);
+ break;
+ case ISNS_ATTR_TAG_ISCSI_NODE_CERTIFICATE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_PG_PORTAL_IP_ADDR:
+ offset = dissect_isns_attr_ip_address(tvb, offset, tree, hf_isns_pg_portal_ip_addr, tag, len);
+ break;
+ case ISNS_ATTR_TAG_PG_PORTAL_PORT:
+ offset = dissect_isns_attr_port(tvb, offset, tree, hf_isns_pg_portal_port, tag, len, ISNS_OTHER_PORT, pinfo);
+ break;
+ case ISNS_ATTR_TAG_PORTAL_GROUP_TAG:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_portal_group_tag, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_FC_PORT_NAME_WWPN:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_fc_port_name_wwpn, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_PORT_ID:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_port_id, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_FC_PORT_TYPE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ /*
+ 0x0000 Unidentified/Null Entry
+ 0x0001 Fibre Channel N_Port
+ 0x0002 Fibre Channel NL_Port
+ 0x0003 Fibre Channel F/NL_Port
+ 0x0081 Fibre Channel F_Port
+ 0x0082 Fibre Channel FL_Port
+ 0x0084 Fibre Channel E_Port
+ 0xFF12 iFCP Port
+ */
+ case ISNS_ATTR_TAG_SYMBOLIC_PORT_NAME:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_symbolic_port_name, tag, len);
+ break;
+ case ISNS_ATTR_TAG_FABRIC_PORT_NAME:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_fabric_port_name, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_HARD_ADDRESS:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_hard_address, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_PORT_IP_ADDRESS:
+ offset = dissect_isns_attr_ip_address(tvb, offset, tree, hf_isns_port_ip_addr, tag, len);
+ break;
+ case ISNS_ATTR_TAG_CLASS_OF_SERVICE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ /*
+ bit 29 Fibre Channel Class 2 Supported
+ bit 28 Fibre Channel Class 3 Supported
+ */
+ case ISNS_ATTR_TAG_FC4_TYPES:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_FC4_DESCRIPTOR:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_fc4_descriptor, tag, len);
+ break;
+ case ISNS_ATTR_TAG_FC4_FEATURES:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_IFCP_SCN_BITMAP:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ /*
+ bit 24 INITIATOR AND SELF INFORMATION ONLY
+ bit 25 TARGET AND SELF INFORMATION ONLY
+ bit 26 MANAGEMENT REGISTRATION/SCN
+ bit 27 OBJECT REMOVED
+ bit 28 OBJECT ADDED
+ bit 29 OBJECT UPDATED
+ bit 30 DD/DDS MEMBER REMOVED (Mgmt Reg/SCN only)
+ bit 31 (Lsb) DD/DDS MEMBER ADDED (Mgmt Reg/SCN only)
+ */
+ case ISNS_ATTR_TAG_PORT_ROLE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ /*
+ bit 29 Control
+ bit 30 FCP Initiator
+ bit 31 (Lsb) FCP Target
+ */
+ case ISNS_ATTR_TAG_PERMANENT_PORT_NAME:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_permanent_port_name, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_PORT_CERTIFICATE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_FC4_TYPE_CODE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ /* 8bit type code in byte0 */
+ case ISNS_ATTR_TAG_FC_NODE_NAME_WWNN:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_fc_node_name_wwnn, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_SYMBOLIC_NODE_NAME:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_symbolic_node_name, tag, len);
+ break;
+ case ISNS_ATTR_TAG_NODE_IP_ADDRESS:
+ offset = dissect_isns_attr_ip_address(tvb, offset, tree, hf_isns_node_ip_addr, tag, len);
+ break;
+ case ISNS_ATTR_TAG_NODE_IPA:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_node_ipa, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_NODE_CERTIFICATE:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_PROXY_ISCSI_NAME:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_proxy_iscsi_name, tag, len);
+ break;
+ case ISNS_ATTR_TAG_SWITCH_NAME:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_switch_name, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_PREFERRED_ID:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_preferred_id, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_ASSIGNED_ID:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_assigned_id, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_VIRTUAL_FABRIC_ID:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_virtual_fabric_id, tag, len);
+ break;
+ case ISNS_ATTR_TAG_VENDOR_OUI:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_vendor_oui, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_DD_SET_ID:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_dd_set_id, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_DD_SET_SYMBOLIC_NAME:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_dd_set_symbolic_name, tag, len);
+ break;
+ case ISNS_ATTR_TAG_DD_SET_STATUS:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_DD_SET_NEXT_ID:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_dd_set_next_id, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_DD_ID:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_dd_id, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_DD_SYMBOLIC_NAME:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_dd_symbolic_name, tag, len);
+ break;
+ case ISNS_ATTR_TAG_DD_MEMBER_ISCSI_INDEX:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_member_iscsi_index, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_DD_MEMBER_ISCSI_NAME:
+ offset = dissect_isns_attr_string(tvb, offset, tree, hf_isns_dd_member_iscsi_name, tag, len);
+ break;
+ case ISNS_ATTR_TAG_DD_MEMBER_IFCP_NODE:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_member_ifcp_node, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_DD_MEMBER_PORTAL_INDEX:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_member_portal_index, tag, len, function_id);
+ break;
+ case ISNS_ATTR_TAG_DD_MEMBER_PORTAL_IP_ADDRESS:
+ offset = dissect_isns_attr_ip_address(tvb, offset, tree, hf_isns_dd_member_portal_ip_addr, tag, len);
+ break;
+ case ISNS_ATTR_TAG_DD_MEMBER_PORTAL_PORT:
+ offset = dissect_isns_attr_port(tvb, offset, tree, hf_isns_dd_member_portal_port,
+ tag, len, ISNS_OTHER_PORT, pinfo);
+ break;
+ case ISNS_ATTR_TAG_DD_FEATURES:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ break;
+ case ISNS_ATTR_TAG_DD_ID_NEXT_ID:
+ offset = dissect_isns_attr_integer(tvb, offset, tree, hf_isns_dd_id_next_id, tag, len, function_id);
+ break;
+ default:
+ offset = dissect_isns_attr_not_decoded_yet(tvb, offset, tree, hf_isns_not_decoded_yet, tag, len);
+ }
+
+
+ /* move on the offset to next attribute */
+
+ return offset;
+}
+
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void proto_register_isns(void)
+{
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ /* The Header Stuff */
+ { &hf_isns_version,
+ { "iSNSP Version","isns.PVer",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "iSNS Protocol Version" ,HFILL}
+ },
+ { &hf_isns_function_id,
+ { "Function ID","isns.functionid",
+ FT_UINT16, BASE_DEC,VALS(&isns_function_ids),0,
+ "iSNS Function ID" ,HFILL}
+ },
+ { &hf_isns_pdu_length,
+ { "PDU Length","isns.pdulength",
+ FT_UINT16, BASE_DEC,NULL,0,
+ "iSNS PDU Length" ,HFILL}
+ },
+
+ { &hf_isns_flags,
+ { "Flags","isns.flags",
+ FT_UINT16, BASE_HEX,NULL,0,
+ "iSNS Flags" ,HFILL}
+ },
+ { &hf_isns_client,
+ { "Client ","isns.flags.client",
+ FT_BOOLEAN, 16, TFS(&isns_flag_client), ISNS_FLAGS_CLIENT,
+ "iSNS Client" ,HFILL}
+ },
+ { &hf_isns_server,
+ { "Server ","isns.flags.server",
+ FT_BOOLEAN, 16, TFS(&isns_flag_server), ISNS_FLAGS_SERVER,
+ "iSNS Server" ,HFILL}
+ },
+ { &hf_isns_auth,
+ { "Auth ","isns.flags.authentication_block",
+ FT_BOOLEAN, 16, TFS(&isns_flag_auth), ISNS_FLAGS_AUTH,
+ "is iSNS Authentication Block present?" ,HFILL}
+ },
+ { &hf_isns_replace,
+ { "Replace ","isns.flags.replace",
+ FT_BOOLEAN, 16, TFS(&isns_flag_replace), ISNS_FLAGS_REPLACE,
+ "iSNS Replace" ,HFILL}
+ },
+ { &hf_isns_last_pdu,
+ { "Last PDU ","isns.flags.lastpdu",
+ FT_BOOLEAN, 16, TFS(&isns_flag_last_pdu), ISNS_FLAGS_LAST_PDU,
+ "iSNS Last PDU" ,HFILL}
+ },
+ { &hf_isns_first_pdu,
+ { "First PDU ","isns.flags.firstpdu",
+ FT_BOOLEAN, 16, TFS(&isns_flag_first_pdu), ISNS_FLAGS_FIRST_PDU,
+ "iSNS First PDU",HFILL }
+ },
+
+
+ { &hf_isns_transaction_id,
+ { "Transaction ID","isns.transactionid",
+ FT_UINT16, BASE_DEC,NULL,0,
+ "iSNS transaction ID" ,HFILL}
+ },
+ { &hf_isns_sequence_id,
+ { "Sequence ID","isns.sequenceid",
+ FT_UINT16, BASE_DEC,NULL,0,
+ "iSNS sequence ID" ,HFILL}
+ },
+
+ { &hf_isns_entity_protocol,
+ { "Entity Protocol","isns.entity_protocol",
+ FT_UINT32, BASE_DEC,VALS(isns_entity_protocol),0,
+ "iSNS Entity Protocol" ,HFILL}
+ },
+ /* The Payload stuff */
+
+ { &hf_isns_dd_member_portal_port,
+ { "DD Member Portal Port","isns.dd_member_portal_port",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "TCP/UDP DD Member Portal Port", HFILL }
+ },
+
+ { &hf_isns_iscsi_node_type,
+ { "iSCSI Node Type","isns.iscsi.node_type",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "iSCSI Node Type", HFILL }
+ },
+
+ { &hf_isns_esi_port,
+ { "ESI Port","isns.esi_port",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "TCP/UDP ESI Port", HFILL }
+ },
+
+ { &hf_isns_scn_port,
+ { "SCN Port","isns.scn_port",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "TCP/UDP SCN Port", HFILL }
+ },
+
+ { &hf_isns_portal_port,
+ { "Portal Port","isns.portal_port",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "TCP/UDP Portal Port", HFILL }
+ },
+
+ { &hf_isns_pg_portal_port,
+ { "PG Portal Port","isns.pg.portal_port",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "PG Portal TCP/UDP Port", HFILL }
+ },
+
+ { &hf_isns_port_type,
+ { "Port Type","isns.port.port_type",
+ FT_BOOLEAN, 16, TFS(&isns_port_type), 0x01, /* bit 15 (or bit 1 of a 16bit word) */
+ "Port Type",HFILL }
+ },
+
+ { &hf_isns_psb,
+ { "Portal Security Bitmap","isns.psb",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Portal Security Bitmap", HFILL }
+ },
+ { &hf_isns_psb_tunnel_mode,
+ { "Tunnel Mode ","isns.psb.tunnel",
+ FT_BOOLEAN, 32, TFS(&isns_psb_tunnel_mode), 0x0040, /* bit 25 */
+ "Tunnel Mode Preferred",HFILL }
+ },
+ { &hf_isns_psb_transport_mode,
+ { "Transport Mode ","isns.psb.transport",
+ FT_BOOLEAN, 32, TFS(&isns_psb_transport_mode), 0x0020, /* bit 26 */
+ "Transport Mode",HFILL }
+ },
+ { &hf_isns_psb_pfs,
+ { "PFS ","isns.psb.pfs",
+ FT_BOOLEAN, 32, TFS(&isns_psb_pfs), 0x0010, /* bit 27 */
+ "PFS",HFILL }
+ },
+ { &hf_isns_psb_aggressive_mode,
+ { "Aggressive Mode ","isns.psb.aggressive_mode",
+ FT_BOOLEAN, 32, TFS(&isns_psb_aggressive_mode), 0x0008, /* bit 28 */
+ "Aggressive Mode",HFILL }
+ },
+ { &hf_isns_psb_main_mode,
+ { "Main Mode ","isns.psb.main_mode",
+ FT_BOOLEAN, 32, TFS(&isns_psb_main_mode), 0x0004, /* bit 29 */
+ "Main Mode",HFILL }
+ },
+ { &hf_isns_psb_ike_ipsec,
+ { "IKE/IPSec ","isns.psb.ike_ipsec",
+ FT_BOOLEAN, 32, TFS(&isns_psb_ike_ipsec), 0x0002, /* bit 30 */
+ "IKE/IPSec",HFILL }
+ },
+ { &hf_isns_psb_bitmap,
+ { "Bitmap ","isns.psb.bitmap",
+ FT_BOOLEAN, 32, TFS(&isns_psb_bitmap), 0x0001, /* bit 31 */
+ "Bitmap",HFILL }
+ },
+
+
+
+ { &hf_isns_scn_bitmap,
+ { "iSCSI SCN Bitmap","isns.scn_bitmap",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "iSCSI SCN Bitmap", HFILL }
+ },
+ { &hf_isns_scn_bitmap_initiator_and_self_information_only,
+ { "Initiator And Self Information Only","isns.scn_bitmap.initiator_and_self_information_only",
+ FT_BOOLEAN, 32, TFS(&isns_scn_bitmap_initiator_and_self_information_only), 0x0080, /* bit 24 */
+ "Initiator And Self Information Only",HFILL }
+ },
+ { &hf_isns_scn_bitmap_target_and_self_information_only,
+ { "Target And Self Information Only","isns.scn_bitmap.target_and_self_information_only",
+ FT_BOOLEAN, 32, TFS(&isns_scn_bitmap_target_and_self_information_only), 0x0040, /* bit 25 */
+ "Target And Self Information Only",HFILL }
+ },
+ { &hf_isns_scn_bitmap_management_registration_scn,
+ { "Management Registration/SCN","isns.scn_bitmap.management_registration_scn",
+ FT_BOOLEAN, 32, TFS(&isns_scn_bitmap_management_registration_scn), 0x0020, /* bit 26 */
+ "Management Registration/SCN",HFILL }
+ },
+ { &hf_isns_scn_bitmap_object_removed,
+ { "Object Removed","isns.scn_bitmap.object_removed",
+ FT_BOOLEAN, 32, TFS(&isns_scn_bitmap_object_removed), 0x0010, /* bit 27 */
+ "Object Removed",HFILL }
+ },
+ { &hf_isns_scn_bitmap_object_added,
+ { "Object Added","isns.scn_bitmap.object_added",
+ FT_BOOLEAN, 32, TFS(&isns_scn_bitmap_object_added), 0x0008, /* bit 28 */
+ "Object Added",HFILL }
+ },
+ { &hf_isns_scn_bitmap_object_updated,
+ { "Object Updated","isns.scn_bitmap.object_updated",
+ FT_BOOLEAN, 32, TFS(&isns_scn_bitmap_object_updated), 0x0004, /* bit 29 */
+ "Object Updated",HFILL }
+ },
+ { &hf_isns_scn_bitmap_dd_dds_member_removed,
+ { "DD/DDS Member Removed (Mgmt Reg/SCN only)","isns.scn_bitmap.dd_dds_member_removed",
+ FT_BOOLEAN, 32, TFS(&isns_scn_bitmap_dd_dds_member_removed), 0x0002, /* bit 30 */
+ "DD/DDS Member Removed (Mgmt Reg/SCN only)",HFILL }
+ },
+ { &hf_isns_scn_bitmap_dd_dds_member_added,
+ { "DD/DDS Member Added (Mgmt Reg/SCN only)","isns.scn_bitmap.dd_dds_member_added",
+ FT_BOOLEAN, 32, TFS(&isns_scn_bitmap_dd_dds_member_added), 0x0001, /* bit 31 */
+ "DD/DDS Member Added (Mgmt Reg/SCN only)",HFILL }
+ },
+
+
+ { &hf_isns_isnt_control,
+ { "Control ","isns.isnt.control",
+ FT_BOOLEAN, 32, TFS(&isns_isnt_control), 0x0004, /* bit 29 */
+ "Control",HFILL }
+ },
+ { &hf_isns_isnt_initiator,
+ { "Initiator ","isns.isnt.initiator",
+ FT_BOOLEAN, 32, TFS(&isns_isnt_initiator), 0x0002, /* bit 30 */
+ "Initiator",HFILL }
+ },
+ { &hf_isns_isnt_target,
+ { "Target ","isns.isnt.target",
+ FT_BOOLEAN, 32, TFS(&isns_isnt_target), 0x0001, /* bit 31 */
+ "Target",HFILL }
+ },
+
+
+ { &hf_isns_resp_errorcode,
+ { "ErrorCode","isns.errorcode",
+ FT_UINT32, BASE_DEC,TFS(isns_errorcode),0,
+ "iSNS Response Error Code" ,HFILL}
+ },
+
+ { &hf_isns_attr_tag,
+ { "Attribute Tag","isns.attr.tag",
+ FT_UINT32, BASE_DEC,TFS(isns_attribute_tags),0,
+ "iSNS Attribute Tag" ,HFILL}
+ },
+
+ { &hf_isns_attr_len,
+ { "Attribute Length","isns.attr.len",
+ FT_UINT32, BASE_DEC,NULL,0,
+ "iSNS Attribute Length" ,HFILL}
+ },
+
+ { &hf_isns_delimiter,
+ { "Delimiter","isns.delimiter",
+ FT_NONE, BASE_NONE, NULL,0,
+ "iSNS Delimiter" ,HFILL}
+ },
+
+ { &hf_isns_not_decoded_yet,
+ { "Not Decoded Yet","isns.not_decoded_yet",
+ FT_NONE, BASE_NONE, NULL,0,
+ "This tag is not yet decoded by ethereal" ,HFILL}
+ },
+
+ { &hf_isns_heartbeat_ipv6_addr,
+ { "Heartbeat Address (ipv6)","isns.heartbeat.address",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Server IPv6 Address", HFILL }},
+
+ { &hf_isns_heartbeat_tcp_port,
+ { "Heartbeat TCP Port","isns.heartbeat.tcpport",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Server TCP Port", HFILL }},
+
+ { &hf_isns_heartbeat_udp_port,
+ { "Heartbeat UDP Port","isns.heartbeat.udpport",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Server UDP Port", HFILL }},
+
+
+ { &hf_isns_heartbeat_interval,
+ { "Heartbeat Interval (secs)","isns.heartbeat.interval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Server Heartbeat interval", HFILL }},
+
+ { &hf_isns_heartbeat_counter,
+ { "Heartbeat counter","isns.heartbeat.counter",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Server Heartbeat Counter", HFILL }},
+
+ { &hf_isns_iscsi_name,
+ { "iSCSI Name","isns.iscsi_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "iSCSI Name of device", HFILL }},
+
+ { &hf_isns_dd_member_iscsi_name,
+ { "DD Member iSCSI Name","isns.dd_member.iscsi_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "DD Member iSCSI Name of device", HFILL }},
+
+ { &hf_isns_virtual_fabric_id,
+ { "Virtual Fabric ID","isns.virtual_fabric_id",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Virtual fabric ID", HFILL }},
+
+ { &hf_isns_proxy_iscsi_name,
+ { "Proxy iSCSI Name","isns.proxy_iscsi_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Proxy iSCSI Name", HFILL }},
+
+ { &hf_isns_fc4_descriptor,
+ { "FC4 Descriptor","isns.fc4_descriptor",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "FC4 Descriptor of this device", HFILL }},
+
+ { &hf_isns_iscsi_auth_method,
+ { "iSCSI Auth Method","isns.iscsi_auth_method",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Authentication Method required by this device", HFILL }},
+
+ { &hf_isns_iscsi_alias,
+ { "iSCSI Alias","isns.iscsi_alias",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "iSCSI Alias of device", HFILL }},
+
+ { &hf_isns_portal_symbolic_name,
+ { "Portal Symbolic Name","isns.portal.symbolic_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Symbolic name of this portal", HFILL }},
+
+ { &hf_isns_dd_set_symbolic_name,
+ { "DD Set Symbolic Name","isns.dd_set.symbolic_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Symbolic name of this DD Set", HFILL }},
+
+ { &hf_isns_dd_symbolic_name,
+ { "DD Symbolic Name","isns.dd.symbolic_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Symbolic name of this DD", HFILL }},
+
+ { &hf_isns_symbolic_port_name,
+ { "Symbolic Port Name","isns.port.symbolic_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Symbolic name of this port", HFILL }},
+
+ { &hf_isns_symbolic_node_name,
+ { "Symbolic Node Name","isns.node.symbolic_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Symbolic name of this node", HFILL }},
+
+ { &hf_isns_entity_identifier,
+ { "Entity Identifier","isns.entity_identifier",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Entity Identifier of this object", HFILL }},
+
+ { &hf_isns_mgmt_ip_addr,
+ { "Management IP Address","isns.mgmt.ip_address",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Management IPv4/IPv6 Address", HFILL }},
+
+ { &hf_isns_node_ip_addr,
+ { "Node IP Address","isns.node.ip_address",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Node IPv4/IPv6 Address", HFILL }},
+
+ { &hf_isns_port_ip_addr,
+ { "Port IP Address","isns.port.ip_address",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Port IPv4/IPv6 Address", HFILL }},
+
+ { &hf_isns_portal_ip_addr,
+ { "Portal IP Address","isns.portal.ip_address",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Portal IPv4/IPv6 Address", HFILL }},
+
+ { &hf_isns_dd_member_portal_ip_addr,
+ { "DD Member Portal IP Address","isns.dd.member_portal.ip_address",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "DD Member Portal IPv4/IPv6 Address", HFILL }},
+
+ { &hf_isns_pg_portal_ip_addr,
+ { "PG Portal IP Address","isns.pg_portal.ip_address",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "PG Portal IPv4/IPv6 Address", HFILL }},
+
+ { &hf_isns_dd_id_next_id,
+ { "DD ID Next ID","isns.index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "DD ID Next ID", HFILL }},
+
+ { &hf_isns_member_iscsi_index,
+ { "Member iSCSI Index","isns.member_iscsi_index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Member iSCSI Index", HFILL }},
+
+ { &hf_isns_member_portal_index,
+ { "Member Portal Index","isns.member_portal_index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Member Portal Index", HFILL }},
+
+ { &hf_isns_member_ifcp_node,
+ { "Member iFCP Node","isns.member_ifcp_node",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Member iFCP Node", HFILL }},
+
+ { &hf_isns_vendor_oui,
+ { "Vendor OUI","isns.index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Vendor OUI", HFILL }},
+
+ { &hf_isns_preferred_id,
+ { "Preferred ID","isns.preferred_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Preferred ID", HFILL }},
+
+ { &hf_isns_dd_set_id,
+ { "DD Set ID","isns.dd_set_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "DD Set ID", HFILL }},
+
+ { &hf_isns_dd_id,
+ { "DD ID","isns.dd_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "DD ID", HFILL }},
+
+ { &hf_isns_port_id,
+ { "Port ID","isns.port_id",
+ FT_UINT24, BASE_HEX, NULL, 0x0,
+ "Port ID", HFILL }},
+
+ { &hf_isns_hard_address,
+ { "Hard Address","isns.hard_address",
+ FT_UINT24, BASE_HEX, NULL, 0x0,
+ "Hard Address", HFILL }},
+
+ { &hf_isns_wwnn_token,
+ { "WWNN Token","isns.wwnn_token",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ "WWNN Token", HFILL }},
+
+ { &hf_isns_fc_port_name_wwpn,
+ { "FC Port Name WWPN","isns.fc_port_name_wwpn",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ "FC Port Name WWPN", HFILL }},
+
+ { &hf_isns_fc_node_name_wwnn,
+ { "FC Node Name WWNN","isns.fc_node_name_wwnn",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ "FC Node Name WWNN", HFILL }},
+
+ { &hf_isns_node_ipa,
+ { "Node IPA","isns.node_ipa",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ "Node IPA", HFILL }},
+
+ { &hf_isns_fabric_port_name,
+ { "Fabric Port Name","isns.fabric_port_name",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ "Fabric Port Name", HFILL }},
+
+ { &hf_isns_permanent_port_name,
+ { "Permanent Port Name","isns.permanent_port_name",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ "Permanent Port Name", HFILL }},
+
+ { &hf_isns_switch_name,
+ { "Switch Name","isns.switch_name",
+ FT_UINT64, BASE_HEX, NULL, 0x0,
+ "Switch Name", HFILL }},
+
+ { &hf_isns_dd_set_next_id,
+ { "DD Set Next ID","isns.dd_set_next_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "DD Set Next ID", HFILL }},
+
+ { &hf_isns_assigned_id,
+ { "Assigned ID","isns.assigned_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Assigned ID", HFILL }},
+
+ { &hf_isns_node_index,
+ { "Node Index","isns.node.index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Node Index", HFILL }},
+
+ { &hf_isns_node_next_index,
+ { "Node Next Index","isns.node.next_index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Node INext ndex", HFILL }},
+
+ { &hf_isns_portal_index,
+ { "Portal Index","isns.portal.index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Portal Index", HFILL }},
+
+ { &hf_isns_portal_next_index,
+ { "Portal Next Index","isns.portal.next_index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Portal Next Index", HFILL }},
+
+ { &hf_isns_entity_index,
+ { "Entity Index","isns.entity.index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Entity Index", HFILL }},
+
+ { &hf_isns_entity_next_index,
+ { "Entity Next Index","isns.entity.next_index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Next Entity Index", HFILL }},
+
+ { &hf_isns_timestamp,
+ { "Timestamp","isns.timestamp",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Timestamp in Seconds", HFILL }},
+
+ { &hf_isns_esi_interval,
+ { "ESI Interval","isns.esi_interval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ESI Interval in Seconds", HFILL }},
+
+ { &hf_isns_registration_period,
+ { "Registration Period","isns.registration_period",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Registration Period in Seconds", HFILL }},
+
+ { &hf_isns_portal_group_tag,
+ { "PG Tag","isns.portal_group_tag",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Portal Group Tag", HFILL }},
+
+ { &hf_isns_payload,
+ { "Payload", "isns.payload",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Payload" ,HFILL}
+ }
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_isns,
+ &ett_isns_flags,
+ &ett_isns_payload,
+ &ett_isns_attribute,
+ &ett_isns_port,
+ &ett_isns_isnt
+ };
+ module_t *isns_module;
+
+/* Register the protocol name and description */
+ proto_isns = proto_register_protocol("iSNS",
+ "iSNS", "isns");
+ proto_register_field_array(proto_isns, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register preferences */
+ isns_module = prefs_register_protocol(proto_isns, NULL);
+ prefs_register_bool_preference(isns_module, "desegment",
+ "Desegment iSNS over TCP messages",
+ "Whether the dissector should desegment "
+ "multi-segment iSNS messages", &isns_desegment);
+
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+
+void
+proto_reg_handoff_isns(void)
+{
+ isns_tcp_handle = create_dissector_handle(dissect_isns_tcp,proto_isns);
+ isns_udp_handle = create_dissector_handle(dissect_isns_udp,proto_isns);
+
+ dissector_add("tcp.port",ISNS_TCP_PORT,isns_tcp_handle);
+ dissector_add("udp.port",ISNS_UDP_PORT,isns_udp_handle);
+}
diff --git a/epan/dissectors/packet-isup.c b/epan/dissectors/packet-isup.c
new file mode 100644
index 0000000000..a2189d843b
--- /dev/null
+++ b/epan/dissectors/packet-isup.c
@@ -0,0 +1,6352 @@
+/* packet-isup.c
+ * Routines for ISUP dissection
+ * Copyright 2001, Martina Obermeier <martina.obermeier@icn.siemens.de>
+ * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
+ * Modified 2003-09-10 by Anders Broman
+ * <anders.broman@ericsson.com>
+ * Inserted routines for BICC dissection according to Q.765.5 Q.1902 Q.1970 Q.1990,
+ * calling SDP dissector for RFC2327 decoding.
+ * Modified 2004-01-10 by Anders Broman to add abillity to dissect
+ * Content type application/ISUP RFC 3204 used in SIP-T
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * References:
+ * ISUP:
+ * http://www.itu.int/rec/recommendation.asp?type=products&lang=e&parent=T-REC-Q
+ * Q.763-199912, Q.763-200212Amd2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/ipv6-utils.h>
+#include <tap.h>
+#include <prefs.h>
+#include "packet-q931.h"
+#include "packet-isup.h"
+#include "packet-e164.h"
+
+#define MTP3_ISUP_SERVICE_INDICATOR 5
+#define MTP3_BICC_SERVICE_INDICATOR 13
+#define ASCII_NUMBER_DELTA 0x30
+#define ASCII_LETTER_DELTA 0x37
+
+/* Definition of protocol field values und lengths */
+
+/* Definition of Message Types */
+#define MESSAGE_TYPE_INITIAL_ADDR 1
+#define MESSAGE_TYPE_SUBSEQ_ADDR 2
+#define MESSAGE_TYPE_INFO_REQ 3
+#define MESSAGE_TYPE_INFO 4
+#define MESSAGE_TYPE_CONTINUITY 5
+#define MESSAGE_TYPE_ADDR_CMPL 6
+#define MESSAGE_TYPE_CONNECT 7
+#define MESSAGE_TYPE_FORW_TRANS 8
+#define MESSAGE_TYPE_ANSWER 9
+#define MESSAGE_TYPE_RELEASE 12
+#define MESSAGE_TYPE_SUSPEND 13
+#define MESSAGE_TYPE_RESUME 14
+#define MESSAGE_TYPE_REL_CMPL 16
+#define MESSAGE_TYPE_CONT_CHECK_REQ 17
+#define MESSAGE_TYPE_RESET_CIRCUIT 18
+#define MESSAGE_TYPE_BLOCKING 19
+#define MESSAGE_TYPE_UNBLOCKING 20
+#define MESSAGE_TYPE_BLOCK_ACK 21
+#define MESSAGE_TYPE_UNBLOCK_ACK 22
+#define MESSAGE_TYPE_CIRC_GRP_RST 23
+#define MESSAGE_TYPE_CIRC_GRP_BLCK 24
+#define MESSAGE_TYPE_CIRC_GRP_UNBL 25
+#define MESSAGE_TYPE_CIRC_GRP_BL_ACK 26
+#define MESSAGE_TYPE_CIRC_GRP_UNBL_ACK 27
+#define MESSAGE_TYPE_FACILITY_REQ 31
+#define MESSAGE_TYPE_FACILITY_ACC 32
+#define MESSAGE_TYPE_FACILITY_REJ 33
+#define MESSAGE_TYPE_LOOP_BACK_ACK 36
+#define MESSAGE_TYPE_PASS_ALONG 40
+#define MESSAGE_TYPE_CIRC_GRP_RST_ACK 41
+#define MESSAGE_TYPE_CIRC_GRP_QRY 42
+#define MESSAGE_TYPE_CIRC_GRP_QRY_RSP 43
+#define MESSAGE_TYPE_CALL_PROGRSS 44
+#define MESSAGE_TYPE_USER2USER_INFO 45
+#define MESSAGE_TYPE_UNEQUIPPED_CIC 46
+#define MESSAGE_TYPE_CONFUSION 47
+#define MESSAGE_TYPE_OVERLOAD 48
+#define MESSAGE_TYPE_CHARGE_INFO 49
+#define MESSAGE_TYPE_NETW_RESRC_MGMT 50
+#define MESSAGE_TYPE_FACILITY 51
+#define MESSAGE_TYPE_USER_PART_TEST 52
+#define MESSAGE_TYPE_USER_PART_AVAIL 53
+#define MESSAGE_TYPE_IDENT_REQ 54
+#define MESSAGE_TYPE_IDENT_RSP 55
+#define MESSAGE_TYPE_SEGMENTATION 56
+#define MESSAGE_TYPE_LOOP_PREVENTION 64
+#define MESSAGE_TYPE_APPLICATION_TRANS 65
+#define MESSAGE_TYPE_PRE_RELEASE_INFO 66
+#define MESSAGE_TYPE_SUBSEQUENT_DIR_NUM 67
+
+
+const value_string isup_message_type_value[] = {
+ { MESSAGE_TYPE_INITIAL_ADDR, "Initial address"},
+ { MESSAGE_TYPE_SUBSEQ_ADDR, "Subsequent address"},
+ { MESSAGE_TYPE_INFO_REQ, "Information request (national use)"},
+ { MESSAGE_TYPE_INFO, "Information (national use)"},
+ { MESSAGE_TYPE_CONTINUITY, "Continuity"},
+ { MESSAGE_TYPE_ADDR_CMPL, "Address complete"},
+ { MESSAGE_TYPE_CONNECT, "Connect"},
+ { MESSAGE_TYPE_FORW_TRANS, "Forward transfer"},
+ { MESSAGE_TYPE_ANSWER, "Answer"},
+ { MESSAGE_TYPE_RELEASE, "Release"},
+ { MESSAGE_TYPE_SUSPEND, "Suspend"},
+ { MESSAGE_TYPE_RESUME, "Resume"},
+ { MESSAGE_TYPE_REL_CMPL, "Release complete"},
+ { MESSAGE_TYPE_CONT_CHECK_REQ, "Continuity check request"},
+ { MESSAGE_TYPE_RESET_CIRCUIT, "Reset Circuit"},
+ { MESSAGE_TYPE_BLOCKING, "Blocking"},
+ { MESSAGE_TYPE_UNBLOCKING, "Unblocking"},
+ { MESSAGE_TYPE_BLOCK_ACK, "Blocking acknowledgement"},
+ { MESSAGE_TYPE_UNBLOCK_ACK, "Unblocking acknowledgment"},
+ { MESSAGE_TYPE_CIRC_GRP_RST, "Circuit group reset"},
+ { MESSAGE_TYPE_CIRC_GRP_BLCK, "Circuit group blocking"},
+ { MESSAGE_TYPE_CIRC_GRP_UNBL, "Circuit group unblocking"},
+ { MESSAGE_TYPE_CIRC_GRP_BL_ACK, "Circuit group blocking acknowledgement"},
+ { MESSAGE_TYPE_CIRC_GRP_UNBL_ACK, "Circuit group unblocking acknowledgement"},
+ { MESSAGE_TYPE_FACILITY_REQ, "Facility request"},
+ { MESSAGE_TYPE_FACILITY_ACC, "Facility accepted"},
+ { MESSAGE_TYPE_FACILITY_REJ, "Facility reject"},
+ { MESSAGE_TYPE_LOOP_BACK_ACK, "Loop back acknowledgement (national use)"},
+ { MESSAGE_TYPE_PASS_ALONG, "Pass-along (national use)"},
+ { MESSAGE_TYPE_CIRC_GRP_RST_ACK, "Circuit group reset acknowledgement"},
+ { MESSAGE_TYPE_CIRC_GRP_QRY, "Circuit group query (national use)"},
+ { MESSAGE_TYPE_CIRC_GRP_QRY_RSP, "Circuit group query response (national use)"},
+ { MESSAGE_TYPE_CALL_PROGRSS, "Call progress"},
+ { MESSAGE_TYPE_USER2USER_INFO, "User-to-user information"},
+ { MESSAGE_TYPE_UNEQUIPPED_CIC, "Unequipped CIC (national use)"},
+ { MESSAGE_TYPE_CONFUSION, "Confusion"},
+ { MESSAGE_TYPE_OVERLOAD, "Overload (national use)"},
+ { MESSAGE_TYPE_CHARGE_INFO, "Charge information (national use)"},
+ { MESSAGE_TYPE_NETW_RESRC_MGMT, "Network resource management"},
+ { MESSAGE_TYPE_FACILITY, "Facility"},
+ { MESSAGE_TYPE_USER_PART_TEST, "User part test"},
+ { MESSAGE_TYPE_USER_PART_AVAIL, "User part available"},
+ { MESSAGE_TYPE_IDENT_REQ, "Identification request"},
+ { MESSAGE_TYPE_IDENT_RSP, "Identification response"},
+ { MESSAGE_TYPE_SEGMENTATION, "Segmentation"},
+ { MESSAGE_TYPE_LOOP_PREVENTION, "Loop prevention"},
+ { MESSAGE_TYPE_APPLICATION_TRANS, "Application transport"},
+ { MESSAGE_TYPE_PRE_RELEASE_INFO, "Pre-release information"},
+ { MESSAGE_TYPE_SUBSEQUENT_DIR_NUM, "Subsequent Directory Number (national use)"},
+
+ { 0, NULL}};
+
+/* Same as above but in acronym form (for the Info column) */
+const value_string isup_message_type_value_acro[] = {
+ { MESSAGE_TYPE_INITIAL_ADDR, "IAM"},
+ { MESSAGE_TYPE_SUBSEQ_ADDR, "SAM"},
+ { MESSAGE_TYPE_INFO_REQ, "INR"},
+ { MESSAGE_TYPE_INFO, "INF"},
+ { MESSAGE_TYPE_CONTINUITY, "COT"},
+ { MESSAGE_TYPE_ADDR_CMPL, "ACM"},
+ { MESSAGE_TYPE_CONNECT, "CON"},
+ { MESSAGE_TYPE_FORW_TRANS, "FOT"},
+ { MESSAGE_TYPE_ANSWER, "ANM"},
+ { MESSAGE_TYPE_RELEASE, "REL"},
+ { MESSAGE_TYPE_SUSPEND, "SUS"},
+ { MESSAGE_TYPE_RESUME, "RES"},
+ { MESSAGE_TYPE_REL_CMPL, "RLC"},
+ { MESSAGE_TYPE_CONT_CHECK_REQ, "CCR"},
+ { MESSAGE_TYPE_RESET_CIRCUIT, "RSC"},
+ { MESSAGE_TYPE_BLOCKING, "BLO"},
+ { MESSAGE_TYPE_UNBLOCKING, "UBL"},
+ { MESSAGE_TYPE_BLOCK_ACK, "BLA"},
+ { MESSAGE_TYPE_UNBLOCK_ACK, "UBLA"},
+ { MESSAGE_TYPE_CIRC_GRP_RST, "GRS"},
+ { MESSAGE_TYPE_CIRC_GRP_BLCK, "CGB"},
+ { MESSAGE_TYPE_CIRC_GRP_UNBL, "CGU"},
+ { MESSAGE_TYPE_CIRC_GRP_BL_ACK, "CGBA"},
+ { MESSAGE_TYPE_CIRC_GRP_UNBL_ACK, "CGUA"},
+ { MESSAGE_TYPE_FACILITY_REQ, "FAR"},
+ { MESSAGE_TYPE_FACILITY_ACC, "FAA"},
+ { MESSAGE_TYPE_FACILITY_REJ, "FRJ"},
+ { MESSAGE_TYPE_LOOP_BACK_ACK, "LPA"},
+ { MESSAGE_TYPE_PASS_ALONG, "PAM"},
+ { MESSAGE_TYPE_CIRC_GRP_RST_ACK, "GRA"},
+ { MESSAGE_TYPE_CIRC_GRP_QRY, "CQM"},
+ { MESSAGE_TYPE_CIRC_GRP_QRY_RSP, "CQR"},
+ { MESSAGE_TYPE_CALL_PROGRSS, "CPG"},
+ { MESSAGE_TYPE_USER2USER_INFO, "UUI"},
+ { MESSAGE_TYPE_UNEQUIPPED_CIC, "UCIC"},
+ { MESSAGE_TYPE_CONFUSION, "CFN"},
+ { MESSAGE_TYPE_OVERLOAD, "OLM"},
+ { MESSAGE_TYPE_CHARGE_INFO, "CRG"},
+ { MESSAGE_TYPE_NETW_RESRC_MGMT, "NRM"},
+ { MESSAGE_TYPE_FACILITY, "FAC"},
+ { MESSAGE_TYPE_USER_PART_TEST, "UPT"},
+ { MESSAGE_TYPE_USER_PART_AVAIL, "UPA"},
+ { MESSAGE_TYPE_IDENT_REQ, "IDR"},
+ { MESSAGE_TYPE_IDENT_RSP, "IDS"},
+ { MESSAGE_TYPE_SEGMENTATION, "SGM"},
+ { MESSAGE_TYPE_LOOP_PREVENTION, "LOP"},
+ { MESSAGE_TYPE_APPLICATION_TRANS, "APM"},
+ { MESSAGE_TYPE_PRE_RELEASE_INFO, "PRI"},
+ { MESSAGE_TYPE_SUBSEQUENT_DIR_NUM, "SDN"},
+
+ { 0, NULL}};
+
+/* Definition of Parameter Types */
+#define PARAM_TYPE_END_OF_OPT_PARAMS 0
+#define PARAM_TYPE_CALL_REF 1
+#define PARAM_TYPE_TRANSM_MEDIUM_REQU 2
+#define PARAM_TYPE_ACC_TRANSP 3
+#define PARAM_TYPE_CALLED_PARTY_NR 4
+#define PARAM_TYPE_SUBSQT_NR 5
+#define PARAM_TYPE_NATURE_OF_CONN_IND 6
+#define PARAM_TYPE_FORW_CALL_IND 7
+#define PARAM_TYPE_OPT_FORW_CALL_IND 8
+#define PARAM_TYPE_CALLING_PRTY_CATEG 9
+#define PARAM_TYPE_CALLING_PARTY_NR 10
+#define PARAM_TYPE_REDIRECTING_NR 11
+#define PARAM_TYPE_REDIRECTION_NR 12
+#define PARAM_TYPE_CONNECTION_REQ 13
+#define PARAM_TYPE_INFO_REQ_IND 14
+#define PARAM_TYPE_INFO_IND 15
+#define PARAM_TYPE_CONTINUITY_IND 16
+#define PARAM_TYPE_BACKW_CALL_IND 17
+#define PARAM_TYPE_CAUSE_INDICATORS 18
+#define PARAM_TYPE_REDIRECTION_INFO 19
+#define PARAM_TYPE_CIRC_GRP_SV_MSG_TYPE 21
+#define PARAM_TYPE_RANGE_AND_STATUS 22
+#define PARAM_TYPE_FACILITY_IND 24
+#define PARAM_TYPE_CLSD_USR_GRP_ILOCK_CD 26
+#define PARAM_TYPE_USER_SERVICE_INFO 29
+#define PARAM_TYPE_SIGNALLING_POINT_CODE 30
+#define PARAM_TYPE_USER_TO_USER_INFO 32
+#define PARAM_TYPE_CONNECTED_NR 33
+#define PARAM_TYPE_SUSP_RESUME_IND 34
+#define PARAM_TYPE_TRANSIT_NETW_SELECT 35
+#define PARAM_TYPE_EVENT_INFO 36
+#define PARAM_TYPE_CIRC_ASSIGN_MAP 37
+#define PARAM_TYPE_CIRC_STATE_IND 38
+#define PARAM_TYPE_AUTO_CONG_LEVEL 39
+#define PARAM_TYPE_ORIG_CALLED_NR 40
+#define PARAM_TYPE_OPT_BACKW_CALL_IND 41
+#define PARAM_TYPE_USER_TO_USER_IND 42
+#define PARAM_TYPE_ORIG_ISC_POINT_CODE 43
+#define PARAM_TYPE_GENERIC_NOTIF_IND 44
+#define PARAM_TYPE_CALL_HIST_INFO 45
+#define PARAM_TYPE_ACC_DELIV_INFO 46
+#define PARAM_TYPE_NETW_SPECIFIC_FACLTY 47
+#define PARAM_TYPE_USER_SERVICE_INFO_PR 48
+#define PARAM_TYPE_PROPAG_DELAY_COUNTER 49
+#define PARAM_TYPE_REMOTE_OPERATIONS 50
+#define PARAM_TYPE_SERVICE_ACTIVATION 51
+#define PARAM_TYPE_USER_TELESERV_INFO 52
+#define PARAM_TYPE_TRANSM_MEDIUM_USED 53
+#define PARAM_TYPE_CALL_DIV_INFO 54
+#define PARAM_TYPE_ECHO_CTRL_INFO 55
+#define PARAM_TYPE_MSG_COMPAT_INFO 56
+#define PARAM_TYPE_PARAM_COMPAT_INFO 57
+#define PARAM_TYPE_MLPP_PRECEDENCE 58
+#define PARAM_TYPE_MCID_REQ_IND 59
+#define PARAM_TYPE_MCID_RSP_IND 60
+#define PARAM_TYPE_HOP_COUNTER 61
+#define PARAM_TYPE_TRANSM_MEDIUM_RQUR_PR 62
+#define PARAM_TYPE_LOCATION_NR 63
+#define PARAM_TYPE_REDIR_NR_RSTRCT 64
+#define PARAM_TYPE_CALL_TRANS_REF 67
+#define PARAM_TYPE_LOOP_PREV_IND 68
+#define PARAM_TYPE_CALL_TRANS_NR 69
+#define PARAM_TYPE_CCSS 75
+#define PARAM_TYPE_FORW_GVNS 76
+#define PARAM_TYPE_BACKW_GVNS 77
+#define PARAM_TYPE_REDIRECT_CAPAB 78
+#define PARAM_TYPE_NETW_MGMT_CTRL 91
+#define PARAM_TYPE_CORRELATION_ID 101
+#define PARAM_TYPE_SCF_ID 102
+#define PARAM_TYPE_CALL_DIV_TREAT_IND 110
+#define PARAM_TYPE_CALLED_IN_NR 111
+#define PARAM_TYPE_CALL_OFF_TREAT_IND 112
+#define PARAM_TYPE_CHARGED_PARTY_IDENT 113
+#define PARAM_TYPE_CONF_TREAT_IND 114
+#define PARAM_TYPE_DISPLAY_INFO 115
+#define PARAM_TYPE_UID_ACTION_IND 116
+#define PARAM_TYPE_UID_CAPAB_IND 117
+#define PARAM_TYPE_REDIRECT_COUNTER 119
+#define PARAM_TYPE_APPLICATON_TRANS 120
+#define PARAM_TYPE_COLLECT_CALL_REQ 121
+#define PARAM_TYPE_GENERIC_NR 192
+#define PARAM_TYPE_GENERIC_DIGITS 193
+
+static const value_string isup_parameter_type_value[] = {
+{ PARAM_TYPE_END_OF_OPT_PARAMS, "End of optional parameters"},
+ { PARAM_TYPE_CALL_REF, "Call Reference (national use)"},
+ { PARAM_TYPE_TRANSM_MEDIUM_REQU, "Transmission medium requirement"},
+ { PARAM_TYPE_ACC_TRANSP, "Access transport"},
+ { PARAM_TYPE_CALLED_PARTY_NR, "Called party number"},
+ { PARAM_TYPE_SUBSQT_NR, "Subsequent number"},
+ { PARAM_TYPE_NATURE_OF_CONN_IND, "Nature of connection indicators"},
+ { PARAM_TYPE_FORW_CALL_IND, "Forward call indicators"},
+ { PARAM_TYPE_OPT_FORW_CALL_IND, "Optional forward call indicators"},
+ { PARAM_TYPE_CALLING_PRTY_CATEG, "Calling party's category"},
+ { PARAM_TYPE_CALLING_PARTY_NR, "Calling party number"},
+ { PARAM_TYPE_REDIRECTING_NR, "Redirecting number"},
+ { PARAM_TYPE_REDIRECTION_NR, "Redirection number"},
+ { PARAM_TYPE_CONNECTION_REQ, "Connection request"},
+ { PARAM_TYPE_INFO_REQ_IND, "Information request indicators (national use)"},
+ { PARAM_TYPE_INFO_IND, "Information indicators (national use)"},
+ { PARAM_TYPE_CONTINUITY_IND, "Continuity request"},
+ { PARAM_TYPE_BACKW_CALL_IND, "Backward call indicators"},
+ { PARAM_TYPE_CAUSE_INDICATORS, "Cause indicators"},
+ { PARAM_TYPE_REDIRECTION_INFO, "Redirection information"},
+ { PARAM_TYPE_CIRC_GRP_SV_MSG_TYPE, "Circuit group supervision message type"},
+ { PARAM_TYPE_RANGE_AND_STATUS, "Range and Status"},
+ { PARAM_TYPE_FACILITY_IND, "Facility indicator"},
+ { PARAM_TYPE_CLSD_USR_GRP_ILOCK_CD, "Closed user group interlock code"},
+ { PARAM_TYPE_USER_SERVICE_INFO, "User service information"},
+ { PARAM_TYPE_SIGNALLING_POINT_CODE, "Signalling point code (national use)"},
+ { PARAM_TYPE_USER_TO_USER_INFO, "User-to-user information"},
+ { PARAM_TYPE_CONNECTED_NR, "Connected number"},
+ { PARAM_TYPE_SUSP_RESUME_IND, "Suspend/Resume indicators"},
+ { PARAM_TYPE_TRANSIT_NETW_SELECT, "Transit network selection (national use)"},
+ { PARAM_TYPE_EVENT_INFO, "Event information"},
+ { PARAM_TYPE_CIRC_ASSIGN_MAP, "Circuit assignment map"},
+ { PARAM_TYPE_CIRC_STATE_IND, "Circuit state indicator (national use)"},
+ { PARAM_TYPE_AUTO_CONG_LEVEL, "Automatic congestion level"},
+ { PARAM_TYPE_ORIG_CALLED_NR, "Original called number"},
+ { PARAM_TYPE_OPT_BACKW_CALL_IND, "Backward call indicators"},
+ { PARAM_TYPE_USER_TO_USER_IND, "User-to-user indicators"},
+ { PARAM_TYPE_ORIG_ISC_POINT_CODE, "Origination ISC point code"},
+ { PARAM_TYPE_GENERIC_NOTIF_IND, "Generic notification indicator"},
+ { PARAM_TYPE_CALL_HIST_INFO, "Call history information"},
+ { PARAM_TYPE_ACC_DELIV_INFO, "Access delivery information"},
+ { PARAM_TYPE_NETW_SPECIFIC_FACLTY, "Network specific facility (national use)"},
+ { PARAM_TYPE_USER_SERVICE_INFO_PR, "User service information prime"},
+ { PARAM_TYPE_PROPAG_DELAY_COUNTER, "Propagation delay counter"},
+ { PARAM_TYPE_REMOTE_OPERATIONS, "Remote operations (national use)"},
+ { PARAM_TYPE_SERVICE_ACTIVATION, "Service activation"},
+ { PARAM_TYPE_USER_TELESERV_INFO, "User teleservice information"},
+ { PARAM_TYPE_TRANSM_MEDIUM_USED, "Transmission medium used"},
+ { PARAM_TYPE_CALL_DIV_INFO, "Call diversion information"},
+ { PARAM_TYPE_ECHO_CTRL_INFO, "Echo control information"},
+ { PARAM_TYPE_MSG_COMPAT_INFO, "Message compatibility information"},
+ { PARAM_TYPE_PARAM_COMPAT_INFO, "Parameter compatibility information"},
+ { PARAM_TYPE_MLPP_PRECEDENCE, "MLPP precedence"},
+ { PARAM_TYPE_MCID_REQ_IND, "MCID request indicators"},
+ { PARAM_TYPE_MCID_RSP_IND, "MCID response indicators"},
+ { PARAM_TYPE_HOP_COUNTER, "Hop counter"},
+ { PARAM_TYPE_TRANSM_MEDIUM_RQUR_PR, "Transmission medium requirement prime"},
+ { PARAM_TYPE_LOCATION_NR, "Location number"},
+ { PARAM_TYPE_REDIR_NR_RSTRCT, "Redirection number restriction"},
+ { PARAM_TYPE_CALL_TRANS_REF, "Call transfer reference"},
+ { PARAM_TYPE_LOOP_PREV_IND, "Loop prevention indicators"},
+ { PARAM_TYPE_CALL_TRANS_NR, "Call transfer number"},
+ { PARAM_TYPE_CCSS, "CCSS"},
+ { PARAM_TYPE_FORW_GVNS, "Forward GVNS"},
+ { PARAM_TYPE_BACKW_GVNS, "Backward GVNS"},
+ { PARAM_TYPE_REDIRECT_CAPAB, "Redirect capability (reserved for national use)"},
+ { PARAM_TYPE_NETW_MGMT_CTRL, "Network management controls"},
+ { PARAM_TYPE_CORRELATION_ID, "Correlation id"},
+ { PARAM_TYPE_SCF_ID, "SCF id"},
+ { PARAM_TYPE_CALL_DIV_TREAT_IND, "Call diversion treatment indicators"},
+ { PARAM_TYPE_CALLED_IN_NR, "Called IN number"},
+ { PARAM_TYPE_CALL_OFF_TREAT_IND, "Call offering treatment indicators"},
+ { PARAM_TYPE_CHARGED_PARTY_IDENT, "Charged party identification (national use)"},
+ { PARAM_TYPE_CONF_TREAT_IND, "Conference treatment indicators"},
+ { PARAM_TYPE_DISPLAY_INFO, "Display information"},
+ { PARAM_TYPE_UID_ACTION_IND, "UID action indicators"},
+ { PARAM_TYPE_UID_CAPAB_IND, "UID capability indicators"},
+ { PARAM_TYPE_REDIRECT_COUNTER, "Redirect counter (reserved for national use)"},
+ { PARAM_TYPE_COLLECT_CALL_REQ, "Collect call request"},
+ { PARAM_TYPE_GENERIC_NR, "Generic number"},
+ { PARAM_TYPE_GENERIC_DIGITS, "Generic digits (national use)"},
+ { PARAM_TYPE_APPLICATON_TRANS, "Application transport"},
+ { 0, NULL}};
+
+
+#define CIC_LENGTH 2
+#define BICC_CIC_LENGTH 4
+#define MESSAGE_TYPE_LENGTH 1
+#define COMMON_HEADER_LENGTH (CIC_LENGTH + MESSAGE_TYPE_LENGTH)
+#define BICC_COMMON_HEADER_LENGTH (BICC_CIC_LENGTH + MESSAGE_TYPE_LENGTH)
+
+#define MAXLENGTH 0xFF /* since length field is 8 Bit long - used in number dissectors;
+ max. number of address digits is 15 digits, but MAXLENGTH used
+ to avoid runtime errors */
+
+#define PARAMETER_TYPE_LENGTH 1
+#define PARAMETER_POINTER_LENGTH 1
+#define PARAMETER_LENGTH_IND_LENGTH 1
+
+/* All following parameter length definitions are WITHOUT the parameter type byte and length indicator for optional parameters*/
+#define PARAMETER_NAME_LENGTH 1
+#define PARAMETER_LENGTH_IND_LENGTH 1
+#define ACCESS_DELIVERY_INFO_LENGTH 1
+#define AUTO_CONGEST_LEVEL_LENGTH 1
+#define BACKWARD_CALL_IND_LENGTH 2
+#define BACKWARD_GVNS_LENGTH 1
+#define CALL_DIV_INFO_LENGTH 1
+#define CALL_DIV_TREATMENT_IND_LENGTH 1
+#define CALL_HISTORY_INFO_LENGTH 2
+#define CALL_OFFERING_TREATMENT_IND_LENGTH 1
+#define CALL_REFERENCE_LENGTH 5
+#define CALL_TRANSFER_REF_LENGTH 1
+#define CALLING_PRTYS_CATEGORY_LENGTH 1
+#define CCSS_LENGTH 1
+#define CIRCUIT_ASSIGNMENT_MAP_LENGTH 5
+#define CIRC_GRP_SV_MSG_TYPE_LENGTH 1
+#define CLOSED_USR_GRP_INTERLOCK_CODE_LENGTH 4
+#define COLLECT_CALL_REQUEST_LENGTH 1
+#define CONFERENCE_TREATMENT_IND_LENGTH 1
+#define CONNECTION_REQUEST_LENGTH 7
+#define CONTINUITY_IND_LENGTH 1
+#define ECHO_CONTROL_INFO_LENGTH 1
+#define END_OF_OPT_PART_LENGTH 1
+#define EVENT_INFO_LENGTH 1
+#define FACILITY_IND_LENGTH 1
+#define FORWARD_CALL_IND_LENGTH 2
+#define GENERIC_NOTIFICATION_IND_LENGTH 1
+#define HOP_COUNTER_LENGTH 1
+#define INFO_IND_LENGTH 2
+#define INFO_REQUEST_IND_LENGTH 2
+#define LOOP_PREVENTION_IND_LENGTH 1
+#define MCID_REQUEST_IND_LENGTH 1
+#define MCID_RESPONSE_IND_LENGTH 1
+#define MLPP_PRECEDENCE_LENGTH 1
+#define NATURE_OF_CONNECTION_IND_LENGTH 1
+#define NETWORK_MANAGEMENT_CONTROLS_LENGTH 1
+#define OPTIONAL_BACKWARD_CALL_IND_LENGTH 1
+#define OPTIONAL_FORWARD_CALL_IND_LENGTH 1
+#define ORIGINAL_ISC_POINT_CODE_LENGTH 2
+#define PROPAGATION_DELAY_COUNT_LENGTH 2
+#define REDIRECTION_NUMBER_LENGTH 2
+#define REDIRECTION_INFO_LENGTH 2
+#define REDIRECTION_NUMBER_RESTRICTION_LENGTH 1
+#define SIGNALLING_POINT_CODE_LENGTH 2
+#define SUSPEND_RESUME_IND_LENGTH 1
+#define TRANSMISSION_MEDIUM_REQUIREMENT_LENGTH 1
+#define TRANSMISSION_MEDIUM_RQMT_PRIME_LENGTH 1
+#define TRANSMISSION_MEDIUM_USED_LENGTH 1
+#define UID_ACTION_IND_LENGTH 1
+#define UID_CAPABILITY_IND_LENGTH 1
+#define USER_TELESERVICE_INFO_LENGTH 2
+#define USER_TO_USER_IND_LENGTH 1
+#define RANGE_LENGTH 1
+
+#define CALL_ID_LENGTH 3 /* for parameter Call Reference */
+#define SPC_LENGTH 2 /* for parameter Call Reference, Connection request */
+#define LOCAL_REF_LENGTH 3 /* for parameter Connection request */
+#define PROTOCOL_CLASS_LENGTH 1 /* for parameter Connection request */
+#define CREDIT_LENGTH 1 /* for parameter Connection request */
+
+#define CIC_OFFSET 0
+#define BICC_CIC_OFFSET 0
+
+#define NO_SATELLITE_CIRCUIT_IN_CONNECTION 0
+#define ONE_SATELLITE_CIRCUIT_IN_CONNECTION 1
+#define TWO_SATELLITE_CIRCUIT_IN_CONNECTION 2
+static const value_string isup_satellite_ind_value[] = {
+ { NO_SATELLITE_CIRCUIT_IN_CONNECTION, "No Satellite circuit in connection"},
+ { ONE_SATELLITE_CIRCUIT_IN_CONNECTION, "One Satellite circuit in connection"},
+ { TWO_SATELLITE_CIRCUIT_IN_CONNECTION, "Two Satellite circuits in connection"},
+ { 0, NULL}};
+
+#define CONTINUITY_CHECK_NOT_REQUIRED 0
+#define CONTINUITY_CHECK_REQUIRED 1
+#define CONTINUITY_CHECK_ON_A_PREVIOUS_CIRCUIT 2
+static const value_string isup_continuity_check_ind_value[] = {
+ { CONTINUITY_CHECK_NOT_REQUIRED, "Continuity check not required"},
+ { CONTINUITY_CHECK_REQUIRED, "Continuity check required on this circuit"},
+ { CONTINUITY_CHECK_ON_A_PREVIOUS_CIRCUIT , "Continuity check performed on a previous circuit"},
+ { 0, NULL}};
+
+static const true_false_string isup_echo_control_device_ind_value = {
+ "Echo control device included",
+ "Echo control device not included"
+};
+
+static const true_false_string isup_natnl_inatnl_call_ind_value = {
+ "Call to be treated as international call",
+ "Call to be treated as national call"
+};
+
+#define NO_END_TO_END_METHOD_AVAILABLE 0
+#define PASS_ALONG_METHOD_AVAILABLE 1
+#define SCCP_METHOD_AVAILABLE 2
+#define PASS_ALONG_AND_SCCP_METHOD_AVAILABLE 3
+static const value_string isup_end_to_end_method_ind_value[] = {
+ { NO_END_TO_END_METHOD_AVAILABLE, "No End-to-end method available (only link-by-link method available)"},
+ { PASS_ALONG_METHOD_AVAILABLE, "Pass-along method available (national use)"},
+ { SCCP_METHOD_AVAILABLE, "SCCP method available"},
+ { PASS_ALONG_AND_SCCP_METHOD_AVAILABLE, "pass-along and SCCP method available (national use)"},
+ { 0, NULL}};
+
+static const true_false_string isup_interworking_ind_value = {
+ "interworking encountered",
+ "no interworking encountered (No.7 signalling all the way)"
+};
+
+static const true_false_string isup_end_to_end_info_ind_value = {
+ "end-to-end information available",
+ "no end-to-end information available"
+};
+
+static const true_false_string isup_ISDN_user_part_ind_value = {
+ "ISDN user part used all the way",
+ "ISDN user part not used all the way"
+};
+
+#define ISUP_PREFERED_ALL_THE_WAY 0
+#define ISUP_NOT_REQUIRED_ALL_THE_WAY 1
+#define ISUP_REQUIRED_ALL_WAY 2
+#define ISUP_ISDN_USER_PART_IND_SPARE 3
+static const value_string isup_preferences_ind_value[] = {
+ { ISUP_PREFERED_ALL_THE_WAY, "ISDN user part prefered all the way"},
+ { ISUP_NOT_REQUIRED_ALL_THE_WAY, "ISDN user part not required all the way"},
+ { ISUP_REQUIRED_ALL_WAY, "ISDN user part required all the way"},
+ { ISUP_ISDN_USER_PART_IND_SPARE, "spare"},
+ { 0, NULL}};
+
+static const true_false_string isup_ISDN_originating_access_ind_value = {
+ "originating access ISDN",
+ "originating access non-ISDN"
+};
+
+#define NO_INDICATION 0
+#define CONNECTIONLESS_METHOD_AVAILABLE 1
+#define CONNECITON_ORIENTED_METHOD_AVAILABLE 2
+#define CONNECTIONLESS_AND_ORIENTED_METHOD_AVAILABLE 3
+static const value_string isup_SCCP_method_ind_value[] = {
+ { NO_INDICATION, "No indication"},
+ { CONNECTIONLESS_METHOD_AVAILABLE, "Connectionless method available (national use)"},
+ { CONNECITON_ORIENTED_METHOD_AVAILABLE, "Connection oriented method available"},
+ { CONNECTIONLESS_AND_ORIENTED_METHOD_AVAILABLE, "Connectionless and -oriented method available (national use)"},
+ { 0, NULL}};
+
+#define UNKNOWN_AT_THIS_TIME 0
+#define OPERATOR_FRENCH 1
+#define OPERATOR_ENGLISH 2
+#define OPERATOR_GERMAN 3
+#define OPERATOR_RUSSIAN 4
+#define OPERATOR_SPANISH 5
+#define ORDINARY_CALLING_SUBSCRIBER 10
+#define CALLING_SUBSCRIBER_WITH_PRIORITY 11
+#define DATA_CALL 12
+#define TEST_CALL 13
+#define PAYPHONE 15
+static const value_string isup_calling_partys_category_value[] = {
+ { UNKNOWN_AT_THIS_TIME, "Category unknown at this time (national use)"},
+ { OPERATOR_FRENCH, "operator, language French"},
+ { OPERATOR_ENGLISH, "operator, language English"},
+ { OPERATOR_GERMAN, "operator, language German"},
+ { OPERATOR_RUSSIAN, "operator, language Russian"},
+ { OPERATOR_SPANISH, "operator, language Spanish"},
+ { ORDINARY_CALLING_SUBSCRIBER, "ordinary calling subscriber"},
+ { CALLING_SUBSCRIBER_WITH_PRIORITY, "calling subscriber with priority"},
+ { DATA_CALL, "data call (voice band data)"},
+ { TEST_CALL, "test call"},
+ /* q.763-200212Amd2 */
+ { 14, "IEPS call marking for preferential call set up"},
+ { PAYPHONE, "payphone"},
+ { 0, NULL}};
+
+#define MEDIUM_SPEECH 0
+#define MEDIUM_64KBS 2
+#define MEDIUM_3_1_KHZ_AUDIO 3
+#define MEDIUM_RESERVED_SERVICE2_1 4
+#define MEDIUM_RESERVED_SERVICE1_2 5
+#define MEDIUM_64KBS_PREFERED 6
+#define MEDIUM_2_64KBS 7
+#define MEDIUM_384KBS 8
+#define MEDIUM_1536KBS 9
+#define MEDIUM_1920KBS 10
+#define MEDIUM_3_64KBS 16
+#define MEDIUM_4_64KBS 17
+#define MEDIUM_5_64KBS 18
+#define MEDIUM_7_64KBS 20
+#define MEDIUM_8_64KBS 21
+#define MEDIUM_9_64KBS 22
+#define MEDIUM_10_64KBS 23
+#define MEDIUM_11_64KBS 24
+#define MEDIUM_12_64KBS 25
+#define MEDIUM_13_64KBS 26
+#define MEDIUM_14_64KBS 27
+#define MEDIUM_15_64KBS 28
+#define MEDIUM_16_64KBS 29
+#define MEDIUM_17_64KBS 30
+#define MEDIUM_18_64KBS 31
+#define MEDIUM_19_64KBS 32
+#define MEDIUM_20_64KBS 33
+#define MEDIUM_21_64KBS 34
+#define MEDIUM_22_64KBS 35
+#define MEDIUM_23_64KBS 36
+#define MEDIUM_25_64KBS 38
+#define MEDIUM_26_64KBS 39
+#define MEDIUM_27_64KBS 40
+#define MEDIUM_28_64KBS 41
+#define MEDIUM_29_64KBS 42
+static const value_string isup_transmission_medium_requirement_value[] = {
+ { MEDIUM_SPEECH, "speech"},
+ { MEDIUM_64KBS, "64 kbit/s unrestricted"},
+ { MEDIUM_3_1_KHZ_AUDIO, "3.1 kHz audio"},
+ { MEDIUM_RESERVED_SERVICE2_1, "reserved for alternate speech (service 2)/64 kbit/s unrestricted (service 1)"},
+ { MEDIUM_RESERVED_SERVICE1_2, "reserved for alternate 64 kbit/s unrestricted (service 1)/speech (service 2)"},
+ { MEDIUM_64KBS_PREFERED, "64 kbit/s prefered"},
+ { MEDIUM_2_64KBS, "2x64 kbit/s unrestricted"},
+ { MEDIUM_384KBS, "384 kbit/s unrestricted"},
+ { MEDIUM_1536KBS, "1536 kbit/s unrestricted"},
+ { MEDIUM_1920KBS, "1920 kbit/s unrestricted"},
+ { MEDIUM_3_64KBS, "3x64 kbit/s unrestricted"},
+ { MEDIUM_4_64KBS, "4x64 kbit/s unrestricted"},
+ { MEDIUM_5_64KBS, "5x64 kbit/s unrestricted"},
+ { MEDIUM_7_64KBS, "7x64 kbit/s unrestricted"},
+ { MEDIUM_8_64KBS, "8x64 kbit/s unrestricted"},
+ { MEDIUM_9_64KBS, "9x64 kbit/s unrestricted"},
+ { MEDIUM_10_64KBS, "10x64 kbit/s unrestricted"},
+ { MEDIUM_11_64KBS, "11x64 kbit/s unrestricted"},
+ { MEDIUM_12_64KBS, "12x64 kbit/s unrestricted"},
+ { MEDIUM_13_64KBS, "13x64 kbit/s unrestricted"},
+ { MEDIUM_14_64KBS, "14x64 kbit/s unrestricted"},
+ { MEDIUM_15_64KBS, "15x64 kbit/s unrestricted"},
+ { MEDIUM_16_64KBS, "16x64 kbit/s unrestricted"},
+ { MEDIUM_17_64KBS, "17x64 kbit/s unrestricted"},
+ { MEDIUM_18_64KBS, "18x64 kbit/s unrestricted"},
+ { MEDIUM_19_64KBS, "19x64 kbit/s unrestricted"},
+ { MEDIUM_20_64KBS, "20x64 kbit/s unrestricted"},
+ { MEDIUM_21_64KBS, "21x64 kbit/s unrestricted"},
+ { MEDIUM_22_64KBS, "22x64 kbit/s unrestricted"},
+ { MEDIUM_23_64KBS, "23x64 kbit/s unrestricted"},
+ { MEDIUM_25_64KBS, "25x64 kbit/s unrestricted"},
+ { MEDIUM_26_64KBS, "26x64 kbit/s unrestricted"},
+ { MEDIUM_27_64KBS, "27x64 kbit/s unrestricted"},
+ { MEDIUM_28_64KBS, "28x64 kbit/s unrestricted"},
+ { MEDIUM_29_64KBS, "29x64 kbit/s unrestricted"},
+ { 0, NULL}};
+static const value_string isup_transmission_medium_requirement_prime_value[] = {
+ { MEDIUM_SPEECH, "speech"},
+ { MEDIUM_64KBS, "reserved for 64 kbit/s unrestricted"},
+ { MEDIUM_3_1_KHZ_AUDIO, "3.1 kHz audio"},
+ { MEDIUM_RESERVED_SERVICE2_1, "reserved for alternate speech (service 2)/64 kbit/s unrestricted (service 1)"},
+ { MEDIUM_RESERVED_SERVICE1_2, "reserved for alternate 64 kbit/s unrestricted (service 1)/speech (service 2)"},
+ { MEDIUM_64KBS_PREFERED, "reserved for 64 kbit/s prefered"},
+ { MEDIUM_2_64KBS, "reserved for 2x64 kbit/s unrestricted"},
+ { MEDIUM_384KBS, "reserved for 384 kbit/s unrestricted"},
+ { MEDIUM_1536KBS, "reserved for 1536 kbit/s unrestricted"},
+ { MEDIUM_1920KBS, "reserved for 1920 kbit/s unrestricted"},
+ { 0, NULL}};
+
+
+/* Definitions for Called and Calling Party number */
+#define ISUP_ODD_EVEN_MASK 0x80
+#define ISUP_NATURE_OF_ADDRESS_IND_MASK 0x7F
+#define ISUP_INN_MASK 0x80
+#define ISUP_NI_MASK 0x80
+#define ISUP_NUMBERING_PLAN_IND_MASK 0x70
+#define ISUP_ADDRESS_PRESENTATION_RESTR_IND_MASK 0x0C
+#define ISUP_SCREENING_IND_MASK 0x03
+#define ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK 0x0F
+#define ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK 0xF0
+
+static const true_false_string isup_odd_even_ind_value = {
+ "odd number of address signals",
+ "even number of address signals"
+};
+
+#define ISUP_CALLED_PARTY_NATURE_SUBSCRIBER_NR 1
+#define ISUP_CALLED_PARTY_NATURE_UNKNOWN 2
+#define ISUP_CALLED_PARTY_NATURE_NATIONAL_NR 3
+#define ISUP_CALLED_PARTY_NATURE_INTERNATNL_NR 4
+#define ISUP_CALLED_PARTY_NATURE_NETW_SPEC_NR 5
+static const value_string isup_called_party_nature_of_address_ind_value[] = {
+ { ISUP_CALLED_PARTY_NATURE_SUBSCRIBER_NR, "subscriber number (national use)"},
+ { ISUP_CALLED_PARTY_NATURE_UNKNOWN, "unknown (national use)"},
+ { ISUP_CALLED_PARTY_NATURE_NATIONAL_NR, "national (significant) number"},
+ { ISUP_CALLED_PARTY_NATURE_INTERNATNL_NR, "international number"},
+ { ISUP_CALLED_PARTY_NATURE_NETW_SPEC_NR, "network-specific number (national use)"},
+ { 0, NULL}};
+
+static const value_string isup_calling_party_nature_of_address_ind_value[] = {
+ { ISUP_CALLED_PARTY_NATURE_SUBSCRIBER_NR, "subscriber number (national use)"},
+ { ISUP_CALLED_PARTY_NATURE_UNKNOWN, "unknown (national use)"},
+ { ISUP_CALLED_PARTY_NATURE_NATIONAL_NR, "national (significant) number"},
+ { ISUP_CALLED_PARTY_NATURE_INTERNATNL_NR, "international number"},
+ { 0, NULL}};
+
+static const true_false_string isup_INN_ind_value = {
+ "routing to internal network number not allowed",
+ "routing to internal network number allowed "
+};
+static const true_false_string isup_NI_ind_value = {
+ "incomplete",
+ "complete"
+};
+
+#define ISDN_NUMBERING_PLAN 1
+#define DATA_NUMBERING_PLAN 3
+#define TELEX_NUMBERING_PLAN 4
+static const value_string isup_numbering_plan_ind_value[] = {
+ { ISDN_NUMBERING_PLAN, "ISDN (Telephony) numbering plan"},
+ { DATA_NUMBERING_PLAN, "Data numbering plan (national use)"},
+ { TELEX_NUMBERING_PLAN, "Telex numbering plan (national use)"},
+ { 5, "Reserved for national use"},
+ { 6, "Reserved for national use"},
+ { 0, NULL}};
+
+#define ADDRESS_PRESETATION_ALLOWED 0
+#define ADDRESS_PRESETATION_RESTRICTED 1
+#define ADDRESS_NOT_AVAILABLE 2
+static const value_string isup_address_presentation_restricted_ind_value[] = {
+ { ADDRESS_PRESETATION_ALLOWED, "presentation allowed"},
+ { ADDRESS_PRESETATION_RESTRICTED, "presentation restricted"},
+ { ADDRESS_NOT_AVAILABLE, "address not availabe (national use)"},
+ { 3, "spare"},
+ { 0, NULL}};
+
+static const value_string isup_screening_ind_value[] = {
+ { 0, "reserved"},
+ { 1, "user provided, verified and passed"},
+ { 2, "reserved"},
+ { 3, "network provided"},
+ { 0, NULL}};
+
+static const value_string isup_screening_ind_enhanced_value[] = {
+ { 0, "user provided, not verified"},
+ { 1, "user provided, verified and passed"},
+ { 2, "user provided, verified and failed"},
+ { 3, "network provided"},
+ { 0, NULL}};
+
+static const value_string isup_called_party_address_digit_value[] = {
+ { 0, "0"},
+ { 1, "1"},
+ { 2, "2"},
+ { 3, "3"},
+ { 4, "4"},
+ { 5, "5"},
+ { 6, "6"},
+ { 7, "7"},
+ { 8, "8"},
+ { 9, "9"},
+ { 10, "spare"},
+ { 11, "code 11 "},
+ { 12, "code 12"},
+ { 15, "Stop sending"},
+ { 0, NULL}};
+
+static const value_string isup_calling_party_address_digit_value[] = {
+ { 0, "0"},
+ { 1, "1"},
+ { 2, "2"},
+ { 3, "3"},
+ { 4, "4"},
+ { 5, "5"},
+ { 6, "6"},
+ { 7, "7"},
+ { 8, "8"},
+ { 9, "9"},
+ { 10, "spare"},
+ { 11, "code 11 "},
+ { 12, "code 12"},
+ { 15, "spare"},
+ { 0, NULL}};
+
+/*End of Called/Calling party address definitions */
+
+
+static const true_false_string isup_calling_party_address_request_ind_value = {
+ "calling party address requested",
+ "calling party address not requested"
+};
+static const true_false_string isup_holding_ind_value = {
+ "holding requested",
+ "holding not requested"
+};
+static const true_false_string isup_calling_partys_category_request_ind_value = {
+ "Calling Party's category requested",
+ "Calling Party's category not requested",
+};
+static const true_false_string isup_charge_information_request_ind_value = {
+ "Charge Information requested",
+ "Charge Information not requested"
+};
+static const true_false_string isup_malicious_call_identification_request_ind_value = {
+ "Malicious call identification requested",
+ "Malicious call identification not requested"
+};
+
+#define CALLING_PARTY_ADDRESS_NOT_INCLUDED 0
+#define CALLING_PARTY_ADDRESS_NOT_AVAILABLE 1
+#define CALLING_PARTY_ADDRESS_INCLUDED 3
+static const value_string isup_calling_party_address_response_ind_value[] = {
+ { CALLING_PARTY_ADDRESS_NOT_INCLUDED, "Calling party address not included"},
+ { CALLING_PARTY_ADDRESS_NOT_AVAILABLE,"Calling party address not available"},
+ { 4, "spare"},
+ { CALLING_PARTY_ADDRESS_INCLUDED, "Calling party address included"},
+ { 0, NULL}};
+
+static const true_false_string isup_hold_provided_ind_value = {
+ "hold provided",
+ "hold not provided"
+};
+static const true_false_string isup_calling_partys_category_response_ind_value = {
+ "Calling Party's category included",
+ "Calling Party's category not included",
+};
+static const true_false_string isup_charge_information_response_ind_value = {
+ "Charge Information included",
+ "Charge Information not included"
+};
+static const true_false_string isup_solicited_information_ind_value = {
+ "unsolicited",
+ "solicited"
+};
+
+static const true_false_string isup_continuity_ind_value = {
+ "Continuity check successful",
+ "Continuity ckec failed"
+};
+
+#define CHARGE_NO_IND 0
+#define CHARGE_NO_CHARGE 1
+#define CHARGE_CHARGE 2
+static const value_string isup_charge_ind_value[] = {
+ { CHARGE_NO_IND, "No indication"},
+ { CHARGE_NO_CHARGE, "No charge"},
+ { CHARGE_CHARGE, "Charge"},
+ { 3, "spare"},
+ { 0, NULL}};
+
+#define CALLED_PARTYS_STATUS_NO_IND 0
+#define CALLED_PARTYS_STATUS_SUBSCR_FREE 1
+#define CALLED_PARTYS_STATUS_CONNECT_WHEN_FREE 2
+static const value_string isup_called_partys_status_ind_value[] = {
+ { CALLED_PARTYS_STATUS_NO_IND, "No indication"},
+ { CALLED_PARTYS_STATUS_SUBSCR_FREE, "Subscriber free"},
+ { CALLED_PARTYS_STATUS_CONNECT_WHEN_FREE, "Connect when free (national use)"},
+ { 3, "spare"},
+ { 0, NULL}};
+
+#define CALLED_PARTYS_CATEGORY_NO_IND 0
+#define CALLED_PARTYS_CATEGORY_ORDINARY_SUBSCR 1
+#define CALLED_PARTYS_CATEGORY_PAYPHONE 2
+static const value_string isup_called_partys_category_ind_value[] = {
+ { CALLED_PARTYS_CATEGORY_NO_IND, "No indication"},
+ { CALLED_PARTYS_CATEGORY_ORDINARY_SUBSCR, "Ordinary subscriber"},
+ { CALLED_PARTYS_CATEGORY_PAYPHONE, "Payphone"},
+ { 3, "spare"},
+ { 0, NULL}};
+
+static const true_false_string isup_ISDN_terminating_access_ind_value = {
+ "terminating access ISDN",
+ "terminating access non-ISDN"
+};
+
+static const true_false_string isup_suspend_resume_ind_value = {
+ "network initiated",
+ "ISDN subscriber initiated"
+};
+#define MAINTENANCE 0
+#define HARDWARE_FAILURE 1
+#define RES_FOR_NATNL_USE 2
+static const value_string isup_cgs_message_type_value[] = {
+ { MAINTENANCE, "maintenance oriented"},
+ { HARDWARE_FAILURE, "hardware failure oriented"},
+ { RES_FOR_NATNL_USE, "reserved for national use (ISUP'84)"},
+ { 3, "spare"},
+ { 0, NULL}};
+
+#define USER_TO_USER_SERVICE 2
+static const value_string isup_facility_ind_value[] = {
+ { USER_TO_USER_SERVICE, "user-to-user service"},
+ { 0, NULL}};
+
+#define MTC_BLCK_STATE_TRANSIENT 0
+#define MTC_BLCK_STATE_UNEQUIPPED 3
+static const value_string isup_mtc_blocking_state_DC00_value[] = {
+ { MTC_BLCK_STATE_TRANSIENT, "transient"},
+ { 1, "spare"},
+ { 2, "spare"},
+ { MTC_BLCK_STATE_UNEQUIPPED, "unequipped"},
+ { 0, NULL}};
+
+#define MTC_BLCK_NO_BLOCKING 0
+#define MTC_LOCALLY_BLOCKED 1
+#define MTC_REMOTELY_BLOCKED 2
+#define MTC_LOCAL_REMOTE_BLOCKED 3
+static const value_string isup_mtc_blocking_state_DCnot00_value[] = {
+ { MTC_BLCK_NO_BLOCKING, "no blocking (active)"},
+ { MTC_LOCALLY_BLOCKED, "locally blocked"},
+ { MTC_REMOTELY_BLOCKED, "remotely blocked"},
+ { MTC_LOCAL_REMOTE_BLOCKED, "locally and remotely blocked"},
+ { 0, NULL}};
+
+#define CALL_PROC_INCOMING_BUSY 1
+#define CALL_PROC_OUTGOING_BUSY 2
+#define CALL_PROC_IDLE 3
+static const value_string isup_call_processing_state_value[] = {
+ { CALL_PROC_INCOMING_BUSY, "circuit incoming busy"},
+ { CALL_PROC_OUTGOING_BUSY, "circuit outgoing busy"},
+ { CALL_PROC_IDLE, "idle"},
+ { 0, NULL}};
+
+#define HW_BLCK_NO_BLOCKING 0
+#define HW_LOCALLY_BLOCKED 1
+#define HW_REMOTELY_BLOCKED 2
+#define HW_LOCAL_REMOTE_BLOCKED 3
+static const value_string isup_HW_blocking_state_value[] = {
+ { HW_BLCK_NO_BLOCKING, "no blocking (active)"},
+ { HW_LOCALLY_BLOCKED, "locally blocked"},
+ { HW_REMOTELY_BLOCKED, "remotely blocked"},
+ { HW_LOCAL_REMOTE_BLOCKED, "locally and remotely blocked"},
+ { 0, NULL}};
+
+#define EVENT_ALERTING 1
+#define EVENT_PROGRESS 2
+#define EVENT_INBAND_INFO 3
+#define EVENT_ON_BUSY 4
+#define EVENT_ON_NO_REPLY 5
+#define EVENT_UNCONDITIONAL 6
+static const value_string isup_event_ind_value[] = {
+ /* according 3.21/Q.763 */
+ { EVENT_ALERTING, "ALERTING"},
+ { EVENT_PROGRESS, "PROGRESS"},
+ { EVENT_INBAND_INFO, "in-band information or an appropriate pattern is now available"},
+ { EVENT_ON_BUSY, "call forwarded on busy (national use)"},
+ { EVENT_ON_NO_REPLY, "call forwarded on no reply (national use)"},
+ { EVENT_UNCONDITIONAL,"call forwarded unconditional (national use)"},
+ { 0, NULL}};
+
+static const true_false_string isup_event_presentation_restricted_ind_value = {
+ /* according 3.21/Q.763 */
+ "presentation restricted",
+ "no indication"
+};
+#define CUG_NON_CUG_CALL 0
+#define CUG_CALL_OUTGOING_ACCESS_ALLOWED 2
+#define CUG_CALL_OUTGOING_ACCESS_NOT_ALLOWED 3
+static const value_string isup_CUG_call_ind_value[] = {
+ /* according 3.38/Q.763 */
+ { CUG_NON_CUG_CALL, "non-CUG call"},
+ { 1, "spare"},
+ { CUG_CALL_OUTGOING_ACCESS_ALLOWED, "closed user group call, outgoing access allowed"},
+ { CUG_CALL_OUTGOING_ACCESS_NOT_ALLOWED, "closed user group call, outgoing access not allowed"},
+ { 0, NULL}};
+
+
+static const true_false_string isup_simple_segmentation_ind_value = {
+ /* according 3.38/Q.763 */
+ "additional information will be sent in a segmentation message",
+ "no additional information will be sent"
+};
+
+static const true_false_string isup_connected_line_identity_request_ind_value = {
+ /* according 3.38/Q.763 */
+ "requested",
+ "not requested"
+};
+
+static const value_string isup_redirecting_ind_value[] = {
+ /* according 3.45/Q.763 */
+ { 0, "no redirection (national use)"},
+ { 1, "call rerouted (national use)"},
+ { 2, "call rerouted, all redirection information presentation restricted (national use)"},
+ { 3, "call diverted"},
+ { 4, "call diverted, all redirection information presentation restricted"},
+ { 5, "call rerouted, redirection number presentation restricted (national use)"},
+ { 6, "call diversion, redirection number presentation restricted (national use)"},
+ { 7, "spare"},
+ { 0, NULL}};
+
+static const value_string isup_original_redirection_reason_value[] = {
+ /* according 3.45/Q.763 */
+ { 0, "unknown/not available"},
+ { 1, "user busy (national use)"},
+ { 2, "no reply (national use)"},
+ { 3, "unconditional (national use)"},
+ { 0, NULL}};
+
+static const value_string isup_redirection_reason_value[] = {
+ /* according 3.45/Q.763 */
+ { 0, "unknown/not available"},
+ { 1, "user busy (national use)"},
+ { 2, "no reply (national use)"},
+ { 3, "unconditional (national use)"},
+ { 4, "deflection during alerting"},
+ { 5, "deflection immediate response"},
+ { 6, "mobile subscriber not reachable"},
+ { 0, NULL}};
+
+static const value_string isup_type_of_network_identification_value[] = {
+ /* according 3.53/Q.763 */
+ { 0, "CCITT/ITU-T-standardized identification"},
+ { 2, "national network identification"},
+ { 0, NULL}};
+
+static const value_string isup_network_identification_plan_value[] = {
+ /* according 3.53/Q.763 */
+ { 0, "if CCITT/ITU-T id - unknown"},
+ { 3, "if CCITT/ITU-T id - public data network id code (X.121)"},
+ { 6, "if CCITT/ITU-T id - public land Mobile Network id code (E.211)"},
+ { 0, NULL}};
+
+static const value_string isup_map_type_value[] = {
+ /* according 3.69/Q.763 */
+ { 1, "1544 kbit/s digital path map format (64 kbit/s base rate"},
+ { 2, "2048 kbit/s digital path map format (64 kbit/s base rate"},
+ { 0, NULL}};
+
+static const value_string isup_auto_congestion_level_value[] = {
+ /* according 3.4/Q.763 */
+ { 1, "Congestion level 1 exceeded"},
+ { 2, "Congestion level 2 exceeded"},
+ { 0, NULL}};
+
+static const true_false_string isup_inband_information_ind_value = {
+ /* according 3.37/Q.763 */
+ "in-band information or an appropirate pattern is now available",
+ "no indication"
+};
+static const true_false_string isup_call_diversion_may_occur_ind_value = {
+ /* according 3.37/Q.763 */
+ "call diversion may occur",
+ "no indication"
+};
+static const true_false_string isup_MLPP_user_ind_value = {
+ /* according 3.37/Q.763 */
+ "MLPP user",
+ "no indication"
+};
+
+static const true_false_string isup_access_delivery_ind_value = {
+ /* according 3.2/Q.763 */
+ "No set-up message generated",
+ "Set-up message generated"
+};
+
+static const value_string isup_loop_prevention_response_ind_value[] = {
+ /* according 3.67/Q.763 */
+ { 0, "insufficient information"},
+ { 1, "no loop exists"},
+ { 2, "simultaneous transfer"},
+ { 0, NULL}};
+
+static const true_false_string isup_temporary_alternative_routing_ind_value = {
+ /* according 3.68/Q.763 */
+ "TAR controlled call",
+ "no indication"
+};
+static const true_false_string isup_extension_ind_value = {
+ /* according 3.68/Q.763 */
+ "last octet",
+ "information continues through the next octet"
+};
+
+
+
+static const value_string isup_call_to_be_diverted_ind_value[] = {
+ /* according 3.72/Q.763 */
+ { 0, "no indication"},
+ { 1, "call diversion allowed"},
+ { 2, "call diversion not allowed"},
+ { 3, "spare"},
+ { 0, NULL}};
+
+static const value_string isup_call_to_be_offered_ind_value[] = {
+ /* according 3.72/Q.763 */
+ { 0, "no indication"},
+ { 1, "call offering not allowed"},
+ { 2, "call offering allowed"},
+ { 3, "spare"},
+ { 0, NULL}};
+
+static const value_string isup_conference_acceptance_ind_value[] = {
+ /* according 3.76/Q.763 */
+ { 0, "no indication"},
+ { 1, "accept conference request"},
+ { 2, "reject conference request"},
+ { 3, "spare"},
+ { 0, NULL}};
+
+static const value_string isup_application_transport_parameter_value[] = {
+ /* according 3.82/Q.763 */
+ { 0, "Unidentified Context and Error Handling (UCEH) ASE"},
+ { 1, "PSS1 ASE (VPN)"},
+ { 2, "spare"},
+ { 3, "Charging ASE"},
+ { 4, "GAT"},
+ { 5, "BAT ASE"},
+ { 6, "Enhanced Unidentified Context and Error Handling ASE (EUCEH ASE)"},
+ { 0, NULL}};
+
+static const true_false_string isup_Release_call_indicator_value = {
+ "release call",
+ "do not release call"
+};
+
+static const true_false_string isup_Send_notification_ind_value = {
+ "send notification",
+ "do not send notification"
+};
+static const value_string isup_APM_segmentation_ind_value[] = {
+
+ { 0x00, "final segment"},
+ { 0x01, "number of following segments"},
+ { 0x02, "number of following segments"},
+ { 0x03, "number of following segments"},
+ { 0x04, "number of following segments"},
+ { 0x05, "number of following segments"},
+ { 0x06, "number of following segments"},
+ { 0x07, "number of following segments"},
+ { 0x08, "number of following segments"},
+ { 0x09, "number of following segments"},
+ { 0, NULL}};
+
+static const true_false_string isup_Sequence_ind_value = {
+ "new sequence",
+ "subsequent segment to first segment"
+};
+
+
+/* Generalized bit masks for 8 and 16 bits fields */
+#define A_8BIT_MASK 0x01
+#define B_8BIT_MASK 0x02
+#define C_8BIT_MASK 0x04
+#define D_8BIT_MASK 0x08
+#define E_8BIT_MASK 0x10
+#define F_8BIT_MASK 0x20
+#define G_8BIT_MASK 0x40
+#define H_8BIT_MASK 0x80
+
+#define BA_8BIT_MASK 0x03
+#define CB_8BIT_MASK 0x06
+#define DC_8BIT_MASK 0x0C
+#define ED_8BIT_MASK 0x18
+#define FE_8BIT_MASK 0x30
+#define GF_8BIT_MASK 0x60
+#define HG_8BIT_MASK 0xC0
+#define GFE_8BIT_MASK 0x70
+#define DCBA_8BIT_MASK 0x0F
+#define EDCBA_8BIT_MASK 0x1F
+#define HGFE_8BIT_MASK 0xF0
+#define GFEDCBA_8BIT_MASK 0x7F
+#define FEDCBA_8BIT_MASK 0x3F
+
+#define A_16BIT_MASK 0x0100
+#define B_16BIT_MASK 0x0200
+#define C_16BIT_MASK 0x0400
+#define D_16BIT_MASK 0x0800
+#define E_16BIT_MASK 0x1000
+#define F_16BIT_MASK 0x2000
+#define G_16BIT_MASK 0x4000
+#define H_16BIT_MASK 0x8000
+#define I_16BIT_MASK 0x0001
+#define J_16BIT_MASK 0x0002
+#define K_16BIT_MASK 0x0004
+#define L_16BIT_MASK 0x0008
+#define M_16BIT_MASK 0x0010
+#define N_16BIT_MASK 0x0020
+#define O_16BIT_MASK 0x0040
+#define P_16BIT_MASK 0x0080
+
+#define BA_16BIT_MASK 0x0300
+#define CB_16BIT_MASK 0x0600
+#define DC_16BIT_MASK 0x0C00
+#define FE_16BIT_MASK 0x3000
+#define HG_16BIT_MASK 0xC000
+#define KJ_16BIT_MASK 0x0006
+#define PO_16BIT_MASK 0x00C0
+
+#define CBA_16BIT_MASK 0x0700
+#define KJI_16BIT_MASK 0x0007
+#define HGFE_16BIT_MASK 0xF000
+#define PONM_16BIT_MASK 0x00F0
+
+/* Initialize the protocol and registered fields */
+static int proto_isup = -1;
+static int proto_bicc = -1;
+static module_t *isup_module;
+
+static gboolean isup_show_cic_in_info = TRUE;
+
+static int hf_isup_cic = -1;
+static int hf_bicc_cic = -1;
+
+static int isup_tap = -1;
+
+static int hf_isup_message_type = -1;
+static int hf_isup_parameter_type = -1;
+static int hf_isup_parameter_length = -1;
+static int hf_isup_mandatory_variable_parameter_pointer = -1;
+static int hf_isup_pointer_to_start_of_optional_part = -1;
+
+static int hf_isup_satellite_indicator = -1;
+static int hf_isup_continuity_check_indicator = -1;
+static int hf_isup_echo_control_device_indicator = -1;
+
+static int hf_isup_forw_call_natnl_inatnl_call_indicator = -1;
+static int hf_isup_forw_call_end_to_end_method_indicator = -1;
+static int hf_isup_forw_call_interworking_indicator = -1;
+static int hf_isup_forw_call_end_to_end_info_indicator = -1;
+static int hf_isup_forw_call_isdn_user_part_indicator = -1;
+static int hf_isup_forw_call_preferences_indicator = -1;
+static int hf_isup_forw_call_isdn_access_indicator = -1;
+static int hf_isup_forw_call_sccp_method_indicator = -1;
+
+static int hf_isup_calling_partys_category = -1;
+
+static int hf_isup_transmission_medium_requirement = -1;
+
+static int hf_isup_odd_even_indicator = -1;
+static int hf_isup_called_party_nature_of_address_indicator = -1;
+static int hf_isup_calling_party_nature_of_address_indicator = -1;
+static int hf_isup_inn_indicator = -1;
+static int hf_isup_ni_indicator = -1;
+static int hf_isup_numbering_plan_indicator = -1;
+static int hf_isup_address_presentation_restricted_indicator = -1;
+static int hf_isup_screening_indicator = -1;
+static int hf_isup_screening_indicator_enhanced = -1;
+static int hf_isup_called_party_odd_address_signal_digit = -1;
+static int hf_isup_calling_party_odd_address_signal_digit = -1;
+static int hf_isup_called_party_even_address_signal_digit = -1;
+static int hf_isup_calling_party_even_address_signal_digit = -1;
+
+static int hf_isup_OECD_inf_ind = -1;
+static int hf_isup_IECD_inf_ind = -1;
+static int hf_isup_OECD_req_ind = -1;
+static int hf_isup_IECD_req_ind = -1;
+
+static int hf_isup_calling_party_address_request_indicator = -1;
+static int hf_isup_info_req_holding_indicator = -1;
+static int hf_isup_calling_partys_category_request_indicator = -1;
+static int hf_isup_charge_information_request_indicator = -1;
+static int hf_isup_malicious_call_identification_request_indicator = -1;
+
+static int hf_isup_calling_party_address_response_indicator = -1;
+static int hf_isup_hold_provided_indicator = -1;
+static int hf_isup_calling_partys_category_response_indicator = -1;
+static int hf_isup_charge_information_response_indicator = -1;
+static int hf_isup_solicited_indicator = -1;
+
+static int hf_isup_continuity_indicator = -1;
+
+static int hf_isup_backw_call_charge_ind = -1 ;
+static int hf_isup_backw_call_called_partys_status_ind = -1;
+static int hf_isup_backw_call_called_partys_category_ind = -1;
+static int hf_isup_backw_call_end_to_end_method_ind = -1;
+static int hf_isup_backw_call_interworking_ind = -1;
+static int hf_isup_backw_call_end_to_end_info_ind = -1;
+static int hf_isup_backw_call_isdn_user_part_ind = -1;
+static int hf_isup_backw_call_holding_ind = -1;
+static int hf_isup_backw_call_isdn_access_ind = -1;
+static int hf_isup_backw_call_echo_control_device_ind = -1;
+static int hf_isup_backw_call_sccp_method_ind = -1;
+
+static int hf_isup_cause_indicator = -1;
+
+static int hf_isup_suspend_resume_indicator = -1;
+
+static int hf_isup_range_indicator = -1;
+static int hf_isup_cgs_message_type = -1;
+
+static int hf_isup_mtc_blocking_state1 = -1;
+static int hf_isup_mtc_blocking_state2 = -1;
+static int hf_isup_call_proc_state = -1;
+static int hf_isup_hw_blocking_state = -1;
+
+static int hf_isup_event_ind = -1;
+static int hf_isup_event_presentation_restricted_ind = -1;
+
+static int hf_isup_cug_call_ind = -1;
+static int hf_isup_simple_segmentation_ind = -1;
+static int hf_isup_connected_line_identity_request_ind = -1;
+
+static int hf_isup_redirecting_ind = -1;
+static int hf_isup_original_redirection_reason = -1;
+static int hf_isup_redirection_counter = -1;
+static int hf_isup_redirection_reason = -1;
+
+static int hf_isup_type_of_network_identification = -1;
+static int hf_isup_network_identification_plan = -1;
+
+static int hf_isup_map_type = -1;
+
+static int hf_isup_automatic_congestion_level = -1;
+
+static int hf_isup_inband_information_ind = -1;
+static int hf_isup_call_diversion_may_occur_ind = -1;
+static int hf_isup_mlpp_user_ind = -1;
+
+static int hf_isup_UUI_type = -1;
+static int hf_isup_UUI_req_service1 = -1;
+static int hf_isup_UUI_req_service2 = -1;
+static int hf_isup_UUI_req_service3 = -1;
+static int hf_isup_UUI_res_service1 = -1;
+static int hf_isup_UUI_res_service2 = -1;
+static int hf_isup_UUI_res_service3 = -1;
+static int hf_isup_UUI_network_discard_ind = -1;
+static int hf_isup_access_delivery_ind = -1;
+
+static int hf_isup_transmission_medium_requirement_prime = -1;
+
+static int hf_isup_loop_prevention_response_ind = -1;
+
+static int hf_isup_temporary_alternative_routing_ind = -1;
+static int hf_isup_extension_ind = -1;
+
+static int hf_isup_call_to_be_diverted_ind = -1;
+
+static int hf_isup_call_to_be_offered_ind = -1;
+
+static int hf_isup_conference_acceptance_ind = -1;
+
+static int hf_isup_transit_at_intermediate_exchange_ind = -1;
+static int hf_isup_Release_call_ind = -1;
+static int hf_isup_Send_notification_ind = -1;
+static int hf_isup_Discard_message_ind_value = -1;
+static int hf_isup_Discard_parameter_ind = -1;
+static int hf_isup_Pass_on_not_possible_indicator = -1;
+static int hf_isup_pass_on_not_possible_indicator2 = -1;
+static int hf_isup_Broadband_narrowband_interworking_ind = -1;
+static int hf_isup_Broadband_narrowband_interworking_ind2 = -1;
+
+static int hf_isup_app_cont_ident = -1;
+static int hf_isup_app_Send_notification_ind = -1;
+static int hf_isup_apm_segmentation_ind = -1;
+static int hf_isup_apm_si_ind = -1;
+static int hf_isup_app_Release_call_ind = -1;
+static int hf_length_indicator = -1;
+static int hf_afi = -1;
+static int hf_bat_ase_identifier = -1;
+static int hf_Action_Indicator = -1;
+
+static int hf_Instruction_ind_for_general_action = -1;
+
+static int hf_Send_notification_ind_for_general_action = -1;
+
+static int hf_Instruction_ind_for_pass_on_not_possible = -1;
+
+static int hf_Send_notification_ind_for_pass_on_not_possible = -1;
+static int hf_BCTP_Version_Indicator = -1;
+static int hf_Tunnelled_Protocol_Indicator = -1;
+static int hf_TPEI = -1;
+static int hf_BVEI = -1;
+static int hf_bncid = -1;
+static int hf_bat_ase_biwfa = -1;
+static int hf_characteristics = -1;
+
+static int hf_Organization_Identifier = -1;
+static int hf_codec_type = -1;
+static int hf_etsi_codec_type = -1;
+static int hf_bearer_control_tunneling = -1;
+static int hf_Local_BCU_ID = -1;
+static int hf_late_cut_trough_cap_ind = -1;
+static int hf_bat_ase_signal = -1;
+static int hf_bat_ase_duration = -1;
+static int hf_bat_ase_bearer_redir_ind = -1;
+static int hf_BAT_ASE_Comp_Report_Reason = -1;
+static int hf_BAT_ASE_Comp_Report_ident = -1;
+static int hf_BAT_ASE_Comp_Report_diagnostic = -1;
+static int hf_nsap_ipv4_addr = -1;
+static int hf_nsap_ipv6_addr = -1;
+static int hf_iana_icp = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_isup = -1;
+static gint ett_isup_parameter = -1;
+static gint ett_isup_address_digits = -1;
+static gint ett_isup_pass_along_message = -1;
+static gint ett_isup_circuit_state_ind = -1;
+static gint ett_bat_ase = -1;
+static gint ett_bicc = -1;
+static gint ett_bat_ase_element = -1;
+static gint ett_bat_ase_iwfa = -1;
+
+
+
+static dissector_handle_t sdp_handle = NULL;
+static dissector_handle_t q931_ie_handle = NULL;
+
+/* ------------------------------------------------------------------
+ Mapping number to ASCII-character
+ ------------------------------------------------------------------ */
+char number_to_char(int number)
+{
+ if (number < 10)
+ return ((char) number + ASCII_NUMBER_DELTA);
+ else
+ return ((char) number + ASCII_LETTER_DELTA);
+}
+
+
+/* ------------------------------------------------------------------ */
+/* Dissectors for all used parameter types */
+/* ------------------------------------------------------------------ */
+/* argument tvbuff_t contains only parameter-specific length */
+/* length indicator is already dissected in dissect_isup_message() or */
+/* dissect_isup_optional_parameter() */
+/* ------------------------------------------------------------------ */
+
+/* ------------------------------------------------------------------
+ Dissector Parameter nature of connection flags
+ */
+static void
+dissect_isup_nature_of_connection_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 nature_of_connection_ind;
+
+ nature_of_connection_ind = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_satellite_indicator, parameter_tvb, 0,NATURE_OF_CONNECTION_IND_LENGTH, nature_of_connection_ind);
+ proto_tree_add_uint(parameter_tree, hf_isup_continuity_check_indicator, parameter_tvb, 0,NATURE_OF_CONNECTION_IND_LENGTH, nature_of_connection_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_echo_control_device_indicator, parameter_tvb, 0, NATURE_OF_CONNECTION_IND_LENGTH, nature_of_connection_ind);
+
+ proto_item_set_text(parameter_item, "Nature of Connection Indicators: 0x%x", nature_of_connection_ind);
+}
+
+/* ------------------------------------------------------------------
+ Dissector Parameter Forward Call Indicators
+ */
+static void
+dissect_isup_forward_call_indicators_parameter(tvbuff_t *parameter_tvb,proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 forward_call_ind;
+
+ forward_call_ind = tvb_get_ntohs(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_forw_call_natnl_inatnl_call_indicator, parameter_tvb, 0, FORWARD_CALL_IND_LENGTH, forward_call_ind);
+ proto_tree_add_uint(parameter_tree, hf_isup_forw_call_end_to_end_method_indicator, parameter_tvb, 0, FORWARD_CALL_IND_LENGTH, forward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_forw_call_interworking_indicator, parameter_tvb, 0, FORWARD_CALL_IND_LENGTH, forward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_forw_call_end_to_end_info_indicator, parameter_tvb, 0, FORWARD_CALL_IND_LENGTH, forward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_forw_call_isdn_user_part_indicator, parameter_tvb, 0, FORWARD_CALL_IND_LENGTH, forward_call_ind);
+ proto_tree_add_uint(parameter_tree, hf_isup_forw_call_preferences_indicator, parameter_tvb, 0, FORWARD_CALL_IND_LENGTH, forward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_forw_call_isdn_access_indicator, parameter_tvb, 0, FORWARD_CALL_IND_LENGTH, forward_call_ind);
+ proto_tree_add_uint(parameter_tree, hf_isup_forw_call_sccp_method_indicator, parameter_tvb, 0, FORWARD_CALL_IND_LENGTH, forward_call_ind);
+
+ proto_item_set_text(parameter_item, "Forward Call Indicators: 0x%x", forward_call_ind );
+}
+
+/* ------------------------------------------------------------------
+ Dissector Parameter Calling Party's Category
+ */
+static void
+dissect_isup_calling_partys_category_parameter(tvbuff_t *parameter_tvb,proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 calling_partys_category;
+
+ calling_partys_category = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_partys_category, parameter_tvb, 0, CALLING_PRTYS_CATEGORY_LENGTH, calling_partys_category);
+
+ proto_item_set_text(parameter_item, "Calling Party's category: 0x%x (%s)", calling_partys_category, val_to_str(calling_partys_category, isup_calling_partys_category_value, "reserved/spare"));
+}
+
+
+/* ------------------------------------------------------------------
+ Dissector Parameter Transmission medium requirement
+ */
+static void
+dissect_isup_transmission_medium_requirement_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 transmission_medium_requirement;
+
+ transmission_medium_requirement = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_transmission_medium_requirement, parameter_tvb, 0, TRANSMISSION_MEDIUM_REQUIREMENT_LENGTH,transmission_medium_requirement);
+
+ proto_item_set_text(parameter_item, "Transmission medium requirement: %u (%s)", transmission_medium_requirement, val_to_str(transmission_medium_requirement, isup_transmission_medium_requirement_value, "spare"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Called party number
+ */
+static void
+dissect_isup_called_party_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char called_number[MAXLENGTH]="";
+ e164_info_t e164_info;
+ gint number_plan;
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_called_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 1);
+ number_plan = (indicators2 & 0x70)>> 4;
+ proto_tree_add_boolean(parameter_tree, hf_isup_inn_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2);
+ offset = 2;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Called Party Number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ while((length = tvb_reported_length_remaining(parameter_tvb, offset)) > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_called_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ called_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_called_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ called_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_called_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ called_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ called_number[i++] = '\0';
+ if ( number_plan == 1 ) {
+ e164_info.e164_number_type = CALLED_PARTY_NUMBER;
+ e164_info.nature_of_address = indicators1 & 0x7f;
+ e164_info.E164_number_str = called_number;
+ e164_info.E164_number_length = i - 1;
+ dissect_e164_number(parameter_tvb, address_digits_tree, 2,
+ (offset - 2), e164_info);
+ }
+ proto_item_set_text(address_digits_item, "Called Party Number: %s", called_number);
+ proto_item_set_text(parameter_item, "Called Party Number: %s", called_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Subsequent number
+ */
+static void
+dissect_isup_subsequent_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char called_number[MAXLENGTH]="";
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ offset = 1;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Subsequent Number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ while((length = tvb_reported_length_remaining(parameter_tvb, offset)) > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_called_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ called_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_called_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ called_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_called_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ called_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ called_number[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Subsequent Number: %s", called_number);
+ proto_item_set_text(parameter_item, "Subsequent Number: %s", called_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Information Request Indicators
+ */
+static void
+dissect_isup_information_request_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 information_request_indicators;
+
+ information_request_indicators = tvb_get_ntohs(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_calling_party_address_request_indicator, parameter_tvb, 0, INFO_REQUEST_IND_LENGTH, information_request_indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_info_req_holding_indicator, parameter_tvb, 0, INFO_REQUEST_IND_LENGTH, information_request_indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_calling_partys_category_request_indicator, parameter_tvb, 0, INFO_REQUEST_IND_LENGTH, information_request_indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_charge_information_request_indicator, parameter_tvb, 0, INFO_REQUEST_IND_LENGTH, information_request_indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_malicious_call_identification_request_indicator, parameter_tvb, 0, INFO_REQUEST_IND_LENGTH, information_request_indicators);
+
+
+ proto_item_set_text(parameter_item, "Information request indicators: 0x%x", information_request_indicators);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Information Indicators
+ */
+static void
+dissect_isup_information_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 information_indicators;
+
+ information_indicators = tvb_get_ntohs(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_party_address_response_indicator, parameter_tvb, 0, INFO_IND_LENGTH, information_indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_hold_provided_indicator, parameter_tvb, 0, INFO_IND_LENGTH, information_indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_calling_partys_category_response_indicator, parameter_tvb, 0, INFO_IND_LENGTH, information_indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_charge_information_response_indicator, parameter_tvb, 0, INFO_IND_LENGTH, information_indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_solicited_indicator, parameter_tvb, 0, INFO_IND_LENGTH, information_indicators);
+
+
+ proto_item_set_text(parameter_item, "Information indicators: 0x%x", information_indicators);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Continuity Indicators
+ */
+static void
+dissect_isup_continuity_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 continuity_indicators;
+
+ continuity_indicators = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_continuity_indicator, parameter_tvb, 0, CONTINUITY_IND_LENGTH, continuity_indicators);
+
+ proto_item_set_text(parameter_item, "Continuity indicators: 0x%x", continuity_indicators);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Backward Call Indicators
+ */
+static void
+dissect_isup_backward_call_indicators_parameter(tvbuff_t *parameter_tvb,proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 backward_call_ind;
+
+ backward_call_ind = tvb_get_ntohs(parameter_tvb, 0);
+
+
+ proto_tree_add_uint(parameter_tree, hf_isup_backw_call_charge_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_uint(parameter_tree, hf_isup_backw_call_called_partys_status_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_uint(parameter_tree, hf_isup_backw_call_called_partys_category_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_uint(parameter_tree, hf_isup_backw_call_end_to_end_method_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_backw_call_interworking_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_backw_call_end_to_end_info_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_backw_call_isdn_user_part_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_backw_call_holding_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_backw_call_isdn_access_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_backw_call_echo_control_device_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+ proto_tree_add_uint(parameter_tree, hf_isup_backw_call_sccp_method_ind, parameter_tvb, 0, BACKWARD_CALL_IND_LENGTH, backward_call_ind);
+
+ proto_item_set_text(parameter_item, "Backward Call Indicators: 0x%x", backward_call_ind);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Cause Indicators - no detailed dissection since defined in Rec. Q.850
+ */
+
+/*
+ * Cause codes for Cause.
+ * The decoding of cause indicators parameter field are defined in ITU-T
+ * Recommendation Q.850; those are different from the ones in the Q.931
+ * dissector, as that has some values not specified by the standard but
+ * that appear to be used for purposes other than the ones in Q.850.
+ */
+static const value_string q850_cause_code_vals[] = {
+ { 0x00, "Valid cause code not yet received" },
+ { 0x01, "Unallocated (unassigned) number" },
+ { 0x02, "No route to specified transit network" },
+ { 0x03, "No route to destination" },
+ { 0x04, "Send special information tone" },
+ { 0x05, "Misdialled trunk prefix" },
+ { 0x06, "Channel unacceptable" },
+ { 0x07, "Call awarded and being delivered in an established channel" },
+ { 0x08, "Preemption" },
+ { 0x09, "Preemption - circuit reserved for reuse" },
+ { 0x0E, "QoR: ported number" },
+ { 0x10, "Normal call clearing" },
+ { 0x11, "User busy" },
+ { 0x12, "No user responding" },
+ { 0x13, "No answer from user (user alerted)" },
+ { 0x14, "Subscriber absent" },
+ { 0x15, "Call rejected" },
+ { 0x16, "Number changed" },
+ { 0x17, "Redirection to new destination" },
+ { 0x18, "Call rejected due to feature at the destination" },
+ { 0x19, "Exchange routing error" },
+ { 0x1A, "Non-selected user clearing" },
+ { 0x1B, "Destination out of order" },
+ { 0x1C, "Invalid number format (address incomplete)" },
+ { 0x1D, "Facility rejected" },
+ { 0x1E, "Response to STATUS ENQUIRY" },
+ { 0x1F, "Normal unspecified" },
+ { 0x21, "Circuit out of order" },
+ { 0x22, "No circuit/channel available" },
+ { 0x26, "Network out of order" },
+ { 0x27, "Permanent frame mode connection out of service" },
+ { 0x28, "Permanent frame mode connection operational" },
+ { 0x29, "Temporary failure" },
+ { 0x2A, "Switching equipment congestion" },
+ { 0x2B, "Access information discarded" },
+ { 0x2C, "Requested circuit/channel not available" },
+ { 0x2E, "Precedence call blocked" },
+ { 0x2F, "Resources unavailable, unspecified" },
+ { 0x31, "Quality of service unavailable" },
+ { 0x32, "Requested facility not subscribed" },
+ { 0x35, "Outgoing calls barred within CUG" },
+ { 0x37, "Incoming calls barred within CUG" },
+ { 0x38, "Call waiting not subscribed" },
+ { 0x39, "Bearer capability not authorized" },
+ { 0x3A, "Bearer capability not presently available" },
+ { 0x3E, "Inconsistency in designated outgoing access information and subscriber class" },
+ { 0x3F, "Service or option not available, unspecified" },
+ { 0x41, "Bearer capability not implemented" },
+ { 0x42, "Channel type not implemented" },
+ { 0x45, "Requested facility not implemented" },
+ { 0x46, "Only restricted digital information bearer capability is available" },
+ { 0x4F, "Service or option not implemented, unspecified" },
+ { 0x51, "Invalid call reference value" },
+ { 0x52, "Identified channel does not exist" },
+ { 0x53, "Call identity does not exist for suspended call" },
+ { 0x54, "Call identity in use" },
+ { 0x55, "No call suspended" },
+ { 0x56, "Call having the requested call identity has been cleared" },
+ { 0x57, "Called user not member of CUG" },
+ { 0x58, "Incompatible destination" },
+ { 0x5A, "Non-existing CUG" },
+ { 0x5B, "Invalid transit network selection (national use)" },
+ { 0x5F, "Invalid message, unspecified" },
+ { 0x60, "Mandatory information element is missing" },
+ { 0x61, "Message type non-existent or not implemented" },
+ { 0x62, "Message not compatible with call state or message type non-existent or not implemented" },
+ { 0x63, "Information element nonexistant or not implemented" },
+ { 0x64, "Invalid information element contents" },
+ { 0x65, "Message not compatible with call state" },
+ { 0x66, "Recovery on timer expiry" },
+ { 0x67, "Parameter non-existent or not implemented - passed on" },
+ { 0x6E, "Message with unrecognized parameter discarded" },
+ { 0x6F, "Protocol error, unspecified" },
+ { 0x7F, "Internetworking, unspecified" },
+ { 0, NULL }
+};
+
+
+
+
+static void
+dissect_isup_cause_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_reported_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb,0, -1, "Cause indicators (-> Q.850)");
+ dissect_q931_cause_ie(parameter_tvb,0,length,
+ parameter_tree,
+ hf_isup_cause_indicator);
+ proto_item_set_text(parameter_item, "Cause indicators, see Q.850 (%u byte%s length)", length , plurality(length, "", "s"));
+}
+
+/* ------------------------------------------------------------------
+ Dissector Parameter Suspend/Resume Indicators
+ */
+static void
+dissect_isup_suspend_resume_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 indicators;
+
+ indicators = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_suspend_resume_indicator, parameter_tvb, 0, SUSPEND_RESUME_IND_LENGTH, indicators);
+
+ proto_item_set_text(parameter_item, "Suspend/Resume indicator: 0x%x", indicators);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Range and Status Indicators
+ */
+static void
+dissect_isup_range_and_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 range, actual_status_length;
+
+ range = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_range_indicator, parameter_tvb, 0, RANGE_LENGTH, range, "Range: %u", range);
+ actual_status_length = tvb_reported_length_remaining(parameter_tvb, RANGE_LENGTH);
+ if (actual_status_length > 0)
+ proto_tree_add_text(parameter_tree, parameter_tvb , RANGE_LENGTH, -1, "Status subfield");
+ else
+ proto_tree_add_text(parameter_tree, parameter_tvb , 0, 0, "Status subfield is not present with this message type");
+
+
+ proto_item_set_text(parameter_item, "Range (%u) and status", range);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Circuit group supervision message type
+ */
+static void
+dissect_isup_circuit_group_supervision_message_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 cgs_message_type;
+
+ cgs_message_type = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_cgs_message_type, parameter_tvb, 0, CIRC_GRP_SV_MSG_TYPE_LENGTH, cgs_message_type);
+
+ proto_item_set_text(parameter_item, "Circuit group supervision message type: %s (%u)" ,val_to_str(cgs_message_type, isup_cgs_message_type_value,"unknown"), cgs_message_type);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Facility indicator parameter
+ */
+static void
+dissect_isup_facility_ind_parameter(tvbuff_t *parameter_tvb, proto_item *parameter_item)
+{
+ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+
+ proto_item_set_text(parameter_item, "Facility indicator: %s (%u)" ,val_to_str(indicator, isup_facility_ind_value,"spare"), indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Circuit state indicator
+ */
+static void
+dissect_isup_circuit_state_ind_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *circuit_state_item;
+ proto_tree *circuit_state_tree;
+ guint8 circuit_state;
+ gint offset=0;
+ gint i=0;
+ gint length;
+
+ while((length = tvb_reported_length_remaining(parameter_tvb, offset)) > 0){
+ circuit_state_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Circuit# CIC+%u state", i);
+ circuit_state_tree = proto_item_add_subtree(circuit_state_item, ett_isup_circuit_state_ind);
+ circuit_state = tvb_get_guint8(parameter_tvb, offset);
+ if ((circuit_state & DC_8BIT_MASK) == 0){
+ proto_tree_add_uint(circuit_state_tree, hf_isup_mtc_blocking_state1, parameter_tvb, offset, 1, circuit_state);
+ proto_item_set_text(circuit_state_item, "Circuit# CIC+%u state: %s", i++, val_to_str(circuit_state&BA_8BIT_MASK, isup_mtc_blocking_state_DC00_value, "unknown"));
+ }
+ else {
+ proto_tree_add_uint(circuit_state_tree, hf_isup_mtc_blocking_state2, parameter_tvb, offset, 1, circuit_state);
+ proto_tree_add_uint(circuit_state_tree, hf_isup_call_proc_state, parameter_tvb, offset, 1, circuit_state);
+ proto_tree_add_uint(circuit_state_tree, hf_isup_hw_blocking_state, parameter_tvb, offset, 1, circuit_state);
+ proto_item_set_text(circuit_state_item, "Circuit# CIC+%u state: %s", i++, val_to_str(circuit_state&BA_8BIT_MASK, isup_mtc_blocking_state_DCnot00_value, "unknown"));
+ }
+ offset++;
+ }
+ proto_item_set_text(parameter_item, "Circuit state indicator (national use)");
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Event information
+ */
+static void
+dissect_isup_event_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 indicators;
+
+ indicators = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_event_ind, parameter_tvb, 0, EVENT_INFO_LENGTH, indicators, "Event indicator: %s (%u)", val_to_str(indicators & GFEDCBA_8BIT_MASK, isup_event_ind_value, "spare"), indicators & GFEDCBA_8BIT_MASK);
+ proto_tree_add_boolean(parameter_tree, hf_isup_event_presentation_restricted_ind, parameter_tvb, 0, EVENT_INFO_LENGTH, indicators);
+
+ proto_item_set_text(parameter_item,"Event information: %s (%u)", val_to_str(indicators & GFEDCBA_8BIT_MASK, isup_event_ind_value, "spare"),indicators );
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter User-to-user information- no detailed dissection since defined in Rec. Q.931
+ */
+static void
+dissect_isup_user_to_user_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_reported_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, -1,
+ "User-to-user info (-> Q.931)");
+ dissect_q931_user_user_ie(parameter_tvb, 0, length,
+ parameter_tree );
+ proto_item_set_text(parameter_item, "User-to-user information,(%u byte%s length)",
+ length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Call Reference
+ */
+static void
+dissect_isup_call_reference_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint32 call_id;
+ guint16 spc;
+
+ call_id = tvb_get_ntoh24(parameter_tvb, 0);
+ spc = tvb_get_letohs(parameter_tvb, CALL_ID_LENGTH) & 0x3FFF; /*since 1st 2 bits spare */
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, CALL_ID_LENGTH, "Call identity: %u", call_id);
+ proto_tree_add_text(parameter_tree, parameter_tvb, CALL_ID_LENGTH, SPC_LENGTH, "Signalling Point Code: %u", spc);
+
+ proto_item_set_text(parameter_item, "Call Reference: Call ID = %u, SPC = %u", call_id, spc);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Access Transport - no detailed dissection since defined in Rec. Q.931
+ */
+static void
+dissect_isup_access_transport_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree,
+ proto_item *parameter_item, packet_info *pinfo)
+{ guint length = tvb_reported_length(parameter_tvb);
+
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, -1,
+ "Access transport parameter field (-> Q.931)");
+
+ if (q931_ie_handle)
+ call_dissector(q931_ie_handle, parameter_tvb, pinfo, parameter_tree);
+
+ proto_item_set_text(parameter_item, "Access transport (%u byte%s length)",
+ length , plurality(length, "", "s"));
+}
+
+/* dissect x.213 NSAP coded Address */
+
+static const value_string x213_afi_value[] = {
+ { 0x34, "IANA ICP"},
+ { 0x35, "IANA ICP"},
+ { 0x36, "X.121"},
+ { 0x37, "X.121"},
+ { 0x38, "ISO DCC"},
+ { 0x39, "ISO DCC"},
+ { 0x40, "F.69"},
+ { 0x41, "F.69"},
+ { 0x42, "E.163"},
+ { 0x43, "E.163"},
+ { 0x44, "E.164"},
+ { 0x45, "E.164"},
+ { 0x46, "ISO 6523-ICD"},
+ { 0x47, "ISO 6523-ICD"},
+ { 0x48, "Local"},
+ { 0x49, "Local"},
+ { 0x50, "Local ISO/IEC 646 character "},
+ { 0x51, "Local ( National character )"},
+ { 0x52, "X.121"},
+ { 0x53, "X.121"},
+ { 0x54, "F.69"},
+ { 0x55, "F.69"},
+ { 0x56, "E.163"},
+ { 0x57, "E.163"},
+ { 0x58, "E.164"},
+ { 0x59, "E.164"},
+
+ { 0x76, "ITU-T IND"},
+ { 0x77, "ITU-T IND"},
+
+ { 0xb8, "IANA ICP Group no"},
+ { 0xb9, "IANA ICP Group no"},
+ { 0xba, "X.121 Group no"},
+ { 0xbb, "X.121 Group no"},
+ { 0xbc, "ISO DCC Group no"},
+ { 0xbd, "ISO DCC Group no"},
+ { 0xbe, "F.69 Group no"},
+ { 0xbf, "F.69 Group no"},
+ { 0xc0, "E.163 Group no"},
+ { 0xc1, "E.163 Group no"},
+ { 0xc2, "E.164 Group no"},
+ { 0xc3, "E.164 Group no"},
+ { 0xc4, "ISO 6523-ICD Group no"},
+ { 0xc5, "ISO 6523-ICD Group no"},
+ { 0xc6, "Local Group no"},
+ { 0xc7, "Local Group no"},
+ { 0xc8, "Local ISO/IEC 646 character Group no"},
+ { 0xc9, "Local ( National character ) Group no"},
+ { 0xca, "X.121 Group no"},
+ { 0xcb, "X.121 Group no"},
+ { 0xcd, "F.69 Group no"},
+ { 0xce, "F.69 Group no"},
+ { 0xcf, "E.163 Group no"},
+ { 0xde, "E.163 Group no"},
+ { 0xd0, "E.164 Group no"},
+ { 0xd1, "E.164 Group no"},
+
+ { 0xe2, "ITU-T IND Group no"},
+ { 0xe3, "ITU-T IND Group no"},
+ { 0, NULL }
+};
+
+
+/* Up-to-date information on the allocated ICP values can be found at: */
+/*http://www.iana.org/assignments/osi-nsapanumbers. */
+static const value_string iana_icp_values[] = {
+ { 0x0, "IP Version 6 Address"},
+ { 0x1, "IP Version 4 Address"},
+ { 0, NULL }
+};
+
+static void
+dissect_nsap(tvbuff_t *parameter_tvb,gint offset,gint len, proto_tree *parameter_tree)
+{
+ guint8 afi, cc_length = 0;
+ guint8 length = 0, address_digit_pair = 0;
+ guint icp, cc, id_code, cc_offset;
+ guint32 addr;
+ struct e_in6_addr ipv6_addr;
+
+
+ afi = tvb_get_guint8(parameter_tvb, offset);
+
+ switch ( afi ) {
+ case 0x35: /* IANA ICP Binary fortmat*/
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, 3,
+ "IDP = %s", tvb_bytes_to_str(parameter_tvb, offset, 3));
+
+ proto_tree_add_uint(parameter_tree, hf_afi, parameter_tvb, offset, 1, afi );
+ offset = offset + 1;
+ icp = tvb_get_ntohs(parameter_tvb, offset);
+ proto_tree_add_uint(parameter_tree, hf_iana_icp, parameter_tvb, offset, 1, icp );
+ if ( icp == 0 ){ /* IPv6 addr */
+ tvb_memcpy(parameter_tvb, (guint8 *)&ipv6_addr,( offset + 2 ), 16);
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset + 2 , 3,
+ "DSP = %s", tvb_bytes_to_str(parameter_tvb, offset + 2, 17));
+ proto_tree_add_ipv6(parameter_tree, hf_nsap_ipv6_addr, parameter_tvb, offset,
+ 16, (guint8 *)&ipv6_addr);
+
+ }
+ else { /* IPv4 addr */
+ tvb_memcpy(parameter_tvb,(guint8 *) &addr, ( offset + 2 ), 4);
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset + 2 , 3,
+ "DSP = %s", tvb_bytes_to_str(parameter_tvb, offset + 2, 17));
+ proto_tree_add_ipv4(parameter_tree, hf_nsap_ipv4_addr, parameter_tvb, offset + 2, 4, addr);
+ }
+
+ break;
+ case 0x45: /* E.164 ATM format */
+ case 0xC3: /* E.164 ATM group format */
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, 9,
+ "IDP = %s", tvb_bytes_to_str(parameter_tvb, offset, 9));
+
+ proto_tree_add_uint(parameter_tree, hf_afi, parameter_tvb, offset, 1, afi );
+
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset + 1, 8,
+ "IDI = %s", tvb_bytes_to_str(parameter_tvb, offset + 1, 8));
+ offset = offset +1;
+ /* Dissect country code after removing non significant zeros */
+ cc_offset = offset;
+ address_digit_pair = tvb_get_guint8(parameter_tvb, cc_offset);
+ while ( address_digit_pair == 0 ) {
+ cc_offset = cc_offset + 1;
+ address_digit_pair = tvb_get_guint8(parameter_tvb, cc_offset);
+ }
+ cc = tvb_get_ntohs(parameter_tvb, cc_offset);
+ if (( address_digit_pair & 0xf0 ) != 0 )
+ cc = cc >> 4;
+
+ switch ( cc & 0x0f00 ) {
+
+ case 0x0 : cc_length = 1;
+ break;
+
+ case 0x0100 : cc_length = 1;
+ break;
+
+ case 0x0200 :
+ switch ( cc & 0x00f0 ) {
+ case 0 :
+ case 7 : cc_length = 2;
+ break;
+ default : cc_length = 3;
+ }
+ break;
+
+ case 0x0300 :
+ switch ( cc & 0x00f0 ) {
+ case 0 :
+ case 1 :
+ case 2 :
+ case 3 :
+ case 4 :
+ case 6 :
+ case 9 : cc_length = 2;
+ break;
+ default : cc_length = 3;
+ break;
+ }
+ break;
+
+ case 0x0400 :
+ switch ( cc & 0x00f0 ) {
+ case 2 : cc_length = 3;
+ break;
+ default : cc_length = 2;
+ break;
+ }
+ break;
+
+ case 0x0500 :
+ switch ( cc & 0x00f0 ) {
+ case 0 :
+ case 9 : cc_length = 3;
+ break;
+ default : cc_length = 2;
+ break;
+ }
+ break;
+
+ case 0x0600 :
+ switch ( cc & 0x00f0 ) {
+ case 7 :
+ case 8 :
+ case 9 : cc_length = 3;
+ break;
+ default : cc_length = 2;
+ break;
+ }
+ break;
+
+ case 0x0700 : cc_length = 1;
+ break;
+
+ case 0x0800 :
+ switch ( cc & 0x00f0 ) {
+ case 1 :
+ case 2 :
+ case 4 :
+ case 6 : cc_length = 2;
+ break;
+ default : cc_length = 3;
+ break;
+ }
+ break;
+
+ case 0x0900 :
+ switch ( cc & 0x00f0 ) {
+ case 0 :
+ case 1 :
+ case 2 :
+ case 3 :
+ case 4 :
+ case 5 :
+ case 8 : cc_length = 2;
+ break;
+ default : cc_length = 3;
+ break;
+ }
+ break;
+
+ default: ;
+ }/* End switch cc */
+ switch ( cc_length ) {
+ case 0x1 : cc = cc >> 8;
+ length = 1;
+ break;
+ case 0x2 : cc = cc >> 4;
+ length = 2;
+ break;
+ default: length = 2;
+ break;
+ }/* end switch cc_length */
+ proto_tree_add_text(parameter_tree,parameter_tvb, cc_offset, length,"Country Code: %x %s length %u",cc,
+ val_to_str(cc,E164_country_code_value,"unknown (%x)"),cc_length);
+ switch ( cc ) {
+ case 0x882 :
+ id_code = tvb_get_ntohs(parameter_tvb, cc_offset + 1);
+ id_code = (id_code & 0x0fff) >> 4;
+ proto_tree_add_text(parameter_tree,parameter_tvb, (cc_offset + 1), 2,"Identification Code: %x %s ",id_code,
+ val_to_str(id_code,E164_International_Networks_vals,"unknown (%x)"));
+
+ break;
+ default:;
+ }
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset + 8, (len - 9),
+ "DSP = %s", tvb_bytes_to_str(parameter_tvb, offset + 8, (len -9)));
+
+ break;
+ default:
+ proto_tree_add_uint(parameter_tree, hf_afi, parameter_tvb, offset, len, afi );
+ }/* end switch afi */
+
+}
+
+
+#define ACTION_INDICATOR 0x01
+#define BACKBONE_NETWORK_CONNECTION_IDENTIFIER 0x02
+#define INTERWORKING_FUNCTION_ADDRESS 0x03
+#define CODEC_LIST 0x04
+#define CODEC 0x05
+#define BAT_COMPATIBILITY_REPORT 0x06
+#define BEARER_NETWORK_CONNECTION_CHARACTERISTICS 0x07
+#define BEARER_CONTROL_INFORMATION 0x08
+#define BEARER_CONTROL_TUNNELLING 0x09
+#define BEARER_CONTROL_UNIT_IDENTIFIER 0x0A
+#define SIGNAL 0x0B
+#define BEARER_REDIRECTION_CAPABILITY 0x0C
+#define BEARER_REDIRECTION_INDICATORS 0x0D
+#define SIGNAL_TYPE 0x0E
+#define DURATION 0x0F
+
+
+static const value_string bat_ase_list_of_Identifiers_vals[] = {
+
+ { 0x00 , "spare" },
+ { ACTION_INDICATOR , "Action Indicator" },
+ { BACKBONE_NETWORK_CONNECTION_IDENTIFIER , "Backbone Network Connection Identifier" },
+ { INTERWORKING_FUNCTION_ADDRESS , "Interworking Function Address" },
+ { CODEC_LIST , "Codec List" },
+ { CODEC , "Codec" },
+ { BAT_COMPATIBILITY_REPORT , "BAT Compatibility Report" },
+ { BEARER_NETWORK_CONNECTION_CHARACTERISTICS , "Bearer Network Connection Characteristics" },
+ { BEARER_CONTROL_INFORMATION , "Bearer Control Information"},
+ { BEARER_CONTROL_TUNNELLING , "Bearer Control Tunnelling"},
+ { BEARER_CONTROL_UNIT_IDENTIFIER , "Bearer Control Unit Identifier" },
+ { SIGNAL , "Signal"},
+ { BEARER_REDIRECTION_CAPABILITY , "Bearer Redirection Capability"},
+ { BEARER_REDIRECTION_INDICATORS , "Bearer Redirection Indicators"},
+ { SIGNAL_TYPE , "Signal Type"},
+ { DURATION , "Duration" },
+ { 0, NULL }
+};
+
+/*ITU-T Q.765.5 (06/2000) 13*/
+static const value_string Instruction_indicator_for_general_action_vals[] =
+{
+ { 0, "Pass on information element"},
+ { 1, "Discard information element"},
+ { 2, "Discard BICC data"},
+ { 3, "Release call"},
+ { 0, NULL}};
+
+static const value_string Instruction_indicator_for_pass_on_not_possible_vals[] = {
+ { 0, "Release call"},
+ { 1, "Discard information element"},
+ { 2, "Discard BICC data"},
+ { 3, "reserved (interpreted as 00)"},
+ { 0, NULL}};
+
+static value_string bat_ase_action_indicator_field_vals[] = {
+
+ { 0x00, "no indication"},
+ { 0x01, "connect backward"},
+ { 0x02, "connect forward"},
+ { 0x03, "connect forward, no notification"},
+ { 0x04, "connect forward, plus notification"},
+ { 0x05, "connect forward, no notification + selected codec"},
+ { 0x06, "connect forward, plus notification + selected codec"},
+ { 0x07, "use idle"},
+ { 0x08, "connected"},
+ { 0x09, "switched"},
+ { 0x0a, "selected codec"},
+ { 0x0b, "modify codec"},
+ { 0x0c, "successful codec modification"},
+ { 0x0d, "codec modification failure"},
+ { 0x0e, "mid-call codec negotiation"},
+ { 0x0f, "modify to selected codec information"},
+ { 0x10, "mid-call codec negotiation failure"},
+ { 0x11, "start signal, notify"},
+ { 0x12, "start signal, no notify"},
+ { 0x13, "stop signal, notify"},
+ { 0x14, "stop signal, no notify"},
+ { 0x15, "start signal acknowledge"},
+ { 0x16, "start signal reject"},
+ { 0x16, "stop signal acknowledge"},
+ { 0x18, "bearer redirect"},
+ { 0, NULL }
+};
+
+static const true_false_string BCTP_BVEI_value = {
+ "Version Error Indication, BCTP version not supported",
+ "No indication"
+};
+
+static value_string BCTP_Tunnelled_Protocol_Indicator_vals[] = {
+
+ { 0x20, "IPBCP (text encoded)"},
+ { 0x21, "spare (text encoded protocol)"},
+ { 0x22, "not used"},
+ { 0, NULL }
+};
+
+static const true_false_string BCTP_TPEI_value = {
+ "Protocol Error Indication, Bearer Control Protocol not supported",
+ "No indication"
+};
+
+#define ITU_T 0x01
+#define ETSI 0x02
+
+static const value_string bat_ase_organization_identifier_subfield_vals[] = {
+
+ { 0x00, "no indication"},
+ { 0x01, "ITU-T"},
+ { 0x02, "ETSI (refer to TS 26.103)"},
+ { 0, NULL }
+};
+
+
+#define G_711_64_A 0x01
+#define G_711_64_U 0x02
+#define G_711_56_A 0x03
+#define G_711_56_U 0x04
+#define G_722_SB_ADPCM 0x05
+#define G_723_1 0x06
+#define G_723_1_Annex_A 0x07
+#define G_726_ADPCM 0x08
+#define G_727_Embedded_ADPCM 0x09
+#define G_728 0x0a
+#define G_729_CS_ACELP 0x0b
+#define G_729_Annex_B 0x0c
+
+static const value_string ITU_T_codec_type_subfield_vals[] = {
+
+ { 0x00, "no indication"},
+ { G_711_64_A, "G.711 64 kbit/s A-law"},
+ { G_711_64_U, "G.711 64 kbit/s -law"},
+ { G_711_56_A, "G.711 56 kbit/s A-law"},
+ { G_711_56_U, "G.711 56 kbit/s -law"},
+ { G_722_SB_ADPCM, "G.722 (SB-ADPCM)"},
+ { G_723_1, "G.723.1"},
+ { G_723_1_Annex_A, "G.723.1 Annex A (silence suppression)"},
+ { G_726_ADPCM, "G.726 (ADPCM)"},
+ { G_727_Embedded_ADPCM, "G.727 (Embedded ADPCM)"},
+ { G_728, "G.728"},
+ { G_729_CS_ACELP, "G.729 (CS-ACELP)"},
+ { G_729_Annex_B, "G.729 Annex B (silence suppression)"},
+ { 0, NULL }
+};
+
+static const value_string ETSI_codec_type_subfield_vals[] = {
+
+ { 0x00, "GSM Full Rate (13.0 kBit/s)( GSM FR )"},
+ { 0x01, "GSM Half Rate (5.6 kBit/s) ( GSM HR )"},
+ { 0x02, "GSM Enhanced Full Rate (12.2 kBit/s)( GSM EFR )"},
+ { 0x03, "Full Rate Adaptive Multi-Rate ( FR AMR )"},
+ { 0x04, "Half Rate Adaptive Multi-Rate ( HR AMR )"},
+ { 0x05, "UMTS Adaptive Multi-Rate ( UMTS AMR )"},
+ { 0x06, "UMTS Adaptive Multi-Rate 2 ( UMTS AMR 2 )"},
+ { 0x07, "TDMA Enhanced Full Rate (7.4 kBit/s) ( TDMA EFR )"},
+ { 0x08, "PDC Enhanced Full Rate (6.7 kBit/s) ( PDC EFR )"},
+ { 0x09, "Full Rate Adaptive Multi-Rate WideBand ( FR AMR-WB )"},
+ { 0x0a, "UMTS Adaptive Multi-Rate WideBand ( UMTS AMR-WB )"},
+ { 0x0b, "8PSK Half Rate Adaptive Multi-Rate ( OHR AMR )"},
+ { 0x0c, "8PSK Full Rate Adaptive Multi-Rate WideBand ( OFR AMR-WB )"},
+ { 0x0d, "8PSK Half Rate Adaptive Multi-Rate WideBand ( OHR AMR-WB )"},
+ { 0xfe, "Reserved for future use."},
+ { 0xff, "Reserved for MuMe dummy Codec Type ( MuMe )"},
+ { 0, NULL }
+};
+
+static const value_string bearer_network_connection_characteristics_vals[] = {
+
+ { 0x00, "no indication"},
+ { 0x01, "AAL type 1"},
+ { 0x02, "AAL type 2"},
+ { 0x03, "Structured AAL type 1"},
+ { 0x04, "IP/RTP"},
+ { 0, NULL }
+};
+
+static const true_false_string Bearer_Control_Tunnelling_ind_value = {
+ "Tunnelling to be used",
+ "No indication"
+};
+
+static const true_false_string late_cut_trough_cap_ind_value = {
+ "Late Cut-through supported",
+ "Late Cut-through not supported"
+};
+/* ITU-T Rec. Q.765.5/Amd.1 (07/2001) */
+static const value_string Bearer_Redirection_Indicator_vals[] = {
+ { 0x00, " no indication"},
+ { 0x01, "late cut-through request"},
+ { 0x02, "redirect temporary reject"},
+ { 0x03, "redirect backwards request"},
+ { 0x04, "redirect forwards request"},
+ { 0x05, "redirect bearer release request"},
+ { 0x06, "redirect bearer release proceed"},
+ { 0x07, "redirect bearer release complete"},
+ { 0x08, "redirect cut-through request"},
+ { 0x09, "redirect bearer connected indication"},
+ { 0x0a, "redirect failure"},
+ { 0x0b, "new connection identifier"},
+ { 0, NULL }
+};
+
+/*26/Q.765.5 - Signal Type */
+static const value_string BAt_ASE_Signal_Type_vals[] = {
+ { 0x00, "DTMF 0"},
+ { 0x01, "DTMF 1"},
+ { 0x02, "DTMF 2"},
+ { 0x03, "DTMF 3"},
+ { 0x04, "DTMF 4"},
+ { 0x05, "DTMF 5"},
+ { 0x06, "DTMF 6"},
+ { 0x07, "DTMF 7"},
+ { 0x08, "DTMF 8"},
+ { 0x09, "DTMF 9"},
+ { 0x0a, "DTMF *"},
+ { 0x0b, "DTMF #"},
+ { 0x0c, "DTMF A"},
+ { 0x0d, "DTMF B"},
+ { 0x0e, "DTMF C"},
+ { 0x1f, "DTMF D"},
+ { 0x40, "dial tone"},
+ { 0x41, "PABX internal dial tone"},
+ { 0x42, "special dial tone"},
+ { 0x43, "second dial tone"},
+ { 0x44, "ringing tone"},
+ { 0x45, "special ringing tone"},
+ { 0x46, "busy tone"},
+ { 0x47, "congestion tone"},
+ { 0x48, "special information tone"},
+ { 0x49, "warning tone"},
+ { 0x4a, "intrusion tone"},
+ { 0x4b, "call waiting tone"},
+ { 0x4c, "pay tone"},
+ { 0x4d, "payphone recognition tone"},
+ { 0x4e, "comfort tone"},
+ { 0x4f, "tone on hold"},
+ { 0x50, "record tone"},
+ { 0x51, "Caller waiting tone"},
+ { 0x52, "positive indication tone"},
+ { 0x53, "negative indication tone"},
+ { 0, NULL }
+};
+
+static const value_string BAT_ASE_Report_Reason_vals[] = {
+
+ { 0x00, "no indication"},
+ { 0x01, "information element non-existent or not implemented"},
+ { 0x02, "BICC data with unrecognized information element, discarded"},
+ { 0, NULL }
+};
+static int
+dissect_codec(tvbuff_t *parameter_tvb, proto_tree *bat_ase_element_tree, gint length_indicator, gint offset,gint identifier)
+{
+/* offset is at length indicator e.g 1 step past identifier */
+guint content_len;
+guint8 tempdata, compatibility_info;
+
+ proto_tree_add_uint(bat_ase_element_tree , hf_bat_ase_identifier , parameter_tvb, offset - 1, 1, identifier );
+ proto_tree_add_uint(bat_ase_element_tree , hf_length_indicator , parameter_tvb, offset, 1, length_indicator );
+ offset = offset + 1;
+ compatibility_info = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_Instruction_ind_for_general_action , parameter_tvb, offset, 1, compatibility_info );
+ proto_tree_add_boolean(bat_ase_element_tree, hf_Send_notification_ind_for_general_action , parameter_tvb, offset, 1, compatibility_info );
+ proto_tree_add_uint(bat_ase_element_tree, hf_Instruction_ind_for_pass_on_not_possible , parameter_tvb, offset, 1, compatibility_info );
+ proto_tree_add_boolean(bat_ase_element_tree, hf_Send_notification_ind_for_pass_on_not_possible , parameter_tvb, offset, 1, compatibility_info );
+ proto_tree_add_boolean(bat_ase_element_tree, hf_isup_extension_ind , parameter_tvb, offset, 1, compatibility_info );
+
+ content_len = length_indicator - 1 ; /* exclude the treated Compatibility information */
+ offset = offset + 1;
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_Organization_Identifier , parameter_tvb, offset, 1, tempdata );
+ switch ( tempdata ){
+ case ITU_T :
+ offset = offset + 1;
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_codec_type , parameter_tvb, offset, 1, tempdata );
+ offset = offset + 1;
+ switch ( tempdata ) {
+ case G_711_64_A :
+ case G_711_64_U :
+ case G_711_56_A :
+ case G_711_56_U :
+ case G_722_SB_ADPCM :
+ case G_723_1 :
+ case G_723_1_Annex_A : /* These codecs have no configuration data */
+ break;
+ case G_726_ADPCM :
+ case G_727_Embedded_ADPCM : /* four bit config data, TODO decode config */
+ if ( content_len > 2 ) {
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(bat_ase_element_tree, parameter_tvb, offset, 1, "Configuration data : 0x%x", tempdata);
+ }
+ break;
+ case G_728 :
+ case G_729_CS_ACELP :
+ case G_729_Annex_B : /* three bit config data, TODO decode config */
+ if ( content_len > 2 ) {
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(bat_ase_element_tree, parameter_tvb, offset, 1 , "Configuration data : 0x%x", tempdata);
+ }
+ break;
+ default:
+ break;
+
+ }/* switch ITU codec type*/
+ offset = offset + 1;
+ break;
+ case ETSI:
+ offset = offset + 1;
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_etsi_codec_type , parameter_tvb, offset, 1, tempdata );
+ if ( content_len > 2 ) {
+ offset = offset + 1;
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(bat_ase_element_tree, parameter_tvb, offset, 1 , "ACS : 0x%x", tempdata);
+ }
+ if ( content_len > 3 ) {
+ offset = offset + 1;
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(bat_ase_element_tree, parameter_tvb, offset, 1 , "SCS : 0x%x", tempdata);
+ }
+ if ( content_len > 4 ) {
+ offset = offset + 1;
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(bat_ase_element_tree, parameter_tvb, offset, 1 , "OM MACS : 0x%x", tempdata);
+ }
+ offset = offset + 1;
+ break;
+ default:
+ offset = offset + 1;
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(bat_ase_element_tree, parameter_tvb, offset, content_len ,
+ "Unknown organisation Identifier ( Non ITU-T/ETSI codec ) %u", tempdata);
+ offset = offset + content_len - 1;
+ break;
+ }/* switch OID */
+return offset;
+}
+
+/* Dissect BAT ASE message according to Q.765.5 200006 and Amendment 1 200107 */
+/* Layout of message */
+/* Element name Octet */
+/* Identifier 1 1 */
+/* Length indicator 1 2 */
+/* Compatibility information 1 3 */
+/* Contents 1 4 */
+/* Identifier n m */
+/* Length indicator n */
+/* Compatibility information n */
+/* Contents n p */
+
+static void
+dissect_bat_ase_Encapsulated_Application_Information(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, gint offset)
+{
+ gint length = tvb_reported_length_remaining(parameter_tvb, offset), list_end;
+ tvbuff_t *next_tvb;
+ proto_tree *bat_ase_tree, *bat_ase_element_tree, *bat_ase_iwfa_tree;
+ proto_item *bat_ase_item, *bat_ase_element_item, *bat_ase_iwfa_item;
+ guint8 identifier,compatibility_info,content, BCTP_Indicator_field_1, BCTP_Indicator_field_2;
+ guint8 sdp_length, tempdata, element_no, number_of_indicators;
+ guint8 diagnostic_len;
+ guint8 length_ind_len;
+ guint tempdata16;
+ guint content_len, length_indicator;
+ guint duration;
+ guint diagnostic;
+ guint32 bncid, Local_BCU_ID;
+ element_no = 0;
+
+ bat_ase_item = proto_tree_add_text(parameter_tree,parameter_tvb,
+ offset, -1,
+"Bearer Association Transport (BAT) Application Service Element (ASE) Encapsulated Application Information:");
+ bat_ase_tree = proto_item_add_subtree(bat_ase_item , ett_bat_ase);
+
+ proto_tree_add_text(bat_ase_tree, parameter_tvb, offset, -1,
+ "BAT ASE Encapsulated Application Information, (%u byte%s length)", length, plurality(length, "", "s"));
+ while(tvb_reported_length_remaining(parameter_tvb, offset) > 0){
+ element_no = element_no + 1;
+ identifier = tvb_get_guint8(parameter_tvb, offset);
+
+ /* length indicator may be 11 bits long */
+ offset = offset + 1;
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ if ( tempdata & 0x80 ) {
+ length_indicator = tempdata & 0x7f;
+ length_ind_len = 1;
+ }
+ else {
+ offset = offset + 1;
+ tempdata16 = ( tempdata & 0x7f );
+ length_indicator = tvb_get_guint8(parameter_tvb, offset)& 0x0f;
+ length_indicator = length_indicator << 7;
+ length_indicator = length_indicator + tempdata16;
+ length_ind_len = 2;
+ }
+
+ bat_ase_element_item = proto_tree_add_text(bat_ase_tree,parameter_tvb,
+ ( offset - length_ind_len),(length_indicator + 2),"BAT ASE Element %u, Identifier: %s",element_no,
+ val_to_str(identifier,bat_ase_list_of_Identifiers_vals,"unknown (%u)"));
+ bat_ase_element_tree = proto_item_add_subtree(bat_ase_element_item ,
+ ett_bat_ase_element);
+ if ( identifier != CODEC ) {
+ /* identifier, lengt indicator and compabillity info must be printed inside CODEC */
+ /* dissection in order to use dissect_codec routine for codec list */
+ proto_tree_add_uint(bat_ase_element_tree , hf_bat_ase_identifier , parameter_tvb,
+ offset - length_ind_len, 1, identifier );
+ proto_tree_add_uint(bat_ase_element_tree , hf_length_indicator , parameter_tvb,
+ offset - length_ind_len + 1, length_ind_len, length_indicator );
+
+ offset = offset + 1;
+ compatibility_info = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_Instruction_ind_for_general_action , parameter_tvb, offset, 1, compatibility_info );
+ proto_tree_add_boolean(bat_ase_element_tree, hf_Send_notification_ind_for_general_action , parameter_tvb, offset, 1, compatibility_info );
+ proto_tree_add_uint(bat_ase_element_tree, hf_Instruction_ind_for_pass_on_not_possible , parameter_tvb, offset, 1, compatibility_info );
+ proto_tree_add_boolean(bat_ase_element_tree, hf_Send_notification_ind_for_pass_on_not_possible , parameter_tvb, offset, 1, compatibility_info );
+ proto_tree_add_boolean(bat_ase_element_tree, hf_isup_extension_ind , parameter_tvb, offset, 1, compatibility_info );
+ offset = offset + 1;
+ }
+ content_len = length_indicator - 1 ; /* exclude the treated Compatibility information */
+
+ /* content will be different depending on identifier */
+ switch ( identifier ){
+
+ case ACTION_INDICATOR :
+
+ content = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_Action_Indicator , parameter_tvb, offset, 1, content );
+ proto_item_append_text(bat_ase_element_item, " - %s",
+ val_to_str(content,bat_ase_action_indicator_field_vals, "unknown (%u)"));
+ offset = offset + 1;
+ break;
+ case BACKBONE_NETWORK_CONNECTION_IDENTIFIER :
+
+ bncid = tvb_get_ntohl(parameter_tvb, offset);
+ switch ( content_len ){
+ case 1:
+ bncid = bncid & 0x000000ff;
+ break;
+ case 2:
+ bncid = bncid & 0x0000ffff;
+ break;
+ case 3:
+ bncid = bncid & 0x00ffffff;
+ break;
+ case 4:;
+ default:;
+ }
+ proto_tree_add_uint_format(bat_ase_element_tree, hf_bncid, parameter_tvb, offset, content_len, bncid, "BNCId: 0x%08x", bncid);
+ proto_item_append_text(bat_ase_element_item, " - 0x%08x",bncid);
+ offset = offset + content_len;
+
+ break;
+ case INTERWORKING_FUNCTION_ADDRESS :
+ bat_ase_iwfa_item = proto_tree_add_item(bat_ase_element_tree, hf_bat_ase_biwfa, parameter_tvb, offset, content_len,
+ FALSE);
+ bat_ase_iwfa_tree = proto_item_add_subtree(bat_ase_iwfa_item , ett_bat_ase_iwfa);
+ dissect_nsap(parameter_tvb, offset, content_len, bat_ase_iwfa_tree);
+
+ offset = offset + content_len;
+ break;
+ case CODEC_LIST :
+ list_end = offset + content_len;
+ while ( offset < ( list_end - 1 )) {
+ identifier = tvb_get_guint8(parameter_tvb, offset);
+ offset = offset + 1;
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ if ( tempdata & 0x80 ) {
+ length_indicator = tempdata & 0x7f;
+ }
+ else {
+ offset = offset +1;
+ length_indicator = tvb_get_guint8(parameter_tvb, offset);
+ length_indicator = length_indicator << 7;
+ length_indicator = length_indicator & ( tempdata & 0x7f );
+ }
+ offset = dissect_codec(parameter_tvb, bat_ase_element_tree, length_indicator , offset, identifier);
+ }
+ break;
+ case CODEC :
+ /* offset is at length indicator in this case */
+ offset = dissect_codec(parameter_tvb, bat_ase_element_tree, length_indicator , offset, identifier);
+ break;/* case codec */
+ case BAT_COMPATIBILITY_REPORT :
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_BAT_ASE_Comp_Report_Reason, parameter_tvb, offset, 1, tempdata );
+ offset = offset + 1;
+
+ diagnostic_len = content_len - 1;
+ while ( diagnostic_len > 0 ) {
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_BAT_ASE_Comp_Report_ident, parameter_tvb, offset, 1, tempdata );
+ offset = offset + 1;
+ diagnostic = tvb_get_letohs(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_BAT_ASE_Comp_Report_diagnostic, parameter_tvb, offset, 2, diagnostic);
+ offset = offset + 2;
+ diagnostic_len = diagnostic_len - 3;
+ }
+ break;
+ case BEARER_NETWORK_CONNECTION_CHARACTERISTICS :
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_characteristics , parameter_tvb,
+ offset, 1, tempdata );
+ proto_item_append_text(bat_ase_element_item, " - %s",
+ val_to_str(tempdata,bearer_network_connection_characteristics_vals, "unknown (%u)"));
+
+ offset = offset + content_len;
+ break;
+/* The Bearer Control Information information element contains the bearer control tunnelling protocol */
+/* ITU-T Q.1990 (2001), BICC bearer control tunnelling protocol. */
+
+ case BEARER_CONTROL_INFORMATION :
+ BCTP_Indicator_field_1 = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_BCTP_Version_Indicator,
+ parameter_tvb, offset, 1, BCTP_Indicator_field_1 );
+
+ proto_tree_add_boolean(bat_ase_element_tree, hf_BVEI,
+ parameter_tvb, offset, 1, BCTP_Indicator_field_1 );
+ offset = offset + 1;
+
+ BCTP_Indicator_field_2 = tvb_get_guint8(parameter_tvb, offset);
+
+ proto_tree_add_uint(bat_ase_element_tree, hf_Tunnelled_Protocol_Indicator ,
+ parameter_tvb, offset, 1, BCTP_Indicator_field_2 );
+
+ proto_tree_add_boolean(bat_ase_element_tree, hf_TPEI,
+ parameter_tvb, offset, 1, BCTP_Indicator_field_2 );
+ offset = offset + 1;
+
+ sdp_length = ( length_indicator ) - 3;
+
+ next_tvb = tvb_new_subset(parameter_tvb, offset, sdp_length, sdp_length);
+ call_dissector(sdp_handle, next_tvb, pinfo, bat_ase_element_tree);
+ offset = offset + sdp_length;
+
+
+ break;
+ case BEARER_CONTROL_TUNNELLING :
+
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_boolean(bat_ase_element_tree, hf_bearer_control_tunneling , parameter_tvb, offset, 1, ( tempdata & 0x01 ) );
+ if ( tempdata & 0x01 )
+ proto_item_append_text(bat_ase_element_item, " - Tunnelling to be used ");
+
+ offset = offset + content_len;
+ break;
+ case BEARER_CONTROL_UNIT_IDENTIFIER :
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(bat_ase_element_tree, parameter_tvb, offset, 1, "Network ID Length indicator= %u",tempdata);
+ offset = offset +1;
+ if ( tempdata > 0 ) {
+ offset = offset +1;
+
+/* Q.765.5 amd 1
+ Network ID
+ The coding of the Network ID field is identical to the coding of the Network ID field in the
+ Global Call Reference parameter as specified in clause 6/Q.1902.3 (see [3]).
+ NOTE .When used inside a network domain, the Network ID may be omitted by setting the
+ Network ID Length indicator to the value "0".
+ Q.1902.3
+ The following codes are used in the subfields of the global call reference parameter field:
+ a) Network ID
+ The Network ID contains the value field (coded according to ASN.1 BER) of an object
+ identifier identifying the network. This means that the tag and length fields are omitted.
+ An example of such an object identifier can be the following:
+ .{itu-t (0) administration (2) national regulatory authority (x) network (y)}
+ The value for x is the value of the national regulatory authority (one of the Data Country
+ Codes associated to the country as specified in ITU-T X.121 shall be used for "national
+ regulatory authority"), the value for y is under the control of the national regulatory
+ authority concerned.
+ b) Node ID
+ A binary number that uniquely identifies within the network the node which generates the
+ call reference.
+ c) Call Reference ID
+ A binary number used for the call reference of the call. This is generated by the node for
+ each call.
+
+*/
+ proto_tree_add_text(bat_ase_element_tree, parameter_tvb, offset, tempdata , "Network ID: %s",
+ tvb_bytes_to_str(parameter_tvb, offset, tempdata));
+ offset = offset + tempdata;
+ } /* end if */
+
+ Local_BCU_ID = tvb_get_letohl(parameter_tvb, offset);
+ proto_tree_add_uint_format(bat_ase_element_tree, hf_Local_BCU_ID , parameter_tvb, offset, 4, Local_BCU_ID , "Local BCU ID : 0x%08x", Local_BCU_ID );
+ offset = offset + 4;
+ break;
+ case SIGNAL :
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_bat_ase_signal , parameter_tvb, offset, 1, tempdata );
+ offset = offset + 1;
+ if ( content_len > 1){
+ duration = tvb_get_letohs(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_bat_ase_duration , parameter_tvb, offset, 2, duration );
+ offset = offset + 2;
+ }
+ break;
+ case BEARER_REDIRECTION_CAPABILITY :
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_boolean(bat_ase_element_tree, hf_late_cut_trough_cap_ind , parameter_tvb, offset, 1, tempdata );
+ offset = offset + content_len;
+ break;
+ case BEARER_REDIRECTION_INDICATORS :
+ number_of_indicators = 0;
+ while ( number_of_indicators < content_len ) {
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_bat_ase_bearer_redir_ind , parameter_tvb, offset, 1, tempdata );
+ offset = offset + 1;
+ number_of_indicators = number_of_indicators + 1;
+ }
+ break;
+ case SIGNAL_TYPE :
+ tempdata = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_bat_ase_signal , parameter_tvb, offset, 1, tempdata );
+ offset = offset + content_len;
+ break;
+ case DURATION :
+ duration = tvb_get_letohs(parameter_tvb, offset);
+ proto_tree_add_uint(bat_ase_element_tree, hf_bat_ase_duration , parameter_tvb, offset, 2, duration );
+ offset = offset + content_len;
+ break;
+ default :
+ proto_tree_add_text(bat_ase_element_tree, parameter_tvb, offset,content_len , "Default ?, (%u byte%s length)", (content_len), plurality(content_len, "", "s"));
+ offset = offset + content_len;
+ }
+ }
+
+}
+
+static void
+dissect_isup_application_transport_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+
+ guint8 application_context_identifier;
+ guint8 application_transport_instruction_ind;
+ guint8 si_and_apm_segmentation_indicator;
+ guint8 apm_Segmentation_local_ref;
+ guint8 pointer_to_transparent_data;
+ guint16 application_context_identifier16;
+ gint offset = 0;
+ guint length = tvb_reported_length(parameter_tvb);
+
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, -1, "Application transport parameter fields:");
+ proto_item_set_text(parameter_item, "Application transport, (%u byte%s length)", length , plurality(length, "", "s"));
+ application_context_identifier = tvb_get_guint8(parameter_tvb, 0);
+
+ if ( (application_context_identifier & H_8BIT_MASK) == 0x80) {
+ proto_tree_add_uint(parameter_tree, hf_isup_app_cont_ident, parameter_tvb,offset, 1, (application_context_identifier & GFEDCBA_8BIT_MASK));
+ offset = offset + 1;
+ if ((application_context_identifier & 0x7f) > 6)
+ return;
+ }
+ else {
+ application_context_identifier16 = tvb_get_letohs(parameter_tvb,offset);
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, 2, "Application context identifier: 0x%x", application_context_identifier16);
+ offset = offset + 2;
+ return; /* no further decoding of this element */
+ }
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, -1, "Application transport instruction indicators: ");
+ application_transport_instruction_ind = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_boolean(parameter_tree, hf_isup_app_Release_call_ind, parameter_tvb, offset, 1, application_transport_instruction_ind);
+ proto_tree_add_boolean(parameter_tree, hf_isup_app_Send_notification_ind, parameter_tvb, offset, 1, application_transport_instruction_ind);
+ offset = offset + 1;
+ if ( (application_transport_instruction_ind & H_8BIT_MASK) == 0x80) {
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, 1, "APM segmentation indicator:");
+ si_and_apm_segmentation_indicator = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(parameter_tree, hf_isup_apm_segmentation_ind , parameter_tvb, offset, 1, si_and_apm_segmentation_indicator );
+ proto_tree_add_boolean(parameter_tree, hf_isup_apm_si_ind , parameter_tvb, offset, 1, si_and_apm_segmentation_indicator );
+ offset = offset + 1;
+
+ if ( (si_and_apm_segmentation_indicator & H_8BIT_MASK) == 0x80) {
+ apm_Segmentation_local_ref = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, 1, "Segmentation local reference (SLR): 0x%x", apm_Segmentation_local_ref );
+ offset = offset + 1;
+ }
+ }
+
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, -1, "APM-user information field" );
+ /* dissect BAT ASE element, without transparent data ( Q.765.5-200006) */
+ if ((application_context_identifier & 0x7f) != 5) {
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, -1, "No further dissection of APM-user information field");
+ return;
+ }
+ pointer_to_transparent_data = tvb_get_guint8(parameter_tvb, offset);
+ if (pointer_to_transparent_data != 0)
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, 1, "Pointer to transparent data: 0x%x Don't know how to dissect further", pointer_to_transparent_data );
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, 1, "Pointer to transparent data: 0x%x No transparent data", pointer_to_transparent_data );
+ offset = offset + 1;
+
+ dissect_bat_ase_Encapsulated_Application_Information(parameter_tvb, pinfo, parameter_tree, offset);
+}
+
+
+
+/* ------------------------------------------------------------------
+ Dissector Parameter Optional Forward Call indicators
+ */
+static void
+dissect_isup_optional_forward_call_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 indicators;
+
+ indicators = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_cug_call_ind, parameter_tvb, 0, OPTIONAL_FORWARD_CALL_IND_LENGTH, indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_simple_segmentation_ind, parameter_tvb, 0, OPTIONAL_FORWARD_CALL_IND_LENGTH, indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_connected_line_identity_request_ind, parameter_tvb, 0, OPTIONAL_FORWARD_CALL_IND_LENGTH, indicators);
+
+
+ proto_item_set_text(parameter_item,"Optional forward call indicators: %s (%u)", val_to_str(indicators & BA_8BIT_MASK, isup_CUG_call_ind_value, "spare"),indicators );
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter calling party number
+ */
+static void
+dissect_isup_calling_party_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char calling_number[MAXLENGTH]="";
+ e164_info_t e164_info;
+ gint number_plan;
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 1);
+ number_plan = (indicators2 & 0x70)>> 4;
+ proto_tree_add_boolean(parameter_tree, hf_isup_ni_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_address_presentation_restricted_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_screening_indicator, parameter_tvb, 1, 1, indicators2);
+ offset = 2;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Calling Party Number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ calling_number[i++] = '\0';
+
+ if ( number_plan == 1 ) {
+ e164_info.e164_number_type = CALLING_PARTY_NUMBER;
+ e164_info.nature_of_address = indicators1 & 0x7f;
+ e164_info.E164_number_str = calling_number;
+ e164_info.E164_number_length = i - 1;
+ dissect_e164_number(parameter_tvb, address_digits_tree, 2,
+ (offset - 2), e164_info);
+ }
+ proto_item_set_text(address_digits_item, "Calling Party Number: %s", calling_number);
+ proto_item_set_text(parameter_item, "Calling Party Number: %s", calling_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Original called number
+ */
+static void
+dissect_isup_original_called_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char calling_number[MAXLENGTH]="";
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 1);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_address_presentation_restricted_indicator, parameter_tvb, 1, 1, indicators2);
+ offset = 2;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Original Called Number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ calling_number[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Original Called Number: %s", calling_number);
+ proto_item_set_text(parameter_item, "Original Called Number: %s", calling_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Redirecting number
+ */
+static void
+dissect_isup_redirecting_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char calling_number[MAXLENGTH]="";
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 1);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_address_presentation_restricted_indicator, parameter_tvb, 1, 1, indicators2);
+ offset = 2;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Redirecting Number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ calling_number[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Redirecting Number: %s", calling_number);
+ proto_item_set_text(parameter_item, "Redirecting Number: %s", calling_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Redirection number
+ */
+static void
+dissect_isup_redirection_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char called_number[MAXLENGTH]="";
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_called_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 1);
+ proto_tree_add_boolean(parameter_tree, hf_isup_inn_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2);
+ offset = 2;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Redirection Number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_called_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ called_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_called_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ called_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_called_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ called_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ called_number[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Redirection Number: %s", called_number);
+ proto_item_set_text(parameter_item, "Redirection Number: %s", called_number);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Connection request
+ */
+static void
+dissect_isup_connection_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint32 local_ref;
+ guint16 spc;
+ guint8 protocol_class, credit, offset=0;
+
+ local_ref = tvb_get_ntoh24(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, LOCAL_REF_LENGTH, "Local Reference: %u", local_ref);
+ offset = LOCAL_REF_LENGTH;
+ spc = tvb_get_letohs(parameter_tvb,offset) & 0x3FFF; /*since 1st 2 bits spare */
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, SPC_LENGTH, "Signalling Point Code: %u", spc);
+ offset += SPC_LENGTH;
+ protocol_class = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, PROTOCOL_CLASS_LENGTH, "Protocol Class: %u", protocol_class);
+ offset += PROTOCOL_CLASS_LENGTH;
+ credit = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, CREDIT_LENGTH, "Credit: %u", credit);
+ offset += CREDIT_LENGTH;
+
+ proto_item_set_text(parameter_item, "Connection request: Local Reference = %u, SPC = %u, Protocol Class = %u, Credit = %u", local_ref, spc, protocol_class, credit);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Redirection information
+ */
+static void
+dissect_isup_redirection_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ if (tvb_length(parameter_tvb) == 2){
+ guint16 indicators;
+ indicators = tvb_get_ntohs(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_redirecting_ind, parameter_tvb,0 , REDIRECTION_INFO_LENGTH, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_original_redirection_reason, parameter_tvb,0 , REDIRECTION_INFO_LENGTH, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_redirection_counter, parameter_tvb,0 , REDIRECTION_INFO_LENGTH, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_redirection_reason, parameter_tvb,0 , REDIRECTION_INFO_LENGTH, indicators);
+ proto_item_set_text(parameter_item, "Redirection Information");
+ }
+ else { /* ISUP'88 (blue book) */
+ guint16 indicators;
+ indicators = tvb_get_guint8(parameter_tvb, 0) * 0x100; /*since 2nd octet isn't present*/
+ proto_tree_add_uint(parameter_tree, hf_isup_redirecting_ind, parameter_tvb, 0, 1, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_original_redirection_reason, parameter_tvb,0 , 1, indicators);
+ proto_item_set_text(parameter_item, "Redirection Information (2nd octet not present since ISUP '88)");
+ }
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Closed user group interlock code
+ */
+static void
+dissect_isup_closed_user_group_interlock_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ char NI_digits[5]="";
+ guint8 digit_pair;
+ guint16 bin_code;
+
+ digit_pair = tvb_get_guint8(parameter_tvb, 0);
+ NI_digits[0] = number_to_char((digit_pair & HGFE_8BIT_MASK) / 0x10);
+ NI_digits[1] = number_to_char(digit_pair & DCBA_8BIT_MASK);
+ digit_pair = tvb_get_guint8(parameter_tvb, 1);
+ NI_digits[2] = number_to_char((digit_pair & HGFE_8BIT_MASK) / 0x10);
+ NI_digits[3] = number_to_char(digit_pair & DCBA_8BIT_MASK);
+ NI_digits[4] = '\0';
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, 2, "Network Identity: %s", NI_digits);
+ bin_code = tvb_get_ntohs(parameter_tvb, 2);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 3, 2, "Binary Code: 0x%x", bin_code);
+ proto_item_set_text(parameter_item, "Closed user group interlock code: NI = %s, Binary code = 0x%x", NI_digits, bin_code);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter User service information- no detailed dissection since defined in Rec. Q.931
+ */
+static void
+dissect_isup_user_service_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length,
+ "User service information (-> Q.931 Bearer_capability)");
+ proto_item_set_text(parameter_item, "User service information, (%u byte%s length)",
+ length , plurality(length, "", "s"));
+ dissect_q931_bearer_capability_ie(parameter_tvb,
+ 0, length,
+ parameter_tree);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Signalling point code
+ */
+static void
+dissect_isup_signalling_point_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 spc;
+
+ spc = tvb_get_letohs(parameter_tvb, 0) & 0x3FFF; /*since 1st 2 bits spare */
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, SIGNALLING_POINT_CODE_LENGTH, "Signalling Point Code: %u", spc);
+
+ proto_item_set_text(parameter_item, "Signalling point code: %u", spc);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Connected number
+ */
+static void
+dissect_isup_connected_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char calling_number[MAXLENGTH]="";
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 1);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_address_presentation_restricted_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_screening_indicator, parameter_tvb, 1, 1, indicators2);
+ offset = 2;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Connected Number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ calling_number[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Connected Number: %s", calling_number);
+ proto_item_set_text(parameter_item, "Connected Number: %s", calling_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Transit network selection
+ */
+static void
+dissect_isup_transit_network_selection_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char network_id[MAXLENGTH]="";
+
+ indicators = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_type_of_network_identification, parameter_tvb, 0, 1, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_network_identification_plan, parameter_tvb, 0, 1, indicators);
+ offset = 1;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Network identification");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ network_id[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ network_id[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ network_id[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ network_id[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Network identification: %s", network_id);
+ proto_item_set_text(parameter_item, "Transit network selection: %s", network_id);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Circuit assignment map
+ */
+static void
+dissect_isup_circuit_assignment_map_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 map_type;
+
+ map_type = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_map_type, parameter_tvb, 0, 1, map_type);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 1, 5, "Circuit assignment map (bit position indicates usage of corresponding circuit->3.69/Q.763)");
+ proto_item_set_text(parameter_item, "Circuit assignment map");
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Automatic congestion level
+ */
+static void
+dissect_isup_automatic_congestion_level_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 congestion_level;
+
+ congestion_level = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_automatic_congestion_level, parameter_tvb, 0, AUTO_CONGEST_LEVEL_LENGTH, congestion_level);
+ proto_item_set_text(parameter_item, "Automatic congestion level: %s (%u)", val_to_str(congestion_level, isup_auto_congestion_level_value, "spare"), congestion_level);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Optional backward Call indicators
+ */
+static void
+dissect_isup_optional_backward_call_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 indicators;
+
+ indicators = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_inband_information_ind, parameter_tvb, 0, OPTIONAL_BACKWARD_CALL_IND_LENGTH, indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_call_diversion_may_occur_ind, parameter_tvb, 0, OPTIONAL_BACKWARD_CALL_IND_LENGTH, indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_simple_segmentation_ind, parameter_tvb, 0, OPTIONAL_BACKWARD_CALL_IND_LENGTH, indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_mlpp_user_ind, parameter_tvb, 0, OPTIONAL_BACKWARD_CALL_IND_LENGTH, indicators);
+
+
+ proto_item_set_text(parameter_item,"Optional backward call indicators: 0x%x", indicators );
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter User-to-user indicators
+ */
+static const true_false_string isup_UUI_type_value = {
+ "Response",
+ "Request"
+};
+static const value_string isup_UUI_request_service_values[] = {
+ { 0, "No information"},
+ { 1, "Spare"},
+ { 2, "Request, not essential"},
+ { 3, "Request,essential"},
+ { 0, NULL}
+};
+
+static const value_string isup_UUI_response_service_values[] = {
+ { 0, "No information"},
+ { 1, "Not provided"},
+ { 2, "Provided"},
+ { 3, "Spare"},
+ { 0, NULL}
+};
+static const true_false_string isup_UUI_network_discard_ind_value= {
+ "User-to-user information discarded by the network",
+ "No information"
+};
+
+static void
+dissect_isup_user_to_user_indicators_parameter(tvbuff_t *parameter_tvb,
+ proto_tree *parameter_tree,
+ proto_item *parameter_item)
+{
+ guint8 indicators;
+
+ indicators = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_UUI_type, parameter_tvb, 0, 1, indicators);
+ if ( (indicators & 0x01) == 0 ){
+ /* Request */
+ proto_tree_add_uint(parameter_tree, hf_isup_UUI_req_service1, parameter_tvb, 0, 1, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_UUI_req_service2, parameter_tvb, 0, 1, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_UUI_req_service3, parameter_tvb, 0, 1, indicators);
+ }
+ else {
+ /* Response */
+ proto_tree_add_uint(parameter_tree, hf_isup_UUI_res_service1, parameter_tvb, 0, 1, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_UUI_res_service2, parameter_tvb, 0, 1, indicators);
+ proto_tree_add_uint(parameter_tree, hf_isup_UUI_res_service3, parameter_tvb, 0, 1, indicators);
+ proto_tree_add_boolean(parameter_tree, hf_isup_UUI_network_discard_ind, parameter_tvb, 0, 1, indicators);
+
+ }
+ proto_item_set_text(parameter_item,"User-to-user indicators: 0x%x", indicators );
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Original ISC point code
+ */
+static void
+dissect_isup_original_isc_point_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 spc;
+
+ spc = tvb_get_letohs(parameter_tvb, 0) & 0x3FFF; /*since 1st 2 bits spare */
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, ORIGINAL_ISC_POINT_CODE_LENGTH, "Origination ISC Point Code: %u", spc);
+
+ proto_item_set_text(parameter_item, "Origination ISC point code: %u", spc);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Generic notification indicator
+ */
+static void
+dissect_isup_generic_notification_indicator_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 indicators;
+
+ indicators = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, GENERIC_NOTIFICATION_IND_LENGTH, "Generic notification indicator: 0x%x (refer to 3.25/Q.763 for detailed decoding)", indicators );
+ proto_item_set_text(parameter_item,"Generic notification indicator: 0x%x", indicators );
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Call history information
+ */
+static void
+dissect_isup_call_history_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 info;
+
+ info = tvb_get_ntohs(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, CALL_HISTORY_INFO_LENGTH, "Call history info: propagation delay = %u ms", info);
+ proto_item_set_text(parameter_item,"Call history info: propagation delay = %u ms", info);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Access delivery information
+ */
+static void
+dissect_isup_access_delivery_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_access_delivery_ind, parameter_tvb, 0, ACCESS_DELIVERY_INFO_LENGTH, indicator);
+ proto_item_set_text(parameter_item, "Access delivery information: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Network specific facility
+ */
+static void
+dissect_isup_network_specific_facility_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "Network specific facility (refer to 3.36/Q.763 for detailed decoding)");
+ proto_item_set_text(parameter_item, "Network specific facility (%u byte%s length)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter User service information prime
+ */
+static void
+dissect_isup_user_service_information_prime_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length,
+ "User service information prime (-> Q.931 Bearer capability information IE)");
+ dissect_q931_bearer_capability_ie(parameter_tvb,
+ 0, length,
+ parameter_tree);
+
+ proto_item_set_text(parameter_item, "User service information prime, (%u byte%s length)",
+ length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Propagation delay counter
+ */
+static void
+dissect_isup_propagation_delay_counter_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 info;
+
+ info = tvb_get_ntohs(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, PROPAGATION_DELAY_COUNT_LENGTH, "Propagation delay counter = %u ms", info);
+ proto_item_set_text(parameter_item,"Propagation delay counter = %u ms", info);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Remote operations
+ */
+static void
+dissect_isup_remote_operations_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "Remote operations");
+ proto_item_set_text(parameter_item, "Remote operations (%u byte%s length)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Service activation
+ */
+static void
+dissect_isup_service_activation_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint i;
+ guint8 feature_code;
+ guint length = tvb_length(parameter_tvb);
+ for (i=0; i< length; i++){
+ feature_code = tvb_get_guint8(parameter_tvb, i);
+ proto_tree_add_text(parameter_tree, parameter_tvb, i, 1, "Feature Code %u: %u", i+1, feature_code);
+ }
+ proto_item_set_text(parameter_item, "Service Activation (%u byte%s length)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter User service information prime - no detailed dissection since defined in Rec. Q.931
+ */
+static void
+dissect_isup_user_teleservice_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length,
+ "User teleservice information (-> Q.931 High Layer Compatibility IE)");
+
+ dissect_q931_high_layer_compat_ie(parameter_tvb, 0, length, parameter_tree);
+
+ proto_item_set_text(parameter_item,
+ "User teleservice information");
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Transmission medium requirement used
+ */
+static void
+dissect_isup_transmission_medium_used_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 transmission_medium_requirement;
+
+ transmission_medium_requirement = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_transmission_medium_requirement_prime, parameter_tvb, 0, TRANSMISSION_MEDIUM_RQMT_PRIME_LENGTH,transmission_medium_requirement);
+
+ proto_item_set_text(parameter_item, "Transmission medium used: %u (%s)", transmission_medium_requirement, val_to_str(transmission_medium_requirement, isup_transmission_medium_requirement_prime_value, "spare/reserved"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Call diversion information
+ */
+static void
+dissect_isup_call_diversion_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, CALL_DIV_INFO_LENGTH, "Call diversion information: 0x%x (refer to 3.6/Q.763 for detailed decoding)", indicator);
+ proto_item_set_text(parameter_item, "Call diversion information: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Echo control information
+ */
+static const value_string OECD_inf_ind_vals[] = {
+ {0x00, "no information"},
+ {0x01, "outgoing echo control device not included and not available"},
+ {0x02, "outgoing echo control device included"},
+ {0x03, "outgoing echo control device not included but available"},
+ { 0, NULL }
+};
+static const value_string IECD_inf_ind_vals[] = {
+ {0x00, "no information"},
+ {0x01, "incomming echo control device not included and not available"},
+ {0x02, "incomming echo control device included"},
+ {0x03, "incomming echo control device not included but available"},
+ { 0, NULL }
+};
+
+static const value_string OECD_req_ind_vals[] = {
+ {0x00, "no information"},
+ {0x01, "outgoing echo control device activation request"},
+ {0x02, "outgoing echo control device deactivation request"},
+ {0x03, "spare"},
+ { 0, NULL }
+};
+
+static const value_string IECD_req_ind_vals[] = {
+ {0x00, "no information"},
+ {0x01, "incomming echo control device activation request"},
+ {0x02, "incomming echo control device deactivation request"},
+ {0x03, "spare"},
+ { 0, NULL }
+};
+
+static void
+dissect_isup_echo_control_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+ gint offset = 0;
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, ECHO_CONTROL_INFO_LENGTH,
+ "Echo control information: 0x%x", indicator);
+
+ proto_tree_add_uint(parameter_tree, hf_isup_OECD_inf_ind,
+ parameter_tvb, offset, 1, indicator );
+
+ proto_tree_add_uint(parameter_tree, hf_isup_IECD_inf_ind,
+ parameter_tvb, offset, 1, indicator );
+
+ proto_tree_add_uint(parameter_tree, hf_isup_OECD_req_ind,
+ parameter_tvb, offset, 1, indicator );
+
+ proto_tree_add_uint(parameter_tree, hf_isup_IECD_req_ind,
+ parameter_tvb, offset, 1, indicator );
+
+ proto_item_set_text(parameter_item, "Echo control information: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Message compatibility information
+ */
+
+static const true_false_string isup_pass_on_not_possible_indicator_value = {
+ "discard information",
+ "release call",
+};
+
+static void
+dissect_isup_message_compatibility_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint length = tvb_length(parameter_tvb);
+ guint instruction_indicators;
+ gint offset = 0;
+ instruction_indicators = tvb_get_guint8(parameter_tvb, offset);
+
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length,
+ "Message compatibility information");
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_transit_at_intermediate_exchange_ind,
+ parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_Release_call_ind,
+ parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_Send_notification_ind,
+ parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_Discard_message_ind_value,
+ parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_pass_on_not_possible_indicator2,
+ parameter_tvb, offset, 1,instruction_indicators);
+
+ proto_tree_add_uint(parameter_tree, hf_isup_Broadband_narrowband_interworking_ind2,
+ parameter_tvb, offset, 1,instruction_indicators);
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_extension_ind ,
+ parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_item_set_text(parameter_item, "Message compatibility information (%u byte%s length)",
+ length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter compatibility information
+ */
+static const true_false_string isup_transit_at_intermediate_exchange_ind_value = {
+ "End node interpretation",
+ "Transit interpretation"
+};
+
+
+static const true_false_string isup_Discard_message_ind_value = {
+ "Discard message",
+ "Do not discard message (pass on)",
+};
+
+static const true_false_string isup_Discard_parameter_ind_value = {
+ "Discard parameter",
+ "Do not discard parameter (pass on)",
+};
+
+static const value_string isup_Pass_on_not_possible_indicator_vals[] = {
+ { 0x00, "Release call" },
+ { 0x01, "Discard message" },
+ { 0x02, "Discard parameter" },
+ { 0x03, "Reserved (interpreted as 00)" },
+ { 0, NULL },
+};
+static const value_string ISUP_Broadband_narrowband_interworking_indicator_vals[] = {
+ { 0x00, "Pass on" },
+ { 0x01, "Discard message" },
+ { 0x02, "Release call" },
+ { 0x03, "Discard parameter" },
+ { 0, NULL },
+};
+
+static void
+dissect_isup_parameter_compatibility_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint length = tvb_length(parameter_tvb);
+ guint len = length;
+ guint8 upgraded_parameter, upgraded_parameter_no;
+ guint8 offset;
+ guint8 instruction_indicators;
+ offset = 0;
+ upgraded_parameter_no = 0;
+
+ proto_item_set_text(parameter_item, "Parameter compatibility information (%u byte%s length)", length , plurality(length, "", "s"));
+/* etxrab Decoded as per Q.763 section 3.41 */
+
+ while ( len > 0 ) {
+ upgraded_parameter_no = upgraded_parameter_no + 1;
+ upgraded_parameter = tvb_get_guint8(parameter_tvb, offset);
+
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, 1,
+ "Upgraded parameter no: %u = %s", upgraded_parameter_no,
+ val_to_str(upgraded_parameter, isup_parameter_type_value, "unknown (%u)"));
+ offset += 1;
+ len -= 1;
+ instruction_indicators = tvb_get_guint8(parameter_tvb, offset);
+
+ proto_tree_add_text(parameter_tree, parameter_tvb, offset, 1,
+ "Instruction indicators: 0x%x ",
+ instruction_indicators);
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_transit_at_intermediate_exchange_ind,
+ parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_Release_call_ind, parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_Send_notification_ind, parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_Discard_message_ind_value, parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_Discard_parameter_ind, parameter_tvb, offset, 1, instruction_indicators );
+
+ proto_tree_add_uint(parameter_tree, hf_isup_Pass_on_not_possible_indicator, parameter_tvb, offset, 1,instruction_indicators);
+
+ proto_tree_add_boolean(parameter_tree, hf_isup_extension_ind , parameter_tvb, offset, 1, instruction_indicators );
+
+ offset += 1;
+ len -= 1;
+ if (!(instruction_indicators & H_8BIT_MASK)) {
+ if (len == 0)
+ return;
+ instruction_indicators = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(parameter_tree, hf_isup_Broadband_narrowband_interworking_ind, parameter_tvb, offset, 1,instruction_indicators);
+ offset += 1;
+ len -= 1;
+ }
+ if (len == 0)
+ return;
+ ;
+ }
+/* etxrab */
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter MLPP precedence
+ */
+static void
+dissect_isup_mlpp_precedence_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ char NI_digits[5]="";
+ guint8 indicators, digit_pair;
+ guint32 bin_code;
+
+ indicators = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, 1, "LFB (Bits 6+7) and precedence level (Bits 1-4): 0x%x",indicators);
+ digit_pair = tvb_get_guint8(parameter_tvb, 1);
+ NI_digits[0] = number_to_char((digit_pair & HGFE_8BIT_MASK) / 0x10);
+ NI_digits[1] = number_to_char(digit_pair & DCBA_8BIT_MASK);
+ digit_pair = tvb_get_guint8(parameter_tvb, 2);
+ NI_digits[2] = number_to_char((digit_pair & HGFE_8BIT_MASK) / 0x10);
+ NI_digits[3] = number_to_char(digit_pair & DCBA_8BIT_MASK);
+ NI_digits[4] = '\0';
+ proto_tree_add_text(parameter_tree, parameter_tvb, 1, 2, "Network Identity: %s", NI_digits);
+ bin_code = tvb_get_ntoh24(parameter_tvb, 3);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 3, 3, "MLPP service domain: 0x%x", bin_code);
+ proto_item_set_text(parameter_item, "MLPP precedence: NI = %s, MLPP service domain = 0x%x", NI_digits, bin_code);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter MCID request indicators
+ */
+static void
+dissect_isup_mcid_request_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0,MCID_REQUEST_IND_LENGTH, "MCID request indicators: 0x%x (MCID requested by Bit1=1, Holding requested by Bit2=1 see 3.31/Q.763)", indicator);
+ proto_item_set_text(parameter_item, "MCID request indicators: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter MCID response indicators
+ */
+static void
+dissect_isup_mcid_response_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0,MCID_RESPONSE_IND_LENGTH, "MCID response indicators: 0x%x (MCID included if Bit1=1, Holding provided if Bit2=1 see 3.32/Q.763)", indicator);
+ proto_item_set_text(parameter_item, "MCID response indicators: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Hop counter
+ */
+static void
+dissect_isup_hop_counter_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 counter;
+
+ counter = tvb_get_guint8(parameter_tvb, 0) & EDCBA_8BIT_MASK; /* since bits H,G and F are spare */
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, HOP_COUNTER_LENGTH, "Hop counter: %u", counter);
+ proto_item_set_text(parameter_item, "Hop counter: %u", counter);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Transmission medium requirement prime
+ */
+static void
+dissect_isup_transmission_medium_requirement_prime_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 transmission_medium_requirement;
+
+ transmission_medium_requirement = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_transmission_medium_requirement_prime, parameter_tvb, 0, TRANSMISSION_MEDIUM_RQMT_PRIME_LENGTH,transmission_medium_requirement);
+
+ proto_item_set_text(parameter_item, "Transmission medium requirement prime: %u (%s)", transmission_medium_requirement, val_to_str(transmission_medium_requirement, isup_transmission_medium_requirement_prime_value, "spare/reserved"));
+}
+
+/* ------------------------------------------------------------------
+ Dissector Parameter location number
+ */
+static void
+dissect_isup_location_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char calling_number[MAXLENGTH]="";
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 1);
+ proto_tree_add_boolean(parameter_tree, hf_isup_inn_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2);
+ if ((indicators2 & GFE_8BIT_MASK) == 0x50)
+ proto_tree_add_text(parameter_tree, parameter_tvb, 1, 1, "Different meaning for Location Number: Numbering plan indicator = private numbering plan");
+ proto_tree_add_uint(parameter_tree, hf_isup_address_presentation_restricted_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_screening_indicator, parameter_tvb, 1, 1, indicators2);
+
+ /* NOTE When the address presentation restricted indicator indicates address not available, the
+ * subfields in items a), b), c) and d) are coded with 0's, and the screening indicator is set to 11
+ * (network provided).
+ */
+ if ( indicators2 == 0x0b ){
+ proto_tree_add_text(parameter_tree, parameter_tvb, 1, -1, "Location number: address not available");
+ proto_item_set_text(parameter_item, "Location number: address not available");
+ return;
+ }
+
+ offset = 2;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Location number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ calling_number[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Location number: %s", calling_number);
+ proto_item_set_text(parameter_item, "Location number: %s", calling_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Redirection number restiriction
+ */
+static void
+dissect_isup_redirection_number_restriction_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ switch (indicator & BA_8BIT_MASK) {
+ case 0:
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, REDIRECTION_NUMBER_RESTRICTION_LENGTH, "Presentation indicator: Presentation allowed");
+ break;
+ case 1:
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, REDIRECTION_NUMBER_RESTRICTION_LENGTH, "Presentation indicator: Presentation restricted");
+ break;
+ default:
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, REDIRECTION_NUMBER_RESTRICTION_LENGTH, "Presentation indicator: spare");
+ break;
+ }
+ proto_item_set_text(parameter_item, "Redirection number restriction: 0x%x ", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Call transfer identity
+ */
+static void
+dissect_isup_call_transfer_reference_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 id;
+
+ id = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, CALL_TRANSFER_REF_LENGTH, "Call transfer identity: %u", id);
+ proto_item_set_text(parameter_item, "Call transfer reference: %u", id);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Loop prevention
+ */
+static void
+dissect_isup_loop_prevention_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ if ((indicator & A_8BIT_MASK)==0) {
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, LOOP_PREVENTION_IND_LENGTH, "Type: Request");
+ proto_item_set_text(parameter_item, "Loop prevention indicators: Request (%u)", indicator);
+ }
+ else {
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, LOOP_PREVENTION_IND_LENGTH, "Type: Response");
+ proto_tree_add_uint(parameter_tree, hf_isup_loop_prevention_response_ind, parameter_tvb, 0, LOOP_PREVENTION_IND_LENGTH, indicator);
+ proto_item_set_text(parameter_item, "Loop prevention indicators: Response (%u)", indicator);
+ }
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Call transfer number
+ */
+static void
+dissect_isup_call_transfer_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char calling_number[MAXLENGTH]="";
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 1);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2);
+ if ((indicators2 & GFE_8BIT_MASK) == 0x50)
+ proto_tree_add_text(parameter_tree, parameter_tvb, 1, 1, "Different meaning for Call Transfer Number: Numbering plan indicator = private numbering plan");
+ proto_tree_add_uint(parameter_tree, hf_isup_address_presentation_restricted_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_screening_indicator_enhanced, parameter_tvb, 1, 1, indicators2);
+ offset = 2;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Call transfer number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ calling_number[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Call transfer number: %s", calling_number);
+ proto_item_set_text(parameter_item, "Call transfer number: %s", calling_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter CCSS
+ */
+static void
+dissect_isup_ccss_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ if ((indicator & A_8BIT_MASK)==0) {
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, LOOP_PREVENTION_IND_LENGTH, "CCSS call indicator: no indication");
+ proto_item_set_text(parameter_item, "CCSS call indicator: no indication (%u)", indicator);
+ }
+ else {
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, LOOP_PREVENTION_IND_LENGTH, "CCSS call indicator: CCSS call");
+ proto_item_set_text(parameter_item, "CCSS call indicator: CCSS call (%u)", indicator);
+ }
+}
+/* ------------------------------------------------------------------
+ Parameter Forward GVNS
+ */
+static void
+dissect_isup_forward_gvns_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "Forward GVNS (refer to 3.66/Q.763 for detailed decoding)");
+ proto_item_set_text(parameter_item, "Forward GVNS (%u Byte%s)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Parameter Redirect capability
+ */
+static void
+dissect_isup_redirect_capability_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "Redirect capability (format is a national matter)");
+ proto_item_set_text(parameter_item, "Redirect Capability (%u Byte%s)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Backward GVNS
+ */
+static void
+dissect_isup_backward_gvns_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, BACKWARD_GVNS_LENGTH, "Backward GVNS: 0x%x (refer to 3.62/Q.763 for detailed decoding)", indicator);
+ proto_item_set_text(parameter_item, "Backward GVNS: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Network management controls
+ */
+static void
+dissect_isup_network_management_controls_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_temporary_alternative_routing_ind, parameter_tvb, 0,NETWORK_MANAGEMENT_CONTROLS_LENGTH, indicator);
+ proto_tree_add_boolean(parameter_tree, hf_isup_extension_ind, parameter_tvb, 0,NETWORK_MANAGEMENT_CONTROLS_LENGTH, indicator);
+ proto_item_set_text(parameter_item, "Network management controls: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Correlation id - no detailed dissection since defined in Rec. Q.1281
+ */
+static void
+dissect_isup_correlation_id_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "Correlation ID (-> Q.1281)");
+ proto_item_set_text(parameter_item, "Correlation ID, see Q.1281 (%u Byte%s)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter SCF id - no detailed dissection since defined in Rec. Q.1281
+ */
+static void
+dissect_isup_scf_id_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "SCF ID (-> Q.1281)");
+ proto_item_set_text(parameter_item, "SCF ID, see Q.1281 (%u Byte%s)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Call diversion treatment indicators
+ */
+static void
+dissect_isup_call_diversion_treatment_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_call_to_be_diverted_ind, parameter_tvb, 0,CALL_DIV_TREATMENT_IND_LENGTH, indicator);
+ proto_tree_add_boolean(parameter_tree, hf_isup_extension_ind, parameter_tvb, 0, CALL_DIV_TREATMENT_IND_LENGTH, indicator);
+ proto_item_set_text(parameter_item, "Call diversion treatment indicators: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter called IN number
+ */
+static void
+dissect_isup_called_in_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char calling_number[MAXLENGTH]="";
+
+ indicators1 = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 0, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 1);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_address_presentation_restricted_indicator, parameter_tvb, 1, 1, indicators2);
+ offset = 2;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Called IN Number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ calling_number[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Called IN Number: %s", calling_number);
+ proto_item_set_text(parameter_item, "Called IN Number: %s", calling_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Call offering treatment indicators
+ */
+static void
+dissect_isup_call_offering_treatment_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_call_to_be_offered_ind, parameter_tvb, 0,CALL_OFFERING_TREATMENT_IND_LENGTH, indicator);
+ proto_tree_add_boolean(parameter_tree, hf_isup_extension_ind, parameter_tvb, 0, CALL_OFFERING_TREATMENT_IND_LENGTH, indicator);
+ proto_item_set_text(parameter_item, "Call offering treatment indicators: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Parameter Charged party identification
+ */
+static void
+dissect_isup_charged_party_identification_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "Charged party identification (format is national network specific)");
+ proto_item_set_text(parameter_item, "Charged party identification (%u Byte%s)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Conference treatment indicators
+ */
+static void
+dissect_isup_conference_treatment_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_uint(parameter_tree, hf_isup_conference_acceptance_ind, parameter_tvb, 0,CONFERENCE_TREATMENT_IND_LENGTH, indicator);
+ proto_tree_add_boolean(parameter_tree, hf_isup_extension_ind, parameter_tvb, 0, CONFERENCE_TREATMENT_IND_LENGTH, indicator);
+ proto_item_set_text(parameter_item, "Conference treatment indicators: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Display information
+ * TODO Output Display info :
+ * Quote from Q.931:
+ * 4.5.16 Display
+ * The purpose of the Display information element is to supply display information
+ * that may be displayed by the user. The information contained in this element is coded
+ * in IA5 characters.
+ * 8 7 6 5 4 3 2 1 Octet
+ * 0 0 1 0 1 0 0 0 1 Display information element identifier
+ * 2 Length of display contents
+ * 0 3 Display information (IA5 characters)
+ * etc.
+ * - end - quote -
+ * Assuming octet 2 and onwards is pased here - just output text ?
+ */
+static void
+dissect_isup_display_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length,
+ "Display information (-> Q.931)");
+ proto_item_set_text(parameter_item, "Display information (%u Byte%s)",
+ length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Parameter UID action indicators
+ */
+static void
+dissect_isup_uid_action_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0,UID_ACTION_IND_LENGTH, "UID action indicators: 0x%x (refer to 3.78/Q.763 for detailed decoding)", indicator);
+ proto_item_set_text(parameter_item, "UID action indicators: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Parameter UID capability indicators
+ */
+static void
+dissect_isup_uid_capability_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0,UID_CAPABILITY_IND_LENGTH, "UID capability indicators: 0x%x (refer to 3.79/Q.763 for detailed decoding)", indicator);
+ proto_item_set_text(parameter_item, "UID capability indicators: 0x%x", indicator);
+}
+/* ------------------------------------------------------------------
+ Parameter Redirect counter
+ */
+static void
+dissect_isup_redirect_counter_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "Redirect counter (format is a national matter)");
+ proto_item_set_text(parameter_item, "Redirect counter (%u Byte%s)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Collect call request
+ */
+static void
+dissect_isup_collect_call_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint8 indicator;
+
+ indicator = tvb_get_guint8(parameter_tvb, 0);
+ if ((indicator & A_8BIT_MASK) == 0) {
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, COLLECT_CALL_REQUEST_LENGTH, "Collect call request indicator: no indication");
+ proto_item_set_text(parameter_item, "Collect call reqeust: no indication (0x%x)", indicator);
+ }
+ else {
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, COLLECT_CALL_REQUEST_LENGTH, "Collect call request indicator: collect call requested");
+ proto_item_set_text(parameter_item, "Collect call reqeust: collect call requested (0x%x)", indicator);
+ }
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Generic number
+ */
+static void
+dissect_isup_generic_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *address_digits_item;
+ proto_tree *address_digits_tree;
+ guint8 indicators1, indicators2, nr_qualifier_ind;
+ guint8 address_digit_pair=0;
+ gint offset=0;
+ gint i=0;
+ gint length;
+ char calling_number[MAXLENGTH]="";
+
+ nr_qualifier_ind = tvb_get_guint8(parameter_tvb, 0);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, 1, "Number qualifier indicator: 0x%x (refer to 3.26/Q.763 for detailed decoding)", nr_qualifier_ind);
+ indicators1 = tvb_get_guint8(parameter_tvb, 1);
+ proto_tree_add_boolean(parameter_tree, hf_isup_odd_even_indicator, parameter_tvb, 1, 1, indicators1);
+ proto_tree_add_uint(parameter_tree, hf_isup_calling_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1);
+ indicators2 = tvb_get_guint8(parameter_tvb, 2);
+ proto_tree_add_boolean(parameter_tree, hf_isup_ni_indicator, parameter_tvb, 2, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_numbering_plan_indicator, parameter_tvb, 2, 1, indicators2);
+ if ((indicators2 & GFE_8BIT_MASK) == 0x50)
+ proto_tree_add_text(parameter_tree, parameter_tvb, 2, 1, "Different meaning for Generic Number: Numbering plan indicator = private numbering plan");
+ proto_tree_add_uint(parameter_tree, hf_isup_address_presentation_restricted_indicator, parameter_tvb, 2, 1, indicators2);
+ proto_tree_add_uint(parameter_tree, hf_isup_screening_indicator_enhanced, parameter_tvb, 2, 1, indicators2);
+ offset = 3;
+
+ address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb,
+ offset, -1,
+ "Generic number");
+ address_digits_tree = proto_item_add_subtree(address_digits_item, ett_isup_address_digits);
+
+ length = tvb_length_remaining(parameter_tvb, offset);
+ while(length > 0){
+ address_digit_pair = tvb_get_guint8(parameter_tvb, offset);
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char(address_digit_pair & ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK);
+ if ((length - 1) > 0 ){
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ offset++;
+ length = tvb_length_remaining(parameter_tvb, offset);
+ }
+
+ if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */
+ proto_tree_add_uint(address_digits_tree, hf_isup_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair);
+ calling_number[i++] = number_to_char((address_digit_pair & ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK) / 0x10);
+ }
+ calling_number[i++] = '\0';
+
+ proto_item_set_text(address_digits_item, "Generic number: %s", calling_number);
+ proto_item_set_text(parameter_item, "Generic number: %s", calling_number);
+
+}
+/* ------------------------------------------------------------------
+ Dissector Parameter Generic digits
+ */
+static void
+dissect_isup_generic_digits_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "Generic digits (refer to 3.24/Q.673 for detailed decoding)");
+ proto_item_set_text(parameter_item, "Generic digits (%u Byte%s)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------ */
+static void
+dissect_isup_unknown_parameter(tvbuff_t *parameter_tvb, proto_item *parameter_item)
+{ guint length = tvb_length(parameter_tvb);
+ proto_item_set_text(parameter_item, "Parameter Type unknown/reserved (%u Byte%s)", length , plurality(length, "", "s"));
+}
+/* ------------------------------------------------------------------ */
+
+/* ------------------------------------------------------------------
+ Dissector all optional parameters
+*/
+static void
+dissect_isup_optional_parameter(tvbuff_t *optional_parameters_tvb,packet_info *pinfo, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ gint offset = 0;
+ guint parameter_type, parameter_length, actual_length;
+ tvbuff_t *parameter_tvb;
+
+ /* Dissect all optional parameters while end of message isn't reached */
+ parameter_type = 0xFF; /* Start-initializiation since parameter_type is used for while-condition */
+
+ while ((tvb_length_remaining(optional_parameters_tvb, offset) >= 1) && (parameter_type != PARAM_TYPE_END_OF_OPT_PARAMS)){
+ parameter_type = tvb_get_guint8(optional_parameters_tvb, offset);
+
+ if (parameter_type != PARAM_TYPE_END_OF_OPT_PARAMS){
+ parameter_length = tvb_get_guint8(optional_parameters_tvb, offset + PARAMETER_TYPE_LENGTH);
+
+ parameter_item = proto_tree_add_text(isup_tree, optional_parameters_tvb,
+ offset,
+ parameter_length + PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_IND_LENGTH,
+ "Parameter: type %u",
+ parameter_type);
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, optional_parameters_tvb, offset, PARAMETER_TYPE_LENGTH, parameter_type, "Optional Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ offset += PARAMETER_TYPE_LENGTH;
+
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, optional_parameters_tvb, offset, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ offset += PARAMETER_LENGTH_IND_LENGTH;
+
+ actual_length = tvb_length_remaining(optional_parameters_tvb, offset);
+ if (actual_length > 0){
+ parameter_tvb = tvb_new_subset(optional_parameters_tvb, offset, MIN(parameter_length, actual_length), parameter_length);
+ switch (parameter_type) {
+ case PARAM_TYPE_CALL_REF:
+ dissect_isup_call_reference_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_TRANSM_MEDIUM_REQU:
+ dissect_isup_transmission_medium_requirement_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_ACC_TRANSP:
+ dissect_isup_access_transport_parameter(parameter_tvb, parameter_tree, parameter_item, pinfo);
+ break;
+ case PARAM_TYPE_CALLED_PARTY_NR:
+ dissect_isup_called_party_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_SUBSQT_NR:
+ dissect_isup_subsequent_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_NATURE_OF_CONN_IND:
+ dissect_isup_nature_of_connection_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_FORW_CALL_IND:
+ dissect_isup_forward_call_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_OPT_FORW_CALL_IND:
+ dissect_isup_optional_forward_call_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CALLING_PRTY_CATEG:
+ dissect_isup_calling_partys_category_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CALLING_PARTY_NR:
+ dissect_isup_calling_party_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_REDIRECTING_NR:
+ dissect_isup_redirecting_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_REDIRECTION_NR:
+ dissect_isup_redirection_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CONNECTION_REQ:
+ dissect_isup_connection_request_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_INFO_REQ_IND:
+ dissect_isup_information_request_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_INFO_IND:
+ dissect_isup_information_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CONTINUITY_IND:
+ dissect_isup_continuity_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_BACKW_CALL_IND:
+ dissect_isup_backward_call_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CAUSE_INDICATORS:
+ dissect_isup_cause_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_REDIRECTION_INFO:
+ dissect_isup_redirection_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CIRC_GRP_SV_MSG_TYPE:
+ dissect_isup_circuit_group_supervision_message_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_RANGE_AND_STATUS:
+ dissect_isup_range_and_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_FACILITY_IND:
+ dissect_isup_facility_ind_parameter(parameter_tvb, parameter_item);
+ break;
+ case PARAM_TYPE_CLSD_USR_GRP_ILOCK_CD:
+ dissect_isup_closed_user_group_interlock_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_USER_SERVICE_INFO:
+ dissect_isup_user_service_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_SIGNALLING_POINT_CODE:
+ dissect_isup_signalling_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_USER_TO_USER_INFO:
+ dissect_isup_user_to_user_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CONNECTED_NR:
+ dissect_isup_connected_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_SUSP_RESUME_IND:
+ dissect_isup_suspend_resume_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_TRANSIT_NETW_SELECT:
+ dissect_isup_transit_network_selection_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_EVENT_INFO:
+ dissect_isup_event_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CIRC_ASSIGN_MAP:
+ dissect_isup_circuit_assignment_map_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CIRC_STATE_IND:
+ dissect_isup_circuit_state_ind_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_AUTO_CONG_LEVEL:
+ dissect_isup_automatic_congestion_level_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_ORIG_CALLED_NR:
+ dissect_isup_original_called_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_OPT_BACKW_CALL_IND:
+ dissect_isup_optional_backward_call_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_USER_TO_USER_IND:
+ dissect_isup_user_to_user_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_ORIG_ISC_POINT_CODE:
+ dissect_isup_original_isc_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_GENERIC_NOTIF_IND:
+ dissect_isup_generic_notification_indicator_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CALL_HIST_INFO :
+ dissect_isup_call_history_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_ACC_DELIV_INFO:
+ dissect_isup_access_delivery_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_NETW_SPECIFIC_FACLTY:
+ dissect_isup_network_specific_facility_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_USER_SERVICE_INFO_PR:
+ dissect_isup_user_service_information_prime_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_PROPAG_DELAY_COUNTER:
+ dissect_isup_propagation_delay_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_REMOTE_OPERATIONS:
+ dissect_isup_remote_operations_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_SERVICE_ACTIVATION:
+ dissect_isup_service_activation_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_USER_TELESERV_INFO:
+ dissect_isup_user_teleservice_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_TRANSM_MEDIUM_USED:
+ dissect_isup_transmission_medium_used_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CALL_DIV_INFO:
+ dissect_isup_call_diversion_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_ECHO_CTRL_INFO:
+ dissect_isup_echo_control_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_MSG_COMPAT_INFO:
+ dissect_isup_message_compatibility_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_PARAM_COMPAT_INFO:
+ dissect_isup_parameter_compatibility_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_MLPP_PRECEDENCE:
+ dissect_isup_mlpp_precedence_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_MCID_REQ_IND:
+ dissect_isup_mcid_request_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_MCID_RSP_IND:
+ dissect_isup_mcid_response_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_HOP_COUNTER:
+ dissect_isup_hop_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_TRANSM_MEDIUM_RQUR_PR:
+ dissect_isup_transmission_medium_requirement_prime_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_LOCATION_NR:
+ dissect_isup_location_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_REDIR_NR_RSTRCT:
+ dissect_isup_redirection_number_restriction_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CALL_TRANS_REF:
+ dissect_isup_call_transfer_reference_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_LOOP_PREV_IND:
+ dissect_isup_loop_prevention_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CALL_TRANS_NR:
+ dissect_isup_call_transfer_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CCSS:
+ dissect_isup_ccss_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_FORW_GVNS:
+ dissect_isup_forward_gvns_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_BACKW_GVNS:
+ dissect_isup_backward_gvns_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_REDIRECT_CAPAB:
+ dissect_isup_redirect_capability_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_NETW_MGMT_CTRL:
+ dissect_isup_network_management_controls_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CORRELATION_ID:
+ dissect_isup_correlation_id_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_SCF_ID:
+ dissect_isup_scf_id_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CALL_DIV_TREAT_IND:
+ dissect_isup_call_diversion_treatment_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CALLED_IN_NR:
+ dissect_isup_called_in_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CALL_OFF_TREAT_IND:
+ dissect_isup_call_offering_treatment_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CHARGED_PARTY_IDENT:
+ dissect_isup_charged_party_identification_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_CONF_TREAT_IND:
+ dissect_isup_conference_treatment_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_DISPLAY_INFO:
+ dissect_isup_display_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_UID_ACTION_IND:
+ dissect_isup_uid_action_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_UID_CAPAB_IND:
+ dissect_isup_uid_capability_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_REDIRECT_COUNTER:
+ dissect_isup_redirect_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_COLLECT_CALL_REQ:
+ dissect_isup_collect_call_request_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_GENERIC_NR:
+ dissect_isup_generic_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_GENERIC_DIGITS:
+ dissect_isup_generic_digits_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PARAM_TYPE_APPLICATON_TRANS:
+ dissect_isup_application_transport_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
+ break;
+
+ default:
+ dissect_isup_unknown_parameter(parameter_tvb, parameter_item);
+ break;
+ }
+ offset += MIN(parameter_length, actual_length);
+ }
+
+ }
+ else {
+ /* End of optional parameters is reached */
+ proto_tree_add_uint_format(isup_tree, hf_isup_message_type, optional_parameters_tvb , offset, PARAMETER_TYPE_LENGTH, parameter_type, "End of optional parameters (%u)", parameter_type);
+ }
+ }
+}
+
+/* ------------------------------------------------------------------ */
+/* Dissectors for all used message types */
+/* Called by dissect_isup_message(), */
+/* call parameter dissectors in order of mandatory parameters */
+/* (since not labeled) */
+/* ------------------------------------------------------------------
+ Dissector Message Type Initial address message
+ */
+gint
+dissect_isup_initial_address_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: Nature of Connection Indicators */
+ parameter_type = PARAM_TYPE_NATURE_OF_CONN_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ NATURE_OF_CONNECTION_IND_LENGTH,
+ "Nature of Connection Indicators");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(NATURE_OF_CONNECTION_IND_LENGTH, actual_length), NATURE_OF_CONNECTION_IND_LENGTH);
+ dissect_isup_nature_of_connection_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += NATURE_OF_CONNECTION_IND_LENGTH;
+
+ /* Do stuff for 2nd mandatory fixed parameter: Forward Call Indicators */
+ parameter_type = PARAM_TYPE_FORW_CALL_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ FORWARD_CALL_IND_LENGTH,
+ "Forward Call Indicators");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(FORWARD_CALL_IND_LENGTH, actual_length), FORWARD_CALL_IND_LENGTH );
+ dissect_isup_forward_call_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += FORWARD_CALL_IND_LENGTH;
+
+ /* Do stuff for 3nd mandatory fixed parameter: Calling party's category */
+ parameter_type = PARAM_TYPE_CALLING_PRTY_CATEG;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ CALLING_PRTYS_CATEGORY_LENGTH,
+ "Calling Party's category");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(CALLING_PRTYS_CATEGORY_LENGTH, actual_length),CALLING_PRTYS_CATEGORY_LENGTH );
+ dissect_isup_calling_partys_category_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += CALLING_PRTYS_CATEGORY_LENGTH;
+
+ /* Do stuff for 4th mandatory fixed parameter: Transmission medium requirement */
+ parameter_type = PARAM_TYPE_TRANSM_MEDIUM_REQU;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ TRANSMISSION_MEDIUM_REQUIREMENT_LENGTH,
+ "Transmission medium requirement");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(TRANSMISSION_MEDIUM_REQUIREMENT_LENGTH, actual_length), TRANSMISSION_MEDIUM_REQUIREMENT_LENGTH);
+ dissect_isup_transmission_medium_requirement_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += TRANSMISSION_MEDIUM_REQUIREMENT_LENGTH;
+
+
+ /* Do stuff for mandatory variable parameter Called party number */
+ parameter_type = PARAM_TYPE_CALLED_PARTY_NR;
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Called Party Number");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_called_party_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type subsequent address message
+ */
+gint dissect_isup_subsequent_address_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for mandatory variable parameter Subsequent number */
+ parameter_type = PARAM_TYPE_SUBSQT_NR;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Subsequent Number");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_subsequent_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+
+/* ------------------------------------------------------------------
+ Dissector Message Type Information request message
+ */
+gint
+dissect_isup_information_request_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: Information request indicators*/
+ parameter_type = PARAM_TYPE_INFO_REQ_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ INFO_REQUEST_IND_LENGTH,
+ "Information request indicators");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(INFO_REQUEST_IND_LENGTH, actual_length), INFO_REQUEST_IND_LENGTH);
+ dissect_isup_information_request_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += INFO_REQUEST_IND_LENGTH;
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Information
+ */
+gint
+dissect_isup_information_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: Information indicators*/
+ parameter_type = PARAM_TYPE_INFO_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ INFO_IND_LENGTH,
+ "Information indicators");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(INFO_IND_LENGTH, actual_length), INFO_IND_LENGTH);
+ dissect_isup_information_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += INFO_IND_LENGTH;
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Continuity
+ */
+gint
+dissect_isup_continuity_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: Continuity indicators*/
+ parameter_type = PARAM_TYPE_CONTINUITY_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ CONTINUITY_IND_LENGTH,
+ "Continuity indicators");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(CONTINUITY_IND_LENGTH, actual_length), CONTINUITY_IND_LENGTH);
+ dissect_isup_continuity_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += CONTINUITY_IND_LENGTH;
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Address complete
+ */
+gint
+dissect_isup_address_complete_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: backward call indicators*/
+ parameter_type = PARAM_TYPE_BACKW_CALL_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ BACKWARD_CALL_IND_LENGTH,
+ "Backward Call Indicators");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(BACKWARD_CALL_IND_LENGTH, actual_length), BACKWARD_CALL_IND_LENGTH);
+ dissect_isup_backward_call_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += BACKWARD_CALL_IND_LENGTH;
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Connect
+ */
+gint
+dissect_isup_connect_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: backward call indicators*/
+ parameter_type = PARAM_TYPE_BACKW_CALL_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ BACKWARD_CALL_IND_LENGTH,
+ "Backward Call Indicators");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(BACKWARD_CALL_IND_LENGTH, actual_length), BACKWARD_CALL_IND_LENGTH);
+ dissect_isup_backward_call_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += BACKWARD_CALL_IND_LENGTH;
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type release message
+ */
+gint
+dissect_isup_release_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for mandatory variable parameter Cause indicators */
+ parameter_type = PARAM_TYPE_CAUSE_INDICATORS;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Cause indicators, see Q.850");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_cause_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Resume/Suspend
+ */
+gint
+dissect_isup_suspend_resume_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: backward call indicators*/
+ parameter_type = PARAM_TYPE_SUSP_RESUME_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ SUSPEND_RESUME_IND_LENGTH,
+ "Suspend/Resume indicator");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(SUSPEND_RESUME_IND_LENGTH, actual_length), SUSPEND_RESUME_IND_LENGTH);
+ dissect_isup_suspend_resume_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += SUSPEND_RESUME_IND_LENGTH;
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Circuit group reset/query message
+ */
+gint
+dissect_isup_circuit_group_reset_query_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for mandatory variable parameter range and status*/
+ parameter_type = PARAM_TYPE_RANGE_AND_STATUS;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Range and status");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_range_and_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Circuit group blocking/blocking ack/unblocking/unblocking ack messages
+ */
+gint
+dissect_isup_circuit_group_blocking_messages(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: circuit group supervision message type*/
+ parameter_type = PARAM_TYPE_CIRC_GRP_SV_MSG_TYPE;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ CIRC_GRP_SV_MSG_TYPE_LENGTH,
+ "Circuit group supervision message type");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(CIRC_GRP_SV_MSG_TYPE_LENGTH, actual_length), CIRC_GRP_SV_MSG_TYPE_LENGTH);
+ dissect_isup_circuit_group_supervision_message_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += CIRC_GRP_SV_MSG_TYPE_LENGTH;
+
+ /* Do stuff for mandatory variable parameter range and status*/
+ parameter_type = PARAM_TYPE_RANGE_AND_STATUS;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Range and status");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_range_and_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+
+/* ------------------------------------------------------------------
+ Dissector Message Type Facility request/accepted
+ */
+gint
+dissect_isup_facility_request_accepted_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: facility indicators*/
+ parameter_type = PARAM_TYPE_FACILITY_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ FACILITY_IND_LENGTH,
+ "Facility indicator");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(FACILITY_IND_LENGTH, actual_length), FACILITY_IND_LENGTH);
+ dissect_isup_facility_ind_parameter(parameter_tvb, parameter_item);
+ offset += FACILITY_IND_LENGTH;
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Facility reject
+ */
+gint
+dissect_isup_facility_reject_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: facility indicators*/
+ parameter_type = PARAM_TYPE_FACILITY_IND;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ FACILITY_IND_LENGTH,
+ "Facility indicator");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(FACILITY_IND_LENGTH, actual_length), FACILITY_IND_LENGTH);
+ dissect_isup_facility_ind_parameter(parameter_tvb, parameter_item);
+ offset += FACILITY_IND_LENGTH;
+
+ /* Do stuff for mandatory variable parameter Cause indicators */
+ parameter_type = PARAM_TYPE_CAUSE_INDICATORS;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Cause indicators, see Q.850");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_cause_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Circuit group reset acknowledgement message
+ */
+gint
+dissect_isup_circuit_group_reset_acknowledgement_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for mandatory variable parameter range and status*/
+ parameter_type = PARAM_TYPE_RANGE_AND_STATUS;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Range and status");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_range_and_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Circuit group query response message
+ */
+gint
+dissect_isup_circuit_group_query_response_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for 1. mandatory variable parameter range and status*/
+ parameter_type = PARAM_TYPE_RANGE_AND_STATUS;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Range and status");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_range_and_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ /* Do stuff for 2. mandatory variable parameter Circuit state indicator*/
+ parameter_type = PARAM_TYPE_CIRC_STATE_IND;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Circuit state indicator (national use)");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_circuit_state_ind_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Call Progress
+*/
+gint
+dissect_isup_call_progress_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, actual_length;
+
+ /* Do stuff for first mandatory fixed parameter: Event information*/
+ parameter_type = PARAM_TYPE_EVENT_INFO;
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset,
+ EVENT_INFO_LENGTH,
+ "Event information");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(EVENT_INFO_LENGTH, actual_length), EVENT_INFO_LENGTH);
+ dissect_isup_event_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += EVENT_INFO_LENGTH;
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type User-to-User information
+ */
+gint
+dissect_isup_user_to_user_information_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for mandatory variable parameter User-to-user information*/
+ parameter_type = PARAM_TYPE_USER_TO_USER_INFO;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "User-to-user information, see Q.931");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_user_to_user_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+/* ------------------------------------------------------------------
+ Dissector Message Type Confusion
+ */
+gint
+dissect_isup_confusion_message(tvbuff_t *message_tvb, proto_tree *isup_tree)
+{ proto_item* parameter_item;
+ proto_tree* parameter_tree;
+ tvbuff_t *parameter_tvb;
+ gint offset = 0;
+ gint parameter_type, parameter_pointer, parameter_length, actual_length;
+
+ /* Do stuff for mandatory variable parameter Cause indicators */
+ parameter_type = PARAM_TYPE_CAUSE_INDICATORS;
+
+ parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer);
+
+ parameter_item = proto_tree_add_text(isup_tree, message_tvb,
+ offset + parameter_pointer,
+ parameter_length + PARAMETER_LENGTH_IND_LENGTH,
+ "Cause indicators, see Q.850");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_isup_parameter);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown"));
+ proto_tree_add_uint_format(parameter_tree, hf_isup_mandatory_variable_parameter_pointer, message_tvb, offset, PARAMETER_POINTER_LENGTH, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer);
+ proto_tree_add_uint_format(parameter_tree, hf_isup_parameter_length, message_tvb, offset + parameter_pointer, PARAMETER_LENGTH_IND_LENGTH, parameter_length, "Parameter length: %u", parameter_length);
+ actual_length = tvb_ensure_length_remaining(message_tvb, offset);
+ parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + PARAMETER_LENGTH_IND_LENGTH, MIN(parameter_length, actual_length), parameter_length );
+ dissect_isup_cause_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ offset += PARAMETER_POINTER_LENGTH;
+
+ return offset;
+}
+/* ------------------------------------------------------------------ */
+static void
+dissect_isup_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *isup_tree)
+{
+ static isup_tap_rec_t tap_rec;
+ tvbuff_t *parameter_tvb;
+ tvbuff_t *optional_parameter_tvb;
+ proto_item* pass_along_item;
+ proto_tree* pass_along_tree;
+ gint offset, bufferlength;
+ guint8 message_type, opt_parameter_pointer;
+ gint opt_part_possible = FALSE; /* default setting - for message types allowing optional
+ params explicitely set to TRUE in case statement */
+ offset = 0;
+
+ /* Extract message type field */
+ message_type = tvb_get_guint8(message_tvb,0);
+
+ proto_tree_add_uint_format(isup_tree, hf_isup_message_type, message_tvb, 0, MESSAGE_TYPE_LENGTH, message_type, "Message type: %s (%u)", val_to_str(message_type, isup_message_type_value, "reserved"), message_type);
+ offset += MESSAGE_TYPE_LENGTH;
+
+ tap_rec.message_type = message_type;
+
+ tap_queue_packet(isup_tap, pinfo, &tap_rec);
+
+ parameter_tvb = tvb_new_subset(message_tvb, offset, -1, -1);
+
+ /* distinguish between message types:*/
+ switch (message_type) {
+ case MESSAGE_TYPE_INITIAL_ADDR:
+ offset += dissect_isup_initial_address_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_SUBSEQ_ADDR:
+ offset += dissect_isup_subsequent_address_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_INFO_REQ:
+ offset += dissect_isup_information_request_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_INFO:
+ offset += dissect_isup_information_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_CONTINUITY:
+ offset += dissect_isup_continuity_message(parameter_tvb, isup_tree);
+ break;
+ case MESSAGE_TYPE_ADDR_CMPL:
+ offset += dissect_isup_address_complete_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_CONNECT:
+ offset += dissect_isup_connect_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_FORW_TRANS:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_ANSWER:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_RELEASE:
+ offset += dissect_isup_release_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_SUSPEND:
+ offset += dissect_isup_suspend_resume_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_RESUME:
+ offset += dissect_isup_suspend_resume_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_REL_CMPL:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_CONT_CHECK_REQ:
+ /* no dissector necessary since no mandatory parameters included */
+ break;
+ case MESSAGE_TYPE_RESET_CIRCUIT:
+ /* no dissector necessary since no mandatory parameters included */
+ break;
+ case MESSAGE_TYPE_BLOCKING:
+ /* no dissector necessary since no mandatory parameters included */
+ break;
+ case MESSAGE_TYPE_UNBLOCKING:
+ /* no dissector necessary since no mandatory parameters included */
+ break;
+ case MESSAGE_TYPE_BLOCK_ACK:
+ /* no dissector necessary since no mandatory parameters included */
+ break;
+ case MESSAGE_TYPE_UNBLOCK_ACK:
+ /* no dissector necessary since no mandatory parameters included */
+ break;
+ case MESSAGE_TYPE_CIRC_GRP_RST:
+ offset += dissect_isup_circuit_group_reset_query_message(parameter_tvb, isup_tree);
+ break;
+ case MESSAGE_TYPE_CIRC_GRP_BLCK:
+ offset += dissect_isup_circuit_group_blocking_messages(parameter_tvb, isup_tree);
+ break;
+ case MESSAGE_TYPE_CIRC_GRP_UNBL:
+ offset += dissect_isup_circuit_group_blocking_messages(parameter_tvb, isup_tree);
+ break;
+ case MESSAGE_TYPE_CIRC_GRP_BL_ACK:
+ offset += dissect_isup_circuit_group_blocking_messages(parameter_tvb, isup_tree);
+ break;
+ case MESSAGE_TYPE_CIRC_GRP_UNBL_ACK:
+ offset += dissect_isup_circuit_group_blocking_messages(parameter_tvb, isup_tree);
+ break;
+ case MESSAGE_TYPE_FACILITY_REQ:
+ offset += dissect_isup_facility_request_accepted_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_FACILITY_ACC:
+ offset += dissect_isup_facility_request_accepted_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_FACILITY_REJ:
+ offset += dissect_isup_facility_reject_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_LOOP_BACK_ACK:
+ /* no dissector necessary since no mandatory parameters included */
+ break;
+ case MESSAGE_TYPE_PASS_ALONG:
+ /* call dissect_isup_message recursively */
+ { guint8 pa_message_type;
+ pa_message_type = tvb_get_guint8(parameter_tvb, 0);
+ pass_along_item = proto_tree_add_text(isup_tree, parameter_tvb, offset, -1, "Pass-along: %s Message (%u)", val_to_str(pa_message_type, isup_message_type_value_acro, "reserved"), pa_message_type);
+ pass_along_tree = proto_item_add_subtree(pass_along_item, ett_isup_pass_along_message);
+ dissect_isup_message(parameter_tvb, pinfo, pass_along_tree);
+ break;
+ }
+ case MESSAGE_TYPE_CIRC_GRP_RST_ACK:
+ offset += dissect_isup_circuit_group_reset_acknowledgement_message(parameter_tvb, isup_tree);
+ break;
+ case MESSAGE_TYPE_CIRC_GRP_QRY:
+ offset += dissect_isup_circuit_group_reset_query_message(parameter_tvb, isup_tree);
+ break;
+ case MESSAGE_TYPE_CIRC_GRP_QRY_RSP:
+ offset += dissect_isup_circuit_group_query_response_message(parameter_tvb, isup_tree);
+ break;
+ case MESSAGE_TYPE_CALL_PROGRSS:
+ offset += dissect_isup_call_progress_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_USER2USER_INFO:
+ offset += dissect_isup_user_to_user_information_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_UNEQUIPPED_CIC:
+ /* no dissector necessary since no mandatory parameters included */
+ break;
+ case MESSAGE_TYPE_CONFUSION:
+ offset += dissect_isup_confusion_message(parameter_tvb, isup_tree);
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_OVERLOAD:
+ /* no dissector necessary since no mandatory parameters included */
+ break;
+ case MESSAGE_TYPE_CHARGE_INFO:
+ /* do nothing since format is a national matter */
+ bufferlength = tvb_length_remaining(message_tvb, offset);
+ if (bufferlength != 0)
+ proto_tree_add_text(isup_tree, parameter_tvb, 0, bufferlength, "Format is a national matter");
+ break;
+ case MESSAGE_TYPE_NETW_RESRC_MGMT:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_FACILITY:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_USER_PART_TEST:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_USER_PART_AVAIL:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_IDENT_REQ:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_IDENT_RSP:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_SEGMENTATION:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_LOOP_PREVENTION:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_APPLICATION_TRANS:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_PRE_RELEASE_INFO:
+ /* no dissector necessary since no mandatory parameters included */
+ opt_part_possible = TRUE;
+ break;
+ case MESSAGE_TYPE_SUBSEQUENT_DIR_NUM:
+ /* do nothing since format is a national matter */
+ bufferlength = tvb_length_remaining(message_tvb, offset);
+ if (bufferlength != 0)
+ proto_tree_add_text(isup_tree, parameter_tvb, 0, bufferlength, "Format is a national matter");
+ break;
+
+ default:
+ bufferlength = tvb_length_remaining(message_tvb, offset);
+ if (bufferlength != 0)
+ proto_tree_add_text(isup_tree, parameter_tvb, 0, bufferlength, "Unknown Message type (possibly reserved/used in former ISUP version)");
+ break;
+ }
+
+ /* extract pointer to start of optional part (if any) */
+ if (opt_part_possible == TRUE){
+ opt_parameter_pointer = tvb_get_guint8(message_tvb, offset);
+ if (opt_parameter_pointer > 0){
+ proto_tree_add_uint_format(isup_tree, hf_isup_pointer_to_start_of_optional_part, message_tvb, offset, PARAMETER_POINTER_LENGTH, opt_parameter_pointer, "Pointer to start of optional part: %u", opt_parameter_pointer);
+ offset += opt_parameter_pointer;
+ optional_parameter_tvb = tvb_new_subset(message_tvb, offset, -1, -1 );
+ dissect_isup_optional_parameter(optional_parameter_tvb, pinfo, isup_tree);
+ }
+ else
+ proto_tree_add_uint_format(isup_tree, hf_isup_pointer_to_start_of_optional_part, message_tvb, offset, PARAMETER_POINTER_LENGTH, opt_parameter_pointer, "No optional parameter present (Pointer: %u)", opt_parameter_pointer);
+ }
+ else if (message_type !=MESSAGE_TYPE_CHARGE_INFO)
+ proto_tree_add_text(isup_tree, message_tvb, 0, 0, "No optional parameters are possible with this message type");
+
+}
+
+/* ------------------------------------------------------------------ */
+static void
+dissect_isup(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *isup_tree = NULL;
+ tvbuff_t *message_tvb;
+ guint16 cic;
+ guint8 message_type;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISUP (ITU)");
+
+/* Extract message type field */
+ message_type = tvb_get_guint8(tvb, CIC_OFFSET + CIC_LENGTH);
+ /* dissect CIC in main dissector since pass-along message type carrying complete IUSP message w/o CIC needs
+ recursive message dissector call */
+ cic = tvb_get_letohs(tvb, CIC_OFFSET) & 0x0FFF; /*since upper 4 bits spare */
+
+
+ pinfo->ctype = CT_ISUP;
+ pinfo->circuit_id = cic;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (isup_show_cic_in_info)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (CIC %u) ", val_to_str(message_type, isup_message_type_value_acro, "reserved"), cic);
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_type, isup_message_type_value_acro, "reserved"));
+ }
+
+/* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_isup, tvb, 0, -1, FALSE);
+ isup_tree = proto_item_add_subtree(ti, ett_isup);
+
+
+ proto_tree_add_uint_format(isup_tree, hf_isup_cic, tvb, CIC_OFFSET, CIC_LENGTH, cic, "CIC: %u", cic);
+ }
+
+ message_tvb = tvb_new_subset(tvb, CIC_LENGTH, -1, -1);
+ dissect_isup_message(message_tvb, pinfo, isup_tree);
+}
+
+/* ------------------------------------------------------------------ */
+static void
+dissect_bicc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *bicc_tree = NULL;
+ tvbuff_t *message_tvb;
+ guint32 bicc_cic;
+ guint8 message_type;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BICC");
+
+/* Extract message type field */
+ message_type = tvb_get_guint8(tvb, BICC_CIC_OFFSET + BICC_CIC_LENGTH);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_type, isup_message_type_value_acro, "reserved"));
+
+/* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_bicc, tvb, 0, -1, FALSE);
+ bicc_tree = proto_item_add_subtree(ti, ett_bicc);
+
+ /* dissect CIC in main dissector since pass-along message type carrying complete BICC/ISUP message w/o CIC needs
+ recursive message dissector call */
+ bicc_cic = tvb_get_letohl(tvb, BICC_CIC_OFFSET);
+
+ proto_tree_add_uint_format(bicc_tree, hf_bicc_cic, tvb, BICC_CIC_OFFSET, BICC_CIC_LENGTH, bicc_cic, "CIC: %u", bicc_cic);
+ }
+
+ message_tvb = tvb_new_subset(tvb, BICC_CIC_LENGTH, -1, -1);
+ dissect_isup_message(message_tvb, pinfo, bicc_tree);
+}
+
+static void
+dissect_application_isup(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *isup_tree = NULL;
+ tvbuff_t *message_tvb;
+ guint8 message_type;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_append_str(pinfo->cinfo, COL_PROTOCOL, "/ISUP(ITU)");
+
+/* Extract message type field */
+ message_type = tvb_get_guint8(tvb, 0);
+ /* application/ISUP has no CIC */
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "ISUP:%s", val_to_str(message_type, isup_message_type_value_acro, "reserved"));
+
+/* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_isup, tvb, 0, -1, FALSE);
+ isup_tree = proto_item_add_subtree(ti, ett_isup);
+
+
+ }
+
+ message_tvb = tvb_new_subset(tvb, 0, -1, -1);
+ dissect_isup_message(message_tvb, pinfo, isup_tree);
+}
+/*---------------------------------------------------------------------*/
+/* Register the protocol with Ethereal */
+void
+proto_register_isup(void)
+{
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_isup_cic,
+ { "CIC", "isup.cic",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_isup_message_type,
+ { "Message Type", "isup.message_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_isup_parameter_type,
+ { "Parameter Type", "isup.parameter_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_isup_parameter_length,
+ { "Parameter Length", "isup.parameter_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_isup_mandatory_variable_parameter_pointer,
+ { "Pointer to Parameter", "isup.mandatory_variable_parameter_pointer",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_isup_pointer_to_start_of_optional_part,
+ { "Pointer to optional parameter part", "isup.optional_parameter_part_pointer",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_isup_satellite_indicator,
+ { "Satellite Indicator", "isup.satellite_indicator",
+ FT_UINT8, BASE_HEX, VALS(isup_satellite_ind_value), BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_continuity_check_indicator,
+ { "Continuity Check Indicator", "isup.continuity_check_indicator",
+ FT_UINT8, BASE_HEX, VALS(isup_continuity_check_ind_value), DC_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_echo_control_device_indicator,
+ { "Echo Control Device Indicator", "isup.echo_control_device_indicator",
+ FT_BOOLEAN, 8, TFS(&isup_echo_control_device_ind_value),E_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_forw_call_natnl_inatnl_call_indicator,
+ { "National/international call indicator", "isup.forw_call_natnl_inatnl_call_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_natnl_inatnl_call_ind_value),A_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_forw_call_end_to_end_method_indicator,
+ { "End-to-end method indicator", "isup.forw_call_end_to_end_method_indicator",
+ FT_UINT16, BASE_HEX, VALS(isup_end_to_end_method_ind_value), CB_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_forw_call_interworking_indicator,
+ { "Interworking indicator", "isup.forw_call_interworking_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_interworking_ind_value), D_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_forw_call_end_to_end_info_indicator,
+ { "End-to-end information indicator", "isup.forw_call_end_to_end_information_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_end_to_end_info_ind_value), E_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_forw_call_isdn_user_part_indicator,
+ { "ISDN user part indicator", "isup.forw_call_isdn_user_part_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_ISDN_user_part_ind_value), F_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_forw_call_preferences_indicator,
+ { "ISDN user part preference indicator", "isup.forw_call_preferences_indicator",
+ FT_UINT16, BASE_HEX, VALS(isup_preferences_ind_value), HG_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_forw_call_isdn_access_indicator,
+ { "ISDN access indicator", "isup.forw_call_isdn_access_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_ISDN_originating_access_ind_value), I_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_forw_call_sccp_method_indicator,
+ { "SCCP method indicator", "isup.forw_call_sccp_method_indicator",
+ FT_UINT16, BASE_HEX, VALS(isup_SCCP_method_ind_value), KJ_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_calling_partys_category,
+ { "Calling Party's category", "isup.calling_partys_category",
+ FT_UINT8, BASE_HEX, VALS(isup_calling_partys_category_value), 0x0,
+ "", HFILL }},
+
+ { &hf_isup_transmission_medium_requirement,
+ { "Transmission medium requirement", "isup.transmission_medium_requirement",
+ FT_UINT8, BASE_DEC, VALS(isup_transmission_medium_requirement_value), 0x0,
+ "", HFILL }},
+
+ { &hf_isup_odd_even_indicator,
+ { "Odd/even indicator", "isup.isdn_odd_even_indicator",
+ FT_BOOLEAN, 8, TFS(&isup_odd_even_ind_value), ISUP_ODD_EVEN_MASK,
+ "", HFILL }},
+
+ { &hf_isup_called_party_nature_of_address_indicator,
+ { "Nature of address indicator", "isup.called_party_nature_of_address_indicator",
+ FT_UINT8, BASE_DEC, VALS(isup_called_party_nature_of_address_ind_value), ISUP_NATURE_OF_ADDRESS_IND_MASK,
+ "", HFILL }},
+
+ { &hf_isup_calling_party_nature_of_address_indicator,
+ { "Nature of address indicator", "isup.calling_party_nature_of_address_indicator",
+ FT_UINT8, BASE_DEC, VALS(isup_calling_party_nature_of_address_ind_value), ISUP_NATURE_OF_ADDRESS_IND_MASK,
+ "", HFILL }},
+
+ { &hf_isup_inn_indicator,
+ { "INN indicator", "isup.inn_indicator",
+ FT_BOOLEAN, 8, TFS(&isup_INN_ind_value), ISUP_INN_MASK,
+ "", HFILL }},
+
+ { &hf_isup_ni_indicator,
+ { "NI indicator", "isup.ni_indicator",
+ FT_BOOLEAN, 8, TFS(&isup_NI_ind_value), ISUP_NI_MASK,
+ "", HFILL }},
+
+ { &hf_isup_numbering_plan_indicator,
+ { "Numbering plan indicator", "isup.numbering_plan_indicator",
+ FT_UINT8, BASE_DEC, VALS(isup_numbering_plan_ind_value), ISUP_NUMBERING_PLAN_IND_MASK,
+ "", HFILL }},
+
+ { &hf_isup_address_presentation_restricted_indicator,
+ { "Address presentation restricted indicator", "isup.address_presentation_restricted_indicator",
+ FT_UINT8, BASE_DEC, VALS(isup_address_presentation_restricted_ind_value), ISUP_ADDRESS_PRESENTATION_RESTR_IND_MASK,
+ "", HFILL }},
+
+ { &hf_isup_screening_indicator,
+ { "Screening indicator", "isup.screening_indicator",
+ FT_UINT8, BASE_DEC, VALS(isup_screening_ind_value), ISUP_SCREENING_IND_MASK,
+ "", HFILL }},
+
+ { &hf_isup_screening_indicator_enhanced,
+ { "Screening indicator", "isup.screening_indicator_enhanced",
+ FT_UINT8, BASE_DEC, VALS(isup_screening_ind_enhanced_value), ISUP_SCREENING_IND_MASK,
+ "", HFILL }},
+
+ { &hf_isup_called_party_odd_address_signal_digit,
+ { "Address signal digit", "isup.called_party_odd_address_signal_digit",
+ FT_UINT8, BASE_DEC, VALS(isup_called_party_address_digit_value), ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_calling_party_odd_address_signal_digit,
+ { "Address signal digit", "isup.calling_party_odd_address_signal_digit",
+ FT_UINT8, BASE_DEC, VALS(isup_calling_party_address_digit_value), ISUP_ODD_ADDRESS_SIGNAL_DIGIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_called_party_even_address_signal_digit,
+ { "Address signal digit", "isup.called_party_even_address_signal_digit",
+ FT_UINT8, BASE_DEC, VALS(isup_called_party_address_digit_value), ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_calling_party_even_address_signal_digit,
+ { "Address signal digit", "isup.calling_party_even_address_signal_digit",
+ FT_UINT8, BASE_DEC, VALS(isup_calling_party_address_digit_value), ISUP_EVEN_ADDRESS_SIGNAL_DIGIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_calling_party_address_request_indicator,
+ { "Calling party address request indicator", "isup.calling_party_address_request_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_calling_party_address_request_ind_value), A_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_info_req_holding_indicator,
+ { "Holding indicator", "isup.info_req_holding_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_holding_ind_value), B_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_calling_partys_category_request_indicator,
+ { "Calling party's category request indicator", "isup.calling_partys_category_request_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_calling_partys_category_request_ind_value), D_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_charge_information_request_indicator,
+ { "Charge information request indicator", "isup.charge_information_request_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_charge_information_request_ind_value), E_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_malicious_call_identification_request_indicator,
+ { "Malicious call identification request indicator (ISUP'88)", "isup.malicious_call_ident_request_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_malicious_call_identification_request_ind_value), H_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_calling_party_address_response_indicator,
+ { "Calling party address response indicator", "isup.calling_party_address_response_indicator",
+ FT_UINT16, BASE_HEX, VALS(isup_calling_party_address_response_ind_value), BA_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_OECD_inf_ind,
+ { "OECD information indicator", "isup.OECD_inf_ind_vals",
+ FT_UINT8, BASE_HEX, VALS(OECD_inf_ind_vals), BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_IECD_inf_ind,
+ { "IECD information indicator", "isup.IECD_inf_ind_vals",
+ FT_UINT8, BASE_HEX, VALS(IECD_inf_ind_vals), DC_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_OECD_req_ind,
+ { "OECD request indicator", "isup.OECD_req_ind_vals",
+ FT_UINT8, BASE_HEX, VALS(OECD_req_ind_vals), FE_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_IECD_req_ind,
+ { "IECD request indicator", "isup.IECD_req_ind_vals",
+ FT_UINT8, BASE_HEX, VALS(IECD_req_ind_vals), HG_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_hold_provided_indicator,
+ { "Hold provided indicator", "isup.hold_provided_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_hold_provided_ind_value), C_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_calling_partys_category_response_indicator,
+ { "Calling party's category response indicator", "isup.calling_partys_category_response_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_calling_partys_category_response_ind_value), F_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_charge_information_response_indicator,
+ { "Charge information response indicator", "isup.charge_information_response_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_charge_information_response_ind_value), G_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_solicited_indicator,
+ { "Solicited indicator", "isup.solicided_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_solicited_information_ind_value), H_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_continuity_indicator,
+ { "Continuity indicator", "isup.continuity_indicator",
+ FT_BOOLEAN, 8, TFS(&isup_continuity_ind_value), A_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_charge_ind,
+ { "Charge indicator", "isup.charge_indicator",
+ FT_UINT16, BASE_HEX, VALS(isup_charge_ind_value), BA_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_called_partys_status_ind,
+ { "Called party's status indicator", "isup.called_partys_status_indicator",
+ FT_UINT16, BASE_HEX, VALS(isup_called_partys_status_ind_value), DC_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_called_partys_category_ind,
+ { "Called party's category indicator", "isup.called_partys_category_indicator",
+ FT_UINT16, BASE_HEX, VALS(isup_called_partys_category_ind_value), FE_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_end_to_end_method_ind,
+ { "End-to-end method indicator", "isup.backw_call_end_to_end_method_indicator",
+ FT_UINT16, BASE_HEX, VALS(isup_end_to_end_method_ind_value), HG_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_interworking_ind,
+ { "Interworking indicator", "isup.backw_call_interworking_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_interworking_ind_value), I_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_end_to_end_info_ind,
+ { "End-to-end information indicator", "isup.backw_call_end_to_end_information_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_end_to_end_info_ind_value), J_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_isdn_user_part_ind,
+ { "ISDN user part indicator", "isup.backw_call_isdn_user_part_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_ISDN_user_part_ind_value), K_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_holding_ind,
+ { "Holding indicator", "isup.backw_call_holding_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_holding_ind_value), L_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_isdn_access_ind,
+ { "ISDN access indicator", "isup.backw_call_isdn_access_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_ISDN_terminating_access_ind_value), M_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_echo_control_device_ind,
+ { "Echo Control Device Indicator", "isup.backw_call_echo_control_device_indicator",
+ FT_BOOLEAN, 16, TFS(&isup_echo_control_device_ind_value), N_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_backw_call_sccp_method_ind,
+ { "SCCP method indicator", "isup.backw_call_sccp_method_indicator",
+ FT_UINT16, BASE_HEX, VALS(isup_SCCP_method_ind_value), PO_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_cause_indicator,
+ { "Cause indicator", "isup.cause_indicator",
+ FT_UINT8, BASE_DEC, VALS(q850_cause_code_vals), 0x7f,
+ "", HFILL }},
+
+ { &hf_isup_suspend_resume_indicator,
+ { "Suspend/Resume indicator", "isup.suspend_resume_indicator",
+ FT_BOOLEAN, 8, TFS(&isup_suspend_resume_ind_value), A_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_range_indicator,
+ { "Range indicator", "isup.range_indicator",
+ FT_UINT8, BASE_DEC, NULL , 0x0,
+ "", HFILL }},
+
+ { &hf_isup_cgs_message_type,
+ { "Circuit group supervision message type", "isup.cgs_message_type",
+ FT_UINT8, BASE_DEC, VALS(isup_cgs_message_type_value), BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_mtc_blocking_state1,
+ { "Maintenance blocking state", "isup.mtc_blocking_state",
+ FT_UINT8, BASE_DEC, VALS(isup_mtc_blocking_state_DC00_value), BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_mtc_blocking_state2,
+ { "Maintenance blocking state", "isup.mtc_blocking_state",
+ FT_UINT8, BASE_DEC, VALS(isup_mtc_blocking_state_DCnot00_value), BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_call_proc_state,
+ { "Call processing state", "isup.call_processing_state",
+ FT_UINT8, BASE_DEC, VALS(isup_call_processing_state_value), DC_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_hw_blocking_state,
+ { "HW blocking state", "isup.hw_blocking_state",
+ FT_UINT8, BASE_DEC, VALS(isup_HW_blocking_state_value), FE_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_event_ind,
+ { "Event indicator", "isup.event_ind",
+ FT_UINT8, 8, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_isup_event_presentation_restricted_ind,
+ { "Event presentation restricted indicator", "isup.event_presentatiation_restr_ind",
+ FT_BOOLEAN, 8, TFS(&isup_event_presentation_restricted_ind_value), H_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_cug_call_ind,
+ { "Closed user group call indicator", "isup.clg_call_ind",
+ FT_UINT8, BASE_DEC, VALS(isup_CUG_call_ind_value), BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_simple_segmentation_ind,
+ { "Simple segmentation indicator", "isup.simple_segmentation_ind",
+ FT_BOOLEAN, 8, TFS(&isup_simple_segmentation_ind_value), C_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_connected_line_identity_request_ind,
+ { "Connected line identity request indicator", "isup.connected_line_identity_request_ind",
+ FT_BOOLEAN, 8, TFS(&isup_connected_line_identity_request_ind_value), H_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_redirecting_ind,
+ { "Redirection indicator", "isup.redirecting_ind",
+ FT_UINT16, BASE_DEC, VALS(isup_redirecting_ind_value), CBA_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_original_redirection_reason,
+ { "Original redirection reason", "isup.original_redirection_reason",
+ FT_UINT16, BASE_DEC, VALS(isup_original_redirection_reason_value), HGFE_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_redirection_counter,
+ { "Redirection counter", "isup.redirection_counter",
+ FT_UINT16, BASE_DEC, NULL, KJI_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_redirection_reason,
+ { "Redirection reason", "isup.redirection_reason",
+ FT_UINT16, BASE_DEC, VALS(isup_redirection_reason_value), PONM_16BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_type_of_network_identification,
+ { "Type of network identification", "isup.type_of_network_identification",
+ FT_UINT8, BASE_DEC, VALS(isup_type_of_network_identification_value), GFE_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_network_identification_plan,
+ { "Network identification plan", "isup.network_identification_plan",
+ FT_UINT8, BASE_DEC, VALS(isup_network_identification_plan_value), DCBA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_map_type,
+ { "Map Type", "isup.map_type",
+ FT_UINT8, BASE_DEC, VALS(isup_map_type_value), FEDCBA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_automatic_congestion_level,
+ { "Automatic congestion level", "isup.automatic_congestion_level",
+ FT_UINT8, BASE_DEC, VALS(isup_auto_congestion_level_value), 0x0,
+ "", HFILL }},
+
+ { &hf_isup_inband_information_ind,
+ { "In-band information indicator", "isup.inband_information_ind",
+ FT_BOOLEAN, 8, TFS(&isup_inband_information_ind_value), A_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_call_diversion_may_occur_ind,
+ { "Call diversion may occur indicator", "isup.call_diversion_may_occur_ind",
+ FT_BOOLEAN, 8, TFS(&isup_call_diversion_may_occur_ind_value), B_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_mlpp_user_ind,
+ { "MLPP user indicator", "isup.mlpp_user",
+ FT_BOOLEAN, 8, TFS(&isup_MLPP_user_ind_value), D_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_UUI_type,
+ { "User-to-User indicator type", "isup.UUI_type",
+ FT_BOOLEAN, 8, TFS(&isup_UUI_type_value), A_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_UUI_req_service1,
+ { "User-to-User indicator request service 1", "isup.UUI_req_service1",
+ FT_UINT8, BASE_DEC, VALS(isup_UUI_request_service_values), CB_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_UUI_req_service2,
+ { "User-to-User indicator request service 2", "isup.UUI_req_service2",
+ FT_UINT8, BASE_DEC, VALS(isup_UUI_request_service_values), ED_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_UUI_req_service3,
+ { "User-to-User indicator request service 3", "isup.UUI_req_service3",
+ FT_UINT8, BASE_DEC, VALS(isup_UUI_request_service_values), GF_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_UUI_res_service1,
+ { "User-to-User indicator response service 1", "isup.UUI_res_service1",
+ FT_UINT8, BASE_DEC, VALS(isup_UUI_response_service_values), CB_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_UUI_res_service2,
+ { "User-to-User indicator response service 2", "isup.UUI_res_service2",
+ FT_UINT8, BASE_DEC, VALS(isup_UUI_response_service_values), ED_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_UUI_res_service3,
+ { "User-to-User response service 3", "isup.UUI_res_service3",
+ FT_UINT8, BASE_DEC, VALS(isup_UUI_response_service_values), GF_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_UUI_network_discard_ind,
+ { "User-to-User indicator network discard indicator", "isup.UUI_network_discard_ind",
+ FT_BOOLEAN, 8, TFS(&isup_UUI_network_discard_ind_value), H_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_access_delivery_ind,
+ { "Access delivery indicator", "isup.access_delivery_ind",
+ FT_BOOLEAN, 8, TFS(&isup_access_delivery_ind_value), A_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_transmission_medium_requirement_prime,
+ { "Transmission medium requirement prime", "isup.transmission_medium_requirement_prime",
+ FT_UINT8, BASE_DEC, VALS(isup_transmission_medium_requirement_prime_value), 0x0,
+ "", HFILL }},
+
+ { &hf_isup_loop_prevention_response_ind,
+ { "Response indicator", "isup.loop_prevention_response_ind",
+ FT_UINT8, BASE_DEC, VALS(isup_loop_prevention_response_ind_value), CB_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_temporary_alternative_routing_ind,
+ { "Temporary alternative routing indicator", "isup.temporary_alternative_routing_ind",
+ FT_BOOLEAN, 8, TFS(&isup_temporary_alternative_routing_ind_value), A_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_extension_ind,
+ { "Extension indicator", "isup.extension_ind",
+ FT_BOOLEAN, 8, TFS(&isup_extension_ind_value), H_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_call_to_be_diverted_ind,
+ { "Call to be diverted indicator", "isup.call_to_be_diverted_ind",
+ FT_UINT8, BASE_DEC, VALS(isup_call_to_be_diverted_ind_value), BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_call_to_be_offered_ind,
+ { "Call to be offered indicator", "isup.call_to_be_offered_ind",
+ FT_UINT8, BASE_DEC, VALS(isup_call_to_be_offered_ind_value), BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_conference_acceptance_ind,
+ { "Conference acceptance indicator", "isup.conference_acceptance_ind",
+ FT_UINT8, BASE_DEC, VALS(isup_conference_acceptance_ind_value), BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_transit_at_intermediate_exchange_ind,
+ { "Transit at intermediate exchange indicator", "isup.transit_at_intermediate_exchange_ind",
+ FT_BOOLEAN, 8, TFS(&isup_transit_at_intermediate_exchange_ind_value), A_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_Release_call_ind,
+ { "Release call indicator", "isup.Release_call_ind",
+ FT_BOOLEAN, 8, TFS(&isup_Release_call_indicator_value), B_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_Send_notification_ind,
+ { "Send notification indicator", "isup.Send_notification_ind",
+ FT_BOOLEAN, 8, TFS(&isup_Send_notification_ind_value),C_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_Discard_message_ind_value,
+ { "Discard message indicator","isup.Discard_message_ind_value",
+ FT_BOOLEAN, 8, TFS(&isup_Discard_message_ind_value), D_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_Discard_parameter_ind,
+ { "Discard parameter indicator","isup.Discard_parameter_ind",
+ FT_BOOLEAN, 8, TFS(&isup_Discard_parameter_ind_value), E_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_Pass_on_not_possible_indicator,
+ { "Pass on not possible indicator", "isup_Pass_on_not_possible_ind",
+ FT_UINT8, BASE_HEX, VALS(isup_Pass_on_not_possible_indicator_vals),GF_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_pass_on_not_possible_indicator2,
+ { "Pass on not possible indicator", "isup_Pass_on_not_possible_val",
+ FT_BOOLEAN, 8, TFS(&isup_pass_on_not_possible_indicator_value),E_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_Broadband_narrowband_interworking_ind,
+ { "Broadband narrowband interworking indicator Bits JF", "isup_broadband-narrowband_interworking_ind",
+ FT_UINT8, BASE_HEX, VALS(ISUP_Broadband_narrowband_interworking_indicator_vals),BA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_Broadband_narrowband_interworking_ind2,
+ { "Broadband narrowband interworking indicator Bits GF", "isup_broadband-narrowband_interworking_ind2",
+ FT_UINT8, BASE_HEX, VALS(ISUP_Broadband_narrowband_interworking_indicator_vals),GF_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_app_cont_ident,
+ { "Application context identifier", "isup.app_context_identifier",
+ FT_UINT8, BASE_DEC, VALS(isup_application_transport_parameter_value),0x0,
+ "", HFILL }},
+
+ { &hf_isup_app_Release_call_ind,
+ { "Release call indicator (RCI)", "isup.app_Release_call_indicator",
+ FT_BOOLEAN, 8, TFS(&isup_Release_call_indicator_value), A_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_app_Send_notification_ind,
+ { "Send notification indicator (SNI)", "isup.app_Send_notification_ind",
+ FT_BOOLEAN, 8, TFS(&isup_Send_notification_ind_value), B_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_apm_segmentation_ind,
+ { "APM segmentation indicator", "isup.apm_segmentation_ind",
+ FT_UINT8, BASE_DEC, VALS(isup_APM_segmentation_ind_value), FEDCBA_8BIT_MASK,
+ "", HFILL }},
+
+ { &hf_isup_apm_si_ind,
+ { "Sequence indicator (SI)", "isup.APM_Sequence_ind",
+ FT_BOOLEAN, 8, TFS(&isup_Sequence_ind_value), G_8BIT_MASK,
+ "", HFILL }},
+ { &hf_bat_ase_identifier,
+ { "BAT ASE Identifiers", "bicc.bat_ase_identifier",
+ FT_UINT8, BASE_HEX, VALS(bat_ase_list_of_Identifiers_vals),0x0,
+ "", HFILL }},
+
+ { &hf_length_indicator,
+ { "BAT ASE Element length indicator", "bicc.bat_ase_length_indicator",
+ FT_UINT8, BASE_DEC, NULL,0x0,
+ "", HFILL }},
+
+ { &hf_Action_Indicator,
+ { "BAT ASE action indicator field", "bicc.bat_ase_bat_ase_action_indicator_field",
+ FT_UINT8, BASE_HEX, VALS(bat_ase_action_indicator_field_vals),0x00,
+ "", HFILL }},
+
+ { &hf_Instruction_ind_for_general_action,
+ { "BAT ASE Instruction indicator for general action", "bicc.bat_ase_Instruction_ind_for_general_action",
+ FT_UINT8, BASE_HEX, VALS(Instruction_indicator_for_general_action_vals),0x03,
+ "", HFILL }},
+
+ { &hf_Send_notification_ind_for_general_action,
+ { "Send notification indicator for general action", "bicc.bat_ase_Send_notification_ind_for_general_action",
+ FT_BOOLEAN, 8, TFS(&isup_Send_notification_ind_value), 0x04,
+ "", HFILL }},
+
+ { &hf_Instruction_ind_for_pass_on_not_possible,
+ { "Instruction ind for pass-on not possible", "bicc.bat_ase_Instruction_ind_for_pass_on_not_possible",
+ FT_UINT8, BASE_HEX, VALS(Instruction_indicator_for_pass_on_not_possible_vals),0x30,
+ "", HFILL }},
+
+ { &hf_Send_notification_ind_for_pass_on_not_possible,
+ { "Send notification indication for pass-on not possible", "bicc.bat_ase_Send_notification_ind_for_pass_on_not_possible",
+ FT_BOOLEAN, 8, TFS(&isup_Send_notification_ind_value), 0x40,
+ "", HFILL }},
+
+ { &hf_BCTP_Version_Indicator,
+ { "BCTP Version Indicator", "bicc.bat_ase_BCTP_Version_Indicator",
+ FT_UINT8, BASE_DEC, NULL,0x1f,
+ "", HFILL }},
+
+ { &hf_BVEI,
+ { "BVEI", "bicc.bat_ase_BCTP_BVEI",
+ FT_BOOLEAN, 8, TFS(&BCTP_BVEI_value), 0x40,
+ "", HFILL }},
+
+ { &hf_Tunnelled_Protocol_Indicator,
+ { "Tunnelled Protocol Indicator", "bicc.bat_ase_BCTP_Tunnelled_Protocol_Indicator",
+ FT_UINT8, BASE_DEC, VALS(BCTP_Tunnelled_Protocol_Indicator_vals),0x3f,
+ "", HFILL }},
+
+ { &hf_TPEI,
+ { "TPEI", "bicc.bat_ase_BCTP_tpei",
+ FT_BOOLEAN, 8, TFS(&BCTP_TPEI_value), 0x40,
+ "", HFILL }},
+
+ { &hf_bncid,
+ { "Backbone Network Connection Identifier (BNCId)", "bat_ase.bncid",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_bat_ase_biwfa,
+ { "Interworking Function Address( X.213 NSAP encoded)", "bat_ase_biwfa",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_afi,
+ { "X.213 Address Format Information ( AFI )", "x213.afi",
+ FT_UINT8, BASE_HEX, VALS(x213_afi_value),0x0,
+ "", HFILL }},
+
+ { &hf_characteristics,
+ { "Backbone network connection characteristics", "bat_ase.char",
+ FT_UINT8, BASE_HEX, VALS(bearer_network_connection_characteristics_vals),0x0,
+ "", HFILL }},
+
+ { &hf_Organization_Identifier,
+ { "Organization identifier subfield ", "bat_ase.organization_identifier_subfield",
+ FT_UINT8, BASE_DEC, VALS(bat_ase_organization_identifier_subfield_vals),0x0,
+ "", HFILL }},
+
+ { &hf_codec_type,
+ { "ITU-T codec type subfield", "bat_ase.ITU_T_codec_type_subfield",
+ FT_UINT8, BASE_HEX, VALS(ITU_T_codec_type_subfield_vals),0x0,
+ "", HFILL }},
+
+ { &hf_etsi_codec_type,
+ { "ETSI codec type subfield", "bat_ase.ETSI_codec_type_subfield",
+ FT_UINT8, BASE_HEX, VALS(ETSI_codec_type_subfield_vals),0x0,
+ "", HFILL }},
+
+
+ { &hf_bearer_control_tunneling,
+ { "Bearer control tunneling", "bat_ase.bearer_control_tunneling",
+ FT_BOOLEAN, 8, TFS(&Bearer_Control_Tunnelling_ind_value),0x01,
+ "", HFILL }},
+
+ { &hf_BAT_ASE_Comp_Report_Reason,
+ { "Compabillity report reason", "bat_ase.Comp_Report_Reason",
+ FT_UINT8, BASE_HEX, VALS(BAT_ASE_Report_Reason_vals),0x0,
+ "", HFILL }},
+
+
+ { &hf_BAT_ASE_Comp_Report_ident,
+ { "Bearer control tunneling", "bat_ase.bearer_control_tunneling",
+ FT_UINT8, BASE_HEX, VALS(bat_ase_list_of_Identifiers_vals),0x0,
+ "", HFILL }},
+
+ { &hf_BAT_ASE_Comp_Report_diagnostic,
+ { "Diagnostics", "bat_ase.Comp_Report_diagnostic",
+ FT_UINT16, BASE_HEX, NULL,0x0,
+ "", HFILL }},
+
+ { &hf_Local_BCU_ID,
+ { "Local BCU ID", "bat_ase.Local_BCU_ID",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_late_cut_trough_cap_ind,
+ { "Late Cut-through capability indicator", "bat_ase.late_cut_trough_cap_ind",
+ FT_BOOLEAN, 8, TFS(&late_cut_trough_cap_ind_value),0x01,
+ "", HFILL }},
+
+ { &hf_bat_ase_signal,
+ { "Q.765.5 - Signal Type", "bat_ase.signal_type",
+ FT_UINT8, BASE_HEX, VALS(BAt_ASE_Signal_Type_vals),0x0,
+ "", HFILL }},
+
+ { &hf_bat_ase_duration,
+ { "Duration in ms", "bat_ase.signal_type",
+ FT_UINT16, BASE_DEC, NULL,0x0,
+ "", HFILL }},
+
+ { &hf_bat_ase_bearer_redir_ind,
+ { "Redirection Indicator", "bat_ase.bearer_redir_ind",
+ FT_UINT8, BASE_HEX, VALS(Bearer_Redirection_Indicator_vals),0x0,
+ "", HFILL }},
+
+ { &hf_nsap_ipv4_addr,
+ { "IWFA IPv4 Address", "nsap.ipv4_addr",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "IPv4 address", HFILL }},
+
+ { &hf_nsap_ipv6_addr,
+ { "IWFA IPv6 Address", "nsap.ipv6_addr",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "IPv6 address", HFILL}},
+
+ { &hf_iana_icp,
+ { "IANA ICP", "nsap.iana_icp",
+ FT_UINT16, BASE_HEX, VALS(iana_icp_values),0x0,
+ "", HFILL }},
+
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_isup,
+ &ett_isup_parameter,
+ &ett_isup_address_digits,
+ &ett_isup_pass_along_message,
+ &ett_isup_circuit_state_ind,
+ &ett_bat_ase,
+ &ett_bat_ase_element,
+ &ett_bat_ase_iwfa
+ };
+
+/* Register the protocol name and description */
+ proto_isup = proto_register_protocol("ISDN User Part",
+ "ISUP", "isup");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_isup, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ isup_tap = register_tap("isup");
+
+ isup_module = prefs_register_protocol(proto_isup, NULL);
+
+ prefs_register_bool_preference(isup_module, "show_cic_in_info", "Show CIC in Info column",
+ "Show the CIC value (in addition to the message type) in the Info column",
+ (gint *)&isup_show_cic_in_info);
+}
+
+
+/* ------------------------------------------------------------------ */
+/* Register isup with the sub-laying MTP L3 dissector */
+void
+proto_reg_handoff_isup(void)
+{
+ dissector_handle_t isup_handle;
+ dissector_handle_t application_isup_handle;
+
+ isup_handle = create_dissector_handle(dissect_isup, proto_isup);
+ application_isup_handle = create_dissector_handle(dissect_application_isup, proto_isup);
+ dissector_add("mtp3.service_indicator", MTP3_ISUP_SERVICE_INDICATOR, isup_handle);
+ dissector_add("m3ua.protocol_data_si", MTP3_ISUP_SERVICE_INDICATOR, isup_handle);
+ dissector_add_string("media_type","application/isup", application_isup_handle);
+
+}
+
+void
+proto_register_bicc(void)
+{
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_bicc_cic,
+ { "Call identification Code (CIC)", "bicc.cic",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_bicc
+ };
+ proto_bicc = proto_register_protocol("Bearer Independent Call Control ",
+ "BICC", "bicc");
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_bicc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+/* Register isup with the sub-laying MTP L3 dissector */
+void
+proto_reg_handoff_bicc(void)
+{
+ dissector_handle_t bicc_handle;
+ sdp_handle = find_dissector("sdp");
+ q931_ie_handle = find_dissector("q931.ie");
+
+ bicc_handle = create_dissector_handle(dissect_bicc, proto_bicc);
+ dissector_add("mtp3.service_indicator", MTP3_BICC_SERVICE_INDICATOR, bicc_handle);
+ dissector_add("m3ua.protocol_data_si", MTP3_BICC_SERVICE_INDICATOR, bicc_handle);
+}
diff --git a/epan/dissectors/packet-isup.h b/epan/dissectors/packet-isup.h
new file mode 100644
index 0000000000..0704d05417
--- /dev/null
+++ b/epan/dissectors/packet-isup.h
@@ -0,0 +1,41 @@
+/* packet-isup.h
+ *
+ * $Id$
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>,
+ * In association with Telos Technology Inc.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define ISUP_MAX_NUM_MESSAGE_TYPES 256
+
+typedef struct _isup_tap_rec_t {
+ guint8 message_type;
+} isup_tap_rec_t;
+
+
+/*
+ * the following allows TAP code access to the messages
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string isup_message_type_value[];
+ETH_VAR_IMPORT const value_string isup_message_type_value_acro[];
+
diff --git a/epan/dissectors/packet-iua.c b/epan/dissectors/packet-iua.c
new file mode 100644
index 0000000000..516961cd71
--- /dev/null
+++ b/epan/dissectors/packet-iua.c
@@ -0,0 +1,909 @@
+/* packet-iua.c
+ * Routines for ISDN Q.921-User Adaptation Layer dissection
+ *
+ * It is hopefully (needs testing) compilant to
+ * http://www.ietf.org/rfc/rfc3057.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-iua-imp-guide-01.txt
+ * To do: - provide better handling of length parameters
+ *
+ * Copyright 2002, Michael Tuexen <tuexen [AT] fh-muenster.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include "sctpppids.h"
+
+#define NETWORK_BYTE_ORDER FALSE
+
+static module_t *iua_module;
+
+/* Initialize the protocol and registered fields */
+static int proto_iua = -1;
+static int hf_int_interface_id = -1;
+static int hf_text_interface_id = -1;
+static int hf_info_string = -1;
+static int hf_dlci_zero_bit = -1;
+static int hf_dlci_spare_bit = -1;
+static int hf_dlci_sapi = -1;
+static int hf_dlci_one_bit = -1;
+static int hf_dlci_tei = -1;
+static int hf_dlci_spare = -1;
+static int hf_diag_info = -1;
+static int hf_interface_range_start = -1;
+static int hf_interface_range_end = -1;
+static int hf_heartbeat_data = -1;
+static int hf_asp_reason = -1;
+static int hf_traffic_mode_type = -1;
+static int hf_error_code = -1;
+static int hf_error_code_ig = -1;
+static int hf_status_type = -1;
+static int hf_status_id = -1;
+static int hf_release_reason = -1;
+static int hf_tei_status = -1;
+static int hf_asp_id = -1;
+static int hf_parameter_tag = -1;
+static int hf_parameter_tag_ig = -1;
+static int hf_parameter_length = -1;
+static int hf_parameter_value = -1;
+static int hf_parameter_padding = -1;
+static int hf_version = -1;
+static int hf_reserved = -1;
+static int hf_message_class = -1;
+static int hf_message_type = -1;
+static int hf_message_length = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_iua = -1;
+static gint ett_iua_parameter = -1;
+
+/* option setable via preferences, default is plain RFC 3057 */
+static gboolean support_IG = FALSE;
+
+static dissector_handle_t q931_handle;
+
+#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
+
+#define PARAMETER_TAG_LENGTH 2
+#define PARAMETER_LENGTH_LENGTH 2
+#define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
+
+#define PARAMETER_TAG_OFFSET 0
+#define PARAMETER_LENGTH_OFFSET (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
+#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
+#define PARAMETER_HEADER_OFFSET PARAMETER_TAG_OFFSET
+
+#define INT_INTERFACE_ID_OFFSET PARAMETER_VALUE_OFFSET
+#define INT_INTERFACE_ID_LENGTH 4
+
+static void
+dissect_int_interface_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_int_interface_id, parameter_tvb, INT_INTERFACE_ID_OFFSET, INT_INTERFACE_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%d)", tvb_get_ntohl(parameter_tvb, INT_INTERFACE_ID_OFFSET));
+}
+
+#define TEXT_INTERFACE_ID_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_text_interface_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 interface_id_length;
+
+ interface_id_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+
+ proto_tree_add_item(parameter_tree, hf_text_interface_id, parameter_tvb, TEXT_INTERFACE_ID_OFFSET, interface_id_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%.*s)", interface_id_length,
+ (const char *)tvb_get_ptr(parameter_tvb, TEXT_INTERFACE_ID_OFFSET, interface_id_length));
+}
+
+#define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_info_string_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 info_string_length;
+
+ info_string_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%.*s)", info_string_length,
+ (const char *)tvb_get_ptr(parameter_tvb, INFO_STRING_OFFSET, info_string_length));
+}
+
+#define DLCI_SAPI_LENGTH 1
+#define DLCI_TEI_LENGTH 1
+#define DLCI_SPARE_LENGTH 2
+
+#define DLCI_SAPI_OFFSET PARAMETER_VALUE_OFFSET
+#define DLCI_TEI_OFFSET (DLCI_SAPI_OFFSET + DLCI_SAPI_LENGTH)
+#define DLCI_SPARE_OFFSET (DLCI_TEI_OFFSET + DLCI_TEI_LENGTH)
+
+#define ZERO_BIT_MASK 0x01
+#define SPARE_BIT_MASK 0x02
+#define SAPI_MASK 0xfc
+#define ONE_BIT_MASK 0x01
+#define TEI_MASK 0xfe
+
+static void
+dissect_dlci_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_tree_add_item(parameter_tree, hf_dlci_zero_bit, parameter_tvb, DLCI_SAPI_OFFSET, DLCI_SAPI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_dlci_spare_bit, parameter_tvb, DLCI_SAPI_OFFSET, DLCI_SAPI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_dlci_sapi, parameter_tvb, DLCI_SAPI_OFFSET, DLCI_SAPI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_dlci_one_bit, parameter_tvb, DLCI_TEI_OFFSET, DLCI_TEI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_dlci_tei, parameter_tvb, DLCI_TEI_OFFSET, DLCI_TEI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_dlci_spare, parameter_tvb, DLCI_SPARE_OFFSET, DLCI_SPARE_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 diag_info_length;
+
+ diag_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_diag_info, parameter_tvb, PARAMETER_VALUE_OFFSET, diag_info_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", diag_info_length, plurality(diag_info_length, "", "s"));
+}
+
+#define START_LENGTH 4
+#define END_LENGTH 4
+#define INTERVAL_LENGTH (START_LENGTH + END_LENGTH)
+
+#define START_OFFSET 0
+#define END_OFFSET (START_OFFSET + START_LENGTH)
+
+static void
+dissect_integer_range_interface_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 number_of_ranges, range_number;
+ gint offset;
+
+ number_of_ranges = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / INTERVAL_LENGTH;
+ offset = PARAMETER_VALUE_OFFSET;
+ for(range_number = 1; range_number <= number_of_ranges; range_number++) {
+ proto_tree_add_item(parameter_tree, hf_interface_range_start, parameter_tvb, offset + START_OFFSET, START_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_interface_range_end, parameter_tvb, offset + END_OFFSET, END_LENGTH, NETWORK_BYTE_ORDER);
+ offset += INTERVAL_LENGTH;
+ };
+
+ proto_item_append_text(parameter_item, " (%u range%s)", number_of_ranges, plurality(number_of_ranges, "", "s"));
+}
+
+#define HEARTBEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 heartbeat_data_length;
+
+ heartbeat_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_heartbeat_data, parameter_tvb, HEARTBEAT_DATA_OFFSET, heartbeat_data_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
+}
+
+#define ASP_MGMT_REASON 1
+
+static const value_string asp_reason_values[] = {
+ { ASP_MGMT_REASON, "Management inhibit" },
+ { 0, NULL } };
+
+#define ASP_REASON_LENGTH 4
+#define ASP_REASON_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_asp_reason_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_asp_reason, parameter_tvb, ASP_REASON_OFFSET, ASP_REASON_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ASP_REASON_OFFSET), asp_reason_values, "unknown"));
+}
+
+#define OVER_RIDE_TRAFFIC_MODE_TYPE 1
+#define LOAD_SHARE_TRAFFIC_MODE_TYPE 2
+
+static const value_string traffic_mode_type_values[] = {
+ { OVER_RIDE_TRAFFIC_MODE_TYPE, "Over-ride" },
+ { LOAD_SHARE_TRAFFIC_MODE_TYPE, "Load-share" },
+ { 0, NULL } };
+
+#define TRAFFIC_MODE_TYPE_LENGTH 4
+#define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)",
+ val_to_str(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), traffic_mode_type_values, "unknown"));
+}
+
+#define INVALID_VERSION_ERROR 0x01
+#define INVALID_INTERFACE_IDENTIFIER_ERROR 0x02
+#define UNSUPPORTED_MESSAGE_CLASS_ERROR 0x03
+#define UNSUPPORTED_MESSAGE_TYPE_ERROR 0x04
+#define UNSUPPORTED_TRAFFIC_HANDLING_MODE_ERROR 0x05
+#define UNEXPECTED_MESSAGE_ERROR 0x06
+#define PROTOCOL_ERROR 0x07
+#define UNSUPPORTED_INTERFACE_IDENTIFIER_TYPE_ERROR 0x08
+#define INVALID_STREAM_IDENTIFIER_ERROR 0x09
+#define UNASSIGNED_TEI_ERROR 0x0a
+#define UNRECOGNIZED_SAPI_ERROR 0x0b
+#define INVALID_TEI_SAPI_COMBINATION_ERROR 0x0c
+#define REFUSED_MANAGEMENT_BLOCKING_ERROR 0x0d
+#define ASP_IDENTIFIER_REQUIRED_ERROR 0x0e
+#define INVALID_ASP_IDENTIFIER_ERROR 0x0f
+
+static const value_string error_code_values[] = {
+ { INVALID_VERSION_ERROR, "Invalid version" },
+ { INVALID_INTERFACE_IDENTIFIER_ERROR, "Invalid interface identifier" },
+ { UNSUPPORTED_MESSAGE_CLASS_ERROR, "Unsuported message class" },
+ { UNSUPPORTED_MESSAGE_TYPE_ERROR, "Unsupported message type" },
+ { UNSUPPORTED_TRAFFIC_HANDLING_MODE_ERROR, "Unsupported traffic handling mode" },
+ { UNEXPECTED_MESSAGE_ERROR, "Unexpected message" },
+ { PROTOCOL_ERROR, "Protocol error" },
+ { UNSUPPORTED_INTERFACE_IDENTIFIER_TYPE_ERROR, "Unsupported interface identifier type" },
+ { INVALID_STREAM_IDENTIFIER_ERROR, "Invalid stream identifier" },
+ { UNASSIGNED_TEI_ERROR, "Unassigned TEI" },
+ { UNRECOGNIZED_SAPI_ERROR, "Unrecognized SAPI" },
+ { INVALID_TEI_SAPI_COMBINATION_ERROR, "Invalid TEI/SAPI combination" },
+ { 0, NULL } };
+
+static const value_string error_code_ig_values[] = {
+ { INVALID_VERSION_ERROR, "Invalid version" },
+ { INVALID_INTERFACE_IDENTIFIER_ERROR, "Invalid interface identifier" },
+ { UNSUPPORTED_MESSAGE_CLASS_ERROR, "Unsuported message class" },
+ { UNSUPPORTED_MESSAGE_TYPE_ERROR, "Unsupported message type" },
+ { UNSUPPORTED_TRAFFIC_HANDLING_MODE_ERROR, "Unsupported traffic handling mode" },
+ { UNEXPECTED_MESSAGE_ERROR, "Unexpected message" },
+ { PROTOCOL_ERROR, "Protocol error" },
+ { UNSUPPORTED_INTERFACE_IDENTIFIER_TYPE_ERROR, "Unsupported interface identifier type" },
+ { INVALID_STREAM_IDENTIFIER_ERROR, "Invalid stream identifier" },
+ { UNASSIGNED_TEI_ERROR, "Unassigned TEI" },
+ { UNRECOGNIZED_SAPI_ERROR, "Unrecognized SAPI" },
+ { INVALID_TEI_SAPI_COMBINATION_ERROR, "Invalid TEI/SAPI combination" },
+ { REFUSED_MANAGEMENT_BLOCKING_ERROR, "Refused - Management blocking" },
+ { ASP_IDENTIFIER_REQUIRED_ERROR, "ASP identifier required" },
+ { INVALID_ASP_IDENTIFIER_ERROR, "Invalid ASP identifier" },
+ { 0, NULL } };
+
+#define ERROR_CODE_LENGTH 4
+#define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, support_IG?hf_error_code_ig:hf_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)",
+ val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), support_IG?error_code_ig_values:error_code_values, "unknown"));
+}
+
+#define ASP_STATE_CHANGE_STATUS_TYPE 0x01
+#define OTHER_STATUS_TYPE 0x02
+
+static const value_string status_type_values[] = {
+ { ASP_STATE_CHANGE_STATUS_TYPE, "Application server state change" },
+ { OTHER_STATUS_TYPE, "Other" },
+ { 0, NULL } };
+
+#define AS_DOWN_STATUS_IDENT 0x01
+#define AS_INACTIVE_STATUS_IDENT 0x02
+#define AS_ACTIVE_STATUS_IDENT 0x03
+#define AS_PENDING_STATUS_IDENT 0x04
+
+#define INSUFFICIENT_ASP_RESOURCES_STATUS_IDENT 0x01
+#define ALTERNATE_ASP_ACTIVE_STATUS_IDENT 0x02
+
+static const value_string status_type_id_values[] = {
+ { ASP_STATE_CHANGE_STATUS_TYPE * 256 * 256 + AS_DOWN_STATUS_IDENT, "Application server down" },
+ { ASP_STATE_CHANGE_STATUS_TYPE * 256 * 256 + AS_INACTIVE_STATUS_IDENT, "Application server inactive" },
+ { ASP_STATE_CHANGE_STATUS_TYPE * 256 * 256 + AS_ACTIVE_STATUS_IDENT, "Application server active" },
+ { ASP_STATE_CHANGE_STATUS_TYPE * 256 * 256 + AS_PENDING_STATUS_IDENT, "Application server pending" },
+ { OTHER_STATUS_TYPE * 256 * 256 + INSUFFICIENT_ASP_RESOURCES_STATUS_IDENT, "Insufficient ASP resources active in AS" },
+ { OTHER_STATUS_TYPE * 256 * 256 + ALTERNATE_ASP_ACTIVE_STATUS_IDENT, "Alternate ASP active" },
+ { 0, NULL } };
+
+static const value_string status_type_id_ig_values[] = {
+ { ASP_STATE_CHANGE_STATUS_TYPE * 256 * 256 + AS_INACTIVE_STATUS_IDENT, "Application server inactive" },
+ { ASP_STATE_CHANGE_STATUS_TYPE * 256 * 256 + AS_ACTIVE_STATUS_IDENT, "Application server active" },
+ { ASP_STATE_CHANGE_STATUS_TYPE * 256 * 256 + AS_PENDING_STATUS_IDENT, "Application server pending" },
+ { OTHER_STATUS_TYPE * 256 * 256 + INSUFFICIENT_ASP_RESOURCES_STATUS_IDENT, "Insufficient ASP resources active in AS" },
+ { OTHER_STATUS_TYPE * 256 * 256 + ALTERNATE_ASP_ACTIVE_STATUS_IDENT, "Alternate ASP active" },
+ { 0, NULL } };
+
+#define STATUS_TYPE_LENGTH 2
+#define STATUS_IDENT_LENGTH 2
+#define STATUS_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+#define STATUS_IDENT_OFFSET (STATUS_TYPE_OFFSET + STATUS_TYPE_LENGTH)
+
+static void
+dissect_status_type_identification_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 status_type, status_id;
+
+ status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
+ status_id = tvb_get_ntohs(parameter_tvb, STATUS_IDENT_OFFSET);
+
+ proto_tree_add_item(parameter_tree, hf_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(parameter_tree, hf_status_id, parameter_tvb, STATUS_IDENT_OFFSET, STATUS_IDENT_LENGTH,
+ status_id, "Status identification: %u (%s)", status_id,
+ val_to_str(status_type * 256 * 256 + status_id, support_IG?status_type_id_ig_values:status_type_id_values, "unknown"));
+
+ proto_item_append_text(parameter_item, " (%s)",
+ val_to_str(status_type * 256 * 256 + status_id, support_IG?status_type_id_ig_values:status_type_id_values, "unknown status information"));
+}
+
+#define PROTOCOL_DATA_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_protocol_data_parameter(tvbuff_t *parameter_tvb, proto_item *parameter_item, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 protocol_data_length;
+ tvbuff_t *protocol_data_tvb;
+
+ protocol_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ protocol_data_tvb = tvb_new_subset(parameter_tvb, PROTOCOL_DATA_OFFSET, protocol_data_length, protocol_data_length);
+ call_dissector(q931_handle, protocol_data_tvb, pinfo, tree);
+
+ proto_item_append_text(parameter_item, " (%u byte%s)", protocol_data_length, plurality(protocol_data_length, "", "s"));
+}
+
+#define RELEASE_MGMT_REASON 0
+#define RELEASE_PHYS_REASON 1
+#define RELEASE_DM_REASON 2
+#define RELEASE_OTHER_REASON 4
+
+static const value_string release_reason_values[] = {
+ { RELEASE_MGMT_REASON, "Management layer generated release" },
+ { RELEASE_PHYS_REASON, "Physical layer alarm generated release" },
+ { RELEASE_DM_REASON, "Layer 2 should release" },
+ { RELEASE_OTHER_REASON, "Other reason" },
+ { 0, NULL } };
+
+#define RELEASE_REASON_OFFSET PARAMETER_VALUE_OFFSET
+#define RELEASE_REASON_LENGTH 4
+
+static void
+dissect_release_reason_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_release_reason, parameter_tvb, RELEASE_REASON_OFFSET, RELEASE_REASON_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)",
+ val_to_str(tvb_get_ntohl(parameter_tvb, RELEASE_REASON_OFFSET), release_reason_values, "unknown"));
+}
+
+#define TEI_STATUS_ASSIGNED 0
+#define TEI_STATUS_UNASSIGNED 1
+
+static const value_string tei_status_values[] = {
+ { TEI_STATUS_ASSIGNED, "TEI is considered assigned by Q.921" },
+ { TEI_STATUS_UNASSIGNED, "TEI is considered unassigned by Q.921" },
+ { 0, NULL } };
+
+#define TEI_STATUS_LENGTH 4
+#define TEI_STATUS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_tei_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_tei_status, parameter_tvb, TEI_STATUS_OFFSET, TEI_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)",
+ val_to_str(tvb_get_ntohl(parameter_tvb, TEI_STATUS_OFFSET), tei_status_values, "unknown"));
+}
+
+#define ASP_ID_LENGTH 4
+#define ASP_ID_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_asp_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_asp_id, parameter_tvb, ASP_ID_OFFSET, ASP_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, ASP_ID_OFFSET));
+}
+
+static void
+dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 parameter_value_length;
+
+ parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ if (parameter_value_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " with tag %u and %u byte%s value",
+ tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET), parameter_value_length, plurality(parameter_value_length, "", "s"));
+}
+
+#define INT_INTERFACE_IDENTIFIER_PARAMETER_TAG 0x01
+#define TEXT_INTERFACE_IDENTIFIER_PARAMETER_TAG 0x03
+#define INFO_PARAMETER_TAG 0x04
+#define DLCI_PARAMETER_TAG 0x05
+#define DIAGNOSTIC_INFORMATION_PARAMETER_TAG 0x07
+#define INTEGER_RANGE_INTERFACE_IDENTIFIER_PARAMETER_TAG 0x08
+#define HEARTBEAT_DATA_PARAMETER_TAG 0x09
+#define ASP_REASON_PARAMETER_TAG 0x0a
+#define TRAFFIC_MODE_TYPE_PARAMETER_TAG 0x0b
+#define ERROR_CODE_PARAMETER_TAG 0x0c
+#define STATUS_TYPE_INDENTIFICATION_PARAMETER_TAG 0x0d
+#define PROTOCOL_DATA_PARAMETER_TAG 0x0e
+#define RELEASE_REASON_PARAMETER_TAG 0x0f
+#define TEI_STATUS_PARAMETER_TAG 0x10
+#define ASP_IDENTIFIER_PARAMETER_TAG 0x11
+
+static const value_string parameter_tag_values[] = {
+ { INT_INTERFACE_IDENTIFIER_PARAMETER_TAG, "Integer interface identifier" },
+ { TEXT_INTERFACE_IDENTIFIER_PARAMETER_TAG, "Text interface identifier" },
+ { INFO_PARAMETER_TAG, "Info" },
+ { DLCI_PARAMETER_TAG, "DLCI" },
+ { DIAGNOSTIC_INFORMATION_PARAMETER_TAG, "Diagnostic information" },
+ { INTEGER_RANGE_INTERFACE_IDENTIFIER_PARAMETER_TAG, "Integer range interface identifier" },
+ { HEARTBEAT_DATA_PARAMETER_TAG, "Hearbeat data" },
+ { ASP_REASON_PARAMETER_TAG, "Reason" },
+ { TRAFFIC_MODE_TYPE_PARAMETER_TAG, "Traffic mode type" },
+ { ERROR_CODE_PARAMETER_TAG, "Error code" },
+ { STATUS_TYPE_INDENTIFICATION_PARAMETER_TAG, "Status type/identification" },
+ { PROTOCOL_DATA_PARAMETER_TAG, "Protocol data" },
+ { RELEASE_REASON_PARAMETER_TAG, "Reason" },
+ { TEI_STATUS_PARAMETER_TAG, "TEI status" },
+ { 0, NULL } };
+
+static const value_string parameter_tag_ig_values[] = {
+ { INT_INTERFACE_IDENTIFIER_PARAMETER_TAG, "Integer interface identifier" },
+ { TEXT_INTERFACE_IDENTIFIER_PARAMETER_TAG, "Text interface identifier" },
+ { INFO_PARAMETER_TAG, "Info" },
+ { DLCI_PARAMETER_TAG, "DLCI" },
+ { DIAGNOSTIC_INFORMATION_PARAMETER_TAG, "Diagnostic information" },
+ { INTEGER_RANGE_INTERFACE_IDENTIFIER_PARAMETER_TAG, "Integer range interface identifier" },
+ { HEARTBEAT_DATA_PARAMETER_TAG, "Hearbeat data" },
+ { TRAFFIC_MODE_TYPE_PARAMETER_TAG, "Traffic mode type" },
+ { ERROR_CODE_PARAMETER_TAG, "Error code" },
+ { STATUS_TYPE_INDENTIFICATION_PARAMETER_TAG, "Status type/identification" },
+ { PROTOCOL_DATA_PARAMETER_TAG, "Protocol data" },
+ { RELEASE_REASON_PARAMETER_TAG, "Reason" },
+ { TEI_STATUS_PARAMETER_TAG, "TEI status" },
+ { ASP_IDENTIFIER_PARAMETER_TAG, "ASP identifier"},
+ { 0, NULL } };
+
+static void
+dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *iua_tree)
+{
+ guint16 tag, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+
+ /* extract tag and length from the parameter */
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = tvb_length(parameter_tvb) - length;
+
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(iua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb),
+ val_to_str(tag, support_IG?parameter_tag_ig_values:parameter_tag_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_iua_parameter);
+
+ /* add tag and length to the iua tree */
+ proto_tree_add_item(parameter_tree, support_IG?hf_parameter_tag_ig:hf_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(tag) {
+ case INT_INTERFACE_IDENTIFIER_PARAMETER_TAG:
+ dissect_int_interface_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case TEXT_INTERFACE_IDENTIFIER_PARAMETER_TAG:
+ dissect_text_interface_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case INFO_PARAMETER_TAG:
+ dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case DLCI_PARAMETER_TAG:
+ dissect_dlci_parameter(parameter_tvb, parameter_tree);
+ break;
+ case DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
+ dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case INTEGER_RANGE_INTERFACE_IDENTIFIER_PARAMETER_TAG:
+ dissect_integer_range_interface_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case HEARTBEAT_DATA_PARAMETER_TAG:
+ dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ASP_REASON_PARAMETER_TAG:
+ if (support_IG)
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ else
+ dissect_asp_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
+ dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ERROR_CODE_PARAMETER_TAG:
+ dissect_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case STATUS_TYPE_INDENTIFICATION_PARAMETER_TAG:
+ dissect_status_type_identification_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PROTOCOL_DATA_PARAMETER_TAG:
+ dissect_protocol_data_parameter(parameter_tvb, parameter_item, pinfo, tree);
+ break;
+ case RELEASE_REASON_PARAMETER_TAG:
+ dissect_release_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case TEI_STATUS_PARAMETER_TAG:
+ dissect_tei_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ASP_IDENTIFIER_PARAMETER_TAG:
+ if (support_IG)
+ dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ else
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ default:
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ };
+
+ if (padding_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *iua_tree)
+{
+ gint offset, length, total_length, remaining_length;
+ tvbuff_t *parameter_tvb;
+
+ offset = 0;
+ while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
+ length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ if (remaining_length >= length)
+ total_length = MIN(total_length, remaining_length);
+ /* create a tvb for the parameter including the padding bytes */
+ parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
+ dissect_parameter(parameter_tvb, pinfo, tree, iua_tree);
+ /* get rid of the handled parameter */
+ offset += total_length;
+ }
+}
+
+#define VERSION_LENGTH 1
+#define RESERVED_LENGTH 1
+#define MESSAGE_CLASS_LENGTH 1
+#define MESSAGE_TYPE_LENGTH 1
+#define MESSAGE_LENGTH_LENGTH 4
+#define COMMON_HEADER_LENGTH (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
+ MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
+
+#define COMMON_HEADER_OFFSET 0
+#define VERSION_OFFSET COMMON_HEADER_OFFSET
+#define RESERVED_OFFSET (VERSION_OFFSET + VERSION_LENGTH)
+#define MESSAGE_CLASS_OFFSET (RESERVED_OFFSET + RESERVED_LENGTH)
+#define MESSAGE_TYPE_OFFSET (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
+#define MESSAGE_LENGTH_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
+#define PARAMETERS_OFFSET (COMMON_HEADER_OFFSET + COMMON_HEADER_LENGTH)
+
+#define PROTOCOL_VERSION_RELEASE_1 1
+
+static const value_string protocol_version_values[] = {
+ { PROTOCOL_VERSION_RELEASE_1, "Release 1" },
+ { 0, NULL } };
+
+#define MESSAGE_CLASS_MGMT_MESSAGE 0
+#define MESSAGE_CLASS_TFER_MESSAGE 1
+#define MESSAGE_CLASS_SSNM_MESSAGE 2
+#define MESSAGE_CLASS_ASPSM_MESSAGE 3
+#define MESSAGE_CLASS_ASPTM_MESSAGE 4
+#define MESSAGE_CLASS_QPTM_MESSAGE 5
+#define MESSAGE_CLASS_MAUP_MESSAGE 6
+#define MESSAGE_CLASS_CL_SUA_MESSAGE 7
+#define MESSAGE_CLASS_CO_SUA_MESSAGE 8
+
+static const value_string message_class_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE, "Management messages" },
+ { MESSAGE_CLASS_TFER_MESSAGE, "Transfer messages" },
+ { MESSAGE_CLASS_SSNM_MESSAGE, "SS7 signalling network management messages" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE, "ASP state maintenance messages" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE, "ASP traffic maintenance messages" },
+ { MESSAGE_CLASS_QPTM_MESSAGE, "Q.921/Q.931 boundary primitive transport messages" },
+ { MESSAGE_CLASS_MAUP_MESSAGE, "MTP2 user adaptation messages" },
+ { MESSAGE_CLASS_CL_SUA_MESSAGE, "Connectionless messages (SUA)" },
+ { MESSAGE_CLASS_CO_SUA_MESSAGE, "Connection-oriented messages (SUA)" },
+ { 0, NULL } };
+
+/* message types for MGMT messages */
+#define MESSAGE_TYPE_ERR 0
+#define MESSAGE_TYPE_NTFY 1
+#define MESSAGE_TYPE_TEI_STATUS_REQ 2
+#define MESSAGE_TYPE_TEI_STATUS_CON 3
+#define MESSAGE_TYPE_TEI_STATUS_IND 4
+#define MESSAGE_TYPE_TEI_QUERY_REQ 5
+
+/* message types for ASPSM messages */
+#define MESSAGE_TYPE_UP 1
+#define MESSAGE_TYPE_DOWN 2
+#define MESSAGE_TYPE_BEAT 3
+#define MESSAGE_TYPE_UP_ACK 4
+#define MESSAGE_TYPE_DOWN_ACK 5
+#define MESSAGE_TYPE_BEAT_ACK 6
+
+/* message types for ASPTM messages */
+#define MESSAGE_TYPE_ACTIVE 1
+#define MESSAGE_TYPE_INACTIVE 2
+#define MESSAGE_TYPE_ACTIVE_ACK 3
+#define MESSAGE_TYPE_INACTIVE_ACK 4
+
+/* message types for QPTM messages */
+#define MESSAGE_TYPE_DATA_REQUEST 1
+#define MESSAGE_TYPE_DATA_INDICATION 2
+#define MESSAGE_TYPE_UNIT_DATA_REQUEST 3
+#define MESSAGE_TYPE_UNIT_DATA_INDICATION 4
+#define MESSAGE_TYPE_ESTABLISH_REQUEST 5
+#define MESSAGE_TYPE_ESTABLISH_CONFIRM 6
+#define MESSAGE_TYPE_ESTABLISH_INDICATION 7
+#define MESSAGE_TYPE_RELEASE_REQUEST 8
+#define MESSAGE_TYPE_RELEASE_CONFIRM 9
+#define MESSAGE_TYPE_RELEASE_INDICATION 10
+
+
+static const value_string message_class_type_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "Error" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "Notify" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_REQ, "TEI status request" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_CON, "TEI status confirmation" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_IND, "TEI status indication" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP up" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP down" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "Heartbeat" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP up ack" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP down ack" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "Heartbeat ack" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP active" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP inactive" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP active ack" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_DATA_REQUEST, "Data request" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_DATA_INDICATION, "Data indication" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_UNIT_DATA_REQUEST, "Unit data request" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_UNIT_DATA_INDICATION, "Unit data indication" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_REQUEST, "Establish request" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_CONFIRM, "Establish confirmation" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_INDICATION, "Establish indication" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_REQUEST, "Release request" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_CONFIRM, "Release confirmation" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_INDICATION, "Release indication" },
+ { 0, NULL } };
+
+static const value_string message_class_type_ig_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "Error" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "Notify" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_REQ, "TEI status request" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_CON, "TEI status confirmation" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_IND, "TEI status indication" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_QUERY_REQ, "TEI query request" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP up" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP down" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "Heartbeat" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP up ack" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP down ack" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "Heartbeat ack" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP active" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP inactive" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP active ack" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_DATA_REQUEST, "Data request" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_DATA_INDICATION, "Data indication" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_UNIT_DATA_REQUEST, "Unit data request" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_UNIT_DATA_INDICATION, "Unit data indication" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_REQUEST, "Establish request" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_CONFIRM, "Establish confirmation" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_INDICATION, "Establish indication" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_REQUEST, "Release request" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_CONFIRM, "Release confirmation" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_INDICATION, "Release indication" },
+ { 0, NULL } };
+
+static const value_string message_class_type_acro_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "ERR" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "NTFY" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_REQ, "TEI_STAT_REQ" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_CON, "TEI_STAT_CON" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_IND, "TEI_STAT_IND" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP_UP" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP_DOWN" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "BEAT" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP_UP_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP_DOWN_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "BEAT_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP_ACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP_INACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP_ACTIVE_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_DATA_REQUEST, "DATA_REQ" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_DATA_INDICATION, "DATA_IND" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_UNIT_DATA_REQUEST, "U_DATA_REQ" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_UNIT_DATA_INDICATION, "U_DATA_IND" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_REQUEST, "EST_REQ" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_CONFIRM, "EST_CON" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_INDICATION, "EST_IND" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_REQUEST, "REL_REQ" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_CONFIRM, "REL_CON" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_INDICATION, "REL_IND" },
+ { 0, NULL } };
+
+static const value_string message_class_type_acro_ig_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "ERR" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "NTFY" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_REQ, "TEI_STAT_REQ" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_CON, "TEI_STAT_CON" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_STATUS_IND, "TEI_STAT_IND" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_TEI_QUERY_REQ, "TEI_QUERY_REQ" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP_UP" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP_DOWN" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "BEAT" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP_UP_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP_DOWN_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "BEAT_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP_ACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP_INACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP_ACTIVE_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_DATA_REQUEST, "DATA_REQ" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_DATA_INDICATION, "DATA_IND" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_UNIT_DATA_REQUEST, "U_DATA_REQ" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_UNIT_DATA_INDICATION, "U_DATA_IND" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_REQUEST, "EST_REQ" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_CONFIRM, "EST_CON" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_ESTABLISH_INDICATION, "EST_IND" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_REQUEST, "REL_REQ" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_CONFIRM, "REL_CON" },
+ { MESSAGE_CLASS_QPTM_MESSAGE * 256 + MESSAGE_TYPE_RELEASE_INDICATION, "REL_IND" },
+ { 0, NULL } };
+
+static void
+dissect_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *iua_tree)
+{
+ guint8 message_class, message_type;
+
+ message_class = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
+ message_type = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_class * 256 + message_type, support_IG?message_class_type_acro_ig_values:message_class_type_acro_values, "UNKNOWN"));
+
+ if (iua_tree) {
+ /* add the components of the common header to the protocol tree */
+ proto_tree_add_item(iua_tree, hf_version, common_header_tvb, VERSION_OFFSET, VERSION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(iua_tree, hf_reserved, common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(iua_tree, hf_message_class, common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(iua_tree, hf_message_type,
+ common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH,
+ message_type, "Message type: %u (%s)",
+ message_type, val_to_str(message_class * 256 + message_type, support_IG?message_class_type_ig_values:message_class_type_values, "reserved"));
+ proto_tree_add_item(iua_tree, hf_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ }
+}
+
+static void
+dissect_iua_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *iua_tree)
+{
+ tvbuff_t *common_header_tvb, *parameters_tvb;
+
+ common_header_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_OFFSET, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
+ parameters_tvb = tvb_new_subset(message_tvb, PARAMETERS_OFFSET, -1, -1);
+ dissect_common_header(common_header_tvb, pinfo, iua_tree);
+ dissect_parameters(parameters_tvb, pinfo, tree, iua_tree);
+}
+
+static void
+dissect_iua(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *iua_item;
+ proto_tree *iua_tree;
+
+ /* make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, support_IG?"IUA (RFC 3057 + IG)":"IUA (RFC 3057)");
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the m3ua protocol tree */
+ iua_item = proto_tree_add_item(tree, proto_iua, message_tvb, 0, -1, FALSE);
+ iua_tree = proto_item_add_subtree(iua_item, ett_iua);
+ } else {
+ iua_tree = NULL;
+ };
+ /* dissect the message */
+ dissect_iua_message(message_tvb, pinfo, tree, iua_tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_iua(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_int_interface_id, { "Integer interface identifier", "iua.int_interface_identifier", FT_INT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_text_interface_id, { "Text interface identifier", "iua.text_interface_identifier", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_info_string, { "Info string", "iua.info_string", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_dlci_zero_bit, { "Zero bit", "iua.dlci_zero_bit", FT_BOOLEAN, 8, NULL, ZERO_BIT_MASK, "", HFILL } },
+ { &hf_dlci_spare_bit, { "Spare bit", "iua.dlci_spare_bit", FT_BOOLEAN, 8, NULL, SPARE_BIT_MASK, "", HFILL } },
+ { &hf_dlci_sapi, { "SAPI", "iua.dlci_sapi", FT_UINT8, BASE_HEX, NULL, SAPI_MASK, "", HFILL } },
+ { &hf_dlci_one_bit, { "One bit", "iua.dlci_one_bit", FT_BOOLEAN, 8, NULL, ONE_BIT_MASK, "", HFILL } },
+ { &hf_dlci_tei, { "TEI", "iua.dlci_tei", FT_UINT8, BASE_HEX, NULL, TEI_MASK, "", HFILL } },
+ { &hf_dlci_spare, { "Spare", "iua.dlci_spare", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_diag_info, { "Diagnostic information", "iua.diagnostic_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_interface_range_start, { "Start", "iua.interface_range_start", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_interface_range_end, { "End", "iua.interface_range_end", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_heartbeat_data, { "Heartbeat data", "iua.heartbeat_data", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_asp_reason, { "Reason", "iua.asp_reason", FT_UINT32, BASE_HEX, VALS(asp_reason_values), 0x0, "", HFILL } },
+ { &hf_traffic_mode_type, { "Traffic mode type", "iua.traffic_mode_type", FT_UINT32, BASE_HEX, VALS(traffic_mode_type_values), 0x0, "", HFILL } },
+ { &hf_error_code, { "Error code", "iua.error_code", FT_UINT32, BASE_DEC, VALS(error_code_values), 0x0, "", HFILL } },
+ { &hf_error_code_ig, { "Error code", "iua.error_code", FT_UINT32, BASE_DEC, VALS(error_code_ig_values), 0x0, "", HFILL } },
+ { &hf_status_type, { "Status type", "iua.status_type", FT_UINT16, BASE_DEC, VALS(status_type_values), 0x0, "", HFILL } },
+ { &hf_status_id, { "Status identification", "iua.status_identification", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_release_reason, { "Reason", "iua.release_reason", FT_UINT32, BASE_HEX, VALS(release_reason_values), 0x0, "", HFILL } },
+ { &hf_tei_status, { "TEI status", "iua.tei_status", FT_UINT32, BASE_HEX, VALS(tei_status_values), 0x0, "", HFILL } },
+ { &hf_asp_id, { "ASP identifier", "iua.asp_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_tag, { "Parameter Tag", "iua.parameter_tag", FT_UINT16, BASE_DEC, VALS(parameter_tag_values), 0x0, "", HFILL } },
+ { &hf_parameter_tag_ig, { "Parameter Tag", "iua.parameter_tag", FT_UINT16, BASE_DEC, VALS(parameter_tag_ig_values), 0x0, "", HFILL } },
+ { &hf_parameter_length, { "Parameter length", "iua.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_value, { "Parameter value", "iua.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_padding, { "Parameter padding", "iua.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_version, { "Version", "iua.version", FT_UINT8, BASE_DEC, VALS(protocol_version_values), 0x0, "", HFILL } },
+ { &hf_reserved, { "Reserved", "iua.reserved", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_message_class, { "Message class", "iua.message_class", FT_UINT8, BASE_DEC, VALS(message_class_values), 0x0, "", HFILL } },
+ { &hf_message_type, { "Message Type", "iua.message_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_message_length, { "Message length", "iua.message_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ };
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_iua,
+ &ett_iua_parameter,
+ };
+
+ /* Register the protocol name and description */
+ proto_iua = proto_register_protocol("ISDN Q.921-User Adaptation Layer", "IUA", "iua");
+ iua_module = prefs_register_protocol(proto_iua, NULL);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_iua, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ prefs_register_bool_preference(iua_module, "support_ig", "Support Implementers Guide", "Support Implementers Guide (version 01)", &support_IG);
+}
+
+#define SCTP_PORT_IUA 9900
+
+void
+proto_reg_handoff_iua(void)
+{
+ dissector_handle_t iua_handle;
+
+ iua_handle = create_dissector_handle(dissect_iua, proto_iua);
+ q931_handle = find_dissector("q931");
+
+ dissector_add("sctp.port", SCTP_PORT_IUA, iua_handle);
+ dissector_add("sctp.ppi", IUA_PAYLOAD_PROTOCOL_ID, iua_handle);
+}
diff --git a/epan/dissectors/packet-jabber.c b/epan/dissectors/packet-jabber.c
new file mode 100644
index 0000000000..78b3f6c8c0
--- /dev/null
+++ b/epan/dissectors/packet-jabber.c
@@ -0,0 +1,143 @@
+/* packet-jabber.c
+ * Routines for Jabber packet dissection
+ * Copyright 2003, Brad Hards <bradh@frogmouth.net>
+ * Heavily based in packet-acap.c, which in turn is heavily based on
+ * packet-imap.c, Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-acap.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+static int proto_jabber = -1;
+static int hf_jabber_response = -1;
+static int hf_jabber_request = -1;
+
+static gint ett_jabber = -1;
+static gint ett_jabber_reqresp = -1;
+
+#define TCP_PORT_JABBER 5222
+
+static void
+dissect_jabber(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gboolean is_request;
+ proto_tree *jabber_tree;
+ proto_item *ti;
+ gint offset = 0;
+ const guchar *line;
+ gint next_offset;
+ int linelen;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Jabber");
+
+ /*
+ * Find the end of the first line.
+ *
+ * Note that "tvb_find_line_end()" will return a value that is
+ * not longer than what's in the buffer, so the "tvb_get_ptr()"
+ * call won't throw an exception.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ line = tvb_get_ptr(tvb, offset, linelen);
+
+ if (pinfo->match_port == pinfo->destport)
+ is_request = TRUE;
+ else
+ is_request = FALSE;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary
+ * (but leave out the line terminator).
+ */
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
+ is_request ? "Request" : "Response",
+ format_text(line, linelen));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_jabber, tvb, offset, -1,
+ FALSE);
+ jabber_tree = proto_item_add_subtree(ti, ett_jabber);
+
+ if (is_request) {
+ proto_tree_add_boolean_hidden(jabber_tree,
+ hf_jabber_request, tvb, 0, 0, TRUE);
+ } else {
+ proto_tree_add_boolean_hidden(jabber_tree,
+ hf_jabber_response, tvb, 0, 0, TRUE);
+ }
+
+ /*
+ * Put the line into the protocol tree.
+ */
+ ti = proto_tree_add_text(jabber_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ }
+}
+
+void
+proto_register_jabber(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_jabber_response,
+ { "Response", "jabber.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if Jabber response", HFILL }},
+
+ { &hf_jabber_request,
+ { "Request", "jabber.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if Jabber request", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_jabber,
+ &ett_jabber_reqresp,
+ };
+
+ proto_jabber = proto_register_protocol("Jabber XML Messaging",
+ "Jabber", "jabber");
+ proto_register_field_array(proto_jabber, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_jabber(void)
+{
+ dissector_handle_t jabber_handle;
+
+ jabber_handle = create_dissector_handle(dissect_jabber, proto_jabber);
+ dissector_add("tcp.port", TCP_PORT_JABBER, jabber_handle);
+}
diff --git a/epan/dissectors/packet-kadm5.c b/epan/dissectors/packet-kadm5.c
new file mode 100644
index 0000000000..a292a8f19d
--- /dev/null
+++ b/epan/dissectors/packet-kadm5.c
@@ -0,0 +1,146 @@
+/* packet-kadm5.c
+ * Routines for kadm5 dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * The kadm5 RPC protocol is used to administer Kerberos principals
+ * and policies. It is not officially documented anywhere. The
+ * information for this dissector came from the MIT kadmin source.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "packet-rpc.h"
+
+#define KADM5_PROGRAM 2112
+#define KADM5PROC_NULL 0
+#define KADM5PROC_CREATE_PRINCIPAL 1
+#define KADM5PROC_DELETE_PRINCIPAL 2
+#define KADM5PROC_MODIFY_PRINCIPAL 3
+#define KADM5PROC_RENAME_PRINCIPAL 4
+#define KADM5PROC_GET_PRINCIPAL 5
+#define KADM5PROC_CHPASS_PRINCIPAL 6
+#define KADM5PROC_CHRAND_PRINCIPAL 7
+#define KADM5PROC_CREATE_POLICY 8
+#define KADM5PROC_DELETE_POLICY 9
+#define KADM5PROC_MODIFY_POLICY 10
+#define KADM5PROC_GET_POLICY 11
+#define KADM5PROC_GET_PRIVS 12
+#define KADM5PROC_INIT 13
+#define KADM5PROC_GET_PRINCS 14
+#define KADM5PROC_GET_POLS 15
+#define KADM5PROC_SETKEY_PRINCIPAL 16
+#define KADM5PROC_SETV4KEY_PRINCIPAL 17
+#define KADM5PROC_CREATE_PRINCIPAL3 18
+#define KADM5PROC_CHPASS_PRINCIPAL3 19
+#define KADM5PROC_CHRAND_PRINCIPAL3 20
+#define KADM5PROC_SETKEY_PRINCIPAL3 21
+
+static int proto_kadm5 = -1;
+static int hf_kadm5_procedure_v2 = -1;
+static gint ett_kadm5 = -1;
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff kadm5_v2_proc[] = {
+ { KADM5PROC_NULL, "NULL", NULL, NULL },
+ { KADM5PROC_CREATE_PRINCIPAL, "CREATE_PRINCIPAL", NULL, NULL },
+ { KADM5PROC_DELETE_PRINCIPAL, "DELETE_PRINCIPAL", NULL, NULL },
+ { KADM5PROC_MODIFY_PRINCIPAL, "MODIFY_PRINCIPAL", NULL, NULL },
+ { KADM5PROC_RENAME_PRINCIPAL, "RENAME_PRINCIPAL", NULL, NULL },
+ { KADM5PROC_GET_PRINCIPAL, "GET_PRINCIPAL", NULL, NULL },
+ { KADM5PROC_CHPASS_PRINCIPAL, "CHPASS_PRINCIPAL", NULL, NULL },
+ { KADM5PROC_CHRAND_PRINCIPAL, "CHRAND_PRINCIPAL", NULL, NULL },
+ { KADM5PROC_CREATE_POLICY, "CREATE_POLICY", NULL, NULL },
+ { KADM5PROC_DELETE_POLICY, "DELETE_POLICY", NULL, NULL },
+ { KADM5PROC_MODIFY_POLICY, "MODIFY_POLICY", NULL, NULL },
+ { KADM5PROC_GET_POLICY, "GET_POLICY", NULL, NULL },
+ { KADM5PROC_GET_PRIVS, "GET_PRIVS", NULL, NULL },
+ { KADM5PROC_INIT, "INIT", NULL, NULL },
+ { KADM5PROC_GET_PRINCS, "GET_PRINCS", NULL, NULL },
+ { KADM5PROC_GET_POLS, "GET_POLS", NULL, NULL },
+ { KADM5PROC_SETKEY_PRINCIPAL, "SETKEY_PRINCIPAL", NULL, NULL },
+ { KADM5PROC_SETV4KEY_PRINCIPAL, "SETV4KEY_PRINCIPAL", NULL, NULL },
+ { KADM5PROC_CREATE_PRINCIPAL3, "CREATE_PRINCIPAL3", NULL, NULL },
+ { KADM5PROC_CHPASS_PRINCIPAL3, "CHPASS_PRINCIPAL3", NULL, NULL },
+ { KADM5PROC_CHRAND_PRINCIPAL3, "CHRAND_PRINCIPAL3", NULL, NULL },
+ { KADM5PROC_SETKEY_PRINCIPAL3, "SETKEY_PRINCIPAL3", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+static const value_string kadm5_v2_proc_vals[] = {
+ { KADM5PROC_NULL, "NULL" },
+ { KADM5PROC_CREATE_PRINCIPAL, "CREATE_PRINCIPAL" },
+ { KADM5PROC_DELETE_PRINCIPAL, "DELETE_PRINCIPAL" },
+ { KADM5PROC_MODIFY_PRINCIPAL, "MODIFY_PRINCIPAL" },
+ { KADM5PROC_RENAME_PRINCIPAL, "RENAME_PRINCIPAL" },
+ { KADM5PROC_GET_PRINCIPAL, "GET_PRINCIPAL" },
+ { KADM5PROC_CHPASS_PRINCIPAL, "CHPASS_PRINCIPAL" },
+ { KADM5PROC_CHRAND_PRINCIPAL, "CHRAND_PRINCIPAL" },
+ { KADM5PROC_CREATE_POLICY, "CREATE_POLICY" },
+ { KADM5PROC_DELETE_POLICY, "DELETE_POLICY" },
+ { KADM5PROC_MODIFY_POLICY, "MODIFY_POLICY" },
+ { KADM5PROC_GET_POLICY, "GET_POLICY" },
+ { KADM5PROC_GET_PRIVS, "GET_PRIVS" },
+ { KADM5PROC_INIT, "INIT" },
+ { KADM5PROC_GET_PRINCS, "GET_PRINCS" },
+ { KADM5PROC_GET_POLS, "GET_POLS" },
+ { KADM5PROC_SETKEY_PRINCIPAL, "SETKEY_PRINCIPAL" },
+ { KADM5PROC_SETV4KEY_PRINCIPAL, "SETV4KEY_PRINCIPAL" },
+ { KADM5PROC_CREATE_PRINCIPAL3, "CREATE_PRINCIPAL3" },
+ { KADM5PROC_CHPASS_PRINCIPAL3, "CHPASS_PRINCIPAL3" },
+ { KADM5PROC_CHRAND_PRINCIPAL3, "CHRAND_PRINCIPAL3" },
+ { KADM5PROC_SETKEY_PRINCIPAL3, "SETKEY_PRINCIPAL3" },
+ { 0, NULL }
+};
+
+void
+proto_register_kadm5(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_kadm5_procedure_v2, {
+ "V2 Procedure", "kadm5.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(kadm5_v2_proc_vals), 0, "V2 Procedure", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_kadm5,
+ };
+
+ proto_kadm5 = proto_register_protocol("Kerberos Administration",
+ "KADM5", "kadm5");
+ proto_register_field_array(proto_kadm5, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_kadm5(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_kadm5, KADM5_PROGRAM, ett_kadm5);
+ /* Register the procedure tables */
+ rpc_init_proc_table(KADM5_PROGRAM, 2, kadm5_v2_proc,
+ hf_kadm5_procedure_v2);
+}
diff --git a/epan/dissectors/packet-kerberos.c b/epan/dissectors/packet-kerberos.c
new file mode 100644
index 0000000000..2c186138b3
--- /dev/null
+++ b/epan/dissectors/packet-kerberos.c
@@ -0,0 +1,4173 @@
+/* packet-kerberos.c
+ * Routines for Kerberos
+ * Wes Hardaker (c) 2000
+ * wjhardaker@ucdavis.edu
+ * Richard Sharpe (C) 2002, rsharpe@samba.org, modularized a bit more and
+ * added AP-REQ and AP-REP dissection
+ *
+ * Ronnie Sahlberg (C) 2004, major rewrite for new ASN.1/BER API.
+ * decryption of kerberos blobs if keytab is provided
+ *
+ * See RFC 1510, and various I-Ds and other documents showing additions,
+ * e.g. ones listed under
+ *
+ * http://www.isi.edu/people/bcn/krb-revisions/
+ *
+ * and
+ *
+ * http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-kerberos-clarifications-05.txt
+ *
+ * and
+ *
+ * http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-kerberos-referrals-03.txt
+ *
+ * Some structures from RFC2630
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#include <epan/strutil.h>
+
+#include <epan/dissectors/packet-kerberos.h>
+#include <epan/dissectors/packet-netbios.h>
+#include <epan/dissectors/packet-tcp.h>
+#include "prefs.h"
+#include <epan/dissectors/packet-ber.h>
+#include <epan/dissectors/packet-smb-common.h>
+
+#include <epan/dissectors/packet-dcerpc-netlogon.h>
+#include <epan/dissectors/packet-dcerpc.h>
+
+#include "asn1.h" /* for "subid_t" */
+#include <epan/dissectors/packet-gssapi.h>
+
+#define UDP_PORT_KERBEROS 88
+#define TCP_PORT_KERBEROS 88
+
+/* Desegment Kerberos over TCP messages */
+static gboolean krb_desegment = TRUE;
+
+static gint proto_kerberos = -1;
+static gint hf_krb_rm_reserved = -1;
+static gint hf_krb_rm_reclen = -1;
+
+static gint hf_krb_pac_signature_type = -1;
+static gint hf_krb_pac_signature_signature = -1;
+static gint hf_krb_pac_clientid = -1;
+static gint hf_krb_pac_namelen = -1;
+static gint hf_krb_pac_clientname = -1;
+static gint hf_krb_w2k_pac_entries = -1;
+static gint hf_krb_w2k_pac_version = -1;
+static gint hf_krb_w2k_pac_type = -1;
+static gint hf_krb_w2k_pac_size = -1;
+static gint hf_krb_w2k_pac_offset = -1;
+static gint hf_krb_padata = -1;
+static gint hf_krb_contentinfo_contenttype = -1;
+static gint hf_krb_error_code = -1;
+static gint hf_krb_ticket = -1;
+static gint hf_krb_AP_REP_enc = -1;
+static gint hf_krb_KDC_REP_enc = -1;
+static gint hf_krb_tkt_vno = -1;
+static gint hf_krb_e_data = -1;
+static gint hf_krb_TransitedEncoding = -1;
+static gint hf_krb_PA_PAC_REQUEST_flag = -1;
+static gint hf_krb_encrypted_authenticator_data = -1;
+static gint hf_krb_PAC_LOGON_INFO = -1;
+static gint hf_krb_PAC_CREDENTIAL_TYPE = -1;
+static gint hf_krb_PAC_SERVER_CHECKSUM = -1;
+static gint hf_krb_PAC_PRIVSVR_CHECKSUM = -1;
+static gint hf_krb_PAC_CLIENT_INFO_TYPE = -1;
+static gint hf_krb_encrypted_PA_ENC_TIMESTAMP = -1;
+static gint hf_krb_checksum_checksum = -1;
+static gint hf_krb_encrypted_PRIV = -1;
+static gint hf_krb_encrypted_Ticket_data = -1;
+static gint hf_krb_encrypted_AP_REP_data = -1;
+static gint hf_krb_encrypted_KDC_REP_data = -1;
+static gint hf_krb_PA_DATA_type = -1;
+static gint hf_krb_PA_DATA_value = -1;
+static gint hf_krb_etype_info_salt = -1;
+static gint hf_krb_SAFE_BODY_user_data = -1;
+static gint hf_krb_realm = -1;
+static gint hf_krb_crealm = -1;
+static gint hf_krb_sname = -1;
+static gint hf_krb_cname = -1;
+static gint hf_krb_name_string = -1;
+static gint hf_krb_provsrv_location = -1;
+static gint hf_krb_e_text = -1;
+static gint hf_krb_name_type = -1;
+static gint hf_krb_lr_type = -1;
+static gint hf_krb_from = -1;
+static gint hf_krb_till = -1;
+static gint hf_krb_authtime = -1;
+static gint hf_krb_patimestamp = -1;
+static gint hf_krb_SAFE_BODY_timestamp = -1;
+static gint hf_krb_pausec = -1;
+static gint hf_krb_lr_time = -1;
+static gint hf_krb_starttime = -1;
+static gint hf_krb_endtime = -1;
+static gint hf_krb_key_expire = -1;
+static gint hf_krb_renew_till = -1;
+static gint hf_krb_rtime = -1;
+static gint hf_krb_ctime = -1;
+static gint hf_krb_cusec = -1;
+static gint hf_krb_stime = -1;
+static gint hf_krb_susec = -1;
+static gint hf_krb_SAFE_BODY_usec = -1;
+static gint hf_krb_nonce = -1;
+static gint hf_krb_transitedtype = -1;
+static gint hf_krb_transitedcontents = -1;
+static gint hf_krb_keytype = -1;
+static gint hf_krb_keyvalue = -1;
+static gint hf_krb_IF_RELEVANT_type = -1;
+static gint hf_krb_IF_RELEVANT_value = -1;
+static gint hf_krb_adtype = -1;
+static gint hf_krb_advalue = -1;
+static gint hf_krb_etype = -1;
+static gint hf_krb_etypes = -1;
+static gint hf_krb_LastReqs = -1;
+static gint hf_krb_IF_RELEVANT = -1;
+static gint hf_krb_addr_type = -1;
+static gint hf_krb_address_ip = -1;
+static gint hf_krb_address_netbios = -1;
+static gint hf_krb_msg_type = -1;
+static gint hf_krb_pvno = -1;
+static gint hf_krb_kvno = -1;
+static gint hf_krb_checksum_type = -1;
+static gint hf_krb_authenticator_vno = -1;
+static gint hf_krb_AuthorizationData = -1;
+static gint hf_krb_key = -1;
+static gint hf_krb_subkey = -1;
+static gint hf_krb_seq_number = -1;
+static gint hf_krb_EncTicketPart = -1;
+static gint hf_krb_EncAPRepPart = -1;
+static gint hf_krb_EncKDCRepPart = -1;
+static gint hf_krb_LastReq = -1;
+static gint hf_krb_Authenticator = -1;
+static gint hf_krb_Checksum = -1;
+static gint hf_krb_signedAuthPack = -1;
+static gint hf_krb_s_address = -1;
+static gint hf_krb_HostAddress = -1;
+static gint hf_krb_HostAddresses = -1;
+static gint hf_krb_APOptions = -1;
+static gint hf_krb_APOptions_use_session_key = -1;
+static gint hf_krb_APOptions_mutual_required = -1;
+static gint hf_krb_TicketFlags = -1;
+static gint hf_krb_TicketFlags_forwardable = -1;
+static gint hf_krb_TicketFlags_forwarded = -1;
+static gint hf_krb_TicketFlags_proxyable = -1;
+static gint hf_krb_TicketFlags_proxy = -1;
+static gint hf_krb_TicketFlags_allow_postdate = -1;
+static gint hf_krb_TicketFlags_postdated = -1;
+static gint hf_krb_TicketFlags_invalid = -1;
+static gint hf_krb_TicketFlags_renewable = -1;
+static gint hf_krb_TicketFlags_initial = -1;
+static gint hf_krb_TicketFlags_pre_auth = -1;
+static gint hf_krb_TicketFlags_hw_auth = -1;
+static gint hf_krb_TicketFlags_transited_policy_checked = -1;
+static gint hf_krb_TicketFlags_ok_as_delegate = -1;
+static gint hf_krb_KDCOptions = -1;
+static gint hf_krb_KDCOptions_forwardable = -1;
+static gint hf_krb_KDCOptions_forwarded = -1;
+static gint hf_krb_KDCOptions_proxyable = -1;
+static gint hf_krb_KDCOptions_proxy = -1;
+static gint hf_krb_KDCOptions_allow_postdate = -1;
+static gint hf_krb_KDCOptions_postdated = -1;
+static gint hf_krb_KDCOptions_renewable = -1;
+static gint hf_krb_KDCOptions_canonicalize = -1;
+static gint hf_krb_KDCOptions_opt_hardware_auth = -1;
+static gint hf_krb_KDCOptions_disable_transited_check = -1;
+static gint hf_krb_KDCOptions_renewable_ok = -1;
+static gint hf_krb_KDCOptions_enc_tkt_in_skey = -1;
+static gint hf_krb_KDCOptions_renew = -1;
+static gint hf_krb_KDCOptions_validate = -1;
+static gint hf_krb_KDC_REQ_BODY = -1;
+static gint hf_krb_PRIV_BODY = -1;
+static gint hf_krb_ENC_PRIV = -1;
+static gint hf_krb_authenticator_enc = -1;
+static gint hf_krb_ticket_enc = -1;
+
+static gint ett_krb_kerberos = -1;
+static gint ett_krb_TransitedEncoding = -1;
+static gint ett_krb_PAC_LOGON_INFO = -1;
+static gint ett_krb_signedAuthPack = -1;
+static gint ett_krb_PAC_CREDENTIAL_TYPE = -1;
+static gint ett_krb_PAC_SERVER_CHECKSUM = -1;
+static gint ett_krb_PAC_PRIVSVR_CHECKSUM = -1;
+static gint ett_krb_PAC_CLIENT_INFO_TYPE = -1;
+static gint ett_krb_KDC_REP_enc = -1;
+static gint ett_krb_EncTicketPart = -1;
+static gint ett_krb_EncAPRepPart = -1;
+static gint ett_krb_EncKDCRepPart = -1;
+static gint ett_krb_LastReq = -1;
+static gint ett_krb_Authenticator = -1;
+static gint ett_krb_Checksum = -1;
+static gint ett_krb_key = -1;
+static gint ett_krb_subkey = -1;
+static gint ett_krb_AuthorizationData = -1;
+static gint ett_krb_sname = -1;
+static gint ett_krb_cname = -1;
+static gint ett_krb_AP_REP_enc = -1;
+static gint ett_krb_padata = -1;
+static gint ett_krb_etypes = -1;
+static gint ett_krb_LastReqs = -1;
+static gint ett_krb_IF_RELEVANT = -1;
+static gint ett_krb_PA_DATA_tree = -1;
+static gint ett_krb_PAC = -1;
+static gint ett_krb_s_address = -1;
+static gint ett_krb_HostAddress = -1;
+static gint ett_krb_HostAddresses = -1;
+static gint ett_krb_authenticator_enc = -1;
+static gint ett_krb_AP_Options = -1;
+static gint ett_krb_KDC_Options = -1;
+static gint ett_krb_Ticket_Flags = -1;
+static gint ett_krb_request = -1;
+static gint ett_krb_recordmark = -1;
+static gint ett_krb_ticket = -1;
+static gint ett_krb_ticket_enc = -1;
+static gint ett_krb_PRIV = -1;
+static gint ett_krb_PRIV_enc = -1;
+
+
+guint32 krb5_errorcode;
+
+
+static int do_col_info;
+
+
+static void
+call_kerberos_callbacks(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int tag)
+{
+ kerberos_callbacks *cb=(kerberos_callbacks *)pinfo->private_data;
+
+ if(!cb){
+ return;
+ }
+
+ while(cb->tag){
+ if(cb->tag==tag){
+ cb->callback(pinfo, tvb, tree);
+ return;
+ }
+ cb++;
+ }
+ return;
+}
+
+
+
+#ifdef HAVE_KERBEROS
+
+/* Decrypt Kerberos blobs */
+static gboolean krb_decrypt = FALSE;
+
+/* keytab filename */
+static char *keytab_filename = "insert filename here";
+
+#endif
+
+#ifdef HAVE_HEIMDAL_KERBEROS
+#include <krb5.h>
+
+typedef struct _enc_key_t {
+ struct _enc_key_t *next;
+ krb5_keytab_entry key;
+} enc_key_t;
+static enc_key_t *enc_key_list=NULL;
+
+
+static void
+add_encryption_key(packet_info *pinfo, int keytype, int keylength, const char *keyvalue)
+{
+ enc_key_t *new_key;
+
+ if(pinfo->fd->flags.visited){
+ return;
+ }
+printf("added key in %d\n",pinfo->fd->num);
+
+ new_key=g_malloc(sizeof(enc_key_t));
+ new_key->next=enc_key_list;
+ enc_key_list=new_key;
+ new_key->key.principal=NULL;
+ new_key->key.vno=0;
+ new_key->key.keyblock.keytype=keytype;
+ new_key->key.keyblock.keyvalue.length=keylength;
+ new_key->key.keyblock.keyvalue.data=g_malloc(keylength);
+ memcpy(new_key->key.keyblock.keyvalue.data, keyvalue, keylength);
+ new_key->key.timestamp=0;
+}
+
+static void
+read_keytab_file(char *filename, krb5_context *context)
+{
+ krb5_keytab keytab;
+ krb5_error_code ret;
+ krb5_kt_cursor cursor;
+ enc_key_t *new_key;
+
+ /* should use a file in the ethereal users dir */
+ ret = krb5_kt_resolve(*context, filename, &keytab);
+ if(ret){
+ fprintf(stderr, "KERBEROS ERROR: Could not open keytab file :%s\n",filename);
+
+ return;
+ }
+
+ ret = krb5_kt_start_seq_get(*context, keytab, &cursor);
+ if(ret){
+ fprintf(stderr, "KERBEROS ERROR: Could not read from keytab file :%s\n",filename);
+ return;
+ }
+
+ do{
+ new_key=g_malloc(sizeof(enc_key_t));
+ new_key->next=enc_key_list;
+ ret = krb5_kt_next_entry(*context, keytab, &(new_key->key), &cursor);
+ if(ret==0){
+ enc_key_list=new_key;
+ }
+ }while(ret==0);
+
+ ret = krb5_kt_end_seq_get(*context, keytab, &cursor);
+ if(ret){
+ krb5_kt_close(*context, keytab);
+ }
+
+}
+
+
+static guint8 *
+decrypt_krb5_data(packet_info *pinfo,
+ krb5_keyusage usage,
+ int length,
+ const char *cryptotext,
+ int keytype)
+{
+ static int first_time=1;
+ static krb5_context context;
+ krb5_error_code ret;
+ krb5_data data;
+ enc_key_t *ek;
+
+ /* dont do anything if we are not attempting to decrypt data */
+ if(!krb_decrypt){
+ return NULL;
+ }
+
+ /* XXX we should only do this for first time, then store somewhere */
+
+ /* should this have a destroy context ? heidal people would know */
+ if(first_time){
+ first_time=0;
+ ret = krb5_init_context(&context);
+ if(ret){
+ return NULL;
+ }
+ read_keytab_file(keytab_filename, &context);
+ }
+
+ for(ek=enc_key_list;ek;ek=ek->next){
+ krb5_crypto crypto;
+ guint8 *cryptocopy; /* workaround for pre-6.1 heimdal bug */
+
+ /* shortcircuit and bail out if enctypes are not matching */
+ if(ek->key.keyblock.keytype!=keytype){
+ continue;
+ }
+
+ ret = krb5_crypto_init(context, &(ek->key.keyblock), 0, &crypto);
+ if(ret){
+ return NULL;
+ }
+
+ /* pre-6.1 versions of heimdal would sometimes change
+ the cryptotext data even when the decryption failed.
+ This would obviously not work since we iterate over the
+ keys. So just give it a copy of the crypto data instead.
+ This has been seen for RC4-HMAC blobs.
+ */
+ cryptocopy=g_malloc(length);
+ memcpy(cryptocopy, cryptotext, length);
+ ret = krb5_decrypt_ivec(context, crypto, usage,
+ cryptocopy, length,
+ &data,
+ NULL);
+ g_free(cryptocopy);
+ if (ret == 0) {
+printf("woohoo decrypted keytype:%d in frame:%d\n", keytype, pinfo->fd->num);
+ krb5_crypto_destroy(context, crypto);
+ return data.data;
+ }
+ krb5_crypto_destroy(context, crypto);
+ }
+ return NULL;
+}
+#endif
+
+
+
+/* TCP Record Mark */
+#define KRB_RM_RESERVED 0x80000000L
+#define KRB_RM_RECLEN 0x7fffffffL
+
+#define KRB5_MSG_AUTHENTICATOR 2 /* Authenticator */
+#define KRB5_MSG_ENC_TICKET_PART 3 /* EncTicketPart */
+#define KRB5_MSG_AS_REQ 10 /* AS-REQ type */
+#define KRB5_MSG_AS_REP 11 /* AS-REP type */
+#define KRB5_MSG_TGS_REQ 12 /* TGS-REQ type */
+#define KRB5_MSG_TGS_REP 13 /* TGS-REP type */
+#define KRB5_MSG_AP_REQ 14 /* AP-REQ type */
+#define KRB5_MSG_AP_REP 15 /* AP-REP type */
+
+#define KRB5_MSG_SAFE 20 /* KRB-SAFE type */
+#define KRB5_MSG_PRIV 21 /* KRB-PRIV type */
+#define KRB5_MSG_CRED 22 /* KRB-CRED type */
+#define KRB5_MSG_ENC_AS_REP_PART 25 /* EncASRepPart */
+#define KRB5_MSG_ENC_TGS_REP_PART 26 /* EncTGSRepPart */
+#define KRB5_MSG_ENC_AP_REP_PART 27 /* EncAPRepPart */
+#define KRB5_MSG_ERROR 30 /* KRB-ERROR type */
+
+/* address type constants */
+#define KRB5_ADDR_IPv4 0x02
+#define KRB5_ADDR_CHAOS 0x05
+#define KRB5_ADDR_XEROX 0x06
+#define KRB5_ADDR_ISO 0x07
+#define KRB5_ADDR_DECNET 0x0c
+#define KRB5_ADDR_APPLETALK 0x10
+#define KRB5_ADDR_NETBIOS 0x14
+#define KRB5_ADDR_IPv6 0x18
+
+/* encryption type constants */
+#define KRB5_ENCTYPE_NULL 0
+#define KRB5_ENCTYPE_DES_CBC_CRC 1
+#define KRB5_ENCTYPE_DES_CBC_MD4 2
+#define KRB5_ENCTYPE_DES_CBC_MD5 3
+#define KRB5_ENCTYPE_DES_CBC_RAW 4
+#define KRB5_ENCTYPE_DES3_CBC_SHA 5
+#define KRB5_ENCTYPE_DES3_CBC_RAW 6
+#define KRB5_ENCTYPE_DES_HMAC_SHA1 8
+#define KRB5_ENCTYPE_DSA_SHA1_CMS 9
+#define KRB5_ENCTYPE_RSA_MD5_CMS 10
+#define KRB5_ENCTYPE_RSA_SHA1_CMS 11
+#define KRB5_ENCTYPE_RC2_CBC_ENV 12
+#define KRB5_ENCTYPE_RSA_ENV 13
+#define KRB5_ENCTYPE_RSA_ES_OEAP_ENV 14
+#define KRB5_ENCTYPE_DES_EDE3_CBC_ENV 15
+#define KRB5_ENCTYPE_DES3_CBC_SHA1 16
+#define KRB5_ENCTYPE_DES_CBC_MD5_NT 20
+#define KERB_ENCTYPE_RC4_HMAC 23
+#define KERB_ENCTYPE_RC4_HMAC_EXP 24
+#define KRB5_ENCTYPE_UNKNOWN 0x1ff
+#define KRB5_ENCTYPE_LOCAL_DES3_HMAC_SHA1 0x7007
+#define KRB5_ENCTYPE_RC4_PLAIN_EXP 0xffffff73
+#define KRB5_ENCTYPE_RC4_PLAIN 0xffffff74
+#define KRB5_ENCTYPE_RC4_PLAIN_OLD_EXP 0xffffff78
+#define KRB5_ENCTYPE_RC4_HMAC_OLD_EXP 0xffffff79
+#define KRB5_ENCTYPE_RC4_PLAIN_OLD 0xffffff7a
+#define KRB5_ENCTYPE_RC4_HMAC_OLD 0xffffff7b
+#define KRB5_ENCTYPE_DES_PLAIN 0xffffff7c
+#define KRB5_ENCTYPE_RC4_SHA 0xffffff7d
+#define KRB5_ENCTYPE_RC4_LM 0xffffff7e
+#define KRB5_ENCTYPE_RC4_PLAIN2 0xffffff7f
+#define KRB5_ENCTYPE_RC4_MD4 0xffffff80
+
+/* checksum types */
+#define KRB5_CHKSUM_NONE 0
+#define KRB5_CHKSUM_CRC32 1
+#define KRB5_CHKSUM_MD4 2
+#define KRB5_CHKSUM_KRB_DES_MAC 4
+#define KRB5_CHKSUM_KRB_DES_MAC_K 5
+#define KRB5_CHKSUM_MD5 7
+#define KRB5_CHKSUM_MD5_DES 8
+#define KRB5_CHKSUM_HMAC_MD5 0xffffff76
+#define KRB5_CHKSUM_MD5_HMAC 0xffffff77
+#define KRB5_CHKSUM_RC4_MD5 0xffffff78
+#define KRB5_CHKSUM_MD25 0xffffff79
+#define KRB5_CHKSUM_DES_MAC_MD5 0xffffff7a
+#define KRB5_CHKSUM_DES_MAC 0xffffff7b
+#define KRB5_CHKSUM_REAL_CRC32 0xffffff7c
+#define KRB5_CHKSUM_SHA1 0xffffff7d
+#define KRB5_CHKSUM_LM 0xffffff7e
+
+
+/*
+ * For KERB_ENCTYPE_RC4_HMAC and KERB_ENCTYPE_RC4_HMAC_EXP, see
+ *
+ * http://www.ietf.org/internet-drafts/draft-brezak-win2k-krb-rc4-hmac-04.txt
+ *
+ * unless it's expired.
+ */
+
+/* pre-authentication type constants */
+#define KRB5_PA_TGS_REQ 1
+#define KRB5_PA_ENC_TIMESTAMP 2
+#define KRB5_PA_PW_SALT 3
+#define KRB5_PA_ENC_ENCKEY 4
+#define KRB5_PA_ENC_UNIX_TIME 5
+#define KRB5_PA_ENC_SANDIA_SECURID 6
+#define KRB5_PA_SESAME 7
+#define KRB5_PA_OSF_DCE 8
+#define KRB5_PA_CYBERSAFE_SECUREID 9
+#define KRB5_PA_AFS3_SALT 10
+#define KRB5_PA_ENCTYPE_INFO 11
+#define KRB5_PA_SAM_CHALLENGE 12
+#define KRB5_PA_SAM_RESPONSE 13
+#define KRB5_PA_PK_AS_REQ 14
+#define KRB5_PA_PK_AS_REP 15
+#define KRB5_PA_DASS 16
+#define KRB5_PA_USE_SPECIFIED_KVNO 20
+#define KRB5_PA_SAM_REDIRECT 21
+#define KRB5_PA_GET_FROM_TYPED_DATA 22
+#define KRB5_PA_SAM_ETYPE_INFO 23
+#define KRB5_PA_ALT_PRINC 24
+#define KRB5_PA_SAM_CHALLENGE2 30
+#define KRB5_PA_SAM_RESPONSE2 31
+#define KRB5_TD_PKINIT_CMS_CERTIFICATES 101
+#define KRB5_TD_KRB_PRINCIPAL 102
+#define KRB5_TD_KRB_REALM 103
+#define KRB5_TD_TRUSTED_CERTIFIERS 104
+#define KRB5_TD_CERTIFICATE_INDEX 105
+#define KRB5_TD_APP_DEFINED_ERROR 106
+#define KRB5_TD_REQ_NONCE 107
+#define KRB5_TD_REQ_SEQ 108
+/* preauthentication types >127 (i.e. negative ones) are app specific.
+ hopefully there will be no collissions here or we will have to
+ come up with something better
+*/
+#define KRB5_PA_PAC_REQUEST 128 /* MS extension */
+#define KRB5_PA_PROV_SRV_LOCATION 255 /* packetcable stuff */
+
+/* Principal name-type */
+#define KRB5_NT_UNKNOWN 0
+#define KRB5_NT_PRINCIPAL 1
+#define KRB5_NT_SRV_INST 2
+#define KRB5_NT_SRV_HST 3
+#define KRB5_NT_SRV_XHST 4
+#define KRB5_NT_UID 5
+#define KRB5_NT_X500_PRINCIPAL 6
+#define KRB5_NT_SMTP_NAME 7
+#define KRB5_NT_ENTERPRISE 10
+
+/*
+ * MS specific name types, from
+ *
+ * http://msdn.microsoft.com/library/en-us/security/security/kerb_external_name.asp
+ */
+#define KRB5_NT_MS_PRINCIPAL -128
+#define KRB5_NT_MS_PRINCIPAL_AND_SID -129
+#define KRB5_NT_ENT_PRINCIPAL_AND_SID -130
+#define KRB5_NT_PRINCIPAL_AND_SID -131
+#define KRB5_NT_SRV_INST_AND_SID -132
+
+/* error table constants */
+/* I prefixed the krb5_err.et constant names with KRB5_ET_ for these */
+#define KRB5_ET_KRB5KDC_ERR_NONE 0
+#define KRB5_ET_KRB5KDC_ERR_NAME_EXP 1
+#define KRB5_ET_KRB5KDC_ERR_SERVICE_EXP 2
+#define KRB5_ET_KRB5KDC_ERR_BAD_PVNO 3
+#define KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO 4
+#define KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO 5
+#define KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN 6
+#define KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN 7
+#define KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE 8
+#define KRB5_ET_KRB5KDC_ERR_NULL_KEY 9
+#define KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE 10
+#define KRB5_ET_KRB5KDC_ERR_NEVER_VALID 11
+#define KRB5_ET_KRB5KDC_ERR_POLICY 12
+#define KRB5_ET_KRB5KDC_ERR_BADOPTION 13
+#define KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP 14
+#define KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP 15
+#define KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP 16
+#define KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP 17
+#define KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED 18
+#define KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED 19
+#define KRB5_ET_KRB5KDC_ERR_TGT_REVOKED 20
+#define KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET 21
+#define KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET 22
+#define KRB5_ET_KRB5KDC_ERR_KEY_EXP 23
+#define KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED 24
+#define KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED 25
+#define KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH 26
+#define KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER 27
+#define KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED 28
+#define KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE 29
+#define KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY 31
+#define KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED 32
+#define KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV 33
+#define KRB5_ET_KRB5KRB_AP_ERR_REPEAT 34
+#define KRB5_ET_KRB5KRB_AP_ERR_NOT_US 35
+#define KRB5_ET_KRB5KRB_AP_ERR_BADMATCH 36
+#define KRB5_ET_KRB5KRB_AP_ERR_SKEW 37
+#define KRB5_ET_KRB5KRB_AP_ERR_BADADDR 38
+#define KRB5_ET_KRB5KRB_AP_ERR_BADVERSION 39
+#define KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE 40
+#define KRB5_ET_KRB5KRB_AP_ERR_MODIFIED 41
+#define KRB5_ET_KRB5KRB_AP_ERR_BADORDER 42
+#define KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT 43
+#define KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER 44
+#define KRB5_ET_KRB5KRB_AP_ERR_NOKEY 45
+#define KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL 46
+#define KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION 47
+#define KRB5_ET_KRB5KRB_AP_ERR_METHOD 48
+#define KRB5_ET_KRB5KRB_AP_ERR_BADSEQ 49
+#define KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM 50
+#define KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED 51
+#define KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG 52
+#define KRB5_ET_KRB5KRB_ERR_GENERIC 60
+#define KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG 61
+#define KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED 62
+#define KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED 63
+#define KRB5_ET_KDC_ERROR_INVALID_SIG 64
+#define KRB5_ET_KDC_ERR_KEY_TOO_WEAK 65
+#define KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH 66
+#define KRB5_ET_KRB_AP_ERR_NO_TGT 67
+#define KRB5_ET_KDC_ERR_WRONG_REALM 68
+#define KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED 69
+#define KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE 70
+#define KRB5_ET_KDC_ERR_INVALID_CERTIFICATE 71
+#define KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE 72
+#define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN 73
+#define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE 74
+#define KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH 75
+#define KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH 76
+
+static const value_string krb5_error_codes[] = {
+ { KRB5_ET_KRB5KDC_ERR_NONE, "KRB5KDC_ERR_NONE" },
+ { KRB5_ET_KRB5KDC_ERR_NAME_EXP, "KRB5KDC_ERR_NAME_EXP" },
+ { KRB5_ET_KRB5KDC_ERR_SERVICE_EXP, "KRB5KDC_ERR_SERVICE_EXP" },
+ { KRB5_ET_KRB5KDC_ERR_BAD_PVNO, "KRB5KDC_ERR_BAD_PVNO" },
+ { KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO, "KRB5KDC_ERR_C_OLD_MAST_KVNO" },
+ { KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO, "KRB5KDC_ERR_S_OLD_MAST_KVNO" },
+ { KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN" },
+ { KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN" },
+ { KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE" },
+ { KRB5_ET_KRB5KDC_ERR_NULL_KEY, "KRB5KDC_ERR_NULL_KEY" },
+ { KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE, "KRB5KDC_ERR_CANNOT_POSTDATE" },
+ { KRB5_ET_KRB5KDC_ERR_NEVER_VALID, "KRB5KDC_ERR_NEVER_VALID" },
+ { KRB5_ET_KRB5KDC_ERR_POLICY, "KRB5KDC_ERR_POLICY" },
+ { KRB5_ET_KRB5KDC_ERR_BADOPTION, "KRB5KDC_ERR_BADOPTION" },
+ { KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP, "KRB5KDC_ERR_ETYPE_NOSUPP" },
+ { KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP, "KRB5KDC_ERR_SUMTYPE_NOSUPP" },
+ { KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KRB5KDC_ERR_PADATA_TYPE_NOSUPP" },
+ { KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP, "KRB5KDC_ERR_TRTYPE_NOSUPP" },
+ { KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED, "KRB5KDC_ERR_CLIENT_REVOKED" },
+ { KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED, "KRB5KDC_ERR_SERVICE_REVOKED" },
+ { KRB5_ET_KRB5KDC_ERR_TGT_REVOKED, "KRB5KDC_ERR_TGT_REVOKED" },
+ { KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET, "KRB5KDC_ERR_CLIENT_NOTYET" },
+ { KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET, "KRB5KDC_ERR_SERVICE_NOTYET" },
+ { KRB5_ET_KRB5KDC_ERR_KEY_EXP, "KRB5KDC_ERR_KEY_EXP" },
+ { KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED, "KRB5KDC_ERR_PREAUTH_FAILED" },
+ { KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED, "KRB5KDC_ERR_PREAUTH_REQUIRED" },
+ { KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH, "KRB5KDC_ERR_SERVER_NOMATCH" },
+ { KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER, "KRB5KDC_ERR_MUST_USE_USER2USER" },
+ { KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KRB5KDC_ERR_PATH_NOT_ACCEPTED" },
+ { KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE, "KRB5KDC_ERR_SVC_UNAVAILABLE" },
+ { KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY, "KRB5KRB_AP_ERR_BAD_INTEGRITY" },
+ { KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED, "KRB5KRB_AP_ERR_TKT_EXPIRED" },
+ { KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV, "KRB5KRB_AP_ERR_TKT_NYV" },
+ { KRB5_ET_KRB5KRB_AP_ERR_REPEAT, "KRB5KRB_AP_ERR_REPEAT" },
+ { KRB5_ET_KRB5KRB_AP_ERR_NOT_US, "KRB5KRB_AP_ERR_NOT_US" },
+ { KRB5_ET_KRB5KRB_AP_ERR_BADMATCH, "KRB5KRB_AP_ERR_BADMATCH" },
+ { KRB5_ET_KRB5KRB_AP_ERR_SKEW, "KRB5KRB_AP_ERR_SKEW" },
+ { KRB5_ET_KRB5KRB_AP_ERR_BADADDR, "KRB5KRB_AP_ERR_BADADDR" },
+ { KRB5_ET_KRB5KRB_AP_ERR_BADVERSION, "KRB5KRB_AP_ERR_BADVERSION" },
+ { KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE, "KRB5KRB_AP_ERR_MSG_TYPE" },
+ { KRB5_ET_KRB5KRB_AP_ERR_MODIFIED, "KRB5KRB_AP_ERR_MODIFIED" },
+ { KRB5_ET_KRB5KRB_AP_ERR_BADORDER, "KRB5KRB_AP_ERR_BADORDER" },
+ { KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT, "KRB5KRB_AP_ERR_ILL_CR_TKT" },
+ { KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER, "KRB5KRB_AP_ERR_BADKEYVER" },
+ { KRB5_ET_KRB5KRB_AP_ERR_NOKEY, "KRB5KRB_AP_ERR_NOKEY" },
+ { KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL, "KRB5KRB_AP_ERR_MUT_FAIL" },
+ { KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION, "KRB5KRB_AP_ERR_BADDIRECTION" },
+ { KRB5_ET_KRB5KRB_AP_ERR_METHOD, "KRB5KRB_AP_ERR_METHOD" },
+ { KRB5_ET_KRB5KRB_AP_ERR_BADSEQ, "KRB5KRB_AP_ERR_BADSEQ" },
+ { KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM, "KRB5KRB_AP_ERR_INAPP_CKSUM" },
+ { KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED, "KRB5KDC_AP_PATH_NOT_ACCEPTED" },
+ { KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG, "KRB5KRB_ERR_RESPONSE_TOO_BIG"},
+ { KRB5_ET_KRB5KRB_ERR_GENERIC, "KRB5KRB_ERR_GENERIC" },
+ { KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG, "KRB5KRB_ERR_FIELD_TOOLONG" },
+ { KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED, "KDC_ERROR_CLIENT_NOT_TRUSTED" },
+ { KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED, "KDC_ERROR_KDC_NOT_TRUSTED" },
+ { KRB5_ET_KDC_ERROR_INVALID_SIG, "KDC_ERROR_INVALID_SIG" },
+ { KRB5_ET_KDC_ERR_KEY_TOO_WEAK, "KDC_ERR_KEY_TOO_WEAK" },
+ { KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH, "KDC_ERR_CERTIFICATE_MISMATCH" },
+ { KRB5_ET_KRB_AP_ERR_NO_TGT, "KRB_AP_ERR_NO_TGT" },
+ { KRB5_ET_KDC_ERR_WRONG_REALM, "KDC_ERR_WRONG_REALM" },
+ { KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED, "KRB_AP_ERR_USER_TO_USER_REQUIRED" },
+ { KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE, "KDC_ERR_CANT_VERIFY_CERTIFICATE" },
+ { KRB5_ET_KDC_ERR_INVALID_CERTIFICATE, "KDC_ERR_INVALID_CERTIFICATE" },
+ { KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE, "KDC_ERR_REVOKED_CERTIFICATE" },
+ { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN, "KDC_ERR_REVOCATION_STATUS_UNKNOWN" },
+ { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE, "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE" },
+ { KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH, "KDC_ERR_CLIENT_NAME_MISMATCH" },
+ { KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH, "KDC_ERR_KDC_NAME_MISMATCH" },
+ { 0, NULL }
+};
+
+
+#define PAC_LOGON_INFO 1
+#define PAC_CREDENTIAL_TYPE 2
+#define PAC_SERVER_CHECKSUM 6
+#define PAC_PRIVSVR_CHECKSUM 7
+#define PAC_CLIENT_INFO_TYPE 10
+static const value_string w2k_pac_types[] = {
+ { PAC_LOGON_INFO , "Logon Info" },
+ { PAC_CREDENTIAL_TYPE , "Credential Type" },
+ { PAC_SERVER_CHECKSUM , "Server Checksum" },
+ { PAC_PRIVSVR_CHECKSUM , "Privsvr Checksum" },
+ { PAC_CLIENT_INFO_TYPE , "Client Info Type" },
+ { 0, NULL },
+};
+
+
+
+static const value_string krb5_princ_types[] = {
+ { KRB5_NT_UNKNOWN , "Unknown" },
+ { KRB5_NT_PRINCIPAL , "Principal" },
+ { KRB5_NT_SRV_INST , "Service and Instance" },
+ { KRB5_NT_SRV_HST , "Service and Host" },
+ { KRB5_NT_SRV_XHST , "Service and Host Components" },
+ { KRB5_NT_UID , "Unique ID" },
+ { KRB5_NT_X500_PRINCIPAL , "Encoded X.509 Distinguished Name" },
+ { KRB5_NT_SMTP_NAME , "SMTP Name" },
+ { KRB5_NT_ENTERPRISE , "Enterprise Name" },
+ { KRB5_NT_MS_PRINCIPAL , "NT 4.0 style name (MS specific)" },
+ { KRB5_NT_MS_PRINCIPAL_AND_SID , "NT 4.0 style name with SID (MS specific)"},
+ { KRB5_NT_ENT_PRINCIPAL_AND_SID, "UPN and SID (MS specific)"},
+ { KRB5_NT_PRINCIPAL_AND_SID , "Principal name and SID (MS specific)"},
+ { KRB5_NT_SRV_INST_AND_SID , "SPN and SID (MS specific)"},
+ { 0 , NULL },
+};
+
+static const value_string krb5_preauthentication_types[] = {
+ { KRB5_PA_TGS_REQ , "PA-TGS-REQ" },
+ { KRB5_PA_ENC_TIMESTAMP , "PA-ENC-TIMESTAMP" },
+ { KRB5_PA_PW_SALT , "PA-PW-SALT" },
+ { KRB5_PA_ENC_ENCKEY , "PA-ENC-ENCKEY" },
+ { KRB5_PA_ENC_UNIX_TIME , "PA-ENC-UNIX-TIME" },
+ { KRB5_PA_ENC_SANDIA_SECURID , "PA-PW-SALT" },
+ { KRB5_PA_SESAME , "PA-SESAME" },
+ { KRB5_PA_OSF_DCE , "PA-OSF-DCE" },
+ { KRB5_PA_CYBERSAFE_SECUREID , "PA-CYBERSAFE-SECURID" },
+ { KRB5_PA_AFS3_SALT , "PA-AFS3-SALT" },
+ { KRB5_PA_ENCTYPE_INFO , "PA-ENCTYPE-INFO" },
+ { KRB5_PA_SAM_CHALLENGE , "PA-SAM-CHALLENGE" },
+ { KRB5_PA_SAM_RESPONSE , "PA-SAM-RESPONSE" },
+ { KRB5_PA_PK_AS_REQ , "PA-PK-AS-REQ" },
+ { KRB5_PA_PK_AS_REP , "PA-PK-AS-REP" },
+ { KRB5_PA_DASS , "PA-DASS" },
+ { KRB5_PA_USE_SPECIFIED_KVNO , "PA-USE-SPECIFIED-KVNO" },
+ { KRB5_PA_SAM_REDIRECT , "PA-SAM-REDIRECT" },
+ { KRB5_PA_GET_FROM_TYPED_DATA , "PA-GET-FROM-TYPED-DATA" },
+ { KRB5_PA_SAM_ETYPE_INFO , "PA-SAM-ETYPE-INFO" },
+ { KRB5_PA_ALT_PRINC , "PA-ALT-PRINC" },
+ { KRB5_PA_SAM_CHALLENGE2 , "PA-SAM-CHALLENGE2" },
+ { KRB5_PA_SAM_RESPONSE2 , "PA-SAM-RESPONSE2" },
+ { KRB5_TD_PKINIT_CMS_CERTIFICATES, "TD-PKINIT-CMS-CERTIFICATES" },
+ { KRB5_TD_KRB_PRINCIPAL , "TD-KRB-PRINCIPAL" },
+ { KRB5_TD_KRB_REALM , "TD-KRB-REALM" },
+ { KRB5_TD_TRUSTED_CERTIFIERS , "TD-TRUSTED-CERTIFIERS" },
+ { KRB5_TD_CERTIFICATE_INDEX , "TD-CERTIFICATE-INDEX" },
+ { KRB5_TD_APP_DEFINED_ERROR , "TD-APP-DEFINED-ERROR" },
+ { KRB5_TD_REQ_NONCE , "TD-REQ-NONCE" },
+ { KRB5_TD_REQ_SEQ , "TD-REQ-SEQ" },
+ { KRB5_PA_PAC_REQUEST , "PA-PAC-REQUEST" },
+ { KRB5_PA_PROV_SRV_LOCATION , "PA-PROV-SRV-LOCATION" },
+ { 0 , NULL },
+};
+
+static const value_string krb5_encryption_types[] = {
+ { KRB5_ENCTYPE_NULL , "NULL" },
+ { KRB5_ENCTYPE_DES_CBC_CRC , "des-cbc-crc" },
+ { KRB5_ENCTYPE_DES_CBC_MD4 , "des-cbc-md4" },
+ { KRB5_ENCTYPE_DES_CBC_MD5 , "des-cbc-md5" },
+ { KRB5_ENCTYPE_DES_CBC_RAW , "des-cbc-raw" },
+ { KRB5_ENCTYPE_DES3_CBC_SHA , "des3-cbc-sha" },
+ { KRB5_ENCTYPE_DES3_CBC_RAW , "des3-cbc-raw" },
+ { KRB5_ENCTYPE_DES_HMAC_SHA1 , "des-hmac-sha1" },
+ { KRB5_ENCTYPE_DSA_SHA1_CMS , "dsa-sha1-cms" },
+ { KRB5_ENCTYPE_RSA_MD5_CMS , "rsa-md5-cms" },
+ { KRB5_ENCTYPE_RSA_SHA1_CMS , "rsa-sha1-cms" },
+ { KRB5_ENCTYPE_RC2_CBC_ENV , "rc2-cbc-env" },
+ { KRB5_ENCTYPE_RSA_ENV , "rsa-env" },
+ { KRB5_ENCTYPE_RSA_ES_OEAP_ENV, "rsa-es-oeap-env" },
+ { KRB5_ENCTYPE_DES_EDE3_CBC_ENV, "des-ede3-cbc-env" },
+ { KRB5_ENCTYPE_DES3_CBC_SHA1 , "des3-cbc-sha1" },
+ { KRB5_ENCTYPE_DES_CBC_MD5_NT , "des-cbc-md5-nt" },
+ { KERB_ENCTYPE_RC4_HMAC , "rc4-hmac" },
+ { KERB_ENCTYPE_RC4_HMAC_EXP , "rc4-hmac-exp" },
+ { KRB5_ENCTYPE_UNKNOWN , "unknown" },
+ { KRB5_ENCTYPE_LOCAL_DES3_HMAC_SHA1 , "local-des3-hmac-sha1" },
+ { KRB5_ENCTYPE_RC4_PLAIN_EXP , "rc4-plain-exp" },
+ { KRB5_ENCTYPE_RC4_PLAIN , "rc4-plain" },
+ { KRB5_ENCTYPE_RC4_PLAIN_OLD_EXP, "rc4-plain-old-exp" },
+ { KRB5_ENCTYPE_RC4_HMAC_OLD_EXP, "rc4-hmac-old-exp" },
+ { KRB5_ENCTYPE_RC4_PLAIN_OLD , "rc4-plain-old" },
+ { KRB5_ENCTYPE_RC4_HMAC_OLD , "rc4-hmac-old" },
+ { KRB5_ENCTYPE_DES_PLAIN , "des-plain" },
+ { KRB5_ENCTYPE_RC4_SHA , "rc4-sha" },
+ { KRB5_ENCTYPE_RC4_LM , "rc4-lm" },
+ { KRB5_ENCTYPE_RC4_PLAIN2 , "rc4-plain2" },
+ { KRB5_ENCTYPE_RC4_MD4 , "rc4-md4" },
+ { 0 , NULL },
+};
+
+static const value_string krb5_checksum_types[] = {
+ { KRB5_CHKSUM_NONE , "none" },
+ { KRB5_CHKSUM_CRC32 , "crc32" },
+ { KRB5_CHKSUM_MD4 , "md4" },
+ { KRB5_CHKSUM_KRB_DES_MAC , "krb-des-mac" },
+ { KRB5_CHKSUM_KRB_DES_MAC_K , "krb-des-mac-k" },
+ { KRB5_CHKSUM_MD5 , "md5" },
+ { KRB5_CHKSUM_MD5_DES , "md5-des" },
+ { KRB5_CHKSUM_HMAC_MD5 , "hmac-md5" },
+ { KRB5_CHKSUM_MD5_HMAC , "md5-hmac" },
+ { KRB5_CHKSUM_RC4_MD5 , "rc5-md5" },
+ { KRB5_CHKSUM_MD25 , "md25" },
+ { KRB5_CHKSUM_DES_MAC_MD5 , "des-mac-md5" },
+ { KRB5_CHKSUM_DES_MAC , "des-mac" },
+ { KRB5_CHKSUM_REAL_CRC32 , "real-crc32" },
+ { KRB5_CHKSUM_SHA1 , "sha1" },
+ { KRB5_CHKSUM_LM , "lm" },
+ { 0 , NULL },
+};
+
+#define KRB5_AD_IF_RELEVANT 1
+#define KRB5_AD_INTENDED_FOR_SERVER 2
+#define KRB5_AD_INTENDED_FOR_APPLICATION_CLASS 3
+#define KRB5_AD_KDC_ISSUED 4
+#define KRB5_AD_OR 5
+#define KRB5_AD_MANDATORY_TICKET_EXTENSIONS 6
+#define KRB5_AD_IN_TICKET_EXTENSIONS 7
+#define KRB5_AD_MANDATORY_FOR_KDC 8
+#define KRB5_AD_OSF_DCE 64
+#define KRB5_AD_SESAME 65
+#define KRB5_AD_OSF_DCE_PKI_CERTID 66
+#define KRB5_AD_WIN2K_PAC 128
+static const value_string krb5_ad_types[] = {
+ { KRB5_AD_IF_RELEVANT , "AD-IF-RELEVANT" },
+ { KRB5_AD_INTENDED_FOR_SERVER , "AD-Intended-For-Server" },
+ { KRB5_AD_INTENDED_FOR_APPLICATION_CLASS , "AD-Intended-For-Application-Class" },
+ { KRB5_AD_KDC_ISSUED , "AD-KDCIssued" },
+ { KRB5_AD_OR , "AD-AND-OR" },
+ { KRB5_AD_MANDATORY_TICKET_EXTENSIONS , "AD-Mandatory-Ticket-Extensions" },
+ { KRB5_AD_IN_TICKET_EXTENSIONS , "AD-IN-Ticket-Extensions" },
+ { KRB5_AD_MANDATORY_FOR_KDC , "AD-MANDATORY-FOR-KDC" },
+ { KRB5_AD_OSF_DCE , "AD-OSF-DCE" },
+ { KRB5_AD_SESAME , "AD-SESAME" },
+ { KRB5_AD_OSF_DCE_PKI_CERTID , "AD-OSF-DCE-PKI-CertID" },
+ { KRB5_AD_WIN2K_PAC , "AD-Win2k-PAC" },
+ { 0 , NULL },
+};
+
+static const value_string krb5_transited_types[] = {
+ { 1 , "DOMAIN-X500-COMPRESS" },
+ { 0 , NULL }
+};
+
+static const value_string krb5_address_types[] = {
+ { KRB5_ADDR_IPv4, "IPv4"},
+ { KRB5_ADDR_CHAOS, "CHAOS"},
+ { KRB5_ADDR_XEROX, "XEROX"},
+ { KRB5_ADDR_ISO, "ISO"},
+ { KRB5_ADDR_DECNET, "DECNET"},
+ { KRB5_ADDR_APPLETALK, "APPLETALK"},
+ { KRB5_ADDR_NETBIOS, "NETBIOS"},
+ { KRB5_ADDR_IPv6, "IPv6"},
+ { 0, NULL },
+};
+
+static const value_string krb5_msg_types[] = {
+ { KRB5_MSG_AUTHENTICATOR, "Authenticator" },
+ { KRB5_MSG_ENC_TICKET_PART, "EncTicketPart" },
+ { KRB5_MSG_TGS_REQ, "TGS-REQ" },
+ { KRB5_MSG_TGS_REP, "TGS-REP" },
+ { KRB5_MSG_AS_REQ, "AS-REQ" },
+ { KRB5_MSG_AS_REP, "AS-REP" },
+ { KRB5_MSG_AP_REQ, "AP-REQ" },
+ { KRB5_MSG_AP_REP, "AP-REP" },
+ { KRB5_MSG_SAFE, "KRB-SAFE" },
+ { KRB5_MSG_PRIV, "KRB-PRIV" },
+ { KRB5_MSG_CRED, "KRB-CRED" },
+ { KRB5_MSG_ENC_AS_REP_PART, "EncASRepPart" },
+ { KRB5_MSG_ENC_TGS_REP_PART, "EncTGSRepPart" },
+ { KRB5_MSG_ENC_AP_REP_PART, "EncAPRepPart" },
+ { KRB5_MSG_ERROR, "KRB-ERROR" },
+ { 0, NULL },
+};
+
+
+
+
+static int dissect_krb5_application_choice(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_Authenticator(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_EncTicketPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_EncAPRepPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_EncKDCRepPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_KDC_REQ(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_KDC_REP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_AP_REQ(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_AP_REP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_SAFE(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_PRIV(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+static int dissect_krb5_ERROR(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset);
+
+static const ber_choice kerberos_applications_choice[] = {
+ { KRB5_MSG_AUTHENTICATOR, BER_CLASS_APP, KRB5_MSG_AUTHENTICATOR, 0, dissect_krb5_Authenticator },
+ { KRB5_MSG_ENC_TICKET_PART, BER_CLASS_APP, KRB5_MSG_ENC_TICKET_PART, 0, dissect_krb5_EncTicketPart },
+ { KRB5_MSG_AS_REQ, BER_CLASS_APP, KRB5_MSG_AS_REQ, 0, dissect_krb5_KDC_REQ },
+ { KRB5_MSG_AS_REP, BER_CLASS_APP, KRB5_MSG_AS_REP, 0, dissect_krb5_KDC_REP },
+ { KRB5_MSG_TGS_REQ, BER_CLASS_APP, KRB5_MSG_TGS_REQ, 0, dissect_krb5_KDC_REQ },
+ { KRB5_MSG_TGS_REP, BER_CLASS_APP, KRB5_MSG_TGS_REP, 0, dissect_krb5_KDC_REP },
+ { KRB5_MSG_AP_REQ, BER_CLASS_APP, KRB5_MSG_AP_REQ, 0, dissect_krb5_AP_REQ },
+ { KRB5_MSG_AP_REP, BER_CLASS_APP, KRB5_MSG_AP_REP, 0, dissect_krb5_AP_REP },
+ { KRB5_MSG_ENC_AS_REP_PART, BER_CLASS_APP, KRB5_MSG_ENC_AS_REP_PART, 0, dissect_krb5_EncKDCRepPart },
+ { KRB5_MSG_ENC_TGS_REP_PART, BER_CLASS_APP, KRB5_MSG_ENC_TGS_REP_PART, 0, dissect_krb5_EncKDCRepPart },
+ { KRB5_MSG_ENC_AP_REP_PART, BER_CLASS_APP, KRB5_MSG_ENC_AP_REP_PART, 0, dissect_krb5_EncAPRepPart },
+ { KRB5_MSG_SAFE, BER_CLASS_APP, KRB5_MSG_SAFE, 0, dissect_krb5_SAFE },
+ { KRB5_MSG_PRIV, BER_CLASS_APP, KRB5_MSG_PRIV, 0, dissect_krb5_PRIV },
+ { KRB5_MSG_ERROR, BER_CLASS_APP, KRB5_MSG_ERROR, 0, dissect_krb5_ERROR },
+ { 0, 0, 0, 0, NULL }
+};
+
+
+static int
+dissect_krb5_application_choice(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_choice(pinfo, tree, tvb, offset, kerberos_applications_choice, -1, -1);
+ return offset;
+}
+
+
+static const true_false_string krb5_apoptions_use_session_key = {
+ "USE SESSION KEY to encrypt the ticket",
+ "Do NOT use the session key to encrypt the ticket"
+};
+static const true_false_string krb5_apoptions_mutual_required = {
+ "MUTUAL authentication is REQUIRED",
+ "Mutual authentication is NOT required"
+};
+
+static int *APOptions_bits[] = {
+ &hf_krb_APOptions_use_session_key,
+ &hf_krb_APOptions_mutual_required,
+ NULL
+};
+static int
+dissect_krb5_APOptions(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_bitstring32(FALSE, pinfo, tree, tvb, offset, APOptions_bits, hf_krb_APOptions, ett_krb_AP_Options, NULL);
+ return offset;
+}
+
+
+
+static const true_false_string krb5_kdcoptions_forwardable = {
+ "FORWARDABLE tickets are allowed/requested",
+ "Do NOT use forwardable tickets"
+};
+static const true_false_string krb5_kdcoptions_forwarded = {
+ "This ticket has been FORWARDED",
+ "This is NOT a forwarded ticket"
+};
+static const true_false_string krb5_kdcoptions_proxyable = {
+ "PROXIABLE tickets are allowed/requested",
+ "Do NOT use proxiable tickets"
+};
+static const true_false_string krb5_kdcoptions_proxy = {
+ "This is a PROXY ticket",
+ "This ticket has NOT been proxied"
+};
+static const true_false_string krb5_kdcoptions_allow_postdate = {
+ "We allow the ticket to be POSTDATED",
+ "We do NOT allow the ticket to be postdated"
+};
+static const true_false_string krb5_kdcoptions_postdated = {
+ "This ticket is POSTDATED",
+ "This ticket is NOT postdated"
+};
+static const true_false_string krb5_kdcoptions_renewable = {
+ "This ticket is RENEWABLE",
+ "This ticket is NOT renewable"
+};
+static const true_false_string krb5_kdcoptions_canonicalize = {
+ "This is a request for a CANONICALIZED ticket",
+ "This is NOT a canonicalized ticket request"
+};
+static const true_false_string krb5_kdcoptions_disable_transited_check = {
+ "Transited checking is DISABLED",
+ "Transited checking is NOT disabled"
+};
+static const true_false_string krb5_kdcoptions_renewable_ok = {
+ "We accept RENEWED tickets",
+ "We do NOT accept renewed tickets"
+};
+static const true_false_string krb5_kdcoptions_enc_tkt_in_skey = {
+ "ENCrypt TKT in SKEY",
+ "Do NOT encrypt the tkt inside the skey"
+};
+static const true_false_string krb5_kdcoptions_renew = {
+ "This is a request to RENEW a ticket",
+ "This is NOT a request to renew a ticket"
+};
+static const true_false_string krb5_kdcoptions_validate = {
+ "This is a request to VALIDATE a postdated ticket",
+ "This is NOT a request to validate a postdated ticket"
+};
+
+static int* KDCOptions_bits[] = {
+ &hf_krb_KDCOptions_forwardable,
+ &hf_krb_KDCOptions_forwarded,
+ &hf_krb_KDCOptions_proxyable,
+ &hf_krb_KDCOptions_proxy,
+ &hf_krb_KDCOptions_allow_postdate,
+ &hf_krb_KDCOptions_postdated,
+ &hf_krb_KDCOptions_renewable,
+ &hf_krb_KDCOptions_opt_hardware_auth,
+ &hf_krb_KDCOptions_canonicalize,
+ &hf_krb_KDCOptions_disable_transited_check,
+ &hf_krb_KDCOptions_renewable_ok,
+ &hf_krb_KDCOptions_enc_tkt_in_skey,
+ &hf_krb_KDCOptions_renew,
+ &hf_krb_KDCOptions_validate,
+ NULL
+};
+
+static int
+dissect_krb5_KDCOptions(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_bitstring32(FALSE, pinfo, tree, tvb, offset, KDCOptions_bits, hf_krb_KDCOptions, ett_krb_KDC_Options, NULL);
+ return offset;
+}
+
+static int
+dissect_krb5_rtime(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_rtime);
+ return offset;
+}
+
+static int
+dissect_krb5_ctime(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_ctime);
+ return offset;
+}
+static int
+dissect_krb5_cusec(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_cusec, NULL);
+ return offset;
+}
+
+static int
+dissect_krb5_stime(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_stime);
+ return offset;
+}
+static int
+dissect_krb5_susec(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_susec, NULL);
+ return offset;
+}
+
+
+static int
+dissect_krb5_error_code(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_error_code, &krb5_errorcode);
+ if(krb5_errorcode && check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "KRB Error: %s",
+ val_to_str(krb5_errorcode, krb5_error_codes,
+ "Unknown error code %#x"));
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_krb5_till(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_till);
+ return offset;
+}
+static int
+dissect_krb5_from(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_from);
+ return offset;
+}
+
+
+
+static int
+dissect_krb5_nonce(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_nonce, NULL);
+ return offset;
+}
+
+
+/*
+ * etype[8] SEQUENCE OF INTEGER, -- EncryptionType,
+ */
+static int
+dissect_krb5_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint32 etype;
+
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_etype, &etype);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(etype, krb5_encryption_types,
+ "%d"));
+ }
+ return offset;
+}
+static ber_sequence etype_sequence_of[1] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_krb5_etype },
+};
+static int
+dissect_krb5_etype_sequence_of(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence_of(FALSE, pinfo, tree, tvb, offset, etype_sequence_of, hf_krb_etypes, ett_krb_etypes);
+
+ return offset;
+}
+static guint32 authenticator_etype;
+static int
+dissect_krb5_authenticator_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_etype, &authenticator_etype);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(authenticator_etype, krb5_encryption_types,
+ "%#x"));
+ }
+ return offset;
+}
+static guint32 Ticket_etype;
+static int
+dissect_krb5_Ticket_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_etype, &Ticket_etype);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(Ticket_etype, krb5_encryption_types,
+ "%#x"));
+ }
+ return offset;
+}
+static guint32 AP_REP_etype;
+static int
+dissect_krb5_AP_REP_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_etype, &AP_REP_etype);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(AP_REP_etype, krb5_encryption_types,
+ "%#x"));
+ }
+ return offset;
+}
+static guint32 PA_ENC_TIMESTAMP_etype;
+static int
+dissect_krb5_PA_ENC_TIMESTAMP_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_etype, &PA_ENC_TIMESTAMP_etype);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(PA_ENC_TIMESTAMP_etype, krb5_encryption_types,
+ "%#x"));
+ }
+ return offset;
+}
+
+
+/*
+ * HostAddress ::= SEQUENCE {
+ * addr-type[0] INTEGER,
+ * address[1] OCTET STRING
+ * }
+ */
+static guint32 addr_type;
+static int dissect_krb5_addr_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_addr_type, &addr_type);
+ return offset;
+}
+static int dissect_krb5_address(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint8 class;
+ gboolean pc;
+ guint32 tag;
+ guint32 len;
+ char address_str[256];
+ proto_item *it=NULL;
+
+ /* read header and len for the octet string */
+ offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag);
+ offset=dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL);
+
+
+ address_str[0]=0;
+ address_str[255]=0;
+ switch(addr_type){
+ case KRB5_ADDR_IPv4:
+ it=proto_tree_add_item(tree, hf_krb_address_ip, tvb, offset, 4, FALSE);
+ sprintf(address_str,"%d.%d.%d.%d",tvb_get_guint8(tvb, offset),tvb_get_guint8(tvb, offset+1),tvb_get_guint8(tvb, offset+2),tvb_get_guint8(tvb, offset+3));
+ break;
+ case KRB5_ADDR_NETBIOS:
+ {
+ char netbios_name[(NETBIOS_NAME_LEN - 1)*4 + 1];
+ int netbios_name_type;
+
+ netbios_name_type = process_netbios_name(tvb_get_ptr(tvb, offset, 16), netbios_name);
+ snprintf(address_str, 255, "%s<%02x>", netbios_name, netbios_name_type);
+ it=proto_tree_add_string_format(tree, hf_krb_address_netbios, tvb, offset, 16, netbios_name, "NetBIOS Name: %s (%s)", address_str, netbios_name_type_descr(netbios_name_type));
+ }
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, len, "KRB Address: I dont know how to parse this type of address yet");
+
+ }
+
+ /* push it up two levels in the decode pane */
+ if(it){
+ proto_item_append_text(proto_item_get_parent(it), " %s",address_str);
+ proto_item_append_text(proto_item_get_parent_nth(it, 2), " %s",address_str);
+ }
+
+ offset+=len;
+ return offset;
+}
+static ber_sequence HostAddress_sequence[] = {
+ { BER_CLASS_CON, 0, 0, dissect_krb5_addr_type },
+ { BER_CLASS_CON, 1, 0, dissect_krb5_address },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_HostAddress(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, HostAddress_sequence, hf_krb_HostAddress, ett_krb_HostAddress);
+
+ return offset;
+}
+static int
+dissect_krb5_s_address(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, HostAddress_sequence, hf_krb_s_address, ett_krb_s_address);
+
+ return offset;
+}
+
+/*
+ * HostAddresses ::= SEQUENCE OF SEQUENCE {
+ * addr-type[0] INTEGER,
+ * address[1] OCTET STRING
+ * }
+ *
+ */
+static ber_sequence HostAddresses_sequence_of[1] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_krb5_HostAddress },
+};
+static int
+dissect_krb5_HostAddresses(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence_of(FALSE, pinfo, tree, tvb, offset, HostAddresses_sequence_of, hf_krb_HostAddresses, ett_krb_HostAddresses);
+
+ return offset;
+}
+
+
+
+static int
+dissect_krb5_msg_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint32 msgtype;
+
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_msg_type, &msgtype);
+
+ if (do_col_info & check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(msgtype, krb5_msg_types,
+ "Unknown msg type %#x"));
+ }
+ do_col_info=FALSE;
+
+ /* append the application type to the subtree */
+ proto_item_append_text(tree, " %s", val_to_str(msgtype, krb5_msg_types, "Unknown:0x%x"));
+
+ return offset;
+}
+
+
+
+static int
+dissect_krb5_pvno(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_pvno, NULL);
+
+ return offset;
+}
+
+
+/*
+ * PrincipalName ::= SEQUENCE {
+ * name-type[0] INTEGER,
+ * name-string[1] SEQUENCE OF GeneralString
+ * }
+ */
+static int
+dissect_krb5_name_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint32 name_type;
+
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_name_type, &name_type);
+ if(tree){
+ proto_item_append_text(tree, " (%s):",
+ val_to_str(name_type, krb5_princ_types,
+ "Unknown:%d"));
+ }
+ return offset;
+}
+static int
+dissect_krb5_name_string(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ char name_string[256];
+
+ offset=dissect_ber_GeneralString(pinfo, tree, tvb, offset, hf_krb_name_string, name_string, 255);
+ if(tree){
+ proto_item_append_text(tree, " %s", name_string);
+ }
+
+ return offset;
+}
+static ber_sequence name_stringe_sequence_of[1] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_GeneralString, BER_FLAGS_NOOWNTAG, dissect_krb5_name_string },
+};
+static int
+dissect_krb5_name_strings(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence_of(FALSE, pinfo, tree, tvb, offset, name_stringe_sequence_of, -1, -1);
+
+ return offset;
+}
+static ber_sequence PrincipalName_sequence[] = {
+ { BER_CLASS_CON, 0, 0, dissect_krb5_name_type },
+ { BER_CLASS_CON, 1, 0, dissect_krb5_name_strings },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_sname(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, PrincipalName_sequence, hf_krb_sname, ett_krb_sname);
+
+ return offset;
+}
+static int
+dissect_krb5_cname(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, PrincipalName_sequence, hf_krb_cname, ett_krb_cname);
+
+ return offset;
+}
+
+
+static int
+dissect_krb5_realm(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_GeneralString(pinfo, tree, tvb, offset, hf_krb_realm, NULL, 0);
+ return offset;
+}
+
+static int
+dissect_krb5_crealm(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_GeneralString(pinfo, tree, tvb, offset, hf_krb_crealm, NULL, 0);
+ return offset;
+}
+
+
+
+static int
+dissect_krb5_PA_PAC_REQUEST_flag(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_boolean(pinfo, tree, tvb, offset, hf_krb_PA_PAC_REQUEST_flag);
+ return offset;
+}
+
+
+static ber_sequence PA_PAC_REQUEST_sequence[] = {
+ { BER_CLASS_CON, 0, 0, dissect_krb5_PA_PAC_REQUEST_flag },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_PA_PAC_REQUEST(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, PA_PAC_REQUEST_sequence, -1, -1);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_krb5_SignedData(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_, int offset)
+{
+/*qqq*/
+ return offset;
+}
+
+
+static char ContentType[64]; /*64 chars should be long enough */
+static int
+dissect_krb5_ContentInfo_ContentType(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ ContentType[0]=0;
+ offset=dissect_ber_object_identifier(TRUE, pinfo, tree, tvb, offset, hf_krb_contentinfo_contenttype, ContentType);
+
+ return offset;
+}
+
+/* the content of this structure depends on the ContentType object identifier */
+static int
+dissect_krb5_ContentInfo_content(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ if(!strcmp(ContentType, "1.2.840.113549.1.7.2")){
+ offset=dissect_krb5_SignedData(pinfo, tree, tvb, offset);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "ContentInfo: dont know how to parse this type yet.");
+ }
+
+ return offset;
+}
+
+static ber_sequence ContentInfo_sequence[] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_krb5_ContentInfo_ContentType },
+ { BER_CLASS_CON, 0, 0, dissect_krb5_ContentInfo_content },
+ { 0, 0, 0, NULL }
+};
+
+static int
+dissect_krb5_PA_PK_AS_REQ_signedAuthPack(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, ContentInfo_sequence, hf_krb_signedAuthPack, ett_krb_signedAuthPack);
+
+ return offset;
+}
+
+static int
+dissect_krb5_PA_PK_AS_REQ_trustedCertifiers(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ BER_NOT_DECODED_YET("trustedCertifiers");
+
+ return offset;
+}
+static int
+dissect_krb5_PA_PK_AS_REQ_kdcCert(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ BER_NOT_DECODED_YET("kdcCert");
+
+ return offset;
+}
+static int
+dissect_krb5_PA_PK_AS_REQ_encryptionCert(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ BER_NOT_DECODED_YET("encryptionCert");
+
+ return offset;
+}
+
+
+
+static ber_sequence PA_PK_AS_REQ_sequence[] = {
+ { BER_CLASS_CON, 0, 0, dissect_krb5_PA_PK_AS_REQ_signedAuthPack },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_krb5_PA_PK_AS_REQ_trustedCertifiers },
+ { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_krb5_PA_PK_AS_REQ_kdcCert },
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL, dissect_krb5_PA_PK_AS_REQ_encryptionCert },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_PA_PK_AS_REQ(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, PA_PK_AS_REQ_sequence, -1, -1);
+
+ return offset;
+}
+
+
+static int
+dissect_krb5_PA_PROV_SRV_LOCATION(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_GeneralString(pinfo, tree, tvb, offset, hf_krb_provsrv_location, NULL, 0);
+
+ return offset;
+}
+
+
+
+static int
+dissect_krb5_kvno(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_kvno, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_krb5_seq_number(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_seq_number, NULL);
+
+ return offset;
+}
+
+
+
+#ifdef HAVE_KERBEROS
+static int
+dissect_krb5_pausec(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_pausec, NULL);
+ return offset;
+}
+static int
+dissect_krb5_patimestamp(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_patimestamp);
+ return offset;
+}
+static const ber_sequence PA_ENC_TS_ENC_sequence[] = {
+ { BER_CLASS_CON, 0, 0, dissect_krb5_patimestamp },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_krb5_pausec },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_decrypt_PA_ENC_TIMESTAMP (packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint8 *plaintext=NULL;
+ int length;
+
+ length=tvb_length_remaining(tvb, offset);
+
+ /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
+ * 7.5.1
+ * AS-REQ PA_ENC_TIMESTAMP are encrypted with usage
+ * == 1
+ */
+ if(!plaintext){
+ plaintext=decrypt_krb5_data(pinfo, 1, length, tvb_get_ptr(tvb, offset, length), PA_ENC_TIMESTAMP_etype);
+ }
+
+ if(plaintext){
+ tvbuff_t *next_tvb;
+ next_tvb = tvb_new_real_data (plaintext,
+ length,
+ length);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+
+ /* Add the decrypted data to the data source list. */
+ add_new_data_source(pinfo, next_tvb, "Decrypted Krb5");
+
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, next_tvb, 0, PA_ENC_TS_ENC_sequence, -1, -1);
+
+ }
+ return offset;
+}
+#endif
+
+
+static int
+dissect_krb5_encrypted_PA_ENC_TIMESTAMP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+#ifdef HAVE_KERBEROS
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_PA_ENC_TIMESTAMP, dissect_krb5_decrypt_PA_ENC_TIMESTAMP);
+#else
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_PA_ENC_TIMESTAMP, NULL);
+#endif
+ return offset;
+}
+static ber_sequence PA_ENC_TIMESTAMP_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_PA_ENC_TIMESTAMP_etype },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
+ dissect_krb5_kvno },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_encrypted_PA_ENC_TIMESTAMP },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_PA_ENC_TIMESTAMP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, PA_ENC_TIMESTAMP_sequence, -1, -1);
+
+ return offset;
+}
+
+
+
+static int
+dissect_krb5_etype_info_salt(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_etype_info_salt, NULL);
+ return offset;
+}
+
+static ber_sequence PA_ENCTYPE_INFO_ENTRY_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_etype },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
+ dissect_krb5_etype_info_salt },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_PA_ENCTYPE_INFO_ENTRY(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, PA_ENCTYPE_INFO_ENTRY_sequence, -1, -1);
+
+ return offset;
+}
+
+static ber_sequence PA_ENCTYPE_INFO_sequence_of[1] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_krb5_PA_ENCTYPE_INFO_ENTRY },
+};
+static int
+dissect_krb5_PA_ENCTYPE_INFO(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence_of(FALSE, pinfo, tree, tvb, offset, PA_ENCTYPE_INFO_sequence_of, -1, -1);
+
+ return offset;
+}
+
+/*
+ * PA-DATA ::= SEQUENCE {
+ * padata-type[1] INTEGER,
+ * padata-value[2] OCTET STRING,
+ * -- might be encoded AP-REQ
+ * }
+ */
+guint32 krb_PA_DATA_type;
+static int
+dissect_krb5_PA_DATA_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_PA_DATA_type, &krb_PA_DATA_type);
+ krb_PA_DATA_type&=0xff; /*this is really just one single byte */
+
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(krb_PA_DATA_type, krb5_preauthentication_types,
+ "Unknown:%d"));
+ }
+ return offset;
+}
+static int
+dissect_krb5_PA_DATA_value(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset)
+{
+ proto_tree *tree=parent_tree;
+
+ if(ber_last_created_item){
+ tree=proto_item_add_subtree(ber_last_created_item, ett_krb_PA_DATA_tree);
+ }
+
+
+ switch(krb_PA_DATA_type){
+ case KRB5_PA_TGS_REQ:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_application_choice);
+ break;
+ case KRB5_PA_PK_AS_REQ:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_PA_PK_AS_REQ);
+ break;
+ case KRB5_PA_PAC_REQUEST:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_PA_PAC_REQUEST);
+ break;
+ case KRB5_PA_PROV_SRV_LOCATION:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_PA_PROV_SRV_LOCATION);
+ break;
+ case KRB5_PA_ENC_TIMESTAMP:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_PA_ENC_TIMESTAMP);
+ break;
+ case KRB5_PA_ENCTYPE_INFO:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, dissect_krb5_PA_ENCTYPE_INFO);
+ break;
+ default:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset,hf_krb_PA_DATA_value, NULL);
+ }
+ return offset;
+/*qqq*/
+}
+
+static ber_sequence PA_DATA_sequence[] = {
+ { BER_CLASS_CON, 1, 0, dissect_krb5_PA_DATA_type },
+ { BER_CLASS_CON, 2, 0, dissect_krb5_PA_DATA_value },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_PA_DATA(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, PA_DATA_sequence, -1, -1);
+
+ return offset;
+}
+
+
+
+
+/*
+ * padata[3] SEQUENCE OF PA-DATA OPTIONAL,
+ *
+ */
+static ber_sequence PA_DATA_sequence_of[1] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_krb5_PA_DATA },
+};
+static int
+dissect_krb5_padata(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence_of(FALSE, pinfo, tree, tvb, offset, PA_DATA_sequence_of, hf_krb_padata, ett_krb_padata);
+
+ return offset;
+}
+
+
+
+
+static const true_false_string krb5_ticketflags_forwardable = {
+ "FORWARDABLE tickets are allowed/requested",
+ "Do NOT use forwardable tickets"
+};
+static const true_false_string krb5_ticketflags_forwarded = {
+ "This ticket has been FORWARDED",
+ "This is NOT a forwarded ticket"
+};
+static const true_false_string krb5_ticketflags_proxyable = {
+ "PROXIABLE tickets are allowed/requested",
+ "Do NOT use proxiable tickets"
+};
+static const true_false_string krb5_ticketflags_proxy = {
+ "This is a PROXY ticket",
+ "This ticket has NOT been proxied"
+};
+static const true_false_string krb5_ticketflags_allow_postdate = {
+ "We allow the ticket to be POSTDATED",
+ "We do NOT allow the ticket to be postdated"
+};
+static const true_false_string krb5_ticketflags_postdated = {
+ "This ticket is POSTDATED",
+ "This ticket is NOT postdated"
+};
+static const true_false_string krb5_ticketflags_invalid = {
+ "This ticket is INVALID",
+ "This ticket is NOT invalid"
+};
+static const true_false_string krb5_ticketflags_renewable = {
+ "This ticket is RENEWABLE",
+ "This ticket is NOT renewable"
+};
+static const true_false_string krb5_ticketflags_initial = {
+ "This ticket was granted by AS and not TGT protocol",
+ "This ticket was granted by TGT and not as protocol"
+};
+static const true_false_string krb5_ticketflags_pre_auth = {
+ "The client was PRE-AUTHenticated",
+ "The client was NOT pre-authenticated"
+};
+static const true_false_string krb5_ticketflags_hw_auth = {
+ "The client was authenticated by HardWare",
+ "The client was NOT authenticated using hardware"
+};
+static const true_false_string krb5_ticketflags_transited_policy_checked = {
+ "Kdc has performed TRANSITED POLICY CHECKING",
+ "Kdc has NOT performed transited policy checking"
+};
+static const true_false_string krb5_ticketflags_ok_as_delegate = {
+ "This ticket is OK AS a DELEGATED ticket",
+ "This ticket is NOT ok as a delegated ticket"
+};
+
+static int* TicketFlags_bits[] = {
+ &hf_krb_TicketFlags_forwardable,
+ &hf_krb_TicketFlags_forwarded,
+ &hf_krb_TicketFlags_proxyable,
+ &hf_krb_TicketFlags_proxy,
+ &hf_krb_TicketFlags_allow_postdate,
+ &hf_krb_TicketFlags_postdated,
+ &hf_krb_TicketFlags_invalid,
+ &hf_krb_TicketFlags_renewable,
+ &hf_krb_TicketFlags_initial,
+ &hf_krb_TicketFlags_pre_auth,
+ &hf_krb_TicketFlags_hw_auth,
+ &hf_krb_TicketFlags_transited_policy_checked,
+ &hf_krb_TicketFlags_ok_as_delegate,
+ NULL
+};
+
+static int
+dissect_krb5_TicketFlags(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_bitstring32(FALSE, pinfo, tree, tvb, offset, TicketFlags_bits, hf_krb_TicketFlags, ett_krb_Ticket_Flags, NULL);
+ return offset;
+}
+
+
+static guint32 keytype;
+static int
+dissect_krb5_keytype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_keytype, &keytype);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(keytype, krb5_encryption_types,
+ "%#x"));
+ }
+ return offset;
+}
+static int keylength;
+static const char *keyvalue;
+static int
+store_keyvalue(packet_info *pinfo _U_, proto_tree *tree _U_, tvbuff_t *tvb, int offset)
+{
+ keylength=tvb_length_remaining(tvb, offset);
+ keyvalue=tvb_get_ptr(tvb, offset, keylength);
+ return 0;
+}
+static int
+dissect_krb5_keyvalue(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_keyvalue, store_keyvalue);
+ return offset;
+}
+
+
+/*
+ * EncryptionKey ::= SEQUENCE {
+ * keytype [0] int32
+ * keyvalue [1] octet string
+ */
+static ber_sequence EncryptionKey_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_keytype },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_keyvalue },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_key(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, EncryptionKey_sequence, hf_krb_key, ett_krb_key);
+
+#ifdef HAVE_KERBEROS
+ add_encryption_key(pinfo, keytype, keylength, keyvalue);
+#endif
+ return offset;
+}
+static int
+dissect_krb5_subkey(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, EncryptionKey_sequence, hf_krb_subkey, ett_krb_subkey);
+#ifdef HAVE_KERBEROS
+ add_encryption_key(pinfo, keytype, keylength, keyvalue);
+#endif
+ return offset;
+}
+
+
+
+static int
+dissect_krb5_PAC_LOGON_INFO(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
+ dcerpc_info di; /* fake dcerpc_info struct */
+ void *old_private_data;
+
+ item=proto_tree_add_item(parent_tree, hf_krb_PAC_LOGON_INFO, tvb, offset, tvb_length_remaining(tvb, offset), FALSE);
+ if(parent_tree){
+ tree=proto_item_add_subtree(item, ett_krb_PAC_LOGON_INFO);
+ }
+
+ /* skip the first 20 bytes, they look like a unique ndr pointer
+ followed by (where did it come from?) a contect_handle ?*/
+ proto_tree_add_text(tree, tvb, offset, 20, "unknown: is this an undocumented policy handle?");
+ offset+=20;
+
+
+ /* the PAC_LOGON_INFO blob */
+ /* fake whatever state the dcerpc runtime support needs */
+ di.conformant_run=0;
+ di.call_data=NULL;
+ old_private_data=pinfo->private_data;
+ pinfo->private_data=&di;
+ init_ndr_pointer_list(pinfo);
+ offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
+ netlogon_dissect_PAC_LOGON_INFO, NDR_POINTER_REF,
+ "PAC_LOGON_INFO:", -1);
+ pinfo->private_data=old_private_data;
+
+ return offset;
+}
+
+static int
+dissect_krb5_PAC_CREDENTIAL_TYPE(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ item=proto_tree_add_item(parent_tree, hf_krb_PAC_CREDENTIAL_TYPE, tvb, offset, tvb_length_remaining(tvb, offset), FALSE);
+ if(parent_tree){
+ tree=proto_item_add_subtree(item, ett_krb_PAC_CREDENTIAL_TYPE);
+ }
+
+/*qqq*/
+ return offset;
+}
+
+static int
+dissect_krb5_PAC_SERVER_CHECKSUM(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ item=proto_tree_add_item(parent_tree, hf_krb_PAC_SERVER_CHECKSUM, tvb, offset, tvb_length_remaining(tvb, offset), FALSE);
+ if(parent_tree){
+ tree=proto_item_add_subtree(item, ett_krb_PAC_SERVER_CHECKSUM);
+ }
+
+ /* signature type */
+ proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, TRUE);
+ offset+=4;
+
+ /* signature data */
+ proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, tvb_length_remaining(tvb, offset), FALSE);
+
+ return offset;
+}
+
+static int
+dissect_krb5_PAC_PRIVSVR_CHECKSUM(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+
+ item=proto_tree_add_item(parent_tree, hf_krb_PAC_PRIVSVR_CHECKSUM, tvb, offset, tvb_length_remaining(tvb, offset), FALSE);
+ if(parent_tree){
+ tree=proto_item_add_subtree(item, ett_krb_PAC_PRIVSVR_CHECKSUM);
+ }
+
+ /* signature type */
+ proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, TRUE);
+ offset+=4;
+
+ /* signature data */
+ proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, tvb_length_remaining(tvb, offset), FALSE);
+
+ return offset;
+}
+
+static int
+dissect_krb5_PAC_CLIENT_INFO_TYPE(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset)
+{
+ proto_item *item=NULL;
+ proto_tree *tree=NULL;
+ guint16 namelen;
+ char *name;
+
+ item=proto_tree_add_item(parent_tree, hf_krb_PAC_CLIENT_INFO_TYPE, tvb, offset, tvb_length_remaining(tvb, offset), FALSE);
+ if(parent_tree){
+ tree=proto_item_add_subtree(item, ett_krb_PAC_CLIENT_INFO_TYPE);
+ }
+
+ /* clientid */
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_krb_pac_clientid);
+
+ /* name length */
+ namelen=tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_krb_pac_namelen, tvb, offset, 2, namelen);
+ offset+=2;
+
+ /* client name */
+ name=tvb_fake_unicode(tvb, offset, namelen/2, TRUE);
+ proto_tree_add_string(tree, hf_krb_pac_clientname, tvb, offset, namelen, name);
+ offset+=namelen;
+
+ return offset;
+}
+
+static int
+dissect_krb5_AD_WIN2K_PAC_struct(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint32 pac_type;
+ guint32 pac_size;
+ guint32 pac_offset;
+ proto_item *it=NULL;
+ proto_tree *tr=NULL;
+ tvbuff_t *next_tvb;
+
+ /* type of pac data */
+ pac_type=tvb_get_letohl(tvb, offset);
+ it=proto_tree_add_uint(tree, hf_krb_w2k_pac_type, tvb, offset, 4, pac_type);
+ if(it){
+ tr=proto_item_add_subtree(it, ett_krb_PAC);
+ }
+
+ offset += 4;
+
+ /* size of pac data */
+ pac_size=tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tr, hf_krb_w2k_pac_size, tvb, offset, 4, pac_size);
+ offset += 4;
+
+ /* offset to pac data */
+ pac_offset=tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tr, hf_krb_w2k_pac_offset, tvb, offset, 4, pac_offset);
+ offset += 8;
+
+
+ next_tvb=tvb_new_subset(tvb, pac_offset, pac_size, pac_size);
+ switch(pac_type){
+ case PAC_LOGON_INFO:
+ dissect_krb5_PAC_LOGON_INFO(pinfo, tr, next_tvb, 0);
+ break;
+ case PAC_CREDENTIAL_TYPE:
+ dissect_krb5_PAC_CREDENTIAL_TYPE(pinfo, tr, next_tvb, 0);
+ break;
+ case PAC_SERVER_CHECKSUM:
+ dissect_krb5_PAC_SERVER_CHECKSUM(pinfo, tr, next_tvb, 0);
+ break;
+ case PAC_PRIVSVR_CHECKSUM:
+ dissect_krb5_PAC_PRIVSVR_CHECKSUM(pinfo, tr, next_tvb, 0);
+ break;
+ case PAC_CLIENT_INFO_TYPE:
+ dissect_krb5_PAC_CLIENT_INFO_TYPE(pinfo, tr, next_tvb, 0);
+ break;
+ default:;
+/*qqq*/
+ }
+ return offset;
+}
+
+static int
+dissect_krb5_AD_WIN2K_PAC(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint32 entries;
+ guint32 version;
+ guint32 i;
+
+ /* first in the PAC structure comes the number of entries */
+ entries=tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_krb_w2k_pac_entries, tvb, offset, 4, entries);
+ offset += 4;
+
+ /* second comes the version */
+ version=tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_krb_w2k_pac_version, tvb, offset, 4, version);
+ offset += 4;
+
+ for(i=0;i<entries;i++){
+ offset=dissect_krb5_AD_WIN2K_PAC_struct(pinfo, tree, tvb, offset);
+ }
+
+ return offset;
+}
+
+static guint32 IF_RELEVANT_type;
+static int
+dissect_krb5_IF_RELEVANT_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_IF_RELEVANT_type, &IF_RELEVANT_type);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(IF_RELEVANT_type, krb5_ad_types,
+ "%#x"));
+ }
+ return offset;
+}
+static int
+dissect_krb5_IF_RELEVANT_value(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ switch(IF_RELEVANT_type){
+ case KRB5_AD_WIN2K_PAC:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_advalue, dissect_krb5_AD_WIN2K_PAC);
+ break;
+ default:
+ offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_IF_RELEVANT_value, NULL);
+ }
+ return offset;
+}
+static ber_sequence IF_RELEVANT_item_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_IF_RELEVANT_type },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_IF_RELEVANT_value },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_IF_RELEVANT_item(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, IF_RELEVANT_item_sequence, hf_krb_IF_RELEVANT, ett_krb_IF_RELEVANT);
+
+ return offset;
+}
+
+static ber_sequence IF_RELEVANT_sequence_of[1] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_krb5_IF_RELEVANT_item },
+};
+
+static int
+dissect_krb5_IF_RELEVANT(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence_of(FALSE, pinfo, tree, tvb, offset, IF_RELEVANT_sequence_of, -1, -1);
+
+ return offset;
+}
+
+static guint32 adtype;
+static int
+dissect_krb5_adtype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_adtype, &adtype);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(adtype, krb5_ad_types,
+ "%#x"));
+ }
+ return offset;
+}
+static int
+dissect_krb5_advalue(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ switch(adtype){
+ case KRB5_AD_IF_RELEVANT:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_advalue, dissect_krb5_IF_RELEVANT);
+ break;
+ default:
+ offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_advalue, NULL);
+ }
+ return offset;
+}
+/*
+ * AuthorizationData ::= SEQUENCE {
+ * ad-type [0] int32
+ * ad-data [1] octet string
+ */
+static ber_sequence AuthorizationData_item_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_adtype },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_advalue },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_AuthorizationData_item(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, AuthorizationData_item_sequence, hf_krb_AuthorizationData, ett_krb_AuthorizationData);
+
+ return offset;
+}
+
+static ber_sequence AuthorizationData_sequence_of[1] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_krb5_AuthorizationData_item },
+};
+static int
+dissect_krb5_AuthorizationData(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence_of(FALSE, pinfo, tree, tvb, offset, AuthorizationData_sequence_of, -1, -1);
+
+ return offset;
+}
+
+
+static int
+dissect_krb5_transited_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint32 trtype;
+
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_transitedtype, &trtype);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(trtype, krb5_transited_types,
+ "%#x"));
+ }
+ return offset;
+}
+
+static int
+dissect_krb5_transited_contents(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_transitedcontents, NULL);
+ return offset;
+}
+
+/*
+ * TransitedEncoding ::= SEQUENCE {
+ * tr-type [0] int32
+ * contents [1] octet string
+ */
+static ber_sequence TransitedEncoding_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_transited_type },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_transited_contents },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_transited(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, TransitedEncoding_sequence, hf_krb_TransitedEncoding, ett_krb_TransitedEncoding);
+
+ return offset;
+}
+
+
+static int
+dissect_krb5_authtime(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_authtime);
+ return offset;
+}
+static int
+dissect_krb5_starttime(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_starttime);
+ return offset;
+}
+static int
+dissect_krb5_endtime(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_endtime);
+ return offset;
+}
+static int
+dissect_krb5_renew_till(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_renew_till);
+ return offset;
+}
+
+/*
+ * EncTicketPart ::= SEQUENCE {
+ * flags [0] TicketFlags,
+ * key [1] EncryptionKey,
+ * crealm [2] Realm,
+ * cname [3] PrincipalName,
+ * transited [4] TransitedEncoding,
+ * authtime [5] KerberosTime,
+ * starttime [6] KerberosTime OPTIONAL,
+ * endtime [7] KerberosTime,
+ * renew-till [8] KerberosTime OPTIONAL,
+ * caddr [9] HostAddresses OPTIONAL,
+ * authorization-data [10] AuthorizationData OPTIONAL
+ * }
+ */
+static ber_sequence EncTicketPart_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_TicketFlags },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_key },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_crealm },
+ { BER_CLASS_CON, 3, 0,
+ dissect_krb5_cname },
+ { BER_CLASS_CON, 4, 0,
+ dissect_krb5_transited },
+ { BER_CLASS_CON, 5, 0,
+ dissect_krb5_authtime },
+ { BER_CLASS_CON, 6, BER_FLAGS_OPTIONAL,
+ dissect_krb5_starttime },
+ { BER_CLASS_CON, 7, 0,
+ dissect_krb5_endtime },
+ { BER_CLASS_CON, 8, BER_FLAGS_OPTIONAL,
+ dissect_krb5_renew_till },
+ { BER_CLASS_CON, 9, BER_FLAGS_OPTIONAL,
+ dissect_krb5_HostAddresses },
+ { BER_CLASS_CON, 10, BER_FLAGS_OPTIONAL,
+ dissect_krb5_AuthorizationData },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_EncTicketPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, EncTicketPart_sequence, hf_krb_EncTicketPart, ett_krb_EncTicketPart);
+
+ return offset;
+}
+
+
+
+
+
+
+/*
+ * EncAPRepPart ::= SEQUENCE {
+ * ctime [0] KerberosTime
+ * cusec [1] Microseconds
+ * subkey [2] encryptionKey OPTIONAL
+ * seq-number [3] uint32 OPTIONAL
+ * }
+ */
+static ber_sequence EncAPRepPart_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_ctime },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_cusec },
+ { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL,
+ dissect_krb5_subkey },
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL,
+ dissect_krb5_seq_number },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_EncAPRepPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, EncAPRepPart_sequence, hf_krb_EncAPRepPart, ett_krb_EncAPRepPart);
+
+ return offset;
+}
+
+
+
+static guint32 lr_type;
+static const value_string krb5_lr_types[] = {
+ { 0 , "No information available" },
+ { 1 , "Time of last initial TGT request" },
+ { 2 , "Time of last initial request" },
+ { 3 , "Time of issue of latest TGT ticket" },
+ { 4 , "Time of last renewal" },
+ { 5 , "Time of last request" },
+ { 6 , "Time when password will expire" },
+ { 7 , "Time when account will expire" },
+ { 0, NULL }
+};
+static int
+dissect_krb5_lr_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_lr_type, &lr_type);
+
+ return offset;
+}
+static int
+dissect_krb5_lr_value(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_lr_time);
+
+ return offset;
+}
+
+static ber_sequence LastReq_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_lr_type },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_lr_value },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_LastReq(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, LastReq_sequence, hf_krb_LastReq, ett_krb_LastReq);
+
+ return offset;
+}
+static ber_sequence LastReq_sequence_of[1] = {
+ { BER_CLASS_UNI, BER_UNI_TAG_SEQUENCE, BER_FLAGS_NOOWNTAG, dissect_krb5_LastReq },
+};
+static int
+dissect_krb5_LastReq_sequence_of(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence_of(FALSE, pinfo, tree, tvb, offset, LastReq_sequence_of, hf_krb_LastReqs, ett_krb_LastReqs);
+
+ return offset;
+}
+
+static int
+dissect_krb5_key_expiration(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_key_expire);
+ return offset;
+}
+
+static ber_sequence EncKDCRepPart_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_key },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_LastReq_sequence_of },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_nonce },
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL,
+ dissect_krb5_key_expiration },
+ { BER_CLASS_CON, 4, 0,
+ dissect_krb5_TicketFlags },
+ { BER_CLASS_CON, 5, 0,
+ dissect_krb5_authtime },
+ { BER_CLASS_CON, 6, BER_FLAGS_OPTIONAL,
+ dissect_krb5_starttime },
+ { BER_CLASS_CON, 7, 0,
+ dissect_krb5_endtime },
+ { BER_CLASS_CON, 8, BER_FLAGS_OPTIONAL,
+ dissect_krb5_renew_till },
+ { BER_CLASS_CON, 9, 0,
+ dissect_krb5_realm },
+ { BER_CLASS_CON, 10, 0,
+ dissect_krb5_sname },
+ { BER_CLASS_CON, 11, BER_FLAGS_OPTIONAL,
+ dissect_krb5_HostAddresses },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_EncKDCRepPart(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, EncKDCRepPart_sequence, hf_krb_EncKDCRepPart, ett_krb_EncKDCRepPart);
+
+ return offset;
+}
+
+
+static int
+dissect_krb5_authenticator_vno(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_authenticator_vno, NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_krb5_checksum_type(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_checksum_type, NULL);
+
+ return offset;
+}
+static int
+dissect_krb5_checksum_checksum(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_checksum_checksum, NULL);
+ return offset;
+}
+
+/*
+ * Checksum ::= SEQUENCE {
+ * }
+ */
+static ber_sequence Checksum_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_checksum_type },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_checksum_checksum },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_Checksum(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, Checksum_sequence, hf_krb_Checksum, ett_krb_Checksum);
+
+ return offset;
+}
+
+/*
+ * Authenticator ::= SEQUENCE {
+ * authenticator-vno [0] integer
+ * crealm [1] Realm
+ * cname [2] PrincipalName
+ * cksum [3] Checksum OPTIONAL
+ * cusec [4] Microseconds
+ * ctime [5] KerberosTime
+ * subkey [6] encryptionKey OPTIONAL
+ * seq-number [7] uint32 OPTIONAL
+ * authorization-data [8] AuthorizationData OPTIONAL
+ * }
+ */
+static ber_sequence Authenticator_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_authenticator_vno },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_crealm },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_cname },
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL,
+ dissect_krb5_Checksum },
+ { BER_CLASS_CON, 4, 0,
+ dissect_krb5_cusec },
+ { BER_CLASS_CON, 5, 0,
+ dissect_krb5_ctime },
+ { BER_CLASS_CON, 6, BER_FLAGS_OPTIONAL,
+ dissect_krb5_subkey },
+ { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL,
+ dissect_krb5_seq_number },
+ { BER_CLASS_CON, 8, BER_FLAGS_OPTIONAL,
+ dissect_krb5_AuthorizationData },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_Authenticator(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, Authenticator_sequence, hf_krb_Authenticator, ett_krb_Authenticator);
+
+ return offset;
+}
+
+
+/*
+ * PRIV-BODY ::= SEQUENCE {
+ * KRB-PRIV ::= [APPLICATION 21] SEQUENCE {
+ * pvno[0] INTEGER,
+ * msg-type[1] INTEGER,
+ * enc-part[3] EncryptedData
+ * }
+ */
+static int
+dissect_krb5_encrypted_PRIV(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_PRIV, NULL);
+ return offset;
+}
+static ber_sequence ENC_PRIV_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_etype },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
+ dissect_krb5_kvno },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_encrypted_PRIV },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_ENC_PRIV(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, ENC_PRIV_sequence, hf_krb_ENC_PRIV, ett_krb_PRIV_enc);
+ return offset;
+}
+static ber_sequence PRIV_BODY_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_pvno },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_msg_type },
+ { BER_CLASS_CON, 3, 0,
+ dissect_krb5_ENC_PRIV },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_PRIV(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, PRIV_BODY_sequence, hf_krb_PRIV_BODY, ett_krb_PRIV);
+
+ return offset;
+}
+
+
+static int
+dissect_krb5_SAFE_BODY_user_data(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ tvbuff_t *new_tvb;
+ offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_SAFE_BODY_user_data, &new_tvb);
+ call_kerberos_callbacks(pinfo, tree, new_tvb, KRB_CBTAG_SAFE_USER_DATA);
+ return offset;
+}
+static int
+dissect_krb5_SAFE_BODY_timestamp(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_generalized_time(pinfo, tree, tvb, offset, hf_krb_SAFE_BODY_timestamp);
+ return offset;
+}
+
+static int
+dissect_krb5_SAFE_BODY_usec(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_SAFE_BODY_usec, NULL);
+ return offset;
+}
+
+static ber_sequence SAFE_BODY_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_SAFE_BODY_user_data },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
+ dissect_krb5_SAFE_BODY_timestamp },
+ { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL,
+ dissect_krb5_SAFE_BODY_usec },
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL,
+ dissect_krb5_seq_number },
+ /*XXX this one is OPTIONAL in packetcable? but mandatory in kerberos */
+ { BER_CLASS_CON, 4, BER_FLAGS_OPTIONAL,
+ dissect_krb5_s_address },
+ { BER_CLASS_CON, 5, BER_FLAGS_OPTIONAL,
+ dissect_krb5_HostAddresses },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_SAFE_BODY(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, SAFE_BODY_sequence, -1, -1);
+
+ return offset;
+}
+
+
+
+static ber_sequence SAFE_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_pvno },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_msg_type },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_SAFE_BODY },
+ { BER_CLASS_CON, 3, 0,
+ dissect_krb5_Checksum },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_SAFE(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, SAFE_sequence, -1, -1);
+
+ return offset;
+}
+
+
+/*
+ * KDC-REQ-BODY ::= SEQUENCE {
+ * kdc-options[0] KDCOptions,
+ * cname[1] PrincipalName OPTIONAL,
+ * -- Used only in AS-REQ
+ * realm[2] Realm, -- Server's realm
+ * -- Also client's in AS-REQ
+ * sname[3] PrincipalName OPTIONAL,
+ * from[4] KerberosTime OPTIONAL,
+ * till[5] KerberosTime,
+ * rtime[6] KerberosTime OPTIONAL,
+ * nonce[7] INTEGER,
+ * etype[8] SEQUENCE OF INTEGER, -- EncryptionType,
+ * -- in preference order
+ * addresses[9] HostAddresses OPTIONAL,
+ * enc-authorization-data[10] EncryptedData OPTIONAL,
+ * -- Encrypted AuthorizationData encoding
+ * additional-tickets[11] SEQUENCE OF Ticket OPTIONAL
+ * }
+ *
+ */
+static ber_sequence KDC_REQ_BODY_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_KDCOptions },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
+ dissect_krb5_cname },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_realm},
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL,
+ dissect_krb5_sname },
+ { BER_CLASS_CON, 4, BER_FLAGS_OPTIONAL,
+ dissect_krb5_from },
+ /* this field is not optional in the kerberos spec,
+ * however, in the packetcable spec it is optional.
+ * make it optional here since normal kerberos will
+ * still decode the pdu correctly.
+ */
+ { BER_CLASS_CON, 5, BER_FLAGS_OPTIONAL,
+ dissect_krb5_till },
+ { BER_CLASS_CON, 6, BER_FLAGS_OPTIONAL,
+ dissect_krb5_rtime },
+ { BER_CLASS_CON, 7, 0,
+ dissect_krb5_nonce },
+ { BER_CLASS_CON, 8, 0,
+ dissect_krb5_etype_sequence_of },
+ { BER_CLASS_CON, 9, BER_FLAGS_OPTIONAL,
+ dissect_krb5_HostAddresses },
+/* XXX [10] and [11] enc-authorization-data and additional-tickets should be added */
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_KDC_REQ_BODY(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, KDC_REQ_BODY_sequence, hf_krb_KDC_REQ_BODY, ett_krb_request);
+
+ return offset;
+}
+
+
+
+/*
+ * KDC-REQ ::= SEQUENCE {
+ * pvno[1] INTEGER,
+ * msg-type[2] INTEGER,
+ * padata[3] SEQUENCE OF PA-DATA OPTIONAL,
+ * req-body[4] KDC-REQ-BODY
+ * }
+ */
+static ber_sequence KDC_REQ_sequence[] = {
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_pvno },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_msg_type },
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL,
+ dissect_krb5_padata },
+ { BER_CLASS_CON, 4, 0,
+ dissect_krb5_KDC_REQ_BODY },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_KDC_REQ(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, KDC_REQ_sequence, -1, -1);
+
+ return offset;
+}
+
+
+#ifdef HAVE_KERBEROS
+static int
+dissect_krb5_decrypt_authenticator_data (packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint8 *plaintext=NULL;
+ int length;
+
+ length=tvb_length_remaining(tvb, offset);
+
+ /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
+ * 7.5.1
+ * Authenticators are encrypted with usage
+ * == 7 or
+ * == 11
+ */
+ if(!plaintext){
+ plaintext=decrypt_krb5_data(pinfo, 7, length, tvb_get_ptr(tvb, offset, length), authenticator_etype);
+ }
+ if(!plaintext){
+ plaintext=decrypt_krb5_data(pinfo, 11, length, tvb_get_ptr(tvb, offset, length), authenticator_etype);
+ }
+
+ if(plaintext){
+ tvbuff_t *next_tvb;
+ next_tvb = tvb_new_real_data (plaintext,
+ length,
+ length);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+
+ /* Add the decrypted data to the data source list. */
+ add_new_data_source(pinfo, next_tvb, "Decrypted Krb5");
+
+
+ offset=dissect_ber_choice(pinfo, tree, next_tvb, 0, kerberos_applications_choice, -1, -1);
+
+ }
+ return offset;
+}
+#endif
+
+
+/*
+ * EncryptedData ::= SEQUENCE {
+ * etype[0] INTEGER, -- EncryptionType
+ * kvno[1] INTEGER OPTIONAL,
+ * cipher[2] OCTET STRING -- ciphertext
+ * }
+ */
+static int
+dissect_krb5_encrypted_authenticator_data(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+#ifdef HAVE_KERBEROS
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_authenticator_data, dissect_krb5_decrypt_authenticator_data);
+#else
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_authenticator_data, NULL);
+#endif
+ return offset;
+}
+static ber_sequence encrypted_authenticator_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_authenticator_etype },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
+ dissect_krb5_kvno },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_encrypted_authenticator_data },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_encrypted_authenticator(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, encrypted_authenticator_sequence, hf_krb_authenticator_enc, ett_krb_authenticator_enc);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_krb5_tkt_vno(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_tkt_vno, NULL);
+ return offset;
+}
+
+
+#ifdef HAVE_KERBEROS
+static int
+dissect_krb5_decrypt_Ticket_data (packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint8 *plaintext;
+ int length;
+
+ length=tvb_length_remaining(tvb, offset);
+
+ /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
+ * 7.5.1
+ * All Ticket encrypted parts use usage == 2
+ */
+ if( (plaintext=decrypt_krb5_data(pinfo, 2, length, tvb_get_ptr(tvb, offset, length), Ticket_etype)) ){
+ tvbuff_t *next_tvb;
+ next_tvb = tvb_new_real_data (plaintext,
+ length,
+ length);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+
+ /* Add the decrypted data to the data source list. */
+ add_new_data_source(pinfo, next_tvb, "Decrypted Krb5");
+
+
+ offset=dissect_ber_choice(pinfo, tree, next_tvb, 0, kerberos_applications_choice, -1, -1);
+
+ }
+ return offset;
+}
+#endif
+
+static int
+dissect_krb5_encrypted_Ticket_data(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+#ifdef HAVE_KERBEROS
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_Ticket_data, dissect_krb5_decrypt_Ticket_data);
+#else
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_Ticket_data, NULL);
+#endif
+ return offset;
+}
+static ber_sequence encrypted_Ticket_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_Ticket_etype },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
+ dissect_krb5_kvno },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_encrypted_Ticket_data },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_Ticket_encrypted(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, encrypted_Ticket_sequence, hf_krb_ticket_enc, ett_krb_ticket_enc);
+
+ return offset;
+}
+
+static ber_sequence Application_1_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_tkt_vno },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_realm },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_sname },
+ { BER_CLASS_CON, 3, 0,
+ dissect_krb5_Ticket_encrypted },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_Application_1(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, Application_1_sequence, hf_krb_ticket, ett_krb_ticket);
+
+ return offset;
+}
+
+
+
+static const ber_choice Ticket_choice[] = {
+ { 1, BER_CLASS_APP, 1, 0,
+ dissect_krb5_Application_1 },
+ { 0, 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_Ticket(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_choice(pinfo, tree, tvb, offset, Ticket_choice, -1, -1);
+
+ return offset;
+}
+
+
+
+
+/*
+ * AP-REQ ::= [APPLICATION 14] SEQUENCE {
+ * pvno[0] INTEGER,
+ * msg-type[1] INTEGER,
+ * ap-options[2] APOptions,
+ * ticket[3] Ticket,
+ * authenticator[4] EncryptedData
+ * }
+ */
+static ber_sequence AP_REQ_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_pvno },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_msg_type },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_APOptions },
+ { BER_CLASS_CON, 3, 0,
+ dissect_krb5_Ticket },
+ { BER_CLASS_CON, 4, 0,
+ dissect_krb5_encrypted_authenticator },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_AP_REQ(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, AP_REQ_sequence, -1, -1);
+
+ return offset;
+}
+
+
+
+
+#ifdef HAVE_KERBEROS
+static int
+dissect_krb5_decrypt_AP_REP_data(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint8 *plaintext=NULL;
+ int length;
+
+ length=tvb_length_remaining(tvb, offset);
+
+ /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
+ * 7.5.1
+ * Authenticators are encrypted with usage
+ * == 7 or
+ * == 11
+ */
+ if(!plaintext){
+ plaintext=decrypt_krb5_data(pinfo, 12, length, tvb_get_ptr(tvb, offset, length), AP_REP_etype);
+ }
+
+ if(plaintext){
+ tvbuff_t *next_tvb;
+ next_tvb = tvb_new_real_data (plaintext,
+ length,
+ length);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+
+ /* Add the decrypted data to the data source list. */
+ add_new_data_source(pinfo, next_tvb, "Decrypted Krb5");
+
+
+ offset=dissect_ber_choice(pinfo, tree, next_tvb, 0, kerberos_applications_choice, -1, -1);
+
+ }
+ return offset;
+}
+#endif
+
+
+static int
+dissect_krb5_encrypted_AP_REP_data(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+#ifdef HAVE_KERBEROS
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_AP_REP_data, dissect_krb5_decrypt_AP_REP_data);
+#else
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_AP_REP_data, NULL);
+#endif
+ return offset;
+}
+static ber_sequence encrypted_AP_REP_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_AP_REP_etype },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
+ dissect_krb5_kvno },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_encrypted_AP_REP_data },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_encrypted_AP_REP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, encrypted_AP_REP_sequence, hf_krb_AP_REP_enc, ett_krb_AP_REP_enc);
+
+ return offset;
+}
+
+/*
+ * AP-REP ::= [APPLICATION 15] SEQUENCE {
+ * pvno[0] INTEGER,
+ * msg-type[1] INTEGER,
+ * enc-part[2] EncryptedData
+ * }
+ */
+static ber_sequence AP_REP_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_pvno },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_msg_type },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_encrypted_AP_REP },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_AP_REP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, AP_REP_sequence, -1, -1);
+
+ return offset;
+}
+
+
+
+
+
+static guint32 KDC_REP_etype;
+static int
+dissect_krb5_KDC_REP_etype(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_integer(pinfo, tree, tvb, offset, hf_krb_etype, &KDC_REP_etype);
+ if(tree){
+ proto_item_append_text(tree, " %s",
+ val_to_str(KDC_REP_etype, krb5_encryption_types,
+ "%#x"));
+ }
+ return offset;
+}
+
+#ifdef HAVE_KERBEROS
+static int
+dissect_krb5_decrypt_KDC_REP_data (packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint8 *plaintext=NULL;
+ int length;
+
+ length=tvb_length_remaining(tvb, offset);
+
+ /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
+ * 7.5.1
+ * ASREP/TGSREP encryptedparts are encrypted with usage
+ * == 3 or
+ * == 8 or
+ * == 9
+ */
+ if(!plaintext){
+ plaintext=decrypt_krb5_data(pinfo, 3, length, tvb_get_ptr(tvb, offset, length), KDC_REP_etype);
+ }
+ if(!plaintext){
+ plaintext=decrypt_krb5_data(pinfo, 8, length, tvb_get_ptr(tvb, offset, length), KDC_REP_etype);
+ }
+ if(!plaintext){
+ plaintext=decrypt_krb5_data(pinfo, 9, length, tvb_get_ptr(tvb, offset, length), KDC_REP_etype);
+ }
+
+ if(plaintext){
+ tvbuff_t *next_tvb;
+ next_tvb = tvb_new_real_data (plaintext,
+ length,
+ length);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+
+ /* Add the decrypted data to the data source list. */
+ add_new_data_source(pinfo, next_tvb, "Decrypted Krb5");
+
+
+ offset=dissect_ber_choice(pinfo, tree, next_tvb, 0, kerberos_applications_choice, -1, -1);
+
+ }
+ return offset;
+}
+#endif
+
+
+static int
+dissect_krb5_encrypted_KDC_REP_data(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+#ifdef HAVE_KERBEROS
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_KDC_REP_data, dissect_krb5_decrypt_KDC_REP_data);
+#else
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_encrypted_KDC_REP_data, NULL);
+#endif
+ return offset;
+}
+static ber_sequence encrypted_KDC_REP_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_KDC_REP_etype },
+ { BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL,
+ dissect_krb5_kvno },
+ { BER_CLASS_CON, 2, 0,
+ dissect_krb5_encrypted_KDC_REP_data },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_encrypted_KDC_REP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, encrypted_KDC_REP_sequence, hf_krb_KDC_REP_enc, ett_krb_KDC_REP_enc);
+
+ return offset;
+}
+
+/*
+ * KDC-REP ::= SEQUENCE {
+ * pvno[0] INTEGER,
+ * msg-type[1] INTEGER,
+ * padata[2] SEQUENCE OF PA-DATA OPTIONAL,
+ * crealm[3] Realm,
+ * cname[4] PrincipalName,
+ * ticket[5] Ticket,
+ * enc-part[6] EncryptedData
+ * }
+ */
+static ber_sequence KDC_REP_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_pvno },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_msg_type },
+ { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL,
+ dissect_krb5_padata },
+ { BER_CLASS_CON, 3, 0,
+ dissect_krb5_crealm },
+ { BER_CLASS_CON, 4, 0,
+ dissect_krb5_cname },
+ { BER_CLASS_CON, 5, 0,
+ dissect_krb5_Ticket },
+ { BER_CLASS_CON, 6, 0,
+ dissect_krb5_encrypted_KDC_REP },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_KDC_REP(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, KDC_REP_sequence, -1, -1);
+
+ return offset;
+}
+
+
+
+
+static int
+dissect_krb5_e_text(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_GeneralString(pinfo, tree, tvb, offset, hf_krb_e_text, NULL, 0);
+ return offset;
+}
+
+static int
+dissect_krb5_e_data(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ switch(krb5_errorcode){
+ case KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED:
+ offset=dissect_ber_octet_string_wcb(FALSE, pinfo, tree, tvb, offset, hf_krb_e_data, dissect_krb5_padata);
+
+ break;
+ default:
+ offset=dissect_ber_octet_string(FALSE, pinfo, tree, tvb, offset, hf_krb_e_data, NULL);
+ }
+ return offset;
+}
+
+
+/*
+ * KRB-ERROR ::= [APPLICATION 30] SEQUENCE {
+ * pvno[0] INTEGER,
+ * msg-type[1] INTEGER,
+ * ctime[2] KerberosTime OPTIONAL,
+ * cusec[3] INTEGER OPTIONAL,
+ * stime[4] KerberosTime,
+ * susec[5] INTEGER,
+ * error-code[6] INTEGER,
+ * crealm[7] Realm OPTIONAL,
+ * cname[8] PrincipalName OPTIONAL,
+ * realm[9] Realm, -- Correct realm
+ * sname[10] PrincipalName, -- Correct name
+ * e-text[11] GeneralString OPTIONAL,
+ * e-data[12] OCTET STRING OPTIONAL
+ * }
+ *
+ * e-data This field contains additional data about the error for use
+ * by the application to help it recover from or handle the
+ * error. If the errorcode is KDC_ERR_PREAUTH_REQUIRED, then
+ * the e-data field will contain an encoding of a sequence of
+ * padata fields, each corresponding to an acceptable pre-
+ * authentication method and optionally containing data for
+ * the method:
+ */
+static ber_sequence ERROR_sequence[] = {
+ { BER_CLASS_CON, 0, 0,
+ dissect_krb5_pvno },
+ { BER_CLASS_CON, 1, 0,
+ dissect_krb5_msg_type },
+ { BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL,
+ dissect_krb5_ctime },
+ { BER_CLASS_CON, 3, BER_FLAGS_OPTIONAL,
+ dissect_krb5_cusec },
+ { BER_CLASS_CON, 4, 0,
+ dissect_krb5_stime },
+ { BER_CLASS_CON, 5, 0,
+ dissect_krb5_susec },
+ { BER_CLASS_CON, 6, 0,
+ dissect_krb5_error_code },
+ { BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL,
+ dissect_krb5_crealm },
+ { BER_CLASS_CON, 8, BER_FLAGS_OPTIONAL,
+ dissect_krb5_cname },
+ { BER_CLASS_CON, 9, 0,
+ dissect_krb5_realm },
+ { BER_CLASS_CON, 10, 0,
+ dissect_krb5_sname },
+ { BER_CLASS_CON, 11, BER_FLAGS_OPTIONAL,
+ dissect_krb5_e_text },
+ { BER_CLASS_CON, 12, BER_FLAGS_OPTIONAL,
+ dissect_krb5_e_data },
+ { 0, 0, 0, NULL }
+};
+static int
+dissect_krb5_ERROR(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ offset=dissect_ber_sequence(FALSE, pinfo, tree, tvb, offset, ERROR_sequence, -1, -1);
+
+ return offset;
+}
+
+
+
+static struct { char *set; char *unset; } bitval = { "Set", "Not set" };
+
+static void dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree);
+static void dissect_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree);
+static gint dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int do_col_info,
+ gboolean have_rm,
+ kerberos_callbacks *cb);
+static gint kerberos_rm_to_reclen(guint krb_rm);
+static void dissect_kerberos_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree);
+static guint get_krb_pdu_len(tvbuff_t *tvb, int offset);
+
+
+
+gint
+dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int do_col_info, kerberos_callbacks *cb)
+{
+ return (dissect_kerberos_common(tvb, pinfo, tree, do_col_info, FALSE, cb));
+}
+
+static void
+dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
+
+ (void)dissect_kerberos_common(tvb, pinfo, tree, TRUE, FALSE, NULL);
+}
+
+static gint
+kerberos_rm_to_reclen(guint krb_rm)
+{
+ return (krb_rm & KRB_RM_RECLEN);
+}
+
+static guint
+get_krb_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint krb_rm;
+ gint pdulen;
+
+ krb_rm = tvb_get_ntohl(tvb, offset);
+ pdulen = kerberos_rm_to_reclen(krb_rm);
+ return (pdulen + 4);
+}
+
+static void
+dissect_kerberos_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ pinfo->fragmented = TRUE;
+ if (dissect_kerberos_common(tvb, pinfo, tree, TRUE, TRUE, NULL) < 0) {
+ /*
+ * The dissector failed to recognize this as a valid
+ * Kerberos message. Mark it as a continuation packet.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+ }
+ }
+}
+
+static void
+dissect_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
+
+ tcp_dissect_pdus(tvb, pinfo, tree, krb_desegment, 4, get_krb_pdu_len,
+ dissect_kerberos_tcp_pdu);
+}
+
+/*
+ * Display the TCP record mark.
+ */
+static void
+show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, gint start, guint32 krb_rm)
+{
+ gint rec_len;
+ proto_item *rm_item;
+ proto_tree *rm_tree;
+
+ if (tree == NULL)
+ return;
+
+ rec_len = kerberos_rm_to_reclen(krb_rm);
+ rm_item = proto_tree_add_text(tree, tvb, start, 4,
+ "Record Mark: %u %s", rec_len, plurality(rec_len, "byte", "bytes"));
+ rm_tree = proto_item_add_subtree(rm_item, ett_krb_recordmark);
+ proto_tree_add_boolean(rm_tree, hf_krb_rm_reserved, tvb, start, 4, krb_rm);
+ proto_tree_add_uint(rm_tree, hf_krb_rm_reclen, tvb, start, 4, krb_rm);
+}
+
+
+static gint
+dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int dci, gboolean have_rm, kerberos_callbacks *cb)
+{
+ int offset = 0;
+ proto_tree *kerberos_tree = NULL;
+ proto_item *item = NULL;
+ void *saved_private_data;
+
+ /* TCP record mark and length */
+ guint32 krb_rm = 0;
+ gint krb_reclen = 0;
+
+ saved_private_data=pinfo->private_data;
+ pinfo->private_data=cb;
+ do_col_info=dci;
+
+ if (tree) {
+ item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, FALSE);
+ kerberos_tree = proto_item_add_subtree(item, ett_krb_kerberos);
+ }
+
+ if (have_rm) {
+ krb_rm = tvb_get_ntohl(tvb, offset);
+ krb_reclen = kerberos_rm_to_reclen(krb_rm);
+ /*
+ * What is a reasonable size limit?
+ */
+ if (krb_reclen > 10 * 1024 * 1024) {
+ pinfo->private_data=saved_private_data;
+ return (-1);
+ }
+ show_krb_recordmark(kerberos_tree, tvb, offset, krb_rm);
+ offset += 4;
+ }
+
+ offset=dissect_ber_choice(pinfo, kerberos_tree, tvb, offset, kerberos_applications_choice, -1, -1);
+
+ proto_item_set_len(item, offset);
+ pinfo->private_data=saved_private_data;
+ return offset;
+}
+
+
+void
+proto_register_kerberos(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_krb_rm_reserved, {
+ "Reserved", "kerberos.rm.reserved", FT_BOOLEAN, 32,
+ &bitval, KRB_RM_RESERVED, "Record mark reserved bit", HFILL }},
+ { &hf_krb_rm_reclen, {
+ "Record Length", "kerberos.rm.length", FT_UINT32, BASE_DEC,
+ NULL, KRB_RM_RECLEN, "Record length", HFILL }},
+ { &hf_krb_transitedtype, {
+ "Type", "kerberos.transited.type", FT_UINT32, BASE_DEC,
+ VALS(krb5_transited_types), 0, "Transited Type", HFILL }},
+ { &hf_krb_transitedcontents, {
+ "Contents", "kerberos.transited.contents", FT_BYTES, BASE_HEX,
+ NULL, 0, "Transitent Contents string", HFILL }},
+ { &hf_krb_keytype, {
+ "Key type", "kerberos.keytype", FT_UINT32, BASE_DEC,
+ VALS(krb5_encryption_types), 0, "Key Type", HFILL }},
+ { &hf_krb_keyvalue, {
+ "Key value", "kerberos.keyvalue", FT_BYTES, BASE_HEX,
+ NULL, 0, "Key value (encryption key)", HFILL }},
+ { &hf_krb_adtype, {
+ "Type", "kerberos.adtype", FT_UINT32, BASE_DEC,
+ VALS(krb5_ad_types), 0, "Authorization Data Type", HFILL }},
+ { &hf_krb_IF_RELEVANT_type, {
+ "Type", "kerberos.IF_RELEVANT.type", FT_UINT32, BASE_DEC,
+ VALS(krb5_ad_types), 0, "IF-RELEVANT Data Type", HFILL }},
+ { &hf_krb_advalue, {
+ "Data", "kerberos.advalue", FT_BYTES, BASE_HEX,
+ NULL, 0, "Authentication Data", HFILL }},
+ { &hf_krb_IF_RELEVANT_value, {
+ "Data", "kerberos.IF_RELEVANT.value", FT_BYTES, BASE_HEX,
+ NULL, 0, "IF_RELEVANT Data", HFILL }},
+ { &hf_krb_etype, {
+ "Encryption type", "kerberos.etype", FT_INT32, BASE_DEC,
+ VALS(krb5_encryption_types), 0, "Encryption Type", HFILL }},
+ { &hf_krb_addr_type, {
+ "Addr-type", "kerberos.addr_type", FT_UINT32, BASE_DEC,
+ VALS(krb5_address_types), 0, "Address Type", HFILL }},
+ { &hf_krb_pac_signature_type, {
+ "Type", "kerberos.pac.signature.type", FT_INT32, BASE_DEC,
+ NULL, 0, "PAC Signature Type", HFILL }},
+ { &hf_krb_name_type, {
+ "Name-type", "kerberos.name_type", FT_INT32, BASE_DEC,
+ VALS(krb5_princ_types), 0, "Type of principal name", HFILL }},
+ { &hf_krb_lr_type, {
+ "Lr-type", "kerberos.lr_type", FT_UINT32, BASE_DEC,
+ VALS(krb5_lr_types), 0, "Type of lastreq value", HFILL }},
+ { &hf_krb_address_ip, {
+ "IP Address", "kerberos.addr_ip", FT_IPv4, BASE_NONE,
+ NULL, 0, "IP Address", HFILL }},
+ { &hf_krb_address_netbios, {
+ "NetBIOS Address", "kerberos.addr_nb", FT_STRING, BASE_NONE,
+ NULL, 0, "NetBIOS Address and type", HFILL }},
+ { &hf_krb_contentinfo_contenttype, {
+ "ContentType", "kerberos.contenttype", FT_STRING, BASE_NONE,
+ NULL, 0, "ContentInfo ContentType field", HFILL }},
+ { &hf_krb_authtime, {
+ "Authtime", "kerberos.authtime", FT_STRING, BASE_NONE,
+ NULL, 0, "Time of initial authentication", HFILL }},
+ { &hf_krb_SAFE_BODY_timestamp, {
+ "Timestamp", "kerberos.SAFE_BODY.timestamp", FT_STRING, BASE_NONE,
+ NULL, 0, "Timestamp of this SAFE_BODY", HFILL }},
+ { &hf_krb_patimestamp, {
+ "patimestamp", "kerberos.patimestamp", FT_STRING, BASE_NONE,
+ NULL, 0, "Time of client", HFILL }},
+ { &hf_krb_pausec, {
+ "pausec", "kerberos.pausec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Microsecond component of client time", HFILL }},
+ { &hf_krb_lr_time, {
+ "Lr-time", "kerberos.lr_time", FT_STRING, BASE_NONE,
+ NULL, 0, "Time of LR-entry", HFILL }},
+ { &hf_krb_starttime, {
+ "Start time", "kerberos.starttime", FT_STRING, BASE_NONE,
+ NULL, 0, "The time after which the ticket is valid", HFILL }},
+ { &hf_krb_endtime, {
+ "End time", "kerberos.endtime", FT_STRING, BASE_NONE,
+ NULL, 0, "The time after which the ticket has expired", HFILL }},
+ { &hf_krb_key_expire, {
+ "Key Expiration", "kerberos.key_expiration", FT_STRING, BASE_NONE,
+ NULL, 0, "The time after which the key will expire", HFILL }},
+ { &hf_krb_renew_till, {
+ "Renew-till", "kerberos.renenw_till", FT_STRING, BASE_NONE,
+ NULL, 0, "The maximum time we can renew the ticket until", HFILL }},
+ { &hf_krb_rtime, {
+ "rtime", "kerberos.rtime", FT_STRING, BASE_NONE,
+ NULL, 0, "Renew Until timestamp", HFILL }},
+ { &hf_krb_ctime, {
+ "ctime", "kerberos.ctime", FT_STRING, BASE_NONE,
+ NULL, 0, "Current Time on the client host", HFILL }},
+ { &hf_krb_cusec, {
+ "cusec", "kerberos.cusec", FT_UINT32, BASE_DEC,
+ NULL, 0, "micro second component of client time", HFILL }},
+ { &hf_krb_SAFE_BODY_usec, {
+ "usec", "kerberos.SAFE_BODY.usec", FT_UINT32, BASE_DEC,
+ NULL, 0, "micro second component of SAFE_BODY time", HFILL }},
+ { &hf_krb_stime, {
+ "stime", "kerberos.stime", FT_STRING, BASE_NONE,
+ NULL, 0, "Current Time on the server host", HFILL }},
+ { &hf_krb_susec, {
+ "susec", "kerberos.susec", FT_UINT32, BASE_DEC,
+ NULL, 0, "micro second component of server time", HFILL }},
+ { &hf_krb_error_code, {
+ "error_code", "kerberos.error_code", FT_UINT32, BASE_DEC,
+ VALS(krb5_error_codes), 0, "Kerberos error code", HFILL }},
+ { &hf_krb_from, {
+ "from", "kerberos.from", FT_STRING, BASE_NONE,
+ NULL, 0, "From when the ticket is to be valid (postdating)", HFILL }},
+ { &hf_krb_till, {
+ "till", "kerberos.till", FT_STRING, BASE_NONE,
+ NULL, 0, "When the ticket will expire", HFILL }},
+ { &hf_krb_name_string, {
+ "Name", "kerberos.name_string", FT_STRING, BASE_NONE,
+ NULL, 0, "String component that is part of a PrincipalName", HFILL }},
+ { &hf_krb_provsrv_location, {
+ "PROVSRV Location", "kerberos.provsrv_location", FT_STRING, BASE_NONE,
+ NULL, 0, "PacketCable PROV SRV Location", HFILL }},
+ { &hf_krb_e_text, {
+ "e-text", "kerberos.e_text", FT_STRING, BASE_NONE,
+ NULL, 0, "Additional (human readable) error description", HFILL }},
+ { &hf_krb_realm, {
+ "Realm", "kerberos.realm", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of the Kerberos Realm", HFILL }},
+ { &hf_krb_crealm, {
+ "Client Realm", "kerberos.crealm", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of the Clients Kerberos Realm", HFILL }},
+ { &hf_krb_pac_clientname, {
+ "Name", "kerberos.pac.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of the Client in the PAC structure", HFILL }},
+ { &hf_krb_msg_type, {
+ "MSG Type", "kerberos.msg.type", FT_UINT32, BASE_DEC,
+ VALS(krb5_msg_types), 0, "Kerberos Message Type", HFILL }},
+ { &hf_krb_APOptions, {
+ "APOptions", "kerberos.apoptions", FT_BYTES, BASE_HEX,
+ NULL, 0, "Kerberos APOptions bitstring", HFILL }},
+ { &hf_krb_APOptions_use_session_key, {
+ "Use Session Key", "kerberos.apoptions.use_session_key", FT_BOOLEAN, 32,
+ TFS(&krb5_apoptions_use_session_key), 0x40000000, "", HFILL }},
+ { &hf_krb_APOptions_mutual_required, {
+ "Mutual required", "kerberos.apoptions.mutual_required", FT_BOOLEAN, 32,
+ TFS(&krb5_apoptions_mutual_required), 0x20000000, "", HFILL }},
+ { &hf_krb_KDCOptions, {
+ "KDCOptions", "kerberos.kdcoptions", FT_BYTES, BASE_HEX,
+ NULL, 0, "Kerberos KDCOptions bitstring", HFILL }},
+ { &hf_krb_TicketFlags, {
+ "Ticket Flags", "kerberos.ticketflags", FT_NONE, BASE_NONE,
+ NULL, 0, "Kerberos Ticket Flags", HFILL }},
+ { &hf_krb_TicketFlags_forwardable, {
+ "Forwardable", "kerberos.ticketflags.forwardable", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_forwardable), 0x40000000, "Flag controlling whether the tickes are forwardable or not", HFILL }},
+ { &hf_krb_TicketFlags_forwarded, {
+ "Forwarded", "kerberos.ticketflags.forwarded", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_forwarded), 0x20000000, "Has this ticket been forwarded?", HFILL }},
+ { &hf_krb_TicketFlags_proxyable, {
+ "Proxyable", "kerberos.ticketflags.proxyable", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_proxyable), 0x10000000, "Flag controlling whether the tickes are proxyable or not", HFILL }},
+ { &hf_krb_TicketFlags_proxy, {
+ "Proxy", "kerberos.ticketflags.proxy", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_proxy), 0x08000000, "Has this ticket been proxied?", HFILL }},
+ { &hf_krb_TicketFlags_allow_postdate, {
+ "Allow Postdate", "kerberos.ticketflags.allow_postdate", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_allow_postdate), 0x04000000, "Flag controlling whether we allow postdated tickets or not", HFILL }},
+ { &hf_krb_TicketFlags_postdated, {
+ "Postdated", "kerberos.ticketflags.postdated", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_postdated), 0x02000000, "Whether this ticket is postdated or not", HFILL }},
+ { &hf_krb_TicketFlags_invalid, {
+ "Invalid", "kerberos.ticketflags.invalid", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_invalid), 0x01000000, "Whether this ticket is invalid or not", HFILL }},
+ { &hf_krb_TicketFlags_renewable, {
+ "Renewable", "kerberos.ticketflags.renewable", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_renewable), 0x00800000, "Whether this ticket is renewable or not", HFILL }},
+ { &hf_krb_TicketFlags_initial, {
+ "Initial", "kerberos.ticketflags.initial", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_initial), 0x00400000, "Whether this ticket is an initial ticket or not", HFILL }},
+ { &hf_krb_TicketFlags_pre_auth, {
+ "Pre-Auth", "kerberos.ticketflags.pre_auth", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_pre_auth), 0x00200000, "Whether this ticket is pre-authenticated or not", HFILL }},
+ { &hf_krb_TicketFlags_hw_auth, {
+ "HW-Auth", "kerberos.ticketflags.hw_auth", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_hw_auth), 0x00100000, "Whether this ticket is hardware-authenticated or not", HFILL }},
+ { &hf_krb_TicketFlags_transited_policy_checked, {
+ "Transited Policy Checked", "kerberos.ticketflags.transited_policy_checked", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_transited_policy_checked), 0x00080000, "Whether this ticket is transited policy checked or not", HFILL }},
+ { &hf_krb_TicketFlags_ok_as_delegate, {
+ "Ok As Delegate", "kerberos.ticketflags.ok_as_delegate", FT_BOOLEAN, 32,
+ TFS(&krb5_ticketflags_ok_as_delegate), 0x00040000, "Whether this ticket is Ok As Delegate or not", HFILL }},
+ { &hf_krb_KDC_REQ_BODY, {
+ "KDC_REQ_BODY", "kerberos.kdc_req_body", FT_NONE, BASE_NONE,
+ NULL, 0, "Kerberos KDC REQuest BODY", HFILL }},
+ { &hf_krb_PRIV_BODY, {
+ "PRIV_BODY", "kerberos.priv_body", FT_NONE, BASE_NONE,
+ NULL, 0, "Kerberos PRIVate BODY", HFILL }},
+ { &hf_krb_encrypted_PRIV, {
+ "Encrypted PRIV", "kerberos.enc_priv", FT_NONE, BASE_NONE,
+ NULL, 0, "Kerberos Encrypted PRIVate blob data", HFILL }},
+ { &hf_krb_KDCOptions_forwardable, {
+ "Forwardable", "kerberos.kdcoptions.forwardable", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_forwardable), 0x40000000, "Flag controlling whether the tickes are forwardable or not", HFILL }},
+ { &hf_krb_KDCOptions_forwarded, {
+ "Forwarded", "kerberos.kdcoptions.forwarded", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_forwarded), 0x20000000, "Has this ticket been forwarded?", HFILL }},
+ { &hf_krb_KDCOptions_proxyable, {
+ "Proxyable", "kerberos.kdcoptions.proxyable", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_proxyable), 0x10000000, "Flag controlling whether the tickes are proxyable or not", HFILL }},
+ { &hf_krb_KDCOptions_proxy, {
+ "Proxy", "kerberos.kdcoptions.proxy", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_proxy), 0x08000000, "Has this ticket been proxied?", HFILL }},
+ { &hf_krb_KDCOptions_allow_postdate, {
+ "Allow Postdate", "kerberos.kdcoptions.allow_postdate", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_allow_postdate), 0x04000000, "Flag controlling whether we allow postdated tickets or not", HFILL }},
+ { &hf_krb_KDCOptions_postdated, {
+ "Postdated", "kerberos.kdcoptions.postdated", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_postdated), 0x02000000, "Whether this ticket is postdated or not", HFILL }},
+ { &hf_krb_KDCOptions_renewable, {
+ "Renewable", "kerberos.kdcoptions.renewable", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_renewable), 0x00800000, "Whether this ticket is renewable or not", HFILL }},
+ { &hf_krb_KDCOptions_canonicalize, {
+ "Canonicalize", "kerberos.kdcoptions.canonicalize", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_canonicalize), 0x00010000, "Do we want the KDC to canonicalize the principal or not", HFILL }},
+ { &hf_krb_KDCOptions_opt_hardware_auth, {
+ "Opt HW Auth", "kerberos.kdcoptions.opt_hardware_auth", FT_BOOLEAN, 32,
+ NULL, 0x00100000, "Opt HW Auth flag", HFILL }},
+ { &hf_krb_KDCOptions_disable_transited_check, {
+ "Disable Transited Check", "kerberos.kdcoptions.disable_transited_check", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_disable_transited_check), 0x00000020, "Whether we should do transited checking or not", HFILL }},
+ { &hf_krb_KDCOptions_renewable_ok, {
+ "Renewable OK", "kerberos.kdcoptions.renewable_ok", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_renewable_ok), 0x00000010, "Whether we accept renewed tickets or not", HFILL }},
+ { &hf_krb_KDCOptions_enc_tkt_in_skey, {
+ "Enc-Tkt-in-Skey", "kerberos.kdcoptions.enc_tkt_in_skey", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_enc_tkt_in_skey), 0x00000008, "Whether the ticket is encrypted in the skey or not", HFILL }},
+ { &hf_krb_KDCOptions_renew, {
+ "Renew", "kerberos.kdcoptions.renew", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_renew), 0x00000002, "Is this a request to renew a ticket?", HFILL }},
+ { &hf_krb_KDCOptions_validate, {
+ "Validate", "kerberos.kdcoptions.validate", FT_BOOLEAN, 32,
+ TFS(&krb5_kdcoptions_validate), 0x00000001, "Is this a request to validate a postdated ticket?", HFILL }},
+ { &hf_krb_pvno, {
+ "Pvno", "kerberos.pvno", FT_UINT32, BASE_DEC,
+ NULL, 0, "Kerberos Protocol Version Number", HFILL }},
+ { &hf_krb_kvno, {
+ "Kvno", "kerberos.kvno", FT_UINT32, BASE_DEC,
+ NULL, 0, "Version Number for the encryption Key", HFILL }},
+ { &hf_krb_checksum_type, {
+ "Type", "kerberos.checksum.type", FT_UINT32, BASE_DEC,
+ VALS(krb5_checksum_types), 0, "Type of checksum", HFILL }},
+ { &hf_krb_authenticator_vno, {
+ "Authenticator vno", "kerberos.authenticator_vno", FT_UINT32, BASE_DEC,
+ NULL, 0, "Version Number for the Authenticator", HFILL }},
+ { &hf_krb_encrypted_authenticator_data, {
+ "Authenticator data", "kerberos.authenticator.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Data content of an encrypted authenticator", HFILL }},
+ { &hf_krb_encrypted_PA_ENC_TIMESTAMP, {
+ "enc PA_ENC_TIMESTAMP", "kerberos.PA_ENC_TIMESTAMP.encrypted", FT_BYTES, BASE_HEX,
+ NULL, 0, "Encrypted PA-ENC-TIMESTAMP blob", HFILL }},
+ { &hf_krb_PAC_LOGON_INFO, {
+ "PAC_LOGON_INFO", "kerberos.PAC_LOGON_INFO", FT_BYTES, BASE_HEX,
+ NULL, 0, "PAC_LOGON_INFO structure", HFILL }},
+ { &hf_krb_PAC_CREDENTIAL_TYPE, {
+ "PAC_CREDENTIAL_TYPE", "kerberos.PAC_CREDENTIAL_TYPE", FT_BYTES, BASE_HEX,
+ NULL, 0, "PAC_CREDENTIAL_TYPE structure", HFILL }},
+ { &hf_krb_PAC_SERVER_CHECKSUM, {
+ "PAC_SERVER_CHECKSUM", "kerberos.PAC_SERVER_CHECKSUM", FT_BYTES, BASE_HEX,
+ NULL, 0, "PAC_SERVER_CHECKSUM structure", HFILL }},
+ { &hf_krb_PAC_PRIVSVR_CHECKSUM, {
+ "PAC_PRIVSVR_CHECKSUM", "kerberos.PAC_PRIVSVR_CHECKSUM", FT_BYTES, BASE_HEX,
+ NULL, 0, "PAC_PRIVSVR_CHECKSUM structure", HFILL }},
+ { &hf_krb_PAC_CLIENT_INFO_TYPE, {
+ "PAC_CLIENT_INFO_TYPE", "kerberos.PAC_CLIENT_INFO_TYPE", FT_BYTES, BASE_HEX,
+ NULL, 0, "PAC_CLIENT_INFO_TYPE structure", HFILL }},
+ { &hf_krb_checksum_checksum, {
+ "checksum", "kerberos.checksum.checksum", FT_BYTES, BASE_HEX,
+ NULL, 0, "Kerberos Checksum", HFILL }},
+ { &hf_krb_ENC_PRIV, {
+ "enc PRIV", "kerberos.ENC_PRIV", FT_BYTES, BASE_HEX,
+ NULL, 0, "Encrypted PRIV blob", HFILL }},
+ { &hf_krb_encrypted_Ticket_data, {
+ "enc-part", "kerberos.ticket.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "The encrypted part of a ticket", HFILL }},
+ { &hf_krb_encrypted_AP_REP_data, {
+ "enc-part", "kerberos.aprep.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "The encrypted part of AP-REP", HFILL }},
+ { &hf_krb_encrypted_KDC_REP_data, {
+ "enc-part", "kerberos.kdcrep.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "The encrypted part of KDC-REP", HFILL }},
+ { &hf_krb_PA_DATA_value, {
+ "Value", "kerberos.padata.value", FT_BYTES, BASE_HEX,
+ NULL, 0, "Content of the PADATA blob", HFILL }},
+ { &hf_krb_etype_info_salt, {
+ "Salt", "kerberos.etype_info.salt", FT_BYTES, BASE_HEX,
+ NULL, 0, "Salt", HFILL }},
+ { &hf_krb_SAFE_BODY_user_data, {
+ "User Data", "kerberos.SAFE_BODY.user_data", FT_BYTES, BASE_HEX,
+ NULL, 0, "SAFE BODY userdata field", HFILL }},
+ { &hf_krb_pac_signature_signature, {
+ "Signature", "kerberos.pac.signature.signature", FT_BYTES, BASE_HEX,
+ NULL, 0, "A PAC signature blob", HFILL }},
+ { &hf_krb_PA_DATA_type, {
+ "Type", "kerberos.padata.type", FT_UINT32, BASE_DEC,
+ VALS(krb5_preauthentication_types), 0, "Type of preauthentication data", HFILL }},
+ { &hf_krb_nonce, {
+ "Nonce", "kerberos.nonce", FT_UINT32, BASE_DEC,
+ NULL, 0, "Kerberos Nonce random number", HFILL }},
+ { &hf_krb_tkt_vno, {
+ "Tkt-vno", "kerberos.tkt_vno", FT_UINT32, BASE_DEC,
+ NULL, 0, "Version number for the Ticket format", HFILL }},
+ { &hf_krb_HostAddress, {
+ "HostAddress", "kerberos.hostaddress", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a Kerberos HostAddress sequence", HFILL }},
+ { &hf_krb_s_address, {
+ "S-Address", "kerberos.s_address", FT_NONE, BASE_DEC,
+ NULL, 0, "This is the Senders address", HFILL }},
+ { &hf_krb_signedAuthPack, {
+ "signedAuthPack", "kerberos.signedAuthPack", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a Kerberos ContentInfo sequence", HFILL }},
+ { &hf_krb_key, {
+ "key", "kerberos.key", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a Kerberos EncryptionKey sequence", HFILL }},
+ { &hf_krb_subkey, {
+ "Subkey", "kerberos.subkey", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a Kerberos subkey", HFILL }},
+ { &hf_krb_seq_number, {
+ "Seq Number", "kerberos.seq_number", FT_UINT32, BASE_DEC,
+ NULL, 0, "This is a Kerberos sequence number", HFILL }},
+ { &hf_krb_AuthorizationData, {
+ "AuthorizationData", "kerberos.AuthorizationData", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a Kerberos AuthorizationData sequence", HFILL }},
+ { &hf_krb_EncTicketPart, {
+ "EncTicketPart", "kerberos.EncTicketPart", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a decrypted Kerberos EncTicketPart sequence", HFILL }},
+ { &hf_krb_EncAPRepPart, {
+ "EncAPRepPart", "kerberos.EncAPRepPart", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a decrypted Kerberos EncAPRepPart sequence", HFILL }},
+ { &hf_krb_EncKDCRepPart, {
+ "EncKDCRepPart", "kerberos.EncKDCRepPart", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a decrypted Kerberos EncKDCRepPart sequence", HFILL }},
+ { &hf_krb_LastReq, {
+ "LastReq", "kerberos.LastReq", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a LastReq sequence", HFILL }},
+ { &hf_krb_Authenticator, {
+ "Authenticator", "kerberos.Authenticator", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a decrypted Kerberos Authenticator sequence", HFILL }},
+ { &hf_krb_Checksum, {
+ "Checksum", "kerberos.Checksum", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a Kerberos Checksum sequence", HFILL }},
+ { &hf_krb_HostAddresses, {
+ "HostAddresses", "kerberos.hostaddresses", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a list of Kerberos HostAddress sequences", HFILL }},
+ { &hf_krb_IF_RELEVANT, {
+ "IF_RELEVANT", "kerberos.if_relevant", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a list of IF-RELEVANT sequences", HFILL }},
+ { &hf_krb_etypes, {
+ "Encryption Types", "kerberos.etypes", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a list of Kerberos encryption types", HFILL }},
+ { &hf_krb_LastReqs, {
+ "LastReqs", "kerberos.LastReqs", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a list of LastReq structures", HFILL }},
+ { &hf_krb_sname, {
+ "Server Name", "kerberos.sname", FT_NONE, BASE_DEC,
+ NULL, 0, "This is the name part server's identity", HFILL }},
+ { &hf_krb_cname, {
+ "Client Name", "kerberos.cname", FT_NONE, BASE_DEC,
+ NULL, 0, "The name part of the client principal identifier", HFILL }},
+ { &hf_krb_authenticator_enc, {
+ "Authenticator", "kerberos.authenticator", FT_NONE, BASE_DEC,
+ NULL, 0, "Encrypted authenticator blob", HFILL }},
+ { &hf_krb_ticket_enc, {
+ "enc-part", "kerberos.ticket.enc_part", FT_NONE, BASE_DEC,
+ NULL, 0, "The structure holding the encrypted part of a ticket", HFILL }},
+ { &hf_krb_AP_REP_enc, {
+ "enc-part", "kerberos.aprep.enc_part", FT_NONE, BASE_DEC,
+ NULL, 0, "The structure holding the encrypted part of AP-REP", HFILL }},
+ { &hf_krb_KDC_REP_enc, {
+ "enc-part", "kerberos.kdcrep.enc_part", FT_NONE, BASE_DEC,
+ NULL, 0, "The structure holding the encrypted part of KDC-REP", HFILL }},
+ { &hf_krb_e_data, {
+ "e-data", "kerberos.e_data", FT_NONE, BASE_DEC,
+ NULL, 0, "The e-data blob", HFILL }},
+ { &hf_krb_padata, {
+ "padata", "kerberos.padata", FT_NONE, BASE_DEC,
+ NULL, 0, "Sequence of preauthentication data", HFILL }},
+ { &hf_krb_ticket, {
+ "Ticket", "kerberos.ticket", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a Kerberos Ticket", HFILL }},
+ { &hf_krb_TransitedEncoding, {
+ "TransitedEncoding", "kerberos.TransitedEncoding", FT_NONE, BASE_DEC,
+ NULL, 0, "This is a Kerberos TransitedEncoding sequence", HFILL }},
+ { &hf_krb_PA_PAC_REQUEST_flag, {
+ "PAC Request", "kerberos.pac_request.flag", FT_UINT32, BASE_DEC,
+ NULL, 0, "This is a MS PAC Request Flag", HFILL }},
+ { &hf_krb_w2k_pac_entries, {
+ "Num Entries", "kerberos.pac.entries", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of W2k PAC entries", HFILL }},
+ { &hf_krb_w2k_pac_version, {
+ "Version", "kerberos.pac.version", FT_UINT32, BASE_DEC,
+ NULL, 0, "Version of PAC structures", HFILL }},
+ { &hf_krb_w2k_pac_type, {
+ "Type", "kerberos.pac.type", FT_UINT32, BASE_DEC,
+ VALS(w2k_pac_types), 0, "Type of W2k PAC entry", HFILL }},
+ { &hf_krb_w2k_pac_size, {
+ "Size", "kerberos.pac.size", FT_UINT32, BASE_DEC,
+ NULL, 0, "Size of W2k PAC entry", HFILL }},
+ { &hf_krb_w2k_pac_offset, {
+ "Offset", "kerberos.pac.offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Offset to W2k PAC entry", HFILL }},
+ { &hf_krb_pac_clientid, {
+ "ClientID", "kerberos.pac.clientid", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "ClientID Timestamp", HFILL }},
+ { &hf_krb_pac_namelen, {
+ "Name Length", "kerberos.pac.namelen", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of client name", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_krb_kerberos,
+ &ett_krb_KDC_REP_enc,
+ &ett_krb_sname,
+ &ett_krb_cname,
+ &ett_krb_AP_REP_enc,
+ &ett_krb_padata,
+ &ett_krb_etypes,
+ &ett_krb_LastReqs,
+ &ett_krb_IF_RELEVANT,
+ &ett_krb_PA_DATA_tree,
+ &ett_krb_s_address,
+ &ett_krb_HostAddress,
+ &ett_krb_HostAddresses,
+ &ett_krb_authenticator_enc,
+ &ett_krb_AP_Options,
+ &ett_krb_KDC_Options,
+ &ett_krb_Ticket_Flags,
+ &ett_krb_request,
+ &ett_krb_recordmark,
+ &ett_krb_ticket,
+ &ett_krb_ticket_enc,
+ &ett_krb_PRIV,
+ &ett_krb_PRIV_enc,
+ &ett_krb_EncTicketPart,
+ &ett_krb_EncAPRepPart,
+ &ett_krb_EncKDCRepPart,
+ &ett_krb_LastReq,
+ &ett_krb_Authenticator,
+ &ett_krb_Checksum,
+ &ett_krb_key,
+ &ett_krb_subkey,
+ &ett_krb_AuthorizationData,
+ &ett_krb_TransitedEncoding,
+ &ett_krb_PAC,
+ &ett_krb_PAC_LOGON_INFO,
+ &ett_krb_PAC_CREDENTIAL_TYPE,
+ &ett_krb_PAC_SERVER_CHECKSUM,
+ &ett_krb_PAC_PRIVSVR_CHECKSUM,
+ &ett_krb_PAC_CLIENT_INFO_TYPE,
+ &ett_krb_signedAuthPack,
+ };
+ module_t *krb_module;
+
+ proto_kerberos = proto_register_protocol("Kerberos", "KRB5", "kerberos");
+ proto_register_field_array(proto_kerberos, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register preferences */
+ krb_module = prefs_register_protocol(proto_kerberos, NULL);
+ prefs_register_bool_preference(krb_module, "desegment",
+ "Desegment Kerberos over TCP messages",
+ "Whether the dissector should desegment "
+ "multi-segment Kerberos messages", &krb_desegment);
+#ifdef HAVE_KERBEROS
+ prefs_register_bool_preference(krb_module, "decrypt",
+ "Try to decrypt Kerberos blobs",
+ "Whether the dissector should try to decrypt "
+ "encrypted Kerberos blobs. This requires that the proper "
+ "keytab file is installed as well.", &krb_decrypt);
+
+ prefs_register_string_preference(krb_module, "file",
+ "Kerberos keytab file",
+ "The keytab file containing all the secrets",
+ &keytab_filename);
+#endif
+}
+
+static int wrap_dissect_gss_kerb(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ tvbuff_t *auth_tvb;
+
+ auth_tvb = tvb_new_subset(
+ tvb, offset, tvb_length_remaining(tvb, offset),
+ tvb_length_remaining(tvb, offset));
+
+ dissect_kerberos_main(auth_tvb, pinfo, tree, FALSE, NULL);
+
+ return tvb_length_remaining(tvb, offset);
+}
+
+
+static dcerpc_auth_subdissector_fns gss_kerb_auth_fns = {
+ wrap_dissect_gss_kerb, /* Bind */
+ wrap_dissect_gss_kerb, /* Bind ACK */
+ NULL, /* AUTH3 */
+ wrap_dissect_gssapi_verf, /* Request verifier */
+ wrap_dissect_gssapi_verf, /* Response verifier */
+ NULL, /* Request data */
+ NULL /* Response data */
+};
+
+
+void
+proto_reg_handoff_kerberos(void)
+{
+ dissector_handle_t kerberos_handle_udp;
+ dissector_handle_t kerberos_handle_tcp;
+
+ kerberos_handle_udp = create_dissector_handle(dissect_kerberos_udp,
+ proto_kerberos);
+ kerberos_handle_tcp = create_dissector_handle(dissect_kerberos_tcp,
+ proto_kerberos);
+ dissector_add("udp.port", UDP_PORT_KERBEROS, kerberos_handle_udp);
+ dissector_add("tcp.port", TCP_PORT_KERBEROS, kerberos_handle_tcp);
+
+ register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
+ DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
+ &gss_kerb_auth_fns);
+
+}
+
+/*
+
+ MISC definitions from RFC1510:
+
+ Realm ::= GeneralString
+
+ KerberosTime ::= GeneralizedTime
+
+ AuthorizationData ::= SEQUENCE OF SEQUENCE {
+ ad-type[0] INTEGER,
+ ad-data[1] OCTET STRING
+ }
+ APOptions ::= BIT STRING {
+ reserved(0),
+ use-session-key(1),
+ mutual-required(2)
+ }
+
+
+ TicketFlags ::= BIT STRING {
+ reserved(0),
+ forwardable(1),
+ forwarded(2),
+ proxiable(3),
+ proxy(4),
+ may-postdate(5),
+ postdated(6),
+ invalid(7),
+ renewable(8),
+ initial(9),
+ pre-authent(10),
+ hw-authent(11)
+ }
+
+ KDCOptions ::= BIT STRING {
+ reserved(0),
+ forwardable(1),
+ forwarded(2),
+ proxiable(3),
+ proxy(4),
+ allow-postdate(5),
+ postdated(6),
+ unused7(7),
+ renewable(8),
+ unused9(9),
+ unused10(10),
+ unused11(11),
+ renewable-ok(27),
+ enc-tkt-in-skey(28),
+ renew(30),
+ validate(31)
+ }
+
+
+ LastReq ::= SEQUENCE OF SEQUENCE {
+ lr-type[0] INTEGER,
+ lr-value[1] KerberosTime
+ }
+
+ Ticket ::= [APPLICATION 1] SEQUENCE {
+ tkt-vno[0] INTEGER,
+ realm[1] Realm,
+ sname[2] PrincipalName,
+ enc-part[3] EncryptedData
+ }
+
+ -- Encrypted part of ticket
+ EncTicketPart ::= [APPLICATION 3] SEQUENCE {
+ flags[0] TicketFlags,
+ key[1] EncryptionKey,
+ crealm[2] Realm,
+ cname[3] PrincipalName,
+ transited[4] TransitedEncoding,
+ authtime[5] KerberosTime,
+ starttime[6] KerberosTime OPTIONAL,
+ endtime[7] KerberosTime,
+ renew-till[8] KerberosTime OPTIONAL,
+ caddr[9] HostAddresses OPTIONAL,
+ authorization-data[10] AuthorizationData OPTIONAL
+ }
+
+ -- encoded Transited field
+ TransitedEncoding ::= SEQUENCE {
+ tr-type[0] INTEGER, -- must be registered
+ contents[1] OCTET STRING
+ }
+
+ -- Unencrypted authenticator
+ Authenticator ::= [APPLICATION 2] SEQUENCE {
+ authenticator-vno[0] INTEGER,
+ crealm[1] Realm,
+ cname[2] PrincipalName,
+ cksum[3] Checksum OPTIONAL,
+ cusec[4] INTEGER,
+ ctime[5] KerberosTime,
+ subkey[6] EncryptionKey OPTIONAL,
+ seq-number[7] INTEGER OPTIONAL,
+ authorization-data[8] AuthorizationData OPTIONAL
+ }
+
+ PA-DATA ::= SEQUENCE {
+ padata-type[1] INTEGER,
+ padata-value[2] OCTET STRING,
+ -- might be encoded AP-REQ
+ }
+
+ padata-type ::= PA-ENC-TIMESTAMP
+ padata-value ::= EncryptedData -- PA-ENC-TS-ENC
+
+ PA-ENC-TS-ENC ::= SEQUENCE {
+ patimestamp[0] KerberosTime, -- client's time
+ pausec[1] INTEGER OPTIONAL
+ }
+
+ EncASRepPart ::= [APPLICATION 25[25]] EncKDCRepPart
+ EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart
+
+ EncKDCRepPart ::= SEQUENCE {
+ key[0] EncryptionKey,
+ last-req[1] LastReq,
+ nonce[2] INTEGER,
+ key-expiration[3] KerberosTime OPTIONAL,
+ flags[4] TicketFlags,
+ authtime[5] KerberosTime,
+ starttime[6] KerberosTime OPTIONAL,
+ endtime[7] KerberosTime,
+ renew-till[8] KerberosTime OPTIONAL,
+ srealm[9] Realm,
+ sname[10] PrincipalName,
+ caddr[11] HostAddresses OPTIONAL
+ }
+
+ APOptions ::= BIT STRING {
+ reserved(0),
+ use-session-key(1),
+ mutual-required(2)
+ }
+
+ EncAPRepPart ::= [APPLICATION 27] SEQUENCE {
+ ctime[0] KerberosTime,
+ cusec[1] INTEGER,
+ subkey[2] EncryptionKey OPTIONAL,
+ seq-number[3] INTEGER OPTIONAL
+ }
+
+ KRB-SAFE ::= [APPLICATION 20] SEQUENCE {
+ pvno[0] INTEGER,
+ msg-type[1] INTEGER,
+ safe-body[2] KRB-SAFE-BODY,
+ cksum[3] Checksum
+ }
+
+ KRB-SAFE-BODY ::= SEQUENCE {
+ user-data[0] OCTET STRING,
+ timestamp[1] KerberosTime OPTIONAL,
+ usec[2] INTEGER OPTIONAL,
+ seq-number[3] INTEGER OPTIONAL,
+ s-address[4] HostAddress,
+ r-address[5] HostAddress OPTIONAL
+ }
+
+ KRB-PRIV ::= [APPLICATION 21] SEQUENCE {
+ pvno[0] INTEGER,
+ msg-type[1] INTEGER,
+ enc-part[3] EncryptedData
+ }
+
+ EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE {
+ user-data[0] OCTET STRING,
+ timestamp[1] KerberosTime OPTIONAL,
+ usec[2] INTEGER OPTIONAL,
+ seq-number[3] INTEGER OPTIONAL,
+ s-address[4] HostAddress, -- sender's addr
+ r-address[5] HostAddress OPTIONAL
+ -- recip's addr
+ }
+
+ KRB-CRED ::= [APPLICATION 22] SEQUENCE {
+ pvno[0] INTEGER,
+ msg-type[1] INTEGER, -- KRB_CRED
+ tickets[2] SEQUENCE OF Ticket,
+ enc-part[3] EncryptedData
+ }
+
+ EncKrbCredPart ::= [APPLICATION 29] SEQUENCE {
+ ticket-info[0] SEQUENCE OF KrbCredInfo,
+ nonce[1] INTEGER OPTIONAL,
+ timestamp[2] KerberosTime OPTIONAL,
+ usec[3] INTEGER OPTIONAL,
+ s-address[4] HostAddress OPTIONAL,
+ r-address[5] HostAddress OPTIONAL
+ }
+
+ KrbCredInfo ::= SEQUENCE {
+ key[0] EncryptionKey,
+ prealm[1] Realm OPTIONAL,
+ pname[2] PrincipalName OPTIONAL,
+ flags[3] TicketFlags OPTIONAL,
+ authtime[4] KerberosTime OPTIONAL,
+ starttime[5] KerberosTime OPTIONAL,
+ endtime[6] KerberosTime OPTIONAL
+ renew-till[7] KerberosTime OPTIONAL,
+ srealm[8] Realm OPTIONAL,
+ sname[9] PrincipalName OPTIONAL,
+ caddr[10] HostAddresses OPTIONAL
+ }
+
+ METHOD-DATA ::= SEQUENCE of PA-DATA
+
+ If the error-code is KRB_AP_ERR_METHOD, then the e-data field will
+ contain an encoding of the following sequence:
+
+ METHOD-DATA ::= SEQUENCE {
+ method-type[0] INTEGER,
+ method-data[1] OCTET STRING OPTIONAL
+ }
+
+ EncryptionKey ::= SEQUENCE {
+ keytype[0] INTEGER,
+ keyvalue[1] OCTET STRING
+ }
+
+ Checksum ::= SEQUENCE {
+ cksumtype[0] INTEGER,
+ checksum[1] OCTET STRING
+ }
+
+*/
+
diff --git a/epan/dissectors/packet-kerberos.h b/epan/dissectors/packet-kerberos.h
new file mode 100644
index 0000000000..9e915e5618
--- /dev/null
+++ b/epan/dissectors/packet-kerberos.h
@@ -0,0 +1,46 @@
+/* packet-kerberos.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_KERBEROS_H
+#define __PACKET_KERBEROS_H
+
+/* This is a list of callback functions a caller can use to specify that
+ octet strings in kerberos to be passed back to application specific
+ dissectors, outside of kerberos.
+ This is used for dissection of application specific data for PacketCable
+ KRB_SAFE user data and eventually to pass kerberos session keys
+ to future DCERPC decryption and other uses.
+ The list is terminated by {0, NULL }
+*/
+#define KRB_CBTAG_SAFE_USER_DATA 1
+typedef struct _kerberos_callbacks {
+ int tag;
+ int (*callback)(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree);
+} kerberos_callbacks;
+
+/* Function prototypes */
+
+gint
+dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int do_col_info, kerberos_callbacks *cb);
+
+#endif /* __PACKET_KERBEROS_H */
diff --git a/epan/dissectors/packet-klm.c b/epan/dissectors/packet-klm.c
new file mode 100644
index 0000000000..c8e455f4a2
--- /dev/null
+++ b/epan/dissectors/packet-klm.c
@@ -0,0 +1,267 @@
+/* packet-klm.c 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Routines for klm dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-nfs.h"
+#include "packet-klm.h"
+
+static int proto_klm = -1;
+static int hf_klm_procedure_v1 = -1;
+static int hf_klm_exclusive = -1;
+static int hf_klm_lock = -1;
+static int hf_klm_servername = -1;
+static int hf_klm_pid = -1;
+static int hf_klm_offset = -1;
+static int hf_klm_len = -1;
+static int hf_klm_stats = -1;
+static int hf_klm_holder = -1;
+static int hf_klm_block = -1;
+
+static gint ett_klm = -1;
+static gint ett_klm_lock = -1;
+static gint ett_klm_holder = -1;
+
+static const value_string names_klm_stats[] =
+{
+#define KLM_GRANTED 0
+ { KLM_GRANTED, "KLM_GRANTED" },
+#define KLM_DENIED 1
+ { KLM_DENIED, "KLM_DENIED" },
+#define KLM_DENIED_NOLOCKS 2
+ { KLM_DENIED_NOLOCKS, "KLM_DENIED_NOLOCKS" },
+#define KLM_WORKING 3
+ { KLM_WORKING, "KLM_WORKING" },
+ { 0, NULL }
+};
+
+static int
+dissect_holder(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+
+ lock_item = proto_tree_add_item(tree, hf_klm_holder, tvb,
+ offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_klm_holder);
+
+ offset = dissect_rpc_bool( tvb, lock_tree,
+ hf_klm_exclusive, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_klm_pid, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_klm_offset, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_klm_len, offset);
+
+ return offset;
+}
+
+static int
+dissect_lock(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+
+ lock_item = proto_tree_add_item(tree, hf_klm_lock, tvb,
+ offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_klm_lock);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_klm_servername, offset, NULL);
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, lock_tree,"fh", NULL);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_klm_pid, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_klm_offset, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_klm_len, offset);
+
+ return offset;
+}
+
+static int
+dissect_klm_unlock_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_lock(tvb, pinfo, tree, offset);
+
+ return offset;
+}
+
+static int
+dissect_klm_stat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_klm_stats, offset);
+
+ return offset;
+}
+
+static int
+dissect_klm_lock_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_bool( tvb, tree,
+ hf_klm_block, offset);
+
+ offset = dissect_rpc_bool( tvb, tree,
+ hf_klm_exclusive, offset);
+
+ offset = dissect_lock(tvb, pinfo, tree, offset);
+
+ return offset;
+}
+
+static int
+dissect_klm_test_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ gint32 stats;
+
+ stats = tvb_get_ntohl(tvb, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_klm_stats, offset);
+
+ if (stats == KLM_DENIED) {
+ offset = dissect_holder(tvb, tree, offset);
+ }
+
+ return offset;
+}
+
+static int
+dissect_klm_test_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_bool( tvb, tree,
+ hf_klm_exclusive, offset);
+
+ offset = dissect_lock(tvb, pinfo, tree, offset);
+
+ return offset;
+}
+
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff klm1_proc[] = {
+ { KLMPROC_TEST, "TEST",
+ dissect_klm_test_call, dissect_klm_test_reply },
+ { KLMPROC_LOCK, "LOCK",
+ dissect_klm_lock_call, dissect_klm_stat_reply },
+ { KLMPROC_CANCEL, "CANCEL",
+ dissect_klm_lock_call, dissect_klm_stat_reply },
+ { KLMPROC_UNLOCK, "UNLOCK",
+ dissect_klm_unlock_call, dissect_klm_stat_reply },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string klm1_proc_vals[] = {
+ { KLMPROC_TEST, "TEST" },
+ { KLMPROC_LOCK, "LOCK" },
+ { KLMPROC_CANCEL, "CANCEL" },
+ { KLMPROC_UNLOCK, "UNLOCK" },
+ { 0, NULL}
+};
+
+void
+proto_register_klm(void)
+{
+ static struct true_false_string tfs_exclusive = { "Exclusive", "Not exclusive" };
+ static struct true_false_string tfs_block = { "Block", "Do not block" };
+
+ static hf_register_info hf[] = {
+ { &hf_klm_procedure_v1, {
+ "V1 Procedure", "klm.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(klm1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_klm_exclusive, {
+ "exclusive", "klm.exclusive", FT_BOOLEAN, BASE_NONE,
+ &tfs_exclusive, 0, "Exclusive lock", HFILL }},
+
+ { &hf_klm_lock, {
+ "lock", "klm.lock", FT_NONE, BASE_NONE,
+ NULL, 0, "KLM lock structure", HFILL }},
+
+ { &hf_klm_servername, {
+ "server name", "klm.servername", FT_STRING, BASE_NONE,
+ NULL, 0, "Server name", HFILL }},
+
+ { &hf_klm_pid, {
+ "pid", "klm.pid", FT_UINT32, BASE_DEC,
+ NULL, 0, "ProcessID", HFILL }},
+
+ { &hf_klm_offset, {
+ "offset", "klm.offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "File offset", HFILL }},
+
+ { &hf_klm_len, {
+ "length", "klm.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of lock region", HFILL }},
+
+ { &hf_klm_stats, {
+ "stats", "klm.stats", FT_UINT32, BASE_DEC,
+ VALS(names_klm_stats), 0, "stats", HFILL }},
+
+ { &hf_klm_holder, {
+ "holder", "klm.holder", FT_NONE, BASE_NONE,
+ NULL, 0, "KLM lock holder", HFILL }},
+
+ { &hf_klm_block, {
+ "block", "klm.block", FT_BOOLEAN, BASE_NONE,
+ &tfs_block, 0, "Block", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_klm,
+ &ett_klm_lock,
+ &ett_klm_holder,
+ };
+
+ proto_klm = proto_register_protocol("Kernel Lock Manager",
+ "KLM", "klm");
+ proto_register_field_array(proto_klm, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_klm(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_klm, KLM_PROGRAM, ett_klm);
+ /* Register the procedure tables */
+ rpc_init_proc_table(KLM_PROGRAM, 1, klm1_proc, hf_klm_procedure_v1);
+}
diff --git a/epan/dissectors/packet-klm.h b/epan/dissectors/packet-klm.h
new file mode 100644
index 0000000000..03ba46fc86
--- /dev/null
+++ b/epan/dissectors/packet-klm.h
@@ -0,0 +1,34 @@
+/* packet-klm.h 2001 Ronnie Sahlberg <See AUTHORS for email>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_KLM_H
+#define PACKET_KLM_H
+
+#define KLMPROC_TEST 1
+#define KLMPROC_LOCK 2
+#define KLMPROC_CANCEL 3
+#define KLMPROC_UNLOCK 4
+
+#define KLM_PROGRAM 100020
+
+#endif
diff --git a/epan/dissectors/packet-kpasswd.c b/epan/dissectors/packet-kpasswd.c
new file mode 100644
index 0000000000..efd396bca8
--- /dev/null
+++ b/epan/dissectors/packet-kpasswd.c
@@ -0,0 +1,167 @@
+/* packet-kpasswd.c
+ * Routines for kpasswd packet dissection
+ * Ronnie Sahlberg 2003
+ *
+ * See RFC 3244
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include "packet-kerberos.h"
+#include "prefs.h"
+
+static int proto_kpasswd = -1;
+static int hf_kpasswd_message_len = -1;
+static int hf_kpasswd_version = -1;
+static int hf_kpasswd_ap_req_len = -1;
+static int hf_kpasswd_ap_req_data = -1;
+static int hf_kpasswd_krb_priv_message = -1;
+
+static gint ett_kpasswd = -1;
+static gint ett_ap_req_data = -1;
+static gint ett_krb_priv_message = -1;
+
+
+
+#define UDP_PORT_KPASSWD 464
+
+
+static const value_string vers_vals[] = {
+ { 0x0001, "Reply" },
+ { 0xff80, "Request" },
+ { 0, NULL },
+};
+
+
+static void
+dissect_kpasswd_ap_req_data(packet_info *pinfo _U_, tvbuff_t *tvb, proto_tree *parent_tree)
+{
+ proto_item *it;
+ proto_tree *tree=NULL;
+
+ if(parent_tree){
+ it=proto_tree_add_item(parent_tree, hf_kpasswd_ap_req_data, tvb, 0, -1, FALSE);
+ tree=proto_item_add_subtree(it, ett_ap_req_data);
+ }
+ dissect_kerberos_main(tvb, pinfo, tree, FALSE, NULL);
+}
+
+static void
+dissect_kpasswd_krb_priv_message(packet_info *pinfo _U_, tvbuff_t *tvb, proto_tree *parent_tree)
+{
+ proto_item *it;
+ proto_tree *tree=NULL;
+
+ if(parent_tree){
+ it=proto_tree_add_item(parent_tree, hf_kpasswd_krb_priv_message, tvb, 0, -1, FALSE);
+ tree=proto_item_add_subtree(it, ett_krb_priv_message);
+ }
+ dissect_kerberos_main(tvb, pinfo, tree, FALSE, NULL);
+}
+
+
+static void
+dissect_kpasswd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *kpasswd_item;
+ proto_tree *kpasswd_tree=NULL;
+ int offset = 0;
+ guint16 message_len, version, ap_req_len;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "KPASSWD");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ message_len=tvb_get_ntohs(tvb, offset);
+ version=tvb_get_ntohs(tvb, offset+2);
+ ap_req_len=tvb_get_ntohs(tvb, offset+4);
+ if(tree){
+ kpasswd_item=proto_tree_add_item(tree, proto_kpasswd, tvb, offset, message_len, FALSE);
+ kpasswd_tree=proto_item_add_subtree(kpasswd_item, ett_kpasswd);
+ }
+
+ proto_tree_add_uint(kpasswd_tree, hf_kpasswd_message_len, tvb, offset, 2, message_len);
+ proto_tree_add_uint(kpasswd_tree, hf_kpasswd_version, tvb, offset+2, 2, version);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str(version, vers_vals, "Unknown command"));
+ proto_tree_add_uint(kpasswd_tree, hf_kpasswd_ap_req_len, tvb, offset+4, 2, ap_req_len);
+ offset+=6;
+
+ /* AP_REQ data */
+ next_tvb=tvb_new_subset(tvb, offset, ap_req_len, ap_req_len);
+ dissect_kpasswd_ap_req_data(pinfo, next_tvb, kpasswd_tree);
+ offset+=ap_req_len;
+
+ /* KRB-PRIB message */
+ next_tvb=tvb_new_subset(tvb, offset, -1, -1);
+ dissect_kpasswd_krb_priv_message(pinfo, next_tvb, kpasswd_tree);
+
+}
+
+
+void
+proto_register_kpasswd(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_kpasswd_message_len,
+ { "Message Length", "kpasswd.message_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Message Length", HFILL }},
+ { &hf_kpasswd_ap_req_len,
+ { "AP_REQ Length", "kpasswd.ap_req_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of AP_REQ data", HFILL }},
+ { &hf_kpasswd_version,
+ { "Version", "kpasswd.version", FT_UINT16, BASE_HEX,
+ VALS(vers_vals), 0, "Version", HFILL }},
+ { &hf_kpasswd_ap_req_data,
+ { "AP_REQ", "kpasswd.ap_req", FT_NONE, BASE_NONE,
+ NULL, 0, "AP_REQ structure", HFILL }},
+ { &hf_kpasswd_krb_priv_message,
+ { "KRB-PRIV", "kpasswd.krb_priv", FT_NONE, BASE_NONE,
+ NULL, 0, "KRB-PRIV message", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_kpasswd,
+ &ett_ap_req_data,
+ &ett_krb_priv_message,
+ };
+
+ proto_kpasswd = proto_register_protocol("MS Kpasswd",
+ "Kpasswd", "kpasswd");
+ proto_register_field_array(proto_kpasswd, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_kpasswd(void)
+{
+ dissector_handle_t kpasswd_handle;
+
+ kpasswd_handle = create_dissector_handle(dissect_kpasswd, proto_kpasswd);
+ dissector_add("udp.port", UDP_PORT_KPASSWD, kpasswd_handle);
+}
diff --git a/epan/dissectors/packet-l2tp.c b/epan/dissectors/packet-l2tp.c
new file mode 100644
index 0000000000..719d8b32d3
--- /dev/null
+++ b/epan/dissectors/packet-l2tp.c
@@ -0,0 +1,1082 @@
+/* packet-l2tp.c
+ * Routines for Layer Two Tunnelling Protocol (L2TP) (RFC 2661) packet
+ * disassembly
+ * John Thomes <john@ensemblecom.com>
+ *
+ * Minor changes by: (2000-01-10)
+ * Laurent Cazalet <laurent.cazalet@mailclub.net>
+ * Thomas Parvais <thomas.parvais@advalvas.be>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+static int proto_l2tp = -1;
+static int hf_l2tp_type = -1;
+static int hf_l2tp_length_bit = -1;
+static int hf_l2tp_seq_bit = -1;
+static int hf_l2tp_offset_bit = -1;
+static int hf_l2tp_priority = -1;
+static int hf_l2tp_version = -1;
+static int hf_l2tp_length = -1;
+static int hf_l2tp_tunnel = -1;
+static int hf_l2tp_session = -1;
+static int hf_l2tp_Ns = -1;
+static int hf_l2tp_Nr = -1;
+static int hf_l2tp_offset = -1;
+static int hf_l2tp_avp_mandatory = -1;
+static int hf_l2tp_avp_hidden = -1;
+static int hf_l2tp_avp_length = -1;
+static int hf_l2tp_avp_vendor_id = -1;
+static int hf_l2tp_avp_type = -1;
+static int hf_l2tp_tie_breaker = -1;
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+
+#define UDP_PORT_L2TP 1701
+
+#define CONTROL_BIT(msg_info) (msg_info & 0x8000) /* Type bit control = 1 data = 0 */
+#define LENGTH_BIT(msg_info) (msg_info & 0x4000) /* Length bit = 1 */
+#define RESERVE_BITS(msg_info) (msg_info &0x37F8) /* Reserved bit - usused */
+#define SEQUENCE_BIT(msg_info) (msg_info & 0x0800) /* SEQUENCE bit = 1 Ns and Nr fields */
+#define OFFSET_BIT(msg_info) (msg_info & 0x0200) /* Offset */
+#define PRIORITY_BIT(msg_info) (msg_info & 0x0100) /* Priority */
+#define L2TP_VERSION(msg_info) (msg_info & 0x000f) /* Version of l2tp */
+#define MANDATORY_BIT(msg_info) (msg_info & 0x8000) /* Mandatory = 1 */
+#define HIDDEN_BIT(msg_info) (msg_info & 0x4000) /* Hidden = 1 */
+#define AVP_LENGTH(msg_info) (msg_info & 0x03ff) /* AVP Length */
+#define FRAMING_SYNC(msg_info) (msg_info & 0x0001) /* SYNC Framing Type */
+#define FRAMING_ASYNC(msg_info) (msg_info & 0x0002) /* ASYNC Framing Type */
+#define BEARER_DIGITAL(msg_info) (msg_info & 0x0001) /* Digital Bearer Type */
+#define BEARER_ANALOG(msg_info) (msg_info & 0x0002) /* Analog Bearer Type */
+
+static gint ett_l2tp = -1;
+static gint ett_l2tp_ctrl = -1;
+static gint ett_l2tp_avp = -1;
+static gint ett_l2tp_lcp = -1;
+
+#define AVP_SCCRQ 1
+#define AVP_SCCRP 2
+#define AVP_SCCCN 3
+#define AVP_StopCCN 4
+#define AVP_Reserved 5
+#define AVP_HELLO 6
+#define AVP_OCRQ 7
+#define AVP_OCRP 8
+#define AVP_ORCRP 9
+#define AVP_ICRQ 10
+#define AVP_ICRP 11
+#define AVP_ICCN 12
+#define AVP_Reserved1 13
+#define AVP_CDN 14
+
+
+#define NUM_CONTROL_CALL_TYPES 16
+static const char *calltypestr[NUM_CONTROL_CALL_TYPES+1] = {
+ "Unknown Call Type ",
+ "Start_Control_Request ",
+ "Start_Control_Reply ",
+ "Start_Control_Connected ",
+ "Stop_Control_Notification ",
+ "Reserved ",
+ "Hello ",
+ "Outgoing_Call_Request ",
+ "Outgoing_Call_Reply ",
+ "Outgoing_Call_Connected ",
+ "Incoming_Call_Request ",
+ "Incoming_Call_Reply ",
+ "Incoming_Call_Connected ",
+ "Reserved ",
+ "Call_Disconnect_Notification",
+ "WAN_Error_Notify ",
+ "Set_Link_Info ",
+};
+
+static const char *calltype_short_str[NUM_CONTROL_CALL_TYPES+1] = {
+ "Unknown ",
+ "SCCRQ ",
+ "SCCRP ",
+ "SCCCN ",
+ "StopCCN ",
+ "Reserved",
+ "Hello ",
+ "OCRQ ",
+ "OCRP ",
+ "OCCN ",
+ "ICRQ ",
+ "ICRP ",
+ "ICCN ",
+ "Reserved",
+ "CDN ",
+ "WEN ",
+ "SLI ",
+};
+
+
+static const char *control_msg = "Control Message";
+static const char *data_msg = "Data Message";
+static const value_string l2tp_type_vals[] = {
+ { 0, "Data Message" },
+ { 1, "Control Message" },
+ { 0, NULL },
+};
+
+static const value_string cause_code_direction_vals[] = {
+ { 0, "global error" },
+ { 1, "at peer" },
+ { 2, "at local" },
+ { 0, NULL },
+};
+
+static const true_false_string l2tp_length_bit_truth =
+ { "Length field is present", "Length field is not present" };
+
+static const true_false_string l2tp_seq_bit_truth =
+ { "Ns and Nr fields are present", "Ns and Nr fields are not present" };
+
+static const true_false_string l2tp_offset_bit_truth =
+ { "Offset Size field is present", "Offset size field is not present" };
+
+static const true_false_string l2tp_priority_truth =
+ { "This data message has priority", "No priority" };
+
+static const value_string authen_type_vals[] = {
+ { 0, "Reserved" },
+ { 1, "Textual username and password" },
+ { 2, "PPP CHAP" },
+ { 3, "PPP PAP" },
+ { 4, "No Authentication" },
+ { 5, "Microsoft CHAP Version 1" },
+ { 0, NULL }
+};
+
+#define CONTROL_MESSAGE 0
+#define RESULT_ERROR_CODE 1
+#define PROTOCOL_VERSION 2
+#define FRAMING_CAPABILITIES 3
+#define BEARER_CAPABILITIES 4
+#define TIE_BREAKER 5
+#define FIRMWARE_REVISION 6
+#define HOST_NAME 7
+#define VENDOR_NAME 8
+#define ASSIGNED_TUNNEL_ID 9
+#define RECEIVE_WINDOW_SIZE 10
+#define CHALLENGE 11
+#define CAUSE_CODE 12
+#define CHALLENGE_RESPONSE 13
+#define ASSIGNED_SESSION 14
+#define CALL_SERIAL_NUMBER 15
+#define MINIMUM_BPS 16
+#define MAXIMUM_BPS 17
+#define BEARER_TYPE 18
+#define FRAMING_TYPE 19
+#define CALLED_NUMBER 21
+#define CALLING_NUMBER 22
+#define SUB_ADDRESS 23
+#define TX_CONNECT_SPEED 24
+#define PHYSICAL_CHANNEL 25
+#define INITIAL_RECEIVED_LCP_CONFREQ 26
+#define LAST_SENT_LCP_CONFREQ 27
+#define LAST_RECEIVED_LCP_CONFREQ 28
+#define PROXY_AUTHEN_TYPE 29
+#define PROXY_AUTHEN_NAME 30
+#define PROXY_AUTHEN_CHALLENGE 31
+#define PROXY_AUTHEN_ID 32
+#define PROXY_AUTHEN_RESPONSE 33
+#define CALL_STATUS_AVPS 34
+#define ACCM 35
+#define RANDOM_VECTOR 36
+#define PRIVATE_GROUP_ID 37
+#define RX_CONNECT_SPEED 38
+#define SEQUENCING_REQUIRED 39
+#define PPP_DISCONNECT_CAUSE_CODE 46 /* RFC 3145 */
+
+#define NUM_AVP_TYPES 40
+static const value_string avp_type_vals[] = {
+ { CONTROL_MESSAGE, "Control Message" },
+ { RESULT_ERROR_CODE, "Result-Error Code" },
+ { PROTOCOL_VERSION, "Protocol Version" },
+ { FRAMING_CAPABILITIES, "Framing Capabilities" },
+ { BEARER_CAPABILITIES, "Bearer Capabilities" },
+ { TIE_BREAKER, "Tie Breaker" },
+ { FIRMWARE_REVISION, "Firmware Revision" },
+ { HOST_NAME, "Host Name" },
+ { VENDOR_NAME, "Vendor Name" },
+ { ASSIGNED_TUNNEL_ID, "Assigned Tunnel ID" },
+ { RECEIVE_WINDOW_SIZE, "Receive Window Size" },
+ { CHALLENGE, "Challenge" },
+ { CAUSE_CODE, "Cause Code" },
+ { CHALLENGE_RESPONSE, "Challenge Response" },
+ { ASSIGNED_SESSION, "Assigned Session" },
+ { CALL_SERIAL_NUMBER, "Call Serial Number" },
+ { MINIMUM_BPS, "Minimum BPS" },
+ { MAXIMUM_BPS, "Maximum BPS" },
+ { BEARER_TYPE, "Bearer Type" },
+ { FRAMING_TYPE, "Framing Type" },
+ { CALLED_NUMBER, "Called Number" },
+ { CALLING_NUMBER, "Calling Number" },
+ { SUB_ADDRESS, "Sub-Address" },
+ { TX_CONNECT_SPEED, "Connect Speed" },
+ { PHYSICAL_CHANNEL, "Physical Channel" },
+ { INITIAL_RECEIVED_LCP_CONFREQ, "Initial Received LCP CONFREQ" },
+ { LAST_SENT_LCP_CONFREQ, "Last Sent LCP CONFREQ" },
+ { LAST_RECEIVED_LCP_CONFREQ, "Last Received LCP CONFREQ" },
+ { PROXY_AUTHEN_TYPE, "Proxy Authen Type" },
+ { PROXY_AUTHEN_NAME, "Proxy Authen Name" },
+ { PROXY_AUTHEN_CHALLENGE, "Proxy Authen Challenge" },
+ { PROXY_AUTHEN_ID, "Proxy Authen ID" },
+ { PROXY_AUTHEN_RESPONSE, "Proxy Authen Response" },
+ { CALL_STATUS_AVPS, "Call status AVPs" },
+ { ACCM, "ACCM" },
+ { RANDOM_VECTOR, "Random Vector" },
+ { PRIVATE_GROUP_ID, "Private group ID" },
+ { RX_CONNECT_SPEED, "RxConnect Speed" },
+ { SEQUENCING_REQUIRED, "Sequencing Required" },
+ { PPP_DISCONNECT_CAUSE_CODE, "PPP Disconnect Cause Code" },
+ { 0, NULL }
+};
+
+/*
+ * These are SMI Network Management Private Enterprise Codes for
+ * organizations; see
+ *
+ * http://www.iana.org/assignments/enterprise-numbers
+ *
+ * for a list.
+ */
+#define VENDOR_IETF 0
+#define VENDOR_ACC 5
+#define VENDOR_CISCO 9
+#define VENDOR_SHIVA 166
+#define VENDOR_LIVINGSTON 307
+#define VENDOR_3COM 429
+#define VENDOR_ASCEND 529
+#define VENDOR_BAY 1584
+#define VENDOR_REDBACK 2352
+#define VENDOR_JUNIPER 2636
+#define VENDOR_COSINE 3085
+#define VENDOR_UNISPHERE 4874
+
+static const value_string avp_vendor_id_vals[] =
+{{VENDOR_IETF,"IETF"},
+{VENDOR_ACC,"ACC"},
+{VENDOR_CISCO,"Cisco"},
+{VENDOR_SHIVA,"Shiva"},
+{VENDOR_LIVINGSTON,"Livingston"},
+{VENDOR_3COM,"3Com"},
+{VENDOR_ASCEND,"Ascend"},
+{VENDOR_BAY,"Bay Networks"},
+{VENDOR_REDBACK,"Redback"},
+{VENDOR_JUNIPER,"Juniper Networks"},
+{VENDOR_COSINE,"CoSine Communications"},
+{VENDOR_UNISPHERE,"Unisphere Networks"},
+{0,NULL}};
+
+static gchar textbuffer[200];
+
+static dissector_handle_t ppp_hdlc_handle;
+static dissector_handle_t ppp_lcp_options_handle;
+
+static void
+dissect_l2tp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *l2tp_tree=NULL, *l2tp_avp_tree, *l2tp_lcp_avp_tree, *ctrl_tree;
+ proto_item *l2tp_item = NULL, *ti, *tf, *te;
+ int rhcode;
+ int index = 0;
+ int tmp_index;
+ guint16 length = 0; /* Length field */
+ guint16 tid; /* Tunnel ID */
+ guint16 cid; /* Call ID */
+ guint16 offset_size; /* Offset size */
+ guint16 ver_len_hidden;
+ guint16 avp_vendor_id;
+ guint16 avp_type;
+ guint16 msg_type;
+ guint16 avp_len;
+ guint16 result_code;
+ guint16 error_code;
+ guint32 bits;
+ guint16 firmware_rev;
+ guint16 control;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) /* build output for closed L2tp frame displayed */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "L2TP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ control = tvb_get_ntohs(tvb, 0);
+
+ if (L2TP_VERSION(control) != 2) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "L2TP Version %u", L2TP_VERSION(control) );
+ }
+ return;
+ }
+
+ rhcode= 10;
+
+ if (LENGTH_BIT(control)) { /* length field included ? */
+ index += 2; /* skip ahead */
+ length = tvb_get_ntohs(tvb, index);
+ }
+
+ /* collect the tunnel id & call id */
+ index += 2;
+ tid = tvb_get_ntohs(tvb, index);
+ index += 2;
+ cid = tvb_get_ntohs(tvb, index);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (CONTROL_BIT(control)) {
+ /* CONTROL MESSAGE */
+ tmp_index = index;
+
+ if ((LENGTH_BIT(control))&&(length==12)) /* ZLB Message */
+ sprintf(textbuffer,"%s - ZLB (tunnel id=%d, session id=%d)",
+ control_msg , tid ,cid);
+ else
+ {
+ if (SEQUENCE_BIT(control)) {
+ tmp_index += 4;
+ }
+
+ tmp_index+=4;
+
+ avp_type = tvb_get_ntohs(tvb, (tmp_index+=2));
+
+ if (avp_type == CONTROL_MESSAGE)
+ {
+ /* We print message type */
+ msg_type = tvb_get_ntohs(tvb, (tmp_index+=2));
+ sprintf(textbuffer,"%s - %s (tunnel id=%d, session id=%d)",
+ control_msg ,
+ ((NUM_CONTROL_CALL_TYPES + 1 ) > msg_type) ?
+ calltype_short_str[msg_type] : "Unknown",
+ tid ,cid);
+ }
+ else
+ {
+ /*
+ * This is not a control message.
+ * We never pass here except in case of bad l2tp packet!
+ */
+ sprintf(textbuffer,"%s (tunnel id=%d, session id=%d)",
+ control_msg , tid ,cid);
+
+ }
+ }
+ }
+ else {
+ /* DATA Message */
+ sprintf(textbuffer,"%s (tunnel id=%d, session id=%d)",
+ data_msg, tid ,cid);
+ }
+ col_add_fstr(pinfo->cinfo,COL_INFO,textbuffer);
+ }
+
+ if (LENGTH_BIT(control)) {
+ /*
+ * Set the length of this tvbuff to be no longer than the length
+ * in the header.
+ *
+ * XXX - complain if that length is longer than the length of
+ * the tvbuff? Have "set_actual_length()" return a Boolean
+ * and have its callers check the result?
+ */
+ set_actual_length(tvb, length);
+ }
+
+ if (tree) {
+ l2tp_item = proto_tree_add_item(tree,proto_l2tp, tvb, 0, -1, FALSE);
+ l2tp_tree = proto_item_add_subtree(l2tp_item, ett_l2tp);
+
+ ti = proto_tree_add_text(l2tp_tree, tvb, 0, 2,
+ "Packet Type: %s Tunnel Id=%d Session Id=%d",
+ (CONTROL_BIT(control) ? control_msg : data_msg), tid, cid);
+
+ ctrl_tree = proto_item_add_subtree(ti, ett_l2tp_ctrl);
+ proto_tree_add_uint(ctrl_tree, hf_l2tp_type, tvb, 0, 2, control);
+ proto_tree_add_boolean(ctrl_tree, hf_l2tp_length_bit, tvb, 0, 2, control);
+ proto_tree_add_boolean(ctrl_tree, hf_l2tp_seq_bit, tvb, 0, 2, control);
+ proto_tree_add_boolean(ctrl_tree, hf_l2tp_offset_bit, tvb, 0, 2, control);
+ proto_tree_add_boolean(ctrl_tree, hf_l2tp_priority, tvb, 0, 2, control);
+ proto_tree_add_uint(ctrl_tree, hf_l2tp_version, tvb, 0, 2, control);
+ }
+ index = 2;
+ if (LENGTH_BIT(control)) {
+ if (tree) {
+ proto_tree_add_item(l2tp_tree, hf_l2tp_length, tvb, index, 2, FALSE);
+ }
+ index += 2;
+ }
+
+ if (tree) {
+ proto_tree_add_item(l2tp_tree, hf_l2tp_tunnel, tvb, index, 2, FALSE);
+ }
+ index += 2;
+ if (tree) {
+ proto_tree_add_item(l2tp_tree, hf_l2tp_session, tvb, index, 2, FALSE);
+ }
+ index += 2;
+
+ if (SEQUENCE_BIT(control)) {
+ if (tree) {
+ proto_tree_add_item(l2tp_tree, hf_l2tp_Ns, tvb, index, 2, FALSE);
+ }
+ index += 2;
+ if (tree) {
+ proto_tree_add_item(l2tp_tree, hf_l2tp_Nr, tvb, index, 2, FALSE);
+ }
+ index += 2;
+ }
+ if (OFFSET_BIT(control)) {
+ offset_size = tvb_get_ntohs(tvb, index);
+ if (tree) {
+ proto_tree_add_uint(l2tp_tree, hf_l2tp_offset, tvb, index, 2,
+ offset_size);
+ }
+ index += 2;
+ if (offset_size != 0) {
+ if (tree) {
+ proto_tree_add_text(l2tp_tree, tvb, index, offset_size, "Offset Padding");
+ }
+ index += offset_size;
+ }
+ }
+ if (tree && (LENGTH_BIT(control))&&(length==12)) {
+ proto_tree_add_text(l2tp_tree, tvb, 0, 0, "Zero Length Bit message");
+ }
+
+ if (!CONTROL_BIT(control)) { /* Data Messages so we are done */
+ if (tree)
+ proto_item_set_len(l2tp_item, index);
+ /* If we have data, signified by having a length bit, dissect it */
+ if (tvb_offset_exists(tvb, index)) {
+ next_tvb = tvb_new_subset(tvb, index, -1, -1);
+ call_dissector(ppp_hdlc_handle, next_tvb, pinfo, tree);
+ }
+ return;
+ }
+
+ if (tree) {
+ if (!LENGTH_BIT(control)) {
+ return;
+ }
+ while (index < length ) { /* Process AVP's */
+ ver_len_hidden = tvb_get_ntohs(tvb, index);
+ avp_len = AVP_LENGTH(ver_len_hidden);
+ avp_vendor_id = tvb_get_ntohs(tvb, index + 2);
+ avp_type = tvb_get_ntohs(tvb, index + 4);
+
+ if (avp_vendor_id == VENDOR_IETF) {
+ tf = proto_tree_add_text(l2tp_tree, tvb, index,
+ avp_len, "%s AVP",
+ val_to_str(avp_type, avp_type_vals, "Unknown (%u)"));
+ } else { /* Vendor-Specific AVP */
+ tf = proto_tree_add_text(l2tp_tree, tvb, index,
+ avp_len, "Vendor %s AVP",
+ val_to_str(avp_vendor_id, avp_vendor_id_vals, "Unknown (%u)"));
+ }
+
+ l2tp_avp_tree = proto_item_add_subtree(tf, ett_l2tp_avp);
+
+ proto_tree_add_boolean_format(l2tp_avp_tree,hf_l2tp_avp_mandatory, tvb, index, 1,
+ rhcode, "Mandatory: %s",
+ (MANDATORY_BIT(ver_len_hidden)) ? "True" : "False" );
+ proto_tree_add_boolean_format(l2tp_avp_tree,hf_l2tp_avp_hidden, tvb, index, 1,
+ rhcode, "Hidden: %s",
+ (HIDDEN_BIT(ver_len_hidden)) ? "True" : "False" );
+ proto_tree_add_uint_format(l2tp_avp_tree,hf_l2tp_avp_length, tvb, index, 2,
+ rhcode, "Length: %u", avp_len);
+ if (HIDDEN_BIT(ver_len_hidden)) { /* don't try do display hidden */
+ index += avp_len;
+ continue;
+ }
+
+ if (avp_len < 6) {
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 0,
+ "AVP length must be >= 6");
+ return;
+ }
+ index += 2;
+ avp_len -= 2;
+
+ proto_tree_add_item(l2tp_avp_tree, hf_l2tp_avp_vendor_id,
+ tvb, index, 2, FALSE);
+ index += 2;
+ avp_len -= 2;
+
+ if (avp_vendor_id != VENDOR_IETF) {
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Type: %u", avp_type);
+ index += 2;
+ avp_len -= 2;
+
+ /* For the time being, we don't decode any Vendor-
+ specific AVP. */
+ proto_tree_add_text(l2tp_avp_tree, tvb, index,
+ avp_len, "Vendor-Specific AVP");
+
+ index += avp_len;
+ continue;
+ }
+
+ proto_tree_add_uint(l2tp_avp_tree, hf_l2tp_avp_type,
+ tvb, index, 2, avp_type);
+ index += 2;
+ avp_len -= 2;
+
+ switch (avp_type) {
+
+ case CONTROL_MESSAGE:
+ msg_type = tvb_get_ntohs(tvb, index);
+ proto_tree_add_text(l2tp_avp_tree,tvb, index, 2,
+ "Control Message Type: (%u) %s", msg_type,
+ ((NUM_CONTROL_CALL_TYPES + 1 ) > msg_type) ?
+ calltypestr[msg_type] : "Unknown");
+ break;
+
+ case RESULT_ERROR_CODE:
+ if (avp_len < 2)
+ break;
+ result_code = tvb_get_ntohs(tvb, index);
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Result code: %u", result_code);
+ index += 2;
+ avp_len -= 2;
+
+ if (avp_len < 2)
+ break;
+ error_code = tvb_get_ntohs(tvb, index);
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Error code: %u", error_code);
+ index += 2;
+ avp_len -= 2;
+
+ if (avp_len == 0)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Error Message: %.*s", avp_len,
+ tvb_get_ptr(tvb, index, avp_len));
+ break;
+
+ case PROTOCOL_VERSION:
+ if (avp_len < 1)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 1,
+ "Version: %u", tvb_get_guint8(tvb, index));
+ index += 1;
+ avp_len -= 1;
+
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 1,
+ "Revision: %u", tvb_get_guint8(tvb, index));
+ break;
+
+ case FRAMING_CAPABILITIES:
+ bits = tvb_get_ntohl(tvb, index);
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Async Framing Supported: %s",
+ (FRAMING_ASYNC(bits)) ? "True" : "False");
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Sync Framing Supported: %s",
+ (FRAMING_SYNC(bits)) ? "True" : "False");
+ break;
+
+ case BEARER_CAPABILITIES:
+ bits = tvb_get_ntohl(tvb, index);
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Analog Access Supported: %s",
+ (BEARER_ANALOG(bits)) ? "True" : "False");
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Digital Access Supported: %s",
+ (BEARER_DIGITAL(bits)) ? "True" : "False");
+ break;
+
+ case TIE_BREAKER:
+ proto_tree_add_item(l2tp_avp_tree, hf_l2tp_tie_breaker, tvb, index, 8, FALSE);
+ break;
+
+ case FIRMWARE_REVISION:
+ firmware_rev = tvb_get_ntohs(tvb, index);
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Firmware Revision: %d 0x%x", firmware_rev,firmware_rev );
+ break;
+
+ case HOST_NAME:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Host Name: %.*s", avp_len,
+ tvb_get_ptr(tvb, index, avp_len));
+ break;
+
+ case VENDOR_NAME:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Vendor Name: %.*s", avp_len,
+ tvb_get_ptr(tvb, index, avp_len));
+ break;
+
+ case ASSIGNED_TUNNEL_ID:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Tunnel ID: %u", tvb_get_ntohs(tvb, index));
+ break;
+
+ case RECEIVE_WINDOW_SIZE:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Receive Window Size: %u",
+ tvb_get_ntohs(tvb, index));
+ break;
+
+ case CHALLENGE:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "CHAP Challenge: %s",
+ tvb_bytes_to_str(tvb, index, avp_len));
+ break;
+
+ case CAUSE_CODE:
+ /*
+ * XXX - export stuff from the Q.931 dissector
+ * to dissect the cause code and cause message,
+ * and use it.
+ */
+ if (avp_len < 2)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Cause Code: %u",
+ tvb_get_ntohs(tvb, index));
+ index += 2;
+ avp_len -= 2;
+
+ if (avp_len < 1)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 1,
+ "Cause Msg: %u",
+ tvb_get_guint8(tvb, index));
+ index += 1;
+ avp_len -= 1;
+
+ if (avp_len == 0)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Advisory Msg: %.*s", avp_len,
+ tvb_get_ptr(tvb, index, avp_len));
+ break;
+
+ case CHALLENGE_RESPONSE:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 16,
+ "CHAP Challenge Response: %s",
+ tvb_bytes_to_str(tvb, index, 16));
+ break;
+
+ case ASSIGNED_SESSION:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Assigned Session: %u",
+ tvb_get_ntohs(tvb, index));
+ break;
+
+ case CALL_SERIAL_NUMBER:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Call Serial Number: %u",
+ tvb_get_ntohl(tvb, index));
+ break;
+
+ case MINIMUM_BPS:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Minimum BPS: %u",
+ tvb_get_ntohl(tvb, index));
+ break;
+
+ case MAXIMUM_BPS:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Maximum BPS: %u",
+ tvb_get_ntohl(tvb, index));
+ break;
+
+ case BEARER_TYPE:
+ bits = tvb_get_ntohl(tvb, index);
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Analog Bearer Type: %s",
+ (BEARER_ANALOG(bits)) ? "True" : "False");
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Digital Bearer Type: %s",
+ (BEARER_DIGITAL(bits)) ? "True" : "False");
+ break;
+
+ case FRAMING_TYPE:
+ bits = tvb_get_ntohl(tvb, index);
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Async Framing Type: %s",
+ (FRAMING_ASYNC(bits)) ? "True" : "False");
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Sync Framing Type: %s",
+ (FRAMING_SYNC(bits)) ? "True" : "False");
+ break;
+
+ case CALLED_NUMBER:
+ if (avp_len == 0)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Called Number: %.*s", avp_len,
+ tvb_get_ptr(tvb, index, avp_len));
+ break;
+
+ case CALLING_NUMBER:
+ if (avp_len == 0)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Calling Number: %.*s", avp_len,
+ tvb_get_ptr(tvb, index, avp_len));
+ break;
+
+ case SUB_ADDRESS:
+ if (avp_len == 0)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Sub-Address: %.*s", avp_len,
+ tvb_get_ptr(tvb, index, avp_len));
+ break;
+
+ case TX_CONNECT_SPEED:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Connect Speed: %u",
+ tvb_get_ntohl(tvb, index));
+ break;
+
+ case PHYSICAL_CHANNEL:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Physical Channel: %u",
+ tvb_get_ntohl(tvb, index));
+ break;
+
+ case INITIAL_RECEIVED_LCP_CONFREQ:
+ te = proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Initial Received LCP CONFREQ: %s",
+ tvb_bytes_to_str(tvb, index, avp_len));
+ l2tp_lcp_avp_tree = proto_item_add_subtree(te, ett_l2tp_lcp);
+ next_tvb = tvb_new_subset(tvb, index, avp_len, avp_len);
+ call_dissector(ppp_lcp_options_handle, next_tvb, pinfo, l2tp_lcp_avp_tree );
+ break;
+
+ case LAST_SENT_LCP_CONFREQ:
+ te = proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Last Sent LCP CONFREQ: %s",
+ tvb_bytes_to_str(tvb, index, avp_len));
+ l2tp_lcp_avp_tree = proto_item_add_subtree(te, ett_l2tp_lcp);
+ next_tvb = tvb_new_subset(tvb, index, avp_len, avp_len);
+ call_dissector(ppp_lcp_options_handle, next_tvb, pinfo, l2tp_lcp_avp_tree );
+ break;
+
+ case LAST_RECEIVED_LCP_CONFREQ:
+ te = proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Last Received LCP CONFREQ: %s",
+ tvb_bytes_to_str(tvb, index, avp_len));
+ l2tp_lcp_avp_tree = proto_item_add_subtree(te, ett_l2tp_lcp);
+ next_tvb = tvb_new_subset(tvb, index, avp_len, avp_len);
+ call_dissector(ppp_lcp_options_handle, next_tvb, pinfo, l2tp_lcp_avp_tree );
+ break;
+
+ case PROXY_AUTHEN_TYPE:
+ msg_type = tvb_get_ntohs(tvb, index);
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Proxy Authen Type: %s",
+ val_to_str(msg_type, authen_type_vals, "Unknown (%u)"));
+ break;
+
+ case PROXY_AUTHEN_NAME:
+ if (avp_len == 0)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Proxy Authen Name: %.*s", avp_len,
+ tvb_get_ptr(tvb, index, avp_len));
+ break;
+
+ case PROXY_AUTHEN_CHALLENGE:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Proxy Authen Challenge: %s",
+ tvb_bytes_to_str(tvb, index, avp_len));
+ break;
+
+ case PROXY_AUTHEN_ID:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index + 1, 1,
+ "Proxy Authen ID: %u",
+ tvb_get_guint8(tvb, index + 1));
+ break;
+
+ case PROXY_AUTHEN_RESPONSE:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Proxy Authen Response: %s",
+ tvb_bytes_to_str(tvb, index, avp_len));
+ break;
+
+ case CALL_STATUS_AVPS:
+ if (avp_len < 2)
+ break;
+ index += 2;
+ avp_len -= 2;
+
+ if (avp_len < 4)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "CRC Errors: %u", tvb_get_ntohl(tvb, index));
+ index += 4;
+ avp_len -= 4;
+
+ if (avp_len < 4)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Framing Errors: %u", tvb_get_ntohl(tvb, index));
+ index += 4;
+ avp_len -= 4;
+
+ if (avp_len < 4)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Hardware Overruns: %u", tvb_get_ntohl(tvb, index));
+ index += 4;
+ avp_len -= 4;
+
+ if (avp_len < 4)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Buffer Overruns: %u", tvb_get_ntohl(tvb, index));
+ index += 4;
+ avp_len -= 4;
+
+ if (avp_len < 4)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Time-out Errors: %u", tvb_get_ntohl(tvb, index));
+ index += 4;
+ avp_len -= 4;
+
+ if (avp_len < 4)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Alignment Errors: %u", tvb_get_ntohl(tvb, index));
+ index += 4;
+ avp_len -= 4;
+ break;
+
+ case ACCM:
+ if (avp_len < 2)
+ break;
+ index += 2;
+ avp_len -= 2;
+
+ if (avp_len < 4)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Send ACCM: %u", tvb_get_ntohl(tvb, index));
+ index += 4;
+ avp_len -= 4;
+
+ if (avp_len < 4)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Receive ACCM: %u", tvb_get_ntohl(tvb, index));
+ index += 4;
+ avp_len -= 4;
+ break;
+
+ case RANDOM_VECTOR:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Random Vector: %s",
+ tvb_bytes_to_str(tvb, index, avp_len));
+ break;
+
+ case PRIVATE_GROUP_ID:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Private Group ID: %s",
+ tvb_bytes_to_str(tvb, index, avp_len));
+ break;
+
+ case RX_CONNECT_SPEED:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 4,
+ "Rx Connect Speed: %u",
+ tvb_get_ntohl(tvb, index));
+ break;
+
+ case PPP_DISCONNECT_CAUSE_CODE:
+ if (avp_len < 2)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Disconnect Code: %u",
+ tvb_get_ntohs(tvb, index));
+ index += 2;
+ avp_len -= 2;
+
+ if (avp_len < 2)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 2,
+ "Control Protocol Number: %u",
+ tvb_get_ntohs(tvb, index));
+ index += 2;
+ avp_len -= 2;
+
+ if (avp_len < 1)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, 1,
+ "Direction: %s",
+ val_to_str(tvb_get_guint8(tvb, index),
+ cause_code_direction_vals,
+ "Reserved (%u)"));
+ index += 1;
+ avp_len -= 1;
+
+ if (avp_len == 0)
+ break;
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Message: %.*s", avp_len,
+ tvb_get_ptr(tvb, index, avp_len));
+ break;
+
+ default:
+ proto_tree_add_text(l2tp_avp_tree, tvb, index, avp_len,
+ "Unknown AVP");
+ break;
+ }
+
+ /* printf("Avp Decode avp_len= %d index= %d length= %d %x\n ",avp_len,
+ index,length,length); */
+
+ index += avp_len;
+ }
+
+ }
+}
+
+/* registration with the filtering engine */
+void
+proto_register_l2tp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_l2tp_type,
+ { "Type", "l2tp.type", FT_UINT16, BASE_DEC, VALS(l2tp_type_vals), 0x8000,
+ "Type bit", HFILL }},
+
+ { &hf_l2tp_length_bit,
+ { "Length Bit", "l2tp.length_bit", FT_BOOLEAN, 16, TFS(&l2tp_length_bit_truth), 0x4000,
+ "Length bit", HFILL }},
+
+ { &hf_l2tp_seq_bit,
+ { "Sequence Bit", "l2tp.seq_bit", FT_BOOLEAN, 16, TFS(&l2tp_seq_bit_truth), 0x0800,
+ "Sequence bit", HFILL }},
+
+ { &hf_l2tp_offset_bit,
+ { "Offset bit", "l2tp.offset_bit", FT_BOOLEAN, 16, TFS(&l2tp_offset_bit_truth), 0x0200,
+ "Offset bit", HFILL }},
+
+ { &hf_l2tp_priority,
+ { "Priority", "l2tp.priority", FT_BOOLEAN, 16, TFS(&l2tp_priority_truth), 0x0100,
+ "Priority bit", HFILL }},
+
+ { &hf_l2tp_version,
+ { "Version", "l2tp.version", FT_UINT16, BASE_DEC, NULL, 0x000f,
+ "Version", HFILL }},
+
+ { &hf_l2tp_length,
+ { "Length","l2tp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_l2tp_tunnel,
+ { "Tunnel ID","l2tp.tunnel", FT_UINT16, BASE_DEC, NULL, 0x0, /* Probably should be FT_BYTES */
+ "Tunnel ID", HFILL }},
+
+ { &hf_l2tp_session,
+ { "Session ID","l2tp.session", FT_UINT16, BASE_DEC, NULL, 0x0, /* Probably should be FT_BYTES */
+ "Session ID", HFILL }},
+
+ { &hf_l2tp_Ns,
+ { "Ns","l2tp.Ns", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_l2tp_Nr,
+ { "Nr","l2tp.Nr", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_l2tp_offset,
+ { "Offset","l2tp.offset", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of octest past the L2TP header at which the"
+ "payload data starts.", HFILL }},
+
+ { &hf_l2tp_avp_mandatory,
+ { "Mandatory", "l2tp.avp.mandatory", FT_BOOLEAN, BASE_NONE, NULL, 0,
+ "Mandatory AVP", HFILL }},
+
+ { &hf_l2tp_avp_hidden,
+ { "Hidden", "l2tp.avp.hidden", FT_BOOLEAN, BASE_NONE, NULL, 0,
+ "Hidden AVP", HFILL }},
+
+ { &hf_l2tp_avp_length,
+ { "Length", "l2tp.avp.length", FT_UINT16, BASE_DEC, NULL, 0,
+ "AVP Length", HFILL }},
+
+ { &hf_l2tp_avp_vendor_id,
+ { "Vendor ID", "l2tp.avp.vendor_id", FT_UINT16, BASE_DEC, VALS(avp_vendor_id_vals), 0,
+ "AVP Vendor ID", HFILL }},
+
+ { &hf_l2tp_avp_type,
+ { "Type", "l2tp.avp.type", FT_UINT16, BASE_DEC, VALS(avp_type_vals), 0,
+ "AVP Type", HFILL }},
+
+ { &hf_l2tp_tie_breaker,
+ { "Tie Breaker", "l2tp.tie_breaker", FT_UINT64, BASE_HEX, NULL, 0,
+ "Tie Breaker", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_l2tp,
+ &ett_l2tp_ctrl,
+ &ett_l2tp_avp,
+ &ett_l2tp_lcp,
+ };
+
+ proto_l2tp = proto_register_protocol(
+ "Layer 2 Tunneling Protocol", "L2TP", "l2tp");
+ proto_register_field_array(proto_l2tp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_l2tp(void)
+{
+ dissector_handle_t l2tp_handle;
+
+ l2tp_handle = create_dissector_handle(dissect_l2tp, proto_l2tp);
+ dissector_add("udp.port", UDP_PORT_L2TP, l2tp_handle);
+
+ /*
+ * Get a handle for the PPP-in-HDLC-like-framing dissector.
+ */
+ ppp_hdlc_handle = find_dissector("ppp_hdlc");
+ ppp_lcp_options_handle = find_dissector("ppp_lcp_options");
+
+}
diff --git a/epan/dissectors/packet-lapb.c b/epan/dissectors/packet-lapb.c
new file mode 100644
index 0000000000..0b010e5073
--- /dev/null
+++ b/epan/dissectors/packet-lapb.c
@@ -0,0 +1,250 @@
+/* packet-lapb.c
+ * Routines for lapb frame disassembly
+ * Olivier Abad <oabad@noos.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "xdlc.h"
+
+static int proto_lapb = -1;
+static int hf_lapb_address = -1;
+static int hf_lapb_control = -1;
+static int hf_lapb_n_r = -1;
+static int hf_lapb_n_s = -1;
+static int hf_lapb_p = -1;
+static int hf_lapb_f = -1;
+static int hf_lapb_s_ftype = -1;
+static int hf_lapb_u_modifier_cmd = -1;
+static int hf_lapb_u_modifier_resp = -1;
+static int hf_lapb_ftype_i = -1;
+static int hf_lapb_ftype_s_u = -1;
+
+static gint ett_lapb = -1;
+static gint ett_lapb_control = -1;
+
+static dissector_handle_t x25_dir_handle;
+static dissector_handle_t x25_handle;
+
+static const xdlc_cf_items lapb_cf_items = {
+ &hf_lapb_n_r,
+ &hf_lapb_n_s,
+ &hf_lapb_p,
+ &hf_lapb_f,
+ &hf_lapb_s_ftype,
+ &hf_lapb_u_modifier_cmd,
+ &hf_lapb_u_modifier_resp,
+ &hf_lapb_ftype_i,
+ &hf_lapb_ftype_s_u
+};
+
+static void
+dissect_lapb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *lapb_tree, *ti;
+ int is_response;
+ guint8 byte0;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPB");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ switch (pinfo->p2p_dir) {
+
+ case P2P_DIR_SENT:
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
+ break;
+
+ case P2P_DIR_RECV:
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
+ break;
+
+ default:
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
+ break;
+ }
+
+ byte0 = tvb_get_guint8(tvb, 0);
+
+ if (byte0 != 0x01 && byte0 != 0x03) /* invalid LAPB frame */
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Invalid LAPB frame");
+ if (tree)
+ ti = proto_tree_add_protocol_format(tree, proto_lapb, tvb, 0, -1,
+ "Invalid LAPB frame");
+ return;
+ }
+
+ switch (pinfo->p2p_dir) {
+
+ case P2P_DIR_SENT:
+ if (byte0 == 0x03)
+ is_response = TRUE;
+ else
+ is_response = FALSE;
+ break;
+
+ case P2P_DIR_RECV:
+ if (byte0 == 0x01)
+ is_response = TRUE;
+ else
+ is_response = FALSE;
+ break;
+
+ default:
+ /*
+ * XXX - should we base this on the source and destination
+ * addresses? The problem is that we can tell one direction
+ * from another with that, but we can't say which is DTE->DCE
+ * and which is DCE->DTE.
+ */
+ is_response = FALSE;
+ break;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_lapb, tvb, 0, 2,
+ "LAPB");
+ lapb_tree = proto_item_add_subtree(ti, ett_lapb);
+ proto_tree_add_uint_format(lapb_tree, hf_lapb_address, tvb, 0, 1, byte0,
+ "Address: 0x%02X", byte0);
+ }
+ else
+ lapb_tree = NULL;
+
+ dissect_xdlc_control(tvb, 1, pinfo, lapb_tree, hf_lapb_control,
+ ett_lapb_control, &lapb_cf_items, NULL, NULL, NULL,
+ is_response, FALSE, FALSE);
+
+ /* not end of frame ==> X.25 */
+ if (tvb_reported_length(tvb) > 2) {
+ next_tvb = tvb_new_subset(tvb, 2, -1, -1);
+ switch (pinfo->p2p_dir) {
+
+ case P2P_DIR_SENT:
+ case P2P_DIR_RECV:
+ call_dissector(x25_dir_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ call_dissector(x25_handle, next_tvb, pinfo, tree);
+ break;
+ }
+ }
+}
+
+void
+proto_register_lapb(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_lapb_address,
+ { "Address Field", "lapb.address", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Address", HFILL }},
+
+ { &hf_lapb_control,
+ { "Control Field", "lapb.control", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Control field", HFILL }},
+
+ { &hf_lapb_n_r,
+ { "N(R)", "lapb.control.n_r", FT_UINT8, BASE_DEC,
+ NULL, XDLC_N_R_MASK, "", HFILL }},
+
+ { &hf_lapb_n_s,
+ { "N(S)", "lapb.control.n_s", FT_UINT8, BASE_DEC,
+ NULL, XDLC_N_S_MASK, "", HFILL }},
+
+ { &hf_lapb_p,
+ { "Poll", "lapb.control.p", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+
+ { &hf_lapb_f,
+ { "Final", "lapb.control.f", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+
+ { &hf_lapb_s_ftype,
+ { "Supervisory frame type", "lapb.control.s_ftype", FT_UINT8, BASE_HEX,
+ VALS(stype_vals), XDLC_S_FTYPE_MASK, "", HFILL }},
+
+ { &hf_lapb_u_modifier_cmd,
+ { "Command", "lapb.control.u_modifier_cmd", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, "", HFILL }},
+
+ { &hf_lapb_u_modifier_resp,
+ { "Response", "lapb.control.u_modifier_resp", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, "", HFILL }},
+
+ { &hf_lapb_ftype_i,
+ { "Frame type", "lapb.control.ftype", FT_UINT8, BASE_HEX,
+ VALS(ftype_vals), XDLC_I_MASK, "", HFILL }},
+
+ { &hf_lapb_ftype_s_u,
+ { "Frame type", "lapb.control.ftype", FT_UINT8, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_lapb,
+ &ett_lapb_control,
+ };
+
+ proto_lapb = proto_register_protocol("Link Access Procedure Balanced (LAPB)",
+ "LAPB", "lapb");
+ proto_register_field_array (proto_lapb, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("lapb", dissect_lapb, proto_lapb);
+}
+
+void
+proto_reg_handoff_lapb(void)
+{
+ dissector_handle_t lapb_handle;
+
+ /*
+ * Get handles for the X.25 dissectors; we don't get an X.25
+ * pseudo-header for LAPB-over-Ethernet, but we do get it
+ * for raw LAPB.
+ */
+ x25_dir_handle = find_dissector("x.25_dir");
+ x25_handle = find_dissector("x.25");
+
+ lapb_handle = find_dissector("lapb");
+ dissector_add("wtap_encap", WTAP_ENCAP_LAPB, lapb_handle);
+}
diff --git a/epan/dissectors/packet-lapbether.c b/epan/dissectors/packet-lapbether.c
new file mode 100644
index 0000000000..5257e7f383
--- /dev/null
+++ b/epan/dissectors/packet-lapbether.c
@@ -0,0 +1,109 @@
+/* packet-lapbether.c
+ * Routines for lapbether frame disassembly
+ * Richard Sharpe <rsharpe@ns.aus.com> based on the lapb module by
+ * Olivier Abad <oabad@noos.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "etypes.h"
+
+static int proto_lapbether = -1;
+
+static int hf_lapbether_length = -1;
+
+static gint ett_lapbether = -1;
+
+static dissector_handle_t lapb_handle;
+
+static void
+dissect_lapbether(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *lapbether_tree, *ti;
+ int len;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPBETHER");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ len = tvb_get_guint8(tvb, 0) + tvb_get_guint8(tvb, 1) * 256;
+
+ if (tree) {
+
+ ti = proto_tree_add_protocol_format(tree, proto_lapbether, tvb, 0, 2,
+ "LAPBETHER");
+
+ lapbether_tree = proto_item_add_subtree(ti, ett_lapbether);
+ proto_tree_add_uint_format(lapbether_tree, hf_lapbether_length, tvb, 0, 2,
+ len, "Length: %u", len);
+
+ }
+
+ next_tvb = tvb_new_subset(tvb, 2, len, len);
+ call_dissector(lapb_handle, next_tvb, pinfo, tree);
+
+}
+
+void
+proto_register_lapbether(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_lapbether_length,
+ { "Length Field", "lapbether.length", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "LAPBEther Length Field", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_lapbether,
+ };
+
+ proto_lapbether = proto_register_protocol ("Link Access Procedure Balanced Ethernet (LAPBETHER)",
+ "LAPBETHER", "lapbether");
+ proto_register_field_array (proto_lapbether, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+/* The registration hand-off routine */
+void
+proto_reg_handoff_lapbether(void)
+{
+ dissector_handle_t lapbether_handle;
+
+ /*
+ * Get a handle for the LAPB dissector.
+ */
+ lapb_handle = find_dissector("lapb");
+
+ lapbether_handle = create_dissector_handle(dissect_lapbether,
+ proto_lapbether);
+ dissector_add("ethertype", ETHERTYPE_DEC, lapbether_handle);
+
+}
diff --git a/epan/dissectors/packet-lapd.c b/epan/dissectors/packet-lapd.c
new file mode 100644
index 0000000000..d766047ef8
--- /dev/null
+++ b/epan/dissectors/packet-lapd.c
@@ -0,0 +1,296 @@
+/* packet-lapd.c
+ * Routines for LAPD frame disassembly
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "xdlc.h"
+
+#include "lapd_sapi.h"
+
+/* ISDN/LAPD references:
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/cisintwk/ito_doc/isdn.htm
+ * http://www.ece.wpi.edu/courses/ee535/hwk11cd95/agrebe/agrebe.html
+ * http://www.acacia-net.com/Clarinet/Protocol/q9213o84.htm
+ */
+
+static int proto_lapd = -1;
+static int hf_lapd_address = -1;
+static int hf_lapd_sapi = -1;
+static int hf_lapd_cr = -1;
+static int hf_lapd_ea1 = -1;
+static int hf_lapd_tei = -1;
+static int hf_lapd_ea2 = -1;
+static int hf_lapd_control = -1;
+static int hf_lapd_n_r = -1;
+static int hf_lapd_n_s = -1;
+static int hf_lapd_p = -1;
+static int hf_lapd_p_ext = -1;
+static int hf_lapd_f = -1;
+static int hf_lapd_f_ext = -1;
+static int hf_lapd_s_ftype = -1;
+static int hf_lapd_u_modifier_cmd = -1;
+static int hf_lapd_u_modifier_resp = -1;
+static int hf_lapd_ftype_i = -1;
+static int hf_lapd_ftype_s_u = -1;
+static int hf_lapd_ftype_s_u_ext = -1;
+
+static gint ett_lapd = -1;
+static gint ett_lapd_address = -1;
+static gint ett_lapd_control = -1;
+
+static dissector_table_t lapd_sapi_dissector_table;
+
+static dissector_handle_t data_handle;
+static dissector_handle_t tei_handle;
+
+/*
+ * Bits in the address field.
+ */
+#define LAPD_SAPI 0xfc00 /* Service Access Point Identifier */
+#define LAPD_SAPI_SHIFT 10
+#define LAPD_CR 0x0200 /* Command/Response bit */
+#define LAPD_EA1 0x0100 /* First Address Extension bit */
+#define LAPD_TEI 0x00fe /* Terminal Endpoint Identifier */
+#define LAPD_EA2 0x0001 /* Second Address Extension bit */
+
+static const value_string lapd_sapi_vals[] = {
+ { LAPD_SAPI_Q931, "Q.931 Call control procedure" },
+ { LAPD_SAPI_PM_Q931, "Packet mode Q.931 Call control procedure" },
+ { LAPD_SAPI_X25, "X.25 Level 3 procedures" },
+ { LAPD_SAPI_L2, "Layer 2 management procedures" },
+ { 0, NULL }
+};
+
+/* Used only for U frames */
+static const xdlc_cf_items lapd_cf_items = {
+ NULL,
+ NULL,
+ &hf_lapd_p,
+ &hf_lapd_f,
+ NULL,
+ &hf_lapd_u_modifier_cmd,
+ &hf_lapd_u_modifier_resp,
+ NULL,
+ &hf_lapd_ftype_s_u
+};
+
+/* Used only for I and S frames */
+static const xdlc_cf_items lapd_cf_items_ext = {
+ &hf_lapd_n_r,
+ &hf_lapd_n_s,
+ &hf_lapd_p_ext,
+ &hf_lapd_f_ext,
+ &hf_lapd_s_ftype,
+ NULL,
+ NULL,
+ &hf_lapd_ftype_i,
+ &hf_lapd_ftype_s_u_ext
+};
+
+static void
+dissect_lapd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *lapd_tree, *addr_tree;
+ proto_item *lapd_ti, *addr_ti;
+ guint16 control;
+ int lapd_header_len;
+ guint16 address, cr, sapi;
+ gboolean is_response;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LAPD");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ address = tvb_get_ntohs(tvb, 0);
+ cr = address & LAPD_CR;
+ sapi = (address & LAPD_SAPI) >> LAPD_SAPI_SHIFT;
+ lapd_header_len = 2; /* address */
+
+ if (pinfo->p2p_dir == P2P_DIR_SENT) {
+ is_response = cr ? TRUE : FALSE;
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "Network");
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "User");
+ }
+ else {
+ /* XXX - what if the direction is unknown? */
+ is_response = cr ? FALSE : TRUE;
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "User");
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "Network");
+ }
+
+ if (tree) {
+ lapd_ti = proto_tree_add_item(tree, proto_lapd, tvb, 0, -1,
+ FALSE);
+ lapd_tree = proto_item_add_subtree(lapd_ti, ett_lapd);
+
+ addr_ti = proto_tree_add_uint(lapd_tree, hf_lapd_address, tvb,
+ 0, 2, address);
+ addr_tree = proto_item_add_subtree(addr_ti, ett_lapd_address);
+
+ proto_tree_add_uint(addr_tree, hf_lapd_sapi,tvb, 0, 1, address);
+ proto_tree_add_uint(addr_tree, hf_lapd_cr, tvb, 0, 1, address);
+ proto_tree_add_uint(addr_tree, hf_lapd_ea1, tvb, 0, 1, address);
+ proto_tree_add_uint(addr_tree, hf_lapd_tei, tvb, 1, 1, address);
+ proto_tree_add_uint(addr_tree, hf_lapd_ea2, tvb, 1, 1, address);
+ }
+ else {
+ lapd_ti = NULL;
+ lapd_tree = NULL;
+ }
+
+ control = dissect_xdlc_control(tvb, 2, pinfo, lapd_tree, hf_lapd_control,
+ ett_lapd_control, &lapd_cf_items, &lapd_cf_items_ext, NULL, NULL,
+ is_response, TRUE, FALSE);
+ lapd_header_len += XDLC_CONTROL_LEN(control, TRUE);
+
+ if (tree)
+ proto_item_set_len(lapd_ti, lapd_header_len);
+
+ next_tvb = tvb_new_subset(tvb, lapd_header_len, -1, -1);
+ if (XDLC_IS_INFORMATION(control)) {
+ /* call next protocol */
+ if (!dissector_try_port(lapd_sapi_dissector_table, sapi,
+ next_tvb, pinfo, tree))
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ } else
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+}
+
+void
+proto_register_lapd(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_lapd_address,
+ { "Address Field", "lapd.address", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Address", HFILL }},
+
+ { &hf_lapd_sapi,
+ { "SAPI", "lapd.sapi", FT_UINT16, BASE_DEC, VALS(lapd_sapi_vals), LAPD_SAPI,
+ "Service Access Point Identifier", HFILL }},
+
+ { &hf_lapd_cr,
+ { "C/R", "lapd.cr", FT_UINT16, BASE_DEC, NULL, LAPD_CR,
+ "Command/Response bit", HFILL }},
+
+ { &hf_lapd_ea1,
+ { "EA1", "lapd.ea1", FT_UINT16, BASE_DEC, NULL, LAPD_EA1,
+ "First Address Extension bit", HFILL }},
+
+ { &hf_lapd_tei,
+ { "TEI", "lapd.tei", FT_UINT16, BASE_DEC, NULL, LAPD_TEI,
+ "Terminal Endpoint Identifier", HFILL }},
+
+ { &hf_lapd_ea2,
+ { "EA2", "lapd.ea2", FT_UINT16, BASE_DEC, NULL, LAPD_EA2,
+ "Second Address Extension bit", HFILL }},
+
+ { &hf_lapd_control,
+ { "Control Field", "lapd.control", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Control field", HFILL }},
+
+ { &hf_lapd_n_r,
+ { "N(R)", "lapd.control.n_r", FT_UINT16, BASE_DEC,
+ NULL, XDLC_N_R_EXT_MASK, "", HFILL }},
+
+ { &hf_lapd_n_s,
+ { "N(S)", "lapd.control.n_s", FT_UINT16, BASE_DEC,
+ NULL, XDLC_N_S_EXT_MASK, "", HFILL }},
+
+ { &hf_lapd_p,
+ { "Poll", "lapd.control.p", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+
+ { &hf_lapd_p_ext,
+ { "Poll", "lapd.control.p", FT_BOOLEAN, 16,
+ TFS(&flags_set_truth), XDLC_P_F_EXT, "", HFILL }},
+
+ { &hf_lapd_f,
+ { "Final", "lapd.control.f", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+
+ { &hf_lapd_f_ext,
+ { "Final", "lapd.control.f", FT_BOOLEAN, 16,
+ TFS(&flags_set_truth), XDLC_P_F_EXT, "", HFILL }},
+
+ { &hf_lapd_s_ftype,
+ { "Supervisory frame type", "lapd.control.s_ftype", FT_UINT16, BASE_HEX,
+ VALS(stype_vals), XDLC_S_FTYPE_MASK, "", HFILL }},
+
+ { &hf_lapd_u_modifier_cmd,
+ { "Command", "lapd.control.u_modifier_cmd", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, "", HFILL }},
+
+ { &hf_lapd_u_modifier_resp,
+ { "Response", "lapd.control.u_modifier_resp", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, "", HFILL }},
+
+ { &hf_lapd_ftype_i,
+ { "Frame type", "lapd.control.ftype", FT_UINT16, BASE_HEX,
+ VALS(ftype_vals), XDLC_I_MASK, "", HFILL }},
+
+ { &hf_lapd_ftype_s_u,
+ { "Frame type", "lapd.control.ftype", FT_UINT8, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+
+ { &hf_lapd_ftype_s_u_ext,
+ { "Frame type", "lapd.control.ftype", FT_UINT16, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_lapd,
+ &ett_lapd_address,
+ &ett_lapd_control,
+ };
+
+ proto_lapd = proto_register_protocol("Link Access Procedure, Channel D (LAPD)",
+ "LAPD", "lapd");
+ proto_register_field_array (proto_lapd, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("lapd", dissect_lapd, proto_lapd);
+
+ lapd_sapi_dissector_table = register_dissector_table("lapd.sapi",
+ "LAPD SAPI", FT_UINT16, BASE_DEC);
+}
+
+void
+proto_reg_handoff_lapd(void)
+{
+ data_handle = find_dissector("data");
+ tei_handle = find_dissector("tei");
+}
diff --git a/epan/dissectors/packet-laplink.c b/epan/dissectors/packet-laplink.c
new file mode 100644
index 0000000000..279240b06b
--- /dev/null
+++ b/epan/dissectors/packet-laplink.c
@@ -0,0 +1,261 @@
+/* packet-laplink.c
+ * Routines for laplink dissection
+ * Copyright 2003, Brad Hards <bradh@frogmouth.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/conversation.h>
+
+#include "packet-tcp.h"
+#include "prefs.h"
+
+#define TCP_PORT_LAPLINK 1547
+#define UDP_PORT_LAPLINK 1547
+
+/* Initialize the protocol and registered fields */
+static int proto_laplink = -1;
+static int hf_laplink_udp_ident = -1;
+static int hf_laplink_udp_name = -1;
+static int hf_laplink_tcp_ident = -1;
+static int hf_laplink_tcp_length = -1;
+static int hf_laplink_tcp_data = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_laplink = -1;
+
+static const value_string laplink_udp_magic[] = {
+ { 0x0f010000, "Name Solicitation" },
+ { 0xf0000200, "Name Reply" },
+ { 0, NULL }
+};
+
+static const value_string laplink_tcp_magic[] = {
+ { 0xff08c000, "Unknown TCP query - connection?" },
+ { 0xff08c200, "Unknown TCP query - connection?" },
+ { 0xff0bc000, "Unknown TCP query - connection?" },
+ { 0xff0bc200, "Unknown TCP query - connection?" },
+ { 0xff10c000, "Unknown TCP response - connection?" },
+ { 0xff10c200, "Unknown TCP response - connection?" },
+ { 0xff11c000, "Unknown TCP query/response - directory list or file transfer?" },
+ { 0xff11c200, "Unknown TCP query - directory list or file request?" },
+ { 0xff13c000, "Unknown TCP response - connection?" },
+ { 0xff13c200, "Unknown TCP response - connection?" },
+ { 0xff14c000, "Unknown TCP response - directory list or file transfer?" },
+ { 0, NULL }
+};
+
+static gboolean laplink_desegment = TRUE;
+
+/* Code to actually dissect the packets - UDP */
+static gint
+dissect_laplink_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_item *ti;
+ proto_tree *laplink_tree;
+ guint32 udp_ident;
+ gchar *udp_ident_string;
+
+ /*
+ * Make sure the identifier is reasonable.
+ */
+ if (!tvb_bytes_exist(tvb, offset, 4))
+ return 0; /* not enough bytes to check */
+ udp_ident = tvb_get_ntohl(tvb, offset);
+ udp_ident_string = match_strval(udp_ident, laplink_udp_magic);
+ if (udp_ident_string == NULL)
+ return 0; /* unknown */
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Laplink");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, udp_ident_string);
+
+ if (tree){
+ ti = proto_tree_add_item(tree, proto_laplink, tvb, 0, -1, FALSE);
+ laplink_tree = proto_item_add_subtree(ti, ett_laplink);
+
+ proto_tree_add_uint(laplink_tree, hf_laplink_udp_ident, tvb, offset, 4, udp_ident);
+ offset += 4;
+
+ proto_tree_add_item(laplink_tree, hf_laplink_udp_name, tvb, offset, -1, FALSE);
+ }
+ return tvb_length(tvb);
+}
+
+/* Code to actually dissect the packets - TCP aspects*/
+static void
+dissect_laplink_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ int length = 0;
+ proto_item *ti;
+ proto_tree *laplink_tree;
+ guint32 tcp_ident;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Laplink");
+
+ tcp_ident = tvb_get_ntohl(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(tcp_ident, laplink_tcp_magic, "TCP TBA (%u)"));
+ }
+
+ if (tree){
+ ti = proto_tree_add_item(tree, proto_laplink, tvb, 0, -1, FALSE);
+
+
+ laplink_tree = proto_item_add_subtree(ti, ett_laplink);
+
+ proto_tree_add_item(laplink_tree, hf_laplink_tcp_ident, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(laplink_tree, hf_laplink_tcp_length, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(laplink_tree, hf_laplink_tcp_data, tvb, offset, length, FALSE);
+
+/* Continue adding tree items to process the packet here */
+
+ }
+
+/* If this protocol has a sub-dissector call it here, see section 1.8 */
+}
+
+static guint
+get_laplink_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint plen;
+ /*
+ * The length doesn't include the length or ident fields; add those in.
+ */
+ plen = (tvb_get_ntohs(tvb, offset+4) + 2 + 4);
+ return plen;
+}
+
+static void
+dissect_laplink_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, laplink_desegment,
+ 6, get_laplink_pdu_len,
+ dissect_laplink_tcp_pdu);
+}
+
+
+/* Register the protocol with Ethereal */
+
+void
+proto_register_laplink(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_laplink_udp_ident,
+ { "UDP Ident", "laplink.udp_ident",
+ FT_UINT32, BASE_HEX, VALS(laplink_udp_magic), 0x0,
+ "Unknown magic", HFILL }
+ },
+ { &hf_laplink_udp_name,
+ { "UDP Name", "laplink.udp_name",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Machine name", HFILL }
+ },
+ { &hf_laplink_tcp_ident,
+ { "TCP Ident", "laplink.tcp_ident",
+ FT_UINT32, BASE_HEX, VALS(laplink_tcp_magic), 0x0,
+ "Unknown magic", HFILL }
+ },
+ { &hf_laplink_tcp_length,
+ { "TCP Data payload length", "laplink.tcp_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of remaining payload", HFILL }
+ },
+ { &hf_laplink_tcp_data,
+ { "Unknown TCP data", "laplink.tcp_data",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "TCP data", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_laplink,
+ };
+
+ module_t *laplink_module;
+
+/* Register the protocol name and description */
+ proto_laplink = proto_register_protocol("Laplink",
+ "Laplink", "laplink");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_laplink, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ laplink_module = prefs_register_protocol(proto_laplink, NULL);
+ prefs_register_bool_preference(laplink_module, "desegment_laplink_over_tcp",
+ "Desegment all Laplink-over-TCP messages",
+ "Whether the Laplink dissector should desegment all Laplink-over-TCP messages",
+ &laplink_desegment);
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_laplink(void)
+{
+ dissector_handle_t laplink_udp_handle;
+ dissector_handle_t laplink_tcp_handle;
+
+ laplink_tcp_handle = create_dissector_handle(dissect_laplink_tcp,
+ proto_laplink);
+ dissector_add("tcp.port", TCP_PORT_LAPLINK, laplink_tcp_handle);
+
+ laplink_udp_handle = new_create_dissector_handle(dissect_laplink_udp,
+ proto_laplink);
+ dissector_add("udp.port", UDP_PORT_LAPLINK, laplink_udp_handle);
+}
+
diff --git a/epan/dissectors/packet-ldap.c b/epan/dissectors/packet-ldap.c
new file mode 100644
index 0000000000..583b9142f1
--- /dev/null
+++ b/epan/dissectors/packet-ldap.c
@@ -0,0 +1,3006 @@
+/* packet-ldap.c
+ * Routines for ldap packet dissection
+ *
+ * See RFC 1777 (LDAP v2), RFC 2251 (LDAP v3), and RFC 2222 (SASL).
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This is not a complete implementation. It doesn't handle the full version 3, more specifically,
+ * it handles only the commands of version 2, but any additional characteristics of the ver3 command are supported.
+ * It's also missing extensible search filters.
+ *
+ * There should probably be alot more error checking, I simply assume that if we have a full packet, it will be a complete
+ * and correct packet.
+ *
+ * AFAIK, it will handle all messages used by the OpenLDAP 1.2.9 server and libraries which was my goal. I do plan to add
+ * the remaining commands as time permits but this is not a priority to me. Send me an email if you need it and I'll see what
+ * I can do.
+ *
+ * Doug Nazar
+ * nazard@dragoninc.on.ca
+ */
+
+/*
+ * 11/11/2002 - Fixed problem when decoding LDAP with desegmentation enabled and the
+ * ASN.1 BER Universal Class Tag: "Sequence Of" header is encapsulated across 2
+ * TCP segments.
+ *
+ * Ronald W. Henderson
+ * ronald.henderson@cognicaseusa.com
+ */
+
+/*
+ * 20-JAN-2004 - added decoding of MS-CLDAP netlogon RPC
+ * using information from the SNIA 2003 conference paper :
+ * Active Directory Domain Controller Location Service
+ * by Anthony Liguori
+ * ronnie sahlberg
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+
+#include "asn1.h"
+#include "prefs.h"
+#include <epan/conversation.h>
+#include "packet-frame.h"
+#include "tap.h"
+#include "packet-ldap.h"
+
+static int proto_ldap = -1;
+static int proto_cldap = -1;
+static int hf_ldap_response_to = -1;
+static int hf_ldap_response_in = -1;
+static int hf_ldap_time = -1;
+static int hf_ldap_sasl_buffer_length = -1;
+static int hf_ldap_length = -1;
+static int hf_ldap_message_id = -1;
+static int hf_ldap_message_type = -1;
+static int hf_ldap_message_length = -1;
+
+static int hf_ldap_message_result = -1;
+static int hf_ldap_message_result_matcheddn = -1;
+static int hf_ldap_message_result_errormsg = -1;
+static int hf_ldap_message_result_referral = -1;
+
+static int hf_ldap_message_bind_version = -1;
+static int hf_ldap_message_bind_dn = -1;
+static int hf_ldap_message_bind_auth = -1;
+static int hf_ldap_message_bind_auth_password = -1;
+static int hf_ldap_message_bind_auth_mechanism = -1;
+static int hf_ldap_message_bind_auth_credentials = -1;
+static int hf_ldap_message_bind_server_credentials = -1;
+
+static int hf_ldap_message_search_base = -1;
+static int hf_ldap_message_search_scope = -1;
+static int hf_ldap_message_search_deref = -1;
+static int hf_ldap_message_search_sizeLimit = -1;
+static int hf_ldap_message_search_timeLimit = -1;
+static int hf_ldap_message_search_typesOnly = -1;
+static int hf_ldap_message_search_filter = -1;
+static int hf_ldap_message_search_reference = -1;
+
+static int hf_ldap_message_dn = -1;
+static int hf_ldap_message_attribute = -1;
+static int hf_ldap_message_value = -1;
+
+static int hf_ldap_message_modrdn_name = -1;
+static int hf_ldap_message_modrdn_delete = -1;
+static int hf_ldap_message_modrdn_superior = -1;
+
+static int hf_ldap_message_compare = -1;
+
+static int hf_ldap_message_modify_add = -1;
+static int hf_ldap_message_modify_replace = -1;
+static int hf_ldap_message_modify_delete = -1;
+
+static int hf_ldap_message_abandon_msgid = -1;
+
+static int hf_mscldap_netlogon_type = -1;
+static int hf_mscldap_netlogon_flags = -1;
+static int hf_mscldap_netlogon_flags_pdc = -1;
+static int hf_mscldap_netlogon_flags_gc = -1;
+static int hf_mscldap_netlogon_flags_ldap = -1;
+static int hf_mscldap_netlogon_flags_ds = -1;
+static int hf_mscldap_netlogon_flags_kdc = -1;
+static int hf_mscldap_netlogon_flags_timeserv = -1;
+static int hf_mscldap_netlogon_flags_closest = -1;
+static int hf_mscldap_netlogon_flags_writable = -1;
+static int hf_mscldap_netlogon_flags_good_timeserv = -1;
+static int hf_mscldap_netlogon_flags_ndnc = -1;
+static int hf_mscldap_domain_guid = -1;
+static int hf_mscldap_forest = -1;
+static int hf_mscldap_domain = -1;
+static int hf_mscldap_hostname = -1;
+static int hf_mscldap_nb_domain = -1;
+static int hf_mscldap_nb_hostname = -1;
+static int hf_mscldap_username = -1;
+static int hf_mscldap_sitename = -1;
+static int hf_mscldap_clientsitename = -1;
+static int hf_mscldap_netlogon_version = -1;
+static int hf_mscldap_netlogon_lm_token = -1;
+static int hf_mscldap_netlogon_nt_token = -1;
+
+static gint ett_ldap = -1;
+static gint ett_ldap_gssapi_token = -1;
+static gint ett_ldap_referrals = -1;
+static gint ett_ldap_attribute = -1;
+static gint ett_mscldap_netlogon_flags = -1;
+
+static int ldap_tap = -1;
+
+/* desegmentation of LDAP */
+static gboolean ldap_desegment = TRUE;
+
+#define TCP_PORT_LDAP 389
+#define UDP_PORT_CLDAP 389
+#define TCP_PORT_GLOBALCAT_LDAP 3268 /* Windows 2000 Global Catalog */
+
+static dissector_handle_t gssapi_handle;
+static dissector_handle_t gssapi_wrap_handle;
+
+
+/* different types of rpc calls ontop of ms cldap */
+#define MSCLDAP_RPC_NETLOGON 1
+
+
+/*
+ * Data structure attached to a conversation, giving authentication
+ * information from a bind request.
+ * We keep a linked list of them, so that we can free up all the
+ * authentication mechanism strings.
+ */
+typedef struct ldap_conv_info_t {
+ struct ldap_conv_info_t *next;
+ guint auth_type; /* authentication type */
+ char *auth_mech; /* authentication mechanism */
+ guint32 first_auth_frame; /* first frame that would use a security layer */
+ GHashTable *unmatched;
+ GHashTable *matched;
+} ldap_conv_info_t;
+static GMemChunk *ldap_conv_info_chunk = NULL;
+static guint ldap_conv_info_chunk_count = 20;
+static ldap_conv_info_t *ldap_info_items;
+
+static GMemChunk *ldap_call_response_chunk = NULL;
+static guint ldap_call_response_chunk_count = 200;
+
+static guint
+ldap_info_hash_matched(gconstpointer k)
+{
+ ldap_call_response_t *key = (ldap_call_response_t *)k;
+
+ return key->messageId;
+}
+
+static gint
+ldap_info_equal_matched(gconstpointer k1, gconstpointer k2)
+{
+ ldap_call_response_t *key1 = (ldap_call_response_t *)k1;
+ ldap_call_response_t *key2 = (ldap_call_response_t *)k2;
+
+ if( key1->req_frame && key2->req_frame && (key1->req_frame!=key2->req_frame) ){
+ return 0;
+ }
+ if( key1->rep_frame && key2->rep_frame && (key1->rep_frame!=key2->rep_frame) ){
+ return 0;
+ }
+
+ return key1->messageId==key2->messageId;
+}
+
+static guint
+ldap_info_hash_unmatched(gconstpointer k)
+{
+ ldap_call_response_t *key = (ldap_call_response_t *)k;
+
+ return key->messageId;
+}
+
+static gint
+ldap_info_equal_unmatched(gconstpointer k1, gconstpointer k2)
+{
+ ldap_call_response_t *key1 = (ldap_call_response_t *)k1;
+ ldap_call_response_t *key2 = (ldap_call_response_t *)k2;
+
+ return key1->messageId==key2->messageId;
+}
+
+
+static value_string msgTypes [] = {
+ {LDAP_REQ_BIND, "Bind Request"},
+ {LDAP_REQ_UNBIND, "Unbind Request"},
+ {LDAP_REQ_SEARCH, "Search Request"},
+ {LDAP_REQ_MODIFY, "Modify Request"},
+ {LDAP_REQ_ADD, "Add Request"},
+ {LDAP_REQ_DELETE, "Delete Request"},
+ {LDAP_REQ_MODRDN, "Modify RDN Request"},
+ {LDAP_REQ_COMPARE, "Compare Request"},
+ {LDAP_REQ_ABANDON, "Abandon Request"},
+ {LDAP_REQ_EXTENDED, "Extended Request"},
+
+ {LDAP_RES_BIND, "Bind Result"},
+ {LDAP_RES_SEARCH_ENTRY, "Search Entry"},
+ {LDAP_RES_SEARCH_RESULT, "Search Result"},
+ {LDAP_RES_SEARCH_REF, "Search Result Reference"},
+ {LDAP_RES_MODIFY, "Modify Result"},
+ {LDAP_RES_ADD, "Add Result"},
+ {LDAP_RES_DELETE, "Delete Result"},
+ {LDAP_RES_MODRDN, "Modify RDN Result"},
+ {LDAP_RES_COMPARE, "Compare Result"},
+ {LDAP_RES_EXTENDED, "Extended Response"},
+ {0, NULL},
+};
+
+static value_string result_codes[] = {
+ {0, "Success"},
+ {1, "Operations error"},
+ {2, "Protocol error"},
+ {3, "Time limit exceeded"},
+ {4, "Size limit exceeded"},
+ {5, "Compare false"},
+ {6, "Compare true"},
+ {7, "Authentication method not supported"},
+ {8, "Strong authentication required"},
+ {10, "Referral"},
+ {11, "Administrative limit exceeded"},
+ {12, "Unavailable critical extension"},
+ {13, "Confidentiality required"},
+ {14, "SASL bind in progress"},
+ {16, "No such attribute"},
+ {17, "Undefined attribute type"},
+ {18, "Inappropriate matching"},
+ {19, "Constraint violation"},
+ {20, "Attribute or value exists"},
+ {21, "Invalid attribute syntax"},
+ {32, "No such object"},
+ {33, "Alias problem"},
+ {34, "Invalid DN syntax"},
+ {36, "Alias derefetencing problem"},
+ {48, "Inappropriate authentication"},
+ {49, "Invalid credentials"},
+ {50, "Insufficient access rights"},
+ {51, "Busy"},
+ {52, "Unavailable"},
+ {53, "Unwilling to perform"},
+ {54, "Loop detected"},
+ {64, "Naming violation"},
+ {65, "Objectclass violation"},
+ {66, "Not allowed on non-leaf"},
+ {67, "Not allowed on RDN"},
+ {68, "Entry already exists"},
+ {69, "Objectclass modification prohibited"},
+ {71, "Affects multiple DSAs"},
+ {80, "Other"},
+ {0, NULL},
+};
+
+static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
+{
+ guint length = 0;
+ gboolean def = FALSE;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_length_decode(a, &def, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse length: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (len)
+ *len = length;
+
+ if (tree)
+ proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start, length);
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_sequence(ASN1_SCK *a, guint *len)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint length;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
+ return ASN1_ERR_WRONG_TYPE;
+
+ if (len)
+ *len = length;
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_set(ASN1_SCK *a, guint *len)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint length;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SET)
+ return ASN1_ERR_WRONG_TYPE;
+
+ if (len)
+ *len = length;
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i, int start, guint length)
+{
+ guint integer = 0;
+ proto_item *temp_item = NULL;
+ int ret;
+
+ ret = asn1_uint32_value_decode(a, length, &integer);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse value: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (i)
+ *i = integer;
+
+ if (tree)
+ temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start, integer);
+
+ if (new_item)
+ *new_item = temp_item;
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i, guint expected_tag)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint length;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret == ASN1_ERR_NOERROR) {
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag)
+ ret = ASN1_ERR_WRONG_TYPE;
+ }
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
+ asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ return read_integer_value(a, tree, hf_id, new_item, i, start, length);
+}
+
+static int read_boolean_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i, int start, guint length)
+{
+ guint integer = 0;
+ proto_item *temp_item = NULL;
+ int ret;
+
+ ret = asn1_uint32_value_decode(a, length, &integer);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse value: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (i)
+ *i = integer;
+
+ if (tree)
+ temp_item = proto_tree_add_boolean(tree, hf_id, a->tvb, start, a->offset-start, integer);
+ if (new_item)
+ *new_item = temp_item;
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_boolean(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint length;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret == ASN1_ERR_NOERROR) {
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_BOL)
+ ret = ASN1_ERR_WRONG_TYPE;
+ }
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ return read_boolean_value(a, tree, hf_id, new_item, i, start, length);
+}
+
+static int read_string_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, char **s, int start, guint length)
+{
+ guchar *string;
+ proto_item *temp_item = NULL;
+ int ret;
+
+ if (length)
+ {
+ ret = asn1_string_value_decode(a, length, &string);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse value: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+ string = g_realloc(string, length + 1);
+ string[length] = '\0';
+ }
+ else
+ string = "(null)";
+
+ if (tree)
+ temp_item = proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset - start, string);
+ if (new_item)
+ *new_item = temp_item;
+
+ if (s && length)
+ *s = string;
+ else if (length)
+ g_free(string);
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_string(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, char **s, guint *length,
+ guint expected_cls, guint expected_tag)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint tmplen;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &tmplen);
+ if (ret == ASN1_ERR_NOERROR) {
+ if (cls != expected_cls || con != ASN1_PRI || tag != expected_tag)
+ ret = ASN1_ERR_WRONG_TYPE;
+ }
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if(length){
+ *length=tmplen;
+ }
+ return read_string_value(a, tree, hf_id, new_item, s, start, tmplen);
+}
+
+static int read_bytestring_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, char **s, int start, guint length)
+{
+ guchar *string;
+ proto_item *temp_item = NULL;
+ int ret;
+
+ if (length)
+ {
+ ret = asn1_string_value_decode(a, length, &string);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse value: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+ string = g_realloc(string, length + 1);
+ string[length] = '\0';
+ }
+ else
+ string = "(null)";
+
+ if (tree)
+ temp_item = proto_tree_add_bytes(tree, hf_id, a->tvb, start, a->offset - start, string);
+ if (new_item)
+ *new_item = temp_item;
+
+ if (s && length)
+ *s = string;
+ else if (length)
+ g_free(string);
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_bytestring(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, char **s, guint expected_cls, guint expected_tag)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint length;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret == ASN1_ERR_NOERROR) {
+ if (cls != expected_cls || con != ASN1_PRI || tag != expected_tag)
+ ret = ASN1_ERR_WRONG_TYPE;
+ }
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ return read_bytestring_value(a, tree, hf_id, new_item, s, start, length);
+}
+
+static int parse_filter_strings(ASN1_SCK *a, char **filter, guint *filter_length, const guchar *operation)
+{
+ guchar *string;
+ guchar *string2;
+ guint string_length;
+ guint string2_length;
+ guint string_bytes;
+ char *filterp;
+ int ret;
+
+ ret = asn1_octet_string_decode(a, &string, &string_length, &string_bytes);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ ret = asn1_octet_string_decode(a, &string2, &string2_length, &string_bytes);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ *filter_length += 2 + strlen(operation) + string_length + string2_length;
+ *filter = g_realloc(*filter, *filter_length);
+ filterp = *filter + strlen(*filter);
+ *filterp++ = '(';
+ if (string_length != 0) {
+ memcpy(filterp, string, string_length);
+ filterp += string_length;
+ }
+ strcpy(filterp, operation);
+ filterp += strlen(operation);
+ if (string2_length != 0) {
+ memcpy(filterp, string2, string2_length);
+ filterp += string2_length;
+ }
+ *filterp++ = ')';
+ *filterp = '\0';
+ g_free(string);
+ g_free(string2);
+ return ASN1_ERR_NOERROR;
+}
+
+/* Richard Dawe: To parse substring filters, I added this function. */
+static int parse_filter_substrings(ASN1_SCK *a, char **filter, guint *filter_length)
+{
+ int end;
+ guchar *string;
+ char *filterp;
+ guint string_length;
+ guint string_bytes;
+ guint seq_len;
+ guint header_bytes;
+ int ret, any_valued;
+
+ /* For ASN.1 parsing of octet strings */
+ guint cls;
+ guint con;
+ guint tag;
+ gboolean def;
+
+ ret = asn1_octet_string_decode(a, &string, &string_length, &string_bytes);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+
+ ret = asn1_sequence_decode(a, &seq_len, &header_bytes);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+
+ *filter_length += 2 + 1 + string_length;
+ *filter = g_realloc(*filter, *filter_length);
+
+ filterp = *filter + strlen(*filter);
+ *filterp++ = '(';
+ if (string_length != 0) {
+ memcpy(filterp, string, string_length);
+ filterp += string_length;
+ }
+ *filterp++ = '=';
+ *filterp = '\0';
+ g_free(string);
+
+ /* Now decode seq_len's worth of octet strings. */
+ any_valued = 0;
+ end = a->offset + seq_len;
+
+ while (a->offset < end) {
+ /* Octet strings here are context-specific, which
+ * asn1_octet_string_decode() barfs on. Emulate it, but don't barf. */
+ ret = asn1_header_decode (a, &cls, &con, &tag, &def, &string_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+
+ /* XXX - check the tag? */
+ if (cls != ASN1_CTX || con != ASN1_PRI) {
+ /* XXX - handle the constructed encoding? */
+ return ASN1_ERR_WRONG_TYPE;
+ }
+ if (!def)
+ return ASN1_ERR_LENGTH_NOT_DEFINITE;
+
+ ret = asn1_string_value_decode(a, (int) string_length, &string);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+
+ /* If we have an 'any' component with a string value, we need to append
+ * an extra asterisk before final component. */
+ if ((tag == 1) && (string_length != 0))
+ any_valued = 1;
+
+ if ( (tag == 1) || ((tag == 2) && any_valued) )
+ (*filter_length)++;
+ *filter_length += string_length;
+ *filter = g_realloc(*filter, *filter_length);
+
+ filterp = *filter + strlen(*filter);
+ if ( (tag == 1) || ((tag == 2) && any_valued) )
+ *filterp++ = '*';
+ if (tag == 2)
+ any_valued = 0;
+ if (string_length != 0) {
+ memcpy(filterp, string, string_length);
+ filterp += string_length;
+ }
+ *filterp = '\0';
+ g_free(string);
+ }
+
+ if (any_valued)
+ {
+ (*filter_length)++;
+ *filter = g_realloc(*filter, *filter_length);
+ filterp = *filter + strlen(*filter);
+ *filterp++ = '*';
+ }
+
+ /* NB: Allocated byte for this earlier */
+ *filterp++ = ')';
+ *filterp = '\0';
+
+ return ASN1_ERR_NOERROR;
+}
+
+/* Returns -1 if we're at the end, returns an ASN1_ERR value otherwise. */
+static int parse_filter(ASN1_SCK *a, char **filter, guint *filter_length,
+ int *end)
+{
+ guint cls, con, tag;
+ guint length;
+ gboolean def;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+
+ if (*end == 0)
+ {
+ *end = a->offset + length;
+ *filter_length = 1;
+ *filter = g_malloc0(*filter_length);
+ }
+
+ if (cls == ASN1_CTX) /* XXX - handle other types as errors? */
+ {
+ switch (tag)
+ {
+ case LDAP_FILTER_AND:
+ {
+ int add_end;
+
+ if (con != ASN1_CON)
+ return ASN1_ERR_WRONG_TYPE;
+ add_end = a->offset + length;
+ *filter_length += 3;
+ *filter = g_realloc(*filter, *filter_length);
+ strcat(*filter, "(&");
+ while ((ret = parse_filter(a, filter, filter_length, &add_end))
+ == ASN1_ERR_NOERROR)
+ continue;
+ if (ret != -1)
+ return ret;
+ strcat(*filter, ")");
+ }
+ break;
+ case LDAP_FILTER_OR:
+ {
+ int or_end;
+
+ if (con != ASN1_CON)
+ return ASN1_ERR_WRONG_TYPE;
+ or_end = a->offset + length;
+ *filter_length += 3;
+ *filter = g_realloc(*filter, *filter_length);
+ strcat(*filter, "(|");
+ while ((ret = parse_filter(a, filter, filter_length, &or_end))
+ == ASN1_ERR_NOERROR)
+ continue;
+ if (ret != -1)
+ return ret;
+ strcat(*filter, ")");
+ }
+ break;
+ case LDAP_FILTER_NOT:
+ {
+ int not_end;
+
+ if (con != ASN1_CON)
+ return ASN1_ERR_WRONG_TYPE;
+ not_end = a->offset + length;
+ *filter_length += 3;
+ *filter = g_realloc(*filter, *filter_length);
+ strcat(*filter, "(!");
+ ret = parse_filter(a, filter, filter_length, &not_end);
+ if (ret != -1 && ret != ASN1_ERR_NOERROR)
+ return ret;
+ strcat(*filter, ")");
+ }
+ break;
+ case LDAP_FILTER_EQUALITY:
+ if (con != ASN1_CON)
+ return ASN1_ERR_WRONG_TYPE;
+ ret = parse_filter_strings(a, filter, filter_length, "=");
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ break;
+ case LDAP_FILTER_GE:
+ if (con != ASN1_CON)
+ return ASN1_ERR_WRONG_TYPE;
+ ret = parse_filter_strings(a, filter, filter_length, ">=");
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ break;
+ case LDAP_FILTER_LE:
+ if (con != ASN1_CON)
+ return ASN1_ERR_WRONG_TYPE;
+ ret = parse_filter_strings(a, filter, filter_length, "<=");
+ if (ret != -1 && ret != ASN1_ERR_NOERROR)
+ return ret;
+ break;
+ case LDAP_FILTER_APPROX:
+ if (con != ASN1_CON)
+ return ASN1_ERR_WRONG_TYPE;
+ ret = parse_filter_strings(a, filter, filter_length, "~=");
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ break;
+ case LDAP_FILTER_PRESENT:
+ {
+ guchar *string;
+ char *filterp;
+
+ if (con != ASN1_PRI)
+ return ASN1_ERR_WRONG_TYPE;
+ ret = asn1_string_value_decode(a, length, &string);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ *filter_length += 4 + length;
+ *filter = g_realloc(*filter, *filter_length);
+ filterp = *filter + strlen(*filter);
+ *filterp++ = '(';
+ if (length != 0) {
+ memcpy(filterp, string, length);
+ filterp += length;
+ }
+ *filterp++ = '=';
+ *filterp++ = '*';
+ *filterp++ = ')';
+ *filterp = '\0';
+ g_free(string);
+ }
+ break;
+ case LDAP_FILTER_SUBSTRINGS:
+ if (con != ASN1_CON)
+ return ASN1_ERR_WRONG_TYPE;
+ /* Richard Dawe: Handle substrings */
+ ret = parse_filter_substrings(a, filter, filter_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ break;
+ default:
+ return ASN1_ERR_WRONG_TYPE;
+ }
+ }
+
+ if (a->offset == *end)
+ return -1;
+ else
+ return ASN1_ERR_NOERROR;
+}
+
+static gboolean read_filter(ASN1_SCK *a, proto_tree *tree, int hf_id)
+{
+ int start = a->offset;
+ char *filter = 0;
+ guint filter_length = 0;
+ int end = 0;
+ int ret;
+
+ while ((ret = parse_filter(a, &filter, &filter_length, &end))
+ == ASN1_ERR_NOERROR)
+ continue;
+
+ if (tree) {
+ if (ret != -1) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Can't parse filter: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ } else
+ proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset-start, filter);
+ }
+
+ g_free(filter);
+
+ return (ret == -1) ? TRUE : FALSE;
+}
+
+/********************************************************************************************/
+
+static void dissect_ldap_result(ASN1_SCK *a, proto_tree *tree, packet_info *pinfo)
+{
+ guint resultCode = 0;
+ int ret;
+ if (read_integer(a, tree, hf_ldap_message_result, 0, &resultCode, ASN1_ENUM) != ASN1_ERR_NOERROR)
+ return;
+
+ if (resultCode != 0) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(resultCode, result_codes,
+ "Unknown (%u)"));
+ }
+
+ if (read_string(a, tree, hf_ldap_message_result_matcheddn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ if (read_string(a, tree, hf_ldap_message_result_errormsg, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+
+ if (resultCode == 10) /* Referral */
+ {
+ int start = a->offset;
+ int end;
+ guint length;
+ proto_item *ti;
+ proto_tree *referralTree;
+
+ ret = read_sequence(a, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "ERROR: Couldn't parse referral URL sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+ ti = proto_tree_add_text(tree, a->tvb, start, length, "Referral URLs");
+ referralTree = proto_item_add_subtree(ti, ett_ldap_referrals);
+
+ end = a->offset + length;
+ while (a->offset < end) {
+ if (read_string(a, referralTree, hf_ldap_message_result_referral, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ }
+ }
+}
+
+static void dissect_ldap_request_bind(ASN1_SCK *a, proto_tree *tree,
+ tvbuff_t *tvb, packet_info *pinfo, ldap_conv_info_t *ldap_info)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint length;
+ int start;
+ int end;
+ int ret;
+ char *mechanism, *s = NULL;
+ int token_offset;
+ gint available_length, reported_length;
+ tvbuff_t *new_tvb;
+ proto_item *gitem;
+ proto_tree *gtree = NULL;
+
+ if (read_integer(a, tree, hf_ldap_message_bind_version, 0, 0, ASN1_INT) != ASN1_ERR_NOERROR)
+ return;
+ if (read_string(a, tree, hf_ldap_message_bind_dn, 0, &s, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", DN=%s", s != NULL ? s : "(null)");
+ g_free(s);
+
+ start = a->offset;
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret == ASN1_ERR_NOERROR) {
+ if (cls != ASN1_CTX) {
+ /* RFCs 1777 and 2251 say these are context-specific types */
+ ret = ASN1_ERR_WRONG_TYPE;
+ }
+ }
+ if (ret != ASN1_ERR_NOERROR) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ proto_registrar_get_name(hf_ldap_message_bind_auth),
+ asn1_err_to_str(ret));
+ return;
+ }
+ proto_tree_add_uint(tree, hf_ldap_message_bind_auth, a->tvb, start,
+ a->offset - start, tag);
+ end = a->offset + length;
+ switch (tag)
+ {
+ case LDAP_AUTH_SIMPLE:
+ if (read_string_value(a, tree, hf_ldap_message_bind_auth_password, NULL,
+ NULL, start, length) != ASN1_ERR_NOERROR)
+ return;
+ break;
+
+ /* For Kerberos V4, dissect it as a ticket. */
+
+ case LDAP_AUTH_SASL:
+ mechanism = NULL;
+ if (read_string(a, tree, hf_ldap_message_bind_auth_mechanism, NULL,
+ &mechanism, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+
+ /*
+ * We need to remember the authentication type and mechanism for this
+ * conversation.
+ *
+ * XXX - actually, we might need to remember more than one
+ * type and mechanism, if you can unbind and rebind with a
+ * different type and/or mechanism.
+ */
+ ldap_info->auth_type = tag;
+ ldap_info->auth_mech = mechanism;
+ ldap_info->first_auth_frame = 0; /* not known until we see the bind reply */
+ /*
+ * If the mechanism in this request is an empty string (which is
+ * returned as a null pointer), use the saved mechanism instead.
+ * Otherwise, if the saved mechanism is an empty string (null),
+ * save this mechanism.
+ */
+ if (mechanism == NULL)
+ mechanism = ldap_info->auth_mech;
+ else {
+ if (ldap_info->auth_mech == NULL) {
+ g_free(ldap_info->auth_mech);
+ }
+ ldap_info->auth_mech = mechanism;
+ }
+
+ if (a->offset < end) {
+ if (mechanism != NULL && strcmp(mechanism, "GSS-SPNEGO") == 0) {
+ /*
+ * This is a GSS-API token ancapsulated within GSS-SPNEGO.
+ * Find out how big it is by parsing the ASN.1 header for the
+ * OCTET STREAM that contains it.
+ */
+ token_offset = a->offset;
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ proto_tree_add_text(tree, a->tvb, token_offset, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
+ asn1_err_to_str(ret));
+ return;
+ }
+ if (tree) {
+ gitem = proto_tree_add_text(tree, tvb, token_offset,
+ (a->offset + length) - token_offset, "GSS-API Token");
+ gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
+ }
+ available_length = tvb_length_remaining(tvb, token_offset);
+ reported_length = tvb_reported_length_remaining(tvb, token_offset);
+ g_assert(available_length >= 0);
+ g_assert(reported_length >= 0);
+ if (available_length > reported_length)
+ available_length = reported_length;
+ if ((guint)available_length > length)
+ available_length = length;
+ if ((guint)reported_length > length)
+ reported_length = length;
+ new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
+ call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
+ a->offset += length;
+ } else if (mechanism != NULL && strcmp(mechanism, "GSSAPI") == 0) {
+ /*
+ * This is a raw GSS-API token.
+ * Find out how big it is by parsing the ASN.1 header for the
+ * OCTET STREAM that contains it.
+ */
+ token_offset = a->offset;
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ proto_tree_add_text(tree, a->tvb, token_offset, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
+ asn1_err_to_str(ret));
+ return;
+ }
+ if (tree) {
+ gitem = proto_tree_add_text(tree, tvb, token_offset,
+ (a->offset + length) - token_offset, "GSS-API Token");
+ gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
+ }
+ if(length==0){
+ /* for GSSAPI the third pdu will sometimes be "empty" */
+ return;
+ }
+ available_length = tvb_length_remaining(tvb, token_offset);
+ reported_length = tvb_reported_length_remaining(tvb, token_offset);
+ g_assert(available_length >= 0);
+ g_assert(reported_length >= 0);
+ if (available_length > reported_length)
+ available_length = reported_length;
+ if ((guint)available_length > length)
+ available_length = length;
+ if ((guint)reported_length > length)
+ reported_length = length;
+ new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
+ call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
+ a->offset += length;
+ } else {
+ if (read_bytestring(a, tree, hf_ldap_message_bind_auth_credentials,
+ NULL, NULL, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ }
+ }
+ break;
+ }
+}
+
+static void dissect_ldap_response_bind(ASN1_SCK *a, proto_tree *tree,
+ int start, guint length, tvbuff_t *tvb, packet_info *pinfo, ldap_conv_info_t *ldap_info)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint cred_length;
+ int end;
+ int ret;
+ int token_offset;
+ gint available_length, reported_length;
+ tvbuff_t *new_tvb;
+ proto_item *gitem;
+ proto_tree *gtree = NULL;
+
+ end = start + length;
+ dissect_ldap_result(a, tree, pinfo);
+ if (a->offset < end) {
+ switch (ldap_info->auth_type) {
+
+ /* For Kerberos V4, dissect it as a ticket. */
+ /* XXX - what about LDAP_AUTH_SIMPLE? */
+
+ case LDAP_AUTH_SASL:
+ /*
+ * All frames after this are assumed to use a security layer.
+ *
+ * XXX - won't work if there's another reply, with the security
+ * layer, starting in the same TCP segment that ends this
+ * reply, but as LDAP is a request/response protocol, and
+ * as the client probably can't start using authentication until
+ * it gets the bind reply and the server won't send a reply until
+ * it gets a request, that probably won't happen.
+ *
+ * XXX - that assumption is invalid; it's not clear where the
+ * hell you find out whether there's any security layer. In
+ * one capture, we have two GSS-SPNEGO negotiations, both of
+ * which select MS KRB5, and the only differences in the tokens
+ * is in the RC4-HMAC ciphertext. The various
+ * draft-ietf--cat-sasl-gssapi-NN.txt drafts seem to imply
+ * that the RFC 2222 spoo with the bitmask and maximum
+ * output message size stuff is done - but where does that
+ * stuff show up? Is it in the ciphertext, which means it's
+ * presumably encrypted?
+ *
+ * Grrr. We have to do a gross heuristic, checking whether the
+ * putative LDAP message begins with 0x00 or not, making the
+ * assumption that we won't have more than 2^24 bytes of
+ * encapsulated stuff.
+ */
+ ldap_info->first_auth_frame = pinfo->fd->num + 1;
+ if (ldap_info->auth_mech != NULL &&
+ strcmp(ldap_info->auth_mech, "GSS-SPNEGO") == 0) {
+ /*
+ * This is a GSS-API token.
+ * Find out how big it is by parsing the ASN.1 header for the
+ * OCTET STREAM that contains it.
+ */
+ token_offset = a->offset;
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &cred_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ proto_tree_add_text(tree, a->tvb, token_offset, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
+ asn1_err_to_str(ret));
+ return;
+ }
+ if (tree) {
+ gitem = proto_tree_add_text(tree, tvb, token_offset,
+ (a->offset + cred_length) - token_offset, "GSS-API Token");
+ gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
+ }
+ available_length = tvb_length_remaining(tvb, token_offset);
+ reported_length = tvb_reported_length_remaining(tvb, token_offset);
+ g_assert(available_length >= 0);
+ g_assert(reported_length >= 0);
+ if (available_length > reported_length)
+ available_length = reported_length;
+ if ((guint)available_length > cred_length)
+ available_length = cred_length;
+ if ((guint)reported_length > cred_length)
+ reported_length = cred_length;
+ new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
+ call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
+ a->offset += cred_length;
+ } else if (ldap_info->auth_mech != NULL &&
+ strcmp(ldap_info->auth_mech, "GSSAPI") == 0) {
+ /*
+ * This is a GSS-API token.
+ * Find out how big it is by parsing the ASN.1 header for the
+ * OCTET STREAM that contains it.
+ */
+ token_offset = a->offset;
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &cred_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ proto_tree_add_text(tree, a->tvb, token_offset, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ proto_registrar_get_name(hf_ldap_message_bind_auth_credentials),
+ asn1_err_to_str(ret));
+ return;
+ }
+ if (tree) {
+ gitem = proto_tree_add_text(tree, tvb, token_offset,
+ (a->offset + cred_length) - token_offset, "GSS-API Token");
+ gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
+ }
+ available_length = tvb_length_remaining(tvb, token_offset);
+ reported_length = tvb_reported_length_remaining(tvb, token_offset);
+ g_assert(available_length >= 0);
+ g_assert(reported_length >= 0);
+ if (available_length > reported_length)
+ available_length = reported_length;
+ if ((guint)available_length > cred_length)
+ available_length = cred_length;
+ if ((guint)reported_length > cred_length)
+ reported_length = cred_length;
+ new_tvb = tvb_new_subset(tvb, a->offset, available_length, reported_length);
+ call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
+ a->offset += cred_length;
+ } else {
+ if (read_bytestring(a, tree, hf_ldap_message_bind_server_credentials,
+ NULL, NULL, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ }
+ break;
+
+ default:
+ if (read_bytestring(a, tree, hf_ldap_message_bind_server_credentials,
+ NULL, NULL, ASN1_CTX, 7) != ASN1_ERR_NOERROR)
+ return;
+ break;
+ }
+ }
+}
+
+static void dissect_ldap_request_search(ASN1_SCK *a, proto_tree *tree, packet_info *pinfo)
+{
+ guint seq_length;
+ int end;
+ int ret;
+ char *s = NULL;
+
+ if (read_string(a, tree, hf_ldap_message_search_base, 0, &s, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Base DN=%s", s != NULL ? s : "(null)");
+ g_free(s);
+
+ if (read_integer(a, tree, hf_ldap_message_search_scope, 0, 0, ASN1_ENUM) != ASN1_ERR_NOERROR)
+ return;
+ if (read_integer(a, tree, hf_ldap_message_search_deref, 0, 0, ASN1_ENUM) != ASN1_ERR_NOERROR)
+ return;
+ if (read_integer(a, tree, hf_ldap_message_search_sizeLimit, 0, 0, ASN1_INT) != ASN1_ERR_NOERROR)
+ return;
+ if (read_integer(a, tree, hf_ldap_message_search_timeLimit, 0, 0, ASN1_INT) != ASN1_ERR_NOERROR)
+ return;
+ if (read_boolean(a, tree, hf_ldap_message_search_typesOnly, 0, 0) != ASN1_ERR_NOERROR)
+ return;
+ if (!read_filter(a, tree, hf_ldap_message_search_filter))
+ return;
+ ret = read_sequence(a, &seq_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse LDAP attribute sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+ end = a->offset + seq_length;
+ while (a->offset < end) {
+ if (read_string(a, tree, hf_ldap_message_attribute, 0, 0, 0, ASN1_UNI,
+ ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ }
+}
+
+static int dissect_mscldap_string(tvbuff_t *tvb, int offset, char *str, int maxlen, gboolean prepend_dot)
+{
+ guint8 len;
+
+ len=tvb_get_guint8(tvb, offset);
+ offset+=1;
+ *str=0;
+
+ while(len){
+ /* add potential field separation dot */
+ if(prepend_dot){
+ if(!maxlen){
+ *str=0;
+ return offset;
+ }
+ maxlen--;
+ *str++='.';
+ *str=0;
+ }
+
+ if(len==0xc0){
+ int new_offset;
+ /* ops its a mscldap compressed string */
+
+ new_offset=tvb_get_guint8(tvb, offset);
+ offset+=1;
+
+ dissect_mscldap_string(tvb, new_offset, str, maxlen, FALSE);
+
+ return offset;
+ }
+
+ prepend_dot=TRUE;
+
+ if(maxlen<=len){
+ if(maxlen>3){
+ *str++='.';
+ *str++='.';
+ *str++='.';
+ }
+ *str=0;
+ return offset; /* will mess up offset in caller, is unlikely */
+ }
+ tvb_memcpy(tvb, str, offset, len);
+ str+=len;
+ *str=0;
+ maxlen-=len;
+ offset+=len;
+
+
+ len=tvb_get_guint8(tvb, offset);
+ offset+=1;
+ }
+ *str=0;
+ return offset;
+}
+
+
+/* These flag bits were found to be defined in the samba sources.
+ * I hope they are correct (but have serious doubts about the CLOSEST
+ * bit being used or being meaningful).
+ */
+static const true_false_string tfs_ads_pdc = {
+ "This is a PDC",
+ "This is NOT a pdc"
+};
+static const true_false_string tfs_ads_gc = {
+ "This is a GLOBAL CATALOGUE of forest",
+ "This is NOT a global catalog of forest"
+};
+static const true_false_string tfs_ads_ldap = {
+ "This is an LDAP server",
+ "This is NOT an ldap server"
+};
+static const true_false_string tfs_ads_ds = {
+ "This dc supports DS",
+ "This dc does NOT support ds"
+};
+static const true_false_string tfs_ads_kdc = {
+ "This is a KDC (kerberos)",
+ "This is NOT a kdc (kerberos)"
+};
+static const true_false_string tfs_ads_timeserv = {
+ "This dc is running TIME SERVICES (ntp)",
+ "This dc is NOT running time services (ntp)"
+};
+static const true_false_string tfs_ads_closest = {
+ "This is the CLOSEST dc (unreliable?)",
+ "This is NOT the closest dc"
+};
+static const true_false_string tfs_ads_writable = {
+ "This dc is WRITABLE",
+ "This dc is NOT writable"
+};
+static const true_false_string tfs_ads_good_timeserv = {
+ "This dc has a GOOD TIME SERVICE (i.e. hardware clock)",
+ "This dc does NOT have a good time service (i.e. no hardware clock)"
+};
+static const true_false_string tfs_ads_ndnc = {
+ "Domain is NON-DOMAIN NC serviced by ldap server",
+ "Domain is NOT non-domain nc serviced by ldap server"
+};
+static int dissect_mscldap_netlogon_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
+{
+ guint32 flags;
+ proto_item *item;
+ proto_tree *tree=NULL;
+
+ flags=tvb_get_letohl(tvb, offset);
+ item=proto_tree_add_item(parent_tree, hf_mscldap_netlogon_flags, tvb, offset, 4, TRUE);
+ if(parent_tree){
+ tree = proto_item_add_subtree(item, ett_mscldap_netlogon_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_ndnc,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_good_timeserv,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_writable,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_closest,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_timeserv,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_kdc,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_ds,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_ldap,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_gc,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_mscldap_netlogon_flags_pdc,
+ tvb, offset, 4, flags);
+
+ offset += 4;
+
+ return offset;
+}
+
+static void dissect_mscldap_response_netlogon(proto_tree *tree, tvbuff_t *tvb)
+{
+ int old_offset, offset=0;
+ char str[256];
+
+/*qqq*/
+
+ /* Type */
+ /*XXX someone that knows what the type means should add that knowledge here*/
+ proto_tree_add_item(tree, hf_mscldap_netlogon_type, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* Flags */
+ offset = dissect_mscldap_netlogon_flags(tree, tvb, offset);
+
+ /* Domain GUID */
+ proto_tree_add_item(tree, hf_mscldap_domain_guid, tvb, offset, 16, TRUE);
+ offset += 16;
+
+ /* Forest */
+ old_offset=offset;
+ offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
+ proto_tree_add_string(tree, hf_mscldap_forest, tvb, old_offset, offset-old_offset, str);
+
+ /* Domain */
+ old_offset=offset;
+ offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
+ proto_tree_add_string(tree, hf_mscldap_domain, tvb, old_offset, offset-old_offset, str);
+
+ /* Hostname */
+ old_offset=offset;
+ offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
+ proto_tree_add_string(tree, hf_mscldap_hostname, tvb, old_offset, offset-old_offset, str);
+
+ /* NetBios Domain */
+ old_offset=offset;
+ offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
+ proto_tree_add_string(tree, hf_mscldap_nb_domain, tvb, old_offset, offset-old_offset, str);
+
+ /* NetBios Hostname */
+ old_offset=offset;
+ offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
+ proto_tree_add_string(tree, hf_mscldap_nb_hostname, tvb, old_offset, offset-old_offset, str);
+
+ /* User */
+ old_offset=offset;
+ offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
+ proto_tree_add_string(tree, hf_mscldap_username, tvb, old_offset, offset-old_offset, str);
+
+ /* Site */
+ old_offset=offset;
+ offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
+ proto_tree_add_string(tree, hf_mscldap_sitename, tvb, old_offset, offset-old_offset, str);
+
+ /* Client Site */
+ old_offset=offset;
+ offset=dissect_mscldap_string(tvb, offset, str, 255, FALSE);
+ proto_tree_add_string(tree, hf_mscldap_clientsitename, tvb, old_offset, offset-old_offset, str);
+
+ /* Version */
+ proto_tree_add_item(tree, hf_mscldap_netlogon_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LM Token */
+ proto_tree_add_item(tree, hf_mscldap_netlogon_lm_token, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* NT Token */
+ proto_tree_add_item(tree, hf_mscldap_netlogon_nt_token, tvb, offset, 2, TRUE);
+ offset += 2;
+
+}
+
+static void dissect_mscldap_response(proto_tree *tree, tvbuff_t *tvb, guint32 rpc)
+{
+ switch(rpc){
+ case MSCLDAP_RPC_NETLOGON:
+ dissect_mscldap_response_netlogon(tree, tvb);
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, 0, tvb_length(tvb),
+ "ERROR: Unknown type of MS-CLDAP RPC call");
+ }
+}
+
+
+static void dissect_ldap_response_search_entry(ASN1_SCK *a, proto_tree *tree,
+ gboolean is_mscldap)
+{
+ guint seq_length;
+ int end_of_sequence;
+ int ret;
+ char *str=NULL;
+ guint32 len;
+ guint32 mscldap_rpc;
+
+ if (read_string(a, tree, hf_ldap_message_dn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ ret = read_sequence(a, &seq_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse search entry response sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+
+ end_of_sequence = a->offset + seq_length;
+ while (a->offset < end_of_sequence)
+ {
+ proto_item *ti;
+ proto_tree *attr_tree;
+ guint set_length;
+ int end_of_set;
+
+ ret = read_sequence(a, 0);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse LDAP attribute sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+ if (read_string(a, tree, hf_ldap_message_attribute, &ti, &str, &len, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+
+ mscldap_rpc=0;
+ if(is_mscldap){
+ if(!strncmp(str, "netlogon", 8)){
+ mscldap_rpc=MSCLDAP_RPC_NETLOGON;
+ }
+ }
+ g_free(str);
+ str=NULL;
+
+
+ attr_tree = proto_item_add_subtree(ti, ett_ldap_attribute);
+
+ ret = read_set(a, &set_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(attr_tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse LDAP value set header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+ end_of_set = a->offset + set_length;
+ while (a->offset < end_of_set) {
+ if(!is_mscldap){
+ if (read_string(a, attr_tree, hf_ldap_message_value, 0, 0, 0, ASN1_UNI,
+ ASN1_OTS) != ASN1_ERR_NOERROR){
+ return;
+ }
+ } else {
+ guint cls, con, tag;
+ gboolean def;
+ guint len;
+ int start = a->offset;
+ int ret;
+ tvbuff_t *mscldap_tvb=NULL;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &len);
+ if (ret == ASN1_ERR_NOERROR) {
+ if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS)
+ ret = ASN1_ERR_WRONG_TYPE;
+ }
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ proto_registrar_get_name(hf_ldap_message_value), asn1_err_to_str(ret));
+ }
+ return;
+ }
+ mscldap_tvb=tvb_new_subset(a->tvb, a->offset, len, len);
+ dissect_mscldap_response(attr_tree, mscldap_tvb, mscldap_rpc);
+ a->offset+=len;
+ }
+
+ }
+ }
+}
+
+static void dissect_ldap_response_search_ref(ASN1_SCK *a, proto_tree *tree)
+{
+ read_string(a, tree, hf_ldap_message_search_reference, 0, 0, 0, ASN1_UNI, ASN1_OTS);
+}
+
+static void dissect_ldap_request_add(ASN1_SCK *a, proto_tree *tree, packet_info *pinfo)
+{
+ guint seq_length;
+ int end_of_sequence;
+ int ret;
+ char *s = NULL;
+
+ if (read_string(a, tree, hf_ldap_message_dn, 0, &s, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", DN=%s", s != NULL ? s : "(null)");
+ g_free(s);
+
+ ret = read_sequence(a, &seq_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse add request sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+
+ end_of_sequence = a->offset + seq_length;
+ while (a->offset < end_of_sequence)
+ {
+ proto_item *ti;
+ proto_tree *attr_tree;
+ guint set_length;
+ int end_of_set;
+
+ ret = read_sequence(a, 0);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse LDAP attribute sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+ if (read_string(a, tree, hf_ldap_message_attribute, &ti, 0, 0, ASN1_UNI,
+ ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ attr_tree = proto_item_add_subtree(ti, ett_ldap_attribute);
+
+ ret = read_set(a, &set_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(attr_tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse LDAP value set header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+ end_of_set = a->offset + set_length;
+ while (a->offset < end_of_set) {
+ if (read_string(a, attr_tree, hf_ldap_message_value, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ }
+ }
+}
+
+static void dissect_ldap_request_delete(ASN1_SCK *a, proto_tree *tree,
+ int start, guint length)
+{
+ read_string_value(a, tree, hf_ldap_message_dn, NULL, NULL, start, length);
+}
+
+static void dissect_ldap_request_modifyrdn(ASN1_SCK *a, proto_tree *tree,
+ guint length)
+{
+ int start = a->offset;
+
+ if (read_string(a, tree, hf_ldap_message_dn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ if (read_string(a, tree, hf_ldap_message_modrdn_name, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ if (read_boolean(a, tree, hf_ldap_message_modrdn_delete, 0, 0) != ASN1_ERR_NOERROR)
+ return;
+
+ if (a->offset < (int) (start + length)) {
+ /* LDAP V3 Modify DN operation, with newSuperior */
+ /* "newSuperior [0] LDAPDN OPTIONAL" (0x80) */
+ if (read_string(a, tree, hf_ldap_message_modrdn_superior, 0, 0, 0, ASN1_CTX, 0) != ASN1_ERR_NOERROR)
+ return;
+ }
+}
+
+static void dissect_ldap_request_compare(ASN1_SCK *a, proto_tree *tree)
+{
+ int start;
+ int length;
+ char *string1 = NULL;
+ char *string2 = NULL;
+ char *s1, *s2;
+ char *compare;
+ int ret;
+
+ if (read_string(a, tree, hf_ldap_message_dn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ ret = read_sequence(a, 0);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse compare request sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+
+ start = a->offset;
+ ret = read_string(a, 0, -1, 0, &string1, 0, ASN1_UNI, ASN1_OTS);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "ERROR: Couldn't parse compare type: %s", asn1_err_to_str(ret));
+ }
+ return;
+ }
+ ret = read_string(a, 0, -1, 0, &string2, 0, ASN1_UNI, ASN1_OTS);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "ERROR: Couldn't parse compare value: %s", asn1_err_to_str(ret));
+ }
+ return;
+ }
+
+ s1 = (string1 == NULL) ? "(null)" : string1;
+ s2 = (string2 == NULL) ? "(null)" : string2;
+ length = 2 + strlen(s1) + strlen(s2);
+ compare = g_malloc0(length);
+ snprintf(compare, length, "%s=%s", s1, s2);
+ proto_tree_add_string(tree, hf_ldap_message_compare, a->tvb, start,
+ a->offset-start, compare);
+
+ g_free(string1);
+ g_free(string2);
+ g_free(compare);
+
+ return;
+}
+
+static void dissect_ldap_request_modify(ASN1_SCK *a, proto_tree *tree)
+{
+ guint seq_length;
+ int end_of_sequence;
+ int ret;
+
+ if (read_string(a, tree, hf_ldap_message_dn, 0, 0, 0, ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ ret = read_sequence(a, &seq_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse modify request sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+ end_of_sequence = a->offset + seq_length;
+ while (a->offset < end_of_sequence)
+ {
+ proto_item *ti;
+ proto_tree *attr_tree;
+ guint set_length;
+ int end_of_set;
+ guint operation;
+
+ ret = read_sequence(a, 0);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse modify request item sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+ ret = read_integer(a, 0, -1, 0, &operation, ASN1_ENUM);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse modify operation: %s",
+ asn1_err_to_str(ret));
+ return;
+ }
+ }
+ ret = read_sequence(a, 0);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse modify request operation sequence header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+
+ switch (operation)
+ {
+ case LDAP_MOD_ADD:
+ if (read_string(a, tree, hf_ldap_message_modify_add, &ti, 0, 0, ASN1_UNI,
+ ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ break;
+
+ case LDAP_MOD_REPLACE:
+ if (read_string(a, tree, hf_ldap_message_modify_replace, &ti, 0, 0,
+ ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ break;
+
+ case LDAP_MOD_DELETE:
+ if (read_string(a, tree, hf_ldap_message_modify_delete, &ti, 0, 0,
+ ASN1_UNI, ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ break;
+
+ default:
+ proto_tree_add_text(tree, a->tvb, a->offset, 0,
+ "Unknown LDAP modify operation (%u)", operation);
+ return;
+ }
+ attr_tree = proto_item_add_subtree(ti, ett_ldap_attribute);
+
+ ret = read_set(a, &set_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ proto_tree_add_text(attr_tree, a->tvb, a->offset, 0,
+ "ERROR: Couldn't parse LDAP value set header: %s",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+ end_of_set = a->offset + set_length;
+ while (a->offset < end_of_set) {
+ if (read_string(a, attr_tree, hf_ldap_message_value, 0, 0, 0, ASN1_UNI,
+ ASN1_OTS) != ASN1_ERR_NOERROR)
+ return;
+ }
+ }
+}
+
+static void dissect_ldap_request_abandon(ASN1_SCK *a, proto_tree *tree,
+ int start, guint length)
+{
+ read_integer_value(a, tree, hf_ldap_message_abandon_msgid, NULL, NULL,
+ start, length);
+}
+
+static ldap_call_response_t *
+ldap_match_call_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ldap_conv_info_t *ldap_info, guint messageId, guint protocolOpTag)
+{
+ ldap_call_response_t lcr, *lcrp=NULL;
+
+ if (!pinfo->fd->flags.visited) {
+ switch(protocolOpTag){
+ case LDAP_REQ_BIND:
+ case LDAP_REQ_SEARCH:
+ case LDAP_REQ_MODIFY:
+ case LDAP_REQ_ADD:
+ case LDAP_REQ_DELETE:
+ case LDAP_REQ_MODRDN:
+ case LDAP_REQ_COMPARE:
+ /*case LDAP_REQ_ABANDON: we dont match for this one*/
+ /*case LDAP_REQ_UNBIND: we dont match for this one*/
+ /* check that we dont already have one of those in the
+ unmatched list and if so remove it */
+ lcr.messageId=messageId;
+ lcrp=g_hash_table_lookup(ldap_info->unmatched, &lcr);
+ if(lcrp){
+ g_hash_table_remove(ldap_info->unmatched, lcrp);
+ }
+ /* if we cant reuse the old one, grab a new chunk */
+ if(!lcrp){
+ lcrp=g_mem_chunk_alloc(ldap_call_response_chunk);
+ }
+ lcrp->messageId=messageId;
+ lcrp->req_frame=pinfo->fd->num;
+ lcrp->req_time.secs=pinfo->fd->abs_secs;
+ lcrp->req_time.nsecs=pinfo->fd->abs_usecs*1000;
+ lcrp->rep_frame=0;
+ lcrp->protocolOpTag=protocolOpTag;
+ lcrp->is_request=TRUE;
+ g_hash_table_insert(ldap_info->unmatched, lcrp, lcrp);
+ return NULL;
+ break;
+ case LDAP_RES_BIND:
+ case LDAP_RES_SEARCH_ENTRY:
+ case LDAP_RES_SEARCH_REF:
+ case LDAP_RES_SEARCH_RESULT:
+ case LDAP_RES_MODIFY:
+ case LDAP_RES_ADD:
+ case LDAP_RES_DELETE:
+ case LDAP_RES_MODRDN:
+ case LDAP_RES_COMPARE:
+ lcr.messageId=messageId;
+ lcrp=g_hash_table_lookup(ldap_info->unmatched, &lcr);
+ if(lcrp){
+ if(!lcrp->rep_frame){
+ g_hash_table_remove(ldap_info->unmatched, lcrp);
+ lcrp->rep_frame=pinfo->fd->num;
+ lcrp->is_request=FALSE;
+ g_hash_table_insert(ldap_info->matched, lcrp, lcrp);
+ }
+ }
+ }
+ }
+
+ if(!lcrp){
+ lcr.messageId=messageId;
+ switch(protocolOpTag){
+ case LDAP_REQ_BIND:
+ case LDAP_REQ_SEARCH:
+ case LDAP_REQ_MODIFY:
+ case LDAP_REQ_ADD:
+ case LDAP_REQ_DELETE:
+ case LDAP_REQ_MODRDN:
+ case LDAP_REQ_COMPARE:
+ /*case LDAP_REQ_ABANDON: we dont match for this one*/
+ /*case LDAP_REQ_UNBIND: we dont match for this one*/
+ lcr.is_request=TRUE;
+ lcr.req_frame=pinfo->fd->num;
+ lcr.rep_frame=0;
+ break;
+ case LDAP_RES_BIND:
+ case LDAP_RES_SEARCH_ENTRY:
+ case LDAP_RES_SEARCH_REF:
+ case LDAP_RES_SEARCH_RESULT:
+ case LDAP_RES_MODIFY:
+ case LDAP_RES_ADD:
+ case LDAP_RES_DELETE:
+ case LDAP_RES_MODRDN:
+ case LDAP_RES_COMPARE:
+ lcr.is_request=FALSE;
+ lcr.req_frame=0;
+ lcr.rep_frame=pinfo->fd->num;
+ break;
+ }
+ lcrp=g_hash_table_lookup(ldap_info->matched, &lcr);
+ if(lcrp){
+ lcrp->is_request=lcr.is_request;
+ }
+ }
+ if(lcrp){
+ if(lcrp->is_request){
+ proto_tree_add_uint(tree, hf_ldap_response_in, tvb, 0, 0, lcrp->rep_frame);
+ } else {
+ nstime_t ns;
+ proto_tree_add_uint(tree, hf_ldap_response_to, tvb, 0, 0, lcrp->req_frame);
+ ns.secs=pinfo->fd->abs_secs-lcrp->req_time.secs;
+ ns.nsecs=pinfo->fd->abs_usecs*1000-lcrp->req_time.nsecs;
+ if(ns.nsecs<0){
+ ns.nsecs+=1000000000;
+ ns.secs--;
+ }
+ proto_tree_add_time(tree, hf_ldap_time, tvb, 0, 0, &ns);
+ }
+ return lcrp;
+ }
+ return NULL;
+}
+
+
+static void
+dissect_ldap_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *ldap_tree, proto_item *ldap_item,
+ gboolean first_time, ldap_conv_info_t *ldap_info,
+ gboolean is_mscldap)
+{
+ int message_id_start;
+ int message_id_length;
+ guint messageLength;
+ guint messageId;
+ int next_offset;
+ guint protocolOpCls, protocolOpCon, protocolOpTag;
+ gchar *typestr;
+ guint opLen;
+ ASN1_SCK a;
+ int start;
+ int ret;
+ ldap_call_response_t *lcrp;
+
+ asn1_open(&a, tvb, offset);
+
+ ret = read_sequence(&a, &messageLength);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (first_time)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Invalid LDAP message (Can't parse sequence header: %s)",
+ asn1_err_to_str(ret));
+ }
+ }
+ if (ldap_tree)
+ {
+ proto_tree_add_text(ldap_tree, tvb, offset, -1,
+ "Invalid LDAP message (Can't parse sequence header: %s)",
+ asn1_err_to_str(ret));
+ }
+ return;
+ }
+
+ message_id_start = a.offset;
+ ret = read_integer(&a, 0, hf_ldap_message_id, 0, &messageId, ASN1_INT);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (first_time && check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Invalid LDAP packet (Can't parse Message ID: %s)",
+ asn1_err_to_str(ret));
+ if (ldap_tree)
+ proto_tree_add_text(ldap_tree, tvb, message_id_start, 1,
+ "Invalid LDAP packet (Can't parse Message ID: %s)",
+ asn1_err_to_str(ret));
+ return;
+ }
+ message_id_length = a.offset - message_id_start;
+
+ start = a.offset;
+ asn1_id_decode(&a, &protocolOpCls, &protocolOpCon, &protocolOpTag);
+ if (protocolOpCls != ASN1_APL)
+ typestr = "Bad message type (not Application)";
+ else
+ typestr = val_to_str(protocolOpTag, msgTypes, "Unknown message type (%u)");
+
+ if (first_time)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "MsgId=%u %s",
+ messageId, typestr);
+ }
+
+ if (ldap_item)
+ proto_item_append_text(ldap_item, ", %s",
+ val_to_str(protocolOpTag, msgTypes,
+ "Unknown message type (%u)"));
+
+ if (ldap_tree)
+ {
+ proto_tree_add_uint(ldap_tree, hf_ldap_message_id, tvb, message_id_start, message_id_length, messageId);
+ if (protocolOpCls == ASN1_APL)
+ {
+ proto_tree_add_uint(ldap_tree, hf_ldap_message_type, tvb,
+ start, a.offset - start, protocolOpTag);
+ }
+ else
+ {
+ proto_tree_add_text(ldap_tree, tvb, start, a.offset - start,
+ "%s", typestr);
+ }
+ }
+ start = a.offset;
+ if (read_length(&a, ldap_tree, hf_ldap_message_length, &opLen) != ASN1_ERR_NOERROR)
+ return;
+
+ if (protocolOpCls == ASN1_APL)
+ {
+ lcrp=ldap_match_call_response(tvb, pinfo, ldap_tree, ldap_info, messageId, protocolOpTag);
+ if(lcrp){
+ tap_queue_packet(ldap_tap, pinfo, lcrp);
+ }
+
+ switch (protocolOpTag)
+ {
+ case LDAP_REQ_BIND:
+ dissect_ldap_request_bind(&a, ldap_tree, tvb, pinfo, ldap_info);
+ break;
+ case LDAP_REQ_UNBIND:
+ /* Nothing to dissect */
+ break;
+ case LDAP_REQ_SEARCH:
+ dissect_ldap_request_search(&a, ldap_tree, pinfo);
+ break;
+ case LDAP_REQ_MODIFY:
+ dissect_ldap_request_modify(&a, ldap_tree);
+ break;
+ case LDAP_REQ_ADD:
+ dissect_ldap_request_add(&a, ldap_tree, pinfo);
+ break;
+ case LDAP_REQ_DELETE:
+ dissect_ldap_request_delete(&a, ldap_tree, start, opLen);
+ break;
+ case LDAP_REQ_MODRDN:
+ dissect_ldap_request_modifyrdn(&a, ldap_tree, opLen);
+ break;
+ case LDAP_REQ_COMPARE:
+ dissect_ldap_request_compare(&a, ldap_tree);
+ break;
+ case LDAP_REQ_ABANDON:
+ dissect_ldap_request_abandon(&a, ldap_tree, start, opLen);
+ break;
+ case LDAP_RES_BIND:
+ dissect_ldap_response_bind(&a, ldap_tree, start, opLen, tvb, pinfo, ldap_info);
+ break;
+ case LDAP_RES_SEARCH_ENTRY: {
+ /*
+ * XXX - this assumes that the LDAP_RES_SEARCH_ENTRY and
+ * LDAP_RES_SEARCH_RESULT appear in the same frame.
+ */
+ guint32 *num_results = p_get_proto_data(pinfo->fd, proto_ldap);
+
+ if (!num_results) {
+ num_results = g_malloc(sizeof(guint32));
+ *num_results = 0;
+ p_add_proto_data(pinfo->fd, proto_ldap, num_results);
+ }
+
+ *num_results += 1;
+ dissect_ldap_response_search_entry(&a, ldap_tree, is_mscldap);
+
+ break;
+ }
+ case LDAP_RES_SEARCH_REF:
+ dissect_ldap_response_search_ref(&a, ldap_tree);
+ break;
+
+ case LDAP_RES_SEARCH_RESULT: {
+ guint32 *num_results = p_get_proto_data(pinfo->fd, proto_ldap);
+
+ if (num_results) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %d result%s",
+ *num_results, *num_results == 1 ? "" : "s");
+ g_free(num_results);
+ p_rem_proto_data(pinfo->fd, proto_ldap);
+ }
+
+ dissect_ldap_result(&a, ldap_tree, pinfo);
+
+ break;
+ }
+
+ case LDAP_RES_MODIFY:
+ case LDAP_RES_ADD:
+ case LDAP_RES_DELETE:
+ case LDAP_RES_MODRDN:
+ case LDAP_RES_COMPARE:
+ dissect_ldap_result(&a, ldap_tree, pinfo);
+ break;
+ default:
+ if (ldap_tree)
+ {
+ proto_tree_add_text(ldap_tree, a.tvb, a.offset, opLen,
+ "Unknown LDAP operation (%u)", protocolOpTag);
+ }
+ break;
+ }
+ }
+
+ /*
+ * XXX - what if "next_offset" is past the offset of the next top-level
+ * sequence? Show that as an error?
+ */
+ asn1_close(&a, &next_offset); /* XXX - use the new value of next_offset? */
+}
+
+
+static void
+dissect_ldap_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_mscldap)
+{
+ int offset = 0;
+ gboolean first_time = TRUE;
+ conversation_t *conversation;
+ gboolean doing_sasl_security = FALSE;
+ guint length_remaining;
+ guint32 sasl_length;
+ guint32 message_data_len;
+ proto_item *ti = NULL;
+ proto_tree *ldap_tree = NULL;
+ ASN1_SCK a;
+ int ret;
+ guint messageLength;
+ int messageOffset;
+ guint headerLength;
+ guint length;
+ gint available_length, reported_length;
+ int len;
+ proto_item *gitem = NULL;
+ proto_tree *gtree = NULL;
+ tvbuff_t *next_tvb;
+ ldap_conv_info_t *ldap_info=NULL;
+
+
+ /*
+ * Do we have a conversation for this connection?
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (conversation == NULL) {
+ /* We don't yet have a conversation, so create one. */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ /*
+ * Do we already have a type and mechanism?
+ */
+ ldap_info = conversation_get_proto_data(conversation, proto_ldap);
+ if (ldap_info == NULL) {
+ /* No. Attach that information to the conversation, and add
+ it to the list of information structures. */
+ ldap_info = g_mem_chunk_alloc(ldap_conv_info_chunk);
+ ldap_info->auth_type = 0;
+ ldap_info->auth_mech = 0;
+ ldap_info->first_auth_frame = 0;
+ ldap_info->matched=g_hash_table_new(ldap_info_hash_matched, ldap_info_equal_matched);
+ ldap_info->unmatched=g_hash_table_new(ldap_info_hash_unmatched, ldap_info_equal_unmatched);
+ conversation_add_proto_data(conversation, proto_ldap, ldap_info);
+ ldap_info->next = ldap_info_items;
+ ldap_info_items = ldap_info;
+ }
+
+ switch (ldap_info->auth_type) {
+ case LDAP_AUTH_SASL:
+ /*
+ * It's SASL; are we using a security layer?
+ */
+ if (ldap_info->first_auth_frame != 0 &&
+ pinfo->fd->num >= ldap_info->first_auth_frame)
+ doing_sasl_security = TRUE; /* yes */
+ }
+
+
+
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ /*
+ * This will throw an exception if we don't have any data left.
+ * That's what we want. (See "tcp_dissect_pdus()", which is
+ * similar, but doesn't have to deal with the SASL issues.
+ * XXX - can we make "tcp_dissect_pdus()" provide enough information
+ * to the "get_pdu_len" routine so that we could have one dealing
+ * with the SASL issues, have that routine deal with SASL and
+ * ASN.1, and just use "tcp_dissect_pdus()"?)
+ */
+ length_remaining = tvb_ensure_length_remaining(tvb, offset);
+
+ /*
+ * Might we be doing a SASL security layer and, if so, *are* we doing
+ * one?
+ *
+ * Just because we've seen a bind reply for SASL, that doesn't mean
+ * that we're using a SASL security layer; I've seen captures in
+ * which some SASL negotiations lead to a security layer being used
+ * and other negotiations don't, and it's not obvious what's different
+ * in the two negotiations. Therefore, we assume that if the first
+ * byte is 0, it's a length for a SASL security layer (that way, we
+ * never reassemble more than 16 megabytes, protecting us from
+ * chewing up *too* much memory), and otherwise that it's an LDAP
+ * message (actually, if it's an LDAP message it should begin with 0x30,
+ * but we want to parse garbage as LDAP messages rather than really
+ * huge lengths).
+ */
+ if (doing_sasl_security && tvb_get_guint8(tvb, offset) == 0) {
+ /*
+ * Yes. The frame begins with a 4-byte big-endian length.
+ * Can we do reassembly?
+ */
+ if (ldap_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the SASL length split across segment boundaries?
+ */
+ if (length_remaining < 4) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this message
+ * starts in the data it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4 - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Get the SASL length, which is the length of data in the buffer
+ * following the length (i.e., it's 4 less than the total length).
+ *
+ * XXX - do we need to reassemble buffers? For now, we
+ * assume that each LDAP message is entirely contained within
+ * a buffer.
+ */
+ sasl_length = tvb_get_ntohl(tvb, offset);
+ message_data_len = sasl_length + 4;
+ if (message_data_len < 4) {
+ /*
+ * The message length was probably so large that the total length
+ * overflowed.
+ *
+ * Report this as an error.
+ */
+ show_reported_bounds_error(tvb, pinfo, tree);
+ return;
+ }
+
+ /*
+ * Is the buffer split across segment boundaries?
+ */
+ if (length_remaining < message_data_len) {
+ /* provide a hint to TCP where the next PDU starts */
+ pinfo->want_pdu_tracking=2;
+ pinfo->bytes_until_next_pdu=message_data_len-length_remaining;
+ /*
+ * Can we do reassembly?
+ */
+ if (ldap_desegment && pinfo->can_desegment) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this message
+ * starts in the data it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = message_data_len - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload we have
+ * available. Make its reported length the amount of data in the PDU.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector will throw a
+ * BoundsError exception, rather than a ReportedBoundsError exception.
+ * We really want a tvbuff where the length is "length", the reported
+ * length is "plen", and the "if the snapshot length were infinite"
+ * length is the minimum of the reported length of the tvbuff handed
+ * to us and "plen", with a new type of exception thrown if the offset
+ * is within the reported length but beyond that third length, with
+ * that exception getting the "Unreassembled Packet" error.
+ */
+ length = length_remaining;
+ if (length > message_data_len)
+ length = message_data_len;
+ next_tvb = tvb_new_subset(tvb, offset, length, message_data_len);
+
+ /*
+ * If this is the first PDU, set the Protocol column and clear the
+ * Info column.
+ */
+ if (first_time)
+ {
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, (gchar *)pinfo->current_proto);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_ldap, next_tvb, 0, -1, FALSE);
+ ldap_tree = proto_item_add_subtree(ti, ett_ldap);
+
+ proto_tree_add_uint(ldap_tree, hf_ldap_sasl_buffer_length, tvb, 0, 4,
+ sasl_length);
+ }
+
+ if (ldap_info->auth_mech != NULL &&
+ strcmp(ldap_info->auth_mech, "GSS-SPNEGO") == 0) {
+ /*
+ * This is GSS-API (using SPNEGO, but we should be done with
+ * the negotiation by now).
+ *
+ * Dissect the GSS_Wrap() token; it'll return the length of
+ * the token, from which we compute the offset in the tvbuff at
+ * which the plaintext data, i.e. the LDAP message, begins.
+ */
+ available_length = tvb_length_remaining(tvb, 4);
+ reported_length = tvb_reported_length_remaining(tvb, 4);
+ g_assert(available_length >= 0);
+ g_assert(reported_length >= 0);
+ if (available_length > reported_length)
+ available_length = reported_length;
+ if ((guint)available_length > sasl_length - 4)
+ available_length = sasl_length - 4;
+ if ((guint)reported_length > sasl_length - 4)
+ reported_length = sasl_length - 4;
+ next_tvb = tvb_new_subset(tvb, 4, available_length, reported_length);
+ if (tree)
+ {
+ gitem = proto_tree_add_text(ldap_tree, next_tvb, 0, -1, "GSS-API Token");
+ gtree = proto_item_add_subtree(gitem, ett_ldap_gssapi_token);
+ }
+ len = call_dissector(gssapi_wrap_handle, next_tvb, pinfo, gtree);
+ /*
+ * if len is 0 it probably mean that we got a PDU that is not
+ * aligned to the start of the segment.
+ */
+ if(len==0){
+ return;
+ }
+ if (gitem != NULL)
+ proto_item_set_len(gitem, len);
+
+ /*
+ * Now dissect the LDAP message.
+ */
+ dissect_ldap_message(tvb, 4 + len, pinfo, ldap_tree, ti, first_time, ldap_info, is_mscldap);
+ } else {
+ /*
+ * We don't know how to handle other authentication mechanisms
+ * yet, so just put in an entry for the SASL buffer.
+ */
+ proto_tree_add_text(ldap_tree, tvb, 4, -1, "SASL buffer");
+ }
+ offset += message_data_len;
+ } else {
+ /*
+ * No, we're not doing a SASL security layer. The frame begins
+ * with a "Sequence Of" header.
+ * Can we do reassembly?
+ */
+ if (ldap_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the "Sequence Of" header split across segment
+ * boundaries? We require at least 6 bytes for the header
+ * which allows for a 4 byte length (ASN.1 BER).
+ */
+ if (length_remaining < 6) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 6 - length_remaining;
+ return;
+ }
+ }
+
+ /* It might still be a packet containing a SASL security layer
+ * but its just that we never saw the BIND packet.
+ * check if it looks like it could be a SASL blob here
+ * and in that case just assume it is GSS-SPNEGO
+ */
+ if( (tvb_bytes_exist(tvb, offset, 5))
+ &&(tvb_get_ntohl(tvb, offset)<=(guint)(tvb_reported_length_remaining(tvb, offset)-4))
+ &&(tvb_get_guint8(tvb, offset+4)==0x60) ){
+ ldap_info->auth_type=LDAP_AUTH_SASL;
+ ldap_info->first_auth_frame=pinfo->fd->num;
+ ldap_info->auth_mech=g_strdup("GSS-SPNEGO");
+ doing_sasl_security=TRUE;
+ continue;
+ }
+
+
+ /*
+ * OK, try to read the "Sequence Of" header; this gets the total
+ * length of the LDAP message.
+ */
+ asn1_open(&a, tvb, offset);
+ ret = read_sequence(&a, &messageLength);
+ asn1_close(&a, &messageOffset);
+
+ if (ret == ASN1_ERR_NOERROR) {
+ /*
+ * Add the length of the "Sequence Of" header to the message
+ * length.
+ */
+ headerLength = messageOffset - offset;
+ messageLength += headerLength;
+ if (messageLength < headerLength) {
+ /*
+ * The message length was probably so large that the total length
+ * overflowed.
+ *
+ * Report this as an error.
+ */
+ show_reported_bounds_error(tvb, pinfo, tree);
+ return;
+ }
+ } else {
+ /*
+ * We couldn't parse the header; just make it the amount of data
+ * remaining in the tvbuff, so we'll give up on this segment
+ * after attempting to parse the message - there's nothing more
+ * we can do. "dissect_ldap_message()" will display the error.
+ */
+ messageLength = length_remaining;
+ }
+
+ /*
+ * Is the message split across segment boundaries?
+ */
+ if (length_remaining < messageLength) {
+ /* provide a hint to TCP where the next PDU starts */
+ pinfo->want_pdu_tracking=2;
+ pinfo->bytes_until_next_pdu=messageLength-length_remaining;
+ /*
+ * Can we do reassembly?
+ */
+ if (ldap_desegment && pinfo->can_desegment) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this message
+ * starts in the data it handed us, and how many more bytes
+ * we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = messageLength - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * If this is the first PDU, set the Protocol column and clear the
+ * Info column.
+ */
+ if (first_time) {
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, (gchar *)pinfo->current_proto);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload we have
+ * available. Make its reported length the amount of data in the
+ * LDAP message.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector will throw a
+ * BoundsError exception, rather than a ReportedBoundsError exception.
+ * We really want a tvbuff where the length is "length", the reported
+ * length is "plen", and the "if the snapshot length were infinite"
+ * length is the minimum of the reported length of the tvbuff handed
+ * to us and "plen", with a new type of exception thrown if the offset
+ * is within the reported length but beyond that third length, with
+ * that exception getting the "Unreassembled Packet" error.
+ */
+ length = length_remaining;
+ if (length > messageLength)
+ length = messageLength;
+ next_tvb = tvb_new_subset(tvb, offset, length, messageLength);
+
+ /*
+ * Now dissect the LDAP message.
+ */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ldap, next_tvb, 0, -1, FALSE);
+ ldap_tree = proto_item_add_subtree(ti, ett_ldap);
+ } else
+ ldap_tree = NULL;
+ dissect_ldap_message(next_tvb, 0, pinfo, ldap_tree, ti, first_time, ldap_info, is_mscldap);
+
+ offset += messageLength;
+ }
+
+ first_time = FALSE;
+ }
+}
+
+
+
+static void
+dissect_ldap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_ldap_pdu(tvb, pinfo, tree, FALSE);
+ return;
+}
+
+static void
+dissect_mscldap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_ldap_pdu(tvb, pinfo, tree, TRUE);
+ return;
+}
+
+static void
+ldap_reinit(void)
+{
+ ldap_conv_info_t *ldap_info;
+
+ /* Free up state attached to the ldap_info structures */
+ for (ldap_info = ldap_info_items; ldap_info != NULL; ldap_info = ldap_info->next) {
+ if (ldap_info->auth_mech != NULL) {
+ g_free(ldap_info->auth_mech);
+ ldap_info->auth_mech=NULL;
+ }
+ g_hash_table_destroy(ldap_info->matched);
+ ldap_info->matched=NULL;
+ g_hash_table_destroy(ldap_info->unmatched);
+ ldap_info->unmatched=NULL;
+ }
+
+ if (ldap_conv_info_chunk != NULL)
+ g_mem_chunk_destroy(ldap_conv_info_chunk);
+
+ ldap_info_items = NULL;
+
+ ldap_conv_info_chunk = g_mem_chunk_new("ldap_conv_info_chunk",
+ sizeof(ldap_conv_info_t),
+ ldap_conv_info_chunk_count * sizeof(ldap_conv_info_t),
+ G_ALLOC_ONLY);
+
+ if (ldap_call_response_chunk != NULL)
+ g_mem_chunk_destroy(ldap_call_response_chunk);
+
+ ldap_call_response_chunk = g_mem_chunk_new("ldap_call_response_chunk",
+ sizeof(ldap_call_response_t),
+ ldap_call_response_chunk_count * sizeof(ldap_call_response_t),
+ G_ALLOC_ONLY);
+}
+
+void
+proto_register_ldap(void)
+{
+ static value_string auth_types[] = {
+ {LDAP_AUTH_SIMPLE, "Simple"},
+ {LDAP_AUTH_KRBV4LDAP, "Kerberos V4 to the LDAP server"},
+ {LDAP_AUTH_KRBV4DSA, "Kerberos V4 to the DSA"},
+ {LDAP_AUTH_SASL, "SASL"},
+ {0, NULL},
+ };
+
+ static value_string search_scope[] = {
+ {0x00, "Base"},
+ {0x01, "Single"},
+ {0x02, "Subtree"},
+ {0x00, NULL},
+ };
+
+ static value_string search_dereference[] = {
+ {0x00, "Never"},
+ {0x01, "Searching"},
+ {0x02, "Base Object"},
+ {0x03, "Always"},
+ {0x00, NULL},
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_ldap_response_in,
+ { "Response In", "ldap.response_in",
+ FT_FRAMENUM, BASE_DEC, NULL, 0x0,
+ "The response to this packet is in this frame", HFILL }},
+
+ { &hf_ldap_response_to,
+ { "Response To", "ldap.response_to",
+ FT_FRAMENUM, BASE_DEC, NULL, 0x0,
+ "This is a response to the LDAP command in this frame", HFILL }},
+
+ { &hf_ldap_time,
+ { "Time", "ldap.time",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
+ "The time between the Call and the Reply", HFILL }},
+
+ { &hf_ldap_sasl_buffer_length,
+ { "SASL Buffer Length", "ldap.sasl_buffer_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SASL Buffer Length", HFILL }},
+
+ { &hf_ldap_length,
+ { "Length", "ldap.length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LDAP Length", HFILL }},
+
+ { &hf_ldap_message_id,
+ { "Message Id", "ldap.message_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LDAP Message Id", HFILL }},
+ { &hf_ldap_message_type,
+ { "Message Type", "ldap.message_type",
+ FT_UINT8, BASE_HEX, &msgTypes, 0x0,
+ "LDAP Message Type", HFILL }},
+ { &hf_ldap_message_length,
+ { "Message Length", "ldap.message_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LDAP Message Length", HFILL }},
+
+ { &hf_ldap_message_result,
+ { "Result Code", "ldap.result.code",
+ FT_UINT8, BASE_HEX, result_codes, 0x0,
+ "LDAP Result Code", HFILL }},
+ { &hf_ldap_message_result_matcheddn,
+ { "Matched DN", "ldap.result.matcheddn",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Result Matched DN", HFILL }},
+ { &hf_ldap_message_result_errormsg,
+ { "Error Message", "ldap.result.errormsg",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Result Error Message", HFILL }},
+ { &hf_ldap_message_result_referral,
+ { "Referral", "ldap.result.referral",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Result Referral URL", HFILL }},
+
+ { &hf_ldap_message_bind_version,
+ { "Version", "ldap.bind.version",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LDAP Bind Version", HFILL }},
+ { &hf_ldap_message_bind_dn,
+ { "DN", "ldap.bind.dn",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Bind Distinguished Name", HFILL }},
+ { &hf_ldap_message_bind_auth,
+ { "Auth Type", "ldap.bind.auth_type",
+ FT_UINT8, BASE_HEX, auth_types, 0x0,
+ "LDAP Bind Auth Type", HFILL }},
+ { &hf_ldap_message_bind_auth_password,
+ { "Password", "ldap.bind.password",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Bind Password", HFILL }},
+ { &hf_ldap_message_bind_auth_mechanism,
+ { "Mechanism", "ldap.bind.mechanism",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Bind Mechanism", HFILL }},
+ { &hf_ldap_message_bind_auth_credentials,
+ { "Credentials", "ldap.bind.credentials",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "LDAP Bind Credentials", HFILL }},
+ { &hf_ldap_message_bind_server_credentials,
+ { "Server Credentials", "ldap.bind.server_credentials",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "LDAP Bind Server Credentials", HFILL }},
+
+ { &hf_ldap_message_search_base,
+ { "Base DN", "ldap.search.basedn",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Search Base Distinguished Name", HFILL }},
+ { &hf_ldap_message_search_scope,
+ { "Scope", "ldap.search.scope",
+ FT_UINT8, BASE_HEX, search_scope, 0x0,
+ "LDAP Search Scope", HFILL }},
+ { &hf_ldap_message_search_deref,
+ { "Dereference", "ldap.search.dereference",
+ FT_UINT8, BASE_HEX, search_dereference, 0x0,
+ "LDAP Search Dereference", HFILL }},
+ { &hf_ldap_message_search_sizeLimit,
+ { "Size Limit", "ldap.search.sizelimit",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LDAP Search Size Limit", HFILL }},
+ { &hf_ldap_message_search_timeLimit,
+ { "Time Limit", "ldap.search.timelimit",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LDAP Search Time Limit", HFILL }},
+ { &hf_ldap_message_search_typesOnly,
+ { "Attributes Only", "ldap.search.typesonly",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "LDAP Search Attributes Only", HFILL }},
+ { &hf_ldap_message_search_filter,
+ { "Filter", "ldap.search.filter",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Search Filter", HFILL }},
+ { &hf_ldap_message_search_reference,
+ { "Reference URL", "ldap.search.reference",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Search Reference URL", HFILL }},
+ { &hf_ldap_message_dn,
+ { "Distinguished Name", "ldap.dn",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Distinguished Name", HFILL }},
+ { &hf_ldap_message_attribute,
+ { "Attribute", "ldap.attribute",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Attribute", HFILL }},
+ /*
+ * XXX - not all LDAP values are text strings; we'd need a file
+ * describing which values (by name) are text strings and which are
+ * binary.
+ *
+ * Some values that are, at least in Microsoft's schema, binary
+ * are:
+ *
+ * invocationId
+ * nTSecurityDescriptor
+ * objectGUID
+ */
+ { &hf_ldap_message_value,
+ { "Value", "ldap.value",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Value", HFILL }},
+
+ { &hf_ldap_message_modrdn_name,
+ { "New Name", "ldap.modrdn.name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP New Name", HFILL }},
+ { &hf_ldap_message_modrdn_delete,
+ { "Delete Values", "ldap.modrdn.delete",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "LDAP Modify RDN - Delete original values", HFILL }},
+ { &hf_ldap_message_modrdn_superior,
+ { "New Location", "ldap.modrdn.superior",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Modify RDN - New Location", HFILL }},
+
+ { &hf_ldap_message_compare,
+ { "Test", "ldap.compare.test",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Compare Test", HFILL }},
+
+ { &hf_ldap_message_modify_add,
+ { "Add", "ldap.modify.add",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Add", HFILL }},
+ { &hf_ldap_message_modify_replace,
+ { "Replace", "ldap.modify.replace",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Replace", HFILL }},
+ { &hf_ldap_message_modify_delete,
+ { "Delete", "ldap.modify.delete",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LDAP Delete", HFILL }},
+
+ { &hf_ldap_message_abandon_msgid,
+ { "Abandon Msg Id", "ldap.abandon.msgid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LDAP Abandon Msg Id", HFILL }},
+
+ { &hf_mscldap_netlogon_type,
+ { "Type", "mscldap.netlogon.type",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Type of <please tell ethereal developers what this type is>", HFILL }},
+
+ { &hf_mscldap_netlogon_version,
+ { "Version", "mscldap.netlogon.version",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Version of <please tell ethereal developers what this type is>", HFILL }},
+
+ { &hf_mscldap_netlogon_lm_token,
+ { "LM Token", "mscldap.netlogon.lm_token",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "LM Token", HFILL }},
+
+ { &hf_mscldap_netlogon_nt_token,
+ { "NT Token", "mscldap.netlogon.nt_token",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "NT Token", HFILL }},
+
+ { &hf_mscldap_netlogon_flags,
+ { "Flags", "mscldap.netlogon.flags",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Netlogon flags describing the DC properties", HFILL }},
+
+ { &hf_mscldap_domain_guid,
+ { "Domain GUID", "mscldap.domain.guid",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Domain GUID", HFILL }},
+
+ { &hf_mscldap_forest,
+ { "Forest", "mscldap.forest",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Forest", HFILL }},
+
+ { &hf_mscldap_domain,
+ { "Domain", "mscldap.domain",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Domainname", HFILL }},
+
+ { &hf_mscldap_hostname,
+ { "Hostname", "mscldap.hostname",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Hostname", HFILL }},
+
+ { &hf_mscldap_nb_domain,
+ { "NetBios Domain", "mscldap.nb_domain",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "NetBios Domainname", HFILL }},
+
+ { &hf_mscldap_nb_hostname,
+ { "NetBios Hostname", "mscldap.nb_hostname",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "NetBios Hostname", HFILL }},
+
+ { &hf_mscldap_username,
+ { "User", "mscldap.username",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "User name", HFILL }},
+
+ { &hf_mscldap_sitename,
+ { "Site", "mscldap.sitename",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Site name", HFILL }},
+
+ { &hf_mscldap_clientsitename,
+ { "Client Site", "mscldap.clientsitename",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Client Site name", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_pdc,
+ { "PDC", "mscldap.netlogon.flags.pdc", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_pdc), 0x00000001, "Is this DC a PDC or not?", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_gc,
+ { "GC", "mscldap.netlogon.flags.gc", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_gc), 0x00000004, "Does this dc service as a GLOBAL CATALOGUE?", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_ldap,
+ { "LDAP", "mscldap.netlogon.flags.ldap", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_ldap), 0x00000008, "Does this DC act as an LDAP server?", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_ds,
+ { "DS", "mscldap.netlogon.flags.ds", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_ds), 0x00000010, "Does this dc provide DS services?", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_kdc,
+ { "KDC", "mscldap.netlogon.flags.kdc", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_kdc), 0x00000020, "Does this dc act as a KDC?", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_timeserv,
+ { "Time Serv", "mscldap.netlogon.flags.timeserv", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_timeserv), 0x00000040, "Does this dc provide time services (ntp) ?", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_closest,
+ { "Closest", "mscldap.netlogon.flags.closest", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_closest), 0x00000080, "Is this the closest dc? (is this used at all?)", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_writable,
+ { "Writable", "mscldap.netlogon.flags.writable", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_writable), 0x00000100, "Is this dc writable? (i.e. can it update the AD?)", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_good_timeserv,
+ { "Good Time Serv", "mscldap.netlogon.flags.good_timeserv", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_good_timeserv), 0x00000200, "Is this a Good Time Server? (i.e. does it have a hardware clock)", HFILL }},
+
+ { &hf_mscldap_netlogon_flags_ndnc,
+ { "NDNC", "mscldap.netlogon.flags.ndnc", FT_BOOLEAN, 32,
+ TFS(&tfs_ads_ndnc), 0x00000400, "Is this an NDNC dc?", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_ldap,
+ &ett_ldap_gssapi_token,
+ &ett_ldap_referrals,
+ &ett_ldap_attribute,
+ &ett_mscldap_netlogon_flags
+ };
+ module_t *ldap_module;
+
+ proto_ldap = proto_register_protocol("Lightweight Directory Access Protocol",
+ "LDAP", "ldap");
+ proto_register_field_array(proto_ldap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ldap_module = prefs_register_protocol(proto_ldap, NULL);
+ prefs_register_bool_preference(ldap_module, "desegment_ldap_messages",
+ "Desegment all LDAP messages spanning multiple TCP segments",
+ "Whether the LDAP dissector should desegment all messages spanning multiple TCP segments",
+ &ldap_desegment);
+
+ proto_cldap = proto_register_protocol(
+ "Connectionless Lightweight Directory Access Protocol",
+ "CLDAP", "cldap");
+
+ register_init_routine(ldap_reinit);
+ ldap_tap=register_tap("ldap");
+}
+
+void
+proto_reg_handoff_ldap(void)
+{
+ dissector_handle_t ldap_handle, cldap_handle;
+
+ ldap_handle = create_dissector_handle(dissect_ldap, proto_ldap);
+ dissector_add("tcp.port", TCP_PORT_LDAP, ldap_handle);
+ dissector_add("tcp.port", TCP_PORT_GLOBALCAT_LDAP, ldap_handle);
+
+ cldap_handle = create_dissector_handle(dissect_mscldap, proto_cldap);
+ dissector_add("udp.port", UDP_PORT_CLDAP, cldap_handle);
+
+ gssapi_handle = find_dissector("gssapi");
+ gssapi_wrap_handle = find_dissector("gssapi_verf");
+}
diff --git a/epan/dissectors/packet-ldap.h b/epan/dissectors/packet-ldap.h
new file mode 100644
index 0000000000..0462ae66fc
--- /dev/null
+++ b/epan/dissectors/packet-ldap.h
@@ -0,0 +1,90 @@
+/* packet-ldap.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_LDAP_H__
+#define __PACKET_LDAP_H__
+
+/*
+ * These are all APPLICATION types; the value is the type tag.
+ */
+#define LDAP_REQ_BIND 0
+#define LDAP_REQ_UNBIND 2
+#define LDAP_REQ_SEARCH 3
+#define LDAP_REQ_MODIFY 6
+#define LDAP_REQ_ADD 8
+#define LDAP_REQ_DELETE 10
+#define LDAP_REQ_MODRDN 12
+#define LDAP_REQ_COMPARE 14
+#define LDAP_REQ_ABANDON 16
+#define LDAP_REQ_EXTENDED 23 /* LDAP V3 only */
+
+#define LDAP_RES_BIND 1
+#define LDAP_RES_SEARCH_ENTRY 4
+#define LDAP_RES_SEARCH_REF 19 /* LDAP V3 only */
+#define LDAP_RES_SEARCH_RESULT 5
+#define LDAP_RES_MODIFY 7
+#define LDAP_RES_ADD 9
+#define LDAP_RES_DELETE 11
+#define LDAP_RES_MODRDN 13
+#define LDAP_RES_COMPARE 15
+#define LDAP_RES_EXTENDED 24 /* LDAP V3 only */
+
+/*
+ * These are all CONTEXT types; the value is the type tag.
+ */
+
+/* authentication type tags */
+#define LDAP_AUTH_SIMPLE 0
+#define LDAP_AUTH_KRBV4LDAP 1 /* LDAP V2 only */
+#define LDAP_AUTH_KRBV4DSA 2 /* LDAP V2 only */
+#define LDAP_AUTH_SASL 3 /* LDAP V3 only */
+
+/* filter type tags */
+#define LDAP_FILTER_AND 0
+#define LDAP_FILTER_OR 1
+#define LDAP_FILTER_NOT 2
+#define LDAP_FILTER_EQUALITY 3
+#define LDAP_FILTER_SUBSTRINGS 4
+#define LDAP_FILTER_GE 5
+#define LDAP_FILTER_LE 6
+#define LDAP_FILTER_PRESENT 7
+#define LDAP_FILTER_APPROX 8
+#define LDAP_FILTER_EXTENSIBLE 9 /* LDAP V3 only */
+
+#define LDAP_MOD_ADD 0
+#define LDAP_MOD_DELETE 1
+#define LDAP_MOD_REPLACE 2
+
+
+typedef struct ldap_call_response {
+ gboolean is_request;
+ guint32 req_frame;
+ nstime_t req_time;
+ guint32 rep_frame;
+ guint messageId;
+ guint protocolOpTag;
+} ldap_call_response_t;
+
+
+#endif
diff --git a/epan/dissectors/packet-ldp.c b/epan/dissectors/packet-ldp.c
new file mode 100644
index 0000000000..d4682034d0
--- /dev/null
+++ b/epan/dissectors/packet-ldp.c
@@ -0,0 +1,3140 @@
+/* packet-ldp.c
+ * Routines for LDP (RFC 3036) packet disassembly
+ *
+ * $Id$
+ *
+ * Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * CRLDP (RFC3212) is now supported
+ * - (c) 2002 Michael Rozhavsky <mike[AT]tochna.technion.ac.il>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1999 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "prefs.h"
+#include "afn.h"
+
+#include "packet-frame.h"
+#include "packet-diffserv-mpls-common.h"
+
+#define TCP_PORT_LDP 646
+#define UDP_PORT_LDP 646
+
+void proto_reg_handoff_ldp(void);
+
+static int proto_ldp = -1;
+
+/* Delete the following if you do not use it, or add to it if you need */
+static int hf_ldp_req = -1;
+static int hf_ldp_rsp = -1;
+static int hf_ldp_version = -1;
+static int hf_ldp_pdu_len = -1;
+static int hf_ldp_lsr = -1;
+static int hf_ldp_ls_id = -1;
+static int hf_ldp_msg_ubit = -1;
+static int hf_ldp_msg_type = -1;
+static int hf_ldp_msg_len = -1;
+static int hf_ldp_msg_id = -1;
+static int hf_ldp_msg_vendor_id = -1;
+static int hf_ldp_msg_experiment_id = -1;
+static int hf_ldp_tlv_value = -1;
+static int hf_ldp_tlv_type = -1;
+static int hf_ldp_tlv_unknown = -1;
+static int hf_ldp_tlv_len = -1;
+static int hf_ldp_tlv_val_hold = -1;
+static int hf_ldp_tlv_val_target = -1;
+static int hf_ldp_tlv_val_request = -1;
+static int hf_ldp_tlv_val_res = -1;
+static int hf_ldp_tlv_ipv4_taddr = -1;
+static int hf_ldp_tlv_config_seqno = -1;
+static int hf_ldp_tlv_ipv6_taddr = -1;
+static int hf_ldp_tlv_fec_wc = -1;
+static int hf_ldp_tlv_fec_af = -1;
+static int hf_ldp_tlv_fec_len = -1;
+static int hf_ldp_tlv_fec_pfval = -1;
+static int hf_ldp_tlv_fec_hoval = -1;
+static int hf_ldp_tlv_addrl_addr_family = -1;
+static int hf_ldp_tlv_addrl_addr = -1;
+static int hf_ldp_tlv_hc_value = -1;
+static int hf_ldp_tlv_pv_lsrid = -1;
+static int hf_ldp_tlv_generic_label = -1;
+static int hf_ldp_tlv_atm_label_vbits = -1;
+static int hf_ldp_tlv_atm_label_vpi = -1;
+static int hf_ldp_tlv_atm_label_vci = -1;
+static int hf_ldp_tlv_fr_label_len = -1;
+static int hf_ldp_tlv_fr_label_dlci = -1;
+static int hf_ldp_tlv_ft_protect_sequence_num = -1;
+static int hf_ldp_tlv_status_ebit = -1;
+static int hf_ldp_tlv_status_fbit = -1;
+static int hf_ldp_tlv_status_data = -1;
+static int hf_ldp_tlv_status_msg_id = -1;
+static int hf_ldp_tlv_status_msg_type = -1;
+static int hf_ldp_tlv_extstatus_data = -1;
+static int hf_ldp_tlv_returned_version = -1;
+static int hf_ldp_tlv_returned_pdu_len = -1;
+static int hf_ldp_tlv_returned_lsr = -1;
+static int hf_ldp_tlv_returned_ls_id = -1;
+static int hf_ldp_tlv_returned_msg_ubit = -1;
+static int hf_ldp_tlv_returned_msg_type = -1;
+static int hf_ldp_tlv_returned_msg_len = -1;
+static int hf_ldp_tlv_returned_msg_id = -1;
+static int hf_ldp_tlv_mac = -1;
+static int hf_ldp_tlv_sess_ver = -1;
+static int hf_ldp_tlv_sess_ka = -1;
+static int hf_ldp_tlv_sess_advbit = -1;
+static int hf_ldp_tlv_sess_ldetbit = -1;
+static int hf_ldp_tlv_sess_pvlim = -1;
+static int hf_ldp_tlv_sess_mxpdu = -1;
+static int hf_ldp_tlv_sess_rxlsr = -1;
+static int hf_ldp_tlv_sess_rxls = -1;
+static int hf_ldp_tlv_sess_atm_merge = -1;
+static int hf_ldp_tlv_sess_atm_lr = -1;
+static int hf_ldp_tlv_sess_atm_dir = -1;
+static int hf_ldp_tlv_sess_atm_minvpi = -1;
+static int hf_ldp_tlv_sess_atm_maxvpi = -1;
+static int hf_ldp_tlv_sess_atm_minvci = -1;
+static int hf_ldp_tlv_sess_atm_maxvci = -1;
+static int hf_ldp_tlv_sess_fr_merge = -1;
+static int hf_ldp_tlv_sess_fr_lr = -1;
+static int hf_ldp_tlv_sess_fr_dir = -1;
+static int hf_ldp_tlv_sess_fr_len = -1;
+static int hf_ldp_tlv_sess_fr_mindlci = -1;
+static int hf_ldp_tlv_sess_fr_maxdlci = -1;
+static int hf_ldp_tlv_ft_sess_flags = -1;
+static int hf_ldp_tlv_ft_sess_flag_r = -1;
+static int hf_ldp_tlv_ft_sess_flag_res = -1;
+static int hf_ldp_tlv_ft_sess_flag_s = -1;
+static int hf_ldp_tlv_ft_sess_flag_a = -1;
+static int hf_ldp_tlv_ft_sess_flag_c = -1;
+static int hf_ldp_tlv_ft_sess_flag_l = -1;
+static int hf_ldp_tlv_ft_sess_res = -1;
+static int hf_ldp_tlv_ft_sess_reconn_to = -1;
+static int hf_ldp_tlv_ft_sess_recovery_time = -1;
+static int hf_ldp_tlv_ft_ack_sequence_num = -1;
+static int hf_ldp_tlv_lbl_req_msg_id = -1;
+static int hf_ldp_tlv_vendor_id = -1;
+static int hf_ldp_tlv_experiment_id = -1;
+static int hf_ldp_tlv_fec_vc_controlword = -1;
+static int hf_ldp_tlv_fec_vc_vctype = -1;
+static int hf_ldp_tlv_fec_vc_infolength = -1;
+static int hf_ldp_tlv_fec_vc_groupid = -1;
+static int hf_ldp_tlv_fec_vc_vcid = -1;
+static int hf_ldp_tlv_fec_vc_intparam_length = -1;
+static int hf_ldp_tlv_fec_vc_intparam_mtu = -1;
+static int hf_ldp_tlv_fec_vc_intparam_tdmbps = -1;
+static int hf_ldp_tlv_fec_vc_intparam_id = -1;
+static int hf_ldp_tlv_fec_vc_intparam_maxcatmcells = -1;
+static int hf_ldp_tlv_fec_vc_intparam_desc = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepbytes = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepopt_ais = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepopt_une = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepopt_rtp = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepopt_ebm = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepopt_mah = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepopt_res = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepopt_ceptype = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepopt_t3 = -1;
+static int hf_ldp_tlv_fec_vc_intparam_cepopt_e3 = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vlanid = -1;
+static int hf_ldp_tlv_fec_vc_intparam_dlcilen = -1;
+static int hf_ldp_tlv_fec_vc_intparam_tdmopt_r = -1;
+static int hf_ldp_tlv_fec_vc_intparam_tdmopt_d = -1;
+static int hf_ldp_tlv_fec_vc_intparam_tdmopt_f = -1;
+static int hf_ldp_tlv_fec_vc_intparam_tdmopt_res1 = -1;
+static int hf_ldp_tlv_fec_vc_intparam_tdmopt_pt = -1;
+static int hf_ldp_tlv_fec_vc_intparam_tdmopt_res2 = -1;
+static int hf_ldp_tlv_fec_vc_intparam_tdmopt_freq = -1;
+static int hf_ldp_tlv_fec_vc_intparam_tdmopt_ssrc = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vccv_cctype_cw = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vccv_cctype_mplsra = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_icmpping = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_lspping = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_bfd = -1;
+static int hf_ldp_tlv_lspid_act_flg = -1;
+static int hf_ldp_tlv_lspid_cr_lsp = -1;
+static int hf_ldp_tlv_lspid_ldpid = -1;
+static int hf_ldp_tlv_er_hop_loose = -1;
+static int hf_ldp_tlv_er_hop_prelen = -1;
+static int hf_ldp_tlv_er_hop_prefix4 = -1;
+static int hf_ldp_tlv_er_hop_prefix6 = -1;
+static int hf_ldp_tlv_er_hop_as = -1;
+static int hf_ldp_tlv_er_hop_cr_lsp = -1;
+static int hf_ldp_tlv_er_hop_ldpid = -1;
+static int hf_ldp_tlv_flags_reserv = -1;
+static int hf_ldp_tlv_flags_weight = -1;
+static int hf_ldp_tlv_flags_ebs = -1;
+static int hf_ldp_tlv_flags_cbs = -1;
+static int hf_ldp_tlv_flags_cdr = -1;
+static int hf_ldp_tlv_flags_pbs = -1;
+static int hf_ldp_tlv_flags_pdr = -1;
+static int hf_ldp_tlv_frequency = -1;
+static int hf_ldp_tlv_pdr = -1;
+static int hf_ldp_tlv_pbs = -1;
+static int hf_ldp_tlv_cdr = -1;
+static int hf_ldp_tlv_cbs = -1;
+static int hf_ldp_tlv_ebs = -1;
+static int hf_ldp_tlv_weight = -1;
+static int hf_ldp_tlv_set_prio = -1;
+static int hf_ldp_tlv_hold_prio = -1;
+static int hf_ldp_tlv_route_pinning = -1;
+static int hf_ldp_tlv_resource_class = -1;
+static int hf_ldp_tlv_diffserv = -1;
+static int hf_ldp_tlv_diffserv_type = -1;
+static int hf_ldp_tlv_diffserv_mapnb = -1;
+static int hf_ldp_tlv_diffserv_map = -1;
+static int hf_ldp_tlv_diffserv_map_exp = -1;
+static int hf_ldp_tlv_diffserv_phbid = -1;
+static int hf_ldp_tlv_diffserv_phbid_dscp = -1;
+static int hf_ldp_tlv_diffserv_phbid_code = -1;
+static int hf_ldp_tlv_diffserv_phbid_bit14 = -1;
+static int hf_ldp_tlv_diffserv_phbid_bit15 = -1;
+static int ett_ldp = -1;
+static int ett_ldp_header = -1;
+static int ett_ldp_ldpid = -1;
+static int ett_ldp_message = -1;
+static int ett_ldp_tlv = -1;
+static int ett_ldp_tlv_val = -1;
+static int ett_ldp_tlv_ft_flags = -1;
+static int ett_ldp_fec = -1;
+static int ett_ldp_fec_vc_interfaceparam = -1;
+static int ett_ldp_fec_vc_interfaceparam_cepopt = -1;
+static int ett_ldp_fec_vc_interfaceparam_vccvtype = -1;
+static int ett_ldp_diffserv_map = -1;
+static int ett_ldp_diffserv_map_phbid = -1;
+
+static int tcp_port = 0;
+static int udp_port = 0;
+
+/* desegmentation of LDP over TCP */
+static gboolean ldp_desegment = FALSE;
+
+/* Add your functions here */
+
+static guint32 global_ldp_tcp_port = TCP_PORT_LDP;
+static guint32 global_ldp_udp_port = UDP_PORT_LDP;
+
+/*
+ * The following define all the TLV types I know about
+ */
+
+#define TLV_FEC 0x0100
+#define TLV_ADDRESS_LIST 0x0101
+#define TLV_HOP_COUNT 0x0103
+#define TLV_PATH_VECTOR 0x0104
+#define TLV_GENERIC_LABEL 0x0200
+#define TLV_ATM_LABEL 0x0201
+#define TLV_FRAME_LABEL 0x0202
+#define TLV_FT_PROTECTION 0x0203
+#define TLV_STATUS 0x0300
+#define TLV_EXTENDED_STATUS 0x0301
+#define TLV_RETURNED_PDU 0x0302
+#define TLV_RETURNED_MESSAGE 0x0303
+#define TLV_COMMON_HELLO_PARMS 0x0400
+#define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
+#define TLV_CONFIGURATION_SEQNO 0x0402
+#define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
+#define TLV_MAC 0x0404
+#define TLV_COMMON_SESSION_PARMS 0x0500
+#define TLV_ATM_SESSION_PARMS 0x0501
+#define TLV_FRAME_RELAY_SESSION_PARMS 0x0502
+#define TLV_FT_SESSION 0x0503
+#define TLV_FT_ACK 0x0504
+#define TLV_FT_CORK 0x0505
+#define TLV_LABEL_REQUEST_MESSAGE_ID 0x0600
+#define TLV_ER 0x0800
+#define TLV_ER_HOP_IPV4 0x0801
+#define TLV_ER_HOP_IPV6 0x0802
+#define TLV_ER_HOP_AS 0x0803
+#define TLV_ER_HOP_LSPID 0x0804
+#define TLV_TRAFFIC_PARAM 0x0810
+#define TLV_PREEMPTION 0x0820
+#define TLV_LSPID 0x0821
+#define TLV_RESOURCE_CLASS 0x0822
+#define TLV_ROUTE_PINNING 0x0823
+#define TLV_DIFFSERV 0x0901
+#define TLV_VENDOR_PRIVATE_START 0x3E00
+#define TLV_VENDOR_PRIVATE_END 0x3EFF
+#define TLV_EXPERIMENTAL_START 0x3F00
+#define TLV_EXPERIMENTAL_END 0x3FFF
+
+static const value_string tlv_type_names[] = {
+ { TLV_FEC, "Forwarding Equivalence Classes TLV" },
+ { TLV_ADDRESS_LIST, "Address List TLV"},
+ { TLV_HOP_COUNT, "Hop Count TLV"},
+ { TLV_PATH_VECTOR, "Path Vector TLV"},
+ { TLV_GENERIC_LABEL, "Generic Label TLV"},
+ { TLV_ATM_LABEL, "ATM Label TLV"},
+ { TLV_FRAME_LABEL, "Frame Label TLV"},
+ { TLV_FT_PROTECTION, "FT Protection TLV"},
+ { TLV_STATUS, "Status TLV"},
+ { TLV_EXTENDED_STATUS, "Extended Status TLV"},
+ { TLV_RETURNED_PDU, "Returned PDU TLV"},
+ { TLV_RETURNED_MESSAGE, "Returned Message TLV"},
+ { TLV_COMMON_HELLO_PARMS, "Common Hello Parameters TLV"},
+ { TLV_IPV4_TRANSPORT_ADDRESS, "IPv4 Transport Address TLV"},
+ { TLV_CONFIGURATION_SEQNO, "Configuration Sequence Number TLV"},
+ { TLV_IPV6_TRANSPORT_ADDRESS, "IPv6 Transport Address TLV"},
+ { TLV_MAC, "MAC TLV"},
+ { TLV_COMMON_SESSION_PARMS, "Common Session Parameters TLV"},
+ { TLV_ATM_SESSION_PARMS, "ATM Session Parameters TLV"},
+ { TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters TLV"},
+ { TLV_FT_SESSION, "FT Session TLV"},
+ { TLV_FT_ACK, "FT ACK TLV"},
+ { TLV_FT_CORK, "FT Cork TLV"},
+ { TLV_LABEL_REQUEST_MESSAGE_ID, "Label Request Message ID TLV"},
+ { TLV_LSPID, "LSP ID TLV"},
+ { TLV_ER, "Explicit route TLV"},
+ { TLV_ER_HOP_IPV4, "ER hop IPv4 prefix TLV"},
+ { TLV_ER_HOP_IPV6, "ER hop IPv6 prefix TLV"},
+ { TLV_ER_HOP_AS, "ER hop Autonomous system number prefix TLV"},
+ { TLV_TRAFFIC_PARAM, "Traffic parameters TLV"},
+ { TLV_PREEMPTION, "Preemption TLV"},
+ { TLV_ER_HOP_LSPID, "ER hop LSPID prefix TLV"},
+ { TLV_RESOURCE_CLASS, "Resource Class (Color) TLV"},
+ { TLV_ROUTE_PINNING, "Route Pinning TLV"},
+ { TLV_DIFFSERV, "Diff-Serv TLV"},
+ { TLV_VENDOR_PRIVATE_START, "Vendor Private TLV"},
+ { TLV_EXPERIMENTAL_START, "Experimental TLV"},
+ { 0, NULL}
+};
+
+/*
+ * The following define all the message types I know about
+ */
+
+#define LDP_NOTIFICATION 0x0001
+#define LDP_HELLO 0x0100
+#define LDP_INITIALIZATION 0x0200
+#define LDP_KEEPALIVE 0x0201
+#define LDP_ADDRESS 0x0300
+#define LDP_ADDRESS_WITHDRAWAL 0x0301
+#define LDP_LABEL_MAPPING 0x0400
+#define LDP_LABEL_REQUEST 0x0401
+#define LDP_LABEL_WITHDRAWAL 0x0402
+#define LDP_LABEL_RELEASE 0x0403
+#define LDP_LABEL_ABORT_REQUEST 0x0404
+#define LDP_VENDOR_PRIVATE_START 0x3E00
+#define LDP_VENDOR_PRIVATE_END 0x3EFF
+#define LDP_EXPERIMENTAL_MESSAGE_START 0x3F00
+#define LDP_EXPERIMENTAL_MESSAGE_END 0x3FFF
+
+static const value_string ldp_message_types[] = {
+ {LDP_NOTIFICATION, "Notification Message"},
+ {LDP_HELLO, "Hello Message"},
+ {LDP_INITIALIZATION, "Initialization Message"},
+ {LDP_KEEPALIVE, "Keep Alive Message"},
+ {LDP_ADDRESS, "Address Message"},
+ {LDP_ADDRESS_WITHDRAWAL, "Address Withdrawal Message"},
+ {LDP_LABEL_MAPPING, "Label Mapping Message"},
+ {LDP_LABEL_REQUEST, "Label Request Message"},
+ {LDP_LABEL_WITHDRAWAL, "Label Withdrawal Message"},
+ {LDP_LABEL_RELEASE, "Label Release Message"},
+ {LDP_LABEL_ABORT_REQUEST, "Label Abort Request Message"},
+ {LDP_VENDOR_PRIVATE_START, "Vendor-Private Message"},
+ {LDP_EXPERIMENTAL_MESSAGE_START, "Experimental Message"},
+ {0, NULL}
+};
+
+static const true_false_string ldp_message_ubit = {
+ "Unknown bit set",
+ "Unknown bit not set"
+};
+
+static const true_false_string hello_targeted_vals = {
+ "Targeted Hello",
+ "Link Hello"
+};
+
+static const value_string tlv_unknown_vals[] = {
+ {0, "Known TLV, do not Forward"},
+ {1, "Known TLV, do Forward"},
+ {2, "Unknown TLV, do not Forward"},
+ {3, "Unknown TLV, do Forward"},
+ {0, NULL}
+};
+
+#define WILDCARD_FEC 1
+#define PREFIX_FEC 2
+#define HOST_FEC 3
+#define CRLSP_FEC 4
+#define VC_FEC 0x80 /* draft-martini-l2circuit-trans-mpls */
+
+static const value_string fec_types[] = {
+ {WILDCARD_FEC, "Wildcard FEC"},
+ {PREFIX_FEC, "Prefix FEC"},
+ {HOST_FEC, "Host Address FEC"},
+ {CRLSP_FEC, "CR LSP FEC"},
+ {VC_FEC, "Virtual Circuit FEC"},
+ {0, NULL}
+};
+
+
+const value_string fec_vc_types_vals[] = {
+ {0x0001, "Frame Relay DLCI"},
+ {0x0002, "ATM AAL5 SDU VCC transport"},
+ {0x0003, "ATM transparent cell transport"},
+ {0x0004, "Ethernet VLAN"},
+ {0x0005, "Ethernet"},
+ {0x0006, "HDLC"},
+ {0x0007, "PPP"},
+ {0x0008, "SONET/SDH Circuit Emulation Service"},
+ {0x0009, "ATM n-to-one VCC cell transport"},
+ {0x000A, "ATM n-to-one VPC cell transport"},
+ {0x000B, "IP layer2 transport"},
+ {0x000C, "ATM one-to-one VCC Cell Mode"},
+ {0x000D, "ATM one-to-one VPC Cell Mode"},
+ {0x000E, "ATM AAL5 PDU VCC transport"},
+ {0x000F, "Frame-Relay Port mode"},
+ {0x0010, "SONET/SDH Circuit Emulation over Packet"},
+ {0x0011, "Structure-agnostic E1 over Packet"},
+ {0x0012, "Structure-agnostic T1 (DS1) over Packet"},
+ {0x0013, "Structure-agnostic E3 over Packet"},
+ {0x0014, "Structure-agnostic T3 (DS3) over Packet"},
+ {0x0015, "CESoPSN basic mode"},
+ {0x0016, "TDMoIP basic mode"},
+ {0x0017, "CESoPSN TDM with CAS"},
+ {0x0018, "TDMoIP TDM with CAS"},
+ {0, NULL}
+};
+
+
+static const value_string fec_vc_ceptype_vals[] = {
+ {0, "SPE mode (STS-1/STS-Mc)"},
+ {1, "VT mode (VT1.5/VT2/VT3/VT6)"},
+ {2, "Fractional SPE (STS-1/VC-3/VC-4)"},
+ {0, NULL}
+};
+
+static const true_false_string fec_vc_tdmopt_r = {
+ "Expects to receive RTP Header",
+ "Does not expect to receive RTP Header"
+};
+
+static const true_false_string fec_vc_tdmopt_d = {
+ "Expects the peer to use Differential timestamping",
+ "Does not expect the peer to use Differential timestamping"
+};
+
+static const true_false_string fec_vc_tdmopt_f = {
+ "Expects TDMoIP encapsulation",
+ "Expects CESoPSN encapsulation"
+};
+
+
+#define FEC_VC_INTERFACEPARAM_MTU 0x01
+#define FEC_VC_INTERFACEPARAM_MAXCATMCELLS 0x02
+#define FEC_VC_INTERFACEPARAM_DESCRIPTION 0x03
+#define FEC_VC_INTERFACEPARAM_CEPBYTES 0x04
+#define FEC_VC_INTERFACEPARAM_CEPOPTIONS 0x05
+#define FEC_VC_INTERFACEPARAM_VLANID 0x06
+#define FEC_VC_INTERFACEPARAM_TDMBPS 0x07
+#define FEC_VC_INTERFACEPARAM_FRDLCILEN 0x08
+#define FEC_VC_INTERFACEPARAM_FRAGIND 0x09
+#define FEC_VC_INTERFACEPARAM_FCSRETENT 0x0A
+#define FEC_VC_INTERFACEPARAM_TDMOPTION 0x0B
+#define FEC_VC_INTERFACEPARAM_VCCV 0x0C
+
+
+
+static const value_string fec_vc_interfaceparm[] = {
+ {FEC_VC_INTERFACEPARAM_MTU, "MTU"},
+ {FEC_VC_INTERFACEPARAM_MAXCATMCELLS, "Max Concatenated ATM cells"},
+ {FEC_VC_INTERFACEPARAM_DESCRIPTION, "Interface Description"},
+ {FEC_VC_INTERFACEPARAM_CEPBYTES, "CEP/TDM Payload Bytes"},
+ {FEC_VC_INTERFACEPARAM_CEPOPTIONS, "CEP options"},
+ {FEC_VC_INTERFACEPARAM_VLANID, "Requested VLAN ID"},
+ {FEC_VC_INTERFACEPARAM_TDMBPS, "CEP/TDM bit-rate"},
+ {FEC_VC_INTERFACEPARAM_FRDLCILEN, "Frame-Relay DLCI Length"},
+ {FEC_VC_INTERFACEPARAM_FRAGIND, "Fragmentation indicator"},
+ {FEC_VC_INTERFACEPARAM_FCSRETENT, "FCS retention indicator"},
+ {FEC_VC_INTERFACEPARAM_TDMOPTION, "TDM options"},
+ {FEC_VC_INTERFACEPARAM_VCCV, "VCCV"},
+ {0, NULL},
+};
+
+static const true_false_string fec_vc_cbit = {
+ "Control Word Present",
+ "Control Word NOT Present"
+};
+
+
+
+static const value_string tlv_atm_merge_vals[] = {
+ {0, "Merge not supported"},
+ {1, "VP merge supported"},
+ {2, "VC merge supported"},
+ {3, "VP & VC merge supported"},
+ {0, NULL}
+};
+
+static const value_string tlv_atm_vbits_vals[] = {
+ {0, "VPI & VCI Significant"},
+ {1, "Only VPI Significant"},
+ {2, "Only VCI Significant"},
+ {3, "VPI & VCI not Significant, nonsense"},
+ {0, NULL}
+};
+
+static const value_string tlv_fr_merge_vals[] = {
+ {0, "Merge not supported"},
+ {1, "Merge supported"},
+ {2, "Unspecified"},
+ {3, "Unspecified"},
+ {0, NULL}
+};
+
+static const value_string tlv_fr_len_vals[] = {
+ {0, "10 bits"},
+ {1, "Reserved"},
+ {2, "23 bits"},
+ {3, "Reserved"},
+ {0, NULL}
+};
+
+static const value_string tlv_ft_flags[] = {
+ {0, "Invalid"},
+ {1, "Using LDP Graceful Restart"},
+ {2, "Check-Pointing of all labels"},
+ {3, "Invalid"},
+ {4, "Invalid"},
+ {5, "Invalid"},
+ {6, "Check-Pointing of all labels"},
+ {7, "Invalid"},
+ {8, "Full FT on selected labels"},
+ {9, "Invalid"},
+ {10, "Full FT on selected labels"},
+ {11, "Invalid"},
+ {12, "Full FT on all labels"},
+ {13, "Invalid"},
+ {14, "Full FT on all labels"},
+ {15, "Invalid"},
+ {0, NULL}
+};
+
+static const true_false_string tlv_ft_r = {
+ "LSR has preserved state and resources for all FT-Labels",
+ "LSR has not preserved state and resources for all FT-Labels"
+};
+
+static const true_false_string tlv_ft_s = {
+ "FT Protection TLV supported on other than KeepAlive",
+ "FT Protection TLV not supported on other than KeepAlive"
+};
+
+static const true_false_string tlv_ft_a = {
+ "Treat all labels as Sequence Numbered FT Labels",
+ "May treat some labels as FT and others as non-FT"
+};
+
+static const true_false_string tlv_ft_c = {
+ "Check-Pointing procedures in use",
+ "Check-Pointing procedures not in use"
+};
+
+static const true_false_string tlv_ft_l = {
+ "Re-learn the state from the network",
+ "Do not re-learn the state from the network"
+};
+
+static const value_string ldp_act_flg_vals[] = {
+ {0, "indicates initial LSP setup"},
+ {1, "indicates modify LSP"},
+ {0, NULL}
+};
+
+static const value_string route_pinning_vals[] = {
+ {0, "route pinning is not requested"},
+ {1, "route pinning is requested"},
+ {0, NULL}
+};
+
+static const value_string diffserv_type_vals[] = {
+ {0, "E-LSP"},
+ {1, "L-LSP"},
+ {0, NULL}
+};
+
+static const value_string ldp_loose_vals[] = {
+ {0, "strict hop"},
+ {1, "loose hop"},
+ {0, NULL}
+};
+
+static const true_false_string tlv_negotiable = {
+ "Negotiable",
+ "Not negotiable"
+};
+
+static const value_string freq_values[] = {
+ {0, "Unspecified"},
+ {1, "Frequent"},
+ {2, "VeryFrequent"},
+ {0, NULL}
+};
+
+static const true_false_string tlv_atm_dirbit = {
+ "Bidirectional capability",
+ "Unidirectional capability"
+};
+
+static const true_false_string hello_requested_vals = {
+ "Source requests periodic hellos",
+ "Source does not request periodic hellos"
+};
+
+static const true_false_string tlv_sess_advbit_vals = {
+ "Downstream On Demand proposed",
+ "Downstream Unsolicited proposed"
+};
+
+static const true_false_string tlv_sess_ldetbit_vals = {
+ "Loop Detection Enabled",
+ "Loop Detection Disabled"
+};
+
+static const true_false_string tlv_status_ebit = {
+ "Fatal Error Notification",
+ "Advisory Notification"
+};
+
+static const true_false_string tlv_status_fbit = {
+ "Notification should be Forwarded",
+ "Notification should NOT be Forwarded"
+};
+
+static const value_string tlv_status_data[] = {
+ {0, "Success"},
+ {1, "Bad LDP Identifier"},
+ {2, "Bad Protocol Version"},
+ {3, "Bad PDU Length"},
+ {4, "Unknown Message Type"},
+ {5, "Bad Message Length"},
+ {6, "Unknown TLV"},
+ {7, "Bad TLV Length"},
+ {8, "Malformed TLV Value"},
+ {9, "Hold Timer Expired"},
+ {10, "Shutdown"},
+ {11, "Loop Detected"},
+ {12, "Unknown FEC"},
+ {13, "No Route"},
+ {14, "No Label Resources"},
+ {15, "Label Resources / Available"},
+ {16, "Session Rejected / No Hello"},
+ {17, "Session Rejected / Parameters Advertisement Mode"},
+ {18, "Session Rejected / Parameters Max PDU Length"},
+ {19, "Session Rejected / Parameters Label Range"},
+ {20, "KeepAlive Timer Expired"},
+ {21, "Label Request Aborted"},
+ {22, "Missing Message Parameters"},
+ {23, "Unsoported Address Family"},
+ {24, "Session Rejected / Bad KeepAlive Time"},
+ {25, "Internal Error"},
+ {26, "No LDP Session"},
+ {27, "Zero FT seqnum"},
+ {28, "Unexpected TLV / Session Not FT"},
+ {29, "Unexpected TLV / Label Not FT"},
+ {30, "Missing FT Protection TLV"},
+ {31, "FT ACK sequence error"},
+ {32, "Temporary Shutdown"},
+ {33, "FT Seq Numbers Exhausted"},
+ {34, "FT Session parameters / changed"},
+ {35, "Unexpected FT Cork TLV"},
+ {0x01000001,"Unexpected Diff-Serv TLV"},
+ {0x01000002,"Unsupported PHB"},
+ {0x01000003,"Invalid EXP<->PHB Mapping"},
+ {0x01000004,"Unsupported PSC"},
+ {0x01000005,"Per-LSP context allocation failure"},
+ {0x04000001,"Bad Explicit Routing TLV Error"},
+ {0x04000002,"Bad Strict Node Error"},
+ {0x04000003,"Bad Strict Node Error"},
+ {0x04000004,"Bad Initial ER-Hop Error"},
+ {0x04000005,"Resource Unavailable"},
+ {0x04000006,"Traffic Parameters Unavailable"},
+ {0x04000007,"LSP Preempted"},
+ {0x04000008,"Modify Request Not Supported"},
+ {0x20000001,"Illegal C-Bit"},
+ {0x20000002,"Wrong C-Bit"},
+ {0, NULL}
+};
+
+/* Define storage class for a string handler function
+ * with a const guint8 * argument, and returning a gchar *
+ */
+typedef gchar *(string_handler_func)(const guint8 *);
+
+/* Default handler for address to string conversion */
+static gchar *
+default_str_handler(const guint8 * bytes _U_)
+{
+ return "<Support for this Address Family not implemented>";
+}
+
+/* Dissect FEC TLV */
+
+static void
+dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti=NULL, *val_tree=NULL, *fec_tree=NULL, *vcintparam_tree=NULL;
+ proto_tree *cepopt_tree=NULL, *vccvtype_tree=NULL;
+ guint16 family, ix=1, ax;
+ guint8 addr_size=0, *addr, implemented, prefix_len_octets, prefix_len, host_len, vc_len;
+ guint8 intparam_len;
+ string_handler_func *str_handler = default_str_handler;
+ char *str;
+
+ if (tree) {
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "FEC Elements");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+ if(val_tree == NULL) return;
+
+ while (rem > 0){
+ switch (tvb_get_guint8(tvb, offset)) {
+ case WILDCARD_FEC:
+ case CRLSP_FEC:
+ ti = proto_tree_add_text(val_tree, tvb, offset, 1, "FEC Element %u", ix);
+ fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
+ if(fec_tree == NULL) return;
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 1, FALSE);
+ rem -= 1;
+ offset += 1;
+ break;
+
+ case PREFIX_FEC:
+ if( rem < 4 ){/*not enough*/
+ proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
+ return;
+ }
+ family=tvb_get_ntohs(tvb, offset+1);
+ prefix_len=tvb_get_guint8(tvb, offset+3);
+ prefix_len_octets=(prefix_len+7)/8;
+
+ implemented=1;
+ switch(family) {
+ case AFNUM_INET: /*IPv4*/
+ addr_size=4;
+ str_handler=ip_to_str;
+ break;
+ case AFNUM_INET6: /*IPv6*/
+ addr_size=16;
+ str_handler = (string_handler_func *) ip6_to_str;
+ break;
+ default:
+ implemented=0;
+ break;
+ }
+
+ if( !implemented ) {
+ guint16 noctets;
+
+ noctets= rem>4+prefix_len_octets?4+prefix_len_octets:rem;
+ proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
+ offset+=noctets;
+ rem-=noctets;
+ break;
+ }
+
+ if( rem < 4+MIN(addr_size, prefix_len_octets) ){
+ proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
+ return;
+ }
+
+ /*Add a subtree for this*/
+ ti = proto_tree_add_text(val_tree, tvb, offset, 4+MIN(addr_size, prefix_len_octets), "FEC Element %u", ix);
+ fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
+ if(fec_tree == NULL) return;
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
+ offset += 1;
+
+
+ if( addr_size < prefix_len_octets) {
+ offset+=addr_size;
+ rem-=addr_size;
+ proto_tree_add_text(fec_tree, tvb, offset-1, 1, "Invalid prefix %u length for family %s", prefix_len, val_to_str(family, afn_vals, "Unknown Family"));
+ break;
+ }
+
+ if( (addr=g_malloc0(addr_size)) == NULL ){
+ /*big big trouble, no mem or bad addr_size*/
+ fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
+ return;
+ }
+
+ for(ax=0; ax+1 <= prefix_len_octets; ax++)
+ addr[ax]=tvb_get_guint8(tvb, offset+ax);
+ if( prefix_len % 8 )
+ addr[ax-1] = addr[ax-1]&(0xFF<<(8-prefix_len%8));
+
+ str = str_handler((const guint8 *)addr);
+ proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, prefix_len_octets, str, "Prefix: %s", str);
+
+ offset += prefix_len_octets;
+ rem -= 4+prefix_len_octets;
+ g_free(addr);
+ break;
+
+ case HOST_FEC:
+ if( rem < 4 ){/*not enough*/
+ proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
+ return;
+ }
+ family=tvb_get_ntohs(tvb, offset+1);
+ host_len=tvb_get_guint8(tvb, offset+3);
+
+ implemented=1;
+ switch(family) {
+ case AFNUM_INET: /*IPv4*/
+ addr_size=4;
+ str_handler=ip_to_str;
+ break;
+ case AFNUM_INET6: /*IPv6*/
+ addr_size=16;
+ str_handler = (string_handler_func *) ip6_to_str;
+ break;
+ default:
+ implemented=0;
+ break;
+ }
+
+ if( !implemented ) {
+ guint16 noctets;
+
+ noctets= rem>4+host_len?4+host_len:rem;
+ proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
+ offset+=noctets;
+ rem-=noctets;
+ break;
+ }
+
+ if( rem < 4+addr_size ){
+ proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
+ return;
+ }
+
+ /*Add a subtree for this*/
+ ti = proto_tree_add_text(val_tree, tvb, offset, 4+addr_size, "FEC Element %u", ix);
+ fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
+ if(fec_tree == NULL) return;
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
+ offset += 1;
+
+
+ if( addr_size != host_len) {
+ offset+=addr_size;
+ rem-=addr_size;
+ proto_tree_add_text(fec_tree, tvb, offset-1, 1, "Invalid address length %u length for family %s", host_len, val_to_str(family, afn_vals, "Unknown Family"));
+ break;
+ }
+
+ if( (addr=g_malloc0(addr_size)) == NULL ){
+ /*big big xtrouble, no mem or bad addr_size*/
+ fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
+ return;
+ }
+
+ for(ax=0; ax+1 <= host_len; ax++)
+ addr[ax]=tvb_get_guint8(tvb, offset+ax);
+
+ str = str_handler((const guint8 *)addr);
+ proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_hoval, tvb, offset, host_len, str, "Address: %s", str);
+
+ offset += host_len;
+ rem -= 4+host_len;
+ g_free(addr);
+ break;
+
+ case VC_FEC:
+ if( rem < 8 ){/*not enough bytes for a minimal VC_FEC*/
+ proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
+ return;
+ }
+ vc_len = tvb_get_guint8 (tvb, offset+3);
+
+
+ ti = proto_tree_add_text(val_tree, tvb, offset, 8+vc_len, "FEC Element %u", ix);
+ fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
+ if(fec_tree == NULL) return;
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_controlword, tvb, offset+1, 1, FALSE);
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vctype, tvb, offset+1, 2, FALSE);
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_infolength, tvb, offset+3,1,FALSE);
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_groupid,tvb, offset +4, 4, FALSE);
+ rem -=8;
+ offset +=8;
+
+ if ( (vc_len > 3) && ( rem > 3 ) ) { /* there is enough room for vcid */
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vcid,tvb, offset, 4, FALSE);
+ proto_item_append_text (ti," VCID: %u",tvb_get_ntohl(tvb,offset));
+
+ } else {
+ proto_tree_add_text(val_tree,tvb,offset +4, 8 +vc_len, "VC FEC size format error");
+ return;
+ }
+ rem -= 4;
+ vc_len -= 4;
+ offset += 4;
+
+ while ( (vc_len > 1) && (rem > 1) ) { /* enough to include id and length */
+ intparam_len = tvb_get_guint8(tvb, offset+1);
+ ti = proto_tree_add_text(fec_tree, tvb, offset, intparam_len, "Interface Parameter");
+ vcintparam_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam);
+ if(vcintparam_tree == NULL) return;
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_id,tvb,offset,1,FALSE);
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_length,tvb, offset+1, 1, FALSE);
+ if (intparam_len < 2){ /* At least Type and Len, protect against len = 0 */
+ proto_tree_add_text(vcintparam_tree, tvb, offset +1, 1, "malformed interface parameter");
+ return;
+ }
+
+ if ( (vc_len -intparam_len) <0 && (rem -intparam_len) <0 ) { /* error condition */
+ proto_tree_add_text(vcintparam_tree, tvb, offset +2, MIN(vc_len,rem), "malformed data");
+ return;
+ }
+ switch (tvb_get_guint8(tvb, offset)) {
+ case FEC_VC_INTERFACEPARAM_MTU:
+ proto_item_append_text(ti,": MTU %u", tvb_get_ntohs(tvb,offset+2));
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_mtu,tvb, offset+2, 2, FALSE);
+ break;
+ case FEC_VC_INTERFACEPARAM_TDMBPS:
+ /* draft-ietf-pwe3-control-protocol-06.txt */
+ proto_item_append_text(ti,": BPS %u", tvb_get_ntohl(tvb,offset+2));
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmbps,tvb, offset+2, 4, FALSE);
+ break;
+ case FEC_VC_INTERFACEPARAM_MAXCATMCELLS:
+ proto_item_append_text(ti,": Max ATM Concat Cells %u", tvb_get_ntohs(tvb,offset+2));
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_maxcatmcells,tvb, offset+2, 2, FALSE);
+ break;
+ case FEC_VC_INTERFACEPARAM_DESCRIPTION:
+ proto_item_append_text(ti,": Description");
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_desc,tvb, offset+2, (intparam_len -2), FALSE);
+ break;
+ case FEC_VC_INTERFACEPARAM_CEPBYTES:
+ proto_item_append_text(ti,": CEP/TDM Payload Bytes %u", tvb_get_ntohs(tvb,offset+2));
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_cepbytes,tvb, offset+2, 2, FALSE);
+ break;
+ case FEC_VC_INTERFACEPARAM_CEPOPTIONS:
+ /* draft-ietf-pwe3-sonet-05.txt */
+ proto_item_append_text(ti,": CEP Options");
+ ti = proto_tree_add_text(vcintparam_tree, tvb, offset + 2, 2, "CEP Options");
+ cepopt_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam_cepopt);
+ if(cepopt_tree == NULL) return;
+ proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_ais, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_une, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_rtp, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_ebm, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_mah, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_res, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_ceptype, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_t3, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_e3, tvb, offset + 2, 2, FALSE);
+ break;
+ case FEC_VC_INTERFACEPARAM_VLANID:
+ proto_item_append_text(ti,": VLAN Id %u", tvb_get_ntohs(tvb,offset+2));
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_vlanid, tvb, offset+2, 2, FALSE);
+ break;
+ case FEC_VC_INTERFACEPARAM_FRDLCILEN:
+ proto_item_append_text(ti,": DLCI Length %u", tvb_get_ntohs(tvb,offset+2));
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_dlcilen, tvb, offset+2, 2, FALSE);
+ break;
+ case FEC_VC_INTERFACEPARAM_FRAGIND:
+ /* draft-ietf-pwe3-fragmentation-05.txt */
+ proto_item_append_text(ti,": Fragmentation");
+ break;
+ case FEC_VC_INTERFACEPARAM_FCSRETENT:
+ /* draft-ietf-pwe3-fcs-retention-00.txt */
+ proto_item_append_text(ti,": FCS retention");
+ break;
+ case FEC_VC_INTERFACEPARAM_TDMOPTION:
+ /* draft-vainshtein-pwe3-tdm-control-protocol-extensions */
+ proto_item_append_text(ti,": TDM Options");
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_r, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_d, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_f, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_res1, tvb, offset+2, 2, FALSE);
+ if (intparam_len >= 8){
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_pt, tvb, offset+4, 1, FALSE);
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_res2, tvb, offset+5, 1, FALSE);
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_freq, tvb, offset+6, 2, FALSE);
+ }
+ if (intparam_len >= 12){
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_ssrc, tvb, offset+8, 4, FALSE);
+ }
+ break;
+ case FEC_VC_INTERFACEPARAM_VCCV:
+ /* draft-ietf-pwe3-vccv-02.txt */
+ proto_item_append_text(ti,": VCCV");
+ ti = proto_tree_add_text(vcintparam_tree, tvb, offset + 2, 1, "CC Type");
+ vccvtype_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam_vccvtype);
+ if(vccvtype_tree == NULL) return;
+ proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cctype_cw, tvb, offset+2, 1, FALSE);
+ proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cctype_mplsra, tvb, offset+2, 1, FALSE);
+ ti = proto_tree_add_text(vcintparam_tree, tvb, offset + 2, 2, "CV Type");
+ vccvtype_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam_vccvtype);
+ if(vccvtype_tree == NULL) return;
+ proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_icmpping, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_lspping, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_bfd, tvb, offset+2, 2, FALSE);
+ break;
+ default: /* unknown */
+ proto_item_append_text(ti," unknown");
+ proto_tree_add_text(vcintparam_tree,tvb, offset+2, (intparam_len -2), "Unknown data");
+
+ break;
+ }
+ rem -= intparam_len;
+ vc_len -= intparam_len;
+ offset += intparam_len;
+ }
+ break;
+
+ default: /* Unknown */
+ /* XXX - do all FEC's have a length that's a multiple of 4? */
+ /* Hmmm, don't think so. Will check. RJS. */
+ /* If we don't know its structure, we have to exit */
+ ti = proto_tree_add_text(val_tree, tvb, offset, 4, "FEC Element %u", ix);
+ fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
+ if(fec_tree == NULL) return;
+ proto_tree_add_text(fec_tree, tvb, offset, rem, "Unknown FEC TLV type");
+ return;
+ }
+ ix++;
+ }
+ }
+}
+
+/* Dissect Address List TLV */
+
+static void
+dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint16 family, ix;
+ guint8 addr_size, *addr;
+ string_handler_func *str_handler = default_str_handler;
+ char *str;
+
+ if (tree) {
+ if( rem < 2 ) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Address List TLV: length is %d, should be >= 2",
+ rem);
+ return;
+ }
+
+ family=tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_ldp_tlv_addrl_addr_family, tvb,
+ offset, 2, FALSE);
+ switch(family) {
+ case AFNUM_INET: /*IPv4*/
+ addr_size=4;
+ str_handler=ip_to_str;
+ break;
+ case AFNUM_INET6: /*IPv6*/
+ addr_size=16;
+ str_handler = (string_handler_func *) ip6_to_str;
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset+2, rem-2,
+ "Support for Address Family not implemented");
+ return;
+ }
+
+ offset+=2; rem-=2;
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "Addresses");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree == NULL) return;
+ if( (addr=g_malloc(addr_size)) == NULL ){
+ /*big big trouble*/
+ fprintf(stderr, "packet-ldp: dissect_tlv_address_list() malloc failed\n");
+ return;
+ }
+
+ for(ix=1; rem >= addr_size; ix++, offset += addr_size,
+ rem -= addr_size) {
+ if( (tvb_memcpy(tvb, addr, offset, addr_size))
+ == NULL)
+ break;
+
+ str = str_handler((const guint8 *)addr);
+ proto_tree_add_string_format(val_tree,
+ hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
+ "Address %u: %s", ix, str);
+ }
+ if(rem)
+ proto_tree_add_text(val_tree, tvb, offset, rem,
+ "Error processing TLV: Extra data at end of address list");
+ g_free(addr);
+ }
+}
+
+/* Dissect Path Vector TLV */
+
+static void
+dissect_tlv_path_vector(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint8 ix;
+ guint32 addr;
+
+ if (tree) {
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "LSR IDs");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree == NULL) return;
+
+ for(ix=1; rem >= 4; ix++, offset += 4, rem -= 4) {
+ tvb_memcpy(tvb, (guint8 *)&addr, offset, 4);
+ proto_tree_add_ipv4_format(val_tree,
+ hf_ldp_tlv_pv_lsrid, tvb, offset, 4,
+ addr, "LSR Id %u: %s", ix,
+ ip_to_str((guint8 *)&addr));
+ }
+ if(rem)
+ proto_tree_add_text(val_tree, tvb, offset, rem,
+ "Error processing TLV: Extra data at end of path vector");
+ }
+}
+
+/* Dissect ATM Label TLV */
+
+static void
+dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint16 id;
+
+ if(tree) {
+ if(rem != 4){
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ATM Label TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "ATM Label");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+ if(val_tree == NULL) return;
+
+ proto_tree_add_item(val_tree, hf_ldp_tlv_atm_label_vbits, tvb, offset, 1, FALSE);
+
+ id=tvb_get_ntohs(tvb, offset)&0x0FFF;
+ proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id);
+
+ id=tvb_get_ntohs(tvb, offset+2);
+ proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id);
+ }
+}
+
+/* Dissect FRAME RELAY Label TLV */
+
+static void
+dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint8 len;
+ guint32 id;
+
+ if(tree) {
+ if(rem != 4){
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Frame Relay Label TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "Frame Relay Label");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+ if(val_tree == NULL) return;
+
+ len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
+ proto_tree_add_uint_format(val_tree, hf_ldp_tlv_fr_label_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len);
+
+ id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
+ proto_tree_add_uint_format(val_tree,
+ hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id);
+ }
+}
+
+/* Dissect STATUS TLV */
+
+static void
+dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint32 data;
+
+ if(tree) {
+ if(rem != 10){
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Status TLV: length is %d, should be 10",
+ rem);
+ return;
+ }
+
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "Status");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+ if(val_tree == NULL) return;
+
+ proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE);
+
+ data=tvb_get_ntohl(tvb, offset)&0x3FFFFFFF;
+ proto_tree_add_uint_format(val_tree, hf_ldp_tlv_status_data, tvb, offset, 4, data, "Status Data: %s (0x%X)", val_to_str(data, tlv_status_data, "Unknown Status Data"), data);
+
+ proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE);
+ }
+}
+
+/* Dissect Returned PDU TLV */
+
+static void
+dissect_tlv_returned_pdu(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if(tree) {
+ if(rem < 10){
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Returned PDU TLV: length is %d, should be >= 10",
+ rem);
+ return;
+ }
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned PDU");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+ if(val_tree == NULL) return;
+
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE);
+ offset += 10;
+ rem -= 10;
+
+ if( rem > 0 ) {
+ /*XXX - dissect returned pdu data*/
+ proto_tree_add_text(val_tree, tvb, offset, rem, "Returned PDU Data");
+ }
+ }
+}
+
+/* Dissect Returned MESSAGE TLV */
+
+static void
+dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint16 type;
+
+ if(tree) {
+ if(rem < 4){
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Returned Message TLV: length is %d, should be >= 4",
+ rem);
+ return;
+ }
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned Message");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+ if(val_tree == NULL) return;
+
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE);
+
+ type=tvb_get_ntohs(tvb, offset)&0x7FFF;
+ proto_tree_add_uint_format(val_tree, hf_ldp_tlv_returned_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type);
+
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE);
+ offset += 4;
+ rem -= 4;
+
+ if( rem >= 4 ) { /*have msg_id*/
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE);
+ offset += 4;
+ rem -= 4;
+ }
+
+ if( rem > 0 ) {
+ /*XXX - dissect returned msg parameters*/
+ proto_tree_add_text(val_tree, tvb, offset, rem, "Returned Message Parameters");
+ }
+ }
+}
+
+/* Dissect the common hello params */
+
+static void
+#if 0
+dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+#else
+dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree)
+#endif
+{
+#if 0
+ proto_tree *ti = NULL;
+#endif
+ proto_tree *val_tree = NULL;
+
+ if (tree) {
+#if 0
+ ti = proto_tree_add_item(tree, hf_ldp_tlv_value, tvb, offset, rem, FALSE);
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+ if(val_tree == NULL) return;
+#else
+ val_tree=tree;
+#endif
+ proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_val_res, tvb, offset + 2, 2, FALSE);
+ }
+}
+
+/* Dissect MAC TLV */
+
+static void
+dissect_tlv_mac(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint8 ix;
+ const guint8 *mac;
+
+ if (tree) {
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "MAC addresses");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree == NULL) return;
+
+ for(ix=1; rem >= 6; ix++, offset += 6, rem -= 6) {
+ mac = tvb_get_ptr(tvb, offset, 6);
+ proto_tree_add_ether(val_tree,
+ hf_ldp_tlv_mac, tvb, offset, 6, mac);
+ }
+ if(rem)
+ proto_tree_add_text(val_tree, tvb, offset, rem,
+ "Error processing TLV: Extra data at end of path vector");
+ }
+}
+
+
+
+/* Dissect the common session params */
+
+static void
+dissect_tlv_common_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if( rem != 14) { /*length of Comm Sess Parms tlv*/
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Common Session Parameters TLV: length is %d, should be 14",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ /*Protocol Version*/
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE);
+
+ /*KeepAlive Time*/
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ka, tvb,offset + 2, 2, FALSE);
+
+ /*A bit*/
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_advbit,tvb, offset + 4, 1, FALSE);
+
+ /*D bit*/
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ldetbit,tvb, offset + 4, 1, FALSE);
+
+ /*Path Vector Limit*/
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_pvlim,tvb, offset + 5, 1, FALSE);
+
+ /*Max PDU Length*/
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_mxpdu,tvb, offset + 6, 2, FALSE);
+
+ /*Rx LSR*/
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxlsr,tvb, offset + 8, 4, FALSE);
+
+ /*Rx LS*/
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxls,tvb, offset + 12, 2, FALSE);
+ }
+ }
+}
+
+/* Dissect the atm session params */
+
+static void
+dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
+ guint8 numlr, ix;
+ guint16 id;
+
+ if (tree != NULL) {
+ if(rem < 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ATM Parameters TLV: length is %d, should be >= 4",
+ rem);
+ return;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, rem,"ATM Parameters");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE);
+
+ /*get the number of label ranges*/
+ numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
+ proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_atm_lr,
+ tvb, offset, 1, numlr, "Number of Label Range components: %u",
+ numlr);
+
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE);
+
+ /*move into range components*/
+ offset += 4;
+ rem -= 4;
+ ti = proto_tree_add_text(val_tree, tvb, offset, rem,"ATM Label Range Components");
+
+ if(numlr) {
+ val_tree=proto_item_add_subtree(ti,ett_ldp_tlv_val);
+ if( ! val_tree ) return;
+ }
+ /*now dissect ranges*/
+ for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
+ ti=proto_tree_add_text(val_tree, tvb, offset, 8,
+ "ATM Label Range Component %u", ix);
+ lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if( lbl_tree == NULL ) break;
+
+ id=tvb_get_ntohs(tvb, offset)&0x0FFF;
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_atm_minvpi,
+ tvb, offset, 2,
+ id, "Minimum VPI: %u", id);
+ id=tvb_get_ntohs(tvb, offset+4)&0x0FFF;
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_atm_maxvpi,
+ tvb, (offset+4), 2, id,
+ "Maximum VPI: %u", id);
+
+ id=tvb_get_ntohs(tvb, offset+2);
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_atm_minvci,
+ tvb, offset+2, 2,
+ id, "Minimum VCI: %u", id);
+ id=tvb_get_ntohs(tvb, offset+6);
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_atm_maxvci,
+ tvb, offset+6, 2,
+ id, "Maximum VCI: %u", id);
+
+ offset += 8;
+ }
+ if( rem || numlr)
+ proto_tree_add_text(val_tree, tvb, offset, rem,
+ "Error processing TLV: Extra data at end of TLV");
+ }
+ }
+}
+
+/* Dissect the frame relay session params */
+
+static void
+dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
+ guint8 numlr, ix, len;
+ guint32 id;
+
+ if (tree != NULL) {
+ if(rem < 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Frame Relay Parameters TLV: length is %d, should be >= 4",
+ rem);
+ return;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, rem,
+ "Frame Relay Parameters");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_merge,
+ tvb, offset, 1, FALSE);
+
+ /*get the number of label ranges*/
+ numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
+ proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_fr_lr,
+ tvb, offset, 1, numlr, "Number of Label Range components: %u",
+ numlr);
+
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_dir,
+ tvb, offset, 1, FALSE);
+
+ /*move into range components*/
+ offset += 4;
+ rem -= 4;
+ ti = proto_tree_add_text(val_tree, tvb, offset, rem,
+ "Frame Relay Label Range Components");
+
+ if(numlr) {
+ val_tree=proto_item_add_subtree(ti,
+ ett_ldp_tlv_val);
+ if( ! val_tree ) return;
+ }
+
+ /*now dissect ranges*/
+ for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
+ ti=proto_tree_add_text(val_tree, tvb, offset, 8,
+ "Frame Relay Label Range Component %u", ix);
+ lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if( lbl_tree == NULL ) break;
+
+ len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
+ proto_tree_add_uint_format(lbl_tree, hf_ldp_tlv_sess_fr_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len);
+
+ id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id);
+ id=tvb_get_ntoh24(tvb, offset+5)&0x7FFFFF;
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id);
+
+ offset += 8;
+ }
+
+ if( rem || numlr)
+ proto_tree_add_text(val_tree, tvb, offset, rem,
+ "Error processing TLV: Extra data at end of TLV");
+ }
+ }
+}
+
+/* Dissect the Fault Tolerant (FT) Session TLV */
+
+static void
+dissect_tlv_ft_session(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL, *flags_tree = NULL;
+ guint16 flags = 0;
+
+ if (tree != NULL) {
+ if(rem != 12){
+ /* error, length must be 12 bytes */
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing FT Session TLV: length is %d, should be 12",
+ rem);
+ return;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "FT Session Parameters");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ /* Flags */
+ ti = proto_tree_add_item(val_tree, hf_ldp_tlv_ft_sess_flags, tvb, offset, 2, FALSE);
+ flags_tree = proto_item_add_subtree(ti, ett_ldp_tlv_ft_flags);
+ if (flags_tree == NULL)
+ return;
+
+ flags = tvb_get_ntohs(tvb, offset);
+ proto_item_append_text(ti, " (%s%s)", (flags & 0x8000) ? "R, " : "",
+ val_to_str(flags & 0xF, tlv_ft_flags, "Invalid"));
+ proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_r, tvb, offset, 2, FALSE);
+ proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_res, tvb, offset, 2, FALSE);
+ proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_s, tvb, offset, 2, FALSE);
+ proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_a, tvb, offset, 2, FALSE);
+ proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_c, tvb, offset, 2, FALSE);
+ proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_l, tvb, offset, 2, FALSE);
+
+ /* Reserved */
+ proto_tree_add_item(val_tree, hf_ldp_tlv_ft_sess_res, tvb, offset + 2, 2, FALSE);
+
+ /* FT Reconnect TO */
+ proto_tree_add_item(val_tree, hf_ldp_tlv_ft_sess_reconn_to, tvb, offset + 4,
+ 4, FALSE);
+
+ /* Recovery Time */
+ proto_tree_add_item(val_tree, hf_ldp_tlv_ft_sess_recovery_time, tvb, offset + 8,
+ 4, FALSE);
+ }
+ }
+
+}
+
+static void
+dissect_tlv_lspid(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 8) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing LSP ID TLV: length is %d, should be 8",
+ rem);
+ return;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, rem,
+ "LSP ID");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_act_flg,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_cr_lsp,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_ldpid,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_er_hop_ipv4(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+
+ if (tree != NULL) {
+ if(rem != 8) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ER HOP IPv4 TLV: length is %d, should be 8",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv4");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+ tvb, offset, 3, FALSE);
+ offset += 3;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix4,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_er_hop_ipv6(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 20) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ER HOP IPv6 TLV: length is %d, should be 20",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv6");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+ tvb, offset, 3, FALSE);
+ offset += 3;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix6,
+ tvb, offset, 16, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_er_hop_as(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ER HOP AS TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP AS");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_as,
+ tvb, offset, 2, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_er_hop_lspid(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 8) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ER HOP LSPID TLV: length is %d, should be 8",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP LSPID");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_cr_lsp,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_ldpid,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_traffic(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint8 val_8;
+ float val_f;
+ proto_item *pi;
+
+ if (tree != NULL) {
+ if(rem != 24) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Traffic Parameters TLV: length is %d, should be 24",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Traffic parameters");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ /* flags */
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_reserv, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_weight, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_ebs, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cbs, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cdr, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pbs, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pdr, tvb, offset, 1, FALSE);
+
+ offset ++;
+ /* frequency */
+ proto_tree_add_item(val_tree, hf_ldp_tlv_frequency, tvb, offset, 1, FALSE);
+ offset ++;
+
+ /* reserver byte */
+ offset ++;
+
+ /* weight */
+ pi = proto_tree_add_item(val_tree, hf_ldp_tlv_weight, tvb, offset, 1, FALSE);
+ val_8 = tvb_get_guint8(tvb, offset);
+ if (val_8 == 0)
+ proto_item_set_text(pi, "Weight: Not applicable");
+ offset ++;
+
+ /* PDR */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_pdr, tvb, offset,
+ 4, val_f, "PDR: %.10g Bps", val_f);
+ offset += 4;
+ /* PBS */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_pbs, tvb, offset,
+ 4, val_f, "PBS: %.10g Bytes", val_f);
+ offset += 4;
+
+ /* CDR */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_cdr, tvb, offset,
+ 4, val_f, "CDR: %.10g Bps", val_f);
+ offset += 4;
+
+ /* CBS */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_cbs, tvb, offset,
+ 4, val_f, "CBS: %.10g Bytes", val_f);
+ offset += 4;
+
+ /* EBS */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_ebs, tvb, offset,
+ 4, val_f, "EBS: %.10g Bytes", val_f);
+
+ }
+ }
+}
+
+static void
+dissect_tlv_route_pinning(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Route Pinning TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Route Pinning");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_route_pinning,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+
+static void
+dissect_tlv_resource_class(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Resource Class TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Resource Class");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_resource_class,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+
+static void
+dissect_tlv_preemption(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Preemption TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Preemption");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_set_prio,
+ tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_hold_prio,
+ tvb, offset, 1, FALSE);
+ }
+ }
+}
+
+
+static void
+dissect_tlv_diffserv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ int type, mapnb, count;
+ int *hfindexes[] = {
+ &hf_ldp_tlv_diffserv_map,
+ &hf_ldp_tlv_diffserv_map_exp,
+ &hf_ldp_tlv_diffserv_phbid,
+ &hf_ldp_tlv_diffserv_phbid_dscp,
+ &hf_ldp_tlv_diffserv_phbid_code,
+ &hf_ldp_tlv_diffserv_phbid_bit14,
+ &hf_ldp_tlv_diffserv_phbid_bit15
+ };
+ gint *etts[] = {
+ &ett_ldp_diffserv_map,
+ &ett_ldp_diffserv_map_phbid
+ };
+
+ if (rem < 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Diff-Serv TLV: length is %d, should be >= 4", rem);
+ return;
+ }
+ proto_tree_add_uint(tree, hf_ldp_tlv_diffserv_type, tvb, offset, 1,
+ type = tvb_get_guint8(tvb, offset));
+ type = (type >> 7) + 1;
+ if (type == 1) {
+ /* E-LSP */
+ offset += 3;
+ proto_tree_add_uint(tree, hf_ldp_tlv_diffserv_mapnb, tvb, offset,
+ 1, mapnb = tvb_get_guint8(tvb, offset) & 15);
+ offset += 1;
+ for (count = 0; count < mapnb; count++) {
+ dissect_diffserv_mpls_common(tvb, tree, type, offset, hfindexes, etts);
+ offset += 4;
+ }
+ }
+ else if (type == 2) {
+ /* L-LSP */
+ dissect_diffserv_mpls_common(tvb, tree, type, offset + 2, hfindexes, etts);
+ }
+}
+
+
+static int
+dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem);
+
+static void
+dissect_tlv_er(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ int len;
+
+ if (tree != NULL) {
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Explicit route");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ len = 0;
+ while (rem > 0) {
+ len = dissect_tlv (tvb, offset, val_tree, rem);
+ offset += len;
+ rem -= len;
+ }
+ }
+ }
+}
+
+
+/* Dissect a TLV and return the number of bytes consumed ... */
+
+static int
+dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ guint16 type, typebak;
+ int length;
+ proto_tree *ti = NULL, *tlv_tree = NULL;
+
+ length=tvb_reported_length_remaining(tvb, offset);
+ rem=MIN(rem, length);
+
+ if( rem < 4 ) {/*chk for minimum header*/
+ if(tree)
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing TLV: length is %d, should be >= 4",
+ rem);
+ return rem;
+ }
+ type = tvb_get_ntohs(tvb, offset) & 0x3FFF;
+
+ length = tvb_get_ntohs(tvb, offset + 2),
+ rem -= 4; /*do not count header*/
+ length = MIN(length, rem); /* Don't go haywire if a problem ... */
+
+ if (tree != NULL) {
+ /*chk for vendor-private*/
+ if(type>=TLV_VENDOR_PRIVATE_START && type<=TLV_VENDOR_PRIVATE_END){
+ typebak=type; /*keep type*/
+ type=TLV_VENDOR_PRIVATE_START;
+
+ /*chk for experimental*/
+ } else if(type>=TLV_EXPERIMENTAL_START && type<=TLV_EXPERIMENTAL_END){
+ typebak=type; /*keep type*/
+ type=TLV_EXPERIMENTAL_START;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
+ val_to_str(type, tlv_type_names, "Unknown TLV type (0x%04X)"));
+ tlv_tree = proto_item_add_subtree(ti, ett_ldp_tlv);
+ if(tlv_tree == NULL) return length+4;
+
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_unknown, tvb, offset, 1, FALSE);
+
+ proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_type, tvb, offset, 2, type, "TLV Type: %s (0x%X)", val_to_str(type, tlv_type_names, "Unknown TLV type"), type );
+
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
+
+ switch (type) {
+
+ case TLV_FEC:
+ dissect_tlv_fec(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ADDRESS_LIST:
+ dissect_tlv_address_list(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_HOP_COUNT:
+ if( length != 1 ) /*error, only one byte*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,length,
+ "Error processing Hop Count TLV: length is %d, should be 1",
+ length);
+ else
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE);
+ break;
+
+ case TLV_PATH_VECTOR:
+ dissect_tlv_path_vector(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_GENERIC_LABEL:
+ if( length != 4 ) /*error, need only label*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Generic Label TLV: length is %d, should be 4",
+ length);
+ else {
+ guint32 label=tvb_get_ntohl(tvb, offset+4) & 0x000FFFFF;
+
+ proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_generic_label,
+ tvb, offset+4, length, label, "Generic Label: %u", label);
+ }
+ break;
+
+ case TLV_ATM_LABEL:
+ dissect_tlv_atm_label(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_FRAME_LABEL:
+ dissect_tlv_frame_label(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_FT_PROTECTION:
+ if( length != 4 ) /* Length must be 4 bytes */
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing FT Protection TLV: length is %d, should be 4",
+ length);
+ else
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_ft_protect_sequence_num, tvb,
+ offset + 4,length, FALSE);
+ break;
+
+ case TLV_STATUS:
+ dissect_tlv_status(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_EXTENDED_STATUS:
+ if( length != 4 ) /*error, need only status_code(guint32)*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Extended Status TLV: length is %d, should be 4",
+ length);
+ else {
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE);
+ }
+ break;
+
+ case TLV_RETURNED_PDU:
+ dissect_tlv_returned_pdu(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_RETURNED_MESSAGE:
+ dissect_tlv_returned_message(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_COMMON_HELLO_PARMS:
+#if 0
+ dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
+#else
+ dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree);
+#endif
+ break;
+
+ case TLV_IPV4_TRANSPORT_ADDRESS:
+ if( length != 4 ) /*error, need only ipv4*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing IPv4 Transport Address TLV: length is %d, should be 4",
+ length);
+ else {
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv4_taddr, tvb, offset + 4, 4, FALSE);
+ }
+ break;
+
+ case TLV_CONFIGURATION_SEQNO:
+ if( length != 4 ) /*error, need only seq_num(guint32)*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Configuration Sequence Number TLV: length is %d, should be 4",
+ length);
+ else {
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
+ }
+ break;
+
+ case TLV_IPV6_TRANSPORT_ADDRESS:
+ if( length != 16 ) /*error, need only ipv6*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing IPv6 Transport Address TLV: length is %d, should be 16",
+ length);
+ else {
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv6_taddr, tvb, offset + 4, 16, FALSE);
+ }
+ break;
+
+ case TLV_MAC: /* draft-lasserre-vkompella-ppvpn-vpls-02.txt */
+ dissect_tlv_mac(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_COMMON_SESSION_PARMS:
+ dissect_tlv_common_session_parms(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ATM_SESSION_PARMS:
+ dissect_tlv_atm_session_parms(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_FRAME_RELAY_SESSION_PARMS:
+ dissect_tlv_frame_relay_session_parms(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_FT_SESSION:
+ /* Used in RFC3478 LDP Graceful Restart */
+ dissect_tlv_ft_session(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_FT_ACK:
+ if( length != 4 ) /* Length must be 4 bytes */
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing FT ACK TLV: length is %d, should be 4",
+ length);
+ else
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_ft_ack_sequence_num, tvb,
+ offset + 4,length, FALSE);
+ break;
+
+ case TLV_FT_CORK:
+ if( length != 0 ) /* Length must be 0 bytes */
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing FT Cork TLV: length is %d, should be 0",
+ length);
+ break;
+
+ case TLV_LABEL_REQUEST_MESSAGE_ID:
+ if( length != 4 ) /*error, need only one msgid*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Label Request Message ID TLV: length is %d, should be 4",
+ length);
+ else
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE);
+ break;
+
+ case TLV_LSPID:
+ dissect_tlv_lspid(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ER:
+ dissect_tlv_er(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ER_HOP_IPV4:
+ dissect_tlv_er_hop_ipv4(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ER_HOP_IPV6:
+ dissect_tlv_er_hop_ipv6(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_ER_HOP_AS:
+ dissect_tlv_er_hop_as(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ER_HOP_LSPID:
+ dissect_tlv_er_hop_lspid(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_TRAFFIC_PARAM:
+ dissect_tlv_traffic(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_PREEMPTION:
+ dissect_tlv_preemption(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_RESOURCE_CLASS:
+ dissect_tlv_resource_class(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_ROUTE_PINNING:
+ dissect_tlv_route_pinning(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_DIFFSERV:
+ dissect_tlv_diffserv(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_VENDOR_PRIVATE_START:
+ if( length < 4 ) /*error, at least Vendor ID*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Vendor Private Start TLV: length is %d, should be >= 4",
+ length);
+ else {
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE);
+ if( length > 4 ) /*have data*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
+ }
+ break;
+
+ case TLV_EXPERIMENTAL_START:
+ if( length < 4 ) /*error, at least Experiment ID*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Experimental Start TLV: length is %d, should be >= 4",
+ length);
+ else {
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE);
+ if( length > 4 ) /*have data*/
+ proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
+ }
+ break;
+
+ default:
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_value, tvb, offset + 4, length, FALSE);
+ break;
+ }
+ }
+
+ return length + 4; /* Length of the value field + header */
+}
+
+
+/* Dissect a Message and return the number of bytes consumed ... */
+
+static int
+dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 type, typebak;
+ guint8 extra=0;
+ int length, rem, ao=0, co;
+ proto_tree *ti = NULL, *msg_tree = NULL;
+
+ rem=tvb_reported_length_remaining(tvb, offset);
+
+ if( rem < 8 ) {/*chk for minimum header = type + length + msg_id*/
+ if( check_col(pinfo->cinfo, COL_INFO) )
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message");
+ if(tree)
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Message: length is %d, should be >= 8",
+ rem);
+ return rem;
+ }
+ type = tvb_get_ntohs(tvb, offset) & 0x7FFF;
+
+ /*chk for vendor-private*/
+ if(type>=LDP_VENDOR_PRIVATE_START && type<=LDP_VENDOR_PRIVATE_END){
+ typebak=type; /*keep type*/
+ type=LDP_VENDOR_PRIVATE_START;
+ extra=4;
+ /*chk for experimental*/
+ } else if(type>=LDP_EXPERIMENTAL_MESSAGE_START && type<=LDP_EXPERIMENTAL_MESSAGE_END){
+ typebak=type; /*keep type*/
+ type=LDP_EXPERIMENTAL_MESSAGE_START;
+ extra=4;
+ }
+
+ if( (length = tvb_get_ntohs(tvb, offset + 2)) < (4+extra) ) {/*not enough data for type*/
+ if( check_col(pinfo->cinfo, COL_INFO) )
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message Length ");
+ if(tree)
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Message Length: length is %d, should be >= %u",
+ length, 4+extra);
+ return rem;
+ }
+ rem -= 4;
+ length = MIN(length, rem); /* Don't go haywire if a problem ... */
+
+ if( check_col(pinfo->cinfo, COL_INFO) ){
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, ldp_message_types, "Unknown Message (0x%04X)"));
+ }
+
+ if( tree ){
+ ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
+ val_to_str(type, ldp_message_types, "Unknown Message type (0x%04X)"));
+ msg_tree = proto_item_add_subtree(ti, ett_ldp_message);
+ if(msg_tree == NULL) return length+4;
+
+ proto_tree_add_item(msg_tree, hf_ldp_msg_ubit, tvb, offset, 1, FALSE);
+
+ type=tvb_get_ntohs(tvb, offset)&0x7FFF;
+ proto_tree_add_uint_format(msg_tree, hf_ldp_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type);
+
+ proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset+4, 4, FALSE);
+ if(extra){
+ int hf_tmp=0;
+
+ switch(type){
+ case LDP_VENDOR_PRIVATE_START:
+ hf_tmp=hf_ldp_msg_vendor_id;
+ break;
+ case LDP_EXPERIMENTAL_MESSAGE_START:
+ hf_tmp=hf_ldp_msg_experiment_id;
+ break;
+ }
+ proto_tree_add_item(msg_tree, hf_tmp, tvb, offset+8, extra, FALSE);
+ }
+ }
+
+ offset += (8+extra);
+ length -= (4+extra);
+
+ if( tree )
+ while( (length-ao) > 0 ) {
+ co=dissect_tlv(tvb, offset, msg_tree, length-ao);
+ offset += co;
+ ao += co;
+ }
+
+ return length+8+extra;
+}
+
+/* Dissect a PDU */
+static void
+dissect_ldp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0, co;
+ int rem, length;
+ proto_tree *ti=NULL, *pdu_tree = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if( tree ){
+ ti=proto_tree_add_item(tree, proto_ldp, tvb, 0, -1, FALSE);
+ pdu_tree = proto_item_add_subtree(ti, ett_ldp);
+
+ proto_tree_add_item(pdu_tree, hf_ldp_version, tvb, offset, 2, FALSE);
+ }
+
+ length = tvb_get_ntohs(tvb, offset+2);
+ if( tree )
+ proto_tree_add_uint(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, length);
+
+ length += 4; /* add the version and type sizes */
+ rem = tvb_reported_length_remaining(tvb, offset);
+ if (length < rem)
+ tvb_set_reported_length(tvb, length);
+
+ if( tree ){
+ proto_tree_add_item(pdu_tree, hf_ldp_lsr, tvb, offset+4, 4, FALSE);
+ proto_tree_add_item(pdu_tree, hf_ldp_ls_id, tvb, offset+8, 2, FALSE);
+ }
+ offset += 10;
+
+ while( tvb_reported_length_remaining(tvb, offset) > 0 ) {
+ co=dissect_msg(tvb, offset, pinfo, pdu_tree);
+ offset += co;
+ }
+}
+
+static int
+dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /*
+ * Make sure the first PDU has a version number of 1;
+ * if not, reject this, so we don't get confused by
+ * packets that happen to be going to or from the
+ * LDP port but that aren't LDP packets.
+ */
+ if (!tvb_bytes_exist(tvb, 0, 2)) {
+ /*
+ * Not enough information to tell.
+ */
+ return 0;
+ }
+ if (tvb_get_ntohs(tvb, 0) != 1) {
+ /*
+ * Not version 1.
+ */
+ return 0;
+ }
+
+ dissect_ldp_pdu(tvb, pinfo, tree);
+
+ /*
+ * XXX - return minimum of this and the length of the PDU?
+ */
+ return tvb_length(tvb);
+}
+
+static int
+dissect_ldp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ volatile gboolean first = TRUE;
+ volatile int offset = 0;
+ int length_remaining;
+ guint16 plen;
+ int length;
+ tvbuff_t *next_tvb;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ length_remaining = tvb_length_remaining(tvb, offset);
+
+ /*
+ * Make sure the first PDU has a version number of 1;
+ * if not, reject this, so we don't get confused by
+ * packets that happen to be going to or from the
+ * LDP port but that aren't LDP packets.
+ *
+ * XXX - this means we can't handle an LDP PDU of which
+ * only one byte appears in a TCP segment. If that's
+ * a problem, we'll either have to completely punt on
+ * rejecting non-LDP packets, or will have to assume
+ * that if we have only one byte, it's an LDP packet.
+ */
+ if (first) {
+ if (length_remaining < 2) {
+ /*
+ * Not enough information to tell.
+ */
+ return 0;
+ }
+ if (tvb_get_ntohs(tvb, offset) != 1) {
+ /*
+ * Not version 1.
+ */
+ return 0;
+ }
+ first = FALSE;
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (ldp_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the LDP header split across segment
+ * boundaries?
+ */
+ if (length_remaining < 4) {
+ /*
+ * Yes. Tell the TCP dissector where
+ * the data for this message starts in
+ * the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4 - length_remaining;
+ return -((gint32) pinfo->desegment_len);
+ }
+ }
+
+ /*
+ * Get the length of the rest of the LDP packet.
+ * XXX - check for a version of 1 first?
+ */
+ plen = tvb_get_ntohs(tvb, offset + 2);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (ldp_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the LDP packet split across segment
+ * boundaries?
+ */
+ if (length_remaining < plen + 4) {
+ /*
+ * Yes. Tell the TCP dissector where the
+ * data for this message starts in the data
+ * it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len =
+ (plen + 4) - length_remaining;
+ return -((gint32) pinfo->desegment_len);
+ }
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload
+ * we have available. Make its reported length the
+ * amount of data in the DNS-over-TCP packet.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector
+ * will throw a BoundsError exception, rather than a
+ * ReportedBoundsError exception. We really want
+ * a tvbuff where the length is "length", the reported
+ * length is "plen + 4", and the "if the snapshot length
+ * were infinite" length is the minimum of the
+ * reported length of the tvbuff handed to us and "plen+4",
+ * with a new type of exception thrown if the offset is
+ * within the reported length but beyond that third length,
+ * with that exception getting the "Unreassembled Packet"
+ * error.
+ */
+ length = length_remaining;
+ if (length > plen + 4)
+ length = plen + 4;
+ next_tvb = tvb_new_subset(tvb, offset, length, plen + 4);
+
+ /*
+ * Dissect the LDP packet.
+ *
+ * Catch the ReportedBoundsError exception; if this
+ * particular message happens to get a ReportedBoundsError
+ * exception, that doesn't mean that we should stop
+ * dissecting LDP messages within this frame or chunk of
+ * reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing
+ * more to see, so we just re-throw it.
+ */
+ TRY {
+ dissect_ldp_pdu(next_tvb, pinfo, tree);
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ }
+ ENDTRY;
+
+ /*
+ * Skip the LDP header and the payload.
+ */
+ offset += plen + 4;
+ }
+ return tvb_length(tvb);
+}
+
+/* Register all the bits needed with the filtering engine */
+
+void
+proto_register_ldp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ldp_req,
+ /* Change the following to the type you need */
+ { "Request", "ldp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_ldp_rsp,
+ { "Response", "ldp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_ldp_version,
+ { "Version", "ldp.hdr.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
+
+ { &hf_ldp_pdu_len,
+ { "PDU Length", "ldp.hdr.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
+
+ { &hf_ldp_lsr,
+ { "LSR ID", "ldp.hdr.ldpid.lsr", FT_IPv4, BASE_HEX, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
+
+ { &hf_ldp_ls_id,
+ { "Label Space ID", "ldp.hdr.ldpid.lsid", FT_UINT16, BASE_DEC, NULL, 0, "LDP Label Space ID", HFILL }},
+
+ { &hf_ldp_msg_ubit,
+ { "U bit", "ldp.msg.ubit", FT_BOOLEAN, 8, TFS(&ldp_message_ubit), 0x80, "Unknown Message Bit", HFILL }},
+
+ { &hf_ldp_msg_type,
+ { "Message Type", "ldp.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
+
+ { &hf_ldp_msg_len,
+ { "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
+
+ { &hf_ldp_msg_id,
+ { "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
+
+ { &hf_ldp_msg_vendor_id,
+ { "Vendor ID", "ldp.msg.vendor.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Vendor-private Message ID", HFILL }},
+
+ { &hf_ldp_msg_experiment_id,
+ { "Experiment ID", "ldp.msg.experiment.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Experimental Message ID", HFILL }},
+
+ { &hf_ldp_tlv_unknown,
+ { "TLV Unknown bits", "ldp.msg.tlv.unknown", FT_UINT8, BASE_HEX, VALS(tlv_unknown_vals), 0xC0, "TLV Unknown bits Field", HFILL }},
+
+ { &hf_ldp_tlv_type,
+ { "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x3FFF, "TLV Type Field", HFILL }},
+
+ { &hf_ldp_tlv_len,
+ {"TLV Length", "ldp.msg.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0, "TLV Length Field", HFILL }},
+
+ { &hf_ldp_tlv_value,
+ { "TLV Value", "ldp.msg.tlv.value", FT_BYTES, BASE_NONE, NULL, 0x0, "TLV Value Bytes", HFILL }},
+
+ { &hf_ldp_tlv_val_hold,
+ { "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time", HFILL }},
+
+ { &hf_ldp_tlv_val_target,
+ { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 16, TFS(&hello_targeted_vals), 0x8000, "Hello Common Parameters Targeted Bit", HFILL }},
+
+ { &hf_ldp_tlv_val_request,
+ { "Hello Requested", "ldp.msg.tlv.hello.requested", FT_BOOLEAN, 16, TFS(&hello_requested_vals), 0x4000, "Hello Common Parameters Hello Requested Bit", HFILL }},
+
+ { &hf_ldp_tlv_val_res,
+ { "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field", HFILL }},
+
+ { &hf_ldp_tlv_ipv4_taddr,
+ { "IPv4 Transport Address", "ldp.msg.tlv.ipv4.taddr", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Transport Address", HFILL }},
+
+ { &hf_ldp_tlv_config_seqno,
+ { "Configuration Sequence Number", "ldp.msg.tlv.hello.cnf_seqno", FT_UINT32, BASE_DEC, NULL, 0x0, "Hello Configuration Sequence Number", HFILL }},
+
+ { &hf_ldp_tlv_ipv6_taddr,
+ { "IPv6 Transport Address", "ldp.msg.tlv.ipv6.taddr", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Transport Address", HFILL }},
+
+ { &hf_ldp_tlv_fec_wc,
+ { "FEC Element Type", "ldp.msg.tlv.fec.type", FT_UINT8, BASE_DEC, VALS(fec_types), 0x0, "Forwarding Equivalence Class Element Types", HFILL }},
+
+ { &hf_ldp_tlv_fec_af,
+ { "FEC Element Address Type", "ldp.msg.tlv.fec.af", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Forwarding Equivalence Class Element Address Family", HFILL }},
+
+ { &hf_ldp_tlv_fec_len,
+ { "FEC Element Length", "ldp.msg.tlv.fec.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Forwarding Equivalence Class Element Length", HFILL }},
+
+ { &hf_ldp_tlv_fec_pfval,
+ { "FEC Element Prefix Value", "ldp.msg.tlv.fec.pfval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Prefix", HFILL }},
+
+ { &hf_ldp_tlv_fec_hoval,
+ { "FEC Element Host Address Value", "ldp.msg.tlv.fec.hoval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Address", HFILL }},
+
+ { &hf_ldp_tlv_addrl_addr_family,
+ { "Address Family", "ldp.msg.tlv.addrl.addr_family", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Address Family List", HFILL }},
+
+ { &hf_ldp_tlv_addrl_addr,
+ { "Address", "ldp.msg.tlv.addrl.addr", FT_STRING, BASE_NONE, NULL, 0x0, "Address", HFILL }},
+
+ { &hf_ldp_tlv_hc_value,
+ { "Hop Count Value", "ldp.msg.tlv.hc.value", FT_UINT8, BASE_DEC, NULL, 0x0, "Hop Count", HFILL }},
+
+ { &hf_ldp_tlv_pv_lsrid,
+ { "LSR Id", "ldp.msg.tlv.pv.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Path Vector LSR Id", HFILL }},
+
+ { &hf_ldp_tlv_sess_ver,
+ { "Session Protocol Version", "ldp.msg.tlv.sess.ver", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Protocol Version", HFILL }},
+
+ { &hf_ldp_tlv_sess_ka,
+ { "Session KeepAlive Time", "ldp.msg.tlv.sess.ka", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters KeepAlive Time", HFILL }},
+
+ { &hf_ldp_tlv_sess_advbit,
+ { "Session Label Advertisement Discipline", "ldp.msg.tlv.sess.advbit",
+ FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80,
+ "Common Session Parameters Label Advertisement Discipline", HFILL }},
+
+ { &hf_ldp_tlv_sess_ldetbit,
+ { "Session Loop Detection", "ldp.msg.tlv.sess.ldetbit", FT_BOOLEAN, 8, TFS(&tlv_sess_ldetbit_vals), 0x40, "Common Session Parameters Loop Detection", HFILL }},
+
+ { &hf_ldp_tlv_sess_pvlim,
+ { "Session Path Vector Limit", "ldp.msg.tlv.sess.pvlim", FT_UINT8, BASE_DEC, NULL, 0x0, "Common Session Parameters Path Vector Limit", HFILL }},
+
+ { &hf_ldp_tlv_sess_mxpdu,
+ { "Session Max PDU Length", "ldp.msg.tlv.sess.mxpdu", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Max PDU Length", HFILL }},
+
+ { &hf_ldp_tlv_sess_rxlsr,
+ { "Session Receiver LSR Identifier", "ldp.msg.tlv.sess.rxlsr", FT_IPv4, BASE_DEC, NULL, 0x0, "Common Session Parameters LSR Identifier", HFILL }},
+
+ { &hf_ldp_tlv_sess_rxls,
+ { "Session Receiver Label Space Identifier", "ldp.msg.tlv.sess.rxlsr", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Receiver Label Space Identifier", HFILL }},
+
+ { &hf_ldp_tlv_sess_atm_merge,
+ { "Session ATM Merge Parameter", "ldp.msg.tlv.sess.atm.merge", FT_UINT8, BASE_DEC, VALS(tlv_atm_merge_vals), 0xC0, "Merge ATM Session Parameters", HFILL }},
+
+ { &hf_ldp_tlv_sess_atm_lr,
+ { "Number of ATM Label Ranges", "ldp.msg.tlv.sess.atm.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
+
+ { &hf_ldp_tlv_sess_atm_dir,
+ { "Directionality", "ldp.msg.tlv.sess.atm.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Label Directionality", HFILL }},
+
+ { &hf_ldp_tlv_sess_atm_minvpi,
+ { "Minimum VPI", "ldp.msg.tlv.sess.atm.minvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Minimum VPI", HFILL }},
+
+ { &hf_ldp_tlv_sess_atm_minvci,
+ { "Minimum VCI", "ldp.msg.tlv.sess.atm.minvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Minimum VCI", HFILL }},
+
+ { &hf_ldp_tlv_sess_atm_maxvpi,
+ { "Maximum VPI", "ldp.msg.tlv.sess.atm.maxvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Maximum VPI", HFILL }},
+
+ { &hf_ldp_tlv_sess_atm_maxvci,
+ { "Maximum VCI", "ldp.msg.tlv.sess.atm.maxvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Maximum VCI", HFILL }},
+
+ { &hf_ldp_tlv_sess_fr_merge,
+ { "Session Frame Relay Merge Parameter", "ldp.msg.tlv.sess.fr.merge", FT_UINT8, BASE_DEC, VALS(tlv_fr_merge_vals), 0xC0, "Merge Frame Relay Session Parameters", HFILL }},
+
+ { &hf_ldp_tlv_sess_fr_lr,
+ { "Number of Frame Relay Label Ranges", "ldp.msg.tlv.sess.fr.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
+
+ { &hf_ldp_tlv_sess_fr_dir,
+ { "Directionality", "ldp.msg.tlv.sess.fr.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Label Directionality", HFILL }},
+
+ { &hf_ldp_tlv_sess_fr_len,
+ { "Number of DLCI bits", "ldp.msg.tlv.sess.fr.len", FT_UINT16, BASE_DEC, VALS(tlv_fr_len_vals), 0x0180, "DLCI Number of bits", HFILL }},
+
+ { &hf_ldp_tlv_sess_fr_mindlci,
+ { "Minimum DLCI", "ldp.msg.tlv.sess.fr.mindlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Minimum DLCI", HFILL }},
+
+ { &hf_ldp_tlv_sess_fr_maxdlci,
+ { "Maximum DLCI", "ldp.msg.tlv.sess.fr.maxdlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Maximum DLCI", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_flags,
+ { "Flags", "ldp.msg.tlv.ft_sess.flags", FT_UINT16, BASE_HEX, NULL, 0x0, "FT Session Flags", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_flag_r,
+ { "R bit", "ldp.msg.tlv.ft_sess.flag_r", FT_BOOLEAN, 16, TFS(&tlv_ft_r), 0x8000, "FT Reconnect Flag", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_flag_res,
+ { "Reserved", "ldp.msg.tlv.ft_sess.flag_res", FT_UINT16, BASE_HEX, NULL, 0x7FF0, "Reserved bits", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_flag_s,
+ { "S bit", "ldp.msg.tlv.ft_sess.flag_s", FT_BOOLEAN, 16, TFS(&tlv_ft_s), 0x8, "Save State Flag", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_flag_a,
+ { "A bit", "ldp.msg.tlv.ft_sess.flag_a", FT_BOOLEAN, 16, TFS(&tlv_ft_a), 0x4, "All-Label protection Required", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_flag_c,
+ { "C bit", "ldp.msg.tlv.ft_sess.flag_c", FT_BOOLEAN, 16, TFS(&tlv_ft_c), 0x2, "Check-Pointint Flag", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_flag_l,
+ { "L bit", "ldp.msg.tlv.ft_sess.flag_l", FT_BOOLEAN, 16, TFS(&tlv_ft_l), 0x1, "Learn From network Flag", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_res,
+ { "Reserved", "ldp.msg.tlv.ft_sess.res", FT_UINT16, BASE_HEX, NULL, 0x0, "Reserved", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_reconn_to,
+ { "Reconnect Timeout", "ldp.msg.tlv.ft_sess.reconn_to", FT_UINT32, BASE_DEC, NULL, 0x0, "FT Reconnect Timeout", HFILL }},
+
+ { &hf_ldp_tlv_ft_sess_recovery_time,
+ { "Recovery Time", "ldp.msg.tlv.ft_sess.recovery_time", FT_UINT32, BASE_DEC, NULL, 0x0, "Recovery Time", HFILL }},
+
+ { &hf_ldp_tlv_ft_ack_sequence_num,
+ { "FT ACK Sequence Number", "ldp.msg.tlv.ft_ack.sequence_num", FT_UINT32, BASE_HEX, NULL, 0x0, "FT ACK Sequence Number", HFILL }},
+
+ { &hf_ldp_tlv_lbl_req_msg_id,
+ { "Label Request Message ID", "ldp.tlv.lbl_req_msg_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Label Request Message to be aborted", HFILL }},
+
+ { &hf_ldp_tlv_vendor_id,
+ { "Vendor ID", "ldp.msg.tlv.vendor_id", FT_UINT32, BASE_HEX, NULL, 0, "IEEE 802 Assigned Vendor ID", HFILL }},
+
+ { &hf_ldp_tlv_experiment_id,
+ { "Experiment ID", "ldp.msg.tlv.experiment_id", FT_UINT32, BASE_HEX, NULL, 0, "Experiment ID", HFILL }},
+
+ { &hf_ldp_tlv_generic_label,
+ { "Generic Label", "ldp.msg.tlv.generic.label", FT_UINT32, BASE_HEX, NULL, 0x000FFFFF, "Generic Label", HFILL }},
+
+ { &hf_ldp_tlv_atm_label_vbits,
+ { "V-bits", "ldp.msg.tlv.atm.label.vbits", FT_UINT8, BASE_HEX, VALS(tlv_atm_vbits_vals), 0x30, "ATM Label V Bits", HFILL }},
+
+ { &hf_ldp_tlv_atm_label_vpi,
+ { "VPI", "ldp.msg.tlv.atm.label.vpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "ATM Label VPI", HFILL }},
+
+ { &hf_ldp_tlv_atm_label_vci,
+ { "VCI", "ldp.msg.tlv.atm.label.vci", FT_UINT16, BASE_DEC, NULL, 0, "ATM Label VCI", HFILL }},
+
+ { &hf_ldp_tlv_fr_label_len,
+ { "Number of DLCI bits", "ldp.msg.tlv.fr.label.len", FT_UINT16, BASE_DEC, VALS(tlv_fr_len_vals), 0x0180, "DLCI Number of bits", HFILL }},
+
+ { &hf_ldp_tlv_fr_label_dlci,
+ { "DLCI", "ldp.msg.tlv.fr.label.dlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "FRAME RELAY Label DLCI", HFILL }},
+
+ { &hf_ldp_tlv_ft_protect_sequence_num,
+ { "FT Sequence Number", "ldp.msg.tlv.ft_protect.sequence_num", FT_UINT32, BASE_HEX, NULL, 0x0, "FT Sequence Number", HFILL }},
+
+ { &hf_ldp_tlv_status_ebit,
+ { "E Bit", "ldp.msg.tlv.status.ebit", FT_BOOLEAN, 8, TFS(&tlv_status_ebit), 0x80, "Fatal Error Bit", HFILL }},
+
+ { &hf_ldp_tlv_status_fbit,
+ { "F Bit", "ldp.msg.tlv.status.fbit", FT_BOOLEAN, 8, TFS(&tlv_status_fbit), 0x40, "Forward Bit", HFILL }},
+
+ { &hf_ldp_tlv_status_data,
+ { "Status Data", "ldp.msg.tlv.status.data", FT_UINT32, BASE_HEX, VALS(tlv_status_data), 0x3FFFFFFF, "Status Data", HFILL }},
+
+ { &hf_ldp_tlv_status_msg_id,
+ { "Message ID", "ldp.msg.tlv.status.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "Identifies peer message to which Status TLV refers", HFILL }},
+
+ { &hf_ldp_tlv_status_msg_type,
+ { "Message Type", "ldp.msg.tlv.status.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x0, "Type of peer message to which Status TLV refers", HFILL }},
+
+ { &hf_ldp_tlv_extstatus_data,
+ { "Extended Status Data", "ldp.msg.tlv.extstatus.data", FT_UINT32, BASE_HEX, NULL, 0x0, "Extended Status Data", HFILL }},
+
+ { &hf_ldp_tlv_returned_version,
+ { "Returned PDU Version", "ldp.msg.tlv.returned.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
+
+ { &hf_ldp_tlv_returned_pdu_len,
+ { "Returned PDU Length", "ldp.msg.tlv.returned.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
+
+ { &hf_ldp_tlv_returned_lsr,
+ { "Returned PDU LSR ID", "ldp.msg.tlv.returned.ldpid.lsr", FT_IPv4, BASE_DEC, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
+
+ { &hf_ldp_tlv_returned_ls_id,
+ { "Returned PDU Label Space ID", "ldp.msg.tlv.returned.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID", HFILL }},
+
+ { &hf_ldp_tlv_returned_msg_ubit,
+ { "Returned Message Unknown bit", "ldp.msg.tlv.returned.msg.ubit", FT_BOOLEAN, BASE_HEX, TFS(&ldp_message_ubit), 0x80, "Message Unknown bit", HFILL }},
+
+ { &hf_ldp_tlv_returned_msg_type,
+ { "Returned Message Type", "ldp.msg.tlv.returned.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
+
+ { &hf_ldp_tlv_returned_msg_len,
+ { "Returned Message Length", "ldp.msg.tlv.returned.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
+
+ { &hf_ldp_tlv_returned_msg_id,
+ { "Returned Message ID", "ldp.msg.tlv.returned.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
+
+ { &hf_ldp_tlv_mac,
+ { "MAC address", "ldp.msg.tlv.mac", FT_ETHER, BASE_NONE, NULL, 0x0, "MAC address", HFILL}},
+
+ {&hf_ldp_tlv_fec_vc_controlword,
+ {"C-bit", "ldp.msg.tlv.fec.vc.controlword", FT_BOOLEAN, 8, TFS(&fec_vc_cbit), 0x80, "Control Word Present", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_vctype,
+ {"VC Type", "ldp.msg.tlv.fec.vc.vctype", FT_UINT16, BASE_HEX, VALS(fec_vc_types_vals), 0x7FFF, "Virtual Circuit Type", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_infolength,
+ {"VC Info Length", "ldp.msg.tlv.fec.vc.infolength", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Info Length", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_groupid,
+ {"Group ID", "ldp.msg.tlv.fec.vc.groupid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC Group ID", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_vcid,
+ {"VC ID", "ldp.msg.tlv.fec.vc.vcid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC VCID", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_length,
+ {"Length", "ldp.msg.tlv.fec.vc.intparam.length", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater Length", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_mtu,
+ {"MTU", "ldp.msg.tlv.fec.vc.intparam.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater MTU", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_tdmbps,
+ {"BPS", "ldp.msg.tlv.fec.vc.intparam.tdmbps", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC Interface Parameter CEP/TDM bit-rate", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_id,
+ {"ID", "ldp.msg.tlv.fec.vc.intparam.id", FT_UINT8, BASE_HEX, VALS(fec_vc_interfaceparm), 0x0, "VC FEC Interface Paramater ID", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_maxcatmcells,
+ {"Number of Cells", "ldp.msg.tlv.fec.vc.intparam.maxatm", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param Max ATM Concat Cells", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_desc,
+ { "Description", "ldp.msg.tlv.fec.vc.intparam.desc", FT_STRING, BASE_DEC, NULL, 0, "VC FEC Interface Description", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepbytes,
+ {"Payload Bytes", "ldp.msg.tlv.fec.vc.intparam.cepbytes", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param CEP/TDM Payload Bytes", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepopt_ais,
+ {"AIS", "ldp.msg.tlv.fec.vc.intparam.cepopt_ais", FT_BOOLEAN, 16, NULL, 0x8000, "VC FEC Interface Param CEP Option AIS", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepopt_une,
+ {"UNE", "ldp.msg.tlv.fec.vc.intparam.cepopt_une", FT_BOOLEAN, 16, NULL, 0x4000, "VC FEC Interface Param CEP Option Unequipped", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepopt_rtp,
+ {"RTP", "ldp.msg.tlv.fec.vc.intparam.cepopt_rtp", FT_BOOLEAN, 16, NULL, 0x2000, "VC FEC Interface Param CEP Option RTP Header", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepopt_ebm,
+ {"EBM", "ldp.msg.tlv.fec.vc.intparam.cepopt_ebm", FT_BOOLEAN, 16, NULL, 0x1000, "VC FEC Interface Param CEP Option EBM Header", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepopt_mah,
+ {"MAH", "ldp.msg.tlv.fec.vc.intparam.cepopt_mah", FT_BOOLEAN, 16, NULL, 0x0800, "VC FEC Interface Param CEP Option MPLS Adaptation header", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepopt_res,
+ {"Reserved", "ldp.msg.tlv.fec.vc.intparam.cepopt_res", FT_UINT16, BASE_HEX, NULL , 0x07E0, "VC FEC Interface Param CEP Option Reserved", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepopt_ceptype,
+ {"CEP Type", "ldp.msg.tlv.fec.vc.intparam.cepopt_ceptype", FT_UINT16, BASE_HEX, VALS(fec_vc_ceptype_vals), 0x001C, "VC FEC Interface Param CEP Option CEP Type", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepopt_t3,
+ {"Async T3", "ldp.msg.tlv.fec.vc.intparam.cepopt_t3", FT_BOOLEAN, 16, NULL, 0x0002, "VC FEC Interface Param CEP Option Async T3", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_cepopt_e3,
+ {"Async E3", "ldp.msg.tlv.fec.vc.intparam.cepopt_e3", FT_BOOLEAN, 16, NULL, 0x0001, "VC FEC Interface Param CEP Option Async E3", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_vlanid,
+ { "VLAN Id", "ldp.msg.tlv.fec.vc.intparam.vlanid", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param VLAN Id", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_dlcilen,
+ {"DLCI Length", "ldp.msg.tlv.fec.vc.intparam.dlcilen", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Parameter Frame-Relay DLCI Length", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_tdmopt_r,
+ {"R Bit", "ldp.msg.tlv.fec.vc.intparam.tdmopt_r", FT_BOOLEAN, 16, TFS(&fec_vc_tdmopt_r), 0x8000, "VC FEC Interface Param TDM Options RTP Header", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_tdmopt_d,
+ {"D Bit", "ldp.msg.tlv.fec.vc.intparam.tdmopt_d", FT_BOOLEAN, 16, TFS(&fec_vc_tdmopt_d), 0x4000, "VC FEC Interface Param TDM Options Dynamic Timestamp", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_tdmopt_f,
+ {"F Bit", "ldp.msg.tlv.fec.vc.intparam.tdmopt_f", FT_BOOLEAN, 16, TFS(&fec_vc_tdmopt_f), 0x2000, "VC FEC Interface Param TDM Options Flavor bit", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_tdmopt_res1,
+ {"RSVD-1", "ldp.msg.tlv.fec.vc.intparam.tdmopt_res1", FT_UINT16, BASE_HEX, NULL, 0x1FFF, "VC FEC Interface Param TDM Options Reserved", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_tdmopt_pt,
+ {"PT", "ldp.msg.tlv.fec.vc.intparam.tdmopt_pt", FT_UINT8, BASE_DEC, NULL, 0x7F, "VC FEC Interface Param TDM Options Payload Type", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_tdmopt_res2,
+ {"RSVD-2", "ldp.msg.tlv.fec.vc.intparam.tdmopt_res2", FT_UINT8, BASE_HEX, NULL, 0x00, "VC FEC Interface Param TDM Options Reserved", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_tdmopt_freq,
+ {"FREQ", "ldp.msg.tlv.fec.vc.intparam.tdmopt_freq", FT_UINT16, BASE_DEC, NULL, 0x00, "VC FEC Interface Param TDM Options Frequency", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_tdmopt_ssrc,
+ {"SSRC", "ldp.msg.tlv.fec.vc.intparam.tdmopt_ssrc", FT_UINT32, BASE_HEX, NULL, 0x00, "VC FEC Interface Param TDM Options SSRC", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_vccv_cctype_cw,
+ {"PWE3 Control Word", "ldp.msg.tlv.fec.vc.intparam.vccv.cctype_cw", FT_BOOLEAN, 8, NULL, 0x10, "VC FEC Interface Param VCCV CC Type PWE3 CW", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_vccv_cctype_mplsra,
+ {"MPLS Router Alert", "ldp.msg.tlv.fec.vc.intparam.vccv.cctype_mplsra", FT_BOOLEAN, 8, NULL, 0x20, "VC FEC Interface Param VCCV CC Type MPLS Router Alert", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_icmpping,
+ {"ICMP Ping", "ldp.msg.tlv.fec.vc.intparam.vccv.cvtype_icmpping", FT_BOOLEAN, 16, NULL, 0x0001, "VC FEC Interface Param VCCV CV Type ICMP Ping", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_lspping,
+ {"LSP Ping", "ldp.msg.tlv.fec.vc.intparam.vccv.cvtype_lspping", FT_BOOLEAN, 16, NULL, 0x0002, "VC FEC Interface Param VCCV CV Type LSP Ping", HFILL }},
+
+ {&hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_bfd,
+ {"BFD", "ldp.msg.tlv.fec.vc.intparam.vccv.cvtype_bfd", FT_BOOLEAN, 16, NULL, 0x0004, "VC FEC Interface Param VCCV CV Type BFD", HFILL }},
+
+
+ { &hf_ldp_tlv_lspid_act_flg,
+ { "Action Indicator Flag", "ldp.msg.tlv.lspid.actflg", FT_UINT16, BASE_HEX, VALS(ldp_act_flg_vals), 0x000F, "Action Indicator Flag", HFILL}},
+
+ { &hf_ldp_tlv_lspid_cr_lsp,
+ { "Local CR-LSP ID", "ldp.msg.tlv.lspid.locallspid", FT_UINT16, BASE_HEX, NULL, 0x0, "Local CR-LSP ID", HFILL}},
+
+ { &hf_ldp_tlv_lspid_ldpid,
+ { "Ingress LSR Router ID", "ldp.msg.tlv.lspid.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Ingress LSR Router ID", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_loose,
+ { "Loose route bit", "ldp.msg.tlv.er_hop.loose", FT_UINT24, BASE_HEX, VALS(ldp_loose_vals), 0x800000, "Loose route bit", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_prelen,
+ { "Prefix length", "ldp.msg.tlv.er_hop.prefixlen", FT_UINT8, BASE_DEC, NULL, 0x0, "Prefix len", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_prefix4,
+ { "IPv4 Address", "ldp.msg.tlv.er_hop.prefix4", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Address", HFILL}},
+ { &hf_ldp_tlv_er_hop_prefix6,
+ { "IPv6 Address", "ldp.msg.tlv.er_hop.prefix6", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Address", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_as,
+ { "AS Number", "ldp.msg.tlv.er_hop.as", FT_UINT16, BASE_DEC, NULL, 0x0, "AS Number", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_cr_lsp,
+ { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.locallspid", FT_UINT16, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_ldpid,
+ { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
+
+ { &hf_ldp_tlv_flags_reserv,
+ { "Reserved", "ldp.msg.tlv.flags_reserv", FT_UINT8, BASE_HEX, NULL, 0xC0, "Reserved", HFILL}},
+
+ { &hf_ldp_tlv_flags_pdr,
+ { "PDR", "ldp.msg.tlv.flags_pdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x1, "PDR negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_pbs,
+ { "PBS", "ldp.msg.tlv.flags_pbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x2, "PBS negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_cdr,
+ { "CDR", "ldp.msg.tlv.flags_cdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x4, "CDR negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_cbs,
+ { "CBS", "ldp.msg.tlv.flags_cbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x8, "CBS negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_ebs,
+ { "EBS", "ldp.msg.tlv.flags_ebs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x10, "EBS negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_weight,
+ { "Weight", "ldp.msg.tlv.flags_weight", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x20, "Weight negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_frequency,
+ { "Frequency", "ldp.msg.tlv.frequency", FT_UINT8, BASE_DEC, VALS(freq_values), 0, "Frequency", HFILL}},
+
+ { &hf_ldp_tlv_weight,
+ { "Weight", "ldp.msg.tlv.weight", FT_UINT8, BASE_DEC, NULL, 0, "Weight of the CR-LSP", HFILL}},
+
+ { &hf_ldp_tlv_pdr,
+ { "PDR", "ldp.msg.tlv.pdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Data Rate", HFILL}},
+
+ { &hf_ldp_tlv_pbs,
+ { "PBS", "ldp.msg.tlv.pbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Burst Size", HFILL}},
+
+ { &hf_ldp_tlv_cdr,
+ { "CDR", "ldp.msg.tlv.cdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Data Rate", HFILL}},
+
+ { &hf_ldp_tlv_cbs,
+ { "CBS", "ldp.msg.tlv.cbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Burst Size", HFILL}},
+
+ { &hf_ldp_tlv_ebs,
+ { "EBS", "ldp.msg.tlv.ebs", FT_DOUBLE, BASE_NONE, NULL, 0, "Excess Burst Size", HFILL}},
+
+ { &hf_ldp_tlv_set_prio,
+ { "Set Prio", "ldp.msg.tlv.set_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP setup priority", HFILL}},
+
+ { &hf_ldp_tlv_hold_prio,
+ { "Hold Prio", "ldp.msg.tlv.hold_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP hold priority", HFILL}},
+
+ { &hf_ldp_tlv_route_pinning,
+ { "Route Pinning", "ldp.msg.tlv.route_pinning", FT_UINT32, BASE_DEC, VALS(route_pinning_vals), 0x80000000, "Route Pinning", HFILL}},
+
+ { &hf_ldp_tlv_resource_class,
+ { "Resource Class", "ldp.msg.tlv.resource_class", FT_UINT32, BASE_HEX, NULL, 0, "Resource Class (Color)", HFILL}},
+
+ { &hf_ldp_tlv_diffserv,
+ { "Diff-Serv TLV", "ldp.msg.tlv.diffserv", FT_NONE, BASE_NONE, NULL,
+ 0, "Diffserv TLV", HFILL}},
+
+ { &hf_ldp_tlv_diffserv_type,
+ { "LSP Type", "ldp.msg.tlv.diffserv.type", FT_UINT8, BASE_DEC,
+ VALS(diffserv_type_vals), 0x80, "LSP Type", HFILL}},
+
+ { &hf_ldp_tlv_diffserv_mapnb,
+ { "MAPnb", "ldp.msg.tlv.diffserv.mapnb", FT_UINT8, BASE_DEC, NULL,
+ 0, MAPNB_DESCRIPTION, HFILL}},
+
+ { &hf_ldp_tlv_diffserv_map,
+ { "MAP", "ldp.msg.tlv.diffserv.map", FT_NONE, BASE_NONE, NULL,
+ 0, MAP_DESCRIPTION, HFILL}},
+
+ { &hf_ldp_tlv_diffserv_map_exp,
+ { "EXP", "ldp.msg.tlv.diffserv.map.exp", FT_UINT8, BASE_DEC, NULL,
+ 0, EXP_DESCRIPTION, HFILL}},
+
+ { &hf_ldp_tlv_diffserv_phbid,
+ { "PHBID", "ldp.msg.tlv.diffserv.phbid", FT_NONE, BASE_NONE, NULL,
+ 0, PHBID_DESCRIPTION, HFILL}},
+
+ { &hf_ldp_tlv_diffserv_phbid_dscp,
+ { "DSCP", "ldp.msg.tlv.diffserv.phbid.dscp", FT_UINT16, BASE_DEC,
+ NULL, PHBID_DSCP_MASK, PHBID_DSCP_DESCRIPTION, HFILL}},
+
+ { &hf_ldp_tlv_diffserv_phbid_code,
+ { "PHB id code", "ldp.msg.tlv.diffserv.phbid.code", FT_UINT16, BASE_DEC,
+ NULL, PHBID_CODE_MASK, PHBID_CODE_DESCRIPTION, HFILL}},
+
+ { &hf_ldp_tlv_diffserv_phbid_bit14,
+ { "Bit 14", "ldp.msg.tlv.diffserv.phbid.bit14", FT_UINT16, BASE_DEC,
+ VALS(phbid_bit14_vals), PHBID_BIT14_MASK, PHBID_BIT14_DESCRIPTION, HFILL}},
+
+ { &hf_ldp_tlv_diffserv_phbid_bit15,
+ { "Bit 15", "ldp.msg.tlv.diffserv.phbid.bit15", FT_UINT16, BASE_DEC,
+ VALS(phbid_bit15_vals), PHBID_BIT15_MASK, PHBID_BIT15_DESCRIPTION, HFILL}}
+
+ };
+
+ static gint *ett[] = {
+ &ett_ldp,
+ &ett_ldp_header,
+ &ett_ldp_ldpid,
+ &ett_ldp_message,
+ &ett_ldp_tlv,
+ &ett_ldp_tlv_val,
+ &ett_ldp_tlv_ft_flags,
+ &ett_ldp_fec,
+ &ett_ldp_fec_vc_interfaceparam,
+ &ett_ldp_fec_vc_interfaceparam_cepopt,
+ &ett_ldp_fec_vc_interfaceparam_vccvtype,
+ &ett_ldp_diffserv_map,
+ &ett_ldp_diffserv_map_phbid
+ };
+ module_t *ldp_module;
+
+ proto_ldp = proto_register_protocol("Label Distribution Protocol",
+ "LDP", "ldp");
+
+ proto_register_field_array(proto_ldp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register our configuration options for , particularly our port */
+
+ ldp_module = prefs_register_protocol(proto_ldp, proto_reg_handoff_ldp);
+
+ prefs_register_uint_preference(ldp_module, "tcp.port", "LDP TCP Port",
+ "Set the TCP port for messages (if other"
+ " than the default of 646)",
+ 10, &global_ldp_tcp_port);
+
+ prefs_register_uint_preference(ldp_module, "udp.port", "LDP UDP Port",
+ "Set the UDP port for messages (if other"
+ " than the default of 646)",
+ 10, &global_ldp_udp_port);
+
+ prefs_register_bool_preference(ldp_module, "desegment_ldp_messages",
+ "Desegment all LDP messages\nspanning multiple TCP segments",
+ "Whether the LDP dissector should desegment all messages spanning multiple TCP segments",
+ &ldp_desegment);
+}
+
+/* The registration hand-off routine */
+void
+proto_reg_handoff_ldp(void)
+{
+ static gboolean ldp_prefs_initialized = FALSE;
+ static dissector_handle_t ldp_tcp_handle, ldp_handle;
+
+ if (!ldp_prefs_initialized) {
+
+ ldp_tcp_handle = new_create_dissector_handle(dissect_ldp_tcp, proto_ldp);
+ ldp_handle = new_create_dissector_handle(dissect_ldp, proto_ldp);
+
+ ldp_prefs_initialized = TRUE;
+
+ }
+ else {
+
+ dissector_delete("tcp.port", tcp_port, ldp_tcp_handle);
+ dissector_delete("udp.port", udp_port, ldp_handle);
+
+ }
+
+ /* Set our port number for future use */
+
+ tcp_port = global_ldp_tcp_port;
+ udp_port = global_ldp_udp_port;
+
+ dissector_add("tcp.port", global_ldp_tcp_port, ldp_tcp_handle);
+ dissector_add("udp.port", global_ldp_udp_port, ldp_handle);
+
+}
diff --git a/epan/dissectors/packet-ldp.h b/epan/dissectors/packet-ldp.h
new file mode 100644
index 0000000000..e1e311df2e
--- /dev/null
+++ b/epan/dissectors/packet-ldp.h
@@ -0,0 +1,34 @@
+/* packet-ldp.h
+ * Declarations of exported routines from LDP dissector
+ * Copyright 2004, Carlos Pignataro <cpignata@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_LDP_H_
+#define __PACKET_LDP_H__
+
+/*
+ * Used by MPLS Echo dissector as well.
+ */
+extern const enum_val_t fec_vc_types_vals[];
+
+#endif
diff --git a/epan/dissectors/packet-llc.c b/epan/dissectors/packet-llc.c
new file mode 100644
index 0000000000..6d488c446d
--- /dev/null
+++ b/epan/dissectors/packet-llc.c
@@ -0,0 +1,750 @@
+/* packet-llc.c
+ * Routines for IEEE 802.2 LLC layer
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "oui.h"
+#include "xdlc.h"
+#include "etypes.h"
+#include "llcsaps.h"
+#include "bridged_pids.h"
+#include "ppptypes.h"
+#include "arcnet_pids.h"
+#include "packet-fc.h"
+#include "packet-ip.h"
+#include "packet-ipx.h"
+#include "packet-netbios.h"
+#include "packet-vines.h"
+#include <epan/sna-utils.h>
+
+#include "packet-llc.h"
+
+#define UDP_PORT_LLC1 12000
+#define UDP_PORT_LLC2 12001
+#define UDP_PORT_LLC3 12002
+#define UDP_PORT_LLC4 12003
+#define UDP_PORT_LLC5 12004
+
+static int proto_llc = -1;
+static int hf_llc_dsap = -1;
+static int hf_llc_ssap = -1;
+static int hf_llc_dsap_ig = -1;
+static int hf_llc_ssap_cr = -1;
+static int hf_llc_ctrl = -1;
+static int hf_llc_n_r = -1;
+static int hf_llc_n_s = -1;
+static int hf_llc_p = -1;
+static int hf_llc_p_ext = -1;
+static int hf_llc_f = -1;
+static int hf_llc_f_ext = -1;
+static int hf_llc_s_ftype = -1;
+static int hf_llc_u_modifier_cmd = -1;
+static int hf_llc_u_modifier_resp = -1;
+static int hf_llc_ftype_i = -1;
+static int hf_llc_ftype_s_u = -1;
+static int hf_llc_ftype_s_u_ext = -1;
+static int hf_llc_type = -1;
+static int hf_llc_oui = -1;
+static int hf_llc_pid = -1;
+
+static gint ett_llc = -1;
+static gint ett_llc_ctrl = -1;
+
+static dissector_table_t subdissector_table;
+static dissector_table_t xid_subdissector_table;
+
+static dissector_handle_t bpdu_handle;
+static dissector_handle_t eth_handle;
+static dissector_handle_t fddi_handle;
+static dissector_handle_t tr_handle;
+static dissector_handle_t data_handle;
+
+/*
+ * Group/Individual bit, in the DSAP.
+ */
+#define DSAP_GI_BIT 0x01
+
+/*
+ * Command/Response bit, in the SSAP.
+ *
+ * The low-order bit of the SSAP apparently determines whether this
+ * is a request or a response. (RFC 1390, "Transmission of IP and
+ * ARP over FDDI Networks", says
+ *
+ * Command frames are identified by having the low order
+ * bit of the SSAP address reset to zero. Response frames
+ * have the low order bit of the SSAP address set to one.
+ *
+ * and a page I've seen seems to imply that's part of 802.2.)
+ */
+#define SSAP_CR_BIT 0x01
+
+/*
+ * Mask to extrace the SAP number from the DSAP or the SSAP.
+ */
+#define SAP_MASK 0xFE
+
+/*
+ * These are for SSAP and DSAP, wth last bit always zero.
+ * XXX - some DSAPs come in separate "individual" and "group" versions,
+ * with the last bit 0 and 1, respectively (e.g., LLC Sub-layer Management,
+ * IBM SNA Path Control, IBM Net Management), but, whilst 0xFE is
+ * the ISO Network Layer Protocol, 0xFF is the Global LSAP.
+ */
+const value_string sap_vals[] = {
+ { SAP_NULL, "NULL LSAP" },
+ { SAP_LLC_SLMGMT, "LLC Sub-Layer Management" },
+ { SAP_SNA_PATHCTRL, "SNA Path Control" },
+ { SAP_IP, "TCP/IP" },
+ { SAP_SNA1, "SNA" },
+ { SAP_SNA2, "SNA" },
+ { SAP_PROWAY_NM_INIT, "PROWAY (IEC955) Network Management and Initialization" },
+ { SAP_NETWARE1, "NetWare (unofficial?)" },
+ { SAP_OSINL1, "ISO Network Layer (OSLAN 1)" },
+ { SAP_TI, "Texas Instruments" },
+ { SAP_OSINL2, "ISO Network Layer (unofficial?)" },
+ { SAP_OSINL3, "ISO Network Layer (unofficial?)" },
+ { SAP_BPDU, "Spanning Tree BPDU" },
+ { SAP_RS511, "EIA RS-511 Manufacturing Message Service" },
+ { SAP_OSINL4, "ISO Network Layer (OSLAN 2)" },
+ { SAP_X25, "ISO 8208 (X.25 over 802.2)" },
+ /*
+ * XXX - setting the group bit of SAP_X25 make 0x7F; is this just
+ * a group version of that?
+ */
+ { 0x7F, "ISO 802.2" },
+ { SAP_XNS, "XNS" },
+ { SAP_BACNET, "BACnet" },
+ { SAP_NESTAR, "Nestar" },
+ { SAP_PROWAY_ASLM, "PROWAY (IEC955) Active Station List Maintenance" },
+ { SAP_ARP, "ARP" }, /* XXX - hand to "dissect_arp()"? */
+ { SAP_SNAP, "SNAP" },
+ { SAP_VINES1, "Banyan Vines" },
+ { SAP_VINES2, "Banyan Vines" },
+ { SAP_NETWARE2, "NetWare" },
+ { SAP_NETBIOS, "NetBIOS" },
+ { SAP_IBMNM, "IBM Net Management" },
+ { SAP_HPEXT, "HP Extended LLC" },
+ { SAP_UB, "Ungermann-Bass" },
+ { SAP_RPL, "Remote Program Load" },
+ { SAP_OSINL5, "ISO Network Layer" },
+ { SAP_GLOBAL, "Global LSAP" },
+ { 0x00, NULL }
+};
+
+/*
+ * See
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/vlan.htm
+ *
+ * for the PIDs for VTP and DRiP that go with an OUI of OUI_CISCO.
+ */
+const value_string oui_vals[] = {
+ { OUI_ENCAP_ETHER, "Encapsulated Ethernet" },
+/*
+http://www.cisco.com/univercd/cc/td/doc/product/software/ios113ed/113ed_cr/ibm_r/brprt1/brsrb.htm
+*/
+ { OUI_CISCO, "Cisco" },
+ { OUI_CISCO_90, "Cisco IOS 9.0 Compatible" },
+ { OUI_BRIDGED, "Frame Relay or ATM bridged frames" },
+ /* RFC 2427, RFC 2684 */
+ { OUI_ATM_FORUM, "ATM Forum" },
+ { OUI_CABLE_BPDU, "DOCSIS Spanning Tree" }, /* DOCSIS spanning tree BPDU */
+ { OUI_APPLE_ATALK, "Apple (AppleTalk)" },
+ { OUI_NORTEL, "Nortel Networks SONMP" },
+ { 0, NULL }
+};
+
+/*
+ * Hash table for translating OUIs to a dissector table/field info pair;
+ * the dissector table maps PID values to dissectors, and the field
+ * corresponds to the PID for that OUI.
+ */
+typedef struct {
+ dissector_table_t table;
+ hf_register_info *field_info;
+} oui_info_t;
+
+static GHashTable *oui_info_table = NULL;
+
+/*
+ * Add an entry for a new OUI.
+ */
+void
+llc_add_oui(guint32 oui, const char *table_name, char *table_ui_name,
+ hf_register_info *hf_item)
+{
+ oui_info_t *new_info;
+
+ new_info = g_malloc(sizeof (oui_info_t));
+ new_info->table = register_dissector_table(table_name,
+ table_ui_name, FT_UINT16, BASE_HEX);
+ new_info->field_info = hf_item;
+
+ /*
+ * Create the hash table for OUI information, if it doesn't
+ * already exist.
+ */
+ if (oui_info_table == NULL) {
+ oui_info_table = g_hash_table_new(g_direct_hash,
+ g_direct_equal);
+ }
+ g_hash_table_insert(oui_info_table, (gpointer)oui, new_info);
+}
+
+void
+capture_llc(const guchar *pd, int offset, int len, packet_counts *ld) {
+
+ int is_snap;
+ guint16 control;
+ int llc_header_len;
+ guint32 oui;
+ guint16 etype;
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
+ ld->other++;
+ return;
+ }
+ is_snap = (pd[offset] == SAP_SNAP) && (pd[offset+1] == SAP_SNAP);
+ llc_header_len = 2; /* DSAP + SSAP */
+
+ /*
+ * XXX - the page referred to in the comment above about the
+ * Command/Response bit also implies that LLC Type 2 always
+ * uses extended operation, so we don't need to determine
+ * whether it's basic or extended operation; is that the case?
+ */
+ control = get_xdlc_control(pd, offset+2, pd[offset+1] & SSAP_CR_BIT);
+ llc_header_len += XDLC_CONTROL_LEN(control, TRUE);
+ if (is_snap)
+ llc_header_len += 5; /* 3 bytes of OUI, 2 bytes of protocol ID */
+ if (!BYTES_ARE_IN_FRAME(offset, len, llc_header_len)) {
+ ld->other++;
+ return;
+ }
+
+ if (is_snap) {
+ oui = pd[offset+3] << 16 | pd[offset+4] << 8 | pd[offset+5];
+ if (XDLC_IS_INFORMATION(control)) {
+ etype = pntohs(&pd[offset+6]);
+ switch (oui) {
+
+ case OUI_ENCAP_ETHER:
+ case OUI_CISCO_90:
+ case OUI_APPLE_ATALK:
+ /* No, I have no idea why Apple used
+ one of their own OUIs, rather than
+ OUI_ENCAP_ETHER, and an Ethernet
+ packet type as protocol ID, for
+ AppleTalk data packets - but used
+ OUI_ENCAP_ETHER and an Ethernet
+ packet type for AARP packets. */
+ capture_ethertype(etype, pd, offset+8, len,
+ ld);
+ break;
+ case OUI_CISCO:
+ capture_ethertype(etype, pd, offset + 8, len,
+ ld);
+ break;
+ default:
+ ld->other++;
+ break;
+ }
+ }
+ }
+ else {
+ /* non-SNAP */
+ if (XDLC_IS_INFORMATION(control)) {
+ switch (pd[offset]) {
+
+ case SAP_IP:
+ capture_ip(pd, offset + llc_header_len, len,
+ ld);
+ break;
+
+ case SAP_NETWARE1:
+ case SAP_NETWARE2:
+ capture_ipx(ld);
+ break;
+
+ case SAP_NETBIOS:
+ capture_netbios(ld);
+ break;
+
+ case SAP_VINES1:
+ case SAP_VINES2:
+ capture_vines(ld);
+ break;
+
+ default:
+ ld->other++;
+ break;
+ }
+ }
+ }
+}
+
+/* Used only for U frames */
+static const xdlc_cf_items llc_cf_items = {
+ NULL,
+ NULL,
+ &hf_llc_p,
+ &hf_llc_f,
+ NULL,
+ &hf_llc_u_modifier_cmd,
+ &hf_llc_u_modifier_resp,
+ NULL,
+ &hf_llc_ftype_s_u
+};
+
+/* Used only for I and S frames */
+static const xdlc_cf_items llc_cf_items_ext = {
+ &hf_llc_n_r,
+ &hf_llc_n_s,
+ &hf_llc_p_ext,
+ &hf_llc_f_ext,
+ &hf_llc_s_ftype,
+ NULL,
+ NULL,
+ &hf_llc_ftype_i,
+ &hf_llc_ftype_s_u_ext
+};
+
+static void
+dissect_llc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *llc_tree = NULL;
+ proto_item *ti = NULL;
+ int is_snap;
+ guint16 control;
+ int llc_header_len;
+ guint8 dsap, ssap;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LLC");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ dsap = tvb_get_guint8(tvb, 0);
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_llc, tvb, 0, -1, FALSE);
+ llc_tree = proto_item_add_subtree(ti, ett_llc);
+ proto_tree_add_uint(llc_tree, hf_llc_dsap, tvb, 0,
+ 1, dsap & SAP_MASK);
+ proto_tree_add_boolean(llc_tree, hf_llc_dsap_ig, tvb, 0,
+ 1, dsap & DSAP_GI_BIT);
+ } else
+ llc_tree = NULL;
+
+ ssap = tvb_get_guint8(tvb, 1);
+ if (tree) {
+ proto_tree_add_uint(llc_tree, hf_llc_ssap, tvb, 1,
+ 1, ssap & SAP_MASK);
+ proto_tree_add_boolean(llc_tree, hf_llc_ssap_cr, tvb, 1,
+ 1, ssap & SSAP_CR_BIT);
+ } else
+ llc_tree = NULL;
+
+ is_snap = (dsap == SAP_SNAP) && (ssap == SAP_SNAP);
+ llc_header_len = 2; /* DSAP + SSAP */
+
+ /*
+ * XXX - the page referred to in the comment above about the
+ * Command/Response bit also implies that LLC Type 2 always
+ * uses extended operation, so we don't need to determine
+ * whether it's basic or extended operation; is that the case?
+ */
+ control = dissect_xdlc_control(tvb, 2, pinfo, llc_tree,
+ hf_llc_ctrl, ett_llc_ctrl,
+ &llc_cf_items, &llc_cf_items_ext,
+ NULL, NULL, ssap & SSAP_CR_BIT, TRUE, FALSE);
+ llc_header_len += XDLC_CONTROL_LEN(control, TRUE);
+ if (is_snap)
+ llc_header_len += 5; /* 3 bytes of OUI, 2 bytes of protocol ID */
+
+ if (tree)
+ proto_item_set_len(ti, llc_header_len);
+
+ if (is_snap) {
+ dissect_snap(tvb, 3, pinfo, tree, llc_tree, control,
+ hf_llc_oui, hf_llc_type, hf_llc_pid, 2);
+ }
+ else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "; DSAP %s %s, SSAP %s %s",
+ val_to_str(dsap & SAP_MASK, sap_vals, "%02x"),
+ dsap & DSAP_GI_BIT ?
+ "Group" : "Individual",
+ val_to_str(ssap & SAP_MASK, sap_vals, "%02x"),
+ ssap & SSAP_CR_BIT ?
+ "Response" : "Command"
+ );
+ }
+
+ if (tvb_length_remaining(tvb, llc_header_len) > 0) {
+ next_tvb = tvb_new_subset(tvb, llc_header_len, -1, -1);
+ if (XDLC_IS_INFORMATION(control)) {
+ /*
+ * Non-SNAP I or UI frame.
+ * Try the regular LLC subdissector table
+ * with the DSAP.
+ */
+ if (!dissector_try_port(subdissector_table,
+ dsap, next_tvb, pinfo, tree)) {
+ call_dissector(data_handle, next_tvb,
+ pinfo, tree);
+ }
+ } else if ((control & (XDLC_U_MODIFIER_MASK|XDLC_U))
+ == (XDLC_XID|XDLC_U)) {
+ /*
+ * Non-SNAP XID frame.
+ * Try the XID LLC subdissector table
+ * with the DSAP.
+ */
+ if (!dissector_try_port(xid_subdissector_table,
+ dsap, next_tvb, pinfo, tree)) {
+ call_dissector(data_handle, next_tvb,
+ pinfo, tree);
+ }
+ } else {
+ call_dissector(data_handle, next_tvb, pinfo,
+ tree);
+ }
+ }
+ }
+}
+
+/*
+ * Dissect SNAP header; used elsewhere, e.g. in the Frame Relay dissector.
+ */
+void
+dissect_snap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
+ proto_tree *snap_tree, int control, int hf_oui, int hf_type, int hf_pid,
+ int bridge_pad)
+{
+ guint32 oui;
+ guint16 etype;
+ tvbuff_t *next_tvb;
+ oui_info_t *oui_info;
+ dissector_table_t subdissector_table;
+ int hf;
+
+ oui = tvb_get_ntoh24(tvb, offset);
+ etype = tvb_get_ntohs(tvb, offset+3);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "; SNAP, OUI 0x%06X (%s), PID 0x%04X",
+ oui, val_to_str(oui, oui_vals, "Unknown"), etype);
+ }
+ if (tree) {
+ proto_tree_add_uint(snap_tree, hf_oui, tvb, offset, 3, oui);
+ }
+
+ switch (oui) {
+
+ case OUI_ENCAP_ETHER:
+ case OUI_CISCO_90:
+ case OUI_APPLE_ATALK:
+ /* No, I have no idea why Apple used
+ one of their own OUIs, rather than
+ OUI_ENCAP_ETHER, and an Ethernet
+ packet type as protocol ID, for
+ AppleTalk data packets - but used
+ OUI_ENCAP_ETHER and an Ethernet
+ packet type for AARP packets. */
+ if (XDLC_IS_INFORMATION(control)) {
+ ethertype(etype, tvb, offset+5,
+ pinfo, tree, snap_tree, hf_type, -1, 0);
+ } else {
+ next_tvb = tvb_new_subset(tvb, offset+5, -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+ break;
+
+ case OUI_BRIDGED:
+ /*
+ * MAC frames bridged over ATM (RFC 2684) or Frame Relay
+ * (RFC 2427).
+ *
+ * We have to figure out how much padding to put
+ * into the frame. We were handed a "bridge_pad"
+ * argument which should be 0 for Frame Relay and
+ * 2 for ATM; we add to that the amount of padding
+ * common to both bridging types.
+ */
+ if (tree) {
+ proto_tree_add_uint(snap_tree, hf_pid, tvb, offset+3, 2,
+ etype);
+ }
+
+ switch (etype) {
+
+ case BPID_ETH_WITH_FCS:
+ case BPID_ETH_WITHOUT_FCS:
+ next_tvb = tvb_new_subset(tvb, offset+5+bridge_pad,
+ -1, -1);
+ call_dissector(eth_handle, next_tvb, pinfo, tree);
+ break;
+
+ case BPID_802_5_WITH_FCS:
+ case BPID_802_5_WITHOUT_FCS:
+ /*
+ * We treat the last padding byte as the Access
+ * Control byte, as that's what the Token
+ * Ring dissector expects the first byte to
+ * be.
+ */
+ next_tvb = tvb_new_subset(tvb, offset+5+bridge_pad,
+ -1, -1);
+ call_dissector(tr_handle, next_tvb, pinfo, tree);
+ break;
+
+ case BPID_FDDI_WITH_FCS:
+ case BPID_FDDI_WITHOUT_FCS:
+ next_tvb = tvb_new_subset(tvb, offset+5+1+bridge_pad,
+ -1, -1);
+ call_dissector(fddi_handle, next_tvb, pinfo, tree);
+ break;
+
+ case BPID_BPDU:
+ next_tvb = tvb_new_subset(tvb, offset+5, -1, -1);
+ call_dissector(bpdu_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ next_tvb = tvb_new_subset(tvb, offset+5, -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ break;
+ }
+ break;
+
+ case OUI_CABLE_BPDU: /* DOCSIS cable modem spanning tree BPDU */
+ if (tree) {
+ proto_tree_add_uint(snap_tree, hf_pid, tvb, offset+3, 2,
+ etype);
+ }
+ next_tvb = tvb_new_subset(tvb, offset+5, -1, -1);
+ call_dissector(bpdu_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ /*
+ * Do we have information for this OUI?
+ */
+ oui_info = g_hash_table_lookup(oui_info_table, (gpointer)oui);
+ if (oui_info != NULL) {
+ /*
+ * Yes - use it.
+ */
+ hf = *oui_info->field_info->p_id;
+ subdissector_table = oui_info->table;
+ } else {
+ /*
+ * No, use hf_pid for the PID and just dissect
+ * the payload as data.
+ */
+ hf = hf_pid;
+ subdissector_table = NULL;
+ }
+ if (tree) {
+ proto_tree_add_uint(snap_tree, hf, tvb, offset+3, 2,
+ etype);
+ }
+ next_tvb = tvb_new_subset(tvb, offset+5, -1, -1);
+ if (XDLC_IS_INFORMATION(control)) {
+ if (subdissector_table != NULL) {
+ /* do lookup with the subdissector table */
+ if (dissector_try_port(subdissector_table,
+ etype, next_tvb, pinfo, tree))
+ break;
+ }
+ }
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ break;
+ }
+}
+
+void
+proto_register_llc(void)
+{
+ static struct true_false_string ig_bit = { "Group", "Individual" };
+ static struct true_false_string cr_bit = { "Response", "Command" };
+
+ static hf_register_info hf[] = {
+ { &hf_llc_dsap,
+ { "DSAP", "llc.dsap", FT_UINT8, BASE_HEX,
+ VALS(sap_vals), 0x0, "", HFILL }},
+
+ { &hf_llc_dsap_ig,
+ { "IG Bit", "llc.dsap.ig", FT_BOOLEAN, BASE_HEX,
+ &ig_bit, 0x0, "Individual/Group", HFILL }},
+
+ { &hf_llc_ssap,
+ { "SSAP", "llc.ssap", FT_UINT8, BASE_HEX,
+ VALS(sap_vals), 0x0, "", HFILL }},
+
+ { &hf_llc_ssap_cr,
+ { "CR Bit", "llc.ssap.cr", FT_BOOLEAN, BASE_HEX,
+ &cr_bit, 0x0, "Command/Response", HFILL }},
+
+ { &hf_llc_ctrl,
+ { "Control", "llc.control", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_llc_n_r,
+ { "N(R)", "llc.control.n_r", FT_UINT16, BASE_DEC,
+ NULL, XDLC_N_R_EXT_MASK, "", HFILL }},
+
+ { &hf_llc_n_s,
+ { "N(S)", "llc.control.n_s", FT_UINT16, BASE_DEC,
+ NULL, XDLC_N_S_EXT_MASK, "", HFILL }},
+
+ { &hf_llc_p,
+ { "Poll", "llc.control.p", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+
+ { &hf_llc_p_ext,
+ { "Poll", "llc.control.p", FT_BOOLEAN, 16,
+ TFS(&flags_set_truth), XDLC_P_F_EXT, "", HFILL }},
+
+ { &hf_llc_f,
+ { "Final", "llc.control.f", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+
+ { &hf_llc_f_ext,
+ { "Final", "llc.control.f", FT_BOOLEAN, 16,
+ TFS(&flags_set_truth), XDLC_P_F_EXT, "", HFILL }},
+
+ { &hf_llc_s_ftype,
+ { "Supervisory frame type", "llc.control.s_ftype", FT_UINT16, BASE_HEX,
+ VALS(stype_vals), XDLC_S_FTYPE_MASK, "", HFILL }},
+
+ { &hf_llc_u_modifier_cmd,
+ { "Command", "llc.control.u_modifier_cmd", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, "", HFILL }},
+
+ { &hf_llc_u_modifier_resp,
+ { "Response", "llc.control.u_modifier_resp", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, "", HFILL }},
+
+ { &hf_llc_ftype_i,
+ { "Frame type", "llc.control.ftype", FT_UINT16, BASE_HEX,
+ VALS(ftype_vals), XDLC_I_MASK, "", HFILL }},
+
+ { &hf_llc_ftype_s_u,
+ { "Frame type", "llc.control.ftype", FT_UINT8, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+
+ { &hf_llc_ftype_s_u_ext,
+ { "Frame type", "llc.control.ftype", FT_UINT16, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+
+ /* registered here but handled in ethertype.c */
+ { &hf_llc_type,
+ { "Type", "llc.type", FT_UINT16, BASE_HEX,
+ VALS(etype_vals), 0x0, "", HFILL }},
+
+ { &hf_llc_oui,
+ { "Organization Code", "llc.oui", FT_UINT24, BASE_HEX,
+ VALS(oui_vals), 0x0, "", HFILL }},
+
+ { &hf_llc_pid,
+ { "Protocol ID", "llc.pid", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_llc,
+ &ett_llc_ctrl,
+ };
+
+ proto_llc = proto_register_protocol("Logical-Link Control", "LLC", "llc");
+ proto_register_field_array(proto_llc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+/* subdissector code */
+ subdissector_table = register_dissector_table("llc.dsap",
+ "LLC SAP", FT_UINT8, BASE_HEX);
+ xid_subdissector_table = register_dissector_table("llc.xid_dsap",
+ "LLC XID SAP", FT_UINT8, BASE_HEX);
+
+ register_dissector("llc", dissect_llc, proto_llc);
+}
+
+static void
+register_hf(gpointer key _U_, gpointer value, gpointer user_data _U_)
+{
+ oui_info_t *info = value;
+
+ proto_register_field_array(proto_llc, info->field_info, 1);
+}
+
+void
+proto_reg_handoff_llc(void)
+{
+ dissector_handle_t llc_handle;
+
+ /*
+ * Get handles for the BPDU, Ethernet, FDDI, and Token Ring
+ * dissectors.
+ */
+ bpdu_handle = find_dissector("bpdu");
+ eth_handle = find_dissector("eth");
+ fddi_handle = find_dissector("fddi");
+ tr_handle = find_dissector("tr");
+ data_handle = find_dissector("data");
+
+ llc_handle = find_dissector("llc");
+ dissector_add("wtap_encap", WTAP_ENCAP_ATM_RFC1483, llc_handle);
+ /* RFC 2043 */
+ dissector_add("ppp.protocol", PPP_LLC, llc_handle);
+ /* RFC 2353 */
+ dissector_add("udp.port", UDP_PORT_LLC1, llc_handle);
+ dissector_add("udp.port", UDP_PORT_LLC2, llc_handle);
+ dissector_add("udp.port", UDP_PORT_LLC3, llc_handle);
+ dissector_add("udp.port", UDP_PORT_LLC4, llc_handle);
+ dissector_add("udp.port", UDP_PORT_LLC5, llc_handle);
+ /* IP-over-FC when we have the full FC frame */
+ dissector_add("fc.ftype", FC_FTYPE_IP, llc_handle);
+
+ /*
+ * BACNET-over-ARCNET is really BACNET-over-802.2 LLC-over-ARCNET,
+ * apparently.
+ */
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_BACNET, llc_handle);
+
+ /*
+ * Register all the fields for PIDs for various OUIs.
+ */
+ g_hash_table_foreach(oui_info_table, register_hf, NULL);
+}
diff --git a/epan/dissectors/packet-llc.h b/epan/dissectors/packet-llc.h
new file mode 100644
index 0000000000..1271473404
--- /dev/null
+++ b/epan/dissectors/packet-llc.h
@@ -0,0 +1,39 @@
+/* packet-llc.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_LLC_H__
+#define __PACKET_LLC_H__
+
+void capture_llc(const guchar *, int, int, packet_counts *);
+
+void dissect_snap(tvbuff_t *, int, packet_info *, proto_tree *,
+ proto_tree *, int, int, int, int, int);
+
+/*
+ * Add an entry for a new OUI.
+ */
+void llc_add_oui(guint32, const char *, char *, hf_register_info *);
+
+extern const value_string sap_vals[];
+
+#endif
diff --git a/epan/dissectors/packet-lmi.c b/epan/dissectors/packet-lmi.c
new file mode 100644
index 0000000000..7a37bcb509
--- /dev/null
+++ b/epan/dissectors/packet-lmi.c
@@ -0,0 +1,256 @@
+/* packet-lmi.c
+ * Routines for Frame Relay Local Management Interface (LMI) disassembly
+ * Copyright 2001, Jeffrey C. Foster <jfoste@woodward.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ToDo:
+ *
+ * References:
+ *
+ * http://www.techfest.com/networking/wan/frrel.htm
+ * http://www.frforum.com/5000/Approved/FRF.1.2/frf1_2.pdf
+ * http://www.cisco.com/univercd/cc/td/doc/cisintwk/ito_doc/frame.htm#xtocid18
+ * http://www.net.aapt.com.au/techref/lmimess.htm
+ * http://www.raleigh.ibm.com:80/cgi-bin/bookmgr/BOOKS/EZ305800/1.2.4.4
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "nlpid.h"
+
+static int proto_lmi = -1;
+static int hf_lmi_call_ref = -1;
+static int hf_lmi_msg_type = -1;
+static int hf_lmi_inf_ele = -1;
+static int hf_lmi_inf_len = -1;
+
+static int hf_lmi_rcd_type = -1;
+static int hf_lmi_send_seq = -1;
+static int hf_lmi_recv_seq = -1;
+static int hf_lmi_dlci_high = -1;
+static int hf_lmi_dlci_low = -1;
+static int hf_lmi_new = -1;
+static int hf_lmi_act = -1;
+
+static gint ett_lmi = -1;
+static gint ett_lmi_ele = -1;
+
+#ifdef _OLD_
+/*
+ * Bits in the address field.
+ */
+#define LMI_CMD 0xf000 /* LMI Command */
+#define LMI_SEQ 0x0fff /* LMI Sequence number */
+
+#endif
+
+static const value_string msg_type_str[] = {
+ {0x75, "Status Enquiry"},
+ {0x7D, "Status"},
+ { 0, NULL }
+ };
+
+static const value_string element_type_str[] = {
+
+/*** These are the ANSI values ***/
+ {0x01, "Report"},
+ {0x03, "Keep Alive"},
+ {0x07, "PVC Status"},
+
+/*** These are the ITU values ***/
+ {0x51, "Report"},
+ {0x53, "Keep Alive"},
+ {0x07, "PVC Status"},
+
+ { 0, NULL }
+ };
+
+static const value_string record_type_str[] = {
+ {0x00, "Full Status"},
+ {0x01, "Link Integrity Verification Only"},
+ {0x02, "Single PVC"},
+ { 0, NULL }
+ };
+
+static const value_string pvc_status_new_str[] = {
+ {0x00, "PVC already present"},
+ {0x01, "PVC is new"},
+ { 0, NULL }
+ };
+
+static const value_string pvc_status_act_str[] = {
+ {0x00, "PVC is Inactive"},
+ {0x01, "PVC is Active"},
+ { 0, NULL }
+ };
+
+static void
+dissect_lmi_report_type(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree_add_uint(tree, hf_lmi_rcd_type, tvb, offset, 1, tvb_get_guint8( tvb, offset));
+}
+
+static void
+dissect_lmi_link_int(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree_add_uint(tree, hf_lmi_send_seq, tvb, offset, 1, tvb_get_guint8( tvb, offset));
+ ++offset;
+ proto_tree_add_uint(tree, hf_lmi_recv_seq, tvb, offset, 1, tvb_get_guint8( tvb, offset));
+
+}
+
+static void
+dissect_lmi_pvc_status(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree_add_uint(tree, hf_lmi_dlci_high, tvb, offset, 1, tvb_get_guint8( tvb, offset));
+ ++offset;
+ proto_tree_add_uint(tree, hf_lmi_dlci_low, tvb, offset, 1, tvb_get_guint8( tvb, offset));
+ ++offset;
+ proto_tree_add_uint(tree, hf_lmi_new, tvb, offset, 1, tvb_get_guint8( tvb, offset));
+ proto_tree_add_uint(tree, hf_lmi_act, tvb, offset, 1, tvb_get_guint8( tvb, offset));
+}
+
+static void
+dissect_lmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *lmi_tree = NULL, *lmi_subtree;
+ proto_item *ti;
+ int offset = 2, len;
+ guint8 msg_type;
+ guint8 ele_id;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LMI");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_lmi, tvb, 0, 3, FALSE);
+ lmi_tree = proto_item_add_subtree(ti, ett_lmi_ele);
+
+ proto_tree_add_item(lmi_tree, hf_lmi_call_ref, tvb, 0, 1, FALSE);
+ }
+ msg_type = tvb_get_guint8( tvb, 1);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(msg_type, msg_type_str, "Unknown message type (0x%02x)"));
+ }
+ if (tree) {
+ proto_tree_add_uint(lmi_tree, hf_lmi_msg_type, tvb, 1, 1, msg_type);
+
+ /* Display the LMI elements */
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ ele_id = tvb_get_guint8( tvb, offset);
+ len = tvb_get_guint8( tvb, offset + 1);
+
+ ti = proto_tree_add_text(lmi_tree, tvb, offset, len + 2,
+ "Information Element: %s",
+ val_to_str(ele_id, element_type_str, "Unknown (%u)"));
+
+ lmi_subtree = proto_item_add_subtree(ti, ett_lmi_ele);
+
+ proto_tree_add_uint(lmi_subtree, hf_lmi_inf_ele, tvb, offset, 1,
+ ele_id);
+ ++offset;
+ proto_tree_add_uint(lmi_subtree, hf_lmi_inf_len, tvb, offset, 1, len);
+ ++offset;
+ if (( ele_id == 1) || (ele_id == 51))
+ dissect_lmi_report_type( tvb, offset, lmi_subtree);
+ else if (( ele_id == 3) || (ele_id == 53))
+ dissect_lmi_link_int( tvb, offset, lmi_subtree);
+ else if (( ele_id == 7) || (ele_id == 57))
+ dissect_lmi_pvc_status( tvb, offset, lmi_subtree);
+ offset += len;
+ }
+ }
+ else {
+ lmi_tree = NULL;
+ }
+}
+
+
+void
+proto_register_lmi(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_lmi_call_ref,
+ { "Call reference", "lmi.cmd", FT_UINT8, BASE_HEX, NULL, 0,
+ "Call Reference", HFILL }},
+
+ { &hf_lmi_msg_type,
+ { "Message Type", "lmi.msg_type", FT_UINT8, BASE_HEX, VALS(msg_type_str), 0,
+ "Message Type", HFILL }},
+
+ { &hf_lmi_inf_ele,
+ { "Type", "lmi.inf_ele_type", FT_UINT8, BASE_DEC, VALS(element_type_str), 0,
+ "Information Element Type", HFILL }},
+ { &hf_lmi_inf_len,
+ { "Length", "lmi.inf_ele_len", FT_UINT8, BASE_DEC, NULL, 0,
+ "Information Element Length", HFILL }},
+
+ { &hf_lmi_rcd_type,
+ { "Record Type", "lmi.ele_rcd_type", FT_UINT8, BASE_DEC, VALS(record_type_str), 0,
+ "Record Type", HFILL }},
+ { &hf_lmi_send_seq,
+ { "Send Seq", "lmi.send_seq", FT_UINT8, BASE_DEC, NULL, 0,
+ "Send Sequence", HFILL }},
+ { &hf_lmi_recv_seq,
+ { "Recv Seq", "lmi.recv_seq", FT_UINT8, BASE_DEC, NULL, 0,
+ "Receive Sequence", HFILL }},
+ { &hf_lmi_dlci_high,
+ { "DLCI High", "lmi.dlci_hi", FT_UINT8, BASE_DEC, NULL, 0x3f,
+ "DLCI High bits", HFILL }},
+ { &hf_lmi_dlci_low,
+ { "DLCI Low", "lmi.dlci_low", FT_UINT8, BASE_DEC, NULL, 0x78,
+ "DLCI Low bits", HFILL }},
+ { &hf_lmi_new,
+ { "DLCI New", "lmi.dlci_new", FT_UINT8, BASE_DEC, VALS(pvc_status_new_str), 0x08,
+ "DLCI New Flag", HFILL }},
+ { &hf_lmi_act,
+ { "DLCI Active","lmi.dlci_act", FT_UINT8, BASE_DEC, VALS(pvc_status_act_str), 0x02,
+ "DLCI Active Flag", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_lmi,
+ &ett_lmi_ele,
+ };
+ proto_lmi = proto_register_protocol ("Local Management Interface", "LMI", "lmi");
+ proto_register_field_array (proto_lmi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_lmi(void)
+{
+ dissector_handle_t lmi_handle;
+
+ lmi_handle = create_dissector_handle(dissect_lmi, proto_lmi);
+ dissector_add("fr.ietf", NLPID_LMI, lmi_handle);
+}
diff --git a/epan/dissectors/packet-lmp.c b/epan/dissectors/packet-lmp.c
new file mode 100644
index 0000000000..5d019a3f0d
--- /dev/null
+++ b/epan/dissectors/packet-lmp.c
@@ -0,0 +1,2306 @@
+/* packet-lmp.c
+ * Routines for LMP packet disassembly
+ *
+ * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * LMP as a standard has shown a remarkable ability to get completely rewritten
+ * across minor versions of the draft. This file currently implements
+ * three versions of LMP; IP based versions described in draft-ietf-ccamp-lmp-02.txt and
+ * draft-ietf-ccamp-lmp-03.txt, and the new UDP based version in draft-ietf-ccamp-lmp-09.txt.
+ * The -09 version is the default; the version being dissected can be changed from
+ * the LMP protocol preferences
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/tvbuff.h>
+#include <epan/packet.h>
+#include <prefs.h>
+#include "in_cksum.h"
+#include "etypes.h"
+#include "ipproto.h"
+
+#include "packet-ip.h"
+#include "packet-rsvp.h"
+#include "packet-frame.h"
+
+static int proto_lmp = -1;
+#define LMP_VER_DRAFT_CCAMP_02 2
+#define LMP_VER_DRAFT_CCAMP_03 3
+#define LMP_VER_DRAFT_CCAMP_09 9
+static int lmp_draft_ver = LMP_VER_DRAFT_CCAMP_09;
+
+#define IP_PROTO_LMP 140
+#define UDP_PORT_LMP_DEFAULT 49998
+static int lmp_udp_port = UDP_PORT_LMP_DEFAULT;
+static int lmp_udp_port_config = UDP_PORT_LMP_DEFAULT;
+
+static dissector_handle_t lmp_handle;
+
+/*----------------------------------------------------------------------
+ * LMP message types
+ */
+typedef enum {
+ LMP_MSG_CONFIG=1,
+ LMP_MSG_CONFIG_ACK,
+ LMP_MSG_CONFIG_NACK,
+ LMP_MSG_HELLO,
+ LMP_MSG_BEGIN_VERIFY,
+ LMP_MSG_BEGIN_VERIFY_ACK,
+ LMP_MSG_BEGIN_VERIFY_NACK,
+ LMP_MSG_END_VERIFY,
+ LMP_MSG_END_VERIFY_ACK,
+ LMP_MSG_TEST,
+ LMP_MSG_TEST_STATUS_SUCCESS,
+ LMP_MSG_TEST_STATUS_FAILURE,
+ LMP_MSG_TEST_STATUS_ACK,
+ LMP_MSG_LINK_SUMMARY,
+ LMP_MSG_LINK_SUMMARY_ACK,
+ LMP_MSG_LINK_SUMMARY_NACK,
+ LMP_MSG_CHANNEL_STATUS,
+ LMP_MSG_CHANNEL_STATUS_ACK,
+ LMP_MSG_CHANNEL_STATUS_REQ,
+ LMP_MSG_CHANNEL_STATUS_RESP
+} lmp_message_types;
+
+static value_string message_type_vals[] = {
+ {LMP_MSG_CONFIG, "Config Message. "},
+ {LMP_MSG_CONFIG_ACK, "ConfigAck Message. "},
+ {LMP_MSG_CONFIG_NACK, "ConfigNack Message. "},
+ {LMP_MSG_HELLO, "Hello Message. "},
+ {LMP_MSG_BEGIN_VERIFY, "BeginVerify Message. "},
+ {LMP_MSG_BEGIN_VERIFY_ACK, "BeginVerifyAck Message. "},
+ {LMP_MSG_BEGIN_VERIFY_NACK, "BeginVerifyNack Message. "},
+ {LMP_MSG_END_VERIFY, "EndVerify Message. "},
+ {LMP_MSG_END_VERIFY_ACK, "EndVerifyAck Message. "},
+ {LMP_MSG_TEST, "Test Message. "},
+ {LMP_MSG_TEST_STATUS_SUCCESS, "TestStatusSuccess Message. "},
+ {LMP_MSG_TEST_STATUS_FAILURE, "TestStatusFailure Message. "},
+ {LMP_MSG_TEST_STATUS_ACK, "TestStatusAck Message. "},
+ {LMP_MSG_LINK_SUMMARY, "LinkSummary Message. "},
+ {LMP_MSG_LINK_SUMMARY_ACK, "LinkSummaryAck Message. "},
+ {LMP_MSG_LINK_SUMMARY_NACK, "LinkSummaryNack Message. "},
+ {LMP_MSG_CHANNEL_STATUS, "ChannelStatus Message. "},
+ {LMP_MSG_CHANNEL_STATUS_ACK, "ChannelStatusAck Message. "},
+ {LMP_MSG_CHANNEL_STATUS_REQ, "ChannelStatusRequest Message. "},
+ {LMP_MSG_CHANNEL_STATUS_RESP, "ChannelStatusResponse Message. "},
+ {0, NULL}
+};
+
+/*------------------------------------------------------------------------------
+ * LMP object classes
+ */
+#define LMP_CLASS_NULL 0
+
+#define LMP_CLASS_LOCAL_CCID 1
+#define LMP_CLASS_REMOTE_CCID 2
+#define LMP_CLASS_LOCAL_NODE_ID 3
+#define LMP_CLASS_REMOTE_NODE_ID 4
+#define LMP_CLASS_LOCAL_LINK_ID 5
+#define LMP_CLASS_REMOTE_LINK_ID 6
+#define LMP_CLASS_LOCAL_INTERFACE_ID 7
+#define LMP_CLASS_REMOTE_INTERFACE_ID 8
+#define LMP_CLASS_MESSAGE_ID 9
+#define LMP_CLASS_MESSAGE_ID_ACK 10
+#define LMP_CLASS_CONFIG 11
+#define LMP_CLASS_HELLO 12
+#define LMP_CLASS_BEGIN_VERIFY 13
+#define LMP_CLASS_BEGIN_VERIFY_ACK 14
+#define LMP_CLASS_VERIFY_ID 15
+#define LMP_CLASS_TE_LINK 16
+#define LMP_CLASS_DATA_LINK 17
+#define LMP_CLASS_CHANNEL_STATUS 18
+#define LMP_CLASS_CHANNEL_STATUS_REQUEST 19
+#define LMP_CLASS_ERROR 20
+#define LMP_CLASS_MAX 20
+
+#define LMP_09_CLASS_CCID 1
+#define LMP_09_CLASS_NODE_ID 2
+#define LMP_09_CLASS_LINK_ID 3
+#define LMP_09_CLASS_INTERFACE_ID 4
+#define LMP_09_CLASS_MESSAGE_ID 5
+#define LMP_09_CLASS_CONFIG 6
+#define LMP_09_CLASS_HELLO 7
+#define LMP_09_CLASS_BEGIN_VERIFY 8
+#define LMP_09_CLASS_BEGIN_VERIFY_ACK 9
+#define LMP_09_CLASS_VERIFY_ID 10
+#define LMP_09_CLASS_TE_LINK 11
+#define LMP_09_CLASS_DATA_LINK 12
+#define LMP_09_CLASS_CHANNEL_STATUS 13
+#define LMP_09_CLASS_CHANNEL_STATUS_REQUEST 14
+#define LMP_09_CLASS_ERROR 20
+#define LMP_09_CLASS_MAX 15
+
+static value_string lmp_class_vals[] = {
+
+ {LMP_CLASS_LOCAL_CCID, "LOCAL_CCID"},
+ {LMP_CLASS_REMOTE_CCID, "REMOTE_CCID"},
+ {LMP_CLASS_LOCAL_NODE_ID, "LOCAL_NODE_ID"},
+ {LMP_CLASS_REMOTE_NODE_ID, "REMOTE_NODE_ID"},
+ {LMP_CLASS_LOCAL_LINK_ID, "LOCAL_LINK_ID"},
+ {LMP_CLASS_REMOTE_LINK_ID, "REMOTE_LINK_ID"},
+ {LMP_CLASS_LOCAL_INTERFACE_ID, "LOCAL_INTERFACE_ID"},
+ {LMP_CLASS_REMOTE_INTERFACE_ID, "REMOTE_INTERFACE_ID"},
+ {LMP_CLASS_MESSAGE_ID, "MESSAGE_ID"},
+ {LMP_CLASS_MESSAGE_ID_ACK, "MESSAGE_ID_ACK"},
+ {LMP_CLASS_CONFIG, "CONFIG"},
+ {LMP_CLASS_HELLO, "HELLO"},
+ {LMP_CLASS_BEGIN_VERIFY, "BEGIN_VERIFY"},
+ {LMP_CLASS_BEGIN_VERIFY_ACK, "BEGIN_VERIFY_ACK"},
+ {LMP_CLASS_VERIFY_ID, "VERIFY_ID"},
+ {LMP_CLASS_TE_LINK, "TE_LINK"},
+ {LMP_CLASS_DATA_LINK, "DATA_LINK"},
+ {LMP_CLASS_CHANNEL_STATUS, "CHANNEL_STATUS"},
+ {LMP_CLASS_CHANNEL_STATUS_REQUEST, "CHANNEL_STATUS_REQUEST"},
+ {LMP_CLASS_ERROR, "ERROR"},
+};
+
+static value_string lmp_09_class_vals[] = {
+
+ {LMP_09_CLASS_CCID, "CCID"},
+ {LMP_09_CLASS_NODE_ID, "NODE_ID"},
+ {LMP_09_CLASS_LINK_ID, "LINK_ID"},
+ {LMP_09_CLASS_INTERFACE_ID, "INTERFACE_ID"},
+ {LMP_09_CLASS_MESSAGE_ID, "MESSAGE_ID"},
+ {LMP_09_CLASS_CONFIG, "CONFIG"},
+ {LMP_09_CLASS_HELLO, "HELLO"},
+ {LMP_09_CLASS_BEGIN_VERIFY, "BEGIN_VERIFY"},
+ {LMP_09_CLASS_BEGIN_VERIFY_ACK, "BEGIN_VERIFY_ACK"},
+ {LMP_09_CLASS_VERIFY_ID, "VERIFY_ID"},
+ {LMP_09_CLASS_TE_LINK, "TE_LINK"},
+ {LMP_09_CLASS_DATA_LINK, "DATA_LINK"},
+ {LMP_09_CLASS_CHANNEL_STATUS, "CHANNEL_STATUS"},
+ {LMP_09_CLASS_CHANNEL_STATUS_REQUEST, "CHANNEL_STATUS_REQUEST"},
+ {LMP_09_CLASS_ERROR, "ERROR"},
+};
+
+
+#define VALID_CLASS(class) ((class) > LMP_CLASS_NULL && (class) < LMP_CLASS_MAX)
+#define VALID_09_CLASS(class) ((class) > LMP_CLASS_NULL && (((class) < LMP_09_CLASS_CHANNEL_STATUS_REQUEST) || ((class)==LMP_09_CLASS_ERROR)))
+
+/*------------------------------------------------------------------------------
+ * Other constants & stuff
+ */
+
+/* Channel Status */
+static const value_string channel_status_str[] = {
+ {1, "Signal Okay (OK)"},
+ {2, "Signal Degraded (SD)"},
+ {3, "Signal Failed (SF)"},
+};
+static const value_string channel_status_short_str[] = {
+ {1, "OK"},
+ {2, "SD"},
+ {3, "SF"},
+};
+
+/*------------------------------------------------------------------------------
+ * LMP Filter values
+ */
+
+enum lmp_filter_keys {
+
+ /* Message types ---------------- */
+ LMPF_MSG,
+
+ LMPF_MSG_CONFIG,
+ LMPF_MSG_CONFIG_ACK,
+ LMPF_MSG_CONFIG_NACK,
+ LMPF_MSG_HELLO,
+ LMPF_MSG_BEGIN_VERIFY,
+ LMPF_MSG_BEGIN_VERIFY_ACK,
+ LMPF_MSG_BEGIN_VERIFY_NACK,
+ LMPF_MSG_END_VERIFY,
+ LMPF_MSG_END_VERIFY_ACK,
+ LMPF_MSG_TEST,
+ LMPF_MSG_TEST_STATUS_SUCCESS,
+ LMPF_MSG_TEST_STATUS_FAILURE,
+ LMPF_MSG_TEST_STATUS_ACK,
+ LMPF_MSG_LINK_SUMMARY,
+ LMPF_MSG_LINK_SUMMARY_ACK,
+ LMPF_MSG_LINK_SUMMARY_NACK,
+ LMPF_MSG_CHANNEL_STATUS,
+ LMPF_MSG_CHANNEL_STATUS_ACK,
+ LMPF_MSG_CHANNEL_STATUS_REQ,
+ LMPF_MSG_CHANNEL_STATUS_RESP,
+
+ /* LMP Message Header Fields ------------------ */
+ LMPF_HDR_FLAGS,
+ LMPF_HDR_FLAGS_CC_DOWN,
+ LMPF_HDR_FLAGS_REBOOT,
+
+ /* LMP Object Class Filters -------------------- */
+ LMPF_OBJECT,
+
+ LMPF_CLASS_LOCAL_CCID,
+ LMPF_CLASS_REMOTE_CCID,
+ LMPF_CLASS_LOCAL_NODE_ID,
+ LMPF_CLASS_REMOTE_NODE_ID,
+ LMPF_CLASS_LOCAL_LINK_ID,
+ LMPF_CLASS_REMOTE_LINK_ID,
+ LMPF_CLASS_LOCAL_INTERFACE_ID,
+ LMPF_CLASS_REMOTE_INTERFACE_ID,
+ LMPF_CLASS_MESSAGE_ID,
+ LMPF_CLASS_MESSAGE_ID_ACK,
+ LMPF_CLASS_CONFIG,
+ LMPF_CLASS_HELLO,
+ LMPF_CLASS_BEGIN_VERIFY,
+ LMPF_CLASS_BEGIN_VERIFY_ACK,
+ LMPF_CLASS_VERIFY_ID,
+ LMPF_CLASS_TE_LINK,
+ LMPF_CLASS_DATA_LINK,
+ LMPF_CLASS_CHANNEL_STATUS,
+ LMPF_CLASS_CHANNEL_STATUS_REQUEST,
+ LMPF_CLASS_ERROR,
+
+ LMPF_09_OBJECT,
+
+ LMPF_09_CLASS_CCID,
+ LMPF_09_CLASS_NODE_ID,
+ LMPF_09_CLASS_LINK_ID,
+ LMPF_09_CLASS_INTERFACE_ID,
+ LMPF_09_CLASS_MESSAGE_ID,
+ LMPF_09_CLASS_CONFIG,
+ LMPF_09_CLASS_HELLO,
+ LMPF_09_CLASS_BEGIN_VERIFY,
+ LMPF_09_CLASS_BEGIN_VERIFY_ACK,
+ LMPF_09_CLASS_VERIFY_ID,
+ LMPF_09_CLASS_TE_LINK,
+ LMPF_09_CLASS_DATA_LINK,
+ LMPF_09_CLASS_CHANNEL_STATUS,
+ LMPF_09_CLASS_CHANNEL_STATUS_REQUEST,
+ LMPF_09_CLASS_ERROR,
+
+ LMPF_VAL_CTYPE,
+ LMPF_VAL_LOCAL_CCID,
+ LMPF_VAL_REMOTE_CCID,
+ LMPF_VAL_LOCAL_NODE_ID,
+ LMPF_VAL_REMOTE_NODE_ID,
+ LMPF_VAL_LOCAL_LINK_ID_IPV4,
+ LMPF_VAL_LOCAL_LINK_ID_IPV6,
+ LMPF_VAL_LOCAL_LINK_ID_UNNUM,
+ LMPF_VAL_REMOTE_LINK_ID_IPV4,
+ LMPF_VAL_REMOTE_LINK_ID_IPV6,
+ LMPF_VAL_REMOTE_LINK_ID_UNNUM,
+ LMPF_VAL_LOCAL_INTERFACE_ID_IPV4,
+ LMPF_VAL_LOCAL_INTERFACE_ID_IPV6,
+ LMPF_VAL_LOCAL_INTERFACE_ID_UNNUM,
+ LMPF_VAL_REMOTE_INTERFACE_ID_IPV4,
+ LMPF_VAL_REMOTE_INTERFACE_ID_IPV6,
+ LMPF_VAL_REMOTE_INTERFACE_ID_UNNUM,
+ LMPF_VAL_MESSAGE_ID,
+ LMPF_VAL_MESSAGE_ID_ACK,
+ LMPF_VAL_CONFIG_HELLO,
+ LMPF_VAL_CONFIG_HELLO_DEAD,
+ LMPF_VAL_HELLO_TXSEQ,
+ LMPF_VAL_HELLO_RXSEQ,
+
+ LMPF_VAL_BEGIN_VERIFY_FLAGS,
+ LMPF_VAL_BEGIN_VERIFY_FLAGS_ALL_LINKS,
+ LMPF_VAL_BEGIN_VERIFY_FLAGS_LINK_TYPE,
+ LMPF_VAL_BEGIN_VERIFY_INTERVAL,
+ LMPF_VAL_BEGIN_VERIFY_ENCTYPE,
+ LMPF_VAL_BEGIN_VERIFY_TRANSPORT,
+ LMPF_VAL_BEGIN_VERIFY_TRANSMISSION_RATE,
+ LMPF_VAL_BEGIN_VERIFY_WAVELENGTH,
+ LMPF_VAL_VERIFY_ID,
+
+ LMPF_VAL_TE_LINK_FLAGS,
+ LMPF_VAL_TE_LINK_FLAGS_FAULT_MGMT,
+ LMPF_VAL_TE_LINK_FLAGS_LINK_VERIFY,
+ LMPF_VAL_TE_LINK_LOCAL_IPV4,
+ LMPF_VAL_TE_LINK_LOCAL_UNNUM,
+ LMPF_VAL_TE_LINK_REMOTE_IPV4,
+ LMPF_VAL_TE_LINK_REMOTE_UNNUM,
+
+ LMPF_VAL_DATA_LINK_FLAGS,
+ LMPF_VAL_DATA_LINK_FLAGS_PORT,
+ LMPF_VAL_DATA_LINK_FLAGS_ALLOCATED,
+ LMPF_VAL_DATA_LINK_LOCAL_IPV4,
+ LMPF_VAL_DATA_LINK_LOCAL_UNNUM,
+ LMPF_VAL_DATA_LINK_REMOTE_IPV4,
+ LMPF_VAL_DATA_LINK_REMOTE_UNNUM,
+ LMPF_VAL_DATA_LINK_SUBOBJ,
+ LMPF_VAL_DATA_LINK_SUBOBJ_SWITCHING_TYPE,
+ LMPF_VAL_DATA_LINK_SUBOBJ_LSP_ENCODING,
+
+ LMPF_VAL_ERROR,
+ LMPF_VAL_ERROR_VERIFY_UNSUPPORTED_LINK,
+ LMPF_VAL_ERROR_VERIFY_UNWILLING,
+ LMPF_VAL_ERROR_VERIFY_TRANSPORT,
+ LMPF_VAL_ERROR_VERIFY_TE_LINK_ID,
+ LMPF_VAL_ERROR_VERIFY_UNKNOWN_CTYPE,
+ LMPF_VAL_ERROR_SUMMARY_BAD_PARAMETERS,
+ LMPF_VAL_ERROR_SUMMARY_RENEGOTIATE,
+ LMPF_VAL_ERROR_SUMMARY_BAD_TE_LINK,
+ LMPF_VAL_ERROR_SUMMARY_BAD_DATA_LINK,
+ LMPF_VAL_ERROR_SUMMARY_UNKNOWN_TEL_CTYPE,
+ LMPF_VAL_ERROR_SUMMARY_UNKNOWN_DL_CTYPE,
+ LMPF_VAL_ERROR_SUMMARY_BAD_REMOTE_LINK_ID,
+ LMPF_VAL_ERROR_CONFIG_BAD_PARAMETERS,
+ LMPF_VAL_ERROR_CONFIG_RENEGOTIATE,
+ LMPF_VAL_ERROR_CONFIG_BAD_CCID,
+
+ LMPF_VAL_SVCCFG_SIGPROTO_PROTO,
+ LMPF_VAL_SVCCFG_SIGPROTO_UNI_VERSION,
+ LMPF_VAL_SVCCFG_PORTATTR_LINK_TYPE,
+ LMPF_VAL_SVCCFG_PORTATTR_SIGNAL_TYPE,
+ LMPF_VAL_SVCCFG_PORTATTR_TP_TRANSPARENCY,
+ LMPF_VAL_SVCCFG_PORTATTR_MAX_NCC,
+ LMPF_VAL_SVCCFG_PORTATTR_MIN_NCC,
+ LMPF_VAL_SVCCFG_PORTATTR_MAX_NVC,
+ LMPF_VAL_SVCCFG_PORTATTR_MIN_NVC,
+ LMPF_VAL_SVCCFG_PORTATTR_INTFC_ID,
+ LMPF_VAL_SVCCFG_TRANSP_TRANSPARENCY,
+ LMPF_VAL_SVCCFG_TRANSP_TCM,
+ LMPF_VAL_SVCCFG_DIVERSITY_DIVERSITY,
+
+ LMPF_MAX
+};
+
+static int lmp_filter[LMPF_MAX];
+
+static hf_register_info lmpf_info[] = {
+
+ /* Message type number */
+ {&lmp_filter[LMPF_MSG],
+ { "Message Type", "lmp.msg", FT_UINT8, BASE_DEC, VALS(message_type_vals), 0x0,
+ "", HFILL }},
+
+ /* Message type shorthands */
+ {&lmp_filter[LMPF_MSG_CONFIG],
+ { "Config Message", "lmp.msg.config", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_CONFIG_ACK],
+ { "ConfigAck Message", "lmp.msg.configack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_CONFIG_NACK],
+ { "ConfigNack Message", "lmp.msg.confignack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_HELLO],
+ { "HELLO Message", "lmp.msg.hello", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_BEGIN_VERIFY],
+ { "BeginVerify Message", "lmp.msg.beginverify", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_BEGIN_VERIFY_ACK],
+ { "BeginVerifyAck Message", "lmp.msg.beginverifyack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_BEGIN_VERIFY_NACK],
+ { "BeginVerifyNack Message", "lmp.msg.beginverifynack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_END_VERIFY],
+ { "EndVerify Message", "lmp.msg.endverify", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_END_VERIFY_ACK],
+ { "EndVerifyAck Message", "lmp.msg.endverifyack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_TEST],
+ { "Test Message", "lmp.msg.test", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_TEST_STATUS_SUCCESS],
+ { "TestStatusSuccess Message", "lmp.msg.teststatussuccess", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_TEST_STATUS_FAILURE],
+ { "TestStatusFailure Message", "lmp.msg.teststatusfailure", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_TEST_STATUS_ACK],
+ { "TestStatusAck Message", "lmp.msg.teststatusack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_LINK_SUMMARY],
+ { "LinkSummary Message", "lmp.msg.linksummary", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_LINK_SUMMARY_ACK],
+ { "LinkSummaryAck Message", "lmp.msg.linksummaryack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_LINK_SUMMARY_NACK],
+ { "LinkSummaryNack Message", "lmp.msg.linksummarynack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_CHANNEL_STATUS],
+ { "ChannelStatus Message", "lmp.msg.channelstatus", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_CHANNEL_STATUS_ACK],
+ { "ChannelStatusAck Message", "lmp.msg.channelstatusack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_CHANNEL_STATUS_REQ],
+ { "ChannelStatusRequest Message", "lmp.msg.channelstatusrequest", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_MSG_CHANNEL_STATUS_RESP],
+ { "ChannelStatusResponse Message", "lmp.msg.channelstatusresponse", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+
+ /* LMP Message Header Fields ------------------- */
+
+ {&lmp_filter[LMPF_HDR_FLAGS],
+ { "LMP Header - Flags", "lmp.hdr.flags", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_HDR_FLAGS_CC_DOWN],
+ { "ControlChannelDown", "lmp.hdr.ccdown", FT_BOOLEAN, 8, NULL, 0x01,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_HDR_FLAGS_REBOOT],
+ { "Reboot", "lmp.hdr.reboot", FT_BOOLEAN, 8, NULL, 0x02,
+ "", HFILL }},
+
+ /* LMP object class filters ------------------------------- */
+
+ {&lmp_filter[LMPF_OBJECT],
+ { "LOCAL_CCID", "lmp.object", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_CLASS_LOCAL_CCID],
+ { "Local CCID", "lmp.obj.ccid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_REMOTE_CCID],
+ { "Remote CCID", "lmp.obj.ccid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_LOCAL_NODE_ID],
+ { "Local NODE_ID", "lmp.obj.Nodeid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_REMOTE_NODE_ID],
+ { "Remote NODE_ID", "lmp.obj.Nodeid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_LOCAL_LINK_ID],
+ { "Local LINK_ID", "lmp.obj.linkid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_REMOTE_LINK_ID],
+ { "Remote LINK_ID", "lmp.obj.linkid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_LOCAL_INTERFACE_ID],
+ { "Local INTERFACE_ID", "lmp.obj.interfaceid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_REMOTE_INTERFACE_ID],
+ { "Remote INTERFACE_ID", "lmp.obj.interfaceid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_MESSAGE_ID],
+ { "MESSAGE_ID", "lmp.obj.messageid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_MESSAGE_ID_ACK],
+ { "MESSAGE_ID Ack", "lmp.obj.messageid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_CONFIG],
+ { "CONFIG", "lmp.obj.config", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_HELLO],
+ { "HELLO", "lmp.obj.hello", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_BEGIN_VERIFY],
+ { "BEGIN_VERIFY", "lmp.obj.begin_verify", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_BEGIN_VERIFY_ACK],
+ { "BEGIN_VERIFY_ACK", "lmp.obj.begin_verify_ack", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_VERIFY_ID],
+ { "VERIFY_ID", "lmp.obj.verifyid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_CLASS_TE_LINK],
+ { "TE_LINK", "lmp.obj.te_link", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_DATA_LINK],
+ { "DATA_LINK", "lmp.obj.data_link", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_CLASS_CHANNEL_STATUS],
+ { "CHANNEL_STATUS", "lmp.obj.channel_status", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_CHANNEL_STATUS_REQUEST],
+ { "CHANNEL_STATUS_REQUEST", "lmp.obj.channel_status_request", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_CLASS_ERROR],
+ { "ERROR", "lmp.obj.error", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_09_OBJECT],
+ { "LOCAL_CCID", "lmp.object", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_09_CLASS_CCID],
+ { "CCID", "lmp.obj.ccid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_NODE_ID],
+ { "NODE_ID", "lmp.obj.Nodeid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_LINK_ID],
+ { "LINK_ID", "lmp.obj.linkid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_INTERFACE_ID],
+ { "INTERFACE_ID", "lmp.obj.interfaceid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_MESSAGE_ID],
+ { "MESSAGE_ID", "lmp.obj.messageid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_CONFIG],
+ { "CONFIG", "lmp.obj.config", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_HELLO],
+ { "HELLO", "lmp.obj.hello", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_BEGIN_VERIFY],
+ { "BEGIN_VERIFY", "lmp.obj.begin_verify", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_BEGIN_VERIFY_ACK],
+ { "BEGIN_VERIFY_ACK", "lmp.obj.begin_verify_ack", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_VERIFY_ID],
+ { "VERIFY_ID", "lmp.obj.verifyid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_09_CLASS_TE_LINK],
+ { "TE_LINK", "lmp.obj.te_link", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_DATA_LINK],
+ { "DATA_LINK", "lmp.obj.data_link", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_09_CLASS_CHANNEL_STATUS],
+ { "CHANNEL_STATUS", "lmp.obj.channel_status", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_CHANNEL_STATUS_REQUEST],
+ { "CHANNEL_STATUS_REQUEST", "lmp.obj.channel_status_request", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_09_CLASS_ERROR],
+ { "ERROR", "lmp.obj.error", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ /* Other LMP Value Filters ------------------------------ */
+
+ {&lmp_filter[LMPF_VAL_CTYPE],
+ { "Object C-Type", "lmp.obj.ctype", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_LOCAL_CCID],
+ { "Local CCID Value", "lmp.local_ccid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_REMOTE_CCID],
+ { "Remote CCID Value", "lmp.remote_ccid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_LOCAL_NODE_ID],
+ { "Local Node ID Value", "lmp.local_nodeid", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_REMOTE_NODE_ID],
+ { "Remote Node ID Value", "lmp.remote_nodeid", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_LOCAL_LINK_ID_IPV4],
+ { "Local Link ID - IPv4", "lmp.local_linkid_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_LOCAL_LINK_ID_UNNUM],
+ { "Local Link ID - Unnumbered", "lmp.local_linkid_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_REMOTE_LINK_ID_IPV4],
+ { "Remote Link ID - IPv4", "lmp.remote_linkid_ipv4", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_REMOTE_LINK_ID_UNNUM],
+ { "Remote Link ID - Unnumbered", "lmp.remote_linkid_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_LOCAL_INTERFACE_ID_IPV4],
+ { "Local Interface ID - IPv4", "lmp.local_interfaceid_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_LOCAL_INTERFACE_ID_UNNUM],
+ { "Local Interface ID - Unnumbered", "lmp.local_interfaceid_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_REMOTE_INTERFACE_ID_IPV4],
+ { "Remote Interface ID - IPv4", "lmp.remote_interfaceid_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_REMOTE_INTERFACE_ID_UNNUM],
+ { "Remote Interface ID - Unnumbered", "lmp.remote_interfaceid_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_MESSAGE_ID],
+ { "Message-ID Value", "lmp.messageid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_MESSAGE_ID_ACK],
+ { "Message-ID Ack Value", "lmp.messageid_ack", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_CONFIG_HELLO],
+ { "HelloInterval", "lmp.hellointerval", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_CONFIG_HELLO_DEAD],
+ { "HelloDeadInterval", "lmp.hellodeadinterval", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_HELLO_TXSEQ],
+ { "TxSeqNum", "lmp.txseqnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_HELLO_RXSEQ],
+ { "RxSeqNum", "lmp.rxseqnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS],
+ { "Flags", "lmp.begin_verify.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_ALL_LINKS],
+ { "Verify All Links", "lmp.begin_verify.all_links",
+ FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_LINK_TYPE],
+ { "Data Link Type", "lmp.begin_verify.link_type",
+ FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_BEGIN_VERIFY_ENCTYPE],
+ { "Encoding Type", "lmp.begin_verify.enctype", FT_UINT8, BASE_DEC, VALS(gmpls_lsp_enc_str), 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_VERIFY_ID],
+ { "Verify-ID", "lmp.verifyid", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_TE_LINK_FLAGS],
+ { "TE-Link Flags", "lmp.te_link_flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_TE_LINK_FLAGS_FAULT_MGMT],
+ { "Fault Management Supported", "lmp.te_link.fault_mgmt",
+ FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_TE_LINK_FLAGS_LINK_VERIFY],
+ { "Link Verification Supported", "lmp.te_link.link_verify",
+ FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_TE_LINK_LOCAL_IPV4],
+ { "TE-Link Local ID - IPv4", "lmp.te_link.local_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_TE_LINK_LOCAL_UNNUM],
+ { "TE-Link Local ID - Unnumbered", "lmp.te_link.local_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_TE_LINK_REMOTE_IPV4],
+ { "TE-Link Remote ID - IPv4", "lmp.te_link.remote_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_TE_LINK_REMOTE_UNNUM],
+ { "TE-Link Remote ID - Unnumbered", "lmp.te_link.remote_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_DATA_LINK_FLAGS],
+ { "Data-Link Flags", "lmp.data_link_flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_PORT],
+ { "Data-Link is Individual Port", "lmp.data_link.port",
+ FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_ALLOCATED],
+ { "Data-Link is Allocated", "lmp.data_link.link_verify",
+ FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_IPV4],
+ { "Data-Link Local ID - IPv4", "lmp.data_link.local_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_UNNUM],
+ { "Data-Link Local ID - Unnumbered", "lmp.data_link.local_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_IPV4],
+ { "Data-Link Remote ID - IPv4", "lmp.data_link.remote_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_UNNUM],
+ { "Data-Link Remote ID - Unnumbered", "lmp.data_link.remote_unnum", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ],
+ { "Subobject", "lmp.data_link_subobj", FT_NONE, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ {&lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_SWITCHING_TYPE],
+ { "Interface Switching Capability", "lmp.data_link_switching", FT_UINT8, BASE_DEC,
+ VALS(gmpls_switching_type_str), 0x0, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_LSP_ENCODING],
+ { "LSP Encoding Type", "lmp.data_link_encoding", FT_UINT8, BASE_DEC,
+ VALS(gmpls_lsp_enc_str), 0x0, "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_ERROR],
+ { "Error Code", "lmp.error", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_ERROR_VERIFY_UNSUPPORTED_LINK],
+ { "Verification - Unsupported for this TE-Link", "lmp.error.verify_unsupported_link",
+ FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_VERIFY_UNWILLING],
+ { "Verification - Unwilling to Verify at this time", "lmp.error.verify_unwilling",
+ FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_VERIFY_TRANSPORT],
+ { "Verification - Transport Unsupported", "lmp.error.verify_unsupported_transport",
+ FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_VERIFY_TE_LINK_ID],
+ { "Verification - TE Link ID Configuration Error", "lmp.error.verify_te_link_id",
+ FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_ERROR_VERIFY_UNKNOWN_CTYPE],
+ { "Verification - Unknown Object C-Type", "lmp.error.verify_unknown_ctype",
+ FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }},
+
+ {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_PARAMETERS],
+ { "Summary - Unacceptable non-negotiable parameters", "lmp.error.summary_bad_params",
+ FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_RENEGOTIATE],
+ { "Summary - Renegotiate Parametere", "lmp.error.summary_renegotiate",
+ FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_TE_LINK],
+ { "Summary - Bad TE Link Object", "lmp.error.summary_bad_te_link",
+ FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_DATA_LINK],
+ { "Summary - Bad Data Link Object", "lmp.error.summary_bad_data_link",
+ FT_BOOLEAN, 8, NULL, 0x10, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_UNKNOWN_TEL_CTYPE],
+ { "Summary - Bad TE Link C-Type", "lmp.error.summary_unknown_tel_ctype",
+ FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_UNKNOWN_DL_CTYPE],
+ { "Summary - Bad Data Link C-Type", "lmp.error.summary_unknown_dl_ctype",
+ FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_REMOTE_LINK_ID],
+ { "Summary - Bad Remote Link ID", "lmp.error.summary_bad_remote_link_id",
+ FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_CONFIG_BAD_PARAMETERS],
+ { "Config - Unacceptable non-negotiable parameters", "lmp.error.config_bad_params",
+ FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_CONFIG_RENEGOTIATE],
+ { "Config - Renegotiate Parametere", "lmp.error.config_renegotiate",
+ FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }},
+ {&lmp_filter[LMPF_VAL_ERROR_CONFIG_BAD_CCID],
+ { "Config - Bad CC ID", "lmp.error.config_bad_ccid",
+ FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }}
+
+};
+
+static int
+lmp_class_to_filter_num(int class)
+{
+ if (VALID_CLASS(class))
+ return class + LMPF_OBJECT;
+ return -1;
+}
+
+static int
+lmp_09_class_to_filter_num(int class)
+{
+ guint16 gap = LMP_09_CLASS_ERROR - LMP_09_CLASS_CHANNEL_STATUS_REQUEST;
+
+ if (VALID_09_CLASS(class)) {
+ if (class != LMP_09_CLASS_ERROR)
+ return LMPF_09_OBJECT + class;
+ else {
+ return LMPF_09_OBJECT + class - gap + 1;
+ }
+ }
+ return -1;
+}
+
+
+/*------------------------------------------------------------------------------
+ * LMP Subtrees
+ *
+ * We have two types of subtrees - a statically defined, constant set and
+ * a class set - one for each class. The static ones are before all the class ones
+ */
+enum {
+ LMP_TREE_MAIN,
+ LMP_TREE_HEADER,
+ LMP_TREE_HEADER_FLAGS,
+ LMP_TREE_OBJECT_HEADER,
+ LMP_TREE_ERROR_FLAGS,
+ LMP_TREE_BEGIN_VERIFY_FLAGS,
+ LMP_TREE_BEGIN_VERIFY_TRANSPORT_FLAGS,
+ LMP_TREE_TE_LINK_FLAGS,
+ LMP_TREE_DATA_LINK_FLAGS,
+ LMP_TREE_DATA_LINK_SUBOBJ,
+ LMP_TREE_CHANNEL_STATUS_ID,
+
+ LMP_TREE_CLASS_START
+};
+#define NUM_LMP_SUBTREES (LMP_TREE_CLASS_START + LMP_CLASS_MAX)
+#define NUM_LMP_09_SUBTREES (LMP_TREE_CLASS_START + LMP_09_CLASS_MAX)
+
+static gint lmp_subtree[MAX(NUM_LMP_SUBTREES,NUM_LMP_09_SUBTREES)];
+static gint lmp_09_subtree[NUM_LMP_09_SUBTREES];
+
+static int lmp_class_to_subtree(int class)
+{
+ if (VALID_CLASS(class))
+ return lmp_subtree[LMP_TREE_CLASS_START + class];
+
+ return -1;
+}
+
+static int lmp_09_class_to_subtree(int class)
+{
+ if (VALID_09_CLASS(class))
+ return lmp_09_subtree[LMP_TREE_CLASS_START + class];
+
+ return -1;
+}
+
+/*------------------------------------------------------------------------------
+ * Da code
+ */
+
+static void
+dissect_lmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *lmp_tree = NULL, *ti, *ti2;
+ proto_tree *lmp_header_tree;
+ proto_tree *lmp_header_flags_tree;
+ proto_tree *lmp_object_tree;
+ proto_tree *lmp_object_header_tree;
+ proto_tree *lmp_flags_tree;
+ proto_tree *lmp_subobj_tree;
+
+ guint8 version;
+ guint8 flags;
+ guint8 message_type;
+ guint16 cksum, computed_cksum;
+ vec_t cksum_vec[1];
+ int j, k, l, len;
+ int msg_length;
+ int obj_length;
+ int mylen;
+ int offset2;
+ int proto;
+
+ proto = pinfo->ipproto;
+ /* If the current preference is NOT LMP09, do not process UDP packets */
+ if ((proto == IP_PROTO_UDP) && (lmp_draft_ver != LMP_VER_DRAFT_CCAMP_09)) {
+ return;
+ }
+ /* If the current preference is NOT LMP09, process only UDP packets */
+ if ((proto != IP_PROTO_UDP) && (lmp_draft_ver == LMP_VER_DRAFT_CCAMP_09)) {
+ return;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LMP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ version = (tvb_get_guint8(tvb, offset+0)) >> 4;
+ flags = tvb_get_guint8(tvb, offset+2);
+ message_type = tvb_get_guint8(tvb, offset+3);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(message_type, message_type_vals, "Unknown (%u). "));
+ }
+
+ if (tree) {
+ msg_length = tvb_get_ntohs(tvb, offset+4);
+ ti = proto_tree_add_item(tree, proto_lmp, tvb, offset, msg_length,
+ FALSE);
+ lmp_tree = proto_item_add_subtree(ti, lmp_subtree[LMP_TREE_MAIN]);
+ ti = proto_tree_add_text(lmp_tree, tvb, offset, 12, "LMP Header. %s",
+ val_to_str(message_type, message_type_vals,
+ "Unknown Message (%u). "));
+ lmp_header_tree = proto_item_add_subtree(ti, lmp_subtree[LMP_TREE_HEADER]);
+ proto_tree_add_text(lmp_header_tree, tvb, offset, 1, "LMP Version: %u",
+ version);
+ ti = proto_tree_add_text(lmp_header_tree, tvb, offset+2, 1, "Flags: %02x",
+ flags);
+ lmp_header_flags_tree = proto_item_add_subtree(ti, lmp_subtree[LMP_TREE_HEADER_FLAGS]);
+ proto_tree_add_boolean(lmp_header_flags_tree, lmp_filter[LMPF_HDR_FLAGS_CC_DOWN],
+ tvb, offset+2, 1, flags);
+ proto_tree_add_boolean(lmp_header_flags_tree, lmp_filter[LMPF_HDR_FLAGS_REBOOT],
+ tvb, offset+2, 1, flags);
+ proto_tree_add_uint(lmp_header_tree, lmp_filter[LMPF_MSG], tvb,
+ offset+3, 1, message_type);
+ proto_tree_add_text(lmp_header_tree, tvb, offset+4, 2, "Length: %d bytes",
+ msg_length);
+ if (LMPF_MSG + message_type <= LMPF_MSG_CHANNEL_STATUS_RESP &&
+ message_type > 0) {
+ proto_tree_add_boolean_hidden(lmp_header_tree, lmp_filter[LMPF_MSG + message_type], tvb,
+ offset+3, 1, 1);
+ } else {
+ proto_tree_add_protocol_format(lmp_header_tree, proto_malformed, tvb, offset+3, 1,
+ "Invalid message type: %u", message_type);
+ return;
+ }
+
+ cksum = tvb_get_ntohs(tvb, offset+6);
+ if (!pinfo->fragmented && (int) tvb_length(tvb) >= msg_length) {
+ /* The packet isn't part of a fragmented datagram and isn't
+ truncated, so we can checksum it. */
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, msg_length);
+ cksum_vec[0].len = msg_length;
+ computed_cksum = in_cksum(&cksum_vec[0], 1);
+
+ if (computed_cksum == 0) {
+ proto_tree_add_text(lmp_header_tree, tvb, offset+6, 2,
+ "Message Checksum: 0x%04x (correct)",
+ cksum);
+ } else {
+ proto_tree_add_text(lmp_header_tree, tvb, offset+6, 2,
+ "Message Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ cksum,
+ in_cksum_shouldbe(cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_text(lmp_header_tree, tvb, offset+6, 2,
+ "Message Checksum: 0x%04x",
+ cksum);
+ }
+
+ offset += 8;
+ len = 8;
+ while (len < msg_length) {
+ guint8 class;
+ guint8 type;
+ guint8 negotiable;
+ char *object_type;
+
+ obj_length = tvb_get_ntohs(tvb, offset+2);
+ class = tvb_get_guint8(tvb, offset+1);
+ type = tvb_get_guint8(tvb, offset);
+ negotiable = (type >> 7); type &= 0x7f;
+ if (lmp_draft_ver == LMP_VER_DRAFT_CCAMP_09) {
+ object_type = val_to_str(class, lmp_09_class_vals, "Unknown");
+ proto_tree_add_uint_hidden(lmp_tree, lmp_filter[LMPF_09_OBJECT],
+ tvb,
+ offset, 1, class);
+ if (VALID_09_CLASS(class)) {
+ ti = proto_tree_add_item(lmp_tree, lmp_filter[lmp_09_class_to_filter_num(class)],
+ tvb, offset, obj_length, FALSE);
+ } else {
+ proto_tree_add_protocol_format(lmp_tree, proto_malformed, tvb, offset+1, 1,
+ "Invalid class: %u", class);
+ return;
+ }
+ lmp_object_tree = proto_item_add_subtree(ti, lmp_09_class_to_subtree(class));
+
+ ti2 = proto_tree_add_text(lmp_object_tree, tvb, offset, 4,
+ "Header. Class %d, C-Type %d, Length %d, %s",
+ class, type, obj_length,
+ negotiable ? "Negotiable" : "Not Negotiable");
+ lmp_object_header_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_OBJECT_HEADER]);
+ proto_tree_add_text(lmp_object_header_tree, tvb, offset, 1,
+ negotiable ? "Negotiable" : "Not Negotiable");
+ proto_tree_add_text(lmp_object_header_tree, tvb, offset+2, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(lmp_object_header_tree, tvb, offset+1, 1,
+ "Object Class: %u - %s",
+ class, object_type);
+ proto_tree_add_item(lmp_object_header_tree, lmp_filter[LMPF_VAL_CTYPE],
+ tvb, offset, 1, type);
+ offset2 = offset+4;
+ mylen = obj_length - 4;
+ } else /* LMP_VER_DRAFT_CCAMP_03 */ {
+ object_type = val_to_str(class, lmp_class_vals, "Unknown");
+ proto_tree_add_uint_hidden(lmp_tree, lmp_filter[LMPF_OBJECT],
+ tvb,
+ offset, 1, class);
+
+ if (VALID_CLASS(class)) {
+ ti = proto_tree_add_item(lmp_tree, lmp_filter[lmp_class_to_filter_num(class)],
+ tvb, offset, obj_length, FALSE);
+ } else {
+ proto_tree_add_protocol_format(lmp_tree, proto_malformed, tvb, offset+1, 1,
+ "Invalid class: %u", class);
+ return;
+ }
+
+ lmp_object_tree = proto_item_add_subtree(ti, lmp_class_to_subtree(class));
+
+ ti2 = proto_tree_add_text(lmp_object_tree, tvb, offset, 4,
+ "Header. Class %d, C-Type %d, Length %d, %s",
+ class, type, obj_length,
+ negotiable ? "Negotiable" : "Not Negotiable");
+ lmp_object_header_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_OBJECT_HEADER]);
+ proto_tree_add_text(lmp_object_header_tree, tvb, offset, 1,
+ negotiable ? "Negotiable" : "Not Negotiable");
+ proto_tree_add_text(lmp_object_header_tree, tvb, offset+2, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(lmp_object_header_tree, tvb, offset+1, 1,
+ "Object Class: %u - %s",
+ class, object_type);
+ proto_tree_add_item(lmp_object_header_tree, lmp_filter[LMPF_VAL_CTYPE],
+ tvb, offset, 1, type);
+ offset2 = offset+4;
+ mylen = obj_length - 4;
+ }
+
+ if (lmp_draft_ver == LMP_VER_DRAFT_CCAMP_09) {
+
+ switch (class) {
+
+ case LMP_CLASS_NULL:
+ break;
+
+ case LMP_09_CLASS_CCID:
+ switch(type) {
+ case 1:
+ l = LMPF_VAL_LOCAL_CCID;
+ proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ tvb_get_ntohl(tvb, offset2));
+ break;
+ case 2:
+ l = LMPF_VAL_REMOTE_CCID;
+ proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ tvb_get_ntohl(tvb, offset2));
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_NODE_ID:
+ switch(type) {
+ case 1:
+ l = LMPF_VAL_LOCAL_NODE_ID;
+ proto_item_append_text(ti, ": %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ case 2:
+ l = LMPF_VAL_REMOTE_NODE_ID;
+ proto_item_append_text(ti, ": %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_LINK_ID:
+ switch(type) {
+ case 1:
+ case 2:
+ l = (type == 1)? LMPF_VAL_LOCAL_LINK_ID_IPV4:
+ LMPF_VAL_REMOTE_LINK_ID_IPV4;
+ proto_item_append_text(ti, ": IPv4 %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ case 3:
+ case 4:
+ l = (type == 3)? LMPF_VAL_LOCAL_LINK_ID_IPV6:
+ LMPF_VAL_REMOTE_LINK_ID_IPV6;
+ proto_item_append_text(ti, ": IPv6 %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, 16, "IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ break;
+ case 5:
+ case 6:
+ l = (type == 5)? LMPF_VAL_LOCAL_LINK_ID_UNNUM:
+ LMPF_VAL_REMOTE_LINK_ID_UNNUM;
+ proto_item_append_text(ti, ": Unnumbered %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_INTERFACE_ID:
+ switch(type) {
+ case 1:
+ case 2:
+ l = (type == 1)? LMPF_VAL_LOCAL_INTERFACE_ID_IPV4:
+ LMPF_VAL_REMOTE_INTERFACE_ID_IPV4;
+ proto_item_append_text(ti, ": IPv4 %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ case 3:
+ case 4:
+ l = (type == 3)? LMPF_VAL_LOCAL_INTERFACE_ID_IPV6:
+ LMPF_VAL_REMOTE_INTERFACE_ID_IPV6;
+ proto_item_append_text(ti, ": IPv6 %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, 16, "IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ break;
+ case 5:
+ case 6:
+ l = (type == 5)? LMPF_VAL_LOCAL_INTERFACE_ID_UNNUM:
+ LMPF_VAL_REMOTE_INTERFACE_ID_UNNUM;
+ proto_item_append_text(ti, ": Unnumbered %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_MESSAGE_ID:
+ switch(type) {
+ case 1:
+ l = LMPF_VAL_MESSAGE_ID;
+ proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ tvb_get_ntohl(tvb, offset2));
+ break;
+ case 2:
+ l = LMPF_VAL_MESSAGE_ID_ACK;
+ proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ tvb_get_ntohl(tvb, offset2));
+ break;
+
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_CONFIG:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": HelloInterval: %d, HelloDeadInterval: %d",
+ tvb_get_ntohs(tvb, offset2), tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_CONFIG_HELLO],
+ tvb, offset2, 2, tvb_get_ntohs(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_CONFIG_HELLO_DEAD],
+ tvb, offset2+2, 2, tvb_get_ntohs(tvb, offset2+2));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_HELLO:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": TxSeq %d, RxSeq: %d",
+ tvb_get_ntohl(tvb, offset2),
+ tvb_get_ntohl(tvb, offset2+4));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_HELLO_TXSEQ],
+ tvb, offset2, 4, tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_HELLO_RXSEQ],
+ tvb, offset2+4, 4, tvb_get_ntohl(tvb, offset2+4));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_BEGIN_VERIFY:
+ switch(type) {
+ case 1:
+ l = tvb_get_ntohs(tvb, offset2);
+ ti2 = proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS],
+ tvb, offset2, 2, FALSE);
+
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_BEGIN_VERIFY_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_ALL_LINKS],
+ tvb, offset2, 2, l);
+ proto_tree_add_boolean(lmp_flags_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_LINK_TYPE],
+ tvb, offset2, 2, l);
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+2, 2,
+ "Verify Interval: %d ms", tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+4, 4,
+ "Number of Data Links: %d", tvb_get_ntohl(tvb, offset2+4));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_ENCTYPE],
+ tvb, offset2+8, 1, FALSE);
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+10, 2,
+ "Verify Transport Mechanism: 0x%0x", tvb_get_ntohs(tvb, offset2+10));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+12, 4,
+ "Transmission Rate: %.10g", tvb_get_ntohieee_float(tvb, offset2+12));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+16, 4,
+ "Wavelength: %d", tvb_get_ntohl(tvb, offset2+16));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_BEGIN_VERIFY_ACK:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": VerifyDeadInterval: %d, TransportResponse: 0x%0x",
+ tvb_get_ntohs(tvb, offset2), tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, 2,
+ "VerifyDeadInterval: %d ms", tvb_get_ntohs(tvb, offset2));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+2, 2,
+ "Verify Transport Response: 0x%0x", tvb_get_ntohs(tvb, offset2+2));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_VERIFY_ID:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_VERIFY_ID], tvb, offset2, 4,
+ tvb_get_ntohl(tvb, offset2));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_TE_LINK:
+ l = tvb_get_guint8(tvb, offset2);
+ ti2 = proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_FLAGS],
+ tvb, offset2, 1, l);
+ proto_item_append_text(ti2, ": %s%s",
+ (l&0x01) ? "Fault-Mgmt-Supported " : "",
+ (l&0x02) ? "Link-Verification-Supported " : "");
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_TE_LINK_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_TE_LINK_FLAGS_FAULT_MGMT],
+ tvb, offset2, 1, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_TE_LINK_FLAGS_LINK_VERIFY],
+ tvb, offset2, 1, l);
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": IPv4: Local %s, Remote %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+4, 4)),
+ ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_LOCAL_IPV4],
+ tvb, offset2+4, 4, FALSE);
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_REMOTE_IPV4],
+ tvb, offset2+8, 4, FALSE);
+ break;
+ case 2:
+ proto_item_append_text(ti, ": IPv6: Local %s, Remote %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)),
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+8, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+4, 16, "TE-Link Local ID - IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+20,16, "TE-Link Remote ID - IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)));
+ break;
+ case 3:
+ proto_item_append_text(ti, ": Unnumbered: Local %d, Remote %d",
+ tvb_get_ntohl(tvb, offset2+4), tvb_get_ntohl(tvb, offset2+8));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_LOCAL_UNNUM],
+ tvb, offset2+4, 4, FALSE);
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_REMOTE_UNNUM],
+ tvb, offset2+8, 4, FALSE);
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_09_CLASS_DATA_LINK:
+ l = tvb_get_guint8(tvb, offset2);
+ ti2 = proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_FLAGS],
+ tvb, offset2, 1, l);
+ proto_item_append_text(ti2, ": %s%s",
+ (l&0x01) ? "Interface-Type-Port " : "Interface-Type-Component-Link ",
+ (l&0x02) ? "Allocated " : "Unallocated ");
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_DATA_LINK_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_PORT],
+ tvb, offset2, 1, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_ALLOCATED],
+ tvb, offset2, 1, l);
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": IPv4: Local %s, Remote %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+4, 4)),
+ ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_IPV4],
+ tvb, offset2+4, 4, FALSE);
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_IPV4],
+ tvb, offset2+8, 4, FALSE);
+ l = 12;
+ break;
+ case 2:
+ proto_item_append_text(ti, ": IPv6: Local %s, Remote %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)),
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+8, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+4, 16,
+ "Data-Link Local ID - IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+20,16,
+ "Data-Link Remote ID - IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)));
+ l = 36;
+ break;
+ case 3:
+ proto_item_append_text(ti, ": Unnumbered: Local %d, Remote %d",
+ tvb_get_ntohl(tvb, offset2+4), tvb_get_ntohl(tvb, offset2+8));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_UNNUM],
+ tvb, offset2+4, 4, FALSE);
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_UNNUM],
+ tvb, offset2+8, 4, FALSE);
+ l = 12;
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+
+ while (l < obj_length - 4) {
+ mylen = tvb_get_guint8(tvb, offset2+l+1);
+ ti2 = proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ],
+ tvb, offset2+l, mylen, FALSE);
+ lmp_subobj_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_DATA_LINK_SUBOBJ]);
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 1,
+ "Subobject Type: %d", tvb_get_guint8(tvb, offset2+l));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+1, 1,
+ "Subobject Length: %d", mylen);
+ switch(tvb_get_guint8(tvb, offset2+l)) {
+ case 1:
+ proto_item_set_text(ti2, "Interface Switching Capability: "
+ "Switching Cap: %s, Encoding Type: %s, Min BW: %.10g, Max BW: %.10g",
+ val_to_str(tvb_get_guint8(tvb, offset2+l+2),
+ gmpls_switching_type_str, "Unknown (%d)"),
+ val_to_str(tvb_get_guint8(tvb, offset2+l+3),
+ gmpls_lsp_enc_str, "Unknown (%d)"),
+ tvb_get_ntohieee_float(tvb, offset2+l+4),
+ tvb_get_ntohieee_float(tvb, offset2+l+8));
+ proto_tree_add_item(lmp_subobj_tree,
+ lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_SWITCHING_TYPE],
+ tvb, offset2+l+2, 1, FALSE);
+ proto_tree_add_item(lmp_subobj_tree,
+ lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_LSP_ENCODING],
+ tvb, offset2+l+3, 1, FALSE);
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+4, 4,
+ "Minimum Reservable Bandwidth: %.10g bytes/s",
+ tvb_get_ntohieee_float(tvb, offset2+l+4));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+8, 4,
+ "Maximum Reservable Bandwidth: %.10g bytes/s",
+ tvb_get_ntohieee_float(tvb, offset2+l+8));
+ break;
+
+ case 2:
+ proto_item_set_text(ti2, "Wavelength: %d",
+ tvb_get_ntohl(tvb, offset2+l+2));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+4, 4,
+ "Wavelength: %d",
+ tvb_get_ntohl(tvb, offset2+l+4));
+ break;
+
+ default:
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l,
+ tvb_get_guint8(tvb, offset2+l+1),
+ "Data (%d bytes)", tvb_get_guint8(tvb, offset2+l+1));
+ break;
+ }
+ l += tvb_get_guint8(tvb, offset2+l+1);
+ }
+
+ break;
+
+ case LMP_09_CLASS_CHANNEL_STATUS:
+ k = 0; j = 0;
+ switch(type) {
+ case 1:
+ case 3:
+ k = 8; break;
+ case 2:
+ k = 20; break;
+ }
+ if (!k)
+ break;
+ for (l=0; l<obj_length - 4; ) {
+ ti2 = proto_tree_add_text(lmp_object_tree, tvb, offset2+l, k,
+ "Interface-Id");
+ lmp_subobj_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_CHANNEL_STATUS_ID]);
+ switch(type) {
+ case 1:
+ if (j < 4)
+ proto_item_append_text(ti, ": [IPv4-%s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
+ proto_item_append_text(ti2, ": IPv4 %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 4,
+ "Interface ID: IPv4: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
+ l += 4;
+ break;
+ case 2:
+ if (j < 4)
+ proto_item_append_text(ti, ": [IPv6-%s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l, 16)));
+ proto_item_append_text(ti2, ": IPv6 %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l, 16)));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2, 16, "Interface ID: IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l, 16)));
+ l += 16;
+ break;
+ case 3:
+ if (j < 4)
+ proto_item_append_text(ti, ": [Unnum-%d", tvb_get_ntohl(tvb, offset2+l));
+ proto_item_append_text(ti, ": Unnumbered %d", tvb_get_ntohl(tvb, offset2+l));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 4,
+ "Interface ID: Unnumbered: %d",
+ tvb_get_ntohl(tvb, offset2+l));
+ l += 4;
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, obj_length-4-l,
+ "Data (%d bytes)", obj_length-4-l);
+ l = obj_length - 4;
+ break;
+ }
+ if (l == obj_length - 4) break;
+
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 1,
+ tvb_get_guint8(tvb, offset2+l) & 0x80 ?
+ "Link Allocated - Active Monitoring" :
+ "Link Not Allocated");
+ if (j < 4)
+ proto_item_append_text(ti, "-%s,%s], ",
+ tvb_get_guint8(tvb, offset2+l) & 0x80 ? "Act" : "NA",
+ val_to_str(tvb_get_ntohl(tvb, offset2+l) & 0x7fffffff,
+ channel_status_short_str, "UNK (%u)."));
+ proto_item_append_text(ti2, ": %s, ",
+ tvb_get_guint8(tvb, offset2+l) & 0x80 ? "Active" : "Not Active");
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 4,
+ "Channel Status: %s",
+ val_to_str(tvb_get_ntohl(tvb, offset2+l) & 0x7fffffff,
+ channel_status_str, "Unknown (%u). "));
+ proto_item_append_text(ti2, val_to_str(tvb_get_ntohl(tvb, offset2+l) & 0x7fffffff,
+ channel_status_str, "Unknown (%u). "));
+ j++;
+ l += 4;
+ if (j==4 && l < obj_length - 4)
+ proto_item_append_text(ti, " ...");
+ }
+ break;
+
+ case LMP_09_CLASS_CHANNEL_STATUS_REQUEST:
+ for (l=0; l<obj_length - 4; ) {
+ switch(type) {
+ case 1:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, 4,
+ "Interface ID: IPv4: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
+ l += 4;
+ break;
+ case 2:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, 16, "Interface ID: IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l,16)));
+ l += 16;
+ break;
+ case 3:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, 4,
+ "Interface ID: Unnumbered: %d",
+ tvb_get_ntohl(tvb, offset2+l));
+ l += 4;
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, obj_length-4-l,
+ "Data (%d bytes)", obj_length-4-l);
+ l = obj_length - 4;
+ break;
+ }
+ }
+ break;
+
+ case LMP_09_CLASS_ERROR:
+ l = tvb_get_ntohl(tvb, offset2);
+ ti2 = proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_ERROR],
+ tvb, offset2, 4, l);
+
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": BEGIN_VERIFY_ERROR: %s%s%s%s",
+ (l&0x01) ? "Unsupported-Link " : "",
+ (l&0x02) ? "Unwilling" : "",
+ (l&0x04) ? "Unsupported-Transport" : "",
+ (l&0x08) ? "TE-Link-ID" : "");
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_ERROR_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_UNSUPPORTED_LINK],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_UNWILLING],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_TRANSPORT],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_TE_LINK_ID],
+ tvb, offset, 4, l);
+ break;
+ case 2:
+ proto_item_append_text(ti, ": LINK_SUMMARY_ERROR: %s%s%s%s%s%s",
+ (l&0x01) ? "Unacceptable-Params " : "",
+ (l&0x02) ? "Renegotiate" : "",
+ (l&0x04) ? "Bad-TE-Link" : "",
+ (l&0x08) ? "Bad-Data-Link" : "",
+ (l&0x10) ? "Bad-TE-Link-CType" : "",
+ (l&0x20) ? "Bad-Data-Link-CType" : "");
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_ERROR_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_PARAMETERS],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_RENEGOTIATE],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_TE_LINK],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_DATA_LINK],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_UNKNOWN_TEL_CTYPE],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_UNKNOWN_DL_CTYPE],
+ tvb, offset, 4, l);
+ break;
+ default:
+ proto_item_append_text(ti, ": UNKNOWN_ERROR (%d): 0x%04x", type, l);
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ } else {
+ /* LMP 03 or LMP 02 */
+ switch (class) {
+ case LMP_CLASS_NULL:
+ break;
+
+ case LMP_CLASS_LOCAL_CCID:
+ case LMP_CLASS_REMOTE_CCID:
+ switch(type) {
+ case 1:
+ l = (class == LMP_CLASS_LOCAL_CCID) ?
+ LMPF_VAL_LOCAL_CCID : LMPF_VAL_REMOTE_CCID;
+ proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ tvb_get_ntohl(tvb, offset2));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_LOCAL_NODE_ID:
+ case LMP_CLASS_REMOTE_NODE_ID:
+ switch(type) {
+ case 1:
+ l = (class == LMP_CLASS_LOCAL_NODE_ID) ?
+ LMPF_VAL_LOCAL_NODE_ID : LMPF_VAL_REMOTE_NODE_ID;
+ proto_item_append_text(ti, ": %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_LOCAL_LINK_ID:
+ case LMP_CLASS_REMOTE_LINK_ID:
+ switch(type) {
+ case 1:
+ l = (class == LMP_CLASS_LOCAL_LINK_ID) ?
+ LMPF_VAL_LOCAL_LINK_ID_IPV4 : LMPF_VAL_REMOTE_LINK_ID_IPV4;
+ proto_item_append_text(ti, ": IPv4 %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ case 2:
+ proto_item_append_text(ti, ": IPv6 %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, 16, "IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ break;
+ case 3:
+ l = (class == LMP_CLASS_LOCAL_LINK_ID) ?
+ LMPF_VAL_LOCAL_LINK_ID_UNNUM : LMPF_VAL_REMOTE_LINK_ID_UNNUM;
+ proto_item_append_text(ti, ": Unnumbered %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_LOCAL_INTERFACE_ID:
+ case LMP_CLASS_REMOTE_INTERFACE_ID:
+ switch(type) {
+ case 1:
+ l = (class == LMP_CLASS_LOCAL_INTERFACE_ID) ?
+ LMPF_VAL_LOCAL_INTERFACE_ID_IPV4 : LMPF_VAL_REMOTE_INTERFACE_ID_IPV4;
+ proto_item_append_text(ti, ": IPv4 %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ case 2:
+ proto_item_append_text(ti, ": IPv6 %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, 16, "IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ break;
+ case 3:
+ l = (class == LMP_CLASS_LOCAL_INTERFACE_ID) ?
+ LMPF_VAL_LOCAL_INTERFACE_ID_UNNUM : LMPF_VAL_REMOTE_INTERFACE_ID_UNNUM;
+ proto_item_append_text(ti, ": Unnumbered %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ FALSE);
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_MESSAGE_ID:
+ case LMP_CLASS_MESSAGE_ID_ACK:
+ switch(type) {
+ case 1:
+ l = (class == LMP_CLASS_MESSAGE_ID) ?
+ LMPF_VAL_MESSAGE_ID : LMPF_VAL_MESSAGE_ID_ACK;
+ proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[l], tvb, offset2, 4,
+ tvb_get_ntohl(tvb, offset2));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_CONFIG:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": HelloInterval: %d, HelloDeadInterval: %d",
+ tvb_get_ntohs(tvb, offset2), tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_CONFIG_HELLO],
+ tvb, offset2, 2, tvb_get_ntohs(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_CONFIG_HELLO_DEAD],
+ tvb, offset2+2, 2, tvb_get_ntohs(tvb, offset2+2));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_HELLO:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": TxSeq %d, RxSeq: %d",
+ tvb_get_ntohl(tvb, offset2),
+ tvb_get_ntohl(tvb, offset2+4));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_HELLO_TXSEQ],
+ tvb, offset2, 4, tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_HELLO_RXSEQ],
+ tvb, offset2+4, 4, tvb_get_ntohl(tvb, offset2+4));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+ case LMP_CLASS_BEGIN_VERIFY:
+ switch(type) {
+ case 1:
+ l = tvb_get_ntohs(tvb, offset2);
+ ti2 = proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS],
+ tvb, offset2, 2, FALSE);
+
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_BEGIN_VERIFY_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_ALL_LINKS],
+ tvb, offset2, 2, l);
+ proto_tree_add_boolean(lmp_flags_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_FLAGS_LINK_TYPE],
+ tvb, offset2, 2, l);
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+2, 2,
+ "Verify Interval: %d ms", tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+4, 4,
+ "Number of Data Links: %d", tvb_get_ntohl(tvb, offset2+4));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_BEGIN_VERIFY_ENCTYPE],
+ tvb, offset2+8, 1, FALSE);
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+10, 2,
+ "Verify Transport Mechanism: 0x%0x", tvb_get_ntohs(tvb, offset2+10));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+12, 4,
+ "Transmission Rate: %.10g", tvb_get_ntohieee_float(tvb, offset2+12));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+16, 4,
+ "Wavelength: %d", tvb_get_ntohl(tvb, offset2+16));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_BEGIN_VERIFY_ACK:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": VerifyDeadInterval: %d, TransportResponse: 0x%0x",
+ tvb_get_ntohs(tvb, offset2), tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, 2,
+ "VerifyDeadInterval: %d ms", tvb_get_ntohs(tvb, offset2));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+2, 2,
+ "Verify Transport Response: 0x%0x", tvb_get_ntohs(tvb, offset2+2));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_VERIFY_ID:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": %d", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_VERIFY_ID], tvb, offset2, 4,
+ tvb_get_ntohl(tvb, offset2));
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_TE_LINK:
+ l = tvb_get_guint8(tvb, offset2);
+ ti2 = proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_FLAGS],
+ tvb, offset2, 1, l);
+ proto_item_append_text(ti2, ": %s%s",
+ (l&0x01) ? "Fault-Mgmt-Supported " : "",
+ (l&0x02) ? "Link-Verification-Supported " : "");
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_TE_LINK_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_TE_LINK_FLAGS_FAULT_MGMT],
+ tvb, offset2, 1, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_TE_LINK_FLAGS_LINK_VERIFY],
+ tvb, offset2, 1, l);
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": IPv4: Local %s, Remote %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+4, 4)),
+ ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_LOCAL_IPV4],
+ tvb, offset2+4, 4, FALSE);
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_REMOTE_IPV4],
+ tvb, offset2+8, 4, FALSE);
+ break;
+ case 2:
+ proto_item_append_text(ti, ": IPv6: Local %s, Remote %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)),
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+8, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+4, 16, "TE-Link Local ID - IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+20,16, "TE-Link Remote ID - IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)));
+ break;
+ case 3:
+ proto_item_append_text(ti, ": Unnumbered: Local %d, Remote %d",
+ tvb_get_ntohl(tvb, offset2+4), tvb_get_ntohl(tvb, offset2+8));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_LOCAL_UNNUM],
+ tvb, offset2+4, 4, FALSE);
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_TE_LINK_REMOTE_UNNUM],
+ tvb, offset2+8, 4, FALSE);
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+
+ case LMP_CLASS_DATA_LINK:
+ l = tvb_get_guint8(tvb, offset2);
+ ti2 = proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_FLAGS],
+ tvb, offset2, 1, l);
+ proto_item_append_text(ti2, ": %s%s",
+ (l&0x01) ? "Interface-Type-Port " : "Interface-Type-Component-Link ",
+ (l&0x02) ? "Allocated " : "Unallocated ");
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_DATA_LINK_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_PORT],
+ tvb, offset2, 1, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_DATA_LINK_FLAGS_ALLOCATED],
+ tvb, offset2, 1, l);
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": IPv4: Local %s, Remote %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+4, 4)),
+ ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_IPV4],
+ tvb, offset2+4, 4, FALSE);
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_IPV4],
+ tvb, offset2+8, 4, FALSE);
+ l = 12;
+ break;
+ case 2:
+ proto_item_append_text(ti, ": IPv6: Local %s, Remote %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)),
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+8, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+4, 16,
+ "Data-Link Local ID - IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+20,16,
+ "Data-Link Remote ID - IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+4, 16)));
+ l = 36;
+ break;
+ case 3:
+ proto_item_append_text(ti, ": Unnumbered: Local %d, Remote %d",
+ tvb_get_ntohl(tvb, offset2+4), tvb_get_ntohl(tvb, offset2+8));
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_LOCAL_UNNUM],
+ tvb, offset2+4, 4, FALSE);
+ proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_REMOTE_UNNUM],
+ tvb, offset2+8, 4, FALSE);
+ l = 12;
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+
+ while (l < obj_length - 4) {
+ mylen = tvb_get_guint8(tvb, offset2+l+1);
+ ti2 = proto_tree_add_item(lmp_object_tree, lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ],
+ tvb, offset2+l, mylen, FALSE);
+ lmp_subobj_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_DATA_LINK_SUBOBJ]);
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 1,
+ "Subobject Type: %d", tvb_get_guint8(tvb, offset2+l));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+1, 1,
+ "Subobject Length: %d", mylen);
+ switch(tvb_get_guint8(tvb, offset2+l)) {
+ case 1:
+ proto_item_set_text(ti2, "Interface Switching Capability: "
+ "Switching Cap: %s, Encoding Type: %s, Min BW: %.10g, Max BW: %.10g",
+ val_to_str(tvb_get_guint8(tvb, offset2+l+2),
+ gmpls_switching_type_str, "Unknown (%d)"),
+ val_to_str(tvb_get_guint8(tvb, offset2+l+3),
+ gmpls_lsp_enc_str, "Unknown (%d)"),
+ tvb_get_ntohieee_float(tvb, offset2+l+4),
+ tvb_get_ntohieee_float(tvb, offset2+l+8));
+ proto_tree_add_item(lmp_subobj_tree,
+ lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_SWITCHING_TYPE],
+ tvb, offset2+l+2, 1, FALSE);
+ proto_tree_add_item(lmp_subobj_tree,
+ lmp_filter[LMPF_VAL_DATA_LINK_SUBOBJ_LSP_ENCODING],
+ tvb, offset2+l+3, 1, FALSE);
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+4, 4,
+ "Minimum Reservable Bandwidth: %.10g bytes/s",
+ tvb_get_ntohieee_float(tvb, offset2+l+4));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+8, 4,
+ "Maximum Reservable Bandwidth: %.10g bytes/s",
+ tvb_get_ntohieee_float(tvb, offset2+l+8));
+ break;
+
+ case 2:
+ proto_item_set_text(ti2, "Wavelength: %d",
+ tvb_get_ntohl(tvb, offset2+l+4));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l+4, 4,
+ "Wavelength: %d",
+ tvb_get_ntohl(tvb, offset2+l+4));
+ break;
+
+ default:
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l,
+ tvb_get_guint8(tvb, offset2+l+1),
+ "Data (%d bytes)", tvb_get_guint8(tvb, offset2+l+1));
+ break;
+ }
+ l += tvb_get_guint8(tvb, offset2+l+1);
+ }
+ break;
+
+ case LMP_CLASS_CHANNEL_STATUS:
+ k = 0; j = 0;
+ switch(type) {
+ case 1:
+ case 3:
+ k = 8; break;
+ case 2:
+ k = 20; break;
+ }
+ if (!k)
+ break;
+ for (l=0; l<obj_length - 4; ) {
+ ti2 = proto_tree_add_text(lmp_object_tree, tvb, offset2+l, k,
+ "Interface-Id");
+ lmp_subobj_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_CHANNEL_STATUS_ID]);
+ switch(type) {
+ case 1:
+ if (j < 4)
+ proto_item_append_text(ti, ": [IPv4-%s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
+ proto_item_append_text(ti2, ": IPv4 %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 4,
+ "Interface ID: IPv4: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
+ l += 4;
+ break;
+ case 2:
+ if (j < 4)
+ proto_item_append_text(ti, ": [IPv6-%s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l, 16)));
+ proto_item_append_text(ti2, ": IPv6 %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l, 16)));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2, 16, "Interface ID: IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l, 16)));
+ l += 16;
+ break;
+ case 3:
+ if (j < 4)
+ proto_item_append_text(ti, ": [Unnum-%d", tvb_get_ntohl(tvb, offset2+l));
+ proto_item_append_text(ti, ": Unnumbered %d", tvb_get_ntohl(tvb, offset2+l));
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 4,
+ "Interface ID: Unnumbered: %d",
+ tvb_get_ntohl(tvb, offset2+l));
+ l += 4;
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, obj_length-4-l,
+ "Data (%d bytes)", obj_length-4-l);
+ l = obj_length - 4;
+ break;
+ }
+ if (l == obj_length - 4) break;
+
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 1,
+ tvb_get_guint8(tvb, offset2+l) & 0x80 ?
+ "Link Allocated - Active Monitoring" :
+ "Link Not Allocated");
+ if (j < 4)
+ proto_item_append_text(ti, "-%s,%s], ",
+ tvb_get_guint8(tvb, offset2+l) & 0x80 ? "Act" : "NA",
+ val_to_str(tvb_get_ntohl(tvb, offset2+l) & 0x7fffffff,
+ channel_status_short_str, "UNK (%u)."));
+ proto_item_append_text(ti2, ": %s, ",
+ tvb_get_guint8(tvb, offset2+l) & 0x80 ? "Active" : "Not Active");
+ proto_tree_add_text(lmp_subobj_tree, tvb, offset2+l, 4,
+ "Channel Status: %s",
+ val_to_str(tvb_get_ntohl(tvb, offset2+l) & 0x7fffffff,
+ channel_status_str, "Unknown (%u). "));
+ proto_item_append_text(ti2, val_to_str(tvb_get_ntohl(tvb, offset2+l) & 0x7fffffff,
+ channel_status_str, "Unknown (%u). "));
+ j++;
+ l += 4;
+ if (j==4 && l < obj_length - 4)
+ proto_item_append_text(ti, " ...");
+ }
+ break;
+
+ case LMP_CLASS_CHANNEL_STATUS_REQUEST:
+ for (l=0; l<obj_length - 4; ) {
+ switch(type) {
+ case 1:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, 4,
+ "Interface ID: IPv4: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+l, 4)));
+ l += 4;
+ break;
+ case 2:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, 16, "Interface ID: IPv6: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l,16)));
+ l += 16;
+ break;
+ case 3:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, 4,
+ "Interface ID: Unnumbered: %d",
+ tvb_get_ntohl(tvb, offset2+l));
+ l += 4;
+ break;
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2+l, obj_length-4-l,
+ "Data (%d bytes)", obj_length-4-l);
+ l = obj_length - 4;
+ break;
+ }
+ }
+ break;
+
+ case LMP_CLASS_ERROR:
+ l = tvb_get_ntohl(tvb, offset2);
+ ti2 = proto_tree_add_uint(lmp_object_tree, lmp_filter[LMPF_VAL_ERROR],
+ tvb, offset2, 4, l);
+
+ /* Errors are different in draft-02 and draft-03 */
+ switch(lmp_draft_ver) {
+ case LMP_VER_DRAFT_CCAMP_02:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": CONFIG_ERROR: %s%s%s",
+ (l&0x01) ? "Unacceptable-Params " : "",
+ (l&0x02) ? "Renegotiate" : "",
+ (l&0x04) ? "Bad Received CCID" : "");
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_ERROR_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_CONFIG_BAD_PARAMETERS],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_CONFIG_RENEGOTIATE],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_CONFIG_BAD_CCID],
+ tvb, offset, 4, l);
+ break;
+ case 2:
+ proto_item_append_text(ti, ": BEGIN_VERIFY_ERROR: %s%s%s%s",
+ (l&0x01) ? "Unsupported-Link " : "",
+ (l&0x02) ? "Unwilling" : "",
+ (l&0x04) ? "Unsupported-Transport" : "",
+ (l&0x08) ? "TE-Link-ID" : "");
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_ERROR_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_UNSUPPORTED_LINK],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_UNWILLING],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_TRANSPORT],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_TE_LINK_ID],
+ tvb, offset, 4, l);
+ break;
+ case 3:
+ proto_item_append_text(ti, ": LINK_SUMMARY_ERROR: %s%s%s",
+ (l&0x01) ? "Unacceptable-Params " : "",
+ (l&0x02) ? "Renegotiate" : "",
+ (l&0x04) ? "Remote-Link-ID" : "");
+
+
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_subtree[LMP_TREE_ERROR_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_PARAMETERS],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_RENEGOTIATE],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_REMOTE_LINK_ID],
+ tvb, offset, 4, l);
+ break;
+
+ default:
+ proto_item_append_text(ti, ": UNKNOWN_ERROR (%d): 0x%04x", type, l);
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+ break;
+ default:
+ case LMP_VER_DRAFT_CCAMP_03:
+ switch(type) {
+ case 1:
+ proto_item_append_text(ti, ": BEGIN_VERIFY_ERROR: %s%s%s%s",
+ (l&0x01) ? "Unsupported-Link " : "",
+ (l&0x02) ? "Unwilling" : "",
+ (l&0x04) ? "Unsupported-Transport" : "",
+ (l&0x08) ? "TE-Link-ID" : "");
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_ERROR_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_UNSUPPORTED_LINK],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_UNWILLING],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_TRANSPORT],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_VERIFY_TE_LINK_ID],
+ tvb, offset, 4, l);
+ break;
+ case 2:
+ proto_item_append_text(ti, ": LINK_SUMMARY_ERROR: %s%s%s%s%s",
+ (l&0x01) ? "Unacceptable-Params " : "",
+ (l&0x02) ? "Renegotiate" : "",
+ (l&0x04) ? "Remote-Link-ID" : "",
+ (l&0x08) ? "TE-Link" : "",
+ (l&0x10) ? "Data-Link" : "");
+
+ lmp_flags_tree = proto_item_add_subtree(ti2, lmp_09_subtree[LMP_TREE_ERROR_FLAGS]);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_PARAMETERS],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_RENEGOTIATE],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_REMOTE_LINK_ID],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_TE_LINK],
+ tvb, offset, 4, l);
+ proto_tree_add_boolean(lmp_flags_tree,
+ lmp_filter[LMPF_VAL_ERROR_SUMMARY_BAD_DATA_LINK],
+ tvb, offset, 4, l);
+ break;
+ default:
+ proto_item_append_text(ti, ": UNKNOWN_ERROR (%d): 0x%04x", type, l);
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ } /* switch type */
+ break;
+ } /* default case in ERROR object switch */
+
+ default:
+ proto_tree_add_text(lmp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+
+ } /* LMP_VER_DRAFT_CCAMP_03 */
+
+ offset += obj_length;
+ len += obj_length;
+
+ } /* while */
+ } /* tree */
+}
+
+static void
+lmp_prefs_applied (void)
+{
+ if (lmp_udp_port != lmp_udp_port_config) {
+ dissector_delete("udp.port", lmp_udp_port, lmp_handle);
+ lmp_udp_port = lmp_udp_port_config;
+ dissector_add("udp.port", lmp_udp_port, lmp_handle);
+ }
+}
+
+static void
+register_lmp_prefs (void)
+{
+ module_t *lmp_module;
+ static enum_val_t lmp_ver[] = {
+ {"draft-ietf-ccamp-lmp-09", "draft-ietf-ccamp-lmp-09", LMP_VER_DRAFT_CCAMP_09},
+ {"draft-ietf-ccamp-lmp-03", "draft-ietf-ccamp-lmp-03", LMP_VER_DRAFT_CCAMP_03},
+ {"draft-ietf-ccamp-lmp-02", "draft-ietf-ccamp-lmp-02", LMP_VER_DRAFT_CCAMP_02},
+ {NULL, NULL, -1}
+ };
+
+ lmp_module = prefs_register_protocol(proto_lmp, lmp_prefs_applied);
+ prefs_register_enum_preference(
+ lmp_module, "version",
+ "Draft version of LMP",
+ "Specifies the IETF CCAMP draft version of LMP to interpret",
+ &lmp_draft_ver, lmp_ver, FALSE);
+ prefs_register_uint_preference(
+ lmp_module, "udp_port", "LMP UDP Port (draft-09 ONLY)",
+ "UDP port number to use for LMP (draft-09 only)", 10, &lmp_udp_port_config);
+}
+
+void
+proto_register_lmp(void)
+{
+ static gint *ett[NUM_LMP_SUBTREES];
+ int i;
+
+ for (i=0; i<NUM_LMP_SUBTREES; i++) {
+ lmp_subtree[i] = -1;
+ ett[i] = &lmp_subtree[i];
+ }
+
+ proto_lmp = proto_register_protocol("Link Management Protocol (LMP)",
+ "LMP", "lmp");
+ proto_register_field_array(proto_lmp, lmpf_info, array_length(lmpf_info));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_lmp_prefs();
+}
+
+void
+proto_reg_handoff_lmp(void)
+{
+ lmp_handle = create_dissector_handle(dissect_lmp, proto_lmp);
+ dissector_add("udp.port", lmp_udp_port, lmp_handle);
+ dissector_add("ip.proto", IP_PROTO_LMP, lmp_handle);
+}
diff --git a/epan/dissectors/packet-lpd.c b/epan/dissectors/packet-lpd.c
new file mode 100644
index 0000000000..d79ea39638
--- /dev/null
+++ b/epan/dissectors/packet-lpd.c
@@ -0,0 +1,196 @@
+/* packet-lpd.c
+ * Routines for LPR and LPRng packet disassembly
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#define TCP_PORT_PRINTER 515
+
+static int proto_lpd = -1;
+static int hf_lpd_response = -1;
+static int hf_lpd_request = -1;
+
+static gint ett_lpd = -1;
+
+enum lpr_type { request, response, unknown };
+
+static gint find_printer_string(tvbuff_t *tvb, int offset);
+
+static dissector_handle_t data_handle;
+
+static void
+dissect_lpd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *lpd_tree;
+ proto_item *ti;
+ enum lpr_type lpr_packet_type;
+ guint8 code;
+ gint printer_len;
+
+ /* This information comes from the LPRng HOWTO, which also describes
+ RFC 1179. http://www.astart.com/lprng/LPRng-HOWTO.html */
+ static char *lpd_client_code[] = {
+ "Unknown command",
+ "LPC: start print / jobcmd: abort",
+ "LPR: transfer a printer job / jobcmd: receive control file",
+ "LPQ: print short form of queue status / jobcmd: receive data file",
+ "LPQ: print long form of queue status",
+ "LPRM: remove jobs",
+ "LPRng lpc: do control operation",
+ "LPRng lpr: transfer a block format print job",
+ "LPRng lpc: secure command transfer",
+ "LPRng lpq: verbose status information"
+ };
+ static char *lpd_server_code[] = {
+ "Success: accepted, proceed",
+ "Queue not accepting jobs",
+ "Queue temporarily full, retry later",
+ "Bad job format, do not retry"
+ };
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LPD");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* rfc1179 states that all responses are 1 byte long */
+ code = tvb_get_guint8(tvb, 0);
+ if (tvb_reported_length(tvb) == 1) {
+ lpr_packet_type = response;
+ }
+ else if (code <= 9) {
+ lpr_packet_type = request;
+ }
+ else {
+ lpr_packet_type = unknown;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (lpr_packet_type == request) {
+ col_set_str(pinfo->cinfo, COL_INFO, lpd_client_code[code]);
+ }
+ else if (lpr_packet_type == response) {
+ col_set_str(pinfo->cinfo, COL_INFO, "LPD response");
+ }
+ else {
+ col_set_str(pinfo->cinfo, COL_INFO, "LPD continuation");
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_lpd, tvb, 0, -1, FALSE);
+ lpd_tree = proto_item_add_subtree(ti, ett_lpd);
+
+ if (lpr_packet_type == response) {
+ proto_tree_add_boolean_hidden(lpd_tree, hf_lpd_response,
+ tvb, 0, 0, TRUE);
+ } else {
+ proto_tree_add_boolean_hidden(lpd_tree, hf_lpd_request,
+ tvb, 0, 0, TRUE);
+ }
+
+ if (lpr_packet_type == request) {
+ printer_len = find_printer_string(tvb, 1);
+
+ if (code <= 9 && printer_len != -1) {
+ proto_tree_add_text(lpd_tree, tvb, 0, 1,
+ lpd_client_code[code]);
+ proto_tree_add_text(lpd_tree, tvb, 1, printer_len,
+ "Printer/options: %s",
+ tvb_format_text(tvb, 1, printer_len));
+ }
+ else {
+ call_dissector(data_handle,tvb, pinfo, tree);
+ }
+ }
+ else if (lpr_packet_type == response) {
+ if (code <= 3) {
+ proto_tree_add_text(lpd_tree, tvb, 0, 1,
+ "Response: %s", lpd_server_code[code]);
+ }
+ else {
+ call_dissector(data_handle,tvb, pinfo, tree);
+ }
+ }
+ else {
+ call_dissector(data_handle,tvb, pinfo, tree);
+ }
+ }
+}
+
+
+static gint
+find_printer_string(tvbuff_t *tvb, int offset)
+{
+ int i;
+
+ /* try to find end of string, either '\n' or '\0' */
+ i = tvb_find_guint8(tvb, offset, -1, '\0');
+ if (i == -1)
+ i = tvb_find_guint8(tvb, offset, -1, '\n');
+ if (i == -1)
+ return -1;
+ return i - offset; /* length of string */
+}
+
+
+void
+proto_register_lpd(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_lpd_response,
+ { "Response", "lpd.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if LPD response", HFILL }},
+
+ { &hf_lpd_request,
+ { "Request", "lpd.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if LPD request", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_lpd,
+ };
+
+ proto_lpd = proto_register_protocol("Line Printer Daemon Protocol", "LPD", "lpd");
+ proto_register_field_array(proto_lpd, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_lpd(void)
+{
+ dissector_handle_t lpd_handle;
+
+ lpd_handle = create_dissector_handle(dissect_lpd, proto_lpd);
+ dissector_add("tcp.port", TCP_PORT_PRINTER, lpd_handle);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-lwapp.c b/epan/dissectors/packet-lwapp.c
new file mode 100644
index 0000000000..ee23838bce
--- /dev/null
+++ b/epan/dissectors/packet-lwapp.c
@@ -0,0 +1,589 @@
+/* packet-lwapp.c
+ *
+ * Routines for LWAPP encapsulated packet disassembly
+ * draft-calhoun-seamoby-lwapp-N (the current draft is 3)
+ *
+ * $Id$
+ *
+ * Copyright (c) 2003 by David Frascone <dave@frascone.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <glib.h>
+#include <epan/filesystem.h>
+#include "xmlstub.h"
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "prefs.h"
+
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#define LWAPP_FLAGS_T 0x04
+#define LWAPP_FLAGS_F 0x02
+#define LWAPP_FLAGS_FT 0x01
+
+static gint proto_lwapp = -1;
+static gint proto_lwapp_l3 = -1;
+static gint proto_lwapp_control = -1;
+static gint ett_lwapp = -1;
+static gint ett_lwapp_l3 = -1;
+static gint ett_lwapp_flags = -1;
+static gint ett_lwapp_control = -1;
+
+static gint hf_lwapp_version = -1;
+static gint hf_lwapp_slotid = -1;
+static gint hf_lwapp_flags_type = -1;
+static gint hf_lwapp_flags_fragment = -1;
+static gint hf_lwapp_flags_fragment_type = -1;
+static gint hf_lwapp_fragment_id = -1;
+static gint hf_lwapp_length = -1;
+static gint hf_lwapp_rssi = -1;
+static gint hf_lwapp_snr = -1;
+static gint hf_lwapp_control = -1;
+static gint hf_lwapp_control_mac = -1;
+static gint hf_lwapp_control_type = -1;
+static gint hf_lwapp_control_seq_no = -1;
+static gint hf_lwapp_control_length = -1;
+
+static dissector_handle_t eth_handle;
+static dissector_handle_t wlan_handle;
+static dissector_handle_t wlan_bsfc_handle;
+static dissector_handle_t data_handle;
+
+/* Set by preferences */
+static gboolean swap_frame_control;
+
+typedef struct {
+ guint8 flags;
+ guint8 fragmentId;
+ guint16 length;
+ guint8 rssi;
+ guint8 snr;
+} LWAPP_Header;
+
+typedef struct {
+ guint8 tag;
+ guint16 length;
+} CNTL_Data_Header;
+
+typedef struct {
+ guint8 type;
+ guint8 seqNo;
+ guint16 length;
+} CNTL_Header;
+
+typedef enum {
+ RESULT_CODE = 1,
+ MWAR_ADDR_PAYLOAD,
+ RAD_PAYLOAD,
+ RAD_SLOT_PAYLOAD,
+ RAD_NAME_PAYLOAD,
+ MWAR_PAYLOAD,
+ VAP_PAYLOAD,
+ STATION_CFG_PAYLOAD,
+ OPERATION_RATE_SET_PAYLOAD,
+ MULTI_DOMAIN_CAPABILITY_PAYLOAD,
+ MAC_OPERATION_PAYLOAD,
+ PHY_TX_POWER_PAYLOAD,
+ PHY_TX_POWER_LEVEL_PAYLOAD,
+ PHY_DSSS_PAYLOAD,
+ PHY_OFDM_PAYLOAD,
+ SUPPORTED_RATES_PAYLOAD,
+ AUTH_PAYLOAD,
+ TEST_PAYLOAD,
+ RRM_NEIGHBOR_CTRL_PAYLOAD,
+ RRM_NOISE_CTRL_PAYLOAD,
+ RRM_NOISE_DATA_PAYLOAD,
+ RRM_INTERFERENCE_CTRL_PAYLOAD,
+ RRM_INTERFERENCE_DATA_PAYLOAD,
+ RRM_LOAD_CTRL_PAYLOAD,
+ RRM_LOAD_DATA_PAYLOAD,
+ CHANGE_STATE_EVENT_PAYLOAD,
+ ADMIN_STATE_PAYLOAD,
+ DELETE_VAP_PAYLOAD,
+ ADD_MOBILE_PAYLOAD,
+ DELETE_MOBILE_PAYLOAD
+} control_tags;
+
+typedef enum
+ {
+ DISCOVERY_REQUEST = 1,
+ DISCOVERY_REPLY,
+ JOIN_REQUEST,
+ JOIN_REPLY,
+ HANDOFF_REQUEST,
+ HANDOFF_REPLY,
+ HANDOFF_COMMAND,
+ HANDOFF_RESPONSE,
+ HANDOFF_CONFIRM,
+ CONFIGURE_REQUEST,
+ CONFIGURE_RESPONSE,
+ CONFIGURE_COMMAND,
+ CONFIGURE_COMMAND_RES,
+ STATISTICS_INFO,
+ CHANGE_STATE_EVENT,
+ CHANGE_STATE_EVENT_RES,
+ RRM_CONTROL_REQ,
+ RRM_CONTROL_RES,
+ RRM_DATA_REQ,
+ RRM_DATA_RES,
+ ECHO_REQUEST,
+ ECHO_RESPONSE,
+ I_AM_UP_REQ,
+ I_AM_UP_RES
+ }CNTLMsgType;
+
+const value_string control_msg_vals[] = {
+ {DISCOVERY_REQUEST, "DISCOVERY_REQUEST"},
+ {DISCOVERY_REPLY, "DISCOVERY_REPLY"},
+ {JOIN_REQUEST, "JOIN_REQUEST"},
+ {JOIN_REPLY, "JOIN_REPLY"},
+ {HANDOFF_REQUEST, "HANDOFF_REQUEST"},
+ {HANDOFF_REPLY, "HANDOFF_REPLY"},
+ {HANDOFF_COMMAND, "HANDOFF_COMMAND"},
+ {HANDOFF_RESPONSE, "HANDOFF_RESPONSE"},
+ {HANDOFF_CONFIRM, "HANDOFF_CONFIRM"},
+ {CONFIGURE_REQUEST, "CONFIGURE_REQUEST"},
+ {CONFIGURE_RESPONSE, "CONFIGURE_RESPONSE"},
+ {CONFIGURE_COMMAND, "CONFIGURE_COMMAND"},
+ {CONFIGURE_COMMAND_RES, "CONFIGURE_COMMAND_RES"},
+ {STATISTICS_INFO, "STATISTICS_INFO"},
+ {CHANGE_STATE_EVENT, "CHANGE_STATE_EVENT"},
+ {CHANGE_STATE_EVENT_RES, "CHANGE_STATE_EVENT_RES"},
+ {RRM_CONTROL_REQ, "RRM_CONTROL_REQ"},
+ {RRM_CONTROL_RES, "RRM_CONTROL_RES"},
+ {RRM_DATA_REQ, "RRM_DATA_REQ"},
+ {RRM_DATA_RES, "RRM_DATA_RES"},
+ {ECHO_REQUEST, "ECHO_REQUEST"},
+ {ECHO_RESPONSE, "ECHO_RESPONSE"},
+ {I_AM_UP_REQ, "I_AM_UP_REQ"},
+ {I_AM_UP_RES, "I_AM_UP_RES"},
+
+ { 0, NULL}
+};
+const value_string control_tag_vals[] = {
+
+ {RESULT_CODE, "RESULT_CODE"},
+ {MWAR_ADDR_PAYLOAD, "MWAR_ADDR_PAYLOAD"},
+ {RAD_PAYLOAD, "RAD_PAYLOAD"},
+ {RAD_SLOT_PAYLOAD, "RAD_SLOT_PAYLOAD"},
+ {RAD_NAME_PAYLOAD, "RAD_NAME_PAYLOAD"},
+ {MWAR_PAYLOAD, "MWAR_PAYLOAD"},
+ {VAP_PAYLOAD, "VAP_PAYLOAD"},
+ {STATION_CFG_PAYLOAD, "STATION_CFG_PAYLOAD"},
+ {OPERATION_RATE_SET_PAYLOAD, "OPERATION_RATE_SET_PAYLOAD"},
+ {MULTI_DOMAIN_CAPABILITY_PAYLOAD, "MULTI_DOMAIN_CAPABILITY_PAYLOAD"},
+ {MAC_OPERATION_PAYLOAD, "MAC_OPERATION_PAYLOAD"},
+ {PHY_TX_POWER_PAYLOAD, "PHY_TX_POWER_PAYLOAD"},
+ {PHY_TX_POWER_LEVEL_PAYLOAD, "PHY_TX_POWER_LEVEL_PAYLOAD"},
+ {PHY_DSSS_PAYLOAD, "PHY_DSSS_PAYLOAD"},
+ {PHY_OFDM_PAYLOAD, "PHY_OFDM_PAYLOAD"},
+ {SUPPORTED_RATES_PAYLOAD, "SUPPORTED_RATES_PAYLOAD"},
+ {AUTH_PAYLOAD, "AUTH_PAYLOAD"},
+ {TEST_PAYLOAD, "TEST_PAYLOAD"},
+ {RRM_NEIGHBOR_CTRL_PAYLOAD, "RRM_NEIGHBOR_CTRL_PAYLOAD"},
+ {RRM_NOISE_CTRL_PAYLOAD, "RRM_NOISE_CTRL_PAYLOAD"},
+ {RRM_NOISE_DATA_PAYLOAD, "RRM_NOISE_DATA_PAYLOAD"},
+ {RRM_INTERFERENCE_CTRL_PAYLOAD, "RRM_INTERFERENCE_CTRL_PAYLOAD"},
+ {RRM_INTERFERENCE_DATA_PAYLOAD, "RRM_INTERFERENCE_DATA_PAYLOAD"},
+ {RRM_LOAD_CTRL_PAYLOAD, "RRM_LOAD_CTRL_PAYLOAD"},
+ {RRM_LOAD_DATA_PAYLOAD, "RRM_LOAD_DATA_PAYLOAD"},
+ {CHANGE_STATE_EVENT_PAYLOAD, "CHANGE_STATE_EVENT_PAYLOAD"},
+ {ADMIN_STATE_PAYLOAD, "ADMIN_STATE_PAYLOAD"},
+ {DELETE_VAP_PAYLOAD, "DELETE_VAP_PAYLOAD"},
+ {ADD_MOBILE_PAYLOAD, "ADD_MOBILE_PAYLOAD"},
+ {DELETE_MOBILE_PAYLOAD, "DELETE_MOBILE_PAYLOAD"},
+ {0, NULL}
+};
+
+static const true_false_string lwapp_flags_type = {
+ "LWAPP Control Packet" ,
+ "Encapsulated 80211"
+};
+
+static const true_false_string lwapp_set_truth = {
+ "Not Set",
+ "Set"
+};
+
+/*
+ * dissect lwapp control packets. This is not fully implemented,
+ * but it's a good start.
+ */
+static void dissect_control(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ CNTL_Header header;
+ proto_tree *control_tree;
+ tvbuff_t *next_tvb;
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ size_t offset=0;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LWAPP");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_str(pinfo->cinfo, COL_INFO,
+ "CNTL ");
+ }
+
+ /* Copy our header */
+ tvb_memcpy(tvb, (guint8*) &header, offset, sizeof(header));
+
+ /*
+ * Fix the length (network byte ordering), and set our version &
+ * slot id
+ */
+ header.length = g_ntohs(header.length);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO,
+ val_to_str(header.type, control_msg_vals, "Bad Type: 0x%02x"));
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_lwapp_control, tvb, offset,
+ -1, FALSE);
+ control_tree = proto_item_add_subtree(ti, ett_lwapp_control);
+
+ proto_tree_add_uint(control_tree, hf_lwapp_control_type,
+ tvb, offset, 1, header.type);
+ offset++;
+
+ proto_tree_add_uint(control_tree, hf_lwapp_control_seq_no,
+ tvb, offset, 1, header.seqNo);
+ offset++;
+
+ proto_tree_add_uint(control_tree, hf_lwapp_control_length,
+ tvb, offset, 2, header.length);
+ offset += 2;
+
+ /* Dissect rest of packet as data */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+
+} /* dissect_control */
+
+/*
+ * This lwapp dissector assumes that there is an 802.3 header at
+ * the start of the packet, so it simply re-calls the ethernet
+ * dissector on the packet.
+ */
+static void dissect_lwapp_l3(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *lwapp_tree;
+ size_t offset=0;
+ tvbuff_t *next_client;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LWAPP-L3");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_str(pinfo->cinfo, COL_INFO, "802.3 Packets over Layer 3");
+ }
+
+ if (tree) {
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_lwapp_l3, tvb, offset,
+ -1, FALSE);
+ lwapp_tree = proto_item_add_subtree(ti, ett_lwapp_l3);
+ }
+
+ /* Dissect as Ethernet */
+ next_client = tvb_new_subset(tvb, 0, -1, -1);
+ call_dissector(eth_handle, next_client, pinfo, tree);
+ return;
+
+} /* dissect_lwapp_l3*/
+
+
+/*
+ * This dissector dissects the lwapp protocol itself. It assumes an
+ * lwapp payload in the data, and doesn't care whether the data was
+ * from a UDP packet, or a Layer 2 one.
+ */
+static void dissect_lwapp(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ LWAPP_Header header;
+ guint8 slotId;
+ guint8 version;
+ proto_tree *lwapp_tree;
+ proto_tree *flags_tree;
+ tvbuff_t *next_client;
+ char dest_mac[6];
+ guint8 have_destmac=0;
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ size_t offset=0;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LWAPP");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_str(pinfo->cinfo, COL_INFO,
+ "LWAPP IP or Layer 2");
+ }
+
+ /* First, set up our dest mac, if we're a control packet with a
+ * dest of port 12223 */
+ if (pinfo->destport == 12223 ) {
+ tvb_memcpy(tvb, (guint8*)dest_mac, offset, 6);
+ have_destmac = 1;
+
+ /* Copy our header */
+ tvb_memcpy(tvb, (guint8*) &header, offset + 6, sizeof(header));
+ } else {
+
+ /* Copy our header */
+ tvb_memcpy(tvb, (guint8*) &header, offset, sizeof(header));
+ }
+
+
+ /*
+ * Fix the length (network byte ordering), and set our version &
+ * slot id
+ */
+ header.length = g_ntohs(header.length);
+ version = (header.flags & 0xc0) >> 6;
+ slotId = (header.flags & 0x38) >> 3;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if ((header.flags & LWAPP_FLAGS_T) != 0)
+ col_append_str(pinfo->cinfo, COL_INFO,
+ " Control Packet");
+ else
+ col_append_str(pinfo->cinfo, COL_INFO,
+ " 802.11 Packet");
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_lwapp, tvb, offset,
+ tvb_length(tvb), FALSE);
+ lwapp_tree = proto_item_add_subtree(ti, ett_lwapp);
+
+ if (have_destmac) {
+ proto_tree_add_ether(lwapp_tree, hf_lwapp_control_mac, tvb, offset,
+ 6, dest_mac);
+ offset += 6;
+ }
+
+ proto_tree_add_uint(lwapp_tree, hf_lwapp_version,
+ tvb, offset, 1, version);
+ proto_tree_add_uint(lwapp_tree, hf_lwapp_slotid,
+ tvb, offset, 1, slotId);
+
+ flags_tree = proto_item_add_subtree(lwapp_tree, ett_lwapp_flags);
+ proto_tree_add_boolean(flags_tree, hf_lwapp_flags_type,
+ tvb, offset, 1, header.flags);
+ proto_tree_add_boolean(flags_tree, hf_lwapp_flags_fragment,
+ tvb, offset, 1, header.flags);
+ proto_tree_add_boolean(flags_tree, hf_lwapp_flags_fragment_type,
+ tvb, offset, 1, header.flags);
+ offset++;
+
+ proto_tree_add_uint(lwapp_tree, hf_lwapp_fragment_id,
+ tvb, offset, 1, header.fragmentId);
+ offset++;
+
+ proto_tree_add_uint(lwapp_tree, hf_lwapp_length,
+ tvb, offset, 2, header.length);
+ offset += 2;
+
+ proto_tree_add_uint(lwapp_tree, hf_lwapp_rssi,
+ tvb, offset, 1, header.rssi);
+ offset++;
+ proto_tree_add_uint(lwapp_tree, hf_lwapp_snr,
+ tvb, offset, 1, header.snr);
+ offset++;
+
+
+ } /* tree */
+
+ next_client = tvb_new_subset(tvb, (have_destmac?6:0) + sizeof(LWAPP_Header), -1, -1);
+ if ((header.flags & LWAPP_FLAGS_T) == 0) {
+ call_dissector(swap_frame_control ? wlan_bsfc_handle : wlan_handle,
+ next_client, pinfo, tree);
+ } else {
+ dissect_control(next_client, pinfo, tree);
+ }
+ return;
+
+} /* dissect_lwapp*/
+
+/* registration with the filtering engine */
+void
+proto_register_lwapp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_lwapp_version,
+ { "Version", "lwapp.version", FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }},
+ { &hf_lwapp_slotid,
+ { "slotId","lwapp.slotId", FT_UINT24, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_lwapp_flags_type,
+ { "Type", "lwapp.flags.type", FT_BOOLEAN, 8,
+ TFS(&lwapp_flags_type), LWAPP_FLAGS_T, "", HFILL }},
+ { &hf_lwapp_flags_fragment,
+ { "Fragment", "lwapp.flags.fragment", FT_BOOLEAN, 8,
+ TFS(&lwapp_set_truth), LWAPP_FLAGS_F,
+ "", HFILL }},
+ { &hf_lwapp_flags_fragment_type,
+ { "Fragment Type", "lwapp.flags.fragmentType", FT_BOOLEAN, 8,
+ TFS(&lwapp_set_truth), LWAPP_FLAGS_FT,
+ "", HFILL }},
+ { &hf_lwapp_fragment_id,
+ { "Fragment Id","lwapp.fragmentId", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_lwapp_length,
+ { "Length","lwapp.Length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_lwapp_rssi,
+ { "RSSI","lwapp.rssi", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_lwapp_snr,
+ { "SNR","lwapp.snr", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_lwapp_control,
+ { "Control Data (not dissected yet)","lwapp.control", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_lwapp_control_mac,
+ { "AP Identity", "lwapp.apid", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Access Point Identity", HFILL }},
+ { &hf_lwapp_control_type,
+ { "Control Type", "lwapp.control.type", FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }},
+ { &hf_lwapp_control_seq_no,
+ { "Control Sequence Number", "lwapp.control.seqno", FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }},
+ { &hf_lwapp_control_length,
+ { "Control Length","lwapp.control.length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_lwapp_l3,
+ &ett_lwapp,
+ &ett_lwapp_control,
+ &ett_lwapp_flags
+ };
+ module_t *lwapp_module;
+
+ proto_lwapp = proto_register_protocol ("LWAPP Encapsulated Packet",
+ "LWAPP", "lwapp");
+
+ proto_lwapp_l3 = proto_register_protocol ("LWAPP Layer 3 Packet",
+ "LWAPP-L3", "lwapp-l3");
+
+ proto_lwapp_control = proto_register_protocol ("LWAP Control Message",
+ "LWAPP-CNTL", "lwapp-cntl");
+ proto_register_field_array(proto_lwapp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ lwapp_module = prefs_register_protocol(proto_lwapp, NULL);
+
+ prefs_register_bool_preference(lwapp_module,"swap_fc","Swap Frame Control",
+ "Swap frame control bytes (needed for some APs",
+ &swap_frame_control);
+
+} /* proto_register_diameter */
+
+void
+proto_reg_handoff_lwapp(void)
+{
+ dissector_handle_t lwapp_l3_handle;
+ dissector_handle_t lwapp_handle;
+
+ /*
+ * Get handles for the Ethernet and wireless dissectors.
+ */
+ eth_handle = find_dissector("eth");
+ wlan_handle = find_dissector("wlan");
+ wlan_bsfc_handle = find_dissector("wlan_bsfc");
+ data_handle = find_dissector("data");
+
+ /* This dissector assumes lwapp packets in an 802.3 frame */
+ lwapp_l3_handle = create_dissector_handle(dissect_lwapp_l3, proto_lwapp_l3);
+
+ /* This dissector assumes a lwapp packet */
+ lwapp_handle = create_dissector_handle(dissect_lwapp, proto_lwapp);
+
+ /*
+ * Ok, the following deserves some comments. We have four
+ * different ways lwapp can appear on the wire. Mostly, this is
+ * because lwapp is such a new protocol.
+ *
+ * First, lwapp can join on multiple udp ports, as encapsulated
+ * packets on top of UDP. In this case, there is a full raw
+ * ethernet frame inside of the UDP packet. This method is
+ * becoming obscelete, but we still wanted to dissect the
+ * packets.
+ *
+ * Next, lwapp can be over UDP, but packged for L3 tunneling. This
+ * is the new-style. In this case, LWAP headers are just transmitted
+ * via UDP.
+ *
+ * The last method is lwapp directly over layer 2. For this, we
+ * dissect two different ethertypes (until IANA gives us one)
+ *
+ */
+
+ /* Obsceleted LWAP via encapsulated 802.3 over UDP */
+
+ dissector_add("udp.port", 12220, lwapp_l3_handle);
+
+ /* new-style lwapp directly over UDP: L3-lwapp*/
+ dissector_add("udp.port", 12222, lwapp_handle);
+ dissector_add("udp.port", 12223, lwapp_handle);
+
+ /* Lwapp over L2 */
+ dissector_add("ethertype", 0x88bb, lwapp_handle);
+ dissector_add("ethertype", 0xbbbb, lwapp_handle);
+
+}
diff --git a/epan/dissectors/packet-m2pa.c b/epan/dissectors/packet-m2pa.c
new file mode 100644
index 0000000000..db548e3e86
--- /dev/null
+++ b/epan/dissectors/packet-m2pa.c
@@ -0,0 +1,465 @@
+/* packet-m2pa.c
+ * Routines for MTP2 Peer Adaptation Layer dissection
+ * It is hopefully (needs testing) compliant to
+ * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-m2pa-02.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-m2pa-11.txt
+ *
+ * Copyright 2001, 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>,
+ * updated by Michael Tuexen <tuexen [AT] fh-muenster.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-m3ua.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include "sctpppids.h"
+
+#define NETWORK_BYTE_ORDER FALSE
+#define SCTP_PORT_M2PA 3565
+
+static int global_sctp_port = SCTP_PORT_M2PA;
+static int sctp_port = 0;
+
+void proto_reg_handoff_m2pa(void);
+
+static int proto_m2pa = -1;
+static module_t *m2pa_module;
+
+static int hf_version = -1;
+static int hf_spare = -1;
+static int hf_v2_type = -1;
+static int hf_v8_type = -1;
+static int hf_class = -1;
+static int hf_length = -1;
+static int hf_unused = -1;
+static int hf_bsn = -1;
+static int hf_fsn = -1;
+static int hf_v2_status = -1;
+static int hf_v8_status = -1;
+static int hf_v2_li_spare = -1;
+static int hf_v8_li_spare = -1;
+static int hf_v2_li_prio = -1;
+static int hf_v8_li_prio = -1;
+static int hf_filler = -1;
+static int hf_unknown_data = -1;
+
+static gint ett_m2pa = -1;
+static gint ett_m2pa_li = -1;
+
+static int mtp3_proto_id;
+static dissector_handle_t mtp3_handle;
+
+typedef enum {
+ M2PA_V2 = 1,
+ M2PA_V11 = 2
+} Version_Type;
+
+static Version_Type m2pa_version = M2PA_V11;
+
+#define VERSION_LENGTH 1
+#define SPARE_LENGTH 1
+#define CLASS_LENGTH 1
+#define V2_TYPE_LENGTH 2
+#define V8_TYPE_LENGTH 1
+#define LENGTH_LENGTH 4
+#define UNUSED_LENGTH 1
+#define BSN_LENGTH 3
+#define FSN_LENGTH 3
+
+#define V2_HEADER_LENGTH (VERSION_LENGTH + SPARE_LENGTH + \
+ V2_TYPE_LENGTH + LENGTH_LENGTH)
+
+#define V8_HEADER_LENGTH (VERSION_LENGTH + SPARE_LENGTH + \
+ CLASS_LENGTH + V8_TYPE_LENGTH + LENGTH_LENGTH + \
+ UNUSED_LENGTH + BSN_LENGTH + UNUSED_LENGTH + \
+ FSN_LENGTH)
+
+#define HEADER_OFFSET 0
+#define VERSION_OFFSET HEADER_OFFSET
+#define SPARE_OFFSET (VERSION_OFFSET + VERSION_LENGTH)
+#define CLASS_OFFSET (SPARE_OFFSET + SPARE_LENGTH)
+#define V2_TYPE_OFFSET (SPARE_OFFSET + SPARE_LENGTH)
+#define V8_TYPE_OFFSET (CLASS_OFFSET + CLASS_LENGTH)
+#define V8_LENGTH_OFFSET (V8_TYPE_OFFSET + V8_TYPE_LENGTH)
+#define V2_LENGTH_OFFSET (V2_TYPE_OFFSET + V2_TYPE_LENGTH)
+#define FIRST_UNUSED_OFFSET (V8_LENGTH_OFFSET + LENGTH_LENGTH)
+#define BSN_OFFSET (FIRST_UNUSED_OFFSET + UNUSED_LENGTH)
+#define SECOND_UNUSED_OFFSET (BSN_OFFSET + BSN_LENGTH)
+#define FSN_OFFSET (SECOND_UNUSED_OFFSET + UNUSED_LENGTH)
+
+static const value_string protocol_version_values[] = {
+ { 1, "Release 1" },
+ { 0, NULL } };
+
+static const value_string message_class_values[] = {
+ { 0xb, "M2PA" },
+ { 0, NULL } };
+
+#define V2_USER_DATA_TYPE 0x0601
+#define V2_LINK_STATUS_TYPE 0x0602
+
+static const value_string v2_message_type_values[] = {
+ { V2_USER_DATA_TYPE, "User Data" },
+ { V2_LINK_STATUS_TYPE, "Link Status" },
+ { 0, NULL } };
+
+#define V8_USER_DATA_TYPE 0x0001
+#define V8_LINK_STATUS_TYPE 0x0002
+
+static const value_string v8_message_type_values[] = {
+ { V8_USER_DATA_TYPE, "User Data" },
+ { V8_LINK_STATUS_TYPE, "Link Status" },
+ { 0, NULL } };
+
+static void
+dissect_v2_header(tvbuff_t *header_tvb, packet_info *pinfo, proto_tree *m2pa_tree)
+{
+ guint16 message_type;
+
+ message_type = tvb_get_ntohs(header_tvb, V2_TYPE_OFFSET);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_type, v2_message_type_values, "reserved"));
+
+ if (m2pa_tree) {
+ proto_tree_add_item(m2pa_tree, hf_version, header_tvb, VERSION_OFFSET, VERSION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_spare, header_tvb, SPARE_OFFSET, SPARE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_v2_type, header_tvb, V2_TYPE_OFFSET, V2_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_length, header_tvb, V2_LENGTH_OFFSET, LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ }
+}
+
+static void
+dissect_v8_header(tvbuff_t *header_tvb, packet_info *pinfo, proto_tree *m2pa_tree)
+{
+ guint8 message_type;
+
+ message_type = tvb_get_guint8(header_tvb, V8_TYPE_OFFSET);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_type, v8_message_type_values, "Unknown"));
+
+ if (m2pa_tree) {
+ proto_tree_add_item(m2pa_tree, hf_version, header_tvb, VERSION_OFFSET, VERSION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_spare, header_tvb, SPARE_OFFSET, SPARE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_class, header_tvb, CLASS_OFFSET, CLASS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_v8_type, header_tvb, V8_TYPE_OFFSET, V8_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_length, header_tvb, V8_LENGTH_OFFSET, LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_unused, header_tvb, FIRST_UNUSED_OFFSET, UNUSED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_bsn, header_tvb, BSN_OFFSET, BSN_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_unused, header_tvb, SECOND_UNUSED_OFFSET, UNUSED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_tree, hf_fsn, header_tvb, FSN_OFFSET, FSN_LENGTH, NETWORK_BYTE_ORDER);
+ }
+}
+
+#define LI_OFFSET 0
+#define LI_LENGTH 1
+#define MTP3_OFFSET (LI_OFFSET + LI_LENGTH)
+
+#define V2_LI_SPARE_MASK 0xfc
+#define V2_LI_PRIORITY_MASK 0x3
+
+static void
+dissect_v2_user_data_message(tvbuff_t *message_data_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree)
+{
+ proto_item *m2pa_li_item;
+ proto_tree *m2pa_li_tree;
+ tvbuff_t *payload_tvb;
+
+ if (tvb_length(message_data_tvb) > 0) {
+ if (m2pa_tree) {
+ m2pa_li_item = proto_tree_add_text(m2pa_tree, message_data_tvb, LI_OFFSET, LI_LENGTH, "Length Indicator");
+ m2pa_li_tree = proto_item_add_subtree(m2pa_li_item, ett_m2pa_li);
+
+ proto_tree_add_item(m2pa_li_tree, hf_v2_li_spare, message_data_tvb, LI_OFFSET, LI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_li_tree, hf_v2_li_prio, message_data_tvb, LI_OFFSET, LI_LENGTH, NETWORK_BYTE_ORDER);
+
+ /* Re-adjust length of M2PA item since it will be dissected as MTP3 */
+ proto_item_set_len(m2pa_item, V2_HEADER_LENGTH + LI_LENGTH);
+ }
+ }
+
+ payload_tvb = tvb_new_subset(message_data_tvb, MTP3_OFFSET, -1, -1);
+ call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
+}
+
+#define V8_LI_SPARE_MASK 0x3f
+#define V8_LI_PRIORITY_MASK 0xc0
+
+static void
+dissect_v8_user_data_message(tvbuff_t *message_data_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree)
+{
+ proto_item *m2pa_li_item;
+ proto_tree *m2pa_li_tree;
+ tvbuff_t *payload_tvb;
+
+ if (tvb_length(message_data_tvb) > 0) {
+ if (m2pa_tree) {
+ m2pa_li_item = proto_tree_add_text(m2pa_tree, message_data_tvb, LI_OFFSET, LI_LENGTH, "Length Indicator");
+ m2pa_li_tree = proto_item_add_subtree(m2pa_li_item, ett_m2pa_li);
+ proto_tree_add_item(m2pa_li_tree, hf_v8_li_prio, message_data_tvb, LI_OFFSET, LI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2pa_li_tree, hf_v8_li_spare, message_data_tvb, LI_OFFSET, LI_LENGTH, NETWORK_BYTE_ORDER);
+
+ /* Re-adjust length of M2PA item since it will be dissected as MTP3 */
+ proto_item_set_len(m2pa_item, V8_HEADER_LENGTH + LI_LENGTH);
+ }
+
+ payload_tvb = tvb_new_subset(message_data_tvb, MTP3_OFFSET, -1, -1);
+ call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
+ }
+}
+
+static const value_string v2_link_status_values[] = {
+ { 1, "In Service" },
+ { 2, "Processor Outage" },
+ { 3, "Processor Outage Ended" },
+ { 4, "Busy" },
+ { 5, "Busy Ended" },
+ { 0, NULL } };
+
+#define STATUS_LENGTH 4
+#define STATUS_OFFSET 0
+#define FILLER_OFFSET (STATUS_OFFSET + STATUS_LENGTH)
+
+static void
+dissect_v2_link_status_message(tvbuff_t *message_data_tvb, packet_info *pinfo, proto_tree *m2pa_tree)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ", val_to_str(tvb_get_ntohl(message_data_tvb, STATUS_OFFSET), v2_link_status_values, "Unknown"));
+ if (m2pa_tree)
+ proto_tree_add_item(m2pa_tree, hf_v2_status, message_data_tvb, STATUS_OFFSET, STATUS_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+static const value_string v8_link_status_values[] = {
+ { 1, "Alignment" },
+ { 2, "Proving Normal" },
+ { 3, "Proving Emergency" },
+ { 4, "Ready" },
+ { 5, "Processor Outage" },
+ { 6, "Processor Outage Ended" },
+ { 7, "Busy" },
+ { 8, "Busy Ended" },
+ { 9, "Out of Service" },
+ { 0, NULL } };
+
+static void
+dissect_v8_link_status_message(tvbuff_t *message_data_tvb, packet_info *pinfo, proto_tree *m2pa_tree)
+{
+ guint16 filler_length;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ", val_to_str(tvb_get_ntohl(message_data_tvb, STATUS_OFFSET), v8_link_status_values, "Unknown"));
+
+ filler_length = tvb_length(message_data_tvb) - STATUS_LENGTH;
+
+ proto_tree_add_item(m2pa_tree, hf_v8_status, message_data_tvb, STATUS_OFFSET, STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ if (filler_length > 0)
+ proto_tree_add_item(m2pa_tree, hf_filler, message_data_tvb, FILLER_OFFSET, filler_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_unknown_message(tvbuff_t *message_data_tvb, proto_tree *m2pa_tree)
+{
+ guint length;
+
+ length = tvb_length(message_data_tvb);
+ if ((m2pa_tree) && (length > 0))
+ proto_tree_add_item(m2pa_tree, hf_unknown_data, message_data_tvb, 0, length, NETWORK_BYTE_ORDER);
+}
+
+#define V2_MESSAGE_DATA_OFFSET (HEADER_OFFSET + V2_HEADER_LENGTH)
+
+static void
+dissect_v2_message_data(tvbuff_t *message_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree)
+{
+ guint32 message_data_length;
+ guint16 type;
+ tvbuff_t *message_data_tvb;
+
+ message_data_length = tvb_get_ntohl(message_tvb, V2_LENGTH_OFFSET);
+ message_data_tvb = tvb_new_subset(message_tvb, V2_MESSAGE_DATA_OFFSET, message_data_length, message_data_length);
+ type = tvb_get_ntohs(message_tvb, V2_TYPE_OFFSET);
+
+ switch(type) {
+ case V2_USER_DATA_TYPE:
+ dissect_v2_user_data_message(message_data_tvb, pinfo, m2pa_item, m2pa_tree, tree);
+ break;
+ case V2_LINK_STATUS_TYPE:
+ dissect_v2_link_status_message(message_data_tvb, pinfo, m2pa_tree);
+ break;
+ default:
+ dissect_unknown_message(message_data_tvb, m2pa_tree);
+ }
+}
+
+#define V8_MESSAGE_DATA_OFFSET (HEADER_OFFSET + V8_HEADER_LENGTH)
+
+static void
+dissect_v8_message_data(tvbuff_t *message_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree)
+{
+ guint32 message_data_length;
+ guint8 type;
+ tvbuff_t *message_data_tvb;
+
+ message_data_length = tvb_get_ntohl(message_tvb, V8_LENGTH_OFFSET) - V8_HEADER_LENGTH;
+ message_data_tvb = tvb_new_subset(message_tvb, V8_MESSAGE_DATA_OFFSET, message_data_length, message_data_length);
+ type = tvb_get_guint8(message_tvb, V8_TYPE_OFFSET);
+
+
+ switch(type) {
+ case V8_USER_DATA_TYPE:
+ dissect_v8_user_data_message(message_data_tvb, pinfo, m2pa_item, m2pa_tree, tree);
+ break;
+ case V8_LINK_STATUS_TYPE:
+ dissect_v8_link_status_message(message_data_tvb, pinfo, m2pa_tree);
+ break;
+ default:
+ dissect_unknown_message(message_data_tvb, m2pa_tree);
+ }
+}
+
+static void
+dissect_v2_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree)
+{
+ dissect_v2_header(message_tvb, pinfo, m2pa_tree);
+ dissect_v2_message_data(message_tvb, pinfo, m2pa_item, m2pa_tree, tree);
+}
+
+static void
+dissect_v8_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_item *m2pa_item, proto_tree *m2pa_tree, proto_tree *tree)
+{
+ dissect_v8_header(message_tvb, pinfo, m2pa_tree);
+ dissect_v8_message_data(message_tvb, pinfo, m2pa_item, m2pa_tree, tree);
+}
+
+static void
+dissect_m2pa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *m2pa_item;
+ proto_tree *m2pa_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ switch(m2pa_version) {
+ case M2PA_V2:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "M2PA (ID 02)");
+ break;
+ case M2PA_V11:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "M2PA (ID 11)");
+ break;
+ };
+
+ if (tree) {
+ m2pa_item = proto_tree_add_item(tree, proto_m2pa, tvb, 0, -1, FALSE);
+ m2pa_tree = proto_item_add_subtree(m2pa_item, ett_m2pa);
+ } else {
+ m2pa_item = NULL;
+ m2pa_tree = NULL;
+ }
+
+ switch(m2pa_version) {
+ case M2PA_V2:
+ dissect_v2_message(tvb, pinfo, m2pa_item, m2pa_tree, tree);
+ break;
+ case M2PA_V11:
+ dissect_v8_message(tvb, pinfo, m2pa_item, m2pa_tree, tree);
+ break;
+ };
+}
+
+void
+proto_register_m2pa(void)
+{
+ static hf_register_info hf[] =
+ { { &hf_version, { "Version", "m2pa.version", FT_UINT8, BASE_DEC, VALS(protocol_version_values), 0x0, "", HFILL} },
+ { &hf_spare, { "Spare", "m2pa.spare", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL} },
+ { &hf_v2_type, { "Message Type", "m2pa.type", FT_UINT16, BASE_HEX, VALS(v2_message_type_values), 0x0, "", HFILL} },
+ { &hf_v8_type, { "Message Type", "m2pa.type", FT_UINT8, BASE_DEC, VALS(v8_message_type_values), 0x0, "", HFILL} },
+ { &hf_class, { "Message Class", "m2pa.class", FT_UINT8, BASE_DEC, VALS(message_class_values), 0x0, "", HFILL} },
+ { &hf_length, { "Message length", "m2pa.length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL} },
+ { &hf_unused, { "Unused", "m2pa.unused", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL} },
+ { &hf_bsn, { "BSN", "m2pa.bsn", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL} },
+ { &hf_fsn, { "FSN", "m2pa.fsn", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL} },
+ { &hf_v2_li_spare, { "Spare", "m2pa.li_spare", FT_UINT8, BASE_DEC, NULL, V2_LI_SPARE_MASK, "", HFILL} },
+ { &hf_v8_li_spare, { "Spare", "m2pa.li_spare", FT_UINT8, BASE_HEX, NULL, V8_LI_SPARE_MASK, "", HFILL} },
+ { &hf_v2_li_prio, { "Priority", "m2pa.li_priority", FT_UINT8, BASE_DEC, NULL, V2_LI_PRIORITY_MASK, "", HFILL} },
+ { &hf_v8_li_prio, { "Priority", "m2pa.li_priority", FT_UINT8, BASE_HEX, NULL, V8_LI_PRIORITY_MASK, "", HFILL} },
+ { &hf_v2_status, { "Link Status", "m2pa.status", FT_UINT32, BASE_DEC, VALS(v2_link_status_values), 0x0, "", HFILL} },
+ { &hf_v8_status, { "Link Status", "m2pa.status", FT_UINT32, BASE_DEC, VALS(v8_link_status_values), 0x0, "", HFILL} },
+ { &hf_filler, { "Filler", "m2pa.filler", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL} },
+ { &hf_unknown_data, { "Unknown Data", "m2pa.unknown_data", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL} }
+ };
+
+ static gint *ett[] = {
+ &ett_m2pa,
+ &ett_m2pa_li
+ };
+
+ static enum_val_t m2pa_version_options[] = {
+ { "draft-2", "Internet Draft version 2", M2PA_V2 },
+ { "draft-11", "Internet Draft version 11", M2PA_V11 },
+ { NULL, NULL, 0 }
+ };
+
+ proto_m2pa = proto_register_protocol("MTP2 Peer Adaptation Layer", "M2PA", "m2pa");
+
+ proto_register_field_array(proto_m2pa, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ m2pa_module = prefs_register_protocol(proto_m2pa, proto_reg_handoff_m2pa);
+
+ prefs_register_enum_preference(m2pa_module, "version", "M2PA version", "Version used by Ethereal", (gint *)&m2pa_version, m2pa_version_options, FALSE);
+ prefs_register_uint_preference(m2pa_module, "port", "M2PA SCTP Port", "Set the port for M2PA messages (Default of 3565)", 10, &global_sctp_port);
+}
+
+void
+proto_reg_handoff_m2pa(void)
+{
+ static int prefs_initialized = FALSE;
+ static dissector_handle_t m2pa_handle;
+
+ /* Port preferences code shamelessly copied from packet-beep.c */
+ if (!prefs_initialized) {
+ mtp3_handle = find_dissector("mtp3");
+ mtp3_proto_id = proto_get_id_by_filter_name("mtp3");
+ m2pa_handle = create_dissector_handle(dissect_m2pa, proto_m2pa);
+
+ dissector_add("sctp.ppi", M2PA_PAYLOAD_PROTOCOL_ID, m2pa_handle);
+
+ prefs_initialized = TRUE;
+
+ } else {
+
+ dissector_delete("sctp.port", sctp_port, m2pa_handle);
+
+ }
+
+ /* Set our port number for future use */
+ sctp_port = global_sctp_port;
+
+ dissector_add("sctp.port", sctp_port, m2pa_handle);
+}
diff --git a/epan/dissectors/packet-m2tp.c b/epan/dissectors/packet-m2tp.c
new file mode 100644
index 0000000000..e17b80f31a
--- /dev/null
+++ b/epan/dissectors/packet-m2tp.c
@@ -0,0 +1,677 @@
+/* packet-m2tp.c
+ * Routines for M2TP User Adaptation Layer dissection
+ * M2TP - MTP2 Transparent Proxy - is a Radisys proprietary
+ * protocol based on the IETF SIGTRAN standard
+ *
+ * Copyright 2001, Heinz Prantner <heinz.prantner[AT]radisys.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-m3ua.c
+ * Thanks to Michael Tuexen for his valuable improvements
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "sctpppids.h"
+
+#define SCTP_PORT_M2TP 9908 /* unassigned port number (not assigned by IANA) */
+
+#define VERSION_LENGTH 1
+#define RESERVED_LENGTH 1
+#define MESSAGE_CLASS_LENGTH 1
+#define MESSAGE_TYPE_LENGTH 1
+#define MESSAGE_LENGTH_LENGTH 4
+#define COMMON_HEADER_LENGTH (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
+ MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
+
+#define VERSION_OFFSET 0
+#define RESERVED_OFFSET (VERSION_OFFSET + VERSION_LENGTH)
+#define MESSAGE_CLASS_OFFSET (RESERVED_OFFSET + RESERVED_LENGTH)
+#define MESSAGE_TYPE_OFFSET (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
+#define MESSAGE_LENGTH_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
+
+#define PARAMETER_TAG_LENGTH 2
+#define PARAMETER_LENGTH_LENGTH 2
+#define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
+
+#define PARAMETER_TAG_OFFSET 0
+#define PARAMETER_LENGTH_OFFSET (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
+#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
+#define PARAMETER_HEADER_OFFSET PARAMETER_TAG_OFFSET
+
+#define INTERFACE_IDENTIFIER_PARAMETER_TAG 1
+#define MASTER_SLAVE_INDICATOR_PARAMETER_TAG 2
+#define M2TP_USER_IDENTIFIER_PARAMETER_TAG 3
+#define INFO_PARAMETER_TAG 4
+#define DIAGNOSTIC_INFORMATION_PARAMETER_TAG 7
+#define HEARTBEAT_DATA_PARAMETER_TAG 9
+#define REASON_PARAMETER_TAG 10
+#define ERROR_CODE_PARAMETER_TAG 12
+#define PROTOCOL_DATA_PARAMETER_TAG 13
+
+
+static const value_string m2tp_parameter_tag_values[] = {
+ { INTERFACE_IDENTIFIER_PARAMETER_TAG, "Interface Identifier" },
+ { MASTER_SLAVE_INDICATOR_PARAMETER_TAG, "Master Slave Indicator" },
+ { M2TP_USER_IDENTIFIER_PARAMETER_TAG, "M2tp User Identifier" },
+ { INFO_PARAMETER_TAG, "Info" },
+ { DIAGNOSTIC_INFORMATION_PARAMETER_TAG, "Diagnostic Information" },
+ { HEARTBEAT_DATA_PARAMETER_TAG, "Heartbeat Data" },
+ { REASON_PARAMETER_TAG, "Reason" },
+ { ERROR_CODE_PARAMETER_TAG, "Error Code" },
+ { PROTOCOL_DATA_PARAMETER_TAG, "Protocol Data" },
+ { 0, NULL } };
+
+#define PROTOCOL_VERSION_RELEASE_1 1
+
+static const value_string m2tp_protocol_version_values[] = {
+ { PROTOCOL_VERSION_RELEASE_1, "Release 1" },
+ { 0, NULL } };
+
+#define MESSAGE_CLASS_MGMT_MESSAGE 0
+#define MESSAGE_CLASS_SGSM_MESSAGE 3
+#define MESSAGE_CLASS_MAUP_MESSAGE 6
+#define MESSAGE_CLASS_DATA_MESSAGE 255
+
+static const value_string m2tp_message_class_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE, "Management Messages" },
+ { MESSAGE_CLASS_SGSM_MESSAGE, "SG State Maintenance Messages" },
+ { MESSAGE_CLASS_MAUP_MESSAGE, "MTP2 User Adaptation Messages" },
+ { MESSAGE_CLASS_DATA_MESSAGE, "User Data Messages" },
+ { 0, NULL } };
+
+/* management messages */
+#define MESSAGE_TYPE_ERR 0
+
+/* sg state maintenance messages */
+#define MESSAGE_TYPE_UP 1
+#define MESSAGE_TYPE_DOWN 2
+#define MESSAGE_TYPE_BEAT 3
+#define MESSAGE_TYPE_UP_ACK 4
+#define MESSAGE_TYPE_DOWN_ACK 5
+#define MESSAGE_TYPE_BEAT_ACK 6
+
+/* mtp2 user message */
+#define MESSAGE_TYPE_DATA 1
+
+
+static const value_string m2tp_message_class_type_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "Error (ERR)" },
+ { MESSAGE_CLASS_DATA_MESSAGE * 256 + MESSAGE_TYPE_DATA, "Payload data (DATA)" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP up (UP)" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP down (DOWN)" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "Heartbeat (BEAT)" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP up ack (UP ACK)" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP down ack (DOWN ACK)" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "Heartbeat ack (BEAT ACK)" },
+ { 0, NULL } };
+
+static const value_string m2tp_message_class_type_acro_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "ERR" },
+ { MESSAGE_CLASS_DATA_MESSAGE * 256 + MESSAGE_TYPE_DATA, "DATA" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP_UP" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP_DOWN" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "BEAT" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP_UP_ACK" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP_DOWN_ACK" },
+ { MESSAGE_CLASS_SGSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "BEAT_ACK" },
+ { 0, NULL } };
+
+
+
+#define HEARTBEAT_PERIOD_OFFSET PARAMETER_VALUE_OFFSET
+
+#define INTERFACE_IDENTIFIER_LENGTH 4
+#define INTERFACE_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+
+#define M2TP_USER_LENGTH 4
+#define M2TP_USER_OFFSET PARAMETER_VALUE_OFFSET
+
+#define PROTOCOL_DATA_OFFSET PARAMETER_VALUE_OFFSET
+
+#define MASTER_SLAVE_LENGTH 4
+#define MASTER_SLAVE_OFFSET PARAMETER_VALUE_OFFSET
+
+#define REASON_LENGTH 4
+#define REASON_OFFSET PARAMETER_VALUE_OFFSET
+
+#define HEART_BEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
+
+#define ERROR_CODE_LENGTH 4
+#define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
+
+#define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
+
+#define BSN_OFFSET PARAMETER_VALUE_OFFSET
+#define FSN_OFFSET PARAMETER_VALUE_OFFSET+1
+
+#define M2TP_USER_MTP2 1
+#define M2TP_USER_Q921 2
+#define M2TP_USER_FRAME_RELAY 3
+
+static const value_string m2tp_user_identifier_values[] = {
+ { M2TP_USER_MTP2, "MTP2" },
+ { M2TP_USER_Q921, "Q.921" },
+ { M2TP_USER_FRAME_RELAY, "Frame Relay" },
+ { 0, NULL }};
+
+#define M2TP_MODE_MASTER 1
+#define M2TP_MODE_SLAVE 2
+
+static const value_string m2tp_mode_values[] = {
+ { M2TP_MODE_MASTER, "Master" },
+ { M2TP_MODE_SLAVE, "Slave" },
+ { 0, NULL}};
+
+#define M2TP_ERROR_CODE_INVALID_VERSION 1
+#define M2TP_ERROR_CODE_INVALID_INTERFACE_IDENTIFIER 2
+#define M2TP_ERROR_CODE_INVALID_ADAPTATION_LAYER_IDENTIFIER 3
+#define M2TP_ERROR_CODE_INVALID_MESSAGE_TYPE 4
+#define M2TP_ERROR_CODE_INVALID_TRAFFIC_HANDLING_MODE 5
+#define M2TP_ERROR_CODE_UNEXPECTED_MESSAGE 6
+#define M2TP_ERROR_CODE_PROTOCOL_ERROR 7
+#define M2TP_ERROR_CODE_INVALID_STREAM_IDENTIFIER 8
+#define M2TP_ERROR_CODE_INCOMPATIBLE_MASTER_SLAVE_CONFIGURATION 9
+
+static const value_string m2tp_error_code_values[] = {
+ { M2TP_ERROR_CODE_INVALID_VERSION, "Invalid Version" },
+ { M2TP_ERROR_CODE_INVALID_INTERFACE_IDENTIFIER, "Invalid Interface Identifier" },
+ { M2TP_ERROR_CODE_INVALID_ADAPTATION_LAYER_IDENTIFIER, "Invalid Adaptation Layer Identifier" },
+ { M2TP_ERROR_CODE_INVALID_MESSAGE_TYPE, "Invalid Message Type" },
+ { M2TP_ERROR_CODE_INVALID_TRAFFIC_HANDLING_MODE, "Invalid Traffic Handling Mode" },
+ { M2TP_ERROR_CODE_UNEXPECTED_MESSAGE, "Unexpected Message" },
+ { M2TP_ERROR_CODE_PROTOCOL_ERROR, "Protocol Error" },
+ { M2TP_ERROR_CODE_INVALID_STREAM_IDENTIFIER, "Invalid Stream Identified" },
+ { M2TP_ERROR_CODE_INCOMPATIBLE_MASTER_SLAVE_CONFIGURATION,"Incompatible Master Slave Configuration" },
+ { 0, NULL } };
+
+#define MANAGEMENT_ORDER_REASON_CODE 1
+#define MTP_RELEASE_REASON_CODE 2
+
+static const value_string m2tp_reason_code_values[] = {
+ { MANAGEMENT_ORDER_REASON_CODE, "Management Order" },
+ { MTP_RELEASE_REASON_CODE, "MTP Release" },
+ { 0, NULL } };
+
+
+/* Initialize the protocol and registered fields */
+static int proto_m2tp = -1;
+static int hf_m2tp_version = -1;
+static int hf_m2tp_reserved = -1;
+static int hf_m2tp_message_class = -1;
+static int hf_m2tp_message_type = -1;
+static int hf_m2tp_message_length = -1;
+static int hf_m2tp_parameter_tag = -1;
+static int hf_m2tp_parameter_length = -1;
+static int hf_m2tp_parameter_value = -1;
+static int hf_m2tp_parameter_padding = -1;
+static int hf_m2tp_interface_identifier = -1;
+static int hf_m2tp_user = -1;
+static int hf_m2tp_master_slave = -1;
+static int hf_m2tp_info_string = -1;
+static int hf_m2tp_heartbeat_data = -1;
+static int hf_m2tp_diagnostic_info = -1;
+static int hf_m2tp_error_code = -1;
+static int hf_m2tp_reason = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_m2tp = -1;
+static gint ett_m2tp_parameter = -1;
+
+static dissector_handle_t mtp2_handle;
+static int mtp2_proto_id;
+
+static guint
+nr_of_padding_bytes (guint length)
+{
+ guint remainder;
+
+ remainder = length % 4;
+
+ if (remainder == 0)
+ return 0;
+ else
+ return 4 - remainder;
+}
+
+/* Common Header */
+static void
+dissect_m2tp_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *m2tp_tree)
+{
+ guint8 version, reserved, message_class, message_type;
+ guint32 message_length;
+
+ /* Extract the common header */
+ version = tvb_get_guint8(common_header_tvb, VERSION_OFFSET);
+ reserved = tvb_get_guint8(common_header_tvb, RESERVED_OFFSET);
+ message_class = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
+ message_type = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
+ message_length = tvb_get_ntohl (common_header_tvb, MESSAGE_LENGTH_OFFSET);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_class * 256 + message_type, m2tp_message_class_type_acro_values, "reserved"));
+
+ if (m2tp_tree) {
+ /* add the components of the common header to the protocol tree */
+ proto_tree_add_uint(m2tp_tree, hf_m2tp_version, common_header_tvb, VERSION_OFFSET, VERSION_LENGTH, version);
+ proto_tree_add_uint(m2tp_tree, hf_m2tp_reserved, common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH, reserved);
+ proto_tree_add_uint(m2tp_tree, hf_m2tp_message_class, common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH, message_class);
+ proto_tree_add_uint_format(m2tp_tree, hf_m2tp_message_type,
+ common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH,
+ message_type, "Message type: %u (%s)",
+ message_type, val_to_str(message_class * 256 + message_type, m2tp_message_class_type_values, "reserved"));
+ proto_tree_add_uint(m2tp_tree, hf_m2tp_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, message_length);
+ };
+}
+
+/* Interface Identifier */
+static void
+dissect_m2tp_interface_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint32 parameter_value;
+
+ if (parameter_tree) {
+ parameter_value = tvb_get_ntohl(parameter_tvb, PARAMETER_VALUE_OFFSET);
+ proto_tree_add_uint(parameter_tree, hf_m2tp_interface_identifier, parameter_tvb, INTERFACE_IDENTIFIER_OFFSET, INTERFACE_IDENTIFIER_LENGTH, parameter_value);
+ proto_item_set_text(parameter_item, "Interface Identifier (%u)", parameter_value);
+ }
+}
+
+/* Master Slave Indicator */
+static void
+dissect_m2tp_master_slave_parameter (tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint32 parameter_value;
+
+ if (parameter_tree) {
+ parameter_value = tvb_get_ntohl(parameter_tvb, PARAMETER_VALUE_OFFSET);
+ proto_tree_add_uint(parameter_tree, hf_m2tp_master_slave, parameter_tvb, MASTER_SLAVE_OFFSET, MASTER_SLAVE_LENGTH, parameter_value);
+ proto_item_set_text(parameter_item, "Master Slave Indicator (%s)", val_to_str(parameter_value, m2tp_mode_values, "unknown"));
+ }
+}
+
+/* M2tp User Identifier */
+static void
+dissect_m2tp_user_identifier_parameter (tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint32 parameter_value;
+
+ if (parameter_tree) {
+ parameter_value = tvb_get_ntohl(parameter_tvb, PARAMETER_VALUE_OFFSET);
+ proto_tree_add_uint(parameter_tree, hf_m2tp_user, parameter_tvb, M2TP_USER_OFFSET, M2TP_USER_LENGTH, parameter_value);
+ proto_item_set_text(parameter_item, "M2TP User Identifier (%u)", parameter_value);
+ }
+}
+
+/* Info String */
+static void
+dissect_m2tp_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 length, info_string_length;
+ const char *info_string;
+
+ if (parameter_tree) {
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ info_string_length = length - PARAMETER_HEADER_LENGTH;
+ info_string = (const char *)tvb_get_ptr(parameter_tvb, INFO_STRING_OFFSET, info_string_length);
+ proto_tree_add_string(parameter_tree, hf_m2tp_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, info_string);
+ proto_item_set_text(parameter_item, "Info String (%.*s)", info_string_length, info_string);
+ }
+}
+
+/* Diagnostic Information */
+static void
+dissect_m2tp_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 length, diagnostic_info_length;
+
+ if (parameter_tree) {
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ diagnostic_info_length = length - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_bytes(parameter_tree, hf_m2tp_diagnostic_info, parameter_tvb, PARAMETER_VALUE_OFFSET, diagnostic_info_length,
+ tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, diagnostic_info_length));
+ proto_item_set_text(parameter_item, "Diagnostic information (%u byte%s)", diagnostic_info_length, plurality(diagnostic_info_length, "", "s"));
+ }
+}
+
+/* Heartbeat Data */
+static void
+dissect_m2tp_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 length, heartbeat_data_length;
+
+ if (parameter_tree) {
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ heartbeat_data_length = length - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_bytes(parameter_tree, hf_m2tp_heartbeat_data, parameter_tvb, PARAMETER_VALUE_OFFSET, heartbeat_data_length,
+ tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, heartbeat_data_length));
+ proto_item_set_text(parameter_item, "Heartbeat data (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
+ }
+}
+
+/* Reason Parameter */
+static void
+dissect_m2tp_reason_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint32 reason;
+
+ if (parameter_tree) {
+ reason = tvb_get_ntohl(parameter_tvb, REASON_OFFSET);
+ proto_tree_add_uint(parameter_tree, hf_m2tp_reason, parameter_tvb, REASON_OFFSET, REASON_LENGTH, reason);
+ proto_item_set_text(parameter_item, "Reason parameter (%s)", val_to_str(reason, m2tp_reason_code_values, "unknown"));
+ }
+}
+
+/* Error Code */
+static void
+dissect_m2tp_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint32 error_code;
+
+ if (parameter_tree) {
+ error_code = tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET);
+ proto_tree_add_uint(parameter_tree, hf_m2tp_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, error_code);
+ proto_item_set_text(parameter_item, "Error code parameter (%s)", val_to_str(error_code, m2tp_error_code_values, "unknown"));
+ }
+}
+
+/* Protocol Data */
+static void
+dissect_m2tp_protocol_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, packet_info *pinfo, proto_item *m2tp_item, proto_tree *tree)
+{
+ guint16 length, protocol_data_length, padding_length;
+ tvbuff_t *mtp2_tvb;
+
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = nr_of_padding_bytes(length);
+ protocol_data_length = length - PARAMETER_HEADER_LENGTH;
+
+ mtp2_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, protocol_data_length, protocol_data_length);
+ call_dissector(mtp2_handle, mtp2_tvb, pinfo, tree);
+
+ if (parameter_tree) {
+ proto_item_set_text(parameter_item, "Protocol data (SS7 message)");
+ proto_item_set_len(parameter_item, proto_item_get_len(parameter_item) - protocol_data_length - padding_length);
+ proto_item_set_len(m2tp_item, proto_item_get_len(m2tp_item) - protocol_data_length - padding_length);
+
+ }
+}
+
+/* Unknown Parameter */
+static void
+dissect_m2tp_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 tag, length, parameter_value_length;
+
+ if (parameter_tree) {
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+
+ parameter_value_length = length - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_bytes(parameter_tree, hf_m2tp_parameter_value,
+ parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length,
+ tvb_get_ptr(parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length));
+
+ proto_item_set_text(parameter_item, "Parameter with tag %u and %u byte%s value", tag, parameter_value_length, plurality(parameter_value_length, "", "s"));
+ }
+}
+
+/* M2TP Parameter */
+static void
+dissect_m2tp_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *m2tp_tree, proto_item *m2tp_item, proto_tree *tree)
+{
+ guint16 tag, length, padding_length, total_length;
+ proto_item *parameter_item = NULL;
+ proto_tree *parameter_tree = NULL;
+
+ /* extract tag and length from the parameter */
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+
+ /* calculate padding and total length */
+ padding_length = nr_of_padding_bytes(length);
+ total_length = length + padding_length;
+
+ if (tree) {
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(m2tp_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, total_length, "Incomplete parameter");
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_m2tp_parameter);
+
+ /* add tag and length to the m2tp tree */
+ proto_tree_add_uint(parameter_tree, hf_m2tp_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, tag);
+ proto_tree_add_uint(parameter_tree, hf_m2tp_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, length);
+ }
+
+ switch(tag) {
+ case INTERFACE_IDENTIFIER_PARAMETER_TAG:
+ dissect_m2tp_interface_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case MASTER_SLAVE_INDICATOR_PARAMETER_TAG:
+ dissect_m2tp_master_slave_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case M2TP_USER_IDENTIFIER_PARAMETER_TAG:
+ dissect_m2tp_user_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case INFO_PARAMETER_TAG:
+ dissect_m2tp_info_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
+ dissect_m2tp_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case HEARTBEAT_DATA_PARAMETER_TAG:
+ dissect_m2tp_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case REASON_PARAMETER_TAG:
+ dissect_m2tp_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ERROR_CODE_PARAMETER_TAG:
+ dissect_m2tp_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PROTOCOL_DATA_PARAMETER_TAG:
+ dissect_m2tp_protocol_data_parameter(parameter_tvb, parameter_tree, parameter_item, pinfo, m2tp_item, tree);
+ break;
+ default:
+ dissect_m2tp_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ };
+
+ if ((parameter_tree) && (padding_length > 0))
+ proto_tree_add_bytes(parameter_tree, hf_m2tp_parameter_padding,
+ parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length,
+ tvb_get_ptr(parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length));
+}
+
+/* M2TP Message */
+static void
+dissect_m2tp_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_item *m2tp_item, proto_tree *m2tp_tree, proto_tree *tree)
+{
+ gint offset, length, padding_length, total_length;
+ tvbuff_t *common_header_tvb, *parameter_tvb;
+
+ offset = 0;
+
+ /* extract and process the common header */
+ common_header_tvb = tvb_new_subset(message_tvb, offset, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
+ dissect_m2tp_common_header(common_header_tvb, pinfo, m2tp_tree);
+ offset += COMMON_HEADER_LENGTH;
+
+ /* extract zero or more parameters and process them individually */
+ while(tvb_reported_length_remaining(message_tvb, offset)) {
+ length = tvb_get_ntohs(message_tvb, offset + PARAMETER_LENGTH_OFFSET);
+ padding_length = nr_of_padding_bytes(length);
+ total_length = length + padding_length;
+ /* create a tvb for the parameter including the padding bytes */
+ parameter_tvb = tvb_new_subset(message_tvb, offset, total_length, total_length);
+ dissect_m2tp_parameter(parameter_tvb, pinfo, m2tp_tree, m2tp_item, tree);
+ /* get rid of the handled parameter */
+ offset += total_length;
+ }
+}
+
+/* M2tp */
+static void
+dissect_m2tp(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *m2tp_item;
+ proto_tree *m2tp_tree;
+
+ /* make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "M2TP");
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the m2tp protocol tree */
+ m2tp_item = proto_tree_add_item(tree, proto_m2tp, message_tvb, 0, -1, FALSE);
+ m2tp_tree = proto_item_add_subtree(m2tp_item, ett_m2tp);
+ } else {
+ m2tp_item = NULL;
+ m2tp_tree = NULL;
+ };
+ /* dissect the message */
+ dissect_m2tp_message(message_tvb, pinfo, m2tp_item, m2tp_tree, tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_m2tp(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_m2tp_version,
+ { "Version", "m2tp.version",
+ FT_UINT8, BASE_DEC, VALS(m2tp_protocol_version_values), 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_reserved,
+ { "Reserved", "m2tp.reserved",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_message_class,
+ { "Message class", "m2tp.message_class",
+ FT_UINT8, BASE_DEC, VALS(m2tp_message_class_values), 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_message_type,
+ { "Message Type", "m2tp.message_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_message_length,
+ { "Message length", "m2tp.message_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_parameter_tag,
+ { "Parameter Tag", "m2tp.parameter_tag",
+ FT_UINT16, BASE_DEC, VALS(m2tp_parameter_tag_values), 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_parameter_length,
+ { "Parameter length", "m2tp.parameter_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_parameter_value,
+ { "Parameter Value", "m2tp.parameter_value",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_m2tp_parameter_padding,
+ { "Padding", "m2tp.parameter_padding",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_m2tp_interface_identifier,
+ { "Interface Identifier", "m2tp.interface_identifier",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_user,
+ { "M2tp User Identifier", "m2tp.user_identifier",
+ FT_UINT32, BASE_DEC, VALS(m2tp_user_identifier_values), 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_master_slave,
+ { "Master Slave Indicator", "m2tp.master_slave",
+ FT_UINT32, BASE_DEC, VALS(m2tp_mode_values), 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_info_string,
+ { "Info string", "m2tp.info_string",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_diagnostic_info,
+ { "Diagnostic information", "m2tp.diagnostic_info",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_m2tp_heartbeat_data,
+ { "Heartbeat data", "m2tp.heartbeat_data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_m2tp_error_code,
+ { "Error code", "m2tp.error_code",
+ FT_UINT32, BASE_DEC, VALS(m2tp_error_code_values), 0x0,
+ "", HFILL}
+ },
+ { &hf_m2tp_reason,
+ { "Reason", "m2tp.reason",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_m2tp,
+ &ett_m2tp_parameter,
+ };
+
+ /* Register the protocol name and description */
+ proto_m2tp = proto_register_protocol("MTP 2 Transparent Proxy", "M2TP", "m2tp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_m2tp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_m2tp(void)
+{
+ dissector_handle_t m2tp_handle;
+ mtp2_handle = find_dissector("mtp2");
+ mtp2_proto_id = proto_get_id_by_filter_name("mtp2");
+ m2tp_handle = create_dissector_handle(dissect_m2tp, proto_m2tp);
+ dissector_add("sctp.ppi", M2TP_PAYLOAD_PROTOCOL_ID, m2tp_handle);
+ dissector_add("sctp.port", SCTP_PORT_M2TP, m2tp_handle);
+}
diff --git a/epan/dissectors/packet-m2ua.c b/epan/dissectors/packet-m2ua.c
new file mode 100644
index 0000000000..48ab05a047
--- /dev/null
+++ b/epan/dissectors/packet-m2ua.c
@@ -0,0 +1,1160 @@
+/* packet-m2ua.c
+ * Routines for MTP2 User Adaptation Layer dissection
+ * It is hopefully (needs testing) compilant to
+ * http://www.ietf.org/rfc/rfc3331.txt
+ * To do: - provide better handling of length parameters
+ *
+ * Copyright 2002, Michael Tuexen <tuexen [AT] fh-muenster.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include "sctpppids.h"
+
+#define SCTP_PORT_M2UA 2904
+#define NETWORK_BYTE_ORDER FALSE
+
+
+
+/* Initialize the protocol and registered fields */
+static int proto_m2ua = -1;
+static int hf_version = -1;
+static int hf_reserved = -1;
+static int hf_message_class = -1;
+static int hf_message_type = -1;
+static int hf_message_length = -1;
+static int hf_parameter_tag = -1;
+static int hf_parameter_length = -1;
+static int hf_parameter_value = -1;
+static int hf_parameter_padding = -1;
+static int hf_interface_id_int = -1;
+static int hf_interface_id_text = -1;
+static int hf_info_string = -1;
+static int hf_diagnostic_information = -1;
+static int hf_interface_id_start = -1;
+static int hf_interface_id_stop = -1;
+static int hf_heartbeat_data = -1;
+static int hf_traffic_mode_type = -1;
+static int hf_error_code = -1;
+static int hf_status_type = -1;
+static int hf_status_ident = -1;
+static int hf_asp_id = -1;
+static int hf_correlation_id = -1;
+static int hf_data_2_li = -1;
+static int hf_state = -1;
+static int hf_event = -1;
+static int hf_congestion_status = -1;
+static int hf_discard_status = -1;
+static int hf_action = -1;
+static int hf_sequence_number = -1;
+static int hf_retrieval_result = -1;
+static int hf_local_lk_id = -1;
+static int hf_sdt_reserved = -1;
+static int hf_sdt_id = -1;
+static int hf_sdl_reserved = -1;
+static int hf_sdl_id = -1;
+static int hf_registration_status = -1;
+static int hf_deregistration_status = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_m2ua = -1;
+static gint ett_m2ua_parameter = -1;
+
+static dissector_handle_t mtp3_handle;
+
+static void
+dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_tree *);
+
+#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
+
+#define VERSION_LENGTH 1
+#define RESERVED_LENGTH 1
+#define MESSAGE_CLASS_LENGTH 1
+#define MESSAGE_TYPE_LENGTH 1
+#define MESSAGE_LENGTH_LENGTH 4
+#define COMMON_HEADER_LENGTH (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
+ MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
+
+#define VERSION_OFFSET 0
+#define RESERVED_OFFSET (VERSION_OFFSET + VERSION_LENGTH)
+#define MESSAGE_CLASS_OFFSET (RESERVED_OFFSET + RESERVED_LENGTH)
+#define MESSAGE_TYPE_OFFSET (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
+#define MESSAGE_LENGTH_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
+
+#define PROTOCOL_VERSION_RELEASE_1 1
+
+static const value_string protocol_version_values[] = {
+ { PROTOCOL_VERSION_RELEASE_1, "Release 1" },
+ { 0, NULL } };
+
+#define MESSAGE_CLASS_MGMT_MESSAGE 0
+#define MESSAGE_CLASS_ASPSM_MESSAGE 3
+#define MESSAGE_CLASS_ASPTM_MESSAGE 4
+#define MESSAGE_CLASS_MAUP_MESSAGE 6
+#define MESSAGE_CLASS_IIM_MESSAGE 10
+
+static const value_string message_class_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE, "Management messages" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE, "ASP state maintenance messages" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE, "ASP traffic maintenance messages" },
+ { MESSAGE_CLASS_MAUP_MESSAGE, "MTP2 user adaptation messages" },
+ { MESSAGE_CLASS_IIM_MESSAGE, "Interface identifier management messages" },
+ { 0, NULL } };
+
+/* MGMT */
+#define MESSAGE_TYPE_ERR 0
+#define MESSAGE_TYPE_NTFY 1
+
+/* ASPSM */
+#define MESSAGE_TYPE_UP 1
+#define MESSAGE_TYPE_DOWN 2
+#define MESSAGE_TYPE_BEAT 3
+#define MESSAGE_TYPE_UP_ACK 4
+#define MESSAGE_TYPE_DOWN_ACK 5
+#define MESSAGE_TYPE_BEAT_ACK 6
+
+/* ASPTM */
+#define MESSAGE_TYPE_ACTIVE 1
+#define MESSAGE_TYPE_INACTIVE 2
+#define MESSAGE_TYPE_ACTIVE_ACK 3
+#define MESSAGE_TYPE_INACTIVE_ACK 4
+
+/* MAUP */
+#define MESSAGE_TYPE_DATA 1
+#define MESSAGE_TYPE_ESTAB_REQ 2
+#define MESSAGE_TYPE_ESTAB_CONF 3
+#define MESSAGE_TYPE_REL_REQ 4
+#define MESSAGE_TYPE_REL_CONF 5
+#define MESSAGE_TYPE_REL_IND 6
+#define MESSAGE_TYPE_STATE_REQ 7
+#define MESSAGE_TYPE_STATE_CONF 8
+#define MESSAGE_TYPE_STATE_IND 9
+#define MESSAGE_TYPE_DATA_RETR_REQ 10
+#define MESSAGE_TYPE_DATA_RETR_CONF 11
+#define MESSAGE_TYPE_DATA_RETR_IND 12
+#define MESSAGE_TYPE_DATA_RETR_COMP_IND 13
+#define MESSAGE_TYPE_CONG_IND 14
+#define MESSAGE_TYPE_DATA_ACK 15
+
+/* IIM */
+#define MESSAGE_TYPE_REG_REQ 1
+#define MESSAGE_TYPE_REG_RSP 2
+#define MESSAGE_TYPE_DEREG_REQ 3
+#define MESSAGE_TYPE_DEREG_RSP 4
+
+static const value_string message_class_type_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "Error (ERR)" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "Notify (NTFY)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP up (UP)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP down (DOWN)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "Heartbeat (BEAT)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP up ack (UP ACK)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP down ack (DOWN ACK)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "Heartbeat ack (BEAT ACK)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP active (ACTIVE)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP inactive (INACTIVE)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP active ack (ACTIVE ACK)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack (INACTIVE ACK)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA, "DATA (DATA)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_ESTAB_REQ, "Establish request (ESTAB_REQ)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_ESTAB_CONF, "Establish confirm (ESTAB_CONF)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_REL_REQ, "Release request (REL_REQ)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_REL_CONF, "Release confirm (REL_CONF)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_REL_IND, "Release indication (REL_IND)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_STATE_REQ, "State request (STATE_REQ)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_STATE_CONF, "State confirm (STATE_CONF)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_STATE_IND, "State indication (STATE_IND)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_RETR_REQ, "Data retrieval request (DATA_RETR_REQ)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_RETR_CONF, "Data retrieval confirm (DATA_RETR_CONF)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_RETR_IND, "Data retrieval indication (DATA_RETR_IND)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_RETR_COMP_IND, "Data retrieval complete indication (DATA_RETR_COMP_IND)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_CONG_IND, "Congestion indication (CONG_IND)" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_ACK, "Data acknowledge (DATA_ACK)" },
+ { MESSAGE_CLASS_IIM_MESSAGE * 256 + MESSAGE_TYPE_REG_REQ , "Registration request (REG_REQ)" },
+ { MESSAGE_CLASS_IIM_MESSAGE * 256 + MESSAGE_TYPE_REG_RSP , "Registration response (REG_RSP)" },
+ { MESSAGE_CLASS_IIM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_REQ , "Deregistration request (DEREG_REQ)" },
+ { MESSAGE_CLASS_IIM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_RSP , "Deregistration response (DEREG_RSP)" },
+ { 0, NULL } };
+
+static const value_string message_class_type_acro_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "ERR" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "NTFY" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP_UP" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP_DOWN" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "BEAT" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP_UP_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP_DOWN_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "BEAT_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP_ACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP_INACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP_ACTIVE_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA, "DATA" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_ESTAB_REQ, "ESTAB_REQ" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_ESTAB_CONF, "ESTAB_CONF" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_REL_REQ, "REL_REQ" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_REL_CONF, "REL_CONF" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_REL_IND, "REL_IND" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_STATE_REQ, "STATE_REQ" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_STATE_CONF, "STATE_CONF" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_STATE_IND, "STATE_IND" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_RETR_REQ, "DATA_RETR_REQ" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_RETR_CONF, "DATA_RETR_CONF" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_RETR_IND, "DATA_RETR_IND" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_RETR_COMP_IND, "DATA_RETR_COMP_IND" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_CONG_IND, "CONG_IND" },
+ { MESSAGE_CLASS_MAUP_MESSAGE * 256 + MESSAGE_TYPE_DATA_ACK, "DATA_ACK" },
+ { MESSAGE_CLASS_IIM_MESSAGE * 256 + MESSAGE_TYPE_REG_REQ , "REG_REQ" },
+ { MESSAGE_CLASS_IIM_MESSAGE * 256 + MESSAGE_TYPE_REG_RSP , "REG_RSP" },
+ { MESSAGE_CLASS_IIM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_REQ , "DEREG_REQ" },
+ { MESSAGE_CLASS_IIM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_RSP , "DEREG_RSP" },
+ { 0, NULL } };
+
+static void
+dissect_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *m2ua_tree)
+{
+ guint8 message_class, message_type;
+
+ /* Extract the common header */
+ message_class = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
+ message_type = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_class * 256 + message_type, message_class_type_acro_values, "reserved"));
+
+ if (m2ua_tree) {
+ /* add the components of the common header to the protocol tree */
+ proto_tree_add_item(m2ua_tree, hf_version, common_header_tvb, VERSION_OFFSET, VERSION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2ua_tree, hf_reserved, common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m2ua_tree, hf_message_class, common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(m2ua_tree, hf_message_type, common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type,
+ "Message type: %s (%u)",
+ val_to_str(message_class * 256 + message_type, message_class_type_values, "reserved"), message_type);
+ proto_tree_add_item(m2ua_tree, hf_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ }
+}
+
+#define PARAMETER_TAG_LENGTH 2
+#define PARAMETER_LENGTH_LENGTH 2
+#define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
+
+#define PARAMETER_TAG_OFFSET 0
+#define PARAMETER_LENGTH_OFFSET (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
+#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
+#define PARAMETER_HEADER_OFFSET PARAMETER_TAG_OFFSET
+
+
+#define INT_INTERFACE_ID_OFFSET PARAMETER_VALUE_OFFSET
+#define INT_INTERFACE_ID_LENGTH 4
+
+static void
+dissect_interface_identifier_int_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_interface_id_int, parameter_tvb, INT_INTERFACE_ID_OFFSET, INT_INTERFACE_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%d)", tvb_get_ntohl(parameter_tvb, INT_INTERFACE_ID_OFFSET));
+}
+
+#define TEXT_INTERFACE_ID_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_interface_identifier_text_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 interface_id_length;
+
+ interface_id_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+
+ proto_tree_add_item(parameter_tree, hf_interface_id_text, parameter_tvb, TEXT_INTERFACE_ID_OFFSET, interface_id_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%.*s)", interface_id_length,
+ (const char *)tvb_get_ptr(parameter_tvb, TEXT_INTERFACE_ID_OFFSET, interface_id_length));
+}
+
+#define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_info_string_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 info_string_length;
+
+ info_string_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%.*s)", info_string_length,
+ (const char *)tvb_get_ptr(parameter_tvb, INFO_STRING_OFFSET, info_string_length));
+}
+
+#define DIAGNOSTIC_INFO_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 diag_info_length;
+
+ diag_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_diagnostic_information, parameter_tvb, DIAGNOSTIC_INFO_OFFSET, diag_info_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", diag_info_length, plurality(diag_info_length, "", "s"));
+}
+
+#define START_LENGTH 4
+#define END_LENGTH 4
+#define INTERVAL_LENGTH (START_LENGTH + END_LENGTH)
+
+#define START_OFFSET 0
+#define END_OFFSET (START_OFFSET + START_LENGTH)
+
+static void
+dissect_interface_identifier_range_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 number_of_ranges, range_number;
+ gint offset;
+
+ number_of_ranges = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / INTERVAL_LENGTH;
+ offset = PARAMETER_VALUE_OFFSET;
+ for(range_number = 1; range_number <= number_of_ranges; range_number++) {
+ proto_tree_add_item(parameter_tree, hf_interface_id_start, parameter_tvb, offset + START_OFFSET, START_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_interface_id_stop, parameter_tvb, offset + END_OFFSET, END_LENGTH, NETWORK_BYTE_ORDER);
+ offset += INTERVAL_LENGTH;
+ };
+
+ proto_item_append_text(parameter_item, " (%u range%s)", number_of_ranges, plurality(number_of_ranges, "", "s"));
+}
+
+#define HEARTBEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 heartbeat_data_length;
+
+ heartbeat_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_heartbeat_data, parameter_tvb, HEARTBEAT_DATA_OFFSET, heartbeat_data_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
+}
+
+#define OVER_RIDE_TYPE 1
+#define LOAD_SHARE_TYPE 2
+#define BROADCAST_TYPE 3
+
+static const value_string traffic_mode_type_values[] = {
+ { OVER_RIDE_TYPE , "Override" },
+ { LOAD_SHARE_TYPE, "Load-share" },
+ { BROADCAST_TYPE, "Broadcast" },
+ { 0, NULL } };
+
+#define TRAFFIC_MODE_TYPE_LENGTH 4
+#define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)",
+ val_to_str(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), traffic_mode_type_values, "unknown"));
+}
+
+#define INVALID_VERSION_ERROR_CODE 0x01
+#define INVALID_INTERFACE_IDENTIFIER_ERROR_CODE 0x02
+#define UNSUPPORTED_MESSAGE_CLASS_ERROR_CODE 0x03
+#define UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE 0x04
+#define UNSUPPORTED_TRAFFIC_HANDLING_MODE_ERROR_CODE 0x05
+#define UNEXPECTED_MESSAGE_ERROR_CODE 0x06
+#define PROTOCOL_ERROR_ERROR_CODE 0x07
+#define UNSUPPORTED_INTERFACE_IDENTIFIER_TYPE_ERROR_CODE 0x08
+#define INVALID_STREAM_IDENTIFIER_ERROR_CODE 0x09
+#define REFUSED_ERROR_CODE 0x0d
+#define ASP_IDENTIFIER_REQUIRED_ERROR_CODE 0x0e
+#define INVALID_ASP_IDENTIFIER_ERROR_CODE 0x0f
+#define ASP_ACTIVE_FOR_INTERFACE_IDENTIFIER_ERROR_CODE 0x10
+#define INVALID_PARAMETER_VALUE_ERROR_CODE 0x11
+#define PARAMETER_FIELD_ERROR_CODE 0x12
+#define UNEXPECTED_PARAMETER_ERROR_CODE 0x13
+#define MISSING_PARAMETER_ERROR_CODE 0x16
+
+static const value_string error_code_values[] = {
+ { INVALID_VERSION_ERROR_CODE, "Invalid version" },
+ { INVALID_INTERFACE_IDENTIFIER_ERROR_CODE, "Invalid interface identifier" },
+ { UNSUPPORTED_MESSAGE_CLASS_ERROR_CODE, "Unsupported message class" },
+ { UNSUPPORTED_MESSAGE_TYPE_ERROR_CODE, "Unsupported message type" },
+ { UNSUPPORTED_TRAFFIC_HANDLING_MODE_ERROR_CODE, "Unsupported traffic handling mode" },
+ { UNEXPECTED_MESSAGE_ERROR_CODE, "Unexpected message" },
+ { PROTOCOL_ERROR_ERROR_CODE, "Protocol error" },
+ { UNSUPPORTED_INTERFACE_IDENTIFIER_TYPE_ERROR_CODE, "Unsupported interface identifier type" },
+ { INVALID_STREAM_IDENTIFIER_ERROR_CODE, "Invalid stream identifier" },
+ { REFUSED_ERROR_CODE, "Refused - management blocking" },
+ { ASP_IDENTIFIER_REQUIRED_ERROR_CODE, "ASP identifier required" },
+ { INVALID_ASP_IDENTIFIER_ERROR_CODE, "Invalid ASP identifier" },
+ { ASP_ACTIVE_FOR_INTERFACE_IDENTIFIER_ERROR_CODE, "ASP active for interface identifier" },
+ { INVALID_PARAMETER_VALUE_ERROR_CODE, "Invalid parameter value" },
+ { PARAMETER_FIELD_ERROR_CODE, "Parameter field error" },
+ { UNEXPECTED_PARAMETER_ERROR_CODE, "Unexpected parameter" },
+ { MISSING_PARAMETER_ERROR_CODE, "Missing parameter" },
+ { 0, NULL } };
+
+#define ERROR_CODE_LENGTH 4
+#define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)",
+ val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), error_code_values, "unknown"));
+}
+
+#define AS_STATE_CHANGE_TYPE 1
+#define OTHER_TYPE 2
+
+static const value_string status_type_values[] = {
+ { AS_STATE_CHANGE_TYPE, "Application server state change" },
+ { OTHER_TYPE, "Other" },
+ { 0, NULL } };
+
+#define RESERVED_INFO 1
+#define AS_INACTIVE_INFO 2
+#define AS_ACTIVE_INFO 3
+#define AS_PENDING_INFO 4
+
+#define INSUFFICIENT_ASP_RES_INFO 1
+#define ALTERNATE_ASP_ACTIVE_INFO 2
+#define ASP_FAILURE_INFO 3
+
+static const value_string status_type_id_values[] = {
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + RESERVED_INFO, "Reserved" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_INACTIVE_INFO, "Application server inactive" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_ACTIVE_INFO, "Application server active" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_PENDING_INFO, "Application server pending" },
+ { OTHER_TYPE * 256 * 256 + INSUFFICIENT_ASP_RES_INFO, "Insufficient ASP resources active in AS" },
+ { OTHER_TYPE * 256 * 256 + ALTERNATE_ASP_ACTIVE_INFO, "Alternate ASP active" },
+ { OTHER_TYPE * 256 * 256 + ASP_FAILURE_INFO, "ASP Failure" },
+ {0, NULL } };
+
+#define STATUS_TYPE_LENGTH 2
+#define STATUS_IDENT_LENGTH 2
+
+#define STATUS_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+#define STATUS_IDENT_OFFSET (STATUS_TYPE_OFFSET + STATUS_TYPE_LENGTH)
+
+static void
+dissect_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 status_type, status_id;
+
+ status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
+ status_id = tvb_get_ntohs(parameter_tvb, STATUS_IDENT_OFFSET);
+
+ proto_tree_add_item(parameter_tree, hf_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(parameter_tree, hf_status_ident, parameter_tvb, STATUS_IDENT_OFFSET, STATUS_IDENT_LENGTH,
+ status_id, "Status identification: %u (%s)", status_id,
+ val_to_str(status_type * 256 * 256 + status_id, status_type_id_values, "unknown"));
+
+ proto_item_append_text(parameter_item, " (%s)",
+ val_to_str(status_type * 256 * 256 + status_id, status_type_id_values, "unknown status information"));
+}
+
+#define ASP_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+#define ASP_IDENTIFIER_LENGTH 4
+
+static void
+dissect_asp_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_asp_id, parameter_tvb, ASP_IDENTIFIER_OFFSET, ASP_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, ASP_IDENTIFIER_OFFSET));
+}
+
+#define CORRELATION_ID_LENGTH 4
+#define CORRELATION_ID_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_correlation_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
+}
+
+#define DATA_1_MTP3_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_protocol_data_1_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_item *parameter_item)
+{
+ tvbuff_t *payload_tvb;
+ guint32 payload_length;
+
+ payload_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+
+ payload_tvb = tvb_new_subset(parameter_tvb, DATA_1_MTP3_OFFSET, payload_length, payload_length);
+ proto_item_set_len(parameter_item, PARAMETER_HEADER_LENGTH);
+ call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
+
+ proto_item_set_text(parameter_item, "Data 1 parameter");
+}
+
+#define DATA_2_LI_LENGTH 1
+#define DATA_2_LI_OFFSET PARAMETER_VALUE_OFFSET
+#define DATA_2_MTP3_OFFSET (DATA_2_LI_OFFSET + DATA_2_LI_LENGTH)
+
+static void
+dissect_protocol_data_2_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ tvbuff_t *payload_tvb;
+ guint32 payload_length;
+
+ payload_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - DATA_2_LI_LENGTH;
+
+ proto_tree_add_item(parameter_tree, hf_data_2_li, parameter_tvb, DATA_2_LI_OFFSET, DATA_2_LI_LENGTH, NETWORK_BYTE_ORDER);
+ payload_tvb = tvb_new_subset(parameter_tvb, DATA_2_MTP3_OFFSET, payload_length, payload_length);
+ proto_item_set_len(parameter_item, PARAMETER_HEADER_LENGTH + DATA_2_LI_LENGTH);
+ call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
+}
+
+
+#define STATUS_LPO_SET 0x0
+#define STATUS_LPO_CLEAR 0x1
+#define STATUS_EMER_SET 0x2
+#define STATUS_EMER_CLEAR 0x3
+#define STATUS_FLUSH_BUFFERS 0x4
+#define STATUS_CONTINUE 0x5
+#define STATUS_CLEAR_RTB 0x6
+#define STATUS_AUDIT 0x7
+#define STATUS_CONG_CLEAR 0x8
+#define STATUS_CONG_ACCEPT 0x9
+#define STATUS_CONG_DISCARD 0xa
+
+static const value_string state_values[] = {
+ { STATUS_LPO_SET, "Request local processor outage" },
+ { STATUS_LPO_CLEAR, "Request local processor outage recovered" },
+ { STATUS_EMER_SET, "Request emergency alignment" },
+ { STATUS_EMER_CLEAR, "Request normal alignment (cancel emergency)" },
+ { STATUS_FLUSH_BUFFERS, "Flush or clear receive, transmit and retransmit queues" },
+ { STATUS_CONTINUE, "Continue or Resume" },
+ { STATUS_CLEAR_RTB, "Clear the retransmit queue" },
+ { STATUS_AUDIT, "Audit state of link" },
+ { STATUS_CONG_CLEAR, "Congestion cleared" },
+ { STATUS_CONG_ACCEPT, "Congestion accept" },
+ { STATUS_CONG_DISCARD, "Congestion discard" },
+ {0, NULL } };
+
+#define STATE_LENGTH 4
+#define STATE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_state_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_state, parameter_tvb, STATE_OFFSET, STATE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, STATE_OFFSET), state_values, "unknown"));
+}
+
+#define EVENT_RPO_ENTER 0x1
+#define EVENT_RPO_EXIT 0x2
+#define EVENT_LPO_ENTER 0x3
+#define EVENT_LPO_EXIT 0x4
+
+static const value_string event_values[] = {
+ { EVENT_RPO_ENTER, "Remote entered processor outage" },
+ { EVENT_RPO_EXIT, "Remote exited processor outage" },
+ { EVENT_LPO_ENTER, "Link entered processor outage" },
+ { EVENT_LPO_EXIT, "Link exited processor outage" },
+ {0, NULL } };
+
+#define EVENT_LENGTH 4
+#define EVENT_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_state_event_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_event, parameter_tvb, EVENT_OFFSET, EVENT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, STATE_OFFSET), event_values, "unknown"));
+}
+
+#define LEVEL_NONE 0x0
+#define LEVEL_1 0x1
+#define LEVEL_2 0x2
+#define LEVEL_3 0x3
+
+static const value_string level_values[] = {
+ { LEVEL_NONE, "No congestion" },
+ { LEVEL_1, "Congestion Level 1" },
+ { LEVEL_2, "Congestion Level 2" },
+ { LEVEL_3, "Congestion Level 3" },
+ {0, NULL } };
+
+#define CONGESTION_STATUS_LENGTH 4
+#define CONGESTION_STATUS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_congestion_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_congestion_status, parameter_tvb, CONGESTION_STATUS_OFFSET, CONGESTION_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, CONGESTION_STATUS_OFFSET), level_values, "unknown"));
+}
+
+#define DISCARD_STATUS_LENGTH 4
+#define DISCARD_STATUS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_discard_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_discard_status, parameter_tvb, DISCARD_STATUS_OFFSET, DISCARD_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, DISCARD_STATUS_OFFSET), level_values, "unknown"));
+}
+
+#define ACTION_RTRV_BSN 0x1
+#define ACTION_RTRV_MSGS 0x2
+
+static const value_string action_values[] = {
+ { ACTION_RTRV_BSN, "Retrieve the backward sequence number" },
+ { ACTION_RTRV_MSGS, "Retrieve the PDUs from the transmit and retransmit queues" },
+ {0, NULL } };
+
+
+#define ACTION_LENGTH 4
+#define ACTION_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_action_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_uint(parameter_tree, hf_action, parameter_tvb, ACTION_OFFSET, ACTION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ACTION_OFFSET), action_values, "unknown"));
+}
+
+#define SEQUENCE_NUMBER_LENGTH 4
+#define SEQUENCE_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_sequence_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_sequence_number, parameter_tvb, SEQUENCE_NUMBER_OFFSET, SEQUENCE_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, SEQUENCE_NUMBER_OFFSET));
+}
+
+#define RESULT_SUCCESS 0x0
+#define RESULT_FAILURE 0x1
+
+static const value_string retrieval_result_values[] = {
+ { RESULT_SUCCESS, "Action successful" },
+ { RESULT_FAILURE , "Action failed" },
+ { 0, NULL } };
+
+
+#define RETRIEVAL_RESULT_LENGTH 4
+#define RETRIEVAL_RESULT_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_retrieval_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_retrieval_result, parameter_tvb, RETRIEVAL_RESULT_OFFSET, RETRIEVAL_RESULT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, RETRIEVAL_RESULT_OFFSET), retrieval_result_values, "unknown"));
+}
+
+static void
+dissect_link_key_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+ guint16 parameters_length;
+
+ parameters_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, tree, parameter_tree);
+}
+
+#define LOCAL_LK_ID_LENGTH 4
+#define LOCAL_LK_ID_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_local_lk_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_local_lk_id, parameter_tvb, LOCAL_LK_ID_OFFSET, LOCAL_LK_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, LOCAL_LK_ID_OFFSET));
+}
+
+#define SDT_RESERVED_LENGTH 2
+#define SDT_ID_LENGTH 2
+#define SDT_RESERVED_OFFSET PARAMETER_VALUE_OFFSET
+#define SDT_ID_OFFSET (SDT_RESERVED_OFFSET + SDT_RESERVED_LENGTH)
+
+static void
+dissect_sdt_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_sdt_reserved, parameter_tvb, SDT_RESERVED_OFFSET, SDT_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_sdt_id, parameter_tvb, SDT_ID_OFFSET, SDT_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohs(parameter_tvb, SDT_ID_OFFSET));
+}
+
+#define SDL_RESERVED_LENGTH 2
+#define SDL_ID_LENGTH 2
+#define SDL_RESERVED_OFFSET PARAMETER_VALUE_OFFSET
+#define SDL_ID_OFFSET (SDL_RESERVED_OFFSET + SDL_RESERVED_LENGTH)
+
+static void
+dissect_sdl_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_sdl_reserved, parameter_tvb, SDL_RESERVED_OFFSET, SDL_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_sdl_id, parameter_tvb, SDL_ID_OFFSET, SDL_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohs(parameter_tvb, SDL_ID_OFFSET));
+}
+
+static void
+dissect_registration_result_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+ guint16 parameters_length;
+
+ parameters_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, tree, parameter_tree);
+}
+
+#define SUCCESSFULL_REGISTRATION_STATUS 0
+#define UNKNOWN_REGISTRATION_STATUS 1
+#define INVALID_SDLI_REGISTRATION_STATUS 2
+#define INVALID_SDTI_REGISTRATION_STATUS 3
+#define INVALID_LINK_KEY_REGISTRATION_STATUS 4
+#define PERMISSION_DENIED_REGISTRATION_STATUS 5
+#define OVERLAPPING_LINK_KEY_REGISTRATION_STATUS 6
+#define LINK_KEY_NOT_PROVISIONED_REGISTRATION_STATUS 7
+#define INSUFFICIENT_RESOURCES_REGISTRATION_STATUS 8
+
+static const value_string registration_status_values[] = {
+ { SUCCESSFULL_REGISTRATION_STATUS, "Successfully registered" },
+ { UNKNOWN_REGISTRATION_STATUS, "Error - Unknown" },
+ { INVALID_SDLI_REGISTRATION_STATUS, "Error - Invalid SDLI" },
+ { INVALID_SDTI_REGISTRATION_STATUS, "Error - Invalid SDTI" },
+ { INVALID_LINK_KEY_REGISTRATION_STATUS, "Error - Invalid link key" },
+ { PERMISSION_DENIED_REGISTRATION_STATUS, "Error - Permission denied" },
+ { OVERLAPPING_LINK_KEY_REGISTRATION_STATUS, "Error - Overlapping (Non-unique) link key" },
+ { LINK_KEY_NOT_PROVISIONED_REGISTRATION_STATUS, "Error - Link key not provisioned" },
+ { INSUFFICIENT_RESOURCES_REGISTRATION_STATUS, "Error - Insufficient resources" },
+ { 0, NULL } };
+
+#define REGISTRATION_STATUS_LENGTH 4
+#define REGISTRATION_STATUS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_registration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_registration_status, parameter_tvb, REGISTRATION_STATUS_OFFSET, REGISTRATION_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, REGISTRATION_STATUS_OFFSET), registration_status_values, "unknown"));
+}
+
+static void
+dissect_deregistration_result_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+ guint16 parameters_length;
+
+ parameters_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, tree, parameter_tree);
+}
+
+#define SUCCESSFULL_DEREGISTRATION_STATUS 0
+#define UNKNOWN_DEREGISTRATION_STATUS 1
+#define INVALID_INTERFACE_IDENTIFIER_DEREGISTRATION_STATUS 2
+#define PERMISSION_DENIED_DEREGISTRATION_STATUS 3
+#define NOT_REGISTRED_DEREGISTRATION_STATUS 4
+
+static const value_string deregistration_status_values[] = {
+ { SUCCESSFULL_DEREGISTRATION_STATUS, "Successfully deregistered" },
+ { UNKNOWN_DEREGISTRATION_STATUS, "Error - Unknown" },
+ { INVALID_INTERFACE_IDENTIFIER_DEREGISTRATION_STATUS, "Error - Invalid interface identifier" },
+ { PERMISSION_DENIED_DEREGISTRATION_STATUS, "Error - Permission denied" },
+ { NOT_REGISTRED_DEREGISTRATION_STATUS, "Error - Not registered" },
+ { 0, NULL } };
+
+#define DEREGISTRATION_STATUS_LENGTH 4
+#define DEREGISTRATION_STATUS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_deregistration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_deregistration_status, parameter_tvb, DEREGISTRATION_STATUS_OFFSET, DEREGISTRATION_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, DEREGISTRATION_STATUS_OFFSET), deregistration_status_values, "unknown"));
+}
+
+static void
+dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 parameter_value_length;
+
+ parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ if (parameter_value_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " with tag %u and %u byte%s value",
+ tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET), parameter_value_length, plurality(parameter_value_length, "", "s"));
+}
+
+/* Common parameter tags */
+#define INTERFACE_IDENTIFIER_INT_PARAMETER_TAG 0x0001
+#define INTERFACE_IDENTIFIER_TEXT_PARAMETER_TAG 0x0003
+#define INFO_STRING_PARAMETER_TAG 0x0004
+#define DIAGNOSTIC_INFORMATION_PARAMETER_TAG 0x0007
+#define INTERFACE_IDENTIFIER_RANGE_PARAMETER_TAG 0x0008
+#define HEARTBEAT_DATA_PARAMETER_TAG 0x0009
+#define TRAFFIC_MODE_TYPE_PARAMETER_TAG 0x000b
+#define ERROR_CODE_PARAMETER_TAG 0x000c
+#define STATUS_PARAMETER_TAG 0x000d
+#define ASP_IDENTIFIER_PARAMETER_TAG 0x0011
+#define CORRELATION_IDENTIFIER_PARAMETER_TAG 0x0013
+
+/* M2PA specific parameter tags */
+#define PROTOCOL_DATA_1_PARAMETER_TAG 0x0300
+#define PROTOCOL_DATA_2_PARAMETER_TAG 0x0301
+#define STATE_REQUEST_PARAMETER_TAG 0x0302
+#define STATE_EVENT_PARAMETER_TAG 0x0303
+#define CONGESTION_STATUS_PARAMETER_TAG 0x0304
+#define DISCARD_STATUS_PARAMETER_TAG 0x0305
+#define ACTION_PARAMETER_TAG 0x0306
+#define SEQUENCE_NUMBER_PARAMETER_TAG 0x0307
+#define RETRIEVAL_RESULT_PARAMETER_TAG 0x0308
+#define LINK_KEY_PARAMETER_TAG 0x0309
+#define LOCAL_LK_IDENTIFIER_PARAMETER_TAG 0x030a
+#define SDT_IDENTIFIER_PARAMETER_TAG 0x030b
+#define SDL_IDENTIFIER_PARAMETER_TAG 0x030c
+#define REG_RESULT_PARAMETER_TAG 0x030d
+#define REG_STATUS_PARAMETER_TAG 0x030e
+#define DEREG_RESULT_PARAMETER_TAG 0x030f
+#define DEREG_STATUS_PARAMETER_TAG 0x0310
+
+static const value_string parameter_tag_values[] = {
+ { INTERFACE_IDENTIFIER_INT_PARAMETER_TAG, "Interface identifier (integer)" },
+ { INTERFACE_IDENTIFIER_TEXT_PARAMETER_TAG, "Interface identifier (text)" },
+ { INFO_STRING_PARAMETER_TAG, "Info string" },
+ { DIAGNOSTIC_INFORMATION_PARAMETER_TAG, "Diagnostic information" },
+ { INTERFACE_IDENTIFIER_RANGE_PARAMETER_TAG, "Interface identifier (integer range)" },
+ { HEARTBEAT_DATA_PARAMETER_TAG, "Heartbeat data" },
+ { TRAFFIC_MODE_TYPE_PARAMETER_TAG, "Traffic mode type" },
+ { ERROR_CODE_PARAMETER_TAG, "Error code" },
+ { STATUS_PARAMETER_TAG, "Status type / information" },
+ { ASP_IDENTIFIER_PARAMETER_TAG, "ASP identifier" },
+ { CORRELATION_IDENTIFIER_PARAMETER_TAG, "Correlation identifier" },
+ { PROTOCOL_DATA_1_PARAMETER_TAG, "Protocol data 1" },
+ { PROTOCOL_DATA_2_PARAMETER_TAG, "Protocol data 2" },
+ { STATE_REQUEST_PARAMETER_TAG, "State request" },
+ { STATE_EVENT_PARAMETER_TAG, "State event" },
+ { CONGESTION_STATUS_PARAMETER_TAG, "Congestion state" },
+ { DISCARD_STATUS_PARAMETER_TAG, "Discard state" },
+ { ACTION_PARAMETER_TAG, "Action" },
+ { SEQUENCE_NUMBER_PARAMETER_TAG, "Sequence number" },
+ { RETRIEVAL_RESULT_PARAMETER_TAG, "Retrieval result" },
+ { LINK_KEY_PARAMETER_TAG, "Link key" },
+ { LOCAL_LK_IDENTIFIER_PARAMETER_TAG, "Local LK identifier" },
+ { SDT_IDENTIFIER_PARAMETER_TAG, "SDT identifier" },
+ { SDL_IDENTIFIER_PARAMETER_TAG, "SDL identifer" },
+ { REG_RESULT_PARAMETER_TAG, "Registration result" },
+ { REG_STATUS_PARAMETER_TAG, "Registration status" },
+ { DEREG_RESULT_PARAMETER_TAG, "Deregistration result" },
+ { DEREG_STATUS_PARAMETER_TAG, "Deregistration status" },
+ { 0, NULL } };
+
+/*
+ * Default preference for 'Protocol Data 1 Parameter Tag' is RFC3331 value
+ * defined above (PROTOCOL_DATA_1_PARAMETER_TAG)
+ *
+ * The other option is the old Draft 7 value defined below.
+ */
+#define PROTOCOL_DATA_1_DRAFT_7 0x000e
+static guint protocol_data_1_global = PROTOCOL_DATA_1_PARAMETER_TAG;
+
+static void
+dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m2ua_tree)
+{
+ guint16 tag, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+
+ /* extract tag and length from the parameter */
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+
+ /* calculate padding and total length */
+ padding_length = tvb_length(parameter_tvb) - length;
+
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(m2ua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb),
+ val_to_str(tag, parameter_tag_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_m2ua_parameter);
+
+ if ((protocol_data_1_global == PROTOCOL_DATA_1_DRAFT_7) &&
+ (tag == PROTOCOL_DATA_1_DRAFT_7))
+ {
+ proto_tree_add_uint_hidden(parameter_tree, hf_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, tag);
+
+ /* add tag and length to the m2ua tree */
+ proto_tree_add_text(parameter_tree, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH,
+ "Parameter Tag: Protocol data 1 (0x000e)");
+
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ tag = PROTOCOL_DATA_1_PARAMETER_TAG;
+ }
+ else
+ {
+ /* add tag and length to the m2ua tree */
+ proto_tree_add_item(parameter_tree, hf_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ }
+
+ switch(tag) {
+ case INTERFACE_IDENTIFIER_INT_PARAMETER_TAG:
+ dissect_interface_identifier_int_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case INTERFACE_IDENTIFIER_TEXT_PARAMETER_TAG:
+ dissect_interface_identifier_text_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case INFO_STRING_PARAMETER_TAG:
+ dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
+ dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case INTERFACE_IDENTIFIER_RANGE_PARAMETER_TAG:
+ dissect_interface_identifier_range_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case HEARTBEAT_DATA_PARAMETER_TAG:
+ dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
+ dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ERROR_CODE_PARAMETER_TAG:
+ dissect_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case STATUS_PARAMETER_TAG:
+ dissect_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ASP_IDENTIFIER_PARAMETER_TAG:
+ dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case CORRELATION_IDENTIFIER_PARAMETER_TAG:
+ dissect_correlation_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PROTOCOL_DATA_1_PARAMETER_TAG:
+ if (protocol_data_1_global == PROTOCOL_DATA_1_DRAFT_7)
+ {
+ tag = PROTOCOL_DATA_1_DRAFT_7;
+ }
+ dissect_protocol_data_1_parameter(parameter_tvb, pinfo, tree, parameter_item);
+ break;
+ case PROTOCOL_DATA_2_PARAMETER_TAG:
+ dissect_protocol_data_2_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
+ break;
+ case STATE_REQUEST_PARAMETER_TAG:
+ dissect_state_request_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case STATE_EVENT_PARAMETER_TAG:
+ dissect_state_event_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case CONGESTION_STATUS_PARAMETER_TAG:
+ dissect_congestion_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case DISCARD_STATUS_PARAMETER_TAG:
+ dissect_discard_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ACTION_PARAMETER_TAG:
+ dissect_action_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case SEQUENCE_NUMBER_PARAMETER_TAG:
+ dissect_sequence_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case RETRIEVAL_RESULT_PARAMETER_TAG:
+ dissect_retrieval_result_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case LINK_KEY_PARAMETER_TAG:
+ dissect_link_key_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case LOCAL_LK_IDENTIFIER_PARAMETER_TAG:
+ dissect_local_lk_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case SDT_IDENTIFIER_PARAMETER_TAG:
+ dissect_sdt_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case SDL_IDENTIFIER_PARAMETER_TAG:
+ dissect_sdl_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case REG_RESULT_PARAMETER_TAG:
+ dissect_registration_result_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case REG_STATUS_PARAMETER_TAG:
+ dissect_registration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case DEREG_RESULT_PARAMETER_TAG:
+ dissect_deregistration_result_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case DEREG_STATUS_PARAMETER_TAG:
+ dissect_deregistration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ default:
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ };
+
+ if (padding_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+
+static void
+dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m2ua_tree)
+{
+ gint offset, length, total_length, remaining_length;
+ tvbuff_t *parameter_tvb;
+
+ offset = 0;
+ while((remaining_length = tvb_reported_length_remaining(parameters_tvb, offset))) {
+ length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ if (remaining_length >= length)
+ total_length = MIN(total_length, remaining_length);
+ /* create a tvb for the parameter including the padding bytes */
+ parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
+ dissect_parameter(parameter_tvb, pinfo, tree, m2ua_tree);
+ /* get rid of the handled parameter */
+ offset += total_length;
+ }
+}
+
+
+static void
+dissect_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m2ua_tree)
+{
+ tvbuff_t *common_header_tvb, *parameters_tvb;
+
+ common_header_tvb = tvb_new_subset(message_tvb, 0, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
+ parameters_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_LENGTH, -1, -1);
+ dissect_common_header(common_header_tvb, pinfo, m2ua_tree);
+ dissect_parameters(parameters_tvb, pinfo, tree, m2ua_tree);
+}
+
+static void
+dissect_m2ua(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *m2ua_item;
+ proto_tree *m2ua_tree;
+
+ /* make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "M2UA");
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the m2ua protocol tree */
+ m2ua_item = proto_tree_add_item(tree, proto_m2ua, message_tvb, 0, -1, FALSE);
+ m2ua_tree = proto_item_add_subtree(m2ua_item, ett_m2ua);
+ } else {
+ m2ua_tree = NULL;
+ };
+ /* dissect the message */
+ dissect_message(message_tvb, pinfo, tree, m2ua_tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_m2ua(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_version, { "Version", "m2ua.version", FT_UINT8, BASE_DEC, VALS(protocol_version_values), 0x0, "", HFILL } },
+ { &hf_reserved, { "Reserved", "m2ua.reserved", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_message_class, { "Message class", "m2ua.message_class", FT_UINT8, BASE_DEC, VALS(message_class_values), 0x0, "", HFILL } },
+ { &hf_message_type, { "Message Type", "m2ua.message_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_message_length, { "Message length", "m2ua.message_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_tag, { "Parameter Tag", "m2ua.parameter_tag", FT_UINT16, BASE_HEX, VALS(parameter_tag_values), 0x0, "", HFILL } },
+ { &hf_parameter_length, { "Parameter length", "m2ua.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_value, { "Parameter value", "m2ua.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_padding, { "Padding", "m2ua.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_interface_id_int, { "Interface Identifier (integer)", "m2ua.interface_identifier_int", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_interface_id_text, { "Interface identifier (text)", "m2ua.interface_identifier_text", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_info_string, { "Info string", "m2ua.info_string", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_diagnostic_information, { "Diagnostic information", "m2ua.diagnostic_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_interface_id_start, { "Interface Identifier (start)", "m2ua.interface_identifier_start", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_interface_id_stop, { "Interface Identifier (stop)", "m2ua.interface_identifier_stop", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_heartbeat_data, { "Heartbeat data", "m2ua.heartbeat_data", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_traffic_mode_type, { "Traffic mode Type", "m2ua.traffic_mode_type", FT_UINT32, BASE_DEC, VALS(traffic_mode_type_values), 0x0, "", HFILL } },
+ { &hf_error_code, { "Error code", "m2ua.error_code", FT_UINT32, BASE_DEC, VALS(error_code_values), 0x0, "", HFILL } },
+ { &hf_status_type, { "Status type", "m2ua.status_type", FT_UINT16, BASE_DEC, VALS(status_type_values), 0x0, "", HFILL } },
+ { &hf_status_ident, { "Status info", "m2ua.status_info", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_asp_id, { "ASP identifier", "m2ua.asp_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_correlation_id, { "Correlation identifier", "m2ua.correlation_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_data_2_li, { "Length indicator", "m2ua.data_2_li", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_state, { "State", "m2ua.state", FT_UINT32, BASE_DEC, VALS(state_values), 0x0, "", HFILL } },
+ { &hf_event, { "Event", "m2ua.event", FT_UINT32, BASE_DEC, VALS(event_values), 0x0, "", HFILL } },
+ { &hf_congestion_status, { "Congestion status", "m2ua.congestion_status", FT_UINT32, BASE_DEC, VALS(level_values), 0x0, "", HFILL } },
+ { &hf_discard_status, { "Discard status", "m2ua.discard_status", FT_UINT32, BASE_DEC, VALS(level_values), 0x0, "", HFILL } },
+ { &hf_action, { "Actions", "m2ua.action", FT_UINT32, BASE_DEC, VALS(action_values), 0x0, "", HFILL } },
+ { &hf_sequence_number, { "Sequence number", "m2ua.sequence_number", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_retrieval_result, { "Retrieval result", "m2ua.retrieval_result", FT_UINT32, BASE_DEC, VALS(retrieval_result_values), 0x0, "", HFILL } },
+ { &hf_local_lk_id, { "Local LK identifier", "m2ua.local_lk_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_sdt_reserved, { "Reserved", "m2ua.sdt_reserved", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_sdt_id, { "SDT identifier", "m2ua.sdt_identifier", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_sdl_reserved, { "Reserved", "m2ua.sdl_reserved", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_sdl_id, { "SDL identifier", "m2ua.sdl_identifier", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_registration_status, { "Registration status", "m2ua.registration_status", FT_UINT32, BASE_DEC, VALS(registration_status_values), 0x0, "", HFILL } },
+ { &hf_deregistration_status, { "Deregistration status", "m2ua.deregistration_status", FT_UINT32, BASE_DEC, VALS(deregistration_status_values), 0x0, "", HFILL } },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_m2ua,
+ &ett_m2ua_parameter,
+ };
+
+ static enum_val_t protocol_data_1_options[] = {
+ { "draft-7", "0x000e (Draft 7)", PROTOCOL_DATA_1_DRAFT_7 },
+ { "rfc3331", "0x0300 (RFC3331)", PROTOCOL_DATA_1_PARAMETER_TAG },
+ { NULL, NULL, 0 }
+ };
+
+ module_t *m2ua_module;
+
+ /* Register the protocol name and description */
+ proto_m2ua = proto_register_protocol("MTP 2 User Adaptation Layer", "M2UA", "m2ua");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_m2ua, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ m2ua_module = prefs_register_protocol(proto_m2ua, NULL);
+
+ prefs_register_enum_preference(m2ua_module,
+ "protocol_data_1_tag",
+ "Protocol Data 1 Parameter Tag",
+ "The value of the parameter tag for protocol data 1",
+ &protocol_data_1_global,
+ protocol_data_1_options,
+ FALSE);
+}
+
+void
+proto_reg_handoff_m2ua(void)
+{
+ dissector_handle_t m2ua_handle;
+
+ mtp3_handle = find_dissector("mtp3");
+ m2ua_handle = create_dissector_handle(dissect_m2ua, proto_m2ua);
+ dissector_add("sctp.ppi", M2UA_PAYLOAD_PROTOCOL_ID, m2ua_handle);
+ dissector_add("sctp.port", SCTP_PORT_M2UA, m2ua_handle);
+}
diff --git a/epan/dissectors/packet-m3ua.c b/epan/dissectors/packet-m3ua.c
new file mode 100644
index 0000000000..407a394bc2
--- /dev/null
+++ b/epan/dissectors/packet-m3ua.c
@@ -0,0 +1,2008 @@
+/* packet-m3ua.c
+ * Routines for MTP3 User Adaptation Layer dissection
+ * It is hopefully (needs testing) compilant to
+ * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-m3ua-05.txt (expired)
+ * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-m3ua-06.txt (expired)
+ * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-m3ua-07.txt (expired)
+ * http://www.ietf.org/rfc/rfc3332.txt
+ *
+ * Copyright 2000, 2001, 2002, 2003, 2004 Michael Tuexen <tuexen [AT] fh-muenster.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include "sctpppids.h"
+#include "packet-mtp3.h"
+
+#define SCTP_PORT_M3UA 2905
+#define NETWORK_BYTE_ORDER FALSE
+#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
+
+#define VERSION_LENGTH 1
+#define RESERVED_LENGTH 1
+#define MESSAGE_CLASS_LENGTH 1
+#define MESSAGE_TYPE_LENGTH 1
+#define MESSAGE_LENGTH_LENGTH 4
+#define COMMON_HEADER_LENGTH (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
+ MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
+
+#define VERSION_OFFSET 0
+#define RESERVED_OFFSET (VERSION_OFFSET + VERSION_LENGTH)
+#define MESSAGE_CLASS_OFFSET (RESERVED_OFFSET + RESERVED_LENGTH)
+#define MESSAGE_TYPE_OFFSET (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
+#define MESSAGE_LENGTH_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
+
+#define PARAMETER_TAG_LENGTH 2
+#define PARAMETER_LENGTH_LENGTH 2
+#define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
+
+#define PARAMETER_TAG_OFFSET 0
+#define PARAMETER_LENGTH_OFFSET (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
+#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
+#define PARAMETER_HEADER_OFFSET PARAMETER_TAG_OFFSET
+
+#define PROTOCOL_VERSION_RELEASE_1 1
+
+static const value_string protocol_version_values[] = {
+ { PROTOCOL_VERSION_RELEASE_1, "Release 1" },
+ { 0, NULL } };
+
+#define MESSAGE_CLASS_MGMT_MESSAGE 0
+#define MESSAGE_CLASS_TFER_MESSAGE 1
+#define MESSAGE_CLASS_SSNM_MESSAGE 2
+#define MESSAGE_CLASS_ASPSM_MESSAGE 3
+#define MESSAGE_CLASS_ASPTM_MESSAGE 4
+#define MESSAGE_CLASS_RKM_MESSAGE 9
+
+static const value_string message_class_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE, "Management messages" },
+ { MESSAGE_CLASS_TFER_MESSAGE, "Transfer messages" },
+ { MESSAGE_CLASS_SSNM_MESSAGE, "SS7 signalling network management messages" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE, "ASP state maintenance messages" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE, "ASP traffic maintenance messages" },
+ { MESSAGE_CLASS_RKM_MESSAGE, "Routing key management messages" },
+ { 0, NULL } };
+
+static const value_string v5_message_class_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE, "Management messages" },
+ { MESSAGE_CLASS_TFER_MESSAGE, "Transfer messages" },
+ { MESSAGE_CLASS_SSNM_MESSAGE, "SS7 signalling network management messages" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE, "ASP state maintenance messages" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE, "ASP traffic maintenance messages" },
+ { 0, NULL } };
+
+#define MESSAGE_TYPE_ERR 0
+#define MESSAGE_TYPE_NTFY 1
+
+#define MESSAGE_TYPE_DATA 1
+
+#define MESSAGE_TYPE_DUNA 1
+#define MESSAGE_TYPE_DAVA 2
+#define MESSAGE_TYPE_DAUD 3
+#define MESSAGE_TYPE_SCON 4
+#define MESSAGE_TYPE_DUPU 5
+#define MESSAGE_TYPE_DRST 6
+
+#define MESSAGE_TYPE_UP 1
+#define MESSAGE_TYPE_DOWN 2
+#define MESSAGE_TYPE_BEAT 3
+#define MESSAGE_TYPE_UP_ACK 4
+#define MESSAGE_TYPE_DOWN_ACK 5
+#define MESSAGE_TYPE_BEAT_ACK 6
+
+#define MESSAGE_TYPE_ACTIVE 1
+#define MESSAGE_TYPE_INACTIVE 2
+#define MESSAGE_TYPE_ACTIVE_ACK 3
+#define MESSAGE_TYPE_INACTIVE_ACK 4
+
+#define MESSAGE_TYPE_REG_REQ 1
+#define MESSAGE_TYPE_REG_RSP 2
+#define MESSAGE_TYPE_DEREG_REQ 3
+#define MESSAGE_TYPE_DEREG_RSP 4
+
+static const value_string v5_message_class_type_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "Error (ERR)" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "Notify (NTFY)" },
+ { MESSAGE_CLASS_TFER_MESSAGE * 256 + MESSAGE_TYPE_DATA, "Payload data (DATA)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUNA, "Destination unavailable (DUNA)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAVA, "Destination available (DAVA)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAUD, "Destination state audit (DAUD)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_SCON, "SS7 Network congestion state (SCON)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUPU, "Destination userpart unavailable (DUPU)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP up (UP)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP down (DOWN)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "Heartbeat (BEAT)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP up ack (UP ACK)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP down ack (DOWN ACK)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "Heartbeat ack (BEAT ACK)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP active (ACTIVE)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP inactive (INACTIVE)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP active ack (ACTIVE ACK)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack (INACTIVE ACK)" },
+ { 0, NULL } };
+
+static const value_string message_class_type_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "Error (ERR)" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "Notify (NTFY)" },
+ { MESSAGE_CLASS_TFER_MESSAGE * 256 + MESSAGE_TYPE_DATA, "Payload data (DATA)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUNA, "Destination unavailable (DUNA)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAVA, "Destination available (DAVA)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAUD, "Destination state audit (DAUD)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_SCON, "SS7 Network congestion state (SCON)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUPU, "Destination userpart unavailable (DUPU)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DRST, "Destination Restricted (DRST)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP up (ASPUP)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP down (ASPDN)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "Heartbeat (BEAT)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP up ack (ASPUP_ACK)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP down ack (ASPDN_ACK)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "Heartbeat ack (BEAT_ACK)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP active (ASPAC)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP inactive (ASPIA)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP active ack (ASPAC_ACK)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack (ASPIA_ACK)" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_REG_REQ , "Registration request (REG_REQ)" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_REG_RSP , "Registration response (REG_RSP)" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_REQ , "Deregistration request (DEREG_REQ)" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_RSP , "Deregistration response (DEREG_RSP)" },
+ { 0, NULL } };
+
+static const value_string v5_message_class_type_acro_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "ERR" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "NTFY" },
+ { MESSAGE_CLASS_TFER_MESSAGE * 256 + MESSAGE_TYPE_DATA, "DATA" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUNA, "DUNA" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAVA, "DAVA" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAUD, "DAUD" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_SCON, "SCON" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUPU, "DUPU" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP_UP" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP_DOWN" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "BEAT" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP_UP_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP_DOWN_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "BEAT_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP_ACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP_INACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP_ACTIVE_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
+ { 0, NULL } };
+
+static const value_string message_class_type_acro_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "ERR" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "NTFY" },
+ { MESSAGE_CLASS_TFER_MESSAGE * 256 + MESSAGE_TYPE_DATA, "DATA" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUNA, "DUNA" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAVA, "DAVA" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAUD, "DAUD" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_SCON, "SCON" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUPU, "DUPU" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DRST, "DRST" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASPUP" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASPDN" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "BEAT" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASPUP_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASPDN_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "BEAT_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASPAC" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASPIA" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASPAC_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASPIA_ACK" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_REG_REQ , "REG_REQ" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_REG_RSP , "REG_RSP" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_REQ , "DEREG_REQ" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_RSP , "DEREG_RSP" },
+ { 0, NULL } };
+
+/* Initialize the protocol and registered fields */
+static int proto_m3ua = -1;
+static int hf_version = -1;
+static int hf_reserved = -1;
+static int hf_message_class = -1;
+static int hf_v5_message_class = -1;
+static int hf_message_type = -1;
+static int hf_message_length = -1;
+static int hf_v5_parameter_tag = -1;
+static int hf_v6_parameter_tag = -1;
+static int hf_v7_parameter_tag = -1;
+static int hf_parameter_tag = -1;
+static int hf_parameter_length = -1;
+static int hf_parameter_value = -1;
+static int hf_parameter_padding = -1;
+static int hf_parameter_trailer = -1;
+static int hf_network_appearance = -1;
+static int hf_info_string = -1;
+static int hf_routing_context = -1;
+static int hf_diagnostic_information = -1;
+static int hf_heartbeat_data = -1;
+static int hf_v5_error_code = -1;
+static int hf_v6_error_code = -1;
+static int hf_v7_error_code = -1;
+static int hf_error_code = -1;
+static int hf_status_type = -1;
+static int hf_status_info = -1;
+static int hf_asp_identifier = -1;
+static int hf_affected_point_code_mask = -1;
+static int hf_affected_point_code_pc = -1;
+static int hf_cause = -1;
+static int hf_user = -1;
+static int hf_reason = -1;
+static int hf_v5_traffic_mode_type = -1;
+static int hf_v6_traffic_mode_type = -1;
+static int hf_v7_traffic_mode_type = -1;
+static int hf_traffic_mode_type = -1;
+static int hf_congestion_reserved = -1;
+static int hf_congestion_level = -1;
+static int hf_concerned_dest_reserved = -1;
+static int hf_concerned_dest_pc = -1;
+static int hf_local_rk_identifier = -1;
+static int hf_dpc_mask = -1;
+static int hf_dpc_pc = -1;
+static int hf_si = -1;
+static int hf_ssn = -1;
+static int hf_opc_list_mask = -1;
+static int hf_opc_list_pc = -1;
+static int hf_cic_range_mask = -1;
+static int hf_cic_range_pc = -1;
+static int hf_cic_range_upper = -1;
+static int hf_cic_range_lower = -1;
+static int hf_protocol_data_opc = -1;
+static int hf_protocol_data_dpc = -1;
+static int hf_protocol_data_si = -1;
+static int hf_protocol_data_ni = -1;
+static int hf_protocol_data_mp = -1;
+static int hf_protocol_data_sls = -1;
+static int hf_correlation_identifier = -1;
+static int hf_registration_status = -1;
+static int hf_deregistration_status = -1;
+static int hf_registration_result_identifier = -1;
+static int hf_registration_result_status = -1;
+static int hf_registration_result_context = -1;
+static int hf_v6_deregistration_result_status = -1;
+static int hf_v6_deregistration_result_context = -1;
+static int hf_li = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_m3ua = -1;
+static gint ett_parameter = -1;
+
+static module_t *m3ua_module;
+static dissector_handle_t mtp3_handle, data_handle;
+static dissector_table_t si_dissector_table;
+
+/* stuff for supporting multiple versions */
+typedef enum {
+ M3UA_V5,
+ M3UA_V6,
+ M3UA_V7,
+ M3UA_RFC
+} Version_Type;
+
+static Version_Type version = M3UA_RFC;
+
+static void
+dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_tree *);
+
+static void
+dissect_v5_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *m3ua_tree)
+{
+ guint8 message_class, message_type;
+
+ /* Extract the common header */
+ message_class = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
+ message_type = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_class * 256 + message_type, v5_message_class_type_acro_values, "reserved"));
+
+ if (m3ua_tree) {
+ /* add the components of the common header to the protocol tree */
+ proto_tree_add_item(m3ua_tree, hf_version, common_header_tvb, VERSION_OFFSET, VERSION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m3ua_tree, hf_reserved, common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m3ua_tree, hf_v5_message_class, common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(m3ua_tree, hf_message_type, common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type,
+ "Message type: %s (%u)", val_to_str(message_class * 256 + message_type, v5_message_class_type_values, "reserved"), message_type);
+ proto_tree_add_item(m3ua_tree, hf_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ }
+}
+
+static void
+dissect_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *m3ua_tree)
+{
+ guint8 message_class, message_type;
+
+ /* Extract the common header */
+ message_class = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
+ message_type = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO,"%s ", val_to_str(message_class * 256 + message_type, message_class_type_acro_values, "reserved"));
+
+ if (m3ua_tree) {
+ /* add the components of the common header to the protocol tree */
+ proto_tree_add_item(m3ua_tree, hf_version, common_header_tvb, VERSION_OFFSET, VERSION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m3ua_tree, hf_reserved, common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(m3ua_tree, hf_message_class, common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(m3ua_tree, hf_message_type, common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type,
+ "Message type: %s (%u)", val_to_str(message_class * 256 + message_type, message_class_type_values, "reserved"), message_type);
+ proto_tree_add_item(m3ua_tree, hf_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ }
+}
+
+#define NETWORK_APPEARANCE_LENGTH 4
+#define NETWORK_APPEARANCE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_network_appearance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_network_appearance, parameter_tvb, NETWORK_APPEARANCE_OFFSET, NETWORK_APPEARANCE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, NETWORK_APPEARANCE_OFFSET));
+}
+
+#define V5_PROTOCOL_DATA_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_v5_protocol_data_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_item *parameter_item)
+{
+ guint16 length, protocol_data_length;
+ tvbuff_t *payload_tvb;
+
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ protocol_data_length = length - PARAMETER_HEADER_LENGTH;
+ payload_tvb = tvb_new_subset(parameter_tvb, V5_PROTOCOL_DATA_OFFSET, protocol_data_length, protocol_data_length);
+ proto_item_append_text(parameter_item, " (SS7 message of %u byte%s)", protocol_data_length, plurality(protocol_data_length, "", "s"));
+ proto_item_set_len(parameter_item, PARAMETER_HEADER_LENGTH);
+ call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
+}
+
+#define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_info_string_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 info_string_length;
+
+ info_string_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%.*s)", info_string_length,
+ (const char *)tvb_get_ptr(parameter_tvb, INFO_STRING_OFFSET, info_string_length));
+}
+
+#define AFFECTED_MASK_LENGTH 1
+#define AFFECTED_DPC_LENGTH 3
+#define AFFECTED_DESTINATION_LENGTH (AFFECTED_MASK_LENGTH + AFFECTED_DPC_LENGTH)
+
+#define AFFECTED_MASK_OFFSET 0
+#define AFFECTED_DPC_OFFSET 1
+
+static void
+dissect_affected_destinations_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 number_of_destinations, destination_number;
+ gint destination_offset;
+ proto_item *item;
+
+ number_of_destinations = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) >> 2;
+ destination_offset = PARAMETER_VALUE_OFFSET;
+ for(destination_number=1; destination_number <= number_of_destinations; destination_number++) {
+ proto_tree_add_item(parameter_tree, hf_affected_point_code_mask, parameter_tvb, destination_offset + AFFECTED_MASK_OFFSET, AFFECTED_MASK_LENGTH, NETWORK_BYTE_ORDER);
+ item = proto_tree_add_item(parameter_tree, hf_affected_point_code_pc, parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET, AFFECTED_DPC_LENGTH, NETWORK_BYTE_ORDER);
+ if (mtp3_pc_structured())
+ proto_item_append_text(item, " (%s)", mtp3_pc_to_str(tvb_get_ntoh24(parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET)));
+ destination_offset += AFFECTED_DESTINATION_LENGTH;
+ }
+ proto_item_append_text(parameter_item, " (%u destination%s)", number_of_destinations, plurality(number_of_destinations, "", "s"));
+}
+
+#define ROUTING_CONTEXT_LENGTH 4
+
+static void
+dissect_routing_context_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 number_of_contexts, context_number;
+ gint context_offset;
+
+ number_of_contexts = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) >> 2;
+ context_offset = PARAMETER_VALUE_OFFSET;
+ for(context_number=1; context_number <= number_of_contexts; context_number++) {
+ proto_tree_add_item(parameter_tree, hf_routing_context, parameter_tvb, context_offset, ROUTING_CONTEXT_LENGTH, NETWORK_BYTE_ORDER);
+ context_offset += ROUTING_CONTEXT_LENGTH;
+ };
+ proto_item_append_text(parameter_item, " (%u context%s)", number_of_contexts, plurality(number_of_contexts, "", "s"));
+}
+
+#define DIAGNOSTIC_INFO_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 diag_info_length;
+
+ diag_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_diagnostic_information, parameter_tvb, DIAGNOSTIC_INFO_OFFSET, diag_info_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", diag_info_length, plurality(diag_info_length, "", "s"));
+}
+
+#define HEARTBEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 heartbeat_data_length;
+
+ heartbeat_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_heartbeat_data, parameter_tvb, HEARTBEAT_DATA_OFFSET, heartbeat_data_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
+}
+
+#define UNKNOWN_UNAVAIL_CAUSE 0
+#define UNEQUIPPED_REMOTE_USER_UNAVAIL_CAUSE 1
+#define INACCESSABLE_REMOTE_USER_UNAVAIL_CAUSE 2
+
+static const value_string unavailability_cause_values[] = {
+ { UNKNOWN_UNAVAIL_CAUSE, "Unknown" },
+ { UNEQUIPPED_REMOTE_USER_UNAVAIL_CAUSE, "Unequipped remote user" },
+ { INACCESSABLE_REMOTE_USER_UNAVAIL_CAUSE, "Inaccessable remote user" },
+ {0, NULL } };
+
+#define RESERVED_0_USER_ID 0
+#define RESERVED_1_USER_ID 1
+#define RESERVED_2_USER_ID 2
+#define SCCP_USER_ID 3
+#define TUP_USER_ID 4
+#define ISUP_USER_ID 5
+#define RESERVED_6_USER_ID 6
+#define RESERVED_7_USER_ID 7
+#define RESERVED_8_USER_ID 8
+#define BROADBAND_ISUP_USER_ID 9
+#define SATELLITE_ISUP_USER_ID 10
+#define RESERVED_11_USER_ID 11
+#define AAL_2_SIGNALING_USER_ID 12
+#define BICC_USER_ID 13
+#define GATEWAY_CONTROL_PROTOCOL_USER_ID 14
+#define RESERVED_15_USER_ID 15
+
+static const value_string user_identity_values[] = {
+ { RESERVED_0_USER_ID, "Reserved" },
+ { RESERVED_1_USER_ID, "Reserved" },
+ { RESERVED_2_USER_ID, "Reserved" },
+ { SCCP_USER_ID, "SCCP" },
+ { TUP_USER_ID, "TUP" },
+ { ISUP_USER_ID, "ISUP" },
+ { RESERVED_6_USER_ID, "Reserved" },
+ { RESERVED_7_USER_ID, "Reserved" },
+ { RESERVED_8_USER_ID, "Reserved" },
+ { BROADBAND_ISUP_USER_ID, "Broadband ISUP" },
+ { SATELLITE_ISUP_USER_ID, "Satellite ISUP" },
+ { RESERVED_11_USER_ID, "Reserved" },
+ { AAL_2_SIGNALING_USER_ID,"AAL type2 Signaling"},
+ { BICC_USER_ID, "Bearer Independent Call Control (BICC)"},
+ { GATEWAY_CONTROL_PROTOCOL_USER_ID, "Gateway Control Protocol"},
+ { RESERVED_15_USER_ID, "Reserved" },
+
+ {0, NULL } };
+
+#define CAUSE_LENGTH 2
+#define USER_LENGTH 2
+
+#define CAUSE_OFFSET PARAMETER_VALUE_OFFSET
+#define USER_OFFSET (CAUSE_OFFSET + CAUSE_LENGTH)
+
+static void
+dissect_user_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_cause, parameter_tvb, CAUSE_OFFSET, CAUSE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_user, parameter_tvb, USER_OFFSET, USER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s: %s)",
+ val_to_str(tvb_get_ntohs(parameter_tvb, USER_OFFSET), user_identity_values, "Unknown user"),
+ val_to_str(tvb_get_ntohs(parameter_tvb, CAUSE_OFFSET), unavailability_cause_values, "unknown cause"));
+}
+
+#define UNSPECIFIED_REASON 0
+#define USER_UNAVAILABLE_REASON 1
+#define MANAGEMENT_BLOCKING_REASON 2
+
+static const value_string reason_values[] = {
+ { UNSPECIFIED_REASON, "Unspecified" },
+ { USER_UNAVAILABLE_REASON, "User unavailable" },
+ { MANAGEMENT_BLOCKING_REASON, "Management blocking" },
+ {0, NULL } };
+
+#define REASON_LENGTH 4
+#define REASON_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_reason_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_reason, parameter_tvb, REASON_OFFSET, REASON_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, REASON_OFFSET), reason_values, "unknown"));
+}
+
+#define TRAFFIC_MODE_TYPE_LENGTH 4
+#define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+
+static const value_string v5_traffic_mode_type_values[] = {
+ { 1, "Over-ride" },
+ { 2, "Load-share" },
+ { 3, "Over-ride (standby)" },
+ { 4, "Load-share (standby)" },
+ { 0, NULL } };
+
+static void
+dissect_v5_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_v5_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), v5_traffic_mode_type_values, "unknown"));
+}
+
+static const value_string v6_traffic_mode_type_values[] = {
+ { 1, "Over-ride" },
+ { 2, "Load-share" },
+ { 3, "Over-ride (standby)" },
+ { 4, "Load-share (standby)" },
+ { 0, NULL } };
+
+static void
+dissect_v6_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_v6_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), v6_traffic_mode_type_values, "unknown"));
+}
+
+static const value_string v7_traffic_mode_type_values[] = {
+ { 1, "Over-ride" },
+ { 2, "Load-share" },
+ { 0, NULL } };
+
+static void
+dissect_v7_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_v7_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), v7_traffic_mode_type_values, "unknown"));
+}
+
+static const value_string traffic_mode_type_values[] = {
+ { 1, "Over-ride" },
+ { 2, "Load-share" },
+ { 3, "Broadcast" },
+ { 0, NULL } };
+
+static void
+dissect_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), traffic_mode_type_values, "unknown"));
+}
+
+#define ERROR_CODE_LENGTH 4
+#define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
+
+static const value_string v5_error_code_values[] = {
+ { 1, "Invalid version" },
+ { 2, "Invalid network appearance" },
+ { 3, "Unsupported message class" },
+ { 4, "Unsupported message type" },
+ { 5, "Invalid traffic handling mode" },
+ { 6, "Unexpected message" },
+ { 7, "Protocol error" },
+ { 8, "Invalid routing context" },
+ { 0, NULL } };
+
+static void
+dissect_v5_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_v5_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), v5_error_code_values, "unknown"));
+}
+
+static const value_string v6_error_code_values[] = {
+ { 1, "Invalid version" },
+ { 2, "Invalid network appearance" },
+ { 3, "Unsupported message class" },
+ { 4, "Unsupported message type" },
+ { 5, "Invalid traffic handling mode" },
+ { 6, "Unexpected message" },
+ { 7, "Protocol error" },
+ { 8, "Invalid routing context" },
+ { 9, "Invalid stream identifier" },
+ { 10, "Invalid parameter value" },
+ { 0, NULL } };
+
+
+static void
+dissect_v6_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_v6_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), v6_error_code_values, "unknown"));
+}
+
+static const value_string v7_error_code_values[] = {
+ { 1, "Invalid version" },
+ { 2, "Invalid network appearance" },
+ { 3, "Unsupported message class" },
+ { 4, "Unsupported message type" },
+ { 5, "Invalid traffic handling mode" },
+ { 6, "Unexpected message" },
+ { 7, "Protocol error" },
+ { 8, "Invalid routing context" },
+ { 9, "Invalid stream identifier" },
+ { 10, "Invalid parameter value" },
+ { 11, "Refused - Management Blocking" },
+ { 12, "Unknown Routing Context" },
+ { 0, NULL } };
+
+
+static void
+dissect_v7_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_v7_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), v7_error_code_values, "unknown"));
+}
+
+static const value_string error_code_values[] = {
+ { 0x01, "Invalid version" },
+ { 0x03, "Unsupported message class" },
+ { 0x04, "Unsupported message type" },
+ { 0x05, "Unsupported traffic handling mode" },
+ { 0x06, "Unexpected message" },
+ { 0x07, "Protocol error" },
+ { 0x09, "Invalid stream identifier" },
+ { 0x0d, "Refused - management blocking" },
+ { 0x0e, "ASP identifier required" },
+ { 0x0f, "Invalid ASP identifier" },
+ { 0x11, "Invalid parameter value" },
+ { 0x12, "Parameter field error" },
+ { 0x13, "Unexpected parameter" },
+ { 0x14, "Destination status unknown" },
+ { 0x15, "Invalid network appearance" },
+ { 0x16, "Missing parameter" },
+ { 0x19, "Invalid routing context" },
+ { 0x1a, "No configured AS for ASP" },
+ { 0, NULL } };
+
+static void
+dissect_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), error_code_values, "unknown"));
+}
+
+#define AS_STATE_CHANGE_TYPE 1
+#define OTHER_TYPE 2
+
+static const value_string status_type_values[] = {
+ { AS_STATE_CHANGE_TYPE, "Application server state change" },
+ { OTHER_TYPE, "Other" },
+ { 0, NULL } };
+
+#define RESERVED_INFO 1
+#define AS_INACTIVE_INFO 2
+#define AS_ACTIVE_INFO 3
+#define AS_PENDING_INFO 4
+
+#define INSUFFICIENT_ASP_RES_INFO 1
+#define ALTERNATE_ASP_ACTIVE_INFO 2
+#define ASP_FAILURE_INFO 3
+
+static const value_string v567_status_type_info_values[] = {
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + RESERVED_INFO, "Reserved" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_INACTIVE_INFO, "Application server inactive" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_ACTIVE_INFO, "Application server active" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_PENDING_INFO, "Application server pending" },
+ { OTHER_TYPE * 256 * 256 + INSUFFICIENT_ASP_RES_INFO, "Insufficient ASP resources active in AS" },
+ { OTHER_TYPE * 256 * 256 + ALTERNATE_ASP_ACTIVE_INFO, "Alternate ASP active" },
+ {0, NULL } };
+
+
+#define STATUS_TYPE_LENGTH 2
+#define STATUS_INFO_LENGTH 2
+
+#define STATUS_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+#define STATUS_INFO_OFFSET (STATUS_TYPE_OFFSET + STATUS_TYPE_LENGTH)
+
+static void
+dissect_v567_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 status_type, status_info;
+
+ status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
+ status_info = tvb_get_ntohs(parameter_tvb, STATUS_INFO_OFFSET);
+
+ proto_tree_add_item(parameter_tree, hf_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(parameter_tree, hf_status_info, parameter_tvb, STATUS_INFO_OFFSET, STATUS_INFO_LENGTH, status_info,
+ "Status info: %s (%u)", val_to_str(status_type * 256 * 256 + status_info, v567_status_type_info_values, "unknown"), status_info);
+
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(status_type * 256 * 256 + status_info, v567_status_type_info_values, "unknown status information"));
+}
+
+static const value_string status_type_info_values[] = {
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + RESERVED_INFO, "Reserved" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_INACTIVE_INFO, "Application server inactive" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_ACTIVE_INFO, "Application server active" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_PENDING_INFO, "Application server pending" },
+ { OTHER_TYPE * 256 * 256 + INSUFFICIENT_ASP_RES_INFO, "Insufficient ASP resources active in AS" },
+ { OTHER_TYPE * 256 * 256 + ALTERNATE_ASP_ACTIVE_INFO, "Alternate ASP active" },
+ { OTHER_TYPE * 256 * 256 + ASP_FAILURE_INFO, "ASP Failure" },
+ {0, NULL } };
+
+static void
+dissect_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 status_type, status_info;
+
+ status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
+ status_info = tvb_get_ntohs(parameter_tvb, STATUS_INFO_OFFSET);
+
+ proto_tree_add_item(parameter_tree, hf_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(parameter_tree, hf_status_info, parameter_tvb, STATUS_INFO_OFFSET, STATUS_INFO_LENGTH, status_info,
+ "Status info: %s (%u)", val_to_str(status_type * 256 * 256 + status_info, status_type_info_values, "unknown"), status_info);
+
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(status_type * 256 * 256 + status_info, status_type_info_values, "unknown status information"));
+}
+
+static const value_string congestion_level_values[] = {
+ { 0, "No congestion or undefined" },
+ { 1, "Congestion level 1" },
+ { 2, "Congestion level 2" },
+ { 3, "Congestion level 3" },
+ { 0, NULL } };
+
+#define CONG_IND_RESERVED_LENGTH 3
+#define CONG_IND_LEVEL_LENGTH 1
+
+#define CONG_IND_RESERVED_OFFSET PARAMETER_VALUE_OFFSET
+#define CONG_IND_LEVEL_OFFSET (CONG_IND_RESERVED_OFFSET + CONG_IND_RESERVED_LENGTH)
+
+static void
+dissect_congestion_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_congestion_reserved, parameter_tvb, CONG_IND_RESERVED_OFFSET, CONG_IND_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_congestion_level, parameter_tvb, CONG_IND_LEVEL_OFFSET, CONG_IND_LEVEL_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_guint8(parameter_tvb, CONG_IND_LEVEL_OFFSET), congestion_level_values, "unknown"));
+}
+
+#define ASP_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+#define ASP_IDENTIFIER_LENGTH 4
+
+static void
+dissect_asp_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_asp_identifier, parameter_tvb, ASP_IDENTIFIER_OFFSET, ASP_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, ASP_IDENTIFIER_OFFSET));
+}
+
+#define PROTOCOL_DATA_1_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_protocol_data_1_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_item *parameter_item)
+{
+ guint16 protocol_data_length;
+ tvbuff_t *payload_tvb;
+
+ protocol_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ payload_tvb = tvb_new_subset(parameter_tvb, PROTOCOL_DATA_1_OFFSET, protocol_data_length, protocol_data_length);
+ proto_item_append_text(parameter_item, " (SS7 message of %u byte%s)", protocol_data_length, plurality(protocol_data_length, "", "s"));
+ proto_item_set_len(parameter_item, PARAMETER_HEADER_LENGTH);
+ call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
+}
+
+#define LI_OCTETT_LENGTH 1
+#define LI_OCTETT_OFFSET PARAMETER_VALUE_OFFSET
+#define PROTOCOL_DATA_2_OFFSET (PARAMETER_VALUE_OFFSET + LI_OCTETT_LENGTH)
+
+static void
+dissect_protocol_data_2_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint8 li;
+ guint16 protocol_data_length;
+ tvbuff_t *payload_tvb;
+
+ li = tvb_get_guint8(parameter_tvb, LI_OCTETT_OFFSET);
+ protocol_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - LI_OCTETT_LENGTH;
+ payload_tvb = tvb_new_subset(parameter_tvb, PROTOCOL_DATA_2_OFFSET, protocol_data_length, protocol_data_length);
+ proto_tree_add_item(parameter_tree, hf_li, parameter_tvb, LI_OCTETT_OFFSET, LI_OCTETT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (SS7 message of %u byte%s)", protocol_data_length, plurality(protocol_data_length, "", "s"));
+ proto_item_set_len(parameter_item, PARAMETER_HEADER_LENGTH + LI_OCTETT_LENGTH);
+ call_dissector(mtp3_handle, payload_tvb, pinfo, tree);
+}
+
+
+
+#define CON_DEST_RESERVED_LENGTH 1
+#define CON_DEST_PC_LENGTH 3
+
+#define CON_DEST_RESERVED_OFFSET PARAMETER_VALUE_OFFSET
+#define CON_DEST_PC_OFFSET (CON_DEST_RESERVED_OFFSET + CON_DEST_RESERVED_LENGTH)
+
+static void
+dissect_concerned_destination_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *item;
+
+ proto_tree_add_item(parameter_tree, hf_concerned_dest_reserved, parameter_tvb, CON_DEST_RESERVED_OFFSET, CON_DEST_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ item = proto_tree_add_item(parameter_tree, hf_concerned_dest_pc, parameter_tvb, CON_DEST_PC_OFFSET, CON_DEST_PC_LENGTH, NETWORK_BYTE_ORDER);
+ if (mtp3_pc_structured())
+ proto_item_append_text(item, " (%s)", mtp3_pc_to_str(tvb_get_ntoh24(parameter_tvb, CON_DEST_PC_OFFSET)));
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntoh24(parameter_tvb, CON_DEST_PC_OFFSET));
+}
+
+static void
+dissect_routing_key_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+ guint16 length, parameters_length;
+
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ parameters_length = length - PARAMETER_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, tree, parameter_tree);
+}
+
+static const value_string registration_result_status_values[] = {
+ { 0, "Successfully Registered" } ,
+ { 1, "Error - Unknown" } ,
+ { 2, "Error - Invalid DPC" } ,
+ { 3, "Error - Invalid Network Appearance" } ,
+ { 4, "Error - Invalid Routing Key" } ,
+ { 5, "Error - Permission Denied" } ,
+ { 6, "Error - Overlapping (Non-unique) Routing Key" } ,
+ { 7, "Error - Routing Key not Provisioned" } ,
+ { 8, "Error - Insufficient Resources" } ,
+ { 0, NULL } };
+
+#define REG_RES_IDENTIFIER_LENGTH 4
+#define REG_RES_STATUS_LENGTH 4
+#define REG_RES_CONTEXT_LENGTH 4
+
+#define REG_RES_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+#define REG_RES_STATUS_OFFSET (REG_RES_IDENTIFIER_OFFSET + REG_RES_IDENTIFIER_LENGTH)
+#define REG_RES_CONTEXT_OFFSET (REG_RES_STATUS_OFFSET + REG_RES_STATUS_LENGTH)
+
+static void
+dissect_v67_registration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_tree_add_item(parameter_tree, hf_registration_result_identifier, parameter_tvb, REG_RES_IDENTIFIER_OFFSET, REG_RES_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_registration_result_status, parameter_tvb, REG_RES_STATUS_OFFSET, REG_RES_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_registration_result_context, parameter_tvb, REG_RES_CONTEXT_OFFSET, REG_RES_CONTEXT_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_registration_result_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+ guint16 length, parameters_length;
+
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ parameters_length = length - PARAMETER_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, tree, parameter_tree);
+}
+
+static const value_string v6_deregistration_result_status_values[] = {
+ { 0, "Successfully De-registered" } ,
+ { 1, "Error - Unknown" } ,
+ { 2, "Error - Invalid Routing context" } ,
+ { 3, "Error - Permission Denied" } ,
+ { 4, "Error - Not registered" } ,
+ { 0, NULL } };
+
+#define DEREG_RES_CONTEXT_LENGTH 4
+#define DEREG_RES_STATUS_LENGTH 4
+
+#define DEREG_RES_CONTEXT_OFFSET PARAMETER_VALUE_OFFSET
+#define DEREG_RES_STATUS_OFFSET (DEREG_RES_CONTEXT_OFFSET + DEREG_RES_CONTEXT_LENGTH)
+
+static void
+dissect_v67_deregistration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_tree_add_item(parameter_tree, hf_v6_deregistration_result_context, parameter_tvb, DEREG_RES_CONTEXT_OFFSET, DEREG_RES_CONTEXT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_v6_deregistration_result_status, parameter_tvb, DEREG_RES_STATUS_OFFSET, DEREG_RES_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_deregistration_result_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+ guint16 length, parameters_length;
+
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ parameters_length = length - PARAMETER_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, tree, parameter_tree);
+}
+
+
+#define LOCAL_RK_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+#define LOCAL_RK_IDENTIFIER_LENGTH 4
+
+static void
+dissect_local_routing_key_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint32 id;
+
+ id = tvb_get_ntohl(parameter_tvb, LOCAL_RK_IDENTIFIER_OFFSET);
+ proto_tree_add_item(parameter_tree, hf_local_rk_identifier, parameter_tvb, LOCAL_RK_IDENTIFIER_OFFSET, LOCAL_RK_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, LOCAL_RK_IDENTIFIER_OFFSET));
+}
+
+#define DPC_MASK_LENGTH 1
+#define DPC_PC_LENGTH 3
+
+#define DPC_MASK_OFFSET PARAMETER_VALUE_OFFSET
+#define DPC_PC_OFFSET (DPC_MASK_OFFSET + DPC_MASK_LENGTH)
+
+static void
+dissect_destination_point_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_item *item;
+
+ proto_tree_add_item(parameter_tree, hf_dpc_mask, parameter_tvb, DPC_MASK_OFFSET, DPC_MASK_LENGTH, NETWORK_BYTE_ORDER);
+ item = proto_tree_add_item(parameter_tree, hf_dpc_pc, parameter_tvb, DPC_PC_OFFSET, DPC_PC_LENGTH, NETWORK_BYTE_ORDER);
+ if (mtp3_pc_structured())
+ proto_item_append_text(item, " (%s)", mtp3_pc_to_str(tvb_get_ntoh24(parameter_tvb, DPC_PC_OFFSET)));
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntoh24(parameter_tvb, DPC_PC_OFFSET));
+}
+
+#define SI_LENGTH 1
+
+static void
+dissect_service_indicators_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 length, number_of_sis, si_number;
+ gint si_offset;
+
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ number_of_sis = length - PARAMETER_HEADER_LENGTH;
+
+ si_offset = PARAMETER_VALUE_OFFSET;
+ for(si_number=1; si_number <= number_of_sis; si_number++) {
+ proto_tree_add_item(parameter_tree, hf_si, parameter_tvb, si_offset, SI_LENGTH, NETWORK_BYTE_ORDER);
+ si_offset += SI_LENGTH;
+ };
+ proto_item_append_text(parameter_item, " (%u indicator%s)", number_of_sis, plurality(number_of_sis, "", "s"));
+
+}
+#define SSN_LENGTH 1
+
+static void
+dissect_subsystem_numbers_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 length, number_of_ssns, ssn_number;
+ gint ssn_offset;
+
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ number_of_ssns = length - PARAMETER_HEADER_LENGTH;
+
+ ssn_offset = PARAMETER_VALUE_OFFSET;
+ for(ssn_number=1; ssn_number <= number_of_ssns; ssn_number++) {
+ proto_tree_add_item(parameter_tree, hf_ssn, parameter_tvb, ssn_offset, SSN_LENGTH, NETWORK_BYTE_ORDER);
+ ssn_offset += SSN_LENGTH;
+ };
+ proto_item_append_text(parameter_item, " (%u number%s)", number_of_ssns, plurality(number_of_ssns, "", "s"));
+
+}
+
+#define OPC_MASK_LENGTH 1
+#define OPC_PC_LENGTH 3
+#define OPC_LENGTH (OPC_MASK_LENGTH + OPC_PC_LENGTH)
+#define OPC_MASK_OFFSET 0
+#define OPC_PC_OFFSET (OPC_MASK_OFFSET + OPC_MASK_LENGTH)
+
+static void
+dissect_originating_point_code_list_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 length, number_of_point_codes, point_code_number;
+ gint point_code_offset;
+ proto_item *item;
+
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ number_of_point_codes = (length - PARAMETER_HEADER_LENGTH) / 4;
+
+ point_code_offset = PARAMETER_VALUE_OFFSET;
+ for(point_code_number=1; point_code_number <= number_of_point_codes; point_code_number++) {
+ proto_tree_add_item(parameter_tree, hf_opc_list_mask, parameter_tvb, point_code_offset + OPC_MASK_OFFSET, OPC_MASK_LENGTH, NETWORK_BYTE_ORDER);
+ item = proto_tree_add_item(parameter_tree, hf_opc_list_pc, parameter_tvb, point_code_offset + OPC_PC_OFFSET, OPC_PC_LENGTH, NETWORK_BYTE_ORDER);
+ if (mtp3_pc_structured())
+ proto_item_append_text(item, " (%s)", mtp3_pc_to_str(tvb_get_ntoh24(parameter_tvb, point_code_offset + OPC_PC_OFFSET)));
+ point_code_offset += OPC_LENGTH;
+ };
+ proto_item_append_text(parameter_item, " (%u point code%s)", number_of_point_codes, plurality(number_of_point_codes, "", "s"));
+}
+
+#define CIC_RANGE_MASK_LENGTH 1
+#define CIC_RANGE_PC_LENGTH 3
+#define CIC_RANGE_LOWER_LENGTH 2
+#define CIC_RANGE_UPPER_LENGTH 2
+#define CIC_RANGE_LENGTH (CIC_RANGE_MASK_LENGTH + CIC_RANGE_PC_LENGTH + CIC_RANGE_LOWER_LENGTH + CIC_RANGE_UPPER_LENGTH)
+#define CIC_RANGE_MASK_OFFSET 0
+#define CIC_RANGE_PC_OFFSET (CIC_RANGE_MASK_OFFSET + CIC_RANGE_MASK_LENGTH)
+#define CIC_RANGE_LOWER_OFFSET (CIC_RANGE_PC_OFFSET + CIC_RANGE_PC_LENGTH)
+#define CIC_RANGE_UPPER_OFFSET (CIC_RANGE_LOWER_OFFSET + CIC_RANGE_LOWER_LENGTH)
+
+static void
+dissect_circuit_range_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 length, number_of_point_codes, point_code_number;
+ gint point_code_offset;
+
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ number_of_point_codes = (length - PARAMETER_HEADER_LENGTH) / CIC_RANGE_LENGTH;
+
+ point_code_offset = PARAMETER_VALUE_OFFSET;
+ for(point_code_number = 1; point_code_number <= number_of_point_codes; point_code_number++) {
+ proto_tree_add_item(parameter_tree, hf_cic_range_mask, parameter_tvb, point_code_offset + CIC_RANGE_MASK_OFFSET, CIC_RANGE_MASK_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_cic_range_pc, parameter_tvb, point_code_offset + CIC_RANGE_PC_OFFSET, CIC_RANGE_PC_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_cic_range_lower, parameter_tvb, point_code_offset + CIC_RANGE_LOWER_OFFSET, CIC_RANGE_LOWER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_cic_range_upper, parameter_tvb, point_code_offset + CIC_RANGE_UPPER_OFFSET, CIC_RANGE_UPPER_LENGTH, NETWORK_BYTE_ORDER);
+ point_code_offset += CIC_RANGE_LENGTH;
+ };
+ proto_item_append_text(parameter_item, " (%u range%s)", number_of_point_codes, plurality(number_of_point_codes, "", "s"));
+}
+
+#define DATA_OPC_LENGTH 4
+#define DATA_DPC_LENGTH 4
+#define DATA_SI_LENGTH 1
+#define DATA_NI_LENGTH 1
+#define DATA_MP_LENGTH 1
+#define DATA_SLS_LENGTH 1
+#define DATA_HDR_LENGTH (DATA_OPC_LENGTH + DATA_DPC_LENGTH + DATA_SI_LENGTH + DATA_NI_LENGTH + DATA_MP_LENGTH + DATA_SLS_LENGTH)
+
+#define DATA_OPC_OFFSET PARAMETER_VALUE_OFFSET
+#define DATA_DPC_OFFSET (DATA_OPC_OFFSET + DATA_OPC_LENGTH)
+#define DATA_SI_OFFSET (DATA_DPC_OFFSET + DATA_DPC_LENGTH)
+#define DATA_NI_OFFSET (DATA_SI_OFFSET + DATA_SI_LENGTH)
+#define DATA_MP_OFFSET (DATA_NI_OFFSET + DATA_NI_LENGTH)
+#define DATA_SLS_OFFSET (DATA_MP_OFFSET + DATA_MP_LENGTH)
+#define DATA_ULP_OFFSET (DATA_SLS_OFFSET + DATA_SLS_LENGTH)
+
+static void
+dissect_protocol_data_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 ulp_length;
+ tvbuff_t *payload_tvb;
+ proto_item *item;
+
+ ulp_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - DATA_HDR_LENGTH;
+
+ if (parameter_tree) {
+ item = proto_tree_add_item(parameter_tree, hf_protocol_data_opc, parameter_tvb, DATA_OPC_OFFSET, DATA_OPC_LENGTH, NETWORK_BYTE_ORDER);
+ if (mtp3_pc_structured())
+ proto_item_append_text(item, " (%s)", mtp3_pc_to_str(tvb_get_ntohl(parameter_tvb, DATA_OPC_OFFSET)));
+ item = proto_tree_add_item(parameter_tree, hf_protocol_data_dpc, parameter_tvb, DATA_DPC_OFFSET, DATA_DPC_LENGTH, NETWORK_BYTE_ORDER);
+ if (mtp3_pc_structured())
+ proto_item_append_text(item, " (%s)", mtp3_pc_to_str(tvb_get_ntohl(parameter_tvb, DATA_DPC_OFFSET)));
+ proto_tree_add_item(parameter_tree, hf_protocol_data_si, parameter_tvb, DATA_SI_OFFSET, DATA_SI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_protocol_data_ni, parameter_tvb, DATA_NI_OFFSET, DATA_NI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_protocol_data_mp, parameter_tvb, DATA_MP_OFFSET, DATA_MP_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_protocol_data_sls, parameter_tvb, DATA_SLS_OFFSET, DATA_SLS_LENGTH, NETWORK_BYTE_ORDER);
+
+ proto_item_append_text(parameter_item, " (SS7 message of %u byte%s)", ulp_length, plurality(ulp_length, "", "s"));
+ proto_item_set_len(parameter_item, PARAMETER_HEADER_LENGTH + DATA_HDR_LENGTH);
+ }
+
+ payload_tvb = tvb_new_subset(parameter_tvb, DATA_ULP_OFFSET, ulp_length, ulp_length);
+ if (!dissector_try_port(si_dissector_table, tvb_get_guint8(parameter_tvb, DATA_SI_OFFSET), payload_tvb, pinfo, tree))
+ call_dissector(data_handle, payload_tvb, pinfo, tree);
+}
+
+#define CORR_ID_OFFSET PARAMETER_VALUE_OFFSET
+#define CORR_ID_LENGTH 4
+
+static void
+dissect_correlation_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_correlation_identifier, parameter_tvb, CORR_ID_OFFSET, CORR_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CORR_ID_OFFSET));
+}
+
+#define REG_STATUS_LENGTH 4
+#define REG_STATUS_OFFSET PARAMETER_VALUE_OFFSET
+
+static const value_string registration_status_values[] = {
+ { 0, "Successfully Registered" },
+ { 1, "Error - Unknown" },
+ { 2, "Error - Invalid DPC" },
+ { 3, "Error - Invalid Network Appearance" },
+ { 4, "Error - Invalid Routing Key" },
+ { 5, "Error - Permission Denied" },
+ { 6, "Error - Cannot Support Unique Routing" },
+ { 7, "Error - Routing Key not Currently Provisioned" },
+ { 8, "Error - Insufficient Resources" },
+ { 9, "Error - Unsupported RK parameter Field" },
+ { 10, "Error - Unsupported/Invalid Traffic Handling Mode" },
+ { 0, NULL } };
+
+static void
+dissect_registration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_registration_status, parameter_tvb, REG_STATUS_OFFSET, REG_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, REG_STATUS_OFFSET), registration_status_values, "unknown"));
+}
+
+#define DEREG_STATUS_LENGTH 4
+#define DEREG_STATUS_OFFSET PARAMETER_VALUE_OFFSET
+
+static const value_string deregistration_status_values[] = {
+ { 0, "Successfully Deregistered" },
+ { 1, "Error - Unknown" },
+ { 2, "Error - Invalid Routing Context" },
+ { 3, "Error - Permission Denied" },
+ { 4, "Error - Not Registered" },
+ { 5, "Error - ASP Currently Active for Routing Context" },
+ { 0, NULL } };
+
+static void
+dissect_deregistration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_deregistration_status, parameter_tvb, DEREG_STATUS_OFFSET, DEREG_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, DEREG_STATUS_OFFSET), deregistration_status_values, "unknown"));
+}
+
+static void
+dissect_registration_results_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+ guint16 parameters_length;
+
+ parameters_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, tree, parameter_tree);
+}
+
+static void
+dissect_deregistration_results_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+ guint16 parameters_length;
+
+ parameters_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, tree, parameter_tree);
+}
+
+static void
+dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 tag, parameter_value_length;
+
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (tag %u and %u byte%s value)", tag, parameter_value_length, plurality(parameter_value_length, "", "s"));
+}
+
+#define V5_NETWORK_APPEARANCE_PARAMETER_TAG 1
+#define V5_PROTOCOL_DATA_PARAMETER_TAG 3
+#define V5_INFO_PARAMETER_TAG 4
+#define V5_AFFECTED_DESTINATIONS_PARAMETER_TAG 5
+#define V5_ROUTING_CONTEXT_PARAMETER_TAG 6
+#define V5_DIAGNOSTIC_INFORMATION_PARAMETER_TAG 7
+#define V5_HEARTBEAT_DATA_PARAMETER_TAG 8
+#define V5_USER_CAUSE_PARAMETER_TAG 9
+#define V5_REASON_PARAMETER_TAG 10
+#define V5_TRAFFIC_MODE_TYPE_PARAMETER_TAG 11
+#define V5_ERROR_CODE_PARAMETER_TAG 12
+#define V5_STATUS_PARAMETER_TAG 13
+#define V5_CONGESTION_INDICATION_PARAMETER_TAG 14
+
+static const value_string v5_parameter_tag_values[] = {
+ { V5_NETWORK_APPEARANCE_PARAMETER_TAG, "Network appearance" },
+ { V5_PROTOCOL_DATA_PARAMETER_TAG, "Protocol data" },
+ { V5_INFO_PARAMETER_TAG, "Info" },
+ { V5_AFFECTED_DESTINATIONS_PARAMETER_TAG, "Affected destinations" },
+ { V5_ROUTING_CONTEXT_PARAMETER_TAG, "Routing context" },
+ { V5_DIAGNOSTIC_INFORMATION_PARAMETER_TAG, "Diagnostic information" },
+ { V5_HEARTBEAT_DATA_PARAMETER_TAG, "Heartbeat data" },
+ { V5_USER_CAUSE_PARAMETER_TAG, "User / Cause" },
+ { V5_REASON_PARAMETER_TAG, "Reason" },
+ { V5_TRAFFIC_MODE_TYPE_PARAMETER_TAG, "Traffic mode type" },
+ { V5_ERROR_CODE_PARAMETER_TAG, "Error code" },
+ { V5_STATUS_PARAMETER_TAG, "Status" },
+ { V5_CONGESTION_INDICATION_PARAMETER_TAG, "Congestion indication" },
+ { 0, NULL } };
+
+static void
+dissect_v5_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
+{
+ guint16 tag, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+
+ /* extract tag and length from the parameter */
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = tvb_length(parameter_tvb) - length;
+
+ if (!tree && tag != V5_PROTOCOL_DATA_PARAMETER_TAG)
+ return; /* Nothing to do here */
+
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(m3ua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), val_to_str(tag, v5_parameter_tag_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_parameter);
+
+ /* add tag and length to the parameter tree */
+ proto_tree_add_item(parameter_tree, hf_v5_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(tag) {
+ case V5_NETWORK_APPEARANCE_PARAMETER_TAG:
+ dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_PROTOCOL_DATA_PARAMETER_TAG:
+ dissect_v5_protocol_data_parameter(parameter_tvb, pinfo, tree, parameter_item);
+ break;
+ case V5_INFO_PARAMETER_TAG:
+ dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_AFFECTED_DESTINATIONS_PARAMETER_TAG:
+ dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_ROUTING_CONTEXT_PARAMETER_TAG:
+ dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
+ dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_HEARTBEAT_DATA_PARAMETER_TAG:
+ dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_USER_CAUSE_PARAMETER_TAG:
+ dissect_user_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_REASON_PARAMETER_TAG:
+ dissect_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_TRAFFIC_MODE_TYPE_PARAMETER_TAG:
+ dissect_v5_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_ERROR_CODE_PARAMETER_TAG:
+ dissect_v5_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_STATUS_PARAMETER_TAG:
+ dissect_v567_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V5_CONGESTION_INDICATION_PARAMETER_TAG:
+ dissect_congestion_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ default:
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ };
+ if (padding_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+#define V6_NETWORK_APPEARANCE_PARAMETER_TAG 1
+#define V6_PROTOCOL_DATA_1_PARAMETER_TAG 2
+#define V6_PROTOCOL_DATA_2_PARAMETER_TAG 3
+#define V6_INFO_PARAMETER_TAG 4
+#define V6_AFFECTED_DESTINATIONS_PARAMETER_TAG 5
+#define V6_ROUTING_CONTEXT_PARAMETER_TAG 6
+#define V6_DIAGNOSTIC_INFORMATION_PARAMETER_TAG 7
+#define V6_HEARTBEAT_DATA_PARAMETER_TAG 8
+#define V6_USER_CAUSE_PARAMETER_TAG 9
+#define V6_REASON_PARAMETER_TAG 10
+#define V6_TRAFFIC_MODE_TYPE_PARAMETER_TAG 11
+#define V6_ERROR_CODE_PARAMETER_TAG 12
+#define V6_STATUS_PARAMETER_TAG 13
+#define V6_CONGESTION_INDICATION_PARAMETER_TAG 14
+#define V6_CONCERNED_DESTINATION_PARAMETER_TAG 15
+#define V6_ROUTING_KEY_PARAMETER_TAG 16
+#define V6_REGISTRATION_RESULT_PARAMETER_TAG 17
+#define V6_DEREGISTRATION_RESULT_PARAMETER_TAG 18
+#define V6_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG 19
+#define V6_DESTINATION_POINT_CODE_PARAMETER_TAG 20
+#define V6_SERVICE_INDICATORS_PARAMETER_TAG 21
+#define V6_SUBSYSTEM_NUMBERS_PARAMETER_TAG 22
+#define V6_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG 23
+#define V6_CIRCUIT_RANGE_PARAMETER_TAG 24
+#define V6_REGISTRATION_RESULTS_PARAMETER_TAG 25
+#define V6_DEREGISTRATION_RESULTS_PARAMETER_TAG 26
+
+static const value_string v6_parameter_tag_values[] = {
+ { V6_NETWORK_APPEARANCE_PARAMETER_TAG, "Network appearance" },
+ { V6_PROTOCOL_DATA_1_PARAMETER_TAG, "Protocol data 1" },
+ { V6_PROTOCOL_DATA_2_PARAMETER_TAG, "Protocol data 2" },
+ { V6_INFO_PARAMETER_TAG, "Info" },
+ { V6_AFFECTED_DESTINATIONS_PARAMETER_TAG, "Affected destinations" },
+ { V6_ROUTING_CONTEXT_PARAMETER_TAG, "Routing context" },
+ { V6_DIAGNOSTIC_INFORMATION_PARAMETER_TAG, "Diagnostic information" },
+ { V6_HEARTBEAT_DATA_PARAMETER_TAG, "Heartbeat data" },
+ { V6_USER_CAUSE_PARAMETER_TAG, "User / Cause" },
+ { V6_REASON_PARAMETER_TAG, "Reason" },
+ { V6_TRAFFIC_MODE_TYPE_PARAMETER_TAG, "Traffic mode type" },
+ { V6_ERROR_CODE_PARAMETER_TAG, "Error code" },
+ { V6_STATUS_PARAMETER_TAG, "Status" },
+ { V6_CONGESTION_INDICATION_PARAMETER_TAG, "Congestion indication" },
+ { V6_CONCERNED_DESTINATION_PARAMETER_TAG, "Concerned destination" },
+ { V6_ROUTING_KEY_PARAMETER_TAG, "Routing Key" },
+ { V6_REGISTRATION_RESULT_PARAMETER_TAG, "Registration result" },
+ { V6_DEREGISTRATION_RESULT_PARAMETER_TAG, "De-registration result" },
+ { V6_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG, "Local routing key identifier" },
+ { V6_DESTINATION_POINT_CODE_PARAMETER_TAG, "Destination point code" },
+ { V6_SERVICE_INDICATORS_PARAMETER_TAG, "Service indicators" },
+ { V6_SUBSYSTEM_NUMBERS_PARAMETER_TAG, "Subsystem numbers" },
+ { V6_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG, "Originating point code list" },
+ { V6_CIRCUIT_RANGE_PARAMETER_TAG, "Circuit range" },
+ { V6_REGISTRATION_RESULTS_PARAMETER_TAG, "Registration results" },
+ { V6_DEREGISTRATION_RESULTS_PARAMETER_TAG, "De-registration results" },
+ { 0, NULL } };
+
+static void
+dissect_v6_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
+{
+ guint16 tag, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+
+ /* extract tag and length from the parameter */
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = tvb_length(parameter_tvb) - length;
+
+ if (!tree && tag != V6_PROTOCOL_DATA_1_PARAMETER_TAG && tag != V6_PROTOCOL_DATA_2_PARAMETER_TAG)
+ return; /* Nothing to do here */
+
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(m3ua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), val_to_str(tag, v6_parameter_tag_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_parameter);
+
+ /* add tag and length to the parameter tree */
+ proto_tree_add_item(parameter_tree, hf_v6_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(tag) {
+ case V6_NETWORK_APPEARANCE_PARAMETER_TAG:
+ dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_PROTOCOL_DATA_1_PARAMETER_TAG:
+ dissect_protocol_data_1_parameter(parameter_tvb, pinfo, tree, parameter_item);
+ break;
+ case V6_PROTOCOL_DATA_2_PARAMETER_TAG:
+ dissect_protocol_data_2_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
+ break;
+ case V6_INFO_PARAMETER_TAG:
+ dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_AFFECTED_DESTINATIONS_PARAMETER_TAG:
+ dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_ROUTING_CONTEXT_PARAMETER_TAG:
+ dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
+ dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_HEARTBEAT_DATA_PARAMETER_TAG:
+ dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_USER_CAUSE_PARAMETER_TAG:
+ dissect_user_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_REASON_PARAMETER_TAG:
+ dissect_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_TRAFFIC_MODE_TYPE_PARAMETER_TAG:
+ dissect_v6_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_ERROR_CODE_PARAMETER_TAG:
+ dissect_v6_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_STATUS_PARAMETER_TAG:
+ dissect_v567_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_CONGESTION_INDICATION_PARAMETER_TAG:
+ dissect_congestion_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_CONCERNED_DESTINATION_PARAMETER_TAG:
+ dissect_concerned_destination_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_ROUTING_KEY_PARAMETER_TAG:
+ dissect_routing_key_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case V6_REGISTRATION_RESULT_PARAMETER_TAG:
+ dissect_v67_registration_result_parameter(parameter_tvb, parameter_tree);
+ break;
+ case V6_DEREGISTRATION_RESULT_PARAMETER_TAG:
+ dissect_v67_deregistration_result_parameter(parameter_tvb, parameter_tree);
+ break;
+ case V6_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG:
+ dissect_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_DESTINATION_POINT_CODE_PARAMETER_TAG:
+ dissect_destination_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_SERVICE_INDICATORS_PARAMETER_TAG:
+ dissect_service_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_SUBSYSTEM_NUMBERS_PARAMETER_TAG:
+ dissect_subsystem_numbers_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG:
+ dissect_originating_point_code_list_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_CIRCUIT_RANGE_PARAMETER_TAG:
+ dissect_circuit_range_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V6_REGISTRATION_RESULTS_PARAMETER_TAG:
+ dissect_registration_results_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case V6_DEREGISTRATION_RESULTS_PARAMETER_TAG:
+ dissect_deregistration_results_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ default:
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ };
+
+ if (padding_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+#define V7_NETWORK_APPEARANCE_PARAMETER_TAG 0x80
+#define V7_PROTOCOL_DATA_1_PARAMETER_TAG 0x81
+#define V7_PROTOCOL_DATA_2_PARAMETER_TAG 0x82
+#define V7_INFO_PARAMETER_TAG 0x04
+#define V7_AFFECTED_DESTINATIONS_PARAMETER_TAG 0x83
+#define V7_ROUTING_CONTEXT_PARAMETER_TAG 0x06
+#define V7_DIAGNOSTIC_INFORMATION_PARAMETER_TAG 0x07
+#define V7_HEARTBEAT_DATA_PARAMETER_TAG 0x09
+#define V7_USER_CAUSE_PARAMETER_TAG 0x84
+#define V7_REASON_PARAMETER_TAG 0x0a
+#define V7_TRAFFIC_MODE_TYPE_PARAMETER_TAG 0x0b
+#define V7_ERROR_CODE_PARAMETER_TAG 0x0c
+#define V7_STATUS_PARAMETER_TAG 0x0d
+#define V7_CONGESTION_INDICATION_PARAMETER_TAG 0x85
+#define V7_CONCERNED_DESTINATION_PARAMETER_TAG 0x86
+#define V7_ROUTING_KEY_PARAMETER_TAG 0x87
+#define V7_REGISTRATION_RESULT_PARAMETER_TAG 0x88
+#define V7_DEREGISTRATION_RESULT_PARAMETER_TAG 0x89
+#define V7_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG 0x8a
+#define V7_DESTINATION_POINT_CODE_PARAMETER_TAG 0x8b
+#define V7_SERVICE_INDICATORS_PARAMETER_TAG 0x8c
+#define V7_SUBSYSTEM_NUMBERS_PARAMETER_TAG 0x8d
+#define V7_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG 0x8e
+#define V7_CIRCUIT_RANGE_PARAMETER_TAG 0x8f
+#define V7_REGISTRATION_RESULTS_PARAMETER_TAG 0x90
+#define V7_DEREGISTRATION_RESULTS_PARAMETER_TAG 0x91
+
+static const value_string v7_parameter_tag_values[] = {
+ { V7_NETWORK_APPEARANCE_PARAMETER_TAG, "Network appearance" },
+ { V7_PROTOCOL_DATA_1_PARAMETER_TAG, "Protocol data 1" },
+ { V7_PROTOCOL_DATA_2_PARAMETER_TAG, "Protocol data 2" },
+ { V7_INFO_PARAMETER_TAG, "Info" },
+ { V7_AFFECTED_DESTINATIONS_PARAMETER_TAG, "Affected destinations" },
+ { V7_ROUTING_CONTEXT_PARAMETER_TAG, "Routing context" },
+ { V7_DIAGNOSTIC_INFORMATION_PARAMETER_TAG, "Diagnostic information" },
+ { V7_HEARTBEAT_DATA_PARAMETER_TAG, "Heartbeat data" },
+ { V7_USER_CAUSE_PARAMETER_TAG, "User / Cause" },
+ { V7_REASON_PARAMETER_TAG, "Reason" },
+ { V7_TRAFFIC_MODE_TYPE_PARAMETER_TAG, "Traffic mode type" },
+ { V7_ERROR_CODE_PARAMETER_TAG, "Error code" },
+ { V7_STATUS_PARAMETER_TAG, "Status" },
+ { V7_CONGESTION_INDICATION_PARAMETER_TAG, "Congestion indication" },
+ { V7_CONCERNED_DESTINATION_PARAMETER_TAG, "Concerned destination" },
+ { V7_ROUTING_KEY_PARAMETER_TAG, "Routing Key" },
+ { V7_REGISTRATION_RESULT_PARAMETER_TAG, "Registration result" },
+ { V7_DEREGISTRATION_RESULT_PARAMETER_TAG, "De-registration result" },
+ { V7_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG, "Local routing key identifier" },
+ { V7_DESTINATION_POINT_CODE_PARAMETER_TAG, "Destination point code" },
+ { V7_SERVICE_INDICATORS_PARAMETER_TAG, "Service indicators" },
+ { V7_SUBSYSTEM_NUMBERS_PARAMETER_TAG, "Subsystem numbers" },
+ { V7_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG, "Originating point code list" },
+ { V7_CIRCUIT_RANGE_PARAMETER_TAG, "Circuit range" },
+ { V7_REGISTRATION_RESULTS_PARAMETER_TAG, "Registration results" },
+ { V7_DEREGISTRATION_RESULTS_PARAMETER_TAG, "De-registration results" },
+ { 0, NULL } };
+
+static void
+dissect_v7_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
+{
+ guint16 tag, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+
+ /* extract tag and length from the parameter */
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = tvb_length(parameter_tvb) - length;
+
+ if (!tree && tag != V7_PROTOCOL_DATA_1_PARAMETER_TAG && tag != V7_PROTOCOL_DATA_2_PARAMETER_TAG)
+ return; /* Nothing to do here */
+
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(m3ua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), val_to_str(tag, v7_parameter_tag_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_parameter);
+
+ /* add tag and length to the parameter tree */
+ proto_tree_add_item(parameter_tree, hf_v7_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(tag) {
+ case V7_NETWORK_APPEARANCE_PARAMETER_TAG:
+ dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_PROTOCOL_DATA_1_PARAMETER_TAG:
+ dissect_protocol_data_1_parameter(parameter_tvb, pinfo, tree, parameter_item);
+ break;
+ case V7_PROTOCOL_DATA_2_PARAMETER_TAG:
+ dissect_protocol_data_2_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
+ break;
+ case V7_INFO_PARAMETER_TAG:
+ dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_AFFECTED_DESTINATIONS_PARAMETER_TAG:
+ dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_ROUTING_CONTEXT_PARAMETER_TAG:
+ dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
+ dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_HEARTBEAT_DATA_PARAMETER_TAG:
+ dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_USER_CAUSE_PARAMETER_TAG:
+ dissect_user_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_REASON_PARAMETER_TAG:
+ dissect_reason_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_TRAFFIC_MODE_TYPE_PARAMETER_TAG:
+ dissect_v7_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_ERROR_CODE_PARAMETER_TAG:
+ dissect_v7_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_STATUS_PARAMETER_TAG:
+ dissect_v567_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_CONGESTION_INDICATION_PARAMETER_TAG:
+ dissect_congestion_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_CONCERNED_DESTINATION_PARAMETER_TAG:
+ dissect_concerned_destination_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_ROUTING_KEY_PARAMETER_TAG:
+ dissect_routing_key_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case V7_REGISTRATION_RESULT_PARAMETER_TAG:
+ dissect_v67_registration_result_parameter(parameter_tvb, parameter_tree);
+ break;
+ case V7_DEREGISTRATION_RESULT_PARAMETER_TAG:
+ dissect_v67_deregistration_result_parameter(parameter_tvb, parameter_tree);
+ break;
+ case V7_LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG:
+ dissect_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_DESTINATION_POINT_CODE_PARAMETER_TAG:
+ dissect_destination_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_SERVICE_INDICATORS_PARAMETER_TAG:
+ dissect_service_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_SUBSYSTEM_NUMBERS_PARAMETER_TAG:
+ dissect_subsystem_numbers_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG:
+ dissect_originating_point_code_list_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_CIRCUIT_RANGE_PARAMETER_TAG:
+ dissect_circuit_range_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case V7_REGISTRATION_RESULTS_PARAMETER_TAG:
+ dissect_registration_results_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case V7_DEREGISTRATION_RESULTS_PARAMETER_TAG:
+ dissect_deregistration_results_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ default:
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ };
+
+ if (padding_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+#define INFO_STRING_PARAMETER_TAG 0x0004
+#define ROUTING_CONTEXT_PARAMETER_TAG 0x0006
+#define DIAGNOSTIC_INFORMATION_PARAMETER_TAG 0x0007
+#define HEARTBEAT_DATA_PARAMETER_TAG 0x0009
+#define TRAFFIC_MODE_TYPE_PARAMETER_TAG 0x000b
+#define ERROR_CODE_PARAMETER_TAG 0x000c
+#define STATUS_PARAMETER_TAG 0x000d
+#define ASP_IDENTIFIER_PARAMETER_TAG 0x0011
+#define AFFECTED_POINT_CODE_PARAMETER_TAG 0x0012
+#define CORRELATION_IDENTIFIER_PARAMETER_TAG 0x0013
+
+#define NETWORK_APPEARANCE_PARAMETER_TAG 0x0200
+#define USER_CAUSE_PARAMETER_TAG 0x0204
+#define CONGESTION_INDICATIONS_PARAMETER_TAG 0x0205
+#define CONCERNED_DESTINATION_PARAMETER_TAG 0x0206
+#define ROUTING_KEY_PARAMETER_TAG 0x0207
+#define REGISTRATION_RESULT_PARAMETER_TAG 0x0208
+#define DEREGISTRATION_RESULT_PARAMETER_TAG 0x0209
+#define LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG 0x020a
+#define DESTINATION_POINT_CODE_PARAMETER_TAG 0x020b
+#define SERVICE_INDICATORS_PARAMETER_TAG 0x020c
+#define ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG 0x020e
+#define CIRCUIT_RANGE_PARAMETER_TAG 0x020f
+#define PROTOCOL_DATA_PARAMETER_TAG 0x0210
+#define REGISTRATION_STATUS_PARAMETER_TAG 0x0212
+#define DEREGISTRATION_STATUS_PARAMETER_TAG 0x0213
+
+static const value_string parameter_tag_values[] = {
+ { INFO_STRING_PARAMETER_TAG, "Info string" } ,
+ { ROUTING_CONTEXT_PARAMETER_TAG, "Routing context" } ,
+ { DIAGNOSTIC_INFORMATION_PARAMETER_TAG, "Diagnostic Information" } ,
+ { HEARTBEAT_DATA_PARAMETER_TAG, "Heartbeat data" } ,
+ { TRAFFIC_MODE_TYPE_PARAMETER_TAG, "Traffic mode type" } ,
+ { ERROR_CODE_PARAMETER_TAG, "Error code" } ,
+ { STATUS_PARAMETER_TAG, "Status" } ,
+ { ASP_IDENTIFIER_PARAMETER_TAG, "ASP identifier" } ,
+ { AFFECTED_POINT_CODE_PARAMETER_TAG, "Affected point code" } ,
+ { CORRELATION_IDENTIFIER_PARAMETER_TAG, "Correlation identifier" } ,
+ { NETWORK_APPEARANCE_PARAMETER_TAG, "Network appearance" } ,
+ { USER_CAUSE_PARAMETER_TAG, "User / cause" } ,
+ { CONGESTION_INDICATIONS_PARAMETER_TAG, "Congestion indications" } ,
+ { CONCERNED_DESTINATION_PARAMETER_TAG, "Concerned destination" } ,
+ { ROUTING_KEY_PARAMETER_TAG, "Routing key" } ,
+ { REGISTRATION_RESULT_PARAMETER_TAG, "Registration result" } ,
+ { DEREGISTRATION_RESULT_PARAMETER_TAG, "Deregistration result" } ,
+ { LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG, "Local routing key identifier" } ,
+ { DESTINATION_POINT_CODE_PARAMETER_TAG, "Destination point code" } ,
+ { SERVICE_INDICATORS_PARAMETER_TAG, "Service indicators" } ,
+ { ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG, "Originating point code list" } ,
+ { CIRCUIT_RANGE_PARAMETER_TAG, "Circuit range" } ,
+ { PROTOCOL_DATA_PARAMETER_TAG, "Protocol data" } ,
+ { REGISTRATION_STATUS_PARAMETER_TAG, "Registration status" } ,
+ { DEREGISTRATION_STATUS_PARAMETER_TAG, "Deregistration status" } ,
+ { 0, NULL } };
+
+static void
+dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
+{
+ guint16 tag, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+
+ /* extract tag and length from the parameter */
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = tvb_length(parameter_tvb) - length;
+
+
+ if (!tree && tag != PROTOCOL_DATA_PARAMETER_TAG)
+ return; /* Nothing to do here */
+
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(m3ua_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), val_to_str(tag, parameter_tag_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_parameter);
+
+ /* add tag and length to the parameter tree */
+ proto_tree_add_item(parameter_tree, hf_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(tag) {
+ case INFO_STRING_PARAMETER_TAG:
+ dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ROUTING_CONTEXT_PARAMETER_TAG:
+ dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case DIAGNOSTIC_INFORMATION_PARAMETER_TAG:
+ dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case HEARTBEAT_DATA_PARAMETER_TAG:
+ dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
+ dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ERROR_CODE_PARAMETER_TAG:
+ dissect_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case STATUS_PARAMETER_TAG:
+ dissect_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ASP_IDENTIFIER_PARAMETER_TAG:
+ dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case AFFECTED_POINT_CODE_PARAMETER_TAG:
+ dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case NETWORK_APPEARANCE_PARAMETER_TAG:
+ dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case USER_CAUSE_PARAMETER_TAG:
+ dissect_user_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case CONGESTION_INDICATIONS_PARAMETER_TAG:
+ dissect_congestion_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case CONCERNED_DESTINATION_PARAMETER_TAG:
+ dissect_concerned_destination_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ROUTING_KEY_PARAMETER_TAG:
+ dissect_routing_key_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case REGISTRATION_RESULT_PARAMETER_TAG:
+ dissect_registration_result_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case DEREGISTRATION_RESULT_PARAMETER_TAG:
+ dissect_deregistration_result_parameter(parameter_tvb, pinfo, tree, parameter_tree);
+ break;
+ case LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG:
+ dissect_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case DESTINATION_POINT_CODE_PARAMETER_TAG:
+ dissect_destination_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case SERVICE_INDICATORS_PARAMETER_TAG:
+ dissect_service_indicators_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ORIGINATING_POINT_CODE_LIST_PARAMETER_TAG:
+ dissect_originating_point_code_list_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case CIRCUIT_RANGE_PARAMETER_TAG:
+ dissect_circuit_range_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case PROTOCOL_DATA_PARAMETER_TAG:
+ dissect_protocol_data_parameter(parameter_tvb, pinfo, tree, parameter_tree, parameter_item);
+ break;
+ case CORRELATION_IDENTIFIER_PARAMETER_TAG:
+ dissect_correlation_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case REGISTRATION_STATUS_PARAMETER_TAG:
+ dissect_registration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case DEREGISTRATION_STATUS_PARAMETER_TAG:
+ dissect_deregistration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ default:
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ };
+
+ if (padding_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
+{
+ gint offset, length, total_length, remaining_length;
+ tvbuff_t *parameter_tvb;
+
+ offset = 0;
+ while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
+ length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ if (remaining_length >= length)
+ total_length = MIN(total_length, remaining_length);
+ /* create a tvb for the parameter including the padding bytes */
+ parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
+ switch(version) {
+ case M3UA_V5:
+ dissect_v5_parameter(parameter_tvb, pinfo, tree, m3ua_tree);
+ break;
+ case M3UA_V6:
+ dissect_v6_parameter(parameter_tvb, pinfo, tree, m3ua_tree);
+ break;
+ case M3UA_V7:
+ dissect_v7_parameter(parameter_tvb, pinfo, tree, m3ua_tree);
+ break;
+ case M3UA_RFC:
+ dissect_parameter(parameter_tvb, pinfo, tree, m3ua_tree);
+ break;
+ }
+ /* get rid of the handled parameter */
+ offset += total_length;
+ }
+}
+
+
+static void
+dissect_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *m3ua_tree)
+{
+ tvbuff_t *common_header_tvb, *parameters_tvb;
+
+ common_header_tvb = tvb_new_subset(message_tvb, 0, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
+ parameters_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_LENGTH, -1, -1);
+ if (version == M3UA_V5)
+ dissect_v5_common_header(common_header_tvb, pinfo, m3ua_tree);
+ else
+ dissect_common_header(common_header_tvb, pinfo, m3ua_tree);
+
+ /* Need to dissect (certain) parameters even when !tree, so subdissectors
+ * (e.g., MTP3) are always called.
+ */
+ dissect_parameters(parameters_tvb, pinfo, tree, m3ua_tree);
+}
+
+static void
+dissect_m3ua(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *m3ua_item;
+ proto_tree *m3ua_tree;
+
+ /* make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ switch(version) {
+ case M3UA_V5:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "M3UA (ID 05)");
+ break;
+ case M3UA_V6:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "M3UA (ID 06)");
+ break;
+ case M3UA_V7:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "M3UA (ID 07)");
+ break;
+ case M3UA_RFC:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "M3UA (RFC 3332)");
+ break;
+ };
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the m3ua protocol tree */
+ m3ua_item = proto_tree_add_item(tree, proto_m3ua, message_tvb, 0, -1, FALSE);
+ m3ua_tree = proto_item_add_subtree(m3ua_item, ett_m3ua);
+ } else {
+ m3ua_tree = NULL;
+ };
+
+ /* dissect the message */
+ dissect_message(message_tvb, pinfo, tree, m3ua_tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_m3ua(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_version, { "Version", "m3ua.version", FT_UINT8, BASE_DEC, VALS(protocol_version_values), 0x0, "", HFILL } },
+ { &hf_reserved, { "Reserved", "m3ua.reserved", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_v5_message_class, { "Message class", "m3ua.message_class", FT_UINT8, BASE_DEC, VALS(v5_message_class_values), 0x0, "", HFILL } },
+ { &hf_message_class, { "Message class", "m3ua.message_class", FT_UINT8, BASE_DEC, VALS(message_class_values), 0x0, "", HFILL } },
+ { &hf_message_type, { "Message Type", "m3ua.message_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_message_length, { "Message length", "m3ua.message_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_v5_parameter_tag, { "Parameter Tag", "m3ua.parameter_tag", FT_UINT16, BASE_DEC, VALS(v5_parameter_tag_values), 0x0, "", HFILL } },
+ { &hf_v6_parameter_tag, { "Parameter Tag", "m3ua.parameter_tag", FT_UINT16, BASE_DEC, VALS(v6_parameter_tag_values), 0x0, "", HFILL } },
+ { &hf_v7_parameter_tag, { "Parameter Tag", "m3ua.parameter_tag", FT_UINT16, BASE_DEC, VALS(v7_parameter_tag_values), 0x0, "", HFILL } },
+ { &hf_parameter_tag, { "Parameter Tag", "m3ua.parameter_tag", FT_UINT16, BASE_DEC, VALS(parameter_tag_values), 0x0, "", HFILL } },
+ { &hf_parameter_length, { "Parameter length", "m3ua.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_value, { "Parameter value", "m3ua.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_padding, { "Padding", "m3ua.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_trailer, { "Trailer", "m3ua.paramter_trailer", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_network_appearance, { "Network appearance", "m3ua.network_appearance", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_info_string, { "Info string", "m3ua.info_string", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_routing_context, { "Routing context", "m3ua.routing_context", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_diagnostic_information, { "Diagnostic information", "m3ua.diagnostic_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_heartbeat_data, { "Heartbeat data", "m3ua.heartbeat_data", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_v5_error_code, { "Error code", "m3ua.error_code", FT_UINT32, BASE_DEC, VALS(v5_error_code_values), 0x0, "", HFILL } },
+ { &hf_v6_error_code, { "Error code", "m3ua.error_code", FT_UINT32, BASE_DEC, VALS(v6_error_code_values), 0x0, "", HFILL } },
+ { &hf_v7_error_code, { "Error code", "m3ua.error_code", FT_UINT32, BASE_DEC, VALS(v7_error_code_values), 0x0, "", HFILL } },
+ { &hf_error_code, { "Error code", "m3ua.error_code", FT_UINT32, BASE_DEC, VALS(error_code_values), 0x0, "", HFILL } },
+ { &hf_status_type, { "Status type", "m3ua.status_type", FT_UINT16, BASE_DEC, VALS(status_type_values), 0x0, "", HFILL } },
+ { &hf_status_info, { "Status info", "m3ua.status_info", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_asp_identifier, { "ASP identifier", "m3ua.asp_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_affected_point_code_mask, { "Mask", "m3ua.affected_point_code_mask", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_affected_point_code_pc, { "Affected point code", "m3ua.affected_point_code_pc", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause, { "Unavailability cause", "m3ua.unavailability_cause", FT_UINT16, BASE_DEC, VALS(unavailability_cause_values), 0x0, "", HFILL } },
+ { &hf_user, { "User Identity", "m3ua.user_identity", FT_UINT16, BASE_DEC, VALS(user_identity_values), 0x0, "", HFILL } },
+ { &hf_reason, { "Reason", "m3ua.reason", FT_UINT32, BASE_DEC, VALS(reason_values), 0x0, "", HFILL } },
+ { &hf_v5_traffic_mode_type, { "Traffic mode Type", "m3ua.traffic_mode_type", FT_UINT32, BASE_DEC, VALS(v5_traffic_mode_type_values), 0x0, "", HFILL } },
+ { &hf_v6_traffic_mode_type, { "Traffic mode Type", "m3ua.traffic_mode_type", FT_UINT32, BASE_DEC, VALS(v6_traffic_mode_type_values), 0x0, "", HFILL } },
+ { &hf_v7_traffic_mode_type, { "Traffic mode Type", "m3ua.traffic_mode_type", FT_UINT32, BASE_DEC, VALS(v7_traffic_mode_type_values), 0x0, "", HFILL } },
+ { &hf_traffic_mode_type, { "Traffic mode Type", "m3ua.traffic_mode_type", FT_UINT32, BASE_DEC, VALS(traffic_mode_type_values), 0x0, "", HFILL } },
+ { &hf_congestion_reserved, { "Reserved", "m3ua.congestion_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_congestion_level, { "Congestion level", "m3ua.congestion_level", FT_UINT8, BASE_DEC, VALS(congestion_level_values), 0x0, "", HFILL } },
+ { &hf_concerned_dest_reserved, { "Reserved", "m3ua.concerned_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_concerned_dest_pc, { "Concerned DPC", "m3ua.concerned_dpc", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_local_rk_identifier, { "Local routing key identifier", "m3ua.local_rk_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_dpc_mask, { "Mask", "m3ua.dpc_mask", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_dpc_pc, { "Destination point code", "m3ua.dpc_pc", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_si, { "Service indicator", "m3ua.si", FT_UINT8, BASE_DEC, VALS(user_identity_values), 0x0, "", HFILL } },
+ { &hf_ssn, { "Subsystem number", "m3ua.ssn", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_opc_list_mask, { "Mask", "m3ua.opc_list_mask", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_opc_list_pc, { "Originating point code", "m3ua.opc_list_pc", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cic_range_mask, { "Mask", "m3ua.cic_range_mask", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cic_range_pc, { "Originating point code", "m3ua.cic_range_pc", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cic_range_lower, { "Lower CIC value", "m3ua.cic_range_lower", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cic_range_upper, { "Upper CIC value", "m3ua.cic_range_upper", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_li, { "Length indicator", "m3ua.protocol_data_2_li", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_protocol_data_opc, { "OPC", "m3ua.protocol_data_opc", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_protocol_data_dpc, { "DPC", "m3ua.protocol_data_dpc", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_protocol_data_si, { "SI", "m3ua.protocol_data_si", FT_UINT8, BASE_DEC, VALS(user_identity_values), 0x0, "", HFILL } },
+ { &hf_protocol_data_ni, { "NI", "m3ua.protocol_data_ni", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_protocol_data_mp, { "MP", "m3ua.protocol_data_mp", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_protocol_data_sls, { "SLS", "m3ua.protocol_data_sls", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_correlation_identifier, { "Correlation Identifier", "m3ua.correlation_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_registration_status, { "Registration status", "m3ua.registration_status", FT_UINT32, BASE_DEC, VALS(registration_status_values), 0x0, "", HFILL } },
+ { &hf_deregistration_status, { "Deregistration status", "m3ua.deregistration_status", FT_UINT32, BASE_DEC, VALS(deregistration_status_values), 0x0, "", HFILL } },
+ { &hf_registration_result_identifier, { "Local RK-identifier value", "m3ua.registration_result_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_registration_result_status, { "Registration status", "m3ua.registration_results_status", FT_UINT32, BASE_DEC, VALS(registration_result_status_values), 0x0, "", HFILL } },
+ { &hf_registration_result_context, { "Routing context", "m3ua.registration_result_routing_context", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_v6_deregistration_result_status, { "De-Registration status", "m3ua.deregistration_results_status", FT_UINT32, BASE_DEC, VALS(v6_deregistration_result_status_values), 0x0, "", HFILL } },
+ { &hf_v6_deregistration_result_context, { "Routing context", "m3ua.deregistration_result_routing_context", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_m3ua,
+ &ett_parameter,
+ };
+
+ static enum_val_t options[] = {
+ { "draft-5", "Internet Draft version 5", M3UA_V5 },
+ { "draft-6", "Internet Draft version 6", M3UA_V6 },
+ { "draft-7", "Internet Draft version 7", M3UA_V7 },
+ { "rfc3332", "RFC 3332", M3UA_RFC },
+ { NULL, NULL, 0 }
+ };
+
+ /* Register the protocol name and description */
+ proto_m3ua = proto_register_protocol("MTP 3 User Adaptation Layer", "M3UA", "m3ua");
+ m3ua_module = prefs_register_protocol(proto_m3ua, NULL);
+ prefs_register_enum_preference(m3ua_module, "version", "M3UA Version", "Version used by Ethereal", (gint *)&version, options, FALSE);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_m3ua, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ si_dissector_table = register_dissector_table("m3ua.protocol_data_si", "MTP3 Service indicator", FT_UINT8, BASE_HEX);
+
+}
+
+void
+proto_reg_handoff_m3ua(void)
+{
+ dissector_handle_t m3ua_handle;
+
+ /*
+ * Get a handle for the MTP3 dissector.
+ */
+ mtp3_handle = find_dissector("mtp3");
+ data_handle = find_dissector("data");
+ m3ua_handle = create_dissector_handle(dissect_m3ua, proto_m3ua);
+ dissector_add("sctp.ppi", M3UA_PAYLOAD_PROTOCOL_ID, m3ua_handle);
+ dissector_add("sctp.port", SCTP_PORT_M3UA, m3ua_handle);
+}
diff --git a/epan/dissectors/packet-mbtcp.c b/epan/dissectors/packet-mbtcp.c
new file mode 100644
index 0000000000..4d9549b45f
--- /dev/null
+++ b/epan/dissectors/packet-mbtcp.c
@@ -0,0 +1,692 @@
+/* packet-mbtcp.c
+ * Routines for Modbus/TCP dissection
+ * By Riaan Swart <rswart@cs.sun.ac.za>
+ * Copyright 2001, Institute for Applied Computer Science
+ * University of Stellenbosch
+ *
+ * See
+ *
+ * http://www.modicon.com/openmbus/
+ *
+ * for information on Modbus/TCP.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#define DEBUG
+
+#define TCP_PORT_MBTCP 502 /* Modbus/TCP located on TCP port 502 */
+
+/* Modbus protocol function codes */
+#define read_coils 1
+#define read_input_discretes 2
+#define read_mult_regs 3
+#define read_input_regs 4
+#define write_coil 5
+#define write_single_reg 6
+#define read_except_stat 7
+#define diagnostics 8
+#define program_484 9
+#define poll_484 10
+#define get_comm_event_ctrs 11
+#define get_comm_event_log 12
+#define program_584_984 13
+#define poll_584_984 14
+#define force_mult_coils 15
+#define write_mult_regs 16
+#define report_slave_id 17
+#define program_884_u84 18
+#define reset_comm_link 19
+#define read_genl_ref 20
+#define write_genl_ref 21
+#define mask_write_reg 22
+#define read_write_reg 23
+#define read_fifo_queue 24
+#define program_ConCept 40
+#define firmware_replace 125
+#define program_584_984_2 126
+#define report_local_addr_mb 127
+
+/* Modbus protocol exception codes */
+#define illegal_function 0x01
+#define illegal_address 0x02
+#define illegal_value 0x03
+#define illegal_response 0x04
+#define acknowledge 0x05
+#define slave_busy 0x06
+#define negative_ack 0x07
+#define memory_err 0x08
+#define gateway_unavailable 0x0a
+#define gateway_trgt_fail 0x0b
+
+/* return codes of function classifying packets as query/response */
+#define query_packet 0
+#define response_packet 1
+#define cannot_classify 2
+
+/* Modbus header */
+typedef struct _modbus_hdr {
+ guint8 unit_id; /* unit identifier (previously slave addr) */
+ guint8 function_code; /* Modbus function code */
+} modbus_hdr;
+
+/* Modbus/TCP header, containing the Modbus header */
+typedef struct _mbtcp_hdr {
+ guint16 transaction_id; /* copied by svr, usually 0 */
+ guint16 protocol_id; /* always 0 */
+ guint16 len; /* len of data that follows */
+ modbus_hdr mdbs_hdr; /* mdbus hdr directly after mdbs/tcp hdr *
+ * in packet */
+} mbtcp_hdr;
+
+/* Initialize the protocol and registered fields */
+static int proto_mbtcp = -1;
+static int hf_mbtcp_transid = -1;
+static int hf_mbtcp_protid = -1;
+static int hf_mbtcp_len = -1;
+static int hf_mbtcp_unitid = -1;
+static int hf_mbtcp_functioncode = -1;
+static int hf_modbus_reference = -1;
+static int hf_modbus_lreference = -1;
+static int hf_modbus_reftype = -1;
+static int hf_modbus_readref = -1;
+static int hf_modbus_writeref = -1;
+static int hf_modbus_wordcnt = -1;
+static int hf_modbus_readwordcnt = -1;
+static int hf_modbus_writewordcnt = -1;
+static int hf_modbus_bytecnt = -1;
+static int hf_modbus_lbytecnt = -1;
+static int hf_modbus_bitcnt = -1;
+static int hf_modbus_exceptioncode = -1;
+static int hf_modbus_andmask = -1;
+static int hf_modbus_ormask = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_mbtcp = -1;
+static gint ett_modbus_hdr = -1;
+static gint ett_group_hdr = -1;
+
+static int
+classify_packet(packet_info *pinfo)
+{
+ /* see if nature of packets can be derived from src/dst ports */
+ /* if so, return as found */
+ if ( ( 502 == pinfo->srcport && 502 != pinfo->destport ) ||
+ ( 502 != pinfo->srcport && 502 == pinfo->destport ) ) {
+ /* the slave is receiving queries on port 502 */
+ if ( 502 == pinfo->srcport )
+ return response_packet;
+ else if ( 502 == pinfo->destport )
+ return query_packet;
+ }
+ /* else, cannot classify */
+ return cannot_classify;
+}
+
+/* Translate function to string, as given on p6 of
+ * "Open Modbus/TCP Specification", release 1 by Andy Swales. */
+static const value_string function_code_vals[] = {
+ { read_coils, "Read coils" },
+ { read_input_discretes, "Read input discretes" },
+ { read_mult_regs, "Read multiple registers" },
+ { read_input_regs, "Read input registers" },
+ { write_coil, "Write coil" },
+ { write_single_reg, "Write single register" },
+ { read_except_stat, "Read exception status" },
+ { diagnostics, "Diagnostics" },
+ { program_484, "Program (484)" },
+ { poll_484, "Poll (484)" },
+ { get_comm_event_ctrs, "Get Comm. Event Counters" },
+ { get_comm_event_log, "Get Comm. Event Log" },
+ { program_584_984, "Program (584/984)" },
+ { poll_584_984, "Poll (584/984)" },
+ { force_mult_coils, "Force Multiple Coils" },
+ { write_mult_regs, "Write Multiple Registers" },
+ { report_slave_id, "Report Slave ID" },
+ { program_884_u84, "Program 884/u84" },
+ { reset_comm_link, "Reset Comm. Link (884/u84)" },
+ { read_genl_ref, "Read General Reference" },
+ { write_genl_ref, "Write General Reference" },
+ { mask_write_reg, "Mask Write Register" },
+ { read_write_reg, "Read Write Register" },
+ { read_fifo_queue, "Read FIFO Queue" },
+ { program_ConCept, "Program (ConCept)" },
+ { firmware_replace, "Firmware replacement" },
+ { program_584_984_2, "Program (584/984)" },
+ { report_local_addr_mb, "Report local address (Modbus)" },
+ { 0, NULL }
+};
+
+static const value_string exception_code_vals[] = {
+ { illegal_function, "Illegal function" },
+ { illegal_address, "Illegal data address" },
+ { illegal_value, "Illegal data value" },
+ { illegal_response, "Illegal response length" },
+ { acknowledge, "Acknowledge" },
+ { slave_busy, "Slave device busy" },
+ { negative_ack, "Negative acknowledge" },
+ { memory_err, "Memory parity error" },
+ { gateway_unavailable, "Gateway path unavailable" },
+ { gateway_trgt_fail, "Gateway target device failed to respond" },
+ { 0, NULL }
+};
+
+/* Code to actually dissect the packets */
+static void
+dissect_mbtcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+/* Set up structures needed to add the protocol subtree and manage it */
+ mbtcp_hdr mh;
+ proto_item *mi, *mf;
+ proto_tree *mbtcp_tree, *modbus_tree, *group_tree;
+ int offset, group_offset, packet_type;
+ guint i;
+ gint packet_len, payload_start, payload_len;
+ char *func_string = "", pkt_type_str[9] = "";
+ char err_str[100] = "";
+ guint32 byte_cnt, group_byte_cnt, group_word_cnt;
+ guint32 packet_num; /* num to uniquely identify different mbtcp
+ * packets in one TCP packet */
+ guint8 exception_code;
+ gboolean exception_returned;
+
+/* Make entries in Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Modbus/TCP");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+/* Make entries in Info column on summary display */
+ offset = 0;
+ tvb_memcpy(tvb, (guint8 *)&mh, offset, sizeof(mbtcp_hdr));
+ mh.transaction_id = g_ntohs(mh.transaction_id);
+ mh.protocol_id = g_ntohs(mh.protocol_id);
+ mh.len = g_ntohs(mh.len);
+ if ( mh.mdbs_hdr.function_code & 0x80 ) {
+ exception_code = tvb_get_guint8(tvb, offset + sizeof(mbtcp_hdr));
+ mh.mdbs_hdr.function_code ^= 0x80;
+ exception_returned = TRUE;
+ }
+ else {
+ exception_code = 0;
+ exception_returned = FALSE;
+ }
+ func_string = val_to_str(mh.mdbs_hdr.function_code, function_code_vals,
+ "Unknown function (%u)");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ packet_type = classify_packet(pinfo);
+ switch ( packet_type ) {
+ case query_packet : strcpy(pkt_type_str, "query");
+ break;
+ case response_packet : strcpy(pkt_type_str, "response");
+ break;
+ case cannot_classify : strcpy(err_str, "Unable to classify as query or response.");
+ strcpy(pkt_type_str, "unknown");
+ break;
+ default :
+ break;
+ }
+ if ( exception_returned )
+ strcpy(err_str, "Exception returned ");
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%8s [%2u pkt(s)]: trans: %5u; unit: %3u, func: %3u: %s. %s",
+ pkt_type_str, 1, mh.transaction_id, (unsigned char) mh.mdbs_hdr.unit_id,
+ (unsigned char) mh.mdbs_hdr.function_code, func_string, err_str);
+ }
+
+ /* build up protocol tree and iterate over multiple packets */
+ packet_num = 0;
+ while (1) {
+ packet_type = classify_packet(pinfo);
+ packet_len = sizeof(mbtcp_hdr) - sizeof(modbus_hdr) + mh.len;
+
+ /* if a tree exists, perform operations to add fields to it */
+ if (tree) {
+ mi = proto_tree_add_protocol_format(tree, proto_mbtcp, tvb, offset,
+ packet_len, "Modbus/TCP");
+ mbtcp_tree = proto_item_add_subtree(mi, ett_mbtcp);
+
+ /* Add items to protocol tree specific to Modbus/TCP Modbus/TCP */
+ proto_tree_add_uint(mbtcp_tree, hf_mbtcp_transid, tvb, offset, 2,
+ mh.transaction_id);
+ proto_tree_add_uint(mbtcp_tree, hf_mbtcp_protid, tvb, offset + 2, 2,
+ mh.protocol_id);
+ proto_tree_add_uint(mbtcp_tree, hf_mbtcp_len, tvb, offset + 4, 2,
+ mh.len);
+
+ /* Add items to protocol tree specific to Modbus generic */
+ mf = proto_tree_add_text(mbtcp_tree, tvb, offset + 6, mh.len,
+ "Modbus");
+ modbus_tree = proto_item_add_subtree(mf, ett_modbus_hdr);
+ proto_tree_add_uint(modbus_tree, hf_mbtcp_unitid, tvb, offset + 6, 1,
+ mh.mdbs_hdr.unit_id);
+ mi = proto_tree_add_uint(modbus_tree, hf_mbtcp_functioncode, tvb, offset + 7, 1,
+ mh.mdbs_hdr.function_code);
+
+ /** detail payload as a function of exception/function code */
+ func_string = val_to_str(mh.mdbs_hdr.function_code,
+ function_code_vals, "Unknown function");
+ payload_start = offset + 8;
+ payload_len = mh.len - sizeof(modbus_hdr);
+ if (exception_returned) {
+ proto_item_set_text(mi, "function %u: %s. Exception: %s",
+ mh.mdbs_hdr.function_code,
+ func_string,
+ val_to_str(exception_code,
+ exception_code_vals,
+ "Unknown exception code (%u)"));
+ proto_tree_add_uint(modbus_tree, hf_modbus_exceptioncode, tvb, payload_start, 1,
+ exception_code);
+ }
+ else {
+ proto_item_set_text(mi, "function %u: %s", mh.mdbs_hdr.function_code,
+ func_string);
+ switch (mh.mdbs_hdr.function_code) {
+
+ case read_coils:
+ case read_input_discretes:
+ if (packet_type == query_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE);
+ }
+ else if (packet_type == response_packet) {
+ byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
+ proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data");
+ }
+ break;
+
+ case read_mult_regs:
+ case read_input_regs:
+ if (packet_type == query_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
+ }
+ else if (packet_type == response_packet) {
+ byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
+ proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data");
+ }
+ break;
+
+ case write_coil:
+ if (packet_type == query_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 1, "Data");
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 3, 1, "Padding");
+ }
+ else if (packet_type == response_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 1, "Data");
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 3, 1, "Padding");
+ }
+ break;
+
+ case write_single_reg:
+ if (packet_type == query_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 2, "Data");
+ }
+ else if (packet_type == response_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 2, "Data");
+ }
+ break;
+
+ case read_except_stat:
+ if (packet_type == response_packet)
+ proto_tree_add_text(modbus_tree, tvb, payload_start, 1, "Data");
+ break;
+
+ case force_mult_coils:
+ if (packet_type == query_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE);
+ byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 4);
+ proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 4, 1,
+ byte_cnt);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 5, byte_cnt, "Data");
+ }
+ else if (packet_type == response_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE);
+ }
+ break;
+
+ case write_mult_regs:
+ if (packet_type == query_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
+ byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 4);
+ proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 4, 1,
+ byte_cnt);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 5, byte_cnt, "Data");
+ }
+ else if (packet_type == response_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
+ }
+ break;
+
+ case read_genl_ref:
+ if (packet_type == query_packet) {
+ byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
+ proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
+ byte_cnt);
+
+ /* add subtrees to describe each group of packet */
+ group_offset = payload_start + 1;
+ for (i = 0; i < byte_cnt / 7; i++) {
+ mi = proto_tree_add_text( modbus_tree, tvb, group_offset, 7,
+ "Group %u", i);
+ group_tree = proto_item_add_subtree(mi, ett_group_hdr);
+ proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset, 1, FALSE);
+ proto_tree_add_item(group_tree, hf_modbus_lreference, tvb, group_offset + 1, 4, FALSE);
+ proto_tree_add_item(group_tree, hf_modbus_wordcnt, tvb, group_offset + 5, 2, FALSE);
+ group_offset += 7;
+ }
+ }
+ else if (packet_type == response_packet) {
+ byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
+ proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
+ byte_cnt);
+
+ /* add subtrees to describe each group of packet */
+ group_offset = payload_start + 1;
+ i = 0;
+ while (byte_cnt > 0) {
+ group_byte_cnt = (guint32)tvb_get_guint8(tvb, group_offset);
+ mi = proto_tree_add_text( modbus_tree, tvb, group_offset, group_byte_cnt + 1,
+ "Group %u", i);
+ group_tree = proto_item_add_subtree(mi, ett_group_hdr);
+ proto_tree_add_uint(group_tree, hf_modbus_bytecnt, tvb, group_offset, 1,
+ group_byte_cnt);
+ proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset + 1, 1, FALSE);
+ proto_tree_add_text(group_tree, tvb, group_offset + 2, group_byte_cnt - 1, "Data");
+ group_offset += (group_byte_cnt + 1);
+ byte_cnt -= (group_byte_cnt + 1);
+ i++;
+ }
+ }
+ break;
+
+ case write_genl_ref:
+ if ((packet_type == query_packet) || (packet_type == response_packet)) {
+ byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
+ proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
+ byte_cnt);
+
+ /* add subtrees to describe each group of packet */
+ group_offset = payload_start + 1;
+ i = 0;
+ while (byte_cnt > 0) {
+ group_word_cnt = tvb_get_ntohs(tvb, group_offset + 5);
+ group_byte_cnt = (2 * group_word_cnt) + 7;
+ mi = proto_tree_add_text( modbus_tree, tvb, group_offset,
+ group_byte_cnt, "Group %u", i);
+ group_tree = proto_item_add_subtree(mi, ett_group_hdr);
+ proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset, 1, FALSE);
+ proto_tree_add_item(group_tree, hf_modbus_lreference, tvb, group_offset + 1, 4, FALSE);
+ proto_tree_add_uint(group_tree, hf_modbus_wordcnt, tvb, group_offset + 5, 2,
+ group_word_cnt);
+ proto_tree_add_text(group_tree, tvb, group_offset + 7, group_byte_cnt - 7, "Data");
+ group_offset += group_byte_cnt;
+ byte_cnt -= group_byte_cnt;
+ i++;
+ }
+ }
+ break;
+
+ case mask_write_reg:
+ if ((packet_type == query_packet) || (packet_type == response_packet)) {
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_andmask, tvb, payload_start + 2, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_ormask, tvb, payload_start + 4, 2, FALSE);
+ }
+ break;
+
+ case read_write_reg:
+ if (packet_type == query_packet) {
+ proto_tree_add_item(modbus_tree, hf_modbus_readref, tvb, payload_start, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_readwordcnt, tvb, payload_start + 2, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_writeref, tvb, payload_start + 4, 2, FALSE);
+ proto_tree_add_item(modbus_tree, hf_modbus_writewordcnt, tvb, payload_start + 6, 2, FALSE);
+ byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 8);
+ proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 8, 1,
+ byte_cnt);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 9, byte_cnt, "Data");
+ }
+ else if (packet_type == response_packet) {
+ byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
+ proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
+ byte_cnt);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data");
+ }
+ break;
+
+ case read_fifo_queue:
+ if (packet_type == query_packet)
+ proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
+ else if (packet_type == response_packet) {
+ byte_cnt = (guint32)tvb_get_ntohs(tvb, payload_start);
+ proto_tree_add_uint(modbus_tree, hf_modbus_lbytecnt, tvb, payload_start, 2,
+ byte_cnt);
+ proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
+ proto_tree_add_text(modbus_tree, tvb, payload_start + 4, byte_cnt - 2, "Data");
+ }
+ break;
+
+ case diagnostics:
+ case program_484:
+ case poll_484:
+ case get_comm_event_ctrs:
+ case get_comm_event_log:
+ case program_584_984:
+ case poll_584_984:
+ case report_slave_id:
+ case program_884_u84:
+ case reset_comm_link:
+ case program_ConCept:
+ case firmware_replace:
+ case program_584_984_2:
+ case report_local_addr_mb:
+ /* these function codes are not part of the Modbus/TCP specification */
+ default:
+ if (payload_len > 0)
+ proto_tree_add_text(modbus_tree, tvb, payload_start, payload_len, "Data");
+ break;
+ }
+ }
+ }
+
+ /* move onto next packet (if there) */
+ offset += packet_len;
+ packet_num++;
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+
+ /* load header structure for next packet */
+ tvb_memcpy(tvb, (guint8 *)&mh, offset, sizeof(mbtcp_hdr));
+ mh.transaction_id = g_ntohs(mh.transaction_id);
+ mh.protocol_id = g_ntohs(mh.protocol_id);
+ mh.len = g_ntohs(mh.len);
+
+ if ( mh.mdbs_hdr.function_code & 0x80 ) {
+ exception_code = tvb_get_guint8(tvb, offset + sizeof(mbtcp_hdr));
+ mh.mdbs_hdr.function_code ^= 0x80;
+ exception_returned = TRUE;
+ } else
+ exception_returned = FALSE;
+ }
+ else
+ break;
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+
+void
+proto_register_modbus(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ /* Modbus/TCP header fields */
+ { &hf_mbtcp_transid,
+ { "transaction identifier", "modbus_tcp.trans_id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_mbtcp_protid,
+ { "protocol identifier", "modbus_tcp.prot_id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_mbtcp_len,
+ { "length", "modbus_tcp.len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ /* Modbus header fields */
+ { &hf_mbtcp_unitid,
+ { "unit identifier", "modbus_tcp.unit_id",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_mbtcp_functioncode,
+ { "function code", "modbus_tcp.func_code",
+ FT_UINT8, BASE_DEC, VALS(function_code_vals), 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_reference,
+ { "reference number", "modbus_tcp.reference_num",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_lreference,
+ { "reference number (32 bit)", "modbus_tcp.reference_num_32",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_reftype,
+ { "reference type", "modbus_tcp.reference_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_readref,
+ { "read reference number", "modbus_tcp.read_reference_num",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_writeref,
+ { "write reference number", "modbus_tcp.write_reference_num",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_wordcnt,
+ { "word count", "modbus_tcp.word_cnt",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_readwordcnt,
+ { "read word count", "modbus_tcp.read_word_cnt",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_writewordcnt,
+ { "write word count", "modbus_tcp.write_word_cnt",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_bitcnt,
+ { "bit count", "modbus_tcp.bit_cnt",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_bytecnt,
+ { "byte count", "modbus_tcp.byte_cnt",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_lbytecnt,
+ { "byte count (16-bit)", "modbus_tcp.byte_cnt_16",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_exceptioncode,
+ { "exception code", "modbus_tcp.exception_code",
+ FT_UINT8, BASE_DEC, VALS(exception_code_vals), 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_andmask,
+ { "AND mask", "modbus_tcp.and_mask",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_modbus_ormask,
+ { "OR mask", "modbus_tcp.or_mask",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_mbtcp,
+ &ett_modbus_hdr,
+ &ett_group_hdr
+ };
+
+ /* Register the protocol name and description */
+ proto_mbtcp = proto_register_protocol("Modbus/TCP", "Modbus/TCP", "mbtcp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_mbtcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+ */
+void
+proto_reg_handoff_mbtcp(void)
+{
+ dissector_handle_t mbtcp_handle;
+
+ mbtcp_handle = create_dissector_handle(dissect_mbtcp, proto_mbtcp);
+ dissector_add("tcp.port", TCP_PORT_MBTCP, mbtcp_handle);
+}
diff --git a/epan/dissectors/packet-mdshdr.c b/epan/dissectors/packet-mdshdr.c
new file mode 100644
index 0000000000..b99f0b1a6c
--- /dev/null
+++ b/epan/dissectors/packet-mdshdr.c
@@ -0,0 +1,387 @@
+/* packet-mdshdr.c
+ * Routines for dissection of Cisco MDS Switch Internal Header
+ * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/value_string.h>
+#include <etypes.h>
+#include <epan/packet.h>
+#include "prefs.h"
+
+#define MDSHDR_VERSION_OFFSET 0
+
+/* Mdshdr Control bits */
+#define MDSHDR_CTL_IDXDIRECT 1
+#define MDSHDR_CTL_IGNACLO 2
+#define MDSHDR_CTL_DRP 4
+
+/* OFFSETS OF FIELDS */
+#define MDSHDR_VER_OFFSET 0
+#define MDSHDR_SOF_OFFSET 1
+#define MDSHDR_PKTLEN_OFFSET 2
+#define MDSHDR_DIDX_OFFSET 5
+#define MDSHDR_SIDX_OFFSET 6
+#define MDSHDR_VSAN_OFFSET 13
+
+/* Two size definitions are sufficient */
+#define MDSHDR_SIZE_BYTE sizeof (gchar)
+#define MDSHDR_SIZE_INT16 sizeof (guint16)
+#define MDSHDR_SIZE_INT32 sizeof (guint32)
+
+/* Other miscellaneous defines; can't rely on sizeof structs */
+#define MDSHDR_MAX_VERSION 0
+#define MDSHDR_HEADER_SIZE 16
+#define MDSHDR_TRAILER_SIZE 6
+
+/* SOF Encodings */
+#define MDSHDR_SOFc1 0x1
+#define MDSHDR_SOFi1 0x2
+#define MDSHDR_SOFn1 0x3
+#define MDSHDR_SOFi2 0x4
+#define MDSHDR_SOFn2 0x5
+#define MDSHDR_SOFi3 0x6
+#define MDSHDR_SOFn3 0x7
+#define MDSHDR_SOFf 0x8
+#define MDSHDR_SOFc4 0x9
+#define MDSHDR_SOFi4 0xa
+#define MDSHDR_SOFn4 0xb
+
+/* EOF Encodings */
+#define MDSHDR_EOFt 0x1
+#define MDSHDR_EOFdt 0x2
+#define MDSHDR_EOFa 0x4
+#define MDSHDR_EOFn 0x3
+#define MDSHDR_EOFdti 0x6
+#define MDSHDR_EOFni 0x7
+#define MDSHDR_EOFrt 0xa
+#define MDSHDR_EOFrti 0xe
+#define MDSHDR_EOF_UNKNOWN 0xb
+
+/* Initialize the protocol and registered fields */
+static int proto_mdshdr = -1;
+static int hf_mdshdr_sof = -1;
+static int hf_mdshdr_pkt_len = -1;
+static int hf_mdshdr_dstidx = -1;
+static int hf_mdshdr_srcidx = -1;
+static int hf_mdshdr_vsan = -1;
+static int hf_mdshdr_eof = -1;
+static int hf_mdshdr_span = -1;
+static int hf_mdshdr_fccrc = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_mdshdr = -1;
+static gint ett_mdshdr_hdr = -1;
+static gint ett_mdshdr_trlr = -1;
+
+static dissector_handle_t data_handle, fc_dissector_handle;
+
+static gboolean decode_if_zero_etype = TRUE;
+
+static const value_string sof_vals[] = {
+ {MDSHDR_SOFc1, "SOFc1"},
+ {MDSHDR_SOFi1, "SOFi1"},
+ {MDSHDR_SOFn1, "SOFn1"},
+ {MDSHDR_SOFi2, "SOFi2"},
+ {MDSHDR_SOFn2, "SOFn2"},
+ {MDSHDR_SOFi3, "SOFi3"},
+ {MDSHDR_SOFn3, "SOFn3"},
+ {MDSHDR_SOFc4, "SOFc4"},
+ {MDSHDR_SOFi4, "SOFi4"},
+ {MDSHDR_SOFn4, "SOFn4"},
+ {MDSHDR_SOFf, "SOFf"},
+ {0, NULL},
+};
+
+static const value_string eof_vals[] = {
+ {MDSHDR_EOFt, "EOFt"},
+ {MDSHDR_EOFdt, "EOFdt"},
+ {MDSHDR_EOFa, "EOFa"},
+ {MDSHDR_EOFn, "EOFn"},
+ {MDSHDR_EOFdti, "EOFdti"},
+ {MDSHDR_EOFni, "EOFni"},
+ {MDSHDR_EOFrt, "EOFrt"},
+ {MDSHDR_EOFrti, "EOFrti"},
+ {MDSHDR_EOF_UNKNOWN, ""},
+ {0, NULL},
+};
+
+void proto_reg_handoff_mdshdr(void);
+
+/* Code to actually dissect the packets */
+static void
+dissect_mdshdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti_main, *ti_hdr, *ti_trlr;
+ proto_tree *mdshdr_tree_main, *mdshdr_tree_hdr, *mdshdr_tree_trlr;
+ int offset = 0,
+ pktlen;
+ tvbuff_t *next_tvb;
+ guint8 sof, eof;
+ guint16 vsan;
+ guint8 span_id;
+ int trailer_start = 0;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDS Header");
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_clear (pinfo->cinfo, COL_INFO);
+
+ sof = tvb_get_guint8 (tvb, offset+MDSHDR_SOF_OFFSET) & 0x0F;
+ pktlen = tvb_get_ntohs (tvb, offset+MDSHDR_PKTLEN_OFFSET) & 0x1FFF;
+ vsan = tvb_get_ntohs (tvb, offset+MDSHDR_VSAN_OFFSET) & 0x0FFF;
+ span_id = (tvb_get_ntohs (tvb, offset+MDSHDR_VSAN_OFFSET) & 0xF000) >> 12;
+
+ /* The Mdshdr trailer is at the end of the frame */
+ if (tvb_bytes_exist (tvb, 0, MDSHDR_HEADER_SIZE + pktlen)) {
+ trailer_start = MDSHDR_HEADER_SIZE + pktlen - MDSHDR_TRAILER_SIZE;
+
+ eof = tvb_get_guint8 (tvb, trailer_start);
+ tvb_set_reported_length (tvb, MDSHDR_HEADER_SIZE+pktlen);
+ }
+ else {
+ eof = MDSHDR_EOF_UNKNOWN;
+ }
+
+ pinfo->src_idx = (tvb_get_ntohs (tvb, MDSHDR_SIDX_OFFSET) & 0x3FF);
+ pinfo->dst_idx = (tvb_get_ntohs (tvb, MDSHDR_DIDX_OFFSET) & 0xFFC) >> 6;
+ pinfo->vsan = vsan;
+ pinfo->sof_eof = 0;
+
+ if ((sof == MDSHDR_SOFi3) || (sof == MDSHDR_SOFi2) || (sof == MDSHDR_SOFi1)
+ || (sof == MDSHDR_SOFi4)) {
+ pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
+ }
+ else if (sof == MDSHDR_SOFf) {
+ pinfo->sof_eof = PINFO_SOF_SOFF;
+ }
+
+ if (eof != MDSHDR_EOFn) {
+ pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
+ }
+ else if (eof != MDSHDR_EOFt) {
+ pinfo->sof_eof |= PINFO_EOF_INVALID;
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+
+ /* create display subtree for the protocol */
+ ti_main = proto_tree_add_protocol_format (tree, proto_mdshdr, tvb, 0,
+ MDSHDR_HEADER_SIZE+pktlen,
+ "MDS Header(%s/%s)",
+ val_to_str(sof, sof_vals, "Unknown(%u)"),
+ val_to_str(eof, eof_vals, "Unknown(%u)"));
+
+ mdshdr_tree_main = proto_item_add_subtree (ti_main, ett_mdshdr);
+
+ /* Add Header part as subtree first */
+ ti_hdr = proto_tree_add_text (mdshdr_tree_main, tvb, MDSHDR_VER_OFFSET,
+ MDSHDR_HEADER_SIZE, "MDS Header");
+
+ mdshdr_tree_hdr = proto_item_add_subtree (ti_hdr, ett_mdshdr_hdr);
+ proto_tree_add_item_hidden (mdshdr_tree_hdr, hf_mdshdr_sof, tvb, MDSHDR_SOF_OFFSET,
+ MDSHDR_SIZE_BYTE, 0);
+ proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_pkt_len, tvb, MDSHDR_PKTLEN_OFFSET,
+ MDSHDR_SIZE_INT16, 0);
+ proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_dstidx, tvb, MDSHDR_DIDX_OFFSET,
+ MDSHDR_SIZE_INT16, 0);
+ proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_srcidx, tvb, MDSHDR_SIDX_OFFSET,
+ MDSHDR_SIZE_INT16, 0);
+ proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_vsan, tvb, MDSHDR_VSAN_OFFSET,
+ MDSHDR_SIZE_INT16, 0);
+ proto_tree_add_uint_hidden(mdshdr_tree_hdr, hf_mdshdr_span,
+ tvb, MDSHDR_VSAN_OFFSET,
+ MDSHDR_SIZE_BYTE, span_id);
+
+ /* Add Mdshdr Trailer part */
+ if (tvb_bytes_exist (tvb, 0, MDSHDR_HEADER_SIZE+pktlen)) {
+ ti_trlr = proto_tree_add_text (mdshdr_tree_main, tvb, trailer_start,
+ MDSHDR_TRAILER_SIZE,
+ "MDS Trailer");
+ mdshdr_tree_trlr = proto_item_add_subtree (ti_trlr, ett_mdshdr_trlr);
+
+ proto_tree_add_item (mdshdr_tree_trlr, hf_mdshdr_eof, tvb,
+ trailer_start, MDSHDR_SIZE_BYTE, 0);
+ proto_tree_add_item (mdshdr_tree_trlr, hf_mdshdr_fccrc, tvb,
+ trailer_start+2, MDSHDR_SIZE_INT32, 0);
+ }
+ }
+
+ /* If this protocol has a sub-dissector call it here, see section 1.8 */
+ if (tvb_bytes_exist (tvb, 0, MDSHDR_HEADER_SIZE+pktlen)) {
+ next_tvb = tvb_new_subset (tvb, MDSHDR_HEADER_SIZE, pktlen, pktlen);
+ }
+ else {
+ next_tvb = tvb_new_subset (tvb, MDSHDR_HEADER_SIZE, -1, -1);
+ }
+
+ /* Call the Fibre Channel dissector */
+ if (fc_dissector_handle) {
+ call_dissector (fc_dissector_handle, next_tvb, pinfo, tree);
+ }
+ else {
+ call_dissector (data_handle, next_tvb, pinfo, tree);
+ }
+}
+
+
+/* Register the protocol with Ethereal. This format is require because a script
+ * is used to build the C function that calls all the protocol registration.
+ */
+
+void
+proto_register_mdshdr(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_mdshdr_sof,
+ {"SOF", "mdshdr.sof", FT_UINT8, BASE_DEC, VALS(sof_vals), 0x0, "", HFILL}},
+ { &hf_mdshdr_pkt_len,
+ {"Packet Len", "mdshdr.plen", FT_UINT16, BASE_DEC, NULL, 0x1FFF, "", HFILL}},
+ { &hf_mdshdr_dstidx,
+ {"Dst Index", "mdshdr.dstidx", FT_UINT16, BASE_HEX, NULL, 0xFFC, "", HFILL}},
+ { &hf_mdshdr_srcidx,
+ {"Src Index", "mdshdr.srcidx", FT_UINT16, BASE_HEX, NULL, 0x3FF, "", HFILL}},
+ { &hf_mdshdr_vsan,
+ {"VSAN", "mdshdr.vsan", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "", HFILL}},
+ { &hf_mdshdr_eof,
+ {"EOF", "mdshdr.eof", FT_UINT8, BASE_DEC, VALS(eof_vals), 0x0, "", HFILL}},
+ { &hf_mdshdr_span,
+ {"SPAN Frame", "mdshdr.span", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_mdshdr_fccrc,
+ {"CRC", "mdshdr.crc", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_mdshdr,
+ &ett_mdshdr_hdr,
+ &ett_mdshdr_trlr
+ };
+ module_t *mdshdr_module;
+
+/* Register the protocol name and description */
+ proto_mdshdr = proto_register_protocol("MDS Header", "MDS Header", "mdshdr");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_mdshdr, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ mdshdr_module = prefs_register_protocol (proto_mdshdr, proto_reg_handoff_mdshdr);
+ prefs_register_bool_preference (mdshdr_module, "decode_if_etype_zero",
+ "Decode as MDS Header if Ethertype == 0",
+ "A frame is considered for decoding as MDSHDR if either "
+ "ethertype is 0xFCFC or zero. Turn this flag off if you "
+ "you don't want ethertype zero to be decoded as MDSHDR. "
+ "This might be useful to avoid problems with test frames.",
+ &decode_if_zero_etype);
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_mdshdr(void)
+{
+ static dissector_handle_t mdshdr_handle;
+ static gboolean registered_for_zero_etype = FALSE;
+ static gboolean mdshdr_prefs_initialized = FALSE;
+
+ if (!mdshdr_prefs_initialized) {
+ /*
+ * This is the first time this has been called (i.e.,
+ * Ethereal/Tethereal is starting up), so create a handle for
+ * the MDS Header dissector, register the dissector for
+ * ethertype ETHERTYPE_FCFT, and fetch the data and Fibre
+ * Channel handles.
+ */
+ mdshdr_handle = create_dissector_handle (dissect_mdshdr, proto_mdshdr);
+ dissector_add ("ethertype", ETHERTYPE_FCFT, mdshdr_handle);
+ data_handle = find_dissector ("data");
+ fc_dissector_handle = find_dissector ("fc");
+ mdshdr_prefs_initialized = TRUE;
+ }
+
+ /*
+ * Only register the dissector for ethertype 0 if the preference
+ * is set to do so.
+ */
+ if (decode_if_zero_etype) {
+ /*
+ * The preference to register for ethertype ETHERTYPE_UNK (0)
+ * is set; if we're not registered for ethertype ETHERTYPE_UNK,
+ * do so.
+ */
+ if (!registered_for_zero_etype) {
+ dissector_add ("ethertype", ETHERTYPE_UNK, mdshdr_handle);
+ registered_for_zero_etype = TRUE;
+ }
+ } else {
+ /*
+ * The preference to register for ethertype ETHERTYPE_UNK (0)
+ * is not set; if we're registered for ethertype ETHERTYPE_UNK,
+ * undo that registration.
+ */
+ if (registered_for_zero_etype) {
+ dissector_delete ("ethertype", ETHERTYPE_UNK, mdshdr_handle);
+ registered_for_zero_etype = FALSE;
+ }
+ }
+}
diff --git a/epan/dissectors/packet-media.c b/epan/dissectors/packet-media.c
new file mode 100644
index 0000000000..726da7a292
--- /dev/null
+++ b/epan/dissectors/packet-media.c
@@ -0,0 +1,88 @@
+/* packet-media.c
+ * Routines for displaying an undissected media type (default case),
+ * based on the generic "data" dissector.
+ *
+ * (C) Olivier Biot, 2004
+ *
+ * $Id$
+ *
+ * Refer to the AUTHORS file or the AUTHORS section in the man page
+ * for contacting the author(s) of this file.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+/* proto_media cannot be static because it's referenced in the
+ * print routines
+ */
+int proto_media = -1;
+
+static void
+dissect_media(tvbuff_t *tvb, packet_info *pinfo , proto_tree *tree)
+{
+ int bytes;
+
+ /* Add media type to the INFO column if it is visible */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", pinfo->match_string);
+ }
+
+ if (tree) {
+ bytes = tvb_length_remaining(tvb, 0);
+ if (bytes > 0) {
+ if (pinfo->private_data) {
+ /* The media type has parameters */
+ proto_tree_add_protocol_format(tree, proto_media, tvb, 0, bytes,
+ "Media Type: %s; %s (%d byte%s)",
+ pinfo->match_string, (char *)pinfo->private_data,
+ bytes, plurality(bytes, "", "s"));
+ } else {
+ /* The media type has no parameters */
+ proto_tree_add_protocol_format(tree, proto_media, tvb, 0, bytes,
+ "Media Type: %s (%d byte%s)",
+ pinfo->match_string,
+ bytes, plurality(bytes, "", "s"));
+ }
+ }
+ }
+}
+
+void
+proto_register_media(void)
+{
+ proto_media = proto_register_protocol (
+ "Media Type", /* name */
+ "Media", /* short name */
+ "media" /* abbrev */
+ );
+ register_dissector("media", dissect_media, proto_media);
+
+ /*
+ * "Media" is used to dissect something whose normal dissector
+ * is disabled, so it cannot itself be disabled.
+ */
+ proto_set_cant_toggle(proto_media);
+}
diff --git a/epan/dissectors/packet-mip.c b/epan/dissectors/packet-mip.c
new file mode 100644
index 0000000000..ce2e46bd80
--- /dev/null
+++ b/epan/dissectors/packet-mip.c
@@ -0,0 +1,519 @@
+/* packet-mip.c
+ * Routines for Mobile IP dissection
+ * Copyright 2000, Stefan Raab <sraab@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <glib.h>
+#include <time.h>
+
+#include <epan/packet.h>
+
+/* Initialize the protocol and registered fields */
+static int proto_mip = -1;
+static int hf_mip_type = -1;
+static int hf_mip_flags = -1;
+static int hf_mip_s = -1;
+static int hf_mip_b = -1;
+static int hf_mip_d = -1;
+static int hf_mip_m = -1;
+static int hf_mip_g = -1;
+static int hf_mip_v = -1;
+static int hf_mip_t = -1;
+static int hf_mip_code = -1;
+static int hf_mip_life = -1;
+static int hf_mip_homeaddr = -1;
+static int hf_mip_haaddr = -1;
+static int hf_mip_coa = -1;
+static int hf_mip_ident = -1;
+static int hf_mip_ext_type = -1;
+static int hf_mip_ext_stype = -1;
+static int hf_mip_ext_len = -1;
+static int hf_mip_ext = -1;
+static int hf_mip_aext_spi = -1;
+static int hf_mip_aext_auth = -1;
+static int hf_mip_next_nai = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_mip = -1;
+static gint ett_mip_flags = -1;
+static gint ett_mip_ext = -1;
+static gint ett_mip_exts = -1;
+
+/* Port used for Mobile IP */
+#define UDP_PORT_MIP 434
+#define NTP_BASETIME 2208988800ul
+
+typedef enum {
+ REGISTRATION_REQUEST = 1,
+ REGISTRATION_REPLY = 3
+} mipMessageTypes;
+
+static const value_string mip_types[] = {
+ {REGISTRATION_REQUEST, "Registration Request"},
+ {REGISTRATION_REPLY, "Registration Reply"},
+ {0, NULL},
+};
+
+static const value_string mip_reply_codes[]= {
+ {0, "Reg Accepted"},
+ {1, "Reg Accepted, but Simultaneous Bindings Unsupported."},
+ {64, "Reg Deny (FA)- Unspecified Reason"},
+ {65, "Reg Deny (FA)- Administratively Prohibited"},
+ {66, "Reg Deny (FA)- Insufficient Resources"},
+ {67, "Reg Deny (FA)- MN failed Authentication"},
+ {68, "Reg Deny (FA)- HA failed Authentication"},
+ {69, "Reg Deny (FA)- Requested Lifetime too Long"},
+ {70, "Reg Deny (FA)- Poorly Formed Request"},
+ {71, "Reg Deny (FA)- Poorly Formed Reply"},
+ {72, "Reg Deny (FA)- Requested Encapsulation Unavailable"},
+ {73, "Reg Deny (FA)- VJ Compression Unavailable"},
+ {74, "Reg Deny (FA)- Requested Reverse Tunnel Unavailable"},
+ {75, "Reg Deny (FA)- Reverse Tunnel is Mandatory and 'T' Bit Not Set"},
+ {76, "Reg Deny (FA)- Mobile Node Too Distant"},
+ {79, "Reg Deny (FA)- Delivery Style Not Supported"},
+ {80, "Reg Deny (FA)- Home Network Unreachable"},
+ {81, "Reg Deny (FA)- HA Host Unreachable"},
+ {82, "Reg Deny (FA)- HA Port Unreachable"},
+ {88, "Reg Deny (FA)- HA Unreachable"},
+ {96, "Reg Deny (FA)(NAI) - Non Zero Home Address Required"},
+ {97, "Reg Deny (FA)(NAI) - Missing NAI"},
+ {98, "Reg Deny (FA)(NAI) - Missing Home Agent"},
+ {99, "Reg Deny (FA)(NAI) - Missing Home Address"},
+ {128, "Reg Deny (HA)- Unspecified"},
+ {129, "Reg Deny (HA)- Administratively Prohibited"},
+ {130, "Reg Deny (HA)- Insufficient Resources"},
+ {131, "Reg Deny (HA)- MN Failed Authentication"},
+ {132, "Reg Deny (HA)- FA Failed Authentication"},
+ {133, "Reg Deny (HA)- Registration ID Mismatch"},
+ {134, "Reg Deny (HA)- Poorly Formed Request"},
+ {135, "Reg Deny (HA)- Too Many Simultaneous Bindings"},
+ {136, "Reg Deny (HA)- Unknown HA Address"},
+ {137, "Reg Deny (HA)- Requested Reverse Tunnel Unavailable"},
+ {138, "Reg Deny (HA)- Reverse Tunnel is Mandatory and 'T' Bit Not Set"},
+ {139, "Reg Deny (HA)- Requested Encapsulation Unavailable"},
+ {0, NULL},
+};
+
+typedef enum {
+ MH_AUTH_EXT = 32,
+ MF_AUTH_EXT = 33,
+ FH_AUTH_EXT = 34,
+ GEN_AUTH_EXT = 36, /* RFC 3012 */
+ OLD_CVSE_EXT = 37, /* RFC 3115 */
+ CVSE_EXT = 38, /* RFC 3115 */
+ MN_NAI_EXT = 131,
+ MF_CHALLENGE_EXT = 132, /* RFC 3012 */
+ OLD_NVSE_EXT = 133, /* RFC 3115 */
+ NVSE_EXT = 134 /* RFC 3115 */
+} MIP_EXTS;
+static const value_string mip_ext_types[]= {
+ {MH_AUTH_EXT, "Mobile-Home Authentication Extension"},
+ {MF_AUTH_EXT, "Mobile-Foreign Authentication Extension"},
+ {FH_AUTH_EXT, "Foreign-Home Authentication Extension"},
+ {MN_NAI_EXT, "Mobile Node NAI Extension"},
+ {GEN_AUTH_EXT, "Generalized Mobile-IP Authentication Extension"},
+ {MF_CHALLENGE_EXT, "MN-FA Challenge Extension"},
+ {CVSE_EXT, "Critical Vendor/Organization Specific Extension"},
+ {OLD_CVSE_EXT, "Critical Vendor/Organization Specific Extension"},
+ {NVSE_EXT, "Normal Vendor/Organization Specific Extension"},
+ {OLD_NVSE_EXT, "Normal Vendor/Organization Specific Extension"},
+ {0, NULL},
+};
+
+static const value_string mip_ext_stypes[]= {
+ {1, "MN AAA Extension"},
+ {0, NULL},
+};
+/* Code to dissect extensions */
+static void
+dissect_mip_extensions( tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *exts_tree=NULL;
+ proto_tree *ext_tree;
+ size_t ext_len;
+ guint8 ext_type;
+ guint8 ext_subtype=0;
+ size_t hdrLen;
+
+ /* None of this really matters if we don't have a tree */
+ if (!tree) return;
+
+ /* Add our tree, if we have extensions */
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "Extensions");
+ exts_tree = proto_item_add_subtree(ti, ett_mip_exts);
+
+ /* And, handle each extension */
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+
+ /* Get our extension info */
+ ext_type = tvb_get_guint8(tvb, offset);
+ if (ext_type == GEN_AUTH_EXT) {
+ /*
+ * Very nasty . . breaks normal extensions, since the length is
+ * in the wrong place :(
+ */
+ ext_subtype = tvb_get_guint8(tvb, offset + 1);
+ ext_len = tvb_get_ntohs(tvb, offset + 2);
+ hdrLen = 4;
+ } else {
+ ext_len = tvb_get_guint8(tvb, offset + 1);
+ hdrLen = 2;
+ }
+
+ ti = proto_tree_add_text(exts_tree, tvb, offset, ext_len + hdrLen,
+ "Extension: %s",
+ val_to_str(ext_type, mip_ext_types,
+ "Unknown Extension %u"));
+ ext_tree = proto_item_add_subtree(ti, ett_mip_ext);
+
+ proto_tree_add_item(ext_tree, hf_mip_ext_type, tvb, offset, 1, ext_type);
+ offset++;
+ if (ext_type != GEN_AUTH_EXT) {
+ /* Another nasty hack since GEN_AUTH_EXT broke everything */
+ proto_tree_add_uint(ext_tree, hf_mip_ext_len, tvb, offset, 1, ext_len);
+ offset++;
+ }
+
+ switch(ext_type) {
+ case MH_AUTH_EXT:
+ case MF_AUTH_EXT:
+ case FH_AUTH_EXT:
+ /* All these extensions look the same. 4 byte SPI followed by a key */
+ proto_tree_add_item(ext_tree, hf_mip_aext_spi, tvb, offset, 4, FALSE);
+ proto_tree_add_item(ext_tree, hf_mip_aext_auth, tvb, offset+4, ext_len-4,
+ FALSE);
+ break;
+ case MN_NAI_EXT:
+ proto_tree_add_item(ext_tree, hf_mip_next_nai, tvb, offset,
+ ext_len, FALSE);
+ break;
+
+ case GEN_AUTH_EXT: /* RFC 3012 */
+ /*
+ * Very nasty . . breaks normal extensions, since the length is
+ * in the wrong place :(
+ */
+ proto_tree_add_uint(ext_tree, hf_mip_ext_stype, tvb, offset, 1, ext_subtype);
+ offset++;
+ proto_tree_add_uint(ext_tree, hf_mip_ext_len, tvb, offset, 2, ext_len);
+ offset+=2;
+ /* SPI */
+ proto_tree_add_item(ext_tree, hf_mip_aext_spi, tvb, offset, 4, FALSE);
+ /* Key */
+ proto_tree_add_item(ext_tree, hf_mip_aext_auth, tvb, offset + 4,
+ ext_len - 4, FALSE);
+
+ break;
+ case OLD_CVSE_EXT: /* RFC 3115 */
+ case CVSE_EXT: /* RFC 3115 */
+ case OLD_NVSE_EXT: /* RFC 3115 */
+ case NVSE_EXT: /* RFC 3115 */
+ case MF_CHALLENGE_EXT: /* RFC 3012 */
+ /* The default dissector is good here. The challenge is all hex anyway. */
+ default:
+ proto_tree_add_item(ext_tree, hf_mip_ext, tvb, offset, ext_len, FALSE);
+ break;
+ } /* ext type */
+
+ offset += ext_len;
+ } /* while data remaining */
+
+} /* dissect_mip_extensions */
+
+/* Code to actually dissect the packets */
+static void
+dissect_mip( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Set up structures we will need to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *mip_tree=NULL;
+ proto_item *tf;
+ proto_tree *flags_tree;
+ guint8 type;
+ guint8 flags;
+ nstime_t ident_time;
+ size_t offset=0;
+
+ /* Make entries in Protocol column and Info column on summary display */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MobileIP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ type = tvb_get_guint8(tvb, offset);
+ switch (type) {
+ case REGISTRATION_REQUEST:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Request: HAddr=%s COA=%s",
+ ip_to_str(tvb_get_ptr(tvb, 4, 4)),
+ ip_to_str(tvb_get_ptr(tvb,12,4)));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
+ mip_tree = proto_item_add_subtree(ti, ett_mip);
+
+ /* type */
+ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
+ offset++;
+
+ /* flags */
+ flags = tvb_get_guint8(tvb, offset);
+ tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb,
+ offset, 1, flags);
+ flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
+ proto_tree_add_boolean(flags_tree, hf_mip_s, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_mip_b, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_mip_d, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_mip_m, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_mip_g, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_mip_v, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_mip_t, tvb, offset, 1, flags);
+ offset++;
+
+ /* lifetime */
+ proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE);
+ offset +=2;
+
+ /* home address */
+ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* home agent address */
+ proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Care of Address */
+ proto_tree_add_item(mip_tree, hf_mip_coa, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Identifier */
+ ident_time.secs = tvb_get_ntohl(tvb,16)-(guint32) NTP_BASETIME;
+ ident_time.nsecs = tvb_get_ntohl(tvb,20)*1000;
+ proto_tree_add_time(mip_tree, hf_mip_ident, tvb, offset, 8, &ident_time);
+ offset += 8;
+
+ } /* if tree */
+ break;
+ case REGISTRATION_REPLY:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Reply: HAddr=%s, Code=%u",
+ ip_to_str(tvb_get_ptr(tvb,4,4)), tvb_get_guint8(tvb,1));
+
+ if (tree) {
+ /* Add Subtree */
+ ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
+ mip_tree = proto_item_add_subtree(ti, ett_mip);
+
+ /* Type */
+ proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
+ offset++;
+
+ /* Reply Code */
+ proto_tree_add_item(mip_tree, hf_mip_code, tvb, offset, 1, FALSE);
+ offset++;
+
+ /* Registration Lifetime */
+ proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* Home address */
+ proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Home Agent Address */
+ proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* Identifier */
+ ident_time.secs = tvb_get_ntohl(tvb,12)-(guint32) NTP_BASETIME;
+ ident_time.nsecs = tvb_get_ntohl(tvb,16)*1000;
+ proto_tree_add_time(mip_tree, hf_mip_ident, tvb, offset, 8, &ident_time);
+ offset += 8;
+ } /* if tree */
+
+ break;
+ } /* End switch */
+
+ if (tree) {
+ if (tvb_reported_length_remaining(tvb, offset) > 0)
+ dissect_mip_extensions(tvb, offset, mip_tree);
+ }
+} /* dissect_mip */
+
+/* Register the protocol with Ethereal */
+void proto_register_mip(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_mip_type,
+ { "Message Type", "mip.type",
+ FT_UINT8, BASE_DEC, VALS(mip_types), 0,
+ "Mobile IP Message type.", HFILL }
+ },
+ { &hf_mip_flags,
+ {"Flags", "mip.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_mip_s,
+ {"Simultaneous Bindings", "mip.s",
+
+ FT_BOOLEAN, 8, NULL, 128,
+ "Simultaneous Bindings Allowed", HFILL }
+ },
+ { &hf_mip_b,
+ {"Broadcast Datagrams", "mip.b",
+ FT_BOOLEAN, 8, NULL, 64,
+ "Broadcast Datagrams requested", HFILL }
+ },
+ { &hf_mip_d,
+ { "Co-lcated Care-of Address", "mip.d",
+ FT_BOOLEAN, 8, NULL, 32,
+ "MN using Co-located Care-of address", HFILL }
+ },
+ { &hf_mip_m,
+ {"Minimal Encapsulation", "mip.m",
+ FT_BOOLEAN, 8, NULL, 16,
+ "MN wants Minimal encapsulation", HFILL }
+ },
+ { &hf_mip_g,
+ {"GRE", "mip.g",
+ FT_BOOLEAN, 8, NULL, 8,
+ "MN wants GRE encapsulation", HFILL }
+ },
+ { &hf_mip_v,
+ { "Van Jacobson", "mip.v",
+ FT_BOOLEAN, 8, NULL, 4,
+ "Van Jacobson", HFILL }
+ },
+ { &hf_mip_t,
+ { "Reverse Tunneling", "mip.t",
+ FT_BOOLEAN, 8, NULL, 2,
+ "Reverse tunneling requested", HFILL }
+ },
+ { &hf_mip_code,
+ { "Reply Code", "mip.code",
+ FT_UINT8, BASE_DEC, VALS(mip_reply_codes), 0,
+ "Mobile IP Reply code.", HFILL }
+ },
+ { &hf_mip_life,
+ { "Lifetime", "mip.life",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Mobile IP Lifetime.", HFILL }
+ },
+ { &hf_mip_homeaddr,
+ { "Home Address", "mip.homeaddr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Mobile Node's home address.", HFILL }
+ },
+
+ { &hf_mip_haaddr,
+ { "Home Agent", "mip.haaddr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Home agent IP Address.", HFILL }
+ },
+ { &hf_mip_coa,
+ { "Care of Address", "mip.coa",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Care of Address.", HFILL }
+ },
+ { &hf_mip_ident,
+ { "Identification", "mip.ident",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0,
+ "MN Identification.", HFILL }
+ },
+ { &hf_mip_ext_type,
+ { "Extension Type", "mip.ext.type",
+ FT_UINT8, BASE_DEC, VALS(mip_ext_types), 0,
+ "Mobile IP Extension Type.", HFILL }
+ },
+ { &hf_mip_ext_stype,
+ { "Gen Auth Ext SubType", "mip.ext.auth.subtype",
+ FT_UINT8, BASE_DEC, VALS(mip_ext_stypes), 0,
+ "Mobile IP Auth Extension Sub Type.", HFILL }
+ },
+ { &hf_mip_ext_len,
+ { "Extension Length", "mip.ext.len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Mobile IP Extension Length.", HFILL }
+ },
+ { &hf_mip_ext,
+ { "Extension", "mip.extension",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Extension", HFILL }
+ },
+ { &hf_mip_aext_spi,
+ { "SPI", "mip.auth.spi",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Authentication Header Security Parameter Index.", HFILL }
+ },
+ { &hf_mip_aext_auth,
+ { "Authenticator", "mip.auth.auth",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "Authenticator.", HFILL }
+ },
+ { &hf_mip_next_nai,
+ { "NAI", "mip.nai",
+ FT_STRING, BASE_NONE, NULL, 0,
+ "NAI", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_mip,
+ &ett_mip_flags,
+ &ett_mip_ext,
+ &ett_mip_exts,
+ };
+
+ /* Register the protocol name and description */
+ proto_mip = proto_register_protocol("Mobile IP", "Mobile IP", "mip");
+
+ /* Register the dissector by name */
+ register_dissector("mip", dissect_mip, proto_mip);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_mip, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mip(void)
+{
+ dissector_handle_t mip_handle;
+
+ mip_handle = find_dissector("mip");
+ dissector_add("udp.port", UDP_PORT_MIP, mip_handle);
+}
diff --git a/epan/dissectors/packet-mip6.c b/epan/dissectors/packet-mip6.c
new file mode 100644
index 0000000000..cf0cf16b37
--- /dev/null
+++ b/epan/dissectors/packet-mip6.c
@@ -0,0 +1,692 @@
+/* packet-mip6.c
+ *
+ * $Id$
+ *
+ * Routines for Mobile IPv6 dissection (draft-ietf-mobileip-ipv6-20.txt)
+ * Copyright 2003 Oy L M Ericsson Ab <teemu.rinta-aho@ericsson.fi>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <epan/packet.h>
+
+#include "ipproto.h"
+#include "ip_opts.h"
+#include "packet-mip6.h"
+
+/* Initialize the protocol and registered header fields */
+static int proto_mip6 = -1;
+static int hf_mip6_proto = -1;
+static int hf_mip6_hlen = -1;
+static int hf_mip6_mhtype = -1;
+static int hf_mip6_reserved = -1;
+static int hf_mip6_csum = -1;
+
+static int hf_mip6_hoti_cookie = -1;
+
+static int hf_mip6_coti_cookie = -1;
+
+static int hf_mip6_hot_nindex = -1;
+static int hf_mip6_hot_cookie = -1;
+static int hf_mip6_hot_token = -1;
+
+static int hf_mip6_cot_nindex = -1;
+static int hf_mip6_cot_cookie = -1;
+static int hf_mip6_cot_token = -1;
+
+static int hf_mip6_bu_seqnr = -1;
+static int hf_mip6_bu_a_flag = -1;
+static int hf_mip6_bu_h_flag = -1;
+static int hf_mip6_bu_l_flag = -1;
+static int hf_mip6_bu_k_flag = -1;
+static int hf_mip6_bu_lifetime = -1;
+
+static int hf_mip6_ba_status = -1;
+static int hf_mip6_ba_k_flag = -1;
+static int hf_mip6_ba_seqnr = -1;
+static int hf_mip6_ba_lifetime = -1;
+
+static int hf_mip6_be_status = -1;
+static int hf_mip6_be_haddr = -1;
+
+static int hf_mip6_bra_interval = -1;
+
+static int hf_mip6_acoa_acoa = -1;
+
+static int hf_mip6_ni_hni = -1;
+static int hf_mip6_ni_cni = -1;
+
+static int hf_mip6_bad_auth = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_mip6 = -1;
+static gint ett_mip6_opt_padn = -1;
+static gint ett_mip6_opt_bra = -1;
+static gint ett_mip6_opt_acoa = -1;
+static gint ett_mip6_opt_ni = -1;
+static gint ett_mip6_opt_bad = -1;
+
+/* Functions to dissect the mobility headers */
+
+static int
+dissect_mip6_brr(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+ proto_tree *data_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Binding Refresh Request");
+
+ if (mip6_tree) {
+ ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF,
+ MIP6_BRR_LEN, "Binding Refresh Request");
+ data_tree = proto_item_add_subtree(ti, ett_mip6);
+ }
+
+ return MIP6_DATA_OFF+MIP6_BRR_LEN;
+}
+
+static int
+dissect_mip6_hoti(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+ proto_tree *data_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Home Test Init");
+
+ if (mip6_tree) {
+ ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF,
+ MIP6_HOTI_LEN, "Home Test Init");
+ data_tree = proto_item_add_subtree(ti, ett_mip6);
+
+ proto_tree_add_item(data_tree, hf_mip6_hoti_cookie, tvb,
+ MIP6_HOTI_COOKIE_OFF, MIP6_HOTI_COOKIE_LEN, FALSE);
+ }
+
+ return MIP6_DATA_OFF+MIP6_HOTI_LEN;
+}
+
+static int
+dissect_mip6_coti(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+ proto_tree *data_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Care-of Test Init");
+
+ if (mip6_tree) {
+ ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF,
+ MIP6_COTI_LEN, "Care-of Test Init");
+ data_tree = proto_item_add_subtree(ti, ett_mip6);
+
+ proto_tree_add_item(data_tree, hf_mip6_coti_cookie, tvb,
+ MIP6_COTI_COOKIE_OFF, MIP6_COTI_COOKIE_LEN, FALSE);
+ }
+
+ return MIP6_DATA_OFF+MIP6_COTI_LEN;
+}
+
+static int
+dissect_mip6_hot(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+ proto_tree *data_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Home Test");
+
+ if (mip6_tree) {
+ ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF,
+ MIP6_HOT_LEN, "Home Test");
+ data_tree = proto_item_add_subtree(ti, ett_mip6);
+
+ proto_tree_add_item(data_tree, hf_mip6_hot_nindex, tvb,
+ MIP6_HOT_INDEX_OFF, MIP6_HOT_INDEX_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_hot_cookie, tvb,
+ MIP6_HOT_COOKIE_OFF, MIP6_HOT_COOKIE_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_hot_token, tvb,
+ MIP6_HOT_TOKEN_OFF, MIP6_HOT_TOKEN_LEN, FALSE);
+ }
+
+ return MIP6_DATA_OFF+MIP6_HOT_LEN;
+}
+
+static int
+dissect_mip6_cot(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+ proto_tree *data_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Care-of Test");
+
+ if (mip6_tree) {
+ ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF,
+ MIP6_COT_LEN, "Care-of Test");
+ data_tree = proto_item_add_subtree(ti, ett_mip6);
+
+ proto_tree_add_item(data_tree, hf_mip6_cot_nindex, tvb,
+ MIP6_COT_INDEX_OFF, MIP6_COT_INDEX_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_cot_cookie, tvb,
+ MIP6_COT_COOKIE_OFF, MIP6_COT_COOKIE_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_hot_token, tvb,
+ MIP6_COT_TOKEN_OFF, MIP6_COT_TOKEN_LEN, FALSE);
+ }
+
+ return MIP6_DATA_OFF+MIP6_COT_LEN;
+}
+
+static int
+dissect_mip6_bu(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+ proto_tree *data_tree = NULL;
+ proto_item *ti;
+ int lifetime;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Binding Update");
+
+ if (mip6_tree) {
+ ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF,
+ MIP6_BU_LEN, "Binding Update");
+ data_tree = proto_item_add_subtree(ti, ett_mip6);
+
+ proto_tree_add_item(data_tree, hf_mip6_bu_seqnr, tvb,
+ MIP6_BU_SEQNR_OFF, MIP6_BU_SEQNR_LEN, FALSE);
+
+ proto_tree_add_item(data_tree, hf_mip6_bu_a_flag, tvb,
+ MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_bu_h_flag, tvb,
+ MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_bu_l_flag, tvb,
+ MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_bu_k_flag, tvb,
+ MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
+
+ lifetime = tvb_get_ntohs(tvb, MIP6_BU_LIFETIME_OFF);
+ proto_tree_add_uint_format(data_tree, hf_mip6_bu_lifetime, tvb,
+ MIP6_BU_LIFETIME_OFF,
+ MIP6_BU_LIFETIME_LEN, lifetime,
+ "Lifetime: %d (%ld seconds)",
+ lifetime, (long)lifetime * 4);
+ }
+
+ return MIP6_DATA_OFF+MIP6_BU_LEN;
+}
+
+static int
+dissect_mip6_ba(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+ proto_tree *data_tree = NULL;
+ proto_item *ti;
+ int lifetime;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Binding Acknowledgement");
+
+ if (mip6_tree) {
+ ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF,
+ MIP6_BA_LEN, "Binding Acknowledgement");
+ data_tree = proto_item_add_subtree(ti, ett_mip6);
+
+ proto_tree_add_item(data_tree, hf_mip6_ba_status, tvb,
+ MIP6_BA_STATUS_OFF, MIP6_BA_STATUS_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_ba_k_flag, tvb,
+ MIP6_BA_FLAGS_OFF, MIP6_BA_FLAGS_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_ba_seqnr, tvb,
+ MIP6_BA_SEQNR_OFF, MIP6_BA_SEQNR_LEN, FALSE);
+ lifetime = tvb_get_ntohs(tvb, MIP6_BA_LIFETIME_OFF);
+ proto_tree_add_uint_format(data_tree, hf_mip6_ba_lifetime, tvb,
+ MIP6_BA_LIFETIME_OFF,
+ MIP6_BA_LIFETIME_LEN, lifetime,
+ "Lifetime: %d (%ld seconds)",
+ lifetime, (long)lifetime * 4);
+ }
+
+ return MIP6_DATA_OFF+MIP6_BA_LEN;
+}
+
+static int
+dissect_mip6_be(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+ proto_tree *data_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Binding Error");
+
+ if (mip6_tree) {
+ ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF,
+ MIP6_BE_LEN, "Binding Error");
+ data_tree = proto_item_add_subtree(ti, ett_mip6);
+
+ proto_tree_add_item(data_tree, hf_mip6_be_status, tvb,
+ MIP6_BE_STATUS_OFF, MIP6_BE_STATUS_LEN, FALSE);
+ proto_tree_add_item(data_tree, hf_mip6_be_haddr, tvb,
+ MIP6_BE_HOA_OFF, MIP6_BE_HOA_LEN, FALSE);
+ }
+
+ return MIP6_DATA_OFF+MIP6_BE_LEN;
+}
+
+static int
+dissect_mip6_unknown(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
+{
+ proto_tree *data_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Unknown MH Type");
+
+ if (mip6_tree) {
+ ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF,
+ MIP6_DATA_OFF+1, "Unknown MH Type");
+ data_tree = proto_item_add_subtree(ti, ett_mip6);
+ }
+
+ return MIP6_DATA_OFF+1;
+}
+
+/* Functions to dissect the mobility options */
+
+static void
+dissect_mip6_opt_padn(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint optlen, packet_info *pinfo _U_,
+ proto_tree *opt_tree)
+{
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: %u bytes", optp->name, optlen);
+}
+
+static void
+dissect_mip6_opt_bra(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
+ guint optlen, packet_info *pinfo _U_,
+ proto_tree *opt_tree)
+{
+ int ri;
+
+ ri = tvb_get_ntohs(tvb, offset + MIP6_BRA_RI_OFF);
+ proto_tree_add_uint_format(opt_tree, hf_mip6_bra_interval, tvb,
+ offset, optlen,
+ ri, "Refresh interval: %d (%ld seconds)",
+ ri, (long)ri * 4);
+}
+
+static void
+dissect_mip6_opt_acoa(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
+ guint optlen, packet_info *pinfo _U_,
+ proto_tree *opt_tree)
+{
+ proto_tree_add_ipv6(opt_tree, hf_mip6_acoa_acoa, tvb,
+ offset, optlen,
+ tvb_get_ptr(tvb, offset + MIP6_ACOA_ACOA_OFF, MIP6_ACOA_ACOA_LEN));
+}
+
+static void
+dissect_mip6_opt_ni(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint optlen, packet_info *pinfo _U_,
+ proto_tree *opt_tree)
+{
+ proto_tree *field_tree = NULL;
+ proto_item *tf;
+
+ tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_item(field_tree, hf_mip6_ni_hni, tvb,
+ offset + MIP6_NI_HNI_OFF, MIP6_NI_HNI_LEN, FALSE);
+ proto_tree_add_item(field_tree, hf_mip6_ni_cni, tvb,
+ offset + MIP6_NI_CNI_OFF, MIP6_NI_CNI_LEN, FALSE);
+}
+
+static void
+dissect_mip6_opt_bad(const ip_tcp_opt *optp _U_, tvbuff_t *tvb, int offset,
+ guint optlen, packet_info *pinfo _U_,
+ proto_tree *opt_tree)
+{
+ proto_tree *field_tree = NULL;
+ proto_item *tf;
+
+ tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_item(field_tree, hf_mip6_bad_auth, tvb,
+ offset + MIP6_BAD_AUTH_OFF,
+ optlen - MIP6_BAD_AUTH_OFF, FALSE);
+}
+
+static const ip_tcp_opt mip6_opts[] = {
+ {
+ PAD1,
+ "Pad1",
+ NULL,
+ NO_LENGTH,
+ 0,
+ NULL,
+ },
+ {
+ PADN,
+ "PadN",
+ &ett_mip6_opt_padn,
+ VARIABLE_LENGTH,
+ 0,
+ dissect_mip6_opt_padn
+ },
+ {
+ BRA,
+ "Binding Refresh Advice",
+ &ett_mip6_opt_bra,
+ FIXED_LENGTH,
+ MIP6_BRA_LEN,
+ dissect_mip6_opt_bra
+ },
+ {
+ ACOA,
+ "Alternate Care-of Address",
+ &ett_mip6_opt_acoa,
+ FIXED_LENGTH,
+ MIP6_ACOA_LEN,
+ dissect_mip6_opt_acoa
+ },
+ {
+ NI,
+ "Nonce Indices",
+ &ett_mip6_opt_ni,
+ FIXED_LENGTH,
+ MIP6_NI_LEN,
+ dissect_mip6_opt_ni
+ },
+ {
+ BAD,
+ "Binding Authorization Data",
+ &ett_mip6_opt_bad,
+ VARIABLE_LENGTH,
+ 0,
+ dissect_mip6_opt_bad
+ },
+};
+
+#define N_MIP6_OPTS (sizeof mip6_opts / sizeof mip6_opts[0])
+
+/* Function to dissect mobility options */
+static int
+dissect_mip6_options(tvbuff_t *tvb, proto_tree *mip6_tree, int offset, int len,
+ packet_info *pinfo)
+{
+ proto_tree *opts_tree = NULL;
+ proto_item *ti;
+
+ if (!mip6_tree)
+ return len;
+
+ ti = proto_tree_add_text(mip6_tree, tvb, offset, len,
+ "Mobility Options");
+ opts_tree = proto_item_add_subtree(ti, ett_mip6);
+
+ dissect_ipv6_options(tvb, offset, len,
+ mip6_opts, N_MIP6_OPTS, -1, pinfo, opts_tree);
+
+ return len;
+}
+
+/* Function that dissects the whole MIPv6 packet */
+static void
+dissect_mip6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *mip6_tree = NULL;
+ proto_item *ti;
+ guint8 type;
+ guint len, offset = 0, start_offset = offset;
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MIPv6");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ len = (tvb_get_guint8(tvb, MIP6_HLEN_OFF) + 1) * 8;
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_mip6, tvb, 0, len, FALSE);
+ mip6_tree = proto_item_add_subtree(ti, ett_mip6);
+
+ /* Process header fields */
+ proto_tree_add_uint_format(mip6_tree, hf_mip6_proto, tvb,
+ MIP6_PROTO_OFF, 1,
+ tvb_get_guint8(tvb, MIP6_PROTO_OFF),
+ "Payload protocol: %s (0x%02x)",
+ ipprotostr(
+ tvb_get_guint8(tvb, MIP6_PROTO_OFF)),
+ tvb_get_guint8(tvb, MIP6_PROTO_OFF));
+
+ proto_tree_add_uint_format(mip6_tree, hf_mip6_hlen, tvb,
+ MIP6_HLEN_OFF, 1,
+ tvb_get_guint8(tvb, MIP6_HLEN_OFF),
+ "Header length: %u (%u bytes)",
+ tvb_get_guint8(tvb, MIP6_HLEN_OFF),
+ len);
+
+ proto_tree_add_item(mip6_tree, hf_mip6_mhtype, tvb,
+ MIP6_TYPE_OFF, 1, FALSE);
+
+ proto_tree_add_item(mip6_tree, hf_mip6_reserved, tvb,
+ MIP6_RES_OFF, 1, FALSE);
+
+ proto_tree_add_item(mip6_tree, hf_mip6_csum, tvb,
+ MIP6_CSUM_OFF, 2, FALSE);
+ }
+
+ /* Process mobility header */
+ type = tvb_get_guint8(tvb, MIP6_TYPE_OFF);
+ switch (type) {
+ case BRR:
+ offset = dissect_mip6_brr(tvb, mip6_tree, pinfo);
+ break;
+ case HOTI:
+ offset = dissect_mip6_hoti(tvb, mip6_tree, pinfo);
+ break;
+ case COTI:
+ offset = dissect_mip6_coti(tvb, mip6_tree, pinfo);
+ break;
+ case HOT:
+ offset = dissect_mip6_hot(tvb, mip6_tree, pinfo);
+ break;
+ case COT:
+ offset = dissect_mip6_cot(tvb, mip6_tree, pinfo);
+ break;
+ case BU:
+ offset = dissect_mip6_bu(tvb, mip6_tree, pinfo);
+ break;
+ case BA:
+ offset = dissect_mip6_ba(tvb, mip6_tree, pinfo);
+ break;
+ case BE:
+ offset = dissect_mip6_be(tvb, mip6_tree, pinfo);
+ break;
+ default:
+ dissect_mip6_unknown(tvb, mip6_tree, pinfo);
+ offset = len;
+ break;
+ }
+
+ /* Process mobility options */
+ if (offset < len) {
+ if (len < (offset - start_offset)) {
+ proto_tree_add_text(tree, tvb, 0, 0, "Bogus header length");
+ return;
+ }
+ len -= (offset - start_offset);
+ dissect_mip6_options(tvb, mip6_tree, offset, len, pinfo);
+ }
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_mip6(void)
+{
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+
+ { &hf_mip6_proto, { "Payload protocol", "mip6.proto",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Payload protocol", HFILL }},
+ { &hf_mip6_hlen, { "Header length", "mip6.hlen",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Header length", HFILL }},
+ { &hf_mip6_mhtype, { "Mobility Header Type", "mip6.mhtype",
+ FT_UINT8, BASE_DEC, VALS(mip6_mh_types), 0,
+ "Mobility Header Type", HFILL }},
+ { &hf_mip6_reserved, { "Reserved", "mip6.reserved",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Reserved", HFILL }},
+ { &hf_mip6_csum, { "Checksum", "mip6.csum",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ "Header Checksum", HFILL }},
+
+ { &hf_mip6_hoti_cookie, { "Home Init Cookie", "mip6.hoti.cookie",
+ FT_UINT64, BASE_HEX, NULL, 0,
+ "Home Init Cookie", HFILL }},
+
+ { &hf_mip6_coti_cookie, { "Care-of Init Cookie", "mip6.coti.cookie",
+ FT_UINT64, BASE_HEX, NULL, 0,
+ "Care-of Init Cookie", HFILL }},
+
+ { &hf_mip6_hot_nindex, { "Home Nonce Index", "mip6.hot.nindex",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Home Nonce Index", HFILL }},
+ { &hf_mip6_hot_cookie, { "Home Init Cookie", "mip6.hot.cookie",
+ FT_UINT64, BASE_HEX, NULL, 0,
+ "Home Init Cookie", HFILL }},
+ { &hf_mip6_hot_token, { "Home Keygen Token", "mip6.hot.token",
+ FT_UINT64, BASE_HEX, NULL, 0,
+ "Home Keygen Token", HFILL }},
+
+ { &hf_mip6_cot_nindex, { "Care-of Nonce Index", "mip6.cot.nindex",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Care-of Nonce Index", HFILL }},
+ { &hf_mip6_cot_cookie, { "Care-of Init Cookie", "mip6.cot.cookie",
+ FT_UINT64, BASE_HEX, NULL, 0,
+ "Care-of Init Cookie", HFILL }},
+ { &hf_mip6_cot_token, { "Care-of Keygen Token", "mip6.cot.token",
+ FT_UINT64, BASE_HEX, NULL, 0,
+ "Care-of Keygen Token", HFILL }},
+
+ { &hf_mip6_bu_seqnr, { "Sequence number", "mip6.bu.seqnr",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Sequence number", HFILL }},
+ { &hf_mip6_bu_a_flag, { "Acknowledge (A) flag", "mip6.bu.a_flag",
+ FT_BOOLEAN, 8, TFS(&mip6_bu_a_flag_value),
+ 0x80, "Acknowledge (A) flag", HFILL }},
+ { &hf_mip6_bu_h_flag, { "Home Registration (H) flag",
+ "mip6.bu.h_flag",
+ FT_BOOLEAN, 8, TFS(&mip6_bu_h_flag_value),
+ 0x40, "Home Registration (H) flag", HFILL }},
+ { &hf_mip6_bu_l_flag, { "Link-Local Compatibility (L) flag",
+ "mip6.bu.l_flag",
+ FT_BOOLEAN, 8, TFS(&mip6_bu_l_flag_value),
+ 0x20, "Home Registration (H) flag", HFILL }},
+ { &hf_mip6_bu_k_flag, { "Key Management Compatibility (K) flag",
+ "mip6.bu.k_flag",
+ FT_BOOLEAN, 8, TFS(&mip6_bu_k_flag_value),
+ 0x10, "Key Management Compatibility (K) flag",
+ HFILL }},
+ { &hf_mip6_bu_lifetime, { "Lifetime", "mip6.bu.lifetime",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Lifetime", HFILL }},
+
+ { &hf_mip6_ba_status, { "Status", "mip6.ba.status",
+ FT_UINT8, BASE_DEC,
+ VALS(&mip6_ba_status_value), 0,
+ "Binding Acknowledgement status", HFILL }},
+ { &hf_mip6_ba_k_flag, { "Key Management Compatibility (K) flag",
+ "mip6.ba.k_flag",
+ FT_BOOLEAN, 8, TFS(&mip6_bu_k_flag_value),
+ 0x80, "Key Management Compatibility (K) flag",
+ HFILL }},
+ { &hf_mip6_ba_seqnr, { "Sequence number", "mip6.ba.seqnr",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Sequence number", HFILL }},
+ { &hf_mip6_ba_lifetime, { "Lifetime", "mip6.ba.lifetime",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Lifetime", HFILL }},
+
+ { &hf_mip6_be_status, { "Status", "mip6.be.status",
+ FT_UINT8, BASE_DEC,
+ VALS(&mip6_be_status_value), 0,
+ "Binding Error status", HFILL }},
+ { &hf_mip6_be_haddr, { "Home Address", "mip6.be.haddr",
+ FT_IPv6, BASE_HEX, NULL, 0,
+ "Home Address", HFILL }},
+
+ { &hf_mip6_bra_interval, { "Refresh interval", "mip6.bra.interval",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Refresh interval", HFILL }},
+
+ { &hf_mip6_acoa_acoa, { "Alternate care-of address", "mip6.acoa.acoa",
+ FT_IPv6, BASE_HEX, NULL, 0,
+ "Alternate Care-of address", HFILL }},
+
+ { &hf_mip6_ni_hni, { "Home nonce index", "mip6.ni.hni",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Home nonce index", HFILL }},
+ { &hf_mip6_ni_cni, { "Care-of nonce index", "mip6.ni.cni",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Care-of nonce index", HFILL }},
+
+ { &hf_mip6_bad_auth, { "Authenticator", "mip6.bad.auth",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "Care-of nonce index", HFILL }}
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_mip6,
+ &ett_mip6_opt_padn,
+ &ett_mip6_opt_bra,
+ &ett_mip6_opt_acoa,
+ &ett_mip6_opt_ni,
+ &ett_mip6_opt_bad,
+ };
+
+ /* Register the protocol name and description */
+ proto_mip6 = proto_register_protocol("Mobile IPv6", "MIPv6", "mipv6");
+
+ /* Register the dissector by name */
+ /* register_dissector("mipv6", dissect_mip6, proto_mip6); */
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_mip6, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mip6(void)
+{
+ dissector_handle_t mip6_handle;
+
+ /* mip6_handle = find_dissector("mipv6"); */
+ mip6_handle = create_dissector_handle(dissect_mip6, proto_mip6);
+ dissector_add("ip.proto", IP_PROTO_MIPV6_OLD, mip6_handle);
+ dissector_add("ip.proto", IP_PROTO_MIPV6, mip6_handle);
+}
diff --git a/epan/dissectors/packet-mip6.h b/epan/dissectors/packet-mip6.h
new file mode 100644
index 0000000000..ec3d1ad9b8
--- /dev/null
+++ b/epan/dissectors/packet-mip6.h
@@ -0,0 +1,211 @@
+/* packet-mip6.h
+ *
+ * $Id$
+ *
+ * Definitions for Mobile IPv6 dissection (draft-ietf-mobileip-ipv6-20.txt)
+ * Copyright 2003 Oy L M Ericsson Ab <teemu.rinta-aho@ericsson.fi>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_MIP6_H_DEFINED__
+#define __PACKET_MIP6_H_DEFINED__
+
+/* Mobility Header types */
+typedef enum {
+ BRR = 0,
+ HOTI = 1,
+ COTI = 2,
+ HOT = 3,
+ COT = 4,
+ BU = 5,
+ BA = 6,
+ BE = 7
+} mhTypes;
+
+static const value_string mip6_mh_types[] = {
+ {BRR, "Binding Refresh Request"},
+ {HOTI, "Home Test Init"},
+ {COTI, "Care-of Test Init"},
+ {HOT, "Home Test"},
+ {COT, "Care-of Test"},
+ {BU, "Binding Update"},
+ {BA, "Binding Acknowledgement"},
+ {BE, "Binding Error"},
+ {0, NULL}
+};
+
+/* Mobility Option types */
+typedef enum {
+ PAD1 = 0,
+ PADN = 1,
+ BRA = 2,
+ ACOA = 3,
+ NI = 4,
+ BAD = 5
+} optTypes;
+
+/* Binding Update flag description */
+static const true_false_string mip6_bu_a_flag_value = {
+ "Binding Acknowledgement requested",
+ "Binding Acknowledgement not requested"
+};
+
+static const true_false_string mip6_bu_h_flag_value = {
+ "Home Registration",
+ "No Home Registration"
+};
+
+static const true_false_string mip6_bu_l_flag_value = {
+ "Link-Local Address Compatibility",
+ "No Link-Local Address Compatibility"
+};
+
+static const true_false_string mip6_bu_k_flag_value = {
+ "Key Management Mobility Compatibility",
+ "No Key Management Mobility Compatibility"
+};
+
+/* Binding Acknowledgement status values */
+static const value_string mip6_ba_status_value[] = {
+ { 0, "Binding Update accepted" },
+ { 1, "Accepted but prefix discovery necessary" },
+ { 128, "Reason unspecified" },
+ { 129, "Administratively prohibited" },
+ { 130, "Insufficient resources" },
+ { 131, "Home registration not supported" },
+ { 132, "Not home subnet" },
+ { 133, "Not home agent for this mobile node" },
+ { 134, "Duplicate Address Detection failed" },
+ { 135, "Sequence number out of window" },
+ { 136, "Expired home nonce index" },
+ { 137, "Expired care-of nonce index" },
+ { 138, "Expired nonces" },
+ { 139, "Registration type change disallowed" },
+ { 0, NULL }
+};
+
+/* Binding Error status values */
+static const value_string mip6_be_status_value[] = {
+ { 1, "Unknown binding for Home Address destination option" },
+ { 2, "Unrecognized MH type value" },
+ { 0, NULL }
+};
+
+/* Message lengths */
+#define MIP6_BRR_LEN 2
+#define MIP6_HOTI_LEN 10
+#define MIP6_COTI_LEN 10
+#define MIP6_HOT_LEN 18
+#define MIP6_COT_LEN 18
+#define MIP6_BU_LEN 6
+#define MIP6_BA_LEN 6
+#define MIP6_BE_LEN 18
+
+/* Field offsets & lengths for mobility headers */
+#define MIP6_PROTO_OFF 0
+#define MIP6_HLEN_OFF 1
+#define MIP6_TYPE_OFF 2
+#define MIP6_RES_OFF 3
+#define MIP6_CSUM_OFF 4
+#define MIP6_DATA_OFF 6
+#define MIP6_PROTO_LEN 1
+#define MIP6_HLEN_LEN 1
+#define MIP6_TYPE_LEN 1
+#define MIP6_RES_LEN 1
+#define MIP6_CSUM_LEN 2
+
+#define MIP6_BRR_RES_OFF 6
+#define MIP6_BRR_OPTS_OFF 8
+#define MIP6_BRR_RES_LEN 2
+
+#define MIP6_HOTI_RES_OFF 6
+#define MIP6_HOTI_COOKIE_OFF 8
+#define MIP6_HOTI_OPTS_OFF 16
+#define MIP6_HOTI_RES_LEN 2
+#define MIP6_HOTI_COOKIE_LEN 8
+
+#define MIP6_COTI_RES_OFF 6
+#define MIP6_COTI_COOKIE_OFF 8
+#define MIP6_COTI_OPTS_OFF 16
+#define MIP6_COTI_RES_LEN 2
+#define MIP6_COTI_COOKIE_LEN 8
+
+#define MIP6_HOT_INDEX_OFF 6
+#define MIP6_HOT_COOKIE_OFF 8
+#define MIP6_HOT_TOKEN_OFF 16
+#define MIP6_HOT_OPTS_OFF 24
+#define MIP6_HOT_INDEX_LEN 2
+#define MIP6_HOT_COOKIE_LEN 8
+#define MIP6_HOT_TOKEN_LEN 8
+
+#define MIP6_COT_INDEX_OFF 6
+#define MIP6_COT_COOKIE_OFF 8
+#define MIP6_COT_TOKEN_OFF 16
+#define MIP6_COT_OPTS_OFF 24
+#define MIP6_COT_INDEX_LEN 2
+#define MIP6_COT_COOKIE_LEN 8
+#define MIP6_COT_TOKEN_LEN 8
+
+#define MIP6_BU_SEQNR_OFF 6
+#define MIP6_BU_FLAGS_OFF 8
+#define MIP6_BU_RES_OFF 9
+#define MIP6_BU_LIFETIME_OFF 10
+#define MIP6_BU_OPTS_OFF 12
+#define MIP6_BU_SEQNR_LEN 2
+#define MIP6_BU_FLAGS_LEN 1
+#define MIP6_BU_RES_LEN 1
+#define MIP6_BU_LIFETIME_LEN 2
+
+#define MIP6_BA_STATUS_OFF 6
+#define MIP6_BA_FLAGS_OFF 7
+#define MIP6_BA_SEQNR_OFF 8
+#define MIP6_BA_LIFETIME_OFF 10
+#define MIP6_BA_OPTS_OFF 12
+#define MIP6_BA_STATUS_LEN 1
+#define MIP6_BA_FLAGS_LEN 1
+#define MIP6_BA_SEQNR_LEN 2
+#define MIP6_BA_LIFETIME_LEN 2
+
+#define MIP6_BE_STATUS_OFF 6
+#define MIP6_BE_RES_OFF 7
+#define MIP6_BE_HOA_OFF 8
+#define MIP6_BE_OPTS_OFF 24
+#define MIP6_BE_STATUS_LEN 1
+#define MIP6_BE_RES_LEN 1
+#define MIP6_BE_HOA_LEN 16
+
+/* Field offsets & field and option lengths for mobility options */
+#define MIP6_BRA_LEN 2
+#define MIP6_BRA_RI_OFF 2
+#define MIP6_BRA_RI_LEN 2
+
+#define MIP6_ACOA_LEN 16
+#define MIP6_ACOA_ACOA_OFF 2
+#define MIP6_ACOA_ACOA_LEN 16
+
+#define MIP6_NI_LEN 4
+#define MIP6_NI_HNI_OFF 2
+#define MIP6_NI_CNI_OFF 4
+#define MIP6_NI_HNI_LEN 2
+#define MIP6_NI_CNI_LEN 2
+
+#define MIP6_BAD_AUTH_OFF 2
+
+#endif /* __PACKET_MIP6_H_DEFINED__ */
diff --git a/epan/dissectors/packet-mmse.c b/epan/dissectors/packet-mmse.c
new file mode 100644
index 0000000000..7a55215b3d
--- /dev/null
+++ b/epan/dissectors/packet-mmse.c
@@ -0,0 +1,1670 @@
+/* packet-mmse.c
+ * Routines for MMS Message Encapsulation dissection
+ * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
+ * Copyright 2004, Olivier Biot
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * ----------
+ *
+ * Dissector of an encoded Multimedia message PDU, as defined by the WAPForum
+ * (http://www.wapforum.org) in "WAP-209-MMSEncapsulation-20020105-a".
+ * Subsequent releases of MMS are in control of the Open Mobile Alliance (OMA):
+ * Dissection of MMS 1.1 as in OMA-MMS-ENC-v1.1.
+ * Dissection of MMS 1.2 as in OMA-MMS-ENC-v1.2 (not finished yet).
+ */
+
+/* This file has been edited with 8-space tabs and 4-space indentation */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "packet-wap.h"
+#include "packet-wsp.h"
+/* #include "packet-mmse.h" */ /* We autoregister */
+
+#define MM_QUOTE 0x7F /* Quoted string */
+
+#define MMS_CONTENT_TYPE 0x3E /* WINA-value for mms-message */
+
+/* General-purpose debug logger.
+ * Requires double parentheses because of variable arguments of printf().
+ *
+ * Enable debug logging for MMSE by defining AM_CFLAGS
+ * so that it contains "-DDEBUG_mmse"
+ */
+#ifdef DEBUG_mmse
+#define DebugLog(x) \
+ printf("%s:%u: ", __FILE__, __LINE__); \
+ printf x; \
+ fflush(stdout)
+#else
+#define DebugLog(x) ;
+#endif
+
+
+/*
+ * Forward declarations
+ */
+static void dissect_mmse_standalone(tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_mmse_encapsulated(tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_mmse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 pdut, char *message_type);
+
+/*
+ * Header field values
+ */
+/* MMS 1.0 */
+#define MM_BCC_HDR 0x81 /* Bcc */
+#define MM_CC_HDR 0x82 /* Cc */
+#define MM_CLOCATION_HDR 0x83 /* X-Mms-Content-Location */
+#define MM_CTYPE_HDR 0x84 /* Content-Type */
+#define MM_DATE_HDR 0x85 /* Date */
+#define MM_DREPORT_HDR 0x86 /* X-Mms-Delivery-Report */
+#define MM_DTIME_HDR 0x87 /* X-Mms-Delivery-Time */
+#define MM_EXPIRY_HDR 0x88 /* X-Mms-Expiry */
+#define MM_FROM_HDR 0x89 /* From */
+#define MM_MCLASS_HDR 0x8A /* X-Mms-Message-Class */
+#define MM_MID_HDR 0x8B /* Message-ID */
+#define MM_MTYPE_HDR 0x8C /* X-Mms-Message-Type */
+#define MM_VERSION_HDR 0x8D /* X-Mms-MMS-Version */
+#define MM_MSIZE_HDR 0x8E /* X-Mms-Message-Size */
+#define MM_PRIORITY_HDR 0x8F /* X-Mms-Priority */
+#define MM_RREPLY_HDR 0x90 /* X-Mms-Read-Reply */
+#define MM_RALLOWED_HDR 0x91 /* X-Mms-Report-Allowed */
+#define MM_RSTATUS_HDR 0x92 /* X-Mms-Response-Status */
+#define MM_RTEXT_HDR 0x93 /* X-Mms-Response-Text */
+#define MM_SVISIBILITY_HDR 0x94 /* X-Mms-Sender-Visibility */
+#define MM_STATUS_HDR 0x95 /* X-Mms-Status */
+#define MM_SUBJECT_HDR 0x96 /* Subject */
+#define MM_TO_HDR 0x97 /* To */
+#define MM_TID_HDR 0x98 /* X-Mms-Transaction-Id */
+/* MMS 1.1 */
+#define MM_RETRIEVE_STATUS_HDR 0x99 /* X-Mms-Retrieve-Status */
+#define MM_RETRIEVE_TEXT_HDR 0x9A /* X-Mms-Retrieve-Text */
+#define MM_READ_STATUS_HDR 0x9B /* X-Mms-Read-Status */
+#define MM_REPLY_CHARGING_HDR 0x9C /* X-Mms-Reply-Charging */
+#define MM_REPLY_CHARGING_DEADLINE_HDR \
+ 0x9D /* X-Mms-Reply-Charging-Deadline*/
+#define MM_REPLY_CHARGING_ID_HDR \
+ 0x9E /* X-Mms-Reply-Charging-ID */
+#define MM_REPLY_CHARGING_SIZE_HDR \
+ 0x9F /* X-Mms-Reply-Charging-Size */
+#define MM_PREV_SENT_BY_HDR 0xA0 /* X-Mms-Previously-Sent-By */
+#define MM_PREV_SENT_DATE_HDR 0xA1 /* X-Mms-Previously-Sent-Date */
+/* MMS 1.2 */
+#define MM_STORE_HDR 0xA2 /* X-Mms-Store */
+#define MM_MM_STATE_HDR 0xA3 /* X-Mms-MM-State */
+#define MM_MM_FLAGS_HDR 0xA4 /* X-Mms-MM-Flags */
+#define MM_STORE_STATUS_HDR 0xA5 /* X-Mms-Store-Status */
+#define MM_STORE_STATUS_TEXT_HDR \
+ 0xA6 /* X-Mms-Store-Status-Text */
+#define MM_STORED_HDR 0xA7 /* X-Mms-Stored */
+#define MM_ATTRIBUTES_HDR 0xA8 /* X-Mms-Attributes */
+#define MM_TOTALS_HDR 0xA9 /* X-Mms-Totals */
+#define MM_MBOX_TOTALS_HDR 0xAA /* X-Mms-Mbox-Totals */
+#define MM_QUOTAS_HDR 0xAB /* X-Mms-Quotas */
+#define MM_MBOX_QUOTAS_HDR 0xAC /* X-Mms-Mbox-Quotas */
+#define MM_MBOX_MSG_COUNT_HDR 0xAD /* X-Mms-Message-Count */
+#define MM_CONTENT_HDR 0xAE /* Content */
+#define MM_START_HDR 0xAF /* X-Mms-Start */
+#define MM_ADDITIONAL_HDR 0xB0 /* Additional-headers */
+#define MM_DISTRIBUION_IND_HDR 0xB1 /* X-Mms-Distribution-Indcator */
+#define MM_ELEMENT_DESCR_HDR 0xB2 /* X-Mms-Element-Descriptor */
+#define MM_LIMIT_HDR 0xB3 /* X-Mms-Limit */
+
+static const value_string vals_mm_header_names[] = {
+ /* MMS 1.0 */
+ { MM_BCC_HDR, "Bcc" },
+ { MM_CC_HDR, "Cc" },
+ { MM_CLOCATION_HDR, "X-Mms-Content-Location" },
+ { MM_CTYPE_HDR, "X-Mms-Content-Type" },
+ { MM_DATE_HDR, "Date" },
+ { MM_DREPORT_HDR, "X-Mms-Delivery-Report" },
+ { MM_DTIME_HDR, "X-Mms-Delivery-Time" },
+ { MM_EXPIRY_HDR, "X-Mms-Expiry" },
+ { MM_FROM_HDR, "From" },
+ { MM_MCLASS_HDR, "X-Mms-Message-Class" },
+ { MM_MID_HDR, "Message-ID" },
+ { MM_MTYPE_HDR, "X-Mms-Message-Type" },
+ { MM_VERSION_HDR, "X-Mms-MMS-Version" },
+ { MM_MSIZE_HDR, "X-Mms-Message-Size" },
+ { MM_PRIORITY_HDR, "X-Mms-Priority" },
+ { MM_RREPLY_HDR, "X-Mms-Read-Reply" },
+ { MM_RALLOWED_HDR, "X-Mms-Report-Allowed" },
+ { MM_RSTATUS_HDR, "X-Mms-Response-Status" },
+ { MM_RTEXT_HDR, "X-Mms-Response-Text" },
+ { MM_SVISIBILITY_HDR, "X-Mms-Sender-Visibility" },
+ { MM_STATUS_HDR, "X-Mms-Status" },
+ { MM_SUBJECT_HDR, "Subject" },
+ { MM_TO_HDR, "To" },
+ { MM_TID_HDR, "X-Mms-Transaction-Id" },
+ /* MMS 1.1 */
+ { MM_RETRIEVE_STATUS_HDR, "X-Mms-Retrieve-Status" },
+ { MM_RETRIEVE_TEXT_HDR, "X-Mms-Retrieve-Text" },
+ { MM_READ_STATUS_HDR, "X-Mms-Read-Status" },
+ { MM_REPLY_CHARGING_HDR, "X-Mms-Reply-Charging" },
+ { MM_REPLY_CHARGING_DEADLINE_HDR,
+ "X-Mms-Reply-Charging-Deadline" },
+ { MM_REPLY_CHARGING_ID_HDR, "X-Mms-Reply-Charging-ID" },
+ { MM_REPLY_CHARGING_SIZE_HDR, "X-Mms-Reply-Charging-Size" },
+ { MM_PREV_SENT_BY_HDR, "X-Mms-Previously-Sent-By" },
+ { MM_PREV_SENT_DATE_HDR, "X-Mms-Previously-Sent-Date" },
+ /* MMS 1.2 */
+ { MM_STORE_HDR, "X-Mms-Store" },
+ { MM_MM_STATE_HDR, "X-Mms-MM-State " },
+ { MM_MM_FLAGS_HDR, "X-Mms-MM-Flags " },
+ { MM_STORE_STATUS_HDR, "X-Mms-Store-Status" },
+ { MM_STORE_STATUS_TEXT_HDR, "X-Mms-Store-Status-Text" },
+ { MM_STORED_HDR, "X-Mms-Stored" },
+ { MM_ATTRIBUTES_HDR, "X-Mms-Attributes" },
+ { MM_TOTALS_HDR, "X-Mms-Totals" },
+ { MM_MBOX_TOTALS_HDR, "X-Mms-Mbox-Totals" },
+ { MM_QUOTAS_HDR, "X-Mms-Quotas" },
+ { MM_MBOX_QUOTAS_HDR, "X-Mms-Mbox-Quotas" },
+ { MM_MBOX_MSG_COUNT_HDR, "X-Mms-Message-Count" },
+ { MM_CONTENT_HDR, "Content" },
+ { MM_START_HDR, "X-Mms-Start" },
+ { MM_ADDITIONAL_HDR, "Additional-headers" },
+ { MM_DISTRIBUION_IND_HDR, "X-Mms-Distribution-Indcator" },
+ { MM_ELEMENT_DESCR_HDR, "X-Mms-Element-Descriptor" },
+ { MM_LIMIT_HDR, "X-Mms-Limit" },
+
+ { 0x00, NULL },
+};
+/*
+ * Initialize the protocol and registered fields
+ */
+static int proto_mmse = -1;
+
+static int hf_mmse_message_type = -1;
+static int hf_mmse_transaction_id = -1;
+static int hf_mmse_mms_version = -1;
+static int hf_mmse_bcc = -1;
+static int hf_mmse_cc = -1;
+static int hf_mmse_content_location = -1;
+static int hf_mmse_date = -1;
+static int hf_mmse_delivery_report = -1;
+static int hf_mmse_delivery_time_abs = -1;
+static int hf_mmse_delivery_time_rel = -1;
+static int hf_mmse_expiry_abs = -1;
+static int hf_mmse_expiry_rel = -1;
+static int hf_mmse_from = -1;
+static int hf_mmse_message_class_id = -1;
+static int hf_mmse_message_class_str = -1;
+static int hf_mmse_message_id = -1;
+static int hf_mmse_message_size = -1;
+static int hf_mmse_priority = -1;
+static int hf_mmse_read_reply = -1;
+static int hf_mmse_report_allowed = -1;
+static int hf_mmse_response_status = -1;
+static int hf_mmse_response_text = -1;
+static int hf_mmse_sender_visibility = -1;
+static int hf_mmse_status = -1;
+static int hf_mmse_subject = -1;
+static int hf_mmse_to = -1;
+static int hf_mmse_content_type = -1;
+static int hf_mmse_ffheader = -1;
+/* MMSE 1.1 */
+static int hf_mmse_read_report = -1;
+static int hf_mmse_retrieve_status = -1;
+static int hf_mmse_retrieve_text = -1;
+static int hf_mmse_read_status = -1;
+static int hf_mmse_reply_charging = -1;
+static int hf_mmse_reply_charging_deadline = -1;
+static int hf_mmse_reply_charging_id = -1;
+static int hf_mmse_reply_charging_size = -1;
+static int hf_mmse_prev_sent_by = -1;
+static int hf_mmse_prev_sent_by_fwd_count = -1;
+static int hf_mmse_prev_sent_by_address = -1;
+static int hf_mmse_prev_sent_date = -1;
+static int hf_mmse_prev_sent_date_fwd_count = -1;
+static int hf_mmse_prev_sent_date_date = -1;
+
+/*
+ * Initialize the subtree pointers
+ */
+static gint ett_mmse = -1;
+static gint ett_mmse_hdr_details = -1;
+
+/*
+ * Valuestrings for PDU types
+ */
+/* MMS 1.0 */
+#define PDU_M_SEND_REQ 0x80
+#define PDU_M_SEND_CONF 0x81
+#define PDU_M_NOTIFICATION_IND 0x82
+#define PDU_M_NOTIFYRESP_IND 0x83
+#define PDU_M_RETRIEVE_CONF 0x84
+#define PDU_M_ACKNOWLEDGE_IND 0x85
+#define PDU_M_DELIVERY_IND 0x86
+/* MMS 1.1 */
+#define PDU_M_READ_REC_IND 0x87
+#define PDU_M_READ_ORIG_IND 0x88
+#define PDU_M_FORWARD_REQ 0x89
+#define PDU_M_FORWARD_CONF 0x8A
+/* MMS 1.2 */
+#define PDU_M_MBOX_STORE_REQ 0x8B
+#define PDU_M_MBOX_STORE_CONF 0x8C
+#define PDU_M_MBOX_VIEW_REQ 0x8D
+#define PDU_M_MBOX_VIEW_CONF 0x8E
+#define PDU_M_MBOX_UPLOAD_REQ 0x8F
+#define PDU_M_MBOX_UPLOAD_CONF 0x90
+#define PDU_M_MBOX_DELETE_REQ 0x91
+#define PDU_M_MBOX_DELETE_CONF 0x92
+#define PDU_M_MBOX_DESCR 0x93
+
+#define pdu_has_content(pdut) \
+ ( ((pdut) == PDU_M_SEND_REQ) \
+ || ((pdut) == PDU_M_DELIVERY_IND) \
+ || ((pdut) == PDU_M_RETRIEVE_CONF) \
+ || ((pdut) == PDU_M_MBOX_VIEW_CONF) \
+ || ((pdut) == PDU_M_MBOX_DESCR) \
+ || ((pdut) == PDU_M_MBOX_UPLOAD_REQ) \
+ )
+
+static const value_string vals_message_type[] = {
+ /* MMS 1.0 */
+ { PDU_M_SEND_REQ, "m-send-req" },
+ { PDU_M_SEND_CONF, "m-send-conf" },
+ { PDU_M_NOTIFICATION_IND, "m-notification-ind" },
+ { PDU_M_NOTIFYRESP_IND, "m-notifyresp-ind" },
+ { PDU_M_RETRIEVE_CONF, "m-retrieve-conf" },
+ { PDU_M_ACKNOWLEDGE_IND, "m-acknowledge-ind" },
+ { PDU_M_DELIVERY_IND, "m-delivery-ind" },
+ /* MMS 1.1 */
+ { PDU_M_READ_REC_IND, "m-read-rec-ind" },
+ { PDU_M_READ_ORIG_IND, "m-read-orig-ind" },
+ { PDU_M_FORWARD_REQ, "m-forward-req" },
+ { PDU_M_FORWARD_CONF, "m-forward-conf" },
+ /* MMS 1.2 */
+ { PDU_M_MBOX_STORE_REQ, "m-mbox-store-req" },
+ { PDU_M_MBOX_STORE_CONF, "m-mbox-store-conf" },
+ { PDU_M_MBOX_VIEW_REQ, "m-mbox-view-req" },
+ { PDU_M_MBOX_VIEW_CONF, "m-mbox-view-conf" },
+ { PDU_M_MBOX_UPLOAD_REQ, "m-mbox-upload-req" },
+ { PDU_M_MBOX_UPLOAD_CONF, "m-mbox-upload-conf" },
+ { PDU_M_MBOX_DELETE_REQ, "m-mbox-delete-req" },
+ { PDU_M_MBOX_DELETE_CONF, "m-mbox-delete-conf" },
+ { PDU_M_MBOX_DESCR, "m-mbox-descr" },
+ { 0x00, NULL },
+};
+
+static const value_string vals_yes_no[] = {
+ { 0x80, "Yes" },
+ { 0x81, "No" },
+ { 0x00, NULL },
+};
+
+static const value_string vals_message_class[] = {
+ { 0x80, "Personal" },
+ { 0x81, "Advertisement" },
+ { 0x82, "Informational" },
+ { 0x83, "Auto" },
+ { 0x00, NULL },
+};
+
+static const value_string vals_priority[] = {
+ { 0x80, "Low" },
+ { 0x81, "Normal" },
+ { 0x82, "High" },
+ { 0x00, NULL },
+};
+
+static const value_string vals_response_status[] = {
+ /* MMS 1.0 - obsolete as from MMS 1.1 */
+ { 0x80, "Ok" },
+ { 0x81, "Unspecified" },
+ { 0x82, "Service denied" },
+ { 0x83, "Message format corrupt" },
+ { 0x84, "Sending address unresolved" },
+ { 0x85, "Message not found" },
+ { 0x86, "Network problem" },
+ { 0x87, "Content not accepted" },
+ { 0x88, "Unsupported message" },
+
+ /*
+ * Transient errors
+ */
+ /* MMS 1.1 */
+ { 0xC0, "Transient failure" },
+ { 0xC1, "Transient: Sending address unresolved" },
+ { 0xC2, "Transient: Message not found" },
+ { 0xC3, "Transient: Network problem" },
+ /* MMS 1.2 */
+ { 0xC4, "Transient: Partial success" },
+
+ /*
+ * Permanent errors
+ */
+ /* MMS 1.1 */
+ { 0xE0, "Permanent failure" },
+ { 0xE1, "Permanent: Service denied" },
+ { 0xE2, "Permanent: Message format corrupt" },
+ { 0xE3, "Permanent: Sending address unresolved" },
+ { 0xE4, "Permanent: Message not found" },
+ { 0xE5, "Permanent: Content not accepted" },
+ { 0xE6, "Permanent: Reply charging limitations not met" },
+ { 0xE7, "Permanent: Reply charging request not accepted" },
+ { 0xE8, "Permanent: Reply charging forwarding denied" },
+ { 0xE9, "Permanent: Reply charging not supported" },
+ /* MMS 1.2 */
+ { 0xEA, "Permanent: Address hiding not supported" },
+
+ { 0x00, NULL },
+};
+
+static const value_string vals_sender_visibility[] = {
+ { 0x80, "Hide" },
+ { 0x81, "Show" },
+ { 0x00, NULL },
+};
+
+static const value_string vals_message_status[] = {
+ /* MMS 1.0 */
+ { 0x80, "Expired" },
+ { 0x81, "Retrieved" },
+ { 0x82, "Rejected" },
+ { 0x83, "Deferred" },
+ { 0x84, "Unrecognized" },
+ /* MMS 1.1 */
+ { 0x85, "Indeterminate" },
+ { 0x86, "Forwarded" },
+ /* MMS 1.2 */
+ { 0x87, "Unreachable" },
+
+ { 0x00, NULL },
+};
+
+static const value_string vals_retrieve_status[] = {
+ /*
+ * Transient errors
+ */
+ /* MMS 1.1 */
+ { 0xC0, "Transient failure" },
+ { 0xC1, "Transient: Message not found" },
+ { 0xC2, "Transient: Network problem" },
+
+ /*
+ * Permanent errors
+ */
+ /* MMS 1.1 */
+ { 0xE0, "Permanent failure" },
+ { 0xE1, "Permanent: Service denied" },
+ { 0xE2, "Permanent: Message not found" },
+ { 0xE3, "Permanent: Content unsupported" },
+
+ { 0x00, NULL },
+};
+
+static const value_string vals_read_status[] = {
+ { 0x80, "Read" },
+ { 0x81, "Deleted without being read" },
+
+ { 0x00, NULL },
+};
+
+static const value_string vals_reply_charging[] = {
+ { 0x80, "Requested" },
+ { 0x81, "Requested text only" },
+ { 0x82, "Accepted" },
+ { 0x83, "Accepted text only" },
+
+ { 0x00, NULL },
+};
+
+static const value_string vals_reply_charging_deadline[] = {
+ { 0x80, "Absolute" },
+ { 0x81, "Relative" },
+
+ { 0x00, NULL },
+};
+
+/*!
+ * Decodes a Text-string from the protocol data
+ * Text-string = [Quote] *TEXT End-of-string
+ * Quote = <Octet 127>
+ * End-of-string = <Octet 0>
+ *
+ * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
+ *
+ * \param tvb The buffer with PDU-data
+ * \param offset Offset within that buffer
+ * \param strval Pointer to variable into which to put pointer to
+ * buffer allocated to hold the text; must be freed
+ * when no longer used
+ *
+ * \return The length in bytes of the entire field
+ */
+static guint
+get_text_string(tvbuff_t *tvb, guint offset, char **strval)
+{
+ guint len;
+
+ DebugLog(("get_text_string(tvb = %p, offset = %u, **strval) - start\n",
+ tvb, offset));
+ len = tvb_strsize(tvb, offset);
+ DebugLog((" [1] tvb_strsize(tvb, offset) == %u\n", len));
+ if (tvb_get_guint8(tvb, offset) == MM_QUOTE)
+ *strval = (char *)tvb_memdup(tvb, offset + 1, len - 1);
+ else
+ *strval = (char *)tvb_memdup(tvb, offset, len);
+ DebugLog((" [3] Return(len) == %u\n", len));
+ return len;
+}
+
+/*!
+ * Decodes a Value-length from the protocol data.
+ * Value-length = Short-length | (Length-quote Length)
+ * Short-length = <Any octet 0-30>
+ * Length-quote = <Octet 31>
+ * Length = Uintvar-integer
+ *
+ * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
+ *
+ * \param tvb The buffer with PDU-data
+ * \param offset Offset within that buffer
+ * \param byte_count Returns the length in bytes of
+ * the "Value-length" field.
+ *
+ * \return The actual value of "Value-length"
+ */
+static guint
+get_value_length(tvbuff_t *tvb, guint offset, guint *byte_count)
+{
+ guint field;
+
+ field = tvb_get_guint8(tvb, offset++);
+ if (field < 31)
+ *byte_count = 1;
+ else { /* Must be 31 so, Uintvar follows */
+ field = tvb_get_guintvar(tvb, offset, byte_count);
+ (*byte_count)++;
+ }
+ return field;
+}
+
+/*!
+ * Decodes an Encoded-string-value from the protocol data
+ * Encoded-string-value = Text-string | Value-length Char-set Text-string
+ *
+ * \param tvb The buffer with PDU-data
+ * \param offset Offset within that buffer
+ * \param strval Pointer to variable into which to put pointer to
+ * buffer allocated to hold the text; must be freed
+ * when no longer used
+ *
+ * \return The length in bytes of the entire field
+ */
+static guint
+get_encoded_strval(tvbuff_t *tvb, guint offset, char **strval)
+{
+ guint field;
+ guint length;
+ guint count;
+
+ field = tvb_get_guint8(tvb, offset);
+
+ if (field < 32) {
+ length = get_value_length(tvb, offset, &count);
+ if (length < 2) {
+ *strval = g_strdup("");
+ } else {
+ /* \todo Something with "Char-set", skip for now */
+ *strval = (char *)tvb_get_string(tvb, offset + count + 1, length - 1);
+ }
+ return count + length;
+ } else
+ return get_text_string(tvb, offset, strval);
+}
+
+/*!
+ * Decodes a Long-integer from the protocol data
+ * Long-integer = Short-length Multi-octet-integer
+ * Short-length = <Any octet 0-30>
+ * Multi-octet-integer = 1*30OCTET
+ *
+ * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
+ *
+ * \param tvb The buffer with PDU-data
+ * \param offset Offset within that buffer
+ * \param byte_count Returns the length in bytes of the field
+ *
+ * \return The value of the Long-integer
+ *
+ * \note A maximum of 4-byte integers will be handled.
+ */
+static guint
+get_long_integer(tvbuff_t *tvb, guint offset, guint *byte_count)
+{
+ guint val;
+
+ *byte_count = tvb_get_guint8(tvb, offset++);
+ switch (*byte_count) {
+ case 1:
+ val = tvb_get_guint8(tvb, offset);
+ break;
+ case 2:
+ val = tvb_get_ntohs(tvb, offset);
+ break;
+ case 3:
+ val = tvb_get_ntoh24(tvb, offset);
+ break;
+ case 4:
+ val = tvb_get_ntohl(tvb, offset);
+ break;
+ default:
+ val = 0;
+ break;
+ }
+ (*byte_count)++;
+ return val;
+}
+
+/*!
+ * Decodes an Integer-value from the protocol data
+ * Integer-value = Short-integer | Long-integer
+ * Short-integer = OCTET
+ * Long-integer = Short-length Multi-octet-integer
+ * Short-length = <Any octet 0-30>
+ * Multi-octet-integer = 1*30OCTET
+ *
+ * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
+ *
+ * \param tvb The buffer with PDU-data
+ * \param offset Offset within that buffer
+ * \param byte_count Returns the length in bytes of the field
+ *
+ * \return The value of the Long-integer
+ *
+ * \note A maximum of 4-byte integers will be handled.
+ */
+static guint
+get_integer_value(tvbuff_t *tvb, guint offset, guint *byte_count)
+{
+ guint val;
+ guint8 peek;
+
+ peek = tvb_get_guint8(tvb, offset++);
+ if (peek & 0x80) {
+ val = peek & 0x7F;
+ *byte_count = 1;
+ return val;
+ } else {
+ *byte_count = peek;
+ switch (peek) {
+ case 1:
+ val = tvb_get_guint8(tvb, offset);
+ break;
+ case 2:
+ val = tvb_get_ntohs(tvb, offset);
+ break;
+ case 3:
+ val = tvb_get_ntoh24(tvb, offset);
+ break;
+ case 4:
+ val = tvb_get_ntohl(tvb, offset);
+ break;
+ default:
+ val = 0;
+ break;
+ }
+ }
+ (*byte_count)++;
+ return val;
+}
+
+/* Code to actually dissect the packets */
+static gboolean
+dissect_mmse_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 pdut;
+
+ DebugLog(("dissect_mmse_heur()\n"));
+ /*
+ * Check if data makes sense for it to be dissected as MMSE: Message-type
+ * field must make sense and followed by either Transaction-Id
+ * or MMS-Version header
+ */
+ if (tvb_get_guint8(tvb, 0) != MM_MTYPE_HDR)
+ return FALSE;
+ pdut = tvb_get_guint8(tvb, 1);
+ if (match_strval(pdut, vals_message_type) == NULL)
+ return FALSE;
+ if ((tvb_get_guint8(tvb, 2) != MM_TID_HDR) &&
+ (tvb_get_guint8(tvb, 2) != MM_VERSION_HDR))
+ return FALSE;
+ dissect_mmse_standalone(tvb, pinfo, tree);
+ return TRUE;
+}
+
+static void
+dissect_mmse_standalone(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 pdut;
+ char *message_type;
+
+ DebugLog(("dissect_mmse_standalone() - START (Packet %u)\n",
+ pinfo->fd->num));
+
+ pdut = tvb_get_guint8(tvb, 1);
+ message_type = match_strval(pdut, vals_message_type);
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MMSE");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "MMS %s", message_type);
+ }
+
+ dissect_mmse(tvb, pinfo, tree, pdut, message_type);
+}
+
+static void
+dissect_mmse_encapsulated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 pdut;
+ char *message_type;
+
+ DebugLog(("dissect_mmse_encapsulated() - START (Packet %u)\n",
+ pinfo->fd->num));
+
+ pdut = tvb_get_guint8(tvb, 1);
+ message_type = match_strval(pdut, vals_message_type);
+
+ /* Make entries in Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(MMS %s)",
+ message_type);
+ }
+
+ dissect_mmse(tvb, pinfo, tree, pdut, message_type);
+}
+
+static void
+dissect_mmse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 pdut,
+ char *message_type)
+{
+ guint offset;
+ guint8 field = 0;
+ char *strval;
+ guint length;
+ guint count;
+ guint8 version = 0x80; /* Default to MMSE 1.0 */
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti = NULL;
+ proto_tree *mmse_tree = NULL;
+
+ DebugLog(("dissect_mmse() - START (Packet %u)\n", pinfo->fd->num));
+
+ /* If tree == NULL then we are only interested in protocol dissection
+ * up to reassembly and handoff to subdissectors if applicable; the
+ * columns must be set appropriately too.
+ * If tree != NULL then we also want to display the protocol tree
+ * with its fields.
+ *
+ * In the interest of speed, skip protocol tree item generation
+ * if tree is NULL.
+ */
+ if (tree) {
+ DebugLog(("tree != NULL\n"));
+
+ ti = proto_tree_add_item(tree, proto_mmse, tvb, 0, -1, FALSE);
+ proto_item_append_text(ti, ", Type: %s", message_type);
+ /* create display subtree for the protocol */
+ mmse_tree = proto_item_add_subtree(ti, ett_mmse);
+
+ /* Report PDU-type */
+ proto_tree_add_uint(mmse_tree, hf_mmse_message_type, tvb, 0, 2, pdut);
+ }
+
+ offset = 2; /* Skip Message-Type */
+
+ /*
+ * Cycle through MMS-headers
+ *
+ * NOTE - some PDUs may convey content which can be handed off
+ * to subdissectors.
+ */
+ if (tree || pdu_has_content(pdut)) {
+ while ((offset < tvb_reported_length(tvb)) &&
+ (field = tvb_get_guint8(tvb, offset++)) != MM_CTYPE_HDR)
+ {
+ DebugLog(("\tField = 0x%02X (offset = %u): %s\n",
+ field, offset,
+ val_to_str(field, vals_mm_header_names,
+ "Unknown MMS header 0x%02X")));
+ switch (field)
+ {
+ case MM_TID_HDR: /* Text-string */
+ length = get_text_string(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree, hf_mmse_transaction_id,
+ tvb, offset - 1, length + 1,strval);
+ }
+ g_free(strval);
+ offset += length;
+ break;
+ case MM_VERSION_HDR: /* nibble-Major/nibble-minor*/
+ version = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ guint8 major, minor;
+
+ major = (version & 0x70) >> 4;
+ minor = version & 0x0F;
+ if (minor == 0x0F)
+ strval = g_strdup_printf("%u", major);
+ else
+ strval = g_strdup_printf("%u.%u", major, minor);
+ proto_tree_add_string(mmse_tree, hf_mmse_mms_version,
+ tvb, offset - 2, 2, strval);
+ g_free(strval);
+ }
+ break;
+ case MM_BCC_HDR: /* Encoded-string-value */
+ length = get_encoded_strval(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree, hf_mmse_bcc, tvb,
+ offset - 1, length + 1, strval);
+ }
+ g_free(strval);
+ offset += length;
+ break;
+ case MM_CC_HDR: /* Encoded-string-value */
+ length = get_encoded_strval(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree, hf_mmse_cc, tvb,
+ offset - 1, length + 1, strval);
+ }
+ g_free(strval);
+ offset += length;
+ break;
+ case MM_CLOCATION_HDR: /* Uri-value */
+ if (pdut == PDU_M_MBOX_DELETE_CONF) {
+ /* General form with length */
+ length = tvb_get_guint8(tvb, offset);
+ if (length == 0x1F) {
+ guint length_len = 0;
+ length = tvb_get_guintvar(tvb, offset + 1,
+ &length_len);
+ length += 1 + length_len;
+ } else {
+ length += 1;
+ }
+ if (tree) {
+ proto_tree_add_string(mmse_tree,
+ hf_mmse_content_location,
+ tvb, offset - 1, length + 1,
+ "<Undecoded value for m-mbox-delete-conf>");
+ }
+ } else {
+ length = get_text_string(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree,
+ hf_mmse_content_location,
+ tvb, offset - 1, length + 1, strval);
+ }
+ g_free(strval);
+ }
+ offset += length;
+ break;
+ case MM_DATE_HDR: /* Long-integer */
+ {
+ guint tval;
+ nstime_t tmptime;
+
+ tval = get_long_integer(tvb, offset, &count);
+ tmptime.secs = tval;
+ tmptime.nsecs = 0;
+ if (tree) {
+ proto_tree_add_time(mmse_tree, hf_mmse_date, tvb,
+ offset - 1, count + 1, &tmptime);
+ }
+ }
+ offset += count;
+ break;
+ case MM_DREPORT_HDR: /* Yes|No */
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree,
+ hf_mmse_delivery_report,
+ tvb, offset - 2, 2, field);
+ }
+ break;
+ case MM_DTIME_HDR:
+ /*
+ * Value-length(Absolute-token Date-value|
+ * Relative-token Delta-seconds-value)
+ */
+ length = get_value_length(tvb, offset, &count);
+ field = tvb_get_guint8(tvb, offset + count);
+ if (tree) {
+ guint tval;
+ nstime_t tmptime;
+ guint cnt;
+
+ tval = get_long_integer(tvb, offset + count + 1, &cnt);
+ tmptime.secs = tval;
+ tmptime.nsecs = 0;
+
+ if (field == 0x80)
+ proto_tree_add_time(mmse_tree,
+ hf_mmse_delivery_time_abs,
+ tvb, offset - 1,
+ length + count + 1, &tmptime);
+ else
+ proto_tree_add_time(mmse_tree,
+ hf_mmse_delivery_time_rel,
+ tvb, offset - 1,
+ length + count + 1, &tmptime);
+ }
+ offset += length + count;
+ break;
+ case MM_EXPIRY_HDR:
+ /*
+ * Value-length(Absolute-token Date-value|
+ * Relative-token Delta-seconds-value)
+ */
+ length = get_value_length(tvb, offset, &count);
+ field = tvb_get_guint8(tvb, offset + count);
+ if (tree) {
+ guint tval;
+ nstime_t tmptime;
+ guint cnt;
+
+ tval = get_long_integer(tvb, offset + count + 1, &cnt);
+ tmptime.secs = tval;
+ tmptime.nsecs = 0;
+
+ if (field == 0x80)
+ proto_tree_add_time(mmse_tree, hf_mmse_expiry_abs,
+ tvb, offset - 1,
+ length + count + 1, &tmptime);
+ else
+ proto_tree_add_time(mmse_tree, hf_mmse_expiry_rel,
+ tvb, offset - 1,
+ length + count + 1, &tmptime);
+ }
+ offset += length + count;
+ break;
+ case MM_FROM_HDR:
+ /*
+ * Value-length(Address-present-token Encoded-string-value
+ * |Insert-address-token)
+ */
+ length = get_value_length(tvb, offset, &count);
+ if (tree) {
+ field = tvb_get_guint8(tvb, offset + count);
+ if (field == 0x81) {
+ proto_tree_add_string(mmse_tree, hf_mmse_from, tvb,
+ offset-1, length + count + 1,
+ "<insert address>");
+ } else {
+ (void) get_encoded_strval(tvb, offset + count + 1,
+ &strval);
+ proto_tree_add_string(mmse_tree, hf_mmse_from, tvb,
+ offset-1, length + count + 1, strval);
+ g_free(strval);
+ }
+ }
+ offset += length + count;
+ break;
+ case MM_MCLASS_HDR:
+ /*
+ * Class-identifier|Text-string
+ */
+ field = tvb_get_guint8(tvb, offset);
+ if (field & 0x80) {
+ offset++;
+ if (tree) {
+ proto_tree_add_uint(mmse_tree,
+ hf_mmse_message_class_id,
+ tvb, offset - 2, 2, field);
+ }
+ } else {
+ length = get_text_string(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree,
+ hf_mmse_message_class_str,
+ tvb, offset - 1, length + 1,
+ strval);
+ }
+ g_free(strval);
+ offset += length;
+ }
+ break;
+ case MM_MID_HDR: /* Text-string */
+ length = get_text_string(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree, hf_mmse_message_id,
+ tvb, offset - 1, length + 1, strval);
+ }
+ g_free(strval);
+ offset += length;
+ break;
+ case MM_MSIZE_HDR: /* Long-integer */
+ length = get_long_integer(tvb, offset, &count);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree, hf_mmse_message_size,
+ tvb, offset - 1, count + 1, length);
+ }
+ offset += count;
+ break;
+ case MM_PRIORITY_HDR: /* Low|Normal|High */
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree, hf_mmse_priority, tvb,
+ offset - 2, 2, field);
+ }
+ break;
+ case MM_RREPLY_HDR: /* Yes|No */
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ if (version == 0x80) { /* MMSE 1.0 */
+ proto_tree_add_uint(mmse_tree, hf_mmse_read_reply,
+ tvb, offset - 2, 2, field);
+ } else {
+ proto_tree_add_uint(mmse_tree, hf_mmse_read_report,
+ tvb, offset - 2, 2, field);
+ }
+ }
+ break;
+ case MM_RALLOWED_HDR: /* Yes|No */
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree, hf_mmse_report_allowed,
+ tvb, offset - 2, 2, field);
+ }
+ break;
+ case MM_RSTATUS_HDR:
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree, hf_mmse_response_status,
+ tvb, offset - 2, 2, field);
+ }
+ break;
+ case MM_RTEXT_HDR: /* Encoded-string-value */
+ if (pdut == PDU_M_MBOX_DELETE_CONF) {
+ /* General form with length */
+ length = tvb_get_guint8(tvb, offset);
+ if (length == 0x1F) {
+ guint length_len = 0;
+ length = tvb_get_guintvar(tvb, offset + 1,
+ &length_len);
+ length += 1 + length_len;
+ } else {
+ length += 1;
+ }
+ if (tree) {
+ proto_tree_add_string(mmse_tree,
+ hf_mmse_content_location,
+ tvb, offset - 1, length + 1,
+ "<Undecoded value for m-mbox-delete-conf>");
+ }
+ } else {
+ length = get_encoded_strval(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree,
+ hf_mmse_response_text, tvb, offset - 1,
+ length + 1, strval);
+ }
+ g_free(strval);
+ }
+ offset += length;
+ break;
+ case MM_SVISIBILITY_HDR: /* Hide|Show */
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree,hf_mmse_sender_visibility,
+ tvb, offset - 2, 2, field);
+ }
+ break;
+ case MM_STATUS_HDR:
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree, hf_mmse_status, tvb,
+ offset - 2, 2, field);
+ }
+ break;
+ case MM_SUBJECT_HDR: /* Encoded-string-value */
+ length = get_encoded_strval(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree, hf_mmse_subject, tvb,
+ offset - 1, length + 1, strval);
+ }
+ g_free(strval);
+ offset += length;
+ break;
+ case MM_TO_HDR: /* Encoded-string-value */
+ length = get_encoded_strval(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree, hf_mmse_to, tvb,
+ offset - 1, length + 1, strval);
+ }
+ g_free(strval);
+ offset += length;
+ break;
+
+ /*
+ * MMS Encapsulation 1.1
+ */
+ case MM_RETRIEVE_STATUS_HDR: /* Well-known-value */
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree, hf_mmse_retrieve_status,
+ tvb, offset - 2, 2, field);
+ }
+ break;
+ case MM_RETRIEVE_TEXT_HDR:
+ if (pdut == PDU_M_MBOX_DELETE_CONF) {
+ /* General form with length */
+ length = tvb_get_guint8(tvb, offset);
+ if (length == 0x1F) {
+ guint length_len = 0;
+ length = tvb_get_guintvar(tvb, offset + 1,
+ &length_len);
+ length += 1 + length_len;
+ } else {
+ length += 1;
+ }
+ if (tree) {
+ proto_tree_add_string(mmse_tree,
+ hf_mmse_content_location,
+ tvb, offset - 1, length + 1,
+ "<Undecoded value for m-mbox-delete-conf>");
+ }
+ } else {
+ /* Encoded-string-value */
+ length = get_encoded_strval(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree,
+ hf_mmse_retrieve_text, tvb, offset - 1,
+ length + 1, strval);
+ }
+ g_free(strval);
+ }
+ offset += length;
+ break;
+ case MM_READ_STATUS_HDR: /* Well-known-value */
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree, hf_mmse_read_status,
+ tvb, offset - 2, 2, field);
+ }
+ break;
+ case MM_REPLY_CHARGING_HDR: /* Well-known-value */
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree, hf_mmse_reply_charging,
+ tvb, offset - 2, 2, field);
+ }
+ break;
+ case MM_REPLY_CHARGING_DEADLINE_HDR: /* Well-known-value */
+ field = tvb_get_guint8(tvb, offset++);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree,
+ hf_mmse_reply_charging_deadline,
+ tvb, offset - 2, 2, field);
+ }
+ break;
+ case MM_REPLY_CHARGING_ID_HDR: /* Text-string */
+ length = get_text_string(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_string(mmse_tree,
+ hf_mmse_reply_charging_id,
+ tvb, offset - 1, length + 1, strval);
+ }
+ g_free(strval);
+ offset += length;
+ break;
+ case MM_REPLY_CHARGING_SIZE_HDR: /* Long-integer */
+ length = get_long_integer(tvb, offset, &count);
+ if (tree) {
+ proto_tree_add_uint(mmse_tree,
+ hf_mmse_reply_charging_size,
+ tvb, offset - 1, count + 1, length);
+ }
+ offset += count;
+ break;
+ case MM_PREV_SENT_BY_HDR:
+ /* Value-length Integer-value Encoded-string-value */
+ length = get_value_length(tvb, offset, &count);
+ if (tree) {
+ guint32 fwd_count, count1, count2;
+ proto_tree *subtree = NULL;
+ proto_item *ti = NULL;
+ /* 1. Forwarded-count-value := Integer-value */
+ fwd_count = get_integer_value(tvb, offset + count,
+ &count1);
+ /* 2. Encoded-string-value */
+ count2 = get_encoded_strval(tvb,
+ offset + count + count1, &strval);
+ /* Now render the fields */
+ ti = proto_tree_add_string_format(tree,
+ hf_mmse_prev_sent_by,
+ tvb, offset - 1, 1 + count + length,
+ "%s (Forwarded-count=%u)",
+ strval, fwd_count);
+ subtree = proto_item_add_subtree(ti,
+ ett_mmse_hdr_details);
+ proto_tree_add_uint(subtree,
+ hf_mmse_prev_sent_by_fwd_count,
+ tvb, offset + count, count1, fwd_count);
+ proto_tree_add_string(subtree,
+ hf_mmse_prev_sent_by_address,
+ tvb, offset + count + count1, count2, strval);
+ g_free(strval);
+ }
+ offset += length + count;
+ break;
+ case MM_PREV_SENT_DATE_HDR:
+ /* Value-Length Forwarded-count-value Date-value */
+ length = get_value_length(tvb, offset, &count);
+ if (tree) {
+ guint32 fwd_count, count1, count2;
+ guint tval;
+ nstime_t tmptime;
+ proto_tree *subtree = NULL;
+ proto_item *ti = NULL;
+ /* 1. Forwarded-count-value := Integer-value */
+ fwd_count = get_integer_value(tvb, offset + count,
+ &count1);
+ /* 2. Date-value := Long-integer */
+ tval = get_long_integer(tvb, offset + count + count1,
+ &count2);
+ tmptime.secs = tval;
+ tmptime.nsecs = 0;
+ strval = abs_time_to_str(&tmptime);
+ /* Now render the fields */
+ ti = proto_tree_add_string_format(tree,
+ hf_mmse_prev_sent_date,
+ tvb, offset - 1, 1 + count + length,
+ "%s (Forwarded-count=%u)",
+ strval, fwd_count);
+ subtree = proto_item_add_subtree(ti,
+ ett_mmse_hdr_details);
+ proto_tree_add_uint(subtree,
+ hf_mmse_prev_sent_date_fwd_count,
+ tvb, offset + count, count1, fwd_count);
+ proto_tree_add_string(subtree,
+ hf_mmse_prev_sent_date_date,
+ tvb, offset + count + count1, count2, strval);
+ g_free(strval);
+ }
+ offset += length + count;
+ break;
+
+ /* MMS Encapsulation 1.2 */
+
+ default:
+ if (field & 0x80) { /* Well-known WSP header encoding */
+ guint8 peek = tvb_get_guint8(tvb, offset);
+ char *hdr_name = val_to_str(field, vals_mm_header_names,
+ "Unknown field (0x%02x)");
+ DebugLog(("\t\tUndecoded well-known header: %s\n",
+ hdr_name));
+
+ if (peek & 0x80) { /* Well-known value */
+ length = 1;
+ if (tree) {
+ proto_tree_add_text(mmse_tree, tvb, offset - 1,
+ length + 1,
+ "%s: <Well-known value 0x%02x>"
+ " (not decoded)",
+ hdr_name, peek);
+ }
+ } else if ((peek == 0) || (peek >= 0x20)) { /* Text */
+ length = get_text_string(tvb, offset, &strval);
+ if (tree) {
+ proto_tree_add_text(mmse_tree, tvb, offset - 1,
+ length + 1, "%s: %s (Not decoded)",
+ hdr_name, strval);
+ g_free(strval);
+ }
+ } else { /* General form with length */
+ if (peek == 0x1F) { /* Value length in guintvar */
+ guint length_len = 0;
+ length = 1 + tvb_get_guintvar(tvb, offset + 1,
+ &length_len);
+ length += length_len;
+ } else { /* Value length in octet */
+ length = 1 + tvb_get_guint8(tvb, offset);
+ }
+ if (tree) {
+ proto_tree_add_text(mmse_tree, tvb, offset - 1,
+ length + 1, "%s: "
+ "<Value in general form> (not decoded)",
+ hdr_name);
+ }
+ }
+ offset += length;
+ } else { /* Literal WSP header encoding */
+ guint length2;
+ char *strval2;
+
+ --offset;
+ length = get_text_string(tvb, offset, &strval);
+ DebugLog(("\t\tUndecoded literal header: %s\n",
+ strval));
+ CLEANUP_PUSH(g_free, strval);
+ length2= get_text_string(tvb, offset+length, &strval2);
+
+ if (tree) {
+ proto_tree_add_string_format(mmse_tree,
+ hf_mmse_ffheader, tvb, offset,
+ length + length2,
+ (const char *) tvb_get_ptr(
+ tvb, offset, length + length2),
+ "%s: %s", strval, strval2);
+ }
+ g_free(strval2);
+ offset += length + length2;
+ CLEANUP_CALL_AND_POP;
+ }
+ break;
+ }
+ DebugLog(("\tEnd(case)\n"));
+ }
+ DebugLog(("\tEnd(switch)\n"));
+ if (field == MM_CTYPE_HDR) {
+ /*
+ * Eeehh, we're now actually back to good old WSP content-type
+ * encoding. Let's steal that from the WSP-dissector.
+ */
+ tvbuff_t *tmp_tvb;
+ guint type;
+ const char *type_str;
+
+ DebugLog(("Content-Type: [from WSP dissector]\n"));
+ DebugLog(("Calling add_content_type() in WSP dissector\n"));
+ offset = add_content_type(mmse_tree, tvb, offset, &type, &type_str);
+ DebugLog(("Generating new TVB subset (offset = %u)\n", offset));
+ tmp_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ DebugLog(("Add POST data\n"));
+ add_post_data(mmse_tree, tmp_tvb, type, type_str, pinfo);
+ DebugLog(("Done!\n"));
+ }
+ } else {
+ DebugLog(("tree == NULL and PDU has no potential content\n"));
+ }
+
+ /* If this protocol has a sub-dissector call it here, see section 1.8 */
+ DebugLog(("dissect_mmse() - END\n"));
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is required because a script is used to build the C function
+ * that calls all the protocol registration.
+ */
+void
+proto_register_mmse(void)
+{
+ /* Setup list of header fields See Section 1.6.1 for details */
+ static hf_register_info hf[] = {
+ { &hf_mmse_message_type,
+ { "X-Mms-Message-Type", "mmse.message_type",
+ FT_UINT8, BASE_HEX, VALS(vals_message_type), 0x00,
+ "Specifies the transaction type. Effectively defines PDU.",
+ HFILL
+ }
+ },
+ { &hf_mmse_transaction_id,
+ { "X-Mms-Transaction-ID", "mmse.transaction_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "A unique identifier for this transaction. "
+ "Identifies request and corresponding response only.",
+ HFILL
+ }
+ },
+ { &hf_mmse_mms_version,
+ { "X-Mms-MMS-Version", "mmse.mms_version",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Version of the protocol used.",
+ HFILL
+ }
+ },
+ { &hf_mmse_bcc,
+ { "Bcc", "mmse.bcc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Blind carbon copy.",
+ HFILL
+ }
+ },
+ { &hf_mmse_cc,
+ { "Cc", "mmse.cc",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Carbon copy.",
+ HFILL
+ }
+ },
+ { &hf_mmse_content_location,
+ { "X-Mms-Content-Location", "mmse.content_location",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Defines the location of the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_date,
+ { "Date", "mmse.date",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Arrival timestamp of the message or sending timestamp.",
+ HFILL
+ }
+ },
+ { &hf_mmse_delivery_report,
+ { "X-Mms-Delivery-Report", "mmse.delivery_report",
+ FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
+ "Whether a report of message delivery is wanted or not.",
+ HFILL
+ }
+ },
+ { &hf_mmse_delivery_time_abs,
+ { "X-Mms-Delivery-Time", "mmse.delivery_time.abs",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "The time at which message delivery is desired.",
+ HFILL
+ }
+ },
+ { &hf_mmse_delivery_time_rel,
+ { "X-Mms-Delivery-Time", "mmse.delivery_time.rel",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "The desired message delivery delay.",
+ HFILL
+ }
+ },
+ { &hf_mmse_expiry_abs,
+ { "X-Mms-Expiry", "mmse.expiry.abs",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Time when message expires and need not be delivered anymore.",
+ HFILL
+ }
+ },
+ { &hf_mmse_expiry_rel,
+ { "X-Mms-Expiry", "mmse.expiry.rel",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "Delay before message expires and need not be delivered anymore.",
+ HFILL
+ }
+ },
+ { &hf_mmse_from,
+ { "From", "mmse.from",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Address of the message sender.",
+ HFILL
+ }
+ },
+ { &hf_mmse_message_class_id,
+ { "X-Mms-Message-Class", "mmse.message_class.id",
+ FT_UINT8, BASE_HEX, VALS(vals_message_class), 0x00,
+ "Of what category is the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_message_class_str,
+ { "X-Mms-Message-Class", "mmse.message_class.str",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Of what category is the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_message_id,
+ { "Message-Id", "mmse.message_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Unique identification of the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_message_size,
+ { "X-Mms-Message-Size", "mmse.message_size",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "The size of the message in octets.",
+ HFILL
+ }
+ },
+ { &hf_mmse_priority,
+ { "X-Mms-Priority", "mmse.priority",
+ FT_UINT8, BASE_HEX, VALS(vals_priority), 0x00,
+ "Priority of the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_read_reply,
+ { "X-Mms-Read-Reply", "mmse.read_reply",
+ FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
+ "Whether a read report from every recipient is wanted.",
+ HFILL
+ }
+ },
+ { &hf_mmse_read_report,
+ { "X-Mms-Read-Report", "mmse.read_report",
+ FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
+ "Whether a read report from every recipient is wanted.",
+ HFILL
+ }
+ },
+ { &hf_mmse_report_allowed,
+ { "X-Mms-Report-Allowed", "mmse.report_allowed",
+ FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
+ "Sending of delivery report allowed or not.",
+ HFILL
+ }
+ },
+ { &hf_mmse_response_status,
+ { "Response-Status", "mmse.response_status",
+ FT_UINT8, BASE_HEX, VALS(vals_response_status), 0x00,
+ "MMS-specific result of a message submission or retrieval.",
+ HFILL
+ }
+ },
+ { &hf_mmse_response_text,
+ { "Response-Text", "mmse.response_text",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Additional information on MMS-specific result.",
+ HFILL
+ }
+ },
+ { &hf_mmse_sender_visibility,
+ { "Sender-Visibility", "mmse.sender_visibility",
+ FT_UINT8, BASE_HEX, VALS(vals_sender_visibility), 0x00,
+ "Disclose sender identity to receiver or not.",
+ HFILL
+ }
+ },
+ { &hf_mmse_status,
+ { "Status", "mmse.status",
+ FT_UINT8, BASE_HEX, VALS(vals_message_status), 0x00,
+ "Current status of the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_subject,
+ { "Subject", "mmse.subject",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Subject of the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_to,
+ { "To", "mmse.to",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Recipient(s) of the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_content_type,
+ { "Data", "mmse.content_type",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Media content of the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_ffheader,
+ { "Free format (not encoded) header", "mmse.ffheader",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Application header without corresponding encoding.",
+ HFILL
+ }
+ },
+ /* MMSE 1.1 */
+ { &hf_mmse_retrieve_status,
+ { "X-Mms-Retrieve-Status", "mmse.retrieve_status",
+ FT_UINT8, BASE_HEX, VALS(vals_retrieve_status), 0x00,
+ "MMS-specific result of a message retrieval.",
+ HFILL
+ }
+ },
+ { &hf_mmse_retrieve_text,
+ { "X-Mms-Retrieve-Text", "mmse.retrieve_text",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Status text of a MMS message retrieval.",
+ HFILL
+ }
+ },
+ { &hf_mmse_read_status,
+ { "X-Mms-Read-Status", "mmse.read_status",
+ FT_UINT8, BASE_HEX, VALS(vals_read_status), 0x00,
+ "MMS-specific message read status.",
+ HFILL
+ }
+ },
+ { &hf_mmse_reply_charging,
+ { "X-Mms-Reply-Charging", "mmse.reply_charging",
+ FT_UINT8, BASE_HEX, VALS(vals_reply_charging), 0x00,
+ "MMS-specific message reply charging method.",
+ HFILL
+ }
+ },
+ { &hf_mmse_reply_charging_deadline,
+ { "X-Mms-Reply-Charging-Deadline", "mmse.reply_charging_deadline",
+ FT_UINT8, BASE_HEX, VALS(vals_reply_charging_deadline), 0x00,
+ "MMS-specific message reply charging deadline type.",
+ HFILL
+ }
+ },
+ { &hf_mmse_reply_charging_id,
+ { "X-Mms-Reply-Charging-Id", "mmse.reply_charging_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Unique reply charging identification of the message.",
+ HFILL
+ }
+ },
+ { &hf_mmse_reply_charging_size,
+ { "X-Mms-Reply-Charging-Size", "mmse.reply_charging_size",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "The size of the reply charging in octets.",
+ HFILL
+ }
+ },
+ { &hf_mmse_prev_sent_by,
+ { "X-Mms-Previously-Sent-By", "mmse.previously_sent_by",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Indicates that the MM has been previously sent by this user.",
+ HFILL
+ }
+ },
+ { &hf_mmse_prev_sent_by_fwd_count,
+ { "Forward Count", "mmse.previously_sent_by.forward_count",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Forward count of the previously sent MM.",
+ HFILL
+ }
+ },
+ { &hf_mmse_prev_sent_by_address,
+ { "Address", "mmse.previously_sent_by.address",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Indicates from whom the MM has been previously sent.",
+ HFILL
+ }
+ },
+ { &hf_mmse_prev_sent_date,
+ { "X-Mms-Previously-Sent-Date", "mmse.previously_sent_date",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Indicates the date that the MM has been previously sent.",
+ HFILL
+ }
+ },
+ { &hf_mmse_prev_sent_date_fwd_count,
+ { "Forward Count", "mmse.previously_sent_date.forward_count",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Forward count of the previously sent MM.",
+ HFILL
+ }
+ },
+ { &hf_mmse_prev_sent_date_date,
+ { "Date", "mmse.previously_sent_date.date",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Time when the MM has been previously sent.",
+ HFILL
+ }
+ },
+
+
+
+ };
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_mmse,
+ &ett_mmse_hdr_details,
+ };
+
+ /* Register the protocol name and description */
+ proto_mmse = proto_register_protocol("MMS Message Encapsulation",
+ "MMSE", "mmse");
+
+ /* Required function calls to register header fields and subtrees used */
+ proto_register_field_array(proto_mmse, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+/* If this dissector uses sub-dissector registration add registration routine.
+ * This format is required because a script is used to find these routines and
+ * create the code that calls these routines.
+ */
+void
+proto_reg_handoff_mmse(void)
+{
+ dissector_handle_t mmse_standalone_handle;
+ dissector_handle_t mmse_encapsulated_handle;
+
+ heur_dissector_add("wsp", dissect_mmse_heur, proto_mmse);
+ mmse_standalone_handle = create_dissector_handle(
+ dissect_mmse_standalone, proto_mmse);
+ mmse_encapsulated_handle = create_dissector_handle(
+ dissect_mmse_encapsulated, proto_mmse);
+ /* As the media types for WSP and HTTP are the same, the WSP dissector
+ * uses the same string dissector table as the HTTP protocol. */
+ dissector_add_string("media_type",
+ "application/vnd.wap.mms-message", mmse_standalone_handle);
+ dissector_add_string("multipart_media_type",
+ "application/vnd.wap.mms-message", mmse_encapsulated_handle);
+}
diff --git a/epan/dissectors/packet-mount.c b/epan/dissectors/packet-mount.c
new file mode 100644
index 0000000000..7dd2c345c9
--- /dev/null
+++ b/epan/dissectors/packet-mount.c
@@ -0,0 +1,1109 @@
+/* packet-mount.c
+ * Routines for mount dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-smb.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <string.h>
+
+#include "packet-rpc.h"
+#include "packet-mount.h"
+#include "packet-nfs.h"
+
+
+static int proto_mount = -1;
+static int proto_sgi_mount = -1;
+static int hf_mount_procedure_v1 = -1;
+static int hf_mount_procedure_v2 = -1;
+static int hf_mount_procedure_v3 = -1;
+static int hf_sgi_mount_procedure_v1 = -1;
+static int hf_mount_path = -1;
+static int hf_mount3_status = -1;
+static int hf_mount_mountlist_hostname = -1;
+static int hf_mount_mountlist_directory = -1;
+static int hf_mount_mountlist = -1;
+static int hf_mount_groups_group = -1;
+static int hf_mount_groups = -1;
+static int hf_mount_exportlist_directory = -1;
+static int hf_mount_exportlist = -1;
+static int hf_mount_has_options = -1;
+static int hf_mount_options = -1;
+static int hf_mount_pathconf_link_max = -1;
+static int hf_mount_pathconf_max_canon = -1;
+static int hf_mount_pathconf_max_input = -1;
+static int hf_mount_pathconf_name_max = -1;
+static int hf_mount_pathconf_path_max = -1;
+static int hf_mount_pathconf_pipe_buf = -1;
+static int hf_mount_pathconf_vdisable = -1;
+static int hf_mount_pathconf_mask = -1;
+static int hf_mount_pathconf_error_all = -1;
+static int hf_mount_pathconf_error_link_max = -1;
+static int hf_mount_pathconf_error_max_canon = -1;
+static int hf_mount_pathconf_error_max_input = -1;
+static int hf_mount_pathconf_error_name_max = -1;
+static int hf_mount_pathconf_error_path_max = -1;
+static int hf_mount_pathconf_error_pipe_buf = -1;
+static int hf_mount_pathconf_chown_restricted = -1;
+static int hf_mount_pathconf_no_trunc = -1;
+static int hf_mount_pathconf_error_vdisable = -1;
+static int hf_mount_statvfs_bsize = -1;
+static int hf_mount_statvfs_frsize = -1;
+static int hf_mount_statvfs_blocks = -1;
+static int hf_mount_statvfs_bfree = -1;
+static int hf_mount_statvfs_bavail = -1;
+static int hf_mount_statvfs_files = -1;
+static int hf_mount_statvfs_ffree = -1;
+static int hf_mount_statvfs_favail = -1;
+static int hf_mount_statvfs_fsid = -1;
+static int hf_mount_statvfs_basetype = -1;
+static int hf_mount_statvfs_flag = -1;
+static int hf_mount_statvfs_flag_rdonly = -1;
+static int hf_mount_statvfs_flag_nosuid = -1;
+static int hf_mount_statvfs_flag_notrunc = -1;
+static int hf_mount_statvfs_flag_nodev = -1;
+static int hf_mount_statvfs_flag_grpid = -1;
+static int hf_mount_statvfs_flag_local = -1;
+static int hf_mount_statvfs_namemax = -1;
+static int hf_mount_statvfs_fstr = -1;
+static int hf_mount_flavors = -1;
+static int hf_mount_flavor = -1;
+
+static gint ett_mount = -1;
+static gint ett_mount_mountlist = -1;
+static gint ett_mount_groups = -1;
+static gint ett_mount_exportlist = -1;
+static gint ett_mount_pathconf_mask = -1;
+static gint ett_mount_statvfs_flag = -1;
+
+#define MAX_GROUP_NAME_LIST 128
+static char group_name_list[MAX_GROUP_NAME_LIST];
+static int group_names_len;
+
+/* RFC 1094, Page 24 */
+/* This function dissects fhstatus for v1 and v2 of the mount protocol.
+ * Formally, hf_mount3_status only define the status codes returned by version
+ * 3 of the protocol.
+ * Though not formally defined in the standard, we use the same
+ * value-to-string mappings as version 3 since we belive that this mapping
+ * is consistant with most v1 and v2 implementations.
+ */
+static int
+dissect_fhstatus(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ gint32 status;
+
+ status=tvb_get_ntohl(tvb,offset);
+ offset = dissect_rpc_uint32(tvb,tree,hf_mount3_status,offset);
+
+ switch (status) {
+ case 0:
+ offset = dissect_fhandle(tvb,offset,pinfo,tree,"fhandle", NULL);
+ break;
+ default:
+ /* void */
+ break;
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_mount_dirpath_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
+ rpc_call_info_value *civ=pinfo->private_data;
+
+ if(civ->request && (civ->proc==1)){
+ unsigned char *host, *name;
+ unsigned const char *dir;
+ int len;
+
+ host=ip_to_str(pinfo->dst.data);
+ len=tvb_get_ntohl(tvb, offset);
+
+ dir=tvb_get_ptr(tvb, offset+4, len);
+ if(dir){
+ unsigned char *ptr;
+ name=g_malloc(strlen(host)+1+len+1+200);
+ ptr=name;
+ memcpy(ptr, host, strlen(host));
+ ptr+=strlen(host);
+ *ptr++=':';
+ memcpy(ptr, dir, len);
+ ptr+=len;
+ *ptr=0;
+
+ nfs_name_snoop_add_name(civ->xid, tvb, -1, strlen(name), 0, 0, name);
+ }
+ }
+ }
+
+ if ( tree )
+ {
+ offset = dissect_rpc_string(tvb,tree,hf_mount_path,offset,NULL);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 25,26 */
+static int
+dissect_mount1_mnt_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_fhstatus(tvb,offset,pinfo,tree);
+
+ return offset;
+}
+
+
+
+/* RFC 1094, Page 26 */
+/* RFC 1813, Page 110 */
+static int
+dissect_mountlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+ char* hostname;
+ char* directory;
+
+ if (tree) {
+ lock_item = proto_tree_add_item(tree, hf_mount_mountlist, tvb,
+ offset, -1, FALSE);
+ if (lock_item)
+ lock_tree = proto_item_add_subtree(lock_item, ett_mount_mountlist);
+ }
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_mount_mountlist_hostname, offset, &hostname);
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_mount_mountlist_directory, offset, &directory);
+
+ if (lock_item) {
+ /* now we have a nicer string */
+ proto_item_set_text(lock_item, "Mount List Entry: %s:%s", hostname, directory);
+ /* now we know, that mountlist is shorter */
+ proto_item_set_len(lock_item, offset - old_offset);
+ }
+ g_free(hostname);
+ g_free(directory);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 26 */
+/* RFC 1813, Page 110 */
+static int
+dissect_mount_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_mountlist);
+
+ return offset;
+}
+
+
+
+/* RFC 1094, Page 26 */
+/* RFC 1813, Page 110 */
+static int
+dissect_group(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ int len,str_len;
+ len=tvb_get_ntohl(tvb,offset);
+ if (group_names_len < MAX_GROUP_NAME_LIST - 5) {
+ str_len=tvb_get_nstringz(tvb,offset+4,
+ MAX_GROUP_NAME_LIST-5-group_names_len,
+ group_name_list+group_names_len);
+ if((group_names_len>=(MAX_GROUP_NAME_LIST-5))||(str_len<0)){
+ strcpy(group_name_list+(MAX_GROUP_NAME_LIST-5),"...");
+ group_names_len=MAX_GROUP_NAME_LIST;
+ } else {
+ group_names_len+=str_len;
+ group_name_list[group_names_len++]=' ';
+ }
+ group_name_list[group_names_len]=0;
+ }
+
+ offset = dissect_rpc_string(tvb, tree,
+ hf_mount_groups_group, offset, NULL);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 26 */
+/* RFC 1813, Page 113 */
+static int
+dissect_exportlist(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item* exportlist_item = NULL;
+ proto_tree* exportlist_tree = NULL;
+ int old_offset = offset;
+ int groups_offset;
+ proto_item* groups_item = NULL;
+ proto_item* groups_tree = NULL;
+ char* directory;
+
+ group_name_list[0]=0;
+ group_names_len=0;
+ if (tree) {
+ exportlist_item = proto_tree_add_item(tree, hf_mount_exportlist, tvb,
+ offset, -1, FALSE);
+ if (exportlist_item)
+ exportlist_tree = proto_item_add_subtree(exportlist_item, ett_mount_exportlist);
+ }
+
+ offset = dissect_rpc_string(tvb, exportlist_tree,
+ hf_mount_exportlist_directory, offset, &directory);
+ groups_offset = offset;
+
+ if (tree) {
+ groups_item = proto_tree_add_item(exportlist_tree, hf_mount_groups, tvb,
+ offset, -1, FALSE);
+ if (groups_item)
+ groups_tree = proto_item_add_subtree(groups_item, ett_mount_groups);
+ }
+
+ offset = dissect_rpc_list(tvb, pinfo, groups_tree, offset, dissect_group);
+ if (groups_item) {
+ /* mark empty lists */
+ if (offset - groups_offset == 4) {
+ proto_item_set_text(groups_item, "Groups: empty");
+ }
+
+ /* now we know, that groups is shorter */
+ proto_item_set_len(groups_item, offset - groups_offset);
+ }
+
+ if (exportlist_item) {
+ /* now we have a nicer string */
+ proto_item_set_text(exportlist_item, "Export List Entry: %s -> %s", directory,group_name_list);
+ /* now we know, that exportlist is shorter */
+ proto_item_set_len(exportlist_item, offset - old_offset);
+ }
+ g_free(directory);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 26 */
+/* RFC 1813, Page 113 */
+static int
+dissect_mount_export_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_exportlist);
+
+ return offset;
+}
+
+
+#define OFFS_MASK 32 /* offset of the "pc_mask" field */
+
+#define PC_ERROR_ALL 0x0001
+#define PC_ERROR_LINK_MAX 0x0002
+#define PC_ERROR_MAX_CANON 0x0004
+#define PC_ERROR_MAX_INPUT 0x0008
+#define PC_ERROR_NAME_MAX 0x0010
+#define PC_ERROR_PATH_MAX 0x0020
+#define PC_ERROR_PIPE_BUF 0x0040
+#define PC_CHOWN_RESTRICTED 0x0080
+#define PC_NO_TRUNC 0x0100
+#define PC_ERROR_VDISABLE 0x0200
+
+static const true_false_string tos_error_all = {
+ "All info invalid",
+ "Some or all info valid"
+};
+
+static const true_false_string tos_error_link_max = {
+ "LINK_MAX invalid",
+ "LINK_MAX valid"
+};
+
+static const true_false_string tos_error_max_canon = {
+ "MAX_CANON invalid",
+ "MAX_CANON valid"
+};
+
+static const true_false_string tos_error_max_input = {
+ "MAX_INPUT invalid",
+ "MAX_INPUT valid"
+};
+
+static const true_false_string tos_error_name_max = {
+ "NAME_MAX invalid",
+ "NAME_MAX valid"
+};
+
+static const true_false_string tos_error_path_max = {
+ "PATH_MAX invalid",
+ "PATH_MAX valid"
+};
+
+static const true_false_string tos_error_pipe_buf = {
+ "PIPE_BUF invalid",
+ "PIPE_BUF valid"
+};
+
+static const true_false_string tos_chown_restricted = {
+ "Only a privileged user can change the ownership of a file",
+ "Users may give away their own files"
+};
+
+static const true_false_string tos_no_trunc = {
+ "File names that are too long will get an error",
+ "File names that are too long will be truncated"
+};
+
+static const true_false_string tos_error_vdisable = {
+ "VDISABLE invalid",
+ "VDISABLE valid"
+};
+
+
+static int
+dissect_mount_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ int saved_offset;
+ guint32 pc_mask;
+ proto_item *lock_item;
+ proto_tree *lock_tree;
+
+ saved_offset=offset;
+ /*
+ * Extract the mask first, so we know which other fields the
+ * server was able to return to us.
+ */
+ pc_mask = tvb_get_ntohl(tvb, offset+OFFS_MASK) & 0xffff;
+ if (!(pc_mask & (PC_ERROR_LINK_MAX|PC_ERROR_ALL))) {
+ if (tree) {
+ dissect_rpc_uint32(tvb,tree,hf_mount_pathconf_link_max,offset);
+ }
+ }
+ offset += 4;
+
+ if (!(pc_mask & (PC_ERROR_MAX_CANON|PC_ERROR_ALL))) {
+ if (tree) {
+ proto_tree_add_item(tree,
+ hf_mount_pathconf_max_canon,tvb,offset+2,2,
+ tvb_get_ntohs(tvb,offset)&0xffff);
+ }
+ }
+ offset += 4;
+
+ if (!(pc_mask & (PC_ERROR_MAX_INPUT|PC_ERROR_ALL))) {
+ if (tree) {
+ proto_tree_add_item(tree,
+ hf_mount_pathconf_max_input,tvb,offset+2,2,
+ tvb_get_ntohs(tvb,offset)&0xffff);
+ }
+ }
+ offset += 4;
+
+ if (!(pc_mask & (PC_ERROR_NAME_MAX|PC_ERROR_ALL))) {
+ if (tree) {
+ proto_tree_add_item(tree,
+ hf_mount_pathconf_name_max,tvb,offset+2,2,
+ tvb_get_ntohs(tvb,offset)&0xffff);
+ }
+ }
+ offset += 4;
+
+ if (!(pc_mask & (PC_ERROR_PATH_MAX|PC_ERROR_ALL))) {
+ if (tree) {
+ proto_tree_add_item(tree,
+ hf_mount_pathconf_path_max,tvb,offset+2,2,
+ tvb_get_ntohs(tvb,offset)&0xffff);
+ }
+ }
+ offset += 4;
+
+ if (!(pc_mask & (PC_ERROR_PIPE_BUF|PC_ERROR_ALL))) {
+ if (tree) {
+ proto_tree_add_item(tree,
+ hf_mount_pathconf_pipe_buf,tvb,offset+2,2,
+ tvb_get_ntohs(tvb,offset)&0xffff);
+ }
+ }
+ offset += 4;
+
+ offset += 4; /* skip "pc_xxx" pad field */
+
+ if (!(pc_mask & (PC_ERROR_VDISABLE|PC_ERROR_ALL))) {
+ if (tree) {
+ proto_tree_add_item(tree,
+ hf_mount_pathconf_vdisable,tvb,offset+3,1,
+ tvb_get_ntohs(tvb,offset)&0xffff);
+ }
+ }
+ offset += 4;
+
+
+ if (tree) {
+ lock_item = proto_tree_add_item(tree, hf_mount_pathconf_mask, tvb,
+ offset+2, 2, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_mount_pathconf_mask);
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_all, tvb,
+ offset + 2, 2, pc_mask);
+
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_link_max, tvb,
+ offset + 2, 2, pc_mask);
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_max_canon, tvb,
+ offset + 2, 2, pc_mask);
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_max_input, tvb,
+ offset + 2, 2, pc_mask);
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_name_max, tvb,
+ offset + 2, 2, pc_mask);
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_path_max, tvb,
+ offset + 2, 2, pc_mask);
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_pipe_buf, tvb,
+ offset + 2, 2, pc_mask);
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_chown_restricted, tvb,
+ offset + 2, 2, pc_mask);
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_no_trunc, tvb,
+ offset + 2, 2, pc_mask);
+ proto_tree_add_boolean(lock_tree, hf_mount_pathconf_error_vdisable, tvb,
+ offset + 2, 2, pc_mask);
+ }
+
+ offset += 8;
+ return offset;
+}
+
+/* RFC 1813, Page 107 */
+static const value_string mount3_mountstat3[] =
+{
+ { 0, "OK" },
+ { 1, "ERR_PERM" },
+ { 2, "ERR_NOENT" },
+ { 5, "ERR_IO" },
+ { 13, "ERR_ACCESS" },
+ { 20, "ERR_NOTDIR" },
+ { 22, "ERR_INVAL" },
+ { 63, "ERR_NAMETOOLONG" },
+ { 10004, "ERR_NOTSUPP" },
+ { 10006, "ERR_SERVERFAULT" },
+ { 0, NULL }
+};
+
+
+/* RFC 1813, Page 107 */
+static int
+dissect_mountstat3(tvbuff_t *tvb, proto_tree *tree, int offset, int hfindex, guint32 *status)
+{
+ guint32 mountstat3;
+
+ mountstat3 = tvb_get_ntohl(tvb, offset);
+
+ offset = dissect_rpc_uint32(tvb,tree,hfindex,offset);
+ *status = mountstat3;
+ return offset;
+}
+
+/* RFC 1831, Page 109 */
+static int
+dissect_mount3_mnt_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 status;
+ guint32 auth_flavors;
+ guint32 auth_flavor;
+ guint32 auth_flavor_i;
+
+ offset = dissect_mountstat3(tvb,tree,offset,hf_mount3_status,&status);
+
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_fh3(tvb,offset,pinfo,tree,"fhandle",NULL);
+
+ auth_flavors = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree,hf_mount_flavors, tvb,
+ offset, 4, auth_flavors);
+ offset += 4;
+ for (auth_flavor_i = 0 ; auth_flavor_i < auth_flavors ; auth_flavor_i++) {
+ auth_flavor = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree,hf_mount_flavor, tvb,
+ offset, 4, auth_flavor);
+ offset += 4;
+ }
+ break;
+ default:
+ /* void */
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_sgi_exportlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* exportlist_item = NULL;
+ proto_tree* exportlist_tree = NULL;
+ int old_offset = offset;
+ int options_offset;
+ char* directory, *options;
+
+ if (tree) {
+ exportlist_item = proto_tree_add_item(tree, hf_mount_exportlist,
+ tvb, offset, -1, FALSE);
+ if (exportlist_item)
+ exportlist_tree = proto_item_add_subtree(exportlist_item,
+ ett_mount_exportlist);
+ }
+
+ offset = dissect_rpc_string(tvb, exportlist_tree,
+ hf_mount_exportlist_directory, offset, &directory);
+
+ offset = dissect_rpc_bool(tvb, exportlist_tree,
+ hf_mount_has_options, offset);
+ options_offset = offset;
+
+ offset = dissect_rpc_string(tvb, exportlist_tree, hf_mount_options,
+ offset, &options);
+
+ if (exportlist_item) {
+ /* now we have a nicer string */
+ proto_item_set_text(exportlist_item,
+ "Export List Entry: %s %s", directory,
+ options);
+ /* now we know, that exportlist is shorter */
+ proto_item_set_len(exportlist_item, offset - old_offset);
+ }
+ g_free(directory);
+ g_free(options);
+
+ return offset;
+}
+
+static int
+dissect_mount_exportlist_reply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_sgi_exportlist);
+
+ return offset;
+}
+
+#define ST_RDONLY 0x00000001
+#define ST_NOSUID 0x00000002
+#define ST_NOTRUNC 0x00000004
+#define ST_NODEV 0x20000000
+#define ST_GRPID 0x40000000
+#define ST_LOCAL 0x80000000
+
+static const true_false_string tos_st_rdonly = {
+ "Read-only file system",
+ "Read/Write file system"
+};
+
+static const true_false_string tos_st_nosuid = {
+ "Does not support setuid/setgid semantics",
+ "Supports setuid/setgid semantics"
+};
+
+static const true_false_string tos_st_notrunc = {
+ "Does not trunctate filenames longer than NAME_MAX",
+ "Truncates filenames longer than NAME_MAX"
+};
+
+static const true_false_string tos_st_nodev = {
+ "Disallows opening of device files",
+ "Allows opening of device files"
+};
+
+static const true_false_string tos_st_grpid = {
+ "Group ID assigned from directory",
+ "Group ID not assigned from directory"
+};
+
+static const true_false_string tos_st_local = {
+ "File system is local",
+ "File system is not local"
+};
+
+static int
+dissect_mount_statvfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item *flag_item;
+ proto_tree *flag_tree;
+ guint32 statvfs_flags;
+
+ statvfs_flags = tvb_get_ntohl(tvb, offset+52);
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_bsize, offset);
+ }
+ offset += 4;
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_frsize, offset);
+ }
+ offset += 4;
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_blocks, offset);
+ }
+ offset += 4;
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_bfree, offset);
+ }
+ offset += 4;
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_bavail, offset);
+ }
+ offset += 4;
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_files, offset);
+ }
+ offset += 4;
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_ffree, offset);
+ }
+ offset += 4;
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_favail, offset);
+ }
+ offset += 4;
+ if (tree) {
+ dissect_rpc_bytes(tvb, tree, hf_mount_statvfs_basetype, offset,
+ 16, TRUE, NULL);
+ }
+ offset += 16;
+ if (tree) {
+ dissect_rpc_bytes(tvb, tree, hf_mount_statvfs_fstr, offset,
+ 32, FALSE, NULL);
+ }
+ offset += 32;
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_fsid, offset);
+ }
+ offset += 4;
+
+ if (tree) {
+ flag_item = proto_tree_add_item(tree, hf_mount_statvfs_flag,
+ tvb, offset, 4, FALSE);
+ if (flag_item) {
+ flag_tree = proto_item_add_subtree(flag_item,
+ ett_mount_statvfs_flag);
+ proto_tree_add_boolean(flag_tree,
+ hf_mount_statvfs_flag_rdonly, tvb, offset, 4,
+ statvfs_flags);
+ proto_tree_add_boolean(flag_tree,
+ hf_mount_statvfs_flag_nosuid, tvb, offset, 4,
+ statvfs_flags);
+ proto_tree_add_boolean(flag_tree,
+ hf_mount_statvfs_flag_notrunc, tvb, offset, 4,
+ statvfs_flags);
+ proto_tree_add_boolean(flag_tree,
+ hf_mount_statvfs_flag_nodev, tvb, offset, 4,
+ statvfs_flags);
+ proto_tree_add_boolean(flag_tree,
+ hf_mount_statvfs_flag_grpid, tvb, offset, 4,
+ statvfs_flags);
+ proto_tree_add_boolean(flag_tree,
+ hf_mount_statvfs_flag_local, tvb, offset, 4,
+ statvfs_flags);
+ }
+ }
+
+ offset += 4;
+ if (tree) {
+ dissect_rpc_uint32(tvb, tree, hf_mount_statvfs_namemax, offset);
+ }
+ offset += 4;
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+
+/* Mount protocol version 1, RFC 1094 */
+static const vsff mount1_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { MOUNTPROC_MNT, "MNT",
+ dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
+ { MOUNTPROC_DUMP, "DUMP",
+ NULL, dissect_mount_dump_reply },
+ { MOUNTPROC_UMNT, "UMNT",
+ dissect_mount_dirpath_call, NULL },
+ { MOUNTPROC_UMNTALL, "UMNTALL",
+ NULL, NULL },
+ { MOUNTPROC_EXPORT, "EXPORT",
+ NULL, dissect_mount_export_reply },
+ { MOUNTPROC_EXPORTALL, "EXPORTALL",
+ NULL, dissect_mount_export_reply },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string mount1_proc_vals[] = {
+ { 0, "NULL" },
+ { MOUNTPROC_MNT, "MNT" },
+ { MOUNTPROC_DUMP, "DUMP" },
+ { MOUNTPROC_UMNT, "UMNT" },
+ { MOUNTPROC_UMNTALL, "UMNTALL" },
+ { MOUNTPROC_EXPORT, "EXPORT" },
+ { MOUNTPROC_EXPORTALL, "EXPORTALL" },
+ { 0, NULL }
+};
+/* end of mount version 1 */
+
+
+/* Mount protocol version 2, private communication from somebody at Sun;
+ mount V2 is V1 plus MOUNTPROC_PATHCONF to fetch information for the
+ POSIX "pathconf()" call. */
+static const vsff mount2_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { MOUNTPROC_MNT, "MNT",
+ dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
+ { MOUNTPROC_DUMP, "DUMP",
+ NULL, dissect_mount_dump_reply },
+ { MOUNTPROC_UMNT, "UMNT",
+ dissect_mount_dirpath_call, NULL },
+ { MOUNTPROC_UMNTALL, "UMNTALL",
+ NULL, NULL },
+ { MOUNTPROC_EXPORT, "EXPORT",
+ NULL, dissect_mount_export_reply },
+ { MOUNTPROC_EXPORTALL, "EXPORTALL",
+ NULL, dissect_mount_export_reply },
+ { MOUNTPROC_PATHCONF, "PATHCONF",
+ dissect_mount_dirpath_call, dissect_mount_pathconf_reply },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string mount2_proc_vals[] = {
+ { 0, "NULL" },
+ { MOUNTPROC_MNT, "MNT" },
+ { MOUNTPROC_DUMP, "DUMP" },
+ { MOUNTPROC_UMNT, "UMNT" },
+ { MOUNTPROC_UMNTALL, "UMNTALL" },
+ { MOUNTPROC_EXPORT, "EXPORT" },
+ { MOUNTPROC_EXPORTALL, "EXPORTALL" },
+ { MOUNTPROC_PATHCONF, "PATHCONF" },
+ { 0, NULL }
+};
+/* end of mount version 2 */
+
+
+/* Mount protocol version 3, RFC 1813 */
+static const vsff mount3_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { MOUNTPROC_MNT, "MNT",
+ dissect_mount_dirpath_call, dissect_mount3_mnt_reply },
+ { MOUNTPROC_DUMP, "DUMP",
+ NULL, dissect_mount_dump_reply },
+ { MOUNTPROC_UMNT, "UMNT",
+ dissect_mount_dirpath_call, NULL },
+ { MOUNTPROC_UMNTALL, "UMNTALL",
+ NULL, NULL },
+ { MOUNTPROC_EXPORT, "EXPORT",
+ NULL, dissect_mount_export_reply },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string mount3_proc_vals[] = {
+ { 0, "NULL" },
+ { MOUNTPROC_MNT, "MNT" },
+ { MOUNTPROC_DUMP, "DUMP" },
+ { MOUNTPROC_UMNT, "UMNT" },
+ { MOUNTPROC_UMNTALL, "UMNTALL" },
+ { MOUNTPROC_EXPORT, "EXPORT" },
+ { 0, NULL }
+};
+/* end of Mount protocol version 3 */
+
+/* SGI mount protocol version 1; actually the same as v1 plus
+ MOUNTPROC_EXPORTLIST and MOUNTPROC_STATVFS */
+
+static const vsff sgi_mount1_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { MOUNTPROC_MNT, "MNT",
+ dissect_mount_dirpath_call, dissect_mount1_mnt_reply },
+ { MOUNTPROC_DUMP, "DUMP",
+ NULL, dissect_mount_dump_reply },
+ { MOUNTPROC_UMNT, "UMNT",
+ dissect_mount_dirpath_call, NULL },
+ { MOUNTPROC_UMNTALL, "UMNTALL",
+ NULL, NULL },
+ { MOUNTPROC_EXPORT, "EXPORT",
+ NULL, dissect_mount_export_reply },
+ { MOUNTPROC_EXPORTALL, "EXPORTALL",
+ NULL, dissect_mount_export_reply },
+ { MOUNTPROC_EXPORTLIST,"EXPORTLIST",
+ NULL, dissect_mount_exportlist_reply },
+ { MOUNTPROC_STATVFS, "STATVFS",
+ dissect_mount_dirpath_call, dissect_mount_statvfs_reply },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string sgi_mount1_proc_vals[] = {
+ { 0, "NULL" },
+ { MOUNTPROC_MNT, "MNT" },
+ { MOUNTPROC_DUMP, "DUMP" },
+ { MOUNTPROC_UMNT, "UMNT" },
+ { MOUNTPROC_UMNTALL, "UMNTALL" },
+ { MOUNTPROC_EXPORT, "EXPORT" },
+ { MOUNTPROC_EXPORTALL, "EXPORTALL" },
+ { MOUNTPROC_EXPORTLIST, "EXPORTLIST" },
+ { MOUNTPROC_STATVFS, "STATVFS" },
+ { 0, NULL }
+};
+/* end of SGI mount protocol version 1 */
+
+void
+proto_register_mount(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_mount_procedure_v1, {
+ "V1 Procedure", "mount.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(mount1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_mount_procedure_v2, {
+ "V2 Procedure", "mount.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(mount2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_mount_procedure_v3, {
+ "V3 Procedure", "mount.procedure_v3", FT_UINT32, BASE_DEC,
+ VALS(mount3_proc_vals), 0, "V3 Procedure", HFILL }},
+ { &hf_sgi_mount_procedure_v1, {
+ "SGI V1 procedure", "mount.procedure_sgi_v1", FT_UINT32, BASE_DEC,
+ VALS(sgi_mount1_proc_vals), 0, "SGI V1 Procedure", HFILL }},
+ { &hf_mount_path, {
+ "Path", "mount.path", FT_STRING, BASE_DEC,
+ NULL, 0, "Path", HFILL }},
+ { &hf_mount3_status, {
+ "Status", "mount.status", FT_UINT32, BASE_DEC,
+ VALS(mount3_mountstat3), 0, "Status", HFILL }},
+ { &hf_mount_mountlist_hostname, {
+ "Hostname", "mount.dump.hostname", FT_STRING, BASE_DEC,
+ NULL, 0, "Hostname", HFILL }},
+ { &hf_mount_mountlist_directory, {
+ "Directory", "mount.dump.directory", FT_STRING, BASE_DEC,
+ NULL, 0, "Directory", HFILL }},
+ { &hf_mount_mountlist, {
+ "Mount List Entry", "mount.dump.entry", FT_NONE, 0,
+ NULL, 0, "Mount List Entry", HFILL }},
+ { &hf_mount_groups_group, {
+ "Group", "mount.export.group", FT_STRING, BASE_DEC,
+ NULL, 0, "Group", HFILL }},
+ { &hf_mount_groups, {
+ "Groups", "mount.export.groups", FT_NONE, 0,
+ NULL, 0, "Groups", HFILL }},
+ { &hf_mount_has_options, {
+ "Has options", "mount.export.has_options", FT_UINT32,
+ BASE_DEC, NULL, 0, "Has options", HFILL }},
+ { &hf_mount_options, {
+ "Options", "mount.export.options", FT_STRING, BASE_DEC,
+ NULL, 0, "Options", HFILL }},
+ { &hf_mount_exportlist_directory, {
+ "Directory", "mount.export.directory", FT_STRING, BASE_DEC,
+ NULL, 0, "Directory", HFILL }},
+ { &hf_mount_exportlist, {
+ "Export List Entry", "mount.export.entry", FT_NONE, 0,
+ NULL, 0, "Export List Entry", HFILL }},
+ { &hf_mount_pathconf_link_max, {
+ "Maximum number of links to a file", "mount.pathconf.link_max",
+ FT_UINT32, BASE_DEC,
+ NULL, 0, "Maximum number of links allowed to a file", HFILL }},
+ { &hf_mount_pathconf_max_canon, {
+ "Maximum terminal input line length", "mount.pathconf.max_canon",
+ FT_UINT16, BASE_DEC,
+ NULL, 0, "Max tty input line length", HFILL }},
+ { &hf_mount_pathconf_max_input, {
+ "Terminal input buffer size", "mount.pathconf.max_input",
+ FT_UINT16, BASE_DEC,
+ NULL, 0, "Terminal input buffer size", HFILL }},
+ { &hf_mount_pathconf_name_max, {
+ "Maximum file name length", "mount.pathconf.name_max",
+ FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum file name length", HFILL }},
+ { &hf_mount_pathconf_path_max, {
+ "Maximum path name length", "mount.pathconf.path_max",
+ FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum path name length", HFILL }},
+ { &hf_mount_pathconf_pipe_buf, {
+ "Pipe buffer size", "mount.pathconf.pipe_buf",
+ FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum amount of data that can be written atomically to a pipe", HFILL }},
+ { &hf_mount_pathconf_vdisable, {
+ "VDISABLE character", "mount.pathconf.vdisable_char",
+ FT_UINT8, BASE_HEX,
+ NULL, 0, "Character value to disable a terminal special character", HFILL }},
+ { &hf_mount_pathconf_mask, {
+ "Reply error/status bits", "mount.pathconf.mask",
+ FT_UINT16, BASE_HEX,
+ NULL, 0, "Bit mask with error and status bits", HFILL }},
+ { &hf_mount_pathconf_error_all, {
+ "ERROR_ALL", "mount.pathconf.mask.error_all",
+ FT_BOOLEAN, 16, TFS(&tos_error_all),
+ PC_ERROR_ALL, "", HFILL }},
+ { &hf_mount_pathconf_error_link_max, {
+ "ERROR_LINK_MAX", "mount.pathconf.mask.error_link_max",
+ FT_BOOLEAN, 16, TFS(&tos_error_link_max),
+ PC_ERROR_LINK_MAX, "", HFILL }},
+ { &hf_mount_pathconf_error_max_canon, {
+ "ERROR_MAX_CANON", "mount.pathconf.mask.error_max_canon",
+ FT_BOOLEAN, 16, TFS(&tos_error_max_canon),
+ PC_ERROR_MAX_CANON, "", HFILL }},
+ { &hf_mount_pathconf_error_max_input, {
+ "ERROR_MAX_INPUT", "mount.pathconf.mask.error_max_input",
+ FT_BOOLEAN, 16, TFS(&tos_error_max_input),
+ PC_ERROR_MAX_INPUT, "", HFILL }},
+ { &hf_mount_pathconf_error_name_max, {
+ "ERROR_NAME_MAX", "mount.pathconf.mask.error_name_max",
+ FT_BOOLEAN, 16, TFS(&tos_error_name_max),
+ PC_ERROR_NAME_MAX, "", HFILL }},
+ { &hf_mount_pathconf_error_path_max, {
+ "ERROR_PATH_MAX", "mount.pathconf.mask.error_path_max",
+ FT_BOOLEAN, 16, TFS(&tos_error_path_max),
+ PC_ERROR_PATH_MAX, "", HFILL }},
+ { &hf_mount_pathconf_error_pipe_buf, {
+ "ERROR_PIPE_BUF", "mount.pathconf.mask.error_pipe_buf",
+ FT_BOOLEAN, 16, TFS(&tos_error_pipe_buf),
+ PC_ERROR_PIPE_BUF, "", HFILL }},
+ { &hf_mount_pathconf_chown_restricted, {
+ "CHOWN_RESTRICTED", "mount.pathconf.mask.chown_restricted",
+ FT_BOOLEAN, 16, TFS(&tos_chown_restricted),
+ PC_CHOWN_RESTRICTED, "", HFILL }},
+ { &hf_mount_pathconf_no_trunc, {
+ "NO_TRUNC", "mount.pathconf.mask.no_trunc",
+ FT_BOOLEAN, 16, TFS(&tos_no_trunc),
+ PC_NO_TRUNC, "", HFILL }},
+ { &hf_mount_pathconf_error_vdisable, {
+ "ERROR_VDISABLE", "mount.pathconf.mask.error_vdisable",
+ FT_BOOLEAN, 16, TFS(&tos_error_vdisable),
+ PC_ERROR_VDISABLE, "", HFILL }},
+ { &hf_mount_statvfs_bsize, {
+ "Block size", "mount.statvfs.f_bsize",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "File system block size", HFILL }},
+ { &hf_mount_statvfs_frsize, {
+ "Fragment size", "mount.statvfs.f_frsize",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "File system fragment size", HFILL }},
+ { &hf_mount_statvfs_blocks, {
+ "Blocks", "mount.statvfs.f_blocks",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Total fragment sized blocks", HFILL }},
+ { &hf_mount_statvfs_bfree, {
+ "Blocks Free", "mount.statvfs.f_bfree",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Free fragment sized blocks", HFILL }},
+ { &hf_mount_statvfs_bavail, {
+ "Blocks Available", "mount.statvfs.f_bavail",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Available fragment sized blocks", HFILL }},
+ { &hf_mount_statvfs_files, {
+ "Files", "mount.statvfs.f_files",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Total files/inodes", HFILL }},
+ { &hf_mount_statvfs_ffree, {
+ "Files Free", "mount.statvfs.f_ffree",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Free files/inodes", HFILL }},
+ { &hf_mount_statvfs_favail, {
+ "Files Available", "mount.statvfs.f_favail",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Available files/inodes", HFILL }},
+ { &hf_mount_statvfs_fsid, {
+ "File system ID", "mount.statvfs.f_fsid",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "File system identifier", HFILL }},
+ { &hf_mount_statvfs_basetype, {
+ "Type", "mount.statvfs.f_basetype",
+ FT_STRING, BASE_DEC, NULL, 0,
+ "File system type", HFILL }},
+ { &hf_mount_statvfs_flag, {
+ "Flags", "mount.statvfs.f_flag",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Flags bit-mask", HFILL }},
+ { &hf_mount_statvfs_flag_rdonly, {
+ "ST_RDONLY", "mount.statvfs.f_flag.st_rdonly",
+ FT_BOOLEAN, 32, TFS(&tos_st_rdonly), ST_RDONLY,
+ "", HFILL }},
+ { &hf_mount_statvfs_flag_nosuid, {
+ "ST_NOSUID", "mount.statvfs.f_flag.st_nosuid",
+ FT_BOOLEAN, 32, TFS(&tos_st_nosuid), ST_NOSUID,
+ "", HFILL }},
+ { &hf_mount_statvfs_flag_notrunc, {
+ "ST_NOTRUNC", "mount.statvfs.f_flag.st_notrunc",
+ FT_BOOLEAN, 32, TFS(&tos_st_notrunc), ST_NOTRUNC,
+ "", HFILL }},
+ { &hf_mount_statvfs_flag_nodev, {
+ "ST_NODEV", "mount.statvfs.f_flag.st_nodev",
+ FT_BOOLEAN, 32, TFS(&tos_st_nodev), ST_NODEV,
+ "", HFILL }},
+ { &hf_mount_statvfs_flag_grpid, {
+ "ST_GRPID", "mount.statvfs.f_flag.st_grpid",
+ FT_BOOLEAN, 32, TFS(&tos_st_grpid), ST_GRPID,
+ "", HFILL }},
+ { &hf_mount_statvfs_flag_local, {
+ "ST_LOCAL", "mount.statvfs.f_flag.st_local",
+ FT_BOOLEAN, 32, TFS(&tos_st_local), ST_LOCAL,
+ "", HFILL }},
+ { &hf_mount_statvfs_namemax, {
+ "Maximum file name length", "mount.statvfs.f_namemax",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Maximum file name length", HFILL }},
+ { &hf_mount_statvfs_fstr, {
+ "File system specific string", "mount.statvfs.f_fstr",
+ FT_BYTES, BASE_HEX, NULL, 0,
+ "File system specific string", HFILL }},
+ { &hf_mount_flavors, {
+ "Flavors", "mount.flavors", FT_UINT32, BASE_DEC,
+ NULL, 0, "Flavors", HFILL }},
+ { &hf_mount_flavor, {
+ "Flavor", "mount.flavor", FT_UINT32, BASE_DEC,
+ VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_mount,
+ &ett_mount_mountlist,
+ &ett_mount_groups,
+ &ett_mount_exportlist,
+ &ett_mount_pathconf_mask,
+ &ett_mount_statvfs_flag,
+ };
+
+ proto_mount = proto_register_protocol("Mount Service", "MOUNT",
+ "mount");
+ proto_sgi_mount = proto_register_protocol("SGI Mount Service",
+ "SGI MOUNT", "sgimount");
+ proto_register_field_array(proto_mount, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mount(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_mount, MOUNT_PROGRAM, ett_mount);
+ rpc_init_prog(proto_sgi_mount, SGI_MOUNT_PROGRAM, ett_mount);
+ /* Register the procedure tables */
+ rpc_init_proc_table(MOUNT_PROGRAM, 1, mount1_proc, hf_mount_procedure_v1);
+ rpc_init_proc_table(MOUNT_PROGRAM, 2, mount2_proc, hf_mount_procedure_v2);
+ rpc_init_proc_table(MOUNT_PROGRAM, 3, mount3_proc, hf_mount_procedure_v3);
+ rpc_init_proc_table(SGI_MOUNT_PROGRAM, 1, sgi_mount1_proc, hf_sgi_mount_procedure_v1);
+}
diff --git a/epan/dissectors/packet-mount.h b/epan/dissectors/packet-mount.h
new file mode 100644
index 0000000000..a6b503e2a8
--- /dev/null
+++ b/epan/dissectors/packet-mount.h
@@ -0,0 +1,21 @@
+/* packet-mount.h */
+/* $Id$ */
+
+#ifndef PACKET_MOUNT_H
+#define PACKET_MOUNT_H
+
+#define MOUNT_PROGRAM 100005
+
+#define MOUNTPROC_NULL 0
+#define MOUNTPROC_MNT 1
+#define MOUNTPROC_DUMP 2
+#define MOUNTPROC_UMNT 3
+#define MOUNTPROC_UMNTALL 4
+#define MOUNTPROC_EXPORT 5
+#define MOUNTPROC_EXPORTALL 6
+#define MOUNTPROC_PATHCONF 7
+
+#define SGI_MOUNT_PROGRAM 391004
+#define MOUNTPROC_EXPORTLIST 99
+#define MOUNTPROC_STATVFS 100
+#endif
diff --git a/epan/dissectors/packet-mpeg1.c b/epan/dissectors/packet-mpeg1.c
new file mode 100644
index 0000000000..e0a94920e1
--- /dev/null
+++ b/epan/dissectors/packet-mpeg1.c
@@ -0,0 +1,394 @@
+/* packet-mpeg1.c
+ *
+ * Routines for RFC 2250 MPEG-1 dissection
+ *
+ * $Id$
+ *
+ * Copyright 2001,
+ * Francisco Javier Cabello Torres, <fjcabello@vtools.es>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect the MPEG-1 video streams.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "rtp_pt.h"
+
+#define RTP_MPG_MBZ(word) ( word >> 11)
+#define RTP_MPG_T(word) ( (word >> 10) & 1 )
+#define RTP_MPG_TR(word) ( word & 0x3ff )
+
+#define RTP_MPG_AN(octet) ( octet >> 7)
+#define RTP_MPG_N(octet) ( (octet >> 6) & 1 )
+#define RTP_MPG_S(octet) ( (octet >> 5) & 1 )
+#define RTP_MPG_B(octet) ( (octet >> 4) & 1 )
+#define RTP_MPG_E(octet) ( (octet >> 3) & 1 )
+#define RTP_MPG_P(octet) ( octet & 7 )
+
+#define RTP_MPG_FBV(octet) ( (octet >> 7) & 1 )
+#define RTP_MPG_BFC(octet) ( (octet >> 4) & 7 )
+#define RTP_MPG_FFV(octet) ( (octet >> 3) & 1 )
+#define RTP_MPG_FFC(octet) ( octet & 7 )
+
+
+/* MPEG1 header fields */
+
+
+static int proto_mpg = -1;
+
+static int hf_rtp_mpg_mbz = -1;
+static int hf_rtp_mpg_T = -1;
+static int hf_rtp_mpg_tr = -1;
+static int hf_rtp_mpg_an = -1;
+static int hf_rtp_mpg_n = -1;
+static int hf_rtp_mpg_s = -1;
+static int hf_rtp_mpg_b = -1;
+static int hf_rtp_mpg_e = -1;
+static int hf_rtp_mpg_p = -1;
+
+
+static int hf_rtp_mpg_fbv = -1;
+static int hf_rtp_mpg_bfc = -1;
+static int hf_rtp_mpg_ffv = -1;
+static int hf_rtp_mpg_ffc = -1;
+static int hf_rtp_mpg_data = -1;
+
+
+
+/* MPEG-1 fields defining a sub tree */
+static gint ett_mpg = -1;
+
+static const value_string rtp_mpg_picture_types_vals[] =
+{
+ { 0, "Forbidden" },
+ { 1, "I-Picture" },
+ { 2, "P-Picture" },
+ { 3, "B-Picture" },
+ { 4, "D-Picture" },
+ { 5, "reserved" },
+ { 6, "reserved" },
+ { 7, "reserved" },
+ { 0, NULL },
+};
+
+static void
+dissect_mpeg1( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *mpg_tree = NULL;
+ unsigned int offset = 0;
+
+ guint8 octet;
+ guint16 word;
+
+
+ guint16 mpg_mbz;
+ guint16 mpg_T;
+ guint16 mpg_tr;
+ guint16 mpg_an;
+ guint16 mpg_n;
+ gboolean mpg_s;
+ gboolean mpg_b;
+ gboolean mpg_e;
+ guint16 mpg_p;
+ guint16 mpg_fbv;
+ guint16 mpg_bfc;
+ guint16 mpg_ffv;
+ guint16 mpg_ffc;
+
+ if ( check_col( pinfo->cinfo, COL_PROTOCOL ) )
+ {
+ col_set_str( pinfo->cinfo, COL_PROTOCOL, "MPEG-1" );
+ }
+
+ if ( check_col( pinfo->cinfo, COL_INFO) )
+ {
+ col_set_str( pinfo->cinfo, COL_INFO, "MPEG-1 message");
+ }
+
+ /* Get MPEG-1 fields */
+
+ word = tvb_get_guint8( tvb, offset );
+ word = (word << 8) | tvb_get_guint8( tvb, offset +1 );
+ mpg_mbz = RTP_MPG_MBZ(word);
+ mpg_T = RTP_MPG_T(word);
+ mpg_tr = RTP_MPG_TR(word);
+
+ octet = tvb_get_guint8( tvb, offset + 2 );
+ mpg_an = RTP_MPG_AN(octet);
+ mpg_n = RTP_MPG_N(octet);
+ mpg_s = RTP_MPG_S(octet);
+ mpg_b = RTP_MPG_B(octet);
+ mpg_e = RTP_MPG_E(octet);
+ mpg_p = RTP_MPG_P(octet);
+
+ octet = tvb_get_guint8( tvb, offset + 3 );
+
+ mpg_fbv = RTP_MPG_FBV(octet);
+ mpg_bfc = RTP_MPG_BFC(octet);
+ mpg_ffv = RTP_MPG_FFV(octet);
+ mpg_ffc = RTP_MPG_FFC(octet);
+
+
+ if ( tree )
+ {
+ ti = proto_tree_add_item( tree, proto_mpg, tvb, offset, -1, FALSE );
+ mpg_tree = proto_item_add_subtree( ti, ett_mpg );
+
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_mbz, tvb, offset, 1, mpg_mbz );
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_T , tvb, offset, 1, mpg_T );
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_tr , tvb, offset, 2, mpg_tr );
+ offset += 2;
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_an, tvb, offset, 1, mpg_an );
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_n , tvb, offset, 1, mpg_n );
+ proto_tree_add_boolean( mpg_tree, hf_rtp_mpg_s , tvb, offset, 1, mpg_s );
+ proto_tree_add_boolean( mpg_tree, hf_rtp_mpg_b , tvb, offset, 1, mpg_b );
+ proto_tree_add_boolean( mpg_tree, hf_rtp_mpg_e , tvb, offset, 1, mpg_e );
+
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_p, tvb , offset, 1, mpg_p );
+ offset += 1;
+
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_fbv, tvb, offset, 1, mpg_fbv );
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_bfc, tvb, offset, 1, mpg_bfc );
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_ffv, tvb, offset, 1, mpg_ffv );
+ proto_tree_add_uint( mpg_tree, hf_rtp_mpg_ffc, tvb, offset, 1, mpg_ffc );
+ offset += 1;
+
+ /* The rest of the packet is the MPEG-1 stream */
+ proto_tree_add_item( mpg_tree, hf_rtp_mpg_data, tvb, offset, -1, FALSE );
+
+ }
+}
+
+void
+proto_register_mpeg1(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_rtp_mpg_mbz,
+ {
+ "MBZ",
+ "rtp.payload_mpeg_mbz",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_mpg_T,
+ {
+ "T",
+ "rtp.payload_mpeg_T",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_mpg_tr,
+ {
+ "Temporal Reference",
+ "rtp.payload_mpeg_tr",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_mpg_an,
+ {
+ "AN",
+ "rtp.payload_mpeg_an",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_rtp_mpg_n,
+ {
+ "New Picture Header",
+ "rtp.payload_mpeg_n",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_rtp_mpg_s,
+ {
+ "Sequence Header",
+ "rtp.payload_mpeg_s",
+ FT_BOOLEAN,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_rtp_mpg_b,
+ {
+ "Beginning-of-slice",
+ "rtp.payload_mpeg_b",
+ FT_BOOLEAN,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_rtp_mpg_e,
+ {
+ "End-of-slice",
+ "rtp.payload_mpeg_an",
+ FT_BOOLEAN,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_rtp_mpg_p,
+ {
+ "Picture type",
+ "rtp.payload_mpeg_p",
+ FT_UINT16,
+ BASE_DEC,
+ VALS(rtp_mpg_picture_types_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_rtp_mpg_fbv,
+ {
+ "FBV",
+ "rtp.payload_mpeg_fbv",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_rtp_mpg_bfc,
+ {
+ "BFC",
+ "rtp.payload_mpeg_bfc",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_mpg_ffv,
+ {
+ "FFV",
+ "rtp.payload_mpeg_ffv",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_rtp_mpg_ffc,
+ {
+ "FFC",
+ "rtp.payload_mpeg_ffc",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_mpg_data,
+ {
+ "MPEG-1 stream",
+ "mpeg1.stream",
+ FT_BYTES,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ };
+
+ static gint *ett[] =
+ {
+ &ett_mpg,
+ };
+
+
+ proto_mpg = proto_register_protocol("RFC 2250 MPEG1","MPEG1","mpeg1");
+ proto_register_field_array(proto_mpg, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mpeg1(void)
+{
+ dissector_handle_t mpeg1_handle;
+
+ mpeg1_handle = create_dissector_handle(dissect_mpeg1, proto_mpg);
+ dissector_add("rtp.pt", PT_MPV, mpeg1_handle);
+}
diff --git a/epan/dissectors/packet-mpls-echo.c b/epan/dissectors/packet-mpls-echo.c
new file mode 100644
index 0000000000..2dde42f368
--- /dev/null
+++ b/epan/dissectors/packet-mpls-echo.c
@@ -0,0 +1,526 @@
+/* packet-mpls-echo.c
+ * Routines for Multiprotocol Label Switching Echo dissection
+ * Copyright 2004, Carlos Pignataro <cpignata@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "packet-ntp.h"
+#include "packet-ldp.h"
+
+#define UDP_PORT_MPLS_ECHO 3503
+
+void proto_reg_handoff_mpls_echo(void);
+
+static int proto_mpls_echo = -1;
+static int hf_mpls_echo_version = -1;
+static int hf_mpls_echo_mbz = -1;
+static int hf_mpls_echo_msgtype = -1;
+static int hf_mpls_echo_replymode = -1;
+static int hf_mpls_echo_returncode = -1;
+static int hf_mpls_echo_returnsubcode = -1;
+static int hf_mpls_echo_handle = -1;
+static int hf_mpls_echo_sequence = -1;
+static int hf_mpls_echo_ts_sent = -1;
+static int hf_mpls_echo_ts_rec = -1;
+static int hf_mpls_echo_tlv_type = -1;
+static int hf_mpls_echo_tlv_len = -1;
+static int hf_mpls_echo_tlv_value = -1;
+static int hf_mpls_echo_tlv_fec_type = -1;
+static int hf_mpls_echo_tlv_fec_len = -1;
+static int hf_mpls_echo_tlv_fec_value = -1;
+static int hf_mpls_echo_tlv_fec_ldp_ipv4 = -1;
+static int hf_mpls_echo_tlv_fec_ldp_ipv4_mask = -1;
+static int hf_mpls_echo_tlv_fec_l2cid_sender = -1;
+static int hf_mpls_echo_tlv_fec_l2cid_remote = -1;
+static int hf_mpls_echo_tlv_fec_l2cid_vcid = -1;
+static int hf_mpls_echo_tlv_fec_l2cid_encap = -1;
+static int hf_mpls_echo_tlv_fec_l2cid_mbz = -1;
+static int hf_mpls_echo_tlv_padaction = -1;
+static int hf_mpls_echo_tlv_padding = -1;
+
+static gint ett_mpls_echo = -1;
+static gint ett_mpls_echo_tlv = -1;
+static gint ett_mpls_echo_tlv_fec = -1;
+
+static int mpls_echo_udp_port = 0;
+
+static guint32 global_mpls_echo_udp_port = UDP_PORT_MPLS_ECHO;
+
+static const value_string mpls_echo_msgtype[] = {
+ {1, "MPLS Echo Request"},
+ {2, "MPLS Echo Reply"},
+ {0, NULL}
+};
+
+static const value_string mpls_echo_replymode[] = {
+ {1, "Do not reply"},
+ {2, "Reply via an IPv4/IPv6 UDP packet"},
+ {3, "Reply via an IPv4/IPv6 UDP packet with Router Alert"},
+ {4, "Reply via application level control channel"},
+ {0, NULL}
+};
+
+static const value_string mpls_echo_returncode[] = {
+ {0, "No return code"},
+ {1, "Malformed echo request received"},
+ {2, "One or more of the TLVs was not understood"},
+ {3, "Replying router is an egress for the FEC at stack depth RSC"},
+ {4, "Replying router has no mapping for the FEC at stack depth RSC"},
+ {5, "Reserved"},
+ {6, "Reserved"},
+ {7, "Reserved"},
+ {8, "Label switched at stack-depth RSC"},
+ {9, "Label switched but no MPLS forwarding at stack-depth RSC"},
+ {10, "Mapping for this FEC is not the given label at stack depth RSC"},
+ {11, "No label entry at stack-depth RSC"},
+ {12, "Protocol not associated with interface at FEC stack depth RSC"},
+ {0, NULL}
+};
+
+#define TLV_TARGET_FEC_STACK 0x0001
+#define TLV_DOWNSTREAM_MAPPING 0x0002
+#define TLV_PAD 0x0003
+#define TLV_ERROR_CODE 0x0004
+#define TLV_VENDOR_CODE 0x0005
+
+/* MPLS Echo TLV Type names */
+static const value_string mpls_echo_tlv_type_names[] = {
+ { TLV_TARGET_FEC_STACK, "Target FEC Stack" },
+ { TLV_DOWNSTREAM_MAPPING, "Downstream Mapping" },
+ { TLV_PAD, "Pad" },
+ { TLV_ERROR_CODE, "Error Code" },
+ { TLV_VENDOR_CODE, "Vendor Enterprise Code" },
+ { 0, NULL}
+};
+
+#define TLV_FEC_STACK_LDP_IPv4 1
+#define TLV_FEC_STACK_LDP_IPv6 2
+#define TLV_FEC_STACK_RSVP_IPv4 3
+#define TLV_FEC_STACK_RSVP_IPv6 4
+#define TLV_FEC_STACK_RES 5
+#define TLV_FEC_STACK_VPN_IPv4 6
+#define TLV_FEC_STACK_VPN_IPv6 7
+#define TLV_FEC_STACK_L2_VPN 8
+#define TLV_FEC_STACK_L2_CID 9
+
+/* FEC sub-TLV Type names */
+static const value_string mpls_echo_tlv_fec_names[] = {
+ { TLV_FEC_STACK_LDP_IPv4, "LDP IPv4 prefix"},
+ { TLV_FEC_STACK_LDP_IPv6, "LDP IPv6 prefix"},
+ { TLV_FEC_STACK_RSVP_IPv4, "RSVP IPv4 Session Query"},
+ { TLV_FEC_STACK_RSVP_IPv6, "RSVP IPv6 Session Query"},
+ { TLV_FEC_STACK_RES, "Reserved"},
+ { TLV_FEC_STACK_VPN_IPv4, "VPN IPv4 prefix"},
+ { TLV_FEC_STACK_VPN_IPv6, "VPN IPv6 prefix"},
+ { TLV_FEC_STACK_L2_VPN, "L2 VPN endpoint"},
+ { TLV_FEC_STACK_L2_CID, "L2 cirtuit ID"},
+ { 0, NULL}
+};
+
+static const value_string mpls_echo_tlv_pad[] = {
+ { 1, "Drop Pad TLV from reply" },
+ { 2, "Copy Pad TLV to reply" },
+ { 0, NULL}
+};
+
+/*
+ * Dissector for FEC sub-TLVs
+ */
+static void
+dissect_mpls_echo_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *tlv_fec_tree = NULL;
+ guint16 index = 1, type;
+ int length;
+
+ if (tree){
+ while (rem >= 4){ /* Type, Length */
+ type = tvb_get_ntohs(tvb, offset);
+ length = tvb_get_ntohs(tvb, offset + 2);
+ ti = proto_tree_add_text(tree, tvb, offset, length + 4, "FEC Element %u: %s",
+ index, val_to_str(type, mpls_echo_tlv_fec_names,
+ "Unknown FEC type (0x%04X)"));
+ tlv_fec_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv_fec);
+ if(tlv_fec_tree == NULL) return;
+
+ /* FEC sub-TLV Type and Length */
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_type, tvb, offset,
+ 2, FALSE);
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_len, tvb, offset + 2,
+ 2, FALSE);
+
+ /* FEC sub-TLV Value */
+ switch (type) {
+ case TLV_FEC_STACK_LDP_IPv4:
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_ldp_ipv4,
+ tvb, offset + 4, 4, FALSE);
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_ldp_ipv4_mask,
+ tvb, offset + 8, 1, FALSE);
+ if (length == 9)
+ proto_tree_add_text(tlv_fec_tree, tvb, offset + 6, 3, "Padding");
+ break;
+ case TLV_FEC_STACK_L2_CID:
+ if (length != 16){
+ if(tree)
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing sub-TLV: length is %d, should be 16", length);
+ return;
+ }
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_sender,
+ tvb, offset + 4, 4, FALSE);
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_remote,
+ tvb, offset + 8, 4, FALSE);
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_vcid,
+ tvb, offset + 12, 4, FALSE);
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_encap,
+ tvb, offset + 16, 2, FALSE);
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_l2cid_mbz,
+ tvb, offset + 18, 2, FALSE);
+ break;
+ case TLV_FEC_STACK_LDP_IPv6:
+ case TLV_FEC_STACK_RSVP_IPv4:
+ case TLV_FEC_STACK_RSVP_IPv6:
+ case TLV_FEC_STACK_RES:
+ case TLV_FEC_STACK_VPN_IPv4:
+ case TLV_FEC_STACK_VPN_IPv6:
+ case TLV_FEC_STACK_L2_VPN:
+ default:
+ proto_tree_add_item(tlv_fec_tree, hf_mpls_echo_tlv_fec_value, tvb, offset + 4,
+ length, FALSE);
+ break;
+ }
+ rem -= 4 + length;
+ offset += 4 + length;
+ index++;
+ }
+ }
+}
+
+/*
+ * Dissector for MPLS Echo TLVs and return bytes consumed
+ */
+static int
+dissect_mpls_echo_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ guint16 type;
+ int length;
+ proto_tree *ti = NULL, *mpls_echo_tlv_tree = NULL;
+
+ length = tvb_reported_length_remaining(tvb, offset);
+ rem = MIN(rem, length);
+
+ if( rem < 4 ) { /* Type Length */
+ if(tree)
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing TLV: length is %d, should be >= 4",
+ rem);
+ return rem;
+ }
+ type = tvb_get_ntohs(tvb, offset);
+ length = tvb_get_ntohs(tvb, offset + 2),
+ rem -= 4; /* do not count Type Length */
+ length = MIN(length, rem);
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
+ val_to_str(type, mpls_echo_tlv_type_names, "Unknown TLV type (0x%04X)"));
+ mpls_echo_tlv_tree = proto_item_add_subtree(ti, ett_mpls_echo_tlv);
+ if(mpls_echo_tlv_tree == NULL) return length+4;
+
+ /* MPLS Echo TLV Type and Length */
+ proto_tree_add_uint_format(mpls_echo_tlv_tree, hf_mpls_echo_tlv_type, tvb,
+ offset, 2, type, "Type: %s (%u)",
+ val_to_str(type, mpls_echo_tlv_type_names, "Unknown TLV type"), type );
+ proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_len, tvb, offset + 2, 2, FALSE);
+
+ /* MPLS Echo TLV Value */
+ switch (type) {
+ case TLV_TARGET_FEC_STACK:
+ dissect_mpls_echo_tlv_fec(tvb, offset + 4, mpls_echo_tlv_tree, length);
+ break;
+ case TLV_PAD:
+ proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_padaction, tvb,
+ offset + 4, 1, FALSE);
+ proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_padding, tvb,
+ offset + 5, length - 1, FALSE);
+ break;
+ case TLV_DOWNSTREAM_MAPPING:
+ case TLV_ERROR_CODE:
+ case TLV_VENDOR_CODE:
+ default:
+ proto_tree_add_item(mpls_echo_tlv_tree, hf_mpls_echo_tlv_value, tvb,
+ offset + 4, length, FALSE);
+ break;
+ }
+ }
+ return length + 4; /* Length of the Value field + Type Length */
+}
+
+/*
+ * Dissector for MPLS Echo (LSP PING) packets
+ */
+static void
+dissect_mpls_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0, rem = 0, len;
+ proto_item *ti = NULL;
+ proto_tree *mpls_echo_tree = NULL;
+ guint8 msgtype;
+ const guint8 *ts_sent, *ts_rec;
+ gchar buff[NTP_TS_SIZE];
+
+ /* If version != 1 we assume it's not an mpls ping packet */
+ if (!tvb_bytes_exist(tvb, 0, 2)) {
+ return; /* Not enough information to tell. */
+ }
+ if (tvb_get_ntohs(tvb, 0) != 1) {
+ return; /* Not version 1. */
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPLS ECHO");
+
+ rem = tvb_reported_length_remaining(tvb, offset);
+
+ if( rem < 32 ) { /* The fixed part of the packet is 32 Bytes */
+ if( check_col(pinfo->cinfo, COL_INFO) )
+ col_set_str(pinfo->cinfo, COL_INFO, "Malformed Message");
+ if(tree)
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Message: length is %d, should be >= 32",
+ rem);
+ return;
+ }
+
+ /* Get the message type and fill in the Column info */
+ msgtype = tvb_get_guint8(tvb, offset + 4);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str(msgtype, mpls_echo_msgtype, "Unknown Message Type (0x%02X)"));
+
+
+ if (tree) {
+
+ /* Add subtree and dissect the fixed part of the message */
+ ti = proto_tree_add_item(tree, proto_mpls_echo, tvb, 0, -1, FALSE);
+ mpls_echo_tree = proto_item_add_subtree(ti, ett_mpls_echo);
+
+ proto_tree_add_item(mpls_echo_tree,
+ hf_mpls_echo_version, tvb, offset, 2, FALSE);
+ proto_tree_add_item(mpls_echo_tree,
+ hf_mpls_echo_mbz, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(mpls_echo_tree,
+ hf_mpls_echo_msgtype, tvb, offset + 4, 1, FALSE);
+ proto_tree_add_item(mpls_echo_tree,
+ hf_mpls_echo_replymode, tvb, offset + 5, 1, FALSE);
+ proto_tree_add_item(mpls_echo_tree,
+ hf_mpls_echo_returncode, tvb, offset + 6, 1, FALSE);
+ proto_tree_add_item(mpls_echo_tree,
+ hf_mpls_echo_returnsubcode, tvb, offset + 7, 1, FALSE);
+ proto_tree_add_item(mpls_echo_tree,
+ hf_mpls_echo_handle, tvb, offset + 8, 4, FALSE);
+ proto_tree_add_item(mpls_echo_tree,
+ hf_mpls_echo_sequence, tvb, offset + 12, 4, FALSE);
+
+ /* Using NTP routine to calculate the timestamp */
+ ts_sent = tvb_get_ptr(tvb, 16, 8);
+ proto_tree_add_bytes_format(mpls_echo_tree, hf_mpls_echo_ts_sent, tvb,
+ offset + 16, 8, ts_sent, "Timestamp Sent: %s", ntp_fmt_ts(ts_sent, buff));
+ ts_rec = tvb_get_ptr(tvb, 24, 8);
+ proto_tree_add_bytes_format(mpls_echo_tree, hf_mpls_echo_ts_rec, tvb,
+ offset + 24, 8, ts_rec, "Timestamp Received: %s", ntp_fmt_ts(ts_rec, buff));
+
+ }
+
+ offset += 32;
+ rem -= 32;
+
+ /* Dissect all TLVs */
+ while(tvb_reported_length_remaining(tvb, offset) > 0 ) {
+ len = dissect_mpls_echo_tlv(tvb, offset, mpls_echo_tree, rem);
+ offset += len;
+ rem -= len;
+ }
+
+}
+
+
+/* Register the protocol with Ethereal */
+
+void
+proto_register_mpls_echo(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_mpls_echo_version,
+ { "Version", "mpls_echo.version",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO Version Number", HFILL}
+ },
+ { &hf_mpls_echo_mbz,
+ { "MBZ", "mpls_echo.mbz",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO Must Be Zero", HFILL}
+ },
+ { &hf_mpls_echo_msgtype,
+ { "Message Type", "mpls_echo.msg_type",
+ FT_UINT8, BASE_DEC, VALS(mpls_echo_msgtype), 0x0, "MPLS ECHO Message Type", HFILL}
+ },
+ { &hf_mpls_echo_replymode,
+ { "Reply Mode", "mpls_echo.reply_mode",
+ FT_UINT8, BASE_DEC, VALS(mpls_echo_replymode), 0x0, "MPLS ECHO Reply Mode", HFILL}
+ },
+ { &hf_mpls_echo_returncode,
+ { "Return Code", "mpls_echo.return_code",
+ FT_UINT8, BASE_DEC, VALS(mpls_echo_returncode), 0x0, "MPLS ECHO Return Code", HFILL}
+ },
+ { &hf_mpls_echo_returnsubcode,
+ { "Return Subcode", "mpls_echo.return_subcode",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO Return Subcode", HFILL}
+ },
+ { &hf_mpls_echo_handle,
+ { "Sender's Handle", "mpls_echo.sender_handle",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "MPLS ECHO Sender's Handle", HFILL}
+ },
+ { &hf_mpls_echo_sequence,
+ { "Sequence Number", "mpls_echo.sequence",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "MPLS ECHO Sequence Number", HFILL}
+ },
+ { &hf_mpls_echo_ts_sent,
+ { "Timestamp Sent", "mpls_echo.timestamp_sent",
+ FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO Timestamp Sent", HFILL}
+ },
+ { &hf_mpls_echo_ts_rec,
+ { "Timestamp Received", "mpls_echo.timestamp_rec",
+ FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO Timestamp Received", HFILL}
+ },
+ { &hf_mpls_echo_tlv_type,
+ { "Type", "mpls_echo.tlv.type",
+ FT_UINT16, BASE_DEC, VALS(mpls_echo_tlv_type_names), 0x0,
+ "MPLS ECHO TLV Type", HFILL}
+ },
+ { &hf_mpls_echo_tlv_len,
+ { "Length", "mpls_echo.tlv.len",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV Length", HFILL}
+ },
+ { &hf_mpls_echo_tlv_value,
+ { "Value", "mpls_echo.tlv.value",
+ FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV Value", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_type,
+ { "Type", "mpls_echo.tlv.fec.type",
+ FT_UINT16, BASE_DEC, VALS(mpls_echo_tlv_fec_names), 0x0,
+ "MPLS ECHO TLV FEC Stack Type", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_len,
+ { "Length", "mpls_echo.tlv.fec.len",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack Length", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_value,
+ { "Value", "mpls_echo.tlv.fec.value",
+ FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack Value", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_ldp_ipv4,
+ { "IPv4 Prefix", "mpls_echo.tlv.fec.ldp_ipv4",
+ FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack IPv4", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_ldp_ipv4_mask,
+ { "Prefix Length", "mpls_echo.tlv.fec.ldp_ipv4_mask",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack IPv4 Prefix Length", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_l2cid_sender,
+ { "Sender's PE Address", "mpls_echo.tlv.fec.l2cid_sender",
+ FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack L2CID Sender", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_l2cid_remote,
+ { "Remote PE Address", "mpls_echo.tlv.fec.l2cid_remote",
+ FT_IPv4, BASE_NONE, NULL, 0x0, "MPLS ECHO TLV FEC Stack L2CID Remote", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_l2cid_vcid,
+ { "VC ID", "mpls_echo.tlv.fec.l2cid_vcid",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "MPLS ECHO TLV FEC Stack L2CID VCID", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_l2cid_encap,
+ { "Encapsulation", "mpls_echo.tlv.fec.l2cid_encap",
+ FT_UINT16, BASE_DEC, VALS(fec_vc_types_vals), 0x0, "MPLS ECHO TLV FEC Stack L2CID Encapsulation", HFILL}
+ },
+ { &hf_mpls_echo_tlv_fec_l2cid_mbz,
+ { "MBZ", "mpls_echo.tlv.fec.l2cid_mbz",
+ FT_UINT16, BASE_HEX, NULL, 0x0, "MPLS ECHO TLV FEC Stack L2CID MBZ", HFILL}
+ },
+ { &hf_mpls_echo_tlv_padaction,
+ { "Pad Action", "mpls_echo.tlv.pad_action",
+ FT_UINT8, BASE_DEC, VALS(mpls_echo_tlv_pad), 0x0, "MPLS ECHO Pad TLV Action", HFILL}
+ },
+ { &hf_mpls_echo_tlv_padding,
+ { "Padding", "mpls_echo.tlv.pad_padding",
+ FT_BYTES, BASE_NONE, NULL, 0x0, "MPLS ECHO Pad TLV Padding", HFILL}
+ }
+ };
+
+ static gint *ett[] = {
+ &ett_mpls_echo,
+ &ett_mpls_echo_tlv,
+ &ett_mpls_echo_tlv_fec,
+ };
+
+ module_t *mpls_echo_module;
+
+ proto_mpls_echo = proto_register_protocol("Multiprotocol Label Switching Echo",
+ "MPLS Echo", "mpls-echo");
+
+ proto_register_field_array(proto_mpls_echo, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ mpls_echo_module = prefs_register_protocol(proto_mpls_echo, proto_reg_handoff_mpls_echo);
+ prefs_register_uint_preference(mpls_echo_module, "udp.port", "MPLS Echo UDP Port",
+ "Set the UDP port for messages (if other"
+ " than the default of 3503)",
+ 10, &global_mpls_echo_udp_port);
+}
+
+
+void
+proto_reg_handoff_mpls_echo(void)
+{
+ static gboolean mpls_echo_prefs_initialized = FALSE;
+ static dissector_handle_t mpls_echo_handle;
+
+ if(!mpls_echo_prefs_initialized) {
+ mpls_echo_handle = create_dissector_handle(dissect_mpls_echo,
+ proto_mpls_echo);
+ mpls_echo_prefs_initialized = TRUE;
+ } else {
+ dissector_delete("udp.port", mpls_echo_udp_port, mpls_echo_handle);
+ }
+
+ mpls_echo_udp_port = global_mpls_echo_udp_port;
+ dissector_add("udp.port", global_mpls_echo_udp_port, mpls_echo_handle);
+}
diff --git a/epan/dissectors/packet-mpls.c b/epan/dissectors/packet-mpls.c
new file mode 100644
index 0000000000..459122b621
--- /dev/null
+++ b/epan/dissectors/packet-mpls.c
@@ -0,0 +1,284 @@
+/* packet-mpls.c
+ * Routines for MPLS data packet disassembly
+ *
+ * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * NOTES
+ *
+ * This module defines routines to handle Ethernet-encapsulated MPLS IP packets.
+ * It should implement all the functionality in <draft-ietf-mpls-label-encaps-07.txt>
+ * Multicast MPLS support is not tested yet
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "ppptypes.h"
+#include "etypes.h"
+#include "prefs.h"
+#include "packet-ppp.h"
+
+static gint proto_mpls = -1;
+
+static gint ett_mpls = -1;
+static gint ett_mpls_control = -1;
+
+/* Special labels in MPLS */
+enum {
+ IP4_EXPLICIT_NULL = 0,
+ ROUTER_ALERT,
+ IP6_EXPLICIT_NULL,
+ IMPLICIT_NULL,
+
+ MAX_RESERVED = 15
+};
+
+static const value_string special_labels[] = {
+ {IP4_EXPLICIT_NULL, "IPv4 Explicit-Null"},
+ {ROUTER_ALERT, "Router Alert"},
+ {IP6_EXPLICIT_NULL, "IPv6 Explicit-Null"},
+ {IMPLICIT_NULL, "Implicit-Null"},
+ {0, NULL }
+};
+
+/* MPLS filter values */
+enum mpls_filter_keys {
+
+ /* Is the packet MPLS-encapsulated? */
+/* MPLSF_PACKET,*/
+
+ /* MPLS encap properties */
+ MPLSF_LABEL,
+ MPLSF_EXP,
+ MPLSF_BOTTOM_OF_STACK,
+ MPLSF_TTL,
+
+ MPLSF_MAX
+};
+
+static int mpls_filter[MPLSF_MAX];
+static int hf_mpls_control_control = -1;
+static int hf_mpls_control_res = -1;
+
+static hf_register_info mplsf_info[] = {
+
+/* {&mpls_filter[MPLSF_PACKET],
+ {"MPLS Label Switched Packet", "mpls", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},*/
+
+ {&mpls_filter[MPLSF_LABEL],
+ {"MPLS Label", "mpls.label", FT_UINT32, BASE_DEC, VALS(special_labels), 0x0,
+ "", HFILL }},
+
+ {&mpls_filter[MPLSF_EXP],
+ {"MPLS Experimental Bits", "mpls.exp", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&mpls_filter[MPLSF_BOTTOM_OF_STACK],
+ {"MPLS Bottom Of Label Stack", "mpls.bottom", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&mpls_filter[MPLSF_TTL],
+ {"MPLS TTL", "mpls.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&hf_mpls_control_control,
+ {"MPLS Control Channel", "mpls.cw.control", FT_UINT8, BASE_DEC, NULL, 0xF0,
+ "First nibble", HFILL }},
+
+ {&hf_mpls_control_res,
+ {"Reserved", "mpls.cw.res", FT_UINT16, BASE_HEX, NULL, 0xFFF,
+ "Reserved", HFILL }},
+};
+
+static dissector_handle_t ipv4_handle;
+static dissector_handle_t ipv6_handle;
+static dissector_handle_t eth_handle;
+static dissector_handle_t data_handle;
+static dissector_table_t ppp_subdissector_table;
+
+/*
+ * Given a 4-byte MPLS label starting at offset "offset", in tvbuff "tvb",
+ * decode it.
+ * Return the label in "label", EXP bits in "exp",
+ * bottom_of_stack in "bos", and TTL in "ttl"
+ */
+void decode_mpls_label(tvbuff_t *tvb, int offset,
+ guint32 *label, guint8 *exp,
+ guint8 *bos, guint8 *ttl)
+{
+ guint8 octet0 = tvb_get_guint8(tvb, offset+0);
+ guint8 octet1 = tvb_get_guint8(tvb, offset+1);
+ guint8 octet2 = tvb_get_guint8(tvb, offset+2);
+
+ *label = (octet0 << 12) + (octet1 << 4) + ((octet2 >> 4) & 0xff);
+ *exp = (octet2 >> 1) & 0x7;
+ *bos = (octet2 & 0x1);
+ *ttl = tvb_get_guint8(tvb, offset+3);
+}
+
+static void
+dissect_mpls_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *mpls_control_tree = NULL;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+ guint8 ctrl;
+ guint16 res, ppp_proto;
+
+ if (tvb_reported_length_remaining(tvb, 0) < 4){
+ if(tree)
+ proto_tree_add_text(tree, tvb, 0, -1, "Error processing Message");
+ return;
+ }
+ ctrl = (tvb_get_guint8(tvb, 0) & 0xF0) >> 4;
+ res = tvb_get_ntohs(tvb, 0) & 0x0FFF;
+ ppp_proto = tvb_get_ntohs(tvb, 2);
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, 0, 4, "MPLS PW Control Channel Header");
+ mpls_control_tree = proto_item_add_subtree(ti, ett_mpls_control);
+ if(mpls_control_tree == NULL) return;
+
+ proto_tree_add_uint_format(mpls_control_tree, hf_mpls_control_control, tvb, 0, 1,
+ ctrl, "Control Channel: 0x%1x", ctrl);
+ proto_tree_add_uint_format(mpls_control_tree, hf_mpls_control_res, tvb, 0, 2,
+ res, "Reserved: 0x%03x", res);
+ proto_tree_add_text(mpls_control_tree, tvb, 2, 2,
+ "PPP DLL Protocol Number: %s (0x%04X)",
+ val_to_str(ppp_proto, ppp_vals, "Unknown"), ppp_proto);
+ }
+ next_tvb = tvb_new_subset(tvb, 4, -1, -1);
+ if (!dissector_try_port(ppp_subdissector_table, ppp_proto,
+ next_tvb, pinfo, tree)) {
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+
+
+}
+
+static void
+dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint32 label;
+ guint8 exp;
+ guint8 bos;
+ guint8 ttl;
+ guint8 ipvers;
+
+ proto_tree *mpls_tree;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "MPLS");
+ }
+
+ if (check_col(pinfo->cinfo,COL_INFO)) {
+ col_add_fstr(pinfo->cinfo,COL_INFO,"MPLS Label Switched Packet");
+ }
+
+ /* Start Decoding Here. */
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ decode_mpls_label(tvb, offset, &label, &exp, &bos, &ttl);
+
+ if (tree) {
+
+ ti = proto_tree_add_item(tree, proto_mpls, tvb, offset, 4, FALSE);
+ mpls_tree = proto_item_add_subtree(ti, ett_mpls);
+
+ if (label <= MAX_RESERVED)
+ proto_tree_add_uint_format(mpls_tree, mpls_filter[MPLSF_LABEL], tvb,
+ offset, 3, label, "Label: %u (%s)",
+ label, val_to_str(label, special_labels,
+ "Reserved - Unknown"));
+ else
+ proto_tree_add_uint(mpls_tree, mpls_filter[MPLSF_LABEL], tvb,
+ offset, 3, label);
+
+ proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_EXP], tvb,
+ offset+2,1, exp);
+ proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_BOTTOM_OF_STACK], tvb,
+ offset+2,1, bos);
+ proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_TTL], tvb,
+ offset+3,1, ttl);
+ }
+ offset += 4;
+ if (bos) break;
+ }
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ ipvers = (tvb_get_guint8(tvb, offset) >> 4) & 0x0F;
+ if (ipvers == 6) {
+ call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+ } else if (ipvers == 4) {
+ call_dissector(ipv4_handle, next_tvb, pinfo, tree);
+ } else if (ipvers == 1) {
+ dissect_mpls_control(next_tvb, pinfo, tree);
+ } else {
+ call_dissector(eth_handle, next_tvb, pinfo, tree);
+ }
+}
+
+void
+proto_register_mpls(void)
+{
+ static gint *ett[] = {
+ &ett_mpls,
+ &ett_mpls_control,
+ };
+
+ proto_mpls = proto_register_protocol("MultiProtocol Label Switching Header",
+ "MPLS", "mpls");
+ proto_register_field_array(proto_mpls, mplsf_info, array_length(mplsf_info));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mpls(void)
+{
+ dissector_handle_t mpls_handle;
+
+ /*
+ * Get a handle for the IPv4 and IPv6 dissectors and PPP protocol dissector table.
+ */
+ ipv4_handle = find_dissector("ip");
+ ipv6_handle = find_dissector("ipv6");
+ eth_handle = find_dissector("eth");
+ data_handle = find_dissector("data");
+ ppp_subdissector_table = find_dissector_table("ppp.protocol");
+
+
+ mpls_handle = create_dissector_handle(dissect_mpls, proto_mpls);
+ dissector_add("ethertype", ETHERTYPE_MPLS, mpls_handle);
+ dissector_add("ppp.protocol", PPP_MPLS_UNI, mpls_handle);
+ dissector_add("chdlctype", ETHERTYPE_MPLS, mpls_handle);
+ dissector_add("chdlctype", ETHERTYPE_MPLS_MULTI, mpls_handle);
+ dissector_add("gre.proto", ETHERTYPE_MPLS, mpls_handle);
+}
diff --git a/epan/dissectors/packet-mq-pcf.c b/epan/dissectors/packet-mq-pcf.c
new file mode 100644
index 0000000000..df586039bd
--- /dev/null
+++ b/epan/dissectors/packet-mq-pcf.c
@@ -0,0 +1,318 @@
+/* packet-mq-pcf.c
+ * Routines for IBM WebSphere MQ PCF packet dissection
+ *
+ * metatech <metatech@flashmail.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* MQ PCF in a nutshell
+*
+* The MQ Programmable Command Formats API allows remotely configuring a queue manager.
+*
+* MQ PCF documentation is called "WebSphere MQ Programmable Command Formats and Administration Interface"
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "packet-mq.h"
+
+static int proto_mqpcf = -1;
+static int hf_mqpcf_cfh_type = -1;
+static int hf_mqpcf_cfh_length = -1;
+static int hf_mqpcf_cfh_version = -1;
+static int hf_mqpcf_cfh_command = -1;
+static int hf_mqpcf_cfh_msgseqnumber = -1;
+static int hf_mqpcf_cfh_control = -1;
+static int hf_mqpcf_cfh_compcode = -1;
+static int hf_mqpcf_cfh_reason = -1;
+static int hf_mqpcf_cfh_paramcount = -1;
+
+static gint ett_mqpcf = -1;
+static gint ett_mqpcf_cfh = -1;
+
+#define MQ_FMT_ADMIN "MQADMIN "
+#define MQ_FMT_EVENT "MQEVENT "
+#define MQ_FMT_PCF "MQPCF "
+
+#define MQ_ENC_INTEGER_NORMAL 0x00000001
+#define MQ_ENC_INTEGER_REVERSED 0x00000002
+
+#define MQ_CMD_NONE 0
+#define MQ_CMD_CHANGE_Q_MGR 1
+#define MQ_CMD_INQUIRE_Q_MGR 2
+#define MQ_CMD_CHANGE_PROCESS 3
+#define MQ_CMD_COPY_PROCESS 4
+#define MQ_CMD_CREATE_PROCESS 5
+#define MQ_CMD_DELETE_PROCESS 6
+#define MQ_CMD_INQUIRE_PROCESS 7
+#define MQ_CMD_CHANGE_Q 8
+#define MQ_CMD_CLEAR_Q 9
+#define MQ_CMD_COPY_Q 10
+#define MQ_CMD_CREATE_Q 11
+#define MQ_CMD_DELETE_Q 12
+#define MQ_CMD_INQUIRE_Q 13
+#define MQ_CMD_RESET_Q_STATS 17
+#define MQ_CMD_INQUIRE_Q_NAMES 18
+#define MQ_CMD_INQUIRE_PROCESS_NAMES 19
+#define MQ_CMD_INQUIRE_CHANNEL_NAMES 20
+#define MQ_CMD_CHANGE_CHANNEL 21
+#define MQ_CMD_COPY_CHANNEL 22
+#define MQ_CMD_CREATE_CHANNEL 23
+#define MQ_CMD_DELETE_CHANNEL 24
+#define MQ_CMD_INQUIRE_CHANNEL 25
+#define MQ_CMD_PING_CHANNEL 26
+#define MQ_CMD_RESET_CHANNEL 27
+#define MQ_CMD_START_CHANNEL 28
+#define MQ_CMD_STOP_CHANNEL 29
+#define MQ_CMD_START_CHANNEL_INIT 30
+#define MQ_CMD_START_CHANNEL_LISTENER 31
+#define MQ_CMD_CHANGE_NAMELIST 32
+#define MQ_CMD_COPY_NAMELIST 33
+#define MQ_CMD_CREATE_NAMELIST 34
+#define MQ_CMD_DELETE_NAMELIST 35
+#define MQ_CMD_INQUIRE_NAMELIST 36
+#define MQ_CMD_INQUIRE_NAMELIST_NAMES 37
+#define MQ_CMD_ESCAPE 38
+#define MQ_CMD_RESOLVE_CHANNEL 39
+#define MQ_CMD_PING_Q_MGR 40
+#define MQ_CMD_INQUIRE_Q_STATUS 41
+#define MQ_CMD_INQUIRE_CHANNEL_STATUS 42
+#define MQ_CMD_CONFIG_EVENT 43
+#define MQ_CMD_Q_MGR_EVENT 44
+#define MQ_CMD_PERFM_EVENT 45
+#define MQ_CMD_CHANNEL_EVENT 46
+#define MQ_CMD_DELETE_PUBLICATION 60
+#define MQ_CMD_DEREGISTER_PUBLISHER 61
+#define MQ_CMD_DEREGISTER_SUBSCRIBER 62
+#define MQ_CMD_PUBLISH 63
+#define MQ_CMD_REGISTER_PUBLISHER 64
+#define MQ_CMD_REGISTER_SUBSCRIBER 65
+#define MQ_CMD_REQUEST_UPDATE 66
+#define MQ_CMD_BROKER_INTERNAL 67
+#define MQ_CMD_INQUIRE_CLUSTER_Q_MGR 70
+#define MQ_CMD_RESUME_Q_MGR_CLUSTER 71
+#define MQ_CMD_SUSPEND_Q_MGR_CLUSTER 72
+#define MQ_CMD_REFRESH_CLUSTER 73
+#define MQ_CMD_RESET_CLUSTER 74
+#define MQ_CMD_REFRESH_SECURITY 78
+#define MQ_CMD_CHANGE_AUTH_INFO 79
+#define MQ_CMD_COPY_AUTH_INFO 80
+#define MQ_CMD_CREATE_AUTH_INFO 81
+#define MQ_CMD_DELETE_AUTH_INFO 82
+#define MQ_CMD_INQUIRE_AUTH_INFO 83
+#define MQ_CMD_INQUIRE_AUTH_INFO_NAMES 84
+
+#define MQ_TEXT_CFH "MQ Command Format Header"
+
+static const value_string mqpcf_opcode_vals[] = {
+ { MQ_CMD_NONE, "NONE" },
+ { MQ_CMD_CHANGE_Q_MGR, "CHANGE_Q_MGR" },
+ { MQ_CMD_INQUIRE_Q_MGR, "INQUIRE_Q_MGR" },
+ { MQ_CMD_CHANGE_PROCESS, "CHANGE_PROCESS" },
+ { MQ_CMD_COPY_PROCESS, "COPY_PROCESS" },
+ { MQ_CMD_CREATE_PROCESS, "CREATE_PROCESS" },
+ { MQ_CMD_DELETE_PROCESS, "DELETE_PROCESS" },
+ { MQ_CMD_INQUIRE_PROCESS, "INQUIRE_PROCESS" },
+ { MQ_CMD_CHANGE_Q, "CHANGE_Q" },
+ { MQ_CMD_CLEAR_Q, "CLEAR_Q" },
+ { MQ_CMD_COPY_Q, "COPY_Q" },
+ { MQ_CMD_CREATE_Q, "CREATE_Q" },
+ { MQ_CMD_DELETE_Q, "DELETE_Q" },
+ { MQ_CMD_INQUIRE_Q, "INQUIRE_Q" },
+ { MQ_CMD_RESET_Q_STATS, "RESET_Q_STATS" },
+ { MQ_CMD_INQUIRE_Q_NAMES, "INQUIRE_Q_NAMES" },
+ { MQ_CMD_INQUIRE_PROCESS_NAMES, "INQUIRE_PROCESS_NAMES" },
+ { MQ_CMD_INQUIRE_CHANNEL_NAMES, "INQUIRE_CHANNEL_NAMES" },
+ { MQ_CMD_CHANGE_CHANNEL, "CHANGE_CHANNEL" },
+ { MQ_CMD_COPY_CHANNEL, "COPY_CHANNEL" },
+ { MQ_CMD_CREATE_CHANNEL, "CREATE_CHANNEL" },
+ { MQ_CMD_DELETE_CHANNEL, "DELETE_CHANNEL" },
+ { MQ_CMD_INQUIRE_CHANNEL, "INQUIRE_CHANNEL" },
+ { MQ_CMD_PING_CHANNEL, "PING_CHANNEL" },
+ { MQ_CMD_RESET_CHANNEL, "RESET_CHANNEL" },
+ { MQ_CMD_START_CHANNEL, "START_CHANNEL" },
+ { MQ_CMD_STOP_CHANNEL, "STOP_CHANNEL" },
+ { MQ_CMD_START_CHANNEL_INIT, "START_CHANNEL_INIT" },
+ { MQ_CMD_START_CHANNEL_LISTENER, "START_CHANNEL_LISTENER" },
+ { MQ_CMD_CHANGE_NAMELIST, "CHANGE_NAMELIST" },
+ { MQ_CMD_CREATE_NAMELIST, "CREATE_NAMELIST" },
+ { MQ_CMD_DELETE_NAMELIST, "DELETE_NAMELIST" },
+ { MQ_CMD_INQUIRE_NAMELIST, "INQUIRE_NAMELIST" },
+ { MQ_CMD_INQUIRE_NAMELIST_NAMES, "INQUIRE_NAMELIST_NAMES" },
+ { MQ_CMD_ESCAPE, "ESCAPE" },
+ { MQ_CMD_RESOLVE_CHANNEL, "RESOLVE_CHANNEL" },
+ { MQ_CMD_PING_Q_MGR, "PING_Q_MGR" },
+ { MQ_CMD_INQUIRE_Q_STATUS, "INQUIRE_Q_STATUS" },
+ { MQ_CMD_INQUIRE_CHANNEL_STATUS, "INQUIRE_CHANNEL_STATUS" },
+ { MQ_CMD_CONFIG_EVENT, "CONFIG_EVENT" },
+ { MQ_CMD_Q_MGR_EVENT, "Q_MGR_EVENT" },
+ { MQ_CMD_PERFM_EVENT, "PERFM_EVENT" },
+ { MQ_CMD_CHANNEL_EVENT, "CHANNEL_EVENT" },
+ { MQ_CMD_DELETE_PUBLICATION, "DELETE_PUBLICATION" },
+ { MQ_CMD_DEREGISTER_PUBLISHER, "DEREGISTER_PUBLISHER" },
+ { MQ_CMD_DEREGISTER_SUBSCRIBER, "DEREGISTER_SUBSCRIBER" },
+ { MQ_CMD_PUBLISH, "PUBLISH" },
+ { MQ_CMD_REGISTER_PUBLISHER, "REGISTER_PUBLISHER" },
+ { MQ_CMD_REGISTER_SUBSCRIBER, "REGISTER_SUBSCRIBER" },
+ { MQ_CMD_REQUEST_UPDATE, "REQUEST_UPDATE" },
+ { MQ_CMD_BROKER_INTERNAL, "BROKER_INTERNAL" },
+ { MQ_CMD_INQUIRE_CLUSTER_Q_MGR, "INQUIRE_CLUSTER_Q_MGR" },
+ { MQ_CMD_RESUME_Q_MGR_CLUSTER, "RESUME_Q_MGR_CLUSTER" },
+ { MQ_CMD_SUSPEND_Q_MGR_CLUSTER, "SUSPEND_Q_MGR_CLUSTER" },
+ { MQ_CMD_REFRESH_CLUSTER, "REFRESH_CLUSTER" },
+ { MQ_CMD_REFRESH_SECURITY, "REFRESH_SECURITY" },
+ { MQ_CMD_CHANGE_AUTH_INFO, "CHANGE_AUTH_INFO" },
+ { MQ_CMD_COPY_AUTH_INFO, "COPY_AUTH_INFO" },
+ { MQ_CMD_CREATE_AUTH_INFO, "CREATE_AUTH_INFO" },
+ { MQ_CMD_DELETE_AUTH_INFO, "DELETE_AUTH_INFO" },
+ { MQ_CMD_INQUIRE_AUTH_INFO, "INQUIRE_AUTH_INFO" },
+ { MQ_CMD_INQUIRE_AUTH_INFO_NAMES, "INQUIRE_AUTH_INFO_NAMES" },
+ { 0, NULL }
+};
+
+static guint32 tvb_get_guint32_endian(tvbuff_t *a_tvb, gint a_iOffset, gboolean a_bLittleEndian)
+{
+ guint32 iResult;
+ if (a_bLittleEndian)
+ iResult = tvb_get_letohl(a_tvb, a_iOffset);
+ else
+ iResult = tvb_get_ntohl(a_tvb, a_iOffset);
+ return iResult;
+}
+
+static void
+dissect_mqpcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *mq_tree = NULL;
+ proto_tree *mqroot_tree = NULL;
+ proto_item *ti = NULL;
+ gint offset = 0;
+ struct mqinfo* mqinfo = pinfo->private_data;
+ gboolean bLittleEndian;
+ bLittleEndian = ((mqinfo->encoding & MQ_ENC_INTEGER_REVERSED) != 0) ? TRUE : FALSE;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "MQ PCF");
+ if (check_col(pinfo->cinfo, COL_INFO)) col_clear(pinfo->cinfo, COL_INFO);
+ if (tvb_length(tvb) >= 36)
+ {
+ gint iSizeMQCFH = 36;
+ guint32 iCommand = tvb_get_guint32_endian(tvb, offset + 12, bLittleEndian);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(iCommand, mqpcf_opcode_vals, "Unknown (0x%02x)"));
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_mqpcf, tvb, offset, -1, FALSE);
+ proto_item_append_text(ti, " (%s)", val_to_str(iCommand, mqpcf_opcode_vals, "Unknown (0x%02x)"));
+ mqroot_tree = proto_item_add_subtree(ti, ett_mqpcf);
+
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeMQCFH, MQ_TEXT_CFH);
+ mq_tree = proto_item_add_subtree(ti, ett_mqpcf_cfh);
+
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_type, tvb, offset + 0, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_length, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_version, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_command, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_msgseqnumber, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_control, tvb, offset + 20, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_compcode, tvb, offset + 24, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_reason, tvb, offset + 28, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mqpcf_cfh_paramcount, tvb, offset + 32, 4, bLittleEndian);
+ }
+ offset += iSizeMQCFH;
+ }
+}
+
+static gboolean
+dissect_mqpcf_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (tvb_length(tvb) >= 36)
+ {
+ struct mqinfo* mqinfo = pinfo->private_data;
+ if (strncmp((const char*)mqinfo->format, MQ_FMT_ADMIN, 8) == 0
+ || strncmp((const char*)mqinfo->format, MQ_FMT_EVENT, 8) == 0
+ || strncmp((const char*)mqinfo->format, MQ_FMT_PCF, 8) == 0)
+ {
+ /* Dissect the packet */
+ dissect_mqpcf(tvb, pinfo, tree);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void
+proto_register_mqpcf(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_mqpcf_cfh_type,
+ { "Type", "mqpcf.cfh.type", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH type", HFILL }},
+
+ { &hf_mqpcf_cfh_length,
+ { "Length", "mqpcf.cfh.length", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH length", HFILL }},
+
+ { &hf_mqpcf_cfh_version,
+ { "Version", "mqpcf.cfh.version", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH version", HFILL }},
+
+ { &hf_mqpcf_cfh_command,
+ { "Command", "mqpcf.cfh.command", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH command", HFILL }},
+
+ { &hf_mqpcf_cfh_msgseqnumber,
+ { "Message sequence number", "mqpcf.cfh.msgseqnumber", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH message sequence number", HFILL }},
+
+ { &hf_mqpcf_cfh_control,
+ { "Control", "mqpcf.cfh.control", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH control", HFILL }},
+
+ { &hf_mqpcf_cfh_compcode,
+ { "Completion code", "mqpcf.cfh.compcode", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH completion code", HFILL }},
+
+ { &hf_mqpcf_cfh_reason,
+ { "Reason code", "mqpcf.cfh.reasoncode", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH reason code", HFILL }},
+
+ { &hf_mqpcf_cfh_paramcount,
+ { "Parameter count", "mqpcf.cfh.paramcount", FT_UINT32, BASE_DEC, NULL, 0x0, "CFH parameter count", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_mqpcf,
+ &ett_mqpcf_cfh,
+ };
+
+ proto_mqpcf = proto_register_protocol("WebSphere MQ Programmable Command Formats", "MQ PCF", "mqpcf");
+ proto_register_field_array(proto_mqpcf, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mqpcf(void)
+{
+ heur_dissector_add("mq", dissect_mqpcf_heur, proto_mqpcf);
+}
diff --git a/epan/dissectors/packet-mq.c b/epan/dissectors/packet-mq.c
new file mode 100644
index 0000000000..666415f7ae
--- /dev/null
+++ b/epan/dissectors/packet-mq.c
@@ -0,0 +1,3285 @@
+/* packet-mq.c
+ * Routines for IBM WebSphere MQ packet dissection
+ *
+ * metatech <metatech@flashmail.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* WebSphere MQ in a nutshell
+*
+* IBM WebSphere MQ (formerly IBM MQSeries) is an asynchronous proprietary messaging middleware that is based on message queues.
+* MQ can run on more than 35 platforms, amongst which UNIX, Windows and mainframes.
+* MQ can be transported on top of TCP, UDP, HTTP, NetBIOS, SPX, SNA LU 6.2, DECnet.
+* MQ has language bindings for C, C++, Java, .NET, COBOL, PL/I, OS/390 assembler, TAL, Visual Basic.
+*
+* The basic MQ topology is on one side the queue manager which hosts the queues. On the other side the
+* applications connect to the queue manager, open a queue, and put or get messages to/from that queue.
+*
+* The MQ middleware allows very generic operations (send, receive) and can be compared to the
+* socket API in terms of genericity, but it is more abstract and offers higher-level functionalities
+* (eg transactions, ...)
+*
+* The MQ middleware is not really intended to be run over public networks between parties
+* that do not know each other in advance, but is rather used on private corporate networks
+* between business applications (it can be compared to a database server for that aspect).
+*
+* The wire format of an MQ segment is a sequence of structures. Most structures start with a 4-letter struct identifier.
+* MQ is a fixed-sized format, most fields have maximum lengths defined in the MQ API.
+* MQ is popular on mainframes because it was available before TCP/IP.
+* MQ supports both ASCII-based and EBCDIC-based character sets.
+*
+* MQ API documentation is called "WebSphere MQ Application Programming Reference"
+*
+* Possible structures combinations :
+* TSH [ ID ^ UID ^ CONN ^ INQ ^ OD ]
+* TSH MSH XQH MD [ PAYLOAD ]
+* TSH [OD] MD [ GMO ^ PMO ] [ [XQH MD] PAYLOAD ]
+* TSH [ SPQU ^ SPPU ^ SPGU ^ SPAU [ SPQI ^ SPQO ^ SPPI ^ SPPO ^ SPGI ^ SPGO ^ SPAI ^ SPAO]]
+* TSH [ XA ] [ XINFO | XID ]
+* where PAYLOAD = [ DH ] [ DLH ] [ MDE ] BUFF
+*
+* This dissector is a beta version. To be improved
+* - Translate the integers/flags into their descriptions
+* - Find the semantics of the unknown fields
+* - Display EBCDIC strings as ASCII
+* - Packets which structures built on different platforms
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "reassemble.h"
+#include "prefs.h"
+#include "packet-tcp.h"
+#include "packet-mq.h"
+
+static int proto_mq = -1;
+static int hf_mq_tsh_structid = -1;
+static int hf_mq_tsh_packetlength = -1;
+static int hf_mq_tsh_byteorder = -1;
+static int hf_mq_tsh_opcode = -1;
+static int hf_mq_tsh_controlflags = -1;
+static int hf_mq_tsh_reserved = -1;
+static int hf_mq_tsh_luwid = -1;
+static int hf_mq_tsh_encoding = -1;
+static int hf_mq_tsh_ccsid = -1;
+static int hf_mq_tsh_padding = -1;
+static int hf_mq_tsh_tcf_confirmreq = -1;
+static int hf_mq_tsh_tcf_error = -1;
+static int hf_mq_tsh_tcf_reqclose = -1;
+static int hf_mq_tsh_tcf_closechann = -1;
+static int hf_mq_tsh_tcf_first = -1;
+static int hf_mq_tsh_tcf_last = -1;
+static int hf_mq_tsh_tcf_reqacc = -1;
+static int hf_mq_tsh_tcf_dlq = -1;
+static int hf_mq_api_replylength = -1;
+static int hf_mq_api_completioncode = -1;
+static int hf_mq_api_reasoncode = -1;
+static int hf_mq_api_objecthandle = -1;
+static int hf_mq_msh_structid = -1;
+static int hf_mq_msh_seqnum = -1;
+static int hf_mq_msh_datalength = -1;
+static int hf_mq_msh_unknown1 = -1;
+static int hf_mq_msh_msglength = -1;
+static int hf_mq_xqh_structid = -1;
+static int hf_mq_xqh_version = -1;
+static int hf_mq_xqh_remoteq = -1;
+static int hf_mq_xqh_remoteqmgr = -1;
+static int hf_mq_id_structid = -1;
+static int hf_mq_id_level = -1;
+static int hf_mq_id_flags = -1;
+static int hf_mq_id_unknown2 = -1;
+static int hf_mq_id_ieflags = -1;
+static int hf_mq_id_unknown4 = -1;
+static int hf_mq_id_maxmsgperbatch = -1;
+static int hf_mq_id_maxtransmissionsize = -1;
+static int hf_mq_id_maxmsgsize = -1;
+static int hf_mq_id_sequencewrapvalue = -1;
+static int hf_mq_id_channel = -1;
+static int hf_mq_id_capflags = -1;
+static int hf_mq_id_unknown5 = -1;
+static int hf_mq_id_ccsid = -1;
+static int hf_mq_id_queuemanager = -1;
+static int hf_mq_id_heartbeatinterval = -1;
+static int hf_mq_id_unknown6 = -1;
+static int hf_mq_id_icf_msgseq = -1;
+static int hf_mq_id_icf_convcap = -1;
+static int hf_mq_id_icf_splitmsg = -1;
+static int hf_mq_id_icf_mqreq = -1;
+static int hf_mq_id_icf_svrsec = -1;
+static int hf_mq_id_icf_runtime = -1;
+static int hf_mq_id_ief_ccsid = -1;
+static int hf_mq_id_ief_enc = -1;
+static int hf_mq_id_ief_mxtrsz = -1;
+static int hf_mq_id_ief_fap = -1;
+static int hf_mq_id_ief_mxmsgsz = -1;
+static int hf_mq_id_ief_mxmsgpb = -1;
+static int hf_mq_id_ief_seqwrap = -1;
+static int hf_mq_id_ief_hbint = -1;
+static int hf_mq_uid_structid = -1;
+static int hf_mq_uid_userid = -1;
+static int hf_mq_uid_password = -1;
+static int hf_mq_uid_longuserid = -1;
+static int hf_mq_uid_securityid = -1;
+static int hf_mq_conn_queuemanager = -1;
+static int hf_mq_conn_appname = -1;
+static int hf_mq_conn_apptype = -1;
+static int hf_mq_conn_acttoken = -1;
+static int hf_mq_conn_version = -1;
+static int hf_mq_conn_options = -1;
+static int hf_mq_inq_nbsel = -1;
+static int hf_mq_inq_nbint = -1;
+static int hf_mq_inq_charlen = -1;
+static int hf_mq_inq_sel = -1;
+static int hf_mq_inq_intvalue = -1;
+static int hf_mq_inq_charvalues = -1;
+static int hf_mq_spi_verb = -1;
+static int hf_mq_spi_version = -1;
+static int hf_mq_spi_length = -1;
+static int hf_mq_spi_base_structid = -1;
+static int hf_mq_spi_base_version = -1;
+static int hf_mq_spi_base_length = -1;
+static int hf_mq_spi_spqo_nbverb = -1;
+static int hf_mq_spi_spqo_verbid = -1;
+static int hf_mq_spi_spqo_maxinoutversion = -1;
+static int hf_mq_spi_spqo_maxinversion = -1;
+static int hf_mq_spi_spqo_maxoutversion = -1;
+static int hf_mq_spi_spqo_flags = -1;
+static int hf_mq_spi_spai_mode = -1;
+static int hf_mq_spi_spai_unknown1 = -1;
+static int hf_mq_spi_spai_unknown2 = -1;
+static int hf_mq_spi_spai_msgid = -1;
+static int hf_mq_spi_spgi_batchsize = -1;
+static int hf_mq_spi_spgi_batchint = -1;
+static int hf_mq_spi_spgi_maxmsgsize = -1;
+static int hf_mq_spi_spgo_options = -1;
+static int hf_mq_spi_spgo_size = -1;
+static int hf_mq_spi_options_blank = -1;
+static int hf_mq_spi_options_syncpoint = -1;
+static int hf_mq_spi_options_deferred = -1;
+static int hf_mq_put_length = -1;
+static int hf_mq_open_options = -1;
+static int hf_mq_ping_length = -1;
+static int hf_mq_ping_buffer = -1;
+static int hf_mq_reset_length = -1;
+static int hf_mq_reset_seqnum = -1;
+static int hf_mq_status_length = -1;
+static int hf_mq_status_code = -1;
+static int hf_mq_status_value = -1;
+static int hf_mq_od_structid = -1;
+static int hf_mq_od_version = -1;
+static int hf_mq_od_objecttype = -1;
+static int hf_mq_od_objectname = -1;
+static int hf_mq_od_objectqmgrname = -1;
+static int hf_mq_od_dynamicqname = -1;
+static int hf_mq_od_alternateuserid = -1;
+static int hf_mq_od_recspresent = -1;
+static int hf_mq_od_knowndestcount = -1;
+static int hf_mq_od_unknowndestcount = -1;
+static int hf_mq_od_invaliddestcount = -1;
+static int hf_mq_od_objectrecoffset = -1;
+static int hf_mq_od_responserecoffset = -1;
+static int hf_mq_od_objectrecptr = -1;
+static int hf_mq_od_responserecptr = -1;
+static int hf_mq_od_alternatesecurityid = -1;
+static int hf_mq_od_resolvedqname = -1;
+static int hf_mq_od_resolvedqmgrname = -1;
+static int hf_mq_or_objname= -1;
+static int hf_mq_or_objqmgrname = -1;
+static int hf_mq_rr_completioncode = -1;
+static int hf_mq_rr_reasoncode = -1;
+static int hf_mq_pmr_msgid = -1;
+static int hf_mq_pmr_correlid = -1;
+static int hf_mq_pmr_groupid = -1;
+static int hf_mq_pmr_feedback = -1;
+static int hf_mq_pmr_acttoken = -1;
+static int hf_mq_md_structid = -1;
+static int hf_mq_md_version = -1;
+static int hf_mq_md_report = -1;
+static int hf_mq_md_msgtype = -1;
+static int hf_mq_md_expiry = -1;
+static int hf_mq_md_feedback = -1;
+static int hf_mq_md_encoding = -1;
+static int hf_mq_md_ccsid = -1;
+static int hf_mq_md_format = -1;
+static int hf_mq_md_priority = -1;
+static int hf_mq_md_persistence = -1;
+static int hf_mq_md_msgid = -1;
+static int hf_mq_md_correlid = -1;
+static int hf_mq_md_backountcount = -1;
+static int hf_mq_md_replytoq = -1;
+static int hf_mq_md_replytoqmgr = -1;
+static int hf_mq_md_userid = -1;
+static int hf_mq_md_acttoken = -1;
+static int hf_mq_md_appliddata = -1;
+static int hf_mq_md_putappltype = -1;
+static int hf_mq_md_putapplname = -1;
+static int hf_mq_md_putdate = -1;
+static int hf_mq_md_puttime = -1;
+static int hf_mq_md_applorigindata = -1;
+static int hf_mq_md_groupid = -1;
+static int hf_mq_md_msgseqnumber = -1;
+static int hf_mq_md_offset = -1;
+static int hf_mq_md_msgflags = -1;
+static int hf_mq_md_originallength = -1;
+static int hf_mq_md_hidden_lastformat = -1;
+static int hf_mq_dlh_structid = -1;
+static int hf_mq_dlh_version = -1;
+static int hf_mq_dlh_reason = -1;
+static int hf_mq_dlh_destq = -1;
+static int hf_mq_dlh_destqmgr = -1;
+static int hf_mq_dlh_encoding = -1;
+static int hf_mq_dlh_ccsid = -1;
+static int hf_mq_dlh_format = -1;
+static int hf_mq_dlh_putappltype = -1;
+static int hf_mq_dlh_putapplname = -1;
+static int hf_mq_dlh_putdate = -1;
+static int hf_mq_dlh_puttime = -1;
+static int hf_mq_dh_putmsgrecfields = -1;
+static int hf_mq_dh_recspresent = -1;
+static int hf_mq_dh_objectrecoffset = -1;
+static int hf_mq_dh_putmsgrecoffset = -1;
+static int hf_mq_gmo_structid = -1;
+static int hf_mq_gmo_version = -1;
+static int hf_mq_gmo_options = -1;
+static int hf_mq_gmo_waitinterval = -1;
+static int hf_mq_gmo_signal1 = -1;
+static int hf_mq_gmo_signal2 = -1;
+static int hf_mq_gmo_resolvedqname = -1;
+static int hf_mq_gmo_matchoptions = -1;
+static int hf_mq_gmo_groupstatus = -1;
+static int hf_mq_gmo_segmentstatus = -1;
+static int hf_mq_gmo_segmentation = -1;
+static int hf_mq_gmo_reserved = -1;
+static int hf_mq_gmo_msgtoken = -1;
+static int hf_mq_gmo_returnedlength = -1;
+static int hf_mq_pmo_structid = -1;
+static int hf_mq_pmo_version = -1;
+static int hf_mq_pmo_options = -1;
+static int hf_mq_pmo_timeout = -1;
+static int hf_mq_pmo_context = -1;
+static int hf_mq_pmo_knowndestcount = -1;
+static int hf_mq_pmo_unknowndestcount = -1;
+static int hf_mq_pmo_invaliddestcount = -1;
+static int hf_mq_pmo_resolvedqname = -1;
+static int hf_mq_pmo_resolvedqmgrname = -1;
+static int hf_mq_pmo_recspresent = -1;
+static int hf_mq_pmo_putmsgrecfields = -1;
+static int hf_mq_pmo_putmsgrecoffset = -1;
+static int hf_mq_pmo_responserecoffset = -1;
+static int hf_mq_pmo_putmsgrecptr = -1;
+static int hf_mq_pmo_responserecptr = -1;
+static int hf_mq_head_structid = -1;
+static int hf_mq_head_version = -1;
+static int hf_mq_head_length = -1;
+static int hf_mq_head_encoding = -1;
+static int hf_mq_head_ccsid = -1;
+static int hf_mq_head_format = -1;
+static int hf_mq_head_flags = -1;
+static int hf_mq_head_struct = -1;
+static int hf_mq_xa_length = -1;
+static int hf_mq_xa_returnvalue = -1;
+static int hf_mq_xa_tmflags = -1;
+static int hf_mq_xa_rmid = -1;
+static int hf_mq_xa_count = -1;
+static int hf_mq_xa_tmflags_join = -1;
+static int hf_mq_xa_tmflags_endrscan = -1;
+static int hf_mq_xa_tmflags_startrscan = -1;
+static int hf_mq_xa_tmflags_suspend = -1;
+static int hf_mq_xa_tmflags_success = -1;
+static int hf_mq_xa_tmflags_resume = -1;
+static int hf_mq_xa_tmflags_fail = -1;
+static int hf_mq_xa_tmflags_onephase = -1;
+static int hf_mq_xa_xid_formatid = -1;
+static int hf_mq_xa_xid_globalxid_length = -1;
+static int hf_mq_xa_xid_brq_length = -1;
+static int hf_mq_xa_xid_globalxid = -1;
+static int hf_mq_xa_xid_brq = -1;
+static int hf_mq_xa_xainfo_length = -1;
+static int hf_mq_xa_xainfo_value = -1;
+
+static gint ett_mq = -1;
+static gint ett_mq_tsh = -1;
+static gint ett_mq_tsh_tcf = -1;
+static gint ett_mq_api = -1;
+static gint ett_mq_msh = -1;
+static gint ett_mq_xqh = -1;
+static gint ett_mq_id = -1;
+static gint ett_mq_id_icf = -1;
+static gint ett_mq_id_ief = -1;
+static gint ett_mq_uid = -1;
+static gint ett_mq_conn = -1;
+static gint ett_mq_inq = -1;
+static gint ett_mq_spi = -1;
+static gint ett_mq_spi_base = -1; /* Factorisation of common SPI items */
+static gint ett_mq_spi_options = -1;
+static gint ett_mq_put = -1;
+static gint ett_mq_open = -1;
+static gint ett_mq_ping = -1;
+static gint ett_mq_reset = -1;
+static gint ett_mq_status = -1;
+static gint ett_mq_od = -1;
+static gint ett_mq_or = -1;
+static gint ett_mq_rr = -1;
+static gint ett_mq_pmr = -1;
+static gint ett_mq_md = -1;
+static gint ett_mq_mde = -1;
+static gint ett_mq_dlh = -1;
+static gint ett_mq_dh = -1;
+static gint ett_mq_gmo = -1;
+static gint ett_mq_pmo = -1;
+static gint ett_mq_head = -1; /* Factorisation of common Header structure items (DH, MDE, CIH, IIH, RFH, RMH, WIH */
+static gint ett_mq_xa = -1;
+static gint ett_mq_xa_tmflags = -1;
+static gint ett_mq_xa_xid = -1;
+static gint ett_mq_xa_info = -1;
+
+static dissector_handle_t mq_tcp_handle;
+static dissector_handle_t mq_spx_handle;
+static dissector_handle_t data_handle;
+
+static heur_dissector_list_t mq_heur_subdissector_list;
+
+static gboolean mq_desegment = TRUE;
+static gboolean mq_reassembly = FALSE;
+
+static GHashTable *mq_fragment_table = NULL;
+static GHashTable *mq_reassembled_table = NULL;
+
+
+#define MQ_PORT_TCP 1414
+#define MQ_SOCKET_SPX 0x5E86
+
+#define MQ_XPT_TCP 0x02
+#define MQ_XPT_NETBIOS 0x03
+#define MQ_XPT_SPX 0x04
+#define MQ_XPT_HTTP 0x07
+
+#define MQ_STRUCTID_NULL 0x00000000
+#define MQ_STRUCTID_CIH 0x43494820
+#define MQ_STRUCTID_DH 0x44482020
+#define MQ_STRUCTID_DLH 0x444C4820
+#define MQ_STRUCTID_GMO 0x474D4F20
+#define MQ_STRUCTID_ID 0x49442020
+#define MQ_STRUCTID_IIH 0x49494820
+#define MQ_STRUCTID_MD 0x4D442020
+#define MQ_STRUCTID_MDE 0x4D444520
+#define MQ_STRUCTID_MSH 0x4D534820
+#define MQ_STRUCTID_OD 0x4F442020
+#define MQ_STRUCTID_PMO 0x504D4F20
+#define MQ_STRUCTID_RFH 0x52464820
+#define MQ_STRUCTID_RMH 0x524D4820
+#define MQ_STRUCTID_TM 0x544D2020
+#define MQ_STRUCTID_TMC2 0x544D4332
+#define MQ_STRUCTID_TSH 0x54534820
+#define MQ_STRUCTID_UID 0x55494420
+#define MQ_STRUCTID_WIH 0x57494820
+#define MQ_STRUCTID_XQH 0x58514820
+#define MQ_STRUCTID_CIH_EBCDIC 0xC3C9C840
+#define MQ_STRUCTID_DH_EBCDIC 0xC4C84040
+#define MQ_STRUCTID_DLH_EBCDIC 0xC4D3C840
+#define MQ_STRUCTID_GMO_EBCDIC 0xC7D4D640
+#define MQ_STRUCTID_ID_EBCDIC 0xC9C44040
+#define MQ_STRUCTID_IIH_EBCDIC 0xC9C9C840
+#define MQ_STRUCTID_MD_EBCDIC 0xD4C44040
+#define MQ_STRUCTID_MDE_EBCDIC 0xD4C4C540
+#define MQ_STRUCTID_MSH_EBCDIC 0xD4E2C840
+#define MQ_STRUCTID_OD_EBCDIC 0xD6C44040
+#define MQ_STRUCTID_PMO_EBCDIC 0xD7D4D640
+#define MQ_STRUCTID_RFH_EBCDIC 0xD9C6C840
+#define MQ_STRUCTID_RMH_EBCDIC 0xD9D4C840
+#define MQ_STRUCTID_TM_EBCDIC 0xE3D44040
+#define MQ_STRUCTID_TMC2_EBCDIC 0xE3D4C3F2
+#define MQ_STRUCTID_TSH_EBCDIC 0xE3E2C840
+#define MQ_STRUCTID_UID_EBCDIC 0xE4C9C440
+#define MQ_STRUCTID_WIH_EBCDIC 0xE6C9C840
+#define MQ_STRUCTID_XQH_EBCDIC 0xE7D8C840
+
+#define MQ_STRUCTID_SPQU 0x53505155 /* SPI Query InOut */
+#define MQ_STRUCTID_SPQI 0x53505149 /* SPI Query In */
+#define MQ_STRUCTID_SPQO 0x5350514F /* SPI Query Out */
+#define MQ_STRUCTID_SPPU 0x53505055 /* SPI Put InOut */
+#define MQ_STRUCTID_SPPI 0x53505049 /* SPI Put In */
+#define MQ_STRUCTID_SPPO 0x5350504F /* SPI Put Out */
+#define MQ_STRUCTID_SPGU 0x53504755 /* SPI Get InOut */
+#define MQ_STRUCTID_SPGI 0x53504749 /* SPI Get In */
+#define MQ_STRUCTID_SPGO 0x5350474F /* SPI Get Out */
+#define MQ_STRUCTID_SPAU 0x53504155 /* SPI Activate InOut */
+#define MQ_STRUCTID_SPAI 0x53504149 /* SPI Activate In */
+#define MQ_STRUCTID_SPAO 0x5350414F /* SPI Activate Out */
+#define MQ_STRUCTID_SPQU_EBCDIC 0xE2D7D8E4 /* SPI Query InOut */
+#define MQ_STRUCTID_SPQI_EBCDIC 0xE2D7D8C9 /* SPI Query In */
+#define MQ_STRUCTID_SPQO_EBCDIC 0xE2D7D8D6 /* SPI Query Out */
+#define MQ_STRUCTID_SPPU_EBCDIC 0xE2D7D7E4 /* SPI Put InOut */
+#define MQ_STRUCTID_SPPI_EBCDIC 0xE2D7D7C9 /* SPI Put In */
+#define MQ_STRUCTID_SPPO_EBCDIC 0xE2D7D7D6 /* SPI Put Out */
+#define MQ_STRUCTID_SPGU_EBCDIC 0xE2D7C7E4 /* SPI Get InOut */
+#define MQ_STRUCTID_SPGI_EBCDIC 0xE2D7C7C9 /* SPI Get In */
+#define MQ_STRUCTID_SPGO_EBCDIC 0xE2D7C7D6 /* SPI Get Out */
+#define MQ_STRUCTID_SPAU_EBCDIC 0xE2D7C1E4 /* SPI Activate InOut */
+#define MQ_STRUCTID_SPAI_EBCDIC 0xE2D7C1C9 /* SPI Activate In */
+#define MQ_STRUCTID_SPAO_EBCDIC 0xE2D7C1D6 /* SPI Activate Out */
+
+#define MQ_TST_INITIAL 0x01
+#define MQ_TST_RESYNC 0x02
+#define MQ_TST_RESET 0x03
+#define MQ_TST_MESSAGE 0x04
+#define MQ_TST_STATUS 0x05
+#define MQ_TST_SECURITY 0x06
+#define MQ_TST_PING 0x07
+#define MQ_TST_USERID 0x08
+#define MQ_TST_HEARTBEAT 0x09
+#define MQ_TST_MQCONN 0x81
+#define MQ_TST_MQDISC 0x82
+#define MQ_TST_MQOPEN 0x83
+#define MQ_TST_MQCLOSE 0x84
+#define MQ_TST_MQGET 0x85
+#define MQ_TST_MQPUT 0x86
+#define MQ_TST_MQPUT1 0x87
+#define MQ_TST_MQSET 0x88
+#define MQ_TST_MQINQ 0x89
+#define MQ_TST_MQCMIT 0x8A
+#define MQ_TST_MQBACK 0x8B
+#define MQ_TST_SPI 0x8C
+#define MQ_TST_MQCONN_REPLY 0x91
+#define MQ_TST_MQDISC_REPLY 0x92
+#define MQ_TST_MQOPEN_REPLY 0x93
+#define MQ_TST_MQCLOSE_REPLY 0x94
+#define MQ_TST_MQGET_REPLY 0x95
+#define MQ_TST_MQPUT_REPLY 0x96
+#define MQ_TST_MQPUT1_REPLY 0x97
+#define MQ_TST_MQSET_REPLY 0x98
+#define MQ_TST_MQINQ_REPLY 0x99
+#define MQ_TST_MQCMIT_REPLY 0x9A
+#define MQ_TST_MQBACK_REPLY 0x9B
+#define MQ_TST_SPI_REPLY 0x9C
+#define MQ_TST_XA_START 0xA1
+#define MQ_TST_XA_END 0xA2
+#define MQ_TST_XA_OPEN 0xA3
+#define MQ_TST_XA_CLOSE 0xA4
+#define MQ_TST_XA_PREPARE 0xA5
+#define MQ_TST_XA_COMMIT 0xA6
+#define MQ_TST_XA_ROLLBACK 0xA7
+#define MQ_TST_XA_FORGET 0xA8
+#define MQ_TST_XA_RECOVER 0xA9
+#define MQ_TST_XA_COMPLETE 0xAA
+#define MQ_TST_XA_START_REPLY 0xB1
+#define MQ_TST_XA_END_REPLY 0xB2
+#define MQ_TST_XA_OPEN_REPLY 0xB3
+#define MQ_TST_XA_CLOSE_REPLY 0xB4
+#define MQ_TST_XA_PREPARE_REPLY 0xB5
+#define MQ_TST_XA_COMMIT_REPLY 0xB6
+#define MQ_TST_XA_ROLLBACK_REPLY 0xB7
+#define MQ_TST_XA_FORGET_REPLY 0xB8
+#define MQ_TST_XA_RECOVER_REPLY 0xB9
+#define MQ_TST_XA_COMPLETE_REPLY 0xBA
+
+#define MQ_SPI_QUERY 0x01
+#define MQ_SPI_PUT 0x02
+#define MQ_SPI_GET 0x03
+#define MQ_SPI_ACTIVATE 0x04
+
+#define MQ_SPI_ACTIVATE_ENABLE 0x01
+#define MQ_SPI_ACTIVATE_DISABLE 0x02
+
+#define MQ_SPI_OPTIONS_BLANK_PADDED 0x01
+#define MQ_SPI_OPTIONS_SYNCPOINT 0x02
+#define MQ_SPI_OPTIONS_DEFERRED 0x04
+
+#define MQ_TCF_CONFIRM_REQUEST 0x01
+#define MQ_TCF_ERROR 0x02
+#define MQ_TCF_REQUEST_CLOSE 0x04
+#define MQ_TCF_CLOSE_CHANNEL 0x08
+#define MQ_TCF_FIRST 0x10
+#define MQ_TCF_LAST 0x20
+#define MQ_TCF_REQUEST_ACCEPTED 0x40
+#define MQ_TCF_DLQ_USED 0x80
+
+#define MQ_ICF_MSG_SEQ 0x01
+#define MQ_ICF_CONVERSION_CAPABLE 0x02
+#define MQ_ICF_SPLIT_MESSAGE 0x04
+#define MQ_ICF_MQREQUEST 0x20
+#define MQ_ICF_SVRCONN_SECURITY 0x40
+#define MQ_ICF_RUNTIME 0x80
+
+#define MQ_IEF_CCSID 0x01
+#define MQ_IEF_ENCODING 0x02
+#define MQ_IEF_MAX_TRANSMISSION_SIZE 0x04
+#define MQ_IEF_FAP_LEVEL 0x08
+#define MQ_IEF_MAX_MSG_SIZE 0x10
+#define MQ_IEF_MAX_MSG_PER_BATCH 0x20
+#define MQ_IEF_SEQ_WRAP_VALUE 0x40
+#define MQ_IEF_HEARTBEAT_INTERVAL 0x80
+
+#define MQ_BIG_ENDIAN 0x01
+#define MQ_LITTLE_ENDIAN 0x02
+
+#define MQ_CONN_VERSION 0x01
+#define MQ_CONNX_VERSION 0x03
+
+#define MQ_STATUS_E_REMOTE_CHANNEL_NOT_FOUND 0x01
+#define MQ_STATUS_E_BAD_REMOTE_CHANNEL_TYPE 0x02
+#define MQ_STATUS_E_REMOTE_QM_UNAVAILABLE 0x03
+#define MQ_STATUS_E_MSG_SEQUENCE_ERROR 0x04
+#define MQ_STATUS_E_REMOTE_QM_TERMINATING 0x05
+#define MQ_STATUS_E_MSG_NOT_RECEIVED 0x06
+#define MQ_STATUS_I_CHANNEL_CLOSED 0x07
+#define MQ_STATUS_I_DISCINTERVAL_EXPIRED 0x08
+#define MQ_STATUS_E_REMOTE_PROTOCOL_ERROR 0x0A
+#define MQ_STATUS_E_BIND_FAILED 0x14
+#define MQ_STATUS_E_MSGWRAP_DIFFERENT 0x15
+#define MQ_STATUS_E_REMOTE_CHANNEL_UNAVAILABLE 0x16
+#define MQ_STATUS_E_TERMINATED_BY_REMOTE_EXIT 0x17
+#define MQ_STATUS_E_SSL_REMOTE_BAD_CIPHER 0x18
+
+/* These errors codes are documented in javax.transaction.xa.XAException */
+#define MQ_XA_RBROLLBACK 100
+#define MQ_XA_RBCOMMFAIL 101
+#define MQ_XA_RBDEADLOCK 102
+#define MQ_XA_RBINTEGRITY 103
+#define MQ_XA_RBOTHER 104
+#define MQ_XA_RBPROTO 105
+#define MQ_XA_RBTIMEOUT 106
+#define MQ_XA_RBTRANSIENT 107
+#define MQ_XA_NOMIGRATE 9
+#define MQ_XA_HEURHAZ 8
+#define MQ_XA_HEURCOM 7
+#define MQ_XA_HEURRB 6
+#define MQ_XA_HEURMIX 5
+#define MQ_XA_RETRY 4
+#define MQ_XA_RDONLY 3
+#define MQ_XA_OK 0
+#define MQ_XAER_ASYNC -2
+#define MQ_XAER_RMERR -3
+#define MQ_XAER_NOTA -4
+#define MQ_XAER_INVAL -5
+#define MQ_XAER_PROTO -6
+#define MQ_XAER_RMFAIL -7
+#define MQ_XAER_DUPID -8
+#define MQ_XAER_OUTSIDE -9
+
+/* These flags are documented in javax.transaction.xa.XAResource */
+#define MQ_XA_TMNOFLAGS 0
+#define MQ_XA_TMJOIN 0x200000
+#define MQ_XA_TMENDRSCAN 0x800000
+#define MQ_XA_TMSTARTRSCAN 0x1000000
+#define MQ_XA_TMSUSPEND 0x2000000
+#define MQ_XA_TMSUCCESS 0x4000000
+#define MQ_XA_TMRESUME 0x8000000
+#define MQ_XA_TMFAIL 0x20000000
+#define MQ_XA_TMONEPHASE 0x40000000
+
+#define MQ_PMRF_NONE 0x00
+#define MQ_PMRF_MSG_ID 0x01
+#define MQ_PMRF_CORREL_ID 0x02
+#define MQ_PMRF_GROUP_ID 0x04
+#define MQ_PMRF_FEEDBACK 0x08
+#define MQ_PMRF_ACCOUNTING_TOKEN 0x10
+
+/* MQ structures */
+/* Undocumented structures */
+#define MQ_TEXT_TSH "Transmission Segment Header"
+#define MQ_TEXT_API "API Header"
+#define MQ_TEXT_ID "Initial Data"
+#define MQ_TEXT_UID "User Id Data"
+#define MQ_TEXT_MSH "Message Segment Header"
+#define MQ_TEXT_CONN "MQCONN"
+#define MQ_TEXT_INQ "MQINQ/MQSET"
+#define MQ_TEXT_PUT "MQPUT/MQGET"
+#define MQ_TEXT_OPEN "MQOPEN/MQCLOSE"
+#define MQ_TEXT_PING "PING"
+#define MQ_TEXT_RESET "RESET"
+#define MQ_TEXT_STAT "STATUS"
+#define MQ_TEXT_SPI "SPI"
+#define MQ_TEXT_XA "XA"
+#define MQ_TEXT_XID "Xid"
+#define MQ_TEXT_XINF "XA_info"
+
+/* Documented structures with structid */
+#define MQ_TEXT_CIH "CICS bridge Header"
+#define MQ_TEXT_DH "Distribution Header"
+#define MQ_TEXT_DLH "Dead-Letter Header"
+#define MQ_TEXT_GMO "Get Message Options"
+#define MQ_TEXT_IIH "IMS Information Header"
+#define MQ_TEXT_MD "Message Descriptor"
+#define MQ_TEXT_MDE "Message Descriptor Extension"
+#define MQ_TEXT_OD "Object Descriptor"
+#define MQ_TEXT_PMO "Put Message Options"
+#define MQ_TEXT_RMH "Reference Message Header"
+#define MQ_TEXT_TM "Trigger Message"
+#define MQ_TEXT_TMC2 "Trigger Message 2 (character format)"
+#define MQ_TEXT_WIH "Work Information Header"
+#define MQ_TEXT_XQH "Transmission Queue Header"
+
+/* Documented structures without structid */
+#define MQ_TEXT_OR "Object Record"
+#define MQ_TEXT_PMR "Put Message Record"
+#define MQ_TEXT_RR "Response Record"
+
+
+static const value_string mq_opcode_vals[] = {
+ { MQ_TST_INITIAL, "INITIAL_DATA" },
+ { MQ_TST_RESYNC, "RESYNC_DATA" },
+ { MQ_TST_RESET, "RESET_DATA" },
+ { MQ_TST_MESSAGE, "MESSAGE_DATA" },
+ { MQ_TST_STATUS, "STATUS_DATA" },
+ { MQ_TST_SECURITY, "SECURITY_DATA" },
+ { MQ_TST_PING, "PING_DATA" },
+ { MQ_TST_USERID, "USERID_DATA" },
+ { MQ_TST_HEARTBEAT, "HEARTBEAT" },
+ { MQ_TST_MQCONN, "MQCONN" },
+ { MQ_TST_MQDISC, "MQDISC" },
+ { MQ_TST_MQOPEN, "MQOPEN" },
+ { MQ_TST_MQCLOSE, "MQCLOSE" },
+ { MQ_TST_MQGET, "MQGET" },
+ { MQ_TST_MQPUT, "MQPUT" },
+ { MQ_TST_MQPUT1, "MQPUT1" },
+ { MQ_TST_MQSET, "MQSET" },
+ { MQ_TST_MQINQ, "MQINQ" },
+ { MQ_TST_MQCMIT, "MQCMIT" },
+ { MQ_TST_MQBACK, "MQBACK" },
+ { MQ_TST_SPI, "SPI" },
+ { MQ_TST_MQCONN_REPLY, "MQCONN_REPLY" },
+ { MQ_TST_MQDISC_REPLY, "MQDISC_REPLY" },
+ { MQ_TST_MQOPEN_REPLY, "MQOPEN_REPLY" },
+ { MQ_TST_MQCLOSE_REPLY, "MQCLOSE_REPLY" },
+ { MQ_TST_MQGET_REPLY, "MQGET_REPLY" },
+ { MQ_TST_MQPUT_REPLY, "MQPUT_REPLY" },
+ { MQ_TST_MQPUT1_REPLY, "MQPUT1_REPLY" },
+ { MQ_TST_MQSET_REPLY, "MQSET_REPLY" },
+ { MQ_TST_MQINQ_REPLY, "MQINQ_REPLY" },
+ { MQ_TST_MQCMIT_REPLY, "MQCMIT_REPLY" },
+ { MQ_TST_MQBACK_REPLY, "MQBACK_REPLY" },
+ { MQ_TST_SPI_REPLY, "SPI_REPLY" },
+ { MQ_TST_XA_START, "XA_START" },
+ { MQ_TST_XA_END, "XA_END" },
+ { MQ_TST_XA_OPEN, "XA_OPEN" },
+ { MQ_TST_XA_CLOSE, "XA_CLOSE" },
+ { MQ_TST_XA_PREPARE, "XA_PREPARE" },
+ { MQ_TST_XA_COMMIT, "XA_COMMIT" },
+ { MQ_TST_XA_ROLLBACK, "XA_ROLLBACK" },
+ { MQ_TST_XA_FORGET, "XA_FORGET" },
+ { MQ_TST_XA_RECOVER, "XA_RECOVER" },
+ { MQ_TST_XA_COMPLETE, "XA_COMPLETE" },
+ { MQ_TST_XA_START_REPLY, "XA_START_REPLY" },
+ { MQ_TST_XA_END_REPLY, "XA_END_REPLY" },
+ { MQ_TST_XA_OPEN_REPLY, "XA_OPEN_REPLY" },
+ { MQ_TST_XA_CLOSE_REPLY, "XA_CLOSE_REPLY" },
+ { MQ_TST_XA_PREPARE_REPLY, "XA_PREPARE_REPLY" },
+ { MQ_TST_XA_COMMIT_REPLY, "XA_COMMIT_REPLY" },
+ { MQ_TST_XA_ROLLBACK_REPLY, "XA_ROLLBACK_REPLY" },
+ { MQ_TST_XA_FORGET_REPLY, "XA_FORGET_REPLY" },
+ { MQ_TST_XA_RECOVER_REPLY, "XA_RECOVER_REPLY" },
+ { MQ_TST_XA_COMPLETE_REPLY, "XA_COMPLETE_REPLY" },
+ { 0, NULL }
+};
+
+static const value_string mq_spi_verbs_vals[] = {
+ { MQ_SPI_QUERY, "QUERY" },
+ { MQ_SPI_PUT, "PUT" },
+ { MQ_SPI_GET, "GET" },
+ { MQ_SPI_ACTIVATE, "ACTIVATE" },
+ { 0, NULL }
+};
+
+static const value_string mq_spi_activate_vals[] = {
+ { MQ_SPI_ACTIVATE_ENABLE, "ENABLE" },
+ { MQ_SPI_ACTIVATE_DISABLE, "DISABLE" },
+ { 0, NULL }
+};
+
+static const value_string mq_status_vals[] = {
+ { MQ_STATUS_E_REMOTE_CHANNEL_NOT_FOUND, "REMOTE_CHANNEL_NOT_FOUND" },
+ { MQ_STATUS_E_BAD_REMOTE_CHANNEL_TYPE, "BAD_REMOTE_CHANNEL_TYPE" },
+ { MQ_STATUS_E_REMOTE_QM_UNAVAILABLE, "REMOTE_QM_UNAVAILABLE" },
+ { MQ_STATUS_E_MSG_SEQUENCE_ERROR, "MSG_SEQUENCE_ERROR" },
+ { MQ_STATUS_E_REMOTE_QM_TERMINATING, "REMOTE_QM_TERMINATING" },
+ { MQ_STATUS_E_MSG_NOT_RECEIVED, "MSG_NOT_RECEIVED" },
+ { MQ_STATUS_I_CHANNEL_CLOSED, "CHANNEL_CLOSED" },
+ { MQ_STATUS_I_DISCINTERVAL_EXPIRED, "DISCINTERVAL_EXPIRED" },
+ { MQ_STATUS_E_REMOTE_PROTOCOL_ERROR, "REMOTE_PROTOCOL_ERROR" },
+ { MQ_STATUS_E_BIND_FAILED, "BIND_FAILED" },
+ { MQ_STATUS_E_MSGWRAP_DIFFERENT, "MSGWRAP_DIFFERENT" },
+ { MQ_STATUS_E_REMOTE_CHANNEL_UNAVAILABLE, "REMOTE_CHANNEL_UNAVAILABLE" },
+ { MQ_STATUS_E_TERMINATED_BY_REMOTE_EXIT, "TERMINATED_BY_REMOTE_EXIT" },
+ { MQ_STATUS_E_SSL_REMOTE_BAD_CIPHER, "SSL_REMOTE_BAD_CIPHER" },
+ { 0, NULL }
+};
+
+static const value_string mq_xaer_vals[] = {
+ { MQ_XA_RBROLLBACK, "XA_RBROLLBACK" },
+ { MQ_XA_RBCOMMFAIL, "XA_RBCOMMFAIL" },
+ { MQ_XA_RBDEADLOCK, "XA_RBDEADLOCK" },
+ { MQ_XA_RBINTEGRITY, "XA_RBINTEGRITY" },
+ { MQ_XA_RBOTHER, "XA_RBOTHER" },
+ { MQ_XA_RBPROTO, "XA_RBPROTO" },
+ { MQ_XA_RBTIMEOUT, "XA_RBTIMEOUT" },
+ { MQ_XA_RBTRANSIENT, "XA_RBTRANSIENT" },
+ { MQ_XA_NOMIGRATE, "XA_NOMIGRATE" },
+ { MQ_XA_HEURHAZ, "XA_HEURHAZ" },
+ { MQ_XA_HEURCOM, "XA_HEURCOM" },
+ { MQ_XA_HEURRB, "XA_HEURRB" },
+ { MQ_XA_HEURMIX, "XA_HEURMIX" },
+ { MQ_XA_RETRY, "XA_RETRY" },
+ { MQ_XA_RDONLY, "XA_RDONLY" },
+ { MQ_XA_OK, "XA_OK" },
+ { (guint32)MQ_XAER_ASYNC, "XAER_ASYNC" },
+ { (guint32)MQ_XAER_RMERR, "XAER_RMERR" },
+ { (guint32)MQ_XAER_NOTA, "XAER_NOTA" },
+ { (guint32)MQ_XAER_INVAL, "XAER_INVAL" },
+ { (guint32)MQ_XAER_PROTO, "XAER_PROTO" },
+ { (guint32)MQ_XAER_RMFAIL, "XAER_RMFAIL" },
+ { (guint32)MQ_XAER_DUPID, "XAER_DUPID" },
+ { (guint32)MQ_XAER_OUTSIDE, "XAER_OUTSIDE" },
+ { 0, NULL }
+};
+
+static const value_string mq_structid_vals[] = {
+ { MQ_STRUCTID_CIH, MQ_TEXT_CIH },
+ { MQ_STRUCTID_DH, MQ_TEXT_DH },
+ { MQ_STRUCTID_DLH, MQ_TEXT_DLH },
+ { MQ_STRUCTID_GMO, MQ_TEXT_GMO },
+ { MQ_STRUCTID_ID, MQ_TEXT_ID },
+ { MQ_STRUCTID_IIH, MQ_TEXT_IIH },
+ { MQ_STRUCTID_MD, MQ_TEXT_MD },
+ { MQ_STRUCTID_MDE, MQ_TEXT_MDE },
+ { MQ_STRUCTID_MSH, MQ_TEXT_MSH },
+ { MQ_STRUCTID_OD, MQ_TEXT_OD },
+ { MQ_STRUCTID_PMO, MQ_TEXT_PMO },
+ { MQ_STRUCTID_RMH, MQ_TEXT_RMH },
+ { MQ_STRUCTID_TM, MQ_TEXT_TM },
+ { MQ_STRUCTID_TMC2, MQ_TEXT_TMC2 },
+ { MQ_STRUCTID_TSH, MQ_TEXT_TSH },
+ { MQ_STRUCTID_UID, MQ_TEXT_UID },
+ { MQ_STRUCTID_WIH, MQ_TEXT_WIH },
+ { MQ_STRUCTID_XQH, MQ_TEXT_XQH },
+ { MQ_STRUCTID_CIH_EBCDIC, MQ_TEXT_CIH },
+ { MQ_STRUCTID_DH_EBCDIC, MQ_TEXT_DH },
+ { MQ_STRUCTID_DLH_EBCDIC, MQ_TEXT_DLH },
+ { MQ_STRUCTID_GMO_EBCDIC, MQ_TEXT_GMO },
+ { MQ_STRUCTID_ID_EBCDIC, MQ_TEXT_ID },
+ { MQ_STRUCTID_IIH_EBCDIC, MQ_TEXT_IIH },
+ { MQ_STRUCTID_MD_EBCDIC, MQ_TEXT_MD },
+ { MQ_STRUCTID_MDE_EBCDIC, MQ_TEXT_MDE },
+ { MQ_STRUCTID_OD_EBCDIC, MQ_TEXT_OD },
+ { MQ_STRUCTID_PMO_EBCDIC, MQ_TEXT_PMO },
+ { MQ_STRUCTID_RMH_EBCDIC, MQ_TEXT_RMH },
+ { MQ_STRUCTID_TM_EBCDIC, MQ_TEXT_TM },
+ { MQ_STRUCTID_TMC2_EBCDIC, MQ_TEXT_TMC2 },
+ { MQ_STRUCTID_TSH_EBCDIC, MQ_TEXT_TSH },
+ { MQ_STRUCTID_UID_EBCDIC, MQ_TEXT_UID },
+ { MQ_STRUCTID_WIH_EBCDIC, MQ_TEXT_WIH },
+ { MQ_STRUCTID_XQH_EBCDIC, MQ_TEXT_XQH },
+ { 0, NULL }
+};
+
+static const value_string mq_byteorder_vals[] = {
+ { MQ_LITTLE_ENDIAN, "Little endian" },
+ { MQ_BIG_ENDIAN, "Big endian" },
+ { 0, NULL }
+};
+
+static const value_string mq_conn_version_vals[] = {
+ { MQ_CONN_VERSION, "MQCONN" },
+ { MQ_CONNX_VERSION, "MQCONNX" },
+ { 0, NULL }
+};
+
+struct mq_msg_properties {
+ gint iOffsetEncoding; /* Message encoding */
+ gint iOffsetCcsid; /* Message character set */
+ gint iOffsetFormat; /* Message format */
+};
+
+static guint32 tvb_get_guint32_endian(tvbuff_t *a_tvb, gint a_iOffset, gboolean a_bLittleEndian)
+{
+ guint32 iResult;
+ if (a_bLittleEndian)
+ iResult = tvb_get_letohl(a_tvb, a_iOffset);
+ else
+ iResult = tvb_get_ntohl(a_tvb, a_iOffset);
+ return iResult;
+}
+
+/* This routine truncates the string at the first blank space */
+static gint strip_trailing_blanks(guint8* a_string, gint a_size)
+{
+ gint i = 0;
+ if (a_string != NULL)
+ {
+ for (i = 0; i < a_size; i++)
+ {
+ if (a_string[i] == ' ' || a_string[i] == '\0')
+ {
+ a_string[i] = '\0';
+ break;
+ }
+ }
+ }
+ return i;
+}
+
+static gint
+dissect_mq_md(tvbuff_t *tvb, proto_tree *tree, gboolean bLittleEndian, gint offset, struct mq_msg_properties* tMsgProps)
+{
+ proto_tree *mq_tree = NULL;
+ guint32 structId;
+ gint iSizeMD = 0;
+
+ if (tvb_length_remaining(tvb, offset) >= 4)
+ {
+ structId = tvb_get_ntohl(tvb, offset);
+ if ((structId == MQ_STRUCTID_MD || structId == MQ_STRUCTID_MD_EBCDIC) && tvb_length_remaining(tvb, offset) >= 8)
+ {
+ guint32 iVersionMD = 0;
+ iVersionMD = tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian);
+ /* Compute length according to version */
+ switch (iVersionMD)
+ {
+ case 1: iSizeMD = 324; break;
+ case 2: iSizeMD = 364; break;
+ }
+
+ if (iSizeMD != 0 && tvb_length_remaining(tvb, offset) >= iSizeMD)
+ {
+ tMsgProps->iOffsetEncoding = offset + 24;
+ tMsgProps->iOffsetCcsid = offset + 28;
+ tMsgProps->iOffsetFormat = offset + 32;
+ if (tree)
+ {
+ proto_item *ti = NULL;
+ ti = proto_tree_add_text(tree, tvb, offset, iSizeMD, MQ_TEXT_MD);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_md);
+
+ proto_tree_add_item(mq_tree, hf_mq_md_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_report, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_msgtype, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_expiry, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_feedback, tvb, offset + 20, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_encoding, tvb, offset + 24, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_ccsid, tvb, offset + 28, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_format, tvb, offset + 32, 8, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_priority, tvb, offset + 40, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_persistence, tvb, offset + 44, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_msgid, tvb, offset + 48, 24, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_correlid, tvb, offset + 72, 24, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_backountcount, tvb, offset + 96, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_replytoq, tvb, offset + 100, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_replytoqmgr, tvb, offset + 148, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_userid, tvb, offset + 196, 12, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_acttoken, tvb, offset + 208, 32, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_appliddata, tvb, offset + 240, 32, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_putappltype, tvb, offset + 272, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_putapplname, tvb, offset + 276, 28, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_putdate, tvb, offset + 304, 8, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_puttime, tvb, offset + 312, 8, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_applorigindata, tvb, offset + 320, 4, FALSE);
+
+ if (iVersionMD >= 2)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_md_groupid, tvb, offset + 324, 24, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_msgseqnumber, tvb, offset + 348, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_offset, tvb, offset + 352, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_msgflags, tvb, offset + 356, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_originallength, tvb, offset + 360, 4, bLittleEndian);
+ }
+ }
+ }
+ }
+ }
+ return iSizeMD;
+}
+
+
+static gint
+dissect_mq_or(tvbuff_t *tvb, proto_tree *tree, gint offset, gint iNbrRecords, gint offsetOR)
+{
+ proto_tree *mq_tree = NULL;
+ proto_item *ti = NULL;
+ gint iSizeOR = 0;
+ if (offsetOR != 0)
+ {
+ iSizeOR = iNbrRecords * 96;
+ if (tvb_length_remaining(tvb, offset) >= iSizeOR)
+ {
+ if (tree)
+ {
+ gint iOffsetOR = 0;
+ gint iRecord = 0;
+ for (iRecord = 0; iRecord < iNbrRecords ; iRecord++)
+ {
+ ti = proto_tree_add_text(tree, tvb, offset + iOffsetOR, 96, MQ_TEXT_OR);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_or);
+ proto_tree_add_item(mq_tree, hf_mq_or_objname, tvb, offset + iOffsetOR, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_or_objqmgrname, tvb, offset + iOffsetOR + 48, 48, FALSE);
+ iOffsetOR += 96;
+ }
+ }
+ }
+ else iSizeOR = 0;
+ }
+ return iSizeOR;
+}
+
+static gint
+dissect_mq_rr(tvbuff_t *tvb, proto_tree *tree, gboolean bLittleEndian, gint offset, gint iNbrRecords, gint offsetRR)
+{
+ proto_tree *mq_tree = NULL;
+ proto_item *ti = NULL;
+ gint iSizeRR = 0;
+ if (offsetRR != 0)
+ {
+ iSizeRR = iNbrRecords * 8;
+ if (tvb_length_remaining(tvb, offset) >= iSizeRR)
+ {
+ if (tree)
+ {
+ gint iOffsetRR = 0;
+ gint iRecord = 0;
+ for (iRecord = 0; iRecord < iNbrRecords; iRecord++)
+ {
+ ti = proto_tree_add_text(tree, tvb, offset + iOffsetRR, 8, MQ_TEXT_RR);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_rr);
+ proto_tree_add_item(mq_tree, hf_mq_rr_completioncode, tvb, offset + iOffsetRR, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_rr_reasoncode, tvb, offset + iOffsetRR + 4, 4, bLittleEndian);
+ iOffsetRR += 8;
+ }
+ }
+ }
+ else iSizeRR = 0;
+ }
+ return iSizeRR;
+}
+
+static gint
+dissect_mq_pmr(tvbuff_t *tvb, proto_tree *tree, gboolean bLittleEndian, gint offset, gint iNbrRecords, gint offsetPMR, guint32 recFlags)
+{
+ proto_tree *mq_tree = NULL;
+ proto_item *ti = NULL;
+ gint iSizePMR1 = 0;
+ gint iSizePMR = 0;
+
+ iSizePMR1 = ((((recFlags & MQ_PMRF_MSG_ID) != 0) * 24)
+ +(((recFlags & MQ_PMRF_CORREL_ID) != 0) * 24)
+ +(((recFlags & MQ_PMRF_GROUP_ID) != 0) * 24)
+ +(((recFlags & MQ_PMRF_FEEDBACK) != 0) * 4)
+ +(((recFlags & MQ_PMRF_ACCOUNTING_TOKEN) != 0) * 32));
+ if (offsetPMR != 0)
+ {
+ iSizePMR = iNbrRecords * iSizePMR1;
+ if (tvb_length_remaining(tvb, offset) >= iSizePMR)
+ {
+ if (tree)
+ {
+ gint iOffsetPMR = 0;
+ gint iRecord = 0;
+ for (iRecord = 0; iRecord < iNbrRecords; iRecord++)
+ {
+ ti = proto_tree_add_text(tree, tvb, offset + iOffsetPMR, iSizePMR1, MQ_TEXT_PMR);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_pmr);
+ if ((recFlags & MQ_PMRF_MSG_ID) != 0)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_pmr_msgid, tvb, offset + iOffsetPMR, 24, bLittleEndian);
+ iOffsetPMR += 24;
+ }
+ if ((recFlags & MQ_PMRF_CORREL_ID) != 0)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_pmr_correlid, tvb, offset + iOffsetPMR, 24, bLittleEndian);
+ iOffsetPMR += 24;
+ }
+ if ((recFlags & MQ_PMRF_GROUP_ID) != 0)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_pmr_groupid, tvb, offset + iOffsetPMR, 24, bLittleEndian);
+ iOffsetPMR += 24;
+ }
+ if ((recFlags & MQ_PMRF_FEEDBACK) != 0)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_pmr_feedback, tvb, offset + iOffsetPMR, 4, bLittleEndian);
+ iOffsetPMR += 4;
+ }
+ if ((recFlags & MQ_PMRF_ACCOUNTING_TOKEN) != 0)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_pmr_acttoken, tvb, offset + iOffsetPMR, 32, bLittleEndian);
+ iOffsetPMR += 32;
+ }
+ }
+ }
+ }
+ else iSizePMR = 0;
+ }
+ return iSizePMR;
+}
+
+static gint
+dissect_mq_gmo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean bLittleEndian, gint offset)
+{
+ proto_tree *mq_tree = NULL;
+ proto_item *ti = NULL;
+ guint32 structId;
+ gint iSizeGMO = 0;
+
+ if (tvb_length_remaining(tvb, offset) >= 4)
+ {
+ structId = tvb_get_ntohl(tvb, offset);
+ if ((structId == MQ_STRUCTID_GMO || structId == MQ_STRUCTID_GMO_EBCDIC) && tvb_length_remaining(tvb, offset) >= 8)
+ {
+ guint32 iVersionGMO = 0;
+ iVersionGMO = tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian);
+ /* Compute length according to version */
+ switch (iVersionGMO)
+ {
+ case 1: iSizeGMO = 72; break;
+ case 2: iSizeGMO = 80; break;
+ case 3: iSizeGMO = 100; break;
+ }
+
+ if (iSizeGMO != 0 && tvb_length_remaining(tvb, offset) >= iSizeGMO)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ guint8* sQueue;
+ sQueue = tvb_get_string(tvb, offset + 24, 48);
+ if (strip_trailing_blanks(sQueue, 48) != 0)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Q=%s", sQueue);
+ }
+ g_free(sQueue);
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(tree, tvb, offset, iSizeGMO, MQ_TEXT_GMO);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_gmo);
+
+ proto_tree_add_item(mq_tree, hf_mq_gmo_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_options, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_waitinterval, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_signal1, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_signal2, tvb, offset + 20, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_resolvedqname, tvb, offset + 24, 48, FALSE);
+
+ if (iVersionGMO >= 2)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_gmo_matchoptions, tvb, offset + 72, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_groupstatus, tvb, offset + 76, 1, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_segmentstatus, tvb, offset + 77, 1, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_segmentation, tvb, offset + 78, 1, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_reserved, tvb, offset + 79, 1, FALSE);
+ }
+
+ if (iVersionGMO >= 3)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_gmo_msgtoken, tvb, offset + 80, 16, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_gmo_returnedlength, tvb, offset + 96, 4, bLittleEndian);
+ }
+ }
+ }
+ }
+ }
+ return iSizeGMO;
+}
+
+static gint
+dissect_mq_pmo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean bLittleEndian, gint offset, gint* iDistributionListSize)
+{
+ proto_tree *mq_tree = NULL;
+ proto_item *ti = NULL;
+ guint32 structId;
+ gint iSizePMO = 0;
+
+ if (tvb_length_remaining(tvb, offset) >= 4)
+ {
+ structId = tvb_get_ntohl(tvb, offset);
+ if ((structId == MQ_STRUCTID_PMO || structId == MQ_STRUCTID_PMO_EBCDIC) && tvb_length_remaining(tvb, offset) >= 8)
+ {
+ guint32 iVersionPMO = 0;
+ iVersionPMO = tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian);
+ /* Compute length according to version */
+ switch (iVersionPMO)
+ {
+ case 1: iSizePMO = 128; break;
+ case 2: iSizePMO = 152;break;
+ }
+
+ if (iSizePMO != 0 && tvb_length_remaining(tvb, offset) >= iSizePMO)
+ {
+ gint iNbrRecords = 0;
+ guint32 iRecFlags = 0;
+ if (iVersionPMO >= 2)
+ {
+ iNbrRecords = tvb_get_guint32_endian(tvb, offset + 128, bLittleEndian);
+ iRecFlags = tvb_get_guint32_endian(tvb, offset + 132, bLittleEndian);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ guint8* sQueue;
+ sQueue = tvb_get_string(tvb, offset + 32, 48);
+ if (strip_trailing_blanks(sQueue, 48) != 0)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Q=%s", sQueue);
+ }
+ g_free(sQueue);
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(tree, tvb, offset, iSizePMO, MQ_TEXT_PMO);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_pmo);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_options, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_timeout, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_context, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_knowndestcount, tvb, offset + 20, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_unknowndestcount, tvb, offset + 24, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_invaliddestcount, tvb, offset + 28, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_resolvedqname, tvb, offset + 32, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_resolvedqmgrname, tvb, offset + 80, 48, FALSE);
+
+ if (iVersionPMO >= 2)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_pmo_recspresent, tvb, offset + 128, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_putmsgrecfields, tvb, offset + 132, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_putmsgrecoffset, tvb, offset + 136, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_responserecoffset, tvb, offset + 140, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_putmsgrecptr, tvb, offset + 144, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_pmo_responserecptr, tvb, offset + 148, 4, bLittleEndian);
+ }
+
+ }
+ if (iNbrRecords > 0)
+ {
+ gint iOffsetPMR = 0;
+ gint iOffsetRR = 0;
+ gint iSizePMRRR = 0;
+
+ *iDistributionListSize = iNbrRecords;
+ iOffsetPMR = tvb_get_guint32_endian(tvb, offset + 136, bLittleEndian);
+ iOffsetRR = tvb_get_guint32_endian(tvb, offset + 140, bLittleEndian);
+ if ((iSizePMRRR = dissect_mq_pmr(tvb, tree, bLittleEndian, offset + iSizePMO, iNbrRecords, iOffsetPMR, iRecFlags)) != 0)
+ iSizePMO += iSizePMRRR;
+ if ((iSizePMRRR = dissect_mq_rr(tvb, tree, bLittleEndian, offset + iSizePMO, iNbrRecords, iOffsetRR)) != 0)
+ iSizePMO += iSizePMRRR;
+ }
+ }
+ }
+ }
+ return iSizePMO;
+}
+
+static gint
+dissect_mq_xid(tvbuff_t *tvb, proto_tree *tree, gboolean bLittleEndian, gint offset)
+{
+ proto_tree *mq_tree = NULL;
+ proto_item *ti = NULL;
+ gint iSizeXid = 0;
+ if (tvb_length_remaining(tvb, offset) >= 6)
+ {
+ guint8 iXidLength = 0;
+ guint8 iBqLength = 0;
+ iXidLength = tvb_get_guint8(tvb, offset + 4);
+ iBqLength = tvb_get_guint8(tvb, offset + 5);
+ iSizeXid = 6 + iXidLength + iBqLength;
+
+ if (tvb_length_remaining(tvb, offset) >= iSizeXid)
+ {
+ if (tree)
+ {
+ ti = proto_tree_add_text(tree, tvb, offset, iSizeXid, MQ_TEXT_XID);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_xa_xid);
+
+ proto_tree_add_item(mq_tree, hf_mq_xa_xid_formatid, tvb, offset, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_xa_xid_globalxid_length, tvb, offset + 4, 1, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_xa_xid_brq_length, tvb, offset + 5, 1, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_xa_xid_globalxid, tvb, offset + 6, iXidLength, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_xa_xid_brq, tvb, offset + 6 + iXidLength, iBqLength, FALSE);
+ }
+ iSizeXid += (4 - (iSizeXid % 4)) % 4; /* Pad for alignment with 4 byte word boundary */
+ if (tvb_length_remaining(tvb, offset) < iSizeXid) iSizeXid = 0;
+ }
+ else iSizeXid = 0;
+ }
+ return iSizeXid;
+}
+
+static void
+dissect_mq_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *mq_tree = NULL;
+ proto_tree *mqroot_tree = NULL;
+ proto_item *ti = NULL;
+ gint offset = 0;
+ guint32 structId = MQ_STRUCTID_NULL;
+ guint8 opcode;
+ guint32 iSegmentLength = 0;
+ guint32 iSizePayload = 0;
+ gint iSizeMD = 0;
+ gboolean bLittleEndian = FALSE;
+ gboolean bPayload = FALSE;
+ gboolean bEBCDIC = FALSE;
+ gint iDistributionListSize = 0;
+ struct mq_msg_properties tMsgProps;
+ static gint iPreviousFrameNumber = -1;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "MQ");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ /* This is a trick to know whether this is the first PDU in this packet or not */
+ if (iPreviousFrameNumber != (gint) pinfo->fd->num)
+ col_clear(pinfo->cinfo, COL_INFO);
+ else
+ col_append_str(pinfo->cinfo, COL_INFO, " | ");
+ }
+ iPreviousFrameNumber = pinfo->fd->num;
+ if (tvb_length(tvb) >= 4)
+ {
+ structId = tvb_get_ntohl(tvb, offset);
+ if ((structId == MQ_STRUCTID_TSH || structId == MQ_STRUCTID_TSH_EBCDIC) && tvb_length_remaining(tvb, offset) >= 28)
+ {
+ /* An MQ packet always starts with this structure*/
+ gint iSizeTSH = 28;
+ guint8 iControlFlags = 0;
+ if (structId == MQ_STRUCTID_TSH_EBCDIC) bEBCDIC = TRUE;
+ opcode = tvb_get_guint8(tvb, offset + 9);
+ bLittleEndian = (tvb_get_guint8(tvb, offset + 8) == MQ_LITTLE_ENDIAN ? TRUE : FALSE);
+ iSegmentLength = tvb_get_ntohl(tvb, offset + 4);
+ iControlFlags = tvb_get_guint8(tvb, offset + 10);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(opcode, mq_opcode_vals, "Unknown (0x%02x)"));
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_mq, tvb, offset, -1, FALSE);
+ proto_item_append_text(ti, " (%s)", val_to_str(opcode, mq_opcode_vals, "Unknown (0x%02x)"));
+ if (bEBCDIC == TRUE) proto_item_append_text(ti, " (EBCDIC)");
+ mqroot_tree = proto_item_add_subtree(ti, ett_mq);
+
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeTSH, MQ_TEXT_TSH);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_tsh);
+
+ proto_tree_add_item(mq_tree, hf_mq_tsh_structid, tvb, offset + 0, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_tsh_packetlength, tvb, offset + 4, 4, FALSE);
+
+ proto_tree_add_item(mq_tree, hf_mq_tsh_byteorder, tvb, offset + 8, 1, FALSE);
+
+ proto_tree_add_item(mq_tree, hf_mq_tsh_opcode, tvb, offset + 9, 1, FALSE);
+
+ /* Control flags */
+ {
+ proto_tree *mq_tree_sub = NULL;
+
+ ti = proto_tree_add_item(mq_tree, hf_mq_tsh_controlflags, tvb, offset + 10, 1, FALSE);
+ mq_tree_sub = proto_item_add_subtree(ti, ett_mq_tsh_tcf);
+
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_tsh_tcf_dlq, tvb, offset + 10, 1, iControlFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_tsh_tcf_reqacc, tvb, offset + 10, 1, iControlFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_tsh_tcf_last, tvb, offset + 10, 1, iControlFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_tsh_tcf_first, tvb, offset + 10, 1, iControlFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_tsh_tcf_closechann, tvb, offset + 10, 1, iControlFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_tsh_tcf_reqclose, tvb, offset + 10, 1, iControlFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_tsh_tcf_error, tvb, offset + 10, 1, iControlFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_tsh_tcf_confirmreq, tvb, offset + 10, 1, iControlFlags);
+ }
+
+ proto_tree_add_item(mq_tree, hf_mq_tsh_reserved, tvb, offset + 11, 1, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_tsh_luwid, tvb, offset + 12, 8, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_tsh_encoding, tvb, offset + 20, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_tsh_ccsid, tvb, offset + 24, 2, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_tsh_padding, tvb, offset + 26, 2, FALSE);
+ }
+ offset += iSizeTSH;
+
+ /* Now dissect the embedded structures */
+ if (tvb_length_remaining(tvb, offset) >= 4)
+ {
+ structId = tvb_get_ntohl(tvb, offset);
+ if (((iControlFlags & MQ_TCF_FIRST) != 0) || opcode < 0x80)
+ {
+ /* First MQ segment (opcodes below 0x80 never span several TSH) */
+ gint iSizeAPI = 16;
+ if (opcode >= 0x80 && opcode <= 0x9F && tvb_length_remaining(tvb, offset) >= 16)
+ {
+ guint32 iReturnCode = 0;
+ iReturnCode = tvb_get_guint32_endian(tvb, offset + 8, bLittleEndian);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (iReturnCode != 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [RC=%d]", iReturnCode);
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeAPI, MQ_TEXT_API);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_api);
+
+ proto_tree_add_item(mq_tree, hf_mq_api_replylength, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_api_completioncode, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_api_reasoncode, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_api_objecthandle, tvb, offset + 12, 4, bLittleEndian);
+ }
+ offset += iSizeAPI;
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+ if ((structId == MQ_STRUCTID_MSH || structId == MQ_STRUCTID_MSH_EBCDIC) && tvb_length_remaining(tvb, offset) >= 20)
+ {
+ gint iSizeMSH = 20;
+ iSizePayload = tvb_get_guint32_endian(tvb, offset + 16, bLittleEndian);
+ bPayload = TRUE;
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeMSH, MQ_TEXT_MSH);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_msh);
+
+ proto_tree_add_item(mq_tree, hf_mq_msh_structid, tvb, offset + 0, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_msh_seqnum, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_msh_datalength, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_msh_unknown1, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_msh_msglength, tvb, offset + 16, 4, bLittleEndian);
+ }
+ offset += iSizeMSH;
+ }
+ else if (opcode == MQ_TST_STATUS && tvb_length_remaining(tvb, offset) >= 8)
+ {
+ /* Some status are 28 bytes long and some are 36 bytes long */
+ guint32 iStatus = 0;
+ gint iStatusLength = 0;
+ iStatus = tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian);
+ iStatusLength = tvb_get_guint32_endian(tvb, offset, bLittleEndian);
+
+ if (tvb_length_remaining(tvb, offset) >= iStatusLength)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (iStatus != 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": Code=%s", val_to_str(iStatus, mq_status_vals, "Unknown (0x%08x)"));
+ }
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, 8, MQ_TEXT_STAT);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_status);
+
+ proto_tree_add_item(mq_tree, hf_mq_status_length, tvb, offset, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_status_code, tvb, offset + 4, 4, bLittleEndian);
+
+ if (iStatusLength >= 12)
+ proto_tree_add_item(mq_tree, hf_mq_status_value, tvb, offset + 8, 4, bLittleEndian);
+ }
+ offset += iStatusLength;
+ }
+ }
+ else if (opcode == MQ_TST_PING && tvb_length_remaining(tvb, offset) > 4)
+ {
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, -1, MQ_TEXT_PING);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_ping);
+
+ proto_tree_add_item(mq_tree, hf_mq_ping_length, tvb, offset, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_ping_buffer, tvb, offset + 4, -1, FALSE);
+ }
+ offset = tvb_length(tvb);
+ }
+ else if (opcode == MQ_TST_RESET && tvb_length_remaining(tvb, offset) >= 8)
+ {
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, -1, MQ_TEXT_RESET);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_reset);
+
+ proto_tree_add_item(mq_tree, hf_mq_reset_length, tvb, offset, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_reset_seqnum, tvb, offset + 4, 4, bLittleEndian);
+ }
+ offset = tvb_length(tvb);
+ }
+ else if (opcode == MQ_TST_MQCONN && tvb_length_remaining(tvb, offset) > 0)
+ {
+ gint iSizeCONN = 0;
+ /*iSizeCONN = ((iVersionID == 4 || iVersionID == 6) ? 120 : 112);*/ /* guess */
+ /* The iVersionID is available in the previous ID segment, we should keep a state
+ * Instead we rely on the segment length announced in the TSH */
+ /* The MQCONN structure is special because it does not start with a structid */
+ iSizeCONN = iSegmentLength - iSizeTSH - iSizeAPI;
+ if (iSizeCONN != 112 && iSizeCONN != 120) iSizeCONN = 0;
+
+ if (iSizeCONN != 0 && tvb_length_remaining(tvb, offset) >= iSizeCONN)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ guint8* sApplicationName;
+ guint8* sQueueManager;
+ sApplicationName = tvb_get_string(tvb, offset + 48, 28);
+ if (strip_trailing_blanks(sApplicationName, 28) != 0)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": App=%s", sApplicationName);
+ }
+ g_free(sApplicationName);
+ sQueueManager = tvb_get_string(tvb, offset, 48);
+ if (strip_trailing_blanks(sQueueManager, 48) != 0)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " QM=%s", sQueueManager);
+ }
+ g_free(sQueueManager);
+ }
+
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeCONN, MQ_TEXT_CONN);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_conn);
+
+ proto_tree_add_item(mq_tree, hf_mq_conn_queuemanager, tvb, offset, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_conn_appname, tvb, offset + 48, 28, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_conn_apptype, tvb, offset + 76, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_conn_acttoken, tvb, offset + 80, 32, FALSE);
+
+ if (iSizeCONN >= 120)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_conn_version, tvb, offset + 112, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_conn_options, tvb, offset + 116, 4, bLittleEndian);
+ }
+ }
+ offset += iSizeCONN;
+ }
+ }
+ else if ((opcode == MQ_TST_MQINQ || opcode == MQ_TST_MQINQ_REPLY || opcode == MQ_TST_MQSET) && tvb_length_remaining(tvb, offset) >= 12)
+ {
+ /* The MQINQ/MQSET structure is special because it does not start with a structid */
+ gint iNbSelectors = 0;
+ gint iNbIntegers = 0;
+ gint iCharLen = 0;
+ gint iOffsetINQ = 0;
+ gint iSelector = 0;
+
+ iNbSelectors = tvb_get_guint32_endian(tvb, offset, bLittleEndian);
+ iNbIntegers = tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian);
+ iCharLen = tvb_get_guint32_endian(tvb, offset + 8, bLittleEndian);
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, -1, MQ_TEXT_INQ);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_inq);
+
+ proto_tree_add_item(mq_tree, hf_mq_inq_nbsel, tvb, offset, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_inq_nbint, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_inq_charlen, tvb, offset + 8, 4, bLittleEndian);
+ }
+ iOffsetINQ = 12;
+ if (tvb_length_remaining(tvb, offset + iOffsetINQ) >= iNbSelectors * 4)
+ {
+ if (tree)
+ {
+ for (iSelector = 0; iSelector < iNbSelectors; iSelector++)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_inq_sel, tvb, offset + iOffsetINQ + iSelector * 4, 4, bLittleEndian);
+ }
+ }
+ iOffsetINQ += iNbSelectors * 4;
+ if (opcode == MQ_TST_MQINQ_REPLY || opcode == MQ_TST_MQSET)
+ {
+ gint iSizeINQValues = 0;
+ iSizeINQValues = iNbIntegers * 4 + iCharLen;
+ if (tvb_length_remaining(tvb, offset + iOffsetINQ) >= iSizeINQValues)
+ {
+ gint iInteger = 0;
+ if (tree)
+ {
+ for (iInteger = 0; iInteger < iNbIntegers; iInteger++)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_inq_intvalue, tvb, offset + iOffsetINQ + iInteger * 4, 4, bLittleEndian);
+ }
+ }
+ iOffsetINQ += iNbIntegers * 4;
+ if (iCharLen != 0)
+ {
+ if (tree)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_inq_charvalues, tvb, offset + iOffsetINQ, iCharLen, FALSE);
+ }
+ }
+ }
+ }
+ }
+ offset += tvb_length(tvb);
+ }
+ else if ((opcode == MQ_TST_SPI || opcode == MQ_TST_SPI_REPLY) && tvb_length_remaining(tvb, offset) >= 12)
+ {
+ gint iOffsetSPI = 0;
+ guint32 iSpiVerb = 0;
+
+ iSpiVerb = tvb_get_guint32_endian(tvb, offset, bLittleEndian);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str(iSpiVerb, mq_spi_verbs_vals, "Unknown (0x%08x)"));
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, 12, MQ_TEXT_SPI);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_spi);
+
+ proto_tree_add_item(mq_tree, hf_mq_spi_verb, tvb, offset, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_length, tvb, offset + 8, 4, bLittleEndian);
+ }
+
+ offset += 12;
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ if ((structId == MQ_STRUCTID_SPQU || structId == MQ_STRUCTID_SPAU_EBCDIC
+ || structId == MQ_STRUCTID_SPPU || structId == MQ_STRUCTID_SPPU_EBCDIC
+ || structId == MQ_STRUCTID_SPGU || structId == MQ_STRUCTID_SPGU_EBCDIC
+ || structId == MQ_STRUCTID_SPAU || structId == MQ_STRUCTID_SPAU_EBCDIC)
+ && tvb_length_remaining(tvb, offset) >= 12)
+ {
+ gint iSizeSPIMD = 0;
+ if (tree)
+ {
+ guint8* sStructId;
+ sStructId = tvb_get_string(tvb, offset, 4);
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, 12, (const char*)sStructId);
+ g_free(sStructId);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_spi_base);
+
+ proto_tree_add_item(mq_tree, hf_mq_spi_base_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_spi_base_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_base_length, tvb, offset + 8, 4, bLittleEndian);
+ }
+ offset += 12;
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+
+ if ((iSizeSPIMD = dissect_mq_md(tvb, mqroot_tree, bLittleEndian, offset, &tMsgProps)) != 0)
+ {
+ gint iSizeGMO = 0;
+ gint iSizePMO = 0;
+ offset += iSizeSPIMD;
+
+ if ((iSizeGMO = dissect_mq_gmo(tvb, pinfo, mqroot_tree, bLittleEndian, offset)) != 0)
+ {
+ offset += iSizeGMO;
+ }
+ else if ((iSizePMO = dissect_mq_pmo(tvb, pinfo, mqroot_tree, bLittleEndian, offset, &iDistributionListSize)) != 0)
+ {
+ offset += iSizePMO;
+ }
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+
+ if ((structId == MQ_STRUCTID_SPQO || structId == MQ_STRUCTID_SPQO_EBCDIC
+ || structId == MQ_STRUCTID_SPQI || structId == MQ_STRUCTID_SPQI_EBCDIC
+ || structId == MQ_STRUCTID_SPPO || structId == MQ_STRUCTID_SPPO_EBCDIC
+ || structId == MQ_STRUCTID_SPPI || structId == MQ_STRUCTID_SPPI_EBCDIC
+ || structId == MQ_STRUCTID_SPGO || structId == MQ_STRUCTID_SPGO_EBCDIC
+ || structId == MQ_STRUCTID_SPGI || structId == MQ_STRUCTID_SPGI_EBCDIC
+ || structId == MQ_STRUCTID_SPAO || structId == MQ_STRUCTID_SPAO_EBCDIC
+ || structId == MQ_STRUCTID_SPAI || structId == MQ_STRUCTID_SPAI_EBCDIC)
+ && tvb_length_remaining(tvb, offset) >= 12)
+ {
+ if (tree)
+ {
+ /* Dissect the common part of these structures */
+ guint8* sStructId;
+ sStructId = tvb_get_string(tvb, offset, 4);
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, -1, (const char*)sStructId);
+ g_free(sStructId);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_spi_base);
+
+ proto_tree_add_item(mq_tree, hf_mq_spi_base_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_spi_base_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_base_length, tvb, offset + 8, 4, bLittleEndian);
+ }
+
+ if (structId == MQ_STRUCTID_SPQO && tvb_length_remaining(tvb, offset) >= 16)
+ {
+ if (tree)
+ {
+ gint iVerbNumber = 0;
+ proto_tree_add_item(mq_tree, hf_mq_spi_spqo_nbverb, tvb, offset + 12, 4, bLittleEndian);
+ iVerbNumber = tvb_get_guint32_endian(tvb, offset + 12, bLittleEndian);
+
+ if (tvb_length_remaining(tvb, offset) >= iVerbNumber * 20 + 16)
+ {
+ gint iVerb = 0;
+ iOffsetSPI = offset + 16;
+ for (iVerb = 0; iVerb < iVerbNumber; iVerb++)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_spi_spqo_verbid, tvb, iOffsetSPI, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_spqo_maxinoutversion, tvb, iOffsetSPI + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_spqo_maxinversion, tvb, iOffsetSPI + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_spqo_maxoutversion, tvb, iOffsetSPI + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_spqo_flags, tvb, iOffsetSPI + 16, 4, bLittleEndian);
+ iOffsetSPI += 20;
+ }
+ offset += iVerbNumber * 20 + 16;
+ }
+ }
+ }
+ else if (structId == MQ_STRUCTID_SPAI && tvb_length_remaining(tvb, offset) >= 136)
+ {
+ if (tree)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_spi_spai_mode, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_spai_unknown1, tvb, offset + 16, 48, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_spai_unknown2, tvb, offset + 64, 48, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_spai_msgid, tvb, offset + 112, 24, bLittleEndian);
+ }
+ offset += 136;
+ }
+ else if (structId == MQ_STRUCTID_SPGI && tvb_length_remaining(tvb, offset) >= 24)
+ {
+ if (tree)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_spi_spgi_batchsize, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_spgi_batchint, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_spi_spgi_maxmsgsize, tvb, offset + 20, 4, bLittleEndian);
+ }
+ offset += 24;
+ }
+ else if ((structId == MQ_STRUCTID_SPGO || structId == MQ_STRUCTID_SPPI) && tvb_length_remaining(tvb, offset) >= 20)
+ {
+ if (tree)
+ {
+ /* Options flags */
+ {
+ proto_tree *mq_tree_sub = NULL;
+ gint iOptionsFlags;
+
+ ti = proto_tree_add_item(mq_tree, hf_mq_spi_spgo_options, tvb, offset + 12, 4, bLittleEndian);
+ mq_tree_sub = proto_item_add_subtree(ti, ett_mq_spi_options);
+ iOptionsFlags = tvb_get_guint32_endian(tvb, offset + 12, bLittleEndian);
+
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_spi_options_deferred, tvb, offset + 12, 4, iOptionsFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_spi_options_syncpoint, tvb, offset + 12, 4, iOptionsFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_spi_options_blank, tvb, offset + 12, 4, iOptionsFlags);
+ }
+ proto_tree_add_item(mq_tree, hf_mq_spi_spgo_size, tvb, offset + 16, 4, bLittleEndian);
+ }
+ iSizePayload = tvb_get_guint32_endian(tvb, offset + 16, bLittleEndian);
+ offset += 20;
+ bPayload = TRUE;
+ }
+ else
+ {
+ offset += 12;
+ }
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+ }
+ }
+ else if ((opcode >= 0xA0 && opcode <= 0xB9) && tvb_length_remaining(tvb, offset) >= 16)
+ {
+ /* The XA structures are special because they do not start with a structid */
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, 16, "%s (%s)", MQ_TEXT_XA, val_to_str(opcode, mq_opcode_vals, "Unknown (0x%02x)"));
+ mq_tree = proto_item_add_subtree(ti, ett_mq_xa);
+
+ proto_tree_add_item(mq_tree, hf_mq_xa_length, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_xa_returnvalue, tvb, offset + 4, 4, bLittleEndian);
+
+ /* Transaction Manager flags */
+ {
+ proto_tree *mq_tree_sub = NULL;
+ guint32 iTMFlags;
+
+ ti = proto_tree_add_item(mq_tree, hf_mq_xa_tmflags, tvb, offset + 8, 4, bLittleEndian);
+ mq_tree_sub = proto_item_add_subtree(ti, ett_mq_xa_tmflags);
+ iTMFlags = tvb_get_guint32_endian(tvb, offset + 8, bLittleEndian);
+
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_xa_tmflags_onephase, tvb, offset + 8, 4, iTMFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_xa_tmflags_fail, tvb, offset + 8, 4, iTMFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_xa_tmflags_resume, tvb, offset + 8, 4, iTMFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_xa_tmflags_success, tvb, offset + 8, 4, iTMFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_xa_tmflags_suspend, tvb, offset + 8, 4, iTMFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_xa_tmflags_startrscan, tvb, offset + 8, 4, iTMFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_xa_tmflags_endrscan, tvb, offset + 8, 4, iTMFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_xa_tmflags_join, tvb, offset + 8, 4, iTMFlags);
+ }
+
+ proto_tree_add_item(mq_tree, hf_mq_xa_rmid, tvb, offset + 12, 4, bLittleEndian);
+ }
+ offset += 16;
+ if (opcode == MQ_TST_XA_START || opcode == MQ_TST_XA_END || opcode == MQ_TST_XA_PREPARE
+ || opcode == MQ_TST_XA_COMMIT || opcode == MQ_TST_XA_ROLLBACK || opcode == MQ_TST_XA_FORGET
+ || opcode == MQ_TST_XA_COMPLETE)
+ {
+ gint iSizeXid = 0;
+ if ((iSizeXid = dissect_mq_xid(tvb, mqroot_tree, bLittleEndian, offset)) != 0)
+ offset += iSizeXid;
+ }
+ else if ((opcode == MQ_TST_XA_OPEN || opcode == MQ_TST_XA_CLOSE)
+ && tvb_length_remaining(tvb, offset) >= 1)
+ {
+ guint8 iXAInfoLength = 0;
+ iXAInfoLength = tvb_get_guint8(tvb, offset);
+ if (tvb_length_remaining(tvb, offset) >= iXAInfoLength + 1)
+ {
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iXAInfoLength + 1, MQ_TEXT_XINF);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_xa_info);
+
+ proto_tree_add_item(mq_tree, hf_mq_xa_xainfo_length, tvb, offset, 1, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_xa_xainfo_value, tvb, offset + 1, iXAInfoLength, FALSE);
+ }
+ }
+ offset += 1 + iXAInfoLength;
+ }
+ else if ((opcode == MQ_TST_XA_RECOVER || opcode == MQ_TST_XA_RECOVER_REPLY)
+ && tvb_length_remaining(tvb, offset) >= 4)
+ {
+ gint iNbXid = 0;
+ iNbXid = tvb_get_guint32_endian(tvb, offset, bLittleEndian);
+ if (tree)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_xa_count, tvb, offset, 4, bLittleEndian);
+ }
+ offset += 4;
+ if (opcode == MQ_TST_XA_RECOVER_REPLY)
+ {
+ gint iXid = 0;
+ for (iXid = 0; iXid < iNbXid; iXid++)
+ {
+ gint iSizeXid = 0;
+ if ((iSizeXid = dissect_mq_xid(tvb, mqroot_tree, bLittleEndian, offset)) != 0)
+ offset += iSizeXid;
+ else
+ break;
+ }
+ }
+ }
+ }
+ else if ((structId == MQ_STRUCTID_ID || structId == MQ_STRUCTID_ID_EBCDIC) && tvb_length_remaining(tvb, offset) >= 5)
+ {
+ guint8 iVersionID = 0;
+ gint iSizeID = 0;
+ iVersionID = tvb_get_guint8(tvb, offset + 4);
+ iSizeID = (iVersionID < 4 ? 44 : 104); /* guess */
+ /* actually 102 but must be aligned to multiple of 4 */
+
+ if (iSizeID != 0 && tvb_length_remaining(tvb, offset) >= iSizeID)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ guint8* sChannel;
+ sChannel = tvb_get_string(tvb, offset + 24, 20);
+ if (strip_trailing_blanks(sChannel, 20) != 0)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": CHL=%s", sChannel);
+ }
+ g_free(sChannel);
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeID, MQ_TEXT_ID);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_id);
+
+ proto_tree_add_item(mq_tree, hf_mq_id_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_id_level, tvb, offset + 4, 1, FALSE);
+
+ /* ID flags */
+ {
+ proto_tree *mq_tree_sub = NULL;
+ guint8 iIDFlags;
+
+ ti = proto_tree_add_item(mq_tree, hf_mq_id_flags, tvb, offset + 5, 1, FALSE);
+ mq_tree_sub = proto_item_add_subtree(ti, ett_mq_id_icf);
+ iIDFlags = tvb_get_guint8(tvb, offset + 5);
+
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_icf_runtime, tvb, offset + 5, 1, iIDFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_icf_svrsec, tvb, offset + 5, 1, iIDFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_icf_mqreq, tvb, offset + 5, 1, iIDFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_icf_splitmsg, tvb, offset + 5, 1, iIDFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_icf_convcap, tvb, offset + 5, 1, iIDFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_icf_msgseq, tvb, offset + 5, 1, iIDFlags);
+ }
+
+ proto_tree_add_item(mq_tree, hf_mq_id_unknown2, tvb, offset + 6, 1, FALSE);
+
+ /* Error flags */
+ {
+ proto_tree *mq_tree_sub = NULL;
+ guint8 iErrorFlags;
+
+ ti = proto_tree_add_item(mq_tree, hf_mq_id_ieflags, tvb, offset + 7, 1, FALSE);
+ mq_tree_sub = proto_item_add_subtree(ti, ett_mq_id_ief);
+ iErrorFlags = tvb_get_guint8(tvb, offset + 7);
+
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_ief_hbint, tvb, offset + 7, 1, iErrorFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_ief_seqwrap, tvb, offset + 7, 1, iErrorFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_ief_mxmsgpb, tvb, offset + 7, 1, iErrorFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_ief_mxmsgsz, tvb, offset + 7, 1, iErrorFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_ief_fap, tvb, offset + 7, 1, iErrorFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_ief_mxtrsz, tvb, offset + 7, 1, iErrorFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_ief_enc, tvb, offset + 7, 1, iErrorFlags);
+ proto_tree_add_boolean(mq_tree_sub, hf_mq_id_ief_ccsid, tvb, offset + 7, 1, iErrorFlags);
+ }
+
+ proto_tree_add_item(mq_tree, hf_mq_id_unknown4, tvb, offset + 8, 2, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_id_maxmsgperbatch, tvb, offset + 10, 2, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_id_maxtransmissionsize, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_id_maxmsgsize, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_id_sequencewrapvalue, tvb, offset + 20, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_id_channel, tvb, offset + 24, 20, FALSE);
+ }
+
+ if (iVersionID >= 4)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ guint8* sQueueManager;
+ sQueueManager = tvb_get_string(tvb, offset + 48, 48);
+ if (strip_trailing_blanks(sQueueManager,48) != 0)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " QM=%s", sQueueManager);
+ }
+ g_free(sQueueManager);
+ }
+
+ if (tree)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_id_capflags, tvb, offset + 44, 1, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_id_unknown5, tvb, offset + 45, 1, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_id_ccsid, tvb, offset + 46, 2, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_id_queuemanager, tvb, offset + 48, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_id_heartbeatinterval, tvb, offset + 96, 4, bLittleEndian);
+ }
+
+ }
+ offset += iSizeID;
+ }
+ }
+ else if ((structId == MQ_STRUCTID_UID || structId == MQ_STRUCTID_UID_EBCDIC) && tvb_length_remaining(tvb, offset) > 0)
+ {
+ gint iSizeUID = 0;
+ /* iSizeUID = (iVersionID < 5 ? 28 : 132); guess */
+ /* The iVersionID is available in the previous ID segment, we should keep a state *
+ * Instead we rely on the segment length announced in the TSH */
+ iSizeUID = iSegmentLength - iSizeTSH;
+ if (iSizeUID != 28 && iSizeUID != 132) iSizeUID = 0;
+
+ if (iSizeUID != 0 && tvb_length_remaining(tvb, offset) >= iSizeUID)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ guint8* sUserId;
+ sUserId = tvb_get_string(tvb, offset + 4, 12);
+ if (strip_trailing_blanks(sUserId, 12) != 0)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": User=%s", sUserId);
+ }
+ g_free(sUserId);
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeUID, MQ_TEXT_UID);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_uid);
+
+ proto_tree_add_item(mq_tree, hf_mq_uid_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_uid_userid, tvb, offset + 4, 12, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_uid_password, tvb, offset + 16, 12, FALSE);
+ }
+
+ if (iSizeUID == 132)
+ {
+ if (tree)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_uid_longuserid, tvb, offset + 28, 64, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_uid_securityid, tvb, offset + 92, 40, FALSE);
+ }
+ }
+ offset += iSizeUID;
+ }
+ }
+ if ((structId == MQ_STRUCTID_OD || structId == MQ_STRUCTID_OD_EBCDIC) && tvb_length_remaining(tvb, offset) >= 8)
+ {
+ /* The OD struct can be present in several messages at different levels */
+ gint iSizeOD = 0;
+ guint32 iVersionOD = 0;
+ iVersionOD = tvb_get_guint32_endian(tvb, offset + 4, bLittleEndian);
+ /* Compute length according to version */
+ switch (iVersionOD)
+ {
+ case 1: iSizeOD = 168; break;
+ case 2: iSizeOD = 200; break;
+ case 3: iSizeOD = 336; break;
+ }
+
+ if (iSizeOD != 0 && tvb_length_remaining(tvb, offset) >= iSizeOD)
+ {
+ gint iNbrRecords = 0;
+ if (iVersionOD >= 2)
+ iNbrRecords = tvb_get_guint32_endian(tvb, offset + 168, bLittleEndian);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ guint8* sQueue;
+ sQueue = tvb_get_string(tvb, offset + 12, 48);
+ if (strip_trailing_blanks(sQueue,48) != 0)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Obj=%s", sQueue);
+ }
+ g_free(sQueue);
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeOD, MQ_TEXT_OD);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_od);
+
+ proto_tree_add_item(mq_tree, hf_mq_od_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_od_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_od_objecttype, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_od_objectname, tvb, offset + 12, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_od_objectqmgrname, tvb, offset + 60, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_od_dynamicqname, tvb, offset + 108, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_od_alternateuserid, tvb, offset + 156, 12, FALSE);
+
+ if (iVersionOD >= 2)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_od_recspresent, tvb, offset + 168, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_od_knowndestcount, tvb, offset + 172, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_od_unknowndestcount, tvb, offset + 176, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_od_invaliddestcount, tvb, offset + 180, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_od_objectrecoffset, tvb, offset + 184, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_od_responserecoffset, tvb, offset + 188, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_od_objectrecptr, tvb, offset + 192, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_od_responserecptr, tvb, offset + 196, 4, bLittleEndian);
+ }
+
+ if (iVersionOD >= 3)
+ {
+ proto_tree_add_item(mq_tree, hf_mq_od_alternatesecurityid, tvb, offset + 200, 40, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_od_resolvedqname, tvb, offset + 240, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_od_resolvedqmgrname, tvb, offset + 288, 48, FALSE);
+ }
+
+ }
+ offset += iSizeOD;
+
+ if (iNbrRecords > 0)
+ {
+ gint iOffsetOR = 0;
+ gint iOffsetRR = 0;
+ gint iSizeORRR = 0;
+
+ iDistributionListSize = iNbrRecords;
+ iOffsetOR = tvb_get_guint32_endian(tvb, offset - iSizeOD + 184, bLittleEndian);
+ iOffsetRR = tvb_get_guint32_endian(tvb, offset - iSizeOD + 188, bLittleEndian);
+ if ((iSizeORRR = dissect_mq_or(tvb, mqroot_tree, offset, iNbrRecords, iOffsetOR)) != 0)
+ offset += iSizeORRR;
+ if ((iSizeORRR = dissect_mq_rr(tvb, mqroot_tree, bLittleEndian, offset, iNbrRecords, iOffsetRR)) != 0)
+ offset += iSizeORRR;
+ }
+ }
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+ if ((opcode == MQ_TST_MQOPEN || opcode == MQ_TST_MQCLOSE
+ || opcode == MQ_TST_MQOPEN_REPLY || opcode == MQ_TST_MQCLOSE_REPLY)
+ && tvb_length_remaining(tvb, offset) >= 4)
+ {
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, 4, MQ_TEXT_OPEN);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_open);
+ proto_tree_add_item(mq_tree, hf_mq_open_options, tvb, offset, 4, bLittleEndian);
+ }
+ offset += 4;
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+ if ((iSizeMD = dissect_mq_md(tvb, mqroot_tree, bLittleEndian, offset, &tMsgProps)) != 0)
+ {
+ gint iSizeGMO = 0;
+ gint iSizePMO = 0;
+ offset += iSizeMD;
+
+ if ((iSizeGMO = dissect_mq_gmo(tvb, pinfo, mqroot_tree, bLittleEndian, offset)) != 0)
+ {
+ offset += iSizeGMO;
+ bPayload = TRUE;
+ }
+ else if ((iSizePMO = dissect_mq_pmo(tvb, pinfo, mqroot_tree, bLittleEndian, offset, &iDistributionListSize)) != 0)
+ {
+ offset += iSizePMO;
+ bPayload = TRUE;
+ }
+ if (tvb_length_remaining(tvb, offset) >= 4)
+ {
+ if (bPayload == TRUE)
+ {
+ iSizePayload = tvb_get_guint32_endian(tvb, offset, bLittleEndian);
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, 4, MQ_TEXT_PUT);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_put);
+ proto_tree_add_item(mq_tree, hf_mq_put_length, tvb, offset, 4, bLittleEndian);
+ }
+ offset += 4;
+ }
+ }
+ }
+ if (iDistributionListSize > 0)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (Distribution List, Size=%d)", iDistributionListSize);
+ }
+ if (bPayload == TRUE)
+ {
+ if (iSizePayload != 0 && tvb_length_remaining(tvb, offset) > 0)
+ {
+ /* For the following header structures, each structure has a "format" field
+ which announces the type of the following structure. For dissection we
+ do not use it and rely on the structid instead. */
+ guint32 iHeadersLength = 0;
+ if (tvb_length_remaining(tvb, offset) >= 4)
+ {
+ gint iSizeMD = 0;
+ structId = tvb_get_ntohl(tvb, offset);
+
+ if ((structId == MQ_STRUCTID_XQH || structId == MQ_STRUCTID_XQH_EBCDIC) && tvb_length_remaining(tvb, offset) >= 104)
+ {
+ /* if MD.format == MQXMIT */
+ gint iSizeXQH = 104;
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeXQH, MQ_TEXT_XQH);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_xqh);
+
+ proto_tree_add_item(mq_tree, hf_mq_xqh_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_xqh_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_xqh_remoteq, tvb, offset + 8, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_xqh_remoteqmgr, tvb, offset + 56, 48, FALSE);
+ }
+ offset += iSizeXQH;
+ iHeadersLength += iSizeXQH;
+
+ if ((iSizeMD = dissect_mq_md(tvb, mqroot_tree, bLittleEndian, offset, &tMsgProps)) != 0)
+ {
+ offset += iSizeMD;
+ iHeadersLength += iSizeMD;
+ }
+
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+ if ((structId == MQ_STRUCTID_DH || structId == MQ_STRUCTID_DH_EBCDIC) && tvb_length_remaining(tvb, offset) >= 48)
+ {
+ /* if MD.format == MQHDIST */
+ gint iSizeDH = 48;
+ gint iNbrRecords = 0;
+ guint32 iRecFlags = 0;
+
+ iNbrRecords = tvb_get_guint32_endian(tvb, offset + 36, bLittleEndian);
+ iRecFlags = tvb_get_guint32_endian(tvb, offset + 32, bLittleEndian);
+ tMsgProps.iOffsetEncoding = offset + 12;
+ tMsgProps.iOffsetCcsid = offset + 16;
+ tMsgProps.iOffsetFormat = offset + 20;
+
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeDH, MQ_TEXT_DH);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_dh);
+
+ proto_tree_add_item(mq_tree, hf_mq_head_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_head_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_length, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_encoding, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_ccsid, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_format, tvb, offset + 20, 8, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_head_flags, tvb, offset + 28, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_dh_putmsgrecfields, tvb, offset + 32, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_dh_recspresent, tvb, offset + 36, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_dh_objectrecoffset , tvb, offset + 40, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_dh_putmsgrecoffset, tvb, offset + 44, 4, bLittleEndian);
+ }
+ offset += iSizeDH;
+ iHeadersLength += iSizeDH;
+
+ if (iNbrRecords > 0)
+ {
+ gint iOffsetOR = 0;
+ gint iOffsetPMR = 0;
+ gint iSizeORPMR = 0;
+
+ iOffsetOR = tvb_get_guint32_endian(tvb, offset - iSizeDH + 40, bLittleEndian);
+ iOffsetPMR = tvb_get_guint32_endian(tvb, offset - iSizeDH + 44, bLittleEndian);
+ if ((iSizeORPMR = dissect_mq_or(tvb, mqroot_tree, offset, iNbrRecords, iOffsetOR)) != 0)
+ {
+ offset += iSizeORPMR;
+ iHeadersLength += iSizeORPMR;
+ }
+ if ((iSizeORPMR = dissect_mq_pmr(tvb, mqroot_tree, bLittleEndian, offset, iNbrRecords, iOffsetPMR, iRecFlags)) != 0)
+ {
+ offset += iSizeORPMR;
+ iHeadersLength += iSizeORPMR;
+ }
+ }
+
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+ if ((structId == MQ_STRUCTID_DLH || structId == MQ_STRUCTID_DLH_EBCDIC) && tvb_length_remaining(tvb, offset) >= 172)
+ {
+ /* if MD.format == MQDEAD */
+ gint iSizeDLH = 172;
+ tMsgProps.iOffsetEncoding = offset + 108;
+ tMsgProps.iOffsetCcsid = offset + 112;
+ tMsgProps.iOffsetFormat = offset + 116;
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeDLH, MQ_TEXT_DLH);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_dlh);
+
+ proto_tree_add_item(mq_tree, hf_mq_dlh_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_reason, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_destq, tvb, offset + 12, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_destqmgr, tvb, offset + 60, 48, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_encoding, tvb, offset + 108, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_ccsid, tvb, offset + 112, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_format, tvb, offset + 116, 8, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_putappltype, tvb, offset + 124, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_putapplname, tvb, offset + 128, 28, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_putdate, tvb, offset + 156, 8, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_dlh_puttime, tvb, offset + 164, 8, FALSE);
+ }
+ offset += iSizeDLH;
+ iHeadersLength += iSizeDLH;
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+ if ((structId == MQ_STRUCTID_MDE || structId == MQ_STRUCTID_MDE_EBCDIC) && tvb_length_remaining(tvb, offset) >= 72)
+ {
+ /* if MD.format == MQHMDE */
+ gint iSizeMDE = 72;
+ tMsgProps.iOffsetEncoding = offset + 12;
+ tMsgProps.iOffsetCcsid = offset + 16;
+ tMsgProps.iOffsetFormat = offset + 20;
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeMDE, MQ_TEXT_MDE);
+ mq_tree = proto_item_add_subtree(ti, ett_mq_mde);
+
+ proto_tree_add_item(mq_tree, hf_mq_head_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_head_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_length, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_encoding, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_ccsid, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_format, tvb, offset + 20, 8, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_head_flags, tvb, offset + 28, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_groupid, tvb, offset + 32, 24, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_md_msgseqnumber, tvb, offset + 56, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_offset, tvb, offset + 60, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_msgflags, tvb, offset + 64, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_md_originallength, tvb, offset + 68, 4, bLittleEndian);
+ }
+ offset += iSizeMDE;
+ iHeadersLength += iSizeMDE;
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+ if ((structId == MQ_STRUCTID_CIH || structId == MQ_STRUCTID_CIH_EBCDIC
+ || structId == MQ_STRUCTID_IIH || structId == MQ_STRUCTID_IIH_EBCDIC
+ || structId == MQ_STRUCTID_RFH || structId == MQ_STRUCTID_RFH_EBCDIC
+ || structId == MQ_STRUCTID_RMH || structId == MQ_STRUCTID_RMH_EBCDIC
+ || structId == MQ_STRUCTID_WIH || structId == MQ_STRUCTID_WIH_EBCDIC)
+ && tvb_length_remaining(tvb, offset) >= 12)
+ {
+ /* Dissect the generic part of the other pre-defined headers */
+ /* We assume that only one such header is present */
+ gint iSizeHeader = 0;
+ iSizeHeader = tvb_get_guint32_endian(tvb, offset + 8, bLittleEndian);
+
+ if (tvb_length_remaining(tvb, offset) >= iSizeHeader)
+ {
+ tMsgProps.iOffsetEncoding = offset + 12;
+ tMsgProps.iOffsetCcsid = offset + 16;
+ tMsgProps.iOffsetFormat = offset + 20;
+ if (tree)
+ {
+ ti = proto_tree_add_text(mqroot_tree, tvb, offset, iSizeHeader, val_to_str(structId, mq_structid_vals, "Unknown (0x%08x)"));
+ mq_tree = proto_item_add_subtree(ti, ett_mq_head);
+
+ proto_tree_add_item(mq_tree, hf_mq_head_structid, tvb, offset, 4, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_head_version, tvb, offset + 4, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_length, tvb, offset + 8, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_encoding, tvb, offset + 12, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_ccsid, tvb, offset + 16, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_format, tvb, offset + 20, 8, FALSE);
+ proto_tree_add_item(mq_tree, hf_mq_head_flags, tvb, offset + 28, 4, bLittleEndian);
+ proto_tree_add_item(mq_tree, hf_mq_head_struct, tvb, offset + 32, iSizeHeader - 32, bLittleEndian);
+
+ }
+ offset += iSizeHeader;
+ iHeadersLength += iSizeHeader;
+ structId = (tvb_length_remaining(tvb, offset) >= 4) ? tvb_get_ntohl(tvb, offset) : MQ_STRUCTID_NULL;
+ }
+ }
+ }
+
+ if (tMsgProps.iOffsetFormat != 0)
+ {
+ guint8* sFormat = NULL;
+ sFormat = tvb_get_string(tvb, tMsgProps.iOffsetFormat, 8);
+ if (strip_trailing_blanks(sFormat, 8) == 0) sFormat = (guint8*)"MQNONE";
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Fmt=%s", sFormat);
+ }
+ if (tree)
+ {
+ proto_tree_add_string_hidden(tree, hf_mq_md_hidden_lastformat, tvb, tMsgProps.iOffsetFormat, 8, (const char*)sFormat);
+ }
+ g_free(sFormat);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%d bytes)", iSizePayload - iHeadersLength);
+ }
+
+ {
+ /* Call subdissector for the payload */
+ tvbuff_t* next_tvb = NULL;
+ struct mqinfo mqinfo;
+ /* Format, encoding and character set are "data type" information, not subprotocol information */
+ mqinfo.encoding = tvb_get_guint32_endian(tvb, tMsgProps.iOffsetEncoding, bLittleEndian);
+ mqinfo.ccsid = tvb_get_guint32_endian(tvb, tMsgProps.iOffsetCcsid, bLittleEndian);
+ tvb_memcpy(tvb, mqinfo.format, tMsgProps.iOffsetFormat, 8);
+ pinfo->private_data = &mqinfo;
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (!dissector_try_heuristic(mq_heur_subdissector_list, next_tvb, pinfo, tree))
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ }
+ offset = tvb_length(tvb);
+ }
+ /* After all recognised structures have been dissected, process remaining structure*/
+ if (tvb_length_remaining(tvb, offset) >= 4)
+ {
+ structId = tvb_get_ntohl(tvb, offset);
+ if (tree)
+ {
+ proto_tree_add_text(mqroot_tree, tvb, offset, -1, val_to_str(structId, mq_structid_vals, "Unknown (0x%08x)"));
+ }
+ }
+ }
+ else
+ {
+ /* This is a MQ segment continuation (if MQ reassembly is not enabled) */
+ if (check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, " [Unreassembled MQ]");
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+ }
+ }
+ else
+ {
+ /* This packet is a TCP continuation of a segment (if desegmentation is not enabled) */
+ if (check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, " [Undesegmented]");
+ if (tree)
+ {
+ proto_tree_add_item(tree, proto_mq, tvb, offset, -1, FALSE);
+ }
+ call_dissector(data_handle, tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+ }
+}
+
+
+static void
+reassemble_mq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Reassembly of the MQ messages that span several PDU (several TSH) */
+ /* Typically a TCP PDU is 1460 bytes and a MQ PDU is 32766 bytes */
+ if (tvb_length(tvb) >= 28)
+ {
+ guint32 structId;
+ structId = tvb_get_ntohl(tvb, 0);
+
+ if (structId == MQ_STRUCTID_TSH || structId == MQ_STRUCTID_TSH_EBCDIC)
+ {
+ guint8 iControlFlags = 0;
+ guint32 iSegmentLength = 0;
+ guint32 iBeginLength = 0;
+ guint8 opcode;
+ gboolean bFirstSegment;
+ gboolean bLastSegment;
+ opcode = tvb_get_guint8(tvb, 9);
+ iControlFlags = tvb_get_guint8(tvb, 10);
+ iSegmentLength = tvb_get_ntohl(tvb, 4);
+ bFirstSegment = ((iControlFlags & MQ_TCF_FIRST) != 0);
+ bLastSegment = ((iControlFlags & MQ_TCF_LAST) != 0);
+
+ if (opcode > 0x80 && !(bFirstSegment && bLastSegment))
+ {
+ /* Optimisation : only fragmented segments go through the reassembly process */
+ if (mq_reassembly)
+ {
+ tvbuff_t* next_tvb;
+ fragment_data* fd_head;
+ guint32 iConnectionId = (pinfo->srcport + pinfo->destport);
+ if (opcode > 0x80 && !bFirstSegment) iBeginLength = 28;
+ fd_head = fragment_add_seq_next(tvb, iBeginLength, pinfo, iConnectionId, mq_fragment_table, mq_reassembled_table, iSegmentLength - iBeginLength, !bLastSegment);
+ if (fd_head != NULL && pinfo->fd->num == fd_head->reassembled_in)
+ {
+ /* Reassembly finished */
+ if (fd_head->next != NULL)
+ {
+ /* 2 or more fragments */
+ next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb, "Reassembled MQ");
+ }
+ else
+ {
+ /* Only 1 fragment */
+ next_tvb = tvb;
+ }
+ dissect_mq_pdu(next_tvb, pinfo, tree);
+ return;
+ }
+ else
+ {
+ /* Reassembly in progress */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "MQ");
+ if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "%s [Reassembled MQ]", val_to_str(opcode, mq_opcode_vals, "Unknown (0x%02x)"));
+ if (tree)
+ {
+ proto_item* ti = NULL;
+ ti = proto_tree_add_item(tree, proto_mq, tvb, 0, -1, FALSE);
+ proto_item_append_text(ti, " (%s) [Reassembled MQ]", val_to_str(opcode, mq_opcode_vals, "Unknown (0x%02x)"));
+ }
+ return;
+ }
+ }
+ else
+ {
+ dissect_mq_pdu(tvb, pinfo, tree);
+ if (bFirstSegment)
+ {
+ /* MQ segment is the first of a unreassembled series */
+ if (check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, " [Unreassembled MQ]");
+ }
+ return;
+ }
+ }
+ /* Reassembly not enabled or non-fragmented message */
+ dissect_mq_pdu(tvb, pinfo, tree);
+ return;
+ }
+ }
+}
+
+static guint
+get_mq_pdu_len(tvbuff_t *tvb, int offset)
+{
+ if (tvb_length_remaining(tvb, offset) >= 8)
+ {
+ if ((tvb_get_ntohl(tvb, 0) == MQ_STRUCTID_TSH || tvb_get_ntohl(tvb, 0) == MQ_STRUCTID_TSH_EBCDIC))
+ return tvb_get_ntohl(tvb, offset + 4);
+ }
+ return 0;
+}
+
+static void
+dissect_mq_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, mq_desegment, 28, get_mq_pdu_len, reassemble_mq);
+}
+
+static void
+dissect_mq_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Since SPX has no standard desegmentation, MQ cannot be performed as well */
+ dissect_mq_pdu(tvb, pinfo, tree);
+}
+
+static gboolean
+dissect_mq_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint iProto)
+{
+ if (tvb_length(tvb) >= 28)
+ {
+ guint32 structId;
+ guint8 cEndian;
+ structId = tvb_get_ntohl(tvb, 0);
+ cEndian = tvb_get_guint8(tvb, 8);
+
+ if ((structId == MQ_STRUCTID_TSH || structId == MQ_STRUCTID_TSH_EBCDIC)
+ && (cEndian == MQ_LITTLE_ENDIAN || cEndian == MQ_BIG_ENDIAN))
+ {
+ /* Register this dissector for this conversation */
+ conversation_t *conversation = NULL;
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL)
+ {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ if (iProto == MQ_XPT_TCP) conversation_set_dissector(conversation, mq_tcp_handle);
+
+ /* Dissect the packet */
+ reassemble_mq(tvb, pinfo, tree);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean
+dissect_mq_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_mq_heur(tvb, pinfo, tree, MQ_XPT_TCP);
+}
+
+static gboolean
+dissect_mq_heur_netbios(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_mq_heur(tvb, pinfo, tree, MQ_XPT_NETBIOS);
+}
+
+static gboolean
+dissect_mq_heur_http(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_mq_heur(tvb, pinfo, tree, MQ_XPT_HTTP);
+}
+
+static void
+mq_init(void)
+{
+ fragment_table_init(&mq_fragment_table);
+ reassembled_table_init(&mq_reassembled_table);
+}
+
+void
+proto_register_mq(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_mq_tsh_structid,
+ { "TSH structid", "mq.tsh.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "TSH structid", HFILL }},
+
+ { &hf_mq_tsh_packetlength,
+ { "MQ Segment length", "mq.tsh.seglength", FT_UINT32, BASE_DEC, NULL, 0x0, "TSH MQ Segment length", HFILL }},
+
+ { &hf_mq_tsh_byteorder,
+ { "Byte order", "mq.tsh.byteorder", FT_UINT8, BASE_HEX, VALS(mq_byteorder_vals), 0x0, "TSH Byte order", HFILL }},
+
+ { &hf_mq_tsh_opcode,
+ { "Segment type", "mq.tsh.type", FT_UINT8, BASE_HEX, VALS(mq_opcode_vals), 0x0, "TSH MQ segment type", HFILL }},
+
+ { &hf_mq_tsh_controlflags,
+ { "Control flags", "mq.tsh.cflags", FT_UINT8, BASE_HEX, NULL, 0x0, "TSH Control flags", HFILL }},
+
+ { &hf_mq_tsh_reserved,
+ { "Reserved", "mq.tsh.reserved", FT_UINT8, BASE_HEX, NULL, 0x0, "TSH Reserved", HFILL }},
+
+ { &hf_mq_tsh_luwid,
+ { "Logical unit of work identifier", "mq.tsh.luwid", FT_BYTES, BASE_HEX, NULL, 0x0, "TSH logical unit of work identifier", HFILL }},
+
+ { &hf_mq_tsh_encoding,
+ { "Encoding", "mq.tsh.encoding", FT_UINT32, BASE_DEC, NULL, 0x0, "TSH Encoding", HFILL }},
+
+ { &hf_mq_tsh_ccsid,
+ { "Character set", "mq.tsh.ccsid", FT_UINT16, BASE_DEC, NULL, 0x0, "TSH CCSID", HFILL }},
+
+ { &hf_mq_tsh_padding,
+ { "Padding", "mq.tsh.padding", FT_UINT16, BASE_HEX, NULL, 0x0, "TSH Padding", HFILL }},
+
+ { &hf_mq_tsh_tcf_confirmreq,
+ { "Confirm request", "mq.tsh.tcf.confirmreq", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_TCF_CONFIRM_REQUEST, "TSH TCF Confirm request", HFILL }},
+
+ { &hf_mq_tsh_tcf_error,
+ { "Error", "mq.tsh.tcf.error", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_TCF_ERROR, "TSH TCF Error", HFILL }},
+
+ { &hf_mq_tsh_tcf_reqclose,
+ { "Request close", "mq.tsh.tcf.reqclose", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_TCF_REQUEST_CLOSE, "TSH TCF Request close", HFILL }},
+
+ { &hf_mq_tsh_tcf_closechann,
+ { "Close channel", "mq.tsh.tcf.closechann", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_TCF_CLOSE_CHANNEL, "TSH TCF Close channel", HFILL }},
+
+ { &hf_mq_tsh_tcf_first,
+ { "First", "mq.tsh.tcf.first", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_TCF_FIRST, "TSH TCF First", HFILL }},
+
+ { &hf_mq_tsh_tcf_last,
+ { "Last", "mq.tsh.tcf.last", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_TCF_LAST, "TSH TCF Last", HFILL }},
+
+ { &hf_mq_tsh_tcf_reqacc,
+ { "Request accepted", "mq.tsh.tcf.reqacc", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_TCF_REQUEST_ACCEPTED, "TSH TCF Request accepted", HFILL }},
+
+ { &hf_mq_tsh_tcf_dlq,
+ { "DLQ used", "mq.tsh.tcf.dlq", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_TCF_DLQ_USED, "TSH TCF DLQ used", HFILL }},
+
+ { &hf_mq_api_replylength,
+ { "Reply length", "mq.api.replylength", FT_UINT32, BASE_DEC, NULL, 0x0, "API Reply length", HFILL }},
+
+ { &hf_mq_api_completioncode,
+ { "Completion code", "mq.api.completioncode", FT_UINT32, BASE_DEC, NULL, 0x0, "API Completion code", HFILL }},
+
+ { &hf_mq_api_reasoncode,
+ { "Reason code", "mq.api.reasoncode", FT_UINT32, BASE_DEC, NULL, 0x0, "API Reason code", HFILL }},
+
+ { &hf_mq_api_objecthandle,
+ { "Object handle", "mq.api.hobj", FT_UINT32, BASE_HEX, NULL, 0x0, "API Object handle", HFILL }},
+
+ { &hf_mq_id_icf_msgseq,
+ { "Message sequence", "mq.id.icf.msgseq", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_ICF_MSG_SEQ, "ID ICF Message sequence", HFILL }},
+
+ { &hf_mq_id_icf_convcap,
+ { "Conversion capable", "mq.id.icf.convcap", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_ICF_CONVERSION_CAPABLE, "ID ICF Conversion capable", HFILL }},
+
+ { &hf_mq_id_icf_splitmsg,
+ { "Split messages", "mq.id.icf.splitmsg", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_ICF_SPLIT_MESSAGE, "ID ICF Split message", HFILL }},
+
+ { &hf_mq_id_icf_mqreq,
+ { "MQ request", "mq.id.icf.mqreq", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_ICF_MQREQUEST, "ID ICF MQ request", HFILL }},
+
+ { &hf_mq_id_icf_svrsec,
+ { "Server connection security", "mq.id.icf.svrsec", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_ICF_SVRCONN_SECURITY, "ID ICF Server connection security", HFILL }},
+
+ { &hf_mq_id_icf_runtime,
+ { "Runtime application", "mq.id.icf.runtime", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_ICF_RUNTIME, "ID ICF Runtime application", HFILL }},
+
+ { &hf_mq_msh_structid,
+ { "MSH structid", "mq.msh.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MSH structid", HFILL }},
+
+ { &hf_mq_msh_seqnum,
+ { "Sequence number", "mq.msh.seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, "MSH sequence number", HFILL }},
+
+ { &hf_mq_msh_datalength,
+ { "Buffer length", "mq.msh.buflength", FT_UINT32, BASE_DEC, NULL, 0x0, "MSH buffer length", HFILL }},
+
+ { &hf_mq_msh_unknown1,
+ { "Unknown1", "mq.msh.unknown1", FT_UINT32, BASE_HEX, NULL, 0x0, "MSH unknown1", HFILL }},
+
+ { &hf_mq_msh_msglength,
+ { "Message length", "mq.msh.msglength", FT_UINT32, BASE_DEC, NULL, 0x0, "MSH message length", HFILL }},
+
+ { &hf_mq_xqh_structid,
+ { "XQH structid", "mq.xqh.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "XQH structid", HFILL }},
+
+ { &hf_mq_xqh_version,
+ { "Version", "mq.xqh.version", FT_UINT32, BASE_DEC, NULL, 0x0, "XQH version", HFILL }},
+
+ { &hf_mq_xqh_remoteq,
+ { "Remote queue", "mq.xqh.remoteq", FT_STRINGZ, BASE_DEC, NULL, 0x0, "XQH remote queue", HFILL }},
+
+ { &hf_mq_xqh_remoteqmgr,
+ { "Remote queue manager", "mq.xqh.remoteqmgr", FT_STRINGZ, BASE_DEC, NULL, 0x0, "XQH remote queue manager", HFILL }},
+
+ { &hf_mq_id_structid,
+ { "ID structid", "mq.id.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "ID structid", HFILL }},
+
+ { &hf_mq_id_level,
+ { "FAP level", "mq.id.level", FT_UINT8, BASE_DEC, NULL, 0x0, "ID Formats And Protocols level", HFILL }},
+
+ { &hf_mq_id_flags,
+ { "Flags", "mq.id.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "ID flags", HFILL }},
+
+ { &hf_mq_id_unknown2,
+ { "Unknown2", "mq.id.unknown2", FT_UINT8, BASE_HEX, NULL, 0x0, "ID unknown2", HFILL }},
+
+ { &hf_mq_id_ieflags,
+ { "Initial error flags", "mq.id.ief", FT_UINT8, BASE_HEX, NULL, 0x0, "ID initial error flags", HFILL }},
+
+ { &hf_mq_id_unknown4,
+ { "Unknown4", "mq.id.unknown4", FT_UINT16, BASE_HEX, NULL, 0x0, "ID unknown4", HFILL }},
+
+ { &hf_mq_id_maxmsgperbatch,
+ { "Maximum messages per batch", "mq.id.maxmsgperbatch", FT_UINT16, BASE_DEC, NULL, 0x0, "ID max msg per batch", HFILL }},
+
+ { &hf_mq_id_maxtransmissionsize,
+ { "Maximum transmission size", "mq.id.maxtranssize", FT_UINT32, BASE_DEC, NULL, 0x0, "ID max trans size", HFILL }},
+
+ { &hf_mq_id_maxmsgsize,
+ { "Maximum message size", "mq.id.maxmsgsize", FT_UINT32, BASE_DEC, NULL, 0x0, "ID max msg size", HFILL }},
+
+ { &hf_mq_id_sequencewrapvalue,
+ { "Sequence wrap value", "mq.id.seqwrap", FT_UINT32, BASE_DEC, NULL, 0x0, "ID seq wrap value", HFILL }},
+
+ { &hf_mq_id_channel,
+ { "Channel name", "mq.id.channelname", FT_STRINGZ, BASE_HEX, NULL, 0x0, "ID channel name", HFILL }},
+
+ { &hf_mq_id_capflags,
+ { "Capability flags", "mq.id.capflags", FT_UINT8, BASE_HEX, NULL, 0x0, "ID Capability flags", HFILL }},
+
+ { &hf_mq_id_unknown5,
+ { "Unknown5", "mq.id.unknown5", FT_UINT8, BASE_HEX, NULL, 0x0, "ID unknown5", HFILL }},
+
+ { &hf_mq_id_ccsid,
+ { "Character set", "mq.id.ccsid", FT_UINT16, BASE_DEC, NULL, 0x0, "ID character set", HFILL }},
+
+ { &hf_mq_id_queuemanager,
+ { "Queue manager", "mq.id.qm", FT_STRINGZ, BASE_HEX, NULL, 0x0, "ID Queue manager", HFILL }},
+
+ { &hf_mq_id_heartbeatinterval,
+ { "Heartbeat interval", "mq.id.hbint", FT_UINT32, BASE_DEC, NULL, 0x0, "ID Heartbeat interval", HFILL }},
+
+ { &hf_mq_id_unknown6,
+ { "Unknown6", "mq.id.unknown6", FT_UINT16, BASE_HEX, NULL, 0x0, "ID unknown6", HFILL }},
+
+ { &hf_mq_id_ief_ccsid,
+ { "Invalid CCSID", "mq.id.ief.ccsid", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_IEF_CCSID, "ID invalid CCSID", HFILL }},
+
+ { &hf_mq_id_ief_enc,
+ { "Invalid encoding", "mq.id.ief.enc", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_IEF_ENCODING, "ID invalid encoding", HFILL }},
+
+ { &hf_mq_id_ief_mxtrsz,
+ { "Invalid maximum transmission size", "mq.id.ief.mxtrsz", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_IEF_MAX_TRANSMISSION_SIZE, "ID invalid maximum transmission size", HFILL }},
+
+ { &hf_mq_id_ief_fap,
+ { "Invalid FAP level", "mq.id.ief.fap", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_IEF_FAP_LEVEL, "ID invalid FAP level", HFILL }},
+
+ { &hf_mq_id_ief_mxmsgsz,
+ { "Invalid message size", "mq.id.ief.mxmsgsz", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_IEF_MAX_MSG_SIZE, "ID invalid message size", HFILL }},
+
+ { &hf_mq_id_ief_mxmsgpb,
+ { "Invalid maximum message per batch", "mq.id.ief.mxmsgpb", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_IEF_MAX_MSG_PER_BATCH, "ID maximum message per batch", HFILL }},
+
+ { &hf_mq_id_ief_seqwrap,
+ { "Invalid sequence wrap value", "mq.id.ief.seqwrap", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_IEF_SEQ_WRAP_VALUE, "ID invalid sequence wrap value", HFILL }},
+
+ { &hf_mq_id_ief_hbint,
+ { "Invalid heartbeat interval", "mq.id.ief.hbint", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_IEF_HEARTBEAT_INTERVAL, "ID invalid heartbeat interval", HFILL }},
+
+ { &hf_mq_uid_structid,
+ { "UID structid", "mq.uid.structid", FT_STRINGZ, BASE_HEX, NULL, 0x0, "UID structid", HFILL }},
+
+ { &hf_mq_uid_userid,
+ { "User ID", "mq.uid.userid", FT_STRINGZ, BASE_HEX, NULL, 0x0, "UID structid", HFILL }},
+
+ { &hf_mq_uid_password,
+ { "Password", "mq.uid.password", FT_STRINGZ, BASE_HEX, NULL, 0x0, "UID password", HFILL }},
+
+ { &hf_mq_uid_longuserid,
+ { "Long User ID", "mq.uid.longuserid", FT_STRINGZ, BASE_HEX, NULL, 0x0, "UID long user id", HFILL }},
+
+ { &hf_mq_uid_securityid,
+ { "Security ID", "mq.uid.securityid", FT_BYTES, BASE_HEX, NULL, 0x0, "UID security id", HFILL }},
+
+ { &hf_mq_conn_queuemanager,
+ { "Queue manager", "mq.conn.qm", FT_STRINGZ, BASE_HEX, NULL, 0x0, "CONN queue manager", HFILL }},
+
+ { &hf_mq_conn_appname,
+ { "Application name", "mq.conn.appname", FT_STRINGZ, BASE_HEX, NULL, 0x0, "CONN application name", HFILL }},
+
+ { &hf_mq_conn_apptype,
+ { "Application type", "mq.conn.apptype", FT_INT32, BASE_DEC, NULL, 0x0, "CONN application type", HFILL }},
+
+ { &hf_mq_conn_acttoken,
+ { "Accounting token", "mq.conn.acttoken", FT_BYTES, BASE_HEX, NULL, 0x0, "CONN accounting token", HFILL }},
+
+ { &hf_mq_conn_version,
+ { "Version", "mq.conn.version", FT_UINT32, BASE_DEC, VALS(mq_conn_version_vals), 0x0, "CONN version", HFILL }},
+
+ { &hf_mq_conn_options,
+ { "Options", "mq.conn.options", FT_UINT32, BASE_HEX, NULL, 0x0, "CONN options", HFILL }},
+
+ { &hf_mq_inq_nbsel,
+ { "Selector count", "mq.inq.nbsel", FT_UINT32, BASE_DEC, NULL, 0x0, "INQ Selector count", HFILL }},
+
+ { &hf_mq_inq_nbint,
+ { "Integer count", "mq.inq.nbint", FT_UINT32, BASE_DEC, NULL, 0x0, "INQ Integer count", HFILL }},
+
+ { &hf_mq_inq_charlen,
+ { "Character length", "mq.inq.charlen", FT_UINT32, BASE_DEC, NULL, 0x0, "INQ Character length", HFILL }},
+
+ { &hf_mq_inq_sel,
+ { "Selector", "mq.inq.sel", FT_UINT32, BASE_DEC, NULL, 0x0, "INQ Selector", HFILL }},
+
+ { &hf_mq_inq_intvalue,
+ { "Integer value", "mq.inq.intvalue", FT_UINT32, BASE_DEC, NULL, 0x0, "INQ Integer value", HFILL }},
+
+ { &hf_mq_inq_charvalues,
+ { "Char values", "mq.inq.charvalues", FT_STRINGZ, BASE_HEX, NULL, 0x0, "INQ Character values", HFILL }},
+
+ { &hf_mq_spi_verb,
+ { "SPI Verb", "mq.spi.verb", FT_UINT32, BASE_DEC, VALS(mq_spi_verbs_vals), 0x0, "SPI Verb", HFILL }},
+
+ { &hf_mq_spi_version,
+ { "Version", "mq.spi.version", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Version", HFILL }},
+
+ { &hf_mq_spi_length,
+ { "Max reply size", "mq.spi.replength", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Max reply size", HFILL }},
+
+ { &hf_mq_spi_base_structid,
+ { "SPI Structid", "mq.spib.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "SPI Base structid", HFILL }},
+
+ { &hf_mq_spi_base_version,
+ { "Version", "mq.spib.version", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Base Version", HFILL }},
+
+ { &hf_mq_spi_base_length,
+ { "Length", "mq.spib.length", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Base Length", HFILL }},
+
+ { &hf_mq_spi_spqo_nbverb,
+ { "Number of verbs", "mq.spqo.nbverb", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Query Output Number of verbs", HFILL }},
+
+ { &hf_mq_spi_spqo_verbid,
+ { "Verb", "mq.spqo.verb", FT_UINT32, BASE_DEC, VALS(mq_spi_verbs_vals), 0x0, "SPI Query Output VerbId", HFILL }},
+
+ { &hf_mq_spi_spqo_maxinoutversion,
+ { "Max InOut Version", "mq.spqo.maxiov", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Query Output Max InOut Version", HFILL }},
+
+ { &hf_mq_spi_spqo_maxinversion,
+ { "Max In Version", "mq.spqo.maxiv", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Query Output Max In Version", HFILL }},
+
+ { &hf_mq_spi_spqo_maxoutversion,
+ { "Max Out Version", "mq.spqo.maxov", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Query Output Max Out Version", HFILL }},
+
+ { &hf_mq_spi_spqo_flags,
+ { "Flags", "mq.spqo.flags", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Query Output flags", HFILL }},
+
+ { &hf_mq_spi_spai_mode,
+ { "Mode", "mq.spai.mode", FT_UINT32, BASE_DEC, VALS(mq_spi_activate_vals), 0x0, "SPI Activate Input mode", HFILL }},
+
+ { &hf_mq_spi_spai_unknown1,
+ { "Unknown1", "mq.spai.unknown1", FT_STRINGZ, BASE_DEC, NULL, 0x0, "SPI Activate Input unknown1", HFILL }},
+
+ { &hf_mq_spi_spai_unknown2,
+ { "Unknown2", "mq.spai.unknown2", FT_STRINGZ, BASE_DEC, NULL, 0x0, "SPI Activate Input unknown2", HFILL }},
+
+ { &hf_mq_spi_spai_msgid,
+ { "Message Id", "mq.spai.msgid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "SPI Activate Input message id", HFILL }},
+
+ { &hf_mq_spi_spgi_batchsize,
+ { "Batch size", "mq.spgi.batchsize", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Get Input batch size", HFILL }},
+
+ { &hf_mq_spi_spgi_batchint,
+ { "Batch interval", "mq.spgi.batchint", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Get Input batch interval", HFILL }},
+
+ { &hf_mq_spi_spgi_maxmsgsize,
+ { "Max message size", "mq.spgi.maxmsgsize", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Get Input max message size", HFILL }},
+
+ { &hf_mq_spi_spgo_options,
+ { "Options", "mq.spgo.options", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Get Output options", HFILL }},
+
+ { &hf_mq_spi_spgo_size,
+ { "Size", "mq.spgo.size", FT_UINT32, BASE_DEC, NULL, 0x0, "SPI Get Output size", HFILL }},
+
+ { &hf_mq_spi_options_blank,
+ { "Blank padded", "mq.spi.options.blank", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_SPI_OPTIONS_BLANK_PADDED, "SPI Options blank padded", HFILL }},
+
+ { &hf_mq_spi_options_syncpoint,
+ { "Syncpoint", "mq.spi.options.sync", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_SPI_OPTIONS_SYNCPOINT, "SPI Options syncpoint", HFILL }},
+
+ { &hf_mq_spi_options_deferred,
+ { "Deferred", "mq.spi.options.deferred", FT_BOOLEAN, 8, TFS(&flags_set_truth), MQ_SPI_OPTIONS_DEFERRED, "SPI Options deferred", HFILL }},
+
+ { &hf_mq_put_length,
+ { "Data length", "mq.put.length", FT_UINT32, BASE_DEC, NULL, 0x0, "PUT Data length", HFILL }},
+
+ { &hf_mq_open_options,
+ { "Options", "mq.open.options", FT_UINT32, BASE_DEC, NULL, 0x0, "OPEN options", HFILL }},
+
+ { &hf_mq_ping_length,
+ { "Length", "mq.ping.length", FT_UINT32, BASE_DEC, NULL, 0x0, "PING length", HFILL }},
+
+ { &hf_mq_ping_buffer,
+ { "Buffer", "mq.ping.buffer", FT_BYTES, BASE_DEC, NULL, 0x0, "PING buffer", HFILL }},
+
+ { &hf_mq_reset_length,
+ { "Length", "mq.ping.length", FT_UINT32, BASE_DEC, NULL, 0x0, "RESET length", HFILL }},
+
+ { &hf_mq_reset_seqnum,
+ { "Sequence number", "mq.ping.seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, "RESET sequence number", HFILL }},
+
+ { &hf_mq_status_length,
+ { "Length", "mq.status.length", FT_UINT32, BASE_DEC, NULL, 0x0, "STATUS length", HFILL }},
+
+ { &hf_mq_status_code,
+ { "Code", "mq.status.code", FT_UINT32, BASE_DEC, VALS(mq_status_vals), 0x0, "STATUS code", HFILL }},
+
+ { &hf_mq_status_value,
+ { "Value", "mq.status.value", FT_UINT32, BASE_DEC, NULL, 0x0, "STATUS value", HFILL }},
+
+ { &hf_mq_od_structid,
+ { "OD structid", "mq.od.structid", FT_STRINGZ, BASE_HEX, NULL, 0x0, "OD structid", HFILL }},
+
+ { &hf_mq_od_version,
+ { "Version", "mq.od.version", FT_UINT32, BASE_DEC, NULL, 0x0, "OD version", HFILL }},
+
+ { &hf_mq_od_objecttype,
+ { "Object type", "mq.od.objtype", FT_UINT32, BASE_DEC, NULL, 0x0, "OD object type", HFILL }},
+
+ { &hf_mq_od_objectname,
+ { "Object name", "mq.od.objname", FT_STRINGZ, BASE_DEC, NULL, 0x0, "OD object name", HFILL }},
+
+ { &hf_mq_od_objectqmgrname,
+ { "Object queue manager name", "mq.od.objqmgrname", FT_STRINGZ, BASE_DEC, NULL, 0x0, "OD object queue manager name", HFILL }},
+
+ { &hf_mq_od_dynamicqname,
+ { "Dynamic queue name", "mq.od.dynqname", FT_STRINGZ, BASE_DEC, NULL, 0x0, "OD dynamic queue name", HFILL }},
+
+ { &hf_mq_od_alternateuserid,
+ { "Alternate user id", "mq.od.altuserid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "OD alternate userid", HFILL }},
+
+ { &hf_mq_od_recspresent,
+ { "Number of records", "mq.od.nbrrec", FT_UINT32, BASE_DEC, NULL, 0x0, "OD number of records", HFILL }},
+
+ { &hf_mq_od_knowndestcount,
+ { "Known destination count", "mq.od.kdestcount", FT_UINT32, BASE_DEC, NULL, 0x0, "OD known destination count", HFILL }},
+
+ { &hf_mq_od_unknowndestcount,
+ { "Unknown destination count", "mq.od.udestcount", FT_UINT32, BASE_DEC, NULL, 0x0, "OD unknown destination count", HFILL }},
+
+ { &hf_mq_od_invaliddestcount,
+ { "Invalid destination count", "mq.od.idestcount", FT_UINT32, BASE_DEC, NULL, 0x0, "OD invalid destination count", HFILL }},
+
+ { &hf_mq_od_objectrecoffset,
+ { "Offset of first OR", "mq.od.offsetor", FT_UINT32, BASE_DEC, NULL, 0x0, "OD offset of first OR", HFILL }},
+
+ { &hf_mq_od_responserecoffset,
+ { "Offset of first RR", "mq.od.offsetrr", FT_UINT32, BASE_DEC, NULL, 0x0, "OD offset of first RR", HFILL }},
+
+ { &hf_mq_od_objectrecptr,
+ { "Address of first OR", "mq.od.addror", FT_UINT32, BASE_HEX, NULL, 0x0, "OD address of first OR", HFILL }},
+
+ { &hf_mq_od_responserecptr,
+ { "Address of first RR", "mq.od.addrrr", FT_UINT32, BASE_HEX, NULL, 0x0, "OD address of first RR", HFILL }},
+
+ { &hf_mq_od_alternatesecurityid,
+ { "Alternate security id", "mq.od.altsecid", FT_STRINGZ, BASE_HEX, NULL, 0x0, "OD alternate security id", HFILL }},
+
+ { &hf_mq_od_resolvedqname,
+ { "Resolved queue name", "mq.od.resolvq", FT_STRINGZ, BASE_HEX, NULL, 0x0, "OD resolved queue name", HFILL }},
+
+ { &hf_mq_od_resolvedqmgrname,
+ { "Resolved queue manager name", "mq.od.resolvqmgr", FT_STRINGZ, BASE_HEX, NULL, 0x0, "OD resolved queue manager name", HFILL }},
+
+ { &hf_mq_or_objname,
+ { "Object name", "mq.od.objname", FT_STRINGZ, BASE_HEX, NULL, 0x0, "OR object name", HFILL }},
+
+ { &hf_mq_or_objqmgrname,
+ { "Object queue manager name", "mq.od.objqmgrname", FT_STRINGZ, BASE_HEX, NULL, 0x0, "OR object queue manager name", HFILL }},
+
+ { &hf_mq_rr_completioncode,
+ { "Completion code", "mq.rr.completioncode", FT_UINT32, BASE_DEC, NULL, 0x0, "OR completion code", HFILL }},
+
+ { &hf_mq_rr_reasoncode,
+ { "Reason code", "mq.rr.reasoncode", FT_UINT32, BASE_DEC, NULL, 0x0, "OR reason code", HFILL }},
+
+ { &hf_mq_pmr_msgid,
+ { "Message Id", "mq.pmr.msgid", FT_BYTES, BASE_DEC, NULL, 0x0, "PMR Message Id", HFILL }},
+
+ { &hf_mq_pmr_correlid,
+ { "Correlation Id", "mq.pmr.correlid", FT_BYTES, BASE_DEC, NULL, 0x0, "PMR Correlation Id", HFILL }},
+
+ { &hf_mq_pmr_groupid,
+ { "GroupId", "mq.pmr.groupid", FT_BYTES, BASE_DEC, NULL, 0x0, "PMR GroupId", HFILL }},
+
+ { &hf_mq_pmr_feedback,
+ { "Feedback", "mq.pmr.feedback", FT_UINT32, BASE_DEC, NULL, 0x0, "PMR Feedback", HFILL }},
+
+ { &hf_mq_pmr_acttoken,
+ { "Accounting token", "mq.pmr.acttoken", FT_BYTES, BASE_DEC, NULL, 0x0, "PMR accounting token", HFILL }},
+
+ { &hf_mq_md_structid,
+ { "MD structid", "mq.md.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD structid", HFILL }},
+
+ { &hf_mq_md_version,
+ { "Version", "mq.md.version", FT_UINT32, BASE_DEC, NULL, 0x0, "MD version", HFILL }},
+
+ { &hf_mq_md_report,
+ { "Report", "mq.md.report", FT_UINT32, BASE_DEC, NULL, 0x0, "MD report", HFILL }},
+
+ { &hf_mq_md_msgtype,
+ { "Message type", "mq.md.msgtype", FT_UINT32, BASE_DEC, NULL, 0x0, "MD message type", HFILL }},
+
+ { &hf_mq_md_expiry,
+ { "Expiry", "mq.md.expiry", FT_INT32, BASE_DEC, NULL, 0x0, "MD expiry", HFILL }},
+
+ { &hf_mq_md_feedback,
+ { "Feedback", "mq.md.feedback", FT_UINT32, BASE_DEC, NULL, 0x0, "MD feedback", HFILL }},
+
+ { &hf_mq_md_encoding,
+ { "Encoding", "mq.md.encoding", FT_UINT32, BASE_DEC, NULL, 0x0, "MD encoding", HFILL }},
+
+ { &hf_mq_md_ccsid,
+ { "Character set", "mq.md.ccsid", FT_INT32, BASE_DEC, NULL, 0x0, "MD character set", HFILL }},
+
+ { &hf_mq_md_format,
+ { "Format", "mq.md.format", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD format", HFILL }},
+
+ { &hf_mq_md_priority,
+ { "Priority", "mq.md.priority", FT_INT32, BASE_DEC, NULL, 0x0, "MD priority", HFILL }},
+
+ { &hf_mq_md_persistence,
+ { "Persistence", "mq.md.persistence", FT_UINT32, BASE_DEC, NULL, 0x0, "MD persistence", HFILL }},
+
+ { &hf_mq_md_msgid,
+ { "MessageId", "mq.md.msgid", FT_BYTES, BASE_DEC, NULL, 0x0, "MD Message Id", HFILL }},
+
+ { &hf_mq_md_correlid,
+ { "CorrelationId", "mq.md.correlid", FT_BYTES, BASE_DEC, NULL, 0x0, "MD Correlation Id", HFILL }},
+
+ { &hf_mq_md_backountcount,
+ { "Backount count", "mq.md.backount", FT_UINT32, BASE_DEC, NULL, 0x0, "MD Backount count", HFILL }},
+
+ { &hf_mq_md_replytoq,
+ { "ReplyToQ", "mq.md.correlid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD ReplyTo queue manager", HFILL }},
+
+ { &hf_mq_md_replytoqmgr,
+ { "ReplyToQMgr", "mq.md.correlid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD ReplyTo queue", HFILL }},
+
+ { &hf_mq_md_userid,
+ { "UserId", "mq.md.userid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD UserId", HFILL }},
+
+ { &hf_mq_md_acttoken,
+ { "Accounting token", "mq.md.acttoken", FT_BYTES, BASE_DEC, NULL, 0x0, "MD accounting token", HFILL }},
+
+ { &hf_mq_md_appliddata,
+ { "ApplicationId data", "mq.md.appldata", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD Put applicationId data", HFILL }},
+
+ { &hf_mq_md_putappltype,
+ { "Put Application Type", "mq.md.appltype", FT_INT32, BASE_DEC, NULL, 0x0, "MD Put application type", HFILL }},
+
+ { &hf_mq_md_putapplname,
+ { "Put Application Name", "mq.md.applname", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD Put application name", HFILL }},
+
+ { &hf_mq_md_putdate,
+ { "Put date", "mq.md.date", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD Put date", HFILL }},
+
+ { &hf_mq_md_puttime,
+ { "Put time", "mq.md.time", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD Put time", HFILL }},
+
+ { &hf_mq_md_applorigindata,
+ { "Application original data", "mq.md.origdata", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD Application original data", HFILL }},
+
+ { &hf_mq_md_groupid,
+ { "GroupId", "mq.md.groupid", FT_BYTES, BASE_DEC, NULL, 0x0, "MD GroupId", HFILL }},
+
+ { &hf_mq_md_msgseqnumber,
+ { "Message sequence number", "mq.md.msgseqnumber", FT_UINT32, BASE_DEC, NULL, 0x0, "MD Message sequence number", HFILL }},
+
+ { &hf_mq_md_offset,
+ { "Offset", "mq.md.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "MD Offset", HFILL }},
+
+ { &hf_mq_md_msgflags,
+ { "Message flags", "mq.md.msgflags", FT_UINT32, BASE_HEX, NULL, 0x0, "MD Message flags", HFILL }},
+
+ { &hf_mq_md_originallength,
+ { "Original length", "mq.md.origdata", FT_INT32, BASE_DEC, NULL, 0x0, "MD Original length", HFILL }},
+
+ { &hf_mq_md_hidden_lastformat,
+ { "Last format", "mq.md.lastformat", FT_STRINGZ, BASE_DEC, NULL, 0x0, "MD Last format", HFILL }},
+
+ { &hf_mq_dlh_structid,
+ { "DLH structid", "mq.dlh.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "DLH structid", HFILL }},
+
+ { &hf_mq_dlh_version,
+ { "Version", "mq.dlh.version", FT_UINT32, BASE_DEC, NULL, 0x0, "DLH version", HFILL }},
+
+ { &hf_mq_dlh_reason,
+ { "Reason", "mq.dlh.reason", FT_UINT32, BASE_DEC, NULL, 0x0, "DLH reason", HFILL }},
+
+ { &hf_mq_dlh_destq,
+ { "Destination queue", "mq.dlh.destq", FT_STRINGZ, BASE_DEC, NULL, 0x0, "DLH destination queue", HFILL }},
+
+ { &hf_mq_dlh_destqmgr,
+ { "Destination queue manager", "mq.dlh.destqmgr", FT_STRINGZ, BASE_DEC, NULL, 0x0, "DLH destination queue manager", HFILL }},
+
+ { &hf_mq_dlh_encoding,
+ { "Encoding", "mq.dlh.encoding", FT_UINT32, BASE_DEC, NULL, 0x0, "DLH encoding", HFILL }},
+
+ { &hf_mq_dlh_ccsid,
+ { "Character set", "mq.dlh.ccsid", FT_INT32, BASE_DEC, NULL, 0x0, "DLH character set", HFILL }},
+
+ { &hf_mq_dlh_format,
+ { "Format", "mq.dlh.format", FT_STRINGZ, BASE_DEC, NULL, 0x0, "DLH format", HFILL }},
+
+ { &hf_mq_dlh_putappltype,
+ { "Put application type", "mq.dlh.putappltype", FT_INT32, BASE_DEC, NULL, 0x0, "DLH put application type", HFILL }},
+
+ { &hf_mq_dlh_putapplname,
+ { "Put application name", "mq.dlh.putapplname", FT_STRINGZ, BASE_DEC, NULL, 0x0, "DLH put application name", HFILL }},
+
+ { &hf_mq_dlh_putdate,
+ { "Put date", "mq.dlh.putdate", FT_STRINGZ, BASE_DEC, NULL, 0x0, "DLH put date", HFILL }},
+
+ { &hf_mq_dlh_puttime,
+ { "Put time", "mq.dlh.puttime", FT_STRINGZ, BASE_DEC, NULL, 0x0, "DLH put time", HFILL }},
+
+ { &hf_mq_dh_putmsgrecfields,
+ { "Flags PMR", "mq.dh.flagspmr", FT_UINT32, BASE_DEC, NULL, 0x0, "DH flags PMR", HFILL }},
+
+ { &hf_mq_dh_recspresent,
+ { "Number of records", "mq.dh.nbrrec", FT_UINT32, BASE_DEC, NULL, 0x0, "DH number of records", HFILL }},
+
+ { &hf_mq_dh_objectrecoffset,
+ { "Offset of first OR", "mq.dh.offsetor", FT_UINT32, BASE_DEC, NULL, 0x0, "DH offset of first OR", HFILL }},
+
+ { &hf_mq_dh_putmsgrecoffset,
+ { "Offset of first PMR", "mq.dh.offsetpmr", FT_UINT32, BASE_DEC, NULL, 0x0, "DH offset of first PMR", HFILL }},
+
+ { &hf_mq_gmo_structid,
+ { "GMO structid", "mq.gmo.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "GMO structid", HFILL }},
+
+ { &hf_mq_gmo_version,
+ { "Version", "mq.gmo.version", FT_UINT32, BASE_DEC, NULL, 0x0, "GMO version", HFILL }},
+
+ { &hf_mq_gmo_options,
+ { "Options", "mq.gmo.options", FT_UINT32, BASE_HEX, NULL, 0x0, "GMO options", HFILL }},
+
+ { &hf_mq_gmo_waitinterval,
+ { "Wait Interval", "mq.gmo.waitint", FT_INT32, BASE_DEC, NULL, 0x0, "GMO wait interval", HFILL }},
+
+ { &hf_mq_gmo_signal1,
+ { "Signal 1", "mq.gmo.signal1", FT_UINT32, BASE_HEX, NULL, 0x0, "GMO signal 1", HFILL }},
+
+ { &hf_mq_gmo_signal2,
+ { "Signal 2", "mq.gmo.signal2", FT_UINT32, BASE_HEX, NULL, 0x0, "GMO signal 2", HFILL }},
+
+ { &hf_mq_gmo_resolvedqname,
+ { "Resolved queue name", "mq.gmo.resolvq", FT_STRINGZ, BASE_HEX, NULL, 0x0, "GMO resolved queue name", HFILL }},
+
+ { &hf_mq_gmo_matchoptions,
+ { "Match options", "mq.gmo.matchopt", FT_UINT32, BASE_HEX, NULL, 0x0, "GMO match options", HFILL }},
+
+ { &hf_mq_gmo_groupstatus,
+ { "Group status", "mq.gmo.grpstat", FT_UINT8, BASE_HEX, NULL, 0x0, "GMO group status", HFILL }},
+
+ { &hf_mq_gmo_segmentstatus,
+ { "Segment status", "mq.gmo.sgmtstat", FT_UINT8, BASE_HEX, NULL, 0x0, "GMO segment status", HFILL }},
+
+ { &hf_mq_gmo_segmentation,
+ { "Segmentation", "mq.gmo.segmentation", FT_UINT8, BASE_HEX, NULL, 0x0, "GMO segmentation", HFILL }},
+
+ { &hf_mq_gmo_reserved,
+ { "Reserved", "mq.gmo.reserved", FT_UINT8, BASE_HEX, NULL, 0x0, "GMO reserved", HFILL }},
+
+ { &hf_mq_gmo_msgtoken,
+ { "Message token", "mq.gmo.msgtoken", FT_BYTES, BASE_HEX, NULL, 0x0, "GMO message token", HFILL }},
+
+ { &hf_mq_gmo_returnedlength,
+ { "Returned length", "mq.gmo.retlen", FT_INT32, BASE_DEC, NULL, 0x0, "GMO returned length", HFILL }},
+
+ { &hf_mq_pmo_structid,
+ { "PMO structid", "mq.pmo.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "PMO structid", HFILL }},
+
+ { &hf_mq_pmo_version,
+ { "Version", "mq.pmo.structid", FT_UINT32, BASE_DEC, NULL, 0x0, "PMO version", HFILL }},
+
+ { &hf_mq_pmo_options,
+ { "Options", "mq.pmo.options", FT_UINT32, BASE_HEX, NULL, 0x0, "PMO options", HFILL }},
+
+ { &hf_mq_pmo_timeout,
+ { "Timeout", "mq.pmo.timeout", FT_INT32, BASE_DEC, NULL, 0x0, "PMO time out", HFILL }},
+
+ { &hf_mq_pmo_context,
+ { "Context", "mq.pmo.context", FT_UINT32, BASE_HEX, NULL, 0x0, "PMO context", HFILL }},
+
+ { &hf_mq_pmo_knowndestcount,
+ { "Known destination count", "mq.pmo.kdstcount", FT_UINT32, BASE_DEC, NULL, 0x0, "PMO known destination count", HFILL }},
+
+ { &hf_mq_pmo_unknowndestcount,
+ { "Unknown destination count", "mq.pmo.udestcount", FT_UINT32, BASE_DEC, NULL, 0x0, "PMO unknown destination count", HFILL }},
+
+ { &hf_mq_pmo_invaliddestcount,
+ { "Invalid destination count", "mq.pmo.idestcount", FT_UINT32, BASE_DEC, NULL, 0x0, "PMO invalid destination count", HFILL }},
+
+ { &hf_mq_pmo_resolvedqname,
+ { "Resolved queue name", "mq.pmo.resolvq", FT_STRINGZ, BASE_DEC, NULL, 0x0, "PMO resolved queue name", HFILL }},
+
+ { &hf_mq_pmo_resolvedqmgrname,
+ { "Resolved queue name manager", "mq.pmo.resolvqmgr", FT_STRINGZ, BASE_DEC, NULL, 0x0, "PMO resolved queue manager name", HFILL }},
+
+ { &hf_mq_pmo_recspresent,
+ { "Number of records", "mq.pmo.nbrrec", FT_UINT32, BASE_DEC, NULL, 0x0, "PMO number of records", HFILL }},
+
+ { &hf_mq_pmo_putmsgrecfields,
+ { "Flags PMR fields", "mq.pmo.flagspmr", FT_UINT32, BASE_HEX, NULL, 0x0, "PMO flags PMR fields", HFILL }},
+
+ { &hf_mq_pmo_putmsgrecoffset,
+ { "Offset of first PMR", "mq.pmo.offsetpmr", FT_UINT32, BASE_DEC, NULL, 0x0, "PMO offset of first PMR", HFILL }},
+
+ { &hf_mq_pmo_responserecoffset,
+ { "Offset of first RR", "mq.pmo.offsetrr", FT_UINT32, BASE_DEC, NULL, 0x0, "PMO offset of first RR", HFILL }},
+
+ { &hf_mq_pmo_putmsgrecptr,
+ { "Address of first record", "mq.pmo.addrrec", FT_UINT32, BASE_HEX, NULL, 0x0, "PMO address of first record", HFILL }},
+
+ { &hf_mq_pmo_responserecptr,
+ { "Address of first response record", "mq.pmo.addrres", FT_UINT32, BASE_HEX, NULL, 0x0, "PMO address of first response record", HFILL }},
+
+ { &hf_mq_head_structid,
+ { "Structid", "mq.head.structid", FT_STRINGZ, BASE_DEC, NULL, 0x0, "Header structid", HFILL }},
+
+ { &hf_mq_head_version,
+ { "Structid", "mq.head.version", FT_UINT32, BASE_DEC, NULL, 0x0, "Header version", HFILL }},
+
+ { &hf_mq_head_length,
+ { "Length", "mq.head.length", FT_UINT32, BASE_DEC, NULL, 0x0, "Header length", HFILL }},
+
+ { &hf_mq_head_encoding,
+ { "Encoding", "mq.head.encoding", FT_UINT32, BASE_DEC, NULL, 0x0, "Header encoding", HFILL }},
+
+ { &hf_mq_head_ccsid,
+ { "Character set", "mq.head.ccsid", FT_INT32, BASE_DEC, NULL, 0x0, "Header character set", HFILL }},
+
+ { &hf_mq_head_format,
+ { "Format", "mq.head.format", FT_STRINGZ, BASE_DEC, NULL, 0x0, "Header format", HFILL }},
+
+ { &hf_mq_head_flags,
+ { "Flags", "mq.head.flags", FT_UINT32, BASE_DEC, NULL, 0x0, "Header flags", HFILL }},
+
+ { &hf_mq_head_struct,
+ { "Struct", "mq.head.struct", FT_BYTES, BASE_HEX, NULL, 0x0, "Header struct", HFILL }},
+
+ { &hf_mq_xa_length,
+ { "Length", "mq.xa.length", FT_UINT32, BASE_DEC, NULL, 0x0, "XA Length", HFILL }},
+
+ { &hf_mq_xa_returnvalue,
+ { "Return value", "mq.xa.returnvalue", FT_INT32, BASE_DEC, VALS(mq_xaer_vals), 0x0, "XA Return Value", HFILL }},
+
+ { &hf_mq_xa_tmflags,
+ { "Transaction Manager Flags", "mq.xa.tmflags", FT_UINT32, BASE_HEX, NULL, 0x0, "XA Transaction Manager Flags", HFILL }},
+
+ { &hf_mq_xa_rmid,
+ { "Resource manager ID", "mq.xa.rmid", FT_UINT32, BASE_DEC, NULL, 0x0, "XA Resource Manager ID", HFILL }},
+
+ { &hf_mq_xa_count,
+ { "Number of Xid", "mq.xa.nbxid", FT_UINT32, BASE_DEC, NULL, 0x0, "XA Number of Xid", HFILL }},
+
+ { &hf_mq_xa_tmflags_join,
+ { "JOIN", "mq.xa.tmflags.join", FT_BOOLEAN, 32, TFS(&flags_set_truth), MQ_XA_TMJOIN, "XA TM Flags JOIN", HFILL }},
+
+ { &hf_mq_xa_tmflags_endrscan,
+ { "ENDRSCAN", "mq.xa.tmflags.endrscan", FT_BOOLEAN, 32, TFS(&flags_set_truth), MQ_XA_TMENDRSCAN, "XA TM Flags ENDRSCAN", HFILL }},
+
+ { &hf_mq_xa_tmflags_startrscan,
+ { "STARTRSCAN", "mq.xa.tmflags.startrscan", FT_BOOLEAN, 32, TFS(&flags_set_truth), MQ_XA_TMSTARTRSCAN, "XA TM Flags STARTRSCAN", HFILL }},
+
+ { &hf_mq_xa_tmflags_suspend,
+ { "SUSPEND", "mq.xa.tmflags.suspend", FT_BOOLEAN, 32, TFS(&flags_set_truth), MQ_XA_TMSUSPEND, "XA TM Flags SUSPEND", HFILL }},
+
+ { &hf_mq_xa_tmflags_success,
+ { "SUCCESS", "mq.xa.tmflags.success", FT_BOOLEAN, 32, TFS(&flags_set_truth), MQ_XA_TMSUCCESS, "XA TM Flags SUCCESS", HFILL }},
+
+ { &hf_mq_xa_tmflags_resume,
+ { "RESUME", "mq.xa.tmflags.resume", FT_BOOLEAN, 32, TFS(&flags_set_truth), MQ_XA_TMRESUME, "XA TM Flags RESUME", HFILL }},
+
+ { &hf_mq_xa_tmflags_fail,
+ { "FAIL", "mq.xa.tmflags.fail", FT_BOOLEAN, 32, TFS(&flags_set_truth), MQ_XA_TMFAIL, "XA TM Flags FAIL", HFILL }},
+
+ { &hf_mq_xa_tmflags_onephase,
+ { "ONEPHASE", "mq.xa.tmflags.onephase", FT_BOOLEAN, 32, TFS(&flags_set_truth), MQ_XA_TMONEPHASE, "XA TM Flags ONEPHASE", HFILL }},
+
+ { &hf_mq_xa_xid_formatid,
+ { "Format ID", "mq.xa.xid.formatid", FT_INT32, BASE_DEC, NULL, 0x0, "XA Xid Format ID", HFILL }},
+
+ { &hf_mq_xa_xid_globalxid_length,
+ { "Global TransactionId Length", "mq.xa.xid.gxidl", FT_UINT8, BASE_DEC, NULL, 0x0, "XA Xid Global TransactionId Length", HFILL }},
+
+ { &hf_mq_xa_xid_brq_length,
+ { "Branch Qualifier Length", "mq.xa.xid.bql", FT_UINT8, BASE_DEC, NULL, 0x0, "XA Xid Branch Qualifier Length", HFILL }},
+
+ { &hf_mq_xa_xid_globalxid,
+ { "Global TransactionId", "mq.xa.xid.gxid", FT_BYTES, BASE_DEC, NULL, 0x0, "XA Xid Global TransactionId", HFILL }},
+
+ { &hf_mq_xa_xid_brq,
+ { "Branch Qualifier", "mq.xa.xid.bq", FT_BYTES, BASE_DEC, NULL, 0x0, "XA Xid Branch Qualifier", HFILL }},
+
+ { &hf_mq_xa_xainfo_length,
+ { "Length", "mq.xa.xainfo.length", FT_UINT8, BASE_DEC, NULL, 0x0, "XA XA_info Length", HFILL }},
+
+ { &hf_mq_xa_xainfo_value,
+ { "Value", "mq.xa.xainfo.value", FT_STRINGZ, BASE_DEC, NULL, 0x0, "XA XA_info Value", HFILL }}
+
+ };
+ static gint *ett[] = {
+ &ett_mq,
+ &ett_mq_tsh,
+ &ett_mq_tsh_tcf,
+ &ett_mq_api,
+ &ett_mq_msh,
+ &ett_mq_xqh,
+ &ett_mq_id,
+ &ett_mq_id_icf,
+ &ett_mq_id_ief,
+ &ett_mq_uid,
+ &ett_mq_conn,
+ &ett_mq_inq,
+ &ett_mq_spi,
+ &ett_mq_spi_base,
+ &ett_mq_spi_options,
+ &ett_mq_put,
+ &ett_mq_open,
+ &ett_mq_ping,
+ &ett_mq_reset,
+ &ett_mq_status,
+ &ett_mq_od,
+ &ett_mq_or,
+ &ett_mq_rr,
+ &ett_mq_pmr,
+ &ett_mq_md,
+ &ett_mq_mde,
+ &ett_mq_dlh,
+ &ett_mq_dh,
+ &ett_mq_gmo,
+ &ett_mq_pmo,
+ &ett_mq_head,
+ &ett_mq_xa,
+ &ett_mq_xa_tmflags,
+ &ett_mq_xa_xid,
+ &ett_mq_xa_info,
+ };
+
+ module_t *mq_module;
+
+ proto_mq = proto_register_protocol("WebSphere MQ", "MQ", "mq");
+ proto_register_field_array(proto_mq, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_heur_dissector_list("mq", &mq_heur_subdissector_list);
+ register_init_routine(mq_init);
+
+ mq_module = prefs_register_protocol(proto_mq, NULL);
+ prefs_register_bool_preference(mq_module, "desegment",
+ "Desegment all MQ messages spanning multiple TCP segments",
+ "Whether the MQ dissector should desegment all messages spanning multiple TCP segments",
+ &mq_desegment);
+ prefs_register_bool_preference(mq_module, "reassembly",
+ "Reassemble segmented MQ messages",
+ "Whether the MQ dissector should reassemble all MQ messages spanning multiple TSH segments",
+ &mq_reassembly);
+}
+
+void
+proto_reg_handoff_mq(void)
+{
+ /* Unlike some protocol (HTTP, POP3, ...) that clearly map to a standard
+ * class of applications (web browser, e-mail client, ...) and have a very well
+ * known port number, the MQ applications are most often specific to a business application */
+
+ mq_tcp_handle = create_dissector_handle(dissect_mq_tcp, proto_mq);
+ mq_spx_handle = create_dissector_handle(dissect_mq_spx, proto_mq);
+
+ dissector_add_handle("tcp.port", mq_tcp_handle);
+ heur_dissector_add("tcp", dissect_mq_heur_tcp, proto_mq);
+ heur_dissector_add("netbios", dissect_mq_heur_netbios, proto_mq);
+ heur_dissector_add("http", dissect_mq_heur_http, proto_mq);
+ dissector_add("spx.socket", MQ_SOCKET_SPX, mq_spx_handle);
+ data_handle = find_dissector("data");
+
+}
diff --git a/epan/dissectors/packet-mq.h b/epan/dissectors/packet-mq.h
new file mode 100644
index 0000000000..e2b8a18759
--- /dev/null
+++ b/epan/dissectors/packet-mq.h
@@ -0,0 +1,36 @@
+/* packet-mq.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_MQ_H__
+#define __PACKET_MQ_H__
+
+/*
+ * Private data passed from the MQ dissector to subdissectors.
+ */
+struct mqinfo {
+ guint32 encoding; /* Message encoding */
+ guint32 ccsid; /* Message character set */
+ guint8 format[8]; /* Message format */
+};
+
+#endif
diff --git a/epan/dissectors/packet-mrdisc.c b/epan/dissectors/packet-mrdisc.c
new file mode 100644
index 0000000000..82a00e72fe
--- /dev/null
+++ b/epan/dissectors/packet-mrdisc.c
@@ -0,0 +1,293 @@
+/* packet-mrdisc.c 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Routines for IGMP/MRDISC packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+
+
+ MRDISC
+ code
+
+ 0x24 x
+ 0x25 x
+ 0x26 x
+
+ MRDISC : IGMP Multicast Router DISCovery
+ Defined in draft-ietf-idmr-igmp-mrdisc-06.txt
+ TTL==1 and IP.DST==224.0.0.2 for all packets.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "packet-igmp.h"
+#include "packet-mrdisc.h"
+
+
+static int proto_mrdisc = -1;
+static int hf_checksum = -1;
+static int hf_checksum_bad = -1;
+static int hf_type = -1;
+static int hf_advint = -1;
+static int hf_numopts = -1;
+static int hf_options = -1;
+static int hf_option = -1;
+static int hf_option_len = -1;
+static int hf_qi = -1;
+static int hf_rv = -1;
+static int hf_option_bytes = -1;
+
+static int ett_mrdisc = -1;
+static int ett_options = -1;
+
+#define MRDISC_MRA 0x24
+#define MRDISC_MRS 0x25
+#define MRDISC_MRT 0x26
+static const value_string mrdisc_types[] = {
+ {MRDISC_MRA, "Multicast Router Advertisement"},
+ {MRDISC_MRS, "Multicast Router Solicitation"},
+ {MRDISC_MRT, "Multicast Router Termination"},
+ {0, NULL}
+};
+
+#define MRDISC_QI 0x01
+#define MRDISC_RV 0x02
+static const value_string mrdisc_options[] = {
+ {MRDISC_QI, "Query Interval"},
+ {MRDISC_RV, "Robustness Variable"},
+ {0, NULL}
+};
+
+
+static int
+dissect_mrdisc_mra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ guint16 num;
+
+ /* Advertising Interval */
+ proto_tree_add_item(parent_tree, hf_advint, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ /* skip unused bytes */
+ offset += 2;
+
+ /* number of options */
+ num = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(parent_tree, hf_numopts, tvb,
+ offset, 2, num);
+ offset += 2;
+
+ /* process any options */
+ while (num--) {
+ proto_tree *tree;
+ proto_item *item;
+ guint8 type,len;
+ int old_offset = offset;
+
+ item = proto_tree_add_item(parent_tree, hf_options,
+ tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_options);
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_option, tvb, offset, 1, type);
+ offset += 1;
+
+ len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_option_len, tvb, offset, 1, len);
+ offset += 1;
+
+ switch (type) {
+ case MRDISC_QI:
+ if (item) {
+ proto_item_set_text(item,"Option: %s == %d",
+ val_to_str(type, mrdisc_options, "unknown %x"),
+ tvb_get_ntohs(tvb, offset));
+ }
+
+ proto_tree_add_item(tree, hf_qi, tvb, offset, len,
+ FALSE);
+ offset += len;
+ break;
+ case MRDISC_RV:
+ if (item) {
+ proto_item_set_text(item,"Option: %s == %d",
+ val_to_str(type, mrdisc_options, "unknown %x"),
+ tvb_get_ntohs(tvb, offset));
+ }
+
+ proto_tree_add_item(tree, hf_rv, tvb, offset, len,
+ FALSE);
+ offset += len;
+ break;
+ default:
+ if (item) {
+ proto_item_set_text(item,"Option: unknown");
+ }
+
+ proto_tree_add_item(tree, hf_option_bytes,
+ tvb, offset, len, FALSE);
+ offset += len;
+ }
+ if (item) {
+ proto_item_set_len(item, offset-old_offset);
+ }
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_mrdisc_mrst(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ /* skip reserved byte */
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ return offset;
+}
+
+
+/* This function is only called from the IGMP dissector */
+int
+dissect_mrdisc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree;
+ proto_item *item;
+ guint8 type;
+
+ if (!proto_is_protocol_enabled(find_protocol_by_id(proto_mrdisc))) {
+ /* we are not enabled, skip entire packet to be nice
+ to the igmp layer. (so clicking on IGMP will display the data)
+ */
+ return offset+tvb_length_remaining(tvb, offset);
+ }
+
+ item = proto_tree_add_item(parent_tree, proto_mrdisc, tvb, offset, 0, FALSE);
+ tree = proto_item_add_subtree(item, ett_mrdisc);
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MRDISC");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+
+ type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s",val_to_str(type, mrdisc_types,
+ "Unknown Type:0x%02x"));
+ }
+
+ /* type of command */
+ proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type);
+ offset += 1;
+
+ switch (type) {
+ case MRDISC_MRA:
+ offset = dissect_mrdisc_mra(tvb, pinfo, tree, offset);
+ break;
+ case MRDISC_MRS:
+ case MRDISC_MRT:
+ /* MRS and MRT packets looks the same */
+ offset = dissect_mrdisc_mrst(tvb, pinfo, tree, offset);
+ break;
+ }
+ return offset;
+}
+
+
+void
+proto_register_mrdisc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_type,
+ { "Type", "mrdisc.type", FT_UINT8, BASE_HEX,
+ VALS(mrdisc_types), 0, "MRDISC Packet Type", HFILL }},
+
+ { &hf_checksum,
+ { "Checksum", "mrdisc.checksum", FT_UINT16, BASE_HEX,
+ NULL, 0, "MRDISC Checksum", HFILL }},
+
+ { &hf_checksum_bad,
+ { "Bad Checksum", "mrdisc.checksum_bad", FT_BOOLEAN, BASE_NONE,
+ NULL, 0, "Bad MRDISC Checksum", HFILL }},
+
+ { &hf_advint,
+ { "Advertising Interval", "mrdisc.adv_int", FT_UINT8, BASE_DEC,
+ NULL, 0, "MRDISC Advertising Interval in seconds", HFILL }},
+
+ { &hf_numopts,
+ { "Number Of Options", "mrdisc.num_opts", FT_UINT16, BASE_DEC,
+ NULL, 0, "MRDISC Number Of Options", HFILL }},
+
+ { &hf_options,
+ { "Options", "mrdisc.options", FT_NONE, BASE_NONE,
+ NULL, 0, "MRDISC Options", HFILL }},
+
+ { &hf_option,
+ { "Option", "mrdisc.option", FT_UINT8, BASE_DEC,
+ VALS(mrdisc_options), 0, "MRDISC Option Type", HFILL }},
+
+ { &hf_option_len,
+ { "Length", "mrdisc.opt_len", FT_UINT8, BASE_DEC,
+ NULL, 0, "MRDISC Option Length", HFILL }},
+
+ { &hf_qi,
+ { "Query Interval", "mrdisc.query_int", FT_UINT16, BASE_DEC,
+ NULL, 0, "MRDISC Query Interval", HFILL }},
+
+ { &hf_rv,
+ { "Robustness Variable", "mrdisc.rob_var", FT_UINT16, BASE_DEC,
+ NULL, 0, "MRDISC Robustness Variable", HFILL }},
+
+ { &hf_option_bytes,
+ { "Data", "mrdisc.option_data", FT_BYTES, BASE_NONE,
+ NULL, 0, "MRDISC Unknown Option Data", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_mrdisc,
+ &ett_options,
+ };
+
+ proto_mrdisc = proto_register_protocol("Multicast Router DISCovery protocol",
+ "MRDISC", "mrdisc");
+ proto_register_field_array(proto_mrdisc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/epan/dissectors/packet-mrdisc.h b/epan/dissectors/packet-mrdisc.h
new file mode 100644
index 0000000000..5056bb1195
--- /dev/null
+++ b/epan/dissectors/packet-mrdisc.h
@@ -0,0 +1,31 @@
+/* packet-mrdisc.h 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Declarations of routines for IGMP/MRDISC packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_MRDISC_H__
+#define __PACKET_MRDISC_H__
+
+int dissect_mrdisc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+
+#endif
+
diff --git a/epan/dissectors/packet-msdp.c b/epan/dissectors/packet-msdp.c
new file mode 100644
index 0000000000..cb15ca0c3d
--- /dev/null
+++ b/epan/dissectors/packet-msdp.c
@@ -0,0 +1,585 @@
+/* packet-msdp.c
+ * Routines for Multicast Source Discovery Protocol (MSDP) dissection.
+ * draft-ietf-msdp-spec-10.txt
+ *
+ * Copyright 2001, Heikki Vatiainen <hessu@cs.tut.fi>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+/* MSDP message types. The messages are TLV (Type-Length-Value) encoded */
+enum { MSDP_SA = 1,
+ MSDP_SA_REQ,
+ MSDP_SA_RSP,
+ MSDP_KEEP_ALIVE,
+ MSDP_NOTIFICATION,
+
+ /* Theses are only assigned in MSDP spec. Their use is specifed
+ * elsewhere */
+ MSDP_TRACE_IN_PROGRESS,
+ MSDP_TRACE_REPLY
+};
+
+static const value_string msdp_types[] = {
+ { MSDP_SA, "IPv4 Source-Active" },
+ { MSDP_SA_REQ, "IPv4 Source-Active Request" },
+ { MSDP_SA_RSP, "IPv4 Source-Active Response" },
+ { MSDP_KEEP_ALIVE, "KeepAlive" },
+ { MSDP_NOTIFICATION, "Notification" },
+
+ { MSDP_TRACE_IN_PROGRESS, "MSDP traceroute in progresss" },
+ { MSDP_TRACE_REPLY, "MSDP traceroute reply" },
+ { 0, NULL },
+};
+
+
+/* Error codes */
+enum { MESSAGE_HEADER_ERROR = 1,
+ SA_REQUEST_ERROR,
+ SA_MESSAGE_SA_RESPONSE_ERROR,
+ HOLD_TIMER_EXPIRED,
+ FSM_ERROR,
+ NOTIFICATION,
+ CEASE
+};
+
+static const value_string error_vals[] = {
+ { MESSAGE_HEADER_ERROR, "Message Header Error" },
+ { SA_REQUEST_ERROR, "SA-Request Error" },
+ { SA_MESSAGE_SA_RESPONSE_ERROR, "SA-Message/SA-Response Error" },
+ { HOLD_TIMER_EXPIRED, "Hold Timer Expired" },
+ { FSM_ERROR, "Finite State Machine Error" },
+ { NOTIFICATION, "Notification" },
+ { CEASE, "Cease" },
+ { 0, NULL },
+};
+
+
+/* Message Header Error subcodes */
+static const value_string hdr_error_vals[] = {
+ { 0, "Unspecific" },
+ { 2, "Bad Message Length" },
+ { 3, "Bad Message Type" },
+ { 0, NULL },
+};
+
+/* SA-Request Error subcodes (the O-bit is always clear) */
+static const value_string sa_req_error_vals[] = {
+ { 0, "Unspecific" },
+ { 1, "Invalid Group" },
+ { 0, NULL },
+};
+
+/* SA-Message/SA-Response Error subcodes */
+static const value_string sa_msg_error_vals[] = {
+ { 0, "Unspecific" },
+ { 1, "Invalid Entry Count" },
+ { 2, "Invalid RP Address" },
+ { 3, "Invalid Group Address" },
+ { 4, "Invalid Source Address" },
+ { 5, "Invalid Sprefix Length" },
+ { 6, "Looping SA (Self is RP)" },
+ { 7, "Unknown Encapsulation" },
+ { 8, "Administrative Scope Boundary Violated" },
+ { 0, NULL },
+};
+
+/* Finite State Machine Error subcodes (the O-bit is always clear) */
+static const value_string fsm_error_vals[] = {
+ { 0, "Unspecific" },
+ { 1, "Unexpected Message Type FSM Error" },
+ { 0, NULL },
+};
+
+/*
+ * Hold Timer Expired subcodes (the O-bit is always clear):
+ * Notification subcodes (the O-bit is always clear):
+ * Cease subcodes (the O-bit is always clear):
+ *
+ * These have only "Unspecific" specified.
+ */
+static const value_string sa_unspec_error_vals[] = {
+ { 0, "Unspecific" },
+ { 0, NULL },
+};
+
+
+/* Initialize the protocol and registered fields */
+static int proto_msdp = -1;
+static int hf_msdp_type = -1;
+static int hf_msdp_length = -1;
+
+static int hf_msdp_sa_entry_count = -1;
+static int hf_msdp_sa_rp_addr = -1;
+static int hf_msdp_sa_reserved = -1;
+static int hf_msdp_sa_sprefix_len = -1;
+static int hf_msdp_sa_group_addr = -1;
+static int hf_msdp_sa_src_addr = -1;
+
+static int hf_msdp_sa_req_res = -1;
+static int hf_msdp_sa_req_group = -1;
+
+static int hf_msdp_not_o = -1;
+static int hf_msdp_not_error = -1;
+static int hf_msdp_not_error_sub = -1;
+
+static int hf_msdp_not_ipv4 = -1;
+static int hf_msdp_not_res = -1;
+static int hf_msdp_not_entry_count = -1;
+static int hf_msdp_not_sprefix_len = -1;
+
+
+static gint ett_msdp = -1;
+static gint ett_msdp_sa_entry = -1;
+static gint ett_msdp_sa_enc_data = -1;
+static gint ett_msdp_not_data = -1;
+
+
+static dissector_handle_t ip_handle;
+
+
+static void
+dissect_msdp_sa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int *offset, int len);
+static void
+dissect_msdp_notification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, guint16 tlv_len);
+
+
+static void
+dissect_msdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *msdp_tree;
+ int offset;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSDP");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str(tvb_get_guint8(tvb, 0),
+ msdp_types,
+ "<Unknown MSDP message type>"));
+
+ if (tree) {
+ guint8 type;
+ guint16 length;
+
+ ti = proto_tree_add_item(tree, proto_msdp, tvb, 0, -1, FALSE);
+ msdp_tree = proto_item_add_subtree(ti, ett_msdp);
+
+ offset = 0;
+ while (tvb_reported_length_remaining(tvb, offset) >= 3) {
+ type = tvb_get_guint8(tvb, offset);
+ length = tvb_get_ntohs(tvb, offset + 1);
+ if (length < 3)
+ break;
+ proto_tree_add_uint(msdp_tree, hf_msdp_type, tvb, offset, 1, type);
+ proto_tree_add_uint(msdp_tree, hf_msdp_length, tvb, offset + 1, 2, length);
+ offset += 3;
+ length -= 3;
+
+ switch (type) {
+ case MSDP_SA:
+ case MSDP_SA_RSP:
+ dissect_msdp_sa(tvb, pinfo, msdp_tree, &offset,
+ length);
+ break;
+ case MSDP_SA_REQ:
+ proto_tree_add_item(msdp_tree, hf_msdp_sa_req_res, tvb, offset, 1, FALSE);
+ proto_tree_add_item(msdp_tree, hf_msdp_sa_req_group, tvb, offset + 1, 4, FALSE);
+ offset += 5;
+ break;
+ case MSDP_NOTIFICATION:
+ dissect_msdp_notification(tvb, pinfo, msdp_tree, &offset, length);
+ break;
+ default:
+ if (length > 0)
+ proto_tree_add_text(msdp_tree, tvb, offset, length, "TLV contents");
+ offset += length;
+ break;
+ }
+ }
+
+ if (tvb_length_remaining(tvb, offset) > 0)
+ proto_tree_add_text(msdp_tree, tvb, offset,
+ -1, "Trailing junk");
+ }
+
+ return;
+}
+
+/* Both Source-Active and Source-Active Response have the same format
+ * with one exception. Encapsulated multicast data is not allowed in
+ * SA Response.
+ */
+static void dissect_msdp_sa(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int *offset, int length)
+{
+ guint8 entries;
+ guint32 rp_addr;
+
+ if (length < 1)
+ return;
+ entries = tvb_get_guint8(tvb, *offset);
+ proto_tree_add_uint(tree, hf_msdp_sa_entry_count, tvb, *offset, 1, entries);
+ *offset += 1;
+ length -= 1;
+
+ if (length < 4) {
+ *offset += length;
+ length = 0;
+ return;
+ }
+ tvb_memcpy(tvb, (guint8 *)&rp_addr, *offset, 4);
+ proto_tree_add_item(tree, hf_msdp_sa_rp_addr, tvb, *offset, 4, FALSE);
+ *offset += 4;
+ length -= 4;
+
+ /* Put each of the (S,G) entries in their own subtree.
+ * This is probably visually better.
+ */
+ while (entries-- > 0) {
+ proto_item *ei;
+ proto_tree *entry_tree;
+
+ if (length < 12) {
+ *offset += length;
+ length = 0;
+ return;
+ }
+ ei = proto_tree_add_text(tree, tvb, *offset, 12, "(S,G) block: %s/%u -> %s",
+ ip_to_str(tvb_get_ptr(tvb, *offset + 8, 4)),
+ tvb_get_guint8(tvb, *offset + 3),
+ ip_to_str(tvb_get_ptr(tvb, *offset + 4, 4)));
+ entry_tree = proto_item_add_subtree(ei, ett_msdp_sa_entry);
+
+ proto_tree_add_item(entry_tree, hf_msdp_sa_reserved, tvb, *offset, 3, FALSE);
+ *offset += 3;
+ length -= 3;
+ proto_tree_add_item(entry_tree, hf_msdp_sa_sprefix_len, tvb, *offset, 1, FALSE);
+ *offset += 1;
+ length -= 1;
+ proto_tree_add_item(entry_tree, hf_msdp_sa_group_addr, tvb, *offset, 4, FALSE);
+ *offset += 4;
+ length -= 4;
+ proto_tree_add_item(entry_tree, hf_msdp_sa_src_addr, tvb, *offset, 4, FALSE);
+ *offset += 4;
+ length -= 4;
+ }
+
+ /*
+ * Check if an encapsulated multicast IPv4 packet follows
+ */
+ if (length > 0) {
+ proto_item *ei;
+ proto_tree *enc_tree;
+ gint available_length, reported_length;
+ tvbuff_t *next_tvb;
+
+ ei = proto_tree_add_text(tree, tvb, *offset, length,
+ "Encapsulated IPv4 packet: %u bytes",
+ length);
+ enc_tree = proto_item_add_subtree(ei, ett_msdp_sa_enc_data);
+
+ available_length = tvb_length_remaining(tvb, *offset);
+ reported_length = tvb_reported_length_remaining(tvb, *offset);
+ g_assert(available_length >= 0);
+ g_assert(reported_length >= 0);
+ if (available_length > reported_length)
+ available_length = reported_length;
+ if (available_length > length)
+ available_length = length;
+ if (reported_length > length)
+ reported_length = length;
+
+ next_tvb = tvb_new_subset(tvb, *offset, available_length,
+ reported_length);
+ /* Set the information columns read-only so that they
+ * reflect the MSDP packet rather than the
+ * encapsulated packet.
+ */
+ col_set_writable(pinfo->cinfo, FALSE);
+ call_dissector(ip_handle, next_tvb, pinfo, enc_tree);
+ }
+ *offset += length;
+
+ return;
+}
+
+/* Note: updates *offset */
+static void add_notification_data_ipv4addr(tvbuff_t *tvb, proto_tree *tree, int *offset, const char *addrtype)
+{
+ guint32 ipaddr;
+
+ proto_tree_add_item(tree, hf_msdp_not_res, tvb, *offset, 3, FALSE);
+ *offset += 3;
+ tvb_memcpy(tvb, (guint8 *)&ipaddr, *offset, 4);
+ proto_tree_add_ipv4_format(tree, hf_msdp_not_ipv4, tvb, *offset, 4, ipaddr,
+ "%s: %s", addrtype, ip_to_str((guint8 *)&ipaddr));
+ *offset += 4;
+
+ return;
+}
+
+static void dissect_msdp_notification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, guint16 tlv_len)
+{
+ guint8 error, error_sub;
+ const value_string *vals;
+
+ proto_tree_add_item(tree, hf_msdp_not_o, tvb, *offset, 1, FALSE);
+ proto_tree_add_item(tree, hf_msdp_not_error, tvb, *offset, 1, FALSE);
+ error = tvb_get_guint8(tvb, *offset);
+ error &= 0x7F; /* Error is 7-bit field. O-bit is bit 8 */
+ *offset += 1;
+
+ /* Depending on the Error Code, we collect the correct
+ * value_strings for the Error subcode
+ */
+ switch (error) {
+ case MESSAGE_HEADER_ERROR:
+ vals = hdr_error_vals;
+ break;
+ case SA_REQUEST_ERROR:
+ vals = sa_req_error_vals;
+ break;
+ case SA_MESSAGE_SA_RESPONSE_ERROR:
+ vals = sa_msg_error_vals;
+ break;
+ case FSM_ERROR:
+ vals = fsm_error_vals;
+ break;
+ case HOLD_TIMER_EXPIRED:
+ case NOTIFICATION:
+ case CEASE:
+ vals = sa_unspec_error_vals;
+ break;
+ default:
+ vals = sa_unspec_error_vals;
+ break;
+ }
+
+ error_sub = tvb_get_guint8(tvb, *offset);
+ proto_tree_add_uint_format(tree, hf_msdp_not_error_sub, tvb, *offset, 1,
+ error_sub, "Error subcode: %s (%u)",
+ val_to_str(error_sub, vals, "<Unknown Error subcode>"),
+ error_sub);
+ *offset += 1;
+
+ /* Do switch again, this time to dissect the data portion
+ * correctly. Ugly.
+ */
+ switch (error) {
+ tvbuff_t *next_tvb;
+ case SA_REQUEST_ERROR:
+ add_notification_data_ipv4addr(tvb, tree, offset, "Group address");
+ break;
+ case SA_MESSAGE_SA_RESPONSE_ERROR:
+ if (error_sub == 0) {
+ break;
+ } else if (error_sub == 1) {
+ proto_tree_add_item(tree, hf_msdp_not_entry_count, tvb, *offset, 1, FALSE);
+ *offset += 1;
+ break;
+ } else if (error_sub == 2) {
+ add_notification_data_ipv4addr(tvb, tree, offset, "RP address");
+ break;
+ } else if (error_sub == 3 || error_sub == 8) {
+ add_notification_data_ipv4addr(tvb, tree, offset, "Group address");
+ break;
+ } else if (error_sub == 4) {
+ add_notification_data_ipv4addr(tvb, tree, offset, "Source address");
+ break;
+ } else if (error_sub == 5) {
+ proto_tree_add_item(tree, hf_msdp_not_sprefix_len, tvb, *offset, 1, FALSE);
+ *offset += 1;
+ break;
+ } else if (error_sub == 6) {
+ /* No break, causes fall through to next label */
+ } else if (error_sub == 7) {
+ proto_tree_add_text(tree, tvb, *offset, tlv_len - 5,
+ "Packet with unknown encapsulation: %u bytes",
+ tlv_len - 5);
+ *offset += tlv_len - 5;
+ break;
+ } else {
+ proto_tree_add_text(tree, tvb, *offset, tlv_len - 5,
+ "<Unknown data>: %u bytes",
+ tlv_len -5);
+ *offset += tlv_len - 5;
+ break;
+ }
+ /* Fall through */
+ case MESSAGE_HEADER_ERROR:
+ case NOTIFICATION:
+ /* Data contains the message that had an error. Even a
+ * broken Notification message causes a Notification
+ * message with Error Code set to Notification to be
+ * sent back.
+ */
+ next_tvb = tvb_new_subset(tvb, *offset, -1, -1);
+ dissect_msdp(next_tvb, pinfo, tree);
+ break;
+ case FSM_ERROR:
+ case HOLD_TIMER_EXPIRED:
+ case CEASE:
+ /* Do nothing. These contain no data */
+ break;
+ default:
+ if (tlv_len - 5 > 0)
+ proto_tree_add_text(tree, tvb, *offset, tlv_len - 5,
+ "<Unknown data>: %u bytes",
+ tlv_len -5);
+ *offset += tlv_len - 5;
+ break;
+ }
+
+ return;
+}
+
+void
+proto_register_msdp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_msdp_type,
+ { "Type", "msdp.type",
+ FT_UINT8, BASE_DEC, VALS(msdp_types), 0,
+ "MSDP TLV type", HFILL }
+ },
+ { &hf_msdp_length,
+ { "Length", "msdp.length",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "MSDP TLV Length", HFILL }
+ },
+ { &hf_msdp_sa_entry_count,
+ { "Entry Count", "msdp.sa.entry_count",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "MSDP SA Entry Count", HFILL }
+ },
+ { &hf_msdp_sa_rp_addr,
+ { "RP Address", "msdp.sa.rp_addr",
+ FT_IPv4, 0, NULL, 0,
+ "Active source's RP address", HFILL }
+ },
+ { &hf_msdp_sa_reserved,
+ { "Reserved", "msdp.sa.reserved",
+ FT_UINT24, BASE_HEX, NULL, 0,
+ "Transmitted as zeros and ignored by a receiver", HFILL }
+ },
+ { &hf_msdp_sa_sprefix_len,
+ { "Sprefix len", "msdp.sa.sprefix_len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "The route prefix length associated with source address", HFILL }
+ },
+ { &hf_msdp_sa_group_addr,
+ { "Group Address", "msdp.sa.group_addr",
+ FT_IPv4, 0, NULL, 0,
+ "The group address the active source has sent data to", HFILL }
+ },
+ { &hf_msdp_sa_src_addr,
+ { "Source Address", "msdp.sa.src_addr",
+ FT_IPv4, 0, NULL, 0,
+ "The IP address of the active source", HFILL }
+ },
+ { &hf_msdp_sa_req_res,
+ { "Reserved", "msdp.sa_req.res",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "Transmitted as zeros and ignored by a receiver", HFILL }
+ },
+ { &hf_msdp_sa_req_group,
+ { "Group Address", "msdp.sa_req.group_addr",
+ FT_IPv4, 0, NULL, 0,
+ "The group address the MSDP peer is requesting", HFILL }
+ },
+ { &hf_msdp_not_o,
+ { "Open-bit", "msdp.not.o",
+ FT_UINT8, BASE_HEX, NULL, 0x80,
+ "If clear, the connection will be closed", HFILL }
+ },
+ { &hf_msdp_not_error,
+ { "Error Code", "msdp.not.error",
+ FT_UINT8, BASE_DEC, VALS(error_vals), 0x7F,
+ "Indicates the type of Notification", HFILL }
+ },
+ { &hf_msdp_not_error_sub,
+ { "Error subode", "msdp.not.error_sub",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Error subcode", HFILL }
+ },
+ { &hf_msdp_not_ipv4,
+ { "IPv4 address", "msdp.not.ipv4",
+ FT_IPv4, 0, NULL, 0,
+ "Group/RP/Source address in Notification messages", HFILL }
+ },
+ { &hf_msdp_not_res,
+ { "Reserved", "msdp.not.res",
+ FT_UINT24, BASE_HEX, NULL, 0,
+ "Reserved field in Notification messages", HFILL }
+ },
+ { &hf_msdp_not_entry_count,
+ { "Entry Count", "msdp.not.entry_count",
+ FT_UINT24, BASE_HEX, NULL, 0,
+ "Entry Count in Notification messages", HFILL }
+ },
+ { &hf_msdp_not_sprefix_len,
+ { "Sprefix len", "msdp.not.sprefix_len",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Source prefix length in Notification messages", HFILL }
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_msdp,
+ &ett_msdp_sa_entry,
+ &ett_msdp_sa_enc_data,
+ &ett_msdp_not_data,
+ };
+
+ proto_msdp = proto_register_protocol("Multicast Source Discovery Protocol",
+ "MSDP", "msdp");
+
+ proto_register_field_array(proto_msdp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_msdp(void)
+{
+ dissector_handle_t msdp_handle;
+
+ msdp_handle = create_dissector_handle(dissect_msdp, proto_msdp);
+ dissector_add("tcp.port", 639, msdp_handle);
+
+ ip_handle = find_dissector("ip");
+
+ return;
+}
diff --git a/epan/dissectors/packet-msn-messenger.c b/epan/dissectors/packet-msn-messenger.c
new file mode 100644
index 0000000000..1b12c13eac
--- /dev/null
+++ b/epan/dissectors/packet-msn-messenger.c
@@ -0,0 +1,153 @@
+/* packet-msn-messenger.c
+ * Routines for MSN Messenger Service packet dissection
+ * Copyright 2003, Chris Waters <chris@waters.co.nz>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+/*
+ * The now-expired Internet-Draft for the MSN Messenger 1.0 protocol
+ * can, as of the time of the writing of this comment, be found at:
+ *
+ * http://praya.sourceforge.net/draft-movva-msn-messenger-protocol-00.txt
+ *
+ * http://mono.es.gnome.org/imsharp/tutoriales/msn/appendixa.html
+ *
+ * http://www.hypothetic.org/docs/msn/ietf_draft.php
+ *
+ * http://babble.wundsam.net/docs/protocol-msn-im.txt
+ *
+ * Note that it's Yet Another FTP-Like Command/Response Protocol,
+ * so it arguably should be dissected as such, although you do have
+ * to worry about the MSG command, as only the first line of it
+ * should be parsed as a command, the rest should be parsed as the
+ * message body. We therefore leave "hf_msnms_command", "tokenlen",
+ * and "next_token", even though they're unused, as reminders that
+ * this should be done.
+ */
+
+static int proto_msnms = -1;
+/* static int hf_msnms_command = -1; */
+
+static gint ett_msnms = -1;
+
+static dissector_handle_t data_handle;
+
+#define TCP_PORT_MSNMS 1863
+
+static void
+dissect_msnms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *msnms_tree;
+ proto_item *ti;
+ gint offset = 0;
+ const guchar *line;
+ gint next_offset;
+ int linelen;
+ /* int tokenlen; */
+ /* const guchar *next_token; */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSNMS");
+
+ /*
+ * Find the end of the first line.
+ *
+ * Note that "tvb_find_line_end()" will return a value that is
+ * not longer than what's in the buffer, so the "tvb_get_ptr()"
+ * call won't throw an exception.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ line = tvb_get_ptr(tvb, offset, linelen);
+
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary.
+ */
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ format_text(line, linelen));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_msnms, tvb, offset, -1,
+ FALSE);
+ msnms_tree = proto_item_add_subtree(ti, ett_msnms);
+
+ /*
+ * Show the rest of the packet as text,
+ * a line at a time.
+ */
+ while (tvb_offset_exists(tvb, offset)) {
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1,
+ &next_offset, FALSE);
+
+ /*
+ * Put this line.
+ */
+ proto_tree_add_text(msnms_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ offset = next_offset;
+ }
+ }
+}
+
+void
+proto_register_msnms(void)
+{
+ static gint *ett[] = {
+ &ett_msnms,
+ };
+
+ proto_msnms = proto_register_protocol("MSN Messenger Service", "MSNMS", "msnms");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_msnms(void)
+{
+ dissector_handle_t msnms_handle;
+
+ msnms_handle = create_dissector_handle(dissect_msnms, proto_msnms);
+ dissector_add("tcp.port", TCP_PORT_MSNMS, msnms_handle);
+ data_handle = find_dissector("data");
+ /*
+ * For MSN Messenger Protocol over HTTP
+ */
+ dissector_add_string("media_type", "application/x-msn-messenger", msnms_handle);
+}
diff --git a/epan/dissectors/packet-msnip.c b/epan/dissectors/packet-msnip.c
new file mode 100644
index 0000000000..e0ec3f0c85
--- /dev/null
+++ b/epan/dissectors/packet-msnip.c
@@ -0,0 +1,334 @@
+/* packet-msnip.c 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Routines for IGMP/MSNIP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+
+
+ MSNIP
+ code
+
+ 0x23 x
+ 0x24 x
+ 0x25 x
+
+ MSNIP " Multicast Source Notification of Interest Protocol
+ Defined in draft-ietf-idmr-igmp-msnip-00.txt
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "packet-igmp.h"
+#include "packet-msnip.h"
+
+
+static int proto_msnip = -1;
+static int hf_checksum = -1;
+static int hf_checksum_bad = -1;
+static int hf_type = -1;
+static int hf_count = -1;
+static int hf_holdtime = -1;
+static int hf_groups = -1;
+static int hf_maddr = -1;
+static int hf_mask = -1;
+static int hf_holdtime16 = -1;
+static int hf_genid = -1;
+static int hf_rec_type = -1;
+
+static int ett_msnip = -1;
+static int ett_groups = -1;
+
+
+#define MSNIP_GM 0x23
+#define MSNIP_IS 0x24
+#define MSNIP_RMR 0x25
+static const value_string msnip_types[] = {
+ {MSNIP_GM, "Multicast Group Map"},
+ {MSNIP_IS, "Multicast Interest Solicitation"},
+ {MSNIP_RMR, "Multicast Receiver Membership Report"},
+ {0, NULL}
+};
+
+#define MSNIP_RECTYPE_TRANSMIT 1
+#define MSNIP_RECTYPE_HOLD 2
+static const value_string msnip_rec_types[] = {
+ {MSNIP_RECTYPE_TRANSMIT, "Request to start transmitting group"},
+ {MSNIP_RECTYPE_HOLD, "Request to hold transmitting group"},
+ {0, NULL}
+};
+
+static int
+dissect_msnip_rmr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ guint8 count;
+
+ /* group count */
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(parent_tree, hf_count, tvb, offset, 1, count);
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ while (count--) {
+ proto_tree *tree;
+ proto_item *item;
+ guint8 rec_type;
+ guint32 maddr;
+ int old_offset = offset;
+
+ item = proto_tree_add_item(parent_tree, hf_groups,
+ tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_groups);
+
+ /* record type */
+ rec_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_rec_type, tvb, offset, 1, rec_type);
+ offset += 1;
+
+ /* skip 3 unused bytes */
+ offset += 3;
+
+ /* multicast group */
+ tvb_memcpy(tvb, (guint8 *)&maddr, offset, 4);
+ proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4,
+ maddr);
+ offset += 4;
+
+ if (item) {
+ proto_item_set_text(item,"Group: %s %s",
+ ip_to_str((guint8 *)&maddr),
+ val_to_str(rec_type, msnip_rec_types,
+ "Unknown Type:0x%02x"));
+
+ proto_item_set_len(item, offset-old_offset);
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_msnip_is(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+
+ /* skip reserved byte */
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ /* 16 bit holdtime */
+ proto_tree_add_uint(parent_tree, hf_holdtime16, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ /* Generation ID */
+ proto_tree_add_uint(parent_tree, hf_genid, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ return offset;
+}
+
+
+static int
+dissect_msnip_gm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ guint8 count;
+
+ /* group count */
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(parent_tree, hf_count, tvb, offset, 1, count);
+ offset += 1;
+
+ /* checksum */
+ igmp_checksum(parent_tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
+
+ /* holdtime */
+ proto_tree_add_uint(parent_tree, hf_holdtime, tvb, offset, 4, count);
+ offset += 4;
+
+ while (count--) {
+ proto_tree *tree;
+ proto_item *item;
+ guint32 maddr;
+ guint8 masklen;
+ int old_offset = offset;
+
+ item = proto_tree_add_item(parent_tree, hf_groups,
+ tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_groups);
+
+ /* multicast group */
+ tvb_memcpy(tvb, (guint8 *)&maddr, offset, 4);
+ proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4,
+ maddr);
+ offset += 4;
+
+ /* mask length */
+ masklen = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_mask, tvb,
+ offset, 1, masklen);
+ offset += 1;
+
+ /* skip 3 unused bytes */
+ offset += 3;
+
+ if (item) {
+ proto_item_set_text(item,"Group: %s/%d",
+ ip_to_str((guint8 *)&maddr), masklen);
+
+ proto_item_set_len(item, offset-old_offset);
+ }
+ }
+
+ return offset;
+}
+
+
+/* This function is only called from the IGMP dissector */
+int
+dissect_msnip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree;
+ proto_item *item;
+ guint8 type;
+
+ if (!proto_is_protocol_enabled(find_protocol_by_id(proto_msnip))) {
+ /* we are not enabled, skip entire packet to be nice
+ to the igmp layer. (so clicking on IGMP will display the data)
+ */
+ return offset+tvb_length_remaining(tvb, offset);
+ }
+
+ item = proto_tree_add_item(parent_tree, proto_msnip, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_msnip);
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSNIP");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+
+ type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s",val_to_str(type, msnip_types,
+ "Unknown Type:0x%02x"));
+ }
+
+ /* type of command */
+ proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type);
+ offset += 1;
+
+ switch (type) {
+ case MSNIP_GM:
+ offset = dissect_msnip_gm(tvb, pinfo, tree, offset);
+ break;
+ case MSNIP_IS:
+ offset = dissect_msnip_is(tvb, pinfo, tree, offset);
+ break;
+ case MSNIP_RMR:
+ offset = dissect_msnip_rmr(tvb, pinfo, tree, offset);
+ break;
+ }
+
+ if (item) {
+ proto_item_set_len(item, offset);
+ }
+
+ return offset;
+}
+
+
+void
+proto_register_msnip(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_type,
+ { "Type", "msnip.type", FT_UINT8, BASE_HEX,
+ VALS(msnip_types), 0, "MSNIP Packet Type", HFILL }},
+
+ { &hf_checksum,
+ { "Checksum", "msnip.checksum", FT_UINT16, BASE_HEX,
+ NULL, 0, "MSNIP Checksum", HFILL }},
+
+ { &hf_checksum_bad,
+ { "Bad Checksum", "msnip.checksum_bad", FT_BOOLEAN, BASE_NONE,
+ NULL, 0, "Bad MSNIP Checksum", HFILL }},
+
+ { &hf_count,
+ { "Count", "msnip.count", FT_UINT8, BASE_DEC,
+ NULL, 0, "MSNIP Number of groups", HFILL }},
+
+ { &hf_holdtime,
+ { "Holdtime", "msnip.holdtime", FT_UINT32, BASE_DEC,
+ NULL, 0, "MSNIP Holdtime in seconds", HFILL }},
+
+ { &hf_groups,
+ { "Groups", "msnip.groups", FT_NONE, BASE_NONE,
+ NULL, 0, "MSNIP Groups", HFILL }},
+
+ { &hf_maddr,
+ { "Multicast group", "msnip.maddr", FT_IPv4, BASE_NONE,
+ NULL, 0, "MSNIP Multicast Group", HFILL }},
+
+ { &hf_mask,
+ { "Netmask", "msnip.netmask", FT_UINT8, BASE_DEC,
+ NULL, 0, "MSNIP Netmask", HFILL }},
+
+ { &hf_holdtime16,
+ { "Holdtime", "msnip.holdtime16", FT_UINT16, BASE_DEC,
+ NULL, 0, "MSNIP Holdtime in seconds", HFILL }},
+
+ { &hf_genid,
+ { "Generation ID", "msnip.genid", FT_UINT16, BASE_DEC,
+ NULL, 0, "MSNIP Generation ID", HFILL }},
+
+ { &hf_rec_type,
+ { "Record Type", "msnip.rec_type", FT_UINT8, BASE_DEC,
+ VALS(msnip_rec_types), 0, "MSNIP Record Type", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_msnip,
+ &ett_groups,
+ };
+
+ proto_msnip = proto_register_protocol("MSNIP: Multicast Source Notification of Interest Protocol",
+ "MSNIP", "msnip");
+ proto_register_field_array(proto_msnip, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
diff --git a/epan/dissectors/packet-msnip.h b/epan/dissectors/packet-msnip.h
new file mode 100644
index 0000000000..5cbd4bccd4
--- /dev/null
+++ b/epan/dissectors/packet-msnip.h
@@ -0,0 +1,31 @@
+/* packet-msnip.h 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Declarations of routines for IGMP/MSNIP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_MSNIP_H__
+#define __PACKET_MSNIP_H__
+
+int dissect_msnip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+
+#endif
+
diff --git a/epan/dissectors/packet-msproxy.c b/epan/dissectors/packet-msproxy.c
new file mode 100644
index 0000000000..b42d1f0a22
--- /dev/null
+++ b/epan/dissectors/packet-msproxy.c
@@ -0,0 +1,1291 @@
+/* packet-msproxy.c
+ * Routines for Microsoft Proxy packet dissection
+ * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * This was derived from the dante socks implementation source code.
+ * Most of the information came from common.h and msproxy_clientprotocol.c
+ *
+ * See http://www.inet.no/dante for more information
+ */
+
+/************************************************************************
+ * *
+ * Notes: These are possible command values. User input is welcome *
+ * *
+ * Command = 0x040a - Remote host closed connection (maybe ?? ) *
+ * Command = 0x0411 - Remote host closed connection *
+ * Command = 0x0413 - Local host closed connection or SYN worked *
+ * *
+ ************************************************************************/
+
+
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include <epan/conversation.h>
+
+#include "packet-tcp.h"
+#include "packet-udp.h"
+
+extern void udp_hash_add(guint16 proto,
+ void (*dissect)(const guchar *, int, frame_data *, proto_tree *));
+
+
+static int proto_msproxy = -1;
+
+static int ett_msproxy = -1;
+static int ett_msproxy_name = -1;
+
+static int hf_msproxy_cmd = -1;
+static int hf_msproxy_clntport = -1;
+
+static int hf_msproxy_dstaddr = -1;
+
+static int hf_msproxy_srcport = -1;
+static int hf_msproxy_dstport = -1;
+static int hf_msproxy_serverport = -1;
+static int hf_msproxy_serveraddr = -1;
+static int hf_msproxy_bindport = -1;
+static int hf_msproxy_bindaddr = -1;
+static int hf_msproxy_boundport = -1;
+static int hf_msproxy_bind_id = -1;
+static int hf_msproxy_resolvaddr = -1;
+
+static int hf_msproxy_server_int_addr = -1;
+static int hf_msproxy_server_int_port = -1;
+static int hf_msproxy_server_ext_addr = -1;
+static int hf_msproxy_server_ext_port = -1;
+
+static dissector_handle_t msproxy_sub_handle;
+
+
+#define UDP_PORT_MSPROXY 1745
+
+#define N_MSPROXY_HELLO 0x05 /* packet 1 from client */
+#define N_MSPROXY_ACK 0x10 /* packet 1 from server */
+#define N_MSPROXY_USERINFO_ACK 0x04 /* packet 2 from server */
+#define N_MSPROXY_AUTH 0x47 /* packet 3 from client */
+#define N_MSPROXY_RESOLVE 0x07 /* Resolve request */
+
+
+/*$$$ 0x0500 was dante value, I see 0x05ff and 0x0500 */
+
+#define MSPROXY_HELLO 0x0500
+#define MSPROXY_HELLO_2 0x05ff
+
+#define MSPROXY_HELLO_ACK 0x1000
+
+#define MSPROXY_USERINFO 0x1000
+#define MSPROXY_USERINFO_ACK 0x0400
+
+#define MSPROXY_AUTH 0x4700
+#define MSPROXY_AUTH_1_ACK 0x4714
+#define MSPROXY_AUTH_2 0x4701
+#define MSPROXY_AUTH_2_ACK 0x4715
+#define MSPROXY_AUTH_2_ACK2 0x4716
+
+#define MSPROXY_RESOLVE 0x070d
+#define MSPROXY_RESOLVE_ACK 0x070f
+
+#define MSPROXY_BIND 0x0704
+#define MSPROXY_BIND_ACK 0x0706
+
+#define MSPROXY_TCP_BIND 0x0707
+#define MSPROXY_TCP_BIND_ACK 0x0708
+
+#define MSPROXY_LISTEN 0x0406
+
+#define MSPROXY_BINDINFO 0x0709
+
+#define MSPROXY_BINDINFO_ACK 0x070a
+
+#define MSPROXY_CONNECT 0x071e
+#define MSPROXY_CONNECT_ACK 0x0703
+
+#define MSPROXY_UDPASSOCIATE 0x0705
+#define MSPROXY_UDPASSOCIATE_ACK 0x0706
+
+#define MSPROXY_UDP_BIND_REQ 0x070b
+
+#define MSPROXY_CONNECTED 0x042c
+#define MSPROXY_SESSIONEND 0x251e
+
+#define MSPROXY_BIND_AUTHFAILED 0x0804
+#define MSPROXY_CONNECT_AUTHFAILED 0x081e
+#define MSPROXY_CONNREFUSED 0x4 /* low 12 bits seem to vary. */
+
+#define FROM_SERVER 1 /* direction of packet data for get_msproxy_cmd_name */
+#define FROM_CLIENT 0
+
+
+
+
+/*$$$ should this be the same as redirect_entry_t ?? */
+/* then the add_conversation could just copy the structure */
+/* using the same allocation (instance for you object guys) */
+/* wouldn't work because there may be multiple child conversations */
+/* from the same MSProxy conversation */
+
+typedef struct {
+ guint32 dst_addr;
+ guint32 clnt_port;
+ guint32 dst_port;
+ guint32 server_int_port;
+ int proto;
+}hash_entry_t;
+
+
+/************** conversation hash stuff ***************/
+
+#define hash_init_count 20
+#define hash_val_length (sizeof(hash_entry_t))
+
+static GMemChunk *vals = NULL;
+
+typedef struct {
+ guint32 remote_addr;
+ guint32 clnt_port;
+ guint32 server_int_port;
+ guint32 remote_port;
+ int proto;
+}redirect_entry_t;
+
+
+/************** negotiated conversation hash stuff ***************/
+
+#define redirect_init_count 20
+#define redirect_val_length (sizeof(redirect_entry_t))
+
+static GMemChunk *redirect_vals = NULL;
+
+
+static guint32 last_row= 0; /* used to see if packet is new */
+
+static void msproxy_sub_dissector( tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree) {
+
+/* Conversation dissector called from TCP or UDP dissector. Decode and */
+/* display the msproxy header, the pass the rest of the data to the tcp */
+/* or udp port decode routine to handle the payload. */
+
+ guint32 *ptr;
+ redirect_entry_t *redirect_info;
+ conversation_t *conversation;
+ proto_tree *msp_tree;
+ proto_item *ti;
+
+ conversation = find_conversation( &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+
+ g_assert( conversation); /* should always find a conversation */
+
+ redirect_info = conversation_get_proto_data(conversation,
+ proto_msproxy);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MS Proxy");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO,
+ (( redirect_info->proto == PT_TCP) ? "TCP stream" :
+ "UDP packets"));
+
+ if ( tree) {
+ ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0, 0,
+ FALSE );
+
+ msp_tree = proto_item_add_subtree(ti, ett_msproxy);
+
+ proto_tree_add_uint( msp_tree, hf_msproxy_dstport, tvb, 0, 0,
+ redirect_info->remote_port);
+
+ proto_tree_add_ipv4( msp_tree, hf_msproxy_dstaddr, tvb, 0, 0,
+ redirect_info->remote_addr);
+
+ }
+
+/* set pinfo->{src/dst port} and call the UDP sub-dissector lookup */
+
+ if ( pinfo->srcport == redirect_info->clnt_port)
+ ptr = &pinfo->destport;
+ else
+ ptr = &pinfo->srcport;
+
+ *ptr = redirect_info->remote_port;
+
+ if ( redirect_info->proto == PT_TCP)
+ decode_tcp_ports( tvb, 0, pinfo, tree, pinfo->srcport,
+ pinfo->destport);
+ else
+ decode_udp_ports( tvb, 0, pinfo, tree, pinfo->srcport,
+ pinfo->destport, -1);
+
+ *ptr = redirect_info->server_int_port;
+}
+
+
+
+static void add_msproxy_conversation( packet_info *pinfo,
+ hash_entry_t *hash_info){
+
+/* check to see if a conversation already exists, if it does assume */
+/* it's our conversation and quit. Otherwise create a new conversation. */
+/* Load the conversation dissector to our dissector and load the */
+/* conversation data structure with the info needed to call the TCP or */
+/* UDP port decoder. */
+
+/* NOTE: Currently this assume that the conversation will be created */
+/* during a packet from the server. If that changes, pinfo->src */
+/* and pinfo->dst will not be correct and this routine will have */
+/* to change. */
+
+ conversation_t *conversation;
+ redirect_entry_t *new_conv_info;
+
+ if (pinfo->fd->flags.visited) {
+ /*
+ * We've already processed this frame once, so we
+ * should already have done this.
+ */
+ return;
+ }
+
+ conversation = find_conversation( &pinfo->src,
+ &pinfo->dst, hash_info->proto, hash_info->server_int_port,
+ hash_info->clnt_port, 0);
+
+ if ( !conversation) {
+ conversation = conversation_new( &pinfo->src, &pinfo->dst,
+ hash_info->proto, hash_info->server_int_port,
+ hash_info->clnt_port, 0);
+ }
+ conversation_set_dissector(conversation, msproxy_sub_handle);
+
+ new_conv_info = g_mem_chunk_alloc(redirect_vals);
+
+ new_conv_info->remote_addr = hash_info->dst_addr;
+ new_conv_info->clnt_port = hash_info->clnt_port;
+ new_conv_info->remote_port = hash_info->dst_port;
+ new_conv_info->server_int_port = hash_info->server_int_port;
+ new_conv_info->proto = hash_info->proto;
+
+ conversation_add_proto_data(conversation, proto_msproxy,
+ new_conv_info);
+}
+
+
+
+static int display_application_name(tvbuff_t *tvb, int offset,
+ proto_tree *tree) {
+
+/* display the application name in the proto tree. */
+
+/* NOTE: this routine assumes that the tree pointer is valid (not NULL) */
+
+ int length;
+
+ length = tvb_strnlen( tvb, offset, 255);
+ proto_tree_add_text( tree, tvb, offset, length, "Application: %.*s",
+ length, tvb_get_ptr( tvb, offset, length));
+
+ return length;
+}
+
+
+static char *get_msproxy_cmd_name( int cmd, int direction) {
+
+/* return the command name string for cmd */
+
+ switch (cmd){
+ case MSPROXY_HELLO_2:
+ case MSPROXY_HELLO: return "Hello";
+
+/* MSPROXY_HELLO_ACK & MSPROXY_USERINFO have the same value (0x1000). */
+/* So use the direction flag to determine which to use. */
+
+ case MSPROXY_USERINFO:
+ if ( direction == FROM_SERVER)
+ return "Hello Acknowledge";
+ else
+ return "User Info";
+ case MSPROXY_USERINFO_ACK: return "User Info Acknowledge";
+ case MSPROXY_AUTH: return "Authentication";
+ case MSPROXY_AUTH_1_ACK: return "Authentication Acknowledge";
+ case MSPROXY_AUTH_2: return "Authentication 2";
+ case MSPROXY_AUTH_2_ACK: return "Authentication 2 Acknowledge";
+ case MSPROXY_RESOLVE: return "Resolve";
+ case MSPROXY_RESOLVE_ACK: return "Resolve Acknowledge";
+ case MSPROXY_BIND: return "Bind";
+ case MSPROXY_TCP_BIND: return "TCP Bind";
+ case MSPROXY_TCP_BIND_ACK: return "TCP Bind Acknowledge";
+ case MSPROXY_LISTEN: return "Listen";
+ case MSPROXY_BINDINFO: return "Bind Info";
+ case MSPROXY_BINDINFO_ACK: return "Bind Info Acknowledge";
+ case MSPROXY_CONNECT: return "Connect";
+ case MSPROXY_CONNECT_ACK: return "Connect Acknowledge";
+ case MSPROXY_UDPASSOCIATE: return "UDP Associate";
+ case MSPROXY_UDP_BIND_REQ: return "UDP Bind";
+ case MSPROXY_UDPASSOCIATE_ACK: return "Bind or Associate Acknowledge";
+ case MSPROXY_CONNECTED: return "Connected";
+ case MSPROXY_SESSIONEND: return "Session End";
+
+ default: return "Unknown";
+ }
+}
+
+
+
+static void dissect_user_info_2(tvbuff_t *tvb, int offset,
+ proto_tree *tree) {
+
+/* decode the user, application, computer name */
+
+
+ int length;
+
+ if ( tree) {
+ length = tvb_strnlen( tvb, offset, 255);
+ if (length == -1)
+ return;
+ proto_tree_add_text( tree, tvb, offset, length + 1,
+ "User name: %.*s", length,
+ tvb_get_ptr( tvb, offset, length));
+ offset += length + 2;
+
+ length = tvb_strnlen( tvb, offset, 255);
+ if (length == -1)
+ return;
+ proto_tree_add_text( tree, tvb, offset, length + 1,
+ "Application name: %.*s", length,
+ tvb_get_ptr( tvb, offset, length));
+ offset += length + 1;
+
+ length = tvb_strnlen( tvb, offset, 255);
+ if (length == -1)
+ return;
+ proto_tree_add_text( tree, tvb, offset, length + 1,
+ "Client computer name: %.*s", length,
+ tvb_get_ptr( tvb, offset, length));
+ }
+}
+
+
+
+static void dissect_msproxy_request_1(tvbuff_t *tvb, int offset,
+ proto_tree *tree) {
+
+/* decode the request _1 structure */
+
+
+ offset += 182;
+
+ dissect_user_info_2( tvb, offset, tree);
+
+}
+
+
+
+static void dissect_bind(tvbuff_t *tvb, int offset,
+ proto_tree *tree, hash_entry_t *conv_info) {
+
+/* decode the bind request */
+
+ offset += 18;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_bindaddr, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_bindport, tvb, offset, 2,
+ FALSE);
+ offset += 6;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_clntport, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
+ offset += 6;
+
+ if ( tree){
+ proto_tree_add_item( tree, hf_msproxy_boundport, tvb, offset, 2,
+ FALSE);
+
+ offset += 82;
+ display_application_name( tvb, offset, tree);
+ }
+}
+
+
+
+static void dissect_auth(tvbuff_t *tvb, int offset,
+ proto_tree *tree) {
+
+/* decode the authorization request */
+
+ if ( tree) {
+ offset += 134;
+
+ proto_tree_add_text( tree, tvb, offset, 7, "NTLMSSP signature: %.7s",
+ tvb_get_ptr( tvb, offset, 7));
+ offset += 7;
+ }
+}
+
+
+
+static void dissect_tcp_bind(tvbuff_t *tvb, int offset,
+ proto_tree *tree, hash_entry_t *conv_info) {
+
+/* decode the bind packet. Set the protocol type in the conversation */
+/* information so the bind_info can use it to create the payload */
+/* dissector. */
+
+
+ conv_info->proto = PT_TCP;
+
+ if ( tree) {
+ offset += 6;
+
+ proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
+ FALSE);
+ offset += 16;
+
+ proto_tree_add_item( tree, hf_msproxy_boundport, tvb, offset, 2,
+ FALSE);
+
+ offset += 96;
+ display_application_name( tvb, offset, tree);
+ }
+}
+
+
+static void dissect_request_connect(tvbuff_t *tvb, int offset,
+ proto_tree *tree, hash_entry_t *conv_info) {
+
+/* decode the connect request, display */
+
+ conv_info->proto = PT_TCP;
+
+ offset += 20;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
+ FALSE);
+
+ conv_info->dst_port = tvb_get_ntohs( tvb, offset);
+ offset += 2;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
+ FALSE);
+
+ tvb_memcpy( tvb, (guint8 *)&conv_info->dst_addr, offset, sizeof( guint32));
+
+ offset += 12;
+
+ conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
+
+ if ( tree){
+ proto_tree_add_uint( tree, hf_msproxy_clntport, tvb, offset, 2,
+ conv_info->clnt_port);
+
+ offset += 84;
+
+ display_application_name( tvb, offset, tree);
+ }
+}
+
+
+static void dissect_bind_info_ack(tvbuff_t *tvb, int offset, proto_tree *tree) {
+
+/* decode the client bind info ack */
+
+
+ if ( tree){
+ offset += 6;
+
+ proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
+ FALSE);
+ offset += 14;
+
+ proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
+ FALSE);
+ offset += 12;
+
+ proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
+ offset, 2, FALSE);
+ offset += 4;
+
+ proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
+ offset, 4, FALSE);
+
+ offset += 78;
+ display_application_name( tvb, offset, tree);
+ }
+}
+
+
+static void dissect_request_resolve(tvbuff_t *tvb, int offset,
+ proto_tree *tree) {
+
+/* dissect the request resolve structure */
+/* display a string with a length, characters encoding */
+/* they are displayed under a tree with the name in Label variable */
+/* return the length of the string and the length byte */
+
+ proto_tree *name_tree;
+ proto_item *ti;
+
+ int length = tvb_get_guint8( tvb, offset);
+
+ if ( tree){
+ ti = proto_tree_add_text(tree, tvb, offset, length + 1,
+ "Host Name: %.*s", length,
+ tvb_get_ptr( tvb, offset + 18, length));
+
+ name_tree = proto_item_add_subtree(ti, ett_msproxy_name);
+
+ proto_tree_add_text( name_tree, tvb, offset, 1, "Length: %d",
+ length);
+
+ ++offset;
+ offset += 17;
+
+ proto_tree_add_text( name_tree, tvb, offset, length, "String: %s",
+ tvb_get_ptr( tvb, offset, length));
+ }
+}
+
+
+
+static void dissect_udp_bind(tvbuff_t *tvb, int offset,
+ proto_tree *tree, hash_entry_t *conv_info) {
+
+/* Dissect the udp bind request. Load the protocol id (PT_UDP) and the */
+/* remote address so bind_info can use it to create conversation */
+/* dissector. */
+
+ conv_info->proto = PT_UDP;
+
+
+ offset += 8;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
+ FALSE);
+ offset += 12;
+
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_dstport, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
+ FALSE);
+
+ offset += 96;
+
+ if ( tree)
+ display_application_name( tvb, offset, tree);
+}
+
+
+static void dissect_udp_assoc(tvbuff_t *tvb, int offset,
+ proto_tree *tree, hash_entry_t *conv_info) {
+
+/* dissect the udp associate request. And load client port into */
+/* conversation data structure for later. */
+
+
+ offset += 28;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_clntport, tvb, offset, 2,
+ FALSE);
+
+ conv_info->clnt_port = tvb_get_ntohs( tvb, offset);
+
+ offset += 90;
+
+ if ( tree)
+ display_application_name( tvb, offset, tree);
+}
+
+
+static void dissect_msproxy_request(tvbuff_t *tvb,
+ proto_tree *tree, hash_entry_t *conv_info) {
+
+ int offset = 0;
+ int cmd;
+
+ if ( tree) {
+ proto_tree_add_text( tree, tvb, offset, 4, "Client id: 0x%0x",
+ tvb_get_letohl( tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text( tree, tvb, offset, 4, "Version: 0x%04x",
+ tvb_get_letohl( tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text( tree, tvb, offset, 4, "Server id: 0x%0x",
+ tvb_get_letohl( tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text( tree, tvb, offset, 1, "Server ack: %u",
+ tvb_get_guint8( tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text( tree, tvb, offset, 1, "Sequence Number: %u",
+ tvb_get_guint8( tvb, offset));
+ offset += 8;
+
+ proto_tree_add_text( tree, tvb, offset, 4, "RWSP signature: %.4s",
+ tvb_get_ptr( tvb, offset, 4));
+ offset += 12;
+ }
+ else /* no tree */
+ offset += 36;
+
+ cmd = tvb_get_ntohs( tvb, offset);
+
+ if ( tree)
+ proto_tree_add_uint_format( tree, hf_msproxy_cmd, tvb, offset, 2,
+ cmd, "Command: 0x%02x (%s)", cmd,
+ get_msproxy_cmd_name( cmd, FROM_CLIENT));
+
+ offset += 2;
+
+ switch (cmd){
+ case MSPROXY_AUTH:
+ dissect_auth( tvb, offset, tree);
+ break;
+
+ case MSPROXY_BIND:
+ dissect_bind( tvb, offset, tree, conv_info);
+ break;
+
+ case MSPROXY_UDP_BIND_REQ:
+ dissect_udp_bind( tvb, offset, tree, conv_info);
+ break;
+
+ case MSPROXY_AUTH_2: /*$$ this is probably wrong place for this */
+ case MSPROXY_TCP_BIND:
+ dissect_tcp_bind( tvb, offset, tree, conv_info);
+ break;
+
+ case MSPROXY_RESOLVE:
+ dissect_request_resolve( tvb, offset, tree);
+ break;
+
+ case MSPROXY_CONNECT:
+ case MSPROXY_LISTEN:
+ dissect_request_connect( tvb, offset, tree,
+ conv_info);
+ break;
+
+ case MSPROXY_BINDINFO_ACK:
+ dissect_bind_info_ack( tvb, offset, tree);
+ break;
+
+ case MSPROXY_HELLO:
+ case MSPROXY_HELLO_2:
+ dissect_msproxy_request_1( tvb, offset, tree);
+ break;
+
+ case MSPROXY_UDPASSOCIATE:
+ dissect_udp_assoc( tvb, offset, tree, conv_info);
+ break;
+ default:
+ if ( tree)
+ proto_tree_add_text( tree, tvb, offset, 0,
+ "Unhandled request command (report this, please)");
+ }
+}
+
+
+
+static void dissect_hello_ack(tvbuff_t *tvb, int offset, proto_tree *tree) {
+
+/* decode the hello acknowledge packet */
+
+ offset += 60;
+
+ if ( tree) {
+ proto_tree_add_item( tree, hf_msproxy_serverport, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ proto_tree_add_item( tree, hf_msproxy_serveraddr, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ }
+}
+
+
+
+/* XXX - implement me */
+static void dissect_user_info_ack(tvbuff_t *tvb _U_, int offset,
+ proto_tree *tree _U_) {
+
+/* decode the response _2 structure */
+
+ offset += 18;
+
+ offset += 2;
+
+}
+
+
+
+static void dissect_udpassociate_ack(tvbuff_t *tvb, int offset,
+ proto_tree *tree) {
+
+ offset += 6;
+
+ if ( tree) {
+ proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
+ FALSE);
+ offset += 14;
+
+ proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
+ offset, 4, FALSE);
+
+ offset += 96;
+ display_application_name( tvb, offset, tree);
+ }
+}
+
+
+
+static void dissect_auth_1_ack(tvbuff_t *tvb, int offset,
+ proto_tree *tree) {
+
+ offset += 134;
+ if ( tree) {
+ proto_tree_add_text( tree, tvb, offset, 7, "NTLMSSP signature: %.7s",
+ tvb_get_ptr( tvb, offset, 7));
+ offset += 48;
+
+ /* XXX - always 255? */
+ proto_tree_add_text( tree, tvb, offset, 255, "NT domain: %.255s",
+ tvb_get_ptr( tvb, offset, 255));
+ }
+}
+
+
+
+/* XXX - implement me */
+static void dissect_msproxy_response_4( tvbuff_t *tvb _U_, int offset,
+ proto_tree *tree _U_) {
+
+/* decode the response _4 structure */
+
+ offset += 134;
+}
+
+
+
+static void dissect_connect_ack( tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, hash_entry_t *conv_info) {
+
+/* decode the connect ack packet */
+ offset += 20;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_server_int_port, tvb,
+ offset, 2, FALSE);
+
+
+ conv_info->proto = PT_TCP;
+ conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
+ offset += 2;
+
+ if ( tree){
+ proto_tree_add_item( tree, hf_msproxy_server_int_addr, tvb,
+ offset, 4, FALSE);
+ offset += 14;
+
+ proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
+ offset, 4, FALSE);
+ offset += 80;
+
+ display_application_name( tvb, offset, tree);
+ }
+
+ add_msproxy_conversation( pinfo, conv_info);
+}
+
+
+
+static void dissect_tcp_bind_ack( tvbuff_t *tvb, int offset, proto_tree *tree) {
+
+/* decode the tcp bind */
+
+ if ( tree) {
+ offset += 6;
+
+ proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
+ FALSE);
+ offset += 16;
+
+ proto_tree_add_uint( tree, hf_msproxy_server_int_port, tvb,
+ offset, 2, FALSE);
+ offset += 6;
+
+ proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
+ offset, 4, FALSE);
+
+ offset += 88;
+
+ display_application_name( tvb, offset, tree);
+ }
+}
+
+
+
+static void dissect_bind_info( tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, hash_entry_t *conv_info) {
+
+/* decode the Bind info response from server */
+
+ offset += 6;
+
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_bind_id, tvb, offset, 4,
+ FALSE);
+ offset += 14;
+
+
+ conv_info->dst_port = tvb_get_ntohs( tvb, offset);
+ if ( tree)
+ proto_tree_add_uint( tree, hf_msproxy_dstport, tvb, offset, 2,
+ conv_info->dst_port);
+ offset += 2;
+
+ tvb_memcpy( tvb, (guint8 *)&conv_info->dst_addr, offset, sizeof( guint32));
+ if ( tree)
+ proto_tree_add_item( tree, hf_msproxy_dstaddr, tvb, offset, 4,
+ FALSE);
+ offset += 12;
+
+ conv_info->server_int_port = tvb_get_ntohs( tvb, offset);
+ if ( tree)
+ proto_tree_add_uint( tree, hf_msproxy_server_int_port, tvb,
+ offset, 2, conv_info->server_int_port);
+ offset += 4;
+
+ if ( tree) {
+ proto_tree_add_item( tree, hf_msproxy_server_ext_port, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item( tree, hf_msproxy_server_ext_addr, tvb,
+ offset, 4, FALSE);
+
+ offset += 78;
+ display_application_name( tvb, offset, tree);
+
+ }
+
+ add_msproxy_conversation( pinfo, conv_info);
+}
+
+
+
+static void dissect_resolve(tvbuff_t *tvb, int offset, proto_tree *tree) {
+
+/* dissect the response resolve structure */
+/* display a string with a length, characters encoding */
+/* they are displayed under a tree with the name in Label variable */
+/* return the length of the string and the length byte */
+
+ if ( tree) {
+ int addr_offset;
+
+ addr_offset = tvb_get_guint8( tvb, offset);
+
+ proto_tree_add_text( tree, tvb, offset, 1, "Address offset: %d",
+ addr_offset);
+
+ ++offset;
+
+ offset += 13;
+
+ offset += addr_offset;
+
+ proto_tree_add_item( tree, hf_msproxy_resolvaddr, tvb, offset, 4,
+ FALSE);
+ }
+}
+
+
+
+static void dissect_msproxy_response(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, hash_entry_t *conv_info) {
+
+ int offset = 0;
+ int cmd;
+
+ if ( tree) {
+ proto_tree_add_text( tree, tvb, offset, 4, "Client id: 0x%0x",
+ tvb_get_letohl( tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text( tree, tvb, offset, 4, "Version: 0x%04x",
+ tvb_get_letohl( tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text( tree, tvb, offset, 4, "Server id: 0x%04x",
+ tvb_get_letohl( tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text( tree, tvb, offset, 1, "Client ack: 0x%02x",
+ tvb_get_guint8( tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text( tree, tvb, offset, 1, "Sequence Number: 0x%02x",
+ tvb_get_guint8( tvb, offset));
+
+ offset += 8;
+
+ proto_tree_add_text( tree, tvb, offset, 4, "RWSP signature: %.4s",
+ tvb_get_ptr( tvb, offset, 4));
+
+ offset += 12;
+ }
+ else
+ offset += 36;
+
+ cmd = tvb_get_ntohs( tvb, offset);
+
+ if ( tree)
+ proto_tree_add_uint_format( tree, hf_msproxy_cmd, tvb, offset, 2,
+ cmd, "Command: 0x%02x (%s)", cmd,
+ get_msproxy_cmd_name( cmd, FROM_SERVER));
+ offset += 2;
+
+ switch (cmd) {
+ case MSPROXY_HELLO_ACK:
+ dissect_hello_ack( tvb, offset, tree);
+ break;
+
+ case MSPROXY_USERINFO_ACK:
+ dissect_user_info_ack( tvb, offset, tree);
+ break;
+
+ case MSPROXY_AUTH_1_ACK:
+ dissect_auth_1_ack( tvb, offset, tree);
+ break;
+
+/* this also handle the MSPROXY_BIND_ACK ??? check this */
+
+ case MSPROXY_UDPASSOCIATE_ACK:
+ dissect_udpassociate_ack( tvb, offset, tree);
+ break;
+
+ case MSPROXY_AUTH_2_ACK:
+ case MSPROXY_AUTH_2_ACK2:
+ dissect_msproxy_response_4( tvb, offset, tree);
+ break;
+
+ case MSPROXY_TCP_BIND_ACK:
+ dissect_tcp_bind_ack( tvb, offset, tree);
+ break;
+
+ case MSPROXY_CONNECT_ACK:
+ dissect_connect_ack( tvb, offset, pinfo, tree,
+ conv_info);
+ break;
+
+ case MSPROXY_BINDINFO:
+ dissect_bind_info( tvb, offset, pinfo, tree, conv_info);
+ break;
+
+ case MSPROXY_RESOLVE_ACK:
+ dissect_resolve( tvb, offset, tree);
+ break;
+
+ case MSPROXY_CONNECT_AUTHFAILED:
+ case MSPROXY_BIND_AUTHFAILED:
+ proto_tree_add_text( tree, tvb, offset, 0, "No know information (help wanted)");
+ break;
+
+ default:
+
+ if (tree &&
+ (((cmd >> 8) == MSPROXY_CONNREFUSED) ||
+ ((cmd >> 12) == MSPROXY_CONNREFUSED)))
+ proto_tree_add_text( tree, tvb, offset, 0,
+ "No know information (help wanted)");
+
+ else if ( tree)
+ proto_tree_add_text( tree, tvb, offset, 0,
+ "Unhandled response command (report this, please)");
+ }
+
+
+}
+
+
+
+static void dissect_msproxy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+
+
+ proto_tree *msproxy_tree = NULL;
+ proto_item *ti;
+ unsigned int cmd;
+
+
+ hash_entry_t *hash_info;
+ conversation_t *conversation;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSproxy");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ conversation = find_conversation( &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+
+ if ( !conversation) {
+ conversation = conversation_new( &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ hash_info = conversation_get_proto_data(conversation, proto_msproxy);
+ if ( !hash_info) {
+ hash_info = g_mem_chunk_alloc(vals);
+ conversation_add_proto_data(conversation, proto_msproxy,
+ hash_info);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+
+ cmd = tvb_get_ntohs( tvb, 36);
+
+ if ( pinfo->srcport == UDP_PORT_MSPROXY)
+ col_add_fstr( pinfo->cinfo, COL_INFO, "Server message: %s",
+ get_msproxy_cmd_name( cmd, FROM_SERVER));
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Client message: %s",
+ get_msproxy_cmd_name( cmd, FROM_CLIENT));
+
+ }
+
+ if (tree) { /* if proto tree, decode data */
+ ti = proto_tree_add_item( tree, proto_msproxy, tvb, 0, -1,
+ FALSE );
+
+ msproxy_tree = proto_item_add_subtree(ti, ett_msproxy);
+ }
+
+ if ( pinfo->srcport == UDP_PORT_MSPROXY)
+ dissect_msproxy_response( tvb, pinfo, msproxy_tree, hash_info);
+ else
+ dissect_msproxy_request( tvb, msproxy_tree, hash_info);
+}
+
+
+
+static void msproxy_reinit( void){
+
+/* Do the cleanup work when a new pass through the packet list is */
+/* performed. Reset the highest row seen counter and re-initialize the */
+/* conversation memory chunks. */
+
+ last_row = 0;
+
+ if (vals)
+ g_mem_chunk_destroy(vals);
+
+ vals = g_mem_chunk_new("msproxy_vals", hash_val_length,
+ hash_init_count * hash_val_length,
+ G_ALLOC_AND_FREE);
+
+ if (redirect_vals)
+ g_mem_chunk_destroy(redirect_vals);
+
+ redirect_vals = g_mem_chunk_new("msproxy_redirect_vals", redirect_val_length,
+ redirect_init_count * redirect_val_length,
+ G_ALLOC_AND_FREE);
+}
+
+
+
+void
+proto_register_msproxy( void){
+
+/* Prep the msproxy protocol, for now, just register it */
+
+ static gint *ett[] = {
+ &ett_msproxy,
+ &ett_msproxy_name
+ };
+ static hf_register_info hf[] = {
+
+ { &hf_msproxy_cmd,
+ { "Command", "msproxy.command", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL
+ }
+ },
+
+ { &hf_msproxy_dstaddr,
+ { "Destination Address", "msproxy.dstaddr", FT_IPv4, BASE_NONE, NULL,
+ 0x0, "", HFILL
+ }
+ },
+
+ { &hf_msproxy_srcport,
+ { "Source Port", "msproxy.srcport", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_dstport,
+ { "Destination Port", "msproxy.dstport", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_clntport,
+ { "Client Port", "msproxy.clntport", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_server_ext_addr,
+ { "Server External Address", "msproxy.server_ext_addr", FT_IPv4, BASE_NONE, NULL,
+ 0x0, "", HFILL
+ }
+ },
+
+ { &hf_msproxy_server_ext_port,
+ { "Server External Port", "msproxy.server_ext_port", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ },
+
+ { &hf_msproxy_server_int_addr,
+ { "Server Internal Address", "msproxy.server_int_addr", FT_IPv4, BASE_NONE, NULL,
+ 0x0, "", HFILL
+ }
+ },
+
+ { &hf_msproxy_server_int_port,
+ { "Server Internal Port", "msproxy.server_int_port", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_serverport,
+ { "Server Port", "msproxy.serverport", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_bindport,
+ { "Bind Port", "msproxy.bindport", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_boundport,
+ { "Bound Port", "msproxy.boundport", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_serveraddr,
+ { "Server Address", "msproxy.serveraddr", FT_IPv4, BASE_NONE, NULL,
+ 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_bindaddr,
+ { "Destination", "msproxy.bindaddr", FT_IPv4, BASE_NONE, NULL,
+ 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_bind_id,
+ { "Bound Port Id", "msproxy.bindid", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_msproxy_resolvaddr,
+ { "Address", "msproxy.resolvaddr", FT_IPv4, BASE_NONE, NULL,
+ 0x0, "", HFILL
+ }
+ }
+
+ };
+
+ proto_msproxy = proto_register_protocol( "MS Proxy Protocol",
+ "MS Proxy", "msproxy");
+
+ proto_register_field_array(proto_msproxy, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine( &msproxy_reinit); /* register re-init routine */
+
+ msproxy_sub_handle = create_dissector_handle(msproxy_sub_dissector,
+ proto_msproxy);
+}
+
+
+void
+proto_reg_handoff_msproxy(void) {
+
+ /* dissector install routine */
+
+ dissector_handle_t msproxy_handle;
+
+ msproxy_handle = create_dissector_handle(dissect_msproxy,
+ proto_msproxy);
+ dissector_add("udp.port", UDP_PORT_MSPROXY, msproxy_handle);
+}
diff --git a/epan/dissectors/packet-mtp2.c b/epan/dissectors/packet-mtp2.c
new file mode 100644
index 0000000000..9dfc559b6c
--- /dev/null
+++ b/epan/dissectors/packet-mtp2.c
@@ -0,0 +1,219 @@
+/* packet-mtp2.c
+ * Routines for MTP2 dissection
+ * It is hopefully (needs testing) compliant to
+ * ITU-T Q.703
+ *
+ * Copyright 2001, Michael Tuexen <tuexen [AT] fh-muenster.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-m2pa.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#define LITTLE_ENDIAN_BYTE_ORDER TRUE
+
+/* Initialize the protocol and registered fields */
+static int proto_mtp2 = -1;
+static int hf_mtp2_bsn = -1;
+static int hf_mtp2_bib = -1;
+static int hf_mtp2_fsn = -1;
+static int hf_mtp2_fib = -1;
+static int hf_mtp2_li = -1;
+static int hf_mtp2_spare = -1;
+static int hf_mtp2_sf = -1;
+static int hf_mtp2_long_sf = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_mtp2 = -1;
+
+static dissector_handle_t mtp3_handle;
+static int mtp3_proto_id;
+
+#define BSN_BIB_LENGTH 1
+#define FSN_FIB_LENGTH 1
+#define LI_LENGTH 1
+#define HEADER_LENGTH (BSN_BIB_LENGTH + FSN_FIB_LENGTH + LI_LENGTH)
+
+#define BSN_BIB_OFFSET 0
+#define FSN_FIB_OFFSET (BSN_BIB_OFFSET + BSN_BIB_LENGTH)
+#define LI_OFFSET (FSN_FIB_OFFSET + FSN_FIB_LENGTH)
+#define SIO_OFFSET (LI_OFFSET + LI_LENGTH)
+
+#define BSN_MASK 0x7f
+#define BIB_MASK 0x80
+#define FSN_MASK 0x7f
+#define FIB_MASK 0x80
+#define LI_MASK 0x3f
+#define SPARE_MASK 0xc0
+
+static void
+dissect_mtp2_header(tvbuff_t *su_tvb, proto_item *mtp2_tree)
+{
+ if (mtp2_tree) {
+ proto_tree_add_item(mtp2_tree, hf_mtp2_bsn, su_tvb, BSN_BIB_OFFSET, BSN_BIB_LENGTH, LITTLE_ENDIAN_BYTE_ORDER);
+ proto_tree_add_item(mtp2_tree, hf_mtp2_bib, su_tvb, BSN_BIB_OFFSET, BSN_BIB_LENGTH, LITTLE_ENDIAN_BYTE_ORDER);
+ proto_tree_add_item(mtp2_tree, hf_mtp2_fsn, su_tvb, FSN_FIB_OFFSET, FSN_FIB_LENGTH, LITTLE_ENDIAN_BYTE_ORDER);
+ proto_tree_add_item(mtp2_tree, hf_mtp2_fib, su_tvb, FSN_FIB_OFFSET, FSN_FIB_LENGTH, LITTLE_ENDIAN_BYTE_ORDER);
+ proto_tree_add_item(mtp2_tree, hf_mtp2_li, su_tvb, LI_OFFSET, LI_LENGTH, LITTLE_ENDIAN_BYTE_ORDER);
+ proto_tree_add_item(mtp2_tree, hf_mtp2_spare, su_tvb, LI_OFFSET, LI_LENGTH, LITTLE_ENDIAN_BYTE_ORDER);
+ }
+}
+
+static void
+dissect_mtp2_fisu(packet_info *pinfo)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "FISU ");
+}
+
+static const value_string status_field_vals[] = {
+ { 0x0, "Status Indication O" },
+ { 0x1, "Status Indication N" },
+ { 0x2, "Status Indication E" },
+ { 0x3, "Status Indication OS" },
+ { 0x4, "Status Indication PO" },
+ { 0x5, "Status Indication BO" },
+ { 0, NULL}
+};
+
+#define SF_OFFSET (LI_OFFSET + LI_LENGTH)
+#define SF_LENGTH 1
+#define LONG_SF_LENGTH 2
+
+static void
+dissect_mtp2_lssu(tvbuff_t *su_tvb, packet_info *pinfo, proto_item *mtp2_tree)
+{
+ guint8 li;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "LSSU ");
+
+ if (mtp2_tree) {
+ li = tvb_get_guint8(su_tvb, LI_OFFSET);
+ if ((li & LI_MASK) == 1)
+ proto_tree_add_item(mtp2_tree, hf_mtp2_sf, su_tvb, SF_OFFSET, SF_LENGTH, LITTLE_ENDIAN_BYTE_ORDER);
+ else
+ proto_tree_add_item(mtp2_tree, hf_mtp2_long_sf, su_tvb, SF_OFFSET, LONG_SF_LENGTH, LITTLE_ENDIAN_BYTE_ORDER);
+ }
+}
+
+static void
+dissect_mtp2_msu(tvbuff_t *su_tvb, packet_info *pinfo, proto_item *mtp2_item, proto_item *tree)
+{
+ gint sif_sio_length;
+ tvbuff_t *sif_sio_tvb;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "MSU ");
+
+ sif_sio_length = tvb_length(su_tvb) - HEADER_LENGTH;
+ sif_sio_tvb = tvb_new_subset(su_tvb, SIO_OFFSET, sif_sio_length, sif_sio_length);
+ call_dissector(mtp3_handle, sif_sio_tvb, pinfo, tree);
+
+ if (tree)
+ proto_item_set_len(mtp2_item, HEADER_LENGTH);
+
+}
+
+static void
+dissect_mtp2_su(tvbuff_t *su_tvb, packet_info *pinfo, proto_item *mtp2_item, proto_item *mtp2_tree, proto_tree *tree)
+{
+ guint8 li;
+
+ dissect_mtp2_header(su_tvb, mtp2_tree);
+ li = tvb_get_guint8(su_tvb, LI_OFFSET);
+ switch(li & LI_MASK) {
+ case 0:
+ dissect_mtp2_fisu(pinfo);
+ break;
+ case 1:
+ case 2:
+ dissect_mtp2_lssu(su_tvb, pinfo, mtp2_tree);
+ break;
+ default:
+ dissect_mtp2_msu(su_tvb, pinfo, mtp2_item, tree);
+ break;
+ }
+}
+
+static void
+dissect_mtp2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *mtp2_item = NULL;
+ proto_tree *mtp2_tree = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP2");
+
+ if (tree) {
+ mtp2_item = proto_tree_add_item(tree, proto_mtp2, tvb, 0, -1, FALSE);
+ mtp2_tree = proto_item_add_subtree(mtp2_item, ett_mtp2);
+ };
+
+ dissect_mtp2_su(tvb, pinfo, mtp2_item, mtp2_tree, tree);
+}
+
+void
+proto_register_mtp2(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_mtp2_bsn, { "Backward sequence number", "mtp2.bsn", FT_UINT8, BASE_DEC, NULL, BSN_MASK, "", HFILL } },
+ { &hf_mtp2_bib, { "Backward indicator bit", "mtp2.bib", FT_UINT8, BASE_DEC, NULL, BIB_MASK, "", HFILL } },
+ { &hf_mtp2_fsn, { "Forward sequence number", "mtp2.fsn", FT_UINT8, BASE_DEC, NULL, FSN_MASK, "", HFILL } },
+ { &hf_mtp2_fib, { "Forward indicator bit", "mtp2.fib", FT_UINT8, BASE_DEC, NULL, FIB_MASK, "", HFILL } },
+ { &hf_mtp2_li, { "Length Indicator", "mtp2.li", FT_UINT8, BASE_DEC, NULL, LI_MASK, "", HFILL } },
+ { &hf_mtp2_spare, { "Spare", "mtp2.spare", FT_UINT8, BASE_DEC, NULL, SPARE_MASK, "", HFILL } },
+ { &hf_mtp2_sf, { "Status field", "mtp2.sf", FT_UINT8, BASE_DEC, VALS(status_field_vals), 0x0, "", HFILL } },
+ { &hf_mtp2_long_sf, { "Status field", "mtp2.sf", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } }
+ };
+
+ static gint *ett[] = {
+ &ett_mtp2
+ };
+
+ proto_mtp2 = proto_register_protocol("Message Transfer Part Level 2", "MTP2", "mtp2");
+ register_dissector("mtp2", dissect_mtp2, proto_mtp2);
+
+ proto_register_field_array(proto_mtp2, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_mtp2(void)
+{
+ dissector_handle_t mtp2_handle;
+
+ mtp2_handle = create_dissector_handle(dissect_mtp2, proto_mtp2);
+
+ dissector_add("wtap_encap", WTAP_ENCAP_MTP2, mtp2_handle);
+
+ mtp3_handle = find_dissector("mtp3");
+ mtp3_proto_id = proto_get_id_by_filter_name("mtp3");
+}
diff --git a/epan/dissectors/packet-mtp3.c b/epan/dissectors/packet-mtp3.c
new file mode 100644
index 0000000000..b23d801b46
--- /dev/null
+++ b/epan/dissectors/packet-mtp3.c
@@ -0,0 +1,694 @@
+/* packet-mtp3.c
+ * Routines for Message Transfer Part Level 3 dissection
+ *
+ * It is (hopefully) compliant to:
+ * ANSI T1.111.4-1996
+ * ITU-T Q.704 7/1996
+ * GF 001-9001 (Chinese ITU variant)
+ *
+ * Copyright 2001, Michael Tuexen <tuexen [AT] fh-muenster.de>
+ * Updated for ANSI and Chinese ITU support by Jeff Morriss <jeff.morriss[AT]ulticom.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+#include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "tap.h"
+#include "prefs.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_mtp3 = -1;
+
+static int mtp3_tap = -1;
+
+static module_t *mtp3_module;
+
+static int hf_mtp3_service_indicator = -1;
+static int hf_mtp3_network_indicator = -1;
+static int hf_mtp3_itu_spare = -1;
+static int hf_mtp3_ansi_priority = -1;
+static int hf_mtp3_itu_opc = -1;
+static int hf_mtp3_24bit_opc = -1;
+static int hf_mtp3_ansi_opc = -1;
+static int hf_mtp3_chinese_opc = -1;
+static int hf_mtp3_opc_network = -1;
+static int hf_mtp3_opc_cluster = -1;
+static int hf_mtp3_opc_member = -1;
+static int hf_mtp3_itu_dpc = -1;
+static int hf_mtp3_24bit_dpc = -1;
+static int hf_mtp3_ansi_dpc = -1;
+static int hf_mtp3_chinese_dpc = -1;
+static int hf_mtp3_dpc_network = -1;
+static int hf_mtp3_dpc_cluster = -1;
+static int hf_mtp3_dpc_member = -1;
+static int hf_mtp3_itu_sls = -1;
+static int hf_mtp3_ansi_5_bit_sls = -1;
+static int hf_mtp3_ansi_8_bit_sls = -1;
+static int hf_mtp3_chinese_itu_sls = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_mtp3 = -1;
+static gint ett_mtp3_sio = -1;
+static gint ett_mtp3_label = -1;
+static gint ett_mtp3_label_dpc = -1;
+static gint ett_mtp3_label_opc = -1;
+
+static dissector_table_t mtp3_sio_dissector_table;
+
+typedef enum {
+ ITU_PC_STRUCTURE_NONE = 1,
+ ITU_PC_STRUCTURE_3_8_3 = 2,
+ ITU_PC_STRUCTURE_4_3_4_3 = 3
+} ITU_PC_Structure_Type;
+
+ITU_PC_Structure_Type itu_pc_structure = ITU_PC_STRUCTURE_NONE;
+
+#include <packet-mtp3.h>
+Standard_Type mtp3_standard = ITU_STANDARD;
+
+static gboolean mtp3_use_ansi_5_bit_sls = FALSE;
+static mtp3_net_addr_fmt_e mtp3_net_addr_fmt = MTP3_NET_ADDR_FMT_DASHED;
+static mtp3_addr_pc_t mtp3_addr_dpc, mtp3_addr_opc;
+
+#define SIO_LENGTH 1
+
+#define ITU_ROUTING_LABEL_LENGTH 4
+#define ITU_HEADER_LENGTH (SIO_LENGTH + ITU_ROUTING_LABEL_LENGTH)
+#define ITU_SLS_LENGTH 1
+
+#define SIO_OFFSET 0
+#define ITU_SLS_OFFSET (SIO_OFFSET + ITU_HEADER_LENGTH - ITU_SLS_LENGTH)
+#define ITU_ROUTING_LABEL_OFFSET (SIO_OFFSET + SIO_LENGTH)
+#define ITU_MTP_PAYLOAD_OFFSET (SIO_OFFSET + ITU_HEADER_LENGTH)
+
+#define ANSI_SLS_LENGTH 1
+#define ANSI_ROUTING_LABEL_LENGTH (ANSI_PC_LENGTH + ANSI_PC_LENGTH + ANSI_SLS_LENGTH)
+#define ANSI_HEADER_LENGTH (SIO_LENGTH + ANSI_ROUTING_LABEL_LENGTH)
+
+#define ANSI_ROUTING_LABEL_OFFSET (SIO_OFFSET + SIO_LENGTH)
+#define ANSI_DPC_OFFSET ANSI_ROUTING_LABEL_OFFSET
+#define ANSI_OPC_OFFSET (ANSI_DPC_OFFSET + ANSI_PC_LENGTH)
+#define ANSI_SLS_OFFSET (ANSI_OPC_OFFSET + ANSI_PC_LENGTH)
+#define ANSI_MTP_PAYLOAD_OFFSET (SIO_OFFSET + ANSI_HEADER_LENGTH)
+
+#define SERVICE_INDICATOR_MASK 0x0F
+#define SPARE_MASK 0x30
+#define ANSI_PRIORITY_MASK SPARE_MASK
+#define NETWORK_INDICATOR_MASK 0xC0
+#define ITU_DPC_MASK 0x00003FFF
+#define ITU_OPC_MASK 0x0FFFC000
+#define ITU_SLS_MASK 0xF0000000
+
+#define ANSI_NETWORK_MASK 0x0000FF
+#define ANSI_CLUSTER_MASK 0x00FF00
+#define ANSI_MEMBER_MASK 0xFF0000
+#define ANSI_5BIT_SLS_MASK 0x1F
+#define ANSI_8BIT_SLS_MASK 0xFF
+#define CHINESE_ITU_SLS_MASK 0xF
+
+static const value_string mtp3_service_indicator_code_vals[] = {
+ { 0x0, "Signalling Network Management Message (SNM)" },
+ { 0x1, "Maintenance Regular Message (MTN)" },
+ { 0x2, "Maintenance Special Message (MTNS)" },
+ { 0x3, "SCCP" },
+ { 0x4, "TUP" },
+ { 0x5, "ISUP" },
+ { 0x6, "DUP (call and circuit related messages)" },
+ { 0x7, "DUP (facility registration and cancellation message)" },
+ { 0x8, "MTP testing user part" },
+ { 0x9, "Spare" },
+ { 0xa, "Spare" },
+ { 0xb, "Spare" },
+ { 0xc, "Spare" },
+ { 0xd, "Spare" },
+ { 0xe, "Spare" },
+ { 0xf, "Spare" },
+ { 0, NULL }
+};
+
+const value_string mtp3_service_indicator_code_short_vals[] = {
+ { 0x0, "SNM" },
+ { 0x1, "MTN" },
+ { 0x2, "MTNS" },
+ { 0x3, "SCCP" },
+ { 0x4, "TUP" },
+ { 0x5, "ISUP" },
+ { 0x6, "DUP (CC)" },
+ { 0x7, "DUP (FAC/CANC)" },
+ { 0x8, "MTP Test" },
+ { 0, NULL }
+};
+
+static const value_string network_indicator_vals[] = {
+ { 0x0, "International network" },
+ { 0x1, "Spare (for international use only)" },
+ { 0x2, "National network" },
+ { 0x3, "Reserved for national use" },
+ { 0, NULL }
+};
+
+static dissector_handle_t data_handle;
+
+
+/*
+ * helper routine to format a point code in structured form
+ */
+
+void
+mtp3_pc_to_str_buf(const guint32 pc, gchar *buf)
+{
+ switch (mtp3_standard)
+ {
+ case ITU_STANDARD:
+ switch (itu_pc_structure) {
+ case ITU_PC_STRUCTURE_NONE:
+ sprintf(buf, "%u", pc);
+ break;
+ case ITU_PC_STRUCTURE_3_8_3:
+ /* this format is used in international ITU networks */
+ sprintf(buf, "%u-%u-%u", (pc & 0x3800)>>11, (pc & 0x7f8) >> 3, (pc & 0x07) >> 0);
+ break;
+ case ITU_PC_STRUCTURE_4_3_4_3:
+ /* this format is used in some national ITU networks, the German one for example. */
+ sprintf(buf, "%u-%u-%u-%u", (pc & 0x3c00) >>10, (pc & 0x0380) >> 7, (pc & 0x0078) >> 3, (pc & 0x0007) >> 0);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ break;
+ case ANSI_STANDARD:
+ case CHINESE_ITU_STANDARD:
+ sprintf(buf, "%u-%u-%u", (pc & ANSI_NETWORK_MASK), (pc & ANSI_CLUSTER_MASK) >> 8, (pc & ANSI_MEMBER_MASK) >> 16);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+#define MAX_STRUCTURED_PC_LENGTH 20
+
+gchar *
+mtp3_pc_to_str(const guint32 pc)
+{
+ static gchar str[MAX_STRUCTURED_PC_LENGTH];
+
+ mtp3_pc_to_str_buf(pc, str);
+ return str;
+}
+
+gboolean
+mtp3_pc_structured(void)
+{
+ if ((mtp3_standard == ITU_STANDARD) && (itu_pc_structure == ITU_PC_STRUCTURE_NONE))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/*
+ * helper routine to format address to string
+ */
+
+void
+mtp3_addr_to_str_buf(
+ const guint8 *data,
+ gchar *buf)
+{
+ mtp3_addr_pc_t *addr_pc_p = (mtp3_addr_pc_t *) data;
+
+ switch (mtp3_net_addr_fmt)
+ {
+ case MTP3_NET_ADDR_FMT_DEC:
+ switch (addr_pc_p->type)
+ {
+ case ITU_STANDARD:
+ sprintf(buf, "%u", addr_pc_p->pc & ITU_PC_MASK);
+ break;
+ default:
+ /* assuming 24-bit */
+ sprintf(buf, "%u", addr_pc_p->pc & ANSI_PC_MASK);
+ break;
+ }
+ break;
+
+ case MTP3_NET_ADDR_FMT_HEX:
+ switch (addr_pc_p->type)
+ {
+ case ITU_STANDARD:
+ sprintf(buf, "%x", addr_pc_p->pc & ITU_PC_MASK);
+ break;
+ default:
+ /* assuming 24-bit */
+ sprintf(buf, "%x", addr_pc_p->pc & ANSI_PC_MASK);
+ break;
+ }
+ break;
+
+ case MTP3_NET_ADDR_FMT_NI_DEC:
+ switch (addr_pc_p->type)
+ {
+ case ITU_STANDARD:
+ sprintf(buf, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & ITU_PC_MASK);
+ break;
+ default:
+ /* assuming 24-bit */
+ sprintf(buf, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & ANSI_PC_MASK);
+ break;
+ }
+ break;
+
+ case MTP3_NET_ADDR_FMT_NI_HEX:
+ switch (addr_pc_p->type)
+ {
+ case ITU_STANDARD:
+ sprintf(buf, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & ITU_PC_MASK);
+ break;
+ default:
+ /* assuming 24-bit */
+ sprintf(buf, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & ANSI_PC_MASK);
+ break;
+ }
+ break;
+
+ default:
+ /* FALLTHRU */
+
+ case MTP3_NET_ADDR_FMT_DASHED:
+ mtp3_pc_to_str_buf(addr_pc_p->pc, buf);
+ break;
+ }
+}
+
+static void
+dissect_mtp3_sio(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree)
+{
+ guint8 sio;
+ proto_item *sio_item;
+ proto_tree *sio_tree;
+
+ sio_item = proto_tree_add_text(mtp3_tree, tvb, SIO_OFFSET, SIO_LENGTH, "Service information octet");
+ sio_tree = proto_item_add_subtree(sio_item, ett_mtp3_sio);
+
+ sio = tvb_get_guint8(tvb, SIO_OFFSET);
+ proto_tree_add_uint(sio_tree, hf_mtp3_network_indicator, tvb, SIO_OFFSET, SIO_LENGTH, sio);
+
+ mtp3_addr_opc.ni = (sio & NETWORK_INDICATOR_MASK) >> 6;
+ mtp3_addr_dpc.ni = (sio & NETWORK_INDICATOR_MASK) >> 6;
+
+ switch(mtp3_standard){
+ case ANSI_STANDARD:
+ proto_tree_add_uint(sio_tree, hf_mtp3_ansi_priority, tvb, SIO_OFFSET, SIO_LENGTH, sio);
+ break;
+ case ITU_STANDARD:
+ case CHINESE_ITU_STANDARD:
+ proto_tree_add_uint(sio_tree, hf_mtp3_itu_spare, tvb, SIO_OFFSET, SIO_LENGTH, sio);
+ break;
+ }
+
+ proto_tree_add_uint(sio_tree, hf_mtp3_service_indicator, tvb, SIO_OFFSET, SIO_LENGTH, sio);
+
+ /* Store the SI so that subidissectors know what SI this msg is */
+ pinfo->private_data = (void *)(sio & SERVICE_INDICATOR_MASK);
+}
+
+static void
+dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree)
+{
+ guint32 label, dpc = 0, opc = 0;
+ proto_item *label_item, *label_dpc_item, *label_opc_item;
+ proto_tree *label_tree, *label_dpc_tree, *label_opc_tree;
+ int *hf_dpc_string;
+ int *hf_opc_string;
+
+
+ switch (mtp3_standard) {
+ case ITU_STANDARD:
+ label_item = proto_tree_add_text(mtp3_tree, tvb, ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, "Routing label");
+ label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);
+
+ label = tvb_get_letohl(tvb, ITU_ROUTING_LABEL_OFFSET);
+
+ opc = (label & ITU_OPC_MASK) >> 14;
+ dpc = label & ITU_DPC_MASK;
+
+ label_dpc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb, ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
+ if (mtp3_pc_structured())
+ proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc));
+
+ label_opc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb, ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
+ if (mtp3_pc_structured())
+ proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc));
+
+ proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
+ break;
+
+ case ANSI_STANDARD:
+ case CHINESE_ITU_STANDARD:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ hf_dpc_string = &hf_mtp3_ansi_dpc;
+ hf_opc_string = &hf_mtp3_ansi_opc;
+ } else /* CHINESE_ITU_STANDARD */ {
+ hf_dpc_string = &hf_mtp3_chinese_dpc;
+ hf_opc_string = &hf_mtp3_chinese_opc;
+ }
+
+ /* Create the Routing Label Tree */
+ label_item = proto_tree_add_text(mtp3_tree, tvb, ANSI_ROUTING_LABEL_OFFSET, ANSI_ROUTING_LABEL_LENGTH, "Routing label");
+ label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);
+
+ /* create the DPC tree */
+ dpc = tvb_get_ntoh24(tvb, ANSI_DPC_OFFSET);
+ label_dpc_item = proto_tree_add_string_format(label_tree, *hf_dpc_string, tvb, ANSI_DPC_OFFSET, ANSI_PC_LENGTH, mtp3_pc_to_str(dpc), "DPC (%s) (%u)", mtp3_pc_to_str(dpc), dpc);
+ label_dpc_tree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc);
+
+ proto_tree_add_uint(label_dpc_tree, hf_mtp3_dpc_member, tvb, ANSI_DPC_OFFSET + ANSI_MEMBER_OFFSET, ANSI_NCM_LENGTH, dpc);
+ proto_tree_add_uint(label_dpc_tree, hf_mtp3_dpc_cluster, tvb, ANSI_DPC_OFFSET + ANSI_CLUSTER_OFFSET, ANSI_NCM_LENGTH, dpc);
+ proto_tree_add_uint(label_dpc_tree, hf_mtp3_dpc_network, tvb, ANSI_DPC_OFFSET + ANSI_NETWORK_OFFSET, ANSI_NCM_LENGTH, dpc);
+
+ /* add full integer values of DPC as hidden for filtering purposes */
+ proto_tree_add_uint_hidden(label_dpc_tree, hf_mtp3_24bit_dpc, tvb, ANSI_DPC_OFFSET, ANSI_PC_LENGTH, dpc);
+
+ /* create the OPC tree */
+ opc = tvb_get_ntoh24(tvb, ANSI_OPC_OFFSET);
+ label_opc_item = proto_tree_add_string_format(label_tree, *hf_opc_string, tvb, ANSI_OPC_OFFSET, ANSI_PC_LENGTH, mtp3_pc_to_str(opc), "OPC (%s) (%u)", mtp3_pc_to_str(opc), opc);
+ label_opc_tree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc);
+
+ proto_tree_add_uint(label_opc_tree, hf_mtp3_opc_member, tvb, ANSI_OPC_OFFSET + ANSI_MEMBER_OFFSET, ANSI_NCM_LENGTH, opc);
+ proto_tree_add_uint(label_opc_tree, hf_mtp3_opc_cluster, tvb, ANSI_OPC_OFFSET + ANSI_CLUSTER_OFFSET, ANSI_NCM_LENGTH, opc);
+ proto_tree_add_uint(label_opc_tree, hf_mtp3_opc_network, tvb, ANSI_OPC_OFFSET + ANSI_NETWORK_OFFSET, ANSI_NCM_LENGTH, opc);
+
+ /* add full integer values of OPC as hidden for filtering purposes */
+ proto_tree_add_uint_hidden(label_opc_tree, hf_mtp3_24bit_opc, tvb, ANSI_OPC_OFFSET, ANSI_PC_LENGTH, opc);
+
+ /* SLS */
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ if (mtp3_use_ansi_5_bit_sls)
+ proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, ANSI_SLS_LENGTH, TRUE);
+ else
+ proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, ANSI_SLS_LENGTH, TRUE);
+ } else /* CHINESE_ITU_STANDARD */ {
+ proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, ITU_SLS_LENGTH, FALSE);
+ }
+ break;
+ }
+
+ mtp3_addr_opc.type = mtp3_standard;
+ mtp3_addr_opc.pc = opc;
+ SET_ADDRESS(&pinfo->net_src, AT_SS7PC, sizeof(mtp3_addr_opc), (guint8 *) &mtp3_addr_opc);
+
+ mtp3_addr_dpc.type = mtp3_standard;
+ mtp3_addr_dpc.pc = dpc;
+ SET_ADDRESS(&pinfo->net_dst, AT_SS7PC, sizeof(mtp3_addr_dpc), (guint8 *) &mtp3_addr_dpc);
+}
+
+static void
+dissect_mtp3_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 sio;
+ guint8 service_indicator;
+ tvbuff_t *payload_tvb = NULL;
+
+ sio = tvb_get_guint8(tvb, SIO_OFFSET);
+ service_indicator = sio & SERVICE_INDICATOR_MASK;
+
+ switch (mtp3_standard) {
+ case ITU_STANDARD:
+ payload_tvb = tvb_new_subset(tvb, ITU_MTP_PAYLOAD_OFFSET, -1, -1);
+ break;
+ case ANSI_STANDARD:
+ case CHINESE_ITU_STANDARD:
+ payload_tvb = tvb_new_subset(tvb, ANSI_MTP_PAYLOAD_OFFSET, -1, -1);
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "DATA ");
+
+ if (!dissector_try_port(mtp3_sio_dissector_table, service_indicator, payload_tvb, pinfo, tree))
+ call_dissector(data_handle, payload_tvb, pinfo, tree);
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_mtp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ mtp3_tap_rec_t tap_rec;
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *mtp3_item = NULL;
+ proto_tree *mtp3_tree = NULL;
+
+ /* Make entries in Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ switch(mtp3_standard) {
+ case ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Int. ITU)");
+ break;
+ case ANSI_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (ANSI)");
+ break;
+ case CHINESE_ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Chin. ITU)");
+ break;
+ };
+
+ if (tree) {
+ /* create display subtree for the protocol */
+ switch (mtp3_standard) {
+ case ITU_STANDARD:
+ mtp3_item = proto_tree_add_item(tree, proto_mtp3, tvb, 0, ITU_HEADER_LENGTH, TRUE);
+ break;
+ case ANSI_STANDARD:
+ case CHINESE_ITU_STANDARD:
+ mtp3_item = proto_tree_add_item(tree, proto_mtp3, tvb, 0, ANSI_HEADER_LENGTH, TRUE);
+ break;
+ }
+ mtp3_tree = proto_item_add_subtree(mtp3_item, ett_mtp3);
+
+ }
+
+ memset(&mtp3_addr_opc, 0, sizeof(mtp3_addr_opc));
+ memset(&mtp3_addr_dpc, 0, sizeof(mtp3_addr_dpc));
+
+ /* Dissect the packet (even if !tree so can call sub-dissectors and update
+ * the source and destination address columns) */
+ dissect_mtp3_sio(tvb, pinfo, mtp3_tree);
+ dissect_mtp3_routing_label(tvb, pinfo, mtp3_tree);
+
+ tap_rec.addr_opc = mtp3_addr_opc;
+ tap_rec.addr_dpc = mtp3_addr_dpc;
+ tap_rec.si_code = (tvb_get_guint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK);
+ tap_rec.size = tvb_length(tvb);
+
+ tap_queue_packet(mtp3_tap, pinfo, &tap_rec);
+
+ dissect_mtp3_payload(tvb, pinfo, tree);
+}
+
+void
+proto_register_mtp3(void)
+{
+
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_mtp3_service_indicator,
+ { "Service indicator", "mtp3.service_indicator",
+ FT_UINT8, BASE_HEX, VALS(mtp3_service_indicator_code_vals), SERVICE_INDICATOR_MASK,
+ "", HFILL }},
+ { &hf_mtp3_network_indicator,
+ { "Network indicator", "mtp3.network_indicator",
+ FT_UINT8, BASE_HEX, VALS(network_indicator_vals), NETWORK_INDICATOR_MASK,
+ "", HFILL }},
+ { &hf_mtp3_itu_spare,
+ { "Spare", "mtp3.spare",
+ FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
+ "", HFILL }},
+ { &hf_mtp3_ansi_priority,
+ { "Priority", "mtp3.priority",
+ FT_UINT8, BASE_HEX, NULL, ANSI_PRIORITY_MASK,
+ "", HFILL }},
+ { &hf_mtp3_itu_opc,
+ { "OPC", "mtp3.opc",
+ FT_UINT32, BASE_DEC, NULL, ITU_OPC_MASK,
+ "", HFILL }},
+ { &hf_mtp3_24bit_opc,
+ { "OPC", "mtp3.opc",
+ FT_UINT32, BASE_DEC, NULL, ANSI_PC_MASK,
+ "", HFILL }},
+ { &hf_mtp3_ansi_opc,
+ { "DPC", "mtp3.ansi_opc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3_chinese_opc,
+ { "DPC", "mtp3.chinese_opc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3_opc_network,
+ { "OPC Network", "mtp3.opc.network",
+ FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
+ "", HFILL }},
+ { &hf_mtp3_opc_cluster,
+ { "OPC Cluster", "mtp3.opc.cluster",
+ FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
+ "", HFILL }},
+ { &hf_mtp3_opc_member,
+ { "OPC Member", "mtp3.opc.member",
+ FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
+ "", HFILL }},
+ { &hf_mtp3_itu_dpc,
+ { "DPC", "mtp3.dpc",
+ FT_UINT32, BASE_DEC, NULL, ITU_DPC_MASK,
+ "", HFILL }},
+ { &hf_mtp3_24bit_dpc,
+ { "DPC", "mtp3.dpc",
+ FT_UINT32, BASE_DEC, NULL, ANSI_PC_MASK,
+ "", HFILL }},
+ { &hf_mtp3_ansi_dpc,
+ { "DPC", "mtp3.ansi_dpc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3_chinese_dpc,
+ { "DPC", "mtp3.chinese_dpc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3_dpc_network,
+ { "DPC Network", "mtp3.dpc.network",
+ FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
+ "", HFILL }},
+ { &hf_mtp3_dpc_cluster,
+ { "DPC Cluster", "mtp3.dpc.cluster",
+ FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
+ "", HFILL }},
+ { &hf_mtp3_dpc_member,
+ { "DPC Member", "mtp3.dpc.member",
+ FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
+ "", HFILL }},
+ { &hf_mtp3_itu_sls,
+ { "Signalling Link Selector", "mtp3.sls",
+ FT_UINT32, BASE_DEC, NULL, ITU_SLS_MASK,
+ "", HFILL }},
+ { &hf_mtp3_ansi_5_bit_sls,
+ { "Signalling Link Selector", "mtp3.sls",
+ FT_UINT8, BASE_DEC, NULL, ANSI_5BIT_SLS_MASK,
+ "", HFILL }},
+ { &hf_mtp3_ansi_8_bit_sls,
+ { "Signalling Link Selector", "mtp3.sls",
+ FT_UINT8, BASE_DEC, NULL, ANSI_8BIT_SLS_MASK,
+ "", HFILL }},
+ { &hf_mtp3_chinese_itu_sls,
+ { "Signalling Link Selector", "mtp3.sls",
+ FT_UINT8, BASE_DEC, NULL, CHINESE_ITU_SLS_MASK,
+ "", HFILL }}
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_mtp3,
+ &ett_mtp3_sio,
+ &ett_mtp3_label,
+ &ett_mtp3_label_dpc,
+ &ett_mtp3_label_opc
+ };
+
+ static enum_val_t mtp3_options[] = {
+ { "itu", "ITU", ITU_STANDARD },
+ { "ansi", "ANSI", ANSI_STANDARD },
+ { "chinese-itu", "Chinese ITU", CHINESE_ITU_STANDARD },
+ { NULL, NULL, 0 }
+ };
+
+ static enum_val_t mtp3_net_addr_fmt_str_e[] = {
+ { "decimal", "Decimal", MTP3_NET_ADDR_FMT_DEC },
+ { "hexadecimal", "Hexadecimal", MTP3_NET_ADDR_FMT_HEX },
+ { "ni-decimal", "NI-Decimal", MTP3_NET_ADDR_FMT_NI_DEC },
+ { "ni-hexadecimal", "NI-Hexadecimal", MTP3_NET_ADDR_FMT_NI_HEX },
+ { "dashed", "Dashed", MTP3_NET_ADDR_FMT_DASHED },
+ { NULL, NULL, 0 }
+ };
+
+ static enum_val_t itu_pc_structures[] = {
+ { "unstructured", "Unstructured", ITU_PC_STRUCTURE_NONE},
+ { "3-8-3", "3-8-3", ITU_PC_STRUCTURE_3_8_3 },
+ { "4-3-4-3", "4-3-4-3", ITU_PC_STRUCTURE_4_3_4_3 },
+ { NULL, NULL, 0 }
+ };
+
+ /* Register the protocol name and description */
+ proto_mtp3 = proto_register_protocol("Message Transfer Part Level 3",
+ "MTP3", "mtp3");
+ register_dissector("mtp3", dissect_mtp3, proto_mtp3);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_mtp3, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ mtp3_sio_dissector_table = register_dissector_table("mtp3.service_indicator",
+ "MTP3 Service indicator",
+ FT_UINT8, BASE_HEX);
+
+ mtp3_tap = register_tap("mtp3");
+
+ mtp3_module = prefs_register_protocol(proto_mtp3, NULL);
+
+ prefs_register_enum_preference(mtp3_module, "standard", "MTP3 standard",
+ "The SS7 standard used in MTP3 packets",
+ (gint *)&mtp3_standard, mtp3_options, FALSE);
+
+ prefs_register_enum_preference(mtp3_module, "itu_pc_structure", "ITU Pointcode structure",
+ "The structure of the pointcodes in ITU networks",
+ (gint *)&itu_pc_structure, itu_pc_structures, FALSE);
+
+ prefs_register_bool_preference(mtp3_module, "ansi_5_bit_sls",
+ "Use 5-bit SLS (ANSI only)",
+ "Use 5-bit (instead of 8-bit) SLS in ANSI MTP3 packets",
+ &mtp3_use_ansi_5_bit_sls);
+
+ prefs_register_enum_preference(mtp3_module, "net_addr_format", "Network Address Format",
+ "Format for point code in the network address columns",
+ (gint *)&mtp3_net_addr_fmt, mtp3_net_addr_fmt_str_e, FALSE);
+}
+
+void
+proto_reg_handoff_mtp3(void)
+{
+ dissector_handle_t mtp3_handle;
+
+ mtp3_handle = create_dissector_handle(dissect_mtp3, proto_mtp3);
+
+ dissector_add("wtap_encap", WTAP_ENCAP_MTP3, mtp3_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-mtp3.h b/epan/dissectors/packet-mtp3.h
new file mode 100644
index 0000000000..cdc1f476d6
--- /dev/null
+++ b/epan/dissectors/packet-mtp3.h
@@ -0,0 +1,83 @@
+/* packet-mtp3.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+typedef enum {
+ ITU_STANDARD = 1,
+ ANSI_STANDARD = 2,
+ CHINESE_ITU_STANDARD = 3
+} Standard_Type;
+
+extern Standard_Type mtp3_standard;
+
+typedef enum {
+ MTP3_NET_ADDR_FMT_DEC = 1,
+ MTP3_NET_ADDR_FMT_HEX = 2,
+ MTP3_NET_ADDR_FMT_NI_DEC = 3,
+ MTP3_NET_ADDR_FMT_NI_HEX = 4,
+ MTP3_NET_ADDR_FMT_DASHED = 5
+} mtp3_net_addr_fmt_e;
+
+typedef struct _mtp3_addr_pc_t {
+ mtp3_net_addr_fmt_e type;
+ guint32 pc;
+ guint8 ni;
+} mtp3_addr_pc_t;
+
+typedef struct _mtp3_tap_rec_t {
+ mtp3_addr_pc_t addr_opc;
+ mtp3_addr_pc_t addr_dpc;
+ guint8 si_code;
+ guint16 size;
+} mtp3_tap_rec_t;
+
+#define ITU_PC_LENGTH 2
+#define ITU_PC_MASK 0x3FFF
+
+#define ANSI_PC_LENGTH 3
+#define ANSI_NCM_LENGTH 1
+#define ANSI_MEMBER_OFFSET 0
+#define ANSI_CLUSTER_OFFSET 1
+#define ANSI_NETWORK_OFFSET 2
+#define ANSI_PC_MASK 0xFFFFFF
+#define ANSI_NETWORK_MASK 0x0000FF
+#define ANSI_CLUSTER_MASK 0x00FF00
+#define ANSI_MEMBER_MASK 0xFF0000
+#define ANSI_PC_STRING_LENGTH 16
+
+extern void mtp3_addr_to_str_buf(const guint8 *data, gchar *buf);
+extern void mtp3_pc_to_str_buf(const guint32 pc, gchar *buf);
+extern gchar* mtp3_pc_to_str(const guint32 pc);
+extern gboolean mtp3_pc_structured(void);
+
+
+/*
+ * the following allows TAP code access to the messages
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string mtp3_service_indicator_code_short_vals[];
+
+/*
+ * I only want to gather stats for non-spare SI codes
+ */
+#define MTP3_NUM_SI_CODE 9
diff --git a/epan/dissectors/packet-mtp3mg.c b/epan/dissectors/packet-mtp3mg.c
new file mode 100644
index 0000000000..7bc8e4f39b
--- /dev/null
+++ b/epan/dissectors/packet-mtp3mg.c
@@ -0,0 +1,1244 @@
+/* packet-mtp3mg.c
+ * Routines for Message Transfer Part Level 3 Management and Test dissection
+ *
+ * It is (hopefully) compliant to:
+ * ANSI T1.111.4-1996
+ * ITU-T Q.704 7/1996
+ * ITU-T Q.707 7/1996 and ANSI T1.111.7-1996 (for SLT message formats)
+ * portions of ITU-T Q.2210 7/1996 (for XCO/XCA message formats)
+ * GF 001-9001 (Chinese ITU variant)
+ *
+ * Copyright 2003, Jeff Morriss <jeff.morriss[AT]ulticom.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-mtp3.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+#include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "prefs.h"
+
+#include <packet-mtp3.h>
+
+/* MTP3 Service Indicators used by this dissector */
+#define MTP3MG_SI 0
+#define MTP3MG_ITU_TEST_SI 1
+#define MTP3MG_ANSI_TEST_SI 2
+
+#define H0H1_LENGTH 1
+#define H0_MASK 0x0f
+#define H1_MASK 0xf0
+#define H1_SHIFT 4
+
+#define H0_CHM 0x01
+#define H0_ECM 0x02
+#define H0_FCM 0x03
+#define H0_TFM 0x04
+#define H0_RSM 0x05
+#define H0_MIM 0x06
+#define H0_TRM 0x07
+#define H0_DLM 0x08
+#define H0_UFC 0x0a
+static const value_string h0_message_type_values[] = {
+ { H0_CHM, "Changeover and changeback messages" },
+ { H0_ECM, "Emergency changeover messages" },
+ { H0_FCM, "Transfer-controlled and signalling route set congestion messages" },
+ { H0_TFM, "Transfer prohibited-allowed-restricted messages" },
+ { H0_RSM, "Signalling-route-set-test messages" },
+ { H0_MIM, "Management inhibit messages" },
+ { H0_TRM, "Traffic restart messages" },
+ { H0_DLM, "Signalling-data-link-connection messages" },
+ { H0_UFC, "User part flow control messages" },
+ { 0, NULL } };
+
+#define TEST_H0_SLT 0x1
+static const value_string test_h0_message_type_values[] = {
+ { TEST_H0_SLT, "Test messages" },
+ { 0, NULL } };
+
+#define CHM_H1_COO 0x01
+#define CHM_H1_COA 0x02
+#define CHM_H1_XCO 0x03
+#define CHM_H1_XCA 0x04
+#define CHM_H1_CBD 0x05
+#define CHM_H1_CBA 0x06
+static const value_string chm_h1_message_type_values[] = {
+ { CHM_H1_COO, "Changeover-order signal" },
+ { CHM_H1_COA, "Changeover-ack signal" },
+ { CHM_H1_XCO, "Extended changeover-order signal" },
+ { CHM_H1_XCA, "Extended changeover-ack signal" },
+ { CHM_H1_CBD, "Changeback-declaration signal" },
+ { CHM_H1_CBA, "Changeback-ack signal" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string chm_h1_message_type_acro_values[] = {
+ { CHM_H1_COO, "COO" },
+ { CHM_H1_COA, "COA" },
+ { CHM_H1_XCO, "XCO" },
+ { CHM_H1_XCA, "XCA" },
+ { CHM_H1_CBD, "CBD" },
+ { CHM_H1_CBA, "CBA" },
+ { 0, NULL } };
+
+#define ECM_H1_ECO 0x01
+#define ECM_H1_ECA 0x02
+static const value_string ecm_h1_message_type_values[] = {
+ { ECM_H1_ECO, "Emergency-changeover-order signal" },
+ { ECM_H1_ECA, "Emergency-changeover-ack signal" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string ecm_h1_message_type_acro_values[] = {
+ { ECM_H1_ECO, "ECO" },
+ { ECM_H1_ECA, "ECA" },
+ { 0, NULL } };
+
+#define FCM_H1_RCT 0x01
+#define FCM_H1_TFC 0x02
+static const value_string fcm_h1_message_type_values[] = {
+ { FCM_H1_RCT, "Signalling-route-set-congestion-test signal" },
+ { FCM_H1_TFC, "Transfer-controlled signal" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string fcm_h1_message_type_acro_values[] = {
+ { FCM_H1_RCT, "RCT" },
+ { FCM_H1_TFC, "TFC" },
+ { 0, NULL } };
+
+#define TFM_H1_TFP 0x01
+#define TFM_H1_TCP 0x02 /* ANSI only */
+#define TFM_H1_TFR 0x03
+#define TFM_H1_TCR 0x04 /* ANSI only */
+#define TFM_H1_TFA 0x05
+#define TFM_H1_TCA 0x06 /* ANSI only */
+static const value_string tfm_h1_message_type_values[] = {
+ { TFM_H1_TFP, "Transfer-prohibited signal" },
+ { TFM_H1_TCP, "Transfer-cluster-prohibited signal (ANSI only)" },
+ { TFM_H1_TFR, "Transfer-restricted signal" },
+ { TFM_H1_TCR, "Transfer-cluster-restricted signal (ANSI only)" },
+ { TFM_H1_TFA, "Transfer-allowed signal" },
+ { TFM_H1_TCA, "Transfer-cluster-allowed signal (ANSI only)" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string tfm_h1_message_type_acro_values[] = {
+ { TFM_H1_TFP, "TFP" },
+ { TFM_H1_TCP, "TCP" },
+ { TFM_H1_TFR, "TFR" },
+ { TFM_H1_TCR, "TCR" },
+ { TFM_H1_TFA, "TFA" },
+ { TFM_H1_TCA, "TCA" },
+ { 0, NULL } };
+
+#define RSM_H1_RST 0x01
+#define RSM_H1_RSR 0x02
+#define RSM_H1_RCP 0x03 /* ANSI only */
+#define RSM_H1_RCR 0x04 /* ANSI only */
+static const value_string rsm_h1_message_type_values[] = {
+ { RSM_H1_RST, "Signalling-route-set-test prohibited signal" },
+ { RSM_H1_RSR, "Signalling-route-set-test restricted signal" },
+ { RSM_H1_RCP, "Signalling-route-set-test cluster-prohibited signal (ANSI only)" },
+ { RSM_H1_RCR, "Signalling-route-set-test cluster-restricted signal (ANSI only)" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string rsm_h1_message_type_acro_values[] = {
+ { RSM_H1_RST, "RST" },
+ { RSM_H1_RSR, "RSR" },
+ { RSM_H1_RCP, "RCP" },
+ { RSM_H1_RCR, "RCR" },
+ { 0, NULL } };
+
+#define MIM_H1_LIN 0x01
+#define MIM_H1_LUN 0x02
+#define MIM_H1_LIA 0x03
+#define MIM_H1_LUA 0x04
+#define MIM_H1_LID 0x05
+#define MIM_H1_LFU 0x06
+#define MIM_H1_LLT 0x07 /* LLI in ANSI */
+#define MIM_H1_LRT 0x08 /* LRI in ANSI */
+static const value_string mim_h1_message_type_values[] = {
+ { MIM_H1_LIN, "Link inhibit signal" },
+ { MIM_H1_LUN, "Link uninhibit signal" },
+ { MIM_H1_LIA, "Link inhibit ack signal" },
+ { MIM_H1_LUA, "Link uninhibit ack signal" },
+ { MIM_H1_LID, "Link inhibit denied signal" },
+ { MIM_H1_LFU, "Link forced uninhibit signal" },
+ { MIM_H1_LLT, "Link local inhibit test signal" },
+ { MIM_H1_LRT, "Link remote inhibit test signal" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string mim_h1_message_type_acro_values[] = {
+ { MIM_H1_LIN, "LIN" },
+ { MIM_H1_LUN, "LUN" },
+ { MIM_H1_LIA, "LIA" },
+ { MIM_H1_LUA, "LUA" },
+ { MIM_H1_LID, "LID" },
+ { MIM_H1_LFU, "LFU" },
+ { MIM_H1_LLT, "LLT (LLI)" },
+ { MIM_H1_LRT, "LRT (LRI)" },
+ { 0, NULL } };
+
+#define TRM_H1_TRA 0x01
+#define TRM_H1_TRW 0x02 /* ANSI only */
+static const value_string trm_h1_message_type_values[] = {
+ { TRM_H1_TRA, "Traffic-restart-allowed signal" },
+ { TRM_H1_TRW, "Traffic-restart-waiting signal (ANSI only)" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string trm_h1_message_type_acro_values[] = {
+ { TRM_H1_TRA, "TRA" },
+ { TRM_H1_TRW, "TRW" },
+ { 0, NULL } };
+
+#define DLM_H1_DLC 0x01
+#define DLM_H1_CSS 0x02
+#define DLM_H1_CNS 0x03
+#define DLM_H1_CNP 0x04
+static const value_string dlm_h1_message_type_values[] = {
+ { DLM_H1_DLC, "Signalling-data-link-connection-order signal" },
+ { DLM_H1_CSS, "Connection-successful signal" },
+ { DLM_H1_CNS, "Connection-not-successful signal" },
+ { DLM_H1_CNP, "Connection-not-possible signal" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string dlm_h1_message_type_acro_values[] = {
+ { DLM_H1_DLC, "DLC" },
+ { DLM_H1_CSS, "CSS" },
+ { DLM_H1_CNS, "CNS" },
+ { DLM_H1_CNP, "CNP" },
+ { 0, NULL } };
+
+#define UFC_H1_UPU 0x01
+static const value_string ufc_h1_message_type_values[] = {
+ { UFC_H1_UPU, "User part unavailable signal" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string ufc_h1_message_type_acro_values[] = {
+ { UFC_H1_UPU, "UPU" },
+ { 0, NULL } };
+
+static const value_string upu_cause_values[] = {
+ { 0x0, "Unknown" },
+ { 0x1, "Unequipped remote user" },
+ { 0x2, "Inaccessible remote user" },
+ { 0, NULL } };
+
+#define TEST_H1_SLTM 0x1
+#define TEST_H1_SLTA 0x2
+static const value_string test_h1_message_type_values[] = {
+ { TEST_H1_SLTM, "Signalling link test message" },
+ { TEST_H1_SLTA, "Signalling link test acknowledgement message" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string test_h1_message_type_acro_values[] = {
+ { TEST_H1_SLTM, "SLTM" },
+ { TEST_H1_SLTA, "SLTA" },
+ { 0, NULL } };
+
+#define COO_LENGTH 2
+#define ANSI_COO_SLC_MASK 0x000f
+#define ANSI_COO_FSN_MASK 0x07f0
+#define ITU_COO_FSN_MASK 0x007f
+#define ANSI_XCO_LENGTH 4
+#define ANSI_XCO_SLC_MASK 0x0000000f
+#define ANSI_XCO_FSN_MASK 0x0ffffff0
+#define ITU_XCO_LENGTH 3
+#define ANSI_CBD_LENGTH 2
+#define ANSI_CBD_SLC_MASK 0x000f
+#define ANSI_CBD_CBC_MASK 0x0ff0
+#define ITU_CBD_LENGTH 1
+
+#define ANSI_ECO_LENGTH 1
+#define ANSI_ECO_SLC_MASK 0x0f
+
+#define ANSI_TFC_STATUS_LENGTH 1
+#define ANSI_TFC_STATUS_OFFSET ANSI_PC_LENGTH
+#define ANSI_TFC_STATUS_MASK 0x03
+#define ITU_TFC_STATUS_LENGTH ITU_PC_LENGTH
+#define ITU_TFC_STATUS_MASK 0xc000
+
+#define ANSI_MIM_LENGTH 1
+#define ANSI_MIM_SLC_MASK 0x0f
+
+#define ANSI_DLC_LENGTH 3
+#define ANSI_DLC_SLC_MASK 0x0000f
+#define ANSI_DLC_LINK_MASK 0x3fff0
+#define ITU_DLC_LENGTH 2
+#define ITU_DLC_LINK_MASK 0x0fff
+
+#define ANSI_UPU_USER_OFFSET ANSI_PC_LENGTH
+#define UPU_USER_LENGTH 1
+#define UPU_USER_MASK 0x0f
+#define UPU_CAUSE_MASK 0xf0
+#define ITU_UPU_USER_OFFSET ITU_PC_LENGTH
+
+#define TEST_LENGTH 1
+#define TEST_LENGTH_MASK 0xf0
+#define TEST_LENGTH_SHIFT 4
+#define TEST_PATTERN_OFFSET TEST_LENGTH
+#define ANSI_TEST_SLC_MASK 0x000f
+
+/* This list is slightly different from that in packet-mtp3.c */
+static const value_string service_indicator_code_vals[] = {
+ { 0x0, "Spare" },
+ { 0x1, "Spare"},
+ { 0x2, "Spare" },
+ { 0x3, "SCCP" },
+ { 0x4, "TUP" },
+ { 0x5, "ISUP" },
+ { 0x6, "DUP (call and circuit related messages)" },
+ { 0x7, "DUP (facility registration and cancellation message)" },
+ { 0x8, "MTP testing user part" },
+ { 0x9, "Spare" },
+ { 0xa, "Spare" },
+ { 0xb, "Spare" },
+ { 0xc, "Spare" },
+ { 0xd, "Spare" },
+ { 0xe, "Spare" },
+ { 0xf, "Spare" },
+ { 0, NULL }
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_mtp3mg = -1;
+static int hf_mtp3mg_h0 = -1;
+static int hf_mtp3mg_chm_h1 = -1;
+static int hf_mtp3mg_ecm_h1 = -1;
+static int hf_mtp3mg_fcm_h1 = -1;
+static int hf_mtp3mg_tfm_h1 = -1;
+static int hf_mtp3mg_rsm_h1 = -1;
+static int hf_mtp3mg_mim_h1 = -1;
+static int hf_mtp3mg_trm_h1 = -1;
+static int hf_mtp3mg_dlm_h1 = -1;
+static int hf_mtp3mg_ufc_h1 = -1;
+static int hf_mtp3mg_coo_ansi_slc = -1;
+static int hf_mtp3mg_coo_ansi_fsn = -1;
+static int hf_mtp3mg_coo_itu_fsn = -1;
+static int hf_mtp3mg_xco_ansi_slc = -1;
+static int hf_mtp3mg_xco_ansi_fsn = -1;
+static int hf_mtp3mg_xco_itu_fsn = -1;
+static int hf_mtp3mg_cbd_ansi_slc = -1;
+static int hf_mtp3mg_cbd_ansi_cbc = -1;
+static int hf_mtp3mg_cbd_itu_cbc = -1;
+static int hf_mtp3mg_eco_ansi_slc = -1;
+static int hf_mtp3mg_tfc_ansi_apc = -1;
+static int hf_mtp3mg_tfc_apc_member = -1;
+static int hf_mtp3mg_tfc_apc_cluster = -1;
+static int hf_mtp3mg_tfc_apc_network = -1;
+static int hf_mtp3mg_tfc_ansi_status = -1;
+static int hf_mtp3mg_tfc_itu_apc = -1;
+static int hf_mtp3mg_tfc_itu_status = -1;
+static int hf_mtp3mg_tfc_chinese_apc = -1;
+static int hf_mtp3mg_tfm_ansi_apc = -1;
+static int hf_mtp3mg_tfm_apc_member = -1;
+static int hf_mtp3mg_tfm_apc_cluster = -1;
+static int hf_mtp3mg_tfm_apc_network = -1;
+static int hf_mtp3mg_tfm_itu_apc = -1;
+static int hf_mtp3mg_tfm_chinese_apc = -1;
+static int hf_mtp3mg_rsm_ansi_apc = -1;
+static int hf_mtp3mg_rsm_apc_member = -1;
+static int hf_mtp3mg_rsm_apc_cluster = -1;
+static int hf_mtp3mg_rsm_apc_network = -1;
+static int hf_mtp3mg_rsm_itu_apc = -1;
+static int hf_mtp3mg_rsm_chinese_apc = -1;
+static int hf_mtp3mg_mim_ansi_slc = -1;
+static int hf_mtp3mg_dlc_ansi_slc = -1;
+static int hf_mtp3mg_dlc_ansi_link = -1;
+static int hf_mtp3mg_dlc_itu_link = -1;
+static int hf_mtp3mg_upu_ansi_apc = -1;
+static int hf_mtp3mg_upu_apc_member = -1;
+static int hf_mtp3mg_upu_apc_cluster = -1;
+static int hf_mtp3mg_upu_apc_network = -1;
+static int hf_mtp3mg_upu_itu_apc = -1;
+static int hf_mtp3mg_upu_chinese_apc = -1;
+static int hf_mtp3mg_upu_user = -1;
+static int hf_mtp3mg_upu_cause = -1;
+static int hf_mtp3test_h0 = -1;
+static int hf_mtp3mg_test_h1 = -1;
+static int hf_mtp3mg_test_ansi_slc = -1;
+static int hf_mtp3mg_test_length = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_mtp3mg = -1;
+static gint ett_mtp3mg_fcm_apc = -1;
+static gint ett_mtp3mg_tfm_apc = -1;
+static gint ett_mtp3mg_rsm_apc = -1;
+static gint ett_mtp3mg_upu_apc = -1;
+
+static void
+dissect_mtp3mg_unknown_message(tvbuff_t *tvb, proto_tree *tree)
+{
+ guint8 message_length;
+
+ message_length = tvb_length_remaining(tvb, 0);
+ proto_tree_add_text(tree, tvb, 0, message_length,
+ "Unknown message (%u byte%s)", message_length,
+ plurality(message_length, "", "s"));
+}
+
+static void
+dissect_mtp3mg_chm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, chm_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case CHM_H1_COO:
+ case CHM_H1_COA:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ proto_tree_add_item(tree, hf_mtp3mg_coo_ansi_slc, tvb, 0,
+ COO_LENGTH, TRUE);
+ proto_tree_add_item(tree, hf_mtp3mg_coo_ansi_fsn, tvb, 0,
+ COO_LENGTH, TRUE);
+ } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
+ proto_tree_add_item(tree, hf_mtp3mg_coo_itu_fsn, tvb, 0,
+ COO_LENGTH, TRUE);
+ }
+ break;
+
+ case CHM_H1_XCO:
+ case CHM_H1_XCA:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ proto_tree_add_item(tree, hf_mtp3mg_xco_ansi_slc, tvb, 0,
+ ANSI_XCO_LENGTH, TRUE);
+ proto_tree_add_item(tree, hf_mtp3mg_xco_ansi_fsn, tvb, 0,
+ ANSI_XCO_LENGTH, TRUE);
+ } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
+ proto_tree_add_item(tree, hf_mtp3mg_xco_itu_fsn, tvb, 0,
+ ITU_XCO_LENGTH, TRUE);
+ }
+ break;
+
+ case CHM_H1_CBD:
+ case CHM_H1_CBA:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ proto_tree_add_item(tree, hf_mtp3mg_cbd_ansi_slc, tvb, 0,
+ ANSI_CBD_LENGTH, TRUE);
+ proto_tree_add_item(tree, hf_mtp3mg_cbd_ansi_cbc, tvb, 0,
+ ANSI_CBD_LENGTH, TRUE);
+ } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
+ proto_tree_add_item(tree, hf_mtp3mg_cbd_itu_cbc, tvb, 0,
+ ITU_CBD_LENGTH, TRUE);
+ }
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg_ecm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, ecm_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case ECM_H1_ECO:
+ case ECM_H1_ECA:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ proto_tree_add_item(tree, hf_mtp3mg_eco_ansi_slc, tvb, 0,
+ ANSI_ECO_LENGTH, TRUE);
+ }
+ /* else: nothing to dissect */
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg_3byte_pc(tvbuff_t *tvb, proto_tree *tree, gint *ett_pc,
+ int *hf_pc, int *hf_pc_member, int *hf_pc_cluster,
+ int *hf_pc_network)
+{
+ guint32 apc;
+ proto_item *apc_item;
+ proto_tree *apc_tree;
+ char pc[ANSI_PC_STRING_LENGTH];
+
+ apc = tvb_get_ntoh24(tvb, 0);
+
+ snprintf(pc, sizeof(pc), "%d-%d-%d",
+ (apc & ANSI_NETWORK_MASK),
+ ((apc & ANSI_CLUSTER_MASK) >> 8),
+ ((apc & ANSI_MEMBER_MASK) >> 16));
+
+ apc_item = proto_tree_add_string_format(tree, *hf_pc, tvb, 0,
+ ANSI_PC_LENGTH, pc,
+ "Affected PC (%s)", pc);
+
+ apc_tree = proto_item_add_subtree(apc_item, *ett_pc);
+
+ proto_tree_add_uint(apc_tree, *hf_pc_member, tvb,
+ ANSI_MEMBER_OFFSET, ANSI_NCM_LENGTH, apc);
+ proto_tree_add_uint(apc_tree, *hf_pc_cluster, tvb,
+ ANSI_CLUSTER_OFFSET, ANSI_NCM_LENGTH, apc);
+ proto_tree_add_uint(apc_tree, *hf_pc_network, tvb,
+ ANSI_NETWORK_OFFSET, ANSI_NCM_LENGTH, apc);
+
+}
+
+static void
+dissect_mtp3mg_fcm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, fcm_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case FCM_H1_RCT:
+ /* nothing to dissect */
+ break;
+
+ case FCM_H1_TFC:
+ if (mtp3_standard == ITU_STANDARD) {
+
+ proto_tree_add_item(tree, hf_mtp3mg_tfc_itu_apc, tvb, 0,
+ ITU_PC_LENGTH, TRUE);
+
+ /* Congestion level is a national option */
+ proto_tree_add_item(tree, hf_mtp3mg_tfc_itu_status, tvb, 0,
+ ITU_TFC_STATUS_LENGTH, TRUE);
+
+
+
+ } else /* ANSI_STANDARD and CHINESE_ITU_STANDARD */ {
+
+ int *hf_apc_string;
+
+ if (mtp3_standard == ANSI_STANDARD) {
+
+ hf_apc_string = &hf_mtp3mg_tfc_ansi_apc;
+
+ } else /* CHINESE_ITU_STANDARD */ {
+
+ hf_apc_string = &hf_mtp3mg_tfc_chinese_apc;
+ }
+
+ dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_fcm_apc,
+ hf_apc_string,
+ &hf_mtp3mg_tfc_apc_member,
+ &hf_mtp3mg_tfc_apc_cluster,
+ &hf_mtp3mg_tfc_apc_network);
+
+ proto_tree_add_item(tree, hf_mtp3mg_tfc_ansi_status, tvb,
+ ANSI_TFC_STATUS_OFFSET, ANSI_TFC_STATUS_LENGTH,
+ TRUE);
+
+ }
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg_tfm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, tfm_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case TFM_H1_TFP:
+ case TFM_H1_TCP:
+ case TFM_H1_TFR:
+ case TFM_H1_TCR:
+ case TFM_H1_TFA:
+ case TFM_H1_TCA:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_tfm_apc,
+ &hf_mtp3mg_tfm_ansi_apc,
+ &hf_mtp3mg_tfm_apc_member,
+ &hf_mtp3mg_tfm_apc_cluster,
+ &hf_mtp3mg_tfm_apc_network);
+
+ } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
+
+ if (h1 == TFM_H1_TCP || h1 == TFM_H1_TCR || h1 == TFM_H1_TCA)
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ else if (mtp3_standard == ITU_STANDARD)
+ proto_tree_add_item(tree, hf_mtp3mg_tfm_itu_apc, tvb, 0,
+ ITU_PC_LENGTH, TRUE);
+ else /* CHINESE_ITU_STANDARD */
+ dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_tfm_apc,
+ &hf_mtp3mg_tfm_chinese_apc,
+ &hf_mtp3mg_tfm_apc_member,
+ &hf_mtp3mg_tfm_apc_cluster,
+ &hf_mtp3mg_tfm_apc_network);
+ }
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg_rsm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, rsm_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case RSM_H1_RST:
+ case RSM_H1_RSR:
+ case RSM_H1_RCP:
+ case RSM_H1_RCR:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_rsm_apc,
+ &hf_mtp3mg_rsm_ansi_apc,
+ &hf_mtp3mg_rsm_apc_member,
+ &hf_mtp3mg_rsm_apc_cluster,
+ &hf_mtp3mg_rsm_apc_network);
+
+ } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
+
+ if (h1 == RSM_H1_RST || h1 == RSM_H1_RSR)
+ {
+ if (mtp3_standard == ITU_STANDARD)
+ proto_tree_add_item(tree, hf_mtp3mg_rsm_itu_apc, tvb, 0,
+ ITU_PC_LENGTH, TRUE);
+
+ else /* CHINESE_ITU_STANDARD */
+ dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_rsm_apc,
+ &hf_mtp3mg_rsm_chinese_apc,
+ &hf_mtp3mg_rsm_apc_member,
+ &hf_mtp3mg_rsm_apc_cluster,
+ &hf_mtp3mg_rsm_apc_network);
+ } else
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg_mim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, mim_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case MIM_H1_LIN:
+ case MIM_H1_LUN:
+ case MIM_H1_LIA:
+ case MIM_H1_LUA:
+ case MIM_H1_LID:
+ case MIM_H1_LFU:
+ case MIM_H1_LLT:
+ case MIM_H1_LRT:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ proto_tree_add_item(tree, hf_mtp3mg_mim_ansi_slc, tvb, 0,
+ ANSI_MIM_LENGTH, TRUE);
+ }
+ /* else: nothing to dissect */
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg_trm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, trm_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case TRM_H1_TRA:
+ /* nothing to dissect */
+ break;
+ case TRM_H1_TRW:
+ if (mtp3_standard != ANSI_STANDARD)
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ /* else: nothing to dissect */
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg_dlm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, dlm_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case DLM_H1_DLC:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ proto_tree_add_item(tree, hf_mtp3mg_dlc_ansi_slc, tvb, 0,
+ ANSI_DLC_LENGTH, TRUE);
+ proto_tree_add_item(tree, hf_mtp3mg_dlc_ansi_link, tvb, 0,
+ ANSI_DLC_LENGTH, TRUE);
+ } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
+ proto_tree_add_item(tree, hf_mtp3mg_dlc_itu_link, tvb, 0,
+ ITU_DLC_LENGTH, TRUE);
+ }
+ break;
+ case DLM_H1_CSS:
+ case DLM_H1_CNS:
+ case DLM_H1_CNP:
+ /* nothing to dissect */
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg_ufc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, ufc_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case UFC_H1_UPU:
+ if (mtp3_standard == ANSI_STANDARD
+ || mtp3_standard == CHINESE_ITU_STANDARD)
+ {
+ int *hf_apc;
+
+ if (mtp3_standard == ANSI_STANDARD)
+ hf_apc = &hf_mtp3mg_upu_ansi_apc;
+ else /* CHINESE_ITU_STANDARD */
+ hf_apc = &hf_mtp3mg_upu_chinese_apc;
+
+ dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_upu_apc,
+ hf_apc,
+ &hf_mtp3mg_rsm_apc_member,
+ &hf_mtp3mg_rsm_apc_cluster,
+ &hf_mtp3mg_rsm_apc_network);
+
+ proto_tree_add_item(tree, hf_mtp3mg_upu_user, tvb,
+ ANSI_UPU_USER_OFFSET, UPU_USER_LENGTH, TRUE);
+ proto_tree_add_item(tree, hf_mtp3mg_upu_cause, tvb,
+ ANSI_UPU_USER_OFFSET, UPU_USER_LENGTH, TRUE);
+ } else /* ITU_STANDARD */ {
+ proto_tree_add_item(tree, hf_mtp3mg_upu_itu_apc, tvb, 0,
+ ITU_PC_LENGTH, TRUE);
+ proto_tree_add_item(tree, hf_mtp3mg_upu_user, tvb,
+ ITU_UPU_USER_OFFSET, UPU_USER_LENGTH, TRUE);
+ proto_tree_add_item(tree, hf_mtp3mg_upu_cause, tvb,
+ ITU_UPU_USER_OFFSET, UPU_USER_LENGTH, TRUE);
+ }
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg_test(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint8 h1)
+{
+ guint8 length;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(h1, test_h1_message_type_acro_values, "Unknown"));
+
+ switch (h1)
+ {
+ case TEST_H1_SLTM:
+ case TEST_H1_SLTA:
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ proto_tree_add_item(tree, hf_mtp3mg_test_ansi_slc, tvb, 0,
+ TEST_LENGTH, TRUE);
+ }
+
+ proto_tree_add_item(tree, hf_mtp3mg_test_length, tvb, 0, TEST_LENGTH,
+ TRUE);
+
+ length = tvb_get_guint8(tvb, 0) >> TEST_LENGTH_SHIFT;
+ proto_tree_add_text(tree, tvb, TEST_PATTERN_OFFSET, length,
+ "Test pattern (%u byte%s)", length,
+ plurality(length, "", "s"));
+ break;
+
+ default:
+ dissect_mtp3mg_unknown_message(tvb, tree);
+ }
+}
+
+static void
+dissect_mtp3mg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ guint8 h0, h1;
+ tvbuff_t *payload_tvb;
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *mtp3mg_item = NULL;
+ proto_tree *mtp3mg_tree = NULL;
+
+ /* Make entries in Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ switch(mtp3_standard) {
+ case ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (Int. ITU)");
+ break;
+ case ANSI_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (ANSI)");
+ break;
+ case CHINESE_ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (Chin. ITU)");
+ break;
+ };
+
+ if (tree) {
+ /* create display subtree for the protocol */
+ mtp3mg_item = proto_tree_add_item(tree, proto_mtp3mg, tvb, 0, -1,
+ TRUE);
+ mtp3mg_tree = proto_item_add_subtree(mtp3mg_item, ett_mtp3mg);
+ }
+
+ /*
+ * Dissect the message
+ */
+ if(pinfo->private_data == (void *)MTP3MG_ANSI_TEST_SI ||
+ pinfo->private_data == (void *)MTP3MG_ITU_TEST_SI)
+ { /* Test messages */
+
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3test_h0, tvb, 0, H0H1_LENGTH,
+ TRUE);
+ /* H1 is added below */
+
+ h0 = tvb_get_guint8(tvb, 0) & H0_MASK;
+ h1 = (tvb_get_guint8(tvb, 0) & H1_MASK) >> H1_SHIFT;
+
+ payload_tvb = tvb_new_subset(tvb, H0H1_LENGTH, -1, -1);
+
+ switch (h0)
+ {
+ case TEST_H0_SLT:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_test_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_test(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+
+ default:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ");
+
+ dissect_mtp3mg_unknown_message(tvb, mtp3mg_tree);
+ } /* switch */
+
+ } else { /* Real management messages */
+
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_h0, tvb, 0, H0H1_LENGTH,
+ TRUE);
+ /* H1 is added below */
+
+ h0 = tvb_get_guint8(tvb, 0) & H0_MASK;
+ h1 = (tvb_get_guint8(tvb, 0) & H1_MASK) >> H1_SHIFT;
+
+ payload_tvb = tvb_new_subset(tvb, H0H1_LENGTH, -1, -1);
+
+ switch (h0)
+ {
+ case H0_CHM:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_chm_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_chm(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+ case H0_ECM:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_ecm_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_ecm(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+ case H0_FCM:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_fcm_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_fcm(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+ case H0_TFM:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_tfm_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_tfm(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+ case H0_RSM:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_rsm_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_rsm(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+ case H0_MIM:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_mim_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_mim(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+ case H0_TRM:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_trm_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_trm(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+ case H0_DLM:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_dlm_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_dlm(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+ case H0_UFC:
+ proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_ufc_h1, tvb, 0,
+ H0H1_LENGTH, TRUE);
+ dissect_mtp3mg_ufc(payload_tvb, pinfo, mtp3mg_tree, h1);
+ break;
+
+ default:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ");
+
+ dissect_mtp3mg_unknown_message(tvb, mtp3mg_tree);
+ } /* switch */
+ } /* else */
+
+}
+
+void
+proto_register_mtp3mg(void)
+{
+
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_mtp3mg_h0,
+ { "H0 (Message Group)", "mtp3mg.h0",
+ FT_UINT8, BASE_HEX, VALS(h0_message_type_values), H0_MASK,
+ "Message group identifier", HFILL }},
+ { &hf_mtp3mg_chm_h1,
+ { "H1 (Message)", "mtp3mg.h1",
+ FT_UINT8, BASE_HEX, VALS(chm_h1_message_type_values), H1_MASK,
+ "Message type", HFILL }},
+ { &hf_mtp3mg_ecm_h1,
+ { "H1 (Message)", "mtp3mg.h1",
+ FT_UINT8, BASE_HEX, VALS(ecm_h1_message_type_values), H1_MASK,
+ "Message type", HFILL }},
+ { &hf_mtp3mg_fcm_h1,
+ { "H1 (Message)", "mtp3mg.h1",
+ FT_UINT8, BASE_HEX, VALS(fcm_h1_message_type_values), H1_MASK,
+ "Message type", HFILL }},
+ { &hf_mtp3mg_tfm_h1,
+ { "H1 (Message)", "mtp3mg.h1",
+ FT_UINT8, BASE_HEX, VALS(tfm_h1_message_type_values), H1_MASK,
+ "Message type", HFILL }},
+ { &hf_mtp3mg_rsm_h1,
+ { "H1 (Message)", "mtp3mg.h1",
+ FT_UINT8, BASE_HEX, VALS(rsm_h1_message_type_values), H1_MASK,
+ "Message type", HFILL }},
+ { &hf_mtp3mg_mim_h1,
+ { "H1 (Message)", "mtp3mg.h1",
+ FT_UINT8, BASE_HEX, VALS(mim_h1_message_type_values), H1_MASK,
+ "Message type", HFILL }},
+ { &hf_mtp3mg_trm_h1,
+ { "H1 (Message)", "mtp3mg.h1",
+ FT_UINT8, BASE_HEX, VALS(trm_h1_message_type_values), H1_MASK,
+ "Message type", HFILL }},
+ { &hf_mtp3mg_dlm_h1,
+ { "H1 (Message)", "mtp3mg.h1",
+ FT_UINT8, BASE_HEX, VALS(dlm_h1_message_type_values), H1_MASK,
+ "Message type", HFILL }},
+ { &hf_mtp3mg_ufc_h1,
+ { "H1 (Message)", "mtp3mg.h1",
+ FT_UINT8, BASE_HEX, VALS(ufc_h1_message_type_values), H1_MASK,
+ "Message type", HFILL }},
+ { &hf_mtp3mg_coo_ansi_slc,
+ { "Signalling Link Code", "mtp3mg.slc",
+ FT_UINT8, BASE_DEC, NULL, ANSI_COO_SLC_MASK,
+ "SLC of affected link", HFILL }},
+ { &hf_mtp3mg_coo_ansi_fsn,
+ { "Forward Sequence Number", "mtp3mg.fsn",
+ FT_UINT8, BASE_DEC, NULL, ANSI_COO_FSN_MASK,
+ "Forward Sequence Number of last accepted message", HFILL }},
+ { &hf_mtp3mg_coo_itu_fsn,
+ { "Forward Sequence Number", "mtp3mg.fsn",
+ FT_UINT8, BASE_DEC, NULL, ITU_COO_FSN_MASK,
+ "Forward Sequence Number of last accepted message", HFILL }},
+ { &hf_mtp3mg_xco_ansi_slc,
+ { "Signalling Link Code", "mtp3mg.slc",
+ FT_UINT32, BASE_DEC, NULL, ANSI_XCO_SLC_MASK,
+ "SLC of affected link", HFILL }},
+ { &hf_mtp3mg_xco_ansi_fsn,
+ { "Forward Sequence Number", "mtp3mg.fsn",
+ FT_UINT32, BASE_DEC, NULL, ANSI_XCO_FSN_MASK,
+ "Forward Sequence Number of last accepted message", HFILL }},
+ { &hf_mtp3mg_xco_itu_fsn,
+ { "Forward Sequence Number", "mtp3mg.fsn",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Forward Sequence Number of last accepted message", HFILL }},
+ { &hf_mtp3mg_cbd_ansi_slc,
+ { "Signalling Link Code", "mtp3mg.slc",
+ FT_UINT16, BASE_DEC, NULL, ANSI_CBD_SLC_MASK,
+ "SLC of affected link", HFILL }},
+ { &hf_mtp3mg_cbd_ansi_cbc,
+ { "Change Back Code", "mtp3mg.cbc",
+ FT_UINT16, BASE_DEC, NULL, ANSI_CBD_CBC_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_cbd_itu_cbc,
+ { "Change Back Code", "mtp3mg.cbc",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3mg_eco_ansi_slc,
+ { "Signalling Link Code", "mtp3mg.slc",
+ FT_UINT8, BASE_DEC, NULL, ANSI_ECO_SLC_MASK,
+ "SLC of affected link", HFILL }},
+ { &hf_mtp3mg_tfc_ansi_apc,
+ { "Affected Point Code", "mtp3mg.ansi_apc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3mg_tfc_apc_member,
+ { "Affected Point Code member", "mtp3mg.apc.member",
+ FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_tfc_apc_cluster,
+ { "Affected Point Code cluster", "mtp3mg.apc.cluster",
+ FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_tfc_apc_network,
+ { "Affected Point Code network", "mtp3mg.apc.network",
+ FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_tfc_ansi_status,
+ { "Status", "mtp3mg.status",
+ FT_UINT8, BASE_DEC, NULL, ANSI_TFC_STATUS_MASK,
+ "Congestion status", HFILL }},
+ { &hf_mtp3mg_tfc_itu_apc,
+ { "Affected Point Code (ITU)", "mtp3mg.apc",
+ FT_UINT8, BASE_DEC, NULL, ITU_PC_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_tfc_itu_status,
+ { "Status", "mtp3mg.status",
+ FT_UINT8, BASE_DEC, NULL, ITU_TFC_STATUS_MASK,
+ "Congestion status", HFILL }},
+ { &hf_mtp3mg_tfc_chinese_apc,
+ { "Affected Point Code", "mtp3mg.chinese_apc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3mg_tfm_ansi_apc,
+ { "Affected Point Code", "mtp3mg.ansi_apc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3mg_tfm_apc_member,
+ { "Affected Point Code member", "mtp3mg.apc.member",
+ FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_tfm_apc_cluster,
+ { "Affected Point Code cluster", "mtp3mg.apc.cluster",
+ FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_tfm_apc_network,
+ { "Affected Point Code network", "mtp3mg.apc.network",
+ FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_tfm_itu_apc,
+ { "Affected Point Code (ITU)", "mtp3mg.apc",
+ FT_UINT8, BASE_DEC, NULL, ITU_PC_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_tfm_chinese_apc,
+ { "Affected Point Code", "mtp3mg.chinese_apc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3mg_rsm_ansi_apc,
+ { "Affected Point Code", "mtp3mg.ansi_apc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3mg_rsm_apc_member,
+ { "Affected Point Code member", "mtp3mg.apc.member",
+ FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_rsm_apc_cluster,
+ { "Affected Point Code cluster", "mtp3mg.apc.cluster",
+ FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_rsm_apc_network,
+ { "Affected Point Code network", "mtp3mg.apc.network",
+ FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_rsm_itu_apc,
+ { "Affected Point Code (ITU)", "mtp3mg.apc",
+ FT_UINT8, BASE_DEC, NULL, ITU_PC_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_rsm_chinese_apc,
+ { "Affected Point Code", "mtp3mg.chinese_apc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3mg_mim_ansi_slc,
+ { "Signalling Link Code", "mtp3mg.slc",
+ FT_UINT8, BASE_DEC, NULL, ANSI_MIM_SLC_MASK,
+ "SLC of affected link", HFILL }},
+ { &hf_mtp3mg_dlc_ansi_slc,
+ { "Signalling Link Code", "mtp3mg.slc",
+ FT_UINT8, BASE_DEC, NULL, ANSI_DLC_SLC_MASK,
+ "SLC of affected link", HFILL }},
+ { &hf_mtp3mg_dlc_ansi_link,
+ { "Link", "mtp3mg.link",
+ FT_UINT8, BASE_DEC, NULL, ANSI_DLC_LINK_MASK,
+ "CIC of BIC used to carry data", HFILL }},
+ { &hf_mtp3mg_dlc_itu_link,
+ { "Link", "mtp3mg.link",
+ FT_UINT8, BASE_DEC, NULL, ITU_DLC_LINK_MASK,
+ "CIC of BIC used to carry data", HFILL }},
+ { &hf_mtp3mg_upu_ansi_apc,
+ { "Affected Point Code", "mtp3mg.ansi_apc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3mg_upu_apc_member,
+ { "Affected Point Code member", "mtp3mg.apc.member",
+ FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_upu_apc_cluster,
+ { "Affected Point Code cluster", "mtp3mg.apc.cluster",
+ FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_upu_apc_network,
+ { "Affected Point Code network", "mtp3mg.apc.network",
+ FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_upu_itu_apc,
+ { "Affected Point Code", "mtp3mg.apc",
+ FT_UINT8, BASE_DEC, NULL, ITU_PC_MASK,
+ "", HFILL }},
+ { &hf_mtp3mg_upu_chinese_apc,
+ { "Affected Point Code", "mtp3mg.chinese_apc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_mtp3mg_upu_user,
+ { "User", "mtp3mg.user",
+ FT_UINT8, BASE_HEX, VALS(service_indicator_code_vals), UPU_USER_MASK,
+ "Unavailable user part", HFILL }},
+ { &hf_mtp3mg_upu_cause,
+ { "Cause", "mtp3mg.cause",
+ FT_UINT8, BASE_HEX, VALS(upu_cause_values), UPU_CAUSE_MASK,
+ "Cause of user unavailability", HFILL }},
+ { &hf_mtp3test_h0,
+ { "H0 (Message Group)", "mtp3mg.test.h0",
+ FT_UINT8, BASE_HEX, VALS(test_h0_message_type_values), H0_MASK,
+ "Message group identifier", HFILL }},
+ { &hf_mtp3mg_test_h1,
+ { "H1 (Message)", "mtp3mg.test.h1",
+ FT_UINT8, BASE_HEX, VALS(test_h1_message_type_values), H1_MASK,
+ "SLT message type", HFILL }},
+ { &hf_mtp3mg_test_length,
+ { "Test length", "mtp3mg.test.length",
+ FT_UINT8, BASE_DEC, NULL, H1_MASK,
+ "Signalling link test pattern length", HFILL }},
+ { &hf_mtp3mg_test_ansi_slc,
+ { "Signalling Link Code", "mtp3mg.slc",
+ FT_UINT8, BASE_DEC, NULL, ANSI_TEST_SLC_MASK,
+ "SLC of affected link", HFILL }}
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_mtp3mg,
+ &ett_mtp3mg_fcm_apc,
+ &ett_mtp3mg_tfm_apc,
+ &ett_mtp3mg_rsm_apc,
+ &ett_mtp3mg_upu_apc
+ };
+
+ /* Register the protocol name and description */
+ proto_mtp3mg = proto_register_protocol("Message Transfer Part Level 3 Management",
+ "MTP3MG", "mtp3mg");
+ register_dissector("mtp3mg", dissect_mtp3mg, proto_mtp3mg);
+
+ /* Required calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_mtp3mg, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_mtp3mg(void)
+{
+ dissector_handle_t mtp3mg_handle;
+
+ mtp3mg_handle = create_dissector_handle(dissect_mtp3mg, proto_mtp3mg);
+
+ dissector_add("mtp3.service_indicator", MTP3MG_SI, mtp3mg_handle);
+
+ /* SI 1 is unused in ANSI and SI 2 is unused in ITU, so it's okay for us
+ * to grab both (regardless of mtp3.standard setting) here.
+ */
+ dissector_add("mtp3.service_indicator", MTP3MG_ITU_TEST_SI, mtp3mg_handle);
+ dissector_add("mtp3.service_indicator", MTP3MG_ANSI_TEST_SI, mtp3mg_handle);
+}
+
diff --git a/epan/dissectors/packet-multipart.c b/epan/dissectors/packet-multipart.c
new file mode 100644
index 0000000000..55942c4ba4
--- /dev/null
+++ b/epan/dissectors/packet-multipart.c
@@ -0,0 +1,933 @@
+/* packet-multipart.c
+ * Routines for multipart media encapsulation dissection
+ * Copyright 2004, Anders Broman.
+ * Copyright 2004, Olivier Biot.
+ *
+ * $Id$
+ *
+ * Refer to the AUTHORS file or the AUTHORS section in the man page
+ * for contacting the author(s) of this file.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * References for "media-type multipart/mixed :
+ * http://www.iana.org/assignments/media-types/index.html
+ * http://www.rfc-editor.org/rfc/rfc2045.txt
+ * http://www.rfc-editor.org/rfc/rfc2046.txt
+ * http://www.rfc-editor.org/rfc/rfc2047.txt
+ * http://www.rfc-editor.org/rfc/rfc2048.txt
+ * http://www.rfc-editor.org/rfc/rfc2049.txt
+ *
+ * Part of the code is modeled from the SIP and HTTP dissectors
+ *
+ * General format of a MIME multipart document:
+ * [ preamble line-end ]
+ * dash-boundary transport-padding line-end
+ * body-part
+ * *encapsulation
+ * close-delimiter transport-padding
+ * [ line-end epilogue ]
+ *
+ * Where:
+ * dash-boundary := "--" boundary
+ * encapsulation := delimiter transport-padding line-end body-part
+ * delimiter := line-end body-part
+ * close-delimiter := delimiter "--"
+ * body-part := MIME-part-headers [ line-end *OCTET ]
+ * transport-padding := *LWSP-char
+ *
+ * Note that line-end is often a LF instead of a CRLF.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "prefs.h"
+#include <glib.h>
+#include <ctype.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+
+/* Dissector table for media requiring special attention in multipart
+ * encapsulation. */
+static dissector_table_t multipart_media_subdissector_table;
+
+/* Initialize the protocol and registered fields */
+static int proto_multipart = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_multipart = -1;
+static gint ett_multipart_main = -1;
+static gint ett_multipart_body = -1;
+
+/* Not sure that compact_name exists for multipart, but choose to keep
+ * the structure from SIP dissector, all the content- is also from SIP */
+
+
+static const char *multipart_headers[] = {
+ "Unknown-header", /* Pad so that the real headers start at index 1 */
+ "Content-Disposition",
+ "Content-Encoding",
+ "Content-Language",
+ "Content-Length",
+ "Content-Type",
+};
+
+#define POS_CONTENT_DISPOSITION 1
+#define POS_CONTENT_ENCODING 2
+#define POS_CONTENT_LANGUAGE 3
+#define POS_CONTENT_LENGTH 4
+#define POS_CONTENT_TYPE 5
+
+/* Initialize the header fields */
+static gint hf_multipart_type = -1;
+static gint hf_header_array[] = {
+ -1, /* "Unknown-header" - Pad so that the real headers start at index 1 */
+ -1, /* "Content-Disposition" */
+ -1, /* "Content-Encoding" */
+ -1, /* "Content-Language" */
+ -1, /* "Content-Length" */
+ -1, /* "Content-Type" */
+};
+
+/* Define media_type/Content type table */
+static dissector_table_t media_type_dissector_table;
+
+/* Data and media dissector handles */
+static dissector_handle_t data_handle;
+static dissector_handle_t media_handle;
+
+/* Determins if bodies with no media type dissector shoud be displayed
+ * as raw text, may cause problems with images sound etc
+ * TODO improve to check for different content types ?
+ */
+static gboolean display_unknown_body_as_text = FALSE;
+
+
+typedef struct {
+ const char *type; /* Type of multipart */
+ char *boundary; /* Boundary string (enclosing quotes removed if any) */
+ guint boundary_length; /* Length of the boundary string */
+} multipart_info_t;
+
+
+
+static gint
+find_first_boundary(tvbuff_t *tvb, gint start, const guint8 *boundary,
+ gint boundary_len, gint *boundary_line_len, gboolean *last_boundary);
+static gint
+find_next_boundary(tvbuff_t *tvb, gint start, const guint8 *boundary,
+ gint boundary_len, gint *boundary_line_len, gboolean *last_boundary);
+static gint
+process_preamble(proto_tree *tree, tvbuff_t *tvb, const guint8 *boundary,
+ gint boundary_len, gboolean *last_boundary);
+static gint
+process_body_part(proto_tree *tree, tvbuff_t *tvb, const guint8 *boundary,
+ gint boundary_len, packet_info *pinfo, gint start,
+ gboolean *last_boundary);
+static gint
+is_known_multipart_header(const char *header_str, guint len);
+static gint
+index_of_char(const char *str, const char c);
+char *
+unfold_and_compact_mime_header(const char *lines, gint *first_colon_offset);
+
+/*
+ * Unfold and clean up a MIME-like header, and process LWS as follows:
+ * o Preserves LWS in quoted text
+ * o Remove LWS before and after a separator
+ * o Remove trailing LWS
+ * o Replace other LWS with a single space
+ * Set value to the start of the value
+ * Return the cleaned-up RFC2822 header (buffer must be freed).
+ */
+char *
+unfold_and_compact_mime_header(const char *lines, gint *first_colon_offset)
+{
+ const char *p = lines;
+ char c;
+ char *ret, *q;
+ char sep_seen = 0; /* Did we see a separator ":;," */
+ char lws = FALSE; /* Did we see LWS (incl. folding) */
+ gint colon = -1;
+
+ if (! lines) return NULL;
+
+ c = *p;
+ ret = g_malloc(strlen(lines) + 1);
+ q = ret;
+
+ while (c) {
+ if (c == ':') {
+ lws = FALSE; /* Prevent leading LWS from showing up */
+ if (colon == -1) {/* First colon */
+ colon = q - ret;
+ }
+ *(q++) = sep_seen = c;
+ p++;
+ } else if (c == ';' || c == ',' || c == '=') {
+ lws = FALSE; /* Prevent leading LWS from showing up */
+ *(q++) = sep_seen = c;
+ p++;
+ } else if (c == ' ' || c == '\t') {
+ lws = TRUE;
+ p++;
+ } else if (c == '\n') {
+ lws = FALSE; /* Skip trailing LWS */
+ if ((c = *(p+1))) {
+ if (c == ' ' || c == '\t') { /* Header unfolding */
+ lws = TRUE;
+ p += 2;
+ } else {
+ *q = c = 0; /* Stop */
+ }
+ }
+ } else if (c == '\r') {
+ lws = FALSE;
+ if ((c = *(p+1))) {
+ if (c == '\n') {
+ if ((c = *(p+2))) {
+ if (c == ' ' || c == '\t') { /* Header unfolding */
+ lws = TRUE;
+ p += 3;
+ } else {
+ *q = c = 0; /* Stop */
+ }
+ }
+ } else if (c == ' ' || c == '\t') { /* Header unfolding */
+ lws = TRUE;
+ p += 2;
+ } else {
+ *q = c = 0; /* Stop */
+ }
+ }
+ } else if (c == '"') { /* Start of quoted-string */
+ lws = FALSE;
+ *(q++) = c;
+ while (c) {
+ c = *(q++) = *(++p);
+ if (c == '"') {
+ p++; /* Skip closing quote */
+ break;
+ }
+ }
+ } else { /* Regular character */
+ if (sep_seen) {
+ sep_seen = 0;
+ lws = FALSE;
+ } else {
+ if (lws) {
+ *(q++) = ' ';
+ lws = FALSE;
+ }
+ }
+ lws = FALSE;
+ *(q++) = c;
+ p++; /* OK */
+ }
+
+ if (c) {
+ c = *p;
+ }
+ }
+ *q = 0;
+
+ *first_colon_offset = colon;
+ return (ret);
+}
+
+/* Return the index of a given char in the given string,
+ * or -1 if not found.
+ */
+static gint
+index_of_char(const char *str, const char c)
+{
+ gint len = 0;
+ const char *p = str;
+
+ while (*p && *p != c) {
+ p++;
+ len++;
+ }
+
+ if (*p)
+ return len;
+ return -1;
+}
+
+/* Retrieve the media information from pinfo->private_data,
+ * and compute the boundary string and its length.
+ * Return a pointer to a filled-in multipart_info_t, or NULL on failure.
+ *
+ * Boundary delimiters must not appear within the encapsulated material,
+ * and must be no longer than 70 characters, not counting the two
+ * leading hyphens. (quote from rfc2046)
+ */
+static multipart_info_t *
+get_multipart_info(packet_info *pinfo)
+{
+ const char *start, *p;
+ int len = 0;
+ multipart_info_t *m_info = NULL;
+ const char *type = pinfo->match_string;
+ const char *parameters = pinfo->private_data;
+ gint dummy;
+
+ if ((type == NULL) || (parameters == NULL)) {
+ /*
+ * We need both a content type AND parameters
+ * for multipart dissection.
+ */
+ return NULL;
+ }
+
+ /* Clean up the parameters */
+ parameters = unfold_and_compact_mime_header(parameters, &dummy);
+
+ /*
+ * Process the private data
+ * The parameters must contain the boundary string
+ */
+ p = parameters;
+ while (*p) {
+ if (strncasecmp(p, "boundary=", 9) == 0)
+ break;
+ /* Skip to next parameter */
+ p = strchr(p, ';');
+ if (p == NULL)
+ return NULL;
+ p++; /* Skip semicolon */
+ while ((*p) && isspace((guchar)*p))
+ p++; /* Skip white space */
+ }
+ start = p + 9;
+ if (start[0] == 0) {
+ return NULL;
+ }
+
+ /*
+ * Process the parameter value
+ */
+ if (start[0] == '"') {
+ /*
+ * Boundary string is a quoted-string
+ */
+ start++; /* Skip the quote */
+ len = index_of_char(start, '"');
+ if (len < 0) {
+ /*
+ * No closing quote
+ */
+ return NULL;
+ }
+ } else {
+ /*
+ * Look for end of boundary
+ */
+ p = start;
+ while (*p) {
+ if (*p == ';' || isspace((guchar)*p))
+ break;
+ p++;
+ len++;
+ }
+ }
+ /*
+ * There is a value for the boundary string
+ */
+ m_info = g_malloc(sizeof(multipart_info_t));
+ m_info->type = type;
+ m_info->boundary = g_strndup(start, len);
+ m_info->boundary_length = len;
+
+ return m_info;
+}
+
+static void
+cleanup_multipart_info(void *data)
+{
+ multipart_info_t *m_info = data;
+ if (m_info) {
+ if (m_info->boundary)
+ g_free(m_info->boundary);
+ g_free(m_info);
+ }
+}
+
+/*
+ * The first boundary does not implicitly contain the leading
+ * line-end sequence.
+ *
+ * Return the offset to the 1st byte of the boundary delimiter line.
+ * Set boundary_line_len to the length of the entire boundary delimiter.
+ * Set last_boundary to TRUE if we've seen the last-boundary delimiter.
+ */
+static gint
+find_first_boundary(tvbuff_t *tvb, gint start, const guint8 *boundary,
+ gint boundary_len, gint *boundary_line_len, gboolean *last_boundary)
+{
+ gint offset = start, next_offset, line_len, boundary_start;
+
+ while (tvb_length_remaining(tvb, offset + 2 + boundary_len) > 0) {
+ boundary_start = offset;
+ if (((tvb_strneql(tvb, offset, (const guint8 *)"--", 2) == 0)
+ && (tvb_strneql(tvb, offset + 2, boundary, boundary_len) == 0)))
+ {
+ /* Boundary string; now check if last */
+ if ((tvb_length_remaining(tvb, offset + 2 + boundary_len + 2) >= 0)
+ && (tvb_strneql(tvb, offset + 2 + boundary_len,
+ (const guint8 *)"--", 2) == 0)) {
+ *last_boundary = TRUE;
+ } else {
+ *last_boundary = FALSE;
+ }
+ /* Look for line end of the boundary line */
+ line_len = tvb_find_line_end(tvb, offset, -1, &offset, FALSE);
+ if (line_len == -1) {
+ *boundary_line_len = -1;
+ } else {
+ *boundary_line_len = offset - boundary_start;
+ }
+ return boundary_start;
+ }
+ line_len = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ if (line_len == -1) {
+ return -1;
+ }
+ offset = next_offset;
+ }
+
+ return -1;
+}
+
+/*
+ * Unless the first boundary, subsequent boundaries include a line-end sequence
+ * before the dashed boundary string.
+ *
+ * Return the offset to the 1st byte of the boundary delimiter line.
+ * Set boundary_line_len to the length of the entire boundary delimiter.
+ * Set last_boundary to TRUE if we've seen the last-boundary delimiter.
+ */
+static gint
+find_next_boundary(tvbuff_t *tvb, gint start, const guint8 *boundary,
+ gint boundary_len, gint *boundary_line_len, gboolean *last_boundary)
+{
+ gint offset = start, next_offset, line_len, boundary_start;
+
+ while (tvb_length_remaining(tvb, offset + 2 + boundary_len) > 0) {
+ line_len = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ if (line_len == -1) {
+ return -1;
+ }
+ boundary_start = offset + line_len;
+ if (((tvb_strneql(tvb, next_offset, (const guint8 *)"--", 2) == 0)
+ && (tvb_strneql(tvb, next_offset + 2, boundary, boundary_len) == 0)))
+ {
+ /* Boundary string; now check if last */
+ if ((tvb_length_remaining(tvb, next_offset + 2 + boundary_len + 2) >= 0)
+ && (tvb_strneql(tvb, next_offset + 2 + boundary_len,
+ (const guint8 *)"--", 2) == 0)) {
+ *last_boundary = TRUE;
+ } else {
+ *last_boundary = FALSE;
+ }
+ /* Look for line end of the boundary line */
+ line_len = tvb_find_line_end(tvb, next_offset, -1, &offset, FALSE);
+ if (line_len == -1) {
+ *boundary_line_len = -1;
+ } else {
+ *boundary_line_len = offset - boundary_start;
+ }
+ return boundary_start;
+ }
+ offset = next_offset;
+ }
+
+ return -1;
+}
+
+/*
+ * Process the multipart preamble:
+ * [ preamble line-end ] dashed-boundary transport-padding line-end
+ *
+ * Return the offset to the start of the first body-part.
+ */
+static gint
+process_preamble(proto_tree *tree, tvbuff_t *tvb, const guint8 *boundary,
+ gint boundary_len, gboolean *last_boundary)
+{
+ gint boundary_start, boundary_line_len, body_part_start;
+
+ body_part_start = 0;
+ boundary_start = find_first_boundary(tvb, 0, boundary, boundary_len,
+ &boundary_line_len, last_boundary);
+ if (boundary_start == 0) {
+ if (tree) {
+ proto_tree_add_text(tree, tvb, boundary_start, boundary_line_len,
+ "First boundary: %s",
+ tvb_format_text(tvb, boundary_start, boundary_line_len));
+ }
+ return boundary_start + boundary_line_len;
+ } else if (boundary_start > 0) {
+ if (boundary_line_len > 0) {
+ gint body_part_start = boundary_start + boundary_line_len;
+
+ if (tree) {
+ if (body_part_start > 0) {
+ proto_tree_add_text(tree, tvb, 0, body_part_start,
+ "Preamble");
+ }
+ proto_tree_add_text(tree, tvb, boundary_start,
+ boundary_line_len, "First boundary: %s",
+ tvb_format_text(tvb, boundary_start,
+ boundary_line_len));
+ }
+ return body_part_start;
+ }
+ }
+ return -1;
+}
+
+/*
+ * Process a multipart body-part:
+ * MIME-part-headers [ line-end *OCTET ]
+ * line-end dashed-boundary transport-padding line-end
+ *
+ * If applicable, call a media subdissector.
+ *
+ * Return the offset to the start of the next body-part.
+ */
+static gint
+process_body_part(proto_tree *tree, tvbuff_t *tvb, const guint8 *boundary,
+ gint boundary_len, packet_info *pinfo, gint start,
+ gboolean *last_boundary)
+{
+ proto_tree *subtree = NULL;
+ proto_item *ti = NULL;
+ gint offset = start, next_offset;
+ gint line_len = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ char *parameters = NULL;
+ gint body_start, boundary_start, boundary_line_len;
+
+ char *content_type_str = NULL;
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, start, 0,
+ "Encapsulated multipart part");
+ subtree = proto_item_add_subtree(ti, ett_multipart_body);
+ }
+ /*
+ * Process the MIME-part-headers
+ */
+
+ while (line_len > 0)
+ {
+ gint colon_offset;
+ char *header_str = tvb_get_string(tvb, offset, next_offset - offset);
+
+ header_str = unfold_and_compact_mime_header(header_str, &colon_offset);
+ if (colon_offset <= 0) {
+ if (tree) {
+ proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
+ "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ }
+ } else {
+ gint hf_index;
+
+ /* Split header name from header value */
+ header_str[colon_offset] = '\0';
+ hf_index = is_known_multipart_header(header_str, colon_offset);
+
+ if (hf_index == -1) {
+ if (tree) {
+ proto_tree_add_text(subtree, tvb, offset,
+ next_offset - offset,
+ "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ }
+ } else {
+ char *value_str = header_str + colon_offset + 1;
+
+ if (tree) {
+ proto_tree_add_string_format(subtree,
+ hf_header_array[hf_index], tvb,
+ offset, next_offset - offset,
+ (const char *)value_str, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ }
+
+ switch (hf_index) {
+ case POS_CONTENT_TYPE:
+ {
+ /* The Content-Type starts at colon_offset + 1 */
+ gint semicolon_offset = index_of_char(
+ value_str, ';');
+
+ if (semicolon_offset > 0) {
+ value_str[semicolon_offset] = '\0';
+ parameters = value_str + semicolon_offset + 1;
+ } else {
+ parameters = NULL;
+ }
+#if GLIB_MAJOR_VERSION < 2
+ content_type_str = g_strdup(value_str);
+ g_strdown(content_type_str);
+#else
+ content_type_str = g_ascii_strdown(value_str, -1);
+#endif
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ offset = next_offset;
+ line_len = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ }
+ if (line_len < 0) {
+ /* ERROR */
+ return -1;
+ }
+ proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
+ "%s", tvb_format_text(tvb, offset, next_offset - offset));
+
+ body_start = next_offset;
+
+ /*
+ * Process the body
+ */
+
+ boundary_start = find_next_boundary(tvb, body_start, boundary, boundary_len,
+ &boundary_line_len, last_boundary);
+ if (boundary_start > 0) {
+ gint body_len = boundary_start - body_start;
+ tvbuff_t *tmp_tvb = tvb_new_subset(tvb, body_start,
+ body_len, body_len);
+
+ if (content_type_str) {
+ /*
+ * subdissection
+ */
+ void *save_private_data = pinfo->private_data;
+ gboolean dissected;
+
+ pinfo->private_data = parameters;
+ /*
+ * First try the dedicated multipart dissector table
+ */
+ dissected = dissector_try_string(multipart_media_subdissector_table,
+ content_type_str, tmp_tvb, pinfo, subtree);
+ if (! dissected) {
+ /*
+ * Fall back to the default media dissector table
+ */
+ dissected = dissector_try_string(media_type_dissector_table,
+ content_type_str, tmp_tvb, pinfo, subtree);
+ }
+ pinfo->private_data = save_private_data;
+ g_free(content_type_str);
+ content_type_str = NULL;
+ parameters = NULL; /* Shares same memory as content_type_str */
+ if (! dissected) {
+ call_dissector(media_handle, tmp_tvb, pinfo, tree);
+ }
+ } else {
+ call_dissector(data_handle, tmp_tvb, pinfo, subtree);
+ }
+ if (tree) {
+ if (*last_boundary == TRUE) {
+ proto_tree_add_text(tree, tvb,
+ boundary_start, boundary_line_len,
+ "Last boundary: %s",
+ tvb_format_text(tvb, boundary_start,
+ boundary_line_len));
+ } else {
+ proto_tree_add_text(tree, tvb,
+ boundary_start, boundary_line_len,
+ "Boundary: %s",
+ tvb_format_text(tvb, boundary_start,
+ boundary_line_len));
+ }
+ }
+ return boundary_start + boundary_line_len;
+ }
+
+ return -1;
+}
+
+/*
+ * Call this method to actually dissect the multipart body.
+ * NOTE - Only do so if a boundary string has been found!
+ */
+static void dissect_multipart(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_tree *subtree = NULL;
+ proto_item *ti = NULL;
+ multipart_info_t *m_info = get_multipart_info(pinfo);
+ gint header_start = 0;
+ guint8 *boundary;
+ gint boundary_len;
+ gint offset = 0;
+ gboolean last_boundary = FALSE;
+
+ if (m_info == NULL) {
+ /*
+ * We can't get the required multipart information
+ */
+ proto_tree_add_text(tree, tvb, 0, -1,
+ "The multipart dissector could not find "
+ "the required boundary parameter.");
+ call_dissector(data_handle, tvb, pinfo, tree);
+ return;
+ }
+ boundary = (guint8 *)m_info->boundary;
+ boundary_len = m_info->boundary_length;
+ /* Clean up the memory if an exception is thrown */
+ /* CLEANUP_PUSH(cleanup_multipart_info, m_info); */
+
+ /* Add stuff to the protocol tree */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_multipart,
+ tvb, 0, -1, FALSE);
+ subtree = proto_item_add_subtree(ti, ett_multipart);
+ proto_item_append_text(ti, ", Type: %s, Boundary: \"%s\"",
+ m_info->type, m_info->boundary);
+ proto_tree_add_string(subtree, hf_multipart_type,
+ tvb, 0, 0, pinfo->match_string);
+ }
+
+ /*
+ * Make no entries in Protocol column and Info column on summary display,
+ * but stop sub-dissectors from clearing entered text in summary display.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_fence(pinfo->cinfo, COL_INFO);
+
+ offset = 0;
+
+ /*
+ * Process the multipart preamble
+ */
+ header_start = process_preamble(subtree, tvb, boundary,
+ boundary_len, &last_boundary);
+ if (header_start == -1) {
+ call_dissector(data_handle, tvb, pinfo, subtree);
+ /* Clean up the dynamically allocated memory */
+ cleanup_multipart_info(m_info);
+ return;
+ }
+ /*
+ * Process the encapsulated bodies
+ */
+ while (last_boundary == FALSE) {
+ header_start = process_body_part(subtree, tvb, boundary, boundary_len,
+ pinfo, header_start, &last_boundary);
+ if (header_start == -1) {
+ /* Clean up the dynamically allocated memory */
+ cleanup_multipart_info(m_info);
+ return;
+ }
+ }
+ /*
+ * Process the multipart trailer
+ */
+ if (tree) {
+ if (tvb_length_remaining(tvb, header_start) > 0) {
+ proto_tree_add_text(subtree, tvb, header_start, -1, "Trailer");
+ }
+ }
+ /* Clean up the dynamically allocated memory */
+ cleanup_multipart_info(m_info);
+ return;
+}
+
+/* Returns index of method in multipart_headers */
+static gint
+is_known_multipart_header(const char *header_str, guint len)
+{
+ guint i;
+
+ for (i = 1; i < array_length(multipart_headers); i++) {
+ if (len == strlen(multipart_headers[i]) &&
+ strncasecmp(header_str, multipart_headers[i], len) == 0) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * Register the protocol with Ethereal.
+ *
+ * This format is required because a script is used to build the C function
+ * that calls all the protocol registration.
+ */
+
+void
+proto_register_multipart(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details */
+ static hf_register_info hf[] = {
+ { &hf_multipart_type,
+ { "Type",
+ "mime_multipart.type",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RFC 3261: MIME multipart encapsulation type", HFILL
+ }
+ },
+ { &hf_header_array[POS_CONTENT_DISPOSITION],
+ { "Content-Disposition",
+ "mime_multipart.header.content-disposition",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RFC 3261: Content-Disposition Header", HFILL
+ }
+ },
+ { &hf_header_array[POS_CONTENT_ENCODING],
+ { "Content-Encoding",
+ "mime_multipart.header.content-encoding",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RFC 3261: Content-Encoding Header", HFILL
+ }
+ },
+ { &hf_header_array[POS_CONTENT_LANGUAGE],
+ { "Content-Language",
+ "mime_multipart.header.content-language",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "RFC 3261: Content-Language Header", HFILL
+ }
+ },
+ { &hf_header_array[POS_CONTENT_LENGTH],
+ { "Content-Length",
+ "mime_multipart.header.content-length",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "RFC 3261: Content-Length Header", HFILL
+ }
+ },
+ { &hf_header_array[POS_CONTENT_TYPE],
+ { "Content-Type",
+ "mime_multipart.header.content-type",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Content-Type Header", HFILL
+ }
+ },
+ };
+
+ /*
+ * Preferences
+ */
+ module_t *multipart_module;
+
+ /*
+ * Setup protocol subtree array
+ */
+ static gint *ett[] = {
+ &ett_multipart,
+ &ett_multipart_main,
+ &ett_multipart_body,
+ };
+
+ /*
+ * Register the protocol name and description
+ */
+ proto_multipart = proto_register_protocol(
+ "MIME Multipart Media Encapsulation",
+ "MIME multipart",
+ "mime_multipart");
+
+ /*
+ * Required function calls to register
+ * the header fields and subtrees used.
+ */
+ proto_register_field_array(proto_multipart, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /*
+ * Get the content type and Internet media type table
+ */
+ media_type_dissector_table = find_dissector_table("media_type");
+
+ multipart_module = prefs_register_protocol(proto_multipart, NULL);
+
+ prefs_register_bool_preference(multipart_module,
+ "display_unknown_body_as_text",
+ "Display bodies without media type as text",
+ "Display multipart bodies with no media type dissector"
+ " as raw text (may cause problems with binary data).",
+ &display_unknown_body_as_text);
+
+ /*
+ * Dissectors requiring different behavior in cases where the media
+ * is contained in a multipart entity should register their multipart
+ * dissector in the dissector table below, which is similar to the
+ * "media_type" dissector table defined in the HTTP dissector code.
+ */
+ multipart_media_subdissector_table = register_dissector_table(
+ "multipart_media_type",
+ "Internet media type (for multipart processing)",
+ FT_STRING, BASE_NONE);
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_multipart(void)
+{
+ dissector_handle_t multipart_handle;
+
+ /*
+ * When we cannot display the data, call the data dissector.
+ * When there is no dissector for the given media, call the media dissector.
+ */
+ data_handle = find_dissector("data");
+ media_handle = find_dissector("media");
+
+ /*
+ * Handle for multipart dissection
+ */
+ multipart_handle = create_dissector_handle(
+ dissect_multipart, proto_multipart);
+
+ dissector_add_string("media_type",
+ "multipart/mixed", multipart_handle);
+ dissector_add_string("media_type",
+ "multipart/related", multipart_handle);
+ dissector_add_string("media_type",
+ "multipart/alternative", multipart_handle);
+ dissector_add_string("media_type",
+ "multipart/form-data", multipart_handle);
+
+}
diff --git a/epan/dissectors/packet-mysql.c b/epan/dissectors/packet-mysql.c
new file mode 100644
index 0000000000..bda5bf6fb3
--- /dev/null
+++ b/epan/dissectors/packet-mysql.c
@@ -0,0 +1,819 @@
+/* packet-mysql.c
+ * Routines for mysql packet dissection
+ *
+ * Huagang XIE <huagang@intruvert.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * the protocol spec at
+ * http://public.logicacmg.com/~redferni/mysql/MySQL-Protocol.html
+ * and MySQL source code
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include "packet-tcp.h"
+#include "reassemble.h"
+#include "prefs.h"
+
+/* Capabilities */
+#define MYSQL_CAPS_LP 0x0001
+#define MYSQL_CAPS_FR 0x0002
+#define MYSQL_CAPS_LF 0x0004
+#define MYSQL_CAPS_CD 0x0008
+#define MYSQL_CAPS_NS 0x0010
+#define MYSQL_CAPS_CP 0x0020
+#define MYSQL_CAPS_OB 0x0040
+#define MYSQL_CAPS_LI 0x0080
+#define MYSQL_CAPS_IS 0x0100
+#define MYSQL_CAPS_CU 0x0200
+#define MYSQL_CAPS_IA 0x0400
+#define MYSQL_CAPS_SL 0x0800
+#define MYSQL_CAPS_II 0x1000
+#define MYSQL_CAPS_TA 0x2000
+
+static int proto_mysql = -1;
+static int hf_mysql_packet_length= -1;
+static int hf_mysql_packet_number= -1;
+static int hf_mysql_opcode= -1;
+static int hf_mysql_response_code= -1;
+static int hf_mysql_error_code= -1;
+static int hf_mysql_payload= -1;
+static int hf_mysql_protocol= -1;
+static int hf_mysql_caps= -1;
+static int hf_mysql_cap_long_password= -1;
+static int hf_mysql_cap_found_rows= -1;
+static int hf_mysql_cap_long_flag= -1;
+static int hf_mysql_cap_connect_with_db= -1;
+static int hf_mysql_cap_no_schema= -1;
+static int hf_mysql_cap_compress= -1;
+static int hf_mysql_cap_odbc= -1;
+static int hf_mysql_cap_local_files= -1;
+static int hf_mysql_cap_ignore_space= -1;
+static int hf_mysql_cap_change_user= -1;
+static int hf_mysql_cap_interactive= -1;
+static int hf_mysql_cap_ssl= -1;
+static int hf_mysql_cap_ignore_sigpipe= -1;
+static int hf_mysql_cap_transactions= -1;
+static int hf_mysql_version = -1;
+static int hf_mysql_max_packet= -1;
+static int hf_mysql_user= -1;
+static int hf_mysql_password= -1;
+static int hf_mysql_thread_id = -1;
+static int hf_mysql_salt= -1;
+static int hf_mysql_charset= -1;
+static int hf_mysql_status= -1;
+static int hf_mysql_unused= -1;
+static int hf_mysql_parameter= -1;
+
+static gint ett_mysql = -1;
+static gint ett_server_greeting = -1;
+static gint ett_caps = -1;
+static gint ett_request = -1;
+
+static gboolean mysql_desegment = TRUE;
+
+#define TCP_PORT_MySQL 3306
+
+#define MySQL_SLEEP 0
+#define MySQL_QUIT 1
+#define MySQL_INIT_DB 2
+#define MySQL_QUERY 3
+#define MySQL_FIELD_LIST 4
+#define MySQL_CREATE_DB 5
+#define MySQL_DROP_DB 6
+#define MySQL_REFRESH 7
+#define MySQL_SHUTDOWN 8
+#define MySQL_STATISTICS 9
+#define MySQL_PROCESS_INFO 10
+#define MySQL_CONNECT 11
+#define MySQL_PROCESS_KILL 12
+#define MySQL_DEBUG 13
+#define MySQL_PING 14
+#define MySQL_TIME 15
+#define MySQL_DELAY_INSERT 16
+#define MySQL_CHANGE_USER 17
+#define MySQL_BINLOG_DUMP 18
+#define MySQL_TABLE_DUMP 19
+#define MySQL_CONNECT_OUT 20
+
+
+static const value_string mysql_opcode_vals[] = {
+ { MySQL_SLEEP, "SLEEP" },
+ { MySQL_QUIT, "Quit" },
+ { MySQL_INIT_DB, "Init Database" },
+ { MySQL_QUERY, "Query" },
+ { MySQL_FIELD_LIST, "Field List" },
+ { MySQL_CREATE_DB, "Create Database" },
+ { MySQL_DROP_DB , "Drop Database" },
+ { MySQL_REFRESH , "Refresh" },
+ { MySQL_SHUTDOWN , "Shutdown" },
+ { MySQL_STATISTICS , "Statistics" },
+ { MySQL_PROCESS_INFO , "Process Info" },
+ { MySQL_CONNECT , "Connect" },
+ { MySQL_PROCESS_KILL , "Process Kill" },
+ { MySQL_DEBUG , "Debug" },
+ { MySQL_PING , "Ping" },
+ { MySQL_TIME , "Time" },
+ { MySQL_DELAY_INSERT , "Delay Insert" },
+ { MySQL_CHANGE_USER , "Change User" },
+ { MySQL_BINLOG_DUMP , "Binlog Dump" },
+ { MySQL_TABLE_DUMP, "Table Dump" },
+ { MySQL_CONNECT_OUT, "Table Connect Out" },
+ { 0, NULL }
+};
+
+static const value_string mysql_status_vals[] = {
+ {1, "IN_TRANS" },
+ {2, "AUTOCOMMIT"},
+ { 0, NULL }
+};
+static const value_string mysql_charset_vals[] = {
+ {1, "big5"},
+ {2, "czech"},
+ {3,"dec8"},
+ {4, "dos" },
+ {5,"german1"},
+ {6,"hp8"},
+ {7,"koi8_ru"},
+ {8,"latin1"},
+ {9,"latin2"},
+ {9,"swe7 "},
+ {10,"usa7"},
+ {11,"ujis"},
+ {12,"sjis"},
+ {13,"cp1251"},
+ {14,"danish"},
+ {15,"hebrew"},
+ {16,"win1251"},
+ {17,"tis620"},
+ {18,"euc_kr"},
+ {19,"estonia"},
+ {20,"hungarian"},
+ {21,"koi8_ukr"},
+ {22,"win1251ukr"},
+ {23,"gb2312"},
+ {24,"greek"},
+ {25,"win1250"},
+ {26,"croat"},
+ {27,"gbk"},
+ {28,"cp1257"},
+ {29,"latin5"},
+ {0,NULL}
+};
+#if 0
+static const value_string mysql_error_code_vals[] = {
+ { 0, "Not defined" },
+ { 1, "File not found" },
+ { 2, "Access violation" },
+ { 3, "Disk full or allocation exceeded" },
+ { 4, "Illegal MySQL Operation" },
+ { 5, "Unknown transfer ID" },
+ { 6, "File already exists" },
+ { 7, "No such user" },
+ { 8, "Option negotiation failed" },
+ { 0, NULL }
+};
+#endif
+
+static guint get_mysql_pdu_len(tvbuff_t *tvb, int offset);
+static void dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree);
+static int mysql_dissect_server_greeting(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+static int mysql_dissect_authentication(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+static int mysql_dissect_request(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+static int mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree);
+
+static void
+dissect_mysql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, mysql_desegment, 3,
+ get_mysql_pdu_len, dissect_mysql_pdu);
+}
+
+static guint
+get_mysql_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint plen;
+
+ /*
+ * Get the length of the MySQL packet.
+ */
+ plen = tvb_get_letoh24(tvb, offset);
+
+ /*
+ * That length doesn't include the length field or the packet
+ * number itself; add them in.
+ */
+ return plen + 4;
+}
+
+static void
+dissect_mysql_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *mysql_tree = NULL;
+ proto_item *ti;
+ conversation_t *conversation;
+
+ int offset = 0;
+ guint packet_number;
+
+ gboolean is_response;
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if (!conversation) {
+ /* create a new conversation */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MySQL");
+
+ if (pinfo->destport == pinfo->match_port) {
+ is_response=FALSE;
+ }else {
+ is_response=TRUE;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_mysql, tvb, offset, -1, FALSE);
+ mysql_tree = proto_item_add_subtree(ti, ett_mysql);
+
+ proto_tree_add_item(mysql_tree, hf_mysql_packet_length, tvb,
+ offset, 3, TRUE);
+ }
+ offset += 3;
+/* packet number */
+ packet_number= tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(mysql_tree, hf_mysql_packet_number, tvb,
+ offset, 1, packet_number);
+ }
+ offset += 1;
+
+ /*
+ * packet == 0 && response --> server greeting
+ * packet == 1 && request --> login request
+ */
+ if(is_response ) {
+ if( packet_number == 0 ) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, "Server Greeting" ) ;
+ }
+ offset = mysql_dissect_server_greeting(tvb,pinfo,offset,mysql_tree);
+ }else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, "Response" ) ;
+ }
+ offset = mysql_dissect_response(tvb,pinfo,offset,mysql_tree);
+ }
+ } else {
+ if( packet_number == 1 ) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, "Login Request") ;
+ }
+ offset = mysql_dissect_authentication(tvb,pinfo,offset,mysql_tree);
+ }else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, "Request") ;
+ }
+ offset = mysql_dissect_request(tvb,pinfo,offset,mysql_tree);
+ }
+ }
+
+/* payload */
+ if (tree && tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_item(mysql_tree, hf_mysql_payload,
+ tvb, offset, -1, FALSE);
+ }
+}
+static int
+mysql_dissect_response(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ gint response_code;
+ gint error_code;
+
+ /* response code */
+ response_code= tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_mysql_response_code, tvb,
+ offset, 1, response_code);
+ }
+ offset +=1;
+
+ if(response_code== 0xff ) {
+ /* error code */
+ error_code = tvb_get_letohs(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Error Code: %x", error_code );
+ }
+ if (tree) {
+ proto_tree_add_uint(tree, hf_mysql_error_code, tvb,
+ offset, 2, error_code);
+ }
+ offset +=2;
+
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, " OK" );
+ }
+ }
+ return offset;
+}
+
+static int
+mysql_dissect_request(tvbuff_t *tvb,packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ gint opcode;
+ gint strlen;
+ proto_item *tf;
+ proto_item *req_tree=NULL;
+
+ if(tree) {
+ tf=proto_tree_add_text(tree,tvb,offset,-1,"Command");
+ req_tree = proto_item_add_subtree(tf ,ett_request);
+ }
+
+ opcode = tvb_get_guint8(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Command: %s",
+ val_to_str(opcode, mysql_opcode_vals, "Unknown (%u)"));
+ }
+
+ if (req_tree) {
+ proto_tree_add_uint_format(req_tree, hf_mysql_opcode, tvb,
+ offset , 1, opcode, "Command: %s (%u)",
+ val_to_str(opcode, mysql_opcode_vals, "Unknown (%u)"),opcode);
+ }
+ /* command parameter */
+
+ offset += 1;
+ if ( (strlen = tvb_length_remaining(tvb,offset)) > 0 ) {
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " : %s",
+ tvb_format_text(tvb,offset,strlen));
+ }
+
+ if (tree) {
+ proto_tree_add_item(req_tree, hf_mysql_parameter, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+ }
+
+ return offset;
+}
+
+
+static int
+mysql_dissect_authentication(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ gint16 client_caps;
+ gint32 max_packet;
+ gint strlen;
+
+ proto_item *tf;
+ proto_item *cap_tree;
+ proto_item *login_tree=NULL;
+
+ if(tree) {
+ tf=proto_tree_add_text(tree,tvb,offset,-1,"Login Packet");
+ login_tree = proto_item_add_subtree(tf ,ett_server_greeting);
+ }
+
+ client_caps= tvb_get_letohs(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Caps: 0x%x",client_caps) ;
+ }
+ if(tree) {
+ tf = proto_tree_add_uint_format(login_tree, hf_mysql_caps, tvb, offset , 1, client_caps, "Caps: 0x%04x ", client_caps );
+ cap_tree = proto_item_add_subtree(tf, ett_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_password, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_found_rows, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_flag, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_connect_with_db, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_no_schema, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_compress, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_odbc, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_local_files, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_space, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_change_user, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_interactive, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ssl, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_sigpipe, tvb, offset, 2, client_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_transactions, tvb, offset, 2, client_caps);
+ }
+
+/* proto_tree_add_uint(tree, hf_mysql_client_caps, tvb,
+ offset, 2, client_caps);
+*/
+ offset +=2;
+ /* 3 bytes max packet, 16777216 - x */
+ max_packet = 0xffffff - tvb_get_letoh24(tvb, offset);
+ if(tree) {
+ proto_tree_add_uint(login_tree, hf_mysql_max_packet, tvb,
+ offset, 3, max_packet);
+ }
+ offset +=3;
+ /* User name */
+ strlen = tvb_strsize(tvb,offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " ,user: %s",
+ tvb_get_ptr(tvb,offset,strlen));
+ }
+ if (tree) {
+ proto_tree_add_item(login_tree, hf_mysql_user, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+
+ /* Password */
+ strlen = tvb_length_remaining(tvb,offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " ,password: %s",
+ tvb_get_ptr(tvb,offset,strlen));
+ }
+ if (tree) {
+ proto_tree_add_item(login_tree, hf_mysql_password, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+
+
+ return offset;
+}
+
+
+static int
+mysql_dissect_server_greeting(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree)
+{
+ gint protocol;
+ gint strlen;
+ gint32 thread_id;
+ gint16 server_caps;
+ gint charset;
+ gint16 status;
+
+ proto_item *tf;
+ proto_item *greeting_tree=NULL;
+ proto_item *cap_tree;
+
+ protocol= tvb_get_guint8(tvb, offset);
+
+ if(tree) {
+ tf = proto_tree_add_text(tree,tvb,offset,-1,"Server Greeting");
+ greeting_tree = proto_item_add_subtree(tf ,ett_server_greeting);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Protocol : %d",protocol) ;
+ }
+ if (tree) {
+ proto_tree_add_uint(greeting_tree, hf_mysql_protocol, tvb,
+ offset, 1, protocol);
+ }
+ offset +=1;
+ /* version string */
+
+ strlen = tvb_strsize(tvb,offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " ,version: %s",
+ tvb_get_ptr(tvb,offset,strlen));
+ }
+ if (tree) {
+ proto_tree_add_item(greeting_tree, hf_mysql_version, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+
+ /* 4 bytes little endian thread_id */
+ thread_id = tvb_get_letohl(tvb, offset);
+ if(tree) {
+ proto_tree_add_uint(greeting_tree, hf_mysql_thread_id, tvb,
+ offset, 4, thread_id);
+ }
+ offset +=4;
+ /* salt string */
+ strlen = tvb_strsize(tvb,offset);
+ if (tree) {
+ proto_tree_add_item(greeting_tree, hf_mysql_salt, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+ /* 2 bytes CAPS */
+ server_caps= tvb_get_letohs(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Caps: 0x%x",server_caps) ;
+ }
+ if(tree) {
+ tf = proto_tree_add_uint_format(greeting_tree, hf_mysql_caps, tvb, offset , 1, server_caps, "Caps: 0x%04x ", server_caps );
+ cap_tree = proto_item_add_subtree(tf, ett_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_password, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_found_rows, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_long_flag, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_connect_with_db, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_no_schema, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_compress, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_odbc, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_local_files, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_space, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_change_user, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_interactive, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ssl, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_ignore_sigpipe, tvb, offset, 2, server_caps);
+ proto_tree_add_boolean(cap_tree, hf_mysql_cap_transactions, tvb, offset, 2, server_caps);
+ }
+ offset+=2;
+ /* 1 byte charset */
+ charset = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint_format(greeting_tree, hf_mysql_charset, tvb,
+ offset, 1, charset, "Charset: %s (%u)",
+ val_to_str(charset, mysql_charset_vals, "Unknown (%u)"), charset);
+ }
+ offset +=1;
+ /* 2 byte status */
+ status = tvb_get_letohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint_format(greeting_tree, hf_mysql_status, tvb,
+ offset, 2, status, "Status: %s (%u)",
+ val_to_str(status, mysql_status_vals, "Unknown (%u)"), status);
+ }
+ offset +=2;
+ /* other unused */
+ strlen = tvb_length_remaining(tvb,offset);
+
+ if (tree) {
+ proto_tree_add_item(greeting_tree, hf_mysql_unused, tvb,
+ offset, strlen, FALSE );
+ }
+ offset +=strlen;
+
+ return offset;
+}
+
+void
+proto_register_mysql(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_mysql_packet_length,
+ { "Packet Length", "mysql.packet_length",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "MySQL packet length", HFILL }},
+
+ { &hf_mysql_packet_number,
+ { "Packet Number", "mysql.packet_number",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL Packet Number", HFILL }},
+
+ { &hf_mysql_opcode,
+ { "Command", "mysql.opcode",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL OPCODE", HFILL }},
+
+ { &hf_mysql_response_code,
+ { "Response Code", "mysql.response_code",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL Respone Code", HFILL }},
+
+ { &hf_mysql_error_code,
+ { "Error Code", "mysql.error_code",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "MySQL Error CODE", HFILL }},
+
+ { &hf_mysql_protocol,
+ { "Protocol", "mysql.protocol",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL Protocol", HFILL }},
+
+ { &hf_mysql_version,
+ { "Version", "mysql.version",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "MySQL Version", HFILL }},
+
+ { &hf_mysql_caps,
+ { "Caps", "mysql.caps",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "MySQL Capabilities", HFILL }},
+
+ { &hf_mysql_cap_long_password,
+ { "Long Password","mysql.caps.lp",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_LP,
+ "", HFILL }},
+
+ { &hf_mysql_cap_found_rows,
+ { "Found Rows","mysql.caps.fr",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_FR,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_long_flag,
+ { "Long Flag","mysql.caps.lf",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_LF,
+ "", HFILL }},
+
+ { &hf_mysql_cap_connect_with_db,
+ { "Connect With Database","mysql.caps.cd",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_CD,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_no_schema,
+ { "Dont Allow database.table.column","mysql.caps.ns",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_NS,
+ "", HFILL }},
+
+ { &hf_mysql_cap_compress,
+ { "Can use compression protocol","mysql.caps.CP",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_CP,
+ "", HFILL }},
+
+ { &hf_mysql_cap_odbc,
+ { "ODBC Client","mysql.caps.ob",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_OB,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_local_files,
+ { "Can Use LOAD DATA LOCAL","mysql.caps.li",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_LI,
+ "", HFILL }},
+
+ { &hf_mysql_cap_ignore_space,
+ { "Ignore Spaces before (","mysql.caps.is",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_IS,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_change_user,
+ { "Support the mysql_change_user()","mysql.caps.cu",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_CU,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_interactive,
+ { "an Interactive Client","mysql.caps.ia",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_IA,
+ "", HFILL }},
+
+
+ { &hf_mysql_cap_ssl,
+ { "Switch to SSL after handshake","mysql.caps.sl",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_SL,
+ "", HFILL }},
+
+ { &hf_mysql_cap_ignore_sigpipe,
+ { "Ignore sigpipes","mysql.caps.ii",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_II,
+ "", HFILL }},
+
+ { &hf_mysql_cap_transactions,
+ { "Client knows about transactions","mysql.caps.ta",
+ FT_BOOLEAN, 16, TFS(&flags_set_truth), MYSQL_CAPS_TA,
+ "", HFILL }},
+
+ { &hf_mysql_max_packet,
+ { "MAX Packet", "mysql.max_packet",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "MySQL Max packet", HFILL }},
+
+ { &hf_mysql_user,
+ { "Username", "mysql.user",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "Login Username", HFILL }},
+
+ { &hf_mysql_password,
+ { "Password", "mysql.password",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Login Password", HFILL }},
+
+ { &hf_mysql_salt,
+ { "Salt", "mysql.salt",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "Salt", HFILL }},
+
+ { &hf_mysql_thread_id,
+ { "Thread ID", "mysql.thread_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MySQL Thread ID", HFILL }},
+
+ { &hf_mysql_charset,
+ { "Charset", "mysql.charset",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "MySQL Charset", HFILL }},
+
+ { &hf_mysql_status,
+ { "Status", "mysql.status",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "MySQL Status", HFILL }},
+
+ { &hf_mysql_unused,
+ { "Unused", "mysql.unused",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Unused", HFILL }},
+
+ { &hf_mysql_parameter,
+ { "Parameter", "mysql.parameter",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Parameter", HFILL }},
+ { &hf_mysql_payload,
+ { "Payload", "mysql.payload",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "MySQL Payload", HFILL }},
+#if 0
+ { &hf_mysql_destination_file,
+ { "DESTINATION File", "mysql.destination_file",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "MySQL source file name", HFILL }},
+
+ { &hf_mysql_blocknum,
+ { "Block", "mysql.block",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Block number", HFILL }},
+
+ { &hf_mysql_error_code,
+ { "Error code", "mysql.error.code",
+ FT_UINT16, BASE_DEC, VALS(mysql_error_code_vals), 0x0,
+ "Error code in case of MySQL error message", HFILL }},
+
+ { &hf_mysql_error_string,
+ { "Error message", "mysql.error.message",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "Error string in case of MySQL error message", HFILL }},
+#endif
+ };
+ static gint *ett[] = {
+ &ett_mysql,
+ &ett_server_greeting,
+ &ett_caps,
+ &ett_request,
+ };
+ module_t *mysql_module;
+
+ proto_mysql = proto_register_protocol("MySQL Protocol",
+ "MySQL", "mysql");
+ proto_register_field_array(proto_mysql, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ mysql_module = prefs_register_protocol(proto_mysql, NULL);
+ prefs_register_bool_preference(mysql_module, "desegment_buffers",
+ "Desegment all MySQL buffers spanning multiple TCP segments",
+ "Whether the MySQL dissector should desegment all MySQL buffers spanning multiple TCP segments",
+ &mysql_desegment);
+}
+
+void
+proto_reg_handoff_mysql(void)
+{
+ dissector_handle_t mysql_handle;
+
+ mysql_handle = create_dissector_handle(dissect_mysql, proto_mysql);
+
+ dissector_add("tcp.port", TCP_PORT_MySQL, mysql_handle);
+}
diff --git a/epan/dissectors/packet-nbipx.c b/epan/dissectors/packet-nbipx.c
new file mode 100644
index 0000000000..3717b063f3
--- /dev/null
+++ b/epan/dissectors/packet-nbipx.c
@@ -0,0 +1,802 @@
+/* packet-nbipx.c
+ * Routines for NetBIOS over IPX packet disassembly
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ipx.h"
+#include "packet-netbios.h"
+
+static int proto_nbipx = -1;
+
+static gint ett_nbipx = -1;
+static gint ett_nbipx_conn_ctrl = -1;
+static gint ett_nbipx_name_type_flags = -1;
+
+static void dissect_conn_control(tvbuff_t *tvb, int offset, proto_tree *tree);
+static void dissect_packet_type(tvbuff_t *tvb, int offset, guint8 packet_type,
+ proto_tree *tree);
+
+/* There is no RFC or public specification of Netware or Microsoft
+ * NetBIOS over IPX packets. I have had to decode the protocol myself,
+ * so there are holes and perhaps errors in this code. (gram)
+ *
+ * A list of "NovelNetBIOS" packet types can be found at
+ *
+ * http://www.protocols.com/pbook/novel.htm#NetBIOS
+ *
+ * and at least some of those packet types appear to match what's in
+ * some NBIPX packets.
+ *
+ * Note, however, that it appears that sometimes NBIPX packets have
+ * 8 IPX addresses at the beginning, and sometimes they don't.
+ *
+ * In the section on "NetBIOS Broadcasts", the document at
+ *
+ * http://www.microsoft.com/technet/network/ipxrout.asp
+ *
+ * says that "the NetBIOS over IPX Broadcast header" contains 8 IPX
+ * network numbers in the "IPX WAN broadcast header", and that it's
+ * followed by a "Name Type Flags" byte (giving information about the
+ * name being registered, deregistered, or checked), a "Data Stream
+ * Type 2" byte giving the type of operation (NBIPX_FIND_NAME,
+ * NBIPX_NAME_RECOGNIZED, or NBIPX_CHECK_NAME - the latter is called
+ * "Add Name"), and a 16-byte NetBIOS name.
+ *
+ * It also says that "NetBIOS over IPX Broadcast packets" have a
+ * packet type of 0x14 (20, or IPX_PACKET_TYPE_WANBCAST) and a
+ * socket number of 0x455 (IPX_SOCKET_NETBIOS).
+ *
+ * However, there are also non-broadcast packets that *also* contain
+ * the 8 IPX network numbers; they appear to be replies to broadcast
+ * packets, and have a packet type of 0x4 (IPX_PACKET_TYPE_PEP).
+ *
+ * Other IPX_PACKET_TYPE_PEP packets to and from the IPX_SOCKET_NETBIOS
+ * socket, however, *don't* have the 8 IPX network numbers; there does
+ * not seem to be any obvious algorithm to determine whether the packet
+ * has the addresses or not. Microsoft Knowledge Base article Q128335
+ * appears to show some code from the NBIPX implementation in NT that
+ * tries to determine the packet type - and it appears to use heuristics
+ * based on the packet length and on looking at what might be the NBIPX
+ * "Data Stream Type" byte depending on whether the packet has the 8
+ * IPX network numbers or not.
+ *
+ * So, for now, we treat *all* NBIPX packets as having a "Data Stream
+ * Type" byte, preceded by another byte of NBIPX information and
+ * followed by more NBIPX stuff, and assume that it's preceded by
+ * 8 IPX network numbers iff:
+ *
+ * the packet is a WAN Broadcast packet
+ *
+ * or
+ *
+ * the packet is the right size for one of those PEP name replies
+ * (50 bytes) *and* has a name packet type as the Data Stream
+ * Type byte at the offset where that byte would be if the packet
+ * does have the 8 IPX network numbers at the beginning.
+ *
+ * The page at
+ *
+ * http://ourworld.compuserve.com/homepages/TimothyDEvans/encap.htm
+ *
+ * indicates, under "NBIPX session packets", that "NBIPX session packets"
+ * have
+ *
+ * 1 byte of NBIPX connection control flag
+ * 1 byte of data stream type
+ * 2 bytes of source connection ID
+ * 2 bytes of destination connection ID
+ * 2 bytes of send sequence number
+ * 2 bytes of total data length
+ * 2 bytes of offset
+ * 2 bytes of data length
+ * 2 bytes of receive sequence number
+ * 2 bytes of "bytes received"
+ *
+ * followed by data.
+ *
+ * Packets with a data stream type of NBIPX_DIRECTED_DATAGRAM appear to
+ * have, following the data stream type, two NetBIOS names, the first
+ * of which is the receiver's NetBIOS name and the second of which is
+ * the sender's NetBIOS name. The page at
+ *
+ * http://support.microsoft.com/support/kb/articles/q203/0/51.asp
+ *
+ * speaks of type 4 (PEP) packets as being used for "SAP, NetBIOS sessions
+ * and directed datagrams" and type 20 (WAN Broadcast) as being used for
+ * "NetBIOS name resolution broadcasts" (but nothing about the non-broadcast
+ * type 4 name resolution stuff).
+ *
+ * We assume that this means that, once you get past the 8 IPX network
+ * numbers if present:
+ *
+ * the first byte is a name type byte for the name packets
+ * and a connection control flag for the other packets;
+ *
+ * the second byte is a data stream type;
+ *
+ * the rest of the bytes are:
+ *
+ * the NetBIOS name being registered/deregistered/etc.,
+ * for name packets;
+ *
+ * the two NetBIOS names, followed by the NetBIOS
+ * datagram, for NBIPX_DIRECTED_DATAGRAM packets;
+ *
+ * the session packet header, possibly followed by
+ * session data, for session packets.
+ *
+ * We don't know yet how to interpret NBIPX_STATUS_QUERY or
+ * NBIPX_STATUS_RESPONSE.
+ *
+ * For now, we treat the datagrams and session data as SMB stuff.
+ */
+#define NBIPX_FIND_NAME 1
+#define NBIPX_NAME_RECOGNIZED 2
+#define NBIPX_CHECK_NAME 3
+#define NBIPX_NAME_IN_USE 4
+#define NBIPX_DEREGISTER_NAME 5
+#define NBIPX_SESSION_DATA 6
+#define NBIPX_SESSION_END 7
+#define NBIPX_SESSION_END_ACK 8
+#define NBIPX_STATUS_QUERY 9
+#define NBIPX_STATUS_RESPONSE 10
+#define NBIPX_DIRECTED_DATAGRAM 11
+
+static const value_string nbipx_data_stream_type_vals[] = {
+ {NBIPX_FIND_NAME, "Find name"},
+ {NBIPX_NAME_RECOGNIZED, "Name recognized"},
+ {NBIPX_CHECK_NAME, "Check name"},
+ {NBIPX_NAME_IN_USE, "Name in use"},
+ {NBIPX_DEREGISTER_NAME, "Deregister name"},
+ {NBIPX_SESSION_DATA, "Session data"},
+ {NBIPX_SESSION_END, "Session end"},
+ {NBIPX_SESSION_END_ACK, "Session end ACK"},
+ {NBIPX_STATUS_QUERY, "Status query"},
+ {NBIPX_STATUS_RESPONSE, "Status response"},
+ {NBIPX_DIRECTED_DATAGRAM, "Directed datagram"},
+ {0, NULL}
+};
+
+static void
+add_routers(proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ int i;
+ int rtr_offset;
+ guint32 router;
+
+ /* Eight routers are listed */
+ for (i = 0; i < 8; i++) {
+ rtr_offset = offset + (i << 2);
+ tvb_memcpy(tvb, (guint8 *)&router, rtr_offset, 4);
+ if (router != 0) {
+ proto_tree_add_text(tree, tvb, rtr_offset, 4,
+ "IPX Network: %s",
+ ipxnet_to_string((guint8*)&router));
+ }
+ }
+}
+
+static void
+dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gboolean has_routes;
+ proto_tree *nbipx_tree = NULL;
+ proto_item *ti = NULL;
+ int offset = 0;
+ guint8 packet_type;
+ guint8 name_type_flag;
+ proto_tree *name_type_flag_tree;
+ proto_item *tf;
+ char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
+ int name_type;
+ gboolean has_payload;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBIPX");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (pinfo->ipxptype == IPX_PACKET_TYPE_WANBCAST) {
+ /*
+ * This is a WAN Broadcast packet; we assume it will have
+ * 8 IPX addresses at the beginning.
+ */
+ has_routes = TRUE;
+ } else {
+ /*
+ * This isn't a WAN Broadcast packet, but it still might
+ * have the 8 addresses.
+ *
+ * If it's the right length for a name operation,
+ * and, if we assume it has routes, the packet type
+ * is a name operation, assume it has routes.
+ *
+ * NOTE: this will throw an exception if the byte that
+ * would be the packet type byte if this has the 8
+ * addresses isn't present; if that's the case, we don't
+ * know how to interpret this packet, so we can't dissect
+ * it anyway.
+ */
+ has_routes = FALSE; /* start out assuming it doesn't */
+ if (tvb_reported_length(tvb) == 50) {
+ packet_type = tvb_get_guint8(tvb, offset + 32 + 1);
+ switch (packet_type) {
+
+ case NBIPX_FIND_NAME:
+ case NBIPX_NAME_RECOGNIZED:
+ case NBIPX_CHECK_NAME:
+ case NBIPX_NAME_IN_USE:
+ case NBIPX_DEREGISTER_NAME:
+ has_routes = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nbipx, tvb, 0,
+ -1, FALSE);
+ nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
+ }
+
+ if (has_routes) {
+ if (tree)
+ add_routers(nbipx_tree, tvb, 0);
+ offset += 32;
+ }
+
+ packet_type = tvb_get_guint8(tvb, offset + 1);
+
+ switch (packet_type) {
+
+ case NBIPX_FIND_NAME:
+ case NBIPX_NAME_RECOGNIZED:
+ case NBIPX_CHECK_NAME:
+ case NBIPX_NAME_IN_USE:
+ case NBIPX_DEREGISTER_NAME:
+ name_type_flag = tvb_get_guint8(tvb, offset);
+ name_type = get_netbios_name(tvb, offset+2, name);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s<%02x>",
+ val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
+ name, name_type);
+ }
+ if (nbipx_tree) {
+ tf = proto_tree_add_text(nbipx_tree, tvb, offset, 1,
+ "Name type flag: 0x%02x", name_type_flag);
+ name_type_flag_tree = proto_item_add_subtree(tf,
+ ett_nbipx_name_type_flags);
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x80, 8,
+ "Group name", "Unique name"));
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x40, 8,
+ "Name in use", "Name not used"));
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x04, 8,
+ "Name registered", "Name not registered"));
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x02, 8,
+ "Name duplicated", "Name not duplicated"));
+ proto_tree_add_text(name_type_flag_tree, tvb, offset,
+ 1, "%s",
+ decode_boolean_bitfield(name_type_flag, 0x01, 8,
+ "Name deregistered", "Name not deregistered"));
+ }
+ offset += 1;
+
+ dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
+ offset += 1;
+
+ if (nbipx_tree)
+ netbios_add_name("Name", tvb, offset, nbipx_tree);
+ offset += NETBIOS_NAME_LEN;
+
+ /*
+ * No payload to be interpreted by another protocol.
+ */
+ has_payload = FALSE;
+ break;
+
+ case NBIPX_SESSION_DATA:
+ case NBIPX_SESSION_END:
+ case NBIPX_SESSION_END_ACK:
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
+ }
+ dissect_conn_control(tvb, offset, nbipx_tree);
+ offset += 1;
+
+ dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
+ offset += 1;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Source connection ID: 0x%04X",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Destination connection ID: 0x%04X",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Send sequence number: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Total data length: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Offset: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Data length: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Receive sequence number: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ if (nbipx_tree) {
+ proto_tree_add_text(nbipx_tree, tvb, offset, 2,
+ "Bytes received: %u",
+ tvb_get_letohs(tvb, offset));
+ }
+ offset += 2;
+
+ /*
+ * We may have payload to dissect.
+ */
+ has_payload = TRUE;
+ break;
+
+ case NBIPX_DIRECTED_DATAGRAM:
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
+ }
+ dissect_conn_control(tvb, offset, nbipx_tree);
+ offset += 1;
+
+ dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
+ offset += 1;
+
+ if (nbipx_tree)
+ netbios_add_name("Receiver's Name", tvb, offset,
+ nbipx_tree);
+ offset += NETBIOS_NAME_LEN;
+
+ if (nbipx_tree)
+ netbios_add_name("Sender's Name", tvb, offset,
+ nbipx_tree);
+ offset += NETBIOS_NAME_LEN;
+
+ /*
+ * We may have payload to dissect.
+ */
+ has_payload = TRUE;
+ break;
+
+ default:
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
+ }
+
+ /*
+ * We don't know what the first byte is.
+ */
+ offset += 1;
+
+ /*
+ * The second byte is a data stream type byte.
+ */
+ dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
+ offset += 1;
+
+ /*
+ * We don't know what the rest of the packet is.
+ */
+ has_payload = FALSE;
+ }
+
+ /*
+ * Set the length of the NBIPX tree item.
+ */
+ if (ti != NULL)
+ proto_item_set_len(ti, offset);
+
+ if (has_payload && tvb_offset_exists(tvb, offset)) {
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ dissect_netbios_payload(next_tvb, pinfo, tree);
+ }
+}
+
+static void
+dissect_conn_control(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint8 conn_control;
+ proto_item *ti;
+ proto_tree *cc_tree;
+
+ if (tree) {
+ conn_control = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(tree, tvb, offset, 1,
+ "Connection control: 0x%02x", conn_control);
+ cc_tree = proto_item_add_subtree(ti, ett_nbipx_conn_ctrl);
+ proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(conn_control, 0x80, 8,
+ "System packet", "Non-system packet"));
+ proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(conn_control, 0x40, 8,
+ "Acknowledgement required",
+ "Acknowledgement not required"));
+ proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(conn_control, 0x20, 8,
+ "Attention", "No attention"));
+ proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(conn_control, 0x10, 8,
+ "End of message", "No end of message"));
+ proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(conn_control, 0x08, 8,
+ "Resend", "No resend"));
+ }
+}
+
+static void
+dissect_packet_type(tvbuff_t *tvb, int offset, guint8 packet_type,
+ proto_tree *tree)
+{
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Packet Type: %s (%02X)",
+ val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
+ packet_type);
+ }
+}
+
+void
+proto_register_nbipx(void)
+{
+/* static hf_register_info hf[] = {
+ { &variable,
+ { "Name", "nbipx.abbreviation", TYPE, VALS_POINTER }},
+ };*/
+ static gint *ett[] = {
+ &ett_nbipx,
+ &ett_nbipx_conn_ctrl,
+ &ett_nbipx_name_type_flags,
+ };
+
+ proto_nbipx = proto_register_protocol("NetBIOS over IPX",
+ "NBIPX", "nbipx");
+ /* proto_register_field_array(proto_nbipx, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_nbipx(void)
+{
+ dissector_handle_t nbipx_handle;
+
+ nbipx_handle = create_dissector_handle(dissect_nbipx, proto_nbipx);
+ dissector_add("ipx.socket", IPX_SOCKET_NETBIOS, nbipx_handle);
+}
+
+/*
+ * Microsoft appear to have something they call "direct hosting", where
+ * SMB - and, I infer, related stuff, such as name resolution - runs
+ * directly over IPX. (In Windows 2000, they also run SMB directly over
+ * TCP, on port 445, and that also appears to be called "direct hosting".
+ * Ethereal handles SMB-over-TCP.)
+ *
+ * The document at
+ *
+ * http://support.microsoft.com/support/kb/articles/q203/0/51.asp
+ *
+ * speaks of NMPI - the "Name Management Protocol on IPX" - as being
+ * "Microsoft's protocol for name management support when you use IPX
+ * without the NetBIOS interface," and says that "This process of routing
+ * the SMB protocol directly through IPX is known as Direct Hosting."
+ *
+ * It speaks of IPX socket 0x551 as being for NMPI; we define it as
+ * IPX_SOCKET_NWLINK_SMB_NAMEQUERY.
+ *
+ * We also define IPX_SOCKET_NWLINK_SMB_DGRAM as 0x0553 and define
+ * IPX_SOCKET_NWLINK_SMB_BROWSE as 0x0555 (with a "? not sure on this"
+ * comment after the latter one).
+ *
+ * We have seen at least some browser announcements on IPX socket 0x553;
+ * those are WAN broadcast packets, complete with 8 IPX network
+ * numbers, and with the header containing the usual two NetBIOS names
+ * that show up in NetBIOS datagrams.
+ *
+ * Network Monitor calls those packets NMPI packets, even though they're
+ * on socket 0x553, not socket 0x551, and contain SMB datagrams, not name
+ * resolution packets.
+ *
+ * At least some of this is discussed in the "SMBPUB.DOC" Word document
+ * stored in
+ *
+ * ftp://ftp.microsoft.com/developr/drg/CIFS/smbpub.zip
+ *
+ * which can also be found in text form at
+ *
+ * http://www.samba.org/samba/ftp/specs/smbpub.txt
+ *
+ * which says that for "connectionless IPX transport" the sockets that
+ * are used are:
+ *
+ * SMB_SERVER_SOCKET (0x550) - SMB requests from clients
+ * SMB_NAME_SOCKET (0x551) - name claims and name query messages
+ * REDIR_SOCKET (0x552) - used by the redirector (client) for
+ * sending SMB requests and receiving SMB replies
+ * MAILSLOT_SOCKET (0x553) - used by the redirector and browser
+ * for mailslot datagrams
+ * MESSENGER_SOCKET (0x554) - used by the redirector to send
+ * messages from client to client
+ *
+ * Name claim/query packets, and mailslot datagrams, are:
+ *
+ * 8 IPX network addresses
+ * 1 byte of opcode
+ * 1 byte of name type
+ * 2 bytes of message ID
+ * 16 bytes of name being sought or claimed
+ * 16 bytes of requesting machine
+ *
+ * The opcode is one of:
+ *
+ * INAME_CLAIM (0xf1) - server name claim message
+ * INAME_DELETE (0xf2) - relinquish server name
+ * INAME_QUERY (0xf3) - locate server name
+ * INAME_FOUND (0xf4) - response to INAME_QUERY
+ * IMSG_HANGUP (0xf5) - messenger hangup
+ * IMSLOT_SEND (0xfc) - mailslot write
+ * IMSLOT_FIND (0xfd) - find name for mailslot write
+ * IMSLOT_NAME (0xfe) - response to IMSLOT_FIND
+ *
+ * The name type is one of:
+ *
+ * INTYPE_MACHINE 1
+ * INTYPE_WKGROUP 2
+ * INTYPE_BROWSER 3
+ */
+static int proto_nmpi = -1;
+
+static gint ett_nmpi = -1;
+static gint ett_nmpi_name_type_flags = -1;
+
+/*
+ * Opcodes.
+ */
+#define INAME_CLAIM 0xf1
+#define INAME_DELETE 0xf2
+#define INAME_QUERY 0xf3
+#define INAME_FOUND 0xf4
+#define IMSG_HANGUP 0xf5
+#define IMSLOT_SEND 0xfc
+#define IMSLOT_FIND 0xfd
+#define IMSLOT_NAME 0xfe
+
+static const value_string nmpi_opcode_vals[] = {
+ {INAME_CLAIM, "Claim name"},
+ {INAME_DELETE, "Delete name"},
+ {INAME_QUERY, "Query name"},
+ {INAME_FOUND, "Name found"},
+ {IMSG_HANGUP, "Messenger hangup"},
+ {IMSLOT_SEND, "Mailslot write"},
+ {IMSLOT_FIND, "Find mailslot name"},
+ {IMSLOT_NAME, "Mailslot name found"},
+ {0, NULL}
+};
+
+/*
+ * Name types.
+ */
+#define INTYPE_MACHINE 1
+#define INTYPE_WORKGROUP 2
+#define INTYPE_BROWSER 3
+
+static const value_string nmpi_name_type_vals[] = {
+ {INTYPE_MACHINE, "Machine"},
+ {INTYPE_WORKGROUP, "Workgroup"},
+ {INTYPE_BROWSER, "Browser"},
+ {0, NULL}
+};
+
+static void
+dissect_nmpi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *nmpi_tree = NULL;
+ proto_item *ti;
+ int offset = 0;
+ guint8 opcode;
+ guint8 nmpi_name_type;
+ char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
+ int name_type;
+ char node_name[(NETBIOS_NAME_LEN - 1)*4 + 1];
+ int node_name_type = 0;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMPI");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nmpi, tvb, offset, 68,
+ FALSE);
+ nmpi_tree = proto_item_add_subtree(ti, ett_nmpi);
+
+ add_routers(nmpi_tree, tvb, offset);
+ }
+ offset += 32;
+
+ /*
+ * XXX - we don't use "node_name" or "node_name_type".
+ */
+ opcode = tvb_get_guint8(tvb, offset);
+ nmpi_name_type = tvb_get_guint8(tvb, offset+1);
+ name_type = get_netbios_name(tvb, offset+4, name);
+ node_name_type = get_netbios_name(tvb, offset+20, node_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ switch (opcode) {
+
+ case INAME_CLAIM:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Claim name %s<%02x>",
+ name, name_type);
+ break;
+
+ case INAME_DELETE:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Delete name %s<%02x>",
+ name, name_type);
+ break;
+
+ case INAME_QUERY:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Query name %s<%02x>",
+ name, name_type);
+ break;
+
+ case INAME_FOUND:
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Name %s<%02x> found",
+ name, name_type);
+ break;
+
+ case IMSG_HANGUP:
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Messenger hangup on %s<%02x>", name, name_type);
+ break;
+
+ case IMSLOT_SEND:
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Mailslot write to %s<%02x>", name, name_type);
+ break;
+
+ case IMSLOT_FIND:
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Find mailslot name %s<%02x>", name, name_type);
+ break;
+
+ case IMSLOT_NAME:
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Mailslot name %s<%02x> found", name, name_type);
+ break;
+
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Unknown NMPI op 0x%02x: name %s<%02x>",
+ opcode, name, name_type);
+ break;
+ }
+ }
+
+ if (tree) {
+ proto_tree_add_text(nmpi_tree, tvb, offset, 1,
+ "Opcode: %s (0x%02x)",
+ val_to_str(opcode, nmpi_opcode_vals, "Unknown"),
+ opcode);
+ proto_tree_add_text(nmpi_tree, tvb, offset+1, 1,
+ "Name Type: %s (0x%02x)",
+ val_to_str(nmpi_name_type, nmpi_name_type_vals, "Unknown"),
+ nmpi_name_type);
+ proto_tree_add_text(nmpi_tree, tvb, offset+2, 2,
+ "Message ID: 0x%04x",
+ tvb_get_letohs(tvb, offset+2));
+ netbios_add_name("Requested name", tvb, offset+4, nmpi_tree);
+ netbios_add_name("Source name", tvb, offset+20, nmpi_tree);
+ }
+
+ offset += 1 + 1 + 2 + NETBIOS_NAME_LEN + NETBIOS_NAME_LEN;
+
+ if (opcode == IMSLOT_SEND && tvb_offset_exists(tvb, offset)) {
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ dissect_netbios_payload(next_tvb, pinfo, tree);
+ }
+}
+
+void
+proto_register_nmpi(void)
+{
+/* static hf_register_info hf[] = {
+ { &variable,
+ { "Name", "nmpi.abbreviation", TYPE, VALS_POINTER }},
+ };*/
+ static gint *ett[] = {
+ &ett_nmpi,
+ &ett_nmpi_name_type_flags,
+ };
+
+ proto_nmpi = proto_register_protocol("Name Management Protocol over IPX",
+ "NMPI", "nmpi");
+ /* proto_register_field_array(proto_nmpi, hf, array_length(hf));*/
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_nmpi(void)
+{
+ dissector_handle_t nmpi_handle;
+
+ nmpi_handle = create_dissector_handle(dissect_nmpi, proto_nmpi);
+ dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_NAMEQUERY,
+ nmpi_handle);
+ dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_MAILSLOT,
+ nmpi_handle);
+}
diff --git a/epan/dissectors/packet-nbns.c b/epan/dissectors/packet-nbns.c
new file mode 100644
index 0000000000..e2d51d206c
--- /dev/null
+++ b/epan/dissectors/packet-nbns.c
@@ -0,0 +1,1926 @@
+/* packet-nbns.c
+ * Routines for NetBIOS-over-TCP packet disassembly (the name dates back
+ * to when it had only NBNS)
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "packet-dns.h"
+#include "packet-netbios.h"
+#include "packet-tcp.h"
+#include "packet-frame.h"
+#include "prefs.h"
+
+static int proto_nbns = -1;
+static int hf_nbns_flags = -1;
+static int hf_nbns_flags_response = -1;
+static int hf_nbns_flags_opcode = -1;
+static int hf_nbns_flags_authoritative = -1;
+static int hf_nbns_flags_truncated = -1;
+static int hf_nbns_flags_recdesired = -1;
+static int hf_nbns_flags_recavail = -1;
+static int hf_nbns_flags_broadcast = -1;
+static int hf_nbns_flags_rcode = -1;
+static int hf_nbns_transaction_id = -1;
+static int hf_nbns_count_questions = -1;
+static int hf_nbns_count_answers = -1;
+static int hf_nbns_count_auth_rr = -1;
+static int hf_nbns_count_add_rr = -1;
+
+static gint ett_nbns = -1;
+static gint ett_nbns_qd = -1;
+static gint ett_nbns_flags = -1;
+static gint ett_nbns_nb_flags = -1;
+static gint ett_nbns_name_flags = -1;
+static gint ett_nbns_rr = -1;
+static gint ett_nbns_qry = -1;
+static gint ett_nbns_ans = -1;
+
+static int proto_nbdgm = -1;
+static int hf_nbdgm_type = -1;
+static int hf_nbdgm_fragment = -1;
+static int hf_nbdgm_first = -1;
+static int hf_nbdgm_node_type = -1;
+static int hf_nbdgm_datagram_id = -1;
+static int hf_nbdgm_src_ip = -1;
+static int hf_nbdgm_src_port = -1;
+
+static gint ett_nbdgm = -1;
+
+static int proto_nbss = -1;
+static int hf_nbss_type = -1;
+static int hf_nbss_flags = -1;
+
+static gint ett_nbss = -1;
+static gint ett_nbss_flags = -1;
+
+/* desegmentation of NBSS over TCP */
+static gboolean nbss_desegment = TRUE;
+
+/* See RFC 1001 and 1002 for information on the first three, and see
+
+ http://www.cifs.com/specs/draft-leach-cifs-v1-spec-01.txt
+
+ Appendix B, and various messages on the CIFS mailing list such as
+
+ http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9811A&L=cifs&P=R386
+
+ for information on the fourth. */
+#define UDP_PORT_NBNS 137
+#define UDP_PORT_NBDGM 138
+#define TCP_PORT_NBSS 139
+#define TCP_PORT_CIFS 445
+
+/* Packet structure taken from RFC 1002. See also RFC 1001.
+ * Opcode, flags, and rcode treated as "flags", similarly to DNS,
+ * to make it easier to lift the dissection code from "packet-dns.c". */
+
+/* Offsets of fields in the NBNS header. */
+#define NBNS_ID 0
+#define NBNS_FLAGS 2
+#define NBNS_QUEST 4
+#define NBNS_ANS 6
+#define NBNS_AUTH 8
+#define NBNS_ADD 10
+
+/* Length of NBNS header. */
+#define NBNS_HDRLEN 12
+
+/* type values */
+#define T_NB 32 /* NetBIOS name service RR */
+#define T_NBSTAT 33 /* NetBIOS node status RR */
+
+/* Bit fields in the flags */
+#define F_RESPONSE (1<<15) /* packet is response */
+#define F_OPCODE (0xF<<11) /* query opcode */
+#define OPCODE_SHIFT 11
+#define F_AUTHORITATIVE (1<<10) /* response is authoritative */
+#define F_TRUNCATED (1<<9) /* response is truncated */
+#define F_RECDESIRED (1<<8) /* recursion desired */
+#define F_RECAVAIL (1<<7) /* recursion available */
+#define F_BROADCAST (1<<4) /* broadcast/multicast packet */
+#define F_RCODE (0xF<<0) /* reply code */
+
+static const true_false_string tfs_flags_response = {
+ "Message is a response",
+ "Message is a query"
+};
+
+static const true_false_string tfs_flags_authoritative = {
+ "Server is an authority for domain",
+ "Server is not an authority for domain"
+};
+
+static const true_false_string tfs_flags_truncated = {
+ "Message is truncated",
+ "Message is not truncated"
+};
+
+static const true_false_string tfs_flags_recdesired = {
+ "Do query recursively",
+ "Don't do query recursively"
+};
+
+static const true_false_string tfs_flags_recavail = {
+ "Server can do recursive queries",
+ "Server can't do recursive queries"
+};
+
+static const true_false_string tfs_flags_broadcast = {
+ "Broadcast packet",
+ "Not a broadcast packet"
+};
+
+/* Opcodes */
+#define OPCODE_QUERY 0 /* standard query */
+#define OPCODE_REGISTRATION 5 /* registration */
+#define OPCODE_RELEASE 6 /* release name */
+#define OPCODE_WACK 7 /* wait for acknowledgement */
+#define OPCODE_REFRESH 8 /* refresh registration */
+#define OPCODE_REFRESHALT 9 /* refresh registration (alternate opcode) */
+#define OPCODE_MHREGISTRATION 15 /* multi-homed registration */
+
+static const value_string opcode_vals[] = {
+ { OPCODE_QUERY, "Name query" },
+ { OPCODE_REGISTRATION, "Registration" },
+ { OPCODE_RELEASE, "Release" },
+ { OPCODE_WACK, "Wait for acknowledgment" },
+ { OPCODE_REFRESH, "Refresh" },
+ { OPCODE_REFRESHALT, "Refresh (alternate opcode)" },
+ { OPCODE_MHREGISTRATION, "Multi-homed registration" },
+ { 0, NULL }
+};
+
+/* Reply codes */
+#define RCODE_NOERROR 0
+#define RCODE_FMTERROR 1
+#define RCODE_SERVFAIL 2
+#define RCODE_NAMEERROR 3
+#define RCODE_NOTIMPL 4
+#define RCODE_REFUSED 5
+#define RCODE_ACTIVE 6
+#define RCODE_CONFLICT 7
+
+static const value_string rcode_vals[] = {
+ { RCODE_NOERROR, "No error" },
+ { RCODE_FMTERROR, "Request was invalidly formatted" },
+ { RCODE_SERVFAIL, "Server failure" },
+ { RCODE_NAMEERROR, "Requested name does not exist" },
+ { RCODE_NOTIMPL, "Request is not implemented" },
+ { RCODE_REFUSED, "Request was refused" },
+ { RCODE_ACTIVE, "Name is owned by another node" },
+ { RCODE_CONFLICT, "Name is in conflict" },
+ { 0, NULL }
+};
+
+/* Values for the "NB_FLAGS" field of RR data. From RFC 1001 and 1002,
+ * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
+ * packet traces. */
+#define NB_FLAGS_ONT (3<<(15-2)) /* bits for node type */
+#define NB_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
+#define NB_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
+#define NB_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
+#define NB_FLAGS_ONT_H_NODE (3<<(15-2)) /* H-mode node */
+
+#define NB_FLAGS_G (1<<(15-0)) /* group name */
+
+/* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
+ * RR data. From RFC 1001 and 1002, except for NAME_FLAGS_ONT_H_NODE,
+ * which was discovered by looking at packet traces. */
+#define NAME_FLAGS_PRM (1<<(15-6)) /* name is permanent node name */
+
+#define NAME_FLAGS_ACT (1<<(15-5)) /* name is active */
+
+#define NAME_FLAGS_CNF (1<<(15-4)) /* name is in conflict */
+
+#define NAME_FLAGS_DRG (1<<(15-3)) /* name is being deregistered */
+
+#define NAME_FLAGS_ONT (3<<(15-2)) /* bits for node type */
+#define NAME_FLAGS_ONT_B_NODE (0<<(15-2)) /* B-mode node */
+#define NAME_FLAGS_ONT_P_NODE (1<<(15-2)) /* P-mode node */
+#define NAME_FLAGS_ONT_M_NODE (2<<(15-2)) /* M-mode node */
+
+#define NAME_FLAGS_G (1<<(15-0)) /* group name */
+
+static char *
+nbns_type_name (int type)
+{
+ switch (type) {
+ case T_NB:
+ return "NB";
+ case T_NBSTAT:
+ return "NBSTAT";
+ }
+
+ return "unknown";
+}
+
+#define NBNAME_BUF_LEN 128
+
+static int
+get_nbns_name(tvbuff_t *tvb, int offset, int nbns_data_offset,
+ char *name_ret, int *name_type_ret)
+{
+ int name_len;
+ char name[MAXDNAME];
+ char nbname[NBNAME_BUF_LEN];
+ char *pname, *pnbname, cname, cnbname;
+ int name_type;
+
+ name_len = get_dns_name(tvb, offset, nbns_data_offset, name,
+ sizeof(name));
+
+ /* OK, now undo the first-level encoding. */
+ pname = &name[0];
+ pnbname = &nbname[0];
+ for (;;) {
+ /* Every two characters of the first level-encoded name
+ * turn into one character in the decoded name. */
+ cname = *pname;
+ if (cname == '\0')
+ break; /* no more characters */
+ if (cname == '.')
+ break; /* scope ID follows */
+ if (cname < 'A' || cname > 'Z') {
+ /* Not legal. */
+ strcpy(nbname,
+ "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
+ goto bad;
+ }
+ cname -= 'A';
+ cnbname = cname << 4;
+ pname++;
+
+ cname = *pname;
+ if (cname == '\0' || cname == '.') {
+ /* No more characters in the name - but we're in
+ * the middle of a pair. Not legal. */
+ strcpy(nbname,
+ "Illegal NetBIOS name (odd number of bytes)");
+ goto bad;
+ }
+ if (cname < 'A' || cname > 'Z') {
+ /* Not legal. */
+ strcpy(nbname,
+ "Illegal NetBIOS name (character not between A and Z in first-level encoding)");
+ goto bad;
+ }
+ cname -= 'A';
+ cnbname |= cname;
+ pname++;
+
+ /* Do we have room to store the character? */
+ if (pnbname < &nbname[NETBIOS_NAME_LEN]) {
+ /* Yes - store the character. */
+ *pnbname = cnbname;
+ }
+
+ /* We bump the pointer even if it's past the end of the
+ name, so we keep track of how long the name is. */
+ pnbname++;
+ }
+
+ /* NetBIOS names are supposed to be exactly 16 bytes long. */
+ if (pnbname - nbname != NETBIOS_NAME_LEN) {
+ /* It's not. */
+ sprintf(nbname, "Illegal NetBIOS name (%ld bytes long)",
+ (long)(pnbname - nbname));
+ goto bad;
+ }
+
+ /* This one is; make its name printable. */
+ name_type = process_netbios_name(nbname, name_ret);
+ name_ret += strlen(name_ret);
+ sprintf(name_ret, "<%02x>", name_type);
+ name_ret += 4;
+ if (cname == '.') {
+ /* We have a scope ID, starting at "pname"; append that to
+ * the decoded host name. */
+ strcpy(name_ret, pname);
+ }
+ if (name_type_ret != NULL)
+ *name_type_ret = name_type;
+ return name_len;
+
+bad:
+ if (name_type_ret != NULL)
+ *name_type_ret = -1;
+ strcpy (name_ret, nbname);
+ return name_len;
+}
+
+
+static int
+get_nbns_name_type_class(tvbuff_t *tvb, int offset, int nbns_data_offset,
+ char *name_ret, int *name_len_ret, int *name_type_ret, int *type_ret,
+ int *class_ret)
+{
+ int name_len;
+ int type;
+ int class;
+
+ name_len = get_nbns_name(tvb, offset, nbns_data_offset, name_ret,
+ name_type_ret);
+ offset += name_len;
+
+ type = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+
+ class = tvb_get_ntohs(tvb, offset);
+
+ *type_ret = type;
+ *class_ret = class;
+ *name_len_ret = name_len;
+
+ return name_len + 4;
+}
+
+static void
+add_name_and_type(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
+ char *tag, char *name, int name_type)
+{
+ if (name_type != -1) {
+ proto_tree_add_text(tree, tvb, offset, len, "%s: %s (%s)",
+ tag, name, netbios_name_type_descr(name_type));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, len, "%s: %s",
+ tag, name);
+ }
+}
+
+static int
+dissect_nbns_query(tvbuff_t *tvb, int offset, int nbns_data_offset,
+ column_info *cinfo, proto_tree *nbns_tree)
+{
+ int len;
+ char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
+ int name_len;
+ int name_type;
+ int type;
+ int class;
+ char *class_name;
+ char *type_name;
+ int data_offset;
+ int data_start;
+ proto_tree *q_tree;
+ proto_item *tq;
+
+ data_start = data_offset = offset;
+
+ len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
+ &name_len, &name_type, &type, &class);
+ data_offset += len;
+
+ type_name = nbns_type_name(type);
+ class_name = dns_class_name(class);
+
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
+ if (nbns_tree != NULL) {
+ tq = proto_tree_add_text(nbns_tree, tvb, offset, len,
+ "%s: type %s, class %s", name, type_name, class_name);
+ q_tree = proto_item_add_subtree(tq, ett_nbns_qd);
+
+ add_name_and_type(q_tree, tvb, offset, name_len, "Name", name,
+ name_type);
+ offset += name_len;
+
+ proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", type_name);
+ offset += 2;
+
+ proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
+ offset += 2;
+ }
+
+ return data_offset - data_start;
+}
+
+static void
+nbns_add_nbns_flags(column_info *cinfo, proto_tree *nbns_tree, tvbuff_t *tvb, int offset,
+ gushort flags, int is_wack)
+{
+ char buf[128+1];
+ guint16 opcode;
+ proto_tree *field_tree;
+ proto_item *tf;
+
+ opcode = (guint16) ((flags & F_OPCODE) >> OPCODE_SHIFT);
+ strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation"));
+ if (flags & F_RESPONSE && !is_wack) {
+ strcat(buf, " response");
+ strcat(buf, ", ");
+ strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
+ "Unknown error"));
+
+ if ((flags & F_RCODE) && check_col(cinfo, COL_INFO))
+ col_append_fstr(cinfo, COL_INFO, ", %s",
+ val_to_str(flags & F_RCODE, rcode_vals,
+ "Unknown error"));
+ }
+ tf = proto_tree_add_uint_format(nbns_tree, hf_nbns_flags,
+ tvb, offset, 2, flags, "Flags: 0x%04x (%s)", flags, buf);
+ field_tree = proto_item_add_subtree(tf, ett_nbns_flags);
+ proto_tree_add_item(field_tree, hf_nbns_flags_response,
+ tvb, offset, 2, FALSE);
+ proto_tree_add_item(field_tree, hf_nbns_flags_opcode,
+ tvb, offset, 2, FALSE);
+ if (flags & F_RESPONSE) {
+ proto_tree_add_item(field_tree, hf_nbns_flags_authoritative,
+ tvb, offset, 2, FALSE);
+ }
+ proto_tree_add_item(field_tree, hf_nbns_flags_truncated,
+ tvb, offset, 2, FALSE);
+ proto_tree_add_item(field_tree, hf_nbns_flags_recdesired,
+ tvb, offset, 2, FALSE);
+ if (flags & F_RESPONSE) {
+ proto_tree_add_item(field_tree, hf_nbns_flags_recavail,
+ tvb, offset, 2, FALSE);
+ }
+ proto_tree_add_item(field_tree, hf_nbns_flags_broadcast,
+ tvb, offset, 2, FALSE);
+ if (flags & F_RESPONSE && !is_wack) {
+ proto_tree_add_item(field_tree, hf_nbns_flags_rcode,
+ tvb, offset, 2, FALSE);
+ }
+}
+
+static void
+nbns_add_nb_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset, gushort flags)
+{
+ char buf[128+1];
+ proto_tree *field_tree;
+ proto_item *tf;
+ static const value_string nb_flags_ont_vals[] = {
+ { NB_FLAGS_ONT_B_NODE, "B-node" },
+ { NB_FLAGS_ONT_P_NODE, "P-node" },
+ { NB_FLAGS_ONT_M_NODE, "M-node" },
+ { NB_FLAGS_ONT_H_NODE, "H-node" },
+ { 0, NULL }
+ };
+
+ strcpy(buf, val_to_str(flags & NB_FLAGS_ONT, nb_flags_ont_vals,
+ "Unknown"));
+ strcat(buf, ", ");
+ if (flags & NB_FLAGS_G)
+ strcat(buf, "group");
+ else
+ strcat(buf, "unique");
+ tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Flags: 0x%x (%s)", flags,
+ buf);
+ field_tree = proto_item_add_subtree(tf, ett_nbns_nb_flags);
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, NB_FLAGS_G,
+ 2*8,
+ "Group name",
+ "Unique name"));
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
+ decode_enumerated_bitfield(flags, NB_FLAGS_ONT,
+ 2*8, nb_flags_ont_vals, "%s"));
+}
+
+static void
+nbns_add_name_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset,
+ gushort flags)
+{
+ char buf[128+1];
+ proto_item *field_tree;
+ proto_item *tf;
+ static const value_string name_flags_ont_vals[] = {
+ { NAME_FLAGS_ONT_B_NODE, "B-node" },
+ { NAME_FLAGS_ONT_P_NODE, "P-node" },
+ { NAME_FLAGS_ONT_M_NODE, "M-node" },
+ { 0, NULL }
+ };
+
+ strcpy(buf, val_to_str(flags & NAME_FLAGS_ONT, name_flags_ont_vals,
+ "Unknown"));
+ strcat(buf, ", ");
+ if (flags & NAME_FLAGS_G)
+ strcat(buf, "group");
+ else
+ strcat(buf, "unique");
+ if (flags & NAME_FLAGS_DRG)
+ strcat(buf, ", being deregistered");
+ if (flags & NAME_FLAGS_CNF)
+ strcat(buf, ", in conflict");
+ if (flags & NAME_FLAGS_ACT)
+ strcat(buf, ", active");
+ if (flags & NAME_FLAGS_PRM)
+ strcat(buf, ", permanent node name");
+ tf = proto_tree_add_text(rr_tree, tvb, offset, 2, "Name flags: 0x%x (%s)",
+ flags, buf);
+ field_tree = proto_item_add_subtree(tf, ett_nbns_name_flags);
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, NAME_FLAGS_G,
+ 2*8,
+ "Group name",
+ "Unique name"));
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
+ decode_enumerated_bitfield(flags, NAME_FLAGS_ONT,
+ 2*8, name_flags_ont_vals, "%s"));
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, NAME_FLAGS_DRG,
+ 2*8,
+ "Name is being deregistered",
+ "Name is not being deregistered"));
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, NAME_FLAGS_CNF,
+ 2*8,
+ "Name is in conflict",
+ "Name is not in conflict"));
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, NAME_FLAGS_ACT,
+ 2*8,
+ "Name is active",
+ "Name is not active"));
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, NAME_FLAGS_PRM,
+ 2*8,
+ "Permanent node name",
+ "Not permanent node name"));
+}
+
+static int
+dissect_nbns_answer(tvbuff_t *tvb, int offset, int nbns_data_offset,
+ column_info *cinfo, proto_tree *nbns_tree, int opcode)
+{
+ int len;
+ char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME + 64];
+ int name_len;
+ int name_type;
+ int type;
+ int class;
+ char *class_name;
+ char *type_name;
+ int data_offset;
+ int cur_offset;
+ int data_start;
+ guint ttl;
+ gushort data_len;
+ gushort flags;
+ proto_tree *rr_tree;
+ proto_item *trr;
+ char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
+ guint num_names;
+ char nbname[16+4+1]; /* 4 for [<last char>] */
+ gushort name_flags;
+
+ data_start = data_offset = offset;
+ cur_offset = offset;
+
+ len = get_nbns_name_type_class(tvb, offset, nbns_data_offset, name,
+ &name_len, &name_type, &type, &class);
+ data_offset += len;
+ cur_offset += len;
+
+ type_name = nbns_type_name(type);
+ class_name = dns_class_name(class);
+
+ ttl = tvb_get_ntohl(tvb, data_offset);
+ data_offset += 4;
+ cur_offset += 4;
+
+ data_len = tvb_get_ntohs(tvb, data_offset);
+ data_offset += 2;
+ cur_offset += 2;
+
+ switch (type) {
+ case T_NB: /* "NB" record */
+ if (cinfo != NULL) {
+ if (opcode != OPCODE_WACK) {
+ col_append_fstr(cinfo, COL_INFO, " %s %s",
+ type_name,
+ ip_to_str(tvb_get_ptr(tvb, data_offset+2, 4)));
+ }
+ }
+ if (nbns_tree == NULL)
+ break;
+ trr = proto_tree_add_text(nbns_tree, tvb, offset,
+ (data_offset - data_start) + data_len,
+ "%s: type %s, class %s",
+ name, type_name, class_name);
+ strcat(name, " (");
+ strcat(name, netbios_name_type_descr(name_type));
+ strcat(name, ")");
+ rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
+ name_len, type_name, class_name, ttl, data_len);
+ while (data_len > 0) {
+ if (opcode == OPCODE_WACK) {
+ /* WACK response. This doesn't contain the
+ * same type of RR data as other T_NB
+ * responses. */
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ flags = tvb_get_ntohs(tvb, cur_offset);
+ nbns_add_nbns_flags(cinfo, rr_tree, tvb, cur_offset,
+ flags, 1);
+ cur_offset += 2;
+ data_len -= 2;
+ } else {
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ flags = tvb_get_ntohs(tvb, cur_offset);
+ nbns_add_nb_flags(rr_tree, tvb, cur_offset,
+ flags);
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 4) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
+ "Addr: %s",
+ ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
+ cur_offset += 4;
+ data_len -= 4;
+ }
+ }
+ break;
+
+ case T_NBSTAT: /* "NBSTAT" record */
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", type_name);
+ if (nbns_tree == NULL)
+ break;
+ trr = proto_tree_add_text(nbns_tree, tvb, offset,
+ (data_offset - data_start) + data_len,
+ "%s: type %s, class %s",
+ name, type_name, class_name);
+ rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
+ name_len, type_name, class_name, ttl, data_len);
+ if (data_len < 1) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ num_names = tvb_get_guint8(tvb, cur_offset);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
+ "Number of names: %u", num_names);
+ cur_offset += 1;
+
+ while (num_names != 0) {
+ if (data_len < NETBIOS_NAME_LEN) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ goto out;
+ }
+ tvb_memcpy(tvb, (guint8 *)nbname, cur_offset,
+ NETBIOS_NAME_LEN);
+ name_type = process_netbios_name(nbname,
+ name_str);
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ NETBIOS_NAME_LEN, "Name: %s<%02x> (%s)",
+ name_str, name_type,
+ netbios_name_type_descr(name_type));
+ cur_offset += NETBIOS_NAME_LEN;
+ data_len -= NETBIOS_NAME_LEN;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ goto out;
+ }
+ name_flags = tvb_get_ntohs(tvb, cur_offset);
+ nbns_add_name_flags(rr_tree, tvb, cur_offset,
+ name_flags);
+ cur_offset += 2;
+ data_len -= 2;
+
+ num_names--;
+ }
+
+ if (data_len < 6) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 6,
+ "Unit ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, cur_offset, 6)));
+ cur_offset += 6;
+ data_len -= 6;
+
+ if (data_len < 1) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
+ "Jumpers: 0x%x", tvb_get_guint8(tvb, cur_offset));
+ cur_offset += 1;
+ data_len -= 1;
+
+ if (data_len < 1) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
+ "Test result: 0x%x", tvb_get_guint8(tvb, cur_offset));
+ cur_offset += 1;
+ data_len -= 1;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Version number: 0x%x", tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Period of statistics: 0x%x",
+ tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Number of CRCs: %u", tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Number of alignment errors: %u",
+ tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Number of collisions: %u", tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Number of send aborts: %u", tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 4) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
+ "Number of good sends: %u", tvb_get_ntohl(tvb, cur_offset));
+ cur_offset += 4;
+ data_len -= 4;
+
+ if (data_len < 4) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 4,
+ "Number of good receives: %u",
+ tvb_get_ntohl(tvb, cur_offset));
+ cur_offset += 4;
+ data_len -= 4;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Number of retransmits: %u", tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Number of no resource conditions: %u",
+ tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Number of command blocks: %u",
+ tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Number of pending sessions: %u",
+ tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Max number of pending sessions: %u",
+ tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Max total sessions possible: %u",
+ tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+
+ if (data_len < 2) {
+ proto_tree_add_text(rr_tree, tvb, cur_offset,
+ data_len, "(incomplete entry)");
+ break;
+ }
+ proto_tree_add_text(rr_tree, tvb, cur_offset, 2,
+ "Session data packet size: %u",
+ tvb_get_ntohs(tvb, cur_offset));
+ cur_offset += 2;
+ data_len -= 2;
+ out:
+ break;
+
+ default:
+ if (cinfo != NULL)
+ col_append_fstr(cinfo, COL_INFO, " %s", type_name);
+ if (nbns_tree == NULL)
+ break;
+ trr = proto_tree_add_text(nbns_tree, tvb, offset,
+ (data_offset - data_start) + data_len,
+ "%s: type %s, class %s",
+ name, type_name, class_name);
+ rr_tree = add_rr_to_tree(trr, ett_nbns_rr, tvb, offset, name,
+ name_len, type_name, class_name, ttl, data_len);
+ proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
+ cur_offset += data_len;
+ break;
+ }
+
+ return cur_offset - data_start;
+}
+
+static int
+dissect_query_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
+ int count, column_info *cinfo, proto_tree *nbns_tree)
+{
+ int start_off, add_off;
+ proto_tree *qatree = NULL;
+ proto_item *ti = NULL;
+
+ start_off = cur_off;
+ if (nbns_tree != NULL) {
+ ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, "Queries");
+ qatree = proto_item_add_subtree(ti, ett_nbns_qry);
+ }
+ while (count-- > 0) {
+ add_off = dissect_nbns_query(tvb, cur_off, nbns_data_offset,
+ cinfo, qatree);
+ cur_off += add_off;
+ }
+ if (ti != NULL)
+ proto_item_set_len(ti, cur_off - start_off);
+
+ return cur_off - start_off;
+}
+
+
+
+static int
+dissect_answer_records(tvbuff_t *tvb, int cur_off, int nbns_data_offset,
+ int count, column_info *cinfo, proto_tree *nbns_tree, int opcode,
+ char *name)
+{
+ int start_off, add_off;
+ proto_tree *qatree = NULL;
+ proto_item *ti = NULL;
+
+ start_off = cur_off;
+ if (nbns_tree != NULL) {
+ ti = proto_tree_add_text(nbns_tree, tvb, start_off, -1, name);
+ qatree = proto_item_add_subtree(ti, ett_nbns_ans);
+ }
+ while (count-- > 0) {
+ add_off = dissect_nbns_answer(tvb, cur_off, nbns_data_offset,
+ cinfo, qatree, opcode);
+ cur_off += add_off;
+ }
+ if (ti != NULL)
+ proto_item_set_len(ti, cur_off - start_off);
+ return cur_off - start_off;
+}
+
+static void
+dissect_nbns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ int nbns_data_offset;
+ column_info *cinfo;
+ proto_tree *nbns_tree = NULL;
+ proto_item *ti;
+ guint16 id, flags, opcode, rcode, quest, ans, auth, add;
+ int cur_off;
+
+ nbns_data_offset = offset;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBNS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* To do: check for runts, errs, etc. */
+ id = tvb_get_ntohs(tvb, offset + NBNS_ID);
+ flags = tvb_get_ntohs(tvb, offset + NBNS_FLAGS);
+ opcode = (guint16) ((flags & F_OPCODE) >> OPCODE_SHIFT);
+ rcode = (guint16) (flags & F_RCODE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s",
+ val_to_str(opcode, opcode_vals, "Unknown operation (%u)"),
+ (flags & F_RESPONSE) ? " response" : "");
+ cinfo = pinfo->cinfo;
+ } else {
+ /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query
+ and answer dissectors, as a way of saying that they
+ shouldn't add stuff to the COL_INFO column (a call to
+ "check_col(cinfo, COL_INFO)" is more expensive than
+ a check that a pointer isn't NULL). */
+ cinfo = NULL;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nbns, tvb, offset, -1,
+ FALSE);
+ nbns_tree = proto_item_add_subtree(ti, ett_nbns);
+
+ proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, tvb,
+ offset + NBNS_ID, 2, id);
+
+ nbns_add_nbns_flags(pinfo->cinfo, nbns_tree, tvb, offset + NBNS_FLAGS,
+ flags, 0);
+ }
+ quest = tvb_get_ntohs(tvb, offset + NBNS_QUEST);
+ if (tree) {
+ proto_tree_add_uint(nbns_tree, hf_nbns_count_questions, tvb,
+ offset + NBNS_QUEST, 2, quest);
+ }
+ ans = tvb_get_ntohs(tvb, offset + NBNS_ANS);
+ if (tree) {
+ proto_tree_add_uint(nbns_tree, hf_nbns_count_answers, tvb,
+ offset + NBNS_ANS, 2, ans);
+ }
+ auth = tvb_get_ntohs(tvb, offset + NBNS_AUTH);
+ if (tree) {
+ proto_tree_add_uint(nbns_tree, hf_nbns_count_auth_rr, tvb,
+ offset + NBNS_AUTH, 2, auth);
+ }
+ add = tvb_get_ntohs(tvb, offset + NBNS_ADD);
+ if (tree) {
+ proto_tree_add_uint(nbns_tree, hf_nbns_count_add_rr, tvb,
+ offset + NBNS_ADD, 2, add);
+ }
+
+ cur_off = offset + NBNS_HDRLEN;
+
+ if (quest > 0) {
+ /* If this is a response, don't add information about the
+ queries to the summary, just add information about the
+ answers. */
+ cur_off += dissect_query_records(tvb, cur_off,
+ nbns_data_offset, quest,
+ (!(flags & F_RESPONSE) ? cinfo : NULL), nbns_tree);
+ }
+
+ if (ans > 0) {
+ /* If this is a request, don't add information about the
+ answers to the summary, just add information about the
+ queries. */
+ cur_off += dissect_answer_records(tvb, cur_off,
+ nbns_data_offset, ans,
+ ((flags & F_RESPONSE) ? cinfo : NULL), nbns_tree,
+ opcode, "Answers");
+ }
+
+ if (tree) {
+ /* Don't add information about the authoritative name
+ servers, or the additional records, to the summary. */
+ if (auth > 0)
+ cur_off += dissect_answer_records(tvb, cur_off,
+ nbns_data_offset,
+ auth, NULL, nbns_tree, opcode,
+ "Authoritative nameservers");
+
+ if (add > 0)
+ cur_off += dissect_answer_records(tvb, cur_off,
+ nbns_data_offset,
+ add, NULL, nbns_tree, opcode,
+ "Additional records");
+ }
+}
+
+/* NetBIOS datagram packet, from RFC 1002, page 32 */
+struct nbdgm_header {
+ guint8 msg_type;
+ struct {
+ guint8 more;
+ guint8 first;
+ guint8 node_type;
+ } flags;
+ guint16 dgm_id;
+ guint32 src_ip;
+ guint16 src_port;
+
+ /* For packets with data */
+ guint16 dgm_length;
+ guint16 pkt_offset;
+
+ /* For error packets */
+ guint8 error_code;
+};
+
+/*
+ * NBDS message types.
+ */
+#define NBDS_DIRECT_UNIQUE 0x10
+#define NBDS_DIRECT_GROUP 0x11
+#define NBDS_BROADCAST 0x12
+#define NBDS_ERROR 0x13
+#define NBDS_QUERY_REQUEST 0x14
+#define NBDS_POS_QUERY_RESPONSE 0x15
+#define NBDS_NEG_QUERY_RESPONSE 0x16
+
+static const value_string nbds_msgtype_vals[] = {
+ { NBDS_DIRECT_UNIQUE, "Direct_unique datagram" },
+ { NBDS_DIRECT_GROUP, "Direct_group datagram" },
+ { NBDS_BROADCAST, "Broadcast datagram" },
+ { NBDS_ERROR, "Datagram error" },
+ { NBDS_QUERY_REQUEST, "Datagram query request" },
+ { NBDS_POS_QUERY_RESPONSE, "Datagram positive query response" },
+ { NBDS_NEG_QUERY_RESPONSE, "Datagram negative query response" },
+ { 0, NULL }
+};
+
+static const true_false_string yesno = {
+ "Yes",
+ "No"
+};
+
+static const value_string node_type_vals[] = {
+ { 0, "B node" },
+ { 1, "P node" },
+ { 2, "M node" },
+ { 3, "NBDD" },
+ { 0, NULL }
+};
+
+static void
+dissect_nbdgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *nbdgm_tree = NULL;
+ proto_item *ti = NULL;
+ struct nbdgm_header header;
+ int flags;
+ int message_index;
+ tvbuff_t *next_tvb;
+
+ static const value_string error_codes[] = {
+ { 0x82, "Destination name not present" },
+ { 0x83, "Invalid source name format" },
+ { 0x84, "Invalid destination name format" },
+ { 0x00, NULL }
+ };
+
+ char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
+ int name_type;
+ int len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBDS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ header.msg_type = tvb_get_guint8(tvb, offset);
+
+ flags = tvb_get_guint8(tvb, offset+1);
+ header.flags.more = flags & 1;
+ header.flags.first = (flags & 2) >> 1;
+ header.flags.node_type = (flags & 12) >> 2;
+
+ header.dgm_id = tvb_get_ntohs(tvb, offset+2);
+ tvb_memcpy(tvb, (guint8 *)&header.src_ip, offset+4, 4);
+ header.src_port = tvb_get_ntohs(tvb, offset+8);
+
+ switch (header.msg_type) {
+
+ case NBDS_DIRECT_UNIQUE:
+ case NBDS_DIRECT_GROUP:
+ case NBDS_BROADCAST:
+ header.dgm_length = tvb_get_ntohs(tvb, offset+10);
+ header.pkt_offset = tvb_get_ntohs(tvb, offset+12);
+ break;
+
+ case NBDS_ERROR:
+ header.error_code = tvb_get_guint8(tvb, offset+10);
+ break;
+ }
+
+ message_index = header.msg_type - 0x0f;
+ if (message_index < 1 || message_index > 8) {
+ message_index = 0;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(header.msg_type, nbds_msgtype_vals,
+ "Unknown message type (0x%02X)"));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nbdgm, tvb, offset, -1,
+ FALSE);
+ nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
+
+ proto_tree_add_uint(nbdgm_tree, hf_nbdgm_type, tvb,
+ offset, 1,
+ header.msg_type);
+ proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_fragment, tvb,
+ offset+1, 1,
+ header.flags.more);
+ proto_tree_add_boolean(nbdgm_tree, hf_nbdgm_first, tvb,
+ offset+1, 1,
+ header.flags.first);
+ proto_tree_add_uint(nbdgm_tree, hf_nbdgm_node_type, tvb,
+ offset+1, 1,
+ header.flags.node_type);
+
+ proto_tree_add_uint(nbdgm_tree, hf_nbdgm_datagram_id, tvb,
+ offset+2, 2, header.dgm_id);
+ proto_tree_add_ipv4(nbdgm_tree, hf_nbdgm_src_ip, tvb,
+ offset+4, 4, header.src_ip);
+ proto_tree_add_uint(nbdgm_tree, hf_nbdgm_src_port, tvb,
+ offset+8, 2, header.src_port);
+
+ }
+
+ offset += 10;
+
+ switch (header.msg_type) {
+
+ case NBDS_DIRECT_UNIQUE:
+ case NBDS_DIRECT_GROUP:
+ case NBDS_BROADCAST:
+ if (tree) {
+ proto_tree_add_text(nbdgm_tree, tvb, offset, 2,
+ "Datagram length: %d bytes", header.dgm_length);
+ proto_tree_add_text(nbdgm_tree, tvb, offset+2, 2,
+ "Packet offset: %d bytes", header.pkt_offset);
+ }
+
+ offset += 4;
+
+ /* Source name */
+ len = get_nbns_name(tvb, offset, offset, name, &name_type);
+
+ if (tree) {
+ add_name_and_type(nbdgm_tree, tvb, offset, len,
+ "Source name", name, name_type);
+ }
+ offset += len;
+
+ /* Destination name */
+ len = get_nbns_name(tvb, offset, offset, name, &name_type);
+
+ if (tree) {
+ add_name_and_type(nbdgm_tree, tvb, offset, len,
+ "Destination name", name, name_type);
+ }
+ offset += len;
+
+ /*
+ * Here we can pass the packet off to the next protocol.
+ * Set the length of our top-level tree item to include
+ * only our stuff.
+ *
+ * XXX - take the datagram length into account?
+ */
+ proto_item_set_len(ti, offset);
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ dissect_netbios_payload(next_tvb, pinfo, tree);
+ break;
+
+ case NBDS_ERROR:
+ if (tree) {
+ proto_tree_add_text(nbdgm_tree, tvb, offset, 1, "Error code: %s",
+ val_to_str(header.error_code, error_codes, "Unknown (0x%x)"));
+ }
+ offset += 1;
+ proto_item_set_len(ti, offset);
+ break;
+
+ case NBDS_QUERY_REQUEST:
+ case NBDS_POS_QUERY_RESPONSE:
+ case NBDS_NEG_QUERY_RESPONSE:
+ /* Destination name */
+ len = get_nbns_name(tvb, offset, offset, name, &name_type);
+
+ if (tree) {
+ add_name_and_type(nbdgm_tree, tvb, offset, len,
+ "Destination name", name, name_type);
+ }
+ offset += len;
+ proto_item_set_len(ti, offset);
+ break;
+ }
+}
+
+/*
+ * NetBIOS Session Service message types.
+ */
+#define SESSION_MESSAGE 0x00
+#define SESSION_REQUEST 0x81
+#define POSITIVE_SESSION_RESPONSE 0x82
+#define NEGATIVE_SESSION_RESPONSE 0x83
+#define RETARGET_SESSION_RESPONSE 0x84
+#define SESSION_KEEP_ALIVE 0x85
+
+static const value_string message_types[] = {
+ { SESSION_MESSAGE, "Session message" },
+ { SESSION_REQUEST, "Session request" },
+ { POSITIVE_SESSION_RESPONSE, "Positive session response" },
+ { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
+ { RETARGET_SESSION_RESPONSE, "Retarget session response" },
+ { SESSION_KEEP_ALIVE, "Session keep-alive" },
+ { 0x0, NULL }
+};
+
+/*
+ * NetBIOS Session Service flags.
+ */
+#define NBSS_FLAGS_E 0x1
+
+static const value_string error_codes[] = {
+ { 0x80, "Not listening on called name" },
+ { 0x81, "Not listening for called name" },
+ { 0x82, "Called name not present" },
+ { 0x83, "Called name present, but insufficient resources" },
+ { 0x8F, "Unspecified error" },
+ { 0x0, NULL }
+};
+
+/*
+ * Dissect a single NBSS packet (there may be more than one in a given
+ * TCP segment).
+ *
+ * [ Hmmm, in my experience, I have never seen more than one NBSS in a
+ * single segment, since they mostly contain SMBs which are essentially
+ * a request response type protocol (RJS). ]
+ *
+ * [ However, under heavy load with many requests multiplexed on one
+ * session it is not unusual to see multiple requests in one TCP
+ * segment. Unfortunately, in this case a single session message is
+ * frequently split over multiple segments, which frustrates decoding
+ * (MMM). ]
+ */
+static int
+dissect_nbss_packet(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, int is_cifs)
+{
+ proto_tree *nbss_tree = NULL;
+ proto_item *ti = NULL;
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint8 msg_type;
+ guint8 flags;
+ volatile int length;
+ int length_remaining;
+ int len;
+ char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
+ int name_type;
+ gint reported_len;
+ tvbuff_t *next_tvb;
+ const char *saved_proto;
+
+ /* Desegmentation */
+ length_remaining = tvb_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (nbss_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the NBSS header split across segment boundaries?
+ */
+ if (length_remaining < 4) {
+ /*
+ * Yes. Tell our caller how many more bytes
+ * we need.
+ */
+ return -(4 - length_remaining);
+ }
+ }
+
+ /*
+ * Get the length of the NBSS message.
+ */
+ if (is_cifs) {
+ flags = 0;
+ length = tvb_get_ntoh24(tvb, offset + 1);
+ } else {
+ flags = tvb_get_guint8(tvb, offset + 1);
+ length = tvb_get_ntohs(tvb, offset + 2);
+ if (flags & NBSS_FLAGS_E)
+ length += 65536;
+ }
+
+ /* give a hint to TCP where the next PDU starts
+ * so that it can attempt to find it in case it starts
+ * somewhere in the middle of a segment.
+ */
+ if(!pinfo->fd->flags.visited){
+ if((length+4)>tvb_reported_length_remaining(tvb, offset)){
+ pinfo->want_pdu_tracking=2;
+ pinfo->bytes_until_next_pdu=(length+4)-tvb_reported_length_remaining(tvb, offset);
+ }
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (nbss_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the NBSS message split across segment boundaries?
+ */
+ if (length_remaining < length + 4) {
+ /*
+ * Yes. Tell our caller how many more bytes
+ * we need.
+ */
+ return -((length + 4) - length_remaining);
+ }
+ }
+
+ msg_type = tvb_get_guint8(tvb, offset);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nbss, tvb, offset, length + 4, FALSE);
+ nbss_tree = proto_item_add_subtree(ti, ett_nbss);
+
+ proto_tree_add_uint_format(nbss_tree, hf_nbss_type, tvb,
+ offset, 1,
+ msg_type,
+ "Message Type: %s",
+ val_to_str(msg_type, message_types,
+ "Unknown (%x)"));
+ }
+
+ offset += 1;
+
+ if (is_cifs) {
+ if (tree) {
+ proto_tree_add_text(nbss_tree, tvb, offset, 3, "Length: %u", length);
+ }
+ offset += 3;
+ } else {
+ if (tree) {
+ tf = proto_tree_add_uint(nbss_tree, hf_nbss_flags, tvb, offset, 1, flags);
+ field_tree = proto_item_add_subtree(tf, ett_nbss_flags);
+ proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(flags, NBSS_FLAGS_E,
+ 8, "Add 65536 to length", "Add 0 to length"));
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_text(nbss_tree, tvb, offset, 2, "Length: %u", length);
+ }
+
+ offset += 2;
+ }
+
+ switch (msg_type) {
+
+ case SESSION_REQUEST:
+ len = get_nbns_name(tvb, offset, offset, name, &name_type);
+ if (tree)
+ add_name_and_type(nbss_tree, tvb, offset, len,
+ "Called name", name, name_type);
+ offset += len;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", to %s ", name);
+
+ len = get_nbns_name(tvb, offset, offset, name, &name_type);
+
+ if (tree)
+ add_name_and_type(nbss_tree, tvb, offset, len,
+ "Calling name", name, name_type);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "from %s", name);
+
+ break;
+
+ case NEGATIVE_SESSION_RESPONSE:
+ if (tree)
+ proto_tree_add_text(nbss_tree, tvb, offset, 1,
+ "Error code: %s",
+ val_to_str(tvb_get_guint8(tvb, offset),
+ error_codes, "Unknown (%x)"));
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(tvb_get_guint8(tvb, offset),
+ error_codes, "Unknown (%x)"));
+
+ break;
+
+ case RETARGET_SESSION_RESPONSE:
+ if (tree)
+ proto_tree_add_text(nbss_tree, tvb, offset, 4,
+ "Retarget IP address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+
+ offset += 4;
+
+ if (tree)
+ proto_tree_add_text(nbss_tree, tvb, offset, 2,
+ "Retarget port: %u",
+ tvb_get_ntohs(tvb, offset));
+
+ break;
+
+ case SESSION_MESSAGE:
+ /*
+ * Here we can pass the message off to the next protocol.
+ * Set the length of our top-level tree item to include
+ * only our stuff.
+ */
+ proto_item_set_len(ti, offset);
+ len = tvb_length_remaining(tvb, offset);
+ reported_len = tvb_reported_length_remaining(tvb, offset);
+ if (len > length)
+ len = length;
+ if (reported_len > length)
+ reported_len = length;
+
+ next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
+
+ /*
+ * Catch the ReportedBoundsError exception; if this
+ * particular message happens to get a ReportedBoundsError
+ * exception, that doesn't mean that we should stop
+ * dissecting NetBIOS messages within this frame or chunk
+ * of reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing
+ * more to see, so we just re-throw it.
+ */
+ saved_proto = pinfo->current_proto;
+ TRY {
+ dissect_netbios_payload(next_tvb, pinfo, tree);
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ pinfo->current_proto = saved_proto;
+ }
+ ENDTRY;
+ break;
+
+ }
+ return length + 4;
+}
+
+static void
+dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct tcpinfo *tcpinfo = pinfo->private_data;
+ int offset = 0;
+ int max_data;
+ guint8 msg_type;
+ guint8 flags;
+ guint32 length;
+ int len;
+ gboolean is_cifs;
+ proto_tree *nbss_tree;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBSS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ max_data = tvb_length(tvb);
+
+ msg_type = tvb_get_guint8(tvb, offset);
+
+ if (pinfo->match_port == TCP_PORT_CIFS) {
+ /*
+ * Windows 2000 CIFS clients can dispense completely
+ * with the NETBIOS encapsulation and directly use CIFS
+ * over TCP. As would be expected, the framing is
+ * identical, except that the length is 24 bits instead
+ * of 17. The only message types used are
+ * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
+ */
+ is_cifs = TRUE;
+ } else {
+ is_cifs = FALSE;
+ }
+
+ /*
+ * This might be a continuation of an earlier message.
+ * (Yes, that might be true even if we're doing TCP reassembly,
+ * as the first TCP segment in the capture might start in the
+ * middle of an NBNS message.)
+ */
+
+ /*
+ * If this isn't reassembled data, check to see whether it
+ * looks like a continuation of a message.
+ * (If it is reassembled data, it shouldn't be a continuation,
+ * as reassembly should've gathered the continuations together
+ * into a message.)
+ */
+ if (!tcpinfo->is_reassembled) {
+ if (max_data < 4) {
+ /*
+ * Not enough data for an NBSS header; assume
+ * it's a continuation of a message.
+ *
+ * XXX - if there's not enough data, we should
+ * attempt to reassemble the data, if the first byte
+ * is a valid message type.
+ */
+ goto continuation;
+ }
+
+ /*
+ * We have enough data for an NBSS header.
+ * Get the flags and length of the message,
+ * and see if they're sane.
+ */
+ if (is_cifs) {
+ flags = 0;
+ length = tvb_get_ntoh24(tvb, offset + 1);
+ } else {
+ flags = tvb_get_guint8(tvb, offset + 1);
+ length = tvb_get_ntohs(tvb, offset + 2);
+ if (flags & NBSS_FLAGS_E)
+ length += 65536;
+ }
+ if ((flags & (~NBSS_FLAGS_E)) != 0) {
+ /*
+ * A bogus flag was set; assume it's a continuation.
+ */
+ goto continuation;
+ }
+
+ switch (msg_type) {
+
+ case SESSION_MESSAGE:
+ /*
+ * This is variable-length.
+ * All we know is that it shouldn't be zero.
+ * (XXX - can we get zero-length messages?
+ * Not with SMB, but perhaps other NetBIOS-based
+ * protocols have them.)
+ */
+ if (length == 0)
+ goto continuation;
+ break;
+
+ case SESSION_REQUEST:
+ /*
+ * This is variable-length.
+ * The names are DNS-encoded 32-byte values;
+ * we need at least 2 bytes (one for each name;
+ * actually, we should have more for the first
+ * name, as there's no name preceding it so
+ * there should be no compression), and we
+ * shouldn't have more than 128 bytes (actually,
+ * we shouldn't have that many).
+ *
+ * XXX - actually, MacOS X 10.1 (yes, that's
+ * redundant, but that's what Apple calls it,
+ * not MacOS X.1) puts names longer than 16
+ * characters into session request messages,
+ * so we can have more than 32 bytes of
+ * name value, so we can have more than 128
+ * bytes of data.
+ */
+ if (length < 2 || length > 256)
+ goto continuation;
+ break;
+
+ case POSITIVE_SESSION_RESPONSE:
+ /*
+ * This has no data, so the length must be zero.
+ */
+ if (length != 0)
+ goto continuation;
+ break;
+
+ case NEGATIVE_SESSION_RESPONSE:
+ /*
+ * This has 1 byte of data.
+ */
+ if (length != 1)
+ goto continuation;
+ break;
+
+ case RETARGET_SESSION_RESPONSE:
+ /*
+ * This has 6 bytes of data.
+ */
+ if (length != 6)
+ goto continuation;
+ break;
+
+ case SESSION_KEEP_ALIVE:
+ /*
+ * This has no data, so the length must be zero.
+ */
+ if (length != 0)
+ goto continuation;
+ break;
+
+ default:
+ /*
+ * Unknown message type; assume it's a continuation.
+ */
+ goto continuation;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ val_to_str(msg_type, message_types, "Unknown (%02x)"));
+ }
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ len = dissect_nbss_packet(tvb, offset, pinfo, tree, is_cifs);
+ if (len < 0) {
+ /*
+ * We need more data to dissect this, and
+ * desegmentation is enabled. "-len" is the
+ * number of additional bytes of data we need.
+ *
+ * Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and
+ * how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = -len;
+ return;
+ }
+ offset += len;
+ }
+
+ return;
+
+continuation:
+ /*
+ * It looks like a continuation.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "NBSS Continuation Message");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nbss, tvb, 0, -1, FALSE);
+ nbss_tree = proto_item_add_subtree(ti, ett_nbss);
+ proto_tree_add_text(nbss_tree, tvb, 0, -1, "Continuation data");
+ }
+}
+
+void
+proto_register_nbt(void)
+{
+
+ static hf_register_info hf_nbns[] = {
+ { &hf_nbns_flags,
+ { "Flags", "nbns.flags",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_nbns_flags_response,
+ { "Response", "nbns.flags.response",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
+ "Is the message a response?", HFILL }},
+ { &hf_nbns_flags_opcode,
+ { "Opcode", "nbns.flags.opcode",
+ FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
+ "Operation code", HFILL }},
+ { &hf_nbns_flags_authoritative,
+ { "Authoritative", "nbns.flags.authoritative",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
+ "Is the server is an authority for the domain?", HFILL }},
+ { &hf_nbns_flags_truncated,
+ { "Truncated", "nbns.flags.truncated",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
+ "Is the message truncated?", HFILL }},
+ { &hf_nbns_flags_recdesired,
+ { "Recursion desired", "nbns.flags.recdesired",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
+ "Do query recursively?", HFILL }},
+ { &hf_nbns_flags_recavail,
+ { "Recursion available", "nbns.flags.recavail",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
+ "Can the server do recursive queries?", HFILL }},
+ { &hf_nbns_flags_broadcast,
+ { "Broadcast", "nbns.flags.broadcast",
+ FT_BOOLEAN, 16, TFS(&tfs_flags_broadcast), F_BROADCAST,
+ "Is this a broadcast packet?", HFILL }},
+ { &hf_nbns_flags_rcode,
+ { "Reply code", "nbns.flags.rcode",
+ FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
+ "Reply code", HFILL }},
+ { &hf_nbns_transaction_id,
+ { "Transaction ID", "nbns.id",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Identification of transaction", HFILL }},
+ { &hf_nbns_count_questions,
+ { "Questions", "nbns.count.queries",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of queries in packet", HFILL }},
+ { &hf_nbns_count_answers,
+ { "Answer RRs", "nbns.count.answers",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of answers in packet", HFILL }},
+ { &hf_nbns_count_auth_rr,
+ { "Authority RRs", "nbns.count.auth_rr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of authoritative records in packet", HFILL }},
+ { &hf_nbns_count_add_rr,
+ { "Additional RRs", "nbns.count.add_rr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of additional records in packet", HFILL }}
+ };
+
+ static hf_register_info hf_nbdgm[] = {
+ { &hf_nbdgm_type,
+ { "Message Type", "nbdgm.type",
+ FT_UINT8, BASE_DEC, VALS(nbds_msgtype_vals), 0x0,
+ "NBDGM message type", HFILL }},
+ { &hf_nbdgm_fragment,
+ { "More fragments follow", "nbdgm.next",
+ FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
+ "TRUE if more fragments follow", HFILL }},
+ { &hf_nbdgm_first,
+ { "This is first fragment", "nbdgm.first",
+ FT_BOOLEAN, BASE_NONE, TFS(&yesno), 0x0,
+ "TRUE if first fragment", HFILL }},
+ { &hf_nbdgm_node_type,
+ { "Node Type", "nbdgm.node_type",
+ FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0,
+ "Node type", HFILL }},
+ { &hf_nbdgm_datagram_id,
+ { "Datagram ID", "nbdgm.dgram_id",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Datagram identifier", HFILL }},
+ { &hf_nbdgm_src_ip,
+ { "Source IP", "nbdgm.src.ip",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Source IPv4 address", HFILL }},
+ { &hf_nbdgm_src_port,
+ { "Source Port", "nbdgm.src.port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Source port", HFILL }}
+ };
+
+ static hf_register_info hf_nbss[] = {
+ { &hf_nbss_type,
+ { "Message Type", "nbss.type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "NBSS message type", HFILL }},
+ { &hf_nbss_flags,
+ { "Flags", "nbss.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "NBSS message flags", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_nbns,
+ &ett_nbns_qd,
+ &ett_nbns_flags,
+ &ett_nbns_nb_flags,
+ &ett_nbns_name_flags,
+ &ett_nbns_rr,
+ &ett_nbns_qry,
+ &ett_nbns_ans,
+ &ett_nbdgm,
+ &ett_nbss,
+ &ett_nbss_flags,
+ };
+ module_t *nbss_module;
+
+ proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
+ proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
+
+ proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
+ "NBDS", "nbdgm");
+ proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
+
+ proto_nbss = proto_register_protocol("NetBIOS Session Service",
+ "NBSS", "nbss");
+ proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+ nbss_module = prefs_register_protocol(proto_nbss, NULL);
+ prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",
+ "Desegment all NBSS packets spanning multiple TCP segments",
+ "Whether NBSS dissector should desegment all packets spanning multiple TCP segments",
+ &nbss_desegment);
+}
+
+void
+proto_reg_handoff_nbt(void)
+{
+ dissector_handle_t nbns_handle, nbdgm_handle, nbss_handle;
+
+ nbns_handle = create_dissector_handle(dissect_nbns, proto_nbns);
+ dissector_add("udp.port", UDP_PORT_NBNS, nbns_handle);
+ nbdgm_handle = create_dissector_handle(dissect_nbdgm, proto_nbdgm);
+ dissector_add("udp.port", UDP_PORT_NBDGM, nbdgm_handle);
+ nbss_handle = create_dissector_handle(dissect_nbss, proto_nbss);
+ dissector_add("tcp.port", TCP_PORT_NBSS, nbss_handle);
+ dissector_add("tcp.port", TCP_PORT_CIFS, nbss_handle);
+}
diff --git a/epan/dissectors/packet-ncp-int.h b/epan/dissectors/packet-ncp-int.h
new file mode 100644
index 0000000000..124fac3085
--- /dev/null
+++ b/epan/dissectors/packet-ncp-int.h
@@ -0,0 +1,142 @@
+/* packet-ncp-int.h
+ * Structures and functions for NetWare Core Protocol.
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ * Modified for NDS support by Greg Morris (gmorris@novell.com)
+ *
+ * Portions Copyright (c) Gilbert Ramirez 2000-2002
+ * Portions Copyright (c) Novell, Inc. 2000-2003
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2000 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_NCP_INT_H__
+#define __PACKET_NCP_INT_H__
+
+typedef struct _ptvc_record ptvc_record;
+typedef struct _sub_ptvc_record sub_ptvc_record;
+
+struct _ptvc_record {
+ int *hf_ptr;
+ gint length;
+ const sub_ptvc_record *sub_ptvc_rec;
+ unsigned int endianness : 1; /* 0=BE, 1=LE */
+ unsigned int var_index : 2;
+ unsigned int repeat_index : 2;
+ unsigned int req_cond_index : 8;
+ unsigned int special_fmt : 2;
+};
+
+#define NCP_FMT_NONE 0
+#define NCP_FMT_NW_DATE 1
+#define NCP_FMT_NW_TIME 2
+#define NCP_FMT_UNICODE 3
+
+extern gboolean nds_defragment;
+
+struct _sub_ptvc_record {
+ gint *ett;
+ const char *descr;
+ const ptvc_record *ptvc_rec;
+};
+
+typedef struct {
+ const char *dfilter_text;
+ dfilter_t *dfilter;
+} conditional_record;
+
+typedef struct {
+ int *hf_ptr;
+ const char *first_string;
+ const char *repeat_string;
+} info_string_t;
+
+typedef struct {
+ guint8 error_in_packet;
+ gint ncp_error_index;
+} error_equivalency;
+
+typedef struct {
+ guint8 func;
+ guint8 subfunc;
+ guint8 has_subfunc;
+ gchar* name;
+ gint group;
+ const ptvc_record *request_ptvc;
+ const ptvc_record *reply_ptvc;
+ const error_equivalency *errors;
+ const int *req_cond_indexes;
+ unsigned int req_cond_size_type;
+ const info_string_t *req_info_str;
+} ncp_record;
+
+typedef struct {
+ const ncp_record *ncp_rec;
+ gboolean *req_cond_results;
+ guint32 req_frame_num;
+ nstime_t req_frame_time;
+ guint32 req_nds_flags;
+ guint8 nds_request_verb;
+ guint8 nds_version;
+ char object_name[256];
+ gboolean nds_frag;
+ guint32 nds_end_frag;
+ guint32 nds_frag_num;
+} ncp_req_hash_value;
+
+void dissect_ncp_request(tvbuff_t*, packet_info*, guint16,
+ guint8, guint16, proto_tree*);
+
+void dissect_ncp_reply(tvbuff_t *, packet_info*, guint16, guint8,
+ guint16, proto_tree*);
+
+void dissect_ping_req(tvbuff_t *, packet_info*, guint16, guint8,
+ guint16, proto_tree*);
+
+void dissect_nds_request(tvbuff_t*, packet_info*, guint16,
+ guint8, guint16, proto_tree*);
+
+void nds_defrag(tvbuff_t*, packet_info*, guint16,
+ guint8, guint16, proto_tree*);
+
+extern int proto_ncp;
+extern gint ett_ncp;
+extern gint ett_nds;
+extern gint ett_nds_segments;
+extern gint ett_nds_segment;
+
+
+extern GHashTable *nds_fragment_table;
+extern GHashTable *nds_reassembled_table;
+extern dissector_handle_t nds_data_handle;
+/*
+ * NCP packet types.
+ */
+#define NCP_ALLOCATE_SLOT 0x1111
+#define NCP_SERVICE_REQUEST 0x2222
+#define NCP_SERVICE_REPLY 0x3333
+#define NCP_WATCHDOG 0x3e3e
+#define NCP_DEALLOCATE_SLOT 0x5555
+#define NCP_BURST_MODE_XFER 0x7777
+#define NCP_POSITIVE_ACK 0x9999
+#define NCP_BROADCAST_SLOT 0xbbbb
+#define NCP_LIP_ECHO 0x4c69
+
+#endif
diff --git a/epan/dissectors/packet-ncp-nmas.c b/epan/dissectors/packet-ncp-nmas.c
new file mode 100644
index 0000000000..65517acbbc
--- /dev/null
+++ b/epan/dissectors/packet-ncp-nmas.c
@@ -0,0 +1,734 @@
+/* packet-ncp-nmas.c
+ * Routines for Novell Modular Authentication Service
+ * Greg Morris <gmorris@novell.com>
+ * Copyright (c) Novell, Inc. 2002-2004
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "packet-ncp-int.h"
+#include "packet-ncp-nmas.h"
+
+static gint ett_nmas = -1;
+
+static int proto_nmas = -1;
+static int hf_func = -1;
+static int hf_subfunc = -1;
+static int hf_ping_version = -1;
+static int hf_ping_flags = -1;
+static int hf_frag_handle = -1;
+static int hf_length = -1;
+static int hf_subverb = -1;
+static int hf_tree = -1;
+static int hf_user = -1;
+static int hf_nmas_version = -1;
+static int hf_msg_version = -1;
+static int hf_session_ident = -1;
+static int hf_msg_verb = -1;
+static int hf_attribute = -1;
+static int hf_clearence = -1;
+static int hf_login_sequence = -1;
+static int hf_opaque = -1;
+static int hf_data = -1;
+static int hf_return_code = -1;
+static int hf_lsm_verb = -1;
+static int hf_squeue_bytes = -1;
+static int hf_cqueue_bytes = -1;
+static int hf_num_creds = -1;
+static int hf_cred_type = -1;
+static int hf_login_state = -1;
+static int hf_enc_cred = -1;
+static int hf_enc_data = -1;
+
+static const value_string nmas_func_enum[] = {
+ { 0x00000001, "Ping" },
+ { 0x00000002, "Fragment" },
+ { 0x00000003, "Abort" },
+ { 0, NULL }
+};
+
+static const value_string nmas_subverb_enum[] = {
+ { 0, "Fragmented Ping" },
+ { 2, "Client Put Data" },
+ { 4, "Client Get Data" },
+ { 6, "Client Get User NDS Credentials" },
+ { 8, "Login Store Management" },
+ { 10, "Writable Object Check" },
+ { 1242, "Message Handler" },
+ { 0, NULL }
+};
+
+static const value_string nmas_msgverb_enum[] = {
+ { 1, "Echo Data" },
+ { 3, "Start Session" },
+ { 5, "Client Write Data" },
+ { 7, "Client Read Data" },
+ { 9, "End Session" },
+ { 0, NULL }
+};
+
+static const value_string nmas_attribute_enum[] = {
+ { 1, "User Name" },
+ { 2, "Tree Name" },
+ { 4, "Clearence" },
+ { 11, "Login Sequence" },
+ { 0, NULL }
+};
+
+static const value_string nmas_lsmverb_enum[] = {
+ { 1, "Put Login Configuration" },
+ { 2, "Get Login Configuration" },
+ { 4, "Delete Login Configuration" },
+ { 5, "Put Login Secret" },
+ { 6, "Delete Login Secret" },
+ { 0, NULL }
+};
+
+static const value_string nmas_errors_enum[] = {
+ { 0xFFFFF9A1, "(-1631) FRAGMENT FAILURE" },
+ { 0xFFFFF9A0, "(-1632) BAD REQUEST SYNTAX" },
+ { 0xFFFFF99F, "(-1633) BUFFER OVERFLOW" },
+ { 0xFFFFF99E, "(-1634) SYSTEM RESOURCES" },
+ { 0xFFFFF99D, "(-1635) INSUFFICIENT MEMORY" },
+ { 0xFFFFF99C, "(-1636) NOT SUPPORTED" },
+ { 0xFFFFF99B, "(-1637) BUFFER UNDERFLOW" },
+ { 0xFFFFF99A, "(-1638) NOT FOUND" },
+ { 0xFFFFF999, "(-1639) INVALID OPERATION" },
+ { 0xFFFFF998, "(-1640) ASN1 DECODE" },
+ { 0xFFFFF997, "(-1641) ASN1 ENCODE" },
+ { 0xFFFFF996, "(-1642) LOGIN FAILED" },
+ { 0xFFFFF995, "(-1643) INVALID PARAMETER" },
+ { 0xFFFFF994, "(-1644) TIMED OUT RECOVERABLE" },
+ { 0xFFFFF993, "(-1645) TIMED OUT NOT RECOVERABLE" },
+ { 0xFFFFF992, "(-1646) TIMED OUT UNKNOWN" },
+ { 0xFFFFF991, "(-1647) AUTHORIZATION FAILURE" },
+ { 0xFFFFF990, "(-1648) INVALID DISTINGUSHED NAME" },
+ { 0xFFFFF98F, "(-1649) CANNOT RESOLVE DISTINGUISHED NAME" },
+ { 0xFFFFF98E, "(-1650) CANNOT RESOLVE CONNECTION" },
+ { 0xFFFFF98D, "(-1651) NO CRYPTOGRAPHY" },
+ { 0xFFFFF98C, "(-1652) INVALID VERSION" },
+ { 0xFFFFF98B, "(-1653) SYNC NEEDED" },
+ { 0xFFFFF98A, "(-1654) PROTOCOL STATE" },
+ { 0xFFFFF989, "(-1655) INVALID HANDLE" },
+ { 0xFFFFF988, "(-1656) INVALID METHOD" },
+ { 0xFFFFF987, "(-1657) DEVELOPMENT VERSION" },
+ { 0xFFFFF986, "(-1658) MISSING KEY" },
+ { 0xFFFFF985, "(-1659) ACCESS NOT ALLOWED" },
+ { 0xFFFFF984, "(-1660) SEQUENCE NOT FOUND" },
+ { 0xFFFFF983, "(-1661) CLEARANCE NOT FOUND" },
+ { 0xFFFFF982, "(-1662) LOGIN SERVER METHOD NOT FOUND" },
+ { 0xFFFFF981, "(-1663) LOGIN CLIENT METHOD NOT FOUND" },
+ { 0xFFFFF980, "(-1664) SERVER NOT FOUND" },
+ { 0xFFFFF97F, "(-1665) LOGIN ATTRIBUTE NOT FOUND" },
+ { 0xFFFFF97E, "(-1666) LEGACY INVALID PASSWORD" },
+ { 0xFFFFF97D, "(-1667) ACCOUNT DISABLED" },
+ { 0xFFFFF97C, "(-1668) ACCOUNT LOCKED" },
+ { 0xFFFFF97B, "(-1669) ADDRESS RESTRICTION" },
+ { 0xFFFFF97A, "(-1670) CONNECTION CLEARED" },
+ { 0xFFFFF979, "(-1671) TIME RESTRICTION" },
+ { 0xFFFFF978, "(-1672) SHORT TERM SECRET" },
+ { 0xFFFFF977, "(-1673) NO NMAS ON TREE" },
+ { 0xFFFFF976, "(-1674) NO NMAS ON SERVER" },
+ { 0xFFFFF975, "(-1675) REQUEST CHALLENGED" },
+ { 0xFFFFF974, "(-1676) LOGIN CANCELED" },
+ { 0xFFFFF973, "(-1677) LOCAL CREDENTIAL STORE" },
+ { 0xFFFFF972, "(-1678) REMOTE CREDENTIAL STORE" },
+ { 0xFFFFF971, "(-1679) SMC NICM" },
+ { 0xFFFFF970, "(-1680) SEQUENCE NOT AUTHORIZED" },
+ { 0xFFFFF96F, "(-1681) TRANSPORT" },
+ { 0xFFFFF96E, "(-1682) CRYPTO FAILED INIT" },
+ { 0xFFFFF96D, "(-1683) DOUBLEBYTE FAILED INIT" },
+ { 0xFFFFF96C, "(-1684) CODEPAGE FAILED INIT" },
+ { 0xFFFFF96B, "(-1685) UNICODE FAILED INIT" },
+ { 0xFFFFF96A, "(-1686) DLL FAILED LOADING" },
+ { 0xFFFFF969, "(-1687) EVALUATION VERSION WARNING" },
+ { 0xFFFFF968, "(-1688) CONCURRENT LOGIN" },
+ { 0xFFFFF969, "(-1689) THREAD CREATE" },
+ { 0xFFFFF96A, "(-1690) SECURE CHANNEL REQUIRED" },
+ { 0xFFFFF96B, "(-1691) NO DEFAULT USER SEQUENCE" },
+ { 0xFFFFF96C, "(-1692) NO TREENAME" },
+ { 0xFFFFF96D, "(-1693) MECHANISM NOT FOUND" },
+ { 0, NULL }
+};
+
+static int
+align_4(tvbuff_t *tvb, int aoffset)
+{
+ if(tvb_length_remaining(tvb, aoffset) > 4 )
+ {
+ return (aoffset%4);
+ }
+ return 0;
+}
+
+static int
+nmas_string(tvbuff_t* tvb, int hfinfo, proto_tree *nmas_tree, int offset, gboolean little)
+{
+ int foffset = offset;
+ guint32 str_length;
+ char buffer[1024];
+ guint32 i;
+ guint16 c_char;
+ guint32 length_remaining = 0;
+
+ if (little) {
+ str_length = tvb_get_letohl(tvb, foffset);
+ }
+ else
+ {
+ str_length = tvb_get_ntohl(tvb, foffset);
+ }
+ foffset += 4;
+ length_remaining = tvb_length_remaining(tvb, foffset);
+ if(str_length > (guint)length_remaining || str_length > 1024)
+ {
+ proto_tree_add_string(nmas_tree, hfinfo, tvb, foffset,
+ length_remaining + 4, "<String too long to process>");
+ foffset += length_remaining;
+ return foffset;
+ }
+ if(str_length == 0)
+ {
+ proto_tree_add_string(nmas_tree, hfinfo, tvb, offset,
+ 4, "<Not Specified>");
+ return foffset;
+ }
+ for ( i = 0; i < str_length; i++ )
+ {
+ c_char = tvb_get_guint8(tvb, foffset );
+ if (c_char<0x20 || c_char>0x7e)
+ {
+ if (c_char != 0x00)
+ {
+ c_char = 0x2e;
+ buffer[i] = c_char & 0xff;
+ }
+ else
+ {
+ i--;
+ str_length--;
+ }
+ }
+ else
+ {
+ buffer[i] = c_char & 0xff;
+ }
+ foffset++;
+ length_remaining--;
+
+ if(length_remaining==1)
+ {
+ i++;
+ break;
+ }
+ }
+ buffer[i] = '\0';
+
+ if (little) {
+ str_length = tvb_get_letohl(tvb, offset);
+ }
+ else
+ {
+ str_length = tvb_get_ntohl(tvb, offset);
+ }
+ proto_tree_add_string(nmas_tree, hfinfo, tvb, offset+4,
+ str_length, buffer);
+ foffset += align_4(tvb, foffset);
+ return foffset;
+}
+
+void
+dissect_nmas_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, ncp_req_hash_value *request_value)
+{
+ guint8 func, subfunc = 0;
+ guint32 msg_length=0;
+ guint32 foffset;
+ guint32 subverb=0;
+ guint32 attribute=0;
+ guint8 msgverb=0;
+ proto_tree *atree;
+ proto_item *aitem;
+
+ foffset = 6;
+ func = tvb_get_guint8(tvb, foffset);
+ foffset += 1;
+ subfunc = tvb_get_guint8(tvb, foffset);
+ foffset += 1;
+
+ /* Fill in the INFO column. */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMAS");
+ col_add_fstr(pinfo->cinfo, COL_INFO, "C NMAS - %s", match_strval(subfunc, nmas_func_enum));
+ }
+ aitem = proto_tree_add_text(ncp_tree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Packet Type: %s", match_strval(subfunc, nmas_func_enum));
+ atree = proto_item_add_subtree(aitem, ett_nmas);
+ switch (subfunc) {
+ case 1:
+ proto_tree_add_item(atree, hf_ping_version, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ break;
+ case 2:
+ proto_tree_add_item(atree, hf_frag_handle, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ foffset += 4; /* Dont know what this is */
+ proto_tree_add_item(atree, hf_length, tvb, foffset, 4, TRUE);
+ msg_length = tvb_get_letohl(tvb, foffset);
+ foffset += 4;
+ foffset += 12;
+ msg_length -= 16;
+ proto_tree_add_item(atree, hf_subverb, tvb, foffset, 4, TRUE);
+ subverb = tvb_get_letohl(tvb, foffset);
+ if (request_value) {
+ request_value->req_nds_flags=subverb;
+ }
+ foffset += 4;
+ msg_length -= 4;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", match_strval(subverb, nmas_subverb_enum));
+ }
+ switch (subverb) {
+ case 0: /* Fragmented Ping */
+ proto_tree_add_item(atree, hf_ping_version, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ break;
+ case 2: /* Client Put Data */
+ proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, FALSE);
+ foffset += msg_length;
+ break;
+ case 4: /* Client Get Data */
+ case 6: /* Client Get User NDS Credentials */
+ /* No Op */
+ break;
+ case 8: /* Login Store Management */
+ msgverb = tvb_get_guint8(tvb, foffset);
+ if (request_value) {
+ request_value->nds_request_verb=msgverb; /* Use nds_request_verb for passed subverb */
+ }
+ proto_tree_add_item(atree, hf_lsm_verb, tvb, foffset, 1, TRUE);
+ foffset += 4;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", match_strval(msgverb, nmas_lsmverb_enum));
+ }
+ switch (msgverb)
+ {
+ case 1:
+ break;
+ case 2:
+ break;
+ case 4:
+ break;
+ case 5:
+ break;
+ case 6:
+ break;
+ default:
+ break;
+ }
+ break;
+ case 10: /* Writable Object Check */
+ /* The first GUINT32 value is the len of the header? */
+ foffset += 4;
+ /* The next two GUINT32 values are reserved and always 0 */
+ foffset += 8;
+ foffset = nmas_string(tvb, hf_tree, atree, foffset, TRUE);
+ foffset = nmas_string(tvb, hf_user, atree, foffset, TRUE);
+ break;
+ case 1242: /* Message Handler */
+ foffset += 4;
+ proto_tree_add_item(atree, hf_msg_version, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_session_ident, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset += 3;
+ msgverb = tvb_get_guint8(tvb, foffset);
+ if (request_value) {
+ request_value->nds_request_verb=msgverb; /* Use nds_request_verb for passed subverb */
+ }
+ proto_tree_add_item(atree, hf_msg_verb, tvb, foffset, 1, FALSE);
+ foffset += 1;
+ msg_length -= 12;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", match_strval(msgverb, nmas_msgverb_enum));
+ }
+ switch(msgverb)
+ {
+ case 1:
+ msg_length = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(atree, hf_length, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_data, tvb, foffset, msg_length, FALSE);
+ foffset += msg_length;
+ break;
+ case 3:
+ msg_length = tvb_get_ntohl(tvb, foffset);
+ msg_length -= 4;
+ proto_tree_add_item(atree, hf_length, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ while (msg_length > 0)
+ {
+ attribute = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ switch (attribute) {
+ case 1:
+ foffset = nmas_string(tvb, hf_user, atree, foffset, FALSE);
+ break;
+ case 2:
+ foffset = nmas_string(tvb, hf_tree, atree, foffset, FALSE);
+ break;
+ case 4:
+ foffset = nmas_string(tvb, hf_clearence, atree, foffset, FALSE);
+ break;
+ case 11:
+ foffset = nmas_string(tvb, hf_login_sequence, atree, foffset, FALSE);
+ break;
+ default:
+ break;
+ }
+ msg_length -= foffset;
+ if (tvb_get_ntohl(tvb, foffset)==0)
+ {
+ break;
+ }
+ }
+ break;
+ case 5:
+ proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, FALSE);
+ foffset += msg_length;
+ break;
+ case 7:
+ case 9:
+ /* No Op */
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case 3:
+ /* No Op */
+ break;
+ default:
+ break;
+ }
+}
+
+void
+dissect_nmas_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, guint8 func _U_, guint8 subfunc, ncp_req_hash_value *request_value)
+{
+ guint32 foffset=0;
+ guint32 subverb=0;
+ guint8 msgverb=0;
+ guint32 msg_length=0;
+ guint32 return_code=0;
+ proto_tree *atree;
+ proto_item *aitem;
+
+ foffset = 8;
+ if (request_value) {
+ subverb = request_value->req_nds_flags;
+ msgverb = request_value->nds_request_verb;
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMAS");
+ }
+ if (tvb_length_remaining(tvb, foffset)<4) {
+ return;
+ }
+
+ aitem = proto_tree_add_text(ncp_tree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Packet Type: %s", match_strval(subfunc, nmas_func_enum));
+ atree = proto_item_add_subtree(aitem, ett_nmas);
+ switch (subfunc) {
+ case 1:
+ proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ break;
+ case 2:
+ proto_tree_add_item(atree, hf_length, tvb, foffset, 4, TRUE);
+ msg_length = tvb_get_letohl(tvb, foffset);
+ return_code = tvb_get_ntohl(tvb, foffset+msg_length);
+
+ foffset += 4;
+ proto_tree_add_item(atree, hf_frag_handle, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ msg_length -= 4;
+ proto_tree_add_text(atree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Verb: %s", match_strval(subverb, nmas_subverb_enum));
+ switch (subverb) {
+ case 0: /* Fragmented Ping */
+ proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ break;
+ case 2: /* Client Put Data */
+ proto_tree_add_item(atree, hf_squeue_bytes, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_cqueue_bytes, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ break;
+ case 4: /* Client Get Data */
+ proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, TRUE);
+ foffset += msg_length;
+ break;
+ case 6: /* Client Get User NDS Credentials */
+ proto_tree_add_item(atree, hf_num_creds, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_cred_type, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_login_state, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ msg_length -= 12;
+ proto_tree_add_item(atree, hf_enc_cred, tvb, foffset, msg_length, TRUE);
+ foffset += msg_length;
+ break;
+ case 8: /* Login Store Management */
+ proto_tree_add_text(atree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Subverb: %s", match_strval(msgverb, nmas_msgverb_enum));
+ switch(msgverb)
+ {
+ /* The data within these structures is all encrypted. */
+ case 1:
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ proto_tree_add_item(atree, hf_enc_data, tvb, foffset, msg_length, TRUE);
+ foffset += msg_length;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 10: /* Writable Object Check */
+ if (tvb_length_remaining(tvb, foffset) < 8)
+ {
+ return_code = tvb_get_letohl(tvb, foffset);
+ if (match_strval(return_code, nmas_errors_enum)!=NULL)
+ {
+ proto_tree_add_item(atree, hf_return_code, tvb, foffset, 4, FALSE);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R Error - %s", match_strval(return_code, nmas_errors_enum));
+ }
+ }
+ return;
+ }
+ proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, TRUE);
+ foffset += 4;
+ break;
+ case 1242: /* Message Handler */
+ proto_tree_add_text(atree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Subverb: %s", match_strval(msgverb, nmas_msgverb_enum));
+ switch(msgverb)
+ {
+ case 1:
+ msg_length = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(atree, hf_length, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_data, tvb, foffset, msg_length, FALSE);
+ foffset += msg_length;
+ break;
+ case 3:
+ proto_tree_add_item(atree, hf_session_ident, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 5:
+ /* No Op */
+ break;
+ case 7:
+ proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, FALSE);
+ foffset += msg_length;
+ break;
+ case 9:
+ /* No Op */
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (match_strval(return_code, nmas_errors_enum)!=NULL)
+ {
+ proto_tree_add_item(atree, hf_return_code, tvb, foffset-4, 4, FALSE);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R Error - %s", match_strval(return_code, nmas_errors_enum));
+ }
+ }
+ if (return_code == 0 && msgverb!=7) {
+ proto_tree_add_text(atree, tvb, foffset, 4, "Return Code: Success (0x00000000)");
+ }
+ break;
+ case 3:
+ break;
+ default:
+ break;
+ }
+}
+
+void
+proto_register_nmas(void)
+{
+ static hf_register_info hf_nmas[] = {
+ { &hf_func,
+ { "Function", "nmas.func", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Function", HFILL }},
+
+ { &hf_subfunc,
+ { "Subfunction", "nmas.subfunc", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Subfunction", HFILL }},
+
+ { &hf_ping_version,
+ { "Ping Version", "nmas.ping_version", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Ping Version", HFILL }},
+
+ { &hf_ping_flags,
+ { "Flags", "nmas.ping_flags", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Flags", HFILL }},
+
+ { &hf_frag_handle,
+ { "Fragment Handle", "nmas.frag_handle", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Fragment Handle", HFILL }},
+
+ { &hf_length,
+ { "Length", "nmas.length", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Length", HFILL }},
+
+ { &hf_subverb,
+ { "Sub Verb", "nmas.subverb",
+ FT_UINT32, BASE_HEX, VALS(nmas_subverb_enum), 0x0,
+ "Sub Verb", HFILL }},
+
+ { &hf_tree,
+ { "Tree", "nmas.tree",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Tree", HFILL }},
+
+ { &hf_user,
+ { "User", "nmas.user",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "User", HFILL }},
+
+ { &hf_nmas_version,
+ { "NMAS Protocol Version", "nmas.version", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "NMAS Protocol Version", HFILL }},
+
+ { &hf_msg_version,
+ { "Message Version", "nmas.msg_version", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Message Version", HFILL }},
+
+ { &hf_session_ident,
+ { "Session Identifier", "nmas.session_ident", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Session Identifier", HFILL }},
+
+ { &hf_msg_verb,
+ { "Message Verb", "nmas.msg_verb", FT_UINT8, BASE_HEX, VALS(nmas_msgverb_enum), 0x0,
+ "Message Verb", HFILL }},
+
+ { &hf_attribute,
+ { "Attribute Type", "nmas.attribute", FT_UINT32, BASE_DEC, VALS(nmas_attribute_enum), 0x0,
+ "Attribute Type", HFILL }},
+
+ { &hf_clearence,
+ { "Requested Clearence", "nmas.clearence",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Requested Clearence", HFILL }},
+
+ { &hf_login_sequence,
+ { "Requested Login Sequence", "nmas.login_seq",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Requested Login Sequence", HFILL }},
+
+ { &hf_opaque,
+ { "Opaque Data", "nmas.opaque",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Opaque Data", HFILL }},
+
+ { &hf_data,
+ { "Data", "nmas.data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Data", HFILL }},
+
+ { &hf_return_code,
+ { "Return Code", "nmas.return_code", FT_UINT32, BASE_HEX, VALS(nmas_errors_enum), 0x0,
+ "Return Code", HFILL }},
+
+ { &hf_lsm_verb,
+ { "Login Store Message Verb", "nmas.lsm_verb", FT_UINT8, BASE_HEX, VALS(nmas_lsmverb_enum), 0x0,
+ "Login Store Message Verb", HFILL }},
+
+ { &hf_squeue_bytes,
+ { "Server Queue Number of Bytes", "nmas.squeue_bytes", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Server Queue Number of Bytes", HFILL }},
+
+ { &hf_cqueue_bytes,
+ { "Client Queue Number of Bytes", "nmas.cqueue_bytes", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Client Queue Number of Bytes", HFILL }},
+
+ { &hf_num_creds,
+ { "Number of Credentials", "nmas.num_creds", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Credentials", HFILL }},
+
+ { &hf_cred_type,
+ { "Credential Type", "nmas.cred_type", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Credential Type", HFILL }},
+
+ { &hf_login_state,
+ { "Login State", "nmas.login_state", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Login State", HFILL }},
+
+ { &hf_enc_cred,
+ { "Encrypted Credential", "nmas.enc_cred",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Encrypted Credential", HFILL }},
+
+ { &hf_enc_data,
+ { "Encrypted Data", "nmas.enc_data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Encrypted Data", HFILL }},
+
+
+ };
+
+ static gint *ett[] = {
+ &ett_nmas,
+ };
+
+ proto_nmas = proto_register_protocol("Novell Modular Authentication Service", "NMAS", "nmas");
+ proto_register_field_array(proto_nmas, hf_nmas, array_length(hf_nmas));
+ proto_register_subtree_array(ett, array_length(ett));
+}
diff --git a/epan/dissectors/packet-ncp-nmas.h b/epan/dissectors/packet-ncp-nmas.h
new file mode 100644
index 0000000000..cca79a5776
--- /dev/null
+++ b/epan/dissectors/packet-ncp-nmas.h
@@ -0,0 +1,36 @@
+/* packet-ncp-nmas.h
+ * Declarations of routines for Novell Modular Authentication Service
+ * Greg Morris <gmorris@novell.com>
+ * Copyright (c) Novell, Inc. 2002-2004
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2000 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_NCP_NMAS_H__
+#define __PACKET_NCP_NMAS_H__
+
+void
+dissect_nmas_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, ncp_req_hash_value *request_value);
+
+void
+dissect_nmas_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, guint8 func, guint8 subfunc, ncp_req_hash_value *request_value);
+
+#endif
diff --git a/epan/dissectors/packet-ncp.c b/epan/dissectors/packet-ncp.c
new file mode 100644
index 0000000000..01b8729372
--- /dev/null
+++ b/epan/dissectors/packet-ncp.c
@@ -0,0 +1,1052 @@
+/* packet-ncp.c
+ * Routines for NetWare Core Protocol
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ * Modified to allow NCP over TCP/IP decodes by James Coe <jammer@cin.net>
+ * Modified to decode server op-lock, packet signature,
+ * & NDS packets by Greg Morris <gmorris@novell.com>
+ *
+ * Portions Copyright (c) by Gilbert Ramirez 2000-2002
+ * Portions Copyright (c) by James Coe 2000-2002
+ * Portions Copyright (c) Novell, Inc. 2000-2003
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2000 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "packet-ipx.h"
+#include "packet-tcp.h"
+#include "packet-ncp-int.h"
+#include "reassemble.h"
+#include <epan/conversation.h>
+
+int proto_ncp = -1;
+static int hf_ncp_ip_ver = -1;
+static int hf_ncp_ip_length = -1;
+static int hf_ncp_ip_rplybufsize = -1;
+static int hf_ncp_ip_sig = -1;
+static int hf_ncp_ip_packetsig = -1;
+static int hf_ncp_type = -1;
+static int hf_ncp_seq = -1;
+static int hf_ncp_connection = -1;
+static int hf_ncp_task = -1;
+static int hf_ncp_stream_type = -1;
+static int hf_ncp_system_flags = -1;
+static int hf_ncp_system_flags_abt = -1;
+static int hf_ncp_system_flags_eob = -1;
+static int hf_ncp_system_flags_sys = -1;
+static int hf_ncp_system_flags_bsy = -1;
+static int hf_ncp_system_flags_lst = -1;
+static int hf_ncp_src_connection = -1;
+static int hf_ncp_dst_connection = -1;
+static int hf_ncp_packet_seqno = -1;
+static int hf_ncp_delay_time = -1;
+static int hf_ncp_burst_seqno = -1;
+static int hf_ncp_ack_seqno = -1;
+static int hf_ncp_burst_len = -1;
+static int hf_ncp_data_offset = -1;
+static int hf_ncp_data_bytes = -1;
+static int hf_ncp_missing_fraglist_count = -1;
+static int hf_ncp_missing_data_offset = -1;
+static int hf_ncp_missing_data_count = -1;
+static int hf_ncp_oplock_flag = -1;
+static int hf_ncp_oplock_handle = -1;
+static int hf_ncp_completion_code = -1;
+static int hf_ncp_connection_status = -1;
+static int hf_ncp_slot = -1;
+static int hf_ncp_control_code = -1;
+static int hf_ncp_fragment_handle = -1;
+static int hf_lip_echo = -1;
+static int hf_ncp_burst_command = -1;
+static int hf_ncp_burst_file_handle = -1;
+static int hf_ncp_burst_reserved = -1;
+
+gint ett_ncp = -1;
+gint ett_nds = -1;
+gint ett_nds_segments = -1;
+gint ett_nds_segment = -1;
+static gint ett_ncp_system_flags = -1;
+
+
+/* Tables for reassembly of fragments. */
+GHashTable *nds_fragment_table = NULL;
+GHashTable *nds_reassembled_table = NULL;
+dissector_handle_t nds_data_handle;
+
+/* desegmentation of NCP over TCP */
+static gboolean ncp_desegment = TRUE;
+
+static dissector_handle_t data_handle;
+
+#define TCP_PORT_NCP 524
+#define UDP_PORT_NCP 524
+
+#define NCP_RQST_HDR_LENGTH 7
+#define NCP_RPLY_HDR_LENGTH 8
+
+
+/* Hash functions */
+gint ncp_equal (gconstpointer v, gconstpointer v2);
+guint ncp_hash (gconstpointer v);
+
+/* These are the header structures to handle NCP over IP */
+#define NCPIP_RQST 0x446d6454 /* "DmdT" */
+#define NCPIP_RPLY 0x744e6350 /* "tNcP" */
+
+struct ncp_ip_header {
+ guint32 signature;
+ guint32 length;
+};
+
+
+/* This header only appears on NCP over IP request packets */
+struct ncp_ip_rqhdr {
+ guint32 version;
+ guint32 rplybufsize;
+};
+
+static const value_string ncp_ip_signature[] = {
+ { NCPIP_RQST, "Demand Transport (Request)" },
+ { NCPIP_RPLY, "Transport is NCP (Reply)" },
+ { 0, NULL },
+};
+
+static const value_string burst_command[] = {
+ { 0x01000000, "Burst Read" },
+ { 0x02000000, "Burst Write" },
+ { 0, NULL },
+};
+
+/* The information in this module comes from:
+ NetWare LAN Analysis, Second Edition
+ Laura A. Chappell and Dan E. Hakes
+ (c) 1994 Novell, Inc.
+ Novell Press, San Jose.
+ ISBN: 0-7821-1362-1
+
+ And from the ncpfs source code by Volker Lendecke
+
+ And:
+ Programmer's Guide to the NetWare Core Protocol
+ Steve Conner & Diane Conner
+ (c) 1996 by Steve Conner & Diane Conner
+ Published by Annabooks, San Diego, California
+ ISBN: 0-929392-31-0
+
+ And:
+ http:developer.novell.com
+ NCP documentation
+
+*/
+
+/*
+ * Every NCP packet has this common header (except for burst packets).
+ */
+struct ncp_common_header {
+ guint16 type;
+ guint8 sequence;
+ guint8 conn_low;
+ guint8 task;
+ guint8 conn_high; /* type=0x5555 doesn't have this */
+};
+
+
+static value_string ncp_type_vals[] = {
+ { NCP_ALLOCATE_SLOT, "Create a service connection" },
+ { NCP_SERVICE_REQUEST, "Service request" },
+ { NCP_SERVICE_REPLY, "Service reply" },
+ { NCP_WATCHDOG, "Watchdog" },
+ { NCP_DEALLOCATE_SLOT, "Destroy service connection" },
+ { NCP_BROADCAST_SLOT, "Server Broadcast" },
+ { NCP_BURST_MODE_XFER, "Burst mode transfer" },
+ { NCP_POSITIVE_ACK, "Request being processed" },
+ { NCP_LIP_ECHO, "Large Internet Packet Echo" },
+ { 0, NULL }
+};
+
+/* Conversation Struct so we can store whether the conversation is using Packet Signature */
+
+typedef struct {
+ conversation_t *conversation;
+} mncp_rhash_key;
+
+typedef struct {
+ gboolean packet_signature;
+} mncp_rhash_value;
+
+static GHashTable *mncp_rhash = NULL;
+static GMemChunk *mncp_rhash_keys = NULL;
+static GMemChunk *mncp_rhash_values = NULL;
+
+/* Hash Functions */
+gint
+mncp_equal(gconstpointer v, gconstpointer v2)
+{
+ const mncp_rhash_key *val1 = (const mncp_rhash_key*)v;
+ const mncp_rhash_key *val2 = (const mncp_rhash_key*)v2;
+
+ if (val1->conversation == val2->conversation ) {
+ return 1;
+ }
+ return 0;
+}
+
+guint
+mncp_hash(gconstpointer v)
+{
+ const mncp_rhash_key *mncp_key = (const mncp_rhash_key*)v;
+ return GPOINTER_TO_UINT(mncp_key->conversation);
+}
+
+/* Initializes the hash table and the mem_chunk area each time a new
+ * file is loaded or re-loaded in ethereal */
+static void
+mncp_init_protocol(void)
+{
+ if (mncp_rhash)
+ g_hash_table_destroy(mncp_rhash);
+ if (mncp_rhash_keys)
+ g_mem_chunk_destroy(mncp_rhash_keys);
+ if (mncp_rhash_values)
+ g_mem_chunk_destroy(mncp_rhash_values);
+
+ mncp_rhash = g_hash_table_new(mncp_hash, mncp_equal);
+ mncp_rhash_keys = g_mem_chunk_new("mncp_rhash_keys",
+ sizeof(mncp_rhash_key),
+ 200 * sizeof(mncp_rhash_key),
+ G_ALLOC_ONLY);
+ mncp_rhash_values = g_mem_chunk_new("mncp_rhash_values",
+ sizeof(mncp_rhash_value),
+ 200 * sizeof(mncp_rhash_value),
+ G_ALLOC_ONLY);
+}
+
+/* After the sequential run, we don't need the ncp_request hash and keys
+ * anymore; the lookups have already been done and the vital info
+ * saved in the reply-packets' private_data in the frame_data struct. */
+static void
+mncp_postseq_cleanup(void)
+{
+}
+
+mncp_rhash_value*
+mncp_hash_insert(conversation_t *conversation)
+{
+ mncp_rhash_key *key;
+ mncp_rhash_value *value;
+
+ /* Now remember the request, so we can find it if we later
+ a reply to it. */
+ key = g_mem_chunk_alloc(mncp_rhash_keys);
+ key->conversation = conversation;
+
+ value = g_mem_chunk_alloc(mncp_rhash_values);
+ value->packet_signature = FALSE;
+
+ g_hash_table_insert(mncp_rhash, key, value);
+
+ return value;
+}
+
+/* Returns the ncp_rec*, or NULL if not found. */
+mncp_rhash_value*
+mncp_hash_lookup(conversation_t *conversation)
+{
+ mncp_rhash_key key;
+
+ key.conversation = conversation;
+
+ return g_hash_table_lookup(mncp_rhash, &key);
+}
+
+/*
+ * Burst packet system flags.
+ */
+#define ABT 0x04 /* Abort request */
+#define BSY 0x08 /* Server Busy */
+#define EOB 0x10 /* End of burst */
+#define LST 0x40 /* Include Fragment List */
+#define SYS 0x80 /* System packet */
+
+static void
+dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean is_tcp)
+{
+ proto_tree *ncp_tree = NULL;
+ proto_item *ti;
+ struct ncp_ip_header ncpiph;
+ struct ncp_ip_rqhdr ncpiphrq;
+ struct ncp_common_header header;
+ guint16 nw_connection, ncp_burst_seqno, ncp_ack_seqno;
+ guint16 flags = 0;
+ char flags_str[1+3+1+3+1+3+1+1];
+ char *sep;
+ proto_tree *flags_tree = NULL;
+ guint16 data_len = 0;
+ guint16 missing_fraglist_count = 0;
+ int hdr_offset = 0;
+ int commhdr;
+ int offset;
+ gint length_remaining;
+ tvbuff_t *next_tvb;
+ guint32 testvar = 0, ncp_burst_command, burst_len, burst_off, burst_file;
+ guint8 subfunction;
+ mncp_rhash_value *request_value = NULL;
+ conversation_t *conversation;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NCP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ hdr_offset = 0;
+
+ if (is_tcp)
+ {
+ if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY)
+ hdr_offset += 1;
+ ncpiph.signature = tvb_get_ntohl(tvb, hdr_offset);
+ ncpiph.length = tvb_get_ntohl(tvb, hdr_offset+4);
+ hdr_offset += 8;
+ if (ncpiph.signature == NCPIP_RQST)
+ {
+ ncpiphrq.version = tvb_get_ntohl(tvb, hdr_offset);
+ hdr_offset += 4;
+ ncpiphrq.rplybufsize = tvb_get_ntohl(tvb, hdr_offset);
+ hdr_offset += 4;
+ }
+ /* Ok, we need to track the conversation so that we can determine
+ * if packet signature is occuring for this connection. We will
+ * store the conversation the first time and that state of packet
+ * signature will be stored later in our logic. This way when we
+ * dissect reply packets we will be able to determine if we need
+ * to also dissect with a signature.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
+ if (ncpiph.length & 0x80000000 || ncpiph.signature == NCPIP_RPLY)
+ {
+ /* First time through we will store packet signature state */
+ if (!pinfo->fd->flags.visited)
+ {
+ if (conversation != NULL)
+ {
+ /* find the record telling us the request made that caused
+ this reply */
+ request_value = mncp_hash_lookup(conversation);
+ /* if for some reason we have no conversation in our hash, create one */
+ if (request_value==NULL)
+ {
+ request_value = mncp_hash_insert(conversation);
+ }
+ }
+ else
+ {
+ /* It's not part of any conversation - create a new one. */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
+ request_value = mncp_hash_insert(conversation);
+ }
+ /* If this is a request packet then we know that we have a signature */
+ if (ncpiph.signature == NCPIP_RQST)
+ {
+ hdr_offset += 8;
+ ncpiph.length &= 0x7fffffff;
+ request_value->packet_signature=TRUE;
+ }
+ else
+ {
+ /* Now on reply packets we have to use the state of the original request packet */
+ /* So look up the request value and check the state of packet signature */
+ request_value = mncp_hash_lookup(conversation);
+ if (request_value->packet_signature==TRUE)
+ {
+ hdr_offset += 8;
+ ncpiph.length &= 0x7fffffff;
+ request_value->packet_signature=TRUE;
+ }
+ else
+ {
+ request_value->packet_signature=FALSE;
+ }
+ }
+ }
+ else
+ {
+ /* Get request value data */
+ request_value = mncp_hash_lookup(conversation);
+ if (request_value->packet_signature==TRUE)
+ {
+ hdr_offset += 8;
+ ncpiph.length &= 0x7fffffff;
+ }
+ }
+ }
+ else
+ {
+ if (!pinfo->fd->flags.visited)
+ {
+ if (conversation != NULL)
+ {
+ /* find the record telling us the request made that caused
+ this reply */
+ request_value = mncp_hash_lookup(conversation);
+ /* if for some reason we have no conversation in our hash, create one */
+ if (request_value==NULL)
+ {
+ request_value = mncp_hash_insert(conversation);
+ }
+ }
+ else
+ {
+ /* It's not part of any conversation - create a new one. */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
+ request_value = mncp_hash_insert(conversation);
+ }
+ /* find the record telling us the request made that caused
+ this reply */
+ request_value->packet_signature=FALSE;
+ }
+ else
+ {
+ request_value = mncp_hash_lookup(conversation);
+ }
+ }
+ }
+
+ /* Record the offset where the NCP common header starts */
+ commhdr = hdr_offset;
+
+ header.type = tvb_get_ntohs(tvb, commhdr);
+ header.sequence = tvb_get_guint8(tvb, commhdr+2);
+ header.conn_low = tvb_get_guint8(tvb, commhdr+3);
+ header.conn_high = tvb_get_guint8(tvb, commhdr+5);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s",
+ val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));
+
+ }
+
+ nw_connection = (header.conn_high << 16) + header.conn_low;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, FALSE);
+ ncp_tree = proto_item_add_subtree(ti, ett_ncp);
+
+ if (is_tcp) {
+ proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, 0, 4, ncpiph.signature);
+ proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, 4, 4, ncpiph.length);
+ if (ncpiph.signature == NCPIP_RQST) {
+ proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, 8, 4, ncpiphrq.version);
+ proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, 12, 4, ncpiphrq.rplybufsize);
+ if (request_value->packet_signature==TRUE)
+ proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, 16, 8, FALSE);
+ } else {
+ if (request_value->packet_signature==TRUE)
+ proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, 8, 8, FALSE);
+ }
+ }
+ proto_tree_add_uint(ncp_tree, hf_ncp_type, tvb, commhdr + 0, 2, header.type);
+ }
+
+
+ /*
+ * Process the packet-type-specific header.
+ */
+ switch (header.type) {
+
+ case NCP_BROADCAST_SLOT: /* Server Broadcast */
+ proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
+ proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
+ proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_oplock_handle, tvb, commhdr + 10, 4, FALSE);
+ break;
+
+ case NCP_LIP_ECHO: /* Lip Echo Packet */
+ proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr, 13, FALSE);
+ break;
+
+ case NCP_BURST_MODE_XFER: /* Packet Burst Packet */
+ /*
+ * XXX - we should keep track of whether there's a burst
+ * outstanding on a connection and, if not, treat the
+ * beginning of the data as a burst header.
+ *
+ * The burst header contains:
+ *
+ * 4 bytes of little-endian function number:
+ * 1 = read, 2 = write;
+ *
+ * 4 bytes of file handle;
+ *
+ * 8 reserved bytes;
+ *
+ * 4 bytes of big-endian file offset;
+ *
+ * 4 bytes of big-endian byte count.
+ *
+ * The data follows for a burst write operation.
+ *
+ * The first packet of a burst read reply contains:
+ *
+ * 4 bytes of little-endian result code:
+ * 0: No error
+ * 1: Initial error
+ * 2: I/O error
+ * 3: No data read;
+ *
+ * 4 bytes of returned byte count (big-endian?).
+ *
+ * The data follows.
+ *
+ * Each burst of a write request is responded to with a
+ * burst packet with a 2-byte little-endian result code:
+ *
+ * 0: Write successful
+ * 4: Write error
+ */
+ flags = tvb_get_guint8(tvb, commhdr + 2);
+ strcpy(flags_str, "");
+ sep = " (";
+ if (flags & ABT) {
+ strcat(flags_str, sep);
+ strcat(flags_str, "ABT");
+ sep = ",";
+ }
+ if (flags & BSY) {
+ strcat(flags_str, sep);
+ strcat(flags_str, "BSY");
+ sep = ",";
+ }
+ if (flags & EOB) {
+ strcat(flags_str, sep);
+ strcat(flags_str, "EOB");
+ sep = ",";
+ }
+ if (flags & LST) {
+ strcat(flags_str, sep);
+ strcat(flags_str, "LST");
+ sep = ",";
+ }
+ if (flags & SYS) {
+ strcat(flags_str, sep);
+ strcat(flags_str, "SYS");
+ }
+ if (flags_str[0] != '\0')
+ strcat(flags_str, ")");
+ ti = proto_tree_add_uint_format(ncp_tree, hf_ncp_system_flags,
+ tvb, commhdr + 2, 1, flags, "Flags: 0x%04x%s", flags,
+ flags_str);
+ flags_tree = proto_item_add_subtree(ti, ett_ncp_system_flags);
+ proto_tree_add_item(flags_tree, hf_ncp_system_flags_abt,
+ tvb, commhdr + 2, 1, FALSE);
+ proto_tree_add_item(flags_tree, hf_ncp_system_flags_bsy,
+ tvb, commhdr + 2, 1, FALSE);
+ proto_tree_add_item(flags_tree, hf_ncp_system_flags_eob,
+ tvb, commhdr + 2, 1, FALSE);
+ proto_tree_add_item(flags_tree, hf_ncp_system_flags_lst,
+ tvb, commhdr + 2, 1, FALSE);
+ proto_tree_add_item(flags_tree, hf_ncp_system_flags_sys,
+ tvb, commhdr + 2, 1, FALSE);
+
+ proto_tree_add_item(ncp_tree, hf_ncp_stream_type,
+ tvb, commhdr + 3, 1, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_src_connection,
+ tvb, commhdr + 4, 4, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_dst_connection,
+ tvb, commhdr + 8, 4, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_packet_seqno,
+ tvb, commhdr + 12, 4, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_delay_time,
+ tvb, commhdr + 16, 4, FALSE);
+ ncp_burst_seqno = tvb_get_ntohs(tvb, commhdr+20);
+ proto_tree_add_item(ncp_tree, hf_ncp_burst_seqno,
+ tvb, commhdr + 20, 2, FALSE);
+ ncp_ack_seqno = tvb_get_ntohs(tvb, commhdr+22);
+ proto_tree_add_item(ncp_tree, hf_ncp_ack_seqno,
+ tvb, commhdr + 22, 2, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_burst_len,
+ tvb, commhdr + 24, 4, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_data_offset,
+ tvb, commhdr + 28, 4, FALSE);
+ data_len = tvb_get_ntohs(tvb, commhdr + 32);
+ proto_tree_add_uint(ncp_tree, hf_ncp_data_bytes,
+ tvb, commhdr + 32, 2, data_len);
+ missing_fraglist_count = tvb_get_ntohs(tvb, commhdr + 34);
+ proto_tree_add_item(ncp_tree, hf_ncp_missing_fraglist_count,
+ tvb, commhdr + 34, 2, FALSE);
+ if (ncp_burst_seqno==ncp_ack_seqno)
+ {
+ ncp_burst_command = tvb_get_ntohl(tvb, commhdr+36);
+ proto_tree_add_item(ncp_tree, hf_ncp_burst_command,
+ tvb, commhdr + 36, 4, FALSE);
+ burst_file = tvb_get_ntohl(tvb, commhdr+40);
+ proto_tree_add_item(ncp_tree, hf_ncp_burst_file_handle,
+ tvb, commhdr + 40, 4, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_burst_reserved,
+ tvb, commhdr + 44, 8, FALSE);
+ burst_off = tvb_get_ntohl(tvb, commhdr+52);
+ proto_tree_add_item(ncp_tree, hf_ncp_data_offset,
+ tvb, commhdr + 52, 4, FALSE);
+ burst_len = tvb_get_ntohl(tvb, commhdr+56);
+ proto_tree_add_item(ncp_tree, hf_ncp_burst_len,
+ tvb, commhdr + 56, 4, FALSE);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, match_strval(ncp_burst_command, burst_command));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %d bytes starting at offset %d in file 0x%08x", burst_len, burst_off, burst_file);
+ }
+ return;
+ }
+ break;
+
+ case NCP_ALLOCATE_SLOT: /* Allocate Slot Request */
+ length_remaining = tvb_length_remaining(tvb, commhdr + 4);
+ if (length_remaining > 4) {
+ testvar = tvb_get_ntohl(tvb, commhdr+4);
+ if (testvar == 0x4c495020) {
+ proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr+4, 13, FALSE);
+ break;
+ }
+ }
+ /* otherwise fall through */
+
+ case NCP_POSITIVE_ACK: /* Positive Acknowledgement */
+ case NCP_SERVICE_REQUEST: /* Server NCP Request */
+ case NCP_SERVICE_REPLY: /* Server NCP Reply */
+ case NCP_WATCHDOG: /* Watchdog Packet */
+ case NCP_DEALLOCATE_SLOT: /* Deallocate Slot Request */
+ default:
+ proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
+ proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
+ proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, FALSE);
+ break;
+ }
+
+ /*
+ * Process the packet body.
+ */
+ switch (header.type) {
+
+ case NCP_ALLOCATE_SLOT: /* Allocate Slot Request */
+ length_remaining = tvb_length_remaining(tvb, commhdr + 4);
+ if (length_remaining > 4) {
+ testvar = tvb_get_ntohl(tvb, commhdr+4);
+ if (testvar == 0x4c495020) {
+ proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
+ "Lip Echo Packet");
+ /*break;*/
+ }
+ }
+
+ case NCP_SERVICE_REQUEST: /* Server NCP Request */
+ case NCP_DEALLOCATE_SLOT: /* Deallocate Slot Request */
+ case NCP_BROADCAST_SLOT: /* Server Broadcast Packet */
+ next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
+ if (tvb_get_guint8(tvb, commhdr+6) == 0x68) {
+ subfunction = tvb_get_guint8(tvb, commhdr+7);
+ switch (subfunction) {
+
+ case 0x02: /* NDS Frag Packet to decode */
+ dissect_nds_request(next_tvb, pinfo,
+ nw_connection, header.sequence,
+ header.type, ncp_tree);
+ break;
+
+ case 0x01: /* NDS Ping */
+ dissect_ping_req(next_tvb, pinfo,
+ nw_connection, header.sequence,
+ header.type, ncp_tree);
+ break;
+
+ default:
+ dissect_ncp_request(next_tvb, pinfo,
+ nw_connection, header.sequence,
+ header.type, ncp_tree);
+ break;
+ }
+ } else {
+ dissect_ncp_request(next_tvb, pinfo, nw_connection,
+ header.sequence, header.type, ncp_tree);
+ }
+ break;
+
+ case NCP_SERVICE_REPLY: /* Server NCP Reply */
+ next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
+ nds_defrag(next_tvb, pinfo, nw_connection, header.sequence,
+ header.type, ncp_tree);
+ break;
+
+ case NCP_POSITIVE_ACK: /* Positive Acknowledgement */
+ /*
+ * XXX - this used to call "nds_defrag()", which would
+ * clear out "frags". Was that the right thing to
+ * do?
+ */
+ next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
+ dissect_ncp_reply(next_tvb, pinfo, nw_connection,
+ header.sequence, header.type, ncp_tree);
+ break;
+
+ case NCP_WATCHDOG: /* Watchdog Packet */
+ /*
+ * XXX - should the completion code be interpreted as
+ * it is in "packet-ncp2222.inc"? If so, this
+ * packet should be handled by "dissect_ncp_reply()".
+ */
+ proto_tree_add_item(ncp_tree, hf_ncp_completion_code,
+ tvb, commhdr + 6, 1, TRUE);
+ proto_tree_add_item(ncp_tree, hf_ncp_connection_status,
+ tvb, commhdr + 7, 1, TRUE);
+ proto_tree_add_item(ncp_tree, hf_ncp_slot,
+ tvb, commhdr + 8, 1, TRUE);
+ proto_tree_add_item(ncp_tree, hf_ncp_control_code,
+ tvb, commhdr + 9, 1, TRUE);
+ /*
+ * Display the rest of the packet as data.
+ */
+ if (tvb_offset_exists(tvb, commhdr + 10)) {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, commhdr + 10, -1, -1),
+ pinfo, ncp_tree);
+ }
+ break;
+
+ case NCP_BURST_MODE_XFER: /* Packet Burst Packet */
+ if (flags & SYS) {
+ /*
+ * System packet; show missing fragments if there
+ * are any.
+ */
+ offset = commhdr + 36;
+ while (missing_fraglist_count != 0) {
+ proto_tree_add_item(ncp_tree, hf_ncp_missing_data_offset,
+ tvb, offset, 4, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_missing_data_count,
+ tvb, offset, 2, FALSE);
+ missing_fraglist_count--;
+ }
+ } else {
+ /*
+ * XXX - do this by using -1 and -1 as the length
+ * arguments to "tvb_new_subset()" and then calling
+ * "tvb_set_reported_length()"? That'll throw an
+ * exception if "data_len" goes past the reported
+ * length of the packet, but that's arguably a
+ * feature in this case.
+ */
+ length_remaining = tvb_length_remaining(tvb, commhdr + 36);
+ if (length_remaining > data_len)
+ length_remaining = data_len;
+ if (data_len != 0) {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, commhdr + 36,
+ length_remaining, data_len),
+ pinfo, ncp_tree);
+ }
+ }
+ break;
+
+ case NCP_LIP_ECHO: /* LIP Echo Packet */
+ proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
+ "Lip Echo Packet");
+ break;
+
+ default:
+ if (tree) {
+ proto_tree_add_text(ncp_tree, tvb, commhdr + 6, -1,
+ "%s packets not supported yet",
+ val_to_str(header.type, ncp_type_vals,
+ "Unknown type (0x%04x)"));
+ }
+ break;
+ }
+}
+
+static void
+dissect_ncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_ncp_common(tvb, pinfo, tree, FALSE);
+}
+
+static guint
+get_ncp_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint32 signature;
+
+ /*
+ * Check the NCP-over-TCP header signature, to make sure it's there.
+ * If it's not there, we cannot trust the next 4 bytes to be a
+ * packet length+"has signature" flag, so we just say the length is
+ * "what remains in the packet".
+ */
+ /*if (tvb_get_guint8(tvb, offset)==0xff)
+ {
+ offset += 1;
+ }*/
+ signature = tvb_get_ntohl(tvb, offset);
+ if (signature != NCPIP_RQST && signature != NCPIP_RPLY)
+ return tvb_length_remaining(tvb, offset);
+
+ /*
+ * Get the length of the NCP-over-TCP packet. Strip off the "has
+ * signature" flag.
+ */
+
+ return tvb_get_ntohl(tvb, offset + 4) & 0x7fffffff;
+}
+
+static void
+dissect_ncp_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_ncp_common(tvb, pinfo, tree, TRUE);
+}
+
+static void
+dissect_ncp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, ncp_desegment, 8, get_ncp_pdu_len,
+ dissect_ncp_tcp_pdu);
+}
+
+void
+proto_register_ncp(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_ncp_ip_sig,
+ { "NCP over IP signature", "ncp.ip.signature",
+ FT_UINT32, BASE_HEX, VALS(ncp_ip_signature), 0x0,
+ "", HFILL }},
+ { &hf_ncp_ip_length,
+ { "NCP over IP length", "ncp.ip.length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_ip_ver,
+ { "NCP over IP Version", "ncp.ip.version",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_ip_rplybufsize,
+ { "NCP over IP Reply Buffer Size", "ncp.ip.replybufsize",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_ip_packetsig,
+ { "NCP over IP Packet Signature", "ncp.ip.packetsig",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_type,
+ { "Type", "ncp.type",
+ FT_UINT16, BASE_HEX, VALS(ncp_type_vals), 0x0,
+ "NCP message type", HFILL }},
+ { &hf_ncp_seq,
+ { "Sequence Number", "ncp.seq",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_connection,
+ { "Connection Number", "ncp.connection",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_task,
+ { "Task Number", "ncp.task",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_oplock_flag,
+ { "Oplock Flag", "ncp.oplock_flag",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_oplock_handle,
+ { "File Handle", "ncp.oplock_handle",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_stream_type,
+ { "Stream Type", "ncp.stream_type",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Type of burst", HFILL }},
+ { &hf_ncp_system_flags,
+ { "System Flags", "ncp.system_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_system_flags_abt,
+ { "ABT", "ncp.system_flags.abt",
+ FT_BOOLEAN, 8, NULL, ABT,
+ "Is this an abort request?", HFILL }},
+ { &hf_ncp_system_flags_eob,
+ { "EOB", "ncp.system_flags.eob",
+ FT_BOOLEAN, 8, NULL, EOB,
+ "Is this the last packet of the burst?", HFILL }},
+ { &hf_ncp_system_flags_sys,
+ { "SYS", "ncp.system_flags.sys",
+ FT_BOOLEAN, 8, NULL, SYS,
+ "Is this a system packet?", HFILL }},
+ { &hf_ncp_system_flags_bsy,
+ { "BSY", "ncp.system_flags.bsy",
+ FT_BOOLEAN, 8, NULL, BSY,
+ "Is the server busy?", HFILL }},
+ { &hf_ncp_system_flags_lst,
+ { "LST", "ncp.system_flags.lst",
+ FT_BOOLEAN, 8, NULL, LST,
+ "Return Fragment List?", HFILL }},
+ { &hf_ncp_src_connection,
+ { "Source Connection ID", "ncp.src_connection",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The workstation's connection identification number", HFILL }},
+ { &hf_ncp_dst_connection,
+ { "Destination Connection ID", "ncp.dst_connection",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The server's connection identification number", HFILL }},
+ { &hf_ncp_packet_seqno,
+ { "Packet Sequence Number", "ncp.packet_seqno",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sequence number of this packet in a burst", HFILL }},
+ { &hf_ncp_delay_time,
+ { "Delay Time", "ncp.delay_time", /* in 100 us increments */
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Delay time between consecutive packet sends (100 us increments)", HFILL }},
+ { &hf_ncp_burst_seqno,
+ { "Burst Sequence Number", "ncp.burst_seqno",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Sequence number of this packet in the burst", HFILL }},
+ { &hf_ncp_ack_seqno,
+ { "ACK Sequence Number", "ncp.ack_seqno",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Next expected burst sequence number", HFILL }},
+ { &hf_ncp_burst_len,
+ { "Burst Length", "ncp.burst_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Total length of data in this burst", HFILL }},
+ { &hf_ncp_data_offset,
+ { "Data Offset", "ncp.data_offset",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Offset of this packet in the burst", HFILL }},
+ { &hf_ncp_data_bytes,
+ { "Data Bytes", "ncp.data_bytes",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of data bytes in this packet", HFILL }},
+ { &hf_ncp_missing_fraglist_count,
+ { "Missing Fragment List Count", "ncp.missing_fraglist_count",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of missing fragments reported", HFILL }},
+ { &hf_ncp_missing_data_offset,
+ { "Missing Data Offset", "ncp.missing_data_offset",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Offset of beginning of missing data", HFILL }},
+ { &hf_ncp_missing_data_count,
+ { "Missing Data Count", "ncp.missing_data_count",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Number of bytes of missing data", HFILL }},
+ { &hf_ncp_completion_code,
+ { "Completion Code", "ncp.completion_code",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_connection_status,
+ { "Connection Status", "ncp.connection_status",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_slot,
+ { "Slot", "ncp.slot",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_control_code,
+ { "Control Code", "ncp.control_code",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_fragment_handle,
+ { "Fragment Handle", "ncp.fragger_hndl",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_lip_echo,
+ { "Large Internet Packet Echo", "ncp.lip_echo",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ { &hf_ncp_burst_command,
+ { "Burst Command", "ncp.burst_command",
+ FT_UINT32, BASE_HEX, VALS(burst_command), 0x0,
+ "Packet Burst Command", HFILL }},
+ { &hf_ncp_burst_file_handle,
+ { "Burst File Handle", "ncp.file_handle",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Packet Burst File Handle", HFILL }},
+ { &hf_ncp_burst_reserved,
+ { "Reserved", "ncp.burst_reserved",
+ FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_ncp,
+ &ett_ncp_system_flags,
+ &ett_nds,
+ &ett_nds_segments,
+ &ett_nds_segment,
+ };
+ module_t *ncp_module;
+
+ proto_ncp = proto_register_protocol("NetWare Core Protocol", "NCP", "ncp");
+ proto_register_field_array(proto_ncp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ncp_module = prefs_register_protocol(proto_ncp, NULL);
+ prefs_register_obsolete_preference(ncp_module, "initial_hash_size");
+ prefs_register_bool_preference(ncp_module, "desegment",
+ "Desegment all NCP-over-TCP messages spanning multiple segments",
+ "Whether the NCP dissector should desegment all messages spanning multiple TCP segments",
+ &ncp_desegment);
+ prefs_register_bool_preference(ncp_module, "defragment_nds",
+ "Defragment all NDS messages spanning multiple packets",
+ "Whether the NCP dissector should defragment all NDS messages spanning multiple packets",
+ &nds_defragment);
+ register_init_routine(&mncp_init_protocol);
+ register_postseq_cleanup_routine(&mncp_postseq_cleanup);
+}
+
+void
+proto_reg_handoff_ncp(void)
+{
+ dissector_handle_t ncp_handle;
+ dissector_handle_t ncp_tcp_handle;
+
+ ncp_handle = create_dissector_handle(dissect_ncp, proto_ncp);
+ ncp_tcp_handle = create_dissector_handle(dissect_ncp_tcp, proto_ncp);
+ dissector_add("tcp.port", TCP_PORT_NCP, ncp_tcp_handle);
+ dissector_add("udp.port", UDP_PORT_NCP, ncp_handle);
+ dissector_add("ipx.packet_type", IPX_PACKET_TYPE_NCP, ncp_handle);
+ dissector_add("ipx.socket", IPX_SOCKET_NCP, ncp_handle);
+
+ data_handle = find_dissector("data");
+}
+
+
diff --git a/epan/dissectors/packet-ncp2222.inc b/epan/dissectors/packet-ncp2222.inc
new file mode 100644
index 0000000000..52331bedba
--- /dev/null
+++ b/epan/dissectors/packet-ncp2222.inc
@@ -0,0 +1,8650 @@
+/* packet-ncp2222.inc
+ *
+ * Routines for NetWare Core Protocol. This C code gets #include'd
+ * into packet-ncp2222.c, which is generated from ncp2222.py. It's
+ * #include'd instead of being in a separate compilation unit so
+ * that all the data tables in packet-ncp2222.c can remain static.
+ *
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ * Modified to decode NDS packets by Greg Morris <gmorris@novell.com>
+ *
+ * Portions Copyright (c) Gilbert Ramirez 2000-2002
+ * Portions Copyright (c) Novell, Inc. 2000-2003
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2000 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define NCP_PACKET_INIT_COUNT 200
+#define PROTO_LENGTH_UNTIL_END -1
+
+gboolean nds_defragment = TRUE;
+
+typedef struct {
+ guint32 nds_frag_verb;
+ guint32 nds_frag_version;
+ guint32 nds_frag_flags;
+ guint32 nds_length;
+ guint32 nds_frag;
+ gboolean nds_fragmented;
+} frag_info;
+
+frag_info frags[100];
+
+const fragment_items nds_frag_items = {
+ &ett_nds_segment,
+ &ett_nds_segments,
+ &hf_nds_segments,
+ &hf_nds_segment,
+ &hf_nds_segment_overlap,
+ &hf_nds_segment_overlap_conflict,
+ &hf_nds_segment_multiple_tails,
+ &hf_nds_segment_too_long_segment,
+ &hf_nds_segment_error,
+ NULL,
+ "segments"
+};
+
+static const value_string nds_tags[] = {
+ { 0x00000000, "No Such Entry" },
+ { 0x00000001, "Local Entry" },
+ { 0x00000002, "Remote Entry" },
+ { 0x00000003, "Alias Entry" },
+ { 0x00000004, "Referral Information" },
+ { 0x00000006, "Entry and Referrals" },
+ { 0, NULL }
+};
+
+static const value_string nds_info_type[] = {
+ { 0x00000000, "Attribute Names Only / " },
+ { 0x00000001, "Attribute Name & Value / " },
+ { 0x00000002, "Effective Privileges / " },
+ { 0x00000003, "Value Information / " },
+ { 0x00000004, "Abbreviated Value / " },
+ { 0, NULL }
+};
+
+static const value_string nds_kind_of_changes[] = {
+ { 0x00000000, "Add Attribute" },
+ { 0x00000001, "Remove Attribute" },
+ { 0x00000002, "Add Value" },
+ { 0x00000003, "Remove Value" },
+ { 0x00000004, "Add Additional Value" },
+ { 0x00000005, "Overwrite Value" },
+ { 0x00000006, "Clear Attribute" },
+ { 0x00000007, "Clear Value" },
+ { 0, NULL }
+};
+
+static const value_string es_type[] = {
+ { 0x00000000, "No type is specified" },
+ { 0x00000001, "Unicode string" },
+ { 0x00000002, "Partial name" },
+ { 0x00000003, "Referrals" },
+ { 0x00000004, "Tuned name" },
+ { 0x00000005, "GUID attribute" },
+ { 0x00000006, "Local entry ID" },
+ { 0x00000007, "Number of defined entry specifiers" },
+ { 0, NULL }
+};
+
+static const value_string nds_protocol_type[] = {
+ { 0x00000000, "(IPX Protocol)" },
+ { 0x00000001, "(IP Protocol)" },
+ { 0x00000002, "(SDLC Protocol)" },
+ { 0x00000003, "(TokenRing on Ethernet Protocol)" },
+ { 0x00000004, "(OSI Protocol)" },
+ { 0x00000005, "(AppleTalk Protocol)" },
+ { 0x00000006, "(NetBEUI Protocol)" },
+ { 0x00000007, "(Socket Address Protocol)" },
+ { 0x00000008, "(UDP Protocol)" },
+ { 0x00000009, "(TCP Protocol)" },
+ { 0x0000000a, "(UDP v6 Protocol)" },
+ { 0x0000000b, "(TCP v6 Protocol)" },
+ { 0x0000000c, "(Internal Protocol)" },
+ { 0x0000000d, "(URL Protocol)" },
+ { 0, NULL }
+};
+
+
+static const value_string nds_syntax[] = {
+ { 0x00000000, "Unknown Syntax" },
+ { 0x00000001, "Distinguished Name" },
+ { 0x00000002, "Case Sensitive Unicode String" },
+ { 0x00000003, "Non Case Sensitive Unicode String" },
+ { 0x00000004, "Printable String" },
+ { 0x00000005, "Numeric String" },
+ { 0x00000006, "Case Insensitive List" },
+ { 0x00000007, "Boolean" },
+ { 0x00000008, "Signed Integer" },
+ { 0x00000009, "Binary String" },
+ { 0x0000000a, "Telephone Number" },
+ { 0x0000000b, "Fax Number" },
+ { 0x0000000c, "Network Address" },
+ { 0x0000000d, "Binary String List" },
+ { 0x0000000e, "Email Address" },
+ { 0x0000000f, "File System Path" },
+ { 0x00000010, "Replica Pointer" },
+ { 0x00000011, "Object ACL" },
+ { 0x00000012, "Postal Address" },
+ { 0x00000013, "Time Stamp" },
+ { 0x00000014, "Class Name" },
+ { 0x00000015, "Stream" },
+ { 0x00000016, "Counter" },
+ { 0x00000017, "Back Link" },
+ { 0x00000018, "Time" },
+ { 0x00000019, "Typed Name" },
+ { 0x0000001a, "Hold" },
+ { 0x0000001b, "Interval" },
+ { 0, NULL }
+};
+
+static const value_string name_space_type[] = {
+ { 0x00000000, "DOS Name Space" },
+ { 0x00000001, "MAC Name Space" },
+ { 0x00000002, "NFS Name Space" },
+ { 0x00000003, "FTAM Name Space" },
+ { 0x00000004, "OS/2, Long Name Space" },
+ { 0, NULL }
+};
+
+
+static const value_string nds_replica_state[] = {
+ { 0x0000, "On" },
+ { 0x0001, "New" },
+ { 0x0002, "Dying" },
+ { 0x0003, "Locked" },
+ { 0x0004, "Create Master State 0" },
+ { 0x0005, "Create Master State 1" },
+ { 0x0006, "Transition On" },
+ { 0x0007, "Dead Replica" },
+ { 0x0008, "Begin Add" },
+ { 0x000b, "Master Start" },
+ { 0x000c, "Master Done" },
+ { 0x0017, "Federated" },
+ { 0x0030, "Split State 0" },
+ { 0x0031, "Split State 1" },
+ { 0x0040, "Join State 0" },
+ { 0x0041, "Join State 1" },
+ { 0x0042, "Join State 2" },
+ { 0x0050, "Move Subtree State 0" },
+ { 0x0051, "Move Subtree State 1" },
+ { 0, NULL }
+};
+
+static const value_string nds_replica_type[] = {
+ { 0x0000, "Master" },
+ { 0x0001, "Secondary" },
+ { 0x0002, "Read Only" },
+ { 0x0003, "Sub Ref" },
+ { 0, NULL }
+};
+
+static const value_string class_def_type[] = {
+ { 0x0000, "Return Class Name" },
+ { 0x0001, "Return Class Name, Flag, and Definition" },
+ { 0x0002, "Return Class Name, Flag, Definition, and Super Class" },
+ { 0x0003, "Return Class Name, Flag, and ASN.1 identifier" },
+ { 0x0004, "Return Class Name, Flag, Definition, Super Class, and ACL" },
+ { 0x0005, "Return Class Name, Flag, Creation Timestamp, Modification Timestamp, Definition, and ACL" },
+ { 0, NULL }
+};
+
+static const value_string nds_search_scope[] = {
+ { 0x0000, "Examine the base object only" },
+ { 0x0001, "Search the immediate subordinates of the base object" },
+ { 0x0002, "Search the base object and all its subordinates" },
+ { 0x0003, "Search the base objects and all objects in its partition (Implemented in NDS 8)" },
+ { 0, NULL }
+};
+
+static const value_string nds_reply_errors[] = {
+ { 0xffffffff, "(-1) Insufficient Space" },
+ { 0xffffff89, "(-119) Buffer too Small" },
+ { 0xffffff88, "(-120) RR Volume Flag Not Set" },
+ { 0xffffff87, "(-121) No Items Found" },
+ { 0xffffff86, "(-122) Connection Already Temporary" },
+ { 0xffffff85, "(-123) Connection Already Logged In" },
+ { 0xffffff84, "(-124) Connection Not Authenticated" },
+ { 0xffffff83, "(-125) Connection Not Logged In" },
+ { 0xffffff82, "(-126) NCP Boundary Check Failed" },
+ { 0xffffff81, "(-127) Lock Waiting" },
+ { 0xffffff80, "(-128) Lock Fail" },
+ { 0xffffff7f, "(-129) Out of Handles" },
+ { 0xffffff7e, "(-130) No Open Privilege" },
+ { 0xffffff7d, "(-131) Hard IO Error" },
+ { 0xffffff7c, "(-132) No Create Privilege" },
+ { 0xffffff7b, "(-133) No Create Delete Privilege" },
+ { 0xffffff7a, "(-134) Create Duplicate When Read Only" },
+ { 0xffffff79, "(-135) Create File with Invalid Name" },
+ { 0xffffff78, "(-136) Invalid File Handle" },
+ { 0xffffff77, "(-137) No Search Privilege" },
+ { 0xffffff76, "(-138) No Delete Privilege" },
+ { 0xffffff75, "(-139) No Rename Privilege" },
+ { 0xffffff74, "(-140) No Set Privilege" },
+ { 0xffffff73, "(-141) Some File in Use" },
+ { 0xffffff72, "(-142) All File in Use" },
+ { 0xffffff71, "(-143) Some Read Only" },
+ { 0xffffff70, "(-144) All Read Only" },
+ { 0xffffff6f, "(-145) Some names Exist" },
+ { 0xffffff6e, "(-146) All Names Exist" },
+ { 0xffffff6d, "(-147) No Read Privilege" },
+ { 0xffffff6c, "(-148) No Write Privilege" },
+ { 0xffffff6b, "(-149) File Detached" },
+ { 0xffffff6a, "(-150) No Alloc Space/Target Not a Subdirectory/Insuffficient Memory" },
+ { 0xffffff69, "(-151) No Spool Space" },
+ { 0xffffff68, "(-152) Invalid Volume" },
+ { 0xffffff67, "(-153) Directory Full" },
+ { 0xffffff66, "(-154) Rename Across Volume" },
+ { 0xffffff65, "(-155) Bad Directory Handle" },
+ { 0xffffff64, "(-156) Invalid Path/No Such Extension" },
+ { 0xffffff63, "(-157) No Directory Handles" },
+ { 0xffffff62, "(-158) Bad File Name" },
+ { 0xffffff61, "(-159) Directory Active" },
+ { 0xffffff60, "(-160) Directory Not Empty" },
+ { 0xffffff5f, "(-161) Directory IO Error" },
+ { 0xffffff5e, "(-162) IO Locked" },
+ { 0xffffff5d, "(-163) Transaction Restarted" },
+ { 0xffffff5c, "(-164) Rename Directory Invalid" },
+ { 0xffffff5b, "(-165) Invalid Open/Create Mode" },
+ { 0xffffff5a, "(-166) Already in Use" },
+ { 0xffffff59, "(-167) Invalid Resource Tag" },
+ { 0xffffff58, "(-168) Access Denied" },
+ { 0xffffff44, "(-188) Login Signing Required" },
+ { 0xffffff43, "(-189) Login Encryption Required" },
+ { 0xffffff42, "(-190) Invalid Data Stream" },
+ { 0xffffff41, "(-191) Invalid Name Space" },
+ { 0xffffff40, "(-192) No Accounting Privileges" },
+ { 0xffffff3f, "(-193) No Account Balance" },
+ { 0xffffff3e, "(-194) Credit Limit Exceeded" },
+ { 0xffffff3d, "(-195) Too Many Holds" },
+ { 0xffffff3c, "(-196) Accounting Disabled" },
+ { 0xffffff3b, "(-197) Intruder Login Lockout" },
+ { 0xffffff3a, "(-198) No Console Rights" },
+ { 0xffffff30, "(-208) Queue IO Failure" },
+ { 0xffffff2f, "(-209) No Queue" },
+ { 0xffffff2e, "(-210) No Queue Server" },
+ { 0xffffff2d, "(-211) No Queue Rights" },
+ { 0xffffff2c, "(-212) Queue Full" },
+ { 0xffffff2b, "(-213) No Queue Job" },
+ { 0xffffff2a, "(-214) No Queue Job Rights/Unencrypted Not Allowed" },
+ { 0xffffff29, "(-215) Queue In Service/Duplicate Password" },
+ { 0xffffff28, "(-216) Queue Not Active/Password Too Short" },
+ { 0xffffff27, "(-217) Queue Station Not Server/Maximum Logins Exceeded" },
+ { 0xffffff26, "(-218) Queue Halted/Bad Login Time" },
+ { 0xffffff25, "(-219) Queue Maximum Servers/Node Address Violation" },
+ { 0xffffff24, "(-220) Login Account Expired" },
+ { 0xffffff22, "(-222) Bad Password" },
+ { 0xffffff21, "(-223) Password Expired" },
+ { 0xffffff20, "(-224) No Login Connection Available" },
+ { 0xffffff18, "(-232) Write to Group Property" },
+ { 0xffffff17, "(-233) Member Already Exists" },
+ { 0xffffff16, "(-234) No Such Member" },
+ { 0xffffff15, "(-235) Property Not Group" },
+ { 0xffffff14, "(-236) No Such Value Set" },
+ { 0xffffff13, "(-237) Property Already Exists" },
+ { 0xffffff12, "(-238) Object Already Exists" },
+ { 0xffffff11, "(-239) Illegal Name" },
+ { 0xffffff10, "(-240) Illegal Wildcard" },
+ { 0xffffff0f, "(-241) Bindery Security" },
+ { 0xffffff0e, "(-242) No Object Read Rights" },
+ { 0xffffff0d, "(-243) No Object Rename Rights" },
+ { 0xffffff0c, "(-244) No Object Delete Rights" },
+ { 0xffffff0b, "(-245) No Object Create Rights" },
+ { 0xffffff0a, "(-246) No Property Delete Rights" },
+ { 0xffffff09, "(-247) No Property Create Rigths" },
+ { 0xffffff08, "(-248) No Property Write Rights" },
+ { 0xffffff07, "(-249) No Propery Read Rights" },
+ { 0xffffff06, "(-250) Temp Remap" },
+ { 0xffffff05, "(-251) Unknown Request/No Such Property" },
+ { 0xffffff04, "(-252) Message Queue Full/Target Already Has Message/No Such Object" },
+ { 0xffffff03, "(-253) Bad Station Number" },
+ { 0xffffff02, "(-254) Bindery Locked/Directory Locked/Spool Delete/Trustee not Found/Timeout" },
+ { 0xffffff01, "(-255) Hard Failure" },
+ { 0xfffffed3, "(-301) Not Enough Memory" },
+ { 0xfffffed2, "(-302) Bad Key" },
+ { 0xfffffed1, "(-303) Bad Context" },
+ { 0xfffffed0, "(-304) Buffer Full" },
+ { 0xfffffecf, "(-305) List Empty" },
+ { 0xfffffece, "(-306) Bad Syntax" },
+ { 0xfffffecd, "(-307) Buffer Empty" },
+ { 0xfffffecc, "(-308) Bad Verb" },
+ { 0xfffffecb, "(-309) Expected Identifier" },
+ { 0xfffffeca, "(-310) Expected Equals" },
+ { 0xfffffec9, "(-311) Attribute Type Expected" },
+ { 0xfffffec8, "(-312) Attribute Type Not Expected" },
+ { 0xfffffec7, "(-313) Filter Tree Empty" },
+ { 0xfffffec6, "(-314) Invalid Object Name" },
+ { 0xfffffec5, "(-315) Expected RDN Delimiter" },
+ { 0xfffffec4, "(-316) Too Many Tokens" },
+ { 0xfffffec3, "(-317) Inconsistent MultiAVA" },
+ { 0xfffffec2, "(-318) Country Name Too Long" },
+ { 0xfffffec1, "(-319) Internal Error" },
+ { 0xfffffec0, "(-320) Can't Add Root" },
+ { 0xfffffebf, "(-321) Unable to Attach" },
+ { 0xfffffebe, "(-322) Invalid Iteration Handle" },
+ { 0xfffffebd, "(-323) Buffer Zero Length" },
+ { 0xfffffebc, "(-324) Invalid Replica Type" },
+ { 0xfffffebb, "(-325) Invalid Attribute Syntax" },
+ { 0xfffffeba, "(-326) Invalid Filter Syntax" },
+ { 0xfffffeb8, "(-328) Unicode Error during Context Creation" },
+ { 0xfffffeb7, "(-329) Invalid Union Tag" },
+ { 0xfffffeb6, "(-330) Invalid Server Response" },
+ { 0xfffffeb5, "(-331) Null Pointer" },
+ { 0xfffffeb4, "(-332) No Server Found" },
+ { 0xfffffeb3, "(-333) No Connection" },
+ { 0xfffffeb2, "(-334) RDN Too Long" },
+ { 0xfffffeb1, "(-335) Duplicate Type" },
+ { 0xfffffeb0, "(-336) Data Store Failure" },
+ { 0xfffffeaf, "(-337) Not Logged In" },
+ { 0xfffffeae, "(-338) Invalid Password Characters" },
+ { 0xfffffead, "(-339) Failed Server Authentication" },
+ { 0xfffffeac, "(-340) Transport Failed" },
+ { 0xfffffeab, "(-341) No Such Syntax" },
+ { 0xfffffeaa, "(-342) Invalid DS Name" },
+ { 0xfffffea9, "(-343) Attribute Name Too Long" },
+ { 0xfffffea8, "(-344) Invalid TDS" },
+ { 0xfffffea7, "(-345) Invalid DS Version" },
+ { 0xfffffea6, "(-346) Unicode Translation" },
+ { 0xfffffea5, "(-347) Schema Name Too Long" },
+ { 0xfffffea4, "(-348) Unicode File Not Found" },
+ { 0xfffffea3, "(-349) Unicode Already Loaded" },
+ { 0xfffffea2, "(-350) Not Context Owner" },
+ { 0xfffffea1, "(-351) Attempt to Authenticate" },
+ { 0xfffffea0, "(-352) No Writable Replicas" },
+ { 0xfffffe9f, "(-353) DN Too Long" },
+ { 0xfffffe9e, "(-354) Rename Not Allowed" },
+ { 0xfffffe9d, "(-355) Not NDS for NT" },
+ { 0xfffffe9c, "(-356) NDS for NT - No Domain" },
+ { 0xfffffe9b, "(-357) NDS for NT - Sync Disabled" },
+ { 0xfffffe9a, "(-358) Iterator Invalid Handle" },
+ { 0xfffffe99, "(-359) Iterator Invalid Position" },
+ { 0xfffffe98, "(-360) Iterator Invalid Search Data" },
+ { 0xfffffe97, "(-361) Iterator Invalid Scope" },
+ { 0xfffffda7, "(-601) No Such Entry" },
+ { 0xfffffda6, "(-602) No Such Value" },
+ { 0xfffffda5, "(-603) No Such Attribute" },
+ { 0xfffffda4, "(-604) No Such Class" },
+ { 0xfffffda3, "(-605) No Such Partition" },
+ { 0xfffffda2, "(-606) Entry Already Exists" },
+ { 0xfffffda1, "(-607) Not Effective Class" },
+ { 0xfffffda0, "(-608) Illegal Attribute" },
+ { 0xfffffd9f, "(-609) Missing Mandatory" },
+ { 0xfffffd9e, "(-610) Illegal DS Name" },
+ { 0xfffffd9d, "(-611) Illegal Containment" },
+ { 0xfffffd9c, "(-612) Can't Have Multiple Values" },
+ { 0xfffffd9b, "(-613) Syntax Violation" },
+ { 0xfffffd9a, "(-614) Duplicate Value" },
+ { 0xfffffd99, "(-615) Attribute Already Exists" },
+ { 0xfffffd98, "(-616) Maximum Entries Exist" },
+ { 0xfffffd97, "(-617) Database Format" },
+ { 0xfffffd96, "(-618) Inconsistent Database" },
+ { 0xfffffd95, "(-619) Invalid Comparison" },
+ { 0xfffffd94, "(-620) Comparison Failed" },
+ { 0xfffffd93, "(-621) Transaction Tracking Disabled" },
+ { 0xfffffd92, "(-622) Invalid Transport" },
+ { 0xfffffd91, "(-623) Syntax Invalid in Name" },
+ { 0xfffffd90, "(-624) Replica Already Exists" },
+ { 0xfffffd8f, "(-625) Transport Failure" },
+ { 0xfffffd8e, "(-626) All Referrals Failed" },
+ { 0xfffffd8d, "(-627) Can't Remove Naming Value" },
+ { 0xfffffd8c, "(-628) Object Class Violation" },
+ { 0xfffffd8b, "(-629) Entry is Not Leaf" },
+ { 0xfffffd8a, "(-630) Different Tree" },
+ { 0xfffffd89, "(-631) Illegal Replica Type" },
+ { 0xfffffd88, "(-632) System Failure" },
+ { 0xfffffd87, "(-633) Invalid Entry for Root" },
+ { 0xfffffd86, "(-634) No Referrals" },
+ { 0xfffffd85, "(-635) Remote Failure" },
+ { 0xfffffd84, "(-636) Unreachable Server" },
+ { 0xfffffd83, "(-637) Previous Move in Progress" },
+ { 0xfffffd82, "(-638) No Character Mapping" },
+ { 0xfffffd81, "(-639) Incomplete Authentication" },
+ { 0xfffffd80, "(-640) Invalid Certificate" },
+ { 0xfffffd7f, "(-641) Invalid Request" },
+ { 0xfffffd7e, "(-642) Invalid Iteration" },
+ { 0xfffffd7d, "(-643) Schema is Non-removable" },
+ { 0xfffffd7c, "(-644) Schema is in Use" },
+ { 0xfffffd7b, "(-645) Class Already Exists" },
+ { 0xfffffd7a, "(-646) Bad Naming Attributes" },
+ { 0xfffffd79, "(-647) Not Root Partition" },
+ { 0xfffffd78, "(-648) Insufficient Stack" },
+ { 0xfffffd77, "(-649) Insufficient Buffer" },
+ { 0xfffffd76, "(-650) Ambiguous Containment" },
+ { 0xfffffd75, "(-651) Ambiguous Naming" },
+ { 0xfffffd74, "(-652) Duplicate Mandatory" },
+ { 0xfffffd73, "(-653) Duplicate Optional" },
+ { 0xfffffd72, "(-654) Partition Busy" },
+ { 0xfffffd71, "(-655) Multiple Replicas" },
+ { 0xfffffd70, "(-656) Crucial Replica" },
+ { 0xfffffd6f, "(-657) Schema Sync in Progress" },
+ { 0xfffffd6e, "(-658) Skulk in Progress" },
+ { 0xfffffd6d, "(-659) Time Not Synchronized" },
+ { 0xfffffd6c, "(-660) Record in Use" },
+ { 0xfffffd6b, "(-661) DS Volume Not Mounted" },
+ { 0xfffffd6a, "(-662) DS Volume IO Failure" },
+ { 0xfffffd69, "(-663) DS Locked" },
+ { 0xfffffd68, "(-664) Old Epoch" },
+ { 0xfffffd67, "(-665) New Epoch" },
+ { 0xfffffd66, "(-666) Incompatible DS Version" },
+ { 0xfffffd65, "(-667) Partition Root" },
+ { 0xfffffd64, "(-668) Entry Not Container" },
+ { 0xfffffd63, "(-669) Failed Authentication" },
+ { 0xfffffd62, "(-670) Invalid Context" },
+ { 0xfffffd61, "(-671) No Such Parent" },
+ { 0xfffffd60, "(-672) No Access" },
+ { 0xfffffd5f, "(-673) Replica Not On" },
+ { 0xfffffd5e, "(-674) Invalid Name Service" },
+ { 0xfffffd5d, "(-675) Invalid Task" },
+ { 0xfffffd5c, "(-676) Invalide Connection Handle" },
+ { 0xfffffd5b, "(-677) Invalid Identity" },
+ { 0xfffffd5a, "(-678) Duplicate ACL" },
+ { 0xfffffd59, "(-679) Partition Already Exists" },
+ { 0xfffffd58, "(-680) Transport Modified" },
+ { 0xfffffd57, "(-681) Alias of an Alias" },
+ { 0xfffffd56, "(-682) Auditing Failed" },
+ { 0xfffffd55, "(-683) Invalid API Version" },
+ { 0xfffffd54, "(-684) Secure NCP Violation" },
+ { 0xfffffd53, "(-685) Move in Progress" },
+ { 0xfffffd52, "(-686) Not a Leaf Partition" },
+ { 0xfffffd51, "(-687) Cannot Abort" },
+ { 0xfffffd50, "(-688) Cache Overflow" },
+ { 0xfffffd4f, "(-689) Invalid Subordinate Count" },
+ { 0xfffffd4e, "(-690) Invalid RDN" },
+ { 0xfffffd4d, "(-691) Modification Time Not Current" },
+ { 0xfffffd4c, "(-692) Incorrect Base Class" },
+ { 0xfffffd4b, "(-693) Missing Reference" },
+ { 0xfffffd4a, "(-694) Lost Entry" },
+ { 0xfffffd49, "(-695) Agent Already Registered" },
+ { 0xfffffd48, "(-696) DS Loader Busy" },
+ { 0xfffffd47, "(-697) DS Cannot Reload" },
+ { 0xfffffd46, "(-698) Replica in Skulk" },
+ { 0xfffffd45, "(-699) Fatal" },
+ { 0xfffffd44, "(-700) Obsolete API" },
+ { 0xfffffd43, "(-701) Synchronization Disabled" },
+ { 0xfffffd42, "(-702) Invalid Parameter" },
+ { 0xfffffd41, "(-703) Duplicate Template" },
+ { 0xfffffd40, "(-704) No Master Replica" },
+ { 0xfffffd3f, "(-705) Duplicate Containment" },
+ { 0xfffffd3e, "(-706) Not a Sibling" },
+ { 0xfffffd3d, "(-707) Invalid Signature" },
+ { 0xfffffd3c, "(-708) Invalid Response" },
+ { 0xfffffd3b, "(-709) Insufficient Sockets" },
+ { 0xfffffd3a, "(-710) Database Read Fail" },
+ { 0xfffffd39, "(-711) Invalid Code Page" },
+ { 0xfffffd38, "(-712) Invalid Escape Character" },
+ { 0xfffffd37, "(-713) Invalide Delimiters" },
+ { 0xfffffd36, "(-714) Not Implemented" },
+ { 0xfffffd35, "(-715) Checksum Failure" },
+ { 0xfffffd34, "(-716) Checksumming Not Supported" },
+ { 0xfffffd33, "(-717) CRC Failure" },
+ { 0xfffffd32, "(-718) Invalid Entry Handle" },
+ { 0xfffffd31, "(-719) Invalid Value Handle" },
+ { 0xfffffd30, "(-720) Connection Denied" },
+ { 0xfffffd2f, "(-721) No Such Federation Link" },
+ { 0xfffffd2e, "(-722) Operetational Schema Mismatch" },
+ { 0xfffffd2d, "(-723) Stream Not Found" },
+ { 0xfffffd2c, "(-724) DClient Unavailable" },
+ { 0xfffffd2b, "(-725) MASV No Access" },
+ { 0xfffffd2a, "(-726) MASV Invalid Request" },
+ { 0xfffffd29, "(-727) MASV Failure" },
+ { 0xfffffd28, "(-728) MASV Already Exists" },
+ { 0xfffffd27, "(-729) MASV Not Found" },
+ { 0xfffffd26, "(-730) MASV Bad Range" },
+ { 0xfffffd25, "(-731) Value Data" },
+ { 0xfffffd24, "(-732) Database Locked" },
+ { 0xfffffd21, "(-735) Nothing to Abort" },
+ { 0xfffffd20, "(-736) End of Stream" },
+ { 0xfffffd1f, "(-737) No Such Template" },
+ { 0xfffffd1e, "(-738) SAS Locked" },
+ { 0xfffffd1d, "(-739) Invalid SAS Version" },
+ { 0xfffffd1c, "(-740) SAS Already Registered" },
+ { 0xfffffd1b, "(-741) Name Type Not Supported" },
+ { 0xfffffd1a, "(-742) Wrong DS Version" },
+ { 0xfffffd19, "(-743) Invalid Control Function" },
+ { 0xfffffd18, "(-744) Invalid Control State" },
+ { 0xfffffd17, "(-745) Cache in Use" },
+ { 0xfffffd16, "(-746) Zero Creation Time" },
+ { 0xfffffd15, "(-747) Would Block" },
+ { 0xfffffd14, "(-748) Connection Timeout" },
+ { 0xfffffd13, "(-749) Too Many Referrals" },
+ { 0xfffffd12, "(-750) Operation Cancelled" },
+ { 0xfffffd11, "(-751) Unknown Target" },
+ { 0xfffffd10, "(-752) GUID Failure" },
+ { 0xfffffd0f, "(-753) Incompatible OS" },
+ { 0xfffffd0e, "(-754) Callback Cancel" },
+ { 0xfffffd0d, "(-755) Invalid Synchronization Data" },
+ { 0xfffffd0c, "(-756) Stream Exists" },
+ { 0xfffffd0b, "(-757) Auxiliary Has Containment" },
+ { 0xfffffd0a, "(-758) Auxiliary Not Container" },
+ { 0xfffffd09, "(-759) Auxiliary Not Effective" },
+ { 0xfffffd08, "(-760) Auxiliary On Alias" },
+ { 0xfffffd07, "(-761) Have Seen State" },
+ { 0xfffffd06, "(-762) Verb Locked" },
+ { 0xfffffd05, "(-763) Verb Exceeds Table Length" },
+ { 0xfffffd04, "(-764) BOF Hit" },
+ { 0xfffffd03, "(-765) EOF Hit" },
+ { 0xfffffd02, "(-766) Incompatible Replica Version" },
+ { 0xfffffd01, "(-767) Query Timeout" },
+ { 0xfffffd00, "(-768) Query Maximum Count" },
+ { 0xfffffcff, "(-769) Duplicate Naming" },
+ { 0xfffffcfe, "(-770) No Transaction Active" },
+ { 0xfffffcfd, "(-771) Transaction Active" },
+ { 0xfffffcfc, "(-772) Illegal Transaction Operation" },
+ { 0xfffffcfb, "(-773) Iterator Syntax" },
+ { 0xfffffcfa, "(-774) Repairing DIB" },
+ { 0xfffffcf9, "(-775) Invalid OID Format" },
+ { 0xfffffcf8, "(-776) Attempted to perform an NDS operation, and the DS agent on this server is closing" },
+ { 0xfffffcf7, "(-777) Attempted to modify an object's attribute that is not stored on the sparse replica" },
+ { 0xfffffcf6, "(-778) VpVector and VpvUser which must be correlated, are out of sync" },
+ { 0xfffffcf5, "(-779) Error Cannot Go Remote" },
+ { 0xfffffcf4, "(-780) Request not Supported" },
+ { 0xfffffcf3, "(-781) Entry Not Local" },
+ { 0xfffffcf2, "(-782) Root Unreachable" },
+ { 0xfffffcf1, "(-783) VRDIM Not Initialized" },
+ { 0xfffffcf0, "(-784) Wait Timeout" },
+ { 0xfffffcef, "(-785) DIB Error" },
+ { 0xfffffcee, "(-786) DIB IO Failure" },
+ { 0xfffffced, "(-787) Illegal Schema Attribute" },
+ { 0xfffffcec, "(-788) Error Schema Partition" },
+ { 0xfffffceb, "(-789) Invalid Template" },
+ { 0xfffffcea, "(-790) Error Opening File" },
+ { 0xfffffce9, "(-791) Error Direct Opening File" },
+ { 0xfffffce8, "(-792) Error Creating File" },
+ { 0xfffffce7, "(-793) Error Direct Creating File" },
+ { 0xfffffce6, "(-794) Error Reading File" },
+ { 0xfffffce5, "(-795) Error Direct Reading File" },
+ { 0xfffffce4, "(-796) Error Writing File" },
+ { 0xfffffce3, "(-797) Error Direct Writing File" },
+ { 0xfffffce2, "(-798) Error Positioning in File" },
+ { 0xfffffce1, "(-799) Error Getting File Size" },
+ { 0xffffe88f, "(-6001) Error Truncating File" },
+ { 0xffffe88e, "(-6002) Error Parsing File Name" },
+ { 0xffffe88d, "(-6003) Error Closing File" },
+ { 0xffffe88c, "(-6004) Error Getting File Info" },
+ { 0xffffe88b, "(-6005) Error Expanding File" },
+ { 0xffffe88a, "(-6006) Error Getting Free Blocks" },
+ { 0xffffe889, "(-6007) Error Checking File Existence" },
+ { 0xffffe888, "(-6008) Error Deleting File" },
+ { 0xffffe887, "(-6009) Error Renaming File" },
+ { 0xffffe886, "(-6010) Error Initializing IO System" },
+ { 0xffffe885, "(-6011) Error Flushing File" },
+ { 0xffffe884, "(-6012) Error Setting Up for Read" },
+ { 0xffffe883, "(-6013) Error Setting up for Write" },
+ { 0xffffe882, "(-6014) Error Old View" },
+ { 0xffffe881, "(-6015) Server in Skulk" },
+ { 0xffffe880, "(-6016) Error Returning Partial Results" },
+ { 0xffffe87f, "(-6017) No Such Schema" },
+ { 0xffffe87e, "(-6018) Serial Number Mismatch" },
+ { 0xffffe87d, "(-6019) Bad Referal Database Serial Number" },
+ { 0xffffe87c, "(-6020) Bad Referal Serial Number" },
+ { 0xffffe87b, "(-6021) Invalid File Sequence" },
+ { 0xffffe87a, "(-6022) Error Referal Trans Gap" },
+ { 0xffffe879, "(-6023) Bad Referal File Number" },
+ { 0xffffe878, "(-6024) Referal File Not Found" },
+ { 0xffffe877, "(-6025) Error Backup Active" },
+ { 0xffffe876, "(-6026) Referal Device Full" },
+ { 0xffffe875, "(-6027) Unsupported Version" },
+ { 0xffffe874, "(-6028) Error Must Wait Checkpoint" },
+ { 0xffffe873, "(-6029) Attribute Maintenance in Progress" },
+ { 0xffffe872, "(-6030) Error Abort Transaction" },
+ { 0xffff0000, "Ok" },
+ { 0x0000, "Ok" },
+ { 0, NULL }
+};
+
+
+static void
+process_ptvc_record(ptvcursor_t *ptvc, const ptvc_record *rec,
+ int *req_cond_results, gboolean really_decode,
+ const ncp_record *ncp_rec);
+
+/* NCP packets come in request/reply pairs. The request packets tell the type
+ * of NCP request and give a sequence ID. The response, unfortunately, only
+ * identifies itself via the sequence ID; you have to know what type of NCP
+ * request the request packet contained in order to successfully parse the NCP
+ * response. A global method for doing this does not exist in ethereal yet
+ * (NFS also requires it), so for now the NCP section will keep its own hash
+ * table keeping track of NCP packet types.
+ *
+ * We construct a conversation specified by the client and server
+ * addresses and the connection number; the key representing the unique
+ * NCP request then is composed of the pointer to the conversation
+ * structure, cast to a "guint" (which may throw away the upper 32
+ * bits of the pointer on a P64 platform, but the low-order 32 bits
+ * are more likely to differ between conversations than the upper 32 bits),
+ * and the sequence number.
+ *
+ * The value stored in the hash table is the ncp_req_hash_value pointer. This
+ * struct tells us the NCP type and gives the ncp2222_record pointer, if
+ * ncp_type == 0x2222.
+ */
+typedef struct {
+ conversation_t *conversation;
+ guint8 nw_sequence;
+} ncp_req_hash_key;
+
+
+typedef struct {
+ guint32 nw_eid;
+} ncp_req_eid_hash_key;
+
+typedef struct {
+ char object_name[256];
+ char *object_class;
+} ncp_req_eid_hash_value;
+
+static GHashTable *ncp_req_hash = NULL;
+static GHashTable *ncp_req_eid_hash = NULL;
+static GMemChunk *ncp_req_eid_hash_keys = NULL;
+static GMemChunk *ncp_req_eid_hash_values = NULL;
+static GMemChunk *ncp_req_hash_keys = NULL;
+static GMemChunk *ncp_req_hash_values = NULL;
+
+/* Hash Functions */
+gint
+ncp_equal(gconstpointer v, gconstpointer v2)
+{
+ const ncp_req_hash_key *val1 = (const ncp_req_hash_key*)v;
+ const ncp_req_hash_key *val2 = (const ncp_req_hash_key*)v2;
+
+ if (val1->conversation == val2->conversation &&
+ val1->nw_sequence == val2->nw_sequence ) {
+ return 1;
+ }
+ return 0;
+}
+
+gint
+ncp_eid_equal(gconstpointer v, gconstpointer v2)
+{
+ const ncp_req_eid_hash_key *val1 = (const ncp_req_eid_hash_key*)v;
+ const ncp_req_eid_hash_key *val2 = (const ncp_req_eid_hash_key*)v2;
+
+ if (val1->nw_eid == val2->nw_eid ) {
+ return 1;
+ }
+ return 0;
+}
+
+guint
+ncp_hash(gconstpointer v)
+{
+ const ncp_req_hash_key *ncp_key = (const ncp_req_hash_key*)v;
+ return GPOINTER_TO_UINT(ncp_key->conversation) + ncp_key->nw_sequence;
+}
+
+guint
+ncp_eid_hash(gconstpointer v)
+{
+ const ncp_req_eid_hash_key *ncp_eid_key = (const ncp_req_eid_hash_key*)v;
+ return GPOINTER_TO_UINT(ncp_eid_key->nw_eid);
+}
+
+/* Frees memory used by the ncp_req_hash_value's */
+static void
+ncp_req_hash_cleanup(gpointer key _U_, gpointer value, gpointer user_data _U_)
+{
+ ncp_req_hash_value *request_value = (ncp_req_hash_value*) value;
+
+ if (request_value->req_cond_results) {
+ g_free(request_value->req_cond_results);
+ }
+}
+
+/* Frees memory used by the ncp_req_hash_value's */
+static void
+ncp_req_eid_hash_cleanup(gpointer key _U_, gpointer value, gpointer user_data _U_)
+{
+ ncp_req_eid_hash_value *request_eid_value = (ncp_req_eid_hash_value*) value;
+
+ if (request_eid_value->object_class) {
+ g_free(request_eid_value->object_name);
+ }
+}
+
+/* Initializes the hash table and the mem_chunk area each time a new
+ * file is loaded or re-loaded in ethereal */
+static void
+ncp_init_protocol(void)
+{
+ /* fragment */
+ fragment_table_init(&nds_fragment_table);
+ reassembled_table_init(&nds_reassembled_table);
+
+ if (ncp_req_hash) {
+ g_hash_table_foreach(ncp_req_hash, ncp_req_hash_cleanup, NULL);
+ g_hash_table_destroy(ncp_req_hash);
+ }
+ if (ncp_req_eid_hash) {
+ g_hash_table_foreach(ncp_req_eid_hash, ncp_req_eid_hash_cleanup, NULL);
+ g_hash_table_destroy(ncp_req_eid_hash);
+ }
+ if (ncp_req_hash_keys)
+ g_mem_chunk_destroy(ncp_req_hash_keys);
+ if (ncp_req_hash_values)
+ g_mem_chunk_destroy(ncp_req_hash_values);
+ if (ncp_req_eid_hash_keys)
+ g_mem_chunk_destroy(ncp_req_eid_hash_keys);
+ if (ncp_req_eid_hash_values)
+ g_mem_chunk_destroy(ncp_req_eid_hash_values);
+
+ ncp_req_hash = g_hash_table_new(ncp_hash, ncp_equal);
+ ncp_req_eid_hash = g_hash_table_new(ncp_eid_hash, ncp_eid_equal);
+ ncp_req_hash_keys = g_mem_chunk_new("ncp_req_hash_keys",
+ sizeof(ncp_req_hash_key),
+ NCP_PACKET_INIT_COUNT * sizeof(ncp_req_hash_key),
+ G_ALLOC_ONLY);
+ ncp_req_hash_values = g_mem_chunk_new("ncp_req_hash_values",
+ sizeof(ncp_req_hash_value),
+ NCP_PACKET_INIT_COUNT * sizeof(ncp_req_hash_value),
+ G_ALLOC_ONLY);
+ ncp_req_eid_hash_keys = g_mem_chunk_new("ncp_req_eid_hash_keys",
+ sizeof(ncp_req_eid_hash_key),
+ NCP_PACKET_INIT_COUNT * sizeof(ncp_req_eid_hash_key),
+ G_ALLOC_ONLY);
+ ncp_req_eid_hash_values = g_mem_chunk_new("ncp_req_eid_hash_values",
+ sizeof(ncp_req_eid_hash_value),
+ NCP_PACKET_INIT_COUNT * sizeof(ncp_req_eid_hash_value),
+ G_ALLOC_ONLY);
+}
+
+/* After the sequential run, we don't need the ncp_request hash and keys
+ * anymore; the lookups have already been done and the vital info
+ * saved in the reply-packets' private_data in the frame_data struct. */
+static void
+ncp_postseq_cleanup(void)
+{
+ if (ncp_req_hash) {
+ /* Destroy the hash, but don't clean up request_condition data. */
+ /*g_hash_table_destroy(ncp_req_hash);
+ ncp_req_hash = NULL;*/
+ }
+ if (ncp_req_hash_keys) {
+ /*g_mem_chunk_destroy(ncp_req_hash_keys);
+ ncp_req_hash_keys = NULL;*/
+ }
+ /* Don't free the ncp_req_hash_values or EID_hash_table, as they're
+ * needed during random-access processing of the proto_tree.*/
+}
+
+ncp_req_hash_value*
+ncp_hash_insert(conversation_t *conversation, guint8 nw_sequence,
+ const ncp_record *ncp_rec)
+{
+ ncp_req_hash_key *request_key;
+ ncp_req_hash_value *request_value;
+
+ /* Now remember the request, so we can find it if we later
+ a reply to it. */
+ request_key = g_mem_chunk_alloc(ncp_req_hash_keys);
+ request_key->conversation = conversation;
+ request_key->nw_sequence = nw_sequence;
+
+ request_value = g_mem_chunk_alloc(ncp_req_hash_values);
+ request_value->ncp_rec = ncp_rec;
+ request_value->req_cond_results = NULL;
+ request_value->req_nds_flags = 0;
+ request_value->nds_request_verb = 0;
+ request_value->nds_version = 0;
+ strcpy(request_value->object_name, " ");
+ request_value->nds_frag = TRUE;
+
+ g_hash_table_insert(ncp_req_hash, request_key, request_value);
+
+ return request_value;
+}
+
+ncp_req_eid_hash_value*
+ncp_eid_hash_insert(guint32 nw_eid)
+{
+ ncp_req_eid_hash_key *request_eid_key;
+ ncp_req_eid_hash_value *request_eid_value;
+
+ /* Now remember the request, so we can find it if we later
+ a reply to it. */
+ request_eid_key = g_mem_chunk_alloc(ncp_req_eid_hash_keys);
+ request_eid_key->nw_eid = nw_eid;
+
+ request_eid_value = g_mem_chunk_alloc(ncp_req_eid_hash_values);
+ strcpy(request_eid_value->object_name, " ");
+ request_eid_value->object_class = NULL;
+
+ g_hash_table_insert(ncp_req_eid_hash, request_eid_key, request_eid_value);
+
+ return request_eid_value;
+}
+
+/* Returns the ncp_rec*, or NULL if not found. */
+ncp_req_hash_value*
+ncp_hash_lookup(conversation_t *conversation, guint8 nw_sequence)
+{
+ ncp_req_hash_key request_key;
+
+ request_key.conversation = conversation;
+ request_key.nw_sequence = nw_sequence;
+
+ return g_hash_table_lookup(ncp_req_hash, &request_key);
+}
+
+/* Returns the value_rec* for needed EID, or NULL if not found. */
+ncp_req_eid_hash_value*
+ncp_eid_hash_lookup(conversation_t *conversation _U_, guint32 nw_eid)
+{
+ ncp_req_eid_hash_key request_eid_key;
+
+ request_eid_key.nw_eid = nw_eid;
+
+ return g_hash_table_lookup(ncp_req_eid_hash, &request_eid_key);
+}
+
+/* Does NCP func require a subfunction code? */
+static gboolean
+ncp_requires_subfunc(guint8 func)
+{
+ const guint8 *ncp_func_requirement = ncp_func_requires_subfunc;
+
+ while (*ncp_func_requirement != 0) {
+ if (*ncp_func_requirement == func) {
+ return TRUE;
+ }
+ ncp_func_requirement++;
+ }
+ return FALSE;
+}
+
+/* Does the NCP func have a length parameter? */
+static gboolean
+ncp_has_length_parameter(guint8 func)
+{
+ const guint8 *ncp_func_requirement = ncp_func_has_no_length_parameter;
+
+ while (*ncp_func_requirement != 0) {
+ if (*ncp_func_requirement == func) {
+ return FALSE;
+ }
+ ncp_func_requirement++;
+ }
+ return TRUE;
+}
+
+
+/* Return a ncp_record* based on func and possibly subfunc */
+static const ncp_record *
+ncp_record_find(guint8 func, guint8 subfunc)
+{
+ const ncp_record *ncp_rec = ncp_packets;
+
+ while(ncp_rec->func != 0 || ncp_rec->subfunc != 0 ||
+ ncp_rec->name != NULL ) {
+ if (ncp_rec->func == func) {
+ if (ncp_rec->has_subfunc) {
+ if (ncp_rec->subfunc == subfunc) {
+ return ncp_rec;
+ }
+ }
+ else {
+ return ncp_rec;
+ }
+ }
+ ncp_rec++;
+ }
+ return NULL;
+}
+
+
+/* Given a proto_item*, assume it contains an integer value
+ * and return a guint from it. */
+guint
+get_item_value(proto_item *item)
+{
+ return fvalue_get_integer(&PITEM_FINFO(item)->value);
+}
+
+
+char *
+get_item_string(proto_item *item)
+{
+ return fvalue_get(&PITEM_FINFO(item)->value);
+}
+
+char *
+get_item_name(proto_item *item)
+{
+ return PITEM_FINFO(item)->hfinfo->name;
+}
+
+
+typedef proto_item* (*padd_func_t)(ptvcursor_t*, const ptvc_record*);
+
+/*
+ * XXX - are these just DOS-format dates and times?
+ *
+ * Should we put code to understand various date and time formats (UNIX,
+ * DOS, SMB weird mutant UNIX, NT, Mac, etc. into libethereal, and have
+ * the "display" member of an HF_ABSOLUTE_TIME field specify whether
+ * it's DOS date/DOS time, DOS time/DOS date, NT time, UNIX time_t,
+ * UNIX "struct timeval", NFSv3/NFSv4 seconds/nanoseconds, Mac, etc.?
+ *
+ * What about hijacking the "bitmask" field to specify the precision of
+ * the time stamp, or putting a combination of precision and format
+ * into the "display" member?
+ *
+ * What about relative times? Should they have units (seconds, milliseconds,
+ * microseconds, nanoseconds, etc.), precision, and format in there?
+ */
+typedef struct {
+ guint year;
+ guint month;
+ guint day;
+} nw_date_t;
+
+typedef struct {
+ guint hour;
+ guint minute;
+ guint second;
+} nw_time_t;
+
+typedef struct {
+ char buffer[1024];
+} nw_uni_t;
+
+#define VTYPE_NONE 0 /* no value */
+#define VTYPE_UINT8 1
+#define VTYPE_UINT16 2
+#define VTYPE_UINT32 3
+#define VTYPE_STRING 4
+#define VTYPE_BITFIELD 5
+#define VTYPE_MULTIVALUE_UINT32 6
+#define VTYPE_BYTES 7
+#define VTYPE_BOOLEAN 8
+
+#define MVTYPE_ATTR_REQUEST 1
+#define MVTYPE_ATTR_REPLY 2
+#define MVTYPE_ATTR_REQUEST2 3 /* XXX - how does this differ from 1? */
+#define MVTYPE_READ_CLASS_REQ 4
+#define MVTYPE_READ_REPLICAS 5
+#define MVTYPE_MODIFY_ATTR_REQUEST 6
+#define MVTYPE_ADDR_REFERRAL_REQUEST 7
+#define MVTYPE_ADDR_REFERRAL_REPLY 8
+#define MVTYPE_LOC_ADDR_REFERRAL_REPLY 9
+#define MVTYPE_PROC_ENTRY_SPECIFIERS 10
+#define MVTYPE_PRINT_TIMESTAMP 11
+#define MVTYPE_LIST_PARTITIONS 12
+#define MVTYPE_CLASS_NAMES 13
+#define MVTYPE_MODIFY_CLASS 14
+#define MVTYPE_ADD_ATTR_REQUEST 15
+
+typedef struct {
+ guint8 vtype;
+ guint32 vvalue;
+ char* vstring;
+ char* vdesc;
+ guint32 vlength;
+ guint32 voffset;
+ guint32 hfname;
+ char* bit1;
+ guint32 bit1hfname;
+ char* bit2;
+ guint32 bit2hfname;
+ char* bit3;
+ guint32 bit3hfname;
+ char* bit4;
+ guint32 bit4hfname;
+ char* bit5;
+ guint32 bit5hfname;
+ char* bit6;
+ guint32 bit6hfname;
+ char* bit7;
+ guint32 bit7hfname;
+ char* bit8;
+ guint32 bit8hfname;
+ char* bit9;
+ guint32 bit9hfname;
+ char* bit10;
+ guint32 bit10hfname;
+ char* bit11;
+ guint32 bit11hfname;
+ char* bit12;
+ guint32 bit12hfname;
+ char* bit13;
+ guint32 bit13hfname;
+ char* bit14;
+ guint32 bit14hfname;
+ char* bit15;
+ guint32 bit15hfname;
+ char* bit16;
+ guint32 bit16hfname;
+ guint8 mvtype;
+ guint32 vflags;
+ guint32 nds_version;
+} nds_val;
+
+
+/* Given an integer, fill in a nw_date_t struct. */
+static void
+uint_to_nwdate(guint data, nw_date_t *nwdate)
+{
+ nwdate->day = data & 0x001f;
+ nwdate->month = (data & 0x01e0) >> 5;
+ nwdate->year = ((data & 0xfe00) >> 9) + 1980;
+}
+
+/* Given an integer, fill in a nw_time_t struct. */
+static void
+uint_to_nwtime(guint data, nw_time_t *nwtime)
+{
+ /* 2-second resolution */
+ nwtime->second = (data & 0x001f) * 2;
+ nwtime->minute = ((data & 0x07e0) >> 5);
+ nwtime->hour = ((data & 0xf800) >> 11);
+}
+
+char *
+unicode_to_string(char * data, guint32 length)
+{
+ guint32 i;
+ guint16 character;
+ int offset = 0;
+ char * buffer = "";
+
+ if (data[1] == 0x00){
+
+ for (i = 0; i < length; i++) {
+ character = data[offset];
+ buffer[i] = character & 0xff;
+ offset += 2;
+ }
+ }
+ else
+ {
+ buffer = data;
+ }
+ return buffer;
+}
+
+static proto_item*
+padd_normal(ptvcursor_t *ptvc, const ptvc_record *rec)
+{
+ return
+ ptvcursor_add(ptvc, *rec->hf_ptr,
+ rec->length, rec->endianness);
+}
+
+
+static proto_item*
+padd_date(ptvcursor_t *ptvc, const ptvc_record *rec)
+{
+ proto_item *item;
+ nw_date_t nw_date;
+ gint offset;
+
+ offset = ptvcursor_current_offset(ptvc);
+
+ item = ptvcursor_add(ptvc, *rec->hf_ptr,
+ rec->length, rec->endianness);
+
+ uint_to_nwdate(get_item_value(item), &nw_date);
+
+ proto_item_set_text(item, get_item_name(item));
+ proto_item_append_text(item, ": %04u/%02u/%02u",
+ nw_date.year, nw_date.month, nw_date.day);
+ return item;
+}
+
+static proto_item*
+padd_time(ptvcursor_t *ptvc, const ptvc_record *rec)
+{
+ proto_item *item;
+ nw_time_t nw_time;
+ gint offset;
+
+ offset = ptvcursor_current_offset(ptvc);
+
+ item = ptvcursor_add(ptvc, *rec->hf_ptr,
+ rec->length, rec->endianness);
+
+ uint_to_nwtime(get_item_value(item), &nw_time);
+
+ proto_item_set_text(item, get_item_name(item));
+ proto_item_append_text(item, ": %02u:%02u:%02u",
+ nw_time.hour, nw_time.minute, nw_time.second);
+ return item;
+}
+
+
+/* Convert a string from little-endian unicode to ascii. At the moment we
+ fake it by taking every odd byte. )-: The caller must free the
+ result returned. */
+static proto_item*
+padd_uni(ptvcursor_t *ptvc, const ptvc_record *rec)
+{
+ proto_item *item;
+ nw_uni_t nw_uni;
+ guint offset;
+
+ strcpy(nw_uni.buffer, "");
+ offset = ptvcursor_current_offset(ptvc);
+
+ item = ptvcursor_add(ptvc, *rec->hf_ptr,
+ rec->length, rec->endianness);
+
+ proto_item_set_text(item, get_item_name(item));
+ proto_item_append_text(item, " %s",
+ nw_uni.buffer);
+
+ return item;
+}
+
+/* Add a value for a ptvc_record, and process the sub-ptvc_record
+ * that it points to. */
+static void
+process_bitfield_sub_ptvc_record(ptvcursor_t *ptvc, const ptvc_record *rec,
+ gboolean really_decode)
+{
+ proto_item *item;
+ proto_tree *sub_tree;
+ const ptvc_record *sub_rec;
+ int current_offset;
+ gint ett;
+ ptvcursor_t *sub_ptvc;
+
+ if (really_decode) {
+ /* Save the current offset */
+ current_offset = ptvcursor_current_offset(ptvc);
+
+ /* Add the item */
+ item = ptvcursor_add(ptvc, *rec->hf_ptr, rec->length,
+ rec->endianness);
+
+ ett = *rec->sub_ptvc_rec->ett;
+
+ /* Make a new protocol sub-tree */
+ sub_tree = proto_item_add_subtree(item, ett);
+
+ /* Make a new ptvcursor */
+ sub_ptvc = ptvcursor_new(sub_tree, ptvcursor_tvbuff(ptvc),
+ current_offset);
+
+ /* Use it */
+ sub_rec = rec->sub_ptvc_rec->ptvc_rec;
+ while(sub_rec->hf_ptr != NULL) {
+ g_assert(!sub_rec->sub_ptvc_rec);
+ ptvcursor_add_no_advance(sub_ptvc, *sub_rec->hf_ptr,
+ sub_rec->length, sub_rec->endianness);
+ sub_rec++;
+ }
+
+ /* Free it. */
+ ptvcursor_free(sub_ptvc);
+ }
+ else {
+ ptvcursor_advance(ptvc, rec->length);
+ }
+}
+
+/* Process a sub-ptvc_record that points to a "struct" ptvc_record. */
+static void
+process_struct_sub_ptvc_record(ptvcursor_t *ptvc, const ptvc_record *rec,
+ int *req_cond_results, gboolean really_decode,
+ const ncp_record *ncp_rec)
+{
+ const ptvc_record *sub_rec;
+ gint ett;
+ proto_tree *old_tree=NULL, *new_tree;
+ proto_item *item=NULL;
+ gint offset=0;
+
+ /* Create a sub-proto_tree? */
+ if (rec->sub_ptvc_rec->descr) {
+ ett = *rec->sub_ptvc_rec->ett;
+ old_tree = ptvcursor_tree(ptvc);
+ offset = ptvcursor_current_offset(ptvc);
+ item = proto_tree_add_text(old_tree, ptvcursor_tvbuff(ptvc),
+ offset, PROTO_LENGTH_UNTIL_END,
+ rec->sub_ptvc_rec->descr);
+ new_tree = proto_item_add_subtree(item, ett);
+ ptvcursor_set_tree(ptvc, new_tree);
+ }
+
+ /* Get the ptvc_record for the struct and call our caller
+ * to process it. */
+ sub_rec = rec->sub_ptvc_rec->ptvc_rec;
+ process_ptvc_record(ptvc, sub_rec, req_cond_results, really_decode, ncp_rec);
+
+ /* Re-set the tree */
+ if (rec->sub_ptvc_rec->descr) {
+ proto_item_set_len(item, ptvcursor_current_offset(ptvc) - offset);
+ ptvcursor_set_tree(ptvc, old_tree);
+ }
+}
+
+/* Run through the table of ptvc_record's and add info to the tree. This
+ * is the work-horse of process_ptvc_record(). */
+static void
+_process_ptvc_record(ptvcursor_t *ptvc, const ptvc_record *rec,
+ int *req_cond_results, gboolean really_decode,
+ const ncp_record *ncp_rec)
+{
+ proto_item *item;
+ guint i, repeat_count;
+ padd_func_t func = NULL;
+
+ if (rec->sub_ptvc_rec) {
+ /* Repeat this? */
+ if (rec->repeat_index == NO_REPEAT) {
+ if (rec->hf_ptr == PTVC_STRUCT) {
+ process_struct_sub_ptvc_record(ptvc, rec,
+ req_cond_results, really_decode,
+ ncp_rec);
+ }
+ else {
+ process_bitfield_sub_ptvc_record(ptvc, rec,
+ really_decode);
+ }
+ }
+ else {
+ repeat_count = repeat_vars[rec->repeat_index];
+ for (i = 0; i < repeat_count; i++ ) {
+ if (rec->hf_ptr == PTVC_STRUCT) {
+ process_struct_sub_ptvc_record(ptvc, rec,
+ req_cond_results, really_decode,
+ ncp_rec);
+ }
+ else {
+ process_bitfield_sub_ptvc_record(ptvc, rec,
+ really_decode);
+ }
+ }
+ }
+ }
+ else {
+ /* If we can't repeat this field, we might use it
+ * to set a 'var'. */
+ if (rec->repeat_index == NO_REPEAT) {
+ if (really_decode) {
+ /* Handle any special formatting. */
+ switch(rec->special_fmt) {
+ case NCP_FMT_NONE:
+ func = padd_normal;
+ break;
+ case NCP_FMT_NW_DATE:
+ func = padd_date;
+ break;
+ case NCP_FMT_NW_TIME:
+ func = padd_time;
+ break;
+ case NCP_FMT_UNICODE:
+ func = padd_uni;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ item = func(ptvc, rec);
+
+ /* Set the value as a 'var' ? */
+ if (rec->var_index != NO_VAR) {
+ repeat_vars[rec->var_index] = get_item_value(item);
+ }
+ }
+ else {
+ /* If we don't decode the field, we
+ * better not use the value to set a var.
+ * Actually, we could, as long as we don't
+ * *use* that var; for now keep this assert in
+ * place. */
+ g_assert(rec->var_index == NO_VAR);
+ ptvcursor_advance(ptvc, rec->length);
+ }
+ }
+ else {
+ /* We do repeat this field. */
+ repeat_count = repeat_vars[rec->repeat_index];
+ if (really_decode) {
+ /* Handle any special formatting. */
+ switch(rec->special_fmt) {
+ case NCP_FMT_NONE:
+ func = padd_normal;
+ break;
+ case NCP_FMT_NW_DATE:
+ func = padd_date;
+ break;
+ case NCP_FMT_NW_TIME:
+ func = padd_time;
+ break;
+ case NCP_FMT_UNICODE:
+ func = padd_uni;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ for (i = 0; i < repeat_count; i++ ) {
+ func(ptvc, rec);
+ }
+ }
+ else {
+ for (i = 0; i < repeat_count; i++ ) {
+ ptvcursor_advance(ptvc, rec->length);
+ }
+ }
+ }
+ }
+}
+
+/* Run through the table of ptvc_record's and add info to the tree.
+ * Honor a request condition result. */
+static void
+process_ptvc_record(ptvcursor_t *ptvc, const ptvc_record *rec,
+ int *req_cond_results, gboolean really_decode,
+ const ncp_record *ncp_rec)
+{
+ gboolean decode;
+
+ while(rec->hf_ptr != NULL) {
+ decode = really_decode;
+ /* If we're supposed to decode, check the request condition
+ * results to see if we should override this and *not* decode. */
+ if (decode && req_cond_results) {
+ if (rec->req_cond_index != NO_REQ_COND) {
+ if (req_cond_results[rec->req_cond_index] == FALSE) {
+ decode = FALSE;
+ }
+ }
+ }
+ if (decode || ncp_rec->req_cond_size_type == REQ_COND_SIZE_CONSTANT) {
+ _process_ptvc_record(ptvc, rec, req_cond_results, decode, ncp_rec);
+ }
+ rec++;
+ }
+}
+
+
+
+/* Clear the repeat_vars array. */
+static void
+clear_repeat_vars(void)
+{
+ guint i;
+
+ for (i = 0 ; i < NUM_REPEAT_VARS; i++ ) {
+ repeat_vars[i] = 0;
+ }
+}
+
+
+/* Given an error_equivalency table and a completion code, return
+ * the string representing the error. */
+static const char*
+ncp_error_string(const error_equivalency *errors, guint8 completion_code)
+{
+ while (errors->ncp_error_index != -1) {
+ if (errors->error_in_packet == completion_code) {
+ return ncp_errors[errors->ncp_error_index];
+ }
+ errors++;
+ }
+
+ return "Unknown Error Code";
+}
+
+static const ncp_record ncp1111_request =
+ { 0x01, 0x00, NO_SUBFUNC, "Create Connection Service", NCP_GROUP_CONNECTION,
+ NULL, NULL, ncp_0x2_errors, NULL, NO_REQ_COND_SIZE, NULL };
+
+static const ncp_record ncp5555_request =
+ { 0x01, 0x00, NO_SUBFUNC, "Destroy Connection Service", NCP_GROUP_CONNECTION,
+ NULL, NULL, ncp_0x2_errors, NULL, NO_REQ_COND_SIZE, NULL };
+
+static const ncp_record ncpbbbb_request =
+ { 0x01, 0x00, NO_SUBFUNC, "Server Broadcast Message", NCP_GROUP_CONNECTION,
+ NULL, NULL, ncp_0x2_errors, NULL, NO_REQ_COND_SIZE, NULL };
+
+static const ncp_record ncplip_echo =
+ { 0x01, 0x00, NO_SUBFUNC, "LIP Echo Packet", NCP_GROUP_CONNECTION,
+ NULL, NULL, ncp_0x2_errors, NULL, NO_REQ_COND_SIZE, NULL };
+
+/* Wrapper around proto_tree_free() */
+void free_proto_tree(void *tree)
+{
+ if (tree) {
+ proto_tree_free((proto_tree*) tree);
+ }
+}
+
+static guint32
+align_4(tvbuff_t *tvb, guint32 aoffset)
+{
+ if(tvb_length_remaining(tvb, aoffset) > 4 )
+ {
+ return (aoffset%4);
+ }
+ return 0;
+}
+
+static void
+get_string(tvbuff_t* tvb, guint offset, guint str_length, char *dest_buf)
+{
+ guint32 i;
+ guint16 c_char;
+ guint32 length_remaining = 0;
+
+ length_remaining = tvb_length_remaining(tvb, offset);
+ if(str_length > length_remaining || str_length > 1024)
+ {
+ strcpy(dest_buf, "String too long to process");
+ return;
+ }
+ dest_buf[0] = '\0';
+ if(str_length == 0)
+ {
+ return;
+ }
+ for ( i = 0; i < str_length; i++ )
+ {
+ c_char = tvb_get_guint8(tvb, offset );
+ if (c_char<0x20 || c_char>0x7e)
+ {
+ if (c_char != 0x00)
+ {
+ c_char = '.';
+ dest_buf[i] = c_char & 0xff;
+ }
+ else
+ {
+ i--;
+ str_length--;
+ }
+ }
+ else
+ {
+ dest_buf[i] = c_char & 0xff;
+ }
+ offset++;
+ length_remaining--;
+
+ if(length_remaining==1)
+ {
+ dest_buf[i+1] = '\0';
+ return;
+ }
+ }
+ dest_buf[i] = '\0';
+ return;
+}
+
+static void
+uni_to_string(char * data, guint32 str_length, char *dest_buf)
+{
+ guint32 i;
+ guint16 c_char;
+ guint32 length_remaining = 0;
+
+ length_remaining = str_length;
+ dest_buf[0] = '\0';
+ if(str_length == 0)
+ {
+ return;
+ }
+ for ( i = 0; i < str_length; i++ )
+ {
+ c_char = data[i];
+ if (c_char<0x20 || c_char>0x7e)
+ {
+ if (c_char != 0x00)
+ {
+ c_char = '.';
+ dest_buf[i] = c_char & 0xff;
+ }
+ else
+ {
+ i--;
+ str_length--;
+ }
+ }
+ else
+ {
+ dest_buf[i] = c_char & 0xff;
+ }
+ length_remaining--;
+
+ if(length_remaining==0)
+ {
+ dest_buf[i+1] = '\0';
+ return;
+ }
+ }
+ dest_buf[i] = '\0';
+ return;
+}
+
+/*************************************
+* Return based on % format in request
+* %d = integer in decimal format = 0
+* %x = integer in hex format = 1
+* %s = string = 2
+**************************************/
+int
+get_info_type(const gchar* check_string)
+{
+ guint length;
+ guint i;
+ char char_val;
+
+ length = strlen(check_string);
+
+ for (i = 0 ; i < length-1 ; i++ ) {
+ char_val = check_string[i+1];
+ if (check_string[i] == 0x25 && check_string[i+1] == 0x64) { /* %d Digits*/
+ return 0;
+ }
+ if ( check_string[i] == 0x78 && check_string[i+1] == 0x25 && check_string[i+2] == 0x73) { /* x%s Bytes*/
+ return 1;
+ }
+ }
+ return 2; /* Normal String */
+}
+
+static void
+process_bitfield(proto_tree *ncp_tree, tvbuff_t *tvb, nds_val *values)
+{
+ gchar flags_str[512];
+ gchar *sep;
+ proto_item *tinew;
+ proto_tree *flags_tree;
+ guint32 i;
+ guint32 bvalue = 0;
+
+ bvalue = 0x00000001;
+ flags_str[0]='\0';
+ sep="";
+ for (i = 0 ; i < (values->vlength*8); i++ ) {
+ if (values->vvalue & bvalue)
+ {
+ strcat(flags_str, sep);
+ switch(bvalue){
+ case 0x00000001:
+ strcat(flags_str, values->bit1);
+ break;
+ case 0x00000002:
+ strcat(flags_str, values->bit2);
+ break;
+ case 0x00000004:
+ strcat(flags_str, values->bit3);
+ break;
+ case 0x00000008:
+ strcat(flags_str, values->bit4);
+ break;
+ case 0x00000010:
+ strcat(flags_str, values->bit5);
+ break;
+ case 0x00000020:
+ strcat(flags_str, values->bit6);
+ break;
+ case 0x00000040:
+ strcat(flags_str, values->bit7);
+ break;
+ case 0x00000080:
+ strcat(flags_str, values->bit8);
+ break;
+ case 0x00000100:
+ strcat(flags_str, values->bit9);
+ break;
+ case 0x00000200:
+ strcat(flags_str, values->bit10);
+ break;
+ case 0x00000400:
+ strcat(flags_str, values->bit11);
+ break;
+ case 0x00000800:
+ strcat(flags_str, values->bit12);
+ break;
+ case 0x00001000:
+ strcat(flags_str, values->bit13);
+ break;
+ case 0x00002000:
+ strcat(flags_str, values->bit14);
+ break;
+ case 0x00004000:
+ strcat(flags_str, values->bit15);
+ break;
+ case 0x00008000:
+ strcat(flags_str, values->bit16);
+ break;
+ default:
+ break;
+ }
+ sep = ", ";
+ }
+ bvalue = bvalue*2;
+ }
+ if(values->vlength==4)
+ {
+ tinew = proto_tree_add_uint_format(ncp_tree, values->hfname,
+ tvb, values->voffset, values->vlength, values->vvalue, "%s 0x%08x",
+ values->vdesc, values->vvalue);
+ }
+ else
+ {
+ tinew = proto_tree_add_uint_format(ncp_tree, values->hfname,
+ tvb, values->voffset, values->vlength, values->vvalue, "%s 0x%04x",
+ values->vdesc, values->vvalue);
+ }
+ if (flags_str[0] != '\0')
+ proto_item_append_text(tinew, " - (%s)", flags_str);
+
+ flags_tree = proto_item_add_subtree(tinew, ett_nds);
+
+ bvalue = 0x00000001;
+
+ for (i = 0 ; i < (values->vlength*8); i++ ) {
+ if (values->vvalue & bvalue)
+ {
+ switch(bvalue)
+ {
+ case 0x00000001:
+ proto_tree_add_item(flags_tree, values->bit1hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000002:
+ proto_tree_add_item(flags_tree, values->bit2hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000004:
+ proto_tree_add_item(flags_tree, values->bit3hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000008:
+ proto_tree_add_item(flags_tree, values->bit4hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000010:
+ proto_tree_add_item(flags_tree, values->bit5hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000020:
+ proto_tree_add_item(flags_tree, values->bit6hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000040:
+ proto_tree_add_item(flags_tree, values->bit7hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000080:
+ proto_tree_add_item(flags_tree, values->bit8hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000100:
+ proto_tree_add_item(flags_tree, values->bit9hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000200:
+ proto_tree_add_item(flags_tree, values->bit10hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000400:
+ proto_tree_add_item(flags_tree, values->bit11hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00000800:
+ proto_tree_add_item(flags_tree, values->bit12hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00001000:
+ proto_tree_add_item(flags_tree, values->bit13hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00002000:
+ proto_tree_add_item(flags_tree, values->bit14hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00004000:
+ proto_tree_add_item(flags_tree, values->bit15hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ case 0x00008000:
+ proto_tree_add_item(flags_tree, values->bit16hfname, tvb, values->voffset, values->vlength, TRUE);
+ break;
+ default:
+ break;
+ }
+ }
+ bvalue = bvalue*2;
+ }
+}
+
+
+static void
+print_nds_values(proto_tree *vtree, tvbuff_t *tvb, guint32 syntax_type, nds_val *vvalues)
+{
+ guint32 value1 = 0;
+ guint32 value2 = 0;
+ guint32 value3 = 0;
+ guint32 value4 = 0;
+ guint32 value5 = 0;
+ guint32 value6 = 0;
+ guint32 voffset = 0;
+ guint32 icounter;
+ guint32 number_of_values = 0;
+ guint32 number_of_items = 0;
+ guint32 r;
+ proto_item *vitem;
+ proto_tree *nvtree;
+ proto_item *aditem;
+ proto_tree *adtree;
+ char *valuestr = NULL;
+ guint16 rtype = 0;
+ guint16 rstate = 0;
+ guint16 rnum = 0;
+ guint16 revent = 0;
+ gint length_remaining;
+
+ voffset = vvalues->voffset;
+ if(tvb_get_guint8(tvb, voffset) == 0x00)
+ {
+ voffset = voffset+2;
+ }
+
+ number_of_values = tvb_get_letohl(tvb, voffset);
+
+ vitem = proto_tree_add_uint_format(vtree, hf_nds_uint32value, tvb, voffset,
+ 4, number_of_values, "Number of Values: %u", number_of_values);
+
+ nvtree = proto_item_add_subtree(vitem, ett_nds);
+
+ voffset = voffset + 4;
+
+ for (icounter = 1 ; icounter <= number_of_values; icounter++ )
+ {
+ switch(syntax_type)
+ {
+ case 0x00000006: /* Case Insensitive List */
+ case 0x0000000d: /* Binary String List */
+ case 0x00000012: /* Postal Address */
+ voffset += align_4(tvb, voffset);
+ voffset = voffset+4;
+ number_of_items = tvb_get_letohl(tvb, voffset);
+ voffset = voffset+4;
+ for (r=1; r<=number_of_items; r++)
+ {
+ value1 = tvb_get_letohl(tvb, voffset);
+ voffset = voffset + 4;
+ get_string(tvb, voffset, value1, vvalues->vstring);
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value1, vvalues->vstring);
+ voffset = voffset + value1;
+ voffset += align_4(tvb, voffset);
+ }
+ break;
+ case 0x00000007: /* Boolean */
+ value1 = tvb_get_letohl(tvb, voffset); /* length of field */
+ if (value1==0)
+ {
+ vvalues->vstring = "False";
+ }
+ else
+ {
+ vvalues->vstring = "True";
+ }
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value1, vvalues->vstring);
+ voffset=voffset+8;
+ break;
+ case 0x00000009: /* Binary String */
+ case 0x00000015: /* Stream */
+ value1 = tvb_get_letohl(tvb, voffset); /* length of field */
+ length_remaining = tvb_length_remaining(tvb, voffset);
+ if(length_remaining == -1 || value1 > (guint32) length_remaining)
+ {
+ break;
+ }
+ voffset += 4;
+ proto_tree_add_bytes(nvtree, hf_value_bytes, tvb, voffset, value1, tvb_get_ptr(tvb, voffset, value1));
+ voffset += value1;
+ voffset += (value1%2);
+ break;
+ case 0x00000008: /* Signed Integer */
+ case 0x00000016: /* Counter */
+ case 0x00000018: /* Time */
+ case 0x0000001b: /* Interval */
+ value1 = tvb_get_letohl(tvb, voffset); /* length of field */
+ voffset = voffset+4;
+ value2 = tvb_get_letohl(tvb, voffset); /* Value */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ value1, value2, "Value %d", value2);
+ voffset = voffset+4;
+ break;
+ case 0x0000000b: /* Fax Number */
+ value1 = tvb_get_letohl(tvb, voffset); /* length of field */
+ voffset = voffset+4;
+ get_string(tvb, voffset, value1, vvalues->vstring);
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value1, vvalues->vstring);
+ voffset = voffset + value1;
+ voffset += align_4(tvb, voffset);
+ value2 = tvb_get_letohl(tvb, voffset); /* Bit Count */
+ voffset=voffset+4;
+ value3 = tvb_get_letohl(tvb, voffset); /* Bit length */
+ voffset = voffset+4;
+ get_string(tvb, voffset, value3, vvalues->vstring);
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value3, vvalues->vstring);
+ voffset = voffset+value3;
+ voffset += align_4(tvb, voffset);
+ break;
+ case 0x0000000c: /* Network Address */
+ value1 = tvb_get_letohl(tvb, voffset); /* length of field */
+ voffset = voffset + 4;
+ value2 = tvb_get_letohl(tvb, voffset); /* type of Protocol */
+ valuestr = match_strval(value2, nds_protocol_type);
+ if (valuestr == NULL)
+ {
+ valuestr="(Undefined Protocol)";
+ }
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ value1, value2, valuestr, value2);
+ voffset = voffset+4;
+ value3 = tvb_get_letohl(tvb, voffset); /* length of address */
+ voffset = voffset+4;
+ switch (value2)
+ {
+ case 0x00000000:
+ proto_tree_add_item(nvtree, hf_nds_net, tvb, voffset, 4, FALSE);
+ proto_tree_add_item(nvtree, hf_nds_node, tvb, voffset+4, 6, FALSE);
+ proto_tree_add_item(nvtree, hf_nds_socket, tvb, voffset+10, 2, FALSE);
+ break;
+ case 0x00000008:
+ proto_tree_add_item(nvtree, hf_nds_port, tvb, voffset, 2, FALSE);
+ value4 = tvb_get_letohl(tvb, voffset+2);
+ proto_tree_add_ipv4(nvtree, hf_add_ref_udp, tvb, voffset+2, 4, value4);
+ break;
+ case 0x00000009:
+ proto_tree_add_item(nvtree, hf_nds_port, tvb, voffset, 2, FALSE);
+ value4 = tvb_get_letohl(tvb, voffset+2);
+ proto_tree_add_ipv4(nvtree, hf_add_ref_tcp, tvb, voffset+2, 4, value4);
+ break;
+ case 0x00000001:
+ proto_tree_add_item(nvtree, hf_nds_port, tvb, voffset, 2, FALSE);
+ value4 = tvb_get_letohl(tvb, voffset+2);
+ proto_tree_add_ipv4(nvtree, hf_add_ref_ip, tvb, voffset+2, 4, value4);
+ break;
+ case 0x0000000d:
+ get_string(tvb, voffset, value3, vvalues->vstring);
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value3, vvalues->vstring);
+ break;
+ default:
+ break;
+ }
+ voffset = voffset + value3;
+ voffset += align_4(tvb, voffset);
+ break;
+ case 0x0000000f: /* File System Path */
+ value1 = tvb_get_letohl(tvb, voffset); /* length of field */
+ voffset = voffset + 4;
+ value2 = tvb_get_letohl(tvb, voffset); /* Name Space */
+ valuestr = match_strval(value2, name_space_type);
+ if (valuestr == NULL)
+ {
+ valuestr = "Unknown Name Space";
+ }
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ 4, valuestr);
+ voffset = voffset+4;
+ value3 = tvb_get_letohl(tvb, voffset); /* Length of Volume name */
+ voffset = voffset+4;
+ get_string(tvb, voffset, value3, vvalues->vstring);
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value3, vvalues->vstring);
+ voffset = voffset+value3;
+ voffset += align_4(tvb, voffset);
+ value4 = tvb_get_letohl(tvb, voffset); /* Length of Path name */
+ voffset = voffset+4;
+ get_string(tvb, voffset, value4, vvalues->vstring);
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value4, vvalues->vstring);
+ voffset = voffset+value4;
+ voffset += align_4(tvb, voffset);
+ break;
+ case 0x00000010: /* Replica Pointer */
+ value1 = tvb_get_letohl(tvb, voffset); /* length of field */
+ voffset = voffset + 4;
+ value2 = tvb_get_letohl(tvb, voffset); /* Length of Server name */
+ voffset = voffset+4;
+ get_string(tvb, voffset, value2, vvalues->vstring);
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value2, vvalues->vstring);
+ voffset = voffset+value2;
+ voffset += align_4(tvb, voffset);
+ rtype = tvb_get_letohs(tvb, voffset); /* replica type */
+ valuestr = match_strval(rtype, nds_replica_type);
+ if (valuestr == NULL)
+ {
+ valuestr="(Unknown Replica Type)";
+ }
+ proto_tree_add_string(nvtree, hf_replica_type, tvb, voffset,
+ 2, valuestr);
+ voffset = voffset+2;
+ rstate = tvb_get_letohs(tvb, voffset); /* replica state */
+ valuestr = match_strval(rstate, nds_replica_state);
+ if (valuestr == NULL)
+ {
+ valuestr="(Unknown Replica State)";
+ }
+ proto_tree_add_string(nvtree, hf_replica_state, tvb, voffset,
+ 2, valuestr);
+ voffset = voffset+2;
+ value3 = tvb_get_letohl(tvb, voffset); /* Replica number */
+ proto_tree_add_uint_format(nvtree, hf_replica_number, tvb, voffset,
+ 4, value3, "Replica Number %d", value3);
+ voffset = voffset+4;
+ if(vvalues->nds_version == 0xfe)
+ {
+ voffset += 4;
+ }
+ number_of_items = tvb_get_letohl(tvb, voffset); /* Number of Addresses */
+ aditem = proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, number_of_items, "Number of Addresses: %u", number_of_items);
+
+ adtree = proto_item_add_subtree(aditem, ett_nds);
+ voffset = voffset+4;
+ for (r=1; r <= number_of_items; r++)
+ {
+ voffset += align_4(tvb, voffset);
+ value4 = tvb_get_letohl(tvb, voffset); /* type of Protocol */
+ valuestr = match_strval(value4, nds_protocol_type);
+ if (valuestr == NULL)
+ {
+ valuestr="(Undefined Protocol)";
+ }
+ proto_tree_add_uint_format(adtree, hf_nds_uint32value, tvb, voffset,
+ 4, value4, valuestr, value4);
+ voffset = voffset+4;
+ value5 = tvb_get_letohl(tvb, voffset); /* length of address */
+ voffset = voffset+4;
+ switch (value4)
+ {
+ case 0x00000000:
+ proto_tree_add_item(adtree, hf_nds_net, tvb, voffset, 4, FALSE);
+ proto_tree_add_item(adtree, hf_nds_node, tvb, voffset+4, 6, FALSE);
+ proto_tree_add_item(adtree, hf_nds_socket, tvb, voffset+10, 2, FALSE);
+ break;
+ case 0x00000001:
+ proto_tree_add_item(adtree, hf_nds_port, tvb, voffset, 2, FALSE);
+ value6 = tvb_get_letohl(tvb, voffset+2);
+ proto_tree_add_ipv4(adtree, hf_add_ref_ip, tvb, voffset+2, 4, value6);
+ break;
+ case 0x00000008:
+ proto_tree_add_item(adtree, hf_nds_port, tvb, voffset, 2, FALSE);
+ value6 = tvb_get_letohl(tvb, voffset+2);
+ proto_tree_add_ipv4(adtree, hf_add_ref_udp, tvb, voffset+2, 4, value6);
+ break;
+ case 0x00000009:
+ proto_tree_add_item(adtree, hf_nds_port, tvb, voffset, 2, FALSE);
+ value6 = tvb_get_letohl(tvb, voffset+2);
+ proto_tree_add_ipv4(adtree, hf_add_ref_tcp, tvb, voffset+2, 4, value6);
+ break;
+ case 0x0000000d:
+ get_string(tvb, voffset, value5, vvalues->vstring);
+ proto_tree_add_string(adtree, hf_value_string, tvb, voffset,
+ value5, vvalues->vstring);
+ break;
+ default:
+ break;
+ }
+ voffset = voffset + value5;
+ }
+ voffset += align_4(tvb, voffset);
+ break;
+ case 0x00000011: /* Object ACL */
+ value1 = tvb_get_letohl(tvb, voffset); /* Length of Field */
+ voffset = voffset + 4;
+ value2 = tvb_get_letohl(tvb, voffset);
+ voffset = voffset + 4;
+ get_string(tvb, voffset, value2, vvalues->vstring); /* Unicode String */
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value2, vvalues->vstring);
+ voffset = voffset + value2;
+ voffset += align_4(tvb, voffset);
+ value3 = tvb_get_letohl(tvb, voffset);
+ voffset = voffset + 4;
+ get_string(tvb, voffset, value3, vvalues->vstring); /* Unicode Subject Name */
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value3, vvalues->vstring);
+ voffset = voffset + value3;
+ voffset += align_4(tvb, voffset);
+ value4 = tvb_get_letohl(tvb, voffset); /* Privileges */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value4, "Privileges %8x", value4);
+ voffset = voffset+4;
+ voffset += align_4(tvb, voffset);
+ break;
+ case 0x00000013: /* Time Stamp */
+ value1 = tvb_get_letohl(tvb, voffset); /* Seconds */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value1, "Lenght of Record: %d", value1);
+ voffset = voffset+4;
+ value2 = tvb_get_letohl(tvb, voffset);
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value2, "Seconds: %d", value2);
+ voffset = voffset + 4;
+ rnum = tvb_get_letohs(tvb, voffset); /* replica number */
+ proto_tree_add_uint_format(nvtree, hf_nds_rnum, tvb, voffset,
+ 2, rnum, "Replica Number: %d", rnum);
+ voffset = voffset+2;
+ revent = tvb_get_letohs(tvb, voffset); /* Event */
+ proto_tree_add_uint_format(nvtree, hf_nds_revent, tvb, voffset,
+ 2, revent, "Event: %d", revent);
+ voffset = voffset+2;
+ voffset += align_4(tvb, voffset);
+ break;
+ case 0x00000017: /* Back Link */
+ value1 = tvb_get_letohl(tvb, voffset); /* Length */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value1, "Length of Record %08x", value1);
+ voffset = voffset+4;
+ value2 = tvb_get_letohl(tvb, voffset); /* Remote ID */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value2, "Remote ID %08x", value2);
+ voffset = voffset+4;
+ value3 = tvb_get_letohl(tvb, voffset); /* Length of string */
+ voffset = voffset+4;
+ get_string(tvb, voffset, value3, vvalues->vstring);
+ proto_tree_add_string_format(nvtree, hf_value_string, tvb, voffset,
+ value3, vvalues->vstring,
+ "Server Distinguished Name - %s", vvalues->vstring);
+ voffset = voffset+value3;
+ voffset += align_4(tvb, voffset);
+ break;
+ case 0x00000019: /* Typed Name */
+ value1 = tvb_get_letohl(tvb, voffset); /* Length */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value1, "Length of Record %08x", value1);
+ voffset = voffset+4;
+ value2 = tvb_get_letohl(tvb, voffset); /* Level */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value2, "Level %d", value2);
+ voffset = voffset+4;
+ value3 = tvb_get_letohl(tvb, voffset); /* Interval */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value3, "Interval %d", value3);
+ voffset = voffset+4;
+ value4 = tvb_get_letohl(tvb, voffset); /* Distinguished Name */
+ voffset = voffset+4;
+ get_string(tvb, voffset, value4, vvalues->vstring);
+ proto_tree_add_string_format(nvtree, hf_value_string, tvb, voffset,
+ value4, vvalues->vstring,
+ "Distinguished Name - %s", vvalues->vstring);
+ voffset = voffset+value4;
+ voffset += align_4(tvb, voffset);
+ break;
+ case 0x0000001a: /* Hold */
+ value1 = tvb_get_letohl(tvb, voffset); /* Length */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value1, "Length of Record %08x", value1);
+ voffset = voffset+4;
+ value2 = tvb_get_letohl(tvb, voffset); /* Amount */
+ proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
+ 4, value2, "Amount %d", value2);
+ voffset = voffset+4;
+ value3 = tvb_get_letohl(tvb, voffset); /* Subject */
+ voffset = voffset+4;
+ get_string(tvb, voffset, value3, vvalues->vstring);
+ proto_tree_add_string_format(nvtree, hf_value_string, tvb, voffset,
+ value3, vvalues->vstring,
+ "Subject - %s", vvalues->vstring);
+ voffset = voffset+value3;
+ voffset += align_4(tvb, voffset);
+ break;
+ case 0x00000001: /* Distinguished Name */
+ case 0x00000002: /* Case Sensitive Unicode String */
+ case 0x00000003: /* Non Case Sensitive Unicode String */
+ case 0x00000004: /* Printable String */
+ case 0x00000005: /* Numeric String */
+ case 0x0000000a: /* Telephone Number */
+ case 0x0000000e: /* Email Address */
+ case 0x00000014: /* Class Name */
+ default:
+ value1 = tvb_get_letohl(tvb, voffset);
+ voffset = voffset + 4;
+ get_string(tvb, voffset, value1, vvalues->vstring);
+ proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
+ value1, vvalues->vstring);
+ voffset = voffset + value1;
+ voffset += align_4(tvb, voffset);
+ break;
+ }
+ voffset += align_4(tvb, voffset);
+ }
+ vvalues->voffset=voffset;
+return;
+}
+
+static guint32
+print_es_type(proto_tree *estree, tvbuff_t *tvb, nds_val *values, guint32 vtype, guint32 ioffset)
+{
+ guint32 value1;
+ guint32 value2;
+ guint32 value3;
+ guint32 value4;
+ guint32 value5;
+ guint32 number_of_referrals;
+ guint32 r;
+ guint32 i;
+ guint16 replica_num;
+ guint16 event_num;
+ nw_uni_t mval_buf;
+ proto_tree *nestree;
+ proto_item *nesitem;
+ proto_tree *atree;
+ proto_item *aitem;
+ char * vstring="";
+
+ strcpy(mval_buf.buffer, "");
+
+ switch (vtype)
+ {
+ case 0: /* No Specifier Type */
+ value1 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
+ 4, value1);
+ ioffset = ioffset + 4;
+ break;
+ case 1: /* Unicode String */
+ value1 = tvb_get_letohl(tvb, ioffset); /* Delimeter Set */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string_format(estree, hf_mv_string, tvb, ioffset,
+ value1, values->vstring, "Delimeter ->%s", values->vstring);
+ ioffset=ioffset + value1;
+ ioffset += align_4(tvb, ioffset);
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(estree, hf_mv_string, tvb, ioffset,
+ value2, values->vstring);
+ values->voffset=ioffset + value2;
+ ioffset = values->voffset;
+ ioffset += align_4(tvb, ioffset);
+ break;
+ case 2: /* Based */
+ value1 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ vstring = match_strval(value1, es_type);
+ if (vstring == NULL)
+ {
+ vstring = "No ES Type Found";
+ }
+ nesitem = proto_tree_add_string_format(estree, hf_es_type, tvb, ioffset,
+ 4, vstring, "Base Context Type - %s", vstring);
+ nestree = proto_item_add_subtree(nesitem, ett_nds);
+ ioffset = ioffset + 4;
+ switch (value1)
+ {
+ case 0: /* No Specifier Type */
+ value2 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ proto_tree_add_item(nestree, hf_es_value, tvb, ioffset,
+ 4, value2);
+ ioffset = ioffset + 4;
+ break;
+ case 1: /* Unicode String */
+ value2 = tvb_get_letohl(tvb, ioffset); /* Delimeter Set */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string_format(nestree, hf_mv_string, tvb, ioffset,
+ value2, values->vstring, "Delimeter ->%s", values->vstring);
+ ioffset=ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ value3 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value3, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(nestree, hf_mv_string, tvb, ioffset,
+ value3, values->vstring);
+ values->voffset=ioffset + value3;
+ ioffset = values->voffset;
+ ioffset += align_4(tvb, ioffset);
+ break;
+ case 2: /* Based */
+ break;
+ case 3: /* Hinted */
+ break;
+ case 4: /* Tuned */
+ value2 = tvb_get_letohl(tvb, ioffset); /* Count */
+ proto_tree_add_item(nestree, hf_es_rdn_count, tvb, ioffset,
+ 4, value2);
+ ioffset = ioffset + 4;
+ for (r = 1 ; r <= value2; r++ )
+ {
+ value3 = tvb_get_letohl(tvb, ioffset); /* Seconds */
+ proto_tree_add_item(nestree, hf_es_seconds, tvb, ioffset,
+ 4, value3);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(nestree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(nestree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ }
+ value4 = tvb_get_letohl(tvb, ioffset); /* Delimeter Set */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value4, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(nestree, hf_mv_string, tvb, ioffset,
+ value4, values->vstring);
+ ioffset=ioffset + value4;
+ ioffset += align_4(tvb, ioffset);
+ value5 = tvb_get_letohl(tvb, ioffset); /* RDN */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value5, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(nestree, hf_rdn_string, tvb, ioffset,
+ value5, values->vstring);
+ ioffset=ioffset + value5;
+ ioffset += align_4(tvb, ioffset);
+ break;
+ case 5: /* GUID */
+ case 6: /* ID32 */
+ case 7: /* Count */
+ default:
+ value1 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
+ 4, value1);
+ ioffset = ioffset + 4;
+ break;
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ vstring = match_strval(value1, es_type);
+ if (vstring == NULL)
+ {
+ vstring = "No ES Type Found";
+ }
+ nesitem = proto_tree_add_string_format(estree, hf_es_type, tvb, ioffset,
+ 4, vstring, "Object Name Type - %s", vstring);
+ nestree = proto_item_add_subtree(nesitem, ett_nds);
+ ioffset = ioffset + 4;
+ switch (value1)
+ {
+ case 0: /* No Specifier Type */
+ value2 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
+ 4, value2);
+ ioffset = ioffset + 4;
+ break;
+ case 1: /* Unicode String */
+ value2 = tvb_get_letohl(tvb, ioffset); /* Delimeter Set */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string_format(estree, hf_mv_string, tvb, ioffset,
+ value2, values->vstring, "Delimeter ->%s", values->vstring);
+ ioffset=ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ value3 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value3, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(estree, hf_mv_string, tvb, ioffset,
+ value3, values->vstring);
+ values->voffset=ioffset + value3;
+ ioffset = values->voffset;
+ ioffset += align_4(tvb, ioffset);
+ break;
+ case 2: /* Based */
+ break;
+ case 3: /* Hinted */
+ break;
+ case 4: /* Tuned */
+ value2 = tvb_get_letohl(tvb, ioffset); /* Count */
+ proto_tree_add_item(estree, hf_es_rdn_count, tvb, ioffset,
+ 4, value2);
+ ioffset = ioffset + 4;
+ for (r = 1 ; r <= value2; r++ )
+ {
+ value3 = tvb_get_letohl(tvb, ioffset); /* Seconds */
+ proto_tree_add_item(estree, hf_es_seconds, tvb, ioffset,
+ 4, value3);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(estree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(estree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ }
+ value4 = tvb_get_letohl(tvb, ioffset); /* Delimeter Set */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value4, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(estree, hf_mv_string, tvb, ioffset,
+ value4, values->vstring);
+ ioffset=ioffset + value4;
+ ioffset += align_4(tvb, ioffset);
+ value5 = tvb_get_letohl(tvb, ioffset); /* RDN */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value5, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(estree, hf_rdn_string, tvb, ioffset,
+ value5, values->vstring);
+ ioffset=ioffset + value5;
+ ioffset += align_4(tvb, ioffset);
+ break;
+ case 5: /* GUID */
+ case 6: /* ID32 */
+ case 7: /* Count */
+ default:
+ value1 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
+ 4, value1);
+ ioffset = ioffset + 4;
+ break;
+ }
+ break;
+ case 3: /* Hinted */
+ number_of_referrals = tvb_get_letohl(tvb, ioffset);
+
+ for (r = 1 ; r <= number_of_referrals; r++ )
+ {
+ aitem = proto_tree_add_uint_format(estree, hf_referral_record, tvb, 6, 0,
+ r, "NDS Referral Record #%u", r);
+ atree = proto_item_add_subtree(aitem, ett_nds);
+
+ value1 = tvb_get_letohl(tvb, ioffset);
+
+ proto_tree_add_uint_format(atree, hf_referral_addcount, tvb, ioffset, 4,
+ value1, "Number of Addresses in Referral - %d", value1);
+
+ ioffset = ioffset + 4;
+ for (i = 1 ; i <= value1; i++ )
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ values->vstring = match_strval(value2, nds_protocol_type);
+ if (values->vstring == NULL)
+ {
+ values->vstring="(Undefined Protocol)";
+ }
+ proto_tree_add_uint_format(atree, hf_nds_uint32value, tvb, ioffset,
+ 4, value2, vstring, value2);
+ ioffset = ioffset+4;
+ value3 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset+4;
+ switch (value2)
+ {
+ case 0x00000000:
+ proto_tree_add_item(atree, hf_nds_net, tvb, ioffset, 4, FALSE);
+ proto_tree_add_item(atree, hf_nds_node, tvb, ioffset+4, 6, FALSE);
+ proto_tree_add_item(atree, hf_nds_socket, tvb, ioffset+10, 2, FALSE);
+ break;
+ case 0x00000001:
+ proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, FALSE);
+ value4 = tvb_get_letohl(tvb, ioffset+2);
+ proto_tree_add_ipv4(atree, hf_add_ref_ip, tvb, ioffset+2, 4, value4);
+ break;
+ case 0x00000008:
+ proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, FALSE);
+ value4 = tvb_get_letohl(tvb, ioffset+2);
+ proto_tree_add_ipv4(atree, hf_add_ref_udp, tvb, ioffset+2, 4, value4);
+ break;
+ case 0x00000009:
+ proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, FALSE);
+ value4 = tvb_get_letohl(tvb, ioffset+2);
+ proto_tree_add_ipv4(atree, hf_add_ref_tcp, tvb, ioffset+2, 4, value4);
+ break;
+ case 0x0000000d:
+ get_string(tvb, ioffset, value3, values->vstring);
+ proto_tree_add_string(atree, hf_value_string, tvb, ioffset,
+ value3, values->vstring);
+ break;
+ default:
+ break;
+ }
+ ioffset = ioffset + value3;
+ ioffset += align_4(tvb, ioffset);
+ }
+
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ vstring = match_strval(value1, es_type);
+ if (vstring == NULL)
+ {
+ vstring = "No ES Type Found";
+ }
+ nesitem = proto_tree_add_string_format(estree, hf_es_type, tvb, ioffset,
+ 4, vstring, "Object Name Type - %s", vstring);
+ nestree = proto_item_add_subtree(nesitem, ett_nds);
+ ioffset = ioffset + 4;
+ switch (value1)
+ {
+ case 0: /* No Specifier Type */
+ value2 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
+ 4, value2);
+ ioffset = ioffset + 4;
+ break;
+ case 1: /* Unicode String */
+ value2 = tvb_get_letohl(tvb, ioffset); /* Delimeter Set */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string_format(estree, hf_mv_string, tvb, ioffset,
+ value2, values->vstring, "Delimeter ->%s", values->vstring);
+ ioffset=ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ value3 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value3, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(estree, hf_mv_string, tvb, ioffset,
+ value3, values->vstring);
+ values->voffset=ioffset + value3;
+ ioffset = values->voffset;
+ ioffset += align_4(tvb, ioffset);
+ break;
+ case 2: /* Based */
+ break;
+ case 3: /* Hinted */
+ break;
+ case 4: /* Tuned */
+ value2 = tvb_get_letohl(tvb, ioffset); /* Count */
+ proto_tree_add_item(estree, hf_es_rdn_count, tvb, ioffset,
+ 4, value2);
+ ioffset = ioffset + 4;
+ for (r = 1 ; r <= value2; r++ )
+ {
+ value3 = tvb_get_letohl(tvb, ioffset); /* Seconds */
+ proto_tree_add_item(estree, hf_es_seconds, tvb, ioffset,
+ 4, value3);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(estree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(estree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ }
+ value4 = tvb_get_letohl(tvb, ioffset); /* Delimeter Set */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value4, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(estree, hf_mv_string, tvb, ioffset,
+ value4, values->vstring);
+ ioffset=ioffset + value4;
+ ioffset += align_4(tvb, ioffset);
+ value5 = tvb_get_letohl(tvb, ioffset); /* RDN */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value5, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(estree, hf_rdn_string, tvb, ioffset,
+ value5, values->vstring);
+ ioffset=ioffset + value5;
+ ioffset += align_4(tvb, ioffset);
+ break;
+ case 5: /* GUID */
+ case 6: /* ID32 */
+ case 7: /* Count */
+ default:
+ value1 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
+ 4, value1);
+ ioffset = ioffset + 4;
+ break;
+ }
+ break;
+ case 4: /* Tuned */
+ value1 = tvb_get_letohl(tvb, ioffset); /* Count */
+ proto_tree_add_item(estree, hf_es_rdn_count, tvb, ioffset,
+ 4, value1);
+ ioffset = ioffset + 4;
+ for (r = 1 ; r <= value1; r++ )
+ {
+ value2 = tvb_get_letohl(tvb, ioffset); /* Seconds */
+ proto_tree_add_item(estree, hf_es_seconds, tvb, ioffset,
+ 4, value2);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(estree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(estree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ }
+ value3 = tvb_get_letohl(tvb, ioffset); /* Delimeter Set */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value3, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(estree, hf_mv_string, tvb, ioffset,
+ value3, values->vstring);
+ ioffset=ioffset + value3;
+ ioffset += align_4(tvb, ioffset);
+ value4 = tvb_get_letohl(tvb, ioffset); /* RDN */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value4, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(estree, hf_rdn_string, tvb, ioffset,
+ value4, values->vstring);
+ ioffset=ioffset + value4;
+ ioffset += align_4(tvb, ioffset);
+ break;
+ case 5: /* GUID */
+ case 6: /* ID32 */
+ case 7: /* Count */
+ default:
+ value1 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
+ 4, value1);
+ ioffset = ioffset + 4;
+ break;
+ }
+ return ioffset;
+}
+
+static void
+process_multivalues(proto_tree *ncp_tree, tvbuff_t *tvb, nds_val *values)
+{
+ guint32 i;
+ guint32 r;
+ guint32 ioffset = 0;
+ guint32 value1 = 0;
+ guint32 value2 = 0;
+ guint8 value3 = 0;
+ guint32 value4 = 0;
+ gint value5 = 0;
+ guint32 value6 = 0;
+ guint32 value7 = 0;
+ char * valuestr = "";
+ proto_tree *ntree;
+ proto_tree *atree;
+ proto_item *nitem;
+ proto_item *aitem;
+ guint32 number_of_referrals = 0;
+ nw_uni_t mval_buf;
+ proto_tree *estree;
+ proto_item *esitem;
+ guint16 replica_num = 0;
+ guint16 event_num = 0;
+ guint32 bvalue=0;
+ nds_val temp_values;
+ proto_tree *sub1tree;
+ proto_item *sub1item;
+ proto_tree *sub2tree;
+ proto_item *sub2item;
+ gint length_remaining;
+
+ strcpy(mval_buf.buffer, "");
+
+ if(values->mvtype != MVTYPE_LIST_PARTITIONS)
+ {
+ nitem = proto_tree_add_uint_format(ncp_tree, values->hfname, tvb, values->voffset+ioffset,
+ values->vlength, values->vvalue, values->vdesc, values->vvalue);
+ }
+ else
+ {
+ nitem = proto_tree_add_string_format(ncp_tree, values->hfname, tvb, values->voffset+ioffset,
+ values->vlength, values->vdesc, "%s", values->vdesc);
+ }
+ ioffset = (values->voffset+4);
+
+ ntree = proto_item_add_subtree(nitem, ett_nds);
+
+ switch (values->mvtype)
+ {
+ case MVTYPE_ATTR_REQUEST: /* Attribute Request */
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value1, values->vstring);
+ ioffset = ioffset + value1;
+ }
+ break;
+
+ case MVTYPE_ATTR_REPLY: /* Attribute Reply */
+ switch(values->vflags)
+ {
+ case 0:
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value1, values->vstring);
+ ioffset = ioffset + value1;
+ }
+ break;
+ case 1:
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+ value1 = tvb_get_letohl(tvb, ioffset);
+ values->vstring = match_strval(value1, nds_syntax);
+ if (values->vstring == NULL)
+ {
+ values->vstring = "No Syntax Found";
+ }
+ proto_tree_add_string(ntree, hf_nds_syntax, tvb, ioffset,
+ 4, values->vstring);
+ ioffset = ioffset + 4;
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value2, values->vstring);
+ ioffset += value2;
+ ioffset += align_4(tvb, ioffset);
+ values->voffset = ioffset;
+
+ print_nds_values(ntree, tvb, value1, values);
+ ioffset = values->voffset;
+ }
+ break;
+ case 2:
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+ value1 = tvb_get_letohl(tvb, ioffset);
+ values->vstring = match_strval(value1, nds_syntax);
+ if (values->vstring == NULL)
+ {
+ values->vstring = "No Syntax Found";
+ }
+ proto_tree_add_string(ntree, hf_nds_syntax, tvb, ioffset,
+ 4, values->vstring);
+ ioffset = ioffset + 4;
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value2, values->vstring);
+ values->voffset=ioffset + value2;
+ ioffset += value2;
+ ioffset += align_4(tvb, ioffset);
+ value3 = tvb_get_letohl(tvb, ioffset);
+
+ proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset, 4,
+ value1, "Number of Values - %d", value1);
+
+ ioffset = ioffset + 4;
+ for (r = 1 ; r <= value3; r++ )
+ {
+ ioffset += 4; /* Length = 4 */
+ value4 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint(ntree, hf_nds_privileges, tvb, ioffset,
+ values->vlength, value4);
+ ioffset = ioffset+4;
+ }
+ }
+ break;
+ case 3:
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+ value1 = tvb_get_letohl(tvb, ioffset);
+ values->vstring = match_strval(value1, nds_syntax);
+ if (values->vstring == NULL)
+ {
+ values->vstring = "No Syntax Found";
+ }
+ proto_tree_add_string(ntree, hf_nds_syntax, tvb, ioffset,
+ 4, values->vstring);
+ ioffset = ioffset + 4;
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value2, values->vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ value3 = tvb_get_letohl(tvb, ioffset);
+
+ aitem = proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset, 4,
+ value3, "Number of Values - %d", value3);
+
+ atree = proto_item_add_subtree(aitem, ett_nds);
+
+ ioffset = ioffset + 4;
+ for (r = 1 ; r <= value3; r++ )
+ {
+ ioffset += align_4(tvb, ioffset);
+ temp_values.vvalue = tvb_get_letohl(tvb, ioffset);
+ temp_values.vlength = 2;
+ temp_values.hfname = hf_nds_vflags;
+ temp_values.voffset = ioffset;
+ temp_values.vdesc = "Value Flags";
+ temp_values.bit1 = "Naming";
+ temp_values.bit1hfname = hf_bit1vflags;
+ temp_values.bit2 = "Base Class";
+ temp_values.bit2hfname = hf_bit2vflags;
+ temp_values.bit3 = "Present";
+ temp_values.bit3hfname = hf_bit3vflags;
+ temp_values.bit4 = "Value Damaged";
+ temp_values.bit4hfname = hf_bit4vflags;
+ temp_values.bit5 = "Not Defined";
+ temp_values.bit5hfname = hf_bit5vflags;
+ temp_values.bit6 = "Not Defined";
+ temp_values.bit6hfname = hf_bit6vflags;
+ temp_values.bit7 = "Not Defined";
+ temp_values.bit7hfname = hf_bit7vflags;
+ temp_values.bit8 = "Not Defined";
+ temp_values.bit8hfname = hf_bit8vflags;
+ temp_values.bit9 = "Not Defined";
+ temp_values.bit9hfname = hf_bit9vflags;
+ temp_values.bit10 = "Not Defined";
+ temp_values.bit10hfname = hf_bit10vflags;
+ temp_values.bit11 = "Not Defined";
+ temp_values.bit11hfname = hf_bit11vflags;
+ temp_values.bit12 = "Not Defined";
+ temp_values.bit12hfname = hf_bit12vflags;
+ temp_values.bit13 = "Not Defined";
+ temp_values.bit13hfname = hf_bit13vflags;
+ temp_values.bit14 = "Not Defined";
+ temp_values.bit14hfname = hf_bit14vflags;
+ temp_values.bit15 = "Not Defined";
+ temp_values.bit15hfname = hf_bit15vflags;
+ temp_values.bit16 = "Not Defined";
+ temp_values.bit16hfname = hf_bit16vflags;
+ process_bitfield(atree, tvb, &temp_values);
+ ioffset = ioffset + 4;
+ value4 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(atree, hf_es_seconds, tvb, ioffset,
+ 4, value4, "Seconds %d", value4);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(atree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(atree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ value5 = tvb_get_letohl(tvb, ioffset); /* length of field */
+ if(value5 > tvb_length_remaining(tvb, ioffset))
+ {
+ break;
+ }
+ ioffset += 4;
+ proto_tree_add_bytes(atree, hf_value_bytes, tvb, ioffset, value5, tvb_get_ptr(tvb, ioffset, value5));
+ ioffset += value5;
+ ioffset += (value5%2);
+ }
+ }
+ break;
+ case 4:
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+ value1 = tvb_get_letohl(tvb, ioffset);
+ values->vstring = match_strval(value1, nds_syntax);
+ if (values->vstring == NULL)
+ {
+ values->vstring = "No Syntax Found";
+ }
+ proto_tree_add_string(ntree, hf_nds_syntax, tvb, ioffset,
+ 4, values->vstring);
+ ioffset = ioffset + 4;
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value2, values->vstring);
+ ioffset = ioffset + value2;
+ value3 = tvb_get_letohl(tvb, ioffset);
+
+ proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset, 4,
+ value3, "Number of Values - %d", value3);
+
+ ioffset = ioffset + 4;
+ for (r = 1 ; r <= value3; r++ )
+ {
+ ioffset += align_4(tvb, ioffset);
+ temp_values.vvalue = tvb_get_letohl(tvb, ioffset);
+ temp_values.vlength = 2;
+ temp_values.hfname = hf_nds_vflags;
+ temp_values.voffset = ioffset;
+ temp_values.vdesc = "Value Flags";
+ temp_values.bit1 = "Naming";
+ temp_values.bit1hfname = hf_bit1vflags;
+ temp_values.bit2 = "Base Class";
+ temp_values.bit2hfname = hf_bit2vflags;
+ temp_values.bit3 = "Present";
+ temp_values.bit3hfname = hf_bit3vflags;
+ temp_values.bit4 = "Value Damaged";
+ temp_values.bit4hfname = hf_bit4vflags;
+ temp_values.bit5 = "Not Defined";
+ temp_values.bit5hfname = hf_bit5vflags;
+ temp_values.bit6 = "Not Defined";
+ temp_values.bit6hfname = hf_bit6vflags;
+ temp_values.bit7 = "Not Defined";
+ temp_values.bit7hfname = hf_bit7vflags;
+ temp_values.bit8 = "Not Defined";
+ temp_values.bit8hfname = hf_bit8vflags;
+ temp_values.bit9 = "Not Defined";
+ temp_values.bit9hfname = hf_bit9vflags;
+ temp_values.bit10 = "Not Defined";
+ temp_values.bit10hfname = hf_bit10vflags;
+ temp_values.bit11 = "Not Defined";
+ temp_values.bit11hfname = hf_bit11vflags;
+ temp_values.bit12 = "Not Defined";
+ temp_values.bit12hfname = hf_bit12vflags;
+ temp_values.bit13 = "Not Defined";
+ temp_values.bit13hfname = hf_bit13vflags;
+ temp_values.bit14 = "Not Defined";
+ temp_values.bit14hfname = hf_bit14vflags;
+ temp_values.bit15 = "Not Defined";
+ temp_values.bit15hfname = hf_bit15vflags;
+ temp_values.bit16 = "Not Defined";
+ temp_values.bit16hfname = hf_bit16vflags;
+ process_bitfield(ntree, tvb, &temp_values);
+ ioffset = ioffset + 4;
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_es_seconds, tvb, ioffset,
+ 4, value1, "Seconds %d", value1);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(ntree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(ntree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint(ntree, hf_nds_value_len, tvb, ioffset,
+ 4, value1);
+ ioffset = ioffset + 4;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case MVTYPE_ATTR_REQUEST2: /* Attribute Request */
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset,
+ 4, value1, "Value %d", value1);
+ ioffset = ioffset + value1;
+ }
+ break;
+
+ case MVTYPE_ADD_ATTR_REQUEST: /* Add Attribute Request */
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value1, values->vstring);
+ ioffset = ioffset + value1;
+ ioffset += align_4(tvb, ioffset);
+ values->voffset = ioffset;
+ print_nds_values(ntree, tvb, 9, values);
+ ioffset = values->voffset;
+ }
+ break;
+
+ case MVTYPE_READ_CLASS_REQ: /* Read Class Request */
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_base, tvb, ioffset,
+ value1, values->vstring);
+ values->mvtype = 1;
+ ioffset = ioffset + value1;
+ }
+ break;
+
+ case MVTYPE_READ_REPLICAS: /* Read Replicas */
+ for (i = 1 ; i <= values->vvalue; i++ )
+ {
+
+ bvalue = 0x00000001;
+
+ for (r = 0 ; r < 9; r++ )
+ {
+
+ if (values->vflags & bvalue)
+ {
+ switch(bvalue)
+ {
+ case 0x00000001: /*p3values.bit1 = "Output Flags"*/
+ temp_values.vvalue = tvb_get_letohl(tvb, ioffset);
+ temp_values.vlength = 2;
+ temp_values.hfname = hf_nds_rflags;
+ temp_values.voffset = ioffset;
+ temp_values.vdesc = "Output Flags";
+ temp_values.bit1 = values->bit1;
+ temp_values.bit1hfname = hf_bit1outflags;
+ temp_values.bit2 = values->bit2;
+ temp_values.bit2hfname = hf_bit2outflags;
+ temp_values.bit3 = values->bit3;
+ temp_values.bit3hfname = hf_bit3outflags;
+ temp_values.bit4 = values->bit4;
+ temp_values.bit4hfname = hf_bit4outflags;
+ temp_values.bit5 = values->bit5;
+ temp_values.bit5hfname = hf_bit5outflags;
+ temp_values.bit6 = values->bit6;
+ temp_values.bit6hfname = hf_bit6outflags;
+ temp_values.bit7 = values->bit7;
+ temp_values.bit7hfname = hf_bit7outflags;
+ temp_values.bit8 = values->bit8;
+ temp_values.bit8hfname = hf_bit8outflags;
+ temp_values.bit9 = values->bit9;
+ temp_values.bit9hfname = hf_bit9outflags;
+ temp_values.bit10 = "Not Defined";
+ temp_values.bit10hfname = hf_bit10outflags;
+ temp_values.bit11 = "Not Defined";
+ temp_values.bit11hfname = hf_bit11outflags;
+ temp_values.bit12 = "Not Defined";
+ temp_values.bit12hfname = hf_bit12outflags;
+ temp_values.bit13 = "Not Defined";
+ temp_values.bit13hfname = hf_bit13outflags;
+ temp_values.bit14 = "Not Defined";
+ temp_values.bit14hfname = hf_bit14outflags;
+ temp_values.bit15 = "Not Defined";
+ temp_values.bit15hfname = hf_bit15outflags;
+ temp_values.bit16 = "Not Defined";
+ temp_values.bit16hfname = hf_bit16outflags;
+ process_bitfield(ntree, tvb, &temp_values);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000002: /*p3values.bit2 = "Entry ID"*/
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_eid, tvb, ioffset,
+ 4, value1, "Entry ID %08x", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000004: /*p3values.bit3 = "Replica State"*/
+ value1 = tvb_get_letohl(tvb, ioffset);
+ temp_values.vstring = match_strval(value1, nds_replica_state);
+ if (temp_values.vstring == NULL)
+ {
+ temp_values.vstring = "No Replica State Found";
+ }
+ proto_tree_add_string(ntree, hf_replica_state, tvb, ioffset,
+ 4, temp_values.vstring);
+ ioffset = ioffset + 4;
+ break;
+ case 0x0000008: /*p3values.bit4 = "Modification Timestamp"*/
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_es_seconds, tvb, ioffset,
+ 4, value1, "Seconds %d", value1);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(ntree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(ntree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ break;
+ case 0x00000010: /*p3values.bit5 = "Purge Time"*/
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Purge Time %d", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000020: /*p3values.bit6 = "Local Partition ID"*/
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_local_partition, tvb, ioffset,
+ 4, value1, "Local Partition ID %08x", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000040: /*p3values.bit7 = "Distinguished Name"*/
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_name, tvb, ioffset,
+ value1, temp_values.vstring);
+ ioffset = ioffset + value1;
+ break;
+ case 0x00000080: /*p3values.bit8 = "Replica Type & State"*/
+ value1 = tvb_get_letohl(tvb, ioffset);
+ value2 = value1 & 0x00ff;
+ temp_values.vstring = match_strval(value2, nds_replica_type);
+ if (temp_values.vstring == NULL)
+ {
+ temp_values.vstring = "No Replica Type Found";
+ }
+ proto_tree_add_string(ntree, hf_replica_type, tvb, ioffset,
+ 4, temp_values.vstring);
+ value3 = value1 & 0xff00;
+ temp_values.vstring = match_strval(value3, nds_replica_state);
+ if (temp_values.vstring == NULL)
+ {
+ temp_values.vstring = "No Replica State Found";
+ }
+ proto_tree_add_string(ntree, hf_replica_state, tvb, ioffset,
+ 4, temp_values.vstring);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000100: /*p3values.bit9 = "Partition Busy"*/
+ value1 = tvb_get_letohs(tvb, ioffset);
+ proto_tree_add_boolean(ntree, hf_partition_busy, tvb, ioffset, 4, value1);
+ ioffset += 4;
+ break;
+ default:
+ break;
+
+ }
+ }
+ bvalue = bvalue*2;
+ ioffset += align_4(tvb, ioffset);
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ }
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ }
+ break;
+
+ case MVTYPE_MODIFY_ATTR_REQUEST: /* Modify Attribute Request */
+ for (i = 0 ; i < values->vvalue; i++ )
+ {
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ valuestr = match_strval(value1, nds_kind_of_changes);
+ if (valuestr == NULL)
+ {
+ valuestr="(Kind Change Not Found)";
+ }
+ proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset,
+ values->vlength, value1, valuestr, value1);
+ ioffset = ioffset+4;
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer); /* Name of Attribute */
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ if(value1 != 1 && value1 != 6)
+ {
+ values->voffset = ioffset;
+ print_nds_values(ntree, tvb, 9, values);
+ ioffset = values->voffset;
+ }
+ }
+ break;
+
+ case MVTYPE_ADDR_REFERRAL_REQUEST: /* Address Referral Request */
+ for (i = 0 ; i < values->vvalue; i++ )
+ {
+
+ value1 = tvb_get_letohl(tvb, ioffset);
+ valuestr = match_strval(value1, nds_protocol_type);
+ if (valuestr == NULL)
+ {
+ valuestr="(Undefined Protocol)";
+ }
+ proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset,
+ values->vlength, value1, valuestr, value1);
+ ioffset = ioffset+4;
+ }
+ break;
+
+ case MVTYPE_ADDR_REFERRAL_REPLY: /* Address Referral Reply */
+ number_of_referrals = values->vvalue;
+
+ for (r = 1 ; r <= number_of_referrals; r++ )
+ {
+ aitem = proto_tree_add_uint_format(ntree, hf_referral_record, tvb, 6, 0,
+ r, "NDS Referral Record #%u", r);
+ atree = proto_item_add_subtree(aitem, ett_nds);
+
+ value1 = tvb_get_letohl(tvb, ioffset);
+
+ proto_tree_add_uint_format(atree, hf_referral_addcount, tvb, ioffset, 4,
+ value1, "Number of Addresses in Referral - %d", value1);
+
+ ioffset = ioffset + 4;
+ for (i = 1 ; i <= value1; i++ )
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ valuestr = match_strval(value2, nds_protocol_type);
+ if (valuestr == NULL)
+ {
+ valuestr="(Undefined Protocol)";
+ }
+ proto_tree_add_uint_format(atree, hf_nds_uint32value, tvb, ioffset,
+ values->vlength, value2, valuestr, value2);
+ ioffset = ioffset+4;
+ value3 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset+4;
+ switch (value2)
+ {
+ case 0x00000000:
+ proto_tree_add_item(atree, hf_nds_net, tvb, ioffset, 4, FALSE);
+ proto_tree_add_item(atree, hf_nds_node, tvb, ioffset+4, 6, FALSE);
+ proto_tree_add_item(atree, hf_nds_socket, tvb, ioffset+10, 2, FALSE);
+ break;
+ case 0x00000001:
+ proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, FALSE);
+ value4 = tvb_get_letohl(tvb, ioffset+2);
+ proto_tree_add_ipv4(atree, hf_add_ref_ip, tvb, ioffset+2, 4, value4);
+ break;
+ case 0x00000008:
+ proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, FALSE);
+ value4 = tvb_get_letohl(tvb, ioffset+2);
+ proto_tree_add_ipv4(atree, hf_add_ref_udp, tvb, ioffset+2, 4, value4);
+ break;
+ case 0x00000009:
+ proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, FALSE);
+ value4 = tvb_get_letohl(tvb, ioffset+2);
+ proto_tree_add_ipv4(atree, hf_add_ref_tcp, tvb, ioffset+2, 4, value4);
+ break;
+ case 0x0000000d:
+ get_string(tvb, ioffset, value3, values->vstring);
+ proto_tree_add_string(atree, hf_value_string, tvb, ioffset,
+ value3, values->vstring);
+ break;
+ default:
+ break;
+ }
+ ioffset = ioffset + value3;
+ ioffset += align_4(tvb, ioffset);
+ }
+
+ }
+ break;
+
+ case MVTYPE_LOC_ADDR_REFERRAL_REPLY: /* Local Address Referral Reply */
+ number_of_referrals = values->vvalue;
+
+ for (r = 1 ; r <= number_of_referrals; r++ )
+ {
+ aitem = proto_tree_add_uint_format(ntree, hf_referral_record, tvb, 6, 0,
+ r, "NDS Referral Record #%u", r);
+ atree = proto_item_add_subtree(aitem, ett_nds);
+
+ value2 = tvb_get_letohl(tvb, ioffset);
+ valuestr = match_strval(value2, nds_protocol_type);
+ if (valuestr == NULL)
+ {
+ valuestr="(Undefined Protocol)";
+ }
+ proto_tree_add_uint_format(atree, hf_nds_uint32value, tvb, ioffset,
+ values->vlength, value2, valuestr, value2);
+ ioffset = ioffset+4;
+ value3 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset+4;
+
+ switch (value2)
+ {
+ case 0x00000000:
+ proto_tree_add_item(atree, hf_nds_net, tvb, ioffset, 4, FALSE);
+ proto_tree_add_item(atree, hf_nds_node, tvb, ioffset+4, 6, FALSE);
+ proto_tree_add_item(atree, hf_nds_socket, tvb, ioffset+10, 2, FALSE);
+ break;
+ case 0x00000001:
+ proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, FALSE);
+ ioffset=ioffset+2;
+ value4 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_ipv4(atree, hf_add_ref_ip, tvb, ioffset, 4, value4);
+ break;
+ case 0x00000008:
+ proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, FALSE);
+ ioffset=ioffset+2;
+ value4 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_ipv4(atree, hf_add_ref_udp, tvb, ioffset, 4, value4);
+ break;
+ case 0x00000009:
+ proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, FALSE);
+ ioffset=ioffset+2;
+ value4 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_ipv4(atree, hf_add_ref_tcp, tvb, ioffset, 4, value4);
+ break;
+ case 0x0000000d:
+ get_string(tvb, ioffset, value3, values->vstring);
+ proto_tree_add_string(atree, hf_value_string, tvb, ioffset,
+ value3, values->vstring);
+ break;
+ default:
+ break;
+ }
+ ioffset = ioffset + value3;
+ ioffset += align_4(tvb, ioffset);
+ }
+ break;
+
+ case MVTYPE_PROC_ENTRY_SPECIFIERS: /* Process Entry Specifiers */
+ value2 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ values->vstring = match_strval(value2, es_type);
+ if (values->vstring == NULL)
+ {
+ values->vstring = "No ES Type Found";
+ }
+ esitem = proto_tree_add_string_format(ntree, hf_es_type, tvb, ioffset,
+ 4, values->vstring, "Output Entry Specifier - %s", values->vstring);
+ estree = proto_item_add_subtree(esitem, ett_nds);
+ ioffset = ioffset + 4;
+ ioffset = print_es_type(estree, tvb, values, value2, ioffset);
+ value3 = tvb_get_letohl(tvb, ioffset); /* ES Type */
+ values->vstring = match_strval(value3, es_type);
+ if (values->vstring == NULL)
+ {
+ values->vstring = "No ES Type Found";
+ }
+ esitem = proto_tree_add_string_format(ntree, hf_es_type, tvb, ioffset,
+ 4, values->vstring, "Input Entry Specifier - %s", values->vstring);
+ estree = proto_item_add_subtree(esitem, ett_nds);
+ ioffset = ioffset + 4;
+ ioffset = print_es_type(estree, tvb, values, value3, ioffset);
+ value4 = tvb_get_letohl(tvb, ioffset);
+ aitem = proto_tree_add_uint_format(ntree, hf_referral_record, tvb, ioffset, 4,
+ value4, "Referral Protocols - %d", value4);
+ atree = proto_item_add_subtree(aitem, ett_nds);
+ ioffset += 4;
+ for (i = 0 ; i < value4; i++ )
+ {
+ value5 = tvb_get_letohl(tvb, ioffset);
+ valuestr = match_strval(value5, nds_protocol_type);
+ if (valuestr == NULL)
+ {
+ valuestr="(Undefined Protocol)";
+ }
+ proto_tree_add_string_format(atree, hf_value_string, tvb, ioffset,
+ 4, valuestr, "Protocol -> %s", valuestr);
+ ioffset = ioffset+4;
+ }
+ value6 = tvb_get_letohl(tvb, ioffset);
+ aitem = proto_tree_add_uint_format(ntree, hf_referral_record, tvb, ioffset, 4,
+ value6, "Tree Walking Protocols - %d", value6);
+ atree = proto_item_add_subtree(aitem, ett_nds);
+ ioffset += 4;
+ for (i = 0 ; i < value6; i++ )
+ {
+ value7 = tvb_get_letohl(tvb, ioffset);
+ valuestr = match_strval(value7, nds_protocol_type);
+ if (valuestr == NULL)
+ {
+ valuestr="(Undefined Protocol)";
+ }
+ proto_tree_add_string_format(atree, hf_value_string, tvb, ioffset,
+ 4, valuestr, "Protocol -> %s", valuestr);
+ ioffset = ioffset+4;
+ }
+ break;
+
+ case MVTYPE_PRINT_TIMESTAMP: /* Print Timestamp */
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(ncp_tree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(ncp_tree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ /* fall through */
+
+ case MVTYPE_LIST_PARTITIONS: /* List Partitions */
+ number_of_referrals = values->vvalue;
+ for (i = 0; i < number_of_referrals; i++)
+ {
+ bvalue = 0x00000001;
+
+ for (r = 0 ; r < 32; r++ )
+ {
+ if (values->vflags & bvalue)
+ {
+ switch(bvalue)
+ {
+ case 0x00000001: /* Information Flags */
+ temp_values.vvalue = tvb_get_letohs(tvb, ioffset);
+ temp_values.vtype = VTYPE_BITFIELD;
+ temp_values.vstring = mval_buf.buffer;
+ temp_values.vdesc = "Information Flags (low) Byte:";
+ temp_values.vlength = 2;
+ temp_values.hfname= hf_nds_rflags;
+ temp_values.voffset = ioffset;
+ temp_values.bit1 = "Output Flags";
+ temp_values.bit1hfname = hf_bit1infoflagsl;
+ temp_values.bit2 = "Entry ID";
+ temp_values.bit2hfname = hf_bit2infoflagsl;
+ temp_values.bit3 = "Entry Flags";
+ temp_values.bit3hfname = hf_bit3infoflagsl;
+ temp_values.bit4 = "Subordinate Count";
+ temp_values.bit4hfname = hf_bit4infoflagsl;
+ temp_values.bit5 = "Modification Time";
+ temp_values.bit5hfname = hf_bit5infoflagsl;
+ temp_values.bit6 = "Modification Timestamp";
+ temp_values.bit6hfname = hf_bit6infoflagsl;
+ temp_values.bit7 = "Creation Timestamp";
+ temp_values.bit7hfname = hf_bit7infoflagsl;
+ temp_values.bit8 = "Partition Root ID";
+ temp_values.bit8hfname = hf_bit8infoflagsl;
+ temp_values.bit9 = "Parent ID";
+ temp_values.bit9hfname = hf_bit9infoflagsl;
+ temp_values.bit10 = "Revision Count";
+ temp_values.bit10hfname = hf_bit10infoflagsl;
+ temp_values.bit11 = "Replica Type";
+ temp_values.bit11hfname = hf_bit11infoflagsl;
+ temp_values.bit12 = "Base Class";
+ temp_values.bit12hfname = hf_bit12infoflagsl;
+ temp_values.bit13 = "Relative Distinguished Name";
+ temp_values.bit13hfname = hf_bit13infoflagsl;
+ temp_values.bit14 = "Distinguished Name";
+ temp_values.bit14hfname = hf_bit14infoflagsl;
+ temp_values.bit15 = "Root Distinguished Name";
+ temp_values.bit15hfname = hf_bit15infoflagsl;
+ temp_values.bit16 = "Parent Distinguished Name";
+ temp_values.bit16hfname = hf_bit16infoflagsl;
+ process_bitfield(ntree, tvb, &temp_values);
+ ioffset = ioffset+2;
+ temp_values.vvalue = tvb_get_letohs(tvb, ioffset);
+ temp_values.vtype = VTYPE_BITFIELD;
+ temp_values.vstring = mval_buf.buffer;
+ temp_values.vdesc = "Information Flags (high) Byte:";
+ temp_values.vlength = 2;
+ temp_values.hfname= hf_nds_rflags;
+ temp_values.voffset = ioffset;
+ temp_values.bit1 = "Purge Time";
+ temp_values.bit1hfname = hf_bit1infoflagsh;
+ temp_values.bit2 = "Dereference Base Class";
+ temp_values.bit2hfname = hf_bit2infoflagsh;
+ temp_values.bit3 = "Not Defined";
+ temp_values.bit3hfname = hf_bit3infoflagsh;
+ temp_values.bit4 = "Not Defined";
+ temp_values.bit4hfname = hf_bit4infoflagsh;
+ temp_values.bit5 = "Not Defined";
+ temp_values.bit5hfname = hf_bit5infoflagsh;
+ temp_values.bit6 = "Not Defined";
+ temp_values.bit6hfname = hf_bit6infoflagsh;
+ temp_values.bit7 = "Not Defined";
+ temp_values.bit7hfname = hf_bit7infoflagsh;
+ temp_values.bit8 = "Not Defined";
+ temp_values.bit8hfname = hf_bit8infoflagsh;
+ temp_values.bit9 = "Not Defined";
+ temp_values.bit9hfname = hf_bit9infoflagsh;
+ temp_values.bit10 = "Not Defined";
+ temp_values.bit10hfname = hf_bit10infoflagsh;
+ temp_values.bit11 = "Not Defined";
+ temp_values.bit11hfname = hf_bit11infoflagsh;
+ temp_values.bit12 = "Not Defined";
+ temp_values.bit12hfname = hf_bit12infoflagsh;
+ temp_values.bit13 = "Not Defined";
+ temp_values.bit13hfname = hf_bit13infoflagsh;
+ temp_values.bit14 = "Not Defined";
+ temp_values.bit14hfname = hf_bit14infoflagsh;
+ temp_values.bit15 = "Not Defined";
+ temp_values.bit15hfname = hf_bit15infoflagsh;
+ temp_values.bit16 = "Not Defined";
+ temp_values.bit16hfname = hf_bit16infoflagsh;
+ process_bitfield(ntree, tvb, &temp_values);
+ ioffset = ioffset+2;
+ break;
+ case 0x00000002: /* Entry ID */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_eid, tvb, ioffset,
+ 4, value1, "Entry ID %08x", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000004: /* Entry Flags */
+ temp_values.vvalue = tvb_get_letohl(tvb, ioffset);
+ temp_values.vtype = VTYPE_BITFIELD;
+ temp_values.vstring = mval_buf.buffer;
+ temp_values.vdesc = "Entry Flags:";
+ temp_values.vlength = 2;
+ temp_values.hfname= hf_nds_eflags;
+ temp_values.voffset = ioffset;
+ temp_values.bit1 = "Alias Entry";
+ temp_values.bit1hfname = hf_bit1eflags;
+ temp_values.bit2 = "Partition Root";
+ temp_values.bit2hfname = hf_bit2eflags;
+ temp_values.bit3 = "Container Entry";
+ temp_values.bit3hfname = hf_bit3eflags;
+ temp_values.bit4 = "Container Alias";
+ temp_values.bit4hfname = hf_bit4eflags;
+ temp_values.bit5 = "Matches List Filter";
+ temp_values.bit5hfname = hf_bit5eflags;
+ temp_values.bit6 = "Reference Entry";
+ temp_values.bit6hfname = hf_bit6eflags;
+ temp_values.bit7 = "40x Reference Entry";
+ temp_values.bit7hfname = hf_bit7eflags;
+ temp_values.bit8 = "Back Linked";
+ temp_values.bit8hfname = hf_bit8eflags;
+ temp_values.bit9 = "New Entry";
+ temp_values.bit9hfname = hf_bit9eflags;
+ temp_values.bit10 = "Temporary Reference";
+ temp_values.bit10hfname = hf_bit10eflags;
+ temp_values.bit11 = "Audited";
+ temp_values.bit11hfname = hf_bit11eflags;
+ temp_values.bit12 = "Entry Not Present";
+ temp_values.bit12hfname = hf_bit12eflags;
+ temp_values.bit13 = "Entry Verify CTS";
+ temp_values.bit13hfname = hf_bit13eflags;
+ temp_values.bit14 = "Entry Damaged";
+ temp_values.bit14hfname = hf_bit14eflags;
+ temp_values.bit15 = "Not Defined";
+ temp_values.bit15hfname = hf_bit15eflags;
+ temp_values.bit16 = "Not Defined";
+ temp_values.bit16hfname = hf_bit16eflags;
+ process_bitfield(ntree, tvb, &temp_values);
+ ioffset = ioffset+4;
+ break;
+ case 0x0000008: /* Subordinate Count */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_sub_count, tvb, ioffset,
+ 4, value1, "Subordinate Count %d", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x0000010: /* Modification Time */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_es_seconds, tvb, ioffset,
+ 4, value1, "Modification Time in Seconds %d", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x0000020: /* Modification Timestamp */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_es_seconds, tvb, ioffset,
+ 4, value1, "Modification Timestamp Seconds %d", value1);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(ntree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(ntree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ break;
+ case 0x0000040: /* Creation Timestamp */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_es_seconds, tvb, ioffset,
+ 4, value1, "Creation Timestamp Seconds %d", value1);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(ntree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(ntree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ break;
+ case 0x00000080: /* Partition Root ID */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_partition_root_id, tvb, ioffset,
+ 4, value1, "Partition Root ID %08x", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000100: /* Parent ID */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_parent, tvb, ioffset,
+ 4, value1, "Parent ID %08x", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000200: /* Revision Count */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_revision, tvb, ioffset,
+ 4, value1, "Revision Count %d", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000400: /* Replica Type & State */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ value2 = value1 & 0x00ff;
+ temp_values.vstring = match_strval(value2, nds_replica_type);
+ if (temp_values.vstring == NULL)
+ {
+ temp_values.vstring = "No Replica Type Found";
+ }
+ proto_tree_add_string(ntree, hf_replica_type, tvb, ioffset,
+ 4, temp_values.vstring);
+ value3 = value1 & 0xff00;
+ temp_values.vstring = match_strval(value3, nds_replica_state);
+ if (temp_values.vstring == NULL)
+ {
+ temp_values.vstring = "No Replica State Found";
+ }
+ proto_tree_add_string(ntree, hf_replica_state, tvb, ioffset,
+ 4, temp_values.vstring);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00000800: /* Base Class */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_base, tvb, ioffset,
+ value1, temp_values.vstring);
+ ioffset = ioffset + value1;
+ break;
+ case 0x00001000: /* Relative Distinguished Name */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_relative_dn, tvb, ioffset,
+ value1, temp_values.vstring);
+ ioffset = ioffset + value1;
+ break;
+ case 0x00002000: /* Distinguished Name */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_name, tvb, ioffset,
+ value1, temp_values.vstring);
+ ioffset = ioffset + value1;
+ break;
+ case 0x00004000: /* Root Distinguished Name */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_name, tvb, ioffset,
+ value1, temp_values.vstring);
+ ioffset = ioffset + value1;
+ break;
+ case 0x00008000: /* Parent Distinguished Name */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_name, tvb, ioffset,
+ value1, temp_values.vstring);
+ ioffset = ioffset + value1;
+ break;
+ case 0x00010000: /* Purge Time */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Purge Time %d", value1);
+ ioffset = ioffset + 4;
+ break;
+ case 0x00020000: /* Dereference Base Class */
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_deref_base, tvb, ioffset,
+ value1, temp_values.vstring);
+ ioffset = ioffset + value1;
+ break;
+ default:
+ break;
+
+ }
+ ioffset += align_4(tvb, ioffset);
+ }
+ bvalue = bvalue*2;
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ }
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ }
+ break;
+
+ case MVTYPE_CLASS_NAMES: /* Class Names */
+ number_of_referrals = values->vvalue;
+ for (i = 0; i < number_of_referrals; i++)
+ {
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ sub1item = proto_tree_add_string(ntree, hf_nds_base_class, tvb, ioffset,
+ value1, temp_values.vstring);
+ sub1tree = proto_item_add_subtree(sub1item, ett_nds);
+ ioffset = ioffset + value1;
+ ioffset += align_4(tvb, ioffset);
+ if(values->vflags != 0)
+ {
+ temp_values.vvalue = tvb_get_letohl(tvb, ioffset);
+ temp_values.vtype = VTYPE_BITFIELD;
+ temp_values.vstring = mval_buf.buffer;
+ temp_values.vdesc = "Class Flags:";
+ temp_values.vlength = 2;
+ temp_values.hfname= hf_nds_cflags;
+ temp_values.voffset = ioffset;
+ temp_values.bit1 = "Ambiguous Containment";
+ temp_values.bit1hfname = hf_bit1cflags;
+ temp_values.bit2 = "Ambiguous Naming";
+ temp_values.bit2hfname = hf_bit2cflags;
+ temp_values.bit3 = "Class Definition Cannot be Removed";
+ temp_values.bit3hfname = hf_bit3cflags;
+ temp_values.bit4 = "Effective Class";
+ temp_values.bit4hfname = hf_bit4cflags;
+ temp_values.bit5 = "Container Class";
+ temp_values.bit5hfname = hf_bit5cflags;
+ temp_values.bit6 = "Not Defined";
+ temp_values.bit6hfname = hf_bit6cflags;
+ temp_values.bit7 = "Not Defined";
+ temp_values.bit7hfname = hf_bit7cflags;
+ temp_values.bit8 = "Not Defined";
+ temp_values.bit8hfname = hf_bit8cflags;
+ temp_values.bit9 = "Not Defined";
+ temp_values.bit9hfname = hf_bit9cflags;
+ temp_values.bit10 = "Not Defined";
+ temp_values.bit10hfname = hf_bit10cflags;
+ temp_values.bit11 = "Not Defined";
+ temp_values.bit11hfname = hf_bit11cflags;
+ temp_values.bit12 = "Not Defined";
+ temp_values.bit12hfname = hf_bit12cflags;
+ temp_values.bit13 = "Not Defined";
+ temp_values.bit13hfname = hf_bit13cflags;
+ temp_values.bit14 = "Not Defined";
+ temp_values.bit14hfname = hf_bit14cflags;
+ temp_values.bit15 = "Not Defined";
+ temp_values.bit15hfname = hf_bit15cflags;
+ temp_values.bit16 = "Not Defined";
+ temp_values.bit16hfname = hf_bit16cflags;
+ process_bitfield(sub1tree, tvb, &temp_values);
+ ioffset = ioffset+4;
+ if(values->vflags != 5)
+ {
+ value1 = tvb_get_letohl(tvb, ioffset); /* length of field */
+ length_remaining = tvb_length_remaining(tvb, ioffset);
+ if(length_remaining == -1 || value1 > (guint32) length_remaining)
+ {
+ break;
+ }
+ ioffset += 4;
+ proto_tree_add_bytes(sub1tree, hf_nds_asn1, tvb, ioffset, value1, tvb_get_ptr(tvb, ioffset, value1));
+ ioffset += value1;
+ ioffset += (value1%2);
+ }
+ if(values->vflags == 1 || values->vflags == 2 || values->vflags == 4)
+ {
+ value1 = tvb_get_letohl(tvb, ioffset); /* Super Classes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Super Classes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_nds_super, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Containment Classes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Containment Classes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_nds_base_class, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Naming Attributes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Naming Attributes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Mandatory Attributes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Mandatory Attributes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Optional Attributes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Optional Attributes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ ioffset += align_4(tvb, ioffset);
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ }
+ }
+ /*if(values->vflags == 2 || values->vflags == 4)*/ /* Class Definitions of Super Classes */
+ if(values->vflags == 4) /* Class Definitions of Super Classes */
+ {
+ value1 = tvb_get_letohl(tvb, ioffset); /* Containment Classes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Containment Classes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_nds_base_class, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Naming Attributes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Naming Attributes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Mandatory Attributes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Mandatory Attributes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Optional Attributes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Optional Attributes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Default ACL */
+ proto_tree_add_uint_format(sub1tree, hf_nds_eid, tvb, ioffset,
+ 4, value1, "Default ACL %08x", value1);
+ ioffset = ioffset + 4;
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ }
+ if(values->vflags == 5) /* Base Class Definitions */
+ {
+ value1 = tvb_get_letohl(tvb, ioffset); /* Creation Timestamp */
+ proto_tree_add_uint_format(sub1tree, hf_es_seconds, tvb, ioffset,
+ 4, value1, "Creation Timestamp Seconds %d", value1);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(sub1tree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(sub1tree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ value1 = tvb_get_letohl(tvb, ioffset); /* Modification Timestamp */
+ proto_tree_add_uint_format(sub1tree, hf_es_seconds, tvb, ioffset,
+ 4, value1, "Modification Timestamp Seconds %d", value1);
+ ioffset = ioffset + 4;
+ replica_num = tvb_get_letohs(tvb, ioffset); /* Replica */
+ proto_tree_add_item(sub1tree, hf_nds_replica_num, tvb, ioffset,
+ 2, replica_num);
+ ioffset = ioffset + 2;
+ event_num = tvb_get_letohs(tvb, ioffset); /* Event */
+ proto_tree_add_item(sub1tree, hf_nds_event_num, tvb, ioffset,
+ 2, event_num);
+ ioffset = ioffset + 2;
+ /* Class Definition */
+ value1 = tvb_get_letohl(tvb, ioffset); /* Super Classes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Super Classes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_nds_super, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Containment Classes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Containment Classes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_nds_base_class, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Naming Attributes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Naming Attributes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Mandatory Attributes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Mandatory Attributes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Optional Attributes */
+ sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_purge, tvb, ioffset,
+ 4, value1, "Optional Attributes %d", value1);
+ sub2tree = proto_item_add_subtree(sub2item, ett_nds);
+ ioffset = ioffset + 4;
+ for (r = 0; r < value1; r++)
+ {
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ temp_values.vstring = mval_buf.buffer;
+ proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
+ value2, temp_values.vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ }
+ value1 = tvb_get_letohl(tvb, ioffset); /* Default ACL */
+ proto_tree_add_uint_format(sub1tree, hf_nds_eid, tvb, ioffset,
+ 4, value1, "Default ACL %08x", value1);
+ ioffset = ioffset + 4;
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case MVTYPE_MODIFY_CLASS: /* Modify Class */
+ for (i = 1 ; i <= values->vvalue; i++ ) /* Attribute Names to add*/
+ {
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value1, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value1, values->vstring);
+ ioffset = ioffset + value1;
+ }
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_att_del, tvb, ioffset,
+ 4, value1, "Attribute Names to Delete %d", value1);
+ ioffset = ioffset + 4;
+ for (i = 1 ; i <= value1; i++ ) /* Attribute Names to delete*/
+ {
+ ioffset += align_4(tvb, ioffset);
+ value2 = tvb_get_letohl(tvb, ioffset);
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
+ value2, values->vstring);
+ ioffset = ioffset + value2;
+ }
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_acl_add, tvb, ioffset,
+ 4, value1, "ACL Templates to Add %d", value1);
+ ioffset = ioffset + 4;
+ for (i = 1 ; i <= value1; i++ ) /* ACL templates to add*/
+ {
+ ioffset += align_4(tvb, ioffset);
+ value2 = tvb_get_letohl(tvb, ioffset); /* Attribute Name */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_attribute_dn, tvb, ioffset,
+ value2, values->vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ value2 = tvb_get_letohl(tvb, ioffset); /* DN of Trustee */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_trustee_dn, tvb, ioffset,
+ value2, values->vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_privileges, tvb, ioffset,
+ 4, value1, "Priviledges 0x%08x", value1);
+ ioffset = ioffset + 4;
+ }
+ if(tvb_length_remaining(tvb, ioffset) < 4 )
+ {
+ break;
+ }
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset);
+ proto_tree_add_uint_format(ntree, hf_nds_acl_del, tvb, ioffset,
+ 4, value1, "ACL Templates to Delete %d", value1);
+ ioffset = ioffset + 4;
+ for (i = 1 ; i <= value1; i++ ) /* ACL templates to delete*/
+ {
+ ioffset += align_4(tvb, ioffset);
+ value2 = tvb_get_letohl(tvb, ioffset); /* Attribute Name */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_attribute_dn, tvb, ioffset,
+ value2, values->vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ value2 = tvb_get_letohl(tvb, ioffset); /* DN of Trustee */
+ ioffset = ioffset + 4;
+ get_string(tvb, ioffset, value2, mval_buf.buffer);
+ values->vstring = mval_buf.buffer;
+ proto_tree_add_string(ntree, hf_nds_trustee_dn, tvb, ioffset,
+ value2, values->vstring);
+ ioffset = ioffset + value2;
+ ioffset += align_4(tvb, ioffset);
+ value1 = tvb_get_letohl(tvb, ioffset); /* Priviledges */
+ proto_tree_add_uint_format(ntree, hf_nds_privileges, tvb, ioffset,
+ 4, value1, "Priviledges 0x%08x", value1);
+ ioffset = ioffset + 4;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Defrag logic
+ *
+ * NDS fragment not being set to 0xffffffff indicates we are inside or at the
+ * beginning of a fragment. But when the end of the fragment
+ * is encounterd the flag is set to 0xffffffff. So we must mark what the
+ * frame number is of the end fragment so that we will be
+ * able to redissect if the user clicks on the packet
+ * or resorts/filters the trace.
+ *
+ * Once we are certain that we are in a fragment sequence
+ * then we can just process each fragment in this conversation
+ * until we reach the fragment == 0xffffffff packet.
+ *
+ * We will be able to easily determine if a conversation is a fragment
+ * with the exception of the last packet in the fragment. So remember
+ * the last fragment packet number.
+ *
+ * Also the NDS dissection requires the values of NDS Verb, Version, and Flags.
+ * Without this values being remembered from the first request packet then
+ * we will be unable to dissect the reply packet. For this reason we remember
+ * these values on the first fragment and then populate the values in the final
+ * fragment. We only do this on the first dissection.
+ *
+ * XXX - this has several problems:
+ *
+ * 1) it uses global variables ("frags");
+ *
+ * 2) the sequence numbers don't start at a fixed value, they're
+ * per-connection sequence numbers;
+ *
+ * 3) the fragment size and handle aren't put into the protocol
+ * tree for fragments other than the last fragment.
+ *
+ * 2) needs to be fixed by having a way of doing defragmentation using
+ * connection sequence numbers; that's needed for fragmentation in
+ * connection-oriented protocols, e.g. COTP, as well.
+ * That might let us fix 1) as well.
+ *
+ * 3) should be fixed by putting that into the protocol tree ourselves
+ * if this isn't the first fragment.
+*/
+void
+nds_defrag(tvbuff_t *tvb, packet_info *pinfo, guint16 nw_connection, guint8 sequence, guint16 type, proto_tree *tree)
+{
+ int i, frag_count=0;
+ guint len=0;
+ guint32 tid = 1;
+ tvbuff_t *frag_tvb = NULL;
+ fragment_data *fd_head;
+ ncp_req_hash_value *request_value = NULL;
+ conversation_t *conversation;
+ guint32 nds_frag;
+
+ for (i = 0; i < 9; i++) {
+ if (!frags[i].nds_fragmented)
+ {
+ frags[i].nds_frag = 0xfffffff0;
+ }
+ }
+ /* Check to see if defragmentation is enabeled in the dissector */
+ if (!nds_defragment) {
+ dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree);
+ return;
+ }
+ /* Has this already been dissected? */
+ if (!pinfo->fd->flags.visited) {
+ /* Find the conversation whence the request would have come. */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, nw_connection, nw_connection, 0);
+ if (conversation != NULL) {
+ /* find the record telling us the request made that caused
+ this reply */
+ request_value = ncp_hash_lookup(conversation, sequence);
+ if (!request_value) {
+ dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree);
+ return;
+ }
+ p_add_proto_data(pinfo->fd, proto_ncp, (void*) request_value);
+ }
+ /* else... we haven't seen an NCP Request for that conversation and sequence. */
+ else
+ {
+ dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree);
+ return;
+ }
+ }
+ else {
+ request_value = p_get_proto_data(pinfo->fd, proto_ncp);
+ if (!request_value) {
+ dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree);
+ return;
+ }
+ }
+ /* Validate that this is an NDS packet */
+ /* If this isn't an NDS packet then just return */
+ if (!request_value->ncp_rec ||
+ request_value->ncp_rec->func!=104 || request_value->ncp_rec->subfunc!=2) {
+ dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree);
+ return;
+ }
+ /* Get the fragment flag */
+ nds_frag = tvb_get_letohl(tvb, 12);
+
+ /* Now we need to find if this is a new fragment or already one defined. */
+ /* We currently limit the maximum number of simultaneous fragments to 100. */
+ for (i=0; i<100; i++)
+ {
+ if (frags[i].nds_frag == nds_frag || frags[i].nds_frag == 0xfffffff0)
+ {
+ if (frags[i].nds_frag == 0xfffffff0)
+ {
+ frags[i].nds_length = 0;
+ frags[i].nds_frag = nds_frag;
+ frags[i].nds_fragmented = TRUE;
+ }
+ break;
+ }
+ }
+ frag_count = i;
+
+ /* is this the end of an existing fragment or just another reply */
+ if (nds_frag == 0xffffffff && request_value->nds_frag_num == 0xffffffff)
+ {
+ dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree);
+ return;
+ }
+
+ /* Now we process the fragments */
+ if (request_value->nds_frag || (request_value->nds_end_frag == pinfo->fd->num))
+ {
+ /* Check to see of this is a fragment. If so then mark as a fragment. */
+ if (frags[frag_count].nds_frag==0xffffffff) {
+ request_value->nds_frag = FALSE;
+ /* nds_length of 0 means start of fragment */
+ frags[frag_count].nds_length = 0;
+ }
+ else
+ {
+ if (frags[frag_count].nds_length == 0)
+ {
+ frags[frag_count].nds_length = tvb_get_letohl(tvb, 0);
+ }
+ }
+ /*
+ * Fragment
+ *
+ */
+ tid = (pinfo->srcport+pinfo->destport);
+ len = tvb_reported_length(tvb);
+ if (len > 0 && tvb_bytes_exist(tvb, 0, len))
+ {
+ if (frags[frag_count].nds_length > len)
+ {
+ /* This is the first fragment so remember the verb, version, and flags. */
+ frags[frag_count].nds_frag_verb = request_value->nds_request_verb;
+ frags[frag_count].nds_frag_version = request_value->nds_version;
+ frags[frag_count].nds_frag_flags = request_value->req_nds_flags;
+ fd_head = fragment_add_seq_next(tvb, 0, pinfo, tid, nds_fragment_table, nds_reassembled_table, len, request_value->nds_frag);
+ frags[frag_count].nds_length = 1;
+ }
+ else
+ {
+ /* Subsequent fragments should be offset by 16 since we do not need */
+ /* the additional fragment handle and size fields in our composite data */
+ fd_head = fragment_add_seq_next(tvb, 16, pinfo, tid, nds_fragment_table, nds_reassembled_table, len-16, request_value->nds_frag);
+ }
+ if (fd_head != NULL)
+ {
+ /* Is this the last fragment? nds_frag will indicate */
+ if (fd_head->next != NULL && !request_value->nds_frag)
+ {
+ frag_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->len, fd_head->len);
+ tvb_set_child_real_data_tvbuff(tvb,
+ frag_tvb);
+ add_new_data_source(pinfo,
+ frag_tvb,
+ "Reassembled NDS");
+ /* Show all fragments. */
+ if (tree)
+ {
+ show_fragment_seq_tree(fd_head,
+ &nds_frag_items,
+ tree, pinfo,
+ frag_tvb);
+ tid++;
+ }
+
+ if (!pinfo->fd->flags.visited)
+ {
+ /* Now we need to find the original fragment number. */
+ /* Get the fragment flag */
+ nds_frag = tvb_get_letohl(frag_tvb, 12);
+ for (i=0; i<100; i++)
+ {
+ if (frags[i].nds_frag == nds_frag)
+ {
+ break;
+ }
+ }
+ if (frags[i].nds_frag == 0xffffffff)
+ {
+ /* Error can't find fragment */
+ /*g_assert(0);*/
+ }
+ frag_count = i;
+ /* Remember this fragment information so we can dissect.
+ * Only do this on the first dissection. After the first
+ * dissection we will just read the memory values.
+ */
+ request_value->nds_end_frag = pinfo->fd->num;
+ request_value->nds_request_verb = frags[frag_count].nds_frag_verb;
+ request_value->nds_version = frags[frag_count].nds_frag_version;
+ request_value->req_nds_flags = frags[frag_count].nds_frag_flags;
+ }
+
+ }
+ else
+ {
+ /* This is either a beggining or middle fragment on second dissection */
+ frag_tvb = tvb_new_subset(tvb, 0, -1, -1);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (request_value->nds_frag)
+ {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "[NDS Fragment %08x]", frags[frag_count].nds_frag);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Fragment from first pass of dissection */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (request_value->nds_frag)
+ {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "[NDS Fragment %08x]", frags[frag_count].nds_frag);
+ }
+ }
+ frag_tvb = NULL;
+ }
+ }
+ else
+ {
+ /*
+ * There are no bytes so Dissect this
+ */
+ frag_tvb = tvb_new_subset(tvb, 0, -1, -1);
+ }
+ if (frag_tvb == NULL)
+ {
+ /* This is a fragment packet */
+ frag_tvb = tvb_new_subset (tvb, 0, -1, -1);
+ nds_data_handle = find_dissector("data");
+ call_dissector(nds_data_handle, frag_tvb, pinfo, tree);
+ }
+ else
+ {
+ /* This is the end fragment so dissect */
+ if (!request_value->nds_frag) {
+ frags[frag_count].nds_length = 0;
+ dissect_ncp_reply(frag_tvb, pinfo, nw_connection, sequence, type, tree);
+ }
+ }
+ }
+ else
+ {
+ /* This is not any fragment packet */
+ frags[frag_count].nds_length = 0;
+ request_value->nds_frag = FALSE;
+ dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree);
+ }
+}
+
+void
+dissect_ncp_request(tvbuff_t *tvb, packet_info *pinfo,
+ guint16 nw_connection, guint8 sequence,
+ guint16 type, proto_tree *ncp_tree)
+{
+ guint8 func, subfunc = 0;
+ gboolean requires_subfunc = FALSE;
+ gboolean has_length = FALSE;
+ ncp_req_hash_value *request_value = NULL;
+ const ncp_record *ncp_rec = NULL;
+ conversation_t *conversation;
+ ptvcursor_t *ptvc = NULL;
+ proto_tree *temp_tree = NULL;
+ gboolean run_req_cond = FALSE;
+ gboolean run_info_str = FALSE;
+ guint32 length_remaining;
+ guint32 testvar;
+
+ func = tvb_get_guint8(tvb, 6);
+
+ /* Determine which ncp_record to use. */
+ switch (type) {
+ case NCP_ALLOCATE_SLOT:
+ length_remaining = tvb_length_remaining(tvb, 4);
+ if (length_remaining > 4)
+ {
+ testvar = tvb_get_ntohl(tvb, 4);
+ if( testvar == 0x4c495020)
+ {
+ ncp_rec = &ncplip_echo;
+ }
+ else
+ {
+ ncp_rec = &ncp1111_request;
+ }
+ }
+ else
+ {
+ ncp_rec = &ncp1111_request;
+ }
+ break;
+ case NCP_SERVICE_REQUEST:
+ requires_subfunc = ncp_requires_subfunc(func);
+ has_length = ncp_has_length_parameter(func);
+ if (requires_subfunc) {
+ if (has_length) {
+ subfunc = tvb_get_guint8(tvb, 9);
+ }
+ else {
+ subfunc = tvb_get_guint8(tvb, 7);
+ }
+ }
+ ncp_rec = ncp_record_find(func, subfunc);
+ break;
+ case NCP_DEALLOCATE_SLOT:
+ ncp_rec = &ncp5555_request;
+ break;
+ case NCP_BROADCAST_SLOT:
+ ncp_rec = &ncpbbbb_request;
+ break;
+ case NCP_LIP_ECHO:
+ ncp_rec = &ncplip_echo;
+ break;
+ default:
+ ncp_rec = NULL;
+ break;
+ }
+
+ /* Fill in the INFO column. */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (ncp_rec) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "C %s", ncp_rec->name);
+ if (ncp_rec->req_info_str) {
+ /* We want to add more stuff to the Info
+ column. */
+ run_info_str = TRUE;
+ }
+ }
+ else {
+ if (requires_subfunc) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "C Unknown Function %u %u (0x%02X/0x%02x)",
+ func, subfunc, func, subfunc);
+ }
+ else {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "C Unknown Function %u (0x%02x)",
+ func, func);
+ }
+ }
+ }
+
+ if (!pinfo->fd->flags.visited) {
+ /* This is the first time we've looked at this packet.
+ Keep track of the address and connection whence the request
+ came, and the address and connection to which the request
+ is being sent, so that we can match up calls with replies.
+ (We don't include the sequence number, as we may want
+ to have all packets over the same connection treated
+ as being part of a single conversation so that we can
+ let the user select that conversation to be displayed.) */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, nw_connection, nw_connection, 0);
+
+ if (conversation == NULL) {
+ /* It's not part of any conversation - create a new one. */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ PT_NCP, nw_connection, nw_connection, 0);
+ }
+ request_value = ncp_hash_insert(conversation, sequence, ncp_rec);
+ request_value->req_frame_num = pinfo->fd->num;
+ request_value->req_frame_time.secs=pinfo->fd->abs_secs;
+ request_value->req_frame_time.nsecs=pinfo->fd->abs_usecs*1000;
+
+ /* If this is the first time we're examining the packet,
+ * check to see if this NCP type uses a "request condition".
+ * If so, we have to build a proto_tree because request conditions
+ * use display filters to work, and without a proto_tree,
+ * display filters can't possibly work. */
+ if (ncp_rec) {
+ if (ncp_rec->req_cond_indexes) {
+ run_req_cond = TRUE;
+ }
+ }
+ }
+
+ /* If we have to handle a request condition, or have to
+ add to the Info column, we need to construct a protocol
+ tree. If we already have a proto_tree, then wonderful.
+ If we don't, we need to build one. */
+ if ((run_info_str || run_req_cond) && !ncp_tree) {
+ proto_item *ti;
+
+ temp_tree = proto_tree_create_root();
+ proto_tree_set_visible(temp_tree, FALSE);
+ ti = proto_tree_add_item(temp_tree, proto_ncp, tvb, 0, -1, FALSE);
+ ncp_tree = proto_item_add_subtree(ti, ett_ncp);
+ }
+
+ if (ncp_tree) {
+ /* If the dissection throws an exception, be sure to free
+ * the temporary proto_tree that was created. Because of the
+ * way the CLEANUP_PUSH macro works, we can't put it in an 'if'
+ * block; it has to be in the same scope as the terminating
+ * CLEANUP_POP or CLEANUP_POP_AND_ALLOC. So, we always
+ * call CLEANUP_POP and friends, but the value of temp_tree is
+ * NULL if no cleanup is needed, and non-null if cleanup is needed. */
+ CLEANUP_PUSH(free_proto_tree, temp_tree);
+
+ /* Before the dissection, if we're saving data for a request
+ * condition, we have to prime the proto tree using the
+ * dfilter information */
+ if (run_req_cond) {
+ const int *needed;
+ dfilter_t *dfilter;
+
+ needed = ncp_rec->req_cond_indexes;
+
+ while (*needed != -1) {
+ dfilter = req_conds[*needed].dfilter;
+ /* Prime the proto_tree with "interesting fields". */
+ dfilter_prime_proto_tree(dfilter, ncp_tree);
+ needed++;
+ }
+ }
+
+ /* Before the dissection, if we need a field for the info_str,
+ * prime the tree. */
+ if (run_info_str) {
+ proto_tree_prime_hfid(ncp_tree, *ncp_rec->req_info_str->hf_ptr);
+ }
+
+ switch (type) {
+ case NCP_BROADCAST_SLOT:
+ ; /* nothing */
+ break;
+
+ case NCP_SERVICE_REQUEST:
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_func, tvb, 6, 1,
+ func, "Function: %u (0x%02X), %s",
+ func, func, ncp_rec ? ncp_rec->name : "Unknown");
+ break;
+
+ default:
+ ; /* nothing */
+ break;
+ }
+
+ if (requires_subfunc) {
+ if (has_length) {
+ proto_tree_add_item(ncp_tree, hf_ncp_length, tvb, 7,
+ 2, FALSE);
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_subfunc, tvb, 9, 1,
+ subfunc, "SubFunction: %u (0x%02x)",
+ subfunc, subfunc);
+ ptvc = ptvcursor_new(ncp_tree, tvb, 10);
+ }
+ else {
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_subfunc, tvb, 7, 1,
+ subfunc, "SubFunction: %u (0x%02x)",
+ subfunc, subfunc);
+ ptvc = ptvcursor_new(ncp_tree, tvb, 8);
+ }
+ }
+ else {
+ ptvc = ptvcursor_new(ncp_tree, tvb, 7);
+ }
+
+ /* The group is not part of the packet, but it's useful
+ * information to display anyway. */
+ if (ncp_rec) {
+ proto_tree_add_text(ncp_tree, tvb, 0, 0, "Group: %s",
+ ncp_groups[ncp_rec->group]);
+ }
+
+ if (ncp_rec && ncp_rec->request_ptvc) {
+ clear_repeat_vars();
+ process_ptvc_record(ptvc, ncp_rec->request_ptvc, NULL, TRUE, ncp_rec);
+ }
+ ptvcursor_free(ptvc);
+ /* NMAS packets are dessected in packet-ncp-nmas.c */
+ if (func == 0x5e && ncp_tree) {
+ dissect_nmas_request(tvb, pinfo, ncp_tree, request_value);
+ }
+
+ /* Now that the dissection is done, do we need to run
+ * some display filters on the resulting tree in order
+ * to save results for "request conditions" ? */
+ if (run_req_cond) {
+ const int *needed;
+ gboolean *results;
+ dfilter_t *dfilter;
+
+ results = g_new0(gboolean, NUM_REQ_CONDS);
+ needed = ncp_rec->req_cond_indexes;
+
+ while (*needed != -1) {
+ /* ncp_tree is not a root proto_tree, but
+ * dfilters will still work on it. */
+ dfilter = req_conds[*needed].dfilter;
+ results[*needed] = dfilter_apply(dfilter, ncp_tree);
+ needed++;
+ }
+
+ /* Save the results so the reply packet dissection
+ * get to them. */
+ request_value->req_cond_results = results;
+ }
+ /* Construct the info string if necessary */
+ if (run_info_str) {
+ GPtrArray *parray;
+ char* byte_string;
+ char non_uni_string[1024];
+ int i, len;
+ field_info *finfo;
+ int info_type;
+
+ if (!request_value)
+ {
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, nw_connection, nw_connection, 0);
+ if (conversation != NULL) {
+ /* find the record telling us the request made that caused
+ this reply */
+ request_value = ncp_hash_lookup(conversation, sequence);
+ }
+ if (!conversation || !request_value)
+ {
+ return;
+ }
+ }
+
+ parray = proto_get_finfo_ptr_array(ncp_tree,
+ *ncp_rec->req_info_str->hf_ptr);
+ len = g_ptr_array_len(parray);
+
+ if (len > 0) {
+
+ col_set_str(pinfo->cinfo, COL_INFO, "C ");
+
+ finfo = g_ptr_array_index(parray, 0);
+
+ info_type = get_info_type((const gchar*) ncp_rec->req_info_str->first_string);
+
+ if (info_type != 0) { /* Is this a string or not? */
+
+ if (info_type == 1) { /* Is this bytes? */
+ byte_string = bytes_to_str(fvalue_get(&finfo->value), fvalue_length(&finfo->value));
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ (const gchar*) ncp_rec->req_info_str->first_string,
+ byte_string);
+ }
+ else
+ {
+ if (info_type == 2) { /* Is this a String? */
+ uni_to_string(fvalue_get(&finfo->value), fvalue_length(&finfo->value), non_uni_string);
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ (const gchar*) ncp_rec->req_info_str->first_string,
+ non_uni_string);
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ (const gchar*) ncp_rec->req_info_str->first_string,
+ fvalue_get(&finfo->value));
+ }
+ }
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ (const gchar*) ncp_rec->req_info_str->first_string,
+ fvalue_get_integer(&finfo->value));
+ }
+ }
+ if (len > 1) {
+ for (i = 1; i < len; i++) {
+ non_uni_string[0]='\0';
+ finfo = g_ptr_array_index(parray, i);
+ info_type = get_info_type((const gchar*) ncp_rec->req_info_str->repeat_string);
+
+ if (info_type != 0) { /* Is this a string or not? */
+ if (info_type == 1)
+ { /* Is this bytes? */
+ byte_string = bytes_to_str(fvalue_get(&finfo->value), fvalue_length(&finfo->value));
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ (const gchar*) ncp_rec->req_info_str->repeat_string,
+ byte_string);
+ }
+ else
+ {
+ if (info_type == 2) { /* Is this a String? */
+ uni_to_string(fvalue_get(&finfo->value), fvalue_length(&finfo->value), non_uni_string);
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ (const gchar*) ncp_rec->req_info_str->repeat_string,
+ non_uni_string);
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ (const gchar*) ncp_rec->req_info_str->repeat_string,
+ fvalue_get(&finfo->value));
+ }
+ }
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ (const gchar*) ncp_rec->req_info_str->repeat_string,
+ fvalue_get_integer(&finfo->value));
+ }
+ }
+ }
+ }
+
+ /* Free the temporary proto_tree */
+ CLEANUP_CALL_AND_POP;
+ }
+}
+
+
+void
+dissect_ncp_reply(tvbuff_t *tvb, packet_info *pinfo,
+ guint16 nw_connection, guint8 sequence, guint16 type,
+ proto_tree *ncp_tree)
+{
+ conversation_t *conversation = NULL;
+ ncp_req_hash_value *request_value = NULL;
+ ncp_req_eid_hash_value *request_eid_value = NULL;
+ const ncp_record *ncp_rec = NULL;
+ int *req_cond_results;
+ guint8 completion_code=0;
+ guint length;
+ ptvcursor_t *ptvc = NULL;
+ const char *error_string;
+ guint32 nds_string_len = 0;
+ guint8 ping_version = 0;
+ guint32 nds_flags = 0;
+ guint32 nds_offset = 0;
+ nw_uni_t reply_buffer;
+ char * verb_string="";
+ guint32 nds_error_code = 0;
+ guint32 nds_reply_buffer = 0;
+ char * nds_error_string = NULL;
+ guint32 nds_frag=0;
+ nds_val pvalues[9];
+ char string_buffer[9][1024];
+ gboolean resolve_eid=FALSE;
+ guint32 global_eid=0;
+ gboolean add_eid = FALSE;
+ char global_object_name[256];
+ int i;
+ guint32 bvalue=0;
+
+ strcpy(reply_buffer.buffer, "");
+ strcpy(global_object_name, "");
+
+ if (!pinfo->fd->flags.visited) {
+ /* Find the conversation whence the request would have come. */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, nw_connection, nw_connection, 0);
+ if (conversation != NULL) {
+ /* find the record telling us the request made that caused
+ this reply */
+ request_value = ncp_hash_lookup(conversation, sequence);
+ if (request_value) {
+ ncp_rec = request_value->ncp_rec;
+ }
+ p_add_proto_data(pinfo->fd, proto_ncp, (void*) request_value);
+ }
+ /* else... we haven't seen an NCP Request for that conversation and sequence. */
+ }
+ else {
+ request_value = p_get_proto_data(pinfo->fd, proto_ncp);
+ if (request_value) {
+ ncp_rec = request_value->ncp_rec;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ if (ncp_rec && ncp_rec->func==0x68 &&
+ (ncp_rec->subfunc==0x02 || ncp_rec->subfunc==0x01)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDS");
+ }
+ }
+
+ /* A completion code of 0 always means OK. Non-zero means failure,
+ * but each non-zero value has a different meaning. And the same value
+ * can have different meanings, depending on the ncp.func (and ncp.subfunc)
+ * value. */
+ completion_code = tvb_get_guint8(tvb, 6);
+ if (completion_code == 0) {
+
+ if(type == NCP_POSITIVE_ACK)
+ {
+ error_string = "Server Busy, Request Being Processed";
+ }
+ else
+ {
+ error_string = "OK";
+ }
+ } else {
+ if (ncp_rec && ncp_rec->errors) {
+ error_string = ncp_error_string(ncp_rec->errors, completion_code);
+ }
+ else {
+ error_string = "Original Request Packet not Found";
+ }
+ }
+ if (type == NCP_SERVICE_REPLY && ncp_rec && ncp_rec->func==0x68 &&
+ ncp_rec->subfunc==0x02)
+ {
+ nds_offset = 8;
+ nds_reply_buffer = tvb_get_letohl(tvb, nds_offset);
+ nds_offset += 4;
+ nds_frag = tvb_get_letohl(tvb, nds_offset);
+ if (nds_reply_buffer > 7)
+ {
+ nds_offset += 4;
+ nds_error_code = tvb_get_letohl(tvb, nds_offset);
+ nds_error_string = match_strval(nds_error_code, nds_reply_errors);
+ if (nds_error_string == NULL)
+ {
+ nds_error_string = "NDS Error - No Definition Found";
+ }
+ if (nds_error_string == NULL || nds_error_code == 0x00000000)
+ {
+ nds_error_string = "Ok";
+ }
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ type == NCP_SERVICE_REPLY ? "R" : "ACK",
+ nds_error_string ? nds_error_string : error_string);
+ }
+
+ if (ncp_tree) {
+ if (request_value) {
+ nstime_t ns;
+
+ proto_tree_add_uint(ncp_tree, hf_ncp_req_frame_num, tvb, 0, 0,
+ request_value->req_frame_num);
+ ns.secs=pinfo->fd->abs_secs-request_value->req_frame_time.secs;
+ ns.nsecs=pinfo->fd->abs_usecs*1000-request_value->req_frame_time.nsecs;
+ if(ns.nsecs<0){
+ ns.nsecs+=1000000000;
+ ns.secs--;
+ }
+ proto_tree_add_time(ncp_tree, hf_ncp_req_frame_time, tvb, 0, 0, &ns);
+
+ }
+
+ /* Put the func (and maybe subfunc) from the request packet
+ * in the proto tree, but hidden. That way filters on ncp.func
+ * or ncp.subfunc will find both the requests and the replies.
+ */
+ if (ncp_rec) {
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_func, tvb, 6, 0,
+ ncp_rec->func, "Function: %u (0x%02X), %s",
+ ncp_rec->func, ncp_rec->func, ncp_rec->name);
+ if (ncp_requires_subfunc(ncp_rec->func)) {
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_subfunc, tvb, 6, 0,
+ ncp_rec->subfunc, "SubFunction: %u (0x%02x)",
+ ncp_rec->subfunc, ncp_rec->subfunc);
+ }
+ }
+
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_completion_code, tvb, 6, 1,
+ completion_code, "Completion Code: %d (0x%02x), %s",
+ completion_code, completion_code, error_string);
+
+ proto_tree_add_item(ncp_tree, hf_ncp_connection_status, tvb, 7, 1, FALSE);
+
+ /*
+ * Unless this is a reply, that's all there is to parse.
+ */
+ if (type != NCP_SERVICE_REPLY)
+ return;
+
+ /* Decode NDS Reply packets */
+ if (ncp_rec) {
+ /* Dissect NMAS Reply packets */
+ if (ncp_rec->func == 0x5e && request_value)
+ {
+ dissect_nmas_reply(tvb, pinfo, ncp_tree, ncp_rec->func, ncp_rec->subfunc, request_value);
+ }
+ if ((ncp_rec->func == 0x68 && ncp_rec->subfunc == 0x01) && completion_code == 0) {
+ ping_version = tvb_get_guint8(tvb, 8);
+ proto_tree_add_item(ncp_tree, hf_ping_version, tvb, 8, 1, TRUE);
+ if (ping_version == 9) {
+ nds_string_len = tvb_get_ntohl(tvb, 9);
+ nds_offset = nds_string_len+16;
+ proto_tree_add_item(ncp_tree, hf_nds_tree_name, tvb, 16, nds_string_len, FALSE);
+ proto_tree_add_item(ncp_tree, hf_nds_reply_depth, tvb, nds_offset, 4, FALSE);
+ proto_tree_add_item(ncp_tree, hf_nds_reply_rev, tvb, (nds_offset+4), 4, FALSE);
+ proto_tree_add_item(ncp_tree, hf_nds_reply_flags, tvb, (nds_offset+8), 4, TRUE);
+ }
+ else {
+ nds_offset = 12;
+ nds_flags = request_value->req_nds_flags;
+ bvalue = 0x00000001;
+
+ for (i = 0 ; i < 32; i++ ) {
+ if (nds_flags & bvalue)
+ {
+ switch(bvalue)
+ {
+ case 0x00000001: /* Supported Fields */
+ pvalues[0].vvalue = tvb_get_letohs(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_BITFIELD;
+ pvalues[0].vstring = "";
+ pvalues[0].vdesc = "Ping (low) Supported Fields:";
+ pvalues[0].vlength = 2;
+ pvalues[0].hfname= hf_nds_rflags;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].bit1 = "Supported Fields";
+ pvalues[0].bit1hfname = hf_bit1pingflags1;
+ pvalues[0].bit2 = "Depth";
+ pvalues[0].bit2hfname = hf_bit2pingflags1;
+ pvalues[0].bit3 = "Revision";
+ pvalues[0].bit3hfname = hf_bit3pingflags1;
+ pvalues[0].bit4 = "Flags";
+ pvalues[0].bit4hfname = hf_bit4pingflags1;
+ pvalues[0].bit5 = "Verification Flags";
+ pvalues[0].bit5hfname = hf_bit5pingflags1;
+ pvalues[0].bit6 = "Letter Version";
+ pvalues[0].bit6hfname = hf_bit6pingflags1;
+ pvalues[0].bit7 = "OS Version";
+ pvalues[0].bit7hfname = hf_bit7pingflags1;
+ pvalues[0].bit8 = "License Flags";
+ pvalues[0].bit8hfname = hf_bit8pingflags1;
+ pvalues[0].bit9 = "DS Time";
+ pvalues[0].bit9hfname = hf_bit9pingflags1;
+ pvalues[0].bit10 = "Not Defined";
+ pvalues[0].bit10hfname = hf_bit10pingflags1;
+ pvalues[0].bit11 = "Not Defined";
+ pvalues[0].bit11hfname = hf_bit11pingflags1;
+ pvalues[0].bit12 = "Not Defined";
+ pvalues[0].bit12hfname = hf_bit12pingflags1;
+ pvalues[0].bit13 = "Not Defined";
+ pvalues[0].bit13hfname = hf_bit13pingflags1;
+ pvalues[0].bit14 = "Not Defined";
+ pvalues[0].bit14hfname = hf_bit14pingflags1;
+ pvalues[0].bit15 = "Not Defined";
+ pvalues[0].bit15hfname = hf_bit15pingflags1;
+ pvalues[0].bit16 = "Not Defined";
+ pvalues[0].bit16hfname = hf_bit16pingflags1;
+
+ process_bitfield(ncp_tree, tvb, &pvalues[0]);
+ nds_offset += 2;
+
+ pvalues[0].vvalue = tvb_get_letohs(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_BITFIELD;
+ pvalues[0].vstring = "";
+ pvalues[0].vdesc = "Ping (high) Supported Fields:";
+ pvalues[0].vlength = 2;
+ pvalues[0].hfname= hf_nds_rflags;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].bit1 = "Sap Name";
+ pvalues[0].bit1hfname = hf_bit1pingflags2;
+ pvalues[0].bit2 = "Tree Name";
+ pvalues[0].bit2hfname = hf_bit2pingflags2;
+ pvalues[0].bit3 = "OS Name";
+ pvalues[0].bit3hfname = hf_bit3pingflags2;
+ pvalues[0].bit4 = "Hardware Name";
+ pvalues[0].bit4hfname = hf_bit4pingflags2;
+ pvalues[0].bit5 = "Vendor Name";
+ pvalues[0].bit5hfname = hf_bit5pingflags2;
+ pvalues[0].bit6 = "Not Defined";
+ pvalues[0].bit6hfname = hf_bit6pingflags2;
+ pvalues[0].bit7 = "Not Defined";
+ pvalues[0].bit7hfname = hf_bit7pingflags2;
+ pvalues[0].bit8 = "Not Defined";
+ pvalues[0].bit8hfname = hf_bit8pingflags2;
+ pvalues[0].bit9 = "Not Defined";
+ pvalues[0].bit9hfname = hf_bit9pingflags2;
+ pvalues[0].bit10 = "Not Defined";
+ pvalues[0].bit10hfname = hf_bit10pingflags2;
+ pvalues[0].bit11 = "Not Defined";
+ pvalues[0].bit11hfname = hf_bit11pingflags2;
+ pvalues[0].bit12 = "Not Defined";
+ pvalues[0].bit12hfname = hf_bit12pingflags2;
+ pvalues[0].bit13 = "Not Defined";
+ pvalues[0].bit13hfname = hf_bit13pingflags2;
+ pvalues[0].bit14 = "Not Defined";
+ pvalues[0].bit14hfname = hf_bit14pingflags2;
+ pvalues[0].bit15 = "Not Defined";
+ pvalues[0].bit15hfname = hf_bit15pingflags2;
+ pvalues[0].bit16 = "Not Defined";
+ pvalues[0].bit16hfname = hf_bit16pingflags2;
+
+ process_bitfield(ncp_tree, tvb, &pvalues[0]);
+ nds_offset += 2;
+ break;
+ case 0x00000002:
+ proto_tree_add_item(ncp_tree, hf_nds_reply_depth, tvb, nds_offset, 4, TRUE);
+ nds_offset += 4;
+ break;
+ case 0x00000004:
+ proto_tree_add_item(ncp_tree, hf_nds_reply_rev, tvb, nds_offset, 4, TRUE);
+ nds_offset += 4;
+ break;
+ case 0x00000008:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_BITFIELD;
+ pvalues[0].vstring = "";
+ pvalues[0].vdesc = "Ping Flags:";
+ pvalues[0].vlength = 4;
+ pvalues[0].hfname= hf_nds_rflags;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].bit1 = "Root Most Master Replica";
+ pvalues[0].bit1hfname = hf_bit1pingpflags1;
+ pvalues[0].bit2 = "Time Synchronized";
+ pvalues[0].bit2hfname = hf_bit2pingpflags1;
+ pvalues[0].bit3 = "Not Defined";
+ pvalues[0].bit3hfname = hf_bit3pingpflags1;
+ pvalues[0].bit4 = "Not Defined";
+ pvalues[0].bit4hfname = hf_bit4pingpflags1;
+ pvalues[0].bit5 = "Not Defined";
+ pvalues[0].bit5hfname = hf_bit5pingpflags1;
+ pvalues[0].bit6 = "Not Defined";
+ pvalues[0].bit6hfname = hf_bit6pingpflags1;
+ pvalues[0].bit7 = "Not Defined";
+ pvalues[0].bit7hfname = hf_bit7pingpflags1;
+ pvalues[0].bit8 = "Not Defined";
+ pvalues[0].bit8hfname = hf_bit8pingpflags1;
+ pvalues[0].bit9 = "Not Defined";
+ pvalues[0].bit9hfname = hf_bit9pingpflags1;
+ pvalues[0].bit10 = "Not Defined";
+ pvalues[0].bit10hfname = hf_bit10pingpflags1;
+ pvalues[0].bit11 = "Not Defined";
+ pvalues[0].bit11hfname = hf_bit11pingpflags1;
+ pvalues[0].bit12 = "Not Defined";
+ pvalues[0].bit12hfname = hf_bit12pingpflags1;
+ pvalues[0].bit13 = "Not Defined";
+ pvalues[0].bit13hfname = hf_bit13pingpflags1;
+ pvalues[0].bit14 = "Not Defined";
+ pvalues[0].bit14hfname = hf_bit14pingpflags1;
+ pvalues[0].bit15 = "Not Defined";
+ pvalues[0].bit15hfname = hf_bit15pingpflags1;
+ pvalues[0].bit16 = "Not Defined";
+ pvalues[0].bit16hfname = hf_bit16pingpflags1;
+
+ process_bitfield(ncp_tree, tvb, &pvalues[0]);
+ nds_offset += 4;
+ break;
+ case 0x00000010:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_BITFIELD;
+ pvalues[0].vstring = "";
+ pvalues[0].vdesc = "Verification Flags:";
+ pvalues[0].vlength = 4;
+ pvalues[0].hfname= hf_nds_rflags;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].bit1 = "Checksum";
+ pvalues[0].bit1hfname = hf_bit1pingvflags1;
+ pvalues[0].bit2 = "CRC32";
+ pvalues[0].bit2hfname = hf_bit2pingvflags1;
+ pvalues[0].bit3 = "Not Defined";
+ pvalues[0].bit3hfname = hf_bit3pingvflags1;
+ pvalues[0].bit4 = "Not Defined";
+ pvalues[0].bit4hfname = hf_bit4pingvflags1;
+ pvalues[0].bit5 = "Not Defined";
+ pvalues[0].bit5hfname = hf_bit5pingvflags1;
+ pvalues[0].bit6 = "Not Defined";
+ pvalues[0].bit6hfname = hf_bit6pingvflags1;
+ pvalues[0].bit7 = "Not Defined";
+ pvalues[0].bit7hfname = hf_bit7pingvflags1;
+ pvalues[0].bit8 = "Not Defined";
+ pvalues[0].bit8hfname = hf_bit8pingvflags1;
+ pvalues[0].bit9 = "Not Defined";
+ pvalues[0].bit9hfname = hf_bit9pingvflags1;
+ pvalues[0].bit10 = "Not Defined";
+ pvalues[0].bit10hfname = hf_bit10pingvflags1;
+ pvalues[0].bit11 = "Not Defined";
+ pvalues[0].bit11hfname = hf_bit11pingvflags1;
+ pvalues[0].bit12 = "Not Defined";
+ pvalues[0].bit12hfname = hf_bit12pingvflags1;
+ pvalues[0].bit13 = "Not Defined";
+ pvalues[0].bit13hfname = hf_bit13pingvflags1;
+ pvalues[0].bit14 = "Not Defined";
+ pvalues[0].bit14hfname = hf_bit14pingvflags1;
+ pvalues[0].bit15 = "Not Defined";
+ pvalues[0].bit15hfname = hf_bit15pingvflags1;
+ pvalues[0].bit16 = "Not Defined";
+ pvalues[0].bit16hfname = hf_bit16pingvflags1;
+
+ process_bitfield(ncp_tree, tvb, &pvalues[0]);
+ nds_offset += 4;
+ break;
+ case 0x00000020:
+ proto_tree_add_item(ncp_tree, hf_nds_letter_ver, tvb, nds_offset, 4, TRUE);
+ nds_offset += 4;
+ break;
+ case 0x00000040:
+ proto_tree_add_item(ncp_tree, hf_nds_os_ver, tvb, nds_offset, 4, TRUE);
+ nds_offset += 4;
+ break;
+ case 0x00000080:
+ proto_tree_add_item(ncp_tree, hf_nds_lic_flags, tvb, nds_offset, 4, TRUE);
+ nds_offset += 4;
+ break;
+ case 0x00000100:
+ proto_tree_add_item(ncp_tree, hf_nds_ds_time, tvb, nds_offset, 4, TRUE);
+ nds_offset += 4;
+ break;
+ case 0x00010000:
+ nds_string_len = tvb_get_letohl(tvb, nds_offset);
+ nds_offset += 4;
+ get_string(tvb, nds_offset, nds_string_len, reply_buffer.buffer);
+ proto_tree_add_text(ncp_tree, tvb, nds_offset, nds_string_len, "SAP Name: %s", reply_buffer.buffer);
+ nds_offset += nds_string_len;
+ nds_offset += align_4(tvb, nds_offset);
+ nds_offset += 2;
+ break;
+ case 0x00020000:
+ nds_string_len = tvb_get_letohl(tvb, nds_offset);
+ nds_offset += 4;
+ get_string(tvb, nds_offset, nds_string_len, reply_buffer.buffer);
+ proto_tree_add_text(ncp_tree, tvb, nds_offset, nds_string_len, "NDS Tree Name: %s", reply_buffer.buffer);
+ nds_offset += nds_string_len;
+ nds_offset += align_4(tvb, nds_offset);
+ break;
+ case 0x00040000:
+ nds_string_len = tvb_get_letohl(tvb, nds_offset);
+ nds_offset += 4;
+ get_string(tvb, nds_offset, nds_string_len, reply_buffer.buffer);
+ proto_tree_add_text(ncp_tree, tvb, nds_offset, nds_string_len, "OS Name: %s", reply_buffer.buffer);
+ nds_offset += nds_string_len;
+ nds_offset += align_4(tvb, nds_offset);
+ break;
+ case 0x00080000:
+ nds_string_len = tvb_get_letohl(tvb, nds_offset);
+ nds_offset += 4;
+ get_string(tvb, nds_offset, nds_string_len, reply_buffer.buffer);
+ proto_tree_add_text(ncp_tree, tvb, nds_offset, nds_string_len, "Hardware Name: %s", reply_buffer.buffer);
+ nds_offset += nds_string_len;
+ nds_offset += align_4(tvb, nds_offset);
+ break;
+ case 0x00100000:
+ nds_string_len = tvb_get_letohl(tvb, nds_offset);
+ nds_offset += 4;
+ get_string(tvb, nds_offset, nds_string_len, reply_buffer.buffer);
+ proto_tree_add_text(ncp_tree, tvb, nds_offset, nds_string_len, "Vendor Name: %s", reply_buffer.buffer);
+ nds_offset += nds_string_len;
+ nds_offset += align_4(tvb, nds_offset);
+ break;
+ case 0x00000200:
+ /* Not Defined */
+ case 0x00000400:
+ /* Not Defined */
+ case 0x00000800:
+ /* Not Defined */
+ case 0x00001000:
+ /* Not Defined */
+ case 0x00002000:
+ /* Not Defined */
+ case 0x00004000:
+ /* Not Defined */
+ case 0x00008000:
+ /* Not Defined */
+ case 0x00200000:
+ /* Not Defined */
+ case 0x00400000:
+ /* Not Defined */
+ case 0x00800000:
+ /* Not Defined */
+ case 0x01000000:
+ /* Not Defined */
+ case 0x02000000:
+ /* Not Defined */
+ case 0x04000000:
+ /* Not Defined */
+ case 0x08000000:
+ /* Not Defined */
+ case 0x10000000:
+ /* Not Defined */
+ case 0x20000000:
+ /* Not Defined */
+ case 0x40000000:
+ /* Not Defined */
+ case 0x80000000:
+ /* Not Defined */
+ default:
+ break;
+ }
+ }
+ bvalue = bvalue*2;
+ }
+ }
+ }
+ if (ncp_rec->func == 0x68 && ncp_rec->subfunc == 0x02)
+ {
+ nds_offset = 8;
+
+ nds_reply_buffer = tvb_get_letohl(tvb, nds_offset);
+ proto_tree_add_uint(ncp_tree, hf_ncp_fragment_size, tvb, nds_offset,
+ 4, nds_reply_buffer);
+ nds_offset += 4;
+ nds_frag = tvb_get_letohl(tvb, nds_offset);
+ proto_tree_add_uint(ncp_tree, hf_ncp_fragment_handle, tvb, nds_offset,
+ 4, nds_frag);
+ nds_offset += 4;
+ if (nds_reply_buffer > 7)
+ {
+ /*
+ * XXX - is this present in
+ * replies to continuation
+ * messages? It doesn't appear to
+ * be.
+ */
+ proto_tree_add_uint_format(ncp_tree, hf_nds_reply_error, tvb, nds_offset,
+ 4, nds_error_code, "NDS Completion Code: 0x%08x, %s",
+ nds_error_code, nds_error_string);
+ }
+ if (request_value && nds_error_code == 0x00000000)
+ {
+ nds_offset = 20;
+ for (i = 0; i < 9; i++) {
+ pvalues[i].vtype = 0;
+ pvalues[i].vvalue = 0;
+ pvalues[i].vlength = 0;
+ pvalues[i].voffset = 0;
+ pvalues[i].hfname = 0;
+ pvalues[i].vdesc = "";
+ string_buffer[i][0] = '\0';
+ pvalues[i].vstring = string_buffer[i];
+ pvalues[i].mvtype = 0;
+ }
+ verb_string = val_to_str(request_value->nds_request_verb,
+ ncp_nds_verb_vals,
+ "Continuation Fragment");
+ switch (request_value->nds_request_verb)
+ {
+ case 0x01:
+ if(request_value->nds_version == 0)
+ {
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vstring = match_strval(pvalues[0].vvalue, nds_tags);
+ if(pvalues[0].vstring == NULL)
+ {
+ pvalues[0].vstring = "No Tags Set";
+ }
+ pvalues[0].vtype = VTYPE_STRING;
+ pvalues[0].vdesc = "Tag: %s";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_tag_string;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ switch(pvalues[0].vvalue)
+ {
+ case 0: /* No Such Entry */
+ break;
+ case 1: /* Local Entry */
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Entry ID: 0x%08x";
+ add_eid = TRUE;
+ strcpy(global_object_name, request_value->object_name);
+ global_eid = pvalues[1].vvalue;
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].hfname = hf_nds_eid;
+ nds_offset = nds_offset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[2].vdesc = "Referral Records: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_referrals;
+ pvalues[2].mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
+ break;
+ case 2: /* Remote Entry */
+ nds_offset += 4; /* GUINT32 reserved field */
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Entry ID: 0x%08x";
+ add_eid = TRUE;
+ global_eid = pvalues[1].vvalue;
+ strcpy(global_object_name, request_value->object_name);
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].hfname = hf_nds_eid;
+ nds_offset = nds_offset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[2].vdesc = "Referral Records: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_referrals;
+ pvalues[2].mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
+ break;
+ case 3: /* Alias Entry */
+ pvalues[1].vtype = VTYPE_STRING;
+ pvalues[1].vdesc = "Alias Name: %s";
+ pvalues[1].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[1].vvalue = 0;
+ pvalues[1].vlength = 256;
+ pvalues[1].vlength = tvb_get_letohl(tvb, nds_offset);
+ if (pvalues[1].vlength == 0x00)
+ {
+ pvalues[1].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[1].voffset = nds_offset+4;
+ nds_offset += 4;
+ get_string(tvb, pvalues[1].voffset, pvalues[1].vlength, pvalues[1].vstring);
+ nds_offset += pvalues[1].vlength;
+ nds_offset += align_4(tvb, nds_offset);
+ pvalues[1].hfname= hf_nds_name;
+ break;
+ case 4: /* Referral Information */
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Distance Object is From Root: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].hfname = hf_nds_eid;
+ nds_offset = nds_offset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[2].vdesc = "Referral Records: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_depth;
+ pvalues[2].mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
+ break;
+ case 6: /* Entry and Referrals */
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Result Flags: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].hfname = hf_nds_result_flags;
+ nds_offset = nds_offset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Entry ID: 0x%08x";
+ add_eid = TRUE;
+ global_eid = pvalues[2].vvalue;
+ strcpy(global_object_name, request_value->object_name);
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_eid;
+ nds_offset = nds_offset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[3].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[3].vdesc = "Referral Records: %u";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = nds_offset;
+ pvalues[3].mvtype = MVTYPE_ADDR_REFERRAL_REPLY;
+ pvalues[3].hfname = hf_nds_referrals;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "CRC: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_crc;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vstring = match_strval(pvalues[1].vvalue, nds_tags);
+ if(pvalues[1].vstring == NULL)
+ {
+ pvalues[1].vstring = "No Tags Set";
+ }
+ pvalues[1].vtype = VTYPE_STRING;
+ pvalues[1].vdesc = "Tag: %s";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ nds_offset = nds_offset+pvalues[1].vlength;
+ pvalues[1].hfname = hf_nds_tag_string;
+ switch(pvalues[1].vvalue)
+ {
+ case 0: /* No Such Entry */
+ break;
+ case 1: /* Local Entry */
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Entry ID: 0x%08x";
+ add_eid = TRUE;
+ global_eid = pvalues[2].vvalue;
+ strcpy(global_object_name, request_value->object_name);
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_eid;
+ nds_offset = nds_offset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[3].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[3].vdesc = "Referral Records: %u";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = nds_offset;
+ pvalues[3].hfname = hf_nds_referrals;
+ pvalues[3].mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
+ break;
+ case 2: /* Remote Entry */
+ nds_offset += 4; /* GUINT32 reserved field */
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ add_eid = TRUE;
+ global_eid = pvalues[2].vvalue;
+ strcpy(global_object_name, request_value->object_name);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Entry ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_eid;
+ nds_offset = nds_offset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[3].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[3].vdesc = "Referral Records: %u";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = nds_offset;
+ pvalues[3].hfname = hf_nds_referrals;
+ pvalues[3].mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
+ break;
+ case 3: /* Alias Entry */
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Alias Name: %s";
+ pvalues[2].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[2].vvalue = 0;
+ pvalues[2].vlength = 256;
+ pvalues[2].vlength = tvb_get_letohl(tvb, nds_offset);
+ if (pvalues[2].vlength == 0x00)
+ {
+ pvalues[2].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[2].voffset = nds_offset+4;
+ nds_offset += 4;
+ get_string(tvb, pvalues[2].voffset, pvalues[2].vlength, pvalues[2].vstring);
+ nds_offset += pvalues[2].vlength;
+ nds_offset += align_4(tvb, nds_offset);
+ pvalues[2].hfname= hf_nds_name;
+ break;
+ case 4: /* Referral Information */
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Distance Object is From Root: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_eid;
+ nds_offset = nds_offset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[3].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[3].vdesc = "Referral Records: %u";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = nds_offset;
+ pvalues[3].hfname = hf_nds_depth;
+ pvalues[3].mvtype = MVTYPE_ADDR_REFERRAL_REPLY;
+ break;
+ case 6: /* Entry and Referrals */
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Result Flags: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_result_flags;
+ nds_offset = nds_offset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[3].vtype = VTYPE_UINT32;
+ pvalues[3].vdesc = "Entry ID: 0x%08x";
+ add_eid = TRUE;
+ strcpy(global_object_name, request_value->object_name);
+ global_eid = pvalues[3].vvalue;
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = nds_offset;
+ pvalues[3].hfname = hf_nds_eid;
+ nds_offset = nds_offset+pvalues[3].vlength;
+ pvalues[4].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[4].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[4].vdesc = "Referral Records: %u";
+ pvalues[4].vlength = 4;
+ pvalues[4].voffset = nds_offset;
+ pvalues[4].mvtype = MVTYPE_ADDR_REFERRAL_REPLY;
+ pvalues[4].hfname = hf_nds_referrals;
+ break;
+ default:
+ break;
+ }
+
+ }
+ break;
+ case 0x02:
+ if(request_value->nds_version != 0x000000fe)
+ {
+ pvalues[0].vvalue = 1;
+ pvalues[0].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[0].vdesc = "Entry Information";
+ pvalues[0].vlength = 0;
+ pvalues[0].voffset = nds_offset-4;
+ pvalues[0].hfname = hf_nds_name;
+ pvalues[0].mvtype = MVTYPE_LIST_PARTITIONS;
+ pvalues[0].vflags = request_value->req_nds_flags;
+ }
+ else
+ {
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "CRC: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_crc;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vvalue = 1;
+ pvalues[1].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[1].vdesc = "Entry Information";
+ pvalues[1].vlength = 0;
+ pvalues[1].voffset = nds_offset-4;
+ pvalues[1].hfname = hf_nds_name;
+ pvalues[1].mvtype = MVTYPE_LIST_PARTITIONS;
+ pvalues[1].vflags = request_value->req_nds_flags;
+ }
+ break;
+ case 0x03:
+ if(request_value->nds_version != 0x000000fe)
+ {
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_iteration;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vstring = match_strval(pvalues[1].vvalue, nds_info_type);
+ if(pvalues[1].vstring == NULL)
+ {
+ pvalues[1].vstring = "No Info Type Set";
+ }
+ pvalues[1].vtype = VTYPE_STRING;
+ pvalues[1].vdesc = "Info Type: %s";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].hfname = hf_nds_info_type;
+ nds_offset = nds_offset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[2].vdesc = "Number of Attributes: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_attr;
+ pvalues[2].mvtype = MVTYPE_ATTR_REPLY;
+ pvalues[2].vflags = request_value->req_nds_flags;
+ pvalues[2].nds_version = request_value->nds_version;
+ }
+ else
+ {
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "CRC: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_crc;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].hfname = hf_nds_iteration;
+ nds_offset = nds_offset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vstring = match_strval(pvalues[2].vvalue, nds_info_type);
+ if(pvalues[2].vstring == NULL)
+ {
+ pvalues[2].vstring = "No Info Type Set";
+ }
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Info Type: %s";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_info_type;
+ nds_offset = nds_offset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[3].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[3].vdesc = "Number of Attributes: %u";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = nds_offset;
+ pvalues[3].hfname = hf_nds_attr;
+ pvalues[3].mvtype = MVTYPE_ATTR_REPLY;
+ pvalues[3].vflags = request_value->req_nds_flags;
+ pvalues[3].nds_version = request_value->nds_version;
+ }
+ break;
+ case 0x04:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ if (pvalues[0].vvalue == 0x00000000)
+ {
+ pvalues[0].vstring = "Did Not Match";
+ }
+ else
+ {
+ pvalues[0].vstring = "Matched";
+ }
+ pvalues[0].vtype = VTYPE_STRING;
+ pvalues[0].vdesc = "Compare Values Returned - %s";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].mvtype = 0;
+ pvalues[0].hfname= hf_nds_compare_results;
+ nds_offset += pvalues[0].vlength;
+ break;
+ case 0x05:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_iteration;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[1].vdesc = "Entry Information";
+ pvalues[1].vlength = 0;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].hfname = hf_nds_name;
+ pvalues[1].mvtype = MVTYPE_LIST_PARTITIONS;
+ pvalues[1].vflags = request_value->req_nds_flags;
+ break;
+ case 0x06:
+ break;
+ case 0x07:
+ break;
+ case 0x08:
+ break;
+ case 0x09:
+ break;
+ case 0x0a:
+ break;
+ case 0x0b:
+ break;
+ case 0x0c:
+ break;
+ case 0x0d:
+ break;
+ case 0x0e:
+ break;
+ case 0x0f:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_iteration;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vstring = match_strval(pvalues[1].vvalue, class_def_type);
+ if(pvalues[1].vstring == NULL)
+ {
+ pvalues[1].vstring = "No Class Definition Type Set";
+ }
+ pvalues[1].vtype = VTYPE_STRING;
+ pvalues[1].vdesc = "Class Definition Type: %s";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].mvtype = 0;
+ pvalues[1].hfname= hf_nds_class_def_type;
+ nds_offset = nds_offset + pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);;
+ pvalues[2].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[2].vdesc = "Class Definitions %u";
+ pvalues[2].vlength = 0;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_classes;
+ pvalues[2].mvtype = MVTYPE_CLASS_NAMES;
+ pvalues[2].vflags = request_value->req_nds_flags;
+ break;
+ case 0x10:
+ break;
+ case 0x11:
+ break;
+ case 0x12:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_iteration;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[1].vdesc = "Classes: %u";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].mvtype = MVTYPE_READ_CLASS_REQ;
+ pvalues[1].hfname= hf_nds_classes;
+ break;
+ case 0x13:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Privileges: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_privileges;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ break;
+ case 0x14:
+ break;
+ case 0x15:
+ break;
+ case 0x16:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_iteration;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vtype = VTYPE_STRING;
+ pvalues[1].vdesc = "Server Distinguished Name: %s";
+ pvalues[1].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[1].vvalue = 0;
+ pvalues[1].vlength = 256;
+ pvalues[1].vlength = tvb_get_letohl(tvb, nds_offset);
+ if (pvalues[1].vlength == 0x00)
+ {
+ pvalues[1].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[1].voffset = nds_offset+4;
+ nds_offset += 4;
+ get_string(tvb, pvalues[1].voffset, pvalues[1].vlength, pvalues[1].vstring);
+ nds_offset += pvalues[1].vlength;
+ nds_offset += align_4(tvb, nds_offset);
+ pvalues[1].hfname= hf_nds_name;
+ nds_offset += align_4(tvb, nds_offset);
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[2].vdesc = "Replicas: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_replicas;
+ pvalues[2].mvtype = MVTYPE_READ_REPLICAS;
+ pvalues[2].bit1 = "Output Flags";
+ pvalues[2].bit2 = "Entry ID";
+ pvalues[2].bit3 = "Replica State";
+ pvalues[2].bit4 = "Modification Timestamp";
+ pvalues[2].bit5 = "Purge Time";
+ pvalues[2].bit6 = "Local Partition ID";
+ pvalues[2].bit7 = "Distinguished Name";
+ pvalues[2].bit8 = "Replica Type";
+ pvalues[2].bit9 = "Partition Busy";
+ pvalues[2].vflags = request_value->req_nds_flags;
+ break;
+ case 0x17:
+ break;
+ case 0x18:
+ break;
+ case 0x19:
+ break;
+ case 0x1a:
+ break;
+ case 0x1b:
+ pvalues[0].vvalue = tvb_get_ntohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "File Handle: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_file_handle;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "File Size: %u";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].hfname = hf_nds_file_size;
+ nds_offset = nds_offset+pvalues[1].vlength;
+ break;
+ case 0x1c:
+ break;
+ case 0x1d:
+ break;
+ case 0x1e:
+ break;
+ case 0x1f:
+ break;
+ case 0x20:
+ break;
+ case 0x21:
+ break;
+ case 0x22:
+ break;
+ case 0x23:
+ break;
+ case 0x24:
+ break;
+ case 0x25:
+ break;
+ case 0x26:
+ break;
+ case 0x27:
+ break;
+ case 0x28:
+ break;
+ case 0x29:
+ break;
+ case 0x2a:
+ break;
+ case 0x2b:
+ break;
+ case 0x2c:
+ break;
+ case 0x2d:
+ break;
+ case 0x2e:
+ break;
+ case 0x2f:
+ break;
+ case 0x30:
+ break;
+ case 0x31:
+ break;
+ case 0x32:
+ break;
+ case 0x33:
+ break;
+ case 0x34:
+ break;
+ case 0x35:
+ if(request_value->nds_version != 0x000000fe)
+ {
+ pvalues[0].vtype = VTYPE_STRING;
+ pvalues[0].vdesc = "Distinguished Name: %s";
+ pvalues[0].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[0].vvalue = 0;
+ pvalues[0].vlength = 256;
+ pvalues[0].vlength = tvb_get_letohl(tvb, nds_offset);
+ if (pvalues[0].vlength == 0x00)
+ {
+ pvalues[0].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[0].voffset = nds_offset+4;
+ nds_offset += 4;
+ get_string(tvb, pvalues[0].voffset, pvalues[0].vlength, pvalues[0].vstring);
+ nds_offset += pvalues[0].vlength;
+ nds_offset += align_4(tvb, nds_offset);
+ pvalues[0].hfname= hf_nds_name;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[1].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[1].vdesc = "Referral Records: %u";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = nds_offset;
+ pvalues[1].hfname = hf_nds_referrals;
+ pvalues[1].mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
+ }
+ else
+ {
+ pvalues[0].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = nds_offset;
+ pvalues[0].hfname = hf_nds_iteration;
+ nds_offset = nds_offset+pvalues[0].vlength;
+ pvalues[1].vtype = VTYPE_STRING;
+ pvalues[1].vdesc = "Distinguished Name: %s";
+ pvalues[1].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[1].vvalue = 0;
+ pvalues[1].vlength = 256;
+ pvalues[1].vlength = tvb_get_letohl(tvb, nds_offset);
+ if (pvalues[1].vlength == 0x00)
+ {
+ pvalues[1].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[1].voffset = nds_offset+4;
+ nds_offset += 4;
+ get_string(tvb, pvalues[1].voffset, pvalues[1].vlength, pvalues[1].vstring);
+ nds_offset += pvalues[1].vlength;
+ nds_offset += align_4(tvb, nds_offset);
+ pvalues[1].hfname= hf_nds_name;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, nds_offset);
+ pvalues[2].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[2].vdesc = "Referral Records: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = nds_offset;
+ pvalues[2].hfname = hf_nds_referrals;
+ pvalues[2].mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
+ }
+ break;
+ case 0x36:
+ break;
+ case 0x37:
+ break;
+ case 0x38:
+ break;
+ case 0x39:
+ break;
+ case 0x3a:
+ break;
+ case 0x3b:
+ break;
+ case 0x3c:
+ break;
+ case 0x3d:
+ break;
+ case 0x3e:
+ break;
+ case 0x3f:
+ break;
+ case 0x40:
+ break;
+ case 0x41:
+ break;
+ case 0x42:
+ break;
+ case 0x43:
+ break;
+ case 0x44:
+ break;
+ case 0x45:
+ break;
+ case 0x46:
+ break;
+ case 0x47:
+ break;
+ case 0x48:
+ break;
+ case 0x49:
+ break;
+ case 0x4a:
+ break;
+ case 0x4b:
+ break;
+ case 0x4c:
+ break;
+ case 0x4d:
+ break;
+ default:
+ break;
+ }
+ if(request_value->nds_request_verb != 0)
+ {
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_nds_verb, tvb, 6, 0,
+ request_value->nds_request_verb, "NDS Verb: %d, %s",
+ request_value->nds_request_verb, verb_string);
+ }
+ /* NDS Entry ID's (EID) is identified in the reply packet of an NDS
+ * resolve name. We need to store this EID and it's associated
+ * name into our hash so that we can resolve the name for
+ * other NDS requests. */
+ if (!pinfo->fd->flags.visited) {
+ if(add_eid)
+ {
+ request_eid_value = ncp_eid_hash_lookup(conversation, global_eid);
+ if (!request_eid_value) {
+ request_eid_value = ncp_eid_hash_insert(global_eid);
+ strcpy(request_eid_value->object_name, global_object_name);
+ }
+ }
+ }
+ /* For NDS requests with just an EID, resolve name from hash table. */
+ if(resolve_eid)
+ {
+ request_eid_value = ncp_eid_hash_lookup(conversation, global_eid);
+ if (request_eid_value) {
+ strcpy(global_object_name, request_eid_value->object_name);
+ proto_tree_add_string_format(ncp_tree, hf_nds_name, tvb, 6, 0,
+ global_object_name, "NDS Name for EID - %s",
+ global_object_name);
+ }
+ }
+ for (i = 0; i < 9; i++) {
+ switch (pvalues[i].vtype) {
+
+ case VTYPE_NONE: /* no value */
+ break;
+
+ case VTYPE_UINT8:
+ proto_tree_add_uint_format(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vtype, "NDS Parameter not defined %u",
+ pvalues[i].vtype);
+ break;
+
+ case VTYPE_UINT16:
+ proto_tree_add_uint_format(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vtype, "NDS Parameter not defined %u",
+ pvalues[i].vtype);
+ break;
+
+ case VTYPE_UINT32:
+ proto_tree_add_uint_format(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vvalue, pvalues[i].vdesc,
+ pvalues[i].vvalue);
+ break;
+
+ case VTYPE_STRING:
+ proto_tree_add_string_format(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vstring, pvalues[i].vdesc,
+ pvalues[i].vstring);
+ break;
+
+ case VTYPE_BITFIELD:
+ process_bitfield(ncp_tree, tvb, &pvalues[i]);
+ break;
+
+ case VTYPE_MULTIVALUE_UINT32:
+ process_multivalues(ncp_tree, tvb, &pvalues[i]);
+ break;
+
+ default:
+ proto_tree_add_uint_format(ncp_tree, hf_nds_p1type, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vtype, "NDS Parameter not defined %u",
+ pvalues[i].vtype);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ length = tvb_length(tvb);
+ if (!ncp_rec && length > 8) {
+ proto_tree_add_text(ncp_tree, tvb, 8, length - 8,
+ "No request record found. Parsing is impossible.");
+ }
+ else if (ncp_rec && ncp_rec->reply_ptvc) {
+ /* If a non-zero completion code was found, it is
+ * legal to not have any fields, even if the packet
+ * type is defined as having fields. */
+ if (completion_code != 0 && tvb_length(tvb) == 8) {
+ return;
+ }
+ /*printf("func=0x%x subfunc=0x%x\n", ncp_rec->func, ncp_rec->subfunc);*/
+
+ /* Any request condition results? */
+ if (request_value) {
+ req_cond_results = request_value->req_cond_results;
+ }
+ else {
+ req_cond_results = NULL;
+ }
+
+ clear_repeat_vars();
+ ptvc = ptvcursor_new(ncp_tree, tvb, 8);
+ process_ptvc_record(ptvc, ncp_rec->reply_ptvc, req_cond_results,
+ TRUE, ncp_rec);
+ ptvcursor_free(ptvc);
+ }
+ }
+}
+
+void
+dissect_nds_request(tvbuff_t *tvb, packet_info *pinfo,
+ guint16 nw_connection, guint8 sequence,
+ guint16 type, proto_tree *ncp_tree)
+{
+ guint8 func, subfunc = 0;
+ ncp_req_hash_value *request_value = NULL;
+ ncp_req_eid_hash_value *request_eid_value = NULL;
+ const ncp_record *ncp_rec = NULL;
+ conversation_t *conversation;
+ ptvcursor_t *ptvc = NULL;
+ proto_tree *temp_tree = NULL;
+ gboolean run_req_cond = FALSE;
+ gboolean run_info_str = FALSE;
+ guint8 nds_verb = 0;
+ char * verb_string = "";
+ guint32 nds_frag = 0;
+ gboolean added_arrow;
+ nds_val pvalues[9];
+ char string_buffer[9][1024];
+ guint8 nds_version = 0;
+ guint32 foffset = 0;
+ nw_uni_t req_buffer;
+ char global_object_name[256];
+ guint32 global_eid=0;
+ gboolean resolve_eid=FALSE;
+ guint32 global_flags=0;
+ int i;
+
+ for (i = 0; i < 9; i++) {
+ pvalues[i].vtype = 0;
+ pvalues[i].vvalue = 0;
+ pvalues[i].vlength = 0;
+ pvalues[i].voffset = 0;
+ pvalues[i].hfname = 0;
+ pvalues[i].vdesc = "";
+ string_buffer[i][0] = '\0';
+ pvalues[i].vstring = string_buffer[i];
+ pvalues[i].mvtype = 0;
+ }
+
+ strcpy(req_buffer.buffer, "");
+ strcpy(global_object_name, "");
+
+ func = tvb_get_guint8(tvb, 6);
+ subfunc = tvb_get_guint8(tvb, 7);
+
+ ncp_rec = ncp_record_find(func, subfunc);
+
+ /* Check to see if this is a fragment packet */
+ nds_frag = tvb_get_letohl(tvb, 8);
+
+ /* Get NDS Verb */
+ if (nds_frag == 0xffffffff) {
+ nds_verb = tvb_get_guint8(tvb, 24);
+ if (nds_verb == 0xfe)
+ {
+ nds_version = nds_verb;
+ nds_verb = tvb_get_guint8(tvb, 32);
+ foffset = 36;
+ }
+ else
+ {
+ nds_version = 0;
+ foffset = 28;
+ }
+ if (type == NCP_SERVICE_REQUEST) {
+ proto_tree_add_item(ncp_tree, hf_nds_buffer_size, tvb, foffset,
+ 4, TRUE);
+ }
+ foffset = foffset+4;
+ verb_string = val_to_str(nds_verb, ncp_nds_verb_vals,
+ "Continuation Fragment");
+ switch(nds_verb) {
+
+ case 0x01:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[0].vvalue;
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].hfname = hf_nds_ver;
+ pvalues[0].voffset = foffset;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_BITFIELD;
+ pvalues[1].vdesc = "Flags:";
+ pvalues[1].vlength = 2;
+ pvalues[1].hfname= hf_nds_nflags;
+ pvalues[1].voffset = foffset;
+ pvalues[1].bit1 = "Entry ID";
+ pvalues[1].bit1hfname = hf_bit1nflags;
+ pvalues[1].bit2 = "Readable";
+ pvalues[1].bit2hfname = hf_bit2nflags;
+ pvalues[1].bit3 = "Writeable";
+ pvalues[1].bit3hfname = hf_bit3nflags;
+ pvalues[1].bit4 = "Master";
+ pvalues[1].bit4hfname = hf_bit4nflags;
+ pvalues[1].bit5 = "Create ID";
+ pvalues[1].bit5hfname = hf_bit5nflags;
+ pvalues[1].bit6 = "Walk Tree";
+ pvalues[1].bit6hfname = hf_bit6nflags;
+ pvalues[1].bit7 = "Dereference Alias";
+ pvalues[1].bit7hfname = hf_bit7nflags;
+ pvalues[1].bit8 = "Not Defined";
+ pvalues[1].bit8hfname = hf_bit8nflags;
+ pvalues[1].bit9 = "Not Defined";
+ pvalues[1].bit9hfname = hf_bit9nflags;
+ pvalues[1].bit10 = "Not Defined";
+ pvalues[1].bit10hfname = hf_bit10nflags;
+ pvalues[1].bit11= "Not Defined";
+ pvalues[1].bit11hfname = hf_bit11nflags;
+ pvalues[1].bit12 = "Not Defined";
+ pvalues[1].bit12hfname = hf_bit12nflags;
+ pvalues[1].bit13 = "Not Defined";
+ pvalues[1].bit13hfname = hf_bit13nflags;
+ pvalues[1].bit14 = "Prefer Referrals";
+ pvalues[1].bit14hfname = hf_bit14nflags;
+ pvalues[1].bit15 = "Prefer Only Referrals";
+ pvalues[1].bit15hfname = hf_bit15nflags;
+ pvalues[1].bit16 = "Not Defined";
+ pvalues[1].bit16hfname = hf_bit16nflags;
+ foffset = foffset+4;
+ if (pvalues[0].vvalue == 0 || pvalues[0].vvalue == 1)
+ {
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Scope: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].hfname= hf_nds_scope;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "Name: %s";
+ pvalues[3].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[3].vvalue = 0;
+ pvalues[3].vlength = 256;
+ pvalues[3].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[3].vlength == 0x00)
+ {
+ pvalues[3].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[3].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[3].voffset, pvalues[3].vlength, req_buffer.buffer);
+ pvalues[3].vstring = req_buffer.buffer;
+ strcpy(global_object_name, req_buffer.buffer);
+ pvalues[3].hfname= hf_nds_name;
+ foffset = foffset+pvalues[3].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[4].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[4].vdesc = "Communications Transports: %u";
+ pvalues[4].vlength = 4;
+ pvalues[4].hfname= hf_nds_comm_trans;
+ pvalues[4].voffset = foffset;
+ pvalues[4].mvtype = MVTYPE_ADDR_REFERRAL_REQUEST;
+ foffset = foffset + (pvalues[4].vvalue * 4) + 4;
+ pvalues[5].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[5].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[5].vdesc = "Tree Walker Transport Type: %u";
+ pvalues[5].vlength = 4;
+ pvalues[5].mvtype = MVTYPE_ADDR_REFERRAL_REQUEST;
+ pvalues[5].hfname= hf_nds_tree_trans;
+ pvalues[5].voffset = foffset;
+ }
+ else
+ {
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Minimum DS Version: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].hfname= hf_min_nds_ver;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[3].vdesc = "Number of Versions to Include: %u";
+ pvalues[3].vlength = 4;
+ pvalues[3].mvtype = MVTYPE_ATTR_REQUEST2;
+ pvalues[3].voffset = foffset;
+ pvalues[3].hfname= hf_nds_ver_include;
+ foffset += (pvalues[3].vvalue * 4) + 4;
+ pvalues[4].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[4].vdesc = "Number of Versions to Exclude: %u";
+ pvalues[4].vlength = 4;
+ pvalues[4].mvtype = MVTYPE_ATTR_REQUEST2;
+ pvalues[4].hfname= hf_nds_ver_exclude;
+ pvalues[4].voffset = foffset;
+ foffset += 4;
+ pvalues[5].vtype = VTYPE_UINT32;
+ pvalues[5].vdesc = "DN Output Type: %u";
+ pvalues[5].vlength = 4;
+ pvalues[5].voffset = foffset;
+ pvalues[5].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[5].hfname= hf_nds_dn_output_type;
+ foffset = foffset+pvalues[5].vlength;
+ pvalues[6].vtype = VTYPE_UINT32;
+ pvalues[6].vdesc = "Nested Output Type: %u";
+ pvalues[6].vlength = 4;
+ pvalues[6].voffset = foffset;
+ pvalues[6].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[6].hfname= hf_nds_nested_output_type;
+ foffset = foffset+pvalues[6].vlength;
+ pvalues[7].vtype = VTYPE_STRING;
+ pvalues[7].vdesc = "Output Delimiter: %s";
+ pvalues[7].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[7].vvalue = 0;
+ pvalues[7].vlength = 256;
+ pvalues[7].vlength = tvb_get_letohl(tvb, foffset);
+ pvalues[7].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[7].voffset, pvalues[7].vlength, req_buffer.buffer);
+ pvalues[7].vstring = req_buffer.buffer;
+ pvalues[7].hfname= hf_nds_output_delimiter;
+ foffset = foffset+pvalues[7].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[8].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[8].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[8].vdesc = "Size of Entry Specifier: %u";
+ pvalues[8].vlength = 4;
+ pvalues[8].mvtype = MVTYPE_PROC_ENTRY_SPECIFIERS;
+ pvalues[8].hfname= hf_nds_output_entry_specifier;
+ pvalues[8].voffset = foffset;
+ }
+ break;
+ case 0x02:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ switch(pvalues[0].vvalue)
+ {
+ case 0:
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Entry ID: 0x%08x";
+ pvalues[1].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[1].vvalue;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname = hf_nds_eid;
+ foffset = foffset+pvalues[1].vlength;
+ break;
+ case 1:
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_BITFIELD;
+ pvalues[1].vdesc = "Request Flags:";
+ pvalues[1].vlength = 2;
+ pvalues[1].hfname= hf_nds_rflags;
+ pvalues[1].voffset = foffset;
+ pvalues[1].bit1 = "Typeless";
+ pvalues[1].bit1hfname = hf_bit1rflags;
+ pvalues[1].bit2 = "Slashed";
+ pvalues[1].bit2hfname = hf_bit2rflags;
+ pvalues[1].bit3 = "Dotted";
+ pvalues[1].bit3hfname = hf_bit3rflags;
+ pvalues[1].bit4 = "Tuned";
+ pvalues[1].bit4hfname = hf_bit4rflags;
+ pvalues[1].bit5 = "Not Defined";
+ pvalues[1].bit5hfname = hf_bit5rflags;
+ pvalues[1].bit6 = "Not Defined";
+ pvalues[1].bit6hfname = hf_bit6rflags;
+ pvalues[1].bit7 = "Not Defined";
+ pvalues[1].bit7hfname = hf_bit7rflags;
+ pvalues[1].bit8 = "Not Defined";
+ pvalues[1].bit8hfname = hf_bit8rflags;
+ pvalues[1].bit9 = "Not Defined";
+ pvalues[1].bit9hfname = hf_bit9rflags;
+ pvalues[1].bit10 = "Not Defined";
+ pvalues[1].bit10hfname = hf_bit10rflags;
+ pvalues[1].bit11 = "Not Defined";
+ pvalues[1].bit11hfname = hf_bit11rflags;
+ pvalues[1].bit12 = "Not Defined";
+ pvalues[1].bit12hfname = hf_bit12rflags;
+ pvalues[1].bit13 = "Not Defined";
+ pvalues[1].bit13hfname = hf_bit13rflags;
+ pvalues[1].bit14 = "Not Defined";
+ pvalues[1].bit14hfname = hf_bit14rflags;
+ pvalues[1].bit15 = "Not Defined";
+ pvalues[1].bit15hfname = hf_bit15rflags;
+ pvalues[1].bit16 = "Not Defined";
+ pvalues[1].bit16hfname = hf_bit16rflags;
+ if((pvalues[1].vvalue&&0xf000) == 0xc000)
+ {
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Name Type: %s";
+ pvalues[2].vstring = "Partial";
+ pvalues[2].mvtype = 0;
+ pvalues[2].vvalue = 0;
+ pvalues[2].vlength = 0;
+ pvalues[2].voffset = 0;
+ pvalues[2].hfname= hf_nds_name_type;
+ }
+ else
+ {
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Name Type: %s";
+ pvalues[2].vstring = "Full";
+ pvalues[2].vvalue = 0;
+ pvalues[2].mvtype = 0;
+ pvalues[2].vlength = 0;
+ pvalues[2].voffset = 0;
+ pvalues[2].hfname= hf_nds_name_type;
+ }
+ foffset = foffset+4;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vtype = VTYPE_UINT32;
+ pvalues[3].vdesc = "Entry ID: 0x%08x";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = foffset;
+ resolve_eid = TRUE;
+ global_eid = pvalues[3].vvalue;
+ pvalues[3].hfname = hf_nds_eid;
+ foffset = foffset+pvalues[3].vlength;
+ break;
+ case 2:
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_BITFIELD;
+ pvalues[1].vdesc = "Request Flags:";
+ pvalues[1].vlength = 2;
+ pvalues[1].hfname= hf_nds_rflags;
+ pvalues[1].voffset = foffset;
+ pvalues[1].bit1 = "Typeless";
+ pvalues[1].bit1hfname = hf_bit1rflags;
+ pvalues[1].bit2 = "Slashed";
+ pvalues[1].bit2hfname = hf_bit2rflags;
+ pvalues[1].bit3 = "Dotted";
+ pvalues[1].bit3hfname = hf_bit3rflags;
+ pvalues[1].bit4 = "Tuned";
+ pvalues[1].bit4hfname = hf_bit4rflags;
+ pvalues[1].bit5 = "Not Defined";
+ pvalues[1].bit5hfname = hf_bit5rflags;
+ pvalues[1].bit6 = "Not Defined";
+ pvalues[1].bit6hfname = hf_bit6rflags;
+ pvalues[1].bit7 = "Not Defined";
+ pvalues[1].bit7hfname = hf_bit7rflags;
+ pvalues[1].bit8 = "Not Defined";
+ pvalues[1].bit8hfname = hf_bit8rflags;
+ pvalues[1].bit9 = "Not Defined";
+ pvalues[1].bit9hfname = hf_bit9rflags;
+ pvalues[1].bit10 = "Not Defined";
+ pvalues[1].bit10hfname = hf_bit10rflags;
+ pvalues[1].bit11 = "Not Defined";
+ pvalues[1].bit11hfname = hf_bit11rflags;
+ pvalues[1].bit12 = "Not Defined";
+ pvalues[1].bit12hfname = hf_bit12rflags;
+ pvalues[1].bit13 = "Not Defined";
+ pvalues[1].bit13hfname = hf_bit13rflags;
+ pvalues[1].bit14 = "Not Defined";
+ pvalues[1].bit14hfname = hf_bit14rflags;
+ pvalues[1].bit15 = "Not Defined";
+ pvalues[1].bit15hfname = hf_bit15rflags;
+ pvalues[1].bit16 = "Not Defined";
+ pvalues[1].bit16hfname = hf_bit16rflags;
+ if((pvalues[1].vvalue&&0xf000) == 0xc000)
+ {
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Name Type: %s";
+ pvalues[2].vstring = "Return Partion Name";
+ pvalues[2].vvalue = 0;
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = pvalues[1].voffset;
+ pvalues[2].mvtype = 0;
+ pvalues[2].hfname= hf_nds_name_type;
+ }
+ else
+ {
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Name Type: %s";
+ pvalues[2].vstring = "Return Full Name";
+ pvalues[2].vvalue = 0;
+ pvalues[2].vlength = 4;
+ pvalues[2].mvtype = 0;
+ pvalues[2].voffset = pvalues[1].voffset;
+ pvalues[2].hfname= hf_nds_name_type;
+ }
+ foffset = foffset+4;
+ pvalues[3].vvalue = tvb_get_letohs(tvb, foffset);
+ global_flags = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vtype = VTYPE_BITFIELD;
+ pvalues[3].vdesc = "Information Flags (low) Byte:";
+ pvalues[3].vlength = 2;
+ pvalues[3].hfname= hf_nds_rflags;
+ pvalues[3].voffset = foffset;
+ pvalues[3].bit1 = "Output Flags";
+ pvalues[3].bit1hfname = hf_bit1infoflagsl;
+ pvalues[3].bit2 = "Entry ID";
+ pvalues[3].bit2hfname = hf_bit2infoflagsl;
+ pvalues[3].bit3 = "Entry Flags";
+ pvalues[3].bit3hfname = hf_bit3infoflagsl;
+ pvalues[3].bit4 = "Subordinate Count";
+ pvalues[3].bit4hfname = hf_bit4infoflagsl;
+ pvalues[3].bit5 = "Modification Time";
+ pvalues[3].bit5hfname = hf_bit5infoflagsl;
+ pvalues[3].bit6 = "Modification Timestamp";
+ pvalues[3].bit6hfname = hf_bit6infoflagsl;
+ pvalues[3].bit7 = "Creation Timestamp";
+ pvalues[3].bit7hfname = hf_bit7infoflagsl;
+ pvalues[3].bit8 = "Partition Root ID";
+ pvalues[3].bit8hfname = hf_bit8infoflagsl;
+ pvalues[3].bit9 = "Parent ID";
+ pvalues[3].bit9hfname = hf_bit9infoflagsl;
+ pvalues[3].bit10 = "Revision Count";
+ pvalues[3].bit10hfname = hf_bit10infoflagsl;
+ pvalues[3].bit11 = "Replica Type";
+ pvalues[3].bit11hfname = hf_bit11infoflagsl;
+ pvalues[3].bit12 = "Base Class";
+ pvalues[3].bit12hfname = hf_bit12infoflagsl;
+ pvalues[3].bit13 = "Relative Distinguished Name";
+ pvalues[3].bit13hfname = hf_bit13infoflagsl;
+ pvalues[3].bit14 = "Distinguished Name";
+ pvalues[3].bit14hfname = hf_bit14infoflagsl;
+ pvalues[3].bit15 = "Root Distinguished Name";
+ pvalues[3].bit15hfname = hf_bit15infoflagsl;
+ pvalues[3].bit16 = "Parent Distinguished Name";
+ pvalues[3].bit16hfname = hf_bit16infoflagsl;
+ foffset = foffset+2;
+ pvalues[4].vvalue = tvb_get_letohs(tvb, foffset);
+ pvalues[4].vtype = VTYPE_BITFIELD;
+ pvalues[4].vdesc = "Information Flags (high) Byte:";
+ pvalues[4].vlength = 2;
+ pvalues[4].hfname= hf_nds_rflags;
+ pvalues[4].voffset = foffset;
+ pvalues[4].bit1 = "Purge Time";
+ pvalues[4].bit1hfname = hf_bit1infoflagsh;
+ pvalues[4].bit2 = "Dereference Base Class";
+ pvalues[4].bit2hfname = hf_bit2infoflagsh;
+ pvalues[4].bit3 = "Not Defined";
+ pvalues[4].bit3hfname = hf_bit3infoflagsh;
+ pvalues[4].bit4 = "Not Defined";
+ pvalues[4].bit4hfname = hf_bit4infoflagsh;
+ pvalues[4].bit5 = "Not Defined";
+ pvalues[4].bit5hfname = hf_bit5infoflagsh;
+ pvalues[4].bit6 = "Not Defined";
+ pvalues[4].bit6hfname = hf_bit6infoflagsh;
+ pvalues[4].bit7 = "Not Defined";
+ pvalues[4].bit7hfname = hf_bit7infoflagsh;
+ pvalues[4].bit8 = "Not Defined";
+ pvalues[4].bit8hfname = hf_bit8infoflagsh;
+ pvalues[4].bit9 = "Not Defined";
+ pvalues[4].bit9hfname = hf_bit9infoflagsh;
+ pvalues[4].bit10 = "Not Defined";
+ pvalues[4].bit10hfname = hf_bit10infoflagsh;
+ pvalues[4].bit11 = "Not Defined";
+ pvalues[4].bit11hfname = hf_bit11infoflagsh;
+ pvalues[4].bit12 = "Not Defined";
+ pvalues[4].bit12hfname = hf_bit12infoflagsh;
+ pvalues[4].bit13 = "Not Defined";
+ pvalues[4].bit13hfname = hf_bit13infoflagsh;
+ pvalues[4].bit14 = "Not Defined";
+ pvalues[4].bit14hfname = hf_bit14infoflagsh;
+ pvalues[4].bit15 = "Not Defined";
+ pvalues[4].bit15hfname = hf_bit15infoflagsh;
+ pvalues[4].bit16 = "Not Defined";
+ pvalues[4].bit16hfname = hf_bit16infoflagsh;
+ foffset = foffset+2;
+ pvalues[5].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[5].vtype = VTYPE_UINT32;
+ pvalues[5].vdesc = "Entry ID: 0x%08x";
+ pvalues[5].vlength = 4;
+ pvalues[5].voffset = foffset;
+ resolve_eid = TRUE;
+ global_eid = pvalues[5].vvalue;
+ pvalues[5].hfname = hf_nds_eid;
+ foffset = foffset+pvalues[5].vlength;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case 0x03:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ if(pvalues[0].vvalue == 0)
+ {
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname= hf_nds_iteration;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Entry ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[2].vvalue;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vstring = match_strval(pvalues[3].vvalue, nds_info_type);
+ global_flags = pvalues[3].vvalue;
+ if(pvalues[3].vstring == NULL)
+ {
+ pvalues[3].vstring = "No Info Type Set";
+ }
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "Info Type: %s";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = foffset;
+ pvalues[3].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[3].hfname= hf_nds_info_type;
+ foffset = foffset + pvalues[3].vlength;
+ pvalues[4].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vtype = VTYPE_UINT32;
+ pvalues[4].vdesc = "All Attributes: %u";
+ pvalues[4].vlength = 4;
+ pvalues[4].voffset = foffset;
+ pvalues[4].hfname= hf_nds_all_attr;
+ foffset = foffset+pvalues[4].vlength;
+ pvalues[5].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[5].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[5].vdesc = "Attributes: %u";
+ pvalues[5].vlength = 4;
+ pvalues[5].voffset = foffset;
+ pvalues[5].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[5].hfname= hf_nds_attr;
+ }
+ else
+ {
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Request Flags: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname= hf_nds_req_flags;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_iteration;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vtype = VTYPE_UINT32;
+ pvalues[3].vdesc = "Entry ID: 0x%08x";
+ pvalues[3].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[3].vvalue;
+ pvalues[3].voffset = foffset;
+ pvalues[3].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[3].vlength;
+ pvalues[4].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vstring = match_strval(pvalues[4].vvalue, nds_info_type);
+ global_flags = pvalues[4].vvalue;
+ if(pvalues[4].vstring == NULL)
+ {
+ pvalues[4].vstring = "No Info Type Set";
+ }
+ pvalues[4].vtype = VTYPE_STRING;
+ pvalues[4].vdesc = "Info Type: %s";
+ pvalues[4].vlength = 4;
+ pvalues[4].voffset = foffset;
+ pvalues[4].hfname= hf_nds_info_type;
+ pvalues[4].mvtype = MVTYPE_ATTR_REQUEST;
+ foffset = foffset+pvalues[4].vlength;
+ pvalues[5].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[5].vtype = VTYPE_UINT32;
+ pvalues[5].vdesc = "All Attributes: %u";
+ pvalues[5].vlength = 4;
+ pvalues[5].voffset = foffset;
+ pvalues[5].hfname= hf_nds_all_attr;
+ foffset = foffset+pvalues[5].vlength;
+ pvalues[6].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[6].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[6].vdesc = "Attributes: %u";
+ pvalues[6].vlength = 4;
+ pvalues[6].voffset = foffset;
+ pvalues[6].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[6].hfname= hf_nds_attr;
+ }
+ break;
+ case 0x04:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Entry ID: 0x%08x";
+ pvalues[1].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[1].vvalue;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname = hf_nds_eid;
+ foffset = foffset+pvalues[1].vlength;
+ foffset += 4; /* Attribute Count = 1 */
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Attribute Name Being Compared: %s";
+ pvalues[2].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[2].vvalue = 0;
+ pvalues[2].vlength = 256;
+ pvalues[2].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[2].vlength == 0x00)
+ {
+ pvalues[2].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[2].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[2].voffset, pvalues[2].vlength, req_buffer.buffer);
+ pvalues[2].vstring = req_buffer.buffer;
+ strcpy(global_object_name, req_buffer.buffer);
+ pvalues[2].hfname= hf_nds_name;
+ foffset = foffset+pvalues[2].vlength;
+ foffset += align_4(tvb, foffset);
+ foffset += 4; /* Attribute Value Count = 1 */
+ /***************
+ * Need Trace file to test. Will have to create a
+ * new mvtype to call print_nds_values.
+ ***************/
+ break;
+ case 0x05:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_BITFIELD;
+ pvalues[1].vdesc = "Request Flags:";
+ pvalues[1].vlength = 2;
+ pvalues[1].hfname= hf_nds_rflags;
+ pvalues[1].voffset = foffset;
+ pvalues[1].bit1 = "List Typeless";
+ pvalues[1].bit1hfname = hf_bit1lflags;
+ pvalues[1].bit2 = "List Containers";
+ pvalues[1].bit2hfname = hf_bit2lflags;
+ pvalues[1].bit3 = "List Slashed";
+ pvalues[1].bit3hfname = hf_bit3lflags;
+ pvalues[1].bit4 = "List Dotted";
+ pvalues[1].bit4hfname = hf_bit4lflags;
+ pvalues[1].bit5 = "Dereference Alias";
+ pvalues[1].bit5hfname = hf_bit5lflags;
+ pvalues[1].bit6 = "List All Containers";
+ pvalues[1].bit6hfname = hf_bit6lflags;
+ pvalues[1].bit7 = "List Obsolete";
+ pvalues[1].bit7hfname = hf_bit7lflags;
+ pvalues[1].bit8 = "List Tuned Output";
+ pvalues[1].bit8hfname = hf_bit8lflags;
+ pvalues[1].bit9 = "List External Reference";
+ pvalues[1].bit9hfname = hf_bit9lflags;
+ pvalues[1].bit10 = "Not Defined";
+ pvalues[1].bit10hfname = hf_bit10lflags;
+ pvalues[1].bit11 = "Not Defined";
+ pvalues[1].bit11hfname = hf_bit11lflags;
+ pvalues[1].bit12 = "Not Defined";
+ pvalues[1].bit12hfname = hf_bit12lflags;
+ pvalues[1].bit13 = "Not Defined";
+ pvalues[1].bit13hfname = hf_bit13lflags;
+ pvalues[1].bit14 = "Not Defined";
+ pvalues[1].bit14hfname = hf_bit14lflags;
+ pvalues[1].bit15 = "Not Defined";
+ pvalues[1].bit15hfname = hf_bit15lflags;
+ pvalues[1].bit16 = "Not Defined";
+ pvalues[1].bit16hfname = hf_bit16lflags;
+ foffset = foffset+pvalues[1].vlength;
+ foffset += 2;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_iteration;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vtype = VTYPE_UINT32;
+ pvalues[3].vdesc = "Parent ID: 0x%08x";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = foffset;
+ pvalues[3].hfname= hf_nds_parent;
+ foffset = foffset+pvalues[3].vlength;
+ pvalues[4].vvalue = tvb_get_letohs(tvb, foffset);
+ global_flags = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vtype = VTYPE_BITFIELD;
+ pvalues[4].vdesc = "Information Flags (low) Byte:";
+ pvalues[4].vlength = 2;
+ pvalues[4].hfname= hf_nds_rflags;
+ pvalues[4].voffset = foffset;
+ pvalues[4].bit1 = "Output Flags";
+ pvalues[4].bit1hfname = hf_bit1infoflagsl;
+ pvalues[4].bit2 = "Entry ID";
+ pvalues[4].bit2hfname = hf_bit2infoflagsl;
+ pvalues[4].bit3 = "Entry Flags";
+ pvalues[4].bit3hfname = hf_bit3infoflagsl;
+ pvalues[4].bit4 = "Subordinate Count";
+ pvalues[4].bit4hfname = hf_bit4infoflagsl;
+ pvalues[4].bit5 = "Modification Time";
+ pvalues[4].bit5hfname = hf_bit5infoflagsl;
+ pvalues[4].bit6 = "Modification Timestamp";
+ pvalues[4].bit6hfname = hf_bit6infoflagsl;
+ pvalues[4].bit7 = "Creation Timestamp";
+ pvalues[4].bit7hfname = hf_bit7infoflagsl;
+ pvalues[4].bit8 = "Partition Root ID";
+ pvalues[4].bit8hfname = hf_bit8infoflagsl;
+ pvalues[4].bit9 = "Parent ID";
+ pvalues[4].bit9hfname = hf_bit9infoflagsl;
+ pvalues[4].bit10 = "Revision Count";
+ pvalues[4].bit10hfname = hf_bit10infoflagsl;
+ pvalues[4].bit11 = "Replica Type";
+ pvalues[4].bit11hfname = hf_bit11infoflagsl;
+ pvalues[4].bit12 = "Base Class";
+ pvalues[4].bit12hfname = hf_bit12infoflagsl;
+ pvalues[4].bit13 = "Relative Distinguished Name";
+ pvalues[4].bit13hfname = hf_bit13infoflagsl;
+ pvalues[4].bit14 = "Distinguished Name";
+ pvalues[4].bit14hfname = hf_bit14infoflagsl;
+ pvalues[4].bit15 = "Root Distinguished Name";
+ pvalues[4].bit15hfname = hf_bit15infoflagsl;
+ pvalues[4].bit16 = "Parent Distinguished Name";
+ pvalues[4].bit16hfname = hf_bit16infoflagsl;
+ foffset = foffset+2;
+ pvalues[5].vvalue = tvb_get_letohs(tvb, foffset);
+ pvalues[5].vtype = VTYPE_BITFIELD;
+ pvalues[5].vdesc = "Information Flags (high) Byte:";
+ pvalues[5].vlength = 2;
+ pvalues[5].hfname= hf_nds_rflags;
+ pvalues[5].voffset = foffset;
+ pvalues[5].bit1 = "Purge Time";
+ pvalues[5].bit1hfname = hf_bit1infoflagsh;
+ pvalues[5].bit2 = "Dereference Base Class";
+ pvalues[5].bit2hfname = hf_bit2infoflagsh;
+ pvalues[5].bit3 = "Not Defined";
+ pvalues[5].bit3hfname = hf_bit3infoflagsh;
+ pvalues[5].bit4 = "Not Defined";
+ pvalues[5].bit4hfname = hf_bit4infoflagsh;
+ pvalues[5].bit5 = "Not Defined";
+ pvalues[5].bit5hfname = hf_bit5infoflagsh;
+ pvalues[5].bit6 = "Not Defined";
+ pvalues[5].bit6hfname = hf_bit6infoflagsh;
+ pvalues[5].bit7 = "Not Defined";
+ pvalues[5].bit7hfname = hf_bit7infoflagsh;
+ pvalues[5].bit8 = "Not Defined";
+ pvalues[5].bit8hfname = hf_bit8infoflagsh;
+ pvalues[5].bit9 = "Not Defined";
+ pvalues[5].bit9hfname = hf_bit9infoflagsh;
+ pvalues[5].bit10 = "Not Defined";
+ pvalues[5].bit10hfname = hf_bit10infoflagsh;
+ pvalues[5].bit11 = "Not Defined";
+ pvalues[5].bit11hfname = hf_bit11infoflagsh;
+ pvalues[5].bit12 = "Not Defined";
+ pvalues[5].bit12hfname = hf_bit12infoflagsh;
+ pvalues[5].bit13 = "Not Defined";
+ pvalues[5].bit13hfname = hf_bit13infoflagsh;
+ pvalues[5].bit14 = "Not Defined";
+ pvalues[5].bit14hfname = hf_bit14infoflagsh;
+ pvalues[5].bit15 = "Not Defined";
+ pvalues[5].bit15hfname = hf_bit15infoflagsh;
+ pvalues[5].bit16 = "Not Defined";
+ pvalues[5].bit16hfname = hf_bit16infoflagsh;
+ foffset = foffset+2;
+ pvalues[6].vtype = VTYPE_STRING;
+ pvalues[6].vdesc = "Name Filter: %s";
+ pvalues[6].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[6].vvalue = 0;
+ pvalues[6].vlength = 256;
+ pvalues[6].vlength = tvb_get_letohl(tvb, foffset);
+ pvalues[6].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[6].voffset, pvalues[6].vlength, pvalues[6].vstring);
+ pvalues[6].hfname= hf_nds_name_filter;
+ foffset = foffset+pvalues[6].vlength;
+ if(pvalues[0].vvalue == 0)
+ {
+ break;
+ }
+ foffset += align_4(tvb, foffset);
+ pvalues[7].vtype = VTYPE_STRING;
+ pvalues[7].vdesc = "Class Filter: %s";
+ pvalues[7].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[7].vvalue = 0;
+ pvalues[7].vlength = 256;
+ pvalues[7].vlength = tvb_get_letohl(tvb, foffset);
+ pvalues[7].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[7].voffset, pvalues[7].vlength, pvalues[7].vstring);
+ pvalues[7].hfname= hf_nds_class_filter;
+ foffset = foffset+pvalues[7].vlength;
+ if(pvalues[0].vvalue == 1)
+ {
+ break;
+ }
+ foffset += align_4(tvb, foffset);
+ pvalues[8].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[8].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[8].vdesc = "Seconds: %u";
+ pvalues[8].vlength = 4;
+ pvalues[8].mvtype = MVTYPE_PRINT_TIMESTAMP;
+ pvalues[8].hfname= hf_nds_time_filter;
+ pvalues[8].voffset = foffset;
+ break;
+ case 0x06:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vstring = "";
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vstring = "";
+ pvalues[1].vdesc = "Request Flags: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].hfname= hf_nds_rflags;
+ pvalues[1].voffset = foffset;
+ foffset = foffset+4;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_iteration;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vstring = "";
+ pvalues[3].vtype = VTYPE_UINT32;
+ pvalues[3].vdesc = "Base Entry ID: 0x%08x";
+ pvalues[3].vlength = 4;
+ resolve_eid = FALSE;
+ global_eid = pvalues[3].vvalue;
+ pvalues[3].voffset = foffset;
+ pvalues[3].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[3].vlength;
+ pvalues[4].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vstring = match_strval(pvalues[4].vvalue, nds_search_scope);
+ if(pvalues[4].vstring == NULL)
+ {
+ pvalues[4].vstring = "No Search Scope Defined";
+ }
+ pvalues[4].vtype = VTYPE_STRING;
+ pvalues[4].vdesc = "Replica Type: %s";
+ pvalues[4].vlength = 4;
+ pvalues[4].voffset = foffset;
+ pvalues[4].mvtype = 0;
+ pvalues[4].hfname= hf_nds_search_scope;
+ foffset = foffset + pvalues[4].vlength;
+ pvalues[5].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[5].vtype = VTYPE_UINT32;
+ pvalues[5].vdesc = "Number of Objects to Search: 0x%08x";
+ pvalues[5].vlength = 4;
+ pvalues[5].voffset = foffset;
+ pvalues[5].hfname= hf_nds_num_objects;
+ foffset = foffset+pvalues[5].vlength;
+ pvalues[6].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[6].vtype = VTYPE_BITFIELD;
+ pvalues[6].vdesc = "Information Types:";
+ pvalues[6].vlength = 2;
+ pvalues[6].hfname= hf_nds_nflags;
+ pvalues[6].voffset = foffset;
+ pvalues[6].bit1 = "Names";
+ pvalues[6].bit1hfname = hf_bit1siflags;
+ pvalues[6].bit2 = "Names and Values";
+ pvalues[6].bit2hfname = hf_bit2siflags;
+ pvalues[6].bit3 = "Effective Privileges";
+ pvalues[6].bit3hfname = hf_bit3siflags;
+ pvalues[6].bit4 = "Value Info";
+ pvalues[6].bit4hfname = hf_bit4siflags;
+ pvalues[6].bit5 = "Abbreviated Value";
+ pvalues[6].bit5hfname = hf_bit5siflags;
+ pvalues[6].bit6 = "Not Defined";
+ pvalues[6].bit6hfname = hf_bit6siflags;
+ pvalues[6].bit7 = "Not Defined";
+ pvalues[6].bit7hfname = hf_bit7siflags;
+ pvalues[6].bit8 = "Not Defined";
+ pvalues[6].bit8hfname = hf_bit8siflags;
+ pvalues[6].bit9 = "Expanded Class";
+ pvalues[6].bit9hfname = hf_bit9siflags;
+ pvalues[6].bit10 = "Not Defined";
+ pvalues[6].bit10hfname = hf_bit10siflags;
+ pvalues[6].bit11= "Not Defined";
+ pvalues[6].bit11hfname = hf_bit11siflags;
+ pvalues[6].bit12 = "Not Defined";
+ pvalues[6].bit12hfname = hf_bit12siflags;
+ pvalues[6].bit13 = "Not Defined";
+ pvalues[6].bit13hfname = hf_bit13siflags;
+ pvalues[6].bit14 = "Not Defined";
+ pvalues[6].bit14hfname = hf_bit14siflags;
+ pvalues[6].bit15 = "Not Defined";
+ pvalues[6].bit15hfname = hf_bit15siflags;
+ pvalues[6].bit16 = "Not Defined";
+ pvalues[6].bit16hfname = hf_bit16siflags;
+ foffset = foffset+4;
+ if(pvalues[0].vvalue != 2)
+ {
+ pvalues[7].vvalue = tvb_get_letohs(tvb, foffset);
+ global_flags = tvb_get_letohl(tvb, foffset);
+ pvalues[7].vtype = VTYPE_BITFIELD;
+ pvalues[7].vdesc = "Information Flags (low) Byte:";
+ pvalues[7].vlength = 2;
+ pvalues[7].hfname= hf_nds_rflags;
+ pvalues[7].voffset = foffset;
+ pvalues[7].bit1 = "Output Flags";
+ pvalues[7].bit1hfname = hf_bit1infoflagsl;
+ pvalues[7].bit2 = "Entry ID";
+ pvalues[7].bit2hfname = hf_bit2infoflagsl;
+ pvalues[7].bit3 = "Entry Flags";
+ pvalues[7].bit3hfname = hf_bit3infoflagsl;
+ pvalues[7].bit4 = "Subordinate Count";
+ pvalues[7].bit4hfname = hf_bit4infoflagsl;
+ pvalues[7].bit5 = "Modification Time";
+ pvalues[7].bit5hfname = hf_bit5infoflagsl;
+ pvalues[7].bit6 = "Modification Timestamp";
+ pvalues[7].bit6hfname = hf_bit6infoflagsl;
+ pvalues[7].bit7 = "Creation Timestamp";
+ pvalues[7].bit7hfname = hf_bit7infoflagsl;
+ pvalues[7].bit8 = "Partition Root ID";
+ pvalues[7].bit8hfname = hf_bit8infoflagsl;
+ pvalues[7].bit9 = "Parent ID";
+ pvalues[7].bit9hfname = hf_bit9infoflagsl;
+ pvalues[7].bit10 = "Revision Count";
+ pvalues[7].bit10hfname = hf_bit10infoflagsl;
+ pvalues[7].bit11 = "Replica Type";
+ pvalues[7].bit11hfname = hf_bit11infoflagsl;
+ pvalues[7].bit12 = "Base Class";
+ pvalues[7].bit12hfname = hf_bit12infoflagsl;
+ pvalues[7].bit13 = "Relative Distinguished Name";
+ pvalues[7].bit13hfname = hf_bit13infoflagsl;
+ pvalues[7].bit14 = "Distinguished Name";
+ pvalues[7].bit14hfname = hf_bit14infoflagsl;
+ pvalues[7].bit15 = "Root Distinguished Name";
+ pvalues[7].bit15hfname = hf_bit15infoflagsl;
+ pvalues[7].bit16 = "Parent Distinguished Name";
+ pvalues[7].bit16hfname = hf_bit16infoflagsl;
+ foffset = foffset+2;
+ pvalues[8].vvalue = tvb_get_letohs(tvb, foffset);
+ pvalues[8].vtype = VTYPE_BITFIELD;
+ pvalues[8].vdesc = "Information Flags (high) Byte:";
+ pvalues[8].vlength = 2;
+ pvalues[8].hfname= hf_nds_rflags;
+ pvalues[8].voffset = foffset;
+ pvalues[8].bit1 = "Purge Time";
+ pvalues[8].bit1hfname = hf_bit1infoflagsh;
+ pvalues[8].bit2 = "Dereference Base Class";
+ pvalues[8].bit2hfname = hf_bit2infoflagsh;
+ pvalues[8].bit3 = "Not Defined";
+ pvalues[8].bit3hfname = hf_bit3infoflagsh;
+ pvalues[8].bit4 = "Not Defined";
+ pvalues[8].bit4hfname = hf_bit4infoflagsh;
+ pvalues[8].bit5 = "Not Defined";
+ pvalues[8].bit5hfname = hf_bit5infoflagsh;
+ pvalues[8].bit6 = "Not Defined";
+ pvalues[8].bit6hfname = hf_bit6infoflagsh;
+ pvalues[8].bit7 = "Not Defined";
+ pvalues[8].bit7hfname = hf_bit7infoflagsh;
+ pvalues[8].bit8 = "Not Defined";
+ pvalues[8].bit8hfname = hf_bit8infoflagsh;
+ pvalues[8].bit9 = "Not Defined";
+ pvalues[8].bit9hfname = hf_bit9infoflagsh;
+ pvalues[8].bit10 = "Not Defined";
+ pvalues[8].bit10hfname = hf_bit10infoflagsh;
+ pvalues[8].bit11 = "Not Defined";
+ pvalues[8].bit11hfname = hf_bit11infoflagsh;
+ pvalues[8].bit12 = "Not Defined";
+ pvalues[8].bit12hfname = hf_bit12infoflagsh;
+ pvalues[8].bit13 = "Not Defined";
+ pvalues[8].bit13hfname = hf_bit13infoflagsh;
+ pvalues[8].bit14 = "Not Defined";
+ pvalues[8].bit14hfname = hf_bit14infoflagsh;
+ pvalues[8].bit15 = "Not Defined";
+ pvalues[8].bit15hfname = hf_bit15infoflagsh;
+ pvalues[8].bit16 = "Not Defined";
+ pvalues[8].bit16hfname = hf_bit16infoflagsh;
+ foffset = foffset+2;
+ }
+ break;
+ case 0x07:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vstring = "";
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vstring = "";
+ pvalues[1].vdesc = "Request Flags: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].hfname= hf_nds_rflags;
+ pvalues[1].voffset = foffset;
+ foffset = foffset+4;
+ if(pvalues[0].vvalue == 0)
+ {
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vstring = "";
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Parent Entry ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ resolve_eid = FALSE;
+ global_eid = pvalues[2].vvalue;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "Relative Distinguished Name: %s";
+ pvalues[3].vstring = "";
+ pvalues[3].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[3].vvalue = 0;
+ pvalues[3].vlength = 256;
+ pvalues[3].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[3].vlength == 0x00)
+ {
+ pvalues[3].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[3].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[3].voffset, pvalues[3].vlength, req_buffer.buffer);
+ pvalues[3].vstring = req_buffer.buffer;
+ strcpy(global_object_name, req_buffer.buffer);
+ pvalues[3].hfname= hf_nds_relative_dn;
+ foffset = foffset+pvalues[3].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[4].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[4].vstring = "";
+ pvalues[4].vdesc = "Attributes: %u";
+ pvalues[4].vlength = 4;
+ pvalues[4].voffset = foffset;
+ pvalues[4].mvtype = MVTYPE_ADD_ATTR_REQUEST;
+ pvalues[4].hfname= hf_nds_attr;
+ }
+ else
+ {
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vstring = "";
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_iteration;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vstring = "";
+ pvalues[3].vtype = VTYPE_UINT32;
+ pvalues[3].vdesc = "Parent Entry ID: 0x%08x";
+ pvalues[3].vlength = 4;
+ resolve_eid = FALSE;
+ global_eid = pvalues[3].vvalue;
+ pvalues[3].voffset = foffset;
+ pvalues[3].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[3].vlength;
+ pvalues[4].vtype = VTYPE_STRING;
+ pvalues[4].vdesc = "Relative Distinguished Name: %s";
+ pvalues[4].vstring = "";
+ pvalues[4].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[4].vvalue = 0;
+ pvalues[4].vlength = 256;
+ pvalues[4].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[4].vlength == 0x00)
+ {
+ pvalues[4].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[4].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[4].voffset, pvalues[4].vlength, req_buffer.buffer);
+ pvalues[4].vstring = req_buffer.buffer;
+ strcpy(global_object_name, req_buffer.buffer);
+ pvalues[4].hfname= hf_nds_relative_dn;
+ foffset = foffset+pvalues[4].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[5].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[5].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[5].vstring = "";
+ pvalues[5].vdesc = "Attributes: %u";
+ pvalues[5].vlength = 4;
+ pvalues[5].voffset = foffset;
+ pvalues[5].mvtype = MVTYPE_ADD_ATTR_REQUEST;
+ pvalues[5].hfname= hf_nds_attr;
+ }
+ break;
+ case 0x08:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Entry ID: 0x%08x";
+ pvalues[1].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[1].vvalue;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[1].vlength;
+ break;
+ case 0x09:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ if(pvalues[0].vvalue == 0)
+ {
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vstring = "";
+ pvalues[1].vdesc = "Iteration Handle: 0x%08x"; /* always 0 */
+ pvalues[1].vlength = 4;
+ pvalues[1].hfname= hf_nds_iteration;
+ pvalues[1].voffset = foffset;
+ foffset = foffset+4;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vstring = "";
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Entry ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ resolve_eid = TRUE;
+ global_eid = pvalues[2].vvalue;
+ pvalues[2].hfname = hf_nds_eid;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[3].vstring = "";
+ pvalues[3].vdesc = "Number of Attributes to Change %u";
+ pvalues[3].vlength = 4;
+ pvalues[3].mvtype = MVTYPE_MODIFY_ATTR_REQUEST;
+ pvalues[3].hfname= hf_nds_number_of_changes;
+ pvalues[3].voffset = foffset;
+ }
+ else
+ {
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vstring = "";
+ pvalues[1].vdesc = "Request Flags: 0x%08x"; /* always 0 */
+ pvalues[1].vlength = 4;
+ pvalues[1].hfname= hf_nds_rflags;
+ pvalues[1].voffset = foffset;
+ foffset = foffset+4;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vstring = "";
+ pvalues[2].vdesc = "Iteration Handle: 0x%08x"; /* always 0 */
+ pvalues[2].vlength = 4;
+ pvalues[2].hfname= hf_nds_iteration;
+ pvalues[2].voffset = foffset;
+ foffset = foffset+4;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vstring = "";
+ pvalues[3].vtype = VTYPE_UINT32;
+ pvalues[3].vdesc = "Entry ID: 0x%08x";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = foffset;
+ resolve_eid = TRUE;
+ global_eid = pvalues[3].vvalue;
+ pvalues[3].hfname = hf_nds_eid;
+ foffset = foffset+pvalues[3].vlength;
+ pvalues[4].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[4].vstring = "";
+ pvalues[4].vdesc = "Number of Attributes to Change %u";
+ pvalues[4].vlength = 4;
+ pvalues[4].mvtype = MVTYPE_MODIFY_ATTR_REQUEST;
+ pvalues[4].hfname= hf_nds_number_of_changes;
+ pvalues[4].voffset = foffset;
+ }
+ break;
+ case 0x0a:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Entry ID: 0x%08x";
+ pvalues[1].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[1].vvalue;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname = hf_nds_eid;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_BOOLEAN;
+ pvalues[2].vdesc = "Keep Original RDN: %s";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].mvtype = 0;
+ pvalues[2].hfname= hf_nds_keep;
+ foffset = foffset+4;
+ foffset += align_4(tvb, foffset);
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "New RDN: %s";
+ pvalues[3].mvtype = 0;
+ pvalues[3].vvalue = 0;
+ pvalues[3].vlength = 256;
+ pvalues[3].vlength = tvb_get_letohl(tvb, foffset);
+ pvalues[3].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[3].voffset, pvalues[3].vlength, pvalues[3].vstring);
+ pvalues[3].hfname= hf_nds_new_rdn;
+ foffset = foffset+pvalues[3].vlength;
+ break;
+ case 0x0b:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohs(tvb, foffset);
+ global_flags = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_BITFIELD;
+ pvalues[1].vdesc = "Attribute Constraints:";
+ pvalues[1].vlength = 2;
+ pvalues[1].hfname= hf_nds_acflags;
+ pvalues[1].voffset = foffset;
+ pvalues[1].bit1 = "Single Valued";
+ pvalues[1].bit1hfname = hf_bit1acflags;
+ pvalues[1].bit2 = "Sized";
+ pvalues[1].bit2hfname = hf_bit2acflags;
+ pvalues[1].bit3 = "Non-Removable";
+ pvalues[1].bit3hfname = hf_bit3acflags;
+ pvalues[1].bit4 = "Read Only";
+ pvalues[1].bit4hfname = hf_bit4acflags;
+ pvalues[1].bit5 = "Hidden";
+ pvalues[1].bit5hfname = hf_bit5acflags;
+ pvalues[1].bit6 = "String";
+ pvalues[1].bit6hfname = hf_bit6acflags;
+ pvalues[1].bit7 = "Synchronize Immediate";
+ pvalues[1].bit7hfname = hf_bit7acflags;
+ pvalues[1].bit8 = "Public Read";
+ pvalues[1].bit8hfname = hf_bit8acflags;
+ pvalues[1].bit9 = "Server Read";
+ pvalues[1].bit9hfname = hf_bit9acflags;
+ pvalues[1].bit10 = "Write Managed";
+ pvalues[1].bit10hfname = hf_bit10acflags;
+ pvalues[1].bit11 = "Per Replica";
+ pvalues[1].bit11hfname = hf_bit11acflags;
+ pvalues[1].bit12 = "Never Schedule Synchronization";
+ pvalues[1].bit12hfname = hf_bit12acflags;
+ pvalues[1].bit13 = "Operational";
+ pvalues[1].bit13hfname = hf_bit13acflags;
+ pvalues[1].bit14 = "Not Defined";
+ pvalues[1].bit14hfname = hf_bit14acflags;
+ pvalues[1].bit15 = "Not Defined";
+ pvalues[1].bit15hfname = hf_bit15acflags;
+ pvalues[1].bit16 = "Not Defined";
+ pvalues[1].bit16hfname = hf_bit16acflags;
+ foffset = foffset+4;
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Attribute Name: %s";
+ pvalues[2].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[2].vvalue = 0;
+ pvalues[2].vlength = 256;
+ pvalues[2].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[2].vlength == 0x00)
+ {
+ pvalues[2].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[2].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[2].voffset, pvalues[2].vlength, req_buffer.buffer);
+ pvalues[2].vstring = req_buffer.buffer;
+ strcpy(global_object_name, req_buffer.buffer);
+ pvalues[2].hfname= hf_nds_name;
+ foffset = foffset+pvalues[2].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vstring = match_strval(pvalues[3].vvalue, nds_syntax);
+ if(pvalues[3].vstring == NULL)
+ {
+ pvalues[3].vstring = "No Syntax Found";
+ }
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "Syntax: %s";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = foffset;
+ pvalues[3].hfname= hf_nds_syntax;
+ pvalues[3].mvtype = 0;
+ foffset = foffset+pvalues[3].vlength;
+ pvalues[4].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vtype = VTYPE_UINT32;
+ pvalues[4].vdesc = "Lower Limit Value %u";
+ pvalues[4].vlength = 4;
+ pvalues[4].voffset = foffset;
+ pvalues[4].hfname = hf_nds_lower;
+ foffset += 4;
+ pvalues[5].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[5].vtype = VTYPE_UINT32;
+ pvalues[5].vdesc = "Upper Limit Value %u";
+ pvalues[5].vlength = 4;
+ pvalues[5].voffset = foffset;
+ pvalues[5].hfname = hf_nds_upper;
+ foffset += 4;
+ pvalues[6].vvalue = tvb_get_letohl(tvb, foffset); /* Length of bytes field */
+ foffset += 4;
+ pvalues[6].vtype = VTYPE_BYTES;
+ pvalues[6].vdesc = "ASN.1 ID";
+ pvalues[6].vlength = pvalues[6].vvalue;
+ pvalues[6].voffset = foffset;
+ pvalues[6].hfname = hf_nds_asn1;
+ break;
+ case 0x0c:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x0d:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vtype = VTYPE_STRING;
+ pvalues[1].vdesc = "Attribute Name: %s";
+ pvalues[1].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[1].vvalue = 0;
+ pvalues[1].vlength = 256;
+ pvalues[1].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[1].vlength == 0x00)
+ {
+ pvalues[1].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[1].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[1].voffset, pvalues[1].vlength, req_buffer.buffer);
+ pvalues[1].vstring = req_buffer.buffer;
+ strcpy(global_object_name, req_buffer.buffer);
+ pvalues[1].hfname= hf_nds_attribute_dn;
+ break;
+ case 0x0e:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x0f:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname= hf_nds_iteration;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ global_flags = pvalues[2].vvalue;
+ pvalues[2].vstring = match_strval(pvalues[2].vvalue, class_def_type);
+ if(pvalues[2].vstring == NULL)
+ {
+ pvalues[2].vstring = "No Class Definition Type Set";
+ }
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Class Definition Type: %s";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].mvtype = 0;
+ pvalues[2].hfname= hf_nds_class_def_type;
+ foffset = foffset + pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ if (pvalues[3].vvalue == 0x00000000)
+ {
+ pvalues[3].vstring = "Do Not Return All Classes";
+ pvalues[3].mvtype = 0;
+ }
+ else
+ {
+ pvalues[3].vstring = "Return All Classes";
+ pvalues[3].mvtype = MVTYPE_ATTR_REQUEST;
+ }
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "%s";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = foffset;
+ pvalues[3].hfname= hf_nds_return_all_classes;
+ foffset = foffset + pvalues[3].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[4].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[4].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[4].vdesc = "Classes: %d";
+ pvalues[4].vlength = 4;
+ pvalues[4].voffset = foffset;
+ pvalues[4].mvtype = MVTYPE_READ_CLASS_REQ;
+ pvalues[4].hfname= hf_nds_classes;
+ break;
+ case 0x10:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vtype = VTYPE_STRING;
+ pvalues[1].vdesc = "Class Name: %s";
+ pvalues[1].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[1].vvalue = 0;
+ pvalues[1].vlength = 256;
+ pvalues[1].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[1].vlength == 0x00)
+ {
+ pvalues[1].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[1].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[1].voffset, pvalues[1].vlength, req_buffer.buffer);
+ pvalues[1].vstring = req_buffer.buffer;
+ strcpy(global_object_name, req_buffer.buffer);
+ pvalues[1].hfname= hf_nds_base_class;
+ foffset = foffset+pvalues[1].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_MULTIVALUE_UINT32;
+ pvalues[2].vdesc = "Number of Attributes to Add: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].mvtype = MVTYPE_MODIFY_CLASS;
+ pvalues[2].hfname= hf_nds_att_add;
+ break;
+ case 0x11:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vtype = VTYPE_STRING;
+ pvalues[1].vdesc = "Class Name: %s";
+ pvalues[1].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[1].vvalue = 0;
+ pvalues[1].vlength = 256;
+ pvalues[1].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[1].vlength == 0x00)
+ {
+ pvalues[1].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[1].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[1].voffset, pvalues[1].vlength, req_buffer.buffer);
+ pvalues[1].vstring = req_buffer.buffer;
+ strcpy(global_object_name, req_buffer.buffer);
+ pvalues[1].hfname= hf_nds_base;
+ break;
+ case 0x12:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname= hf_nds_iteration;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Entry ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[2].vvalue;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[2].vlength;
+ break;
+ case 0x13:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Entry ID: 0x%08x";
+ pvalues[1].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[1].vvalue;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vtype = VTYPE_STRING;
+ pvalues[2].vdesc = "Trustee Name: %s";
+ pvalues[2].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[2].vvalue = 0;
+ pvalues[2].vlength = 256;
+ pvalues[2].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[2].vlength == 0x00)
+ {
+ pvalues[2].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[2].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[2].voffset, pvalues[2].vlength, req_buffer.buffer);
+ pvalues[2].vstring = req_buffer.buffer;
+ pvalues[2].hfname= hf_nds_name;
+ foffset = foffset+pvalues[2].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "Attribute to be Checked: %s";
+ pvalues[3].mvtype = 0;
+ pvalues[3].vvalue = 0;
+ pvalues[3].vlength = 256;
+ pvalues[3].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[3].vlength == 0x00)
+ {
+ pvalues[3].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[3].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[3].voffset, pvalues[3].vlength, pvalues[3].vstring);
+ pvalues[3].hfname= hf_nds_name;
+ foffset = foffset+pvalues[3].vlength;
+ foffset += align_4(tvb, foffset);
+ if(pvalues[0].vvalue != 0)
+ {
+ pvalues[4].vtype = VTYPE_STRING;
+ pvalues[4].vdesc = "Security Equivalence: %s";
+ pvalues[4].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[4].vvalue = 0;
+ pvalues[4].vlength = 256;
+ pvalues[4].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[4].vlength == 0x00)
+ {
+ pvalues[4].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[4].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[4].voffset, pvalues[4].vlength, pvalues[4].vstring);
+ pvalues[4].hfname= hf_nds_name;
+ foffset = foffset+pvalues[4].vlength;
+ foffset += align_4(tvb, foffset);
+ }
+ break;
+ case 0x14:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x15:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x16:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_BITFIELD;
+ pvalues[1].vdesc = "Request Flags:";
+ pvalues[1].vlength = 2;
+ pvalues[1].hfname= hf_nds_rflags;
+ pvalues[1].voffset = foffset;
+ pvalues[1].bit1 = "Typeless";
+ pvalues[1].bit1hfname = hf_nds_bit1;
+ pvalues[1].bit2 = "All Containers";
+ pvalues[1].bit2hfname = hf_nds_bit2;
+ pvalues[1].bit3 = "Slashed";
+ pvalues[1].bit3hfname = hf_nds_bit3;
+ pvalues[1].bit4 = "Dotted";
+ pvalues[1].bit4hfname = hf_nds_bit4;
+ pvalues[1].bit5 = "Tuned";
+ pvalues[1].bit5hfname = hf_nds_bit5;
+ pvalues[1].bit6 = "Not Defined";
+ pvalues[1].bit6hfname = hf_nds_bit6;
+ pvalues[1].bit7 = "Not Defined";
+ pvalues[1].bit7hfname = hf_nds_bit7;
+ pvalues[1].bit8 = "Not Defined";
+ pvalues[1].bit8hfname = hf_nds_bit8;
+ pvalues[1].bit9 = "Not Defined";
+ pvalues[1].bit9hfname = hf_nds_bit9;
+ pvalues[1].bit10 = "Not Defined";
+ pvalues[1].bit10hfname = hf_nds_bit10;
+ pvalues[1].bit11 = "Not Defined";
+ pvalues[1].bit11hfname = hf_nds_bit11;
+ pvalues[1].bit12 = "Not Defined";
+ pvalues[1].bit12hfname = hf_nds_bit12;
+ pvalues[1].bit13 = "Not Defined";
+ pvalues[1].bit13hfname = hf_nds_bit13;
+ pvalues[1].bit14 = "Not Defined";
+ pvalues[1].bit14hfname = hf_nds_bit14;
+ pvalues[1].bit15 = "Not Defined";
+ pvalues[1].bit15hfname = hf_nds_bit15;
+ pvalues[1].bit16 = "Not Defined";
+ pvalues[1].bit16hfname = hf_nds_bit16;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Iteration Handle: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_iteration;
+ foffset = foffset+pvalues[2].vlength;
+ if(pvalues[0].vvalue == 0)
+ {
+ global_flags = 0x000000c0;
+ break;
+ }
+ pvalues[3].vvalue = tvb_get_letohs(tvb, foffset);
+ pvalues[3].vtype = VTYPE_BITFIELD;
+ pvalues[3].vdesc = "Information Flags (low) Byte:";
+ pvalues[3].vlength = 2;
+ pvalues[3].hfname= hf_nds_rflags;
+ pvalues[3].voffset = foffset;
+ pvalues[3].bit1 = "Output Flags";
+ pvalues[3].bit1hfname = hf_bit1l1flagsl;
+ pvalues[3].bit2 = "Entry ID";
+ pvalues[3].bit2hfname = hf_bit2l1flagsl;
+ pvalues[3].bit3 = "Replica State";
+ pvalues[3].bit3hfname = hf_bit3l1flagsl;
+ pvalues[3].bit4 = "Modification Timestamp";
+ pvalues[3].bit4hfname = hf_bit4l1flagsl;
+ pvalues[3].bit5 = "Purge Time";
+ pvalues[3].bit5hfname = hf_bit5l1flagsl;
+ pvalues[3].bit6 = "Local Partition ID";
+ pvalues[3].bit6hfname = hf_bit6l1flagsl;
+ pvalues[3].bit7 = "Distinguished Name";
+ pvalues[3].bit7hfname = hf_bit7l1flagsl;
+ pvalues[3].bit8 = "Replica Type";
+ pvalues[3].bit8hfname = hf_bit8l1flagsl;
+ pvalues[3].bit9 = "Partition Busy";
+ pvalues[3].bit9hfname = hf_bit9l1flagsl;
+ pvalues[3].bit10 = "Not Defined";
+ pvalues[3].bit10hfname = hf_bit10l1flagsl;
+ pvalues[3].bit11 = "Not Defined";
+ pvalues[3].bit11hfname = hf_bit11l1flagsl;
+ pvalues[3].bit12 = "Not Defined";
+ pvalues[3].bit12hfname = hf_bit12l1flagsl;
+ pvalues[3].bit13 = "Not Defined";
+ pvalues[3].bit13hfname = hf_bit13l1flagsl;
+ pvalues[3].bit14 = "Not Defined";
+ pvalues[3].bit14hfname = hf_bit14l1flagsl;
+ pvalues[3].bit15 = "Not Defined";
+ pvalues[3].bit15hfname = hf_bit15l1flagsl;
+ pvalues[3].bit16 = "Not Defined";
+ pvalues[3].bit16hfname = hf_bit16l1flagsl;
+ global_flags = pvalues[3].vvalue;
+ foffset = foffset+2;
+ pvalues[4].vvalue = tvb_get_letohs(tvb, foffset);
+ pvalues[4].vtype = VTYPE_BITFIELD;
+ pvalues[4].vdesc = "Information Flags (high) Byte:";
+ pvalues[4].vlength = 2;
+ pvalues[4].hfname= hf_nds_rflags;
+ pvalues[4].voffset = foffset;
+ pvalues[4].bit1 = "Not Defined";
+ pvalues[4].bit1hfname = hf_bit1l1flagsl;
+ pvalues[4].bit2 = "Not Defined";
+ pvalues[4].bit2hfname = hf_bit2l1flagsl;
+ pvalues[4].bit3 = "Not Defined";
+ pvalues[4].bit3hfname = hf_bit3l1flagsl;
+ pvalues[4].bit4 = "Not Defined";
+ pvalues[4].bit4hfname = hf_bit4l1flagsl;
+ pvalues[4].bit5 = "Not Defined";
+ pvalues[4].bit5hfname = hf_bit5l1flagsl;
+ pvalues[4].bit6 = "Not Defined";
+ pvalues[4].bit6hfname = hf_bit6l1flagsl;
+ pvalues[4].bit7 = "Not Defined";
+ pvalues[4].bit7hfname = hf_bit7l1flagsl;
+ pvalues[4].bit8 = "Not Defined";
+ pvalues[4].bit8hfname = hf_bit8l1flagsl;
+ pvalues[4].bit9 = "Not Defined";
+ pvalues[4].bit9hfname = hf_bit9l1flagsl;
+ pvalues[4].bit10 = "Not Defined";
+ pvalues[4].bit10hfname = hf_bit10l1flagsl;
+ pvalues[4].bit11 = "Not Defined";
+ pvalues[4].bit11hfname = hf_bit11l1flagsl;
+ pvalues[4].bit12 = "Not Defined";
+ pvalues[4].bit12hfname = hf_bit12l1flagsl;
+ pvalues[4].bit13 = "Not Defined";
+ pvalues[4].bit13hfname = hf_bit13l1flagsl;
+ pvalues[4].bit14 = "Not Defined";
+ pvalues[4].bit14hfname = hf_bit14l1flagsl;
+ pvalues[4].bit15 = "Not Defined";
+ pvalues[4].bit15hfname = hf_bit15l1flagsl;
+ pvalues[4].bit16 = "Not Defined";
+ pvalues[4].bit16hfname = hf_bit16l1flagsl;
+ foffset = foffset+2;
+ if(pvalues[0].vvalue == 1)
+ {
+ break;
+ }
+ pvalues[5].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[5].vtype = VTYPE_UINT32;
+ pvalues[5].vdesc = "Partition Root ID: 0x%08x";
+ pvalues[5].vlength = 4;
+ pvalues[5].voffset = foffset;
+ pvalues[5].hfname= hf_nds_partition_root_id;
+ foffset = foffset+pvalues[5].vlength;
+ break;
+ case 0x17:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[0].vvalue;
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].hfname = hf_nds_ver;
+ pvalues[0].voffset = foffset;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[1].vvalue;
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Flags: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].hfname = hf_nds_req_flags;
+ pvalues[1].voffset = foffset;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "New Partition Root ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_new_part_id;
+ foffset = foffset+pvalues[2].vlength;
+ break;
+ case 0x18:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[0].vvalue;
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].hfname = hf_nds_ver;
+ pvalues[0].voffset = foffset;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[1].vvalue;
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Flags: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].hfname = hf_nds_req_flags;
+ pvalues[1].voffset = foffset;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Child Partition Root ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_child_part_id;
+ foffset = foffset+pvalues[2].vlength;
+ break;
+ case 0x19:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[0].vvalue;
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].hfname = hf_nds_ver;
+ pvalues[0].voffset = foffset;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[1].vvalue;
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Flags: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].hfname = hf_nds_req_flags;
+ pvalues[1].voffset = foffset;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Master Partition Root ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_master_part_id;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vstring = match_strval(pvalues[3].vvalue, nds_replica_type);
+ if(pvalues[3].vstring == NULL)
+ {
+ pvalues[3].vstring = "No Replica Type Found";
+ }
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "Replica Type: %s";
+ pvalues[3].vlength = 4;
+ pvalues[3].voffset = foffset;
+ pvalues[3].mvtype = 0;
+ pvalues[3].hfname= hf_replica_type;
+ foffset = foffset + pvalues[3].vlength;
+ pvalues[4].vtype = VTYPE_STRING;
+ pvalues[4].vdesc = "Target Server Name: %s";
+ pvalues[4].mvtype = 0;
+ pvalues[4].vvalue = 0;
+ pvalues[4].vlength = 256;
+ pvalues[4].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[4].vlength == 0x00)
+ {
+ pvalues[4].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[4].voffset = foffset+4;
+ foffset = foffset + 4;
+ get_string(tvb, pvalues[4].voffset, pvalues[4].vlength, pvalues[4].vstring);
+ pvalues[4].hfname= hf_nds_target_name;
+ break;
+ case 0x1a:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x1b:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[0].vvalue;
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].hfname = hf_nds_ver;
+ pvalues[0].voffset = foffset;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[1].vvalue;
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Streams Flags: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].hfname = hf_nds_stream_flags;
+ pvalues[1].voffset = foffset;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Entry ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[2].vvalue;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[2].vlength;
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "Stream Name: %s";
+ pvalues[3].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[3].vvalue = 0;
+ pvalues[3].vlength = 256;
+ pvalues[3].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[3].vlength == 0x00)
+ {
+ pvalues[3].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[3].voffset = foffset+4;
+ foffset += 4;
+ get_string(tvb, pvalues[3].voffset, pvalues[3].vlength, pvalues[3].vstring);
+ foffset += pvalues[3].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[3].hfname= hf_nds_stream_name;
+ break;
+ case 0x1c:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x1d:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x1e:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x1f:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x20:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x21:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x22:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x23:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x24:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x25:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x26:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[0].vvalue;
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].hfname = hf_nds_ver;
+ pvalues[0].voffset = foffset;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ nds_version = pvalues[1].vvalue;
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Flags: 0x%08x";
+ pvalues[1].vlength = 4;
+ pvalues[1].hfname = hf_nds_req_flags;
+ pvalues[1].voffset = foffset;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Time Delay in Seconds: %u";
+ pvalues[2].vlength = 4;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_time_delay;
+ foffset = foffset+pvalues[2].vlength;
+ if(pvalues[0].vvalue == 0)
+ {
+ pvalues[3].vtype = VTYPE_STRING;
+ pvalues[3].vdesc = "Root Most Object Name: %s";
+ pvalues[3].mvtype = MVTYPE_ATTR_REQUEST;
+ pvalues[3].vvalue = 0;
+ pvalues[3].vlength = 256;
+ pvalues[3].vlength = tvb_get_letohl(tvb, foffset);
+ if (pvalues[3].vlength == 0x00)
+ {
+ pvalues[3].vtype = VTYPE_NONE;
+ break;
+ }
+ pvalues[3].voffset = foffset+4;
+ foffset += 4;
+ get_string(tvb, pvalues[3].voffset, pvalues[3].vlength, pvalues[3].vstring);
+ foffset += pvalues[3].vlength;
+ foffset += align_4(tvb, foffset);
+ pvalues[3].hfname= hf_nds_root_name;
+ }
+ else
+ {
+ pvalues[3].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[3].vtype = VTYPE_UINT32;
+ pvalues[3].vdesc = "Entry ID: 0x%08x";
+ pvalues[3].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[3].vvalue;
+ pvalues[3].voffset = foffset;
+ pvalues[3].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[3].vlength;
+ resolve_eid = TRUE;
+ global_eid = pvalues[3].vvalue;
+ }
+ break;
+ case 0x27:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x28:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x29:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x2a:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x2b:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x2c:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x2d:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x2e:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x2f:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x30:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x31:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x32:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x33:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x34:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x35:
+ pvalues[0].vvalue = 0;
+ break;
+ case 0x36:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x37:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x38:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x39:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Entry ID: 0x%08x";
+ pvalues[1].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[1].vvalue;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[1].vlength;
+ break;
+ case 0x3a:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Reply Buffer Size: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_buffer_size;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Version: %u";
+ pvalues[1].vlength = 4;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[1].vlength;
+ pvalues[2].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[2].vtype = VTYPE_UINT32;
+ pvalues[2].vdesc = "Entry ID: 0x%08x";
+ pvalues[2].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[2].vvalue;
+ pvalues[2].voffset = foffset;
+ pvalues[2].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[2].vlength;
+ break;
+ case 0x3b:
+ pvalues[0].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[0].vtype = VTYPE_UINT32;
+ pvalues[0].vdesc = "Version: %u";
+ pvalues[0].vlength = 4;
+ pvalues[0].voffset = foffset;
+ pvalues[0].hfname= hf_nds_ver;
+ foffset = foffset+pvalues[0].vlength;
+ pvalues[1].vvalue = tvb_get_letohl(tvb, foffset);
+ pvalues[1].vtype = VTYPE_UINT32;
+ pvalues[1].vdesc = "Entry ID: 0x%08x";
+ pvalues[1].vlength = 4;
+ resolve_eid = TRUE;
+ global_eid = pvalues[1].vvalue;
+ pvalues[1].voffset = foffset;
+ pvalues[1].hfname= hf_nds_eid;
+ foffset = foffset+pvalues[1].vlength;
+ break;
+ case 0x3c:
+ break;
+ case 0x3d:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x3e:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x3f:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x40:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x41:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x42:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x43:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x44:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x45:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x46:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x47:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x48:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x49:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x4a:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x4b:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x4c:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ case 0x4d:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ break;
+ default:
+ pvalues[0].vtype = VTYPE_NONE; /* Not Defined */
+ }
+ }
+ /* Fill in the INFO column. */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (ncp_rec) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDS");
+ if (nds_frag != 0xffffffff) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "C Continue NDS Fragment %08x", nds_frag);
+ }
+ else {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "C NDS %s", verb_string);
+ }
+ run_info_str = TRUE;
+ }
+ else {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "C Unknown Function %d (0x%02x)",
+ func, func);
+ }
+
+ }
+
+ /* Keep track of the address and connection whence the request
+ came, and the address and connection to which the request
+ is being sent, so that we can match up calls with replies.
+ (We don't include the sequence number, as we may want
+ to have all packets over the same connection treated
+ as being part of a single conversation so that we can
+ let the user select that conversation to be displayed.) */
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, nw_connection, nw_connection, 0);
+ if (conversation == NULL) {
+ /* It's not part of any conversation - create a new one. */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ PT_NCP, nw_connection, nw_connection, 0);
+ }
+
+ if (!pinfo->fd->flags.visited) {
+ request_value = ncp_hash_insert(conversation, sequence, ncp_rec);
+ request_value->req_frame_num = pinfo->fd->num;
+ request_value->req_frame_time.secs=pinfo->fd->abs_secs;
+ request_value->req_frame_time.nsecs=pinfo->fd->abs_usecs*1000;
+
+ /* If this is the first time we're examining the packet,
+ * check to see if this NCP type uses a "request condition".
+ * If so, we have to build a proto_tree because request conditions
+ * use display filters to work, and without a proto_tree,
+ * display filters can't possibly work. If we already have
+ * a proto_tree, then wonderful. If we don't, we need to build
+ * one. */
+ if (ncp_rec && !ncp_tree) {
+ run_req_cond = TRUE;
+ }
+ /* Keep track of the Fragment number in the request for defrag logic */
+ request_value->nds_frag_num = nds_frag;
+ }
+
+ /* If we have to handle a request condition, or have to
+ add to the Info column, we need to construct a protocol
+ tree. If we already have a proto_tree, then wonderful.
+ If we don't, we need to build one. */
+ if ((run_info_str || run_req_cond) && !ncp_tree) {
+ proto_item *ti;
+
+ temp_tree = proto_tree_create_root();
+ proto_tree_set_visible(temp_tree, FALSE);
+ ti = proto_tree_add_item(temp_tree, proto_ncp, tvb, 0, -1, FALSE);
+ ncp_tree = proto_item_add_subtree(ti, ett_ncp);
+ }
+
+ if (ncp_tree) {
+ /* If the dissection throws an exception, be sure to free
+ * the temporary proto_tree that was created. Because of the
+ * way the CLEANUP_PUSH macro works, we can't put it in an 'if'
+ * block; it has to be in the same scope as the terminating
+ * CLEANUP_POP or CLEANUP_POP_AND_ALLOC. So, we always
+ * call CLEANUP_POP and friends, but the value of temp_tree is
+ * NULL if no cleanup is needed, and non-null if cleanup is needed.
+ */
+
+ CLEANUP_PUSH(free_proto_tree, temp_tree);
+
+ request_value = ncp_hash_lookup(conversation, sequence);
+
+ switch (type) {
+ case NCP_BROADCAST_SLOT:
+ ; /* nothing */
+ break;
+
+ case NCP_SERVICE_REQUEST:
+
+ ptvc = ptvcursor_new(ncp_tree, tvb, 7);
+ if (ncp_rec && ncp_rec->request_ptvc)
+ {
+ clear_repeat_vars();
+ process_ptvc_record(ptvc, ncp_rec->request_ptvc, NULL, TRUE, ncp_rec);
+ }
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_func, tvb, 6, 1,
+ func, "Function: %d (0x%02X), %s",
+ func, func, ncp_rec ? ncp_rec->name : "Unknown");
+
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_subfunc, tvb, 7, 1,
+ subfunc, "SubFunction: %d (0x%02x)",
+ subfunc, subfunc);
+
+ proto_tree_add_uint(ncp_tree, hf_ncp_fragment_handle, tvb, 8, 4,
+ nds_frag);
+
+ if (nds_frag == 0xffffffff) {
+
+ proto_tree_add_item(ncp_tree, hf_ncp_fragment_size, tvb, 12, 4, TRUE);
+
+ proto_tree_add_item(ncp_tree, hf_ncp_message_size, tvb, 16, 4, TRUE);
+
+ proto_tree_add_item(ncp_tree, hf_ncp_nds_flag, tvb, 20, 4, FALSE);
+
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_nds_verb, tvb, 24, 4,
+ nds_verb, "NDS Verb: %d, (0x%02x), %s",
+ nds_verb, nds_verb, verb_string);
+ added_arrow = FALSE;
+ for (i = 0; i < 9; i++) {
+ switch (pvalues[i].vtype) {
+
+ case VTYPE_NONE: /* no value */
+ break;
+
+ case VTYPE_UINT8:
+ proto_tree_add_uint_format(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vtype, "NDS Parameter not defined %d",
+ pvalues[i].vtype);
+ break;
+
+ case VTYPE_UINT16:
+ proto_tree_add_uint_format(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vtype, "NDS Parameter not defined %d",
+ pvalues[i].vtype);
+ break;
+
+ case VTYPE_UINT32:
+ proto_tree_add_uint_format(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vvalue, pvalues[i].vdesc,
+ pvalues[i].vvalue);
+ break;
+
+ case VTYPE_STRING:
+ proto_tree_add_string_format(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vstring, pvalues[i].vdesc, pvalues[i].vstring);
+ if (pvalues[i].mvtype == MVTYPE_ATTR_REQUEST) {
+ /*
+ * The "vstring" value is set to the input ES type
+ * for MVTYPE_PROC_ENTRY_SPECIFIERS,
+ * to add string to columninfo
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (!added_arrow) {
+ col_append_str(pinfo->cinfo, COL_INFO, " -> ");
+ added_arrow = TRUE;
+ }
+ col_append_str(pinfo->cinfo, COL_INFO, pvalues[i].vstring);
+ }
+ }
+ break;
+
+ case VTYPE_BITFIELD:
+ process_bitfield(ncp_tree, tvb, &pvalues[i]);
+ break;
+
+ case VTYPE_MULTIVALUE_UINT32:
+ process_multivalues(ncp_tree, tvb, &pvalues[i]);
+ if (pvalues[i].mvtype == MVTYPE_PROC_ENTRY_SPECIFIERS) {
+ /*
+ * The "vstring" value is set to the input ES type
+ * by "process_multivalues()".
+ */
+ strcpy(global_object_name, pvalues[i].vstring);
+ }
+ if (pvalues[i].mvtype == MVTYPE_ATTR_REQUEST || pvalues[i].mvtype == MVTYPE_PROC_ENTRY_SPECIFIERS) {
+ /*
+ * The "vstring" value is set to the input ES type
+ * for MVTYPE_PROC_ENTRY_SPECIFIERS,
+ * and the last string for MVTYPE_ATTR_REQUEST,
+ * by "process_multivalues()".
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (!added_arrow) {
+ col_append_str(pinfo->cinfo, COL_INFO, " -> ");
+ added_arrow = TRUE;
+ }
+ col_append_str(pinfo->cinfo, COL_INFO, pvalues[i].vstring);
+ }
+ }
+ break;
+
+ case VTYPE_BYTES:
+ proto_tree_add_bytes(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, tvb_get_ptr(tvb, pvalues[i].voffset, pvalues[i].vvalue));
+ break;
+
+ case VTYPE_BOOLEAN:
+ proto_tree_add_item(ncp_tree, pvalues[i].hfname, tvb, pvalues[i].voffset, pvalues[i].vlength, TRUE);
+ break;
+
+ default:
+ proto_tree_add_uint_format(ncp_tree, hf_nds_p1type, tvb, pvalues[i].voffset,
+ pvalues[i].vlength, pvalues[i].vtype, "NDS Parameter not defined %u",
+ pvalues[i].vtype);
+ break;
+ }
+ /* For NDS requests with just an EID, resolve name from hash table. */
+ }
+ request_eid_value = ncp_eid_hash_lookup(conversation, global_eid);
+ if(resolve_eid) {
+ if (request_eid_value) {
+ strcpy(global_object_name, request_eid_value->object_name);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Object Name - ");
+ col_append_str(pinfo->cinfo, COL_INFO, global_object_name);
+ }
+ }
+ }
+ if (request_value)
+ {
+ request_value->nds_request_verb = nds_verb;
+ request_value->nds_version = nds_version;
+ strcpy(request_value->object_name, global_object_name);
+ request_value->req_nds_flags = global_flags;
+ }
+ }
+ break;
+
+ default:
+ ; /* nothing */
+ break;
+ }
+ ptvcursor_free(ptvc);
+
+ /* Free the temporary proto_tree */
+ CLEANUP_CALL_AND_POP;
+ }
+}
+
+/*
+ * XXX - this duplicates stuff in "dissect_ncp_request()"; could
+ * "dissect_ncp_request()" not just call "dissect_ping_req()" if
+ * the operation is an NCP ping, and "dissect_ping_req()" just dissect
+ * ping portion?
+ */
+void
+dissect_ping_req(tvbuff_t *tvb, packet_info *pinfo,
+ guint16 nw_connection, guint8 sequence,
+ guint16 type, proto_tree *ncp_tree)
+{
+ guint8 func, subfunc = 0;
+ ncp_req_hash_value *request_value = NULL;
+ const ncp_record *ncp_rec = NULL;
+ conversation_t *conversation;
+ ptvcursor_t *ptvc = NULL;
+ proto_tree *temp_tree = NULL;
+ gint length_remaining = 0;
+ guint32 nds_flags;
+ guint32 ping_version;
+ nds_val pvalue;
+ char string_buffer[1024];
+
+ pvalue.vvalue = 0;
+ pvalue.vlength = 0;
+ pvalue.voffset = 0;
+ pvalue.hfname = 0;
+ pvalue.vdesc = "";
+ string_buffer[0] = '\0';
+ pvalue.vstring = string_buffer;
+ pvalue.mvtype = 0;
+
+ func = tvb_get_guint8(tvb, 6);
+ subfunc = tvb_get_guint8(tvb, 7);
+
+ ncp_rec = ncp_record_find(func, subfunc);
+
+ /* Fill in the INFO column. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (ncp_rec)
+ {
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDS");
+ col_add_fstr(pinfo->cinfo, COL_INFO, "C Ping for NDS");
+ }
+
+ }
+ if (!pinfo->fd->flags.visited)
+ {
+
+ /* This is the first time we've looked at this packet.
+ Keep track of the address and connection whence the request
+ came, and the address and connection to which the request
+ is being sent, so that we can match up calls with replies.
+ (We don't include the sequence number, as we may want
+ to have all packets over the same connection treated
+ as being part of a single conversation so that we can
+ let the user select that conversation to be displayed.) */
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, nw_connection, nw_connection, 0);
+
+ if (conversation == NULL)
+ {
+ /* It's not part of any conversation - create a new one. */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ PT_NCP, nw_connection, nw_connection, 0);
+ }
+
+ request_value = ncp_hash_insert(conversation, sequence, ncp_rec);
+ request_value->req_frame_num = pinfo->fd->num;
+ request_value->req_frame_time.secs=pinfo->fd->abs_secs;
+ request_value->req_frame_time.nsecs=pinfo->fd->abs_usecs*1000;
+
+ /* If this is the first time we're examining the packet,
+ * check to see if this NCP type uses a "request condition".
+ * If so, we have to build a proto_tree because request conditions
+ * use display filters to work, and without a proto_tree,
+ * display filters can't possibly work. If we already have
+ * a proto_tree, then wonderful. If we don't, we need to build
+ * one. */
+ if (ncp_rec && !ncp_tree) {
+ proto_item *ti;
+
+ temp_tree = proto_tree_create_root();
+ proto_tree_set_visible(temp_tree, FALSE);
+ ti = proto_tree_add_item(temp_tree, proto_ncp, tvb, 0, -1, FALSE);
+ ncp_tree = proto_item_add_subtree(ti, ett_ncp);
+ }
+ }
+
+ if (ncp_tree) {
+ /* If the dissection throws an exception, be sure to free
+ * the temporary proto_tree that was created. Because of the
+ * way the CLEANUP_PUSH macro works, we can't put it in an 'if'
+ * block; it has to be in the same scope as the terminating
+ * CLEANUP_POP or CLEANUP_POP_AND_ALLOC. So, we always
+ * call CLEANUP_POP and friends, but the value of temp_tree is
+ * NULL if no cleanup is needed, and non-null if cleanup is needed.
+ */
+ CLEANUP_PUSH(free_proto_tree, temp_tree);
+
+ switch (type) {
+
+ case NCP_BROADCAST_SLOT:
+ ; /* nothing */
+ break;
+
+ case NCP_SERVICE_REQUEST:
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_func, tvb, 6, 1,
+ func, "Function: %u (0x%02X), %s",
+ func, func, ncp_rec ? ncp_rec->name : "Unknown");
+
+ proto_tree_add_uint_format(ncp_tree, hf_ncp_subfunc, tvb, 7, 1,
+ subfunc, "SubFunction: %u (0x%02x)",
+ subfunc, subfunc);
+
+ length_remaining = tvb_reported_length_remaining(tvb, 8);
+ if (length_remaining >= 8) {
+ ping_version = tvb_get_letohl(tvb, 8);
+ proto_tree_add_uint(ncp_tree, hf_nds_ping_version, tvb, 8,
+ 4, ping_version);
+ nds_flags = tvb_get_letohl(tvb, 12);
+ if (request_value)
+ request_value->req_nds_flags = nds_flags;
+
+
+ pvalue.vvalue = tvb_get_letohs(tvb, 12);
+ pvalue.vtype = VTYPE_BITFIELD;
+ pvalue.vstring = "";
+ pvalue.vdesc = "Ping (low) Request Flags:";
+ pvalue.vlength = 2;
+ pvalue.hfname= hf_nds_rflags;
+ pvalue.voffset = 12;
+ pvalue.bit1 = "Supported Fields";
+ pvalue.bit1hfname = hf_bit1pingflags1;
+ pvalue.bit2 = "Depth";
+ pvalue.bit2hfname = hf_bit2pingflags1;
+ pvalue.bit3 = "Revision";
+ pvalue.bit3hfname = hf_bit3pingflags1;
+ pvalue.bit4 = "Flags";
+ pvalue.bit4hfname = hf_bit4pingflags1;
+ pvalue.bit5 = "Verification Flags";
+ pvalue.bit5hfname = hf_bit5pingflags1;
+ pvalue.bit6 = "Letter Version";
+ pvalue.bit6hfname = hf_bit6pingflags1;
+ pvalue.bit7 = "OS Version";
+ pvalue.bit7hfname = hf_bit7pingflags1;
+ pvalue.bit8 = "License Flags";
+ pvalue.bit8hfname = hf_bit8pingflags1;
+ pvalue.bit9 = "DS Time";
+ pvalue.bit9hfname = hf_bit9pingflags1;
+ pvalue.bit10 = "Not Defined";
+ pvalue.bit10hfname = hf_bit10pingflags1;
+ pvalue.bit11 = "Not Defined";
+ pvalue.bit11hfname = hf_bit11pingflags1;
+ pvalue.bit12 = "Not Defined";
+ pvalue.bit12hfname = hf_bit12pingflags1;
+ pvalue.bit13 = "Not Defined";
+ pvalue.bit13hfname = hf_bit13pingflags1;
+ pvalue.bit14 = "Not Defined";
+ pvalue.bit14hfname = hf_bit14pingflags1;
+ pvalue.bit15 = "Not Defined";
+ pvalue.bit15hfname = hf_bit15pingflags1;
+ pvalue.bit16 = "Not Defined";
+ pvalue.bit16hfname = hf_bit16pingflags1;
+
+ process_bitfield(ncp_tree, tvb, &pvalue);
+
+ pvalue.vvalue = tvb_get_letohs(tvb, 14);
+ pvalue.vtype = VTYPE_BITFIELD;
+ pvalue.vstring = "";
+ pvalue.vdesc = "Ping (high) Request Flags:";
+ pvalue.vlength = 2;
+ pvalue.hfname= hf_nds_rflags;
+ pvalue.voffset = 14;
+ pvalue.bit1 = "Sap Name";
+ pvalue.bit1hfname = hf_bit1pingflags2;
+ pvalue.bit2 = "Tree Name";
+ pvalue.bit2hfname = hf_bit2pingflags2;
+ pvalue.bit3 = "OS Name";
+ pvalue.bit3hfname = hf_bit3pingflags2;
+ pvalue.bit4 = "Hardware Name";
+ pvalue.bit4hfname = hf_bit4pingflags2;
+ pvalue.bit5 = "Vendor Name";
+ pvalue.bit5hfname = hf_bit5pingflags2;
+ pvalue.bit6 = "Not Defined";
+ pvalue.bit6hfname = hf_bit6pingflags2;
+ pvalue.bit7 = "Not Defined";
+ pvalue.bit7hfname = hf_bit7pingflags2;
+ pvalue.bit8 = "Not Defined";
+ pvalue.bit8hfname = hf_bit8pingflags2;
+ pvalue.bit9 = "Not Defined";
+ pvalue.bit9hfname = hf_bit9pingflags2;
+ pvalue.bit10 = "Not Defined";
+ pvalue.bit10hfname = hf_bit10pingflags2;
+ pvalue.bit11 = "Not Defined";
+ pvalue.bit11hfname = hf_bit11pingflags2;
+ pvalue.bit12 = "Not Defined";
+ pvalue.bit12hfname = hf_bit12pingflags2;
+ pvalue.bit13 = "Not Defined";
+ pvalue.bit13hfname = hf_bit13pingflags2;
+ pvalue.bit14 = "Not Defined";
+ pvalue.bit14hfname = hf_bit14pingflags2;
+ pvalue.bit15 = "Not Defined";
+ pvalue.bit15hfname = hf_bit15pingflags2;
+ pvalue.bit16 = "Not Defined";
+ pvalue.bit16hfname = hf_bit16pingflags2;
+
+ process_bitfield(ncp_tree, tvb, &pvalue);
+ }
+ break;
+
+ default:
+ ; /* nothing */
+ break;
+ }
+ ptvc = ptvcursor_new(ncp_tree, tvb, 7);
+ if (ncp_rec && ncp_rec->request_ptvc) {
+ clear_repeat_vars();
+ process_ptvc_record(ptvc, ncp_rec->request_ptvc, NULL, TRUE, ncp_rec);
+ }
+ ptvcursor_free(ptvc);
+
+ /* Free the temporary proto_tree */
+ CLEANUP_CALL_AND_POP;
+ }
+}
diff --git a/epan/dissectors/packet-ndmp.c b/epan/dissectors/packet-ndmp.c
new file mode 100644
index 0000000000..4bf431a815
--- /dev/null
+++ b/epan/dissectors/packet-ndmp.c
@@ -0,0 +1,3493 @@
+/* packet-ndmp.c
+ * Routines for NDMP dissection
+ * 2001 Ronnie Sahlberg (see AUTHORS for email)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* see www.ndmp.org for protocol specifications.
+ this file implements version 3 of ndmp
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "packet-rpc.h"
+#include "packet-scsi.h"
+#include "packet-frame.h"
+#include "prefs.h"
+#include "reassemble.h"
+#include "rpc_defrag.h"
+
+#define TCP_PORT_NDMP 10000
+
+static int proto_ndmp = -1;
+static int hf_ndmp_version = -1;
+static int hf_ndmp_header = -1;
+static int hf_ndmp_sequence = -1;
+static int hf_ndmp_reply_sequence = -1;
+static int hf_ndmp_timestamp = -1;
+static int hf_ndmp_msgtype = -1;
+static int hf_ndmp_msg = -1;
+static int hf_ndmp_error = -1;
+static int hf_ndmp_hostname = -1;
+static int hf_ndmp_os_type = -1;
+static int hf_ndmp_os_vers = -1;
+static int hf_ndmp_hostid = -1;
+static int hf_ndmp_addr_types = -1;
+static int hf_ndmp_addr_type = -1;
+static int hf_ndmp_auth_type = -1;
+static int hf_ndmp_auth_types = -1;
+static int hf_ndmp_auth_challenge = -1;
+static int hf_ndmp_auth_digest = -1;
+static int hf_ndmp_auth_id = -1;
+static int hf_ndmp_auth_password = -1;
+static int hf_ndmp_butype_info = -1;
+static int hf_ndmp_butype_name = -1;
+static int hf_ndmp_butype_default_env = -1;
+static int hf_ndmp_butype_attr_backup_file_history = -1;
+static int hf_ndmp_butype_attr_backup_filelist = -1;
+static int hf_ndmp_butype_attr_recover_filelist = -1;
+static int hf_ndmp_butype_attr_backup_direct = -1;
+static int hf_ndmp_butype_attr_recover_direct = -1;
+static int hf_ndmp_butype_attr_backup_incremental = -1;
+static int hf_ndmp_butype_attr_recover_incremental = -1;
+static int hf_ndmp_butype_attr_backup_utf8 = -1;
+static int hf_ndmp_butype_attr_recover_utf8 = -1;
+static int hf_ndmp_butype_env_name = -1;
+static int hf_ndmp_butype_env_value = -1;
+static int hf_ndmp_fs_info = -1;
+static int hf_ndmp_fs_invalid_total_size = -1;
+static int hf_ndmp_fs_invalid_used_size = -1;
+static int hf_ndmp_fs_invalid_avail_size = -1;
+static int hf_ndmp_fs_invalid_total_inodes = -1;
+static int hf_ndmp_fs_invalid_used_inodes = -1;
+static int hf_ndmp_fs_fs_type = -1;
+static int hf_ndmp_fs_logical_device = -1;
+static int hf_ndmp_fs_physical_device = -1;
+static int hf_ndmp_fs_total_size = -1;
+static int hf_ndmp_fs_used_size = -1;
+static int hf_ndmp_fs_avail_size = -1;
+static int hf_ndmp_fs_total_inodes = -1;
+static int hf_ndmp_fs_used_inodes = -1;
+static int hf_ndmp_fs_env = -1;
+static int hf_ndmp_fs_env_name = -1;
+static int hf_ndmp_fs_env_value = -1;
+static int hf_ndmp_fs_status = -1;
+static int hf_ndmp_tape_info = -1;
+static int hf_ndmp_tape_model = -1;
+static int hf_ndmp_tape_dev_cap = -1;
+static int hf_ndmp_tape_device = -1;
+static int hf_ndmp_tape_open_mode = -1;
+static int hf_ndmp_tape_attr_rewind = -1;
+static int hf_ndmp_tape_attr_unload = -1;
+static int hf_ndmp_tape_capability = -1;
+static int hf_ndmp_tape_capability_name = -1;
+static int hf_ndmp_tape_capability_value = -1;
+static int hf_ndmp_scsi_info = -1;
+static int hf_ndmp_scsi_model = -1;
+static int hf_ndmp_server_vendor = -1;
+static int hf_ndmp_server_product = -1;
+static int hf_ndmp_server_revision = -1;
+static int hf_ndmp_scsi_device = -1;
+static int hf_ndmp_scsi_controller = -1;
+static int hf_ndmp_scsi_id = -1;
+static int hf_ndmp_scsi_lun = -1;
+static int hf_ndmp_execute_cdb_flags_data_in = -1;
+static int hf_ndmp_execute_cdb_flags_data_out = -1;
+static int hf_ndmp_execute_cdb_timeout = -1;
+static int hf_ndmp_execute_cdb_datain_len = -1;
+static int hf_ndmp_execute_cdb_cdb_len = -1;
+static int hf_ndmp_execute_cdb_dataout = -1;
+static int hf_ndmp_execute_cdb_status = -1;
+static int hf_ndmp_execute_cdb_dataout_len = -1;
+static int hf_ndmp_execute_cdb_datain = -1;
+static int hf_ndmp_execute_cdb_sns_len = -1;
+static int hf_ndmp_tape_invalid_file_num = -1;
+static int hf_ndmp_tape_invalid_soft_errors = -1;
+static int hf_ndmp_tape_invalid_block_size = -1;
+static int hf_ndmp_tape_invalid_block_no = -1;
+static int hf_ndmp_tape_invalid_total_space = -1;
+static int hf_ndmp_tape_invalid_space_remain = -1;
+static int hf_ndmp_tape_invalid_partition = -1;
+static int hf_ndmp_tape_flags_no_rewind = -1;
+static int hf_ndmp_tape_flags_write_protect = -1;
+static int hf_ndmp_tape_flags_error = -1;
+static int hf_ndmp_tape_flags_unload = -1;
+static int hf_ndmp_tape_file_num = -1;
+static int hf_ndmp_tape_soft_errors = -1;
+static int hf_ndmp_tape_block_size = -1;
+static int hf_ndmp_tape_block_no = -1;
+static int hf_ndmp_tape_total_space = -1;
+static int hf_ndmp_tape_space_remain = -1;
+static int hf_ndmp_tape_partition = -1;
+static int hf_ndmp_tape_mtio_op = -1;
+static int hf_ndmp_count = -1;
+static int hf_ndmp_resid_count = -1;
+static int hf_ndmp_mover_state = -1;
+static int hf_ndmp_mover_pause = -1;
+static int hf_ndmp_halt = -1;
+static int hf_ndmp_halt_reason = -1;
+static int hf_ndmp_record_size = -1;
+static int hf_ndmp_record_num = -1;
+static int hf_ndmp_data_written = -1;
+static int hf_ndmp_seek_position = -1;
+static int hf_ndmp_bytes_left_to_read = -1;
+static int hf_ndmp_window_offset = -1;
+static int hf_ndmp_window_length = -1;
+static int hf_ndmp_addr_ip = -1;
+static int hf_ndmp_addr_tcp = -1;
+static int hf_ndmp_addr_fcal_loop_id = -1;
+static int hf_ndmp_addr_ipc = -1;
+static int hf_ndmp_mover_mode = -1;
+static int hf_ndmp_file_name = -1;
+static int hf_ndmp_nt_file_name = -1;
+static int hf_ndmp_dos_file_name = -1;
+static int hf_ndmp_log_type = -1;
+static int hf_ndmp_log_message_id = -1;
+static int hf_ndmp_log_message = -1;
+static int hf_ndmp_connected = -1;
+static int hf_ndmp_connected_reason = -1;
+static int hf_ndmp_data = -1;
+static int hf_ndmp_files = -1;
+static int hf_ndmp_file_fs_type = -1;
+static int hf_ndmp_file_names = -1;
+static int hf_ndmp_file_stats = -1;
+static int hf_ndmp_file_node = -1;
+static int hf_ndmp_file_parent = -1;
+static int hf_ndmp_file_fh_info = -1;
+static int hf_ndmp_file_invalid_atime = -1;
+static int hf_ndmp_file_invalid_ctime = -1;
+static int hf_ndmp_file_invalid_group = -1;
+static int hf_ndmp_file_type = -1;
+static int hf_ndmp_file_mtime = -1;
+static int hf_ndmp_file_atime = -1;
+static int hf_ndmp_file_ctime = -1;
+static int hf_ndmp_file_owner = -1;
+static int hf_ndmp_file_group = -1;
+static int hf_ndmp_file_fattr = -1;
+static int hf_ndmp_file_size = -1;
+static int hf_ndmp_file_links = -1;
+static int hf_ndmp_dirs = -1;
+static int hf_ndmp_nodes = -1;
+static int hf_ndmp_nlist = -1;
+static int hf_ndmp_bu_original_path = -1;
+static int hf_ndmp_bu_destination_dir = -1;
+static int hf_ndmp_bu_new_name = -1;
+static int hf_ndmp_bu_other_name = -1;
+static int hf_ndmp_state_invalid_ebr = -1;
+static int hf_ndmp_state_invalid_etr = -1;
+static int hf_ndmp_bu_operation = -1;
+static int hf_ndmp_data_state = -1;
+static int hf_ndmp_data_halted = -1;
+static int hf_ndmp_data_bytes_processed = -1;
+static int hf_ndmp_data_est_bytes_remain = -1;
+static int hf_ndmp_data_est_time_remain = -1;
+
+static gint ett_ndmp = -1;
+static gint ett_ndmp_header = -1;
+static gint ett_ndmp_butype_attrs = -1;
+static gint ett_ndmp_fs_invalid = -1;
+static gint ett_ndmp_tape_attr = -1;
+static gint ett_ndmp_execute_cdb_flags = -1;
+static gint ett_ndmp_execute_cdb_cdb = -1;
+static gint ett_ndmp_execute_cdb_sns = -1;
+static gint ett_ndmp_execute_cdb_payload = -1;
+static gint ett_ndmp_tape_invalid = -1;
+static gint ett_ndmp_tape_flags = -1;
+static gint ett_ndmp_addr = -1;
+static gint ett_ndmp_file = -1;
+static gint ett_ndmp_file_name = -1;
+static gint ett_ndmp_file_stats = -1;
+static gint ett_ndmp_file_invalids = -1;
+static gint ett_ndmp_state_invalids = -1;
+
+
+/* XXX someone should start adding the new stuff from v3, v4 and v5*/
+#define NDMP_PROTOCOL_V2 1
+#define NDMP_PROTOCOL_V3 2
+#define NDMP_PROTOCOL_V4 3
+#define NDMP_PROTOCOL_V5 4
+
+static enum_val_t ndmp_protocol_versions[] = {
+ { "version2", "Version 2", NDMP_PROTOCOL_V2 },
+ { "version3", "Version 3", NDMP_PROTOCOL_V3 },
+ { "version4", "Version 4", NDMP_PROTOCOL_V4 },
+ { "version5", "Version 5", NDMP_PROTOCOL_V5 },
+ { NULL, NULL, 0 }
+};
+
+static gint ndmp_protocol_version = NDMP_PROTOCOL_V2;
+
+
+struct ndmp_header {
+ guint32 seq;
+ guint32 time;
+ guint32 type;
+ guint32 msg;
+ guint32 rep_seq;
+ guint32 err;
+};
+
+/* desegmentation of NDMP packets */
+static gboolean ndmp_desegment = TRUE;
+
+/* defragmentation of fragmented NDMP records */
+static gboolean ndmp_defragment = FALSE;
+
+#define NDMP_MESSAGE_REQUEST 0x00
+#define NDMP_MESSAGE_REPLY 0x01
+static const value_string msg_type_vals[] = {
+ {NDMP_MESSAGE_REQUEST, "Request"},
+ {NDMP_MESSAGE_REPLY, "Reply"},
+ {0, NULL}
+};
+
+#define NDMP_NO_ERR 0x00
+#define NDMP_NOT_SUPPORTED_ERR 0x01
+#define NDMP_DEVICE_BUSY_ERR 0x02
+#define NDMP_DEVICE_OPENED_ERR 0x03
+#define NDMP_NOT_AUTHORIZED_ERR 0x04
+#define NDMP_PERMISSION_ERR 0x05
+#define NDMP_DEV_NOT_OPEN_ERR 0x06
+#define NDMP_IO_ERR 0x07
+#define NDMP_TIMEOUT_ERR 0x08
+#define NDMP_ILLEGAL_ARGS_ERR 0x09
+#define NDMP_NO_TAPE_LOADED_ERR 0x0a
+#define NDMP_WRITE_PROTECT_ERR 0x0b
+#define NDMP_EOF_ERR 0x0c
+#define NDMP_EOM_ERR 0x0d
+#define NDMP_FILE_NOT_FOUND_ERR 0x0e
+#define NDMP_BAD_FILE_ERR 0x0f
+#define NDMP_NO_DEVICE_ERR 0x10
+#define NDMP_NO_BUS_ERR 0x11
+#define NDMP_XDR_DECODE_ERR 0x12
+#define NDMP_ILLEGAL_STATE_ERR 0x13
+#define NDMP_UNDEFINED_ERR 0x14
+#define NDMP_XDR_ENCODE_ERR 0x15
+#define NDMP_NO_MEM_ERR 0x16
+#define NDMP_CONNECT_ERR 0x17
+
+static const value_string error_vals[] = {
+ {NDMP_NO_ERR, "NO_ERR"},
+ {NDMP_NOT_SUPPORTED_ERR, "NOT_SUPPORTED_ERR"},
+ {NDMP_DEVICE_BUSY_ERR, "DEVICE_BUSY_ERR"},
+ {NDMP_DEVICE_OPENED_ERR, "DEVICE_OPENED_ERR"},
+ {NDMP_NOT_AUTHORIZED_ERR, "NOT_AUTHORIZED_ERR"},
+ {NDMP_PERMISSION_ERR, "PERMISSION_ERR"},
+ {NDMP_DEV_NOT_OPEN_ERR, "DEV_NOT_OPEN_ERR"},
+ {NDMP_IO_ERR, "IO_ERR"},
+ {NDMP_TIMEOUT_ERR, "TIMEOUT_ERR"},
+ {NDMP_ILLEGAL_ARGS_ERR, "ILLEGAL_ARGS_ERR"},
+ {NDMP_NO_TAPE_LOADED_ERR, "NO_TAPE_LOADED_ERR"},
+ {NDMP_WRITE_PROTECT_ERR, "WRITE_PROTECT_ERR"},
+ {NDMP_EOF_ERR, "EOF_ERR"},
+ {NDMP_EOM_ERR, "EOM_ERR"},
+ {NDMP_FILE_NOT_FOUND_ERR, "FILE_NOT_FOUND_ERR"},
+ {NDMP_BAD_FILE_ERR, "BAD_FILE_ERR"},
+ {NDMP_NO_DEVICE_ERR, "NO_DEVICE_ERR"},
+ {NDMP_NO_BUS_ERR, "NO_BUS_ERR"},
+ {NDMP_XDR_DECODE_ERR, "XDR_DECODE_ERR"},
+ {NDMP_ILLEGAL_STATE_ERR, "ILLEGAL_STATE_ERR"},
+ {NDMP_UNDEFINED_ERR, "UNDEFINED_ERR"},
+ {NDMP_XDR_ENCODE_ERR, "XDR_ENCODE_ERR"},
+ {NDMP_NO_MEM_ERR, "NO_MEM_ERR"},
+ {NDMP_CONNECT_ERR, "CONNECT_ERR"},
+ {0, NULL}
+};
+
+
+
+#define NDMP_CONFIG_GET_HOST_INFO 0x100
+#define NDMP_CONFIG_GET_CONNECTION_TYPE 0x102
+#define NDMP_CONFIG_GET_AUTH_ATTR 0x103
+#define NDMP_CONFIG_GET_BUTYPE_INFO 0x104
+#define NDMP_CONFIG_GET_FS_INFO 0x105
+#define NDMP_CONFIG_GET_TAPE_INFO 0x106
+#define NDMP_CONFIG_GET_SCSI_INFO 0x107
+#define NDMP_CONFIG_GET_SERVER_INFO 0x108
+#define NDMP_SCSI_OPEN 0x200
+#define NDMP_SCSI_CLOSE 0x201
+#define NDMP_SCSI_GET_STATE 0x202
+#define NDMP_SCSI_SET_TARGET 0x203
+#define NDMP_SCSI_RESET_DEVICE 0x204
+#define NDMP_SCSI_RESET_BUS 0x205
+#define NDMP_SCSI_EXECUTE_CDB 0x206
+#define NDMP_TAPE_OPEN 0x300
+#define NDMP_TAPE_CLOSE 0x301
+#define NDMP_TAPE_GET_STATE 0x302
+#define NDMP_TAPE_MTIO 0x303
+#define NDMP_TAPE_WRITE 0x304
+#define NDMP_TAPE_READ 0x305
+#define NDMP_TAPE_EXECUTE_CDB 0x307
+#define NDMP_DATA_GET_STATE 0x400
+#define NDMP_DATA_START_BACKUP 0x401
+#define NDMP_DATA_START_RECOVER 0x402
+#define NDMP_DATA_ABORT 0x403
+#define NDMP_DATA_GET_ENV 0x404
+#define NDMP_DATA_STOP 0x407
+#define NDMP_DATA_LISTEN 0x409
+#define NDMP_DATA_CONNECT 0x40a
+#define NDMP_NOTIFY_DATA_HALTED 0x501
+#define NDMP_NOTIFY_CONNECTED 0x502
+#define NDMP_NOTIFY_MOVER_HALTED 0x503
+#define NDMP_NOTIFY_MOVER_PAUSED 0x504
+#define NDMP_NOTIFY_DATA_READ 0x505
+#define NDMP_LOG_FILE 0x602
+#define NDMP_LOG_MESSAGE 0x603
+#define NDMP_FH_ADD_FILE 0x703
+#define NDMP_FH_ADD_DIR 0x704
+#define NDMP_FH_ADD_NODE 0x705
+#define NDMP_CONNECT_OPEN 0x900
+#define NDMP_CONNECT_CLIENT_AUTH 0x901
+#define NDMP_CONNECT_CLOSE 0x902
+#define NDMP_CONNECT_SERVER_AUTH 0x903
+#define NDMP_MOVER_GET_STATE 0xa00
+#define NDMP_MOVER_LISTEN 0xa01
+#define NDMP_MOVER_CONTINUE 0xa02
+#define NDMP_MOVER_ABORT 0xa03
+#define NDMP_MOVER_STOP 0xa04
+#define NDMP_MOVER_SET_WINDOW 0xa05
+#define NDMP_MOVER_READ 0xa06
+#define NDMP_MOVER_CLOSE 0xa07
+#define NDMP_MOVER_SET_RECORD_SIZE 0xa08
+#define NDMP_MOVER_CONNECT 0xa09
+
+
+
+
+static const value_string msg_vals[] = {
+ {NDMP_CONFIG_GET_HOST_INFO, "CONFIG_GET_HOST_INFO"},
+ {NDMP_CONFIG_GET_CONNECTION_TYPE, "CONFIG_GET_CONNECTION_TYPE"},
+ {NDMP_CONFIG_GET_AUTH_ATTR, "CONFIG_GET_AUTH_ATTR"},
+ {NDMP_CONFIG_GET_BUTYPE_INFO, "CONFIG_GET_BUTYPE_INFO"},
+ {NDMP_CONFIG_GET_FS_INFO, "CONFIG_GET_FS_INFO"},
+ {NDMP_CONFIG_GET_TAPE_INFO, "CONFIG_GET_TAPE_INFO"},
+ {NDMP_CONFIG_GET_SCSI_INFO, "CONFIG_GET_SCSI_INFO"},
+ {NDMP_CONFIG_GET_SERVER_INFO, "CONFIG_GET_SERVER_INFO"},
+ {NDMP_SCSI_OPEN, "SCSI_OPEN"},
+ {NDMP_SCSI_CLOSE, "SCSI_CLOSE"},
+ {NDMP_SCSI_GET_STATE, "SCSI_GET_STATE"},
+ {NDMP_SCSI_SET_TARGET, "SCSI_SET_TARGET"},
+ {NDMP_SCSI_RESET_DEVICE, "SCSI_RESET_DEVICE"},
+ {NDMP_SCSI_RESET_BUS, "SCSI_RESET_BUS"},
+ {NDMP_SCSI_EXECUTE_CDB, "SCSI_EXECUTE_CDB"},
+ {NDMP_TAPE_OPEN, "TAPE_OPEN"},
+ {NDMP_TAPE_CLOSE, "TAPE_CLOSE"},
+ {NDMP_TAPE_GET_STATE, "TAPE_GET_STATE"},
+ {NDMP_TAPE_MTIO, "TAPE_MTIO"},
+ {NDMP_TAPE_WRITE, "TAPE_WRITE"},
+ {NDMP_TAPE_READ, "TAPE_READ"},
+ {NDMP_TAPE_EXECUTE_CDB, "TAPE_EXECUTE_CDB"},
+ {NDMP_DATA_GET_STATE, "DATA_GET_STATE"},
+ {NDMP_DATA_START_BACKUP, "DATA_START_BACKUP"},
+ {NDMP_DATA_START_RECOVER, "DATA_START_RECOVER"},
+ {NDMP_DATA_ABORT, "DATA_ABORT"},
+ {NDMP_DATA_GET_ENV, "DATA_GET_ENV"},
+ {NDMP_DATA_STOP, "DATA_STOP"},
+ {NDMP_DATA_LISTEN, "DATA_LISTEN"},
+ {NDMP_DATA_CONNECT, "DATA_CONNECT"},
+ {NDMP_NOTIFY_DATA_HALTED, "NOTIFY_DATA_HALTED"},
+ {NDMP_NOTIFY_CONNECTED, "NOTIFY_CONNECTED"},
+ {NDMP_NOTIFY_MOVER_HALTED, "NOTIFY_MOVER_HALTED"},
+ {NDMP_NOTIFY_MOVER_PAUSED, "NOTIFY_MOVER_PAUSED"},
+ {NDMP_NOTIFY_DATA_READ, "NOTIFY_DATA_READ"},
+ {NDMP_LOG_FILE, "LOG_FILE"},
+ {NDMP_LOG_MESSAGE, "LOG_MESSAGE"},
+ {NDMP_FH_ADD_FILE, "FH_ADD_FILE"},
+ {NDMP_FH_ADD_DIR, "FH_ADD_DIR"},
+ {NDMP_FH_ADD_NODE, "FH_ADD_NODE"},
+ {NDMP_CONNECT_OPEN, "CONNECT_OPEN"},
+ {NDMP_CONNECT_CLIENT_AUTH, "CONNECT_CLIENT_AUTH"},
+ {NDMP_CONNECT_CLOSE, "CONNECT_CLOSE"},
+ {NDMP_CONNECT_SERVER_AUTH, "CONNECT_SERVER_AUTH"},
+ {NDMP_MOVER_GET_STATE, "MOVER_GET_STATE"},
+ {NDMP_MOVER_LISTEN, "MOVER_LISTEN"},
+ {NDMP_MOVER_CONTINUE, "MOVER_CONTINUE"},
+ {NDMP_MOVER_ABORT, "MOVER_ABORT"},
+ {NDMP_MOVER_STOP, "MOVER_STOP"},
+ {NDMP_MOVER_SET_WINDOW, "MOVER_SET_WINDOW"},
+ {NDMP_MOVER_READ, "MOVER_READ"},
+ {NDMP_MOVER_CLOSE, "MOVER_CLOSE"},
+ {NDMP_MOVER_SET_RECORD_SIZE, "MOVER_SET_RECORD_SIZE"},
+ {NDMP_MOVER_CONNECT, "MOVER_CONNECT"},
+ {0, NULL}
+};
+
+static int
+dissect_connect_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* version number */
+ proto_tree_add_item(tree, hf_ndmp_version, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq _U_)
+{
+ guint32 err;
+
+ /* error */
+ err=tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_ndmp_error, tvb, offset, 4, FALSE);
+ if(err && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " NDMP Error:%s",
+ val_to_str(err, error_vals,
+ "Unknown NDMP error code %#x"));
+ }
+
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_ndmp_get_host_info_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* hostname */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_hostname, offset, NULL);
+
+ /* os type */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_os_type, offset, NULL);
+
+ /* os version */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_os_vers, offset, NULL);
+
+ /* hostid */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_hostid, offset, NULL);
+
+ return offset;
+}
+
+#define NDMP_ADDR_LOCAL 0
+#define NDMP_ADDR_TCP 1
+#define NDMP_ADDR_FC 2
+#define NDMP_ADDR_IPC 3
+static const value_string addr_type_vals[] = {
+ {NDMP_ADDR_LOCAL, "Local"},
+ {NDMP_ADDR_TCP, "TCP"},
+ {NDMP_ADDR_FC, "FC"},
+ {NDMP_ADDR_IPC, "IPC"},
+ {0,NULL}
+};
+
+static int
+dissect_ndmp_addr_type(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_ndmp_addr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /*address type*/
+ return dissect_ndmp_addr_type(tvb, offset, pinfo, tree);
+}
+
+static int
+dissect_ndmp_config_get_connection_type_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* addr types */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_ndmp_addr_type, hf_ndmp_addr_types);
+
+ return offset;
+}
+
+#define NDMP_AUTH_NONE 0
+#define NDMP_AUTH_TEXT 1
+#define NDMP_AUTH_MD5 2
+static const value_string auth_type_vals[] = {
+ {NDMP_AUTH_NONE, "None"},
+ {NDMP_AUTH_TEXT, "Text"},
+ {NDMP_AUTH_MD5, "MD5"},
+ {0,NULL}
+};
+static int
+dissect_auth_type(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_get_auth_type_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* auth type */
+ return dissect_auth_type(tvb, offset, pinfo, tree);
+}
+
+static int
+dissect_auth_attr_msg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 seq _U_)
+{
+ guint type;
+
+ type=tvb_get_ntohl(tvb,offset);
+
+ /* auth type */
+ proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ switch(type){
+ case NDMP_AUTH_NONE:
+ break;
+ case NDMP_AUTH_TEXT:
+ break;
+ case NDMP_AUTH_MD5:
+ proto_tree_add_item(tree, hf_ndmp_auth_challenge,
+ tvb, offset, 64, FALSE);
+ offset+=64;
+ }
+
+ return offset;
+}
+
+static int
+dissect_default_env(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ /* name */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_butype_env_name, offset, NULL);
+
+ /* value */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_butype_env_value, offset, NULL);
+
+ return offset;
+}
+
+
+static const true_false_string tfs_butype_attr_backup_file_history = {
+ "Backup FILE HISTORY",
+ "Do NOT backup file history"
+};
+static const true_false_string tfs_butype_attr_backup_filelist = {
+ "Backup FILELIST",
+ "Do NOT backup filelist"
+};
+static const true_false_string tfs_butype_attr_recover_filelist = {
+ "Recover FILELIST",
+ "Do NOT recover filelist"
+};
+static const true_false_string tfs_butype_attr_backup_direct = {
+ "Perform DIRECT backup",
+ "Do NOT perform direct backup"
+};
+static const true_false_string tfs_butype_attr_recover_direct = {
+ "Perform DIRECT recovery",
+ "Do NOT perform direct recovery"
+};
+static const true_false_string tfs_butype_attr_backup_incremental = {
+ "Perform INCREMENTAL backup",
+ "Perform FULL backup"
+};
+static const true_false_string tfs_butype_attr_recover_incremental = {
+ "Perform INCREMENTAL revocery",
+ "Perform FULL recovery"
+};
+static const true_false_string tfs_butype_attr_backup_utf8 = {
+ "Backup using UTF8",
+ "Normal backup. Do NOT use utf8"
+};
+static const true_false_string tfs_butype_attr_recover_utf8 = {
+ "Recover using UTF8",
+ "Normal recover. Do NOT use utf8"
+};
+static int
+dissect_butype_attrs(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 flags;
+
+ flags=tvb_get_ntohl(tvb, offset);
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Attributes: 0x%08x", flags);
+ tree = proto_item_add_subtree(item, ett_ndmp_butype_attrs);
+ }
+
+ proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_utf8,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_utf8,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_incremental,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_incremental,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_direct,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_direct,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_butype_attr_recover_filelist,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_filelist,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_butype_attr_backup_file_history,
+ tvb, offset, 4, flags);
+
+ offset += 4;
+ return offset;
+}
+
+static int
+dissect_butype_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /*butype name*/
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_butype_name, offset, NULL);
+
+ /* default env */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_default_env, hf_ndmp_butype_default_env);
+
+ /* attrs */
+ offset = dissect_butype_attrs(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+static int
+dissect_get_butype_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* butype */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_butype_info, hf_ndmp_butype_info);
+
+ return offset;
+}
+
+static const true_false_string tfs_fs_invalid_total_size = {
+ "Total size is INVALID",
+ "Total size is VALID"
+};
+static const true_false_string tfs_fs_invalid_used_size = {
+ "Used size is INVALID",
+ "Used size is VALID"
+};
+static const true_false_string tfs_fs_invalid_avail_size = {
+ "Available size is INVALID",
+ "Available size is VALID"
+};
+static const true_false_string tfs_fs_invalid_total_inodes = {
+ "Total inode count is INVALID",
+ "Total inode count is VALID"
+};
+static const true_false_string tfs_fs_invalid_used_inodes = {
+ "Used inode count is INVALID",
+ "Used inode count is VALID"
+};
+static int
+dissect_fs_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 flags;
+
+ flags=tvb_get_ntohl(tvb, offset);
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Invalids: 0x%08x", flags);
+ tree = proto_item_add_subtree(item, ett_ndmp_fs_invalid);
+ }
+
+ proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_used_inodes,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_total_inodes,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_avail_size,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_used_size,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_fs_invalid_total_size,
+ tvb, offset, 4, flags);
+
+ offset+=4;
+ return offset;
+}
+
+static int
+dissect_fs_env(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ /* name */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_fs_env_name, offset, NULL);
+
+ /* value */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_fs_env_value, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_fs_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* invalid bits */
+ offset=dissect_fs_invalid(tvb, offset, pinfo, tree);
+
+ /* fs type */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_fs_fs_type, offset, NULL);
+
+ /* fs logical device */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_fs_logical_device, offset, NULL);
+
+ /* fs physical device */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_fs_physical_device, offset, NULL);
+
+ /*total_size*/
+ offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_total_size,
+ offset);
+
+ /*used_size*/
+ offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_used_size,
+ offset);
+
+ /*avail_size*/
+ offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_avail_size,
+ offset);
+
+ /*total_inodes*/
+ offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_total_inodes,
+ offset);
+
+ /*used_inodes*/
+ offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_fs_used_inodes,
+ offset);
+
+ /* env */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_fs_env, hf_ndmp_fs_env);
+
+ /* status */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_fs_status, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_get_fs_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* fs */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_fs_info, hf_ndmp_fs_info);
+
+ return offset;
+}
+
+static const true_false_string tfs_tape_attr_rewind = {
+ "Device supports REWIND",
+ "Device does NOT support rewind"
+};
+static const true_false_string tfs_tape_attr_unload = {
+ "Device supports UNLOAD",
+ "Device does NOT support unload"
+};
+static int
+dissect_tape_attr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 flags;
+
+ flags=tvb_get_ntohl(tvb, offset);
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Attributes: 0x%08x", flags);
+ tree = proto_item_add_subtree(item, ett_ndmp_tape_attr);
+ }
+
+ proto_tree_add_boolean(tree, hf_ndmp_tape_attr_unload,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_attr_rewind,
+ tvb, offset, 4, flags);
+
+ offset+=4;
+ return offset;
+}
+
+static int
+dissect_tape_capability(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ /* name */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_tape_capability_name, offset, NULL);
+
+ /* value */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_tape_capability_value, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_tape_dev_cap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* device */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_tape_device, offset, NULL);
+
+ /* tape attributes */
+ offset = dissect_tape_attr(tvb, offset, pinfo, tree);
+
+ /* capability */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_tape_capability, hf_ndmp_tape_capability);
+
+ return offset;
+}
+
+static int
+dissect_tape_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* model */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_tape_model, offset, NULL);
+
+ /* device capabilites */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_tape_dev_cap, hf_ndmp_tape_dev_cap);
+
+ return offset;
+}
+
+static int
+dissect_get_tape_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* tape */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_tape_info, hf_ndmp_tape_info);
+
+ return offset;
+}
+
+static int
+dissect_scsi_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* model */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_scsi_model, offset, NULL);
+
+ /* device capabilites */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_tape_dev_cap, hf_ndmp_tape_dev_cap);
+
+ return offset;
+}
+
+static int
+dissect_get_scsi_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* scsi */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_scsi_info, hf_ndmp_scsi_info);
+
+ return offset;
+}
+
+static int
+dissect_get_server_info_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* vendor */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_server_vendor, offset, NULL);
+
+ /* product */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_server_product, offset, NULL);
+
+ /* revision */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_server_revision, offset, NULL);
+
+
+ /* server */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_auth_type, hf_ndmp_auth_types);
+
+ return offset;
+}
+
+static int
+dissect_scsi_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* device */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_scsi_device, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_scsi_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* controller */
+ proto_tree_add_item(tree, hf_ndmp_scsi_controller, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* id */
+ proto_tree_add_item(tree, hf_ndmp_scsi_id, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* lun */
+ proto_tree_add_item(tree, hf_ndmp_scsi_lun, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_scsi_set_state_request(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
+{
+ /* device */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_scsi_device, offset, NULL);
+
+ /* controller */
+ proto_tree_add_item(tree, hf_ndmp_scsi_controller, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* id */
+ proto_tree_add_item(tree, hf_ndmp_scsi_id, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* lun */
+ proto_tree_add_item(tree, hf_ndmp_scsi_lun, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_execute_cdb_flags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 flags;
+
+ flags = tvb_get_ntohl(tvb, offset);
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Flags: 0x%08x", flags);
+ tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_ndmp_execute_cdb_flags_data_in,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_execute_cdb_flags_data_out,
+ tvb, offset, 4, flags);
+ offset += 4;
+ return offset;
+}
+
+static int
+dissect_execute_cdb_cdb(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, gint devtype)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 cdb_len;
+ guint32 cdb_len_full;
+
+ cdb_len = tvb_get_ntohl(tvb, offset);
+ cdb_len_full = rpc_roundup(cdb_len);
+
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset,
+ 4+cdb_len_full, "CDB");
+ tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_cdb);
+ }
+
+ proto_tree_add_uint(tree, hf_ndmp_execute_cdb_cdb_len, tvb, offset, 4,
+ cdb_len);
+ offset += 4;
+
+ if (cdb_len != 0) {
+ dissect_scsi_cdb(tvb, pinfo, tree, offset, cdb_len, devtype);
+ offset += cdb_len_full;
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_execute_cdb_payload(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree,
+ char *name, int hf_len, gboolean isreq)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 payload_len;
+ guint32 payload_len_full;
+
+ payload_len = tvb_get_ntohl(tvb, offset);
+ payload_len_full = rpc_roundup(payload_len);
+
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset,
+ 4+payload_len_full, "%s", name);
+ tree = proto_item_add_subtree(item,
+ ett_ndmp_execute_cdb_payload);
+ }
+
+ proto_tree_add_uint(tree, hf_len, tvb, offset, 4, payload_len);
+ offset += 4;
+
+ if (payload_len != 0) {
+ dissect_scsi_payload(tvb, pinfo, tree, offset, isreq,
+ payload_len);
+ offset += payload_len_full;
+ }
+
+ return offset;
+}
+
+/*
+ * XXX - we assume that NDMP_SCSI_EXECUTE_CDB requests only go to SCSI Media
+ * Changer devices and NDMP_TAPE_EXECUTE_CDB only go to SCSI Sequential
+ * Access devices.
+ *
+ * If that's not the case, we'll have to use the SCSI dissector's mechanisms
+ * for saving inquiry data for devices, and use inquiry data when available.
+ * Unfortunately, that means we need to save the name of the device, and
+ * use it as a device identifier; as the name isn't available in the
+ * NDMP_SCSI_EXECUTE_CDB or NDMP_TAPE_EXECUTE_CDB messages, that means
+ * we need to remember the currently-opened "SCSI" and "TAPE" devices
+ * from NDMP_SCSI_OPEN and NDMP_TAPE_OPEN, and attach to all frames
+ * that are the ones that trigger the dissection of NDMP_SCSI_EXECUTE_CDB
+ * or NDMP_TAPE_EXECUTE_CDB requests pointers to those names.
+ */
+static int
+dissect_execute_cdb_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq, gint devtype)
+{
+ conversation_t *conversation;
+ scsi_task_id_t task_key;
+
+ /*
+ * We need to provide SCSI task information to the SCSI
+ * dissection routines. We use a conversation plus the
+ * sequence number in requests and the reply sequence
+ * number in replies to identify SCSI tasks.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL) {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ task_key.conv_id = conversation->index;
+ task_key.task_id = seq;
+ pinfo->private_data = &task_key;
+
+ /* flags */
+ offset = dissect_execute_cdb_flags(tvb, offset, pinfo, tree);
+
+ /* timeout */
+ proto_tree_add_item(tree, hf_ndmp_execute_cdb_timeout, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* datain_len */
+ proto_tree_add_item(tree, hf_ndmp_execute_cdb_datain_len, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* CDB */
+ offset = dissect_execute_cdb_cdb(tvb, offset, pinfo, tree, devtype);
+
+ /* dataout */
+ offset = dissect_execute_cdb_payload(tvb, offset, pinfo, tree,
+ "Data out", hf_ndmp_execute_cdb_dataout_len, TRUE);
+
+ return offset;
+}
+
+static int
+dissect_execute_cdb_request_mc(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
+ SCSI_DEV_SMC);
+}
+
+static int
+dissect_execute_cdb_request_tape(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ return dissect_execute_cdb_request(tvb, offset, pinfo, tree, seq,
+ SCSI_DEV_SSC);
+}
+
+static int
+dissect_execute_cdb_sns(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 sns_len;
+ guint32 sns_len_full;
+
+ sns_len = tvb_get_ntohl(tvb, offset);
+ sns_len_full = rpc_roundup(sns_len);
+
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset,
+ 4+sns_len_full, "Sense data");
+ tree = proto_item_add_subtree(item, ett_ndmp_execute_cdb_sns);
+ }
+
+ proto_tree_add_uint(tree, hf_ndmp_execute_cdb_sns_len, tvb, offset, 4,
+ sns_len);
+ offset += 4;
+
+ if (sns_len != 0) {
+ dissect_scsi_snsinfo(tvb, pinfo, tree, offset, sns_len);
+ offset += sns_len_full;
+ }
+
+ return offset;
+}
+
+static int
+dissect_execute_cdb_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ conversation_t *conversation;
+ scsi_task_id_t task_key;
+
+ /*
+ * We need to provide SCSI task information to the SCSI
+ * dissection routines. We use a conversation plus the
+ * sequence number in requests and the reply sequence
+ * number in replies to identify SCSI tasks.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if (conversation != NULL) {
+ task_key.conv_id = conversation->index;
+ task_key.task_id = seq;
+ pinfo->private_data = &task_key;
+ } else {
+ /* no conversation, meaning we didn't see the request */
+ pinfo->private_data = NULL;
+ }
+
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* status */
+ proto_tree_add_item(tree, hf_ndmp_execute_cdb_status, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* dataout_len */
+ proto_tree_add_item(tree, hf_ndmp_execute_cdb_dataout_len, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* datain */
+ offset = dissect_execute_cdb_payload(tvb, offset, pinfo, tree,
+ "Data in", hf_ndmp_execute_cdb_datain_len, FALSE);
+
+ /* ext_sense */
+ offset = dissect_execute_cdb_sns(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+#define NDMP_TAPE_OPEN_MODE_READ 0
+#define NDMP_TAPE_OPEN_MODE_RDWR 1
+static const value_string tape_open_mode_vals[] = {
+ {NDMP_TAPE_OPEN_MODE_READ, "Read"},
+ {NDMP_TAPE_OPEN_MODE_RDWR, "Read/Write"},
+ {0, NULL}
+};
+
+static int
+dissect_tape_open_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* device */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_tape_device, offset, NULL);
+
+ /* open mode */
+ proto_tree_add_item(tree, hf_ndmp_tape_open_mode, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+
+static const true_false_string tfs_ndmp_tape_invalid_file_num = {
+ "File num is valid",
+ "File num is INVALID"
+};
+static const true_false_string tfs_ndmp_tape_invalid_soft_errors = {
+ "Soft errors is valid",
+ "Soft errors is INVALID"
+};
+static const true_false_string tfs_ndmp_tape_invalid_block_size = {
+ "Block size is valid",
+ "Block size is INVALID"
+};
+static const true_false_string tfs_ndmp_tape_invalid_block_no = {
+ "Block no is valid",
+ "Block no is INVALID"
+};
+static const true_false_string tfs_ndmp_tape_invalid_total_space = {
+ "Total space is valid",
+ "Total space is INVALID"
+};
+static const true_false_string tfs_ndmp_tape_invalid_space_remain = {
+ "Space remaining is INVALID",
+ "Space remaining is valid"
+};
+static const true_false_string tfs_ndmp_tape_invalid_partition = {
+ "Partition is INVALID",
+ "Partition is valid"
+};
+static int
+dissect_tape_invalid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 flags;
+
+ flags=tvb_get_ntohl(tvb, offset);
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Invalids: 0x%08x", flags);
+ tree = proto_item_add_subtree(item, ett_ndmp_tape_invalid);
+ }
+
+ proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_partition,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_space_remain,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_total_space,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_block_no,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_block_size,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_soft_errors,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_invalid_file_num,
+ tvb, offset, 4, flags);
+
+ offset+=4;
+ return offset;
+}
+
+static const true_false_string tfs_ndmp_tape_flags_no_rewind = {
+ "This is a NON-REWINDING device",
+ "This device supports rewind"
+};
+static const true_false_string tfs_ndmp_tape_flags_write_protect = {
+ "This device is WRITE-PROTECTED",
+ "This device is NOT write-protected"
+};
+static const true_false_string tfs_ndmp_tape_flags_error = {
+ "This device shows ERROR",
+ "This device shows NO errors"
+};
+static const true_false_string tfs_ndmp_tape_flags_unload = {
+ "This device supports UNLOAD",
+ "This device does NOT support unload"
+};
+static int
+dissect_tape_flags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 flags;
+
+ flags=tvb_get_ntohl(tvb, offset);
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Flags: 0x%08x", flags);
+ tree = proto_item_add_subtree(item, ett_ndmp_tape_flags);
+ }
+
+
+ proto_tree_add_boolean(tree, hf_ndmp_tape_flags_unload,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_flags_error,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_flags_write_protect,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_tape_flags_no_rewind,
+ tvb, offset, 4, flags);
+
+ offset+=4;
+ return offset;
+}
+
+static int
+dissect_tape_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* invalid bits */
+ offset=dissect_tape_invalid(tvb, offset, pinfo, tree);
+
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* flags */
+ offset=dissect_tape_flags(tvb, offset, pinfo, tree);
+
+ /* file_num */
+ proto_tree_add_item(tree, hf_ndmp_tape_file_num, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* soft_errors */
+ proto_tree_add_item(tree, hf_ndmp_tape_soft_errors, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* block_size */
+ proto_tree_add_item(tree, hf_ndmp_tape_block_size, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* block_no */
+ proto_tree_add_item(tree, hf_ndmp_tape_block_no, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* total_space */
+ offset = dissect_rpc_uint64(tvb, tree,hf_ndmp_tape_total_space,
+ offset);
+
+ /* space_remain */
+ offset = dissect_rpc_uint64(tvb, tree,hf_ndmp_tape_space_remain,
+ offset);
+
+ /* partition */
+ proto_tree_add_item(tree, hf_ndmp_tape_partition, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+#define NDMP_TAPE_MTIO_FSF 0
+#define NDMP_TAPE_MTIO_BSF 1
+#define NDMP_TAPE_MTIO_FSR 2
+#define NDMP_TAPE_MTIO_BSR 3
+#define NDMP_TAPE_MTIO_REW 4
+#define NDMP_TAPE_MTIO_EOF 5
+#define NDMP_TAPE_MTIO_OFF 6
+static const value_string tape_mtio_vals[] = {
+ {NDMP_TAPE_MTIO_FSF, "FSF"},
+ {NDMP_TAPE_MTIO_BSF, "BSF"},
+ {NDMP_TAPE_MTIO_FSR, "FSR"},
+ {NDMP_TAPE_MTIO_BSR, "BSR"},
+ {NDMP_TAPE_MTIO_REW, "REW"},
+ {NDMP_TAPE_MTIO_EOF, "EOF"},
+ {NDMP_TAPE_MTIO_OFF, "OFF"},
+ {0, NULL}
+};
+
+static int
+dissect_tape_mtio_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* op */
+ proto_tree_add_item(tree, hf_ndmp_tape_mtio_op, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* count */
+ proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_tape_mtio_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* resid count */
+ proto_tree_add_item(tree, hf_ndmp_resid_count, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+#define NDMP_MOVER_STATE_IDLE 0
+#define NDMP_MOVER_STATE_LISTEN 1
+#define NDMP_MOVER_STATE_ACTIVE 2
+#define NDMP_MOVER_STATE_PAUSED 3
+#define NDMP_MOVER_STATE_HALTED 4
+static const value_string mover_state_vals[] = {
+ {NDMP_MOVER_STATE_IDLE, "MOVER_STATE_IDLE"},
+ {NDMP_MOVER_STATE_LISTEN, "MOVER_STATE_LISTEN"},
+ {NDMP_MOVER_STATE_ACTIVE, "MOVER_STATE_ACTIVE"},
+ {NDMP_MOVER_STATE_PAUSED, "MOVER_STATE_PAUSED"},
+ {NDMP_MOVER_STATE_HALTED, "MOVER_STATE_HALTED"},
+ {0, NULL}
+};
+
+#define NDMP_MOVER_PAUSE_NA 0
+#define NDMP_MOVER_PAUSE_EOM 1
+#define NDMP_MOVER_PAUSE_EOF 2
+#define NDMP_MOVER_PAUSE_SEEK 3
+#define NDMP_MOVER_PAUSE_MEDIA_ERROR 4
+#define NDMP_MOVER_PAUSE_EOW 5
+static const value_string mover_pause_vals[] = {
+ {NDMP_MOVER_PAUSE_NA, "MOVER_PAUSE_NA"},
+ {NDMP_MOVER_PAUSE_EOM, "MOVER_PAUSE_EOM"},
+ {NDMP_MOVER_PAUSE_EOF, "MOVER_PAUSE_EOF"},
+ {NDMP_MOVER_PAUSE_SEEK, "MOVER_PAUSE_SEEK"},
+ {NDMP_MOVER_PAUSE_MEDIA_ERROR, "MOVER_PAUSE_MEDIA_ERROR"},
+ {NDMP_MOVER_PAUSE_EOW, "MOVER_PAUSE_EOW"},
+ {0, NULL}
+};
+
+#define NDMP_HALT_NA 0
+#define NDMP_HALT_CONNECT_CLOSE 1
+#define NDMP_HALT_ABORTED 2
+#define NDMP_HALT_INTERNAL_ERROR 3
+#define NDMP_HALT_CONNECT_ERROR 4
+static const value_string halt_vals[] = {
+ {NDMP_HALT_NA, "HALT_NA"},
+ {NDMP_HALT_CONNECT_CLOSE, "HALT_CONNECT_CLOSE"},
+ {NDMP_HALT_ABORTED, "HALT_ABORTED"},
+ {NDMP_HALT_INTERNAL_ERROR, "HALT_INTERNAL_ERROR"},
+ {NDMP_HALT_CONNECT_ERROR, "HALT_CONNECT_ERROR"},
+ {0, NULL}
+};
+
+static int
+dissect_ndmp_addr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 type;
+
+ type=tvb_get_ntohl(tvb, offset);
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Type: %s ", val_to_str(type, addr_type_vals,"Unknown addr type (0x%02x)") );
+ tree = proto_item_add_subtree(item, ett_ndmp_addr);
+ }
+
+ /*address type*/
+ proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+
+ switch(type){
+ case NDMP_ADDR_LOCAL:
+ break;
+ case NDMP_ADDR_TCP:
+ /* IP addr */
+ proto_tree_add_item(tree, hf_ndmp_addr_ip, tvb, offset, 4, FALSE);
+ offset+=4;
+
+ /* TCP port */
+ proto_tree_add_item(tree, hf_ndmp_addr_tcp, tvb, offset, 4, FALSE);
+ offset+=4;
+
+ break;
+ case NDMP_ADDR_FC:
+ /* FCAL loop id */
+ proto_tree_add_item(tree, hf_ndmp_addr_fcal_loop_id, tvb, offset, 4, FALSE);
+ offset+=4;
+
+ break;
+ case NDMP_ADDR_IPC:
+ /* IPC address */
+ offset = dissect_rpc_data(tvb, tree, hf_ndmp_addr_ipc, offset);
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_mover_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* mover state */
+ proto_tree_add_item(tree, hf_ndmp_mover_state, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* mover pause */
+ proto_tree_add_item(tree, hf_ndmp_mover_pause, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* halt */
+ proto_tree_add_item(tree, hf_ndmp_halt, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* record size */
+ proto_tree_add_item(tree, hf_ndmp_record_size, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* record num */
+ proto_tree_add_item(tree, hf_ndmp_record_num, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* data written */
+ proto_tree_add_item(tree, hf_ndmp_data_written, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* seek position */
+ proto_tree_add_item(tree, hf_ndmp_seek_position, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* bytes left to read */
+ proto_tree_add_item(tree, hf_ndmp_bytes_left_to_read, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* window offset */
+ proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* window length */
+ proto_tree_add_item(tree, hf_ndmp_window_length, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* this is where v2 ends */
+ if(ndmp_protocol_version==NDMP_PROTOCOL_V2){
+ return offset;
+ }
+
+
+ /* ndmp addr */
+ offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+#define NDMP_MOVER_MODE_READ 0
+#define NDMP_MOVER_MODE_WRITE 1
+static const value_string mover_mode_vals[] = {
+ {NDMP_MOVER_MODE_READ, "MODE_READ"},
+ {NDMP_MOVER_MODE_WRITE, "MOVER_MODE_WRITE"},
+ {0, NULL}
+};
+
+static int
+dissect_mover_listen_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* mode */
+ proto_tree_add_item(tree, hf_ndmp_mover_mode, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /*address type*/
+ proto_tree_add_item(tree, hf_ndmp_addr_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_mover_listen_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* ndmp addr */
+ offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+static int
+dissect_mover_set_window_request(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
+{
+ /* window offset */
+ proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* window length */
+ proto_tree_add_item(tree, hf_ndmp_window_length, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+static int
+dissect_mover_set_record_size_request(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
+{
+ /* record size */
+ proto_tree_add_item(tree, hf_ndmp_record_size, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_mover_connect_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* mode */
+ proto_tree_add_item(tree, hf_ndmp_mover_mode, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* ndmp addr */
+ offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+static int
+dissect_log_file_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* file */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_file_name, offset, NULL);
+
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ return offset;
+}
+
+#define NDMP_LOG_TYPE_NORMAL 0
+#define NDMP_LOG_TYPE_DEBUG 1
+#define NDMP_LOG_TYPE_ERROR 2
+#define NDMP_LOG_TYPE_WARNING 3
+static const value_string log_type_vals[] = {
+ {NDMP_LOG_TYPE_NORMAL, "NORMAL"},
+ {NDMP_LOG_TYPE_DEBUG, "DEBUG"},
+ {NDMP_LOG_TYPE_ERROR, "ERROR"},
+ {NDMP_LOG_TYPE_WARNING, "WARNING"},
+ {0, NULL}
+};
+
+static int
+dissect_log_message_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* type */
+ proto_tree_add_item(tree, hf_ndmp_log_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* message id */
+ proto_tree_add_item(tree, hf_ndmp_log_message_id, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* message */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_log_message, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_notify_data_halted_request(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
+{
+ /* halt */
+ proto_tree_add_item(tree, hf_ndmp_halt, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* reason */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_halt_reason, offset, NULL);
+
+ return offset;
+}
+
+#define NDMP_CONNECTED_CONNECTED 0
+#define NDMP_CONNECTED_SHUTDOWN 1
+#define NDMP_CONNECTED_REFUSED 2
+static const value_string connected_vals[] = {
+ {NDMP_CONNECTED_CONNECTED, "CONNECTED"},
+ {NDMP_CONNECTED_SHUTDOWN, "SHUTDOWN"},
+ {NDMP_CONNECTED_REFUSED, "REFUSED"},
+ {0, NULL}
+};
+
+static int
+dissect_notify_connected_request(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
+{
+ /* connected */
+ proto_tree_add_item(tree, hf_ndmp_connected, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* version number */
+ proto_tree_add_item(tree, hf_ndmp_version, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* reason */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_connected_reason, offset, NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_notify_mover_paused_request(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree, guint32 seq _U_)
+{
+ /* mover pause */
+ proto_tree_add_item(tree, hf_ndmp_mover_pause, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* seek position */
+ proto_tree_add_item(tree, hf_ndmp_seek_position, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+static int
+dissect_auth_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint type;
+
+ type=tvb_get_ntohl(tvb,offset);
+
+ /* auth type */
+ proto_tree_add_item(tree, hf_ndmp_auth_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ switch(type){
+ case NDMP_AUTH_NONE:
+ break;
+ case NDMP_AUTH_TEXT:
+ /* auth id */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_auth_id, offset, NULL);
+
+ /* auth password */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_auth_password, offset, NULL);
+
+
+ break;
+ case NDMP_AUTH_MD5:
+ /* auth id */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_auth_id, offset, NULL);
+
+ /* digest */
+ proto_tree_add_item(tree, hf_ndmp_auth_digest,
+ tvb, offset, 16, FALSE);
+ offset+=16;
+ }
+
+ return offset;
+}
+
+static int
+dissect_connect_client_auth_request(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
+{
+ return dissect_auth_data(tvb, offset, pinfo, tree);
+}
+
+static int
+dissect_connect_server_auth_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* auth data */
+ offset = dissect_auth_data(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+static int
+dissect_tape_write_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* data */
+ offset = dissect_rpc_data(tvb, tree, hf_ndmp_data, offset);
+
+ return offset;
+}
+
+static int
+dissect_tape_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* count */
+ proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_tape_read_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* count */
+ proto_tree_add_item(tree, hf_ndmp_count, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_tape_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* data */
+ offset = dissect_rpc_data(tvb, tree, hf_ndmp_data, offset);
+
+ return offset;
+}
+
+#define NDMP_FS_UNIX 0
+#define NDMP_FS_NT 1
+#define NDMP_FS_OTHER 2
+static const value_string file_fs_type_vals[] = {
+ {NDMP_FS_UNIX, "UNIX"},
+ {NDMP_FS_NT, "NT"},
+ {NDMP_FS_OTHER, "OTHER"},
+ {0, NULL}
+};
+
+static int
+dissect_file_name(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ int old_offset=offset;
+ guint32 type;
+ char *name;
+
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "File");
+ tree = proto_item_add_subtree(item, ett_ndmp_file_name);
+ }
+
+ /* file type */
+ type=tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_ndmp_file_fs_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ switch(type){
+ case NDMP_FS_UNIX:
+ /* file */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_file_name, offset, &name);
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
+ }
+ break;
+ case NDMP_FS_NT:
+ /* nt file */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_nt_file_name, offset, &name);
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
+ }
+
+ /* dos file */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_dos_file_name, offset, NULL);
+ break;
+ default:
+ /* file */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_file_name, offset, &name);
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", name);
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
+ val_to_str(type, file_fs_type_vals, "Unknown type") );
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static const true_false_string tfs_ndmp_file_invalid_atime = {
+ "Atime is INVALID",
+ "Atime is valid"
+};
+static const true_false_string tfs_ndmp_file_invalid_ctime = {
+ "Ctime is INVALID",
+ "Ctime is valid"
+};
+static const true_false_string tfs_ndmp_file_invalid_group = {
+ "Group is INVALID",
+ "Group is valid"
+};
+static int
+dissect_file_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 flags;
+
+ flags=tvb_get_ntohl(tvb, offset);
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Invalids: 0x%08x", flags);
+ tree = proto_item_add_subtree(item, ett_ndmp_file_invalids);
+ }
+
+ proto_tree_add_boolean(tree, hf_ndmp_file_invalid_group,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_file_invalid_ctime,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_file_invalid_atime,
+ tvb, offset, 4, flags);
+
+ offset+=4;
+ return offset;
+}
+
+#define NDMP_FILE_TYPE_DIR 0
+#define NDMP_FILE_TYPE_FIFO 1
+#define NDMP_FILE_TYPE_CSPEC 2
+#define NDMP_FILE_TYPE_BSPEC 3
+#define NDMP_FILE_TYPE_REG 4
+#define NDMP_FILE_TYPE_SLINK 5
+#define NDMP_FILE_TYPE_SOCK 6
+#define NDMP_FILE_TYPE_REGISTRY 7
+#define NDMP_FILE_TYPE_OTHER 8
+static const value_string file_type_vals[] = {
+ {NDMP_FILE_TYPE_DIR, "DIR"},
+ {NDMP_FILE_TYPE_FIFO, "FIFO"},
+ {NDMP_FILE_TYPE_CSPEC, "CSPEC"},
+ {NDMP_FILE_TYPE_BSPEC, "BSPEC"},
+ {NDMP_FILE_TYPE_REG, "REG"},
+ {NDMP_FILE_TYPE_SLINK, "SLINK"},
+ {NDMP_FILE_TYPE_SOCK, "SOCK"},
+ {NDMP_FILE_TYPE_REGISTRY, "REGISTRY"},
+ {NDMP_FILE_TYPE_OTHER, "OTHER"},
+ {0, NULL}
+};
+
+static int
+dissect_file_stats(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ int old_offset=offset;
+ nstime_t ns;
+
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "Stats:");
+ tree = proto_item_add_subtree(item, ett_ndmp_file_stats);
+ }
+
+ /* invalids */
+ offset = dissect_file_invalids(tvb, offset, pinfo, tree);
+
+ /* file fs type */
+ proto_tree_add_item(tree, hf_ndmp_file_fs_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* file type */
+ proto_tree_add_item(tree, hf_ndmp_file_type, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* mtime */
+ ns.secs=tvb_get_ntohl(tvb, offset);
+ ns.nsecs=0;
+ proto_tree_add_time(tree, hf_ndmp_file_mtime, tvb, offset, 4, &ns);
+ offset += 4;
+
+ /* atime */
+ ns.secs=tvb_get_ntohl(tvb, offset);
+ ns.nsecs=0;
+ proto_tree_add_time(tree, hf_ndmp_file_atime, tvb, offset, 4, &ns);
+ offset += 4;
+
+ /* ctime */
+ ns.secs=tvb_get_ntohl(tvb, offset);
+ ns.nsecs=0;
+ proto_tree_add_time(tree, hf_ndmp_file_ctime, tvb, offset, 4, &ns);
+ offset += 4;
+
+ /* owner */
+ proto_tree_add_item(tree, hf_ndmp_file_owner, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* group */
+ proto_tree_add_item(tree, hf_ndmp_file_group, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /*XXX here we should do proper dissection of mode for unix or
+ fattr for nt, call appropriate functions in nfs/smb*/
+ /* fattr */
+ proto_tree_add_item(tree, hf_ndmp_file_fattr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /*file size*/
+ offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_file_size,
+ offset);
+
+ /* links */
+ proto_tree_add_item(tree, hf_ndmp_file_links, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+dissect_file(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ int old_offset=offset;
+
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "File:");
+ tree = proto_item_add_subtree(item, ett_ndmp_file);
+ }
+
+ /* file names */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_file_name, hf_ndmp_file_names);
+
+ /* file stats */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_file_stats, hf_ndmp_file_stats);
+
+ /* node */
+ proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* fh_info */
+ proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_fh_add_file_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* files */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_file, hf_ndmp_files);
+
+ return offset;
+}
+
+static int
+dissect_dir(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* file names */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_file_name, hf_ndmp_file_names);
+
+ /* node */
+ proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* parent */
+ proto_tree_add_item(tree, hf_ndmp_file_parent, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+static int
+dissect_fh_add_dir_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* dirs */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_dir, hf_ndmp_dirs);
+
+ return offset;
+}
+
+static int
+dissect_node(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* file stats */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_file_stats, hf_ndmp_file_stats);
+
+ /* node */
+ proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* fh_info */
+ proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+
+static int
+dissect_fh_add_node_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /* node */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_node, hf_ndmp_nodes);
+
+ return offset;
+}
+
+static int
+dissect_data_start_backup_request(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq _U_)
+{
+ /*butype name*/
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_butype_name, offset, NULL);
+
+ /* default env */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_default_env, hf_ndmp_butype_default_env);
+
+ return offset;
+}
+
+static int
+dissect_nlist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ /*original path*/
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_bu_original_path, offset, NULL);
+
+ /*destination dir*/
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_bu_destination_dir, offset, NULL);
+
+ if(ndmp_protocol_version==NDMP_PROTOCOL_V2){
+ /* just 2 reserved bytes (4 with padding) */
+ offset += 4;
+ } else {
+ /*new name*/
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_bu_new_name, offset, NULL);
+
+ /*other name*/
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_bu_other_name, offset, NULL);
+
+ /* node */
+ proto_tree_add_item(tree, hf_ndmp_file_node, tvb, offset, 8, FALSE);
+ offset += 8;
+ }
+
+ /* fh_info */
+ proto_tree_add_item(tree, hf_ndmp_file_fh_info, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+
+static int
+dissect_data_start_recover_request(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree, guint32 seq _U_)
+{
+ if(ndmp_protocol_version==NDMP_PROTOCOL_V2){
+ /* ndmp addr */
+ offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
+ }
+
+ /* default env */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_default_env, hf_ndmp_butype_default_env);
+
+ /* nlist */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_nlist, hf_ndmp_nlist);
+
+ /*butype name*/
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ndmp_butype_name, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_data_get_env_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* default env */
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_default_env, hf_ndmp_butype_default_env);
+
+ return offset;
+}
+
+
+static const true_false_string tfs_ndmp_state_invalid_ebr = {
+ "Estimated Bytes Remaining is INVALID",
+ "Estimated Bytes Remaining is valid"
+};
+static const true_false_string tfs_ndmp_state_invalid_etr = {
+ "Estimated Time Remaining is INVALID",
+ "Estimated Time Remaining is valid"
+};
+static int
+dissect_state_invalids(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *parent_tree)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ guint32 flags;
+
+ flags=tvb_get_ntohl(tvb, offset);
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Invalids: 0x%08x", flags);
+ tree = proto_item_add_subtree(item, ett_ndmp_state_invalids);
+ }
+
+ proto_tree_add_boolean(tree, hf_ndmp_state_invalid_etr,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_ndmp_state_invalid_ebr,
+ tvb, offset, 4, flags);
+
+ offset+=4;
+ return offset;
+}
+
+#define NDMP_DATA_OP_NOACTION 0
+#define NDMP_DATA_OP_BACKUP 1
+#define NDMP_DATA_OP_RESTORE 2
+static const value_string bu_operation_vals[] = {
+ {NDMP_DATA_OP_NOACTION, "NOACTION"},
+ {NDMP_DATA_OP_BACKUP, "BACKUP"},
+ {NDMP_DATA_OP_RESTORE, "RESTORE"},
+ {0, NULL}
+};
+
+#define NDMP_DATA_STATE_IDLE 0
+#define NDMP_DATA_STATE_ACTIVE 1
+#define NDMP_DATA_STATE_HALTED 2
+#define NDMP_DATA_STATE_LISTEN 3
+#define NDMP_DATA_STATE_CONNECTED 4
+static const value_string data_state_vals[] = {
+ {NDMP_DATA_STATE_IDLE, "IDLE"},
+ {NDMP_DATA_STATE_ACTIVE, "ACTIVE"},
+ {NDMP_DATA_STATE_HALTED, "HALTED"},
+ {NDMP_DATA_STATE_LISTEN, "LISTEN"},
+ {NDMP_DATA_STATE_CONNECTED, "CONNECTED"},
+ {0, NULL}
+};
+
+#define NDMP_DATA_HALTED_NA 0
+#define NDMP_DATA_HALTED_SUCCESSFUL 1
+#define NDMP_DATA_HALTED_ABORTED 2
+#define NDMP_DATA_HALTED_INTERNAL_ERROR 3
+#define NDMP_DATA_HALTED_CONNECT_ERROR 4
+static const value_string data_halted_vals[] = {
+ {NDMP_DATA_HALTED_NA, "HALTED_NA"},
+ {NDMP_DATA_HALTED_SUCCESSFUL, "HALTED_SUCCESSFUL"},
+ {NDMP_DATA_HALTED_ABORTED, "HALTED_ABORTED"},
+ {NDMP_DATA_HALTED_INTERNAL_ERROR, "HALTED_INTERNAL_ERROR"},
+ {NDMP_DATA_HALTED_CONNECT_ERROR, "HALTED_CONNECT_ERROR"},
+ {0, NULL}
+};
+
+static int
+dissect_data_get_state_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq)
+{
+ nstime_t ns;
+
+ /* invalids */
+ offset = dissect_state_invalids(tvb, offset, pinfo, tree);
+
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, seq);
+
+ /* operation */
+ proto_tree_add_item(tree, hf_ndmp_bu_operation, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* state */
+ proto_tree_add_item(tree, hf_ndmp_data_state, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* halted reason */
+ proto_tree_add_item(tree, hf_ndmp_data_halted, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /*bytes processed*/
+ offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_data_bytes_processed,
+ offset);
+
+ /*est bytes remain*/
+ offset = dissect_rpc_uint64(tvb, tree, hf_ndmp_data_est_bytes_remain,
+ offset);
+
+ /* est time remain */
+ ns.secs=tvb_get_ntohl(tvb, offset);
+ ns.nsecs=0;
+ proto_tree_add_time(tree, hf_ndmp_data_est_time_remain, tvb, offset, 4, &ns);
+ offset += 4;
+
+ /* ndmp addr */
+ offset=dissect_ndmp_addr(tvb, offset, pinfo, tree);
+
+ /* window offset */
+ proto_tree_add_item(tree, hf_ndmp_window_offset, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* window length */
+ proto_tree_add_item(tree, hf_ndmp_window_length, tvb, offset, 8, FALSE);
+ offset += 8;
+
+ return offset;
+}
+
+
+typedef struct _ndmp_command {
+ guint32 cmd;
+ int (*request) (tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq);
+ int (*response)(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint32 seq);
+} ndmp_command;
+
+static const ndmp_command ndmp_commands[] = {
+ {NDMP_CONFIG_GET_HOST_INFO,
+ NULL, dissect_ndmp_get_host_info_reply},
+ {NDMP_CONFIG_GET_CONNECTION_TYPE,
+ NULL, dissect_ndmp_config_get_connection_type_reply},
+ {NDMP_CONFIG_GET_AUTH_ATTR,
+ dissect_get_auth_type_request, dissect_auth_attr_msg},
+ {NDMP_CONFIG_GET_BUTYPE_INFO,
+ NULL, dissect_get_butype_info_reply},
+ {NDMP_CONFIG_GET_FS_INFO,
+ NULL, dissect_get_fs_info_reply},
+ {NDMP_CONFIG_GET_TAPE_INFO,
+ NULL, dissect_get_tape_info_reply},
+ {NDMP_CONFIG_GET_SCSI_INFO,
+ NULL, dissect_get_scsi_info_reply},
+ {NDMP_CONFIG_GET_SERVER_INFO,
+ NULL, dissect_get_server_info_reply},
+ {NDMP_SCSI_OPEN,
+ dissect_scsi_open_request, dissect_error},
+ {NDMP_SCSI_CLOSE,
+ NULL, dissect_error},
+ {NDMP_SCSI_GET_STATE,
+ NULL, dissect_scsi_get_state_reply},
+ {NDMP_SCSI_SET_TARGET,
+ dissect_scsi_set_state_request, dissect_error},
+ {NDMP_SCSI_RESET_DEVICE,
+ NULL, dissect_error},
+ {NDMP_SCSI_RESET_BUS,
+ NULL, dissect_error},
+ {NDMP_SCSI_EXECUTE_CDB,
+ dissect_execute_cdb_request_mc, dissect_execute_cdb_reply},
+ {NDMP_TAPE_OPEN,
+ dissect_tape_open_request, dissect_error},
+ {NDMP_TAPE_CLOSE,
+ NULL, dissect_error},
+ {NDMP_TAPE_GET_STATE,
+ NULL, dissect_tape_get_state_reply},
+ {NDMP_TAPE_MTIO,
+ dissect_tape_mtio_request, dissect_tape_mtio_reply},
+ {NDMP_TAPE_WRITE,
+ dissect_tape_write_request, dissect_tape_write_reply},
+ {NDMP_TAPE_READ,
+ dissect_tape_read_request, dissect_tape_read_reply},
+ {NDMP_TAPE_EXECUTE_CDB,
+ dissect_execute_cdb_request_tape, dissect_execute_cdb_reply},
+ {NDMP_DATA_GET_STATE,
+ NULL, dissect_data_get_state_reply},
+ {NDMP_DATA_START_BACKUP,
+ dissect_data_start_backup_request, dissect_error },
+ {NDMP_DATA_START_RECOVER,
+ dissect_data_start_recover_request, dissect_error },
+ {NDMP_DATA_ABORT,
+ NULL, dissect_error},
+ {NDMP_DATA_GET_ENV,
+ NULL, dissect_data_get_env_reply},
+ {NDMP_DATA_STOP,
+ NULL, dissect_error},
+ {NDMP_DATA_LISTEN,
+ dissect_ndmp_addr_msg, dissect_mover_listen_reply},
+ {NDMP_DATA_CONNECT,
+ dissect_ndmp_addr_msg, dissect_error},
+ {NDMP_NOTIFY_DATA_HALTED,
+ dissect_notify_data_halted_request, NULL},
+ {NDMP_NOTIFY_CONNECTED,
+ dissect_notify_connected_request, NULL},
+ {NDMP_NOTIFY_MOVER_HALTED,
+ dissect_notify_data_halted_request, NULL},
+ {NDMP_NOTIFY_MOVER_PAUSED,
+ dissect_notify_mover_paused_request, NULL},
+ {NDMP_NOTIFY_DATA_READ,
+ dissect_mover_set_window_request, NULL},
+ {NDMP_LOG_FILE,
+ dissect_log_file_request, NULL},
+ {NDMP_LOG_MESSAGE,
+ dissect_log_message_request, NULL},
+ {NDMP_FH_ADD_FILE,
+ dissect_fh_add_file_request, NULL},
+ {NDMP_FH_ADD_DIR,
+ dissect_fh_add_dir_request, NULL},
+ {NDMP_FH_ADD_NODE,
+ dissect_fh_add_node_request, NULL},
+ {NDMP_CONNECT_OPEN,
+ dissect_connect_open_request, dissect_error},
+ {NDMP_CONNECT_CLIENT_AUTH,
+ dissect_connect_client_auth_request, dissect_error},
+ {NDMP_CONNECT_CLOSE,
+ NULL,NULL},
+ {NDMP_CONNECT_SERVER_AUTH,
+ dissect_auth_attr_msg, dissect_connect_server_auth_reply},
+ {NDMP_MOVER_GET_STATE,
+ NULL, dissect_mover_get_state_reply},
+ {NDMP_MOVER_LISTEN,
+ dissect_mover_listen_request, dissect_mover_listen_reply},
+ {NDMP_MOVER_CONTINUE,
+ NULL, dissect_error},
+ {NDMP_MOVER_ABORT,
+ NULL, dissect_error},
+ {NDMP_MOVER_STOP,
+ NULL, dissect_error},
+ {NDMP_MOVER_SET_WINDOW,
+ dissect_mover_set_window_request, dissect_error},
+ {NDMP_MOVER_READ,
+ dissect_mover_set_window_request, dissect_error},
+ {NDMP_MOVER_CLOSE,
+ NULL, dissect_error},
+ {NDMP_MOVER_SET_RECORD_SIZE,
+ dissect_mover_set_record_size_request, dissect_error},
+ {NDMP_MOVER_CONNECT,
+ dissect_mover_connect_request, dissect_error},
+ {0, NULL,NULL}
+};
+
+
+static int
+dissect_ndmp_header(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, struct ndmp_header *nh)
+{
+ proto_item* item = NULL;
+ proto_tree* tree = NULL;
+ nstime_t ns;
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, hf_ndmp_header, tvb,
+ offset, 24, FALSE);
+ tree = proto_item_add_subtree(item, ett_ndmp_header);
+ }
+
+ /* sequence number */
+ proto_tree_add_uint(tree, hf_ndmp_sequence, tvb, offset, 4, nh->seq);
+ offset += 4;
+
+ /* timestamp */
+ ns.secs=nh->time;
+ ns.nsecs=0;
+ proto_tree_add_time(tree, hf_ndmp_timestamp, tvb, offset, 4, &ns);
+ offset += 4;
+
+ /* Message Type */
+ proto_tree_add_uint(tree, hf_ndmp_msgtype, tvb, offset, 4, nh->type);
+ offset += 4;
+
+ /* Message */
+ proto_tree_add_uint(tree, hf_ndmp_msg, tvb, offset, 4, nh->msg);
+ offset += 4;
+
+ /* Reply sequence number */
+ proto_tree_add_uint(tree, hf_ndmp_reply_sequence, tvb, offset, 4, nh->rep_seq);
+ offset += 4;
+
+ /* error */
+ offset=dissect_error(tvb, offset, pinfo, tree, nh->seq);
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ val_to_str(nh->msg, msg_vals, "Unknown Message (0x%02x)"),
+ val_to_str(nh->type, msg_type_vals, "Unknown Type (0x%02x)")
+ );
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_ndmp_cmd(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, struct ndmp_header *nh)
+{
+ int i;
+ proto_item *cmd_item=NULL;
+ proto_tree *cmd_tree=NULL;
+
+ offset=dissect_ndmp_header(tvb, offset, pinfo, tree, nh);
+
+ for(i=0;ndmp_commands[i].cmd!=0;i++){
+ if(ndmp_commands[i].cmd==nh->msg){
+ break;
+ }
+ }
+
+
+ if(ndmp_commands[i].cmd==0){
+ /* we do not know this message */
+ proto_tree_add_text(tree, tvb, offset, -1, "Unknown type of NDMP message: 0x%02x", nh->msg);
+ offset+=tvb_length_remaining(tvb, offset);
+ return offset;
+ }
+
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ if(tree){
+ cmd_item = proto_tree_add_text(tree, tvb, offset, -1,
+ msg_vals[i].strptr);
+ cmd_tree = proto_item_add_subtree(cmd_item, ett_ndmp);
+ }
+ }
+
+ if(nh->type==NDMP_MESSAGE_REQUEST){
+ if(ndmp_commands[i].request){
+ offset=ndmp_commands[i].request(tvb, offset, pinfo, cmd_tree,
+ nh->seq);
+ }
+ } else {
+ if(ndmp_commands[i].response){
+ offset=ndmp_commands[i].response(tvb, offset, pinfo, cmd_tree,
+ nh->rep_seq);
+ }
+ }
+
+ return offset;
+}
+
+static gboolean
+dissect_ndmp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ tvbuff_t *frag_tvb, fragment_data *ipfd_head, gboolean is_tcp,
+ guint32 rpc_rm, gboolean first_pdu)
+{
+ int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0;
+ guint32 size;
+ struct ndmp_header nh;
+ proto_item *ndmp_item = NULL;
+ proto_tree *ndmp_tree = NULL;
+
+ /* size of this NDMP PDU */
+ size = tvb_length_remaining(tvb, offset);
+ if (size < 24) {
+ /* too short to be NDMP */
+ return FALSE;
+ }
+
+ /*
+ * Check the NDMP header, if we have it.
+ */
+ nh.seq = tvb_get_ntohl(tvb, offset);
+ nh.time = tvb_get_ntohl(tvb, offset+4);
+ nh.type = tvb_get_ntohl(tvb, offset+8);
+ nh.msg = tvb_get_ntohl(tvb, offset+12);
+ nh.rep_seq = tvb_get_ntohl(tvb, offset+16);
+ nh.err = tvb_get_ntohl(tvb, offset+20);
+
+ if (nh.type > 1)
+ return FALSE;
+ if (nh.msg > 0xa09 || nh.msg == 0)
+ return FALSE;
+ if (nh.err > 0x17)
+ return FALSE;
+
+ /*
+ * Check if this is the last fragment.
+ */
+ if (!(rpc_rm & RPC_RM_LASTFRAG)) {
+ /*
+ * This isn't the last fragment.
+ * If we're doing reassembly, just return
+ * TRUE to indicate that this looks like
+ * the beginning of an NDMP message,
+ * and let them do reassembly.
+ */
+ if (ndmp_defragment)
+ return TRUE;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDMP");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (first_pdu)
+ col_clear(pinfo->cinfo, COL_INFO);
+ else
+ col_append_fstr(pinfo->cinfo, COL_INFO, "; ");
+ }
+
+ if (tree) {
+ ndmp_item = proto_tree_add_item(tree, proto_ndmp,
+ tvb, 0, -1, FALSE);
+ ndmp_tree = proto_item_add_subtree(ndmp_item, ett_ndmp);
+
+ if (is_tcp) {
+ show_rpc_fraginfo(tvb, frag_tvb, ndmp_tree, rpc_rm,
+ ipfd_head, pinfo);
+ }
+ }
+
+ /*
+ * We cannot trust what dissect_ndmp_cmd() tells us, as there
+ * are implementations which pad some additional data after
+ * the PDU. We MUST use size.
+ */
+ dissect_ndmp_cmd(tvb, offset, pinfo, ndmp_tree, &nh);
+ return TRUE;
+}
+
+static void
+dissect_ndmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ int len;
+ gboolean first_pdu = TRUE;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * Process this fragment.
+ */
+ len = dissect_rpc_fragment(tvb, offset, pinfo, tree,
+ dissect_ndmp_message, FALSE, proto_ndmp, ett_ndmp,
+ ndmp_defragment, first_pdu);
+ first_pdu = FALSE;
+ if (len < 0) {
+ /*
+ * We need more data from the TCP stream for
+ * this fragment.
+ */
+ return;
+ }
+ if (len == 0) {
+ /*
+ * It's not NDMP. Stop processing.
+ */
+ break;
+ }
+
+ offset += len;
+ }
+}
+
+void
+proto_register_ndmp(void)
+{
+
+ static hf_register_info hf_ndmp[] = {
+ { &hf_ndmp_header, {
+ "NDMP Header", "ndmp.header", FT_NONE, 0,
+ NULL, 0, "NDMP Header", HFILL }},
+
+ { &hf_ndmp_sequence, {
+ "Sequence", "ndmp.sequence", FT_UINT32, BASE_DEC,
+ NULL, 0, "Sequence number for NDMP PDU", HFILL }},
+
+ { &hf_ndmp_reply_sequence, {
+ "Reply Sequence", "ndmp.reply_sequence", FT_UINT32, BASE_DEC,
+ NULL, 0, "Reply Sequence number for NDMP PDU", HFILL }},
+
+ { &hf_ndmp_timestamp, {
+ "Time", "ndmp.timestamp", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Timestamp for this NDMP PDU", HFILL }},
+
+ { &hf_ndmp_msgtype, {
+ "Type", "ndmp.msg_type", FT_UINT32, BASE_DEC,
+ VALS(msg_type_vals), 0, "Is this a Request or Response?", HFILL }},
+
+ { &hf_ndmp_msg, {
+ "Message", "ndmp.msg", FT_UINT32, BASE_HEX,
+ VALS(msg_vals), 0, "Type of NDMP PDU", HFILL }},
+
+ { &hf_ndmp_error, {
+ "Error", "ndmp.error", FT_UINT32, BASE_DEC,
+ VALS(error_vals), 0, "Error code for this NDMP PDU", HFILL }},
+
+ { &hf_ndmp_version, {
+ "Version", "ndmp.version", FT_UINT32, BASE_DEC,
+ NULL, 0, "Version of NDMP protocol", HFILL }},
+
+ { &hf_ndmp_hostname, {
+ "Hostname", "ndmp.hostname", FT_STRING, BASE_NONE,
+ NULL, 0, "Hostname", HFILL }},
+
+ { &hf_ndmp_hostid, {
+ "HostID", "ndmp.hostid", FT_STRING, BASE_NONE,
+ NULL, 0, "HostID", HFILL }},
+
+ { &hf_ndmp_os_type, {
+ "OS Type", "ndmp.os.type", FT_STRING, BASE_NONE,
+ NULL, 0, "OS Type", HFILL }},
+
+ { &hf_ndmp_os_vers, {
+ "OS Version", "ndmp.os.version", FT_STRING, BASE_NONE,
+ NULL, 0, "OS Version", HFILL }},
+
+ { &hf_ndmp_addr_types, {
+ "Addr Types", "ndmp.addr_types", FT_NONE, BASE_NONE,
+ NULL, 0, "List Of Address Types", HFILL }},
+
+ { &hf_ndmp_addr_type, {
+ "Addr Type", "ndmp.addr_type", FT_UINT32, BASE_DEC,
+ VALS(addr_type_vals), 0, "Address Type", HFILL }},
+
+ { &hf_ndmp_auth_type, {
+ "Auth Type", "ndmp.auth_type", FT_UINT32, BASE_DEC,
+ VALS(auth_type_vals), 0, "Authentication Type", HFILL }},
+
+ { &hf_ndmp_auth_challenge, {
+ "Challenge", "ndmp.auth.challenge", FT_BYTES, BASE_HEX,
+ NULL, 0, "Authentication Challenge", HFILL }},
+
+ { &hf_ndmp_auth_digest, {
+ "Digest", "ndmp.auth.digest", FT_BYTES, BASE_HEX,
+ NULL, 0, "Authentication Digest", HFILL }},
+
+ { &hf_ndmp_butype_info, {
+ "Butype Info", "ndmp.butype.info", FT_NONE, BASE_NONE,
+ NULL, 0, "Butype Info", HFILL }},
+
+ { &hf_ndmp_butype_name, {
+ "Butype Name", "ndmp.butype.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of Butype", HFILL }},
+
+ { &hf_ndmp_butype_default_env, {
+ "Default Env", "ndmp.butype.default_env", FT_NONE, BASE_NONE,
+ NULL, 0, "Default Env's for this Butype Info", HFILL }},
+
+ { &hf_ndmp_butype_attr_backup_file_history, {
+ "", "ndmp.butype.attr.backup_file_history", FT_BOOLEAN, 32,
+ TFS(&tfs_butype_attr_backup_file_history), 0x00000001, "backup_file_history", HFILL }},
+
+ { &hf_ndmp_butype_attr_backup_filelist, {
+ "", "ndmp.butype.attr.backup_filelist", FT_BOOLEAN, 32,
+ TFS(&tfs_butype_attr_backup_filelist), 0x00000002, "backup_filelist", HFILL }},
+
+ { &hf_ndmp_butype_attr_recover_filelist, {
+ "", "ndmp.butype.attr.recover_filelist", FT_BOOLEAN, 32,
+ TFS(&tfs_butype_attr_recover_filelist), 0x00000004, "recover_filelist", HFILL }},
+
+ { &hf_ndmp_butype_attr_backup_direct, {
+ "", "ndmp.butype.attr.backup_direct", FT_BOOLEAN, 32,
+ TFS(&tfs_butype_attr_backup_direct), 0x00000008, "backup_direct", HFILL }},
+
+ { &hf_ndmp_butype_attr_recover_direct, {
+ "", "ndmp.butype.attr.recover_direct", FT_BOOLEAN, 32,
+ TFS(&tfs_butype_attr_recover_direct), 0x00000010, "recover_direct", HFILL }},
+
+ { &hf_ndmp_butype_attr_backup_incremental, {
+ "", "ndmp.butype.attr.backup_incremental", FT_BOOLEAN, 32,
+ TFS(&tfs_butype_attr_backup_incremental), 0x00000020, "backup_incremental", HFILL }},
+
+ { &hf_ndmp_butype_attr_recover_incremental, {
+ "", "ndmp.butype.attr.recover_incremental", FT_BOOLEAN, 32,
+ TFS(&tfs_butype_attr_recover_incremental), 0x00000040, "recover_incremental", HFILL }},
+
+ { &hf_ndmp_butype_attr_backup_utf8, {
+ "", "ndmp.butype.attr.backup_utf8", FT_BOOLEAN, 32,
+ TFS(&tfs_butype_attr_backup_utf8), 0x00000080, "backup_utf8", HFILL }},
+
+ { &hf_ndmp_butype_attr_recover_utf8, {
+ "", "ndmp.butype.attr.recover_utf8", FT_BOOLEAN, 32,
+ TFS(&tfs_butype_attr_recover_utf8), 0x00000100, "recover_utf8", HFILL }},
+
+ { &hf_ndmp_butype_env_name, {
+ "Name", "ndmp.butype.env.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name for this env-variable", HFILL }},
+
+ { &hf_ndmp_butype_env_value, {
+ "Value", "ndmp.butype.env.value", FT_STRING, BASE_NONE,
+ NULL, 0, "Value for this env-variable", HFILL }},
+
+ { &hf_ndmp_fs_info, {
+ "FS Info", "ndmp.fs.info", FT_NONE, BASE_NONE,
+ NULL, 0, "FS Info", HFILL }},
+
+ { &hf_ndmp_fs_invalid_total_size, {
+ "", "ndmp.fs.invalid.total_size", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_invalid_total_size), 0x00000001, "If total size is invalid", HFILL }},
+
+ { &hf_ndmp_fs_invalid_used_size, {
+ "", "ndmp.fs.invalid.used_size", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_invalid_used_size), 0x00000002, "If used size is invalid", HFILL }},
+
+ { &hf_ndmp_fs_invalid_avail_size, {
+ "", "ndmp.fs.invalid.avail_size", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_invalid_avail_size), 0x00000004, "If available size is invalid", HFILL }},
+
+ { &hf_ndmp_fs_invalid_total_inodes, {
+ "", "ndmp.fs.invalid.total_inodes", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_invalid_total_inodes), 0x00000008, "If total number of inodes is invalid", HFILL }},
+
+ { &hf_ndmp_fs_invalid_used_inodes, {
+ "", "ndmp.fs.invalid.used_inodes", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_invalid_used_inodes), 0x00000010, "If used number of inodes is invalid", HFILL }},
+
+ { &hf_ndmp_fs_fs_type, {
+ "Type", "ndmp.fs.type", FT_STRING, BASE_NONE,
+ NULL, 0, "Type of FS", HFILL }},
+
+ { &hf_ndmp_fs_logical_device, {
+ "Logical Device", "ndmp.fs.logical_device", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of logical device", HFILL }},
+
+ { &hf_ndmp_fs_physical_device, {
+ "Physical Device", "ndmp.fs.physical_device", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of physical device", HFILL }},
+
+ { &hf_ndmp_fs_total_size, {
+ "Total Size", "ndmp.fs.total_size", FT_UINT64, BASE_DEC,
+ NULL, 0, "Total size of FS", HFILL }},
+
+ { &hf_ndmp_fs_used_size, {
+ "Used Size", "ndmp.fs.used_size", FT_UINT64, BASE_DEC,
+ NULL, 0, "Total used size of FS", HFILL }},
+
+ { &hf_ndmp_fs_avail_size, {
+ "Avail Size", "ndmp.fs.avail_size", FT_UINT64, BASE_DEC,
+ NULL, 0, "Total available size on FS", HFILL }},
+
+ { &hf_ndmp_fs_total_inodes, {
+ "Total Inodes", "ndmp.fs.total_inodes", FT_UINT64, BASE_DEC,
+ NULL, 0, "Total number of inodes on FS", HFILL }},
+
+ { &hf_ndmp_fs_used_inodes, {
+ "Used Inodes", "ndmp.fs.used_inodes", FT_UINT64, BASE_DEC,
+ NULL, 0, "Number of used inodes on FS", HFILL }},
+
+ { &hf_ndmp_fs_env, {
+ "Env variables", "ndmp.fs.env", FT_NONE, BASE_NONE,
+ NULL, 0, "Environment variables for FS", HFILL }},
+
+ { &hf_ndmp_fs_env_name, {
+ "Name", "ndmp.fs.env.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name for this env-variable", HFILL }},
+
+ { &hf_ndmp_fs_env_value, {
+ "Value", "ndmp.fs.env.value", FT_STRING, BASE_NONE,
+ NULL, 0, "Value for this env-variable", HFILL }},
+
+ { &hf_ndmp_fs_status, {
+ "Status", "ndmp.fs.status", FT_STRING, BASE_NONE,
+ NULL, 0, "Status for this FS", HFILL }},
+
+ { &hf_ndmp_tape_info, {
+ "Tape Info", "ndmp.tape.info", FT_NONE, BASE_NONE,
+ NULL, 0, "Tape Info", HFILL }},
+
+ { &hf_ndmp_tape_model, {
+ "Model", "ndmp.tape.model", FT_STRING, BASE_NONE,
+ NULL, 0, "Model of the TAPE drive", HFILL }},
+
+ { &hf_ndmp_tape_dev_cap, {
+ "Device Capability", "ndmp.tape.dev_cap", FT_NONE, BASE_NONE,
+ NULL, 0, "Tape Device Capability", HFILL }},
+
+ { &hf_ndmp_tape_device, {
+ "Device", "ndmp.tape.device", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of TAPE Device", HFILL }},
+
+ { &hf_ndmp_tape_attr_rewind, {
+ "", "ndmp.tape.attr.rewind", FT_BOOLEAN, 32,
+ TFS(&tfs_tape_attr_rewind), 0x00000001, "If this device supports rewind", HFILL }},
+
+ { &hf_ndmp_tape_attr_unload, {
+ "", "ndmp.tape.attr.unload", FT_BOOLEAN, 32,
+ TFS(&tfs_tape_attr_unload), 0x00000002, "If this device supports unload", HFILL }},
+
+ { &hf_ndmp_tape_capability, {
+ "Tape Capabilities", "ndmp.tape.capability", FT_NONE, BASE_NONE,
+ NULL, 0, "Tape Capabilities", HFILL }},
+
+ { &hf_ndmp_tape_capability_name, {
+ "Name", "ndmp.tape.cap.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name for this env-variable", HFILL }},
+
+ { &hf_ndmp_tape_capability_value, {
+ "Value", "ndmp.tape.cap.value", FT_STRING, BASE_NONE,
+ NULL, 0, "Value for this env-variable", HFILL }},
+
+ { &hf_ndmp_scsi_info, {
+ "SCSI Info", "ndmp.scsi.info", FT_NONE, BASE_NONE,
+ NULL, 0, "SCSI Info", HFILL }},
+
+ { &hf_ndmp_scsi_model, {
+ "Model", "ndmp.scsi.model", FT_STRING, BASE_NONE,
+ NULL, 0, "Model of the SCSI device", HFILL }},
+
+ { &hf_ndmp_server_vendor, {
+ "Vendor", "ndmp.server.vendor", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of vendor", HFILL }},
+
+ { &hf_ndmp_server_product, {
+ "Product", "ndmp.server.product", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of product", HFILL }},
+
+ { &hf_ndmp_server_revision, {
+ "Revision", "ndmp.server.revision", FT_STRING, BASE_NONE,
+ NULL, 0, "Revision of this product", HFILL }},
+
+ { &hf_ndmp_auth_types, {
+ "Auth types", "ndmp.auth.types", FT_NONE, BASE_NONE,
+ NULL, 0, "Auth types", HFILL }},
+
+ { &hf_ndmp_scsi_device, {
+ "Device", "ndmp.scsi.device", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of SCSI Device", HFILL }},
+
+ { &hf_ndmp_scsi_controller, {
+ "Controller", "ndmp.scsi.controller", FT_UINT32, BASE_DEC,
+ NULL, 0, "Target Controller", HFILL }},
+
+ { &hf_ndmp_scsi_id, {
+ "ID", "ndmp.scsi.id", FT_UINT32, BASE_DEC,
+ NULL, 0, "Target ID", HFILL }},
+
+ { &hf_ndmp_scsi_lun, {
+ "LUN", "ndmp.scsi.lun", FT_UINT32, BASE_DEC,
+ NULL, 0, "Target LUN", HFILL }},
+
+ { &hf_ndmp_execute_cdb_flags_data_in, {
+ "DATA_IN", "ndmp.execute_cdb.flags.data_in", FT_BOOLEAN, 32,
+ NULL, 0x00000001, "DATA_IN", HFILL }},
+
+ { &hf_ndmp_execute_cdb_flags_data_out, {
+ "DATA_OUT", "ndmp.execute_cdb.flags.data_out", FT_BOOLEAN, 32,
+ NULL, 0x00000002, "DATA_OUT", HFILL }},
+
+ { &hf_ndmp_execute_cdb_timeout, {
+ "Timeout", "ndmp.execute_cdb.timeout", FT_UINT32, BASE_DEC,
+ NULL, 0, "Reselect timeout, in milliseconds", HFILL }},
+
+ { &hf_ndmp_execute_cdb_datain_len, {
+ "Data in length", "ndmp.execute_cdb.datain_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Expected length of data bytes to read", HFILL }},
+
+ { &hf_ndmp_execute_cdb_cdb_len, {
+ "CDB length", "ndmp.execute_cdb.cdb_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of CDB", HFILL }},
+
+ { &hf_ndmp_execute_cdb_dataout, {
+ "Data out", "ndmp.execute_cdb.dataout", FT_BYTES, BASE_NONE,
+ NULL, 0, "Data to be transferred to the SCSI device", HFILL }},
+
+ { &hf_ndmp_execute_cdb_status, {
+ "Status", "ndmp.execute_cdb.status", FT_UINT8, BASE_DEC,
+ VALS(scsi_status_val), 0, "SCSI status", HFILL }},
+
+ { &hf_ndmp_execute_cdb_dataout_len, {
+ "Data out length", "ndmp.execute_cdb.dataout_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of bytes transferred to the device", HFILL }},
+
+ { &hf_ndmp_execute_cdb_datain, {
+ "Data in", "ndmp.execute_cdb.datain", FT_BYTES, BASE_NONE,
+ NULL, 0, "Data transferred from the SCSI device", HFILL }},
+
+ { &hf_ndmp_execute_cdb_sns_len, {
+ "Sense data length", "ndmp.execute_cdb.sns_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of sense data", HFILL }},
+
+ { &hf_ndmp_tape_open_mode, {
+ "Mode", "ndmp.tape.open_mode", FT_UINT32, BASE_DEC,
+ VALS(tape_open_mode_vals), 0, "Mode to open tape in", HFILL }},
+
+ { &hf_ndmp_tape_invalid_file_num, {
+ "", "ndmp.tape.invalid.file_num", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_invalid_file_num), 0x00000001, "invalid_file_num", HFILL }},
+
+ { &hf_ndmp_tape_invalid_soft_errors, {
+ "", "ndmp.tape.invalid.soft_errors", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_invalid_soft_errors), 0x00000002, "soft_errors", HFILL }},
+
+ { &hf_ndmp_tape_invalid_block_size, {
+ "", "ndmp.tape.invalid.block_size", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_invalid_block_size), 0x00000004, "block_size", HFILL }},
+
+ { &hf_ndmp_tape_invalid_block_no, {
+ "", "ndmp.tape.invalid.block_no", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_invalid_block_no), 0x00000008, "block_no", HFILL }},
+
+ { &hf_ndmp_tape_invalid_total_space, {
+ "", "ndmp.tape.invalid.total_space", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_invalid_total_space), 0x00000010, "total_space", HFILL }},
+
+ { &hf_ndmp_tape_invalid_space_remain, {
+ "", "ndmp.tape.invalid.space_remain", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_invalid_space_remain), 0x00000020, "space_remain", HFILL }},
+
+ { &hf_ndmp_tape_invalid_partition, {
+ "", "ndmp.tape.invalid.partition", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_invalid_partition), 0x00000040, "partition", HFILL }},
+
+ { &hf_ndmp_tape_flags_no_rewind, {
+ "", "ndmp.tape.flags.no_rewind", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_flags_no_rewind), 0x00000008, "no_rewind", HFILL, }},
+
+ { &hf_ndmp_tape_flags_write_protect, {
+ "", "ndmp.tape.flags.write_protect", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_flags_write_protect), 0x00000010, "write_protect", HFILL, }},
+
+ { &hf_ndmp_tape_flags_error, {
+ "", "ndmp.tape.flags.error", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_flags_error), 0x00000020, "error", HFILL, }},
+
+ { &hf_ndmp_tape_flags_unload, {
+ "", "ndmp.tape.flags.unload", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_tape_flags_unload), 0x00000040, "unload", HFILL, }},
+
+ { &hf_ndmp_tape_file_num, {
+ "file_num", "ndmp.tape.status.file_num", FT_UINT32, BASE_DEC,
+ NULL, 0, "file_num", HFILL }},
+
+ { &hf_ndmp_tape_soft_errors, {
+ "soft_errors", "ndmp.tape.status.soft_errors", FT_UINT32, BASE_DEC,
+ NULL, 0, "soft_errors", HFILL }},
+
+ { &hf_ndmp_tape_block_size, {
+ "block_size", "ndmp.tape.status.block_size", FT_UINT32, BASE_DEC,
+ NULL, 0, "block_size", HFILL }},
+
+ { &hf_ndmp_tape_block_no, {
+ "block_no", "ndmp.tape.status.block_no", FT_UINT32, BASE_DEC,
+ NULL, 0, "block_no", HFILL }},
+
+ { &hf_ndmp_tape_total_space, {
+ "total_space", "ndmp.tape.status.total_space", FT_UINT64, BASE_DEC,
+ NULL, 0, "total_space", HFILL }},
+
+ { &hf_ndmp_tape_space_remain, {
+ "space_remain", "ndmp.tape.status.space_remain", FT_UINT64, BASE_DEC,
+ NULL, 0, "space_remain", HFILL }},
+
+ { &hf_ndmp_tape_partition, {
+ "partition", "ndmp.tape.status.partition", FT_UINT32, BASE_DEC,
+ NULL, 0, "partition", HFILL }},
+
+ { &hf_ndmp_tape_mtio_op, {
+ "Operation", "ndmp.tape.mtio.op", FT_UINT32, BASE_DEC,
+ VALS(tape_mtio_vals), 0, "MTIO Operation", HFILL }},
+
+ { &hf_ndmp_count, {
+ "Count", "ndmp.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of bytes/objects/operations", HFILL }},
+
+ { &hf_ndmp_resid_count, {
+ "Resid Count", "ndmp.resid_count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of remaining bytes/objects/operations", HFILL }},
+
+ { &hf_ndmp_mover_state, {
+ "State", "ndmp.mover.state", FT_UINT32, BASE_DEC,
+ VALS(mover_state_vals), 0, "State of the selected mover", HFILL }},
+
+ { &hf_ndmp_mover_pause, {
+ "Pause", "ndmp.mover.pause", FT_UINT32, BASE_DEC,
+ VALS(mover_pause_vals), 0, "Reason why the mover paused", HFILL }},
+
+ { &hf_ndmp_halt, {
+ "Halt", "ndmp.halt", FT_UINT32, BASE_DEC,
+ VALS(halt_vals), 0, "Reason why it halted", HFILL }},
+
+ { &hf_ndmp_record_size, {
+ "Record Size", "ndmp.record.size", FT_UINT32, BASE_DEC,
+ NULL, 0, "Record size in bytes", HFILL }},
+
+ { &hf_ndmp_record_num, {
+ "Record Num", "ndmp.record.num", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of records", HFILL }},
+
+ { &hf_ndmp_data_written, {
+ "Data Written", "ndmp.data.written", FT_UINT64, BASE_DEC,
+ NULL, 0, "Number of data bytes written", HFILL }},
+
+ { &hf_ndmp_seek_position, {
+ "Seek Position", "ndmp.seek.position", FT_UINT64, BASE_DEC,
+ NULL, 0, "Current seek position on device", HFILL }},
+
+ { &hf_ndmp_bytes_left_to_read, {
+ "Bytes left to read", "ndmp.bytes_left_to_read", FT_UINT64, BASE_DEC,
+ NULL, 0, "Number of bytes left to be read from the device", HFILL }},
+
+ { &hf_ndmp_window_offset, {
+ "Window Offset", "ndmp.window.offset", FT_UINT64, BASE_DEC,
+ NULL, 0, "Offset to window in bytes", HFILL }},
+
+ { &hf_ndmp_window_length, {
+ "Window Length", "ndmp.window.length", FT_UINT64, BASE_DEC,
+ NULL, 0, "Size of window in bytes", HFILL }},
+
+ { &hf_ndmp_addr_ip, {
+ "IP Address", "ndmp.addr.ip", FT_IPv4, BASE_DEC,
+ NULL, 0, "IP Address", HFILL }},
+
+ { &hf_ndmp_addr_tcp, {
+ "TCP Port", "ndmp.addr.tcp_port", FT_UINT32, BASE_DEC,
+ NULL, 0, "TCP Port", HFILL }},
+
+ { &hf_ndmp_addr_fcal_loop_id, {
+ "Loop ID", "ndmp.addr.loop_id", FT_UINT32, BASE_HEX,
+ NULL, 0, "FCAL Loop ID", HFILL }},
+
+ { &hf_ndmp_addr_ipc, {
+ "IPC", "ndmp.addr.ipc", FT_BYTES, BASE_HEX,
+ NULL, 0, "IPC identifier", HFILL }},
+
+ { &hf_ndmp_mover_mode, {
+ "Mode", "ndmp.mover.mode", FT_UINT32, BASE_HEX,
+ VALS(mover_mode_vals), 0, "Mover Mode", HFILL }},
+
+ { &hf_ndmp_file_name, {
+ "File", "ndmp.file", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of File", HFILL }},
+
+ { &hf_ndmp_nt_file_name, {
+ "NT File", "ndmp.file", FT_STRING, BASE_NONE,
+ NULL, 0, "NT Name of File", HFILL }},
+
+ { &hf_ndmp_dos_file_name, {
+ "DOS File", "ndmp.file", FT_STRING, BASE_NONE,
+ NULL, 0, "DOS Name of File", HFILL }},
+
+ { &hf_ndmp_log_type, {
+ "Type", "ndmp.log.type", FT_UINT32, BASE_HEX,
+ VALS(log_type_vals), 0, "Type of log entry", HFILL }},
+
+ { &hf_ndmp_log_message_id, {
+ "Message ID", "ndmp.log.message.id", FT_UINT32, BASE_DEC,
+ NULL, 0, "ID of this log entry", HFILL }},
+
+ { &hf_ndmp_log_message, {
+ "Message", "ndmp.log.message", FT_STRING, BASE_NONE,
+ NULL, 0, "Log entry", HFILL }},
+
+ { &hf_ndmp_halt_reason, {
+ "Reason", "ndmp.halt.reason", FT_STRING, BASE_NONE,
+ NULL, 0, "Textual reason for why it halted", HFILL }},
+
+ { &hf_ndmp_connected, {
+ "Connected", "ndmp.connected", FT_UINT32, BASE_DEC,
+ VALS(connected_vals), 0, "Status of connection", HFILL }},
+
+ { &hf_ndmp_connected_reason, {
+ "Reason", "ndmp.connected.reason", FT_STRING, BASE_NONE,
+ NULL, 0, "Textual description of the connection status", HFILL }},
+
+ { &hf_ndmp_auth_id, {
+ "ID", "ndmp.auth.id", FT_STRING, BASE_NONE,
+ NULL, 0, "ID of client authenticating", HFILL }},
+
+ { &hf_ndmp_auth_password, {
+ "Password", "ndmp.auth.password", FT_STRING, BASE_NONE,
+ NULL, 0, "Password of client authenticating", HFILL }},
+
+ { &hf_ndmp_data, {
+ "Data", "ndmp.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Data written/read", HFILL }},
+
+ { &hf_ndmp_files, {
+ "Files", "ndmp.files", FT_NONE, 0,
+ NULL, 0, "List of files", HFILL }},
+
+ { &hf_ndmp_file_names, {
+ "File Names", "ndmp.file.names", FT_NONE, 0,
+ NULL, 0, "List of file names", HFILL }},
+
+ { &hf_ndmp_file_fs_type, {
+ "File FS Type", "ndmp.file.fs_type", FT_UINT32, BASE_DEC,
+ VALS(file_fs_type_vals), 0, "Type of file permissions (UNIX or NT)", HFILL }},
+
+ { &hf_ndmp_file_type, {
+ "File Type", "ndmp.file.type", FT_UINT32, BASE_DEC,
+ VALS(file_type_vals), 0, "Type of file", HFILL }},
+
+ { &hf_ndmp_file_stats, {
+ "File Stats", "ndmp.file.stats", FT_NONE, 0,
+ NULL, 0, "List of file stats", HFILL }},
+
+ { &hf_ndmp_file_node, {
+ "Node", "ndmp.file.node", FT_UINT64, BASE_DEC,
+ NULL, 0, "Node used for direct access", HFILL }},
+
+ { &hf_ndmp_file_parent, {
+ "Parent", "ndmp.file.parent", FT_UINT64, BASE_DEC,
+ NULL, 0, "Parent node(directory) for this node", HFILL }},
+
+ { &hf_ndmp_file_fh_info, {
+ "FH Info", "ndmp.file.fh_info", FT_UINT64, BASE_DEC,
+ NULL, 0, "FH Info used for direct access", HFILL }},
+
+ { &hf_ndmp_file_invalid_atime, {
+ "", "ndmp.file.invalid_atime", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_file_invalid_atime), 0x00000001, "invalid_atime", HFILL, }},
+
+ { &hf_ndmp_file_invalid_ctime, {
+ "", "ndmp.file.invalid_ctime", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_file_invalid_ctime), 0x00000002, "invalid_ctime", HFILL, }},
+
+ { &hf_ndmp_file_invalid_group, {
+ "", "ndmp.file.invalid_group", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_file_invalid_group), 0x00000004, "invalid_group", HFILL, }},
+
+ { &hf_ndmp_file_mtime, {
+ "mtime", "ndmp.file.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Timestamp for mtime for this file", HFILL }},
+
+ { &hf_ndmp_file_atime, {
+ "atime", "ndmp.file.atime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Timestamp for atime for this file", HFILL }},
+
+ { &hf_ndmp_file_ctime, {
+ "ctime", "ndmp.file.ctime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Timestamp for ctime for this file", HFILL }},
+
+ { &hf_ndmp_file_owner, {
+ "Owner", "ndmp.file.owner", FT_UINT32, BASE_DEC,
+ NULL, 0, "UID for UNIX, owner for NT", HFILL }},
+
+ { &hf_ndmp_file_group, {
+ "Group", "ndmp.file.group", FT_UINT32, BASE_DEC,
+ NULL, 0, "GID for UNIX, NA for NT", HFILL }},
+
+ { &hf_ndmp_file_fattr, {
+ "Fattr", "ndmp.file.fattr", FT_UINT32, BASE_HEX,
+ NULL, 0, "Mode for UNIX, fattr for NT", HFILL }},
+
+ { &hf_ndmp_file_size, {
+ "Size", "ndmp.file.size", FT_UINT64, BASE_DEC,
+ NULL, 0, "File Size", HFILL }},
+
+ { &hf_ndmp_file_links, {
+ "Links", "ndmp.file.links", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of links to this file", HFILL }},
+
+ { &hf_ndmp_dirs, {
+ "Dirs", "ndmp.dirs", FT_NONE, 0,
+ NULL, 0, "List of directories", HFILL }},
+
+ { &hf_ndmp_nodes, {
+ "Nodes", "ndmp.nodes", FT_NONE, 0,
+ NULL, 0, "List of nodes", HFILL }},
+
+ { &hf_ndmp_nlist, {
+ "Nlist", "ndmp.nlist", FT_NONE, 0,
+ NULL, 0, "List of names", HFILL }},
+
+ { &hf_ndmp_bu_original_path, {
+ "Original Path", "ndmp.bu.original_path", FT_STRING, BASE_NONE,
+ NULL, 0, "Original path where backup was created", HFILL }},
+
+ { &hf_ndmp_bu_destination_dir, {
+ "Destination Dir", "ndmp.bu.destination_dir", FT_STRING, BASE_NONE,
+ NULL, 0, "Destination directory to restore backup to", HFILL }},
+
+ { &hf_ndmp_bu_new_name, {
+ "New Name", "ndmp.bu.new_name", FT_STRING, BASE_NONE,
+ NULL, 0, "New Name", HFILL }},
+
+ { &hf_ndmp_bu_other_name, {
+ "Other Name", "ndmp.bu.other_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Other Name", HFILL }},
+
+ { &hf_ndmp_state_invalid_ebr, {
+ "", "ndmp.bu.state.invalid_ebr", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_state_invalid_ebr), 0x00000001, "Whether EstimatedBytesLeft is valid or not", HFILL, }},
+
+ { &hf_ndmp_state_invalid_etr, {
+ "", "ndmp.bu.state.invalid_etr", FT_BOOLEAN, 32,
+ TFS(&tfs_ndmp_state_invalid_etr), 0x00000002, "Whether EstimatedTimeLeft is valid or not", HFILL, }},
+
+ { &hf_ndmp_bu_operation, {
+ "Operation", "ndmp.bu.operation", FT_UINT32, BASE_DEC,
+ VALS(bu_operation_vals), 0, "BU Operation", HFILL, }},
+
+ { &hf_ndmp_data_state, {
+ "State", "ndmp.data.state", FT_UINT32, BASE_DEC,
+ VALS(data_state_vals), 0, "Data state", HFILL, }},
+
+ { &hf_ndmp_data_halted, {
+ "Halted Reason", "ndmp.data.halted", FT_UINT32, BASE_DEC,
+ VALS(data_halted_vals), 0, "Data halted reason", HFILL, }},
+
+ { &hf_ndmp_data_bytes_processed, {
+ "Bytes Processed", "ndmp.data.bytes_processed", FT_UINT64, BASE_DEC,
+ NULL, 0, "Number of bytes processed", HFILL }},
+
+ { &hf_ndmp_data_est_bytes_remain, {
+ "Est Bytes Remain", "ndmp.data.est_bytes_remain", FT_UINT64, BASE_DEC,
+ NULL, 0, "Estimated number of bytes remaining", HFILL }},
+
+ { &hf_ndmp_data_est_time_remain, {
+ "Est Time Remain", "ndmp.data.est_time_remain", FT_RELATIVE_TIME, BASE_DEC,
+ NULL, 0, "Estimated time remaining", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_ndmp,
+ &ett_ndmp_header,
+ &ett_ndmp_butype_attrs,
+ &ett_ndmp_fs_invalid,
+ &ett_ndmp_tape_attr,
+ &ett_ndmp_execute_cdb_flags,
+ &ett_ndmp_execute_cdb_cdb,
+ &ett_ndmp_execute_cdb_sns,
+ &ett_ndmp_execute_cdb_payload,
+ &ett_ndmp_tape_invalid,
+ &ett_ndmp_tape_flags,
+ &ett_ndmp_addr,
+ &ett_ndmp_file,
+ &ett_ndmp_file_name,
+ &ett_ndmp_file_stats,
+ &ett_ndmp_file_invalids,
+ &ett_ndmp_state_invalids,
+ };
+
+ module_t *ndmp_module;
+
+ proto_ndmp = proto_register_protocol("Network Data Management Protocol", "NDMP", "ndmp");
+ proto_register_field_array(proto_ndmp, hf_ndmp, array_length(hf_ndmp));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* desegmentation */
+ ndmp_module = prefs_register_protocol(proto_ndmp, NULL);
+ prefs_register_enum_preference(ndmp_module,
+ "protocol_version",
+ "Protocol version",
+ "Version of the NDMP protocol",
+ &ndmp_protocol_version,
+ ndmp_protocol_versions,
+ FALSE);
+ prefs_register_bool_preference(ndmp_module, "desegment",
+ "Desegment all NDMP messages spanning multiple TCP segments",
+ "Whether the dissector should desegment NDMP messages",
+ &ndmp_desegment);
+ prefs_register_bool_preference(ndmp_module, "defragment",
+ "Defragment all multi-fragment NDMP messages",
+ "Whether the dissector should defragment multi-fragment NDMP messages",
+ &ndmp_defragment);
+}
+
+void
+proto_reg_handoff_ndmp(void)
+{
+ dissector_handle_t ndmp_handle;
+
+ ndmp_handle = create_dissector_handle(dissect_ndmp, proto_ndmp);
+ dissector_add("tcp.port",TCP_PORT_NDMP, ndmp_handle);
+}
diff --git a/epan/dissectors/packet-ndps.c b/epan/dissectors/packet-ndps.c
new file mode 100644
index 0000000000..17d890e2e2
--- /dev/null
+++ b/epan/dissectors/packet-ndps.c
@@ -0,0 +1,8886 @@
+/* packet-ndps.c
+ * Routines for NetWare's NDPS
+ * Greg Morris <gmorris@novell.com>
+ * Copyright (c) Novell, Inc. 2002-2003
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "packet-ipx.h"
+#include "packet-tcp.h"
+#include <epan/conversation.h>
+#include "packet-ndps.h"
+#include "reassemble.h"
+
+#define NDPS_PACKET_INIT_COUNT 200
+
+/* Tables for reassembly of fragments. */
+static GHashTable *ndps_fragment_table = NULL;
+static GHashTable *ndps_reassembled_table = NULL;
+
+/* desegmentation of ndps */
+static gboolean ndps_defragment = TRUE;
+
+static guint32 tid = 1;
+
+/* Show ID's value */
+static gboolean ndps_show_oids=FALSE;
+
+/* Global Attribute for evaluation of Values */
+static char *global_attribute_name=NULL;
+
+static void dissect_ndps_request(tvbuff_t*, packet_info*, proto_tree*, guint32, guint32, int);
+
+static void dissect_ndps_reply(tvbuff_t *, packet_info*, proto_tree*, int);
+
+static int hf_ndps_segments = -1;
+static int hf_ndps_segment = -1;
+static int hf_ndps_segment_overlap = -1;
+static int hf_ndps_segment_overlap_conflict = -1;
+static int hf_ndps_segment_multiple_tails = -1;
+static int hf_ndps_segment_too_long_segment = -1;
+static int hf_ndps_segment_error = -1;
+
+static gint ett_ndps_segments = -1;
+static gint ett_ndps_segment = -1;
+
+static int proto_ndps = -1;
+static int hf_ndps_record_mark = -1;
+static int hf_ndps_length = -1;
+static int hf_ndps_xid = -1;
+static int hf_ndps_packet_type = -1;
+static int hf_ndps_rpc_version = -1;
+static int hf_ndps_error = -1;
+static int hf_ndps_num_objects = -1;
+static int hf_ndps_num_attributes = -1;
+static int hf_ndps_sbuffer = -1;
+static int hf_ndps_rbuffer = -1;
+static int hf_ndps_user_name = -1;
+static int hf_ndps_broker_name = -1;
+static int hf_ndps_num_results = -1;
+static int hf_ndps_num_options = -1;
+static int hf_ndps_num_jobs = -1;
+static int hf_ndps_pa_name = -1;
+static int hf_ndps_tree = -1;
+static int hf_ndps_reqframe = -1;
+static int hf_ndps_error_val = -1;
+static int hf_ndps_ext_error = -1;
+static int hf_ndps_object = -1;
+static int hf_ndps_cred_type = -1;
+static int hf_ndps_server_name = -1;
+static int hf_ndps_connection = -1;
+static int hf_ndps_auth_null = -1;
+static int hf_ndps_rpc_accept = -1;
+static int hf_ndps_rpc_acc_stat = -1;
+static int hf_ndps_rpc_rej_stat = -1;
+static int hf_ndps_rpc_acc_results = -1;
+static int hf_ndps_problem_type = -1;
+static int hf_security_problem_type = -1;
+static int hf_service_problem_type = -1;
+static int hf_access_problem_type = -1;
+static int hf_printer_problem_type = -1;
+static int hf_selection_problem_type = -1;
+static int hf_doc_access_problem_type = -1;
+static int hf_attribute_problem_type = -1;
+static int hf_update_problem_type = -1;
+static int hf_obj_id_type = -1;
+static int hf_oid_struct_size = -1;
+static int hf_object_name = -1;
+static int hf_ndps_document_number = -1;
+static int hf_ndps_nameorid = -1;
+static int hf_local_object_name = -1;
+static int hf_printer_name = -1;
+static int hf_ndps_qualified_name = -1;
+static int hf_ndps_item_count = -1;
+static int hf_ndps_num_passwords = -1;
+static int hf_ndps_num_servers = -1;
+static int hf_ndps_num_locations = -1;
+static int hf_ndps_num_areas = -1;
+static int hf_ndps_num_address_items = -1;
+static int hf_ndps_num_job_categories = -1;
+static int hf_ndps_num_page_selects = -1;
+static int hf_ndps_num_page_informations = -1;
+static int hf_ndps_num_names = -1;
+static int hf_ndps_num_categories = -1;
+static int hf_ndps_num_colorants = -1;
+static int hf_ndps_num_events = -1;
+static int hf_ndps_num_args = -1;
+static int hf_ndps_num_transfer_methods = -1;
+static int hf_ndps_num_doc_types = -1;
+static int hf_ndps_num_destinations = -1;
+static int hf_ndps_qualifier = -1;
+static int hf_ndps_lib_error = -1;
+static int hf_ndps_other_error = -1;
+static int hf_ndps_other_error_2 = -1;
+static int hf_ndps_session = -1;
+static int hf_ndps_abort_flag = -1;
+static int hf_obj_attribute_type = -1;
+static int hf_ndps_attribute_value = -1;
+static int hf_ndps_lower_range = -1;
+static int hf_ndps_upper_range = -1;
+static int hf_ndps_n64 = -1;
+static int hf_ndps_lower_range_n64 = -1;
+static int hf_ndps_upper_range_n64 = -1;
+static int hf_ndps_attrib_boolean = -1;
+static int hf_ndps_realization = -1;
+static int hf_ndps_xdimension_n64 = -1;
+static int hf_ndps_ydimension_n64 = -1;
+static int hf_ndps_dim_value = -1;
+static int hf_ndps_dim_flag = -1;
+static int hf_ndps_xydim_value = -1;
+static int hf_ndps_location_value = -1;
+static int hf_ndps_xmin_n64 = -1;
+static int hf_ndps_xmax_n64 = -1;
+static int hf_ndps_ymin_n64 = -1;
+static int hf_ndps_ymax_n64 = -1;
+static int hf_ndps_edge_value = -1;
+static int hf_ndps_cardinal_or_oid = -1;
+static int hf_ndps_cardinal_name_or_oid = -1;
+static int hf_ndps_integer_or_oid = -1;
+static int hf_ndps_profile_id = -1;
+static int hf_ndps_persistence = -1;
+static int hf_ndps_language_count = -1;
+static int hf_ndps_language_id = -1;
+static int hf_address_type = -1;
+static int hf_ndps_address = -1;
+static int hf_ndps_add_bytes = -1;
+static int hf_ndps_event_type = -1;
+static int hf_ndps_event_object_identifier = -1;
+static int hf_ndps_octet_string = -1;
+static int hf_ndps_scope = -1;
+static int hf_address_len = -1;
+static int hf_ndps_net = -1;
+static int hf_ndps_node = -1;
+static int hf_ndps_socket = -1;
+static int hf_ndps_port = -1;
+static int hf_ndps_ip = -1;
+static int hf_ndps_server_type = -1;
+static int hf_ndps_num_services = -1;
+static int hf_ndps_service_type = -1;
+static int hf_ndps_service_enabled = -1;
+static int hf_ndps_method_name = -1;
+static int hf_ndps_method_ver = -1;
+static int hf_ndps_file_name = -1;
+static int hf_ndps_admin_submit = -1;
+static int hf_ndps_oid = -1;
+static int hf_ndps_object_op = -1;
+static int hf_answer_time = -1;
+static int hf_oid_asn1_type = -1;
+static int hf_ndps_item_ptr = -1;
+static int hf_ndps_len = -1;
+static int hf_limit_enc = -1;
+static int hf_ndps_delivery_add_count = -1;
+static int hf_ndps_qualified_name2 = -1;
+static int hf_ndps_delivery_add_type = -1;
+static int hf_ndps_criterion_type = -1;
+static int hf_ndps_num_ignored_attributes = -1;
+static int hf_ndps_ignored_type = -1;
+static int hf_ndps_num_resources = -1;
+static int hf_ndps_resource_type = -1;
+static int hf_ndps_identifier_type = -1;
+static int hf_ndps_page_flag = -1;
+static int hf_ndps_media_type = -1;
+static int hf_ndps_doc_content = -1;
+static int hf_ndps_page_size = -1;
+static int hf_ndps_direction = -1;
+static int hf_ndps_page_order = -1;
+static int hf_ndps_medium_size = -1;
+static int hf_ndps_long_edge_feeds = -1;
+static int hf_ndps_inc_across_feed = -1;
+static int hf_ndps_size_inc_in_feed = -1;
+static int hf_ndps_page_orientation = -1;
+static int hf_ndps_numbers_up = -1;
+static int hf_ndps_xdimension = -1;
+static int hf_ndps_ydimension = -1;
+static int hf_ndps_state_severity = -1;
+static int hf_ndps_training = -1;
+static int hf_ndps_colorant_set = -1;
+static int hf_ndps_card_enum_time = -1;
+static int hf_ndps_attrs_arg = -1;
+static int hf_ndps_context_len = -1;
+static int hf_ndps_context = -1;
+static int hf_ndps_filter = -1;
+static int hf_ndps_item_filter = -1;
+static int hf_ndps_substring_match = -1;
+static int hf_ndps_time_limit = -1;
+static int hf_ndps_count_limit = -1;
+static int hf_ndps_operator = -1;
+static int hf_ndps_password = -1;
+static int hf_ndps_retrieve_restrictions = -1;
+static int hf_ndps_bind_security_option_count = -1;
+static int hf_bind_security = -1;
+static int hf_ndps_max_items = -1;
+static int hf_ndps_status_flags = -1;
+static int hf_ndps_resource_list_type = -1;
+static int hf_os_count = -1;
+static int hf_os_type = -1;
+static int hf_ndps_printer_type_count = -1;
+static int hf_ndps_printer_type = -1;
+static int hf_ndps_printer_manuf = -1;
+static int hf_ndps_inf_file_name = -1;
+static int hf_ndps_vendor_dir = -1;
+static int hf_banner_type = -1;
+static int hf_font_type = -1;
+static int hf_printer_id = -1;
+static int hf_ndps_font_name = -1;
+static int hf_ndps_return_code = -1;
+static int hf_ndps_banner_count = -1;
+static int hf_ndps_banner_name = -1;
+static int hf_ndps_font_type_count = -1;
+static int hf_font_type_name = -1;
+static int hf_ndps_font_file_count = -1;
+static int hf_font_file_name = -1;
+static int hf_ndps_printer_def_count = -1;
+static int hf_ndps_prn_file_name = -1;
+static int hf_ndps_prn_dir_name = -1;
+static int hf_ndps_def_file_name = -1;
+static int hf_ndps_num_win31_keys = -1;
+static int hf_ndps_num_win95_keys = -1;
+static int hf_ndps_num_windows_keys = -1;
+static int hf_ndps_windows_key = -1;
+static int hf_archive_type = -1;
+static int hf_archive_file_size = -1;
+static int hf_ndps_data = -1;
+static int hf_get_status_flag = -1;
+static int hf_res_type = -1;
+static int hf_file_timestamp = -1;
+static int hf_sub_complete = -1;
+static int hf_doc_content = -1;
+static int hf_ndps_doc_name = -1;
+static int hf_print_arg = -1;
+static int hf_local_id = -1;
+static int hf_ndps_included_doc_len = -1;
+static int hf_ndps_included_doc = -1;
+static int hf_ndps_ref_name = -1;
+static int hf_interrupt_job_type = -1;
+static int hf_pause_job_type = -1;
+static int hf_ndps_force = -1;
+static int hf_resubmit_op_type = -1;
+static int hf_shutdown_type = -1;
+static int hf_ndps_supplier_flag = -1;
+static int hf_ndps_language_flag = -1;
+static int hf_ndps_method_flag = -1;
+static int hf_ndps_delivery_address_flag = -1;
+static int hf_ndps_list_profiles_type = -1;
+static int hf_ndps_list_profiles_choice_type = -1;
+static int hf_ndps_list_profiles_result_type = -1;
+static int hf_ndps_integer_type_flag = -1;
+static int hf_ndps_integer_type_value = -1;
+static int hf_ndps_continuation_option = -1;
+static int hf_ndps_ds_info_type = -1;
+static int hf_ndps_guid = -1;
+static int hf_ndps_list_services_type = -1;
+static int hf_ndps_item_bytes = -1;
+static int hf_ndps_certified = -1;
+static int hf_ndps_attribute_set = -1;
+static int hf_ndps_data_item_type = -1;
+static int hf_info_int = -1;
+static int hf_info_int16 = -1;
+static int hf_info_int32 = -1;
+static int hf_info_boolean = -1;
+static int hf_info_string = -1;
+static int hf_info_bytes = -1;
+static int hf_ndps_list_local_servers_type = -1;
+static int hf_ndps_registry_name = -1;
+static int hf_ndps_client_server_type = -1;
+static int hf_ndps_session_type = -1;
+static int hf_time = -1;
+static int hf_ndps_supplier_name = -1;
+static int hf_ndps_message = -1;
+static int hf_ndps_delivery_method_count = -1;
+static int hf_delivery_method_type = -1;
+static int hf_ndps_get_session_type = -1;
+static int hf_packet_count = -1;
+static int hf_last_packet_flag = -1;
+static int hf_ndps_get_resman_session_type = -1;
+static int hf_problem_type = -1;
+static int hf_ndps_num_values = -1;
+static int hf_ndps_object_ids_7 = -1;
+static int hf_ndps_object_ids_8 = -1;
+static int hf_ndps_object_ids_9 = -1;
+static int hf_ndps_object_ids_10 = -1;
+static int hf_ndps_object_ids_11 = -1;
+static int hf_ndps_object_ids_12 = -1;
+static int hf_ndps_object_ids_13 = -1;
+static int hf_ndps_object_ids_14 = -1;
+static int hf_ndps_object_ids_15 = -1;
+static int hf_ndps_object_ids_16 = -1;
+static int hf_ndps_attribute_time = -1;
+static int hf_print_security = -1;
+static int hf_notify_time_interval = -1;
+static int hf_notify_sequence_number = -1;
+static int hf_notify_lease_exp_time = -1;
+static int hf_notify_printer_uri = -1;
+static int hf_level = -1;
+static int hf_interval = -1;
+
+static int hf_spx_ndps_program = -1;
+static int hf_spx_ndps_version = -1;
+static int hf_spx_ndps_func_print = -1;
+static int hf_spx_ndps_func_registry = -1;
+static int hf_spx_ndps_func_notify = -1;
+static int hf_spx_ndps_func_resman = -1;
+static int hf_spx_ndps_func_delivery = -1;
+static int hf_spx_ndps_func_broker = -1;
+
+static gint ett_ndps = -1;
+static dissector_handle_t ndps_data_handle;
+
+/* desegmentation of NDPS over TCP */
+static gboolean ndps_desegment = TRUE;
+
+static const value_string true_false[] = {
+ { 0x00000000, "Accept" },
+ { 0x00000001, "Deny" },
+ { 0, NULL }
+};
+
+static const value_string ndps_limit_enc_enum[] = {
+ { 0x00000000, "Time" },
+ { 0x00000001, "Count" },
+ { 0x00000002, "Error" },
+ { 0, NULL }
+};
+
+static const value_string problem_type_enum[] = {
+ { 0x00000000, "Standard" },
+ { 0x00000001, "Extended" },
+ { 0, NULL }
+};
+
+static const value_string accept_stat[] = {
+ { 0x00000000, "Success" },
+ { 0x00000001, "Program Unavailable" },
+ { 0x00000002, "Program Mismatch" },
+ { 0x00000003, "Procedure Unavailable" },
+ { 0x00000004, "Garbage Arguments" },
+ { 0x00000005, "System Error" },
+ { 0, NULL }
+};
+
+static const value_string reject_stat[] = {
+ { 0x00000000, "RPC Mismatch" },
+ { 0x00000001, "Authentication Error" },
+ { 0, NULL }
+};
+
+static const value_string error_type_enum[] = {
+ { 0x00000000, "Security Error" },
+ { 0x00000001, "Service Error" },
+ { 0x00000002, "Access Error" },
+ { 0x00000003, "Printer Error" },
+ { 0x00000004, "Selection Error" },
+ { 0x00000005, "Document Access Error" },
+ { 0x00000006, "Attribute Error" },
+ { 0x00000007, "Update Error" },
+ { 0, NULL }
+};
+
+static const value_string security_problem_enum[] = {
+ { 0x00000000, "Authentication" },
+ { 0x00000001, "Credentials" },
+ { 0x00000002, "Rights" },
+ { 0x00000003, "Invalid PAC" },
+ { 0, NULL }
+};
+
+static const value_string service_problem_enum[] = {
+ { 0x00000000, "Sever Busy" },
+ { 0x00000001, "Server Unavailable" },
+ { 0x00000002, "Complex Operation" },
+ { 0x00000003, "Resource Limit" },
+ { 0x00000004, "Unclassified Server Error" },
+ { 0x00000005, "Too Many Items in List" },
+ { 0x00000006, "Resource not Available" },
+ { 0x00000007, "Cancel Document Support" },
+ { 0x00000008, "Modify Document Support" },
+ { 0x00000009, "Multiple Document Support" },
+ { 0x0000000a, "Parameter Valid Support" },
+ { 0x0000000b, "Invalid Checkpoint" },
+ { 0x0000000c, "Continuation Context" },
+ { 0x0000000d, "Pause Limit Exceeded" },
+ { 0x0000000e, "Unsupported Operation" },
+ { 0x0000000f, "Notify Service Error" },
+ { 0x00000010, "Accounting Service Error" },
+ { 0, NULL }
+};
+
+static const value_string access_problem_enum[] = {
+ { 0x00000000, "Wrong Object Class" },
+ { 0x00000001, "Lack of Access Rights" },
+ { 0x00000002, "Can't Interrupt Job" },
+ { 0x00000003, "Wrong Object State" },
+ { 0x00000004, "Client Not Bound" },
+ { 0x00000005, "Not Available" },
+ { 0x00000006, "Notify Service Not Connected" },
+ { 0x00000007, "PDS Not Connected" },
+ { 0, NULL }
+};
+
+static const value_string printer_problem_enum[] = {
+ { 0x00000000, "Printer Error" },
+ { 0x00000001, "Printer Needs Attention" },
+ { 0x00000002, "Printer Needs Key Operator" },
+ { 0, NULL }
+};
+
+static const value_string selection_problem_enum[] = {
+ { 0x00000000, "Invalid ID" },
+ { 0x00000001, "Unknown ID" },
+ { 0x00000002, "Object Exists" },
+ { 0x00000003, "ID Changed" },
+ { 0, NULL }
+};
+
+static const value_string doc_access_problem_enum[] = {
+ { 0x00000000, "Access Not Available" },
+ { 0x00000001, "Time Expired" },
+ { 0x00000002, "Access Denied" },
+ { 0x00000003, "Unknown Document" },
+ { 0x00000004, "No Documents in Job" },
+ { 0, NULL }
+};
+
+static const value_string attribute_problem_enum[] = {
+ { 0x00000000, "Invalid Syntax" },
+ { 0x00000001, "Undefined Type" },
+ { 0x00000002, "Wrong Matching" },
+ { 0x00000003, "Constraint Violated" },
+ { 0x00000004, "Unsupported Type" },
+ { 0x00000005, "Illegal Modification" },
+ { 0x00000006, "Consists With Other Attribute" },
+ { 0x00000007, "Undefined Attribute Value" },
+ { 0x00000008, "Unsupported Value" },
+ { 0x00000009, "Invalid Noncompulsed Modification" },
+ { 0x0000000a, "Per Job Inadmissible" },
+ { 0x0000000b, "Not Multivalued" },
+ { 0x0000000c, "Mandatory Omitted" },
+ { 0x0000000d, "Illegal For Class" },
+ { 0, NULL }
+};
+
+static const value_string update_problem_enum[] = {
+ { 0x00000000, "No Modifications Allowed" },
+ { 0x00000001, "Insufficient Rights" },
+ { 0x00000002, "Previous Operation Incomplete" },
+ { 0x00000003, "Cancel Not Possible" },
+ { 0, NULL }
+};
+
+static const value_string obj_identification_enum[] = {
+ { 0x00000000, "Printer Contained Object ID" },
+ { 0x00000001, "Document Identifier" },
+ { 0x00000002, "Object Identifier" },
+ { 0x00000003, "Object Name" },
+ { 0x00000004, "Name or Object ID" },
+ { 0x00000005, "Simple Name" },
+ { 0x00000006, "Printer Configuration Object ID" },
+ { 0x00000007, "Qualified Name" },
+ { 0x00000008, "Event Object ID" },
+ { 0, NULL }
+};
+
+static const value_string nameorid_enum[] = {
+ { 0x00000000, "None" },
+ { 0x00000001, "Global" },
+ { 0x00000002, "Local" },
+ { 0, NULL }
+};
+
+static const value_string qualified_name_enum[] = {
+ { 0x00000000, "None" },
+ { 0x00000001, "Simple" },
+ { 0x00000002, "NDS" },
+ { 0, NULL }
+};
+
+static const value_string qualified_name_enum2[] = {
+ { 0x00000000, "NDS" },
+ { 0, NULL }
+};
+
+static const value_string spx_ndps_program_vals[] = {
+ { 0x00060976, "Print Program" },
+ { 0x00060977, "Broker Program" },
+ { 0x00060978, "Registry Program" },
+ { 0x00060979, "Notify Program" },
+ { 0x0006097a, "Resource Manager Program" },
+ { 0x0006097b, "Programmatic Delivery Program" },
+ { 0, NULL }
+};
+
+static const value_string spx_ndps_print_func_vals[] = {
+ { 0x00000000, "None" },
+ { 0x00000001, "Bind PSM" },
+ { 0x00000002, "Bind PA" },
+ { 0x00000003, "Unbind" },
+ { 0x00000004, "Print" },
+ { 0x00000005, "Modify Job" },
+ { 0x00000006, "Cancel Job" },
+ { 0x00000007, "List Object Attributes" },
+ { 0x00000008, "Promote Job" },
+ { 0x00000009, "Interrupt" },
+ { 0x0000000a, "Pause" },
+ { 0x0000000b, "Resume" },
+ { 0x0000000c, "Clean" },
+ { 0x0000000d, "Create" },
+ { 0x0000000e, "Delete" },
+ { 0x0000000f, "Disable PA" },
+ { 0x00000010, "Enable PA" },
+ { 0x00000011, "Resubmit Jobs" },
+ { 0x00000012, "Set" },
+ { 0x00000013, "Shutdown PA" },
+ { 0x00000014, "Startup PA" },
+ { 0x00000015, "Reorder Job" },
+ { 0x00000016, "Pause PA" },
+ { 0x00000017, "Resume PA" },
+ { 0x00000018, "Transfer Data" },
+ { 0x00000019, "Device Control" },
+ { 0x0000001a, "Add Event Profile" },
+ { 0x0000001b, "Remove Event Profile" },
+ { 0x0000001c, "Modify Event Profile" },
+ { 0x0000001d, "List Event Profiles" },
+ { 0x0000001e, "Shutdown PSM" },
+ { 0x0000001f, "Cancel PSM Shutdown" },
+ { 0x00000020, "Set Printer DS Information" },
+ { 0x00000021, "Clean User Jobs" },
+ { 0x00000022, "Map GUID to NDS Name" },
+ { 0x00000023, "Add Event Profile 2" },
+ { 0x00000024, "List Event Profile 2" },
+ { 0, NULL }
+};
+
+static const value_string spx_ndps_notify_func_vals[] = {
+ { 0x00000000, "None" },
+ { 0x00000001, "Notify Bind" },
+ { 0x00000002, "Notify Unbind" },
+ { 0x00000003, "Register Supplier" },
+ { 0x00000004, "Deregister Supplier" },
+ { 0x00000005, "Add Profile" },
+ { 0x00000006, "Remove Profile" },
+ { 0x00000007, "Modify Profile" },
+ { 0x00000008, "List Profiles" },
+ { 0x00000009, "Report Event" },
+ { 0x0000000a, "List Supported Languages" },
+ { 0x0000000b, "Report Notification" },
+ { 0x0000000c, "Add Delivery Method" },
+ { 0x0000000d, "Remove Delivery Method" },
+ { 0x0000000e, "List Delivery Methods" },
+ { 0x0000000f, "Get Delivery Method Information" },
+ { 0x00000010, "Get Notify NDS Object Name" },
+ { 0x00000011, "Get Notify Session Information" },
+ { 0, NULL }
+};
+
+static const value_string spx_ndps_deliver_func_vals[] = {
+ { 0x00000000, "None" },
+ { 0x00000001, "Delivery Bind" },
+ { 0x00000002, "Delivery Unbind" },
+ { 0x00000003, "Delivery Send" },
+ { 0x00000004, "Delivery Send2" },
+ { 0, NULL }
+};
+
+static const value_string spx_ndps_registry_func_vals[] = {
+ { 0x00000000, "None" },
+ { 0x00000001, "Bind" },
+ { 0x00000002, "Unbind" },
+ { 0x00000003, "Register Server" },
+ { 0x00000004, "Deregister Server" },
+ { 0x00000005, "Register Registry" },
+ { 0x00000006, "Deregister Registry" },
+ { 0x00000007, "Registry Update" },
+ { 0x00000008, "List Local Servers" },
+ { 0x00000009, "List Servers" },
+ { 0x0000000a, "List Known Registries" },
+ { 0x0000000b, "Get Registry NDS Object Name" },
+ { 0x0000000c, "Get Registry Session Information" },
+ { 0, NULL }
+};
+
+static const value_string spx_ndps_resman_func_vals[] = {
+ { 0x00000000, "None" },
+ { 0x00000001, "Bind" },
+ { 0x00000002, "Unbind" },
+ { 0x00000003, "Add Resource File" },
+ { 0x00000004, "Delete Resource File" },
+ { 0x00000005, "List Resources" },
+ { 0x00000006, "Get Resource File" },
+ { 0x00000007, "Get Resource File Date" },
+ { 0x00000008, "Get Resource Manager NDS Object Name" },
+ { 0x00000009, "Get Resource Manager Session Information" },
+ { 0x0000000a, "Set Resource Language Context" },
+ { 0, NULL }
+};
+
+static const value_string spx_ndps_broker_func_vals[] = {
+ { 0x00000000, "None" },
+ { 0x00000001, "Bind" },
+ { 0x00000002, "Unbind" },
+ { 0x00000003, "List Services" },
+ { 0x00000004, "Enable Service" },
+ { 0x00000005, "Disable Service" },
+ { 0x00000006, "Down Broker" },
+ { 0x00000007, "Get Broker NDS Object Name" },
+ { 0x00000008, "Get Broker Session Information" },
+ { 0, NULL }
+};
+
+static const value_string ndps_packet_types[] = {
+ { 0x00000000, "Request" },
+ { 0x00000001, "Reply" },
+ { 0, NULL }
+};
+
+static const value_string ndps_realization_enum[] = {
+ { 0x00000000, "Logical" },
+ { 0x00000001, "Physical" },
+ { 0x00000002, "Logical & Physical" },
+ { 0, NULL }
+};
+
+static const value_string ndps_dim_value_enum[] = {
+ { 0x00000000, "Numeric" },
+ { 0x00000001, "Named" },
+ { 0, NULL }
+};
+
+static const value_string ndps_xydim_value_enum[] = {
+ { 0x00000000, "Real" },
+ { 0x00000001, "Named" },
+ { 0x00000002, "Cardinal" },
+ { 0, NULL }
+};
+
+static const value_string ndps_location_value_enum[] = {
+ { 0x00000000, "Numeric" },
+ { 0x00000001, "Named" },
+ { 0, NULL }
+};
+
+static const value_string ndps_edge_value_enum[] = {
+ { 0x00000000, "Bottom" },
+ { 0x00000001, "Right" },
+ { 0x00000002, "Top" },
+ { 0x00000003, "Left" },
+ { 0, NULL }
+};
+
+static const value_string ndps_card_or_oid_enum[] = {
+ { 0x00000000, "Number" },
+ { 0x00000001, "ID" },
+ { 0, NULL }
+};
+
+static const value_string ndps_card_name_or_oid_enum[] = {
+ { 0x00000000, "Number" },
+ { 0x00000001, "ID" },
+ { 0, NULL }
+};
+
+static const value_string ndps_integer_or_oid_enum[] = {
+ { 0x00000000, "ID" },
+ { 0x00000001, "Number" },
+ { 0, NULL }
+};
+
+static const value_string ndps_persistence_enum[] = {
+ { 0x00000000, "Permanent" },
+ { 0x00000001, "Volatile" },
+ { 0, NULL }
+};
+
+static const value_string ndps_address_type_enum[] = {
+ { 0x00000000, "User" },
+ { 0x00000001, "Server" },
+ { 0x00000002, "Volume" },
+ { 0x00000003, "Organization Unit" },
+ { 0x00000004, "Organization" },
+ { 0x00000005, "Group" },
+ { 0x00000006, "Distinguished Name" },
+ { 0x00000007, "User or Container" },
+ { 0x00000008, "Case Exact String" },
+ { 0x00000009, "Case Ignore String" },
+ { 0x0000000a, "Numeric String" },
+ { 0x0000000b, "DOS File Name" },
+ { 0x0000000c, "Phone Number" },
+ { 0x0000000d, "Boolean" },
+ { 0x0000000e, "Integer" },
+ { 0x0000000f, "Network Address" },
+ { 0x00000010, "Choice" },
+ { 0x00000011, "GroupWise User" },
+ { 0, NULL }
+};
+
+static const value_string ndps_address_enum[] = {
+ { 0x00000000, "IPX" },
+ { 0x00000001, "IP" },
+ { 0x00000002, "SDLC" },
+ { 0x00000003, "Token Ring to Ethernet" },
+ { 0x00000004, "OSI" },
+ { 0x00000005, "AppleTalk" },
+ { 0x00000006, "Count" },
+ { 0, NULL }
+};
+
+
+static const value_string ndps_server_type_enum[] = {
+ { 0x00000000, "All" },
+ { 0x00000001, "Public Access Printer Agent" },
+ { 0x00000002, "Notification Server" },
+ { 0x00000003, "Resource Manager" },
+ { 0x00000004, "Network Port Handler" },
+ { 0, NULL }
+};
+
+static const value_string ndps_event_object_enum[] = {
+ { 0x00000000, "Object" },
+ { 0x00000001, "Filter" },
+ { 0x00000002, "Detail" },
+ { 0, NULL }
+};
+
+static const value_string ndps_service_type_enum[] = {
+ { 0x00000000, "SRS" },
+ { 0x00000001, "ENS" },
+ { 0x00000002, "RMS" },
+ { 0, NULL }
+};
+
+static const value_string ndps_delivery_add_enum[] = {
+ { 0x00000000, "MHS Address" },
+ { 0x00000001, "Distinguished Name" },
+ { 0x00000002, "Text" },
+ { 0x00000003, "Octet String" },
+ { 0x00000004, "Distinguished Name String" },
+ { 0x00000005, "RPC Address" },
+ { 0x00000006, "Qualified Name" },
+ { 0, NULL }
+};
+
+static const value_string ndps_resource_enum[] = {
+ { 0x00000000, "Name or ID" },
+ { 0x00000001, "Text" },
+ { 0, NULL }
+};
+
+
+static const value_string ndps_identifier_enum[] = {
+ { 0x00000000, "ID Nominal Number" },
+ { 0x00000001, "ID Alpha-numeric" },
+ { 0x00000002, "ID Tag" },
+ { 0, NULL }
+};
+
+static const value_string ndps_media_enum[] = {
+ { 0x00000000, "Select All Pages" },
+ { 0x00000001, "Selected Pages" },
+ { 0, NULL }
+};
+
+static const value_string ndps_page_size_enum[] = {
+ { 0x00000000, "ID" },
+ { 0x00000001, "Dimensions" },
+ { 0, NULL }
+};
+
+static const value_string ndps_pres_direction_enum[] = {
+ { 0x00000000, "Right to Bottom" },
+ { 0x00000001, "Left to Bottom" },
+ { 0x00000002, "Bidirectional to Bottom" },
+ { 0x00000003, "Right to Top" },
+ { 0x00000004, "Left to Top" },
+ { 0x00000005, "Bidirectional to Top" },
+ { 0x00000006, "Bottom to Right" },
+ { 0x00000007, "Bottom to Left" },
+ { 0x00000008, "Top to Left" },
+ { 0x00000009, "Top to Right" },
+ { 0, NULL }
+};
+
+static const value_string ndps_page_order_enum[] = {
+ { 0x00000000, "Unknown" },
+ { 0x00000001, "First to Last" },
+ { 0x00000002, "Last to First" },
+ { 0, NULL }
+};
+
+static const value_string ndps_medium_size_enum[] = {
+ { 0x00000000, "Discrete" },
+ { 0x00000001, "Continuous" },
+ { 0, NULL }
+};
+
+static const value_string ndps_page_orientation_enum[] = {
+ { 0x00000000, "Unknown" },
+ { 0x00000001, "Face Up" },
+ { 0x00000002, "Face Down" },
+ { 0, NULL }
+};
+
+static const value_string ndps_print_security[] = {
+ { 0x00000001, "Low" },
+ { 0x00000002, "Medium" },
+ { 0x00000003, "High" },
+ { 0, NULL }
+};
+
+static const value_string ndps_numbers_up_enum[] = {
+ { 0x00000000, "Cardinal" },
+ { 0x00000001, "Name or Object ID" },
+ { 0x00000002, "Cardinal Range" },
+ { 0, NULL }
+};
+
+
+static const value_string ndps_state_severity_enum[] = {
+ { 0x00000001, "Other" },
+ { 0x00000002, "Warning" },
+ { 0x00000003, "Critical" },
+ { 0, NULL }
+};
+
+
+static const value_string ndps_training_enum[] = {
+ { 0x00000001, "Other" },
+ { 0x00000002, "Unknown" },
+ { 0x00000003, "Untrained" },
+ { 0x00000004, "Trained" },
+ { 0x00000005, "Field Service" },
+ { 0x00000006, "Management" },
+ { 0, NULL }
+};
+
+static const value_string ndps_colorant_set_enum[] = {
+ { 0x00000000, "Name" },
+ { 0x00000001, "Description" },
+ { 0, NULL }
+};
+
+static const value_string ndps_card_enum_time_enum[] = {
+ { 0x00000000, "Cardinal" },
+ { 0x00000001, "Enumeration" },
+ { 0x00000002, "Time" },
+ { 0, NULL }
+};
+
+static const value_string ndps_attrs_arg_enum[] = {
+ { 0x00000000, "Continuation" },
+ { 0x00000001, "Specification" },
+ { 0, NULL }
+};
+
+
+static const value_string ndps_filter_enum[] = {
+ { 0x00000000, "Item" },
+ { 0x00000001, "And" },
+ { 0x00000002, "Or" },
+ { 0x00000003, "Not" },
+ { 0, NULL }
+};
+
+
+static const value_string ndps_filter_item_enum[] = {
+ { 0x00000000, "Equality" },
+ { 0x00000001, "Substrings" },
+ { 0x00000002, "Greater then or Equal to" },
+ { 0x00000003, "Less then or Equal to" },
+ { 0x00000004, "Present" },
+ { 0x00000005, "Subset of" },
+ { 0x00000006, "Superset of" },
+ { 0x00000007, "Non NULL Set Intersect" },
+ { 0, NULL }
+};
+
+static const value_string ndps_match_criteria_enum[] = {
+ { 0x00000000, "Exact" },
+ { 0x00000001, "Case Insensitive" },
+ { 0x00000002, "Same Letter" },
+ { 0x00000003, "Approximate" },
+ { 0, NULL }
+};
+
+static const value_string ndps_operator_enum[] = {
+ { 0x00000000, "Attributes" },
+ { 0x00000002, "Ordered Jobs" },
+ { 0, NULL }
+};
+
+static const value_string ndps_resource_type_enum[] = {
+ { 0x00000000, "Printer Drivers" },
+ { 0x00000001, "Printer Definitions" },
+ { 0x00000002, "Printer Definitions Short" },
+ { 0x00000003, "Banner Page Files" },
+ { 0x00000004, "Font Types" },
+ { 0x00000005, "Printer Driver Files" },
+ { 0x00000006, "Printer Definition File" },
+ { 0x00000007, "Font Files" },
+ { 0x00000008, "Generic Type" },
+ { 0x00000009, "Generic Files" },
+ { 0x0000000a, "Printer Definition File 2" },
+ { 0x0000000b, "Printer Driver Types 2" },
+ { 0x0000000c, "Printer Driver Files 2" },
+ { 0x0000000d, "Printer Driver Types Archive" },
+ { 0x0000000e, "Languages Available" },
+ { 0, NULL }
+};
+
+static const value_string ndps_os_type_enum[] = {
+ { 0x00000000, "DOS" },
+ { 0x00000001, "Windows 3.1" },
+ { 0x00000002, "Windows 95" },
+ { 0x00000003, "Windows NT" },
+ { 0x00000004, "OS2" },
+ { 0x00000005, "MAC" },
+ { 0x00000006, "UNIX" },
+ { 0x00000007, "Windows NT 4.0" },
+ { 0x00000008, "Windows 2000/XP" },
+ { 0x00000009, "Windows 98" },
+ { 0xffffffff, "None" },
+ { 0, NULL }
+};
+
+static const value_string ndps_banner_type_enum[] = {
+ { 0x00000000, "All" },
+ { 0x00000001, "PCL" },
+ { 0x00000002, "PostScript" },
+ { 0x00000003, "ASCII Text" },
+ { 0, NULL }
+};
+
+static const value_string ndps_font_type_enum[] = {
+ { 0x00000000, "TrueType" },
+ { 0x00000001, "PostScript" },
+ { 0x00000002, "System" },
+ { 0x00000003, "SPD" },
+ { 0x00000004, "True Doc" },
+ { 0, NULL }
+};
+
+static const value_string ndps_archive_enum[] = {
+ { 0x00000000, "ZIP" },
+ { 0x00000001, "JAR" },
+ { 0, NULL }
+};
+
+
+static const value_string ndps_res_type_enum[] = {
+ { 0x00000000, "Printer Driver" },
+ { 0x00000001, "Printer Definition" },
+ { 0x00000002, "Banner Page" },
+ { 0x00000003, "Font" },
+ { 0x00000004, "Generic Resource" },
+ { 0x00000005, "Print Driver Archive" },
+ { 0, NULL }
+};
+
+static const value_string ndps_print_arg_enum[] = {
+ { 0x00000000, "Create Job" },
+ { 0x00000001, "Add Document" },
+ { 0x00000002, "Close Job" },
+ { 0, NULL }
+};
+
+static const value_string ndps_doc_content_enum[] = {
+ { 0x00000000, "Content Included" },
+ { 0x00000001, "Content Referenced" },
+ { 0, NULL }
+};
+
+static const value_string ndps_interrupt_job_enum[] = {
+ { 0x00000000, "Job ID" },
+ { 0x00000001, "Name" },
+ { 0, NULL }
+};
+
+static const value_string ndps_pause_job_enum[] = {
+ { 0x00000000, "Job ID" },
+ { 0x00000001, "Name" },
+ { 0, NULL }
+};
+
+static const value_string ndps_resubmit_op_enum[] = {
+ { 0x00000000, "Copy" },
+ { 0x00000001, "Move" },
+ { 0, NULL }
+};
+
+static const value_string ndps_shutdown_enum[] = {
+ { 0x00000000, "Do Current Jobs" },
+ { 0x00000001, "Immediate" },
+ { 0x00000002, "Do Pending Jobs" },
+ { 0, NULL }
+};
+
+static const value_string ndps_list_profiles_choice_enum[] = {
+ { 0x00000000, "ID" },
+ { 0x00000001, "Filter" },
+ { 0, NULL }
+};
+
+static const value_string ndps_list_profiles_result_enum[] = {
+ { 0x00000000, "Complete" },
+ { 0x00000001, "No Event Objects" },
+ { 0x00000002, "Profile ID's" },
+ { 0, NULL }
+};
+
+static const value_string ndps_ds_info_enum[] = {
+ { 0x00000000, "Add" },
+ { 0x00000001, "Remove" },
+ { 0x00000002, "Update" },
+ { 0, NULL }
+};
+
+static const value_string ndps_list_services_enum[] = {
+ { 0x00000000, "Supported" },
+ { 0x00000001, "Enabled" },
+ { 0, NULL }
+};
+
+static const value_string ndps_data_item_enum[] = {
+ { 0x00000000, "Int8" },
+ { 0x00000001, "Int16" },
+ { 0x00000002, "Int32" },
+ { 0x00000003, "Boolean" },
+ { 0x00000004, "Character String" },
+ { 0x00000005, "Byte String" },
+ { 0, NULL }
+};
+
+static const value_string ndps_list_local_servers_enum[] = {
+ { 0x00000000, "Specification" },
+ { 0x00000001, "Continuation" },
+ { 0, NULL }
+};
+
+static const value_string ndps_delivery_method_enum[] = {
+ { 0x00000000, "Specification" },
+ { 0x00000001, "Continuation" },
+ { 0, NULL }
+};
+
+static const value_string ndps_attribute_enum[] = {
+ { 0x00000000, "Null" },
+ { 0x00000001, "Text" },
+ { 0x00000002, "Descriptive Name" },
+ { 0x00000003, "Descriptor" },
+ { 0x00000004, "Message" },
+ { 0x00000005, "Error Message" },
+ { 0x00000006, "Simple Name" },
+ { 0x00000007, "Distinguished Name String" },
+ { 0x00000008, "Distinguished Name Seq" },
+ { 0x00000009, "Delta Time" },
+ { 0x0000000a, "Time" },
+ { 0x0000000b, "Integer" },
+ { 0x0000000c, "Integer Seq" },
+ { 0x0000000d, "Cardinal" },
+ { 0x0000000e, "Cardinal Seq" },
+ { 0x0000000f, "Positive Integer" },
+ { 0x00000010, "Integer Range" },
+ { 0x00000011, "Cardinal Range" },
+ { 0x00000012, "Maximum Integer" },
+ { 0x00000013, "Minimum Integer" },
+ { 0x00000014, "Integer 64" },
+ { 0x00000015, "Integer 64 Seq" },
+ { 0x00000016, "Cardinal 64" },
+ { 0x00000017, "Cardinal 64 Seq" },
+ { 0x00000018, "Positive Integer 64" },
+ { 0x00000019, "Integer 64 Range" },
+ { 0x0000001a, "Cardinal 64 Range" },
+ { 0x0000001b, "Maximum Integer 64" },
+ { 0x0000001c, "Minimum Integer 64" },
+ { 0x0000001d, "Real" },
+ { 0x0000001e, "Real Seq" },
+ { 0x0000001f, "Non-Negative Real" },
+ { 0x00000020, "Real Range" },
+ { 0x00000021, "Non-Negative Real Range" },
+ { 0x00000022, "Boolean" },
+ { 0x00000023, "Percent" },
+ { 0x00000024, "Object Identifier" },
+ { 0x00000025, "Object Identifier Seq" },
+ { 0x00000026, "Name or OID" },
+ { 0x00000027, "Name or OID Seq" },
+ { 0x00000028, "Distinguished Name" },
+ { 0x00000029, "Relative Distinguished Name Seq" },
+ { 0x0000002a, "Realization" },
+ { 0x0000002b, "Medium Dimensions" },
+ { 0x0000002c, "Dimension" },
+ { 0x0000002d, "XY Dimensions" },
+ { 0x0000002e, "Locations" },
+ { 0x0000002f, "Area" },
+ { 0x00000030, "Area Seq" },
+ { 0x00000031, "Edge" },
+ { 0x00000032, "Font Reference" },
+ { 0x00000033, "Cardinal or OID" },
+ { 0x00000034, "OID Cardinal Map" },
+ { 0x00000035, "Cardinal or Name or OID" },
+ { 0x00000036, "Positive Integer or OID" },
+ { 0x00000037, "Event Handling Profile" },
+ { 0x00000038, "Octet String" },
+ { 0x00000039, "Priority" },
+ { 0x0000003a, "Locale" },
+ { 0x0000003b, "Method Delivery Address" },
+ { 0x0000003c, "Object Identification" },
+ { 0x0000003d, "Results Profile" },
+ { 0x0000003e, "Criteria" },
+ { 0x0000003f, "Job Password" },
+ { 0x00000040, "Job Level" },
+ { 0x00000041, "Job Categories" },
+ { 0x00000042, "Print Checkpoint" },
+ { 0x00000043, "Ignored Attribute" },
+ { 0x00000044, "Resource" },
+ { 0x00000045, "Medium Substitution" },
+ { 0x00000046, "Font Substitution" },
+ { 0x00000047, "Resource Context Seq" },
+ { 0x00000048, "Sides" },
+ { 0x00000049, "Page Select Seq" },
+ { 0x0000004a, "Page Media Select" },
+ { 0x0000004b, "Document Content" },
+ { 0x0000004c, "Page Size" },
+ { 0x0000004d, "Presentation Direction" },
+ { 0x0000004e, "Page Order" },
+ { 0x0000004f, "File Reference" },
+ { 0x00000050, "Medium Source Size" },
+ { 0x00000051, "Input Tray Medium" },
+ { 0x00000052, "Output Bins Chars" },
+ { 0x00000053, "Page ID Type" },
+ { 0x00000054, "Level Range" },
+ { 0x00000055, "Category Set" },
+ { 0x00000056, "Numbers Up Supported" },
+ { 0x00000057, "Finishing" },
+ { 0x00000058, "Print Contained Object ID" },
+ { 0x00000059, "Print Config Object ID" },
+ { 0x0000005a, "Typed Name" },
+ { 0x0000005b, "Network Address" },
+ { 0x0000005c, "XY Dimensions Value" },
+ { 0x0000005d, "Name or OID Dimensions Map" },
+ { 0x0000005e, "Printer State Reason" },
+ { 0x0000005f, "Enumeration" },
+ { 0x00000060, "Qualified Name" },
+ { 0x00000061, "Qualified Name Set" },
+ { 0x00000062, "Colorant Set" },
+ { 0x00000063, "Resource Printer ID" },
+ { 0x00000064, "Event Object ID" },
+ { 0x00000065, "Qualified Name Map" },
+ { 0x00000066, "File Path" },
+ { 0x00000067, "Uniform Resource Identifier" },
+ { 0x00000068, "Cardinal or Enum or Time" },
+ { 0x00000069, "Print Contained Object ID Set" },
+ { 0x0000006a, "Octet String Pair" },
+ { 0x0000006b, "Octet String Integer Pair" },
+ { 0x0000006c, "Extended Resource Identifier" },
+ { 0x0000006d, "Event Handling Profile 2" },
+ { 0, NULL }
+};
+
+static const value_string ndps_error_types[] = {
+ { 0x00000000, "Ok" },
+ { 0x00000001, "Error" },
+ { 0xFFFFFC18, "Broker Out of Memory" }, /* Broker Errors */
+ { 0xFFFFFC17, "Broker Bad NetWare Version" },
+ { 0xFFFFFC16, "Broker Wrong Command Line Arguments" },
+ { 0xFFFFFC15, "Broker Name Not Given" },
+ { 0xFFFFFC14, "Not Broker Class" },
+ { 0xFFFFFC13, "Invalid Broker Password" },
+ { 0xFFFFFC12, "Invalid Broker Name" },
+ { 0xFFFFFC11, "Broker Failed to Create Thread" },
+ { 0xFFFFFC10, "Broker Failed to Initialize NUT" },
+ { 0xFFFFFC0F, "Broker Failed to Get Messages" },
+ { 0xFFFFFC0E, "Broker Failed to Allocate Resources" },
+ { 0xFFFFFC0D, "Broker Service Name Must be Fully Distinguished" },
+ { 0xFFFFFC0C, "Broker Uninitialized Module" },
+ { 0xFFFFFC0B, "Broker DS Value Size Too Large" },
+ { 0xFFFFFC0A, "Broker No Attribute Values" },
+ { 0xFFFFFC09, "Broker Unknown Session" },
+ { 0xFFFFFC08, "Broker Service Disabled" },
+ { 0xFFFFFC07, "Broker Unknown Modify Operation" },
+ { 0xFFFFFC06, "Broker Invalid Arguments" },
+ { 0xFFFFFC05, "Broker Duplicate Session ID" },
+ { 0xFFFFFC04, "Broker Unknown Service" },
+ { 0xFFFFFC03, "Broker Service Already Enabled" },
+ { 0xFFFFFC02, "Broker Service Already Disabled" },
+ { 0xFFFFFC01, "Broker Invalid Credential" },
+ { 0xFFFFFC00, "Broker Unknown Designator" },
+ { 0xFFFFFBFF, "Broker Failed to Make Change Permanent" },
+ { 0xFFFFFBFE, "Broker Not Admin Type Session" },
+ { 0xFFFFFBFD, "Broker Option Not Supported" },
+ { 0xFFFFFBFC, "Broker No Effective Rights" },
+ { 0xFFFFFBFB, "Broker Could Not Find File" },
+ { 0xFFFFFBFA, "Broker Error Reading File" },
+ { 0xFFFFFBF9, "Broker Not NLM File Format" },
+ { 0xFFFFFBF8, "Broker Wrong NLM File Version" },
+ { 0xFFFFFBF7, "Broker Reentrant Initialization Failure" },
+ { 0xFFFFFBF6, "Broker Already in Progress" },
+ { 0xFFFFFBF5, "Broker Initialize Failure" },
+ { 0xFFFFFBF4, "Broker Inconsistent File Format" },
+ { 0xFFFFFBF3, "Broker Can't Load at Startup" },
+ { 0xFFFFFBF2, "Broker Autoload Modules Not Loaded" },
+ { 0xFFFFFBF1, "Broker Unresolved External" },
+ { 0xFFFFFBF0, "Broker Public Already Defined" },
+ { 0xFFFFFBEF, "Broker Other Broker Using Object" },
+ { 0xFFFFFBEE, "Broker Service Failed to Initialize" },
+ { 0xFFFFFBB4, "Registry Out of Memory" }, /* SRS Errors */
+ { 0xFFFFFBB3, "Registry Bad NetWare Version" },
+ { 0xFFFFFBB2, "Registry Failed to Create Context" },
+ { 0xFFFFFBB1, "Registry Failed Login" },
+ { 0xFFFFFBB0, "Registry Failed to Create Thread" },
+ { 0xFFFFFBAF, "Registry Failed to Get Messages" },
+ { 0xFFFFFBAE, "Registry Service Name Must Be Fully Distinguished" },
+ { 0xFFFFFBAD, "Registry DS Value Size Too Large" },
+ { 0xFFFFFBAC, "Registry No Attribute Values" },
+ { 0xFFFFFBAB, "Registry Unknown Session" },
+ { 0xFFFFFBAA, "Registry Service Disabled" },
+ { 0xFFFFFBA9, "Registry Unknown Modify Operation" },
+ { 0xFFFFFBA8, "Registry Can't Start Advertise" },
+ { 0xFFFFFBA7, "Registry Duplicate Server Entry" },
+ { 0xFFFFFBA6, "Registry Can't Bind to Registry" },
+ { 0xFFFFFBA5, "Registry Can't Create Client" },
+ { 0xFFFFFBA4, "Registry Invalid Arguments" },
+ { 0xFFFFFBA3, "Registry Duplicate Session ID" },
+ { 0xFFFFFBA2, "Registry Unknown Server Entry" },
+ { 0xFFFFFBA1, "Registry Invalid Credential" },
+ { 0xFFFFFBA0, "Registry Type Session" },
+ { 0xFFFFFB9F, "Registry Server Type Session" },
+ { 0xFFFFFB9E, "Registry Not Server Type Session" },
+ { 0xFFFFFB9D, "Not Registry Type Session" },
+ { 0xFFFFFB9C, "Registry Unknown Designator" },
+ { 0xFFFFFB9B, "Registry Option Not Supported" },
+ { 0xFFFFFB9A, "Registry Not in List Iteration" },
+ { 0xFFFFFB99, "Registry Invalid Continuation Handle" },
+ { 0xFFFFFB50, "Notify Out of Memory" }, /* Notification Service Errors */
+ { 0xFFFFFB4F, "Notify Bad NetWare Version" },
+ { 0xFFFFFB4E, "Notify Failed to Create Thread" },
+ { 0xFFFFFB4D, "Notify Failed to Get Messages" },
+ { 0xFFFFFB4C, "Notify Failed to Create Context" },
+ { 0xFFFFFB4B, "Notify Failed Login" },
+ { 0xFFFFFB4A, "Notify Service Name Must be Fully Distiguished" },
+ { 0xFFFFFB49, "Notify DS Value Size Too Large" },
+ { 0xFFFFFB48, "Notify No Attribute Values" },
+ { 0xFFFFFB47, "Notify Unknown Session" },
+ { 0xFFFFFB46, "Notify Unknown Notify Profile" },
+ { 0xFFFFFB45, "Notify Error Reading File" },
+ { 0xFFFFFB44, "Notify Error Writing File" },
+ { 0xFFFFFB43, "Wrong Notify Database Version" },
+ { 0xFFFFFB42, "Corrupted Notify Database" },
+ { 0xFFFFFB41, "Notify Unknown Event Object ID" },
+ { 0xFFFFFB40, "Notify Method Already Installed" },
+ { 0xFFFFFB3F, "Notify Unknown Method" },
+ { 0xFFFFFB3E, "Notify Service Disabled" },
+ { 0xFFFFFB3D, "Notify Unknown Modify Operation" },
+ { 0xFFFFFB3C, "Out of Notify Entries" },
+ { 0xFFFFFB3B, "Notify Unknown Language ID" },
+ { 0xFFFFFB3A, "Notify Queue Empty" },
+ { 0xFFFFFB39, "Notify Can't Load Delivery Method" },
+ { 0xFFFFFB38, "Notify Invalid Arguments" },
+ { 0xFFFFFB37, "Notify Duplicate Session ID" },
+ { 0xFFFFFB36, "Notify Invalid Credentials" },
+ { 0xFFFFFB35, "Notify Unknown Choice" },
+ { 0xFFFFFB34, "Notify Unknown Attribute Value" },
+ { 0xFFFFFB33, "Notify Error Writing Database" },
+ { 0xFFFFFB32, "Notify Unknown Object ID" },
+ { 0xFFFFFB31, "Notify Unknown Designator" },
+ { 0xFFFFFB30, "Notify Failed to Make Change Permanent" },
+ { 0xFFFFFB2F, "Notify User Interface Not Supported" },
+ { 0xFFFFFB2E, "Notify Not Supplied Type of Session" },
+ { 0xFFFFFB2D, "Notify Not Admin Type Session" },
+ { 0xFFFFFB2C, "Notify No Service Registry Available" },
+ { 0xFFFFFB2B, "Notify Failed to Register With Any Server" },
+ { 0xFFFFFB2A, "Notify Empty Event Object Set" },
+ { 0xFFFFFB29, "Notify Unknown Notify Handle" },
+ { 0xFFFFFB28, "Notify Option Not Supported" },
+ { 0xFFFFFB27, "Notify Unknown RPC Session" },
+ { 0xFFFFFB26, "Notify Initialization Error" },
+ { 0xFFFFFB25, "Notify No Effective Rights" },
+ { 0xFFFFFB24, "Notify No Persistent Storage" },
+ { 0xFFFFFB23, "Notify Bad Method Filename" },
+ { 0xFFFFFB22, "Notify Unknown Continuation Handle" },
+ { 0xFFFFFB21, "Notify Invalid Continuation Handle" },
+ { 0xFFFFFB20, "Notify Could Not Find File" },
+ { 0xFFFFFB1F, "Notify Error Reading File" },
+ { 0xFFFFFB1E, "Notify Not NLM File Format" },
+ { 0xFFFFFB1D, "Notify Wrong NLM File Version" },
+ { 0xFFFFFB1C, "Notify Reentrant Initialization Failure" },
+ { 0xFFFFFB1B, "Notify Already in Progress" },
+ { 0xFFFFFB1A, "Notify Initialization Failure" },
+ { 0xFFFFFB19, "Notify Inconsistent File Format" },
+ { 0xFFFFFB18, "Notify Can't Load at Startup" },
+ { 0xFFFFFB17, "Notify Autoload Modules Not Loaded" },
+ { 0xFFFFFB16, "Notify Unresolved External" },
+ { 0xFFFFFB15, "Notify Public Already Defined" },
+ { 0xFFFFFB14, "Notify Using Unknown Methods" },
+ { 0xFFFFFB13, "Notify Service Not Fully Enabled" },
+ { 0xFFFFFB12, "Notify Foreign NDS Tree Name" },
+ { 0xFFFFFB11, "Notify Delivery Method Rejected Address" },
+ { 0xFFFFFB10, "Notify Unsupported Delivery Address Type" },
+ { 0xFFFFFB0F, "Notify User Object No Default Server" },
+ { 0xFFFFFB0E, "Notify Failed to Send Notification" },
+ { 0xFFFFFB0D, "Notify Bad Volume in Address" },
+ { 0xFFFFFB0C, "Notify Broker Has No File Rights" },
+ { 0xFFFFFB0B, "Notify Maximum Methods Supported" },
+ { 0xFFFFFB0A, "Notify No Filter Provided" },
+ { 0xFFFFFB09, "Notify IPX Not Supported By Method" },
+ { 0xFFFFFB08, "Notify IP Not Supported By Method" },
+ { 0xFFFFFB07, "Notify Failed to Startup Winsock" },
+ { 0xFFFFFB06, "Notify No Protocols Available" },
+ { 0xFFFFFB05, "Notify Failed to Launch RPC Server" },
+ { 0xFFFFFB04, "Notify Invalid SLP Attribute Format" },
+ { 0xFFFFFB03, "Notify Invalid SLP URL Format" },
+ { 0xFFFFFB02, "Notify Unknown Attribute Object ID" },
+ { 0xFFFFFB01, "Notify Duplicate Session ID" },
+ { 0xFFFFFB00, "Notify Failed to Authenticate" },
+ { 0xFFFFFAFF, "Notify Failed to Authenticate Protocol Mismatch" },
+ { 0xFFFFFAFE, "Notify Failed to Authenticate Internal Error" },
+ { 0xFFFFFAFD, "Notify Failed to Authenticate Connection Error" },
+ { 0xFFFFFC7C, "Resource Manager Out of Memory" }, /* ResMan Errors */
+ { 0xFFFFFC7B, "Resource Manager Bad NetWare Version" },
+ { 0xFFFFFC7A, "Resource Manager Wrong Command Line Arguments" },
+ { 0xFFFFFC79, "Resource Manager Broker Name Not Given" },
+ { 0xFFFFFC78, "Resource Manager Invalid Broker Password" },
+ { 0xFFFFFC77, "Resource Manager Invalid Broker Name" },
+ { 0xFFFFFC76, "Resource Manager Failed to Create Thread" },
+ { 0xFFFFFC75, "Resource Manager Service Name Must be Fully Distinguished" },
+ { 0xFFFFFC74, "Resource Manager DS Value Size Too Large" },
+ { 0xFFFFFC73, "Resource Manager No Attribute Values" },
+ { 0xFFFFFC72, "Resource Manager Unknown Session" },
+ { 0xFFFFFC71, "Resource Manager Error Reading File" },
+ { 0xFFFFFC70, "Resource Manager Error Writing File" },
+ { 0xFFFFFC6F, "Resource Manager Service Disabled" },
+ { 0xFFFFFC6E, "Resource Manager Unknown Modify Operation" },
+ { 0xFFFFFC6D, "Resource Manager Duplicate Session ID" },
+ { 0xFFFFFC6C, "Resource Manager Invalid Credentials" },
+ { 0xFFFFFC6B, "Resource Manager No Service Registry Available" },
+ { 0xFFFFFC6A, "Resource Manager Failed to Register With any Server" },
+ { 0xFFFFFC69, "Resource Manager Failed to Get Messages" },
+ { 0xFFFFFC68, "Resource Manager Failed to Create Context" },
+ { 0xFFFFFC67, "Resource Manager Failed to Login" },
+ { 0xFFFFFC66, "Resource Manager NPD Files Generation Error" },
+ { 0xFFFFFC65, "Resource Manager INF File Format Error" },
+ { 0xFFFFFC64, "Resource Manager No Printer Type in INF File" },
+ { 0xFFFFFC63, "Resource Manager No INF Files Present" },
+ { 0xFFFFFC62, "Resource Manager File Open Error" },
+ { 0xFFFFFC61, "Resource Manager Read File Error" },
+ { 0xFFFFFC60, "Resource Manager Write File Error" },
+ { 0xFFFFFC5F, "Resource Manager Resource Type Invalid" },
+ { 0xFFFFFC5E, "Resource Manager No Such Filename" },
+ { 0xFFFFFC5D, "Resource Manager Banner Type Invalid" },
+ { 0xFFFFFC5C, "Resource Manager List Type Unknown" },
+ { 0xFFFFFC5B, "Resource Manager OS Not Supported" },
+ { 0xFFFFFC5A, "Resource Manager No Banner Files Present" },
+ { 0xFFFFFC59, "Resource Manager Printer Definition Type Unknown" },
+ { 0xFFFFFC58, "Resource Manager No Printer Types in List" },
+ { 0xFFFFFC57, "Resource Manager Option Not Supported" },
+ { 0xFFFFFC56, "Resource Manager Unicode Convention Error" },
+ { 0xFFFFFC55, "Resource Manager Invalid Arguments" },
+ { 0xFFFFFC54, "Resource Manager Initialization Error" },
+ { 0xFFFFFC53, "Resource Manager No Service Registry Available" },
+ { 0xFFFFFC52, "Resource Manager Failed to Register to Any Server" },
+ { 0xFFFFFC51, "Resource Manager Unknown Designator" },
+ { 0xFFFFFC50, "Resource Manager Not Admin Session" },
+ { 0xFFFFFC4F, "Resource Manager No Effective Rights" },
+ { 0xFFFFFC4E, "Resource Manager Bad File Attribute" },
+ { 0xFFFFFC4D, "Resource Manager Document ID Format Error" },
+ { 0xFFFFFC4C, "Resource Manager Unknown RPC Session" },
+ { 0xFFFFFC4B, "Resource Manager Session Being Removed" },
+ { 0xFFFFFC49, "Resource Manager Font Manager IO Error" },
+ { 0xFFFFFC48, "Resource Manager Font Manager Reentrancy" },
+ { 0xFFFFFC47, "Resource Manager Font Manager Sequence Error" },
+ { 0xFFFFFC46, "Resource Manager Font Manager Corrupt Index File" },
+ { 0xFFFFFC45, "Resource Manager Font Manager No Such Font" },
+ { 0xFFFFFC44, "Resource Manager Font Manager Not Initialized" },
+ { 0xFFFFFC43, "Resource Manager Font Manager System Error" },
+ { 0xFFFFFC42, "Resource Manager Font Manager Bad Parameter" },
+ { 0xFFFFFC41, "Resource Manager Font Manager Path Too Long" },
+ { 0xFFFFFC40, "Resource Manager Font Manager Failure" },
+ { 0xFFFFFC3F, "Resource Manager Duplicate TIRPC Session" },
+ { 0xFFFFFC3E, "Resource Manager Connection Lost RMS Data" },
+ { 0xFFFFFC3D, "Resource Manager Failed to Start Winsock" },
+ { 0xFFFFFC3C, "Resource Manager No Protocols Available" },
+ { 0xFFFFFC3B, "Resource Manager Failed to Launch RPC Server" },
+ { 0xFFFFFC3A, "Resource Manager Invalid SLP Attribute Format" },
+ { 0xFFFFFC39, "Resource Manager Invalid SLP URL Format" },
+ { 0xFFFFFC38, "Resource Manager Unresolved External" },
+ { 0xFFFFFC37, "Resource Manager Failed to Authenticate" },
+ { 0xFFFFFC36, "Resource Manager Failed to Authenticate Protocol Mismatch" },
+ { 0xFFFFFC35, "Resource Manager Failed to Authenticate Internal Error" },
+ { 0xFFFFFC34, "Resource Manager Failed to Authenticate Connection Error" },
+ { 0xFFFFFC33, "Resource Manager No Rights to Remote Resdir" },
+ { 0xFFFFFC32, "Resource Manager Can't Initialize NDPS Library" },
+ { 0xFFFFFC31, "Resource Manager Can't Create Resource Reference" },
+ { 0xFFFFFC30, "Resource Manager File is Zero Length" },
+ { 0xFFFFFC2F, "Resource Manager Failed to Write INF in Address" },
+ { 0xFFFFFCDF, "NDPSM No Memory" }, /* NDPSM Errors */
+ { 0xFFFFFCDE, "NDPSM Memory Not Found" },
+ { 0xFFFFFCDD, "NDPSM Job Storage Limit" },
+ { 0xFFFFFCDC, "NDPSM Job Retention Limit" },
+ { 0xFFFFFCDB, "NDPSM Unsupported Type" },
+ { 0xFFFFFCDA, "NDPSM Undefined Type" },
+ { 0xFFFFFCD9, "NDPSM Unsupported Operation" },
+ { 0xFFFFFCD8, "NDPSM Error Accessing Database" },
+ { 0xFFFFFCD7, "NDPSM No PDS" },
+ { 0xFFFFFCD6, "NDPSM Invalid Class" },
+ { 0xFFFFFCD5, "NDPSM Bad Parameter" },
+ { 0xFFFFFCD4, "NDPSM Object Not Found" },
+ { 0xFFFFFCD3, "NDPSM Attribute Not Found" },
+ { 0xFFFFFCD2, "NDPSM Value Not Found" },
+ { 0xFFFFFCD1, "NDPSM Values Not Comparable" },
+ { 0xFFFFFCD0, "NDPSM Invalid Value Syntax" },
+ { 0xFFFFFCCF, "NDPSM Job Not Found" },
+ { 0xFFFFFCCE, "NDPSM Communications Error" },
+ { 0xFFFFFCCD, "NDPSM Printer Agent Initializing" },
+ { 0xFFFFFCCC, "NDPSM Printer Agent Going Down" },
+ { 0xFFFFFCCB, "NDPSM Printer Agent Disabled" },
+ { 0xFFFFFCCA, "NDPSM Printer Agent Paused" },
+ { 0xFFFFFCC9, "NDPSM Bad Printer Agent Handle" },
+ { 0xFFFFFCC8, "NDPSM Object Not Locked" },
+ { 0xFFFFFCC7, "NDPSM Version Incompatible" },
+ { 0xFFFFFCC6, "NDPSM PSM Initializing" },
+ { 0xFFFFFCC5, "NDPSM PSM Going Down" },
+ { 0xFFFFFCC4, "NDPSM Notification Service Error" },
+ { 0xFFFFFCC3, "NDPSM Medium Needs Mounted" },
+ { 0xFFFFFCC2, "NDPSM PDS Not Responding" },
+ { 0xFFFFFCC1, "NDPSM Session Not Found" },
+ { 0xFFFFFCC0, "NDPSM RPC Failure" },
+ { 0xFFFFFCBF, "NDPSM Duplicate Value" },
+ { 0xFFFFFCBE, "NDPSM PDS Refuses Rename" },
+ { 0xFFFFFCBD, "NDPSM No Mandatory Attribute" },
+ { 0xFFFFFCBC, "NDPSM Already Attached" },
+ { 0xFFFFFCBB, "NDPSM Can't Attach" },
+ { 0xFFFFFCBA, "NDPSM Too Many NetWare Servers" },
+ { 0xFFFFFCB9, "NDPSM Can't Create Document File" },
+ { 0xFFFFFCB8, "NDPSM Can't Delete Document File" },
+ { 0xFFFFFCB7, "NDPSM Can't Open Document File" },
+ { 0xFFFFFCB6, "NDPSM Can't Write Document File" },
+ { 0xFFFFFCB5, "NDPSM Job is Active" },
+ { 0xFFFFFCB4, "NDPSM No Scheduler" },
+ { 0xFFFFFCB3, "NDPSM Changing Connection" },
+ { 0xFFFFFCB2, "NDPSM Could not Create Account Reference" },
+ { 0xFFFFFCB1, "NDPSM Accounting Service Error" },
+ { 0xFFFFFCB0, "NDPSM RMS Service Error" },
+ { 0xFFFFFCAF, "NDPSM Failed Validation" },
+ { 0xFFFFFCAE, "NDPSM Broker Server Connecting" },
+ { 0xFFFFFCAD, "NDPSM SRS Service Error" },
+ { 0xFFFFFD44, "JPM Execute Request Later" },
+ { 0xFFFFFD43, "JPM Failed to Open Document" },
+ { 0xFFFFFD42, "JPM Failed to Read Document File" },
+ { 0xFFFFFD41, "JPM Bad Printer Agent Handle" },
+ { 0xFFFFFD40, "JPM Bad Job Handle" },
+ { 0xFFFFFD3F, "JPM Bad Document Handle" },
+ { 0xFFFFFD3E, "JPM Unsupported Operation" },
+ { 0xFFFFFD3D, "JPM Request Queue Full" },
+ { 0xFFFFFD3C, "JPM Printer Agent Not Found" },
+ { 0xFFFFFD3B, "JPM Invalid Request" },
+ { 0xFFFFFD3A, "JPM Not Accepting Requests" },
+ { 0xFFFFFD39, "JPM Printer Agent Already Serviced By PDS" },
+ { 0xFFFFFD38, "JPM No Job" },
+ { 0xFFFFFD37, "JPM Job Not Found" },
+ { 0xFFFFFD36, "JPM Could not Access Database" },
+ { 0xFFFFFD35, "JPM Bad Object Type" },
+ { 0xFFFFFD34, "JPM Job Already Closed" },
+ { 0xFFFFFD33, "JPM Document Already Closed" },
+ { 0xFFFFFD32, "JPM Print Handler Not Registered" },
+ { 0xFFFFFD31, "JPM Version Incompatible" },
+ { 0xFFFFFD30, "JPM Printer Agent Paused" },
+ { 0xFFFFFD2F, "JPM Printer Agent Shutdown" },
+ { 0xFFFFFD2E, "JPM No CLIB Context" },
+ { 0xFFFFFD2D, "JPM Accounting Already Serviced" },
+ { 0xFFFFFC7B, "Database Can't Create File" },
+ { 0xFFFFFC7A, "Database Can't Find Data File" },
+ { 0xFFFFFC79, "Database Can't Open Data File" },
+ { 0xFFFFFC78, "Database Can't Open Index File" },
+ { 0xFFFFFC77, "Database Index File Not Open" },
+ { 0xFFFFFC76, "Database Can't Rename File" },
+ { 0xFFFFFC75, "Database Can't Read Data File" },
+ { 0xFFFFFC74, "Database Can't Read Index File" },
+ { 0xFFFFFC73, "Database Can't Write Data File" },
+ { 0xFFFFFC72, "Database Can't Write Index File" },
+ { 0xFFFFFC71, "Database Can't Delete Printer Agent Directory" },
+ { 0xFFFFFC70, "Database Already Deleted" },
+ { 0xFFFFFC6F, "Database Object Exists" },
+ { 0xFFFFFC6E, "Database Descriptor In Use" },
+ { 0xFFFFFC6D, "Database Descriptor Being Deleted" },
+ { 0, NULL }
+};
+
+static const value_string ndps_credential_enum[] = {
+ { 0, "SIMPLE" },
+ { 1, "CERTIFIED" },
+ { 2, "NDPS 0" },
+ { 3, "NDPS 1" },
+ { 4, "NDPS 2" },
+ { 0, NULL }
+};
+
+static const value_string ndps_object_op_enum[] = {
+ { 0, "None" },
+ { 1, "Add" },
+ { 2, "Delete" },
+ { 3, "Delete Object" },
+ { 0, NULL }
+};
+
+static const value_string ndps_client_server_enum[] = {
+ { 0, "Client" },
+ { 1, "Server" },
+ { 2, "Client and Server" },
+ { 0, NULL }
+};
+
+static const value_string ndps_session_type_enum[] = {
+ { 0, "Unknown" },
+ { 1, "User" },
+ { 2, "Admin" },
+ { 3, "Server" },
+ { 4, "Registry" },
+ { 0, NULL }
+};
+
+static const value_string ndps_get_session_type_enum[] = {
+ { 0, "Unknown" },
+ { 1, "User" },
+ { 2, "Admin" },
+ { 3, "Supplier" },
+ { 0, NULL }
+};
+
+static const value_string ndps_get_resman_session_type_enum[] = {
+ { 0, "Unknown" },
+ { 1, "User" },
+ { 2, "Admin" },
+ { 0, NULL }
+};
+
+static int
+align_4(tvbuff_t *tvb, int aoffset)
+{
+ if(tvb_length_remaining(tvb, aoffset) > 4 )
+ {
+ return (aoffset%4);
+ }
+ return 0;
+}
+
+static int
+ndps_string(tvbuff_t* tvb, int hfinfo, proto_tree *ndps_tree, int offset, char *stringval, size_t buflen)
+{
+ int foffset = offset;
+ guint32 str_length;
+ char buffer[1024];
+ guint32 i;
+ guint16 c_char;
+ guint32 length_remaining = 0;
+
+ if (stringval == NULL) {
+ stringval = buffer;
+ buflen = sizeof buffer;
+ }
+ str_length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ length_remaining = tvb_length_remaining(tvb, foffset);
+ if(str_length > (guint)length_remaining || str_length > 1024)
+ {
+ proto_tree_add_string(ndps_tree, hfinfo, tvb, foffset,
+ length_remaining + 4, "<String too long to process>");
+ foffset += length_remaining;
+ return foffset;
+ }
+ if(str_length == 0)
+ {
+ proto_tree_add_string(ndps_tree, hfinfo, tvb, offset,
+ 4, "<Not Specified>");
+ return foffset;
+ }
+ for ( i = 0; i < str_length; i++ )
+ {
+ c_char = tvb_get_guint8(tvb, foffset );
+ if (c_char<0x20 || c_char>0x7e)
+ {
+ if (c_char != 0x00)
+ {
+ c_char = 0x2e;
+ if (i < buflen - 1)
+ stringval[i] = c_char & 0xff;
+ }
+ else
+ {
+ i--;
+ str_length--;
+ }
+ }
+ else
+ {
+ if (i < buflen - 1)
+ stringval[i] = c_char & 0xff;
+ }
+ foffset++;
+ length_remaining--;
+
+ if(length_remaining==1)
+ {
+ i++;
+ break;
+ }
+ }
+ stringval[i] = '\0';
+
+ str_length = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_string(ndps_tree, hfinfo, tvb, offset+4,
+ str_length, stringval);
+ foffset += align_4(tvb, foffset);
+ return foffset;
+}
+
+static int
+objectidentifier(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 length;
+ char *label=NULL;
+ guint32 label_value=0;
+ proto_tree *atree;
+ proto_item *aitem;
+ gboolean found=TRUE;
+
+ length = tvb_get_ntohl(tvb, foffset);
+ if (length==0)
+ {
+ return foffset;
+ }
+ if (ndps_show_oids)
+ {
+ proto_tree_add_uint(ndps_tree, hf_oid_struct_size, tvb, foffset, 4, length);
+ }
+ foffset += 4;
+ switch (length)
+ {
+ case 9:
+ label_value = tvb_get_ntohl(tvb, foffset+5);
+ label = match_strval(label_value, object_ids_7);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_7, tvb, foffset, length, label);
+ break;
+ case 10:
+ label_value = tvb_get_ntohl(tvb, foffset+6);
+ label = match_strval(label_value, object_ids_8);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_8, tvb, foffset, length, label);
+ break;
+ case 11:
+ label_value = tvb_get_ntohl(tvb, foffset+7);
+ label = match_strval(label_value, object_ids_9);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_9, tvb, foffset, length, label);
+ break;
+ case 12:
+ label_value = tvb_get_ntohl(tvb, foffset+8);
+ label = match_strval(label_value, object_ids_10);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_10, tvb, foffset, length, label);
+ break;
+ case 13:
+ label_value = tvb_get_ntohl(tvb, foffset+9);
+ label = match_strval(label_value, object_ids_11);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_11, tvb, foffset, length, label);
+ break;
+ case 14:
+ label_value = tvb_get_ntohl(tvb, foffset+10);
+ label = match_strval(label_value, object_ids_12);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_12, tvb, foffset, length, label);
+ break;
+ case 15:
+ label_value = tvb_get_ntohl(tvb, foffset+11);
+ label = match_strval(label_value, object_ids_13);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_13, tvb, foffset, length, label);
+ break;
+ case 16:
+ label_value = tvb_get_ntohl(tvb, foffset+12);
+ label = match_strval(label_value, object_ids_14);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_14, tvb, foffset, length, label);
+ break;
+ case 17:
+ label_value = tvb_get_ntohl(tvb, foffset+13);
+ label = match_strval(label_value, object_ids_15);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_15, tvb, foffset, length, label);
+ break;
+ case 18:
+ label_value = tvb_get_ntohl(tvb, foffset+14);
+ label = match_strval(label_value, object_ids_16);
+ if (label==NULL)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ aitem = proto_tree_add_none_format(ndps_tree, hf_ndps_object_ids_16, tvb, foffset, length, label);
+ break;
+ default:
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, length, "Unknown ID");
+ found=FALSE;
+ break;
+ }
+ if (!found)
+ {
+ label_value = 1;
+ label = match_strval(label_value, object_ids_7);
+ }
+ if (ndps_show_oids)
+ {
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_oid_asn1_type, tvb, foffset, 1, FALSE);
+ foffset += 1;
+ length = tvb_get_guint8(tvb, foffset);
+ foffset += 1;
+ proto_tree_add_item(atree, hf_ndps_oid, tvb, foffset, length, FALSE);
+ foffset += length;
+ }
+ else
+ {
+ if (!found)
+ {
+ foffset += length;
+ }
+ else
+ {
+ foffset += 1;
+ length = tvb_get_guint8(tvb, foffset);
+ foffset += 1;
+ foffset += length;
+ }
+ }
+ global_attribute_name = label;
+ return foffset+(length%2);
+}
+
+static int
+name_or_id(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 name_or_id_val;
+
+ name_or_id_val = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_nameorid, tvb, foffset, 4, name_or_id_val);
+ foffset += 4;
+ switch (name_or_id_val)
+ {
+ case 1: /* Global */
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ break;
+
+ case 2: /* Local */
+ foffset = ndps_string(tvb, hf_local_object_name, ndps_tree, foffset, NULL, 0);
+ break;
+ }
+ foffset += align_4(tvb, foffset);
+ return foffset;
+}
+
+static int
+qualifiedname(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 qualified_name_type=0;
+
+ qualified_name_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_qualified_name, tvb, foffset, 4, qualified_name_type);
+ foffset += 4;
+ if (qualified_name_type != 0) {
+ if (qualified_name_type == 1) {
+ foffset = ndps_string(tvb, hf_printer_name, ndps_tree, foffset, NULL, 0);
+ }
+ else
+ {
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_tree, ndps_tree, foffset, NULL, 0);
+ }
+ }
+ return foffset;
+}
+
+static int
+objectidentification(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 object_type=0;
+ proto_tree *atree;
+ proto_item *aitem;
+
+ object_type = tvb_get_ntohl(tvb, foffset);
+ aitem = proto_tree_add_item(ndps_tree, hf_obj_id_type, tvb, foffset, 4, FALSE);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset += 4;
+ switch(object_type)
+ {
+ case 0: /* Printer Contained Object ID */
+ foffset = ndps_string(tvb, hf_printer_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_ndps_object, tvb, foffset,
+ 4, FALSE);
+ foffset += 4;
+ break;
+ case 1: /* Document Identifier */
+ foffset = ndps_string(tvb, hf_printer_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_ndps_document_number, tvb, foffset,
+ 4, FALSE);
+ foffset += 4;
+ break;
+ case 2: /* Object Identifier */
+ foffset = objectidentifier(tvb, atree, foffset);
+ break;
+ case 3: /* Object Name */
+ foffset = ndps_string(tvb, hf_object_name, atree, foffset, NULL, 0);
+ if (foffset > tvb_length_remaining(tvb, foffset)) {
+ return foffset;
+ }
+ foffset = name_or_id(tvb, atree, foffset);
+ break;
+ case 4: /* Name or Object ID */
+ foffset = name_or_id(tvb, atree, foffset);
+ break;
+ case 5: /* Simple Name */
+ foffset = ndps_string(tvb, hf_object_name, atree, foffset, NULL, 0);
+ break;
+ case 6: /* Printer Configuration Object ID */
+ foffset = ndps_string(tvb, hf_printer_name, atree, foffset, NULL, 0);
+ break;
+ case 7: /* Qualified Name */
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ break;
+ case 8: /* Event Object ID */
+ foffset = ndps_string(tvb, hf_object_name, atree, foffset, NULL, 0);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_tree_add_item(atree, hf_ndps_event_type, tvb, foffset,
+ 4, FALSE);
+ foffset += 4;
+ default:
+ break;
+ }
+ return foffset;
+}
+
+static int
+print_address(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 address_type=0;
+ guint32 address=0;
+ guint32 address_len=0;
+
+ address_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_address, tvb, foffset, 4, address_type);
+ foffset += 4;
+ address_len = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(ndps_tree, hf_address_len, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ switch(address_type)
+ {
+ case 0x00000000:
+ proto_tree_add_item(ndps_tree, hf_ndps_net, tvb, foffset, 4, FALSE);
+ proto_tree_add_item(ndps_tree, hf_ndps_node, tvb, foffset+4, 6, FALSE);
+ proto_tree_add_item(ndps_tree, hf_ndps_socket, tvb, foffset+10, 2, FALSE);
+ foffset += address_len;
+ break;
+ case 0x00000001:
+ proto_tree_add_item(ndps_tree, hf_ndps_port, tvb, foffset, 2, FALSE);
+ address = tvb_get_letohl(tvb, foffset+2);
+ proto_tree_add_ipv4(ndps_tree, hf_ndps_ip, tvb, foffset+2, 4, address);
+ foffset += address_len;
+ break;
+ default:
+ foffset += tvb_get_ntohl(tvb, foffset -4);
+ break;
+ }
+ return foffset+(address_len%4);
+}
+
+static int
+address_item(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 address_type=0;
+
+ address_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_address_type, tvb, foffset, 4, address_type);
+ foffset += 4;
+ switch(address_type)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ break;
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 13:
+ proto_tree_add_item(ndps_tree, hf_ndps_attrib_boolean, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 14:
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 15:
+ foffset = print_address(tvb, ndps_tree, foffset);
+ break;
+ case 16:
+ case 17:
+ default:
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ break;
+ }
+ return foffset;
+}
+
+static int
+credentials(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 cred_type=0;
+ guint32 length=0;
+ guint32 number_of_items;
+ guint32 i;
+ proto_tree *atree;
+ proto_item *aitem;
+
+ cred_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_cred_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ switch (cred_type)
+ {
+ case 0:
+ foffset = ndps_string(tvb, hf_ndps_user_name, ndps_tree, foffset, NULL, 0);
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_passwords, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Password %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_password, tvb, foffset, length, FALSE);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset += length;
+ }
+ break;
+ case 1:
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_certified, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ break;
+ case 2:
+ foffset = ndps_string(tvb, hf_ndps_server_name, ndps_tree, foffset, NULL, 0);
+ foffset += 2;
+ proto_tree_add_item(ndps_tree, hf_ndps_connection, tvb, foffset, 2, FALSE);
+ foffset += 2;
+ break;
+ case 3:
+ length=tvb_get_ntohl(tvb, foffset);
+ foffset = ndps_string(tvb, hf_ndps_server_name, ndps_tree, foffset, NULL, 0);
+ if (length == 0)
+ {
+ foffset += 2;
+ }
+ if (tvb_get_ntohs(tvb, foffset)==0) /* NDPS 1.0 */
+ {
+ foffset+=2;
+ if (tvb_get_ntohs(tvb, foffset)==0) /* NDPS 1.1 */
+ {
+ foffset += 2;
+ }
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_connection, tvb, foffset, 2, FALSE);
+ foffset += 2;
+ foffset = ndps_string(tvb, hf_ndps_user_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 4:
+ foffset = ndps_string(tvb, hf_ndps_server_name, ndps_tree, foffset, NULL, 0);
+ foffset += 2;
+ proto_tree_add_item(ndps_tree, hf_ndps_connection, tvb, foffset, 2, FALSE);
+ foffset += 2;
+ foffset = ndps_string(tvb, hf_ndps_user_name, ndps_tree, foffset, NULL, 0);
+ foffset += 8; /* Don't know what these 8 bytes signify */
+ proto_tree_add_item(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, FALSE);
+ foffset += 4; /* XXX - what does this count? */
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_tree, ndps_tree, foffset, NULL, 0);
+ break;
+ default:
+ break;
+ }
+ return foffset;
+}
+
+
+static int
+event_object_set(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 number_of_items;
+ guint32 number_of_items2;
+ guint32 i;
+ guint32 j;
+ guint32 object_identifier;
+ proto_tree *atree;
+ proto_item *aitem;
+ proto_tree *btree;
+ proto_item *bitem;
+ proto_tree *ctree;
+ proto_item *citem;
+
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Event");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_events, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Event %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ proto_tree_add_item(btree, hf_ndps_event_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = objectidentifier(tvb, btree, foffset);
+ foffset += align_4(tvb, foffset);
+ foffset = objectidentification(tvb, btree, foffset);
+ foffset += align_4(tvb, foffset);
+ proto_tree_add_item(btree, hf_ndps_object_op, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ object_identifier = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_event_object_identifier, tvb, foffset, 4, object_identifier);
+ foffset += 4;
+ switch (object_identifier)
+ {
+ case 1:
+ foffset = objectidentifier(tvb, btree, foffset);
+ foffset += align_4(tvb, foffset);
+ break;
+
+ case 2:
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_item_count, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ for (j = 1 ; j <= number_of_items2; j++ )
+ {
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Item %u", j);
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = objectidentifier(tvb, ctree, foffset);
+ foffset += align_4(tvb, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ }
+ break;
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ return foffset;
+}
+
+
+static int
+cardinal_seq(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 number_of_items;
+ guint32 length;
+ guint32 i;
+ proto_tree *atree;
+ proto_item *aitem;
+
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Cardinal %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ return foffset;
+}
+
+
+static int
+server_entry(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ char server_name[1024];
+ guint32 number_of_items;
+ guint32 i;
+ guint32 data_type;
+ proto_tree *atree;
+ proto_item *aitem;
+ proto_tree *btree;
+ proto_item *bitem;
+
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Server Info");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_server_name, ndps_tree, foffset, server_name, sizeof server_name);
+ proto_item_append_text(aitem, ": %s", server_name);
+ proto_tree_add_item(atree, hf_ndps_server_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = print_address(tvb, atree, foffset);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_servers, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Info %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ data_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(btree, hf_ndps_data_item_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ switch (data_type)
+ {
+ case 0: /* Int8 */
+ proto_tree_add_item(btree, hf_info_int, tvb, foffset, 1, FALSE);
+ foffset++;
+ break;
+ case 1: /* Int16 */
+ proto_tree_add_item(btree, hf_info_int16, tvb, foffset, 2, FALSE);
+ foffset += 2;
+ break;
+ case 2: /* Int32 */
+ proto_tree_add_item(btree, hf_info_int32, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 3: /* Boolean */
+ proto_tree_add_item(btree, hf_info_boolean, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 4: /* String */
+ case 5: /* Bytes */
+ foffset = ndps_string(tvb, hf_info_string, btree, foffset, NULL, 0);
+ break;
+ default:
+ break;
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ return foffset;
+}
+
+
+static int
+attribute_value(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 i;
+ guint32 j;
+ guint32 number_of_items;
+ guint32 number_of_items2;
+ guint32 attribute_type;
+ guint32 integer_or_oid;
+ guint32 event_object_type;
+ guint32 ignored_type;
+ guint32 resource_type;
+ guint32 identifier_type;
+ guint32 criterion_type;
+ guint32 card_enum_time;
+ guint32 media_type;
+ guint32 doc_content;
+ guint32 page_size;
+ guint32 medium_size;
+ guint32 numbers_up;
+ guint32 colorant_set;
+ guint32 length;
+ guint32 dimension;
+ guint32 location;
+ guint32 cardinal;
+ char *label;
+ guint32 label_value;
+ proto_tree *atree;
+ proto_item *aitem;
+ proto_tree *btree;
+ proto_item *bitem;
+
+ if (global_attribute_name==NULL)
+ {
+ label_value = 1;
+ label = match_strval(label_value, object_ids_7);
+ global_attribute_name = label;
+ }
+ attribute_type = tvb_get_ntohl(tvb, foffset);
+ if (ndps_show_oids)
+ {
+ proto_tree_add_item(ndps_tree, hf_obj_attribute_type, tvb, foffset, 4, FALSE);
+ }
+ foffset += 4;
+ switch(attribute_type)
+ {
+ case 0: /* Null */
+ proto_tree_add_item(ndps_tree, hf_ndps_data, tvb, foffset+4, tvb_get_ntohl(tvb, foffset), FALSE);
+ break;
+ case 1: /* Text */
+ case 2: /* Descriptive Name */
+ case 3: /* Descriptor */
+ case 6: /* Simple Name */
+ case 40: /* Distinguished Name*/
+ case 50: /* Font Reference */
+ case 58: /* Locale */
+ case 102: /* File Path */
+ case 103: /* Uniform Resource Identifier */
+ case 108: /* Extended Resource Identifier */
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 4: /* Message */
+ case 5: /* Error Message */
+ case 38: /* Name or OID */
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+ case 39: /* Name or OID Seq */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Item %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 7: /* Distinguished Name String*/
+ case 79: /* File Reference */
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+ case 8: /* Distinguished Name String Seq */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Name %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_object_name, atree, foffset, NULL, 0);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 9: /* Delta Time */
+ case 10: /* Time */
+ case 11: /* Integer */
+ case 13: /* Cardinal */
+ case 15: /* Positive Integer */
+ case 18: /* Maximum Integer */
+ case 19: /* Minimum Integer */
+ case 35: /* Percent */
+ case 57: /* Job Priority */
+ case 72: /* Sides */
+ case 95: /* Enumeration */
+ if (strcmp(global_attribute_name,"(Novell) Attribute PRINTER SECURITY LEVEL")==0)
+ {
+ proto_tree_add_item(ndps_tree, hf_print_security, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ break;
+ case 12: /* Integer Seq */
+ case 14: /* Cardinal Seq */
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_info_int32, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ break;
+ case 16: /* Integer Range */
+ case 17: /* Cardinal Range */
+ proto_tree_add_item(ndps_tree, hf_ndps_lower_range, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_upper_range, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 20: /* Integer 64 */
+ case 22: /* Cardinal 64 */
+ case 24: /* Positive Integer 64 */
+ case 31: /* Non-Negative Real */
+ case 29: /* Real */
+ proto_tree_add_item(ndps_tree, hf_ndps_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+ case 21: /* Integer 64 Seq */
+ case 23: /* Cardinal 64 Seq */
+ case 30: /* Real Seq */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Item %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 25: /* Integer 64 Range */
+ case 26: /* Cardinal 64 Range */
+ case 32: /* Real Range */
+ case 33: /* Non-Negative Real Range */
+ proto_tree_add_item(ndps_tree, hf_ndps_lower_range_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_upper_range_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+ case 27: /* Maximum Integer 64 */
+ proto_tree_add_item(ndps_tree, hf_ndps_lower_range_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+ case 28: /* Minimum Integer 64 */
+ proto_tree_add_item(ndps_tree, hf_ndps_upper_range_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+ case 34: /* Boolean */
+ proto_tree_add_item(ndps_tree, hf_ndps_attrib_boolean, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 36: /* Object Identifier */
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ break;
+ case 37: /* Object Identifier Seq */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 41: /* Relative Distinguished Name Seq */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_names, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Name %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_object_name, atree, foffset, NULL, 0);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 42: /* Realization */
+ proto_tree_add_item(ndps_tree, hf_ndps_realization, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 43: /* Medium Dimensions */
+ proto_tree_add_item(ndps_tree, hf_ndps_xdimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ydimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+ case 44: /* Dimension */
+ dimension = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_dim_value, tvb, foffset, 4, dimension);
+ foffset += 4;
+ if (dimension == 0) {
+ proto_tree_add_item(ndps_tree, hf_ndps_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ }
+ else
+ {
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_dim_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+ case 45: /* XY Dimensions */
+ dimension = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_xydim_value, tvb, foffset, 4, dimension);
+ foffset += 4;
+ if (dimension == 1) {
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_xdimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ydimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_dim_flag, tvb, foffset, 8, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+ case 46: /* Locations */
+ location = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_location_value, tvb, foffset, 4, location);
+ foffset += 4;
+ if (location == 0) {
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_locations, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Location %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ }
+ else
+ {
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_dim_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+ case 47: /* Area */
+ proto_tree_add_item(ndps_tree, hf_ndps_xmin_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_xmax_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ymin_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ymax_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+ case 48: /* Area Seq */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_areas, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Area %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_xmin_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(atree, hf_ndps_xmax_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(atree, hf_ndps_ymin_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(atree, hf_ndps_ymax_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 49: /* Edge */
+ proto_tree_add_item(ndps_tree, hf_ndps_edge_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 51: /* Cardinal or OID */
+ cardinal = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_cardinal_or_oid, tvb, foffset, 4, cardinal);
+ foffset += 4;
+ if (cardinal==0) {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else
+ {
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ }
+ break;
+ case 52: /* OID Cardinal Map */
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 53: /* Cardinal or Name or OID */
+ cardinal = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_cardinal_name_or_oid, tvb, foffset, 4, cardinal);
+ foffset += 4;
+ if (cardinal==0) {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else
+ {
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ }
+ break;
+ case 54: /* Positive Integer or OID */
+ integer_or_oid = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_integer_or_oid, tvb, foffset, 4, integer_or_oid);
+ foffset += 4;
+ if (integer_or_oid==0) {
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ break;
+ case 55: /* Event Handling Profile */
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_persistence, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_address_items, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Address Item %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = address_item(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_events, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Event %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_event_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = objectidentifier(tvb, atree, foffset);
+ foffset += align_4(tvb, foffset);
+ foffset = objectidentification(tvb, atree, foffset);
+ proto_tree_add_item(atree, hf_ndps_object_op, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ event_object_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_event_object_identifier, tvb, foffset, 4, event_object_type);
+ foffset += 4;
+ switch (event_object_type)
+ {
+ case 2:
+ /* Number of Objects */
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ for (j = 1 ; j <= number_of_items2; j++ )
+ {
+ foffset = objectidentifier(tvb, atree, foffset);
+ }
+ foffset += 4;
+ break;
+
+ case 1:
+ foffset = objectidentifier(tvb, atree, foffset);
+ break;
+
+ case 0:
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ for (j = 1 ; j <= number_of_items2; j++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Object %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ break;
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 56: /* Octet String */
+ case 63: /* Job Password */
+ case 66: /* Print Checkpoint */
+ foffset = ndps_string(tvb, hf_info_string, ndps_tree, foffset, NULL, 0);
+ break;
+ case 59: /* Method Delivery Address */
+ proto_tree_add_item(ndps_tree, hf_ndps_delivery_add_type, tvb, foffset, 4, FALSE);
+ event_object_type = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ switch(event_object_type)
+ {
+ case 0: /*MHS ADDR*/
+ case 1: /*DISTINGUISHED_NAME*/
+ case 2: /*TEXT*/
+ case 3: /*OCTET_STRING*/
+ foffset = ndps_string(tvb, hf_info_string, ndps_tree, foffset, NULL, 0);
+ break;
+ case 4: /*DIST_NAME_STRING*/
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+ case 5: /*RPC_ADDRESS*/
+ case 6: /*QUALIFIED_NAME*/
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 60: /* Object Identification */
+ foffset = objectidentification(tvb, ndps_tree, foffset);
+ break;
+ case 61: /* Results Profile */
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ foffset = address_item(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+ case 62: /* Criteria */
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ criterion_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_criterion_type, tvb, foffset, 4, criterion_type);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 64: /* Job Level */
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 65: /* Job Categories */
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_job_categories, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Job %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 67: /* Ignored Attribute */
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_ignored_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Ignored Attribute %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ ignored_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_ignored_type, tvb, foffset, 4, ignored_type);
+ foffset += 4;
+ if (ignored_type == 38)
+ {
+ foffset = name_or_id(tvb, atree, foffset);
+ }
+ else
+ {
+ foffset = objectidentifier(tvb, atree, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 68: /* Resource */
+ resource_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_resource_type, tvb, foffset, 4, resource_type);
+ foffset += 4;
+ if (resource_type == 0)
+ {
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ foffset = ndps_string(tvb, hf_ndps_tree, ndps_tree, foffset, NULL, 0);
+ }
+ break;
+ case 69: /* Medium Substitution */
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+ case 70: /* Font Substitution */
+ foffset = ndps_string(tvb, hf_ndps_tree, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_tree, ndps_tree, foffset, NULL, 0);
+ break;
+ case 71: /* Resource Context Seq */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_resources, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Resource %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ resource_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_resource_type, tvb, foffset, 4, resource_type);
+ foffset += 4;
+ if (resource_type == 0)
+ {
+ foffset = name_or_id(tvb, atree, foffset);
+ }
+ else
+ {
+ foffset = ndps_string(tvb, hf_ndps_tree, atree, foffset, NULL, 0);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 73: /* Page Select Seq */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_page_selects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Page Select %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_page_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ identifier_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_identifier_type, tvb, foffset, 4, identifier_type);
+ foffset += 4;
+ if (identifier_type == 0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ if (identifier_type == 1)
+ {
+ foffset = ndps_string(tvb, hf_ndps_tree, atree, foffset, NULL, 0);
+ }
+ if (identifier_type == 2)
+ {
+ foffset = name_or_id(tvb, atree, foffset);
+ }
+ proto_tree_add_item(atree, hf_ndps_page_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ identifier_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_identifier_type, tvb, foffset, 4, identifier_type);
+ foffset += 4;
+ if (identifier_type == 0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ if (identifier_type == 1)
+ {
+ foffset = ndps_string(tvb, hf_ndps_tree, atree, foffset, NULL, 0);
+ }
+ if (identifier_type == 2)
+ {
+ foffset = name_or_id(tvb, atree, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 74: /* Page Media Select */
+ media_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_media_type, tvb, foffset, 4, media_type);
+ foffset += 4;
+ if (media_type == 0)
+ {
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ foffset = ndps_string(tvb, hf_ndps_tree, ndps_tree, foffset, NULL, 0);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Item %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_page_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ identifier_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_identifier_type, tvb, foffset, 4, identifier_type);
+ foffset += 4;
+ if (identifier_type == 0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ if (identifier_type == 1)
+ {
+ foffset = ndps_string(tvb, hf_ndps_tree, atree, foffset, NULL, 0);
+ }
+ if (identifier_type == 2)
+ {
+ foffset = name_or_id(tvb, atree, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ }
+ break;
+ case 75: /* Document Content */
+ doc_content = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_doc_content, tvb, foffset, 4, doc_content);
+ foffset += 4;
+ if (doc_content == 0)
+ {
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_octet_string, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ }
+ else
+ {
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ }
+ break;
+ case 76: /* Page Size */
+ page_size = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_page_size, tvb, foffset, 4, page_size);
+ foffset += 4;
+ if (page_size == 0)
+ {
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_xdimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ydimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ }
+ break;
+ case 77: /* Presentation Direction */
+ proto_tree_add_item(ndps_tree, hf_ndps_direction, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 78: /* Page Order */
+ proto_tree_add_item(ndps_tree, hf_ndps_page_order, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 80: /* Medium Source Size */
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ medium_size = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_medium_size, tvb, foffset, 4, medium_size);
+ foffset += 4;
+ if (medium_size == 0)
+ {
+ page_size = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_page_size, tvb, foffset, 4, page_size);
+ foffset += 4;
+ if (page_size == 0)
+ {
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_xdimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ydimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_long_edge_feeds, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_xmin_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_xmax_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ymin_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ymax_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ }
+ else
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_lower_range_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_upper_range_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_inc_across_feed, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_lower_range_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_upper_range_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_size_inc_in_feed, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_long_edge_feeds, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_xmin_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_xmax_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ymin_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ymax_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ }
+ break;
+ case 81: /* Input Tray Medium */
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+ case 82: /* Output Bins Characteristics */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_page_informations, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Page Information %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_page_order, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_ndps_page_orientation, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 83: /* Page ID Type */
+ proto_tree_add_item(ndps_tree, hf_ndps_identifier_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 84: /* Level Range */
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_lower_range, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_upper_range, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 85: /* Category Set */
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_categories, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Category %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ }
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_values, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Value %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 86: /* Numbers Up Supported */
+ numbers_up=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_numbers_up, tvb, foffset, 4, numbers_up);
+ foffset += 4;
+ switch(numbers_up)
+ {
+ case 0: /*Cardinal*/
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 1: /*Name or OID*/
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+ case 2: /*Cardinal Range*/
+ proto_tree_add_item(ndps_tree, hf_ndps_lower_range, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_upper_range, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 87: /* Finishing */
+ case 88: /* Print Contained Object ID */
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 89: /* Print Config Object ID */
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ break;
+ case 90: /* Typed Name */
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_level, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_interval, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 91: /* Network Address */
+ proto_tree_add_item(ndps_tree, hf_ndps_address, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_add_bytes, tvb, foffset, 4, FALSE);
+ }
+ foffset += length;
+ break;
+ case 92: /* XY Dimensions Value */
+ dimension = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_xydim_value, tvb, foffset, 4, dimension);
+ foffset += 4;
+ switch (dimension)
+ {
+ case 1:
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+
+ case 0:
+ proto_tree_add_item(ndps_tree, hf_ndps_xdimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ proto_tree_add_item(ndps_tree, hf_ndps_ydimension_n64, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ break;
+
+ default:
+ proto_tree_add_item(ndps_tree, hf_ndps_xdimension, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_ydimension, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ }
+ break;
+ case 93: /* Name or OID Dimensions Map */
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_xdimension, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_ydimension, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 94: /* Printer State Reason */
+ foffset += 4;
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_state_severity, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_training, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ foffset += align_4(tvb, foffset);
+ foffset = objectidentification(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+ case 96: /* Qualified Name */
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ break;
+ case 97: /* Qualified Name Set */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_names, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Name %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 98: /* Colorant Set */
+ colorant_set = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_colorant_set, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (colorant_set==0)
+ {
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_colorants, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Colorant %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ }
+ break;
+ case 99: /* Resource Printer ID */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_printer_def_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Printer %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_printer_type, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_printer_manuf, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_inf_file_name, atree, foffset, NULL, 0);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 100: /* Event Object ID */
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_event_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 101: /* Qualified Name Map */
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ break;
+ case 104: /* Cardinal or Enum or Time */
+ card_enum_time = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_card_enum_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ switch (card_enum_time)
+ {
+ case 0:
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+
+ case 1:
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+
+ default:
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ }
+ break;
+ case 105: /* Print Contained Object ID Set */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 106: /* Octet String Pair */
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_octet_string, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_octet_string, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ break;
+ case 107: /* Octet String Integer Pair */
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_octet_string, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 109: /* Event Handling Profile 2 */
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_persistence, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_octet_string, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_delivery_add_type, tvb, foffset, 4, FALSE);
+ event_object_type = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ switch(event_object_type)
+ {
+ case 0: /*MHS ADDR*/
+ case 1: /*DISTINGUISHED_NAME*/
+ case 2: /*TEXT*/
+ foffset = ndps_string(tvb, hf_ndps_tree, ndps_tree, foffset, NULL, 0);
+ break;
+ case 3: /*OCTET_STRING*/
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_octet_string, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ break;
+ case 4: /*DIST_NAME_STRING*/
+ foffset = ndps_string(tvb, hf_object_name, ndps_tree, foffset, NULL, 0);
+ foffset = name_or_id(tvb, ndps_tree, foffset);
+ break;
+ case 5: /*RPC_ADDRESS*/
+ case 6: /*QUALIFIED_NAME*/
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ break;
+ default:
+ break;
+ }
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_events, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Event %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_object_name, atree, foffset, NULL, 0);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_tree_add_item(atree, hf_ndps_event_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ break;
+ default:
+ break;
+ }
+ return foffset;
+}
+
+
+static int
+commonarguments(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 number_of_items;
+ guint32 i;
+ proto_tree *atree;
+ proto_item *aitem;
+ proto_tree *btree;
+ proto_item *bitem;
+
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Common Arguments");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_args, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Argument %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, atree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ return foffset;
+}
+
+static int
+res_add_input_data(tvbuff_t* tvb, proto_tree *ndps_tree, int foffset)
+{
+ guint32 resource_type=0;
+
+ resource_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_res_type, tvb, foffset, 4, resource_type);
+ foffset += 4;
+ switch (resource_type)
+ {
+ case 0: /* Print Drivers */
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_prn_dir_name, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_prn_file_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 1: /* Printer Definitions */
+ foffset = ndps_string(tvb, hf_ndps_vendor_dir, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_prn_file_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 2: /* Banner Page Files */
+ foffset = ndps_string(tvb, hf_ndps_banner_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 3: /* Font Types */
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_font_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_prn_file_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 4: /* Generic Files/ Archive */
+ case 5: /* Printer Driver Archive */
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_prn_dir_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_archive_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ default:
+ break;
+ }
+ return foffset;
+}
+
+
+static const fragment_items ndps_frag_items = {
+ &ett_ndps_segment,
+ &ett_ndps_segments,
+ &hf_ndps_segments,
+ &hf_ndps_segment,
+ &hf_ndps_segment_overlap,
+ &hf_ndps_segment_overlap_conflict,
+ &hf_ndps_segment_multiple_tails,
+ &hf_ndps_segment_too_long_segment,
+ &hf_ndps_segment_error,
+ NULL,
+ "segments"
+};
+
+static dissector_handle_t ndps_data_handle;
+
+/* NDPS packets come in request/reply pairs. The request packets tell the
+ * Function and Program numbers. The response, unfortunately, only
+ * identifies itself via the Exchange ID; you have to know what type of NDPS
+ * request the request packet contained in order to successfully parse the
+ * response. A global method for doing this does not exist in ethereal yet
+ * (NFS also requires it), so for now the NDPS section will keep its own hash
+ * table keeping track of NDPS packets.
+ *
+ * We construct a conversation specified by the client and server
+ * addresses and the connection number; the key representing the unique
+ * NDPS request then is composed of the pointer to the conversation
+ * structure, cast to a "guint" (which may throw away the upper 32
+ * bits of the pointer on a P64 platform, but the low-order 32 bits
+ * are more likely to differ between conversations than the upper 32 bits),
+ * and the sequence number.
+ *
+ * The value stored in the hash table is the ncp_req_hash_value pointer. This
+ * struct tells us the NDPS Program and Function and gives the NDPS_record pointer.
+ */
+typedef struct {
+ conversation_t *conversation;
+ guint32 ndps_xport;
+} ndps_req_hash_key;
+
+typedef struct {
+ guint32 ndps_prog;
+ guint32 ndps_func;
+ guint32 ndps_frame_num;
+ gboolean ndps_frag;
+ guint32 ndps_end_frag;
+} ndps_req_hash_value;
+
+static GHashTable *ndps_req_hash = NULL;
+static GMemChunk *ndps_req_hash_keys = NULL;
+static GMemChunk *ndps_req_hash_values = NULL;
+
+/* Hash Functions */
+gint
+ndps_equal(gconstpointer v, gconstpointer v2)
+{
+ const ndps_req_hash_key *val1 = (const ndps_req_hash_key*)v;
+ const ndps_req_hash_key *val2 = (const ndps_req_hash_key*)v2;
+
+ if (val1->conversation == val2->conversation &&
+ val1->ndps_xport == val2->ndps_xport ) {
+ return 1;
+ }
+ return 0;
+}
+
+guint
+ndps_hash(gconstpointer v)
+{
+ const ndps_req_hash_key *ndps_key = (const ndps_req_hash_key*)v;
+ return GPOINTER_TO_UINT(ndps_key->conversation) + ndps_key->ndps_xport;
+}
+
+/* Initializes the hash table and the mem_chunk area each time a new
+ * file is loaded or re-loaded in ethereal */
+static void
+ndps_init_protocol(void)
+{
+ /* fragment */
+ fragment_table_init(&ndps_fragment_table);
+ reassembled_table_init(&ndps_reassembled_table);
+
+ if (ndps_req_hash)
+ g_hash_table_destroy(ndps_req_hash);
+ if (ndps_req_hash_keys)
+ g_mem_chunk_destroy(ndps_req_hash_keys);
+ if (ndps_req_hash_values)
+ g_mem_chunk_destroy(ndps_req_hash_values);
+
+ ndps_req_hash = g_hash_table_new(ndps_hash, ndps_equal);
+ ndps_req_hash_keys = g_mem_chunk_new("ndps_req_hash_keys",
+ sizeof(ndps_req_hash_key),
+ NDPS_PACKET_INIT_COUNT * sizeof(ndps_req_hash_key),
+ G_ALLOC_ONLY);
+ ndps_req_hash_values = g_mem_chunk_new("ndps_req_hash_values",
+ sizeof(ndps_req_hash_value),
+ NDPS_PACKET_INIT_COUNT * sizeof(ndps_req_hash_value),
+ G_ALLOC_ONLY);
+}
+
+/* After the sequential run, we don't need the ncp_request hash and keys
+ * anymore; the lookups have already been done and the vital info
+ * saved in the reply-packets' private_data in the frame_data struct. */
+static void
+ndps_postseq_cleanup(void)
+{
+ if (ndps_req_hash) {
+ /* Destroy the hash, but don't clean up request_condition data. */
+ g_hash_table_destroy(ndps_req_hash);
+ ndps_req_hash = NULL;
+ }
+ if (ndps_req_hash_keys) {
+ g_mem_chunk_destroy(ndps_req_hash_keys);
+ ndps_req_hash_keys = NULL;
+ }
+ /* Don't free the ncp_req_hash_values, as they're
+ * needed during random-access processing of the proto_tree.*/
+}
+
+ndps_req_hash_value*
+ndps_hash_insert(conversation_t *conversation, guint32 ndps_xport)
+{
+ ndps_req_hash_key *request_key;
+ ndps_req_hash_value *request_value;
+
+ /* Now remember the request, so we can find it if we later
+ a reply to it. */
+ request_key = g_mem_chunk_alloc(ndps_req_hash_keys);
+ request_key->conversation = conversation;
+ request_key->ndps_xport = ndps_xport;
+
+ request_value = g_mem_chunk_alloc(ndps_req_hash_values);
+ request_value->ndps_prog = 0;
+ request_value->ndps_func = 0;
+ request_value->ndps_frame_num = 0;
+ request_value->ndps_frag = FALSE;
+ request_value->ndps_end_frag = 0;
+
+ g_hash_table_insert(ndps_req_hash, request_key, request_value);
+
+ return request_value;
+}
+
+/* Returns the ncp_rec*, or NULL if not found. */
+ndps_req_hash_value*
+ndps_hash_lookup(conversation_t *conversation, guint32 ndps_xport)
+{
+ ndps_req_hash_key request_key;
+
+ request_key.conversation = conversation;
+ request_key.ndps_xport = ndps_xport;
+
+ return g_hash_table_lookup(ndps_req_hash, &request_key);
+}
+
+/* ================================================================= */
+/* NDPS */
+/* ================================================================= */
+
+static void
+dissect_ndps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ndps_tree)
+{
+ guint32 ndps_xid;
+ guint32 ndps_prog;
+ guint32 ndps_packet_type;
+ guint32 ndps_rpc_version;
+ int foffset;
+ guint32 ndps_hfname;
+ guint32 ndps_func;
+ const char *ndps_program_string;
+ const char *ndps_func_string;
+
+
+ ndps_packet_type = tvb_get_ntohl(tvb, 8);
+ if (ndps_packet_type != 0 && ndps_packet_type != 1) { /* Packet Type */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "(Continuation Data)");
+ proto_tree_add_text(ndps_tree, tvb, 0, tvb_length_remaining(tvb, 0), "Data - (%d Bytes)", tvb_length_remaining(tvb, 0));
+ return;
+ }
+ foffset = 0;
+ proto_tree_add_item(ndps_tree, hf_ndps_record_mark, tvb,
+ foffset, 2, FALSE);
+ foffset += 2;
+ proto_tree_add_item(ndps_tree, hf_ndps_length, tvb,
+ foffset, 2, FALSE);
+ foffset += 2;
+
+ ndps_xid = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_xid, tvb, foffset, 4, ndps_xid);
+ foffset += 4;
+ ndps_packet_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_packet_type, tvb, foffset, 4, ndps_packet_type);
+ foffset += 4;
+ if(ndps_packet_type == 0x00000001) /* Reply packet */
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "R NDPS ");
+ proto_tree_add_item(ndps_tree, hf_ndps_rpc_accept, tvb, foffset, 4, FALSE);
+ if (tvb_get_ntohl(tvb, foffset)==0) {
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_auth_null, tvb, foffset, 8, FALSE);
+ foffset += 8;
+ }
+ else
+ {
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_rpc_rej_stat, tvb, foffset+4, 4, FALSE);
+ foffset += 4;
+ }
+ dissect_ndps_reply(tvb, pinfo, ndps_tree, foffset);
+ }
+ else
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "C NDPS ");
+ ndps_rpc_version = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_rpc_version, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ ndps_prog = tvb_get_ntohl(tvb, foffset);
+ ndps_program_string = match_strval(ndps_prog, spx_ndps_program_vals);
+ if( ndps_program_string != NULL)
+ {
+ proto_tree_add_item(ndps_tree, hf_spx_ndps_program, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, (const gchar*) ndps_program_string);
+ col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ }
+ proto_tree_add_item(ndps_tree, hf_spx_ndps_version, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ ndps_func = tvb_get_ntohl(tvb, foffset);
+ switch(ndps_prog)
+ {
+ case 0x060976:
+ ndps_hfname = hf_spx_ndps_func_print;
+ ndps_func_string = match_strval(ndps_func, spx_ndps_print_func_vals);
+ break;
+ case 0x060977:
+ ndps_hfname = hf_spx_ndps_func_broker;
+ ndps_func_string = match_strval(ndps_func, spx_ndps_broker_func_vals);
+ break;
+ case 0x060978:
+ ndps_hfname = hf_spx_ndps_func_registry;
+ ndps_func_string = match_strval(ndps_func, spx_ndps_registry_func_vals);
+ break;
+ case 0x060979:
+ ndps_hfname = hf_spx_ndps_func_notify;
+ ndps_func_string = match_strval(ndps_func, spx_ndps_notify_func_vals);
+ break;
+ case 0x06097a:
+ ndps_hfname = hf_spx_ndps_func_resman;
+ ndps_func_string = match_strval(ndps_func, spx_ndps_resman_func_vals);
+ break;
+ case 0x06097b:
+ ndps_hfname = hf_spx_ndps_func_delivery;
+ ndps_func_string = match_strval(ndps_func, spx_ndps_deliver_func_vals);
+ break;
+ default:
+ ndps_hfname = 0;
+ ndps_func_string = NULL;
+ break;
+ }
+ if(ndps_hfname != 0)
+ {
+ proto_tree_add_item(ndps_tree, ndps_hfname, tvb, foffset, 4, FALSE);
+ if (ndps_func_string != NULL)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, (const gchar*) ndps_func_string);
+
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_auth_null, tvb, foffset, 16, FALSE);
+ foffset+=16;
+ dissect_ndps_request(tvb, pinfo, ndps_tree, ndps_prog, ndps_func, foffset);
+ }
+ }
+ }
+ }
+}
+
+static guint
+get_ndps_pdu_len(tvbuff_t *tvb, int offset)
+{
+ return tvb_get_ntohs(tvb, offset +2) + 4;
+}
+
+static void
+dissect_ndps_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ndps_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDPS");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ndps, tvb, 0, -1, FALSE);
+ ndps_tree = proto_item_add_subtree(ti, ett_ndps);
+ }
+ dissect_ndps(tvb, pinfo, ndps_tree);
+}
+
+/*
+ * Defrag logic
+ *
+ * SPX EOM not being set indicates we are inside or at the
+ * beginning of a fragment. But when the end of the fragment
+ * is encounterd the flag is set. So we must mark what the
+ * frame number is of the end fragment so that we will be
+ * able to redissect if the user clicks on the packet
+ * or resorts/filters the trace.
+ *
+ * Once we are certain that we are in a fragment sequence
+ * then we can just process each fragment in this conversation
+ * until we reach the eom message packet. We can tell we are at
+ * the final fragment because it is flagged as SPX EOM.
+ *
+ * We will be able to easily determine if a conversation is a fragment
+ * with the exception of the last packet in the fragment. So remember
+ * the last fragment packet number.
+ */
+static void
+ndps_defrag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int len=0;
+ tvbuff_t *next_tvb = NULL;
+ fragment_data *fd_head;
+ spx_info *spx_info;
+ ndps_req_hash_value *request_value = NULL;
+ conversation_t *conversation;
+
+ /* Get SPX info from SPX dissector */
+ spx_info = pinfo->private_data;
+ /* Check to see if defragmentation is enabled in the dissector */
+ if (!ndps_defragment) {
+ dissect_ndps(tvb, pinfo, tree);
+ return;
+ }
+ /* Has this already been dissected? */
+ if (!pinfo->fd->flags.visited)
+ {
+ /* Lets see if this is a new conversation */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->srcport, 0);
+
+ if (conversation == NULL)
+ {
+ /* It's not part of any conversation - create a new one. */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->srcport, 0);
+ /* Create new request value hash */
+ request_value = ndps_hash_insert(conversation, (guint32) pinfo->srcport);
+ }
+ /* So now we need to get the request info for this conversation */
+ request_value = ndps_hash_lookup(conversation, (guint32) pinfo->srcport);
+ if (request_value == NULL)
+ {
+ /* We haven't seen a packet with this conversation yet so create one. */
+ request_value = ndps_hash_insert(conversation, (guint32) pinfo->srcport);
+ }
+ /* Add it to pinfo so we can get it on further dissection requests */
+ p_add_proto_data(pinfo->fd, proto_ndps, (void*) request_value);
+ }
+ else
+ {
+ /* Get request value data */
+ request_value = p_get_proto_data(pinfo->fd, proto_ndps);
+ }
+ /* Check to see of this is a fragment. If so then mark as a fragment. */
+ if (!spx_info->eom) {
+ request_value->ndps_frag = TRUE;
+ }
+ /* Now we process the fragments */
+ if (request_value->ndps_frag || (request_value->ndps_end_frag == pinfo->fd->num))
+ {
+ /*
+ * Fragment
+ */
+ tid = (pinfo->srcport+pinfo->destport);
+ len = tvb_reported_length_remaining(tvb, 0);
+ if (tvb_bytes_exist(tvb, 0, len))
+ {
+ fd_head = fragment_add_seq_next(tvb, 0, pinfo, tid, ndps_fragment_table, ndps_reassembled_table, len, !spx_info->eom);
+ if (fd_head != NULL)
+ {
+ /* Is this the last fragment? EOM will indicate */
+ if (fd_head->next != NULL && spx_info->eom)
+ {
+ next_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->len, fd_head->len);
+ tvb_set_child_real_data_tvbuff(tvb,
+ next_tvb);
+ add_new_data_source(pinfo,
+ next_tvb,
+ "Reassembled NDPS");
+ /* Show all fragments. */
+ if (tree)
+ {
+ show_fragment_seq_tree(fd_head,
+ &ndps_frag_items,
+ tree, pinfo,
+ next_tvb);
+ tid++;
+ }
+ /* Remember this fragment number so we can dissect again */
+ request_value->ndps_end_frag = pinfo->fd->num;
+
+ }
+ else
+ {
+ /* This is either a beggining or middle fragment on second dissection */
+ next_tvb = tvb_new_subset(tvb, 0, -1, -1);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (!spx_info->eom)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[NDPS Fragment]");
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Fragment from first pass of dissection */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (!spx_info->eom)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[NDPS Fragment]");
+ }
+ }
+ next_tvb = NULL;
+ }
+ }
+ else
+ {
+ /*
+ * There are no bytes so Dissect this
+ */
+ next_tvb = tvb_new_subset(tvb, 0, -1, -1);
+ }
+ if (next_tvb == NULL)
+ {
+ /* This is a fragment packet */
+ next_tvb = tvb_new_subset (tvb, 0, -1, -1);
+ call_dissector(ndps_data_handle, next_tvb, pinfo, tree);
+ }
+ else
+ {
+ /* This is the end fragment so dissect and mark end */
+ if (spx_info->eom) {
+ request_value->ndps_frag = FALSE;
+ dissect_ndps(next_tvb, pinfo, tree);
+ }
+ }
+ }
+ else
+ {
+ /* This is not any fragment packet */
+ request_value->ndps_frag = FALSE;
+ dissect_ndps(tvb, pinfo, tree);
+ }
+}
+
+static void
+dissect_ndps_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, ndps_desegment, 4, get_ndps_pdu_len,
+ dissect_ndps_pdu);
+}
+
+
+static void
+dissect_ndps_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ndps_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDPS");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ndps, tvb, 0, -1, FALSE);
+ ndps_tree = proto_item_add_subtree(ti, ett_ndps);
+ }
+ ndps_defrag(tvb, pinfo, ndps_tree);
+}
+
+static void
+dissect_ndps_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ndps_tree, guint32 ndps_prog, guint32 ndps_func, int foffset)
+{
+ ndps_req_hash_value *request_value = NULL;
+ conversation_t *conversation;
+ guint32 i;
+ guint32 j;
+ guint32 field_len;
+ guint32 cred_type;
+ guint32 resource_type;
+ guint32 filter_type;
+ guint32 print_type;
+ guint32 length;
+ guint32 number_of_items;
+ guint32 number_of_items2;
+ guint32 doc_content;
+ guint32 list_attr_op;
+ guint32 scope;
+ guint32 job_type;
+ gboolean supplier_flag;
+ gboolean language_flag;
+ gboolean method_flag;
+ gboolean delivery_address_flag;
+ guint32 profiles_type;
+ guint32 profiles_choice_type;
+ guint32 integer_type_flag;
+ guint32 local_servers_type;
+ gint length_remaining;
+ proto_tree *atree;
+ proto_item *aitem;
+ proto_tree *btree;
+ proto_item *bitem;
+ proto_tree *ctree;
+ proto_item *citem;
+ proto_tree *dtree;
+ proto_item *ditem;
+
+ if (!pinfo->fd->flags.visited)
+ {
+ /* This is the first time we've looked at this packet.
+ Keep track of the Program and connection whence the request
+ came, and the address and connection to which the request
+ is being sent, so that we can match up calls with replies.
+ (We don't include the sequence number, as we may want
+ to have all packets over the same connection treated
+ as being part of a single conversation so that we can
+ let the user select that conversation to be displayed.) */
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->srcport, 0);
+
+ if (conversation == NULL)
+ {
+ /* It's not part of any conversation - create a new one. */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->srcport, 0);
+ }
+
+ request_value = ndps_hash_insert(conversation, (guint32) pinfo->srcport);
+ request_value->ndps_prog = ndps_prog;
+ request_value->ndps_func = ndps_func;
+ request_value->ndps_frame_num = pinfo->fd->num;
+ }
+ switch(ndps_prog)
+ {
+ case 0x060976: /* Print */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Bind PSM */
+ foffset = credentials(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000002: /* Bind PA */
+ foffset = credentials(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_retrieve_restrictions, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_bind_security_option_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Security %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ if (length!=0)
+ {
+ proto_tree_add_uint(atree, hf_bind_security, tvb, foffset, 4, length);
+ }
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000003: /* Unbind */
+ proto_tree_add_item(ndps_tree, hf_ndps_object, tvb, foffset,
+ 4, FALSE);
+ break;
+ case 0x00000004: /* Print */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ print_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_print_arg, tvb, foffset, 4, print_type);
+ foffset += 4;
+ switch (print_type)
+ {
+ case 0: /* Create Job */
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_sub_complete, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Transfer Method");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ for (j = 1 ; j <= number_of_items2; j++ )
+ {
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Value %u", j);
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = attribute_value(tvb, ctree, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ }
+ proto_tree_add_item(btree, hf_ndps_qualifier, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Document Content");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Type %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ foffset += align_4(tvb, foffset);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ doc_content = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_doc_content, tvb, foffset, 4, doc_content);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Value %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ if (doc_content==0)
+ {
+ length = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_included_doc_len, tvb, foffset, 4, length);
+ foffset += 4;
+ length_remaining = tvb_length_remaining(tvb, foffset);
+ if (length_remaining == -1 || length > (guint32) length_remaining) /* Segmented Data */
+ {
+ proto_tree_add_item(btree, hf_ndps_data, tvb, foffset, -1, FALSE);
+ return;
+ }
+ if (length!=0)
+ {
+ proto_tree_add_item(btree, hf_ndps_included_doc, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ }
+ else
+ {
+ foffset = ndps_string(tvb, hf_ndps_ref_name, btree, foffset, NULL, 0);
+ foffset = name_or_id(tvb, btree, foffset);
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset += 4;
+ if (align_4(tvb, foffset)>0) {
+ foffset += align_4(tvb, foffset);
+ }
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Document Type");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ for (j = 1 ; j <= number_of_items2; j++ )
+ {
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Value %u", j);
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = attribute_value(tvb, ctree, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ }
+ proto_tree_add_item(btree, hf_ndps_qualifier, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Document Attributes");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset); /* Document Attributes */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ break;
+ case 1: /* Add Job */
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_sub_complete, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Transfer Method");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_transfer_methods, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Method %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset); /* Transfer Method */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_tree_add_item(ndps_tree, hf_doc_content, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Document Type");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_doc_types, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Type %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset); /* Document Type */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ foffset += align_4(tvb, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Document Attributes");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset); /* Document Attributes */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ break;
+ case 2: /* Close Job */
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x00000005: /* Modify Job */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_document_number, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Job Modifications");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Modification %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset); /* Job Modifications */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Document Modifications");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Modification %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset); /* Document Modifications */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ break;
+ case 0x00000006: /* Cancel Job */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_document_number, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* XXX - what does this count? */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ /* Start of nameorid */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Cancel Message");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of nameorid */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Retention Period");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_status_flags, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ break;
+ case 0x00000007: /* List Object Attributes */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ list_attr_op = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_attrs_arg, tvb, foffset, 4, list_attr_op);
+ foffset += 4;
+ if (list_attr_op==0) /* Continuation */
+ {
+ length = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_context_len, tvb, foffset, 4, length);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_context, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_tree_add_item(ndps_tree, hf_ndps_abort_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Attribute %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = attribute_value(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ }
+ else /* Specification */
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object Class");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset += 4;
+ foffset += align_4(tvb, foffset);
+ scope = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_scope, tvb, foffset, 4, scope);
+ foffset += 4;
+ if (scope!=0) /* Scope Does not equal 0 */
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Selector Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset); /* Start of NWDPSelector */
+ proto_tree_add_uint(atree, hf_ndps_num_options, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Option %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentification(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset += align_4(tvb, foffset);
+ filter_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_filter, tvb, foffset, 4, filter_type);
+ foffset += 4;
+ /*if (filter_type == 0 || filter_type == 3 )
+ {
+ foffset = filteritem(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Filter Items");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ foffset = filteritem(tvb, ndps_tree, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }*/
+ proto_tree_add_item(ndps_tree, hf_ndps_time_limit, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_count_limit, tvb, foffset, 4, FALSE);
+ foffset += 4; /* End of NWDPSelector */
+ }
+ foffset += 4; /* Don't know what this is */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Requested Attributes");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset); /* Start of NWDPObjectIdentifierSet */
+ proto_tree_add_uint(atree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset); /* End of NWDPObjectIdentifierSet */
+ if (number_of_items == 0)
+ {
+ break;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_operator, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000008: /* Promote Job */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NWDPPrtContainedObjectId */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Job ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ /* Start of nameorid */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of nameorid */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000009: /* Interrupt */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ job_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_interrupt_job_type, tvb, foffset, 4, job_type);
+ foffset += 4;
+ if (job_type==0)
+ {
+ /* Start of NWDPPrtContainedObjectId */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Job ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ }
+ else
+ {
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ }
+ /* Start of nameorid */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Interrupt Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of nameorid */
+ /* Start of NWDPPrtContainedObjectId */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Interrupting Job");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000000a: /* Pause */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ job_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_pause_job_type, tvb, foffset, 4, job_type);
+ foffset += 4;
+ if (job_type==0)
+ {
+ /* Start of NWDPPrtContainedObjectId */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Job ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ }
+ else
+ {
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ }
+ /* Start of nameorid */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Pause Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of nameorid */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000000b: /* Resume */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NWDPPrtContainedObjectId */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Job ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ /* Start of nameorid */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Resume Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of nameorid */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000000c: /* Clean */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of nameorid */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Clean Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of nameorid */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000000d: /* Create */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object Class");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentification(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_force, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Reference Object Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentification(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Start of AttributeSet */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object Attribute");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset); /* Object Attribute Set */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of AttributeSet */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000000e: /* Delete */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object Class");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentification(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000000f: /* Disable PA */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Disable PA Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000010: /* Enable PA */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Enable PA Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000011: /* Resubmit Jobs */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ foffset = address_item(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_resubmit_op_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Resubmit Job");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset); /* Start of ResubmitJob Set */
+ proto_tree_add_uint(atree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ /* Start of NWDPPrtContainedObjectId */
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Job ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, btree, foffset, NULL, 0);
+ proto_tree_add_item(btree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ proto_tree_add_item(atree, hf_ndps_document_number, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of AttributeSet */
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Job Attributes");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ for (j = 1 ; j <= number_of_items2; j++ )
+ {
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Attribute %u", j);
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = attribute_value(tvb, ctree, foffset); /* Object Attribute Set */
+ proto_item_set_end(citem, tvb, foffset);
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of AttributeSet */
+ /* Start of AttributeSet */
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Document Attributes");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ for (j = 1 ; j <= number_of_items2; j++ )
+ {
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Attribute %u", j);
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = attribute_value(tvb, ctree, foffset); /* Object Attribute Set */
+ proto_item_set_end(citem, tvb, foffset);
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of AttributeSet */
+ }
+ proto_item_set_end(aitem, tvb, foffset); /* End of ResubmitJob Set */
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Resubmit Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000012: /* Set */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object Class");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentification(tvb, atree, foffset);
+ /* Start of AttributeSet */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Attribute Modifications");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Modification %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset); /* Object Attribute Set */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of AttributeSet */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000013: /* Shutdown PA */
+ case 0x0000001e: /* Shutdown PSM */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_shutdown_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Shutdown Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ case 0x00000014: /* Startup PA */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Startup Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000015: /* Reorder Job */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NWDPPrtContainedObjectId */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Job Identification");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ /* Start of NWDPPrtContainedObjectId */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Reference Job ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000016: /* Pause PA */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Pause Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000017: /* Resume PA */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Resume Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000018: /* Transfer Data */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_get_status_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_data, tvb, foffset+4, tvb_get_ntohl(tvb, foffset), FALSE);
+ break;
+ case 0x00000019: /* Device Control */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of Object Identifier */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Operation ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of Object Identifier */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000001a: /* Add Event Profile */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of Eventhandling2 */
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_persistence, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ foffset = ndps_string(tvb, hf_ndps_supplier_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ foffset += align_4(tvb, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Delivery Address");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_delivery_add_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Address %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = address_item(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000001b: /* Remove Event Profile */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 0x0000001c: /* Modify Event Profile */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ supplier_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_boolean(ndps_tree, hf_ndps_supplier_flag, tvb, foffset, 4, supplier_flag);
+ foffset += 4;
+ if (supplier_flag)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Supplier ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ language_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_boolean(ndps_tree, hf_ndps_language_flag, tvb, foffset, 4, language_flag);
+ foffset += 4;
+ if (language_flag)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ method_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_boolean(ndps_tree, hf_ndps_method_flag, tvb, foffset, 4, method_flag);
+ foffset += 4;
+ if (method_flag)
+ {
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ }
+ delivery_address_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_boolean(ndps_tree, hf_ndps_delivery_address_flag, tvb, foffset, 4, delivery_address_flag);
+ foffset += 4;
+ if (delivery_address_flag)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Delivery Address");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = print_address(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000001d: /* List Event Profiles */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ profiles_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_list_profiles_type, tvb, foffset, 4, profiles_type);
+ foffset += 4;
+ if (profiles_type==0) /* Spec */
+ {
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ profiles_choice_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_list_profiles_choice_type, tvb, foffset, 4, profiles_choice_type);
+ foffset += 4;
+ if (profiles_choice_type==0) /* Choice */
+ {
+ foffset = cardinal_seq(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Consumer");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ /* End of NameorID */
+ proto_tree_add_item(atree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_list_profiles_result_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of integeroption */
+ integer_type_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_integer_type_flag, tvb, foffset, 4, integer_type_flag);
+ foffset += 4;
+ if (integer_type_flag!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_integer_type_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ /* End of integeroption */
+ }
+ else /* Cont */
+ {
+ length = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_context_len, tvb, foffset, 4, length);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_context, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_tree_add_item(ndps_tree, hf_ndps_abort_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ break;
+ case 0x0000001f: /* Cancel PSM Shutdown */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Cancel Shutdown Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000020: /* Set Printer DS Information */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_ds_info_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_printer_name, ndps_tree, foffset, NULL, 0);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "DS Object Name");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ break;
+ case 0x00000021: /* Clean User Jobs */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Clean Message Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = commonarguments(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000022: /* Map GUID to NDS Name */
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_guid, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ break;
+ case 0x00000023: /* AddEventProfile2 */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of Eventhandling2 */
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_persistence, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Consumer Name");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset = ndps_string(tvb, hf_ndps_supplier_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ foffset += align_4(tvb, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Delivery Address");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_delivery_add_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Address %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = address_item(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Account");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Start of object identifier set */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Notify Attributes");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of object identifier set */
+ proto_tree_add_item(ndps_tree, hf_notify_time_interval, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_notify_sequence_number, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_notify_lease_exp_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_notify_printer_uri, ndps_tree, foffset, NULL, 0);
+ /* End of Eventhandling2 */
+ break;
+ case 0x00000024: /* ListEventProfiles2 */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ profiles_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_list_profiles_type, tvb, foffset, 4, profiles_type);
+ foffset += 4;
+ if (profiles_type==0) /* Spec */
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Supplier Alias");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ profiles_choice_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_list_profiles_choice_type, tvb, foffset, 4, profiles_choice_type);
+ foffset += 4;
+ if (profiles_choice_type==0) /* Choice */
+ {
+ foffset = cardinal_seq(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Consumer");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_list_profiles_result_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of integeroption */
+ integer_type_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_integer_type_flag, tvb, foffset, 4, integer_type_flag);
+ foffset += 4;
+ if (integer_type_flag!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_integer_type_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ /* End of integeroption */
+ }
+ else /* Cont */
+ {
+ length = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_context_len, tvb, foffset, 4, length);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_context, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_tree_add_item(ndps_tree, hf_ndps_abort_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x060977: /* Broker */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Bind */
+ foffset = credentials(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_retrieve_restrictions, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_bind_security_option_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Security %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_bind_security, tvb, foffset, length, FALSE);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 0x00000002: /* Unbind */
+ break;
+ case 0x00000003: /* List Services */
+ proto_tree_add_item(ndps_tree, hf_ndps_list_services_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 0x00000004: /* Enable Service */
+ proto_tree_add_item(ndps_tree, hf_ndps_service_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Parameters");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_item_bytes, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ break;
+ case 0x00000005: /* Disable Service */
+ proto_tree_add_item(ndps_tree, hf_ndps_list_services_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 0x00000006: /* Down Broker */
+ case 0x00000007: /* Get Broker NDS Object Name */
+ case 0x00000008: /* Get Broker Session Information */
+ default:
+ break;
+ }
+ break;
+ case 0x060978: /* Registry */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Bind */
+ foffset = credentials(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_retrieve_restrictions, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_bind_security_option_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Security %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_bind_security, tvb, foffset, length, FALSE);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 0x00000002: /* Unbind */
+ break;
+ case 0x00000003: /* Register Server */
+ foffset = server_entry(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000004: /* Deregister Server */
+ case 0x00000006: /* Deregister Registry */
+ case 0x0000000b: /* Get Registry NDS Object Name */
+ case 0x0000000c: /* Get Registry Session Information */
+ /* NoOp */
+ break;
+ case 0x00000005: /* Register Registry */
+ foffset = ndps_string(tvb, hf_ndps_registry_name, ndps_tree, foffset, NULL, 0);
+ foffset = print_address(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000007: /* Registry Update */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Add");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Entry %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = server_entry(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Remove");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Entry %u", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = server_entry(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ break;
+ case 0x00000008: /* List Local Servers */
+ case 0x00000009: /* List Servers */
+ case 0x0000000a: /* List Known Registries */
+ local_servers_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_list_local_servers_type, tvb, foffset, 4, local_servers_type);
+ foffset += 4;
+ if (local_servers_type==0)
+ {
+ /* Start of integeroption */
+ integer_type_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_integer_type_flag, tvb, foffset, 4, integer_type_flag);
+ foffset += 4;
+ if (integer_type_flag!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_integer_type_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ /* End of integeroption */
+ }
+ else
+ {
+ length = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_context_len, tvb, foffset, 4, length);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_context, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_tree_add_item(ndps_tree, hf_ndps_abort_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x060979: /* Notify */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Notify Bind */
+ foffset = credentials(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_retrieve_restrictions, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Security %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_bind_security, tvb, foffset, length, FALSE);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 0x00000002: /* Notify Unbind */
+ case 0x0000000a: /* List Supported Languages */
+ case 0x00000010: /* Get Notify NDS Object Name */
+ case 0x00000011: /* Get Notify Session Information */
+ /* NoOp */
+ break;
+ case 0x00000003: /* Register Supplier */
+ foffset = ndps_string(tvb, hf_ndps_supplier_name, ndps_tree, foffset, NULL, 0);
+ /* Start of QualifiedName Set*/
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Supplier Alias %u", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ /* End of QualifiedName Set*/
+ break;
+ case 0x00000004: /* Deregister Supplier */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 0x00000005: /* Add Profile */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Supplier Alias");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Start of Eventhandling */
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_persistence, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Consumer Name");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_delivery_add_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Delivery Addresses");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Address %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = address_item(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ /* End of Eventhandling */
+ break;
+ case 0x00000006: /* Remove Profile */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 0x00000007: /* Modify Profile */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ supplier_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_boolean(ndps_tree, hf_ndps_supplier_flag, tvb, foffset, 4, supplier_flag);
+ foffset += 4;
+ if (supplier_flag)
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Supplier ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ language_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_boolean(ndps_tree, hf_ndps_language_flag, tvb, foffset, 4, language_flag);
+ foffset += 4;
+ if (language_flag)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ method_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_boolean(ndps_tree, hf_ndps_method_flag, tvb, foffset, 4, method_flag);
+ foffset += 4;
+ if (method_flag)
+ {
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ }
+ delivery_address_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_boolean(ndps_tree, hf_ndps_delivery_address_flag, tvb, foffset, 4, delivery_address_flag);
+ foffset += 4;
+ if (delivery_address_flag)
+ {
+ foffset = print_address(tvb, ndps_tree, foffset);
+ }
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000008: /* List Profiles */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ profiles_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_list_profiles_type, tvb, foffset, 4, profiles_type);
+ foffset += 4;
+ if (profiles_type==0) /* Spec */
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Supplier Alias");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ profiles_choice_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_list_profiles_choice_type, tvb, foffset, 4, profiles_choice_type);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ if (profiles_choice_type==0) /* Choice */
+ {
+ foffset = cardinal_seq(tvb, ndps_tree, foffset);
+ }
+ else
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Consumer");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ /* End of NameorID */
+ proto_tree_add_item(atree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_list_profiles_result_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of integeroption */
+ integer_type_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_integer_type_flag, tvb, foffset, 4, integer_type_flag);
+ foffset += 4;
+ if (integer_type_flag!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_integer_type_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ /* End of integeroption */
+ }
+ else /* Cont */
+ {
+ length = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_context_len, tvb, foffset, 4, length);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_context, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_tree_add_item(ndps_tree, hf_ndps_abort_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ break;
+ case 0x00000009: /* Report Event */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of ReportEventItemSet */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Event Items");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Item %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ /* Start of ReportEventItem */
+ proto_tree_add_item(btree, hf_ndps_event_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Containing Class");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = objectidentifier(tvb, ctree, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Containing Object");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = objectidentification(tvb, ctree, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Filter Class");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = objectidentifier(tvb, ctree, foffset);
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Object Class");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = objectidentifier(tvb, ctree, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Object ID");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = objectidentification(tvb, ctree, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Event Object ID");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = objectidentifier(tvb, ctree, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ /* Start of AttributeSet */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Attribute Modifications");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ for (j = 1 ; j <= number_of_items; j++ )
+ {
+ ditem = proto_tree_add_text(ctree, tvb, foffset, -1, "Modification %d", j);
+ dtree = proto_item_add_subtree(ditem, ett_ndps);
+ foffset = attribute_value(tvb, dtree, foffset); /* Object Attribute Set */
+ proto_item_set_end(ditem, tvb, foffset);
+ }
+ proto_item_set_end(citem, tvb, foffset);
+ /* End of AttributeSet */
+ foffset = ndps_string(tvb, hf_ndps_message, btree, foffset, NULL, 0);
+ proto_tree_add_item(btree, hf_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of ReportEventItem */
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of ReportEventItemSet */
+ break;
+ case 0x0000000b: /* Report Notification */
+ /* Start of DestinationSet */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_destinations, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Destination %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ /* Start of Destination */
+ /* Start of NameorID */
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Method ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = name_or_id(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of NameorID */
+ /* Start of NotifyDeliveryAddr */
+ proto_tree_add_item(atree, hf_address_len, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = print_address(tvb, atree, foffset);
+ /* End of NotifyDeliveryAddr */
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of Destination */
+ }
+ /* End of DestinationSet */
+ foffset = ndps_string(tvb, hf_ndps_supplier_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_ndps_event_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Containing Class");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Containing Object");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentification(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Filter Class");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object Class");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentification(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Event Object ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Start of AttributeSet */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Attributes");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of AttributeSet */
+ foffset = ndps_string(tvb, hf_ndps_message, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Account");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ break;
+ case 0x0000000c: /* Add Delivery Method */
+ foffset = ndps_string(tvb, hf_ndps_file_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 0x0000000d: /* Remove Delivery Method */
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ break;
+ case 0x0000000e: /* List Delivery Methods */
+ cred_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(ndps_tree, hf_delivery_method_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ switch (cred_type)
+ {
+ case 0: /* Specification */
+ /* Start of integeroption */
+ integer_type_flag = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_integer_type_flag, tvb, foffset, 4, integer_type_flag);
+ foffset += 4;
+ if (integer_type_flag!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_integer_type_value, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ /* End of integeroption */
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 1: /* Continuation */
+ length = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_context_len, tvb, foffset, 4, length);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_context, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset += (length%2);
+ proto_tree_add_item(ndps_tree, hf_ndps_abort_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x0000000f: /* Get Delivery Method Information */
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x06097a: /* Resman */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Bind */
+ foffset = credentials(tvb, ndps_tree, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_retrieve_restrictions, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_bind_security_option_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Security %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_bind_security, tvb, foffset, length, FALSE);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 0x00000002: /* Unbind */
+ case 0x00000008: /* Get Resource Manager NDS Object Name */
+ case 0x00000009: /* Get Resource Manager Session Information */
+ /* NoOp */
+ break;
+ case 0x00000003: /* Add Resource File */
+ proto_tree_add_item(ndps_tree, hf_packet_count, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_last_packet_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_file_timestamp, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = res_add_input_data(tvb, ndps_tree, foffset);
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Item %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length=tvb_get_ntohl(tvb, foffset);
+ length_remaining = tvb_length_remaining(tvb, foffset);
+ if(length_remaining == -1 || (guint32) length_remaining < length)
+ {
+ return;
+ }
+ proto_tree_add_item(atree, hf_ndps_item_ptr, tvb, foffset, length, FALSE);
+ foffset += length;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 0x00000004: /* Delete Resource File */
+ foffset = res_add_input_data(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000005: /* List Resources */
+ proto_tree_add_item(ndps_tree, hf_ndps_max_items, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_status_flags, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_resource_list_type, tvb, foffset, 4, FALSE);
+ resource_type = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ switch (resource_type)
+ {
+ case 0: /* Print Drivers */
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 1: /* Printer Definitions */
+ case 2: /* Printer Definitions Short */
+ foffset = ndps_string(tvb, hf_ndps_vendor_dir, ndps_tree, foffset, NULL, 0);
+ break;
+ case 3: /* Banner Page Files */
+ proto_tree_add_item(ndps_tree, hf_banner_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 4: /* Font Types */
+ proto_tree_add_item(ndps_tree, hf_font_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 5: /* Printer Driver Files */
+ case 12: /* Printer Driver Files 2 */
+ case 9: /* Generic Files */
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_printer_type, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_printer_manuf, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_inf_file_name, ndps_tree, foffset, NULL, 0);
+ field_len = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_printer_id, tvb, foffset, field_len, FALSE);
+ break;
+ case 6: /* Printer Definition File */
+ case 10: /* Printer Definition File 2 */
+ foffset = ndps_string(tvb, hf_ndps_vendor_dir, ndps_tree, foffset, NULL, 0);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_printer_type, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_printer_manuf, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_inf_file_name, ndps_tree, foffset, NULL, 0);
+ field_len = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_printer_id, tvb, foffset, field_len, FALSE);
+ break;
+ case 7: /* Font Files */
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_font_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_font_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 8: /* Generic Type */
+ case 11: /* Printer Driver Types 2 */
+ case 13: /* Printer Driver Types Archive */
+ foffset = ndps_string(tvb, hf_ndps_printer_manuf, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_printer_type, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_inf_file_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 14: /* Languages Available */
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x00000006: /* Get Resource File */
+ proto_tree_add_item(ndps_tree, hf_get_status_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_res_type, tvb, foffset, 4, FALSE);
+ resource_type = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ switch (resource_type)
+ {
+ case 0: /* Print Drivers */
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_prn_dir_name, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_prn_file_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 1: /* Printer Definitions */
+ foffset = ndps_string(tvb, hf_ndps_vendor_dir, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_prn_file_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 2: /* Banner Page Files */
+ foffset = ndps_string(tvb, hf_ndps_banner_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 3: /* Font Types */
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_font_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_prn_file_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 4: /* Generic Files/ Archive */
+ case 5: /* Printer Driver Archive */
+ proto_tree_add_item(ndps_tree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_prn_dir_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_archive_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x00000007: /* Get Resource File Date */
+ proto_tree_add_item(ndps_tree, hf_ndps_status_flags, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = res_add_input_data(tvb, ndps_tree, foffset);
+ break;
+ case 0x0000000a: /* Set Resource Language Context */
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x06097b: /* Delivery */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Delivery Bind */
+ foffset = credentials(tvb, ndps_tree, foffset);
+ break;
+ case 0x00000002: /* Delivery Unbind */
+ /* NoOp */
+ break;
+ case 0x00000003: /* Delivery Send */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Item %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Supplier ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(btree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ proto_tree_add_item(btree, hf_ndps_event_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Containing Class");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Containing Object");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentification(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Filter Class");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Object Class");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Object ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentification(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Event Object ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ foffset = attribute_value(tvb, atree, foffset);
+ foffset = ndps_string(tvb, hf_ndps_message, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Account");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = qualifiedname(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 0x00000004: /* Delivery Send2 */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Supplier ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(btree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ proto_tree_add_item(atree, hf_ndps_event_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Containing Class");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Containing Object");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentification(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Filter Class");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Object Class");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Object ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentification(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Event Object ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ /* Start of AttributeSet */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ foffset = attribute_value(tvb, btree, foffset);
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of AttributeSet */
+ foffset = ndps_string(tvb, hf_ndps_message, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Account");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = qualifiedname(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+static int
+ndps_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ndps_tree, int foffset)
+{
+ guint32 number_of_items;
+ guint32 ndps_problem_type;
+ guint32 problem_type;
+ guint32 i;
+ proto_tree *atree;
+ proto_item *aitem;
+ proto_tree *btree;
+ proto_item *bitem;
+
+ ndps_problem_type = tvb_get_ntohl(tvb, foffset);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R NDPS - Error");
+ proto_tree_add_uint(ndps_tree, hf_ndps_problem_type, tvb, foffset, 4, ndps_problem_type);
+ foffset += 4;
+ switch(ndps_problem_type)
+ {
+ case 0: /* Security Error */
+ problem_type = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_problem_type, tvb, foffset, 4, problem_type);
+ foffset += 4;
+ if (problem_type==0) /* Standard Error */
+ {
+ proto_tree_add_item(ndps_tree, hf_security_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else /* Extended Error */
+ {
+ /* Start of objectidentifier */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Extended Error");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of objectidentifier */
+ }
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Message");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ break;
+ case 1: /* Service Error */
+ proto_tree_add_item(ndps_tree, hf_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (tvb_get_ntohl(tvb, foffset-4)==0) /* Standard Error */
+ {
+ proto_tree_add_item(ndps_tree, hf_service_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else /* Extended Error */
+ {
+ /* Start of objectidentifier */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Extended Error");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of objectidentifier */
+ }
+ foffset = objectidentification(tvb, ndps_tree, foffset);
+ foffset = attribute_value(tvb, ndps_tree, foffset); /* Object Attribute Set */
+ proto_tree_add_item(ndps_tree, hf_ndps_lib_error, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_other_error, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_other_error_2, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 2: /* Access Error */
+ proto_tree_add_item(ndps_tree, hf_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (tvb_get_ntohl(tvb, foffset-4)==0) /* Standard Error */
+ {
+ proto_tree_add_item(ndps_tree, hf_access_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else /* Extended Error */
+ {
+ /* Start of objectidentifier */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Extended Error");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of objectidentifier */
+ }
+ foffset = objectidentification(tvb, ndps_tree, foffset);
+ break;
+ case 3: /* Printer Error */
+ proto_tree_add_item(ndps_tree, hf_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (tvb_get_ntohl(tvb, foffset-4)==0) /* Standard Error */
+ {
+ proto_tree_add_item(ndps_tree, hf_printer_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else /* Extended Error */
+ {
+ /* Start of objectidentifier */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Extended Error");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of objectidentifier */
+ }
+ foffset = objectidentification(tvb, ndps_tree, foffset);
+ break;
+ case 4: /* Selection Error */
+ proto_tree_add_item(ndps_tree, hf_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (tvb_get_ntohl(tvb, foffset-4)==0) /* Standard Error */
+ {
+ proto_tree_add_item(ndps_tree, hf_selection_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else /* Extended Error */
+ {
+ /* Start of objectidentifier */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Extended Error");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of objectidentifier */
+ }
+ foffset = objectidentification(tvb, ndps_tree, foffset);
+ foffset = attribute_value(tvb, ndps_tree, foffset); /* Object Attribute Set */
+ break;
+ case 5: /* Document Access Error */
+ proto_tree_add_item(ndps_tree, hf_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (tvb_get_ntohl(tvb, foffset-4)==0) /* Standard Error */
+ {
+ proto_tree_add_item(ndps_tree, hf_doc_access_problem_type, tvb, foffset, 4, FALSE);
+ foffset = objectidentifier(tvb, ndps_tree, foffset);
+ }
+ else /* Extended Error */
+ {
+ /* Start of objectidentifier */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Extended Error");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of objectidentifier */
+ }
+ foffset = objectidentification(tvb, ndps_tree, foffset);
+ break;
+ case 6: /* Attribute Error */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Item %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (tvb_get_ntohl(tvb, foffset-4)==0) /* Standard Error */
+ {
+ proto_tree_add_item(atree, hf_attribute_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else /* Extended Error */
+ {
+ /* Start of objectidentifier */
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Extended Error");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentifier(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of objectidentifier */
+ }
+ foffset = attribute_value(tvb, atree, foffset); /* Object Attribute Set */
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 7: /* Update Error */
+ proto_tree_add_item(ndps_tree, hf_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (tvb_get_ntohl(tvb, foffset-4)==0) /* Standard Error */
+ {
+ proto_tree_add_item(ndps_tree, hf_update_problem_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ else /* Extended Error */
+ {
+ /* Start of objectidentifier */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Extended Error");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = objectidentifier(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of objectidentifier */
+ }
+ foffset = objectidentification(tvb, ndps_tree, foffset);
+ break;
+ default:
+ break;
+ }
+ return foffset;
+}
+
+static int
+return_code(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ndps_tree, int foffset)
+{
+ proto_tree_add_item(ndps_tree, hf_ndps_return_code, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (check_col(pinfo->cinfo, COL_INFO) && tvb_get_ntohl(tvb, foffset-4) != 0)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R NDPS - Error");
+ if (tvb_get_ntohl(tvb, foffset-4) == 0)
+ {
+ return foffset;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_ext_error, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ return foffset;
+}
+
+static void
+dissect_ndps_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ndps_tree, int foffset)
+{
+ conversation_t *conversation = NULL;
+ ndps_req_hash_value *request_value = NULL;
+ proto_tree *atree;
+ proto_item *aitem;
+ proto_tree *btree;
+ proto_item *bitem;
+ proto_tree *ctree;
+ proto_item *citem;
+ proto_tree *dtree;
+ proto_item *ditem;
+ guint32 i;
+ guint32 j;
+ guint32 k;
+ guint32 number_of_items=0;
+ guint32 number_of_items2=0;
+ guint32 number_of_items3=0;
+ guint32 length=0;
+ guint32 ndps_func=0;
+ guint32 ndps_prog=0;
+ guint32 error_val=0;
+ guint32 resource_type=0;
+ gint length_remaining;
+
+ if (!pinfo->fd->flags.visited) {
+ /* Find the conversation whence the request would have come. */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_NCP, (guint32) pinfo->destport, (guint32) pinfo->destport, 0);
+ if (conversation != NULL) {
+ /* find the record telling us the request made that caused
+ this reply */
+ request_value = ndps_hash_lookup(conversation, (guint32) pinfo->destport);
+ p_add_proto_data(pinfo->fd, proto_ndps, (void*) request_value);
+ }
+ /* else... we haven't seen an NDPS Request for that conversation. */
+ }
+ else {
+ request_value = p_get_proto_data(pinfo->fd, proto_ndps);
+ }
+ if (request_value) {
+ ndps_prog = request_value->ndps_prog;
+ ndps_func = request_value->ndps_func;
+ proto_tree_add_uint_format(ndps_tree, hf_ndps_reqframe, tvb, 0,
+ 0, request_value->ndps_frame_num,
+ "Response to Request in Frame Number: %u",
+ request_value->ndps_frame_num);
+ }
+
+ if (tvb_length_remaining(tvb, foffset) < 12 && tvb_get_ntohl(tvb, foffset) == 0) /* No error and no return data */
+ {
+ proto_tree_add_uint(ndps_tree, hf_ndps_error_val, tvb, foffset, 4, error_val);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "- Ok");
+ return;
+ }
+ if(ndps_func == 1 || ndps_func == 2)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_rpc_acc_stat, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (tvb_length_remaining(tvb,foffset) < 4 ) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "- Error");
+ return;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_rpc_acc_results, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (tvb_length_remaining(tvb,foffset) < 4) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "- Error");
+ return;
+ }
+ }
+ error_val = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_error_val, tvb, foffset, 4, error_val);
+ foffset += 4;
+ /* Some functions return an error with no data, 0 is ok */
+ if (match_strval(tvb_get_ntohl(tvb, foffset), ndps_error_types) && tvb_length_remaining(tvb,foffset) < 8 && (tvb_get_ntohl(tvb, foffset)!=0))
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_return_code, tvb, foffset, 4, FALSE);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "- Error");
+ return;
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "- Ok");
+ switch(ndps_prog)
+ {
+ case 0x060976: /* Print */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Bind PSM */
+ proto_tree_add_item(ndps_tree, hf_ndps_oid, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ if(tvb_length_remaining(tvb, foffset) < 4)
+ {
+ break;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "PSM Name");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ break;
+ case 0x00000002: /* Bind PA */
+ proto_tree_add_item(ndps_tree, hf_ndps_oid, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ if(tvb_length_remaining(tvb, foffset) < 4)
+ {
+ break;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ }
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ break;
+ case 0x00000003: /* Unbind */
+ break;
+ case 0x00000004: /* Print */
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ndps_tree, foffset, NULL, 0);
+ proto_tree_add_item(ndps_tree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000005: /* Modify Job */
+ case 0x00000006: /* Cancel Job */
+ case 0x00000008: /* Promote Job */
+ case 0x0000000b: /* Resume */
+ case 0x0000000d: /* Create */
+ /* Start of AttributeSet */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object Attribute Set");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset); /* Object Attribute Set */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of AttributeSet */
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000007: /* List Object Attributes */
+ proto_tree_add_item(ndps_tree, hf_answer_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Continuation Option */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Continuation Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_options, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Option %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ length=tvb_get_ntohl(tvb, foffset);
+ length_remaining = tvb_length_remaining(tvb, foffset);
+ if(length_remaining == -1 || (guint32) length_remaining < length)
+ {
+ return;
+ }
+ proto_tree_add_item(btree, hf_ndps_item_ptr, tvb, foffset, length, FALSE);
+ foffset += length;
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Limit Encountered Option */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Limit Encountered Option");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_len, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_limit_enc, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Object Results Set */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object Results Set");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_results, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Result %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = objectidentification(tvb, btree, foffset);
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_num_objects, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ for (j = 1 ; j <= number_of_items2; j++ )
+ {
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Attribute %d", j);
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = objectidentifier(tvb, ctree, foffset);
+ foffset += align_4(tvb, foffset);
+ number_of_items3 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ctree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items3);
+ foffset += 4;
+ for (k = 1 ; k <= number_of_items3; k++ )
+ {
+ ditem = proto_tree_add_text(ctree, tvb, foffset, -1, "Value %d", k);
+ dtree = proto_item_add_subtree(ditem, ett_ndps);
+ foffset = attribute_value(tvb, dtree, foffset);
+ foffset += align_4(tvb, foffset);
+ proto_item_set_end(ditem, tvb, foffset);
+ }
+ proto_tree_add_item(ctree, hf_ndps_qualifier, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(citem, tvb, foffset);
+ }
+ foffset = objectidentifier(tvb, btree, foffset);
+ foffset += 2;
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000009: /* Interrupt */
+ case 0x0000000a: /* Pause */
+ /* Start of NWDPPrtContainedObjectId */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Job ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ /* Start of AttributeSet */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Object Attribute Set");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Attribute %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset); /* Object Attribute Set */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of AttributeSet */
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x0000000c: /* Clean */
+ case 0x0000000e: /* Delete */
+ case 0x0000000f: /* Disable PA */
+ case 0x00000010: /* Enable PA */
+ case 0x00000012: /* Set */
+ case 0x00000013: /* Shutdown PA */
+ case 0x00000014: /* Startup PA */
+ case 0x00000018: /* Transfer Data */
+ case 0x00000019: /* Device Control */
+ case 0x0000001b: /* Remove Event Profile */
+ case 0x0000001c: /* Modify Event Profile */
+ case 0x0000001e: /* Shutdown PSM */
+ case 0x0000001f: /* Cancel PSM Shutdown */
+ case 0x00000020: /* Set Printer DS Information */
+ case 0x00000021: /* Clean User Jobs */
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000011: /* Resubmit Jobs */
+ number_of_items = tvb_get_ntohl(tvb, foffset); /* Start of ResubmitJob Set */
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_jobs, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Resubmit Job");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Job %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ /* Start of NWDPPrtContainedObjectId */
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Old Job");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ctree, foffset, NULL, 0);
+ proto_tree_add_item(ctree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(citem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ /* Start of NWDPPrtContainedObjectId */
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "New Job");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_pa_name, ctree, foffset, NULL, 0);
+ proto_tree_add_item(ctree, hf_local_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(citem, tvb, foffset);
+ /* End of NWDPPrtContainedObjectId */
+ /* Start of AttributeSet */
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ctree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Job Status");
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ for (j = 1 ; j <= number_of_items2; j++ )
+ {
+ ditem = proto_tree_add_text(ctree, tvb, foffset, -1, "Object %d", j);
+ dtree = proto_item_add_subtree(ditem, ett_ndps);
+ foffset = attribute_value(tvb, dtree, foffset); /* Object Attribute Set */
+ proto_item_set_end(ditem, tvb, foffset);
+ }
+ proto_item_set_end(citem, tvb, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of AttributeSet */
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of ResubmitJob Set */
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000015: /* Reorder Job */
+ /* Start of AttributeSet */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Job Status");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Object %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, btree, foffset); /* Object Attribute Set */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of AttributeSet */
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000016: /* Pause PA */
+ case 0x00000017: /* Resume PA */
+ /* Start of AttributeSet */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Printer Status");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Object %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = attribute_value(tvb, atree, foffset); /* Object Attribute Set */
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of AttributeSet */
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x0000001a: /* Add Event Profile */
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x0000001d: /* List Event Profiles */
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ /* Start of Eventhandling */
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_persistence, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Consumer Name");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Delivery Addresses");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_delivery_add_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Address %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = address_item(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ /* End of Eventhandling */
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_continuation_option, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000022: /* Map GUID to NDS Name */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "NDS Printer Name");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000023: /* AddEventProfile2 */
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_notify_lease_exp_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ break;
+ case 0x00000024: /* ListEventProfiles2 */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_events, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Event %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ /* Start of Eventhandling2 */
+ proto_tree_add_item(atree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_ndps_persistence, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Consumer Name");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = qualifiedname(tvb, btree, foffset);
+ foffset = ndps_string(tvb, hf_ndps_supplier_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(bitem, tvb, foffset);
+ /* Start of NameorID */
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Method ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = name_or_id(tvb, btree, foffset);
+ foffset += align_4(tvb, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of NameorID */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_delivery_add_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Delivery Addresses");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Address %d", i);
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = address_item(tvb, ctree, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ foffset = event_object_set(tvb, atree, foffset);
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Account");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = qualifiedname(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ /* Start of object identifier set */
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Notify Attributes");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(btree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ citem = proto_tree_add_text(btree, tvb, foffset, -1, "Attribute %d", i);
+ ctree = proto_item_add_subtree(citem, ett_ndps);
+ foffset = objectidentifier(tvb, ctree, foffset);
+ proto_item_set_end(citem, tvb, foffset);
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of object identifier set */
+ proto_tree_add_item(atree, hf_notify_time_interval, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_notify_sequence_number, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_notify_lease_exp_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_notify_printer_uri, atree, foffset, NULL, 0);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of Eventhandling2 */
+ length = tvb_get_ntohl(tvb, foffset); /* Added on 10-17-03 */
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_continuation_option, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ if(error_val != 0)
+ {
+ foffset = ndps_error(tvb, pinfo, ndps_tree, foffset);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x060977: /* Broker */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Bind */
+ case 0x00000002: /* Unbind */
+ case 0x00000004: /* Enable Service */
+ case 0x00000005: /* Disable Service */
+ case 0x00000006: /* Down Broker */
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000003: /* List Services */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_services, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Service %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_service_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_ndps_service_enabled, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000007: /* Get Broker NDS Object Name */
+ proto_tree_add_item(ndps_tree, hf_ndps_item_count, tvb, foffset,
+ 4, FALSE); /* XXX - what does this count? */
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_broker_name, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_tree, ndps_tree, foffset, NULL, 0);
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000008: /* Get Broker Session Information */
+ default:
+ break;
+ }
+ break;
+ case 0x060978: /* Registry */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Bind */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Attribute %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_set, tvb, foffset, length, FALSE);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 0x00000002: /* Unbind */
+ /* NoOp */
+ break;
+ case 0x00000003: /* Register Server */
+ case 0x00000004: /* Deregister Server */
+ case 0x00000005: /* Register Registry */
+ case 0x00000006: /* Deregister Registry */
+ case 0x00000007: /* Registry Update */
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000008: /* List Local Servers */
+ case 0x00000009: /* List Servers */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Item %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = server_entry(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_continuation_option, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x0000000a: /* List Known Registries */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_item(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_item(ndps_tree, hf_ndps_client_server_type, tvb, foffset, 4, FALSE);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_registry_name, atree, foffset, NULL, 0);
+ foffset = print_address(tvb, atree, foffset);
+ }
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_continuation_option, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x0000000b: /* Get Registry NDS Object Name */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "NDS Printer Name");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x0000000c: /* Get Registry Session Information */
+ proto_tree_add_item(ndps_tree, hf_ndps_session_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x060979: /* Notify */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Notify Bind */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_num_attributes, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Attribute %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(atree, hf_ndps_attribute_set, tvb, foffset, length, FALSE);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 0x00000002: /* Notify Unbind */
+ /* NoOp */
+ break;
+ case 0x00000003: /* Register Supplier */
+ proto_tree_add_item(ndps_tree, hf_ndps_session, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000004: /* Deregister Supplier */
+ case 0x0000000b: /* Report Notification */
+ case 0x0000000d: /* Remove Delivery Method */
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000005: /* Add Profile */
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000006: /* Remove Profile */
+ case 0x00000007: /* Modify Profile */
+ case 0x00000009: /* Report Event */
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000008: /* List Profiles */
+ /* Start of ProfileResultSet */
+ proto_tree_add_item(ndps_tree, hf_ndps_len, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of Eventhandling */
+ proto_tree_add_item(ndps_tree, hf_ndps_profile_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_persistence, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Consumer Name");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = qualifiedname(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_value, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Delivery Addresses");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_delivery_add_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Address %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = address_item(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset = event_object_set(tvb, ndps_tree, foffset);
+ /* End of Eventhandling */
+ /* End of ProfileResultSet */
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_continuation_option, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x0000000a: /* List Supported Languages */
+ /* Start of IntegerSeq */
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, length, FALSE);
+ }
+ foffset += length;
+ /* End of IntegerSeq */
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x0000000c: /* Add Delivery Method */
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x0000000e: /* List Delivery Methods */
+ /* Start of DeliveryMethodSet */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_delivery_method_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ /* Start of DeliveryMethod */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ /* Start of NameorID */
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Method ID");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = name_or_id(tvb, btree, foffset);
+ foffset += align_4(tvb, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ /* End of NameorID */
+ foffset = ndps_string(tvb, hf_ndps_method_name, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_method_ver, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_file_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_ndps_admin_submit, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of DeliveryMethod */
+ }
+ /* End of DeliveryMethodSet */
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x0000000f: /* Get Delivery Method Information */
+ /* Start of DeliveryMethod */
+ /* Start of NameorID */
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Method ID");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = name_or_id(tvb, atree, foffset);
+ /* End of NameorID */
+ foffset = ndps_string(tvb, hf_ndps_method_name, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_method_ver, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_file_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_ndps_admin_submit, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ /* End of DeliveryMethod */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_delivery_add_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Delivery Addresses");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Address %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = address_item(tvb, btree, foffset);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000010: /* Get Notify NDS Object Name */
+ proto_tree_add_item(ndps_tree, hf_ndps_item_count, tvb, foffset,
+ 4, FALSE); /* XXX - what does this count? */
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_broker_name, ndps_tree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_tree, ndps_tree, foffset, NULL, 0);
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000011: /* Get Notify Session Information */
+ proto_tree_add_item(ndps_tree, hf_ndps_get_session_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x06097a: /* Resman */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Bind */
+ length = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ if (length!=0)
+ {
+ proto_tree_add_item(ndps_tree, hf_ndps_attribute_set, tvb, foffset, length, FALSE);
+ }
+ break;
+ case 0x00000002: /* Unbind */
+ /* NoOp */
+ break;
+ case 0x00000003: /* Add Resource File */
+ case 0x00000004: /* Delete Resource File */
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x00000005: /* List Resources */
+ proto_tree_add_item(ndps_tree, hf_ndps_return_code, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (check_col(pinfo->cinfo, COL_INFO) && tvb_get_ntohl(tvb, foffset-4) != 0)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R NDPS - Error");
+ if (tvb_get_ntohl(tvb, foffset-4) != 0)
+ {
+ break;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_status_flags, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_resource_list_type, tvb, foffset, 4, FALSE);
+ resource_type = tvb_get_ntohl(tvb, foffset);
+ foffset += 4;
+ switch (resource_type)
+ {
+ case 0: /* Print Drivers */
+ case 1: /* Printer Definitions */
+ case 2: /* Printer Definitions Short */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_printer_def_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Definition %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ if (tvb_get_ntohl(tvb, foffset)==0) { /* Offset for old type support */
+ foffset += 2;
+ }
+ foffset += 4; /* Item always == 1 */
+ foffset = ndps_string(tvb, hf_ndps_printer_manuf, atree, foffset, NULL, 0);
+ if (tvb_get_ntohl(tvb, foffset)==0) {
+ foffset += 2;
+ }
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_printer_type, atree, foffset, NULL, 0);
+ if (tvb_get_ntohl(tvb, foffset)==0) {
+ foffset += 2;
+ }
+ foffset += 4;
+ foffset = ndps_string(tvb, hf_ndps_inf_file_name, atree, foffset, NULL, 0);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 3: /* Banner Page Files */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Banner %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_banner_name, atree, foffset, NULL, 0);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 4: /* Font Types */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_font_type_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Font %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_font_type_name, atree, foffset, NULL, 0);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 7: /* Font Files */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_font_file_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Font File %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_font_file_name, atree, foffset, NULL, 0);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 5: /* Printer Driver Files */
+ case 12: /* Printer Driver Files 2 */
+ case 9: /* Generic Files */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_printer_def_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "File %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_prn_file_name, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_prn_dir_name, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_inf_file_name, atree, foffset, NULL, 0);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 6: /* Printer Definition File */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_printer_def_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Definition %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_prn_file_name, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_prn_dir_name, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_inf_file_name, atree, foffset, NULL, 0);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Item %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_def_file_name, atree, foffset, NULL, 0);
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_win31_keys, tvb, foffset, 4, number_of_items2);
+ bitem = proto_tree_add_text(atree, tvb, foffset, 4, "Windows 3.1 Keys");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items2; i++ )
+ {
+ foffset = ndps_string(tvb, hf_ndps_windows_key, btree, foffset, NULL, 0);
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_win95_keys, tvb, foffset, 4, number_of_items2);
+ bitem = proto_tree_add_text(atree, tvb, foffset, 4, "Windows 95 Keys");
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items2; i++ )
+ {
+ foffset = ndps_string(tvb, hf_ndps_windows_key, btree, foffset, NULL, 0);
+ }
+ proto_item_set_end(bitem, tvb, foffset);
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 10: /* Printer Definition File 2 */
+ foffset = ndps_string(tvb, hf_ndps_def_file_name, ndps_tree, foffset, NULL, 0);
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_os_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "OS %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_os_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ number_of_items2 = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(atree, hf_ndps_num_windows_keys, tvb, foffset, 4, number_of_items2);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items2; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Key %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_windows_key, btree, foffset, NULL, 0);
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 8: /* Generic Type */
+ case 11: /* Printer Driver Types 2 */
+ case 13: /* Printer Driver Types Archive */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_printer_type_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Type %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ foffset = ndps_string(tvb, hf_ndps_printer_manuf, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_printer_type, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_prn_file_name, atree, foffset, NULL, 0);
+ foffset = ndps_string(tvb, hf_ndps_prn_dir_name, atree, foffset, NULL, 0);
+ proto_tree_add_item(atree, hf_archive_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(atree, hf_archive_file_size, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ case 14: /* Languages Available */
+ number_of_items = tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_language_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Language %d", i);
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ proto_tree_add_item(atree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_item_set_end(aitem, tvb, foffset);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x00000006: /* Get Resource File */
+ proto_tree_add_item(ndps_tree, hf_ndps_return_code, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (check_col(pinfo->cinfo, COL_INFO) && tvb_get_ntohl(tvb, foffset-4) != 0)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R NDPS - Error");
+ if (tvb_get_ntohl(tvb, foffset-4) != 0)
+ {
+ break;
+ }
+ proto_tree_add_item(ndps_tree, hf_get_status_flag, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_file_timestamp, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_ndps_data, tvb, foffset, -1, FALSE);
+ break;
+ case 0x00000007: /* Get Resource File Date */
+ proto_tree_add_item(ndps_tree, hf_ndps_return_code, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (check_col(pinfo->cinfo, COL_INFO) && tvb_get_ntohl(tvb, foffset-4) != 0)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R NDPS - Error");
+ if (tvb_get_ntohl(tvb, foffset-4) != 0)
+ {
+ break;
+ }
+ proto_tree_add_item(ndps_tree, hf_file_timestamp, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ case 0x00000008: /* Get Resource Manager NDS Object Name */
+ foffset = qualifiedname(tvb, ndps_tree, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_error_val, tvb, foffset, 4, error_val);
+ foffset += 4;
+ break;
+ case 0x00000009: /* Get Resource Manager Session Information */
+ proto_tree_add_item(ndps_tree, hf_ndps_get_resman_session_type, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ proto_tree_add_item(ndps_tree, hf_time, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ foffset = return_code(tvb, pinfo, ndps_tree, foffset);
+ break;
+ case 0x0000000a: /* Set Resource Language Context */
+ proto_tree_add_item(ndps_tree, hf_ndps_return_code, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (check_col(pinfo->cinfo, COL_INFO) && tvb_get_ntohl(tvb, foffset-4) != 0)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R NDPS - Error");
+ if (tvb_get_ntohl(tvb, foffset-4) != 0)
+ {
+ break;
+ }
+ proto_tree_add_item(ndps_tree, hf_ndps_language_id, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x06097b: /* Delivery */
+ switch(ndps_func)
+ {
+ case 0x00000001: /* Delivery Bind */
+ proto_tree_add_item(ndps_tree, hf_ndps_return_code, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (check_col(pinfo->cinfo, COL_INFO) && tvb_get_ntohl(tvb, foffset-4) != 0)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R NDPS - Error");
+ break;
+ case 0x00000002: /* Delivery Unbind */
+ /* NoOp */
+ break;
+ case 0x00000003: /* Delivery Send */
+ case 0x00000004: /* Delivery Send2 */
+ proto_tree_add_item(ndps_tree, hf_ndps_return_code, tvb, foffset, 4, FALSE);
+ foffset += 4;
+ if (check_col(pinfo->cinfo, COL_INFO) && tvb_get_ntohl(tvb, foffset-4) != 0)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "R NDPS - Error");
+ if (tvb_get_ntohl(tvb, foffset-4) != 0)
+ {
+ break;
+ }
+ number_of_items=tvb_get_ntohl(tvb, foffset);
+ proto_tree_add_uint(ndps_tree, hf_ndps_item_count, tvb, foffset, 4, number_of_items);
+ foffset += 4;
+ aitem = proto_tree_add_text(ndps_tree, tvb, foffset, -1, "Failed Items");
+ atree = proto_item_add_subtree(aitem, ett_ndps);
+ for (i = 1 ; i <= number_of_items; i++ )
+ {
+ bitem = proto_tree_add_text(atree, tvb, foffset, -1, "Item %d", i);
+ btree = proto_item_add_subtree(bitem, ett_ndps);
+ length=tvb_get_ntohl(tvb, foffset);
+ length_remaining = tvb_length_remaining(tvb, foffset);
+ if(length_remaining == -1 || (guint32) length_remaining < length)
+ {
+ return;
+ }
+ proto_tree_add_item(btree, hf_ndps_item_ptr, tvb, foffset, length, FALSE);
+ foffset += length;
+ proto_item_set_end(bitem, tvb, foffset);
+ }
+ proto_item_set_end(aitem, tvb, foffset);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+void
+proto_register_ndps(void)
+{
+ static hf_register_info hf_ndps[] = {
+ { &hf_ndps_record_mark,
+ { "Record Mark", "ndps.record_mark", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Record Mark", HFILL }},
+
+ { &hf_ndps_packet_type,
+ { "Packet Type", "ndps.packet_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_packet_types), 0x0,
+ "Packet Type", HFILL }},
+
+ { &hf_ndps_length,
+ { "Record Length", "ndps.record_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Record Length", HFILL }},
+
+ { &hf_ndps_xid,
+ { "Exchange ID", "ndps.xid",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Exchange ID", HFILL }},
+
+ { &hf_ndps_rpc_version,
+ { "RPC Version", "ndps.rpc_version",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "RPC Version", HFILL }},
+
+ { &hf_spx_ndps_program,
+ { "NDPS Program Number", "spx.ndps_program",
+ FT_UINT32, BASE_HEX, VALS(spx_ndps_program_vals), 0x0,
+ "NDPS Program Number", HFILL }},
+
+ { &hf_spx_ndps_version,
+ { "Program Version", "spx.ndps_version",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Program Version", HFILL }},
+
+ { &hf_ndps_error,
+ { "NDPS Error", "spx.ndps_error",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "NDPS Error", HFILL }},
+
+ { &hf_spx_ndps_func_print,
+ { "Print Program", "spx.ndps_func_print",
+ FT_UINT32, BASE_HEX, VALS(spx_ndps_print_func_vals), 0x0,
+ "Print Program", HFILL }},
+
+ { &hf_spx_ndps_func_notify,
+ { "Notify Program", "spx.ndps_func_notify",
+ FT_UINT32, BASE_HEX, VALS(spx_ndps_notify_func_vals), 0x0,
+ "Notify Program", HFILL }},
+
+ { &hf_spx_ndps_func_delivery,
+ { "Delivery Program", "spx.ndps_func_delivery",
+ FT_UINT32, BASE_HEX, VALS(spx_ndps_deliver_func_vals), 0x0,
+ "Delivery Program", HFILL }},
+
+ { &hf_spx_ndps_func_registry,
+ { "Registry Program", "spx.ndps_func_registry",
+ FT_UINT32, BASE_HEX, VALS(spx_ndps_registry_func_vals), 0x0,
+ "Registry Program", HFILL }},
+
+ { &hf_spx_ndps_func_resman,
+ { "ResMan Program", "spx.ndps_func_resman",
+ FT_UINT32, BASE_HEX, VALS(spx_ndps_resman_func_vals), 0x0,
+ "ResMan Program", HFILL }},
+
+ { &hf_spx_ndps_func_broker,
+ { "Broker Program", "spx.ndps_func_broker",
+ FT_UINT32, BASE_HEX, VALS(spx_ndps_broker_func_vals), 0x0,
+ "Broker Program", HFILL }},
+
+ { &hf_ndps_num_objects,
+ { "Number of Objects", "ndps.num_objects",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Objects", HFILL }},
+
+ { &hf_ndps_num_attributes,
+ { "Number of Attributes", "ndps.num_attributes",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Attributes", HFILL }},
+
+ { &hf_ndps_sbuffer,
+ { "Server", "ndps.sbuffer",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Server", HFILL }},
+
+ { &hf_ndps_rbuffer,
+ { "Connection", "ndps.rbuffer",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Connection", HFILL }},
+
+ { &hf_ndps_user_name,
+ { "Trustee Name", "ndps.user_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Trustee Name", HFILL }},
+
+ { &hf_ndps_broker_name,
+ { "Broker Name", "ndps.broker_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Broker Name", HFILL }},
+
+ { &hf_ndps_num_results,
+ { "Number of Results", "ndps.num_results",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Results", HFILL }},
+
+ { &hf_ndps_num_options,
+ { "Number of Options", "ndps.num_options",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Options", HFILL }},
+
+ { &hf_ndps_num_jobs,
+ { "Number of Jobs", "ndps.num_jobs",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Jobs", HFILL }},
+
+ { &hf_ndps_pa_name,
+ { "Printer Name", "ndps.pa_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Printer Name", HFILL }},
+
+ { &hf_ndps_tree,
+ { "Tree", "ndps.tree",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Tree", HFILL }},
+
+ { &hf_ndps_reqframe,
+ { "Request Frame", "ndps.reqframe",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Request Frame", HFILL }},
+
+ { &hf_ndps_error_val,
+ { "Return Status", "ndps.error_val",
+ FT_UINT32, BASE_HEX, VALS(ndps_error_types), 0x0,
+ "Return Status", HFILL }},
+
+ { &hf_ndps_object,
+ { "Object ID", "ndps.object",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Object ID", HFILL }},
+
+ { &hf_ndps_cred_type,
+ { "Credential Type", "ndps.cred_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_credential_enum), 0x0,
+ "Credential Type", HFILL }},
+
+ { &hf_ndps_server_name,
+ { "Server Name", "ndps.server_name",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Server Name", HFILL }},
+
+ { &hf_ndps_connection,
+ { "Connection", "ndps.connection",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Connection", HFILL }},
+
+ { &hf_ndps_ext_error,
+ { "Extended Error Code", "ndps.ext_error",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Extended Error Code", HFILL }},
+
+ { &hf_ndps_auth_null,
+ { "Auth Null", "ndps.auth_null",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Auth Null", HFILL }},
+
+ { &hf_ndps_rpc_accept,
+ { "RPC Accept or Deny", "ndps.rpc_acc",
+ FT_UINT32, BASE_HEX, VALS(true_false), 0x0,
+ "RPC Accept or Deny", HFILL }},
+
+ { &hf_ndps_rpc_acc_stat,
+ { "RPC Accept Status", "ndps.rpc_acc_stat",
+ FT_UINT32, BASE_HEX, VALS(accept_stat), 0x0,
+ "RPC Accept Status", HFILL }},
+
+ { &hf_ndps_rpc_rej_stat,
+ { "RPC Reject Status", "ndps.rpc_rej_stat",
+ FT_UINT32, BASE_HEX, VALS(reject_stat), 0x0,
+ "RPC Reject Status", HFILL }},
+
+ { &hf_ndps_rpc_acc_results,
+ { "RPC Accept Results", "ndps.rpc_acc_res",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "RPC Accept Results", HFILL }},
+
+ { &hf_ndps_problem_type,
+ { "Problem Type", "ndps.rpc_prob_type",
+ FT_UINT32, BASE_HEX, VALS(error_type_enum), 0x0,
+ "Problem Type", HFILL }},
+
+ { &hf_security_problem_type,
+ { "Security Problem", "ndps.rpc_sec_prob",
+ FT_UINT32, BASE_HEX, VALS(security_problem_enum), 0x0,
+ "Security Problem", HFILL }},
+
+ { &hf_service_problem_type,
+ { "Service Problem", "ndps.rpc_serv_prob",
+ FT_UINT32, BASE_HEX, VALS(service_problem_enum), 0x0,
+ "Service Problem", HFILL }},
+
+ { &hf_access_problem_type,
+ { "Access Problem", "ndps.rpc_acc_prob",
+ FT_UINT32, BASE_HEX, VALS(access_problem_enum), 0x0,
+ "Access Problem", HFILL }},
+
+ { &hf_printer_problem_type,
+ { "Printer Problem", "ndps.rpc_print_prob",
+ FT_UINT32, BASE_HEX, VALS(printer_problem_enum), 0x0,
+ "Printer Problem", HFILL }},
+
+ { &hf_selection_problem_type,
+ { "Selection Problem", "ndps.rpc_sel_prob",
+ FT_UINT32, BASE_HEX, VALS(selection_problem_enum), 0x0,
+ "Selection Problem", HFILL }},
+
+ { &hf_doc_access_problem_type,
+ { "Document Access Problem", "ndps.rpc_doc_acc_prob",
+ FT_UINT32, BASE_HEX, VALS(doc_access_problem_enum), 0x0,
+ "Document Access Problem", HFILL }},
+
+ { &hf_attribute_problem_type,
+ { "Attribute Problem", "ndps.rpc_attr_prob",
+ FT_UINT32, BASE_HEX, VALS(attribute_problem_enum), 0x0,
+ "Attribute Problem", HFILL }},
+
+ { &hf_update_problem_type,
+ { "Update Problem", "ndps.rpc_update_prob",
+ FT_UINT32, BASE_HEX, VALS(update_problem_enum), 0x0,
+ "Update Problem", HFILL }},
+
+ { &hf_obj_id_type,
+ { "Object ID Type", "ndps.rpc_obj_id_type",
+ FT_UINT32, BASE_HEX, VALS(obj_identification_enum), 0x0,
+ "Object ID Type", HFILL }},
+
+ { &hf_oid_struct_size,
+ { "OID Struct Size", "ndps.rpc_oid_struct_size",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "OID Struct Size", HFILL }},
+
+ { &hf_object_name,
+ { "Object Name", "ndps.ndps_object_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Object Name", HFILL }},
+
+ { &hf_ndps_document_number,
+ { "Document Number", "ndps.ndps_doc_num",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Document Number", HFILL }},
+
+ { &hf_ndps_nameorid,
+ { "Name or ID Type", "ndps.ndps_nameorid",
+ FT_UINT32, BASE_HEX, VALS(nameorid_enum), 0x0,
+ "Name or ID Type", HFILL }},
+
+ { &hf_local_object_name,
+ { "Local Object Name", "ndps.ndps_loc_object_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Local Object Name", HFILL }},
+
+ { &hf_printer_name,
+ { "Printer Name", "ndps.ndps_printer_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Printer Name", HFILL }},
+
+ { &hf_ndps_qualified_name,
+ { "Qualified Name Type", "ndps.ndps_qual_name_type",
+ FT_UINT32, BASE_HEX, VALS(qualified_name_enum), 0x0,
+ "Qualified Name Type", HFILL }},
+
+ { &hf_ndps_qualified_name2,
+ { "Qualified Name Type", "ndps.ndps_qual_name_type2",
+ FT_UINT32, BASE_HEX, VALS(qualified_name_enum2), 0x0,
+ "Qualified Name Type", HFILL }},
+
+ { &hf_ndps_item_count,
+ { "Number of Items", "ndps.ndps_item_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Items", HFILL }},
+
+ { &hf_ndps_num_passwords,
+ { "Number of Passwords", "ndps.num_passwords",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Passwords", HFILL }},
+
+ { &hf_ndps_num_servers,
+ { "Number of Servers", "ndps.num_servers",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Servers", HFILL }},
+
+ { &hf_ndps_num_locations,
+ { "Number of Locations", "ndps.num_locations",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Locations", HFILL }},
+
+ { &hf_ndps_num_areas,
+ { "Number of Areas", "ndps.num_areas",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Areas", HFILL }},
+
+ { &hf_ndps_num_address_items,
+ { "Number of Address Items", "ndps.num_address_items",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Address Items", HFILL }},
+
+ { &hf_ndps_num_job_categories,
+ { "Number of Job Categories", "ndps.num_job_categories",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Job Categories", HFILL }},
+
+ { &hf_ndps_num_page_selects,
+ { "Number of Page Select Items", "ndps.num_page_selects",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Page Select Items", HFILL }},
+
+ { &hf_ndps_num_page_informations,
+ { "Number of Page Information Items", "ndps.num_page_informations",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Page Information Items", HFILL }},
+
+ { &hf_ndps_num_names,
+ { "Number of Names", "ndps.num_names",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Names", HFILL }},
+
+ { &hf_ndps_num_categories,
+ { "Number of Categories", "ndps.num_categories",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Categories", HFILL }},
+
+ { &hf_ndps_num_colorants,
+ { "Number of Colorants", "ndps.num_colorants",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Colorants", HFILL }},
+
+ { &hf_ndps_num_events,
+ { "Number of Events", "ndps.num_events",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Events", HFILL }},
+
+ { &hf_ndps_num_args,
+ { "Number of Arguments", "ndps.num_argss",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Arguments", HFILL }},
+
+ { &hf_ndps_num_transfer_methods,
+ { "Number of Transfer Methods", "ndps.num_transfer_methods",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Transfer Methods", HFILL }},
+
+ { &hf_ndps_num_doc_types,
+ { "Number of Document Types", "ndps.num_doc_types",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Document Types", HFILL }},
+
+ { &hf_ndps_num_destinations,
+ { "Number of Destinations", "ndps.num_destinations",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Destinations", HFILL }},
+
+ { &hf_ndps_qualifier,
+ { "Qualifier", "ndps.ndps_qual",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Qualifier", HFILL }},
+
+ { &hf_ndps_lib_error,
+ { "Lib Error", "ndps.ndps_lib_error",
+ FT_UINT32, BASE_HEX, VALS(ndps_error_types), 0x0,
+ "Lib Error", HFILL }},
+
+ { &hf_ndps_other_error,
+ { "Other Error", "ndps.ndps_other_error",
+ FT_UINT32, BASE_HEX, VALS(ndps_error_types), 0x0,
+ "Other Error", HFILL }},
+
+ { &hf_ndps_other_error_2,
+ { "Other Error 2", "ndps.ndps_other_error_2",
+ FT_UINT32, BASE_HEX, VALS(ndps_error_types), 0x0,
+ "Other Error 2", HFILL }},
+
+ { &hf_ndps_session,
+ { "Session Handle", "ndps.ndps_session",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Session Handle", HFILL }},
+
+ { &hf_ndps_abort_flag,
+ { "Abort?", "ndps.ndps_abort",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Abort?", HFILL }},
+
+ { &hf_obj_attribute_type,
+ { "Value Syntax", "ndps.ndps_attrib_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_attribute_enum), 0x0,
+ "Value Syntax", HFILL }},
+
+ { &hf_ndps_attribute_value,
+ { "Value", "ndps.attribue_value",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Value", HFILL }},
+
+ { &hf_ndps_lower_range,
+ { "Lower Range", "ndps.lower_range",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Lower Range", HFILL }},
+
+ { &hf_ndps_upper_range,
+ { "Upper Range", "ndps.upper_range",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Upper Range", HFILL }},
+
+ { &hf_ndps_n64,
+ { "Value", "ndps.n64",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Value", HFILL }},
+
+ { &hf_ndps_lower_range_n64,
+ { "Lower Range", "ndps.lower_range_n64",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Lower Range", HFILL }},
+
+ { &hf_ndps_upper_range_n64,
+ { "Upper Range", "ndps.upper_range_n64",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Upper Range", HFILL }},
+
+ { &hf_ndps_attrib_boolean,
+ { "Value?", "ndps.ndps_attrib_boolean",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Value?", HFILL }},
+
+ { &hf_ndps_realization,
+ { "Realization Type", "ndps.ndps_realization",
+ FT_UINT32, BASE_HEX, VALS(ndps_realization_enum), 0x0,
+ "Realization Type", HFILL }},
+
+ { &hf_ndps_xdimension_n64,
+ { "X Dimension", "ndps.xdimension_n64",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "X Dimension", HFILL }},
+
+ { &hf_ndps_ydimension_n64,
+ { "Y Dimension", "ndps.xdimension_n64",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Y Dimension", HFILL }},
+
+ { &hf_ndps_dim_value,
+ { "Dimension Value Type", "ndps.ndps_dim_value",
+ FT_UINT32, BASE_HEX, VALS(ndps_dim_value_enum), 0x0,
+ "Dimension Value Type", HFILL }},
+
+ { &hf_ndps_dim_flag,
+ { "Dimension Flag", "ndps.ndps_dim_falg",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Dimension Flag", HFILL }},
+
+ { &hf_ndps_xydim_value,
+ { "XY Dimension Value Type", "ndps.ndps_xydim_value",
+ FT_UINT32, BASE_HEX, VALS(ndps_xydim_value_enum), 0x0,
+ "XY Dimension Value Type", HFILL }},
+
+ { &hf_ndps_location_value,
+ { "Location Value Type", "ndps.ndps_location_value",
+ FT_UINT32, BASE_HEX, VALS(ndps_location_value_enum), 0x0,
+ "Location Value Type", HFILL }},
+
+ { &hf_ndps_xmin_n64,
+ { "Minimum X Dimension", "ndps.xmin_n64",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Minimum X Dimension", HFILL }},
+
+ { &hf_ndps_xmax_n64,
+ { "Maximum X Dimension", "ndps.xmax_n64",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Maximum X Dimension", HFILL }},
+
+ { &hf_ndps_ymin_n64,
+ { "Minimum Y Dimension", "ndps.ymin_n64",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Minimum Y Dimension", HFILL }},
+
+ { &hf_ndps_ymax_n64,
+ { "Maximum Y Dimension", "ndps.ymax_n64",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Maximum Y Dimension", HFILL }},
+
+ { &hf_ndps_edge_value,
+ { "Edge Value", "ndps.ndps_edge_value",
+ FT_UINT32, BASE_HEX, VALS(ndps_edge_value_enum), 0x0,
+ "Edge Value", HFILL }},
+
+ { &hf_ndps_cardinal_or_oid,
+ { "Cardinal or OID", "ndps.ndps_car_or_oid",
+ FT_UINT32, BASE_HEX, VALS(ndps_card_or_oid_enum), 0x0,
+ "Cardinal or OID", HFILL }},
+
+ { &hf_ndps_cardinal_name_or_oid,
+ { "Cardinal Name or OID", "ndps.ndps_car_name_or_oid",
+ FT_UINT32, BASE_HEX, VALS(ndps_card_name_or_oid_enum), 0x0,
+ "Cardinal Name or OID", HFILL }},
+
+ { &hf_ndps_integer_or_oid,
+ { "Integer or OID", "ndps.ndps_integer_or_oid",
+ FT_UINT32, BASE_HEX, VALS(ndps_integer_or_oid_enum), 0x0,
+ "Integer or OID", HFILL }},
+
+ { &hf_ndps_profile_id,
+ { "Profile ID", "ndps.ndps_profile_id",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Profile ID", HFILL }},
+
+ { &hf_ndps_persistence,
+ { "Persistence", "ndps.ndps_persistence",
+ FT_UINT32, BASE_HEX, VALS(ndps_persistence_enum), 0x0,
+ "Persistence", HFILL }},
+
+ { &hf_ndps_language_count,
+ { "Number of Languages", "ndps.ndps_language_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Languages", HFILL }},
+
+ { &hf_ndps_language_id,
+ { "Language ID", "ndps.ndps_lang_id",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Language ID", HFILL }},
+
+ { &hf_address_type,
+ { "Address Type", "ndps.ndps_address_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_address_type_enum), 0x0,
+ "Address Type", HFILL }},
+
+ { &hf_ndps_address,
+ { "Address", "ndps.ndps_address",
+ FT_UINT32, BASE_HEX, VALS(ndps_address_enum), 0x0,
+ "Address", HFILL }},
+
+ { &hf_ndps_add_bytes,
+ { "Address Bytes", "ndps.add_bytes",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Address Bytes", HFILL }},
+
+ { &hf_ndps_event_type,
+ { "Event Type", "ndps.ndps_event_type",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Event Type", HFILL }},
+
+ { &hf_ndps_event_object_identifier,
+ { "Event Object Type", "ndps.ndps_event_object_identifier",
+ FT_UINT32, BASE_HEX, VALS(ndps_event_object_enum), 0x0,
+ "Event Object Type", HFILL }},
+
+ { &hf_ndps_octet_string,
+ { "Octet String", "ndps.octet_string",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Octet String", HFILL }},
+
+ { &hf_ndps_scope,
+ { "Scope", "ndps.scope",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Scope", HFILL }},
+
+ { &hf_address_len,
+ { "Address Length", "ndps.addr_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Address Length", HFILL }},
+
+ { &hf_ndps_net,
+ { "IPX Network", "ndps.net",
+ FT_IPXNET, BASE_NONE, NULL, 0x0,
+ "Scope", HFILL }},
+
+ { &hf_ndps_node,
+ { "Node", "ndps.node",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Node", HFILL }},
+
+ { &hf_ndps_socket,
+ { "IPX Socket", "ndps.socket",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "IPX Socket", HFILL }},
+
+ { &hf_ndps_port,
+ { "IP Port", "ndps.port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "IP Port", HFILL }},
+
+ { &hf_ndps_ip,
+ { "IP Address", "ndps.ip",
+ FT_IPv4, BASE_DEC, NULL, 0x0,
+ "IP Address", HFILL }},
+
+ { &hf_ndps_server_type,
+ { "NDPS Server Type", "ndps.ndps_server_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_server_type_enum), 0x0,
+ "NDPS Server Type", HFILL }},
+
+ { &hf_ndps_num_services,
+ { "Number of Services", "ndps.ndps_num_services",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Services", HFILL }},
+
+ { &hf_ndps_service_type,
+ { "NDPS Service Type", "ndps.ndps_service_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_service_type_enum), 0x0,
+ "NDPS Service Type", HFILL }},
+
+ { &hf_ndps_service_enabled,
+ { "Service Enabled?", "ndps.ndps_service_enabled",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Service Enabled?", HFILL }},
+
+ { &hf_ndps_method_name,
+ { "Method Name", "ndps.method_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Method Name", HFILL }},
+
+ { &hf_ndps_method_ver,
+ { "Method Version", "ndps.method_ver",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Method Version", HFILL }},
+
+ { &hf_ndps_file_name,
+ { "File Name", "ndps.file_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "File Name", HFILL }},
+
+ { &hf_ndps_admin_submit,
+ { "Admin Submit Flag?", "ndps.admin_submit_flag",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Admin Submit Flag?", HFILL }},
+
+ { &hf_ndps_oid,
+ { "Object ID", "ndps.oid",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Object ID", HFILL }},
+
+ { &hf_ndps_object_op,
+ { "Operation", "ndps.ndps_object_op",
+ FT_UINT32, BASE_HEX, VALS(ndps_object_op_enum), 0x0,
+ "Operation", HFILL }},
+
+ { &hf_answer_time,
+ { "Answer Time", "ndps.answer_time",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Answer Time", HFILL }},
+
+ { &hf_oid_asn1_type,
+ { "ASN.1 Type", "ndps.asn1_type",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "ASN.1 Type", HFILL }},
+
+ { &hf_ndps_item_ptr,
+ { "Item Pointer", "ndps.item_ptr",
+ FT_BYTES, BASE_DEC, NULL, 0x0,
+ "Item Pointer", HFILL }},
+
+ { &hf_ndps_len,
+ { "Length", "ndps.ndps_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length", HFILL }},
+
+ { &hf_limit_enc,
+ { "Limit Encountered", "ndps.ndps_limit_enc",
+ FT_UINT32, BASE_HEX, VALS(ndps_limit_enc_enum), 0x0,
+ "Limit Encountered", HFILL }},
+
+ { &hf_ndps_delivery_add_count,
+ { "Number of Delivery Addresses", "ndps.delivery_add_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Delivery Addresses", HFILL }},
+
+ { &hf_ndps_delivery_add_type,
+ { "Delivery Address Type", "ndps.ndps_delivery_add_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_delivery_add_enum), 0x0,
+ "Delivery Address Type", HFILL }},
+
+ { &hf_ndps_criterion_type,
+ { "Criterion Type", "ndps.ndps_criterion_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_attribute_enum), 0x0,
+ "Criterion Type", HFILL }},
+
+ { &hf_ndps_num_ignored_attributes,
+ { "Number of Ignored Attributes", "ndps.num_ignored_attributes",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Ignored Attributes", HFILL }},
+
+ { &hf_ndps_ignored_type,
+ { "Ignored Type", "ndps.ndps_ignored_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_attribute_enum), 0x0,
+ "Ignored Type", HFILL }},
+
+ { &hf_ndps_num_resources,
+ { "Number of Resources", "ndps.ndps_num_resources",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Resources", HFILL }},
+
+ { &hf_ndps_resource_type,
+ { "Resource Type", "ndps.ndps_resource_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_resource_enum), 0x0,
+ "Resource Type", HFILL }},
+
+ { &hf_ndps_identifier_type,
+ { "Identifier Type", "ndps.ndps_identifier_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_identifier_enum), 0x0,
+ "Identifier Type", HFILL }},
+
+ { &hf_ndps_page_flag,
+ { "Page Flag", "ndps.ndps_page_flag",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Page Flag", HFILL }},
+
+ { &hf_ndps_media_type,
+ { "Media Type", "ndps.ndps_media_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_media_enum), 0x0,
+ "Media Type", HFILL }},
+
+ { &hf_ndps_page_size,
+ { "Page Size", "ndps.ndps_page_size",
+ FT_UINT32, BASE_HEX, VALS(ndps_page_size_enum), 0x0,
+ "Page Size", HFILL }},
+
+ { &hf_ndps_direction,
+ { "Direction", "ndps.ndps_direction",
+ FT_UINT32, BASE_HEX, VALS(ndps_pres_direction_enum), 0x0,
+ "Direction", HFILL }},
+
+ { &hf_ndps_page_order,
+ { "Page Order", "ndps.ndps_page_order",
+ FT_UINT32, BASE_HEX, VALS(ndps_page_order_enum), 0x0,
+ "Page Order", HFILL }},
+
+ { &hf_ndps_medium_size,
+ { "Medium Size", "ndps.ndps_medium_size",
+ FT_UINT32, BASE_HEX, VALS(ndps_medium_size_enum), 0x0,
+ "Medium Size", HFILL }},
+
+ { &hf_ndps_long_edge_feeds,
+ { "Long Edge Feeds?", "ndps.ndps_long_edge_feeds",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Long Edge Feeds?", HFILL }},
+
+ { &hf_ndps_inc_across_feed,
+ { "Increment Across Feed", "ndps.inc_across_feed",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Increment Across Feed", HFILL }},
+
+ { &hf_ndps_size_inc_in_feed,
+ { "Size Increment in Feed", "ndps.size_inc_in_feed",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Size Increment in Feed", HFILL }},
+
+ { &hf_ndps_page_orientation,
+ { "Page Orientation", "ndps.ndps_page_orientation",
+ FT_UINT32, BASE_HEX, VALS(ndps_page_orientation_enum), 0x0,
+ "Page Orientation", HFILL }},
+
+ { &hf_ndps_numbers_up,
+ { "Numbers Up", "ndps.ndps_numbers_up",
+ FT_UINT32, BASE_HEX, VALS(ndps_numbers_up_enum), 0x0,
+ "Numbers Up", HFILL }},
+
+ { &hf_ndps_xdimension,
+ { "X Dimension", "ndps.ndps_xdimension",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "X Dimension", HFILL }},
+
+ { &hf_ndps_ydimension,
+ { "Y Dimension", "ndps.ndps_ydimension",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Y Dimension", HFILL }},
+
+ { &hf_ndps_state_severity,
+ { "State Severity", "ndps.ndps_state_severity",
+ FT_UINT32, BASE_HEX, VALS(ndps_state_severity_enum), 0x0,
+ "State Severity", HFILL }},
+
+ { &hf_ndps_training,
+ { "Training", "ndps.ndps_training",
+ FT_UINT32, BASE_HEX, VALS(ndps_training_enum), 0x0,
+ "Training", HFILL }},
+
+ { &hf_ndps_colorant_set,
+ { "Colorant Set", "ndps.ndps_colorant_set",
+ FT_UINT32, BASE_HEX, VALS(ndps_colorant_set_enum), 0x0,
+ "Colorant Set", HFILL }},
+
+ { &hf_ndps_card_enum_time,
+ { "Cardinal, Enum, or Time", "ndps.ndps_card_enum_time",
+ FT_UINT32, BASE_HEX, VALS(ndps_card_enum_time_enum), 0x0,
+ "Cardinal, Enum, or Time", HFILL }},
+
+ { &hf_ndps_attrs_arg,
+ { "List Attribute Operation", "ndps.ndps_attrs_arg",
+ FT_UINT32, BASE_HEX, VALS(ndps_attrs_arg_enum), 0x0,
+ "List Attribute Operation", HFILL }},
+
+ { &hf_ndps_context_len,
+ { "Context Length", "ndps.context_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Context Length", HFILL }},
+
+ { &hf_ndps_context,
+ { "Context", "ndps.context",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Context", HFILL }},
+
+ { &hf_ndps_filter,
+ { "Filter Type", "ndps.ndps_filter",
+ FT_UINT32, BASE_HEX, VALS(ndps_filter_enum), 0x0,
+ "Filter Type", HFILL }},
+
+ { &hf_ndps_item_filter,
+ { "Filter Item Operation", "ndps.ndps_filter_item",
+ FT_UINT32, BASE_HEX, VALS(ndps_filter_item_enum), 0x0,
+ "Filter Item Operation", HFILL }},
+
+ { &hf_ndps_substring_match,
+ { "Substring Match", "ndps.ndps_substring_match",
+ FT_UINT32, BASE_HEX, VALS(ndps_match_criteria_enum), 0x0,
+ "Substring Match", HFILL }},
+
+ { &hf_ndps_time_limit,
+ { "Time Limit", "ndps.ndps_time_limit",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Time Limit", HFILL }},
+
+ { &hf_ndps_count_limit,
+ { "Count Limit", "ndps.ndps_count_limit",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Count Limit", HFILL }},
+
+ { &hf_ndps_operator,
+ { "Operator Type", "ndps.ndps_operator",
+ FT_UINT32, BASE_DEC, VALS(ndps_operator_enum), 0x0,
+ "Operator Type", HFILL }},
+
+ { &hf_ndps_password,
+ { "Password", "ndps.password",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Password", HFILL }},
+
+ { &hf_ndps_retrieve_restrictions,
+ { "Retrieve Restrictions", "ndps.ndps_ret_restrict",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Retrieve Restrictions", HFILL }},
+
+ { &hf_ndps_bind_security_option_count,
+ { "Number of Bind Security Options", "ndps.ndps_bind_security_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Bind Security Options", HFILL }},
+
+ { &hf_bind_security,
+ { "Bind Security Options", "ndps.ndps_bind_security",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Bind Security Options", HFILL }},
+
+ { &hf_ndps_max_items,
+ { "Maximum Items in List", "ndps.ndps_max_items",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Maximum Items in List", HFILL }},
+
+ { &hf_ndps_status_flags,
+ { "Status Flag", "ndps.ndps_status_flags",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Status Flag", HFILL }},
+
+ { &hf_ndps_resource_list_type,
+ { "Resource Type", "ndps.ndps_resource_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_resource_type_enum), 0x0,
+ "Resource Type", HFILL }},
+
+ { &hf_os_count,
+ { "Number of OSes", "ndps.os_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of OSes", HFILL }},
+
+ { &hf_os_type,
+ { "OS Type", "ndps.os_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_os_type_enum), 0x0,
+ "OS Type", HFILL }},
+
+ { &hf_ndps_printer_type_count,
+ { "Number of Printer Types", "ndps.printer_type_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Printer Types", HFILL }},
+
+ { &hf_ndps_printer_type,
+ { "Printer Type", "ndps.prn_type",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Printer Type", HFILL }},
+
+ { &hf_ndps_printer_manuf,
+ { "Printer Manufacturer", "ndps.prn_manuf",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Printer Manufacturer", HFILL }},
+
+ { &hf_ndps_inf_file_name,
+ { "INF File Name", "ndps.inf_file_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "INF File Name", HFILL }},
+
+ { &hf_ndps_vendor_dir,
+ { "Vendor Directory", "ndps.vendor_dir",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Vendor Directory", HFILL }},
+
+ { &hf_banner_type,
+ { "Banner Type", "ndps.banner_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_banner_type_enum), 0x0,
+ "Banner Type", HFILL }},
+
+ { &hf_font_type,
+ { "Font Type", "ndps.font_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_font_type_enum), 0x0,
+ "Font Type", HFILL }},
+
+ { &hf_printer_id,
+ { "Printer ID", "ndps.printer_id",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Printer ID", HFILL }},
+
+ { &hf_ndps_font_name,
+ { "Font Name", "ndps.font_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Font Name", HFILL }},
+
+ { &hf_ndps_return_code,
+ { "Return Code", "ndps.ret_code",
+ FT_UINT32, BASE_HEX, VALS(ndps_error_types), 0x0,
+ "Return Code", HFILL }},
+
+ { &hf_ndps_banner_count,
+ { "Number of Banners", "ndps.banner_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Banners", HFILL }},
+
+ { &hf_ndps_banner_name,
+ { "Banner Name", "ndps.banner_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Banner Name", HFILL }},
+
+ { &hf_ndps_font_type_count,
+ { "Number of Font Types", "ndps.font_type_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Font Types", HFILL }},
+
+ { &hf_font_type_name,
+ { "Font Type Name", "ndps.font_type_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Font Type Name", HFILL }},
+
+ { &hf_ndps_font_file_count,
+ { "Number of Font Files", "ndps.font_file_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Font Files", HFILL }},
+
+ { &hf_font_file_name,
+ { "Font File Name", "ndps.font_file_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Font File Name", HFILL }},
+
+ { &hf_ndps_printer_def_count,
+ { "Number of Printer Definitions", "ndps.printer_def_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Printer Definitions", HFILL }},
+
+ { &hf_ndps_prn_file_name,
+ { "Printer File Name", "ndps.print_file_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Printer File Name", HFILL }},
+
+ { &hf_ndps_prn_dir_name,
+ { "Printer Directory Name", "ndps.print_dir_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Printer Directory Name", HFILL }},
+
+ { &hf_ndps_def_file_name,
+ { "Printer Definition Name", "ndps.print_def_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Printer Definition Name", HFILL }},
+
+ { &hf_ndps_num_win31_keys,
+ { "Number of Windows 3.1 Keys", "ndps.num_win31_keys",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Windows 3.1 Keys", HFILL }},
+
+ { &hf_ndps_num_win95_keys,
+ { "Number of Windows 95 Keys", "ndps.num_win95_keys",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Windows 95 Keys", HFILL }},
+
+ { &hf_ndps_num_windows_keys,
+ { "Number of Windows Keys", "ndps.num_windows_keys",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Windows Keys", HFILL }},
+
+ { &hf_ndps_windows_key,
+ { "Windows Key", "ndps.windows_key",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Windows Key", HFILL }},
+
+ { &hf_archive_type,
+ { "Archive Type", "ndps.archive_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_archive_enum), 0x0,
+ "Archive Type", HFILL }},
+
+ { &hf_archive_file_size,
+ { "Archive File Size", "ndps.archive_size",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Archive File Size", HFILL }},
+
+ { &hf_ndps_segment_overlap,
+ { "Segment overlap", "ndps.segment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Segment overlaps with other segments", HFILL }},
+
+ { &hf_ndps_segment_overlap_conflict,
+ { "Conflicting data in segment overlap", "ndps.segment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Overlapping segments contained conflicting data", HFILL }},
+
+ { &hf_ndps_segment_multiple_tails,
+ { "Multiple tail segments found", "ndps.segment.multipletails",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Several tails were found when desegmenting the packet", HFILL }},
+
+ { &hf_ndps_segment_too_long_segment,
+ { "Segment too long", "ndps.segment.toolongsegment", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Segment contained data past end of packet", HFILL }},
+
+ { &hf_ndps_segment_error,
+ {"Desegmentation error", "ndps.segment.error", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "Desegmentation error due to illegal segments", HFILL }},
+
+ { &hf_ndps_segment,
+ { "NDPS Fragment", "ndps.fragment", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "NDPS Fragment", HFILL }},
+
+ { &hf_ndps_segments,
+ { "NDPS Fragments", "ndps.fragments", FT_NONE, BASE_NONE,
+ NULL, 0x0, "NDPS Fragments", HFILL }},
+
+ { &hf_ndps_data,
+ { "[Data]", "ndps.data", FT_NONE, BASE_NONE,
+ NULL, 0x0, "[Data]", HFILL }},
+
+ { &hf_get_status_flag,
+ { "Get Status Flag", "ndps.get_status_flags",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Get Status Flag", HFILL }},
+
+ { &hf_res_type,
+ { "Resource Type", "ndps.res_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_res_type_enum), 0x0,
+ "Resource Type", HFILL }},
+
+ { &hf_file_timestamp,
+ { "File Time Stamp", "ndps.file_time_stamp",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "File Time Stamp", HFILL }},
+
+ { &hf_print_arg,
+ { "Print Type", "ndps.print_arg",
+ FT_UINT32, BASE_DEC, VALS(ndps_print_arg_enum), 0x0,
+ "Print Type", HFILL }},
+
+ { &hf_sub_complete,
+ { "Submission Complete?", "ndps.sub_complete", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Submission Complete?", HFILL }},
+
+ { &hf_doc_content,
+ { "Document Content", "ndps.doc_content",
+ FT_UINT32, BASE_DEC, VALS(ndps_doc_content_enum), 0x0,
+ "Document Content", HFILL }},
+
+ { &hf_ndps_doc_name,
+ { "Document Name", "ndps.doc_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Document Name", HFILL }},
+
+ { &hf_local_id,
+ { "Local ID", "ndps.local_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Local ID", HFILL }},
+
+ { &hf_ndps_included_doc_len,
+ { "Included Document Length", "ndps.included_doc_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Included Document Length", HFILL }},
+
+ { &hf_ndps_included_doc,
+ { "Included Document", "ndps.included_doc",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Included Document", HFILL }},
+
+ { &hf_ndps_ref_name,
+ { "Referenced Document Name", "ndps.ref_doc_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Referenced Document Name", HFILL }},
+
+ { &hf_interrupt_job_type,
+ { "Interrupt Job Identifier", "ndps.interrupt_job_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_interrupt_job_enum), 0x0,
+ "Interrupt Job Identifier", HFILL }},
+
+ { &hf_pause_job_type,
+ { "Pause Job Identifier", "ndps.pause_job_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_pause_job_enum), 0x0,
+ "Pause Job Identifier", HFILL }},
+
+ { &hf_ndps_force,
+ { "Force?", "ndps.ndps_force",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Force?", HFILL }},
+
+ { &hf_resubmit_op_type,
+ { "Resubmit Operation Type", "ndps.resubmit_op_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_resubmit_op_enum), 0x0,
+ "Resubmit Operation Type", HFILL }},
+
+ { &hf_shutdown_type,
+ { "Shutdown Type", "ndps.shutdown_type",
+ FT_UINT32, BASE_DEC, VALS(ndps_shutdown_enum), 0x0,
+ "Shutdown Type", HFILL }},
+
+ { &hf_ndps_supplier_flag,
+ { "Supplier Data?", "ndps.supplier_flag",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Supplier Data?", HFILL }},
+
+ { &hf_ndps_language_flag,
+ { "Language Data?", "ndps.language_flag",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Language Data?", HFILL }},
+
+ { &hf_ndps_method_flag,
+ { "Method Data?", "ndps.method_flag",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Method Data?", HFILL }},
+
+ { &hf_ndps_delivery_address_flag,
+ { "Delivery Address Data?", "ndps.delivery_flag",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Delivery Address Data?", HFILL }},
+
+ { &hf_ndps_list_profiles_type,
+ { "List Profiles Type", "ndps.ndps_list_profiles_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_attrs_arg_enum), 0x0,
+ "List Profiles Type", HFILL }},
+
+ { &hf_ndps_list_profiles_choice_type,
+ { "List Profiles Choice Type", "ndps.ndps_list_profiles_choice_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_list_profiles_choice_enum), 0x0,
+ "List Profiles Choice Type", HFILL }},
+
+ { &hf_ndps_list_profiles_result_type,
+ { "List Profiles Result Type", "ndps.ndps_list_profiles_result_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_list_profiles_result_enum), 0x0,
+ "List Profiles Result Type", HFILL }},
+
+ { &hf_ndps_integer_type_flag,
+ { "Integer Type Flag", "ndps.ndps_integer_type_flag",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Integer Type Flag", HFILL }},
+
+ { &hf_ndps_integer_type_value,
+ { "Integer Type Value", "ndps.ndps_integer_type_value",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Integer Type Value", HFILL }},
+
+ { &hf_ndps_continuation_option,
+ { "Continuation Option", "ndps.ndps_continuation_option",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Continuation Option", HFILL }},
+
+ { &hf_ndps_ds_info_type,
+ { "DS Info Type", "ndps.ndps_ds_info_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_ds_info_enum), 0x0,
+ "DS Info Type", HFILL }},
+
+ { &hf_ndps_guid,
+ { "GUID", "ndps.guid",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "GUID", HFILL }},
+
+ { &hf_ndps_list_services_type,
+ { "Services Type", "ndps.ndps_list_services_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_list_services_enum), 0x0,
+ "Services Type", HFILL }},
+
+ { &hf_ndps_item_bytes,
+ { "Item Ptr", "ndps.item_bytes",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Item Ptr", HFILL }},
+
+ { &hf_ndps_certified,
+ { "Certified", "ndps.certified",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Certified", HFILL }},
+
+ { &hf_ndps_attribute_set,
+ { "Attribute Set", "ndps.attribute_set",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Attribute Set", HFILL }},
+
+ { &hf_ndps_data_item_type,
+ { "Item Type", "ndps.ndps_data_item_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_data_item_enum), 0x0,
+ "Item Type", HFILL }},
+
+ { &hf_info_int,
+ { "Integer Value", "ndps.info_int",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Integer Value", HFILL }},
+
+ { &hf_info_int16,
+ { "16 Bit Integer Value", "ndps.info_int16",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "16 Bit Integer Value", HFILL }},
+
+ { &hf_info_int32,
+ { "32 Bit Integer Value", "ndps.info_int32",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "32 Bit Integer Value", HFILL }},
+
+ { &hf_info_boolean,
+ { "Boolean Value", "ndps.info_boolean",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Boolean Value", HFILL }},
+
+ { &hf_info_string,
+ { "String Value", "ndps.info_string",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "String Value", HFILL }},
+
+ { &hf_info_bytes,
+ { "Byte Value", "ndps.info_bytes",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Byte Value", HFILL }},
+
+ { &hf_ndps_list_local_servers_type,
+ { "Server Type", "ndps.ndps_list_local_server_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_list_local_servers_enum), 0x0,
+ "Server Type", HFILL }},
+
+ { &hf_ndps_registry_name,
+ { "Registry Name", "ndps.registry_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Registry Name", HFILL }},
+
+ { &hf_ndps_client_server_type,
+ { "Client/Server Type", "ndps.ndps_client_server_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_client_server_enum), 0x0,
+ "Client/Server Type", HFILL }},
+
+ { &hf_ndps_session_type,
+ { "Session Type", "ndps.ndps_session_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_session_type_enum), 0x0,
+ "Session Type", HFILL }},
+
+ { &hf_time,
+ { "Time", "ndps.time",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Time", HFILL }},
+
+ { &hf_ndps_supplier_name,
+ { "Supplier Name", "ndps.supplier_name",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Supplier Name", HFILL }},
+
+ { &hf_ndps_message,
+ { "Message", "ndps.message",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Message", HFILL }},
+
+ { &hf_ndps_delivery_method_count,
+ { "Number of Delivery Methods", "ndps.delivery_method_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Delivery Methods", HFILL }},
+
+ { &hf_delivery_method_type,
+ { "Delivery Method Type", "ndps.delivery_method_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_delivery_method_enum), 0x0,
+ "Delivery Method Type", HFILL }},
+
+ { &hf_ndps_get_session_type,
+ { "Session Type", "ndps.ndps_get_session_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_get_session_type_enum), 0x0,
+ "Session Type", HFILL }},
+
+ { &hf_packet_count,
+ { "Packet Count", "ndps.packet_count",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Packet Count", HFILL }},
+
+ { &hf_last_packet_flag,
+ { "Last Packet Flag", "ndps.last_packet_flag",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Last Packet Flag", HFILL }},
+
+ { &hf_ndps_get_resman_session_type,
+ { "Session Type", "ndps.ndps_get_resman_session_type",
+ FT_UINT32, BASE_HEX, VALS(ndps_get_resman_session_type_enum), 0x0,
+ "Session Type", HFILL }},
+
+ { &hf_problem_type,
+ { "Problem Type", "ndps.ndps_get_resman_session_type",
+ FT_UINT32, BASE_HEX, VALS(problem_type_enum), 0x0,
+ "Problem Type", HFILL }},
+
+ { &hf_ndps_num_values,
+ { "Number of Values", "ndps.num_values",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of Values", HFILL }},
+
+ { &hf_ndps_object_ids_7,
+ { "Object ID Definition", "ndps.objectid_def7",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_object_ids_8,
+ { "Object ID Definition", "ndps.objectid_def8",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_object_ids_9,
+ { "Object ID Definition", "ndps.objectid_def9",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_object_ids_10,
+ { "Object ID Definition", "ndps.objectid_def10",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_object_ids_11,
+ { "Object ID Definition", "ndps.objectid_def11",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_object_ids_12,
+ { "Object ID Definition", "ndps.objectid_def12",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_object_ids_13,
+ { "Object ID Definition", "ndps.objectid_def13",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_object_ids_14,
+ { "Object ID Definition", "ndps.objectid_def14",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_object_ids_15,
+ { "Object ID Definition", "ndps.objectid_def15",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_object_ids_16,
+ { "Object ID Definition", "ndps.objectid_def16",
+ FT_NONE, BASE_HEX, NULL,
+ 0x0, "Object ID Definition", HFILL }},
+
+ { &hf_ndps_attribute_time,
+ { "Time", "ndps.attribute_time",
+ FT_ABSOLUTE_TIME, BASE_DEC, NULL, 0x0,
+ "Time", HFILL }},
+
+ { &hf_print_security,
+ { "Printer Security", "ndps.print_security",
+ FT_UINT32, BASE_HEX, VALS(ndps_print_security), 0x0,
+ "Printer Security", HFILL }},
+
+ { &hf_notify_time_interval,
+ { "Notify Time Interval", "ndps.notify_time_interval",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Notify Time Interval", HFILL }},
+
+ { &hf_notify_sequence_number,
+ { "Notify Sequence Number", "ndps.notify_seq_number",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Notify Sequence Number", HFILL }},
+
+ { &hf_notify_lease_exp_time,
+ { "Notify Lease Expiration Time", "ndps.notify_lease_exp_time",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Notify Lease Expiration Time", HFILL }},
+
+ { &hf_notify_printer_uri,
+ { "Notify Printer URI", "ndps.notify_printer_uri",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Notify Printer URI", HFILL }},
+
+ { &hf_level,
+ { "Level", "ndps.level",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Level", HFILL }},
+
+ { &hf_interval,
+ { "Interval", "ndps.interval",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Interval", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_ndps,
+ &ett_ndps_segments,
+ &ett_ndps_segment,
+ };
+ module_t *ndps_module;
+
+ proto_ndps = proto_register_protocol("Novell Distributed Print System", "NDPS", "ndps");
+ proto_register_field_array(proto_ndps, hf_ndps, array_length(hf_ndps));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ndps_module = prefs_register_protocol(proto_ndps, NULL);
+ prefs_register_bool_preference(ndps_module, "desegment_tcp",
+ "Desegment all NDPS messages spanning multiple TCP segments",
+ "Whether the NDPS dissector should desegment all messages spanning multiple TCP segments",
+ &ndps_desegment);
+ prefs_register_bool_preference(ndps_module, "desegment_spx",
+ "Desegment all NDPS messages spanning multiple SPX packets",
+ "Whether the NDPS dissector should desegment all messages spanning multiple SPX packets",
+ &ndps_defragment);
+ prefs_register_bool_preference(ndps_module, "show_oid",
+ "Display NDPS Details",
+ "Whether or not the NDPS dissector should show object id's and other details",
+ &ndps_show_oids);
+
+ register_init_routine(&ndps_init_protocol);
+ register_postseq_cleanup_routine(&ndps_postseq_cleanup);
+}
+
+void
+proto_reg_handoff_ndps(void)
+{
+ dissector_handle_t ndps_handle, ndps_tcp_handle;
+
+ ndps_handle = create_dissector_handle(dissect_ndps_ipx, proto_ndps);
+ ndps_tcp_handle = create_dissector_handle(dissect_ndps_tcp, proto_ndps);
+
+ dissector_add("spx.socket", SPX_SOCKET_PA, ndps_handle);
+ dissector_add("spx.socket", SPX_SOCKET_BROKER, ndps_handle);
+ dissector_add("spx.socket", SPX_SOCKET_SRS, ndps_handle);
+ dissector_add("spx.socket", SPX_SOCKET_ENS, ndps_handle);
+ dissector_add("spx.socket", SPX_SOCKET_RMS, ndps_handle);
+ dissector_add("spx.socket", SPX_SOCKET_NOTIFY_LISTENER, ndps_handle);
+ dissector_add("tcp.port", TCP_PORT_PA, ndps_tcp_handle);
+ dissector_add("tcp.port", TCP_PORT_BROKER, ndps_tcp_handle);
+ dissector_add("tcp.port", TCP_PORT_SRS, ndps_tcp_handle);
+ dissector_add("tcp.port", TCP_PORT_ENS, ndps_tcp_handle);
+ dissector_add("tcp.port", TCP_PORT_RMS, ndps_tcp_handle);
+ dissector_add("tcp.port", TCP_PORT_NOTIFY_LISTENER, ndps_tcp_handle);
+ ndps_data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ndps.h b/epan/dissectors/packet-ndps.h
new file mode 100644
index 0000000000..ac7d23eb90
--- /dev/null
+++ b/epan/dissectors/packet-ndps.h
@@ -0,0 +1,1852 @@
+/* packet-ndps.h
+ * Routines for NetWare's NDPS
+ * Greg Morris <gmorris@novell.com>
+ *
+ * Copyright (c) Novell, Inc. 2002-2003
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#define NDPS_HEADER_LEN 16
+
+#define TCP_PORT_PA 0x0d44 /* NDPS Printer Agent */
+#define TCP_PORT_BROKER 0x0bc6 /* NDPS Broker */
+#define TCP_PORT_SRS 0x0bca /* NDPS Service Registry Service */
+#define TCP_PORT_ENS 0x0bc8 /* NDPS Event Notification Service */
+#define TCP_PORT_RMS 0x0bcb /* NDPS Remote Management Service */
+#define TCP_PORT_NOTIFY_LISTENER 0x0bc9 /* NDPS Notify Listener */
+
+
+/*
+ * The following value strings are definitions of NDPS
+ * Object ID's defined by Novell. Third parties are able
+ * to define their own undocumented OID's. These cannot be
+ * listed and the NDPS dissector will list these as unknown.
+ */
+
+static const value_string object_ids_7[] = { /* 0607 (LENGTH 7)*/
+ /* These values are 0x060728CF3F+(defined number)*/
+ { 0x00000001, "Unknown Object ID" },
+ { 0x01000006, "ID-VC" },
+ { 0x0, NULL },
+};
+
+static const value_string object_ids_8[] = { /* 0608 (LENGTH 8)*/
+ /* These values are 0x28CF3F01+(defined number)*/
+ { 0x00000600, "STATE" },
+ { 0x00000601, "AVAILABILITY" },
+ { 0x00000602, "GENERIC" },
+ { 0x0000060A, "PRINT QUALITY" },
+ { 0x0000060B, "FONT FIDELITY" },
+ { 0x0000060C, "MEDIUM FIDELITY" },
+ { 0x00000610, "CONTENT ORIENTATION" },
+ { 0x00000612, "JOB STATE" },
+ { 0x00000613, "REASONS" },
+ { 0x00000614, "JOB SCHEDULING" },
+ { 0x00000615, "JOB VALIDATE" },
+ { 0x00000616, "DOCUMENT TYPE" },
+ { 0x00000617, "DOCUMENT STATE" },
+ { 0x00000619, "CONFIDENTIALITY POLICY" },
+ { 0x0000061A, "INTEGRITY POLICY" },
+ { 0x0000061B, "SECURITY LABEL" },
+ { 0x0000061C, "SECURITY POLICY" },
+ { 0x0000061D, "PRINTER RESOLUTION" },
+ { 0x0000061E, "PRINTER STATE" },
+ { 0x00000621, "PRINTER OUTPUT_BIN" },
+ { 0x00000622, "INPUT TRAY" },
+ { 0x00000624, "CHECKPOINT FORMATS" },
+ { 0x00000629, "DISTINGUISHED NAME SYNTAX" },
+ { 0x00000632, "MEDIUM" },
+ { 0x00000634, "MEDIUM TYPE" },
+ { 0x00000635, "MEDIUM SIZE" },
+ { 0x00000636, "MEDIUM COLOR" },
+ { 0x00000637, "MEDIUM TOOTH" },
+ { 0x00000638, "MEDIUM GRAIN" },
+ { 0x00000641, "RESOURCE" },
+ { 0x00000642, "RESOURCE TYPE" },
+ { 0x0000064B, "TRANSFER METHOD" },
+ { 0x0000064C, "TRANSFER METHOD TYPE" },
+ { 0x0000064D, "DOCUMENT REFERENCE TYPE" },
+ { 0x00000650, "DELIVERY METHOD" },
+ { 0x00000654, "AUXILARY PACKAGE" },
+ { 0x00000655, "AUXILARY SHEET" },
+ { 0x0000065A, "FINISHING" },
+ { 0x0000065B, "STITCHING" },
+ { 0x0000065C, "BINDING" },
+ { 0x0000065D, "STITCHING TYPE" },
+ { 0x0000065E, "BINDING TYPE" },
+ { 0x0000065F, "BINDING COLOR" },
+ { 0x00000660, "PERFORATION TYPE" },
+ { 0x00000661, "PERFORATION" },
+ { 0x00000662, "TRIMMING" },
+ { 0x00000663, "PUNCHING" },
+ { 0x00000664, "IMPOSITION" },
+ { 0x00000665, "PLEX" },
+ { 0x00000666, "LOGICAL PAGE ORIGIN" },
+ { 0x00000669, "SCHEDULER" },
+ { 0x0000066E, "SLITTING" },
+ { 0x0000066F, "COVERS" },
+ { 0x00000670, "COVER NAME" },
+ { 0x00000671, "FOLDING" },
+ { 0x00000673, "OUTPUT" },
+ { 0x00000678, "EVENT CLASS" },
+ { 0x00000679, "EVENT ABORTED" },
+ { 0x0000067A, "EVENT ERROR" },
+ { 0x0000067B, "EVENT WARNING" },
+ { 0x0000067C, "EVENT REPORT" },
+ { 0x0, NULL },
+};
+
+static const value_string object_ids_9[] = { /* 060928 (LENGTH 9)*/
+ /* These values are 0xCF3F0100+(defined number)*/
+ { 0x00060001, "READY" },
+ { 0x00060002, "ON REQUEST" },
+ { 0x00060003, "UNAVAILABLE" },
+ { 0x00060004, "UNKNOWN" },
+ { 0x00060005, "BUSY" },
+ { 0x00060006, "INITIALIZING" },
+ { 0x00060007, "TERMINATING" },
+ { 0x00060101, "HIGH AVAILABILITY" },
+ { 0x00060102, "NORMAL AVAILABILITY" },
+ { 0x00060103, "LOW AVAILABILITY" },
+ { 0x00060106, "UNKNOWN AVAILABILITY" },
+ { 0x00060200, "GENERIC NONE" },
+ { 0x00060A00, "DRAFT PRINT QUALITY" },
+ { 0x00060A01, "NORMAL PRINT QUALITY" },
+ { 0x00060A02, "HIGH PRINT QUALITY" },
+ { 0x00060C00, "MEDIUM FIDELITY SIZE" },
+ { 0x00060C01, "MEDIUM FIDELITY COLOR" },
+ { 0x00060C02, "MEDIUM FIDELITY TOOTH" },
+ { 0x00060C03, "MEDIUM FIDELITY GRAIN" },
+ { 0x00060C04, "MEDIUM FIDELITY WEIGHT" },
+ { 0x00060C05, "MEDIUM FIDELITY ARA" },
+ { 0x00061000, "CONTENT ORIENTATION PORTRAIT" },
+ { 0x00061001, "CONTENT ORIENTATION LANDSCAPE" },
+ { 0x00061003, "CONTENT ORIENTATION REVERSE PORTRAIT" },
+ { 0x00061004, "CONTENT ORIENTATION REVERSE LANDSCAPE" },
+ { 0x00061200, "JOB STATE UNKNOWN" },
+ { 0x00061201, "JOB STATE PRE PROCESSING" },
+ { 0x00061204, "JOB STATE PENDING" },
+ { 0x00061205, "JOB STATE PROCESSING" },
+ { 0x00061206, "JOB STATE INTERRUPTED" },
+ { 0x00061209, "JOB STATE RETAINED" },
+ { 0x0006120A, "JOB STATE HELD" },
+ { 0x0006120B, "JOB STATE PAUSED" },
+ { 0x0006120E, "JOB STATE CANCELLED" },
+ { 0x0006120F, "JOB STATE COMPLETED" },
+ { 0x00061210, "JOB STATE PRINTING" },
+ { 0x00061301, "REASONS DOCUMENTS NEEDED" },
+ { 0x00061302, "REASONS JOB HOLD SET" },
+ { 0x00061303, "REASONS JOB PRINTED AFTER SPECIFIED" },
+ { 0x00061304, "REASONS REQESTED RESPONSE NOT READY" },
+ { 0x00061305, "REASONS SUCCESSFULLY COMPLETE" },
+ { 0x00061306, "REASONS COMPLETED WITH WARNING" },
+ { 0x00061307, "REASONS COMPLETED WITH ERROR" },
+ { 0x00061308, "REASONS CANCELED BY USER" },
+ { 0x00061309, "REASONS CANCELED BY OPERATOR" },
+ { 0x0006130A, "REASONS ABORTED BY SYSTEM" },
+ { 0x00061400, "JOB SCHEDULED AFTER COMPLETED" },
+ { 0x00061401, "JOB SCHEDULED BEFORE COMPLETED" },
+ { 0x00061402, "JOB SCHEDULING EITHER" },
+ { 0x00061500, "JOB VALIDATE AND PRINT" },
+ { 0x00061501, "JOB VALIDATE SUBMIT ONLY" },
+ { 0x00061600, "DOCUMENT TYPE IS PRINTABLE" },
+ { 0x00061601, "DOCUMENT TYPE IS FONT" },
+ { 0x00061603, "DOCUMENT TYPE IS OTHER RESOURCE" },
+ { 0x00061700, "DOCUMENT STATE TRANSFER PENDING" },
+ { 0x00061701, "DOCUMENT STATE PENDING" },
+ { 0x00061702, "DOCUMENT STATE PROCESSING" },
+ { 0x00061703, "DOCUMENT STATE COMPLETED" },
+ { 0x00061704, "DOCUMENT STATE PRINTING" },
+ { 0x00061B00, "SECURITY LABEL SHEET TOP" },
+ { 0x00061B01, "SECURITY LABEL NO SHEET TOP" },
+ { 0x00061B02, "SECURITY LABEL SHEET BOTTOM" },
+ { 0x00061B03, "SECURITY LABEL NO SHEET BOTTOM" },
+ { 0x00061B04, "SECURITY LABEL JOB START SHEET" },
+ { 0x00061B05, "SECURITY LABEL JOB END SHEET" },
+ { 0x00061C00, "SECURITY POLICY DISCLOSE" },
+ { 0x00061D00, "PRINTER RESOLUTION LOWEST" },
+ { 0x00061D01, "PRINTER RESOLUTION MEDIUM" },
+ { 0x00061D02, "PRINTER RESOLUTION HIGHEST" },
+ { 0x00061E00, "PRINTER STATE UNKNOWN" },
+ { 0x00061E01, "PRINTER STATE IDLE" },
+ { 0x00061E02, "PRINTER STATE PRINTING" },
+ { 0x00061E03, "PRINTER STATE NEEDS ATTENTION" },
+ { 0x00061E04, "PRINTER STATE PAUSED" },
+ { 0x00061E05, "PRINTER STATE SHUTDOWN" },
+ { 0x00061E06, "PRINTER STATE JOB START WAIT" },
+ { 0x00061E07, "PRINTER STATE JOB END WAIT" },
+ { 0x00061E08, "PRINTER STATE NEEDS KEY OPERATOR" },
+ { 0x00061E09, "PRINTER STATE JOB PASSWORD WAIT" },
+ { 0x00061E0A, "PRINTER STATE TIMED OUT" },
+ { 0x00061E0B, "PRINTER STATE CONNECTING" },
+ { 0x00062100, "OUTPUT BIN TOP" },
+ { 0x00062101, "OUTPUT BIN MIDDLE" },
+ { 0x00062102, "OUTPUT BIN BOTTOM" },
+ { 0x00062103, "OUTPUT BIN SIDE" },
+ { 0x00062104, "OUTPUT BIN FACE UP" },
+ { 0x00062105, "OUTPUT BIN LEFT" },
+ { 0x00062106, "OUTPUT BIN RIGHT" },
+ { 0x00062107, "OUTPUT BIN LARGE" },
+ { 0x00062108, "OUTPUT BIN PRIVATE" },
+ { 0x00062109, "OUTPUT BIN FACE DOWN" },
+ { 0x0006210A, "OUTPUT BIN COLLATOR" },
+ { 0x00062200, "INPUT TRAY TOP" },
+ { 0x00062201, "INPUT TRAY MIDDLE" },
+ { 0x00062202, "INPUT TRAY BOTTOM" },
+ { 0x00062203, "INPUT TRAY ENVELOPE" },
+ { 0x00062204, "INPUT TRAY MANUAL" },
+ { 0x00062205, "INPUT TRAY LARGE CAPACITY" },
+ { 0x00062206, "INPUT TRAY MAIN" },
+ { 0x00062207, "INPUT TRAY SIDE" },
+ { 0x00062400, "CHEKPOINT FORMAT NO CONTEXT" },
+ { 0x00062900, "DISTINGUISHED NAME SYNTAX AUTOMATIC" },
+ { 0x00062901, "DISTINGUISHED NAME SYNTAX X.500" },
+ { 0x00062902, "DISTINGUISHED NAME SYNTAX XFN" },
+ { 0x00062903, "DISTINGUISHED NAME SYNTAX DCE" },
+ { 0x00062904, "DISTINGUISHED NAME SYNTAX CDS" },
+ { 0x00062905, "DISTINGUISHED NAME SYNTAX NIS" },
+ { 0x00062906, "DISTINGUISHED NAME SYNTAX DNS" },
+ { 0x00062907, "DISTINGUISHED NAME SYNTAX DEC NS" },
+ { 0x00062908, "DISTINGUISHED NAME SYNTAX INTERNET MAIL" },
+ { 0x00062909, "DISTINGUISHED NAME SYNTAX XNS" },
+ { 0x00062914, "DISTINGUISHED NAME SYNTAX POSIX" },
+ { 0x00062915, "DISTINGUISHED NAME SYNTAX UNIX" },
+ { 0x00062916, "DISTINGUISHED NAME SYNTAX OS2" },
+ { 0x00062917, "DISTINGUISHED NAME SYNTAX PC DOS" },
+ { 0x00062918, "DISTINGUISHED NAME SYNTAX NT" },
+ { 0x00062919, "DISTINGUISHED NAME SYNTAX MVS" },
+ { 0x0006291A, "DISTINGUISHED NAME SYNTAX VM" },
+ { 0x0006291B, "DISTINGUISHED NAME SYNTAX OS400" },
+ { 0x0006291C, "DISTINGUISHED NAME SYNTAX VMS" },
+ { 0x00063200, "MEDIUM ISO A4 WHITE" },
+ { 0x00063201, "MEDIUM ISO A4 COLORED" },
+ { 0x00063202, "MEDIUM ISO A4 TRANSPARENT" },
+ { 0x0006320A, "MEDIUM ISO A3 WHITE" },
+ { 0x0006320B, "MEDIUM ISO A3 COLORED" },
+ { 0x00063214, "MEDIUM ISO A5 WHITE" },
+ { 0x00063215, "MEDIUM ISO A5 COLORED" },
+ { 0x0006321E, "MEDIUM ISO B4 WHITE" },
+ { 0x0006321F, "MEDIUM ISO B4 COLORED" },
+ { 0x00063228, "MEDIUM ISO B5 WHITE" },
+ { 0x00063229, "MEDIUM ISO B5 COLORED" },
+ { 0x00063232, "MEDIUM NORTH AMERICA LETTER WHITE" },
+ { 0x00063233, "MEDIUM NORTH AMERICA LETTER COLOR" },
+ { 0x00063234, "MEDIUM NORTH AMERICA LETTER TRANSPARENT" },
+ { 0x0006323C, "MEDIUM NORTH AMERICA LEGAL WHITE" },
+ { 0x0006323D, "MEDIUM NORTH AMERICA LEGAL COLORED" },
+ { 0x00063249, "MEDIUM ISO B5 ENVELOPE" },
+ { 0x00063253, "MEDIUM ISO B4 ENVELOPE" },
+ { 0x00063258, "MEDIUM ISO C3 ENVELOPE" },
+ { 0x0006325D, "MEDIUM ISO C4 ENVELOPE" },
+ { 0x00063267, "MEDIUM ISO C5 ENVELOPE" },
+ { 0x0006326C, "MEDIUM ISO C6 ENVELOPE" },
+ { 0x00063271, "MEDIUM ISO DESIGN LONG ENVELOPE" },
+ { 0x0006327B, "MEDIUM NORTH AMERICA 10X13 ENVELOPE" },
+ { 0x00063400, "MEDIUM TYPE STATIONERY" },
+ { 0x00063401, "MEDIUM TYPE TRANSPARENCY" },
+ { 0x00063402, "MEDIUM TYPE ENVELOPE" },
+ { 0x00063403, "MEDIUM TYPE ENVELOPE PLAIN" },
+ { 0x00063404, "MEDIUM TYPE CONTINUOUS LONG" },
+ { 0x00063405, "MEDIUM TYPE CONTINUOUS SHORT" },
+ { 0x00063406, "MEDIUM TYPE TABULATED STOCK" },
+ { 0x00063407, "MEDIUM TYPE MULTI-PART FORMS" },
+ { 0x00063408, "MEDIUM TYPE LABELS" },
+ { 0x00063409, "MEDIUM TYPE ENVELOPE WITH WINDOW" },
+ { 0x0006340A, "MEDIUM TYPE MULTI-LAYER" },
+ { 0x00063500, "MEDIUM SIZE NORTH AMERICA LETTER" },
+ { 0x00063501, "MEDIUM SIZE NORTH AMERICA LEGAL" },
+ { 0x00063502, "MEDIUM SIZE NORTH AMERICA 10X13 ENVELOPE" },
+ { 0x00063503, "MEDIUM SIZE NORTH AMERICA 9X12 ENVELOPE" },
+ { 0x00063504, "MEDIUM SIZE NORTH AMERICA NUMBER 10 ENVELOPE" },
+ { 0x00063505, "MEDIUM SIZE NORTH AMERICA 7X9 ENVELOPE" },
+ { 0x00063506, "MEDIUM SIZE NORTH AMERICA 9X11 ENVELOPE" },
+ { 0x00063507, "MEDIUM SIZE NORTH AMERICA 10X14 ENVELOPE" },
+ { 0x00063508, "MEDIUM SIZE NORTH AMERICA NUMBER 9 ENVELOPE" },
+ { 0x00063509, "MEDIUM SIZE NORTH AMERICA 6X9 ENVELOPE" },
+ { 0x0006350A, "MEDIUM SIZE NORTH AMERICA 10X15 ENVELOPE" },
+ { 0x0006350B, "MEDIUM SIZE A" },
+ { 0x0006350C, "MEDIUM SIZE B" },
+ { 0x0006350D, "MEDIUM SIZE C" },
+ { 0x0006350E, "MEDIUM SIZE D" },
+ { 0x0006350F, "MEDIUM SIZE E" },
+ { 0x00063510, "MEDIUM SIZE MONARCH ENVELOPE" },
+ { 0x00063514, "MEDIUM SIZE ISO A0" },
+ { 0x00063515, "MEDIUM SIZE ISO A1" },
+ { 0x00063516, "MEDIUM SIZE ISO A2" },
+ { 0x00063517, "MEDIUM SIZE ISO A3" },
+ { 0x00063518, "MEDIUM SIZE ISO A4" },
+ { 0x00063519, "MEDIUM SIZE ISO A5" },
+ { 0x0006351A, "MEDIUM SIZE ISO A6" },
+ { 0x0006351B, "MEDIUM SIZE ISO A7" },
+ { 0x0006351C, "MEDIUM SIZE ISO A8" },
+ { 0x0006351D, "MEDIUM SIZE ISO A9" },
+ { 0x0006351E, "MEDIUM SIZE ISO A10" },
+ { 0x00063528, "MEDIUM SIZE ISO B0" },
+ { 0x00063529, "MEDIUM SIZE ISO B1" },
+ { 0x0006352A, "MEDIUM SIZE ISO B2" },
+ { 0x0006352B, "MEDIUM SIZE ISO B3" },
+ { 0x0006352C, "MEDIUM SIZE ISO B4" },
+ { 0x0006352D, "MEDIUM SIZE ISO B5" },
+ { 0x0006352E, "MEDIUM SIZE ISO B6" },
+ { 0x0006352F, "MEDIUM SIZE ISO B7" },
+ { 0x00063530, "MEDIUM SIZE ISO B8" },
+ { 0x00063531, "MEDIUM SIZE ISO B9" },
+ { 0x00063532, "MEDIUM SIZE ISO B10" },
+ { 0x0006353F, "MEDIUM SIZE ISO C3" },
+ { 0x00063540, "MEDIUM SIZE ISO C4" },
+ { 0x00063541, "MEDIUM SIZE ISO C5" },
+ { 0x00063542, "MEDIUM SIZE ISO C6" },
+ { 0x00063543, "MEDIUM SIZE ISO DESIGNATED LANGUAGE" },
+ { 0x00063550, "MEDIUM SIZE JIS B0" },
+ { 0x00063551, "MEDIUM SIZE JIS B1" },
+ { 0x00063552, "MEDIUM SIZE JIS B2" },
+ { 0x00063553, "MEDIUM SIZE JIS B3" },
+ { 0x00063554, "MEDIUM SIZE JIS B4" },
+ { 0x00063555, "MEDIUM SIZE JIS B5" },
+ { 0x00063556, "MEDIUM SIZE JIS B6" },
+ { 0x00063557, "MEDIUM SIZE JIS B7" },
+ { 0x00063558, "MEDIUM SIZE JIS B8" },
+ { 0x00063559, "MEDIUM SIZE JIS B9" },
+ { 0x0006355A, "MEDIUM SIZE JIS B10" },
+ { 0x00063564, "MEDIUM SIZE EXECUTIVE" },
+ { 0x00063565, "MEDIUM SIZE FOLIO" },
+ { 0x00063566, "MEDIUM SIZE INVOICE" },
+ { 0x00063567, "MEDIUM SIZE LEDGER" },
+ { 0x00063568, "MEDIUM SIZE QUARTO" },
+ { 0x00063600, "MEDIUM COLOR WHITE" },
+ { 0x00063601, "MEDIUM COLOR PINK" },
+ { 0x00063602, "MEDIUM COLOR YELLOW" },
+ { 0x00063603, "MEDIUM COLOR BUFF" },
+ { 0x00063604, "MEDIUM COLOR GOLDENROD" },
+ { 0x00063605, "MEDIUM COLOR BLUE" },
+ { 0x00063606, "MEDIUM COLOR GREEN" },
+ { 0x00063607, "MEDIUM COLOR CLEAR" },
+ { 0x00063701, "MEDIUM TOOTH FINE" },
+ { 0x00063702, "MEDIUM TOOTH COARSE" },
+ { 0x00063801, "MEDIUM GRAIN LONG" },
+ { 0x00063802, "MEDIUM GRAIN SHORT" },
+ { 0x00064100, "RESOURCE TYPE" },
+ { 0x00064B00, "TRANSFER METHOD WITH REQUEST" },
+ { 0x00064B01, "TRANSFER METHOD REFERENCE DATA" },
+ { 0x00064B02, "TRANSFER METHOD FTAM BY CLIENT" },
+ { 0x00064B03, "TRANSFER METHOD FTAM BY SERVER" },
+ { 0x00064C00, "TRANSFER METHOD TYPE PUSH" },
+ { 0x00064C01, "TRANSFER METHOD TYPE PULL" },
+ { 0x00064C02, "TRANSFER METHOD TYPE IMMEDIATE" },
+ { 0x00064D00, "DOCUMENT REFERENCE TYPE IMMEDIATE " },
+ { 0x00065000, "DELIVERY METHOD PICK UP" },
+ { 0x00065001, "DELIVERY METHOD SECURE PICK UP" },
+ { 0x00065002, "DELIVERY METHOD OFFICE MAIL" },
+ { 0x00065003, "DELIVERY METHOD POSTAL MAIL" },
+ { 0x00065004, "DELIVERY METHOD NOTIFICATION SERVICE" },
+ { 0x00065005, "DELIVERY METHOD ELECTRONIC MAIL" },
+ { 0x00065006, "DELIVERY METHOD FILE" },
+ { 0x00065008, "DELIVERY METHOD WITH JOB RESULTS" },
+ { 0x00065009, "DELIVERY METHOD PRINTED MATERIAL MAIL" },
+ { 0x0006500A, "DELIVERY METHOD BULK MAIL" },
+ { 0x0006500B, "DELIVERY METHOD XPRS MAIL" },
+ { 0x0006500C, "DELIVERY METHOD BUDGET XPRS MAIL" },
+ { 0x0006500D, "DELIVERY METHOD DOCUMENT FILE" },
+ { 0x0006500E, "DELIVERY METHOD FILE ADDRESSED TO" },
+ { 0x0006500F, "DELIVERY METHOD NONE" },
+ { 0x00065400, "AUXILARY PACKAGE JOB SEPARATORS" },
+ { 0x00065401, "AUXILARY PACKAGE JOB SET START" },
+ { 0x00065402, "AUXILARY PACKAGE JOB SET END" },
+ { 0x00065403, "AUXILARY PACKAGE JOB SET WRAP" },
+ { 0x00065404, "AUXILARY PACKAGE JOB SET START COPY SEPARATORS" },
+ { 0x00065405, "AUXILARY PACKAGE JOB SET END COPY SEPARATORS" },
+ { 0x00065406, "AUXILARY PACKAGE JOB SET WRAP COPY SEPARATORS" },
+ { 0x00065407, "AUXILARY PACKAGE JOB COPY START" },
+ { 0x00065408, "AUXILARY PACKAGE JOB COPY END" },
+ { 0x00065409, "AUXILARY PACKAGE JOB COPY WRAP" },
+ { 0x00065414, "AUXILARY PACKAGE DOCUMENT SEPARATORS" },
+ { 0x00065415, "AUXILARY PACKAGE DOCUMENT SET START" },
+ { 0x00065416, "AUXILARY PACKAGE DOCUMENT SET END" },
+ { 0x00065417, "AUXILARY PACKAGE DOCUMENT SET WRAP" },
+ { 0x00065418, "AUXILARY PACKAGE DOCUMENT SET START COPY SEPARATOR" },
+ { 0x00065419, "AUXILARY PACKAGE DOCUMENT SET END COPY SEPARATOR" },
+ { 0x0006541A, "AUXILARY PACKAGE DOCUMENT SET WRAP COPY SEPARATOR" },
+ { 0x0006541B, "AUXILARY PACKAGE DOCUMENT COPY START" },
+ { 0x0006541C, "AUXILARY PACKAGE DOCUMENT COPY END" },
+ { 0x0006541D, "AUXILARY PACKAGE DOCUMENT COPY WRAP" },
+ { 0x0006550A, "AUXILARY JOB SET START" },
+ { 0x0006550B, "AUXILARY JOB SET SEPARATOR" },
+ { 0x0006550C, "AUXILARY JOB SET END" },
+ { 0x0006550D, "AUXILARY JOB COPY START" },
+ { 0x0006550E, "AUXILARY JOB COPY SEPARATOR" },
+ { 0x0006550F, "AUXILARY JOB COPY END" },
+ { 0x0006551E, "AUXILARY DOCUMENT SET START" },
+ { 0x0006551F, "AUXILARY DOCUMENT SET SEPARATOR" },
+ { 0x00065520, "AUXILARY DOCUMENT SET END" },
+ { 0x00065521, "AUXILARY DOCUMENT COPY START" },
+ { 0x00065522, "AUXILARY DOCUMENT COPY SEPARATOR" },
+ { 0x00065523, "AUXILARY DOCUMENT COPY END" },
+ { 0x00065A00, "FINISHING STAPLE" },
+ { 0x00065A01, "FINISHING STAPLE TOP LEFT" },
+ { 0x00065A02, "FINISHING STAPLE BOTTOM LEFT" },
+ { 0x00065A03, "FINISHING STAPLE TOP RIGHT" },
+ { 0x00065A04, "FINISHING STAPLE BOTTOM RIGHT" },
+ { 0x00065A05, "FINISHING SADDLE STITCH" },
+ { 0x00065A06, "FINISHING EDGE STITCH" },
+ { 0x00065A07, "FINISHING PUNCH" },
+ { 0x00065A08, "FINISHING COVER" },
+ { 0x00065A09, "FINISHING BIND" },
+ { 0x00065B00, "STITCHING DEFAULT" },
+ { 0x00065B01, "STITCHING STAPLE" },
+ { 0x00065B02, "STITCHING STAPLE TOP LEFT" },
+ { 0x00065B03, "STITCHING STAPLE BOTTOM LEFT" },
+ { 0x00065B04, "STITCHING STAPLE TOP RIGHT" },
+ { 0x00065B05, "STITCHING STAPLE BOTTOM RIGHT" },
+ { 0x00065B06, "STITCHING SADDLE STITCH" },
+ { 0x00065B07, "STITCHING EDGE STITCH" },
+ { 0x00065B08, "STITCHING EDGE RIGHT" },
+ { 0x00065B09, "STITCHING EDGE TOP" },
+ { 0x00065C00, "BINDING DEFAULT" },
+ { 0x00065D00, "STITCHING TYPE DEFAULT" },
+ { 0x00065D03, "STITCHING TYPE STAPLE" },
+ { 0x00065D04, "STITCHING TYPE EDGE" },
+ { 0x00065D05, "STITCHING TYPE SADDLE" },
+ { 0x00065E00, "BINDING TYPE DEFAULT" },
+ { 0x00065E01, "BINDING TYPE TAPE" },
+ { 0x00065E02, "BINDING TYPE PLASTIC" },
+ { 0x00065E03, "BINDING TYPE VELO" },
+ { 0x00065E04, "BINDING TYPE PERFECT" },
+ { 0x00065E05, "BINDING TYPE SPIRAL" },
+ { 0x00065F00, "BINDING COLOR DEFAULT" },
+ { 0x00065F01, "BINDING COLOR BLACK" },
+ { 0x00065F02, "BINDING COLOR BLUE" },
+ { 0x00065F03, "BINDING COLOR GRAY" },
+ { 0x00065F04, "BINDING COLOR BROWN" },
+ { 0x00066000, "PERFORATION TYPE DEFAULT" },
+ { 0x00066100, "PERFORATION DEFAULT" },
+ { 0x00066200, "TRIMMING DEFAULT" },
+ { 0x00066300, "PUNCHING DEFAULT" },
+ { 0x00066403, "IMPOSITION SIMPLE 2 UP" },
+ { 0x00066404, "IMPOSITION SIMPLE 4 UP" },
+ { 0x00066500, "PLEX SIMPLEX" },
+ { 0x00066501, "PLEX DUPLEX" },
+ { 0x00066502, "PLEX TUMBLE" },
+ { 0x00066600, "LOGICAL PAGE ORIGIN LOWER LEFT" },
+ { 0x00066601, "LOGICAL PAGE ORIGIN LOWER RIGHT" },
+ { 0x00066602, "LOGICAL PAGE ORIGIN UPPER RIGHT" },
+ { 0x00066603, "LOGICAL PAGE ORIGIN UPPER_LEFT" },
+ { 0x00066900, "SCHEDULER FIFO" },
+ { 0x00066901, "SCHEDULER SHORT JOB FIRST" },
+ { 0x00066E00, "SLITTING DEFAULT" },
+ { 0x00066F00, "COVERS DEFAULT" },
+ { 0x00067000, "COVER NAME DEFAULT" },
+ { 0x00067100, "FOLDING DEFAULT" },
+ { 0x00067300, "OUTPUT PAGE COLLATE" },
+ { 0x00067301, "OUTPUT NO PAGE COLLATE" },
+ { 0x00067304, "OUTPUT DECOLLATE" },
+ { 0x00067305, "OUTPUT NO DECOLLATE" },
+ { 0x00067306, "OUTPUT BURST" },
+ { 0x00067307, "OUTPUT NO BURST" },
+ { 0x0006730A, "OUTPUT STACKING DEFAULT" },
+ { 0x00067800, "EVENT CLASS ABORTED" },
+ { 0x00067801, "EVENT CLASS ERROR" },
+ { 0x00067802, "EVENT CLASS WARNING" },
+ { 0x00067803, "EVENT CLASS REPORT" },
+ { 0x00067804, "EVENT CLASS STATE CHANGE" },
+ { 0x00067900, "EVENT JOB ABORTED BY SERVER " },
+ { 0x00067901, "EVENT JOB CANCELED BY OPERATOR" },
+ { 0x00067902, "EVENT JOB CANCELED BY USER" },
+ { 0x00067903, "EVENT DOCUMENT ABORTED BY SERVER " },
+ { 0x00067904, "EVENT DOCUMENT CANCELED BY OPERATOR" },
+ { 0x00067905, "EVENT DOCUMENT CANCELED BY USER" },
+ { 0x00067A03, "EVENT ERROR DEADLINE" },
+ { 0x00067A04, "EVENT ERROR DISCARD TIME" },
+ { 0x00067A05, "EVENT ERROR PRINTER SHUTDOWN" },
+ { 0x00067A06, "EVENT ERROR NO RESOURCES" },
+ { 0x00067A07, "EVENT ERROR UNRECOGNIZED RESOURCE" },
+ { 0x00067A08, "EVENT ERROR NO DOCUMENT" },
+ { 0x00067A09, "EVENT ERROR JOB SUBMIT INCOMPLETE" },
+ { 0x00067A0A, "EVENT ERROR PAGE SELECT" },
+ { 0x00067A0B, "EVENT ERROR DOCUMENT CONTENT" },
+ { 0x00067A63, "EVENT ERROR OTHER" },
+ { 0x00067B00, "EVENT WARNING RESOURCE NEEDS ATTENTION" },
+ { 0x00067B01, "EVENT WARNING RESOURCE NEEDS OPERATOR" },
+ { 0x00067B02, "EVENT WARNING PRINTER SHUTDOWN" },
+ { 0x00067B03, "EVENT WARNING JOB MODIFIED" },
+ { 0x00067B04, "EVENT WARNING ALMOST DEADLINE" },
+ { 0x00067B05, "EVENT WARNING ALMOST DISCARDED" },
+ { 0x00067B06, "EVENT WARNING CRITERIA EXCEEDED" },
+ { 0x00067B07, "EVENT WARNING DUPLICATE ATTRIBUTE IGNORED" },
+ { 0x00067B08, "EVENT WARNING JOB PAUSED" },
+ { 0x00067B09, "EVENT WARNING JOB INTERRUPTED" },
+ { 0x00067B0A, "EVENT WARNING ATTRIBUTE IGNORED" },
+ { 0x00067B63, "EVENT WARNING OTHER" },
+ { 0x00067C00, "EVENT REPORT JOB COMPLETED" },
+ { 0x00067C01, "EVENT REPORT CHECKPOINT TAKEN" },
+ { 0x00067C02, "EVENT REPORT RESOURCE MESSAGE" },
+ { 0x00067C03, "EVENT REPORT JOB DISCARDED" },
+ { 0x00067C04, "EVENT REPORT FILE TRANSFERRED" },
+ { 0x00067C05, "EVENT REPORT JOB PROMOTED" },
+ { 0x00067C06, "EVENT REPORT JOB RESUMED" },
+ { 0x00067C07, "EVENT REPORT PROCESS STARTED" },
+ { 0x00067C08, "EVENT REPORT PRINT STARTED" },
+ { 0x00068149, "CHARACTER_REPERTOIRE" },
+ { 0x0006814A, "CHARACTER_MAPPING" },
+ { 0x0, NULL },
+};
+
+static const value_string object_ids_10[] = {
+ /* These values are 0x3F010000+(defined number)*/
+ { 0x06328105, "MEDIUM NORTH AMERICA 9X12 ENVELOPE" },
+ { 0x06328106, "MEDIUM MONARCH ENVELOPE" },
+ { 0x0632810F, "MEDIUM NORTH AMERICA NUMBER 10 ENVELOPE" },
+ { 0x06328110, "MEDIUM NORTH AMERICA 7X9 ENVELOPE" },
+ { 0x06328111, "MEDIUM NORTH AMERICA 9X11 ENVELOPE" },
+ { 0x06328112, "MEDIUM NORTH AMERICA 10X14 ENVELOPE" },
+ { 0x06328113, "MEDIUM NORTH AMERICA NUMBER 9 ENVELOPE" },
+ { 0x06328114, "MEDIUM NORTH AMERICA 6X9 ENVELOPE" },
+ { 0x06328115, "MEDIUM NORTH AMERICA 10X15 ENVELOPE" },
+ { 0x06328116, "MEDIUM JIS B4 WHITE" },
+ { 0x06328117, "MEDIUM JIS B4 COLORED" },
+ { 0x06328120, "MEDIUM JIS B5 WHITE" },
+ { 0x06328121, "MEDIUM JIS B5 COLORED" },
+ { 0x0632812A, "MEDIUM EXECUTIVE" },
+ { 0x0632812B, "MEDIUM FOLIO" },
+ { 0x0632812C, "MEDIUM INVOICE" },
+ { 0x0632812D, "MEDIUM LEDGER" },
+ { 0x0632812E, "MEDIUM QUARTO" },
+ { 0x06328148, "MEDIUM ISO A0 WHITE" },
+ { 0x06328149, "MEDIUM ISO A1 WHITE" },
+ { 0x0632814A, "MEDIUM ISO A2 WHITE" },
+ { 0x0632814E, "MEDIUM ISO A6 WHITE" },
+ { 0x0632814F, "MEDIUM ISO A7 WHITE" },
+ { 0x06328150, "MEDIUM ISO A8 WHITE" },
+ { 0x06328151, "MEDIUM ISO A9 WHITE" },
+ { 0x06328152, "MEDIUM ISO A10 WHITE" },
+ { 0x0632815C, "MEDIUM ISO B0 WHITE" },
+ { 0x0632815D, "MEDIUM ISO B1 WHITE" },
+ { 0x0632815E, "MEDIUM ISO B2 WHITE" },
+ { 0x0632815F, "MEDIUM ISO B3 WHITE" },
+ { 0x06328162, "MEDIUM ISO B6 WHITE" },
+ { 0x06328163, "MEDIUM ISO B7 WHITE" },
+ { 0x06328164, "MEDIUM ISO B8 WHITE" },
+ { 0x06328165, "MEDIUM ISO B9 WHITE" },
+ { 0x06328166, "MEDIUM ISO B10 WHITE" },
+ { 0x06328170, "MEDIUM JIS B0 WHITE" },
+ { 0x06328171, "MEDIUM JIS B1 WHITE" },
+ { 0x06328172, "MEDIUM JIS B2 WHITE" },
+ { 0x06328173, "MEDIUM JIS B3 WHITE" },
+ { 0x06328176, "MEDIUM JIS B6 WHITE" },
+ { 0x06328177, "MEDIUM JIS B7 WHITE" },
+ { 0x06328178, "MEDIUM JIS B8 WHITE" },
+ { 0x06328179, "MEDIUM JIS B9 WHITE" },
+ { 0x0632817A, "MEDIUM JIS B10 WHITE" },
+ { 0x06328204, "MEDIUM A" },
+ { 0x06328205, "MEDIUM B" },
+ { 0x06328206, "MEDIUM C" },
+ { 0x06328207, "MEDIUM D" },
+ { 0x06328208, "MEDIUM E" },
+ { 0x06328768, "MEDIUM DEFAULT" },
+ /* These values are 0x480186F8+(defined number)*/
+ { 0x37010400, "NDPS OBJECT CLASS" },
+ { 0x37010401, "NDPS VALUE CLASS" },
+ { 0x37010402, "NDPS NDS TOP" },
+ { 0x0, NULL },
+};
+
+static const value_string object_ids_11[] = {
+ /* These values are 0x0186F837+(defined number)*/
+ { 0x01040000, "(Novell) Object Class GENERIC" },
+ { 0x01040001, "(Novell) Object Class JOB" },
+ { 0x01040002, "(Novell) Object Class DOCUMENT" },
+ { 0x01040003, "(Novell) Object Class PRINTER" },
+ { 0x01040004, "(Novell) Object Class MEDIUM" },
+ { 0x01040005, "(Novell) Object Class FONT" },
+ { 0x01040006, "(Novell) Object Class TRANSFER METHOD" },
+ { 0x01040007, "(Novell) Object Class DELIVERY METHOD" },
+ { 0x01040008, "(Novell) Object Class AUXILIARY SHEET" },
+ { 0x01040009, "(Novell) Object Class FINISHING" },
+ { 0x0104000B, "(Novell) Object Class IMPOSITION" },
+ { 0x0104000C, "(Novell) Object Class SCHEDULER" },
+ { 0x0104000E, "(Novell) Object Class RESOURCE" },
+ { 0x0104000F, "(Novell) Object Class INPUT" },
+ { 0x01040010, "(Novell) Object Class OUTPUT" },
+ { 0x01040011, "(Novell) Object Class AUXILIARY SHEET PACKAGE" },
+ { 0x01040012, "(Novell) Object Class MANAGER" },
+ { 0x01040013, "(Novell) Object Class JOB DEFAULTS" },
+ { 0x01040014, "(Novell) Object Class DOCUMENT DEFAULTS" },
+ { 0x01040015, "(Novell) Object Class JOB LIMITS" },
+ { 0x01040016, "(Novell) Object Class DOCUMENT LIMITS" },
+ { 0x01040017, "(Novell) Object Class ABSTRACT EVENT" },
+ { 0x01040018, "(Novell) Object Class RETAINED JOB" },
+ { 0x01040019, "(Novell) Object Class MARKER" },
+ { 0x0104001A, "(Novell) Object Class MEDIA PATH" },
+ { 0x0104001B, "(Novell) Object Class CHANNEL" },
+ { 0x0104001C, "(Novell) Object Class INTERPRETER" },
+ { 0x0104001D, "(Novell) Object Class NOTIFICATION METHOD" },
+ { 0x0104001E, "(Novell) Object Class MARKER SUPPLIES" },
+ { 0x0104001F, "(Novell) Object Class MARKER COLORANT" },
+ { 0x01040020, "(Novell) Object Class COVER" },
+ { 0x01040021, "(Novell) Object Class LIGHT" },
+ { 0x01040022, "(Novell) Object Class BUFFER" },
+ { 0x01040023, "(Novell) Object Class RESOURCE CONTEXT" },
+ { 0x01040024, "(Novell) Object Class ACCOUNTING" },
+ { 0x01040025, "(Novell) Object Class FINISHER DEVICE" },
+ { 0x01040026, "(Novell) Object Class FINISHER SUPPLY" },
+ { 0x01040027, "(Novell) Object Class PRINTER POOL" },
+ { 0x01040100, "(Novell) Value Class PRINTER STATE" },
+ { 0x01040101, "(Novell) Value Class TRANSFER METHOD" },
+ { 0x01040102, "(Novell) Value Class SCHEDULER" },
+ { 0x01040103, "(Novell) Value Class DISTINGUISHED NAME SYNTAX" },
+ { 0x01040104, "(Novell) Value Class DEVICE CONTROL" },
+ { 0x01040105, "(Novell) Value Class PRINTER OUTPUT BIN" },
+ { 0x01040106, "(Novell) Value Class INPUT TRAY" },
+ { 0x01040107, "(Novell) Value Class MEDIUM" },
+ { 0x01040108, "(Novell) Value Class MEDIUM TYPE" },
+ { 0x01040109, "(Novell) Value Class MANAGER STATE" },
+ { 0x0104010A, "(Novell) Value Class NOTIFICATION METHOD" },
+ { 0x0104010B, "(Novell) Value Class REASONS" },
+ { 0x0104010C, "(Novell) Value Class DEVICE STATE" },
+ { 0x01040203, "(Novell) Object Class NDS ORGANIZATION" },
+ { 0x01040204, "(Novell) Object Class NDS ORGANIZATIONAL UNIT" },
+ { 0x01040205, "(Novell) Object Class NDS GROUP" },
+ { 0x01040206, "(Novell) Object Class NDS USER" },
+ { 0x0, NULL },
+};
+
+static const value_string object_ids_12[] = { /* 060C60 864801 (LENGTH 12)*/
+ /* These values are 0x86F83701+(defined number)*/
+ { 0x04000000, "(Novell) Object Class GENERIC DPA" },
+ { 0x04000001, "(Novell) Object Class GENERIC MIB" },
+ { 0x04000002, "(Novell) Object Class GENERIC DPS" },
+ { 0x04000003, "(Novell) Object Class GENERIC VENDOR" },
+ { 0x04000100, "(Novell) Object Class JOB DPA" },
+ { 0x04000101, "(Novell) Object Class JOB MIB" },
+ { 0x04000102, "(Novell) Object Class JOB DPS" },
+ { 0x04000103, "(Novell) Object Class JOB VENDOR" },
+ { 0x04000200, "(Novell) Object Class DOCUMENT DPA" },
+ { 0x04000201, "(Novell) Object Class DOCUMENT MIB" },
+ { 0x04000202, "(Novell) Object Class DOCUMENT DPS" },
+ { 0x04000203, "(Novell) Object Class DOCUMENT VENDOR" },
+ { 0x04000300, "(Novell) Object Class PRINTER DPA" },
+ { 0x04000301, "(Novell) Object Class PRINTER MIB" },
+ { 0x04000302, "(Novell) Object Class PRINTER DPS" },
+ { 0x04000303, "(Novell) Object Class PRINTER HISTORY" },
+ { 0x04000304, "(Novell) Object Class PRINTER VENDOR" },
+ { 0x04000400, "(Novell) Object Class MEDIUM DPA" },
+ { 0x04000401, "(Novell) Object Class MEDIUM MIB" },
+ { 0x04000402, "(Novell) Object Class MEDIUM DPS" },
+ { 0x04000403, "(Novell) Object Class MEDIUM VENDOR" },
+ { 0x04000500, "(Novell) Object Class FONT DPA" },
+ { 0x04000501, "(Novell) Object Class FONT MIB" },
+ { 0x04000502, "(Novell) Object Class FONT DPS" },
+ { 0x04000503, "(Novell) Object Class FONT VENDOR" },
+ { 0x04000600, "(Novell) Object Class TRANSFER METHOD DPA" },
+ { 0x04000601, "(Novell) Object Class TRANSFER METHOD MIB" },
+ { 0x04000602, "(Novell) Object Class TRANSFER METHOD DPS" },
+ { 0x04000603, "(Novell) Object Class TRANSFER METHOD VENDOR" },
+ { 0x04000700, "(Novell) Object Class DELIVERY METHOD DPA" },
+ { 0x04000701, "(Novell) Object Class DELIVERY METHOD MIB" },
+ { 0x04000702, "(Novell) Object Class DELIVERY METHOD DPS" },
+ { 0x04000703, "(Novell) Object Class DELIVERY METHOD VENDOR" },
+ { 0x04000800, "(Novell) Object Class AUXILIARY SHEET DPA" },
+ { 0x04000801, "(Novell) Object Class AUXILIARY SHEET MIB" },
+ { 0x04000802, "(Novell) Object Class AUXILIARY SHEET DPS" },
+ { 0x04000803, "(Novell) Object Class AUXILIARY SHEET VENDOR" },
+ { 0x04000900, "(Novell) Object Class FINISHING DPA" },
+ { 0x04000901, "(Novell) Object Class FINISHING MIB" },
+ { 0x04000902, "(Novell) Object Class FINISHING DPS" },
+ { 0x04000903, "(Novell) Object Class FINISHING VENDOR" },
+ { 0x04000B00, "(Novell) Object Class IMPOSITION DPA" },
+ { 0x04000B01, "(Novell) Object Class IMPOSITION MIB" },
+ { 0x04000B02, "(Novell) Object Class IMPOSITION DPS" },
+ { 0x04000B03, "(Novell) Object Class IMPOSITION VENDOR" },
+ { 0x04000C00, "(Novell) Object Class SCHEDULER DPA" },
+ { 0x04000C01, "(Novell) Object Class SCHEDULER MIB" },
+ { 0x04000C02, "(Novell) Object Class SCHEDULER DPS" },
+ { 0x04000C03, "(Novell) Object Class SCHEDULER VENDOR" },
+ { 0x04000E00, "(Novell) Object Class RESOURCE DPA" },
+ { 0x04000E01, "(Novell) Object Class RESOURCE MIB" },
+ { 0x04000E02, "(Novell) Object Class RESOURCE DPS" },
+ { 0x04000E03, "(Novell) Object Class RESOURCE VENDOR" },
+ { 0x04000F00, "(Novell) Object Class INPUT DPA" },
+ { 0x04000F01, "(Novell) Object Class INPUT MIB" },
+ { 0x04000F02, "(Novell) Object Class INPUT DPS" },
+ { 0x04000F03, "(Novell) Object Class INPUT VENDOR" },
+ { 0x04001000, "(Novell) Object Class OUTPUT DPA" },
+ { 0x04001001, "(Novell) Object Class OUTPUT MIB" },
+ { 0x04001002, "(Novell) Object Class OUTPUT DPS" },
+ { 0x04001003, "(Novell) Object Class OUTPUT VENDOR" },
+ { 0x04001100, "(Novell) Object Class AUXILIARY SHEET PKG DPA" },
+ { 0x04001101, "(Novell) Object Class AUXILIARY SHEET PKG MIB" },
+ { 0x04001102, "(Novell) Object Class AUXILIARY SHEET PKG DPS" },
+ { 0x04001103, "(Novell) Object Class AUXILIARY SHEET PKG VENDOR" },
+ { 0x04001200, "(Novell) Object Class MANAGER DPA" },
+ { 0x04001201, "(Novell) Object Class MANAGER MIB" },
+ { 0x04001202, "(Novell) Object Class MANAGER DPS" },
+ { 0x04001203, "(Novell) Object Class MANAGER VENDOR" },
+ { 0x04001300, "(Novell) Object Class JOB DEFAULTS DPA" },
+ { 0x04001301, "(Novell) Object Class JOB DEFAULTS MIB" },
+ { 0x04001302, "(Novell) Object Class JOB DEFAULTS DPS" },
+ { 0x04001303, "(Novell) Object Class JOB DEFAULTS VENDOR" },
+ { 0x04001400, "(Novell) Object Class DOCUMENT DEFAULTS DPA" },
+ { 0x04001401, "(Novell) Object Class DOCUMENT DEFAULTS MIB" },
+ { 0x04001402, "(Novell) Object Class DOCUMENT DEFAULTS DPS" },
+ { 0x04001403, "(Novell) Object Class DOCUMENT DEFAULTS VENDOR" },
+ { 0x04001500, "(Novell) Object Class JOB LIMITS DPA" },
+ { 0x04001501, "(Novell) Object Class JOB LIMITS MIB" },
+ { 0x04001502, "(Novell) Object Class JOB LIMITS DPS" },
+ { 0x04001503, "(Novell) Object Class JOB LIMITS VENDOR" },
+ { 0x04001600, "(Novell) Object Class DOCUMENT LIMITS DPA" },
+ { 0x04001601, "(Novell) Object Class DOCUMENT LIMITS MIB" },
+ { 0x04001602, "(Novell) Object Class DOCUMENT LIMITS DPS" },
+ { 0x04001603, "(Novell) Object Class DOCUMENT LIMITS VENDOR" },
+ { 0x04001700, "(Novell) Object Class ABSTRACT EVENT DPA" },
+ { 0x04001701, "(Novell) Object Class ABSTRACT EVENT MIB" },
+ { 0x04001702, "(Novell) Object Class ABSTRACT EVENT DPS" },
+ { 0x04001703, "(Novell) Object Class ABSTRACT EVENT VENDOR" },
+ { 0x04001900, "(Novell) Object Class MARKER DPA" },
+ { 0x04001901, "(Novell) Object Class MARKER MIB" },
+ { 0x04001902, "(Novell) Object Class MARKER DPS" },
+ { 0x04001903, "(Novell) Object Class MARKER VENDOR" },
+ { 0x04001A00, "(Novell) Object Class MEDIA PATH DPA" },
+ { 0x04001A01, "(Novell) Object Class MEDIA PATH MIB" },
+ { 0x04001A02, "(Novell) Object Class MEDIA PATH DPS" },
+ { 0x04001A03, "(Novell) Object Class MEDIA PATH VENDOR" },
+ { 0x04001B00, "(Novell) Object Class CHANNEL DPA" },
+ { 0x04001B01, "(Novell) Object Class CHANNEL MIB" },
+ { 0x04001B02, "(Novell) Object Class CHANNEL DPS" },
+ { 0x04001B03, "(Novell) Object Class CHANNEL VENDOR" },
+ { 0x04001C00, "(Novell) Object Class INTERP DPA" },
+ { 0x04001C01, "(Novell) Object Class INTERP MIB" },
+ { 0x04001C02, "(Novell) Object Class INTERP DPS" },
+ { 0x04001C03, "(Novell) Object Class INTERP VENDOR" },
+ { 0x04001D00, "(Novell) Object Class NOTIFICATION METHOD DPA" },
+ { 0x04001D01, "(Novell) Object Class NOTIFICATION METHOD MIB" },
+ { 0x04001D02, "(Novell) Object Class NOTIFICATION METHOD DPS" },
+ { 0x04001D03, "(Novell) Object Class NOTIFICATION METHOD VENDOR" },
+ { 0x04001E00, "(Novell) Object Class MARKER SUPPLIES DPA" },
+ { 0x04001E01, "(Novell) Object Class MARKER SUPPLIES MIB" },
+ { 0x04001E02, "(Novell) Object Class MARKER SUPPLIES DPS" },
+ { 0x04001E03, "(Novell) Object Class MARKER SUPPLIES VENDOR" },
+ { 0x04001F00, "(Novell) Object Class MARKER COLORANT DPA" },
+ { 0x04001F01, "(Novell) Object Class MARKER COLORANT MIB" },
+ { 0x04001F02, "(Novell) Object Class MARKER COLORANT DPS" },
+ { 0x04001F03, "(Novell) Object Class MARKER COLORANT VENDOR" },
+ { 0x04002000, "(Novell) Object Class COVER DPA" },
+ { 0x04002001, "(Novell) Object Class COVER MIB" },
+ { 0x04002002, "(Novell) Object Class COVER DPS" },
+ { 0x04002003, "(Novell) Object Class COVER VENDOR" },
+ { 0x04002100, "(Novell) Object Class LIGHT DPA" },
+ { 0x04002101, "(Novell) Object Class LIGHT MIB" },
+ { 0x04002102, "(Novell) Object Class LIGHT DPS" },
+ { 0x04002103, "(Novell) Object Class LIGHT VENDOR" },
+ { 0x04002200, "(Novell) Object Class BUFFER DPA" },
+ { 0x04002201, "(Novell) Object Class BUFFER MIB" },
+ { 0x04002202, "(Novell) Object Class BUFFER DPS" },
+ { 0x04002203, "(Novell) Object Class BUFFER VENDOR" },
+ { 0x04002300, "(Novell) Object Class RESOURCE CONTEXT DPA" },
+ { 0x04002301, "(Novell) Object Class RESOURCE CONTEXT MIB" },
+ { 0x04002302, "(Novell) Object Class RESOURCE CONTEXT DPS" },
+ { 0x04002303, "(Novell) Object Class RESOURCE CONTEXT VENDOR" },
+ { 0x04002500, "(Novell) Object Class FINISHER DEVICE DPA" },
+ { 0x04002501, "(Novell) Object Class FINISHER DEVICE MIB" },
+ { 0x04002502, "(Novell) Object Class FINISHER DEVICE DPS" },
+ { 0x04002503, "(Novell) Object Class FINISHER DEVICE VENDOR" },
+ { 0x04002600, "(Novell) Object Class FINISHER SUPPLY DPA" },
+ { 0x04002601, "(Novell) Object Class FINISHER SUPPLY MIB" },
+ { 0x04002602, "(Novell) Object Class FINISHER SUPPLY DPS" },
+ { 0x04002603, "(Novell) Object Class FINISHER SUPPLY VENDOR" },
+ { 0x04002700, "(Novell) Object Class PRINTER POOL DPA" },
+ { 0x04002701, "(Novell) Object Class PRINTER POOL MIB" },
+ { 0x04002702, "(Novell) Object Class PRINTER POOL DPS" },
+ { 0x04002703, "(Novell) Object Class PRINTER POOL VENDOR" },
+ { 0x04010000, "(Novell) Value PRINTER STATE NOT CONNECTED" },
+ { 0x04010001, "(Novell) Value PRINTER STATE STOPPED" },
+ { 0x04010002, "(Novell) Value PRINTER STATE ACTIVE" },
+ { 0x04010003, "(Novell) Value PRINTER STATE PAUSED NOT CONNECTED" },
+ { 0x04010004, "(Novell) Value PRINTER STATE PRINTER STOPPED" },
+ { 0x04010100, "(Novell) Value TRANSFER METHOD NDPS DATA" },
+ { 0x04010200, "(Novell) Value SCHEDULER MEDIA" },
+ { 0x04010201, "(Novell) Value SCHEDULER OPERATOR" },
+ { 0x04010202, "(Novell) Value SCHEDULER CURRENT MEDIUM" },
+ { 0x04010300, "(Novell) Value DISTINGUISHED NAME SYNTAX NDS" },
+ { 0x04010400, "(Novell) Value DEVICE CONTROL PAUSE INPUT" },
+ { 0x04010401, "(Novell) Value DEVICE CONTROL RESUME INPUT" },
+ { 0x04010402, "(Novell) Value DEVICE CONTROL PAUSE OUTPUT" },
+ { 0x04010403, "(Novell) Value DEVICE CONTROL RESUME OUTPUT" },
+ { 0x04010404, "(Novell) Value DEVICE CONTROL RESET" },
+ { 0x04010405, "(Novell) Value DEVICE CONTROL FORM FEED" },
+ { 0x04010406, "(Novell) Value DEVICE CONTROL CONTINUE" },
+ { 0x04010407, "(Novell) Value DEVICE CONTROL REFRESH INFORMATION" },
+ { 0x04010500, "(Novell) Value OUTPUT BIN MAIN" },
+ { 0x04010501, "(Novell) Value OUTPUT BIN MAIL BOX 1" },
+ { 0x04010502, "(Novell) Value OUTPUT BIN MAIL BOX 2" },
+ { 0x04010503, "(Novell) Value OUTPUT BIN MAIL BOX 3" },
+ { 0x04010504, "(Novell) Value OUTPUT BIN MAIL BOX 4" },
+ { 0x04010505, "(Novell) Value OUTPUT BIN MAIL BOX 5" },
+ { 0x04010506, "(Novell) Value OUTPUT BIN MAIL BOX 6" },
+ { 0x04010507, "(Novell) Value OUTPUT BIN MAIL BOX 7" },
+ { 0x04010508, "(Novell) Value OUTPUT BIN MAIL BOX 8" },
+ { 0x04010509, "(Novell) Value OUTPUT BIN MAIL BOX 9" },
+ { 0x0401050A, "(Novell) Value OUTPUT BIN MAIL BOX 10" },
+ { 0x0401050B, "(Novell) Value OUTPUT BIN MAIL BOX 11" },
+ { 0x0401050C, "(Novell) Value OUTPUT BIN MAIL BOX 12" },
+ { 0x0401050D, "(Novell) Value OUTPUT BIN MAIL BOX 13" },
+ { 0x0401050E, "(Novell) Value OUTPUT BIN MAIL BOX 14" },
+ { 0x0401050F, "(Novell) Value OUTPUT BIN MAIL BOX 15" },
+ { 0x04010600, "(Novell) Value INPUT TRAY FRONT" },
+ { 0x04010601, "(Novell) Value INPUT TRAY BACK" },
+ { 0x04010602, "(Novell) Value INPUT TRAY MULTI PURPOSE" },
+ { 0x04010603, "(Novell) Value INPUT TRAY SECONDARY" },
+ { 0x04010604, "(Novell) Value INPUT TRAY 1" },
+ { 0x04010605, "(Novell) Value INPUT TRAY 2" },
+ { 0x04010606, "(Novell) Value INPUT TRAY 3" },
+ { 0x04010607, "(Novell) Value INPUT TRAY 4" },
+ { 0x04010608, "(Novell) Value INPUT TRAY 5" },
+ { 0x04010609, "(Novell) Value INPUT TRAY 6" },
+ { 0x0401060A, "(Novell) Value INPUT TRAY 7" },
+ { 0x0401060B, "(Novell) Value INPUT TRAY 8" },
+ { 0x0401060C, "(Novell) Value INPUT TRAY 9" },
+ { 0x0401060D, "(Novell) Value INPUT TRAY 10" },
+ { 0x04010700, "(Novell) Value MEDIUM 8X10" },
+ { 0x04010701, "(Novell) Value MEDIUM SPFOLIO" },
+ { 0x04010702, "(Novell) Value MEDIUM FOOLSCAP" },
+ { 0x04010800, "(Novell) Value MEDIUM TYPE STANDARD" },
+ { 0x04010801, "(Novell) Value MEDIUM TYPE CARD STOCK" },
+ { 0x04010802, "(Novell) Value MEDIUM TYPE BOND" },
+ { 0x04010803, "(Novell) Value MEDIUM TYPE LETTERHEAD" },
+ { 0x04010804, "(Novell) Value MEDIUM TYPE GLOSSY" },
+ { 0x04010805, "(Novell) Value MEDIUM TYPE CLAY BASED" },
+ { 0x04010806, "(Novell) Value MEDIUM TYPE SPECIAL" },
+ { 0x04010900, "(Novell) Value MSTATE INITIALIZING" },
+ { 0x04010901, "(Novell) Value MSTATE ACTIVE" },
+ { 0x04010902, "(Novell) Value MSTATE TERMINATING" },
+ { 0x04010903, "(Novell) Value MSTATE DOWN" },
+ { 0x04010A00, "NOTIFY METHOD ID POP UP" },
+ { 0x04010A01, "NOTIFY METHOD ID SPX PROGRAM" },
+ { 0x04010A02, "NOTIFY METHOD ID TIRPC PROGRAM" },
+ { 0x04010A03, "NOTIFY METHOD ID LOG FILE" },
+ { 0x04010A04, "NOTIFY METHOD ID MHS EMAIL" },
+ { 0x04010A05, "NOTIFY METHOD ID GROUPWISE EMAIL" },
+ { 0x04010A06, "NOTIFY METHOD ID WINSOCK PROGRAM" },
+ { 0x04010A07, "NOTIFY METHOD ID PROGRAM" },
+ { 0x04010A08, "NOTIFY METHOD ID DIRECT POP UP" },
+ { 0x04010A09, "NOTIFY METHOD ID SMTP EMAIL" },
+ { 0x04010A0A, "NOTIFY METHOD ID INDP" },
+ { 0x04010B00, "(Novell) Value REASONS OPER HOLD SET" },
+ { 0x04010B01, "(Novell) Value REASONS JOB START TIMEOUT" },
+ { 0x04010B02, "(Novell) Value REASONS JOB ACCOUNTING HOLD" },
+ { 0x04010C00, "(Novell) Value DEVICE PRINTER NORMAL" },
+ { 0x04010C01, "(Novell) Value DEVICE PRINTER BUSY" },
+ { 0x04010C02, "(Novell) Value DEVICE PRINTER NON CRITICAL" },
+ { 0x04010C03, "(Novell) Value DEVICE PRINTER CRITICAL" },
+ { 0x04010C04, "(Novell) Value DEVICE PRINTER UNAVAILABLE" },
+ { 0x04010C05, "(Novell) Value DEVICE PRINTER MOV OFF" },
+ { 0x04010C06, "(Novell) Value DEVICE PRINTER OFFLINE" },
+ { 0x04010C07, "(Novell) Value DEVICE PRINTER MOV ON" },
+ { 0x04010C08, "(Novell) Value DEVICE PRINTER STANDBY" },
+ { 0x04020100, "(Novell) Object Class NDS MANAGER" },
+ { 0x04020101, "(Novell) Object Class NDS BROKER" },
+ { 0x04020200, "(Novell) Object Class NDS PRINTER" },
+ { 0x04020301, "(Novell) Attribute NDS DEFAULT C A P" },
+ { 0x04020302, "(Novell) Attribute NDS DEFAULT P A P" },
+ { 0x04020303, "(Novell) Attribute NDS INSTALL C A P" },
+ { 0x04020304, "(Novell) Attribute NDS INSTALL P A P" },
+ { 0x04020305, "(Novell) Attribute NDS INSTALL T S" },
+ { 0x04020306, "(Novell) Attribute NDS INSTALL F F" },
+ { 0x04020307, "(Novell) Attribute NDS INSTALL FS" },
+ { 0x04020601, "(Novell) Attribute NDS GROUP MEMBERSHIP" },
+ { 0x0, NULL },
+};
+
+static const value_string object_ids_13[] = { /* 060D6086 480186 (LENGTH 13)*/
+ /* These values are 0xF8370104+(defined number)*/
+ { 0x00000000, "(Novell) Attribute OBJECT CLASS" },
+ { 0x00000001, "(Novell) Attribute DESCRIPTOR" },
+ { 0x00000002, "(Novell) Attribute DESCRIPTIVE NAME" },
+ { 0x00000004, "(Novell) Attribute STATE" },
+ { 0x00000005, "(Novell) Attribute MESSAGE" },
+ { 0x00000006, "(Novell) Attribute AVAILABILITY" },
+ { 0x00000007, "(Novell) Attribute LIST OF MANAGERS" },
+ { 0x00000008, "(Novell) Attribute JOB ATTRIBUTES SUPPORTED" },
+ { 0x00000009, "(Novell) Attribute DOCUMENT ATTRIBUTES SUPPORTED" },
+ { 0x0000000A, "(Novell) Attribute LOGGING PROFILE" },
+ { 0x0000000C, "(Novell) Attribute ASSOCIATED SERVER" },
+ { 0x00000200, "(Novell) Attribute NOTIFICATION PROFILE" },
+ { 0x00000201, "(Novell) Attribute ERROR CODE" },
+ { 0x00000202, "(Novell) Attribute IPP USER NAME" },
+ { 0x00000203, "(Novell) Attribute NATURAL LANGUAGE" },
+ { 0x00000204, "(Novell) Attribute CHARACTER SET" },
+ { 0x00000205, "(Novell) Attribute FINISHING PROCESS" },
+ { 0x00000206, "(Novell) Attribute CLIENT ADDRESS" },
+ { 0x00000207, "(Novell) Attribute XRI SUPPORTED" },
+ { 0x00000208, "(Novell) Attribute SOURCE ADDRESS" },
+ { 0x00010001, "(Novell) Attribute JOB NAME" },
+ { 0x00010002, "(Novell) Attribute JOB ORIGINATOR" },
+ { 0x00010003, "(Novell) Attribute JOB OWNER" },
+ { 0x00010004, "(Novell) Attribute JOB COMMENT" },
+ { 0x00010007, "(Novell) Attribute JOB CLIENT ID" },
+ { 0x00010008, "(Novell) Attribute JOB NON COMPULSARY ATTRIBUTES" },
+ { 0x0001000F, "(Novell) Attribute RESULTS PROFILE" },
+ { 0x00010010, "(Novell) Attribute JOB FINISHING" },
+ { 0x00010016, "(Novell) Attribute JOB ABORT CRITERIA" },
+ { 0x00010017, "(Novell) Attribute JOB WARNING CRITERIA" },
+ { 0x00010018, "(Novell) Attribute DOCUMENT ABORT CRITERIA" },
+ { 0x0001001E, "(Novell) Attribute JOB START WAIT" },
+ { 0x0001001F, "(Novell) Attribute JOB END WAIT" },
+ { 0x00010020, "(Novell) Attribute JOB HOLD" },
+ { 0x00010021, "(Novell) Attribute JOB PASSWORD" },
+ { 0x00010022, "(Novell) Attribute JOB PRINT AFTER" },
+ { 0x00010023, "(Novell) Attribute JOB PRIORITY" },
+ { 0x00010024, "(Novell) Attribute JOB DEADLINE TIME" },
+ { 0x00010025, "(Novell) Attribute JOB DISCARD TIME" },
+ { 0x00010026, "(Novell) Attribute JOB RETENTION PERIOD" },
+ { 0x00010027, "(Novell) Attribute JOB MSG TO OPERATOR" },
+ { 0x00010028, "(Novell) Attribute JOB SCHEDULING" },
+ { 0x00010029, "(Novell) Attribute JOB VALIDATE" },
+ { 0x0001002B, "(Novell) Attribute PRINTER NAME REQUESTED" },
+ { 0x0001002C, "(Novell) Attribute PRINTER LOCATIONS REQUESTED" },
+ { 0x0001002D, "(Novell) Attribute PRINTER MODELS REQUESTED" },
+ { 0x0001002F, "(Novell) Attribute PRINTER SPEED RANGE REQUESTED" },
+ { 0x00010078, "(Novell) Attribute USER NAME" },
+ { 0x00010200, "(Novell) Attribute JOB FORM FEED REQUESTED" },
+ { 0x00010201, "(Novell) Attribute JOB BANNER REQUESTED" },
+ { 0x00010202, "(Novell) Attribute JOB OPERATOR HOLD" },
+ { 0x00010203, "(Novell) Attribute JOB PRINTER OBJECT ID" },
+ { 0x00010204, "(Novell) Attribute JOB ID" },
+ { 0x00010205, "(Novell) Attribute JOB START MESSAGE" },
+ { 0x00010206, "(Novell) Attribute JOB END MESSAGE" },
+ { 0x00010207, "(Novell) Attribute ACCOUNTING INFORMATION" },
+ { 0x00010208, "(Novell) Attribute ESTIMATED COMPLETION TIME" },
+ { 0x00010209, "(Novell) Attribute ASSIGNED PORTS STATES" },
+ { 0x0001020A, "(Novell) Attribute PRINTER TYPES REQUESTED" },
+ { 0x0001020B, "(Novell) Attribute JOB CONTROL LANGUAGE" },
+ { 0x0001020C, "(Novell) Attribute JOB COPIES OCTETS" },
+ { 0x0001020D, "(Novell) Attribute JOB COST" },
+ { 0x0001020E, "(Novell) Attribute JOB HOLD UNTIL" },
+ { 0x0001020F, "(Novell) Attribute IPP JOB NAME" },
+ { 0x00010210, "(Novell) Attribute AUDITING JOB PDL" },
+ { 0x00020000, "(Novell) Attribute DEFAULT CHARACTER SET" },
+ { 0x00020001, "(Novell) Attribute DEFAULT CHARACTER MAPPING" },
+ { 0x00020002, "(Novell) Attribute DEFAULT FONT" },
+ { 0x00020003, "(Novell) Attribute DEFAULT CHARACTER REPERTOIR" },
+ { 0x00020006, "(Novell) Attribute DEFAULT RESOURCES" },
+ { 0x00020007, "(Novell) Attribute DEFAULT PRINTER RESOLUTION" },
+ { 0x00020008, "(Novell) Attribute DEFAULT RESOLUTIONS USED" },
+ { 0x0002000C, "(Novell) Attribute NEW LINE OPTION" },
+ { 0x0002000D, "(Novell) Attribute CARRIAGE CONTROL TYPE" },
+ { 0x0002000E, "(Novell) Attribute TABLE REFERENCE CHARACTER" },
+ { 0x0002000F, "(Novell) Attribute SHIFT OUT SHIFT IN" },
+ { 0x00020014, "(Novell) Attribute DOCUMENT STATE" },
+ { 0x00020015, "(Novell) Attribute COPIES COMPLETED" },
+ { 0x00020032, "(Novell) Attribute FONT SUBSTITUTION" },
+ { 0x00020033, "(Novell) Attribute MEDIUM SUBSTITUTION" },
+ { 0x0002003B, "(Novell) Attribute MEDIUM FIDELITY" },
+ { 0x0002003D, "(Novell) Attribute SIDES" },
+ { 0x0002003E, "(Novell) Attribute PAGE SELECT" },
+ { 0x0002003F, "(Novell) Attribute PAGE MEDIA SELECT" },
+ { 0x00020040, "(Novell) Attribute COPY COUNT" },
+ { 0x00020044, "(Novell) Attribute RESET PRINTER" },
+ { 0x00020045, "(Novell) Attribute BINDING EDGE" },
+ { 0x00020046, "(Novell) Attribute BINDING EDGE IMAGE SHIFT" },
+ { 0x00020047, "(Novell) Attribute NUMBER UP" },
+ { 0x00020048, "(Novell) Attribute PLEX" },
+ { 0x00020049, "(Novell) Attribute X IMAGE SHIFT" },
+ { 0x0002004A, "(Novell) Attribute Y IMAGE SHIFT" },
+ { 0x00020050, "(Novell) Attribute TRANSFER METHOD" },
+ { 0x00020052, "(Novell) Attribute DOCUMENT SEQUENCE NUMBER" },
+ { 0x00020053, "(Novell) Attribute DOCUMENT CONTENT" },
+ { 0x00020054, "(Novell) Attribute FILE REFERENCE" },
+ { 0x00020055, "(Novell) Attribute DOCUMENT TYPE" },
+ { 0x00020057, "(Novell) Attribute RESOURCE CONTEXT" },
+ { 0x00020058, "(Novell) Attribute NON COMPULSORY ATTRIBUTES" },
+ { 0x00020059, "(Novell) Attribute DOCUMENT FILE NAME" },
+ { 0x0002005A, "(Novell) Attribute DOCUMENT NAME" },
+ { 0x0002005B, "(Novell) Attribute DOCUMENT AUTHORS" },
+ { 0x0002005C, "(Novell) Attribute DOCUMENT COMMENT" },
+ { 0x0002005D, "(Novell) Attribute DOCUMENT REVISION DATE" },
+ { 0x0002005F, "(Novell) Attribute PAGE ORDER RECEIVED" },
+ { 0x00020061, "(Novell) Attribute PAGE SIZE" },
+ { 0x00020062, "(Novell) Attribute CONTENT ORIENTATION" },
+ { 0x00020064, "(Novell) Attribute CHARACTER SETS USED" },
+ { 0x00020065, "(Novell) Attribute CHARACTER MAPPINGS USED" },
+ { 0x00020066, "(Novell) Attribute FONTS USED" },
+ { 0x00020067, "(Novell) Attribute CHARACTER REPERTOIRES USED" },
+ { 0x00020068, "(Novell) Attribute MEDIA USED" },
+ { 0x0002006A, "(Novell) Attribute OCTET COUNT" },
+ { 0x0002006B, "(Novell) Attribute PAGE COUNT" },
+ { 0x0002006C, "(Novell) Attribute GLYPH COUNT" },
+ { 0x0002006D, "(Novell) Attribute FONT COUNT" },
+ { 0x0002006E, "(Novell) Attribute FONT CHANGE COUNT" },
+ { 0x0002006F, "(Novell) Attribute MAXIMUM FONTS PER PAGE" },
+ { 0x00020070, "(Novell) Attribute PERCENT GRAPHICS" },
+ { 0x00020071, "(Novell) Attribute PERCENT IMAGES" },
+ { 0x00020073, "(Novell) Attribute PRESENT DIRECTORIES USED" },
+ { 0x00020076, "(Novell) Attribute RESOURCES USED" },
+ { 0x00020201, "(Novell) Attribute FINISHING" },
+ { 0x00020202, "(Novell) Attribute OUTPUT METHOD" },
+ { 0x00020203, "(Novell) Attribute PRINT QUALITY" },
+ { 0x00020204, "(Novell) Attribute DEFAULT MEDIUM" },
+ { 0x00020205, "(Novell) Attribute DEFAULT INPUT TRAY" },
+ { 0x00020206, "(Novell) Attribute INPUT TRAYS USED" },
+ { 0x00020207, "(Novell) Attribute INPUT TRAY SELECT" },
+ { 0x00020208, "(Novell) Attribute DOCUMENT PDL" },
+ { 0x00030002, "(Novell) Attribute PRINTER LOCATIONS" },
+ { 0x00030003, "(Novell) Attribute PRINTER MODEL" },
+ { 0x00030005, "(Novell) Attribute PRINTER REALIZATION" },
+ { 0x00030015, "(Novell) Attribute MEDIA SUPPORTED" },
+ { 0x00030016, "(Novell) Attribute MEDIA READY" },
+ { 0x0003001B, "(Novell) Attribute FINISHINGS SUPPORTED" },
+ { 0x0003001C, "(Novell) Attribute FINISHINGS READY" },
+ { 0x00030027, "(Novell) Attribute PRINT QUALITIES SUPPORTED" },
+ { 0x00030028, "(Novell) Attribute PRINT QUALITIES READY" },
+ { 0x00030032, "(Novell) Attribute CHARACTER SETS SUPPORTED" },
+ { 0x00030033, "(Novell) Attribute CHARACTER SETS READY" },
+ { 0x00030035, "(Novell) Attribute CHARACTER MAPPINGS SUPPORTED" },
+ { 0x00030036, "(Novell) Attribute CHARACTER MAPPINGS READY" },
+ { 0x00030038, "(Novell) Attribute CHARACTER REPRTIOR SUPPORTED" },
+ { 0x00030039, "(Novell) Attribute CHARACTER REPRTIOR READY" },
+ { 0x0003003F, "(Novell) Attribute PAGE SELECT SUPPORTED" },
+ { 0x00030049, "(Novell) Attribute CONTENT ORIENTS SUPPORTED" },
+ { 0x0003004E, "(Novell) Attribute SHEET COUNT" },
+ { 0x00030051, "(Novell) Attribute PRESENT DIRECTORIES SUPPORTED" },
+ { 0x00030056, "(Novell) Attribute PRINTER RESOURCE CONTEXT" },
+ { 0x00030058, "(Novell) Attribute MEDIUM FIDEL SUPPORTED" },
+ { 0x0003005A, "(Novell) Attribute PRINTER CONFIGURATION LEVEL RANGE" },
+ { 0x0003005B, "(Novell) Attribute PRINTER CONFIGURATION CATEGORY SETS" },
+ { 0x0003005C, "(Novell) Attribute PRINTER CONFIGURATION POLICY" },
+ { 0x0003005D, "(Novell) Attribute PRINTER INTG LEVEL RANGE" },
+ { 0x0003005E, "(Novell) Attribute PRINTER INTG CATEGORY SETS" },
+ { 0x0003005F, "(Novell) Attribute PRINTER INTG POLICY" },
+ { 0x00030060, "(Novell) Attribute PRINTER SECURITY LABEL POLICY" },
+ { 0x00030067, "(Novell) Attribute NEW LINE OPTIONS SUPPORTED" },
+ { 0x00030068, "(Novell) Attribute CC TYPES SUPPORTED" },
+ { 0x0003006A, "(Novell) Attribute SHIFT OUT SHIFT IN SUPPORTED" },
+ { 0x0003006B, "(Novell) Attribute INPUT TRAYS MEDIUM" },
+ { 0x00030200, "(Novell) Attribute PRINTER ID" },
+ { 0x00030201, "(Novell) Attribute PRINTER STATE REASONS" },
+ { 0x00030202, "(Novell) Attribute PREVIOUS PRINTER STATE" },
+ { 0x00030203, "(Novell) Attribute JOB POOL" },
+ { 0x00030204, "(Novell) Attribute PDS EXECUTE AND PARAMETERS" },
+ { 0x00030205, "(Novell) Attribute PRINT HANDLER EXECUTE AND PARAMETERS" },
+ { 0x00030206, "(Novell) Attribute PDS STATE" },
+ { 0x00030209, "(Novell) Attribute SCHEDULERS SUPPORTED" },
+ { 0x0003020A, "(Novell) Attribute SCHEDULER READY" },
+ { 0x0003020B, "(Novell) Attribute PRINTER DATA POOL SIZE LIMIT" },
+ { 0x0003020C, "(Novell) Attribute PRINTER RETAINED SIZE LIMIT" },
+ { 0x0003020E, "(Novell) Attribute PRINTER MANAGER NAME" },
+ { 0x0003020F, "(Novell) Attribute PRINTER VOLUME SIZE" },
+ { 0x00030210, "(Novell) Attribute PRINTER VOLUME FREE SPACE" },
+ { 0x00030211, "(Novell) Attribute PRINTER SHEET COUNT SINCE SERVICE" },
+ { 0x00030212, "(Novell) Attribute PRINTER JOB COUNT SINCE SERVICE" },
+ { 0x00030213, "(Novell) Attribute PRINTER CURRENT RESOURCE SERVICE" },
+ { 0x00030214, "(Novell) Attribute PRINTER CURRENT NOTIFICATION SERVICE" },
+ { 0x00030215, "(Novell) Attribute PRINTER MANUFACTURER" },
+ { 0x00030216, "(Novell) Attribute PRINTER INITIALIZATION STRING" },
+ { 0x00030217, "(Novell) Attribute PRINTER RESET STRING" },
+ { 0x00030218, "(Novell) Attribute COLOR SUPPORTED" },
+ { 0x0003021A, "(Novell) Attribute PRINTER CONTROL SNAP FSPEC" },
+ { 0x0003021B, "(Novell) Attribute PRINTER PDS CONFIGURATION SNAP FSPEC " },
+ { 0x0003021C, "(Novell) Attribute PRINTER PRINT HANDLER CONFIGURATION SNAP FSPEC" },
+ { 0x0003021D, "(Novell) Attribute PRINTER RESOURCE PRINTER ID" },
+ { 0x0003021E, "(Novell) Attribute PRINTER JOBS SCHEDULED" },
+ { 0x0003021F, "(Novell) Attribute PRINTER JOBS ACTIVE" },
+ { 0x00030220, "(Novell) Attribute PRINTER DATA POOL TOTAL KB" },
+ { 0x00030221, "(Novell) Attribute PRINTER DATA POOL RETEN KB" },
+ { 0x00030222, "(Novell) Attribute PRINTER PDS IDENTIFICATION" },
+ { 0x00030223, "(Novell) Attribute PRINTER DEVICE ID" },
+ { 0x00030224, "(Novell) Attribute PRINTER BANNERS SUPPORTED" },
+ { 0x00030226, "(Novell) Attribute PRINTER PRIMARY NOTIFY SERVICE" },
+ { 0x00030227, "(Novell) Attribute PRINTER PRIMARY RESOURCE SERVICE" },
+ { 0x00030228, "(Novell) Attribute PRINTER NEEDS ATTENTION TIME" },
+ { 0x00030229, "(Novell) Attribute PRINTER NEEDS OP ATTENTION TIME" },
+ { 0x0003022A, "(Novell) Attribute PDLS SUPPORTED" },
+ { 0x0003022B, "(Novell) Attribute PRINTER MAXIMUM SPEED UNIT" },
+ { 0x0003022C, "(Novell) Attribute PRINTER MAXIMUM SPEED" },
+ { 0x0003022D, "(Novell) Attribute PRINTER TRANSFER METHOD SUPPORTED" },
+ { 0x0003022E, "(Novell) Attribute PDS ADDITIONAL PARAMETERS" },
+ { 0x0003022F, "(Novell) Attribute PRINT HANDLER ADDITIONAL PARAMETERS" },
+ { 0x00030230, "(Novell) Attribute PRINTER MAXIMUM RESOLUTION" },
+ { 0x00030231, "(Novell) Attribute PRINTER JOB WAIT TIMEOUT" },
+ { 0x00030232, "(Novell) Attribute PRINTER STATE SEVERITY" },
+ { 0x00030233, "(Novell) Attribute PRINTER AGENT NAME" },
+ { 0x00030234, "(Novell) Attribute PRINTER STATE" },
+ { 0x00030235, "(Novell) Attribute FONTS SUPPORTED" },
+ { 0x00030236, "(Novell) Attribute FONTS READY" },
+ { 0x0003023B, "(Novell) Attribute SIDES SUPPORTED" },
+ { 0x0003023C, "(Novell) Attribute SIDES READY" },
+ { 0x0003023D, "(Novell) Attribute PRINTER RESOLUTIONS SUPPORTED" },
+ { 0x0003023E, "(Novell) Attribute PRINTER ASSOCIATED PRINTS" },
+ { 0x0003023F, "(Novell) Attribute PRINTERS READY" },
+ { 0x00030240, "(Novell) Attribute DEFAULT INPUT DEVICE" },
+ { 0x00030241, "(Novell) Attribute CONTROL LANGUAGE FAMILY" },
+ { 0x00030242, "(Novell) Attribute DEVICE STATE" },
+ { 0x00030243, "(Novell) Attribute PRINTER NAME ALIASES" },
+ { 0x00030244, "(Novell) Attribute PRINTER MEMORY SIZE" },
+ { 0x00030245, "(Novell) Attribute PRINTER TYPES" },
+ { 0x00030246, "(Novell) Attribute PRINTER JOB COMPLETION EVALUATION ATTRIBUTES" },
+ { 0x00030247, "(Novell) Attribute PREVIOUS PA NAMES" },
+ { 0x00030248, "(Novell) Attribute PRINTER OBJECT QUEUES" },
+ { 0x00030249, "(Novell) Attribute PRINTER OPERATIONS SUPPORTED" },
+ { 0x0003024A, "(Novell) Attribute PRINTER JOB ACCOUNTING ATTRIBUTES" },
+ { 0x0003024B, "(Novell) Attribute ACCOUNTING EXECUTE AND PARAMETERS" },
+ { 0x0003024C, "(Novell) Attribute PRINTER SECURITY LEVEL" },
+ { 0x0003024D, "(Novell) Attribute PRINTER STARTUP TIME" },
+ { 0x0003024E, "(Novell) Attribute IPP ENABLED" },
+ { 0x0003024F, "(Novell) Attribute LPR ENABLED" },
+ { 0x00030250, "(Novell) Attribute MULTIPLE DOCUMENTS SUPPORTED" },
+ { 0x00030251, "(Novell) Attribute LPR ACCESS FILTER" },
+ { 0x00030252, "(Novell) Attribute LPR CONFIGURED TIME" },
+ { 0x00030253, "(Novell) Attribute LPR HOST NAME" },
+ { 0x00030254, "(Novell) Attribute PRINTER AGENT ADDRESS" },
+ { 0x00030255, "(Novell) Attribute URI SUPPORTED" },
+ { 0x00030256, "(Novell) Attribute PRINTER PRF RESOURCE SERVICES" },
+ { 0x00030257, "(Novell) Attribute PRINTER MAXIMUM SPEED COLOR" },
+ { 0x00030258, "(Novell) Attribute LAST JOB NUMBER" },
+ { 0x00030259, "(Novell) Attribute DEVICE URI" },
+ { 0x0003025A, "(Novell) Attribute DEVICE ADDRESS" },
+ { 0x0003025B, "(Novell) Attribute LPR DATA FILTER" },
+ { 0x0003025C, "(Novell) Attribute IPP SECURITY CONFIGURED" },
+ { 0x0003025D, "(Novell) Attribute INITIAL PROFILE ID" },
+ { 0x0003025E, "(Novell) Attribute PRINTER XRI" },
+ { 0x0003025F, "(Novell) Attribute MESSAGE FROM ADMIN" },
+ { 0x00030260, "(Novell) Attribute PRINTER CURRENT NOTIFICATION SERVICE ADDRESS" },
+ { 0x00030261, "(Novell) Attribute PRINTER CURRENT RSRC SERVICE ADDRESS" },
+ { 0x00030262, "(Novell) Attribute LAST JOB COMPLETE TIME" },
+ { 0x00030263, "(Novell) Attribute PRINTER ENERGY STATE" },
+ { 0x00030264, "(Novell) Attribute PRINTER AUDITING LEVEL" },
+ { 0x00030265, "(Novell) Attribute PRINTER PAGE COUNT" },
+ { 0x00040000, "(Novell) Attribute MEDIUM IDENTIFIER" },
+ { 0x00040003, "(Novell) Attribute MEDIUM TYPE" },
+ { 0x00040004, "(Novell) Attribute MEDIUM SIZE" },
+ { 0x00040005, "(Novell) Attribute MEDIUM DIMENSIONS" },
+ { 0x00040006, "(Novell) Attribute MEDIUM COLOR" },
+ { 0x00040007, "(Novell) Attribute MEDIUM TOOTH" },
+ { 0x00040008, "(Novell) Attribute MEDIUM GRAIN" },
+ { 0x00040009, "(Novell) Attribute MEDIUM SIDES" },
+ { 0x0004000A, "(Novell) Attribute MEDIUM WEIGHT" },
+ { 0x0004000B, "(Novell) Attribute MEDIUM ASSURE REP AREA" },
+ { 0x0004000C, "(Novell) Attribute MEDIUM ASSOCIATED MEDIA" },
+ { 0x0004000D, "(Novell) Attribute MEDIUM REALIZATION" },
+ { 0x0004000F, "(Novell) Attribute MEDIUM FORM PARTS" },
+ { 0x00040014, "(Novell) Attribute MEDIUM HOLES COUNT" },
+ { 0x00040015, "(Novell) Attribute MEDIUM HOLES REFERENCE EDGE" },
+ { 0x00040016, "(Novell) Attribute MEDIUM HOLES AXIS OFF" },
+ { 0x00040017, "(Novell) Attribute MEDIUM HOLES LOCATIONS" },
+ { 0x00040018, "(Novell) Attribute MEDIUM HOLES DIAMETER" },
+ { 0x00050000, "(Novell) Attribute FONT IDENTIFIER" },
+ { 0x00060000, "(Novell) Attribute TRANSFER METHOD ID" },
+ { 0x00060001, "(Novell) Attribute TRANSFER METHOD TYPE" },
+ { 0x00060002, "(Novell) Attribute DOCUMENT REFERENCE TYPE" },
+ { 0x00070000, "(Novell) Attribute DELIVERY METHOD ID" },
+ { 0x00080000, "(Novell) Attribute AUXILIARY SHEET ID" },
+ { 0x00080001, "(Novell) Attribute AUXILIARY SHEET MEDIUM" },
+ { 0x00090000, "(Novell) Attribute FINISHING IDENTIFIER" },
+ { 0x00090001, "(Novell) Attribute FINISHING ASSOCIATED FINISHINGS " },
+ { 0x00090002, "(Novell) Attribute FINISHING REALIZATION" },
+ { 0x00090003, "(Novell) Attribute FINISHING SPECIFICATION" },
+ { 0x000B0000, "(Novell) Attribute IMPOSITION IDENTIFIER" },
+ { 0x000B0007, "(Novell) Attribute LOGICAL PAGE ORIGIN" },
+ { 0x000B0008, "(Novell) Attribute LOGICAL PAGE X OFFSET" },
+ { 0x000B0009, "(Novell) Attribute LOGICAL PAGE Y OFFSET" },
+ { 0x000B000A, "(Novell) Attribute LOGICAL PAGE SCALING" },
+ { 0x000B000C, "(Novell) Attribute IMPOSITION NOT UP" },
+ { 0x000C0200, "(Novell) Attribute SCHEDULER ID" },
+ { 0x000C0201, "(Novell) Attribute SCHEDULER EXECUTE NAME" },
+ { 0x000C0202, "(Novell) Attribute SCHEDULER EXECUTE PARAMETERS" },
+ { 0x000E0000, "(Novell) Attribute RESOURCE NAME" },
+ { 0x000E0001, "(Novell) Attribute RESOURCE TYPE" },
+ { 0x000F0200, "(Novell) Attribute INPUT ID" },
+ { 0x000F0201, "(Novell) Attribute INPUT LOCATION" },
+ { 0x000F0202, "(Novell) Attribute INPUT CURRENT MEDIUM" },
+ { 0x00100200, "(Novell) Attribute OUTPUT ID" },
+ { 0x00100201, "(Novell) Attribute OUTPUT LOCATION" },
+ { 0x00100202, "(Novell) Attribute OUTPUT PAGE GROUPING" },
+ { 0x00110000, "(Novell) Attribute AUXILIARY SHEET PACKAGE ID" },
+ { 0x00110001, "(Novell) Attribute START SHEET OF SET" },
+ { 0x00110002, "(Novell) Attribute SEPARATOR SHEET OF SET" },
+ { 0x00110003, "(Novell) Attribute END SHEET OF SET" },
+ { 0x00110004, "(Novell) Attribute START SHEET OF COPY" },
+ { 0x00110005, "(Novell) Attribute SEPERATOR SHEET OF COPY" },
+ { 0x00110006, "(Novell) Attribute END SHEET OF COPY" },
+ { 0x00120200, "(Novell) Attribute MANAGER NAME" },
+ { 0x00120201, "(Novell) Attribute MANAGER STATE" },
+ { 0x00120202, "(Novell) Attribute MANAGER DNS NAME" },
+ { 0x00120203, "(Novell) Attribute IPP PORTS SUPPORTED" },
+ { 0x00120204, "(Novell) Attribute MANAGER VERSION" },
+ { 0x00130200, "(Novell) Attribute JOB DEFAULTS ID" },
+ { 0x00140200, "(Novell) Attribute DOCUMENT DEFAULTS ID" },
+ { 0x00150200, "(Novell) Attribute JOB LIMITS ID" },
+ { 0x00160200, "(Novell) Attribute DOCUMENT LIMITS ID" },
+ { 0x00170200, "(Novell) Attribute ABSTRACT EVENT ID" },
+ { 0x00170201, "(Novell) Attribute ALERT OTHER" },
+ { 0x00170202, "(Novell) Attribute ALERT UNKNOWN" },
+ { 0x00170203, "(Novell) Attribute ALERT COVER OPEN" },
+ { 0x00170204, "(Novell) Attribute ALERT COVER CLOSED" },
+ { 0x00170205, "(Novell) Attribute ALERT INTERLOCK OPEN" },
+ { 0x00170206, "(Novell) Attribute ALERT INTERLOCK CLOSED" },
+ { 0x00170207, "(Novell) Attribute ALERT CONFIGURATION CHANGE" },
+ { 0x00170208, "(Novell) Attribute ALERT JAM" },
+ { 0x00170209, "(Novell) Attribute ALERT JAM CLEAR" },
+ { 0x0017020A, "(Novell) Attribute ALERT SUBUNIT LIFE ALARM" },
+ { 0x0017020B, "(Novell) Attribute ALERT SUBUNIT LIFE OVER" },
+ { 0x0017020C, "(Novell) Attribute ALERT SUBUNIT ALARM EMPTY" },
+ { 0x0017020D, "(Novell) Attribute ALERT SUBUNIT EMPTY" },
+ { 0x0017020E, "(Novell) Attribute ALERT SUBUNIT ALARM FULL" },
+ { 0x0017020F, "(Novell) Attribute ALERT SUBUNIT FULL" },
+ { 0x00170210, "(Novell) Attribute ALERT SUBUNIT NEAR LIMIT" },
+ { 0x00170211, "(Novell) Attribute ALERT SUBUNIT AT LIMIT" },
+ { 0x00170212, "(Novell) Attribute ALERT SUBUNIT OPENED" },
+ { 0x00170213, "(Novell) Attribute ALERT SUBUNIT CLOSED" },
+ { 0x00170214, "(Novell) Attribute ALERT SUBUNIT TURN ON" },
+ { 0x00170215, "(Novell) Attribute ALERT SUBUNIT TURN OFF" },
+ { 0x00170216, "(Novell) Attribute ALERT SUBUNIT OFFLINE" },
+ { 0x00170217, "(Novell) Attribute ALERT SUBUNIT POWER SAVE" },
+ { 0x00170218, "(Novell) Attribute ALERT SUBUNIT WARM UP" },
+ { 0x00170219, "(Novell) Attribute ALERT SUBUNIT ADDED" },
+ { 0x0017021A, "(Novell) Attribute ALERT SUBUNIT REMOVED" },
+ { 0x0017021B, "(Novell) Attribute ALERT SUBUNIT RESOURCE ADD" },
+ { 0x0017021C, "(Novell) Attribute ALERT SUBUNIT RESOURCE REMOVED" },
+ { 0x0017021D, "(Novell) Attribute ALERT SUBUNIT REC FAIL" },
+ { 0x0017021E, "(Novell) Attribute ALERT SUBUNIT UNR FAIL" },
+ { 0x0017021F, "(Novell) Attribute ALERT SUBUNIT R S ERR" },
+ { 0x00170220, "(Novell) Attribute ALERT SUBUNIT UR S ERR" },
+ { 0x00170221, "(Novell) Attribute ALERT SUBUNIT MTR FAIL" },
+ { 0x00170222, "(Novell) Attribute ALERT SUBUNIT MEMORY EXHAUSTED" },
+ { 0x00170223, "(Novell) Attribute ALERT SUBUNIT UNDER TEMPERATURE" },
+ { 0x00170224, "(Novell) Attribute ALERT SUBUNIT OVER TEMPERATURE" },
+ { 0x00170225, "(Novell) Attribute ALERT SUBUNIT TIME FAIL" },
+ { 0x00170226, "(Novell) Attribute ALERT SUBUNIT THERMAL FAILURE" },
+ { 0x00170264, "(Novell) Attribute ALERT JOB START WAIT" },
+ { 0x00170265, "(Novell) Attribute ALERT JOB END WAIT" },
+ { 0x00170267, "(Novell) Attribute ALERT JOB HELD USER" },
+ { 0x00170268, "(Novell) Attribute ALERT JOB USER HOLD REMOVE" },
+ { 0x00170269, "(Novell) Attribute ALERT JOB HELD OPERATORE" },
+ { 0x0017026A, "(Novell) Attribute ALERT JOB OPERATOR HOLD REMOVE" },
+ { 0x0017026B, "(Novell) Attribute ALERT JOB CREATED" },
+ { 0x0017026C, "(Novell) Attribute ALERT JOB REORDERED" },
+ { 0x0017026D, "(Novell) Attribute ALERT JOB COMPLETE BRIEF" },
+ { 0x0017026E, "(Novell) Attribute ALERT JOB STATE CHANGED" },
+ { 0x0017026F, "(Novell) Attribute ALERT JOB CONFIGURATION CHANGED" },
+ { 0x00170270, "(Novell) Attribute ALERT JOB PROGRESS" },
+ { 0x00190200, "(Novell) Attribute MARKER ID" },
+ { 0x001A0200, "(Novell) Attribute MEDIA PATH ID" },
+ { 0x001B0200, "(Novell) Attribute CHANNEL ID" },
+ { 0x001C0200, "(Novell) Attribute INTERPRETER ID" },
+ { 0x001C0201, "(Novell) Attribute PRTINTERPFEEDRES" },
+ { 0x001C0202, "(Novell) Attribute PRTINTERPXFEEDRES" },
+ { 0x001E0200, "(Novell) Attribute MARKER SUPPLIES ID" },
+ { 0x001F0200, "(Novell) Attribute MARKER COLORANT ID" },
+ { 0x00200200, "(Novell) Attribute COVER ID" },
+ { 0x00210200, "(Novell) Attribute LIGHT ID" },
+ { 0x00220200, "(Novell) Attribute BUFFER ID" },
+ { 0x00250200, "(Novell) Attribute FINISHER DEVICE ID" },
+ { 0x00260200, "(Novell) Attribute FINISHER SUPPLY ID" },
+ { 0x00260201, "(Novell) Attribute FINISHER SUPPLY DEVICE ID" },
+ { 0x00270200, "(Novell) Attribute PRINTER POOL ID" },
+ { 0x00270201, "(Novell) Attribute PRINTER POOL NAME" },
+ { 0x00270202, "(Novell) Attribute POOL LAST JOB NUMBER" },
+ { 0x00270203, "(Novell) Attribute PRINTER POOL PA NAME" },
+ { 0x02008100, "(Novell) Attribute NDS COMMON NAME" },
+ { 0x02008101, "(Novell) Attribute NDS DESCRIPTION" },
+ { 0x02008102, "(Novell) Attribute NDS LOCALITY NAME" },
+ { 0x02008103, "(Novell) Attribute NDS NETWORK ADDRESS" },
+ { 0x02008104, "(Novell) Attribute NDS ORGANIZATION" },
+ { 0x02008105, "(Novell) Attribute NDS ORGANIZATIONAL UNIT" },
+ { 0x02008106, "(Novell) Attribute NDS SEE ALSO" },
+ { 0x02008107, "(Novell) Attribute NDS CLASS NAME" },
+ { 0x02008108, "(Novell) Attribute NDS GUID" },
+ { 0x02010000, "(Novell) Attribute NDS PRINTER TO PA ID MAPS" },
+ { 0x02010001, "(Novell) Attribute NDS DATAPOOL LOCATIONS" },
+ { 0x02010002, "(Novell) Attribute NDS DB VOLUME NAME" },
+ { 0x02010003, "(Novell) Attribute NDS MANAGER STATUS" },
+ { 0x02010004, "(Novell) Attribute NDS DATABASE DIRECTORY PATH" },
+ { 0x02010100, "(Novell) Attribute NDS DELIVERY METHODS INSTALLED" },
+ { 0x02010101, "(Novell) Attribute NDS MHS SEND DIRECTORY PATH" },
+ { 0x02010102, "(Novell) Attribute NDS MHS SEND DIRECTORY VOLUME" },
+ { 0x02010103, "(Novell) Attribute NDS NOTIFY SERVICE ENABLED" },
+ { 0x02010104, "(Novell) Attribute NDS REGISTERED ADVERTISING NAME" },
+ { 0x02010105, "(Novell) Attribute NDS REGISTERED SERVICE ENABLED" },
+ { 0x02010106, "(Novell) Attribute NDS RESOURCE MANAGEMENT SERVICE ENABLED" },
+ { 0x02010107, "(Novell) Attribute NDS RESOURCE MANAGER DATABASE PATH" },
+ { 0x02010108, "(Novell) Attribute NDS RESOURCE MANAGER DATABASE VOLUME" },
+ { 0x02010109, "(Novell) Attribute NDS NOTIFY NETWORK ADDRESS" },
+ { 0x0201010A, "(Novell) Attribute NDS REGISTERED NETWORK ADDRESS" },
+ { 0x0201010B, "(Novell) Attribute NDS RESOURCE NETWORK ADDRESS" },
+ { 0x0201010C, "(Novell) Attribute NDS GROUPWISE APIGW DIRECTORY PATH" },
+ { 0x0201010D, "(Novell) Attribute NDS GROUPWISE APIGW DIRECTORY VOLUME" },
+ { 0x0201010E, "(Novell) Attribute NDS NOTIFY NETWORK ADDRESS" },
+ { 0x0201010F, "(Novell) Attribute NDS REGISTERED NETWORK ADDRESS" },
+ { 0x02010110, "(Novell) Attribute NDS RESOURCE NETWORK ADDRESS" },
+ { 0x02010111, "(Novell) Attribute NDS SMTP SERVER" },
+ { 0x02018300, "(Novell) Attribute NDS ACCOUNT BALANCE" },
+ { 0x02018301, "(Novell) Attribute NDS ALLOW UNLIMITED" },
+ { 0x02018302, "(Novell) Attribute NDS FULL NAME" },
+ { 0x02018303, "(Novell) Attribute NDS HOST DEVICE" },
+ { 0x02018304, "(Novell) Attribute NDS MINIMUM ACCOUNT BALANCE" },
+ { 0x02018305, "(Novell) Attribute NDS RESOURCE" },
+ { 0x02018306, "(Novell) Attribute NDS STATUS" },
+ { 0x02018307, "(Novell) Attribute NDS VERSION" },
+ { 0x02020000, "(Novell) Attribute NDS OPERATOR ROLE" },
+ { 0x02020001, "(Novell) Attribute NDS USER ROLE" },
+ { 0x02020002, "(Novell) Attribute NDS MANAGER ROLE" },
+ { 0x02020003, "(Novell) Attribute NDS PRINTER STATUS" },
+ { 0x0202000A, "(Novell) Attribute NDS CLIENT INSTALL CANDIDATE" },
+ { 0x02020015, "(Novell) Attribute NDS NOTIFY CONSUMERS" },
+ { 0x0202001A, "(Novell) Attribute NDS PRINTER QUEUE LIST" },
+ { 0x0202001E, "(Novell) Attribute NDS DATAPOOL LOCATION" },
+ { 0x0202001F, "(Novell) Attribute NDS PRINTER SIBLINGS" },
+ { 0x02020021, "(Novell) Attribute NDS ACCOUNTANT ROLE" },
+ { 0x02020022, "(Novell) Attribute NDS IPP URI" },
+ { 0x02020023, "(Novell) Attribute NDS IPP SECURITY SCHEME" },
+ { 0x02028200, "(Novell) Attribute NDS OWNER" },
+ { 0x02028201, "(Novell) Attribute NDS SERIAL NUMBER" },
+ { 0x0, NULL },
+};
+
+static const value_string object_ids_14[] = { /* 060E6086 480186F8 (LENGTH 14)*/
+ /* These values are 0x37010400+(defined number)*/
+ { 0x01008102, "(Novell) Attribute JOB PRIVACY LEVEL" },
+ { 0x01008103, "(Novell) Attribute JOB PRIVACY CATEGORY" },
+ { 0x01008104, "(Novell) Attribute JOB PRIVACY POLICY" },
+ { 0x01008105, "(Novell) Attribute JOB SECURITY INTEGRITY LEVEL" },
+ { 0x01008106, "(Novell) Attribute JOB SECURITY INTEGRITY CATAGORY" },
+ { 0x01008107, "(Novell) Attribute JOB SECURITY INTEGRITY POLICY" },
+ { 0x01008108, "(Novell) Attribute JOB SECURITY LABEL" },
+ { 0x01008148, "(Novell) Attribute CURRENT JOB STATE" },
+ { 0x01008149, "(Novell) Attribute PREVIOUS JOB STATE" },
+ { 0x0100814A, "(Novell) Attribute PRINTERS ASSIGNED" },
+ { 0x0100814C, "(Novell) Attribute SUBMISSION TIME" },
+ { 0x0100814D, "(Novell) Attribute MODIFICATION TIME" },
+ { 0x0100814E, "(Novell) Attribute STARTED PRINTING TIME" },
+ { 0x0100814F, "(Novell) Attribute JOB COPIES COMPLETED" },
+ { 0x01008150, "(Novell) Attribute PAGES COMPLETED" },
+ { 0x01008151, "(Novell) Attribute OCTETS COMPLETED" },
+ { 0x01008154, "(Novell) Attribute INTERVENING JOBS" },
+ { 0x01008155, "(Novell) Attribute PRINT CHECKPOINT" },
+ { 0x01008156, "(Novell) Attribute NEW JOB IDENTIFIER" },
+ { 0x01008157, "(Novell) Attribute ON REQUEST RESOURCES REQUESTED" },
+ { 0x01008158, "(Novell) Attribute JOB MESSAGE FROM ADMIN" },
+ { 0x01008159, "(Novell) Attribute LAST JOB EVENTS" },
+ { 0x0100815A, "(Novell) Attribute NAME OF LAST ACCESSOR" },
+ { 0x0100815D, "(Novell) Attribute ERROR COUNT" },
+ { 0x0100815E, "(Novell) Attribute WARNING COUNT" },
+ { 0x0100815F, "(Novell) Attribute PROCESSING TIME" },
+ { 0x01008160, "(Novell) Attribute JOB SUBMIT COMPLETE" },
+ { 0x01008161, "(Novell) Attribute COMPLETION TIME" },
+ { 0x01008162, "(Novell) Attribute NUMBER OF DOCUMENTS" },
+ { 0x01008163, "(Novell) Attribute IGNORED ATTRIBUTES" },
+ { 0x01008164, "(Novell) Attribute JOB STATE REASONS" },
+ { 0x01008165, "(Novell) Attribute TOTAL JOB OCTETS" },
+ { 0x01008166, "(Novell) Attribute FINISH INCLUDE JOB SHEETS" },
+ { 0x01008167, "(Novell) Attribute FINISH INCLUDE DOCUMENT SHEETS" },
+ { 0x01008168, "(Novell) Attribute JOB SHEETS" },
+ { 0x01008169, "(Novell) Attribute DOCUMENT SHEETS" },
+ { 0x0100816B, "(Novell) Attribute IMPRESSIONS COMPLETED" },
+ { 0x0100816C, "(Novell) Attribute MEDIA SHEETS COMPLETED" },
+ { 0x0100816D, "(Novell) Attribute JOB PAGE COUNT" },
+ { 0x0100816E, "(Novell) Attribute JOB IMPRESSION COUNT" },
+ { 0x0100816F, "(Novell) Attribute JOB MEDIA SHEET COUNT" },
+ { 0x01008170, "(Novell) Attribute JOB ID ON PRINTER" },
+ { 0x01008171, "(Novell) Attribute JOB ID ON CLIENT" },
+ { 0x02008172, "(Novell) Attribute PRESENTATION DIRECTION" },
+ { 0x02008173, "(Novell) Attribute CONTENT ORIENTS USED" },
+ { 0x02008174, "(Novell) Attribute CURRENT PAGE ORDER" },
+ { 0x0300810C, "(Novell) Attribute JOB FINISHINGS SUPPORTED" },
+ { 0x0300810D, "(Novell) Attribute JOB FINISHINGS READY" },
+ { 0x0300814A, "(Novell) Attribute NUMBERS UP SUPPORTED" },
+ { 0x0300814C, "(Novell) Attribute X IMAGE SHIFT RANG SUPPORTED" },
+ { 0x0300814E, "(Novell) Attribute Y IMAGE SHIFT RANG SUPPORTED" },
+ { 0x03008158, "(Novell) Attribute RESOURCES SUPPORTED" },
+ { 0x0300815B, "(Novell) Attribute PRINTER TIMEOUT PERIOD" },
+ { 0x0300815F, "(Novell) Attribute RESOURCES READY" },
+ { 0x03008163, "(Novell) Attribute JOB ABORT CRITERIA SUPPORTED" },
+ { 0x03008164, "(Novell) Attribute JOB WARNING CRITERIA SUPPORTED" },
+ { 0x03008165, "(Novell) Attribute DOCUMENT ABORT CRITERIA SUPPORTED" },
+ { 0x03008166, "(Novell) Attribute BINDING EDGES SUPPORTED" },
+ { 0x03008167, "(Novell) Attribute EDGE IMAGE SHIFT MAXIMUM SUPPORTED" },
+ { 0x03008168, "(Novell) Attribute JOB SHEETS SUPPORTED" },
+ { 0x03008169, "(Novell) Attribute JOB SHEETS READY" },
+ { 0x0300816A, "(Novell) Attribute DOCUMENT SHEETS SUPPORTED" },
+ { 0x0300816B, "(Novell) Attribute DOCUMENT SHEETS READY" },
+ { 0x0300816C, "(Novell) Attribute FINISH INCLUDED DOCUMENT SHEET SUPPORTED" },
+ { 0x0300816D, "(Novell) Attribute FINISH INCLUDED JOB SHEET SUPPORTED" },
+ { 0x03008170, "(Novell) Attribute JOB SIZE RANGE SUPPORTED" },
+ { 0x03008171, "(Novell) Attribute JOB SIZE RANGE READY" },
+ { 0x03008172, "(Novell) Attribute CHECKPOINT FORMATS SUPPORTED" },
+ { 0x03008173, "(Novell) Attribute ARE FOREIGN JOBS VISABLE" },
+ { 0x03008174, "(Novell) Attribute PRINTER ENABLED" },
+ { 0x03030202, "(Novell) Attribute HARDWARE MEMORY SIZE" },
+ { 0x17028148, "(Novell) Attribute ALERT PA CREATED" },
+ { 0x17028149, "(Novell) Attribute ALERT PA DELETED" },
+ { 0x1702814A, "(Novell) Attribute ALERT PRINT QUEUE CONNECTION LOST" },
+ { 0x1702814B, "(Novell) Attribute ALERT NOTIFY SERVICE ERROR" },
+ { 0x1702814C, "(Novell) Attribute ALERT RMS ERROR" },
+ { 0x1702814D, "(Novell) Attribute ALERT SRS ERROR" },
+ { 0x1702814E, "(Novell) Attribute ALERT IPP PORT NOT AVAILABLE" },
+ { 0x1702814F, "(Novell) Attribute ALERT DNS NAME PROBLEM" },
+ { 0x17028150, "(Novell) Attribute ALERT CANT PING PRINTER" },
+ { 0x17028151, "(Novell) Attribute ALERT LPR COMMUNICATION FAILED" },
+ { 0x17028152, "(Novell) Attribute ALERT SNMP COMMUNICATION FAILED" },
+ { 0x1702822C, "(Novell) Attribute ALERT PRINTER OFF LINE" },
+ { 0x1702822D, "(Novell) Attribute ALERT PRINTER ON LINE" },
+ { 0x1702822E, "(Novell) Attribute ALERT PRINTER READY" },
+ { 0x17028375, "(Novell) Attribute ALERT DOOR OPEN" },
+ { 0x17028376, "(Novell) Attribute ALERT DOOR CLOSED" },
+ { 0x17028377, "(Novell) Attribute ALERT POWER UP" },
+ { 0x17028378, "(Novell) Attribute ALERT POWER DOWN" },
+ { 0x17028379, "(Novell) Attribute ALERT PRINTER NMS RESET" },
+ { 0x1702837A, "(Novell) Attribute ALERT PRINTER MANUAL RESET" },
+ { 0x1702837B, "(Novell) Attribute ALERT PRINTER READY TO PRINT" },
+ { 0x17028621, "(Novell) Attribute ALERT INPUT TRAY MISSING" },
+ { 0x17028622, "(Novell) Attribute ALERT INPUT SIZE CHANGE" },
+ { 0x17028623, "(Novell) Attribute ALERT INPUT WEIGHT CHANGE" },
+ { 0x17028624, "(Novell) Attribute ALERT INPUT TYPE CHANGE" },
+ { 0x17028625, "(Novell) Attribute ALERT INPUT COLOR CHANGE" },
+ { 0x17028626, "(Novell) Attribute ALERT INPUT PARTS CHANGE" },
+ { 0x17028627, "(Novell) Attribute ALERT INPUT SUPPLY LOW" },
+ { 0x17028628, "(Novell) Attribute ALERT INPUT SUPPLY EMPTY" },
+ { 0x17028629, "(Novell) Attribute ALERT INPUT MEDIA CHANGE REQUEST" },
+ { 0x1702862A, "(Novell) Attribute ALERT INPUT MANUAL INPUT REQUEST" },
+ { 0x1702862B, "(Novell) Attribute ALERT INPUT TRAY POSITION FAILED" },
+ { 0x1702862C, "(Novell) Attribute ALERT INPUT TRAY ELV FAILED" },
+ { 0x1702862D, "(Novell) Attribute ALERT INPUT CANT FEED SIZE" },
+ { 0x17028705, "(Novell) Attribute ALERT OUTPUT TRAY MISSING" },
+ { 0x17028706, "(Novell) Attribute ALERT OUTPUT TRAY ALMOST" },
+ { 0x17028707, "(Novell) Attribute ALERT OUTPUT TRAY FULL" },
+ { 0x17028708, "(Novell) Attribute ALERT OUTPUT TRAY OTHER" },
+ { 0x17028709, "(Novell) Attribute ALERT OUTPUT TRAY OK" },
+ { 0x1702870A, "(Novell) Attribute ALERT OUTPUT TRAY EMPTIED" },
+ { 0x17028769, "(Novell) Attribute ALERT FUSER LO TEMP" },
+ { 0x1702876A, "(Novell) Attribute ALERT FUSER HI TEMP" },
+ { 0x1702876B, "(Novell) Attribute ALERT FUSER OK TEMP" },
+ { 0x1702876C, "(Novell) Attribute ALERT FUSER THERMAL FAILURE" },
+ { 0x1702876D, "(Novell) Attribute ALERT ADJUSTING PRINTER QUALITY" },
+ { 0x1702884D, "(Novell) Attribute ALERT TONER EMPTY" },
+ { 0x1702884E, "(Novell) Attribute ALERT INK EMPTY" },
+ { 0x1702884F, "(Novell) Attribute ALERT RIBBON EMPTY" },
+ { 0x17028850, "(Novell) Attribute ALERT TONER ALMOST" },
+ { 0x17028851, "(Novell) Attribute ALERT INK ALMOST" },
+ { 0x17028852, "(Novell) Attribute ALERT RIBBON ALMOST" },
+ { 0x17028853, "(Novell) Attribute ALERT WASTE TONER ALMOST" },
+ { 0x17028854, "(Novell) Attribute ALERT WASTE INK ALMOST" },
+ { 0x17028855, "(Novell) Attribute ALERT WASTE TONER FULL" },
+ { 0x17028856, "(Novell) Attribute ALERT WASTE INK FULL" },
+ { 0x17028857, "(Novell) Attribute ALERT OPC LIFE ALMOST" },
+ { 0x17028858, "(Novell) Attribute ALERT OPC LIFE OVER" },
+ { 0x17028859, "(Novell) Attribute ALERT DEVELOPER ALMOST" },
+ { 0x1702885A, "(Novell) Attribute ALERT DEVELOPER EMPTY" },
+ { 0x1702885B, "(Novell) Attribute ALERT TONER CARTRIDGE MISSING" },
+ { 0x17028A15, "(Novell) Attribute ALERT MEDIA TRAY MISSING" },
+ { 0x17028A16, "(Novell) Attribute ALERT MEDIA TRAY ALMOST" },
+ { 0x17028A17, "(Novell) Attribute ALERT MEDIA TRAY FULL" },
+ { 0x17028B5D, "(Novell) Attribute ALERT INTERP MEMORY INCREASED" },
+ { 0x17028B5E, "(Novell) Attribute ALERT INTERP MEMORY DECREASED" },
+ { 0x17028B5F, "(Novell) Attribute ALERT INTERP CARTRIDGE ADD" },
+ { 0x17028B60, "(Novell) Attribute ALERT INTERP CARTRIDGE DELETE" },
+ { 0x17028B61, "(Novell) Attribute ALERT INTERP RESOURCE ADD" },
+ { 0x17028B62, "(Novell) Attribute ALERT INTERP RESOURCE DELETE" },
+ { 0x17028B63, "(Novell) Attribute ALERT INTERP RESOURCE UN" },
+ { 0x17028B65, "(Novell) Attribute ALERT INTERP COMPLEX PAGE" },
+ { 0x17028C40, "(Novell) Attribute ALERT WARMING UP" },
+ { 0x17028C41, "(Novell) Attribute ALERT WARMED UP" },
+ { 0x17028C42, "(Novell) Attribute ALERT INPUT JAM" },
+ { 0x17028C44, "(Novell) Attribute ALERT INPUT SUPPLY NONE" },
+ { 0x17028C46, "(Novell) Attribute ALERT TIME OUT" },
+ { 0x17028C47, "(Novell) Attribute ALERT MANUAL FEED WAIT" },
+ { 0x17028C48, "(Novell) Attribute ALERT PAPER LENGTH" },
+ { 0x17028C49, "(Novell) Attribute ALERT OUTPUT JAM" },
+ { 0x17028C4B, "(Novell) Attribute ALERT MANUAL FEED" },
+ { 0x17028C4C, "(Novell) Attribute ALERT STORAGE" },
+ { 0x17028C4D, "(Novell) Attribute ALERT ENGINE" },
+ { 0x17028C4E, "(Novell) Attribute ALERT INTERP OTHER" },
+ { 0x17028C4F, "(Novell) Attribute ALERT IO ERROR" },
+ { 0x17028C50, "(Novell) Attribute ALERT VIDEO" },
+ { 0x17028C51, "(Novell) Attribute ALERT MOTOR OTHER" },
+ { 0x17028C52, "(Novell) Attribute ALERT TEMPERATURE OTHER" },
+ { 0x17028C53, "(Novell) Attribute ALERT RECORDER OTHER" },
+ { 0x17028C54, "(Novell) Attribute ALERT KNIFE OTHER" },
+ { 0x17028C55, "(Novell) Attribute ALERT CASSETTE OTHER" },
+ { 0x17028C56, "(Novell) Attribute ALERT PRINTER OTHER" },
+ { 0x17028C57, "(Novell) Attribute ALERT BATTERY LOW" },
+ { 0x17028C58, "(Novell) Attribute ALERT SELF TEST" },
+ { 0x17028C59, "(Novell) Attribute ALERT ADJUST PRINTER QUALITY" },
+ { 0x17028C5A, "(Novell) Attribute ALERT QUALITY ADJUSTED" },
+ { 0x17028C5D, "(Novell) Attribute ALERT INPUT TRAY OTHER" },
+ { 0x17028C5E, "(Novell) Attribute ALERT INPUT TRAY OK" },
+ { 0x17028C5F, "(Novell) Attribute ALERT MEDIA CHANGE" },
+ { 0x17028C60, "(Novell) Attribute ALERT INPUT MEDIA EMPTY" },
+ { 0x17028C61, "(Novell) Attribute ALERT INPUT MEDIA OK" },
+ { 0x17028C62, "(Novell) Attribute ALERT MANUAL FEED COMPLETE" },
+ { 0x17028C63, "(Novell) Attribute ALERT CHANGE MEDIA REQUEST" },
+ { 0x17028C64, "(Novell) Attribute ALERT CHANGE MEDIA COMPLETE" },
+ { 0x17028C65, "(Novell) Attribute ALERT TONER OTHER" },
+ { 0x17028C66, "(Novell) Attribute ALERT TONER OK" },
+ { 0x17028C67, "(Novell) Attribute ALERT INK OTHER" },
+ { 0x17028C68, "(Novell) Attribute ALERT INK OK" },
+ { 0x17028C69, "(Novell) Attribute ALERT RIBBON OTHER" },
+ { 0x17028C6A, "(Novell) Attribute ALERT RIBBON OK" },
+ { 0x17028C6B, "(Novell) Attribute ALERT OPC OK" },
+ { 0x17028C6D, "(Novell) Attribute ALERT DEVICE OTHER" },
+ { 0x17028C6E, "(Novell) Attribute ALERT DEVICE OK" },
+ { 0x17028C6F, "(Novell) Attribute ALERT CARTRIDGE ALMOST" },
+ { 0x17028C70, "(Novell) Attribute ALERT CARTRIDGE REPLACE" },
+ { 0x17028C71, "(Novell) Attribute ALERT CARTRIDGE OTHER" },
+ { 0x17028C72, "(Novell) Attribute ALERT CARTRIDGE OK" },
+ { 0x17028C73, "(Novell) Attribute ALERT FUSER ALMOST" },
+ { 0x17028C74, "(Novell) Attribute ALERT FUSER REPLACE" },
+ { 0x17028C75, "(Novell) Attribute ALERT FUSER OTHER" },
+ { 0x17028C76, "(Novell) Attribute ALERT FUSER OK" },
+ { 0x17028C77, "(Novell) Attribute ALERT WIPER ALMOST" },
+ { 0x17028C78, "(Novell) Attribute ALERT WIPER REPLACE" },
+ { 0x17028C79, "(Novell) Attribute ALERT WIPER OTHER" },
+ { 0x17028C7A, "(Novell) Attribute ALERT WIPER OK" },
+ { 0x17028C7B, "(Novell) Attribute ALERT WASTE ALMOST" },
+ { 0x17028C7C, "(Novell) Attribute ALERT WASTE REPLACE" },
+ { 0x17028C7D, "(Novell) Attribute ALERT WASTE OTHER" },
+ { 0x17028C7E, "(Novell) Attribute ALERT WASTE PACKAGE OK" },
+ { 0x17028C7F, "(Novell) Attribute ALERT OIL ALMOST" },
+ { 0x17028D00, "(Novell) Attribute ALERT OIL REPLACE" },
+ { 0x17028D01, "(Novell) Attribute ALERT OIL OTHER" },
+ { 0x17028D02, "(Novell) Attribute ALERT OIL OK" },
+ { 0x17028D03, "(Novell) Attribute ALERT BELT NEAR EOL" },
+ { 0x17028D04, "(Novell) Attribute ALERT BELT REPLACE" },
+ { 0x17028D05, "(Novell) Attribute ALERT BELT OTHER" },
+ { 0x17028D06, "(Novell) Attribute ALERT BELT OK" },
+ { 0x17028D07, "(Novell) Attribute ALERT STORAGE HIGH WATER" },
+ { 0x17028D08, "(Novell) Attribute ALERT STORAGE ERROR" },
+ { 0x17028D09, "(Novell) Attribute ALERT STORAGE OTHER" },
+ { 0x17028D0A, "(Novell) Attribute ALERT STORAGE OK" },
+ { 0x17028D0B, "(Novell) Attribute ALERT ENGINE OK" },
+ { 0x17028D0C, "(Novell) Attribute ALERT INTERP OK" },
+ { 0x17028D0D, "(Novell) Attribute ALERT IO OK" },
+ { 0x17028D0E, "(Novell) Attribute ALERT VIDEO OK" },
+ { 0x17028D0F, "(Novell) Attribute ALERT MOTOR OK" },
+ { 0x17028D10, "(Novell) Attribute ALERT TEMPERATURE OK" },
+ { 0x17028D11, "(Novell) Attribute ALERT RECORDER OK" },
+ { 0x17028D12, "(Novell) Attribute ALERT KNIFE OK" },
+ { 0x17028D13, "(Novell) Attribute ALERT CASSETTE OK" },
+ { 0x17028D14, "(Novell) Attribute ALERT PRINTER OK" },
+ { 0x17028D15, "(Novell) Attribute ALERT BATTERY OK " },
+ { 0x17028D16, "(Novell) Attribute ALERT BATTERY OTHER" },
+ { 0x17028D17, "(Novell) Attribute ALERT MAINTENANCE CHECK" },
+ { 0x17028D18, "(Novell) Attribute ALERT JOB START" },
+ { 0x17028D19, "(Novell) Attribute ALERT JOB END" },
+ { 0x17028D1A, "(Novell) Attribute ALERT JOB SEND NEXT" },
+ { 0x17028D1B, "(Novell) Attribute ALERT POWERSAVER ENTER" },
+ { 0x17028D1C, "(Novell) Attribute ALERT POWERSAVER EXIT" },
+ { 0x17028D1D, "(Novell) Attribute ALERT COMMUNICATIONS ERROR" },
+ { 0x17028D1E, "(Novell) Attribute ALERT COMMUNICATIONS OK" },
+ { 0x17028D1F, "(Novell) Attribute ALERT DRY INK LOW" },
+ { 0x17028D20, "(Novell) Attribute ALERT DRY INK EMPTY" },
+ { 0x17028D21, "(Novell) Attribute ALERT DRY INK OK" },
+ { 0x17028D22, "(Novell) Attribute ALERT DRY INK OTHER" },
+ { 0x17028D23, "(Novell) Attribute ALERT INPUT TRAY FAIL" },
+ { 0x17028D24, "(Novell) Attribute ALERT OUTPUT TRAY FAIL" },
+ { 0x17028D25, "(Novell) Attribute ALERT UNRECOVERABLE ERROR" },
+ { 0x17028D26, "(Novell) Attribute ALERT BYPASS OPEN" },
+ { 0x17028D27, "(Novell) Attribute ALERT BYPASS CLOSED" },
+ { 0x17028D28, "(Novell) Attribute ALERT BYPASS MISSING" },
+ { 0x17028D29, "(Novell) Attribute ALERT BYPASS OK" },
+ { 0x17028D2B, "(Novell) Attribute ALERT PHOTOREC MISSING" },
+ { 0x17028D2C, "(Novell) Attribute ALERT PHOTOREC OK" },
+ { 0x17028D2D, "(Novell) Attribute ALERT PHOTOREC NEAR EOL" },
+ { 0x17028D2E, "(Novell) Attribute ALERT PHOTOREC EOL" },
+ { 0x17028D2F, "(Novell) Attribute ALERT PHOTOREC OTHER" },
+ { 0x17028D30, "(Novell) Attribute ALERT PHOTOCON MISSING" },
+ { 0x17028D31, "(Novell) Attribute ALERT PHOTOCON OK" },
+ { 0x17028D32, "(Novell) Attribute ALERT PHOTOCON NEAR EOL" },
+ { 0x17028D33, "(Novell) Attribute ALERT PHOTOCON EOL" },
+ { 0x17028D34, "(Novell) Attribute ALERT PHOTOCON OTHER" },
+ { 0x17028D35, "(Novell) Attribute ALERT DEVELOPER CARTRIDGE MISSING" },
+ { 0x17028D36, "(Novell) Attribute ALERT DEVELOPER CARTRIDGE OK" },
+ { 0x17028D37, "(Novell) Attribute ALERT DEVICE CARTRIDGE NEAR EOL" },
+ { 0x17028D38, "(Novell) Attribute ALERT DEVELOPER CARTRIDGE OTHER" },
+ { 0x17028D39, "(Novell) Attribute ALERT NOT READY" },
+ { 0x17028D3A, "(Novell) Attribute ALERT TEST PRINT" },
+ { 0x17028D3B, "(Novell) Attribute ALERT TEST COMPLETE" },
+ { 0x17028D3C, "(Novell) Attribute ALERT MEMORY LOW WATER" },
+ { 0x17028D3D, "(Novell) Attribute ALERT MEMORY OK" },
+ { 0x17028D3E, "(Novell) Attribute ALERT ROS FAULT" },
+ { 0x17028D3F, "(Novell) Attribute ALERT ROS OK" },
+ { 0x17028D40, "(Novell) Attribute ALERT DUPLEX FAULT" },
+ { 0x17028D41, "(Novell) Attribute ALERT DUPLEX OK" },
+ { 0x17028D42, "(Novell) Attribute ALERT LASER FAULT" },
+ { 0x17028D43, "(Novell) Attribute ALERT LASER OK" },
+ { 0x17028D44, "(Novell) Attribute ALERT IMAGER FAULT" },
+ { 0x17028D45, "(Novell) Attribute ALERT IMAGER OK" },
+ { 0x17028D46, "(Novell) Attribute ALERT DEVELOPER CARTRIDGE EOL" },
+ { 0x17028D47, "(Novell) Attribute ALERT STAPLER EMPTY" },
+ { 0x17028D48, "(Novell) Attribute ALERT STAPLER OK" },
+ { 0x17028D49, "(Novell) Attribute ALERT STAPLER PIN JAM" },
+ { 0x17028D4A, "(Novell) Attribute ALERT STAPLER PIN OK" },
+ { 0x17028D4B, "(Novell) Attribute ALERT PUNCH JAM" },
+ { 0x17028D4C, "(Novell) Attribute ALERT PUNCH OTHER" },
+ { 0x17028D4D, "(Novell) Attribute ALERT PUNCH OK" },
+ { 0x17028D4E, "(Novell) Attribute ALERT PUNCH WASTE NEAR" },
+ { 0x17028D4F, "(Novell) Attribute ALERT PUNCH WASTE FULL" },
+ { 0x17028D50, "(Novell) Attribute ALERT PUNCH WASTE OK" },
+ { 0x17028D51, "(Novell) Attribute ALERT WASTE NEAR FULL" },
+ { 0x17028D52, "(Novell) Attribute ALERT WASTE FULL" },
+ { 0x17028D53, "(Novell) Attribute ALERT WASTE OK" },
+ { 0x17028D54, "(Novell) Attribute ALERT WAX LOW" },
+ { 0x17028D55, "(Novell) Attribute ALERT WAX EMPTY" },
+ { 0x17028D56, "(Novell) Attribute ALERT WAX OK" },
+ { 0x17028D57, "(Novell) Attribute ALERT PAGE CLEARED" },
+ { 0x17028D58, "(Novell) Attribute ALERT PAGE PUNT" },
+ { 0x17028D59, "(Novell) Attribute ALERT RIBBON JAM" },
+ { 0x17028D5A, "(Novell) Attribute ALERT PRINTER RELEASE LEVER NOT ENGAGED" },
+ { 0x17028D5B, "(Novell) Attribute ALERT PRINTER RELEASE LEVER ENGAGED" },
+ { 0x17028D5C, "(Novell) Attribute ALERT DUPLEX NOT SUPPORTED" },
+ { 0x17028D5D, "(Novell) Attribute ALERT PAPER ORIENTATION WRONG" },
+ { 0x17028D5E, "(Novell) Attribute ALERT STAPLER OPEN" },
+ { 0x17028D5F, "(Novell) Attribute ALERT STAPLER OTHER" },
+ { 0x17028E08, "(Novell) Attribute ALERT PRINT HANDLER NOT CONNECTED" },
+ { 0x17028E09, "(Novell) Attribute ALERT PRINT HANDLER OTHER ERROR" },
+ { 0x17028E0A, "(Novell) Attribute ALERT JOB START TIMEOUT" },
+ { 0x17028E0B, "(Novell) Attribute ALERT JOB END TIMEOUT" },
+ { 0x17028E0C, "(Novell) Attribute ALERT PDS PRINT HANDLER OTHER" },
+ { 0x17028E0D, "(Novell) Attribute ALERT PRINT HANDLER VOLUME NOT MOUNTED" },
+ { 0x17028E0E, "(Novell) Attribute ALERT PRINT HANDLER VOLUME FULL" },
+ { 0x17028E0F, "(Novell) Attribute ALERT ACCOUNTING SERVICE ERROR" },
+ { 0x17028E10, "(Novell) Attribute ALERT DEVICE PAUSED" },
+ { 0x17028E11, "(Novell) Attribute ALERT DEVICE INPUT PAUSED" },
+ { 0x17028E12, "(Novell) Attribute ALERT DEVICE SHUTDOWN" },
+ { 0x17028E13, "(Novell) Attribute ALERT GATEWAY WITHOUT CONFIGURATION FILE" },
+ { 0x17028E14, "(Novell) Attribute ALERT PRINTER STATE CHANGED" },
+ { 0x17028E15, "(Novell) Attribute ALERT PRINTER STOPPED" },
+ { 0x0, NULL },
+};
+
+static const value_string object_ids_15[] = { /* 060F6086 480186F837 (LENGTH 15)*/
+ /* These values are 0x01040003+(defined number)*/
+ { 0x01050101, "(Novell) Attribute PRINTER GENERAL CONFIGURATION CHANGES" },
+ { 0x01050102, "(Novell) Attribute PRINTER GENERAL CURRENT LOCAL" },
+ { 0x01050103, "(Novell) Attribute PRINTER GENERAL RESET" },
+ { 0x01050104, "(Novell) Attribute PRINTER GENERAL CURRENT OPERATION" },
+ { 0x01050105, "(Novell) Attribute PRINTER GENERAL SERVICE PERSON" },
+ { 0x01050106, "(Novell) Attribute PRINTER INPUT DEFAULT INDEX" },
+ { 0x01050107, "(Novell) Attribute PRINTER OUTPUT DEFAULT INDEX" },
+ { 0x01050108, "(Novell) Attribute PRINTER MARKER DEFAULT INDEX" },
+ { 0x01050109, "(Novell) Attribute PRINTER MEDIA PATH DEFAULT INDEX" },
+ { 0x0105010A, "(Novell) Attribute PRINTER CONSOLE LOCALIZATION" },
+ { 0x0105010B, "(Novell) Attribute PRINTER CONTINUOUS NUMBER DISPLAY LINES" },
+ { 0x0105010C, "(Novell) Attribute PRINTER CONTINUOUS NUMBER DISPLAY CHARACTERS" },
+ { 0x0105010D, "(Novell) Attribute PRINTER CONSOLE DISABLE" },
+ { 0x01050201, "(Novell) Attribute PRINTER STORAGE REFERENCE SEQUENCE NUMBER" },
+ { 0x01050202, "(Novell) Attribute PRINTER STORAGE REFERENCES INDEX" },
+ { 0x01050301, "(Novell) Attribute PRINTER DEVICE REFERENCE SEQUENCE NUMBER" },
+ { 0x01050302, "(Novell) Attribute PRINTER DEVICE REFERENCE INDEX" },
+ { 0x01070101, "(Novell) Attribute PRINTER LOCALIZATION INDEX" },
+ { 0x01070102, "(Novell) Attribute PRINTER LOCAL LANGUAGE" },
+ { 0x01070103, "(Novell) Attribute PRINTER LOCALIZATION COUNTRY" },
+ { 0x01070104, "(Novell) Attribute PRINTER LOCAL CHARACTER SET" },
+ { 0x03030204, "(Novell) Attribute HARDWARE DEVICE ID" },
+ { 0x03030205, "(Novell) Attribute HARDWARE DEVICE STATUS" },
+ { 0x03030501, "(Novell) Attribute HARDWARE PRINTER STATUS" },
+ { 0x03030502, "(Novell) Attribute HARDWARE PRINTER DETECTED ERROR STATE" },
+ { 0x03030604, "(Novell) Attribute HARDWARE DISK STORAGE CAPACITY" },
+ /* These values are 0x0104000F+(defined number)*/
+ { 0x01080201, "(Novell) Attribute PRINTER INPUT INDEX" },
+ { 0x01080202, "(Novell) Attribute PRINTER INPUT TYPE" },
+ { 0x01080203, "(Novell) Attribute PRINTER INPUT DIMINSION UNIT" },
+ { 0x01080204, "(Novell) Attribute PRINTER INPUT MEDIA DIMINSION FEED DDEC" },
+ { 0x01080205, "(Novell) Attribute PRINTER INPUT MEDIA DIMINSION XFEEDDDEC" },
+ { 0x01080206, "(Novell) Attribute PRINTER INPUT MEDIA DIMINSION FEEDDCHO" },
+ { 0x01080207, "(Novell) Attribute PRINTER INPUT MEDIA DIMINSION XFEEDDCHO" },
+ { 0x01080208, "(Novell) Attribute PRINTER INPUT CAPACITY UNIT" },
+ { 0x01080209, "(Novell) Attribute PRINTER INPUT MAXIMUM CAPACITY" },
+ { 0x0108020A, "(Novell) Attribute PRINTER INPUT CURRENT LEVEL" },
+ { 0x0108020B, "(Novell) Attribute PRINTER INPUT STATUS" },
+ { 0x0108020C, "(Novell) Attribute PRINTER INPUT MEDIA NAME" },
+ { 0x0108020D, "(Novell) Attribute PRINTER INPUT NAME" },
+ { 0x0108020E, "(Novell) Attribute PRINTER INPUT VENDOR NAME" },
+ { 0x0108020F, "(Novell) Attribute PRINTER INPUT MODEL" },
+ { 0x01080210, "(Novell) Attribute PRINTER INPUT VERSION" },
+ { 0x01080211, "(Novell) Attribute PRINTER INPUT SERIAL NUMBER" },
+ { 0x01080212, "(Novell) Attribute PRINTER INPUT DESCRIPTION" },
+ { 0x01080213, "(Novell) Attribute PRINTER INPUT SECURITY" },
+ /* These values are 0x01040010+(defined number)*/
+ { 0x01090201, "(Novell) Attribute PRINTER OUTPUT INDEX" },
+ { 0x01090202, "(Novell) Attribute PRINTER OUTPUT TYPE" },
+ { 0x01090203, "(Novell) Attribute PRINTER OUTPUT CAPACITY UNIT" },
+ { 0x01090204, "(Novell) Attribute PRINTER OUTPUT MAXIMUM CAPACITY" },
+ { 0x01090205, "(Novell) Attribute PRINTER OUTPUT REMAINING CAPACITY" },
+ { 0x01090206, "(Novell) Attribute PRINTER OUTPUT STATUS" },
+ { 0x01090207, "(Novell) Attribute PRINTER OUTPUT NAME" },
+ { 0x01090208, "(Novell) Attribute PRINTER OUTPUT VENDOR NAME" },
+ { 0x01090209, "(Novell) Attribute PRINTER OUTPUT MODEL" },
+ { 0x0109020A, "(Novell) Attribute PRINTER OUTPUT VERSION" },
+ { 0x0109020B, "(Novell) Attribute PRINTER OUTPUT SERIAL NUMBER" },
+ { 0x0109020C, "(Novell) Attribute PRINTER OUTPUT DESCRIPTION" },
+ { 0x0109020D, "(Novell) Attribute PRINTER OUTPUT SECURITY" },
+ { 0x0109020E, "(Novell) Attribute PRINTER OUTPUT DIMINSION UNIT" },
+ { 0x0109020F, "(Novell) Attribute PRINTER OUTPUT MAXIMUM DIMINSION FEED DIRECTION" },
+ { 0x01090210, "(Novell) Attribute PRINTER OUTPUT MAXIMUM DIMINSION TRANSFER FEED DIRECTION" },
+ { 0x01090211, "(Novell) Attribute PRINTER OUTPUT MINIMUM DIMINSION FEED DIRECTION" },
+ { 0x01090212, "(Novell) Attribute PRINTER OUTPUT MINIMUM DIMINSION TRANSFER FEED DIRECTION" },
+ { 0x01090213, "(Novell) Attribute PRINTER OUTPUT STACK INGORE DER" },
+ { 0x01090214, "(Novell) Attribute PRINTER OUTPUT PAGE DELIVORY ENTRY" },
+ { 0x01090215, "(Novell) Attribute PRINTER OUTPUT BURSTING" },
+ { 0x01090216, "(Novell) Attribute PRINTER OUTPUT DECOLLATING" },
+ { 0x01090217, "(Novell) Attribute PRINTER OUTPUT PAGE COLLATED" },
+ { 0x01090218, "(Novell) Attribute PRINTER OUTPUT OFFSET STACKING" },
+ /* These values are 0x01040017+(defined number)*/
+ { 0x02819C29, "(Novell) Attribute ALERT SUBUNIT MISSING" },
+ { 0x02819C2A, "(Novell) Attribute ALERT SUBUNIT OK" },
+ { 0x0281A328, "(Novell) Attribute ALERT OUTPUT TRAY MBX SELECTED" },
+ { 0x0281A40B, "(Novell) Attribute ALERT FUSER TIME FAILED" },
+ /* These values are 0x01040019+(defined number)*/
+ { 0x01000201, "(Novell) Attribute PRINTER MARKER INDEX" },
+ { 0x01000202, "(Novell) Attribute PRINTER MARKER MARK TECH" },
+ { 0x01000203, "(Novell) Attribute PRINTER MARKER COUNT UNIT" },
+ { 0x01000204, "(Novell) Attribute PRINTER MARKER LIFE COUNT" },
+ { 0x01000205, "(Novell) Attribute PRINTER MARKER POWER ON COUNT" },
+ { 0x01000206, "(Novell) Attribute PRINTER MARKER PROCESS COLORS" },
+ { 0x01000207, "(Novell) Attribute PRINTER MARKER SPOT COLORANTS" },
+ { 0x01000208, "(Novell) Attribute PRINTER MARKER ADD UNIT" },
+ { 0x01000209, "(Novell) Attribute PRINTER MARKER ADD RFEEDDIR" },
+ { 0x0100020A, "(Novell) Attribute PRINTER MARKER ADDRXFEEDDIR" },
+ { 0x0100020B, "(Novell) Attribute PRINTER MARKER NORTH MARGIN" },
+ { 0x0100020C, "(Novell) Attribute PRINTER MARKER SOUTH MARGIN" },
+ { 0x0100020D, "(Novell) Attribute PRINTER MARKER WEST MARGIN" },
+ { 0x0100020E, "(Novell) Attribute PRINTER MARKER EAST MARGIN" },
+ { 0x0100020F, "(Novell) Attribute PRINTER MARKER STATUS" },
+ /* These values are 0x0104001A+(defined number)*/
+ { 0x010D0401, "(Novell) Attribute PRINTER MEDIA PATH INDEX" },
+ { 0x010D0402, "(Novell) Attribute PRINTER MEDIA PATH MAXIMUM SPEED UNIT" },
+ { 0x010D0403, "(Novell) Attribute PRINTER MEDIA PATH SIZE UNIT" },
+ { 0x010D0404, "(Novell) Attribute PRINTER MEDIA PATH MAXIMUM SPEED" },
+ { 0x010D0405, "(Novell) Attribute PRINTER MEDIA PATH MAXIMUM FEED DIRECTION" },
+ { 0x010D0406, "(Novell) Attribute PRINTER MEDIA PATH MAXIMUM TRANSFER FEED DIRECTION" },
+ { 0x010D0407, "(Novell) Attribute PRINTER MEDIA PATH MINIMUM FEED DIRECTION" },
+ { 0x010D0408, "(Novell) Attribute PRINTER MEDIA PATH MINIMUM TRANSFER FEED DIRECTION" },
+ { 0x010D0409, "(Novell) Attribute PRINTER MEDIA PATH TYPE" },
+ { 0x010D040A, "(Novell) Attribute PRINTER MEDIA PATH DESCRIPTION" },
+ { 0x010D040B, "(Novell) Attribute PRINTER MEDIA PATH STATUS" },
+ /* These values are 0x0104001B+(defined number)*/
+ { 0x010E0101, "(Novell) Attribute PRINTER CHANNEL INDEX" },
+ { 0x010E0102, "(Novell) Attribute PRINTER CHANNEL TYPE" },
+ { 0x010E0103, "(Novell) Attribute PRINTER CHANNEL PROTOVERS" },
+ { 0x010E0104, "(Novell) Attribute PRINTER CHANNEL CURRENT JCL INDEX" },
+ { 0x010E0105, "(Novell) Attribute PRINTER CHANNEL DEFAULT PDL INDEX" },
+ { 0x010E0106, "(Novell) Attribute PRINTER CHANNEL STATE" },
+ { 0x010E0107, "(Novell) Attribute PRINTER CHANNEL IF INDEX" },
+ { 0x010E0108, "(Novell) Attribute PRINTER CHANNEL STATUS" },
+ /* These values are 0x0104001C+(defined number)*/
+ { 0x010F0101, "(Novell) Attribute PRINTER INTERPRETER INDEX" },
+ { 0x010F0102, "(Novell) Attribute PRINTER INTERPRETER LANGUAGE FAM" },
+ { 0x010F0103, "(Novell) Attribute PRINTER INTERPRETER LANGUAGE LEVEL" },
+ { 0x010F0104, "(Novell) Attribute PRINTER INTERPRETER LANGUAGE VERSION" },
+ { 0x010F0105, "(Novell) Attribute PRINTER INTERPRETER DESCRIPTION" },
+ { 0x010F0106, "(Novell) Attribute PRINTER INTERPRETER VERSION" },
+ { 0x010F0107, "(Novell) Attribute PRINTER INTERPRETER DEFAULT ORIENTATION" },
+ { 0x010F0108, "(Novell) Attribute PRINTER INTERPRETER FEED ADDRESS" },
+ { 0x010F0109, "(Novell) Attribute PRINTER INTERPRETER TRANSFER FEED ADDRESS" },
+ { 0x010F010A, "(Novell) Attribute PRINTER INTERPRETER DEFAULT CHARACTERS IN" },
+ { 0x010F010B, "(Novell) Attribute PRINTER INTERPRETER DEFAULT CHARACTERS OUT" },
+ { 0x010F010C, "(Novell) Attribute PRINTER INTERPRETER TWO WAY" },
+ /* These values are 0x0104001E+(defined number)*/
+ { 0x01000101, "(Novell) Attribute PRINTER MARKER SUPPLIES INDEX" },
+ { 0x01000102, "(Novell) Attribute PRINTER MARKER SUPPLIES MARKER INDEX" },
+ { 0x01000103, "(Novell) Attribute PRINTER MARKER SUPPLIES COLOR INDEX" },
+ { 0x01000104, "(Novell) Attribute PRINTER MARKER SUPPLIES CLASS" },
+ { 0x01000105, "(Novell) Attribute PRINTER MARKER SUPPLIES TYPE" },
+ { 0x01000106, "(Novell) Attribute PRINTER MARKER SUPPLIES DESCRIPTION" },
+ { 0x01000107, "(Novell) Attribute PRINTER MARKER SUPPLIES SUPPLY UNIT" },
+ { 0x01000108, "(Novell) Attribute PRINTER MARKER SUPPLIES MAXIMUM CAPACITY" },
+ { 0x01000109, "(Novell) Attribute PRINTER MARKER SUPPLIES LEVEL" },
+ /* These values are 0x0104001F+(defined number)*/
+ { 0x01000101, "(Novell) Attribute PRINTER MARKER COLORANT INDEX" },
+ { 0x01000102, "(Novell) Attribute PRINTER MARKER COLORANT MARKER INDEX" },
+ { 0x01000103, "(Novell) Attribute PRINTER MARKER COLORANT ROLE" },
+ { 0x01000104, "(Novell) Attribute PRINTER MARKER COLORANT VALUE" },
+ { 0x01000105, "(Novell) Attribute PRINTER MARKER COLORANT TONE" },
+ /* These values are 0x01040020+(defined number)*/
+ { 0x01000101, "(Novell) Attribute PRINTER COVER INDEX" },
+ { 0x01000102, "(Novell) Attribute PRINTER COVER DESCRIPTION" },
+ { 0x01000103, "(Novell) Attribute PRINTER COVER STATUS" },
+ /* These values are 0x01040021+(defined number)*/
+ { 0x01000601, "(Novell) Attribute PRINTER CONSOLE LIGHT INDEX" },
+ { 0x01000602, "(Novell) Attribute PRINTER CONSOLE ON TIME" },
+ { 0x01000603, "(Novell) Attribute PRINTER CONSOLE OFF TIME" },
+ { 0x01000604, "(Novell) Attribute PRINTER CONSOLE COLOR" },
+ { 0x01000605, "(Novell) Attribute PRINTER CONSOLE DESCRIPTION" },
+ /* These values are 0x01040022+(defined number)*/
+ { 0x01000501, "(Novell) Attribute PRINTER CONSOLE DISPLAY BUFFER INDEX" },
+ { 0x01000502, "(Novell) Attribute PRINTER CONSOLE DISPLAY BUFFER TEXT" },
+ /* These values are 0x01040025+(defined number)*/
+ { 0x011E0101, "(Novell) Attribute FINISH DEVICE INDEX" },
+ { 0x011E0102, "(Novell) Attribute FINISH DEVICE TYPE" },
+ { 0x011E0103, "(Novell) Attribute FINISH DEVICE PRESENT ON OFF" },
+ { 0x011E0104, "(Novell) Attribute FINISH DEVICE CAPACITY UNIT" },
+ { 0x011E0105, "(Novell) Attribute FINISH DEVICE MAXIMUM CAPACITY" },
+ { 0x011E0106, "(Novell) Attribute FINISH DEVICE CURRENT CAPACITY" },
+ { 0x011E0107, "(Novell) Attribute FINISH DEVICE ASSOCIATED MEDIA PATH" },
+ { 0x011E0108, "(Novell) Attribute FINISH DEVICE ASSOCIATED OUTPUTS" },
+ { 0x011E0109, "(Novell) Attribute FINISH DEVICE STATUS" },
+ { 0x011E010A, "(Novell) Attribute FINISH DEVICE DESCRIPTION" },
+ { 0x01210101, "(Novell) Attribute FINISH DEVICE OTHER" },
+ { 0x01210103, "(Novell) Attribute FINISH DEVICE NAME" },
+ { 0x01210104, "(Novell) Attribute FINISH DEVICE VENDOR NAME" },
+ { 0x01210105, "(Novell) Attribute FINISH DEVICE MODEL" },
+ { 0x01210106, "(Novell) Attribute FINISH DEVICE VERSION" },
+ { 0x01210107, "(Novell) Attribute FINISH DEVICE SERIAL NUMBER" },
+ { 0x01210108, "(Novell) Attribute FINISH DEVICE MAXIMUM SHEETS" },
+ { 0x01210109, "(Novell) Attribute FINISH PROCESS OFFSET UNITS" },
+ { 0x0121010A, "(Novell) Attribute FINISH REFERENCE EDGE" },
+ { 0x0121010B, "(Novell) Attribute FINISH AXIS OFFSET" },
+ { 0x0121010C, "(Novell) Attribute FINISH JOG EDGE" },
+ { 0x0121010D, "(Novell) Attribute FINISH HEAD LOCATION" },
+ { 0x0121010E, "(Novell) Attribute FINISH OPERATOR RESTRICTIONS" },
+ { 0x0121010F, "(Novell) Attribute FINISH NUMBER OF POSITIONS" },
+ { 0x01210110, "(Novell) Attribute FINISH NAMED CONFIGURATION" },
+ { 0x01210111, "(Novell) Attribute FINISH MEDIA TYPE RESTRICT" },
+ { 0x01210112, "(Novell) Attribute FINISH PRINTER INPUT TRAY SUPPORT" },
+ { 0x01210113, "(Novell) Attribute FINISH PREVIOUS FINISH IN GOP" },
+ { 0x01210114, "(Novell) Attribute FINISH NEXT FINISH IN GOP" },
+ { 0x0121011E, "(Novell) Attribute STITCHING TYPE" },
+ { 0x0121011F, "(Novell) Attribute STITCHING DIRECTION" },
+ { 0x01210120, "(Novell) Attribute STITCHING ANGLE" },
+ { 0x01210128, "(Novell) Attribute FOLDING TYPE" },
+ { 0x01210132, "(Novell) Attribute BINDING TYPE" },
+ { 0x01210150, "(Novell) Attribute PUNCH HOLE TYPE" },
+ { 0x01210151, "(Novell) Attribute PUNCH HOLE SIZE LONG DIMENSION" },
+ { 0x01210152, "(Novell) Attribute PUNCH HOLE SIZE SHORT DIMENSION" },
+ { 0x01210153, "(Novell) Attribute PUNCH PATTERN" },
+ { 0x01210164, "(Novell) Attribute SLITTING TYPE" },
+ /* These values are 0x01040026+(defined number)*/
+ { 0x011F0101, "(Novell) Attribute FINISH SUPPLY INDEX" },
+ { 0x011F0102, "(Novell) Attribute FINISH SUPPLY DEVICE INDEX" },
+ { 0x011F0103, "(Novell) Attribute FINISH SUPPLY CLASS" },
+ { 0x011F0104, "(Novell) Attribute FINISH SUPPLY TYPE" },
+ { 0x011F0105, "(Novell) Attribute FINISH SUPPLY DESCRIPTION" },
+ { 0x011F0106, "(Novell) Attribute FINISH SUPPLY UNIT" },
+ { 0x011F0107, "(Novell) Attribute FINISH SUPPLY MAXIMUM CAPACITY" },
+ { 0x011F0108, "(Novell) Attribute FINISH SUPPLY CURRENT LEVEL" },
+ { 0x011F0109, "(Novell) Attribute FINISH SUPPLY COLOR NAME" },
+ { 0x0, NULL },
+};
+
+static const value_string object_ids_16[] = { /* 06106086 480186F83701 (LENGTH 16)*/
+ /* These values are 0x04002501+(defined number)*/
+ { 0x21018102, "(Novell) Attribute WRAPPING TYPE" },
+ { 0x21018120, "(Novell) Attribute STACK OUTPUT TYPE" },
+ { 0x21018121, "(Novell) Attribute STACK OFFSET" },
+ { 0x21018122, "(Novell) Attribute STACK ROTATION" },
+ { 0x0, NULL },
+};
diff --git a/epan/dissectors/packet-netbios.c b/epan/dissectors/packet-netbios.c
new file mode 100644
index 0000000000..973731b77f
--- /dev/null
+++ b/epan/dissectors/packet-netbios.c
@@ -0,0 +1,1430 @@
+/* packet-netbios.c
+ * Routines for NetBIOS protocol packet disassembly
+ * Jeff Foster <jfoste@woodward.com>
+ * Copyright 1999 Jeffrey C. Foster
+ *
+ * derived from the packet-nbns.c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "llcsaps.h"
+#include "reassemble.h"
+#include "prefs.h"
+#include "packet-netbios.h"
+
+/* Netbios command numbers */
+#define NB_ADD_GROUP 0x00
+#define NB_ADD_NAME 0x01
+#define NB_NAME_IN_CONFLICT 0x02
+#define NB_STATUS_QUERY 0x03
+#define NB_TERMINATE_TRACE_R 0x07
+#define NB_DATAGRAM 0x08
+#define NB_DATAGRAM_BCAST 0x09
+#define NB_NAME_QUERY 0x0a
+#define NB_ADD_NAME_RESP 0x0d
+#define NB_NAME_RESP 0x0e
+#define NB_STATUS_RESP 0x0f
+#define NB_TERMINATE_TRACE_LR 0x13
+#define NB_DATA_ACK 0x14
+#define NB_DATA_FIRST_MIDDLE 0x15
+#define NB_DATA_ONLY_LAST 0x16
+#define NB_SESSION_CONFIRM 0x17
+#define NB_SESSION_END 0x18
+#define NB_SESSION_INIT 0x19
+#define NB_NO_RECEIVE 0x1a
+#define NB_RECEIVE_OUTSTANDING 0x1b
+#define NB_RECEIVE_CONTINUE 0x1c
+#define NB_KEEP_ALIVE 0x1f
+
+/* Offsets of fields in the NetBIOS header. */
+#define NB_LENGTH 0
+#define NB_DELIMITER 2
+#define NB_COMMAND 4
+#define NB_FLAGS 5
+#define NB_DATA1 5
+#define NB_RESYNC 6
+#define NB_DATA2 6
+#define NB_CALL_NAME_TYPE 7
+#define NB_XMIT_CORL 8
+#define NB_RESP_CORL 10
+#define NB_RMT_SES 12
+#define NB_LOCAL_SES 13
+#define NB_RECVER_NAME 12
+#define NB_SENDER_NAME 28
+
+
+static int proto_netbios = -1;
+static int hf_netb_cmd = -1;
+static int hf_netb_hdr_len = -1;
+static int hf_netb_xmit_corrl = -1;
+static int hf_netb_resp_corrl = -1;
+static int hf_netb_call_name_type = -1;
+static int hf_netb_ack = -1;
+static int hf_netb_ack_with_data = -1;
+static int hf_netb_ack_expected = -1;
+static int hf_netb_recv_cont_req = -1;
+static int hf_netb_send_no_ack = -1;
+static int hf_netb_version = -1;
+static int hf_netb_largest_frame = -1;
+static int hf_netb_nb_name = -1;
+static int hf_netb_nb_name_type = -1;
+static int hf_netb_status_buffer_len = -1;
+static int hf_netb_status = -1;
+static int hf_netb_name_type = -1;
+static int hf_netb_max_data_recv_size = -1;
+static int hf_netb_termination_indicator = -1;
+static int hf_netb_num_data_bytes_accepted = -1;
+static int hf_netb_local_ses_no = -1;
+static int hf_netb_remote_ses_no = -1;
+static int hf_netb_data1 = -1;
+static int hf_netb_data2 = -1;
+static int hf_netb_fragments = -1;
+static int hf_netb_fragment = -1;
+static int hf_netb_fragment_overlap = -1;
+static int hf_netb_fragment_overlap_conflict = -1;
+static int hf_netb_fragment_multiple_tails = -1;
+static int hf_netb_fragment_too_long_fragment = -1;
+static int hf_netb_fragment_error = -1;
+
+static gint ett_netb = -1;
+static gint ett_netb_name = -1;
+static gint ett_netb_flags = -1;
+static gint ett_netb_status = -1;
+static gint ett_netb_fragments = -1;
+static gint ett_netb_fragment = -1;
+
+static const fragment_items netbios_frag_items = {
+ &ett_netb_fragment,
+ &ett_netb_fragments,
+ &hf_netb_fragments,
+ &hf_netb_fragment,
+ &hf_netb_fragment_overlap,
+ &hf_netb_fragment_overlap_conflict,
+ &hf_netb_fragment_multiple_tails,
+ &hf_netb_fragment_too_long_fragment,
+ &hf_netb_fragment_error,
+ NULL,
+ "fragments"
+};
+
+static dissector_handle_t data_handle;
+
+/* The strings for the station type, used by get_netbios_name function;
+ many of them came from the file "NetBIOS.txt" in the Zip archive at
+
+ http://www.net3group.com/ftp/browser.zip
+ */
+
+static const value_string nb_name_type_vals[] = {
+ {0x00, "Workstation/Redirector"},
+ {0x01, "Browser"},
+ {0x02, "Workstation/Redirector"},
+ /* not sure what 0x02 is, I'm seeing alot of them however */
+ /* i'm seeing them with workstation/redirection host
+ announcements */
+ {0x03, "Messenger service/Main name"},
+ {0x05, "Forwarded name"},
+ {0x06, "RAS Server service"},
+ {0x1b, "Domain Master Browser"},
+ {0x1c, "Domain Controllers"},
+ {0x1d, "Local Master Browser"},
+ {0x1e, "Browser Election Service"},
+ {0x1f, "Net DDE Service"},
+ {0x20, "Server service"},
+ {0x21, "RAS client service"},
+ {0x22, "Exchange Interchange (MSMail Connector)"},
+ {0x23, "Exchange Store"},
+ {0x24, "Exchange Directory"},
+ {0x2b, "Lotus Notes Server service"},
+ {0x30, "Modem sharing server service"},
+ {0x31, "Modem sharing client service"},
+ {0x43, "SMS Clients Remote Control"},
+ {0x44, "SMS Administrators Remote Control Tool"},
+ {0x45, "SMS Clients Remote Chat"},
+ {0x46, "SMS Clients Remote Transfer"},
+ {0x4c, "DEC Pathworks TCP/IP Service on Windows NT"},
+ {0x52, "DEC Pathworks TCP/IP Service on Windows NT"},
+ {0x6a, "Microsoft Exchange IMC"},
+ {0x87, "Microsoft Exchange MTA"},
+ {0xbe, "Network Monitor Agent"},
+ {0xbf, "Network Monitor Analyzer"},
+ {0x00, NULL}
+};
+
+/* Tables for reassembly of fragments. */
+static GHashTable *netbios_fragment_table = NULL;
+static GHashTable *netbios_reassembled_table = NULL;
+
+/* defragmentation of NetBIOS Frame */
+static gboolean netbios_defragment = TRUE;
+
+/* See
+
+ http://www.s390.ibm.com/bookmgr-cgi/bookmgr.cmd/BOOKS/BK8P7001/CCONTENTS
+
+ and
+
+ http://ourworld.compuserve.com/homepages/TimothyDEvans/contents.htm
+
+ for information about the NetBIOS Frame Protocol (which is what this
+ module dissects). */
+
+/* the strings for the command types */
+
+static const value_string cmd_vals[] = {
+ { NB_ADD_GROUP, "Add Group Name Query" },
+ { NB_ADD_NAME, "Add Name Query" },
+ { NB_NAME_IN_CONFLICT, "Name In Conflict" },
+ { NB_STATUS_QUERY, "Status Query" },
+ { NB_TERMINATE_TRACE_R, "Terminate Trace" },
+ { NB_DATAGRAM, "Datagram" },
+ { NB_DATAGRAM_BCAST, "Broadcast Datagram" },
+ { NB_NAME_QUERY, "Name Query" },
+ { NB_ADD_NAME_RESP, "Add Name Response" },
+ { NB_NAME_RESP, "Name Recognized" },
+ { NB_STATUS_RESP, "Status Response" },
+ { NB_TERMINATE_TRACE_LR, "Terminate Trace" },
+ { NB_DATA_ACK, "Data Ack" },
+ { NB_DATA_FIRST_MIDDLE, "Data First Middle" },
+ { NB_DATA_ONLY_LAST, "Data Only Last" },
+ { NB_SESSION_CONFIRM, "Session Confirm" },
+ { NB_SESSION_END, "Session End" },
+ { NB_SESSION_INIT, "Session Initialize" },
+ { NB_NO_RECEIVE, "No Receive" },
+ { NB_RECEIVE_OUTSTANDING, "Receive Outstanding" },
+ { NB_RECEIVE_CONTINUE, "Receive Continue" },
+ { NB_KEEP_ALIVE, "Session Alive" },
+ { 0, NULL }
+};
+
+static const value_string name_types[] = {
+ { 0, "Unique name" },
+ { 1, "Group name" },
+ { 0, NULL }
+};
+
+static const true_false_string flags_set = {
+ "Set",
+ "Not set"
+};
+static const true_false_string flags_allowed = {
+ "Allowed",
+ "Not allowed"
+};
+static const true_false_string flags_yes_no = {
+ "Yes",
+ "No"
+};
+
+static const true_false_string netb_version_str = {
+ "2.00 or higher",
+ "1.xx"
+};
+
+static const value_string termination_indicator_vals[] = {
+ { 0x0000, "Normal session end" },
+ { 0x0001, "Abnormal session end" },
+ { 0, NULL }
+};
+
+static const value_string status_vals[] = {
+ { 0, "Add name not in process" },
+ { 1, "Add name in process" },
+ { 0, NULL }
+};
+
+static const value_string max_frame_size_vals[] = {
+ { 0, "516" },
+ { 1, "1500" },
+ { 2, "2052" },
+ { 3, "4472" },
+ { 4, "8144" },
+ { 5, "11407" },
+ { 6, "17800" }, /* 17800 in TR spec, 17749 in NBF spec */
+ { 7, "65535" },
+ { 0, NULL }
+};
+
+
+void capture_netbios(packet_counts *ld)
+{
+ ld->netbios++;
+}
+
+
+int
+process_netbios_name(const guchar *name_ptr, char *name_ret)
+{
+ int i;
+ int name_type = *(name_ptr + NETBIOS_NAME_LEN - 1);
+ guchar name_char;
+ static const char hex_digits[16] = "0123456789abcdef";
+
+ for (i = 0; i < NETBIOS_NAME_LEN - 1; i++) {
+ name_char = *name_ptr++;
+ if (name_char >= ' ' && name_char <= '~')
+ *name_ret++ = name_char;
+ else {
+ /* It's not printable; show it as <XX>, where
+ XX is the value in hex. */
+ *name_ret++ = '<';
+ *name_ret++ = hex_digits[(name_char >> 4)];
+ *name_ret++ = hex_digits[(name_char & 0x0F)];
+ *name_ret++ = '>';
+ }
+ }
+ *name_ret = '\0';
+
+ /* Remove trailing space characters from name. */
+
+ name_ret--;
+
+ for (i = 0; i < NETBIOS_NAME_LEN - 1; i++) {
+ if (*name_ret != ' ') {
+ *(name_ret + 1) = 0;
+ break;
+ }
+ name_ret--;
+ }
+
+ return name_type;
+}
+
+
+int get_netbios_name( tvbuff_t *tvb, int offset, char *name_ret)
+
+{/* Extract the name string and name type. Return the name string in */
+ /* name_ret and return the name_type. */
+
+ return process_netbios_name( tvb_get_ptr( tvb, offset, NETBIOS_NAME_LEN ), name_ret);
+}
+
+
+/*
+ * Get a string describing the type of a NetBIOS name.
+ */
+char *
+netbios_name_type_descr(int name_type)
+{
+ return val_to_str(name_type, nb_name_type_vals, "Unknown");
+}
+
+void netbios_add_name(char* label, tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+
+{/* add a name field display tree. Display the name and station type in sub-tree */
+
+ proto_tree *field_tree;
+ proto_item *tf;
+ char name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
+ int name_type;
+ char *name_type_str;
+
+ /* decode the name field */
+ name_type = get_netbios_name( tvb, offset, name_str);
+ name_type_str = netbios_name_type_descr(name_type);
+ tf = proto_tree_add_text( tree, tvb, offset, NETBIOS_NAME_LEN,
+ "%s: %s<%02x> (%s)", label, name_str, name_type, name_type_str);
+
+ field_tree = proto_item_add_subtree( tf, ett_netb_name);
+ proto_tree_add_string_format( field_tree, hf_netb_nb_name, tvb, offset,
+ 15, name_str, "%s", name_str);
+ proto_tree_add_uint_format( field_tree, hf_netb_nb_name_type, tvb, offset + 15, 1, name_type,
+ "0x%02x (%s)", name_type, name_type_str);
+}
+
+
+static void netbios_data_first_middle_flags( tvbuff_t *tvb, proto_tree *tree, int offset)
+
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint flags = tvb_get_guint8( tvb, offset);
+
+ /* decode the flag field for Data First Middle packet*/
+
+ tf = proto_tree_add_text(tree, tvb, offset, 1,
+ "Flags: 0x%02x", flags);
+ field_tree = proto_item_add_subtree(tf, ett_netb_flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_ack, tvb, offset, 1, flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_ack_expected, tvb, offset, 1, flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_recv_cont_req, tvb, offset, 1, flags);
+}
+
+static void netbios_data_only_flags( tvbuff_t *tvb, proto_tree *tree,
+ int offset)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint flags = tvb_get_guint8( tvb, offset);
+
+ /* decode the flag field for Data Only Last packet*/
+
+ tf = proto_tree_add_text(tree, tvb, offset, 1,
+ "Flags: 0x%02x", flags);
+ field_tree = proto_item_add_subtree(tf, ett_netb_flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_ack, tvb, offset, 1, flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_ack_with_data, tvb, offset, 1, flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_ack_expected, tvb, offset, 1, flags);
+}
+
+
+
+static void netbios_add_ses_confirm_flags( tvbuff_t *tvb, proto_tree *tree,
+ int offset)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint flags = tvb_get_guint8( tvb, offset);
+
+ /* decode the flag field for Session Confirm packet */
+ tf = proto_tree_add_text(tree, tvb, offset, 1,
+ "Flags: 0x%02x", flags);
+ field_tree = proto_item_add_subtree( tf, ett_netb_flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_send_no_ack, tvb, offset, 1, flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_version, tvb, offset, 1, flags);
+}
+
+
+static void netbios_add_session_init_flags( tvbuff_t *tvb, proto_tree *tree,
+ int offset)
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint flags = tvb_get_guint8( tvb, offset);
+ /* decode the flag field for Session Init packet */
+
+ tf = proto_tree_add_text(tree, tvb, offset, 1,
+ "Flags: 0x%02x", flags);
+ field_tree = proto_item_add_subtree(tf, ett_netb_flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_send_no_ack, tvb, offset, 1, flags);
+
+ proto_tree_add_uint( field_tree, hf_netb_largest_frame, tvb, offset, 1,
+ flags);
+
+ proto_tree_add_boolean( field_tree, hf_netb_version, tvb, offset, 1, flags);
+}
+
+
+static void netbios_no_receive_flags( tvbuff_t *tvb, proto_tree *tree,
+ int offset)
+
+{
+ proto_tree *field_tree;
+ proto_item *tf;
+ guint flags = tvb_get_guint8( tvb, offset);
+
+ /* decode the flag field for No Receive packet*/
+
+ tf = proto_tree_add_text(tree, tvb, offset, 1,
+ "Flags: 0x%02x", flags);
+
+ if (flags & 0x02) {
+ field_tree = proto_item_add_subtree(tf, ett_netb_flags);
+ proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(flags, 0x02, 8,
+ "SEND.NO.ACK data not received", NULL));
+ }
+}
+
+
+/************************************************************************/
+/* */
+/* The routines to display the netbios field values in the tree */
+/* */
+/************************************************************************/
+
+
+static void nb_xmit_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* display the transmit correlator */
+
+ proto_tree_add_item( tree, hf_netb_xmit_corrl, tvb, offset + NB_XMIT_CORL,
+ 2, TRUE);
+}
+
+
+static void nb_resp_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* display the response correlator */
+
+ proto_tree_add_item( tree, hf_netb_resp_corrl, tvb, offset + NB_RESP_CORL,
+ 2, TRUE);
+}
+
+
+static void nb_call_name_type( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* display the call name type */
+
+ proto_tree_add_item( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
+ 1, TRUE);
+
+}
+
+
+static guint8 nb_local_session( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* add the local session to tree, and return its value */
+
+ guint8 local_session = tvb_get_guint8( tvb, offset + NB_LOCAL_SES);
+
+ proto_tree_add_uint( tree, hf_netb_local_ses_no, tvb, offset + NB_LOCAL_SES, 1,
+ local_session);
+
+ return local_session;
+}
+
+
+static guint8 nb_remote_session( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* add the remote session to tree, and return its value */
+
+ guint8 remote_session = tvb_get_guint8( tvb, offset + NB_RMT_SES);
+
+ proto_tree_add_uint( tree, hf_netb_remote_ses_no, tvb, offset + NB_RMT_SES, 1,
+ remote_session);
+
+ return remote_session;
+}
+
+
+static void nb_data1(int hf, tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* add the DATA1 to tree with specified hf_ value */
+
+ proto_tree_add_item( tree, hf, tvb, offset + NB_DATA1, 1, TRUE);
+
+}
+
+
+static void nb_data2(int hf, tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* add the DATA2 to tree with specified hf_ value */
+
+ proto_tree_add_item( tree, hf, tvb, offset + NB_DATA2, 2, TRUE);
+
+}
+
+
+static void nb_resync_indicator( tvbuff_t *tvb, int offset, proto_tree *tree, char *cmd_str)
+{
+ guint16 resync_indicator = tvb_get_letohs( tvb, offset + NB_DATA2);
+
+
+ switch (resync_indicator) {
+
+ case 0x0000:
+ proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
+ "Re-sync indicator: No re-sync");
+ break;
+
+ case 0x0001:
+ proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
+ "Re-sync indicator: First '%s' following 'Receive Outstanding'", cmd_str);
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
+ "Re-sync indicator: 0x%04x", resync_indicator);
+ break;
+ }
+}
+
+/************************************************************************/
+/* */
+/* The routines called by the top level to handle individual commands */
+/* */
+/************************************************************************/
+
+static guint32
+dissect_netb_unknown( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle any unknown commands, do nothing */
+
+ proto_tree_add_text(tree, tvb, offset + NB_COMMAND + 1, -1,
+ "Unknown NetBIOS command data");
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_add_group_name( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the ADD GROUP NAME QUERY command */
+
+ nb_resp_corrl( tvb, offset, tree);
+
+ netbios_add_name("Group name to add", tvb, offset + NB_SENDER_NAME,
+ tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_add_name( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the ADD NAME QUERY command */
+
+ nb_resp_corrl( tvb, offset, tree);
+
+ netbios_add_name("Name to add", tvb, offset + NB_SENDER_NAME, tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_name_in_conflict( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the NAME IN CONFLICT command */
+
+ netbios_add_name("Name In Conflict", tvb, offset + NB_RECVER_NAME,
+ tree);
+ netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME, tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_status_query( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the STATUS QUERY command */
+
+ guint8 status_request = tvb_get_guint8( tvb, offset + NB_DATA1);
+
+ switch (status_request) {
+
+ case 0:
+ proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
+ "Status request: NetBIOS 1.x or 2.0");
+ break;
+
+ case 1:
+ proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
+ "Status request: NetBIOS 2.1, initial status request");
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
+ "Status request: NetBIOS 2.1, %u names received so far",
+ status_request);
+ break;
+ }
+ nb_data2( hf_netb_status_buffer_len, tvb, offset, tree);
+ nb_resp_corrl( tvb, offset, tree);
+ netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
+ netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME, tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_terminate_trace( tvbuff_t *tvb _U_, int offset _U_, proto_tree *tree _U_)
+
+{/* Handle the TERMINATE TRACE command */
+
+ /*
+ * XXX - are any of the fields in this message significant?
+ * The IBM NetBIOS document shows them as "Reserved".
+ */
+
+ return 0;
+}
+
+
+static guchar zeroes[10];
+
+static guint32
+dissect_netb_datagram( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the DATAGRAM command */
+
+ netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
+ /* Weird. In some datagrams, this is 10 octets of 0, followed
+ by a MAC address.... */
+
+ if (memcmp( tvb_get_ptr( tvb,offset + NB_SENDER_NAME, 10), zeroes, 10) == 0) {
+ proto_tree_add_text( tree, tvb, offset + NB_SENDER_NAME + 10, 6,
+ "Sender's MAC Address: %s",
+ ether_to_str( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6)));
+ } else {
+ netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
+ tree);
+ }
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_datagram_bcast( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the DATAGRAM BROADCAST command */
+
+ /* We assume the same weirdness can happen here.... */
+ if ( memcmp( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6), zeroes, 10) == 0) {
+ proto_tree_add_text( tree, tvb, offset + NB_SENDER_NAME + 10, 6,
+ "Sender's Node Address: %s",
+ ether_to_str( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6)));
+ } else {
+ netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
+ tree);
+ }
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_name_query( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the NAME QUERY command */
+ guint8 local_session_number = tvb_get_guint8( tvb, offset + NB_DATA2);
+
+ if (local_session_number == 0) {
+ proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
+ "Local Session No.: 0 (FIND.NAME request)");
+ } else {
+ proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
+ "Local Session No.: 0x%02x", local_session_number);
+ }
+ nb_call_name_type( tvb, offset, tree);
+ nb_resp_corrl( tvb, offset, tree);
+ netbios_add_name("Query Name", tvb, offset + NB_RECVER_NAME, tree);
+ if (local_session_number != 0) {
+ netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
+ tree);
+ }
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_add_name_resp( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the ADD NAME RESPONSE command */
+
+ nb_data1( hf_netb_status, tvb, offset, tree);
+ nb_data2( hf_netb_name_type, tvb, offset, tree);
+ nb_xmit_corrl( tvb, offset, tree);
+ netbios_add_name("Name to be added", tvb, offset + NB_RECVER_NAME,
+ tree);
+ netbios_add_name("Name to be added", tvb, offset + NB_SENDER_NAME,
+ tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_name_resp( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the NAME RECOGNIZED command */
+ guint8 local_session_number = tvb_get_guint8( tvb, offset + NB_DATA2);
+
+ switch (local_session_number) {
+
+ case 0x00:
+ proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
+ "State of name: No LISTEN pending, or FIND.NAME response");
+ break;
+
+ case 0xFF:
+ proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
+ "State of name: LISTEN pending, but insufficient resources to establish session");
+ break;
+
+ default:
+ proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
+ "Local Session No.: 0x%02x", local_session_number);
+ break;
+ }
+ nb_call_name_type( tvb, offset, tree);
+ nb_xmit_corrl( tvb, offset, tree);
+ if (local_session_number != 0x00 && local_session_number != 0xFF)
+ nb_resp_corrl(tvb, offset, tree);
+ netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
+ if (local_session_number != 0x00 && local_session_number != 0xFF) {
+ netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
+ tree);
+ }
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_status_resp( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the STATUS RESPONSE command */
+ guint8 status_response = tvb_get_guint8( tvb, offset + NB_DATA1);
+ proto_item *td2;
+ proto_tree *data2_tree;
+ guint16 data2;
+
+ nb_call_name_type( tvb, offset, tree);
+ if (status_response == 0) {
+ proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
+ "Status response: NetBIOS 1.x or 2.0");
+ } else {
+ proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
+ "Status response: NetBIOS 2.1, %u names sent so far",
+ status_response);
+ }
+ data2 = tvb_get_letohs( tvb, offset + NB_DATA2);
+
+ td2 = proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2, "Status: 0x%04x",
+ data2);
+ data2_tree = proto_item_add_subtree(td2, ett_netb_status);
+ if (data2 & 0x8000) {
+ proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(data2, 0x8000, 8*2,
+ "Data length exceeds maximum frame size", NULL));
+ }
+ if (data2 & 0x4000) {
+ proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(data2, 0x4000, 8*2,
+ "Data length exceeds user's buffer", NULL));
+ }
+ proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
+ decode_numeric_bitfield(data2, 0x3FFF, 2*8,
+ "Status data length = %u"));
+ nb_xmit_corrl( tvb, offset, tree);
+ netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
+ netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
+ tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_data_ack( tvbuff_t* tvb, int offset, proto_tree *tree)
+
+{/* Handle the DATA ACK command */
+
+ nb_xmit_corrl( tvb, offset, tree);
+ nb_remote_session( tvb, offset, tree);
+ nb_local_session( tvb, offset, tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_data_first_middle( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the DATA FIRST MIDDLE command */
+
+ guint8 remote_session, local_session;
+
+ /*
+ * This is the first frame, or the middle frame, of a fragmented
+ * packet.
+ *
+ * XXX - there are no sequence numbers, so we have to assume
+ * that fragments arrive in order with no duplicates.
+ * In fact, 802.2 LLC is supposed to handle that, so we
+ * might have to have the LLC dissector do so (but the TCP
+ * dissector doesn't currently handle out-of-order or duplicate
+ * data, either).
+ */
+
+ netbios_data_first_middle_flags( tvb, tree, offset + NB_FLAGS);
+
+ nb_resync_indicator( tvb, offset, tree, "DATA FIRST MIDDLE");
+ nb_xmit_corrl( tvb, offset, tree);
+ nb_resp_corrl( tvb, offset, tree);
+ remote_session = nb_remote_session( tvb, offset, tree);
+ local_session = nb_local_session( tvb, offset, tree);
+
+ /*
+ * Return a combination of the remote and local session numbers,
+ * for use when reassembling.
+ */
+ return (remote_session << 8) + local_session;
+}
+
+
+static guint32
+dissect_netb_data_only_last( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the DATA ONLY LAST command */
+
+ guint8 remote_session, local_session;
+
+ /*
+ * This is a complete packet, or the last frame of a fragmented
+ * packet.
+ */
+
+ netbios_data_only_flags( tvb, tree, offset + NB_FLAGS);
+
+ nb_resync_indicator( tvb, offset, tree, "DATA ONLY LAST");
+ nb_xmit_corrl( tvb, offset, tree);
+ nb_resp_corrl( tvb, offset, tree);
+ remote_session = nb_remote_session( tvb, offset, tree);
+ local_session = nb_local_session( tvb, offset, tree);
+
+ /*
+ * Return a combination of the remote and local session numbers,
+ * for use when reassembling.
+ */
+ return (remote_session << 8) + local_session;
+}
+
+
+static guint32
+dissect_netb_session_confirm( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the SESSION CONFIRM command */
+
+ netbios_add_ses_confirm_flags( tvb, tree, offset + NB_FLAGS);
+
+ nb_data2( hf_netb_max_data_recv_size, tvb, offset, tree);
+ nb_xmit_corrl( tvb, offset, tree);
+ nb_resp_corrl( tvb, offset, tree);
+ nb_remote_session( tvb, offset, tree);
+ nb_local_session( tvb, offset, tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_session_end( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the SESSION END command */
+
+ nb_data2( hf_netb_termination_indicator, tvb, offset, tree);
+ nb_remote_session( tvb, offset, tree);
+ nb_local_session( tvb, offset, tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_session_init( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the SESSION INITIALIZE command */
+
+ netbios_add_session_init_flags( tvb, tree, offset + NB_FLAGS);
+
+ nb_data2( hf_netb_max_data_recv_size, tvb, offset, tree);
+ nb_resp_corrl( tvb, offset, tree);
+ nb_xmit_corrl( tvb, offset, tree);
+ nb_remote_session( tvb, offset, tree);
+ nb_local_session( tvb, offset, tree);
+
+ return 0;
+}
+
+static guint32
+dissect_netb_no_receive( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the NO RECEIVE command */
+
+ netbios_no_receive_flags( tvb, tree, offset + NB_FLAGS);
+
+ nb_data2( hf_netb_num_data_bytes_accepted, tvb, offset, tree);
+ nb_remote_session( tvb, offset, tree);
+ nb_local_session( tvb, offset, tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_receive_outstanding( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the RECEIVE OUTSTANDING command */
+
+ nb_data2( hf_netb_num_data_bytes_accepted, tvb, offset, tree);
+ nb_remote_session( tvb, offset, tree);
+ nb_local_session( tvb, offset, tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_receive_continue( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the RECEIVE CONTINUE command */
+
+ nb_xmit_corrl( tvb, offset, tree);
+ nb_remote_session( tvb, offset, tree);
+ nb_local_session( tvb, offset, tree);
+
+ return 0;
+}
+
+
+static guint32
+dissect_netb_session_alive( tvbuff_t *tvb, int offset, proto_tree *tree)
+
+{/* Handle the SESSION ALIVE command */
+
+ /*
+ * XXX - all the fields are claimed to be "Reserved", but
+ * the session numbers appear to be non-zero in at least
+ * one capture, and they do appear to match session numbers
+ * in other messages, and I'd expect that you had to identify
+ * sessions in this message in any case.
+ *
+ * We show only those fields.
+ */
+ nb_remote_session( tvb, offset, tree);
+ nb_local_session( tvb, offset, tree);
+
+ return 0;
+}
+
+
+/************************************************************************/
+/* */
+/* The table routines called by the top level to handle commands */
+/* */
+/************************************************************************/
+
+
+static guint32 (*dissect_netb[])(tvbuff_t *, int, proto_tree *) = {
+
+ dissect_netb_add_group_name, /* Add Group Name 0x00 */
+ dissect_netb_add_name, /* Add Name 0x01 */
+ dissect_netb_name_in_conflict,/* Name In Conflict 0x02 */
+ dissect_netb_status_query, /* Status Query 0x03 */
+ dissect_netb_unknown, /* unknown 0x04 */
+ dissect_netb_unknown, /* unknown 0x05 */
+ dissect_netb_unknown, /* unknown 0x06 */
+ dissect_netb_terminate_trace, /* Terminate Trace 0x07 */
+ dissect_netb_datagram, /* Datagram 0x08 */
+ dissect_netb_datagram_bcast, /* Datagram Broadcast 0x09 */
+ dissect_netb_name_query, /* Name Query 0x0A */
+ dissect_netb_unknown, /* unknown 0x0B */
+ dissect_netb_unknown, /* unknown 0x0C */
+ dissect_netb_add_name_resp, /* Add Name Response 0x0D */
+ dissect_netb_name_resp, /* Name Recognized 0x0E */
+ dissect_netb_status_resp, /* Status Response 0x0F */
+ dissect_netb_unknown, /* unknown 0x10 */
+ dissect_netb_unknown, /* unknown 0x11 */
+ dissect_netb_unknown, /* unknown 0x12 */
+ dissect_netb_terminate_trace, /* Terminate Trace 0x13 */
+ dissect_netb_data_ack, /* Data Ack 0x14 */
+ dissect_netb_data_first_middle,/* Data First Middle 0x15 */
+ dissect_netb_data_only_last, /* Data Only Last 0x16 */
+ dissect_netb_session_confirm, /* Session Confirm 0x17 */
+ dissect_netb_session_end, /* Session End 0x18 */
+ dissect_netb_session_init, /* Session Initialize 0x19 */
+ dissect_netb_no_receive, /* No Receive 0x1A */
+ dissect_netb_receive_outstanding,/* Receive Outstanding 0x1B */
+ dissect_netb_receive_continue,/* Receive Continue 0x1C */
+ dissect_netb_unknown, /* unknown 0x1D */
+ dissect_netb_unknown, /* unknown 0x1E */
+ dissect_netb_session_alive, /* Session Alive 0x1f */
+ dissect_netb_unknown,
+};
+
+static heur_dissector_list_t netbios_heur_subdissector_list;
+
+void
+dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /*
+ * Try the heuristic dissectors for NetBIOS; if none of them
+ * accept the packet, dissect it as data.
+ */
+ if (!dissector_try_heuristic(netbios_heur_subdissector_list,
+ tvb, pinfo, tree))
+ call_dissector(data_handle,tvb, pinfo, tree);
+}
+
+static void
+dissect_netbios(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+
+{
+ proto_tree *netb_tree = NULL;
+ proto_item *ti;
+ guint16 hdr_len, command;
+ char *command_name;
+ char name[(NETBIOS_NAME_LEN - 1)*4 + 1];
+ int name_type;
+ guint16 session_id;
+ gboolean save_fragmented;
+ int len;
+ fragment_data *fd_head;
+ tvbuff_t *next_tvb;
+
+ int offset = 0;
+
+ /* load the display labels */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NetBIOS");
+
+
+/* Find NetBIOS marker EFFF, this is done because I have seen an extra LLC */
+/* byte on our network. This only checks for one extra LLC byte. */
+
+ if ( 0xefff != tvb_get_letohs(tvb, 2)){
+ ++offset;
+ if ( 0xefff != tvb_get_letohs(tvb, 3)){
+
+ if (check_col( pinfo->cinfo, COL_INFO)) /* print bad packet */
+ col_set_str( pinfo->cinfo, COL_INFO, "Bad packet, no 0xEFFF marker");
+
+ return; /* this is an unknow packet, no marker */
+ }
+ }
+
+
+ hdr_len = tvb_get_letohs(tvb, offset + NB_LENGTH);
+ command = tvb_get_guint8( tvb, offset + NB_COMMAND);
+ /* limit command so no table overflows */
+ command = MIN( command, sizeof( dissect_netb)/ sizeof(void *));
+
+ if (check_col( pinfo->cinfo, COL_INFO)) { /* print command name */
+ command_name = val_to_str(command, cmd_vals, "Unknown (0x%02x)");
+ switch ( command ) {
+ case NB_NAME_QUERY:
+ name_type = get_netbios_name( tvb, offset + 12, name);
+ col_add_fstr( pinfo->cinfo, COL_INFO, "%s for %s<%02x>",
+ command_name, name, name_type);
+ break;
+
+ case NB_NAME_RESP:
+ case NB_ADD_NAME:
+ case NB_ADD_GROUP:
+ name_type = get_netbios_name( tvb, offset + 28, name);
+ col_add_fstr( pinfo->cinfo, COL_INFO, "%s - %s<%02x>",
+ command_name, name, name_type);
+ break;
+
+ default:
+ col_add_fstr( pinfo->cinfo, COL_INFO, "%s",
+ command_name);
+ break;
+ }
+ }
+
+ if ( tree) {
+ ti = proto_tree_add_item(tree, proto_netbios, tvb, 0, hdr_len, FALSE);
+ netb_tree = proto_item_add_subtree(ti, ett_netb);
+
+ proto_tree_add_uint_format(netb_tree, hf_netb_hdr_len, tvb, offset, 2, hdr_len,
+ "Length: %d bytes", hdr_len);
+
+ proto_tree_add_text(netb_tree, tvb, offset + 2, 2,
+ "Delimiter: EFFF (NetBIOS)");
+
+ proto_tree_add_uint(netb_tree, hf_netb_cmd, tvb, offset + NB_COMMAND, 1, command);
+ }
+
+ /* if command in table range */
+ if ( command < sizeof( dissect_netb)/ sizeof(void *)) {
+
+ /* branch to handle commands */
+ session_id = (dissect_netb[ command])( tvb, offset, netb_tree);
+
+ offset += hdr_len; /* move past header */
+
+ save_fragmented = pinfo->fragmented;
+
+ /*
+ * Process user data in frames that have it.
+ */
+ switch (command) {
+
+ case NB_DATAGRAM:
+ case NB_DATAGRAM_BCAST:
+ /*
+ * No fragmentation here.
+ */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ dissect_netbios_payload(next_tvb, pinfo, tree);
+ break;
+
+ case NB_DATA_FIRST_MIDDLE:
+ case NB_DATA_ONLY_LAST:
+ /*
+ * Possibly fragmented.
+ */
+ len = tvb_reported_length_remaining(tvb, offset);
+ if (netbios_defragment &&
+ tvb_bytes_exist(tvb, offset, len)) {
+ fd_head = fragment_add_seq_next(tvb, offset,
+ pinfo, session_id,
+ netbios_fragment_table,
+ netbios_reassembled_table,
+ len, command == NB_DATA_FIRST_MIDDLE);
+ if (fd_head != NULL) {
+ if (fd_head->next != NULL) {
+ next_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->len, fd_head->len);
+ tvb_set_child_real_data_tvbuff(tvb,
+ next_tvb);
+ add_new_data_source(pinfo,
+ next_tvb,
+ "Reassembled NetBIOS");
+ /* Show all fragments. */
+ if (tree) {
+ show_fragment_seq_tree(fd_head,
+ &netbios_frag_items,
+ netb_tree, pinfo,
+ next_tvb);
+ }
+ } else {
+ next_tvb = tvb_new_subset(tvb,
+ offset, -1, -1);
+ }
+ } else {
+ next_tvb = NULL;
+ }
+ } else {
+ /*
+ * Dissect this, regardless of whether
+ * it's NB_DATA_FIRST_MIDDLE or
+ * NB_DATA_ONLY_LAST.
+ *
+ * XXX - it'd be nice to show
+ * NB_DATA_FIRST_MIDDLE as a fragment
+ * if it's not the first fragment (i.e.,
+ * MIDDLE rather than FIRST), and show
+ * NB_DATA_ONLY_LAST as a fragment if
+ * it's part of a fragmented datagram
+ * (i.e, LAST rather than ONLY), but
+ * we'd have to do reassembly to
+ * be able to determine that.
+ */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ }
+ if (next_tvb != NULL)
+ dissect_netbios_payload(next_tvb, pinfo, tree);
+ else {
+ next_tvb = tvb_new_subset (tvb, offset, -1, -1);
+ call_dissector(data_handle, next_tvb, pinfo,
+ tree);
+ }
+ break;
+ }
+ }
+}
+
+static void
+netbios_init(void)
+{
+ /*
+ * Initialize the fragment and reassembly tables.
+ */
+ fragment_table_init(&netbios_fragment_table);
+ reassembled_table_init(&netbios_reassembled_table);
+}
+
+void proto_register_netbios(void)
+{
+ static gint *ett[] = {
+ &ett_netb,
+ &ett_netb_name,
+ &ett_netb_flags,
+ &ett_netb_status,
+ &ett_netb_fragments,
+ &ett_netb_fragment,
+ };
+
+ static hf_register_info hf_netb[] = {
+ { &hf_netb_cmd,
+ { "Command", "netbios.command", FT_UINT8, BASE_HEX, VALS(cmd_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_netb_hdr_len,
+ { "Header Length", "netbios.hdr_len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_xmit_corrl,
+ { "Transmit Correlator", "netbios.xmit_corrl", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_resp_corrl,
+ { "Response Correlator", "netbios.resp_corrl", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_call_name_type,
+ { "Caller's Name Type", "netbios.call_name_type", FT_UINT8, BASE_HEX, VALS(name_types), 0x0,
+ "", HFILL }},
+
+ { &hf_netb_nb_name_type,
+ { "NetBIOS Name Type", "netbios.nb_name_type", FT_UINT8, BASE_HEX, VALS(nb_name_type_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_netb_nb_name,
+ { "NetBIOS Name", "netbios.nb_name", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_ack,
+ { "Acknowledge", "netbios.ack", FT_BOOLEAN, 8, TFS( &flags_set), 0x08,
+ "", HFILL }},
+
+ { &hf_netb_ack_with_data,
+ { "Acknowledge with data", "netbios.ack_with_data", FT_BOOLEAN, 8, TFS( &flags_allowed), 0x04,
+ "", HFILL }},
+
+ { &hf_netb_ack_expected,
+ { "Acknowledge expected", "netbios.ack_expected", FT_BOOLEAN, 8,
+ TFS( &flags_yes_no), 0x02, "", HFILL }},
+
+ { &hf_netb_recv_cont_req,
+ { "RECEIVE_CONTINUE requested", "netbios.recv_cont_req", FT_BOOLEAN, 8,
+ TFS( &flags_yes_no), 0x01, "", HFILL }},
+
+ { &hf_netb_send_no_ack,
+ { "Handle SEND.NO.ACK", "netbios.send_no_ack", FT_BOOLEAN, 8,
+ TFS( &flags_yes_no), 0x80, "", HFILL }},
+
+ { &hf_netb_version,
+ { "NetBIOS Version", "netbios.version", FT_BOOLEAN, 8,
+ TFS( &netb_version_str), 0x01, "", HFILL }},
+
+ { &hf_netb_largest_frame,
+ { "Largest Frame", "netbios.largest_frame", FT_UINT8, BASE_DEC, VALS(max_frame_size_vals), 0x0E,
+ "", HFILL }},
+
+ { &hf_netb_status_buffer_len,
+ { "Length of status buffer", "netbios.status_buffer_len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_status,
+ { "Status", "netbios.status", FT_UINT8, BASE_DEC, VALS(status_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_netb_name_type,
+ { "Name type", "netbios.name_type", FT_UINT16, BASE_DEC, VALS(name_types), 0x0,
+ "", HFILL }},
+
+ { &hf_netb_max_data_recv_size,
+ { "Maximum data receive size", "netbios.max_data_recv_size", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_termination_indicator,
+ { "Termination indicator", "netbios.termination_indicator", FT_UINT16, BASE_HEX, VALS(termination_indicator_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_netb_num_data_bytes_accepted,
+ { "Number of data bytes accepted", "netbios.num_data_bytes_accepted", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_local_ses_no,
+ { "Local Session No.", "netbios.local_session", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_remote_ses_no,
+ { "Remote Session No.", "netbios.remote_session", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_data1,
+ { "DATA1 value", "netbios.data1", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_data2,
+ { "DATA2 value", "netbios.data2", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_netb_fragment_overlap,
+ { "Fragment overlap", "netbios.fragment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_netb_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "netbios.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_netb_fragment_multiple_tails,
+ { "Multiple tail fragments found", "netbios.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_netb_fragment_too_long_fragment,
+ { "Fragment too long", "netbios.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
+
+ { &hf_netb_fragment_error,
+ {"Defragmentation error", "netbios.fragment.error", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
+
+ { &hf_netb_fragment,
+ { "NetBIOS Fragment", "netbios.fragment", FT_FRAMENUM, BASE_NONE,
+ NULL, 0x0, "NetBIOS Fragment", HFILL }},
+
+ { &hf_netb_fragments,
+ { "NetBIOS Fragments", "netbios.fragments", FT_NONE, BASE_NONE,
+ NULL, 0x0, "NetBIOS Fragments", HFILL }},
+ };
+ module_t *netbios_module;
+
+ proto_netbios = proto_register_protocol("NetBIOS", "NetBIOS", "netbios");
+ proto_register_subtree_array(ett, array_length(ett));
+ proto_register_field_array(proto_netbios, hf_netb, array_length(hf_netb));
+
+ register_heur_dissector_list("netbios", &netbios_heur_subdissector_list);
+
+ netbios_module = prefs_register_protocol(proto_netbios, NULL);
+ prefs_register_bool_preference(netbios_module, "defragment",
+ "Defragment all NetBIOS messages spanning multiple frames",
+ "Whether the NetBIOS dissector should defragment all messages spanning multiple frames",
+ &netbios_defragment);
+
+ register_init_routine(netbios_init);
+}
+
+void
+proto_reg_handoff_netbios(void)
+{
+ dissector_handle_t netbios_handle;
+
+ netbios_handle = create_dissector_handle(dissect_netbios,
+ proto_netbios);
+ dissector_add("llc.dsap", SAP_NETBIOS, netbios_handle);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-netbios.h b/epan/dissectors/packet-netbios.h
new file mode 100644
index 0000000000..6bc1d51ac5
--- /dev/null
+++ b/epan/dissectors/packet-netbios.h
@@ -0,0 +1,46 @@
+/* packet-netbios.h
+ * Declarations of public routines for NetBIOS protocol packet disassembly
+ * Jeff Foster <foste@woodward.com>
+ * Copyright 1999 Jeffrey C. Foster
+ *
+ * derived from the packet-nbns.c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_NETBIOS_H__
+#define __PACKET_NETBIOS_H__
+
+/* Length of NetBIOS names */
+#define NETBIOS_NAME_LEN 16
+
+void capture_netbios(packet_counts *);
+
+extern int process_netbios_name(const guchar *name_ptr, char *name_ret);
+extern int get_netbios_name(tvbuff_t *tvb, int offset,
+ char *name_ret);
+extern char *netbios_name_type_descr(int name_type);
+extern void netbios_add_name( char* label, tvbuff_t *tvb, int offset,
+ proto_tree *tree);
+extern void dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree);
+
+#endif
diff --git a/epan/dissectors/packet-netflow.c b/epan/dissectors/packet-netflow.c
new file mode 100644
index 0000000000..fcb560feaf
--- /dev/null
+++ b/epan/dissectors/packet-netflow.c
@@ -0,0 +1,1767 @@
+/*
+ ** packet-netflow.c
+ **
+ *****************************************************************************
+ ** (c) 2002 bill fumerola <fumerola@yahoo-inc.com>
+ ** All rights reserved.
+ **
+ ** This program is free software; you can redistribute it and/or
+ ** modify it under the terms of the GNU General Public License
+ ** as published by the Free Software Foundation; either version 2
+ ** of the License, or (at your option) any later version.
+ **
+ ** This program is distributed in the hope that it will be useful,
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ ** GNU General Public License for more details.
+ **
+ ** You should have received a copy of the GNU General Public License
+ ** along with this program; if not, write to the Free Software
+ ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *****************************************************************************
+ **
+ ** Previous NetFlow dissector written by Matthew Smart <smart@monkey.org>
+ ** NetFlow v9 support added by same.
+ **
+ ** See
+ **
+ ** http://www.cisco.com/warp/public/cc/pd/iosw/prodlit/tflow_wp.htm
+ **
+ ** for NetFlow v9 information.
+ **
+ *****************************************************************************
+ **
+ ** this code was written from the following documentation:
+ **
+ ** http://www.cisco.com/univercd/cc/td/doc/product/rtrmgmt/nfc/nfc_3_6/iug/format.pdf
+ ** http://www.caida.org/tools/measurement/cflowd/configuration/configuration-9.html
+ **
+ ** some documentation is more accurate then others. in some cases, live data and
+ ** information contained in responses from vendors were also used. some fields
+ ** are dissected as vendor specific fields.
+ **
+ ** See also
+ **
+ ** http://www.cisco.com/univercd/cc/td/doc/cisintwk/intsolns/netflsol/nfwhite.htm
+ **
+ ** $Yahoo: //depot/fumerola/packet-netflow/packet-netflow.c#14 $
+ ** $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <string.h>
+
+#include "prefs.h"
+
+#define UDP_PORT_NETFLOW 2055
+
+static guint global_netflow_udp_port = UDP_PORT_NETFLOW;
+static guint netflow_udp_port = 0;
+
+/*
+ * pdu identifiers & sizes
+ */
+
+#define V1PDU_SIZE (4 * 12)
+#define V5PDU_SIZE (4 * 12)
+#define V7PDU_SIZE (4 * 13)
+#define V8PDU_AS_SIZE (4 * 7)
+#define V8PDU_PROTO_SIZE (4 * 7)
+#define V8PDU_SPREFIX_SIZE (4 * 8)
+#define V8PDU_DPREFIX_SIZE (4 * 8)
+#define V8PDU_MATRIX_SIZE (4 * 10)
+#define V8PDU_DESTONLY_SIZE (4 * 8)
+#define V8PDU_SRCDEST_SIZE (4 * 10)
+#define V8PDU_FULL_SIZE (4 * 11)
+#define V8PDU_TOSAS_SIZE (V8PDU_AS_SIZE + 4)
+#define V8PDU_TOSPROTOPORT_SIZE (V8PDU_PROTO_SIZE + 4)
+#define V8PDU_TOSSRCPREFIX_SIZE V8PDU_SPREFIX_SIZE
+#define V8PDU_TOSDSTPREFIX_SIZE V8PDU_DPREFIX_SIZE
+#define V8PDU_TOSMATRIX_SIZE V8PDU_MATRIX_SIZE
+#define V8PDU_PREPORTPROTOCOL_SIZE (4 * 10)
+
+static const value_string v5_sampling_mode[] = {
+ {0, "No sampling mode configured"},
+ {1, "Packet Interval sampling mode configured"},
+ {0, NULL}
+};
+
+enum {
+ V8PDU_NO_METHOD = 0,
+ V8PDU_AS_METHOD,
+ V8PDU_PROTO_METHOD,
+ V8PDU_SPREFIX_METHOD,
+ V8PDU_DPREFIX_METHOD,
+ V8PDU_MATRIX_METHOD,
+ V8PDU_DESTONLY_METHOD,
+ V8PDU_SRCDEST_METHOD,
+ V8PDU_FULL_METHOD,
+ V8PDU_TOSAS_METHOD,
+ V8PDU_TOSPROTOPORT_METHOD,
+ V8PDU_TOSSRCPREFIX_METHOD,
+ V8PDU_TOSDSTPREFIX_METHOD,
+ V8PDU_TOSMATRIX_METHOD,
+ V8PDU_PREPORTPROTOCOL_METHOD
+};
+
+static const value_string v8_agg[] = {
+ {V8PDU_AS_METHOD, "V8 AS aggregation"},
+ {V8PDU_PROTO_METHOD, "V8 Proto/Port aggregation"},
+ {V8PDU_SPREFIX_METHOD, "V8 Source Prefix aggregation"},
+ {V8PDU_DPREFIX_METHOD, "V8 Destination Prefix aggregation"},
+ {V8PDU_MATRIX_METHOD, "V8 Network Matrix aggregation"},
+ {V8PDU_DESTONLY_METHOD, "V8 Destination aggregation (Cisco Catalyst)"},
+ {V8PDU_SRCDEST_METHOD, "V8 Src/Dest aggregation (Cisco Catalyst)"},
+ {V8PDU_FULL_METHOD, "V8 Full aggregation (Cisco Catalyst)"},
+ {V8PDU_TOSAS_METHOD, "V8 TOS+AS aggregation aggregation"},
+ {V8PDU_TOSPROTOPORT_METHOD, "V8 TOS+Protocol aggregation"},
+ {V8PDU_TOSSRCPREFIX_METHOD, "V8 TOS+Source Prefix aggregation"},
+ {V8PDU_TOSDSTPREFIX_METHOD, "V8 TOS+Destination Prefix aggregation"},
+ {V8PDU_TOSMATRIX_METHOD, "V8 TOS+Prefix Matrix aggregation"},
+ {V8PDU_PREPORTPROTOCOL_METHOD, "V8 Port+Protocol aggregation"},
+ {0, NULL}
+};
+
+/* Version 9 template cache structures */
+#define V9TEMPLATE_CACHE_MAX_ENTRIES 100
+
+struct v9_template_entry {
+ guint16 type;
+ guint16 length;
+};
+
+struct v9_template {
+ guint16 id;
+ guint16 count;
+ guint32 length;
+ guint32 source_id;
+ guint32 source_addr;
+ struct v9_template_entry *entries;
+};
+
+static struct v9_template v9_template_cache[V9TEMPLATE_CACHE_MAX_ENTRIES];
+
+/*
+ * ethereal tree identifiers
+ */
+
+static int proto_netflow = -1;
+static int ett_netflow = -1;
+static int ett_unixtime = -1;
+static int ett_flow = -1;
+static int ett_template = -1;
+static int ett_dataflowset = -1;
+
+/*
+ * cflow header
+ */
+
+static int hf_cflow_version = -1;
+static int hf_cflow_count = -1;
+static int hf_cflow_sysuptime = -1;
+static int hf_cflow_unix_secs = -1;
+static int hf_cflow_unix_nsecs = -1;
+static int hf_cflow_timestamp = -1;
+static int hf_cflow_samplingmode = -1;
+static int hf_cflow_samplerate = -1;
+
+/*
+ * cflow version specific info
+ */
+static int hf_cflow_sequence = -1;
+static int hf_cflow_engine_type = -1;
+static int hf_cflow_engine_id = -1;
+static int hf_cflow_source_id = -1;
+
+static int hf_cflow_aggmethod = -1;
+static int hf_cflow_aggversion = -1;
+
+/* Version 9 */
+
+static int hf_cflow_template_flowset_id = -1;
+static int hf_cflow_data_flowset_id = -1;
+static int hf_cflow_options_flowset_id = -1;
+static int hf_cflow_flowset_id = -1;
+static int hf_cflow_flowset_length = -1;
+static int hf_cflow_template_id = -1;
+static int hf_cflow_template_field_count = -1;
+static int hf_cflow_template_field_type = -1;
+static int hf_cflow_template_field_length = -1;
+
+/*
+ * pdu storage
+ */
+static int hf_cflow_srcaddr = -1;
+static int hf_cflow_srcaddr_v6 = -1;
+static int hf_cflow_srcnet = -1;
+static int hf_cflow_dstaddr = -1;
+static int hf_cflow_dstaddr_v6 = -1;
+static int hf_cflow_dstnet = -1;
+static int hf_cflow_nexthop = -1;
+static int hf_cflow_nexthop_v6 = -1;
+static int hf_cflow_bgpnexthop = -1;
+static int hf_cflow_bgpnexthop_v6 = -1;
+static int hf_cflow_inputint = -1;
+static int hf_cflow_outputint = -1;
+static int hf_cflow_flows = -1;
+static int hf_cflow_packets = -1;
+static int hf_cflow_packets64 = -1;
+static int hf_cflow_packetsout = -1;
+static int hf_cflow_octets = -1;
+static int hf_cflow_octets64 = -1;
+static int hf_cflow_timestart = -1;
+static int hf_cflow_timeend = -1;
+static int hf_cflow_srcport = -1;
+static int hf_cflow_dstport = -1;
+static int hf_cflow_prot = -1;
+static int hf_cflow_tos = -1;
+static int hf_cflow_flags = -1;
+static int hf_cflow_tcpflags = -1;
+static int hf_cflow_dstas = -1;
+static int hf_cflow_srcas = -1;
+static int hf_cflow_dstmask = -1;
+static int hf_cflow_srcmask = -1;
+static int hf_cflow_routersc = -1;
+static int hf_cflow_mulpackets = -1;
+static int hf_cflow_muloctets = -1;
+static int hf_cflow_octets_exp = -1;
+static int hf_cflow_packets_exp = -1;
+static int hf_cflow_flows_exp = -1;
+
+void proto_reg_handoff_netflow(void);
+
+typedef int dissect_pdu_t(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+ int verspec);
+static int dissect_pdu(proto_tree * tree, tvbuff_t * tvb, int offset,
+ int verspec);
+static int dissect_v8_aggpdu(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset, int verspec);
+static int dissect_v8_flowpdu(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset, int verspec);
+static int dissect_v9_flowset(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset, int verspec);
+static int dissect_v9_data(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset, guint16 id, guint length);
+static void dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset, struct v9_template * template);
+#if 0
+static int dissect_v9_options(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset);
+#endif
+static int dissect_v9_template(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset);
+static void v9_template_add(struct v9_template * template);
+static struct v9_template *v9_template_get(guint16 id, guint32 src_addr,
+ guint32 src_id);
+
+static gchar *getprefix(const guint32 * address, int prefix);
+static void dissect_netflow(tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree);
+
+static int flow_process_ints(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset);
+static int flow_process_ports(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset);
+static int flow_process_timeperiod(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset);
+static int flow_process_aspair(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset);
+static int flow_process_sizecount(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset);
+static int flow_process_textfield(proto_tree * pdutree, tvbuff_t * tvb,
+ int offset, int bytes,
+ const char *text);
+
+
+static void
+dissect_netflow(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ proto_tree *netflow_tree = NULL;
+ proto_tree *ti;
+ proto_item *timeitem, *pduitem;
+ proto_tree *timetree, *pdutree;
+ unsigned int pduret, ver = 0, pdus = 0, x = 1, vspec;
+ size_t available, pdusize, offset = 0;
+ nstime_t ts;
+ dissect_pdu_t *pduptr;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CFLOW");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_netflow, tvb,
+ offset, -1, FALSE);
+ netflow_tree = proto_item_add_subtree(ti, ett_netflow);
+ }
+
+ ver = tvb_get_ntohs(tvb, offset);
+ vspec = ver;
+ switch (ver) {
+ case 1:
+ pdusize = V1PDU_SIZE;
+ pduptr = &dissect_pdu;
+ break;
+ case 5:
+ pdusize = V5PDU_SIZE;
+ pduptr = &dissect_pdu;
+ break;
+ case 7:
+ pdusize = V7PDU_SIZE;
+ pduptr = &dissect_pdu;
+ break;
+ case 8:
+ pdusize = -1; /* deferred */
+ pduptr = &dissect_v8_aggpdu;
+ break;
+ case 9:
+ pdusize = -1; /* deferred */
+ pduptr = &dissect_v9_flowset;
+ break;
+ default:
+ return;
+ }
+
+ if (tree)
+ proto_tree_add_uint(netflow_tree, hf_cflow_version, tvb,
+ offset, 2, ver);
+ offset += 2;
+
+ pdus = tvb_get_ntohs(tvb, offset);
+ if (pdus <= 0)
+ return;
+ if (tree)
+ proto_tree_add_uint(netflow_tree, hf_cflow_count, tvb,
+ offset, 2, pdus);
+ offset += 2;
+
+ /*
+ * set something interesting in the display now that we have info
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (ver == 9) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "total: %u (v%u) FlowSets", pdus, ver);
+ } else {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "total: %u (v%u) flows", pdus, ver);
+ }
+ }
+
+ /*
+ * the rest is only interesting if we're displaying/searching the
+ * packet
+ */
+ if (!tree)
+ return;
+
+ proto_tree_add_item(netflow_tree, hf_cflow_sysuptime, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ ts.secs = tvb_get_ntohl(tvb, offset);
+ ts.nsecs = tvb_get_ntohl(tvb, offset + 4);
+ timeitem = proto_tree_add_time(netflow_tree,
+ hf_cflow_timestamp, tvb, offset,
+ 8, &ts);
+ timetree = proto_item_add_subtree(timeitem, ett_unixtime);
+
+ proto_tree_add_item(timetree, hf_cflow_unix_secs, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ if (ver != 9) {
+ proto_tree_add_item(timetree, hf_cflow_unix_nsecs, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ }
+
+ /*
+ * version specific header
+ */
+ if (ver == 5 || ver == 7 || ver == 8 || ver == 9) {
+ proto_tree_add_item(netflow_tree, hf_cflow_sequence,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ if (ver == 5 || ver == 8) {
+ proto_tree_add_item(netflow_tree, hf_cflow_engine_type,
+ tvb, offset++, 1, FALSE);
+ proto_tree_add_item(netflow_tree, hf_cflow_engine_id,
+ tvb, offset++, 1, FALSE);
+ } else if (ver == 9) {
+ proto_tree_add_item(netflow_tree, hf_cflow_source_id,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ if (ver == 8) {
+ vspec = tvb_get_guint8(tvb, offset);
+ switch (vspec) {
+ case V8PDU_AS_METHOD:
+ pdusize = V8PDU_AS_SIZE;
+ break;
+ case V8PDU_PROTO_METHOD:
+ pdusize = V8PDU_PROTO_SIZE;
+ break;
+ case V8PDU_SPREFIX_METHOD:
+ pdusize = V8PDU_SPREFIX_SIZE;
+ break;
+ case V8PDU_DPREFIX_METHOD:
+ pdusize = V8PDU_DPREFIX_SIZE;
+ break;
+ case V8PDU_MATRIX_METHOD:
+ pdusize = V8PDU_MATRIX_SIZE;
+ break;
+ case V8PDU_DESTONLY_METHOD:
+ pdusize = V8PDU_DESTONLY_SIZE;
+ pduptr = &dissect_v8_flowpdu;
+ break;
+ case V8PDU_SRCDEST_METHOD:
+ pdusize = V8PDU_SRCDEST_SIZE;
+ pduptr = &dissect_v8_flowpdu;
+ break;
+ case V8PDU_FULL_METHOD:
+ pdusize = V8PDU_FULL_SIZE;
+ pduptr = &dissect_v8_flowpdu;
+ break;
+ case V8PDU_TOSAS_METHOD:
+ pdusize = V8PDU_TOSAS_SIZE;
+ break;
+ case V8PDU_TOSPROTOPORT_METHOD:
+ pdusize = V8PDU_TOSPROTOPORT_SIZE;
+ break;
+ case V8PDU_TOSSRCPREFIX_METHOD:
+ pdusize = V8PDU_TOSSRCPREFIX_SIZE;
+ break;
+ case V8PDU_TOSDSTPREFIX_METHOD:
+ pdusize = V8PDU_TOSDSTPREFIX_SIZE;
+ break;
+ case V8PDU_TOSMATRIX_METHOD:
+ pdusize = V8PDU_TOSMATRIX_SIZE;
+ break;
+ case V8PDU_PREPORTPROTOCOL_METHOD:
+ pdusize = V8PDU_PREPORTPROTOCOL_SIZE;
+ break;
+ default:
+ pdusize = -1;
+ vspec = 0;
+ break;
+ }
+ proto_tree_add_uint(netflow_tree, hf_cflow_aggmethod,
+ tvb, offset++, 1, vspec);
+ proto_tree_add_item(netflow_tree, hf_cflow_aggversion,
+ tvb, offset++, 1, FALSE);
+ }
+ if (ver == 7 || ver == 8)
+ offset = flow_process_textfield(netflow_tree, tvb, offset, 4,
+ "reserved");
+ else if (ver == 5) {
+ proto_tree_add_item(netflow_tree, hf_cflow_samplingmode,
+ tvb, offset, 2, FALSE);
+ proto_tree_add_item(netflow_tree, hf_cflow_samplerate,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /*
+ * everything below here should be payload
+ */
+ for (x = 1; x < pdus + 1; x++) {
+ /*
+ * make sure we have a pdu's worth of data
+ */
+ available = tvb_length_remaining(tvb, offset);
+ if (ver == 9 && available >= 4) {
+ /* pdusize can be different for each v9 flowset */
+ pdusize = tvb_get_ntohs(tvb, offset + 2);
+ }
+
+ if (available < pdusize)
+ break;
+
+ if (ver == 9) {
+ pduitem = proto_tree_add_text(netflow_tree, tvb,
+ offset, pdusize, "FlowSet %u/%u", x, pdus);
+ } else {
+ pduitem = proto_tree_add_text(netflow_tree, tvb,
+ offset, pdusize, "pdu %u/%u", x, pdus);
+ }
+ pdutree = proto_item_add_subtree(pduitem, ett_flow);
+
+ pduret = pduptr(pdutree, tvb, offset, vspec);
+
+ /*
+ * if we came up short, stop processing
+ */
+ if (pduret == pdusize)
+ offset += pduret;
+ else
+ break;
+ }
+}
+
+/*
+ * flow_process_* == common groups of fields, probably could be inline
+ */
+
+static int
+flow_process_ints(proto_tree * pdutree, tvbuff_t * tvb, int offset)
+{
+ proto_tree_add_item(pdutree, hf_cflow_inputint, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(pdutree, hf_cflow_outputint, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+static int
+flow_process_ports(proto_tree * pdutree, tvbuff_t * tvb, int offset)
+{
+ proto_tree_add_item(pdutree, hf_cflow_srcport, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(pdutree, hf_cflow_dstport, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+static int
+flow_process_timeperiod(proto_tree * pdutree, tvbuff_t * tvb, int offset)
+{
+ nstime_t ts;
+
+ ts.secs = tvb_get_ntohl(tvb, offset) / 1000;
+ ts.nsecs = ((tvb_get_ntohl(tvb, offset) % 1000) * 1000000);
+ proto_tree_add_time(pdutree, hf_cflow_timestart, tvb, offset, 4, &ts);
+ offset += 4;
+
+ ts.secs = tvb_get_ntohl(tvb, offset) / 1000;
+ ts.nsecs = ((tvb_get_ntohl(tvb, offset) % 1000) * 1000000);
+ proto_tree_add_time(pdutree, hf_cflow_timeend, tvb, offset, 4, &ts);
+ offset += 4;
+
+ return offset;
+}
+
+
+static int
+flow_process_aspair(proto_tree * pdutree, tvbuff_t * tvb, int offset)
+{
+ proto_tree_add_item(pdutree, hf_cflow_srcas, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(pdutree, hf_cflow_dstas, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ return offset;
+}
+
+static int
+flow_process_sizecount(proto_tree * pdutree, tvbuff_t * tvb, int offset)
+{
+ proto_tree_add_item(pdutree, hf_cflow_packets, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(pdutree, hf_cflow_octets, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+flow_process_textfield(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+ int bytes, const char *text)
+{
+ proto_tree_add_text(pdutree, tvb, offset, bytes, text);
+ offset += bytes;
+
+ return offset;
+}
+
+static int
+dissect_v8_flowpdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+ int verspec)
+{
+ int startoffset = offset;
+
+ proto_tree_add_item(pdutree, hf_cflow_dstaddr, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ if (verspec != V8PDU_DESTONLY_METHOD) {
+ proto_tree_add_item(pdutree, hf_cflow_srcaddr, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ }
+ if (verspec == V8PDU_FULL_METHOD) {
+ proto_tree_add_item(pdutree, hf_cflow_dstport, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ proto_tree_add_item(pdutree, hf_cflow_srcport, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ }
+
+ offset = flow_process_sizecount(pdutree, tvb, offset);
+ offset = flow_process_timeperiod(pdutree, tvb, offset);
+
+ proto_tree_add_item(pdutree, hf_cflow_outputint, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ if (verspec != V8PDU_DESTONLY_METHOD) {
+ proto_tree_add_item(pdutree, hf_cflow_inputint, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ }
+
+ proto_tree_add_item(pdutree, hf_cflow_tos, tvb, offset++, 1, FALSE);
+ if (verspec == V8PDU_FULL_METHOD)
+ proto_tree_add_item(pdutree, hf_cflow_prot, tvb, offset++, 1,
+ FALSE);
+ offset = flow_process_textfield(pdutree, tvb, offset, 1, "marked tos");
+
+ if (verspec == V8PDU_SRCDEST_METHOD)
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 2,
+ "reserved");
+ else if (verspec == V8PDU_FULL_METHOD)
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 1, "padding");
+
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 4, "extra packets");
+
+ proto_tree_add_item(pdutree, hf_cflow_routersc, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ return (offset - startoffset);
+}
+
+/*
+ * dissect a version 8 pdu, returning the length of the pdu processed
+ */
+
+static int
+dissect_v8_aggpdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+ int verspec)
+{
+ int startoffset = offset;
+
+ proto_tree_add_item(pdutree, hf_cflow_flows, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ offset = flow_process_sizecount(pdutree, tvb, offset);
+ offset = flow_process_timeperiod(pdutree, tvb, offset);
+
+ switch (verspec) {
+ case V8PDU_AS_METHOD:
+ case V8PDU_TOSAS_METHOD:
+ offset = flow_process_aspair(pdutree, tvb, offset);
+
+ if (verspec == V8PDU_TOSAS_METHOD) {
+ proto_tree_add_item(pdutree, hf_cflow_tos, tvb,
+ offset++, 1, FALSE);
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 1,
+ "padding");
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 2,
+ "reserved");
+ }
+ break;
+ case V8PDU_PROTO_METHOD:
+ case V8PDU_TOSPROTOPORT_METHOD:
+ proto_tree_add_item(pdutree, hf_cflow_prot, tvb, offset++, 1,
+ FALSE);
+
+ if (verspec == V8PDU_PROTO_METHOD)
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 1,
+ "padding");
+ else if (verspec == V8PDU_TOSPROTOPORT_METHOD)
+ proto_tree_add_item(pdutree, hf_cflow_tos, tvb,
+ offset++, 1, FALSE);
+
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 2,
+ "reserved");
+ offset = flow_process_ports(pdutree, tvb, offset);
+
+ if (verspec == V8PDU_TOSPROTOPORT_METHOD)
+ offset = flow_process_ints(pdutree, tvb, offset);
+ break;
+ case V8PDU_SPREFIX_METHOD:
+ case V8PDU_DPREFIX_METHOD:
+ case V8PDU_TOSSRCPREFIX_METHOD:
+ case V8PDU_TOSDSTPREFIX_METHOD:
+ proto_tree_add_item(pdutree,
+ verspec ==
+ V8PDU_SPREFIX_METHOD ?
+ hf_cflow_srcnet : hf_cflow_dstnet, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(pdutree,
+ verspec ==
+ V8PDU_SPREFIX_METHOD ?
+ hf_cflow_srcmask : hf_cflow_dstmask, tvb,
+ offset++, 1, FALSE);
+
+ if (verspec == V8PDU_SPREFIX_METHOD
+ || verspec == V8PDU_DPREFIX_METHOD)
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 1,
+ "padding");
+ else if (verspec == V8PDU_TOSSRCPREFIX_METHOD
+ || verspec == V8PDU_TOSDSTPREFIX_METHOD)
+ proto_tree_add_item(pdutree, hf_cflow_tos, tvb,
+ offset++, 1, FALSE);
+
+ proto_tree_add_item(pdutree,
+ verspec ==
+ V8PDU_SPREFIX_METHOD ? hf_cflow_srcas
+ : hf_cflow_dstas, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(pdutree,
+ verspec ==
+ V8PDU_SPREFIX_METHOD ?
+ hf_cflow_inputint : hf_cflow_outputint,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 2,
+ "reserved");
+ break;
+ case V8PDU_MATRIX_METHOD:
+ case V8PDU_TOSMATRIX_METHOD:
+ case V8PDU_PREPORTPROTOCOL_METHOD:
+ proto_tree_add_item(pdutree, hf_cflow_srcnet, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+
+ proto_tree_add_item(pdutree, hf_cflow_dstnet, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+
+ proto_tree_add_item(pdutree, hf_cflow_srcmask, tvb, offset++,
+ 1, FALSE);
+
+ proto_tree_add_item(pdutree, hf_cflow_dstmask, tvb, offset++,
+ 1, FALSE);
+
+ if (verspec == V8PDU_TOSMATRIX_METHOD ||
+ verspec == V8PDU_PREPORTPROTOCOL_METHOD) {
+ proto_tree_add_item(pdutree, hf_cflow_tos, tvb,
+ offset++, 1, FALSE);
+ if (verspec == V8PDU_TOSMATRIX_METHOD) {
+ offset =
+ flow_process_textfield(pdutree, tvb,
+ offset, 1,
+ "padding");
+ } else if (verspec == V8PDU_PREPORTPROTOCOL_METHOD) {
+ proto_tree_add_item(pdutree, hf_cflow_prot,
+ tvb, offset++, 1, FALSE);
+ }
+ } else {
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 2,
+ "reserved");
+ }
+
+ if (verspec == V8PDU_MATRIX_METHOD
+ || verspec == V8PDU_TOSMATRIX_METHOD) {
+ offset = flow_process_aspair(pdutree, tvb, offset);
+ } else if (verspec == V8PDU_PREPORTPROTOCOL_METHOD) {
+ offset = flow_process_ports(pdutree, tvb, offset);
+ }
+
+ offset = flow_process_ints(pdutree, tvb, offset);
+ break;
+ }
+
+
+ return (offset - startoffset);
+}
+
+/* Dissect a version 9 FlowSet and return the length we processed. */
+
+static int
+dissect_v9_flowset(proto_tree * pdutree, tvbuff_t * tvb, int offset, int ver)
+{
+ int length;
+ guint16 flowset_id;
+
+ if (ver != 9)
+ return (0);
+
+ flowset_id = tvb_get_ntohs(tvb, offset);
+ if (flowset_id == 0) {
+ /* Template */
+ proto_tree_add_item(pdutree, hf_cflow_template_flowset_id, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(pdutree, hf_cflow_flowset_length, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ dissect_v9_template(pdutree, tvb, offset);
+ } else if (flowset_id == 1) {
+ /* Options */
+ proto_tree_add_item(pdutree, hf_cflow_options_flowset_id, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(pdutree, hf_cflow_flowset_length, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ /* dissect_v9_options(pdutree, tvb, offset); */
+ } else if (flowset_id >= 2 && flowset_id <= 255) {
+ /* Reserved */
+ proto_tree_add_item(pdutree, hf_cflow_flowset_id, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(pdutree, hf_cflow_flowset_length, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+ } else {
+ /* Data */
+ proto_tree_add_item(pdutree, hf_cflow_data_flowset_id, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(pdutree, hf_cflow_flowset_length, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ /*
+ * The length includes the length of the FlowSet ID and
+ * the length field itself.
+ */
+ length -= 4;
+ if (length > 0) {
+ dissect_v9_data(pdutree, tvb, offset, flowset_id,
+ (guint)length);
+ }
+ }
+
+ return (length);
+}
+
+static int
+dissect_v9_data(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+ guint16 id, guint length)
+{
+ struct v9_template *template;
+ proto_tree *data_tree;
+ proto_item *data_item;
+
+ template = v9_template_get(id, 0, 0);
+ if (template != NULL && template->length != 0) {
+ int count;
+
+ count = 1;
+ while (length >= template->length) {
+ data_item = proto_tree_add_text(pdutree, tvb,
+ offset, template->length, "pdu %d", count++);
+ data_tree = proto_item_add_subtree(data_item,
+ ett_dataflowset);
+
+ dissect_v9_pdu(data_tree, tvb, offset, template);
+
+ offset += template->length;
+ length -= template->length;
+ }
+ if (length != 0) {
+ proto_tree_add_text(pdutree, tvb, offset, length,
+ "Padding (%u byte%s)",
+ length, plurality(length, "", "s"));
+ }
+ } else {
+ proto_tree_add_text(pdutree, tvb, offset, length,
+ "Data (%u byte%s), no template found",
+ length, plurality(length, "", "s"));
+ }
+
+ return (0);
+}
+
+static void
+dissect_v9_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset,
+ struct v9_template * template)
+{
+ int i;
+
+ for (i = 0; i < template->count; i++) {
+ guint32 ipv4addr;
+ guint8 ipv6addr[16];
+ guint16 type, length;
+ nstime_t ts;
+
+ type = template->entries[i].type;
+ length = template->entries[i].length;
+
+ switch (type) {
+ case 1: /* bytes */
+ if (length == 4) {
+ proto_tree_add_item(pdutree, hf_cflow_octets,
+ tvb, offset, length, FALSE);
+ } else if (length == 8) {
+ proto_tree_add_item(pdutree, hf_cflow_octets64,
+ tvb, offset, length, FALSE);
+ } else {
+ proto_tree_add_text(pdutree,
+ tvb, offset, length,
+ "Octets: length %u", length);
+ }
+ break;
+
+ case 2: /* packets */
+ if (length == 4) {
+ proto_tree_add_item(pdutree, hf_cflow_packets,
+ tvb, offset, length, FALSE);
+ } else if (length == 8) {
+ proto_tree_add_item(pdutree, hf_cflow_packets64,
+ tvb, offset, length, FALSE);
+ } else {
+ proto_tree_add_text(pdutree,
+ tvb, offset, length,
+ "Packets: length %u", length);
+ }
+ break;
+
+ case 3: /* flows */
+ if (length == 4) {
+ proto_tree_add_item(pdutree, hf_cflow_flows,
+ tvb, offset, length, FALSE);
+ } else {
+ proto_tree_add_text(pdutree,
+ tvb, offset, length,
+ "Flows: length %u", length);
+ }
+ break;
+
+ case 4: /* proto */
+ proto_tree_add_item(pdutree, hf_cflow_prot,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 5: /* TOS */
+ proto_tree_add_item(pdutree, hf_cflow_tos,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 6: /* TCP flags */
+ proto_tree_add_item(pdutree, hf_cflow_tcpflags,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 7: /* source port */
+ proto_tree_add_item(pdutree, hf_cflow_srcport,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 8: /* source IP */
+ if (length == 4) {
+ tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset,
+ sizeof(ipv4addr));
+ proto_tree_add_ipv4(pdutree, hf_cflow_srcaddr,
+ tvb, offset, length, ipv4addr);
+ } else if (length == 16) {
+ tvb_memcpy(tvb, ipv6addr, offset,
+ sizeof(ipv6addr));
+ proto_tree_add_ipv6(pdutree, hf_cflow_srcaddr_v6,
+ tvb, offset, length, ipv6addr);
+ } else {
+ proto_tree_add_text(pdutree,
+ tvb, offset, length,
+ "SrcAddr: length %u", length);
+ }
+ break;
+
+ case 9: /* source mask */
+ proto_tree_add_item(pdutree, hf_cflow_srcmask,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 10: /* input SNMP */
+ proto_tree_add_item(pdutree, hf_cflow_inputint,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 11: /* dest port */
+ proto_tree_add_item(pdutree, hf_cflow_dstport,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 12: /* dest IP */
+ if (length == 4) {
+ tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset,
+ sizeof(ipv4addr));
+ proto_tree_add_ipv4(pdutree, hf_cflow_dstaddr,
+ tvb, offset, length, ipv4addr);
+ } else if (length == 16) {
+ tvb_memcpy(tvb, ipv6addr, offset,
+ sizeof(ipv6addr));
+ proto_tree_add_ipv6(pdutree, hf_cflow_dstaddr_v6,
+ tvb, offset, length, ipv6addr);
+ } else {
+ proto_tree_add_text(pdutree,
+ tvb, offset, length,
+ "DstAddr: length %u", length);
+ }
+ break;
+
+ case 13: /* dest mask */
+ proto_tree_add_item(pdutree, hf_cflow_dstmask,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 14: /* output SNMP */
+ proto_tree_add_item(pdutree, hf_cflow_outputint,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 15: /* nexthop IP */
+ if (length == 4) {
+ tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset,
+ sizeof(ipv4addr));
+ proto_tree_add_ipv4(pdutree, hf_cflow_nexthop,
+ tvb, offset, length, ipv4addr);
+ } else if (length == 16) {
+ tvb_memcpy(tvb, ipv6addr, offset,
+ sizeof(ipv6addr));
+ proto_tree_add_ipv6(pdutree, hf_cflow_nexthop_v6,
+ tvb, offset, length, ipv6addr);
+ } else {
+ proto_tree_add_text(pdutree,
+ tvb, offset, length,
+ "NextHop: length %u", length);
+ }
+ break;
+
+ case 16: /* source AS */
+ proto_tree_add_item(pdutree, hf_cflow_srcas,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 17: /* dest AS */
+ proto_tree_add_item(pdutree, hf_cflow_dstas,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 18: /* BGP nexthop IP */
+ if (length == 4) {
+ tvb_memcpy(tvb, (guint8 *)&ipv4addr, offset,
+ sizeof(ipv4addr));
+ proto_tree_add_ipv4(pdutree, hf_cflow_bgpnexthop,
+ tvb, offset, length, ipv4addr);
+ } else if (length == 16) {
+ tvb_memcpy(tvb, ipv6addr, offset,
+ sizeof(ipv6addr));
+ proto_tree_add_ipv6(pdutree, hf_cflow_bgpnexthop_v6,
+ tvb, offset, length, ipv6addr);
+ } else {
+ proto_tree_add_text(pdutree,
+ tvb, offset, length,
+ "BGPNextHop: length %u", length);
+ }
+ break;
+
+ case 19: /* multicast packets */
+ proto_tree_add_item(pdutree, hf_cflow_mulpackets,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 20: /* multicast octets */
+ proto_tree_add_item(pdutree, hf_cflow_muloctets,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 21: /* last switched */
+ ts.secs = tvb_get_ntohl(tvb, offset) / 1000;
+ ts.nsecs = 0;
+ proto_tree_add_time(pdutree, hf_cflow_timeend,
+ tvb, offset, length, &ts);
+ break;
+
+ case 22: /* first switched */
+ ts.secs = tvb_get_ntohl(tvb, offset) / 1000;
+ ts.nsecs = 0;
+ proto_tree_add_time(pdutree, hf_cflow_timestart,
+ tvb, offset, length, &ts);
+ break;
+
+ case 40: /* bytes exported */
+ proto_tree_add_item(pdutree, hf_cflow_octets_exp,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 41: /* packets exported */
+ proto_tree_add_item(pdutree, hf_cflow_packets_exp,
+ tvb, offset, length, FALSE);
+ break;
+
+ case 42: /* flows exported */
+ proto_tree_add_item(pdutree, hf_cflow_flows_exp,
+ tvb, offset, length, FALSE);
+ break;
+
+ default:
+ proto_tree_add_text(pdutree, tvb, offset, length,
+ "Type %u", type);
+ break;
+ }
+
+ offset += length;
+ }
+}
+
+#if 0
+static int
+dissect_v9_options(proto_tree * pdutree, tvbuff_t * tvb, int offset)
+{
+ return (0);
+}
+#endif
+
+static int
+dissect_v9_template(proto_tree * pdutree, tvbuff_t * tvb, int offset)
+{
+ struct v9_template template;
+ proto_tree *template_tree;
+ proto_item *template_item;
+ guint16 id, count;
+ gint32 i;
+
+ id = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(pdutree, hf_cflow_template_id, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(pdutree, hf_cflow_template_field_count, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ /* Cache template */
+ memset(&template, 0, sizeof(template));
+ template.id = id;
+ template.count = count;
+ template.source_addr = 0; /* XXX */
+ template.source_id = 0; /* XXX */
+ template.entries = g_malloc(count * sizeof(struct v9_template_entry));
+ tvb_memcpy(tvb, (guint8 *)template.entries, offset,
+ count * sizeof(struct v9_template_entry));
+ v9_template_add(&template);
+
+ for (i = 1; i <= count; i++) {
+ guint16 type, length;
+
+ type = tvb_get_ntohs(tvb, offset);
+ length = tvb_get_ntohs(tvb, offset + 2);
+
+ template_item = proto_tree_add_text(pdutree, tvb,
+ offset, 4, "Field (%u/%u)", i, count);
+ template_tree = proto_item_add_subtree(template_item, ett_template);
+
+ proto_tree_add_item(template_tree,
+ hf_cflow_template_field_type, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(template_tree,
+ hf_cflow_template_field_length, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ return (0);
+}
+
+static value_string v9_template_types[] = {
+ { 1, "BYTES" },
+ { 2, "PKTS" },
+ { 3, "FLOWS" },
+ { 4, "PROT" },
+ { 5, "TOS" },
+ { 6, "TCP_FLAGS" },
+ { 7, "L4_SRC_PORT" },
+ { 8, "IP_SRC_ADDR" },
+ { 9, "SRC_MASK" },
+ { 10, "INPUT_SNMP" },
+ { 11, "L4_DST_PORT" },
+ { 12, "IP_DST_ADDR" },
+ { 13, "DST_MASK" },
+ { 14, "OUTPUT_SNMP" },
+ { 15, "IP_NEXT_HOP" },
+ { 16, "SRC_AS" },
+ { 17, "DST_AS" },
+ { 18, "BGP_NEXT_HOP" },
+ { 19, "MUL_DPKTS" },
+ { 20, "MUL_DOCTETS" },
+ { 21, "LAST_SWITCHED" },
+ { 22, "FIRST_SWITCHED" },
+ { 24, "OUT_PKTS" },
+ { 40, "TOTAL_BYTES_EXP" },
+ { 41, "TOTAL_PKTS_EXP" },
+ { 42, "TOTAL_FLOWS_EXP" },
+ { 0, NULL },
+};
+
+static void
+v9_template_add(struct v9_template *template)
+{
+ int i;
+
+ /* Add up the actual length of the data and store in proper byte order */
+ template->length = 0;
+ for (i = 0; i < template->count; i++) {
+ template->entries[i].type = g_ntohs(template->entries[i].type);
+ template->entries[i].length = g_ntohs(template->entries[i].length);
+ template->length += template->entries[i].length;
+ }
+
+ memmove(&v9_template_cache[template->id % V9TEMPLATE_CACHE_MAX_ENTRIES],
+ template, sizeof(*template));
+}
+
+static struct v9_template *
+v9_template_get(guint16 id, guint32 src_addr, guint32 src_id)
+{
+ struct v9_template *template;
+
+ src_addr = 0;
+ template = &v9_template_cache[id % V9TEMPLATE_CACHE_MAX_ENTRIES];
+
+ if (template->id != id ||
+ template->source_addr != src_addr ||
+ template->source_id != src_id) {
+ template = NULL;
+ }
+
+ return (template);
+}
+
+/*
+ * dissect a version 1, 5, or 7 pdu and return the length of the pdu we
+ * processed
+ */
+
+static int
+dissect_pdu(proto_tree * pdutree, tvbuff_t * tvb, int offset, int ver)
+{
+ int startoffset = offset;
+ guint32 srcaddr, dstaddr;
+ guint8 mask;
+ nstime_t ts;
+
+ memset(&ts, '\0', sizeof(ts));
+
+ /*
+ * memcpy so we can use the values later to calculate a prefix
+ */
+ tvb_memcpy(tvb, (guint8 *) & srcaddr, offset, 4);
+ proto_tree_add_ipv4(pdutree, hf_cflow_srcaddr, tvb, offset, 4,
+ srcaddr);
+ offset += 4;
+
+ tvb_memcpy(tvb, (guint8 *) & dstaddr, offset, 4);
+ proto_tree_add_ipv4(pdutree, hf_cflow_dstaddr, tvb, offset, 4,
+ dstaddr);
+ offset += 4;
+
+ proto_tree_add_item(pdutree, hf_cflow_nexthop, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ offset = flow_process_ints(pdutree, tvb, offset);
+ offset = flow_process_sizecount(pdutree, tvb, offset);
+ offset = flow_process_timeperiod(pdutree, tvb, offset);
+ offset = flow_process_ports(pdutree, tvb, offset);
+
+ /*
+ * and the similarities end here
+ */
+ if (ver == 1) {
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 2, "padding");
+
+ proto_tree_add_item(pdutree, hf_cflow_prot, tvb, offset++, 1,
+ FALSE);
+
+ proto_tree_add_item(pdutree, hf_cflow_tos, tvb, offset++, 1,
+ FALSE);
+
+ proto_tree_add_item(pdutree, hf_cflow_tcpflags, tvb, offset++,
+ 1, FALSE);
+
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 3, "padding");
+
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 4,
+ "reserved");
+ } else {
+ if (ver == 5)
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 1,
+ "padding");
+ else {
+ proto_tree_add_item(pdutree, hf_cflow_flags, tvb,
+ offset++, 1, FALSE);
+ }
+
+ proto_tree_add_item(pdutree, hf_cflow_tcpflags, tvb, offset++,
+ 1, FALSE);
+
+ proto_tree_add_item(pdutree, hf_cflow_prot, tvb, offset++, 1,
+ FALSE);
+
+ proto_tree_add_item(pdutree, hf_cflow_tos, tvb, offset++, 1,
+ FALSE);
+
+ offset = flow_process_aspair(pdutree, tvb, offset);
+
+ mask = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(pdutree, tvb, offset, 1,
+ "SrcMask: %u (prefix: %s/%u)",
+ mask, getprefix(&srcaddr, mask),
+ mask != 0 ? mask : 32);
+ proto_tree_add_uint_hidden(pdutree, hf_cflow_srcmask, tvb,
+ offset++, 1, mask);
+
+ mask = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(pdutree, tvb, offset, 1,
+ "DstMask: %u (prefix: %s/%u)",
+ mask, getprefix(&dstaddr, mask),
+ mask != 0 ? mask : 32);
+ proto_tree_add_uint_hidden(pdutree, hf_cflow_dstmask, tvb,
+ offset++, 1, mask);
+
+ offset =
+ flow_process_textfield(pdutree, tvb, offset, 2, "padding");
+
+ if (ver == 7) {
+ proto_tree_add_item(pdutree, hf_cflow_routersc, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ }
+ }
+
+ return (offset - startoffset);
+}
+
+static gchar *
+getprefix(const guint32 * address, int prefix)
+{
+ guint32 gprefix;
+
+ gprefix = *address & g_htonl((0xffffffff << (32 - prefix)));
+
+ return (ip_to_str((const guint8 *)&gprefix));
+}
+
+
+static void
+netflow_reinit(void)
+{
+ int i;
+
+ /*
+ * Clear out the template cache.
+ * Free the table of fields for each entry, and then zero out
+ * the cache.
+ */
+ for (i = 0; i < V9TEMPLATE_CACHE_MAX_ENTRIES; i++)
+ g_free(v9_template_cache[i].entries);
+ memset(v9_template_cache, 0, sizeof v9_template_cache);
+}
+
+void
+proto_register_netflow(void)
+{
+ static hf_register_info hf[] = {
+ /*
+ * flow header
+ */
+ {&hf_cflow_version,
+ {"Version", "cflow.version",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "NetFlow Version", HFILL}
+ },
+ {&hf_cflow_count,
+ {"Count", "cflow.count",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Count of PDUs", HFILL}
+ },
+ {&hf_cflow_sysuptime,
+ {"SysUptime", "cflow.sysuptime",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Time since router booted (in milliseconds)", HFILL}
+ },
+
+ {&hf_cflow_timestamp,
+ {"Timestamp", "cflow.timestamp",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Current seconds since epoch", HFILL}
+ },
+ {&hf_cflow_unix_secs,
+ {"CurrentSecs", "cflow.unix_secs",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Current seconds since epoch", HFILL}
+ },
+ {&hf_cflow_unix_nsecs,
+ {"CurrentNSecs", "cflow.unix_nsecs",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Residual nanoseconds since epoch", HFILL}
+ },
+ {&hf_cflow_samplingmode,
+ {"SamplingMode", "cflow.samplingmode",
+ FT_UINT16, BASE_DEC, VALS(v5_sampling_mode), 0xC000,
+ "Sampling Mode of exporter", HFILL}
+ },
+ {&hf_cflow_samplerate,
+ {"SampleRate", "cflow.samplerate",
+ FT_UINT16, BASE_DEC, NULL, 0x3FFF,
+ "Sample Frequency of exporter", HFILL}
+ },
+
+ /*
+ * end version-agnostic header
+ * version-specific flow header
+ */
+ {&hf_cflow_sequence,
+ {"FlowSequence", "cflow.sequence",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sequence number of flows seen", HFILL}
+ },
+ {&hf_cflow_engine_type,
+ {"EngineType", "cflow.engine_type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Flow switching engine type", HFILL}
+ },
+ {&hf_cflow_engine_id,
+ {"EngineId", "cflow.engine_id",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Slot number of switching engine", HFILL}
+ },
+ {&hf_cflow_source_id,
+ {"SourceId", "cflow.source_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Identifier for export device", HFILL}
+ },
+ {&hf_cflow_aggmethod,
+ {"AggMethod", "cflow.aggmethod",
+ FT_UINT8, BASE_DEC, VALS(v8_agg), 0x0,
+ "CFlow V8 Aggregation Method", HFILL}
+ },
+ {&hf_cflow_aggversion,
+ {"AggVersion", "cflow.aggversion",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "CFlow V8 Aggregation Version", HFILL}
+ },
+ /*
+ * end version specific header storage
+ */
+ /*
+ * Version 9
+ */
+ {&hf_cflow_flowset_id,
+ {"FlowSet Id", "cflow.flowset_id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "FlowSet Id", HFILL}
+ },
+ {&hf_cflow_data_flowset_id,
+ {"Data FlowSet (Template Id)", "cflow.data_flowset_id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Data FlowSet with corresponding to a template Id", HFILL}
+ },
+ {&hf_cflow_options_flowset_id,
+ {"Options FlowSet", "cflow.options_flowset_id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Options FlowSet", HFILL}
+ },
+ {&hf_cflow_template_flowset_id,
+ {"Template FlowSet", "cflow.template_flowset_id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Template FlowSet", HFILL}
+ },
+ {&hf_cflow_flowset_length,
+ {"FlowSet Length", "cflow.flowset_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "FlowSet length", HFILL}
+ },
+ {&hf_cflow_template_id,
+ {"Template Id", "cflow.template_id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Template Id", HFILL}
+ },
+ {&hf_cflow_template_field_count,
+ {"Field Count", "cflow.template_field_count",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Template field count", HFILL}
+ },
+ {&hf_cflow_template_field_type,
+ {"Type", "cflow.template_field_type",
+ FT_UINT16, BASE_DEC, VALS(v9_template_types), 0x0,
+ "Template field type", HFILL}
+ },
+ {&hf_cflow_template_field_length,
+ {"Length", "cflow.template_field_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Template field length", HFILL}
+ },
+ /*
+ * begin pdu content storage
+ */
+ {&hf_cflow_srcaddr,
+ {"SrcAddr", "cflow.srcaddr",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Flow Source Address", HFILL}
+ },
+ {&hf_cflow_srcaddr_v6,
+ {"SrcAddr", "cflow.srcaddrv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Flow Source Address", HFILL}
+ },
+ {&hf_cflow_srcnet,
+ {"SrcNet", "cflow.srcnet",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Flow Source Network", HFILL}
+ },
+ {&hf_cflow_dstaddr,
+ {"DstAddr", "cflow.dstaddr",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Flow Destination Address", HFILL}
+ },
+ {&hf_cflow_dstaddr_v6,
+ {"DstAddr", "cflow.dstaddrv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Flow Destination Address", HFILL}
+ },
+ {&hf_cflow_dstnet,
+ {"DstNet", "cflow.dstaddr",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Flow Destination Network", HFILL}
+ },
+ {&hf_cflow_nexthop,
+ {"NextHop", "cflow.nexthop",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Router nexthop", HFILL}
+ },
+ {&hf_cflow_nexthop_v6,
+ {"NextHop", "cflow.nexthopv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Router nexthop", HFILL}
+ },
+ {&hf_cflow_bgpnexthop,
+ {"BGPNextHop", "cflow.bgpnexthop",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "BGP Router Nexthop", HFILL}
+ },
+ {&hf_cflow_bgpnexthop_v6,
+ {"BGPNextHop", "cflow.bgpnexthopv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "BGP Router Nexthop", HFILL}
+ },
+ {&hf_cflow_inputint,
+ {"InputInt", "cflow.inputint",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Flow Input Interface", HFILL}
+ },
+ {&hf_cflow_outputint,
+ {"OutputInt", "cflow.outputint",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Flow Output Interface", HFILL}
+ },
+ {&hf_cflow_flows,
+ {"Flows", "cflow.flows",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Flows Aggregated in PDU", HFILL}
+ },
+ {&hf_cflow_packets,
+ {"Packets", "cflow.packets",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Count of packets", HFILL}
+ },
+ {&hf_cflow_packets64,
+ {"Packets", "cflow.packets64",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Count of packets", HFILL}
+ },
+ {&hf_cflow_packetsout,
+ {"PacketsOut", "cflow.packetsout",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Count of packets going out", HFILL}
+ },
+ {&hf_cflow_octets,
+ {"Octets", "cflow.octets",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Count of bytes", HFILL}
+ },
+ {&hf_cflow_octets64,
+ {"Octets", "cflow.octets64",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Count of bytes", HFILL}
+ },
+ {&hf_cflow_timestart,
+ {"StartTime", "cflow.timestart",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
+ "Uptime at start of flow", HFILL}
+ },
+ {&hf_cflow_timeend,
+ {"EndTime", "cflow.timeend",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
+ "Uptime at end of flow", HFILL}
+ },
+ {&hf_cflow_srcport,
+ {"SrcPort", "cflow.srcport",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Flow Source Port", HFILL}
+ },
+ {&hf_cflow_dstport,
+ {"DstPort", "cflow.dstport",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Flow Destination Port", HFILL}
+ },
+ {&hf_cflow_prot,
+ {"Protocol", "cflow.protocol",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "IP Protocol", HFILL}
+ },
+ {&hf_cflow_tos,
+ {"IP ToS", "cflow.tos",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "IP Type of Service", HFILL}
+ },
+ {&hf_cflow_flags,
+ {"Export Flags", "cflow.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "CFlow Flags", HFILL}
+ },
+ {&hf_cflow_tcpflags,
+ {"TCP Flags", "cflow.tcpflags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "TCP Flags", HFILL}
+ },
+ {&hf_cflow_srcas,
+ {"SrcAS", "cflow.srcas",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Source AS", HFILL}
+ },
+ {&hf_cflow_dstas,
+ {"DstAS", "cflow.dstas",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Destination AS", HFILL}
+ },
+ {&hf_cflow_srcmask,
+ {"SrcMask", "cflow.srcmask",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Source Prefix Mask", HFILL}
+ },
+ {&hf_cflow_dstmask,
+ {"DstMask", "cflow.dstmask",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Destination Prefix Mask", HFILL}
+ },
+ {&hf_cflow_routersc,
+ {"Router Shortcut", "cflow.routersc",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Router shortcut by switch", HFILL}
+ },
+ {&hf_cflow_mulpackets,
+ {"MulticastPackets", "cflow.mulpackets",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Count of multicast packets", HFILL}
+ },
+ {&hf_cflow_muloctets,
+ {"MulticastOctets", "cflow.muloctets",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Count of multicast octets", HFILL}
+ },
+ {&hf_cflow_octets_exp,
+ {"OctetsExp", "cflow.octetsexp",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Octets exported", HFILL}
+ },
+ {&hf_cflow_packets_exp,
+ {"PacketsExp", "cflow.packetsexp",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Packets exported", HFILL}
+ },
+ {&hf_cflow_flows_exp,
+ {"FlowsExp", "cflow.flowsexp",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Flows exported", HFILL}
+ }
+ /*
+ * end pdu content storage
+ */
+ };
+
+ static gint *ett[] = {
+ &ett_netflow,
+ &ett_unixtime,
+ &ett_flow,
+ &ett_template,
+ &ett_dataflowset
+ };
+
+ module_t *netflow_module;
+
+ proto_netflow = proto_register_protocol("Cisco NetFlow", "CFLOW",
+ "cflow");
+
+ proto_register_field_array(proto_netflow, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register our configuration options for NetFlow */
+ netflow_module = prefs_register_protocol(proto_netflow,
+ proto_reg_handoff_netflow);
+
+ prefs_register_uint_preference(netflow_module, "udp.port",
+ "NetFlow UDP Port", "Set the port for NetFlow messages",
+ 10, &global_netflow_udp_port);
+
+ register_init_routine(&netflow_reinit);
+}
+
+
+/*
+ * protocol/port association
+ */
+void
+proto_reg_handoff_netflow(void)
+{
+ static int netflow_prefs_initialized = FALSE;
+ static dissector_handle_t netflow_handle;
+
+ if (!netflow_prefs_initialized) {
+ netflow_handle = create_dissector_handle(dissect_netflow,
+ proto_netflow);
+ netflow_prefs_initialized = TRUE;
+ } else {
+ dissector_delete("udp.port", netflow_udp_port, netflow_handle);
+ }
+
+ /* Set out port number for future use */
+ netflow_udp_port = global_netflow_udp_port;
+
+ dissector_add("udp.port", netflow_udp_port, netflow_handle);
+}
diff --git a/epan/dissectors/packet-nfs.c b/epan/dissectors/packet-nfs.c
new file mode 100644
index 0000000000..3b73d5640e
--- /dev/null
+++ b/epan/dissectors/packet-nfs.c
@@ -0,0 +1,8794 @@
+/* packet-nfs.c
+ * Routines for nfs dissection
+ * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
+ * Copyright 2000-2004, Mike Frisch <frisch@hummingbird.com> (NFSv4 decoding)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-smb.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <string.h>
+
+
+#include "packet-rpc.h"
+#include "packet-nfs.h"
+#include "prefs.h"
+#include "epan/int-64bit.h"
+
+static int proto_nfs = -1;
+
+static int hf_nfs_procedure_v2 = -1;
+static int hf_nfs_procedure_v3 = -1;
+static int hf_nfs_procedure_v4 = -1;
+static int hf_nfs_fh_length = -1;
+static int hf_nfs_fh_hash = -1;
+static int hf_nfs_fh_mount_fileid = -1;
+static int hf_nfs_fh_mount_generation = -1;
+static int hf_nfs_fh_snapid = -1;
+static int hf_nfs_fh_unused = -1;
+static int hf_nfs_fh_flags = -1;
+static int hf_nfs_fh_fileid = -1;
+static int hf_nfs_fh_generation = -1;
+static int hf_nfs_fh_fsid = -1;
+static int hf_nfs_fh_export_fileid = -1;
+static int hf_nfs_fh_export_generation = -1;
+static int hf_nfs_fh_export_snapid = -1;
+static int hf_nfs_fh_fsid_major = -1;
+static int hf_nfs_fh_fsid_minor = -1;
+static int hf_nfs_fh_fsid_inode = -1;
+static int hf_nfs_fh_xfsid_major = -1;
+static int hf_nfs_fh_xfsid_minor = -1;
+static int hf_nfs_fh_fstype = -1;
+static int hf_nfs_fh_fn = -1;
+static int hf_nfs_fh_fn_len = -1;
+static int hf_nfs_fh_fn_inode = -1;
+static int hf_nfs_fh_fn_generation = -1;
+static int hf_nfs_fh_xfn = -1;
+static int hf_nfs_fh_xfn_len = -1;
+static int hf_nfs_fh_xfn_inode = -1;
+static int hf_nfs_fh_xfn_generation = -1;
+static int hf_nfs_fh_dentry = -1;
+static int hf_nfs_fh_dev = -1;
+static int hf_nfs_fh_xdev = -1;
+static int hf_nfs_fh_dirinode = -1;
+static int hf_nfs_fh_pinode = -1;
+static int hf_nfs_fh_hp_len = -1;
+static int hf_nfs_fh_version = -1;
+static int hf_nfs_fh_auth_type = -1;
+static int hf_nfs_fh_fsid_type = -1;
+static int hf_nfs_fh_fileid_type = -1;
+static int hf_nfs_stat = -1;
+static int hf_nfs_name = -1;
+static int hf_nfs_full_name = -1;
+static int hf_nfs_readlink_data = -1;
+static int hf_nfs_read_offset = -1;
+static int hf_nfs_read_count = -1;
+static int hf_nfs_read_totalcount = -1;
+static int hf_nfs_data = -1;
+static int hf_nfs_write_beginoffset = -1;
+static int hf_nfs_write_offset = -1;
+static int hf_nfs_write_totalcount = -1;
+static int hf_nfs_symlink_to = -1;
+static int hf_nfs_readdir_cookie = -1;
+static int hf_nfs_readdir_count = -1;
+static int hf_nfs_readdir_entry = -1;
+static int hf_nfs_readdir_entry_fileid = -1;
+static int hf_nfs_readdir_entry_name = -1;
+static int hf_nfs_readdir_entry_cookie = -1;
+static int hf_nfs_readdir_entry3_fileid = -1;
+static int hf_nfs_readdir_entry3_name = -1;
+static int hf_nfs_readdir_entry3_cookie = -1;
+static int hf_nfs_readdirplus_entry_fileid = -1;
+static int hf_nfs_readdirplus_entry_name = -1;
+static int hf_nfs_readdirplus_entry_cookie = -1;
+static int hf_nfs_readdir_eof = -1;
+static int hf_nfs_statfs_tsize = -1;
+static int hf_nfs_statfs_bsize = -1;
+static int hf_nfs_statfs_blocks = -1;
+static int hf_nfs_statfs_bfree = -1;
+static int hf_nfs_statfs_bavail = -1;
+static int hf_nfs_ftype3 = -1;
+static int hf_nfs_nfsstat3 = -1;
+static int hf_nfs_read_eof = -1;
+static int hf_nfs_write_stable = -1;
+static int hf_nfs_write_committed = -1;
+static int hf_nfs_createmode3 = -1;
+static int hf_nfs_fsstat_invarsec = -1;
+static int hf_nfs_fsinfo_rtmax = -1;
+static int hf_nfs_fsinfo_rtpref = -1;
+static int hf_nfs_fsinfo_rtmult = -1;
+static int hf_nfs_fsinfo_wtmax = -1;
+static int hf_nfs_fsinfo_wtpref = -1;
+static int hf_nfs_fsinfo_wtmult = -1;
+static int hf_nfs_fsinfo_dtpref = -1;
+static int hf_nfs_fsinfo_maxfilesize = -1;
+static int hf_nfs_fsinfo_properties = -1;
+static int hf_nfs_pathconf_linkmax = -1;
+static int hf_nfs_pathconf_name_max = -1;
+static int hf_nfs_pathconf_no_trunc = -1;
+static int hf_nfs_pathconf_chown_restricted = -1;
+static int hf_nfs_pathconf_case_insensitive = -1;
+static int hf_nfs_pathconf_case_preserving = -1;
+
+static int hf_nfs_atime = -1;
+static int hf_nfs_atime_sec = -1;
+static int hf_nfs_atime_nsec = -1;
+static int hf_nfs_atime_usec = -1;
+static int hf_nfs_mtime = -1;
+static int hf_nfs_mtime_sec = -1;
+static int hf_nfs_mtime_nsec = -1;
+static int hf_nfs_mtime_usec = -1;
+static int hf_nfs_ctime = -1;
+static int hf_nfs_ctime_sec = -1;
+static int hf_nfs_ctime_nsec = -1;
+static int hf_nfs_ctime_usec = -1;
+static int hf_nfs_dtime = -1;
+static int hf_nfs_dtime_sec = -1;
+static int hf_nfs_dtime_nsec = -1;
+
+static int hf_nfs_fattr_type = -1;
+static int hf_nfs_fattr_nlink = -1;
+static int hf_nfs_fattr_uid = -1;
+static int hf_nfs_fattr_gid = -1;
+static int hf_nfs_fattr_size = -1;
+static int hf_nfs_fattr_blocksize = -1;
+static int hf_nfs_fattr_rdev = -1;
+static int hf_nfs_fattr_blocks = -1;
+static int hf_nfs_fattr_fsid = -1;
+static int hf_nfs_fattr_fileid = -1;
+static int hf_nfs_fattr3_type = -1;
+static int hf_nfs_fattr3_nlink = -1;
+static int hf_nfs_fattr3_uid = -1;
+static int hf_nfs_fattr3_gid = -1;
+static int hf_nfs_fattr3_size = -1;
+static int hf_nfs_fattr3_used = -1;
+static int hf_nfs_fattr3_rdev = -1;
+static int hf_nfs_fattr3_fsid = -1;
+static int hf_nfs_fattr3_fileid = -1;
+static int hf_nfs_wcc_attr_size = -1;
+static int hf_nfs_set_size3_size = -1;
+static int hf_nfs_cookie3 = -1;
+static int hf_nfs_fsstat3_resok_tbytes = -1;
+static int hf_nfs_fsstat3_resok_fbytes = -1;
+static int hf_nfs_fsstat3_resok_abytes = -1;
+static int hf_nfs_fsstat3_resok_tfiles = -1;
+static int hf_nfs_fsstat3_resok_ffiles = -1;
+static int hf_nfs_fsstat3_resok_afiles = -1;
+static int hf_nfs_uid3 = -1;
+static int hf_nfs_gid3 = -1;
+static int hf_nfs_offset3 = -1;
+static int hf_nfs_count3 = -1;
+static int hf_nfs_count3_maxcount = -1;
+static int hf_nfs_count3_dircount= -1;
+
+/* NFSv4 */
+static int hf_nfs_argop4 = -1;
+static int hf_nfs_resop4 = -1;
+static int hf_nfs_linktext4 = -1;
+static int hf_nfs_tag4 = -1;
+static int hf_nfs_component4 = -1;
+static int hf_nfs_clientid4 = -1;
+static int hf_nfs_ace4 = -1;
+static int hf_nfs_recall = -1;
+static int hf_nfs_open_claim_type4 = -1;
+static int hf_nfs_opentype4 = -1;
+static int hf_nfs_limit_by4 = -1;
+static int hf_nfs_open_delegation_type4 = -1;
+static int hf_nfs_ftype4 = -1;
+static int hf_nfs_change_info4_atomic = -1;
+static int hf_nfs_open4_share_access = -1;
+static int hf_nfs_open4_share_deny = -1;
+static int hf_nfs_seqid4 = -1;
+static int hf_nfs_lock_seqid4 = -1;
+static int hf_nfs_mand_attr = -1;
+static int hf_nfs_recc_attr = -1;
+static int hf_nfs_time_how4 = -1;
+static int hf_nfs_attrlist4 = -1;
+static int hf_nfs_fattr4_link_support = -1;
+static int hf_nfs_fattr4_symlink_support = -1;
+static int hf_nfs_fattr4_named_attr = -1;
+static int hf_nfs_fattr4_unique_handles = -1;
+static int hf_nfs_fattr4_archive = -1;
+static int hf_nfs_fattr4_cansettime = -1;
+static int hf_nfs_fattr4_case_insensitive = -1;
+static int hf_nfs_fattr4_case_preserving = -1;
+static int hf_nfs_fattr4_chown_restricted = -1;
+static int hf_nfs_fattr4_hidden = -1;
+static int hf_nfs_fattr4_homogeneous = -1;
+static int hf_nfs_fattr4_mimetype = -1;
+static int hf_nfs_fattr4_no_trunc = -1;
+static int hf_nfs_fattr4_system = -1;
+static int hf_nfs_fattr4_owner = -1;
+static int hf_nfs_fattr4_owner_group = -1;
+static int hf_nfs_fattr4_size = -1;
+static int hf_nfs_fattr4_aclsupport = -1;
+static int hf_nfs_fattr4_lease_time = -1;
+static int hf_nfs_fattr4_fileid = -1;
+static int hf_nfs_fattr4_files_avail = -1;
+static int hf_nfs_fattr4_files_free = -1;
+static int hf_nfs_fattr4_files_total = -1;
+static int hf_nfs_fattr4_maxfilesize = -1;
+static int hf_nfs_fattr4_maxlink = -1;
+static int hf_nfs_fattr4_maxname = -1;
+static int hf_nfs_fattr4_numlinks = -1;
+static int hf_nfs_fattr4_maxread = -1;
+static int hf_nfs_fattr4_maxwrite = -1;
+static int hf_nfs_fattr4_quota_hard = -1;
+static int hf_nfs_fattr4_quota_soft = -1;
+static int hf_nfs_fattr4_quota_used = -1;
+static int hf_nfs_fattr4_space_avail = -1;
+static int hf_nfs_fattr4_space_free = -1;
+static int hf_nfs_fattr4_space_total = -1;
+static int hf_nfs_fattr4_space_used = -1;
+static int hf_nfs_who = -1;
+static int hf_nfs_server = -1;
+static int hf_nfs_stable_how4 = -1;
+static int hf_nfs_dirlist4_eof = -1;
+static int hf_nfs_stateid4 = -1;
+static int hf_nfs_offset4 = -1;
+static int hf_nfs_specdata1 = -1;
+static int hf_nfs_specdata2 = -1;
+static int hf_nfs_lock_type4 = -1;
+static int hf_nfs_reclaim4 = -1;
+static int hf_nfs_length4 = -1;
+static int hf_nfs_changeid4 = -1;
+static int hf_nfs_changeid4_before = -1;
+static int hf_nfs_changeid4_after = -1;
+static int hf_nfs_nfstime4_seconds = -1;
+static int hf_nfs_nfstime4_nseconds = -1;
+static int hf_nfs_fsid4_major = -1;
+static int hf_nfs_fsid4_minor = -1;
+static int hf_nfs_acetype4 = -1;
+static int hf_nfs_aceflag4 = -1;
+static int hf_nfs_acemask4 = -1;
+static int hf_nfs_delegate_type = -1;
+static int hf_nfs_secinfo_flavor = -1;
+static int hf_nfs_secinfo_arr4 = -1;
+static int hf_nfs_num_blocks = -1;
+static int hf_nfs_bytes_per_block = -1;
+static int hf_nfs_eof = -1;
+static int hf_nfs_stateid4_delegate_stateid = -1;
+static int hf_nfs_verifier4 = -1;
+static int hf_nfs_cookie4 = -1;
+static int hf_nfs_cookieverf4 = -1;
+static int hf_nfs_cb_program = -1;
+static int hf_nfs_cb_location = -1;
+static int hf_nfs_recall4 = -1;
+static int hf_nfs_filesize = -1;
+static int hf_nfs_count4 = -1;
+static int hf_nfs_count4_dircount = -1;
+static int hf_nfs_count4_maxcount = -1;
+static int hf_nfs_minorversion = -1;
+static int hf_nfs_open_owner4 = -1;
+static int hf_nfs_lock_owner4 = -1;
+static int hf_nfs_new_lock_owner = -1;
+static int hf_nfs_sec_oid4 = -1;
+static int hf_nfs_qop4 = -1;
+static int hf_nfs_secinfo_rpcsec_gss_info_service = -1;
+static int hf_nfs_attrdircreate = -1;
+static int hf_nfs_client_id4_id = -1;
+static int hf_nfs_stateid4_other = -1;
+static int hf_nfs_lock4_reclaim = -1;
+static int hf_nfs_acl4 = -1;
+static int hf_nfs_callback_ident = -1;
+static int hf_nfs_r_netid = -1;
+static int hf_nfs_r_addr = -1;
+
+static gint ett_nfs = -1;
+static gint ett_nfs_fh_encoding = -1;
+static gint ett_nfs_fh_mount = -1;
+static gint ett_nfs_fh_file = -1;
+static gint ett_nfs_fh_export = -1;
+static gint ett_nfs_fh_fsid = -1;
+static gint ett_nfs_fh_xfsid = -1;
+static gint ett_nfs_fh_fn = -1;
+static gint ett_nfs_fh_xfn = -1;
+static gint ett_nfs_fh_hp = -1;
+static gint ett_nfs_fh_auth = -1;
+static gint ett_nfs_fhandle = -1;
+static gint ett_nfs_timeval = -1;
+static gint ett_nfs_mode = -1;
+static gint ett_nfs_fattr = -1;
+static gint ett_nfs_sattr = -1;
+static gint ett_nfs_diropargs = -1;
+static gint ett_nfs_readdir_entry = -1;
+static gint ett_nfs_mode3 = -1;
+static gint ett_nfs_specdata3 = -1;
+static gint ett_nfs_fh3 = -1;
+static gint ett_nfs_nfstime3 = -1;
+static gint ett_nfs_fattr3 = -1;
+static gint ett_nfs_post_op_fh3 = -1;
+static gint ett_nfs_sattr3 = -1;
+static gint ett_nfs_diropargs3 = -1;
+static gint ett_nfs_sattrguard3 = -1;
+static gint ett_nfs_set_mode3 = -1;
+static gint ett_nfs_set_uid3 = -1;
+static gint ett_nfs_set_gid3 = -1;
+static gint ett_nfs_set_size3 = -1;
+static gint ett_nfs_set_atime = -1;
+static gint ett_nfs_set_mtime = -1;
+static gint ett_nfs_pre_op_attr = -1;
+static gint ett_nfs_post_op_attr = -1;
+static gint ett_nfs_wcc_attr = -1;
+static gint ett_nfs_wcc_data = -1;
+static gint ett_nfs_access = -1;
+static gint ett_nfs_fsinfo_properties = -1;
+
+/* NFSv4 */
+static gint ett_nfs_compound_call4 = -1;
+static gint ett_nfs_utf8string = -1;
+static gint ett_nfs_argop4 = -1;
+static gint ett_nfs_resop4 = -1;
+static gint ett_nfs_access4 = -1;
+static gint ett_nfs_close4 = -1;
+static gint ett_nfs_commit4 = -1;
+static gint ett_nfs_create4 = -1;
+static gint ett_nfs_delegpurge4 = -1;
+static gint ett_nfs_delegreturn4 = -1;
+static gint ett_nfs_getattr4 = -1;
+static gint ett_nfs_getfh4 = -1;
+static gint ett_nfs_link4 = -1;
+static gint ett_nfs_lock4 = -1;
+static gint ett_nfs_lockt4 = -1;
+static gint ett_nfs_locku4 = -1;
+static gint ett_nfs_lookup4 = -1;
+static gint ett_nfs_lookupp4 = -1;
+static gint ett_nfs_nverify4 = -1;
+static gint ett_nfs_open4 = -1;
+static gint ett_nfs_openattr4 = -1;
+static gint ett_nfs_open_confirm4 = -1;
+static gint ett_nfs_open_downgrade4 = -1;
+static gint ett_nfs_putfh4 = -1;
+static gint ett_nfs_putpubfh4 = -1;
+static gint ett_nfs_putrootfh4 = -1;
+static gint ett_nfs_read4 = -1;
+static gint ett_nfs_readdir4 = -1;
+static gint ett_nfs_readlink4 = -1;
+static gint ett_nfs_remove4 = -1;
+static gint ett_nfs_rename4 = -1;
+static gint ett_nfs_renew4 = -1;
+static gint ett_nfs_restorefh4 = -1;
+static gint ett_nfs_savefh4 = -1;
+static gint ett_nfs_secinfo4 = -1;
+static gint ett_nfs_setattr4 = -1;
+static gint ett_nfs_setclientid4 = -1;
+static gint ett_nfs_setclientid_confirm4 = -1;
+static gint ett_nfs_verify4 = -1;
+static gint ett_nfs_write4 = -1;
+static gint ett_nfs_release_lockowner4 = -1;
+static gint ett_nfs_illegal4 = -1;
+static gint ett_nfs_verifier4 = -1;
+static gint ett_nfs_opaque = -1;
+static gint ett_nfs_dirlist4 = -1;
+static gint ett_nfs_pathname4 = -1;
+static gint ett_nfs_change_info4 = -1;
+static gint ett_nfs_open_delegation4 = -1;
+static gint ett_nfs_open_claim4 = -1;
+static gint ett_nfs_opentype4 = -1;
+static gint ett_nfs_lock_owner4 = -1;
+static gint ett_nfs_cb_client4 = -1;
+static gint ett_nfs_client_id4 = -1;
+static gint ett_nfs_bitmap4 = -1;
+static gint ett_nfs_fattr4 = -1;
+static gint ett_nfs_fsid4 = -1;
+static gint ett_nfs_fs_locations4 = -1;
+static gint ett_nfs_fs_location4 = -1;
+static gint ett_nfs_open4_result_flags = -1;
+static gint ett_nfs_secinfo4_flavor_info = -1;
+static gint ett_nfs_stateid4 = -1;
+static gint ett_nfs_fattr4_fh_expire_type = -1;
+static gint ett_nfs_ace4 = -1;
+static gint ett_nfs_clientaddr4 = -1;
+static gint ett_nfs_aceflag4 = -1;
+static gint ett_nfs_acemask4 = -1;
+
+
+/* fhandle displayfilters to match also corresponding request/response
+ packet in addition to the one containing the actual filehandle */
+gboolean nfs_fhandle_reqrep_matching = FALSE;
+static GMemChunk *nfs_fhandle_data_chunk = NULL;
+static int nfs_fhandle_data_init_count = 100;
+static GHashTable *nfs_fhandle_data_table = NULL;
+GHashTable *nfs_fhandle_frame_table = NULL;
+
+static gint
+nfs_fhandle_data_equal(gconstpointer k1, gconstpointer k2)
+{
+ const nfs_fhandle_data_t *key1 = (const nfs_fhandle_data_t *)k1;
+ const nfs_fhandle_data_t *key2 = (const nfs_fhandle_data_t *)k2;
+
+ return (key1->len==key2->len)
+ &&(!memcmp(key1->fh, key2->fh, key1->len));
+}
+static guint
+nfs_fhandle_data_hash(gconstpointer k)
+{
+ const nfs_fhandle_data_t *key = (const nfs_fhandle_data_t *)k;
+ int i;
+ int hash;
+
+ hash=0;
+ for(i=0;i<key->len;i++)
+ hash ^= key->fh[i];
+
+ return hash;
+}
+static gboolean
+nfs_fhandle_data_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
+{
+ nfs_fhandle_data_t *nns = (nfs_fhandle_data_t *)value;
+
+ if(nns->fh){
+ tvb_free(nns->tvb);
+ nns->tvb=NULL;
+ g_free((gpointer)nns->fh);
+ nns->fh=NULL;
+ nns->len=0;
+ }
+
+ return TRUE;
+}
+static gint
+nfs_fhandle_frame_equal(gconstpointer k1, gconstpointer k2)
+{
+ guint32 key1 = (guint32)k1;
+ guint32 key2 = (guint32)k2;
+
+ return key1==key2;
+}
+static guint
+nfs_fhandle_frame_hash(gconstpointer k)
+{
+ guint32 key = (guint32)k;
+
+ return key;
+}
+static gboolean
+nfs_fhandle_frame_free_all(gpointer key_arg _U_, gpointer value _U_, gpointer user_data _U_)
+{
+ return TRUE;
+}
+static void
+nfs_fhandle_reqrep_matching_init(void)
+{
+ if (nfs_fhandle_frame_table != NULL) {
+ g_hash_table_foreach_remove(nfs_fhandle_frame_table,
+ nfs_fhandle_frame_free_all, NULL);
+ } else {
+ nfs_fhandle_frame_table=g_hash_table_new(nfs_fhandle_frame_hash,
+ nfs_fhandle_frame_equal);
+ }
+
+
+ if (nfs_fhandle_data_table != NULL) {
+ g_hash_table_foreach_remove(nfs_fhandle_data_table,
+ nfs_fhandle_data_free_all, NULL);
+ } else {
+ nfs_fhandle_data_table=g_hash_table_new(nfs_fhandle_data_hash,
+ nfs_fhandle_data_equal);
+ }
+
+ if(nfs_fhandle_data_chunk){
+ g_mem_chunk_destroy(nfs_fhandle_data_chunk);
+ nfs_fhandle_data_chunk = NULL;
+ }
+
+ if(nfs_fhandle_reqrep_matching){
+ nfs_fhandle_data_chunk = g_mem_chunk_new("nfs_fhandle_data_chunk",
+ sizeof(nfs_fhandle_data_t),
+ nfs_fhandle_data_init_count * sizeof(nfs_fhandle_data_t),
+ G_ALLOC_ONLY);
+ }
+
+}
+
+
+/* file name snooping */
+gboolean nfs_file_name_snooping = FALSE;
+gboolean nfs_file_name_full_snooping = FALSE;
+typedef struct nfs_name_snoop {
+ int fh_length;
+ unsigned char *fh;
+ int name_len;
+ unsigned char *name;
+ int parent_len;
+ unsigned char *parent;
+ int full_name_len;
+ unsigned char *full_name;
+} nfs_name_snoop_t;
+
+typedef struct nfs_name_snoop_key {
+ int key;
+ int fh_length;
+ const unsigned char *fh;
+} nfs_name_snoop_key_t;
+
+static GMemChunk *nfs_name_snoop_chunk = NULL;
+static int nfs_name_snoop_init_count = 100;
+static GHashTable *nfs_name_snoop_unmatched = NULL;
+
+static GMemChunk *nfs_name_snoop_key_chunk = NULL;
+static int nfs_name_snoop_key_init_count = 100;
+static GHashTable *nfs_name_snoop_matched = NULL;
+
+static GHashTable *nfs_name_snoop_known = NULL;
+
+static gint
+nfs_name_snoop_matched_equal(gconstpointer k1, gconstpointer k2)
+{
+ const nfs_name_snoop_key_t *key1 = (const nfs_name_snoop_key_t *)k1;
+ const nfs_name_snoop_key_t *key2 = (const nfs_name_snoop_key_t *)k2;
+
+ return (key1->key==key2->key)
+ &&(key1->fh_length==key2->fh_length)
+ &&(!memcmp(key1->fh, key2->fh, key1->fh_length));
+}
+static guint
+nfs_name_snoop_matched_hash(gconstpointer k)
+{
+ const nfs_name_snoop_key_t *key = (const nfs_name_snoop_key_t *)k;
+ int i;
+ guint hash;
+
+ hash=key->key;
+ for(i=0;i<key->fh_length;i++)
+ hash ^= key->fh[i];
+
+ return hash;
+}
+static gint
+nfs_name_snoop_unmatched_equal(gconstpointer k1, gconstpointer k2)
+{
+ guint32 key1 = (guint32)k1;
+ guint32 key2 = (guint32)k2;
+
+ return key1==key2;
+}
+static guint
+nfs_name_snoop_unmatched_hash(gconstpointer k)
+{
+ guint32 key = (guint32)k;
+
+ return key;
+}
+static gboolean
+nfs_name_snoop_unmatched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
+{
+ nfs_name_snoop_t *nns = (nfs_name_snoop_t *)value;
+
+ if(nns->name){
+ g_free((gpointer)nns->name);
+ nns->name=NULL;
+ nns->name_len=0;
+ }
+ if(nns->full_name){
+ g_free((gpointer)nns->full_name);
+ nns->full_name=NULL;
+ nns->full_name_len=0;
+ }
+ if(nns->parent){
+ g_free((gpointer)nns->parent);
+ nns->parent=NULL;
+ nns->parent_len=0;
+ }
+ if(nns->fh){
+ g_free((gpointer)nns->fh);
+ nns->fh=NULL;
+ nns->fh_length=0;
+ }
+ return TRUE;
+}
+
+static void
+nfs_name_snoop_init(void)
+{
+ if (nfs_name_snoop_unmatched != NULL) {
+ g_hash_table_foreach_remove(nfs_name_snoop_unmatched,
+ nfs_name_snoop_unmatched_free_all, NULL);
+ } else {
+ /* The fragment table does not exist. Create it */
+ nfs_name_snoop_unmatched=g_hash_table_new(nfs_name_snoop_unmatched_hash,
+ nfs_name_snoop_unmatched_equal);
+ }
+ if (nfs_name_snoop_matched != NULL) {
+ g_hash_table_foreach_remove(nfs_name_snoop_matched,
+ nfs_name_snoop_unmatched_free_all, NULL);
+ } else {
+ /* The fragment table does not exist. Create it */
+ nfs_name_snoop_matched=g_hash_table_new(nfs_name_snoop_matched_hash,
+ nfs_name_snoop_matched_equal);
+ }
+ if (nfs_name_snoop_known != NULL) {
+ g_hash_table_foreach_remove(nfs_name_snoop_known,
+ nfs_name_snoop_unmatched_free_all, NULL);
+ } else {
+ /* The fragment table does not exist. Create it */
+ nfs_name_snoop_known=g_hash_table_new(nfs_name_snoop_matched_hash,
+ nfs_name_snoop_matched_equal);
+ }
+
+ if(nfs_name_snoop_chunk){
+ g_mem_chunk_destroy(nfs_name_snoop_chunk);
+ nfs_name_snoop_chunk = NULL;
+ }
+ if(nfs_name_snoop_key_chunk){
+ g_mem_chunk_destroy(nfs_name_snoop_key_chunk);
+ nfs_name_snoop_key_chunk = NULL;
+ }
+
+ if(nfs_file_name_snooping){
+ nfs_name_snoop_chunk = g_mem_chunk_new("nfs_name_snoop_chunk",
+ sizeof(nfs_name_snoop_t),
+ nfs_name_snoop_init_count * sizeof(nfs_name_snoop_t),
+ G_ALLOC_ONLY);
+ nfs_name_snoop_key_chunk = g_mem_chunk_new("nfs_name_snoop_key_chunk",
+ sizeof(nfs_name_snoop_key_t),
+ nfs_name_snoop_key_init_count * sizeof(nfs_name_snoop_key_t),
+ G_ALLOC_ONLY);
+ }
+
+}
+
+void
+nfs_name_snoop_add_name(int xid, tvbuff_t *tvb, int name_offset, int name_len, int parent_offset, int parent_len, unsigned char *name)
+{
+ nfs_name_snoop_t *nns, *old_nns;
+ const unsigned char *ptr=NULL;
+
+ /* filter out all '.' and '..' names */
+ if(!name){
+ ptr=(const unsigned char *)tvb_get_ptr(tvb, name_offset, name_len);
+ if(ptr[0]=='.'){
+ if(ptr[1]==0){
+ return;
+ }
+ if(ptr[1]=='.'){
+ if(ptr[2]==0){
+ return;
+ }
+ }
+ }
+ }
+
+ nns=g_mem_chunk_alloc(nfs_name_snoop_chunk);
+
+ nns->fh_length=0;
+ nns->fh=NULL;
+
+ if(parent_len){
+ nns->parent_len=parent_len;
+ nns->parent=tvb_memdup(tvb, parent_offset, parent_len);
+ } else {
+ nns->parent_len=0;
+ nns->parent=NULL;
+ }
+
+ nns->name_len=name_len;
+ if(name){
+ nns->name=name;
+ } else {
+ nns->name=g_malloc(name_len+1);
+ memcpy(nns->name, ptr, name_len);
+ }
+ nns->name[name_len]=0;
+
+ nns->full_name_len=0;
+ nns->full_name=NULL;
+
+ /* remove any old entry for this */
+ old_nns=g_hash_table_lookup(nfs_name_snoop_unmatched, (gconstpointer)xid);
+ if(old_nns){
+ /* if we haven't seen the reply yet, then there are no
+ matched entries for it, thus we can dealloc the arrays*/
+ if(!old_nns->fh){
+ g_free(old_nns->name);
+ old_nns->name=NULL;
+ old_nns->name_len=0;
+
+ g_free(old_nns->parent);
+ old_nns->parent=NULL;
+ old_nns->parent_len=0;
+
+ g_mem_chunk_free(nfs_name_snoop_chunk, old_nns);
+ }
+ g_hash_table_remove(nfs_name_snoop_unmatched, (gconstpointer)xid);
+ }
+
+ g_hash_table_insert(nfs_name_snoop_unmatched, (gpointer)xid, nns);
+}
+
+static void
+nfs_name_snoop_add_fh(int xid, tvbuff_t *tvb, int fh_offset, int fh_length)
+{
+ unsigned char *fh;
+ nfs_name_snoop_t *nns, *old_nns;
+ nfs_name_snoop_key_t *key;
+
+ /* find which request we correspond to */
+ nns=g_hash_table_lookup(nfs_name_snoop_unmatched, (gconstpointer)xid);
+ if(!nns){
+ /* oops couldnt find matching request, bail out */
+ return;
+ }
+
+ /* if we have already seen this response earlier */
+ if(nns->fh){
+ return;
+ }
+
+ /* oki, we have a new entry */
+ fh=tvb_memdup(tvb, fh_offset, fh_length);
+ nns->fh=fh;
+ nns->fh_length=fh_length;
+
+ key=g_mem_chunk_alloc(nfs_name_snoop_key_chunk);
+ key->key=0;
+ key->fh_length=nns->fh_length;
+ key->fh =nns->fh;
+
+ /* already have something matched for this fh, remove it from
+ the table */
+ old_nns=g_hash_table_lookup(nfs_name_snoop_matched, key);
+ if(old_nns){
+ g_hash_table_remove(nfs_name_snoop_matched, key);
+ }
+
+ g_hash_table_remove(nfs_name_snoop_unmatched, (gconstpointer)xid);
+ g_hash_table_insert(nfs_name_snoop_matched, key, nns);
+}
+
+static void
+nfs_full_name_snoop(nfs_name_snoop_t *nns, int *len, unsigned char **name, unsigned char **pos)
+{
+ nfs_name_snoop_t *parent_nns = NULL;
+ nfs_name_snoop_key_t key;
+
+ /* check if the nns component ends with a '/' else we just allocate
+ an extra byte to len to accommodate for it later */
+ if(nns->name[nns->name_len-1]!='/'){
+ (*len)++;
+ }
+
+ (*len) += nns->name_len;
+
+ if(nns->parent==NULL){
+ *name = g_malloc((*len)+1);
+ *pos = *name;
+
+ strcpy(*pos, nns->name);
+ *pos += nns->name_len;
+ return;
+ }
+
+ key.key=0;
+ key.fh_length=nns->parent_len;
+ key.fh=nns->parent;
+
+ parent_nns=g_hash_table_lookup(nfs_name_snoop_matched, &key);
+
+ if(parent_nns){
+ nfs_full_name_snoop(parent_nns, len, name, pos);
+ if(*name){
+ /* make sure components are '/' separated */
+ if( (*pos)[-1] != '/'){
+ **pos='/';
+ (*pos)++;
+ **pos=0;
+ }
+ strcpy(*pos, nns->name);
+ *pos += nns->name_len;
+ }
+ return;
+ }
+
+ return;
+}
+
+static void
+nfs_name_snoop_fh(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int fh_offset, int fh_length, gboolean hidden)
+{
+ nfs_name_snoop_key_t key;
+ nfs_name_snoop_t *nns = NULL;
+
+ /* if this is a new packet, see if we can register the mapping */
+ if(!pinfo->fd->flags.visited){
+ key.key=0;
+ key.fh_length=fh_length;
+ key.fh=(const unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
+
+ nns=g_hash_table_lookup(nfs_name_snoop_matched, &key);
+ if(nns){
+ nfs_name_snoop_key_t *k;
+ k=g_mem_chunk_alloc(nfs_name_snoop_key_chunk);
+ k->key=pinfo->fd->num;
+ k->fh_length=nns->fh_length;
+ k->fh=nns->fh;
+ g_hash_table_insert(nfs_name_snoop_known, k, nns);
+
+ if(nfs_file_name_full_snooping){
+ unsigned char *name=NULL, *pos=NULL;
+ int len=0;
+
+ nfs_full_name_snoop(nns, &len, &name, &pos);
+ if(name){
+ nns->full_name=name;
+ nns->full_name_len=len;
+ }
+ }
+ }
+ }
+
+ /* see if we know this mapping */
+ if(!nns){
+ key.key=pinfo->fd->num;
+ key.fh_length=fh_length;
+ key.fh=(const unsigned char *)tvb_get_ptr(tvb, fh_offset, fh_length);
+
+ nns=g_hash_table_lookup(nfs_name_snoop_known, &key);
+ }
+
+ /* if we know the mapping, print the filename */
+ if(nns){
+ if(hidden){
+ proto_tree_add_string_hidden(tree, hf_nfs_name, tvb,
+ fh_offset, 0, nns->name);
+ }else {
+ proto_tree_add_string_format(tree, hf_nfs_name, tvb,
+ fh_offset, 0, nns->name, "Name: %s", nns->name);
+ }
+ if(nns->full_name){
+ if(hidden){
+ proto_tree_add_string_hidden(tree, hf_nfs_full_name, tvb,
+ fh_offset, 0, nns->name);
+ } else {
+ proto_tree_add_string_format(tree, hf_nfs_full_name, tvb,
+ fh_offset, 0, nns->name, "Full Name: %s", nns->full_name);
+ }
+ }
+ }
+}
+
+/* file handle dissection */
+
+#define FHT_UNKNOWN 0
+#define FHT_SVR4 1
+#define FHT_LINUX_KNFSD_LE 2
+#define FHT_LINUX_NFSD_LE 3
+#define FHT_LINUX_KNFSD_NEW 4
+#define FHT_NETAPP 5
+
+static const value_string names_fhtype[] =
+{
+ { FHT_UNKNOWN, "unknown" },
+ { FHT_SVR4, "System V R4" },
+ { FHT_LINUX_KNFSD_LE, "Linux knfsd (little-endian)" },
+ { FHT_LINUX_NFSD_LE, "Linux user-land nfsd (little-endian)" },
+ { FHT_LINUX_KNFSD_NEW, "Linux knfsd (new)" },
+ { FHT_NETAPP, "NetApp file handle" },
+ { 0, NULL }
+};
+
+
+/* SVR4: checked with ReliantUNIX (5.43, 5.44, 5.45) */
+
+static void
+dissect_fhandle_data_SVR4(tvbuff_t* tvb, int offset, proto_tree *tree,
+ int fhlen _U_)
+{
+ guint32 nof = offset;
+
+ /* file system id */
+ {
+ guint32 fsid_O;
+ guint32 fsid_L;
+ guint32 temp;
+ guint32 fsid_major;
+ guint32 fsid_minor;
+
+ fsid_O = nof;
+ fsid_L = 4;
+ temp = tvb_get_ntohl(tvb, fsid_O);
+ fsid_major = ( temp>>18 ) & 0x3fff; /* 14 bits */
+ fsid_minor = ( temp ) & 0x3ffff; /* 18 bits */
+ if (tree) {
+ proto_item* fsid_item = NULL;
+ proto_tree* fsid_tree = NULL;
+
+ fsid_item = proto_tree_add_text(tree, tvb,
+ fsid_O, fsid_L,
+ "file system ID: %d,%d", fsid_major, fsid_minor);
+ if (fsid_item) {
+ fsid_tree = proto_item_add_subtree(fsid_item,
+ ett_nfs_fh_fsid);
+ proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
+ tvb, fsid_O, 2, fsid_major);
+ proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
+ tvb, fsid_O+1, 3, fsid_minor);
+ }
+ }
+ nof = fsid_O + fsid_L;
+ }
+
+ /* file system type */
+ {
+ guint32 fstype_O;
+ guint32 fstype_L;
+ guint32 fstype;
+
+ fstype_O = nof;
+ fstype_L = 4;
+ fstype = tvb_get_ntohl(tvb, fstype_O);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_fh_fstype, tvb,
+ fstype_O, fstype_L, fstype);
+ }
+ nof = fstype_O + fstype_L;
+ }
+
+ /* file number */
+ {
+ guint32 fn_O;
+ guint32 fn_len_O;
+ guint32 fn_len_L;
+ guint32 fn_len;
+ guint32 fn_data_O;
+ guint32 fn_data_inode_O;
+ guint32 fn_data_inode_L;
+ guint32 inode;
+ guint32 fn_data_gen_O;
+ guint32 fn_data_gen_L;
+ guint32 gen;
+ guint32 fn_L;
+
+ fn_O = nof;
+ fn_len_O = fn_O;
+ fn_len_L = 2;
+ fn_len = tvb_get_ntohs(tvb, fn_len_O);
+ fn_data_O = fn_O + fn_len_L;
+ fn_data_inode_O = fn_data_O + 2;
+ fn_data_inode_L = 4;
+ inode = tvb_get_ntohl(tvb, fn_data_inode_O);
+ fn_data_gen_O = fn_data_inode_O + fn_data_inode_L;
+ fn_data_gen_L = 4;
+ gen = tvb_get_ntohl(tvb, fn_data_gen_O);
+ fn_L = fn_len_L + fn_len;
+ if (tree) {
+ proto_item* fn_item = NULL;
+ proto_tree* fn_tree = NULL;
+
+ fn_item = proto_tree_add_uint(tree, hf_nfs_fh_fn, tvb,
+ fn_O, fn_L, inode);
+ if (fn_item) {
+ fn_tree = proto_item_add_subtree(fn_item,
+ ett_nfs_fh_fn);
+ proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_len,
+ tvb, fn_len_O, fn_len_L, fn_len);
+ proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_inode,
+ tvb, fn_data_inode_O, fn_data_inode_L, inode);
+ proto_tree_add_uint(fn_tree, hf_nfs_fh_fn_generation,
+ tvb, fn_data_gen_O, fn_data_gen_L, gen);
+ }
+ }
+ nof = fn_O + fn_len_L + fn_len;
+ }
+
+ /* exported file number */
+ {
+ guint32 xfn_O;
+ guint32 xfn_len_O;
+ guint32 xfn_len_L;
+ guint32 xfn_len;
+ guint32 xfn_data_O;
+ guint32 xfn_data_inode_O;
+ guint32 xfn_data_inode_L;
+ guint32 xinode;
+ guint32 xfn_data_gen_O;
+ guint32 xfn_data_gen_L;
+ guint32 xgen;
+ guint32 xfn_L;
+
+ xfn_O = nof;
+ xfn_len_O = xfn_O;
+ xfn_len_L = 2;
+ xfn_len = tvb_get_ntohs(tvb, xfn_len_O);
+ xfn_data_O = xfn_O + xfn_len_L;
+ xfn_data_inode_O = xfn_data_O + 2;
+ xfn_data_inode_L = 4;
+ xinode = tvb_get_ntohl(tvb, xfn_data_inode_O);
+ xfn_data_gen_O = xfn_data_inode_O + xfn_data_inode_L;
+ xfn_data_gen_L = 4;
+ xgen = tvb_get_ntohl(tvb, xfn_data_gen_O);
+ xfn_L = xfn_len_L + xfn_len;
+ if (tree) {
+ proto_item* xfn_item = NULL;
+ proto_tree* xfn_tree = NULL;
+
+ xfn_item = proto_tree_add_uint(tree, hf_nfs_fh_xfn, tvb,
+ xfn_O, xfn_L, xinode);
+ if (xfn_item) {
+ xfn_tree = proto_item_add_subtree(xfn_item,
+ ett_nfs_fh_xfn);
+ proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_len,
+ tvb, xfn_len_O, xfn_len_L, xfn_len);
+ proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_inode,
+ tvb, xfn_data_inode_O, xfn_data_inode_L, xinode);
+ proto_tree_add_uint(xfn_tree, hf_nfs_fh_xfn_generation,
+ tvb, xfn_data_gen_O, xfn_data_gen_L, xgen);
+ }
+ }
+ }
+}
+
+
+/* Checked with RedHat Linux 6.2 (kernel 2.2.14 knfsd) */
+
+static void
+dissect_fhandle_data_LINUX_KNFSD_LE(tvbuff_t* tvb, int offset, proto_tree *tree,
+ int fhlen _U_)
+{
+ guint32 dentry;
+ guint32 inode;
+ guint32 dirinode;
+ guint32 temp;
+ guint32 fsid_major;
+ guint32 fsid_minor;
+ guint32 xfsid_major;
+ guint32 xfsid_minor;
+ guint32 xinode;
+ guint32 gen;
+
+ dentry = tvb_get_letohl(tvb, offset+0);
+ inode = tvb_get_letohl(tvb, offset+4);
+ dirinode = tvb_get_letohl(tvb, offset+8);
+ temp = tvb_get_letohs (tvb,offset+12);
+ fsid_major = (temp >> 8) & 0xff;
+ fsid_minor = (temp ) & 0xff;
+ temp = tvb_get_letohs(tvb,offset+16);
+ xfsid_major = (temp >> 8) & 0xff;
+ xfsid_minor = (temp ) & 0xff;
+ xinode = tvb_get_letohl(tvb,offset+20);
+ gen = tvb_get_letohl(tvb,offset+24);
+
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_fh_dentry,
+ tvb, offset+0, 4, dentry);
+ proto_tree_add_uint(tree, hf_nfs_fh_fn_inode,
+ tvb, offset+4, 4, inode);
+ proto_tree_add_uint(tree, hf_nfs_fh_dirinode,
+ tvb, offset+8, 4, dirinode);
+
+ /* file system id (device) */
+ {
+ proto_item* fsid_item = NULL;
+ proto_tree* fsid_tree = NULL;
+
+ fsid_item = proto_tree_add_text(tree, tvb,
+ offset+12, 4,
+ "file system ID: %d,%d", fsid_major, fsid_minor);
+ if (fsid_item) {
+ fsid_tree = proto_item_add_subtree(fsid_item,
+ ett_nfs_fh_fsid);
+ proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
+ tvb, offset+13, 1, fsid_major);
+ proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
+ tvb, offset+12, 1, fsid_minor);
+ }
+ }
+
+ /* exported file system id (device) */
+ {
+ proto_item* xfsid_item = NULL;
+ proto_tree* xfsid_tree = NULL;
+
+ xfsid_item = proto_tree_add_text(tree, tvb,
+ offset+16, 4,
+ "exported file system ID: %d,%d", xfsid_major, xfsid_minor);
+ if (xfsid_item) {
+ xfsid_tree = proto_item_add_subtree(xfsid_item,
+ ett_nfs_fh_xfsid);
+ proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_major,
+ tvb, offset+17, 1, xfsid_major);
+ proto_tree_add_uint(xfsid_tree, hf_nfs_fh_xfsid_minor,
+ tvb, offset+16, 1, xfsid_minor);
+ }
+ }
+
+ proto_tree_add_uint(tree, hf_nfs_fh_xfn_inode,
+ tvb, offset+20, 4, xinode);
+ proto_tree_add_uint(tree, hf_nfs_fh_fn_generation,
+ tvb, offset+24, 4, gen);
+ }
+}
+
+
+/* Checked with RedHat Linux 5.2 (nfs-server 2.2beta47 user-land nfsd) */
+
+static void
+dissect_fhandle_data_LINUX_NFSD_LE(tvbuff_t* tvb, int offset, proto_tree *tree,
+ int fhlen _U_)
+{
+ /* pseudo inode */
+ {
+ guint32 pinode;
+ pinode = tvb_get_letohl(tvb, offset+0);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_fh_pinode,
+ tvb, offset+0, 4, pinode);
+ }
+ }
+
+ /* hash path */
+ {
+ guint32 hashlen;
+
+ hashlen = tvb_get_guint8(tvb, offset+4);
+ if (tree) {
+ proto_item* hash_item = NULL;
+ proto_tree* hash_tree = NULL;
+
+ hash_item = proto_tree_add_text(tree, tvb, offset+4,
+ hashlen + 1,
+ "hash path: %s",
+ tvb_bytes_to_str(tvb,offset+5,hashlen));
+ if (hash_item) {
+ hash_tree = proto_item_add_subtree(hash_item,
+ ett_nfs_fh_hp);
+ if (hash_tree) {
+ proto_tree_add_uint(hash_tree,
+ hf_nfs_fh_hp_len, tvb, offset+4, 1,
+ hashlen);
+ proto_tree_add_text(hash_tree, tvb, offset+5,
+ hashlen,
+ "key: %s",
+ tvb_bytes_to_str(tvb,offset+5,hashlen));
+ }
+ }
+ }
+ }
+}
+
+
+/* Checked with SuSE 7.1 (kernel 2.4.0 knfsd) */
+/* read linux-2.4.5/include/linux/nfsd/nfsfh.h for more details */
+
+#define AUTH_TYPE_NONE 0
+static const value_string auth_type_names[] = {
+ { AUTH_TYPE_NONE, "no authentication" },
+ {0,NULL}
+};
+
+#define FSID_TYPE_MAJOR_MINOR_INODE 0
+static const value_string fsid_type_names[] = {
+ { FSID_TYPE_MAJOR_MINOR_INODE, "major/minor/inode" },
+ {0,NULL}
+};
+
+#define FILEID_TYPE_ROOT 0
+#define FILEID_TYPE_INODE_GENERATION 1
+#define FILEID_TYPE_INODE_GENERATION_PARENT 2
+static const value_string fileid_type_names[] = {
+ { FILEID_TYPE_ROOT, "root" },
+ { FILEID_TYPE_INODE_GENERATION, "inode/generation" },
+ { FILEID_TYPE_INODE_GENERATION_PARENT, "inode/generation/parent" },
+ {0,NULL}
+};
+
+static void
+dissect_fhandle_data_NETAPP(tvbuff_t* tvb, int offset, proto_tree *tree,
+ int fhlen _U_)
+{
+ if (tree) {
+ guint32 mount = tvb_get_letohl(tvb, offset + 0);
+ guint32 mount_gen = tvb_get_letohl(tvb, offset + 4);
+ guint16 flags = tvb_get_letohs(tvb, offset + 8);
+ guint8 snapid = tvb_get_guint8(tvb, offset + 10);
+ guint8 unused = tvb_get_guint8(tvb, offset + 11);
+ guint32 inum = tvb_get_ntohl(tvb, offset + 12);
+ guint32 generation = tvb_get_letohl(tvb, offset + 16);
+ guint32 fsid = tvb_get_letohl(tvb, offset + 20);
+ guint32 export = tvb_get_letohl(tvb, offset + 24);
+ guint32 export_snapgen = tvb_get_letohl(tvb, offset + 28);
+ proto_item *item;
+ proto_tree *subtree;
+ char flag_string[128] = "";
+ char *strings[] = { " MNT_PNT", " SNAPDIR", " SNAPDIR_ENT",
+ " EMPTY", " VBN_ACCESS", " MULTIVOLUME",
+ " METADATA" };
+ guint16 bit = sizeof(strings) / sizeof(strings[0]);
+ while (bit--)
+ if (flags & (1<<bit))
+ strcat(flag_string, strings[bit]);
+ item = proto_tree_add_text(tree, tvb, offset + 0, 8,
+ "mount (inode %u)", mount);
+ subtree = proto_item_add_subtree(item, ett_nfs_fh_mount);
+ item = proto_tree_add_uint(subtree, hf_nfs_fh_mount_fileid,
+ tvb, offset + 0, 4, mount);
+ item = proto_tree_add_uint(subtree, hf_nfs_fh_mount_generation,
+ tvb, offset + 4, 4, mount_gen);
+ item = proto_tree_add_text(tree, tvb, offset + 8, 16,
+ "file (inode %u)", inum);
+ subtree = proto_item_add_subtree(item, ett_nfs_fh_file);
+ item = proto_tree_add_uint_format(subtree, hf_nfs_fh_flags,
+ tvb, offset + 8, 2, flags,
+ "Flags: %#02x%s", flags,
+ flag_string);
+ item = proto_tree_add_uint(subtree, hf_nfs_fh_snapid, tvb,
+ offset + 10, 1, snapid);
+ item = proto_tree_add_uint(subtree, hf_nfs_fh_unused, tvb,
+ offset + 11, 1, unused);
+ item = proto_tree_add_uint(subtree, hf_nfs_fh_fileid, tvb,
+ offset + 12, 4, inum);
+ item = proto_tree_add_uint(subtree, hf_nfs_fh_generation, tvb,
+ offset + 16, 4, generation);
+ item = proto_tree_add_uint(subtree, hf_nfs_fh_fsid, tvb,
+ offset + 20, 4, fsid);
+ item = proto_tree_add_text(tree, tvb, offset + 24, 8,
+ "export (inode %u)", export);
+ subtree = proto_item_add_subtree(item, ett_nfs_fh_export);
+ item = proto_tree_add_uint(subtree, hf_nfs_fh_export_fileid,
+ tvb, offset + 24, 4, export);
+ item = proto_tree_add_uint(subtree,
+ hf_nfs_fh_export_generation,
+ tvb, offset + 28, 3,
+ export_snapgen & 0xffffff);
+ item = proto_tree_add_uint(subtree, hf_nfs_fh_export_snapid,
+ tvb, offset + 31, 1,
+ export_snapgen >> 24);
+ }
+}
+
+static void
+dissect_fhandle_data_LINUX_KNFSD_NEW(tvbuff_t* tvb, int offset, proto_tree *tree,
+ int fhlen _U_)
+{
+ guint8 version;
+ guint8 auth_type;
+ guint8 fsid_type;
+ guint8 fileid_type;
+
+ version = tvb_get_guint8(tvb, offset + 0);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_fh_version,
+ tvb, offset+0, 1, version);
+ }
+
+ switch (version) {
+ case 1: {
+ auth_type = tvb_get_guint8(tvb, offset + 1);
+ fsid_type = tvb_get_guint8(tvb, offset + 2);
+ fileid_type = tvb_get_guint8(tvb, offset + 3);
+ if (tree) {
+ proto_item* encoding_item = proto_tree_add_text(tree, tvb,
+ offset + 1, 3,
+ "encoding: %u %u %u",
+ auth_type, fsid_type, fileid_type);
+ if (encoding_item) {
+ proto_tree* encoding_tree = proto_item_add_subtree(encoding_item,
+ ett_nfs_fh_encoding);
+ if (encoding_tree) {
+ proto_tree_add_uint(encoding_tree, hf_nfs_fh_auth_type,
+ tvb, offset+1, 1, auth_type);
+ proto_tree_add_uint(encoding_tree, hf_nfs_fh_fsid_type,
+ tvb, offset+2, 1, fsid_type);
+ proto_tree_add_uint(encoding_tree, hf_nfs_fh_fileid_type,
+ tvb, offset+3, 1, fileid_type);
+ }
+ }
+ }
+ offset += 4;
+ } break;
+ default: {
+ /* unknown version */
+ goto out;
+ }
+ }
+
+ switch (auth_type) {
+ case 0: {
+ /* no authentication */
+ if (tree) {
+ proto_tree_add_text(tree, tvb,
+ offset + 0, 0,
+ "authentication: none");
+ }
+ } break;
+ default: {
+ /* unknown authentication type */
+ goto out;
+ }
+ }
+
+ switch (fsid_type) {
+ case 0: {
+ guint16 fsid_major;
+ guint16 fsid_minor;
+ guint32 fsid_inode;
+
+ fsid_major = tvb_get_ntohs(tvb, offset + 0);
+ fsid_minor = tvb_get_ntohs(tvb, offset + 2);
+ fsid_inode = tvb_get_letohl(tvb, offset + 4);
+ if (tree) {
+ proto_item* fsid_item = proto_tree_add_text(tree, tvb,
+ offset+0, 8,
+ "file system ID: %u,%u (inode %u)",
+ fsid_major, fsid_minor, fsid_inode);
+ if (fsid_item) {
+ proto_tree* fsid_tree = proto_item_add_subtree(fsid_item,
+ ett_nfs_fh_fsid);
+ if (fsid_tree) {
+ proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_major,
+ tvb, offset+0, 2, fsid_major);
+ proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_minor,
+ tvb, offset+2, 2, fsid_minor);
+ proto_tree_add_uint(fsid_tree, hf_nfs_fh_fsid_inode,
+ tvb, offset+4, 4, fsid_inode);
+ }
+ }
+ }
+ offset += 8;
+ } break;
+ default: {
+ /* unknown fsid type */
+ goto out;
+ }
+ }
+
+ switch (fileid_type) {
+ case 0: {
+ if (tree) {
+ proto_tree_add_text(tree, tvb,
+ offset+0, 0,
+ "file ID: root inode");
+ }
+ } break;
+ case 1: {
+ guint32 inode;
+ guint32 generation;
+
+ inode = tvb_get_letohl(tvb, offset + 0);
+ generation = tvb_get_letohl(tvb, offset + 4);
+
+ if (tree) {
+ proto_item* fileid_item = proto_tree_add_text(tree, tvb,
+ offset+0, 8,
+ "file ID: %u (%u)",
+ inode, generation);
+ if (fileid_item) {
+ proto_tree* fileid_tree = proto_item_add_subtree(
+ fileid_item, ett_nfs_fh_fn);
+ if (fileid_tree) {
+ proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
+ tvb, offset+0, 4, inode);
+ proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
+ tvb, offset+4, 4, generation);
+ }
+ }
+ }
+
+ offset += 8;
+ } break;
+ case 2: {
+ guint32 inode;
+ guint32 generation;
+ guint32 parent_inode;
+
+ inode = tvb_get_letohl(tvb, offset + 0);
+ generation = tvb_get_letohl(tvb, offset + 4);
+ parent_inode = tvb_get_letohl(tvb, offset + 8);
+
+ if (tree) {
+ proto_item* fileid_item = proto_tree_add_text(tree, tvb,
+ offset+0, 8,
+ "file ID: %u (%u)",
+ inode, generation);
+ if (fileid_item) {
+ proto_tree* fileid_tree = proto_item_add_subtree(
+ fileid_item, ett_nfs_fh_fn);
+ if (fileid_tree) {
+ proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_inode,
+ tvb, offset+0, 4, inode);
+ proto_tree_add_uint(fileid_tree, hf_nfs_fh_fn_generation,
+ tvb, offset+4, 4, generation);
+ proto_tree_add_uint(fileid_tree, hf_nfs_fh_dirinode,
+ tvb, offset+8, 4, parent_inode);
+ }
+ }
+ }
+
+ offset += 12;
+ } break;
+ default: {
+ /* unknown fileid type */
+ goto out;
+ }
+ }
+
+out:
+ ;
+}
+
+
+static void
+dissect_fhandle_data_unknown(tvbuff_t *tvb, int offset, proto_tree *tree,
+ guint fhlen)
+{
+ guint sublen;
+ guint bytes_left;
+ gboolean first_line;
+
+ bytes_left = fhlen;
+ first_line = TRUE;
+ while (bytes_left != 0) {
+ sublen = 16;
+ if (sublen > bytes_left)
+ sublen = bytes_left;
+ proto_tree_add_text(tree, tvb, offset, sublen,
+ "%s%s",
+ first_line ? "data: " :
+ " ",
+ tvb_bytes_to_str(tvb,offset,sublen));
+ bytes_left -= sublen;
+ offset += sublen;
+ first_line = FALSE;
+ }
+}
+
+
+static void
+dissect_fhandle_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, unsigned int fhlen, gboolean hidden, guint32 *hash)
+{
+ unsigned int fhtype = FHT_UNKNOWN;
+
+ /* filehandle too long */
+ if (fhlen>64) goto type_ready;
+ /* Not all bytes there. Any attempt to deduce the type would be
+ senseless. */
+ if (!tvb_bytes_exist(tvb,offset,fhlen)) goto type_ready;
+
+ /* this is to set up fhandle display filters to find both packets
+ of an RPC call */
+ if(nfs_fhandle_reqrep_matching && (!hidden) ){
+ nfs_fhandle_data_t *old_fhd=NULL;
+ unsigned char *fh;
+
+ if( !pinfo->fd->flags.visited ){
+ nfs_fhandle_data_t fhd;
+
+ /* first check if we have seen this fhandle before */
+ fhd.len=fhlen;
+ fhd.fh=(const unsigned char *)tvb_get_ptr(tvb, offset, fhlen);
+ old_fhd=g_hash_table_lookup(nfs_fhandle_data_table,
+ (gconstpointer)&fhd);
+ if(!old_fhd){
+ /* oh, a new fhandle, alloc struct and store it in the table*/
+ old_fhd=g_mem_chunk_alloc(nfs_fhandle_data_chunk);
+ old_fhd->len=fhlen;
+ fh=g_malloc(fhlen);
+ memcpy(fh, fhd.fh, fhlen);
+ old_fhd->fh=fh;
+ old_fhd->tvb=tvb_new_real_data(old_fhd->fh, old_fhd->len, old_fhd->len);
+ g_hash_table_insert(nfs_fhandle_data_table,
+ (gpointer)old_fhd, (gpointer)old_fhd);
+ }
+
+ /* XXX here we should really check that we havent stored
+ this fhandle for this frame number already.
+ We should also make sure we can handle when we have multiple
+ fhandles seen for the same frame, which WILL happen for certain
+ nfs calls. For now, we dont handle this and those calls will
+ not work properly with this feature
+ */
+ g_hash_table_insert(nfs_fhandle_frame_table,
+ (gpointer)pinfo->fd->num,
+ (gpointer)old_fhd);
+ }
+ }
+
+ /* create a semiunique hash value for the filehandle */
+ {
+ guint32 fhhash;
+ guint32 i;
+
+ for(fhhash=0,i=0;i<(fhlen-3);i+=4){
+ guint32 val;
+ val = tvb_get_ntohl(tvb, offset+i);
+ fhhash ^= val;
+ fhhash += val;
+ }
+ if(hidden){
+ proto_tree_add_uint_hidden(tree, hf_nfs_fh_hash, tvb, offset,
+ fhlen, fhhash);
+ } else {
+ proto_tree_add_uint(tree, hf_nfs_fh_hash, tvb, offset,
+ fhlen, fhhash);
+ }
+ if(hash){
+ *hash=fhhash;
+ }
+ }
+ if(nfs_file_name_snooping){
+ nfs_name_snoop_fh(pinfo, tree, tvb, offset, fhlen, hidden);
+ }
+
+ if(!hidden){
+ /* calculate (heuristically) fhtype */
+ switch (fhlen) {
+ case 12:
+ if (tvb_get_ntohl(tvb,offset) == 0x01000000) {
+ fhtype=FHT_LINUX_KNFSD_NEW;
+ }
+ break;
+ case 20:
+ if (tvb_get_ntohl(tvb,offset) == 0x01000001) {
+ fhtype=FHT_LINUX_KNFSD_NEW;
+ }
+ break;
+ case 24:
+ if (tvb_get_ntohl(tvb,offset) == 0x01000002) {
+ fhtype=FHT_LINUX_KNFSD_NEW;
+ }
+ break;
+ case 32: {
+ guint32 len1;
+ guint32 len2;
+ if (tvb_get_ntohs(tvb,offset+4) == 0) {
+ len1=tvb_get_ntohs(tvb,offset+8);
+ if (tvb_bytes_exist(tvb,offset+10+len1,2)) {
+ len2=tvb_get_ntohs(tvb,
+ offset+10+len1);
+ if (fhlen==12+len1+len2) {
+ fhtype=FHT_SVR4;
+ goto type_ready;
+ }
+ }
+ }
+ /* For a NetApp filehandle, the flag bits must
+ include WAFL_FH_MULTIVOLUME, and the fileid
+ and generation number need to be nonzero in
+ the mount point, file, and export. */
+ if ((tvb_get_ntohl(tvb,offset+8) & 0x20000000)
+ && tvb_get_ntohl(tvb,offset+0)
+ && tvb_get_ntohl(tvb,offset+4)
+ && tvb_get_ntohl(tvb,offset+12)
+ && tvb_get_ntohl(tvb,offset+16)
+ && tvb_get_ntohl(tvb,offset+24)
+ && tvb_get_ntohl(tvb,offset+28)) {
+ fhtype=FHT_NETAPP;
+ goto type_ready;
+ }
+ len1 = tvb_get_guint8(tvb,offset+4);
+ if (len1<28 && tvb_bytes_exist(tvb,offset+5,len1)) {
+ int wrong=0;
+ for (len2=5+len1;len2<32;len2++) {
+ if (tvb_get_guint8(tvb,offset+len2)) {
+ wrong=1;
+ break;
+ }
+ }
+ if (!wrong) {
+ fhtype=FHT_LINUX_NFSD_LE;
+ goto type_ready;
+ }
+ }
+ if (tvb_get_ntohl(tvb,offset+28) == 0) {
+ if (tvb_get_ntohs(tvb,offset+14) == 0) {
+ if (tvb_get_ntohs(tvb,offset+18) == 0) {
+ fhtype=FHT_LINUX_KNFSD_LE;
+ goto type_ready;
+ }
+ }
+ }
+ } break;
+ }
+ }
+
+type_ready:
+
+ if(!hidden){
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "type: %s", val_to_str(fhtype, names_fhtype, "Unknown"));
+
+
+ switch (fhtype) {
+ case FHT_SVR4:
+ dissect_fhandle_data_SVR4 (tvb, offset, tree,
+ fhlen);
+ break;
+ case FHT_LINUX_KNFSD_LE:
+ dissect_fhandle_data_LINUX_KNFSD_LE(tvb, offset, tree,
+ fhlen);
+ break;
+ case FHT_LINUX_NFSD_LE:
+ dissect_fhandle_data_LINUX_NFSD_LE (tvb, offset, tree,
+ fhlen);
+ break;
+ case FHT_LINUX_KNFSD_NEW:
+ dissect_fhandle_data_LINUX_KNFSD_NEW (tvb, offset, tree,
+ fhlen);
+ break;
+ case FHT_NETAPP:
+ dissect_fhandle_data_NETAPP (tvb, offset, tree,
+ fhlen);
+ break;
+ case FHT_UNKNOWN:
+ default:
+ dissect_fhandle_data_unknown(tvb, offset, tree, fhlen);
+ break;
+ }
+ }
+}
+
+void
+dissect_fhandle_hidden(packet_info *pinfo, proto_tree *tree, nfs_fhandle_data_t *nfd)
+{
+ if(nfd && nfd->len){
+ dissect_fhandle_data(nfd->tvb, 0, pinfo, tree, nfd->len, TRUE, NULL);
+ }
+}
+
+
+/***************************/
+/* NFS Version 2, RFC 1094 */
+/***************************/
+
+
+/* RFC 1094, Page 12..14 */
+static const value_string names_nfs_stat[] =
+{
+ { 0, "OK" },
+ { 1, "ERR_PERM" },
+ { 2, "ERR_NOENT" },
+ { 5, "ERR_IO" },
+ { 6, "ERR_NX_IO" },
+ { 13, "ERR_ACCES" },
+ { 17, "ERR_EXIST" },
+ { 18, "ERR_XDEV" }, /* not in spec, but can happen */
+ { 19, "ERR_NODEV" },
+ { 20, "ERR_NOTDIR" },
+ { 21, "ERR_ISDIR" },
+ { 22, "ERR_INVAL" }, /* not in spec, but I think it can happen */
+ { 26, "ERR_TXTBSY" }, /* not in spec, but I think it can happen */
+ { 27, "ERR_FBIG" },
+ { 28, "ERR_NOSPC" },
+ { 30, "ERR_ROFS" },
+ { 31, "ERR_MLINK" }, /* not in spec, but can happen */
+ { 45, "ERR_OPNOTSUPP" }, /* not in spec, but I think it can happen */
+ { 63, "ERR_NAMETOOLONG" },
+ { 66, "ERR_NOTEMPTY" },
+ { 69, "ERR_DQUOT" },
+ { 70, "ERR_STALE" },
+ { 99, "ERR_WFLUSH" },
+ { 0, NULL }
+};
+
+/* NFSv4 Draft Specification, Page 198-199 */
+static const value_string names_nfs_stat4[] = {
+ { 0, "NFS4_OK" },
+ { 1, "NFS4ERR_PERM" },
+ { 2, "NFS4ERR_NOENT" },
+ { 5, "NFS4ERR_IO" },
+ { 6, "NFS4ERR_NXIO" },
+ { 13, "NFS4ERR_ACCES" },
+ { 17, "NFS4ERR_EXIST" },
+ { 18, "NFS4ERR_XDEV" },
+ { 19, "NFS4ERR_NODEV" },
+ { 20, "NFS4ERR_NOTDIR" },
+ { 21, "NFS4ERR_ISDIR" },
+ { 22, "NFS4ERR_INVAL" },
+ { 27, "NFS4ERR_FBIG" },
+ { 28, "NFS4ERR_NOSPC" },
+ { 30, "NFS4ERR_ROFS" },
+ { 31, "NFS4ERR_MLINK" },
+ { 63, "NFS4ERR_NAMETOOLONG" },
+ { 66, "NFS4ERR_NOTEMPTY" },
+ { 69, "NFS4ERR_DQUOT" },
+ { 70, "NFS4ERR_STALE" },
+ { 10001, "NFS4ERR_BADHANDLE" },
+ { 10003, "NFS4ERR_BAD_COOKIE" },
+ { 10004, "NFS4ERR_NOTSUPP" },
+ { 10005, "NFS4ERR_TOOSMALL" },
+ { 10006, "NFS4ERR_SERVERFAULT" },
+ { 10007, "NFS4ERR_BADTYPE" },
+ { 10008, "NFS4ERR_DELAY" },
+ { 10009, "NFS4ERR_SAME" },
+ { 10010, "NFS4ERR_DENIED" },
+ { 10011, "NFS4ERR_EXPIRED" },
+ { 10012, "NFS4ERR_LOCKED" },
+ { 10013, "NFS4ERR_GRACE" },
+ { 10014, "NFS4ERR_FHEXPIRED" },
+ { 10015, "NFS4ERR_SHARE_DENIED" },
+ { 10016, "NFS4ERR_WRONGSEC" },
+ { 10017, "NFS4ERR_CLID_INUSE" },
+ { 10018, "NFS4ERR_RESOURCE" },
+ { 10019, "NFS4ERR_MOVED" },
+ { 10020, "NFS4ERR_NOFILEHANDLE" },
+ { 10021, "NFS4ERR_MINOR_VERS_MISMATCH" },
+ { 10022, "NFS4ERR_STALE_CLIENTID" },
+ { 10023, "NFS4ERR_STALE_STATEID" },
+ { 10024, "NFS4ERR_OLD_STATEID" },
+ { 10025, "NFS4ERR_BAD_STATEID" },
+ { 10026, "NFS4ERR_BAD_SEQID" },
+ { 10027, "NFS4ERR_NOT_SAME" },
+ { 10028, "NFS4ERR_LOCK_RANGE" },
+ { 10029, "NFS4ERR_SYMLINK" },
+ { 10030, "NFS4ERR_READDIR_NOSPC" },
+ { 10031, "NFS4ERR_LEASE_MOVED" },
+ { 10032, "NFS4ERR_ATTRNOTSUPP" },
+ { 10033, "NFS4ERR_NO_GRACE" },
+ { 10034, "NFS4ERR_RECLAIM_BAD" },
+ { 10035, "NFS4ERR_RECLAIM_CONFLICT" },
+ { 10036, "NFS4ERR_BADXDR" },
+ { 10037, "NFS4ERR_LOCKS_HELD" },
+ { 10038, "NFS4ERR_OPENMODE" },
+ { 10039, "NFS4ERR_BADOWNER" },
+ { 10040, "NFS4ERR_BADCHAR" },
+ { 10041, "NFS4ERR_BADNAME" },
+ { 10042, "NFS4ERR_BAD_RANGE" },
+ { 10043, "NFS4ERR_LOCK_NOTSUPP" },
+ { 10044, "NFS4ERR_OP_ILLEGAL" },
+ { 10045, "NFS4ERR_DEADLOCK" },
+ { 10046, "NFS4ERR_FILE_OPEN" },
+ { 10047, "NFS4ERR_ADMIN_REVOKED" },
+ { 10048, "NFS4ERR_CB_PATH_DOWN" },
+ { 0, NULL }
+};
+
+
+/* This function has been modified to support NFSv4 style error codes as
+ * well as being backwards compatible with NFSv2 and NFSv3.
+ */
+static int
+dissect_stat_internal(tvbuff_t *tvb, int offset,
+ proto_tree *tree, guint32* status, int nfsvers)
+{
+ guint32 stat;
+
+ stat = tvb_get_ntohl(tvb, offset+0);
+
+ if (tree) {
+ /* this gives the right NFSv2 number<->message relation */
+ /* and makes it searchable via "nfs.status" */
+ proto_tree_add_uint_format(tree, hf_nfs_nfsstat3, tvb,
+ offset+0, 4, stat, "Status: %s (%u)",
+ val_to_str(stat,
+ (nfsvers != 4)? names_nfs_stat: names_nfs_stat4,"%u"), stat);
+ }
+
+ offset += 4;
+
+ if (status) *status = stat;
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 12..14 */
+static int
+dissect_stat(tvbuff_t *tvb, int offset, proto_tree *tree,
+ guint32 *status)
+{
+ return dissect_stat_internal(tvb, offset, tree, status, !4);
+}
+
+
+/* RFC 1094, Page 12..14 */
+static int
+dissect_nfs2_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ proto_item_append_text(tree, ", RMDIR Reply");
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", RMDIR Reply Error:%s", err);
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs2_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ proto_item_append_text(tree, ", SYMLINK Reply");
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", SYMLINK Reply Error:%s", err);
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs2_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ proto_item_append_text(tree, ", LINK Reply");
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", LINK Reply Error:%s", err);
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs2_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ proto_item_append_text(tree, ", RENAME Reply");
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", RENAME Reply Error:%s", err);
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs2_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ proto_item_append_text(tree, ", REMOVE Reply");
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", REMOVE Reply Error:%s", err);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_nfs_nfsstat4(tvbuff_t *tvb, int offset,
+ proto_tree *tree, guint32 *status)
+{
+ return dissect_stat_internal(tvb, offset, tree, status, 4);
+}
+
+
+/* RFC 1094, Page 15 */
+static int
+dissect_ftype(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ guint32 ftype;
+ char* ftype_name = NULL;
+
+ const value_string nfs2_ftype[] =
+ {
+ { 0, "Non-File" },
+ { 1, "Regular File" },
+ { 2, "Directory" },
+ { 3, "Block Special Device" },
+ { 4, "Character Special Device" },
+ { 5, "Symbolic Link" },
+ { 0, NULL }
+ };
+
+ ftype = tvb_get_ntohl(tvb, offset+0);
+ ftype_name = val_to_str(ftype, nfs2_ftype, "%u");
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "%s: %s (%u)", name, ftype_name, ftype);
+ }
+
+ offset += 4;
+ return offset;
+}
+
+
+/* RFC 1094, Page 15 */
+int
+dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
+ char *name, guint32 *hash)
+{
+ proto_item* fitem;
+ proto_tree* ftree = NULL;
+
+ if (tree) {
+ fitem = proto_tree_add_text(tree, tvb, offset, FHSIZE,
+ "%s", name);
+ if (fitem)
+ ftree = proto_item_add_subtree(fitem, ett_nfs_fhandle);
+ }
+
+ /* are we snooping fh to filenames ?*/
+ if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
+ rpc_call_info_value *civ=pinfo->private_data;
+
+ /* NFS v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
+ if( (civ->prog==100003)
+ &&(civ->vers==2)
+ &&(!civ->request)
+ &&((civ->proc==4)||(civ->proc==9)||(civ->proc==14))
+ ) {
+ nfs_name_snoop_add_fh(civ->xid, tvb,
+ offset, 32);
+ }
+
+ /* MOUNT v1,v2 MNT replies might give us a filehandle*/
+ if( (civ->prog==100005)
+ &&(civ->proc==1)
+ &&((civ->vers==1)||(civ->vers==2))
+ &&(!civ->request)
+ ) {
+ nfs_name_snoop_add_fh(civ->xid, tvb,
+ offset, 32);
+ }
+ }
+
+ dissect_fhandle_data(tvb, offset, pinfo, ftree, FHSIZE, FALSE, hash);
+
+ offset += FHSIZE;
+ return offset;
+}
+
+/* RFC 1094, Page 15 */
+static int
+dissect_nfs2_statfs_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 hash;
+
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", STATFS Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+static int
+dissect_nfs2_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 hash;
+
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", READLINK Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+static int
+dissect_nfs2_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 hash;
+
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "object", &hash);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", GETATTR Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 15 */
+static int
+dissect_timeval(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_time, int hf_time_sec, int hf_time_usec)
+{
+ guint32 seconds;
+ guint32 useconds;
+ nstime_t ts;
+
+ proto_item* time_item;
+ proto_tree* time_tree = NULL;
+
+ seconds = tvb_get_ntohl(tvb, offset+0);
+ useconds = tvb_get_ntohl(tvb, offset+4);
+ ts.secs = seconds;
+ ts.nsecs = useconds*1000;
+
+ if (tree) {
+ time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8,
+ &ts);
+ if (time_item)
+ time_tree = proto_item_add_subtree(time_item, ett_nfs_timeval);
+ }
+
+ if (time_tree) {
+ proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4,
+ seconds);
+ proto_tree_add_uint(time_tree, hf_time_usec, tvb, offset+4, 4,
+ useconds);
+ }
+ offset += 8;
+ return offset;
+}
+
+
+/* RFC 1094, Page 16 */
+static const value_string nfs2_mode_names[] = {
+ { 0040000, "Directory" },
+ { 0020000, "Character Special Device" },
+ { 0060000, "Block Special Device" },
+ { 0100000, "Regular File" },
+ { 0120000, "Symbolic Link" },
+ { 0140000, "Named Socket" },
+ { 0000000, NULL },
+};
+
+static int
+dissect_mode(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ guint32 mode;
+ proto_item* mode_item = NULL;
+ proto_tree* mode_tree = NULL;
+
+ mode = tvb_get_ntohl(tvb, offset+0);
+
+ if (tree) {
+ mode_item = proto_tree_add_text(tree, tvb, offset, 4,
+ "%s: 0%o", name, mode);
+ if (mode_item)
+ mode_tree = proto_item_add_subtree(mode_item, ett_nfs_mode);
+ }
+
+ if (mode_tree) {
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_enumerated_bitfield(mode, 0160000, 16,
+ nfs2_mode_names, "%s"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 04000, 16, "Set user id on exec", "not SUID"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 02000, 16, "Set group id on exec", "not SGID"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 01000, 16, "Save swapped text even after use", "not save swapped text"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 0400, 16, "Read permission for owner", "no Read permission for owner"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 0200, 16, "Write permission for owner", "no Write permission for owner"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 0100, 16, "Execute permission for owner", "no Execute permission for owner"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 040, 16, "Read permission for group", "no Read permission for group"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 020, 16, "Write permission for group", "no Write permission for group"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 010, 16, "Execute permission for group", "no Execute permission for group"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 04, 16, "Read permission for others", "no Read permission for others"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 02, 16, "Write permission for others", "no Write permission for others"));
+ proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode, 01, 16, "Execute permission for others", "no Execute permission for others"));
+ }
+
+ offset += 4;
+ return offset;
+}
+
+
+/* RFC 1094, Page 15 */
+int
+dissect_fattr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* fattr_item = NULL;
+ proto_tree* fattr_tree = NULL;
+ int old_offset = offset;
+
+ if (tree) {
+ fattr_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", name);
+ fattr_tree = proto_item_add_subtree(fattr_item, ett_nfs_fattr);
+ }
+
+ offset = dissect_ftype(tvb, offset, fattr_tree, "type");
+ offset = dissect_mode(tvb, offset, fattr_tree, "mode");
+ offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_nlink, offset);
+ offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_uid, offset);
+ offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_gid, offset);
+ offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_size, offset);
+ offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_blocksize, offset);
+ offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_rdev, offset);
+ offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_blocks, offset);
+ offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_fsid, offset);
+ offset = dissect_rpc_uint32(tvb, fattr_tree, hf_nfs_fattr_fileid, offset);
+
+ offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
+ offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
+ offset = dissect_timeval(tvb, offset, fattr_tree, hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_usec);
+
+ /* now we know, that fattr is shorter */
+ if (fattr_item) {
+ proto_item_set_len(fattr_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 17 */
+static int
+dissect_sattr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* sattr_item = NULL;
+ proto_tree* sattr_tree = NULL;
+ int old_offset = offset;
+
+ if (tree) {
+ sattr_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", name);
+ sattr_tree = proto_item_add_subtree(sattr_item, ett_nfs_sattr);
+ }
+
+ if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
+ offset = dissect_mode(tvb, offset, sattr_tree, "mode");
+ else {
+ proto_tree_add_text(sattr_tree, tvb, offset, 4, "mode: no value");
+ offset += 4;
+ }
+
+ if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
+ offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_uid,
+ offset);
+ else {
+ proto_tree_add_text(sattr_tree, tvb, offset, 4, "uid: no value");
+ offset += 4;
+ }
+
+ if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
+ offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_gid,
+ offset);
+ else {
+ proto_tree_add_text(sattr_tree, tvb, offset, 4, "gid: no value");
+ offset += 4;
+ }
+
+ if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff)
+ offset = dissect_rpc_uint32(tvb, sattr_tree, hf_nfs_fattr_size,
+ offset);
+ else {
+ proto_tree_add_text(sattr_tree, tvb, offset, 4, "size: no value");
+ offset += 4;
+ }
+
+ if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
+ offset = dissect_timeval(tvb, offset, sattr_tree, hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_usec);
+ } else {
+ proto_tree_add_text(sattr_tree, tvb, offset, 8, "atime: no value");
+ offset += 8;
+ }
+
+ if (tvb_get_ntohl(tvb, offset+0) != 0xffffffff) {
+ offset = dissect_timeval(tvb, offset, sattr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_usec);
+ } else {
+ proto_tree_add_text(sattr_tree, tvb, offset, 8, "mtime: no value");
+ offset += 8;
+ }
+
+ /* now we know, that sattr is shorter */
+ if (sattr_item) {
+ proto_item_set_len(sattr_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 17 */
+static int
+dissect_filename(tvbuff_t *tvb, int offset,
+ proto_tree *tree, int hf, char **string_ret)
+{
+ offset = dissect_rpc_string(tvb, tree, hf, offset, string_ret);
+ return offset;
+}
+
+
+/* RFC 1094, Page 17 */
+static int
+dissect_path(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, char **name)
+{
+ offset = dissect_rpc_string(tvb, tree, hf, offset, name);
+ return offset;
+}
+
+
+/* RFC 1094, Page 17,18 */
+static int
+dissect_attrstat(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, char *funcname)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_fattr(tvb, offset, tree, "attributes");
+ proto_item_append_text(tree, ", %s Reply", funcname);
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", %s Reply Error:%s", funcname, err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 17,18 */
+static int
+dissect_nfs2_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+ offset = dissect_attrstat(tvb, offset, tree, pinfo, "WRITE");
+
+ return offset;
+}
+
+static int
+dissect_nfs2_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+ offset = dissect_attrstat(tvb, offset, tree, pinfo, "SETATTR");
+
+ return offset;
+}
+
+static int
+dissect_nfs2_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree* tree)
+{
+ offset = dissect_attrstat(tvb, offset, tree, pinfo, "GETATTR");
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 18 */
+static int
+dissect_diropargs(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char* label, guint32 *hash, char **name)
+{
+ proto_item* diropargs_item = NULL;
+ proto_tree* diropargs_tree = NULL;
+ int old_offset = offset;
+
+ if (tree) {
+ diropargs_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", label);
+ diropargs_tree = proto_item_add_subtree(diropargs_item, ett_nfs_diropargs);
+ }
+
+ /* are we snooping fh to filenames ?*/
+ if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
+ /* v2 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
+ rpc_call_info_value *civ=pinfo->private_data;
+
+ if( (civ->prog==100003)
+ &&(civ->vers==2)
+ &&(civ->request)
+ &&((civ->proc==4)||(civ->proc==9)||(civ->proc==14))
+ ) {
+ nfs_name_snoop_add_name(civ->xid, tvb,
+ offset+36, tvb_get_ntohl(tvb, offset+32),
+ offset, 32, NULL);
+ }
+ }
+
+ offset = dissect_fhandle(tvb, offset, pinfo, diropargs_tree, "dir", hash);
+ offset = dissect_filename(tvb, offset, diropargs_tree, hf_nfs_name, name);
+
+ /* now we know, that diropargs is shorter */
+ if (diropargs_item) {
+ proto_item_set_len(diropargs_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 18 */
+static int
+dissect_nfs2_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+ }
+ proto_item_append_text(tree, ", RMDIR Call DH:0x%08x/%s", hash, name);
+ g_free(name);
+
+ return offset;
+}
+
+static int
+dissect_nfs2_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+ }
+ proto_item_append_text(tree, ", REMOVE Call DH:0x%08x/%s", hash, name);
+ g_free(name);
+
+ return offset;
+}
+
+static int
+dissect_nfs2_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+ }
+ proto_item_append_text(tree, ", LOOKUP Call DH:0x%08x/%s", hash, name);
+ g_free(name);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 18 */
+static int
+dissect_diropres(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char *funcname)
+{
+ guint32 status;
+ guint32 hash;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
+ offset = dissect_fattr (tvb, offset, tree, "attributes");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", %s Reply FH:0x%08x", funcname, hash);
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", %s Reply Error:%s", funcname, err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* nfsdata is simply a chunk of RPC opaque data (length, data, fill bytes) */
+static int
+dissect_nfsdata(tvbuff_t *tvb, int offset, proto_tree *tree, int hf)
+{
+ offset = dissect_rpc_data(tvb, tree, hf, offset);
+ return offset;
+}
+
+
+/* RFC 1094, Page 18 */
+static int
+dissect_nfs2_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ offset = dissect_diropres(tvb, offset, pinfo, tree, "MKDIR");
+ return offset;
+}
+
+static int
+dissect_nfs2_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ offset = dissect_diropres(tvb, offset, pinfo, tree, "CREATE");
+ return offset;
+}
+
+static int
+dissect_nfs2_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ offset = dissect_diropres(tvb, offset, pinfo, tree, "LOOKUP");
+ return offset;
+}
+
+
+/* RFC 1094, Page 6 */
+static int
+dissect_nfs2_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 hash;
+
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
+ offset = dissect_sattr (tvb, offset, tree, "attributes");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", SETATTR Call FH:0x%08x", hash);
+ return offset;
+}
+
+
+/* RFC 1094, Page 6 */
+static int
+dissect_nfs2_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 status;
+ char *err;
+ char *name=NULL;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_path(tvb, offset, tree, hf_nfs_readlink_data, &name);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Path:%s", name);
+ }
+ proto_item_append_text(tree, ", READLINK Reply Path:%s", name);
+ g_free(name);
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", READLINK Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 7 */
+static int
+dissect_nfs2_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 offset_value;
+ guint32 count;
+ guint32 totalcount;
+ guint32 hash;
+
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
+ offset_value = tvb_get_ntohl(tvb, offset+0);
+ count = tvb_get_ntohl(tvb, offset+4);
+ totalcount = tvb_get_ntohl(tvb, offset+8);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_read_offset, tvb,
+ offset+0, 4, offset_value);
+ proto_tree_add_uint(tree, hf_nfs_read_count, tvb,
+ offset+4, 4, count);
+ proto_tree_add_uint(tree, hf_nfs_read_totalcount, tvb,
+ offset+8, 4, totalcount);
+ }
+ offset += 12;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%d Count:%d TotalCount:%d", hash, offset_value, count, totalcount);
+ }
+ proto_item_append_text(tree, ", READ Call FH:0x%08x Offset:%d Count:%d TotalCount:%d", hash, offset_value, count, totalcount);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 7 */
+static int
+dissect_nfs2_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_fattr(tvb, offset, tree, "attributes");
+ proto_item_append_text(tree, ", READ Reply");
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", READ Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 8 */
+static int
+dissect_nfs2_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 beginoffset;
+ guint32 offset_value;
+ guint32 totalcount;
+ guint32 hash;
+
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "file", &hash);
+ beginoffset = tvb_get_ntohl(tvb, offset+0);
+ offset_value = tvb_get_ntohl(tvb, offset+4);
+ totalcount = tvb_get_ntohl(tvb, offset+8);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_write_beginoffset, tvb,
+ offset+0, 4, beginoffset);
+ proto_tree_add_uint(tree, hf_nfs_write_offset, tvb,
+ offset+4, 4, offset_value);
+ proto_tree_add_uint(tree, hf_nfs_write_totalcount, tvb,
+ offset+8, 4, totalcount);
+ }
+ offset += 12;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x BeginOffset:%d Offset:%d TotalCount:%d", hash, beginoffset, offset_value, totalcount);
+ }
+ proto_item_append_text(tree, ", WRITE Call FH:0x%08x BeginOffset:%d Offset:%d TotalCount:%d", hash, beginoffset, offset_value, totalcount);
+
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 8 */
+static int
+dissect_nfs2_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
+ offset = dissect_sattr (tvb, offset, tree, "attributes");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+ }
+ proto_item_append_text(tree, ", MKDIR Call DH:0x%08x/%s", hash, name);
+ g_free(name);
+
+ return offset;
+}
+
+static int
+dissect_nfs2_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs(tvb, offset, pinfo, tree, "where", &hash, &name);
+ offset = dissect_sattr (tvb, offset, tree, "attributes");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+ }
+ proto_item_append_text(tree, ", CREATE Call DH:0x%08x/%s", hash, name);
+ g_free(name);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 9 */
+static int
+dissect_nfs2_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 from_hash;
+ char *from_name=NULL;
+ guint32 to_hash;
+ char *to_name=NULL;
+
+ offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
+ offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To DH:0x%08x/%s", from_hash, from_name, to_hash, to_name);
+ }
+ proto_item_append_text(tree, ", RENAME Call From DH:0x%08x/%s To DH:0x%08x/%s", from_hash, from_name, to_hash, to_name);
+
+ g_free(from_name);
+ g_free(to_name);
+ return offset;
+}
+
+
+/* RFC 1094, Page 9 */
+static int
+dissect_nfs2_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 from_hash;
+ guint32 to_hash;
+ char *to_name=NULL;
+
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "from", &from_hash);
+ offset = dissect_diropargs(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
+ }
+ proto_item_append_text(tree, ", LINK Call From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
+
+ g_free(to_name);
+ return offset;
+}
+
+
+/* RFC 1094, Page 10 */
+static int
+dissect_nfs2_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 from_hash;
+ char *from_name=NULL;
+ char *to_name=NULL;
+
+ offset = dissect_diropargs(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
+ offset = dissect_path(tvb, offset, tree, hf_nfs_symlink_to, &to_name);
+ offset = dissect_sattr(tvb, offset, tree, "attributes");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
+ }
+ proto_item_append_text(tree, ", SYMLINK Call From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
+ g_free(from_name);
+ g_free(to_name);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 11 */
+static int
+dissect_nfs2_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 cookie;
+ guint32 count;
+ guint32 hash;
+
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "dir", &hash);
+ cookie = tvb_get_ntohl(tvb, offset+ 0);
+ count = tvb_get_ntohl(tvb, offset+ 4);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_readdir_cookie, tvb,
+ offset+ 0, 4, cookie);
+ proto_tree_add_uint(tree, hf_nfs_readdir_count, tvb,
+ offset+ 4, 4, count);
+ }
+ offset += 8;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", READDIR Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 11 */
+static int
+dissect_readdir_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ proto_item* entry_item = NULL;
+ proto_tree* entry_tree = NULL;
+ int old_offset = offset;
+ guint32 fileid;
+ guint32 cookie;
+ char *name;
+
+ if (tree) {
+ entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
+ offset+0, -1, FALSE);
+ entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
+ }
+
+ fileid = tvb_get_ntohl(tvb, offset + 0);
+ if (entry_tree)
+ proto_tree_add_uint(entry_tree, hf_nfs_readdir_entry_fileid, tvb,
+ offset+0, 4, fileid);
+ offset += 4;
+
+ offset = dissect_filename(tvb, offset, entry_tree,
+ hf_nfs_readdir_entry_name, &name);
+ if (entry_item)
+ proto_item_set_text(entry_item, "Entry: file ID %u, name %s",
+ fileid, name);
+ g_free(name);
+
+ cookie = tvb_get_ntohl(tvb, offset + 0);
+ if (entry_tree)
+ proto_tree_add_uint(entry_tree, hf_nfs_readdir_entry_cookie, tvb,
+ offset+0, 4, cookie);
+ offset += 4;
+
+ /* now we know, that a readdir entry is shorter */
+ if (entry_item) {
+ proto_item_set_len(entry_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+/* RFC 1094, Page 11 */
+static int
+dissect_nfs2_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 status;
+ guint32 eof_value;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ proto_item_append_text(tree, ", READDIR Reply");
+
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset,
+ dissect_readdir_entry);
+ eof_value = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
+ offset+ 0, 4, eof_value);
+ offset += 4;
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", READDIR Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1094, Page 12 */
+static int
+dissect_nfs2_statfs_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ guint32 tsize;
+ guint32 bsize;
+ guint32 blocks;
+ guint32 bfree;
+ guint32 bavail;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ tsize = tvb_get_ntohl(tvb, offset+ 0);
+ bsize = tvb_get_ntohl(tvb, offset+ 4);
+ blocks = tvb_get_ntohl(tvb, offset+ 8);
+ bfree = tvb_get_ntohl(tvb, offset+12);
+ bavail = tvb_get_ntohl(tvb, offset+16);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_statfs_tsize, tvb,
+ offset+ 0, 4, tsize);
+ proto_tree_add_uint(tree, hf_nfs_statfs_bsize, tvb,
+ offset+ 4, 4, bsize);
+ proto_tree_add_uint(tree, hf_nfs_statfs_blocks, tvb,
+ offset+ 8, 4, blocks);
+ proto_tree_add_uint(tree, hf_nfs_statfs_bfree, tvb,
+ offset+12, 4, bfree);
+ proto_tree_add_uint(tree, hf_nfs_statfs_bavail, tvb,
+ offset+16, 4, bavail);
+ }
+ offset += 20;
+ proto_item_append_text(tree, ", STATFS Reply");
+ break;
+ default:
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", STATFS Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff nfs2_proc[] = {
+ { 0, "NULL", /* OK */
+ NULL, NULL },
+ { 1, "GETATTR", /* OK */
+ dissect_nfs2_getattr_call, dissect_nfs2_getattr_reply },
+ { 2, "SETATTR", /* OK */
+ dissect_nfs2_setattr_call, dissect_nfs2_setattr_reply },
+ { 3, "ROOT", /* OK */
+ NULL, NULL },
+ { 4, "LOOKUP", /* OK */
+ dissect_nfs2_lookup_call, dissect_nfs2_lookup_reply },
+ { 5, "READLINK", /* OK */
+ dissect_nfs2_readlink_call, dissect_nfs2_readlink_reply },
+ { 6, "READ", /* OK */
+ dissect_nfs2_read_call, dissect_nfs2_read_reply },
+ { 7, "WRITECACHE", /* OK */
+ NULL, NULL },
+ { 8, "WRITE", /* OK */
+ dissect_nfs2_write_call, dissect_nfs2_write_reply },
+ { 9, "CREATE", /* OK */
+ dissect_nfs2_create_call, dissect_nfs2_create_reply },
+ { 10, "REMOVE", /* OK */
+ dissect_nfs2_remove_call, dissect_nfs2_remove_reply },
+ { 11, "RENAME", /* OK */
+ dissect_nfs2_rename_call, dissect_nfs2_rename_reply },
+ { 12, "LINK", /* OK */
+ dissect_nfs2_link_call, dissect_nfs2_link_reply },
+ { 13, "SYMLINK", /* OK */
+ dissect_nfs2_symlink_call, dissect_nfs2_symlink_reply },
+ { 14, "MKDIR", /* OK */
+ dissect_nfs2_mkdir_call, dissect_nfs2_mkdir_reply },
+ { 15, "RMDIR", /* OK */
+ dissect_nfs2_rmdir_call, dissect_nfs2_rmdir_reply },
+ { 16, "READDIR", /* OK */
+ dissect_nfs2_readdir_call, dissect_nfs2_readdir_reply },
+ { 17, "STATFS", /* OK */
+ dissect_nfs2_statfs_call, dissect_nfs2_statfs_reply },
+ { 0,NULL,NULL,NULL }
+};
+
+static const value_string nfsv2_proc_vals[] = {
+ { 0, "NULL" },
+ { 1, "GETATTR" },
+ { 2, "SETATTR" },
+ { 3, "ROOT" },
+ { 4, "LOOKUP" },
+ { 5, "READLINK" },
+ { 6, "READ" },
+ { 7, "WRITECACHE" },
+ { 8, "WRITE" },
+ { 9, "CREATE" },
+ { 10, "REMOVE" },
+ { 11, "RENAME" },
+ { 12, "LINK" },
+ { 13, "SYMLINK" },
+ { 14, "MKDIR" },
+ { 15, "RMDIR" },
+ { 16, "READDIR" },
+ { 17, "STATFS" },
+ { 0, NULL }
+};
+
+/* end of NFS Version 2 */
+
+
+/***************************/
+/* NFS Version 3, RFC 1813 */
+/***************************/
+
+
+/* RFC 1813, Page 15 */
+static int
+dissect_filename3(tvbuff_t *tvb, int offset,
+ proto_tree *tree, int hf, char **string_ret)
+{
+ offset = dissect_rpc_string(tvb, tree, hf, offset, string_ret);
+ return offset;
+}
+
+
+/* RFC 1813, Page 15 */
+static int
+dissect_nfspath3(tvbuff_t *tvb, int offset, proto_tree *tree, int hf, char **name)
+{
+ offset = dissect_rpc_string(tvb, tree, hf, offset, name);
+ return offset;
+}
+
+/* RFC 1813, Page 15 */
+static int
+dissect_cookieverf3(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, NFS3_COOKIEVERFSIZE,
+ "Verifier: Opaque Data");
+ offset += NFS3_COOKIEVERFSIZE;
+ return offset;
+}
+
+
+/* RFC 1813, Page 16 */
+static int
+dissect_createverf3(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, NFS3_CREATEVERFSIZE,
+ "Verifier: Opaque Data");
+ offset += NFS3_CREATEVERFSIZE;
+ return offset;
+}
+
+
+/* RFC 1813, Page 16 */
+static int
+dissect_writeverf3(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, NFS3_WRITEVERFSIZE,
+ "Verifier: Opaque Data");
+ offset += NFS3_WRITEVERFSIZE;
+ return offset;
+}
+
+/* RFC 1813, Page 16 */
+static int
+dissect_mode3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ guint32 mode3;
+ proto_item* mode3_item = NULL;
+ proto_tree* mode3_tree = NULL;
+
+ mode3 = tvb_get_ntohl(tvb, offset+0);
+
+ if (tree) {
+ mode3_item = proto_tree_add_text(tree, tvb, offset, 4,
+ "%s: 0%o", name, mode3);
+ if (mode3_item)
+ mode3_tree = proto_item_add_subtree(mode3_item, ett_nfs_mode3);
+ }
+
+ /* RFC 1813, Page 23 */
+ if (mode3_tree) {
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x800, 12, "Set user id on exec", "not SUID"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x400, 12, "Set group id on exec", "not SGID"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x200, 12, "Save swapped text even after use", "not save swapped text"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x100, 12, "Read permission for owner", "no Read permission for owner"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x80, 12, "Write permission for owner", "no Write permission for owner"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x40, 12, "Execute permission for owner", "no Execute permission for owner"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x20, 12, "Read permission for group", "no Read permission for group"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x10, 12, "Write permission for group", "no Write permission for group"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x8, 12, "Execute permission for group", "no Execute permission for group"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x4, 12, "Read permission for others", "no Read permission for others"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x2, 12, "Write permission for others", "no Write permission for others"));
+ proto_tree_add_text(mode3_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mode3, 0x1, 12, "Execute permission for others", "no Execute permission for others"));
+ }
+
+ offset += 4;
+ return offset;
+}
+
+/* RFC 1813, Page 16,17 */
+static const value_string names_nfs_nfsstat3[] =
+{
+ { 0, "OK" },
+ { 1, "ERR_PERM" },
+ { 2, "ERR_NOENT" },
+ { 5, "ERR_IO" },
+ { 6, "ERR_NX_IO" },
+ { 13, "ERR_ACCES" },
+ { 17, "ERR_EXIST" },
+ { 18, "ERR_XDEV" },
+ { 19, "ERR_NODEV" },
+ { 20, "ERR_NOTDIR" },
+ { 21, "ERR_ISDIR" },
+ { 22, "ERR_INVAL" },
+ { 27, "ERR_FBIG" },
+ { 28, "ERR_NOSPC" },
+ { 30, "ERR_ROFS" },
+ { 31, "ERR_MLINK" },
+ { 63, "ERR_NAMETOOLONG" },
+ { 66, "ERR_NOTEMPTY" },
+ { 69, "ERR_DQUOT" },
+ { 70, "ERR_STALE" },
+ { 71, "ERR_REMOTE" },
+ { 10001, "ERR_BADHANDLE" },
+ { 10002, "ERR_NOT_SYNC" },
+ { 10003, "ERR_BAD_COOKIE" },
+ { 10004, "ERR_NOTSUPP" },
+ { 10005, "ERR_TOOSMALL" },
+ { 10006, "ERR_SERVERFAULT" },
+ { 10007, "ERR_BADTYPE" },
+ { 10008, "ERR_JUKEBOX" },
+ { 0, NULL }
+};
+
+
+/* RFC 1813, Page 16 */
+static int
+dissect_nfsstat3(tvbuff_t *tvb, int offset,
+ proto_tree *tree,guint32 *status)
+{
+ guint32 nfsstat3;
+
+ nfsstat3 = tvb_get_ntohl(tvb, offset+0);
+
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_nfsstat3, tvb,
+ offset, 4, nfsstat3);
+ }
+
+ offset += 4;
+ *status = nfsstat3;
+ return offset;
+}
+
+
+static const value_string names_nfs_ftype3[] =
+{
+ { NF3REG, "Regular File" },
+ { NF3DIR, "Directory" },
+ { NF3BLK, "Block Special Device" },
+ { NF3CHR, "Character Special Device" },
+ { NF3LNK, "Symbolic Link" },
+ { NF3SOCK,"Socket" },
+ { NF3FIFO,"Named Pipe" },
+ { 0, NULL }
+};
+
+
+/* RFC 1813, Page 20 */
+static int
+dissect_ftype3(tvbuff_t *tvb, int offset, proto_tree *tree,
+ int hf, guint32* ftype3)
+{
+ guint32 type;
+
+ type = tvb_get_ntohl(tvb, offset+0);
+
+ if (tree) {
+ proto_tree_add_uint(tree, hf, tvb, offset, 4, type);
+ }
+
+ offset += 4;
+ *ftype3 = type;
+ return offset;
+}
+
+
+/* RFC 1813, Page 20 */
+static int
+dissect_specdata3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ guint32 specdata1;
+ guint32 specdata2;
+
+ proto_item* specdata3_item;
+ proto_tree* specdata3_tree = NULL;
+
+ specdata1 = tvb_get_ntohl(tvb, offset+0);
+ specdata2 = tvb_get_ntohl(tvb, offset+4);
+
+ if (tree) {
+ specdata3_item = proto_tree_add_text(tree, tvb, offset, 8,
+ "%s: %u,%u", name, specdata1, specdata2);
+ if (specdata3_item)
+ specdata3_tree = proto_item_add_subtree(specdata3_item,
+ ett_nfs_specdata3);
+ }
+
+ if (specdata3_tree) {
+ proto_tree_add_text(specdata3_tree, tvb,offset+0,4,
+ "specdata1: %u", specdata1);
+ proto_tree_add_text(specdata3_tree, tvb,offset+4,4,
+ "specdata2: %u", specdata2);
+ }
+
+ offset += 8;
+ return offset;
+}
+
+
+/* RFC 1813, Page 21 */
+int
+dissect_nfs_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, char *name, guint32 *hash)
+{
+ guint fh3_len;
+ guint fh3_len_full;
+ guint fh3_fill;
+ proto_item* fitem = NULL;
+ proto_tree* ftree = NULL;
+ int fh_offset,fh_length;
+
+ fh3_len = tvb_get_ntohl(tvb, offset+0);
+ fh3_len_full = rpc_roundup(fh3_len);
+ fh3_fill = fh3_len_full - fh3_len;
+
+ if (tree) {
+ fitem = proto_tree_add_text(tree, tvb, offset, 4+fh3_len_full,
+ "%s", name);
+ if (fitem)
+ ftree = proto_item_add_subtree(fitem, ett_nfs_fh3);
+ }
+
+ /* are we snooping fh to filenames ?*/
+ if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
+ rpc_call_info_value *civ=pinfo->private_data;
+
+ /* NFS v3 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
+ if( (civ->prog==100003)
+ &&(civ->vers==3)
+ &&(!civ->request)
+ &&((civ->proc==3)||(civ->proc==8)||(civ->proc==9))
+ ) {
+ fh_length=tvb_get_ntohl(tvb, offset);
+ fh_offset=offset+4;
+ nfs_name_snoop_add_fh(civ->xid, tvb,
+ fh_offset, fh_length);
+ }
+
+ /* MOUNT v3 MNT replies might give us a filehandle */
+ if( (civ->prog==100005)
+ &&(civ->vers==3)
+ &&(!civ->request)
+ &&(civ->proc==1)
+ ) {
+ fh_length=tvb_get_ntohl(tvb, offset);
+ fh_offset=offset+4;
+ nfs_name_snoop_add_fh(civ->xid, tvb,
+ fh_offset, fh_length);
+ }
+ }
+
+ proto_tree_add_uint(ftree, hf_nfs_fh_length, tvb, offset+0, 4,
+ fh3_len);
+
+ /* Handle WebNFS requests where filehandle may be 0 length */
+ if (fh3_len > 0)
+ {
+ dissect_fhandle_data(tvb, offset+4, pinfo, ftree, fh3_len, FALSE, hash);
+
+ offset += fh3_len_full;
+ }
+
+ offset += 4;
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 21 */
+static int
+dissect_nfstime3(tvbuff_t *tvb, int offset,
+ proto_tree *tree, int hf_time, int hf_time_sec, int hf_time_nsec)
+{
+ guint32 seconds;
+ guint32 nseconds;
+ nstime_t ts;
+
+ proto_item* time_item;
+ proto_tree* time_tree = NULL;
+
+ seconds = tvb_get_ntohl(tvb, offset+0);
+ nseconds = tvb_get_ntohl(tvb, offset+4);
+ ts.secs = seconds;
+ ts.nsecs = nseconds;
+
+ if (tree) {
+ time_item = proto_tree_add_time(tree, hf_time, tvb, offset, 8,
+ &ts);
+ if (time_item)
+ time_tree = proto_item_add_subtree(time_item, ett_nfs_nfstime3);
+ }
+
+ if (time_tree) {
+ proto_tree_add_uint(time_tree, hf_time_sec, tvb, offset, 4,
+ seconds);
+ proto_tree_add_uint(time_tree, hf_time_nsec, tvb, offset+4, 4,
+ nseconds);
+ }
+ offset += 8;
+ return offset;
+}
+
+
+/* RFC 1813, Page 22 */
+int
+dissect_nfs_fattr3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* fattr3_item = NULL;
+ proto_tree* fattr3_tree = NULL;
+ int old_offset = offset;
+ guint32 type;
+
+ if (tree) {
+ fattr3_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", name);
+ fattr3_tree = proto_item_add_subtree(fattr3_item, ett_nfs_fattr3);
+ }
+
+ offset = dissect_ftype3(tvb,offset,fattr3_tree,hf_nfs_fattr3_type,&type);
+ offset = dissect_mode3(tvb,offset,fattr3_tree,"mode");
+ offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs_fattr3_nlink,
+ offset);
+ offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs_fattr3_uid,
+ offset);
+ offset = dissect_rpc_uint32(tvb, fattr3_tree, hf_nfs_fattr3_gid,
+ offset);
+ offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_size,
+ offset);
+ offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_used,
+ offset);
+ offset = dissect_specdata3(tvb,offset,fattr3_tree,"rdev");
+ offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_fsid,
+ offset);
+ offset = dissect_rpc_uint64(tvb, fattr3_tree, hf_nfs_fattr3_fileid,
+ offset);
+ offset = dissect_nfstime3 (tvb,offset,fattr3_tree,hf_nfs_atime,hf_nfs_atime_sec,hf_nfs_atime_nsec);
+ offset = dissect_nfstime3 (tvb,offset,fattr3_tree,hf_nfs_mtime,hf_nfs_mtime_sec,hf_nfs_mtime_nsec);
+ offset = dissect_nfstime3 (tvb,offset,fattr3_tree,hf_nfs_ctime,hf_nfs_ctime_sec,hf_nfs_ctime_nsec);
+
+ /* now we know, that fattr3 is shorter */
+ if (fattr3_item) {
+ proto_item_set_len(fattr3_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+static const value_string value_follows[] =
+ {
+ { 0, "no value" },
+ { 1, "value follows"},
+ { 0, NULL }
+ };
+
+
+/* RFC 1813, Page 23 */
+int
+dissect_nfs_post_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree,
+ char* name)
+{
+ proto_item* post_op_attr_item = NULL;
+ proto_tree* post_op_attr_tree = NULL;
+ int old_offset = offset;
+ guint32 attributes_follow;
+
+ if (tree) {
+ post_op_attr_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", name);
+ post_op_attr_tree = proto_item_add_subtree(post_op_attr_item,
+ ett_nfs_post_op_attr);
+ }
+
+ attributes_follow = tvb_get_ntohl(tvb, offset+0);
+ proto_tree_add_text(post_op_attr_tree, tvb, offset, 4,
+ "attributes_follow: %s (%u)",
+ val_to_str(attributes_follow,value_follows,"Unknown"), attributes_follow);
+ offset += 4;
+ switch (attributes_follow) {
+ case TRUE:
+ offset = dissect_nfs_fattr3(tvb, offset, post_op_attr_tree,
+ "attributes");
+ break;
+ case FALSE:
+ /* void */
+ break;
+ }
+
+ /* now we know, that post_op_attr_tree is shorter */
+ if (post_op_attr_item) {
+ proto_item_set_len(post_op_attr_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 24 */
+static int
+dissect_wcc_attr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* wcc_attr_item = NULL;
+ proto_tree* wcc_attr_tree = NULL;
+ int old_offset = offset;
+
+ if (tree) {
+ wcc_attr_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", name);
+ wcc_attr_tree = proto_item_add_subtree(wcc_attr_item,
+ ett_nfs_wcc_attr);
+ }
+
+ offset = dissect_rpc_uint64(tvb, wcc_attr_tree, hf_nfs_wcc_attr_size,
+ offset);
+ offset = dissect_nfstime3(tvb, offset, wcc_attr_tree, hf_nfs_mtime, hf_nfs_mtime_sec, hf_nfs_mtime_nsec);
+ offset = dissect_nfstime3(tvb, offset, wcc_attr_tree, hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
+ /* now we know, that wcc_attr_tree is shorter */
+ if (wcc_attr_item) {
+ proto_item_set_len(wcc_attr_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 24 */
+static int
+dissect_pre_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* pre_op_attr_item = NULL;
+ proto_tree* pre_op_attr_tree = NULL;
+ int old_offset = offset;
+ guint32 attributes_follow;
+
+ if (tree) {
+ pre_op_attr_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", name);
+ pre_op_attr_tree = proto_item_add_subtree(pre_op_attr_item,
+ ett_nfs_pre_op_attr);
+ }
+
+ attributes_follow = tvb_get_ntohl(tvb, offset+0);
+ proto_tree_add_text(pre_op_attr_tree, tvb, offset, 4,
+ "attributes_follow: %s (%u)",
+ val_to_str(attributes_follow,value_follows,"Unknown"), attributes_follow);
+ offset += 4;
+ switch (attributes_follow) {
+ case TRUE:
+ offset = dissect_wcc_attr(tvb, offset, pre_op_attr_tree,
+ "attributes");
+ break;
+ case FALSE:
+ /* void */
+ break;
+ }
+
+ /* now we know, that pre_op_attr_tree is shorter */
+ if (pre_op_attr_item) {
+ proto_item_set_len(pre_op_attr_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 24 */
+static int
+dissect_wcc_data(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* wcc_data_item = NULL;
+ proto_tree* wcc_data_tree = NULL;
+ int old_offset = offset;
+
+ if (tree) {
+ wcc_data_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", name);
+ wcc_data_tree = proto_item_add_subtree(wcc_data_item,
+ ett_nfs_wcc_data);
+ }
+
+ offset = dissect_pre_op_attr (tvb, offset, wcc_data_tree, "before");
+ offset = dissect_nfs_post_op_attr(tvb, offset, wcc_data_tree, "after" );
+
+ /* now we know, that wcc_data is shorter */
+ if (wcc_data_item) {
+ proto_item_set_len(wcc_data_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 25 */
+static int
+dissect_post_op_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, char* name)
+{
+ proto_item* post_op_fh3_item = NULL;
+ proto_tree* post_op_fh3_tree = NULL;
+ int old_offset = offset;
+ guint32 handle_follows;
+
+ if (tree) {
+ post_op_fh3_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", name);
+ post_op_fh3_tree = proto_item_add_subtree(post_op_fh3_item,
+ ett_nfs_post_op_fh3);
+ }
+
+ handle_follows = tvb_get_ntohl(tvb, offset+0);
+ proto_tree_add_text(post_op_fh3_tree, tvb, offset, 4,
+ "handle_follows: %s (%u)",
+ val_to_str(handle_follows,value_follows,"Unknown"), handle_follows);
+ offset += 4;
+ switch (handle_follows) {
+ case TRUE:
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, post_op_fh3_tree,
+ "handle", NULL);
+ break;
+ case FALSE:
+ /* void */
+ break;
+ }
+
+ /* now we know, that post_op_fh3_tree is shorter */
+ if (post_op_fh3_item) {
+ proto_item_set_len(post_op_fh3_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 25 */
+static int
+dissect_set_mode3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* set_mode3_item = NULL;
+ proto_tree* set_mode3_tree = NULL;
+ int old_offset = offset;
+ guint32 set_it;
+ char* set_it_name;
+
+ set_it = tvb_get_ntohl(tvb, offset+0);
+ set_it_name = val_to_str(set_it,value_follows,"Unknown");
+
+ if (tree) {
+ set_mode3_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s: %s", name, set_it_name);
+ set_mode3_tree = proto_item_add_subtree(set_mode3_item,
+ ett_nfs_set_mode3);
+ }
+
+ if (set_mode3_tree)
+ proto_tree_add_text(set_mode3_tree, tvb, offset, 4,
+ "set_it: %s (%u)", set_it_name, set_it);
+
+ offset += 4;
+
+ switch (set_it) {
+ case 1:
+ offset = dissect_mode3(tvb, offset, set_mode3_tree,
+ "mode");
+ break;
+ default:
+ /* void */
+ break;
+ }
+
+ /* now we know, that set_mode3 is shorter */
+ if (set_mode3_item) {
+ proto_item_set_len(set_mode3_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 26 */
+static int
+dissect_set_uid3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* set_uid3_item = NULL;
+ proto_tree* set_uid3_tree = NULL;
+ int old_offset = offset;
+ guint32 set_it;
+ char* set_it_name;
+
+ set_it = tvb_get_ntohl(tvb, offset+0);
+ set_it_name = val_to_str(set_it,value_follows,"Unknown");
+
+ if (tree) {
+ set_uid3_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s: %s", name, set_it_name);
+ set_uid3_tree = proto_item_add_subtree(set_uid3_item,
+ ett_nfs_set_uid3);
+ }
+
+ if (set_uid3_tree)
+ proto_tree_add_text(set_uid3_tree, tvb, offset, 4,
+ "set_it: %s (%u)", set_it_name, set_it);
+
+ offset += 4;
+
+ switch (set_it) {
+ case 1:
+ offset = dissect_rpc_uint32(tvb, set_uid3_tree,
+ hf_nfs_uid3, offset);
+ break;
+ default:
+ /* void */
+ break;
+ }
+
+ /* now we know, that set_uid3 is shorter */
+ if (set_uid3_item) {
+ proto_item_set_len(set_uid3_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 26 */
+static int
+dissect_set_gid3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* set_gid3_item = NULL;
+ proto_tree* set_gid3_tree = NULL;
+ int old_offset = offset;
+ guint32 set_it;
+ char* set_it_name;
+
+ set_it = tvb_get_ntohl(tvb, offset+0);
+ set_it_name = val_to_str(set_it,value_follows,"Unknown");
+
+ if (tree) {
+ set_gid3_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s: %s", name, set_it_name);
+ set_gid3_tree = proto_item_add_subtree(set_gid3_item,
+ ett_nfs_set_gid3);
+ }
+
+ if (set_gid3_tree)
+ proto_tree_add_text(set_gid3_tree, tvb, offset, 4,
+ "set_it: %s (%u)", set_it_name, set_it);
+
+ offset += 4;
+
+ switch (set_it) {
+ case 1:
+ offset = dissect_rpc_uint32(tvb, set_gid3_tree,
+ hf_nfs_gid3, offset);
+ break;
+ default:
+ /* void */
+ break;
+ }
+
+ /* now we know, that set_gid3 is shorter */
+ if (set_gid3_item) {
+ proto_item_set_len(set_gid3_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 26 */
+static int
+dissect_set_size3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* set_size3_item = NULL;
+ proto_tree* set_size3_tree = NULL;
+ int old_offset = offset;
+ guint32 set_it;
+ char* set_it_name;
+
+ set_it = tvb_get_ntohl(tvb, offset+0);
+ set_it_name = val_to_str(set_it,value_follows,"Unknown");
+
+ if (tree) {
+ set_size3_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s: %s", name, set_it_name);
+ set_size3_tree = proto_item_add_subtree(set_size3_item,
+ ett_nfs_set_size3);
+ }
+
+ if (set_size3_tree)
+ proto_tree_add_text(set_size3_tree, tvb, offset, 4,
+ "set_it: %s (%u)", set_it_name, set_it);
+
+ offset += 4;
+
+ switch (set_it) {
+ case 1:
+ offset = dissect_rpc_uint64(tvb, set_size3_tree,
+ hf_nfs_set_size3_size, offset);
+ break;
+ default:
+ /* void */
+ break;
+ }
+
+ /* now we know, that set_size3 is shorter */
+ if (set_size3_item) {
+ proto_item_set_len(set_size3_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 25 */
+#define DONT_CHANGE 0
+#define SET_TO_SERVER_TIME 1
+#define SET_TO_CLIENT_TIME 2
+
+static const value_string time_how[] =
+ {
+ { DONT_CHANGE, "don't change" },
+ { SET_TO_SERVER_TIME, "set to server time" },
+ { SET_TO_CLIENT_TIME, "set to client time" },
+ { 0, NULL }
+ };
+
+
+/* RFC 1813, Page 26 */
+static int
+dissect_set_atime(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* set_atime_item = NULL;
+ proto_tree* set_atime_tree = NULL;
+ int old_offset = offset;
+ guint32 set_it;
+ char* set_it_name;
+
+ set_it = tvb_get_ntohl(tvb, offset+0);
+ set_it_name = val_to_str(set_it,time_how,"Unknown");
+
+ if (tree) {
+ set_atime_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s: %s", name, set_it_name);
+ set_atime_tree = proto_item_add_subtree(set_atime_item,
+ ett_nfs_set_atime);
+ }
+
+ if (set_atime_tree)
+ proto_tree_add_text(set_atime_tree, tvb, offset, 4,
+ "set_it: %s (%u)", set_it_name, set_it);
+
+ offset += 4;
+
+ switch (set_it) {
+ case SET_TO_CLIENT_TIME:
+ if (set_atime_item) {
+ offset = dissect_nfstime3(tvb, offset, set_atime_tree,
+ hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
+ }
+ break;
+ default:
+ /* void */
+ break;
+ }
+
+ /* now we know, that set_atime is shorter */
+ if (set_atime_item) {
+ proto_item_set_len(set_atime_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 26 */
+static int
+dissect_set_mtime(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* set_mtime_item = NULL;
+ proto_tree* set_mtime_tree = NULL;
+ int old_offset = offset;
+ guint32 set_it;
+ char* set_it_name;
+
+ set_it = tvb_get_ntohl(tvb, offset+0);
+ set_it_name = val_to_str(set_it,time_how,"Unknown");
+
+ if (tree) {
+ set_mtime_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s: %s", name, set_it_name);
+ set_mtime_tree = proto_item_add_subtree(set_mtime_item,
+ ett_nfs_set_mtime);
+ }
+
+ if (set_mtime_tree)
+ proto_tree_add_text(set_mtime_tree, tvb, offset, 4,
+ "set_it: %s (%u)", set_it_name, set_it);
+
+ offset += 4;
+
+ switch (set_it) {
+ case SET_TO_CLIENT_TIME:
+ if (set_mtime_item) {
+ offset = dissect_nfstime3(tvb, offset, set_mtime_tree,
+ hf_nfs_atime, hf_nfs_atime_sec, hf_nfs_atime_nsec);
+ }
+ break;
+ default:
+ /* void */
+ break;
+ }
+
+ /* now we know, that set_mtime is shorter */
+ if (set_mtime_item) {
+ proto_item_set_len(set_mtime_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 25..27 */
+static int
+dissect_sattr3(tvbuff_t *tvb, int offset, proto_tree *tree, char* name)
+{
+ proto_item* sattr3_item = NULL;
+ proto_tree* sattr3_tree = NULL;
+ int old_offset = offset;
+
+ if (tree) {
+ sattr3_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", name);
+ sattr3_tree = proto_item_add_subtree(sattr3_item, ett_nfs_sattr3);
+ }
+
+ offset = dissect_set_mode3(tvb, offset, sattr3_tree, "mode");
+ offset = dissect_set_uid3 (tvb, offset, sattr3_tree, "uid");
+ offset = dissect_set_gid3 (tvb, offset, sattr3_tree, "gid");
+ offset = dissect_set_size3(tvb, offset, sattr3_tree, "size");
+ offset = dissect_set_atime(tvb, offset, sattr3_tree, "atime");
+ offset = dissect_set_mtime(tvb, offset, sattr3_tree, "mtime");
+
+ /* now we know, that sattr3 is shorter */
+ if (sattr3_item) {
+ proto_item_set_len(sattr3_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 27 */
+static int
+dissect_diropargs3(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, char* label, guint32 *hash, char **name)
+{
+ proto_item* diropargs3_item = NULL;
+ proto_tree* diropargs3_tree = NULL;
+ int old_offset = offset;
+ int parent_offset, parent_len;
+ int name_offset, name_len;
+
+ if (tree) {
+ diropargs3_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s", label);
+ diropargs3_tree = proto_item_add_subtree(diropargs3_item,
+ ett_nfs_diropargs3);
+ }
+
+ parent_offset=offset+4;
+ parent_len=tvb_get_ntohl(tvb, offset);
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, diropargs3_tree, "dir", hash);
+ name_offset=offset+4;
+ name_len=tvb_get_ntohl(tvb, offset);
+ offset = dissect_filename3(tvb, offset, diropargs3_tree,
+ hf_nfs_name, name);
+
+ /* are we snooping fh to filenames ?*/
+ if((!pinfo->fd->flags.visited) && nfs_file_name_snooping){
+ /* v3 LOOKUP, CREATE, MKDIR calls might give us a mapping*/
+ rpc_call_info_value *civ=pinfo->private_data;
+
+ if( (civ->prog==100003)
+ &&(civ->vers==3)
+ &&(civ->request)
+ &&((civ->proc==3)||(civ->proc==8)||(civ->proc==9))
+ ) {
+ nfs_name_snoop_add_name(civ->xid, tvb,
+ name_offset, name_len,
+ parent_offset, parent_len, NULL);
+ }
+ }
+
+
+ /* now we know, that diropargs3 is shorter */
+ if (diropargs3_item) {
+ proto_item_set_len(diropargs3_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs3_remove_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+ }
+ proto_item_append_text(tree, ", REMOVE Call DH:0x%08x/%s", hash, name);
+ g_free(name);
+
+ return offset;
+}
+
+static int
+dissect_nfs3_null_call(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item_append_text(tree, ", NULL Call");
+
+ return offset;
+}
+
+static int
+dissect_nfs3_null_reply(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item_append_text(tree, ", NULL Reply");
+
+ return offset;
+}
+
+static int
+dissect_nfs3_rmdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs3(tvb, offset, pinfo, tree, "object", &hash, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+ }
+ proto_item_append_text(tree, ", RMDIR Call DH:0x%08x/%s", hash, name);
+ g_free(name);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 40 */
+int
+dissect_access(tvbuff_t *tvb, int offset, proto_tree *tree,
+ char* name)
+{
+ guint32 access;
+ proto_item* access_item = NULL;
+ proto_tree* access_tree = NULL;
+
+ access = tvb_get_ntohl(tvb, offset+0);
+
+ if (tree) {
+ access_item = proto_tree_add_text(tree, tvb, offset, 4,
+ "%s: 0x%02x", name, access);
+ if (access_item)
+ access_tree = proto_item_add_subtree(access_item, ett_nfs_access);
+ }
+
+ if (access_tree) {
+ proto_tree_add_text(access_tree, tvb, offset, 4, "%s READ",
+ decode_boolean_bitfield(access, 0x001, 6, "allow", "not allow"));
+ proto_tree_add_text(access_tree, tvb, offset, 4, "%s LOOKUP",
+ decode_boolean_bitfield(access, 0x002, 6, "allow", "not allow"));
+ proto_tree_add_text(access_tree, tvb, offset, 4, "%s MODIFY",
+ decode_boolean_bitfield(access, 0x004, 6, "allow", "not allow"));
+ proto_tree_add_text(access_tree, tvb, offset, 4, "%s EXTEND",
+ decode_boolean_bitfield(access, 0x008, 6, "allow", "not allow"));
+ proto_tree_add_text(access_tree, tvb, offset, 4, "%s DELETE",
+ decode_boolean_bitfield(access, 0x010, 6, "allow", "not allow"));
+ proto_tree_add_text(access_tree, tvb, offset, 4, "%s EXECUTE",
+ decode_boolean_bitfield(access, 0x020, 6, "allow", "not allow"));
+ }
+
+ offset += 4;
+ return offset;
+}
+
+
+/* RFC 1813, Page 32,33 */
+static int
+dissect_nfs3_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", GETATTR Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 32,33 */
+static int
+dissect_nfs3_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_fattr3(tvb, offset, tree, "obj_attributes");
+ proto_item_append_text(tree, ", GETATTR Reply");
+ break;
+ default:
+ /* void */
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", GETATTR Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 33 */
+static int
+dissect_sattrguard3(tvbuff_t *tvb, int offset, proto_tree* tree, char *name)
+{
+ proto_item* sattrguard3_item = NULL;
+ proto_tree* sattrguard3_tree = NULL;
+ int old_offset = offset;
+ guint32 check;
+ char* check_name;
+
+ check = tvb_get_ntohl(tvb, offset+0);
+ check_name = val_to_str(check,value_follows,"Unknown");
+
+ if (tree) {
+ sattrguard3_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "%s: %s", name, check_name);
+ sattrguard3_tree = proto_item_add_subtree(sattrguard3_item,
+ ett_nfs_sattrguard3);
+ }
+
+ if (sattrguard3_tree)
+ proto_tree_add_text(sattrguard3_tree, tvb, offset, 4,
+ "check: %s (%u)", check_name, check);
+
+ offset += 4;
+
+ switch (check) {
+ case TRUE:
+ offset = dissect_nfstime3(tvb, offset, sattrguard3_tree,
+ hf_nfs_ctime, hf_nfs_ctime_sec, hf_nfs_ctime_nsec);
+ break;
+ case FALSE:
+ /* void */
+ break;
+ }
+
+ /* now we know, that sattrguard3 is shorter */
+ if (sattrguard3_item) {
+ proto_item_set_len(sattrguard3_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 33..36 */
+static int
+dissect_nfs3_setattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3 (tvb, offset, pinfo, tree, "object", &hash);
+ offset = dissect_sattr3 (tvb, offset, tree, "new_attributes");
+ offset = dissect_sattrguard3(tvb, offset, tree, "guard");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", SETATTR Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 33..36 */
+static int
+dissect_nfs3_setattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_wcc_data(tvb, offset, tree, "obj_wcc");
+ proto_item_append_text(tree, ", SETATTR Reply");
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "obj_wcc");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", SETATTR Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 37..39 */
+static int
+dissect_nfs3_lookup_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "what", &hash, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+ }
+ proto_item_append_text(tree, ", LOOKUP Call DH:0x%08x/%s", hash, name);
+ g_free(name);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 37..39 */
+static int
+dissect_nfs3_lookup_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+ guint32 hash;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "dir_attributes");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", LOOKUP Reply FH:0x%08x", hash);
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "dir_attributes");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", LOOKUP Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 40..43 */
+static int
+dissect_nfs3_access_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+ offset = dissect_access (tvb, offset, tree, "access");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", ACCESS Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 40..43 */
+static int
+dissect_nfs3_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+ offset = dissect_access(tvb, offset, tree, "access");
+
+ proto_item_append_text(tree, ", ACCESS Reply");
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", ACCESS Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 44,45 */
+static int
+dissect_nfs3_readlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", READLINK Call FH:0x%08x", hash);
+
+ return offset;
+}
+static int
+dissect_nfs3_readlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+ char *name=NULL;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "symlink_attributes");
+ offset = dissect_nfspath3(tvb, offset, tree,
+ hf_nfs_readlink_data, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Path:%s", name);
+ }
+ proto_item_append_text(tree, ", READLINK Reply Path:%s", name);
+ g_free(name);
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "symlink_attributes");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", READLINK Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 46..48 */
+static int
+dissect_nfs3_read_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ unsigned char *off;
+ guint32 len;
+ guint32 hash;
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file", &hash);
+
+ off=u64toa(tvb_get_ptr(tvb, offset, 8));
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
+
+ len=tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
+
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%s Len:%d", hash, off, len);
+ }
+ proto_item_append_text(tree, ", READ Call FH:0x%08x Offset:%s Len:%d", hash, off, len);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 46..48 */
+static int
+dissect_nfs3_read_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ guint32 len;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "file_attributes");
+ len=tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3,
+ offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs_read_eof,
+ offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Len:%d", len);
+ }
+ proto_item_append_text(tree, ", READ Reply Len:%d", len);
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_data);
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "file_attributes");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", READ Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 49 */
+static const value_string names_stable_how[] = {
+ { UNSTABLE, "UNSTABLE" },
+ { DATA_SYNC, "DATA_SYNC" },
+ { FILE_SYNC, "FILE_SYNC" },
+ { 0, NULL }
+};
+
+
+/* RFC 1813, Page 49 */
+static int
+dissect_stable_how(tvbuff_t *tvb, int offset, proto_tree* tree, int hfindex)
+{
+ guint32 stable_how;
+
+ stable_how = tvb_get_ntohl(tvb,offset+0);
+ if (tree) {
+ proto_tree_add_uint(tree, hfindex, tvb,
+ offset, 4, stable_how);
+ }
+ offset += 4;
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 49..54 */
+static int
+dissect_nfs3_write_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ unsigned char *off;
+ guint32 len;
+ guint32 stable;
+ guint32 hash;
+
+ offset = dissect_nfs_fh3 (tvb, offset, pinfo, tree, "file", &hash);
+
+ off=u64toa(tvb_get_ptr(tvb, offset, 8));
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
+
+ len=tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
+
+ stable=tvb_get_ntohl(tvb, offset);
+ offset = dissect_stable_how(tvb, offset, tree, hf_nfs_write_stable);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x Offset:%s Len:%d %s", hash, off, len, val_to_str(stable, names_stable_how, "Stable:%u"));
+ }
+ proto_item_append_text(tree, ", WRITE Call FH:0x%08x Offset:%s Len:%d %s", hash, off, len, val_to_str(stable, names_stable_how, "Stable:%u"));
+
+ offset = dissect_nfsdata (tvb, offset, tree, hf_nfs_data);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 49..54 */
+static int
+dissect_nfs3_write_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ guint32 len;
+ guint32 stable;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_wcc_data (tvb, offset, tree, "file_wcc");
+ len=tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3,
+ offset);
+ stable=tvb_get_ntohl(tvb, offset);
+ offset = dissect_stable_how(tvb, offset, tree,
+ hf_nfs_write_committed);
+ offset = dissect_writeverf3(tvb, offset, tree);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Len:%d %s", len, val_to_str(stable, names_stable_how, "Stable:%u"));
+ }
+ proto_item_append_text(tree, ", WRITE Reply Len:%d %s", len, val_to_str(stable, names_stable_how, "Stable:%u"));
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "file_wcc");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", WRITE Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 54 */
+static const value_string names_createmode3[] = {
+ { UNCHECKED, "UNCHECKED" },
+ { GUARDED, "GUARDED" },
+ { EXCLUSIVE, "EXCLUSIVE" },
+ { 0, NULL }
+};
+
+
+/* RFC 1813, Page 54 */
+static int
+dissect_createmode3(tvbuff_t *tvb, int offset, proto_tree* tree, guint32* mode)
+{
+ guint32 mode_value;
+
+ mode_value = tvb_get_ntohl(tvb, offset + 0);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nfs_createmode3, tvb,
+ offset+0, 4, mode_value);
+ }
+ offset += 4;
+
+ *mode = mode_value;
+ return offset;
+}
+
+
+/* RFC 1813, Page 54..58 */
+static int
+dissect_nfs3_create_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 mode;
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs3 (tvb, offset, pinfo, tree, "where", &hash, &name);
+ offset = dissect_createmode3(tvb, offset, tree, &mode);
+ switch (mode) {
+ case UNCHECKED:
+ case GUARDED:
+ offset = dissect_sattr3(tvb, offset, tree, "obj_attributes");
+ break;
+ case EXCLUSIVE:
+ offset = dissect_createverf3(tvb, offset, tree);
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s Mode:%s", hash, name, val_to_str(mode, names_createmode3, "Unknown Mode:%u"));
+ }
+ proto_item_append_text(tree, ", CREATE Call DH:0x%08x/%s Mode:%s", hash, name, val_to_str(mode, names_createmode3, "Unknown Mode:%u"));
+ g_free(name);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 54..58 */
+static int
+dissect_nfs3_create_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+ proto_item_append_text(tree, ", CREATE Reply");
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", CREATE Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 58..60 */
+static int
+dissect_nfs3_mkdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+ char *name=NULL;
+
+ offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name);
+ offset = dissect_sattr3 (tvb, offset, tree, "attributes");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", DH:0x%08x/%s", hash, name);
+ }
+ proto_item_append_text(tree, ", MKDIR Call DH:0x%08x/%s", hash, name);
+ g_free(name);
+
+ return offset;
+}
+
+static int
+dissect_nfs3_mkdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+ proto_item_append_text(tree, ", MKDIR Reply");
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", MKDIR Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 61..63 */
+static int
+dissect_nfs3_symlink_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 from_hash;
+ char *from_name=NULL;
+ char *to_name=NULL;
+
+ offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &from_hash, &from_name);
+ offset = dissect_sattr3 (tvb, offset, tree, "symlink_attributes");
+ offset = dissect_nfspath3 (tvb, offset, tree, hf_nfs_symlink_to, &to_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
+ }
+ proto_item_append_text(tree, ", SYMLINK Call From DH:0x%08x/%s To %s", from_hash, from_name, to_name);
+ g_free(from_name);
+ g_free(to_name);
+
+ return offset;
+}
+static int
+dissect_nfs3_symlink_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+ proto_item_append_text(tree, ", SYMLINK Reply");
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", SYMLINK Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 63..66 */
+static int
+dissect_nfs3_mknod_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 type;
+ guint32 hash;
+ char *name=NULL;
+ char *type_str;
+
+ offset = dissect_diropargs3(tvb, offset, pinfo, tree, "where", &hash, &name);
+ offset = dissect_ftype3(tvb, offset, tree, hf_nfs_ftype3, &type);
+ switch (type) {
+ case NF3CHR:
+ case NF3BLK:
+ offset = dissect_sattr3(tvb, offset, tree, "dev_attributes");
+ offset = dissect_specdata3(tvb, offset, tree, "spec");
+ break;
+ case NF3SOCK:
+ case NF3FIFO:
+ offset = dissect_sattr3(tvb, offset, tree, "pipe_attributes");
+ break;
+ default:
+ /* nothing to do */
+ break;
+ }
+
+ type_str=val_to_str(type, names_nfs_ftype3, "Unknown type:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x/%s %s", hash, name, type_str);
+ }
+ proto_item_append_text(tree, ", MKNOD Call FH:0x%08x/%s %s", hash, name, type_str);
+ g_free(name);
+
+ return offset;
+}
+static int
+dissect_nfs3_mknod_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_post_op_fh3 (tvb, offset, pinfo, tree, "obj");
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+ proto_item_append_text(tree, ", MKNOD Reply");
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", MKNOD Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 67..69 */
+static int
+dissect_nfs3_remove_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+ proto_item_append_text(tree, ", REMOVE Reply");
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", REMOVE Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+static int
+dissect_nfs3_rmdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+ proto_item_append_text(tree, ", RMDIR Reply");
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "dir_wcc");
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", RMDIR Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 71..74 */
+static int
+dissect_nfs3_rename_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 from_hash;
+ char *from_name=NULL;
+ guint32 to_hash;
+ char *to_name=NULL;
+
+ offset = dissect_diropargs3(tvb, offset, pinfo, tree, "from", &from_hash, &from_name);
+ offset = dissect_diropargs3(tvb, offset, pinfo, tree, "to", &to_hash, &to_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x/%s To DH:0x%08x/%s", from_hash, from_name, to_hash, to_name);
+ }
+ proto_item_append_text(tree, ", RENAME Call From DH:0x%08x/%s To DH:0x%08x/%s", from_hash, from_name, to_hash, to_name);
+
+ g_free(from_name);
+ g_free(to_name);
+ return offset;
+}
+
+
+/* RFC 1813, Page 71..74 */
+static int
+dissect_nfs3_rename_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_wcc_data(tvb, offset, tree, "fromdir_wcc");
+ offset = dissect_wcc_data(tvb, offset, tree, "todir_wcc");
+ proto_item_append_text(tree, ", RENAME Reply");
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "fromdir_wcc");
+ offset = dissect_wcc_data(tvb, offset, tree, "todir_wcc");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", RENAME Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 74..76 */
+static int
+dissect_nfs3_link_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 from_hash;
+ guint32 to_hash;
+ char *to_name=NULL;
+
+ offset = dissect_nfs_fh3 (tvb, offset, pinfo, tree, "file", &from_hash);
+ offset = dissect_diropargs3(tvb, offset, pinfo, tree, "link", &to_hash, &to_name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
+ }
+ proto_item_append_text(tree, ", LINK Call From DH:0x%08x To DH:0x%08x/%s", from_hash, to_hash, to_name);
+
+ g_free(to_name);
+ return offset;
+}
+
+
+/* RFC 1813, Page 74..76 */
+static int
+dissect_nfs3_link_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "file_attributes");
+ offset = dissect_wcc_data(tvb, offset, tree, "linkdir_wcc");
+ proto_item_append_text(tree, ", LINK Reply");
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "file_attributes");
+ offset = dissect_wcc_data(tvb, offset, tree, "linkdir_wcc");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", LINK Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 76..80 */
+static int
+dissect_nfs3_readdir_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3 (tvb, offset, pinfo, tree, "dir", &hash);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie3, offset);
+ offset = dissect_cookieverf3(tvb, offset, tree);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", READDIR Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 76..80 */
+static int
+dissect_entry3(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ proto_item* entry_item = NULL;
+ proto_tree* entry_tree = NULL;
+ int old_offset = offset;
+ char *name=NULL;
+
+ if (tree) {
+ entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
+ offset+0, -1, FALSE);
+ entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
+ }
+
+ offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdir_entry3_fileid,
+ offset);
+
+ offset = dissect_filename3(tvb, offset, entry_tree,
+ hf_nfs_readdir_entry3_name, &name);
+ if (entry_item)
+ proto_item_set_text(entry_item, "Entry: name %s", name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," %s", name);
+ }
+ g_free(name);
+
+ offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdir_entry3_cookie,
+ offset);
+
+ /* now we know, that a readdir entry is shorter */
+ if (entry_item) {
+ proto_item_set_len(entry_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 76..80 */
+static int
+dissect_nfs3_readdir_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 status;
+ guint32 eof_value;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ proto_item_append_text(tree, ", READDIR Reply");
+
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "dir_attributes");
+ offset = dissect_cookieverf3(tvb, offset, tree);
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset,
+ dissect_entry3);
+ eof_value = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
+ offset+ 0, 4, eof_value);
+ offset += 4;
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "dir_attributes");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", READDIR Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 80..83 */
+static int
+dissect_nfs3_readdirplus_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3 (tvb, offset, pinfo, tree, "dir", &hash);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie3, offset);
+ offset = dissect_cookieverf3(tvb, offset, tree);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3_dircount,
+ offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3_maxcount,
+ offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", READDIRPLUS Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 80..83 */
+static int
+dissect_entryplus3(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ proto_item* entry_item = NULL;
+ proto_tree* entry_tree = NULL;
+ int old_offset = offset;
+ char *name=NULL;
+
+ if (tree) {
+ entry_item = proto_tree_add_item(tree, hf_nfs_readdir_entry, tvb,
+ offset+0, -1, FALSE);
+ entry_tree = proto_item_add_subtree(entry_item, ett_nfs_readdir_entry);
+ }
+
+ offset = dissect_rpc_uint64(tvb, entry_tree,
+ hf_nfs_readdirplus_entry_fileid, offset);
+
+ offset = dissect_filename3(tvb, offset, entry_tree,
+ hf_nfs_readdirplus_entry_name, &name);
+ if (entry_item)
+ proto_item_set_text(entry_item, "Entry: name %s", name);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," %s", name);
+ }
+ g_free(name);
+
+ offset = dissect_rpc_uint64(tvb, entry_tree, hf_nfs_readdirplus_entry_cookie,
+ offset);
+
+ offset = dissect_nfs_post_op_attr(tvb, offset, entry_tree,
+ "name_attributes");
+ offset = dissect_post_op_fh3(tvb, offset, pinfo, entry_tree, "name_handle");
+
+ /* now we know, that a readdirplus entry is shorter */
+ if (entry_item) {
+ proto_item_set_len(entry_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 80..83 */
+static int
+dissect_nfs3_readdirplus_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 status;
+ guint32 eof_value;
+ char *err;
+
+ offset = dissect_stat(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ proto_item_append_text(tree, ", READDIRPLUS Reply");
+
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "dir_attributes");
+ offset = dissect_cookieverf3(tvb, offset, tree);
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset,
+ dissect_entryplus3);
+ eof_value = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_readdir_eof, tvb,
+ offset+ 0, 4, eof_value);
+ offset += 4;
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "dir_attributes");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", READDIRPLUS Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 84..86 */
+static int
+dissect_nfs3_fsstat_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", FSSTAT Call DH:0x%08x", hash);
+ return offset;
+}
+
+
+static int
+dissect_nfs3_fsstat_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ guint32 invarsec;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_tbytes,
+ offset);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_fbytes,
+ offset);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_abytes,
+ offset);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_tfiles,
+ offset);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_ffiles,
+ offset);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_fsstat3_resok_afiles,
+ offset);
+ invarsec = tvb_get_ntohl(tvb, offset + 0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_fsstat_invarsec, tvb,
+ offset+0, 4, invarsec);
+ offset += 4;
+
+ proto_item_append_text(tree, ", FSSTAT Reply");
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", FSSTAT Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+#define FSF3_LINK 0x0001
+#define FSF3_SYMLINK 0x0002
+#define FSF3_HOMOGENEOUS 0x0008
+#define FSF3_CANSETTIME 0x0010
+
+
+/* RFC 1813, Page 86..90 */
+static int
+dissect_nfs3_fsinfo_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", FSINFO Call DH:0x%08x", hash);
+ return offset;
+}
+static int
+dissect_nfs3_fsinfo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ guint32 rtmax;
+ guint32 rtpref;
+ guint32 rtmult;
+ guint32 wtmax;
+ guint32 wtpref;
+ guint32 wtmult;
+ guint32 dtpref;
+ guint32 properties;
+ proto_item* properties_item = NULL;
+ proto_tree* properties_tree = NULL;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+ rtmax = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_fsinfo_rtmax, tvb,
+ offset+0, 4, rtmax);
+ offset += 4;
+ rtpref = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_fsinfo_rtpref, tvb,
+ offset+0, 4, rtpref);
+ offset += 4;
+ rtmult = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_fsinfo_rtmult, tvb,
+ offset+0, 4, rtmult);
+ offset += 4;
+ wtmax = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_fsinfo_wtmax, tvb,
+ offset+0, 4, wtmax);
+ offset += 4;
+ wtpref = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_fsinfo_wtpref, tvb,
+ offset+0, 4, wtpref);
+ offset += 4;
+ wtmult = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_fsinfo_wtmult, tvb,
+ offset+0, 4, wtmult);
+ offset += 4;
+ dtpref = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_fsinfo_dtpref, tvb,
+ offset+0, 4, dtpref);
+ offset += 4;
+
+ offset = dissect_rpc_uint64(tvb, tree,
+ hf_nfs_fsinfo_maxfilesize, offset);
+ offset = dissect_nfstime3(tvb, offset, tree, hf_nfs_dtime, hf_nfs_dtime_sec, hf_nfs_dtime_nsec);
+ properties = tvb_get_ntohl(tvb, offset+0);
+ if (tree) {
+ properties_item = proto_tree_add_uint(tree,
+ hf_nfs_fsinfo_properties,
+ tvb, offset+0, 4, properties);
+ if (properties_item)
+ properties_tree = proto_item_add_subtree(properties_item,
+ ett_nfs_fsinfo_properties);
+ if (properties_tree) {
+ proto_tree_add_text(properties_tree, tvb,
+ offset, 4, "%s",
+ decode_boolean_bitfield(properties,
+ FSF3_CANSETTIME,5,
+ "SETATTR can set time on server",
+ "SETATTR can't set time on server"));
+
+ proto_tree_add_text(properties_tree, tvb,
+ offset, 4, "%s",
+ decode_boolean_bitfield(properties,
+ FSF3_HOMOGENEOUS,5,
+ "PATHCONF is valid for all files",
+ "PATHCONF should be get for every single file"));
+
+ proto_tree_add_text(properties_tree, tvb,
+ offset, 4, "%s",
+ decode_boolean_bitfield(properties,
+ FSF3_SYMLINK,5,
+ "File System supports symbolic links",
+ "File System does not symbolic hard links"));
+
+ proto_tree_add_text(properties_tree, tvb,
+ offset, 4, "%s",
+ decode_boolean_bitfield(properties,
+ FSF3_LINK,5,
+ "File System supports hard links",
+ "File System does not support hard links"));
+ }
+ }
+ offset += 4;
+
+ proto_item_append_text(tree, ", FSINFO Reply");
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", FSINFO Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 90..92 */
+static int
+dissect_nfs3_pathconf_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "object", &hash);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", PATHCONF Call DH:0x%08x", hash);
+ return offset;
+}
+static int
+dissect_nfs3_pathconf_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ guint32 linkmax;
+ guint32 name_max;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+ linkmax = tvb_get_ntohl(tvb, offset + 0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_pathconf_linkmax, tvb,
+ offset+0, 4, linkmax);
+ offset += 4;
+ name_max = tvb_get_ntohl(tvb, offset + 0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfs_pathconf_name_max, tvb,
+ offset+0, 4, name_max);
+ offset += 4;
+ offset = dissect_rpc_bool(tvb, tree,
+ hf_nfs_pathconf_no_trunc, offset);
+ offset = dissect_rpc_bool(tvb, tree,
+ hf_nfs_pathconf_chown_restricted, offset);
+ offset = dissect_rpc_bool(tvb, tree,
+ hf_nfs_pathconf_case_insensitive, offset);
+ offset = dissect_rpc_bool(tvb, tree,
+ hf_nfs_pathconf_case_preserving, offset);
+
+ proto_item_append_text(tree, ", PATHCONF Reply");
+ break;
+ default:
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree,
+ "obj_attributes");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", PATHCONF Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 92..95 */
+static int
+dissect_nfs3_commit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 hash;
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "file", &hash);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset3, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_count3, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,", FH:0x%08x", hash);
+ }
+ proto_item_append_text(tree, ", COMMIT Call FH:0x%08x", hash);
+
+ return offset;
+}
+
+
+/* RFC 1813, Page 92..95 */
+static int
+dissect_nfs3_commit_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ guint32 status;
+ char *err;
+
+ offset = dissect_nfsstat3(tvb, offset, tree, &status);
+ switch (status) {
+ case 0:
+ offset = dissect_wcc_data (tvb, offset, tree, "file_wcc");
+ offset = dissect_writeverf3(tvb, offset, tree);
+
+ proto_item_append_text(tree, ", COMMIT Reply");
+ break;
+ default:
+ offset = dissect_wcc_data(tvb, offset, tree, "file_wcc");
+
+ err=val_to_str(status, names_nfs_stat, "Unknown error:%u");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," Error:%s", err);
+ }
+ proto_item_append_text(tree, ", COMMIT Reply Error:%s", err);
+ break;
+ }
+
+ return offset;
+}
+
+/**********************************************************/
+/* NFS Version 4, RFC 3010 with nfs4_prot.x 1.103 changes */
+/**********************************************************/
+
+static int
+dissect_nfs_utf8string(tvbuff_t *tvb, int offset,
+ proto_tree *tree, int hf, char **string_ret)
+{
+ /* TODO: this dissector is subject to change; do not remove */
+ return dissect_rpc_string(tvb, tree, hf, offset, string_ret);
+}
+
+static int
+dissect_nfs_specdata4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_specdata1, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_specdata2, offset);
+
+ return offset;
+}
+
+static const value_string names_ftype4[] = {
+ { NF4REG, "NF4REG" },
+ { NF4DIR, "NF4DIR" },
+ { NF4BLK, "NF4BLK" },
+ { NF4CHR, "NF4CHR" },
+ { NF4LNK, "NF4LNK" },
+ { NF4SOCK, "NF4SOCK" },
+ { NF4FIFO, "NF4FIFO" },
+ { NF4ATTRDIR, "NF4ATTRDIR" },
+ { NF4NAMEDATTR, "NF4NAMEDATTR" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_lock_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree *newftree = NULL;
+ proto_item *fitem = NULL;
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 4, "Owner");
+
+ if (fitem)
+ {
+ newftree = proto_item_add_subtree(fitem, ett_nfs_lock_owner4);
+
+ if (newftree)
+ {
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
+ offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_pathname4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint32 comp_count, i;
+ proto_item *fitem = NULL;
+ proto_tree *newftree = NULL;
+
+ comp_count=tvb_get_ntohl(tvb, offset);
+ fitem = proto_tree_add_text(tree, tvb, offset, 4,
+ "pathname components (%u)", comp_count);
+ offset += 4;
+
+ if (fitem)
+ {
+ newftree = proto_item_add_subtree(fitem, ett_nfs_pathname4);
+
+ if (newftree)
+ {
+ for (i = 0; i < comp_count; i++)
+ offset = dissect_nfs_utf8string(tvb, offset, newftree,
+ hf_nfs_component4, NULL);
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_nfstime4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_nfstime4_seconds, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_nfstime4_nseconds, offset);
+
+ return offset;
+}
+
+static const value_string names_time_how4[] = {
+#define SET_TO_SERVER_TIME4 0
+ { SET_TO_SERVER_TIME4, "SET_TO_SERVER_TIME4" },
+#define SET_TO_CLIENT_TIME4 1
+ { SET_TO_CLIENT_TIME4, "SET_TO_CLIENT_TIME4" },
+ { 0, NULL },
+};
+
+static int
+dissect_nfs_settime4(tvbuff_t *tvb, int offset,
+ proto_tree *tree, char *name _U_)
+{
+ guint32 set_it;
+
+ set_it = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_nfs_time_how4, tvb, offset+0,
+ 4, set_it);
+ offset += 4;
+
+ if (set_it == SET_TO_CLIENT_TIME4)
+ offset = dissect_nfs_nfstime4(tvb, offset, tree);
+
+ return offset;
+}
+
+static int
+dissect_nfs_fsid4(tvbuff_t *tvb, int offset, proto_tree *tree, char *name)
+{
+ proto_tree *newftree = NULL;
+ proto_item *fitem = NULL;
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
+
+ if (fitem == NULL) return offset;
+
+ newftree = proto_item_add_subtree(fitem, ett_nfs_fsid4);
+
+ if (newftree == NULL) return offset;
+
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_fsid4_major,
+ offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_fsid4_minor,
+ offset);
+
+ return offset;
+}
+
+static const value_string names_acetype4[] = {
+#define ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000
+ { ACE4_ACCESS_ALLOWED_ACE_TYPE, "ACE4_ACCESS_ALLOWED_ACE_TYPE" },
+#define ACE4_ACCESS_DENIED_ACE_TYPE 0x00000001
+ { ACE4_ACCESS_DENIED_ACE_TYPE, "ACE4_ACCESS_DENIED_ACE_TYPE" },
+#define ACE4_SYSTEM_AUDIT_ACE_TYPE 0x00000002
+ { ACE4_SYSTEM_AUDIT_ACE_TYPE, "ACE4_SYSTEM_AUDIT_ACE_TYPE" },
+#define ACE4_SYSTEM_ALARM_ACE_TYPE 0x00000003
+ { ACE4_SYSTEM_ALARM_ACE_TYPE, "ACE4_SYSTEM_ALARM_ACE_TYPE" },
+ { 0, NULL }
+};
+
+/* ACE mask values */
+#define ACE4_READ_DATA 0x00000001
+#define ACE4_LIST_DIRECTORY 0x00000001
+#define ACE4_WRITE_DATA 0x00000002
+#define ACE4_ADD_FILE 0x00000002
+#define ACE4_APPEND_DATA 0x00000004
+#define ACE4_ADD_SUBDIRECTORY 0x00000004
+#define ACE4_READ_NAMED_ATTRS 0x00000008
+#define ACE4_WRITE_NAMED_ATTRS 0x00000010
+#define ACE4_EXECUTE 0x00000020
+#define ACE4_DELETE_CHILD 0x00000040
+#define ACE4_READ_ATTRIBUTES 0x00000080
+#define ACE4_WRITE_ATTRIBUTES 0x00000100
+#define ACE4_DELETE 0x00010000
+#define ACE4_READ_ACL 0x00020000
+#define ACE4_WRITE_ACL 0x00040000
+#define ACE4_WRITE_OWNER 0x00080000
+#define ACE4_SYNCHRONIZE 0x00100000
+
+static int
+dissect_nfs_acemask4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint32 acemask;
+ proto_item *acemask_item = NULL;
+ proto_tree *acemask_tree = NULL;
+
+ acemask = tvb_get_ntohl(tvb, offset);
+
+ acemask_item = proto_tree_add_text(tree, tvb, offset, 4,
+ "acemask: 0x%08x", acemask);
+
+ if (acemask_item)
+ acemask_tree = proto_item_add_subtree(acemask_item, ett_nfs_acemask4);
+
+ if (acemask_tree)
+ {
+ if (acemask & ACE4_READ_DATA)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_READ_DATA/ACE4_LIST_DIRECTORY (0x%08x)",
+ ACE4_READ_DATA);
+
+ if (acemask & ACE4_WRITE_DATA)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_WRITE_DATA/ACE4_ADD_FILE (0x%08x)",
+ ACE4_WRITE_DATA);
+
+ if (acemask & ACE4_APPEND_DATA)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_ADD_FILE/ACE4_ADD_SUBDIRECTORY (0x%08x)",
+ ACE4_APPEND_DATA);
+
+ if (acemask & ACE4_READ_NAMED_ATTRS)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_READ_NAMED_ATTRS (0x%08x)",
+ ACE4_READ_NAMED_ATTRS);
+
+ if (acemask & ACE4_WRITE_NAMED_ATTRS)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_WRITE_NAMED_ATTRS (0x%08x)",
+ ACE4_WRITE_NAMED_ATTRS);
+
+ if (acemask & ACE4_EXECUTE)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_EXECUTE (0x%08x)",
+ ACE4_EXECUTE);
+
+ if (acemask & ACE4_DELETE_CHILD)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_DELETE_CHILD (0x%08x)",
+ ACE4_DELETE_CHILD);
+
+ if (acemask & ACE4_READ_ATTRIBUTES)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_READ_ATTRIBUTES (0x%08x)",
+ ACE4_READ_ATTRIBUTES);
+
+ if (acemask & ACE4_WRITE_ATTRIBUTES)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_WRITE_ATTRIBUTES (0x%08x)",
+ ACE4_WRITE_ATTRIBUTES);
+
+ if (acemask & ACE4_DELETE)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_DELETE (0x%08x)",
+ ACE4_DELETE);
+
+ if (acemask & ACE4_READ_ACL)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_READ_ACL (0x%08x)",
+ ACE4_READ_ACL);
+
+ if (acemask & ACE4_WRITE_ACL)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_WRITE_ACL (0x%08x)",
+ ACE4_WRITE_ACL);
+
+ if (acemask & ACE4_WRITE_OWNER)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_WRITE_OWNER (0x%08x)",
+ ACE4_WRITE_OWNER);
+
+ if (acemask & ACE4_SYNCHRONIZE)
+ proto_tree_add_text(acemask_tree, tvb, offset, 4,
+ "ACE4_SYNCHRONIZE (0x%08x)",
+ ACE4_SYNCHRONIZE);
+ }
+
+ offset += 4;
+
+ return offset;
+}
+
+/* ACE flag values */
+#define ACE4_FILE_INHERIT_ACE 0x00000001
+#define ACE4_DIRECTORY_INHERIT_ACE 0x00000002
+#define ACE4_NO_PROPAGATE_INHERIT_ACE 0x00000004
+#define ACE4_INHERIT_ONLY_ACE 0x00000008
+#define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010
+#define ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020
+#define ACE4_IDENTIFIER_GROUP 0x00000040
+
+
+static int
+dissect_nfs_ace4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item* ace_item = NULL;
+ proto_tree* ace_tree = NULL;
+ proto_item *aceflag_item = NULL;
+ proto_tree *aceflag_tree = NULL;
+ guint32 aceflag4;
+
+ if (tree) {
+ ace_item = proto_tree_add_text(tree, tvb, offset, 4,
+ "ACE");
+
+ if (ace_item)
+ ace_tree = proto_item_add_subtree(ace_item, ett_nfs_ace4);
+ }
+
+ if (ace_tree) {
+ offset = dissect_rpc_uint32(tvb, ace_tree, hf_nfs_acetype4, offset);
+
+ aceflag4 = tvb_get_ntohl(tvb, offset);
+
+ aceflag_item = proto_tree_add_text(ace_tree, tvb, offset, 4,
+ "aceflag: 0x%08x", aceflag4);
+
+ if (aceflag_item)
+ {
+ aceflag_tree = proto_item_add_subtree(aceflag_item, ett_nfs_aceflag4);
+
+ if (aceflag_tree)
+ {
+ if (aceflag4 & ACE4_FILE_INHERIT_ACE)
+ proto_tree_add_text(aceflag_tree, tvb, offset, 4,
+ "ACE4_FILE_INHERIT_ACE (0x%08x)", ACE4_FILE_INHERIT_ACE);
+
+ if (aceflag4 & ACE4_DIRECTORY_INHERIT_ACE)
+ proto_tree_add_text(aceflag_tree, tvb, offset, 4,
+ "ACE4_DIRECTORY_INHERIT_ACE (0x%08x)",
+ ACE4_DIRECTORY_INHERIT_ACE);
+
+ if (aceflag4 & ACE4_INHERIT_ONLY_ACE)
+ proto_tree_add_text(aceflag_tree, tvb, offset, 4,
+ "ACE4_INHERIT_ONLY_ACE (0x%08x)",
+ ACE4_INHERIT_ONLY_ACE);
+
+ if (aceflag4 & ACE4_SUCCESSFUL_ACCESS_ACE_FLAG)
+ proto_tree_add_text(aceflag_tree, tvb, offset, 4,
+ "ACE4_SUCCESSFUL_ACCESS_ACE_FLAG (0x%08x)",
+ ACE4_SUCCESSFUL_ACCESS_ACE_FLAG);
+
+ if (aceflag4 & ACE4_FAILED_ACCESS_ACE_FLAG)
+ proto_tree_add_text(aceflag_tree, tvb, offset, 4,
+ "ACE4_FAILED_ACCESS_ACE_FLAG (0x%08x)",
+ ACE4_FAILED_ACCESS_ACE_FLAG);
+
+ if (aceflag4 & ACE4_IDENTIFIER_GROUP)
+ proto_tree_add_text(aceflag_tree, tvb, offset, 4,
+ "ACE4_IDENTIFIER_GROUP (0x%08x)",
+ ACE4_IDENTIFIER_GROUP);
+ }
+ }
+
+ offset += 4;
+
+ offset = dissect_nfs_acemask4(tvb, offset, ace_tree);
+
+ offset = dissect_nfs_utf8string(tvb, offset, ace_tree, hf_nfs_who, NULL);
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_fattr4_acl(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_rpc_array(tvb, pinfo, tree, offset, dissect_nfs_ace4,
+ hf_nfs_acl4);
+}
+
+static int
+dissect_nfs_fh4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, char *name)
+{
+ return dissect_nfs_fh3(tvb, offset, pinfo, tree, name, NULL);
+}
+
+static int
+dissect_nfs_fs_location4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree *newftree = NULL;
+ proto_item *fitem = NULL;
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 0, "rootpath");
+
+ if (fitem == NULL) return offset;
+
+ newftree = proto_item_add_subtree(fitem, ett_nfs_fs_location4);
+
+ if (newftree == NULL) return offset;
+
+ offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_server, NULL);
+
+ return offset;
+}
+
+static int
+dissect_nfs_fs_locations4(tvbuff_t *tvb, packet_info *pinfo, int offset,
+ proto_tree *tree, char *name)
+{
+ proto_tree *newftree = NULL;
+ proto_item *fitem = NULL;
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
+
+ if (fitem == NULL) return offset;
+
+ newftree = proto_item_add_subtree(fitem, ett_nfs_fs_locations4);
+
+ if (newftree == NULL) return offset;
+
+ offset = dissect_nfs_pathname4(tvb, offset, newftree);
+
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset,
+ dissect_nfs_fs_location4);
+
+ return offset;
+}
+
+static int
+dissect_nfs_mode4(tvbuff_t *tvb, int offset,
+ proto_tree *tree, char *name)
+{
+ return dissect_mode(tvb, offset, tree, name);
+}
+
+static const value_string nfs4_fattr4_fh_expire_type_names[] = {
+#define FH4_PERSISTENT 0x00000000
+ { FH4_PERSISTENT, "FH4_PERSISTENT" },
+#define FH4_NOEXPIRE_WITH_OPEN 0x00000001
+ { FH4_NOEXPIRE_WITH_OPEN, "FH4_NOEXPIRE_WITH_OPEN" },
+#define FH4_VOLATILE_ANY 0x00000002
+ { FH4_VOLATILE_ANY, "FH4_VOLATILE_ANY" },
+#define FH4_VOL_MIGRATION 0x00000004
+ { FH4_VOL_MIGRATION, "FH4_VOL_MIGRATION" },
+#define FH4_VOL_RENAME 0x00000008
+ { FH4_VOL_RENAME, "FH4_VOL_RENAME" },
+ { 0, NULL }
+};
+
+
+static int
+dissect_nfs_fattr4_fh_expire_type(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint32 expire_type;
+ proto_item *expire_type_item = NULL;
+ proto_tree *expire_type_tree = NULL;
+
+ expire_type = tvb_get_ntohl(tvb, offset + 0);
+
+ if (tree)
+ {
+ expire_type_item = proto_tree_add_text(tree, tvb, offset, 4,
+ "fattr4_fh_expire_type: 0x%08x", expire_type);
+ if (expire_type_item)
+ expire_type_tree = proto_item_add_subtree(expire_type_item,
+ ett_nfs_fattr4_fh_expire_type);
+ }
+
+ if (expire_type_tree)
+ {
+ if (expire_type == FH4_PERSISTENT)
+ {
+ proto_tree_add_text(expire_type_tree, tvb, offset, 4, "%s",
+ decode_enumerated_bitfield(expire_type, FH4_PERSISTENT, 8,
+ nfs4_fattr4_fh_expire_type_names, "%s"));
+ }
+ else
+ {
+ if (expire_type & FH4_NOEXPIRE_WITH_OPEN)
+ proto_tree_add_text(expire_type_tree, tvb, offset, 4,
+ "FH4_NOEXPIRE_WITH_OPEN (0x%08x)", FH4_NOEXPIRE_WITH_OPEN);
+
+ if (expire_type & FH4_VOLATILE_ANY)
+ proto_tree_add_text(expire_type_tree, tvb, offset, 4,
+ "FH4_VOLATILE_ANY (0x%08x)", FH4_VOLATILE_ANY);
+
+ if (expire_type & FH4_VOL_MIGRATION)
+ proto_tree_add_text(expire_type_tree, tvb, offset, 4,
+ "FH4_VOL_MIGRATION (0x%08x)", FH4_VOL_MIGRATION);
+
+ if (expire_type & FH4_VOL_RENAME)
+ proto_tree_add_text(expire_type_tree, tvb, offset, 4,
+ "FH4_VOL_RENAME (0x%08x)", FH4_VOL_RENAME);
+ }
+ }
+
+ offset += 4;
+
+ return offset;
+}
+
+static const value_string names_fattr4[] = {
+#define FATTR4_SUPPORTED_ATTRS 0
+ { FATTR4_SUPPORTED_ATTRS, "FATTR4_SUPPORTED_ATTRS" },
+#define FATTR4_TYPE 1
+ { FATTR4_TYPE, "FATTR4_TYPE" },
+#define FATTR4_FH_EXPIRE_TYPE 2
+ { FATTR4_FH_EXPIRE_TYPE, "FATTR4_FH_EXPIRE_TYPE" },
+#define FATTR4_CHANGE 3
+ { FATTR4_CHANGE, "FATTR4_CHANGE" },
+#define FATTR4_SIZE 4
+ { FATTR4_SIZE, "FATTR4_SIZE" },
+#define FATTR4_LINK_SUPPORT 5
+ { FATTR4_LINK_SUPPORT, "FATTR4_LINK_SUPPORT" },
+#define FATTR4_SYMLINK_SUPPORT 6
+ { FATTR4_SYMLINK_SUPPORT, "FATTR4_SYMLINK_SUPPORT" },
+#define FATTR4_NAMED_ATTR 7
+ { FATTR4_NAMED_ATTR, "FATTR4_NAMED_ATTR" },
+#define FATTR4_FSID 8
+ { FATTR4_FSID, "FATTR4_FSID" },
+#define FATTR4_UNIQUE_HANDLES 9
+ { FATTR4_UNIQUE_HANDLES, "FATTR4_UNIQUE_HANDLES" },
+#define FATTR4_LEASE_TIME 10
+ { FATTR4_LEASE_TIME, "FATTR4_LEASE_TIME" },
+#define FATTR4_RDATTR_ERROR 11
+ { FATTR4_RDATTR_ERROR, "FATTR4_RDATTR_ERROR" },
+#define FATTR4_ACL 12
+ { FATTR4_ACL, "FATTR4_ACL" },
+#define FATTR4_ACLSUPPORT 13
+ { FATTR4_ACLSUPPORT, "FATTR4_ACLSUPPORT" },
+#define FATTR4_ARCHIVE 14
+ { FATTR4_ARCHIVE, "FATTR4_ARCHIVE" },
+#define FATTR4_CANSETTIME 15
+ { FATTR4_CANSETTIME, "FATTR4_CANSETTIME" },
+#define FATTR4_CASE_INSENSITIVE 16
+ { FATTR4_CASE_INSENSITIVE, "FATTR4_CASE_INSENSITIVE" },
+#define FATTR4_CASE_PRESERVING 17
+ { FATTR4_CASE_PRESERVING, "FATTR4_CASE_PRESERVING" },
+#define FATTR4_CHOWN_RESTRICTED 18
+ { FATTR4_CHOWN_RESTRICTED, "FATTR4_CHOWN_RESTRICTED" },
+#define FATTR4_FILEHANDLE 19
+ { FATTR4_FILEHANDLE, "FATTR4_FILEHANDLE" },
+#define FATTR4_FILEID 20
+ { FATTR4_FILEID, "FATTR4_FILEID" },
+#define FATTR4_FILES_AVAIL 21
+ { FATTR4_FILES_AVAIL, "FATTR4_FILES_AVAIL" },
+#define FATTR4_FILES_FREE 22
+ { FATTR4_FILES_FREE, "FATTR4_FILES_FREE" },
+#define FATTR4_FILES_TOTAL 23
+ { FATTR4_FILES_TOTAL, "FATTR4_FILES_TOTAL" },
+#define FATTR4_FS_LOCATIONS 24
+ { FATTR4_FS_LOCATIONS, "FATTR4_FS_LOCATIONS" },
+#define FATTR4_HIDDEN 25
+ { FATTR4_HIDDEN, "FATTR4_HIDDEN" },
+#define FATTR4_HOMOGENEOUS 26
+ { FATTR4_HOMOGENEOUS, "FATTR4_HOMOGENEOUS" },
+#define FATTR4_MAXFILESIZE 27
+ { FATTR4_MAXFILESIZE, "FATTR4_MAXFILESIZE" },
+#define FATTR4_MAXLINK 28
+ { FATTR4_MAXLINK, "FATTR4_MAXLINK" },
+#define FATTR4_MAXNAME 29
+ { FATTR4_MAXNAME, "FATTR4_MAXNAME" },
+#define FATTR4_MAXREAD 30
+ { FATTR4_MAXREAD, "FATTR4_MAXREAD" },
+#define FATTR4_MAXWRITE 31
+ { FATTR4_MAXWRITE, "FATTR4_MAXWRITE" },
+#define FATTR4_MIMETYPE 32
+ { FATTR4_MIMETYPE, "FATTR4_MIMETYPE" },
+#define FATTR4_MODE 33
+ { FATTR4_MODE, "FATTR4_MODE" },
+#define FATTR4_NO_TRUNC 34
+ { FATTR4_NO_TRUNC, "FATTR4_NO_TRUNC" },
+#define FATTR4_NUMLINKS 35
+ { FATTR4_NUMLINKS, "FATTR4_NUMLINKS" },
+#define FATTR4_OWNER 36
+ { FATTR4_OWNER, "FATTR4_OWNER" },
+#define FATTR4_OWNER_GROUP 37
+ { FATTR4_OWNER_GROUP, "FATTR4_OWNER_GROUP" },
+#define FATTR4_QUOTA_AVAIL_HARD 38
+ { FATTR4_QUOTA_AVAIL_HARD, "FATTR4_QUOTA_AVAIL_HARD" },
+#define FATTR4_QUOTA_AVAIL_SOFT 39
+ { FATTR4_QUOTA_AVAIL_SOFT, "FATTR4_QUOTA_AVAIL_SOFT" },
+#define FATTR4_QUOTA_USED 40
+ { FATTR4_QUOTA_USED, "FATTR4_QUOTA_USED" },
+#define FATTR4_RAWDEV 41
+ { FATTR4_RAWDEV, "FATTR4_RAWDEV" },
+#define FATTR4_SPACE_AVAIL 42
+ { FATTR4_SPACE_AVAIL, "FATTR4_SPACE_AVAIL" },
+#define FATTR4_SPACE_FREE 43
+ { FATTR4_SPACE_FREE, "FATTR4_SPACE_FREE" },
+#define FATTR4_SPACE_TOTAL 44
+ { FATTR4_SPACE_TOTAL, "FATTR4_SPACE_TOTAL" },
+#define FATTR4_SPACE_USED 45
+ { FATTR4_SPACE_USED, "FATTR4_SPACE_USED" },
+#define FATTR4_SYSTEM 46
+ { FATTR4_SYSTEM, "FATTR4_SYSTEM" },
+#define FATTR4_TIME_ACCESS 47
+ { FATTR4_TIME_ACCESS, "FATTR4_TIME_ACCESS" },
+#define FATTR4_TIME_ACCESS_SET 48
+ { FATTR4_TIME_ACCESS_SET, "FATTR4_TIME_ACCESS_SET" },
+#define FATTR4_TIME_BACKUP 49
+ { FATTR4_TIME_BACKUP, "FATTR4_TIME_BACKUP" },
+#define FATTR4_TIME_CREATE 50
+ { FATTR4_TIME_CREATE, "FATTR4_TIME_CREATE" },
+#define FATTR4_TIME_DELTA 51
+ { FATTR4_TIME_DELTA, "FATTR4_TIME_DELTA" },
+#define FATTR4_TIME_METADATA 52
+ { FATTR4_TIME_METADATA, "FATTR4_TIME_METADATA" },
+#define FATTR4_TIME_MODIFY 53
+ { FATTR4_TIME_MODIFY, "FATTR4_TIME_MODIFY" },
+#define FATTR4_TIME_MODIFY_SET 54
+ { FATTR4_TIME_MODIFY_SET, "FATTR4_TIME_MODIFY_SET" },
+#define FATTR4_MOUNTED_ON_FILEID 55
+ { FATTR4_MOUNTED_ON_FILEID, "FATTR4_MOUNTED_ON_FILEID" },
+ { 0, NULL }
+};
+
+#define FATTR4_BITMAP_ONLY 0
+#define FATTR4_FULL_DISSECT 1
+
+static int
+dissect_nfs_attributes(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, int type)
+{
+ guint32 bitmap_len;
+ proto_item *fitem = NULL;
+ proto_tree *newftree = NULL;
+ proto_item *attr_fitem = NULL;
+ proto_tree *attr_newftree = NULL;
+ guint32 i;
+ gint j;
+ guint32 fattr;
+ guint32 *bitmap;
+ guint32 sl;
+ int attr_vals_offset;
+
+ bitmap_len = tvb_get_ntohl(tvb, offset);
+ tvb_ensure_bytes_exist(tvb, offset, 4 + bitmap_len * 4);
+ fitem = proto_tree_add_text(tree, tvb, offset, 4 + bitmap_len * 4,
+ "%s", "attrmask");
+ offset += 4;
+
+ if (fitem == NULL) return offset;
+
+ newftree = proto_item_add_subtree(fitem, ett_nfs_bitmap4);
+
+ if (newftree == NULL) return offset;
+
+ attr_vals_offset = offset + 4 + bitmap_len * 4;
+
+ bitmap = g_malloc(bitmap_len * sizeof(guint32));
+ if (bitmap == NULL) return offset;
+
+ for (i = 0; i < bitmap_len; i++)
+ {
+ bitmap[i] = tvb_get_ntohl(tvb, offset);
+
+ sl = 0x00000001;
+
+ for (j = 0; j < 32; j++)
+ {
+ fattr = 32 * i + j;
+
+ if (bitmap[i] & sl)
+ {
+ /* switch label if attribute is recommended vs. mandatory */
+ attr_fitem = proto_tree_add_uint(newftree,
+ (fattr < FATTR4_ACL)? hf_nfs_mand_attr: hf_nfs_recc_attr,
+ tvb, offset, 4, fattr);
+
+ if (attr_fitem == NULL) break;
+
+ attr_newftree = proto_item_add_subtree(attr_fitem, ett_nfs_bitmap4);
+
+ if (attr_newftree == NULL) break;
+
+ if (type == FATTR4_FULL_DISSECT)
+ {
+ /* do a full decode of the arguments for the set flag */
+ switch(fattr)
+ {
+ case FATTR4_SUPPORTED_ATTRS:
+ attr_vals_offset = dissect_nfs_attributes(tvb,
+ attr_vals_offset, pinfo, attr_newftree,
+ FATTR4_BITMAP_ONLY);
+ break;
+
+ case FATTR4_TYPE:
+ attr_vals_offset = dissect_rpc_uint32(tvb,
+ attr_newftree, hf_nfs_ftype4, attr_vals_offset);
+ break;
+
+ case FATTR4_FH_EXPIRE_TYPE:
+ attr_vals_offset = dissect_nfs_fattr4_fh_expire_type(tvb,
+ attr_vals_offset, attr_newftree);
+ break;
+
+ case FATTR4_CHANGE:
+ attr_vals_offset = dissect_rpc_uint64(tvb, attr_newftree,
+ hf_nfs_changeid4, attr_vals_offset);
+ break;
+
+ case FATTR4_SIZE:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_size, attr_vals_offset);
+ break;
+
+ case FATTR4_LINK_SUPPORT:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_link_support,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_SYMLINK_SUPPORT:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_symlink_support,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_NAMED_ATTR:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_named_attr, attr_vals_offset);
+ break;
+
+ case FATTR4_FSID:
+ attr_vals_offset = dissect_nfs_fsid4(tvb, attr_vals_offset,
+ attr_newftree, "fattr4_fsid");
+ break;
+
+ case FATTR4_UNIQUE_HANDLES:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_unique_handles,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_LEASE_TIME:
+ attr_vals_offset = dissect_rpc_uint32(tvb,
+ attr_newftree, hf_nfs_fattr4_lease_time,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_RDATTR_ERROR:
+ attr_vals_offset = dissect_nfs_nfsstat4(tvb,
+ attr_vals_offset, attr_newftree, NULL);
+ break;
+
+ case FATTR4_ACL:
+ attr_vals_offset = dissect_nfs_fattr4_acl(tvb,
+ attr_vals_offset, pinfo, attr_newftree);
+ break;
+
+ case FATTR4_ACLSUPPORT:
+ attr_vals_offset = dissect_rpc_uint32(tvb,
+ attr_newftree, hf_nfs_fattr4_aclsupport,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_ARCHIVE:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_archive,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_CANSETTIME:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_cansettime, attr_vals_offset);
+ break;
+
+ case FATTR4_CASE_INSENSITIVE:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_case_insensitive,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_CASE_PRESERVING:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_case_preserving,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_CHOWN_RESTRICTED:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_chown_restricted,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_FILEID:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_fileid, attr_vals_offset);
+ break;
+
+ case FATTR4_FILES_AVAIL:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_files_avail,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_FILEHANDLE:
+ attr_vals_offset = dissect_nfs_fh4(tvb, attr_vals_offset,
+ pinfo, attr_newftree, "fattr4_filehandle");
+ break;
+
+ case FATTR4_FILES_FREE:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_files_free, attr_vals_offset);
+ break;
+
+ case FATTR4_FILES_TOTAL:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_files_total,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_FS_LOCATIONS:
+ attr_vals_offset = dissect_nfs_fs_locations4(tvb, pinfo,
+ attr_vals_offset, attr_newftree,
+ "fattr4_fs_locations");
+ break;
+
+ case FATTR4_HIDDEN:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_hidden, attr_vals_offset);
+ break;
+
+ case FATTR4_HOMOGENEOUS:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_homogeneous,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_MAXFILESIZE:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_maxfilesize,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_MAXLINK:
+ attr_vals_offset = dissect_rpc_uint32(tvb,
+ attr_newftree, hf_nfs_fattr4_maxlink, attr_vals_offset);
+ break;
+
+ case FATTR4_MAXNAME:
+ attr_vals_offset = dissect_rpc_uint32(tvb,
+ attr_newftree, hf_nfs_fattr4_maxname, attr_vals_offset);
+ break;
+
+ case FATTR4_MAXREAD:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_maxread, attr_vals_offset);
+ break;
+
+ case FATTR4_MAXWRITE:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_maxwrite, attr_vals_offset);
+ break;
+
+ case FATTR4_MIMETYPE:
+ attr_vals_offset = dissect_nfs_utf8string(tvb,
+ attr_vals_offset, attr_newftree,
+ hf_nfs_fattr4_mimetype, NULL);
+ break;
+
+ case FATTR4_MODE:
+ attr_vals_offset = dissect_nfs_mode4(tvb,
+ attr_vals_offset, attr_newftree, "fattr4_mode");
+ break;
+
+ case FATTR4_NO_TRUNC:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_no_trunc, attr_vals_offset);
+ break;
+
+ case FATTR4_NUMLINKS:
+ attr_vals_offset = dissect_rpc_uint32(tvb,
+ attr_newftree, hf_nfs_fattr4_numlinks, attr_vals_offset);
+ break;
+
+ case FATTR4_OWNER:
+ attr_vals_offset = dissect_nfs_utf8string(tvb,
+ attr_vals_offset, attr_newftree,
+ hf_nfs_fattr4_owner,
+ NULL);
+ break;
+
+ case FATTR4_OWNER_GROUP:
+ attr_vals_offset = dissect_nfs_utf8string(tvb,
+ attr_vals_offset, attr_newftree,
+ hf_nfs_fattr4_owner_group, NULL);
+ break;
+
+ case FATTR4_QUOTA_AVAIL_HARD:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_quota_hard, attr_vals_offset);
+ break;
+
+ case FATTR4_QUOTA_AVAIL_SOFT:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_quota_soft, attr_vals_offset);
+ break;
+
+ case FATTR4_QUOTA_USED:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_quota_used, attr_vals_offset);
+ break;
+
+ case FATTR4_RAWDEV:
+ attr_vals_offset = dissect_nfs_specdata4(tvb,
+ attr_vals_offset, attr_newftree);
+ break;
+
+ case FATTR4_SPACE_AVAIL:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_space_avail,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_SPACE_FREE:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_space_free, attr_vals_offset);
+ break;
+
+ case FATTR4_SPACE_TOTAL:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_space_total,
+ attr_vals_offset);
+ break;
+
+ case FATTR4_SPACE_USED:
+ attr_vals_offset = dissect_rpc_uint64(tvb,
+ attr_newftree, hf_nfs_fattr4_space_used, attr_vals_offset);
+ break;
+
+ case FATTR4_SYSTEM:
+ attr_vals_offset = dissect_rpc_bool(tvb,
+ attr_newftree, hf_nfs_fattr4_system, attr_vals_offset);
+ break;
+
+ case FATTR4_TIME_ACCESS:
+ case FATTR4_TIME_BACKUP:
+ case FATTR4_TIME_CREATE:
+ case FATTR4_TIME_DELTA:
+ case FATTR4_TIME_METADATA:
+ case FATTR4_TIME_MODIFY:
+ attr_vals_offset = dissect_nfs_nfstime4(tvb, attr_vals_offset,
+ attr_newftree);
+ break;
+
+ case FATTR4_TIME_ACCESS_SET:
+ case FATTR4_TIME_MODIFY_SET:
+ attr_vals_offset = dissect_nfs_settime4(tvb,
+ attr_vals_offset, attr_newftree, "settime4");
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ sl <<= 1;
+ }
+
+ offset += 4;
+ }
+
+ g_free(bitmap);
+
+ return offset;
+}
+
+static int
+dissect_nfs_fattr4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_tree *newftree = NULL;
+ proto_item *fitem = NULL;
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 4, "obj_attributes");
+
+ if (fitem == NULL) return offset;
+
+ newftree = proto_item_add_subtree(fitem, ett_nfs_fattr4);
+
+ if (newftree == NULL) return offset;
+
+ offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
+ FATTR4_FULL_DISSECT);
+
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_attrlist4);
+
+ return offset;
+}
+
+static const value_string names_open4_share_access[] = {
+#define OPEN4_SHARE_ACCESS_READ 0x00000001
+ { OPEN4_SHARE_ACCESS_READ, "OPEN4_SHARE_ACCESS_READ" },
+#define OPEN4_SHARE_ACCESS_WRITE 0x00000002
+ { OPEN4_SHARE_ACCESS_WRITE, "OPEN4_SHARE_ACCESS_WRITE" },
+#define OPEN4_SHARE_ACCESS_BOTH 0x00000003
+ { OPEN4_SHARE_ACCESS_BOTH, "OPEN4_SHARE_ACCESS_BOTH" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_open4_share_access(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+ guint share_access;
+
+ share_access = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_nfs_open4_share_access, tvb, offset, 4,
+ share_access);
+ offset += 4;
+
+ return offset;
+}
+
+static const value_string names_open4_share_deny[] = {
+#define OPEN4_SHARE_DENY_NONE 0x00000000
+ { OPEN4_SHARE_DENY_NONE, "OPEN4_SHARE_DENY_NONE" },
+#define OPEN4_SHARE_DENY_READ 0x00000001
+ { OPEN4_SHARE_DENY_READ, "OPEN4_SHARE_DENY_READ" },
+#define OPEN4_SHARE_DENY_WRITE 0x00000002
+ { OPEN4_SHARE_DENY_WRITE, "OPEN4_SHARE_DENY_WRITE" },
+#define OPEN4_SHARE_DENY_BOTH 0x00000003
+ { OPEN4_SHARE_DENY_BOTH, "OPEN4_SHARE_DENY_BOTH" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_open4_share_deny(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+ guint deny_access;
+
+ deny_access = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_nfs_open4_share_deny, tvb, offset, 4,
+ deny_access);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_nfs_open_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_clientid4, offset);
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_open_owner4);
+
+ return offset;
+}
+
+static int
+dissect_nfs_open_claim_delegate_cur4(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+ offset = dissect_rpc_uint64(tvb, tree,
+ hf_nfs_stateid4_delegate_stateid, offset);
+ offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_component4, NULL);
+
+ return offset;
+}
+
+#define CLAIM_NULL 0
+#define CLAIM_PREVIOUS 1
+#define CLAIM_DELEGATE_CUR 2
+#define CLAIM_DELEGATE_PREV 3
+
+static const value_string names_claim_type4[] = {
+ { CLAIM_NULL, "CLAIM_NULL" },
+ { CLAIM_PREVIOUS, "CLAIM_PREVIOUS" },
+ { CLAIM_DELEGATE_CUR, "CLAIM_DELEGATE_CUR" },
+ { CLAIM_DELEGATE_PREV, "CLAIM_DELEGATE_PREV" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_open_claim4(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+ guint open_claim_type4;
+ proto_item *fitem = NULL;
+ proto_tree *newftree = NULL;
+
+ open_claim_type4 = tvb_get_ntohl(tvb, offset);
+ fitem = proto_tree_add_uint(tree, hf_nfs_open_claim_type4, tvb,
+ offset+0, 4, open_claim_type4);
+ offset += 4;
+
+ if (fitem) {
+ newftree = proto_item_add_subtree(fitem, ett_nfs_open_claim4);
+
+ if (newftree) {
+
+ switch(open_claim_type4)
+ {
+ case CLAIM_NULL:
+ offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, NULL);
+ break;
+
+ case CLAIM_PREVIOUS:
+ offset = dissect_rpc_uint32(tvb, newftree,
+ hf_nfs_delegate_type, offset);
+ break;
+
+ case CLAIM_DELEGATE_CUR:
+ offset = dissect_nfs_open_claim_delegate_cur4(tvb, offset,
+ newftree);
+ break;
+
+ case CLAIM_DELEGATE_PREV:
+ offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, NULL);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_createhow4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint mode;
+
+ /* This is intentional; we're using the same flags as NFSv3 */
+ mode = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_nfs_createmode3, tvb, offset, 4, mode);
+ offset += 4;
+
+ switch(mode)
+ {
+ case UNCHECKED: /* UNCHECKED4 */
+ case GUARDED: /* GUARDED4 */
+ offset = dissect_nfs_fattr4(tvb, offset, pinfo, tree);
+ break;
+
+ case EXCLUSIVE: /* EXCLUSIVE4 */
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_verifier4, offset);
+ break;
+
+ default:
+ break;
+ }
+
+ return offset;
+}
+
+#define OPEN4_NOCREATE 0
+#define OPEN4_CREATE 1
+static const value_string names_opentype4[] = {
+ { OPEN4_NOCREATE, "OPEN4_NOCREATE" },
+ { OPEN4_CREATE, "OPEN4_CREATE" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_openflag4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint opentype4;
+ proto_item *fitem = NULL;
+ proto_tree *newftree = NULL;
+
+ opentype4 = tvb_get_ntohl(tvb, offset);
+ fitem = proto_tree_add_uint(tree, hf_nfs_opentype4, tvb,
+ offset+0, 4, opentype4);
+ offset += 4;
+
+ if (fitem) {
+ newftree = proto_item_add_subtree(fitem, ett_nfs_opentype4);
+
+ if (newftree) {
+
+ switch(opentype4)
+ {
+ case OPEN4_CREATE:
+ offset = dissect_nfs_createhow4(tvb, offset, pinfo, newftree);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_clientaddr4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_r_netid);
+ offset = dissect_nfsdata(tvb, offset, tree, hf_nfs_r_addr);
+
+ return offset;
+}
+
+
+static int
+dissect_nfs_cb_client4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree *cb_location = NULL;
+ proto_item *fitem = NULL;
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_cb_program, offset);
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 0, "cb_location");
+
+ if (fitem)
+ {
+ cb_location = proto_item_add_subtree(fitem, ett_nfs_clientaddr4);
+
+ offset = dissect_nfs_clientaddr4(tvb, offset, cb_location);
+ }
+
+ return offset;
+}
+
+static const value_string names_stable_how4[] = {
+#define UNSTABLE4 0
+ { UNSTABLE4, "UNSTABLE4" },
+#define DATA_SYNC4 1
+ { DATA_SYNC4, "DATA_SYNC4" },
+#define FILE_SYNC4 2
+ { FILE_SYNC4, "FILE_SYNC4" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_stable_how4(tvbuff_t *tvb, int offset,
+ proto_tree *tree, char *name)
+{
+ guint stable_how4;
+
+ stable_how4 = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_nfs_stable_how4, tvb,
+ offset+0, 4, stable_how4, "%s: %s (%u)", name,
+ val_to_str(stable_how4, names_stable_how4, "%u"), stable_how4);
+ offset += 4;
+
+ return offset;
+}
+
+static const value_string names_nfsv4_operation[] = {
+ { NFS4_OP_ACCESS, "ACCESS" },
+ { NFS4_OP_CLOSE, "CLOSE" },
+ { NFS4_OP_COMMIT, "COMMIT" },
+ { NFS4_OP_CREATE, "CREATE" },
+ { NFS4_OP_DELEGPURGE, "DELEGPURGE" },
+ { NFS4_OP_DELEGRETURN, "DELEGRETURN" },
+ { NFS4_OP_GETATTR, "GETATTR" },
+ { NFS4_OP_GETFH, "GETFH" },
+ { NFS4_OP_LINK, "LINK" },
+ { NFS4_OP_LOCK, "LOCK" },
+ { NFS4_OP_LOCKT, "LOCKT" },
+ { NFS4_OP_LOCKU, "LOCKU" },
+ { NFS4_OP_LOOKUP, "LOOKUP" },
+ { NFS4_OP_LOOKUPP, "LOOKUPP" },
+ { NFS4_OP_NVERIFY, "NVERIFY" },
+ { NFS4_OP_OPEN, "OPEN" },
+ { NFS4_OP_OPENATTR, "OPENATTR" },
+ { NFS4_OP_OPEN_CONFIRM, "OPEN_CONFIRM" },
+ { NFS4_OP_OPEN_DOWNGRADE, "OPEN_DOWNGRADE" },
+ { NFS4_OP_PUTFH, "PUTFH" },
+ { NFS4_OP_PUTPUBFH, "PUTPUBFH" },
+ { NFS4_OP_PUTROOTFH, "PUTROOTFH" },
+ { NFS4_OP_READ, "READ" },
+ { NFS4_OP_READDIR, "READDIR" },
+ { NFS4_OP_READLINK, "READLINK" },
+ { NFS4_OP_REMOVE, "REMOVE" },
+ { NFS4_OP_RENAME, "RENAME" },
+ { NFS4_OP_RENEW, "RENEW" },
+ { NFS4_OP_RESTOREFH, "RESTOREFH" },
+ { NFS4_OP_SAVEFH, "SAVEFH" },
+ { NFS4_OP_SECINFO, "SECINFO" },
+ { NFS4_OP_SETATTR, "SETATTR" },
+ { NFS4_OP_SETCLIENTID, "SETCLIENTID" },
+ { NFS4_OP_SETCLIENTID_CONFIRM, "SETCLIENTID_CONFIRM" },
+ { NFS4_OP_VERIFY, "VERIFY" },
+ { NFS4_OP_WRITE, "WRITE" },
+ { NFS4_OP_RELEASE_LOCKOWNER, "RELEASE_LOCKOWNER" },
+ { NFS4_OP_ILLEGAL, "ILLEGAL" },
+ { 0, NULL }
+};
+
+gint *nfsv4_operation_ett[] =
+{
+ &ett_nfs_access4 ,
+ &ett_nfs_close4 ,
+ &ett_nfs_commit4 ,
+ &ett_nfs_create4 ,
+ &ett_nfs_delegpurge4 ,
+ &ett_nfs_delegreturn4 ,
+ &ett_nfs_getattr4 ,
+ &ett_nfs_getfh4 ,
+ &ett_nfs_link4 ,
+ &ett_nfs_lock4 ,
+ &ett_nfs_lockt4 ,
+ &ett_nfs_locku4 ,
+ &ett_nfs_lookup4 ,
+ &ett_nfs_lookupp4 ,
+ &ett_nfs_nverify4 ,
+ &ett_nfs_open4 ,
+ &ett_nfs_openattr4 ,
+ &ett_nfs_open_confirm4 ,
+ &ett_nfs_open_downgrade4 ,
+ &ett_nfs_putfh4 ,
+ &ett_nfs_putpubfh4 ,
+ &ett_nfs_putrootfh4 ,
+ &ett_nfs_read4 ,
+ &ett_nfs_readdir4 ,
+ &ett_nfs_readlink4 ,
+ &ett_nfs_remove4 ,
+ &ett_nfs_rename4 ,
+ &ett_nfs_renew4 ,
+ &ett_nfs_restorefh4 ,
+ &ett_nfs_savefh4 ,
+ &ett_nfs_secinfo4 ,
+ &ett_nfs_setattr4 ,
+ &ett_nfs_setclientid4 ,
+ &ett_nfs_setclientid_confirm4 ,
+ &ett_nfs_verify4 ,
+ &ett_nfs_write4,
+ &ett_nfs_release_lockowner4,
+};
+
+static int
+dissect_nfs_entry4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_cookie4, offset);
+ offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_component4, NULL);
+ offset = dissect_nfs_fattr4(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+static int
+dissect_nfs_dirlist4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_tree *newftree = NULL;
+
+ newftree = proto_item_add_subtree(tree, ett_nfs_dirlist4);
+ if (newftree==NULL) return offset;
+
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_nfs_entry4);
+ offset = dissect_rpc_bool(tvb, newftree, hf_nfs_dirlist4_eof, offset);
+
+ return offset;
+}
+
+static int
+dissect_nfs_change_info4(tvbuff_t *tvb, int offset,
+ proto_tree *tree, char *name)
+{
+ proto_tree *newftree = NULL;
+ proto_tree *fitem = NULL;
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 0, "%s", name);
+
+ if (fitem) {
+ newftree = proto_item_add_subtree(fitem, ett_nfs_change_info4);
+
+ if (newftree) {
+ offset = dissect_rpc_bool(tvb, newftree,
+ hf_nfs_change_info4_atomic, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_changeid4_before,
+ offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_changeid4_after,
+ offset);
+ }
+ }
+
+ return offset;
+}
+
+static const value_string names_nfs_lock_type4[] =
+{
+#define READ_LT 1
+ { READ_LT, "READ_LT" },
+#define WRITE_LT 2
+ { WRITE_LT, "WRITE_LT" },
+#define READW_LT 3
+ { READW_LT, "READW_LT" },
+#define WRITEW_LT 4
+ { WRITEW_LT, "WRITEW_LT" },
+#define RELEASE_STATE 5
+ { RELEASE_STATE, "RELEASE_STATE" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_lock4denied(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_offset4, offset);
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_length4, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_lock_type4, offset);
+ offset = dissect_nfs_lock_owner4(tvb, offset, tree);
+
+ return offset;
+}
+
+
+static const value_string names_open4_result_flags[] = {
+#define OPEN4_RESULT_MLOCK 0x00000001
+ { OPEN4_RESULT_MLOCK, "OPEN4_RESULT_MLOCK" },
+#define OPEN4_RESULT_CONFIRM 0x00000002
+ { OPEN4_RESULT_CONFIRM, "OPEN4_RESULT_CONFIRM" },
+#define OPEN4_RESULT_LOCKTYPE_POSIX 0x00000004
+ { OPEN4_RESULT_LOCKTYPE_POSIX, "OPEN4_RESULT_LOCKTYPE_POSIX" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_open4_rflags(tvbuff_t *tvb, int offset,
+ proto_tree *tree, char *name)
+{
+ guint rflags;
+ proto_item *rflags_item = NULL;
+ proto_item *rflags_tree = NULL;
+
+ rflags = tvb_get_ntohl(tvb, offset);
+
+ if (tree)
+ {
+ rflags_item = proto_tree_add_text(tree, tvb, offset, 4,
+ "%s: 0x%08x", name, rflags);
+
+ if (rflags_item)
+ {
+ rflags_tree = proto_item_add_subtree(rflags_item,
+ ett_nfs_open4_result_flags);
+
+ if (rflags_tree)
+ {
+ proto_tree_add_text(rflags_tree, tvb, offset, 4, "%s",
+ decode_enumerated_bitfield(rflags, OPEN4_RESULT_MLOCK, 2,
+ names_open4_result_flags, "%s"));
+
+ proto_tree_add_text(rflags_tree, tvb, offset, 4, "%s",
+ decode_enumerated_bitfield(rflags, OPEN4_RESULT_CONFIRM, 2,
+ names_open4_result_flags, "%s"));
+ }
+ }
+ }
+
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_nfs_stateid4(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+ proto_item *fitem = NULL;
+ proto_tree *newftree = NULL;
+ int sublen;
+ int bytes_left;
+ gboolean first_line;
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 4, "stateid");
+
+ if (fitem) {
+ newftree = proto_item_add_subtree(fitem, ett_nfs_stateid4);
+ if (newftree) {
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
+ offset);
+
+ bytes_left = 12;
+ first_line = TRUE;
+
+ while (bytes_left != 0)
+ {
+ sublen = 12;
+ if (sublen > bytes_left)
+ sublen = bytes_left;
+
+ proto_tree_add_text(newftree, tvb, offset, sublen, "%s%s",
+ first_line ? "other: " : " ",
+ tvb_bytes_to_str(tvb, offset, sublen));
+
+ bytes_left -= sublen;
+ offset += sublen;
+ first_line = FALSE;
+ }
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_open_read_delegation4(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_nfs_stateid4(tvb, offset, tree);
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs_recall4, offset);
+ offset = dissect_nfs_ace4(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+static int
+dissect_nfs_modified_limit4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_num_blocks, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_bytes_per_block, offset);
+
+ return offset;
+}
+
+#define NFS_LIMIT_SIZE 1
+#define NFS_LIMIT_BLOCKS 2
+static const value_string names_limit_by4[] = {
+ { NFS_LIMIT_SIZE, "NFS_LIMIT_SIZE" },
+ { NFS_LIMIT_BLOCKS, "NFS_LIMIT_BLOCKS" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_space_limit4(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+ guint limitby;
+
+ limitby = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_nfs_limit_by4, tvb, offset+0, 4, limitby);
+ offset += 4;
+
+ switch(limitby)
+ {
+ case NFS_LIMIT_SIZE:
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_filesize,
+ offset);
+ break;
+
+ case NFS_LIMIT_BLOCKS:
+ offset = dissect_nfs_modified_limit4(tvb, offset, tree);
+ break;
+
+ default:
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_open_write_delegation4(tvbuff_t *tvb, int offset,
+ packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_nfs_stateid4(tvb, offset, tree);
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs_recall, offset);
+ offset = dissect_nfs_space_limit4(tvb, offset, tree);
+ offset = dissect_nfs_ace4(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+#define OPEN_DELEGATE_NONE 0
+#define OPEN_DELEGATE_READ 1
+#define OPEN_DELEGATE_WRITE 2
+static const value_string names_open_delegation_type4[] = {
+ { OPEN_DELEGATE_NONE, "OPEN_DELEGATE_NONE" },
+ { OPEN_DELEGATE_READ, "OPEN_DELEGATE_READ" },
+ { OPEN_DELEGATE_WRITE, "OPEN_DELEGATE_WRITE" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfs_open_delegation4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint delegation_type;
+ proto_tree *newftree = NULL;
+ proto_item *fitem = NULL;
+
+ delegation_type = tvb_get_ntohl(tvb, offset);
+ fitem = proto_tree_add_uint(tree, hf_nfs_open_delegation_type4, tvb,
+ offset+0, 4, delegation_type);
+ offset += 4;
+
+ if (fitem) {
+ newftree = proto_item_add_subtree(fitem, ett_nfs_open_delegation4);
+
+ switch(delegation_type)
+ {
+ case OPEN_DELEGATE_NONE:
+ break;
+
+ case OPEN_DELEGATE_READ:
+ offset = dissect_nfs_open_read_delegation4(tvb, offset, pinfo,
+ newftree);
+ break;
+
+ case OPEN_DELEGATE_WRITE:
+ offset = dissect_nfs_open_write_delegation4(tvb, offset, pinfo,
+ newftree);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_rpcsec_gss_info(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
+ hf_nfs_sec_oid4, FALSE, 0, FALSE, NULL, NULL);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_qop4, offset);
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nfs_secinfo_rpcsec_gss_info_service, offset);
+
+ return offset;
+}
+
+static int
+dissect_nfs_open_to_lock_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_seqid4, offset);
+ offset = dissect_nfs_stateid4(tvb, offset, tree);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_lock_seqid4, offset);
+ offset = dissect_nfs_lock_owner4(tvb, offset, tree);
+
+ return offset;
+}
+
+static int
+dissect_nfs_exist_lock_owner4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_nfs_stateid4(tvb, offset, tree);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_lock_seqid4, offset);
+
+ return offset;
+}
+
+static int
+dissect_nfs_locker4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint new_lock_owner;
+
+ new_lock_owner = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nfs_new_lock_owner, offset);
+
+ if (new_lock_owner)
+ offset = dissect_nfs_open_to_lock_owner4(tvb, offset, tree);
+ else
+ offset = dissect_nfs_exist_lock_owner4(tvb, offset, tree);
+
+ return offset;
+}
+
+static int
+dissect_nfs_client_id4(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ offset = dissect_rpc_uint64(tvb, tree, hf_nfs_verifier4, offset);
+ offset = dissect_rpc_data(tvb, tree, hf_nfs_client_id4_id, offset);
+
+ return offset;
+}
+
+static int
+dissect_nfs_argop4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 ops, ops_counter;
+ guint opcode;
+ proto_item *fitem;
+ proto_tree *ftree = NULL;
+ proto_tree *newftree = NULL;
+
+ ops = tvb_get_ntohl(tvb, offset+0);
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 4,
+ "Operations (count: %u)", ops);
+ offset += 4;
+
+ if (fitem == NULL) return offset;
+
+ ftree = proto_item_add_subtree(fitem, ett_nfs_argop4);
+
+ if (ftree == NULL) return offset;
+
+ for (ops_counter=0; ops_counter<ops; ops_counter++)
+ {
+ opcode = tvb_get_ntohl(tvb, offset);
+
+ fitem = proto_tree_add_uint(ftree, hf_nfs_argop4, tvb, offset, 4,
+ opcode);
+ offset += 4;
+
+ /* the opcodes are not contiguous */
+ if ((opcode < NFS4_OP_ACCESS || opcode > NFS4_OP_WRITE) &&
+ (opcode != NFS4_OP_ILLEGAL))
+ break;
+
+ if (fitem == NULL) break;
+
+ /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
+ if (opcode == NFS4_OP_ILLEGAL)
+ newftree = proto_item_add_subtree(fitem, ett_nfs_illegal4);
+ else
+ newftree = proto_item_add_subtree(fitem,
+ *nfsv4_operation_ett[opcode - 3]);
+
+ if (newftree == NULL) break;
+
+ switch(opcode)
+ {
+ case NFS4_OP_ACCESS:
+ offset = dissect_access(tvb, offset, newftree, "access");
+ break;
+
+ case NFS4_OP_CLOSE:
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
+ offset);
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_COMMIT:
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4,
+ offset);
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4,
+ offset);
+ break;
+
+ case NFS4_OP_CREATE:
+ {
+ guint create_type;
+
+ create_type = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_ftype4,
+ offset);
+
+ switch(create_type)
+ {
+ case NF4LNK:
+ offset = dissect_nfs_utf8string(tvb, offset, newftree,
+ hf_nfs_linktext4, NULL);
+ break;
+
+ case NF4BLK:
+ case NF4CHR:
+ offset = dissect_nfs_specdata4(tvb, offset, newftree);
+ break;
+
+ case NF4SOCK:
+ case NF4FIFO:
+ case NF4DIR:
+ break;
+
+ default:
+ break;
+ }
+
+ offset = dissect_nfs_utf8string(tvb, offset, newftree, hf_nfs_component4, NULL);
+
+ offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
+ }
+ break;
+
+ case NFS4_OP_DELEGPURGE:
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
+ break;
+
+ case NFS4_OP_DELEGRETURN:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_GETATTR:
+ offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
+ FATTR4_BITMAP_ONLY);
+ break;
+
+ case NFS4_OP_GETFH:
+ break;
+
+ case NFS4_OP_LINK:
+ offset = dissect_nfs_utf8string(tvb, offset, newftree,
+ hf_nfs_component4, NULL);
+ break;
+
+ case NFS4_OP_LOCK:
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_lock_type4, offset);
+ offset = dissect_rpc_bool(tvb, newftree, hf_nfs_lock4_reclaim, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
+ offset = dissect_nfs_locker4(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_LOCKT:
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_lock_type4, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
+ offset = dissect_nfs_lock_owner4(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_LOCKU:
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_lock_type4, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_seqid4, offset);
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_length4, offset);
+ break;
+
+ case NFS4_OP_LOOKUP:
+ offset = dissect_nfs_utf8string(tvb, offset, newftree,
+ hf_nfs_component4, NULL);
+ break;
+
+ case NFS4_OP_LOOKUPP:
+ break;
+
+ case NFS4_OP_NVERIFY:
+ offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
+ break;
+
+ case NFS4_OP_OPEN:
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
+ offset);
+ offset = dissect_nfs_open4_share_access(tvb, offset, newftree);
+ offset = dissect_nfs_open4_share_deny(tvb, offset, newftree);
+ offset = dissect_nfs_open_owner4(tvb, offset, newftree);
+ offset = dissect_nfs_openflag4(tvb, offset, pinfo, newftree);
+ offset = dissect_nfs_open_claim4(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_OPENATTR:
+ offset = dissect_rpc_bool(tvb, newftree, hf_nfs_attrdircreate,
+ offset);
+ break;
+
+ case NFS4_OP_OPEN_CONFIRM:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
+ offset);
+ break;
+
+ case NFS4_OP_OPEN_DOWNGRADE:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_seqid4,
+ offset);
+ offset = dissect_nfs_open4_share_access(tvb, offset, newftree);
+ offset = dissect_nfs_open4_share_deny(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_PUTFH:
+ offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "filehandle");
+ break;
+
+ case NFS4_OP_PUTPUBFH:
+ case NFS4_OP_PUTROOTFH:
+ break;
+
+ case NFS4_OP_READ:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4,
+ offset);
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4,
+ offset);
+ break;
+
+ case NFS4_OP_READDIR:
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookie4,
+ offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_cookieverf4,
+ offset);
+ offset = dissect_rpc_uint32(tvb, newftree,
+ hf_nfs_count4_dircount, offset);
+ offset = dissect_rpc_uint32(tvb, newftree,
+ hf_nfs_count4_maxcount, offset);
+ offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
+ FATTR4_BITMAP_ONLY);
+ break;
+
+ case NFS4_OP_READLINK:
+ break;
+
+ case NFS4_OP_REMOVE:
+ offset = dissect_nfs_utf8string(tvb, offset, newftree,
+ hf_nfs_component4, NULL);
+ break;
+
+ case NFS4_OP_RENAME:
+ offset = dissect_nfs_utf8string(tvb, offset, newftree,
+ hf_nfs_component4, NULL);
+ offset = dissect_nfs_utf8string(tvb, offset, newftree,
+ hf_nfs_component4, NULL);
+ break;
+
+ case NFS4_OP_RENEW:
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
+ break;
+
+ case NFS4_OP_RESTOREFH:
+ case NFS4_OP_SAVEFH:
+ break;
+
+ case NFS4_OP_SECINFO:
+ offset = dissect_nfs_utf8string(tvb, offset, newftree,
+ hf_nfs_component4, NULL);
+ break;
+
+ case NFS4_OP_SETATTR:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
+ break;
+
+ case NFS4_OP_SETCLIENTID:
+ {
+ proto_tree *client_tree = NULL;
+ proto_tree *callback_tree = NULL;
+
+ fitem = proto_tree_add_text(newftree, tvb, offset, 0, "client");
+ if (fitem)
+ {
+ client_tree = proto_item_add_subtree(fitem, ett_nfs_client_id4);
+
+ if (client_tree)
+ offset = dissect_nfs_client_id4(tvb, offset, client_tree);
+ }
+
+ fitem = proto_tree_add_text(newftree, tvb, offset, 0, "callback");
+ if (fitem)
+ {
+ callback_tree = proto_item_add_subtree(fitem,
+ ett_nfs_cb_client4);
+
+ if (callback_tree)
+ offset = dissect_nfs_cb_client4(tvb, offset, callback_tree);
+ }
+
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_callback_ident,
+ offset);
+ }
+ break;
+
+ case NFS4_OP_SETCLIENTID_CONFIRM:
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4, offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4, offset);
+ break;
+
+ case NFS4_OP_VERIFY:
+ offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
+ break;
+
+ case NFS4_OP_WRITE:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_offset4, offset);
+ offset = dissect_nfs_stable_how4(tvb, offset, newftree, "stable");
+ offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
+ break;
+
+ case NFS4_OP_RELEASE_LOCKOWNER:
+ offset = dissect_nfs_lock_owner4(tvb, offset, newftree);
+ break;
+
+ /* In theory, it's possible to get this opcode */
+ case NFS4_OP_ILLEGAL:
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs4_compound_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, NULL);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfs_minorversion, offset);
+ offset = dissect_nfs_argop4(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+static int
+dissect_nfs_secinfo4_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint flavor;
+ proto_item *fitem;
+ proto_tree *secftree;
+
+ flavor = tvb_get_ntohl(tvb, offset);
+ fitem = proto_tree_add_uint(tree, hf_nfs_secinfo_flavor, tvb, offset, 4,
+ flavor);
+ offset += 4;
+
+ if (fitem)
+ {
+ switch(flavor)
+ {
+ case RPCSEC_GSS:
+ secftree = proto_item_add_subtree(fitem, ett_nfs_secinfo4_flavor_info);
+ if (secftree)
+ offset = dissect_nfs_rpcsec_gss_info(tvb, offset, secftree);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs_resop4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 ops, ops_counter;
+ guint32 opcode;
+ proto_item *fitem;
+ proto_tree *ftree = NULL;
+ proto_tree *newftree = NULL;
+ guint32 status;
+
+ ops = tvb_get_ntohl(tvb, offset+0);
+
+ fitem = proto_tree_add_text(tree, tvb, offset, 4,
+ "Operations (count: %u)", ops);
+ offset += 4;
+
+ if (fitem == NULL) return offset;
+
+ ftree = proto_item_add_subtree(fitem, ett_nfs_resop4);
+
+ if (ftree == NULL) return offset; /* error adding new subtree */
+
+ for (ops_counter = 0; ops_counter < ops; ops_counter++)
+ {
+ opcode = tvb_get_ntohl(tvb, offset);
+
+ /* sanity check for bogus packets */
+ if ((opcode < NFS4_OP_ACCESS || opcode > NFS4_OP_WRITE) &&
+ (opcode != NFS4_OP_ILLEGAL))
+ break;
+
+ fitem = proto_tree_add_uint(ftree, hf_nfs_resop4, tvb, offset, 4,
+ opcode);
+ offset += 4;
+
+ if (fitem == NULL) break; /* error adding new item to tree */
+
+ /* all of the V4 ops are contiguous, except for NFS4_OP_ILLEGAL */
+ if (opcode == NFS4_OP_ILLEGAL)
+ newftree = proto_item_add_subtree(fitem, ett_nfs_illegal4);
+ else
+ newftree = proto_item_add_subtree(fitem,
+ *nfsv4_operation_ett[opcode - 3]);
+
+ if (newftree == NULL)
+ break; /* error adding new subtree to operation item */
+
+ offset = dissect_nfs_nfsstat4(tvb, offset, newftree, &status);
+
+ /*
+ * With the exception of NFS4_OP_LOCK, NFS4_OP_LOCKT, and
+ * NFS4_OP_SETATTR, all other ops do *not* return data with the
+ * failed status code.
+ */
+ if ((status != NFS4_OK) &&
+ ((opcode != NFS4_OP_LOCK) && (opcode != NFS4_OP_LOCKT) &&
+ (opcode != NFS4_OP_SETATTR)))
+ continue;
+
+ /* These parsing routines are only executed if the status is NFS4_OK */
+ switch(opcode)
+ {
+ case NFS4_OP_ACCESS:
+ offset = dissect_access(tvb, offset, newftree, "Supported");
+ offset = dissect_access(tvb, offset, newftree, "Access");
+ break;
+
+ case NFS4_OP_CLOSE:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_COMMIT:
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4,
+ offset);
+ break;
+
+ case NFS4_OP_CREATE:
+ offset = dissect_nfs_change_info4(tvb, offset, newftree,
+ "change_info");
+ offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
+ FATTR4_BITMAP_ONLY);
+ break;
+
+ case NFS4_OP_GETATTR:
+ offset = dissect_nfs_fattr4(tvb, offset, pinfo, newftree);
+ break;
+
+ case NFS4_OP_GETFH:
+ offset = dissect_nfs_fh4(tvb, offset, pinfo, newftree, "Filehandle");
+ break;
+
+ case NFS4_OP_LINK:
+ offset = dissect_nfs_change_info4(tvb, offset, newftree,
+ "change_info");
+ break;
+
+ case NFS4_OP_LOCK:
+ case NFS4_OP_LOCKT:
+ if (status == NFS4_OK)
+ {
+ if (opcode == NFS4_OP_LOCK)
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ }
+ else
+ if (status == NFS4ERR_DENIED)
+ offset = dissect_nfs_lock4denied(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_LOCKU:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_OPEN:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ offset = dissect_nfs_change_info4(tvb, offset, newftree,
+ "change_info");
+ offset = dissect_nfs_open4_rflags(tvb, offset, newftree,
+ "result_flags");
+ offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
+ FATTR4_BITMAP_ONLY);
+ offset = dissect_nfs_open_delegation4(tvb, offset, pinfo, newftree);
+ break;
+
+ case NFS4_OP_OPEN_CONFIRM:
+ case NFS4_OP_OPEN_DOWNGRADE:
+ offset = dissect_nfs_stateid4(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_READ:
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_eof, offset);
+ offset = dissect_nfsdata(tvb, offset, newftree, hf_nfs_data);
+ break;
+
+ case NFS4_OP_READDIR:
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4, offset);
+ offset = dissect_nfs_dirlist4(tvb, offset, pinfo, newftree);
+ break;
+
+ case NFS4_OP_READLINK:
+ offset = dissect_nfs_utf8string(tvb, offset, newftree,
+ hf_nfs_linktext4, NULL);
+ break;
+
+ case NFS4_OP_REMOVE:
+ offset = dissect_nfs_change_info4(tvb, offset, newftree,
+ "change_info");
+ break;
+
+ case NFS4_OP_RENAME:
+ offset = dissect_nfs_change_info4(tvb, offset, newftree,
+ "source_cinfo");
+ offset = dissect_nfs_change_info4(tvb, offset, newftree,
+ "target_cinfo");
+ break;
+
+ case NFS4_OP_SECINFO:
+ offset = dissect_rpc_array(tvb, pinfo, newftree, offset,
+ dissect_nfs_secinfo4_res, hf_nfs_secinfo_arr4);
+ break;
+
+ case NFS4_OP_SETATTR:
+ offset = dissect_nfs_attributes(tvb, offset, pinfo, newftree,
+ FATTR4_BITMAP_ONLY);
+ break;
+
+ case NFS4_OP_SETCLIENTID:
+ if (status == NFS4_OK)
+ {
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_clientid4,
+ offset);
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4,
+ offset);
+ }
+ else
+ if (status == NFS4ERR_CLID_INUSE)
+ offset = dissect_nfs_clientaddr4(tvb, offset, newftree);
+ break;
+
+ case NFS4_OP_WRITE:
+ offset = dissect_rpc_uint32(tvb, newftree, hf_nfs_count4,
+ offset);
+ offset = dissect_nfs_stable_how4(tvb, offset, newftree,
+ "committed");
+ offset = dissect_rpc_uint64(tvb, newftree, hf_nfs_verifier4,
+ offset);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfs4_compound_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree* tree)
+{
+ guint32 status;
+
+ offset = dissect_nfs_nfsstat4(tvb, offset, tree, &status);
+ offset = dissect_nfs_utf8string(tvb, offset, tree, hf_nfs_tag4, NULL);
+ offset = dissect_nfs_resop4(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff nfs3_proc[] = {
+ { 0, "NULL", /* OK */
+ dissect_nfs3_null_call, dissect_nfs3_null_reply },
+ { 1, "GETATTR", /* OK */
+ dissect_nfs3_getattr_call, dissect_nfs3_getattr_reply },
+ { 2, "SETATTR", /* OK */
+ dissect_nfs3_setattr_call, dissect_nfs3_setattr_reply },
+ { 3, "LOOKUP", /* OK */
+ dissect_nfs3_lookup_call, dissect_nfs3_lookup_reply },
+ { 4, "ACCESS", /* OK */
+ dissect_nfs3_access_call, dissect_nfs3_access_reply },
+ { 5, "READLINK", /* OK */
+ dissect_nfs3_readlink_call, dissect_nfs3_readlink_reply },
+ { 6, "READ", /* OK */
+ dissect_nfs3_read_call, dissect_nfs3_read_reply },
+ { 7, "WRITE", /* OK */
+ dissect_nfs3_write_call, dissect_nfs3_write_reply },
+ { 8, "CREATE", /* OK */
+ dissect_nfs3_create_call, dissect_nfs3_create_reply },
+ { 9, "MKDIR", /* OK */
+ dissect_nfs3_mkdir_call, dissect_nfs3_mkdir_reply },
+ { 10, "SYMLINK", /* OK */
+ dissect_nfs3_symlink_call, dissect_nfs3_symlink_reply },
+ { 11, "MKNOD", /* OK */
+ dissect_nfs3_mknod_call, dissect_nfs3_mknod_reply },
+ { 12, "REMOVE", /* OK */
+ dissect_nfs3_remove_call, dissect_nfs3_remove_reply },
+ { 13, "RMDIR", /* OK */
+ dissect_nfs3_rmdir_call, dissect_nfs3_rmdir_reply },
+ { 14, "RENAME", /* OK */
+ dissect_nfs3_rename_call, dissect_nfs3_rename_reply },
+ { 15, "LINK", /* OK */
+ dissect_nfs3_link_call, dissect_nfs3_link_reply },
+ { 16, "READDIR", /* OK */
+ dissect_nfs3_readdir_call, dissect_nfs3_readdir_reply },
+ { 17, "READDIRPLUS", /* OK */
+ dissect_nfs3_readdirplus_call, dissect_nfs3_readdirplus_reply },
+ { 18, "FSSTAT", /* OK */
+ dissect_nfs3_fsstat_call, dissect_nfs3_fsstat_reply },
+ { 19, "FSINFO", /* OK */
+ dissect_nfs3_fsinfo_call, dissect_nfs3_fsinfo_reply },
+ { 20, "PATHCONF", /* OK */
+ dissect_nfs3_pathconf_call, dissect_nfs3_pathconf_reply },
+ { 21, "COMMIT", /* OK */
+ dissect_nfs3_commit_call, dissect_nfs3_commit_reply },
+ { 0,NULL,NULL,NULL }
+};
+
+static const value_string nfsv3_proc_vals[] = {
+ { 0, "NULL" },
+ { 1, "GETATTR" },
+ { 2, "SETATTR" },
+ { 3, "LOOKUP" },
+ { 4, "ACCESS" },
+ { 5, "READLINK" },
+ { 6, "READ" },
+ { 7, "WRITE" },
+ { 8, "CREATE" },
+ { 9, "MKDIR" },
+ { 10, "SYMLINK" },
+ { 11, "MKNOD" },
+ { 12, "REMOVE" },
+ { 13, "RMDIR" },
+ { 14, "RENAME" },
+ { 15, "LINK" },
+ { 16, "READDIR" },
+ { 17, "READDIRPLUS" },
+ { 18, "FSSTAT" },
+ { 19, "FSINFO" },
+ { 20, "PATHCONF" },
+ { 21, "COMMIT" },
+ { 0, NULL }
+};
+
+/* end of NFS Version 3 */
+
+/* the call to dissect_nfs3_null_call & dissect_nfs3_null_reply is
+ * intentional. The V4 NULLPROC is the same as V3.
+ */
+static const vsff nfs4_proc[] = {
+ { 0, "NULL",
+ dissect_nfs3_null_call, dissect_nfs3_null_reply },
+ { 1, "COMPOUND",
+ dissect_nfs4_compound_call, dissect_nfs4_compound_reply },
+ { 0, NULL, NULL, NULL }
+};
+
+static const value_string nfsv4_proc_vals[] = {
+ { 0, "NULL" },
+ { 1, "COMPOUND" },
+ { 0, NULL }
+};
+
+static struct true_false_string yesno = { "Yes", "No" };
+
+
+void
+proto_register_nfs(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_nfs_procedure_v2, {
+ "V2 Procedure", "nfs.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(nfsv2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_nfs_procedure_v3, {
+ "V3 Procedure", "nfs.procedure_v3", FT_UINT32, BASE_DEC,
+ VALS(nfsv3_proc_vals), 0, "V3 Procedure", HFILL }},
+ { &hf_nfs_procedure_v4, {
+ "V4 Procedure", "nfs.procedure_v4", FT_UINT32, BASE_DEC,
+ VALS(nfsv4_proc_vals), 0, "V4 Procedure", HFILL }},
+ { &hf_nfs_fh_length, {
+ "length", "nfs.fh.length", FT_UINT32, BASE_DEC,
+ NULL, 0, "file handle length", HFILL }},
+ { &hf_nfs_fh_hash, {
+ "hash", "nfs.fh.hash", FT_UINT32, BASE_HEX,
+ NULL, 0, "file handle hash", HFILL }},
+ { &hf_nfs_fh_mount_fileid, {
+ "fileid", "nfs.fh.mount.fileid", FT_UINT32, BASE_DEC,
+ NULL, 0, "mount point fileid", HFILL }},
+ { &hf_nfs_fh_mount_generation, {
+ "generation", "nfs.fh.mount.generation", FT_UINT32, BASE_HEX,
+ NULL, 0, "mount point generation", HFILL }},
+ { &hf_nfs_fh_flags, {
+ "flags", "nfs.fh.flags", FT_UINT16, BASE_HEX,
+ NULL, 0, "file handle flags", HFILL }},
+ { &hf_nfs_fh_snapid, {
+ "snapid", "nfs.fh.snapid", FT_UINT8, BASE_DEC,
+ NULL, 0, "snapshot ID", HFILL }},
+ { &hf_nfs_fh_unused, {
+ "unused", "nfs.fh.unused", FT_UINT8, BASE_DEC,
+ NULL, 0, "unused", HFILL }},
+ { &hf_nfs_fh_fileid, {
+ "fileid", "nfs.fh.fileid", FT_UINT32, BASE_DEC,
+ NULL, 0, "file ID", HFILL }},
+ { &hf_nfs_fh_generation, {
+ "generation", "nfs.fh.generation", FT_UINT32, BASE_HEX,
+ NULL, 0, "inode generation", HFILL }},
+ { &hf_nfs_fh_fsid, {
+ "fsid", "nfs.fh.fsid", FT_UINT32, BASE_HEX,
+ NULL, 0, "file system ID", HFILL }},
+ { &hf_nfs_fh_export_fileid, {
+ "fileid", "nfs.fh.export.fileid", FT_UINT32, BASE_DEC,
+ NULL, 0, "export point fileid", HFILL }},
+ { &hf_nfs_fh_export_generation, {
+ "generation", "nfs.fh.export.generation", FT_UINT32, BASE_HEX,
+ NULL, 0, "export point generation", HFILL }},
+ { &hf_nfs_fh_export_snapid, {
+ "snapid", "nfs.fh.export.snapid", FT_UINT8, BASE_DEC,
+ NULL, 0, "export point snapid", HFILL }},
+ { &hf_nfs_fh_fsid_major, {
+ "major", "nfs.fh.fsid.major", FT_UINT32, BASE_DEC,
+ NULL, 0, "major file system ID", HFILL }},
+ { &hf_nfs_fh_fsid_minor, {
+ "minor", "nfs.fh.fsid.minor", FT_UINT32, BASE_DEC,
+ NULL, 0, "minor file system ID", HFILL }},
+ { &hf_nfs_fh_fsid_inode, {
+ "inode", "nfs.fh.fsid.inode", FT_UINT32, BASE_DEC,
+ NULL, 0, "file system inode", HFILL }},
+ { &hf_nfs_fh_xfsid_major, {
+ "exported major", "nfs.fh.xfsid.major", FT_UINT32, BASE_DEC,
+ NULL, 0, "exported major file system ID", HFILL }},
+ { &hf_nfs_fh_xfsid_minor, {
+ "exported minor", "nfs.fh.xfsid.minor", FT_UINT32, BASE_DEC,
+ NULL, 0, "exported minor file system ID", HFILL }},
+ { &hf_nfs_fh_fstype, {
+ "file system type", "nfs.fh.fstype", FT_UINT32, BASE_DEC,
+ NULL, 0, "file system type", HFILL }},
+ { &hf_nfs_fh_fn, {
+ "file number", "nfs.fh.fn", FT_UINT32, BASE_DEC,
+ NULL, 0, "file number", HFILL }},
+ { &hf_nfs_fh_fn_len, {
+ "length", "nfs.fh.fn.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "file number length", HFILL }},
+ { &hf_nfs_fh_fn_inode, {
+ "inode", "nfs.fh.fn.inode", FT_UINT32, BASE_DEC,
+ NULL, 0, "file number inode", HFILL }},
+ { &hf_nfs_fh_fn_generation, {
+ "generation", "nfs.fh.fn.generation", FT_UINT32, BASE_DEC,
+ NULL, 0, "file number generation", HFILL }},
+ { &hf_nfs_fh_xfn, {
+ "exported file number", "nfs.fh.xfn", FT_UINT32, BASE_DEC,
+ NULL, 0, "exported file number", HFILL }},
+ { &hf_nfs_fh_xfn_len, {
+ "length", "nfs.fh.xfn.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "exported file number length", HFILL }},
+ { &hf_nfs_fh_xfn_inode, {
+ "exported inode", "nfs.fh.xfn.inode", FT_UINT32, BASE_DEC,
+ NULL, 0, "exported file number inode", HFILL }},
+ { &hf_nfs_fh_xfn_generation, {
+ "generation", "nfs.fh.xfn.generation", FT_UINT32, BASE_DEC,
+ NULL, 0, "exported file number generation", HFILL }},
+ { &hf_nfs_fh_dentry, {
+ "dentry", "nfs.fh.dentry", FT_UINT32, BASE_HEX,
+ NULL, 0, "dentry (cookie)", HFILL }},
+ { &hf_nfs_fh_dev, {
+ "device", "nfs.fh.dev", FT_UINT32, BASE_DEC,
+ NULL, 0, "device", HFILL }},
+ { &hf_nfs_fh_xdev, {
+ "exported device", "nfs.fh.xdev", FT_UINT32, BASE_DEC,
+ NULL, 0, "exported device", HFILL }},
+ { &hf_nfs_fh_dirinode, {
+ "directory inode", "nfs.fh.dirinode", FT_UINT32, BASE_DEC,
+ NULL, 0, "directory inode", HFILL }},
+ { &hf_nfs_fh_pinode, {
+ "pseudo inode", "nfs.fh.pinode", FT_UINT32, BASE_HEX,
+ NULL, 0, "pseudo inode", HFILL }},
+ { &hf_nfs_fh_hp_len, {
+ "length", "nfs.fh.hp.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "hash path length", HFILL }},
+ { &hf_nfs_fh_version, {
+ "version", "nfs.fh.version", FT_UINT8, BASE_DEC,
+ NULL, 0, "file handle layout version", HFILL }},
+ { &hf_nfs_fh_auth_type, {
+ "auth_type", "nfs.fh.auth_type", FT_UINT8, BASE_DEC,
+ VALS(auth_type_names), 0, "authentication type", HFILL }},
+ { &hf_nfs_fh_fsid_type, {
+ "fsid_type", "nfs.fh.fsid_type", FT_UINT8, BASE_DEC,
+ VALS(fsid_type_names), 0, "file system ID type", HFILL }},
+ { &hf_nfs_fh_fileid_type, {
+ "fileid_type", "nfs.fh.fileid_type", FT_UINT8, BASE_DEC,
+ VALS(fileid_type_names), 0, "file ID type", HFILL }},
+ { &hf_nfs_stat, {
+ "Status", "nfs.status2", FT_UINT32, BASE_DEC,
+ VALS(names_nfs_stat), 0, "Reply status", HFILL }},
+ { &hf_nfs_full_name, {
+ "Full Name", "nfs.full_name", FT_STRING, BASE_DEC,
+ NULL, 0, "Full Name", HFILL }},
+ { &hf_nfs_name, {
+ "Name", "nfs.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name", HFILL }},
+ { &hf_nfs_readlink_data, {
+ "Data", "nfs.readlink.data", FT_STRING, BASE_DEC,
+ NULL, 0, "Symbolic Link Data", HFILL }},
+ { &hf_nfs_read_offset, {
+ "Offset", "nfs.read.offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Read Offset", HFILL }},
+ { &hf_nfs_read_count, {
+ "Count", "nfs.read.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Read Count", HFILL }},
+ { &hf_nfs_read_totalcount, {
+ "Total Count", "nfs.read.totalcount", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total Count (obsolete)", HFILL }},
+ { &hf_nfs_data, {
+ "Data", "nfs.data", FT_BYTES, BASE_DEC,
+ NULL, 0, "Data", HFILL }},
+ { &hf_nfs_write_beginoffset, {
+ "Begin Offset", "nfs.write.beginoffset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Begin offset (obsolete)", HFILL }},
+ { &hf_nfs_write_offset, {
+ "Offset", "nfs.write.offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Offset", HFILL }},
+ { &hf_nfs_write_totalcount, {
+ "Total Count", "nfs.write.totalcount", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total Count (obsolete)", HFILL }},
+ { &hf_nfs_symlink_to, {
+ "To", "nfs.symlink.to", FT_STRING, BASE_DEC,
+ NULL, 0, "Symbolic link destination name", HFILL }},
+ { &hf_nfs_readdir_cookie, {
+ "Cookie", "nfs.readdir.cookie", FT_UINT32, BASE_DEC,
+ NULL, 0, "Directory Cookie", HFILL }},
+ { &hf_nfs_readdir_count, {
+ "Count", "nfs.readdir.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Directory Count", HFILL }},
+
+ { &hf_nfs_readdir_entry, {
+ "Entry", "nfs.readdir.entry", FT_NONE, 0,
+ NULL, 0, "Directory Entry", HFILL }},
+
+ { &hf_nfs_readdir_entry_fileid, {
+ "File ID", "nfs.readdir.entry.fileid", FT_UINT32, BASE_DEC,
+ NULL, 0, "File ID", HFILL }},
+
+ { &hf_nfs_readdir_entry_name, {
+ "Name", "nfs.readdir.entry.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name", HFILL }},
+
+ { &hf_nfs_readdir_entry_cookie, {
+ "Cookie", "nfs.readdir.entry.cookie", FT_UINT32, BASE_DEC,
+ NULL, 0, "Directory Cookie", HFILL }},
+
+ { &hf_nfs_readdir_entry3_fileid, {
+ "File ID", "nfs.readdir.entry3.fileid", FT_UINT64, BASE_DEC,
+ NULL, 0, "File ID", HFILL }},
+
+ { &hf_nfs_readdir_entry3_name, {
+ "Name", "nfs.readdir.entry3.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name", HFILL }},
+
+ { &hf_nfs_readdir_entry3_cookie, {
+ "Cookie", "nfs.readdir.entry3.cookie", FT_UINT64, BASE_DEC,
+ NULL, 0, "Directory Cookie", HFILL }},
+
+ { &hf_nfs_readdirplus_entry_fileid, {
+ "File ID", "nfs.readdirplus.entry.fileid", FT_UINT64, BASE_DEC,
+ NULL, 0, "Name", HFILL }},
+
+ { &hf_nfs_readdirplus_entry_name, {
+ "Name", "nfs.readdirplus.entry.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name", HFILL }},
+
+ { &hf_nfs_readdirplus_entry_cookie, {
+ "Cookie", "nfs.readdirplus.entry.cookie", FT_UINT64, BASE_DEC,
+ NULL, 0, "Directory Cookie", HFILL }},
+
+ { &hf_nfs_readdir_eof, {
+ "EOF", "nfs.readdir.eof", FT_UINT32, BASE_DEC,
+ NULL, 0, "EOF", HFILL }},
+
+ { &hf_nfs_statfs_tsize, {
+ "Transfer Size", "nfs.statfs.tsize", FT_UINT32, BASE_DEC,
+ NULL, 0, "Transfer Size", HFILL }},
+ { &hf_nfs_statfs_bsize, {
+ "Block Size", "nfs.statfs.bsize", FT_UINT32, BASE_DEC,
+ NULL, 0, "Block Size", HFILL }},
+ { &hf_nfs_statfs_blocks, {
+ "Total Blocks", "nfs.statfs.blocks", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total Blocks", HFILL }},
+ { &hf_nfs_statfs_bfree, {
+ "Free Blocks", "nfs.statfs.bfree", FT_UINT32, BASE_DEC,
+ NULL, 0, "Free Blocks", HFILL }},
+ { &hf_nfs_statfs_bavail, {
+ "Available Blocks", "nfs.statfs.bavail", FT_UINT32, BASE_DEC,
+ NULL, 0, "Available Blocks", HFILL }},
+ { &hf_nfs_ftype3, {
+ "Type", "nfs.type", FT_UINT32, BASE_DEC,
+ VALS(names_nfs_ftype3), 0, "File Type", HFILL }},
+ { &hf_nfs_nfsstat3, {
+ "Status", "nfs.status", FT_UINT32, BASE_DEC,
+ VALS(names_nfs_nfsstat3), 0, "Reply status", HFILL }},
+ { &hf_nfs_read_eof, {
+ "EOF", "nfs.read.eof", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "EOF", HFILL }},
+ { &hf_nfs_write_stable, {
+ "Stable", "nfs.write.stable", FT_UINT32, BASE_DEC,
+ VALS(names_stable_how), 0, "Stable", HFILL }},
+ { &hf_nfs_write_committed, {
+ "Committed", "nfs.write.committed", FT_UINT32, BASE_DEC,
+ VALS(names_stable_how), 0, "Committed", HFILL }},
+ { &hf_nfs_createmode3, {
+ "Create Mode", "nfs.createmode", FT_UINT32, BASE_DEC,
+ VALS(names_createmode3), 0, "Create Mode", HFILL }},
+ { &hf_nfs_fsstat_invarsec, {
+ "invarsec", "nfs.fsstat.invarsec", FT_UINT32, BASE_DEC,
+ NULL, 0, "probable number of seconds of file system invariance", HFILL }},
+ { &hf_nfs_fsinfo_rtmax, {
+ "rtmax", "nfs.fsinfo.rtmax", FT_UINT32, BASE_DEC,
+ NULL, 0, "maximum READ request", HFILL }},
+ { &hf_nfs_fsinfo_rtpref, {
+ "rtpref", "nfs.fsinfo.rtpref", FT_UINT32, BASE_DEC,
+ NULL, 0, "Preferred READ request size", HFILL }},
+ { &hf_nfs_fsinfo_rtmult, {
+ "rtmult", "nfs.fsinfo.rtmult", FT_UINT32, BASE_DEC,
+ NULL, 0, "Suggested READ multiple", HFILL }},
+ { &hf_nfs_fsinfo_wtmax, {
+ "wtmax", "nfs.fsinfo.wtmax", FT_UINT32, BASE_DEC,
+ NULL, 0, "Maximum WRITE request size", HFILL }},
+ { &hf_nfs_fsinfo_wtpref, {
+ "wtpref", "nfs.fsinfo.wtpref", FT_UINT32, BASE_DEC,
+ NULL, 0, "Preferred WRITE request size", HFILL }},
+ { &hf_nfs_fsinfo_wtmult, {
+ "wtmult", "nfs.fsinfo.wtmult", FT_UINT32, BASE_DEC,
+ NULL, 0, "Suggested WRITE multiple", HFILL }},
+ { &hf_nfs_fsinfo_dtpref, {
+ "dtpref", "nfs.fsinfo.dtpref", FT_UINT32, BASE_DEC,
+ NULL, 0, "Preferred READDIR request", HFILL }},
+ { &hf_nfs_fsinfo_maxfilesize, {
+ "maxfilesize", "nfs.fsinfo.maxfilesize", FT_UINT64, BASE_DEC,
+ NULL, 0, "Maximum file size", HFILL }},
+ { &hf_nfs_fsinfo_properties, {
+ "Properties", "nfs.fsinfo.propeties", FT_UINT32, BASE_HEX,
+ NULL, 0, "File System Properties", HFILL }},
+ { &hf_nfs_pathconf_linkmax, {
+ "linkmax", "nfs.pathconf.linkmax", FT_UINT32, BASE_DEC,
+ NULL, 0, "Maximum number of hard links", HFILL }},
+ { &hf_nfs_pathconf_name_max, {
+ "name_max", "nfs.pathconf.name_max", FT_UINT32, BASE_DEC,
+ NULL, 0, "Maximum file name length", HFILL }},
+ { &hf_nfs_pathconf_no_trunc, {
+ "no_trunc", "nfs.pathconf.no_trunc", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "No long file name truncation", HFILL }},
+ { &hf_nfs_pathconf_chown_restricted, {
+ "chown_restricted", "nfs.pathconf.chown_restricted", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "chown is restricted to root", HFILL }},
+ { &hf_nfs_pathconf_case_insensitive, {
+ "case_insensitive", "nfs.pathconf.case_insensitive", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "file names are treated case insensitive", HFILL }},
+ { &hf_nfs_pathconf_case_preserving, {
+ "case_preserving", "nfs.pathconf.case_preserving", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "file name cases are preserved", HFILL }},
+
+ { &hf_nfs_fattr_type, {
+ "type", "nfs.fattr.type", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr.type", HFILL }},
+
+ { &hf_nfs_fattr_nlink, {
+ "nlink", "nfs.fattr.nlink", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr.nlink", HFILL }},
+
+ { &hf_nfs_fattr_uid, {
+ "uid", "nfs.fattr.uid", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr.uid", HFILL }},
+
+ { &hf_nfs_fattr_gid, {
+ "gid", "nfs.fattr.gid", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr.gid", HFILL }},
+
+ { &hf_nfs_fattr_size, {
+ "size", "nfs.fattr.size", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr.size", HFILL }},
+
+ { &hf_nfs_fattr_blocksize, {
+ "blocksize", "nfs.fattr.blocksize", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr.blocksize", HFILL }},
+
+ { &hf_nfs_fattr_rdev, {
+ "rdev", "nfs.fattr.rdev", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr.rdev", HFILL }},
+
+ { &hf_nfs_fattr_blocks, {
+ "blocks", "nfs.fattr.blocks", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr.blocks", HFILL }},
+
+ { &hf_nfs_fattr_fsid, {
+ "fsid", "nfs.fattr.fsid", FT_UINT32, BASE_HEX,
+ NULL, 0, "nfs.fattr.fsid", HFILL }},
+
+ { &hf_nfs_fattr_fileid, {
+ "fileid", "nfs.fattr.fileid", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr.fileid", HFILL }},
+
+ { &hf_nfs_fattr3_type, {
+ "Type", "nfs.fattr3.type", FT_UINT32, BASE_DEC,
+ VALS(names_nfs_ftype3), 0, "nfs.fattr3.type", HFILL }},
+
+ { &hf_nfs_fattr3_nlink, {
+ "nlink", "nfs.fattr3.nlink", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr3.nlink", HFILL }},
+
+ { &hf_nfs_fattr3_uid, {
+ "uid", "nfs.fattr3.uid", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr3.uid", HFILL }},
+
+ { &hf_nfs_fattr3_gid, {
+ "gid", "nfs.fattr3.gid", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr3.gid", HFILL }},
+
+ { &hf_nfs_fattr3_size, {
+ "size", "nfs.fattr3.size", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr3.size", HFILL }},
+
+ { &hf_nfs_fattr3_used, {
+ "used", "nfs.fattr3.used", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr3.used", HFILL }},
+
+ { &hf_nfs_fattr3_rdev, {
+ "rdev", "nfs.fattr3.rdev", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr3.rdev", HFILL }},
+
+ { &hf_nfs_fattr3_fsid, {
+ "fsid", "nfs.fattr3.fsid", FT_UINT64, BASE_HEX,
+ NULL, 0, "nfs.fattr3.fsid", HFILL }},
+
+ { &hf_nfs_fattr3_fileid, {
+ "fileid", "nfs.fattr3.fileid", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr3.fileid", HFILL }},
+
+ { &hf_nfs_wcc_attr_size, {
+ "size", "nfs.wcc_attr.size", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.wcc_attr.size", HFILL }},
+
+ { &hf_nfs_set_size3_size, {
+ "size", "nfs.set_size3.size", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.set_size3.size", HFILL }},
+
+ { &hf_nfs_uid3, {
+ "uid", "nfs.uid3", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.uid3", HFILL }},
+
+ { &hf_nfs_gid3, {
+ "gid", "nfs.gid3", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.gid3", HFILL }},
+
+ { &hf_nfs_cookie3, {
+ "cookie", "nfs.cookie3", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.cookie3", HFILL }},
+
+ { &hf_nfs_offset3, {
+ "offset", "nfs.offset3", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.offset3", HFILL }},
+
+ { &hf_nfs_count3, {
+ "count", "nfs.count3", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.count3", HFILL }},
+
+ { &hf_nfs_count3_maxcount, {
+ "maxcount", "nfs.count3_maxcount", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.count3_maxcount", HFILL }},
+
+ { &hf_nfs_count3_dircount, {
+ "dircount", "nfs.count3_dircount", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.count3_dircount", HFILL }},
+
+ { &hf_nfs_fsstat3_resok_tbytes, {
+ "Total bytes", "nfs.fsstat3_resok.tbytes", FT_UINT64, BASE_DEC,
+ NULL, 0, "Total bytes", HFILL }},
+
+ { &hf_nfs_fsstat3_resok_fbytes, {
+ "Free bytes", "nfs.fsstat3_resok.fbytes", FT_UINT64, BASE_DEC,
+ NULL, 0, "Free bytes", HFILL }},
+
+ { &hf_nfs_fsstat3_resok_abytes, {
+ "Available free bytes", "nfs.fsstat3_resok.abytes", FT_UINT64, BASE_DEC,
+ NULL, 0, "Available free bytes", HFILL }},
+
+ { &hf_nfs_fsstat3_resok_tfiles, {
+ "Total file slots", "nfs.fsstat3_resok.tfiles", FT_UINT64, BASE_DEC,
+ NULL, 0, "Total file slots", HFILL }},
+
+ { &hf_nfs_fsstat3_resok_ffiles, {
+ "Free file slots", "nfs.fsstat3_resok.ffiles", FT_UINT64, BASE_DEC,
+ NULL, 0, "Free file slots", HFILL }},
+
+ { &hf_nfs_fsstat3_resok_afiles, {
+ "Available free file slots", "nfs.fsstat3_resok.afiles", FT_UINT64, BASE_DEC,
+ NULL, 0, "Available free file slots", HFILL }},
+
+ /* NFSv4 */
+
+ { &hf_nfs_argop4, {
+ "Opcode", "nfs.call.operation", FT_UINT32, BASE_DEC,
+ VALS(names_nfsv4_operation), 0, "Opcode", HFILL }},
+
+ { &hf_nfs_resop4, {
+ "Opcode", "nfs.reply.operation", FT_UINT32, BASE_DEC,
+ VALS(names_nfsv4_operation), 0, "Opcode", HFILL }},
+
+ { &hf_nfs_linktext4, {
+ "Name", "nfs.symlink.linktext", FT_STRING, BASE_DEC,
+ NULL, 0, "Symbolic link contents", HFILL }},
+
+ { &hf_nfs_component4, {
+ "Filename", "nfs.pathname.component", FT_STRING, BASE_DEC,
+ NULL, 0, "Pathname component", HFILL }},
+
+ { &hf_nfs_tag4, {
+ "Tag", "nfs.tag", FT_STRING, BASE_DEC,
+ NULL, 0, "Tag", HFILL }},
+
+ { &hf_nfs_clientid4, {
+ "clientid", "nfs.clientid", FT_UINT64, BASE_HEX,
+ NULL, 0, "Client ID", HFILL }},
+
+ { &hf_nfs_ace4, {
+ "ace", "nfs.ace", FT_STRING, BASE_DEC,
+ NULL, 0, "Access Control Entry", HFILL }},
+
+ { &hf_nfs_recall, {
+ "EOF", "nfs.recall", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "Recall", HFILL }},
+
+ { &hf_nfs_open_claim_type4, {
+ "Claim Type", "nfs.open.claim_type", FT_UINT32, BASE_DEC,
+ VALS(names_claim_type4), 0, "Claim Type", HFILL }},
+
+ { &hf_nfs_opentype4, {
+ "Open Type", "nfs.open.opentype", FT_UINT32, BASE_DEC,
+ VALS(names_opentype4), 0, "Open Type", HFILL }},
+
+ { &hf_nfs_limit_by4, {
+ "Space Limit", "nfs.open.limit_by", FT_UINT32, BASE_DEC,
+ VALS(names_limit_by4), 0, "Limit By", HFILL }},
+
+ { &hf_nfs_open_delegation_type4, {
+ "Delegation Type", "nfs.open.delegation_type", FT_UINT32, BASE_DEC,
+ VALS(names_open_delegation_type4), 0, "Delegation Type", HFILL }},
+
+ { &hf_nfs_ftype4, {
+ "nfs_ftype4", "nfs.nfs_ftype4", FT_UINT32, BASE_DEC,
+ VALS(names_ftype4), 0, "nfs.nfs_ftype4", HFILL }},
+
+ { &hf_nfs_change_info4_atomic, {
+ "Atomic", "nfs.change_info.atomic", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "Atomic", HFILL }},
+
+ { &hf_nfs_open4_share_access, {
+ "share_access", "nfs.open4.share_access", FT_UINT32, BASE_DEC,
+ VALS(names_open4_share_access), 0, "Share Access", HFILL }},
+
+ { &hf_nfs_open4_share_deny, {
+ "share_deny", "nfs.open4.share_deny", FT_UINT32, BASE_DEC,
+ VALS(names_open4_share_deny), 0, "Share Deny", HFILL }},
+
+ { &hf_nfs_seqid4, {
+ "seqid", "nfs.seqid", FT_UINT32, BASE_HEX,
+ NULL, 0, "Sequence ID", HFILL }},
+
+ { &hf_nfs_lock_seqid4, {
+ "lock_seqid", "nfs.lock_seqid", FT_UINT32, BASE_HEX,
+ NULL, 0, "Lock Sequence ID", HFILL }},
+
+ { &hf_nfs_mand_attr, {
+ "mand_attr", "nfs.attr", FT_UINT32, BASE_DEC,
+ VALS(names_fattr4), 0, "Mandatory Attribute", HFILL }},
+
+ { &hf_nfs_recc_attr, {
+ "recc_attr", "nfs.attr", FT_UINT32, BASE_DEC,
+ VALS(names_fattr4), 0, "Recommended Attribute", HFILL }},
+
+ { &hf_nfs_time_how4, {
+ "set_it", "nfs.set_it", FT_UINT32, BASE_DEC,
+ VALS(names_time_how4), 0, "How To Set Time", HFILL }},
+
+ { &hf_nfs_attrlist4, {
+ "attr_vals", "nfs.fattr4.attr_vals", FT_BYTES, BASE_DEC,
+ NULL, 0, "attr_vals", HFILL }},
+
+ { &hf_nfs_fattr4_link_support, {
+ "fattr4_link_support", "nfs.fattr4_link_support", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_link_support", HFILL }},
+
+ { &hf_nfs_fattr4_symlink_support, {
+ "fattr4_symlink_support", "nfs.fattr4_symlink_support", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_symlink_support", HFILL }},
+
+ { &hf_nfs_fattr4_named_attr, {
+ "fattr4_named_attr", "nfs.fattr4_named_attr", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "nfs.fattr4_named_attr", HFILL }},
+
+ { &hf_nfs_fattr4_unique_handles, {
+ "fattr4_unique_handles", "nfs.fattr4_unique_handles", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_unique_handles", HFILL }},
+
+ { &hf_nfs_fattr4_archive, {
+ "fattr4_archive", "nfs.fattr4_archive", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_archive", HFILL }},
+
+ { &hf_nfs_fattr4_cansettime, {
+ "fattr4_cansettime", "nfs.fattr4_cansettime", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_cansettime", HFILL }},
+
+ { &hf_nfs_fattr4_case_insensitive, {
+ "fattr4_case_insensitive", "nfs.fattr4_case_insensitive", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_case_insensitive", HFILL }},
+
+ { &hf_nfs_fattr4_case_preserving, {
+ "fattr4_case_preserving", "nfs.fattr4_case_preserving", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_case_preserving", HFILL }},
+
+ { &hf_nfs_fattr4_chown_restricted, {
+ "fattr4_chown_restricted", "nfs.fattr4_chown_restricted", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_chown_restricted", HFILL }},
+
+ { &hf_nfs_fattr4_hidden, {
+ "fattr4_hidden", "nfs.fattr4_hidden", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_hidden", HFILL }},
+
+ { &hf_nfs_fattr4_homogeneous, {
+ "fattr4_homogeneous", "nfs.fattr4_homogeneous", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_homogeneous", HFILL }},
+
+ { &hf_nfs_fattr4_mimetype, {
+ "fattr4_mimetype", "nfs.fattr4_mimetype", FT_STRING, BASE_DEC,
+ NULL, 0, "nfs.fattr4_mimetype", HFILL }},
+
+ { &hf_nfs_fattr4_no_trunc, {
+ "fattr4_no_trunc", "nfs.fattr4_no_trunc", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_no_trunc", HFILL }},
+
+ { &hf_nfs_fattr4_system, {
+ "fattr4_system", "nfs.fattr4_system", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.fattr4_system", HFILL }},
+
+ { &hf_nfs_who, {
+ "who", "nfs.who", FT_STRING, BASE_DEC,
+ NULL, 0, "nfs.who", HFILL }},
+
+ { &hf_nfs_server, {
+ "server", "nfs.server", FT_STRING, BASE_DEC,
+ NULL, 0, "nfs.server", HFILL }},
+
+ { &hf_nfs_fattr4_owner, {
+ "fattr4_owner", "nfs.fattr4_owner", FT_STRING, BASE_DEC,
+ NULL, 0, "nfs.fattr4_owner", HFILL }},
+
+ { &hf_nfs_fattr4_owner_group, {
+ "fattr4_owner_group", "nfs.fattr4_owner_group", FT_STRING, BASE_DEC,
+ NULL, 0, "nfs.fattr4_owner_group", HFILL }},
+
+ { &hf_nfs_stable_how4, {
+ "stable_how4", "nfs.stable_how4", FT_UINT32, BASE_DEC,
+ VALS(names_stable_how4), 0, "nfs.stable_how4", HFILL }},
+
+ { &hf_nfs_dirlist4_eof, {
+ "eof", "nfs.dirlist4.eof", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.dirlist4.eof", HFILL }},
+
+ { &hf_nfs_stateid4, {
+ "stateid", "nfs.stateid4", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.stateid4", HFILL }},
+
+ { &hf_nfs_offset4, {
+ "offset", "nfs.offset4", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.offset4", HFILL }},
+
+ { &hf_nfs_specdata1, {
+ "specdata1", "nfs.specdata1", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.specdata1", HFILL }},
+
+ { &hf_nfs_specdata2, {
+ "specdata2", "nfs.specdata2", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.specdata2", HFILL }},
+
+ { &hf_nfs_lock_type4, {
+ "locktype", "nfs.locktype4", FT_UINT32, BASE_DEC,
+ VALS(names_nfs_lock_type4), 0, "nfs.locktype4", HFILL }},
+
+ { &hf_nfs_reclaim4, {
+ "reclaim", "nfs.reclaim4", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "Reclaim", HFILL }},
+
+ { &hf_nfs_length4, {
+ "length", "nfs.length4", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.length4", HFILL }},
+
+ { &hf_nfs_changeid4, {
+ "changeid", "nfs.changeid4", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.changeid4", HFILL }},
+
+ { &hf_nfs_changeid4_before, {
+ "changeid (before)", "nfs.changeid4.before", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.changeid4.before", HFILL }},
+
+ { &hf_nfs_changeid4_after, {
+ "changeid (after)", "nfs.changeid4.after", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.changeid4.after", HFILL }},
+
+ { &hf_nfs_nfstime4_seconds, {
+ "seconds", "nfs.nfstime4.seconds", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.nfstime4.seconds", HFILL }},
+
+ { &hf_nfs_nfstime4_nseconds, {
+ "nseconds", "nfs.nfstime4.nseconds", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.nfstime4.nseconds", HFILL }},
+
+ { &hf_nfs_fsid4_major, {
+ "fsid4.major", "nfs.fsid4.major", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.nfstime4.fsid4.major", HFILL }},
+
+ { &hf_nfs_fsid4_minor, {
+ "fsid4.minor", "nfs.fsid4.minor", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fsid4.minor", HFILL }},
+
+ { &hf_nfs_acetype4, {
+ "acetype", "nfs.acetype4", FT_UINT32, BASE_DEC,
+ VALS(names_acetype4), 0, "nfs.acetype4", HFILL }},
+
+ { &hf_nfs_aceflag4, {
+ "aceflag", "nfs.aceflag4", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.aceflag4", HFILL }},
+
+ { &hf_nfs_acemask4, {
+ "acemask", "nfs.acemask4", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.acemask4", HFILL }},
+
+ { &hf_nfs_fattr4_size, {
+ "size", "nfs.fattr4.size", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.size", HFILL }},
+
+ { &hf_nfs_fattr4_lease_time, {
+ "lease_time", "nfs.fattr4.lease_time", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr4.lease_time", HFILL }},
+
+ { &hf_nfs_fattr4_aclsupport, {
+ "aclsupport", "nfs.fattr4.aclsupport", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr4.aclsupport", HFILL }},
+
+ { &hf_nfs_fattr4_fileid, {
+ "fileid", "nfs.fattr4.fileid", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.fileid", HFILL }},
+
+ { &hf_nfs_fattr4_files_avail, {
+ "files_avail", "nfs.fattr4.files_avail", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.files_avail", HFILL }},
+
+ { &hf_nfs_fattr4_files_free, {
+ "files_free", "nfs.fattr4.files_free", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.files_free", HFILL }},
+
+ { &hf_nfs_fattr4_files_total, {
+ "files_total", "nfs.fattr4.files_total", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.files_total", HFILL }},
+
+ { &hf_nfs_fattr4_maxfilesize, {
+ "maxfilesize", "nfs.fattr4.maxfilesize", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.maxfilesize", HFILL }},
+
+ { &hf_nfs_fattr4_maxlink, {
+ "maxlink", "nfs.fattr4.maxlink", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr4.maxlink", HFILL }},
+
+ { &hf_nfs_fattr4_maxname, {
+ "maxname", "nfs.fattr4.maxname", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr4.maxname", HFILL }},
+
+ { &hf_nfs_fattr4_numlinks, {
+ "numlinks", "nfs.fattr4.numlinks", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.fattr4.numlinks", HFILL }},
+
+ { &hf_nfs_delegate_type, {
+ "delegate_type", "nfs.delegate_type", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.delegate_type", HFILL }},
+
+ { &hf_nfs_secinfo_flavor, {
+ "flavor", "nfs.secinfo.flavor", FT_UINT32, BASE_DEC,
+ VALS(rpc_auth_flavor), 0, "nfs.secinfo.flavor", HFILL }},
+
+ { &hf_nfs_num_blocks, {
+ "num_blocks", "nfs.num_blocks", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.num_blocks", HFILL }},
+
+ { &hf_nfs_bytes_per_block, {
+ "bytes_per_block", "nfs.bytes_per_block", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.bytes_per_block", HFILL }},
+
+ { &hf_nfs_eof, {
+ "eof", "nfs.eof", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.eof", HFILL }},
+
+ { &hf_nfs_fattr4_maxread, {
+ "maxread", "nfs.fattr4.maxread", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.maxread", HFILL }},
+
+ { &hf_nfs_fattr4_maxwrite, {
+ "maxwrite", "nfs.fattr4.maxwrite", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.maxwrite", HFILL }},
+
+ { &hf_nfs_fattr4_quota_hard, {
+ "quota_hard", "nfs.fattr4.quota_hard", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.quota_hard", HFILL }},
+
+ { &hf_nfs_fattr4_quota_soft, {
+ "quota_soft", "nfs.fattr4.quota_soft", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.quota_soft", HFILL }},
+
+ { &hf_nfs_fattr4_quota_used, {
+ "quota_used", "nfs.fattr4.quota_used", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.quota_used", HFILL }},
+
+ { &hf_nfs_fattr4_space_avail, {
+ "space_avail", "nfs.fattr4.space_avail", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.space_avail", HFILL }},
+
+ { &hf_nfs_fattr4_space_free, {
+ "space_free", "nfs.fattr4.space_free", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.space_free", HFILL }},
+
+ { &hf_nfs_fattr4_space_total, {
+ "space_total", "nfs.fattr4.space_total", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.space_total", HFILL }},
+
+ { &hf_nfs_fattr4_space_used, {
+ "space_used", "nfs.fattr4.space_used", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.fattr4.space_used", HFILL }},
+
+ { &hf_nfs_stateid4_delegate_stateid, {
+ "delegate_stateid", "nfs.delegate_stateid", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.delegate_stateid", HFILL }},
+
+ { &hf_nfs_verifier4, {
+ "verifier", "nfs.verifier4", FT_UINT64, BASE_HEX,
+ NULL, 0, "nfs.verifier4", HFILL }},
+
+ { &hf_nfs_cookie4, {
+ "cookie", "nfs.cookie4", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.cookie4", HFILL }},
+
+ { &hf_nfs_cookieverf4, {
+ "cookieverf", "nfs.cookieverf4", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.cookieverf4", HFILL }},
+
+ { &hf_nfs_cb_location, {
+ "cb_location", "nfs.cb_location", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.cb_location", HFILL }},
+
+ { &hf_nfs_cb_program, {
+ "cb_program", "nfs.cb_program", FT_UINT32, BASE_HEX,
+ NULL, 0, "nfs.cb_program", HFILL }},
+
+ { &hf_nfs_recall4, {
+ "recall", "nfs.recall4", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.recall4", HFILL }},
+
+ { &hf_nfs_filesize, {
+ "filesize", "nfs.filesize", FT_UINT64, BASE_DEC,
+ NULL, 0, "nfs.filesize", HFILL }},
+
+ { &hf_nfs_count4, {
+ "count", "nfs.count4", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.count4", HFILL }},
+
+ { &hf_nfs_count4_dircount, {
+ "dircount", "nfs.dircount", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.dircount", HFILL }},
+
+ { &hf_nfs_count4_maxcount, {
+ "maxcount", "nfs.maxcount", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.maxcount", HFILL }},
+
+ { &hf_nfs_minorversion, {
+ "minorversion", "nfs.minorversion", FT_UINT32, BASE_DEC,
+ NULL, 0, "nfs.minorversion", HFILL }},
+
+ { &hf_nfs_atime, {
+ "atime", "nfs.atime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Access Time", HFILL }},
+
+ { &hf_nfs_atime_sec, {
+ "seconds", "nfs.atime.sec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Access Time, Seconds", HFILL }},
+
+ { &hf_nfs_atime_nsec, {
+ "nano seconds", "nfs.atime.nsec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Access Time, Nano-seconds", HFILL }},
+
+ { &hf_nfs_atime_usec, {
+ "micro seconds", "nfs.atime.usec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Access Time, Micro-seconds", HFILL }},
+
+ { &hf_nfs_mtime, {
+ "mtime", "nfs.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Modify Time", HFILL }},
+
+ { &hf_nfs_mtime_sec, {
+ "seconds", "nfs.mtime.sec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Modify Seconds", HFILL }},
+
+ { &hf_nfs_mtime_nsec, {
+ "nano seconds", "nfs.mtime.nsec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Modify Time, Nano-seconds", HFILL }},
+
+ { &hf_nfs_mtime_usec, {
+ "micro seconds", "nfs.mtime.usec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Modify Time, Micro-seconds", HFILL }},
+
+ { &hf_nfs_ctime, {
+ "ctime", "nfs.ctime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Creation Time", HFILL }},
+
+ { &hf_nfs_ctime_sec, {
+ "seconds", "nfs.ctime.sec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Creation Time, Seconds", HFILL }},
+
+ { &hf_nfs_ctime_nsec, {
+ "nano seconds", "nfs.ctime.nsec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Creation Time, Nano-seconds", HFILL }},
+
+ { &hf_nfs_ctime_usec, {
+ "micro seconds", "nfs.ctime.usec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Creation Time, Micro-seconds", HFILL }},
+
+ { &hf_nfs_dtime, {
+ "time delta", "nfs.dtime", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Time Delta", HFILL }},
+
+ { &hf_nfs_dtime_sec, {
+ "seconds", "nfs.dtime.sec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Time Delta, Seconds", HFILL }},
+
+ { &hf_nfs_dtime_nsec, {
+ "nano seconds", "nfs.dtime.nsec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Time Delta, Nano-seconds", HFILL }},
+
+ { &hf_nfs_open_owner4, {
+ "owner", "nfs.open_owner4", FT_BYTES, BASE_DEC,
+ NULL, 0, "owner", HFILL }},
+
+ { &hf_nfs_lock_owner4, {
+ "owner", "nfs.lock_owner4", FT_BYTES, BASE_DEC,
+ NULL, 0, "owner", HFILL }},
+
+ { &hf_nfs_secinfo_rpcsec_gss_info_service, {
+ "service", "nfs.secinfo.rpcsec_gss_info.service", FT_UINT32,
+ BASE_DEC, VALS(rpc_authgss_svc), 0, "service", HFILL }},
+
+ { &hf_nfs_attrdircreate, {
+ "attribute dir create", "nfs.openattr4.createdir", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.openattr4.createdir", HFILL }},
+
+ { &hf_nfs_new_lock_owner, {
+ "new lock owner?", "nfs.lock.locker.new_lock_owner", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.lock.locker.new_lock_owner", HFILL }},
+
+ { &hf_nfs_lock4_reclaim, {
+ "reclaim?", "nfs.lock.reclaim", FT_BOOLEAN,
+ BASE_NONE, &yesno, 0, "nfs.lock.reclaim", HFILL }},
+
+ { &hf_nfs_sec_oid4, {
+ "oid", "nfs.secinfo.flavor_info.rpcsec_gss_info.oid", FT_BYTES,
+ BASE_DEC, NULL, 0, "oid", HFILL }},
+
+ { &hf_nfs_qop4, {
+ "qop", "nfs.secinfo.flavor_info.rpcsec_gss_info.qop", FT_UINT32,
+ BASE_DEC, NULL, 0, "qop", HFILL }},
+
+ { &hf_nfs_client_id4_id, {
+ "id", "nfs.nfs_client_id4.id", FT_BYTES, BASE_DEC,
+ NULL, 0, "nfs.nfs_client_id4.id", HFILL }},
+
+ { &hf_nfs_stateid4_other, {
+ "Data", "nfs.stateid4.other", FT_BYTES, BASE_DEC,
+ NULL, 0, "Data", HFILL }},
+
+ { &hf_nfs_acl4, {
+ "ACL", "nfs.acl", FT_NONE, BASE_NONE,
+ NULL, 0, "Access Control List", HFILL }},
+
+ { &hf_nfs_callback_ident, {
+ "callback_ident", "nfs.callback.ident", FT_UINT32, BASE_HEX,
+ NULL, 0, "Callback Identifier", HFILL }},
+
+ { &hf_nfs_r_netid, {
+ "r_netid", "nfs.r_netid", FT_BYTES, BASE_DEC, NULL, 0,
+ "r_netid", HFILL }},
+
+ { &hf_nfs_r_addr, {
+ "r_addr", "nfs.r_addr", FT_BYTES, BASE_DEC, NULL, 0,
+ "r_addr", HFILL }},
+
+ { &hf_nfs_secinfo_arr4, {
+ "Flavors Info", "nfs.flavors.info", FT_NONE, BASE_NONE,
+ NULL, 0, "Flavors Info", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_nfs,
+ &ett_nfs_fh_encoding,
+ &ett_nfs_fh_fsid,
+ &ett_nfs_fh_file,
+ &ett_nfs_fh_mount,
+ &ett_nfs_fh_export,
+ &ett_nfs_fh_xfsid,
+ &ett_nfs_fh_fn,
+ &ett_nfs_fh_xfn,
+ &ett_nfs_fh_hp,
+ &ett_nfs_fh_auth,
+ &ett_nfs_fhandle,
+ &ett_nfs_timeval,
+ &ett_nfs_mode,
+ &ett_nfs_fattr,
+ &ett_nfs_sattr,
+ &ett_nfs_diropargs,
+ &ett_nfs_readdir_entry,
+ &ett_nfs_mode3,
+ &ett_nfs_specdata3,
+ &ett_nfs_fh3,
+ &ett_nfs_nfstime3,
+ &ett_nfs_fattr3,
+ &ett_nfs_post_op_fh3,
+ &ett_nfs_sattr3,
+ &ett_nfs_diropargs3,
+ &ett_nfs_sattrguard3,
+ &ett_nfs_set_mode3,
+ &ett_nfs_set_uid3,
+ &ett_nfs_set_gid3,
+ &ett_nfs_set_size3,
+ &ett_nfs_set_atime,
+ &ett_nfs_set_mtime,
+ &ett_nfs_pre_op_attr,
+ &ett_nfs_post_op_attr,
+ &ett_nfs_wcc_attr,
+ &ett_nfs_wcc_data,
+ &ett_nfs_access,
+ &ett_nfs_fsinfo_properties,
+ &ett_nfs_compound_call4,
+ &ett_nfs_utf8string,
+ &ett_nfs_argop4,
+ &ett_nfs_resop4,
+ &ett_nfs_access4,
+ &ett_nfs_close4,
+ &ett_nfs_commit4,
+ &ett_nfs_create4,
+ &ett_nfs_delegpurge4,
+ &ett_nfs_delegreturn4,
+ &ett_nfs_getattr4,
+ &ett_nfs_getfh4,
+ &ett_nfs_link4,
+ &ett_nfs_lock4,
+ &ett_nfs_lockt4,
+ &ett_nfs_locku4,
+ &ett_nfs_lookup4,
+ &ett_nfs_lookupp4,
+ &ett_nfs_nverify4,
+ &ett_nfs_open4,
+ &ett_nfs_openattr4,
+ &ett_nfs_open_confirm4,
+ &ett_nfs_open_downgrade4,
+ &ett_nfs_putfh4,
+ &ett_nfs_putpubfh4,
+ &ett_nfs_putrootfh4,
+ &ett_nfs_read4,
+ &ett_nfs_readdir4,
+ &ett_nfs_readlink4,
+ &ett_nfs_remove4,
+ &ett_nfs_rename4,
+ &ett_nfs_renew4,
+ &ett_nfs_restorefh4,
+ &ett_nfs_savefh4,
+ &ett_nfs_setattr4,
+ &ett_nfs_setclientid4,
+ &ett_nfs_setclientid_confirm4,
+ &ett_nfs_verify4,
+ &ett_nfs_write4,
+ &ett_nfs_release_lockowner4,
+ &ett_nfs_illegal4,
+ &ett_nfs_verifier4,
+ &ett_nfs_opaque,
+ &ett_nfs_dirlist4,
+ &ett_nfs_pathname4,
+ &ett_nfs_change_info4,
+ &ett_nfs_open_delegation4,
+ &ett_nfs_open_claim4,
+ &ett_nfs_opentype4,
+ &ett_nfs_lock_owner4,
+ &ett_nfs_cb_client4,
+ &ett_nfs_client_id4,
+ &ett_nfs_bitmap4,
+ &ett_nfs_fattr4,
+ &ett_nfs_fsid4,
+ &ett_nfs_fs_locations4,
+ &ett_nfs_fs_location4,
+ &ett_nfs_open4_result_flags,
+ &ett_nfs_secinfo4,
+ &ett_nfs_secinfo4_flavor_info,
+ &ett_nfs_stateid4,
+ &ett_nfs_fattr4_fh_expire_type,
+ &ett_nfs_ace4,
+ &ett_nfs_clientaddr4,
+ &ett_nfs_aceflag4,
+ &ett_nfs_acemask4,
+ };
+ module_t *nfs_module;
+
+ proto_nfs = proto_register_protocol("Network File System", "NFS", "nfs");
+ proto_register_field_array(proto_nfs, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ nfs_module=prefs_register_protocol(proto_nfs, NULL);
+ prefs_register_bool_preference(nfs_module, "file_name_snooping",
+ "Snoop FH to filename mappings",
+ "Whether the dissector should snoop the FH to filename mappings by looking inside certain packets",
+ &nfs_file_name_snooping);
+ prefs_register_bool_preference(nfs_module, "file_full_name_snooping",
+ "Snoop full path to filenames",
+ "Whether the dissector should snoop the full pathname for files for matching FH's",
+ &nfs_file_name_full_snooping);
+ prefs_register_bool_preference(nfs_module, "fhandle_find_both_reqrep",
+ "Fhandle filters finds both request/response",
+ "With this option display filters for nfs fhandles (nfs.fh.{name|full_name|hash}) will find both the request and response packets for a RPC call, even if the actual fhandle is only present in one of the packets",
+ &nfs_fhandle_reqrep_matching);
+ register_init_routine(nfs_name_snoop_init);
+ register_init_routine(nfs_fhandle_reqrep_matching_init);
+}
+
+void
+proto_reg_handoff_nfs(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_nfs, NFS_PROGRAM, ett_nfs);
+ /* Register the procedure tables */
+ rpc_init_proc_table(NFS_PROGRAM, 2, nfs2_proc, hf_nfs_procedure_v2);
+ rpc_init_proc_table(NFS_PROGRAM, 3, nfs3_proc, hf_nfs_procedure_v3);
+ rpc_init_proc_table(NFS_PROGRAM, 4, nfs4_proc, hf_nfs_procedure_v4);
+}
diff --git a/epan/dissectors/packet-nfs.h b/epan/dissectors/packet-nfs.h
new file mode 100644
index 0000000000..5c5be608df
--- /dev/null
+++ b/epan/dissectors/packet-nfs.h
@@ -0,0 +1,132 @@
+/* packet-nfs.h (c) 1999 Uwe Girlich */
+/* $Id$ */
+
+#ifndef __PACKET_NFS_H__
+#define __PACKET_NFS_H__
+
+#include "packet-rpc.h"
+
+#define NFS_PROGRAM 100003
+
+#define FHSIZE 32
+
+/* verifier */
+#define NFS3_COOKIEVERFSIZE 8
+#define NFS3_CREATEVERFSIZE 8
+#define NFS3_WRITEVERFSIZE 8
+
+/* for ftype3 */
+#define NF3REG 1
+#define NF3DIR 2
+#define NF3BLK 3
+#define NF3CHR 4
+#define NF3LNK 5
+#define NF3SOCK 6
+#define NF3FIFO 7
+
+/*
+ * NFSv4 error codes used in code, as opposed to UI
+ */
+#define NFS4_OK 0
+#define NFS4ERR_DENIED 10010
+#define NFS4ERR_CLID_INUSE 10017
+
+/*
+ * NFSv4 file types
+ */
+#define NF4REG 1
+#define NF4DIR 2
+#define NF4BLK 3
+#define NF4CHR 4
+#define NF4LNK 5
+#define NF4SOCK 6
+#define NF4FIFO 7
+#define NF4ATTRDIR 8
+#define NF4NAMEDATTR 9
+
+/*
+ * Since NFSv4 "operations" are handled differently than previous NFS
+ * versions, these tokens are necessary.
+ */
+#define NFS4_OP_ACCESS 3
+#define NFS4_OP_CLOSE 4
+#define NFS4_OP_COMMIT 5
+#define NFS4_OP_CREATE 6
+#define NFS4_OP_DELEGPURGE 7
+#define NFS4_OP_DELEGRETURN 8
+#define NFS4_OP_GETATTR 9
+#define NFS4_OP_GETFH 10
+#define NFS4_OP_LINK 11
+#define NFS4_OP_LOCK 12
+#define NFS4_OP_LOCKT 13
+#define NFS4_OP_LOCKU 14
+#define NFS4_OP_LOOKUP 15
+#define NFS4_OP_LOOKUPP 16
+#define NFS4_OP_NVERIFY 17
+#define NFS4_OP_OPEN 18
+#define NFS4_OP_OPENATTR 19
+#define NFS4_OP_OPEN_CONFIRM 20
+#define NFS4_OP_OPEN_DOWNGRADE 21
+#define NFS4_OP_PUTFH 22
+#define NFS4_OP_PUTPUBFH 23
+#define NFS4_OP_PUTROOTFH 24
+#define NFS4_OP_READ 25
+#define NFS4_OP_READDIR 26
+#define NFS4_OP_READLINK 27
+#define NFS4_OP_REMOVE 28
+#define NFS4_OP_RENAME 29
+#define NFS4_OP_RENEW 30
+#define NFS4_OP_RESTOREFH 31
+#define NFS4_OP_SAVEFH 32
+#define NFS4_OP_SECINFO 33
+#define NFS4_OP_SETATTR 34
+#define NFS4_OP_SETCLIENTID 35
+#define NFS4_OP_SETCLIENTID_CONFIRM 36
+#define NFS4_OP_VERIFY 37
+#define NFS4_OP_WRITE 38
+#define NFS4_OP_RELEASE_LOCKOWNER 39
+#define NFS4_OP_ILLEGAL 10044
+
+/* for write */
+#define UNSTABLE 0
+#define DATA_SYNC 1
+#define FILE_SYNC 2
+
+/* for create */
+#define UNCHECKED 0
+#define GUARDED 1
+#define EXCLUSIVE 2
+
+extern gboolean nfs_file_name_snooping;
+
+extern int dissect_fhandle(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
+ char *name, guint32 *hash);
+extern int dissect_nfs_fh3(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
+ char *name, guint32 *hash);
+
+int dissect_nfs_post_op_attr(tvbuff_t *tvb, int offset, proto_tree *tree,
+ char* name);
+
+void nfs_name_snoop_add_name(int xid, tvbuff_t *tvb, int name_offset, int name_len, int parent_offset, int parent_len, unsigned char *name);
+
+
+extern gboolean nfs_fhandle_reqrep_matching;
+extern GHashTable *nfs_fhandle_frame_table;
+typedef struct nfs_fhandle_data {
+ int len;
+ const unsigned char *fh;
+ tvbuff_t *tvb;
+} nfs_fhandle_data_t;
+void dissect_fhandle_hidden(packet_info *pinfo, proto_tree *tree, nfs_fhandle_data_t *nfd);
+
+typedef int (diss_p)(tvbuff_t *tvb, int offset, proto_tree *tree, int hf);
+
+/* Used in packet-nfsacl.c for NFS_ACL dissection */
+extern int dissect_fattr(tvbuff_t *tvb, int offset, proto_tree *tree,
+ char* name);
+
+extern int dissect_access(tvbuff_t *tvb, int offset, proto_tree *tree,
+ char* name);
+
+#endif /* packet-nfs.h */
+
diff --git a/epan/dissectors/packet-nfsacl.c b/epan/dissectors/packet-nfsacl.c
new file mode 100644
index 0000000000..5999ec45d2
--- /dev/null
+++ b/epan/dissectors/packet-nfsacl.c
@@ -0,0 +1,638 @@
+/* packet-nfsacl.c
+ * Stubs for Sun's NFS ACL RPC service (runs on port 2049, and is presumably
+ * handled by the same kernel server code that handles NFS)
+ *
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "packet-rpc.h"
+#include "packet-nfs.h"
+
+static int proto_nfsacl = -1;
+static int hf_nfsacl_procedure_v1 = -1;
+static int hf_nfsacl_procedure_v2 = -1;
+static int hf_nfsacl_procedure_v3 = -1;
+static int hf_nfsacl_entry = -1;
+static int hf_nfsacl_aclcnt = -1;
+static int hf_nfsacl_dfaclcnt = -1;
+static int hf_nfsacl2_status = -1;
+static int hf_nfsacl3_status = -1;
+static int hf_nfsacl_aclent = -1;
+static int hf_nfsacl_aclent_type = -1;
+static int hf_nfsacl_aclent_uid = -1;
+static int hf_nfsacl_aclent_perm = -1;
+static int hf_nfsacl_create = -1;
+
+static gint ett_nfsacl = -1;
+static gint ett_nfsacl_mask = -1;
+static gint ett_nfsacl_entry = -1;
+static gint ett_nfsacl_aclent = -1;
+static gint ett_nfsacl_aclent_perm = -1;
+static gint ett_nfsacl_aclent_entries = -1;
+
+#define NFSACL_PROGRAM 100227
+
+#define NFSACLPROC_NULL 0
+
+#define NFSACLPROC2_GETACL 1
+#define NFSACLPROC2_SETACL 2
+#define NFSACLPROC2_GETATTR 3
+#define NFSACLPROC2_ACCESS 4
+#define NFSACLPROC2_GETXATTRDIR 5
+
+#define NFSACLPROC3_GETACL 1
+#define NFSACLPROC3_SETACL 2
+#define NFSACLPROC3_GETXATTRDIR 3
+
+#define ACL2_OK 0
+#define ACL3_OK 0
+
+static int
+dissect_nfsacl_mask(tvbuff_t *tvb, int offset, proto_tree *tree,
+ char *name)
+{
+ guint32 mask;
+ proto_item *mask_item = NULL;
+ proto_tree *mask_tree = NULL;
+
+ mask = tvb_get_ntohl(tvb, offset + 0);
+
+ if (tree)
+ {
+ mask_item = proto_tree_add_text(tree, tvb, offset, 4, "%s: 0x%02x",
+ name, mask);
+
+ if (mask_item)
+ mask_tree = proto_item_add_subtree(mask_item, ett_nfsacl_mask);
+ }
+
+ if (mask_tree)
+ {
+ proto_tree_add_text(mask_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mask, 0x01, 8, "ACL entry",
+ "(no ACL entry)"));
+ proto_tree_add_text(mask_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mask, 0x02, 8, "ACL count",
+ "(no ACL count)"));
+ proto_tree_add_text(mask_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mask, 0x04, 8, "default ACL entry",
+ "(no default ACL entry)"));
+ proto_tree_add_text(mask_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(mask, 0x08, 8, "default ACL count",
+ "(no default ACL count)"));
+ }
+
+ offset += 4;
+ return offset;
+}
+
+#define NA_READ 0x4
+#define NA_WRITE 0x2
+#define NA_EXEC 0x1
+
+static const value_string names_nfsacl_aclent_type[] = {
+#define NA_USER_OBJ 0x1
+ { NA_USER_OBJ, "NA_USER_OBJ" },
+#define NA_USER 0x2
+ { NA_USER, "NA_USER" },
+#define NA_GROUP_OBJ 0x4
+ { NA_GROUP_OBJ, "NA_GROUP_OBJ" },
+#define NA_GROUP 0x8
+ { NA_GROUP, "NA_GROUP" },
+#define NA_CLASS_OBJ 0x10
+ { NA_CLASS_OBJ, "NA_CLASS_OBJ" },
+#define NA_OTHER_OBJ 0x20
+ { NA_OTHER_OBJ, "NA_OTHER_OBJ" },
+#define NA_ACL_DEFAULT 0x1000
+ { NA_ACL_DEFAULT, "NA_ACL_DEFAULT" },
+ { NA_ACL_DEFAULT | NA_USER_OBJ, "Default NA_USER_OBJ" },
+ { NA_ACL_DEFAULT | NA_USER, "Default NA_USER" },
+ { NA_ACL_DEFAULT | NA_GROUP_OBJ, "Default NA_GROUP_OBJ" },
+ { NA_ACL_DEFAULT | NA_GROUP, "Default NA_GROUP" },
+ { NA_ACL_DEFAULT | NA_CLASS_OBJ, "Default NA_CLASS_OBJ" },
+ { NA_ACL_DEFAULT | NA_OTHER_OBJ, "Default NA_OTHER_OBJ" },
+ { 0, NULL },
+};
+
+static int
+dissect_nfsacl_aclent(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree* tree)
+{
+ proto_item *entry_item = NULL;
+ proto_tree *entry_tree = NULL;
+ guint32 perm;
+ proto_item *perm_item = NULL;
+ proto_tree *perm_tree = NULL;
+
+ if (tree)
+ {
+ entry_item = proto_tree_add_item(tree, hf_nfsacl_aclent, tvb,
+ offset + 0, -1, FALSE);
+ entry_tree = proto_item_add_subtree(entry_item, ett_nfsacl_aclent);
+ }
+
+ offset = dissect_rpc_uint32(tvb, entry_tree, hf_nfsacl_aclent_type, offset);
+ offset = dissect_rpc_uint32(tvb, entry_tree, hf_nfsacl_aclent_uid, offset);
+
+ perm = tvb_get_ntohl(tvb, offset);
+
+ perm_item = proto_tree_add_uint(entry_tree, hf_nfsacl_aclent_perm,
+ tvb, offset, 4, perm);
+
+ if (perm_item)
+ perm_tree = proto_item_add_subtree(perm_item, ett_nfsacl_aclent_perm);
+
+ if (perm_tree)
+ {
+ proto_tree_add_text(perm_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(perm, NA_READ, 4, "READ", "no READ"));
+
+ proto_tree_add_text(perm_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(perm, NA_WRITE, 4, "WRITE", "no WRITE"));
+
+ proto_tree_add_text(perm_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(perm, NA_EXEC, 4, "EXEC", "no EXEC"));
+ }
+
+ offset += 4;
+
+ return offset;
+}
+
+
+static int
+dissect_nfsacl_secattr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 aclcnt, dfaclcnt;
+ guint32 i;
+ proto_item *entry_item = NULL;
+ proto_tree *entry_tree = NULL;
+
+ offset = dissect_nfsacl_mask(tvb, offset, tree, "mask");
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfsacl_aclcnt, offset);
+
+ aclcnt = tvb_get_ntohl(tvb, offset);
+
+ entry_item = proto_tree_add_text(tree, tvb, offset, 4,
+ "Total ACL entries: %d", aclcnt);
+
+ if (entry_item)
+ entry_tree = proto_item_add_subtree(entry_item,
+ ett_nfsacl_aclent_entries);
+
+ offset += 4;
+
+ if (aclcnt > 0)
+ {
+ for (i = 0; i < aclcnt; i++)
+ offset = dissect_nfsacl_aclent(tvb, offset, pinfo, entry_tree);
+ }
+
+ /* */
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_nfsacl_dfaclcnt, offset);
+
+ dfaclcnt = tvb_get_ntohl(tvb, offset);
+
+ entry_item = proto_tree_add_text(tree, tvb, offset, 4,
+ "Total default ACL entries: %d", dfaclcnt);
+
+ if (entry_item)
+ entry_tree = proto_item_add_subtree(entry_item,
+ ett_nfsacl_aclent_entries);
+
+ offset += 4;
+
+ if (dfaclcnt > 0)
+ {
+ for (i = 0; i < dfaclcnt; i++)
+ offset = dissect_nfsacl_aclent(tvb, offset, pinfo, entry_tree);
+ }
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff nfsacl1_proc[] = {
+ { NFSACLPROC_NULL, "NULL",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string nfsacl1_proc_vals[] = {
+ { NFSACLPROC_NULL, "NULL" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfsacl2_getacl_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "fhandle", NULL);
+ offset = dissect_nfsacl_mask(tvb, offset, tree, "mask");
+ return offset;
+}
+
+static int
+dissect_nfsacl2_getacl_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 status;
+
+ status = tvb_get_ntohl(tvb, offset + 0);
+
+ proto_tree_add_uint(tree, hf_nfsacl2_status, tvb, offset + 0, 4, status);
+
+ offset += 4;
+
+ if (status == ACL2_OK)
+ {
+ offset = dissect_fattr(tvb, offset, tree, "attr");
+ offset = dissect_nfsacl_secattr(tvb, offset, pinfo, tree);
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfsacl2_setacl_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "fhandle", NULL);
+ offset = dissect_nfsacl_secattr(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+static int
+dissect_nfsacl2_setacl_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 status;
+
+ status = tvb_get_ntohl(tvb, offset + 0);
+
+ proto_tree_add_uint(tree, hf_nfsacl2_status, tvb, offset + 0, 4, status);
+
+ offset += 4;
+
+ if (status == ACL2_OK)
+ offset = dissect_fattr(tvb, offset, tree, "attr");
+
+ return offset;
+}
+
+static int
+dissect_nfsacl2_getattr_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "fhandle", NULL);
+
+ return offset;
+}
+
+static int
+dissect_nfsacl2_getattr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ offset = dissect_fattr(tvb, offset, tree, "attr");
+
+ return offset;
+}
+
+static int
+dissect_nfsacl2_access_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "fhandle", NULL);
+ offset = dissect_access(tvb, offset, tree, "access");
+
+ return offset;
+}
+
+static int
+dissect_nfsacl2_access_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 status;
+
+ status = tvb_get_ntohl(tvb, offset + 0);
+
+ proto_tree_add_uint(tree, hf_nfsacl2_status, tvb, offset + 0, 4, status);
+
+ offset += 4;
+
+ if (status == ACL2_OK)
+ {
+ offset = dissect_fattr(tvb, offset, tree, "attr");
+ offset = dissect_access(tvb, offset, tree, "access");
+ }
+
+ return offset;
+}
+
+static int
+dissect_nfsacl2_getxattrdir_call(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "fhandle", NULL);
+ offset = dissect_rpc_bool(tvb, tree, hf_nfsacl_create, offset);
+
+ return offset;
+}
+
+static int
+dissect_nfsacl2_getxattrdir_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 status;
+
+ status = tvb_get_ntohl(tvb, offset + 0);
+
+ proto_tree_add_uint(tree, hf_nfsacl2_status, tvb, offset + 0, 4, status);
+
+ offset += 4;
+
+ if (status == ACL2_OK)
+ {
+ offset = dissect_fhandle(tvb, offset, pinfo, tree, "fhandle", NULL);
+ offset = dissect_fattr(tvb, offset, tree, "attr");
+ }
+
+ return offset;
+}
+
+static const vsff nfsacl2_proc[] = {
+ { NFSACLPROC_NULL, "NULL",
+ NULL, NULL },
+ { NFSACLPROC2_GETACL, "GETACL",
+ dissect_nfsacl2_getacl_call, dissect_nfsacl2_getacl_reply },
+ { NFSACLPROC2_SETACL, "SETACL",
+ dissect_nfsacl2_setacl_call, dissect_nfsacl2_setacl_reply },
+ { NFSACLPROC2_GETATTR, "GETATTR",
+ dissect_nfsacl2_getattr_call, dissect_nfsacl2_getattr_reply },
+ { NFSACLPROC2_ACCESS, "ACCESS",
+ dissect_nfsacl2_access_call, dissect_nfsacl2_access_reply },
+ { NFSACLPROC2_GETXATTRDIR, "GETXATTRDIR",
+ dissect_nfsacl2_getxattrdir_call, dissect_nfsacl2_getxattrdir_reply },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string nfsacl2_proc_vals[] = {
+ { NFSACLPROC_NULL, "NULL" },
+ { NFSACLPROC2_GETACL, "GETACL" },
+ { NFSACLPROC2_SETACL, "SETACL" },
+ { NFSACLPROC2_GETATTR, "GETATTR" },
+ { NFSACLPROC2_ACCESS, "ACCESS" },
+ { NFSACLPROC2_GETXATTRDIR, "GETXATTRDIR" },
+ { 0, NULL }
+};
+
+static int
+dissect_nfsacl3_getacl_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "fhandle", NULL);
+ offset = dissect_nfsacl_mask(tvb, offset, tree, "mask");
+
+ return offset;
+}
+
+static int
+dissect_nfsacl3_getacl_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 status;
+ proto_item *entry_item = NULL;
+ proto_tree *entry_tree = NULL;
+
+ status = tvb_get_ntohl(tvb, offset + 0);
+
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfsacl3_status, tvb, offset + 0, 4,
+ status);
+
+ offset += 4;
+
+ if (tree)
+ {
+ entry_item = proto_tree_add_item(tree, hf_nfsacl_entry, tvb,
+ offset + 0, -1, FALSE);
+ if (entry_item)
+ entry_tree = proto_item_add_subtree(entry_item, ett_nfsacl_entry);
+ }
+
+ if (entry_tree)
+ offset = dissect_nfs_post_op_attr(tvb, offset, entry_tree, "attr");
+
+ if (status != ACL3_OK)
+ return offset;
+
+ if (entry_tree)
+ offset = dissect_nfsacl_secattr(tvb, offset, pinfo, entry_tree);
+
+ return offset;
+}
+
+static int
+dissect_nfsacl3_setacl_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+
+{
+ proto_item *acl_item = NULL;
+ proto_tree *acl_tree = NULL;
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "fhandle", NULL);
+
+ if (tree)
+ {
+ acl_item = proto_tree_add_item(tree, hf_nfsacl_entry, tvb, offset + 0,
+ -1, FALSE);
+
+ if (acl_item)
+ acl_tree = proto_item_add_subtree(acl_item, ett_nfsacl_entry);
+ }
+
+ if (acl_tree)
+ offset = dissect_nfsacl_secattr(tvb, offset, pinfo, acl_tree);
+
+ return offset;
+}
+
+static int
+dissect_nfsacl3_setacl_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 status = tvb_get_ntohl(tvb, offset + 0);
+
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfsacl3_status, tvb, offset + 0, 4,
+ status);
+
+ offset += 4;
+
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree, "attr");
+
+ return offset;
+}
+
+static int
+dissect_nfsacl3_getxattrdir_call(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree)
+
+{
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "fhandle", NULL);
+ offset = dissect_rpc_bool(tvb, tree, hf_nfsacl_create, offset);
+
+ return offset;
+}
+
+static int
+dissect_nfsacl3_getxattrdir_reply(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 status;
+
+ status = tvb_get_ntohl(tvb, offset + 0);
+
+ if (tree)
+ proto_tree_add_uint(tree, hf_nfsacl3_status, tvb, offset + 0, 4,
+ status);
+
+ offset += 4;
+
+ if (status == ACL3_OK)
+ {
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, tree, "fhandle", NULL);
+ offset = dissect_nfs_post_op_attr(tvb, offset, tree, "attr");
+ }
+
+ return offset;
+}
+
+static const vsff nfsacl3_proc[] = {
+ { NFSACLPROC_NULL, "NULL",
+ NULL, NULL },
+ { NFSACLPROC3_GETACL, "GETACL",
+ dissect_nfsacl3_getacl_call, dissect_nfsacl3_getacl_reply },
+ { NFSACLPROC3_SETACL, "SETACL",
+ dissect_nfsacl3_setacl_call, dissect_nfsacl3_setacl_reply },
+ { NFSACLPROC3_GETXATTRDIR, "GETXATTRDIR",
+ dissect_nfsacl3_getxattrdir_call, dissect_nfsacl3_getxattrdir_reply },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string nfsacl3_proc_vals[] = {
+ { NFSACLPROC_NULL, "NULL" },
+ { NFSACLPROC3_GETACL, "GETACL" },
+ { NFSACLPROC3_SETACL, "SETACL" },
+ { 0, NULL }
+};
+
+static const value_string names_nfsacl2_status[] = {
+ { ACL2_OK, "ACL2_OK" },
+ { 0, NULL }
+};
+
+static const value_string names_nfsacl3_status[] = {
+ { ACL3_OK, "ACL3_OK" },
+ { 0, NULL }
+};
+
+static struct true_false_string yesno = { "Yes", "No" };
+
+void
+proto_register_nfsacl(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_nfsacl_procedure_v1, {
+ "V1 Procedure", "nfsacl.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(nfsacl1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_nfsacl_procedure_v2, {
+ "V2 Procedure", "nfsacl.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(nfsacl2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_nfsacl_procedure_v3, {
+ "V3 Procedure", "nfsacl.procedure_v3", FT_UINT32, BASE_DEC,
+ VALS(nfsacl3_proc_vals), 0, "V3 Procedure", HFILL }},
+ /* generic */
+ { &hf_nfsacl_entry, {
+ "ACL", "nfsacl.acl", FT_NONE, 0,
+ NULL, 0, "ACL", HFILL }},
+ { &hf_nfsacl_aclcnt, {
+ "ACL count", "nfsacl.aclcnt", FT_UINT32, BASE_DEC,
+ NULL, 0, "ACL count", HFILL }},
+ { &hf_nfsacl_dfaclcnt, {
+ "Default ACL count", "nfsacl.dfaclcnt", FT_UINT32, BASE_DEC,
+ NULL, 0, "Default ACL count", HFILL }},
+ { &hf_nfsacl_aclent, {
+ "ACL Entry", "nfsacl.aclent", FT_NONE, 0,
+ NULL, 0, "ACL", HFILL }},
+ { &hf_nfsacl_aclent_type, {
+ "Type", "nfsacl.aclent.type", FT_UINT32, BASE_DEC,
+ VALS(names_nfsacl_aclent_type), 0, "Type", HFILL }},
+ { &hf_nfsacl_aclent_uid, {
+ "UID", "nfsacl.aclent.uid", FT_UINT32, BASE_DEC,
+ NULL, 0, "UID", HFILL }},
+ { &hf_nfsacl_aclent_perm, {
+ "Permissions", "nfsacl.aclent.perm", FT_UINT32, BASE_DEC,
+ NULL, 0, "Permissions", HFILL }},
+ /* V2 */
+ { &hf_nfsacl2_status, {
+ "Status", "nfsacl.status2", FT_UINT32, BASE_DEC,
+ VALS(names_nfsacl2_status), 0, "Status", HFILL }},
+ /* V3 */
+ { &hf_nfsacl3_status, {
+ "Status", "nfsacl.status3", FT_UINT32, BASE_DEC,
+ VALS(names_nfsacl3_status), 0, "Status", HFILL }},
+ { &hf_nfsacl_create, {
+ "create", "nfsacl.create", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "Create?", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_nfsacl,
+ &ett_nfsacl_mask,
+ &ett_nfsacl_entry,
+ &ett_nfsacl_aclent,
+ &ett_nfsacl_aclent_perm,
+ &ett_nfsacl_aclent_entries
+ };
+
+ proto_nfsacl = proto_register_protocol("NFSACL", "NFSACL", "nfsacl");
+ proto_register_field_array(proto_nfsacl, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_nfsacl(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_nfsacl, NFSACL_PROGRAM, ett_nfsacl);
+ /* Register the procedure tables */
+ rpc_init_proc_table(NFSACL_PROGRAM, 1, nfsacl1_proc, hf_nfsacl_procedure_v1);
+ rpc_init_proc_table(NFSACL_PROGRAM, 2, nfsacl2_proc, hf_nfsacl_procedure_v2);
+ rpc_init_proc_table(NFSACL_PROGRAM, 3, nfsacl3_proc, hf_nfsacl_procedure_v3);
+}
diff --git a/epan/dissectors/packet-nfsauth.c b/epan/dissectors/packet-nfsauth.c
new file mode 100644
index 0000000000..fb15990de9
--- /dev/null
+++ b/epan/dissectors/packet-nfsauth.c
@@ -0,0 +1,85 @@
+/* packet-nfsauth.c
+ * Stubs for Sun's NFS AUTH RPC service
+ *
+ * Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+
+static int proto_nfsauth = -1;
+static int hf_nfsauth_procedure_v1 = -1;
+
+static gint ett_nfsauth = -1;
+
+#define NFSAUTH_PROGRAM 100231
+
+#define NFSAUTHPROC_NULL 0
+#define NFSAUTH1_ACCESS 1
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff nfsauth1_proc[] = {
+ { NFSAUTHPROC_NULL, "NULL",
+ NULL, NULL },
+ { NFSAUTH1_ACCESS, "ACCESS",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string nfsauth1_proc_vals[] = {
+ { NFSAUTHPROC_NULL, "NULL" },
+ { NFSAUTH1_ACCESS, "ACCESS" },
+ { 0, NULL }
+};
+
+
+void
+proto_register_nfsauth(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_nfsauth_procedure_v1, {
+ "V1 Procedure", "nfsauth.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(nfsauth1_proc_vals), 0, "V1 Procedure", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_nfsauth,
+ };
+
+ proto_nfsauth = proto_register_protocol("NFSAUTH", "NFSAUTH", "nfsauth");
+ proto_register_field_array(proto_nfsauth, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_nfsauth(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_nfsauth, NFSAUTH_PROGRAM, ett_nfsauth);
+ /* Register the procedure tables */
+ rpc_init_proc_table(NFSAUTH_PROGRAM, 1, nfsauth1_proc, hf_nfsauth_procedure_v1);
+}
diff --git a/epan/dissectors/packet-nisplus.c b/epan/dissectors/packet-nisplus.c
new file mode 100644
index 0000000000..ed2975986e
--- /dev/null
+++ b/epan/dissectors/packet-nisplus.c
@@ -0,0 +1,1959 @@
+/* packet-nisplus.c
+ * 2001 Ronnie Sahlberg <See AUTHORS for email>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <time.h>
+
+#include "packet-rpc.h"
+#include "packet-nisplus.h"
+
+static int proto_nisplus = -1;
+static int hf_nisplus_procedure_v3 = -1;
+static int hf_nisplus_object = -1;
+static int hf_nisplus_oid = -1;
+static int hf_nisplus_object_ctime = -1;
+static int hf_nisplus_object_mtime = -1;
+static int hf_nisplus_object_name = -1;
+static int hf_nisplus_object_owner = -1;
+static int hf_nisplus_object_group = -1;
+static int hf_nisplus_object_domain = -1;
+static int hf_nisplus_object_ttl = -1;
+static int hf_nisplus_object_type = -1;
+static int hf_nisplus_object_private = -1;
+static int hf_nisplus_directory = -1;
+static int hf_nisplus_directory_name = -1;
+static int hf_nisplus_directory_type = -1;
+static int hf_nisplus_directory_ttl = -1;
+static int hf_nisplus_directory_mask = -1;
+static int hf_nisplus_directory_mask_list = -1;
+static int hf_nisplus_access_mask = -1;
+static int hf_nisplus_mask_world_read = -1;
+static int hf_nisplus_mask_world_modify = -1;
+static int hf_nisplus_mask_world_create = -1;
+static int hf_nisplus_mask_world_destroy = -1;
+static int hf_nisplus_mask_group_read = -1;
+static int hf_nisplus_mask_group_modify = -1;
+static int hf_nisplus_mask_group_create = -1;
+static int hf_nisplus_mask_group_destroy = -1;
+static int hf_nisplus_mask_owner_read = -1;
+static int hf_nisplus_mask_owner_modify = -1;
+static int hf_nisplus_mask_owner_create = -1;
+static int hf_nisplus_mask_owner_destroy = -1;
+static int hf_nisplus_mask_nobody_read = -1;
+static int hf_nisplus_mask_nobody_modify = -1;
+static int hf_nisplus_mask_nobody_create = -1;
+static int hf_nisplus_mask_nobody_destroy = -1;
+static int hf_nisplus_server_name = -1;
+static int hf_nisplus_key_type = -1;
+static int hf_nisplus_key_data = -1;
+static int hf_nisplus_servers = -1;
+static int hf_nisplus_cbservers = -1;
+static int hf_nisplus_server = -1;
+static int hf_nisplus_endpoints = -1;
+static int hf_nisplus_endpoint = -1;
+static int hf_nisplus_endpoint_uaddr = -1;
+static int hf_nisplus_endpoint_family = -1;
+static int hf_nisplus_endpoint_proto = -1;
+static int hf_nisplus_link = -1;
+static int hf_nisplus_attrs_array = -1;
+static int hf_nisplus_attr = -1;
+static int hf_nisplus_attr_name = -1;
+static int hf_nisplus_attr_val = -1;
+static int hf_nisplus_entry = -1;
+static int hf_nisplus_entry_type = -1;
+static int hf_nisplus_entry_cols = -1;
+static int hf_nisplus_entry_col = -1;
+static int hf_nisplus_entry_flags = -1;
+static int hf_nisplus_entry_val = -1;
+static int hf_nisplus_entry_mask = -1;
+static int hf_nisplus_entry_mask_binary = -1;
+static int hf_nisplus_entry_mask_crypt = -1;
+static int hf_nisplus_entry_mask_xdr = -1;
+static int hf_nisplus_entry_mask_modified = -1;
+static int hf_nisplus_entry_mask_asn = -1;
+static int hf_nisplus_table = -1;
+static int hf_nisplus_table_type = -1;
+static int hf_nisplus_table_maxcol = -1;
+static int hf_nisplus_table_sep = -1;
+static int hf_nisplus_table_cols = -1;
+static int hf_nisplus_table_col = -1;
+static int hf_nisplus_table_path = -1;
+static int hf_nisplus_table_col_name = -1;
+static int hf_nisplus_table_col_mask = -1;
+static int hf_nisplus_table_col_mask_binary = -1;
+static int hf_nisplus_table_col_mask_encrypted = -1;
+static int hf_nisplus_table_col_mask_xdr = -1;
+static int hf_nisplus_table_col_mask_searchable = -1;
+static int hf_nisplus_table_col_mask_casesensitive = -1;
+static int hf_nisplus_table_col_mask_modified = -1;
+static int hf_nisplus_table_col_mask_asn = -1;
+static int hf_nisplus_group = -1;
+static int hf_nisplus_group_flags = -1;
+static int hf_nisplus_grps = -1;
+static int hf_nisplus_group_name = -1;
+static int hf_nisplus_ib_flags = -1;
+static int hf_nisplus_ib_bufsize = -1;
+static int hf_nisplus_cookie = -1;
+static int hf_nisplus_fd_dirname = -1;
+static int hf_nisplus_fd_requester = -1;
+static int hf_nisplus_taglist = -1;
+static int hf_nisplus_tag = -1;
+static int hf_nisplus_tag_type = -1;
+static int hf_nisplus_tag_val = -1;
+static int hf_nisplus_dump_dir = -1;
+static int hf_nisplus_dump_time = -1;
+static int hf_nisplus_dummy = -1;
+static int hf_nisplus_ping_dir = -1;
+static int hf_nisplus_ping_time = -1;
+static int hf_nisplus_error = -1;
+static int hf_nisplus_dir_data = -1;
+static int hf_nisplus_signature = -1;
+static int hf_nisplus_log_entries = -1;
+static int hf_nisplus_log_entry = -1;
+static int hf_nisplus_log_type = -1;
+static int hf_nisplus_log_time = -1;
+static int hf_nisplus_log_principal = -1;
+static int hf_nisplus_callback_status = -1;
+static int hf_nisplus_cp_status = -1;
+static int hf_nisplus_cp_zticks = -1;
+static int hf_nisplus_cp_dticks = -1;
+static int hf_nisplus_zticks = -1;
+static int hf_nisplus_dticks = -1;
+static int hf_nisplus_aticks = -1;
+static int hf_nisplus_cticks = -1;
+
+static gint ett_nisplus = -1;
+static gint ett_nisplus_object = -1;
+static gint ett_nisplus_oid = -1;
+static gint ett_nisplus_directory = -1;
+static gint ett_nisplus_directory_mask = -1;
+static gint ett_nisplus_access_mask = -1;
+static gint ett_nisplus_server = -1;
+static gint ett_nisplus_endpoint = -1;
+static gint ett_nisplus_link = -1;
+static gint ett_nisplus_attr = -1;
+static gint ett_nisplus_entry = -1;
+static gint ett_nisplus_entry_col = -1;
+static gint ett_nisplus_entry_mask = -1;
+static gint ett_nisplus_table = -1;
+static gint ett_nisplus_table_col = -1;
+static gint ett_nisplus_table_col_mask = -1;
+static gint ett_nisplus_group = -1;
+static gint ett_nisplus_grps = -1;
+static gint ett_nisplus_tag = -1;
+static gint ett_nisplus_log_entry = -1;
+
+
+#define NIS_MASK_TABLE_BINARY 0x0001
+#define NIS_MASK_TABLE_CRYPT 0x0002
+#define NIS_MASK_TABLE_XDR 0x0004
+#define NIS_MASK_TABLE_SRCH 0x0008
+#define NIS_MASK_TABLE_CASE 0x0010
+#define NIS_MASK_TABLE_MODIFIED 0x0020
+#define NIS_MASK_TABLE_ASN 0x0040
+
+
+#define NIS_MASK_ENTRY_BINARY 0x0001
+#define NIS_MASK_ENTRY_CRYPT 0x0002
+#define NIS_MASK_ENTRY_XDR 0x0004
+#define NIS_MASK_ENTRY_MODIFIED 0x0008
+#define NIS_MASK_ENTRY_ASN 0x0040
+
+
+#define NIS_MASK_WORLD_READ 0x0001
+#define NIS_MASK_WORLD_MODIFY 0x0002
+#define NIS_MASK_WORLD_CREATE 0x0004
+#define NIS_MASK_WORLD_DESTROY 0x0008
+#define NIS_MASK_GROUP_READ 0x0010
+#define NIS_MASK_GROUP_MODIFY 0x0020
+#define NIS_MASK_GROUP_CREATE 0x0040
+#define NIS_MASK_GROUP_DESTROY 0x0080
+#define NIS_MASK_OWNER_READ 0x0100
+#define NIS_MASK_OWNER_MODIFY 0x0200
+#define NIS_MASK_OWNER_CREATE 0x0400
+#define NIS_MASK_OWNER_DESTROY 0x0800
+#define NIS_MASK_NOBODY_READ 0x1000
+#define NIS_MASK_NOBODY_MODIFY 0x2000
+#define NIS_MASK_NOBODY_CREATE 0x4000
+#define NIS_MASK_NOBODY_DESTROY 0x8000
+
+
+static const value_string key_type[] = {
+#define NIS_KEY_NONE 0
+ { NIS_KEY_NONE, "No Public Key (unix/sys auth)" },
+#define NIS_KEY_DH 1
+ { NIS_KEY_DH, "Diffie-Hellman" },
+#define NIS_KEY_RSA 2
+ { NIS_KEY_RSA, "RSA" },
+#define NIS_KEY_KERB 3
+ { NIS_KEY_KERB, "Kerberos" },
+#define NIS_KEY_DHEXT 4
+ { NIS_KEY_DHEXT, "Extended Diffie-Hellman for RPC-GSS" },
+ { 0, NULL },
+};
+
+static const value_string obj_type[] = {
+#define NIS_BOGUS_OBJ 0
+ { NIS_BOGUS_OBJ, "Bogus Object" },
+#define NIS_NO_OBJ 1
+ { NIS_NO_OBJ, "NULL Object" },
+#define NIS_DIRECTORY_OBJ 2
+ { NIS_DIRECTORY_OBJ, "Directory Object" },
+#define NIS_GROUP_OBJ 3
+ { NIS_GROUP_OBJ, "Group Object" },
+#define NIS_TABLE_OBJ 4
+ { NIS_TABLE_OBJ, "Table Object" },
+#define NIS_ENTRY_OBJ 5
+ { NIS_ENTRY_OBJ, "Entry Object" },
+#define NIS_LINK_OBJ 6
+ { NIS_LINK_OBJ, "Link Object" },
+#define NIS_PRIVATE_OBJ 7
+ { NIS_PRIVATE_OBJ, "Private Object" },
+ { 0, NULL },
+};
+
+static const value_string ns_type[] = {
+#define NIS_TYPE_UNKNOWN 0
+ { NIS_TYPE_UNKNOWN, "UNKNOWN" },
+#define NIS_TYPE_NIS 1
+ { NIS_TYPE_NIS, "NIS Plus Service" },
+#define NIS_TYPE_SUNYP 2
+ { NIS_TYPE_SUNYP, "Old NIS Service (YP)" },
+#define NIS_TYPE_IVY 3
+ { NIS_TYPE_IVY, "NIS Plus Plus Service" },
+#define NIS_TYPE_DNS 4
+ { NIS_TYPE_DNS, "Domain Name Service (DNS)" },
+#define NIS_TYPE_X500 5
+ { NIS_TYPE_X500, "ISO/CCITT X.500 Service" },
+#define NIS_TYPE_DNANS 6
+ { NIS_TYPE_DNANS, "Digital DECNet Name Service" },
+#define NIS_TYPE_XCHS 7
+ { NIS_TYPE_XCHS, "Xerox ClearingHouse Service" },
+#define NIS_TYPE_CDS 8
+ { NIS_TYPE_CDS, "CDS" },
+ { 0, NULL },
+};
+
+
+
+
+static int
+dissect_nisplus_time(tvbuff_t *tvb, int offset, proto_tree *tree, int hfindex)
+{
+ nstime_t ts;
+
+ ts.nsecs = 0;
+ ts.secs = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ proto_tree_add_time(tree, hfindex, tvb, offset, 4, &ts);
+
+ return offset;
+}
+
+static int
+dissect_group(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree,
+ hf_nisplus_group_name, offset, NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_group_obj(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_group,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_group);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_group_flags, offset);
+
+ offset = dissect_rpc_array(tvb, pinfo, lock_tree, offset,
+ dissect_group, hf_nisplus_grps);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+dissect_access_rights(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item* mask_item = NULL;
+ proto_tree* mask_tree = NULL;
+ guint32 mask;
+
+ mask_item = proto_tree_add_item(tree, hf_nisplus_access_mask,
+ tvb, offset, 4, FALSE);
+
+ mask_tree = proto_item_add_subtree(mask_item, ett_nisplus_access_mask);
+ mask = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_world_read, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_world_modify, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_world_create, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_world_destroy, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_group_read, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_group_modify, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_group_create, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_group_destroy, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_owner_read, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_owner_modify, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_owner_create, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_owner_destroy, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_nobody_read, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_nobody_modify, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_nobody_create, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_mask_nobody_destroy, tvb, offset, 4, mask);
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_table(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ proto_item* mask_item = NULL;
+ proto_tree* mask_tree = NULL;
+ guint32 mask;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_table_col,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_table_col);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_table_col_name, offset, NULL);
+
+
+ mask_item = proto_tree_add_item(lock_tree, hf_nisplus_table_col_mask,
+ tvb, offset, 4,
+ FALSE);
+ mask_tree = proto_item_add_subtree(mask_item, ett_nisplus_table_col_mask);
+ mask = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_table_col_mask_binary,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_table_col_mask_encrypted,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_table_col_mask_xdr,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_table_col_mask_searchable,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_table_col_mask_casesensitive,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_table_col_mask_modified,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_table_col_mask_asn,
+ tvb, offset, 4, mask);
+ offset += 4;
+
+ offset = dissect_access_rights(tvb, offset, lock_tree);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_table_obj(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_table,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_table);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_table_type, offset, NULL);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_table_maxcol, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_table_sep, offset);
+
+ offset = dissect_rpc_array(tvb, pinfo, lock_tree, offset,
+ dissect_table, hf_nisplus_table_cols);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_table_path, offset, NULL);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ proto_item* mask_item = NULL;
+ proto_tree* mask_tree = NULL;
+ guint32 mask;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_entry_col,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_entry_col);
+
+ mask_item = proto_tree_add_item(lock_tree, hf_nisplus_entry_mask,
+ tvb, offset, 4,
+ FALSE);
+
+ mask_tree = proto_item_add_subtree(mask_item, ett_nisplus_entry_mask);
+ mask = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_entry_mask_binary, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_entry_mask_crypt, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_entry_mask_xdr, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_entry_mask_modified, tvb, offset, 4, mask);
+ proto_tree_add_boolean(mask_tree, hf_nisplus_entry_mask_asn, tvb, offset, 4, mask);
+ offset += 4;
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_entry_val, offset, NULL);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_entry_obj(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_entry,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_entry);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_entry_type, offset, NULL);
+
+ offset = dissect_rpc_array(tvb, pinfo, lock_tree, offset,
+ dissect_entry, hf_nisplus_entry_cols);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_attr(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_attr,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_attr);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_attr_name, offset, NULL);
+
+ offset = dissect_rpc_data(tvb, lock_tree,
+ hf_nisplus_attr_val, offset);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_link_obj(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_link,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_link);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_object_type, offset);
+
+ offset = dissect_rpc_array(tvb, pinfo, lock_tree, offset,
+ dissect_attr, hf_nisplus_attrs_array);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_object_name, offset, NULL);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+dissect_endpoint(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_endpoint,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_endpoint);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_endpoint_uaddr, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_endpoint_family, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_endpoint_proto, offset, NULL);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+dissect_directory_server(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_server,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_server);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_server_name, offset, NULL);
+
+ offset = dissect_rpc_array(tvb, pinfo, lock_tree, offset,
+ dissect_endpoint, hf_nisplus_endpoints);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_key_type, offset);
+
+ offset = dissect_rpc_data(tvb, lock_tree,
+ hf_nisplus_key_data, offset);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+dissect_directory_mask(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_directory_mask,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_directory_mask);
+
+ offset = dissect_access_rights(tvb, offset, lock_tree);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_object_type, offset);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_directory_obj(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_directory,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_directory);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_directory_name, offset, NULL);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_directory_type, offset);
+
+ offset = dissect_rpc_array(tvb, pinfo, lock_tree, offset,
+ dissect_directory_server, hf_nisplus_servers);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_directory_ttl, offset);
+
+ offset = dissect_rpc_array(tvb, pinfo, lock_tree, offset,
+ dissect_directory_mask, hf_nisplus_directory_mask_list);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_nisplus_oid(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_oid, tvb,
+ offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_oid);
+
+ offset = dissect_nisplus_time(tvb, offset, lock_tree,
+ hf_nisplus_object_ctime);
+
+ offset = dissect_nisplus_time(tvb, offset, lock_tree,
+ hf_nisplus_object_mtime);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_nisplus_object(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ gint32 type;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_object, tvb,
+ offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_object);
+
+ offset = dissect_nisplus_oid(tvb, offset, lock_tree);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_object_name, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_object_owner, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_object_group, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_object_domain, offset, NULL);
+
+ offset = dissect_access_rights(tvb, offset, lock_tree);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_object_ttl, offset);
+
+ type = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_object_type, offset);
+ switch (type) {
+ case NIS_DIRECTORY_OBJ:
+ offset = dissect_directory_obj(tvb, offset, pinfo, lock_tree);
+ break;
+ case NIS_GROUP_OBJ:
+ offset = dissect_group_obj(tvb, offset, pinfo, lock_tree);
+ break;
+ case NIS_TABLE_OBJ:
+ offset = dissect_table_obj(tvb, offset, pinfo, lock_tree);
+ break;
+ case NIS_ENTRY_OBJ:
+ offset = dissect_entry_obj(tvb, offset, pinfo, lock_tree);
+ break;
+ case NIS_LINK_OBJ:
+ offset = dissect_link_obj(tvb, offset, pinfo, lock_tree);
+ break;
+ case NIS_PRIVATE_OBJ:
+ offset = dissect_rpc_data(tvb, lock_tree,
+ hf_nisplus_object_private, offset);
+ break;
+ case NIS_NO_OBJ:
+ break;
+ case NIS_BOGUS_OBJ:
+ break;
+ default:
+ break;
+ };
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+/* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ end of nis object, thats right, all this was the definition of
+ ONE SINGLE struct.
+*/
+
+
+
+static int
+dissect_ns_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree,
+ hf_nisplus_object_name, offset, NULL);
+
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_nisplus_object, hf_nisplus_object);
+
+ return offset;
+}
+
+static int
+dissect_ib_request(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree,
+ hf_nisplus_object_name, offset, NULL);
+
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_attr, hf_nisplus_attrs_array);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_ib_flags, offset);
+
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_nisplus_object, hf_nisplus_object);
+
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_directory_server, hf_nisplus_cbservers);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_ib_bufsize, offset);
+
+ offset = dissect_rpc_data(tvb, tree,
+ hf_nisplus_cookie, offset);
+
+ return offset;
+}
+
+static int
+dissect_fd_args(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree,
+ hf_nisplus_fd_dirname, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, tree,
+ hf_nisplus_fd_requester, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_nisplus_tag(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_tag, tvb,
+ offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_tag);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_tag_type, offset);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_tag_val, offset, NULL);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_nisplus_taglist(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_nisplus_tag, hf_nisplus_taglist);
+
+ return offset;
+}
+
+static int
+dissect_dump_args(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree,
+ hf_nisplus_dump_dir, offset, NULL);
+
+ offset = dissect_nisplus_time(tvb, offset, tree,
+ hf_nisplus_dump_time);
+
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_directory_server, hf_nisplus_cbservers);
+
+ return offset;
+}
+
+static int
+dissect_netobj(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_data(tvb, tree,
+ hf_nisplus_dummy, offset);
+
+ return offset;
+}
+
+static int
+dissect_nisname(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree,
+ hf_nisplus_object_name, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_ping_args(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree,
+ hf_nisplus_ping_dir, offset, NULL);
+
+ offset = dissect_nisplus_time(tvb, offset, tree,
+ hf_nisplus_ping_time);
+
+ return offset;
+}
+
+
+static const value_string nis_error[] = {
+#define NIS_SUCCESS 0
+ { NIS_SUCCESS, "A-ok, let's rock n roll" },
+#define NIS_S_SUCCESS 1
+ { NIS_S_SUCCESS, "Name found (maybe)" },
+#define NIS_NOTFOUND 2
+ { NIS_NOTFOUND, "Name definitely not found" },
+#define NIS_S_NOTFOUND 3
+ { NIS_S_NOTFOUND, "Name maybe not found" },
+#define NIS_CACHEEXPIRED 4
+ { NIS_CACHEEXPIRED, "Name exists but cache out of date" },
+#define NIS_NAMEUNREACHABLE 5
+ { NIS_NAMEUNREACHABLE, "Can't get there from here" },
+#define NIS_UNKNOWNOBJ 6
+ { NIS_UNKNOWNOBJ, "Object type is bogus" },
+#define NIS_TRYAGAIN 7
+ { NIS_TRYAGAIN, "I'm busy, call back" },
+#define NIS_SYSTEMERROR 8
+ { NIS_SYSTEMERROR, "Generic system error" },
+#define NIS_CHAINBROKEN 9
+ { NIS_CHAINBROKEN, "First/Next warning" },
+#define NIS_PERMISSION 10
+ { NIS_PERMISSION, "Not enough permission to access" },
+#define NIS_NOTOWNER 11
+ { NIS_NOTOWNER, "You don't own it, sorry" },
+#define NIS_NOT_ME 12
+ { NIS_NOT_ME, "I don't serve this name" },
+#define NIS_NOMEMORY 13
+ { NIS_NOMEMORY, "Outta VM! Help!" },
+#define NIS_NAMEEXISTS 14
+ { NIS_NAMEEXISTS, "Can't create over another name" },
+#define NIS_NOTMASTER 15
+ { NIS_NOTMASTER, "I'm justa secondaray, don't ask me" },
+#define NIS_INVALIDOBJ 16
+ { NIS_INVALIDOBJ, "Object is broken somehow" },
+#define NIS_BADNAME 17
+ { NIS_BADNAME, "Unparsable name" },
+#define NIS_NOCALLBACK 18
+ { NIS_NOCALLBACK, "Couldn't talk to call back proc" },
+#define NIS_CBRESULTS 19
+ { NIS_CBRESULTS, "Results being called back to you" },
+#define NIS_NOSUCHNAME 20
+ { NIS_NOSUCHNAME, "Name unknown" },
+#define NIS_NOTUNIQUE 21
+ { NIS_NOTUNIQUE, "Value is not uniques (entry)" },
+#define NIS_IBMODERROR 22
+ { NIS_IBMODERROR, "Inf. Base. Modify error." },
+#define NIS_NOSUCHTABLE 23
+ { NIS_NOSUCHTABLE, "Name for table was wrong" },
+#define NIS_TYPEMISMATCH 24
+ { NIS_TYPEMISMATCH, "Entry and table type mismatch" },
+#define NIS_LINKNAMEERROR 25
+ { NIS_LINKNAMEERROR, "Link points to bogus name" },
+#define NIS_PARTIAL 26
+ { NIS_PARTIAL, "Partial success, found table" },
+#define NIS_TOOMANYATTRS 27
+ { NIS_TOOMANYATTRS, "Too many attributes" },
+#define NIS_RPCERROR 28
+ { NIS_RPCERROR, "RPC error encountered" },
+#define NIS_BADATTRIBUTE 29
+ { NIS_BADATTRIBUTE, "Bad or invalid attribute" },
+#define NIS_NOTSEARCHABLE 30
+ { NIS_NOTSEARCHABLE, "Non-searchable object searched" },
+#define NIS_CBERROR 31
+ { NIS_CBERROR, "Error during callback (svc crash)" },
+#define NIS_FOREIGNNS 32
+ { NIS_FOREIGNNS, "Foreign Namespace" },
+#define NIS_BADOBJECT 33
+ { NIS_BADOBJECT, "Malformed object structure" },
+#define NIS_NOTSAMEOBJ 34
+ { NIS_NOTSAMEOBJ, "Object swapped during deletion" },
+#define NIS_MODFAIL 35
+ { NIS_MODFAIL, "Failure during a Modify." },
+#define NIS_BADREQUEST 36
+ { NIS_BADREQUEST, "Illegal query for table" },
+#define NIS_NOTEMPTY 37
+ { NIS_NOTEMPTY, "Attempt to remove a non-empty tbl" },
+#define NIS_COLDSTART_ERR 38
+ { NIS_COLDSTART_ERR, "Error accesing the cold start file" },
+#define NIS_RESYNC 39
+ { NIS_RESYNC, "Transaction log too far out of date" },
+#define NIS_FAIL 40
+ { NIS_FAIL, "NIS operation failed." },
+#define NIS_UNAVAIL 41
+ { NIS_UNAVAIL, "NIS+ service is unavailable (client)" },
+#define NIS_RES2BIG 42
+ { NIS_RES2BIG, "NIS+ result too big for datagram" },
+#define NIS_SRVAUTH 43
+ { NIS_SRVAUTH, "NIS+ server wasn't authenticated." },
+#define NIS_CLNTAUTH 44
+ { NIS_CLNTAUTH, "NIS+ Client wasn't authenticated." },
+#define NIS_NOFILESPACE 45
+ { NIS_NOFILESPACE, "NIS+ server ran out of disk space" },
+#define NIS_NOPROC 46
+ { NIS_NOPROC, "NIS+ server couldn't create new proc" },
+#define NIS_DUMPLATER 47
+ { NIS_DUMPLATER, "NIS+ server already has dump child" },
+ { 0, NULL },
+};
+
+static int
+dissect_nisplus_result(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_error, offset);
+
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_nisplus_object, hf_nisplus_object);
+
+ offset = dissect_rpc_data(tvb, tree,
+ hf_nisplus_cookie, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_zticks, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_dticks, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_aticks, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_cticks, offset);
+
+ return offset;
+}
+
+static int
+dissect_fd_result(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_error, offset);
+
+ offset = dissect_rpc_string(tvb, tree,
+ hf_nisplus_fd_dirname, offset, NULL);
+
+ offset = dissect_rpc_data(tvb, tree,
+ hf_nisplus_dir_data, offset);
+
+ offset = dissect_rpc_data(tvb, tree,
+ hf_nisplus_signature, offset);
+
+ return offset;
+}
+
+static const value_string entry_type[] = {
+#define LOG_NOP 0
+ { LOG_NOP, "NOP" },
+#define LOG_ADD_NAME 1
+ { LOG_ADD_NAME, "Name Was Added" },
+#define LOG_REM_NAME 2
+ { LOG_REM_NAME, "Name Was Removed" },
+#define LOG_MOD_NAME_OLD 3
+ { LOG_MOD_NAME_OLD, "Name Was Modified" },
+#define LOG_MOD_NAME_NEW 4
+ { LOG_MOD_NAME_NEW, "Name Was Modified" },
+#define LOG_ADD_IBASE 5
+ { LOG_ADD_IBASE, "Entry Added To Information Base" },
+#define LOG_REM_IBASE 6
+ { LOG_REM_IBASE, "Entry Removed From Information Base" },
+#define LOG_MOD_IBASE 7
+ { LOG_MOD_IBASE, "Entry Modified In Information Base" },
+#define LOG_UPD_STAMP 8
+ { LOG_UPD_STAMP, "Update Timestamp" },
+ { 0, NULL },
+};
+static int
+dissect_log_entry(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nisplus_log_entry,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nisplus_log_entry);
+
+ offset = dissect_nisplus_time(tvb, offset, lock_tree,
+ hf_nisplus_log_time);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nisplus_log_type, offset);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_log_principal, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_nisplus_directory_name, offset, NULL);
+
+ offset = dissect_rpc_array(tvb, pinfo, lock_tree, offset,
+ dissect_attr, hf_nisplus_attrs_array);
+
+ offset = dissect_nisplus_object(tvb, offset, pinfo, lock_tree);
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_log_result(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_error, offset);
+
+ offset = dissect_rpc_data(tvb, tree,
+ hf_nisplus_cookie, offset);
+
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_log_entry, hf_nisplus_log_entries);
+
+ return offset;
+}
+
+static int
+dissect_callback_result(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_bool(tvb, tree, hf_nisplus_callback_status,
+ offset);
+
+ return offset;
+}
+
+static int
+dissect_change_time(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_nisplus_time(tvb, offset, tree,
+ hf_nisplus_log_time);
+
+ return offset;
+}
+
+static int
+dissect_cp_result(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_cp_status, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_cp_zticks, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_cp_dticks, offset);
+
+ return offset;
+}
+
+static int
+dissect_nisplus_error(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_nisplus_error, offset);
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff nisplus3_proc[] = {
+ { NISPROC_NULL, "NULL",
+ NULL, NULL },
+ { NISPROC_LOOKUP, "LOOKUP",
+ dissect_ns_request, dissect_nisplus_result },
+ { NISPROC_ADD, "ADD",
+ dissect_ns_request, dissect_nisplus_result },
+ { NISPROC_MODIFY, "MODIFY",
+ dissect_ns_request, dissect_nisplus_result },
+ { NISPROC_REMOVE, "REMOVE",
+ dissect_ns_request, dissect_nisplus_result },
+ { NISPROC_IBLIST, "IBLIST",
+ dissect_ib_request, dissect_nisplus_result },
+ { NISPROC_IBADD, "IBADD",
+ dissect_ib_request, dissect_nisplus_result },
+ { NISPROC_IBMODIFY, "IBMODIFY",
+ dissect_ib_request, dissect_nisplus_result },
+ { NISPROC_IBREMOVE, "IBREMOVE",
+ dissect_ib_request, dissect_nisplus_result },
+ { NISPROC_IBFIRST, "IBFIRST",
+ dissect_ib_request, dissect_nisplus_result },
+ { NISPROC_IBNEXT, "IBNEXT",
+ dissect_ib_request, dissect_nisplus_result },
+ { NISPROC_FINDDIRECTORY, "FINDDIRECTORY",
+ dissect_fd_args, dissect_fd_result },
+ { NISPROC_STATUS, "STATUS",
+ dissect_nisplus_taglist, dissect_nisplus_taglist },
+ { NISPROC_DUMPLOG, "DUMPLOG",
+ dissect_dump_args, dissect_log_result },
+ { NISPROC_DUMP, "DUMP",
+ dissect_dump_args, dissect_log_result },
+ { NISPROC_CALLBACK, "CALLBACK",
+ dissect_netobj, dissect_callback_result },
+ { NISPROC_CPTIME, "CPTIME",
+ dissect_nisname, dissect_change_time },
+ { NISPROC_CHECKPOINT, "CHECKPOINT",
+ dissect_nisname, dissect_cp_result },
+ { NISPROC_PING, "PING",
+ dissect_ping_args, NULL },
+ { NISPROC_SERVSTATE, "SERVSTATE",
+ dissect_nisplus_taglist, dissect_nisplus_taglist },
+ { NISPROC_MKDIR, "MKDIR",
+ dissect_nisname, dissect_nisplus_error },
+ { NISPROC_RMDIR, "RMDIR",
+ dissect_nisname, dissect_nisplus_error },
+ { NISPROC_UPDKEYS, "UPDKEYS",
+ dissect_nisname, dissect_nisplus_error },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string nisplus3_proc_vals[] = {
+ { NISPROC_NULL, "NULL" },
+ { NISPROC_LOOKUP, "LOOKUP" },
+ { NISPROC_ADD, "ADD" },
+ { NISPROC_MODIFY, "MODIFY" },
+ { NISPROC_REMOVE, "REMOVE" },
+ { NISPROC_IBLIST, "IBLIST" },
+ { NISPROC_IBADD, "IBADD" },
+ { NISPROC_IBMODIFY, "IBMODIFY" },
+ { NISPROC_IBREMOVE, "IBREMOVE" },
+ { NISPROC_IBFIRST, "IBFIRST" },
+ { NISPROC_IBNEXT, "IBNEXT" },
+ { NISPROC_FINDDIRECTORY, "FINDDIRECTORY" },
+ { NISPROC_STATUS, "STATUS" },
+ { NISPROC_DUMPLOG, "DUMPLOG" },
+ { NISPROC_DUMP, "DUMP" },
+ { NISPROC_CALLBACK, "CALLBACK" },
+ { NISPROC_CPTIME, "CPTIME" },
+ { NISPROC_CHECKPOINT, "CHECKPOINT" },
+ { NISPROC_PING, "PING" },
+ { NISPROC_SERVSTATE, "SERVSTATE" },
+ { NISPROC_MKDIR, "MKDIR" },
+ { NISPROC_RMDIR, "RMDIR" },
+ { NISPROC_UPDKEYS, "UPDKEYS" },
+ { 0, NULL }
+};
+
+
+
+void
+proto_register_nis(void)
+{
+ static const true_false_string tfs_col_binary = {
+ "column is binary",
+ "column is NOT binary"
+ };
+ static const true_false_string tfs_col_encrypted = {
+ "column is encrypted",
+ "column is NOT encrypted"
+ };
+ static const true_false_string tfs_col_xdr = {
+ "column is xdr encoded",
+ "column is NOT xdr encoded"
+ };
+ static const true_false_string tfs_col_searchable = {
+ "column is searchable",
+ "column is NOT searchable"
+ };
+ static const true_false_string tfs_col_casesensitive = {
+ "column is case sensitive",
+ "column is NOT case sensitive"
+ };
+ static const true_false_string tfs_col_modified = {
+ "column is modified",
+ "column is NOT modified"
+ };
+ static const true_false_string tfs_col_asn = {
+ "column is asn.1 encoded",
+ "column is NOT asn.1 encoded"
+ };
+
+ static const true_false_string tfs_entry_binary = {
+ "entry is binary",
+ "entry is NOT binary"
+ };
+
+ static const true_false_string tfs_entry_crypt = {
+ "entry is encrypted",
+ "entry is NOT encrypted"
+ };
+
+ static const true_false_string tfs_entry_xdr = {
+ "entry is xdr encoded",
+ "entry is NOT xdr encoded"
+ };
+
+ static const true_false_string tfs_entry_modified = {
+ "entry is modified",
+ "entry is NOT modified"
+ };
+
+ static const true_false_string tfs_entry_asn = {
+ "entry is asn.1 encoded",
+ "entry is NOT asn.1 encoded"
+ };
+
+ static const true_false_string tfs_world_read = {
+ "world can read",
+ "world can NOT read"
+ };
+
+ static const true_false_string tfs_world_modify = {
+ "world can modify",
+ "world can NOT modify"
+ };
+
+ static const true_false_string tfs_world_create = {
+ "world can create",
+ "world can NOT create"
+ };
+
+ static const true_false_string tfs_world_destroy = {
+ "world can destroy",
+ "world can NOT destroy"
+ };
+
+ static const true_false_string tfs_group_read = {
+ "group can read",
+ "group can NOT read"
+ };
+
+ static const true_false_string tfs_group_modify = {
+ "group can modify",
+ "group can NOT modify"
+ };
+
+ static const true_false_string tfs_group_create = {
+ "group can create",
+ "group can NOT create"
+ };
+
+ static const true_false_string tfs_group_destroy = {
+ "group can destroy",
+ "group can NOT destroy"
+ };
+
+ static const true_false_string tfs_owner_read = {
+ "owner can read",
+ "owner can NOT read"
+ };
+
+ static const true_false_string tfs_owner_modify = {
+ "owner can modify",
+ "owner can NOT modify"
+ };
+
+ static const true_false_string tfs_owner_create = {
+ "owner can create",
+ "owner can NOT create"
+ };
+
+ static const true_false_string tfs_owner_destroy = {
+ "owner can destroy",
+ "owner can NOT destroy"
+ };
+
+ static const true_false_string tfs_nobody_read = {
+ "nobody can read",
+ "nobody can NOT read"
+ };
+
+ static const true_false_string tfs_nobody_modify = {
+ "nobody can modify",
+ "nobody can NOT modify"
+ };
+
+ static const true_false_string tfs_nobody_create = {
+ "nobody can create",
+ "nobody can NOT create"
+ };
+
+ static const true_false_string tfs_nobody_destroy = {
+ "nobody can destroy",
+ "nobody can NOT destroy"
+ };
+
+ static const true_false_string tfs_callback_status = {
+ "unknown",
+ "unknown"
+ };
+
+
+
+
+ static hf_register_info hf[] = {
+ { &hf_nisplus_procedure_v3, {
+ "V3 Procedure", "nisplus.procedure_v3", FT_UINT32, BASE_DEC,
+ VALS(nisplus3_proc_vals), 0, "V3 Procedure", HFILL }},
+ { &hf_nisplus_object, {
+ "NIS Object", "nisplus.object", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Object", HFILL }},
+
+ { &hf_nisplus_oid, {
+ "Object Identity Verifier", "nisplus.object.oid", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Object Identity Verifier", HFILL }},
+
+ { &hf_nisplus_object_name, {
+ "name", "nisplus.object.name", FT_STRING, BASE_DEC,
+ NULL, 0, "NIS Name For This Object", HFILL }},
+
+ { &hf_nisplus_object_owner, {
+ "owner", "nisplus.object.owner", FT_STRING, BASE_DEC,
+ NULL, 0, "NIS Name Of Object Owner", HFILL }},
+
+ { &hf_nisplus_object_group, {
+ "group", "nisplus.object.group", FT_STRING, BASE_DEC,
+ NULL, 0, "NIS Name Of Access Group", HFILL }},
+
+ { &hf_nisplus_object_domain, {
+ "domain", "nisplus.object.domain", FT_STRING, BASE_DEC,
+ NULL, 0, "NIS Administrator For This Object", HFILL }},
+
+ { &hf_nisplus_object_ttl, {
+ "ttl", "nisplus.object.ttl", FT_UINT32, BASE_DEC,
+ NULL, 0, "NIS Time To Live For This Object", HFILL }},
+
+ { &hf_nisplus_object_private, {
+ "private", "nisplus.object.private", FT_BYTES, BASE_DEC,
+ NULL, 0, "NIS Private Object", HFILL }},
+
+ { &hf_nisplus_directory, {
+ "directory", "nisplus.directory", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Directory Object", HFILL }},
+
+ { &hf_nisplus_directory_name, {
+ "directory name", "nisplus.directory.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name Of Directory Being Served", HFILL }},
+
+ { &hf_nisplus_directory_type, {
+ "type", "nisplus.directory.type", FT_UINT32, BASE_DEC,
+ VALS(ns_type), 0, "NIS Type Of Name Service", HFILL }},
+
+ { &hf_nisplus_directory_ttl, {
+ "ttl", "nisplus.directory.ttl", FT_UINT32, BASE_DEC,
+ NULL, 0, "Time To Live", HFILL }},
+
+ { &hf_nisplus_directory_mask, {
+ "mask", "nisplus.directory.mask", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Directory Create/Destroy Rights", HFILL }},
+
+ { &hf_nisplus_directory_mask_list, {
+ "mask list", "nisplus.directory.mask_list", FT_NONE, BASE_NONE,
+ NULL, 0, "List Of Directory Create/Destroy Rights", HFILL }},
+
+ { &hf_nisplus_mask_world_read, {
+ "WORLD READ", "nisplus.directory.mask.world_read",
+ FT_BOOLEAN, 32, TFS(&tfs_world_read),
+ NIS_MASK_WORLD_READ, "World Read Flag", HFILL }},
+
+ { &hf_nisplus_mask_world_modify, {
+ "WORLD MODIFY", "nisplus.directory.mask.world_modify",
+ FT_BOOLEAN, 32, TFS(&tfs_world_modify),
+ NIS_MASK_WORLD_MODIFY, "World Modify Flag", HFILL }},
+
+ { &hf_nisplus_mask_world_create, {
+ "WORLD CREATE", "nisplus.directory.mask.world_create",
+ FT_BOOLEAN, 32, TFS(&tfs_world_create),
+ NIS_MASK_WORLD_CREATE, "World Create Flag", HFILL }},
+
+ { &hf_nisplus_mask_world_destroy, {
+ "WORLD DESTROY", "nisplus.directory.mask.world_destroy",
+ FT_BOOLEAN, 32, TFS(&tfs_world_destroy),
+ NIS_MASK_WORLD_DESTROY, "World Destroy Flag", HFILL }},
+
+ { &hf_nisplus_mask_group_read, {
+ "GROUP READ", "nisplus.directory.mask.group_read",
+ FT_BOOLEAN, 32, TFS(&tfs_group_read),
+ NIS_MASK_GROUP_READ, "Group Read Flag", HFILL }},
+
+ { &hf_nisplus_mask_group_modify, {
+ "GROUP MODIFY", "nisplus.directory.mask.group_modify",
+ FT_BOOLEAN, 32, TFS(&tfs_group_modify),
+ NIS_MASK_GROUP_MODIFY, "Group Modify Flag", HFILL }},
+
+ { &hf_nisplus_mask_group_create, {
+ "GROUP CREATE", "nisplus.directory.mask.group_create",
+ FT_BOOLEAN, 32, TFS(&tfs_group_create),
+ NIS_MASK_GROUP_CREATE, "Group Create Flag", HFILL }},
+
+ { &hf_nisplus_mask_group_destroy, {
+ "GROUP DESTROY", "nisplus.directory.mask.group_destroy",
+ FT_BOOLEAN, 32, TFS(&tfs_group_destroy),
+ NIS_MASK_GROUP_DESTROY, "Group Destroy Flag", HFILL }},
+
+ { &hf_nisplus_mask_owner_read, {
+ "OWNER READ", "nisplus.directory.mask.owner_read",
+ FT_BOOLEAN, 32, TFS(&tfs_owner_read),
+ NIS_MASK_OWNER_READ, "Owner Read Flag", HFILL }},
+
+ { &hf_nisplus_mask_owner_modify, {
+ "OWNER MODIFY", "nisplus.directory.mask.owner_modify",
+ FT_BOOLEAN, 32, TFS(&tfs_owner_modify),
+ NIS_MASK_OWNER_MODIFY, "Owner Modify Flag", HFILL }},
+
+ { &hf_nisplus_mask_owner_create, {
+ "OWNER CREATE", "nisplus.directory.mask.owner_create",
+ FT_BOOLEAN, 32, TFS(&tfs_owner_create),
+ NIS_MASK_OWNER_CREATE, "Owner Create Flag", HFILL }},
+
+ { &hf_nisplus_mask_owner_destroy, {
+ "OWNER DESTROY", "nisplus.directory.mask.owner_destroy",
+ FT_BOOLEAN, 32, TFS(&tfs_owner_destroy),
+ NIS_MASK_OWNER_DESTROY, "Owner Destroy Flag", HFILL }},
+
+ { &hf_nisplus_mask_nobody_read, {
+ "NOBODY READ", "nisplus.directory.mask.nobody_read",
+ FT_BOOLEAN, 32, TFS(&tfs_nobody_read),
+ NIS_MASK_NOBODY_READ, "Nobody Read Flag", HFILL }},
+
+ { &hf_nisplus_mask_nobody_modify, {
+ "NOBODY MODIFY", "nisplus.directory.mask.nobody_modify",
+ FT_BOOLEAN, 32, TFS(&tfs_nobody_modify),
+ NIS_MASK_NOBODY_MODIFY, "Nobody Modify Flag", HFILL }},
+
+ { &hf_nisplus_mask_nobody_create, {
+ "NOBODY CREATE", "nisplus.directory.mask.nobody_create",
+ FT_BOOLEAN, 32, TFS(&tfs_nobody_create),
+ NIS_MASK_NOBODY_CREATE, "Nobody Create Flag", HFILL }},
+
+ { &hf_nisplus_mask_nobody_destroy, {
+ "NOBODY DESTROY", "nisplus.directory.mask.nobody_destroy",
+ FT_BOOLEAN, 32, TFS(&tfs_nobody_destroy),
+ NIS_MASK_NOBODY_DESTROY, "Nobody Destroy Flag", HFILL }},
+
+ { &hf_nisplus_access_mask, {
+ "access mask", "nisplus.access.mask", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Access Mask", HFILL }},
+
+ { &hf_nisplus_object_type, {
+ "type", "nisplus.object.type", FT_UINT32, BASE_DEC,
+ VALS(obj_type), 0, "NIS Type Of Object", HFILL }},
+
+ { &hf_nisplus_servers, {
+ "nis servers", "nisplus.servers", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Servers For This Directory", HFILL }},
+
+ { &hf_nisplus_cbservers, {
+ "nis servers", "nisplus.servers", FT_NONE, BASE_NONE,
+ NULL, 0, "Optional Callback Server", HFILL }},
+
+ { &hf_nisplus_server, {
+ "server", "nisplus.server", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Server For This Directory", HFILL }},
+
+ { &hf_nisplus_server_name, {
+ "name", "nisplus.server.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name Of NIS Server", HFILL }},
+
+ { &hf_nisplus_key_type, {
+ "type", "nisplus.key.type", FT_UINT32, BASE_DEC,
+ VALS(key_type), 0, "Type Of Key", HFILL }},
+
+ { &hf_nisplus_key_data, {
+ "key data", "nisplus.key.data", FT_BYTES, BASE_DEC,
+ NULL, 0, "Encryption Key", HFILL }},
+
+ { &hf_nisplus_endpoints, {
+ "nis endpoints", "nisplus.endpoints", FT_NONE, BASE_NONE,
+ NULL, 0, "Endpoints For This NIS Server", HFILL }},
+
+ { &hf_nisplus_endpoint, {
+ "endpoint", "nisplus.endpoint", FT_NONE, BASE_NONE,
+ NULL, 0, "Endpoint For This NIS Server", HFILL }},
+
+ { &hf_nisplus_endpoint_uaddr, {
+ "addr", "nisplus.endpoint.uaddr", FT_STRING, BASE_DEC,
+ NULL, 0, "Address", HFILL }},
+
+ { &hf_nisplus_endpoint_family, {
+ "family", "nisplus.endpoint.family", FT_STRING, BASE_DEC,
+ NULL, 0, "Transport Family", HFILL }},
+
+ { &hf_nisplus_endpoint_proto, {
+ "proto", "nisplus.endpoint.proto", FT_STRING, BASE_DEC,
+ NULL, 0, "Protocol", HFILL }},
+
+ { &hf_nisplus_link, {
+ "link", "nisplus.link", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Link Object", HFILL }},
+
+ { &hf_nisplus_attrs_array, {
+ "Attributes", "nisplus.attributes", FT_NONE, BASE_NONE,
+ NULL, 0, "List Of Attributes", HFILL }},
+
+ { &hf_nisplus_attr, {
+ "Attribute", "nisplus.attr", FT_NONE, BASE_NONE,
+ NULL, 0, "Attribute", HFILL }},
+
+ { &hf_nisplus_attr_name, {
+ "name", "nisplus.attr.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Attribute Name", HFILL }},
+
+ { &hf_nisplus_attr_val, {
+ "val", "nisplus.attr.val", FT_BYTES, BASE_HEX,
+ NULL, 0, "Attribute Value", HFILL }},
+
+ { &hf_nisplus_entry, {
+ "entry", "nisplus.entry", FT_NONE, BASE_NONE,
+ NULL, 0, "Entry Object", HFILL }},
+
+ { &hf_nisplus_entry_type, {
+ "type", "nisplus.entry.type", FT_STRING, BASE_DEC,
+ NULL, 0, "Entry Type", HFILL }},
+
+ { &hf_nisplus_entry_cols, {
+ "columns", "nisplus.entry.cols", FT_NONE, BASE_NONE,
+ NULL, 0, "Entry Columns", HFILL }},
+
+ { &hf_nisplus_entry_col, {
+ "column", "nisplus.entry.col", FT_NONE, BASE_NONE,
+ NULL, 0, "Entry Column", HFILL }},
+
+ { &hf_nisplus_entry_flags, {
+ "flags", "nisplus.entry.flags", FT_UINT32, BASE_HEX,
+ NULL, 0, "Entry Col Flags", HFILL }},
+
+ { &hf_nisplus_entry_val, {
+ "val", "nisplus.entry.val", FT_STRING, BASE_DEC,
+ NULL, 0, "Entry Value", HFILL }},
+
+ { &hf_nisplus_entry_mask, {
+ "flags", "nisplus.entry.flags", FT_NONE, BASE_NONE,
+ NULL, 0, "Entry Col Flags", HFILL }},
+
+ { &hf_nisplus_entry_mask_binary, {
+ "BINARY", "nisplus.entry.flags.binary",
+ FT_BOOLEAN, 32, TFS(&tfs_entry_binary),
+ NIS_MASK_ENTRY_BINARY, "Is This Entry BINARY Flag", HFILL }},
+
+ { &hf_nisplus_entry_mask_crypt, {
+ "ENCRYPTED", "nisplus.entry.flags.encrypted",
+ FT_BOOLEAN, 32, TFS(&tfs_entry_crypt),
+ NIS_MASK_ENTRY_CRYPT, "Is This Entry ENCRYPTED Flag", HFILL }},
+
+ { &hf_nisplus_entry_mask_xdr, {
+ "XDR", "nisplus.entry.flags.xdr",
+ FT_BOOLEAN, 32, TFS(&tfs_entry_xdr),
+ NIS_MASK_ENTRY_XDR, "Is This Entry XDR Encoded Flag", HFILL }},
+
+ { &hf_nisplus_entry_mask_modified, {
+ "MODIFIED", "nisplus.entry.flags.modified",
+ FT_BOOLEAN, 32, TFS(&tfs_entry_modified),
+ NIS_MASK_ENTRY_MODIFIED, "Is This Entry MODIFIED Flag", HFILL }},
+
+ { &hf_nisplus_entry_mask_asn, {
+ "ASN.1", "nisplus.entry.flags.asn",
+ FT_BOOLEAN, 32, TFS(&tfs_entry_asn),
+ NIS_MASK_ENTRY_ASN, "Is This Entry ASN.1 Encoded Flag", HFILL }},
+
+ { &hf_nisplus_table, {
+ "table", "nisplus.table", FT_NONE, BASE_NONE,
+ NULL, 0, "Table Object", HFILL }},
+
+ { &hf_nisplus_table_type, {
+ "type", "nisplus.table.type", FT_STRING, BASE_DEC,
+ NULL, 0, "Table Type", HFILL }},
+
+ { &hf_nisplus_table_maxcol, {
+ "max columns", "nisplus.table.maxcol", FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum Number Of Columns For Table", HFILL }},
+
+ { &hf_nisplus_table_sep, {
+ "separator", "nisplus.table.separator", FT_UINT8, BASE_HEX,
+ NULL, 0, "Separator Character", HFILL }},
+
+ { &hf_nisplus_table_cols, {
+ "columns", "nisplus.table.cols", FT_NONE, BASE_NONE,
+ NULL, 0, "Table Columns", HFILL }},
+
+ { &hf_nisplus_table_col, {
+ "column", "nisplus.table.col", FT_NONE, BASE_NONE,
+ NULL, 0, "Table Column", HFILL }},
+
+ { &hf_nisplus_table_path, {
+ "path", "nisplus.table.path", FT_STRING, BASE_DEC,
+ NULL, 0, "Table Path", HFILL }},
+
+ { &hf_nisplus_table_col_name, {
+ "column name", "nisplus.table.col.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Column Name", HFILL }},
+
+ { &hf_nisplus_table_col_mask, {
+ "flags", "nisplus.table.col.flags", FT_NONE, BASE_NONE,
+ NULL, 0, "Flags For This Column", HFILL }},
+
+ { &hf_nisplus_table_col_mask_binary, {
+ "binary", "nisplus.table.flags.binary",
+ FT_BOOLEAN, 32, TFS(&tfs_col_binary),
+ NIS_MASK_TABLE_BINARY, "Is This Column BINARY", HFILL }},
+
+ { &hf_nisplus_table_col_mask_encrypted, {
+ "encrypted", "nisplus.table.flags.encrypted",
+ FT_BOOLEAN, 32, TFS(&tfs_col_encrypted),
+ NIS_MASK_TABLE_CRYPT, "Is This Column ENCRYPTED", HFILL }},
+
+ { &hf_nisplus_table_col_mask_xdr, {
+ "xdr", "nisplus.table.flags.xdr",
+ FT_BOOLEAN, 32, TFS(&tfs_col_xdr),
+ NIS_MASK_TABLE_XDR, "Is This Column XDR Encoded", HFILL }},
+
+ { &hf_nisplus_table_col_mask_searchable, {
+ "searchable", "nisplus.table.flags.searchable",
+ FT_BOOLEAN, 32, TFS(&tfs_col_searchable),
+ NIS_MASK_TABLE_SRCH, "Is This Column SEARCHABLE", HFILL }},
+
+ { &hf_nisplus_table_col_mask_casesensitive, {
+ "casesensitive", "nisplus.table.flags.casesensitive",
+ FT_BOOLEAN, 32, TFS(&tfs_col_casesensitive),
+ NIS_MASK_TABLE_CASE, "Is This Column CASESENSITIVE", HFILL }},
+
+ { &hf_nisplus_table_col_mask_modified, {
+ "modified", "nisplus.table.flags.modified",
+ FT_BOOLEAN, 32, TFS(&tfs_col_modified),
+ NIS_MASK_TABLE_MODIFIED, "Is This Column MODIFIED", HFILL }},
+
+ { &hf_nisplus_table_col_mask_asn, {
+ "asn", "nisplus.table.flags.asn",
+ FT_BOOLEAN, 32, TFS(&tfs_col_asn),
+ NIS_MASK_TABLE_ASN, "Is This Column ASN.1 Encoded", HFILL }},
+
+ { &hf_nisplus_group, {
+ "Group", "nisplus.group", FT_NONE, BASE_NONE,
+ NULL, 0, "Group Object", HFILL }},
+
+ { &hf_nisplus_grps, {
+ "Groups", "nisplus.grps", FT_NONE, BASE_NONE,
+ NULL, 0, "List Of Groups", HFILL }},
+
+ { &hf_nisplus_group_flags, {
+ "flags", "nisplus.group.flags", FT_UINT32, BASE_HEX,
+ NULL, 0, "Group Object Flags", HFILL }},
+
+ { &hf_nisplus_group_name, {
+ "group name", "nisplus.group.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name Of Group Member", HFILL }},
+
+ { &hf_nisplus_object_ctime, {
+ "ctime", "nisplus.ctime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time Of Creation", HFILL }},
+
+ { &hf_nisplus_object_mtime, {
+ "mtime", "nisplus.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time Last Modified", HFILL }},
+
+ { &hf_nisplus_ib_flags, {
+ "flags", "nisplus.ib.flags", FT_UINT32, BASE_HEX,
+ NULL, 0, "Information Base Flags", HFILL }},
+
+ { &hf_nisplus_ib_bufsize, {
+ "bufsize", "nisplus.ib.bufsize", FT_UINT32, BASE_HEX,
+ NULL, 0, "Optional First/NextBufSize", HFILL }},
+
+ { &hf_nisplus_cookie, {
+ "cookie", "nisplus.cookie", FT_BYTES, BASE_HEX,
+ NULL, 0, "Cookie", HFILL }},
+
+ { &hf_nisplus_fd_dirname, {
+ "dirname", "nisplus.fd.dirname", FT_STRING, BASE_DEC,
+ NULL, 0, "Directory Name", HFILL }},
+
+ { &hf_nisplus_fd_requester, {
+ "requester", "nisplus.fd.requester", FT_STRING, BASE_DEC,
+ NULL, 0, "Host Principal Name For Signature", HFILL }},
+
+ { &hf_nisplus_taglist, {
+ "taglist", "nisplus.taglist", FT_NONE, BASE_NONE,
+ NULL, 0, "List Of Tags", HFILL }},
+
+ { &hf_nisplus_tag, {
+ "tag", "nisplus.tag", FT_NONE, BASE_NONE,
+ NULL, 0, "Tag", HFILL }},
+
+ { &hf_nisplus_tag_type, {
+ "type", "nisplus.tag.type", FT_UINT32, BASE_DEC,
+ NULL, 0, "Type Of Statistics Tag", HFILL }},
+
+ { &hf_nisplus_tag_val, {
+ "value", "nisplus.tag.value", FT_STRING, BASE_DEC,
+ NULL, 0, "Value Of Statistics Tag", HFILL }},
+
+ { &hf_nisplus_dump_dir, {
+ "directory", "nisplus.dump.dir", FT_STRING, BASE_DEC,
+ NULL, 0, "Directory To Dump", HFILL }},
+
+ { &hf_nisplus_dump_time, {
+ "time", "nisplus.dump.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "From This Timestamp", HFILL }},
+
+ { &hf_nisplus_dummy, {
+ " ", ".nisplus.dummy", FT_BYTES, BASE_NONE,
+ NULL, 0, " ", HFILL }},
+
+ { &hf_nisplus_ping_time, {
+ "time", "nisplus.ping.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Timestamp Of The Transaction", HFILL }},
+
+ { &hf_nisplus_ping_dir, {
+ "directory", "nisplus.ping.dir", FT_STRING, BASE_DEC,
+ NULL, 0, "Directory That Had The Change", HFILL }},
+
+ { &hf_nisplus_error, {
+ "status", "nisplus.status", FT_UINT32, BASE_DEC,
+ VALS(nis_error), 0, "NIS Status Code", HFILL }},
+
+ { &hf_nisplus_dir_data, {
+ "data", "nisplus.fd.dir.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Directory Data In XDR Format", HFILL }},
+
+ { &hf_nisplus_signature, {
+ "signature", "nisplus.fd.sig", FT_BYTES, BASE_HEX,
+ NULL, 0, "Signature Of The Source", HFILL }},
+
+ { &hf_nisplus_log_entries, {
+ "log entries", "nisplus.log.entries", FT_NONE, BASE_NONE,
+ NULL, 0, "Log Entries", HFILL }},
+
+ { &hf_nisplus_log_entry, {
+ "log entry", "nisplus.log.entry", FT_NONE, BASE_NONE,
+ NULL, 0, "Log Entry", HFILL }},
+
+ { &hf_nisplus_log_time, {
+ "time", "nisplus.log.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time Of Log Entry", HFILL }},
+
+ { &hf_nisplus_log_type, {
+ "type", "nisplus.log.entry.type", FT_UINT32, BASE_DEC,
+ VALS(entry_type), 0, "Type Of Entry In Transaction Log", HFILL }},
+
+ { &hf_nisplus_log_principal, {
+ "principal", "nisplus.log.principal", FT_STRING, BASE_DEC,
+ NULL, 0, "Principal Making The Change", HFILL }},
+
+ { &hf_nisplus_callback_status, {
+ "status", "nisplus.callback.status",
+ FT_BOOLEAN, 0, TFS(&tfs_callback_status),
+ 0, "Status Of Callback Thread", HFILL }},
+
+ { &hf_nisplus_cp_status, {
+ "status", "nisplus.checkpoint.status", FT_UINT32, BASE_DEC,
+ NULL, 0, "Checkpoint Status", HFILL }},
+
+ { &hf_nisplus_cp_zticks, {
+ "zticks", "nisplus.checkpoint.zticks", FT_UINT32, BASE_DEC,
+ NULL, 0, "Service Ticks", HFILL }},
+
+ { &hf_nisplus_cp_dticks, {
+ "dticks", "nisplus.checkpoint.dticks", FT_UINT32, BASE_DEC,
+ NULL, 0, "Database Ticks", HFILL }},
+
+ { &hf_nisplus_zticks, {
+ "zticks", "nisplus.zticks", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_nisplus_dticks, {
+ "dticks", "nisplus.dticks", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_nisplus_aticks, {
+ "aticks", "nisplus.aticks", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_nisplus_cticks, {
+ "cticks", "nisplus.cticks", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_nisplus,
+ &ett_nisplus_object,
+ &ett_nisplus_oid,
+ &ett_nisplus_directory,
+ &ett_nisplus_directory_mask,
+ &ett_nisplus_access_mask,
+ &ett_nisplus_server,
+ &ett_nisplus_endpoint,
+ &ett_nisplus_link,
+ &ett_nisplus_attr,
+ &ett_nisplus_entry,
+ &ett_nisplus_entry_col,
+ &ett_nisplus_entry_mask,
+ &ett_nisplus_table,
+ &ett_nisplus_table_col,
+ &ett_nisplus_table_col_mask,
+ &ett_nisplus_group,
+ &ett_nisplus_grps,
+ &ett_nisplus_tag,
+ &ett_nisplus_log_entry,
+ };
+
+ proto_nisplus = proto_register_protocol("NIS+",
+ "NIS+", "nisplus");
+ proto_register_field_array(proto_nisplus, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_nis(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_nisplus, NIS_PROGRAM, ett_nisplus);
+ /* Register the procedure tables */
+ rpc_init_proc_table(NIS_PROGRAM, 3, nisplus3_proc, hf_nisplus_procedure_v3);
+}
+
+
+
+
+
+
+/* xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ callback protocol for NIS+
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */
+
+static int proto_nispluscb = -1;
+static int hf_nispluscb_procedure_v1 = -1;
+static int hf_nispluscb_entries = -1;
+static int hf_nispluscb_entry = -1;
+
+static gint ett_nispluscb = -1;
+static gint ett_nispluscb_entry = -1;
+
+static int
+dissect_cb_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+ int old_offset = offset;
+
+ lock_item = proto_tree_add_item(tree, hf_nispluscb_entry,
+ tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_nispluscb_entry);
+
+/*XXXXX Not implemented yet*/
+
+ proto_item_set_len(lock_item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_cback_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset = dissect_rpc_array(tvb, pinfo, tree, offset,
+ dissect_cb_entry, hf_nispluscb_entries);
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff cb1_proc[] = {
+ { CBPROC_NULL, "NULL",
+ NULL, NULL },
+ { CBPROC_RECEIVE, "RECEIVE",
+ dissect_cback_data, dissect_callback_result },
+ { CBPROC_FINISH, "FINISH",
+ NULL, NULL },
+ { CBPROC_ERROR, "ERROR",
+ dissect_nisplus_error, NULL },
+ { 0, NULL, NULL, NULL },
+};
+static const value_string nispluscb1_proc_vals[] = {
+ { CBPROC_NULL, "NULL" },
+ { CBPROC_RECEIVE, "RECEIVE" },
+ { CBPROC_FINISH, "FINISH" },
+ { CBPROC_ERROR, "ERROR" },
+ { 0, NULL }
+};
+
+void
+proto_register_niscb(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_nispluscb_procedure_v1, {
+ "V1 Procedure", "nispluscb.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(nispluscb1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_nispluscb_entries, {
+ "entries", "nispluscb.entries", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Callback Entries", HFILL }},
+
+ { &hf_nispluscb_entry, {
+ "entry", "nispluscb.entry", FT_NONE, BASE_NONE,
+ NULL, 0, "NIS Callback Entry", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_nispluscb,
+ &ett_nispluscb_entry,
+ };
+
+ proto_nispluscb = proto_register_protocol("NIS+ Callback",
+ "NIS+ CB", "nispluscb");
+ proto_register_field_array(proto_nispluscb, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_niscb(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_nispluscb, CB_PROGRAM, ett_nispluscb);
+ /* Register the procedure tables */
+ rpc_init_proc_table(CB_PROGRAM, 1, cb1_proc, hf_nispluscb_procedure_v1);
+}
diff --git a/epan/dissectors/packet-nisplus.h b/epan/dissectors/packet-nisplus.h
new file mode 100644
index 0000000000..dbc6c50aee
--- /dev/null
+++ b/epan/dissectors/packet-nisplus.h
@@ -0,0 +1,64 @@
+/* packet-nisplus.h
+ * 2001 Ronnie Sahlberg <See AUTHORS for email>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_NIS_H
+#define PACKET_NIS_H
+
+#define NISPROC_NULL 0
+#define NISPROC_LOOKUP 1
+#define NISPROC_ADD 2
+#define NISPROC_MODIFY 3
+#define NISPROC_REMOVE 4
+#define NISPROC_IBLIST 5
+#define NISPROC_IBADD 6
+#define NISPROC_IBMODIFY 7
+#define NISPROC_IBREMOVE 8
+#define NISPROC_IBFIRST 9
+#define NISPROC_IBNEXT 10
+
+#define NISPROC_FINDDIRECTORY 12
+
+#define NISPROC_STATUS 14
+#define NISPROC_DUMPLOG 15
+#define NISPROC_DUMP 16
+#define NISPROC_CALLBACK 17
+#define NISPROC_CPTIME 18
+#define NISPROC_CHECKPOINT 19
+#define NISPROC_PING 20
+#define NISPROC_SERVSTATE 21
+#define NISPROC_MKDIR 22
+#define NISPROC_RMDIR 23
+#define NISPROC_UPDKEYS 24
+
+#define NIS_PROGRAM 100300
+
+
+#define CBPROC_NULL 0
+#define CBPROC_RECEIVE 1
+#define CBPROC_FINISH 2
+#define CBPROC_ERROR 3
+
+#define CB_PROGRAM 100302
+
+#endif
diff --git a/epan/dissectors/packet-nlm.c b/epan/dissectors/packet-nlm.c
new file mode 100644
index 0000000000..7aa352c082
--- /dev/null
+++ b/epan/dissectors/packet-nlm.c
@@ -0,0 +1,1237 @@
+/* packet-nlm.c
+ * Routines for nlm dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-mount.c
+ *
+ * 2001-JAN Ronnie Sahlberg <See AUTHORS for email>
+ * Updates to version 1 of the protocol.
+ * Added version 3 of the protocol.
+ * Added version 4 of the protocol.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-nfs.h"
+#include "packet-nlm.h"
+#include "prefs.h"
+#include <string.h>
+
+/*
+ * NFS Lock Manager protocol specs can only be found in actual
+ * implementations or in the nice book:
+ * Brent Callaghan: "NFS Illustrated", Addison-Wesley, ISBN 0-201-32570-5
+ * which I use here as reference (BC).
+ *
+ * They can also be found if you go to
+ *
+ * http://www.opengroup.org/publications/catalog/c702.htm
+ *
+ * and follow the links to the HTML version of the document.
+ */
+
+static int proto_nlm = -1;
+static int hf_nlm_procedure_v1 = -1;
+static int hf_nlm_procedure_v2 = -1;
+static int hf_nlm_procedure_v3 = -1;
+static int hf_nlm_procedure_v4 = -1;
+static int hf_nlm_cookie = -1;
+static int hf_nlm_block = -1;
+static int hf_nlm_exclusive = -1;
+static int hf_nlm_lock = -1;
+static int hf_nlm_lock_caller_name = -1;
+static int hf_nlm_lock_owner = -1;
+static int hf_nlm_lock_svid = -1;
+static int hf_nlm_lock_l_offset = -1;
+static int hf_nlm_lock_l_offset64 = -1;
+static int hf_nlm_lock_l_len = -1;
+static int hf_nlm_lock_l_len64 = -1;
+static int hf_nlm_reclaim = -1;
+static int hf_nlm_stat = -1;
+static int hf_nlm_state = -1;
+static int hf_nlm_test_stat = -1;
+static int hf_nlm_test_stat_stat = -1;
+static int hf_nlm_holder = -1;
+static int hf_nlm_share = -1;
+static int hf_nlm_share_mode = -1;
+static int hf_nlm_share_access = -1;
+static int hf_nlm_share_name = -1;
+static int hf_nlm_sequence = -1;
+static int hf_nlm_request_in = -1;
+static int hf_nlm_reply_in = -1;
+static int hf_nlm_time = -1;
+
+static gint ett_nlm = -1;
+static gint ett_nlm_lock = -1;
+
+
+
+/*
+ * stuff to match MSG and RES packets for async NLM
+ */
+
+static gboolean nlm_match_msgres = FALSE;
+static GHashTable *nlm_msg_res_unmatched = NULL;
+static GHashTable *nlm_msg_res_matched = NULL;
+
+/* XXX when matching the packets we should really check the conversation (only address
+ NOT ports) and command type as well. I am lazy and thinks the cookie itself is
+ good enough for now
+*/
+typedef struct _nlm_msg_res_unmatched_data {
+ int req_frame;
+ nstime_t ns;
+ int cookie_len;
+ const char *cookie;
+} nlm_msg_res_unmatched_data;
+
+typedef struct _nlm_msg_res_matched_data {
+ int req_frame;
+ int rep_frame;
+ nstime_t ns;
+} nlm_msg_res_matched_data;
+
+static gboolean
+nlm_msg_res_unmatched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
+{
+ nlm_msg_res_unmatched_data *umd = (nlm_msg_res_unmatched_data *)value;
+
+ g_free((gpointer)umd->cookie);
+ g_free(umd);
+
+ return TRUE;
+}
+static gboolean
+nlm_msg_res_matched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
+{
+ nlm_msg_res_matched_data *md = (nlm_msg_res_matched_data *)value;
+
+ g_free(md);
+
+ return TRUE;
+}
+
+static guint
+nlm_msg_res_unmatched_hash(gconstpointer k)
+{
+ const nlm_msg_res_unmatched_data *umd = (const nlm_msg_res_unmatched_data *)k;
+ guint8 hash=0;
+ int i;
+
+ for(i=0;i<umd->cookie_len;i++){
+ hash^=umd->cookie[i];
+ }
+
+ return hash;
+}
+static guint
+nlm_msg_res_matched_hash(gconstpointer k)
+{
+ guint hash = (guint)k;
+
+ return hash;
+}
+
+static gint
+nlm_msg_res_unmatched_equal(gconstpointer k1, gconstpointer k2)
+{
+ const nlm_msg_res_unmatched_data *umd1 = (const nlm_msg_res_unmatched_data *)k1;
+ const nlm_msg_res_unmatched_data *umd2 = (const nlm_msg_res_unmatched_data *)k2;
+
+ if(umd1->cookie_len!=umd2->cookie_len){
+ return 0;
+ }
+
+ return( !memcmp(umd1->cookie, umd2->cookie, umd1->cookie_len));
+}
+static gint
+nlm_msg_res_matched_equal(gconstpointer k1, gconstpointer k2)
+{
+ guint mk1 = (guint)k1;
+ guint mk2 = (guint)k2;
+
+ return( mk1==mk2 );
+}
+
+static void
+nlm_msg_res_match_init(void)
+{
+ if(nlm_msg_res_unmatched != NULL){
+ g_hash_table_foreach_remove(nlm_msg_res_unmatched,
+ nlm_msg_res_unmatched_free_all, NULL);
+ } else {
+ nlm_msg_res_unmatched=g_hash_table_new(nlm_msg_res_unmatched_hash,
+ nlm_msg_res_unmatched_equal);
+ }
+
+ if(nlm_msg_res_matched != NULL){
+ g_hash_table_foreach_remove(nlm_msg_res_matched,
+ nlm_msg_res_matched_free_all, NULL);
+ } else {
+ nlm_msg_res_matched=g_hash_table_new(nlm_msg_res_matched_hash,
+ nlm_msg_res_matched_equal);
+ }
+}
+
+static void
+nlm_print_msgres_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
+{
+ nlm_msg_res_matched_data *md;
+
+ md=g_hash_table_lookup(nlm_msg_res_matched, (gconstpointer)pinfo->fd->num);
+ if(md){
+ nstime_t ns;
+ proto_tree_add_uint(tree, hf_nlm_request_in, tvb, 0, 0, md->req_frame);
+ ns.secs= pinfo->fd->abs_secs-md->ns.secs;
+ ns.nsecs=pinfo->fd->abs_usecs*1000-md->ns.nsecs;
+ if(ns.nsecs<0){
+ ns.nsecs+=1000000000;
+ ns.secs--;
+ }
+ proto_tree_add_time(tree, hf_nlm_time, tvb, 0, 0, &ns);
+
+ }
+}
+
+static void
+nlm_print_msgres_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
+{
+ nlm_msg_res_matched_data *md;
+
+ md=g_hash_table_lookup(nlm_msg_res_matched, (gconstpointer)pinfo->fd->num);
+ if(md){
+ proto_tree_add_uint(tree, hf_nlm_reply_in, tvb, 0, 0, md->rep_frame);
+ }
+}
+static void
+nlm_match_fhandle_reply(packet_info *pinfo, proto_tree *tree)
+{
+ nlm_msg_res_matched_data *md;
+
+ md=g_hash_table_lookup(nlm_msg_res_matched, (gconstpointer)pinfo->fd->num);
+ if(md && md->rep_frame){
+ nfs_fhandle_data_t *fhd;
+ fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
+ nfs_fhandle_frame_table,
+ (gconstpointer)md->req_frame);
+ if(fhd){
+ dissect_fhandle_hidden(pinfo,
+ tree, fhd);
+ }
+ }
+}
+static void
+nlm_match_fhandle_request(packet_info *pinfo, proto_tree *tree)
+{
+ nlm_msg_res_matched_data *md;
+
+ md=g_hash_table_lookup(nlm_msg_res_matched, (gconstpointer)pinfo->fd->num);
+ if(md && md->rep_frame){
+ nfs_fhandle_data_t *fhd;
+ fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
+ nfs_fhandle_frame_table,
+ (gconstpointer)md->rep_frame);
+ if(fhd){
+ dissect_fhandle_hidden(pinfo,
+ tree, fhd);
+ }
+ }
+}
+
+static void
+nlm_register_unmatched_res(packet_info *pinfo, tvbuff_t *tvb, int offset)
+{
+ nlm_msg_res_unmatched_data umd;
+ nlm_msg_res_unmatched_data *old_umd;
+
+ umd.cookie_len=tvb_get_ntohl(tvb, offset);
+ umd.cookie=(const char *)tvb_get_ptr(tvb, offset+4, -1);
+
+ /* have we seen this cookie before? */
+ old_umd=g_hash_table_lookup(nlm_msg_res_unmatched, (gconstpointer)&umd);
+ if(old_umd){
+ nlm_msg_res_matched_data *md;
+
+ md=g_malloc(sizeof(nlm_msg_res_matched_data));
+ md->req_frame=old_umd->req_frame;
+ md->rep_frame=pinfo->fd->num;
+ md->ns=old_umd->ns;
+ g_hash_table_insert(nlm_msg_res_matched, (gpointer)md->req_frame, (gpointer)md);
+ g_hash_table_insert(nlm_msg_res_matched, (gpointer)md->rep_frame, (gpointer)md);
+
+ g_hash_table_remove(nlm_msg_res_unmatched, (gconstpointer)old_umd);
+ g_free((gpointer)old_umd->cookie);
+ g_free(old_umd);
+ }
+}
+
+static void
+nlm_register_unmatched_msg(packet_info *pinfo, tvbuff_t *tvb, int offset)
+{
+ nlm_msg_res_unmatched_data *umd;
+ nlm_msg_res_unmatched_data *old_umd;
+
+ /* allocate and build the unmatched structure for this request */
+ umd=g_malloc(sizeof(nlm_msg_res_unmatched_data));
+ umd->req_frame=pinfo->fd->num;
+ umd->ns.secs=pinfo->fd->abs_secs;
+ umd->ns.nsecs=pinfo->fd->abs_usecs*1000;
+ umd->cookie_len=tvb_get_ntohl(tvb, offset);
+ umd->cookie=tvb_memdup(tvb, offset+4, umd->cookie_len);
+
+ /* remove any old duplicates */
+ old_umd=g_hash_table_lookup(nlm_msg_res_unmatched, (gconstpointer)umd);
+ if(old_umd){
+ g_hash_table_remove(nlm_msg_res_unmatched, (gconstpointer)old_umd);
+ g_free((gpointer)old_umd->cookie);
+ g_free(old_umd);
+ }
+
+ /* add new one */
+ g_hash_table_insert(nlm_msg_res_unmatched, (gpointer)umd, (gpointer)umd);
+}
+
+
+
+
+static const value_string names_nlm_stats[] =
+{
+ /* NLM_GRANTED is the function number 5 and the state code 0.
+ * So we use for the state the postfix _S.
+ */
+#define NLM_GRANTED_S 0
+ { NLM_GRANTED_S, "NLM_GRANTED" },
+#define NLM_DENIED 1
+ { NLM_DENIED, "NLM_DENIED" },
+#define NLM_DENIED_NOLOCKS 2
+ { NLM_DENIED_NOLOCKS, "NLM_DENIED_NOLOCKS" },
+#define NLM_BLOCKED 3
+ { NLM_BLOCKED, "NLM_BLOCKED" },
+#define NLM_DENIED_GRACE_PERIOD 4
+ { NLM_DENIED_GRACE_PERIOD, "NLM_DENIED_GRACE_PERIOD" },
+#define NLM_DEADLCK 5
+ { NLM_DEADLCK, "NLM_DEADLCK" },
+#define NLM_ROFS 6
+ { NLM_ROFS, "NLM_ROFS" },
+#define NLM_STALE_FH 7
+ { NLM_STALE_FH, "NLM_STALE_FH" },
+#define NLM_BIG 8
+ { NLM_BIG, "NLM_BIG" },
+#define NLM_FAILED 9
+ { NLM_FAILED, "NLM_FAILED" },
+ { 0, NULL }
+};
+
+
+static const value_string names_fsh_mode[] =
+{
+#define FSM_DN 0
+ { FSM_DN, "deny none" },
+#define FSM_DR 1
+ { FSM_DR, "deny read" },
+#define FSM_DW 2
+ { FSM_DW, "deny write" },
+#define FSM_DRW 3
+ { FSM_DRW, "deny read/write" },
+
+ { 0, NULL }
+};
+
+
+static const value_string names_fsh_access[] =
+{
+#define FSA_NONE 0
+ { FSA_NONE, "no access" },
+#define FSA_R 1
+ { FSA_R, "read-only" },
+#define FSA_W 2
+ { FSA_W, "write-only" },
+#define FSA_RW 3
+ { FSA_RW, "read/write" },
+ { 0, NULL }
+};
+
+
+
+
+
+
+/* **************************** */
+/* generic dissecting functions */
+/* **************************** */
+static int
+dissect_lock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int version, int offset)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+
+ if (tree) {
+ lock_item = proto_tree_add_item(tree, hf_nlm_lock, tvb,
+ offset, -1, FALSE);
+ if (lock_item)
+ lock_tree = proto_item_add_subtree(lock_item, ett_nlm_lock);
+ }
+
+ offset = dissect_rpc_string(tvb,lock_tree,
+ hf_nlm_lock_caller_name, offset, NULL);
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, lock_tree, "fh", NULL);
+
+ offset = dissect_rpc_data(tvb, lock_tree, hf_nlm_lock_owner, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_lock_svid, offset);
+
+ if (version == 4) {
+ offset = dissect_rpc_uint64(tvb, lock_tree, hf_nlm_lock_l_offset64, offset);
+ offset = dissect_rpc_uint64(tvb, lock_tree, hf_nlm_lock_l_len64, offset);
+ }
+ else {
+ offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_lock_l_offset, offset);
+ offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_lock_l_len, offset);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_nlm_test(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, int version)
+{
+ if(nlm_match_msgres){
+ rpc_call_info_value *rpc_call=pinfo->private_data;
+ if(rpc_call->proc==6){ /* NLM_TEST_MSG */
+ if( (!pinfo->fd->flags.visited) ){
+ nlm_register_unmatched_msg(pinfo, tvb, offset);
+ } else {
+ nlm_print_msgres_request(pinfo, tree, tvb);
+ }
+ /* for the fhandle matching that finds both request and
+ response packet */
+ if(nfs_fhandle_reqrep_matching){
+ nlm_match_fhandle_request(pinfo, tree);
+ }
+ }
+ }
+
+ offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
+ dissect_rpc_bool(tvb, tree, hf_nlm_exclusive, offset);
+ offset += 4;
+ offset = dissect_lock(tvb, pinfo, tree, version, offset);
+ return offset;
+}
+
+static int
+dissect_nlm_lock(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree,int version)
+{
+ if(nlm_match_msgres){
+ rpc_call_info_value *rpc_call=pinfo->private_data;
+ if(rpc_call->proc==7){ /* NLM_LOCK_MSG */
+ if( (!pinfo->fd->flags.visited) ){
+ nlm_register_unmatched_msg(pinfo, tvb, offset);
+ } else {
+ nlm_print_msgres_request(pinfo, tree, tvb);
+ }
+ /* for the fhandle matching that finds both request and
+ response packet */
+ if(nfs_fhandle_reqrep_matching){
+ nlm_match_fhandle_request(pinfo, tree);
+ }
+ }
+ }
+
+ offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nlm_block, offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nlm_exclusive, offset);
+ offset = dissect_lock(tvb, pinfo, tree, version, offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nlm_reclaim, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nlm_state, offset);
+ return offset;
+}
+
+static int
+dissect_nlm_cancel(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree,int version)
+{
+ if(nlm_match_msgres){
+ rpc_call_info_value *rpc_call=pinfo->private_data;
+ if(rpc_call->proc==8){ /* NLM_CANCEL_MSG */
+ if( (!pinfo->fd->flags.visited) ){
+ nlm_register_unmatched_msg(pinfo, tvb, offset);
+ } else {
+ nlm_print_msgres_request(pinfo, tree, tvb);
+ }
+ /* for the fhandle matching that finds both request and
+ response packet */
+ if(nfs_fhandle_reqrep_matching){
+ nlm_match_fhandle_request(pinfo, tree);
+ }
+ }
+ }
+
+ offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nlm_block, offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nlm_exclusive, offset);
+ offset = dissect_lock(tvb, pinfo, tree, version, offset);
+ return offset;
+}
+
+static int
+dissect_nlm_unlock(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree,int version)
+{
+ if(nlm_match_msgres){
+ rpc_call_info_value *rpc_call=pinfo->private_data;
+ if(rpc_call->proc==9){ /* NLM_UNLOCK_MSG */
+ if( (!pinfo->fd->flags.visited) ){
+ nlm_register_unmatched_msg(pinfo, tvb, offset);
+ } else {
+ nlm_print_msgres_request(pinfo, tree, tvb);
+ }
+ /* for the fhandle matching that finds both request and
+ response packet */
+ if(nfs_fhandle_reqrep_matching){
+ nlm_match_fhandle_request(pinfo, tree);
+ }
+ }
+ }
+
+ offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
+ offset = dissect_lock(tvb, pinfo, tree, version, offset);
+ return offset;
+}
+
+static int
+dissect_nlm_granted(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree,int version)
+{
+ if(nlm_match_msgres){
+ rpc_call_info_value *rpc_call=pinfo->private_data;
+ if(rpc_call->proc==10){ /* NLM_GRANTED_MSG */
+ if( (!pinfo->fd->flags.visited) ){
+ nlm_register_unmatched_msg(pinfo, tvb, offset);
+ } else {
+ nlm_print_msgres_request(pinfo, tree, tvb);
+ }
+ /* for the fhandle matching that finds both request and
+ response packet */
+ if(nfs_fhandle_reqrep_matching){
+ nlm_match_fhandle_request(pinfo, tree);
+ }
+ }
+ }
+
+ offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
+ offset = dissect_rpc_bool(tvb, tree, hf_nlm_exclusive, offset);
+ offset = dissect_lock(tvb, pinfo, tree, version, offset);
+ return offset;
+}
+
+
+static int
+dissect_nlm_test_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree,int version)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+
+ if(nlm_match_msgres){
+ rpc_call_info_value *rpc_call=pinfo->private_data;
+ if(rpc_call->proc==11){ /* NLM_TEST_RES */
+ if( (!pinfo->fd->flags.visited) ){
+ nlm_register_unmatched_res(pinfo, tvb, offset);
+ } else {
+ nlm_print_msgres_reply(pinfo, tree, tvb);
+ }
+ /* for the fhandle matching that finds both request and
+ response packet */
+ if(nfs_fhandle_reqrep_matching){
+ nlm_match_fhandle_reply(pinfo, tree);
+ }
+ }
+ }
+
+ offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
+
+ if (tree) {
+ lock_item = proto_tree_add_item(tree, hf_nlm_test_stat, tvb,
+ offset, -1, FALSE);
+ if (lock_item)
+ lock_tree = proto_item_add_subtree(lock_item,
+ ett_nlm_lock);
+ }
+
+ offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_test_stat_stat,
+ offset);
+
+ /* last structure is optional, only supplied for stat==1 (LOCKED) */
+ if(tvb_reported_length_remaining(tvb, offset) == 0){
+ return offset;
+ }
+
+ if (tree) {
+ lock_item = proto_tree_add_item(lock_tree, hf_nlm_holder, tvb,
+ offset, -1, FALSE);
+ if (lock_item)
+ lock_tree = proto_item_add_subtree(lock_item,
+ ett_nlm_lock);
+ }
+
+ offset = dissect_rpc_bool(tvb, lock_tree, hf_nlm_exclusive,
+ offset);
+ offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_lock_svid,
+ offset);
+ offset = dissect_rpc_data(tvb, lock_tree, hf_nlm_lock_owner,
+ offset);
+
+ if (version == 4) {
+ offset = dissect_rpc_uint64(tvb, lock_tree,
+ hf_nlm_lock_l_offset64, offset);
+ offset = dissect_rpc_uint64(tvb, lock_tree,
+ hf_nlm_lock_l_len64, offset);
+ }
+ else {
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nlm_lock_l_offset, offset);
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_nlm_lock_l_len, offset);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_nlm_share(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree,int version _U_)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+
+ offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
+
+ if (tree) {
+ lock_item = proto_tree_add_item(tree, hf_nlm_share, tvb,
+ offset, -1, FALSE);
+ if (lock_item)
+ lock_tree = proto_item_add_subtree(lock_item,
+ ett_nlm_lock);
+ }
+
+ offset = dissect_rpc_string(tvb,lock_tree,
+ hf_nlm_lock_caller_name, offset, NULL);
+
+ offset = dissect_nfs_fh3(tvb, offset, pinfo, lock_tree, "fh", NULL);
+
+ offset = dissect_rpc_data(tvb, lock_tree, hf_nlm_lock_owner, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_share_mode, offset);
+ offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_share_access, offset);
+
+
+ offset = dissect_rpc_bool(tvb, tree, hf_nlm_reclaim, offset);
+ return offset;
+}
+
+static int
+dissect_nlm_shareres(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, int version _U_)
+{
+ offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nlm_stat, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nlm_sequence, offset);
+ return offset;
+}
+
+static int
+dissect_nlm_freeall(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree,int version _U_)
+{
+ offset = dissect_rpc_string(tvb,tree,
+ hf_nlm_share_name, offset, NULL);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_nlm_stat, offset);
+
+ return offset;
+}
+
+
+/* RPC functions */
+
+
+/* This function is identical for all NLM protocol versions (1-4)*/
+static int
+dissect_nlm_gen_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ if(nlm_match_msgres){
+ rpc_call_info_value *rpc_call=pinfo->private_data;
+ if((rpc_call->proc==12) /* NLM_LOCK_RES */
+ || (rpc_call->proc==13) /* NLM_CANCEL_RES */
+ || (rpc_call->proc==14) /* NLM_UNLOCK_RES */
+ || (rpc_call->proc==15) ){ /* NLM_GRENTED_RES */
+ if( (!pinfo->fd->flags.visited) ){
+ nlm_register_unmatched_res(pinfo, tvb, offset);
+ } else {
+ nlm_print_msgres_reply(pinfo, tree, tvb);
+ }
+ /* for the fhandle matching that finds both request and
+ response packet */
+ if(nfs_fhandle_reqrep_matching){
+ nlm_match_fhandle_reply(pinfo, tree);
+ }
+ }
+ }
+
+ offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_nlm_stat, offset);
+ return offset;
+}
+
+static int
+dissect_nlm1_test(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_test(tvb,offset,pinfo,tree,1);
+}
+
+static int
+dissect_nlm4_test(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_test(tvb,offset,pinfo,tree,4);
+}
+
+
+static int
+dissect_nlm1_lock(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_lock(tvb,offset,pinfo,tree,1);
+}
+
+static int
+dissect_nlm4_lock(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_lock(tvb,offset,pinfo,tree,4);
+}
+
+
+static int
+dissect_nlm1_cancel(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_cancel(tvb,offset,pinfo,tree,1);
+}
+
+static int
+dissect_nlm4_cancel(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_cancel(tvb,offset,pinfo,tree,4);
+}
+
+
+static int
+dissect_nlm1_unlock(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_unlock(tvb,offset,pinfo,tree,1);
+}
+
+static int
+dissect_nlm4_unlock(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_unlock(tvb,offset,pinfo,tree,4);
+}
+
+
+static int
+dissect_nlm1_granted(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_granted(tvb,offset,pinfo,tree,1);
+}
+
+static int
+dissect_nlm4_granted(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_granted(tvb,offset,pinfo,tree,4);
+}
+
+
+static int
+dissect_nlm1_test_res(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_test_res(tvb,offset,pinfo,tree,1);
+}
+
+static int
+dissect_nlm4_test_res(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_test_res(tvb,offset,pinfo,tree,4);
+}
+
+static int
+dissect_nlm3_share(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_share(tvb,offset,pinfo,tree,3);
+}
+
+static int
+dissect_nlm4_share(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_share(tvb,offset,pinfo,tree,4);
+}
+
+static int
+dissect_nlm3_shareres(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_shareres(tvb,offset,pinfo,tree,3);
+}
+
+static int
+dissect_nlm4_shareres(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_shareres(tvb,offset,pinfo,tree,4);
+}
+
+static int
+dissect_nlm3_freeall(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_freeall(tvb,offset,pinfo,tree,3);
+}
+
+static int
+dissect_nlm4_freeall(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ return dissect_nlm_freeall(tvb,offset,pinfo,tree,4);
+}
+
+
+
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+/* NLM protocol version 1 */
+static const vsff nlm1_proc[] = {
+ { NLM_NULL, "NULL",
+ NULL, NULL },
+ { NLM_TEST, "TEST",
+ dissect_nlm1_test, dissect_nlm1_test_res },
+ { NLM_LOCK, "LOCK",
+ dissect_nlm1_lock, dissect_nlm_gen_reply },
+ { NLM_CANCEL, "CANCEL",
+ dissect_nlm1_cancel, dissect_nlm_gen_reply },
+ { NLM_UNLOCK, "UNLOCK",
+ dissect_nlm1_unlock, dissect_nlm_gen_reply },
+ { NLM_GRANTED, "GRANTED",
+ dissect_nlm1_granted, dissect_nlm_gen_reply },
+ { NLM_TEST_MSG, "TEST_MSG",
+ dissect_nlm1_test, NULL },
+ { NLM_LOCK_MSG, "LOCK_MSG",
+ dissect_nlm1_lock, NULL },
+ { NLM_CANCEL_MSG, "CANCEL_MSG",
+ dissect_nlm1_cancel, NULL },
+ { NLM_UNLOCK_MSG, "UNLOCK_MSG",
+ dissect_nlm1_unlock, NULL },
+ { NLM_GRANTED_MSG, "GRANTED_MSG",
+ dissect_nlm1_granted, NULL },
+ { NLM_TEST_RES, "TEST_RES",
+ dissect_nlm1_test_res, NULL },
+ { NLM_LOCK_RES, "LOCK_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_CANCEL_RES, "CANCEL_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_UNLOCK_RES, "UNLOCK_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_GRANTED_RES, "GRANTED_RES",
+ dissect_nlm_gen_reply, NULL },
+ { 0, NULL,
+ NULL, NULL }
+};
+static const value_string nlm1_proc_vals[] = {
+ { NLM_NULL, "NULL" },
+ { NLM_TEST, "TEST" },
+ { NLM_LOCK, "LOCK" },
+ { NLM_CANCEL, "CANCEL" },
+ { NLM_UNLOCK, "UNLOCK" },
+ { NLM_GRANTED, "GRANTED" },
+ { NLM_TEST_MSG, "TEST_MSG" },
+ { NLM_LOCK_MSG, "LOCK_MSG" },
+ { NLM_CANCEL_MSG, "CANCEL_MSG" },
+ { NLM_UNLOCK_MSG, "UNLOCK_MSG" },
+ { NLM_GRANTED_MSG, "GRANTED_MSG" },
+ { NLM_TEST_RES, "TEST_RES" },
+ { NLM_LOCK_RES, "LOCK_RES" },
+ { NLM_CANCEL_RES, "CANCEL_RES" },
+ { NLM_UNLOCK_RES, "UNLOCK_RES" },
+ { NLM_GRANTED_RES, "GRANTED_RES" },
+ { 0, NULL }
+};
+/* end of NLM protocol version 1 */
+
+/* NLM protocol version 2 */
+static const vsff nlm2_proc[] = {
+ { NLM_NULL, "NULL",
+ NULL, NULL },
+ { NLM_TEST, "TEST",
+ dissect_nlm1_test, dissect_nlm1_test_res },
+ { NLM_LOCK, "LOCK",
+ dissect_nlm1_lock, dissect_nlm_gen_reply },
+ { NLM_CANCEL, "CANCEL",
+ dissect_nlm1_cancel, dissect_nlm_gen_reply },
+ { NLM_UNLOCK, "UNLOCK",
+ dissect_nlm1_unlock, dissect_nlm_gen_reply },
+ { NLM_GRANTED, "GRANTED",
+ dissect_nlm1_granted, dissect_nlm_gen_reply },
+ { NLM_TEST_MSG, "TEST_MSG",
+ dissect_nlm1_test, NULL },
+ { NLM_LOCK_MSG, "LOCK_MSG",
+ dissect_nlm1_lock, NULL },
+ { NLM_CANCEL_MSG, "CANCEL_MSG",
+ dissect_nlm1_cancel, NULL },
+ { NLM_UNLOCK_MSG, "UNLOCK_MSG",
+ dissect_nlm1_unlock, NULL },
+ { NLM_GRANTED_MSG, "GRANTED_MSG",
+ dissect_nlm1_granted, NULL },
+ { NLM_TEST_RES, "TEST_RES",
+ dissect_nlm1_test_res, NULL },
+ { NLM_LOCK_RES, "LOCK_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_CANCEL_RES, "CANCEL_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_UNLOCK_RES, "UNLOCK_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_GRANTED_RES, "GRANTED_RES",
+ dissect_nlm_gen_reply, NULL },
+ { 0, NULL,
+ NULL, NULL }
+};
+static const value_string nlm2_proc_vals[] = {
+ { NLM_NULL, "NULL" },
+ { NLM_TEST, "TEST" },
+ { NLM_LOCK, "LOCK" },
+ { NLM_CANCEL, "CANCEL" },
+ { NLM_UNLOCK, "UNLOCK" },
+ { NLM_GRANTED, "GRANTED" },
+ { NLM_TEST_MSG, "TEST_MSG" },
+ { NLM_LOCK_MSG, "LOCK_MSG" },
+ { NLM_CANCEL_MSG, "CANCEL_MSG" },
+ { NLM_UNLOCK_MSG, "UNLOCK_MSG" },
+ { NLM_GRANTED_MSG, "GRANTED_MSG" },
+ { NLM_TEST_RES, "TEST_RES" },
+ { NLM_LOCK_RES, "LOCK_RES" },
+ { NLM_CANCEL_RES, "CANCEL_RES" },
+ { NLM_UNLOCK_RES, "UNLOCK_RES" },
+ { NLM_GRANTED_RES, "GRANTED_RES" },
+ { 0, NULL }
+};
+/* end of NLM protocol version 2 */
+
+/* NLM protocol version 3 */
+static const vsff nlm3_proc[] = {
+ { NLM_NULL, "NULL",
+ NULL, NULL },
+ { NLM_TEST, "TEST",
+ dissect_nlm1_test, dissect_nlm1_test_res },
+ { NLM_LOCK, "LOCK",
+ dissect_nlm1_lock, dissect_nlm_gen_reply },
+ { NLM_CANCEL, "CANCEL",
+ dissect_nlm1_cancel, dissect_nlm_gen_reply },
+ { NLM_UNLOCK, "UNLOCK",
+ dissect_nlm1_unlock, dissect_nlm_gen_reply },
+ { NLM_GRANTED, "GRANTED",
+ dissect_nlm1_granted, dissect_nlm_gen_reply },
+ { NLM_TEST_MSG, "TEST_MSG",
+ dissect_nlm1_test, NULL },
+ { NLM_LOCK_MSG, "LOCK_MSG",
+ dissect_nlm1_lock, NULL },
+ { NLM_CANCEL_MSG, "CANCEL_MSG",
+ dissect_nlm1_cancel, NULL },
+ { NLM_UNLOCK_MSG, "UNLOCK_MSG",
+ dissect_nlm1_unlock, NULL },
+ { NLM_GRANTED_MSG, "GRANTED_MSG",
+ dissect_nlm1_granted, NULL },
+ { NLM_TEST_RES, "TEST_RES",
+ dissect_nlm1_test_res, NULL },
+ { NLM_LOCK_RES, "LOCK_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_CANCEL_RES, "CANCEL_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_UNLOCK_RES, "UNLOCK_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_GRANTED_RES, "GRANTED_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_SHARE, "SHARE",
+ dissect_nlm3_share, dissect_nlm3_shareres },
+ { NLM_UNSHARE, "UNSHARE",
+ dissect_nlm3_share, dissect_nlm3_shareres },
+ { NLM_NM_LOCK, "NM_LOCK",
+ dissect_nlm1_lock, dissect_nlm_gen_reply },
+ { NLM_FREE_ALL, "FREE_ALL",
+ dissect_nlm3_freeall, NULL },
+ { 0, NULL,
+ NULL, NULL }
+};
+static const value_string nlm3_proc_vals[] = {
+ { NLM_NULL, "NULL" },
+ { NLM_TEST, "TEST" },
+ { NLM_LOCK, "LOCK" },
+ { NLM_CANCEL, "CANCEL" },
+ { NLM_UNLOCK, "UNLOCK" },
+ { NLM_GRANTED, "GRANTED" },
+ { NLM_TEST_MSG, "TEST_MSG" },
+ { NLM_LOCK_MSG, "LOCK_MSG" },
+ { NLM_CANCEL_MSG, "CANCEL_MSG" },
+ { NLM_UNLOCK_MSG, "UNLOCK_MSG" },
+ { NLM_GRANTED_MSG, "GRANTED_MSG" },
+ { NLM_TEST_RES, "TEST_RES" },
+ { NLM_LOCK_RES, "LOCK_RES" },
+ { NLM_CANCEL_RES, "CANCEL_RES" },
+ { NLM_UNLOCK_RES, "UNLOCK_RES" },
+ { NLM_GRANTED_RES, "GRANTED_RES" },
+ { NLM_SHARE, "SHARE" },
+ { NLM_UNSHARE, "UNSHARE" },
+ { NLM_NM_LOCK, "NM_LOCK" },
+ { NLM_FREE_ALL, "FREE_ALL" },
+ { 0, NULL }
+};
+/* end of NLM protocol version 3 */
+
+
+/* NLM protocol version 4 */
+static const vsff nlm4_proc[] = {
+ { NLM_NULL, "NULL",
+ NULL, NULL },
+ { NLM_TEST, "TEST",
+ dissect_nlm4_test, dissect_nlm4_test_res },
+ { NLM_LOCK, "LOCK",
+ dissect_nlm4_lock, dissect_nlm_gen_reply },
+ { NLM_CANCEL, "CANCEL",
+ dissect_nlm4_cancel, dissect_nlm_gen_reply },
+ { NLM_UNLOCK, "UNLOCK",
+ dissect_nlm4_unlock, dissect_nlm_gen_reply },
+ { NLM_GRANTED, "GRANTED",
+ dissect_nlm4_granted, dissect_nlm_gen_reply },
+ { NLM_TEST_MSG, "TEST_MSG",
+ dissect_nlm4_test, NULL },
+ { NLM_LOCK_MSG, "LOCK_MSG",
+ dissect_nlm4_lock, NULL },
+ { NLM_CANCEL_MSG, "CANCEL_MSG",
+ dissect_nlm4_cancel, NULL },
+ { NLM_UNLOCK_MSG, "UNLOCK_MSG",
+ dissect_nlm4_unlock, NULL },
+ { NLM_GRANTED_MSG, "GRANTED_MSG",
+ dissect_nlm4_granted, NULL },
+ { NLM_TEST_RES, "TEST_RES",
+ dissect_nlm4_test_res, NULL },
+ { NLM_LOCK_RES, "LOCK_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_CANCEL_RES, "CANCEL_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_UNLOCK_RES, "UNLOCK_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_GRANTED_RES, "GRANTED_RES",
+ dissect_nlm_gen_reply, NULL },
+ { NLM_SHARE, "SHARE",
+ dissect_nlm4_share, dissect_nlm4_shareres },
+ { NLM_UNSHARE, "UNSHARE",
+ dissect_nlm4_share, dissect_nlm4_shareres },
+ { NLM_NM_LOCK, "NM_LOCK",
+ dissect_nlm4_lock, dissect_nlm_gen_reply },
+ { NLM_FREE_ALL, "FREE_ALL",
+ dissect_nlm4_freeall, NULL },
+ { 0, NULL,
+ NULL, NULL }
+};
+static const value_string nlm4_proc_vals[] = {
+ { NLM_NULL, "NULL" },
+ { NLM_TEST, "TEST" },
+ { NLM_LOCK, "LOCK" },
+ { NLM_CANCEL, "CANCEL" },
+ { NLM_UNLOCK, "UNLOCK" },
+ { NLM_GRANTED, "GRANTED" },
+ { NLM_TEST_MSG, "TEST_MSG" },
+ { NLM_LOCK_MSG, "LOCK_MSG" },
+ { NLM_CANCEL_MSG, "CANCEL_MSG" },
+ { NLM_UNLOCK_MSG, "UNLOCK_MSG" },
+ { NLM_GRANTED_MSG, "GRANTED_MSG" },
+ { NLM_TEST_RES, "TEST_RES" },
+ { NLM_LOCK_RES, "LOCK_RES" },
+ { NLM_CANCEL_RES, "CANCEL_RES" },
+ { NLM_UNLOCK_RES, "UNLOCK_RES" },
+ { NLM_GRANTED_RES, "GRANTED_RES" },
+ { NLM_SHARE, "SHARE" },
+ { NLM_UNSHARE, "UNSHARE" },
+ { NLM_NM_LOCK, "NM_LOCK" },
+ { NLM_FREE_ALL, "FREE_ALL" },
+ { 0, NULL }
+};
+/* end of NLM protocol version 4 */
+
+
+static struct true_false_string yesno = { "Yes", "No" };
+
+
+void
+proto_register_nlm(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_nlm_procedure_v1, {
+ "V1 Procedure", "nlm.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(nlm1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_nlm_procedure_v2, {
+ "V2 Procedure", "nlm.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(nlm2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_nlm_procedure_v3, {
+ "V3 Procedure", "nlm.procedure_v3", FT_UINT32, BASE_DEC,
+ VALS(nlm3_proc_vals), 0, "V3 Procedure", HFILL }},
+ { &hf_nlm_procedure_v4, {
+ "V4 Procedure", "nlm.procedure_v4", FT_UINT32, BASE_DEC,
+ VALS(nlm4_proc_vals), 0, "V4 Procedure", HFILL }},
+ { &hf_nlm_cookie, {
+ "cookie", "nlm.cookie", FT_BYTES, BASE_DEC,
+ NULL, 0, "cookie", HFILL }},
+ { &hf_nlm_block, {
+ "block", "nlm.block", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "block", HFILL }},
+ { &hf_nlm_exclusive, {
+ "exclusive", "nlm.exclusive", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "exclusive", HFILL }},
+ { &hf_nlm_lock, {
+ "lock", "nlm.lock", FT_NONE, 0,
+ NULL, 0, "lock", HFILL }},
+ { &hf_nlm_lock_caller_name, {
+ "caller_name", "nlm.lock.caller_name", FT_STRING, BASE_NONE,
+ NULL, 0, "caller_name", HFILL }},
+ { &hf_nlm_lock_owner, {
+ "owner", "nlm.lock.owner", FT_BYTES, BASE_DEC,
+ NULL, 0, "owner", HFILL }},
+ { &hf_nlm_lock_svid, {
+ "svid", "nlm.lock.svid", FT_UINT32, BASE_DEC,
+ NULL, 0, "svid", HFILL }},
+ { &hf_nlm_lock_l_offset64, {
+ "l_offset", "nlm.lock.l_offset", FT_UINT64, BASE_DEC,
+ NULL, 0, "l_offset", HFILL }},
+ { &hf_nlm_lock_l_offset, {
+ "l_offset", "nlm.lock.l_offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "l_offset", HFILL }},
+ { &hf_nlm_lock_l_len64, {
+ "l_len", "nlm.lock.l_len", FT_UINT64, BASE_DEC,
+ NULL, 0, "l_len", HFILL }},
+ { &hf_nlm_lock_l_len, {
+ "l_len", "nlm.lock.l_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "l_len", HFILL }},
+ { &hf_nlm_reclaim, {
+ "reclaim", "nlm.reclaim", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "reclaim", HFILL }},
+ { &hf_nlm_state, {
+ "state", "nlm.state", FT_UINT32, BASE_DEC,
+ NULL, 0, "STATD state", HFILL }},
+ { &hf_nlm_stat, {
+ "stat", "nlm.stat", FT_UINT32, BASE_DEC,
+ VALS(names_nlm_stats), 0, "stat", HFILL }},
+ { &hf_nlm_test_stat, {
+ "test_stat", "nlm.test_stat", FT_NONE, 0,
+ NULL, 0, "test_stat", HFILL }},
+ { &hf_nlm_test_stat_stat, {
+ "stat", "nlm.test_stat.stat", FT_UINT32, BASE_DEC,
+ VALS(names_nlm_stats), 0, "stat", HFILL }},
+ { &hf_nlm_holder, {
+ "holder", "nlm.holder", FT_NONE, 0,
+ NULL, 0, "holder", HFILL }},
+ { &hf_nlm_share, {
+ "share", "nlm.share", FT_NONE, 0,
+ NULL, 0, "share", HFILL }},
+ { &hf_nlm_share_mode, {
+ "mode", "nlm.share.mode", FT_UINT32, BASE_DEC,
+ VALS(names_fsh_mode), 0, "mode", HFILL }},
+ { &hf_nlm_share_access, {
+ "access", "nlm.share.access", FT_UINT32, BASE_DEC,
+ VALS(names_fsh_access), 0, "access", HFILL }},
+ { &hf_nlm_share_name, {
+ "name", "nlm.share.name", FT_STRING, BASE_NONE,
+ NULL, 0, "name", HFILL }},
+ { &hf_nlm_sequence, {
+ "sequence", "nlm.sequence", FT_INT32, BASE_DEC,
+ NULL, 0, "sequence", HFILL }},
+ { &hf_nlm_request_in, {
+ "Request MSG in", "nlm.msg_in", FT_UINT32, BASE_DEC,
+ NULL, 0, "The RES packet is a response to the MSG in this packet", HFILL }},
+ { &hf_nlm_reply_in, {
+ "Reply RES in", "nlm.res_in", FT_UINT32, BASE_DEC,
+ NULL, 0, "The response to this MSG packet is in this packet", HFILL }},
+ { &hf_nlm_time, {
+ "Time from request", "nlm.time", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Time between Request and Reply for async NLM calls", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_nlm,
+ &ett_nlm_lock,
+ };
+ module_t *nlm_module;
+
+ proto_nlm = proto_register_protocol("Network Lock Manager Protocol",
+ "NLM", "nlm");
+ proto_register_field_array(proto_nlm, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ nlm_module = prefs_register_protocol(proto_nlm, NULL);
+ prefs_register_bool_preference(nlm_module, "msg_res_matching",
+ "Match MSG/RES packets for async NLM",
+ "Whether the dissector will track and match MSG and RES calls for asynchronous NLM",
+ &nlm_match_msgres);
+ register_init_routine(nlm_msg_res_match_init);
+}
+
+void
+proto_reg_handoff_nlm(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_nlm, NLM_PROGRAM, ett_nlm);
+ /* Register the procedure tables */
+ rpc_init_proc_table(NLM_PROGRAM, 1, nlm1_proc, hf_nlm_procedure_v1);
+ rpc_init_proc_table(NLM_PROGRAM, 2, nlm2_proc, hf_nlm_procedure_v2);
+ rpc_init_proc_table(NLM_PROGRAM, 3, nlm3_proc, hf_nlm_procedure_v3);
+ rpc_init_proc_table(NLM_PROGRAM, 4, nlm4_proc, hf_nlm_procedure_v4);
+}
diff --git a/epan/dissectors/packet-nlm.h b/epan/dissectors/packet-nlm.h
new file mode 100644
index 0000000000..65e3ec18b4
--- /dev/null
+++ b/epan/dissectors/packet-nlm.h
@@ -0,0 +1,40 @@
+/* packet-nlm.h (c) 1999 Uwe Girlich */
+/* $Id$ */
+
+#ifndef __PACKET_NLM_H__
+#define __PACKET_NLM_H__
+
+#define NLM_PROGRAM 100021
+
+/* synchronous procedures */
+#define NLM_NULL 0
+#define NLM_TEST 1
+#define NLM_LOCK 2
+#define NLM_CANCEL 3
+#define NLM_UNLOCK 4
+#define NLM_GRANTED 5
+
+/* asynchronous requests */
+#define NLM_TEST_MSG 6
+#define NLM_LOCK_MSG 7
+#define NLM_CANCEL_MSG 8
+#define NLM_UNLOCK_MSG 9
+#define NLM_GRANTED_MSG 10
+
+/* asynchronous responses */
+#define NLM_TEST_RES 11
+#define NLM_LOCK_RES 12
+#define NLM_CANCEL_RES 13
+#define NLM_UNLOCK_RES 14
+#define NLM_GRANTED_RES 15
+
+/* 16-19 not assigned */
+
+/* DOS file sharing */
+#define NLM_SHARE 20
+#define NLM_UNSHARE 21
+#define NLM_NM_LOCK 22
+#define NLM_FREE_ALL 23
+
+#endif /* packet-nlm.h */
+
diff --git a/epan/dissectors/packet-nlsp.c b/epan/dissectors/packet-nlsp.c
new file mode 100644
index 0000000000..11b3159510
--- /dev/null
+++ b/epan/dissectors/packet-nlsp.c
@@ -0,0 +1,1659 @@
+/* packet-nlsp.c
+ * Routines for NetWare Link Services Protocol
+ *
+ * $Id$
+ *
+ * Based on ISIS dissector by Stuart Stanley <stuarts@mxmail.net>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ipx.h"
+
+/* NLSP base header */
+static int proto_nlsp = -1;
+
+static int hf_nlsp_irpd = -1;
+static int hf_nlsp_header_length = -1;
+static int hf_nlsp_minor_version = -1;
+static int hf_nlsp_nr = -1;
+static int hf_nlsp_type = -1;
+static int hf_nlsp_major_version = -1;
+static int hf_nlsp_packet_length = -1;
+static int hf_nlsp_hello_state = -1;
+static int hf_nlsp_hello_multicast = -1;
+static int hf_nlsp_hello_circuit_type = -1;
+static int hf_nlsp_hello_holding_timer = -1;
+static int hf_nlsp_hello_priority = -1;
+static int hf_nlsp_lsp_sequence_number = -1;
+static int hf_nlsp_lsp_checksum = -1;
+static int hf_nlsp_lsp_p = -1;
+static int hf_nlsp_lsp_attached_flag = -1;
+static int hf_nlsp_lsp_lspdbol = -1;
+static int hf_nlsp_lsp_router_type = -1;
+
+static gint ett_nlsp = -1;
+static gint ett_nlsp_hello_clv_area_addr = -1;
+static gint ett_nlsp_hello_clv_neighbors = -1;
+static gint ett_nlsp_hello_local_mtu = -1;
+static gint ett_nlsp_hello_clv_unknown = -1;
+static gint ett_nlsp_lsp_info = -1;
+static gint ett_nlsp_lsp_clv_area_addr = -1;
+static gint ett_nlsp_lsp_clv_mgt_info = -1;
+static gint ett_nlsp_lsp_clv_link_info = -1;
+static gint ett_nlsp_lsp_clv_svcs_info = -1;
+static gint ett_nlsp_lsp_clv_ext_routes = -1;
+static gint ett_nlsp_lsp_clv_unknown = -1;
+static gint ett_nlsp_csnp_lsp_entries = -1;
+static gint ett_nlsp_csnp_lsp_entry = -1;
+static gint ett_nlsp_csnp_clv_unknown = -1;
+static gint ett_nlsp_psnp_lsp_entries = -1;
+static gint ett_nlsp_psnp_lsp_entry = -1;
+static gint ett_nlsp_psnp_clv_unknown = -1;
+
+#define PACKET_TYPE_MASK 0x1f
+
+/*
+ * See
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/cisintwk/ito_doc/nlsp.htm
+ *
+ * for some information about Hello packets.
+ */
+
+#define NLSP_TYPE_L1_HELLO 15
+#define NLSP_TYPE_WAN_HELLO 17
+#define NLSP_TYPE_L1_LSP 18
+#define NLSP_TYPE_L1_CSNP 24
+#define NLSP_TYPE_L1_PSNP 26
+
+static const value_string nlsp_packet_type_vals[] = {
+ { NLSP_TYPE_L1_HELLO, "L1 Hello"},
+ { NLSP_TYPE_WAN_HELLO, "WAN Hello"},
+ { NLSP_TYPE_L1_LSP, "L1 LSP"},
+ { NLSP_TYPE_L1_CSNP, "L1 CSNP"},
+ { NLSP_TYPE_L1_PSNP, "L1 PSNP"},
+ { 0, NULL}
+};
+
+static const value_string nlsp_attached_flag_vals[] = {
+ { 0, "Other routing areas cannot be reached through this router"},
+ { 1, "Other routing areas can be reached through this router"},
+ { 0, NULL}
+};
+
+static const value_string nlsp_router_type_vals[] = {
+ { 1, "Level 1 Router"},
+ { 3, "Level 1 and Level 2 Router"},
+ { 0, NULL}
+};
+
+static const true_false_string supported_string = {
+ "Supported",
+ "Unsupported"
+};
+
+/*
+ * Our sub-packet dismantle structure for CLV's
+ */
+typedef struct {
+ int optcode; /* code for option */
+ char *tree_text; /* text for fold out */
+ gint *tree_id; /* id for add_item */
+ void (*dissect)(tvbuff_t *tvb, proto_tree *tree,
+ int offset, int length);
+} nlsp_clv_handle_t;
+
+/*
+ * Name: nlsp_dissect_unknown()
+ *
+ * Description:
+ * There was some error in the protocol and we are in unknown space
+ * here. Add a tree item to cover the error and go on. Note
+ * that we make sure we don't go off the end of the bleedin packet here!
+ *
+ * Input
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : tree of display data. May be NULL.
+ * int : current offset into packet data
+ * char * : format text
+ * subsequent args : arguments to format
+ *
+ * Output:
+ * void (may modify proto tree)
+ */
+void
+nlsp_dissect_unknown(tvbuff_t *tvb, proto_tree *tree, int offset,
+ char *fmat, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmat);
+ proto_tree_add_text_valist(tree, tvb, offset, -1, fmat, ap);
+ va_end(ap);
+}
+
+/*
+ * Name: nlsp_dissect_clvs()
+ *
+ * Description:
+ * Dispatch routine to shred all the CLVs in a packet. We just
+ * walk through the clv entries in the packet. For each one, we
+ * search the passed in valid clv's for this protocol (opts) for
+ * a matching code. If found, we add to the display tree and
+ * then call the dissector. If it is not, we just post an
+ * "unknown" clv entry using the passed in unknown clv tree id.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * nlsp_clv_handle_t * : NULL dissector terminated array of codes
+ * and handlers (along with tree text and tree id's).
+ * int : length of CLV area.
+ * int : unknown clv tree id
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+nlsp_dissect_clvs(tvbuff_t *tvb, proto_tree *tree, int offset,
+ const nlsp_clv_handle_t *opts, int len, int unknown_tree_id)
+{
+ guint8 code;
+ guint8 length;
+ int q;
+ proto_item *ti;
+ proto_tree *clv_tree;
+ int adj;
+
+ while ( len > 0 ) {
+ code = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ length = tvb_get_guint8(tvb, offset);
+ offset += 1;
+
+ adj = (sizeof(code) + sizeof(length) + length);
+ len -= adj;
+ if ( len < 0 ) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short CLV header (%d vs %d)",
+ adj, len + adj );
+ return;
+ }
+ q = 0;
+ while ((opts[q].dissect != NULL )&&( opts[q].optcode != code )){
+ q++;
+ }
+ if ( opts[q].dissect ) {
+ if (tree) {
+ /* adjust by 2 for code/len octets */
+ ti = proto_tree_add_text(tree, tvb, offset - 2,
+ length + 2, "%s (%u)",
+ opts[q].tree_text, length );
+ clv_tree = proto_item_add_subtree(ti,
+ *opts[q].tree_id );
+ } else {
+ clv_tree = NULL;
+ }
+ opts[q].dissect(tvb, clv_tree, offset,
+ length);
+ } else {
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset - 2,
+ length + 2, "Unknown code %u (%u)",
+ code, length);
+ clv_tree = proto_item_add_subtree(ti,
+ unknown_tree_id );
+ } else {
+ clv_tree = NULL;
+ }
+ }
+ offset += length;
+ }
+}
+
+/*
+ * Name: dissect_area_address_clv()
+ *
+ * Description:
+ * Decode an area address clv.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ while (length > 0) {
+ if (length < 4) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short area address entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Area address network number: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ length -= 4;
+
+ if (length < 4) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short area address entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Area address mask: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ length -= 4;
+ }
+}
+
+/*
+ * Name: dissect_neighbor_clv()
+ *
+ * Description:
+ * Decode an neighbor clv.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_neighbor_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ while (length > 0) {
+ if (length < 6) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short neighbor entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Neighbor: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ offset += 6;
+ length -= 6;
+ }
+}
+
+/*
+ * Name: dissect_hello_local_mtu_clv()
+ *
+ * Description:
+ * Decode for a hello packet's local MTU clv.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_hello_local_mtu_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ if (length < 4) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short link info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "MTU Size: %u",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ length -= 4;
+}
+
+static const nlsp_clv_handle_t clv_hello_opts[] = {
+ {
+ 0xC0,
+ "Area address(es)",
+ &ett_nlsp_hello_clv_area_addr,
+ dissect_area_address_clv
+ },
+ {
+ 6,
+ "Neighbors",
+ &ett_nlsp_hello_clv_neighbors,
+ dissect_neighbor_clv
+ },
+ {
+ 0xC5,
+ "Local MTU",
+ &ett_nlsp_hello_local_mtu,
+ dissect_hello_local_mtu_clv
+ },
+
+ {
+ 0,
+ "",
+ NULL,
+ NULL
+ }
+};
+
+/*
+ * Name: nlsp_dissect_nlsp_hello()
+ *
+ * Description:
+ * This procedure rips apart NLSP hellos.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to add to. May be NULL.
+ * int offset : our offset into packet data.
+ * int : hello type, a la NLSP_TYPE_* values
+ * int : header length of packet.
+ *
+ * Output:
+ * void, will modify proto_tree if not NULL.
+ */
+#define NLSP_HELLO_CTYPE_MASK 0x03
+#define NLSP_HELLO_STATE_MASK 0xC0
+#define NLSP_HELLO_MULTICAST_MASK 0x10
+
+static const value_string nlsp_hello_state_vals[] = {
+ { 0, "Up" },
+ { 1, "Initializing" },
+ { 2, "Down" },
+ { 0, NULL }
+};
+
+#define NLSP_HELLO_TYPE_RESERVED 0
+#define NLSP_HELLO_TYPE_LEVEL_1 1
+#define NLSP_HELLO_TYPE_LEVEL_2 2
+#define NLSP_HELLO_TYPE_LEVEL_12 3
+
+static const value_string nlsp_hello_circuit_type_vals[] = {
+ { NLSP_HELLO_TYPE_RESERVED, "Reserved 0 (discard PDU)"},
+ { NLSP_HELLO_TYPE_LEVEL_1, "Level 1 only"},
+ { NLSP_HELLO_TYPE_LEVEL_2, "Level 2 only"},
+ { NLSP_HELLO_TYPE_LEVEL_12, "Level 1 and 2"},
+ { 0, NULL}
+};
+
+#define NLSP_HELLO_PRIORITY_MASK 0x7f
+
+static void
+nlsp_dissect_nlsp_hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int hello_type, int header_length)
+{
+ guint16 packet_length;
+ int len;
+ guint16 holding_timer;
+
+ if (tree) {
+ if (hello_type == NLSP_TYPE_WAN_HELLO) {
+ proto_tree_add_item(tree, hf_nlsp_hello_state, tvb,
+ offset, 1, FALSE);
+ } else {
+ proto_tree_add_item(tree, hf_nlsp_hello_multicast, tvb,
+ offset, 1, FALSE);
+ }
+ proto_tree_add_item(tree, hf_nlsp_hello_circuit_type, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Sending Router System ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", System ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ offset += 6;
+
+ if (tree) {
+ holding_timer = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_nlsp_hello_holding_timer,
+ tvb, offset, 2, holding_timer,
+ "Holding Timer: %us", holding_timer);
+ }
+ offset += 2;
+
+ packet_length = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nlsp_packet_length, tvb,
+ offset, 2, packet_length);
+ }
+ offset += 2;
+
+ if (tree) {
+ proto_tree_add_item(tree, hf_nlsp_hello_priority, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ if (hello_type == NLSP_TYPE_WAN_HELLO) {
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Local WAN Circuit ID: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ } else {
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Designated Router System ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ proto_tree_add_text(tree, tvb, offset+6, 1,
+ "Designated Router Pseudonode ID: %u",
+ tvb_get_guint8(tvb, offset+6));
+ }
+ offset += 7;
+ }
+
+ len = packet_length - header_length;
+ if (len < 0) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "packet header length %d went beyond packet",
+ header_length);
+ return;
+ }
+
+ /*
+ * Now, we need to decode our CLVs. We need to pass in
+ * our list of valid ones!
+ */
+ nlsp_dissect_clvs(tvb, tree, offset,
+ clv_hello_opts, len, ett_nlsp_hello_clv_unknown);
+}
+
+/*
+ * Name: dissect_lsp_mgt_info_clv()
+ *
+ * Description:
+ * Decode for a lsp packet's management information clv.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_mgt_info_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ guint8 name_length;
+
+ if (length < 4) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short management info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Network number: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ length -= 4;
+
+ if (length < 6) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short management info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Node number: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ offset += 6;
+ length -= 6;
+
+ if (length < 1) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short management info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "IPX version number: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ length -= 1;
+
+ if (length < 1) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short management info entry");
+ return;
+ }
+ name_length = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Name length: %u", name_length);
+ }
+ offset += 1;
+ length -= 1;
+
+ if (name_length != 0) {
+ if (length < name_length) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short management info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, name_length,
+ "Name: %s",
+ tvb_format_text(tvb, offset, name_length));
+ }
+ offset += name_length;
+ length -= name_length;
+ }
+}
+
+/*
+ * Name: dissect_lsp_link_info_clv()
+ *
+ * Description:
+ * Decode for a lsp packet's link information clv.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static const value_string media_type_vals[] = {
+ { 0x0000, "Generic LAN" },
+ { 0x8000, "Generic WAN" },
+ { 0x0001, "Localtalk" },
+ { 0x0002, "Ethernet II" },
+ { 0x0003, "IEEE 802.3 with IEEE 802.2 without SNAP" },
+ { 0x0005, "IEEE 802.3 with IPX header and no 802.2 header" },
+ { 0x000A, "IEEE 802.3 with IEEE 802.2 and SNAP" },
+ { 0x0004, "IEEE 802.5 with IEEE 802.2 without SNAP" },
+ { 0x000B, "IEEE 802.5 with IEEE 802.2 and SNAP" },
+ { 0x0006, "IEEE 802.4" },
+ { 0x0007, "IBM PC Network II" },
+ { 0x0008, "Gateway G/Net" },
+ { 0x0009, "Proteon ProNET" },
+ { 0x000C, "Racore LANPAC" },
+ { 0x800D, "ISDN" },
+ { 0x000E, "ARCnet" },
+ { 0x000F, "IBM PC Network II with 802.2 without SNAP" },
+ { 0x0010, "IBM PC Network II with 802.2 and SNAP" },
+ { 0x0011, "Corvus OmniNet at 4 Mbps" },
+ { 0x0012, "Harris Adacom" },
+ { 0x0013, "IP tunnel" },
+ { 0x8013, "IP Relay" },
+ { 0x0014, "FDDI with 802.2 without SNAP" },
+ { 0x0015, "Commtex IVDLAN" },
+ { 0x0016, "Dataco OSI" },
+ { 0x0017, "FDDI with 802.2 and SNAP" },
+ { 0x0018, "IBM SDLC tunnel" },
+ { 0x0019, "PC Office frame" },
+ { 0x001A, "Hypercommunications WAIDNET" },
+ { 0x801C, "PPP" },
+ { 0x801D, "Proxim RangeLAN" },
+ { 0x801E, "X.25" },
+ { 0x801F, "Frame Relay" },
+ { 0x0020, "Integrated Workstations BUS-NET" },
+ { 0x8021, "Novell SNA Links" },
+ { 0, NULL }
+};
+
+static void
+dissect_lsp_link_info_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ guint8 flags_cost;
+
+ if (length < 1) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short link info entry");
+ return;
+ }
+ if (tree) {
+ flags_cost = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ decode_boolean_bitfield(flags_cost, 0x80, 1*8,
+ "Cost not present", "Cost present"));
+ if (!(flags_cost & 0x80)) {
+ /*
+ * 0x80 clear => cost present.
+ */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ decode_boolean_bitfield(flags_cost, 0x40, 1*8,
+ "Cost is internal metric",
+ "Cost is external metric"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ decode_numeric_bitfield(flags_cost, 0x3F, 1*8,
+ "Cost = %u"));
+ }
+ }
+ offset += 1;
+ length -= 1;
+
+ if (length < 3) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short link info entry");
+ return;
+ }
+ offset += 3; /* Reserved */
+ length -= 3;
+
+ if (length < 7) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short link info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Router System ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ proto_tree_add_text(tree, tvb, offset+6, 1,
+ "Router Pseudonode ID: %u",
+ tvb_get_guint8(tvb, offset+6));
+ }
+ offset += 7;
+ length -= 7;
+
+ if (length < 4) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short link info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "MTU Size: %u",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ length -= 4;
+
+ if (length < 4) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short link info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Delay: %uus",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ length -= 4;
+
+ if (length < 4) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short link info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Throughput: %u bits/s",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ length -= 4;
+
+ if (length < 2) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short link info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Media type: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), media_type_vals,
+ "Unknown (0x%04x)"));
+ }
+ offset += 2;
+ length -= 2;
+}
+
+/*
+ * Name: dissect_lsp_svcs_info_clv()
+ *
+ * Description:
+ * Decode for a lsp packet's services information clv.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_svcs_info_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ if (length < 1) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short services info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Hops to reach the service: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ length -= 1;
+
+ if (length < 4) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short services info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Network number: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ length -= 4;
+
+ if (length < 6) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short services info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Node number: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ offset += 6;
+ length -= 6;
+
+ if (length < 2) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short services info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Socket: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), ipx_socket_vals,
+ "Unknown (0x%04x)"));
+ }
+ offset += 2;
+ length -= 2;
+
+ if (length < 2) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short services info entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Type: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), server_vals,
+ "Unknown (0x%04x)"));
+ }
+ offset += 2;
+ length -= 2;
+
+ if (length > 0) {
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Service Name: %s",
+ tvb_format_text(tvb, offset, length));
+ }
+ }
+}
+
+
+/*
+ * Name: dissect_lsp_ext_routes_clv()
+ *
+ * Description:
+ * Decode for a lsp packet's external routes clv.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of clv we are decoding
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_lsp_ext_routes_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ while (length > 0) {
+ if (length < 1) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short external routes entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Hops: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ length -= 1;
+
+ if (length < 4) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short external routes entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Network number: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+ length -= 4;
+
+ if (length < 2) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short external routes entry");
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "RIP delay: %u ticks",
+ tvb_get_ntohs(tvb, offset));
+ }
+ offset += 2;
+ length -= 2;
+ }
+}
+
+static const nlsp_clv_handle_t clv_l1_lsp_opts[] = {
+ {
+ 0xC0,
+ "Area address(es)",
+ &ett_nlsp_lsp_clv_area_addr,
+ dissect_area_address_clv
+ },
+ {
+ 0xC1,
+ "Management information",
+ &ett_nlsp_lsp_clv_mgt_info,
+ dissect_lsp_mgt_info_clv
+ },
+ {
+ 0xC2,
+ "Link information",
+ &ett_nlsp_lsp_clv_link_info,
+ dissect_lsp_link_info_clv
+ },
+ {
+ 0xC3,
+ "Services information",
+ &ett_nlsp_lsp_clv_svcs_info,
+ dissect_lsp_svcs_info_clv
+ },
+ {
+ 0xC4,
+ "External routes",
+ &ett_nlsp_lsp_clv_ext_routes,
+ dissect_lsp_ext_routes_clv
+ },
+
+ {
+ 0,
+ "",
+ NULL,
+ NULL
+ }
+};
+
+/*
+ * Name: nlsp_dissect_nlsp_lsp()
+ *
+ * Description:
+ * Print out the LSP part of the main header and then call the CLV
+ * de-mangler with the right list of valid CLVs.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to add to. May be NULL.
+ * int offset : our offset into packet data.
+ * int : header length of packet.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+/* P | ATT | OVERFLOW | ROUTER TYPE FIELD description */
+#define NLSP_LSP_PARTITION_MASK 0x80
+#define NLSP_LSP_PARTITION_SHIFT 7
+#define NLSP_LSP_PARTITION(info) (((info) & NLSP_LSP_PARTITION_MASK) >> NLSP_LSP_PARTITION_SHIFT)
+
+#define NLSP_LSP_ATT_MASK 0x78
+#define NLSP_LSP_ATT_SHIFT 3
+#define NLSP_LSP_ATT(info) (((info) & NLSP_LSP_ATT_MASK) >> NLSP_LSP_ATT_SHIFT)
+
+#define NLSP_LSP_OVERFLOW_MASK 0x04
+#define NLSP_LSP_OVERFLOW_SHIFT 2
+#define NLSP_LSP_OVERFLOW(info) (((info) & NLSP_LSP_OVERFLOW_MASK) >> NLSP_LSP_OVERFLOW_SHIFT)
+
+#define NLSP_LSP_ROUTER_TYPE_MASK 0x03
+#define NLSP_LSP_ROUTER_TYPE(info) ((info) & NLSP_LSP_ROUTER_TYPE_MASK)
+
+static void
+nlsp_dissect_nlsp_lsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int header_length)
+{
+ guint16 packet_length;
+ guint16 remaining_lifetime;
+ guint32 sequence_number;
+ int len;
+
+ packet_length = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nlsp_packet_length, tvb,
+ offset, 2, packet_length);
+ }
+ offset += 2;
+
+ remaining_lifetime = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Remaining Lifetime: %us",
+ remaining_lifetime);
+ }
+ offset += 2;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", LSP ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "LSP ID system ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ offset += 6;
+ /* XXX - append the pseudonode ID */
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "LSP ID pseudonode ID: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "LSP ID LSP number: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+
+ sequence_number = tvb_get_ntohl(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", Sequence: 0x%08x, Lifetime: %us",
+ sequence_number, remaining_lifetime);
+ }
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nlsp_lsp_sequence_number, tvb,
+ offset, 4, sequence_number);
+ }
+ offset += 4;
+
+ if (tree) {
+ /* XXX -> we could validate the cksum here! */
+ proto_tree_add_item(tree, hf_nlsp_lsp_checksum, tvb,
+ offset, 2, FALSE );
+ }
+ offset += 2;
+
+ if (tree) {
+ proto_tree_add_item(tree, hf_nlsp_lsp_p, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(tree, hf_nlsp_lsp_attached_flag, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(tree, hf_nlsp_lsp_lspdbol, tvb,
+ offset, 1, FALSE);
+ proto_tree_add_item(tree, hf_nlsp_lsp_router_type, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ len = packet_length - header_length;
+ if (len < 0) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "packet header length %d went beyond packet",
+ header_length);
+ return;
+ }
+
+ /*
+ * Now, we need to decode our CLVs. We need to pass in
+ * our list of valid ones!
+ */
+ nlsp_dissect_clvs(tvb, tree, offset,
+ clv_l1_lsp_opts, len, ett_nlsp_lsp_clv_unknown);
+}
+
+/*
+ * Name: dissect_snp_lsp_entries()
+ *
+ * Description:
+ * All the snp packets use a common payload format. We have up
+ * to n entries (based on length), which are made of:
+ * 2 : remaining life time
+ * 8 : lsp id
+ * 4 : sequence number
+ * 2 : checksum
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to fill out. May be NULL
+ * int : offset into packet data where we are.
+ * int : length of payload to decode.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+dissect_csnp_lsp_entries(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ proto_tree *subtree,*ti;
+
+ while (length > 0) {
+ if (length < 16) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short CSNP header entry");
+ return;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, 16,
+ "LSP-ID: %s, Sequence: 0x%08x, Lifetime: %5us, Checksum: 0x%04x",
+ ether_to_str(tvb_get_ptr(tvb, offset+2, 6)), /* XXX - rest of system ID */
+ tvb_get_ntohl(tvb, offset+10),
+ tvb_get_ntohs(tvb, offset),
+ tvb_get_ntohs(tvb, offset+14));
+
+ subtree = proto_item_add_subtree(ti, ett_nlsp_csnp_lsp_entry);
+
+ proto_tree_add_text(subtree, tvb, offset+2, 6,
+ "LSP ID source ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset+2, 6)));
+ proto_tree_add_text(subtree, tvb, offset+8, 1,
+ "LSP ID pseudonode ID: %u",
+ tvb_get_guint8(tvb, offset+8));
+ proto_tree_add_text(subtree, tvb, offset+9, 1,
+ "LSP ID LSP number: %u",
+ tvb_get_guint8(tvb, offset+9));
+
+ proto_tree_add_text(subtree, tvb, offset+10, 4,
+ "LSP Sequence Number: 0x%08x",
+ tvb_get_ntohl(tvb, offset+10));
+
+ proto_tree_add_text(subtree, tvb, offset, 2,
+ "Remaining Lifetime: %us",
+ tvb_get_ntohs(tvb, offset));
+
+ proto_tree_add_text(subtree, tvb, offset+14, 2,
+ "LSP checksum: 0x%04x",
+ tvb_get_ntohs(tvb, offset+14));
+
+ length -= 16;
+ offset += 16;
+ }
+}
+
+static void
+dissect_psnp_lsp_entries(tvbuff_t *tvb, proto_tree *tree, int offset,
+ int length)
+{
+ proto_tree *subtree,*ti;
+
+ while (length > 0) {
+ if (length < 16) {
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Short PSNP header entry");
+ return;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, 16,
+ "LSP-ID: %s, Sequence: 0x%08x, Lifetime: %5us, Checksum: 0x%04x",
+ ether_to_str(tvb_get_ptr(tvb, offset+2, 6)), /* XXX - rest of system ID */
+ tvb_get_ntohl(tvb, offset+10),
+ tvb_get_ntohs(tvb, offset),
+ tvb_get_ntohs(tvb, offset+14));
+
+ subtree = proto_item_add_subtree(ti, ett_nlsp_psnp_lsp_entry);
+
+ proto_tree_add_text(subtree, tvb, offset+2, 6,
+ "LSP ID source ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset+2, 6)));
+ proto_tree_add_text(subtree, tvb, offset+8, 1,
+ "LSP ID pseudonode ID: %u",
+ tvb_get_guint8(tvb, offset+8));
+ proto_tree_add_text(subtree, tvb, offset+9, 1,
+ "LSP ID LSP number: %u",
+ tvb_get_guint8(tvb, offset+9));
+
+ proto_tree_add_text(subtree, tvb, offset+10, 4,
+ "LSP Sequence Number: 0x%08x",
+ tvb_get_ntohl(tvb, offset+10));
+
+ proto_tree_add_text(subtree, tvb, offset, 2,
+ "Remaining Lifetime: %us",
+ tvb_get_ntohs(tvb, offset));
+
+ proto_tree_add_text(subtree, tvb, offset+14, 2,
+ "LSP checksum: 0x%04x",
+ tvb_get_ntohs(tvb, offset+14));
+
+ length -= 16;
+ offset += 16;
+ }
+}
+
+static const nlsp_clv_handle_t clv_l1_csnp_opts[] = {
+ {
+ 9,
+ "LSP entries",
+ &ett_nlsp_csnp_lsp_entries,
+ dissect_csnp_lsp_entries
+ },
+
+ {
+ 0,
+ "",
+ NULL,
+ NULL
+ }
+};
+
+/*
+ * Name: nlsp_dissect_nlsp_csnp()
+ *
+ * Description:
+ * Tear apart a L1 CSNP header and then call into payload dissect
+ * to pull apart the lsp id payload.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to add to. May be NULL.
+ * int offset : our offset into packet data.
+ * int : header length of packet.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+nlsp_dissect_nlsp_csnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int header_length)
+{
+ guint16 packet_length;
+ int len;
+
+ packet_length = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nlsp_packet_length, tvb,
+ offset, 2, packet_length);
+ }
+ offset += 2;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Source ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Source ID system ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ offset += 6;
+ /* XXX - add the pseudonode ID */
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Source ID pseudonode ID: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Start LSP ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Start LSP ID source ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ offset += 6;
+ /* XXX - append the pseudonode ID */
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Start LSP ID pseudonode ID: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Start LSP ID LSP number: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", End LSP ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "End LSP ID source ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ offset += 6;
+ /* XXX - append the pseudonode ID */
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "End LSP ID pseudonode ID: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "End LSP ID LSP number: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+
+ len = packet_length - header_length;
+ if (len < 0) {
+ return;
+ }
+ /* Call into payload dissector */
+ nlsp_dissect_clvs(tvb, tree, offset,
+ clv_l1_csnp_opts, len, ett_nlsp_csnp_clv_unknown);
+}
+
+static const nlsp_clv_handle_t clv_l1_psnp_opts[] = {
+ {
+ 9,
+ "LSP entries",
+ &ett_nlsp_psnp_lsp_entries,
+ dissect_psnp_lsp_entries
+ },
+
+ {
+ 0,
+ "",
+ NULL,
+ NULL
+ }
+};
+
+/*
+ * Name: nlsp_dissect_nlsp_psnp()
+ *
+ * Description:
+ * Tear apart a L1 PSNP header and then call into payload dissect
+ * to pull apart the lsp id payload.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * proto_tree * : protocol display tree to add to. May be NULL.
+ * int offset : our offset into packet data.
+ * int : header length of packet.
+ *
+ * Output:
+ * void, but we will add to proto tree if !NULL.
+ */
+static void
+nlsp_dissect_nlsp_psnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int header_length)
+{
+ guint16 packet_length;
+ int len;
+
+ packet_length = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_nlsp_packet_length, tvb,
+ offset, 2, packet_length);
+ }
+ offset += 2;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Source ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Source ID system ID: %s",
+ ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ offset += 6;
+ /* XXX - add the pseudonode ID */
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Source ID pseudonode ID: %u",
+ tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+
+ len = packet_length - header_length;
+ if (len < 0) {
+ return;
+ }
+ /* Call into payload dissector */
+ nlsp_dissect_clvs(tvb, tree, offset,
+ clv_l1_psnp_opts, len, ett_nlsp_psnp_clv_unknown);
+}
+
+/*
+ * Name: dissect_nlsp()
+ *
+ * Description:
+ * Main entry area for nlsp de-mangling. This will build the
+ * main nlsp tree data and call the sub-protocols as needed.
+ *
+ * Input:
+ * tvbuff_t * : tvbuffer for packet data
+ * packet_info * : info for current packet
+ * proto_tree * : tree of display data. May be NULL.
+ *
+ * Output:
+ * void, but we will add to the proto_tree if it is not NULL.
+ */
+static void
+dissect_nlsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *nlsp_tree = NULL;
+ int offset = 0;
+ guint8 nlsp_major_version;
+ guint8 nlsp_header_length;
+ guint8 packet_type_flags;
+ guint8 packet_type;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NLSP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ nlsp_major_version = tvb_get_guint8(tvb, 5);
+ if (nlsp_major_version != 1){
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Unknown NLSP version (%u vs 1)",
+ nlsp_major_version);
+ }
+ nlsp_dissect_unknown(tvb, tree, 0,
+ "Unknown NLSP version (%d vs 1)",
+ nlsp_major_version, 1);
+ return;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nlsp, tvb, 0, -1, FALSE);
+ nlsp_tree = proto_item_add_subtree(ti, ett_nlsp);
+ }
+
+ if (tree) {
+ proto_tree_add_item(nlsp_tree, hf_nlsp_irpd, tvb, offset, 1,
+ FALSE );
+ }
+ offset += 1;
+
+ nlsp_header_length = tvb_get_guint8(tvb, 1);
+ if (tree) {
+ proto_tree_add_uint(nlsp_tree, hf_nlsp_header_length, tvb,
+ offset, 1, nlsp_header_length );
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_item(nlsp_tree, hf_nlsp_minor_version, tvb,
+ offset, 1, FALSE );
+ }
+ offset += 1;
+
+ offset += 1; /* Reserved */
+
+ packet_type_flags = tvb_get_guint8(tvb, offset);
+ packet_type = packet_type_flags & PACKET_TYPE_MASK;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(packet_type, nlsp_packet_type_vals, "Unknown (%u)"));
+ }
+ if (tree) {
+ if (packet_type == NLSP_TYPE_L1_LSP) {
+ proto_tree_add_boolean(nlsp_tree, hf_nlsp_nr, tvb, offset, 1,
+ packet_type_flags );
+ }
+ proto_tree_add_uint(nlsp_tree, hf_nlsp_type, tvb, offset, 1,
+ packet_type_flags );
+ }
+ offset += 1;
+
+ if (tree) {
+ proto_tree_add_item(nlsp_tree, hf_nlsp_major_version, tvb,
+ offset, 1, FALSE );
+ }
+ offset += 1;
+
+ offset += 2; /* Reserved */
+
+ switch (packet_type) {
+
+ case NLSP_TYPE_L1_HELLO:
+ case NLSP_TYPE_WAN_HELLO:
+ nlsp_dissect_nlsp_hello(tvb, pinfo, nlsp_tree, offset,
+ packet_type, nlsp_header_length);
+ break;
+
+ case NLSP_TYPE_L1_LSP:
+ nlsp_dissect_nlsp_lsp(tvb, pinfo, nlsp_tree, offset,
+ nlsp_header_length);
+ break;
+
+ case NLSP_TYPE_L1_CSNP:
+ nlsp_dissect_nlsp_csnp(tvb, pinfo, nlsp_tree, offset,
+ nlsp_header_length);
+ break;
+
+ case NLSP_TYPE_L1_PSNP:
+ nlsp_dissect_nlsp_psnp(tvb, pinfo, nlsp_tree, offset,
+ nlsp_header_length);
+ break;
+
+ default:
+ nlsp_dissect_unknown(tvb, tree, offset,
+ "Unknown NLSP packet type");
+ }
+}
+
+/*
+ * Name: proto_register_nlsp()
+ *
+ * Description:
+ * main register for NLSP protocol set. We register some display
+ * formats and the protocol module variables.
+ *
+ * NOTE: this procedure to autolinked by the makefile process that
+ * builds register.c
+ *
+ * Input:
+ * void
+ *
+ * Output:
+ * void
+ */
+void
+proto_register_nlsp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_nlsp_irpd,
+ { "NetWare Link Services Protocol Discriminator", "nlsp.irpd",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nlsp_header_length,
+ { "PDU Header Length", "nlsp.header_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nlsp_minor_version,
+ { "Minor Version", "nlsp.minor_version", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nlsp_nr,
+ { "Multi-homed Non-routing Server", "nlsp.nr", FT_BOOLEAN, 8,
+ NULL, 0x80, "", HFILL }},
+
+ { &hf_nlsp_type,
+ { "Packet Type", "nlsp.type", FT_UINT8, BASE_DEC,
+ VALS(nlsp_packet_type_vals), PACKET_TYPE_MASK, "", HFILL }},
+
+ { &hf_nlsp_major_version,
+ { "Major Version", "nlsp.major_version", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nlsp_packet_length,
+ { "Packet Length", "nlsp.packet_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_nlsp_hello_state,
+ { "State", "nlsp.hello.state", FT_UINT8, BASE_DEC,
+ VALS(nlsp_hello_state_vals), NLSP_HELLO_STATE_MASK,
+ "", HFILL }},
+
+ { &hf_nlsp_hello_multicast,
+ { "Multicast Routing", "nlsp.hello.multicast", FT_BOOLEAN, 8,
+ TFS(&supported_string), NLSP_HELLO_MULTICAST_MASK,
+ "If set, this router supports multicast routing", HFILL }},
+
+ { &hf_nlsp_hello_circuit_type,
+ { "Circuit Type", "nlsp.hello.circuit_type", FT_UINT8, BASE_DEC,
+ VALS(nlsp_hello_circuit_type_vals), NLSP_HELLO_CTYPE_MASK,
+ "", HFILL }},
+
+ { &hf_nlsp_hello_holding_timer,
+ { "Holding Timer", "nlsp.hello.holding_timer", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_nlsp_hello_priority,
+ { "Priority", "nlsp.hello.priority", FT_UINT8, BASE_DEC,
+ NULL, NLSP_HELLO_PRIORITY_MASK,
+ "", HFILL }},
+
+ { &hf_nlsp_lsp_sequence_number,
+ { "Sequence Number", "nlsp.sequence_number",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nlsp_lsp_checksum,
+ { "Checksum", "nlsp.lsp.checksum",
+ FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_nlsp_lsp_p,
+ { "Partition Repair", "nlsp.lsp.partition_repair", FT_BOOLEAN, 8,
+ TFS(&supported_string), NLSP_LSP_PARTITION_MASK,
+ "If set, this router supports the optional Partition Repair function", HFILL }},
+
+ { &hf_nlsp_lsp_attached_flag,
+ { "Attached Flag", "nlsp.lsp.attached_flag", FT_UINT8, BASE_DEC,
+ VALS(nlsp_attached_flag_vals), NLSP_LSP_ATT_MASK, "", HFILL }},
+
+ { &hf_nlsp_lsp_lspdbol,
+ { "LSP Database Overloaded", "nlsp.lsp.lspdbol", FT_BOOLEAN, 8,
+ NULL, NLSP_LSP_OVERFLOW_MASK, "", HFILL }},
+
+ { &hf_nlsp_lsp_router_type,
+ { "Router Type", "nlsp.lsp.router_type", FT_UINT8, BASE_DEC,
+ VALS(nlsp_router_type_vals), NLSP_LSP_ROUTER_TYPE_MASK,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_nlsp,
+ &ett_nlsp_hello_clv_area_addr,
+ &ett_nlsp_hello_clv_neighbors,
+ &ett_nlsp_hello_local_mtu,
+ &ett_nlsp_hello_clv_unknown,
+ &ett_nlsp_lsp_info,
+ &ett_nlsp_lsp_clv_area_addr,
+ &ett_nlsp_lsp_clv_mgt_info,
+ &ett_nlsp_lsp_clv_link_info,
+ &ett_nlsp_lsp_clv_svcs_info,
+ &ett_nlsp_lsp_clv_ext_routes,
+ &ett_nlsp_lsp_clv_unknown,
+ &ett_nlsp_csnp_lsp_entries,
+ &ett_nlsp_csnp_lsp_entry,
+ &ett_nlsp_csnp_clv_unknown,
+ &ett_nlsp_psnp_lsp_entries,
+ &ett_nlsp_psnp_lsp_entry,
+ &ett_nlsp_psnp_clv_unknown,
+ };
+
+ proto_nlsp = proto_register_protocol("NetWare Link Services Protocol",
+ "NLSP", "nlsp");
+ proto_register_field_array(proto_nlsp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_nlsp(void)
+{
+ dissector_handle_t nlsp_handle;
+
+ nlsp_handle = create_dissector_handle(dissect_nlsp, proto_nlsp);
+ dissector_add("ipx.socket", IPX_SOCKET_NLSP, nlsp_handle);
+}
diff --git a/epan/dissectors/packet-nntp.c b/epan/dissectors/packet-nntp.c
new file mode 100644
index 0000000000..71478fcd07
--- /dev/null
+++ b/epan/dissectors/packet-nntp.c
@@ -0,0 +1,148 @@
+/* packet-nntp.c
+ * Routines for nntp packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+static int proto_nntp = -1;
+static int hf_nntp_response = -1;
+static int hf_nntp_request = -1;
+
+static gint ett_nntp = -1;
+
+#define TCP_PORT_NNTP 119
+
+static void
+dissect_nntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gchar *type;
+ proto_tree *nntp_tree;
+ proto_item *ti;
+ gint offset = 0;
+ gint next_offset;
+ int linelen;
+
+ if (pinfo->match_port == pinfo->destport)
+ type = "Request";
+ else
+ type = "Response";
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NNTP");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary
+ * (but leave out the line terminator).
+ *
+ * Note that "tvb_find_line_end()" will return a value that
+ * is not longer than what's in the buffer, so the
+ * "tvb_get_ptr()" call won't throw an exception.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
+ FALSE);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", type,
+ tvb_format_text(tvb, offset, linelen));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_nntp, tvb, offset, -1,
+ FALSE);
+ nntp_tree = proto_item_add_subtree(ti, ett_nntp);
+
+ if (pinfo->match_port == pinfo->destport) {
+ proto_tree_add_boolean_hidden(nntp_tree,
+ hf_nntp_request, tvb, 0, 0, TRUE);
+ } else {
+ proto_tree_add_boolean_hidden(nntp_tree,
+ hf_nntp_response, tvb, 0, 0, TRUE);
+ }
+
+ /*
+ * Show the request or response as text, a line at a time.
+ * XXX - for requests, we could display the stuff after the
+ * first line, if any, based on what the request was, and
+ * for responses, we could display it based on what the
+ * matching request was, although the latter requires us to
+ * know what the matching request was....
+ */
+ while (tvb_offset_exists(tvb, offset)) {
+ /*
+ * Find the end of the line.
+ */
+ tvb_find_line_end(tvb, offset, -1, &next_offset,
+ FALSE);
+
+ /*
+ * Put this line.
+ */
+ proto_tree_add_text(nntp_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ offset = next_offset;
+ }
+ }
+}
+
+void
+proto_register_nntp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_nntp_response,
+ { "Response", "nntp.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if NNTP response", HFILL }},
+
+ { &hf_nntp_request,
+ { "Request", "nntp.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if NNTP request", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_nntp,
+ };
+
+ proto_nntp = proto_register_protocol("Network News Transfer Protocol",
+ "NNTP", "nntp");
+ proto_register_field_array(proto_nntp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_nntp(void)
+{
+ dissector_handle_t nntp_handle;
+
+ nntp_handle = create_dissector_handle(dissect_nntp, proto_nntp);
+ dissector_add("tcp.port", TCP_PORT_NNTP, nntp_handle);
+}
diff --git a/epan/dissectors/packet-nt-oui.c b/epan/dissectors/packet-nt-oui.c
new file mode 100644
index 0000000000..5a471943cf
--- /dev/null
+++ b/epan/dissectors/packet-nt-oui.c
@@ -0,0 +1,54 @@
+/* packet-nt-oui.c
+ * Register an LLC dissector table for Nortel's OUI 00:00:0c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include "packet-llc.h"
+#include "oui.h"
+
+static int hf_llc_nortel_pid = -1;
+
+static const value_string nortel_pid_vals[] = {
+ { 0x01a1, "SONMP flatnet hello" },
+ { 0x01a2, "SONMP segment hello" },
+ { 0x01a3, "SONMP bridge hello" },
+ { 0, NULL }
+};
+
+/*
+ * NOTE: there's no dissector here, just registration routines to set
+ * up the dissector table for the Nortel OUI.
+ */
+void
+proto_register_nortel_oui(void)
+{
+ static hf_register_info hf = {
+ &hf_llc_nortel_pid,
+ { "PID", "llc.nortel_pid", FT_UINT16, BASE_HEX,
+ VALS(nortel_pid_vals), 0x0, "", HFILL },
+ };
+
+ llc_add_oui(OUI_NORTEL, "llc.nortel_pid", "Nortel OUI PID", &hf);
+}
diff --git a/epan/dissectors/packet-nt-sonmp.c b/epan/dissectors/packet-nt-sonmp.c
new file mode 100644
index 0000000000..f0c2bebbaa
--- /dev/null
+++ b/epan/dissectors/packet-nt-sonmp.c
@@ -0,0 +1,337 @@
+/* packet-sonmp.c
+* Routines for the disassembly of the "Nortel Networks / SynOptics Network Management Protocol"
+* (c) Copyright Giles Scott <giles.scott1 [AT] btinternet.com>
+*
+* $Id$
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+/* #include "strutil.h" */
+#include "nlpid.h"
+
+/* Although this protocol is propietary it is documented in the SynOptics MIB's
+* So I'm not giving anything away :-)
+* The only thing I have not done is decode the segment identifier;
+* This changes so much depending on whether the chassis supports
+* multi-segment autotopology. As the 5000 is now EOL don't see much point.
+*
+* MIB's s5emt104.mib, s5tcs112.mib, synro179.mib these should be available via
+* http://www.nortelnetworks.com
+*/
+
+
+/* chassis types */
+/* From synro193.mib - SnpxChassisType */
+static value_string sonmp_chassis_val[] =
+{
+ {2, "m3000"},
+ {3, "m3030"},
+ {4, "m2310"},
+ {5, "m2810"},
+ {6, "m2912"},
+ {7, "m2914"},
+ {8, "m271x"},
+ {9, "m2813"},
+ {10, "m2814"},
+ {11, "m2915"},
+ {12, "m5000"},
+ {13, "m2813SA"},
+ {14, "m2814SA"},
+ {15, "m810M"},
+ {16, "m1032x Ethercell"},
+ {17, "5005"},
+ {18, "Alcatel Ethernet workgroup conc"},
+ {20, "m2715SA"},
+ {21, "m2486"},
+ {22, "m28xxx"},
+ {23, "m23xxx"},
+ {24, "5DN000"},
+ {25, "NBayStack"},
+ {26, "m2310x"},
+ {27, "BayStack100 hub"},
+ {28, "M3000 Fast ethernet"},
+ {29, "Xedia"},
+ {31, "28200"},
+ {32, "Centillion-sixSlot"},
+ {33, "Centillion-twelveSlot"},
+ {34, "Centillion-singleSlot"},
+ {35, "BayStack301"},
+ {36, "BayStackTr"},
+ {37, "FVC Multimedia Switch"},
+ {38, "SwitchNode"},
+ {39, "BayStack 302"},
+ {40, "BayStack 350"},
+ {41, "BayStack 150"},
+ {42, "Centillion 50"},
+ {43, "Centillion 50tr"},
+ {44, "BayStack 303-304"},
+ {45, "BayStack 200"},
+ {46, "BayStack 250"},
+ {47, "StackProbe"},
+ {48, "BayStack 450"},
+ {49, "BayStack 303-24T"},
+ {50, "Accelar 1200 L3 switch"},
+ {51, "Accelar 1250 L3 switch"},
+ {52, "Accelar 1100 L3 switch"},
+ {53, "Accelar 1150 L3 switch"},
+ {54, "Accelar 1050 L3 switch"},
+ {55, "Accelar 1051 L3 switch"},
+ {56, "Accelar 8610 L3 switch"},
+ {57, "Accelar 8006"},
+ {58, "Accelar 8010"},
+ {59, "Accelar 8006"},
+ {60, "BayStack 670"},
+ {61, "Accelar 740"},
+ {62, "Accelar 750"},
+ {63, "Accelar 790"},
+ {64, "Business Policy switch 2000"},
+ {65, "Accelar 8110 L2 switch"},
+ {66, "Accelar 8106 L2 switch"},
+ {67, "BayStack 3580"},
+ {68, "Baystack 10 PSU"},
+ {69, "BayStack 420"},
+ {70, "OPTera Metro 1200ESM"},
+ {71, "OPTera 8010co"},
+ {72, "OPTera 8610co L3 switch"},
+ {73, "OPTera 8110co L2 switch"},
+ {74, "OPTera 8003"},
+ {75, "OPTera 8603 L3 switch"},
+ {76, "OPTera 8103 L2 switch"},
+ {77, "Baystack 380 10/100/1000 switch"},
+ {78, "Baystack 470 10/100 switch"},
+ {79, "OPTera Metro 1450ESM"},
+ {80, "OPTera Metro 1400ESM"},
+ {81, "Alteon switch family"},
+ {82, "BayStack 460-24T-PWR"},
+ {83, "OPTera Metro 8010 OPM L2 Switch"},
+ {84, "OPTera Metro 8010co OPM L2 Switch"},
+ {85, "OPTera Metro 8006 OPM L2 Switch"},
+ {86, "OPTera Metro 8003 OPM L2 Switch"},
+ {87, "Alteon 180e"},
+ {88, "Alteon AD3"},
+ {89, "Alteon 184"},
+ {90, "Alteon AD4"},
+ {91, "Passport 1424 L3 switch"},
+ {92, "Passport 1648 L3 switch"},
+ {93, "Passport 1612 L3 switch"},
+ {94, "Passport 1624 L3 switch"},
+ {95, "BayStack 380-24F Fiber 1000 switch"},
+ {96, "BayStack 4700 24T switch"},
+ {97, "BayStack 4700 48T switch"},
+ {98, "BayStack 5510 24-port"},
+ {99, "BayStack 2200 Wireless LAN AP"},
+ {100, "passport RBS 2402 L3 switch"},
+ {101, "Alteon AAS 2424"},
+ {102, "Alteon AAS 2224"},
+ {103, "Alteon AAS 2208"},
+ {104, "Alteon AAS 2216"},
+ {105, "Alteon AAS 3408"},
+ {106, "Alteon AAS 3416"},
+ {0, NULL}
+};
+
+/* from synro179.mib - SnpxBackplaneType */
+static value_string sonmp_backplane_val[] =
+{
+ {1, "Other"},
+ {2, "ethernet"},
+ {3, "ethernet and tokenring"},
+ {4, "ethernet and FDDI"},
+ {5, "ethernet, tokenring and FDDI"},
+ {6, "ethernet and tokenring with redundant power"},
+ {7, "ethernet, tokenring, FDDI with redunadant power"},
+ {8, "token ring"},
+ {9, "ethernet, tokenring and fast ethernet"},
+ {10, "ethernet and fast ethernet"},
+ {11, "ethernet, tokenring, fast ethernet with redunant power"},
+ {12, "ethernet, fast ethernet and gigabit ethernet"},
+ {0, NULL}
+};
+
+static value_string sonmp_nmm_state_val[] =
+{
+ {1, "Topology Change"},
+ {2, "Heartbeat"},
+ {3, "New"},
+ {0, NULL}
+};
+
+
+/* Offsets in SONMP NMM Hello structure. */
+#define SONMP_IP_ADDRESS 0
+#define SONMP_SEGMENT_IDENTIFIER 4
+#define SONMP_CHASSIS_TYPE 7
+#define SONMP_BACKPLANE_TYPE 8
+#define SONMP_NMM_STATE 9
+#define SONMP_NUMBER_OF_LINKS 10
+
+static int proto_sonmp = -1;
+static int hf_sonmp_ip_address = -1;
+/* static int hf_sonmp_segment_identifier = -1; */
+static int hf_sonmp_chassis_type = -1;
+static int hf_sonmp_backplane_type = -1;
+static int hf_sonmp_nmm_state = -1;
+static int hf_sonmp_number_of_links = -1;
+
+static gint ett_sonmp = -1;
+
+
+static void
+dissect_sonmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ char *hello_type;
+ guint32 sonmp_ip_address;
+ guint32 sonmp_segment_identifier = 0; /* actually 3 bytes not 4 */
+ guint8 sonmp_chassis_type;
+ guint8 sonmp_backplane_type;
+ guint8 sonmp_nmm_state;
+ guint8 sonmp_number_of_links;
+
+ proto_tree *sonmp_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SONMP");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ hello_type = "";
+ if (pinfo->dl_dst.type == AT_ETHER) {
+
+ switch (pinfo->dl_dst.data[5]) {
+
+ case 0:
+ hello_type = "Segment ";
+ break;
+
+ case 1:
+ hello_type = "FlatNet ";
+ break;
+ }
+ }
+ col_add_fstr(pinfo->cinfo, COL_INFO, "SONMP - %sHello",
+ hello_type);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_sonmp, tvb, 0, 11,
+ "Nortel Networks / SynOptics Network Management Protocol");
+ sonmp_tree = proto_item_add_subtree(ti, ett_sonmp);
+
+ sonmp_ip_address = tvb_get_letohl(tvb, SONMP_IP_ADDRESS);
+ proto_tree_add_ipv4(sonmp_tree, hf_sonmp_ip_address,
+ tvb, SONMP_IP_ADDRESS, 4, sonmp_ip_address);
+
+ /* there is probably a better way of doing this but i need to get three bytes :-( */
+ sonmp_segment_identifier = tvb_get_guint8(tvb, SONMP_SEGMENT_IDENTIFIER);
+ sonmp_segment_identifier = (sonmp_segment_identifier <<16) + tvb_get_ntohs(tvb, SONMP_SEGMENT_IDENTIFIER +1);
+
+ proto_tree_add_text(sonmp_tree,
+ tvb, SONMP_SEGMENT_IDENTIFIER, 3, "Segment identifier: %06x", sonmp_segment_identifier);
+
+ sonmp_chassis_type = tvb_get_guint8(tvb, SONMP_CHASSIS_TYPE);
+
+ proto_tree_add_uint_format(sonmp_tree, hf_sonmp_chassis_type, tvb, SONMP_CHASSIS_TYPE, 1, sonmp_chassis_type,
+ "Chassis : %s (%u)",
+ val_to_str(sonmp_chassis_type, sonmp_chassis_val, "Unknown"), sonmp_chassis_type);
+
+ sonmp_backplane_type = tvb_get_guint8(tvb, SONMP_BACKPLANE_TYPE);
+ proto_tree_add_uint_format(sonmp_tree, hf_sonmp_backplane_type, tvb, SONMP_BACKPLANE_TYPE, 1,sonmp_backplane_type,
+ "Backplane : %s (%u)",
+ val_to_str(sonmp_backplane_type, sonmp_backplane_val, "Unknown"), sonmp_backplane_type);
+
+
+ sonmp_nmm_state = tvb_get_guint8(tvb, SONMP_NMM_STATE);
+ proto_tree_add_uint_format(sonmp_tree, hf_sonmp_nmm_state,
+ tvb, SONMP_NMM_STATE, 1, sonmp_nmm_state,
+ "State: %s", val_to_str(sonmp_nmm_state, sonmp_nmm_state_val, "Unknown"));
+
+ sonmp_number_of_links = tvb_get_guint8(tvb, SONMP_NUMBER_OF_LINKS);
+ proto_tree_add_item(sonmp_tree, hf_sonmp_number_of_links,
+ tvb, SONMP_NUMBER_OF_LINKS, 1, sonmp_number_of_links);
+ }
+
+
+}
+
+
+
+void
+proto_register_sonmp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_sonmp_ip_address,
+ { "NMM IP address", "sonmp.ipaddress", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "IP address of the agent (NMM)", HFILL }},
+
+ /* { &hf_sonmp_segment_identifier,
+ { "Segment Identifier", "sonmp.segmentident", FT_UINT24, BASE_HEX, NULL, 0x0,
+ "Segment id of the segment from which the agent is sending the topology message", HFILL }},
+ */
+ { &hf_sonmp_chassis_type,
+ { "Chassis type", "sonmp.chassis", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Chassis type of the agent sending the topology message", HFILL }},
+
+ { &hf_sonmp_backplane_type,
+ { "Backplane type", "sonmp.backplane", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Backplane type of the agent sending the topology message", HFILL }},
+
+ { &hf_sonmp_nmm_state,
+ { "NMM state", "sonmp.nmmstate", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Current state of this agent", HFILL }},
+
+ { &hf_sonmp_number_of_links,
+ { "Number of links", "sonmp.numberoflinks", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of interconnect ports", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_sonmp,
+ };
+ proto_sonmp = proto_register_protocol("Nortel SONMP", "SONMP", "sonmp");
+ proto_register_field_array(proto_sonmp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("sonmp", dissect_sonmp, proto_sonmp);
+}
+
+void
+proto_reg_handoff_sonmp(void)
+{
+ dissector_handle_t sonmp_handle;
+
+ sonmp_handle = create_dissector_handle(dissect_sonmp, proto_sonmp);
+
+ dissector_add("llc.nortel_pid", 0x01a1, sonmp_handle); /* flatnet hello */
+ dissector_add("llc.nortel_pid", 0x01a2, sonmp_handle); /* Segment hello */
+ /* not got round to adding this but its really old, so I'm not sure people will see it */
+ /* it uses a different packet format */
+ /* dissector_add("llc.nortel_pid", 0x01a3, sonmp_handle); */ /* Bridge hello */
+}
diff --git a/epan/dissectors/packet-nt-tpcp.c b/epan/dissectors/packet-nt-tpcp.c
new file mode 100644
index 0000000000..71d9e31085
--- /dev/null
+++ b/epan/dissectors/packet-nt-tpcp.c
@@ -0,0 +1,257 @@
+/* packet-tpcp.c
+* Routines for Transparent Proxy Cache Protocol packet disassembly
+* (c) Copyright Giles Scott <giles.scott1 [AT] btinternet.com>
+*
+* $Id$
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h> /* this is for get_hostname and get_udp_port */
+
+#define UDP_PORT_TPCP 3121
+
+/* TPCP version1/2 PDU format */
+typedef struct _tpcppdu_t {
+ guint8 version; /* PDU version 1 */
+ guint8 type; /* PDU type: 1=request, 2=reply, 3=add filter, 4=rem filter */
+ /* Version 2 adds 5=add session 6= remove session */
+ guint16 flags; /* 0x0001: 0=UDP, 1=TCP*/
+ /* 0x0002: 0=NONE, 1=DONT REDIRECT */
+ /* 0x0004: 0=NONE, 1=Xon */
+ /* 0x0008: 0=NONE, 1=Xoff */
+ guint16 id; /* request/response identification or TTL */
+ guint16 cport; /* client UDP or TCP port number */
+ guint32 caddr; /* client IPv4 address */
+ guint32 saddr; /* server IPV4 address */
+ /* tpcp version 2 only*/
+ guint32 vaddr; /* Virtual Server IPv4 address */
+ guint32 rasaddr; /* RAS server IPv4 address */
+ guint32 signature; /* 0x74706370 - tpcp */
+} tpcpdu_t;
+
+
+static const value_string type_vals[] = {
+ { 1, "Request" },
+ { 2, "Reply" },
+ { 3, "Add Filter" },
+ { 4, "Remove Filter" },
+ /* 5 and 6 are for version 2 only */
+ { 5, "Add Session" },
+ { 6, "Remove Session" },
+ { 0, NULL }
+};
+
+/* TPCP Flags */
+#define TF_TPCP_UDPTCP 0x0001
+#define TF_TPCP_DONTREDIRECT 0x0002
+#define TF_TPCP_XON 0x0004
+#define TF_TPCP_XOFF 0x0008
+
+
+/* Version info */
+#define TPCP_VER_1 1
+#define TPCP_VER_2 2
+#define TPCP_VER_1_LENGTH 16
+#define TPCP_VER_2_LENGTH 28
+
+/* things we can do filters on */
+static int hf_tpcp_version = -1;
+static int hf_tpcp_type = -1;
+static int hf_tpcp_flags_tcp = -1;
+static int hf_tpcp_flags_redir = -1;
+static int hf_tpcp_flags_xon = -1;
+static int hf_tpcp_flags_xoff = -1;
+static int hf_tpcp_id = -1;
+static int hf_tpcp_cport = -1;
+static int hf_tpcp_caddr = -1;
+static int hf_tpcp_saddr = -1;
+static int hf_tpcp_vaddr = -1;
+static int hf_tpcp_rasaddr = -1;
+
+static int proto_tpcp = -1;
+
+static gint ett_tpcp = -1;
+static gint ett_tpcp_flags = -1;
+
+
+static void
+dissect_tpcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tpcpdu_t tpcph;
+ proto_tree *tpcp_tree = NULL, *field_tree = NULL;
+ proto_item *ti, *tf;
+ guint8 length = TPCP_VER_1_LENGTH;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPCP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* need to find out which version!! */
+ tpcph.version = tvb_get_guint8(tvb, 0);
+ /* as version 1 and 2 are so similar use the same structure, just don't use as much for version 1*/
+ if (tpcph.version == TPCP_VER_1) {
+ length = TPCP_VER_1_LENGTH;
+ tvb_memcpy(tvb, (guint8 *) &tpcph, 0, length);
+ } else if (tpcph.version == TPCP_VER_2){
+ length = TPCP_VER_2_LENGTH;
+ tvb_memcpy(tvb, (guint8 *) &tpcph, 0, length);
+ }
+
+
+ tpcph.id = g_ntohs(tpcph.id);
+ tpcph.flags = g_ntohs(tpcph.flags);
+ tpcph.cport = g_ntohs(tpcph.cport);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO,"%s id %d CPort %s CIP %s SIP %s",
+ val_to_str(tpcph.type, type_vals, "Unknown"),
+ tpcph.id,
+ get_udp_port(tpcph.cport),
+ ip_to_str((guint8 *)&tpcph.caddr),
+ ip_to_str((guint8 *)&tpcph.saddr));
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_tpcp, tvb, 0, length,
+ "Alteon WebSystems - Transparent Proxy Cache Protocol");
+
+ tpcp_tree = proto_item_add_subtree(ti, ett_tpcp);
+
+ proto_tree_add_item(tpcp_tree, hf_tpcp_version, tvb, 0, 1, tpcph.version);
+
+ proto_tree_add_uint_format(tpcp_tree, hf_tpcp_type, tvb, 1, 1, tpcph.type,
+ "Type: %s (%d)",
+ val_to_str(tpcph.type, type_vals, "Unknown"), tpcph.type);
+
+ /* flags next , i'll do that when I can work out how to do it :-( */
+ tf = proto_tree_add_text(tpcp_tree, tvb, 2, 2, "Flags: 0x%04x",tpcph.flags);
+
+ field_tree = proto_item_add_subtree(tf, ett_tpcp_flags);
+ proto_tree_add_boolean(field_tree, hf_tpcp_flags_tcp, tvb, 2, 2, tpcph.flags);
+ proto_tree_add_boolean(field_tree, hf_tpcp_flags_redir, tvb, 2,2, tpcph.flags);
+ proto_tree_add_boolean(field_tree, hf_tpcp_flags_xon, tvb, 2, 2, tpcph.flags);
+ proto_tree_add_boolean(field_tree, hf_tpcp_flags_xoff, tvb, 2, 2, tpcph.flags);
+
+ proto_tree_add_uint(tpcp_tree, hf_tpcp_id, tvb, 4, 2, tpcph.id);
+
+ proto_tree_add_uint_format(tpcp_tree, hf_tpcp_cport, tvb, 6, 2, tpcph.cport,
+ "Client Source port: %s", get_udp_port(tpcph.cport));
+
+ proto_tree_add_ipv4(tpcp_tree, hf_tpcp_caddr, tvb, 8, 4, tpcph.caddr);
+
+ proto_tree_add_ipv4(tpcp_tree, hf_tpcp_saddr, tvb, 12, 4, tpcph.saddr);
+
+ if (tpcph.version == TPCP_VER_2) {
+ proto_tree_add_ipv4(tpcp_tree, hf_tpcp_vaddr, tvb, 16, 4, tpcph.vaddr);
+ proto_tree_add_ipv4(tpcp_tree, hf_tpcp_rasaddr, tvb, 20, 4, tpcph.rasaddr);
+ proto_tree_add_text(tpcp_tree, tvb, 24, 4, "Signature: %u", tpcph.signature);
+ }
+
+ }
+}
+
+void
+proto_register_tpcp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tpcp_version,
+ { "Version", "tpcp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "TPCP version", HFILL }},
+
+ { &hf_tpcp_type,
+ { "Type", "tpcp.type", FT_UINT8, BASE_DEC,NULL, 0x0,
+ "PDU type", HFILL }},
+
+ { &hf_tpcp_flags_tcp,
+ { "UDP/TCP", "tpcp.flags.tcp", FT_BOOLEAN, 8, TFS(&flags_set_truth), TF_TPCP_UDPTCP,
+ "Protocol type", HFILL }},
+
+ { &hf_tpcp_flags_redir,
+ { "No Redirect", "tpcp.flags.redir", FT_BOOLEAN, 8, TFS(&flags_set_truth), TF_TPCP_DONTREDIRECT,
+ "Don't redirect client", HFILL }},
+
+ { &hf_tpcp_flags_xon,
+ { "XON", "tpcp.flags.xon", FT_BOOLEAN, 8, TFS(&flags_set_truth), TF_TPCP_XON,
+ "", HFILL }},
+
+ { &hf_tpcp_flags_xoff,
+ { "XOFF", "tpcp.flags.xoff", FT_BOOLEAN, 8, TFS(&flags_set_truth), TF_TPCP_XOFF,
+ "", HFILL }},
+
+ { &hf_tpcp_id,
+ { "Client indent", "tpcp.cid", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tpcp_cport,
+ { "Client Source Port", "tpcp.cport", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tpcp_caddr,
+ { "Client Source IP address", "tpcp.caddr", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tpcp_saddr,
+ { "Server IP address", "tpcp.saddr", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tpcp_vaddr,
+ { "Virtual Server IP address", "tpcp.vaddr", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tpcp_rasaddr,
+ { "RAS server IP address", "tpcp.rasaddr", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ };
+
+
+ static gint *ett[] = {
+ &ett_tpcp,
+ &ett_tpcp_flags,
+ };
+
+ proto_tpcp = proto_register_protocol("Alteon - Transparent Proxy Cache Protocol",
+ "TPCP", "tpcp");
+ proto_register_field_array(proto_tpcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_tpcp(void)
+{
+ dissector_handle_t tpcp_handle;
+
+ tpcp_handle = create_dissector_handle(dissect_tpcp, proto_tpcp);
+ dissector_add("udp.port", UDP_PORT_TPCP, tpcp_handle);
+}
diff --git a/epan/dissectors/packet-ntlmssp.c b/epan/dissectors/packet-ntlmssp.c
new file mode 100644
index 0000000000..1d3cbcca20
--- /dev/null
+++ b/epan/dissectors/packet-ntlmssp.c
@@ -0,0 +1,1612 @@
+/* packet-ntlmssp.c
+ * Routines for NTLM Secure Service Provider
+ * Devin Heitmueller <dheitmueller@netilla.com>
+ * Copyright 2003, Tim Potter <tpot@samba.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include "packet-smb-common.h"
+#include "asn1.h" /* XXX - needed for subid_t */
+#include "packet-gssapi.h"
+#include "packet-frame.h"
+#include "prefs.h"
+#include "crypt-rc4.h"
+#include "crypt-md4.h"
+#include "crypt-des.h"
+#include "packet-dcerpc.h"
+
+/* Message types */
+
+#define NTLMSSP_NEGOTIATE 1
+#define NTLMSSP_CHALLENGE 2
+#define NTLMSSP_AUTH 3
+#define NTLMSSP_UNKNOWN 4
+
+static const value_string ntlmssp_message_types[] = {
+ { NTLMSSP_NEGOTIATE, "NTLMSSP_NEGOTIATE" },
+ { NTLMSSP_CHALLENGE, "NTLMSSP_CHALLENGE" },
+ { NTLMSSP_AUTH, "NTLMSSP_AUTH" },
+ { NTLMSSP_UNKNOWN, "NTLMSSP_UNKNOWN" },
+ { 0, NULL }
+};
+
+/*
+ * NTLMSSP negotiation flags
+ * Taken from Samba
+ */
+#define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
+#define NTLMSSP_NEGOTIATE_OEM 0x00000002
+#define NTLMSSP_REQUEST_TARGET 0x00000004
+#define NTLMSSP_NEGOTIATE_00000008 0x00000008
+#define NTLMSSP_NEGOTIATE_SIGN 0x00000010
+#define NTLMSSP_NEGOTIATE_SEAL 0x00000020
+#define NTLMSSP_NEGOTIATE_DATAGRAM_STYLE 0x00000040
+#define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
+#define NTLMSSP_NEGOTIATE_NETWARE 0x00000100
+#define NTLMSSP_NEGOTIATE_NTLM 0x00000200
+#define NTLMSSP_NEGOTIATE_00000400 0x00000400
+#define NTLMSSP_NEGOTIATE_00000800 0x00000800
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x00001000
+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
+#define NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL 0x00004000
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
+#define NTLMSSP_CHAL_INIT_RESPONSE 0x00010000
+#define NTLMSSP_CHAL_ACCEPT_RESPONSE 0x00020000
+#define NTLMSSP_CHAL_NON_NT_SESSION_KEY 0x00040000
+#define NTLMSSP_NEGOTIATE_NTLM2 0x00080000
+#define NTLMSSP_NEGOTIATE_00100000 0x00100000
+#define NTLMSSP_NEGOTIATE_00200000 0x00200000
+#define NTLMSSP_NEGOTIATE_00400000 0x00400000
+#define NTLMSSP_CHAL_TARGET_INFO 0x00800000
+#define NTLMSSP_NEGOTIATE_01000000 0x01000000
+#define NTLMSSP_NEGOTIATE_02000000 0x02000000
+#define NTLMSSP_NEGOTIATE_04000000 0x04000000
+#define NTLMSSP_NEGOTIATE_08000000 0x08000000
+#define NTLMSSP_NEGOTIATE_10000000 0x10000000
+#define NTLMSSP_NEGOTIATE_128 0x20000000
+#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000
+#define NTLMSSP_NEGOTIATE_80000000 0x80000000
+
+static int proto_ntlmssp = -1;
+static int hf_ntlmssp = -1;
+static int hf_ntlmssp_auth = -1;
+static int hf_ntlmssp_message_type = -1;
+static int hf_ntlmssp_negotiate_flags = -1;
+static int hf_ntlmssp_negotiate_flags_01 = -1;
+static int hf_ntlmssp_negotiate_flags_02 = -1;
+static int hf_ntlmssp_negotiate_flags_04 = -1;
+static int hf_ntlmssp_negotiate_flags_08 = -1;
+static int hf_ntlmssp_negotiate_flags_10 = -1;
+static int hf_ntlmssp_negotiate_flags_20 = -1;
+static int hf_ntlmssp_negotiate_flags_40 = -1;
+static int hf_ntlmssp_negotiate_flags_80 = -1;
+static int hf_ntlmssp_negotiate_flags_100 = -1;
+static int hf_ntlmssp_negotiate_flags_200 = -1;
+static int hf_ntlmssp_negotiate_flags_400 = -1;
+static int hf_ntlmssp_negotiate_flags_800 = -1;
+static int hf_ntlmssp_negotiate_flags_1000 = -1;
+static int hf_ntlmssp_negotiate_flags_2000 = -1;
+static int hf_ntlmssp_negotiate_flags_4000 = -1;
+static int hf_ntlmssp_negotiate_flags_8000 = -1;
+static int hf_ntlmssp_negotiate_flags_10000 = -1;
+static int hf_ntlmssp_negotiate_flags_20000 = -1;
+static int hf_ntlmssp_negotiate_flags_40000 = -1;
+static int hf_ntlmssp_negotiate_flags_80000 = -1;
+static int hf_ntlmssp_negotiate_flags_100000 = -1;
+static int hf_ntlmssp_negotiate_flags_200000 = -1;
+static int hf_ntlmssp_negotiate_flags_400000 = -1;
+static int hf_ntlmssp_negotiate_flags_800000 = -1;
+static int hf_ntlmssp_negotiate_flags_1000000 = -1;
+static int hf_ntlmssp_negotiate_flags_2000000 = -1;
+static int hf_ntlmssp_negotiate_flags_4000000 = -1;
+static int hf_ntlmssp_negotiate_flags_8000000 = -1;
+static int hf_ntlmssp_negotiate_flags_10000000 = -1;
+static int hf_ntlmssp_negotiate_flags_20000000 = -1;
+static int hf_ntlmssp_negotiate_flags_40000000 = -1;
+static int hf_ntlmssp_negotiate_flags_80000000 = -1;
+static int hf_ntlmssp_negotiate_workstation_strlen = -1;
+static int hf_ntlmssp_negotiate_workstation_maxlen = -1;
+static int hf_ntlmssp_negotiate_workstation_buffer = -1;
+static int hf_ntlmssp_negotiate_workstation = -1;
+static int hf_ntlmssp_negotiate_domain_strlen = -1;
+static int hf_ntlmssp_negotiate_domain_maxlen = -1;
+static int hf_ntlmssp_negotiate_domain_buffer = -1;
+static int hf_ntlmssp_negotiate_domain = -1;
+static int hf_ntlmssp_ntlm_challenge = -1;
+static int hf_ntlmssp_reserved = -1;
+static int hf_ntlmssp_challenge_domain = -1;
+static int hf_ntlmssp_auth_username = -1;
+static int hf_ntlmssp_auth_domain = -1;
+static int hf_ntlmssp_auth_hostname = -1;
+static int hf_ntlmssp_auth_lmresponse = -1;
+static int hf_ntlmssp_auth_ntresponse = -1;
+static int hf_ntlmssp_auth_sesskey = -1;
+static int hf_ntlmssp_string_len = -1;
+static int hf_ntlmssp_string_maxlen = -1;
+static int hf_ntlmssp_string_offset = -1;
+static int hf_ntlmssp_blob_len = -1;
+static int hf_ntlmssp_blob_maxlen = -1;
+static int hf_ntlmssp_blob_offset = -1;
+static int hf_ntlmssp_address_list = -1;
+static int hf_ntlmssp_address_list_len = -1;
+static int hf_ntlmssp_address_list_maxlen = -1;
+static int hf_ntlmssp_address_list_offset = -1;
+static int hf_ntlmssp_address_list_server_nb = -1;
+static int hf_ntlmssp_address_list_domain_nb = -1;
+static int hf_ntlmssp_address_list_server_dns = -1;
+static int hf_ntlmssp_address_list_domain_dns = -1;
+static int hf_ntlmssp_address_list_terminator = -1;
+static int hf_ntlmssp_address_list_item_type = -1;
+static int hf_ntlmssp_address_list_item_len = -1;
+static int hf_ntlmssp_address_list_item_content = -1;
+static int hf_ntlmssp_verf = -1;
+static int hf_ntlmssp_verf_vers = -1;
+static int hf_ntlmssp_verf_body = -1;
+static int hf_ntlmssp_verf_unknown1 = -1;
+static int hf_ntlmssp_verf_crc32 = -1;
+static int hf_ntlmssp_verf_sequence = -1;
+static int hf_ntlmssp_decrypted_payload = -1;
+
+static gint ett_ntlmssp = -1;
+static gint ett_ntlmssp_negotiate_flags = -1;
+static gint ett_ntlmssp_string = -1;
+static gint ett_ntlmssp_blob = -1;
+static gint ett_ntlmssp_address_list = -1;
+static gint ett_ntlmssp_address_list_item = -1;
+
+/* Configuration variables */
+static char *nt_password = NULL;
+
+#define MAX_BLOB_SIZE 256
+typedef struct _ntlmssp_blob {
+ guint16 length;
+ guint8 contents[MAX_BLOB_SIZE];
+} ntlmssp_blob;
+
+/* Used in the conversation function */
+typedef struct _ntlmssp_info {
+ guint32 flags;
+ rc4_state_struct rc4_state_peer1;
+ rc4_state_struct rc4_state_peer2;
+ guint32 peer1_dest_port;
+ int rc4_state_initialized;
+ ntlmssp_blob ntlm_response;
+ ntlmssp_blob lm_response;
+} ntlmssp_info;
+
+/*
+ * GMemChunk from which ntlmssp_info structures are allocated.
+ */
+static GMemChunk *ntlmssp_info_chunk;
+static int ntlmssp_info_count = 10;
+
+/* If this struct exists in the payload_decrypt, then we have already
+ decrypted it once */
+typedef struct _ntlmssp_packet_info {
+ guint32 flags;
+ guint8 *decrypted_payload;
+ guint8 verifier[16];
+ gboolean payload_decrypted;
+ gboolean verifier_decrypted;
+} ntlmssp_packet_info;
+
+/*
+ * GMemChunk from which ntlmssp_packet_info structures are allocated.
+ */
+static GMemChunk *ntlmssp_packet_info_chunk;
+static int ntlmssp_packet_info_count = 10;
+
+/*
+ * GSlist of decrypted payloads.
+ */
+static GSList *decrypted_payloads;
+
+/*
+ Generate a challenge response, given an eight byte challenge and
+ either the NT or the Lan Manager password hash (16 bytes).
+ Returns output in response, which is expected to be 24 bytes.
+*/
+static int ntlmssp_generate_challenge_response(guint8 *response,
+ const guint8 *passhash,
+ const guint8 *challenge)
+{
+ guint8 pw21[21]; /* Password hash padded to 21 bytes */
+
+ memset(pw21, 0x0, sizeof(pw21));
+ memcpy(pw21, passhash, 16);
+
+ memset(response, 0, 24);
+
+ crypt_des_ecb(response, challenge, pw21, 1);
+ crypt_des_ecb(response + 8, challenge, pw21 + 7, 1);
+ crypt_des_ecb(response + 16, challenge, pw21 + 14, 1);
+
+ return 1;
+}
+
+/* Create an NTLMSSP version 1 key.
+ * password points to the ANSI password to encrypt, challenge points to
+ * the 8 octet challenge string, key128 will do a 128 bit key if set to 1,
+ * otherwise it will do a 40 bit key. The result is stored in
+ * sspkey (expected to be 16 octets)
+ */
+static void
+create_ntlmssp_v1_key(const char *nt_password, const guint8 *challenge,
+ int use_key_128, guint8 *sspkey)
+{
+ unsigned char lm_password_upper[16];
+ unsigned char lm_password_hash[16];
+ guint8 lm_challenge_response[24];
+ guint8 rc4key[24];
+ guint8 pw21[21]; /* Password hash padded to 21 bytes */
+ size_t password_len;
+ unsigned int i;
+ unsigned char lmhash_key[] =
+ {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
+
+ memset(lm_password_upper, 0, sizeof(lm_password_upper));
+
+ /* Create a Lan Manager hash of the input password */
+ if (nt_password[0] != '\0') {
+ password_len = strlen(nt_password);
+ /* Truncate password if too long */
+ if (password_len > 16)
+ password_len = 16;
+ for (i = 0; i < password_len; i++) {
+ lm_password_upper[i] = toupper(nt_password[i]);
+ }
+ }
+
+ crypt_des_ecb(lm_password_hash, lmhash_key, lm_password_upper, 1);
+ crypt_des_ecb(lm_password_hash+8, lmhash_key, lm_password_upper+7, 1);
+
+ /* Generate the LanMan Challenge Response */
+ ntlmssp_generate_challenge_response(lm_challenge_response,
+ lm_password_hash, challenge);
+
+ /* Generate the NTLMSSP-v1 RC4 Key.
+ * The RC4 key is derived from the Lan Manager Hash.
+ * See lkcl "DCE/RPC over SMB" page 254 for the algorithm.
+ */
+ memset(pw21, 0xBD, sizeof(pw21));
+ memcpy(pw21, lm_password_hash, sizeof(lm_password_hash));
+
+ /* Only the first eight bytes of challenge_response is used */
+ crypt_des_ecb(rc4key, lm_challenge_response, pw21, 1);
+ crypt_des_ecb(rc4key + 8, lm_challenge_response, pw21 + 7, 1);
+ crypt_des_ecb(rc4key + 16, lm_challenge_response, pw21 + 14, 1);
+
+ /* Create the SSP Key */
+ memset(sspkey, 0, sizeof(sspkey));
+ if (use_key_128) {
+ /* Create 128 bit key */
+ memcpy(sspkey, rc4key, 16);
+ }
+ else {
+ /* Create 40 bit key */
+ memcpy(sspkey, rc4key, 5);
+ sspkey[5]=0xe5;
+ sspkey[6]=0x38;
+ sspkey[7]=0xb0;
+ }
+ return;
+}
+
+/* dissect a string - header area contains:
+ two byte len
+ two byte maxlen
+ four byte offset of string in data area
+ The function returns the offset at the end of the string header,
+ but the 'end' parameter returns the offset of the end of the string itself
+ The 'start' parameter returns the offset of the beginning of the string
+*/
+static int
+dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
+ proto_tree *ntlmssp_tree,
+ gboolean unicode_strings,
+ int string_hf, int *start, int *end)
+{
+ proto_tree *tree = NULL;
+ proto_item *tf = NULL;
+ gint16 string_length = tvb_get_letohs(tvb, offset);
+ gint16 string_maxlen = tvb_get_letohs(tvb, offset+2);
+ gint32 string_offset = tvb_get_letohl(tvb, offset+4);
+ const char *string_text = NULL;
+ int result_length;
+ guint16 bc;
+
+ *start = (string_offset > offset+8 ? string_offset : offset+8);
+ if (0 == string_length) {
+ *end = *start;
+ if (ntlmssp_tree)
+ proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
+ offset, 8, "NULL");
+ return offset+8;
+ }
+
+ bc = result_length = string_length;
+ string_text = get_unicode_or_ascii_string(tvb, &string_offset,
+ unicode_strings, &result_length,
+ FALSE, TRUE, &bc);
+
+ if (ntlmssp_tree) {
+ tf = proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
+ string_offset, result_length, string_text);
+ tree = proto_item_add_subtree(tf, ett_ntlmssp_string);
+ }
+ proto_tree_add_uint(tree, hf_ntlmssp_string_len,
+ tvb, offset, 2, string_length);
+ offset += 2;
+ proto_tree_add_uint(tree, hf_ntlmssp_string_maxlen,
+ tvb, offset, 2, string_maxlen);
+ offset += 2;
+ proto_tree_add_uint(tree, hf_ntlmssp_string_offset,
+ tvb, offset, 4, string_offset);
+ offset += 4;
+
+ *end = string_offset + string_length;
+ return offset;
+}
+
+/* dissect a generic blob - header area contains:
+ two byte len
+ two byte maxlen
+ four byte offset of blob in data area
+ The function returns the offset at the end of the blob header,
+ but the 'end' parameter returns the offset of the end of the blob itself
+*/
+static int
+dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
+ proto_tree *ntlmssp_tree,
+ int blob_hf, int *end, ntlmssp_blob *result)
+{
+ proto_item *tf = NULL;
+ proto_tree *tree = NULL;
+ guint16 blob_length = tvb_get_letohs(tvb, offset);
+ guint16 blob_maxlen = tvb_get_letohs(tvb, offset+2);
+ guint32 blob_offset = tvb_get_letohl(tvb, offset+4);
+
+ if (0 == blob_length) {
+ *end = (blob_offset > ((guint)offset)+8 ? blob_offset : ((guint)offset)+8);
+ if (ntlmssp_tree)
+ proto_tree_add_text(ntlmssp_tree, tvb, offset, 8, "%s: Empty",
+ proto_registrar_get_name(blob_hf));
+ return offset+8;
+ }
+
+ if (ntlmssp_tree) {
+ tf = proto_tree_add_item (ntlmssp_tree, blob_hf, tvb,
+ blob_offset, blob_length, FALSE);
+ tree = proto_item_add_subtree(tf, ett_ntlmssp_blob);
+ }
+ proto_tree_add_uint(tree, hf_ntlmssp_blob_len,
+ tvb, offset, 2, blob_length);
+ offset += 2;
+ proto_tree_add_uint(tree, hf_ntlmssp_blob_maxlen,
+ tvb, offset, 2, blob_maxlen);
+ offset += 2;
+ proto_tree_add_uint(tree, hf_ntlmssp_blob_offset,
+ tvb, offset, 4, blob_offset);
+ offset += 4;
+
+ *end = blob_offset + blob_length;
+
+ if (result != NULL) {
+ result->length = blob_length;
+ memset(result->contents, 0, MAX_BLOB_SIZE);
+ if (blob_length < MAX_BLOB_SIZE)
+ tvb_memcpy(tvb, result->contents, blob_offset, blob_length);
+ }
+
+ /* If we are dissecting the NTLM response and it is a NTLMv2
+ response call the appropriate dissector. */
+
+ if (blob_hf == hf_ntlmssp_auth_ntresponse && blob_length > 24)
+ dissect_ntlmv2_response(tvb, tree, blob_offset, blob_length);
+
+ return offset;
+}
+
+static int
+dissect_ntlmssp_negotiate_flags (tvbuff_t *tvb, int offset,
+ proto_tree *ntlmssp_tree,
+ guint32 negotiate_flags)
+{
+ proto_tree *negotiate_flags_tree = NULL;
+ proto_item *tf = NULL;
+
+ if (ntlmssp_tree) {
+ tf = proto_tree_add_uint (ntlmssp_tree,
+ hf_ntlmssp_negotiate_flags,
+ tvb, offset, 4, negotiate_flags);
+ negotiate_flags_tree = proto_item_add_subtree (tf, ett_ntlmssp_negotiate_flags);
+ }
+
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_80000000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_40000000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_20000000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_10000000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_8000000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_4000000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_2000000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_1000000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_800000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_400000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_200000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_100000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_80000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_40000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_20000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_10000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_8000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_4000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_2000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_1000,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_800,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_400,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_200,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_100,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_80,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_40,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_20,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_10,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_08,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_04,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_02,
+ tvb, offset, 4, negotiate_flags);
+ proto_tree_add_boolean (negotiate_flags_tree,
+ hf_ntlmssp_negotiate_flags_01,
+ tvb, offset, 4, negotiate_flags);
+
+ return (offset + 4);
+}
+
+
+static int
+dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree)
+{
+ guint32 negotiate_flags;
+ int start;
+ int workstation_end;
+ int domain_end;
+
+ /* NTLMSSP Negotiate Flags */
+ negotiate_flags = tvb_get_letohl (tvb, offset);
+ offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
+ negotiate_flags);
+
+ offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
+ hf_ntlmssp_negotiate_domain,
+ &start, &workstation_end);
+ offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
+ hf_ntlmssp_negotiate_workstation,
+ &start, &domain_end);
+
+ /* XXX - two blobs after this one, sometimes? */
+
+ return MAX(workstation_end, domain_end);
+}
+
+
+static int
+dissect_ntlmssp_address_list (tvbuff_t *tvb, int offset,
+ proto_tree *ntlmssp_tree,
+ int *end)
+{
+ guint16 list_length = tvb_get_letohs(tvb, offset);
+ guint16 list_maxlen = tvb_get_letohs(tvb, offset+2);
+ guint32 list_offset = tvb_get_letohl(tvb, offset+4);
+ guint16 item_type, item_length;
+ guint32 item_offset;
+ proto_item *tf = NULL;
+ proto_tree *tree = NULL;
+ proto_item *addr_tf = NULL;
+ proto_tree *addr_tree = NULL;
+
+ /* the address list is just a blob */
+ if (0 == list_length) {
+ *end = (list_offset > ((guint)offset)+8 ? list_offset : ((guint)offset)+8);
+ if (ntlmssp_tree)
+ proto_tree_add_text(ntlmssp_tree, tvb, offset, 8,
+ "Address List: Empty");
+ return offset+8;
+ }
+
+ if (ntlmssp_tree) {
+ tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_address_list, tvb,
+ list_offset, list_length, FALSE);
+ tree = proto_item_add_subtree(tf, ett_ntlmssp_address_list);
+ }
+ proto_tree_add_uint(tree, hf_ntlmssp_address_list_len,
+ tvb, offset, 2, list_length);
+ offset += 2;
+ proto_tree_add_uint(tree, hf_ntlmssp_address_list_maxlen,
+ tvb, offset, 2, list_maxlen);
+ offset += 2;
+ proto_tree_add_uint(tree, hf_ntlmssp_address_list_offset,
+ tvb, offset, 4, list_offset);
+ offset += 4;
+
+ /* Now enumerate through the individual items in the list */
+ item_offset = list_offset;
+
+ while (item_offset < (list_offset + list_length)) {
+ const char *text=NULL;
+ guint32 content_offset;
+ guint16 content_length;
+ guint32 type_offset;
+ guint32 len_offset;
+
+ /* Content type */
+ type_offset = item_offset;
+ item_type = tvb_get_letohs(tvb, type_offset);
+
+ /* Content length */
+ len_offset = type_offset + 2;
+ content_length = tvb_get_letohs(tvb, len_offset);
+
+ /* Content value */
+ content_offset = len_offset + 2;
+ item_length = content_length + 4;
+
+ /* Strings are always in unicode regardless of the negotiated
+ string type. */
+ if (content_length > 0) {
+ guint16 bc;
+ int result_length;
+ int item_offset_int;
+
+ item_offset_int = content_offset;
+ bc = content_length;
+ text = get_unicode_or_ascii_string(tvb, &item_offset_int,
+ TRUE, &result_length,
+ FALSE, FALSE, &bc);
+ }
+
+ if (!text) text = ""; /* Make sure we don't blow up below */
+
+ switch(item_type) {
+ case NTLM_NAME_NB_HOST:
+ addr_tf = proto_tree_add_string(tree, hf_ntlmssp_address_list_server_nb,
+ tvb, item_offset, item_length, text);
+ break;
+ case NTLM_NAME_NB_DOMAIN:
+ addr_tf = proto_tree_add_string(tree, hf_ntlmssp_address_list_domain_nb,
+ tvb, item_offset, item_length, text);
+ break;
+ case NTLM_NAME_DNS_HOST:
+ addr_tf = proto_tree_add_string(tree, hf_ntlmssp_address_list_server_dns,
+ tvb, item_offset, item_length, text);
+ break;
+ case NTLM_NAME_DNS_DOMAIN:
+ addr_tf = proto_tree_add_string(tree, hf_ntlmssp_address_list_domain_dns,
+ tvb, item_offset, item_length, text);
+ break;
+ case NTLM_NAME_END:
+ addr_tf = proto_tree_add_item(tree, hf_ntlmssp_address_list_terminator,
+ tvb, item_offset, item_length, TRUE);
+ }
+
+ /* Now show the actual bytes that made up the summary line */
+ addr_tree = proto_item_add_subtree (addr_tf,
+ ett_ntlmssp_address_list_item);
+ proto_tree_add_item (addr_tree, hf_ntlmssp_address_list_item_type,
+ tvb, type_offset, 2, TRUE);
+ proto_tree_add_item (addr_tree, hf_ntlmssp_address_list_item_len,
+ tvb, len_offset, 2, TRUE);
+ if (content_length > 0) {
+ proto_tree_add_string(addr_tree, hf_ntlmssp_address_list_item_content,
+ tvb, content_offset, content_length, text);
+ }
+
+ item_offset += item_length;
+ }
+
+ *end = list_offset + list_length;
+ return offset;
+}
+
+static int
+dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
+ proto_tree *ntlmssp_tree)
+{
+ guint32 negotiate_flags;
+ int item_start, item_end;
+ int data_start, data_end;
+ ntlmssp_info *conv_ntlmssp_info;
+ conversation_t *conversation;
+ gboolean unicode_strings = FALSE;
+ guint8 challenge[8];
+ guint8 sspkey[16]; /* NTLMSSP cipher key */
+ guint8 ssp_key_len; /* Either 8 or 16 (40 bit or 128) */
+
+ /* need to find unicode flag */
+ negotiate_flags = tvb_get_letohl (tvb, offset+8);
+ if (negotiate_flags & NTLMSSP_NEGOTIATE_UNICODE)
+ unicode_strings = TRUE;
+
+ /* Domain name */
+ offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, unicode_strings,
+ hf_ntlmssp_challenge_domain,
+ &item_start, &item_end);
+ data_start = item_start;
+ data_end = item_end;
+
+ /* NTLMSSP Negotiate Flags */
+ offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
+ negotiate_flags);
+
+ /* NTLMSSP NT Lan Manager Challenge */
+ proto_tree_add_item (ntlmssp_tree,
+ hf_ntlmssp_ntlm_challenge,
+ tvb, offset, 8, FALSE);
+
+ /*
+ * Store the flags and the RC4 state information with the conversation,
+ * as they're needed in order to dissect subsequent messages.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (!conversation) { /* Create one */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+
+ if (!conversation_get_proto_data(conversation, proto_ntlmssp)) {
+ conv_ntlmssp_info = g_mem_chunk_alloc(ntlmssp_info_chunk);
+ /* Insert the flags into the conversation */
+ conv_ntlmssp_info->flags = negotiate_flags;
+ /* Insert the RC4 state information into the conversation */
+ tvb_memcpy(tvb, challenge, offset, 8);
+
+ /* Between the challenge and the user provided password, we can build the
+ NTLMSSP key and initialize the cipher */
+ if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_128) {
+ create_ntlmssp_v1_key(nt_password, challenge, 1, sspkey);
+ ssp_key_len = 16;
+ }
+ else {
+ create_ntlmssp_v1_key(nt_password, challenge, 0, sspkey);
+ ssp_key_len = 8;
+ }
+ crypt_rc4_init(&conv_ntlmssp_info->rc4_state_peer1, sspkey, ssp_key_len);
+ crypt_rc4_init(&conv_ntlmssp_info->rc4_state_peer2, sspkey, ssp_key_len);
+ conv_ntlmssp_info->peer1_dest_port = pinfo->destport;
+ conv_ntlmssp_info->rc4_state_initialized = 1;
+
+ conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
+ }
+ offset += 8;
+
+ /* Reserved (function not completely known) */
+ /* XXX - SSP key? */
+ proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
+ tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /*
+ * The presence or absence of this field is not obviously correlated
+ * with any flags in the previous NEGOTIATE message or in this
+ * message (other than the "Workstation Supplied" and "Domain
+ * Supplied" flags in the NEGOTIATE message, at least in the capture
+ * I've seen - but those also correlate with the presence of workstation
+ * and domain name fields, so it doesn't seem to make sense that they
+ * actually *indicate* whether the subsequent CHALLENGE has an
+ * address list).
+ */
+ if (offset < data_start) {
+ offset = dissect_ntlmssp_address_list(tvb, offset, ntlmssp_tree, &item_end);
+ data_end = MAX(data_end, item_end);
+ }
+
+ return MAX(offset, data_end);
+}
+
+static int
+dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
+ proto_tree *ntlmssp_tree)
+{
+ int item_start, item_end;
+ int data_start, data_end = 0;
+ guint32 negotiate_flags;
+ gboolean unicode_strings = FALSE;
+ ntlmssp_info *conv_ntlmssp_info;
+ conversation_t *conversation;
+
+ /*
+ * Get flag info from the original negotiate message, if any.
+ * This is because the flag information is sometimes missing from
+ * the AUTHENTICATE message, so we can't figure out whether
+ * strings are Unicode or not by looking at *our* flags.
+ */
+ conv_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
+ if (conv_ntlmssp_info == NULL) {
+ /*
+ * There isn't any. Is there any from this conversation? If so,
+ * it means this is the first time we've dissected this frame, so
+ * we should give it flag info.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (conversation != NULL) {
+ conv_ntlmssp_info = conversation_get_proto_data(conversation, proto_ntlmssp);
+ if (conv_ntlmssp_info != NULL) {
+ /*
+ * We have flag info; attach it to the frame.
+ */
+ p_add_proto_data(pinfo->fd, proto_ntlmssp, conv_ntlmssp_info);
+ }
+ }
+ }
+ if (conv_ntlmssp_info != NULL) {
+ if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_UNICODE)
+ unicode_strings = TRUE;
+ }
+
+ /*
+ * Sometimes the session key and flags are missing.
+ * Sometimes the session key is present but the flags are missing.
+ * Sometimes they're both present.
+ *
+ * This does not correlate with any flags in the previous CHALLENGE
+ * message, and only correlates with "Negotiate Unicode", "Workstation
+ * Supplied", and "Domain Supplied" in the NEGOTIATE message - but
+ * those don't make sense as flags to use to determine this.
+ *
+ * So we check all of the descriptors to figure out where the data
+ * area begins, and if the session key or the flags would be in the
+ * middle of the data area, we assume the field in question is
+ * missing.
+ */
+
+ /* Lan Manager response */
+ data_start = tvb_get_letohl(tvb, offset+4);
+ offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
+ hf_ntlmssp_auth_lmresponse,
+ &item_end,
+ conv_ntlmssp_info == NULL ? NULL :
+ &conv_ntlmssp_info->lm_response);
+ data_end = MAX(data_end, item_end);
+
+ /* NTLM response */
+ item_start = tvb_get_letohl(tvb, offset+4);
+ offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
+ hf_ntlmssp_auth_ntresponse,
+ &item_end,
+ conv_ntlmssp_info == NULL ? NULL :
+ &conv_ntlmssp_info->ntlm_response);
+ data_start = MIN(data_start, item_start);
+ data_end = MAX(data_end, item_end);
+
+ /* domain name */
+ item_start = tvb_get_letohl(tvb, offset+4);
+ offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
+ unicode_strings,
+ hf_ntlmssp_auth_domain,
+ &item_start, &item_end);
+ data_start = MIN(data_start, item_start);
+ data_end = MAX(data_end, item_end);
+
+ /* user name */
+ item_start = tvb_get_letohl(tvb, offset+4);
+ offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
+ unicode_strings,
+ hf_ntlmssp_auth_username,
+ &item_start, &item_end);
+ data_start = MIN(data_start, item_start);
+ data_end = MAX(data_end, item_end);
+
+ /* hostname */
+ item_start = tvb_get_letohl(tvb, offset+4);
+ offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
+ unicode_strings,
+ hf_ntlmssp_auth_hostname,
+ &item_start, &item_end);
+ data_start = MIN(data_start, item_start);
+ data_end = MAX(data_end, item_end);
+
+ if (offset < data_start) {
+ /* Session Key */
+ offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
+ hf_ntlmssp_auth_sesskey,
+ &item_end, NULL);
+ data_end = MAX(data_end, item_end);
+ }
+
+ if (offset < data_start) {
+ /* NTLMSSP Negotiate Flags */
+ negotiate_flags = tvb_get_letohl (tvb, offset);
+ offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
+ negotiate_flags);
+ }
+
+ return MAX(offset, data_end);
+}
+
+static void
+dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 ntlmssp_message_type;
+ volatile int offset = 0;
+ proto_tree *volatile ntlmssp_tree = NULL;
+ proto_item *tf = NULL;
+
+ /* Setup a new tree for the NTLMSSP payload */
+ if (tree) {
+ tf = proto_tree_add_item (tree,
+ hf_ntlmssp,
+ tvb, offset, -1, FALSE);
+
+ ntlmssp_tree = proto_item_add_subtree (tf,
+ ett_ntlmssp);
+ }
+
+ /*
+ * Catch the ReportedBoundsError exception; the stuff we've been
+ * handed doesn't necessarily run to the end of the packet, it's
+ * an item inside a packet, so if it happens to be malformed (or
+ * we, or a dissector we call, has a bug), so that an exception
+ * is thrown, we want to report the error, but return and let
+ * our caller dissect the rest of the packet.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing more
+ * in the packet after our blob to see, so we just re-throw the
+ * exception.
+ */
+ TRY {
+ /* NTLMSSP constant */
+ proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth,
+ tvb, offset, 8, FALSE);
+ offset += 8;
+
+ /* NTLMSSP Message Type */
+ proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
+ tvb, offset, 4, TRUE);
+ ntlmssp_message_type = tvb_get_letohl (tvb, offset);
+ offset += 4;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(ntlmssp_message_type,
+ ntlmssp_message_types,
+ "Unknown message type"));
+
+ /* Call the appropriate dissector based on the Message Type */
+ switch (ntlmssp_message_type) {
+
+ case NTLMSSP_NEGOTIATE:
+ offset = dissect_ntlmssp_negotiate (tvb, offset, ntlmssp_tree);
+ break;
+
+ case NTLMSSP_CHALLENGE:
+ offset = dissect_ntlmssp_challenge (tvb, pinfo, offset, ntlmssp_tree);
+ break;
+
+ case NTLMSSP_AUTH:
+ offset = dissect_ntlmssp_auth (tvb, pinfo, offset, ntlmssp_tree);
+ break;
+
+ default:
+ /* Unrecognized message type */
+ proto_tree_add_text (ntlmssp_tree, tvb, offset, -1,
+ "Unrecognized NTLMSSP Message");
+ break;
+ }
+ } CATCH(BoundsError) {
+ RETHROW;
+ } CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ } ENDTRY;
+}
+
+/*
+ * Get the encryption state tied to this conversation. cryptpeer indicates
+ * whether to retrieve the data for peer1 or peer2.
+ */
+static rc4_state_struct *
+get_encrypted_state(packet_info *pinfo, int cryptpeer)
+{
+ conversation_t *conversation;
+ ntlmssp_info *conv_ntlmssp_info;
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (conversation == NULL) {
+ /* We don't have a conversation. In this case, stop processing
+ because we do not have enough info to decrypt the payload */
+ return NULL;
+ }
+ else {
+ /* We have a conversation, check for encryption state */
+ conv_ntlmssp_info = conversation_get_proto_data(conversation,
+ proto_ntlmssp);
+ if (conv_ntlmssp_info == NULL) {
+ /* No encryption state tied to the conversation. Therefore, we
+ cannot decrypt the payload */
+ return NULL;
+ }
+ else {
+ /* We have the encryption state in the conversation. So return the
+ crypt state tied to the requested peer
+ */
+ if (cryptpeer == 1) {
+ return &conv_ntlmssp_info->rc4_state_peer1;
+ } else {
+ return &conv_ntlmssp_info->rc4_state_peer2;
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ * See page 45 of "DCE/RPC over SMB" by Luke Kenneth Casson Leighton.
+ */
+static void
+decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
+ packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *decr_tree = NULL;
+ proto_item *tf = NULL;
+ conversation_t *conversation;
+ rc4_state_struct *rc4_state;
+ rc4_state_struct *rc4_state_peer;
+ tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
+ guint8 *peer_block;
+ ntlmssp_info *conv_ntlmssp_info = NULL;
+ ntlmssp_packet_info *packet_ntlmssp_info = NULL;
+ int decrypted_offset = 0;
+
+ packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
+ if (packet_ntlmssp_info == NULL) {
+ /* We don't have data for this packet */
+ return;
+ }
+ if (!packet_ntlmssp_info->verifier_decrypted) {
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (conversation == NULL) {
+ /* There is no conversation, thus no encryption state */
+ return;
+ }
+
+ conv_ntlmssp_info = conversation_get_proto_data(conversation,
+ proto_ntlmssp);
+ if (conv_ntlmssp_info == NULL) {
+ /* There is no NTLMSSP state tied to the conversation */
+ return;
+ }
+ if (conv_ntlmssp_info->rc4_state_initialized != 1 ) {
+ /* The crypto sybsystem is not initialized. This means that either
+ the conversation did not include a challenge, or we are doing
+ something other than NTLMSSP v1 */
+ return;
+ }
+
+ if (conv_ntlmssp_info->peer1_dest_port == pinfo->destport) {
+ rc4_state = get_encrypted_state(pinfo, 1);
+ rc4_state_peer = get_encrypted_state(pinfo, 0);
+ } else {
+ rc4_state = get_encrypted_state(pinfo, 0);
+ rc4_state_peer = get_encrypted_state(pinfo, 1);
+ }
+
+ if (rc4_state == NULL || rc4_state_peer == NULL) {
+ /* There is no encryption state, so we cannot decrypt */
+ return;
+ }
+
+ /* Setup the buffer to decrypt to */
+ tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
+ offset, encrypted_block_length);
+
+ /* Do the actual decryption of the verifier */
+ crypt_rc4(rc4_state, packet_ntlmssp_info->verifier,
+ encrypted_block_length);
+
+ /* We setup a temporary buffer so we can re-encrypt the payload after
+ decryption. This is to update the opposite peer's RC4 state */
+ peer_block = g_malloc(encrypted_block_length);
+ memcpy(peer_block, packet_ntlmssp_info->verifier,
+ encrypted_block_length);
+ crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
+ g_free(peer_block);
+
+ /* Mark the packet as decrypted so that subsequent attempts to dissect
+ the packet use the already decrypted payload instead of attempting
+ to decrypt again */
+ packet_ntlmssp_info->verifier_decrypted = TRUE;
+ }
+
+ /* Show the decrypted buffer in a new window */
+ decr_tvb = tvb_new_real_data(packet_ntlmssp_info->verifier,
+ encrypted_block_length,
+ encrypted_block_length);
+ tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
+ add_new_data_source(pinfo, decr_tvb,
+ "Decrypted NTLMSSP Verifier");
+
+ /* Show the decrypted payload in the tree */
+ tf = proto_tree_add_text(tree, decr_tvb, 0, -1,
+ "Decrypted Verifier (%d byte%s)",
+ encrypted_block_length,
+ plurality(encrypted_block_length, "", "s"));
+ decr_tree = proto_item_add_subtree (tf, ett_ntlmssp);
+
+ /* LKCL page 45 says this is a "reserved" field. I'm not sure if it's
+ garbage because it's some sort of nonce, or because there is a problem
+ with the verifier decryption routine. */
+ proto_tree_add_item (decr_tree, hf_ntlmssp_verf_unknown1,
+ decr_tvb, decrypted_offset, 4, TRUE);
+ decrypted_offset += 4;
+
+ /* CRC32 of the DCE fragment data */
+ proto_tree_add_item (decr_tree, hf_ntlmssp_verf_crc32,
+ decr_tvb, decrypted_offset, 4, TRUE);
+ decrypted_offset += 4;
+
+ /* Incrementing sequence number of DCE conversation */
+ proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
+ decr_tvb, decrypted_offset, 4, TRUE);
+ decrypted_offset += 4;
+}
+
+static int
+dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ volatile int offset = 0;
+ proto_tree *volatile ntlmssp_tree = NULL;
+ proto_item *tf = NULL;
+ guint32 verifier_length;
+ guint32 encrypted_block_length;
+
+ verifier_length = tvb_length_remaining (tvb, offset);
+ encrypted_block_length = verifier_length - 4;
+
+ if (encrypted_block_length < 12) {
+ /* Don't know why this would happen, but if it does, don't even bother
+ attempting decryption/dissection */
+ return offset + verifier_length;
+ }
+
+ /* Setup a new tree for the NTLMSSP payload */
+ if (tree) {
+ tf = proto_tree_add_item (tree,
+ hf_ntlmssp_verf,
+ tvb, offset, -1, FALSE);
+
+ ntlmssp_tree = proto_item_add_subtree (tf,
+ ett_ntlmssp);
+ }
+
+ /*
+ * Catch the ReportedBoundsError exception; the stuff we've been
+ * handed doesn't necessarily run to the end of the packet, it's
+ * an item inside a packet, so if it happens to be malformed (or
+ * we, or a dissector we call, has a bug), so that an exception
+ * is thrown, we want to report the error, but return and let
+ * our caller dissect the rest of the packet.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing more
+ * in the packet after our blob to see, so we just re-throw the
+ * exception.
+ */
+ TRY {
+ /* Version number */
+ proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
+ tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* Encrypted body */
+ proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
+ tvb, offset, encrypted_block_length, TRUE);
+
+ /* Try to decrypt */
+ decrypt_verifier (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree);
+
+ offset += encrypted_block_length;
+ } CATCH(BoundsError) {
+ RETHROW;
+ } CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ } ENDTRY;
+
+ return offset;
+}
+
+static tvbuff_t *
+dissect_ntlmssp_encrypted_payload(tvbuff_t *tvb, int offset,
+ packet_info *pinfo,
+ dcerpc_auth_info *auth_info _U_)
+{
+ tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
+ guint8 *peer_block;
+ conversation_t *conversation;
+ guint32 encrypted_block_length;
+ rc4_state_struct *rc4_state;
+ rc4_state_struct *rc4_state_peer;
+ ntlmssp_info *conv_ntlmssp_info = NULL;
+ ntlmssp_packet_info *packet_ntlmssp_info = NULL;
+
+ encrypted_block_length = tvb_length_remaining (tvb, offset);
+
+ /* Check to see if we already have state for this packet */
+ packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
+ if (packet_ntlmssp_info == NULL) {
+ /* We don't have any packet state, so create one */
+ packet_ntlmssp_info = g_mem_chunk_alloc(ntlmssp_packet_info_chunk);
+ memset(packet_ntlmssp_info, 0, sizeof(ntlmssp_packet_info));
+ p_add_proto_data(pinfo->fd, proto_ntlmssp, packet_ntlmssp_info);
+ }
+
+ if (!packet_ntlmssp_info->payload_decrypted) {
+ /* Pull the challenge info from the conversation */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ if (conversation == NULL) {
+ /* There is no conversation, thus no encryption state */
+ return NULL;
+ }
+
+ conv_ntlmssp_info = conversation_get_proto_data(conversation,
+ proto_ntlmssp);
+ if (conv_ntlmssp_info == NULL) {
+ /* There is no NTLMSSP state tied to the conversation */
+ return NULL;
+ }
+
+ /* Get the pair of RC4 state structures. One is used for to decrypt the
+ payload. The other is used to re-encrypt the payload to represent
+ the peer */
+ if (conv_ntlmssp_info->peer1_dest_port == pinfo->destport) {
+ rc4_state = get_encrypted_state(pinfo, 1);
+ rc4_state_peer = get_encrypted_state(pinfo, 0);
+ } else {
+ rc4_state = get_encrypted_state(pinfo, 0);
+ rc4_state_peer = get_encrypted_state(pinfo, 1);
+ }
+
+ if (rc4_state == NULL || rc4_state_peer == NULL) {
+ /* There is no encryption state, so we cannot decrypt */
+ return NULL;
+ }
+
+ /* Store the decrypted contents in the packet state struct
+ (of course at this point, they aren't decrypted yet) */
+ packet_ntlmssp_info->decrypted_payload = tvb_memdup(tvb, offset,
+ encrypted_block_length);
+ decrypted_payloads = g_slist_prepend(decrypted_payloads,
+ packet_ntlmssp_info->decrypted_payload);
+
+ /* Do the decryption of the payload */
+ crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
+ encrypted_block_length);
+
+ /* We setup a temporary buffer so we can re-encrypt the payload after
+ decryption. This is to update the opposite peer's RC4 state */
+ peer_block = g_malloc(encrypted_block_length);
+ memcpy(peer_block, packet_ntlmssp_info->decrypted_payload,
+ encrypted_block_length);
+ crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
+ g_free(peer_block);
+
+ packet_ntlmssp_info->payload_decrypted = TRUE;
+ }
+
+ /* Show the decrypted buffer in a new window */
+ decr_tvb = tvb_new_real_data(packet_ntlmssp_info->decrypted_payload,
+ encrypted_block_length,
+ encrypted_block_length);
+
+ tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
+
+ offset += encrypted_block_length;
+
+ return decr_tvb;
+}
+
+static void
+free_payload(gpointer decrypted_payload, gpointer user_data _U_)
+{
+ g_free(decrypted_payload);
+}
+
+static void
+ntlmssp_init_protocol(void)
+{
+ if (ntlmssp_info_chunk != NULL)
+ g_mem_chunk_destroy(ntlmssp_info_chunk);
+ if (ntlmssp_packet_info_chunk != NULL)
+ g_mem_chunk_destroy(ntlmssp_packet_info_chunk);
+
+ /*
+ * Free the decrypted payloads, and then free the list of decrypted
+ * payloads.
+ */
+ if (decrypted_payloads != NULL) {
+ g_slist_foreach(decrypted_payloads, free_payload, NULL);
+ g_slist_free(decrypted_payloads);
+ decrypted_payloads = NULL;
+ }
+
+ ntlmssp_info_chunk = g_mem_chunk_new("ntlmssp_info_chunk",
+ sizeof(ntlmssp_info),
+ ntlmssp_info_count * sizeof(ntlmssp_info),
+ G_ALLOC_ONLY);
+ ntlmssp_packet_info_chunk = g_mem_chunk_new("ntlmssp_packet_info_chunk",
+ sizeof(ntlmssp_packet_info),
+ ntlmssp_packet_info_count * sizeof(ntlmssp_packet_info),
+ G_ALLOC_ONLY);
+}
+
+void
+proto_register_ntlmssp(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_ntlmssp,
+ { "NTLMSSP", "ntlmssp", FT_NONE, BASE_NONE, NULL, 0x0, "NTLMSSP", HFILL }},
+
+ { &hf_ntlmssp_auth,
+ { "NTLMSSP identifier", "ntlmssp.identifier", FT_STRING, BASE_NONE, NULL, 0x0, "NTLMSSP Identifier", HFILL }},
+
+ { &hf_ntlmssp_message_type,
+ { "NTLM Message Type", "ntlmssp.messagetype", FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0, "", HFILL }},
+
+ { &hf_ntlmssp_negotiate_flags,
+ { "Flags", "ntlmssp.negotiateflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_01,
+
+ { "Negotiate UNICODE", "ntlmssp.negotiateunicode", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_UNICODE, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_02,
+ { "Negotiate OEM", "ntlmssp.negotiateoem", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_OEM, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_04,
+ { "Request Target", "ntlmssp.requesttarget", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_REQUEST_TARGET, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_08,
+ { "Request 0x00000008", "ntlmssp.negotiate00000008", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000008, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_10,
+ { "Negotiate Sign", "ntlmssp.negotiatesign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SIGN, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_20,
+ { "Negotiate Seal", "ntlmssp.negotiateseal", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SEAL, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_40,
+ { "Negotiate Datagram Style", "ntlmssp.negotiatedatagramstyle", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_DATAGRAM_STYLE, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_80,
+ { "Negotiate Lan Manager Key", "ntlmssp.negotiatelmkey", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_LM_KEY, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_100,
+ { "Negotiate Netware", "ntlmssp.negotiatenetware", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NETWARE, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_200,
+ { "Negotiate NTLM key", "ntlmssp.negotiatentlm", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_400,
+ { "Negotiate 0x00000400", "ntlmssp.negotiate00000400", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000400, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_800,
+ { "Negotiate 0x00000800", "ntlmssp.negotiate00000800", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000800, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_1000,
+ { "Negotiate Domain Supplied", "ntlmssp.negotiatedomainsupplied", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_2000,
+ { "Negotiate Workstation Supplied", "ntlmssp.negotiateworkstationsupplied", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_4000,
+ { "Negotiate This is Local Call", "ntlmssp.negotiatethisislocalcall", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_8000,
+ { "Negotiate Always Sign", "ntlmssp.negotiatealwayssign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_ALWAYS_SIGN, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_10000,
+ { "Negotiate Challenge Init Response", "ntlmssp.negotiatechallengeinitresponse", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_INIT_RESPONSE, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_20000,
+ { "Negotiate Challenge Accept Response", "ntlmssp.negotiatechallengeacceptresponse", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_ACCEPT_RESPONSE, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_40000,
+ { "Negotiate Challenge Non NT Session Key", "ntlmssp.negotiatechallengenonntsessionkey", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_NON_NT_SESSION_KEY, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_80000,
+ { "Negotiate NTLM2 key", "ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM2, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_100000,
+ { "Negotiate 0x00100000", "ntlmssp.negotiatent00100000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00100000, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_200000,
+ { "Negotiate 0x00200000", "ntlmssp.negotiatent00200000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00200000, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_400000,
+ { "Negotiate 0x00400000", "ntlmssp.negotiatent00400000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00400000, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_800000,
+ { "Negotiate Target Info", "ntlmssp.negotiatetargetinfo", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_CHAL_TARGET_INFO, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_1000000,
+ { "Negotiate 0x01000000", "ntlmssp.negotiatent01000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_01000000, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_2000000,
+ { "Negotiate 0x02000000", "ntlmssp.negotiatent02000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_02000000, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_4000000,
+ { "Negotiate 0x04000000", "ntlmssp.negotiatent04000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_04000000, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_8000000,
+ { "Negotiate 0x08000000", "ntlmssp.negotiatent08000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_08000000, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_10000000,
+ { "Negotiate 0x10000000", "ntlmssp.negotiatent10000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_10000000, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_20000000,
+ { "Negotiate 128", "ntlmssp.negotiate128", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_128, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_40000000,
+ { "Negotiate Key Exchange", "ntlmssp.negotiatekeyexch", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_KEY_EXCH, "", HFILL }},
+ { &hf_ntlmssp_negotiate_flags_80000000,
+ { "Negotiate 0x80000000", "ntlmssp.negotiatent80000000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_80000000, "", HFILL }},
+ { &hf_ntlmssp_negotiate_workstation_strlen,
+ { "Calling workstation name length", "ntlmssp.negotiate.callingworkstation.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_negotiate_workstation_maxlen,
+ { "Calling workstation name max length", "ntlmssp.negotiate.callingworkstation.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_negotiate_workstation_buffer,
+ { "Calling workstation name buffer", "ntlmssp.negotiate.callingworkstation.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_negotiate_workstation,
+ { "Calling workstation name", "ntlmssp.negotiate.callingworkstation", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_negotiate_domain_strlen,
+ { "Calling workstation domain length", "ntlmssp.negotiate.domain.strlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_negotiate_domain_maxlen,
+ { "Calling workstation domain max length", "ntlmssp.negotiate.domain.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_negotiate_domain_buffer,
+ { "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_negotiate_domain,
+ { "Calling workstation domain", "ntlmssp.negotiate.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_ntlm_challenge,
+ { "NTLM Challenge", "ntlmssp.ntlmchallenge", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_reserved,
+ { "Reserved", "ntlmssp.reserved", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_challenge_domain,
+ { "Domain", "ntlmssp.challenge.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_auth_domain,
+ { "Domain name", "ntlmssp.auth.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_auth_username,
+ { "User name", "ntlmssp.auth.username", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_auth_hostname,
+ { "Host name", "ntlmssp.auth.hostname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_auth_lmresponse,
+ { "Lan Manager Response", "ntlmssp.auth.lmresponse", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_auth_ntresponse,
+ { "NTLM Response", "ntlmssp.auth.ntresponse", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_auth_sesskey,
+ { "Session Key", "ntlmssp.auth.sesskey", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_string_len,
+ { "Length", "ntlmssp.string.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_string_maxlen,
+ { "Maxlen", "ntlmssp.string.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_string_offset,
+ { "Offset", "ntlmssp.string.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_blob_len,
+ { "Length", "ntlmssp.blob.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_blob_maxlen,
+ { "Maxlen", "ntlmssp.blob.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_blob_offset,
+ { "Offset", "ntlmssp.blob.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_address_list,
+ { "Address List", "ntlmssp.challenge.addresslist", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_address_list_len,
+ { "Length", "ntlmssp.challenge.addresslist.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_address_list_maxlen,
+ { "Maxlen", "ntlmssp.challenge.addresslist.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_address_list_offset,
+ { "Offset", "ntlmssp.challenge.addresslist.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_address_list_item_type,
+ { "Target item type", "ntlmssp.targetitemtype", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, "", HFILL }},
+ { &hf_ntlmssp_address_list_item_len,
+ { "Target item Length", "ntlmssp.challenge.addresslist.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_address_list_item_content,
+ { "Target item Content", "ntlmssp.challenge.addresslist.item.content", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
+ { &hf_ntlmssp_address_list_server_nb,
+ { "Server NetBIOS Name", "ntlmssp.challenge.addresslist.servernb", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_address_list_domain_nb,
+ { "Domain NetBIOS Name", "ntlmssp.challenge.addresslist.domainnb", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_address_list_server_dns,
+ { "Server DNS Name", "ntlmssp.challenge.addresslist.serverdns", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_address_list_domain_dns,
+ { "Domain DNS Name", "ntlmssp.challenge.addresslist.domaindns", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_address_list_terminator,
+ { "List Terminator", "ntlmssp.challenge.addresslist.terminator", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_verf,
+ { "NTLMSSP Verifier", "ntlmssp.verf", FT_NONE, BASE_NONE, NULL, 0x0, "NTLMSSP Verifier", HFILL }},
+ { &hf_ntlmssp_verf_vers,
+ { "Version Number", "ntlmssp.verf.vers", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_verf_body,
+ { "Verifier Body", "ntlmssp.verf.body", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_decrypted_payload,
+ { "NTLM Decrypted Payload", "ntlmssp.decrypted_payload", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_verf_unknown1,
+ { "Unknown 1", "ntlmssp.verf.unknown1", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_verf_crc32,
+ { "Verifier CRC32", "ntlmssp.verf.crc32", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_ntlmssp_verf_sequence,
+ { "Verifier Sequence Number", "ntlmssp.verf.sequence", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}
+ };
+
+
+ static gint *ett[] = {
+ &ett_ntlmssp,
+ &ett_ntlmssp_negotiate_flags,
+ &ett_ntlmssp_string,
+ &ett_ntlmssp_blob,
+ &ett_ntlmssp_address_list,
+ &ett_ntlmssp_address_list_item
+ };
+ module_t *ntlmssp_module;
+
+ proto_ntlmssp = proto_register_protocol (
+ "NTLM Secure Service Provider", /* name */
+ "NTLMSSP", /* short name */
+ "ntlmssp" /* abbrev */
+ );
+ proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+ register_init_routine(&ntlmssp_init_protocol);
+
+ ntlmssp_module = prefs_register_protocol(proto_ntlmssp, NULL);
+
+ prefs_register_string_preference(ntlmssp_module, "nt_password",
+ "NT Password",
+ "NT Password (used to decrypt payloads)",
+ &nt_password);
+
+ register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
+ new_register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
+}
+
+static int wrap_dissect_ntlmssp(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ tvbuff_t *auth_tvb;
+
+ auth_tvb = tvb_new_subset(
+ tvb, offset, tvb_length_remaining(tvb, offset),
+ tvb_length_remaining(tvb, offset));
+
+ dissect_ntlmssp(auth_tvb, pinfo, tree);
+
+ return tvb_length_remaining(tvb, offset);
+}
+
+static int wrap_dissect_ntlmssp_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep _U_)
+{
+ tvbuff_t *auth_tvb;
+
+ auth_tvb = tvb_new_subset(
+ tvb, offset, tvb_length_remaining(tvb, offset),
+ tvb_length_remaining(tvb, offset));
+
+ return dissect_ntlmssp_verf(auth_tvb, pinfo, tree);
+}
+
+static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = {
+ wrap_dissect_ntlmssp, /* Bind */
+ wrap_dissect_ntlmssp, /* Bind ACK */
+ wrap_dissect_ntlmssp, /* AUTH3 */
+ wrap_dissect_ntlmssp_verf, /* Request verifier */
+ wrap_dissect_ntlmssp_verf, /* Response verifier */
+ NULL, /* Request data */
+ NULL /* Response data */
+};
+
+static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = {
+ wrap_dissect_ntlmssp, /* Bind */
+ wrap_dissect_ntlmssp, /* Bind ACK */
+ wrap_dissect_ntlmssp, /* AUTH3 */
+ wrap_dissect_ntlmssp_verf, /* Request verifier */
+ wrap_dissect_ntlmssp_verf, /* Response verifier */
+ dissect_ntlmssp_encrypted_payload, /* Request data */
+ dissect_ntlmssp_encrypted_payload /* Response data */
+};
+
+void
+proto_reg_handoff_ntlmssp(void)
+{
+ dissector_handle_t ntlmssp_handle, ntlmssp_wrap_handle;
+
+ /* Register protocol with the GSS-API module */
+
+ ntlmssp_handle = find_dissector("ntlmssp");
+ ntlmssp_wrap_handle = find_dissector("ntlmssp_verf");
+ gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp,
+ ntlmssp_handle, ntlmssp_wrap_handle,
+ "NTLMSSP - Microsoft NTLM Security Support Provider");
+
+ /* Register authenticated pipe dissector */
+
+ /*
+ * XXX - the verifiers here seem to have a version of 1 and a body of all
+ * zeroes.
+ *
+ * XXX - DCE_C_AUTHN_LEVEL_CONNECT is, according to the DCE RPC 1.1
+ * spec, upgraded to DCE_C_AUTHN_LEVEL_PKT. Should we register
+ * any other levels here?
+ */
+ register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
+ DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
+ &ntlmssp_sign_fns);
+
+ register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
+ DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
+ &ntlmssp_sign_fns);
+
+ register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
+ DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
+ &ntlmssp_seal_fns);
+}
diff --git a/epan/dissectors/packet-ntp.c b/epan/dissectors/packet-ntp.c
new file mode 100644
index 0000000000..10c563b6e0
--- /dev/null
+++ b/epan/dissectors/packet-ntp.c
@@ -0,0 +1,954 @@
+/* packet-ntp.c
+ * Routines for NTP packet dissection
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "packet-ntp.h"
+
+/*
+ * Dissecting NTP packets version 3 and 4 (RFC2030, RFC1769, RFC1361,
+ * RFC1305).
+ *
+ * Those packets have simple structure:
+ * 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |LI | VN |Mode | Stratum | Poll | Precision |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Root Delay |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Root Dispersion |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reference Identifier |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reference Timestamp (64) |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Originate Timestamp (64) |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Receive Timestamp (64) |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Transmit Timestamp (64) |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Key Identifier (optional) (32) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Message Digest (optional) (128) |
+ * | |
+ * | |
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * NTP timestamps are represented as a 64-bit unsigned fixed-point number,
+ * in seconds relative to 0h on 1 January 1900. The integer part is in the
+ * first 32 bits and the fraction part in the last 32 bits.
+ */
+
+#define UDP_PORT_NTP 123
+#define TCP_PORT_NTP 123
+
+/* Leap indicator, 2bit field is used to warn of a inserted/deleted
+ * second, or to alarm loosed synchronization.
+ */
+#define NTP_LI_MASK 0xC0
+
+#define NTP_LI_NONE 0
+#define NTP_LI_61 1
+#define NTP_LI_59 2
+#define NTP_LI_ALARM 3
+
+static const value_string li_types[] = {
+ { NTP_LI_NONE, "no warning" },
+ { NTP_LI_61, "last minute has 61 seconds" },
+ { NTP_LI_59, "last minute has 59 seconds" },
+ { NTP_LI_ALARM, "alarm condition (clock not synchronized)" },
+ { 0, NULL}
+};
+
+/* Version info, 3bit field informs about NTP version used in particular
+ * packet. According to rfc2030, version info could be only 3 or 4, but I
+ * have noticed packets with 1 or even 6 as version numbers. They are
+ * produced as a result of ntptrace command. Are those packets mailformed
+ * on purpose? I don't know yet, probably some browsing through ntp sources
+ * would help. My solution is to put them as reserved for now.
+ */
+#define NTP_VN_MASK 0x38
+
+static const value_string ver_nums[] = {
+ { 0, "reserved" },
+ { 1, "reserved" },
+ { 2, "reserved" },
+ { 3, "NTP Version 3" },
+ { 4, "NTP Version 4" },
+ { 5, "reserved" },
+ { 6, "reserved" },
+ { 7, "reserved" },
+ { 0, NULL}
+};
+
+/* Mode, 3bit field representing mode of comunication.
+ */
+#define NTP_MODE_MASK 7
+
+#define NTP_MODE_RSV 0
+#define NTP_MODE_SYMACT 1
+#define NTP_MODE_SYMPAS 2
+#define NTP_MODE_CLIENT 3
+#define NTP_MODE_SERVER 4
+#define NTP_MODE_BCAST 5
+#define NTP_MODE_CTRL 6
+#define NTP_MODE_PRIV 7
+
+static const value_string mode_types[] = {
+ { NTP_MODE_RSV, "reserved" },
+ { NTP_MODE_SYMACT, "symmetric active" },
+ { NTP_MODE_SYMPAS, "symmetric passive" },
+ { NTP_MODE_CLIENT, "client" },
+ { NTP_MODE_SERVER, "server" },
+ { NTP_MODE_BCAST, "broadcast" },
+ { NTP_MODE_CTRL, "reserved for NTP control message"},
+ { NTP_MODE_PRIV, "reserved for private use" },
+ { 0, NULL}
+};
+
+/* According to rfc, primary (stratum-0 and stratum-1) servers should set
+ * their Reference Clock ID (4bytes field) according to following table:
+ */
+static const struct {
+ char *id;
+ char *data;
+} primary_sources[] = {
+ { "LOCL", "uncalibrated local clock" },
+ { "PPS\0", "atomic clock or other pulse-per-second source" },
+ { "ACTS", "NIST dialup modem service" },
+ { "USNO", "USNO modem service" },
+ { "PTB\0", "PTB (Germany) modem service" },
+ { "TDF\0", "Allouis (France) Radio 164 kHz" },
+ { "DCF\0", "Mainflingen (Germany) Radio 77.5 kHz" },
+ { "MSF\0", "Rugby (UK) Radio 60 kHz" },
+ { "WWV\0", "Ft. Collins (US) Radio 2.5, 5, 10, 15, 20 MHz" },
+ { "WWVB", "Boulder (US) Radio 60 kHz" },
+ { "WWVH", "Kaui Hawaii (US) Radio 2.5, 5, 10, 15 MHz" },
+ { "CHU\0", "Ottawa (Canada) Radio 3330, 7335, 14670 kHz" },
+ { "LORC", "LORAN-C radionavigation system" },
+ { "OMEG", "OMEGA radionavigation system" },
+ { "GPS\0", "Global Positioning Service" },
+ { "GOES", "Geostationary Orbit Environment Satellite" },
+ { "DCN\0", "DCN routing protocol" },
+ { "NIST", "NIST public modem" },
+ { "TSP\0", "TSP time protocol" },
+ { "DTS\0", "Digital Time Service" },
+ { "ATOM", "Atomic clock (calibrated)" },
+ { "VLF\0", "VLF radio (OMEGA,, etc.)" },
+ { "IRIG", "IRIG-B timecode" },
+ { "1PPS", "External 1 PPS input" },
+ { "FREE", "(Internal clock)" },
+ { NULL, NULL}
+};
+
+#define NTP_EXT_R_MASK 0x80
+
+static const value_string ext_r_types[] = {
+ { 0, "Request" },
+ { 1, "Response" },
+ { 0, NULL}
+};
+
+#define NTP_EXT_ERROR_MASK 0x40
+#define NTP_EXT_VN_MASK 0x3f
+
+static const value_string ext_op_types[] = {
+ { 0, "NULL" },
+ { 1, "ASSOC" },
+ { 2, "CERT" },
+ { 3, "COOK" },
+ { 4, "AUTO" },
+ { 5, "TAI" },
+ { 6, "SIGN" },
+ { 7, "IFF" },
+ { 8, "GQ" },
+ { 9, "MV" },
+ { 0, NULL}
+};
+
+#define NTPCTRL_R_MASK 0x80
+
+#define ctrl_r_types ext_r_types
+
+#define NTPCTRL_ERROR_MASK 0x40
+#define NTPCTRL_MORE_MASK 0x20
+#define NTPCTRL_OP_MASK 0x1f
+
+static const value_string ctrl_op_types[] = {
+ { 0, "UNSPEC" },
+ { 1, "READSTAT" },
+ { 2, "READVAR" },
+ { 3, "WRITEVAR" },
+ { 4, "READCLOCK" },
+ { 5, "WRITECLOCK" },
+ { 6, "SETTRAP" },
+ { 7, "ASYNCMSG" },
+ { 31, "UNSETTRAP" },
+ { 0, NULL}
+};
+
+#define NTPPRIV_R_MASK 0x80
+
+#define priv_r_types ext_r_types
+
+#define NTPPRIV_MORE_MASK 0x40
+
+#define NTPPRIV_AUTH_MASK 0x80
+#define NTPPRIV_SEQ_MASK 0x7f
+
+static const value_string priv_impl_types[] = {
+ { 0, "UNIV" },
+ { 2, "XNTPD_OLD (pre-IPv6)" },
+ { 3, "XNTPD" },
+ { 0, NULL}
+};
+
+static const value_string priv_rc_types[] = {
+ { 0, "PEER_LIST" },
+ { 1, "PEER_LIST_SUM" },
+ { 2, "PEER_INFO" },
+ { 3, "PEER_STATS" },
+ { 4, "SYS_INFO" },
+ { 5, "SYS_STATS" },
+ { 6, "IO_STATS" },
+ { 7, "MEM_STATS" },
+ { 8, "LOOP_INFO" },
+ { 9, "TIMER_STATS" },
+ { 10, "CONFIG" },
+ { 11, "UNCONFIG" },
+ { 12, "SET_SYS_FLAG" },
+ { 13, "CLR_SYS_FLAG" },
+ { 16, "GET_RESTRICT" },
+ { 17, "RESADDFLAGS" },
+ { 18, "RESSUBFLAGS" },
+ { 19, "UNRESTRICT" },
+ { 20, "MON_GETLIST" },
+ { 21, "RESET_STATS" },
+ { 22, "RESET_PEER" },
+ { 23, "REREAD_KEYS" },
+ { 26, "TRUSTKEY" },
+ { 27, "UNTRUSTKEY" },
+ { 28, "AUTHINFO" },
+ { 29, "TRAPS" },
+ { 30, "ADD_TRAP" },
+ { 31, "CLR_TRAP" },
+ { 32, "REQUEST_KEY" },
+ { 33, "CONTROL_KEY" },
+ { 34, "GET_CTLSTATS" },
+ { 36, "GET_CLOCKINFO" },
+ { 37, "SET_CLKFUDGE" },
+ { 38, "GET_KERNEL" },
+ { 39, "GET_CLKBUGINFO" },
+ { 42, "MON_GETLIST_1" },
+ { 43, "HOSTNAME_ASSOCID" },
+ { 0, NULL}
+};
+
+/*
+ * Maximum MAC length.
+ */
+#define MAX_MAC_LEN (5 * sizeof (guint32))
+
+static int proto_ntp = -1;
+
+static int hf_ntp_flags = -1;
+static int hf_ntp_flags_li = -1;
+static int hf_ntp_flags_vn = -1;
+static int hf_ntp_flags_mode = -1;
+static int hf_ntp_stratum = -1;
+static int hf_ntp_ppoll = -1;
+static int hf_ntp_precision = -1;
+static int hf_ntp_rootdelay = -1;
+static int hf_ntp_rootdispersion = -1;
+static int hf_ntp_refid = -1;
+static int hf_ntp_reftime = -1;
+static int hf_ntp_org = -1;
+static int hf_ntp_rec = -1;
+static int hf_ntp_xmt = -1;
+static int hf_ntp_keyid = -1;
+static int hf_ntp_mac = -1;
+
+static int hf_ntp_ext = -1;
+static int hf_ntp_ext_flags = -1;
+static int hf_ntp_ext_flags_r = -1;
+static int hf_ntp_ext_flags_error = -1;
+static int hf_ntp_ext_flags_vn = -1;
+static int hf_ntp_ext_op = -1;
+static int hf_ntp_ext_len = -1;
+static int hf_ntp_ext_associd = -1;
+static int hf_ntp_ext_tstamp = -1;
+static int hf_ntp_ext_fstamp = -1;
+static int hf_ntp_ext_vallen = -1;
+static int hf_ntp_ext_val = -1;
+static int hf_ntp_ext_siglen = -1;
+static int hf_ntp_ext_sig = -1;
+
+static int hf_ntpctrl_flags2 = -1;
+static int hf_ntpctrl_flags2_r = -1;
+static int hf_ntpctrl_flags2_error = -1;
+static int hf_ntpctrl_flags2_more = -1;
+static int hf_ntpctrl_flags2_opcode = -1;
+
+static int hf_ntppriv_flags_r = -1;
+static int hf_ntppriv_flags_more = -1;
+static int hf_ntppriv_auth_seq = -1;
+static int hf_ntppriv_auth = -1;
+static int hf_ntppriv_seq = -1;
+static int hf_ntppriv_impl = -1;
+static int hf_ntppriv_reqcode = -1;
+
+static gint ett_ntp = -1;
+static gint ett_ntp_flags = -1;
+static gint ett_ntp_ext = -1;
+static gint ett_ntp_ext_flags = -1;
+static gint ett_ntpctrl_flags2 = -1;
+static gint ett_ntppriv_auth_seq = -1;
+
+static void dissect_ntp_std(tvbuff_t *, proto_tree *, guint8);
+static void dissect_ntp_ctrl(tvbuff_t *, proto_tree *, guint8);
+static void dissect_ntp_priv(tvbuff_t *, proto_tree *, guint8);
+static int dissect_ntp_ext(tvbuff_t *, proto_tree *, int);
+
+/* ntp_fmt_ts - converts NTP timestamp to human readable string.
+ * reftime - 64bit timestamp (IN)
+ * buff - string buffer for result (OUT)
+ * returns pointer to filled buffer.
+ */
+char *
+ntp_fmt_ts(const guint8 *reftime, char* buff)
+{
+ guint32 tempstmp, tempfrac;
+ time_t temptime;
+ struct tm *bd;
+ double fractime;
+
+ tempstmp = pntohl(&reftime[0]);
+ tempfrac = pntohl(&reftime[4]);
+ if ((tempstmp == 0) && (tempfrac == 0)) {
+ strcpy (buff, "NULL");
+ return buff;
+ } else {
+ temptime = tempstmp - (guint32) NTP_BASETIME;
+ bd = gmtime(&temptime);
+ if (bd != NULL) {
+ fractime = bd->tm_sec + tempfrac / 4294967296.0;
+ snprintf(buff, NTP_TS_SIZE,
+ "%04d-%02d-%02d %02d:%02d:%07.4f UTC",
+ bd->tm_year + 1900, bd->tm_mon + 1, bd->tm_mday,
+ bd->tm_hour, bd->tm_min, fractime);
+ } else
+ strncpy(buff, "Not representable", NTP_TS_SIZE);
+ }
+ return buff;
+}
+
+/* dissect_ntp - dissects NTP packet data
+ * tvb - tvbuff for packet data (IN)
+ * pinfo - packet info
+ * proto_tree - resolved protocol tree
+ */
+static void
+dissect_ntp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ntp_tree;
+ proto_item *ti;
+ guint8 flags;
+ char *infostr;
+ void (*dissector)(tvbuff_t *, proto_item *, guint8);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NTP");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ flags = tvb_get_guint8(tvb, 0);
+ switch (flags & NTP_MODE_MASK) {
+ default:
+ infostr = "NTP";
+ dissector = dissect_ntp_std;
+ break;
+ case NTP_MODE_CTRL:
+ infostr = "NTP control";
+ dissector = dissect_ntp_ctrl;
+ break;
+ case NTP_MODE_PRIV:
+ infostr = "NTP private";
+ dissector = dissect_ntp_priv;
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, infostr);
+
+ if (tree) {
+ /* Adding NTP item and subtree */
+ ti = proto_tree_add_item(tree, proto_ntp, tvb, 0, -1, FALSE);
+ ntp_tree = proto_item_add_subtree(ti, ett_ntp);
+
+ (*dissector)(tvb, ntp_tree, flags);
+ }
+}
+
+static void
+dissect_ntp_std(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
+{
+ proto_tree *flags_tree;
+ proto_item *tf;
+ guint8 stratum;
+ guint8 ppoll;
+ gint8 precision;
+ double rootdelay;
+ double rootdispersion;
+ const guint8 *refid;
+ guint32 refid_addr;
+ const guint8 *reftime;
+ const guint8 *org;
+ const guint8 *rec;
+ const guint8 *xmt;
+ gchar buff[NTP_TS_SIZE];
+ int i;
+ int macofs;
+ gint maclen;
+
+ tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
+
+ /* Adding flag subtree and items */
+ flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
+
+ /* Stratum, 1byte field represents distance from primary source
+ */
+ stratum = tvb_get_guint8(tvb, 1);
+ if (stratum == 0) {
+ strcpy (buff, "Peer Clock Stratum: unspecified or unavailable (%u)");
+ } else if (stratum == 1) {
+ strcpy (buff, "Peer Clock Stratum: primary reference (%u)");
+ } else if ((stratum >= 2) && (stratum <= 15)) {
+ strcpy (buff, "Peer Clock Stratum: secondary reference (%u)");
+ } else {
+ strcpy (buff, "Peer Clock Stratum: reserved: %u");
+ }
+ proto_tree_add_uint_format(ntp_tree, hf_ntp_stratum, tvb, 1, 1,
+ stratum, buff, stratum);
+ /* Poll interval, 1byte field indicating the maximum interval
+ * between successive messages, in seconds to the nearest
+ * power of two.
+ */
+ ppoll = tvb_get_guint8(tvb, 2);
+ proto_tree_add_uint_format(ntp_tree, hf_ntp_ppoll, tvb, 2, 1,
+ ppoll,
+ (((ppoll >= 4) && (ppoll <= 16)) ?
+ "Peer Polling Interval: %u (%u sec)" :
+ "Peer Polling Interval: invalid (%u)"),
+ ppoll,
+ 1 << ppoll);
+
+ /* Precision, 1byte field indicating the precision of the
+ * local clock, in seconds to the nearest power of two.
+ */
+ precision = tvb_get_guint8(tvb, 3);
+ proto_tree_add_int_format(ntp_tree, hf_ntp_precision, tvb, 3, 1,
+ precision,
+ "Peer Clock Precision: %8.6f sec",
+ pow(2, precision));
+
+ /* Root Delay is a 32-bit signed fixed-point number indicating
+ * the total roundtrip delay to the primary reference source,
+ * in seconds with fraction point between bits 15 and 16.
+ */
+ rootdelay = ((gint16)tvb_get_ntohs(tvb, 4)) +
+ (tvb_get_ntohs(tvb, 6) / 65536.0);
+ proto_tree_add_double_format(ntp_tree, hf_ntp_rootdelay, tvb, 4, 4,
+ rootdelay,
+ "Root Delay: %9.4f sec",
+ rootdelay);
+
+ /* Root Dispersion, 32-bit unsigned fixed-point number indicating
+ * the nominal error relative to the primary reference source, in
+ * seconds with fraction point between bits 15 and 16.
+ */
+ rootdispersion = ((gint16)tvb_get_ntohs(tvb, 8)) +
+ (tvb_get_ntohs(tvb, 10) / 65536.0);
+ proto_tree_add_double_format(ntp_tree, hf_ntp_rootdispersion, tvb, 8, 4,
+ rootdispersion,
+ "Clock Dispersion: %9.4f sec",
+ rootdispersion);
+
+ /* Now, there is a problem with secondary servers. Standards
+ * asks from stratum-2 - stratum-15 servers to set this to the
+ * low order 32 bits of the latest transmit timestamp of the
+ * reference source.
+ * But, all V3 and V4 servers set this to IP adress of their
+ * higher level server. My decision was to resolve this address.
+ */
+ refid = tvb_get_ptr(tvb, 12, 4);
+ if (stratum <= 1) {
+ snprintf (buff, sizeof buff,
+ "Unindentified reference source '%.4s'",
+ refid);
+ for (i = 0; primary_sources[i].id; i++) {
+ if (memcmp (refid, primary_sources[i].id,
+ 4) == 0) {
+ strcpy (buff, primary_sources[i].data);
+ break;
+ }
+ }
+ } else {
+ buff[sizeof(buff) - 1] = '\0';
+ tvb_memcpy(tvb, (guint8 *)&refid_addr, 12, 4);
+ strncpy (buff, get_hostname (refid_addr),
+ sizeof(buff));
+ if (buff[sizeof(buff) - 1] != '\0')
+ strcpy(&buff[sizeof(buff) - 4], "...");
+ }
+ proto_tree_add_bytes_format(ntp_tree, hf_ntp_refid, tvb, 12, 4,
+ refid,
+ "Reference Clock ID: %s", buff);
+
+ /* Reference Timestamp: This is the time at which the local clock was
+ * last set or corrected.
+ */
+ reftime = tvb_get_ptr(tvb, 16, 8);
+ proto_tree_add_bytes_format(ntp_tree, hf_ntp_reftime, tvb, 16, 8,
+ reftime,
+ "Reference Clock Update Time: %s",
+ ntp_fmt_ts(reftime, buff));
+
+ /* Originate Timestamp: This is the time at which the request departed
+ * the client for the server.
+ */
+ org = tvb_get_ptr(tvb, 24, 8);
+ proto_tree_add_bytes_format(ntp_tree, hf_ntp_org, tvb, 24, 8,
+ org,
+ "Originate Time Stamp: %s",
+ ntp_fmt_ts(org, buff));
+
+ /* Receive Timestamp: This is the time at which the request arrived at
+ * the server.
+ */
+ rec = tvb_get_ptr(tvb, 32, 8);
+ proto_tree_add_bytes_format(ntp_tree, hf_ntp_rec, tvb, 32, 8,
+ rec,
+ "Receive Time Stamp: %s",
+ ntp_fmt_ts(rec, buff));
+
+ /* Transmit Timestamp: This is the time at which the reply departed the
+ * server for the client.
+ */
+ xmt = tvb_get_ptr(tvb, 40, 8);
+ proto_tree_add_bytes_format(ntp_tree, hf_ntp_xmt, tvb, 40, 8,
+ xmt,
+ "Transmit Time Stamp: %s",
+ ntp_fmt_ts(xmt, buff));
+
+ /* MAX_MAC_LEN is the largest message authentication code
+ * (MAC) length. If we have more data left in the packet
+ * after the header than that, the extra data is NTP4
+ * extensions; parse them as such.
+ */
+ macofs = 48;
+ while (tvb_reported_length_remaining(tvb, macofs) > (gint)MAX_MAC_LEN)
+ macofs = dissect_ntp_ext(tvb, ntp_tree, macofs);
+
+ /* When the NTP authentication scheme is implemented, the
+ * Key Identifier and Message Digest fields contain the
+ * message authentication code (MAC) information defined in
+ * Appendix C of RFC-1305. Will print this as hex code for now.
+ */
+ if (tvb_reported_length_remaining(tvb, macofs) >= 4)
+ proto_tree_add_item(ntp_tree, hf_ntp_keyid, tvb, macofs, 4,
+ FALSE);
+ macofs += 4;
+ maclen = tvb_reported_length_remaining(tvb, macofs);
+ if (maclen > 0)
+ proto_tree_add_item(ntp_tree, hf_ntp_mac, tvb, macofs,
+ maclen, FALSE);
+}
+
+static int
+dissect_ntp_ext(tvbuff_t *tvb, proto_tree *ntp_tree, int offset)
+{
+ proto_tree *ext_tree, *flags_tree;
+ proto_item *tf;
+ guint16 extlen;
+ int endoffset;
+ guint8 flags;
+ guint32 vallen, vallen_round, siglen;
+
+ extlen = tvb_get_ntohs(tvb, offset+2);
+ if (extlen < 8) {
+ /* Extension length isn't enough for the extension header.
+ * Report the error, and return an offset that goes to
+ * the end of the tvbuff, so we stop dissecting.
+ */
+ proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
+ "Extension length %u < 8", extlen);
+ offset += tvb_length_remaining(tvb, offset);
+ return offset;
+ }
+ if (extlen % 4) {
+ /* Extension length isn't a multiple of 4.
+ * Report the error, and return an offset that goes
+ * to the end of the tvbuff, so we stop dissecting.
+ */
+ proto_tree_add_text(ntp_tree, tvb, offset+2, 2,
+ "Extension length %u isn't a multiple of 4",
+ extlen);
+ offset += tvb_length_remaining(tvb, offset);
+ return offset;
+ }
+ endoffset = offset + extlen;
+
+ tf = proto_tree_add_item(ntp_tree, hf_ntp_ext, tvb, offset, extlen,
+ FALSE);
+ ext_tree = proto_item_add_subtree(tf, ett_ntp_ext);
+
+ flags = tvb_get_guint8(tvb, offset);
+ tf = proto_tree_add_uint(ext_tree, hf_ntp_ext_flags, tvb, offset, 1,
+ flags);
+ flags_tree = proto_item_add_subtree(tf, ett_ntp_ext_flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_r, tvb, offset, 1,
+ flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_error, tvb, offset, 1,
+ flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_ext_flags_vn, tvb, offset, 1,
+ flags);
+ offset++;
+
+ proto_tree_add_item(ext_tree, hf_ntp_ext_op, tvb, offset, 1, FALSE);
+ offset++;
+
+ proto_tree_add_uint(ext_tree, hf_ntp_ext_len, tvb, offset, 2, extlen);
+ offset += 2;
+
+ if ((flags & NTP_EXT_VN_MASK) != 2) {
+ /* don't care about autokey v1 */
+ return endoffset;
+ }
+
+ proto_tree_add_item(ext_tree, hf_ntp_ext_associd, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+
+ /* check whether everything up to "vallen" is present */
+ if (extlen < MAX_MAC_LEN) {
+ /* XXX - report as error? */
+ return endoffset;
+ }
+
+ proto_tree_add_item(ext_tree, hf_ntp_ext_tstamp, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ proto_tree_add_item(ext_tree, hf_ntp_ext_fstamp, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ /* XXX fstamp can be server flags */
+
+ vallen = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(ext_tree, hf_ntp_ext_vallen, tvb, offset, 4,
+ vallen);
+ offset += 4;
+ vallen_round = (vallen + 3) & (-4);
+ if (vallen != 0) {
+ if ((guint32)(endoffset - offset) < vallen_round) {
+ /*
+ * Value goes past the length of the extension
+ * field.
+ */
+ proto_tree_add_text(ext_tree, tvb, offset,
+ endoffset - offset,
+ "Value length makes value go past the end of the extension field");
+ return endoffset;
+ }
+ proto_tree_add_item(ext_tree, hf_ntp_ext_val, tvb, offset,
+ vallen, FALSE);
+ }
+ offset += vallen_round;
+
+ siglen = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(ext_tree, hf_ntp_ext_siglen, tvb, offset, 4,
+ siglen);
+ offset += 4;
+ if (siglen != 0) {
+ if (offset + (int)siglen > endoffset) {
+ /*
+ * Value goes past the length of the extension
+ * field.
+ */
+ proto_tree_add_text(ext_tree, tvb, offset,
+ endoffset - offset,
+ "Signature length makes value go past the end of the extension field");
+ return endoffset;
+ }
+ proto_tree_add_item(ext_tree, hf_ntp_ext_sig, tvb,
+ offset, siglen, FALSE);
+ }
+ return endoffset;
+}
+
+static void
+dissect_ntp_ctrl(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
+{
+ proto_tree *flags_tree;
+ proto_item *tf;
+ guint8 flags2;
+
+ tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
+
+ /* Adding flag subtree and items */
+ flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_flags_li, tvb, 0, 1, flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
+
+ flags2 = tvb_get_guint8(tvb, 1);
+ tf = proto_tree_add_uint(ntp_tree, hf_ntpctrl_flags2, tvb, 1, 1,
+ flags2);
+ flags_tree = proto_item_add_subtree(tf, ett_ntpctrl_flags2);
+ proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_r, tvb, 1, 1,
+ flags2);
+ proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_error, tvb, 1, 1,
+ flags2);
+ proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_more, tvb, 1, 1,
+ flags2);
+ proto_tree_add_uint(flags_tree, hf_ntpctrl_flags2_opcode, tvb, 1, 1,
+ flags2);
+}
+
+static void
+dissect_ntp_priv(tvbuff_t *tvb, proto_tree *ntp_tree, guint8 flags)
+{
+ proto_tree *flags_tree;
+ proto_item *tf;
+ guint8 auth_seq, impl, reqcode;
+
+ tf = proto_tree_add_uint(ntp_tree, hf_ntp_flags, tvb, 0, 1, flags);
+
+ /* Adding flag subtree and items */
+ flags_tree = proto_item_add_subtree(tf, ett_ntp_flags);
+ proto_tree_add_uint(flags_tree, hf_ntppriv_flags_r, tvb, 0, 1, flags);
+ proto_tree_add_uint(flags_tree, hf_ntppriv_flags_more, tvb, 0, 1,
+ flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_flags_vn, tvb, 0, 1, flags);
+ proto_tree_add_uint(flags_tree, hf_ntp_flags_mode, tvb, 0, 1, flags);
+
+ auth_seq = tvb_get_guint8(tvb, 1);
+ tf = proto_tree_add_uint(ntp_tree, hf_ntppriv_auth_seq, tvb, 1, 1,
+ auth_seq);
+ flags_tree = proto_item_add_subtree(tf, ett_ntppriv_auth_seq);
+ proto_tree_add_uint(flags_tree, hf_ntppriv_auth, tvb, 1, 1, auth_seq);
+ proto_tree_add_uint(flags_tree, hf_ntppriv_seq, tvb, 1, 1, auth_seq);
+
+ impl = tvb_get_guint8(tvb, 2);
+ proto_tree_add_uint(ntp_tree, hf_ntppriv_impl, tvb, 2, 1, impl);
+
+ reqcode = tvb_get_guint8(tvb, 3);
+ proto_tree_add_uint(ntp_tree, hf_ntppriv_reqcode, tvb, 3, 1, reqcode);
+}
+
+void
+proto_register_ntp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ntp_flags, {
+ "Flags", "ntp.flags", FT_UINT8, BASE_HEX,
+ NULL, 0, "Flags (Leap/Version/Mode)", HFILL }},
+ { &hf_ntp_flags_li, {
+ "Leap Indicator", "ntp.flags.li", FT_UINT8, BASE_DEC,
+ VALS(li_types), NTP_LI_MASK, "Leap Indicator", HFILL }},
+ { &hf_ntp_flags_vn, {
+ "Version number", "ntp.flags.vn", FT_UINT8, BASE_DEC,
+ VALS(ver_nums), NTP_VN_MASK, "Version number", HFILL }},
+ { &hf_ntp_flags_mode, {
+ "Mode", "ntp.flags.mode", FT_UINT8, BASE_DEC,
+ VALS(mode_types), NTP_MODE_MASK, "Mode", HFILL }},
+ { &hf_ntp_stratum, {
+ "Peer Clock Stratum", "ntp.stratum", FT_UINT8, BASE_DEC,
+ NULL, 0, "Peer Clock Stratum", HFILL }},
+ { &hf_ntp_ppoll, {
+ "Peer Polling Interval", "ntp.ppoll", FT_UINT8, BASE_DEC,
+ NULL, 0, "Peer Polling Interval", HFILL }},
+ { &hf_ntp_precision, {
+ "Peer Clock Precision", "ntp.precision", FT_INT8, BASE_DEC,
+ NULL, 0, "Peer Clock Precision", HFILL }},
+ { &hf_ntp_rootdelay, {
+ "Root Delay", "ntp.rootdelay", FT_DOUBLE, BASE_DEC,
+ NULL, 0, "Root Delay", HFILL }},
+ { &hf_ntp_rootdispersion, {
+ "Clock Dispersion", "ntp.rootdispersion", FT_DOUBLE, BASE_DEC,
+ NULL, 0, "Clock Dispersion", HFILL }},
+ { &hf_ntp_refid, {
+ "Reference Clock ID", "ntp.refid", FT_BYTES, BASE_NONE,
+ NULL, 0, "Reference Clock ID", HFILL }},
+ { &hf_ntp_reftime, {
+ "Reference Clock Update Time", "ntp.reftime", FT_BYTES, BASE_NONE,
+ NULL, 0, "Reference Clock Update Time", HFILL }},
+ { &hf_ntp_org, {
+ "Originate Time Stamp", "ntp.org", FT_BYTES, BASE_NONE,
+ NULL, 0, "Originate Time Stamp", HFILL }},
+ { &hf_ntp_rec, {
+ "Receive Time Stamp", "ntp.rec", FT_BYTES, BASE_NONE,
+ NULL, 0, "Receive Time Stamp", HFILL }},
+ { &hf_ntp_xmt, {
+ "Transmit Time Stamp", "ntp.xmt", FT_BYTES, BASE_NONE,
+ NULL, 0, "Transmit Time Stamp", HFILL }},
+ { &hf_ntp_keyid, {
+ "Key ID", "ntp.keyid", FT_BYTES, BASE_HEX,
+ NULL, 0, "Key ID", HFILL }},
+ { &hf_ntp_mac, {
+ "Message Authentication Code", "ntp.mac", FT_BYTES, BASE_HEX,
+ NULL, 0, "Message Authentication Code", HFILL }},
+
+ { &hf_ntp_ext, {
+ "Extension", "ntp.ext", FT_NONE, BASE_NONE,
+ NULL, 0, "Extension", HFILL }},
+ { &hf_ntp_ext_flags, {
+ "Flags", "ntp.ext.flags", FT_UINT8, BASE_HEX,
+ NULL, 0, "Flags (Response/Error/Version)", HFILL }},
+ { &hf_ntp_ext_flags_r, {
+ "Response bit", "ntp.ext.flags.r", FT_UINT8, BASE_DEC,
+ VALS(ext_r_types), NTP_EXT_R_MASK, "Response bit", HFILL }},
+ { &hf_ntp_ext_flags_error, {
+ "Error bit", "ntp.ext.flags.error", FT_UINT8, BASE_DEC,
+ NULL, NTP_EXT_ERROR_MASK, "Error bit", HFILL }},
+ { &hf_ntp_ext_flags_vn, {
+ "Version", "ntp.ext.flags.vn", FT_UINT8, BASE_DEC,
+ NULL, NTP_EXT_VN_MASK, "Version", HFILL }},
+ { &hf_ntp_ext_op, {
+ "Opcode", "ntp.ext.op", FT_UINT8, BASE_DEC,
+ VALS(ext_op_types), 0, "Opcode", HFILL }},
+ { &hf_ntp_ext_len, {
+ "Extension length", "ntp.ext.len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Extension length", HFILL }},
+ { &hf_ntp_ext_associd, {
+ "Association ID", "ntp.ext.associd", FT_UINT32, BASE_DEC,
+ NULL, 0, "Association ID", HFILL }},
+ { &hf_ntp_ext_tstamp, {
+ "Timestamp", "ntp.ext.tstamp", FT_UINT32, BASE_HEX,
+ NULL, 0, "Timestamp", HFILL }},
+ { &hf_ntp_ext_fstamp, {
+ "File Timestamp", "ntp.ext.fstamp", FT_UINT32, BASE_HEX,
+ NULL, 0, "File Timestamp", HFILL }},
+ { &hf_ntp_ext_vallen, {
+ "Value length", "ntp.ext.vallen", FT_UINT32, BASE_DEC,
+ NULL, 0, "Value length", HFILL }},
+ { &hf_ntp_ext_val, {
+ "Value", "ntp.ext.val", FT_BYTES, BASE_HEX,
+ NULL, 0, "Value", HFILL }},
+ { &hf_ntp_ext_siglen, {
+ "Signature length", "ntp.ext.siglen", FT_UINT32, BASE_DEC,
+ NULL, 0, "Signature length", HFILL }},
+ { &hf_ntp_ext_sig, {
+ "Signature", "ntp.ext.sig", FT_BYTES, BASE_HEX,
+ NULL, 0, "Signature", HFILL }},
+
+ { &hf_ntpctrl_flags2, {
+ "Flags 2", "ntpctrl.flags2", FT_UINT8, BASE_HEX,
+ NULL, 0, "Flags (Response/Error/More/Opcode)", HFILL }},
+ { &hf_ntpctrl_flags2_r, {
+ "Response bit", "ntpctrl.flags2.r", FT_UINT8, BASE_DEC,
+ VALS(ctrl_r_types), NTPCTRL_R_MASK, "Response bit", HFILL }},
+ { &hf_ntpctrl_flags2_error, {
+ "Error bit", "ntpctrl.flags2.error", FT_UINT8, BASE_DEC,
+ NULL, NTPCTRL_ERROR_MASK, "Error bit", HFILL }},
+ { &hf_ntpctrl_flags2_more, {
+ "More bit", "ntpctrl.flags2.more", FT_UINT8, BASE_DEC,
+ NULL, NTPCTRL_MORE_MASK, "More bit", HFILL }},
+ { &hf_ntpctrl_flags2_opcode, {
+ "Opcode", "ntpctrl.flags2.opcode", FT_UINT8, BASE_DEC,
+ VALS(ctrl_op_types), NTPCTRL_OP_MASK, "Opcode", HFILL }},
+
+ { &hf_ntppriv_flags_r, {
+ "Response bit", "ntppriv.flags.r", FT_UINT8, BASE_DEC,
+ VALS(priv_r_types), NTPPRIV_R_MASK, "Response bit", HFILL }},
+ { &hf_ntppriv_flags_more, {
+ "More bit", "ntppriv.flags.more", FT_UINT8, BASE_DEC,
+ NULL, NTPPRIV_MORE_MASK, "More bit", HFILL }},
+ { &hf_ntppriv_auth_seq, {
+ "Auth, sequence", "ntppriv.auth_seq", FT_UINT8, BASE_DEC,
+ NULL, 0, "Auth bit, sequence number", HFILL }},
+ { &hf_ntppriv_auth, {
+ "Auth bit", "ntppriv.auth", FT_UINT8, BASE_DEC,
+ NULL, NTPPRIV_AUTH_MASK, "Auth bit", HFILL }},
+ { &hf_ntppriv_seq, {
+ "Sequence number", "ntppriv.seq", FT_UINT8, BASE_DEC,
+ NULL, NTPPRIV_SEQ_MASK, "Sequence number", HFILL }},
+ { &hf_ntppriv_impl, {
+ "Implementation", "ntppriv.impl", FT_UINT8, BASE_DEC,
+ VALS(priv_impl_types), 0, "Implementation", HFILL }},
+ { &hf_ntppriv_reqcode, {
+ "Request code", "ntppriv.reqcode", FT_UINT8, BASE_DEC,
+ VALS(priv_rc_types), 0, "Request code", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ntp,
+ &ett_ntp_flags,
+ &ett_ntp_ext,
+ &ett_ntp_ext_flags,
+ &ett_ntpctrl_flags2,
+ &ett_ntppriv_auth_seq,
+ };
+
+ proto_ntp = proto_register_protocol("Network Time Protocol", "NTP",
+ "ntp");
+ proto_register_field_array(proto_ntp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ntp(void)
+{
+ dissector_handle_t ntp_handle;
+
+ ntp_handle = create_dissector_handle(dissect_ntp, proto_ntp);
+ dissector_add("udp.port", UDP_PORT_NTP, ntp_handle);
+ dissector_add("tcp.port", TCP_PORT_NTP, ntp_handle);
+}
diff --git a/epan/dissectors/packet-ntp.h b/epan/dissectors/packet-ntp.h
new file mode 100644
index 0000000000..889231aa21
--- /dev/null
+++ b/epan/dissectors/packet-ntp.h
@@ -0,0 +1,38 @@
+/* packet-ntp.h
+ * Definitions for packet disassembly structures and routines
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ * Joerg Mayer <jmayer@loplof.de>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This is from yahoolib.h from gtkyahoo */
+
+#ifndef PACKET_NTP_H
+#define PACKET_NTP_H
+
+/* NTP_BASETIME is infact epoch - ntp_start_time */
+#define NTP_BASETIME 2208988800ul
+#define NTP_TS_SIZE 100
+
+extern char * ntp_fmt_ts(const guint8 *reftime, char* buff);
+
+#endif
diff --git a/epan/dissectors/packet-null.c b/epan/dissectors/packet-null.c
new file mode 100644
index 0000000000..cf0dc20af6
--- /dev/null
+++ b/epan/dissectors/packet-null.c
@@ -0,0 +1,487 @@
+/* packet-null.c
+ * Routines for null packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ *
+ * This file created by Mike Hall <mlh@io.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <string.h>
+#include <epan/packet.h>
+#include "packet-null.h"
+#include <epan/atalk-utils.h>
+#include "prefs.h"
+#include "packet-ip.h"
+#include "packet-ipx.h"
+#include "packet-osi.h"
+#include "packet-ppp.h"
+#include "etypes.h"
+#include "aftypes.h"
+
+static dissector_table_t null_dissector_table;
+
+/* protocols and header fields */
+static int proto_null = -1;
+static int hf_null_etype = -1;
+static int hf_null_family = -1;
+
+static gint ett_null = -1;
+
+/* Null/loopback structs and definitions */
+
+/* Family values. */
+static const value_string family_vals[] = {
+ {BSD_AF_INET, "IP" },
+ {BSD_AF_ISO, "OSI" },
+ {BSD_AF_APPLETALK, "Appletalk" },
+ {BSD_AF_IPX, "Netware IPX/SPX"},
+ {BSD_AF_INET6_BSD, "IPv6" },
+ {BSD_AF_INET6_FREEBSD, "IPv6" },
+ {BSD_AF_INET6_DARWIN, "IPv6" },
+ {0, NULL }
+};
+
+static dissector_handle_t ppp_hdlc_handle;
+static dissector_handle_t data_handle;
+void
+capture_null( const guchar *pd, int len, packet_counts *ld )
+{
+ guint32 null_header;
+
+ /*
+ * BSD drivers that use DLT_NULL - including the FreeBSD 3.2 ISDN-for-BSD
+ * drivers, as well as the 4.4-Lite and FreeBSD loopback drivers -
+ * stuff the AF_ value for the protocol, in *host* byte order, in the
+ * first four bytes. (BSD drivers that use DLT_LOOP, such as recent
+ * OpenBSD loopback drivers, stuff it in *network* byte order in the
+ * first four bytes.)
+ *
+ * However, the IRIX and UNICOS/mp snoop socket mechanism supplies,
+ * on loopback devices, a 4-byte header that has a 2 byte (big-endian)
+ * AF_ value and 2 bytes of 0, so it's
+ *
+ * 0000AAAA
+ *
+ * when read on a little-endian machine and
+ *
+ * AAAA0000
+ *
+ * when read on a big-endian machine. The current CVS version of libpcap
+ * compensates for this by converting it to standard 4-byte format before
+ * processing the packet, but snoop captures from IRIX or UNICOS/mp
+ * have the 2-byte+2-byte header, as might tcpdump or libpcap captures
+ * with older versions of libpcap.
+ *
+ * AF_ values are small integers, and probably fit in 8 bits (current
+ * values on the BSDs do), and have their upper 24 bits zero.
+ * This means that, in practice, if you look at the header as a 32-bit
+ * integer in host byte order:
+ *
+ * on a little-endian machine:
+ *
+ * a little-endian DLT_NULL header looks like
+ *
+ * 000000AA
+ *
+ * a big-endian DLT_NULL header, or a DLT_LOOP header, looks
+ * like
+ *
+ * AA000000
+ *
+ * an IRIX or UNICOS/mp DLT_NULL header looks like
+ *
+ * 0000AA00
+ *
+ * on a big-endian machine:
+ *
+ * a big-endian DLT_NULL header, or a DLT_LOOP header, looks
+ * like
+ *
+ * 000000AA
+ *
+ * a little-endian DLT_NULL header looks like
+ *
+ * AA000000
+ *
+ * an IRIX or UNICOS/mp DLT_NULL header looks like
+ *
+ * 00AA0000
+ *
+ * However, according to Gerald Combs, a FreeBSD ISDN PPP dump that
+ * Andreas Klemm sent to ethereal-dev has a packet type of DLT_NULL,
+ * and the family bits look like PPP's protocol field. (Was this an
+ * older, or different, ISDN driver?) Looking at what appears to be
+ * that capture file, it appears that it's using PPP in HDLC framing,
+ * RFC 1549, wherein the first two octets of the frame are 0xFF
+ * (address) and 0x03 (control), so the header bytes are, in order:
+ *
+ * 0xFF
+ * 0x03
+ * high-order byte of a PPP protocol field
+ * low-order byte of a PPP protocol field
+ *
+ * If we treat that as a 32-bit host-byte-order value, it looks like
+ *
+ * PPPP03FF
+ *
+ * where PPPP is a byte-swapped PPP protocol type if we read it on
+ * a little-endian machine and
+ *
+ * FF03PPPP
+ *
+ * where PPPP is a PPP protocol type if we read it on a big-endian
+ * machine. 0x0000 does not appear to be a valid PPP protocol type
+ * value, so at least one of those hex digits is guaranteed not to
+ * be 0.
+ *
+ * Old versions of libpcap for Linux used DLT_NULL for loopback devices,
+ * but not any other devices. (Current versions use DLT_EN10MB for it.)
+ * The Linux loopback driver puts an *Ethernet* header at the beginning
+ * of loopback packets, with fake source and destination addresses and
+ * the appropriate Ethernet type value; however, those older versions of
+ * libpcap for Linux compensated for this by skipping the source and
+ * destination MAC addresses, replacing them with 2 bytes of 0.
+ * This means that if we're reading the capture on a little-endian
+ * machine, the header, treated as a 32-bit integer, looks like
+ *
+ * EEEE0000
+ *
+ * where EEEE is a byte-swapped Ethernet type, and if we're reading it
+ * on a big-endian machine, it looks like
+ *
+ * 0000EEEE
+ *
+ * where EEEE is an Ethernet type.
+ *
+ * If the first 2 bytes of the header are FF 03:
+ *
+ * it can't be a big-endian BSD DLT_NULL header, or a DLT_LOOP
+ * header, as AF_ values are small so the first 2 bytes of the
+ * header would be 0;
+ *
+ * it can't be a little-endian BSD DLT_NULL header, as the
+ * resulting AF_ value would be >= 0x03FF, which is too big
+ * for an AF_ value;
+ *
+ * it can't be an IRIX or UNICOS/mp DLT_NULL header, as the
+ * resulting AF_ value with be 0x03FF.
+ *
+ * So the first thing we do is check the first two bytes of the
+ * header; if it's FF 03, we treat the packet as a PPP frame.
+ *
+ * Otherwise, if the upper 16 bits are non-zero, either:
+ *
+ * it's a BSD DLT_NULL or DLT_LOOP header whose AF_ value
+ * is not in our byte order;
+ *
+ * it's an IRIX or UNICOS/mp DLT_NULL header being read on
+ * a big-endian machine;
+ *
+ * it's a Linux DLT_NULL header being read on a little-endian
+ * machine.
+ *
+ * In all those cases except for the IRIX or UNICOS/mp DLT_NULL header,
+ * we should byte-swap it (if it's a Linux DLT_NULL header, that'll
+ * put the Ethernet type in the right byte order). In the case
+ * of the IRIX or UNICOS/mp DLT_NULL header, we should just get
+ * the upper 16 bits as an AF_ value.
+ *
+ * If it's a BSD DLT_NULL or DLT_LOOP header whose AF_ value is not
+ * in our byte order, then the upper 2 hex digits would be non-zero
+ * and the next 2 hex digits down would be zero, as AF_ values fit in
+ * 8 bits, and the upper 2 hex digits are the *lower* 8 bits of the value.
+ *
+ * If it's an IRIX or UNICOS/mp DLT_NULL header, the upper 2 hex digits
+ * would be zero and the next 2 hex digits down would be non-zero, as
+ * the upper 16 bits are a big-endian AF_ value. Furthermore, the
+ * next 2 hex digits down are likely to be < 0x60, as 0x60 is 96,
+ * and, so far, we're far from requiring AF_ values that high.
+ *
+ * If it's a Linux DLT_NULL header, the third hex digit from the top
+ * will be >= 6, as Ethernet types are >= 1536, or 0x0600, and
+ * it's byte-swapped, so the second 2 hex digits from the top are
+ * >= 0x60.
+ *
+ * So, if the upper 16 bits are non-zero:
+ *
+ * if the upper 2 hex digits are 0 and the next 2 hex digits are
+ * in the range 0x00-0x5F, we treat it as a big-endian IRIX or
+ * UNICOS/mp DLT_NULL header;
+ *
+ * otherwise, we byte-swap it and do the next stage.
+ *
+ * If the upper 16 bits are zero, either:
+ *
+ * it's a BSD DLT_NULLor DLT_LOOP header whose AF_ value is in
+ * our byte order;
+ *
+ * it's an IRIX or UNICOS/mp DLT_NULL header being read on
+ * a little-endian machine;
+ *
+ * it's a Linux DLT_NULL header being read on a big-endian
+ * machine.
+ *
+ * In all of those cases except for the IRIX or UNICOS/mp DLT_NULL header,
+ * we should *not* byte-swap it. In the case of the IRIX or UNICOS/mp
+ * DLT_NULL header, we should extract the AF_ value and byte-swap it.
+ *
+ * If it's a BSD DLT_NULL or DLT_LOOP header whose AF_ value is
+ * in our byte order, the upper 6 hex digits would all be zero.
+ *
+ * If it's an IRIX or UNICOS/mp DLT_NULL header, the upper 4 hex
+ * digits would be zero and the next 2 hex digits would not be zero.
+ * Furthermore, the third hex digit from the bottom would be <
+ */
+ if (!BYTES_ARE_IN_FRAME(0, len, 2)) {
+ ld->other++;
+ return;
+ }
+ if (pd[0] == 0xFF && pd[1] == 0x03) {
+ /*
+ * Hand it to PPP.
+ */
+ capture_ppp_hdlc(pd, 0, len, ld);
+ } else {
+ /*
+ * Treat it as a normal DLT_NULL header.
+ */
+ if (!BYTES_ARE_IN_FRAME(0, len, (int)sizeof(null_header))) {
+ ld->other++;
+ return;
+ }
+ memcpy((char *)&null_header, (const char *)&pd[0], sizeof(null_header));
+
+ if ((null_header & 0xFFFF0000) != 0) {
+ /*
+ * It is possible that the AF_ type was only a 16 bit value.
+ * IRIX and UNICOS/mp loopback snoop use a 4 byte header with
+ * AF_ type in the first 2 bytes!
+ * BSD AF_ types will always have the upper 8 bits as 0.
+ */
+ if ((null_header & 0xFF000000) == 0 &&
+ (null_header & 0x00FF0000) < 0x00060000) {
+ /*
+ * Looks like a IRIX or UNICOS/mp loopback header, in the
+ * correct byte order. Set the null header value to the
+ * AF_ type, which is in the upper 16 bits of "null_header".
+ */
+ null_header >>= 16;
+ } else {
+ /* Byte-swap it. */
+ null_header = BSWAP32(null_header);
+ }
+ } else {
+ /*
+ * Check for an IRIX or UNICOS/mp snoop header.
+ */
+ if ((null_header & 0x000000FF) == 0 &&
+ (null_header & 0x0000FF00) < 0x00000600) {
+ /*
+ * Looks like a IRIX or UNICOS/mp loopback header, in the
+ * wrong byte order. Set the null header value to the AF_
+ * type; that's in the lower 16 bits of "null_header", but
+ * is byte-swapped.
+ */
+ null_header = BSWAP16(null_header & 0xFFFF);
+ }
+ }
+
+ /*
+ * The null header value must be greater than the IEEE 802.3 maximum
+ * frame length to be a valid Ethernet type; if it is, hand it
+ * to "ethertype()", otherwise treat it as a BSD AF_type (we wire
+ * in the values of the BSD AF_ types, because the values
+ * in the file will be BSD values, and the OS on which
+ * we're building this might not have the same values or
+ * might not have them defined at all; XXX - what if different
+ * BSD derivatives have different values?).
+ */
+ if (null_header > IEEE_802_3_MAX_LEN)
+ capture_ethertype((guint16) null_header, pd, 4, len, ld);
+ else {
+
+ switch (null_header) {
+
+ case BSD_AF_INET:
+ capture_ip(pd, 4, len, ld);
+ break;
+
+ default:
+ ld->other++;
+ break;
+ }
+ }
+ }
+}
+
+static void
+dissect_null(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 null_header;
+ proto_tree *fh_tree;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+
+ /*
+ * See comment in "capture_null()" for an explanation of what we're
+ * doing.
+ */
+ if (tvb_get_ntohs(tvb, 0) == 0xFF03) {
+ /*
+ * Hand it to PPP.
+ */
+ call_dissector(ppp_hdlc_handle, tvb, pinfo, tree);
+ } else {
+
+ /* load the top pane info. This should be overwritten by
+ the next protocol in the stack */
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A" );
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A" );
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "N/A" );
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Null/Loopback" );
+
+ /*
+ * Treat it as a normal DLT_NULL header.
+ */
+ tvb_memcpy(tvb, (guint8 *)&null_header, 0, sizeof(null_header));
+
+ if ((null_header & 0xFFFF0000) != 0) {
+ /*
+ * It is possible that the AF_ type was only a 16 bit value.
+ * IRIX and UNICOS/mp loopback snoop use a 4 byte header with
+ * AF_ type in the first 2 bytes!
+ * BSD AF_ types will always have the upper 8 bits as 0.
+ */
+ if ((null_header & 0xFF000000) == 0 &&
+ (null_header & 0x00FF0000) < 0x00060000) {
+ /*
+ * Looks like a IRIX or UNICOS/mp loopback header, in the
+ * correct byte order. Set the null header value to the
+ * AF_ type, which is in the upper 16 bits of "null_header".
+ */
+ null_header >>= 16;
+ } else {
+ /* Byte-swap it. */
+ null_header = BSWAP32(null_header);
+ }
+ } else {
+ /*
+ * Check for an IRIX or UNICOS/mp snoop header.
+ */
+ if ((null_header & 0x000000FF) == 0 &&
+ (null_header & 0x0000FF00) < 0x00000600) {
+ /*
+ * Looks like a IRIX or UNICOS/mp loopback header, in the
+ * wrong byte order. Set the null header value to the AF_
+ * type; that's in the lower 16 bits of "null_header", but
+ * is byte-swapped.
+ */
+ null_header = BSWAP16(null_header & 0xFFFF);
+ }
+ }
+
+ /*
+ * The null header value must be greater than the IEEE 802.3 maximum
+ * frame length to be a valid Ethernet type; if it is, hand it
+ * to "ethertype()", otherwise treat it as a BSD AF_type (we wire
+ * in the values of the BSD AF_ types, because the values
+ * in the file will be BSD values, and the OS on which
+ * we're building this might not have the same values or
+ * might not have them defined at all; XXX - what if different
+ * BSD derivatives have different values?).
+ */
+ if (null_header > IEEE_802_3_MAX_LEN) {
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_null, tvb, 0, 4, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_null);
+ } else
+ fh_tree = NULL;
+ ethertype((guint16) null_header, tvb, 4, pinfo, tree, fh_tree, hf_null_etype, -1,
+ 0);
+ } else {
+ /* populate a tree in the second pane with the status of the link
+ layer (ie none) */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_null, tvb, 0, 4, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_null);
+ proto_tree_add_uint(fh_tree, hf_null_family, tvb, 0, 4, null_header);
+ }
+
+ next_tvb = tvb_new_subset(tvb, 4, -1, -1);
+ if (!dissector_try_port(null_dissector_table, null_header,
+ next_tvb, pinfo, tree)) {
+ /* No sub-dissector found. Label rest of packet as "Data" */
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+ }
+ }
+}
+
+void
+proto_register_null(void)
+{
+ static hf_register_info hf[] = {
+
+ /* registered here but handled in ethertype.c */
+ { &hf_null_etype,
+ { "Type", "null.type", FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_null_family,
+ { "Family", "null.family", FT_UINT32, BASE_DEC, VALS(family_vals), 0x0,
+ "", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_null,
+ };
+
+ proto_null = proto_register_protocol("Null/Loopback", "Null", "null");
+ proto_register_field_array(proto_null, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ null_dissector_table = register_dissector_table("null.type",
+ "BSD AF_ type", FT_UINT32, BASE_DEC);
+}
+
+void
+proto_reg_handoff_null(void)
+{
+ dissector_handle_t null_handle;
+
+ /*
+ * Get a handle for the PPP-in-HDLC-like-framing dissector.
+ */
+ ppp_hdlc_handle = find_dissector("ppp_hdlc");
+ data_handle = find_dissector("data");
+ null_handle = create_dissector_handle(dissect_null, proto_null);
+ dissector_add("wtap_encap", WTAP_ENCAP_NULL, null_handle);
+}
diff --git a/epan/dissectors/packet-null.h b/epan/dissectors/packet-null.h
new file mode 100644
index 0000000000..88eb16e46b
--- /dev/null
+++ b/epan/dissectors/packet-null.h
@@ -0,0 +1,29 @@
+/* packet-null.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_NULL_H__
+#define __PACKET_NULL_H__
+
+void capture_null(const guchar *, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-olsr.c b/epan/dissectors/packet-olsr.c
new file mode 100644
index 0000000000..a3739ddfe3
--- /dev/null
+++ b/epan/dissectors/packet-olsr.c
@@ -0,0 +1,683 @@
+/* packet-olsr.c
+ * Routines for OLSR (IPv4 & IPv6 compatible) RFC parsing
+ * Compatible with RFC-compliant OLSR implementations such as
+ * NRLOLSRD (http://pf.itd.nrl.navy.mil/projects/olsr/).
+ * Parser created by Aaron Woo <woo@itd.nrl.navy.mil> of
+ * the Naval Research Laboratory
+ * Currently maintained by Jeff Weston <weston@itd.nrl.navy.mil>.
+ *
+ * http://www.ietf.org/rfc/rfc3626.txt
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/ipv6-utils.h>
+
+#define UDP_PORT_OLSR 698
+#define HELLO 1
+#define TC 2
+#define MID 3
+#define HNA 4
+
+/* Initialize the protocol and registered fields */
+static int proto_olsr = -1;
+static int hf_olsr_packet_len = -1;
+static int hf_olsr_packet_seq_num = -1;
+static int hf_olsr_message_type = -1;
+static int hf_olsr_vtime = -1;
+static int hf_olsr_message_size = -1;
+static int hf_olsr_ttl = -1;
+static int hf_olsr_hop_count = -1;
+static int hf_olsr_message_seq_num = -1;
+
+static int hf_olsr_htime = -1;
+static int hf_olsr_willingness = -1;
+
+static int hf_olsr_link_type = -1;
+static int hf_olsr_link_message_size = -1;
+static int hf_olsr_ansn = -1;
+
+static int hf_olsr_origin_addr = -1;
+static int hf_olsr_neighbor_addr = -1;
+static int hf_olsr_interface_addr = -1;
+static int hf_olsr_netmask = -1;
+static int hf_olsr_network_addr = -1;
+static int hf_olsr_origin6_addr = -1;
+static int hf_olsr_neighbor6_addr = -1;
+static int hf_olsr_interface6_addr = -1;
+static int hf_olsr_netmask6 = -1;
+static int hf_olsr_network6_addr = -1;
+
+/* Initialize the subtree pointers*/
+static gint ett_olsr = -1;
+
+static const value_string message_type_vals[] = {
+ { HELLO, "HELLO" },
+ { TC, "TC" },
+ { MID, "MID" },
+ { HNA, "HNA" },
+ { 0, NULL }
+};
+
+/*------------------------- Packet Dissecting Code-------------------------*/
+static int
+dissect_olsr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *olsr_tree;
+
+ int offset, link_message_size, message_size, message_type, packet_size, position;
+ int high_bits, low_bits, vtime, htime;
+ double Vtime, Htime;
+
+ guint16 packet_len;
+
+ guint32 origin_addr;
+ guint32 neighbor_addr;
+ guint32 interface_addr;
+ guint32 network_addr;
+ guint32 netmask;
+ struct e_in6_addr origin6_addr, *origin=&origin6_addr;
+ struct e_in6_addr neighbor6_addr, *neighbor=&neighbor6_addr;
+ struct e_in6_addr interface6_addr, *theinterface=&interface6_addr;
+ struct e_in6_addr network6_addr, *network=&network6_addr;
+ struct e_in6_addr netmask6, *netmask_v6=&netmask6;
+
+
+ /* Does this packet have a valid message type at the beginning? */
+ if (!tvb_bytes_exist(tvb, 0, 2))
+ return 0; /* not enough bytes for the packet length */
+ packet_len = tvb_get_ntohs(tvb, 0);
+ if (packet_len < 4)
+ return 0; /* length not enough for a packet header */
+ if (packet_len > 4) {
+ /*
+ * The packet claims to have more than just a packet
+ * header.
+ */
+ if (packet_len < 8) {
+ /*
+ * ...but it doesn't claim to have enough for
+ * a full message header.
+ */
+ return 0;
+ }
+
+ /*
+ * OK, let's look at the type of the first message and
+ * at its size field.
+ */
+ if (!tvb_bytes_exist(tvb, 4, 4))
+ return 0; /* not enough bytes for them */
+ message_type = tvb_get_guint8(tvb, 4);
+ if (match_strval(message_type, message_type_vals) == NULL)
+ return 0; /* not valid */
+ /* OK, what about the message length? */
+ message_size = tvb_get_ntohs(tvb, 4+2);
+ if (message_size < 4)
+ return 0; /* length not enough for a message header */
+ }
+
+ /*-------------Setting the Protocol and Info Columns in the Ethereal Display----------*/
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && (pinfo->src.type==AT_IPv4))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "OLSR (IPv4) Packet, Length: %u Bytes", packet_len);
+ else if(check_col(pinfo->cinfo, COL_INFO) && (pinfo->src.type==AT_IPv6))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "OLSR (IPv6) Packet, Length: %u Bytes", packet_len);
+
+/*-----------------------------------------------------Fetching Info from IPv4 Packet and Adding to Tree-------------------------------------------*/
+ if (tree && (pinfo->src.type==AT_IPv4)) {
+ ti = proto_tree_add_item(tree, proto_olsr, tvb, 0, -1, FALSE);
+ olsr_tree = proto_item_add_subtree(ti, ett_olsr);
+
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_packet_len, tvb, 0, 2, packet_len, "Packet Length: %u bytes", packet_len);
+ proto_tree_add_item(olsr_tree, hf_olsr_packet_seq_num, tvb, 2, 2, FALSE);
+
+ packet_size = (packet_len - 4) / 4;
+ position = 4;
+
+ while(packet_size>0) {
+ message_type = tvb_get_guint8(tvb, position);
+ proto_tree_add_uint(olsr_tree, hf_olsr_message_type, tvb, position, 1, message_type);
+
+ /*-------------Dissect Validity Time-------------------------*/
+ vtime = tvb_get_guint8(tvb, position+1);
+ high_bits = ((vtime & 0xF0) >> 4);
+ low_bits = (vtime & 0x0F);
+ Vtime = ((1<<low_bits)/16.0)*(1+(high_bits/16.0));
+ proto_tree_add_double_format(olsr_tree, hf_olsr_vtime, tvb, position+1, 1, Vtime, "Validity Time: %.3f (in seconds)", Vtime);
+
+ /*-------------Dissect Message Size---------------------------*/
+ message_size = tvb_get_ntohs(tvb, position+2);
+ if (message_size < 4) {
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_message_size, tvb, position+2, 2, message_size,"Message Size: %u bytes (too short, must be >= 4)", message_size);
+ break;
+ }
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_message_size, tvb, position+2, 2, message_size,"Message Size: %u bytes", message_size);
+
+ packet_size--;
+ message_size = (message_size - 4) /4;
+ offset = position + 4;
+ position = offset;
+
+ /*-----------------Dissecting: Origin Addr, TTL, Hop Count, and Message Seq Number*/
+ if(message_size > 0) {
+ tvb_memcpy(tvb, (guint8*)&origin_addr, offset, 4);
+ proto_tree_add_ipv4(olsr_tree, hf_olsr_origin_addr, tvb, offset, 4, origin_addr);
+ message_size--;
+ packet_size--;
+ offset+=4;
+ }
+ if(message_size > 0) {
+ proto_tree_add_item(olsr_tree, hf_olsr_ttl, tvb, offset, 1, FALSE);
+ proto_tree_add_item(olsr_tree, hf_olsr_hop_count, tvb, offset+1, 1, FALSE);
+ proto_tree_add_item(olsr_tree, hf_olsr_message_seq_num, tvb, offset+2, 2, FALSE);
+ message_size--;
+ packet_size--;
+ offset+=4;
+ }
+
+ position = offset;
+
+ /* --------------Dissecting TC message--------------------- */
+ if(message_size>0 && message_type == TC) {
+ proto_tree_add_item(olsr_tree, hf_olsr_ansn, tvb, offset, 2, FALSE);
+
+ offset+=4;
+ message_size--;
+ packet_size--;
+
+ while(message_size>0) {
+ tvb_memcpy(tvb, (guint8*)&neighbor_addr, offset, 4);
+ proto_tree_add_ipv4(olsr_tree, hf_olsr_neighbor_addr, tvb, offset, 4, neighbor_addr);
+ message_size--;
+ offset+=4;
+ packet_size--;
+ }
+ position = offset;
+ }
+
+ /* -------------Dissect HELLO message----------------------- */
+ else if(message_size>0 && message_type == HELLO) {
+ /*---------------------Dissect Hello Emission Invertal-------------------*/
+ htime = tvb_get_guint8(tvb, offset+2);
+ high_bits = ((htime & 0xF0) >> 4);
+ low_bits = (htime & 0x0F);
+ Htime = ((1<<low_bits)/16.0)*(1+(high_bits/16.0));
+ proto_tree_add_double_format(olsr_tree, hf_olsr_htime, tvb, offset+2, 1, Htime, "Hello Emission Interval: %.3f (in seconds)", Htime);
+
+ /*-------------------------Dissect Willingness---------------------------*/
+ switch(tvb_get_guint8(tvb, offset+3)) {
+ case 0:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Never");
+ break;
+ case 1:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Low");
+ break;
+ case 3:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Default");
+ break;
+ case 6:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: High");
+ break;
+ case 7:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Always");
+ break;
+ default :
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Invalid!");
+ break;
+ }/* end switch Willingness */
+
+ offset+=4;
+ message_size--;
+ packet_size--;
+
+ while(message_size>0) {
+ /*------------------------------Dissect Link Type---------------------------------- */
+ switch(tvb_get_guint8(tvb, offset)) {
+ case 0:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Unspecified Link");
+ break;
+ case 1:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Asymmetric Link");
+ break;
+ case 6:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Symmetric Link");
+ break;
+ case 3:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Lost Link");
+ break;
+ case 10:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: MPR Link");
+ break;
+ case 5:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Pending");
+ break;
+ default:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Invalid");
+ break;
+ }/* end switch Link Type */
+
+ /*----------------------Dissect Link Message Size--------------------------*/
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_message_size, tvb, offset+2, 2, tvb_get_ntohs(tvb, offset+2), "Link Message Size: %u bytes", tvb_get_ntohs(tvb, offset+2));
+
+ link_message_size = (tvb_get_ntohs(tvb, offset+2) - 4) / 4;
+ offset+=4;
+ message_size--;
+ packet_size--;
+
+ /*-------------------Dissect Neighbor Addresses--------------------*/
+ while(link_message_size>0) {
+ tvb_memcpy(tvb, (guint8*)&neighbor_addr, offset, 4);
+ proto_tree_add_ipv4(olsr_tree, hf_olsr_neighbor_addr, tvb, offset, 4, neighbor_addr);
+ offset+=4;
+ message_size--;
+ packet_size--;
+ link_message_size--;
+ } /* end while */
+ } /* end while */
+ position = offset;
+ } /* end if for Hello */
+ /*---------------------------------Dissect MID Message----------------------------------*/
+ else if(message_size>0 && message_type==MID) {
+ while(message_size>0) {
+ tvb_memcpy(tvb, (guint8*)&interface_addr, offset, 4);
+ proto_tree_add_ipv4(olsr_tree, hf_olsr_interface_addr, tvb, offset, 4, interface_addr);
+ message_size--;
+ offset+=4;
+ packet_size--;
+ } /* end while for MID */
+ position = offset;
+ } /* end if for MID */
+ /*-----------------------------Dissect HNA Message--------------------------------*/
+ else if(message_size>0 && message_type==HNA) {
+ while(message_size>0) {
+ tvb_memcpy(tvb, (guint8*)&network_addr, offset, 4);
+ proto_tree_add_ipv4(olsr_tree, hf_olsr_network_addr, tvb, offset, 4, network_addr);
+ message_size--;
+ packet_size--;
+ offset+=4;
+ tvb_memcpy(tvb, (guint8*)&netmask, offset, 4);
+ proto_tree_add_ipv4(olsr_tree, hf_olsr_netmask, tvb, offset, 4, netmask);
+ message_size--;
+ packet_size--;
+ offset+=4;
+ } /* end while for HNA */
+ position = offset;
+ } /* end if for HNA */
+
+ } /* end while for message alive */
+ } /* end if for IPV4 */
+
+
+/*-----------------------------------------------------Fetching Info from IPv6 Packet and Adding to Tree-------------------------------------------------*/
+ if (tree && (pinfo->src.type==AT_IPv6)) {
+ ti = proto_tree_add_item(tree, proto_olsr, tvb, 0, -1, FALSE);
+ olsr_tree = proto_item_add_subtree(ti, ett_olsr);
+
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_packet_len, tvb, 0, 2, packet_len, "Packet Length: %u bytes", packet_len);
+ proto_tree_add_item(olsr_tree, hf_olsr_packet_seq_num, tvb, 2, 2, FALSE);
+
+
+ packet_size = (packet_len - 4) / 4;
+ position = 4;
+
+ while(packet_size>0) {
+ message_type = tvb_get_guint8(tvb, position);
+ proto_tree_add_uint(olsr_tree, hf_olsr_message_type, tvb, position, 1, message_type);
+
+ /*-------------Dissect Validity Time-------------------------*/
+ vtime = tvb_get_guint8(tvb, position+1);
+ high_bits = ((vtime & 0xF0) >> 4);
+ low_bits = (vtime & 0x0F);
+ Vtime = ((1<<low_bits)/16.0)*(1.0+(high_bits/16.0));
+ proto_tree_add_double_format(olsr_tree, hf_olsr_vtime, tvb, position+1, 1, Vtime, "Validity Time: %.3f (in seconds)", Vtime);
+
+ /*-------------Dissect Message Size---------------------------*/
+ message_size = tvb_get_ntohs(tvb, position+2);
+ if (message_size < 4) {
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_message_size, tvb, position+2, 2, message_size,"Message Size: %u bytes (too short, must be >= 4)", message_size);
+ break;
+ }
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_message_size, tvb, position+2, 2, message_size,"Message Size: %u bytes", message_size);
+
+ packet_size--;
+ message_size = (message_size - 4) /4;
+
+ offset = position + 4;
+ position = offset;
+
+ /*-----------------Dissecting: Origin Addr, TTL, Hop Count, and Message Seq Number */
+ if(message_size > 0) {
+ tvb_memcpy(tvb, (guint8*)&origin6_addr, offset, 16);
+ proto_tree_add_ipv6(olsr_tree, hf_olsr_origin6_addr, tvb, offset, 16, (guint8*)origin);
+ offset+=16;
+ message_size-=4;
+ packet_size-=4;
+ }
+ if(message_size > 0) {
+ proto_tree_add_item(olsr_tree, hf_olsr_ttl, tvb, offset, 1, FALSE);
+ proto_tree_add_item(olsr_tree, hf_olsr_hop_count, tvb, offset+1, 1, FALSE);
+ proto_tree_add_item(olsr_tree, hf_olsr_message_seq_num, tvb, offset+2, 2, FALSE);
+ message_size--;
+ packet_size--;
+ offset+=4;
+ }
+
+ position = offset;
+
+ /* --------------Dissecting TC message--------------------- */
+ if(message_size>0 && message_type == TC) {
+ proto_tree_add_item(olsr_tree, hf_olsr_ansn, tvb, offset, 2, FALSE);
+
+ offset+=4;
+ message_size--;
+ packet_size--;
+
+ while(message_size>0) {
+ tvb_memcpy(tvb, (guint8*)&neighbor6_addr, offset, 16);
+ proto_tree_add_ipv6(olsr_tree, hf_olsr_neighbor6_addr, tvb, offset, 16, (guint8*)neighbor);
+ message_size-=4;
+ offset+=16;
+ packet_size-=4;
+ }
+ position = offset;
+ }
+
+ /* -------------Dissect HELLO message----------------------- */
+ else if(message_size>0 && message_type == HELLO) {
+ /*---------------------Dissect Hellow Emission Invertal-------------------*/
+ htime = tvb_get_guint8(tvb, offset+2);
+ high_bits = ((htime & 0xF0) >> 4);
+ low_bits = (htime & 0x0F);
+ Htime = ((1<<low_bits)/16.0)*(1.0+(high_bits/16.0));
+ proto_tree_add_double_format(olsr_tree, hf_olsr_htime, tvb, offset+2, 1, Htime, "Hello Emission Interval: %.3f (in seconds)", Htime);
+
+ /*---------------------Dissect Willingness----------------------------------*/
+ switch(tvb_get_guint8(tvb, offset+3)) {
+ case 0:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Never");
+ break;
+ case 1:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Low");
+ break;
+ case 3:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Default");
+ break;
+ case 6:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: High");
+ break;
+ case 7:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Always");
+ break;
+ default :
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_willingness, tvb, offset+3, 1, tvb_get_guint8(tvb, offset+2), "Willingness: Invalid!");
+ break;
+ } /* end switch for willingness */
+
+ offset+=4;
+ message_size--;
+ packet_size--;
+
+ while(message_size>0) {
+ /*----------------------Dissect Link Type------------------------------------*/
+ switch(tvb_get_guint8(tvb, offset)) {
+ case 0:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Unspecified Link");
+ break;
+ case 1:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Asymmetric Link");
+ break;
+ case 6:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Symmetric Link");
+ break;
+ case 3:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Lost Link");
+ break;
+ case 10:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: MPR Link");
+ break;
+ case 5:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Pending");
+ break;
+ default:
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_type, tvb, offset, 1, tvb_get_guint8(tvb, offset), "Link Type: Invalid");
+ break;
+ } /* end switch Link Type */
+
+ /*-------------------------Dissect Link Message Size-----------------------------*/
+ proto_tree_add_uint_format(olsr_tree, hf_olsr_link_message_size, tvb, offset+2, 2, tvb_get_ntohs(tvb, offset+2), "Link Message Size: %u bytes", tvb_get_ntohs(tvb, offset+2));
+
+ link_message_size = (tvb_get_ntohs(tvb, offset+2) - 4) / 4;
+ offset+=4;
+ message_size--;
+ packet_size--;
+
+ /*--------------------------Dissect Neighbor Addresses---------------------------*/
+ while(link_message_size>0) {
+ tvb_memcpy(tvb, (guint8*)&neighbor6_addr, offset, 16);
+ proto_tree_add_ipv6(olsr_tree, hf_olsr_neighbor6_addr, tvb, offset, 16, (guint8*)neighbor);
+ offset+=16;
+ message_size-=4;
+ packet_size-=4;
+ link_message_size-=4;
+ } /* end while */
+ } /* end while */
+ position = offset;
+ } /* end if for Hello */
+ /*---------------------------------Dissect MID Message----------------------------------*/
+ else if(message_size>0 && message_type==MID) {
+ while(message_size>0) {
+ tvb_memcpy(tvb, (guint8*)&interface6_addr, offset, 16);
+ proto_tree_add_ipv6(olsr_tree, hf_olsr_interface6_addr, tvb, offset, 16, (guint8*)theinterface);
+ message_size-=4;
+ offset+=16;
+ packet_size-=4;
+ } /* end while for MID */
+ position = offset;
+ } /* end if for MID */
+ /*-----------------------------Dissect HNA Message--------------------------------*/
+ else if(message_size>0 && message_type==HNA) {
+ while(message_size>0) {
+ tvb_memcpy(tvb, (guint8*)&network6_addr, offset, 16);
+ proto_tree_add_ipv6(olsr_tree, hf_olsr_network6_addr, tvb, offset, 16, (guint8*)network);
+ offset+=16;
+ message_size-=4;
+ packet_size-=4;
+ tvb_memcpy(tvb, (guint8*)&netmask6, offset, 16);
+ proto_tree_add_ipv6(olsr_tree, hf_olsr_netmask6, tvb, offset, 16, (guint8*)netmask_v6);
+ message_size-=4;
+ packet_size-=4;
+ offset+=16;
+ } /* end while for HNA */
+ position = offset;
+ } /* end if for HNA */
+ } /* end while for message alive */
+ } /* end if for IPV6 */
+ return tvb_length(tvb);
+} /* end Dissecting */
+
+/*-----------Register the Dissector for OLSR--------------*/
+void
+proto_register_olsr(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_olsr_packet_len,
+ { "Packet Length", "olsr.packet_len",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Packet Length in Bytes", HFILL }},
+
+ { &hf_olsr_packet_seq_num,
+ { "Packet Sequence Number", "olsr.packet_seq_num",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Packet Sequence Number", HFILL }},
+
+ { &hf_olsr_message_type,
+ { "Message Type", "olsr.message_type",
+ FT_UINT8, BASE_DEC, VALS(message_type_vals), 0,
+ "Message Type", HFILL }},
+
+ { &hf_olsr_message_size,
+ { "Message", "olsr.message_size",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Message Size in Bytes", HFILL }},
+
+ { &hf_olsr_message_seq_num,
+ { "Message Sequence Number", "olsr.message_seq_num",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Message Sequence Number", HFILL }},
+
+ { &hf_olsr_vtime,
+ { "Validity Time", "olsr.vtime",
+ FT_DOUBLE, BASE_NONE, NULL, 0,
+ "Validity Time", HFILL }},
+
+ { &hf_olsr_ansn,
+ { "Advertised Neighbor Sequence Number (ANSN)", "olsr.ansn",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Advertised Neighbor Sequence Number (ANSN)", HFILL }},
+
+ { &hf_olsr_htime,
+ { "Hello emission interval", "olsr.htime",
+ FT_DOUBLE, BASE_NONE, NULL, 0,
+ "Hello emission interval", HFILL }},
+
+ { &hf_olsr_willingness,
+ { "Willingness to Carry and Forward", "olsr.willingness",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Willingness to Carry and Forward", HFILL }},
+
+ { &hf_olsr_ttl,
+ { "Time to Live", "olsr.ttl",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Time to Live", HFILL }},
+
+ { &hf_olsr_link_type,
+ { "Link Type", "olsr.link_type",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Link Type", HFILL }},
+
+ { &hf_olsr_link_message_size,
+ { "Link Message Size", "olsr.link_message_size",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Link Message Size", HFILL }},
+
+ { &hf_olsr_hop_count,
+ { "Hop Count", "olsr.hop_count",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "Hop Count", HFILL }},
+
+ { &hf_olsr_origin_addr,
+ { "Originator Address", "olsr.origin_addr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Originator Address", HFILL }},
+
+ { &hf_olsr_neighbor_addr,
+ { "Neighbor Address", "olsr.neighbor_addr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Neighbor Address", HFILL }},
+
+
+ { &hf_olsr_network_addr,
+ { "Network Address", "olsr.network_addr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Network Address", HFILL }},
+
+ { &hf_olsr_interface_addr,
+ { "Interface Address", "olsr.interface_addr",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Interface Address", HFILL }},
+
+ { &hf_olsr_netmask,
+ { "Netmask", "olsr.netmask",
+ FT_IPv4, BASE_NONE, NULL, 0,
+ "Netmask", HFILL }},
+
+ { &hf_olsr_origin6_addr,
+ { "Originator Address", "olsr.origin6_addr",
+ FT_IPv6, BASE_NONE, NULL, 0,
+ "Originator Address", HFILL }},
+
+ { &hf_olsr_neighbor6_addr,
+ { "Neighbor Address", "olsr.neighbor6_addr",
+ FT_IPv6, BASE_NONE, NULL, 0,
+ "Neighbor Address", HFILL }},
+
+ { &hf_olsr_network6_addr,
+ { "Network Address", "olsr.network6_addr",
+ FT_IPv6, BASE_NONE, NULL, 0,
+ "Network Address", HFILL }},
+
+ { &hf_olsr_interface6_addr,
+ { "Interface Address", "olsr.interface6_addr",
+ FT_IPv6, BASE_NONE, NULL, 0,
+ "Interface Address", HFILL }},
+
+ { &hf_olsr_netmask6,
+ { "Netmask", "olsr.netmask6",
+ FT_IPv6, BASE_NONE, NULL, 0,
+ "Netmask", HFILL }},
+ };
+
+
+ static gint *ett[] = {
+ &ett_olsr,
+ };
+
+
+ proto_olsr = proto_register_protocol("Optimized Link State Routing Protocol",
+ "OLSR", "olsr");
+
+ proto_register_field_array(proto_olsr, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_olsr(void)
+{
+ dissector_handle_t olsr_handle;
+
+ olsr_handle = new_create_dissector_handle(dissect_olsr, proto_olsr);
+ dissector_add("udp.port", UDP_PORT_OLSR, olsr_handle);
+}
diff --git a/epan/dissectors/packet-osi-options.c b/epan/dissectors/packet-osi-options.c
new file mode 100644
index 0000000000..f49cffed75
--- /dev/null
+++ b/epan/dissectors/packet-osi-options.c
@@ -0,0 +1,460 @@
+/* packet-osi-options.c
+ * Routines for the decode of ISO/OSI option part
+ * Covers:
+ * ISO 8473 CLNP (ConnectionLess Mode Network Service Protocol)
+ * ISO 10589 ISIS (Intradomain Routing Information Exchange Protocol)
+ * ISO 9542 ESIS (End System To Intermediate System Routing Exchange Protocol)
+ *
+ * $Id$
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "nlpid.h"
+#include "packet-osi.h"
+#include "packet-isis.h"
+#include "packet-isis-clv.h"
+#include "packet-isis-hello.h"
+#include "packet-isis-lsp.h"
+#include "packet-isis-snp.h"
+#include "packet-esis.h"
+#include "packet-osi-options.h"
+
+#define OSI_OPT_SECURITY 0xc5
+#define OSI_OPT_QOS_MAINTANANCE 0xc3
+#define OSI_OPT_PRIORITY 0xcd
+#define OSI_OPT_ADDRESS_MASK 0xe1
+#define OSI_OPT_SNPA_MASK 0xe2
+#define OSI_OPT_ES_CONFIG_TIMER 0xc6
+
+#define OSI_OPT_MAX_PRIORITY 0x0e
+
+#define OSI_OPT_PADDING 0xcc
+#define OSI_OPT_SOURCE_ROUTING 0xc8
+#define OSI_OPT_RECORD_OF_ROUTE 0xcb
+#define OSI_OPT_REASON_OF_DISCARD 0xc1
+
+#define OSI_OPT_SEC_MASK 0xc0
+#define OSI_OPT_SEC_RESERVED 0x00
+#define OSI_OPT_SEC_SRC_ADR_SPEC 0x40
+#define OSI_OPT_SEC_DST_ADR_SPEC 0x80
+#define OSI_OPT_SEC_GLOBAL_UNIQUE 0xc0
+
+#define OSI_OPT_QOS_MASK 0xc0
+#define OSI_OPT_QOS_RESERVED 0x00
+#define OSI_OPT_QOS_SRC_ADR_SPEC 0x40
+#define OSI_OPT_QOS_DST_ADR_SPEC 0x80
+#define OSI_OPT_QOS_GLOBAL_UNIQUE 0xc0
+
+#define OSI_OPT_QOS_SUB_MASK 0x3f
+#define OSI_OPT_QOS_SUB_RSVD 0x20
+#define OSI_OPT_QOS_SUB_SEQ_VS_TRS 0x10
+#define OSI_OPT_QOS_SUB_CONG_EXPED 0x08
+#define OSI_OPT_QOS_SUB_TSD_VS_COST 0x04
+#define OSI_OPT_QOS_SUB_RESERR_TRS 0x02
+#define OSI_OPT_QOS_SUB_RESERR_COST 0x01
+
+#define OSI_OPT_RFD_GENERAL 0x00
+#define OSI_OPT_RFD_ADDRESS 0x80
+#define OSI_OPT_RFD_SOURCE_ROUTING 0x90
+#define OSI_OPT_RFD_LIFETIME 0xa0
+#define OSI_OPT_RFD_PDU_DISCARDED 0xb0
+#define OSI_OPT_RFD_REASSEMBLY 0xc0
+
+#define OSI_OPT_RFD_MASK 0xf0
+#define OSI_OPT_RFD_SUB_MASK 0x0f
+
+
+
+
+static gint ott_osi_options = -1;
+static gint ott_osi_qos = -1;
+static gint ott_osi_route = -1;
+static gint ott_osi_redirect = -1;
+
+static const value_string osi_opt_sec_vals[] = {
+ { OSI_OPT_SEC_RESERVED, "Reserved"},
+ { OSI_OPT_SEC_SRC_ADR_SPEC, "Source Address Specific"},
+ { OSI_OPT_SEC_DST_ADR_SPEC, "Destination Address Specific"},
+ { OSI_OPT_SEC_GLOBAL_UNIQUE, "Globally Unique"},
+ { 0, NULL} };
+
+static const value_string osi_opt_qos_vals[] = {
+ { OSI_OPT_QOS_RESERVED, "Reserved"},
+ { OSI_OPT_QOS_SRC_ADR_SPEC, "Source Address Specific"},
+ { OSI_OPT_QOS_DST_ADR_SPEC, "Destination Address Specific"},
+ { OSI_OPT_QOS_GLOBAL_UNIQUE, "Globally Unique"},
+ { 0, NULL} };
+
+static const value_string osi_opt_qos_sub_vals[] = {
+ { 0x20, " xx10 0000 Reserved"},
+ { 0x10, " xx01 0000 Sequencing versus transit delay"},
+ { 0x08, " xx00 1000 Congestion experienced"},
+ { 0x04, " xx00 0100 Transit delay versus cost"},
+ { 0x02, " xx00 0010 Residual error probability versus transit delay"},
+ { 0x01, " xx00 0001 Residual error probability versus cost"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_general[] = {
+ { 0x00, "Reason not specified"},
+ { 0x01, "Protocol procedure error"},
+ { 0x02, "Incorrect checksum"},
+ { 0x03, "PDU discarded due to congestion"},
+ { 0x04, "Header syntax error ( cannot be parsed )"},
+ { 0x05, "Segmentation needed but not permitted"},
+ { 0x06, "Incomplete PDU received"},
+ { 0x07, "Duplicate option"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_address[] = {
+ { 0x00, "Destination Address unreachable"},
+ { 0x01, "Destination Address unknown"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_src_route[] = {
+ { 0x00, "Unspecified source routing error"},
+ { 0x01, "Syntax error in source routing field"},
+ { 0x02, "Unknown address in source routing field"},
+ { 0x03, "Path not acceptable"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_lifetime[] = {
+ { 0x00, "Lifetime expired while data unit in transit"},
+ { 0x01, "Lifetime expired during reassembly"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_discarded[] = {
+ { 0x00, "Unsupported option not specified"},
+ { 0x01, "Unsupported protocol version"},
+ { 0x02, "Unsupported security option"},
+ { 0x03, "Unsupported source routing option"},
+ { 0x04, "Unsupported recording of route option"},
+ { 0, NULL} };
+
+static const value_string osi_opt_rfd_reassembly[] = {
+ { 0x00, "Reassembly interference"},
+ { 0, NULL} };
+
+
+static void
+dissect_option_qos( const guchar type, const guchar sub_type, int offset,
+ guchar len, tvbuff_t *tvb, proto_tree *tree ) {
+
+ guchar tmp_type = 0;
+ proto_item *ti;
+ proto_tree *osi_qos_tree = NULL;
+
+
+ ti = proto_tree_add_text( tree, tvb, offset, len,
+ "Quality of service maintenance: %s",
+ val_to_str( type, osi_opt_qos_vals, "Unknown (0x%x)") );
+
+ osi_qos_tree = proto_item_add_subtree( ti, ott_osi_qos );
+
+ if ( OSI_OPT_SEC_MASK == type ) { /* Analye BIT field to get all Values */
+
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_RSVD;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, tvb, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_SEQ_VS_TRS;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, tvb, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type &OSI_OPT_QOS_SUB_CONG_EXPED;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, tvb, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_TSD_VS_COST;
+
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, tvb, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_RESERR_TRS;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, tvb, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ tmp_type = sub_type & OSI_OPT_QOS_SUB_RESERR_COST;
+ if ( tmp_type ) {
+ proto_tree_add_text( osi_qos_tree, tvb, offset, len,
+ val_to_str( tmp_type, osi_opt_qos_sub_vals, "Unknown (0x%x)") );
+ }
+ }
+}
+
+static void
+dissect_option_route( guchar parm_type, int offset, guchar parm_len,
+ tvbuff_t *tvb, proto_tree *tree ) {
+
+ guchar next_hop = 0;
+ guchar this_hop = 0;
+ guchar netl = 0;
+ guchar last_hop = 0;
+ guchar cnt_hops = 0;
+
+ proto_item *ti;
+ proto_tree *osi_route_tree = NULL;
+
+ static const value_string osi_opt_route[] = {
+ { 0x03, "No Network Entity Titles Recorded Yet"},
+ { 0xff, "Recording Terminated !"},
+ { 0, NULL} };
+
+ if ( parm_type == OSI_OPT_SOURCE_ROUTING ) {
+ next_hop = tvb_get_guint8(tvb, offset + 1 );
+ netl = tvb_get_guint8(tvb, next_hop + 2 );
+ this_hop = offset + 3; /* points to first netl */
+
+ ti = proto_tree_add_text( tree, tvb, offset + next_hop, netl,
+ "Source Routing: %s ( Next Hop Highlighted In Data Buffer )",
+ (tvb_get_guint8(tvb, offset) == 0) ? "Partial Source Routing" :
+ "Complete Source Routing" );
+ }
+ else {
+ last_hop = tvb_get_guint8(tvb, offset + 1 );
+ /* points to the end of the list */
+ netl = tvb_get_guint8(tvb, last_hop );
+ /* mis-used to highlight buffer */
+
+ ti = proto_tree_add_text( tree, tvb, offset + next_hop, netl,
+ "Record of Route: %s : %s",
+ (tvb_get_guint8(tvb, offset) == 0) ? "Partial Source Routing" :
+ "Complete Source Routing" ,
+ val_to_str( last_hop, osi_opt_route, "Unknown (0x%x" ) );
+ if ( 255 == last_hop )
+ this_hop = parm_len + 1; /* recording terminated, nothing to show */
+ else
+ this_hop = offset + 3;
+ }
+ osi_route_tree = proto_item_add_subtree( ti, ott_osi_route );
+
+ while ( this_hop < parm_len ) {
+ netl = tvb_get_guint8(tvb, this_hop + 1);
+ proto_tree_add_text( osi_route_tree, tvb, offset + this_hop, netl,
+ "Hop #%3u NETL: %2u, NET: %s",
+ cnt_hops++,
+ netl,
+ print_nsap_net( tvb_get_ptr(tvb, this_hop + 1, netl), netl ) );
+ this_hop += 1 + netl;
+ }
+}
+
+
+
+
+
+static void
+dissect_option_rfd( const guchar error, const guchar field, int offset,
+ guchar len, tvbuff_t *tvb, proto_tree *tree ) {
+ guchar error_class = 0;
+ char *format_string[] =
+ { "Reason for discard {General} : %s, in field %u",
+ "Reason for discard {Address} : %s, in field %u",
+ "Reason for discard {Source Routing}: %s, in field %u",
+ "Reason for discard {Lifetime} : %s, in field %u",
+ "Reason for discard {PDU discarded} : %s, in field %u",
+ "Reason for discard {Reassembly} : %s, in field %u"
+ };
+
+ error_class = error & OSI_OPT_RFD_MASK;
+
+ if ( OSI_OPT_RFD_GENERAL == error_class ) {
+ proto_tree_add_text( tree, tvb, offset + field, 1, format_string[0],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_general, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_ADDRESS == error_class ) {
+ proto_tree_add_text( tree, tvb, offset + field, 1, format_string[1],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_address, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_SOURCE_ROUTING == error_class ) {
+ proto_tree_add_text( tree, tvb, offset + field, 1, format_string[2],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_src_route, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_LIFETIME == error_class ) {
+ proto_tree_add_text( tree, tvb, offset + field, 1, format_string[3],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_lifetime, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_PDU_DISCARDED == error_class ) {
+ proto_tree_add_text( tree, tvb, offset + field, 1, format_string[4],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_discarded, "Unknown (0x%x)"), field );
+ }
+ else if ( OSI_OPT_RFD_REASSEMBLY == error_class ) {
+ proto_tree_add_text( tree, tvb, offset + field, 1, format_string[5],
+ val_to_str( error & OSI_OPT_RFD_SUB_MASK,
+ osi_opt_rfd_reassembly, "Unknown (0x%x)"), field );
+ }
+ else {
+ proto_tree_add_text( tree, tvb, offset, len,
+ "Reason for discard: UNKNOWN Error Class" );
+ }
+}
+
+/* ############################## Dissection Functions ###################### */
+
+/*
+ * Name: dissect_osi_options()
+ *
+ * Description:
+ * Main entry area for esis de-mangling. This will build the
+ * main esis tree data and call the sub-protocols as needed.
+ *
+ * Input:
+ * guchar : length of option section
+ * tvbuff_t * : tvbuff containing packet data
+ * int : offset into packet where we are (packet_data[offset]== start
+ * of what we care about)
+ * proto_tree * : tree of display data. May be NULL.
+ *
+ * Output:
+ * void, but we will add to the proto_tree if it is not NULL.
+ */
+void
+dissect_osi_options( guchar opt_len, tvbuff_t *tvb,
+ int offset, proto_tree *tree) {
+ proto_item *ti;
+ proto_tree *osi_option_tree = NULL;
+ guchar parm_len = 0;
+ guchar parm_type = 0;
+ guint8 octet;
+
+ if (tree) {
+ if ( 0 == opt_len ) {
+ proto_tree_add_text( tree, tvb, offset, 0,
+ "### No Options for this PDU ###" );
+ return;
+ }
+
+ ti = proto_tree_add_text( tree, tvb, offset, opt_len,
+ "### Option Section ###" );
+ osi_option_tree = proto_item_add_subtree( ti, ott_osi_options );
+
+ while ( 0 < opt_len ) {
+ parm_type = (int) tvb_get_guint8(tvb, offset);
+ offset++;
+ parm_len = (int) tvb_get_guint8(tvb, offset);
+ offset++;
+
+ switch ( parm_type ) {
+ case OSI_OPT_QOS_MAINTANANCE:
+ octet = tvb_get_guint8(tvb, offset);
+ dissect_option_qos( (guchar) (octet&OSI_OPT_QOS_MASK),
+ (guchar) (octet&OSI_OPT_QOS_SUB_MASK),
+ offset, parm_len, tvb, osi_option_tree );
+ break;
+ case OSI_OPT_SECURITY:
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text( osi_option_tree, tvb, offset, parm_len,
+ "Security type: %s",
+ val_to_str( octet&OSI_OPT_SEC_MASK,
+ osi_opt_sec_vals, "Unknown (0x%x)") );
+ break;
+ case OSI_OPT_PRIORITY:
+ octet = tvb_get_guint8(tvb, offset);
+ if ( OSI_OPT_MAX_PRIORITY >= octet ) {
+ proto_tree_add_text( osi_option_tree, tvb, offset, parm_len,
+ "Priority : %u", octet );
+ }
+ else {
+ proto_tree_add_text( osi_option_tree, tvb, offset, parm_len,
+ "Priority : %u ( Invalid )",
+ octet );
+ }
+ break;
+ case OSI_OPT_ADDRESS_MASK:
+ proto_tree_add_text( osi_option_tree, tvb, offset, parm_len,
+ "Address Mask: %s",
+ print_area( tvb_get_ptr(tvb, offset, parm_len), parm_len ) );
+ break;
+ case OSI_OPT_SNPA_MASK:
+ proto_tree_add_text( osi_option_tree, tvb, offset, parm_len,
+ "SNPA Mask : %s",
+ print_system_id( tvb_get_ptr(tvb, offset, parm_len), parm_len ));
+ break;
+ case OSI_OPT_ES_CONFIG_TIMER:
+ proto_tree_add_text( osi_option_tree, tvb, offset, parm_len,
+ "ESCT : %u seconds", tvb_get_ntohs( tvb, offset ) );
+ break;
+ case OSI_OPT_PADDING:
+ proto_tree_add_text( osi_option_tree, tvb, offset, parm_len,
+ "Padding : %u Octets", parm_len ) ;
+ break;
+ case OSI_OPT_SOURCE_ROUTING:
+ case OSI_OPT_RECORD_OF_ROUTE:
+ dissect_option_route( parm_type,
+ offset, parm_len, tvb, osi_option_tree );
+ break;
+ case OSI_OPT_REASON_OF_DISCARD:
+ dissect_option_rfd( tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset + 1),
+ offset, parm_len, tvb, osi_option_tree );
+ break;
+ }
+ opt_len -= parm_len + 2;
+ offset += parm_len;
+ }
+ }
+} /* dissect-osi-options */
+
+
+/*
+ * Name: proto_register_osi_options()
+ *
+ * Description:
+ * main register for esis protocol set. We register some display
+ * formats and the protocol module variables.
+ *
+ * NOTE: this procedure to autolinked by the makefile process that
+ * builds register.c
+ *
+ * Input:
+ * void
+ *
+ * Output:
+ * void
+ */
+
+void
+proto_register_osi_options(void) {
+ static gint *ott[] = {
+ &ott_osi_options,
+ &ott_osi_qos,
+ &ott_osi_route,
+ &ott_osi_redirect,
+ };
+ proto_register_subtree_array( ott, array_length(ott));
+}
diff --git a/epan/dissectors/packet-osi-options.h b/epan/dissectors/packet-osi-options.h
new file mode 100644
index 0000000000..27ee3ded8c
--- /dev/null
+++ b/epan/dissectors/packet-osi-options.h
@@ -0,0 +1,36 @@
+/* packet-osi-options.h
+ * Defines for OSI options part decode
+ *
+ * $Id$
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_OSI_OPTION_H
+#define _PACKET_OSI_OPTIONS_H
+
+/*
+ * published API functions
+ */
+extern void dissect_osi_options( guchar, tvbuff_t *, int,
+ proto_tree *);
+extern void proto_register_osi_options(void);
+
+#endif /* _PACKET_OSI_OPTIONS_H */
diff --git a/epan/dissectors/packet-osi.c b/epan/dissectors/packet-osi.c
new file mode 100644
index 0000000000..6afbc80adf
--- /dev/null
+++ b/epan/dissectors/packet-osi.c
@@ -0,0 +1,305 @@
+/* packet-osi.c
+ * Routines for ISO/OSI network and transport protocol packet disassembly
+ * Main entrance point and common functions
+ *
+ * $Id$
+ * Laurent Deniel <laurent.deniel@free.fr>
+ * Ralf Schneider <Ralf.Schneider@t-online.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "llcsaps.h"
+#include "aftypes.h"
+#include "nlpid.h"
+#include "ppptypes.h"
+#include "chdlctypes.h"
+#include "packet-osi.h"
+#include "packet-isis.h"
+#include "packet-esis.h"
+
+
+cksum_status_t
+calc_checksum( tvbuff_t *tvb, int offset, guint len, guint checksum) {
+ const gchar *buffer;
+ guint available_len;
+ const guint8 *p;
+ guint32 c0, c1;
+ guint seglen;
+ guint i;
+
+ if ( 0 == checksum )
+ return( NO_CKSUM );
+
+ available_len = tvb_length_remaining( tvb, offset );
+ if ( available_len < len )
+ return( DATA_MISSING );
+
+ buffer = tvb_get_ptr( tvb, offset, len );
+
+ /*
+ * The maximum values of c0 and c1 will occur if all bytes have the
+ * value 255; if so, then c0 will be len*255 and c1 will be
+ * (len*255 + (len-1)*255 + ... + 255), which is
+ * (len + (len - 1) + ... + 1)*255, or 255*(len*(len + 1))/2.
+ * This means it can overflow if "len" is 5804 or greater.
+ *
+ * (A+B) mod 255 = ((A mod 255) + (B mod 255) mod 255, so
+ * we can solve this by taking c0 and c1 mod 255 every
+ * 5803 bytes.
+ */
+ p = buffer;
+ c0 = 0;
+ c1 = 0;
+ while (len != 0) {
+ seglen = len;
+ if (seglen > 5803)
+ seglen = 5803;
+ for (i = 0; i < seglen; i++) {
+ c0 = c0 + *(p++);
+ c1 += c0;
+ }
+
+ c0 = c0 % 255;
+ c1 = c1 % 255;
+
+ len -= seglen;
+ }
+ if (c0 != 0 || c1 != 0)
+ return( CKSUM_NOT_OK ); /* XXX - what should the checksum field be? */
+ else
+ return( CKSUM_OK );
+}
+
+
+cksum_status_t
+check_and_get_checksum( tvbuff_t *tvb, int offset, guint len, guint checksum, int offset_check, guint16* result) {
+ const gchar *buffer;
+ guint available_len;
+ const guint8 *p;
+ guint8 discard = 0;
+ guint32 c0, c1, factor;
+ guint seglen, initlen = len;
+ guint i;
+ int block, x, y;
+
+ if ( 0 == checksum )
+ return( NO_CKSUM );
+
+ available_len = tvb_length_remaining( tvb, offset );
+ offset_check -= offset;
+ if ( ( available_len < len ) || ( offset_check < 0 ) || ( (guint)(offset_check+2) > len ) )
+ return( DATA_MISSING );
+
+ buffer = tvb_get_ptr( tvb, offset, len );
+ block = offset_check / 5803;
+
+ /*
+ * The maximum values of c0 and c1 will occur if all bytes have the
+ * value 255; if so, then c0 will be len*255 and c1 will be
+ * (len*255 + (len-1)*255 + ... + 255), which is
+ * (len + (len - 1) + ... + 1)*255, or 255*(len*(len + 1))/2.
+ * This means it can overflow if "len" is 5804 or greater.
+ *
+ * (A+B) mod 255 = ((A mod 255) + (B mod 255) mod 255, so
+ * we can solve this by taking c0 and c1 mod 255 every
+ * 5803 bytes.
+ */
+ p = buffer;
+ c0 = 0;
+ c1 = 0;
+
+ while (len != 0) {
+ seglen = len;
+ if ( block-- == 0 ) {
+ seglen = offset_check % 5803;
+ discard = 1;
+ } else if ( seglen > 5803 )
+ seglen = 5803;
+ for (i = 0; i < seglen; i++) {
+ c0 = c0 + *(p++);
+ c1 += c0;
+ }
+ if ( discard ) {
+ /*
+ * This works even if (offset_check % 5803) == 5802
+ */
+ p += 2;
+ c1 += 2*c0;
+ len -= 2;
+ discard = 0;
+ }
+
+ c0 = c0 % 255;
+ c1 = c1 % 255;
+
+ len -= seglen;
+ }
+
+ factor = ( initlen - offset_check ) * c0;
+ x = factor - c0 - c1;
+ y = c1 - factor - 1;
+
+ /*
+ * This algorithm uses the 8 bits one's complement arithmetic.
+ * Therefore, we must correct an effect produced
+ * by the "standard" arithmetic (two's complement)
+ */
+
+ if (x < 0 ) x--;
+ if (y > 0 ) y++;
+
+ x %= 255;
+ y %= 255;
+
+ if (x == 0) x = 0xFF;
+ if (y == 0) y = 0x01;
+
+ *result = ( x << 8 ) | ( y & 0xFF );
+
+ if (*result != checksum)
+ return( CKSUM_NOT_OK ); /* XXX - what should the checksum field be? */
+ else
+ return( CKSUM_OK );
+}
+
+
+
+/* main entry point */
+
+/*
+ * These assume the NLPID is a secondary protocol identifier, not an
+ * initial protocol identifier.
+ *
+ * This is an issue only if, in any packet where an NLPID appears, it's
+ * an initial protocol identifier *AND* it can have the value 1, which
+ * means T.70 for an IPI and X.29 for an SPI.
+ */
+const value_string nlpid_vals[] = {
+ { NLPID_NULL, "NULL" },
+ { NLPID_SPI_X_29, "X.29" },
+ { NLPID_X_633, "X.633" },
+ { NLPID_Q_931, "Q.931" },
+ { NLPID_Q_2931, "Q.2931" },
+ { NLPID_Q_2119, "Q.2119" },
+ { NLPID_SNAP, "SNAP" },
+ { NLPID_ISO8473_CLNP, "CLNP" },
+ { NLPID_ISO9542_ESIS, "ESIS" },
+ { NLPID_ISO10589_ISIS, "ISIS" },
+ { NLPID_ISO10747_IDRP, "IDRP" },
+ { NLPID_ISO9542X25_ESIS, "ESIS (X.25)" },
+ { NLPID_ISO10030, "ISO 10030" },
+ { NLPID_ISO11577, "ISO 11577" },
+ { NLPID_COMPRESSED, "Data compression protocol" },
+ { NLPID_IP, "IP" },
+ { NLPID_SNDCF, "SubNetwork Dependent Convergence Function"},
+ { NLPID_IP6, "IPv6" },
+ { NLPID_PPP, "PPP" },
+ { 0, NULL },
+};
+
+static dissector_table_t osinl_subdissector_table;
+static dissector_handle_t data_handle, ppp_handle;
+
+static void dissect_osi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 nlpid;
+ tvbuff_t *new_tvb;
+
+ pinfo->current_proto = "OSI";
+
+ nlpid = tvb_get_guint8(tvb, 0);
+
+ /* do lookup with the subdissector table */
+ if (dissector_try_port(osinl_subdissector_table, nlpid, tvb, pinfo, tree))
+ return;
+
+ switch (nlpid) {
+
+ /* ESIS (X.25) is not currently decoded */
+
+ case NLPID_ISO9542X25_ESIS:
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESIS (X.25)");
+ }
+ call_dissector(data_handle,tvb, pinfo, tree);
+ break;
+ case NLPID_ISO10747_IDRP:
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IDRP");
+ }
+ call_dissector(data_handle,tvb, pinfo, tree);
+ break;
+ case NLPID_PPP:
+ /* XXX - we should put the NLPID into the protocol tree.
+ We should also probably have a subdissector table for
+ those protocols whose PDUs *aren't* defined to begin
+ with an NLPID. */
+ new_tvb = tvb_new_subset(tvb, 1, -1, -1);
+ call_dissector(ppp_handle, new_tvb, pinfo, tree);
+ break;
+ default:
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISO");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ISO protocol (%02x)", nlpid);
+ }
+ call_dissector(data_handle,tvb, pinfo, tree);
+ break;
+ }
+} /* dissect_osi */
+
+void
+proto_register_osi(void)
+{
+ /* There's no "OSI" protocol *per se*, but we do register a
+ dissector table so various protocols running at the
+ network layer can register themselves. */
+ osinl_subdissector_table = register_dissector_table("osinl",
+ "OSI NLPID", FT_UINT8, BASE_HEX);
+}
+
+void
+proto_reg_handoff_osi(void)
+{
+ dissector_handle_t osi_handle;
+
+ osi_handle = create_dissector_handle(dissect_osi, -1);
+ dissector_add("llc.dsap", SAP_OSINL1, osi_handle);
+ dissector_add("llc.dsap", SAP_OSINL2, osi_handle);
+ dissector_add("llc.dsap", SAP_OSINL3, osi_handle);
+ dissector_add("llc.dsap", SAP_OSINL4, osi_handle);
+ dissector_add("llc.dsap", SAP_OSINL5, osi_handle);
+ dissector_add("ppp.protocol", PPP_OSI, osi_handle);
+ dissector_add("chdlctype", CHDLCTYPE_OSI, osi_handle);
+ dissector_add("null.type", BSD_AF_ISO, osi_handle);
+ dissector_add("gre.proto", SAP_OSINL5, osi_handle);
+ data_handle = find_dissector("data");
+ ppp_handle = find_dissector("ppp");
+}
diff --git a/epan/dissectors/packet-osi.h b/epan/dissectors/packet-osi.h
new file mode 100644
index 0000000000..9594917c09
--- /dev/null
+++ b/epan/dissectors/packet-osi.h
@@ -0,0 +1,91 @@
+/* packet-osi.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef _PACKET_OSI_H
+#define _PACKET_OSI_H
+
+#include <epan/osi-utils.h>
+
+#define PDU_TYPE_ESIS_ESH 100
+#define PDU_TYPE_ESIS_ISH 101
+#define PDU_TYPE_ESIS_RD 102
+
+#define PDU_TYPE_ISIS_L1_HELLO 201
+#define PDU_TYPE_ISIS_L2_HELLO 202
+#define PDU_TYPE_ISIS_PTP_HELLO 203
+#define PDU_TYPE_ISIS_L1_CSNP 204
+#define PDU_TYPE_ISIS_L1_PSNP 205
+#define PDU_TYPE_ISIS_L2_CSNP 206
+#define PDU_TYPE_ISIS_L2_PSNP 207
+
+
+
+
+
+#define PROTO_STRING_ISIS "ISO 10589 ISIS InTRA Domain Routeing Information Exchange Protocol"
+#define PROTO_STRING_IDRP "ISO 10747 IDRP InTER Domain Routeing Information Exchange Protocol"
+#define PROTO_STRING_ESIS "ISO 9542 ESIS Routeing Information Exchange Protocol"
+#define PROTO_STRING_CLNP "ISO 8473 CLNP ConnectionLess Network Protocol"
+#define PROTO_STRING_COTP "ISO 8073 COTP Connection-Oriented Transport Protocol"
+#define PROTO_STRING_CLTP "ISO 8602 CLTP ConnectionLess Transport Protocol"
+#define PROTO_STRING_LSP "ISO 10589 ISIS Link State Protocol Data Unit"
+#define PROTO_STRING_CSNP "ISO 10589 ISIS Complete Sequence Numbers Protocol Data Unit"
+#define PROTO_STRING_PSNP "ISO 10589 ISIS Partial Sequence Numbers Protocol Data Unit"
+
+#define OSI_PDU_TYPE_MASK 0x1f
+#define BIS_PDU_TYPE MASK 0xff
+
+
+#define BIT_1 0x01
+#define BIT_2 0x02
+#define BIT_3 0x04
+#define BIT_4 0x08
+#define BIT_5 0x10
+#define BIT_6 0x20
+#define BIT_7 0x40
+#define BIT_8 0x80
+
+#define BIT_9 0x0100
+#define BIT_10 0x0200
+#define BIT_11 0x0400
+#define BIT_12 0x0800
+#define BIT_13 0x1000
+#define BIT_14 0x2000
+#define BIT_15 0x4000
+#define BIT_16 0x8000
+
+/*
+ * published API functions
+ */
+
+typedef enum {
+ NO_CKSUM, /* checksum field is 0 */
+ DATA_MISSING, /* not all the data covered by the checksum was captured */
+ CKSUM_OK, /* checksum is OK */
+ CKSUM_NOT_OK /* checksum is not OK */
+} cksum_status_t;
+
+extern cksum_status_t calc_checksum(tvbuff_t *, int, guint, guint);
+extern cksum_status_t check_and_get_checksum( tvbuff_t *, int, guint, guint, int, guint16*);
+
+#endif /* _PACKET_OSI_H */
diff --git a/epan/dissectors/packet-ospf.c b/epan/dissectors/packet-ospf.c
new file mode 100644
index 0000000000..02ac9e64fd
--- /dev/null
+++ b/epan/dissectors/packet-ospf.c
@@ -0,0 +1,2145 @@
+/* packet-ospf.c
+ * Routines for OSPF packet disassembly
+ * (c) Copyright Hannes R. Boehm <hannes@boehm.org>
+ *
+ * $Id$
+ *
+ * At this time, this module is able to analyze OSPF
+ * packets as specified in RFC2328. MOSPF (RFC1584) and other
+ * OSPF Extensions which introduce new Packet types
+ * (e.g the External Atributes LSA) are not supported.
+ * Furthermore RFC2740 (OSPFv3 - OSPF for IPv6) is now supported
+ * - (c) 2001 Palle Lyckegaard <palle[AT]lyckegaard.dk>
+ *
+ * TOS - support is not fully implemented
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "ipproto.h"
+#include "in_cksum.h"
+#include "packet-rsvp.h"
+
+#define OSPF_VERSION_2 2
+#define OSPF_VERSION_3 3
+#define OSPF_VERSION_2_HEADER_LENGTH 24
+#define OSPF_VERSION_3_HEADER_LENGTH 16
+
+
+#define OSPF_HELLO 1
+#define OSPF_DB_DESC 2
+#define OSPF_LS_REQ 3
+#define OSPF_LS_UPD 4
+#define OSPF_LS_ACK 5
+
+static const value_string pt_vals[] = {
+ {OSPF_HELLO, "Hello Packet" },
+ {OSPF_DB_DESC, "DB Descr." },
+ {OSPF_LS_REQ, "LS Request" },
+ {OSPF_LS_UPD, "LS Update" },
+ {OSPF_LS_ACK, "LS Acknowledge" },
+ {0, NULL }
+};
+
+#define OSPF_AUTH_NONE 0
+#define OSPF_AUTH_SIMPLE 1
+#define OSPF_AUTH_CRYPT 2
+
+static const value_string auth_vals[] = {
+ {OSPF_AUTH_NONE, "Null" },
+ {OSPF_AUTH_SIMPLE, "Simple password" },
+ {OSPF_AUTH_CRYPT, "Cryptographic" },
+ {0, NULL }
+};
+
+#define OSPF_V2_OPTIONS_DN 0x01
+#define OSPF_V2_OPTIONS_E 0x02
+#define OSPF_V2_OPTIONS_MC 0x04
+#define OSPF_V2_OPTIONS_NP 0x08
+#define OSPF_V2_OPTIONS_EA 0x10
+#define OSPF_V2_OPTIONS_DC 0x20
+#define OSPF_V2_OPTIONS_O 0x40
+#define OSPF_V3_OPTIONS_V6 0x01
+#define OSPF_V3_OPTIONS_E 0x02
+#define OSPF_V3_OPTIONS_MC 0x04
+#define OSPF_V3_OPTIONS_N 0x08
+#define OSPF_V3_OPTIONS_R 0x10
+#define OSPF_V3_OPTIONS_DC 0x20
+
+
+#define OSPF_DBD_FLAG_MS 1
+#define OSPF_DBD_FLAG_M 2
+#define OSPF_DBD_FLAG_I 4
+
+#define OSPF_LS_REQ_LENGTH 12
+
+#define OSPF_LSTYPE_ROUTER 1
+#define OSPF_LSTYPE_NETWORK 2
+#define OSPF_LSTYPE_SUMMERY 3
+#define OSPF_LSTYPE_ASBR 4
+#define OSPF_LSTYPE_ASEXT 5
+#define OSPF_LSTYPE_GRPMEMBER 6
+#define OSPF_LSTYPE_ASEXT7 7
+#define OSPF_LSTYPE_EXTATTR 8
+#define OSPF_V3_LSTYPE_ROUTER 0x2001
+#define OSPF_V3_LSTYPE_NETWORK 0x2002
+#define OSPF_V3_LSTYPE_INTER_AREA_PREFIX 0x2003
+#define OSPF_V3_LSTYPE_INTER_AREA_ROUTER 0x2004
+#define OSPF_V3_LSTYPE_AS_EXTERNAL 0x4005
+#define OSPF_V3_LSTYPE_GROUP_MEMBERSHIP 0x2006
+#define OSPF_V3_LSTYPE_TYPE_7 0x2007
+#define OSPF_V3_LSTYPE_LINK 0x0008
+#define OSPF_V3_LSTYPE_INTRA_AREA_PREFIX 0x2009
+
+/* Opaque LSA types */
+#define OSPF_LSTYPE_OP_LINKLOCAL 9
+#define OSPF_LSTYPE_OP_AREALOCAL 10
+#define OSPF_LSTYPE_OP_ASWIDE 11
+
+#define OSPF_LINK_PTP 1
+#define OSPF_LINK_TRANSIT 2
+#define OSPF_LINK_STUB 3
+#define OSPF_LINK_VIRTUAL 4
+
+#define OSPF_V3_LINK_PTP 1
+#define OSPF_V3_LINK_TRANSIT 2
+#define OSPF_V3_LINK_RESERVED 3
+#define OSPF_V3_LINK_VIRTUAL 4
+
+#define OSPF_LSA_HEADER_LENGTH 20
+
+/* Known opaque LSAs */
+#define OSPF_LSA_MPLS_TE 1
+
+
+static const value_string ls_type_vals[] = {
+ {OSPF_LSTYPE_ROUTER, "Router-LSA" },
+ {OSPF_LSTYPE_NETWORK, "Network-LSA" },
+ {OSPF_LSTYPE_SUMMERY, "Summary-LSA (IP network)" },
+ {OSPF_LSTYPE_ASBR, "Summary-LSA (ASBR)" },
+ {OSPF_LSTYPE_ASEXT, "AS-External-LSA (ASBR)" },
+ {OSPF_LSTYPE_GRPMEMBER, "Group Membership LSA" },
+ {OSPF_LSTYPE_ASEXT7, "NSSA AS-External-LSA" },
+ {OSPF_LSTYPE_EXTATTR, "External Attributes LSA" },
+ {OSPF_LSTYPE_OP_LINKLOCAL, "Opaque LSA, Link-local scope" },
+ {OSPF_LSTYPE_OP_AREALOCAL, "Opaque LSA, Area-local scope" },
+ {0, NULL }
+
+};
+
+static const value_string ls_opaque_type_vals[] = {
+ {OSPF_LSA_MPLS_TE, "Traffic Engineering LSA" },
+ {2, "Sycamore Optical Topology Descriptions" },
+ {3, "grace-LSA" },
+ {0, NULL }
+};
+
+static const value_string v3_ls_type_vals[] = {
+ {OSPF_V3_LSTYPE_ROUTER, "Router-LSA" },
+ {OSPF_V3_LSTYPE_NETWORK, "Network-LSA" },
+ {OSPF_V3_LSTYPE_INTER_AREA_PREFIX, "Inter-Area-Prefix-LSA" },
+ {OSPF_V3_LSTYPE_INTER_AREA_ROUTER, "Inter-Area-Router-LSA" },
+ {OSPF_V3_LSTYPE_AS_EXTERNAL, "AS-External-LSA" },
+ {OSPF_V3_LSTYPE_GROUP_MEMBERSHIP, "Group-Membership-LSA" },
+ {OSPF_V3_LSTYPE_TYPE_7, "Type-LSA" },
+ {OSPF_V3_LSTYPE_LINK, "Link-LSA" },
+ {OSPF_V3_LSTYPE_INTRA_AREA_PREFIX, "Intra-Area-Prefix-LSA" },
+ {0, NULL }
+
+};
+
+
+#define OSPF_V3_ROUTER_LSA_FLAG_B 0x01
+#define OSPF_V3_ROUTER_LSA_FLAG_E 0x02
+#define OSPF_V3_ROUTER_LSA_FLAG_V 0x04
+#define OSPF_V3_ROUTER_LSA_FLAG_W 0x08
+
+#define OSPF_V3_PREFIX_OPTION_NU 0x01
+#define OSPF_V3_PREFIX_OPTION_LA 0x02
+#define OSPF_V3_PREFIX_OPTION_MC 0x04
+#define OSPF_V3_PREFIX_OPTION_P 0x08
+
+#define OSPF_V3_AS_EXTERNAL_FLAG_T 0x01
+#define OSPF_V3_AS_EXTERNAL_FLAG_F 0x02
+#define OSPF_V3_AS_EXTERNAL_FLAG_E 0x04
+
+
+static int proto_ospf = -1;
+
+static gint ett_ospf = -1;
+static gint ett_ospf_hdr = -1;
+static gint ett_ospf_hello = -1;
+static gint ett_ospf_desc = -1;
+static gint ett_ospf_lsr = -1;
+static gint ett_ospf_lsa = -1;
+static gint ett_ospf_lsa_router_link = -1;
+static gint ett_ospf_lsa_upd = -1;
+
+/* Trees for opaque LSAs */
+static gint ett_ospf_lsa_mpls = -1;
+static gint ett_ospf_lsa_mpls_router = -1;
+static gint ett_ospf_lsa_mpls_link = -1;
+static gint ett_ospf_lsa_mpls_link_stlv = -1;
+
+/*-----------------------------------------------------------------------
+ * OSPF Filtering
+ *-----------------------------------------------------------------------*/
+
+/* The OSPF filtering keys */
+enum {
+
+ OSPFF_MSG_TYPE,
+
+ OSPFF_MSG_MIN,
+ OSPFF_MSG_HELLO,
+ OSPFF_MSG_DB_DESC,
+ OSPFF_MSG_LS_REQ,
+ OSPFF_MSG_LS_UPD,
+ OSPFF_MSG_LS_ACK,
+
+ OSPFF_LS_TYPE,
+ OSPFF_LS_OPAQUE_TYPE,
+
+ OSPFF_LS_MPLS_TE_INSTANCE,
+
+ OSPFF_LS_MIN,
+ OSPFF_LS_ROUTER,
+ OSPFF_LS_NETWORK,
+ OSPFF_LS_SUMMARY,
+ OSPFF_LS_ASBR,
+ OSPFF_LS_ASEXT,
+ OSPFF_LS_GRPMEMBER,
+ OSPFF_LS_ASEXT7,
+ OSPFF_LS_EXTATTR,
+ OSPFF_LS_OPAQUE,
+
+ OSPFF_SRC_ROUTER,
+ OSPFF_ADV_ROUTER,
+ OSPFF_LS_MPLS,
+ OSPFF_LS_MPLS_ROUTERID,
+
+ OSPFF_LS_MPLS_LINKID,
+ OSPFF_LS_MPLS_LOCAL_ADDR,
+ OSPFF_LS_MPLS_REMOTE_ADDR,
+ OSPFF_LS_MPLS_LOCAL_IFID,
+ OSPFF_LS_MPLS_REMOTE_IFID,
+
+ OSPFF_MAX
+};
+
+static int ospf_filter[OSPFF_MAX];
+
+static hf_register_info ospff_info[] = {
+
+ /* Message type number */
+ {&ospf_filter[OSPFF_MSG_TYPE],
+ { "Message Type", "ospf.msg", FT_UINT8, BASE_DEC, VALS(pt_vals), 0x0,
+ "", HFILL }},
+
+ /* Message types */
+ {&ospf_filter[OSPFF_MSG_HELLO],
+ { "Hello", "ospf.msg.hello", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_MSG_DB_DESC],
+ { "Database Description", "ospf.msg.dbdesc", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_MSG_LS_REQ],
+ { "Link State Adv Request", "ospf.msg.lsreq", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_MSG_LS_UPD],
+ { "Link State Adv Update", "ospf.msg.lsupdate", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_MSG_LS_ACK],
+ { "Link State Adv Acknowledgement", "ospf.msg.lsack", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "", HFILL }},
+
+
+
+ /* LS Types */
+ {&ospf_filter[OSPFF_LS_TYPE],
+ { "Link-State Advertisement Type", "ospf.lsa", FT_UINT8, BASE_DEC,
+ VALS(ls_type_vals), 0x0, "", HFILL }},
+ {&ospf_filter[OSPFF_LS_OPAQUE_TYPE],
+ { "Link State ID Opaque Type", "ospf.lsid_opaque_type", FT_UINT8, BASE_DEC,
+ VALS(ls_opaque_type_vals), 0x0, "", HFILL }},
+
+ {&ospf_filter[OSPFF_LS_MPLS_TE_INSTANCE],
+ { "Link State ID TE-LSA Instance", "ospf.lsid_te_lsa.instance", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ {&ospf_filter[OSPFF_LS_ROUTER],
+ { "Router LSA", "ospf.lsa.router", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_LS_NETWORK],
+ { "Network LSA", "ospf.lsa.network", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_LS_SUMMARY],
+ { "Summary LSA (IP Network)", "ospf.lsa.summary", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ {&ospf_filter[OSPFF_LS_ASBR],
+ { "Summary LSA (ASBR)", "ospf.lsa.asbr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_LS_ASEXT],
+ { "AS-External LSA (ASBR)", "ospf.lsa.asext", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_LS_GRPMEMBER],
+ { "Group Membership LSA", "ospf.lsa.member", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_LS_ASEXT7],
+ { "NSSA AS-External LSA", "ospf.lsa.nssa", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_LS_EXTATTR],
+ { "External Attributes LSA", "ospf.lsa.attr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_LS_OPAQUE],
+ { "Opaque LSA", "ospf.lsa.opaque", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ /* Other interesting OSPF values */
+
+ {&ospf_filter[OSPFF_SRC_ROUTER],
+ { "Source OSPF Router", "ospf.srcrouter", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&ospf_filter[OSPFF_ADV_ROUTER],
+ { "Advertising Router", "ospf.advrouter", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&ospf_filter[OSPFF_LS_MPLS],
+ { "MPLS Traffic Engineering LSA", "ospf.lsa.mpls", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ {&ospf_filter[OSPFF_LS_MPLS_ROUTERID],
+ { "MPLS/TE Router ID", "ospf.mpls.routerid", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&ospf_filter[OSPFF_LS_MPLS_LINKID],
+ { "MPLS/TE Link ID", "ospf.mpls.linkid", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ {&ospf_filter[OSPFF_LS_MPLS_LOCAL_ADDR],
+ { "MPLS/TE Local Interface Address", "ospf.mpls.local_addr", FT_IPv4,
+ BASE_NONE, NULL, 0x0, "", HFILL }},
+ {&ospf_filter[OSPFF_LS_MPLS_REMOTE_ADDR],
+ { "MPLS/TE Remote Interface Address", "ospf.mpls.remote_addr", FT_IPv4,
+ BASE_NONE, NULL, 0x0, "", HFILL }},
+ {&ospf_filter[OSPFF_LS_MPLS_LOCAL_IFID],
+ { "MPLS/TE Local Interface Index", "ospf.mpls.local_id", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+ {&ospf_filter[OSPFF_LS_MPLS_REMOTE_IFID],
+ { "MPLS/TE Remote Interface Index", "ospf.mpls.remote_id", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+
+
+};
+
+static guint8 ospf_msg_type_to_filter (guint8 msg_type)
+{
+ if (msg_type >= OSPF_HELLO &&
+ msg_type <= OSPF_LS_ACK)
+ return msg_type + OSPFF_MSG_MIN;
+ return -1;
+}
+
+static guint8 ospf_ls_type_to_filter (guint8 ls_type)
+{
+ if (ls_type >= OSPF_LSTYPE_ROUTER &&
+ ls_type <= OSPF_LSTYPE_EXTATTR)
+ return OSPFF_LS_MIN + ls_type;
+ else if (ls_type >= OSPF_LSTYPE_OP_LINKLOCAL &&
+ ls_type <= OSPF_LSTYPE_OP_ASWIDE)
+ return OSPFF_LS_OPAQUE;
+ else
+ return -1;
+}
+
+static dissector_handle_t data_handle;
+
+static void dissect_ospf_hello(tvbuff_t*, int, proto_tree*, guint8);
+static void dissect_ospf_db_desc(tvbuff_t*, int, proto_tree*, guint8);
+static void dissect_ospf_ls_req(tvbuff_t*, int, proto_tree*, guint8);
+static void dissect_ospf_ls_upd(tvbuff_t*, int, proto_tree*, guint8);
+static void dissect_ospf_ls_ack(tvbuff_t*, int, proto_tree*, guint8);
+
+/* dissect_ospf_v[23]lsa returns the offset of the next LSA
+ * if disassemble_body is set to FALSE (e.g. in LSA ACK
+ * packets), the offset is set to the offset of the next
+ * LSA header
+ */
+static int dissect_ospf_v2_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
+static int dissect_ospf_v3_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body);
+
+static void dissect_ospf_options(tvbuff_t *, int, proto_tree *, guint8);
+
+static void dissect_ospf_v3_prefix_options(tvbuff_t *, int, proto_tree *);
+
+static void dissect_ospf_v3_address_prefix(tvbuff_t *, int, int, proto_tree *);
+
+static void
+dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ospf_tree = NULL;
+ proto_item *ti;
+ proto_tree *ospf_header_tree;
+ guint8 version;
+ guint8 packet_type;
+ guint16 ospflen;
+ vec_t cksum_vec[4];
+ int cksum_vec_len;
+ guint32 phdr[2];
+ guint16 cksum, computed_cksum;
+ guint length, reported_length;
+ guint16 auth_type;
+ char auth_data[8+1];
+ int crypto_len;
+ unsigned int ospf_header_length;
+ guint8 instance_ID;
+ guint8 reserved;
+ guint32 areaid;
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "OSPF");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ version = tvb_get_guint8(tvb, 0);
+ switch (version) {
+ case OSPF_VERSION_2:
+ ospf_header_length = OSPF_VERSION_2_HEADER_LENGTH;
+ break;
+ case OSPF_VERSION_3:
+ ospf_header_length = OSPF_VERSION_3_HEADER_LENGTH;
+ break;
+ default:
+ ospf_header_length = 0;
+ break;
+ }
+
+ packet_type = tvb_get_guint8(tvb, 1);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(packet_type, pt_vals, "Unknown (%u)"));
+ }
+
+ if (tree) {
+ ospflen = tvb_get_ntohs(tvb, 2);
+
+ ti = proto_tree_add_item(tree, proto_ospf, tvb, 0, ospflen, FALSE);
+ ospf_tree = proto_item_add_subtree(ti, ett_ospf);
+
+ ti = proto_tree_add_text(ospf_tree, tvb, 0, ospf_header_length,
+ "OSPF Header");
+ ospf_header_tree = proto_item_add_subtree(ti, ett_ospf_hdr);
+
+ proto_tree_add_text(ospf_header_tree, tvb, 0, 1, "OSPF Version: %u",
+ version);
+ proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_MSG_TYPE],
+ tvb, 1, 1, FALSE);
+ proto_tree_add_item_hidden(ospf_header_tree,
+ ospf_filter[ospf_msg_type_to_filter(packet_type)],
+ tvb, 1, 1, FALSE);
+ proto_tree_add_text(ospf_header_tree, tvb, 2, 2, "Packet Length: %u",
+ ospflen);
+ proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_SRC_ROUTER],
+ tvb, 4, 4, FALSE);
+ areaid=tvb_get_ntohl(tvb,8);
+ proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: %s%s",
+ ip_to_str(tvb_get_ptr(tvb, 8, 4)), areaid == 0 ? " (Backbone)" : "");
+ cksum = tvb_get_ntohs(tvb, 12);
+ length = tvb_length(tvb);
+ /* XXX - include only the length from the OSPF header? */
+ reported_length = tvb_reported_length(tvb);
+ if (cksum == 0) {
+ /* No checksum supplied in the packet. */
+ proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
+ "Packet Checksum: 0x%04x (none)", cksum);
+ } else if (!pinfo->fragmented && length >= reported_length
+ && length >= ospf_header_length
+ && (version == OSPF_VERSION_2 || version == OSPF_VERSION_3)) {
+ /* The packet isn't part of a fragmented datagram and isn't
+ truncated, and we know how to checksum this version of
+ OSPF, so we can checksum it. */
+
+ switch (version) {
+
+ case OSPF_VERSION_2:
+ /* Header, not including the authentication data (the OSPFv2
+ checksum excludes the 64-bit authentication field). */
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, 16);
+ cksum_vec[0].len = 16;
+ if (length > ospf_header_length) {
+ /* Rest of the packet, again not including the
+ authentication data. */
+ reported_length -= ospf_header_length;
+ cksum_vec[1].ptr = tvb_get_ptr(tvb, ospf_header_length, reported_length);
+ cksum_vec[1].len = reported_length;
+ cksum_vec_len = 2;
+ } else {
+ /* There's nothing but a header. */
+ cksum_vec_len = 1;
+ }
+ break;
+
+ case OSPF_VERSION_3:
+ /* IPv6-style checksum, covering the entire OSPF packet
+ and a prepended IPv6 pseudo-header. */
+
+ /* Set up the fields of the pseudo-header. */
+ cksum_vec[0].ptr = pinfo->src.data;
+ cksum_vec[0].len = pinfo->src.len;
+ cksum_vec[1].ptr = pinfo->dst.data;
+ cksum_vec[1].len = pinfo->dst.len;
+ cksum_vec[2].ptr = (const guint8 *)&phdr;
+ phdr[0] = g_htonl(ospflen);
+ phdr[1] = g_htonl(IP_PROTO_OSPF);
+ cksum_vec[2].len = 8;
+
+ cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, reported_length);
+ cksum_vec[3].len = reported_length;
+ cksum_vec_len = 4;
+ break;
+
+ default:
+ g_assert_not_reached();
+ cksum_vec_len = 0;
+ }
+ computed_cksum = in_cksum(cksum_vec, cksum_vec_len);
+ if (computed_cksum == 0) {
+ proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
+ "Packet Checksum: 0x%04x (correct)", cksum);
+ } else {
+ proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
+ "Packet Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ cksum, in_cksum_shouldbe(cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
+ "Packet Checksum: 0x%04x", cksum);
+ }
+
+
+ /* Authentication is only valid for OSPFv2 */
+ if ( version == OSPF_VERSION_2 ) {
+ auth_type = tvb_get_ntohs(tvb, 14);
+ proto_tree_add_text(ospf_header_tree, tvb, 14, 2, "Auth Type: %s",
+ val_to_str(auth_type, auth_vals, "Unknown (%u)"));
+ switch (auth_type) {
+
+ case OSPF_AUTH_NONE:
+ proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (none)");
+ break;
+
+ case OSPF_AUTH_SIMPLE:
+ tvb_get_nstringz0(tvb, 16, 8+1, auth_data);
+ proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data: %s", auth_data);
+ break;
+
+ case OSPF_AUTH_CRYPT:
+ proto_tree_add_text(ospf_header_tree, tvb, 18, 1, "Auth Key ID: %u",
+ tvb_get_guint8(tvb, 18));
+ crypto_len = tvb_get_guint8(tvb, 19);
+ proto_tree_add_text(ospf_header_tree, tvb, 19, 1, "Auth Data Length: %u",
+ crypto_len);
+ proto_tree_add_text(ospf_header_tree, tvb, 20, 4, "Auth Crypto Sequence Number: 0x%x",
+ tvb_get_ntohl(tvb, 20));
+
+ /* Show the message digest that was appended to the end of the
+ OSPF message - but only if it's present (we don't want
+ to get an exception before we've tried dissecting OSPF
+ message). */
+ if (tvb_bytes_exist(tvb, ospflen, crypto_len)) {
+ proto_tree_add_text(ospf_header_tree, tvb, ospflen, crypto_len,
+ "Auth Data: %s",
+ tvb_bytes_to_str(tvb, ospflen, crypto_len));
+ }
+ break;
+
+ default:
+ proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (unknown)");
+ break;
+ }
+
+ }
+
+ /* Instance ID and "reserved" is OSPFv3-only */
+ if ( version == OSPF_VERSION_3 ) {
+ instance_ID = tvb_get_guint8(tvb, 14);
+ proto_tree_add_text(ospf_header_tree, tvb, 14, 1, "Instance ID: %u",
+ instance_ID);
+ reserved = tvb_get_guint8(tvb, 15);
+ proto_tree_add_text(ospf_header_tree, tvb, 15, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
+ reserved);
+
+ }
+
+ /* Adjust the length of the tvbuff to match the size of the OSPF
+ * packet (since the dissect routines use it to work out where the
+ * end of the OSPF packet is).
+ */
+ tvb_set_reported_length(tvb, ospflen);
+
+ switch (packet_type){
+
+ case OSPF_HELLO:
+ dissect_ospf_hello(tvb, ospf_header_length, ospf_tree, version);
+ break;
+
+ case OSPF_DB_DESC:
+ dissect_ospf_db_desc(tvb, ospf_header_length, ospf_tree, version);
+ break;
+
+ case OSPF_LS_REQ:
+ dissect_ospf_ls_req(tvb, ospf_header_length, ospf_tree, version);
+ break;
+
+ case OSPF_LS_UPD:
+ dissect_ospf_ls_upd(tvb, ospf_header_length, ospf_tree, version);
+ break;
+
+ case OSPF_LS_ACK:
+ dissect_ospf_ls_ack(tvb, ospf_header_length, ospf_tree, version);
+ break;
+
+ default:
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, ospf_header_length, -1, -1), pinfo, tree);
+ break;
+ }
+ }
+}
+
+static void
+dissect_ospf_hello(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
+{
+ proto_tree *ospf_hello_tree;
+ proto_item *ti;
+
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "OSPF Hello Packet");
+ ospf_hello_tree = proto_item_add_subtree(ti, ett_ospf_hello);
+
+ switch (version ) {
+ case OSPF_VERSION_2:
+ proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, "Network Mask: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 2,
+ "Hello Interval: %u seconds",
+ tvb_get_ntohs(tvb, offset + 4));
+
+ dissect_ospf_options(tvb, offset + 6, ospf_hello_tree, version);
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 7, 1, "Router Priority: %u",
+ tvb_get_guint8(tvb, offset + 7));
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 4, "Router Dead Interval: %u seconds",
+ tvb_get_ntohl(tvb, offset + 8));
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
+
+ offset += 20;
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
+ "Active Neighbor: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ }
+ break;
+ case OSPF_VERSION_3:
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 0, 4, "Interface ID: %u",
+ tvb_get_ntohl(tvb, offset + 0));
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 1, "Router Priority: %u",
+ tvb_get_guint8(tvb, offset + 4));
+ dissect_ospf_options(tvb, offset + 5, ospf_hello_tree, version);
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 2,
+ "Hello Interval: %u seconds",
+ tvb_get_ntohs(tvb, offset + 8));
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 10, 2, "Router Dead Interval: %u seconds",
+ tvb_get_ntohs(tvb, offset + 10));
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
+ proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
+ offset += 20;
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ proto_tree_add_text(ospf_hello_tree, tvb, offset, 4,
+ "Active Neighbor: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+dissect_ospf_db_desc(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
+{
+ proto_tree *ospf_db_desc_tree=NULL;
+ proto_item *ti;
+ guint8 flags;
+ guint8 reserved;
+ char flags_string[20] = "";
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "OSPF DB Description");
+ ospf_db_desc_tree = proto_item_add_subtree(ti, ett_ospf_desc);
+
+ switch (version ) {
+
+ case OSPF_VERSION_2:
+
+ proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 2, "Interface MTU: %u",
+ tvb_get_ntohs(tvb, offset));
+
+ dissect_ospf_options(tvb, offset + 2, ospf_db_desc_tree, version);
+
+ flags = tvb_get_guint8(tvb, offset + 3);
+ if (flags & OSPF_DBD_FLAG_MS)
+ strcat(flags_string, "MS");
+ if (flags & OSPF_DBD_FLAG_M) {
+ if (flags_string[0] != '\0')
+ strcat(flags_string, "/");
+ strcat(flags_string, "M");
+ }
+ if (flags & OSPF_DBD_FLAG_I) {
+ if (flags_string[0] != '\0')
+ strcat(flags_string, "/");
+ strcat(flags_string, "I");
+ }
+ proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 3, 1, "Flags: 0x%x (%s)",
+ flags, flags_string);
+ proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 4, "DD Sequence: %u",
+ tvb_get_ntohl(tvb, offset + 4));
+
+ offset += 8;
+ break;
+
+ case OSPF_VERSION_3:
+
+ reserved = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
+ reserved);
+
+ dissect_ospf_options(tvb, offset + 1, ospf_db_desc_tree, version);
+
+ proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 2, "Interface MTU: %u",
+ tvb_get_ntohs(tvb, offset+4));
+
+ reserved = tvb_get_guint8(tvb, offset + 6);
+ proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 6, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
+ reserved);
+
+ flags = tvb_get_guint8(tvb, offset + 7);
+ if (flags & OSPF_DBD_FLAG_MS)
+ strcat(flags_string, "MS");
+ if (flags & OSPF_DBD_FLAG_M) {
+ if (flags_string[0] != '\0')
+ strcat(flags_string, "/");
+ strcat(flags_string, "M");
+ }
+ if (flags & OSPF_DBD_FLAG_I) {
+ if (flags_string[0] != '\0')
+ strcat(flags_string, "/");
+ strcat(flags_string, "I");
+ }
+ proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 7, 1, "Flags: 0x%x (%s)",
+ flags, flags_string);
+
+ proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 8, 4, "DD Sequence: %u",
+ tvb_get_ntohl(tvb, offset + 8));
+
+ offset += 12;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* LS Headers will be processed here */
+ /* skip to the end of DB-Desc header */
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ if ( version == OSPF_VERSION_2)
+ offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
+ else
+ if ( version == OSPF_VERSION_3)
+ offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
+ }
+
+}
+
+static void
+dissect_ospf_ls_req(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
+{
+ proto_tree *ospf_lsr_tree;
+ proto_item *ti;
+ guint32 ls_type;
+ guint16 reserved;
+
+ /* zero or more LS requests may be within a LS Request */
+ /* we place every request for a LSA in a single subtree */
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ ti = proto_tree_add_text(tree, tvb, offset, OSPF_LS_REQ_LENGTH,
+ "Link State Request");
+ ospf_lsr_tree = proto_item_add_subtree(ti, ett_ospf_lsr);
+
+ switch ( version ) {
+
+ case OSPF_VERSION_2:
+ ls_type = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_LS_TYPE],
+ tvb, offset, 4, FALSE);
+ break;
+ case OSPF_VERSION_3:
+ reserved = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(ospf_lsr_tree, tvb, offset, 2,
+ (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"), reserved);
+ ls_type = tvb_get_ntohs(tvb, offset+2);
+ proto_tree_add_text(ospf_lsr_tree, tvb, offset+2, 2, "LS Type: %s (0x%04x)",
+ val_to_str(ls_type, v3_ls_type_vals, "Unknown"),
+ ls_type);
+ break;
+ default:
+ ls_type=0;
+ break;
+ }
+
+
+ proto_tree_add_text(ospf_lsr_tree, tvb, offset + 4, 4, "Link State ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
+ proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_ADV_ROUTER],
+ tvb, offset + 8, 4, FALSE);
+
+ offset += 12;
+ }
+}
+
+static void
+dissect_ospf_ls_upd(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
+{
+ proto_tree *ospf_lsa_upd_tree=NULL;
+ proto_item *ti;
+ guint32 lsa_nr;
+ guint32 lsa_counter;
+
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "LS Update Packet");
+ ospf_lsa_upd_tree = proto_item_add_subtree(ti, ett_ospf_lsa_upd);
+
+ lsa_nr = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(ospf_lsa_upd_tree, tvb, offset, 4, "Number of LSAs: %u",
+ lsa_nr);
+ /* skip to the beginning of the first LSA */
+ offset += 4; /* the LS Upd Packet contains only a 32 bit #LSAs field */
+
+ lsa_counter = 0;
+ while (lsa_counter < lsa_nr) {
+ if ( version == OSPF_VERSION_2)
+ offset = dissect_ospf_v2_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
+ else
+ if ( version == OSPF_VERSION_3)
+ offset = dissect_ospf_v3_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE);
+ lsa_counter += 1;
+ }
+}
+
+static void
+dissect_ospf_ls_ack(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
+{
+ /* the body of a LS Ack packet simply contains zero or more LSA Headers */
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ if ( version == OSPF_VERSION_2)
+ offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE);
+ else
+ if ( version == OSPF_VERSION_3)
+ offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE);
+ }
+}
+
+/*
+ * Returns if an LSA is opaque, i.e. requires special treatment
+ */
+static int
+is_opaque(int lsa_type)
+{
+ return (lsa_type >= OSPF_LSTYPE_OP_LINKLOCAL &&
+ lsa_type <= OSPF_LSTYPE_OP_ASWIDE);
+}
+
+/* MPLS/TE TLV types */
+#define MPLS_TLV_ROUTER 1
+#define MPLS_TLV_LINK 2
+
+/* MPLS/TE Link STLV types */
+enum {
+ MPLS_LINK_TYPE = 1,
+ MPLS_LINK_ID,
+ MPLS_LINK_LOCAL_IF,
+ MPLS_LINK_REMOTE_IF,
+ MPLS_LINK_TE_METRIC,
+ MPLS_LINK_MAX_BW,
+ MPLS_LINK_MAX_RES_BW,
+ MPLS_LINK_UNRES_BW,
+ MPLS_LINK_COLOR,
+ MPLS_LINK_LOCAL_ID = 11,
+ MPLS_LINK_REMOTE_ID,
+ MPLS_LINK_PROTECTION = 14,
+ MPLS_LINK_IF_SWITCHING_DESC,
+ MPLS_LINK_SHARED_RISK_GROUP
+};
+
+static const value_string mpls_link_stlv_str[] = {
+ {MPLS_LINK_TYPE, "Link Type"},
+ {MPLS_LINK_ID, "Link ID"},
+ {MPLS_LINK_LOCAL_IF, "Local Interface IP Address"},
+ {MPLS_LINK_REMOTE_IF, "Remote Interface IP Address"},
+ {MPLS_LINK_TE_METRIC, "Traffic Engineering Metric"},
+ {MPLS_LINK_MAX_BW, "Maximum Bandwidth"},
+ {MPLS_LINK_MAX_RES_BW, "Maximum Reservable Bandwidth"},
+ {MPLS_LINK_UNRES_BW, "Unreserved Bandwidth"},
+ {MPLS_LINK_COLOR, "Resource Class/Color"},
+ {MPLS_LINK_LOCAL_ID, "Link Local Identifier"},
+ {MPLS_LINK_REMOTE_ID, "Link Remote Identifier"},
+ {MPLS_LINK_PROTECTION, "Link Protection Type"},
+ {MPLS_LINK_IF_SWITCHING_DESC, "Interface Switching Capability Descriptor"},
+ {MPLS_LINK_SHARED_RISK_GROUP, "Shared Risk Link Group"},
+ {0, NULL},
+};
+
+/*
+ * Dissect MPLS/TE opaque LSA
+ */
+static void
+dissect_ospf_lsa_mpls(tvbuff_t *tvb, int offset, proto_tree *tree,
+ guint32 length)
+{
+ proto_item *ti;
+ proto_tree *mpls_tree;
+ proto_tree *tlv_tree;
+ proto_tree *stlv_tree;
+
+ int tlv_type;
+ int tlv_length;
+ int tlv_end_offset;
+
+ int stlv_type, stlv_len, stlv_offset;
+ char *stlv_name;
+ int i;
+
+ ti = proto_tree_add_text(tree, tvb, offset, length,
+ "MPLS Traffic Engineering LSA");
+ proto_tree_add_item_hidden(tree, ospf_filter[OSPFF_LS_MPLS],
+ tvb, offset, 2, FALSE);
+ mpls_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls);
+
+ while (length != 0) {
+ tlv_type = tvb_get_ntohs(tvb, offset);
+ tlv_length = tvb_get_ntohs(tvb, offset + 2);
+ tlv_end_offset = offset + tlv_length + 4;
+
+ switch (tlv_type) {
+
+ case MPLS_TLV_ROUTER:
+ ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
+ "Router Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
+ tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_router);
+ proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 1 - Router Address");
+ proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
+ tlv_length);
+ proto_tree_add_item(tlv_tree, ospf_filter[OSPFF_LS_MPLS_ROUTERID],
+ tvb, offset+4, 4, FALSE);
+ break;
+
+ case MPLS_TLV_LINK:
+ ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
+ "Link Information");
+ tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
+ proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 2 - Link Information");
+ proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
+ tlv_length);
+ stlv_offset = offset + 4;
+
+ /* Walk down the sub-TLVs for link information */
+ while (stlv_offset < tlv_end_offset) {
+ stlv_type = tvb_get_ntohs(tvb, stlv_offset);
+ stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2);
+ stlv_name = val_to_str(stlv_type, mpls_link_stlv_str, "Unknown sub-TLV");
+ switch (stlv_type) {
+
+ case MPLS_LINK_TYPE:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s: %u", stlv_name,
+ tvb_get_guint8(tvb, stlv_offset + 4));
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "%s: %u", stlv_name,
+ tvb_get_guint8(tvb, stlv_offset + 4));
+ break;
+
+ case MPLS_LINK_ID:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s: %s (%x)", stlv_name,
+ ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)),
+ tvb_get_ntohl(tvb, stlv_offset + 4));
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ proto_tree_add_item(stlv_tree, ospf_filter[OSPFF_LS_MPLS_LINKID],
+ tvb, stlv_offset+4, 4, FALSE);
+ break;
+
+ case MPLS_LINK_LOCAL_IF:
+ case MPLS_LINK_REMOTE_IF:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s", stlv_name);
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ /* The Local/Remote Interface IP Address sub-TLV is TLV type 3/4, and is 4N
+ octets in length, where N is the number of neighbor addresses. */
+ for (i=0; i < stlv_len; i+=4)
+ proto_tree_add_item(stlv_tree,
+ stlv_type==MPLS_LINK_LOCAL_IF ?
+ ospf_filter[OSPFF_LS_MPLS_LOCAL_ADDR] :
+ ospf_filter[OSPFF_LS_MPLS_REMOTE_ADDR],
+ tvb, stlv_offset+4+i, 4, FALSE);
+ break;
+
+ case MPLS_LINK_TE_METRIC:
+ case MPLS_LINK_COLOR:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s: %u", stlv_name,
+ tvb_get_ntohl(tvb, stlv_offset + 4));
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %u", stlv_name,
+ tvb_get_ntohl(tvb, stlv_offset + 4));
+ break;
+
+ case MPLS_LINK_MAX_BW:
+ case MPLS_LINK_MAX_RES_BW:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s: %.10g", stlv_name,
+ tvb_get_ntohieee_float(tvb, stlv_offset + 4));
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %.10g", stlv_name,
+ tvb_get_ntohieee_float(tvb, stlv_offset + 4));
+ break;
+
+ case MPLS_LINK_UNRES_BW:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s", stlv_name);
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ for (i = 0; i < 8; i++) {
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+(i*4), 4,
+ "Pri %d: %.10g bytes/s (%.0f bits/s)", i,
+ tvb_get_ntohieee_float(tvb, stlv_offset + 4 + i*4),
+ tvb_get_ntohieee_float(tvb, stlv_offset + 4 + i*4) * 8.0);
+ }
+ break;
+
+ case MPLS_LINK_LOCAL_ID:
+ case MPLS_LINK_REMOTE_ID:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "Link Local/Remote Identifier");
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "Local ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4)));
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+8, 4, "Remote ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, stlv_offset + 8, 4)));
+ break;
+
+ case MPLS_LINK_IF_SWITCHING_DESC:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s", stlv_name);
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Switching Type: %s",
+ val_to_str(tvb_get_guint8(tvb,stlv_offset+4),
+ gmpls_switching_type_str, "Unknown (%d)"));
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+5, 1, "Encoding: %s",
+ val_to_str(tvb_get_guint8(tvb,stlv_offset+5),
+ gmpls_lsp_enc_str, "Unknown (%d)"));
+ for (i = 0; i < 8; i++) {
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+8+(i*4), 4,
+ "Pri %d: %.10g bytes/s (%.0f bits/s)", i,
+ tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4),
+ tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4) * 8.0);
+ }
+ break;
+ case MPLS_LINK_PROTECTION:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s", stlv_name);
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Protection Capability: %s (0x%x)",
+ val_to_str(tvb_get_guint8(tvb,stlv_offset+4), gmpls_protection_cap_str, "Unknown (%d)"),tvb_get_guint8(tvb,stlv_offset+4));
+ break;
+
+ case MPLS_LINK_SHARED_RISK_GROUP:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s", stlv_name);
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ for (i=0; i < stlv_len; i+=4)
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+i, 4, "Shared Risk Link Group: %u",
+ tvb_get_ntohl(tvb,stlv_offset+4+i));
+ break;
+
+ default:
+ proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "Unknown Link sub-TLV: %u", stlv_type);
+ break;
+ }
+ stlv_offset += ((stlv_len+4+3)/4)*4;
+ }
+ break;
+
+ default:
+ ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4,
+ "Unknown LSA: %u", tlv_type);
+ tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link);
+ proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: %u - Unknown",
+ tlv_type);
+ proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u",
+ tlv_length);
+ proto_tree_add_text(tlv_tree, tvb, offset+4, tlv_length, "TLV Data");
+ break;
+ }
+
+ offset += tlv_length + 4;
+ length -= tlv_length + 4;
+ }
+}
+
+/*
+ * Dissect opaque LSAs
+ */
+static void
+dissect_ospf_lsa_opaque(tvbuff_t *tvb, int offset, proto_tree *tree,
+ guint8 ls_id_type, guint32 length)
+{
+ switch (ls_id_type) {
+
+ case OSPF_LSA_MPLS_TE:
+ dissect_ospf_lsa_mpls(tvb, offset, tree, length);
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Unknown LSA Type %u", ls_id_type);
+ break;
+ } /* switch on opaque LSA id */
+}
+
+static int
+dissect_ospf_v2_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
+ gboolean disassemble_body)
+{
+ proto_tree *ospf_lsa_tree;
+ proto_item *ti;
+
+ guint8 ls_type;
+ guint16 ls_length;
+ int end_offset;
+ guint16 nr_links;
+ guint16 nr_tos;
+
+ /* router LSA */
+ guint8 link_type;
+ guint16 link_counter;
+ guint8 tos_counter;
+ char *link_type_str;
+ char *link_type_short_str;
+ char *link_id;
+
+ /* AS-external LSA */
+ guint8 options;
+
+ /* opaque LSA */
+ guint8 ls_id_type;
+
+ ls_type = tvb_get_guint8(tvb, offset + 3);
+ ls_length = tvb_get_ntohs(tvb, offset + 18);
+ end_offset = offset + ls_length;
+
+ if (disassemble_body) {
+ ti = proto_tree_add_text(tree, tvb, offset, ls_length,
+ "LS Type: %s",
+ val_to_str(ls_type, ls_type_vals, "Unknown (%d)"));
+ } else {
+ ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
+ "LSA Header");
+ }
+ ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
+ tvb_get_ntohs(tvb, offset));
+ dissect_ospf_options(tvb, offset + 2, ospf_lsa_tree, OSPF_VERSION_2);
+ proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_TYPE], tvb,
+ offset + 3, 1, FALSE);
+ proto_tree_add_item_hidden(ospf_lsa_tree,
+ ospf_filter[ospf_ls_type_to_filter(ls_type)], tvb,
+ offset + 3, 1, FALSE);
+
+ if (is_opaque(ls_type)) {
+ ls_id_type = tvb_get_guint8(tvb, offset + 4);
+ proto_tree_add_uint(ospf_lsa_tree, ospf_filter[OSPFF_LS_OPAQUE_TYPE],
+ tvb, offset + 4, 1, ls_id_type);
+
+ switch (ls_id_type) {
+
+ case OSPF_LSA_MPLS_TE:
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 1, "Link State ID TE-LSA Reserved: %u",
+ tvb_get_guint8(tvb, offset + 5));
+ proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_MPLS_TE_INSTANCE],
+ tvb, offset + 6, 2, FALSE);
+ break;
+
+ default:
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3, "Link State ID Opaque ID: %u",
+ tvb_get_ntoh24(tvb, offset + 5));
+ break;
+ }
+ } else {
+ ls_id_type = 0;
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
+ }
+
+ proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER],
+ tvb, offset + 8, 4, FALSE);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%08x",
+ tvb_get_ntohl(tvb, offset + 12));
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
+ tvb_get_ntohs(tvb, offset + 16));
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
+ ls_length);
+
+ /* skip past the LSA header to the body */
+ offset += OSPF_LSA_HEADER_LENGTH;
+ if (ls_length <= OSPF_LSA_HEADER_LENGTH)
+ return offset; /* no data, or bogus length */
+ ls_length -= OSPF_LSA_HEADER_LENGTH;
+
+ if (!disassemble_body)
+ return offset;
+
+ switch (ls_type){
+
+ case OSPF_LSTYPE_ROUTER:
+ /* again: flags should be secified in detail */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x",
+ tvb_get_guint8(tvb, offset));
+ nr_links = tvb_get_ntohs(tvb, offset + 2);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "Number of Links: %u",
+ nr_links);
+ offset += 4;
+ /* nr_links links follow
+ * maybe we should put each of the links into its own subtree ???
+ */
+ for (link_counter = 1; link_counter <= nr_links; link_counter++) {
+ proto_tree *ospf_lsa_router_link_tree;
+ proto_item *ti_local;
+
+
+ /* check the Link Type and ID */
+ link_type = tvb_get_guint8(tvb, offset + 8);
+ switch (link_type) {
+
+ case OSPF_LINK_PTP:
+ link_type_str="Point-to-point connection to another router";
+ link_type_short_str="PTP";
+ link_id="Neighboring router's Router ID";
+ break;
+
+ case OSPF_LINK_TRANSIT:
+ link_type_str="Connection to a transit network";
+ link_type_short_str="Transit";
+ link_id="IP address of Designated Router";
+ break;
+
+ case OSPF_LINK_STUB:
+ link_type_str="Connection to a stub network";
+ link_type_short_str="Stub";
+ link_id="IP network/subnet number";
+ break;
+
+ case OSPF_LINK_VIRTUAL:
+ link_type_str="Virtual link";
+ link_type_short_str="Virtual";
+ link_id="Neighboring router's Router ID";
+ break;
+
+ default:
+ link_type_str="Unknown link type";
+ link_type_short_str="Unknown";
+ link_id="Unknown link ID";
+ break;
+ }
+
+ nr_tos = tvb_get_guint8(tvb, offset + 9);
+
+
+ ti_local = proto_tree_add_text(ospf_lsa_tree, tvb, offset, 12 + 4 * nr_tos,
+ "Type: %-8s ID: %-15s Data: %-15s Metric: %d",
+ link_type_short_str,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)),
+ ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)),
+ tvb_get_ntohs(tvb, offset + 10));
+
+ ospf_lsa_router_link_tree = proto_item_add_subtree(ti_local, ett_ospf_lsa_router_link);
+
+ proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset, 4, "%s: %s", link_id,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+
+ /* link_data should be specified in detail (e.g. network mask) (depends on link type)*/
+ proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 4, 4, "Link Data: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
+
+ proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 8, 1, "Link Type: %u - %s",
+ link_type, link_type_str);
+ proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 9, 1, "Number of TOS metrics: %u",
+ nr_tos);
+ proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 10, 2, "TOS 0 metric: %u",
+ tvb_get_ntohs(tvb, offset + 10));
+
+ offset += 12;
+
+ /* nr_tos metrics may follow each link
+ * ATTENTION: TOS metrics are not tested (I don't have TOS
+ * based routing)
+ * please send me a mail if it is/isn't working
+ */
+ for (tos_counter = 1; tos_counter <= nr_tos; tos_counter++) {
+ proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_ntohs(tvb, offset + 2));
+ offset += 4;
+ }
+ }
+ break;
+
+ case OSPF_LSTYPE_NETWORK:
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ while (offset < end_offset) {
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ }
+ break;
+
+ case OSPF_LSTYPE_SUMMERY:
+ /* Type 3 and 4 LSAs have the same format */
+ case OSPF_LSTYPE_ASBR:
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Metric: %u",
+ tvb_get_ntoh24(tvb, offset + 1));
+ offset += 4;
+
+ /* TOS-specific information, if any */
+ while (offset < end_offset) {
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_ntoh24(tvb, offset + 1));
+ offset += 4;
+ }
+ break;
+
+ case OSPF_LSTYPE_ASEXT:
+ case OSPF_LSTYPE_ASEXT7:
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ options = tvb_get_guint8(tvb, offset);
+ if (options & 0x80) { /* check wether or not E bit is set */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
+ "External Type: Type 2 (metric is larger than any other link state path)");
+ } else {
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
+ "External Type: Type 1 (metric is specified in the same units as interface cost)");
+ }
+ /* the metric field of a AS-external LAS is specified in 3 bytes */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3, "Metric: %u",
+ tvb_get_ntoh24(tvb, offset + 1));
+ offset += 4;
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ /* TOS-specific information, if any */
+ while (offset < end_offset) {
+ options = tvb_get_guint8(tvb, offset);
+ if (options & 0x80) { /* check wether or not E bit is set */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
+ "External Type: Type 2 (metric is larger than any other link state path)");
+ } else {
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
+ "External Type: Type 1 (metric is specified in the same units as interface cost)");
+ }
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u",
+ options & 0x7F,
+ tvb_get_ntoh24(tvb, offset + 1));
+ offset += 4;
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case OSPF_LSTYPE_OP_LINKLOCAL:
+ case OSPF_LSTYPE_OP_AREALOCAL:
+ case OSPF_LSTYPE_OP_ASWIDE:
+ /*
+ * RFC 2370 opaque LSAs.
+ */
+ dissect_ospf_lsa_opaque(tvb, offset, ospf_lsa_tree, ls_id_type,
+ ls_length);
+ offset += ls_length;
+ break;
+
+ default:
+ /* unknown LSA type */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
+ "Unknown LSA Type");
+ offset += ls_length;
+ break;
+ }
+ /* return the offset of the next LSA */
+ return offset;
+}
+
+static int
+dissect_ospf_v3_lsa(tvbuff_t *tvb, int offset, proto_tree *tree,
+ gboolean disassemble_body)
+{
+ proto_tree *ospf_lsa_tree;
+ proto_item *ti;
+
+ guint16 ls_type;
+ guint16 ls_length;
+ int end_offset;
+ guint8 reserved;
+
+ /* router LSA */
+ guint8 link_type;
+ char *link_type_str;
+ guint32 metric;
+
+ guint8 router_lsa_flags;
+ char router_lsa_flags_string[5];
+
+ guint8 router_priority;
+ guint32 number_prefixes;
+ guint8 prefix_length;
+ guint16 reserved16;
+
+ guint16 referenced_ls_type;
+
+ guint8 flags;
+ guint8 flags_string[4];
+ guint32 external_route_tag;
+
+
+ ls_type = tvb_get_ntohs(tvb, offset + 2);
+ ls_length = tvb_get_ntohs(tvb, offset + 18);
+ end_offset = offset + ls_length;
+
+ if (disassemble_body) {
+ ti = proto_tree_add_text(tree, tvb, offset, ls_length,
+ "%s (Type: 0x%04x)", val_to_str(ls_type, v3_ls_type_vals,"Unknown"), ls_type);
+ } else {
+ ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH,
+ "LSA Header");
+ }
+ ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa);
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds",
+ tvb_get_ntohs(tvb, offset));
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "LSA Type: 0x%04x (%s)",
+ ls_type, val_to_str(ls_type, v3_ls_type_vals,"Unkown"));
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
+
+ proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER],
+ tvb, offset + 8, 4, FALSE);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%08x",
+ tvb_get_ntohl(tvb, offset + 12));
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
+ tvb_get_ntohs(tvb, offset + 16));
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u",
+ ls_length);
+
+ /* skip past the LSA header to the body */
+ offset += OSPF_LSA_HEADER_LENGTH;
+ ls_length -= OSPF_LSA_HEADER_LENGTH;
+
+ if (!disassemble_body)
+ return offset;
+
+ switch (ls_type){
+
+
+ case OSPF_V3_LSTYPE_ROUTER:
+
+ /* flags field in an router-lsa */
+ router_lsa_flags=tvb_get_guint8(tvb,offset);
+ if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_B)
+ router_lsa_flags_string[3] = 'B';
+ else
+ router_lsa_flags_string[3] = '.';
+ if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_E)
+ router_lsa_flags_string[2] = 'E';
+ else
+ router_lsa_flags_string[2] = '.';
+ if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_V)
+ router_lsa_flags_string[1] = 'V';
+ else
+ router_lsa_flags_string[1] = '.';
+ if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_W)
+ router_lsa_flags_string[0] = 'W';
+ else
+ router_lsa_flags_string[0] = '.';
+
+ router_lsa_flags_string[4]=0;
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x (%s)",
+ router_lsa_flags, router_lsa_flags_string);
+
+ /* options field in an router-lsa */
+ dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
+
+ /* skip the router-lsa flags and options */
+ offset+=4;
+ ls_length-=4;
+
+ if (ls_length > 0)
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
+ "Router Interfaces:");
+
+ /* scan all router-lsa router interfaces */
+ /* maybe we should put each of the links into its own subtree ??? */
+ while (ls_length > 0 ) {
+
+ /* check the type */
+ link_type = tvb_get_guint8(tvb, offset);
+ switch (link_type) {
+
+ case OSPF_V3_LINK_PTP:
+ link_type_str="Point-to-point connection to another router";
+ break;
+
+ case OSPF_V3_LINK_TRANSIT:
+ link_type_str="Connection to a transit network";
+ break;
+
+ case OSPF_V3_LINK_RESERVED:
+ link_type_str="Connection to a stub network";
+ break;
+
+ case OSPF_V3_LINK_VIRTUAL:
+ link_type_str="Virtual link";
+ break;
+
+ default:
+ link_type_str="Unknown link type";
+ break;
+ }
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Type: %u (%s)", link_type,link_type_str);
+
+ /* reserved field */
+ reserved = tvb_get_guint8(tvb, offset+1);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 1,
+ (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
+
+ /* metric */
+ metric=tvb_get_ntohs(tvb, offset+2);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2,"Metric: %u",metric);
+
+ /* Interface ID */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Interface ID: %u",
+ tvb_get_ntohl(tvb, offset + 4));
+
+ /* Neighbor Interface ID */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Neighbor Interface ID: %u",
+ tvb_get_ntohl(tvb, offset + 8));
+
+ /* Neighbor Router ID */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "Neighbor Router ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
+
+ /* skip to the (possible) next entry */
+ offset+=16;
+ ls_length-=16;
+
+ }
+ break;
+
+ case OSPF_V3_LSTYPE_NETWORK:
+
+ /* reserved field */
+ reserved = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
+ (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
+
+ /* options field in an network-lsa */
+ dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
+
+ offset += 4;
+ ls_length-=4;
+
+ while (ls_length > 0 ) {
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ ls_length-=4;
+ offset += 4;
+ }
+ break;
+
+
+ case OSPF_V3_LSTYPE_INTER_AREA_PREFIX:
+
+ /* reserved field */
+ reserved = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
+ (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
+
+ /* metric */
+ metric=tvb_get_ntoh24(tvb, offset+1);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3,"Metric: %u",metric);
+
+ /* prefix length */
+ prefix_length=tvb_get_guint8(tvb, offset+4);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
+
+ /* prefix options */
+ dissect_ospf_v3_prefix_options(tvb, offset+5, ospf_lsa_tree);
+
+ /* 16 bits reserved */
+ reserved16=tvb_get_ntohs(tvb, offset+6);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,
+ (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved16);
+
+ offset+=8;
+
+ /* address_prefix */
+ dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
+
+ offset+=(prefix_length+31)/32*4;
+
+ break;
+
+
+ case OSPF_V3_LSTYPE_INTER_AREA_ROUTER:
+
+ /* reserved field */
+ reserved = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1,
+ (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
+
+ /* options field in an inter-area-router-lsa */
+ dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
+
+ /* reserved field */
+ reserved = tvb_get_guint8(tvb, offset+4);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1,
+ (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved);
+
+ /* metric */
+ metric=tvb_get_ntoh24(tvb, offset+5);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3,"Metric: %u",metric);
+
+ /* Destination Router ID */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Destination Router ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
+
+ offset+=12;
+ break;
+
+
+ case OSPF_V3_LSTYPE_AS_EXTERNAL:
+
+ /* flags */
+ flags=tvb_get_guint8(tvb, offset);
+ if (flags & OSPF_V3_AS_EXTERNAL_FLAG_E)
+ flags_string[0] = 'E';
+ else
+ flags_string[0] = '.';
+ if (flags & OSPF_V3_AS_EXTERNAL_FLAG_F)
+ flags_string[1] = 'F';
+ else
+ flags_string[1] = '.';
+ if (flags & OSPF_V3_AS_EXTERNAL_FLAG_T)
+ flags_string[2] = 'T';
+ else
+ flags_string[2] = '.';
+
+ flags_string[3]=0;
+
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x (%s)",
+ flags, flags_string);
+
+ /* 24 bits metric */
+ metric=tvb_get_ntoh24(tvb, offset+1);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 3,
+ "Metric: %u", metric);
+
+ /* prefix length */
+ prefix_length=tvb_get_guint8(tvb, offset+4);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length);
+
+ /* prefix options */
+ dissect_ospf_v3_prefix_options(tvb, offset+5, ospf_lsa_tree);
+
+ /* referenced LS type */
+ referenced_ls_type=tvb_get_ntohs(tvb, offset+6);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,"Referenced LS type 0x%04x (%s)",
+ referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
+
+ offset+=8;
+
+ /* address_prefix */
+ dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
+
+ offset+=(prefix_length+31)/32*4;
+
+ /* Forwarding Address (optional - only if F-flag is on) */
+ if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_F) ) {
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 16,"Forwarding Address: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)));
+
+ offset+=16;
+ }
+
+ /* External Route Tag (optional - only if T-flag is on) */
+ if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_T) ) {
+ external_route_tag=tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4,"External Route Tag: %u",
+ external_route_tag);
+
+ offset+=4;
+ }
+
+ /* Referenced Link State ID (optional - only if Referenced LS type is non-zero */
+ if ( (offset < end_offset) && (referenced_ls_type != 0) ) {
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Referenced Link State ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset+=4;
+ }
+
+ break;
+
+ case OSPF_V3_LSTYPE_LINK:
+
+ /* router priority */
+ router_priority=tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Router Priority: %u", router_priority);
+
+ /* options field in an link-lsa */
+ dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3);
+
+ /* Link-local Interface Address */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 16, "Link-local Interface Address: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, 16)));
+
+ /* Number prefixes */
+ number_prefixes=tvb_get_ntohl(tvb, offset + 20);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+20, 4, "# prefixes: %d",number_prefixes);
+
+ offset+=24;
+
+ while (number_prefixes > 0) {
+
+ /* prefix length */
+ prefix_length=tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
+
+ /* prefix options */
+ dissect_ospf_v3_prefix_options(tvb, offset+1, ospf_lsa_tree);
+
+ /* 16 bits reserved */
+ reserved16=tvb_get_ntohs(tvb, offset+2);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
+ (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved16);
+
+ offset+=4;
+
+ /* address_prefix */
+ dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
+
+ offset+=(prefix_length+31)/32*4;
+
+ number_prefixes--;
+
+ }
+ break;
+
+ case OSPF_V3_LSTYPE_INTRA_AREA_PREFIX:
+
+ /* # prefixes */
+ number_prefixes=tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2,"# prefixes: %u",number_prefixes);
+
+ /* referenced LS type */
+ referenced_ls_type=tvb_get_ntohs(tvb, offset+2);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,"Referenced LS type 0x%04x (%s)",
+ referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
+
+ /* Referenced Link State ID */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Referenced Link State ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
+
+ /* Referenced Advertising Router */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Referenced Advertising Router: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
+
+ offset+=12;
+
+ while (number_prefixes > 0) {
+
+ /* prefix length */
+ prefix_length=tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length);
+
+ /* prefix options */
+ dissect_ospf_v3_prefix_options(tvb, offset+1, ospf_lsa_tree);
+
+ /* 16 bits metric */
+ metric=tvb_get_ntohs(tvb, offset+2);
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,
+ "Metric: %u", metric);
+
+ offset+=4;
+
+ /* address_prefix */
+ dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
+
+ offset+=(prefix_length+31)/32*4;
+
+ number_prefixes--;
+ }
+ break;
+
+ default:
+ /* unknown LSA type */
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length,
+ "Unknown LSA Type 0x%04x",ls_type);
+ offset += ls_length;
+ break;
+ }
+ /* return the offset of the next LSA */
+ return offset;
+}
+
+
+static void
+dissect_ospf_options(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version)
+{
+ guint8 options_ospfv2;
+ guint32 options_ospfv3;
+ char options_string[20] = "";
+
+ /* ATTENTION !!! no check for length of options string - with OSPFv3 maximum length is 14 characters */
+
+ switch ( version ) {
+
+ case OSPF_VERSION_2:
+
+ options_ospfv2 = tvb_get_guint8(tvb, offset);
+
+ if (options_ospfv2 & OSPF_V2_OPTIONS_E)
+ strcat(options_string, "E");
+
+ if (options_ospfv2 & OSPF_V2_OPTIONS_MC) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "MC");
+ }
+
+ if (options_ospfv2 & OSPF_V2_OPTIONS_NP) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "NP");
+ }
+
+ if (options_ospfv2 & OSPF_V2_OPTIONS_EA) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "EA");
+ }
+
+ if (options_ospfv2 & OSPF_V2_OPTIONS_DC) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "DC");
+ }
+
+ if (options_ospfv2 & OSPF_V2_OPTIONS_O) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "O");
+ }
+
+ if (options_ospfv2 & OSPF_V2_OPTIONS_DN) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "DN");
+ }
+
+ proto_tree_add_text(tree, tvb, offset, 1, "Options: 0x%x (%s)",
+ options_ospfv2, options_string);
+ break;
+
+
+ case OSPF_VERSION_3:
+
+ options_ospfv3 = tvb_get_ntoh24(tvb, offset);
+
+ if (options_ospfv3 & OSPF_V3_OPTIONS_V6)
+ strcat(options_string, "V6");
+
+ if (options_ospfv3 & OSPF_V3_OPTIONS_E) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "E");
+ }
+
+ if (options_ospfv3 & OSPF_V3_OPTIONS_MC) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "MC");
+ }
+
+ if (options_ospfv3 & OSPF_V3_OPTIONS_N) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "N");
+ }
+
+ if (options_ospfv3 & OSPF_V3_OPTIONS_R) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "R");
+ }
+
+ if (options_ospfv3 & OSPF_V3_OPTIONS_DC) {
+ if (options_string[0] != '\0')
+ strcat(options_string, "/");
+ strcat(options_string, "DC");
+ }
+
+ proto_tree_add_text(tree, tvb, offset, 3, "Options: 0x%x (%s)",
+ options_ospfv3, options_string);
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+
+static void dissect_ospf_v3_prefix_options(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+
+ guint8 prefix_options;
+ char prefix_options_string[11];
+ guint8 position;
+
+ position=0;
+
+ prefix_options=tvb_get_guint8(tvb, offset);
+
+ strcpy(prefix_options_string,"");
+
+ if (prefix_options & OSPF_V3_PREFIX_OPTION_P) {
+ strcat(prefix_options_string, "P");
+ position++;
+ }
+
+ if (prefix_options & OSPF_V3_PREFIX_OPTION_MC) {
+ if ( (position > 0) && (prefix_options_string[position-1] != '/') ) {
+ strcat(prefix_options_string, "/");
+ position++;
+ }
+ strcat(prefix_options_string, "MC");
+ position+=2;
+ }
+
+ if (prefix_options & OSPF_V3_PREFIX_OPTION_LA) {
+ if ( (position > 0) && (prefix_options_string[position-1] != '/') ) {
+ strcat(prefix_options_string, "/");
+ position++;
+ }
+ strcat(prefix_options_string, "LA");
+ position+=2;
+ }
+
+ if (prefix_options & OSPF_V3_PREFIX_OPTION_NU) {
+ if ( (position > 0) && (prefix_options_string[position-1] != '/') ) {
+ strcat(prefix_options_string, "/");
+ position++;
+ }
+ strcat(prefix_options_string, "NU");
+ }
+
+ prefix_options_string[10]=0;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "PrefixOptions: 0x%02x (%s)",prefix_options, prefix_options_string);
+
+}
+
+
+static void dissect_ospf_v3_address_prefix(tvbuff_t *tvb, int offset, int prefix_length, proto_tree *tree)
+{
+
+ guint8 value;
+ guint8 position;
+ guint8 bufpos;
+ gchar buffer[32+7];
+ gchar bytebuf[3];
+ guint8 bytes_to_process;
+ int start_offset;
+
+ start_offset=offset;
+ position=0;
+ bufpos=0;
+ bytes_to_process=((prefix_length+31)/32)*4;
+
+ while (bytes_to_process > 0 ) {
+
+ value=tvb_get_guint8(tvb, offset);
+
+ if ( (position > 0) && ( (position%2) == 0 ) )
+ buffer[bufpos++]=':';
+
+ sprintf(bytebuf,"%02x",value);
+ buffer[bufpos++]=bytebuf[0];
+ buffer[bufpos++]=bytebuf[1];
+
+ position++;
+ offset++;
+ bytes_to_process--;
+ }
+
+ buffer[bufpos]=0;
+ proto_tree_add_text(tree, tvb, start_offset, ((prefix_length+31)/32)*4, "Address Prefix: %s",buffer);
+
+}
+
+
+void
+proto_register_ospf(void)
+{
+ static gint *ett[] = {
+ &ett_ospf,
+ &ett_ospf_hdr,
+ &ett_ospf_hello,
+ &ett_ospf_desc,
+ &ett_ospf_lsr,
+ &ett_ospf_lsa,
+ &ett_ospf_lsa_router_link,
+ &ett_ospf_lsa_upd,
+ &ett_ospf_lsa_mpls,
+ &ett_ospf_lsa_mpls_router,
+ &ett_ospf_lsa_mpls_link,
+ &ett_ospf_lsa_mpls_link_stlv
+ };
+
+ proto_ospf = proto_register_protocol("Open Shortest Path First",
+ "OSPF", "ospf");
+ proto_register_field_array(proto_ospf, ospff_info, array_length(ospff_info));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ospf(void)
+{
+ dissector_handle_t ospf_handle;
+
+ ospf_handle = create_dissector_handle(dissect_ospf, proto_ospf);
+ dissector_add("ip.proto", IP_PROTO_OSPF, ospf_handle);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-pcnfsd.c b/epan/dissectors/packet-pcnfsd.c
new file mode 100644
index 0000000000..40578c1e49
--- /dev/null
+++ b/epan/dissectors/packet-pcnfsd.c
@@ -0,0 +1,442 @@
+/* packet-pcnfsd.c
+ * Routines for PCNFSD dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-ypbind.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+/*
+Protocol information comes from the book
+ "NFS Illustrated" by Brent Callaghan, ISBN 0-201-32570-5
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "packet-rpc.h"
+#include "packet-pcnfsd.h"
+
+static int proto_pcnfsd = -1;
+static int hf_pcnfsd_procedure_v1 = -1;
+static int hf_pcnfsd_procedure_v2 = -1;
+static int hf_pcnfsd_auth_client = -1;
+static int hf_pcnfsd_auth_ident_obscure = -1;
+static int hf_pcnfsd_auth_ident_clear = -1;
+static int hf_pcnfsd_auth_password_obscure = -1;
+static int hf_pcnfsd_auth_password_clear = -1;
+static int hf_pcnfsd_comment = -1;
+static int hf_pcnfsd_status = -1;
+static int hf_pcnfsd_uid = -1;
+static int hf_pcnfsd_gid = -1;
+static int hf_pcnfsd_gids_count = -1;
+static int hf_pcnfsd_homedir = -1;
+static int hf_pcnfsd_def_umask = -1;
+static int hf_pcnfsd_username = -1;
+
+
+static gint ett_pcnfsd = -1;
+static gint ett_pcnfsd_auth_ident = -1;
+static gint ett_pcnfsd_auth_password = -1;
+static gint ett_pcnfsd_gids = -1;
+
+int
+dissect_pcnfsd_username(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ return dissect_rpc_string(tvb, tree, hf_pcnfsd_username, offset, NULL);
+}
+
+#define MAP_REQ_UID 0
+#define MAP_REQ_GID 1
+#define MAP_REQ_UNAME 2
+#define MAP_REQ_GNAME 3
+
+static const value_string names_mapreq[] =
+{
+ { MAP_REQ_UID, "MAP_REQ_UID" },
+ { MAP_REQ_GID, "MAP_REQ_GID" },
+ { MAP_REQ_UNAME, "MAP_REQ_UNAME" },
+ { MAP_REQ_GNAME, "MAP_REQ_GNAME" },
+ { 0, NULL }
+};
+
+int
+dissect_pcnfsd_mapreq(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint32 mapreq;
+
+ mapreq = tvb_get_ntohl(tvb, offset + 0);
+
+ if (tree)
+ proto_tree_add_text(tree, tvb, offset, 4, "Request: %s (%u)",
+ val_to_str(mapreq, names_mapreq, "%u"), mapreq);
+
+ offset += 4;
+
+ return offset;
+}
+
+int
+dissect_pcnfsd2_dissect_mapreq_arg_item(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_pcnfsd_mapreq(tvb, offset, tree);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_uid, offset);
+
+ offset = dissect_pcnfsd_username(tvb, offset, tree);
+
+ return offset;
+}
+
+int
+dissect_pcnfsd2_mapid_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree, hf_pcnfsd_comment, offset, NULL);
+
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset,
+ dissect_pcnfsd2_dissect_mapreq_arg_item);
+
+ return offset;
+}
+
+#define MAP_RES_OK 0
+#define MAP_RES_UNKNOWN 1
+#define MAP_RES_DENIED 2
+
+static const value_string names_maprstat[] =
+{
+ { MAP_RES_OK, "MAP_RES_OK" },
+ { MAP_RES_UNKNOWN, "MAP_RES_UNKNOWN" },
+ { MAP_RES_DENIED, "MAP_RES_DENIED" },
+ { 0, NULL }
+};
+
+int
+dissect_pcnfsd2_dissect_mapreq_res_item(tvbuff_t *tvb, int offset,
+ packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 maprstat;
+
+ offset = dissect_pcnfsd_mapreq(tvb, offset, tree);
+
+ maprstat = tvb_get_ntohl(tvb, offset + 0);
+
+ if (tree)
+ proto_tree_add_text(tree, tvb, offset, 4, "Status: %s (%u)",
+ val_to_str(maprstat, names_maprstat, "%u"), maprstat);
+
+ offset += 4;
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_uid, offset);
+
+ offset = dissect_pcnfsd_username(tvb, offset, tree);
+
+ return offset;
+}
+
+int
+dissect_pcnfsd2_mapid_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree, hf_pcnfsd_comment, offset, NULL);
+
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset,
+ dissect_pcnfsd2_dissect_mapreq_res_item);
+
+ return offset;
+}
+
+/* "NFS Illustrated 14.7.13 */
+static void
+pcnfsd_decode_obscure(char* data, int len)
+{
+ for ( ; len>0 ; len--, data++) {
+ *data = (*data ^ 0x5b) & 0x7f;
+ }
+}
+
+
+/* "NFS Illustrated" 14.7.13 */
+static int
+dissect_pcnfsd2_auth_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ int newoffset;
+ char *ident = NULL;
+ proto_item *ident_item = NULL;
+ proto_tree *ident_tree = NULL;
+ char *password = NULL;
+ proto_item *password_item = NULL;
+ proto_tree *password_tree = NULL;
+
+ offset = dissect_rpc_string(tvb, tree,
+ hf_pcnfsd_auth_client, offset, NULL);
+
+ if (tree) {
+ ident_item = proto_tree_add_text(tree, tvb,
+ offset, -1, "Authentication Ident");
+ if (ident_item)
+ ident_tree = proto_item_add_subtree(
+ ident_item, ett_pcnfsd_auth_ident);
+ }
+ newoffset = dissect_rpc_string(tvb, ident_tree,
+ hf_pcnfsd_auth_ident_obscure, offset, &ident);
+ if (ident_item) {
+ proto_item_set_len(ident_item, newoffset-offset);
+ }
+
+ if (ident) {
+ pcnfsd_decode_obscure(ident, strlen(ident));
+ if (ident_tree)
+ proto_tree_add_string(ident_tree,
+ hf_pcnfsd_auth_ident_clear,
+ tvb, offset+4, strlen(ident), ident);
+ }
+ if (ident_item) {
+ proto_item_set_text(ident_item, "Authentication Ident: %s",
+ ident);
+ }
+ if (ident) {
+ g_free(ident);
+ ident = NULL;
+ }
+
+ offset = newoffset;
+
+ if (tree) {
+ password_item = proto_tree_add_text(tree, tvb,
+ offset, -1, "Authentication Password");
+ if (password_item)
+ password_tree = proto_item_add_subtree(
+ password_item, ett_pcnfsd_auth_password);
+ }
+ newoffset = dissect_rpc_string(tvb, password_tree,
+ hf_pcnfsd_auth_password_obscure, offset, &password);
+ if (password_item) {
+ proto_item_set_len(password_item, newoffset-offset);
+ }
+
+ if (password) {
+ pcnfsd_decode_obscure(password, strlen(password));
+ if (password_tree)
+ proto_tree_add_string(password_tree,
+ hf_pcnfsd_auth_password_clear,
+ tvb, offset+4, strlen(password), password);
+ }
+ if (password_item) {
+ proto_item_set_text(password_item, "Authentication Password: %s",
+ password);
+ }
+ if (password) {
+ g_free(password);
+ password = NULL;
+ }
+
+ offset = newoffset;
+
+ offset = dissect_rpc_string(tvb, tree,
+ hf_pcnfsd_comment, offset, NULL);
+
+ return offset;
+}
+
+
+/* "NFS Illustrated" 14.7.13 */
+static int
+dissect_pcnfsd2_auth_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ int gids_count;
+ proto_item *gitem = NULL;
+ proto_tree *gtree = NULL;
+ int gids_i;
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_status, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_uid, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_gid, offset);
+ gids_count = tvb_get_ntohl(tvb,offset+0);
+ if (tree) {
+ gitem = proto_tree_add_text(tree, tvb,
+ offset, 4+gids_count*4, "Group IDs: %d", gids_count);
+ gtree = proto_item_add_subtree(gitem, ett_pcnfsd_gids);
+ }
+ if (gtree) {
+ proto_tree_add_item(gtree, hf_pcnfsd_gids_count, tvb, offset, 4, FALSE);
+ }
+ offset += 4;
+ for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
+ offset = dissect_rpc_uint32(tvb, gtree,
+ hf_pcnfsd_gid, offset);
+ }
+ offset = dissect_rpc_string(tvb, tree,
+ hf_pcnfsd_homedir, offset, NULL);
+ /* should be signed int32 */
+ offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_def_umask, offset);
+ offset = dissect_rpc_string(tvb, tree,
+ hf_pcnfsd_comment, offset, NULL);
+
+ return offset;
+}
+
+
+/* "NFS Illustrated", 14.6 */
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff pcnfsd1_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { 1, "AUTH", NULL, NULL },
+ { 2, "PR_INIT", NULL, NULL },
+ { 3, "PR_START", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string pcnfsd1_proc_vals[] = {
+ { 0, "NULL" },
+ { 1, "AUTH" },
+ { 2, "PR_INIT" },
+ { 3, "PR_START" },
+ { 0, NULL }
+};
+/* end of PCNFS version 1 */
+
+
+/* "NFS Illustrated", 14.7 */
+static const vsff pcnfsd2_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { 1, "INFO", NULL, NULL },
+ { 2, "PR_INIT", NULL, NULL },
+ { 3, "PR_START", NULL, NULL },
+ { 4, "PR_LIST", NULL, NULL },
+ { 5, "PR_QUEUE", NULL, NULL },
+ { 6, "PR_STATUS", NULL, NULL },
+ { 7, "PR_CANCEL", NULL, NULL },
+ { 8, "PR_ADMIN", NULL, NULL },
+ { 9, "PR_REQUEUE", NULL, NULL },
+ { 10, "PR_HOLD", NULL, NULL },
+ { 11, "PR_RELEASE", NULL, NULL },
+ { 12, "MAPID",
+ dissect_pcnfsd2_mapid_call, dissect_pcnfsd2_mapid_reply },
+ { 13, "AUTH",
+ dissect_pcnfsd2_auth_call, dissect_pcnfsd2_auth_reply },
+ { 14, "ALERT", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string pcnfsd2_proc_vals[] = {
+ { 0, "NULL" },
+ { 1, "INFO" },
+ { 2, "PR_INIT" },
+ { 3, "PR_START" },
+ { 4, "PR_LIST" },
+ { 5, "PR_QUEUE" },
+ { 6, "PR_STATUS" },
+ { 7, "PR_CANCEL" },
+ { 8, "PR_ADMIN" },
+ { 9, "PR_REQUEUE" },
+ { 10, "PR_HOLD" },
+ { 11, "PR_RELEASE" },
+ { 12, "MAPID" },
+ { 13, "AUTH" },
+ { 14, "ALERT" },
+ { 0, NULL }
+};
+/* end of PCNFS version 2 */
+
+
+void
+proto_register_pcnfsd(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pcnfsd_procedure_v1, {
+ "V1 Procedure", "pcnfsd.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(pcnfsd1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_pcnfsd_procedure_v2, {
+ "V2 Procedure", "pcnfsd.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(pcnfsd2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_pcnfsd_auth_client, {
+ "Authentication Client", "pcnfsd.auth.client", FT_STRING, BASE_DEC,
+ NULL, 0, "Authentication Client", HFILL }},
+ { &hf_pcnfsd_auth_ident_obscure, {
+ "Obscure Ident", "pcnfsd.auth.ident.obscure", FT_STRING, BASE_DEC,
+ NULL, 0, "Athentication Obscure Ident", HFILL }},
+ { &hf_pcnfsd_auth_ident_clear, {
+ "Clear Ident", "pcnfsd.auth.ident.clear", FT_STRING, BASE_DEC,
+ NULL, 0, "Authentication Clear Ident", HFILL }},
+ { &hf_pcnfsd_auth_password_obscure, {
+ "Obscure Password", "pcnfsd.auth.password.obscure", FT_STRING, BASE_DEC,
+ NULL, 0, "Athentication Obscure Password", HFILL }},
+ { &hf_pcnfsd_auth_password_clear, {
+ "Clear Password", "pcnfsd.auth.password.clear", FT_STRING, BASE_DEC,
+ NULL, 0, "Authentication Clear Password", HFILL }},
+ { &hf_pcnfsd_comment, {
+ "Comment", "pcnfsd.comment", FT_STRING, BASE_DEC,
+ NULL, 0, "Comment", HFILL }},
+ { &hf_pcnfsd_status, {
+ "Reply Status", "pcnfsd.status", FT_UINT32, BASE_DEC,
+ NULL, 0, "Status", HFILL }},
+ { &hf_pcnfsd_uid, {
+ "User ID", "pcnfsd.uid", FT_UINT32, BASE_DEC,
+ NULL, 0, "User ID", HFILL }},
+ { &hf_pcnfsd_gid, {
+ "Group ID", "pcnfsd.gid", FT_UINT32, BASE_DEC,
+ NULL, 0, "Group ID", HFILL }},
+ { &hf_pcnfsd_gids_count, {
+ "Group ID Count", "pcnfsd.gids.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Group ID Count", HFILL }},
+ { &hf_pcnfsd_homedir, {
+ "Home Directory", "pcnfsd.homedir", FT_STRING, BASE_DEC,
+ NULL, 0, "Home Directory", HFILL }},
+ { &hf_pcnfsd_def_umask, {
+ "def_umask", "pcnfsd.def_umask", FT_INT32, BASE_OCT,
+ NULL, 0, "def_umask", HFILL }},
+ { &hf_pcnfsd_username, {
+ "User name", "pcnfsd.username", FT_STRING, BASE_DEC,
+ NULL, 0, "pcnfsd.username", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_pcnfsd,
+ &ett_pcnfsd_auth_ident,
+ &ett_pcnfsd_auth_password,
+ &ett_pcnfsd_gids
+ };
+
+ proto_pcnfsd = proto_register_protocol("PC NFS",
+ "PCNFSD", "pcnfsd");
+ proto_register_field_array(proto_pcnfsd, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pcnfsd(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_pcnfsd, PCNFSD_PROGRAM, ett_pcnfsd);
+ /* Register the procedure tables */
+ rpc_init_proc_table(PCNFSD_PROGRAM, 1, pcnfsd1_proc, hf_pcnfsd_procedure_v1);
+ rpc_init_proc_table(PCNFSD_PROGRAM, 2, pcnfsd2_proc, hf_pcnfsd_procedure_v2);
+}
+
diff --git a/epan/dissectors/packet-pcnfsd.h b/epan/dissectors/packet-pcnfsd.h
new file mode 100644
index 0000000000..f217bdc768
--- /dev/null
+++ b/epan/dissectors/packet-pcnfsd.h
@@ -0,0 +1,31 @@
+/* packet-pcnfsd.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_PCNFSD_H
+#define PACKET_PCNFSD_H
+
+#define PCNFSD_PROGRAM 150001
+
+#endif
+
diff --git a/epan/dissectors/packet-per.c b/epan/dissectors/packet-per.c
new file mode 100644
index 0000000000..a18355ee4a
--- /dev/null
+++ b/epan/dissectors/packet-per.c
@@ -0,0 +1,1544 @@
+/*
+XXX all this offset>>3 and calculations of bytes in the tvb everytime
+we put something in the tree is just silly. should be replaced with some
+proper helper routines
+*/
+/* packet-per.c
+ * Routines for dissection of ASN.1 Aligned PER
+ * 2003 Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "prefs.h"
+#include "packet-per.h"
+
+
+static int proto_per = -1;
+static int hf_per_GeneralString_length = -1;
+static int hf_per_extension_bit = -1;
+static int hf_per_extension_present_bit = -1;
+static int hf_per_choice_extension = -1;
+static int hf_per_num_sequence_extensions = -1;
+static int hf_per_small_number_bit = -1;
+static int hf_per_optional_field_bit = -1;
+static int hf_per_sequence_of_length = -1;
+static int hf_per_object_identifier_length = -1;
+static int hf_per_open_type_length = -1;
+static int hf_per_octet_string_length = -1;
+static int hf_per_bit_string_length = -1;
+
+static gint ett_per_sequence_of_item = -1;
+
+
+/*
+#define DEBUG_ENTRY(x) \
+printf("#%d %s tvb:0x%08x\n",pinfo->fd->num,x,(int)tvb);
+*/
+#define DEBUG_ENTRY(x) \
+ ;
+
+
+
+/* whether the PER helpers should put the internal PER fields into the tree
+ or not.
+*/
+static guint display_internal_per_fields = FALSE;
+
+
+
+static const true_false_string tfs_extension_present_bit = {
+ "",
+ ""
+};
+static const true_false_string tfs_extension_bit = {
+ "Extension bit is set",
+ "Extension bit is clear"
+};
+static const true_false_string tfs_small_number_bit = {
+ "The number is small, 0-63",
+ "The number is large, >63"
+};
+static const true_false_string tfs_optional_field_bit = {
+ "",
+ ""
+};
+
+
+
+
+/* 10.9 */
+/* this decodes and returns a length determinant according to 10.9 */
+guint32
+dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, guint32 *length)
+{
+ guint8 byte;
+ guint32 len;
+
+ if(!length){
+ length=&len;
+ }
+
+ /* byte aligned */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ byte=tvb_get_guint8(tvb, offset>>3);
+ offset+=8;
+
+ if((byte&0x80)==0){
+ *length=byte;
+ if(hf_index!=-1){
+ proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, *length);
+ }
+ return offset;
+ }
+ if((byte&0xc0)==0x80){
+ *length=(byte&0x3f);
+ *length=((*length)<<8)+tvb_get_guint8(tvb, offset>>3);
+ offset+=8;
+ if(hf_index!=-1){
+ proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-2, 2, *length);
+ }
+ return offset;
+ }
+ PER_NOT_DECODED_YET("10.9.3.8.1");
+ return offset;
+}
+
+/* 10.6 normally small non-negative whole number */
+static guint32
+dissect_per_normally_small_nonnegative_whole_number(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, guint32 *length)
+{
+ gboolean small_number;
+ guint32 len;
+
+DEBUG_ENTRY("dissect_per_normally_small_nonnegative_whole_number");
+ if(!length){
+ length=&len;
+ }
+
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, hf_per_small_number_bit, &small_number, NULL);
+ if(!small_number){
+ int i;
+ /* 10.6.1 */
+ *length=0;
+ for(i=0;i<6;i++){
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &small_number, NULL);
+ *length<<=1;
+ if(small_number){
+ *length|=1;
+ }
+ }
+ if(hf_index!=-1){
+ if((offset&0x07)<7){
+ proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, *length);
+ } else {
+ proto_tree_add_uint(tree, hf_index, tvb, (offset>>3), 1, *length);
+ }
+ }
+ return offset;
+ }
+
+ /* 10.6.2 */
+ offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_index, length);
+
+ return offset;
+}
+
+
+
+/* this function reads a GeneralString */
+/* currently based on pure guesswork since RFC2833 didnt tell me much
+ i guess that the PER encoding for this is a normally-small-whole-number
+ followed by a ascii string.
+
+ based on pure guesswork. it looks ok in the only capture i have where
+ there is a 1 byte general string encoded
+*/
+guint32
+dissect_per_GeneralString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index)
+{
+ proto_tree *etr=NULL;
+ guint32 length;
+
+ if(display_internal_per_fields){
+ etr=tree;
+ }
+
+ offset=dissect_per_length_determinant(tvb, offset, pinfo, etr, hf_per_GeneralString_length, &length);
+
+
+ proto_tree_add_item(tree, hf_index, tvb, offset>>3, length, FALSE);
+
+ offset+=length*8;
+
+ return offset;
+}
+
+/* 19 this function dissects a sequence of */
+static guint32
+dissect_per_sequence_of_helper(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *), guint32 length)
+{
+ guint32 i;
+
+DEBUG_ENTRY("dissect_per_sequence_of_helper");
+ for(i=0;i<length;i++){
+ guint32 lold_offset=offset;
+ proto_item *litem;
+ proto_tree *ltree;
+
+ litem=proto_tree_add_text(tree, tvb, offset>>3, 0, "Item %d", i);
+ ltree=proto_item_add_subtree(litem, ett_per_sequence_of_item);
+
+ offset=(*func)(tvb, offset, pinfo, ltree);
+ proto_item_set_len(litem, (offset>>3)!=(lold_offset>>3)?(offset>>3)-(lold_offset>>3):1);
+ }
+
+ return offset;
+}
+guint32
+dissect_per_sequence_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *))
+{
+ proto_item *item;
+ proto_tree *tree;
+ guint32 old_offset=offset;
+ guint32 length;
+ proto_tree *etr = NULL;
+
+DEBUG_ENTRY("dissect_per_sequence_of");
+
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset>>3, 0, FALSE);
+ tree=proto_item_add_subtree(item, ett_index);
+
+ /* semi-constrained whole number for number of elements */
+ /* each element encoded as 10.9 */
+
+ if(display_internal_per_fields){
+ etr=tree;
+ }
+ offset=dissect_per_length_determinant(tvb, offset, pinfo, etr, hf_per_sequence_of_length, &length);
+
+ offset=dissect_per_sequence_of_helper(tvb, offset, pinfo, tree, func, length);
+
+
+ proto_item_set_len(item, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1);
+ return offset;
+}
+
+
+/* dissect a constrained IA5String that consists of the full ASCII set,
+ i.e. no FROM stuff limiting the alphabet
+*/
+guint32
+dissect_per_IA5String(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo, tree, hf_index, min_len, max_len, NULL, NULL);
+
+ return offset;
+}
+
+/* XXX we dont do >64k length strings yet */
+guint32
+dissect_per_restricted_character_string(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len, char *alphabet, int alphabet_length)
+{
+ guint32 length;
+ gboolean byte_aligned;
+ static char str[1024];
+ guint char_pos;
+ int bits_per_char;
+ guint32 old_offset;
+
+DEBUG_ENTRY("dissect_per_restricted_character_string");
+ /* xx.x if the length is 0 bytes there will be no encoding */
+ if(max_len==0){
+ return offset;
+ }
+
+
+ if(min_len==-1){
+ min_len=0;
+ }
+
+
+ /* xx.x */
+ length=max_len;
+ if(min_len!=max_len){
+ proto_tree *etr = NULL;
+
+ if(display_internal_per_fields){
+ etr=tree;
+ }
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ etr, hf_per_octet_string_length, min_len, max_len,
+ &length, NULL, FALSE);
+ }
+
+
+ /* xx.x if length is fixed or constrained to be less than or equal to
+ two bytes, then it will not be byte aligned. */
+ byte_aligned=TRUE;
+ if((min_len==max_len)&&(max_len<=2)){
+ byte_aligned=FALSE;
+ }
+ if(max_len<2){
+ byte_aligned=FALSE;
+ }
+ if(!length){
+ /* there is no string at all, so dont do any byte alignment */
+ byte_aligned=FALSE;
+ }
+
+ if(byte_aligned){
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ }
+
+
+ if(length>=1024){
+ PER_NOT_DECODED_YET("restricted char string too long");
+ length=1024;
+ }
+
+ /* 27.5.2 depending of the alphabet length, find how many bits
+ are used to encode each character */
+/* unaligned PER
+ if(alphabet_length<=2){
+ bits_per_char=1;
+ } else if(alphabet_length<=4){
+ bits_per_char=2;
+ } else if(alphabet_length<=8){
+ bits_per_char=3;
+ } else if(alphabet_length<=16){
+ bits_per_char=4;
+ } else if(alphabet_length<=32){
+ bits_per_char=5;
+ } else if(alphabet_length<=64){
+ bits_per_char=6;
+ } else if(alphabet_length<=128){
+ bits_per_char=7;
+ } else {
+ bits_per_char=8;
+ }
+*/
+ if(alphabet_length<=2){
+ bits_per_char=1;
+ } else if(alphabet_length<=4){
+ bits_per_char=2;
+ } else if(alphabet_length<=16){
+ bits_per_char=4;
+ } else {
+ bits_per_char=8;
+ }
+
+ old_offset=offset;
+ for(char_pos=0;char_pos<length;char_pos++){
+ guchar val;
+ int i;
+ gboolean bit;
+
+ val=0;
+ for(i=0;i<bits_per_char;i++){
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
+ val=(val<<1)|bit;
+ }
+ if (val >= alphabet_length)
+ str[char_pos] = '?'; /* XXX - how to mark this? */
+ else
+ str[char_pos]=alphabet[val];
+ }
+ str[char_pos]=0;
+ proto_tree_add_string(tree, hf_index, tvb, (old_offset>>3), (offset>>3)-(old_offset>>3), str);
+
+ return offset;
+}
+guint32
+dissect_per_NumericString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_index, min_len, max_len, " 0123456789", 11);
+
+ return offset;
+}
+guint32
+dissect_per_PrintableString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
+{
+ offset=dissect_per_restricted_character_string(tvb, offset, pinfo, tree, hf_index, min_len, max_len, " '()+,-.*0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 74);
+ return offset;
+}
+guint32
+dissect_per_BMPString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
+{
+ guint32 length;
+ static char *str;
+
+ /* xx.x if the length is 0 bytes there will be no encoding */
+ if(max_len==0){
+ return offset;
+ }
+
+
+ if(min_len==-1){
+ min_len=0;
+ }
+
+
+ /* xx.x */
+ length=max_len;
+ if(min_len!=max_len){
+ proto_tree *etr = NULL;
+
+ if(display_internal_per_fields){
+ etr=tree;
+ }
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ etr, hf_per_octet_string_length, min_len, max_len,
+ &length, NULL, FALSE);
+ }
+
+
+ /* align to byte boundary */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+
+ if(length>=1024){
+ PER_NOT_DECODED_YET("BMPString too long");
+ length=1024;
+ }
+
+ str = tvb_fake_unicode(tvb, offset>>3, length, FALSE);
+
+ proto_tree_add_string(tree, hf_index, tvb, offset>>3, length*2, str);
+
+ offset+=(length<<3)*2;
+
+ return offset;
+}
+
+
+/* this function dissects a constrained sequence of */
+guint32
+dissect_per_constrained_sequence_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *), int min_len, int max_len)
+{
+ proto_item *item;
+ proto_tree *tree;
+ guint32 old_offset=offset;
+ guint32 length;
+
+
+DEBUG_ENTRY("dissect_per_constrained_sequence_of");
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset>>3, 0, FALSE);
+ tree=proto_item_add_subtree(item, ett_index);
+
+ /* 19.5 if min==max and min,max<64k ==> no length determinant */
+ if((min_len==max_len) && (min_len<65536)){
+ length=min_len;
+ goto call_sohelper;
+ }
+
+ /* 19.6 ub>=64k or unset */
+ if(max_len>=65536){
+ guint32 old_offset=offset;
+ /* semi-constrained whole number for number of elements */
+ /* each element encoded as 10.9 */
+ offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, -1, &length);
+ length+=min_len;
+ proto_tree_add_uint(tree, hf_per_sequence_of_length, tvb, old_offset>>3, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1, length);
+ goto call_sohelper;
+ }
+
+ /* constrained whole number for number of elements */
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_per_sequence_of_length, min_len, max_len,
+ &length, NULL, FALSE);
+
+
+
+call_sohelper:
+ offset=dissect_per_sequence_of_helper(tvb, offset, pinfo, tree, func, length);
+
+
+ proto_item_set_len(item, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1);
+ return offset;
+}
+
+/* this function dissects a constrained set of */
+guint32
+dissect_per_constrained_set_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *), int min_len, int max_len)
+{
+ /* for basic-per a set-of is encoded in the same way as a sequence-of */
+DEBUG_ENTRY("dissect_per_constrained_set_of");
+ offset=dissect_per_constrained_sequence_of(tvb, offset, pinfo, parent_tree, hf_index, ett_index, func, min_len, max_len);
+ return offset;
+}
+
+
+
+
+
+
+/* this function dissects a set of */
+guint32
+dissect_per_set_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *))
+{
+ /* for basic-per a set-of is encoded in the same way as a sequence-of */
+DEBUG_ENTRY("dissect_per_set_of");
+ offset=dissect_per_sequence_of(tvb, offset, pinfo, parent_tree, hf_index, ett_index, func);
+ return offset;
+}
+
+
+
+
+/* this function reads a OBJECT IDENTIFIER */
+guint32
+dissect_per_object_identifier(tvbuff_t *tvb, guint32 offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, char *value_string)
+{
+ int i,count;
+ char str[256],*strp;
+ guint8 byte;
+ guint32 value;
+ proto_tree *etr=NULL;
+
+DEBUG_ENTRY("dissect_per_object_identifier");
+
+ if(display_internal_per_fields){
+ etr=tree;
+ }
+
+ /* first byte is the count and it is byte aligned */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ count=tvb_get_guint8(tvb, offset>>3);
+
+
+ proto_tree_add_uint(etr, hf_per_object_identifier_length, tvb, offset>>3, 1, count);
+ offset+=8;
+
+ value=0;
+ for(i=0,strp=str;i<count;i++){
+ byte=tvb_get_guint8(tvb,offset>>3);
+ offset+=8;
+
+ if((strp-str)>200){
+PER_NOT_DECODED_YET("too long octet_string");
+ /*XXX assert here */
+ return offset;
+ }
+
+ if(i==0){
+ /* the first byte contains the first two object identifier components */
+ if(byte<40){
+ strp+=sprintf(strp,"0.%d",byte);
+ } else if (byte<80){
+ strp+=sprintf(strp,"1.%d",byte-40);
+ } else {
+ strp+=sprintf(strp,"2.%d",byte-80);
+ }
+ continue;
+ }
+
+ value=(value<<7)|(byte&0x7f);
+ if(byte&0x80){
+ continue;
+ }
+
+ strp+=sprintf(strp,".%d",value);
+ value=0;
+ }
+ *strp=0;
+
+ proto_tree_add_string(tree, hf_index, tvb, (offset>>3)-count, count, str);
+
+ if (value_string) {
+ strcpy(value_string, str);
+ }
+
+ return offset;
+}
+
+
+
+
+/* this function reads a single bit */
+guint32
+dissect_per_boolean(tvbuff_t *tvb, guint32 offset, packet_info *pinfo _U_, proto_tree *tree, int hf_index, gboolean *bool, proto_item **item)
+{
+ guint8 ch, mask;
+ gboolean value;
+ header_field_info *hfi;
+ proto_item *it;
+
+DEBUG_ENTRY("dissect_per_boolean");
+
+ ch=tvb_get_guint8(tvb, offset>>3);
+ mask=1<<(7-(offset&0x07));
+ if(ch&mask){
+ value=1;
+ } else {
+ value=0;
+ }
+ if(hf_index!=-1){
+ char str[256];
+ hfi = proto_registrar_get_nth(hf_index);
+ sprintf(str,"%s: %c%c%c%c %c%c%c%c %s",
+ hfi->name,
+ mask&0x80?'0'+value:'.',
+ mask&0x40?'0'+value:'.',
+ mask&0x20?'0'+value:'.',
+ mask&0x10?'0'+value:'.',
+ mask&0x08?'0'+value:'.',
+ mask&0x04?'0'+value:'.',
+ mask&0x02?'0'+value:'.',
+ mask&0x01?'0'+value:'.',
+ value?"True":"False"
+ );
+ it=proto_tree_add_boolean_format(tree, hf_index, tvb, offset>>3, 1, value, str);
+ if(item){
+ *item=it;
+ }
+ }
+
+ if(bool){
+ *bool=value;
+ }
+ return offset+1;
+}
+
+
+
+
+/* we currently only handle integers up to 32 bits in length. */
+guint32
+dissect_per_integer(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, gint32 *value, proto_item **item)
+{
+ guint32 i, length;
+ gint32 val;
+ proto_item *it=NULL;
+
+ /* 12.2.6 b */
+ offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, -1, &length);
+ /* gassert here? */
+ if(length>4){
+PER_NOT_DECODED_YET("too long integer");
+ length=4;
+ }
+
+ val=0;
+ for(i=0;i<length;i++){
+ if(i==0){
+ if(tvb_get_guint8(tvb, offset>>3)&0x80){
+ /* negative number */
+ val=0xffffffff;
+ } else {
+ /* positive number */
+ val=0;
+ }
+ }
+ val=(val<<8)|tvb_get_guint8(tvb,offset>>3);
+ offset+=8;
+ }
+ it=proto_tree_add_int(tree, hf_index, tvb, (offset>>3)-(length+1), length+1, val);
+
+ if(item){
+ *item=it;
+ }
+ if(value){
+ *value=val;
+ }
+
+ return offset;
+}
+
+
+/* this function reads a constrained integer with or without a
+ PER visible extension marker present
+
+ has_extension==TRUE would map to asn constructs such as:
+ rfc-number INTEGER (1..32768, ...)
+ while has_extension==FALSE would map to:
+ t35CountryCode INTEGER (0..255)
+
+ it only handles integers that fit inside a 32 bit integer
+10.5.1 info only
+10.5.2 info only
+10.5.3 range=ub-lb+1
+10.5.4 empty range
+10.5.5 info only
+ 10.5.6 unaligned version
+10.5.7 aligned version
+10.5.7.1 decoding of 0-255 1-8 bits
+10.5.7.2 decoding og 0-256 8 bits
+10.5.7.3 decoding of 0-65535 16 bits
+ 10.5.7.4
+*/
+guint32
+dissect_per_constrained_integer(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, guint32 min, guint32 max, guint32 *value, proto_item **item, gboolean has_extension)
+{
+ proto_item *it=NULL;
+ guint32 range, val;
+ gint val_start, val_length;
+ nstime_t timeval;
+ header_field_info *hfi;
+ int num_bits;
+ int pad;
+ guint32 tmp;
+
+DEBUG_ENTRY("dissect_per_constrained_integer");
+ if(has_extension){
+ gboolean extension_present;
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &extension_present, NULL);
+ if(extension_present){
+ offset=dissect_per_integer(tvb, offset, pinfo, tree,
+ hf_index,
+ NULL, NULL);
+ return offset;
+ }
+ }
+
+ hfi = proto_registrar_get_nth(hf_index);
+
+ /* 10.5.3 */
+ if((max-min)>65536){
+ /* just set range really big so it will fall through
+ to the bottom of the encoding */
+ range=1000000;
+ } else {
+ range=max-min+1;
+ }
+
+ num_bits=0;
+ pad=0;
+ val=0;
+ timeval.secs=val; timeval.nsecs=0;
+ /* 10.5.4 */
+ if(range==1){
+ val_start = offset>>3; val_length = 0;
+ val = min;
+ } else if(range<=255) {
+ /* 10.5.7.1 */
+ char str[256];
+ int i, bit, length;
+
+ length=1;
+ if(range<=2){
+ num_bits=1;
+ } else if(range<=4){
+ num_bits=2;
+ } else if(range<=8){
+ num_bits=3;
+ } else if(range<=16){
+ num_bits=4;
+ } else if(range<=32){
+ num_bits=5;
+ } else if(range<=64){
+ num_bits=6;
+ } else if(range<=128){
+ num_bits=7;
+ } else if(range<=256){
+ num_bits=8;
+ }
+ /* prepare the string */
+ sprintf(str, "%s: ", hfi->name);
+ for(bit=0;bit<((int)(offset&0x07));bit++){
+ if(bit&&(!(bit%4))){
+ strcat(str, " ");
+ }
+ strcat(str,".");
+ }
+ /* read the bits for the int */
+ for(i=0;i<num_bits;i++){
+ if(bit&&(!(bit%4))){
+ strcat(str, " ");
+ }
+ if(bit&&(!(bit%8))){
+ length+=1;
+ strcat(str, " ");
+ }
+ bit++;
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &tmp, NULL);
+ val<<=1;
+ if(tmp){
+ val|=tmp;
+ strcat(str, "1");
+ } else {
+ strcat(str, "0");
+ }
+ }
+ for(;bit%8;bit++){
+ if(bit&&(!(bit%4))){
+ strcat(str, " ");
+ }
+ strcat(str,".");
+ }
+ val_start = (offset-num_bits)>>3; val_length = length;
+ val+=min;
+ } else if(range==256){
+ /* 10.5.7.2 */
+ num_bits=8;
+ pad=7-(offset&0x07);
+
+ /* in the aligned case, align to byte boundary */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ val=tvb_get_guint8(tvb, offset>>3);
+ offset+=8;
+
+ val_start = (offset>>3)-1; val_length = 1;
+ val+=min;
+ } else if(range<=65536){
+ /* 10.5.7.3 */
+ num_bits=16;
+ pad=7-(offset&0x07);
+
+ /* in the aligned case, align to byte boundary */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ val=tvb_get_guint8(tvb, offset>>3);
+ val<<=8;
+ offset+=8;
+ val|=tvb_get_guint8(tvb, offset>>3);
+ offset+=8;
+
+ val_start = (offset>>3)-2; val_length = 2;
+ val+=min;
+ } else {
+ int i,num_bytes;
+ gboolean bit;
+
+ /* 10.5.7.4 */
+ /* 12.2.6 */
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
+ num_bytes=bit;
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
+ num_bytes=(num_bytes<<1)|bit;
+
+ num_bytes++; /* lower bound for length determinant is 1 */
+
+ /* byte aligned */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ val=0;
+ for(i=0;i<num_bytes;i++){
+ val=(val<<8)|tvb_get_guint8(tvb,offset>>3);
+ offset+=8;
+ }
+ val_start = (offset>>3)-(num_bytes+1); val_length = num_bytes+1;
+ val+=min;
+ }
+
+ timeval.secs = val;
+ if (IS_FT_UINT(hfi->type)) {
+ it = proto_tree_add_uint(tree, hf_index, tvb, val_start, val_length, val);
+ } else if (IS_FT_INT(hfi->type)) {
+ it = proto_tree_add_int(tree, hf_index, tvb, val_start, val_length, val);
+ } else if (IS_FT_TIME(hfi->type)) {
+ it = proto_tree_add_time(tree, hf_index, tvb, val_start, val_length, &timeval);
+ } else {
+ g_assert_not_reached();
+ }
+ if (item) *item = it;
+ if (value) *value = val;
+ return offset;}
+
+/* this functions decodes a CHOICE
+ it can only handle CHOICE INDEX values that fits inside a 32 bit integer.
+ 22.1
+ 22.2
+ 22.3
+ 22.4
+ 22.5
+22.6 no extensions
+22.7 extension marker == 0
+ 22.8 extension marker == 1
+*/
+guint32
+dissect_per_choice(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, gint ett_index, per_choice_t *choice, char *name, guint32 *value)
+{
+ gboolean extension_present, extension_flag;
+ int extension_root_entries;
+ guint32 choice_index;
+ int i;
+ proto_item *it=NULL;
+ proto_tree *tr=NULL;
+ guint32 old_offset=offset;
+ int min_choice=INT_MAX;
+ int max_choice=-1;
+
+DEBUG_ENTRY("dissect_per_choice");
+
+ it=proto_tree_add_text(tree, tvb, offset>>3, 0, name);
+ tr=proto_item_add_subtree(it, ett_index);
+
+
+ /* first check if there should be an extension bit for this CHOICE.
+ we do this by just checking the first choice arm
+ */
+ if(choice[0].extension==ASN1_NO_EXTENSIONS){
+ extension_present=0;
+ } else {
+ proto_tree *etr=NULL;
+
+ if(display_internal_per_fields){
+ etr=tr;
+ }
+ extension_present=1;
+ /* will be placed called again below to place it in the tree */
+ offset=dissect_per_boolean(tvb, offset, pinfo, etr, hf_per_extension_bit, &extension_flag, NULL);
+ }
+
+ /* count the number of entries in the extension_root */
+ extension_root_entries=0;
+ for(i=0;choice[i].name;i++){
+ switch(choice[i].extension){
+ case ASN1_NO_EXTENSIONS:
+ case ASN1_EXTENSION_ROOT:
+ if(choice[i].value<min_choice){
+ min_choice=choice[i].value;
+ }
+ if(choice[i].value>max_choice){
+ max_choice=choice[i].value;
+ }
+ extension_root_entries++;
+ break;
+ }
+ }
+
+ if( (!extension_present)
+ || (extension_present && (extension_flag==0)) ){
+ guint32 choice_offset=offset;
+ proto_tree *choicetree;
+ proto_item *choiceitem;
+ proto_tree *etr=NULL;
+
+ /* 22.6 */
+ /* 22.7 */
+/*qqq make it similar to the section below instead */
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tr, hf_index, min_choice, max_choice,
+ &choice_index, &choiceitem, FALSE);
+ if(value){
+ *value=choice_index;
+ }
+
+ choicetree=proto_item_add_subtree(choiceitem, ett_index);
+
+ if(display_internal_per_fields){
+ etr=choicetree;
+ }
+
+ /* find and call the appropriate callback */
+ for(i=0;choice[i].name;i++){
+ if(choice[i].value==(int)choice_index){
+ if(choice[i].func){
+ offset=choice[i].func(tvb, offset, pinfo, choicetree);
+ break;
+ } else {
+ PER_NOT_DECODED_YET(choice[i].name);
+ break;
+ }
+ }
+ }
+ proto_item_set_len(choiceitem, (offset>>3)!=(choice_offset>>3)?(offset>>3)-(choice_offset>>3):1);
+ } else {
+ guint32 length;
+ int i, index;
+ guint32 choice_offset;
+ proto_tree *choicetree;
+ proto_item *choiceitem;
+ proto_tree *etr=NULL;
+
+ if(display_internal_per_fields){
+ etr=tr;
+ }
+
+ /* 22.8 */
+ offset=dissect_per_normally_small_nonnegative_whole_number(tvb, offset, pinfo, etr, hf_per_choice_extension, &choice_index);
+ offset=dissect_per_length_determinant(tvb, offset, pinfo, etr, hf_per_open_type_length, &length);
+
+
+ choice_offset=offset;
+ choiceitem=proto_tree_add_text(tr, tvb, offset>>3, 0, "Choice");
+ choicetree=proto_item_add_subtree(choiceitem, ett_index);
+
+ index=-1;
+ for(i=0;choice[i].name;i++){
+ if(choice[i].extension==ASN1_NOT_EXTENSION_ROOT){
+ if(!choice_index){
+ index=i;
+ break;
+ }
+ choice_index--;
+ }
+ }
+
+ if(index!=-1){
+ if(value){
+ *value=index;
+ }
+ }
+
+ if(index==-1){
+ /* if we dont know how to decode this one, just step offset to the next structure */
+ offset+=length*8;
+ PER_NOT_DECODED_YET("unknown choice extension");
+ } else {
+ guint32 new_offset;
+
+ proto_item_set_text(choiceitem, choice[index].name);
+ new_offset=choice[index].func(tvb, offset, pinfo, choicetree);
+
+ if((new_offset>(offset+(length*8)))||((new_offset+8)<(offset+length*8))){
+printf("new_offset:%d offset:%d length*8:%d\n",new_offset,offset,length*8);
+/* g_assert_not_reached();*/
+ }
+
+ offset+=length*8;
+ }
+ proto_item_set_len(choiceitem, (offset>>3)!=(choice_offset>>3)?(offset>>3)-(choice_offset>>3):1);
+ }
+
+ proto_item_set_len(it, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1);
+ return offset;
+}
+
+
+static char *
+index_get_optional_name(per_sequence_t *sequence, int index)
+{
+ int i;
+
+ for(i=0;sequence[i].name;i++){
+ if((sequence[i].extension!=ASN1_NOT_EXTENSION_ROOT)&&(sequence[i].optional==ASN1_OPTIONAL)){
+ if(index==0){
+ return sequence[i].name;
+ }
+ index--;
+ }
+ }
+ return "<unknown type>";
+}
+
+static char *
+index_get_extension_name(per_sequence_t *sequence, int index)
+{
+ int i;
+
+ for(i=0;sequence[i].name;i++){
+ if(sequence[i].extension==ASN1_NOT_EXTENSION_ROOT){
+ if(index==0){
+ return sequence[i].name;
+ }
+ index--;
+ }
+ }
+ return "<unknown type>";
+}
+
+/* this functions decodes a SEQUENCE
+ it can only handle SEQUENCES with at most 32 DEFAULT or OPTIONAL fields
+18.1 extension bit
+18.2 optinal/default items in root
+18.3 we ignore the case where n>64K
+18.4 the root sequence
+ 18.5
+ 18.6
+ 18.7
+ 18.8
+ 18.9
+*/
+guint32
+dissect_per_sequence(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, per_sequence_t *sequence)
+{
+ gboolean extension_present, extension_flag, optional_field_flag;
+ proto_item *item;
+ proto_tree *tree;
+ guint32 old_offset=offset;
+ guint32 i, num_opts;
+ guint32 optional_mask;
+
+
+DEBUG_ENTRY("dissect_per_sequence");
+
+ item=proto_tree_add_item(parent_tree, hf_index, tvb, offset>>3, 0, FALSE);
+ tree=proto_item_add_subtree(item, ett_index);
+
+
+ /* first check if there should be an extension bit for this CHOICE.
+ we do this by just checking the first choice arm
+ */
+ /* 18.1 */
+ extension_flag=0;
+ if(sequence[0].extension==ASN1_NO_EXTENSIONS){
+ extension_present=0;
+ } else {
+ proto_tree *etr=NULL;
+
+ if(display_internal_per_fields){
+ etr=tree;
+ }
+ extension_present=1;
+ offset=dissect_per_boolean(tvb, offset, pinfo, etr, hf_per_extension_bit, &extension_flag, NULL);
+ }
+ /* 18.2 */
+ num_opts=0;
+ for(i=0;sequence[i].name;i++){
+ if((sequence[i].extension!=ASN1_NOT_EXTENSION_ROOT)&&(sequence[i].optional==ASN1_OPTIONAL)){
+ num_opts++;
+ }
+ }
+
+ optional_mask=0;
+ for(i=0;i<num_opts;i++){
+ proto_item *it=NULL;
+ proto_tree *etr=NULL;
+ if(display_internal_per_fields){
+ etr=tree;
+ }
+ offset=dissect_per_boolean(tvb, offset, pinfo, etr, hf_per_optional_field_bit, &optional_field_flag, &it);
+ optional_mask<<=1;
+ if(optional_field_flag){
+ optional_mask|=0x01;
+ }
+ if(it){
+ proto_item_append_text(it, " (%s %s present)",
+ index_get_optional_name(sequence, i),
+ optional_field_flag?"is":"is NOT"
+ );
+ }
+ }
+
+
+ /* 18.4 */
+ for(i=0;sequence[i].name;i++){
+ if( (sequence[i].extension==ASN1_NO_EXTENSIONS)
+ || (sequence[i].extension==ASN1_EXTENSION_ROOT) ){
+ if(sequence[i].optional==ASN1_OPTIONAL){
+ gboolean is_present;
+ is_present=(1<<(num_opts-1))&optional_mask;
+ num_opts--;
+ if(!is_present){
+ continue;
+ }
+ }
+ if(sequence[i].func){
+ offset=sequence[i].func(tvb, offset, pinfo, tree);
+ } else {
+ PER_NOT_DECODED_YET(sequence[i].name);
+ }
+ }
+ }
+
+
+ if(extension_flag){
+ gboolean extension_bit;
+ guint32 num_known_extensions;
+ guint32 num_extensions;
+ guint32 extension_mask;
+ proto_tree *etr=NULL;
+ proto_item *it=NULL;
+
+ if(display_internal_per_fields){
+ etr=tree;
+ }
+
+ offset=dissect_per_normally_small_nonnegative_whole_number(tvb, offset, pinfo, etr, hf_per_num_sequence_extensions, &num_extensions);
+ /* the X.691 standard is VERY unclear here.
+ there is no mention that the lower bound lb for this
+ (apparently) semiconstrained value is 1,
+ apart from the NOTE: comment in 18.8 that this value can
+ not be 0.
+ In my book, there is a semantic difference between having
+ a comment that says that the value can not be zero
+ and stating that the lb is 1.
+ I dont know if this is right or not but it makes
+ some of the very few captures I have decode properly.
+
+ It could also be that the captures I have are generated by
+ a broken implementation.
+ If this is wrong and you dont report it as a bug
+ then it wont get fixed!
+ */
+ num_extensions+=1;
+
+ extension_mask=0;
+ for(i=0;i<num_extensions;i++){
+ offset=dissect_per_boolean(tvb, offset, pinfo, etr, hf_per_extension_present_bit, &extension_bit, &it);
+ extension_mask=(extension_mask<<1)|extension_bit;
+ if(it){
+ proto_item_append_text(it, " (%s %s present)",
+ index_get_extension_name(sequence, i),
+ extension_bit?"is":"is NOT"
+ );
+ }
+
+ }
+
+ /* find how many extensions we know about */
+ num_known_extensions=0;
+ for(i=0;sequence[i].name;i++){
+ if(sequence[i].extension==ASN1_NOT_EXTENSION_ROOT){
+ num_known_extensions++;
+ }
+ }
+
+ /* decode the extensions one by one */
+ for(i=0;i<num_extensions;i++){
+ guint32 length;
+ guint32 new_offset;
+ guint32 extension_index;
+ guint32 j,k;
+
+ if(!((1L<<(num_extensions-1-i))&extension_mask)){
+ /* this extension is not encoded in this PDU */
+ continue;
+ }
+
+ offset=dissect_per_length_determinant(tvb, offset, pinfo, etr, hf_per_open_type_length, &length);
+
+ if(i>=num_known_extensions){
+ /* we dont know how to decode this extension */
+ offset+=length*8;
+ PER_NOT_DECODED_YET("unknown sequence extension");
+ continue;
+ }
+
+ extension_index=0;
+ for(j=0,k=0;sequence[j].name;j++){
+ if(sequence[j].extension==ASN1_NOT_EXTENSION_ROOT){
+ if(k==i){
+ extension_index=j;
+ break;
+ }
+ k++;
+ }
+ }
+
+ if(sequence[extension_index].func){
+ new_offset=sequence[extension_index].func(tvb, offset, pinfo, tree);
+ } else {
+ PER_NOT_DECODED_YET(sequence[extension_index].name);
+ }
+ offset+=length*8;
+
+ }
+ }
+
+
+ proto_item_set_len(item, (offset>>3)!=(old_offset>>3)?(offset>>3)-(old_offset>>3):1);
+ return offset;
+}
+
+
+
+/* 15 Encoding the bitstring type
+
+ max_len or min_len == -1 means there is no lower/upper constraint
+
+*/
+guint32
+dissect_per_bit_string(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len)
+{
+ guint32 length;
+ header_field_info *hfi;
+
+ hfi = (hf_index==-1) ? NULL : proto_registrar_get_nth(hf_index);
+
+DEBUG_ENTRY("dissect_per_bit_string");
+ /* 15.8 if the length is 0 bytes there will be no encoding */
+ if(max_len==0) {
+ return offset;
+ }
+
+ if(min_len==-1) {
+ min_len=0;
+ }
+
+ /* 15.9 if length is fixed and less than or equal to sixteen bits*/
+ if((min_len==max_len)&&(max_len<=16)){
+ static char bytes[4];
+ int i;
+ guint32 old_offset=offset;
+ gboolean bit;
+
+ bytes[0]=bytes[1]=bytes[2]=0;
+ for(i=0;i<min_len;i++){
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
+ bytes[0]=(bytes[0]<<1)|bit;
+ }
+ if(min_len>8){
+ for(i=8;i<min_len;i++){
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
+ bytes[1]=(bytes[1]<<1)|bit;
+ }
+ if(min_len<16){
+ bytes[1]|=bytes[0]<<(min_len-8);
+ bytes[0]>>=16-min_len;
+ }
+ }
+ if (hfi) {
+ proto_tree_add_bytes(tree, hf_index, tvb, old_offset>>3, (min_len+7)/8+(offset&0x07)?1:0, bytes);
+ }
+ return offset;
+ }
+
+
+ /* 15.10 if length is fixed and less than to 64kbits*/
+ if((min_len==max_len)&&(min_len<65536)){
+ /* align to byte */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ if (hfi) {
+ proto_tree_add_item(tree, hf_index, tvb, offset>>3, (min_len+7)/8, FALSE);
+ }
+ offset+=min_len;
+ return offset;
+ }
+
+ /* 15.11 */
+ if(max_len>0){
+ proto_tree *etr = NULL;
+
+ if(display_internal_per_fields){
+ etr=tree;
+ }
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ etr, hf_per_bit_string_length, min_len, max_len,
+ &length, NULL, FALSE);
+ } else {
+ offset=dissect_per_length_determinant(tvb, offset, pinfo, tree, hf_per_bit_string_length, &length);
+ }
+ if(length){
+ /* align to byte */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ if (hfi) {
+ proto_tree_add_item(tree, hf_index, tvb, offset>>3, (length+7)/8, FALSE);
+ }
+ }
+ offset+=length;
+
+ return offset;
+}
+
+
+/* this fucntion dissects an OCTET STRING
+ 16.1
+ 16.2
+ 16.3
+ 16.4
+ 16.5
+ 16.6
+ 16.7
+ 16.8
+
+ max_len or min_len == -1 means there is no lower/upper constraint
+
+ hf_index can either be a FT_BYTES or an FT_STRING
+*/
+guint32
+dissect_per_octet_string(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len, guint32 *value_offset, guint32 *value_len)
+{
+ proto_tree *etr = NULL;
+ proto_item *it = NULL;
+ gint val_start, val_length;
+ guint32 length;
+ header_field_info *hfi;
+ static char bytes[4];
+ char *pbytes = NULL;
+
+ hfi = (hf_index==-1) ? NULL : proto_registrar_get_nth(hf_index);
+ if (display_internal_per_fields) {
+ etr = tree;
+ }
+
+DEBUG_ENTRY("dissect_per_octet_string");
+
+ if(min_len==-1){
+ min_len=0;
+ }
+
+ if (max_len==0) { /* 16.5 if the length is 0 bytes there will be no encoding */
+ val_start = offset>>3;
+ val_length = 0;
+
+ } else if((min_len==max_len)&&(max_len<=2)) { /* 16.6 if length is fixed and less than or equal to two bytes*/
+ guint32 i, old_offset=offset;
+ gboolean bit;
+
+ for(i=0;i<8;i++){
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
+ bytes[0]=(bytes[0]<<1)|bit;
+ }
+ if(min_len==2){
+ for(i=0;i<8;i++){
+ offset=dissect_per_boolean(tvb, offset, pinfo, tree, -1, &bit, NULL);
+ bytes[1]=(bytes[1]<<1)|bit;
+ }
+ }
+ bytes[min_len]=0;
+ pbytes = bytes;
+ val_start = old_offset>>3;
+ val_length = min_len+(offset&0x07)?1:0;
+
+ } else if ((min_len==max_len)&&(min_len<65536)) { /* 16.7 if length is fixed and less than to 64k*/
+ /* align to byte */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ val_start = offset>>3;
+ val_length = min_len;
+ offset+=min_len*8;
+
+ } else { /* 16.8 */
+ if(max_len>0) {
+ offset = dissect_per_constrained_integer(tvb, offset, pinfo, etr,
+ hf_per_octet_string_length, min_len, max_len,
+ &length, NULL, FALSE);
+ } else {
+ offset = dissect_per_length_determinant(tvb, offset, pinfo, etr,
+ hf_per_octet_string_length, &length);
+ }
+
+ if(length){
+ /* align to byte */
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ }
+ val_start = offset>>3;
+ val_length = length;
+ offset+=length*8;
+ }
+
+ if (hfi) {
+ if (IS_FT_UINT(hfi->type)||IS_FT_INT(hfi->type)) {
+ if (IS_FT_UINT(hfi->type))
+ it = proto_tree_add_uint(tree, hf_index, tvb, val_start, val_length, val_length);
+ else
+ it = proto_tree_add_int(tree, hf_index, tvb, val_start, val_length, val_length);
+ proto_item_append_text(it, (val_length == 1) ? " octet" : " octets");
+ } else {
+ if (pbytes) {
+ if(IS_FT_STRING(hfi->type)){
+ proto_tree_add_string(tree, hf_index, tvb, val_start, val_length, pbytes);
+ } else if (hfi->type==FT_BYTES) {
+ proto_tree_add_bytes(tree, hf_index, tvb, val_start, val_length, pbytes);
+ } else {
+ g_assert_not_reached();
+ }
+ } else {
+ proto_tree_add_item(tree, hf_index, tvb, val_start, val_length, FALSE);
+ }
+ }
+ }
+ if (value_offset) *value_offset = val_start;
+ if (value_len) *value_len = val_length;
+ return offset;
+}
+
+
+
+void
+proto_register_per(void)
+{
+ static hf_register_info hf[] =
+ {
+ { &hf_per_num_sequence_extensions,
+ { "Number of Sequence Extensions", "per.num_sequence_extensions", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of extensions encoded in this sequence", HFILL }},
+ { &hf_per_choice_extension,
+ { "Choice Extension", "per.choice_extension", FT_UINT32, BASE_DEC,
+ NULL, 0, "Which extension of the Choice is encoded", HFILL }},
+ { &hf_per_GeneralString_length,
+ { "GeneralString Length", "per.generalstring_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of the GeneralString", HFILL }},
+ { &hf_per_extension_bit,
+ { "Extension Bit", "per.extension_bit", FT_BOOLEAN, 8,
+ TFS(&tfs_extension_bit), 0x01, "The extension bit of an aggregate", HFILL }},
+ { &hf_per_extension_present_bit,
+ { "Extension Present Bit", "per.extension_present_bit", FT_BOOLEAN, 8,
+ TFS(&tfs_extension_present_bit), 0x01, "Whether this optional extension is present or not", HFILL }},
+ { &hf_per_small_number_bit,
+ { "Small Number Bit", "per.small_number_bit", FT_BOOLEAN, 8,
+ TFS(&tfs_small_number_bit), 0x01, "The small number bit for a section 10.6 integer", HFILL }},
+ { &hf_per_optional_field_bit,
+ { "Optional Field Bit", "per.optional_field_bit", FT_BOOLEAN, 8,
+ TFS(&tfs_optional_field_bit), 0x01, "This bit specifies the presence/absence of an optional field", HFILL }},
+ { &hf_per_sequence_of_length,
+ { "Sequence-Of Length", "per.sequence_of_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of items in the Sequence Of", HFILL }},
+ { &hf_per_object_identifier_length,
+ { "Object Length", "per.object_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of the object identifier", HFILL }},
+ { &hf_per_open_type_length,
+ { "Open Type Length", "per.open_type_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of an open type encoding", HFILL }},
+ { &hf_per_octet_string_length,
+ { "Octet String Length", "per.octet_string_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of bytes in the Octet String", HFILL }},
+ { &hf_per_bit_string_length,
+ { "Bit String Length", "per.bit_string_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of bits in the Bit String", HFILL }},
+ };
+
+ static gint *ett[] =
+ {
+ &ett_per_sequence_of_item
+ };
+ module_t *per_module;
+
+ proto_per = proto_register_protocol("Packed Encoding Rules (ASN.1 X.691)", "PER", "per");
+ proto_register_field_array(proto_per, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ proto_set_cant_toggle(proto_per);
+
+ per_module = prefs_register_protocol(proto_per, NULL);
+ prefs_register_bool_preference(per_module, "display_internal_per_fields",
+ "Display the internal PER fields in the tree",
+ "Whether the dissector should put the internal PER data in the tree or if it should hide it",
+ &display_internal_per_fields);
+
+}
+
+void
+proto_reg_handoff_per(void)
+{
+}
+
diff --git a/epan/dissectors/packet-per.h b/epan/dissectors/packet-per.h
new file mode 100644
index 0000000000..1aa640af81
--- /dev/null
+++ b/epan/dissectors/packet-per.h
@@ -0,0 +1,103 @@
+/* packet-per.h
+ * Routines for dissection of ASN.1 Aligned PER
+ * 2003 Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_PER_H__
+#define __PACKET_PER_H__
+
+#define PER_NOT_DECODED_YET(x) \
+proto_tree_add_text(tree, tvb, offset, 0, "something unknown here [%s]",x); \
+fprintf(stderr,"Not decoded yet in packet : %d [%s]\n", pinfo->fd->num,x); \
+if (check_col(pinfo->cinfo, COL_INFO)){ \
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[UNKNOWN PER: %s]", x); \
+} \
+tvb_get_guint8(tvb, 9999);
+
+/* in all functions here, offset is guint32 and is
+ byteposition<<3 + bitposition
+*/
+
+/* values for extensions */
+#define ASN1_NO_EXTENSIONS 0
+#define ASN1_EXTENSION_ROOT 1
+#define ASN1_NOT_EXTENSION_ROOT 2
+
+/* value for optional */
+#define ASN1_NOT_OPTIONAL 0
+#define ASN1_OPTIONAL 1
+
+typedef struct _per_choice_t {
+ int value;
+ char *name;
+ int extension;
+ int (*func)(tvbuff_t *, int, packet_info *, proto_tree *);
+} per_choice_t;
+
+typedef struct _per_sequence_t {
+ char *name;
+ int extension;
+ int optional;
+ int (*func)(tvbuff_t *, int, packet_info *, proto_tree *);
+} per_sequence_t;
+
+
+extern guint32 dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, guint32 *length);
+
+extern guint32 dissect_per_GeneralString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index);
+
+extern guint32 dissect_per_sequence_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *));
+
+extern guint32 dissect_per_IA5String(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len);
+
+extern guint32 dissect_per_NumericString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len);
+
+extern guint32 dissect_per_PrintableString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len);
+
+extern guint32 dissect_per_BMPString(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len);
+
+extern guint32 dissect_per_constrained_sequence_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *), int min_len, int max_len);
+
+extern guint32 dissect_per_constrained_set_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *), int min_len, int max_len);
+
+extern guint32 dissect_per_set_of(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, int (*func)(tvbuff_t *, int , packet_info *, proto_tree *));
+
+extern guint32 dissect_per_object_identifier(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, char *value_string);
+
+extern guint32 dissect_per_boolean(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, gboolean *bool, proto_item **item);
+
+extern guint32 dissect_per_integer(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, gint32 *value, proto_item **item);
+
+extern guint32 dissect_per_constrained_integer(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, guint32 min, guint32 max, guint32 *value, proto_item **item, gboolean has_extension);
+
+extern guint32 dissect_per_choice(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, gint ett_index, per_choice_t *choice, char *name, guint32 *value);
+
+extern guint32 dissect_per_sequence(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *parent_tree, int hf_index, gint ett_index, per_sequence_t *sequence);
+
+extern guint32 dissect_per_octet_string(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len, guint32 *value_offset, guint32 *value_len);
+
+extern guint32 dissect_per_bit_string(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len);
+
+extern guint32 dissect_per_restricted_character_string(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, int hf_index, int min_len, int max_len, char *alphabet, int alphabet_length);
+
+#endif /* __PACKET_PER_H__ */
diff --git a/epan/dissectors/packet-pflog.c b/epan/dissectors/packet-pflog.c
new file mode 100644
index 0000000000..4f53a07f2b
--- /dev/null
+++ b/epan/dissectors/packet-pflog.c
@@ -0,0 +1,475 @@
+/* packet-pflog.c
+ * Routines for pflog (OpenBSD Firewall Logging) packet disassembly
+ *
+ * $Id$
+ *
+ * Copyright 2001 Mike Frantzen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "etypes.h"
+#include <epan/resolv.h>
+#include "packet-ip.h"
+#include "packet-ipv6.h"
+#include "packet-pflog.h"
+
+#ifndef offsetof
+/* Can't trust stddef.h to be there for us */
+# define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+#ifndef BPF_WORDALIGN
+#define BPF_ALIGNMENT sizeof(long)
+#define BPF_WORDALIGN(x) (((x) + (BPF_ALIGNMENT - 1)) & ~(BPF_ALIGNMENT - 1))
+#endif
+
+static dissector_handle_t data_handle, ip_handle, ipv6_handle;
+
+/* header fields */
+static int proto_pflog = -1;
+static int hf_pflog_length = -1;
+static int hf_pflog_af = -1;
+static int hf_pflog_action = -1;
+static int hf_pflog_reason = -1;
+static int hf_pflog_ifname = -1;
+static int hf_pflog_ruleset = -1;
+static int hf_pflog_rulenr = -1;
+static int hf_pflog_subrulenr = -1;
+static int hf_pflog_dir = -1;
+
+static gint ett_pflog = -1;
+
+/* old header */
+static int proto_old_pflog = -1;
+static int hf_old_pflog_af = -1;
+static int hf_old_pflog_ifname = -1;
+static int hf_old_pflog_rnr = -1;
+static int hf_old_pflog_reason = -1;
+static int hf_old_pflog_action = -1;
+static int hf_old_pflog_dir = -1;
+
+static gint ett_old_pflog = -1;
+
+void
+capture_pflog(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ struct pfloghdr *pflogh;
+ unsigned int hdrlen;
+
+ pflogh = (struct pfloghdr *)pd;
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, sizeof(guint8))) {
+ ld->other++;
+ return;
+ }
+
+ if (pflogh->length < MIN_PFLOG_HDRLEN) {
+ ld->other++;
+ return;
+ }
+ hdrlen = BPF_WORDALIGN(pflogh->length);
+ if (!BYTES_ARE_IN_FRAME(offset, hdrlen, sizeof(guint8))) {
+ ld->other++;
+ return;
+ }
+ offset += hdrlen;
+
+ switch (pflogh->af) {
+
+ case BSD_PF_INET:
+ capture_ip(pd, offset, len, ld);
+ break;
+
+#ifdef notyet
+ case BSD_PF_INET6:
+ capture_ipv6(pd, offset, len, ld);
+ break;
+#endif
+
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+static const value_string af_vals[] = {
+ { BSD_PF_INET, "IPv4" },
+ { BSD_PF_INET6, "IPv6" },
+ { 0, NULL }
+};
+
+static const value_string reason_vals[] = {
+ { 0, "match" },
+ { 1, "bad-offset" },
+ { 2, "fragment" },
+ { 3, "short" },
+ { 4, "normalize" },
+ { 5, "memory" },
+ { 0, NULL }
+};
+
+static const value_string action_vals[] = {
+ { PF_PASS, "passed" },
+ { PF_DROP, "dropped" },
+ { PF_SCRUB, "scrubbed" },
+ { 0, NULL }
+};
+
+static const value_string old_dir_vals[] = {
+ { PF_OLD_IN, "in" },
+ { PF_OLD_OUT, "out" },
+ { 0, NULL }
+};
+
+static const value_string dir_vals[] = {
+ { PF_INOUT, "inout" },
+ { PF_IN, "in" },
+ { PF_OUT, "out" },
+ { 0, NULL }
+};
+
+static void
+dissect_pflog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+#define MAX_RULE_STR 128
+ struct pfloghdr pflogh;
+ static char rulestr[MAX_RULE_STR];
+ tvbuff_t *next_tvb;
+ proto_tree *pflog_tree;
+ proto_item *ti;
+ int hdrlen;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PFLOG");
+
+ /* Copy out the pflog header to insure alignment */
+ tvb_memcpy(tvb, (guint8 *)&pflogh, 0, sizeof(pflogh));
+
+ /* Byteswap the header now */
+ pflogh.rulenr = g_ntohl(pflogh.rulenr);
+ pflogh.subrulenr = g_ntohl(pflogh.subrulenr);
+
+ hdrlen = BPF_WORDALIGN(pflogh.length);
+
+ if (pflogh.subrulenr == (guint32) -1)
+ snprintf(rulestr, sizeof(rulestr), "%u",
+ pflogh.rulenr);
+ else
+ snprintf(rulestr, sizeof(rulestr), "%u.%s.%u",
+ pflogh.rulenr, pflogh.ruleset, pflogh.subrulenr);
+
+ if (hdrlen < MIN_PFLOG_HDRLEN) {
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_pflog, tvb, 0,
+ hdrlen, "PF Log invalid header length (%u)", hdrlen);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "Invalid header length %u",
+ hdrlen);
+ }
+ return;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_pflog, tvb, 0,
+ hdrlen,
+ "PF Log %s %s on %s by rule %s",
+ val_to_str(pflogh.af, af_vals, "unknown (%u)"),
+ val_to_str(pflogh.action, action_vals, "unknown (%u)"),
+ pflogh.ifname,
+ rulestr);
+ pflog_tree = proto_item_add_subtree(ti, ett_pflog);
+
+ proto_tree_add_uint(pflog_tree, hf_pflog_length, tvb,
+ offsetof(struct pfloghdr, length), sizeof(pflogh.length),
+ pflogh.length);
+ proto_tree_add_uint(pflog_tree, hf_pflog_af, tvb,
+ offsetof(struct pfloghdr, af), sizeof(pflogh.af),
+ pflogh.af);
+ proto_tree_add_uint(pflog_tree, hf_pflog_action, tvb,
+ offsetof(struct pfloghdr, action), sizeof(pflogh.action),
+ pflogh.action);
+ proto_tree_add_uint(pflog_tree, hf_pflog_reason, tvb,
+ offsetof(struct pfloghdr, reason), sizeof(pflogh.reason),
+ pflogh.reason);
+ proto_tree_add_string(pflog_tree, hf_pflog_ifname, tvb,
+ offsetof(struct pfloghdr, ifname), sizeof(pflogh.ifname),
+ pflogh.ifname);
+ proto_tree_add_string(pflog_tree, hf_pflog_ruleset, tvb,
+ offsetof(struct pfloghdr, ruleset), sizeof(pflogh.ruleset),
+ pflogh.ruleset);
+ proto_tree_add_int(pflog_tree, hf_pflog_rulenr, tvb,
+ offsetof(struct pfloghdr, rulenr), sizeof(pflogh.rulenr),
+ pflogh.rulenr);
+ proto_tree_add_int(pflog_tree, hf_pflog_subrulenr, tvb,
+ offsetof(struct pfloghdr, subrulenr), sizeof(pflogh.subrulenr),
+ pflogh.subrulenr);
+ proto_tree_add_uint(pflog_tree, hf_pflog_dir, tvb,
+ offsetof(struct pfloghdr, dir), sizeof(pflogh.dir),
+ pflogh.dir);
+ }
+
+ /* Set the tvbuff for the payload after the header */
+ next_tvb = tvb_new_subset(tvb, hdrlen, -1, -1);
+
+ switch (pflogh.af) {
+
+ case BSD_PF_INET:
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+ break;
+
+ case BSD_PF_INET6:
+ call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[%s %s/%s] ",
+ val_to_str(pflogh.action, action_vals, "unknown (%u)"),
+ pflogh.ifname,
+ rulestr);
+ }
+}
+
+void
+proto_register_pflog(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pflog_length,
+ { "Header Length", "pflog.length", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of Header", HFILL }},
+ { &hf_pflog_af,
+ { "Address Family", "pflog.af", FT_UINT32, BASE_DEC, VALS(af_vals), 0x0,
+ "Protocol (IPv4 vs IPv6)", HFILL }},
+ { &hf_pflog_action,
+ { "Action", "pflog.action", FT_UINT8, BASE_DEC, VALS(action_vals), 0x0,
+ "Action taken by PF on the packet", HFILL }},
+ { &hf_pflog_reason,
+ { "Reason", "pflog.reason", FT_UINT8, BASE_DEC, VALS(reason_vals), 0x0,
+ "Reason for logging the packet", HFILL }},
+ { &hf_pflog_ifname,
+ { "Interface", "pflog.ifname", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Interface", HFILL }},
+ { &hf_pflog_ruleset,
+ { "Ruleset", "pflog.ruleset", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Ruleset name in anchor", HFILL }},
+ { &hf_pflog_rulenr,
+ { "Rule Number", "pflog.rulenr", FT_INT32, BASE_DEC, NULL, 0x0,
+ "Last matched firewall main ruleset rule number", HFILL }},
+ { &hf_pflog_subrulenr,
+ { "Sub Rule Number", "pflog.subrulenr", FT_INT32, BASE_DEC, NULL, 0x0,
+ "Last matched firewall anchored ruleset rule number", HFILL }},
+ { &hf_pflog_dir,
+ { "Direction", "pflog.dir", FT_UINT8, BASE_DEC, VALS(dir_vals), 0x0,
+ "Direction of packet in stack (inbound versus outbound)", HFILL }},
+ };
+ static gint *ett[] = { &ett_pflog };
+
+ proto_pflog = proto_register_protocol("OpenBSD Packet Filter log file",
+ "PFLOG", "pflog");
+ proto_register_field_array(proto_pflog, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pflog(void)
+{
+ dissector_handle_t pflog_handle;
+
+ ip_handle = find_dissector("ip");
+ ipv6_handle = find_dissector("ipv6");
+ data_handle = find_dissector("data");
+
+ pflog_handle = create_dissector_handle(dissect_pflog, proto_pflog);
+ dissector_add("wtap_encap", WTAP_ENCAP_PFLOG, pflog_handle);
+}
+
+
+void
+capture_old_pflog(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ struct old_pfloghdr pflogh;
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, (int)OLD_PFLOG_HDRLEN)) {
+ ld->other++;
+ return;
+ }
+
+ offset += OLD_PFLOG_HDRLEN;
+
+ /* Copy out the pflog header to insure alignment */
+ memcpy(&pflogh, pd, sizeof(pflogh));
+ pflogh.af = g_ntohl(pflogh.af);
+
+ switch (pflogh.af) {
+
+ case BSD_PF_INET:
+ capture_ip(pd, offset, len, ld);
+ break;
+
+#ifdef notyet
+ case BSD_PF_INET6:
+ capture_ipv6(pd, offset, len, ld);
+ break;
+#endif
+
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+static void
+dissect_old_pflog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct old_pfloghdr pflogh;
+ tvbuff_t *next_tvb;
+ proto_tree *pflog_tree;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PFLOG-OLD");
+
+ /* Copy out the pflog header to insure alignment */
+ tvb_memcpy(tvb, (guint8 *)&pflogh, 0, sizeof(pflogh));
+
+ /* Byteswap the header now */
+ pflogh.af = g_ntohl(pflogh.af);
+ pflogh.rnr = g_ntohs(pflogh.rnr);
+ pflogh.reason = g_ntohs(pflogh.reason);
+ pflogh.action = g_ntohs(pflogh.action);
+ pflogh.dir = g_ntohs(pflogh.dir);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_old_pflog, tvb, 0,
+ OLD_PFLOG_HDRLEN,
+ "PF Log (pre 3.4) %s %s on %s by rule %d",
+ val_to_str(pflogh.af, af_vals, "unknown (%u)"),
+ val_to_str(pflogh.action, action_vals, "unknown (%u)"),
+ pflogh.ifname,
+ pflogh.rnr);
+ pflog_tree = proto_item_add_subtree(ti, ett_pflog);
+
+ proto_tree_add_uint(pflog_tree, hf_old_pflog_af, tvb,
+ offsetof(struct old_pfloghdr, af), sizeof(pflogh.af),
+ pflogh.af);
+ proto_tree_add_int(pflog_tree, hf_old_pflog_rnr, tvb,
+ offsetof(struct old_pfloghdr, rnr), sizeof(pflogh.rnr),
+ pflogh.rnr);
+ proto_tree_add_string(pflog_tree, hf_old_pflog_ifname, tvb,
+ offsetof(struct old_pfloghdr, ifname), sizeof(pflogh.ifname),
+ pflogh.ifname);
+ proto_tree_add_uint(pflog_tree, hf_old_pflog_reason, tvb,
+ offsetof(struct old_pfloghdr, reason), sizeof(pflogh.reason),
+ pflogh.reason);
+ proto_tree_add_uint(pflog_tree, hf_old_pflog_action, tvb,
+ offsetof(struct old_pfloghdr, action), sizeof(pflogh.action),
+ pflogh.action);
+ proto_tree_add_uint(pflog_tree, hf_old_pflog_dir, tvb,
+ offsetof(struct old_pfloghdr, dir), sizeof(pflogh.dir),
+ pflogh.dir);
+ }
+
+ /* Set the tvbuff for the payload after the header */
+ next_tvb = tvb_new_subset(tvb, OLD_PFLOG_HDRLEN, -1, -1);
+
+ switch (pflogh.af) {
+
+ case BSD_PF_INET:
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+ break;
+
+ case BSD_PF_INET6:
+ call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[%s %s/#%d] ",
+ val_to_str(pflogh.action, action_vals, "unknown (%u)"),
+ pflogh.ifname,
+ pflogh.rnr);
+ }
+}
+
+void
+proto_register_old_pflog(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_old_pflog_af,
+ { "Address Family", "pflog.af", FT_UINT32, BASE_DEC, VALS(af_vals), 0x0,
+ "Protocol (IPv4 vs IPv6)", HFILL }},
+ { &hf_old_pflog_ifname,
+ { "Interface", "pflog.ifname", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Interface", HFILL }},
+ { &hf_old_pflog_rnr,
+ { "Rule Number", "pflog.rnr", FT_INT16, BASE_DEC, NULL, 0x0,
+ "Last matched firewall rule number", HFILL }},
+ { &hf_old_pflog_reason,
+ { "Reason", "pflog.reason", FT_UINT16, BASE_DEC, VALS(reason_vals), 0x0,
+ "Reason for logging the packet", HFILL }},
+ { &hf_old_pflog_action,
+ { "Action", "pflog.action", FT_UINT16, BASE_DEC, VALS(action_vals), 0x0,
+ "Action taken by PF on the packet", HFILL }},
+ { &hf_old_pflog_dir,
+ { "Direction", "pflog.dir", FT_UINT16, BASE_DEC, VALS(old_dir_vals), 0x0,
+ "Direction of packet in stack (inbound versus outbound)", HFILL }},
+ };
+ static gint *ett[] = { &ett_old_pflog };
+
+ proto_old_pflog = proto_register_protocol(
+ "OpenBSD Packet Filter log file, pre 3.4",
+ "PFLOG-OLD", "pflog-old");
+ proto_register_field_array(proto_old_pflog, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_old_pflog(void)
+{
+ dissector_handle_t pflog_handle;
+
+ ip_handle = find_dissector("ip");
+ ipv6_handle = find_dissector("ipv6");
+ data_handle = find_dissector("data");
+
+ pflog_handle = create_dissector_handle(dissect_old_pflog, proto_old_pflog);
+ dissector_add("wtap_encap", WTAP_ENCAP_OLD_PFLOG, pflog_handle);
+}
+
diff --git a/epan/dissectors/packet-pflog.h b/epan/dissectors/packet-pflog.h
new file mode 100644
index 0000000000..fa51bb9926
--- /dev/null
+++ b/epan/dissectors/packet-pflog.h
@@ -0,0 +1,79 @@
+/* packet-pflog.h
+ *
+ * $Id$
+ *
+ * Copyright 2001 Mike Frantzen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PACKET_PFLOG_H__
+#define __PACKET_PFLOG_H__
+
+/* The header in OpenBSD pflog files. */
+
+struct pfloghdr {
+ guchar length;
+ guchar af;
+ guchar action;
+ guchar reason;
+ char ifname[16];
+ char ruleset[16];
+ guint32 rulenr;
+ guint32 subrulenr;
+ guchar dir;
+ guchar pad[3];
+};
+
+#define PFLOG_HDRLEN sizeof(struct pfloghdr)
+/* minus pad, also used as a signature */
+#define PFLOG_REAL_HDRLEN offsetof(struct pfloghdr, pad);
+#define MIN_PFLOG_HDRLEN 45
+
+struct old_pfloghdr {
+ guint32 af;
+ char ifname[16];
+ gint16 rnr;
+ guint16 reason;
+ guint16 action;
+ guint16 dir;
+};
+#define OLD_PFLOG_HDRLEN sizeof(struct old_pfloghdr)
+
+/* Actions */
+#define PF_PASS 0
+#define PF_DROP 1
+#define PF_SCRUB 2
+
+/* Directions */
+#define PF_OLD_IN 0
+#define PF_OLD_OUT 1
+
+#define PF_INOUT 0
+#define PF_IN 1
+#define PF_OUT 2
+
+# define BSD_PF_INET 2
+# define BSD_PF_INET6 24
+
+#endif /* __PACKET_PFLOG_H__ */
diff --git a/epan/dissectors/packet-pgm.c b/epan/dissectors/packet-pgm.c
new file mode 100644
index 0000000000..9e7a8857be
--- /dev/null
+++ b/epan/dissectors/packet-pgm.c
@@ -0,0 +1,1934 @@
+/* packet-pgm.c
+ * Routines for PGM packet disassembly, RFC 3208
+ *
+ * $Id$
+ *
+ * Copyright (c) 2000 by Talarian Corp
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1999 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "afn.h"
+#include "ipproto.h"
+#include "in_cksum.h"
+#include <epan/resolv.h>
+#include <epan/strutil.h>
+#include "prefs.h"
+
+#include <epan/proto.h>
+
+/*
+ * Flag to control whether to check the PGM checksum.
+ */
+static gboolean pgm_check_checksum = TRUE;
+
+void proto_reg_handoff_pgm(void);
+static void proto_rereg_pgm(void);
+
+typedef guint8 nchar_t;
+typedef guint16 nshort_t;
+typedef guint32 nlong_t;
+
+/* The PGM main header */
+typedef struct {
+ nshort_t sport; /* source port */
+ nshort_t dport; /* destination port */
+ nchar_t type; /* PGM type */
+ nchar_t opts; /* options */
+ nshort_t cksum; /* checksum */
+ nchar_t gsi[6]; /* Global Source ID */
+ nshort_t tsdulen; /* TSDU length */
+} pgm_type;
+#define pgmhdr_ntoh(_p) \
+ (_p)->sport = g_ntohs((_p)->sport); \
+ (_p)->dport = g_ntohs((_p)->dport); \
+ (_p)->type = g_ntohs((_p)->type); \
+ (_p)->opts = g_ntohs((_p)->opts); \
+ (_p)->cksum = g_ntohs((_p)->cksum); \
+ (_p)->tsdulen = g_ntohs((_p)->tsdulen)
+
+/* The PGM SPM header */
+typedef struct {
+ nlong_t sqn; /* SPM's sequence number */
+ nlong_t trail; /* Trailing edge sequence number */
+ nlong_t lead; /* Leading edge sequence number */
+ nshort_t path_afi; /* NLA AFI */
+ nshort_t res; /* reserved */
+ nlong_t path; /* Path NLA */
+} pgm_spm_t;
+#define spm_ntoh(_p) \
+ (_p)->sqn = g_ntohl((_p)->sqn); \
+ (_p)->trail = g_ntohl((_p)->trail); \
+ (_p)->lead = g_ntohl((_p)->lead); \
+ (_p)->path_afi = g_ntohs((_p)->path_afi); \
+ (_p)->res = g_ntohs((_p)->res);
+
+/* The PGM Data (ODATA/RDATA) header */
+typedef struct {
+ nlong_t sqn; /* Data Packet sequence number */
+ nlong_t trail; /* Trailing edge sequence number */
+} pgm_data_t;
+#define data_ntoh(_p) \
+ (_p)->sqn = g_ntohl((_p)->sqn); \
+ (_p)->trail = g_ntohl((_p)->trail)
+
+/* The PGM NAK (NAK/N-NAK/NCF) header */
+typedef struct {
+ nlong_t sqn; /* Requested sequence number */
+ nshort_t src_afi; /* NLA AFI for source (IPv4 is set to 1) */
+ nshort_t src_res; /* reserved */
+ nlong_t src; /* Source NLA */
+ nshort_t grp_afi; /* Multicast group AFI (IPv4 is set to 1) */
+ nshort_t grp_res; /* reserved */
+ nlong_t grp; /* Multicast group NLA */
+} pgm_nak_t;
+#define nak_ntoh(_p) \
+ (_p)->sqn = g_ntohl((_p)->sqn); \
+ (_p)->src_afi = g_ntohs((_p)->src_afi); \
+ (_p)->src_res = g_ntohs((_p)->src_res); \
+ (_p)->grp_afi = g_ntohs((_p)->grp_afi); \
+ (_p)->grp_res = g_ntohs((_p)->grp_res)
+
+/* The PGM POLL header */
+typedef struct {
+ nlong_t sqn; /* POLL sequence number */
+ nshort_t round; /* POLL Round */
+ nshort_t subtype; /* POLL subtype */
+ nshort_t path_afi; /* NLA AFI for last hop router (IPv4 is set to 1) */
+ nshort_t res; /* reserved */
+ nlong_t path; /* Last hop router NLA */
+ nlong_t backoff_ivl; /* POLL backoff interval */
+ nlong_t rand_str; /* POLL random string */
+ nlong_t matching_bmask; /* POLL matching bitmask */
+} pgm_poll_t;
+#define poll_ntoh(_p) \
+ (_p)->sqn = g_ntohl((_p)->sqn); \
+ (_p)->round = g_ntohs((_p)->round); \
+ (_p)->subtype = g_ntohs((_p)->subtype); \
+ (_p)->path_afi = g_ntohs((_p)->path_afi); \
+ (_p)->res = g_ntohs((_p)->res); \
+ (_p)->backoff_ivl = g_ntohl((_p)->backoff_ivl); \
+ (_p)->rand_str = g_ntohl((_p)->rand_str); \
+ (_p)->matching_bmask = g_ntohl((_p)->matching_bmask)
+
+/* The PGM POLR header */
+typedef struct {
+ nlong_t sqn; /* POLR sequence number */
+ nshort_t round; /* POLR Round */
+ nshort_t res; /* reserved */
+} pgm_polr_t;
+#define polr_ntoh(_p) \
+ (_p)->sqn = g_ntohl((_p)->sqn); \
+ (_p)->round = g_ntohs((_p)->round); \
+ (_p)->res = g_ntohs((_p)->res)
+
+/* The PGM ACK header (PGMCC) */
+typedef struct {
+ nlong_t rx_max_sqn; /* RX_MAX sequence number */
+ nlong_t bitmap; /* Received Packet Bitmap */
+} pgm_ack_t;
+#define ack_ntoh(_p) \
+ (_p)->rx_max_sqn = g_ntohl((_p)->rx_max_sqn); \
+ (_p)->bitmap = g_ntohl((_p)->bitmap)
+
+/* constants for hdr types */
+#if defined(PGM_SPEC_01_PCKTS)
+/* old spec-01 types */
+#define PGM_SPM_PCKT 0x00
+#define PGM_ODATA_PCKT 0x10
+#define PGM_RDATA_PCKT 0x11
+#define PGM_NAK_PCKT 0x20
+#define PGM_NNAK_PCKT 0x21
+#define PGM_NCF_PCKT 0x30
+#else
+/* spec-02 types (as well as spec-04+) */
+#define PGM_SPM_PCKT 0x00
+#define PGM_ODATA_PCKT 0x04
+#define PGM_RDATA_PCKT 0x05
+#define PGM_NAK_PCKT 0x08
+#define PGM_NNAK_PCKT 0x09
+#define PGM_NCF_PCKT 0x0A
+#define PGM_POLL_PCKT 0x01
+#define PGM_POLR_PCKT 0x02
+#define PGM_ACK_PCKT 0x0D
+#endif /* PGM_SPEC_01_PCKTS */
+
+/* port swapping on NAK and NNAKs or not (default is to swap) */
+/* PGM_NO_PORT_SWAP */
+
+/* option flags (main PGM header) */
+#define PGM_OPT 0x01
+#define PGM_OPT_NETSIG 0x02
+#define PGM_OPT_VAR_PKTLEN 0x40
+#define PGM_OPT_PARITY 0x80
+
+/* option types */
+#define PGM_OPT_LENGTH 0x00
+#define PGM_OPT_END 0x80
+#define PGM_OPT_FRAGMENT 0x01
+#define PGM_OPT_NAK_LIST 0x02
+#define PGM_OPT_JOIN 0x03
+#define PGM_OPT_REDIRECT 0x07
+#define PGM_OPT_SYN 0x0D
+#define PGM_OPT_FIN 0x0E
+#define PGM_OPT_RST 0x0F
+#define PGM_OPT_PARITY_PRM 0x08
+#define PGM_OPT_PARITY_GRP 0x09
+#define PGM_OPT_CURR_TGSIZE 0x0A
+#define PGM_OPT_PGMCC_DATA 0x12
+#define PGM_OPT_PGMCC_FEEDBACK 0x13
+#define PGM_OPT_NAK_BO_IVL 0x04
+#define PGM_OPT_NAK_BO_RNG 0x05
+
+/* POLL subtypes */
+#define PGM_POLL_GENERAL 0x0
+#define PGM_POLL_DLR 0x1
+
+static const nchar_t PGM_OPT_INVALID = 0x7F;
+
+/* OPX bit values */
+#define PGM_OPX_IGNORE 0x00
+#define PGM_OPX_INVAL 0x01
+#define PGM_OPX_DISCARD 0x10
+
+/* option formats */
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+} pgm_opt_generic_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nshort_t total_len;
+} pgm_opt_length_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+} pgm_opt_nak_list_t;
+
+/*
+ * To squeeze the whole option into 255 bytes, we
+ * can only have 62 in the list
+ */
+#define PGM_MAX_NAK_LIST_SZ (62)
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+ nlong_t opt_join_min;
+} pgm_opt_join_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t po;
+ nlong_t prm_tgsz;
+} pgm_opt_parity_prm_t;
+
+/* OPT_PARITY_PRM P and O bits */
+static const nchar_t PGM_OPT_PARITY_PRM_PRO = 0x2;
+static const nchar_t PGM_OPT_PARITY_PRM_OND = 0x1;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+ nlong_t prm_grp;
+} pgm_opt_parity_grp_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+ nlong_t prm_atgsz;
+} pgm_opt_curr_tgsize_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+ nlong_t tsp;
+ nshort_t acker_afi;
+ nshort_t res2;
+ nlong_t acker;
+} pgm_opt_pgmcc_data_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+ nlong_t tsp;
+ nshort_t acker_afi;
+ nshort_t loss_rate;
+ nlong_t acker;
+} pgm_opt_pgmcc_feedback_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+ nlong_t bo_ivl;
+ nlong_t bo_ivl_sqn;
+} pgm_opt_nak_bo_ivl_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+ nlong_t min_bo_ivl;
+ nlong_t max_bo_ivl;
+} pgm_opt_nak_bo_rng_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+ nshort_t afi;
+ nshort_t res2;
+ nlong_t dlr;
+} pgm_opt_redirect_t;
+
+typedef struct {
+ nchar_t type;
+ nchar_t len;
+ nchar_t opx;
+ nchar_t res;
+ nlong_t first_sqn;
+ nlong_t offset;
+ nlong_t total_length;
+} pgm_opt_fragment_t;
+
+/*
+ * Udp port for UDP encapsulation
+ */
+#define DEFAULT_UDP_ENCAP_UCAST_PORT 3055
+#define DEFAULT_UDP_ENCAP_MCAST_PORT 3056
+
+static int udp_encap_ucast_port = 0;
+static int udp_encap_mcast_port = 0;
+static int old_encap_ucast_port = 0;
+static int old_encap_mcast_port = 0;
+
+static int proto_pgm = -1;
+static int ett_pgm = -1;
+static int ett_pgm_optbits = -1;
+static int ett_pgm_opts = -1;
+static int ett_pgm_spm = -1;
+static int ett_pgm_data = -1;
+static int ett_pgm_nak = -1;
+static int ett_pgm_poll = -1;
+static int ett_pgm_polr = -1;
+static int ett_pgm_ack = -1;
+static int ett_pgm_opts_join = -1;
+static int ett_pgm_opts_parityprm = -1;
+static int ett_pgm_opts_paritygrp = -1;
+static int ett_pgm_opts_naklist = -1;
+static int ett_pgm_opts_ccdata = -1;
+static int ett_pgm_opts_nak_bo_ivl = -1;
+static int ett_pgm_opts_nak_bo_rng = -1;
+static int ett_pgm_opts_redirect = -1;
+static int ett_pgm_opts_fragment = -1;
+
+static int hf_pgm_main_sport = -1;
+static int hf_pgm_main_dport = -1;
+static int hf_pgm_main_type = -1;
+static int hf_pgm_main_opts = -1;
+static int hf_pgm_main_opts_opt = -1;
+static int hf_pgm_main_opts_netsig = -1;
+static int hf_pgm_main_opts_varlen = -1;
+static int hf_pgm_main_opts_parity = -1;
+static int hf_pgm_main_cksum = -1;
+static int hf_pgm_main_cksum_bad = -1;
+static int hf_pgm_main_gsi = -1;
+static int hf_pgm_main_tsdulen = -1;
+static int hf_pgm_spm_sqn = -1;
+static int hf_pgm_spm_lead = -1;
+static int hf_pgm_spm_trail = -1;
+static int hf_pgm_spm_pathafi = -1;
+static int hf_pgm_spm_res = -1;
+static int hf_pgm_spm_path = -1;
+static int hf_pgm_data_sqn = -1;
+static int hf_pgm_data_trail = -1;
+static int hf_pgm_nak_sqn = -1;
+static int hf_pgm_nak_srcafi = -1;
+static int hf_pgm_nak_srcres = -1;
+static int hf_pgm_nak_src = -1;
+static int hf_pgm_nak_grpafi = -1;
+static int hf_pgm_nak_grpres = -1;
+static int hf_pgm_nak_grp = -1;
+static int hf_pgm_poll_sqn = -1;
+static int hf_pgm_poll_round = -1;
+static int hf_pgm_poll_subtype = -1;
+static int hf_pgm_poll_pathafi = -1;
+static int hf_pgm_poll_res = -1;
+static int hf_pgm_poll_path = -1;
+static int hf_pgm_poll_backoff_ivl = -1;
+static int hf_pgm_poll_rand_str = -1;
+static int hf_pgm_poll_matching_bmask = -1;
+static int hf_pgm_polr_sqn = -1;
+static int hf_pgm_polr_round = -1;
+static int hf_pgm_polr_res = -1;
+static int hf_pgm_ack_sqn = -1;
+static int hf_pgm_ack_bitmap = -1;
+
+static int hf_pgm_opt_type = -1;
+static int hf_pgm_opt_len = -1;
+static int hf_pgm_opt_tlen = -1;
+
+static int hf_pgm_genopt_type = -1;
+static int hf_pgm_genopt_len = -1;
+static int hf_pgm_genopt_opx = -1;
+
+static int hf_pgm_opt_join_res = -1;
+static int hf_pgm_opt_join_minjoin = -1;
+
+static int hf_pgm_opt_parity_prm_po = -1;
+static int hf_pgm_opt_parity_prm_prmtgsz = -1;
+
+static int hf_pgm_opt_parity_grp_res = -1;
+static int hf_pgm_opt_parity_grp_prmgrp = -1;
+
+#ifdef PGM_UNUSED_HANDLES
+static int hf_pgm_opt_curr_tgsize_type = -1;
+static int hf_pgm_opt_curr_tgsize_len = -1;
+static int hf_pgm_opt_curr_tgsize_opx = -1;
+static int hf_pgm_opt_curr_tgsize_res = -1;
+static int hf_pgm_opt_curr_tgsize_prmatgsz = -1;
+#endif
+
+static int hf_pgm_opt_nak_res = -1;
+static int hf_pgm_opt_nak_list = -1;
+
+static int hf_pgm_opt_ccdata_res = -1;
+static int hf_pgm_opt_ccdata_tsp = -1;
+static int hf_pgm_opt_ccdata_afi = -1;
+static int hf_pgm_opt_ccdata_res2 = -1;
+static int hf_pgm_opt_ccdata_acker = -1;
+
+static int hf_pgm_opt_ccfeedbk_res = -1;
+static int hf_pgm_opt_ccfeedbk_tsp = -1;
+static int hf_pgm_opt_ccfeedbk_afi = -1;
+static int hf_pgm_opt_ccfeedbk_lossrate = -1;
+static int hf_pgm_opt_ccfeedbk_acker = -1;
+
+static int hf_pgm_opt_nak_bo_ivl_res = -1;
+static int hf_pgm_opt_nak_bo_ivl_bo_ivl = -1;
+static int hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn = -1;
+
+static int hf_pgm_opt_nak_bo_rng_res = -1;
+static int hf_pgm_opt_nak_bo_rng_min_bo_ivl = -1;
+static int hf_pgm_opt_nak_bo_rng_max_bo_ivl = -1;
+
+static int hf_pgm_opt_redirect_res = -1;
+static int hf_pgm_opt_redirect_afi = -1;
+static int hf_pgm_opt_redirect_res2 = -1;
+static int hf_pgm_opt_redirect_dlr = -1;
+
+static int hf_pgm_opt_fragment_res = -1;
+static int hf_pgm_opt_fragment_first_sqn = -1;
+static int hf_pgm_opt_fragment_offset = -1;
+static int hf_pgm_opt_fragment_total_length = -1;
+
+static dissector_table_t subdissector_table;
+static heur_dissector_list_t heur_subdissector_list;
+static dissector_handle_t data_handle;
+
+/*
+ * As of the time this comment was typed
+ *
+ * http://search.ietf.org/internet-drafts/draft-speakman-pgm-spec-06.txt
+ *
+ * was the URL for the PGM draft.
+ */
+
+static char *
+optsstr(nchar_t opts)
+{
+ static char msg[256];
+ char *p = msg, *str;
+
+ if (opts == 0)
+ return("");
+
+ if (opts & PGM_OPT){
+ sprintf(p, "Present");
+ p += strlen("Present");
+ }
+ if (opts & PGM_OPT_NETSIG){
+ if (p != msg)
+ str = ",NetSig";
+ else
+ str = "NetSig";
+ sprintf(p, str);
+ p += strlen(str);
+ }
+ if (opts & PGM_OPT_VAR_PKTLEN){
+ if (p != msg)
+ str = ",VarLen";
+ else
+ str = "VarLen";
+ sprintf(p, str);
+ p += strlen(str);
+ }
+ if (opts & PGM_OPT_PARITY){
+ if (p != msg)
+ str = ",Parity";
+ else
+ str = "Parity";
+ sprintf(p, str);
+ p += strlen(str);
+ }
+ if (p == msg) {
+ sprintf(p, "0x%x", opts);
+ }
+ return(msg);
+}
+static char *
+paritystr(nchar_t parity)
+{
+ static char msg[256];
+ char *p = msg, *str;
+
+ if (parity == 0)
+ return("");
+
+ if (parity & PGM_OPT_PARITY_PRM_PRO){
+ sprintf(p, "Pro-active");
+ p += strlen("Pro-active");
+ }
+ if (parity & PGM_OPT_PARITY_PRM_OND){
+ if (p != msg)
+ str = ",On-demand";
+ else
+ str = "On-demand";
+ sprintf(p, str);
+ p += strlen(str);
+ }
+ if (p == msg) {
+ sprintf(p, "0x%x", parity);
+ }
+ return(msg);
+}
+
+static const value_string opt_vals[] = {
+ { PGM_OPT_LENGTH, "Length" },
+ { PGM_OPT_END, "End" },
+ { PGM_OPT_FRAGMENT, "Fragment" },
+ { PGM_OPT_NAK_LIST, "NakList" },
+ { PGM_OPT_JOIN, "Join" },
+ { PGM_OPT_REDIRECT, "ReDirect" },
+ { PGM_OPT_SYN, "Syn" },
+ { PGM_OPT_FIN, "Fin" },
+ { PGM_OPT_RST, "Rst" },
+ { PGM_OPT_PARITY_PRM, "ParityPrm" },
+ { PGM_OPT_PARITY_GRP, "ParityGrp" },
+ { PGM_OPT_CURR_TGSIZE, "CurrTgsiz" },
+ { PGM_OPT_PGMCC_DATA, "CcData" },
+ { PGM_OPT_PGMCC_FEEDBACK, "CcFeedBack" },
+ { PGM_OPT_NAK_BO_IVL, "NakBackOffIvl" },
+ { PGM_OPT_NAK_BO_RNG, "NakBackOffRng" },
+ { PGM_OPT_FRAGMENT, "Fragment" },
+ { 0, NULL }
+};
+
+static const value_string opx_vals[] = {
+ { PGM_OPX_IGNORE, "Ignore" },
+ { PGM_OPX_INVAL, "Inval" },
+ { PGM_OPX_DISCARD, "DisCard" },
+ { 0, NULL }
+};
+
+static void
+dissect_pgmopts(tvbuff_t *tvb, int offset, proto_tree *tree,
+ const char *pktname)
+{
+ proto_item *tf;
+ proto_tree *opts_tree = NULL;
+ proto_tree *opt_tree = NULL;
+ pgm_opt_length_t opts;
+ pgm_opt_generic_t genopts;
+ gboolean theend = FALSE, firsttime = TRUE;
+
+ tvb_memcpy(tvb, (guint8 *)&opts, offset, sizeof(opts));
+ if (opts.type != PGM_OPT_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s Options - initial option is %s, should be %s",
+ pktname,
+ val_to_str(opts.type, opt_vals, "Unknown (0x%02x)"),
+ val_to_str(PGM_OPT_LENGTH, opt_vals, "Unknown (0x%02x)"));
+ return;
+ }
+ opts.total_len = g_ntohs(opts.total_len);
+
+ if (opts.total_len < 4) {
+ proto_tree_add_text(opts_tree, tvb, offset, 4,
+ "%s Options (Total Length %u - invalid, must be >= 4)",
+ pktname, opts.total_len);
+ return;
+ }
+ tf = proto_tree_add_text(tree, tvb, offset,
+ opts.total_len,
+ "%s Options (Total Length %d)", pktname, opts.total_len);
+ opts_tree = proto_item_add_subtree(tf, ett_pgm_opts);
+ proto_tree_add_uint(opts_tree, hf_pgm_opt_type, tvb,
+ offset, 1, opts.type);
+ proto_tree_add_uint(opts_tree, hf_pgm_opt_len, tvb,
+ offset+1, 1, opts.len);
+ proto_tree_add_uint(opts_tree, hf_pgm_opt_tlen, tvb,
+ offset+2, 2, opts.total_len);
+
+ offset += 4;
+ for (opts.total_len -= 4; !theend && opts.total_len != 0;){
+ if (opts.total_len < 4) {
+ proto_tree_add_text(opts_tree, tvb, offset, opts.total_len,
+ "Remaining total options length doesn't have enough for an options header");
+ break;
+ }
+ tvb_memcpy(tvb, (guint8 *)&genopts, offset, sizeof(genopts));
+ if (genopts.type & PGM_OPT_END) {
+ genopts.type &= ~PGM_OPT_END;
+ theend = TRUE;
+ }
+ if (genopts.len < 4) {
+ proto_tree_add_text(opts_tree, tvb, offset, genopts.len,
+ "Option: %s, Length: %u (invalid, must be >= 4)",
+ val_to_str(genopts.type, opt_vals, "Unknown (0x%02x)"),
+ genopts.len);
+ break;
+ }
+ if (opts.total_len < genopts.len) {
+ proto_tree_add_text(opts_tree, tvb, offset, genopts.len,
+ "Option: %s, Length: %u (> remaining total options length)",
+ val_to_str(genopts.type, opt_vals, "Unknown (0x%02x)"),
+ genopts.len);
+ break;
+ }
+ tf = proto_tree_add_text(opts_tree, tvb, offset, genopts.len,
+ "Option: %s, Length: %u",
+ val_to_str(genopts.type, opt_vals, "Unknown (0x%02x)"),
+ genopts.len);
+
+ switch(genopts.type) {
+ case PGM_OPT_JOIN:{
+ pgm_opt_join_t optdata;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_join);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type,
+ tvb, offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long)sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx, tvb,
+ offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_join_res, tvb,
+ offset+3, 1, optdata.res);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_join_minjoin, tvb,
+ offset+4, 4, g_ntohl(optdata.opt_join_min));
+
+ break;
+ }
+ case PGM_OPT_PARITY_PRM:{
+ pgm_opt_parity_prm_t optdata;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_parityprm);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type,
+ tvb, offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long) sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx,
+ tvb, offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint_format(opt_tree, hf_pgm_opt_parity_prm_po, tvb,
+ offset+3, 1, optdata.po, "Parity Parameters: %s (0x%x)",
+ paritystr(optdata.po), optdata.po);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_parity_prm_prmtgsz,
+ tvb, offset+4, 4, g_ntohl(optdata.prm_tgsz));
+
+ break;
+ }
+ case PGM_OPT_PARITY_GRP:{
+ pgm_opt_parity_grp_t optdata;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_paritygrp);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type,
+ tvb, offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long) sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx,
+ tvb, offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_parity_grp_res, tvb,
+ offset+3, 1, optdata.res);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_parity_grp_prmgrp,
+ tvb, offset+4, 4, g_ntohl(optdata.prm_grp));
+
+ break;
+ }
+ case PGM_OPT_NAK_LIST:{
+ pgm_opt_nak_list_t optdata;
+ nlong_t naklist[PGM_MAX_NAK_LIST_SZ+1];
+ char nakbuf[8192], *ptr;
+ int i, j, naks, soffset = 0;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_naklist);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type, tvb,
+ offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long) sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx,
+ tvb, offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_nak_res, tvb,
+ offset+3, 1, optdata.res);
+
+ optdata.len -= sizeof(pgm_opt_nak_list_t);
+ tvb_memcpy(tvb, (guint8 *)naklist, offset+4, optdata.len);
+ naks = (optdata.len/sizeof(nlong_t));
+ ptr = nakbuf;
+ j = 0;
+ /*
+ * Print out 8 per line
+ */
+ for (i=0; i < naks; i++) {
+ sprintf(nakbuf+soffset, "0x%lx ",
+ (unsigned long)g_ntohl(naklist[i]));
+ soffset = strlen(nakbuf);
+ if ((++j % 8) == 0) {
+ if (firsttime) {
+ proto_tree_add_bytes_format(opt_tree,
+ hf_pgm_opt_nak_list, tvb, offset+4, optdata.len,
+ nakbuf, "List(%d): %s", naks, nakbuf);
+ soffset = 0;
+ } else {
+ proto_tree_add_bytes_format(opt_tree,
+ hf_pgm_opt_nak_list, tvb, offset+4, optdata.len,
+ nakbuf, "List: %s", nakbuf);
+ soffset = 0;
+ }
+ firsttime = FALSE;
+ }
+ }
+ if (soffset) {
+ if (firsttime) {
+ proto_tree_add_bytes_format(opt_tree,
+ hf_pgm_opt_nak_list, tvb, offset+4, optdata.len,
+ nakbuf, "List(%d): %s", naks, nakbuf);
+ soffset = 0;
+ } else {
+ proto_tree_add_bytes_format(opt_tree,
+ hf_pgm_opt_nak_list, tvb, offset+4, optdata.len,
+ nakbuf, "List: %s", nakbuf);
+ soffset = 0;
+ }
+ }
+ break;
+ }
+ case PGM_OPT_PGMCC_DATA:{
+ pgm_opt_pgmcc_data_t optdata;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type,
+ tvb, offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long) sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx,
+ tvb, offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_ccdata_res, tvb,
+ offset+3, 1, optdata.res);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_ccdata_tsp, tvb,
+ offset+4, 4, optdata.tsp);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_ccdata_afi, tvb,
+ offset+8, 2, g_ntohs(optdata.acker_afi));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_ccdata_res2, tvb,
+ offset+10, 2, g_ntohs(optdata.res2));
+
+ switch (g_ntohs(optdata.acker_afi)) {
+
+ case AFNUM_INET:
+ proto_tree_add_ipv4(opt_tree, hf_pgm_opt_ccdata_acker,
+ tvb, offset+12, 4, optdata.acker);
+ break;
+
+ default:
+ /*
+ * XXX - the header is variable-length,
+ * as the length of the NLA depends on
+ * its AFI.
+ *
+ * However, our structure for it is
+ * fixed-length, and assumes it's a 4-byte
+ * IPv4 address.
+ */
+ break;
+ }
+
+ break;
+ }
+ case PGM_OPT_PGMCC_FEEDBACK:{
+ pgm_opt_pgmcc_feedback_t optdata;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type,
+ tvb, offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long) sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx,
+ tvb, offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_ccfeedbk_res, tvb,
+ offset+3, 1, optdata.res);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_ccfeedbk_tsp, tvb,
+ offset+4, 4, optdata.tsp);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_ccfeedbk_afi, tvb,
+ offset+8, 2, g_ntohs(optdata.acker_afi));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_ccfeedbk_lossrate, tvb,
+ offset+10, 2, g_ntohs(optdata.loss_rate));
+
+ switch (g_ntohs(optdata.acker_afi)) {
+
+ case AFNUM_INET:
+ proto_tree_add_ipv4(opt_tree, hf_pgm_opt_ccfeedbk_acker,
+ tvb, offset+12, 4, optdata.acker);
+ break;
+
+ default:
+ /*
+ * XXX - the header is variable-length,
+ * as the length of the NLA depends on
+ * its AFI.
+ *
+ * However, our structure for it is
+ * fixed-length, and assumes it's a 4-byte
+ * IPv4 address.
+ */
+ break;
+ }
+
+ break;
+ }
+ case PGM_OPT_NAK_BO_IVL:{
+ pgm_opt_nak_bo_ivl_t optdata;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_ivl);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type,
+ tvb, offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long) sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx, tvb,
+ offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_nak_bo_ivl_res, tvb,
+ offset+3, 1, optdata.res);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_nak_bo_ivl_bo_ivl, tvb,
+ offset+4, 4, g_ntohl(optdata.bo_ivl));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn, tvb,
+ offset+8, 4, g_ntohl(optdata.bo_ivl_sqn));
+
+ break;
+ }
+ case PGM_OPT_NAK_BO_RNG:{
+ pgm_opt_nak_bo_rng_t optdata;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_rng);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type,
+ tvb, offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long) sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx, tvb,
+ offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_nak_bo_rng_res, tvb,
+ offset+3, 1, optdata.res);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_nak_bo_rng_min_bo_ivl, tvb,
+ offset+4, 4, g_ntohl(optdata.min_bo_ivl));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_nak_bo_rng_max_bo_ivl, tvb,
+ offset+8, 4, g_ntohl(optdata.max_bo_ivl));
+
+ break;
+ }
+ case PGM_OPT_REDIRECT:{
+ pgm_opt_redirect_t optdata;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_redirect);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type,
+ tvb, offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long) sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx,
+ tvb, offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_redirect_res, tvb,
+ offset+3, 1, optdata.res);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_redirect_afi, tvb,
+ offset+4, 2, g_ntohs(optdata.afi));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_redirect_res2, tvb,
+ offset+6, 2, g_ntohs(optdata.res2));
+
+ switch (g_ntohs(optdata.afi)) {
+
+ case AFNUM_INET:
+ proto_tree_add_ipv4(opt_tree, hf_pgm_opt_redirect_dlr,
+ tvb, offset+8, 4, optdata.dlr);
+ break;
+
+ default:
+ /*
+ * XXX - the header is variable-length,
+ * as the length of the NLA depends on
+ * its AFI.
+ *
+ * However, our structure for it is
+ * fixed-length, and assumes it's a 4-byte
+ * IPv4 address.
+ */
+ break;
+ }
+
+ break;
+ }
+ case PGM_OPT_FRAGMENT:{
+ pgm_opt_fragment_t optdata;
+
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_fragment);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_type,
+ tvb, offset, 1, genopts.type);
+
+ if (genopts.len < sizeof optdata) {
+ proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len,
+ "Length: %u (bogus, must be >= %lu)",
+ genopts.len,
+ (unsigned long) sizeof optdata);
+ break;
+ }
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_len, tvb,
+ offset+1, 1, genopts.len);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_genopt_opx, tvb,
+ offset+2, 1, genopts.opx);
+
+ tvb_memcpy(tvb, (guint8 *)&optdata, offset, sizeof(optdata));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_fragment_res, tvb,
+ offset+3, 1, optdata.res);
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_fragment_first_sqn, tvb,
+ offset+4, 4, g_ntohl(optdata.first_sqn));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_fragment_offset, tvb,
+ offset+8, 4, g_ntohl(optdata.offset));
+
+ proto_tree_add_uint(opt_tree, hf_pgm_opt_fragment_total_length, tvb,
+ offset+12, 4, g_ntohl(optdata.total_length));
+
+ break;
+ }
+ }
+ offset += genopts.len;
+ opts.total_len -= genopts.len;
+
+ }
+ return ;
+}
+
+static const value_string type_vals[] = {
+ { PGM_SPM_PCKT, "SPM" },
+ { PGM_RDATA_PCKT, "RDATA" },
+ { PGM_ODATA_PCKT, "ODATA" },
+ { PGM_NAK_PCKT, "NAK" },
+ { PGM_NNAK_PCKT, "NNAK" },
+ { PGM_NCF_PCKT, "NCF" },
+ { PGM_POLL_PCKT, "POLL" },
+ { PGM_POLR_PCKT, "POLR" },
+ { PGM_ACK_PCKT, "ACK" },
+ { 0, NULL }
+};
+
+static const value_string poll_subtype_vals[] = {
+ { PGM_POLL_GENERAL, "General" },
+ { PGM_POLL_DLR, "DLR" },
+ { 0, NULL }
+};
+/* Determine if there is a sub-dissector and call it. This has been */
+/* separated into a stand alone routine to other protocol dissectors */
+/* can call to it, ie. socks */
+
+void
+decode_pgm_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, pgm_type *pgmhdr)
+{
+ tvbuff_t *next_tvb;
+ int found = 0;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ /* do lookup with the subdissector table */
+ found = dissector_try_port(subdissector_table, pgmhdr->sport,
+ next_tvb, pinfo, tree);
+ if (found)
+ return;
+
+ found = dissector_try_port(subdissector_table, pgmhdr->dport,
+ next_tvb, pinfo, tree);
+ if (found)
+ return;
+
+ /* do lookup with the heuristic subdissector table */
+ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
+ return;
+
+ /* Oh, well, we don't know this; dissect it as data. */
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+
+}
+int
+total_size(tvbuff_t *tvb, pgm_type *hdr)
+{
+ int bytes = sizeof(pgm_type);
+ pgm_opt_length_t opts;
+
+ switch(hdr->type) {
+ case PGM_SPM_PCKT:
+ bytes += sizeof(pgm_spm_t);
+ break;
+
+ case PGM_RDATA_PCKT:
+ case PGM_ODATA_PCKT:
+ bytes += sizeof(pgm_data_t);
+ break;
+
+ case PGM_NAK_PCKT:
+ case PGM_NNAK_PCKT:
+ case PGM_NCF_PCKT:
+ bytes += sizeof(pgm_nak_t);
+ break;
+ case PGM_POLL_PCKT:
+ bytes += sizeof(pgm_poll_t);
+ break;
+ case PGM_POLR_PCKT:
+ bytes += sizeof(pgm_polr_t);
+ break;
+ case PGM_ACK_PCKT:
+ bytes += sizeof(pgm_ack_t);
+ break;
+ }
+ if ((hdr->opts & PGM_OPT)) {
+ tvb_memcpy(tvb, (guint8 *)&opts, bytes, sizeof(opts));
+ bytes += g_ntohs(opts.total_len);
+ }
+ return(bytes);
+}
+/*
+ * dissect_pgm - The dissector for Pragmatic General Multicast
+ */
+static void
+dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *pgm_tree = NULL;
+ proto_tree *opt_tree = NULL;
+ proto_tree *type_tree = NULL;
+ proto_item *tf;
+ pgm_type pgmhdr;
+ pgm_spm_t spm;
+ pgm_data_t data;
+ pgm_nak_t nak;
+ pgm_poll_t poll;
+ pgm_polr_t polr;
+ pgm_ack_t ack;
+ int offset = 0;
+ guint hlen, plen;
+ proto_item *ti;
+ const char *pktname;
+ const char *pollstname;
+ char *gsi;
+ int isdata = 0;
+ guint pgmlen, reportedlen;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGM");
+
+ /* Clear out the Info column. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb, (guint8 *)&pgmhdr, offset, sizeof(pgm_type));
+ hlen = sizeof(pgm_type);
+ pgmhdr.sport = g_ntohs(pgmhdr.sport);
+ pgmhdr.dport = g_ntohs(pgmhdr.dport);
+ pgmhdr.tsdulen = g_ntohs(pgmhdr.tsdulen);
+ pgmhdr.cksum = g_ntohs(pgmhdr.cksum);
+
+ pktname = val_to_str(pgmhdr.type, type_vals, "Unknown (0x%02x)");
+
+ gsi = bytes_to_str(pgmhdr.gsi, 6);
+ switch(pgmhdr.type) {
+ case PGM_SPM_PCKT:
+ plen = sizeof(pgm_spm_t);
+ tvb_memcpy(tvb, (guint8 *)&spm, sizeof(pgm_type), plen);
+ spm_ntoh(&spm);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%-5s sqn 0x%x gsi %s", pktname, spm.sqn, gsi);
+ }
+ break;
+
+ case PGM_RDATA_PCKT:
+ case PGM_ODATA_PCKT:
+ plen = sizeof(pgm_data_t);
+ tvb_memcpy(tvb, (guint8 *)&data, sizeof(pgm_type), plen);
+ data_ntoh(&data);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, data.sqn, gsi,
+ pgmhdr.tsdulen);
+ }
+ isdata = 1;
+ break;
+
+ case PGM_NAK_PCKT:
+ case PGM_NNAK_PCKT:
+ case PGM_NCF_PCKT:
+ plen = sizeof(pgm_nak_t);
+ tvb_memcpy(tvb, (guint8 *)&nak, sizeof(pgm_type), plen);
+ nak_ntoh(&nak);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%-5s sqn 0x%x gsi %s", pktname, nak.sqn, gsi);
+ }
+ break;
+ case PGM_POLL_PCKT:
+ plen = sizeof(pgm_poll_t);
+ tvb_memcpy(tvb, (guint8 *)&poll, sizeof(pgm_type), plen);
+ poll_ntoh(&poll);
+ pollstname = val_to_str(poll.subtype, poll_subtype_vals, "Unknown (0x%02x)");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%-5s sqn 0x%x gsi %s subtype %s", pktname, poll.sqn, gsi, pollstname);
+ }
+ break;
+ case PGM_POLR_PCKT:
+ plen = sizeof(pgm_polr_t);
+ tvb_memcpy(tvb, (guint8 *)&polr, sizeof(pgm_type), plen);
+ polr_ntoh(&polr);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%-5s sqn 0x%x gsi %s", pktname, polr.sqn, gsi);
+ }
+ break;
+ case PGM_ACK_PCKT:
+ plen = sizeof(pgm_ack_t);
+ tvb_memcpy(tvb, (guint8 *)&ack, sizeof(pgm_type), plen);
+ ack_ntoh(&ack);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%-5s sqn 0x%x gsi %s", pktname, ack.rx_max_sqn, gsi);
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_pgm,
+ tvb, offset, total_size(tvb, &pgmhdr),
+ "Pragmatic General Multicast: Type %s"
+ " SrcPort %u, DstPort %u, GSI %s", pktname,
+ pgmhdr.sport, pgmhdr.dport,
+ bytes_to_str(pgmhdr.gsi, 6));
+
+ pgm_tree = proto_item_add_subtree(ti, ett_pgm);
+ proto_tree_add_uint(pgm_tree, hf_pgm_main_sport, tvb, offset, 2,
+ pgmhdr.sport);
+ proto_tree_add_uint(pgm_tree, hf_pgm_main_dport, tvb, offset+2,
+ 2, pgmhdr.dport);
+ proto_tree_add_uint(pgm_tree, hf_pgm_main_type, tvb,
+ offset+4, 1, pgmhdr.type);
+
+ tf = proto_tree_add_uint_format(pgm_tree, hf_pgm_main_opts, tvb,
+ offset+5, 1, pgmhdr.opts, "Options: %s (0x%x)",
+ optsstr(pgmhdr.opts), pgmhdr.opts);
+ opt_tree = proto_item_add_subtree(tf, ett_pgm_optbits);
+
+ proto_tree_add_boolean(opt_tree, hf_pgm_main_opts_opt, tvb,
+ offset+5, 1, (pgmhdr.opts & PGM_OPT));
+ proto_tree_add_boolean(opt_tree, hf_pgm_main_opts_netsig, tvb,
+ offset+5, 1, (pgmhdr.opts & PGM_OPT_NETSIG));
+ proto_tree_add_boolean(opt_tree, hf_pgm_main_opts_varlen, tvb,
+ offset+5, 1, (pgmhdr.opts & PGM_OPT_VAR_PKTLEN));
+ proto_tree_add_boolean(opt_tree, hf_pgm_main_opts_parity, tvb,
+ offset+5, 1, (pgmhdr.opts & PGM_OPT_PARITY));
+
+ reportedlen = tvb_reported_length(tvb);
+ pgmlen = tvb_length(tvb);
+ if (pgm_check_checksum && pgmlen >= reportedlen) {
+ vec_t cksum_vec[1];
+ guint16 computed_cksum;
+
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, offset, pgmlen);
+ cksum_vec[0].len = pgmlen;
+ computed_cksum = in_cksum(&cksum_vec[0], 1);
+ if (computed_cksum == 0) {
+ proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb,
+ offset+6, 2, pgmhdr.cksum, "Checksum: 0x%04x (correct)", pgmhdr.cksum);
+ } else {
+ proto_tree_add_boolean_hidden(pgm_tree, hf_pgm_main_cksum_bad, tvb,
+ offset+6, 2, TRUE);
+ proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb,
+ offset+6, 2, pgmhdr.cksum, "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ pgmhdr.cksum, in_cksum_shouldbe(pgmhdr.cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_uint(pgm_tree, hf_pgm_main_cksum, tvb, offset+6,
+ 2, pgmhdr.cksum);
+ }
+
+ proto_tree_add_bytes(pgm_tree, hf_pgm_main_gsi, tvb, offset+8,
+ 6, pgmhdr.gsi);
+ proto_tree_add_uint(pgm_tree, hf_pgm_main_tsdulen, tvb,
+ offset+14, 2, pgmhdr.tsdulen);
+
+ offset = sizeof(pgm_type);
+ tf = proto_tree_add_text(pgm_tree, tvb, offset, plen, "%s Packet",
+ pktname);
+ switch(pgmhdr.type) {
+ case PGM_SPM_PCKT:
+ type_tree = proto_item_add_subtree(tf, ett_pgm_spm);
+
+ proto_tree_add_uint(type_tree, hf_pgm_spm_sqn, tvb,
+ offset, 4, spm.sqn);
+ proto_tree_add_uint(type_tree, hf_pgm_spm_trail, tvb,
+ offset+4, 4, spm.trail);
+ proto_tree_add_uint(type_tree, hf_pgm_spm_lead, tvb,
+ offset+8, 4, spm.lead);
+ proto_tree_add_uint(type_tree, hf_pgm_spm_pathafi, tvb,
+ offset+12, 2, spm.path_afi);
+ proto_tree_add_uint(type_tree, hf_pgm_spm_res, tvb,
+ offset+14, 2, spm.res);
+ switch (spm.path_afi) {
+
+ case AFNUM_INET:
+ proto_tree_add_ipv4(type_tree, hf_pgm_spm_path,
+ tvb, offset+16, 4, spm.path);
+ break;
+
+ default:
+ /*
+ * XXX - the header is variable-length,
+ * as the length of the NLA depends on
+ * its AFI.
+ *
+ * However, our structure for it is
+ * fixed-length, and assumes it's a 4-byte
+ * IPv4 address.
+ */
+ return;
+ }
+
+ if ((pgmhdr.opts & PGM_OPT) == FALSE)
+ break;
+ offset += plen;
+
+ dissect_pgmopts(tvb, offset, type_tree, pktname);
+
+ break;
+
+ case PGM_RDATA_PCKT:
+ case PGM_ODATA_PCKT: {
+ type_tree = proto_item_add_subtree(tf, ett_pgm_data);
+
+ proto_tree_add_uint(type_tree, hf_pgm_spm_sqn, tvb,
+ offset, 4, data.sqn);
+ proto_tree_add_uint(type_tree, hf_pgm_spm_trail, tvb,
+ offset+4, 4, data.trail);
+
+ if ((pgmhdr.opts & PGM_OPT) == FALSE)
+ break;
+ offset += plen;
+
+ dissect_pgmopts(tvb, offset, type_tree, pktname);
+
+ break;
+ }
+
+
+ case PGM_NAK_PCKT:
+ case PGM_NNAK_PCKT:
+ case PGM_NCF_PCKT:
+ type_tree = proto_item_add_subtree(tf, ett_pgm_nak);
+
+ proto_tree_add_uint(type_tree, hf_pgm_nak_sqn, tvb,
+ offset, 4, nak.sqn);
+ proto_tree_add_uint(type_tree, hf_pgm_nak_srcafi, tvb,
+ offset+4, 2, nak.src_afi);
+ proto_tree_add_uint(type_tree, hf_pgm_nak_srcres, tvb,
+ offset+6, 2, nak.src_res);
+
+ switch (nak.src_afi) {
+
+ case AFNUM_INET:
+ proto_tree_add_ipv4(type_tree, hf_pgm_nak_src,
+ tvb, offset+8, 4, nak.src);
+ break;
+
+ default:
+ /*
+ * XXX - the header is variable-length,
+ * as the length of the NLA depends on
+ * its AFI.
+ *
+ * However, our structure for it is
+ * fixed-length, and assumes it's a 4-byte
+ * IPv4 address.
+ */
+ break;
+ }
+
+ proto_tree_add_uint(type_tree, hf_pgm_nak_grpafi, tvb,
+ offset+12, 2, nak.grp_afi);
+ proto_tree_add_uint(type_tree, hf_pgm_nak_grpres, tvb,
+ offset+14, 2, nak.grp_res);
+
+ switch (nak.grp_afi) {
+
+ case AFNUM_INET:
+ proto_tree_add_ipv4(type_tree, hf_pgm_nak_grp,
+ tvb, offset+16, 4, nak.grp);
+ break;
+
+ default:
+ /*
+ * XXX - the header is variable-length,
+ * as the length of the NLA depends on
+ * its AFI.
+ *
+ * However, our structure for it is
+ * fixed-length, and assumes it's a 4-byte
+ * IPv4 address.
+ */
+ return;
+ }
+
+ if ((pgmhdr.opts & PGM_OPT) == FALSE)
+ break;
+ offset += plen;
+
+ dissect_pgmopts(tvb, offset, type_tree, pktname);
+
+ break;
+ case PGM_POLL_PCKT:
+ type_tree = proto_item_add_subtree(tf, ett_pgm_poll);
+
+ proto_tree_add_uint(type_tree, hf_pgm_poll_sqn, tvb,
+ offset, 4, poll.sqn);
+ proto_tree_add_uint(type_tree, hf_pgm_poll_round, tvb,
+ offset+4, 2, poll.round);
+ proto_tree_add_uint(type_tree, hf_pgm_poll_subtype, tvb,
+ offset+6, 2, poll.subtype);
+ proto_tree_add_uint(type_tree, hf_pgm_poll_pathafi, tvb,
+ offset+8, 2, poll.path_afi);
+ proto_tree_add_uint(type_tree, hf_pgm_poll_res, tvb,
+ offset+10, 2, poll.res);
+
+ switch (poll.path_afi) {
+
+ case AFNUM_INET:
+ proto_tree_add_ipv4(type_tree, hf_pgm_poll_path,
+ tvb, offset+12, 4, poll.path);
+ break;
+
+ default:
+ /*
+ * XXX - the header is variable-length,
+ * as the length of the NLA depends on
+ * its AFI.
+ *
+ * However, our structure for it is
+ * fixed-length, and assumes it's a 4-byte
+ * IPv4 address.
+ */
+ break;
+ }
+
+ proto_tree_add_uint(type_tree, hf_pgm_poll_backoff_ivl, tvb,
+ offset+16, 4, poll.backoff_ivl);
+ proto_tree_add_uint(type_tree, hf_pgm_poll_rand_str, tvb,
+ offset+20, 4, poll.rand_str);
+ proto_tree_add_uint(type_tree, hf_pgm_poll_matching_bmask, tvb,
+ offset+24, 4, poll.matching_bmask);
+
+ if ((pgmhdr.opts & PGM_OPT) == FALSE)
+ break;
+ offset += plen;
+
+ dissect_pgmopts(tvb, offset, type_tree, pktname);
+
+ break;
+ case PGM_POLR_PCKT:
+ type_tree = proto_item_add_subtree(tf, ett_pgm_polr);
+
+ proto_tree_add_uint(type_tree, hf_pgm_polr_sqn, tvb,
+ offset, 4, polr.sqn);
+ proto_tree_add_uint(type_tree, hf_pgm_polr_round, tvb,
+ offset+4, 2, polr.round);
+ proto_tree_add_uint(type_tree, hf_pgm_polr_res, tvb,
+ offset+6, 2, polr.res);
+
+ if ((pgmhdr.opts & PGM_OPT) == FALSE)
+ break;
+ offset += plen;
+
+ dissect_pgmopts(tvb, offset, type_tree, pktname);
+
+ break;
+ case PGM_ACK_PCKT:
+ type_tree = proto_item_add_subtree(tf, ett_pgm_ack);
+
+ proto_tree_add_uint(type_tree, hf_pgm_ack_sqn, tvb,
+ offset, 4, ack.rx_max_sqn);
+ proto_tree_add_uint(type_tree, hf_pgm_ack_bitmap, tvb,
+ offset+4, 4, ack.bitmap);
+
+ if ((pgmhdr.opts & PGM_OPT) == FALSE)
+ break;
+ offset += plen;
+
+ dissect_pgmopts(tvb, offset, type_tree, pktname);
+
+ break;
+ }
+
+ }
+ if (isdata) {
+ /*
+ * Now see if there are any sub-dissectors, if so call them
+ */
+ offset = total_size(tvb, &pgmhdr);
+ decode_pgm_ports(tvb, offset, pinfo, tree, &pgmhdr);
+ }
+ pktname = NULL;
+}
+static const true_false_string opts_present = {
+ "Present",
+ "Not Present"
+};
+
+/* Register all the bits needed with the filtering engine */
+void
+proto_register_pgm(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pgm_main_sport,
+ { "Source Port", "pgm.hdr.sport", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_main_dport,
+ { "Destination Port", "pgm.hdr.dport", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_main_type,
+ { "Type", "pgm.hdr.type", FT_UINT8, BASE_HEX,
+ VALS(type_vals), 0x0, "", HFILL }},
+ { &hf_pgm_main_opts,
+ { "Options", "pgm.hdr.opts", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_main_opts_opt,
+ { "Options", "pgm.hdr.opts.opt", FT_BOOLEAN, BASE_NONE,
+ TFS(&opts_present), PGM_OPT, "", HFILL }},
+ { &hf_pgm_main_opts_netsig,
+ { "Network Significant Options", "pgm.hdr.opts.netsig",
+ FT_BOOLEAN, BASE_NONE,
+ TFS(&opts_present), PGM_OPT_NETSIG, "", HFILL }},
+ { &hf_pgm_main_opts_varlen,
+ { "Variable length Parity Packet Option", "pgm.hdr.opts.varlen",
+ FT_BOOLEAN, BASE_NONE,
+ TFS(&opts_present), PGM_OPT_VAR_PKTLEN, "", HFILL }},
+ { &hf_pgm_main_opts_parity,
+ { "Parity", "pgm.hdr.opts.parity", FT_BOOLEAN, BASE_NONE,
+ TFS(&opts_present), PGM_OPT_PARITY, "", HFILL }},
+ { &hf_pgm_main_cksum,
+ { "Checksum", "pgm.hdr.cksum", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_main_cksum_bad,
+ { "Bad Checksum", "pgm.hdr.cksum_bad", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_main_gsi,
+ { "Global Source Identifier", "pgm.hdr.gsi", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_main_tsdulen,
+ { "Transport Service Data Unit Length", "pgm.hdr.tsdulen", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_pgm_spm_sqn,
+ { "Sequence number", "pgm.spm.sqn", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_spm_trail,
+ { "Trailing Edge Sequence Number", "pgm.spm.trail", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_spm_lead,
+ { "Leading Edge Sequence Number", "pgm.spm.lead", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_spm_pathafi,
+ { "Path NLA AFI", "pgm.spm.pathafi", FT_UINT16, BASE_DEC,
+ VALS(afn_vals), 0x0, "", HFILL }},
+ { &hf_pgm_spm_res,
+ { "Reserved", "pgm.spm.res", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_spm_path,
+ { "Path NLA", "pgm.spm.path", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_data_sqn,
+ { "Data Packet Sequence Number", "pgm.data.sqn", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_data_trail,
+ { "Trailing Edge Sequence Number", "pgm.data.trail", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_nak_sqn,
+ { "Requested Sequence Number", "pgm.nak.sqn", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_nak_srcafi,
+ { "Source NLA AFI", "pgm.nak.srcafi", FT_UINT16, BASE_DEC,
+ VALS(afn_vals), 0x0, "", HFILL }},
+ { &hf_pgm_nak_srcres,
+ { "Reserved", "pgm.nak.srcres", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_nak_src,
+ { "Source NLA", "pgm.nak.src", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_nak_grpafi,
+ { "Multicast Group AFI", "pgm.nak.grpafi", FT_UINT16, BASE_DEC,
+ VALS(afn_vals), 0x0, "", HFILL }},
+ { &hf_pgm_nak_grpres,
+ { "Reserved", "pgm.nak.grpres", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_nak_grp,
+ { "Multicast Group NLA", "pgm.nak.grp", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_poll_sqn,
+ { "Sequence Number", "pgm.poll.sqn", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_poll_round,
+ { "Round", "pgm.poll.round", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_poll_subtype,
+ { "Subtype", "pgm.poll.subtype", FT_UINT16, BASE_HEX,
+ VALS(poll_subtype_vals), 0x0, "", HFILL }},
+ { &hf_pgm_poll_pathafi,
+ { "Path NLA AFI", "pgm.poll.pathafi", FT_UINT16, BASE_DEC,
+ VALS(afn_vals), 0x0, "", HFILL }},
+ { &hf_pgm_poll_res,
+ { "Reserved", "pgm.poll.res", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_poll_path,
+ { "Path NLA", "pgm.poll.path", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_poll_backoff_ivl,
+ { "Back-off Interval", "pgm.poll.backoff_ivl", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_poll_rand_str,
+ { "Random String", "pgm.poll.rand_str", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_poll_matching_bmask,
+ { "Matching Bitmask", "pgm.poll.matching_bmask", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_polr_sqn,
+ { "Sequence Number", "pgm.polr.sqn", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_polr_round,
+ { "Round", "pgm.polr.round", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_polr_res,
+ { "Reserved", "pgm.polr.res", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_ack_sqn,
+ { "Maximum Received Sequence Number", "pgm.ack.maxsqn", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_pgm_ack_bitmap,
+ { "Packet Bitmap", "pgm.ack.bitmap", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_type,
+ { "Type", "pgm.opts.type", FT_UINT8, BASE_HEX,
+ VALS(opt_vals), 0x0, "", HFILL }},
+ { &hf_pgm_opt_len,
+ { "Length", "pgm.opts.len", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_tlen,
+ { "Total Length", "pgm.opts.tlen", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_genopt_type,
+ { "Type", "pgm.genopts.type", FT_UINT8, BASE_HEX,
+ VALS(opt_vals), 0x0, "", HFILL }},
+ { &hf_pgm_genopt_len,
+ { "Length", "pgm.genopts.len", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_genopt_opx,
+ { "Option Extensibility Bits", "pgm.genopts.opx", FT_UINT8, BASE_HEX,
+ VALS(opx_vals), 0x0, "", HFILL }},
+ { &hf_pgm_opt_parity_prm_po,
+ { "Parity Parameters", "pgm.opts.parity_prm.op", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_parity_prm_prmtgsz,
+ { "Transmission Group Size", "pgm.opts.parity_prm.prm_grp",
+ FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_join_res,
+ { "Reserved", "pgm.opts.join.res", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_join_minjoin,
+ { "Minimum Sequence Number", "pgm.opts.join.min_join",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_parity_grp_res,
+ { "Reserved", "pgm.opts.parity_prm.op", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_parity_grp_prmgrp,
+ { "Transmission Group Size", "pgm.opts.parity_prm.prm_grp",
+ FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_nak_res,
+ { "Reserved", "pgm.opts.nak.op", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_nak_list,
+ { "List", "pgm.opts.nak.list", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccdata_res,
+ { "Reserved", "pgm.opts.ccdata.res", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccdata_tsp,
+ { "Time Stamp", "pgm.opts.ccdata.tstamp", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccdata_afi,
+ { "Acker AFI", "pgm.opts.ccdata.afi", FT_UINT16, BASE_DEC,
+ VALS(afn_vals), 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccdata_res2,
+ { "Reserved", "pgm.opts.ccdata.res2", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccdata_acker,
+ { "Acker", "pgm.opts.ccdata.acker", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccfeedbk_res,
+ { "Reserved", "pgm.opts.ccdata.res", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccfeedbk_tsp,
+ { "Time Stamp", "pgm.opts.ccdata.tstamp", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccfeedbk_afi,
+ { "Acker AFI", "pgm.opts.ccdata.afi", FT_UINT16, BASE_DEC,
+ VALS(afn_vals), 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccfeedbk_lossrate,
+ { "Loss Rate", "pgm.opts.ccdata.lossrate", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_ccfeedbk_acker,
+ { "Acker", "pgm.opts.ccdata.acker", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_nak_bo_ivl_res,
+ { "Reserved", "pgm.opts.nak_bo_ivl.res", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_nak_bo_ivl_bo_ivl,
+ { "Back-off Interval", "pgm.opts.nak_bo_ivl.bo_ivl", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn,
+ { "Back-off Interval Sequence Number", "pgm.opts.nak_bo_ivl.bo_ivl_sqn", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_nak_bo_rng_res,
+ { "Reserved", "pgm.opts.nak_bo_rng.res", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_nak_bo_rng_min_bo_ivl,
+ { "Min Back-off Interval", "pgm.opts.nak_bo_rng.min_bo_ivl", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_nak_bo_rng_max_bo_ivl,
+ { "Max Back-off Interval", "pgm.opts.nak_bo_rng.max_bo_ivl", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_redirect_res,
+ { "Reserved", "pgm.opts.redirect.res", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_redirect_afi,
+ { "DLR AFI", "pgm.opts.redirect.afi", FT_UINT16, BASE_DEC,
+ VALS(afn_vals), 0x0, "", HFILL }},
+ { &hf_pgm_opt_redirect_res2,
+ { "Reserved", "pgm.opts.redirect.res2", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_redirect_dlr,
+ { "DLR", "pgm.opts.redirect.dlr", FT_IPv4, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_fragment_res,
+ { "Reserved", "pgm.opts.fragment.res", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_fragment_first_sqn,
+ { "First Sequence Number", "pgm.opts.fragment.first_sqn", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_fragment_offset,
+ { "Fragment Offset", "pgm.opts.fragment.fragment_offset", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_pgm_opt_fragment_total_length,
+ { "Total Length", "pgm.opts.fragment.total_length", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_pgm,
+ &ett_pgm_optbits,
+ &ett_pgm_spm,
+ &ett_pgm_data,
+ &ett_pgm_nak,
+ &ett_pgm_poll,
+ &ett_pgm_polr,
+ &ett_pgm_ack,
+ &ett_pgm_opts,
+ &ett_pgm_opts_join,
+ &ett_pgm_opts_parityprm,
+ &ett_pgm_opts_paritygrp,
+ &ett_pgm_opts_naklist,
+ &ett_pgm_opts_ccdata,
+ &ett_pgm_opts_nak_bo_ivl,
+ &ett_pgm_opts_nak_bo_rng,
+ &ett_pgm_opts_redirect,
+ &ett_pgm_opts_fragment,
+ };
+ module_t *pgm_module;
+
+ proto_pgm = proto_register_protocol("Pragmatic General Multicast",
+ "PGM", "pgm");
+
+ proto_register_field_array(proto_pgm, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ subdissector_table = register_dissector_table("pgm.port",
+ "PGM port", FT_UINT16, BASE_DEC);
+ register_heur_dissector_list("pgm", &heur_subdissector_list);
+
+ /*
+ * Register configuration preferences for UDP encapsulation
+ * (Note: Initially the ports are set to zero so the
+ * dissecting of PGM encapsulated in UPD packets
+ * is off by default)
+ */
+ pgm_module = prefs_register_protocol(proto_pgm, proto_rereg_pgm);
+
+ prefs_register_bool_preference(pgm_module, "check_checksum",
+ "Check the validity of the PGM checksum when possible",
+ "Whether to check the validity of the PGM checksum",
+ &pgm_check_checksum);
+
+ prefs_register_uint_preference(pgm_module, "udp.encap_ucast_port",
+ "PGM Encap Unicast Port (standard is 3055)",
+ "PGM Encap is PGM packets encapsulated in UDP packets"
+ " (Note: This option is off, i.e. port is 0, by default)",
+ 10, &udp_encap_ucast_port);
+ old_encap_ucast_port = udp_encap_ucast_port;
+
+ prefs_register_uint_preference(pgm_module, "udp.encap_mcast_port",
+ "PGM Encap Multicast Port (standard is 3056)",
+ "PGM Encap is PGM packets encapsulated in UDP packets"
+ " (Note: This option is off, i.e. port is 0, by default)",
+ 10, &udp_encap_mcast_port);
+
+ old_encap_mcast_port = udp_encap_mcast_port;
+}
+
+static dissector_handle_t pgm_handle;
+
+/* The registration hand-off routine */
+void
+proto_reg_handoff_pgm(void)
+{
+ pgm_handle = create_dissector_handle(dissect_pgm, proto_pgm);
+
+ /*
+ * Set up PGM Encap dissecting, which is off by default
+ */
+ dissector_add("udp.port", udp_encap_ucast_port, pgm_handle);
+ dissector_add("udp.port", udp_encap_mcast_port, pgm_handle);
+
+ dissector_add("ip.proto", IP_PROTO_PGM, pgm_handle);
+
+ data_handle = find_dissector("data");
+}
+
+static void
+proto_rereg_pgm(void)
+{
+ /*
+ * Remove the old ones
+ */
+ dissector_delete("udp.port", old_encap_ucast_port, pgm_handle);
+ dissector_delete("udp.port", old_encap_mcast_port, pgm_handle);
+
+ /*
+ * Set the new ones
+ */
+ dissector_add("udp.port", udp_encap_ucast_port, pgm_handle);
+ dissector_add("udp.port", udp_encap_mcast_port, pgm_handle);
+}
diff --git a/epan/dissectors/packet-pim.c b/epan/dissectors/packet-pim.c
new file mode 100644
index 0000000000..485bb0ee33
--- /dev/null
+++ b/epan/dissectors/packet-pim.c
@@ -0,0 +1,1210 @@
+/* packet-pim.c
+ * Routines for PIM disassembly
+ * (c) Copyright Jun-ichiro itojun Hagino <itojun@itojun.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stddef.h> /* For offsetof */
+#include <string.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "ipproto.h"
+#include "afn.h"
+#include "packet-ipv6.h"
+#include "in_cksum.h"
+
+#define PIM_TYPE(x) ((x) & 0x0f)
+#define PIM_VER(x) (((x) & 0xf0) >> 4)
+
+enum pimv2_addrtype {
+ pimv2_unicast, pimv2_group, pimv2_source
+};
+
+static int proto_pim = -1;
+static int hf_pim_version = -1;
+static int hf_pim_type = -1;
+static int hf_pim_code = -1;
+static int hf_pim_cksum = -1;
+
+static gint ett_pim = -1;
+
+static dissector_handle_t ip_handle;
+static dissector_handle_t ipv6_handle;
+
+/*
+ * For PIM v1, see the PDF slides at
+ *
+ * http://www.mbone.de/training/Module3.pdf
+ *
+ * Is it documented anywhere else?
+ */
+static const char *
+dissect_pimv1_addr(tvbuff_t *tvb, int offset) {
+ static char buf[512];
+ guint16 flags_masklen;
+
+ flags_masklen = tvb_get_ntohs(tvb, offset);
+ if (flags_masklen & 0x0180) {
+ (void)snprintf(buf, sizeof(buf),
+ "(%s%s%s) ",
+ flags_masklen & 0x0100 ? "S" : "",
+ flags_masklen & 0x0080 ? "W" : "",
+ flags_masklen & 0x0040 ? "R" : "");
+ } else
+ buf[0] = '\0';
+ (void)snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s/%u",
+ ip_to_str(tvb_get_ptr(tvb, offset + 2, 4)), flags_masklen & 0x3f);
+
+ return buf;
+}
+
+static const value_string type1vals[] = {
+ { 0, "Query" },
+ { 1, "Register" },
+ { 2, "Register-stop" },
+ { 3, "Join/Prune" },
+ { 4, "RP-Reachable" },
+ { 5, "Assert" },
+ { 6, "Graft" },
+ { 7, "Graft-Ack" },
+ { 8, "Mode" },
+ { 0, NULL },
+};
+
+/* This function is only called from the IGMP dissector */
+int
+dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset) {
+ guint8 pim_type;
+ guint8 pim_ver;
+ guint length, pim_length;
+ guint16 pim_cksum, computed_cksum;
+ vec_t cksum_vec[1];
+ proto_tree *pim_tree = NULL;
+ proto_item *ti;
+ proto_tree *pimopt_tree = NULL;
+ proto_item *tiopt;
+
+ if (!proto_is_protocol_enabled(find_protocol_by_id(proto_pim))) {
+ /*
+ * We are not enabled; skip entire packet to be nice to the
+ * IGMP layer (so clicking on IGMP will display the data).
+ */
+ return offset+tvb_length_remaining(tvb, offset);
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIMv1");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, FALSE);
+ pim_tree = proto_item_add_subtree(ti, ett_pim);
+
+ /* Put IGMP type, 0x14, into the tree */
+ proto_tree_add_text(pim_tree, tvb, offset, 1,
+ "Type: PIM (0x14)");
+ }
+ offset += 1;
+
+ pim_type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(pim_type, type1vals, "Unknown (%u)"));
+
+ if (tree) {
+ proto_tree_add_uint(pim_tree, hf_pim_code, tvb, offset, 1, pim_type);
+ }
+ offset += 1;
+
+ pim_cksum = tvb_get_ntohs(tvb, offset);
+ pim_ver = PIM_VER(tvb_get_guint8(tvb, offset + 2));
+ if (pim_ver != 1) {
+ /*
+ * Not PIMv1 - what gives?
+ */
+ if (tree) {
+ proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb,
+ offset, 2, pim_cksum);
+ }
+ offset += 2;
+ if (tree)
+ proto_tree_add_uint(pim_tree, hf_pim_version, tvb, offset, 1, pim_ver);
+ return offset+tvb_length_remaining(tvb, offset);
+ }
+
+ /*
+ * Well, it's PIM v1, so we can check whether this is a
+ * Register message, and thus can figure out how much to
+ * checksum and whether to make the columns read-only.
+ */
+ length = tvb_length(tvb);
+ if (pim_type == 1) {
+ /*
+ * Register message - the PIM header is 8 bytes long.
+ * Also set the columns non-writable. Otherwise the IPv4 or
+ * IPv6 dissector for the encapsulated packet that caused
+ * this register will overwrite the PIM info in the columns.
+ */
+ pim_length = 8;
+ col_set_writable(pinfo->cinfo, FALSE);
+ } else {
+ /*
+ * Other message - checksum the entire packet.
+ */
+ pim_length = tvb_reported_length(tvb);
+ }
+
+ if (tree) {
+ if (!pinfo->fragmented && length >= pim_length) {
+ /*
+ * The packet isn't part of a fragmented datagram and isn't
+ * truncated, so we can checksum it.
+ */
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length);
+ cksum_vec[0].len = pim_length;
+ computed_cksum = in_cksum(&cksum_vec[0], 1);
+ if (computed_cksum == 0) {
+ proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
+ offset, 2, pim_cksum,
+ "Checksum: 0x%04x (correct)",
+ pim_cksum);
+ } else {
+ proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
+ offset, 2, pim_cksum,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb,
+ offset, 2, pim_cksum);
+ }
+ }
+ offset += 2;
+
+ if (tree)
+ proto_tree_add_uint(pim_tree, hf_pim_version, tvb, offset, 1, pim_ver);
+ offset += 1;
+
+ offset += 3; /* skip reserved stuff */
+
+ if (tree) {
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1,
+ "PIM parameters");
+ pimopt_tree = proto_item_add_subtree(tiopt, ett_pim);
+ } else
+ goto done;
+
+ /* version 1 decoder */
+ switch (pim_type) {
+ case 0: /* query */
+ {
+ guint8 mode;
+ guint16 holdtime;
+ static const value_string pimv1_modevals[] = {
+ { 0, "Dense" },
+ { 1, "Sparse" },
+ { 2, "Sparse-Dense" },
+ { 0, NULL },
+ };
+
+ mode = tvb_get_guint8(tvb, offset) >> 4;
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+ "Mode: %s",
+ val_to_str(mode, pimv1_modevals, "Unknown (%u)"));
+ offset += 2;
+ holdtime = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 2,
+ "Holdtime: %u%s", holdtime,
+ holdtime == 0xffff ? " (infty)" : "");
+ offset += 2;
+ break;
+ }
+
+ case 1: /* register */
+ {
+ guint8 v_hl;
+ tvbuff_t *next_tvb;
+
+ /*
+ * The rest of the packet is a multicast data packet.
+ */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ /*
+ * It's an IP packet - determine whether it's IPv4 or IPv6.
+ */
+ v_hl = tvb_get_guint8(tvb, offset);
+ switch((v_hl & 0xf0) >> 4) {
+ case 0: /* Null-Register dummy header.
+ * Has the same address family as the encapsulating PIM packet,
+ * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet.
+ */
+ if (pinfo->src.type == AT_IPv4) {
+ proto_tree_add_text(pimopt_tree, tvb, offset, -1,
+ "IPv4 dummy header");
+ proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4,
+ "Source: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
+ proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4,
+ "Group: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
+ } else if (pinfo->src.type == AT_IPv6) {
+ struct ip6_hdr ip6_hdr;
+ tvb_memcpy(tvb, (guint8 *)&ip6_hdr, offset,
+ sizeof ip6_hdr);
+ proto_tree_add_text(pimopt_tree, tvb, offset, -1,
+ "IPv6 dummy header");
+ proto_tree_add_text(pimopt_tree, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_src), 16,
+ "Source: %s",
+ ip6_to_str(&ip6_hdr.ip6_src));
+ proto_tree_add_text(pimopt_tree, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_dst), 16,
+ "Group: %s",
+ ip6_to_str(&ip6_hdr.ip6_dst));
+ } else
+ proto_tree_add_text(pimopt_tree, tvb, offset, -1,
+ "Dummy header for an unknown protocol");
+ break;
+ case 4: /* IPv4 */
+#if 0
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+#else
+ call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree);
+#endif
+ break;
+ case 6: /* IPv6 */
+#if 0
+ call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+#else
+ call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree);
+#endif
+ break;
+ default:
+ proto_tree_add_text(pimopt_tree, tvb, offset, -1,
+ "Unknown IP version %d", (v_hl & 0xf0) >> 4);
+ break;
+ }
+ break;
+ }
+
+ case 2: /* register-stop */
+ {
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "Group: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "Source: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ break;
+ }
+
+ case 3: /* join/prune */
+ case 6: /* graft */
+ case 7: /* graft-ack */
+ {
+ int off;
+ const char *s;
+ int ngroup, i, njoin, nprune, j;
+ guint16 holdtime;
+ guint8 mask_len;
+ guint8 adr_len;
+ proto_tree *grouptree = NULL;
+ proto_item *tigroup;
+ proto_tree *subtree = NULL;
+ proto_item *tisub;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "Upstream-neighbor: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ offset += 2; /* skip reserved stuff */
+
+ holdtime = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 2,
+ "Holdtime: %u%s", holdtime,
+ holdtime == 0xffff ? " (infty)" : "");
+ offset += 2;
+
+ offset += 1; /* skip reserved stuff */
+
+ mask_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+ "Mask length: %u", mask_len);
+ offset += 1;
+
+ adr_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+ "Address length: %u", adr_len);
+ offset += 1;
+
+ ngroup = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+ "Groups: %u", ngroup);
+ offset += 1;
+
+ for (i = 0; i < ngroup; i++) {
+ tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "Group %d: %s", i,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ grouptree = proto_item_add_subtree(tigroup, ett_pim);
+ offset += 4;
+
+ proto_tree_add_text(grouptree, tvb, offset, 4,
+ "Group %d Mask: %s", i,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ njoin = tvb_get_ntohs(tvb, offset);
+ nprune = tvb_get_ntohs(tvb, offset + 2);
+
+ tisub = proto_tree_add_text(grouptree, tvb, offset, 2,
+ "Join: %d", njoin);
+ subtree = proto_item_add_subtree(tisub, ett_pim);
+ off = offset + 4;
+ for (j = 0; j < njoin; j++) {
+ s = dissect_pimv1_addr(tvb, off);
+ proto_tree_add_text(subtree, tvb, off, 6,
+ "IP address: %s", s);
+ off += 6;
+ }
+
+ tisub = proto_tree_add_text(grouptree, tvb, offset + 2, 2,
+ "Prune: %d", nprune);
+ subtree = proto_item_add_subtree(tisub, ett_pim);
+ for (j = 0; j < nprune; j++) {
+ s = dissect_pimv1_addr(tvb, off);
+ proto_tree_add_text(subtree, tvb, off, 6,
+ "IP address: %s", s);
+ off += 6;
+ }
+ offset = off;
+ }
+ break;
+ }
+
+ case 4: /* rp-reachability */
+ {
+ guint16 holdtime;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "Group Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "Group Mask: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "RP Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ offset += 2; /* skip reserved stuff */
+
+ holdtime = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 2,
+ "Holdtime: %u%s", holdtime,
+ holdtime == 0xffff ? " (infty)" : "");
+ offset += 2;
+ break;
+ }
+
+ case 5: /* assert */
+ {
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "Group Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "Group Mask: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x80, 8,
+ "RP Tree", "Not RP Tree"));
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Preference: %u",
+ tvb_get_ntohl(tvb, offset) & 0x7fffffff);
+ offset += 4;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Metric: %u",
+ tvb_get_ntohl(tvb, offset));
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+done:;
+
+ return offset+tvb_length_remaining(tvb, offset);
+}
+
+static const char *
+dissect_pim_addr(tvbuff_t *tvb, int offset, enum pimv2_addrtype at,
+ int *advance) {
+ static char buf[512];
+ guint8 af;
+ guint8 et;
+ guint8 flags;
+ guint8 mask_len;
+ int len = 0;
+
+ af = tvb_get_guint8(tvb, offset);
+ if (af != AFNUM_INET && af != AFNUM_INET6) {
+ /*
+ * We don't handle the other formats, and addresses don't include
+ * a length field, so we can't even show them as raw bytes.
+ */
+ return NULL;
+ }
+
+ et = tvb_get_guint8(tvb, offset + 1);
+ if (et != 0) {
+ /*
+ * The only defined encoding type is 0, for the native encoding;
+ * again, as addresses don't include a length field, we can't
+ * even show addresses with a different encoding type as raw
+ * bytes.
+ */
+ return NULL;
+ }
+
+ switch (at) {
+ case pimv2_unicast:
+ switch (af) {
+ case AFNUM_INET:
+ len = 4;
+ (void)snprintf(buf, sizeof(buf), "%s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 2, len)));
+ break;
+
+ case AFNUM_INET6:
+ len = 16;
+ (void)snprintf(buf, sizeof(buf), "%s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 2, len)));
+ break;
+ }
+ if (advance)
+ *advance = 2 + len;
+ break;
+
+ case pimv2_group:
+ mask_len = tvb_get_guint8(tvb, offset + 3);
+ switch (af) {
+ case AFNUM_INET:
+ len = 4;
+ (void)snprintf(buf, sizeof(buf), "%s/%u",
+ ip_to_str(tvb_get_ptr(tvb, offset + 4, len)), mask_len);
+ break;
+
+ case AFNUM_INET6:
+ len = 16;
+ (void)snprintf(buf, sizeof(buf), "%s/%u",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, len)), mask_len);
+ break;
+ }
+ if (advance)
+ *advance = 4 + len;
+ break;
+
+ case pimv2_source:
+ flags = tvb_get_guint8(tvb, offset + 2);
+ mask_len = tvb_get_guint8(tvb, offset + 3);
+ switch (af) {
+ case AFNUM_INET:
+ len = 4;
+ (void)snprintf(buf, sizeof(buf), "%s/%u",
+ ip_to_str(tvb_get_ptr(tvb, offset + 4, len)), mask_len);
+ break;
+
+ case AFNUM_INET6:
+ len = 16;
+ (void)snprintf(buf, sizeof(buf), "%s/%u",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, len)), mask_len);
+ break;
+ }
+ if (flags) {
+ (void)snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+ " (%s%s%s)",
+ flags & 0x04 ? "S" : "",
+ flags & 0x02 ? "W" : "",
+ flags & 0x01 ? "R" : "");
+ }
+ if (advance)
+ *advance = 4 + len;
+ break;
+ default:
+ return NULL;
+ }
+
+ return buf;
+}
+
+static const value_string type2vals[] = {
+ { 0, "Hello" },
+ { 1, "Register" },
+ { 2, "Register-stop" },
+ { 3, "Join/Prune" },
+ { 4, "Bootstrap" },
+ { 5, "Assert" },
+ { 6, "Graft" },
+ { 7, "Graft-Ack" },
+ { 8, "Candidate-RP-Advertisement" },
+ { 0, NULL },
+};
+
+/*
+ * For PIM v2, see RFC 2362, and draft-ietf-pim-sm-v2-new-03 (when PIM
+ * is run over IPv6, the rules for computing the PIM checksum from the
+ * draft in question, not from RFC 2362, should be used).
+ */
+static void
+dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ int offset = 0;
+ guint8 pim_typever;
+ guint length, pim_length;
+ guint16 pim_cksum, computed_cksum;
+ vec_t cksum_vec[4];
+ guint32 phdr[2];
+ char *typestr;
+ proto_tree *pim_tree = NULL;
+ proto_item *ti;
+ proto_tree *pimopt_tree = NULL;
+ proto_item *tiopt;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIM");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ pim_typever = tvb_get_guint8(tvb, 0);
+
+ switch (PIM_VER(pim_typever)) {
+ case 2:
+ typestr = val_to_str(PIM_TYPE(pim_typever), type2vals, "Unknown (%u)");
+ break;
+ case 1: /* PIMv1 - we should never see this */
+ default:
+ typestr = "Unknown";
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "PIMv%d",
+ PIM_VER(pim_typever));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, typestr);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, FALSE);
+ pim_tree = proto_item_add_subtree(ti, ett_pim);
+
+ proto_tree_add_uint(pim_tree, hf_pim_version, tvb, offset, 1,
+ PIM_VER(pim_typever));
+ proto_tree_add_uint(pim_tree, hf_pim_type, tvb, offset, 1,
+ PIM_TYPE(pim_typever));
+
+ pim_cksum = tvb_get_ntohs(tvb, offset + 2);
+ length = tvb_length(tvb);
+ if (PIM_VER(pim_typever) == 2) {
+ /*
+ * Well, it's PIM v2, so we can check whether this is a Register
+ * message, and thus can figure out how much to checksum and
+ * whether to make the columns read-only.
+ */
+ if (PIM_TYPE(pim_typever) == 1) {
+ /*
+ * Register message - the PIM header is 8 bytes long.
+ * Also set the columns non-writable. Otherwise the IPv4 or
+ * IPv6 dissector for the encapsulated packet that caused
+ * this register will overwrite the PIM info in the columns.
+ */
+ pim_length = 8;
+ col_set_writable(pinfo->cinfo, FALSE);
+ } else {
+ /*
+ * Other message - checksum the entire packet.
+ */
+ pim_length = tvb_reported_length(tvb);
+ }
+ } else {
+ /*
+ * We don't know what type of message this is, so say that
+ * the length is 0, to force it not to be checksummed.
+ */
+ pim_length = 0;
+ }
+ if (!pinfo->fragmented && length >= pim_length) {
+ /*
+ * The packet isn't part of a fragmented datagram and isn't
+ * truncated, so we can checksum it.
+ */
+
+ switch (pinfo->src.type) {
+ case AT_IPv4:
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length);
+ cksum_vec[0].len = pim_length;
+ computed_cksum = in_cksum(&cksum_vec[0], 1);
+ break;
+ case AT_IPv6:
+ /* Set up the fields of the pseudo-header. */
+ cksum_vec[0].ptr = pinfo->src.data;
+ cksum_vec[0].len = pinfo->src.len;
+ cksum_vec[1].ptr = pinfo->dst.data;
+ cksum_vec[1].len = pinfo->dst.len;
+ cksum_vec[2].ptr = (const guint8 *)&phdr;
+ phdr[0] = g_htonl(pim_length);
+ phdr[1] = g_htonl(IP_PROTO_PIM);
+ cksum_vec[2].len = 8;
+ cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, pim_length);
+ cksum_vec[3].len = pim_length;
+ computed_cksum = in_cksum(&cksum_vec[0], 4);
+ break;
+ default:
+ /* PIM is available for IPv4 and IPv6 right now */
+ computed_cksum = 0; /* squelch GCC complaints */
+ g_assert_not_reached();
+ break;
+ }
+
+ if (computed_cksum == 0) {
+ proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
+ offset + 2, 2, pim_cksum,
+ "Checksum: 0x%04x (correct)",
+ pim_cksum);
+ } else {
+ proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
+ offset + 2, 2, pim_cksum,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb,
+ offset + 2, 2, pim_cksum);
+ }
+
+ offset += 4;
+
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1,
+ "PIM parameters");
+ pimopt_tree = proto_item_add_subtree(tiopt, ett_pim);
+ } else
+ goto done;
+
+ if (PIM_VER(pim_typever) != 2)
+ goto done;
+
+ /* version 2 decoder */
+ switch (PIM_TYPE(pim_typever)) {
+ case 0: /*hello*/
+ {
+ while (tvb_reported_length_remaining(tvb, offset) >= 2) {
+ guint16 hello_opt, opt_len;
+ guint16 holdtime;
+ guint16 lan_delay;
+ guint16 override_interval;
+ guint32 priority;
+ guint32 opt_value = 0;
+
+ hello_opt = tvb_get_ntohs(tvb, offset);
+ opt_len = tvb_get_ntohs(tvb, offset + 2);
+
+ if(opt_len == 2)
+ opt_value = tvb_get_ntohs(tvb, offset + 4);
+ if(opt_len == 4)
+ opt_value = tvb_get_ntohl(tvb, offset + 4);
+
+ switch(hello_opt) {
+ case 1: /* holdtime */
+ holdtime = opt_value;
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len,
+ "Holdtime (%u): %us %s", hello_opt, holdtime,
+ holdtime == 0xffff ? " (infty)" : "");
+ break;
+ case 2: /* LAN prune delay
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type = 2 | Length = 4 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |T| LAN Prune Delay | Override Interval |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ {
+ proto_tree *sub_tree = NULL;
+ proto_item *landelay_option;
+
+ landelay_option = proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len,
+ "LAN Prune Delay (%u)", hello_opt);
+ sub_tree = proto_item_add_subtree(landelay_option, ett_pim);
+
+ lan_delay = (opt_value & 0x7fff0000) >> 16;
+ override_interval = opt_value & 0x0000ffff;
+ proto_tree_add_text(sub_tree, tvb, offset + 4, 1,
+ "T bit is %s",
+ opt_value & 0x8000 ? "set" : "not set");
+ proto_tree_add_text(sub_tree, tvb, offset + 4, 2,
+ "LAN Delay: %ums", lan_delay);
+ proto_tree_add_text(sub_tree, tvb, offset + 6, 2,
+ "Override Interval: %ums", override_interval);
+ break;
+ }
+ case 19: /* priority */
+ priority = opt_value;
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len,
+ "DR Priority (%u): %u", hello_opt, priority);
+ break;
+ case 20: /* generation ID */
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len,
+ "Generation ID (%u): %d", hello_opt, opt_value);
+ break;
+
+ case 24: /* address list */
+ case 65001: /* address list (old implementations) */
+ {
+ int i;
+ proto_tree *sub_tree = NULL;
+ proto_item *addrlist_option;
+
+ addrlist_option = proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len,
+ "%sAddress List (%u)",
+ hello_opt == 65001 ? "old " : "",
+ hello_opt);
+ sub_tree = proto_item_add_subtree(addrlist_option, ett_pim);
+
+ for (i = offset + 4; i < offset + 4 + opt_len; ) {
+ int advance;
+ const char *s;
+
+ s = dissect_pim_addr(tvb, i, pimv2_unicast, &advance);
+ if (s == NULL)
+ break;
+ proto_tree_add_text(sub_tree, tvb, offset,
+ advance, "Address: %s", s);
+ i += advance;
+ }
+ break;
+ }
+ default:
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len,
+ "Unknown option (%u), length: %u, value: 0x%x",
+ hello_opt, opt_len, opt_value);
+ break;
+ }
+ offset += 4 + opt_len;
+ }
+ break;
+ }
+
+ case 1: /* register */
+ {
+ guint32 flags;
+ guint8 v_hl;
+ tvbuff_t *next_tvb;
+ proto_tree *flag_tree = NULL;
+ proto_item *tiflag;
+
+ flags = tvb_get_ntohl(tvb, offset);
+ tiflag = proto_tree_add_text(pimopt_tree, tvb, offset, 4,
+ "Flags: 0x%08x", flags);
+ flag_tree = proto_item_add_subtree(tiflag, ett_pim);
+ proto_tree_add_text(flag_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(flags, 0x80000000, 32,
+ "Border", "Not border"));
+ proto_tree_add_text(flag_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(flags, 0x40000000, 32,
+ "Null-Register", "Not Null-Register"));
+ offset += 4;
+
+ /*
+ * The rest of the packet is a multicast data packet.
+ */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ /*
+ * It's an IP packet - determine whether it's IPv4 or IPv6.
+ */
+ v_hl = tvb_get_guint8(tvb, offset);
+ switch((v_hl & 0xf0) >> 4) {
+ case 0: /* Null-Register dummy header.
+ * Has the same address family as the encapsulating PIM packet,
+ * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet.
+ */
+ if (pinfo->src.type == AT_IPv4) {
+ proto_tree_add_text(pimopt_tree, tvb, offset, -1,
+ "IPv4 dummy header");
+ proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4,
+ "Source: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 12, 4)));
+ proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4,
+ "Group: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset + 16, 4)));
+ } else if (pinfo->src.type == AT_IPv6) {
+ struct ip6_hdr ip6_hdr;
+ tvb_memcpy(tvb, (guint8 *)&ip6_hdr, offset,
+ sizeof ip6_hdr);
+ proto_tree_add_text(pimopt_tree, tvb, offset, -1,
+ "IPv6 dummy header");
+ proto_tree_add_text(pimopt_tree, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_src), 16,
+ "Source: %s",
+ ip6_to_str(&ip6_hdr.ip6_src));
+ proto_tree_add_text(pimopt_tree, tvb,
+ offset + offsetof(struct ip6_hdr, ip6_dst), 16,
+ "Group: %s",
+ ip6_to_str(&ip6_hdr.ip6_dst));
+ } else
+ proto_tree_add_text(pimopt_tree, tvb, offset, -1,
+ "Dummy header for an unknown protocol");
+ break;
+ case 4: /* IPv4 */
+#if 0
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+#else
+ call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree);
+#endif
+ break;
+ case 6: /* IPv6 */
+#if 0
+ call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+#else
+ call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree);
+#endif
+ break;
+ default:
+ proto_tree_add_text(pimopt_tree, tvb, offset, -1,
+ "Unknown IP version %d", (v_hl & 0xf0) >> 4);
+ break;
+ }
+ break;
+ }
+
+ case 2: /* register-stop */
+ {
+ int advance;
+ const char *s;
+
+ s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
+ if (s == NULL)
+ break;
+ proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s);
+ offset += advance;
+ s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
+ if (s == NULL)
+ break;
+ proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s);
+ break;
+ }
+
+ case 3: /* join/prune */
+ case 6: /* graft */
+ case 7: /* graft-ack */
+ {
+ int advance;
+ int off;
+ const char *s;
+ int ngroup, i, njoin, nprune, j;
+ guint16 holdtime;
+ proto_tree *grouptree = NULL;
+ proto_item *tigroup;
+ proto_tree *subtree = NULL;
+ proto_item *tisub;
+
+ if (PIM_TYPE(pim_typever) != 7) {
+ /* not graft-ack */
+ s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
+ if (s == NULL)
+ break;
+ proto_tree_add_text(pimopt_tree, tvb, offset, advance,
+ "Upstream-neighbor: %s", s);
+ offset += advance;
+ }
+
+ offset += 1; /* skip reserved field */
+
+ ngroup = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+ "Groups: %u", ngroup);
+ offset += 1;
+
+ if (PIM_TYPE(pim_typever) != 7) {
+ /* not graft-ack */
+ holdtime = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 2,
+ "Holdtime: %u%s", holdtime,
+ holdtime == 0xffff ? " (infty)" : "");
+ }
+ offset += 2;
+
+ for (i = 0; i < ngroup; i++) {
+ s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
+ if (s == NULL)
+ goto breakbreak3;
+ tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance,
+ "Group %d: %s", i, s);
+ grouptree = proto_item_add_subtree(tigroup, ett_pim);
+ offset += advance;
+
+ njoin = tvb_get_ntohs(tvb, offset);
+ nprune = tvb_get_ntohs(tvb, offset + 2);
+
+ tisub = proto_tree_add_text(grouptree, tvb, offset, 2,
+ "Join: %d", njoin);
+ subtree = proto_item_add_subtree(tisub, ett_pim);
+ off = offset + 4;
+ for (j = 0; j < njoin; j++) {
+ s = dissect_pim_addr(tvb, off, pimv2_source,
+ &advance);
+ if (s == NULL)
+ goto breakbreak3;
+ proto_tree_add_text(subtree, tvb, off, advance,
+ "IP address: %s", s);
+ off += advance;
+ }
+
+ tisub = proto_tree_add_text(grouptree, tvb, offset + 2, 2,
+ "Prune: %d", nprune);
+ subtree = proto_item_add_subtree(tisub, ett_pim);
+ for (j = 0; j < nprune; j++) {
+ s = dissect_pim_addr(tvb, off, pimv2_source,
+ &advance);
+ if (s == NULL)
+ goto breakbreak3;
+ proto_tree_add_text(subtree, tvb, off, advance,
+ "IP address: %s", s);
+ off += advance;
+ }
+ offset = off;
+ }
+ breakbreak3:
+ break;
+ }
+
+ case 4: /* bootstrap */
+ {
+ const char *s;
+ int advance;
+ int i, j;
+ int frpcnt;
+ guint16 holdtime;
+ proto_tree *grouptree = NULL;
+ proto_item *tigroup;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 2,
+ "Fragment tag: 0x%04x", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+ "Hash mask len: %u", tvb_get_guint8(tvb, offset));
+ offset += 1;
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+ "BSR priority: %u", tvb_get_guint8(tvb, offset));
+ offset += 1;
+
+ s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
+ if (s == NULL)
+ break;
+ proto_tree_add_text(pimopt_tree, tvb, offset, advance, "BSR: %s", s);
+ offset += advance;
+
+ for (i = 0; tvb_reported_length_remaining(tvb, offset) > 0; i++) {
+ s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
+ if (s == NULL)
+ goto breakbreak4;
+ tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance,
+ "Group %d: %s", i, s);
+ grouptree = proto_item_add_subtree(tigroup, ett_pim);
+ offset += advance;
+
+ proto_tree_add_text(grouptree, tvb, offset, 1,
+ "RP count: %u", tvb_get_guint8(tvb, offset));
+ offset += 1;
+ frpcnt = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(grouptree, tvb, offset, 1,
+ "FRP count: %u", frpcnt);
+ offset += 3;
+
+ for (j = 0; j < frpcnt; j++) {
+ s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
+ if (s == NULL)
+ goto breakbreak4;
+ proto_tree_add_text(grouptree, tvb, offset, advance,
+ "RP %d: %s", j, s);
+ offset += advance;
+
+ holdtime = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(grouptree, tvb, offset, 2,
+ "Holdtime: %u%s", holdtime,
+ holdtime == 0xffff ? " (infty)" : "");
+ offset += 2;
+ proto_tree_add_text(grouptree, tvb, offset, 1,
+ "Priority: %u", tvb_get_guint8(tvb, offset));
+ offset += 2; /* also skips reserved field */
+ }
+ }
+
+ breakbreak4:
+ break;
+ }
+
+ case 5: /* assert */
+ {
+ const char *s;
+ int advance;
+
+ s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
+ if (s == NULL)
+ break;
+ proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s);
+ offset += advance;
+
+ s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
+ if (s == NULL)
+ break;
+ proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s);
+ offset += advance;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x80, 8,
+ "RP Tree", "Not RP Tree"));
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Preference: %u",
+ tvb_get_ntohl(tvb, offset) & 0x7fffffff);
+ offset += 4;
+
+ proto_tree_add_text(pimopt_tree, tvb, offset, 4, "Metric: %u",
+ tvb_get_ntohl(tvb, offset));
+
+ break;
+ }
+
+ case 8: /* Candidate-RP-Advertisement */
+ {
+ const char *s;
+ int advance;
+ int pfxcnt;
+ guint16 holdtime;
+ int i;
+
+ pfxcnt = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+ "Prefix-count: %u", pfxcnt);
+ offset += 1;
+ proto_tree_add_text(pimopt_tree, tvb, offset, 1,
+ "Priority: %u", tvb_get_guint8(tvb, offset));
+ offset += 1;
+ holdtime = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(pimopt_tree, tvb, offset, 2,
+ "Holdtime: %u%s", holdtime,
+ holdtime == 0xffff ? " (infty)" : "");
+ offset += 2;
+
+ s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
+ if (s == NULL)
+ break;
+ proto_tree_add_text(pimopt_tree, tvb, offset, advance, "RP: %s", s);
+ offset += advance;
+
+ for (i = 0; i < pfxcnt; i++) {
+ s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
+ if (s == NULL)
+ goto breakbreak8;
+ proto_tree_add_text(pimopt_tree, tvb, offset, advance,
+ "Group %d: %s", i, s);
+ offset += advance;
+ }
+ breakbreak8:
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+done:;
+}
+
+void
+proto_register_pim(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pim_version,
+ { "Version", "pim.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+ { &hf_pim_type,
+ { "Type", "pim.type",
+ FT_UINT8, BASE_DEC, VALS(type2vals), 0x0, "", HFILL }},
+ { &hf_pim_code,
+ { "Code", "pim.code",
+ FT_UINT8, BASE_DEC, VALS(type1vals), 0x0, "", HFILL }},
+ { &hf_pim_cksum,
+ { "Checksum", "pim.cksum",
+ FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_pim,
+ };
+
+ proto_pim = proto_register_protocol("Protocol Independent Multicast",
+ "PIM", "pim");
+ proto_register_field_array(proto_pim, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pim(void)
+{
+ dissector_handle_t pim_handle;
+
+ pim_handle = create_dissector_handle(dissect_pim, proto_pim);
+ dissector_add("ip.proto", IP_PROTO_PIM, pim_handle);
+
+ /*
+ * Get handles for the IPv4 and IPv6 dissectors.
+ */
+ ip_handle = find_dissector("ip");
+ ipv6_handle = find_dissector("ipv6");
+}
diff --git a/epan/dissectors/packet-pim.h b/epan/dissectors/packet-pim.h
new file mode 100644
index 0000000000..e4b7514212
--- /dev/null
+++ b/epan/dissectors/packet-pim.h
@@ -0,0 +1,30 @@
+/* packet-pim.h
+ * Declarations of routines for IGMP/PIMv1 packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_PIM_H__
+#define __PACKET_PIM_H__
+
+int dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset);
+
+#endif
diff --git a/epan/dissectors/packet-pktc.c b/epan/dissectors/packet-pktc.c
new file mode 100644
index 0000000000..07b63f5bf6
--- /dev/null
+++ b/epan/dissectors/packet-pktc.c
@@ -0,0 +1,784 @@
+/* packet-pktc.c
+ * Routines for PacketCable (PKTC) Kerberized Key Management and
+ * PacketCable (PKTC) MTA FQDN packet disassembly
+ *
+ * References:
+ * [1] PacketCable Security Specification, PKT-SP-SEC-I10-040113, January 13,
+ * 2004, Cable Television Laboratories, Inc., http://www.PacketCable.com/
+ *
+ * Ronnie Sahlberg 2004
+ * Thomas Anders 2004
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include "packet-pktc.h"
+#include "packet-kerberos.h"
+
+#define PKTC_PORT 1293
+#define PKTC_MTAFQDN_PORT 2246
+
+static int proto_pktc = -1;
+static gint hf_pktc_app_spec_data = -1;
+static gint hf_pktc_list_of_ciphersuites = -1;
+static gint hf_pktc_list_of_ciphersuites_len = -1;
+static gint hf_pktc_kmmid = -1;
+static gint hf_pktc_doi = -1;
+static gint hf_pktc_version_major = -1;
+static gint hf_pktc_version_minor = -1;
+static gint hf_pktc_server_nonce = -1;
+static gint hf_pktc_server_principal = -1;
+static gint hf_pktc_timestamp = -1;
+static gint hf_pktc_snmpEngineID_len = -1;
+static gint hf_pktc_snmpEngineID = -1;
+static gint hf_pktc_snmpEngineBoots = -1;
+static gint hf_pktc_snmpEngineTime = -1;
+static gint hf_pktc_usmUserName_len = -1;
+static gint hf_pktc_usmUserName = -1;
+static gint hf_pktc_ipsec_spi = -1;
+static gint hf_pktc_snmpAuthenticationAlgorithm = -1;
+static gint hf_pktc_snmpEncryptionTransformID = -1;
+static gint hf_pktc_ipsecAuthenticationAlgorithm = -1;
+static gint hf_pktc_ipsecEncryptionTransformID = -1;
+static gint hf_pktc_reestablish_flag = -1;
+static gint hf_pktc_ack_required_flag = -1;
+static gint hf_pktc_sha1_hmac = -1;
+static gint hf_pktc_sec_param_lifetime = -1;
+static gint hf_pktc_grace_period = -1;
+
+static gint hf_pktc_mtafqdn_msgtype = -1;
+static gint hf_pktc_mtafqdn_enterprise = -1;
+static gint hf_pktc_mtafqdn_version = -1;
+static gint hf_pktc_mtafqdn_mac = -1;
+static gint hf_pktc_mtafqdn_pub_key_hash = -1;
+static gint hf_pktc_mtafqdn_manu_cert_revoked = -1;
+static gint hf_pktc_mtafqdn_fqdn = -1;
+static gint hf_pktc_mtafqdn_ip = -1;
+
+static gint ett_pktc = -1;
+static gint ett_pktc_app_spec_data = -1;
+static gint ett_pktc_list_of_ciphersuites = -1;
+
+static gint ett_pktc_mtafqdn = -1;
+
+#define KMMID_WAKEUP 0x01
+#define KMMID_AP_REQUEST 0x02
+#define KMMID_AP_REPLY 0x03
+#define KMMID_SEC_PARAM_REC 0x04
+#define KMMID_REKEY 0x05
+#define KMMID_ERROR_REPLY 0x06
+static const value_string kmmid_types[] = {
+ { KMMID_WAKEUP , "Wake Up" },
+ { KMMID_AP_REQUEST , "AP Request" },
+ { KMMID_AP_REPLY , "AP Reply" },
+ { KMMID_SEC_PARAM_REC , "Security Parameter Recovered" },
+ { KMMID_REKEY , "Rekey" },
+ { KMMID_ERROR_REPLY , "Error Reply" },
+ { 0, NULL }
+};
+
+#define DOI_IPSEC 1
+#define DOI_SNMPv3 2
+#define SNMPv3_NULL 0x20
+#define SNMPv3_DES 0x21
+#define SNMPv3_HMAC_MD5 0x21
+#define SNMPv3_HMAC_SHA1 0x22
+#define ESP_3DES 0x03
+#define ESP_RC5 0x04
+#define ESP_IDEA 0x05
+#define ESP_CAST 0x06
+#define ESP_BLOWFISH 0x07
+#define ESP_NULL 0x0b
+#define ESP_AES 0x0c
+#define HMAC_MD5_96 0x01
+#define HMAC_SHA1_96 0x02
+
+
+/* Domain of Interpretation */
+static const value_string doi_types[] = {
+ { DOI_IPSEC , "IPsec" },
+ { DOI_SNMPv3 , "SNMPv3" },
+ { 0, NULL }
+};
+
+/* SNMPv3 ciphersuites */
+static const value_string snmp_authentication_algorithm_vals[] = {
+ { SNMPv3_HMAC_MD5 , "HMAC-MD5" },
+ { SNMPv3_HMAC_SHA1 , "HMAC-SHA1" },
+ { 0 , NULL }
+};
+static const value_string snmp_transform_id_vals[] = {
+ { SNMPv3_NULL , "NULL" }, /* no encryption */
+ { SNMPv3_DES , "DES" },
+ { 0 , NULL }
+};
+
+/* IPsec ciphersuites */
+static const value_string ipsec_transform_id_vals[] = {
+ { ESP_3DES , "3DES" },
+ { ESP_RC5 , "RC5" },
+ { ESP_IDEA , "IDEA" },
+ { ESP_CAST , "CAST" },
+ { ESP_BLOWFISH , "BLOWFISH" },
+ { ESP_NULL , "NULL" }, /* no encryption, RFC 2410 */
+ { ESP_AES , "AES-128" },
+ { 0 , NULL }
+};
+
+static const value_string ipsec_authentication_algorithm_vals[] = {
+ { HMAC_MD5_96 , "HMAC-MD5-96" }, /* RFC 2403 */
+ { HMAC_SHA1_96 , "HMAC-SHA-1-96" }, /* RFC 2404 */
+ { 0 , NULL }
+};
+
+/* MTA FQDN Message Types */
+#define PKTC_MTAFQDN_REQ 0x01
+#define PKTC_MTAFQDN_REP 0x02
+#define PKTC_MTAFQDN_ERR 0x03
+static const value_string pktc_mtafqdn_msgtype_vals[] = {
+ { PKTC_MTAFQDN_REQ, "MTA FQDN Request" },
+ { PKTC_MTAFQDN_REP, "MTA FQDN Reply" },
+ { PKTC_MTAFQDN_ERR, "MTA FQDN Error Reply" },
+ { 0 , NULL }
+};
+
+static int
+dissect_pktc_app_specific_data(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 doi, guint8 kmmid)
+{
+ int old_offset=offset;
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ guint8 len;
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, hf_pktc_app_spec_data, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_pktc_app_spec_data);
+ }
+
+ switch(doi){
+ case DOI_SNMPv3:
+ switch(kmmid){
+ /* we dont distinguish between manager and agent engineid.
+ feel free to add separation for this if it is imporant enough
+ for you. */
+ case KMMID_AP_REQUEST:
+ case KMMID_AP_REPLY:
+ /* snmpEngineID Length */
+ len=tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_pktc_snmpEngineID_len, tvb, offset, 1, len);
+ offset+=1;
+
+ /* snmpEngineID */
+ proto_tree_add_item(tree, hf_pktc_snmpEngineID, tvb, offset, len, FALSE);
+ offset+=len;
+
+ /* boots */
+ proto_tree_add_item(tree, hf_pktc_snmpEngineBoots, tvb, offset, 4, FALSE);
+ offset+=4;
+
+ /* time */
+ proto_tree_add_item(tree, hf_pktc_snmpEngineTime, tvb, offset, 4, FALSE);
+ offset+=4;
+
+ /* usmUserName Length */
+ len=tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_pktc_usmUserName_len, tvb, offset, 1, len);
+ offset+=1;
+
+ /* usmUserName */
+ proto_tree_add_item(tree, hf_pktc_usmUserName, tvb, offset, len, FALSE);
+ offset+=len;
+
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Unknown KMMID");
+ tvb_get_guint8(tvb, 9999); /* bail out and inform user we cant dissect the packet */
+ };
+ break;
+ case DOI_IPSEC:
+ switch(kmmid){
+ /* we dont distinguish between SPIs for inbound Security Associations
+ of the client (AP-REQ) vs. server (AP-REP, REKEY). Feel free to add
+ separation for this if it is imporant enough for you. */
+ case KMMID_AP_REQUEST:
+ case KMMID_AP_REPLY:
+ case KMMID_REKEY:
+ /* Security Parameter Index (SPI) */
+ proto_tree_add_item(tree, hf_pktc_ipsec_spi, tvb, offset, 4, FALSE);
+ offset+=4;
+
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Unknown KMMID");
+ tvb_get_guint8(tvb, 9999); /* bail out and inform user we cant dissect the packet */
+ };
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Unknown DOI");
+ tvb_get_guint8(tvb, 9999); /* bail out and inform user we cant dissect the packet */
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_pktc_list_of_ciphersuites(packet_info *pinfo _U_, proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 doi)
+{
+ int old_offset=offset;
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ guint8 len, i;
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, hf_pktc_list_of_ciphersuites, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_pktc_list_of_ciphersuites);
+ }
+
+
+ /* number of ciphersuites */
+ len=tvb_get_guint8(tvb, offset);
+ if (len>0) {
+ proto_item_append_text(tree, " (%d):", len);
+ }
+ proto_tree_add_uint_hidden(tree, hf_pktc_list_of_ciphersuites_len, tvb, offset, 1, len);
+ offset+=1;
+
+ switch(doi){
+ case DOI_SNMPv3:
+ for(i=0;i<len;i++){
+ /* SNMPv3 authentication algorithm */
+ proto_tree_add_item(tree, hf_pktc_snmpAuthenticationAlgorithm, tvb, offset, 1, FALSE);
+ proto_item_append_text(tree, " %s", val_to_str(tvb_get_guint8(tvb, offset), snmp_authentication_algorithm_vals, "%0x"));
+ offset+=1;
+
+ /* SNMPv3 encryption transform id */
+ proto_tree_add_item(tree, hf_pktc_snmpEncryptionTransformID, tvb, offset, 1, FALSE);
+ offset+=1;
+ }
+ break;
+ case DOI_IPSEC:
+ for(i=0;i<len;i++){
+ /* IPsec authentication algorithm */
+ proto_tree_add_item(tree, hf_pktc_ipsecAuthenticationAlgorithm, tvb, offset, 1, FALSE);
+ proto_item_append_text(tree, " %s", val_to_str(tvb_get_guint8(tvb, offset), ipsec_authentication_algorithm_vals, "%0x"));
+ offset+=1;
+
+ /* IPsec encryption transform id */
+ proto_tree_add_item(tree, hf_pktc_ipsecEncryptionTransformID, tvb, offset, 1, FALSE);
+ proto_item_append_text(tree, "/%s", val_to_str(tvb_get_guint8(tvb, offset), snmp_transform_id_vals, "%0x"));
+ offset+=1;
+ }
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Unknown DOI");
+ tvb_get_guint8(tvb, 9999); /* bail out and inform user we cant dissect the packet */
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_pktc_wakeup(proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ guint32 snonce;
+ guint string_len;
+
+ /* Server Nonce */
+ snonce=tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_pktc_server_nonce, tvb, offset, 4, snonce);
+ offset+=4;
+
+ /* Server Kerberos Principal Identifier */
+ string_len=tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_pktc_server_principal, tvb, offset, string_len, FALSE);
+ offset+=string_len;
+
+ return offset;
+}
+
+static int
+dissect_pktc_ap_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint8 doi)
+{
+ tvbuff_t *pktc_tvb;
+ guint32 snonce;
+
+ /* AP Request kerberos blob */
+ pktc_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ offset += dissect_kerberos_main(pktc_tvb, pinfo, tree, FALSE, NULL);
+
+ /* Server Nonce */
+ snonce=tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_pktc_server_nonce, tvb, offset, 4, snonce);
+ offset+=4;
+
+ /* app specific data */
+ offset=dissect_pktc_app_specific_data(pinfo, tree, tvb, offset, doi, KMMID_AP_REQUEST);
+
+ /* list of ciphersuites */
+ offset=dissect_pktc_list_of_ciphersuites(pinfo, tree, tvb, offset, doi);
+
+ /* re-establish flag */
+ proto_tree_add_item(tree, hf_pktc_reestablish_flag, tvb, offset, 1, FALSE);
+ offset+=1;
+
+ /* sha-1 hmac */
+ proto_tree_add_item(tree, hf_pktc_sha1_hmac, tvb, offset, 20, FALSE);
+ offset+=20;
+
+ return offset;
+}
+
+static int
+dissect_pktc_ap_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint8 doi)
+{
+ tvbuff_t *pktc_tvb;
+
+ /* AP Reply kerberos blob */
+ pktc_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ offset += dissect_kerberos_main(pktc_tvb, pinfo, tree, FALSE, NULL);
+
+ /* app specific data */
+ offset=dissect_pktc_app_specific_data(pinfo, tree, tvb, offset, doi, KMMID_AP_REPLY);
+
+ /* selected ciphersuite */
+ offset=dissect_pktc_list_of_ciphersuites(pinfo, tree, tvb, offset, doi);
+
+ /* sec param lifetime */
+ proto_tree_add_uint_format(tree, hf_pktc_sec_param_lifetime, tvb, offset, 4,
+ tvb_get_ntohl(tvb, offset), "%s: %s",
+ proto_registrar_get_name(hf_pktc_sec_param_lifetime),
+ time_secs_to_str(tvb_get_ntohl(tvb, offset)));
+ offset+=4;
+
+ /* grace period */
+ proto_tree_add_item(tree, hf_pktc_grace_period, tvb, offset, 4, FALSE);
+ offset+=4;
+
+ /* re-establish flag */
+ proto_tree_add_item(tree, hf_pktc_reestablish_flag, tvb, offset, 1, FALSE);
+ offset+=1;
+
+ /* ack required flag */
+ proto_tree_add_item(tree, hf_pktc_ack_required_flag, tvb, offset, 1, FALSE);
+ offset+=1;
+
+ /* sha-1 hmac */
+ proto_tree_add_item(tree, hf_pktc_sha1_hmac, tvb, offset, 20, FALSE);
+ offset+=20;
+
+ return offset;
+}
+
+static int
+dissect_pktc_sec_param_rec(proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ /* sha-1 hmac of the subkey of the preceding AP-REP */
+ proto_tree_add_item(tree, hf_pktc_sha1_hmac, tvb, offset, 20, FALSE);
+ offset+=20;
+
+ return offset;
+}
+
+static int
+dissect_pktc_rekey(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint8 doi)
+{
+ guint32 snonce;
+ guint string_len;
+ const guint8 *timestr;
+
+ /* Server Nonce */
+ snonce=tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_pktc_server_nonce, tvb, offset, 4, snonce);
+ offset+=4;
+
+ /* Server Kerberos Principal Identifier */
+ string_len=tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_pktc_server_principal, tvb, offset, string_len, FALSE);
+ offset+=string_len;
+
+ /* Timestamp: YYMMDDhhmmssZ */
+ /* They really came up with a two-digit year in late 1990s! =8o */
+ timestr=tvb_get_ptr(tvb, offset, 13);
+ proto_tree_add_string_format(tree, hf_pktc_timestamp, tvb, offset, 13, timestr,
+ "%s: %.2s-%.2s-%.2s %.2s:%.2s:%.2s",
+ proto_registrar_get_name(hf_pktc_timestamp),
+ timestr, timestr+2, timestr+4, timestr+6, timestr+8, timestr+10);
+ offset+=13;
+
+ /* app specific data */
+ offset=dissect_pktc_app_specific_data(pinfo, tree, tvb, offset, doi, KMMID_REKEY);
+
+ /* list of ciphersuites */
+ offset=dissect_pktc_list_of_ciphersuites(pinfo, tree, tvb, offset, doi);
+
+ /* sec param lifetime */
+ proto_tree_add_item(tree, hf_pktc_sec_param_lifetime, tvb, offset, 4, FALSE);
+ offset+=4;
+
+ /* grace period */
+ proto_tree_add_item(tree, hf_pktc_grace_period, tvb, offset, 4, FALSE);
+ offset+=4;
+
+ /* re-establish flag */
+ proto_tree_add_item(tree, hf_pktc_reestablish_flag, tvb, offset, 1, FALSE);
+ offset+=1;
+
+ /* sha-1 hmac */
+ proto_tree_add_item(tree, hf_pktc_sha1_hmac, tvb, offset, 20, FALSE);
+ offset+=20;
+
+ return offset;
+}
+
+static int
+dissect_pktc_error_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+ tvbuff_t *pktc_tvb;
+
+ /* KRB_ERROR */
+ pktc_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ offset += dissect_kerberos_main(pktc_tvb, pinfo, tree, FALSE, NULL);
+
+ return offset;
+}
+
+static int
+dissect_pktc_mtafqdn_krbsafeuserdata(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree)
+{
+ int offset=0, string_len=0;
+ guint8 msgtype;
+ guint32 bignum;
+ nstime_t ts;
+
+ /* message type */
+ msgtype = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_pktc_mtafqdn_msgtype, tvb, offset, 1, msgtype);
+ offset+=1;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str(msgtype, pktc_mtafqdn_msgtype_vals, "MsgType %u"));
+
+ /* enterprise */
+ proto_tree_add_uint(tree, hf_pktc_mtafqdn_enterprise, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+
+ /* protocol version */
+ proto_tree_add_uint(tree, hf_pktc_mtafqdn_version, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ offset+=1;
+
+ switch(msgtype) {
+ case PKTC_MTAFQDN_REQ:
+ /* MTA MAC address */
+ proto_tree_add_ether(tree, hf_pktc_mtafqdn_mac, tvb, offset, 6, tvb_get_ptr(tvb, offset, 6));
+ offset+=6;
+
+ /* MTA pub key hash */
+ proto_tree_add_item(tree, hf_pktc_mtafqdn_pub_key_hash, tvb, offset, 20, FALSE);
+ offset+=20;
+
+ /* manufacturer cert revocation time */
+ bignum = tvb_get_ntohl(tvb, offset);
+ ts.secs = bignum;
+ proto_tree_add_time_format(tree, hf_pktc_mtafqdn_manu_cert_revoked, tvb, offset, 4,
+ &ts, "%s: %s",
+ proto_registrar_get_name(hf_pktc_mtafqdn_manu_cert_revoked),
+ (bignum==0) ? "not revoked" : abs_time_secs_to_str(bignum));
+ break;
+
+ case PKTC_MTAFQDN_REP:
+ /* MTA FQDN */
+ string_len = tvb_length_remaining(tvb, offset) - 4;
+ proto_tree_add_item(tree, hf_pktc_mtafqdn_fqdn, tvb, offset, string_len, FALSE);
+ offset+=string_len;
+
+ /* MTA IP address */
+ tvb_memcpy(tvb, (guint8 *)&bignum, offset, sizeof(bignum));
+ proto_tree_add_ipv4(tree, hf_pktc_mtafqdn_ip, tvb, offset, 4, bignum);
+
+ break;
+ }
+
+ return offset;
+}
+
+static kerberos_callbacks cb[] = {
+ { KRB_CBTAG_SAFE_USER_DATA, dissect_pktc_mtafqdn_krbsafeuserdata },
+ { 0, NULL }
+};
+
+static void
+dissect_pktc_mtafqdn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset=0;
+ proto_tree *pktc_mtafqdn_tree = NULL;
+ proto_item *item = NULL;
+ tvbuff_t *pktc_mtafqdn_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PKTC");
+
+ if (tree) {
+ item = proto_tree_add_item(tree, proto_pktc, tvb, 0, 0, FALSE);
+ pktc_mtafqdn_tree = proto_item_add_subtree(item, ett_pktc_mtafqdn);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "MTA FQDN %s",
+ pinfo->srcport == pinfo->match_port ? "Reply":"Request");
+ }
+
+
+ /* KRB_AP_RE[QP] */
+ pktc_mtafqdn_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ offset += dissect_kerberos_main(pktc_mtafqdn_tvb, pinfo, pktc_mtafqdn_tree, FALSE, NULL);
+
+ /* KRB_SAFE */
+ pktc_mtafqdn_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ offset += dissect_kerberos_main(pktc_mtafqdn_tvb, pinfo, pktc_mtafqdn_tree, FALSE, cb);
+
+ proto_item_set_len(item, offset);
+}
+
+
+static void
+dissect_pktc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 kmmid, doi, version;
+ int offset=0;
+ proto_tree *pktc_tree = NULL;
+ proto_item *item = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PKTC");
+
+ if (tree) {
+ item = proto_tree_add_item(tree, proto_pktc, tvb, 0, 3, FALSE);
+ pktc_tree = proto_item_add_subtree(item, ett_pktc);
+ }
+
+ /* key management message id */
+ kmmid=tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(pktc_tree, hf_pktc_kmmid, tvb, offset, 1, kmmid);
+ offset+=1;
+
+ /* domain of interpretation */
+ doi=tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(pktc_tree, hf_pktc_doi, tvb, offset, 1, doi);
+ offset+=1;
+
+ /* version */
+ version=tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(pktc_tree, tvb, offset, 1, "Version: %d.%d", (version>>4)&0x0f, (version)&0x0f);
+ proto_tree_add_uint_hidden(pktc_tree, hf_pktc_version_major, tvb, offset, 1, (version>>4)&0x0f);
+ proto_tree_add_uint_hidden(pktc_tree, hf_pktc_version_minor, tvb, offset, 1, (version)&0x0f);
+ offset+=1;
+
+ /* fill COL_INFO */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(kmmid, kmmid_types, "Unknown KMMID %#x"));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
+ val_to_str(doi, doi_types, "Unknown DOI %#x"));
+ }
+
+ switch(kmmid){
+ case KMMID_WAKEUP:
+ offset=dissect_pktc_wakeup(pktc_tree, tvb, offset);
+ break;
+ case KMMID_AP_REQUEST:
+ offset=dissect_pktc_ap_request(pinfo, pktc_tree, tvb, offset, doi);
+ break;
+ case KMMID_AP_REPLY:
+ offset=dissect_pktc_ap_reply(pinfo, pktc_tree, tvb, offset, doi);
+ break;
+ case KMMID_SEC_PARAM_REC:
+ offset=dissect_pktc_sec_param_rec(pktc_tree, tvb, offset);
+ break;
+ case KMMID_REKEY:
+ offset=dissect_pktc_rekey(pinfo, pktc_tree, tvb, offset, doi);
+ break;
+ case KMMID_ERROR_REPLY:
+ offset=dissect_pktc_error_reply(pinfo, pktc_tree, tvb, offset);
+ break;
+ };
+
+ proto_item_set_len(item, offset);
+}
+
+void
+proto_register_pktc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pktc_kmmid, {
+ "Key Management Message ID", "pktc.kmmid", FT_UINT8, BASE_HEX,
+ VALS(kmmid_types), 0, "Key Management Message ID", HFILL }},
+ { &hf_pktc_doi, {
+ "Domain of Interpretation", "pktc.doi", FT_UINT8, BASE_DEC,
+ VALS(doi_types), 0, "Domain of Interpretation", HFILL }},
+ { &hf_pktc_version_major, {
+ "Major version", "pktc.version.major", FT_UINT8, BASE_DEC,
+ NULL, 0, "Major version of PKTC", HFILL }},
+ { &hf_pktc_version_minor, {
+ "Minor version", "pktc.version.minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "Minor version of PKTC", HFILL }},
+ { &hf_pktc_server_nonce, {
+ "Server Nonce", "pktc.server_nonce", FT_UINT32, BASE_HEX,
+ NULL, 0, "Server Nonce random number", HFILL }},
+ { &hf_pktc_server_principal, {
+ "Server Kerberos Principal Identifier", "pktc.server_principal", FT_STRING, BASE_DEC,
+ NULL, 0, "Server Kerberos Principal Identifier", HFILL }},
+ { &hf_pktc_timestamp, {
+ "Timestamp", "pktc.timestamp", FT_STRING, BASE_NONE,
+ NULL, 0, "Timestamp (UTC)", HFILL }},
+ { &hf_pktc_app_spec_data, {
+ "Application Specific Data", "pktc.asd", FT_NONE, BASE_HEX,
+ NULL, 0, "KMMID/DOI application specific data", HFILL }},
+ { &hf_pktc_list_of_ciphersuites, {
+ "List of Ciphersuites", "pktc.ciphers", FT_NONE, BASE_HEX,
+ NULL, 0, "List of Ciphersuites", HFILL }},
+ { &hf_pktc_list_of_ciphersuites_len, {
+ "Number of Ciphersuites", "pktc.ciphers.len", FT_UINT8, BASE_DEC,
+ NULL, 0, "Number of Ciphersuites", HFILL }},
+ { &hf_pktc_snmpAuthenticationAlgorithm, {
+ "SNMPv3 Authentication Algorithm", "pktc.asd.snmp_auth_alg", FT_UINT8, BASE_HEX,
+ VALS(snmp_authentication_algorithm_vals), 0, "SNMPv3 Authentication Algorithm", HFILL }},
+ { &hf_pktc_snmpEncryptionTransformID, {
+ "SNMPv3 Encryption Transform ID", "pktc.asd.snmp_enc_alg", FT_UINT8, BASE_HEX,
+ VALS(snmp_transform_id_vals), 0, "SNMPv3 Encryption Transform ID", HFILL }},
+ { &hf_pktc_ipsecAuthenticationAlgorithm, {
+ "IPsec Authentication Algorithm", "pktc.asd.ipsec_auth_alg", FT_UINT8, BASE_HEX,
+ VALS(ipsec_authentication_algorithm_vals), 0, "IPsec Authentication Algorithm", HFILL }},
+ { &hf_pktc_ipsecEncryptionTransformID, {
+ "IPsec Encryption Transform ID", "pktc.asd.ipsec_enc_alg", FT_UINT8, BASE_HEX,
+ VALS(ipsec_transform_id_vals), 0, "IPsec Encryption Transform ID", HFILL }},
+ { &hf_pktc_snmpEngineID_len, {
+ "SNMPv3 Engine ID Length", "pktc.asd.snmp_engine_id.len", FT_UINT8, BASE_DEC,
+ NULL, 0, "Length of SNMPv3 Engine ID", HFILL }},
+ { &hf_pktc_snmpEngineID, {
+ "SNMPv3 Engine ID", "pktc.asd.snmp_engine_id", FT_BYTES, BASE_HEX,
+ NULL, 0, "SNMPv3 Engine ID", HFILL }},
+ { &hf_pktc_snmpEngineBoots, {
+ "SNMPv3 Engine Boots", "pktc.asd.snmp_engine_boots", FT_UINT32, BASE_DEC,
+ NULL, 0, "SNMPv3 Engine Boots", HFILL }},
+ { &hf_pktc_snmpEngineTime, {
+ "SNMPv3 Engine Time", "pktc.asd.snmp_engine_time", FT_UINT32, BASE_DEC,
+ NULL, 0, "SNMPv3 Engine ID Time", HFILL }},
+ { &hf_pktc_usmUserName_len, {
+ "SNMPv3 USM User Name Length", "pktc.asd.snmp_usm_username.len", FT_UINT8, BASE_DEC,
+ NULL, 0, "Length of SNMPv3 USM User Name", HFILL }},
+ { &hf_pktc_usmUserName, {
+ "SNMPv3 USM User Name", "pktc.asd.snmp_usm_username", FT_STRING, BASE_DEC,
+ NULL, 0, "SNMPv3 USM User Name", HFILL }},
+ { &hf_pktc_ipsec_spi, {
+ "IPsec Security Parameter Index", "pktc.asd.ipsec_spi", FT_UINT32, BASE_DEC,
+ NULL, 0, "Security Parameter Index for inbound Security Association (IPsec)", HFILL }},
+ { &hf_pktc_reestablish_flag, {
+ "Re-establish Flag", "pktc.reestablish", FT_BOOLEAN, BASE_NONE,
+ NULL, 0, "Re-establish Flag", HFILL }},
+ { &hf_pktc_ack_required_flag, {
+ "ACK Required Flag", "pktc.ack_required", FT_BOOLEAN, BASE_NONE,
+ NULL, 0, "ACK Required Flag", HFILL }},
+ { &hf_pktc_sec_param_lifetime, {
+ "Security Parameter Lifetime", "pktc.spl", FT_UINT32, BASE_DEC,
+ NULL, 0, "Lifetime in seconds of security parameter", HFILL }},
+ { &hf_pktc_sha1_hmac, {
+ "SHA-1 HMAC", "pktc.sha1_hmac", FT_BYTES, BASE_HEX,
+ NULL, 0, "SHA-1 HMAC", HFILL }},
+ { &hf_pktc_grace_period, {
+ "Grace Period", "pktc.grace_period", FT_UINT32, BASE_DEC,
+ NULL, 0, "Grace Period in seconds", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_pktc,
+ &ett_pktc_app_spec_data,
+ &ett_pktc_list_of_ciphersuites,
+ };
+
+ proto_pktc = proto_register_protocol("PacketCable", "PKTC", "pktc");
+ proto_register_field_array(proto_pktc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pktc(void)
+{
+ dissector_handle_t pktc_handle;
+
+ pktc_handle = create_dissector_handle(dissect_pktc, proto_pktc);
+ dissector_add("udp.port", PKTC_PORT, pktc_handle);
+}
+
+
+void
+proto_register_pktc_mtafqdn(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pktc_mtafqdn_msgtype, {
+ "Message Type", "pktc.mtafqdn.msgtype", FT_UINT8, BASE_DEC,
+ VALS(pktc_mtafqdn_msgtype_vals), 0, "MTA FQDN Message Type", HFILL }},
+ { &hf_pktc_mtafqdn_enterprise, {
+ "Enterprise Number", "pktc.mtafqdn.enterprise", FT_UINT32, BASE_DEC,
+ NULL, 0, "Enterprise Number", HFILL }},
+ { &hf_pktc_mtafqdn_version, {
+ "Protocol Version", "pktc.mtafqdn.version", FT_UINT8, BASE_DEC,
+ NULL, 0, "MTA FQDN Protocol Version", HFILL }},
+ /* MTA FQDN REQ */
+ { &hf_pktc_mtafqdn_mac, {
+ "MTA MAC address", "pktc.mtafqdn.mac", FT_ETHER, BASE_NONE,
+ NULL, 0, "MTA MAC address", HFILL }},
+ { &hf_pktc_mtafqdn_pub_key_hash, {
+ "MTA Public Key Hash", "pktc.mtafqdn.pub_key_hash", FT_BYTES, BASE_HEX,
+ NULL, 0, "MTA Public Key Hash (SHA-1)", HFILL }},
+ { &hf_pktc_mtafqdn_manu_cert_revoked, {
+ "Manufacturer Cert Revocation Time", "pktc.mtafqdn.manu_cert_revoked", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Manufacturer Cert Revocation Time (UTC) or 0 if not revoked", HFILL }},
+ /* MTA FQDN REP */
+ { &hf_pktc_mtafqdn_fqdn, {
+ "MTA FQDN", "pktc.mtafqdn.fqdn", FT_STRING, BASE_NONE,
+ NULL, 0, "MTA FQDN", HFILL }},
+ { &hf_pktc_mtafqdn_ip, {
+ "MTA IP Address", "pktc.mtafqdn.ip", FT_IPv4, BASE_NONE,
+ NULL, 0, "MTA IP Address (all zeros if not supplied)", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_pktc_mtafqdn,
+ };
+
+ proto_register_field_array(proto_pktc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pktc_mtafqdn(void)
+{
+ dissector_handle_t pktc_mtafqdn_handle;
+
+ pktc_mtafqdn_handle = create_dissector_handle(dissect_pktc_mtafqdn, proto_pktc);
+ dissector_add("udp.port", PKTC_MTAFQDN_PORT, pktc_mtafqdn_handle);
+}
diff --git a/epan/dissectors/packet-pktc.h b/epan/dissectors/packet-pktc.h
new file mode 100644
index 0000000000..a00b9579c7
--- /dev/null
+++ b/epan/dissectors/packet-pktc.h
@@ -0,0 +1,31 @@
+/* packet-pktc.h
+ * Declarations of routines for PKTC PacketCable packet disassembly
+ * Ronnie Sahlberg 2004
+ * See the spec: PKT-SP-SEC-I10-040113.pdf
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_PKTC_H__
+#define __PACKET_PKTC_H__
+
+
+#endif
diff --git a/epan/dissectors/packet-pop.c b/epan/dissectors/packet-pop.c
new file mode 100644
index 0000000000..e78a53be54
--- /dev/null
+++ b/epan/dissectors/packet-pop.c
@@ -0,0 +1,234 @@
+/* packet-pop.c
+ * Routines for pop packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+static int proto_pop = -1;
+static int hf_pop_response = -1;
+static int hf_pop_request = -1;
+
+static gint ett_pop = -1;
+static gint ett_pop_reqresp = -1;
+
+static dissector_handle_t data_handle;
+
+#define TCP_PORT_POP 110
+
+static gboolean response_is_continuation(const guchar *data);
+
+static void
+dissect_pop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gboolean is_request;
+ gboolean is_continuation;
+ proto_tree *pop_tree, *reqresp_tree;
+ proto_item *ti;
+ gint offset = 0;
+ const guchar *line;
+ gint next_offset;
+ int linelen;
+ int tokenlen;
+ const guchar *next_token;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "POP");
+
+ /*
+ * Find the end of the first line.
+ *
+ * Note that "tvb_find_line_end()" will return a value that is
+ * not longer than what's in the buffer, so the "tvb_get_ptr()"
+ * call won't throw an exception.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ line = tvb_get_ptr(tvb, offset, linelen);
+
+ if (pinfo->match_port == pinfo->destport) {
+ is_request = TRUE;
+ is_continuation = FALSE;
+ } else {
+ is_request = FALSE;
+ is_continuation = response_is_continuation(line);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary
+ * if it's a POP request or reply (but leave out the
+ * line terminator).
+ * Otherwise, just call it a continuation.
+ */
+ if (is_continuation)
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
+ is_request ? "Request" : "Response",
+ format_text(line, linelen));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_pop, tvb, offset, -1,
+ FALSE);
+ pop_tree = proto_item_add_subtree(ti, ett_pop);
+
+ if (is_continuation) {
+ /*
+ * Put the whole packet into the tree as data.
+ */
+ call_dissector(data_handle,tvb, pinfo, pop_tree);
+ return;
+ }
+
+ if (is_request) {
+ proto_tree_add_boolean_hidden(pop_tree,
+ hf_pop_request, tvb, 0, 0, TRUE);
+ } else {
+ proto_tree_add_boolean_hidden(pop_tree,
+ hf_pop_response, tvb, 0, 0, TRUE);
+ }
+
+ /*
+ * Put the line into the protocol tree.
+ */
+ ti = proto_tree_add_text(pop_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ reqresp_tree = proto_item_add_subtree(ti, ett_pop_reqresp);
+
+ /*
+ * Extract the first token, and, if there is a first
+ * token, add it as the request or reply code.
+ */
+ tokenlen = get_token_len(line, line + linelen, &next_token);
+ if (tokenlen != 0) {
+ if (is_request) {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ tokenlen, "Request: %s",
+ format_text(line, tokenlen));
+ } else {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ tokenlen, "Response: %s",
+ format_text(line, tokenlen));
+ }
+ offset += next_token - line;
+ linelen -= next_token - line;
+ line = next_token;
+ }
+
+ /*
+ * Add the rest of the first line as request or
+ * reply data.
+ */
+ if (linelen != 0) {
+ if (is_request) {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ linelen, "Request Arg: %s",
+ format_text(line, linelen));
+ } else {
+ proto_tree_add_text(reqresp_tree, tvb, offset,
+ linelen, "Response Arg: %s",
+ format_text(line, linelen));
+ }
+ }
+ offset = next_offset;
+
+ /*
+ * Show the rest of the request or response as text,
+ * a line at a time.
+ */
+ while (tvb_offset_exists(tvb, offset)) {
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1,
+ &next_offset, FALSE);
+
+ /*
+ * Put this line.
+ */
+ proto_tree_add_text(pop_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ offset = next_offset;
+ }
+ }
+}
+
+static gboolean response_is_continuation(const guchar *data)
+{
+ if (strncmp(data, "+OK", strlen("+OK")) == 0)
+ return FALSE;
+
+ if (strncmp(data, "-ERR", strlen("-ERR")) == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+proto_register_pop(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_pop_response,
+ { "Response", "pop.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if POP response", HFILL }},
+
+ { &hf_pop_request,
+ { "Request", "pop.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if POP request", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_pop,
+ &ett_pop_reqresp,
+ };
+
+ proto_pop = proto_register_protocol("Post Office Protocol", "POP", "pop");
+ proto_register_field_array(proto_pop, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pop(void)
+{
+ dissector_handle_t pop_handle;
+
+ pop_handle = create_dissector_handle(dissect_pop, proto_pop);
+ dissector_add("tcp.port", TCP_PORT_POP, pop_handle);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-portmap.c b/epan/dissectors/packet-portmap.c
new file mode 100644
index 0000000000..72b55e6beb
--- /dev/null
+++ b/epan/dissectors/packet-portmap.c
@@ -0,0 +1,626 @@
+/* packet-portmap.c
+ * Routines for portmap dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-smb.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-portmap.h"
+#include "ipproto.h"
+#include "epan/conversation.h"
+#include "epan/packet_info.h"
+
+/*
+ * See:
+ *
+ * RFC 1833, "Binding Protocols for ONC RPC Version 2".
+ */
+
+static int proto_portmap = -1;
+static int hf_portmap_procedure_v1 = -1;
+static int hf_portmap_procedure_v2 = -1;
+static int hf_portmap_procedure_v3 = -1;
+static int hf_portmap_procedure_v4 = -1;
+static int hf_portmap_proto = -1;
+static int hf_portmap_prog = -1;
+static int hf_portmap_proc = -1;
+static int hf_portmap_version = -1;
+static int hf_portmap_port = -1;
+static int hf_portmap_answer = -1;
+static int hf_portmap_args = -1;
+static int hf_portmap_result = -1;
+static int hf_portmap_rpcb = -1;
+static int hf_portmap_rpcb_prog = -1;
+static int hf_portmap_rpcb_version = -1;
+static int hf_portmap_rpcb_netid = -1;
+static int hf_portmap_rpcb_addr = -1;
+static int hf_portmap_rpcb_owner = -1;
+static int hf_portmap_uaddr = -1;
+
+
+static gint ett_portmap = -1;
+static gint ett_portmap_rpcb = -1;
+static gint ett_portmap_entry = -1;
+
+static dissector_handle_t rpc_handle;
+static dissector_handle_t rpc_tcp_handle;
+
+/* Dissect a getport call */
+static int
+dissect_getport_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 proto;
+ guint32 prog;
+
+ /* make sure we remember protocol type until the reply packet */
+ if(!pinfo->fd->flags.visited){
+ rpc_call_info_value *rpc_call=pinfo->private_data;
+ if(rpc_call){
+ proto = tvb_get_ntohl(tvb, offset+8);
+ if(proto==IP_PROTO_UDP){ /* only do this for UDP */
+ rpc_call->private_data=(void *)PT_UDP;
+ }
+ }
+ }
+
+ if ( tree )
+ {
+ prog = tvb_get_ntohl(tvb, offset+0);
+ proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
+ offset, 4, prog, "Program: %s (%u)",
+ rpc_prog_name(prog), prog);
+ proto_tree_add_item(tree, hf_portmap_version, tvb,
+ offset+4, 4, FALSE);
+
+ proto = tvb_get_ntohl(tvb, offset+8);
+ proto_tree_add_uint_format(tree, hf_portmap_proto, tvb,
+ offset+8, 4, proto, "Proto: %s (%u)", ipprotostr(proto), proto);
+
+ proto_tree_add_item(tree, hf_portmap_port, tvb,
+ offset+12, 4, FALSE);
+ }
+
+ return offset+16;
+}
+
+static int
+dissect_getport_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ /* we might have learnt a <ipaddr><protocol><port> mapping for ONC-RPC*/
+ if(!pinfo->fd->flags.visited){
+ rpc_call_info_value *rpc_call=pinfo->private_data;
+ /* only do this for UDP, TCP does not need anything like this */
+ if(rpc_call && ((int)rpc_call->private_data==PT_UDP) ){
+ guint32 port;
+ port=tvb_get_ntohl(tvb, offset);
+ if(port){
+ conversation_t *conv;
+ conv=find_conversation(&pinfo->src, &pinfo->dst, (port_type)rpc_call->private_data, port, 0, NO_ADDR_B|NO_PORT_B);
+ if(!conv){
+ conv=conversation_new(&pinfo->src, &pinfo->dst, (port_type)rpc_call->private_data, port, 0, NO_ADDR2|NO_PORT2);
+ }
+ conversation_set_dissector(conv, rpc_handle);
+ }
+ }
+ }
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_portmap_port,
+ offset);
+ return offset;
+}
+
+/* Dissect a 'set' call */
+static int
+dissect_set_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 proto;
+ guint32 prog;
+
+ if ( tree )
+ {
+ prog = tvb_get_ntohl(tvb, offset+0);
+ proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
+ offset, 4, prog, "Program: %s (%d)",
+ rpc_prog_name(prog), prog);
+ proto_tree_add_item(tree, hf_portmap_version, tvb,
+ offset+4, 4, FALSE);
+
+ proto = tvb_get_ntohl(tvb, offset+8);
+ proto_tree_add_uint_format(tree, hf_portmap_proto,tvb,
+ offset+8, 4, proto, "Proto: %s (%d)", ipprotostr(proto), proto);
+
+ proto_tree_add_item(tree, hf_portmap_port, tvb,
+ offset+12, 4, FALSE);
+ }
+
+ return offset+16;
+}
+
+/* Dissect a 'unset' call */
+static int
+dissect_unset_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 proto;
+ guint32 prog;
+
+ if ( tree )
+ {
+ prog = tvb_get_ntohl(tvb, offset+0);
+ proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
+ offset, 4, prog, "Program: %s (%d)",
+ rpc_prog_name(prog), prog);
+ proto_tree_add_item(tree, hf_portmap_version, tvb,
+ offset+4, 4, FALSE);
+
+ proto = tvb_get_ntohl(tvb, offset+8);
+ proto_tree_add_uint(tree, hf_portmap_proto, tvb,
+ offset+8, 4, proto);
+
+ proto_tree_add_item(tree, hf_portmap_port, tvb,
+ offset+12, 4, FALSE);
+ }
+
+ return offset+16;
+}
+
+static int
+dissect_set_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ offset = dissect_rpc_bool(tvb, tree, hf_portmap_answer,
+ offset);
+ return offset;
+}
+
+static int
+dissect_dump_entry(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ int prog, version, proto, port;
+ proto_item *ti, *subtree;
+
+ prog = tvb_get_ntohl(tvb, offset+0);
+ version = tvb_get_ntohl(tvb, offset+4);
+ proto = tvb_get_ntohl(tvb, offset+8);
+ port = tvb_get_ntohl(tvb, offset+12);
+ if ( tree )
+ {
+ ti = proto_tree_add_text(tree, tvb, offset, 16,
+ "Map Entry: %s (%u) V%d",
+ rpc_prog_name(prog), prog, version);
+ subtree = proto_item_add_subtree(ti, ett_portmap_entry);
+
+ proto_tree_add_uint_format(subtree, hf_portmap_prog, tvb,
+ offset+0, 4, prog,
+ "Program: %s (%u)", rpc_prog_name(prog), prog);
+ proto_tree_add_uint(subtree, hf_portmap_version, tvb,
+ offset+4, 4, version);
+ proto_tree_add_uint_format(subtree, hf_portmap_proto, tvb,
+ offset+8, 4, proto,
+ "Protocol: %s (0x%02x)", ipprotostr(proto), proto);
+ proto_tree_add_uint(subtree, hf_portmap_port, tvb,
+ offset+12, 4, port);
+ }
+ offset += 16;
+ return offset;
+}
+
+static int
+dissect_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset,
+ dissect_dump_entry);
+ return offset;
+}
+
+/* Dissect a callit call */
+static int
+dissect_callit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint32 prog, vers, proc;
+
+ prog = tvb_get_ntohl(tvb, offset+0);
+ if ( tree )
+ {
+ proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
+ offset, 4, prog, "Program: %s (%u)",
+ rpc_prog_name(prog), prog);
+ }
+
+ vers = tvb_get_ntohl(tvb, offset+4);
+ if ( tree )
+ {
+ proto_tree_add_uint(tree, hf_portmap_version, tvb,
+ offset+4, 4, vers);
+ }
+
+ proc = tvb_get_ntohl(tvb, offset+8);
+ if ( tree )
+ {
+ proto_tree_add_uint_format(tree, hf_portmap_proc, tvb,
+ offset+8, 4, proc, "Procedure: %s (%u)",
+ rpc_proc_name(prog, vers, proc), proc);
+ }
+
+ offset += 12;
+
+ /* Dissect the arguments for this procedure.
+ Make the columns non-writable, so the dissector won't change
+ them out from under us. */
+ col_set_writable(pinfo->cinfo, FALSE);
+ offset = dissect_rpc_indir_call(tvb, pinfo, tree, offset,
+ hf_portmap_args, prog, vers, proc);
+
+ return offset;
+}
+
+/* Dissect a callit reply */
+static int
+dissect_callit_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ if ( tree )
+ {
+ proto_tree_add_item(tree, hf_portmap_port, tvb,
+ offset, 4, FALSE);
+ }
+ offset += 4;
+
+ /* Dissect the result of this procedure.
+ Make the columns non-writable, so the dissector won't change
+ them out from under us. */
+ col_set_writable(pinfo->cinfo, FALSE);
+ offset = dissect_rpc_indir_reply(tvb, pinfo, tree, offset,
+ hf_portmap_result, hf_portmap_prog, hf_portmap_version,
+ hf_portmap_proc);
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff portmap1_proc[] = {
+ { PORTMAPPROC_NULL, "NULL", NULL, NULL },
+ { PORTMAPPROC_SET, "SET", NULL, NULL },
+ { PORTMAPPROC_UNSET, "UNSET", NULL, NULL },
+ { PORTMAPPROC_GETPORT, "GETPORT", NULL, NULL },
+ { PORTMAPPROC_DUMP, "DUMP", NULL, NULL },
+ { PORTMAPPROC_CALLIT, "CALLIT", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string portmap1_proc_vals[] = {
+ { PORTMAPPROC_NULL, "NULL" },
+ { PORTMAPPROC_SET, "SET" },
+ { PORTMAPPROC_UNSET, "UNSET" },
+ { PORTMAPPROC_GETPORT, "GETPORT" },
+ { PORTMAPPROC_DUMP, "DUMP" },
+ { PORTMAPPROC_CALLIT, "CALLIT" },
+ { 0, NULL }
+};
+/* end of Portmap version 1 */
+
+static const vsff portmap2_proc[] = {
+ { PORTMAPPROC_NULL, "NULL",
+ NULL, NULL },
+ { PORTMAPPROC_SET, "SET",
+ dissect_set_call, dissect_set_reply },
+ { PORTMAPPROC_UNSET, "UNSET",
+ dissect_unset_call, dissect_set_reply },
+ { PORTMAPPROC_GETPORT, "GETPORT",
+ dissect_getport_call, dissect_getport_reply },
+ { PORTMAPPROC_DUMP, "DUMP",
+ NULL, dissect_dump_reply },
+ { PORTMAPPROC_CALLIT, "CALLIT",
+ dissect_callit_call, dissect_callit_reply },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string portmap2_proc_vals[] = {
+ { PORTMAPPROC_NULL, "NULL" },
+ { PORTMAPPROC_SET, "SET" },
+ { PORTMAPPROC_UNSET, "UNSET" },
+ { PORTMAPPROC_GETPORT, "GETPORT" },
+ { PORTMAPPROC_DUMP, "DUMP" },
+ { PORTMAPPROC_CALLIT, "CALLIT" },
+ { 0, NULL }
+};
+/* end of Portmap version 2 */
+
+
+/* RFC 1833, Page 3 */
+static int
+dissect_rpcb(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* rpcb_item = NULL;
+ proto_tree* rpcb_tree = NULL;
+ int old_offset = offset;
+ guint32 prog;
+
+ if (tree) {
+ rpcb_item = proto_tree_add_item(tree, hf_portmap_rpcb, tvb,
+ offset, -1, FALSE);
+ if (rpcb_item)
+ rpcb_tree = proto_item_add_subtree(rpcb_item, ett_portmap_rpcb);
+ }
+
+ prog = tvb_get_ntohl(tvb, offset);
+ if (rpcb_tree)
+ proto_tree_add_uint_format(rpcb_tree, hf_portmap_rpcb_prog, tvb,
+ offset, 4, prog,
+ "Program: %s (%u)", rpc_prog_name(prog), prog);
+ offset += 4;
+
+ offset = dissect_rpc_uint32(tvb, rpcb_tree,
+ hf_portmap_rpcb_version, offset);
+ offset = dissect_rpc_string(tvb, rpcb_tree,
+ hf_portmap_rpcb_netid, offset, NULL);
+ offset = dissect_rpc_string(tvb, rpcb_tree,
+ hf_portmap_rpcb_addr, offset, NULL);
+ offset = dissect_rpc_string(tvb, rpcb_tree,
+ hf_portmap_rpcb_owner, offset, NULL);
+
+ /* now we know, that rpcb is shorter */
+ if (rpcb_item) {
+ proto_item_set_len(rpcb_item, offset - old_offset);
+ }
+
+ return offset;
+}
+
+
+
+/* RFC 1833, Page 7 */
+static int
+dissect_rpcb3_getaddr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ offset = dissect_rpcb(tvb, offset, pinfo, tree);
+
+ return offset;
+}
+
+
+/* RFC 1833, Page 7 */
+static int
+dissect_rpcb3_getaddr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree,
+ hf_portmap_uaddr, offset, NULL);
+
+ return offset;
+}
+
+
+/* RFC 1833, Page 7 */
+static int
+dissect_rpcb3_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ offset = dissect_rpc_list(tvb, pinfo, tree, offset, dissect_rpcb);
+ return offset;
+}
+
+/* RFC 1833, page 4 */
+static int
+dissect_rpcb_rmtcallres(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ /* Dissect the remote universal address. */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_portmap_rpcb_addr, offset, NULL);
+
+ /* Dissect the result of this procedure.
+ Make the columns non-writable, so the dissector won't change
+ them out from under us. */
+ col_set_writable(pinfo->cinfo, FALSE);
+ offset = dissect_rpc_indir_reply(tvb, pinfo, tree, offset,
+ hf_portmap_result, hf_portmap_prog, hf_portmap_version,
+ hf_portmap_proc);
+
+ return offset;
+}
+
+
+/* Portmapper version 3, RFC 1833, Page 7 */
+static const vsff portmap3_proc[] = {
+ { RPCBPROC_NULL, "NULL",
+ NULL, NULL },
+ { RPCBPROC_SET, "SET",
+ NULL, NULL },
+ { RPCBPROC_UNSET, "UNSET",
+ NULL, NULL },
+ { RPCBPROC_GETADDR, "GETADDR",
+ dissect_rpcb3_getaddr_call, dissect_rpcb3_getaddr_reply},
+ { RPCBPROC_DUMP, "DUMP",
+ NULL, dissect_rpcb3_dump_reply },
+ { RPCBPROC_CALLIT, "CALLIT",
+ dissect_callit_call, dissect_rpcb_rmtcallres },
+ { RPCBPROC_GETTIME, "GETTIME",
+ NULL, NULL },
+ { RPCBPROC_UADDR2TADDR, "UADDR2TADDR",
+ NULL, NULL },
+ { RPCBPROC_TADDR2UADDR, "TADDR2UADDR",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string portmap3_proc_vals[] = {
+ { RPCBPROC_NULL, "NULL" },
+ { RPCBPROC_SET, "SET" },
+ { RPCBPROC_UNSET, "UNSET" },
+ { RPCBPROC_GETADDR, "GETADDR" },
+ { RPCBPROC_DUMP, "DUMP" },
+ { RPCBPROC_CALLIT, "CALLIT" },
+ { RPCBPROC_GETTIME, "GETTIME" },
+ { RPCBPROC_UADDR2TADDR, "UADDR2TADDR" },
+ { RPCBPROC_TADDR2UADDR, "TADDR2UADDR" },
+ { 0, NULL }
+};
+/* end of Portmap version 3 */
+
+
+/* Portmapper version 4, RFC 1833, Page 8 */
+static const vsff portmap4_proc[] = {
+ { RPCBPROC_NULL, "NULL",
+ NULL, NULL },
+ { RPCBPROC_SET, "SET",
+ NULL, NULL },
+ { RPCBPROC_UNSET, "UNSET",
+ NULL, NULL },
+ { RPCBPROC_GETADDR, "GETADDR",
+ dissect_rpcb3_getaddr_call, dissect_rpcb3_getaddr_reply},
+ { RPCBPROC_DUMP, "DUMP",
+ NULL, dissect_rpcb3_dump_reply },
+ { RPCBPROC_BCAST, "BCAST",
+ dissect_callit_call, dissect_rpcb_rmtcallres },
+ { RPCBPROC_GETTIME, "GETTIME",
+ NULL, NULL },
+ { RPCBPROC_UADDR2TADDR, "UADDR2TADDR",
+ NULL, NULL },
+ { RPCBPROC_TADDR2UADDR, "TADDR2UADDR",
+ NULL, NULL },
+ { RPCBPROC_GETVERSADDR, "GETVERSADDR",
+ NULL, NULL },
+ { RPCBPROC_INDIRECT, "INDIRECT",
+ dissect_callit_call, dissect_rpcb_rmtcallres },
+ { RPCBPROC_GETADDRLIST, "GETADDRLIST",
+ NULL, NULL },
+ { RPCBPROC_GETSTAT, "GETSTAT",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string portmap4_proc_vals[] = {
+ { RPCBPROC_NULL, "NULL" },
+ { RPCBPROC_SET, "SET" },
+ { RPCBPROC_UNSET, "UNSET" },
+ { RPCBPROC_GETADDR, "GETADDR" },
+ { RPCBPROC_DUMP, "DUMP" },
+ { RPCBPROC_BCAST, "BCAST" },
+ { RPCBPROC_GETTIME, "GETTIME" },
+ { RPCBPROC_UADDR2TADDR, "UADDR2TADDR" },
+ { RPCBPROC_TADDR2UADDR, "TADDR2UADDR" },
+ { RPCBPROC_GETVERSADDR, "GETVERSADDR" },
+ { RPCBPROC_INDIRECT, "INDIRECT" },
+ { RPCBPROC_GETADDRLIST, "GETADDRLIST" },
+ { RPCBPROC_GETSTAT, "GETSTAT" },
+ { 0, NULL }
+};
+/* end of Portmap version 4 */
+
+void
+proto_register_portmap(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_portmap_procedure_v1, {
+ "V1 Procedure", "portmap.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(portmap1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_portmap_procedure_v2, {
+ "V2 Procedure", "portmap.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(portmap2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_portmap_procedure_v3, {
+ "V3 Procedure", "portmap.procedure_v3", FT_UINT32, BASE_DEC,
+ VALS(portmap3_proc_vals), 0, "V3 Procedure", HFILL }},
+ { &hf_portmap_procedure_v4, {
+ "V4 Procedure", "portmap.procedure_v4", FT_UINT32, BASE_DEC,
+ VALS(portmap4_proc_vals), 0, "V4 Procedure", HFILL }},
+ { &hf_portmap_prog, {
+ "Program", "portmap.prog", FT_UINT32, BASE_DEC,
+ NULL, 0, "Program", HFILL }},
+ { &hf_portmap_port, {
+ "Port", "portmap.port", FT_UINT32, BASE_DEC,
+ NULL, 0, "Port", HFILL }},
+ { &hf_portmap_proc, {
+ "Procedure", "portmap.proc", FT_UINT32, BASE_DEC,
+ NULL, 0, "Procedure", HFILL }},
+ { &hf_portmap_proto, {
+ "Protocol", "portmap.proto", FT_UINT32, BASE_DEC,
+ NULL, 0, "Protocol", HFILL }},
+ { &hf_portmap_version, {
+ "Version", "portmap.version", FT_UINT32, BASE_DEC,
+ NULL, 0, "Version", HFILL }},
+ { &hf_portmap_answer, {
+ "Answer", "portmap.answer", FT_BOOLEAN, BASE_DEC,
+ NULL, 0, "Answer", HFILL }},
+ { &hf_portmap_args, {
+ "Arguments", "portmap.args", FT_BYTES, BASE_HEX,
+ NULL, 0, "Arguments", HFILL }},
+ { &hf_portmap_result, {
+ "Result", "portmap.result", FT_BYTES, BASE_HEX,
+ NULL, 0, "Result", HFILL }},
+ { &hf_portmap_rpcb, {
+ "RPCB", "portmap.rpcb", FT_NONE, 0,
+ NULL, 0, "RPCB", HFILL }},
+ { &hf_portmap_rpcb_prog, {
+ "Program", "portmap.rpcb.prog", FT_UINT32, BASE_DEC,
+ NULL, 0, "Program", HFILL }},
+ { &hf_portmap_rpcb_version, {
+ "Version", "portmap.rpcb.version", FT_UINT32, BASE_DEC,
+ NULL, 0, "Version", HFILL }},
+ { &hf_portmap_rpcb_netid, {
+ "Network Id", "portmap.rpcb.netid", FT_STRING, BASE_DEC,
+ NULL, 0, "Network Id", HFILL }},
+ { &hf_portmap_rpcb_addr, { /* address in rpcb structure in request */
+ "Universal Address", "portmap.rpcb.addr", FT_STRING, BASE_DEC,
+ NULL, 0, "Universal Address", HFILL }},
+ { &hf_portmap_rpcb_owner, {
+ "Owner of this Service", "portmap.rpcb.owner", FT_STRING, BASE_DEC,
+ NULL, 0, "Owner of this Service", HFILL }},
+ { &hf_portmap_uaddr, { /* address in RPCBPROC_GETADDR reply */
+ "Universal Address", "portmap.uaddr", FT_STRING, BASE_DEC,
+ NULL, 0, "Universal Address", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_portmap,
+ &ett_portmap_rpcb,
+ &ett_portmap_entry
+ };
+
+ proto_portmap = proto_register_protocol("Portmap", "Portmap", "portmap");
+ proto_register_field_array(proto_portmap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_portmap(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_portmap, PORTMAP_PROGRAM, ett_portmap);
+ /* Register the procedure tables */
+ rpc_init_proc_table(PORTMAP_PROGRAM, 1, portmap1_proc, hf_portmap_procedure_v1);
+ rpc_init_proc_table(PORTMAP_PROGRAM, 2, portmap2_proc, hf_portmap_procedure_v2);
+ rpc_init_proc_table(PORTMAP_PROGRAM, 3, portmap3_proc, hf_portmap_procedure_v3);
+ rpc_init_proc_table(PORTMAP_PROGRAM, 4, portmap4_proc, hf_portmap_procedure_v4);
+ rpc_handle = find_dissector("rpc");
+ rpc_tcp_handle = find_dissector("rpc-tcp");
+}
diff --git a/epan/dissectors/packet-portmap.h b/epan/dissectors/packet-portmap.h
new file mode 100644
index 0000000000..695bad532c
--- /dev/null
+++ b/epan/dissectors/packet-portmap.h
@@ -0,0 +1,62 @@
+/* packet-portmap.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_PORTMAP_H
+#define PACKET_PORTMAP_H
+
+#define PORTMAP_PROGRAM 100000
+
+#define PORTMAPPROC_NULL 0
+#define PORTMAPPROC_SET 1
+#define PORTMAPPROC_UNSET 2
+#define PORTMAPPROC_GETPORT 3
+#define PORTMAPPROC_DUMP 4
+#define PORTMAPPROC_CALLIT 5
+
+/* RFC 1833, Page 7 */
+#define RPCBPROC_NULL 0
+#define RPCBPROC_SET 1
+#define RPCBPROC_UNSET 2
+#define RPCBPROC_GETADDR 3
+#define RPCBPROC_DUMP 4
+#define RPCBPROC_CALLIT 5
+#define RPCBPROC_GETTIME 6
+#define RPCBPROC_UADDR2TADDR 7
+#define RPCBPROC_TADDR2UADDR 8
+
+/* RFC 1833, Page 8 */
+#define RPCBPROC_BCAST RPCBPROC_CALLIT
+#define RPCBPROC_GETVERSADDR 9
+#define RPCBPROC_INDIRECT 10
+#define RPCBPROC_GETADDRLIST 11
+#define RPCBPROC_GETSTAT 12
+
+struct pmap {
+ guint32 pm_prog;
+ guint32 pm_vers;
+ guint32 pm_prot;
+ guint32 pm_port;
+};
+
+#endif
diff --git a/epan/dissectors/packet-postgresql.c b/epan/dissectors/packet-postgresql.c
new file mode 100644
index 0000000000..651ba1fb8f
--- /dev/null
+++ b/epan/dissectors/packet-postgresql.c
@@ -0,0 +1,221 @@
+/* packet-postgresql.c
+ * Routines for postgresql packet disassembly
+ *
+ * Copyright 2004, Edwin Calo <calo@fusemail.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+static int proto_postgresql = -1;
+static int hf_postgresql_response = -1;
+static int hf_postgresql_request = -1;
+static int hf_postgresql_length = -1;
+static int hf_postgresql_string_size = -1;
+static int hf_postgresql_string = -1;
+static int hf_postgresql_total_length = -1;
+static int hf_postgresql_bitone = -1;
+static int hf_postgresql_buff_remaining = -1;
+static int hf_postgresql_opcode = -1;
+static int hf_postgresql_idone = -1;
+static gint ett_postgresql = -1;
+
+#define TCP_PORT_POSTGRESQL 5432
+
+/*
+ * For a protocol description, see:
+ *
+ * http://www.postgresql.org/docs/7.4/interactive/protocol.html
+ *
+ * for version 3.0 of the protocol and
+ *
+ * http://www.postgresql.org/docs/7.3/interactive/protocol.html
+ *
+ * for version 2.0 of the protocol and
+ *
+ * http://www.postgresql.org/docs/6.3/interactive/c50.htm
+ *
+ * for version 1.0 of the protocol.
+ *
+ * It looks like there are two types of PDUs: Old style and new style.
+ * New style PDUs start with a Length guint32, where the high byte is
+ * equal to 0. Old style PDUs start with a single Byte (different from 0)
+ * that contains the type of the PDU.
+ *
+ * The specific types can be found at:
+ * http://www.postgresql.org/docs/7.4/interactive/protocol-message-formats.html
+ *
+ */
+
+static void
+dissect_postgresql (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ proto_tree *postgresql_tree;
+ proto_item *ti;
+ gint offset = 0;
+ gint buff_remaining = 0;
+
+ guint8 *string;
+ guint8 bitone;
+ gint flag = 0;
+ gint counter = 0;
+
+
+
+
+ if (check_col (pinfo->cinfo, COL_PROTOCOL))
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "POSTGRESQL");
+
+ ti = proto_tree_add_item (tree, proto_postgresql, tvb, offset, -1, FALSE);
+ postgresql_tree = proto_item_add_subtree (ti, ett_postgresql);
+
+ buff_remaining = tvb_length_remaining (tvb, offset);
+
+ if (check_col (pinfo->cinfo, COL_INFO))
+ {
+ col_add_str (pinfo->cinfo, COL_INFO,
+ (pinfo->match_port ==
+ pinfo->destport) ? " Request" : " Response");
+ }
+
+ counter=0;
+ flag=0;
+ while ( buff_remaining >= 1 )
+ {
+ bitone = tvb_get_guint8 (tvb, offset);
+ offset += 1;
+
+ if(bitone > 0x7f || (bitone > 0x0 && bitone < 0x20) )
+ {
+ if(counter > 3)
+ {
+ if(offset > counter)
+ {
+ offset -= counter+1;
+
+ /* Reading the string from the packet */
+ string = tvb_get_string(tvb,offset,counter);
+ /* Printing the data */
+ proto_tree_add_string (postgresql_tree,hf_postgresql_string,tvb, offset,counter, string );
+ if (check_col (pinfo->cinfo, COL_INFO)) { col_append_fstr (pinfo->cinfo, COL_INFO, " %s", string ); }
+ g_free(string); /* Freeing up string */
+ string=NULL;
+
+ offset += counter+1;
+ counter=0;
+ }
+ else
+ {
+ counter=0;
+ offset+=1;
+ }
+ }
+ else
+ {
+ counter=0;
+ offset+=1;
+ }
+ }
+
+ if( bitone == 0 )
+ {
+ if(counter != 0)
+ {
+ if(offset > counter)
+ {
+ offset -= counter+1;
+ if( counter > 1)
+ {
+ /* Reading the string from the packet */
+ string = tvb_get_string(tvb,offset,counter);
+ /* Printing the data */
+ proto_tree_add_string (postgresql_tree,hf_postgresql_string,tvb, offset,counter, string );
+ if (check_col (pinfo->cinfo, COL_INFO)) { col_append_fstr (pinfo->cinfo, COL_INFO, " %s", string ); }
+ g_free(string); /* Freeing up string */
+ string=NULL;
+
+ }
+ offset += counter+1;
+ }
+ counter = 0;
+ }
+ counter=0;
+ }
+ else
+ {
+ counter += 1;
+ }
+
+ buff_remaining = tvb_length_remaining (tvb, offset);
+ }
+}
+
+
+void proto_register_postgresql (void)
+{
+
+ static hf_register_info hf[] = {
+ {&hf_postgresql_response,
+ {"Response", "postgresql.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if postgresql response", HFILL}},
+ {&hf_postgresql_request,
+ {"Request", "postgresql.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if postgresql request", HFILL}},
+ {&hf_postgresql_string, {"String", "hf_postgresql_string", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL}},
+ {&hf_postgresql_length, {"Length", "hf_postgresql_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_postgresql_string_size, {"Size", "hf_postgresql_string_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_postgresql_total_length, {"TotalLength", "hf_postgresql_total_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_postgresql_buff_remaining, {"Buffer Remaining", "hf_postgresql_buff_remaining", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL}},
+ {&hf_postgresql_opcode, {"Op Code", "hf_postgresql_opcode", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_postgresql_bitone, {"Bitone", "hf_postgresql_bitone", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
+ {&hf_postgresql_idone, {"idone", "hf_postgresql_idone", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
+
+
+
+ };
+
+ static gint *ett[] = {
+ &ett_postgresql,
+ };
+
+ proto_postgresql =
+ proto_register_protocol ("POSTGRESQL", "POSTGRESQL", "postgresql");
+ proto_register_field_array (proto_postgresql, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_postgresql (void)
+{
+ dissector_handle_t postgresql_handle;
+
+ postgresql_handle =
+ create_dissector_handle (dissect_postgresql, proto_postgresql);
+ dissector_add ("tcp.port", TCP_PORT_POSTGRESQL, postgresql_handle);
+}
diff --git a/epan/dissectors/packet-ppp.c b/epan/dissectors/packet-ppp.c
new file mode 100644
index 0000000000..66962677a8
--- /dev/null
+++ b/epan/dissectors/packet-ppp.c
@@ -0,0 +1,3767 @@
+/* packet-ppp.c
+ * Routines for ppp packet disassembly
+ * RFC 1661, RFC 1662
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ *
+ * This file created and by Mike Hall <mlh@io.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include "prefs.h"
+#include <epan/packet.h>
+#include "packet-ppp.h"
+#include "ppptypes.h"
+#include "etypes.h"
+#include "ip_opts.h"
+#include <epan/atalk-utils.h>
+#include "packet-chdlc.h"
+#include "packet-ip.h"
+#include "packet-ipx.h"
+#include "packet-vines.h"
+#include "nlpid.h"
+#include "crc16.h"
+#include "crc32.h"
+
+#define ppp_min(a, b) ((a<b) ? a : b)
+
+static int proto_ppp = -1;
+static int hf_ppp_address = -1;
+static int hf_ppp_control = -1;
+static int hf_ppp_protocol = -1;
+
+static gint ett_ppp = -1;
+
+static int proto_lcp = -1;
+
+static gint ett_lcp = -1;
+static gint ett_lcp_options = -1;
+static gint ett_lcp_authprot_opt = -1;
+static gint ett_lcp_qualprot_opt = -1;
+static gint ett_lcp_fcs_alternatives_opt = -1;
+static gint ett_lcp_numbered_mode_opt = -1;
+static gint ett_lcp_callback_opt = -1;
+static gint ett_lcp_multilink_ep_disc_opt = -1;
+static gint ett_lcp_internationalization_opt = -1;
+
+static int proto_ipcp = -1;
+
+static gint ett_ipcp = -1;
+static gint ett_ipcp_options = -1;
+static gint ett_ipcp_ipaddrs_opt = -1;
+static gint ett_ipcp_compressprot_opt = -1;
+
+static int proto_osicp = -1;
+
+static gint ett_osicp = -1;
+static gint ett_osicp_options = -1;
+static gint ett_osicp_align_npdu_opt = -1;
+
+static int proto_ccp = -1;
+
+static gint ett_ccp = -1;
+static gint ett_ccp_options = -1;
+static gint ett_ccp_stac_opt = -1;
+static gint ett_ccp_mppc_opt = -1;
+static gint ett_ccp_bsdcomp_opt = -1;
+static gint ett_ccp_lzsdcp_opt = -1;
+static gint ett_ccp_mvrca_opt = -1;
+static gint ett_ccp_deflate_opt = -1;
+
+static int proto_cbcp = -1;
+
+static gint ett_cbcp = -1;
+static gint ett_cbcp_options = -1;
+static gint ett_cbcp_callback_opt = -1;
+static gint ett_cbcp_callback_opt_addr = -1;
+
+static int proto_bacp = -1;
+
+static gint ett_bacp = -1;
+static gint ett_bacp_options = -1;
+static gint ett_bacp_favored_peer_opt = -1;
+
+static int proto_bap = -1;
+
+static gint ett_bap = -1;
+static gint ett_bap_options = -1;
+static gint ett_bap_link_type_opt = -1;
+static gint ett_bap_phone_delta_opt = -1;
+static gint ett_bap_phone_delta_subopt = -1;
+static gint ett_bap_call_status_opt = -1;
+
+static int proto_comp_data = -1;
+
+static gint ett_comp_data = -1;
+
+static int proto_pppmuxcp = -1;
+
+static gint ett_pppmuxcp = -1;
+static gint ett_pppmuxcp_options = -1;
+
+static int proto_pppmux = -1;
+
+static gint ett_pppmux = -1;
+static gint ett_pppmux_subframe = -1;
+static gint ett_pppmux_subframe_hdr = -1;
+static gint ett_pppmux_subframe_flags = -1;
+static gint ett_pppmux_subframe_info = -1;
+
+static int proto_mp = -1;
+static int hf_mp_frag_first = -1;
+static int hf_mp_frag_last = -1;
+static int hf_mp_sequence_num = -1;
+
+static int ett_mp = -1;
+static int ett_mp_flags = -1;
+
+static int proto_mplscp = -1;
+static gint ett_mplscp = -1;
+static gint ett_mplscp_options = -1;
+
+static int proto_cdpcp = -1;
+static gint ett_cdpcp = -1;
+static gint ett_cdpcp_options = -1;
+
+static int proto_pap = -1; /* PAP vars */
+static gint ett_pap = -1;
+static gint ett_pap_data = -1;
+static gint ett_pap_peer_id = -1;
+static gint ett_pap_password = -1;
+static gint ett_pap_message = -1;
+
+static int proto_chap = -1; /* CHAP vars */
+static gint ett_chap = -1;
+static gint ett_chap_data = -1;
+static gint ett_chap_value = -1;
+static gint ett_chap_name = -1;
+static gint ett_chap_message = -1;
+
+static int proto_ipv6cp = -1; /* IPv6CP vars */
+
+static gint ett_ipv6cp = -1;
+static gint ett_ipv6cp_options = -1;
+static gint ett_ipv6cp_if_id_opt = -1;
+static gint ett_ipv6cp_compressprot_opt = -1;
+
+static dissector_table_t ppp_subdissector_table;
+static dissector_handle_t chdlc_handle;
+static dissector_handle_t data_handle;
+
+/* options */
+static gint ppp_fcs_decode = 0; /* 0 = No FCS, 1 = 16 bit FCS, 2 = 32 bit FCS */
+#define NO_FCS 0
+#define FCS_16 1
+#define FCS_32 2
+
+const enum_val_t fcs_options[] = {
+ {"none", "None", NO_FCS},
+ {"16-bit", "16-Bit", FCS_16},
+ {"32-bit", "32-Bit", FCS_32},
+ {NULL, NULL, -1}
+};
+
+gboolean ppp_vj_decomp = TRUE; /* Default to VJ header decompression */
+
+/*
+ * For Default Protocol ID negotiated with PPPMuxCP. We need to
+ * this ID so that if the first subframe doesn't have protocol
+ * ID, we can use it
+ */
+
+static guint pppmux_def_prot_id = 0;
+
+/* PPP definitions */
+
+/*
+ * Used by the GTP dissector as well.
+ */
+const value_string ppp_vals[] = {
+ {PPP_PADDING, "Padding Protocol" },
+ {PPP_ROHC_SCID, "ROHC small-CID" },
+ {PPP_ROHC_LCID, "ROHC large-CID" },
+ {PPP_IP, "IP" },
+ {PPP_OSI, "OSI" },
+ {PPP_DEC4, "DECnet Phase IV" },
+ {PPP_AT, "Appletalk" },
+ {PPP_IPX, "Netware IPX/SPX"},
+ {PPP_VJC_COMP, "VJ compressed TCP"},
+ {PPP_VJC_UNCOMP,"VJ uncompressed TCP"},
+ {PPP_BPDU, "Bridging PDU"},
+ {PPP_ST, "Stream Protocol (ST-II)" },
+ {PPP_VINES, "Vines" },
+ {PPP_AT_EDDP, "AppleTalk EDDP" },
+ {PPP_AT_SB, "AppleTalk SmartBuffered" },
+ {PPP_MP, "Multilink"},
+ {PPP_NB, "NETBIOS Framing" },
+ {PPP_CISCO, "Cisco Systems" },
+ {PPP_ASCOM, "Ascom Timeplex" },
+ {PPP_LBLB, "Fujitsu Link Backup and Load Balancing" },
+ {PPP_RL, "DCA Remote Lan" },
+ {PPP_SDTP, "Serial Data Transport Protocol" },
+ {PPP_LLC, "SNA over LLC" },
+ {PPP_SNA, "SNA" },
+ {PPP_IPV6HC, "IPv6 Header Compression " },
+ {PPP_KNX, "KNX Bridging Data" },
+ {PPP_ENCRYPT, "Encryption" },
+ {PPP_ILE, "Individual Link Encryption" },
+ {PPP_IPV6, "IPv6" },
+ {PPP_MUX, "PPP Multiplexing"},
+ {PPP_RTP_FH, "RTP IPHC Full Header" },
+ {PPP_RTP_CTCP, "RTP IPHC Compressed TCP" },
+ {PPP_RTP_CNTCP, "RTP IPHC Compressed Non TCP" },
+ {PPP_RTP_CUDP8, "RTP IPHC Compressed UDP 8" },
+ {PPP_RTP_CRTP8, "RTP IPHC Compressed RTP 8" },
+ {PPP_STAMPEDE, "Stampede Bridging" },
+ {PPP_MPPLUS, "MP+ Protocol" },
+ {PPP_NTCITS_IPI,"NTCITS IPI" },
+ {PPP_ML_SLCOMP, "single link compression in multilink" },
+ {PPP_COMP, "compressed packet" },
+ {PPP_STP_HELLO, "802.1d Hello Packet" },
+ {PPP_IBM_SR, "IBM Source Routing BPDU" },
+ {PPP_DEC_LB, "DEC LANBridge100 Spanning Tree"},
+ {PPP_CDP, "Cisco Discovery Protocol" },
+ {PPP_NETCS, "Netcs Twin Routing" },
+ {PPP_STP, "Scheduled Transfer Protocol" },
+ {PPP_EDP, "Extreme Discovery Protocol" },
+ {PPP_OSCP, "Optical Supervisory Channel Protocol" },
+ {PPP_OSCP2, "Optical Supervisory Channel Protocol" },
+ {PPP_LUXCOM, "Luxcom" },
+ {PPP_SIGMA, "Sigma Network Systems" },
+ {PPP_ACSP, "Apple Client Server Protocol" },
+ {PPP_MPLS_UNI, "MPLS Unicast"},
+ {PPP_MPLS_MULTI, "MPLS Multicast"},
+ {PPP_P12844, "IEEE p1284.4 standard - data packets" },
+ {PPP_ETSI, "ETSI TETRA Networks Procotol Type 1" },
+ {PPP_MFTP, "Multichannel Flow Treatment Protocol" },
+ {PPP_RTP_CTCPND,"RTP IPHC Compressed TCP No Delta" },
+ {PPP_RTP_CS, "RTP IPHC Context State" },
+ {PPP_RTP_CUDP16,"RTP IPHC Compressed UDP 16" },
+ {PPP_RTP_CRDP16,"RTP IPHC Compressed RTP 16" },
+ {PPP_CCCP, "Cray Communications Control Protocol" },
+ {PPP_CDPD_MNRP, "CDPD Mobile Network Registration Protocol" },
+ {PPP_EXPANDAP, "Expand accelarator protocol" },
+ {PPP_ODSICP, "ODSICP NCP" },
+ {PPP_DOCSIS, "DOCSIS DLL" },
+ {PPP_LZS, "Stacker LZS" },
+ {PPP_REFTEK, "RefTek Protocol" },
+ {PPP_FC, "Fibre Channel" },
+ {PPP_EMIT, "EMIT Protocols" },
+ {PPP_IPCP, "IP Control Protocol" },
+ {PPP_OSICP, "OSI Control Protocol" },
+ {PPP_XNSIDPCP, "Xerox NS IDP Control Protocol" },
+ {PPP_DECNETCP, "DECnet Phase IV Control Protocol" },
+ {PPP_ATCP, "AppleTalk Control Protocol" },
+ {PPP_IPXCP, "IPX Control Protocol" },
+ {PPP_BRIDGENCP, "Bridging NCP" },
+ {PPP_SPCP, "Stream Protocol Control Protocol" },
+ {PPP_BVCP, "Banyan Vines Control Protocol" },
+ {PPP_MLCP, "Multi-Link Control Protocol" },
+ {PPP_NBCP, "NETBIOS Framing Control Protocol" },
+ {PPP_CISCOCP, "Cisco Systems Control Protocol" },
+ {PPP_ASCOMCP, "Ascom Timeplex" },
+ {PPP_LBLBCP, "Fujitsu LBLB Control Protocol" },
+ {PPP_RLNCP, "DCA Remote Lan Network Control Protocol" },
+ {PPP_SDCP, "Serial Data Control Protocol" },
+ {PPP_LLCCP, "SNA over LLC Control Protocol" },
+ {PPP_SNACP, "SNA Control Protocol" },
+ {PPP_KNXCP, "KNX Bridging Control Protocol" },
+ {PPP_ECP, "Encryption Control Protocol" },
+ {PPP_ILECP, "Individual Encryption Control Protocol" },
+ {PPP_IPV6CP, "IPv6 Control Protocol" },
+ {PPP_MUXCP, "PPPMux Control Protocol"},
+ {PPP_STAMPEDECP,"Stampede Bridging Control Protocol" },
+ {PPP_MPPCP, "MP+ Contorol Protocol" },
+ {PPP_IPICP, "NTCITS IPI Control Protocol" },
+ {PPP_SLCC, "single link compression in multilink control" },
+ {PPP_CCP, "Compression Control Protocol" },
+ {PPP_CDPCP, "CDP Control Protocol" },
+ {PPP_NETCSCP, "Netcs Twin Routing" },
+ {PPP_STPCP, "STP - Control Protocol" },
+ {PPP_EDPCP, "EDP Control Protocol" },
+ {PPP_ACSPC, "Apple Client Server Protocol Control" },
+ {PPP_MPLSCP, "MPLS Control Protocol" },
+ {PPP_P12844CP, "IEEE p1284.4 standard - Protocol Control" },
+ {PPP_ETSICP, "ETSI TETRA TNP1 Control Protocol" },
+ {PPP_MFTPCP, "Multichannel Flow Treatment Protocol" },
+ {PPP_LCP, "Link Control Protocol" },
+ {PPP_PAP, "Password Authentication Protocol" },
+ {PPP_LQR, "Link Quality Report protocol" },
+ {PPP_SPAP, "Shiva Password Authentication Protocol" },
+ {PPP_CBCP, "Callback Control Protocol" },
+ {PPP_BACP, "Bandwidth Allocation Control Protocol" },
+ {PPP_BAP, "Bandwidth Allocation Protocol" },
+ {PPP_CONTCP, "Container Control Protocol" },
+ {PPP_CHAP, "Challenge Handshake Authentication Protocol" },
+ {PPP_RSAAP, "RSA Authentication Protocol" },
+ {PPP_EAP, "Extensible Authentication Protocol" },
+ {PPP_SIEP, "Mitsubishi Security Information Exchange Protocol"},
+ {PPP_SBAP, "Stampede Bridging Authorization Protocol" },
+ {PPP_PRPAP, "Proprietary Authentication Protocol" },
+ {PPP_PRPAP2, "Proprietary Authentication Protocol" },
+ {PPP_PRPNIAP, "Proprietary Node ID Authentication Protocol" },
+ {0, NULL }
+};
+
+/* CP (LCP, IPCP, etc.) codes.
+ * from pppd fsm.h
+ */
+#define CONFREQ 1 /* Configuration Request */
+#define CONFACK 2 /* Configuration Ack */
+#define CONFNAK 3 /* Configuration Nak */
+#define CONFREJ 4 /* Configuration Reject */
+#define TERMREQ 5 /* Termination Request */
+#define TERMACK 6 /* Termination Ack */
+#define CODEREJ 7 /* Code Reject */
+
+static const value_string cp_vals[] = {
+ {CONFREQ, "Configuration Request" },
+ {CONFACK, "Configuration Ack" },
+ {CONFNAK, "Configuration Nak" },
+ {CONFREJ, "Configuration Reject" },
+ {TERMREQ, "Termination Request" },
+ {TERMACK, "Termination Ack" },
+ {CODEREJ, "Code Reject" },
+ {0, NULL } };
+
+/*
+ * LCP-specific packet types.
+ */
+#define PROTREJ 8 /* Protocol Reject */
+#define ECHOREQ 9 /* Echo Request */
+#define ECHOREP 10 /* Echo Reply */
+#define DISCREQ 11 /* Discard Request */
+#define IDENT 12 /* Identification */
+#define TIMEREMAIN 13 /* Time remaining */
+
+/*
+ * CCP-specific packet types.
+ */
+#define RESETREQ 14 /* Reset Request */
+#define RESETACK 15 /* Reset Ack */
+
+/*
+ * CBCP-specific packet types.
+ */
+#define CBREQ 1 /* Callback Request */
+#define CBRES 2 /* Callback Response */
+#define CBACK 3 /* Callback Ack */
+
+#define CBCP_OPT 6 /* Use callback control protocol */
+
+/*
+ * BAP-specific packet types.
+ */
+#define BAP_CREQ 1 /* Call Request */
+#define BAP_CRES 2 /* Call Response */
+#define BAP_CBREQ 3 /* Callback Request */
+#define BAP_CBRES 4 /* Callback Response */
+#define BAP_LDQREQ 5 /* Link Drop Query Request */
+#define BAP_LDQRES 6 /* Link Drop Query Response */
+#define BAP_CSI 7 /* Call Status Indication */
+#define BAP_CSRES 8 /* Call Status Response */
+
+static const value_string lcp_vals[] = {
+ {CONFREQ, "Configuration Request" },
+ {CONFACK, "Configuration Ack" },
+ {CONFNAK, "Configuration Nak" },
+ {CONFREJ, "Configuration Reject" },
+ {TERMREQ, "Termination Request" },
+ {TERMACK, "Termination Ack" },
+ {CODEREJ, "Code Reject" },
+ {PROTREJ, "Protocol Reject" },
+ {ECHOREQ, "Echo Request" },
+ {ECHOREP, "Echo Reply" },
+ {DISCREQ, "Discard Request" },
+ {IDENT, "Identification" },
+ {TIMEREMAIN, "Time Remaining" },
+ {0, NULL }
+};
+
+static const value_string ccp_vals[] = {
+ {CONFREQ, "Configuration Request" },
+ {CONFACK, "Configuration Ack" },
+ {CONFNAK, "Configuration Nak" },
+ {CONFREJ, "Configuration Reject" },
+ {TERMREQ, "Termination Request" },
+ {TERMACK, "Termination Ack" },
+ {CODEREJ, "Code Reject" },
+ {RESETREQ, "Reset Request" },
+ {RESETACK, "Reset Ack" },
+ {0, NULL }
+};
+
+static const value_string cbcp_vals[] = {
+ {CBREQ, "Callback Request" },
+ {CBRES, "Callback Response" },
+ {CBACK, "Callback Ack" },
+ {0, NULL }
+};
+
+static const value_string bap_vals[] = {
+ {BAP_CREQ, "Call Request" },
+ {BAP_CRES, "Call Response" },
+ {BAP_CBREQ, "Callback Request" },
+ {BAP_CBRES, "Callback Response" },
+ {BAP_LDQREQ, "Link Drop Query Request" },
+ {BAP_LDQRES, "Link Drop Query Response" },
+ {BAP_CSI, "Call Status Indication" },
+ {BAP_CSRES, "Call Status Response" },
+ {0, NULL }
+};
+
+#define BAP_RESP_CODE_REQACK 0x00
+#define BAP_RESP_CODE_REQNAK 0x01
+#define BAP_RESP_CODE_REQREJ 0x02
+#define BAP_RESP_CODE_REQFULLNAK 0x03
+static const value_string bap_resp_code_vals[] = {
+ {BAP_RESP_CODE_REQACK, "Request Ack" },
+ {BAP_RESP_CODE_REQNAK, "Request Nak" },
+ {BAP_RESP_CODE_REQREJ, "Request Rej" },
+ {BAP_RESP_CODE_REQFULLNAK, "Request Full Nak" },
+ {0, NULL }
+};
+
+#define BAP_LINK_TYPE_ISDN 0 /* ISDN */
+#define BAP_LINK_TYPE_X25 1 /* X.25 */
+#define BAP_LINK_TYPE_ANALOG 2 /* Analog */
+#define BAP_LINK_TYPE_SD 3 /* Switched Digital (non-ISDN) */
+#define BAP_LINK_TYPE_ISDNOV 4 /* ISDN data over voice */
+#define BAP_LINK_TYPE_RESV5 5 /* Reserved */
+#define BAP_LINK_TYPE_RESV6 6 /* Reserved */
+#define BAP_LINK_TYPE_RESV7 7 /* Reserved */
+static const value_string bap_link_type_vals[] = {
+ {BAP_LINK_TYPE_ISDN, "ISDN" },
+ {BAP_LINK_TYPE_X25, "X.25" },
+ {BAP_LINK_TYPE_ANALOG, "Analog" },
+ {BAP_LINK_TYPE_SD, "Switched Digital (non-ISDN)" },
+ {BAP_LINK_TYPE_ISDNOV, "ISDN data over voice" },
+ {BAP_LINK_TYPE_RESV5, "Reserved" },
+ {BAP_LINK_TYPE_RESV6, "Reserved" },
+ {BAP_LINK_TYPE_RESV7, "Reserved" },
+ {0, NULL }
+};
+
+#define BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT 1 /* Unique Digit */
+#define BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM 2 /* Subscriber Number */
+#define BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR 3 /* Phone Number Sub Address */
+static const value_string bap_phone_delta_subopt_vals[] = {
+ {BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT, "Unique Digit" },
+ {BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM, "Subscriber Number" },
+ {BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR, "Phone Number Sub Address" },
+ {0, NULL }
+};
+
+/*
+ * Cause codes for Cause.
+ *
+ * The following code table is taken from packet-q931.c but is slightly
+ * adapted to BAP protocol.
+ */
+static const value_string q931_cause_code_vals[] = {
+ { 0x00, "Call successful" },
+ { 0x01, "Unallocated (unassigned) number" },
+ { 0x02, "No route to specified transit network" },
+ { 0x03, "No route to destination" },
+ { 0x04, "Send special information tone" },
+ { 0x05, "Misdialled trunk prefix" },
+ { 0x06, "Channel unacceptable" },
+ { 0x07, "Call awarded and being delivered in an established channel" },
+ { 0x08, "Prefix 0 dialed but not allowed" },
+ { 0x09, "Prefix 1 dialed but not allowed" },
+ { 0x0A, "Prefix 1 dialed but not required" },
+ { 0x0B, "More digits received than allowed, call is proceeding" },
+ { 0x10, "Normal call clearing" },
+ { 0x11, "User busy" },
+ { 0x12, "No user responding" },
+ { 0x13, "No answer from user (user alerted)" },
+ { 0x14, "Subscriber absent" },
+ { 0x15, "Call rejected" },
+ { 0x16, "Number changed" },
+ { 0x17, "Reverse charging rejected" },
+ { 0x18, "Call suspended" },
+ { 0x19, "Call resumed" },
+ { 0x1A, "Non-selected user clearing" },
+ { 0x1B, "Destination out of order" },
+ { 0x1C, "Invalid number format (incomplete number)" },
+ { 0x1D, "Facility rejected" },
+ { 0x1E, "Response to STATUS ENQUIRY" },
+ { 0x1F, "Normal unspecified" },
+ { 0x21, "Circuit out of order" },
+ { 0x22, "No circuit/channel available" },
+ { 0x23, "Destination unattainable" },
+ { 0x25, "Degraded service" },
+ { 0x26, "Network out of order" },
+ { 0x27, "Transit delay range cannot be achieved" },
+ { 0x28, "Throughput range cannot be achieved" },
+ { 0x29, "Temporary failure" },
+ { 0x2A, "Switching equipment congestion" },
+ { 0x2B, "Access information discarded" },
+ { 0x2C, "Requested circuit/channel not available" },
+ { 0x2D, "Pre-empted" },
+ { 0x2E, "Precedence call blocked" },
+ { 0x2F, "Resources unavailable, unspecified" },
+ { 0x31, "Quality of service unavailable" },
+ { 0x32, "Requested facility not subscribed" },
+ { 0x33, "Reverse charging not allowed" },
+ { 0x34, "Outgoing calls barred" },
+ { 0x35, "Outgoing calls barred within CUG" },
+ { 0x36, "Incoming calls barred" },
+ { 0x37, "Incoming calls barred within CUG" },
+ { 0x38, "Call waiting not subscribed" },
+ { 0x39, "Bearer capability not authorized" },
+ { 0x3A, "Bearer capability not presently available" },
+ { 0x3E, "Inconsistency in designated outgoing access information and subscriber class" },
+ { 0x3F, "Service or option not available, unspecified" },
+ { 0x41, "Bearer capability not implemented" },
+ { 0x42, "Channel type not implemented" },
+ { 0x43, "Transit network selection not implemented" },
+ { 0x44, "Message not implemented" },
+ { 0x45, "Requested facility not implemented" },
+ { 0x46, "Only restricted digital information bearer capability is available" },
+ { 0x4F, "Service or option not implemented, unspecified" },
+ { 0x51, "Invalid call reference value" },
+ { 0x52, "Identified channel does not exist" },
+ { 0x53, "Call identity does not exist for suspended call" },
+ { 0x54, "Call identity in use" },
+ { 0x55, "No call suspended" },
+ { 0x56, "Call having the requested call identity has been cleared" },
+ { 0x57, "Called user not member of CUG" },
+ { 0x58, "Incompatible destination" },
+ { 0x59, "Non-existent abbreviated address entry" },
+ { 0x5A, "Destination address missing, and direct call not subscribed" },
+ { 0x5B, "Invalid transit network selection (national use)" },
+ { 0x5C, "Invalid facility parameter" },
+ { 0x5D, "Mandatory information element is missing" },
+ { 0x5F, "Invalid message, unspecified" },
+ { 0x60, "Mandatory information element is missing" },
+ { 0x61, "Message type non-existent or not implemented" },
+ { 0x62, "Message not compatible with call state or message type non-existent or not implemented" },
+ { 0x63, "Information element nonexistant or not implemented" },
+ { 0x64, "Invalid information element contents" },
+ { 0x65, "Message not compatible with call state" },
+ { 0x66, "Recovery on timer expiry" },
+ { 0x67, "Parameter non-existent or not implemented - passed on" },
+ { 0x6E, "Message with unrecognized parameter discarded" },
+ { 0x6F, "Protocol error, unspecified" },
+ { 0x7F, "Internetworking, unspecified" },
+ { 0xFF, "Non-specific failure" },
+ { 0, NULL }
+};
+
+static const value_string bap_call_status_opt_action_vals[] = {
+ {0, "No retry" },
+ {1, "Retry" },
+ {0, NULL }
+};
+
+#define STAC_CM_NONE 0
+#define STAC_CM_LCB 1
+#define STAC_CM_CRC 2
+#define STAC_CM_SN 3
+#define STAC_CM_EXTMODE 4
+static const value_string stac_checkmode_vals[] = {
+ {STAC_CM_NONE, "None" },
+ {STAC_CM_LCB, "LCB" },
+ {STAC_CM_CRC, "CRC" },
+ {STAC_CM_SN, "Sequence Number" },
+ {STAC_CM_EXTMODE, "Extended Mode" },
+ {0, NULL }
+};
+
+#define LZSDCP_CM_NONE 0
+#define LZSDCP_CM_LCB 1
+#define LZSDCP_CM_SN 2
+#define LZSDCP_CM_SN_LCB 3
+static const value_string lzsdcp_checkmode_vals[] = {
+ {LZSDCP_CM_NONE, "None" },
+ {LZSDCP_CM_LCB, "LCB" },
+ {LZSDCP_CM_SN, "Sequence Number" },
+ {LZSDCP_CM_SN_LCB, "Sequence Number + LCB" },
+ {0, NULL }
+};
+
+#define LZSDCP_PM_NONE 0
+#define LZSDCP_PM_PROC_UNCOMP 1
+static const value_string lzsdcp_processmode_vals[] = {
+ {LZSDCP_PM_NONE, "None" },
+ {LZSDCP_PM_PROC_UNCOMP, "Process-Uncompressed" },
+ {0, NULL }
+};
+
+/*
+ * Options. (LCP)
+ */
+#define CI_MRU 1 /* Maximum Receive Unit */
+#define CI_ASYNCMAP 2 /* Async Control Character Map */
+#define CI_AUTHTYPE 3 /* Authentication Type */
+#define CI_QUALITY 4 /* Quality Protocol */
+#define CI_MAGICNUMBER 5 /* Magic Number */
+#define CI_PCOMPRESSION 7 /* Protocol Field Compression */
+#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
+#define CI_FCS_ALTERNATIVES 9 /* FCS Alternatives (RFC 1570) */
+#define CI_SELF_DESCRIBING_PAD 10 /* Self-Describing Pad (RFC 1570) */
+#define CI_NUMBERED_MODE 11 /* Numbered Mode (RFC 1663) */
+#define CI_CALLBACK 13 /* Callback (RFC 1570) */
+#define CI_COMPOUND_FRAMES 15 /* Compound frames (RFC 1570) */
+#define CI_MULTILINK_MRRU 17 /* Multilink MRRU (RFC 1717) */
+#define CI_MULTILINK_SSNH 18 /* Multilink Short Sequence Number
+ Header (RFC 1717) */
+#define CI_MULTILINK_EP_DISC 19 /* Multilink Endpoint Discriminator
+ (RFC 1717) */
+#define CI_DCE_IDENTIFIER 21 /* DCE Identifier */
+#define CI_MULTILINK_PLUS_PROC 22 /* Multilink Plus Procedure */
+#define CI_LINK_DISC_FOR_BACP 23 /* Link Discriminator for BACP
+ (RFC 2125) */
+#define CI_LCP_AUTHENTICATION 24 /* LCP Authentication Option */
+#define CI_COBS 25 /* Consistent Overhead Byte
+ Stuffing */
+#define CI_PREFIX_ELISION 26 /* Prefix elision */
+#define CI_MULTILINK_HDR_FMT 27 /* Multilink header format */
+#define CI_INTERNATIONALIZATION 28 /* Internationalization (RFC 2484) */
+#define CI_SDL_ON_SONET_SDH 29 /* Simple Data Link on SONET/SDH */
+
+static void dissect_lcp_mru_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+static void dissect_lcp_async_map_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+static void dissect_lcp_protocol_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+static void dissect_lcp_authprot_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+static void dissect_lcp_magicnumber_opt(const ip_tcp_opt *optp,
+ tvbuff_t *tvb, int offset, guint length,
+ packet_info *pinfo, proto_tree *tree);
+static void dissect_lcp_fcs_alternatives_opt(const ip_tcp_opt *optp,
+ tvbuff_t *tvb, int offset, guint length,
+ packet_info *pinfo, proto_tree *tree);
+static void dissect_lcp_numbered_mode_opt(const ip_tcp_opt *optp,
+ tvbuff_t *tvb, int offset, guint length,
+ packet_info *pinfo, proto_tree *tree);
+static void dissect_lcp_self_describing_pad_opt(const ip_tcp_opt *optp,
+ tvbuff_t *tvb, int offset, guint length,
+ packet_info *pinfo, proto_tree *tree);
+static void dissect_lcp_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+static void dissect_lcp_multilink_mrru_opt(const ip_tcp_opt *optp,
+ tvbuff_t *tvb, int offset, guint length,
+ packet_info *pinfo, proto_tree *tree);
+static void dissect_lcp_multilink_ep_disc_opt(const ip_tcp_opt *optp,
+ tvbuff_t *tvb, int offset, guint length,
+ packet_info *pinfo, proto_tree *tree);
+static void dissect_lcp_bap_link_discriminator_opt(const ip_tcp_opt *optp,
+ tvbuff_t *tvb, int offset, guint length,
+ packet_info *pinfo, proto_tree *tree);
+static void dissect_lcp_internationalization_opt(const ip_tcp_opt *optp,
+ tvbuff_t *tvb, int offset, guint length,
+ packet_info *pinfo, proto_tree *tree);
+static void dissect_mp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static const ip_tcp_opt lcp_opts[] = {
+ {
+ CI_MRU,
+ "Maximum Receive Unit",
+ NULL,
+ FIXED_LENGTH,
+ 4,
+ dissect_lcp_mru_opt
+ },
+ {
+ CI_ASYNCMAP,
+ "Async Control Character Map",
+ NULL,
+ FIXED_LENGTH,
+ 6,
+ dissect_lcp_async_map_opt
+ },
+ {
+ CI_AUTHTYPE,
+ "Authentication protocol",
+ &ett_lcp_authprot_opt,
+ VARIABLE_LENGTH,
+ 4,
+ dissect_lcp_authprot_opt
+ },
+ {
+ CI_QUALITY,
+ "Quality protocol",
+ &ett_lcp_qualprot_opt,
+ VARIABLE_LENGTH,
+ 4,
+ dissect_lcp_protocol_opt
+ },
+ {
+ CI_MAGICNUMBER,
+ "Magic number",
+ NULL,
+ FIXED_LENGTH,
+ 6,
+ dissect_lcp_magicnumber_opt
+ },
+ {
+ CI_PCOMPRESSION,
+ "Protocol field compression",
+ NULL,
+ FIXED_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_ACCOMPRESSION,
+ "Address/control field compression",
+ NULL,
+ FIXED_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_FCS_ALTERNATIVES,
+ "FCS alternatives",
+ &ett_lcp_fcs_alternatives_opt,
+ FIXED_LENGTH,
+ 3,
+ dissect_lcp_fcs_alternatives_opt
+ },
+ {
+ CI_SELF_DESCRIBING_PAD,
+ "Maximum octets of self-describing padding",
+ NULL,
+ FIXED_LENGTH,
+ 3,
+ dissect_lcp_self_describing_pad_opt
+ },
+ {
+ CI_NUMBERED_MODE,
+ "Numbered mode",
+ &ett_lcp_numbered_mode_opt,
+ VARIABLE_LENGTH,
+ 4,
+ dissect_lcp_numbered_mode_opt
+ },
+ {
+ CI_CALLBACK,
+ "Callback",
+ &ett_lcp_callback_opt,
+ VARIABLE_LENGTH,
+ 3,
+ dissect_lcp_callback_opt,
+ },
+ {
+ CI_COMPOUND_FRAMES,
+ "Compound frames",
+ NULL,
+ FIXED_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_MULTILINK_MRRU,
+ "Multilink MRRU",
+ NULL,
+ FIXED_LENGTH,
+ 4,
+ dissect_lcp_multilink_mrru_opt
+ },
+ {
+ CI_MULTILINK_SSNH,
+ "Use short sequence number headers",
+ NULL,
+ FIXED_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_MULTILINK_EP_DISC,
+ "Multilink endpoint discriminator",
+ &ett_lcp_multilink_ep_disc_opt,
+ VARIABLE_LENGTH,
+ 3,
+ dissect_lcp_multilink_ep_disc_opt,
+ },
+ {
+ CI_DCE_IDENTIFIER,
+ "DCE identifier",
+ NULL,
+ VARIABLE_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_MULTILINK_PLUS_PROC,
+ "Multilink Plus Procedure",
+ NULL,
+ VARIABLE_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_LINK_DISC_FOR_BACP,
+ "Link discriminator for BAP",
+ NULL,
+ FIXED_LENGTH,
+ 4,
+ dissect_lcp_bap_link_discriminator_opt
+ },
+ {
+ CI_LCP_AUTHENTICATION,
+ "LCP authentication",
+ NULL,
+ VARIABLE_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_COBS,
+ "Consistent Overhead Byte Stuffing",
+ NULL,
+ VARIABLE_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_PREFIX_ELISION,
+ "Prefix elision",
+ NULL,
+ VARIABLE_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_MULTILINK_HDR_FMT,
+ "Multilink header format",
+ NULL,
+ VARIABLE_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_INTERNATIONALIZATION,
+ "Internationalization",
+ &ett_lcp_internationalization_opt,
+ VARIABLE_LENGTH,
+ 7,
+ dissect_lcp_internationalization_opt
+ },
+ {
+ CI_SDL_ON_SONET_SDH,
+ "Simple data link on SONET/SDH",
+ NULL,
+ VARIABLE_LENGTH,
+ 2,
+ NULL
+ }
+};
+
+#define N_LCP_OPTS (sizeof lcp_opts / sizeof lcp_opts[0])
+
+/*
+ * CHAP Algorithms
+ */
+#define CHAP_ALG_MD5 0x05 /* CHAP with MD5 */
+#define CHAP_ALG_MSV1 0x80 /* MS-CHAPv1 */
+#define CHAP_ALG_MSV2 0x81 /* MS-CHAPv2 */
+
+static const value_string chap_alg_vals[] = {
+ {CHAP_ALG_MD5, "CHAP with MD5" },
+ {CHAP_ALG_MSV1, "MS-CHAP" },
+ {CHAP_ALG_MSV2, "MS-CHAP-2" },
+ {0, NULL }
+};
+
+
+/*
+ * Options. (IPCP)
+ */
+#define CI_ADDRS 1 /* IP Addresses (deprecated) (RFC 1172) */
+#define CI_COMPRESSTYPE 2 /* Compression Type (RFC 1332) */
+#define CI_ADDR 3 /* IP Address (RFC 1332) */
+#define CI_MOBILE_IPv4 4 /* Mobile IPv4 (RFC 2290) */
+#define CI_MS_DNS1 129 /* Primary DNS value (RFC 1877) */
+#define CI_MS_WINS1 130 /* Primary WINS value (RFC 1877) */
+#define CI_MS_DNS2 131 /* Secondary DNS value (RFC 1877) */
+#define CI_MS_WINS2 132 /* Secondary WINS value (RFC 1877) */
+
+static void dissect_ipcp_addrs_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static const ip_tcp_opt ipcp_opts[] = {
+ {
+ CI_ADDRS,
+ "IP addresses (deprecated)",
+ &ett_ipcp_ipaddrs_opt,
+ FIXED_LENGTH,
+ 10,
+ dissect_ipcp_addrs_opt
+ },
+ {
+ CI_COMPRESSTYPE,
+ "IP compression protocol",
+ &ett_ipcp_compressprot_opt,
+ VARIABLE_LENGTH,
+ 4,
+ dissect_lcp_protocol_opt
+ },
+ {
+ CI_ADDR,
+ "IP address",
+ NULL,
+ FIXED_LENGTH,
+ 6,
+ dissect_ipcp_addr_opt
+ },
+ {
+ CI_MOBILE_IPv4,
+ "Mobile node's home IP address",
+ NULL,
+ FIXED_LENGTH,
+ 6,
+ dissect_ipcp_addr_opt
+ },
+ {
+ CI_MS_DNS1,
+ "Primary DNS server IP address",
+ NULL,
+ FIXED_LENGTH,
+ 6,
+ dissect_ipcp_addr_opt
+ },
+ {
+ CI_MS_WINS1,
+ "Primary WINS server IP address",
+ NULL,
+ FIXED_LENGTH,
+ 6,
+ dissect_ipcp_addr_opt
+ },
+ {
+ CI_MS_DNS2,
+ "Secondary DNS server IP address",
+ NULL,
+ FIXED_LENGTH,
+ 6,
+ dissect_ipcp_addr_opt
+ },
+ {
+ CI_MS_WINS2,
+ "Secondary WINS server IP address",
+ NULL,
+ FIXED_LENGTH,
+ 6,
+ dissect_ipcp_addr_opt
+ }
+};
+
+#define N_IPCP_OPTS (sizeof ipcp_opts / sizeof ipcp_opts[0])
+
+/*
+ * Options. (OSICP)
+ */
+#define CI_OSICP_ALIGN_NPDU 1 /* Alignment of the OSI NPDU (RFC 1377) */
+
+static void dissect_osicp_align_npdu_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static const ip_tcp_opt osicp_opts[] = {
+ {
+ CI_OSICP_ALIGN_NPDU,
+ "Align-NPDU",
+ &ett_osicp_align_npdu_opt,
+ FIXED_LENGTH,
+ 3,
+ dissect_osicp_align_npdu_opt
+ }
+};
+
+#define N_OSICP_OPTS (sizeof osicp_opts / sizeof osicp_opts[0])
+
+/*
+ * Options. (CCP)
+ */
+#define CI_CCP_OUI 0 /* OUI (RFC1962) */
+#define CI_CCP_PREDICT1 1 /* Predictor type 1 (RFC1962) */
+#define CI_CCP_PREDICT2 2 /* Predictor type 2 (RFC1962) */
+#define CI_CCP_PUDDLE 3 /* Puddle Jumper (RFC1962) */
+#define CI_CCP_HPPPC 16 /* Hewlett-Packard PPC (RFC1962) */
+#define CI_CCP_STAC 17 /* stac Electronics LZS (RFC1974) */
+#define CI_CCP_MPPC 18 /* Microsoft PPC (RFC2218/3078) */
+#define CI_CCP_GFZA 19 /* Gandalf FZA (RFC1962) */
+#define CI_CCP_V42BIS 20 /* V.42bis compression */
+#define CI_CCP_BSDLZW 21 /* BSD LZW Compress (RFC1977) */
+#define CI_CCP_LZSDCP 23 /* LZS-DCP (RFC1967) */
+#define CI_CCP_MVRCA 24 /* MVRCA (Magnalink) (RFC1975) */
+#define CI_CCP_DEFLATE 26 /* Deflate (RFC1979) */
+#define CI_CCP_RESERVED 255 /* Reserved (RFC1962) */
+
+/*
+ * Microsoft Point-To-Point Compression (MPPC) and Encryption (MPPE)
+ * supported bits.
+ */
+#define MPPC_SUPPORTED_BITS_C 0x00000001 /* MPPC negotiation */
+#define MPPE_SUPPORTED_BITS_D 0x00000010 /* Obsolete */
+#define MPPE_SUPPORTED_BITS_L 0x00000020 /* 40-bit encryption */
+#define MPPE_SUPPORTED_BITS_S 0x00000040 /* 128-bit encryption */
+#define MPPE_SUPPORTED_BITS_M 0x00000080 /* 56-bit encryption */
+#define MPPE_SUPPORTED_BITS_H 0x01000000 /* stateless mode */
+
+static void dissect_ccp_stac_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_ccp_mppc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_ccp_bsdcomp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_ccp_lzsdcp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_ccp_mvrca_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_ccp_deflate_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static const ip_tcp_opt ccp_opts[] = {
+ {
+ CI_CCP_STAC,
+ "Stac Electronics LZS",
+ &ett_ccp_stac_opt,
+ VARIABLE_LENGTH,
+ 5,
+ /* In RFC 1974, this is a fixed-length field of size 5,
+ but in Ascend Proprietary STAC compression this field
+ is 6 octets. Sigh... */
+ dissect_ccp_stac_opt
+ },
+ {
+ CI_CCP_MPPC,
+ "Microsoft PPC",
+ &ett_ccp_mppc_opt,
+ FIXED_LENGTH,
+ 6,
+ dissect_ccp_mppc_opt
+ },
+ {
+ CI_CCP_BSDLZW,
+ "BSD Compress",
+ &ett_ccp_bsdcomp_opt,
+ FIXED_LENGTH,
+ 3,
+ dissect_ccp_bsdcomp_opt
+ },
+ {
+ CI_CCP_LZSDCP,
+ "LZS-DCP",
+ &ett_ccp_lzsdcp_opt,
+ FIXED_LENGTH,
+ 6,
+ dissect_ccp_lzsdcp_opt
+ },
+ {
+ CI_CCP_MVRCA,
+ "MVRCA (Magnalink)",
+ &ett_ccp_mvrca_opt,
+ FIXED_LENGTH,
+ 4,
+ dissect_ccp_mvrca_opt
+ },
+ {
+ CI_CCP_DEFLATE,
+ "Deflate",
+ &ett_ccp_deflate_opt,
+ FIXED_LENGTH,
+ 4, /* RFC1979 says the length is 3 but it's actually 4. */
+ dissect_ccp_deflate_opt
+ },
+};
+
+#define N_CCP_OPTS (sizeof ccp_opts / sizeof ccp_opts[0])
+
+/*
+ * Options. (CBCP)
+ */
+#define CI_CBCP_NO_CALLBACK 1 /* No callback */
+#define CI_CBCP_CB_USER 2 /* Callback to a user-specified number */
+#define CI_CBCP_CB_PRE 3 /* Callback to a pre-specified or
+ administrator specified number */
+#define CI_CBCP_CB_ANY 4 /* Callback to any of a list of numbers */
+
+static void dissect_cbcp_no_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_cbcp_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static const ip_tcp_opt cbcp_opts[] = {
+ {
+ CI_CBCP_NO_CALLBACK,
+ "No callback",
+ NULL,
+ FIXED_LENGTH,
+ 2,
+ dissect_cbcp_no_callback_opt
+ },
+ {
+ CI_CBCP_CB_USER,
+ "Callback to a user-specified number",
+ &ett_cbcp_callback_opt,
+ VARIABLE_LENGTH,
+ 4,
+ dissect_cbcp_callback_opt
+ },
+ {
+ CI_CBCP_CB_PRE,
+ "Callback to a pre-specified or admin-specified number",
+ &ett_cbcp_callback_opt,
+ FIXED_LENGTH,
+ 3,
+ dissect_cbcp_callback_opt
+ },
+ {
+ CI_CBCP_CB_ANY,
+ "Callback to any of a list of numbers",
+ &ett_cbcp_callback_opt,
+ VARIABLE_LENGTH,
+ 4,
+ dissect_cbcp_callback_opt
+ }
+
+};
+
+#define N_CBCP_OPTS (sizeof cbcp_opts / sizeof cbcp_opts[0])
+
+/*
+ * Options. (BACP)
+ */
+#define CI_BACP_FAVORED_PEER 1 /* Favored-Peer */
+
+static void dissect_bacp_favored_peer_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static const ip_tcp_opt bacp_opts[] = {
+ {
+ CI_BACP_FAVORED_PEER,
+ "Favored-Peer",
+ &ett_bacp_favored_peer_opt,
+ FIXED_LENGTH,
+ 6,
+ dissect_bacp_favored_peer_opt
+ }
+};
+
+#define N_BACP_OPTS (sizeof bacp_opts / sizeof bacp_opts[0])
+
+/*
+ * Options. (BAP)
+ */
+#define CI_BAP_LINK_TYPE 1 /* Link Type */
+#define CI_BAP_PHONE_DELTA 2 /* Phone-Delta */
+#define CI_BAP_NO_PHONE_NUM_NEEDED 3 /* No Phone Number Needed */
+#define CI_BAP_REASON 4 /* Reason */
+#define CI_BAP_LINK_DISC 5 /* Link Discriminator */
+#define CI_BAP_CALL_STATUS 6 /* Call Status */
+
+static void dissect_bap_link_type_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_bap_phone_delta_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_bap_link_disc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_bap_reason_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static void dissect_bap_call_status_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static const ip_tcp_opt bap_opts[] = {
+ {
+ CI_BAP_LINK_TYPE,
+ "Link Type",
+ &ett_bap_link_type_opt,
+ FIXED_LENGTH,
+ 5,
+ dissect_bap_link_type_opt
+ },
+ {
+ CI_BAP_PHONE_DELTA,
+ "Phone Delta",
+ &ett_bap_phone_delta_opt,
+ VARIABLE_LENGTH,
+ 4,
+ dissect_bap_phone_delta_opt
+ },
+ {
+ CI_BAP_NO_PHONE_NUM_NEEDED,
+ "No Phone Number Needed",
+ NULL,
+ FIXED_LENGTH,
+ 2,
+ NULL
+ },
+ {
+ CI_BAP_REASON,
+ "Reason",
+ NULL,
+ VARIABLE_LENGTH,
+ 2,
+ dissect_bap_reason_opt
+ },
+ {
+ CI_BAP_LINK_DISC,
+ "Link Discriminator",
+ NULL,
+ FIXED_LENGTH,
+ 4,
+ dissect_bap_link_disc_opt
+ },
+ {
+ CI_BAP_CALL_STATUS,
+ "Call Status",
+ &ett_bap_call_status_opt,
+ FIXED_LENGTH,
+ 4,
+ dissect_bap_call_status_opt
+ }
+};
+
+#define N_BAP_OPTS (sizeof bap_opts / sizeof bap_opts[0])
+
+static void dissect_ppp(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree);
+
+static const value_string pap_vals[] = {
+ {CONFREQ, "Authenticate-Request" },
+ {CONFACK, "Authenticate-Ack" },
+ {CONFNAK, "Authenticate-Nak" },
+ {0, NULL } };
+
+static void dissect_pap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+#define CHAP_CHAL 1 /* CHAP Challenge */
+#define CHAP_RESP 2 /* CHAP Response */
+#define CHAP_SUCC 3 /* CHAP Success */
+#define CHAP_FAIL 4 /* CHAP Failure */
+
+static const value_string chap_vals[] = {
+ {CHAP_CHAL, "Challenge" },
+ {CHAP_RESP, "Response" },
+ {CHAP_SUCC, "Success" },
+ {CHAP_FAIL, "Failure" },
+ {0, NULL } };
+
+static void dissect_chap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static const value_string pppmuxcp_vals[] = {
+ {CONFREQ, "Configuration Request" },
+ {CONFACK, "Configuration Ack" },
+ {0, NULL}
+};
+
+/*
+ * PPPMuxCP options
+ */
+
+#define CI_DEFAULT_PID 1
+
+static void dissect_pppmuxcp_def_pid_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo, proto_tree *tree);
+
+
+static const ip_tcp_opt pppmuxcp_opts[] = {
+ {
+ CI_DEFAULT_PID,
+ "Default Protocol ID",
+ NULL,
+ FIXED_LENGTH,
+ 4,
+ dissect_pppmuxcp_def_pid_opt
+ }
+};
+
+#define N_PPPMUXCP_OPTS (sizeof pppmuxcp_opts / sizeof pppmuxcp_opts[0])
+
+/*
+ * Options. (IPv6CP)
+ */
+#define CI_IPV6CP_IF_ID 1 /* Interface Identifier (RFC 2472) */
+#define CI_IPV6CP_COMPRESSTYPE 2 /* Compression Type (RFC 2472) */
+
+static void dissect_ipv6cp_if_id_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo,
+ proto_tree *tree);
+
+static const ip_tcp_opt ipv6cp_opts[] = {
+ {
+ CI_IPV6CP_IF_ID,
+ "Interface Identifier",
+ &ett_ipv6cp_if_id_opt,
+ FIXED_LENGTH,
+ 10,
+ dissect_ipv6cp_if_id_opt
+ },
+ {
+ CI_COMPRESSTYPE,
+ "IPv6 compression protocol",
+ &ett_ipcp_compressprot_opt,
+ VARIABLE_LENGTH,
+ 4,
+ dissect_lcp_protocol_opt
+ },
+};
+
+#define N_IPV6CP_OPTS (sizeof ipv6cp_opts / sizeof ipv6cp_opts[0])
+
+/*
+*******************************************************************************
+* DETAILS : Calculate a new FCS-16 given the current FCS-16 and the new data.
+*******************************************************************************
+*/
+static guint16
+fcs16(tvbuff_t * tvbuff)
+{
+ guint len = tvb_length(tvbuff)-2;
+
+ /* Check for Invalid Length */
+ if (len == 0)
+ return (0x0000);
+ return crc16_ccitt_tvb(tvbuff, len);
+}
+
+/*
+*******************************************************************************
+* DETAILS : Calculate a new FCS-32 given the current FCS-32 and the new data.
+*******************************************************************************
+*/
+static guint32
+fcs32(tvbuff_t * tvbuff)
+{
+ guint len = tvb_length(tvbuff)-4;
+
+ /* Check for invalid Length */
+ if (len == 0)
+ return (0x00000000);
+ return crc32_ccitt_tvb(tvbuff, len);
+}
+
+tvbuff_t *
+decode_fcs(tvbuff_t *tvb, proto_tree *fh_tree, int fcs_decode, int proto_offset)
+{
+ tvbuff_t *next_tvb;
+ gint len, reported_len;
+ int rx_fcs_offset;
+ guint32 rx_fcs_exp;
+ guint32 rx_fcs_got;
+
+ /*
+ * Remove the FCS, if any, from the packet data.
+ */
+ switch (fcs_decode) {
+
+ case NO_FCS:
+ next_tvb = tvb_new_subset(tvb, proto_offset, -1, -1);
+ break;
+
+ case FCS_16:
+ /*
+ * Do we have the entire packet, and does it include a 2-byte FCS?
+ */
+ len = tvb_length_remaining(tvb, proto_offset);
+ reported_len = tvb_reported_length_remaining(tvb, proto_offset);
+ if (reported_len < 2 || len < 0) {
+ /*
+ * The packet is claimed not to even have enough data for a 2-byte FCS,
+ * or we're already past the end of the captured data.
+ * Don't slice anything off.
+ */
+ next_tvb = tvb_new_subset(tvb, proto_offset, -1, -1);
+ } else if (len < reported_len) {
+ /*
+ * The packet is claimed to have enough data for a 2-byte FCS, but
+ * we didn't capture all of the packet.
+ * Slice off the 2-byte FCS from the reported length, and trim the
+ * captured length so it's no more than the reported length; that
+ * will slice off what of the FCS, if any, is in the captured
+ * length.
+ */
+ reported_len -= 2;
+ if (len > reported_len)
+ len = reported_len;
+ next_tvb = tvb_new_subset(tvb, proto_offset, len, reported_len);
+ } else {
+ /*
+ * We have the entire packet, and it includes a 2-byte FCS.
+ * Slice it off.
+ */
+ len -= 2;
+ reported_len -= 2;
+ next_tvb = tvb_new_subset(tvb, proto_offset, len, reported_len);
+
+ /*
+ * Compute the FCS and put it into the tree.
+ */
+ rx_fcs_offset = proto_offset + len;
+ rx_fcs_exp = fcs16(tvb);
+ rx_fcs_got = tvb_get_letohs(tvb, rx_fcs_offset);
+ if (rx_fcs_got != rx_fcs_exp) {
+ proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 2,
+ "FCS 16: 0x%04x (incorrect, should be 0x%04x)",
+ rx_fcs_got, rx_fcs_exp);
+ } else {
+ proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 2,
+ "FCS 16: 0x%04x (correct)",
+ rx_fcs_got);
+ }
+ }
+ break;
+
+ case FCS_32:
+ /*
+ * Do we have the entire packet, and does it include a 4-byte FCS?
+ */
+ len = tvb_length_remaining(tvb, proto_offset);
+ reported_len = tvb_reported_length_remaining(tvb, proto_offset);
+ if (reported_len < 4) {
+ /*
+ * The packet is claimed not to even have enough data for a 4-byte FCS.
+ * Just pass on the tvbuff as is.
+ */
+ next_tvb = tvb_new_subset(tvb, proto_offset, -1, -1);
+ } else if (len < reported_len) {
+ /*
+ * The packet is claimed to have enough data for a 4-byte FCS, but
+ * we didn't capture all of the packet.
+ * Slice off the 4-byte FCS from the reported length, and trim the
+ * captured length so it's no more than the reported length; that
+ * will slice off what of the FCS, if any, is in the captured
+ * length.
+ */
+ reported_len -= 4;
+ if (len > reported_len)
+ len = reported_len;
+ next_tvb = tvb_new_subset(tvb, proto_offset, len, reported_len);
+ } else {
+ /*
+ * We have the entire packet, and it includes a 4-byte FCS.
+ * Slice it off.
+ */
+ len -= 4;
+ reported_len -= 4;
+ next_tvb = tvb_new_subset(tvb, proto_offset, len, reported_len);
+
+ /*
+ * Compute the FCS and put it into the tree.
+ */
+ rx_fcs_offset = proto_offset + len;
+ rx_fcs_exp = fcs32(tvb);
+ rx_fcs_got = tvb_get_letohl(tvb, rx_fcs_offset);
+ if (rx_fcs_got != rx_fcs_exp) {
+ proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 4,
+ "FCS 32: 0x%08x (incorrect, should be 0x%08x)",
+ rx_fcs_got, rx_fcs_exp);
+ } else {
+ proto_tree_add_text(fh_tree, tvb, rx_fcs_offset, 4,
+ "FCS 32: 0x%08x (correct)",
+ rx_fcs_got);
+ }
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ next_tvb = NULL;
+ }
+
+ return next_tvb;
+}
+
+void
+capture_ppp_hdlc( const guchar *pd, int offset, int len, packet_counts *ld ) {
+ if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
+ ld->other++;
+ return;
+ }
+ if (pd[0] == CHDLC_ADDR_UNICAST || pd[0] == CHDLC_ADDR_MULTICAST) {
+ capture_chdlc(pd, offset, len, ld);
+ return;
+ }
+ if (!BYTES_ARE_IN_FRAME(offset, len, 4)) {
+ ld->other++;
+ return;
+ }
+ switch (pntohs(&pd[offset + 2])) {
+ case PPP_IP:
+ capture_ip(pd, offset + 4, len, ld);
+ break;
+ case PPP_IPX:
+ capture_ipx(ld);
+ break;
+ case PPP_VINES:
+ capture_vines(ld);
+ break;
+ default:
+ ld->other++;
+ break;
+ }
+}
+
+static void
+dissect_lcp_mru_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "%s: %u", optp->name,
+ tvb_get_ntohs(tvb, offset + 2));
+}
+
+static void
+dissect_lcp_async_map_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 map;
+ char *mapstr;
+ static const char *ctrlchars[32] = {
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "NL", "VT", "NP (FF)", "CR", "SO", "SI",
+ "DLE", "DC1 (XON)", "DC2", "DC3 (XOFF)", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+ };
+ char mapbuf[32*(10+2)+1];
+ char *mapp;
+ int i;
+
+ /*
+ * XXX - walk through the map and show the characters to map?
+ * Put them in a subtree of this item, and have the top-level item
+ * either say "None", "All", or give a list of the characters?)
+ */
+ map = tvb_get_ntohl(tvb, offset + 2);
+ if (map == 0x00000000)
+ mapstr = "None"; /* don't map any control characters */
+ else if (map == 0xffffffff)
+ mapstr = "All"; /* map all control characters */
+ else {
+ /*
+ * Show the names of the control characters being mapped.
+ */
+ mapp = &mapbuf[0];
+ for (i = 0; i < 32; i++) {
+ if (map & (1 << i)) {
+ if (mapp != &mapbuf[0]) {
+ strcpy(mapp, ", ");
+ mapp += 2;
+ }
+ strcpy(mapp, ctrlchars[i]);
+ mapp += strlen(ctrlchars[i]);
+ }
+ }
+ mapstr = mapbuf;
+ }
+ proto_tree_add_text(tree, tvb, offset, length, "%s: 0x%08x (%s)", optp->name,
+ map, mapstr);
+}
+
+static void
+dissect_lcp_protocol_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint16 protocol;
+ proto_item *tf;
+ proto_tree *field_tree = NULL;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
+ optp->name, length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2;
+ length -= 2;
+ protocol = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s: %s (0x%02x)", optp->name,
+ val_to_str(protocol, ppp_vals, "Unknown"), protocol);
+ offset += 2;
+ length -= 2;
+ if (length > 0)
+ proto_tree_add_text(field_tree, tvb, offset, length, "Data (%d byte%s)", length,
+ plurality(length, "", "s"));
+}
+
+static void
+dissect_lcp_authprot_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint16 protocol;
+ guint8 algorithm;
+ proto_item *tf;
+ proto_tree *field_tree = NULL;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
+ optp->name, length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2;
+ length -= 2;
+ protocol = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s: %s (0x%02x)", optp->name,
+ val_to_str(protocol, ppp_vals, "Unknown"), protocol);
+ offset += 2;
+ length -= 2;
+ if (length > 0) {
+ if (protocol == PPP_CHAP) {
+ algorithm = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Algorithm: %s (0x%02x)",
+ val_to_str(algorithm, chap_alg_vals, "Unknown"),
+ algorithm);
+ offset++;
+ } else {
+ proto_tree_add_text(field_tree, tvb, offset, length, "Data (%d byte%s)", length,
+ plurality(length, "", "s"));
+ }
+ }
+}
+
+static void
+dissect_lcp_magicnumber_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "%s: 0x%08x", optp->name,
+ tvb_get_ntohl(tvb, offset + 2));
+}
+
+static void
+dissect_lcp_fcs_alternatives_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree = NULL;
+ guint8 alternatives;
+
+ alternatives = tvb_get_guint8(tvb, offset + 2);
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s: 0x%02x",
+ optp->name, alternatives);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2;
+ if (alternatives & 0x1)
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1, "%s",
+ decode_boolean_bitfield(alternatives, 0x1, 8, "Null FCS", NULL));
+ if (alternatives & 0x2)
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1, "%s",
+ decode_boolean_bitfield(alternatives, 0x2, 8, "CCITT 16-bit FCS", NULL));
+ if (alternatives & 0x4)
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1, "%s",
+ decode_boolean_bitfield(alternatives, 0x4, 8, "CCITT 32-bit FCS", NULL));
+}
+
+static void
+dissect_lcp_self_describing_pad_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "%s: %u", optp->name,
+ tvb_get_guint8(tvb, offset + 2));
+}
+
+static void
+dissect_lcp_numbered_mode_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree = NULL;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
+ optp->name, length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2;
+ length -= 2;
+ proto_tree_add_text(field_tree, tvb, offset, 1, "Window: %u",
+ tvb_get_guint8(tvb, offset));
+ offset += 1;
+ length -= 1;
+ if (length > 0)
+ proto_tree_add_text(field_tree, tvb, offset, length, "Address (%d byte%s)",
+ length, plurality(length, "", "s"));
+}
+
+static const value_string callback_op_vals[] = {
+ {0, "Location is determined by user authentication" },
+ {1, "Message is dialing string" },
+ {2, "Message is location identifier" },
+ {3, "Message is E.164" },
+ {4, "Message is distinguished name" },
+ {5, "unassigned"},
+ {6, "Location is determined during CBCP negotiation" },
+ {0, NULL }
+};
+
+static void
+dissect_lcp_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb, int offset,
+ guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree = NULL;
+ guint8 operation;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
+ optp->name, length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2;
+ length -= 2;
+ operation = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(field_tree, tvb, offset, 1, "Operation: %s (0x%02x)",
+ val_to_str(operation, callback_op_vals, "Unknown"),
+ operation);
+ offset += 1;
+ length -= 1;
+ if (length > 0)
+ proto_tree_add_text(field_tree, tvb, offset, length, "Message (%d byte%s)",
+ length, plurality(length, "", "s"));
+}
+
+static void
+dissect_lcp_multilink_mrru_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "%s: %u", optp->name,
+ tvb_get_ntohs(tvb, offset + 2));
+}
+
+#define CLASS_NULL 0
+#define CLASS_LOCAL 1
+#define CLASS_IP 2
+#define CLASS_IEEE_802_1 3
+#define CLASS_PPP_MAGIC_NUMBER 4
+#define CLASS_PSDN_DIRECTORY_NUMBER 5
+
+static const value_string multilink_ep_disc_class_vals[] = {
+ {CLASS_NULL, "Null" },
+ {CLASS_LOCAL, "Locally assigned address" },
+ {CLASS_IP, "IP address" },
+ {CLASS_IEEE_802_1, "IEEE 802.1 globally assigned MAC address" },
+ {CLASS_PPP_MAGIC_NUMBER, "PPP magic-number block" },
+ {CLASS_PSDN_DIRECTORY_NUMBER, "Public switched network directory number" },
+ {0, NULL }
+};
+
+static void
+dissect_lcp_multilink_ep_disc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree = NULL;
+ guint8 ep_disc_class;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
+ optp->name, length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2;
+ length -= 2;
+ ep_disc_class = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(field_tree, tvb, offset, 1, "Class: %s (%u)",
+ val_to_str(ep_disc_class, multilink_ep_disc_class_vals, "Unknown"),
+ ep_disc_class);
+ offset += 1;
+ length -= 1;
+ if (length > 0) {
+ switch (ep_disc_class) {
+
+ case CLASS_NULL:
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s), should have been empty",
+ length, plurality(length, "", "s"));
+ break;
+
+ case CLASS_LOCAL:
+ if (length > 20) {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s), should have been <20",
+ length, plurality(length, "", "s"));
+ } else {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s)",
+ length, plurality(length, "", "s"));
+ }
+ break;
+
+ case CLASS_IP:
+ if (length != 4) {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s), should have been 4",
+ length, plurality(length, "", "s"));
+ } else {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ }
+ break;
+
+ case CLASS_IEEE_802_1:
+ if (length != 6) {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s), should have been 6",
+ length, plurality(length, "", "s"));
+ } else {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address: %s", ether_to_str(tvb_get_ptr(tvb, offset, 6)));
+ }
+ break;
+
+ case CLASS_PPP_MAGIC_NUMBER:
+ /* XXX - dissect as 32-bit magic numbers */
+ if (length > 20) {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s), should have been <20",
+ length, plurality(length, "", "s"));
+ } else {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s)",
+ length, plurality(length, "", "s"));
+ }
+ break;
+
+ case CLASS_PSDN_DIRECTORY_NUMBER:
+ if (length > 15) {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s), should have been <20",
+ length, plurality(length, "", "s"));
+ } else {
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s)",
+ length, plurality(length, "", "s"));
+ }
+ break;
+
+ default:
+ proto_tree_add_text(field_tree, tvb, offset, length,
+ "Address (%d byte%s)",
+ length, plurality(length, "", "s"));
+ break;
+ }
+ }
+}
+
+static void
+dissect_lcp_bap_link_discriminator_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, length,
+ "%s: 0x%04x", optp->name,
+ tvb_get_ntohs(tvb, offset + 2));
+}
+
+/* Character set numbers from the IANA charset registry. */
+static const value_string charset_num_vals[] = {
+ {105, "UTF-8" },
+ {0, NULL }
+};
+
+static void
+dissect_lcp_internationalization_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree = NULL;
+ guint32 charset;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
+ optp->name, length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2;
+ length -= 2;
+ charset = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(field_tree, tvb, offset, 4, "Character set: %s (0x%04x)",
+ val_to_str(charset, charset_num_vals, "Unknown"),
+ charset);
+ offset += 4;
+ length -= 4;
+ if (length > 0) {
+ /* XXX - should be displayed as an ASCII string */
+ proto_tree_add_text(field_tree, tvb, offset, length, "Language tag (%d byte%s)",
+ length, plurality(length, "", "s"));
+ }
+}
+
+static void
+dissect_ipcp_addrs_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree = NULL;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s: %u byte%s",
+ optp->name, length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ offset += 2;
+ length -= 2;
+ proto_tree_add_text(field_tree, tvb, offset, 4,
+ "Source IP address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ length -= 4;
+ proto_tree_add_text(field_tree, tvb, offset, 4,
+ "Destination IP address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+}
+
+static void dissect_ipcp_addr_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "%s: %s", optp->name,
+ ip_to_str(tvb_get_ptr(tvb, offset + 2, 4)));
+}
+
+static void dissect_osicp_align_npdu_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+ guint8 alignment;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ alignment = tvb_get_guint8(tvb, offset + 2);
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Alignment: %u", alignment);
+}
+
+static void dissect_pppmuxcp_def_pid_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ pppmux_def_prot_id = tvb_get_ntohs(tvb, offset + 2);
+ proto_tree_add_text(tree, tvb, offset + 2, length - 2, "%s: %s (0x%02x)",optp->name,
+ val_to_str(pppmux_def_prot_id, ppp_vals, "Unknown"), pppmux_def_prot_id);
+}
+
+
+static void
+dissect_ccp_stac_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+ guint8 check_mode;
+
+ if (length == 6) {
+ proto_tree_add_text(tree, tvb, offset, length,
+ "%s (Ascend Proprietary version)", optp->name);
+ /* We don't know how to decode the following 4 octets, since
+ there's no public document that describe their usage. */
+ } else {
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_text(field_tree, tvb, offset + 2, 2,
+ "History Count: %u", tvb_get_ntohs(tvb, offset + 2));
+ check_mode = tvb_get_guint8(tvb, offset + 4);
+ proto_tree_add_text(field_tree, tvb, offset + 4, 1,
+ "Check Mode: %s (0x%02X)",
+ val_to_str(check_mode, stac_checkmode_vals, "Unknown"),
+ check_mode);
+ }
+}
+
+static void
+dissect_ccp_mppc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *flags_tree;
+ guint32 supported_bits;
+
+ supported_bits = tvb_get_ntohl(tvb, offset + 2);
+ tf = proto_tree_add_text(tree, tvb, offset, length,
+ "%s: Supported Bits: 0x%08X", optp->name, supported_bits);
+ flags_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
+ decode_boolean_bitfield(supported_bits, MPPC_SUPPORTED_BITS_C, 8*4,
+ "Desire to negotiate MPPC", "NO Desire to negotiate MPPC"));
+ proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
+ decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_D, 8*4,
+ "Obsolete (should NOT be 1)", "Obsolete (should ALWAYS be 0)"));
+ proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
+ decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_L, 8*4,
+ "40-bit encryption ON", "40-bit encryption OFF"));
+ proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
+ decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_S, 8*4,
+ "128-bit encryption ON", "128-bit encryption OFF"));
+ proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
+ decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_M, 8*4,
+ "56-bit encryption ON", "56-bit encryption OFF"));
+ proto_tree_add_text(flags_tree, tvb, offset + 2, 4, "%s",
+ decode_boolean_bitfield(supported_bits, MPPE_SUPPORTED_BITS_H, 8*4,
+ "Stateless mode ON", "Stateless mode OFF"));
+}
+
+static void
+dissect_ccp_bsdcomp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Version: %u", tvb_get_guint8(tvb, offset + 2) >> 5);
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Dict: %u bits",
+ tvb_get_guint8(tvb, offset + 2) & 0x1f);
+}
+
+static void
+dissect_ccp_lzsdcp_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+ guint8 check_mode;
+ guint8 process_mode;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_text(field_tree, tvb, offset + 2, 2,
+ "History Count: %u", tvb_get_ntohs(tvb, offset + 2));
+ check_mode = tvb_get_guint8(tvb, offset + 4);
+ proto_tree_add_text(field_tree, tvb, offset + 4, 1,
+ "Check Mode: %s (0x%02X)",
+ val_to_str(check_mode, lzsdcp_checkmode_vals, "Unknown"),
+ check_mode);
+ process_mode = tvb_get_guint8(tvb, offset + 5);
+ proto_tree_add_text(field_tree, tvb, offset + 5, 1,
+ "Process Mode: %s (0x%02X)",
+ val_to_str(process_mode, lzsdcp_processmode_vals, "Unkown"),
+ process_mode);
+}
+
+static void
+dissect_ccp_mvrca_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Features: %u", tvb_get_guint8(tvb, offset + 2) >> 5);
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Packet by Packet flag: %s",
+ tvb_get_guint8(tvb, offset + 2) & 0x20 ? "true" : "false");
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "History: %u", tvb_get_guint8(tvb, offset + 2) & 0x20);
+ proto_tree_add_text(field_tree, tvb, offset + 3, 1,
+ "Number of contexts: %u", tvb_get_guint8(tvb, offset + 3));
+}
+
+static void
+dissect_ccp_deflate_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+ guint8 method;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Window: %u", hi_nibble(tvb_get_guint8(tvb, offset + 2)));
+ method = lo_nibble(tvb_get_guint8(tvb, offset + 2));
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Method: %s (0x%02x)",
+ method == 0x08 ? "zlib compression" : "other", method);
+ proto_tree_add_text(field_tree, tvb, offset + 3, 1,
+ "Sequence number check method: %u",
+ tvb_get_guint8(tvb, offset + 2) & 0x03);
+}
+
+static void
+dissect_cbcp_no_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+}
+
+static void
+dissect_cbcp_callback_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+ proto_item *ta;
+ proto_tree *addr_tree;
+ guint8 addr_type;
+ guint addr_len;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Callback delay: %u", tvb_get_guint8(tvb, offset + 2));
+ offset += 3;
+ length -= 3;
+
+ while (length > 0) {
+ ta = proto_tree_add_text(field_tree, tvb, offset, length,
+ "Callback Address");
+ addr_type = tvb_get_guint8(tvb, offset);
+ addr_tree = proto_item_add_subtree(tf, ett_cbcp_callback_opt_addr);
+ proto_tree_add_text(addr_tree, tvb, offset, 1,
+ "Address Type: %s (%u)",
+ ((addr_type == 1) ? "PSTN/ISDN" : "Other"), addr_type);
+ offset++;
+ length--;
+ addr_len = tvb_strsize(tvb, offset);
+ proto_tree_add_text(addr_tree, tvb, offset, addr_len,
+ "Address: %s",
+ tvb_format_text(tvb, offset, addr_len - 1));
+ offset += (addr_len + 1);
+ length -= (addr_len + 1);
+ }
+}
+
+static void
+dissect_bacp_favored_peer_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_text(field_tree, tvb, offset + 2, 4,
+ "Magic number: 0x%08x", tvb_get_ntohl(tvb, offset + 2));
+}
+
+static void
+dissect_bap_link_type_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+ guint8 link_type;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ proto_tree_add_text(field_tree, tvb, offset + 2, 2,
+ "Link Speed: %u kbps", tvb_get_ntohs(tvb, offset + 2));
+ link_type = tvb_get_guint8(tvb, offset + 4);
+ proto_tree_add_text(field_tree, tvb, offset + 4, 1,
+ "Link Type: %s (%u)", val_to_str(link_type, bap_link_type_vals,
+ "Unknown"), link_type);
+}
+
+static void
+dissect_bap_phone_delta_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+ proto_item *ti;
+ proto_tree *suboption_tree;
+ guint8 subopt_type;
+ guint8 subopt_len;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ offset += 2;
+ length -= 2;
+
+ while (length > 0) {
+ subopt_type = tvb_get_guint8(tvb, offset);
+ subopt_len = tvb_get_guint8(tvb, offset + 1);
+ ti = proto_tree_add_text(field_tree, tvb, offset, subopt_len,
+ "Sub-Option (%d byte%s)",
+ subopt_len, plurality(subopt_len, "", "s"));
+ suboption_tree = proto_item_add_subtree(ti, ett_bap_phone_delta_subopt);
+
+ proto_tree_add_text(suboption_tree, tvb, offset, 1,
+ "Sub-Option Type: %s (%u)",
+ val_to_str(subopt_type, bap_phone_delta_subopt_vals, "Unknown"),
+ subopt_type);
+
+ proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
+ "Sub-Option Length: %u", subopt_len);
+
+ switch (subopt_type) {
+ case BAP_PHONE_DELTA_SUBOPT_UNIQ_DIGIT:
+ proto_tree_add_text(suboption_tree, tvb, offset + 2, 1, "Uniq Digit: %u",
+ tvb_get_guint8(tvb, offset + 2));
+ break;
+ case BAP_PHONE_DELTA_SUBOPT_SUBSC_NUM:
+ if (subopt_len > 2) {
+ proto_tree_add_text(suboption_tree, tvb, offset + 2, subopt_len - 2,
+ "Subscriber Number: %s",
+ tvb_format_text(tvb, offset + 2, subopt_len - 2));
+ } else {
+ proto_tree_add_text(suboption_tree, tvb, offset + 1, 1,
+ "Invalid suboption length: %u", subopt_len);
+ }
+ break;
+ case BAP_PHONE_DELTA_SUBOPT_PHONENUM_SUBADDR:
+ if (subopt_len > 2) {
+ proto_tree_add_text(suboption_tree, tvb, offset + 2, subopt_len - 2,
+ "Phone Number Sub Address: %s",
+ tvb_format_text(tvb, offset + 2, subopt_len - 2));
+ }
+ break;
+ default:
+ proto_tree_add_text(suboption_tree, tvb, offset + 2, subopt_len - 2,
+ "Unknown");
+ break;
+ }
+ offset += subopt_len;
+ length -= subopt_len;
+ }
+}
+
+static void
+dissect_bap_reason_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ if (length > 2) {
+ proto_tree_add_text(tree, tvb, offset, length, "%s: %s",
+ optp->name,
+ tvb_format_text(tvb, offset + 2, length - 2));
+ }
+}
+
+static void
+dissect_bap_link_disc_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "%s: 0x%04x",
+ optp->name, tvb_get_ntohs(tvb, offset + 2));
+}
+
+static void
+dissect_bap_call_status_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_item *tf;
+ proto_tree *field_tree;
+ guint8 status, action;
+
+ tf = proto_tree_add_text(tree, tvb, offset, length, "%s", optp->name);
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+
+ status = tvb_get_guint8(tvb, offset + 2);
+ proto_tree_add_text(field_tree, tvb, offset + 2, 1,
+ "Status: %s (0x%02x)",
+ val_to_str(status, q931_cause_code_vals, "Unknown"), status);
+
+ action = tvb_get_guint8(tvb, offset + 3);
+ proto_tree_add_text(field_tree, tvb, offset + 3, 1,
+ "Action: %s (0x%02x)",
+ val_to_str(action, bap_call_status_opt_action_vals, "Unknown"), action);
+}
+
+static void
+dissect_cp( tvbuff_t *tvb, int proto_id, int proto_subtree_index,
+ const value_string *proto_vals, int options_subtree_index,
+ const ip_tcp_opt *opts, int nopts, packet_info *pinfo,
+ proto_tree *tree )
+{
+ proto_item *ti;
+ proto_tree *fh_tree = NULL;
+ proto_item *tf;
+ proto_tree *field_tree;
+
+ guint8 code;
+ guint8 id;
+ int length, offset;
+ guint16 protocol;
+
+ code = tvb_get_guint8(tvb, 0);
+ id = tvb_get_guint8(tvb, 1);
+ length = tvb_get_ntohs(tvb, 2);
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ proto_get_protocol_short_name(find_protocol_by_id(proto_id)));
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(code, proto_vals, "Unknown"));
+
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_id, tvb, 0, length, FALSE);
+ fh_tree = proto_item_add_subtree(ti, proto_subtree_index);
+ proto_tree_add_text(fh_tree, tvb, 0, 1, "Code: %s (0x%02x)",
+ val_to_str(code, proto_vals, "Unknown"), code);
+ proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x",
+ id);
+ proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u",
+ length);
+ }
+ offset = 4;
+ length -= 4;
+
+ switch (code) {
+ case CONFREQ:
+ case CONFACK:
+ case CONFNAK:
+ case CONFREJ:
+ if(tree) {
+ if (length > 0) {
+ tf = proto_tree_add_text(fh_tree, tvb, offset, length,
+ "Options: (%d byte%s)", length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, options_subtree_index);
+ dissect_ip_tcp_options(tvb, offset, length, opts, nopts, -1,
+ pinfo, field_tree);
+ }
+ }
+ break;
+
+ case ECHOREQ:
+ case ECHOREP:
+ case DISCREQ:
+ case IDENT:
+ if(tree) {
+ proto_tree_add_text(fh_tree, tvb, offset, 4, "Magic number: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ length -= 4;
+ if (length > 0)
+ proto_tree_add_text(fh_tree, tvb, offset, length, "Message (%d byte%s)",
+ length, plurality(length, "", "s"));
+ }
+ break;
+
+ case TIMEREMAIN:
+ if(tree) {
+ proto_tree_add_text(fh_tree, tvb, offset, 4, "Magic number: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ length -= 4;
+ proto_tree_add_text(fh_tree, tvb, offset, 4, "Seconds remaining: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ length -= 4;
+ if (length > 0)
+ proto_tree_add_text(fh_tree, tvb, offset, length, "Message (%d byte%s)",
+ length, plurality(length, "", "s"));
+ }
+ break;
+
+ case PROTREJ:
+ if(tree) {
+ gboolean save_in_error_pkt;
+ tvbuff_t *next_tvb;
+
+ protocol = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(fh_tree, tvb, offset, 2,
+ "Rejected protocol: %s (0x%04x)",
+ val_to_str(protocol, ppp_vals, "Unknown"),
+ protocol);
+ offset += 2;
+ length -= 2;
+ if (length > 0) {
+ proto_tree_add_text(fh_tree, tvb, offset, length,
+ "Rejected packet (%d byte%s)",
+ length, plurality(length, "", "s"));
+
+ /* Save the current value of the "we're inside an error packet"
+ flag, and set that flag; subdissectors may treat packets
+ that are the payload of error packets differently from
+ "real" packets. */
+ save_in_error_pkt = pinfo->in_error_pkt;
+ pinfo->in_error_pkt = TRUE;
+
+ /* Decode the rejected packet. */
+ next_tvb = tvb_new_subset(tvb, offset, length, length);
+ if (!dissector_try_port(ppp_subdissector_table, protocol,
+ next_tvb, pinfo, fh_tree)) {
+ call_dissector(data_handle, next_tvb, pinfo, fh_tree);
+ }
+
+ /* Restore the "we're inside an error packet" flag. */
+ pinfo->in_error_pkt = save_in_error_pkt;
+ }
+ }
+ break;
+
+ case CODEREJ:
+ /* decode the rejected LCP packet here. */
+ if (length > 0)
+ proto_tree_add_text(fh_tree, tvb, offset, length, "Rejected packet (%d byte%s)",
+ length, plurality(length, "", "s"));
+ break;
+
+ case TERMREQ:
+ case TERMACK:
+ if (length > 0)
+ proto_tree_add_text(fh_tree, tvb, offset, length, "Data (%d byte%s)",
+ length, plurality(length, "", "s"));
+ break;
+
+ default:
+ if (length > 0)
+ proto_tree_add_text(fh_tree, tvb, offset, length, "Stuff (%d byte%s)",
+ length, plurality(length, "", "s"));
+ break;
+ }
+}
+
+/* Protocol field compression */
+#define PFC_BIT 0x01
+
+static void
+dissect_ppp_common( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *fh_tree, proto_item *ti )
+{
+ guint16 ppp_prot;
+ int proto_len;
+ tvbuff_t *next_tvb;
+
+ ppp_prot = tvb_get_guint8(tvb, 0);
+ if (ppp_prot & PFC_BIT) {
+ /* Compressed protocol field - just the byte we fetched. */
+ proto_len = 1;
+ } else {
+ /* Uncompressed protocol field - fetch all of it. */
+ ppp_prot = tvb_get_ntohs(tvb, 0);
+ proto_len = 2;
+ }
+
+ /* If "ti" is not null, it refers to the top-level "proto_ppp" item
+ for PPP, and was given a length equal to the length of any
+ stuff in the header preceding the protocol type, e.g. an HDLC
+ header; add the length of the protocol type field to it. */
+ if (ti != NULL)
+ proto_item_set_len(ti, proto_item_get_len(ti) + proto_len);
+
+ if (tree)
+ proto_tree_add_uint(fh_tree, hf_ppp_protocol, tvb, 0, proto_len, ppp_prot);
+
+ next_tvb = tvb_new_subset(tvb, proto_len, -1, -1);
+
+ /* do lookup with the subdissector table */
+ if (!dissector_try_port(ppp_subdissector_table, ppp_prot, next_tvb, pinfo, tree)) {
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", ppp_prot);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "PPP %s (0x%04x)",
+ val_to_str(ppp_prot, ppp_vals, "Unknown"), ppp_prot);
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+}
+
+static void
+dissect_lcp_options(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_ip_tcp_options(tvb, 0, tvb_reported_length(tvb), lcp_opts, N_LCP_OPTS,
+ -1, pinfo, tree);
+}
+
+/*
+ * RFC 1661.
+ */
+static void
+dissect_lcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb, proto_lcp, ett_lcp, lcp_vals, ett_lcp_options,
+ lcp_opts, N_LCP_OPTS, pinfo, tree);
+}
+
+/*
+ * RFC 1332.
+ */
+static void
+dissect_ipcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb, proto_ipcp, ett_ipcp, cp_vals, ett_ipcp_options,
+ ipcp_opts, N_IPCP_OPTS, pinfo, tree);
+}
+
+/*
+ * RFC 1377.
+ */
+static void
+dissect_osicp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb, proto_osicp, ett_osicp, cp_vals, ett_osicp_options,
+ osicp_opts, N_OSICP_OPTS, pinfo, tree);
+}
+
+/*
+ * RFC 1962.
+ */
+static void
+dissect_ccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb, proto_ccp, ett_ccp, ccp_vals, ett_ccp_options,
+ ccp_opts, N_CCP_OPTS, pinfo, tree);
+}
+
+/*
+ * Callback Control Protocol - see
+ *
+ * http://www.linet.gr.jp/~manabe/PPxP/doc/Standards/draft-gidwani-ppp-callback-cp-00.txt
+ */
+static void
+dissect_cbcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb, proto_cbcp, ett_cbcp, cbcp_vals, ett_cbcp_options,
+ cbcp_opts, N_CBCP_OPTS, pinfo, tree);
+}
+
+/*
+ * RFC 2125 (BACP and BAP).
+ */
+static void
+dissect_bacp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb, proto_bacp, ett_bacp, cp_vals, ett_bacp_options,
+ bacp_opts, N_BACP_OPTS, pinfo, tree);
+}
+
+static void
+dissect_bap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *fh_tree = NULL;
+ proto_item *tf;
+ proto_tree *field_tree;
+
+ guint8 type;
+ guint8 id;
+ int length, offset;
+ guint8 resp_code;
+
+ type = tvb_get_guint8(tvb, 0);
+ id = tvb_get_guint8(tvb, 1);
+ length = tvb_get_ntohs(tvb, 2);
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP BAP");
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(type, bap_vals, "Unknown"));
+
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_bap, tvb, 0, length, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_bap_options);
+ proto_tree_add_text(fh_tree, tvb, 0, 1, "Type: %s (0x%02x)",
+ val_to_str(type, bap_vals, "Unknown"), type);
+ proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x",
+ id);
+ proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u",
+ length);
+ }
+ offset = 4;
+ length -= 4;
+
+ if (type == BAP_CRES || type == BAP_CBRES ||
+ type == BAP_LDQRES || type == BAP_CSRES) {
+ resp_code = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(fh_tree, tvb, offset, 1, "Response Code: %s (0x%02x)",
+ val_to_str(resp_code, bap_resp_code_vals, "Unknown"), resp_code);
+ offset++;
+ length--;
+ }
+
+ if(tree) {
+ if (length > 0) {
+ tf = proto_tree_add_text(fh_tree, tvb, offset, length,
+ "Data (%d byte%s)", length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, ett_bap_options);
+ dissect_ip_tcp_options(tvb, offset, length, bap_opts, N_BAP_OPTS, -1,
+ pinfo, field_tree);
+ }
+ }
+}
+
+static void
+dissect_comp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *comp_data_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP Comp");
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Compressed data");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_comp_data, tvb, 0, -1, FALSE);
+ comp_data_tree = proto_item_add_subtree(ti, ett_comp_data);
+ }
+}
+
+/*
+ * RFC 3153 (both PPPMuxCP and PPPMux).
+ */
+static void
+dissect_pppmuxcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb,proto_pppmuxcp,ett_pppmuxcp,pppmuxcp_vals,
+ ett_pppmuxcp_options,pppmuxcp_opts,N_PPPMUXCP_OPTS,pinfo,tree);
+}
+
+#define PPPMUX_FLAGS_MASK 0xc0
+#define PPPMUX_PFF_BIT_SET 0x80
+#define PPPMUX_LXT_BIT_SET 0x40
+
+static void
+dissect_pppmux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *mux_tree, *hdr_tree, *sub_tree, *flag_tree;
+ proto_tree *info_tree;
+ proto_item *ti = NULL,*sub_ti = NULL;
+ guint8 flags, byte;
+ guint16 length;
+ static guint16 pid;
+ tvbuff_t *next_tvb;
+ int offset = 0, length_remaining;
+ int length_field = 0, pid_field = 0,hdr_length = 0;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "PPP PPPMux");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "PPP Multiplexing");
+
+ length_remaining = tvb_reported_length(tvb);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_pppmux, tvb, 0, -1, FALSE);
+ mux_tree = proto_item_add_subtree(ti,ett_pppmux);
+
+ while (length_remaining > 0) {
+
+ flags = tvb_get_guint8(tvb,offset) & PPPMUX_FLAGS_MASK;
+
+ if (flags && PPPMUX_LXT_BIT_SET ) {
+ length = tvb_get_ntohs(tvb,offset) & 0x3fff;
+ length_field = 2;
+ } else {
+ length = tvb_get_guint8(tvb,offset) & 0x3f;
+ length_field = 1;
+ }
+
+ if (flags && PPPMUX_PFF_BIT_SET) {
+ byte = tvb_get_guint8(tvb,offset + length_field);
+ if (byte && PFC_BIT) { /* Compressed PID field*/
+ pid = byte;
+ pid_field = 1;
+ } else { /*PID field is 2 bytes*/
+ pid = tvb_get_ntohs(tvb,offset + length_field);
+ pid_field = 2;
+ }
+ } else {
+ if (!pid){ /*No Last PID, hence use the default */
+ if (pppmux_def_prot_id)
+ pid = pppmux_def_prot_id;
+ }
+ }
+
+ hdr_length = length_field + pid_field;
+
+ ti = proto_tree_add_text(mux_tree, tvb, offset, length + length_field,
+ "PPPMux Sub-frame");
+ sub_tree = proto_item_add_subtree(ti,ett_pppmux_subframe);
+ sub_ti = proto_tree_add_text(sub_tree, tvb, offset,
+ hdr_length,"Header field");
+
+ hdr_tree = proto_item_add_subtree(sub_ti,ett_pppmux_subframe_hdr);
+ ti = proto_tree_add_text(hdr_tree, tvb, offset, length_field, "PFF/LXT: 0x%02X",
+ flags);
+
+ flag_tree = proto_item_add_subtree(ti,ett_pppmux_subframe_flags);
+ proto_tree_add_text(flag_tree,tvb,offset,length_field,"%s",
+ decode_boolean_bitfield(flags,0x80,8,"PID Present","PID not present"));
+ proto_tree_add_text(flag_tree,tvb,offset,length_field,"%s",
+ decode_boolean_bitfield(flags,0x40,8,"2 bytes ength field ","1 byte length field"));
+
+ ti = proto_tree_add_text(hdr_tree,tvb,offset,length_field,"Sub-frame Length = %u",length);
+
+ if (flags && PPPMUX_PFF_BIT_SET)
+ proto_tree_add_text(hdr_tree,tvb,offset + length_field,pid_field,"%s: %s(0x%02x)",
+ "Protocol ID",val_to_str(pid,ppp_vals,"Unknown"), pid);
+
+ offset += hdr_length;
+ length_remaining -= hdr_length;
+ length -= pid_field;
+
+ sub_ti = proto_tree_add_text(sub_tree,tvb,offset,length,"Information Field");
+ info_tree = proto_item_add_subtree(sub_ti,ett_pppmux_subframe_info);
+
+ next_tvb = tvb_new_subset(tvb,offset,length,-1);
+
+ if (!dissector_try_port(ppp_subdissector_table, pid, next_tvb, pinfo, info_tree)) {
+ call_dissector(data_handle, next_tvb, pinfo, info_tree);
+ }
+ offset += length;
+ length_remaining -= length;
+ } /* While length_remaining */
+ pid = 0;
+ } /* if tree */
+}
+
+/*
+ * RFC 3032.
+ */
+static void
+dissect_mplscp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb, proto_mplscp, ett_mplscp, cp_vals, ett_mplscp_options,
+ NULL, 0, pinfo, tree);
+}
+
+/*
+ * Cisco Discovery Protocol Control Protocol.
+ * XXX - where is this documented?
+ */
+static void
+dissect_cdpcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb, proto_cdpcp, ett_cdpcp, cp_vals, ett_cdpcp_options,
+ NULL, 0, pinfo, tree);
+}
+
+#define MP_FRAG_MASK 0xC0
+#define MP_FRAG(bits) ((bits) & MP_FRAG_MASK)
+#define MP_FRAG_FIRST 0x80
+#define MP_FRAG_LAST 0x40
+#define MP_FRAG_RESERVED 0x3f
+
+static const true_false_string frag_truth = {
+ "Yes",
+ "No"
+};
+
+/* According to RFC 1717, the length the MP header isn't indicated anywhere
+ in the header itself. It starts out at four bytes and can be
+ negotiated down to two using LCP. We currently assume that all
+ headers are four bytes. - gcc
+ */
+static void
+dissect_mp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *mp_tree, *hdr_tree;
+ proto_item *ti = NULL;
+ guint8 flags;
+ gchar *flag_str;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP MP");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "PPP Multilink");
+
+ flags = tvb_get_guint8(tvb, 0);
+
+ if (tree) {
+ switch (flags) {
+ case MP_FRAG_FIRST:
+ flag_str = "First";
+ break;
+ case MP_FRAG_LAST:
+ flag_str = "Last";
+ break;
+ case MP_FRAG_FIRST|MP_FRAG_LAST:
+ flag_str = "First, Last";
+ break;
+ default:
+ flag_str = "Unknown";
+ break;
+ }
+ ti = proto_tree_add_item(tree, proto_mp, tvb, 0, 4, FALSE);
+ mp_tree = proto_item_add_subtree(ti, ett_mp);
+ ti = proto_tree_add_text(mp_tree, tvb, 0, 1, "Fragment: 0x%2X (%s)",
+ flags, flag_str);
+ hdr_tree = proto_item_add_subtree(ti, ett_mp_flags);
+ proto_tree_add_boolean(hdr_tree, hf_mp_frag_first, tvb, 0, 1, flags);
+ proto_tree_add_boolean(hdr_tree, hf_mp_frag_last, tvb, 0, 1, flags),
+ proto_tree_add_text(hdr_tree, tvb, 0, 1, "%s",
+ decode_boolean_bitfield(flags, MP_FRAG_RESERVED, sizeof(flags) * 8,
+ "reserved", "reserved"));
+ proto_tree_add_item(mp_tree, hf_mp_sequence_num, tvb, 1, 3, FALSE);
+ }
+
+ if (tvb_reported_length_remaining(tvb, 4) > 0) {
+ next_tvb = tvb_new_subset(tvb, 4, -1, -1);
+ dissect_ppp(next_tvb, pinfo, tree);
+ }
+}
+
+/*
+ * Handles PPP without HDLC framing, just a protocol field (RFC 1661).
+ */
+static void
+dissect_ppp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) {
+ proto_item *ti = NULL;
+ proto_tree *fh_tree = NULL;
+
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, -1, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_ppp);
+ }
+
+ dissect_ppp_common(tvb, pinfo, tree, fh_tree, ti);
+}
+
+/*
+ * Handles link-layer encapsulations where the frame might be
+ * a PPP in HDLC-like Framing frame (RFC 1662) or a Cisco HDLC frame.
+ */
+static void
+dissect_ppp_hdlc( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *fh_tree = NULL;
+ guint8 byte0;
+ int proto_offset;
+ tvbuff_t *next_tvb;
+
+ byte0 = tvb_get_guint8(tvb, 0);
+ if (byte0 == CHDLC_ADDR_UNICAST || byte0 == CHDLC_ADDR_MULTICAST) {
+ /* Cisco HDLC encapsulation */
+ call_dissector(chdlc_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ /*
+ * XXX - should we have a routine that always dissects PPP, for use
+ * when we know the packets are PPP, not CHDLC?
+ */
+
+ /* PPP HDLC encapsulation */
+ if (byte0 == 0xff)
+ proto_offset = 2;
+ else {
+ /* address and control are compressed (NULL) */
+ proto_offset = 0;
+ }
+
+ /* load the top pane info. This should be overwritten by
+ the next protocol in the stack */
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP" );
+
+ switch (pinfo->p2p_dir) {
+
+ case P2P_DIR_SENT:
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
+ break;
+
+ case P2P_DIR_RECV:
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
+ break;
+
+ default:
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
+ break;
+ }
+
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_ppp, tvb, 0, proto_offset, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_ppp);
+ if (byte0 == 0xff) {
+ proto_tree_add_item(fh_tree, hf_ppp_address, tvb, 0, 1, FALSE);
+ proto_tree_add_item(fh_tree, hf_ppp_control, tvb, 1, 1, FALSE);
+ }
+ }
+
+ next_tvb = decode_fcs(tvb, fh_tree, ppp_fcs_decode, proto_offset);
+
+ dissect_ppp_common(next_tvb, pinfo, tree, fh_tree, ti);
+}
+
+/*
+ * Handles PAP just as a protocol field
+ */
+static void
+dissect_pap( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) {
+ proto_item *ti;
+ proto_tree *fh_tree = NULL;
+ proto_item *tf;
+ proto_tree *field_tree;
+ proto_item *tm;
+ proto_tree *message_tree;
+ proto_item *tp;
+ proto_tree *peer_id_tree;
+ proto_item *tpw;
+ proto_tree *passwd_tree;
+
+ guint8 code;
+ guint8 id, peer_id_length, password_length, msg_length;
+ int length, offset;
+
+ code = tvb_get_guint8(tvb, 0);
+ id = tvb_get_guint8(tvb, 1);
+ length = tvb_get_ntohs(tvb, 2);
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP PAP");
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(code, pap_vals, "Unknown"));
+
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_pap, tvb, 0, length, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_pap);
+ proto_tree_add_text(fh_tree, tvb, 0, 1, "Code: %s (0x%02x)",
+ val_to_str(code, pap_vals, "Unknown"), code);
+ proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x",
+ id);
+ proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u",
+ length);
+ }
+ offset = 4;
+ length -= 4;
+
+ switch (code) {
+ case CONFREQ:
+ if(tree) {
+ if (length > 0) {
+ tf = proto_tree_add_text(fh_tree, tvb, offset, length,
+ "Data (%d byte%s)", length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, ett_pap_data);
+ peer_id_length = tvb_get_guint8(tvb, offset);
+ tp = proto_tree_add_text(field_tree, tvb, offset, 1,
+ "Peer ID length: %d byte%s", peer_id_length, plurality(peer_id_length, "", "s"));
+ if (--length > 0) {
+ peer_id_tree = proto_item_add_subtree(tp, ett_pap_peer_id);
+ proto_tree_add_text(peer_id_tree, tvb, ++offset, ppp_min(peer_id_length, length),
+ "Peer-ID (%d byte%s)", peer_id_length, plurality(peer_id_length, "", "s"));
+ offset+=peer_id_length;
+ length-=peer_id_length;
+ if (length > 0) {
+ password_length = tvb_get_guint8(tvb, offset);
+ if (--length > 0) {
+ tpw = proto_tree_add_text(field_tree, tvb, offset, 1,
+ "Password length: %d byte%s", password_length, plurality(password_length, "", "s"));
+ passwd_tree = proto_item_add_subtree(tpw, ett_pap_password);
+ proto_tree_add_text(passwd_tree, tvb, ++offset, ppp_min(password_length, length),
+ "Password (%d byte%s)", password_length, plurality(password_length, "", "s"));
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case CONFACK:
+ case CONFNAK:
+ if(tree) {
+ if (length > 0) {
+ tf = proto_tree_add_text(fh_tree, tvb, offset, length,
+ "Data (%d byte%s)", length, plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, ett_pap_data);
+ msg_length = tvb_get_guint8(tvb, offset);
+ tm = proto_tree_add_text(field_tree, tvb, offset, 1,
+ "Message length: %d byte%s", msg_length, plurality(msg_length, "", "s"));
+ if (--length > 0) {
+ message_tree = proto_item_add_subtree(tm, ett_pap_message);
+ proto_tree_add_text(message_tree, tvb, ++offset, ppp_min(msg_length, length),
+ "Message (%d byte%s)", msg_length, plurality(msg_length, "", "s"));
+ }
+ }
+ }
+ break;
+ default:
+ if (length > 0)
+ proto_tree_add_text(fh_tree, tvb, offset, length, "Stuff (%d byte%s)",
+ length, plurality(length, "", "s"));
+ break;
+ }
+}
+
+/*
+ * Handles CHAP just as a protocol field
+ */
+static void
+dissect_chap( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ) {
+ proto_item *ti;
+ proto_tree *fh_tree = NULL;
+ proto_item *tf;
+ proto_tree *field_tree;
+ proto_item *tv;
+ proto_tree *value_tree;
+
+ guint8 code, id, value_size;
+ guint16 length;
+ int offset;
+ int name_length;
+
+ code = tvb_get_guint8(tvb, 0);
+ id = tvb_get_guint8(tvb, 1);
+ length = tvb_get_ntohs(tvb, 2);
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP CHAP");
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(code, chap_vals, "Unknown"));
+
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_chap, tvb, 0, length, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_chap);
+ proto_tree_add_text(fh_tree, tvb, 0, 1, "Code: %s (0x%02x)",
+ val_to_str(code, chap_vals, "Unknown"), code);
+ proto_tree_add_text(fh_tree, tvb, 1, 1, "Identifier: 0x%02x",
+ id);
+ proto_tree_add_text(fh_tree, tvb, 2, 2, "Length: %u",
+ length);
+ }
+ offset = 4;
+ length -= 4;
+
+ switch (code) {
+ case CHAP_CHAL:
+ case CHAP_RESP:
+ if(tree) {
+ if (length > 0) {
+ tf = proto_tree_add_text(fh_tree, tvb, offset, length,
+ "Data (%d byte%s)", length,
+ plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, ett_chap_data);
+ value_size = tvb_get_guint8(tvb, offset);
+ name_length = length - value_size - 1;
+ tv = proto_tree_add_text(field_tree, tvb, offset, 1,
+ "Value Size: %d byte%s",
+ value_size, plurality(value_size, "", "s"));
+ if (--length > 0) {
+ value_tree = proto_item_add_subtree(tv, ett_chap_value);
+ proto_tree_add_text(value_tree, tvb, ++offset,
+ ppp_min(value_size, length),
+ "Value (%d byte%s)",
+ value_size, plurality(value_size, "", "s"));
+ offset+=value_size;
+ length-=value_size;
+ if (length > 0) {
+ proto_tree_add_text(field_tree, tvb, offset,
+ ppp_min(name_length, length),
+ "Name (%d byte%s)", name_length,
+ plurality(name_length, "", "s"));
+ }
+ }
+ }
+ }
+ break;
+
+ case CHAP_SUCC:
+ case CHAP_FAIL:
+ if(tree) {
+ if (length > 0) {
+ tf = proto_tree_add_text(fh_tree, tvb, offset, length,
+ "Data (%d byte%s)", length,
+ plurality(length, "", "s"));
+ field_tree = proto_item_add_subtree(tf, ett_chap_data);
+ tv = proto_tree_add_text(field_tree, tvb, offset, length,
+ "Message: %d byte%s",
+ length, plurality(length, "", "s"));
+ }
+ }
+ break;
+ default:
+ if (length > 0)
+ proto_tree_add_text(fh_tree, tvb, offset, length, "Stuff (%d byte%s)",
+ length, plurality(length, "", "s"));
+ break;
+ }
+}
+
+/*
+ * RFC 2472.
+ */
+static void
+dissect_ipv6cp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_cp(tvb, proto_ipv6cp, ett_ipv6cp, cp_vals, ett_ipv6cp_options,
+ ipv6cp_opts, N_IPV6CP_OPTS, pinfo, tree);
+}
+
+static void dissect_ipv6cp_if_id_opt(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint length, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, length, "%s: %02x%02x:%02x%02x:%02x%x:%02x%02x",
+ optp->name,
+ tvb_get_guint8(tvb, offset + 2),
+ tvb_get_guint8(tvb, offset + 3),
+ tvb_get_guint8(tvb, offset + 4),
+ tvb_get_guint8(tvb, offset + 5),
+ tvb_get_guint8(tvb, offset + 6),
+ tvb_get_guint8(tvb, offset + 7),
+ tvb_get_guint8(tvb, offset + 8),
+ tvb_get_guint8(tvb, offset + 9)
+ );
+}
+
+void
+proto_register_ppp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ppp_address,
+ { "Address", "ppp.address", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_ppp_control,
+ { "Control", "ppp.control", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_ppp_protocol,
+ { "Protocol", "ppp.protocol", FT_UINT16, BASE_HEX,
+ VALS(ppp_vals), 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ppp,
+ };
+
+ module_t *ppp_module;
+
+ proto_ppp = proto_register_protocol("Point-to-Point Protocol", "PPP", "ppp");
+ proto_register_field_array(proto_ppp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+/* subdissector code */
+ ppp_subdissector_table = register_dissector_table("ppp.protocol",
+ "PPP protocol", FT_UINT16, BASE_HEX);
+
+ register_dissector("ppp_hdlc", dissect_ppp_hdlc, proto_ppp);
+ register_dissector("ppp_lcp_options", dissect_lcp_options, proto_ppp);
+ register_dissector("ppp", dissect_ppp, proto_ppp);
+
+ /* Register the preferences for the ppp protocol */
+ ppp_module = prefs_register_protocol(proto_ppp, NULL);
+
+ prefs_register_enum_preference(ppp_module,
+ "fcs_type",
+ "PPP Frame Checksum Type",
+ "The type of PPP frame checksum (none, 16-bit, 32-bit)",
+ &ppp_fcs_decode,
+ fcs_options, FALSE);
+ prefs_register_bool_preference(ppp_module,
+ "decompress_vj",
+ "Decompress Van Jacobson-compressed frames",
+ "Whether Van Jacobson-compressed PPP frames should be decompressed",
+ &ppp_vj_decomp);
+ prefs_register_uint_preference(ppp_module,
+ "default_proto_id",
+ "PPPMuxCP Default PID",
+ "Default Protocol ID to be used for PPPMuxCP",
+ 16, &pppmux_def_prot_id);
+}
+
+void
+proto_reg_handoff_ppp(void)
+{
+ dissector_handle_t ppp_hdlc_handle, ppp_handle;
+
+ /*
+ * Get a handle for the CHDLC dissector.
+ */
+ chdlc_handle = find_dissector("chdlc");
+ data_handle = find_dissector("data");
+
+ ppp_hdlc_handle = find_dissector("ppp_hdlc");
+ ppp_handle = find_dissector("ppp");
+ dissector_add("wtap_encap", WTAP_ENCAP_PPP, ppp_hdlc_handle);
+ dissector_add("wtap_encap", WTAP_ENCAP_PPP_WITH_PHDR, ppp_hdlc_handle);
+ dissector_add("fr.ietf", NLPID_PPP, ppp_handle);
+ dissector_add("gre.proto", ETHERTYPE_PPP, ppp_hdlc_handle);
+}
+
+void
+proto_register_mp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_mp_frag_first,
+ { "First fragment", "mp.first", FT_BOOLEAN, 8,
+ TFS(&frag_truth), MP_FRAG_FIRST, "", HFILL }},
+
+ { &hf_mp_frag_last,
+ { "Last fragment", "mp.last", FT_BOOLEAN, 8,
+ TFS(&frag_truth), MP_FRAG_LAST, "", HFILL }},
+
+ { &hf_mp_sequence_num,
+ { "Sequence number", "mp.seq", FT_UINT24, BASE_DEC, NULL, 0x0,
+ "", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_mp,
+ &ett_mp_flags,
+ };
+
+ proto_mp = proto_register_protocol("PPP Multilink Protocol", "PPP MP", "mp");
+ proto_register_field_array(proto_mp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mp(void)
+{
+ dissector_handle_t mp_handle;
+
+ mp_handle = create_dissector_handle(dissect_mp, proto_mp);
+ dissector_add("ppp.protocol", PPP_MP, mp_handle);
+}
+
+void
+proto_register_lcp(void)
+{
+ static gint *ett[] = {
+ &ett_lcp,
+ &ett_lcp_options,
+ &ett_lcp_authprot_opt,
+ &ett_lcp_qualprot_opt,
+ &ett_lcp_fcs_alternatives_opt,
+ &ett_lcp_numbered_mode_opt,
+ &ett_lcp_callback_opt,
+ &ett_lcp_multilink_ep_disc_opt,
+ &ett_lcp_internationalization_opt,
+ };
+
+ proto_lcp = proto_register_protocol("PPP Link Control Protocol", "PPP LCP",
+ "lcp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_lcp(void)
+{
+ dissector_handle_t lcp_handle;
+
+ lcp_handle = create_dissector_handle(dissect_lcp, proto_lcp);
+ dissector_add("ppp.protocol", PPP_LCP, lcp_handle);
+
+ /*
+ * NDISWAN on Windows translates Ethernet frames from higher-level
+ * protocols into PPP frames to hand to the PPP driver, and translates
+ * PPP frames from the PPP driver to hand to the higher-level protocols.
+ *
+ * Apparently the PPP driver, on at least some versions of Windows,
+ * passes frames for internal-to-PPP protocols up through NDISWAN;
+ * the protocol type field appears to be passed through unchanged
+ * (unlike what's done with, for example, the protocol type field
+ * for IP, which is mapped from its PPP value to its Ethernet value).
+ *
+ * This means that we may see, on Ethernet captures, frames for
+ * protocols internal to PPP, so we register PPP_LCP with the
+ * "ethertype" dissector table as well as the PPP protocol dissector
+ * table.
+ */
+ dissector_add("ethertype", PPP_LCP, lcp_handle);
+}
+
+void
+proto_register_ipcp(void)
+{
+ static gint *ett[] = {
+ &ett_ipcp,
+ &ett_ipcp_options,
+ &ett_ipcp_ipaddrs_opt,
+ &ett_ipcp_compressprot_opt,
+ };
+
+ proto_ipcp = proto_register_protocol("PPP IP Control Protocol", "PPP IPCP",
+ "ipcp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ipcp(void)
+{
+ dissector_handle_t ipcp_handle;
+
+ ipcp_handle = create_dissector_handle(dissect_ipcp, proto_ipcp);
+ dissector_add("ppp.protocol", PPP_IPCP, ipcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_IPCP, ipcp_handle);
+}
+
+void
+proto_register_osicp(void)
+{
+ static gint *ett[] = {
+ &ett_osicp,
+ &ett_osicp_options,
+ &ett_osicp_align_npdu_opt,
+ };
+
+ proto_osicp = proto_register_protocol("PPP OSI Control Protocol", "PPP OSICP",
+ "osicp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_osicp(void)
+{
+ dissector_handle_t osicp_handle;
+
+ osicp_handle = create_dissector_handle(dissect_osicp, proto_osicp);
+ dissector_add("ppp.protocol", PPP_OSICP, osicp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_OSICP, osicp_handle);
+}
+
+void
+proto_register_ccp(void)
+{
+ static gint *ett[] = {
+ &ett_ccp,
+ &ett_ccp_options,
+ &ett_ccp_stac_opt,
+ &ett_ccp_mppc_opt,
+ &ett_ccp_bsdcomp_opt,
+ &ett_ccp_lzsdcp_opt,
+ &ett_ccp_mvrca_opt,
+ &ett_ccp_deflate_opt,
+ };
+
+ proto_ccp = proto_register_protocol("PPP Compression Control Protocol",
+ "PPP CCP", "ccp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ccp(void)
+{
+ dissector_handle_t ccp_handle;
+
+ ccp_handle = create_dissector_handle(dissect_ccp, proto_ccp);
+ dissector_add("ppp.protocol", PPP_CCP, ccp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_CCP, ccp_handle);
+}
+
+void
+proto_register_cbcp(void)
+{
+ static gint *ett[] = {
+ &ett_cbcp,
+ &ett_cbcp_options,
+ &ett_cbcp_callback_opt,
+ &ett_cbcp_callback_opt_addr
+ };
+
+ proto_cbcp = proto_register_protocol("PPP Callback Control Protocol",
+ "PPP CBCP", "cbcp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_cbcp(void)
+{
+ dissector_handle_t cbcp_handle;
+
+ cbcp_handle = create_dissector_handle(dissect_cbcp, proto_cbcp);
+ dissector_add("ppp.protocol", PPP_CBCP, cbcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_CBCP, cbcp_handle);
+}
+
+void
+proto_register_bacp(void)
+{
+ static gint *ett[] = {
+ &ett_bacp,
+ &ett_bacp_options,
+ &ett_bacp_favored_peer_opt
+ };
+
+ proto_bacp = proto_register_protocol("PPP Bandwidth Allocation Control Protocol",
+ "PPP BACP", "bacp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_bacp(void)
+{
+ dissector_handle_t bacp_handle;
+
+ bacp_handle = create_dissector_handle(dissect_bacp, proto_bacp);
+ dissector_add("ppp.protocol", PPP_BACP, bacp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_BACP, bacp_handle);
+}
+
+void
+proto_register_bap(void)
+{
+ static gint *ett[] = {
+ &ett_bap,
+ &ett_bap_options,
+ &ett_bap_link_type_opt,
+ &ett_bap_phone_delta_opt,
+ &ett_bap_phone_delta_subopt,
+ &ett_bap_call_status_opt
+ };
+
+ proto_bap = proto_register_protocol("PPP Bandwidth Allocation Protocol",
+ "PPP BAP", "bap");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_bap(void)
+{
+ dissector_handle_t bap_handle;
+
+ bap_handle = create_dissector_handle(dissect_bap, proto_bap);
+ dissector_add("ppp.protocol", PPP_BAP, bap_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_BAP, bap_handle);
+}
+
+void
+proto_register_comp_data(void)
+{
+ static gint *ett[] = {
+ &ett_comp_data
+ };
+
+ proto_comp_data = proto_register_protocol("PPP Compressed Datagram",
+ "PPP Comp", "comp_data");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_comp_data(void)
+{
+ dissector_handle_t comp_data_handle;
+
+ comp_data_handle = create_dissector_handle(dissect_comp_data,
+ proto_comp_data);
+ dissector_add("ppp.protocol", PPP_COMP, comp_data_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_COMP, comp_data_handle);
+}
+
+void
+proto_register_pap(void)
+{
+ static gint *ett[] = {
+ &ett_pap,
+ &ett_pap_data,
+ &ett_pap_peer_id,
+ &ett_pap_password,
+ &ett_pap_message,
+ };
+
+ proto_pap = proto_register_protocol("PPP Password Authentication Protocol", "PPP PAP",
+ "pap");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pap(void)
+{
+ dissector_handle_t pap_handle;
+
+ pap_handle = create_dissector_handle(dissect_pap, proto_pap);
+ dissector_add("ppp.protocol", PPP_PAP, pap_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_PAP, pap_handle);
+}
+
+void
+proto_register_chap(void)
+{
+ static gint *ett[] = {
+ &ett_chap,
+ &ett_chap_data,
+ &ett_chap_value,
+ &ett_chap_name,
+ &ett_chap_message,
+ };
+
+ proto_chap = proto_register_protocol("PPP Challenge Handshake Authentication Protocol", "PPP CHAP",
+ "chap");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_chap(void)
+{
+ dissector_handle_t chap_handle;
+
+ chap_handle = create_dissector_handle(dissect_chap, proto_chap);
+ dissector_add("ppp.protocol", PPP_CHAP, chap_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_CHAP, chap_handle);
+}
+
+void
+proto_register_pppmuxcp(void)
+{
+ static gint *ett[] = {
+ &ett_pppmuxcp,
+ &ett_pppmuxcp_options,
+ };
+
+ proto_pppmuxcp = proto_register_protocol("PPPMux Control Protocol",
+ "PPP PPPMuxCP",
+ "pppmuxcp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_pppmuxcp(void)
+{
+ dissector_handle_t muxcp_handle;
+
+ muxcp_handle = create_dissector_handle(dissect_pppmuxcp, proto_pppmuxcp);
+ dissector_add("ppp.protocol", PPP_MUXCP, muxcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_MUXCP, muxcp_handle);
+}
+
+
+void
+proto_register_pppmux(void)
+{
+ static gint *ett[] = {
+ &ett_pppmux,
+ &ett_pppmux_subframe,
+ &ett_pppmux_subframe_hdr,
+ &ett_pppmux_subframe_flags,
+ &ett_pppmux_subframe_info,
+ };
+
+ proto_pppmux = proto_register_protocol("PPP Multiplexing",
+ "PPP PPPMux",
+ "pppmux");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pppmux(void)
+{
+ dissector_handle_t pppmux_handle;
+
+ pppmux_handle = create_dissector_handle(dissect_pppmux, proto_pppmux);
+ dissector_add("ppp.protocol", PPP_MUX, pppmux_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_MUX, pppmux_handle);
+}
+
+void
+proto_register_mplscp(void)
+{
+ static gint *ett[] = {
+ &ett_mplscp,
+ &ett_mplscp_options,
+ };
+
+ proto_mplscp = proto_register_protocol("PPP MPLS Control Protocol",
+ "PPP MPLSCP", "mplscp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_mplscp(void)
+{
+ dissector_handle_t mplscp_handle;
+
+ mplscp_handle = create_dissector_handle(dissect_mplscp, proto_mplscp);
+ dissector_add("ppp.protocol", PPP_MPLSCP, mplscp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_MPLSCP, mplscp_handle);
+}
+
+void
+proto_register_cdpcp(void)
+{
+ static gint *ett[] = {
+ &ett_cdpcp,
+ &ett_cdpcp_options,
+ };
+
+ proto_cdpcp = proto_register_protocol("PPP CDP Control Protocol",
+ "PPP CDPCP", "cdpcp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_cdpcp(void)
+{
+ dissector_handle_t cdpcp_handle;
+
+ cdpcp_handle = create_dissector_handle(dissect_cdpcp, proto_cdpcp);
+ dissector_add("ppp.protocol", PPP_CDPCP, cdpcp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_CDPCP, cdpcp_handle);
+}
+
+void
+proto_register_ipv6cp(void)
+{
+ static gint *ett[] = {
+ &ett_ipv6cp,
+ &ett_ipv6cp_options,
+ &ett_ipv6cp_if_id_opt,
+ &ett_ipv6cp_compressprot_opt,
+ };
+
+ proto_ipv6cp = proto_register_protocol("PPP IPv6 Control Protocol",
+ "PPP IPV6CP", "ipv6cp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ipv6cp(void)
+{
+ dissector_handle_t ipv6cp_handle;
+
+ ipv6cp_handle = create_dissector_handle(dissect_ipv6cp, proto_ipv6cp);
+ dissector_add("ppp.protocol", PPP_IPV6CP, ipv6cp_handle);
+
+ /*
+ * See above comment about NDISWAN for an explanation of why we're
+ * registering with the "ethertype" dissector table.
+ */
+ dissector_add("ethertype", PPP_IPV6CP, ipv6cp_handle);
+}
diff --git a/epan/dissectors/packet-ppp.h b/epan/dissectors/packet-ppp.h
new file mode 100644
index 0000000000..900f209199
--- /dev/null
+++ b/epan/dissectors/packet-ppp.h
@@ -0,0 +1,44 @@
+/* packet-ppp.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_PPP_H__
+#define __PACKET_PPP_H__
+
+/* PPP options */
+extern gboolean ppp_vj_decomp;/* FALSE = No VJ header decompression,
+ TRUE = Decompress VJ */
+void capture_ppp_hdlc(const guchar *, int, int, packet_counts *);
+
+tvbuff_t *decode_fcs(tvbuff_t *tvb, proto_tree *fh_tree, int fcs_decode, int proto_offset);
+
+/*
+ * Used by the GTP dissector as well.
+ */
+extern const value_string ppp_vals[];
+
+/*
+ * Used by CHDLC dissector as well.
+ */
+extern const enum_val_t fcs_options[];
+
+#endif
diff --git a/epan/dissectors/packet-pppoe.c b/epan/dissectors/packet-pppoe.c
new file mode 100644
index 0000000000..d1f33240fc
--- /dev/null
+++ b/epan/dissectors/packet-pppoe.c
@@ -0,0 +1,309 @@
+/* packet-pppoe.c
+ * Routines for PPP Over Ethernet (PPPoE) packet disassembly (RFC2516)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "etypes.h"
+
+static int proto_pppoed = -1;
+
+static gint ett_pppoed = -1;
+static gint ett_pppoed_tags = -1;
+
+static int proto_pppoes = -1;
+
+static dissector_handle_t ppp_handle;
+
+/* For lack of a better source, I made up the following defines. -jsj */
+
+#define PPPOE_CODE_SESSION 0x00
+#define PPPOE_CODE_PADO 0x7
+#define PPPOE_CODE_PADI 0x9
+#define PPPOE_CODE_PADR 0x19
+#define PPPOE_CODE_PADS 0x65
+#define PPPOE_CODE_PADT 0xa7
+
+#define PPPOE_TAG_EOL 0x0000
+#define PPPOE_TAG_SVC_NAME 0x0101
+#define PPPOE_TAG_AC_NAME 0x0102
+#define PPPOE_TAG_HOST_UNIQ 0x0103
+#define PPPOE_TAG_AC_COOKIE 0x0104
+#define PPPOE_TAG_VENDOR 0x0105
+#define PPPOE_TAG_RELAY_ID 0x0110
+#define PPPOE_TAG_SVC_ERR 0x0201
+#define PPPOE_TAG_AC_ERR 0x0202
+#define PPPOE_TAG_GENERIC_ERR 0x0203
+
+static gchar *
+pppoecode_to_str(guint8 codetype, const char *fmt) {
+ static const value_string code_vals[] = {
+ {PPPOE_CODE_SESSION, "Session Data" },
+ {PPPOE_CODE_PADO, "Active Discovery Offer (PADO)" },
+ {PPPOE_CODE_PADI, "Active Discovery Initiation (PADI)" },
+ {PPPOE_CODE_PADR, "Active Discovery Request (PADR)" },
+ {PPPOE_CODE_PADS, "Active Discovery Session-confirmation (PADS)"},
+ {PPPOE_CODE_PADT, "Active Discovery Terminate (PADT)" },
+ {0, NULL } };
+
+ return val_to_str(codetype, code_vals, fmt);
+}
+
+static gchar *
+pppoetag_to_str(guint16 tag_type, const char *fmt) {
+ static const value_string code_vals[] = {
+ {PPPOE_TAG_EOL, "End-Of-List" },
+ {PPPOE_TAG_SVC_NAME, "Service-Name" },
+ {PPPOE_TAG_AC_NAME, "AC-Name" },
+ {PPPOE_TAG_HOST_UNIQ, "Host-Uniq" },
+ {PPPOE_TAG_AC_COOKIE, "AC-Cookie" },
+ {PPPOE_TAG_VENDOR, "Vendor-Specific" },
+ {PPPOE_TAG_RELAY_ID, "Relay-Session-Id" },
+ {PPPOE_TAG_SVC_ERR, "Service-Name-Error"},
+ {PPPOE_TAG_AC_ERR, "AC-System-Error" },
+ {PPPOE_TAG_GENERIC_ERR,"Generic-Error" },
+ {0, NULL } };
+
+ return val_to_str(tag_type, code_vals, fmt);
+}
+
+
+static void
+dissect_pppoe_tags(tvbuff_t *tvb, int offset, proto_tree *tree, int payload_length) {
+
+ guint16 poe_tag;
+ guint16 poe_tag_length;
+ int tagstart;
+
+ proto_tree *pppoe_tree;
+ proto_item *ti;
+
+ /* Start Decoding Here. */
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb,offset,payload_length,"PPPoE Tags");
+ pppoe_tree = proto_item_add_subtree(ti, ett_pppoed_tags);
+
+ tagstart = offset;
+ while(tagstart <= payload_length-2 ) {
+
+ poe_tag = tvb_get_ntohs(tvb, tagstart);
+ poe_tag_length = tvb_get_ntohs(tvb, tagstart + 2);
+
+ proto_tree_add_text(pppoe_tree, tvb,tagstart,4,
+ "Tag: %s", pppoetag_to_str(poe_tag,"Unknown (0x%02x)"));
+
+ switch(poe_tag) {
+ case PPPOE_TAG_SVC_NAME:
+ case PPPOE_TAG_AC_NAME:
+ case PPPOE_TAG_SVC_ERR:
+ case PPPOE_TAG_AC_ERR:
+ case PPPOE_TAG_GENERIC_ERR:
+ /* tag value should be interpreted as a utf-8 unterminated string.*/
+ if(poe_tag_length > 0 ) {
+ /* really should do some limit checking here. :( */
+ proto_tree_add_text(pppoe_tree, tvb,tagstart+4,poe_tag_length,
+ " String Data: %s",
+ tvb_format_text(tvb, tagstart+4,poe_tag_length ));
+ }
+ break;
+ default:
+ if(poe_tag_length > 0 ) {
+ proto_tree_add_text(pppoe_tree, tvb,tagstart+4,poe_tag_length,
+ " Binary Data: (%d bytes)", poe_tag_length );
+ }
+ }
+
+ if (poe_tag == PPPOE_TAG_EOL) break;
+
+ tagstart += 4 + poe_tag_length;
+ }
+ }
+}
+
+static void
+dissect_pppoed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ guint8 pppoe_ver_type;
+ guint8 pppoe_ver;
+ guint8 pppoe_type;
+ guint8 pppoe_code;
+ guint16 pppoe_session_id;
+ guint16 pppoe_length;
+
+ proto_tree *pppoe_tree;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "PPPoED");
+ }
+ if (check_col(pinfo->cinfo,COL_INFO)) {
+ col_clear(pinfo->cinfo,COL_INFO);
+ }
+
+ /* Start Decoding Here. */
+ pppoe_ver_type = tvb_get_guint8(tvb, 0);
+ pppoe_ver = (pppoe_ver_type >> 4) & 0x0f;
+ pppoe_type = pppoe_ver_type & 0x0f;
+ pppoe_code = tvb_get_guint8(tvb, 1);
+
+ if (check_col(pinfo->cinfo,COL_INFO)) {
+ col_add_fstr(pinfo->cinfo,COL_INFO,pppoecode_to_str(pppoe_code,"Unknown code (0x%02x)"));
+ }
+
+ pppoe_session_id = tvb_get_ntohs(tvb, 2);
+ pppoe_length = tvb_get_ntohs(tvb, 4);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_pppoed, tvb,0,
+ pppoe_length+6, FALSE);
+ pppoe_tree = proto_item_add_subtree(ti, ett_pppoed);
+ proto_tree_add_text(pppoe_tree, tvb,0,1,
+ "Version: %u", pppoe_ver);
+ proto_tree_add_text(pppoe_tree, tvb,0,1,
+ "Type: %u", pppoe_type);
+ proto_tree_add_text(pppoe_tree, tvb,1,1,
+ "Code: %s", pppoecode_to_str(pppoe_code,"Unknown (0x%02x)"));
+ proto_tree_add_text(pppoe_tree, tvb,2,2,
+ "Session ID: %04x", pppoe_session_id);
+ proto_tree_add_text(pppoe_tree, tvb,4,2,
+ "Payload Length: %u", pppoe_length);
+ }
+ dissect_pppoe_tags(tvb,6,tree,6+pppoe_length);
+}
+
+void
+proto_register_pppoed(void)
+{
+ static gint *ett[] = {
+ &ett_pppoed,
+ &ett_pppoed_tags,
+ };
+
+ proto_pppoed = proto_register_protocol("PPP-over-Ethernet Discovery",
+ "PPPoED", "pppoed");
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pppoed(void)
+{
+ dissector_handle_t pppoed_handle;
+
+ pppoed_handle = create_dissector_handle(dissect_pppoed, proto_pppoed);
+ dissector_add("ethertype", ETHERTYPE_PPPOED, pppoed_handle);
+}
+
+static void
+dissect_pppoes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ guint8 pppoe_ver_type;
+ guint8 pppoe_ver;
+ guint8 pppoe_type;
+ guint8 pppoe_code;
+ guint16 pppoe_session_id;
+ guint16 pppoe_length;
+ gint length, reported_length;
+
+ proto_tree *pppoe_tree;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo,COL_PROTOCOL, "PPPoES");
+ }
+ if (check_col(pinfo->cinfo,COL_INFO)) {
+ col_clear(pinfo->cinfo,COL_INFO);
+ }
+
+ /* Start Decoding Here. */
+ pppoe_ver_type = tvb_get_guint8(tvb, 0);
+ pppoe_ver = (pppoe_ver_type >> 4) & 0x0f;
+ pppoe_type = pppoe_ver_type & 0x0f;
+ pppoe_code = tvb_get_guint8(tvb, 1);
+
+ if (check_col(pinfo->cinfo,COL_INFO)) {
+ col_add_fstr(pinfo->cinfo,COL_INFO,
+ pppoecode_to_str(pppoe_code,"Unknown code (0x%02x)"));
+ }
+
+ pppoe_session_id = tvb_get_ntohs(tvb, 2);
+ pppoe_length = tvb_get_ntohs(tvb, 4);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_pppoes, tvb,0,
+ 6, FALSE);
+ pppoe_tree = proto_item_add_subtree(ti, ett_pppoed);
+ proto_tree_add_text(pppoe_tree, tvb,0,1,
+ "Version: %u", pppoe_ver);
+ proto_tree_add_text(pppoe_tree, tvb,0,1,
+ "Type: %u", pppoe_type);
+ proto_tree_add_text(pppoe_tree, tvb,1,1,
+ "Code: %s", pppoecode_to_str(pppoe_code,"Unknown (0x%02x)"));
+ proto_tree_add_text(pppoe_tree, tvb,2,2,
+ "Session ID: %04x", pppoe_session_id);
+ proto_tree_add_text(pppoe_tree, tvb,4,2,
+ "Payload Length: %u", pppoe_length);
+ }
+ /* dissect_ppp is apparently done as a 'top level' dissector,
+ * so this doesn't work:
+ * dissect_ppp(pd,offset+6,pinfo->fd,tree);
+ * Im gonna try fudging it.
+ */
+ length = tvb_length_remaining(tvb, 6);
+ reported_length = tvb_reported_length_remaining(tvb, 6);
+ g_assert(length >= 0);
+ g_assert(reported_length >= 0);
+ if (length > reported_length)
+ length = reported_length;
+ if ((guint)length > pppoe_length)
+ length = pppoe_length;
+ if ((guint)reported_length > pppoe_length)
+ reported_length = pppoe_length;
+ next_tvb = tvb_new_subset(tvb,6,length,reported_length);
+ call_dissector(ppp_handle,next_tvb,pinfo,tree);
+}
+void
+proto_register_pppoes(void)
+{
+ proto_pppoes = proto_register_protocol("PPP-over-Ethernet Session",
+ "PPPoES", "pppoes");
+}
+
+void
+proto_reg_handoff_pppoes(void)
+{
+ dissector_handle_t pppoes_handle;
+
+ pppoes_handle = create_dissector_handle(dissect_pppoes, proto_pppoes);
+ dissector_add("ethertype", ETHERTYPE_PPPOES, pppoes_handle);
+
+ /*
+ * Get a handle for the PPP dissector.
+ */
+ ppp_handle = find_dissector("ppp");
+}
diff --git a/epan/dissectors/packet-pptp.c b/epan/dissectors/packet-pptp.c
new file mode 100644
index 0000000000..f4db883388
--- /dev/null
+++ b/epan/dissectors/packet-pptp.c
@@ -0,0 +1,839 @@
+/* packet-pptp.c
+ * Routines for the Point-to-Point Tunnelling Protocol (PPTP) (RFC 2637)
+ * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+
+static int proto_pptp = -1;
+static int hf_pptp_message_type = -1;
+
+static gint ett_pptp = -1;
+
+static dissector_handle_t data_handle;
+
+#define TCP_PORT_PPTP 1723
+
+#define MAGIC_COOKIE 0x1A2B3C4D
+
+static const value_string msgtype_vals[] = {
+ { 1, "Control Message" },
+ { 2, "Management Message" },
+ { 0, NULL }
+};
+
+#define NUM_FRAME_TYPES 4
+#define frametype2str(t) \
+ ((t < NUM_FRAME_TYPES) ? frametypestr[t] : "Unknown framing type")
+
+static const char *frametypestr[NUM_FRAME_TYPES] = {
+ "Unknown framing type",
+ "Asynchronous Framing supported",
+ "Synchronous Framing supported",
+ "Either Framing supported"
+};
+
+#define NUM_BEARER_TYPES 4
+#define bearertype2str(t) \
+ ((t < NUM_BEARER_TYPES) ? bearertypestr[t] : "Unknown bearer type")
+
+static const char *bearertypestr[NUM_BEARER_TYPES] = {
+ "Unknown bearer type",
+ "Analog access supported",
+ "Digital access supported",
+ "Either access supported"
+};
+
+#define NUM_CNTRLRESULT_TYPES 6
+#define cntrlresulttype2str(t) \
+ ((t < NUM_CNTRLRESULT_TYPES) ? cntrlresulttypestr[t] : "Unknown Start-Control-connection-Reply result code")
+
+static const char *cntrlresulttypestr[NUM_CNTRLRESULT_TYPES] = {
+ "Unknown Start-Control-connection-Reply result code",
+ "Successful channel establishment",
+ "General error",
+ "Command channel already exists",
+ "Requester not authorized",
+ "Protocol version not supported"
+};
+
+#define NUM_ERROR_TYPES 7
+#define errortype2str(t) \
+ ((t < NUM_ERROR_TYPES) ? errortypestr[t] : "Unknown general error code")
+
+static const char *errortypestr[NUM_ERROR_TYPES] = {
+ "None",
+ "Not-Connected",
+ "Bad-Format",
+ "Bad-Value",
+ "No-Resource",
+ "Bad-Call ID",
+ "PAC-Error"
+};
+
+#define NUM_REASON_TYPES 4
+#define reasontype2str(t) \
+ ((t < NUM_REASON_TYPES) ? reasontypestr[t] : "Unknown Stop-Control-Connection-Request reason code")
+
+static const char *reasontypestr[NUM_REASON_TYPES] = {
+ "Unknown Stop-Control-Connection-Request reason code",
+ "None",
+ "Stop-Protocol",
+ "Stop-Local-Shutdown"
+};
+
+#define NUM_STOPRESULT_TYPES 3
+#define stopresulttype2str(t) \
+ ((t < NUM_STOPRESULT_TYPES) ? stopresulttypestr[t] : "Unknown Stop-Control-Connection-Reply result code")
+
+static const char *stopresulttypestr[NUM_STOPRESULT_TYPES] = {
+ "Unknown Stop-Control-Connection-Reply result code",
+ "OK",
+ "General error"
+};
+
+#define NUM_ECHORESULT_TYPES 3
+#define echoresulttype2str(t) \
+ ((t < NUM_ECHORESULT_TYPES) ? echoresulttypestr[t] : "Unknown Echo-Reply result code")
+
+static const char *echoresulttypestr[NUM_ECHORESULT_TYPES] = {
+ "Unknown Echo-Reply result code",
+ "OK",
+ "General error"
+};
+
+#define NUM_OUTRESULT_TYPES 8
+#define outresulttype2str(t) \
+ ((t < NUM_OUTRESULT_TYPES) ? outresulttypestr[t] : "Unknown Outgoing-Call-Reply result code")
+
+static const char *outresulttypestr[NUM_OUTRESULT_TYPES] = {
+ "Unknown Outgoing-Call-Reply result code",
+ "Connected",
+ "General Error",
+ "No Carrier",
+ "Busy",
+ "No Dial Tone",
+ "Time-out",
+ "Do Not Accept"
+};
+
+#define NUM_INRESULT_TYPES 4
+#define inresulttype2str(t) \
+ ((t < NUM_INRESULT_TYPES) ? inresulttypestr[t] : "Unknown Incoming-Call-Reply result code")
+
+static const char *inresulttypestr[NUM_INRESULT_TYPES] = {
+ "Unknown Incoming-Call-Reply result code",
+ "Connect",
+ "General Error",
+ "Do Not Accept"
+};
+
+#define NUM_DISCRESULT_TYPES 5
+#define discresulttype2str(t) \
+ ((t < NUM_DISCRESULT_TYPES) ? discresulttypestr[t] : "Unknown Call-Disconnect-Notify result code")
+
+static const char *discresulttypestr[NUM_DISCRESULT_TYPES] = {
+ "Unknown Call-Disconnect-Notify result code",
+ "Lost Carrier",
+ "General Error",
+ "Admin Shutdown",
+ "Request"
+};
+
+static void dissect_unknown(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_cntrl_req(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_cntrl_reply(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_stop_req(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_stop_reply(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_echo_req(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_echo_reply(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_out_req(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_out_reply(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_in_req(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_in_reply(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_in_connected(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_clear_req(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_disc_notify(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_error_notify(tvbuff_t *, int, packet_info *, proto_tree *);
+static void dissect_set_link(tvbuff_t *, int, packet_info *, proto_tree *);
+
+#define NUM_CNTRL_TYPES 16
+#define cntrltype2str(t) \
+ ((t < NUM_CNTRL_TYPES) ? strfuncs[t].str : "UNKNOWN-CONTROL-TYPE")
+
+static struct strfunc {
+ const char * str;
+ void (*func)(tvbuff_t *, int, packet_info *, proto_tree *);
+} strfuncs[NUM_CNTRL_TYPES] = {
+ {"Unknown control type", dissect_unknown },
+ {"Start-Control-Connection-Request", dissect_cntrl_req },
+ {"Start-Control-Connection-Reply", dissect_cntrl_reply },
+ {"Stop-Control-Connection-Request", dissect_stop_req },
+ {"Stop-Control-Connection-Reply", dissect_stop_reply },
+ {"Echo-Request", dissect_echo_req },
+ {"Echo-Reply", dissect_echo_reply },
+ {"Outgoing-Call-Request", dissect_out_req },
+ {"Outgoing-Call-Reply", dissect_out_reply },
+ {"Incoming-Call-Request", dissect_in_req },
+ {"Incoming-Call-Reply", dissect_in_reply },
+ {"Incoming-Call-Connected", dissect_in_connected },
+ {"Call-Clear-Request", dissect_clear_req },
+ {"Call-Disconnect-Notify", dissect_disc_notify },
+ {"WAN-Error-Notify", dissect_error_notify },
+ {"Set-Link-Info", dissect_set_link }
+};
+
+/*
+ * Length of host name and vendor name strings in control requests and
+ * replies.
+ */
+#define HOSTLEN 64
+#define VENDORLEN 64
+
+/*
+ * Length of phone number(s) and subaddress in call requests.
+ */
+#define PHONELEN 64
+#define SUBADDRLEN 64
+
+/*
+ * Length of statistics in a Call-Disconnect-Notify message.
+ */
+#define STATSLEN 128
+
+static void
+dissect_pptp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint16 len;
+ guint16 cntrl_type;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPTP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ len = tvb_get_ntohs(tvb, offset);
+ cntrl_type = tvb_get_ntohs(tvb, offset + 8);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", cntrltype2str(cntrl_type));
+
+ if (tree) {
+ guint32 cookie;
+ proto_item * ti;
+ proto_tree * pptp_tree;
+
+ ti = proto_tree_add_item(tree, proto_pptp, tvb, offset, len, FALSE);
+ pptp_tree = proto_item_add_subtree(ti, ett_pptp);
+
+ proto_tree_add_text(pptp_tree, tvb, offset, 2, "Length: %u", len);
+ offset += 2;
+
+ proto_tree_add_item(pptp_tree, hf_pptp_message_type, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ cookie = tvb_get_ntohl(tvb, offset);
+
+ if (cookie == MAGIC_COOKIE)
+ proto_tree_add_text(pptp_tree, tvb, offset, 4,
+ "Cookie: %#08x (correct)", cookie);
+ else
+ proto_tree_add_text(pptp_tree, tvb, offset, 4,
+ "Cookie: %#08x (incorrect)", cookie);
+ offset += 4;
+
+ proto_tree_add_text(pptp_tree, tvb, offset, 2,
+ "Control type: %s (%u)", cntrltype2str(cntrl_type), cntrl_type);
+ offset += 2;
+
+ proto_tree_add_text(pptp_tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ if (cntrl_type < NUM_CNTRL_TYPES)
+ ( *(strfuncs[cntrl_type].func))(tvb, offset, pinfo, pptp_tree);
+ else
+ call_dissector(data_handle,tvb_new_subset(tvb, offset, -1, -1), pinfo, pptp_tree);
+ }
+}
+
+static void
+dissect_unknown(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ call_dissector(data_handle,tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+}
+
+static void
+dissect_cntrl_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint8 major_ver;
+ guint8 minor_ver;
+ guint32 frame;
+ guint32 bearer;
+ guint8 host[HOSTLEN+1];
+ guint8 vendor[VENDORLEN+1];
+
+ major_ver = tvb_get_guint8(tvb, offset);
+ minor_ver = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Protocol version: %u.%u", major_ver, minor_ver);
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ frame = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Framing capabilities: %s (%u)", frametype2str(frame), frame);
+ offset += 4;
+
+ bearer = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Maximum channels: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Firmware revision: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ tvb_memcpy(tvb, host, offset, HOSTLEN);
+ host[HOSTLEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, HOSTLEN,
+ "Hostname: %s", host);
+ offset += HOSTLEN;
+
+ tvb_memcpy(tvb, vendor, offset, VENDORLEN);
+ vendor[VENDORLEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, VENDORLEN,
+ "Vendor: %s", vendor);
+}
+
+static void
+dissect_cntrl_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint8 major_ver;
+ guint8 minor_ver;
+ guint8 result;
+ guint8 error;
+ guint32 frame;
+ guint32 bearer;
+ guint8 host[HOSTLEN+1];
+ guint8 vendor[VENDORLEN+1];
+
+ major_ver = tvb_get_guint8(tvb, offset);
+ minor_ver = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Protocol version: %u.%u", major_ver, minor_ver);
+ offset += 2;
+
+ result = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Result: %s (%u)", cntrlresulttype2str(result), result);
+ offset += 1;
+
+ error = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Error: %s (%u)", errortype2str(error), error);
+ offset += 1;
+
+ frame = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Framing capabilities: %s (%u)", frametype2str(frame), frame);
+ offset += 4;
+
+ bearer = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Maximum channels: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Firmware revision: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ tvb_memcpy(tvb, host, offset, HOSTLEN);
+ host[HOSTLEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, HOSTLEN,
+ "Hostname: %s", host);
+ offset += HOSTLEN;
+
+ tvb_memcpy(tvb, vendor, offset, VENDORLEN);
+ vendor[VENDORLEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, VENDORLEN,
+ "Vendor: %s", vendor);
+}
+
+static void
+dissect_stop_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint8 reason;
+
+ reason = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Reason: %s (%u)", reasontype2str(reason), reason);
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Reserved: %u", tvb_get_guint8(tvb, offset));
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+}
+
+static void
+dissect_stop_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint8 result;
+ guint8 error;
+
+ result = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Result: %s (%u)", stopresulttype2str(result), result);
+ offset += 1;
+
+ error = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Error: %s (%u)", errortype2str(error), error);
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+}
+
+static void
+dissect_echo_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Identifier: %u", tvb_get_ntohl(tvb, offset));
+}
+
+static void
+dissect_echo_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint8 result;
+ guint8 error;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Identifier: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ result = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Result: %s (%u)", echoresulttype2str(result), result);
+ offset += 1;
+
+ error = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, sizeof(error),
+ "Error: %s (%u)", errortype2str(error), error);
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+}
+
+static void
+dissect_out_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 bearer;
+ guint32 frame;
+ guint8 phone[PHONELEN+1];
+ guint8 subaddr[SUBADDRLEN+1];
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Call Serial Number: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Minimum BPS: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Maximum BPS: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ bearer = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
+ offset += 4;
+
+ frame = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Framing capabilities: %s (%u)", frametype2str(frame), frame);
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Receive window size: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Processing delay: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Phone number length: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ tvb_memcpy(tvb, phone, offset, PHONELEN);
+ phone[PHONELEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, PHONELEN,
+ "Phone number: %s", phone);
+ offset += PHONELEN;
+
+ tvb_memcpy(tvb, subaddr, offset, SUBADDRLEN);
+ subaddr[SUBADDRLEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, SUBADDRLEN,
+ "Subaddress: %s", subaddr);
+}
+
+static void
+dissect_out_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint8 result;
+ guint8 error;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ result = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Result: %s (%u)", outresulttype2str(result), result);
+ offset += 1;
+
+ error = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Error: %s (%u)", errortype2str(error), error);
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Cause code: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Connect speed: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Receive window size: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Processing delay: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Physical channel ID: %u", tvb_get_ntohl(tvb, offset));
+}
+
+static void
+dissect_in_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 bearer;
+ guint8 dialed[PHONELEN+1];
+ guint8 dialing[PHONELEN+1];
+ guint8 subaddr[SUBADDRLEN+1];
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Call serial number: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ bearer = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer);
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Physical channel ID: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Dialed number length: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Dialing number length: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ tvb_memcpy(tvb, dialing, offset, PHONELEN);
+ dialed[PHONELEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, PHONELEN,
+ "Dialed number: %s", dialed);
+ offset += PHONELEN;
+
+ tvb_memcpy(tvb, dialing, offset, PHONELEN);
+ dialing[PHONELEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, PHONELEN,
+ "Dialing number: %s", dialing);
+ offset += PHONELEN;
+
+ tvb_memcpy(tvb, subaddr, offset, SUBADDRLEN);
+ subaddr[SUBADDRLEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, SUBADDRLEN,
+ "Subaddress: %s", subaddr);
+}
+
+static void
+dissect_in_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint8 result;
+ guint8 error;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ result = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Result: %s (%u)", inresulttype2str(result), result);
+ offset += 1;
+
+ error = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Error: %s (%u)", errortype2str(error), error);
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Receive window size: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Processing delay: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+}
+
+static void
+dissect_in_connected(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint32 frame;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Connect speed: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Receive window size: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Processing delay: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ frame = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Framing capabilities: %s (%u)", frametype2str(frame), frame);
+}
+
+static void
+dissect_clear_req(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+}
+
+static void
+dissect_disc_notify(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint8 result;
+ guint8 error;
+ guint8 stats[STATSLEN+1];
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ result = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Result: %s (%u)", discresulttype2str(result), result);
+ offset += 1;
+
+ error = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Error: %s (%u)", errortype2str(error), error);
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Cause code: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ tvb_memcpy(tvb, stats, offset, STATSLEN);
+ stats[STATSLEN] = '\0';
+ proto_tree_add_text(tree, tvb, offset, STATSLEN,
+ "Call statistics: %s", stats);
+}
+
+static void
+dissect_error_notify(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "CRC errors: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Framing errors: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Hardware overruns: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Buffer overruns: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Time-out errors: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Alignment errors: %u", tvb_get_ntohl(tvb, offset));
+}
+
+static void
+dissect_set_link(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Peer's call ID: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Reserved: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Send ACCM: %#08x", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Recv ACCM: %#08x", tvb_get_ntohl(tvb, offset));
+}
+
+void
+proto_register_pptp(void)
+{
+ static gint *ett[] = {
+ &ett_pptp,
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_pptp_message_type,
+ { "Message type", "pptp.type",
+ FT_UINT16, BASE_DEC, VALS(msgtype_vals), 0x0,
+ "PPTP message type", HFILL }}
+ };
+
+ proto_pptp = proto_register_protocol("Point-to-Point Tunnelling Protocol",
+ "PPTP", "pptp");
+ proto_register_field_array(proto_pptp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_pptp(void)
+{
+ dissector_handle_t pptp_handle;
+
+ pptp_handle = create_dissector_handle(dissect_pptp, proto_pptp);
+ dissector_add("tcp.port", TCP_PORT_PPTP, pptp_handle);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-pres.c b/epan/dissectors/packet-pres.c
new file mode 100644
index 0000000000..61b421e285
--- /dev/null
+++ b/epan/dissectors/packet-pres.c
@@ -0,0 +1,1820 @@
+/* packet-pres.c
+*
+* Routine to dissect ISO 8823 OSI Presentation Protocol packets
+*
+* $Id$
+*
+* Yuriy Sidelnikov <YSidelnikov@hotmail.com>
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-pres.h"
+#include "packet-frame.h"
+#include "prefs.h"
+
+#include <epan/strutil.h>
+
+#include "asn1.h"
+#include "format-oid.h"
+
+#include "packet-ses.h"
+extern const value_string ses_vals[];
+
+/* pres header fields */
+static int proto_pres = -1;
+/* type of session envelop */
+static struct SESSION_DATA_STRUCTURE* session = NULL;
+static int hf_pres_rc_type = -1;
+static int hf_pres_ms_type = -1;
+static int hf_pres_seq_type = -1;
+static int hf_pres_protocol_version =-1;
+/* pres fields defining a sub tree */
+static gint ett_pres = -1;
+static gint ett_pres_param = -1;
+static gint ett_pres_rc = -1;
+static gint ett_pres_ms = -1;
+static gint ett_pres_itm = -1;
+
+/*
+----------------------------------------------------------------------------------------------------------*/
+static dissector_handle_t acse_handle = NULL;
+
+static int hf_pres_type = -1;
+static int hf_pres_length = -1;
+static int hf_value = -1;
+
+
+static int hf_cp_type_message_length = -1;
+
+static int hf_protocol_version = -1;
+static int hf_context_management = -1;
+static int hf_restoration = -1;
+
+
+static const value_string pres_vals[] =
+{
+ {PRES_CONNECTION_REQUEST_CONFIRM, "Connection request/confirm PDU" },
+ {PRES_CONNECTION_REFUSE, "Connection refuse PDU" },
+ {0, NULL }
+};
+
+static const value_string cr_vals[] =
+{
+ {MODE_SELECTOR, "Mode Selector"},
+ {SEQUENCE_TOP, "Sequence"},
+ {SET_TOP, "Set"},
+ {0, NULL}
+};
+
+static const value_string sequence_top_vals[] =
+{
+ {CALLED_PRESENTATION_SELECTOR, "Called presentation selector"},
+ {CALLING_PRESENTATION_SELECTOR, "Calling presentation selector"},
+ {PRESENTATION_CONTEXT_DEFINITION_LIST, "Presentation context definition list"},
+ {RESPONDING_PRESENTATION_SELECTOR, "Responding presentation selector"},
+ {PROTOCOL_VERSION, "Protocol version"},
+ {PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST, "Presentation context definition result list"},
+ {PRESENTATION_REQUIREMENTS,"Presentation requirements"},
+ {DEFAULT_CONTEXT_NAME,"Default context name"},
+ {USER_SESSION_REQUIREMENTS,"User session requirements"},
+ {DEFAULT_CONTEXT_RESULT,"Default context result"},
+ {PROVIDER_REASON,"Provider reason"},
+ {0, NULL}
+};
+static const value_string sequence_list_vals[] =
+{
+ {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
+ {ABSTRACT_SYNTAX_NAME,"Abstract syntax name"},
+ {TRANSFER_SYNTAX_NAMES,"Transfer syntax names"},
+ {0, NULL}
+};
+static const value_string sequence_list_result_vals[] =
+{
+ {PRESENTATION_RESULT,"Result"},
+ {PRESENTATION_RESULT_INTEGER,"Integer"},
+ {PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME,"Transfer syntax name"},
+ {0, NULL}
+};
+static const value_string presentation_context_definition_vals[] =
+{
+ {SEQUENCE, "Sequence"},
+ {0, NULL}
+};
+static const value_string sequence_list_result_values_vals[] =
+{
+ {PRESENTATION_RESULT_ACCEPTANCE,"Acceptance"},
+ {PRESENTATION_RESULT_USER_REJECTION,"User rejection"},
+ {PRESENTATION_RESULT_PROVIDER_REJECTION,"Provider rejection"},
+ {0, NULL}
+};
+static const value_string provider_reason_values_vals[] =
+{
+ {REASON_NOT_SPECIFIED,"Reason not specified"},
+ {TEMPORARY_CONGESTION,"Temporary congestion"},
+ {LOCAL_LIMIT_EXCEEDED,"Local limit exceeded"},
+ {CALLED_PRESENTATION_ADDRESS_UNKNOWN,"Called presentation address unknown"},
+ {PROTOCOL_VERSION_NOT_SUPPORTED,"Protocol version not supported"},
+ {DEFAULT_CONTEXT_NOT_SUPPORTED,"Default context not supported"},
+ {USER_DATA_NOT_READABLE,"User data not readable"},
+ {NO_PSAP_AVAILABLE,"No PSAP available"},
+ {0, NULL}
+};
+
+static const value_string user_data_values_vals[] =
+{
+ {SIMPLY_ENCODED_DATA,"Simply encoded data"},
+ {FULLY_ENCODED_DATA,"Fully encoded data "},
+ {0, NULL}
+};
+static const value_string presentation_data_values[] =
+{
+ {PRESENTATION_CONTEXT_IDENTIFIER,"Presentation context identifier"},
+ {SINGLE_ASN1_TYPE,"Single ASN.1 type"},
+ {OCTET_ALIGNED,"Octet aligned"},
+ {ARBITRARY,"Arbitrary"},
+ {DATA_BLOCK,"Data block"},
+ {0, NULL}
+};
+static const value_string provider_abort_values_vals[] =
+{
+ {PR_REASON_NOT_SPECIFIED,"Reason not specified"},
+ {UNRECOGNIZED_PDU,"Unrecognized ppdu"},
+ {UNEXPECTED_PDU,"Unexpected ppdu"},
+ {UNEXPECTED_SESSION_SERVICE_PRIMITIVE,"Unexpected session service primitive"},
+ {UNRECOGNIZED_PPDU_PARAMETER,"Unrecognized ppdu parameter"},
+ {UNEXPECTED_PPDU_PARAMETER,"Unexpected ppdu parameter"},
+ {INVALID_PPDU_PARAMETER_VALUE,"Invalid ppdu parameter value"},
+ {0, NULL}
+};
+static const value_string event_identifier_values_vals[] =
+{
+ {REASON_CP_PPDU,"cp PPDU"},
+ {REASON_CPA_PPDU,"cpa PPDU"},
+ {REASON_CPR_PPDU,"cpr PPDU"},
+ {REASON_ARU_PPDU,"aru PPDU"},
+ {REASON_ARP_PPDU,"arp PPDU"},
+ {REASON_AC_PPDU,"ac PPDU"},
+ {REASON_ACA_PPDU,"aca PPDU"},
+ {REASON_TD_PPDU,"td PPDU"},
+ {REASON_TTD_PPDU,"td PPDU"},
+ {REASON_TE_PPDU,"te PPDU"},
+ {REASON_TC_PPDU,"tc PPDU"},
+ {REASON_TCC_PPDU,"tcc PPDU"},
+ {REASON_RS_PPDU,"rs PPDU"},
+ {REASON_RSA_PPDU,"rsa PPDU"},
+ {S_RELEASE_INDICATION,"s release indication"},
+ {S_RELEASE_CONFIRM,"s release confirm"},
+ {S_TOKEN_GIVE_INDICATION,"s token give indication"},
+ {S_TOKEN_PLEASE_INDICATION,"s token please indication"},
+ {S_CONTROL_GIVE_INDICATION,"s control give indication"},
+ {S_SYNC_MINOR_INDICATION,"s sync minor indication"},
+ {S_SYNC_MINOR_CONFIRM,"s sync minor confirm"},
+ {S_SYNC_MAJOR_INDICATION,"s sync major indication"},
+ {S_SYNC_MAJOR_CONFIRM,"s sync major confirm"},
+ {S_P_EXCEPTION_REPORT_INDICATION,"s p exception report indication"},
+ {S_U_EXCEPTION_REPORT_INDICATION,"s u exception report indication"},
+ {S_ACTIVITY_START_INDICATION,"s activity start indication"},
+ {S_ACTIVITY_RESUME_INDICATION,"s activity resume indication"},
+ {S_ACTIVITY_INTERRUPT_INDICATION,"s activity interrupt indication"},
+ {S_ACTIVITY_INTERRUPT_CONFIRM,"s activity interrupt confirm"},
+ {S_ACTIVITY_DISCARD_INDICATION,"s activity discard indication"},
+ {S_ACTIVITY_DISCARD_CONFIRM,"s activity discard confirm"},
+ {S_ACTIVITY_END_INDICATION,"s activity end indication"},
+ {S_ACTIVITY_END_CONFIRM,"s activity end confirm"},
+ {0, NULL}
+};
+/* pointers for acse dissector */
+proto_tree *global_tree = NULL;
+packet_info *global_pinfo = NULL;
+/* dissector for data */
+static dissector_handle_t data_handle;
+
+static void
+call_acse_dissector(tvbuff_t *tvb, gint offset, gint param_len,
+ packet_info *pinfo, proto_tree *tree, proto_tree *param_tree)
+{
+ /* do we have OSI acse/rose packet dissector ? */
+ if(!acse_handle)
+ {
+ /* No - display as data */
+ if (tree)
+ {
+ proto_tree_add_text(param_tree, tvb, offset, param_len,
+ "No ACSE dissector available");
+ }
+ }
+ else
+ {
+ /* Yes - call app dissector */
+ tvbuff_t *next_tvb;
+
+ next_tvb = tvb_new_subset(tvb, offset, param_len, param_len);
+ TRY
+ {
+ call_dissector(acse_handle, next_tvb, pinfo, tree);
+ }
+ CATCH_ALL
+ {
+ show_exception(tvb, pinfo, tree, EXCEPT_CODE);
+ }
+ ENDTRY;
+ }
+}
+static char*
+string_to_hex(unsigned char * in,char * out,int len)
+{
+ char ascii[MAXSTRING];
+ int i;
+ memset(&ascii,0x00,sizeof(ascii));
+for(i=0;i<len;i++)
+ {
+ unsigned char o_out = *(in+i);
+ sprintf(out+(i<<1),"%.2x",* (in+i));
+ if( ( (o_out) >= 'a') & ( (o_out) <='z') ||
+ ( (o_out) >= 'A') & ( (o_out) <='Z') ||
+ ( (o_out) >= '0') & ( (o_out) <='9')
+ )
+ {
+ ascii[i] = o_out;
+ }
+ else
+ {
+ ascii[i] = '.';
+ }
+
+ }
+ strcat(out," ");
+ strcat(out,ascii);
+ return out;
+}
+
+static int read_length(ASN1_SCK *a, proto_tree *tree, int hf_id, guint *len)
+{
+ guint length = 0;
+ gboolean def = FALSE;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_length_decode(a, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse length: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (len)
+ *len = length;
+
+ if (tree && hf_id)
+ proto_tree_add_uint(tree, hf_id, a->tvb, start, a->offset-start,
+length);
+
+ return ASN1_ERR_NOERROR;
+}
+static int read_integer_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i, int start, guint length)
+{
+ guint integer = 0;
+ proto_item *temp_item = NULL;
+ int ret;
+
+ ret = asn1_uint32_value_decode(a, length, &integer);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse value: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ if (i)
+ *i = integer;
+
+ if (tree && hf_id)
+ temp_item = proto_tree_add_uint(tree, hf_id, a->tvb, start,
+a->offset-start, integer);
+
+ if (new_item)
+ *new_item = temp_item;
+
+ return ASN1_ERR_NOERROR;
+}
+
+static int read_integer(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, guint *i)
+{
+ guint cls, con, tag;
+ gboolean def;
+ guint length;
+ int start = a->offset;
+ int ret;
+
+ ret = asn1_header_decode(a, &cls, &con, &tag, &def, &length);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse header: %s",
+ (hf_id != -1) ? proto_registrar_get_name(hf_id) : "LDAP message",
+ asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+
+ return read_integer_value(a, tree, hf_id, new_item, i, start, length);
+}
+/* display asn.1 Integer type */
+static void
+show_integer(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ proto_tree *pres_tree_itm = NULL;
+ proto_item *itm;
+ int ret;
+ int save_len = item_len;
+ int off = *offset;
+ itm = proto_tree_add_text(pres_tree, tvb, *offset, item_len,
+ "Integer");
+ pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
+ ret = read_integer(asn,pres_tree_itm,0,NULL,&item_len);
+ if (ret == ASN1_ERR_NOERROR )
+ {
+ *offset = asn->offset;
+ itm = proto_tree_add_text(pres_tree_itm, tvb, (*offset)-item_len,
+item_len,
+ "Integer value: %u",item_len);
+ }
+ else
+ {
+ /* can't dissect item. Skip it. */
+ *offset = off+ save_len;
+ }
+
+}
+static void
+show_presentation_requirements(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
+*tvb,int *offset,int item_len,int tag)
+{
+ proto_tree *pres_tree_itm = NULL;
+ proto_item *itm;
+ guint16 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+(asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(pres_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+
+ itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+
+item_len,
+ val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
+ pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
+ *offset = asn->offset;
+ flags = tvb_get_ntohs(tvb, *offset);
+ proto_tree_add_boolean(pres_tree_itm,hf_context_management, tvb, *offset,
+2, flags);
+ proto_tree_add_boolean(pres_tree_itm,hf_restoration, tvb, *offset, 2,
+flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+
+static void
+show_protocol_version(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *pres_tree_itm = NULL;
+ proto_item *itm;
+ guint16 flags;
+ gint length;
+/* do we have enough bytes to dissect this item ? */
+ if( ( length = tvb_reported_length_remaining(tvb, *offset)) <
+(asn->offset -*offset)+ item_len )
+ {
+ proto_tree_add_text(pres_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ return;
+ }
+
+ itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+
+item_len,
+ val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
+ pres_tree_itm = proto_item_add_subtree(itm, ett_pres_itm);
+ *offset = asn->offset;
+ flags = tvb_get_ntohs(tvb, *offset);
+ proto_tree_add_boolean(pres_tree_itm,hf_protocol_version, tvb, *offset,
+2, flags);
+ *offset = *offset + item_len;
+ asn->offset = *offset;
+}
+static void
+print_oid_value(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ guint ret;
+ subid_t *oid;
+ guint len;
+ gchar *display_string;
+ guint length;
+ guint start=*offset;
+
+ ret = asn1_oid_value_decode (asn, item_len, &oid, &len);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ return ;
+ }
+ length = asn->offset - start;
+ display_string = format_oid(oid, len);
+ proto_tree_add_text(pres_tree, tvb, *offset,length,"Value:%s",
+display_string);
+ g_free(display_string);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+static void
+print_oid(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int *offset,int
+item_len)
+{
+ guint ret;
+ subid_t *oid;
+ guint len;
+ guint nbytes;
+ gchar *display_string;
+ guint length;
+ guint start=*offset;
+
+ ret = asn1_oid_decode ( asn, &oid, &len, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ return ;
+ }
+ length = asn->offset - start;
+ display_string = format_oid(oid, len);
+ proto_tree_add_text(pres_tree, tvb, *offset,length,"Value:%s",
+display_string);
+ g_free(display_string);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+print_value(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ gint start = *offset;
+ char tmp[MAXSTRING];
+ *offset = asn->offset; /* align to data*/
+ string_to_hex((char*)tvb_get_ptr(tvb,*offset,item_len),tmp,item_len);
+ proto_tree_add_text(pres_tree, tvb, *offset, item_len, tmp);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+static int
+get_integer_value(ASN1_SCK *asn,int length,int *offset)
+{
+ int off = *offset;
+ int asn_off = asn->offset;
+ int item_len = -1;
+ int ret;
+ /* align pointers */
+ *offset=asn->offset;
+ ret = asn1_uint32_value_decode(asn, length, &item_len);
+ /* return to present position */
+ *offset = off;
+ asn->offset = asn_off;
+
+ if (ret != ASN1_ERR_NOERROR )
+ {
+ return -1;
+ }
+ else
+ {
+ return item_len;
+ }
+
+}
+static void
+show_presentation_context_definition_result_seq(ASN1_SCK *asn,proto_tree
+*pres_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ proto_tree *pres_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = *offset;
+ guint header_len;
+ int old_offset;
+
+ /* print seq */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ old_offset = *offset ;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+new_item_len )
+ {
+ proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
+new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, sequence_list_result_vals,
+ "Unknown item (0x%02x)"));
+ pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+ case PRESENTATION_RESULT:
+ {
+ proto_tree *pres_tree_pr = NULL;
+ proto_item *pr;
+ int value = get_integer_value(asn,new_item_len,offset);
+ pr = proto_tree_add_text(pres_tree_ms, tvb, *offset,
+new_item_len+(asn->offset-*offset),
+ val_to_str(value ,sequence_list_result_values_vals,
+ "Unknown item (0x%02x)"));
+ pres_tree_pr = proto_item_add_subtree(pr, ett_pres_ms);
+
+ print_value(asn,pres_tree_pr,tvb,offset,new_item_len);
+ }
+ break;
+ case PRESENTATION_RESULT_INTEGER:
+ print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
+ break;
+ case PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME:
+ print_oid_value(asn,pres_tree_ms,tvb,offset,new_item_len);
+ break;
+
+ default:
+ proto_tree_add_text(pres_tree, tvb, *offset,
+new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ }
+ *offset = old_offset+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ }
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+
+static void
+show_presentation_context_definition_seq(ASN1_SCK *asn,proto_tree
+*pres_tree,tvbuff_t *tvb,int *offset,int item_len)
+{
+ proto_tree *pres_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = *offset;
+ guint header_len;
+ int old_offset;
+
+ /* print seq */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ old_offset = *offset ;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+new_item_len )
+ {
+ proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
+new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, sequence_list_vals,
+ "Unknown item (0x%02x)"));
+ pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+ case PRESENTATION_CONTEXT_IDENTIFIER:
+ print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
+ break;
+ case ABSTRACT_SYNTAX_NAME:
+ print_oid_value(asn,pres_tree_ms,tvb,offset,new_item_len);
+ break;
+ case TRANSFER_SYNTAX_NAMES:
+ print_oid(asn,pres_tree_ms,tvb,offset,new_item_len);
+ break;
+ default:
+ proto_tree_add_text(pres_tree, tvb, *offset,
+new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ }
+ *offset = old_offset+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ }
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+}
+static void
+show_fully_encoded_seq(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
+*offset,int item_len)
+{
+ proto_tree *pres_tree_ms = NULL;
+ guint length;
+ guint type;
+ proto_item *ms;
+ guint new_item_len;
+ guint start = *offset;
+ guint header_len;
+ guint acse = 0; /* no acse id */
+ int old_offset;
+ /* print seq */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ old_offset = *offset ;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, pres_tree, 0, &new_item_len) != ASN1_ERR_NOERROR)
+ {
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+new_item_len )
+ {
+ proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+ return ;
+ }
+ if(!new_item_len && length>2)
+ {
+ new_item_len = length-1; /* can't get length from asn1 tag. Use rest of the pdu len. */
+ }
+ header_len = asn->offset - (*offset) +1;
+ ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
+new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, presentation_data_values,
+ "Unknown item (0x%02x)"));
+ pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+ case PRESENTATION_CONTEXT_IDENTIFIER:
+ {
+ acse = get_integer_value(asn,new_item_len,offset);
+ print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
+ }
+ break;
+ case OCTET_ALIGNED:
+ case DATA_BLOCK:
+ {
+ proto_item *acse_ms;
+ /* yes, we have to call ACSE dissector */
+ acse_ms = proto_tree_add_text(pres_tree_ms, tvb, *offset,new_item_len+(asn->offset-*offset),
+ "User data");
+
+ session->abort_type = DATA_BLOCK;
+ /* call acse dissector */
+ call_acse_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,pres_tree_ms);
+ }
+ break;
+ case SINGLE_ASN1_TYPE:
+
+ {
+ proto_item *acse_ms;
+ /* yes, we have to call ACSE dissector */
+ acse_ms = proto_tree_add_text(pres_tree_ms, tvb, *offset,
+new_item_len+(asn->offset-*offset),
+ "User data");
+ /* call acse dissector */
+ call_acse_dissector(tvb,*offset,new_item_len,global_pinfo,global_tree,pres_tree_ms);
+ acse = 0;
+ }
+ break;
+ case ARBITRARY:
+ print_value(asn,pres_tree_ms,tvb,offset,new_item_len);
+ break;
+ default:
+ proto_tree_add_text(pres_tree, tvb, *offset,
+new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ }
+ *offset = old_offset+new_item_len+header_len;
+ item_len-=new_item_len+header_len;
+ }
+ /* align the pointer */
+ (*offset)=start+item_len;
+ asn->offset = (*offset);
+
+}
+static void
+show_fully_encoded_data(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ proto_tree *pres_tree_ms = NULL;
+ proto_tree *pres_tree_pc = NULL;
+ gint length;
+ guint type;
+ guint header_len;
+ proto_item *ms;
+ gint new_item_len;
+ guint start = asn->offset;
+ guint item_length = item_len;
+ pres_tree_pc = pres_tree;
+
+/* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
+ "Wrong item.Need %u bytes but have %u", item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset =asn->offset;
+ start = *offset;
+ /* read the rest */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ int old_offset = *offset;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
+ASN1_ERR_NOERROR)
+ {
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+new_item_len )
+ {
+ proto_tree_add_text(pres_tree_pc, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ if(!new_item_len && length>2)
+ {
+ /* check if really do have what to dissect */
+ new_item_len = length-1;
+ }
+ ms = proto_tree_add_text(pres_tree_pc, tvb, *offset-1,
+new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, presentation_context_definition_vals,
+ "Unknown item (0x%02x)"));
+ pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+
+ case SEQUENCE:
+ show_fully_encoded_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
+ *offset = old_offset+(new_item_len+header_len);
+ break;
+
+ default:
+ proto_tree_add_text(pres_tree_ms, tvb, *offset,
+new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ *offset = old_offset+(new_item_len+header_len);
+ }
+ item_len = item_len - (new_item_len+header_len);
+
+ }
+
+
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+}
+static void
+show_session_provider_abort(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
+*tvb,int *offset,int item_len)
+{
+ gint length;
+ gint value;
+ proto_tree *pres_tree_pc = NULL;
+ proto_tree *pres_tree_pp = NULL;
+ proto_item *itu;
+ gint new_item_len;
+
+
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(pres_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ *offset = asn->offset;
+ return;
+ }
+ itu = proto_tree_add_text(pres_tree, tvb, *offset,item_len,
+ "Provider abort");
+ pres_tree_pp = proto_item_add_subtree(itu, ett_pres_ms);
+
+ if(item_len <= 0)
+ {
+ proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
+ "Provider reason not specified");
+ *offset = asn->offset;
+ return;
+ }
+ itu = proto_tree_add_text(pres_tree_pp, tvb, *offset,ABORT_REASON_LEN,
+ "Abort reason");
+ pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
+ (*offset)++; /* skip type */
+ asn->offset = *offset;
+ item_len--;
+ /* get length */
+ if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
+ASN1_ERR_NOERROR)
+ {
+ *offset = asn->offset;
+ return;
+ }
+ /* try to get Abort reason */
+ value = get_integer_value(asn,new_item_len,offset);
+
+
+ proto_tree_add_text(pres_tree_pc, tvb, *offset+1,new_item_len,
+ val_to_str(value, provider_abort_values_vals,"Unknown item (0x%02x)"));
+ item_len-=(asn->offset-*offset)+new_item_len;
+ *offset = asn->offset+new_item_len;
+ asn->offset = *offset;
+ /* do we have Event identifier ? */
+ if(item_len > 0)
+ {
+ itu = proto_tree_add_text(pres_tree_pp, tvb, *offset,item_len,
+ "Event identifier");
+ pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
+
+ (*offset)++; /* skip type */
+ asn->offset = *offset;
+ item_len--;
+ /* get length */
+ if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
+ASN1_ERR_NOERROR)
+ {
+ *offset = asn->offset;
+ return;
+ }
+ /* try to get Event identifier */
+ value = get_integer_value(asn,new_item_len,offset);
+
+ proto_tree_add_text(pres_tree_pc, tvb, *offset+1,new_item_len,
+ val_to_str(value, event_identifier_values_vals,"Unknown item (0x%02x)"));
+ item_len-=(asn->offset-*offset)+new_item_len;
+ *offset = asn->offset+new_item_len;
+ asn->offset = *offset;
+ }
+}
+static void
+show_user_data(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
+*offset,int item_len,int tag)
+{
+ proto_tree *pres_tree_ud = NULL;
+ proto_tree *pres_tree_pc = NULL;
+ proto_item *itm;
+ proto_item *itu;
+ guint start = asn->offset;
+ guint item_length = item_len;
+
+ itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset -*offset)+
+item_len, "User data");
+ pres_tree_ud = proto_item_add_subtree(itm, ett_pres_ms);
+ itu = proto_tree_add_text(pres_tree_ud, tvb,
+*offset,item_len+(asn->offset-*offset),
+ val_to_str(tag, user_data_values_vals,"Unknown item (0x%02x)"));
+ pres_tree_pc = proto_item_add_subtree(itu, ett_pres_ms);
+ switch(tag)
+ {
+ case SIMPLY_ENCODED_DATA:
+ break;
+ case FULLY_ENCODED_DATA:
+ show_fully_encoded_data(asn,pres_tree_pc,tvb,offset,item_len);
+ break;
+ default:
+ break;
+ }
+
+
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+
+}
+
+static void
+show_presentation_context_definition(ASN1_SCK *asn,proto_tree
+*pres_tree,tvbuff_t *tvb,int *offset,int item_len,int tag)
+{
+ proto_tree *pres_tree_ms = NULL;
+ proto_tree *pres_tree_pc = NULL;
+ proto_item *itm;
+ gint length;
+ guint type;
+ guint header_len;
+ proto_item *ms;
+ gint new_item_len;
+ guint start = asn->offset;
+ guint item_length = item_len;
+
+ itm = proto_tree_add_text(pres_tree, tvb,
+*offset,item_len+(asn->offset-*offset),
+ val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
+ pres_tree_pc = proto_item_add_subtree(itm, ett_pres_ms);
+
+/* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(pres_tree_pc, tvb, *offset, item_len,
+ "Wrong item.Need %u bytes but have %u", item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ *offset =asn->offset;
+ start = *offset;
+ /* read the rest */
+ while ( item_len > 0 && tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ int old_offset = *offset;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, pres_tree_pc, 0, &new_item_len) !=
+ASN1_ERR_NOERROR)
+ {
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ header_len = asn->offset - (*offset) +1;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+new_item_len )
+ {
+ proto_tree_add_text(pres_tree_pc, tvb, *offset, new_item_len,
+ "Wrong item.Need %u bytes but have %u", new_item_len,length);
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+ return ;
+ }
+ ms = proto_tree_add_text(pres_tree_pc, tvb, *offset-1,
+new_item_len+(asn->offset-*offset)+1,
+ val_to_str(type, presentation_context_definition_vals,
+ "Unknown item (0x%02x)"));
+ pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
+ *offset = asn->offset;
+
+
+ switch(type)
+ {
+
+ case SEQUENCE:
+ if(tag == PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST
+ || tag == DEFAULT_CONTEXT_RESULT)
+ {
+ show_presentation_context_definition_result_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
+ }
+ else
+ {
+ show_presentation_context_definition_seq(asn,pres_tree_ms,tvb,offset,new_item_len);
+ }
+ *offset = old_offset+(new_item_len+header_len);
+ break;
+
+ default:
+ proto_tree_add_text(pres_tree_ms, tvb, *offset,
+new_item_len+(asn->offset-*offset),
+ "Unknown asn.1 parameter: (0x%02x)", type);
+ *offset = old_offset+(new_item_len+header_len);
+ }
+ item_len = item_len - (new_item_len+header_len);
+
+ }
+
+
+ /* align the pointer */
+ (*offset)=start+item_length;
+ asn->offset = (*offset);
+}
+/* if we can't dissect */
+static void
+dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const char *field_name, int ret)
+{
+ char *errstr;
+ errstr = asn1_err_to_str(ret);
+
+ if (tree != NULL)
+ {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "ERROR: Couldn't parse %s: %s", field_name, errstr);
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+}
+
+static int read_string_value(ASN1_SCK *a, proto_tree *tree, int hf_id,
+ proto_item **new_item, char **s, int start, guint length)
+{
+ guchar *string;
+ proto_item *temp_item = NULL;
+ int ret;
+
+ if (length)
+ {
+ ret = asn1_string_value_decode(a, length, &string);
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ if (tree)
+ {
+ proto_tree_add_text(tree, a->tvb, start, 0,
+ "%s: ERROR: Couldn't parse value: %s",
+ proto_registrar_get_name(hf_id), asn1_err_to_str(ret));
+ }
+ return ret;
+ }
+ string = g_realloc(string, length + 1);
+ string[length] = '\0';
+ }
+ else
+ string = "(null)";
+
+ if (tree && hf_id)
+ temp_item = proto_tree_add_string(tree, hf_id, a->tvb, start, a->offset
+- start, string);
+ if (new_item)
+ *new_item = temp_item;
+
+ if (s && length)
+ *s = string;
+ else
+ if (length)
+ g_free(string);
+ return ASN1_ERR_NOERROR;
+}
+static void
+show_provider_reason(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t *tvb,int
+*offset,int item_len,int type)
+{
+ proto_item *ms;
+ proto_item *pr;
+ proto_tree *pres_tree_ms = NULL;
+ proto_tree *pres_tree_pr = NULL;
+ int off = *offset;
+ int value=0;
+ int new_item_len = item_len+(asn->offset-*offset);
+
+ ms = proto_tree_add_text(pres_tree, tvb, *offset, new_item_len,
+ val_to_str(type, sequence_top_vals,
+ "Unknown item (0x%02x)"));
+ pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
+ value = get_integer_value(asn,item_len,offset);
+ pr = proto_tree_add_text(pres_tree_ms, tvb, *offset, new_item_len,
+ val_to_str(value, provider_reason_values_vals,
+ "Unknown item (0x%02x)"));
+ pres_tree_pr = proto_item_add_subtree(pr, ett_pres_ms);
+ print_value(asn,pres_tree_pr,tvb,offset,item_len);
+ asn->offset = *offset = off+new_item_len;
+}
+static void
+show_presentation_selector (ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
+*tvb,int *offset,int item_len,int type)
+{
+ proto_item *ms;
+ proto_tree *pres_tree_ms = NULL;
+ int ret;
+ char *s;
+
+ ms = proto_tree_add_text(pres_tree, tvb, *offset,
+item_len+(asn->offset-*offset),
+ val_to_str(type, sequence_top_vals,
+ "Unknown item (0x%02x)"));
+
+
+ pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
+
+ ret = read_string_value(asn, pres_tree,0,NULL, &s,
+*offset+(asn->offset-*offset), item_len);
+ if(ret == ASN1_ERR_NOERROR)
+ {
+ if( item_len)
+ {
+ proto_tree_add_text(pres_tree_ms, tvb, *offset+2, item_len,
+ "String:%s",s);
+ g_free(s);
+ }
+ else
+ {
+ proto_tree_add_text(pres_tree_ms, tvb, *offset+2, item_len,
+ "Zero selector length");
+
+ }
+ }
+
+
+
+}
+/* display top sequence */
+static void
+show_sequence_top(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int item_len)
+{
+ int ret;
+ guint cls, con, tag,len1;
+ gint type;
+ gboolean def;
+ proto_item *itm;
+ gint length;
+ while(item_len > 0 )
+ {
+/* do we have enough bytes to dissect this item ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) < item_len )
+ {
+ proto_tree_add_text(pres_tree, tvb, *offset, item_len,
+ "Wrong Item.Need %u bytes but have %u", item_len,length);
+ break;
+ }
+ /* get tag */
+ type = tvb_get_guint8(tvb, *offset);
+ /* decode header */
+ ret = asn1_header_decode(asn, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR)
+ {
+ dissect_parse_error(tvb, *offset, pinfo, pres_tree,
+ "sequence error", ret);
+ break;
+ }
+ item_len = item_len - (asn->offset - *offset);
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag)
+ {
+ case TAG_01:
+ /* Calling-presentation-selector and
+ User data have the same tag number
+ Try to recognize which one do we really have */
+ if( con == ASN1_CON)
+ {
+ /* it is User data */
+ /* print it */
+ show_user_data(asn,pres_tree,tvb,offset,len1,type);
+ break;
+ }
+ /* it is Calling-presentation-selector */
+ /* simply go below, we don't need to break here */
+
+ case CALLED_PRESENTATION_SELECTOR:
+ case RESPONDING_PRESENTATION_SELECTOR:
+ /*case CALLING_PRESENTATION_SELECTOR:*/
+ /*
+ * [Called-presentation-selector]
+ * [Calling-presentation-selector]
+ * [Responding-presentation-selector]
+ */
+ show_presentation_selector(asn,pres_tree,tvb,offset,len1,tag);
+ break;
+ case DEFAULT_CONTEXT_NAME:
+ case PRESENTATION_CONTEXT_DEFINITION_LIST:
+ show_presentation_context_definition(asn,pres_tree,tvb,offset,len1,tag);
+ break;
+ case PROTOCOL_VERSION:
+ /*case TAG_00: */
+ if(cls == ASN1_APL)
+ {
+ /* yes, it is application */
+ *offset = asn->offset;
+ item_len = len1;
+ continue;
+ }
+ show_protocol_version(asn,pres_tree,tvb,offset,len1,tag);
+ break;
+ case PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST:
+ case DEFAULT_CONTEXT_RESULT:
+ show_presentation_context_definition(asn,pres_tree,tvb,offset,len1,tag);
+ break;
+ case PRESENTATION_REQUIREMENTS:
+ show_presentation_requirements(asn,pres_tree,tvb,offset,len1,tag);
+ break;
+ case PROVIDER_REASON:
+ show_provider_reason(asn,pres_tree,tvb,offset,len1,tag);
+ break;
+ /* to do */
+
+ case USER_SESSION_REQUIREMENTS:
+
+ itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset
+-*offset)+ len1,
+ val_to_str(tag, sequence_top_vals,"Unknown item (0x%02x)"));
+ (asn->offset)+=len1;
+ break;
+
+ default:
+ itm = proto_tree_add_text(pres_tree, tvb, *offset,(asn->offset
+-*offset)+ len1,
+ "Unknown tag: %x",tag);
+ (asn->offset)+=len1;
+ }
+
+ item_len-=len1;
+ *offset = asn->offset;
+ }
+
+}
+static void
+show_connection_request_confirm(ASN1_SCK *asn,proto_tree *pres_tree,tvbuff_t
+*tvb,packet_info *pinfo,int *offset,int* item_len)
+{
+ guint8 type;
+ guint length;
+ proto_tree *pres_tree_ms = NULL;
+ proto_item *ms;
+ /* get type of set */
+ while ( tvb_reported_length_remaining(tvb, *offset) > 0 )
+ {
+ int asn1_tag;
+ /* get item type */
+ type = tvb_get_guint8(tvb, *offset);
+ asn1_tag = type & 0x1f;
+ /* skip type */
+ (*offset)++;
+ asn->offset = *offset;
+ /* get length */
+ if (read_length(asn, pres_tree, 0, item_len) != ASN1_ERR_NOERROR)
+ {
+ return;
+ }
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, *offset)) <
+(guint)*item_len )
+ {
+ proto_tree_add_text(pres_tree, tvb, *offset, -1,
+ "Wrong item.Need %u bytes but have %u", *item_len,length);
+ return;
+ }
+ ms = proto_tree_add_text(pres_tree, tvb, *offset-1,
+*item_len+(asn->offset-*offset)+1,
+ val_to_str(asn1_tag, cr_vals,
+ "Unknown item (0x%02x)"));
+ pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
+
+ switch(asn1_tag)
+ {
+ case MODE_SELECTOR:
+ proto_tree_add_uint(pres_tree_ms, hf_pres_ms_type, tvb, (*offset)-1, 1,
+type);
+ proto_tree_add_text(pres_tree_ms, tvb, *offset, (asn->offset-*offset),
+ "Lenght:%u",*item_len);
+ *offset=asn->offset;
+ show_integer(asn,pres_tree_ms,tvb,offset,*item_len);
+ break;
+ case SET_TOP:
+ case SEQUENCE_TOP:
+ proto_tree_add_uint(pres_tree_ms, hf_pres_seq_type, tvb, (*offset)-1, 1,
+type);
+ proto_tree_add_text(pres_tree_ms, tvb, *offset, (asn->offset-*offset),
+ "Lenght:%u",*item_len);
+ *offset=asn->offset;
+ show_sequence_top(asn,pres_tree_ms,tvb,pinfo,offset,*item_len);
+ break;
+ default:
+ proto_tree_add_text(pres_tree, tvb, (*offset)-1,
+*item_len+(asn->offset-*offset)+1,
+ "Unknown asn.1 parameter: (0x%02x).Tag :(0x%02x)", type,asn1_tag);
+ (*offset)+=*item_len+(asn->offset-*offset);
+ asn->offset = *offset;
+ }
+
+ }
+}
+
+
+/*
+* Dissect an Ppdu.
+*/
+static int
+dissect_ppdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree
+*tree)
+{
+ proto_item *ti;
+ proto_tree *pres_tree = NULL;
+ guint length;
+ guint rest_len;
+ guint s_type;
+ ASN1_SCK asn;
+ guint cp_type_len;
+/* do we have spdu type from the session dissector? */
+ if( !pinfo->private_data )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Internal error:can't get spdu type from session dissector.");
+ return FALSE;
+ }
+ }
+ else
+ {
+ session = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
+ if(session->spdu_type == 0 )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
+ return FALSE;
+ }
+ }
+ }
+/* get type of tag */
+ s_type = tvb_get_guint8(tvb, offset);
+ /* set up type of Ppdu */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_pres, tvb, offset, -1,
+ FALSE);
+ pres_tree = proto_item_add_subtree(ti, ett_pres);
+ }
+ offset++;
+/* open asn.1 stream */
+ asn1_open(&asn, tvb, offset);
+
+ switch(session->spdu_type)
+ {
+ case SES_REFUSE:
+ proto_tree_add_uint(pres_tree, hf_pres_type, tvb, offset-1, 1, s_type);
+ if (read_length(&asn, pres_tree, hf_cp_type_message_length, &cp_type_len)
+!= ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
+)
+ {
+ if(tree)
+ {
+ proto_tree_add_text(pres_tree, tvb, offset, -1,
+ "Wrong Ppdu.Need %u bytes but have %u", cp_type_len,length);
+ }
+ return FALSE;
+ }
+ if (tree)
+ {
+ asn.offset = offset;
+ show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,cp_type_len);
+ offset=asn.offset;
+ }
+ break;
+ case SES_CONNECTION_REQUEST:
+ case SES_CONNECTION_ACCEPT:
+ proto_tree_add_uint(pres_tree, hf_pres_type, tvb, offset-1, 1, s_type);
+
+ if (read_length(&asn, pres_tree, hf_cp_type_message_length, &cp_type_len)
+!= ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < cp_type_len
+)
+ {
+ if(tree)
+ {
+ proto_tree_add_text(pres_tree, tvb, offset, -1,
+ "Wrong Ppdu.Need %u bytes but have %u", cp_type_len,length);
+ }
+ return FALSE;
+ }
+ if(tree)
+ {
+ show_connection_request_confirm(&asn,pres_tree,tvb,pinfo,&offset,&cp_type_len);
+ }
+ break;
+ case SES_ABORT:
+ /* get length */
+ if (read_length(&asn, pres_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ /* skip length */
+ offset = asn.offset;
+ /* do we have enough bytes to dissect ? */
+ if( ( length =tvb_reported_length_remaining(tvb, offset)) < rest_len )
+ {
+ if(tree)
+ {
+ proto_tree_add_text(pres_tree, tvb, offset, -1,
+ "Wrong Ppdu.Need %u bytes but have %u", rest_len,length);
+ }
+ return FALSE;
+ }
+ if(session->abort_type == SESSION_USER_ABORT )
+ {
+ /* is it PC */
+ if(s_type == ASN1_CLASS_PC+ASN1_CLASS_CONTEXT_SPECIFIC)
+ {
+ if (tree)
+ {
+ offset=asn.offset;
+ show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,rest_len);
+ offset=asn.offset;
+ }
+ }
+ else
+ {
+ if (tree)
+ {
+ offset=asn.offset;
+ show_session_provider_abort(&asn,pres_tree,tvb,&offset,rest_len);
+ offset=asn.offset;
+ }
+ }
+ }
+ else
+ {
+ if (tree)
+ {
+ offset=asn.offset;
+ show_sequence_top(&asn,pres_tree,tvb,pinfo,&offset,rest_len);
+ offset=asn.offset;
+ }
+ }
+ break;
+ default:
+ {
+ proto_item *ms;
+ proto_tree *pres_tree_ms = NULL;
+ /* back to length */
+ offset--;
+ /* get length */
+ if (read_length(&asn, pres_tree, 0, &rest_len) != ASN1_ERR_NOERROR)
+ {
+ return FALSE;
+ }
+ if(!rest_len)
+ {
+ guint rest_pdu_len = 0;
+ /* do we really haven't any more bytes ? */
+ if( (rest_pdu_len = tvb_reported_length_remaining(tvb, offset)) )
+ {
+ /*
+ * we have but can't say how many from asn1 information.
+ * use pdu len instead
+ */
+ if(rest_pdu_len > 2)
+ {
+ rest_len = rest_pdu_len;
+ }
+ }
+ }
+ ms = proto_tree_add_text(pres_tree, tvb, offset, rest_len,
+ val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
+ pres_tree_ms = proto_item_add_subtree(ms, ett_pres_ms);
+ show_user_data(&asn,pres_tree_ms,tvb,&offset,rest_len,s_type);
+ }
+ }
+/* close asn.1 stream */
+ asn1_close(&asn, &offset);
+
+ return offset;
+}
+
+/*
+* Dissect PPDUs inside a SPDU.
+*/
+static void
+dissect_pres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+/* first, try to check length */
+/* do we have at least 4 bytes */
+ if (!tvb_bytes_exist(tvb, 0, 4))
+ {
+ proto_tree_add_text(tree, tvb, offset, tvb_reported_length_remaining(tvb,
+offset),
+ "User data");
+ return; /* no, it isn't a presentation PDU */
+ }
+
+ /* we can't make any additional checking here */
+ /* postpone it before dissector will have more information */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PRES");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+ /* save pointers for calling the acse dissector */
+ global_tree = tree;
+ global_pinfo = pinfo;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0)
+ {
+ offset = dissect_ppdu(tvb, offset, pinfo, tree);
+ if(offset == FALSE )
+ {
+ proto_tree_add_text(tree, tvb, offset, -1,"Internal error");
+ offset = tvb_length(tvb);
+ break;
+ }
+ }
+}
+
+void
+proto_register_pres(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_pres_type,
+ {
+ "PPDU Type",
+ "pres.type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(pres_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_pres_length,
+ {
+ "Length",
+ "pres.length",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_cp_type_message_length,
+ {
+ "Message Length",
+ "cp_type.message_length",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "CP type Message Length",
+ HFILL
+ }
+ },
+ {
+ &hf_pres_rc_type,
+ {
+ "Connection reqiest/confirm",
+ "pres.type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(pres_vals),
+ 0x0,
+ "Connection reqiest/confirm",
+ HFILL
+ }
+ },
+
+ {
+ &hf_pres_ms_type,
+ {
+ "Mode selector",
+ "pres.mode.selector",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Mode select",
+ HFILL
+ }
+ },
+ {
+ &hf_pres_protocol_version,
+ {
+ "Protocol version",
+ "pres.protocol.version",
+ FT_UINT16,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ "Protocol version",
+ HFILL
+ }
+ },
+ {
+ &hf_value,
+ {
+ "Value",
+ "pres.value",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Value",
+ HFILL
+ }
+ },
+
+ {
+ &hf_pres_seq_type,
+ {
+ "Sequence",
+ "pres.sequence",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Mode select",
+ HFILL
+ }
+ },
+
+ {
+ &hf_protocol_version,
+ {
+ "Protocol version 1",
+ "pres.protocol.version",
+ FT_BOOLEAN, 16,
+ NULL,
+ PRES_PROTOCOL_VERGION,
+ "Protocol version 1",
+ HFILL
+ }
+ },
+ {
+ &hf_context_management,
+ {
+ "Context management",
+ "pres.context.management",
+ FT_BOOLEAN, 16,
+ NULL,
+ PRES_CONTEXT_MANAGEMENT,
+ "Context management",
+ HFILL
+ }
+ },
+ {
+ &hf_restoration,
+ {
+ "Restoration",
+ "pres.restoration",
+ FT_BOOLEAN, 16,
+ NULL,
+ PRES_RESTORATION,
+ "Restoration",
+ HFILL
+ }
+ },
+
+
+ };
+
+ static gint *ett[] =
+ {
+ &ett_pres,
+ &ett_pres_param,
+ &ett_pres_rc,
+ &ett_pres_ms,
+ &ett_pres_itm,
+ };
+ module_t *pres_module;
+
+
+ proto_pres = proto_register_protocol(PROTO_STRING_PRES, "PRES", "pres");
+ proto_register_field_array(proto_pres, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ pres_module = prefs_register_protocol(proto_pres, NULL);
+
+ /*
+ * Register the dissector by name, so other dissectors can
+ * grab it by name rather than just referring to it directly
+ * (you can't refer to it directly from a plugin dissector
+ * on Windows without stuffing it into the Big Transfer Vector).
+ */
+ register_dissector("pres", dissect_pres, proto_pres);
+}
+
+void
+proto_reg_handoff_pres(void)
+{
+ /* find data dissector */
+ data_handle = find_dissector("data");
+ /* define acse sub dissector */
+ acse_handle = find_dissector("acse");
+}
diff --git a/epan/dissectors/packet-pres.h b/epan/dissectors/packet-pres.h
new file mode 100644
index 0000000000..a8a7f35178
--- /dev/null
+++ b/epan/dissectors/packet-pres.h
@@ -0,0 +1,172 @@
+/* packet-pres.h
+*
+* Routine to dissect ISO 8823 OSI Presentation Protocol packets
+*
+* $Id$
+*
+* Yuriy Sidelnikov <YSidelnikov@hotmail.com>
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define PROTO_STRING_PRES "ISO 8823 OSI Presentation Protocol"
+#define PROTO_STRING_PRES_INFO "ISO 8823 OSI Presentation Protocol."
+
+/* type of PPDU */
+
+#define PRES_CONNECTION_REQUEST_CONFIRM 0x31
+#define PRES_CONNECTION_REFUSE 0x30
+
+/* asn.1 definitions */
+#define ASN1_CLASS_UNIVERSAL 0x00
+#define ASN1_CLASS_APPLICATION 0x40
+#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80
+#define ASN1_CLASS_Private 0xc0
+#define ASN1_CLASS_PC 0x20
+
+#define INTEGER_ITEM 0x01
+#define BOOLEAN_ITEM 0x01
+
+/* type of parameters */
+#define MODE_SELECTOR 0
+#define SET_TOP 1
+#define SEQUENCE_TOP 2
+
+
+#define SEQUENCE 0x30
+
+/* sequence top */
+#define TAG_00 0
+#define TAG_01 1
+
+enum
+{
+PROTOCOL_VERSION,
+CALLING_PRESENTATION_SELECTOR,
+CALLED_PRESENTATION_SELECTOR,
+RESPONDING_PRESENTATION_SELECTOR,
+PRESENTATION_CONTEXT_DEFINITION_LIST,
+PRESENTATION_CONTEXT_DEFINITION_RESULT_LIST,
+DEFAULT_CONTEXT_NAME,
+DEFAULT_CONTEXT_RESULT,
+PRESENTATION_REQUIREMENTS,
+USER_SESSION_REQUIREMENTS,
+PROVIDER_REASON
+};
+/* definition list **/
+#define PRESENTATION_CONTEXT_IDENTIFIER 2
+#define ABSTRACT_SYNTAX_NAME 6
+#define TRANSFER_SYNTAX_NAMES 0x30
+/* result list */
+#define PRESENTATION_RESULT 0x80
+#define PRESENTATION_RESULT_TRANSFER_SYNTAX_NAME 0x81
+#define PRESENTATION_RESULT_INTEGER 0x82
+
+/* result values */
+#define PRESENTATION_RESULT_ACCEPTANCE 0
+#define PRESENTATION_RESULT_USER_REJECTION 1
+#define PRESENTATION_RESULT_PROVIDER_REJECTION 2
+
+/* provider reason */
+enum
+{
+REASON_NOT_SPECIFIED,
+TEMPORARY_CONGESTION,
+LOCAL_LIMIT_EXCEEDED,
+CALLED_PRESENTATION_ADDRESS_UNKNOWN,
+PROTOCOL_VERSION_NOT_SUPPORTED,
+DEFAULT_CONTEXT_NOT_SUPPORTED,
+USER_DATA_NOT_READABLE,
+NO_PSAP_AVAILABLE
+};
+/* user data */
+#define SIMPLY_ENCODED_DATA 0x60
+#define FULLY_ENCODED_DATA 0x61
+
+/* PDV */
+#define SINGLE_ASN1_TYPE 0xa0
+#define OCTET_ALIGNED 0xa1
+#define ARBITRARY 0xa2
+#define DATA_BLOCK 0x81
+
+/* provider reasons */
+enum
+{
+PR_REASON_NOT_SPECIFIED,
+UNRECOGNIZED_PDU,
+UNEXPECTED_PDU,
+UNEXPECTED_SESSION_SERVICE_PRIMITIVE,
+UNRECOGNIZED_PPDU_PARAMETER,
+UNEXPECTED_PPDU_PARAMETER,
+INVALID_PPDU_PARAMETER_VALUE
+};
+/* event identifier */
+enum
+{
+REASON_CP_PPDU,
+REASON_CPA_PPDU,
+REASON_CPR_PPDU,
+REASON_ARU_PPDU,
+REASON_ARP_PPDU,
+REASON_AC_PPDU,
+REASON_ACA_PPDU,
+REASON_TD_PPDU,
+REASON_TTD_PPDU,
+REASON_TE_PPDU,
+REASON_TC_PPDU,
+REASON_TCC_PPDU,
+REASON_RS_PPDU,
+REASON_RSA_PPDU,
+S_RELEASE_INDICATION,
+S_RELEASE_CONFIRM,
+S_TOKEN_GIVE_INDICATION,
+S_TOKEN_PLEASE_INDICATION,
+S_CONTROL_GIVE_INDICATION,
+S_SYNC_MINOR_INDICATION,
+S_SYNC_MINOR_CONFIRM,
+S_SYNC_MAJOR_INDICATION,
+S_SYNC_MAJOR_CONFIRM,
+S_P_EXCEPTION_REPORT_INDICATION,
+S_U_EXCEPTION_REPORT_INDICATION,
+S_ACTIVITY_START_INDICATION,
+S_ACTIVITY_RESUME_INDICATION,
+S_ACTIVITY_INTERRUPT_INDICATION,
+S_ACTIVITY_INTERRUPT_CONFIRM,
+S_ACTIVITY_DISCARD_INDICATION,
+S_ACTIVITY_DISCARD_CONFIRM,
+S_ACTIVITY_END_INDICATION,
+S_ACTIVITY_END_CONFIRM
+};
+
+/* flags */
+#define PRES_PROTOCOL_VERGION 0x0080
+
+#define PRES_CONTEXT_MANAGEMENT 0x0080
+#define PRES_RESTORATION 0x0040
+
+#define ACSE_PRESENTATION_CONTEXT_IDENTIFIER 3
+
+
+#define MAXSTRING 256
+#define UNKNOWN_SES_PDU_TYPE -1
+
+#define ABORT_REASON_LEN 3
+
+
+
diff --git a/epan/dissectors/packet-prism.c b/epan/dissectors/packet-prism.c
new file mode 100644
index 0000000000..57cc16b38a
--- /dev/null
+++ b/epan/dissectors/packet-prism.c
@@ -0,0 +1,313 @@
+/*
+ * packet-prism.c
+ * Decode packets with a Prism header
+ *
+ * Prism II-based wlan devices have a monitoring mode that sticks
+ * a proprietary header on each packet with lots of good
+ * information. This file is responsible for decoding that
+ * data.
+ *
+ * By Tim Newsham
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "packet-ieee80211.h"
+#include "packet-prism.h"
+#include "packet-wlancap.h"
+
+/* protocol */
+static int proto_prism = -1;
+
+/* header fields */
+static int hf_prism_msgcode = -1;
+static int hf_prism_msglen = -1;
+
+/*
+ * A value from the header.
+ *
+ * It appears from looking at the linux-wlan-ng and Prism II HostAP
+ * drivers, and various patches to the orinoco_cs drivers to add
+ * Prism headers, that:
+ *
+ * the "did" identifies what the value is (i.e., what it's the value
+ * of);
+ *
+ * "status" is 0 if the value is present or 1 if it's absent;
+ *
+ * "len" is the length of the value (always 4, in that code);
+ *
+ * "data" is the value of the data (or 0 if not present).
+ *
+ * Note: all of those values are in the *host* byte order of the machine
+ * on which the capture was written.
+ */
+struct val_80211 {
+ unsigned int did;
+ unsigned short status, len;
+ unsigned int data;
+};
+
+/*
+ * Header attached during Prism monitor mode.
+ *
+ * At least according to one paper I've seen, the Prism 2.5 chip set
+ * provides:
+ *
+ * RSSI (receive signal strength indication) is "the total power
+ * received by the radio hardware while receiving the frame,
+ * including signal, interfereence, and background noise";
+ *
+ * "silence value" is "the total power observed just before the
+ * start of the frame".
+ *
+ * None of the drivers I looked at supply the "rssi" or "sq" value,
+ * but they do supply "signal" and "noise" values, along with a "rate"
+ * value that's 1/5 of the raw value from what is presumably a raw
+ * HFA384x frame descriptor, with the comment "set to 802.11 units",
+ * which presumably means the units are 500 Kb/s.
+ *
+ * I infer from the current NetBSD "wi" driver that "signal" and "noise"
+ * are adjusted dBm values, with the dBm value having 100 added to it
+ * for the Prism II cards (although the NetBSD code has an XXX comment
+ * for the #define for WI_PRISM_DBM_OFFSET) and 149 (with no XXX comment)
+ * for the Orinoco cards.
+ */
+struct prism_hdr {
+ unsigned int msgcode, msglen;
+ char devname[16];
+ struct val_80211 hosttime, mactime, channel, rssi, sq, signal,
+ noise, rate, istx, frmlen;
+};
+
+#define VALFIELDS(name) \
+ static int hf_prism_ ## name ## _data = -1
+VALFIELDS(hosttime);
+VALFIELDS(mactime);
+VALFIELDS(channel);
+VALFIELDS(rssi);
+VALFIELDS(sq);
+VALFIELDS(signal);
+VALFIELDS(noise);
+VALFIELDS(rate);
+VALFIELDS(istx);
+VALFIELDS(frmlen);
+
+static gint ett_prism = -1;
+
+static dissector_handle_t ieee80211_handle;
+static dissector_handle_t wlancap_handle;
+
+void
+capture_prism(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ guint32 cookie = 0;
+ guint32 length = 0;
+ if (!BYTES_ARE_IN_FRAME(offset, len, sizeof(guint32) *2 )) {
+ ld->other++;
+ return;
+ }
+
+ cookie = pntohl(pd);
+ length = pntohl(pd+sizeof(guint32));
+
+ /* Handle the new type of capture format */
+ if (cookie == WLANCAP_MAGIC_COOKIE_V1) {
+ if(!BYTES_ARE_IN_FRAME(offset, len, length)) {
+ ld->other++;
+ return;
+ }
+ offset += length;
+ } else {
+ /* We have an old capture format */
+ if(!BYTES_ARE_IN_FRAME(offset, len, (int)sizeof(struct prism_hdr))) {
+ ld->other++;
+ return;
+ }
+ offset += sizeof(struct prism_hdr);
+ }
+
+ /* 802.11 header follows */
+ capture_ieee80211(pd, offset, len, ld);
+
+}
+
+/*
+ * yah, I know, macros, ugh, but it makes the code
+ * below more readable
+ */
+#define IFHELP(size, name, var, str) \
+ if(tree) { \
+ proto_tree_add_uint_format(prism_tree, hf_prism_ ## name, \
+ tvb, offset, size, hdr.var, str, hdr.var); \
+ } \
+ offset += (size)
+#define INTFIELD(size, name, str) IFHELP(size, name, name, str)
+#define VALFIELD(name, str) \
+ if (hdr.name.status == 0) { \
+ if(tree) { \
+ proto_tree_add_uint_format(prism_tree, hf_prism_ ## name ## _data, \
+ tvb, offset, 12, hdr.name.data, \
+ str ": 0x%x (DID 0x%x, Status 0x%x, Length 0x%x)", \
+ hdr.name.data, hdr.name.did, \
+ hdr.name.status, hdr.name.len); \
+ } \
+ } \
+ offset += 12
+
+static void
+dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct prism_hdr hdr;
+ proto_tree *prism_tree = NULL;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+ int offset;
+ guint32 msgcode;
+
+ offset = 0;
+
+ /* handle the new capture type. */
+ msgcode = tvb_get_ntohl(tvb, offset);
+ if (msgcode == WLANCAP_MAGIC_COOKIE_V1) {
+ call_dissector(wlancap_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism");
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %.16s "
+ "Message 0x%x, Length %d", hdr.devname,
+ hdr.msgcode, hdr.msglen);
+
+ if(tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_prism,
+ tvb, 0, sizeof hdr, "Prism Monitoring Header");
+ prism_tree = proto_item_add_subtree(ti, ett_prism);
+ }
+
+ INTFIELD(4, msgcode, "Message Code: %d");
+ INTFIELD(4, msglen, "Message Length: %d");
+ if(tree) {
+ proto_tree_add_text(prism_tree, tvb, offset, sizeof hdr.devname,
+ "Device: %s", hdr.devname);
+ }
+ offset += sizeof hdr.devname;
+
+ VALFIELD(hosttime, "Host Time");
+ VALFIELD(mactime, "MAC Time");
+ VALFIELD(channel, "Channel");
+ if (hdr.rate.status == 0) {
+ if (check_col(pinfo->cinfo, COL_RSSI))
+ col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", hdr.rssi.data);
+ if (tree) {
+ proto_tree_add_uint_format(prism_tree, hf_prism_rssi_data,
+ tvb, offset, 12, hdr.rssi.data,
+ "RSSI: 0x%x (DID 0x%x, Status 0x%x, Length 0x%x)",
+ hdr.rssi.data, hdr.rssi.did, hdr.rssi.status, hdr.rssi.len);
+ }
+ }
+ offset += 12;
+ VALFIELD(sq, "SQ");
+ VALFIELD(signal, "Signal");
+ VALFIELD(noise, "Noise");
+ if (hdr.rate.status == 0) {
+ if (check_col(pinfo->cinfo, COL_TX_RATE)) {
+ col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
+ hdr.rate.data / 2, hdr.rate.data & 1 ? 5 : 0);
+ }
+ if (tree) {
+ proto_tree_add_uint_format(prism_tree, hf_prism_rate_data,
+ tvb, offset, 12, hdr.rate.data,
+ "Data Rate: %u.%u Mb/s",
+ hdr.rate.data / 2, hdr.rate.data & 1 ? 5 : 0);
+ }
+ }
+ offset += 12;
+ VALFIELD(istx, "IsTX");
+ VALFIELD(frmlen, "Frame Length");
+
+ /* dissect the 802.11 header next */
+ next_tvb = tvb_new_subset(tvb, sizeof hdr, -1, -1);
+ call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
+}
+
+#define IFHELP2(size, name, var, str) \
+ { &hf_prism_ ## name, { \
+ str, "prism." #var, size, BASE_HEX, NULL, 0x0, "", HFILL } },
+#define INTFIELD2(size, name, str) IFHELP2(size, name, name, str)
+#define VALFIELD2(name, str) \
+ IFHELP2(FT_UINT32, name ## _data, name.data, str " Field")
+
+void
+proto_register_prism(void)
+{
+ static hf_register_info hf[] = {
+ INTFIELD2(FT_UINT32, msgcode, "Message Code")
+ INTFIELD2(FT_UINT32, msglen, "Message Length")
+ VALFIELD2(hosttime, "Host Time")
+ VALFIELD2(mactime, "MAC Time")
+ VALFIELD2(channel, "Channel")
+ VALFIELD2(rssi, "RSSI")
+ VALFIELD2(sq, "SQ")
+ VALFIELD2(signal, "Signal")
+ VALFIELD2(noise, "Noise")
+ VALFIELD2(rate, "Rate")
+ VALFIELD2(istx, "IsTX")
+ VALFIELD2(frmlen, "Frame Length")
+
+ };
+ static gint *ett[] = {
+ &ett_prism
+ };
+
+ proto_prism = proto_register_protocol("Prism", "Prism", "prism");
+ proto_register_field_array(proto_prism, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_prism(void)
+{
+ dissector_handle_t prism_handle;
+
+ /* handle for 802.11 dissector */
+ ieee80211_handle = find_dissector("wlan");
+ wlancap_handle = find_dissector("wlancap");
+
+ prism_handle = create_dissector_handle(dissect_prism, proto_prism);
+ dissector_add("wtap_encap", WTAP_ENCAP_PRISM_HEADER, prism_handle);
+}
diff --git a/epan/dissectors/packet-prism.h b/epan/dissectors/packet-prism.h
new file mode 100644
index 0000000000..7af1893345
--- /dev/null
+++ b/epan/dissectors/packet-prism.h
@@ -0,0 +1,37 @@
+/*
+ * packet-prism.h
+ * Declarations for packet-prism.c
+ *
+ * prism wlan devices have a monitoring mode that sticks
+ * a proprietary header on each packet with lots of good
+ * information. This file is responsible for decoding that
+ * data.
+ *
+ * By Tim Newsham
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+void capture_prism(const guchar *pd, int offset, int len, packet_counts *ld);
+void proto_register_prism(void);
+void proto_reg_handoff_prism(void);
diff --git a/epan/dissectors/packet-ptp.c b/epan/dissectors/packet-ptp.c
new file mode 100644
index 0000000000..f6081f98a6
--- /dev/null
+++ b/epan/dissectors/packet-ptp.c
@@ -0,0 +1,2126 @@
+/* packet-ptp.c
+ * Routines for PTP (Precision Time Protocol) dissection
+ * Copyright 2004, Auges Tchouante <tchouante2001@yahoo.fr>
+ * Copyright 2004, Dominic Béchaz <bdo@zhwin.ch> , ZHW/InES
+ * Copyright 2004, Markus Seehofer <mseehofe@nt.hirschmann.de>
+ *
+ * A plugin for:
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+
+
+/**********************************************************/
+/* Port definition's for PTP */
+/**********************************************************/
+#define EVENT_PORT_PTP 319
+#define GENERAL_PORT_PTP 320
+
+/*END Port definition's for PTP*/
+
+/**********************************************************/
+/* Offsets of fields within a PTP packet. */
+/**********************************************************/
+
+/*Common offsets for all Messages (Synch, Delay_Req, Follow_Up, Delay_Resp ....)*/
+#define PTP_VERSIONPTP_OFFSET 0
+#define PTP_VERSIONNETWORK_OFFSET 2
+#define PTP_SUBDOMAIN_OFFSET 4
+#define PTP_MESSAGETYPE_OFFSET 20
+#define PTP_SOURCECOMMUNICATIONTECHNOLOGY_OFFSET 21
+#define PTP_SOURCEUUID_OFFSET 22
+#define PTP_SOURCEPORTID_OFFSET 28
+#define PTP_SEQUENCEID_OFFSET 30
+#define PTP_CONTROL_OFFSET 32
+#define PTP_FLAGS_OFFSET 34
+#define PTP_FLAGS_LI61_OFFSET 34
+#define PTP_FLAGS_LI59_OFFSET 34
+#define PTP_FLAGS_BOUNDARY_CLOCK_OFFSET 34
+#define PTP_FLAGS_ASSIST_OFFSET 34
+#define PTP_FLAGS_EXT_SYNC_OFFSET 34
+#define PTP_FLAGS_PARENT_STATS_OFFSET 34
+#define PTP_FLAGS_SYNC_BURST_OFFSET 34
+
+/*Offsets for PTP_Sync and Delay_Req (=SDR) messages*/
+#define PTP_SDR_ORIGINTIMESTAMP_OFFSET 40
+#define PTP_SDR_ORIGINTIMESTAMP_SECONDS_OFFSET 40
+#define PTP_SDR_ORIGINTIMESTAMP_NANOSECONDS_OFFSET 44
+#define PTP_SDR_EPOCHNUMBER_OFFSET 48
+#define PTP_SDR_CURRENTUTCOFFSET_OFFSET 50
+#define PTP_SDR_GRANDMASTERCOMMUNICATIONTECHNOLOGY_OFFSET 53
+#define PTP_SDR_GRANDMASTERCLOCKUUID_OFFSET 54
+#define PTP_SDR_GRANDMASTERPORTID_OFFSET 60
+#define PTP_SDR_GRANDMASTERSEQUENCEID_OFFSET 62
+#define PTP_SDR_GRANDMASTERCLOCKSTRATUM_OFFSET 67
+#define PTP_SDR_GRANDMASTERCLOCKIDENTIFIER_OFFSET 68
+#define PTP_SDR_GRANDMASTERCLOCKVARIANCE_OFFSET 74
+#define PTP_SDR_GRANDMASTERPREFERRED_OFFSET 77
+#define PTP_SDR_GRANDMASTERISBOUNDARYCLOCK_OFFSET 79
+#define PTP_SDR_SYNCINTERVAL_OFFSET 83
+#define PTP_SDR_LOCALCLOCKVARIANCE_OFFSET 86
+#define PTP_SDR_LOCALSTEPSREMOVED_OFFSET 90
+#define PTP_SDR_LOCALCLOCKSTRATUM_OFFSET 95
+#define PTP_SDR_LOCALCLOCKIDENTIFIER_OFFSET 96
+#define PTP_SDR_PARENTCOMMUNICATIONTECHNOLOGY_OFFSET 101
+#define PTP_SDR_PARENTUUID_OFFSET 102
+#define PTP_SDR_PARENTPORTFIELD_OFFSET 110
+#define PTP_SDR_ESTIMATEDMASTERVARIANCE_OFFSET 114
+#define PTP_SDR_ESTIMATEDMASTERDRIFT_OFFSET 116
+#define PTP_SDR_UTCREASONABLE_OFFSET 123
+
+/*Offsets for Follow_Up (=FU) messages*/
+#define PTP_FU_ASSOCIATEDSEQUENCEID_OFFSET 42
+#define PTP_FU_PRECISEORIGINTIMESTAMP_OFFSET 44
+#define PTP_FU_PRECISEORIGINTIMESTAMP_SECONDS_OFFSET 44
+#define PTP_FU_PRECISEORIGINTIMESTAMP_NANOSECONDS_OFFSET 48
+
+/*Offsets for Delay_Resp (=DR) messages*/
+#define PTP_DR_DELAYRECEIPTTIMESTAMP_OFFSET 40
+#define PTP_DR_DELAYRECEIPTTIMESTAMP_SECONDS_OFFSET 40
+#define PTP_DR_DELAYRECEIPTTIMESTAMP_NANOSECONDS_OFFSET 44
+#define PTP_DR_REQUESTINGSOURCECOMMUNICATIONTECHNOLOGY_OFFSET 49
+#define PTP_DR_REQUESTINGSOURCEUUID_OFFSET 50
+#define PTP_DR_REQUESTINGSOURCEPORTID_OFFSET 56
+#define PTP_DR_REQUESTINGSOURCESEQUENCEID_OFFSET 58
+
+/*Offsets for Management (=MM) messages*/
+#define PTP_MM_TARGETCOMMUNICATIONTECHNOLOGY_OFFSET 41
+#define PTP_MM_TARGETUUID_OFFSET 42
+#define PTP_MM_TARGETPORTID_OFFSET 48
+#define PTP_MM_BOUNDARYHOPS_OFFSET 52
+#define PTP_MM_MANAGEMENTMESSAGEKEY_OFFSET 55
+#define PTP_MM_PARAMETERLENGTH_OFFSET 58
+ /*PARAMETERLENGTH > 0*/
+#define PTP_MM_MESSAGEPARAMETERS_OFFSET 60
+ /*PTP_MM_CLOCK_IDENTITY (PARAMETERLENGTH = 64)*/
+#define PTP_MM_CLOCK_IDENTITY_CLOCKCOMMUNICATIONTECHNOLOGY_OFFSET 63
+#define PTP_MM_CLOCK_IDENTITY_CLOCKUUIDFIELD_OFFSET 64
+#define PTP_MM_CLOCK_IDENTITY_CLOCKPORTFIELD_OFFSET 74
+#define PTP_MM_CLOCK_IDENTITY_MANUFACTURERIDENTITY_OFFSET 76
+
+ /*PTP_MM_INITIALIZE_CLOCK (PARAMETERLENGTH = 4)*/
+#define PTP_MM_INITIALIZE_CLOCK_INITIALISATIONKEY_OFFSET 62
+
+ /*PTP_MM_SET_SUBDOMAIN (PARAMETERLENGTH = 16)*/
+#define PTP_MM_SET_SUBDOMAIN_SUBDOMAINNAME_OFFSET 60
+
+ /*PTP_MM_DEFAULT_DATA_SET (PARAMETERLENGTH = 76)*/
+#define PTP_MM_DEFAULT_DATA_SET_CLOCKCOMMUNICATIONTECHNOLOGY_OFFSET 63
+#define PTP_MM_DEFAULT_DATA_SET_CLOCKUUIDFIELD_OFFSET 64
+#define PTP_MM_DEFAULT_DATA_SET_CLOCKPORTFIELD_OFFSET 74
+#define PTP_MM_DEFAULT_DATA_SET_CLOCKSTRATUM_OFFSET 79
+#define PTP_MM_DEFAULT_DATA_SET_CLOCKIDENTIFIER_OFFSET 80
+#define PTP_MM_DEFAULT_DATA_SET_CLOCKVARIANCE_OFFSET 86
+#define PTP_MM_DEFAULT_DATA_SET_CLOCKFOLLOWUPCAPABLE_OFFSET 89
+#define PTP_MM_DEFAULT_DATA_SET_PREFERRED_OFFSET 95
+#define PTP_MM_DEFAULT_DATA_SET_INITIALIZABLE_OFFSET 99
+#define PTP_MM_DEFAULT_DATA_SET_EXTERNALTIMING_OFFSET 103
+#define PTP_MM_DEFAULT_DATA_SET_ISBOUNDARYCLOCK_OFFSET 107
+#define PTP_MM_DEFAULT_DATA_SET_SYNCINTERVAL_OFFSET 111
+#define PTP_MM_DEFAULT_DATA_SET_SUBDOMAINNAME_OFFSET 112
+#define PTP_MM_DEFAULT_DATA_SET_NUMBERPORTS_OFFSET 130
+#define PTP_MM_DEFAULT_DATA_SET_NUMBERFOREIGNRECORDS_OFFSET 134
+
+ /*PTP_MM_UPDATE_DEFAULT_DATA_SET (PARAMETERLENGTH = 36)*/
+#define PTP_MM_UPDATE_DEFAULT_DATA_SET_CLOCKSTRATUM_OFFSET 63
+#define PTP_MM_UPDATE_DEFAULT_DATA_SET_CLOCKIDENTIFIER_OFFSET 64
+#define PTP_MM_UPDATE_DEFAULT_DATA_SET_CLOCKVARIANCE_OFFSET 70
+#define PTP_MM_UPDATE_DEFAULT_DATA_SET_PREFERRED_OFFSET 75
+#define PTP_MM_UPDATE_DEFAULT_DATA_SET_SYNCINTERVAL_OFFSET 79
+#define PTP_MM_UPDATE_DEFAULT_DATA_SET_SUBDOMAINNAME_OFFSET 80
+
+ /*PTP_MM_CURRENT_DATA_SET (PARAMETERLENGTH = 20)*/
+#define PTP_MM_CURRENT_DATA_SET_STEPSREMOVED_OFFSET 62
+#define PTP_MM_CURRENT_DATA_SET_OFFSETFROMMASTER_OFFSET 64
+#define PTP_MM_CURRENT_DATA_SET_OFFSETFROMMASTERSECONDS_OFFSET 64
+#define PTP_MM_CURRENT_DATA_SET_OFFSETFROMMASTERNANOSECONDS_OFFSET 68
+#define PTP_MM_CURRENT_DATA_SET_ONEWAYDELAY_OFFSET 72
+#define PTP_MM_CURRENT_DATA_SET_ONEWAYDELAYSECONDS_OFFSET 72
+#define PTP_MM_CURRENT_DATA_SET_ONEWAYDELAYNANOSECONDS_OFFSET 76
+
+ /*PTP_MM_PARENT_DATA_SET (PARAMETERLENGTH = 90)*/
+#define PTP_MM_PARENT_DATA_SET_PARENTCOMMUNICATIONTECHNOLOGY_OFFSET 63
+#define PTP_MM_PARENT_DATA_SET_PARENTUUID_OFFSET 64
+#define PTP_MM_PARENT_DATA_SET_PARENTPORTID_OFFSET 74
+#define PTP_MM_PARENT_DATA_SET_PARENTLASTSYNCSEQUENCENUMBER_OFFSET 78
+#define PTP_MM_PARENT_DATA_SET_PARENTFOLLOWUPCAPABLE_OFFSET 83
+#define PTP_MM_PARENT_DATA_SET_PARENTEXTERNALTIMING_OFFSET 87
+#define PTP_MM_PARENT_DATA_SET_PARENTVARIANCE_OFFSET 90
+#define PTP_MM_PARENT_DATA_SET_PARENTSTATS_OFFSET 95
+#define PTP_MM_PARENT_DATA_SET_OBSERVEDVARIANCE_OFFSET 98
+#define PTP_MM_PARENT_DATA_SET_OBSERVEDDRIFT_OFFSET 100
+#define PTP_MM_PARENT_DATA_SET_UTCREASONABLE_OFFSET 107
+#define PTP_MM_PARENT_DATA_SET_GRANDMASTERCOMMUNICATIONTECHNOLOGY_OFFSET 111
+#define PTP_MM_PARENT_DATA_SET_GRANDMASTERUUIDFIELD_OFFSET 112
+#define PTP_MM_PARENT_DATA_SET_GRANDMASTERPORTIDFIELD_OFFSET 122
+#define PTP_MM_PARENT_DATA_SET_GRANDMASTERSTRATUM_OFFSET 127
+#define PTP_MM_PARENT_DATA_SET_GRANDMASTERIDENTIFIER_OFFSET 128
+#define PTP_MM_PARENT_DATA_SET_GRANDMASTERVARIANCE_OFFSET 134
+#define PTP_MM_PARENT_DATA_SET_GRANDMASTERPREFERRED_OFFSET 139
+#define PTP_MM_PARENT_DATA_SET_GRANDMASTERISBOUNDARYCLOCK_OFFSET 143
+#define PTP_MM_PARENT_DATA_SET_GRANDMASTERSEQUENCENUMBER_OFFSET 146
+
+ /*PTP_MM_PORT_DATA_SET (PARAMETERLENGTH = 52)*/
+#define PTP_MM_PORT_DATA_SET_RETURNEDPORTNUMBER_OFFSET 62
+#define PTP_MM_PORT_DATA_SET_PORTSTATE_OFFSET 67
+#define PTP_MM_PORT_DATA_SET_LASTSYNCEVENTSEQUENCENUMBER_OFFSET 70
+#define PTP_MM_PORT_DATA_SET_LASTGENERALEVENTSEQUENCENUMBER_OFFSET 74
+#define PTP_MM_PORT_DATA_SET_PORTCOMMUNICATIONTECHNOLOGY_OFFSET 79
+#define PTP_MM_PORT_DATA_SET_PORTUUIDFIELD_OFFSET 80
+#define PTP_MM_PORT_DATA_SET_PORTIDFIELD_OFFSET 90
+#define PTP_MM_PORT_DATA_SET_BURSTENABLED_OFFSET 95
+#define PTP_MM_PORT_DATA_SET_SUBDOMAINADDRESSOCTETS_OFFSET 97
+#define PTP_MM_PORT_DATA_SET_EVENTPORTADDRESSOCTETS_OFFSET 98
+#define PTP_MM_PORT_DATA_SET_GENERALPORTADDRESSOCTETS_OFFSET 99
+#define PTP_MM_PORT_DATA_SET_SUBDOMAINADDRESS_OFFSET 100
+#define PTP_MM_PORT_DATA_SET_EVENTPORTADDRESS_OFFSET 106
+#define PTP_MM_PORT_DATA_SET_GENERALPORTADDRESS_OFFSET 110
+
+ /*PTP_MM_GLOBAL_TIME_DATA_SET (PARAMETERLENGTH = 24)*/
+#define PTP_MM_GLOBAL_TIME_DATA_SET_LOCALTIME_OFFSET 60
+#define PTP_MM_GLOBAL_TIME_DATA_SET_LOCALTIMESECONDS_OFFSET 60
+#define PTP_MM_GLOBAL_TIME_DATA_SET_LOCALTIMENANOSECONDS_OFFSET 64
+#define PTP_MM_GLOBAL_TIME_DATA_SET_CURRENTUTCOFFSET_OFFSET 70
+#define PTP_MM_GLOBAL_TIME_DATA_SET_LEAP59_OFFSET 75
+#define PTP_MM_GLOBAL_TIME_DATA_SET_LEAP61_OFFSET 79
+#define PTP_MM_GLOBAL_TIME_DATA_SET_EPOCHNUMBER_OFFSET 82
+
+ /*PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES (PARAMETERLENGTH = 16)*/
+#define PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES_CURRENTUTCOFFSET_OFFSET 62
+#define PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES_LEAP59_OFFSET 67
+#define PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES_LEAP61_OFFSET 71
+#define PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES_EPOCHNUMBER_OFFSET 74
+
+ /*PTP_MM_GET_FOREIGN_DATA_SET (PARAMETERLENGTH = 4)*/
+#define PTP_MM_GET_FOREIGN_DATA_SET_RECORDKEY_OFFSET 62
+
+ /*PTP_MM_FOREIGN_DATA_SET (PARAMETERLENGTH = 28)*/
+#define PTP_MM_FOREIGN_DATA_SET_RETURNEDPORTNUMBER_OFFSET 62
+#define PTP_MM_FOREIGN_DATA_SET_RETURNEDRECORDNUMBER_OFFSET 66
+#define PTP_MM_FOREIGN_DATA_SET_FOREIGNMASTERCOMMUNICATIONTECHNOLOGY_OFFSET 71
+#define PTP_MM_FOREIGN_DATA_SET_FOREIGNMASTERUUIDFIELD_OFFSET 72
+#define PTP_MM_FOREIGN_DATA_SET_FOREIGNMASTERPORTIDFIELD_OFFSET 82
+#define PTP_MM_FOREIGN_DATA_SET_FOREIGNMASTERSYNCS_OFFSET 86
+
+ /*PTP_MM_SET_SYNC_INTERVAL (PARAMETERLENGTH = 4)*/
+#define PTP_MM_SET_SYNC_INTERVAL_SYNCINTERVAL_OFFSET 62
+
+ /*PTP_MM_SET_TIME (PARAMETERLENGTH = 8)*/
+#define PTP_MM_SET_TIME_LOCALTIME_OFFSET 60
+#define PTP_MM_SET_TIME_LOCALTIMESECONDS_OFFSET 60
+#define PTP_MM_SET_TIME_LOCALTIMENANOSECONDS_OFFSET 64
+
+/*END Offsets of fields within a PTP packet.*/
+
+/**********************************************************/
+/* flag-field-mask-definitions */
+/**********************************************************/
+#define PTP_FLAGS_LI61_BITMASK 0x01
+#define PTP_FLAGS_LI59_BITMASK 0x02
+#define PTP_FLAGS_BOUNDARY_CLOCK_BITMASK 0x04
+#define PTP_FLAGS_ASSIST_BITMASK 0x08
+#define PTP_FLAGS_EXT_SYNC_BITMASK 0x10
+#define PTP_FLAGS_PARENT_STATS_BITMASK 0x20
+#define PTP_FLAGS_SYNC_BURST_BITMASK 0x40
+
+/*END flag-field-mask-definitions*/
+
+/**********************************************************/
+/* managementMessage definitions */
+/**********************************************************/
+#define PTP_MM_NULL 0
+#define PTP_MM_OBTAIN_IDENTITY 1
+#define PTP_MM_CLOCK_IDENTITY 2
+#define PTP_MM_INITIALIZE_CLOCK 3
+#define PTP_MM_SET_SUBDOMAIN 4
+#define PTP_MM_CLEAR_DESIGNATED_PREFERRED_MASTER 5
+#define PTP_MM_SET_DESIGNATED_PREFERRED_MASTER 6
+#define PTP_MM_GET_DEFAULT_DATA_SET 7
+#define PTP_MM_DEFAULT_DATA_SET 8
+#define PTP_MM_UPDATE_DEFAULT_DATA_SET 9
+#define PTP_MM_GET_CURRENT_DATA_SET 10
+#define PTP_MM_CURRENT_DATA_SET 11
+#define PTP_MM_GET_PARENT_DATA_SET 12
+#define PTP_MM_PARENT_DATA_SET 13
+#define PTP_MM_GET_PORT_DATA_SET 14
+#define PTP_MM_PORT_DATA_SET 15
+#define PTP_MM_GET_GLOBAL_TIME_DATA_SET 16
+#define PTP_MM_GLOBAL_TIME_DATA_SET 17
+#define PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES 18
+#define PTP_MM_GOTO_FAULTY_STATE 19
+#define PTP_MM_GET_FOREIGN_DATA_SET 20
+#define PTP_MM_FOREIGN_DATA_SET 21
+#define PTP_MM_SET_SYNC_INTERVAL 22
+#define PTP_MM_DISABLE_PORT 23
+#define PTP_MM_ENABLE_PORT 24
+#define PTP_MM_DISABLE_BURST 25
+#define PTP_MM_ENABLE_BURST 26
+#define PTP_MM_SET_TIME 27
+
+static const value_string ptp_managementMessageKey_vals[] = {
+ {PTP_MM_NULL, "PTP_MM_NULL"},
+ {PTP_MM_OBTAIN_IDENTITY, "PTP_MM_OBTAIN_IDENTITY"},
+ {PTP_MM_CLOCK_IDENTITY, "PTP_MM_CLOCK_IDENTITY"},
+ {PTP_MM_INITIALIZE_CLOCK, "PTP_MM_INITIALIZE_CLOCK"},
+ {PTP_MM_SET_SUBDOMAIN, "PTP_MM_SET_SUBDOMAIN"},
+ {PTP_MM_CLEAR_DESIGNATED_PREFERRED_MASTER, "PTP_MM_CLEAR_DESIGNATED_PREFERRED_MASTER"},
+ {PTP_MM_SET_DESIGNATED_PREFERRED_MASTER, "PTP_MM_SET_DESIGNATED_PREFERRED_MASTER"},
+ {PTP_MM_GET_DEFAULT_DATA_SET, "PTP_MM_GET_DEFAULT_DATA_SET"},
+ {PTP_MM_DEFAULT_DATA_SET, "PTP_MM_DEFAULT_DATA_SET"},
+ {PTP_MM_UPDATE_DEFAULT_DATA_SET, "PTP_MM_UPDATE_DEFAULT_DATA_SET"},
+ {PTP_MM_GET_CURRENT_DATA_SET, "PTP_MM_GET_CURRENT_DATA_SET"},
+ {PTP_MM_CURRENT_DATA_SET, "PTP_MM_CURRENT_DATA_SET"},
+ {PTP_MM_GET_PARENT_DATA_SET, "PTP_MM_GET_PARENT_DATA_SET"},
+ {PTP_MM_PARENT_DATA_SET, "PTP_MM_PARENT_DATA_SET"},
+ {PTP_MM_GET_PORT_DATA_SET, "PTP_MM_GET_PORT_DATA_SET"},
+ {PTP_MM_PORT_DATA_SET, "PTP_MM_PORT_DATA_SET"},
+ {PTP_MM_GET_GLOBAL_TIME_DATA_SET, "PTP_MM_GET_GLOBAL_TIME_DATA_SET"},
+ {PTP_MM_GLOBAL_TIME_DATA_SET, "PTP_MM_GLOBAL_TIME_DATA_SET"},
+ {PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES, "PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES"},
+ {PTP_MM_GOTO_FAULTY_STATE, "PTP_MM_GOTO_FAULTY_STATE"},
+ {PTP_MM_GET_FOREIGN_DATA_SET, "PTP_MM_GET_FOREIGN_DATA_SET"},
+ {PTP_MM_FOREIGN_DATA_SET, "PTP_MM_FOREIGN_DATA_SET"},
+ {PTP_MM_SET_SYNC_INTERVAL, "PTP_MM_SET_SYNC_INTERVAL"},
+ {PTP_MM_DISABLE_PORT, "PTP_MM_DISABLE_PORT"},
+ {PTP_MM_ENABLE_PORT, "PTP_MM_ENABLE_PORT"},
+ {PTP_MM_DISABLE_BURST, "PTP_MM_DISABLE_BURST"},
+ {PTP_MM_ENABLE_BURST, "PTP_MM_ENABLE_BURST"},
+ {PTP_MM_SET_TIME, "PTP_MM_SET_TIME"},
+ {0, NULL } };
+ /*same again but better readable text for info column*/
+ static const value_string ptp_managementMessageKey_infocolumn_vals[] = {
+ {PTP_MM_NULL, "Null"},
+ {PTP_MM_OBTAIN_IDENTITY, "Obtain Identity"},
+ {PTP_MM_CLOCK_IDENTITY, "Clock Identity"},
+ {PTP_MM_INITIALIZE_CLOCK, "Initialize Clock"},
+ {PTP_MM_SET_SUBDOMAIN, "Set Subdomain"},
+ {PTP_MM_CLEAR_DESIGNATED_PREFERRED_MASTER, "Clear Designated Preferred Master"},
+ {PTP_MM_SET_DESIGNATED_PREFERRED_MASTER, "Set Designated Preferred Master"},
+ {PTP_MM_GET_DEFAULT_DATA_SET, "Get Default Data Set"},
+ {PTP_MM_DEFAULT_DATA_SET, "Default Data Set"},
+ {PTP_MM_UPDATE_DEFAULT_DATA_SET, "Update Default Data Set"},
+ {PTP_MM_GET_CURRENT_DATA_SET, "Get Current Data Set"},
+ {PTP_MM_CURRENT_DATA_SET, "Current Data Set"},
+ {PTP_MM_GET_PARENT_DATA_SET, "Get Parent Data Set"},
+ {PTP_MM_PARENT_DATA_SET, "Parent Data Set"},
+ {PTP_MM_GET_PORT_DATA_SET, "Get Port Data Set"},
+ {PTP_MM_PORT_DATA_SET, "Port Data Set"},
+ {PTP_MM_GET_GLOBAL_TIME_DATA_SET, "Get Global Time Data Set"},
+ {PTP_MM_GLOBAL_TIME_DATA_SET, "Global Time Data Set"},
+ {PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES, "Update Global Time Properties"},
+ {PTP_MM_GOTO_FAULTY_STATE, "Goto Faulty State"},
+ {PTP_MM_GET_FOREIGN_DATA_SET, "Get Foreign Data Set"},
+ {PTP_MM_FOREIGN_DATA_SET, "Foreign Data Set"},
+ {PTP_MM_SET_SYNC_INTERVAL, "Set Sync Interval"},
+ {PTP_MM_DISABLE_PORT, "Disable Port"},
+ {PTP_MM_ENABLE_PORT, "Enable Port"},
+ {PTP_MM_DISABLE_BURST, "Disable Burst"},
+ {PTP_MM_ENABLE_BURST, "Enable Burst"},
+ {PTP_MM_SET_TIME, "Set Time"},
+ {0, NULL } };
+
+/*END managementMessage definitions*/
+
+/**********************************************************/
+/* CommunicationId definitions */
+/**********************************************************/
+#define PTP_CLOSED 0
+#define PTP_ETHER 1
+#define PTP_FFBUS 4
+#define PTP_PROFIBUS 5
+#define PTP_LON 6
+#define PTP_DNET 7
+#define PTP_SDS 8
+#define PTP_CONTROLNET 9
+#define PTP_CANOPEN 10
+#define PTP_IEEE1394 243
+#define PTP_IEEE802_11A 244
+#define PTP_IEEE_WIRELESS 245
+#define PTP_INFINIBAND 246
+#define PTP_BLUETOOTH 247
+#define PTP_IEEE802_15_1 248
+#define PTP_IEEE1451_3 249
+#define PTP_IEEE1451_5 250
+#define PTP_USB 251
+#define PTP_ISA 252
+#define PTP_PCI 253
+#define PTP_VXI 254
+#define PTP_DEFAULT 255
+
+static const value_string ptp_communicationid_vals[] = {
+ {PTP_CLOSED, "Closed system outside the scope of this standard."},
+ {PTP_ETHER, "IEEE 802.3 (Ethernet)"},
+ {PTP_FFBUS, "FoundationFieldbus"},
+ {PTP_PROFIBUS, "PROFIBUS"},
+ {PTP_LON, "LonTalk"},
+ {PTP_DNET, "DeviceNet"},
+ {PTP_SDS, "SmartDistributedSystem"},
+ {PTP_CONTROLNET, "ControlNet"},
+ {PTP_CANOPEN, "CANopen"},
+ {PTP_IEEE1394, "IEEE 1394"},
+ {PTP_IEEE802_11A, "IEEE 802.11a"},
+ {PTP_IEEE_WIRELESS, "IEEE 802.11b"},
+ {PTP_INFINIBAND, "InfiniBand"},
+ {PTP_BLUETOOTH, "Bluetooth wireless"},
+ {PTP_IEEE802_15_1, "IEEE 802.15.1"},
+ {PTP_IEEE1451_3, "IEEE 1451.3"},
+ {PTP_IEEE1451_5, "IEEE 1451.5"},
+ {PTP_USB, "USB bus"},
+ {PTP_ISA, "ISA bus"},
+ {PTP_PCI, "PCI bus"},
+ {PTP_VXI, "VXI bus"},
+ {PTP_DEFAULT, "Default value"},
+ {0, NULL } };
+
+/*END CommunicationId definitions*/
+
+/**********************************************************/
+/* PTP message types (PTP_CONTROL field) */
+/**********************************************************/
+#define PTP_SYNC_MESSAGE 0x00
+#define PTP_DELAY_REQ_MESSAGE 0x01
+#define PTP_FOLLOWUP_MESSAGE 0x02
+#define PTP_DELAY_RESP_MESSAGE 0x03
+#define PTP_MANAGEMENT_MESSAGE 0x04
+
+static const value_string ptp_control_vals[] = {
+ {PTP_SYNC_MESSAGE, "Sync Message"},
+ {PTP_DELAY_REQ_MESSAGE, "Delay_Req Message"},
+ {PTP_FOLLOWUP_MESSAGE, "Follow_Up Message"},
+ {PTP_DELAY_RESP_MESSAGE, "Delay_Resp Message"},
+ {PTP_MANAGEMENT_MESSAGE, "Management Message"},
+ {0, NULL } };
+
+/*END PTP message types*/
+
+/**********************************************************/
+/* Channel values for the PTP_MESSAGETYPE field */
+/**********************************************************/
+#define PTP_MESSAGETYPE_EVENT 0x01
+#define PTP_MESSAGETYPE_GENERAL 0x02
+
+static const value_string ptp_messagetype_vals[] = {
+ {PTP_MESSAGETYPE_EVENT, "Event Message"},
+ {PTP_MESSAGETYPE_GENERAL, "General Message"},
+ {0, NULL } };
+
+/*END channel values for the PTP_MESSAGETYPE field*/
+
+/* Channel values for boolean vals (FLAGS)*/
+
+static const value_string ptp_bool_vals[] = {
+ {1, "True"},
+ {0, "False"},
+ {0, NULL }};
+
+/**********************************************************/
+/* Initialize the protocol and registered fields */
+/**********************************************************/
+
+static int proto_ptp = -1;
+static int hf_ptp_versionptp = -1;
+static int hf_ptp_versionnetwork = -1;
+static int hf_ptp_subdomain = -1;
+static int hf_ptp_messagetype = -1;
+static int hf_ptp_sourcecommunicationtechnology = -1;
+static int hf_ptp_sourceuuid = -1;
+static int hf_ptp_sourceportid = -1;
+static int hf_ptp_sequenceid = -1;
+static int hf_ptp_control = -1;
+static int hf_ptp_flags = -1;
+static int hf_ptp_flags_li61 = -1;
+static int hf_ptp_flags_li59 = -1;
+static int hf_ptp_flags_boundary_clock = -1;
+static int hf_ptp_flags_assist = -1;
+static int hf_ptp_flags_ext_sync = -1;
+static int hf_ptp_flags_parent = -1;
+static int hf_ptp_flags_sync_burst = -1;
+
+/*offsets for ptp_sync and delay_req (=sdr) messages*/
+static int hf_ptp_origintimestamp = -1; /*Field for seconds & nanoseconds*/
+static int hf_ptp_sdr_origintimestamp_seconds = -1;
+static int hf_ptp_sdr_origintimestamp_nanoseconds = -1;
+static int hf_ptp_sdr_epochnumber = -1;
+static int hf_ptp_sdr_currentutcoffset = -1;
+static int hf_ptp_sdr_grandmastercommunicationtechnology = -1;
+static int hf_ptp_sdr_grandmasterclockuuid = -1;
+static int hf_ptp_sdr_grandmasterportid = -1;
+static int hf_ptp_sdr_grandmastersequenceid = -1;
+static int hf_ptp_sdr_grandmasterclockstratum = -1;
+static int hf_ptp_sdr_grandmasterclockidentifier = -1;
+static int hf_ptp_sdr_grandmasterclockvariance = -1;
+static int hf_ptp_sdr_grandmasterpreferred = -1;
+static int hf_ptp_sdr_grandmasterisboundaryclock = -1;
+static int hf_ptp_sdr_syncinterval = -1;
+static int hf_ptp_sdr_localclockvariance = -1;
+static int hf_ptp_sdr_localstepsremoved = -1;
+static int hf_ptp_sdr_localclockstratum = -1;
+static int hf_ptp_sdr_localclockidentifier = -1;
+static int hf_ptp_sdr_parentcommunicationtechnology = -1;
+static int hf_ptp_sdr_parentuuid = -1;
+static int hf_ptp_sdr_parentportfield = -1;
+static int hf_ptp_sdr_estimatedmastervariance = -1;
+static int hf_ptp_sdr_estimatedmasterdrift = -1;
+static int hf_ptp_sdr_utcreasonable = -1;
+
+/*offsets for follow_up (=fu) messages*/
+static int hf_ptp_fu_associatedsequenceid = -1;
+static int hf_ptp_fu_preciseorigintimestamp = -1;
+static int hf_ptp_fu_preciseorigintimestamp_seconds = -1;
+static int hf_ptp_fu_preciseorigintimestamp_nanoseconds = -1;
+
+/*offsets for delay_resp (=dr) messages*/
+static int hf_ptp_dr_delayreceipttimestamp = -1;
+static int hf_ptp_dr_delayreceipttimestamp_seconds = -1;
+static int hf_ptp_dr_delayreceipttimestamp_nanoseconds = -1;
+static int hf_ptp_dr_requestingsourcecommunicationtechnology = -1;
+static int hf_ptp_dr_requestingsourceuuid = -1;
+static int hf_ptp_dr_requestingsourceportid = -1;
+static int hf_ptp_dr_requestingsourcesequenceid = -1;
+
+/*offsets for management (=mm) messages*/
+static int hf_ptp_mm_targetcommunicationtechnology = -1;
+static int hf_ptp_mm_targetuuid = -1;
+static int hf_ptp_mm_targetportid = -1;
+static int hf_ptp_mm_boundaryhops = -1;
+static int hf_ptp_mm_managementmessagekey = -1;
+static int hf_ptp_mm_parameterlength = -1;
+ /*parameterlength > 0*/
+static int hf_ptp_mm_messageparameters = -1;
+ /*ptp_mm_clock_identity (parameterlength = 64)*/
+static int hf_ptp_mm_clock_identity_clockcommunicationtechnology = -1;
+static int hf_ptp_mm_clock_identity_clockuuidfield = -1;
+static int hf_ptp_mm_clock_identity_clockportfield = -1;
+static int hf_ptp_mm_clock_identity_manufactureridentity = -1;
+
+ /*ptp_mm_initialize_clock (parameterlength = 4)*/
+static int hf_ptp_mm_initialize_clock_initialisationkey = -1;
+
+ /*ptp_mm_set_subdomain (parameterlength = 16)*/
+static int hf_ptp_mm_set_subdomain_subdomainname = -1;
+
+ /*ptp_mm_default_data_set (parameterlength = 76)*/
+static int hf_ptp_mm_default_data_set_clockcommunicationtechnology = -1;
+static int hf_ptp_mm_default_data_set_clockuuidfield = -1;
+static int hf_ptp_mm_default_data_set_clockportfield = -1;
+static int hf_ptp_mm_default_data_set_clockstratum = -1;
+static int hf_ptp_mm_default_data_set_clockidentifier = -1;
+static int hf_ptp_mm_default_data_set_clockvariance = -1;
+static int hf_ptp_mm_default_data_set_clockfollowupcapable = -1;
+static int hf_ptp_mm_default_data_set_preferred = -1;
+static int hf_ptp_mm_default_data_set_initializable = -1;
+static int hf_ptp_mm_default_data_set_externaltiming = -1;
+static int hf_ptp_mm_default_data_set_isboundaryclock = -1;
+static int hf_ptp_mm_default_data_set_syncinterval = -1;
+static int hf_ptp_mm_default_data_set_subdomainname = -1;
+static int hf_ptp_mm_default_data_set_numberports = -1;
+static int hf_ptp_mm_default_data_set_numberforeignrecords = -1;
+
+ /*ptp_mm_update_default_data_set (parameterlength = 36)*/
+static int hf_ptp_mm_update_default_data_set_clockstratum = -1;
+static int hf_ptp_mm_update_default_data_set_clockidentifier = -1;
+static int hf_ptp_mm_update_default_data_set_clockvariance = -1;
+static int hf_ptp_mm_update_default_data_set_preferred = -1;
+static int hf_ptp_mm_update_default_data_set_syncinterval = -1;
+static int hf_ptp_mm_update_default_data_set_subdomainname = -1;
+
+ /*ptp_mm_current_data_set (parameterlength = 20)*/
+static int hf_ptp_mm_current_data_set_stepsremoved = -1;
+static int hf_ptp_mm_current_data_set_offsetfrommaster = -1;
+static int hf_ptp_mm_current_data_set_offsetfrommasterseconds = -1;
+static int hf_ptp_mm_current_data_set_offsetfrommasternanoseconds = -1;
+static int hf_ptp_mm_current_data_set_onewaydelay = -1;
+static int hf_ptp_mm_current_data_set_onewaydelayseconds = -1;
+static int hf_ptp_mm_current_data_set_onewaydelaynanoseconds = -1;
+
+ /*ptp_mm_parent_data_set (parameterlength = 90)*/
+static int hf_ptp_mm_parent_data_set_parentcommunicationtechnology = -1;
+static int hf_ptp_mm_parent_data_set_parentuuid = -1;
+static int hf_ptp_mm_parent_data_set_parentportid = -1;
+static int hf_ptp_mm_parent_data_set_parentlastsyncsequencenumber = -1;
+static int hf_ptp_mm_parent_data_set_parentfollowupcapable = -1;
+static int hf_ptp_mm_parent_data_set_parentexternaltiming = -1;
+static int hf_ptp_mm_parent_data_set_parentvariance = -1;
+static int hf_ptp_mm_parent_data_set_parentstats = -1;
+static int hf_ptp_mm_parent_data_set_observedvariance = -1;
+static int hf_ptp_mm_parent_data_set_observeddrift = -1;
+static int hf_ptp_mm_parent_data_set_utcreasonable = -1;
+static int hf_ptp_mm_parent_data_set_grandmastercommunicationtechnology = -1;
+static int hf_ptp_mm_parent_data_set_grandmasteruuidfield = -1;
+static int hf_ptp_mm_parent_data_set_grandmasterportidfield = -1;
+static int hf_ptp_mm_parent_data_set_grandmasterstratum = -1;
+static int hf_ptp_mm_parent_data_set_grandmasteridentifier = -1;
+static int hf_ptp_mm_parent_data_set_grandmastervariance = -1;
+static int hf_ptp_mm_parent_data_set_grandmasterpreferred = -1;
+static int hf_ptp_mm_parent_data_set_grandmasterisboundaryclock = -1;
+static int hf_ptp_mm_parent_data_set_grandmastersequencenumber = -1;
+
+ /*ptp_mm_port_data_set (parameterlength = 52)*/
+static int hf_ptp_mm_port_data_set_returnedportnumber = -1;
+static int hf_ptp_mm_port_data_set_portstate = -1;
+static int hf_ptp_mm_port_data_set_lastsynceventsequencenumber = -1;
+static int hf_ptp_mm_port_data_set_lastgeneraleventsequencenumber = -1;
+static int hf_ptp_mm_port_data_set_portcommunicationtechnology = -1;
+static int hf_ptp_mm_port_data_set_portuuidfield = -1;
+static int hf_ptp_mm_port_data_set_portidfield = -1;
+static int hf_ptp_mm_port_data_set_burstenabled = -1;
+static int hf_ptp_mm_port_data_set_subdomainaddressoctets = -1;
+static int hf_ptp_mm_port_data_set_eventportaddressoctets = -1;
+static int hf_ptp_mm_port_data_set_generalportaddressoctets = -1;
+static int hf_ptp_mm_port_data_set_subdomainaddress = -1;
+static int hf_ptp_mm_port_data_set_eventportaddress = -1;
+static int hf_ptp_mm_port_data_set_generalportaddress = -1;
+
+ /*ptp_mm_global_time_data_set (parameterlength = 24)*/
+static int hf_ptp_mm_global_time_data_set_localtime = -1;
+static int hf_ptp_mm_global_time_data_set_localtimeseconds = -1;
+static int hf_ptp_mm_global_time_data_set_localtimenanoseconds = -1;
+static int hf_ptp_mm_global_time_data_set_currentutcoffset = -1;
+static int hf_ptp_mm_global_time_data_set_leap59 = -1;
+static int hf_ptp_mm_global_time_data_set_leap61 = -1;
+static int hf_ptp_mm_global_time_data_set_epochnumber = -1;
+
+ /*ptp_mm_update_global_time_properties (parameterlength = 16)*/
+static int hf_ptp_mm_update_global_time_properties_currentutcoffset = -1;
+static int hf_ptp_mm_update_global_time_properties_leap59 = -1;
+static int hf_ptp_mm_update_global_time_properties_leap61 = -1;
+static int hf_ptp_mm_update_global_time_properties_epochnumber = -1;
+
+ /*ptp_mm_get_foreign_data_set (parameterlength = 4)*/
+static int hf_ptp_mm_get_foreign_data_set_recordkey = -1;
+
+ /*ptp_mm_foreign_data_set (parameterlength = 28)*/
+static int hf_ptp_mm_foreign_data_set_returnedportnumber = -1;
+static int hf_ptp_mm_foreign_data_set_returnedrecordnumber = -1;
+static int hf_ptp_mm_foreign_data_set_foreignmastercommunicationtechnology = -1;
+static int hf_ptp_mm_foreign_data_set_foreignmasteruuidfield = -1;
+static int hf_ptp_mm_foreign_data_set_foreignmasterportidfield = -1;
+static int hf_ptp_mm_foreign_data_set_foreignmastersyncs = -1;
+
+ /*ptp_mm_set_sync_interval (parameterlength = 4)*/
+static int hf_ptp_mm_set_sync_interval_syncinterval = -1;
+
+ /*ptp_mm_set_time (parameterlength = 8)*/
+static int hf_ptp_mm_set_time_localtime = -1;
+static int hf_ptp_mm_set_time_localtimeseconds = -1;
+static int hf_ptp_mm_set_time_localtimenanoseconds = -1;
+
+/*END Initialize the protocol and registered fields */
+
+/* Initialize the subtree pointers */
+static gint ett_ptp = -1;
+static gint ett_ptp_flags = -1;
+static gint ett_ptp_time = -1;
+static gint ett_ptp_time2 = -1;
+
+
+/* Code to actually dissect the packets */
+static void
+dissect_ptp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 ptp_control, ptp_mm_messagekey = 0;
+ nstime_t ts; /*time structure with seconds and nanoseconds*/
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti, *flags_ti, *time_ti, *time2_ti;
+ proto_tree *ptp_tree, *ptp_flags_tree, *ptp_time_tree, *ptp_time2_tree;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "PTP");
+
+
+/* Get control field (what kind of message is this? (Sync, DelayReq, ....) */
+
+ ptp_control = tvb_get_guint8 (tvb, PTP_CONTROL_OFFSET);
+ /* MGMT packet? */
+ if ( ptp_control == PTP_MANAGEMENT_MESSAGE ){
+ /* Get the managementMessageKey */
+ ptp_mm_messagekey = tvb_get_guint8(tvb, PTP_MM_MANAGEMENTMESSAGEKEY_OFFSET);
+ }
+
+/* Create and set the string for "Info" column */
+ switch(ptp_control){
+ case PTP_SYNC_MESSAGE:{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Sync Message");
+ break;
+ }
+ case PTP_DELAY_REQ_MESSAGE:{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Delay_Request Message");
+ break;
+ }
+ case PTP_FOLLOWUP_MESSAGE:{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Follow_Up Message");
+ break;
+ }
+ case PTP_DELAY_RESP_MESSAGE:{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Delay_Response Message");
+ break;
+ }
+ case PTP_MANAGEMENT_MESSAGE:{
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Management Message (%s)",
+ val_to_str(ptp_mm_messagekey,
+ ptp_managementMessageKey_infocolumn_vals,
+ "Unknown message key %u"));
+ }
+ break;
+ }
+ default:{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "Unknown Message");
+ break;
+ }
+ }
+
+ if (tree) {
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_ptp, tvb, 0, -1, FALSE);
+
+ ptp_tree = proto_item_add_subtree(ti, ett_ptp);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_versionptp, tvb, PTP_VERSIONPTP_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_versionnetwork, tvb, PTP_VERSIONNETWORK_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_subdomain, tvb, PTP_SUBDOMAIN_OFFSET, 16, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_messagetype, tvb, PTP_MESSAGETYPE_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sourcecommunicationtechnology, tvb, PTP_SOURCECOMMUNICATIONTECHNOLOGY_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sourceuuid, tvb, PTP_SOURCEUUID_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sourceportid, tvb, PTP_SOURCEPORTID_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sequenceid, tvb, PTP_SEQUENCEID_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_control, tvb, PTP_CONTROL_OFFSET, 1, FALSE);
+
+ /*Subtree for the flag-field*/
+ if(tree){
+ flags_ti = proto_tree_add_item(ptp_tree,
+ hf_ptp_flags, tvb, PTP_FLAGS_OFFSET, 2, FALSE);
+
+ ptp_flags_tree = proto_item_add_subtree(flags_ti, ett_ptp_flags);
+
+ proto_tree_add_item(ptp_flags_tree,
+ hf_ptp_flags_li61, tvb, PTP_FLAGS_LI61_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_flags_tree,
+ hf_ptp_flags_li59, tvb, PTP_FLAGS_LI59_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_flags_tree,
+ hf_ptp_flags_boundary_clock, tvb, PTP_FLAGS_BOUNDARY_CLOCK_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_flags_tree,
+ hf_ptp_flags_assist, tvb, PTP_FLAGS_ASSIST_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_flags_tree,
+ hf_ptp_flags_ext_sync, tvb, PTP_FLAGS_EXT_SYNC_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_flags_tree,
+ hf_ptp_flags_parent, tvb, PTP_FLAGS_PARENT_STATS_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_flags_tree,
+ hf_ptp_flags_sync_burst, tvb, PTP_FLAGS_SYNC_BURST_OFFSET, 2, FALSE);
+ }
+
+ /* The rest of the ptp-dissector depends on the control-field */
+
+ switch(ptp_control){
+ case PTP_SYNC_MESSAGE:
+ case PTP_DELAY_REQ_MESSAGE:{
+
+ /*Subtree for the timestamp-field*/
+ ts.secs = tvb_get_ntohl(tvb, PTP_SDR_ORIGINTIMESTAMP_SECONDS_OFFSET);
+ ts.nsecs = tvb_get_ntohl(tvb, PTP_SDR_ORIGINTIMESTAMP_NANOSECONDS_OFFSET);
+ if(tree){
+ time_ti = proto_tree_add_time(ptp_tree,
+ hf_ptp_origintimestamp, tvb, PTP_SDR_ORIGINTIMESTAMP_OFFSET, 8, &ts);
+
+ ptp_time_tree = proto_item_add_subtree(time_ti, ett_ptp_time);
+
+ proto_tree_add_item(ptp_time_tree,
+ hf_ptp_sdr_origintimestamp_seconds, tvb,
+ PTP_SDR_ORIGINTIMESTAMP_SECONDS_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_time_tree, hf_ptp_sdr_origintimestamp_nanoseconds, tvb,
+ PTP_SDR_ORIGINTIMESTAMP_NANOSECONDS_OFFSET, 4, FALSE);
+ }
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_epochnumber, tvb, PTP_SDR_EPOCHNUMBER_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_currentutcoffset, tvb, PTP_SDR_CURRENTUTCOFFSET_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_sdr_grandmastercommunicationtechnology, tvb,
+ PTP_SDR_GRANDMASTERCOMMUNICATIONTECHNOLOGY_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_grandmasterclockuuid, tvb, PTP_SDR_GRANDMASTERCLOCKUUID_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_grandmasterportid, tvb, PTP_SDR_GRANDMASTERPORTID_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_grandmastersequenceid, tvb, PTP_SDR_GRANDMASTERSEQUENCEID_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_grandmasterclockstratum, tvb,
+ PTP_SDR_GRANDMASTERCLOCKSTRATUM_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_sdr_grandmasterclockidentifier, tvb,
+ PTP_SDR_GRANDMASTERCLOCKIDENTIFIER_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_grandmasterclockvariance, tvb,
+ PTP_SDR_GRANDMASTERCLOCKVARIANCE_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_grandmasterpreferred, tvb, PTP_SDR_GRANDMASTERPREFERRED_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_sdr_grandmasterisboundaryclock, tvb,
+ PTP_SDR_GRANDMASTERISBOUNDARYCLOCK_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_syncinterval, tvb, PTP_SDR_SYNCINTERVAL_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_localclockvariance, tvb, PTP_SDR_LOCALCLOCKVARIANCE_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_localstepsremoved, tvb, PTP_SDR_LOCALSTEPSREMOVED_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_localclockstratum, tvb, PTP_SDR_LOCALCLOCKSTRATUM_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_localclockidentifier, tvb, PTP_SDR_LOCALCLOCKIDENTIFIER_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_sdr_parentcommunicationtechnology, tvb,
+ PTP_SDR_PARENTCOMMUNICATIONTECHNOLOGY_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_parentuuid, tvb, PTP_SDR_PARENTUUID_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_parentportfield, tvb, PTP_SDR_PARENTPORTFIELD_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_estimatedmastervariance, tvb,
+ PTP_SDR_ESTIMATEDMASTERVARIANCE_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_estimatedmasterdrift, tvb, PTP_SDR_ESTIMATEDMASTERDRIFT_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_sdr_utcreasonable, tvb, PTP_SDR_UTCREASONABLE_OFFSET, 1, FALSE);
+ break;
+ }
+ case PTP_FOLLOWUP_MESSAGE:{
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_fu_associatedsequenceid, tvb, PTP_FU_ASSOCIATEDSEQUENCEID_OFFSET, 2, FALSE);
+
+ /*Subtree for the timestamp-field*/
+ ts.secs = tvb_get_ntohl(tvb, PTP_FU_PRECISEORIGINTIMESTAMP_SECONDS_OFFSET);
+ ts.nsecs = tvb_get_ntohl(tvb, PTP_FU_PRECISEORIGINTIMESTAMP_NANOSECONDS_OFFSET);
+ if(tree){
+ time_ti = proto_tree_add_time(ptp_tree,
+ hf_ptp_fu_preciseorigintimestamp, tvb,
+ PTP_FU_PRECISEORIGINTIMESTAMP_OFFSET, 8, &ts);
+
+ ptp_time_tree = proto_item_add_subtree(time_ti, ett_ptp_time);
+
+ proto_tree_add_item(ptp_time_tree, hf_ptp_fu_preciseorigintimestamp_seconds, tvb,
+ PTP_FU_PRECISEORIGINTIMESTAMP_SECONDS_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_time_tree, hf_ptp_fu_preciseorigintimestamp_nanoseconds, tvb,
+ PTP_FU_PRECISEORIGINTIMESTAMP_NANOSECONDS_OFFSET, 4, FALSE);
+ }
+ break;
+ }
+ case PTP_DELAY_RESP_MESSAGE:{
+ /*Subtree for the timestamp-field*/
+ ts.secs = tvb_get_ntohl(tvb, PTP_DR_DELAYRECEIPTTIMESTAMP_SECONDS_OFFSET);
+ ts.nsecs = tvb_get_ntohl(tvb, PTP_DR_DELAYRECEIPTTIMESTAMP_NANOSECONDS_OFFSET);
+ if(tree){
+ time_ti = proto_tree_add_time(ptp_tree,
+ hf_ptp_dr_delayreceipttimestamp, tvb,
+ PTP_DR_DELAYRECEIPTTIMESTAMP_OFFSET, 8, &ts);
+
+ ptp_time_tree = proto_item_add_subtree(time_ti, ett_ptp_time);
+
+ proto_tree_add_item(ptp_time_tree, hf_ptp_dr_delayreceipttimestamp_seconds, tvb,
+ PTP_DR_DELAYRECEIPTTIMESTAMP_SECONDS_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_time_tree, hf_ptp_dr_delayreceipttimestamp_nanoseconds, tvb,
+ PTP_DR_DELAYRECEIPTTIMESTAMP_NANOSECONDS_OFFSET, 4, FALSE);
+ }
+
+ proto_tree_add_item(ptp_tree, hf_ptp_dr_requestingsourcecommunicationtechnology, tvb,
+ PTP_DR_REQUESTINGSOURCECOMMUNICATIONTECHNOLOGY_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_dr_requestingsourceuuid, tvb, PTP_DR_REQUESTINGSOURCEUUID_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_dr_requestingsourceportid, tvb, PTP_DR_REQUESTINGSOURCEPORTID_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_dr_requestingsourcesequenceid, tvb,
+ PTP_DR_REQUESTINGSOURCESEQUENCEID_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MANAGEMENT_MESSAGE:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_targetcommunicationtechnology, tvb,
+ PTP_MM_TARGETCOMMUNICATIONTECHNOLOGY_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_mm_targetuuid, tvb, PTP_MM_TARGETUUID_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_mm_targetportid, tvb, PTP_MM_TARGETPORTID_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_mm_boundaryhops, tvb, PTP_MM_BOUNDARYHOPS_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_mm_managementmessagekey, tvb, PTP_MM_MANAGEMENTMESSAGEKEY_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_mm_parameterlength, tvb, PTP_MM_PARAMETERLENGTH_OFFSET, 2, FALSE);
+
+ switch(ptp_mm_messagekey){
+ case PTP_MM_CLOCK_IDENTITY:{
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_mm_clock_identity_clockcommunicationtechnology, tvb,
+ PTP_MM_CLOCK_IDENTITY_CLOCKCOMMUNICATIONTECHNOLOGY_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_clock_identity_clockuuidfield, tvb,
+ PTP_MM_CLOCK_IDENTITY_CLOCKUUIDFIELD_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_clock_identity_clockportfield, tvb,
+ PTP_MM_CLOCK_IDENTITY_CLOCKPORTFIELD_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_clock_identity_manufactureridentity, tvb,
+ PTP_MM_CLOCK_IDENTITY_MANUFACTURERIDENTITY_OFFSET, 48, FALSE);
+ break;
+ }
+ case PTP_MM_INITIALIZE_CLOCK:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_initialize_clock_initialisationkey, tvb,
+ PTP_MM_INITIALIZE_CLOCK_INITIALISATIONKEY_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MM_SET_SUBDOMAIN:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_set_subdomain_subdomainname, tvb,
+ PTP_MM_SET_SUBDOMAIN_SUBDOMAINNAME_OFFSET, 16, FALSE);
+ break;
+ }
+ case PTP_MM_DEFAULT_DATA_SET:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_clockcommunicationtechnology,
+ tvb, PTP_MM_DEFAULT_DATA_SET_CLOCKCOMMUNICATIONTECHNOLOGY_OFFSET,
+ 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_clockuuidfield, tvb,
+ PTP_MM_DEFAULT_DATA_SET_CLOCKUUIDFIELD_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_clockportfield, tvb,
+ PTP_MM_DEFAULT_DATA_SET_CLOCKPORTFIELD_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_clockstratum, tvb,
+ PTP_MM_DEFAULT_DATA_SET_CLOCKSTRATUM_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_clockidentifier, tvb,
+ PTP_MM_DEFAULT_DATA_SET_CLOCKIDENTIFIER_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_clockvariance, tvb,
+ PTP_MM_DEFAULT_DATA_SET_CLOCKVARIANCE_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_clockfollowupcapable, tvb,
+ PTP_MM_DEFAULT_DATA_SET_CLOCKFOLLOWUPCAPABLE_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_preferred, tvb,
+ PTP_MM_DEFAULT_DATA_SET_PREFERRED_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_initializable, tvb,
+ PTP_MM_DEFAULT_DATA_SET_INITIALIZABLE_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_externaltiming, tvb,
+ PTP_MM_DEFAULT_DATA_SET_EXTERNALTIMING_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_isboundaryclock, tvb,
+ PTP_MM_DEFAULT_DATA_SET_ISBOUNDARYCLOCK_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_syncinterval, tvb,
+ PTP_MM_DEFAULT_DATA_SET_SYNCINTERVAL_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_subdomainname, tvb,
+ PTP_MM_DEFAULT_DATA_SET_SUBDOMAINNAME_OFFSET, 16, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_numberports, tvb,
+ PTP_MM_DEFAULT_DATA_SET_NUMBERPORTS_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_default_data_set_numberforeignrecords, tvb,
+ PTP_MM_DEFAULT_DATA_SET_NUMBERFOREIGNRECORDS_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MM_UPDATE_DEFAULT_DATA_SET:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_update_default_data_set_clockstratum, tvb,
+ PTP_MM_UPDATE_DEFAULT_DATA_SET_CLOCKSTRATUM_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_update_default_data_set_clockidentifier, tvb,
+ PTP_MM_UPDATE_DEFAULT_DATA_SET_CLOCKIDENTIFIER_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_update_default_data_set_clockvariance, tvb,
+ PTP_MM_UPDATE_DEFAULT_DATA_SET_CLOCKVARIANCE_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_update_default_data_set_preferred, tvb,
+ PTP_MM_UPDATE_DEFAULT_DATA_SET_PREFERRED_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_update_default_data_set_syncinterval, tvb,
+ PTP_MM_UPDATE_DEFAULT_DATA_SET_SYNCINTERVAL_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_update_default_data_set_subdomainname, tvb,
+ PTP_MM_UPDATE_DEFAULT_DATA_SET_SUBDOMAINNAME_OFFSET, 16, FALSE);
+ break;
+ }
+ case PTP_MM_CURRENT_DATA_SET:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_current_data_set_stepsremoved, tvb,
+ PTP_MM_CURRENT_DATA_SET_STEPSREMOVED_OFFSET, 2, FALSE);
+
+ /* Subtree for offset from master*/
+ ts.secs = tvb_get_ntohl(tvb, PTP_MM_CURRENT_DATA_SET_OFFSETFROMMASTERSECONDS_OFFSET);
+
+ ts.nsecs = tvb_get_ntohl(tvb,
+ PTP_MM_CURRENT_DATA_SET_OFFSETFROMMASTERNANOSECONDS_OFFSET);
+
+ if(tree){
+ time_ti = proto_tree_add_time(ptp_tree,
+ hf_ptp_mm_current_data_set_offsetfrommaster, tvb,
+ PTP_MM_CURRENT_DATA_SET_OFFSETFROMMASTER_OFFSET, 8, &ts);
+
+ ptp_time_tree = proto_item_add_subtree(time_ti, ett_ptp_time);
+
+ proto_tree_add_item(ptp_time_tree,
+ hf_ptp_mm_current_data_set_offsetfrommasterseconds, tvb,
+ PTP_MM_CURRENT_DATA_SET_OFFSETFROMMASTERSECONDS_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_time_tree,
+ hf_ptp_mm_current_data_set_offsetfrommasternanoseconds, tvb,
+ PTP_MM_CURRENT_DATA_SET_OFFSETFROMMASTERNANOSECONDS_OFFSET, 4, FALSE);
+ }
+
+ /* Subtree for offset from master*/
+ ts.secs = tvb_get_ntohl(tvb, PTP_MM_CURRENT_DATA_SET_ONEWAYDELAYSECONDS_OFFSET);
+
+ ts.nsecs = tvb_get_ntohl(tvb, PTP_MM_CURRENT_DATA_SET_ONEWAYDELAYNANOSECONDS_OFFSET);
+
+ if(tree){
+ time2_ti = proto_tree_add_time(ptp_tree,
+ hf_ptp_mm_current_data_set_onewaydelay, tvb,
+ PTP_MM_CURRENT_DATA_SET_ONEWAYDELAY_OFFSET, 8, &ts);
+
+ ptp_time2_tree = proto_item_add_subtree(time2_ti, ett_ptp_time2);
+
+ proto_tree_add_item(ptp_time2_tree, hf_ptp_mm_current_data_set_onewaydelayseconds,
+ tvb, PTP_MM_CURRENT_DATA_SET_ONEWAYDELAYSECONDS_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_time2_tree,
+ hf_ptp_mm_current_data_set_onewaydelaynanoseconds,
+ tvb, PTP_MM_CURRENT_DATA_SET_ONEWAYDELAYNANOSECONDS_OFFSET, 4, FALSE);
+ }
+ break;
+ }
+ case PTP_MM_PARENT_DATA_SET:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_parentcommunicationtechnology,
+ tvb, PTP_MM_PARENT_DATA_SET_PARENTCOMMUNICATIONTECHNOLOGY_OFFSET,
+ 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_parentuuid, tvb,
+ PTP_MM_PARENT_DATA_SET_PARENTUUID_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_parentportid, tvb,
+ PTP_MM_PARENT_DATA_SET_PARENTPORTID_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_parentlastsyncsequencenumber,
+ tvb, PTP_MM_PARENT_DATA_SET_PARENTLASTSYNCSEQUENCENUMBER_OFFSET,
+ 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_parentfollowupcapable, tvb,
+ PTP_MM_PARENT_DATA_SET_PARENTFOLLOWUPCAPABLE_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_parentexternaltiming, tvb,
+ PTP_MM_PARENT_DATA_SET_PARENTEXTERNALTIMING_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_parentvariance, tvb,
+ PTP_MM_PARENT_DATA_SET_PARENTVARIANCE_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_parentstats, tvb,
+ PTP_MM_PARENT_DATA_SET_PARENTSTATS_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_observedvariance, tvb,
+ PTP_MM_PARENT_DATA_SET_OBSERVEDVARIANCE_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_observeddrift, tvb,
+ PTP_MM_PARENT_DATA_SET_OBSERVEDDRIFT_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_utcreasonable, tvb,
+ PTP_MM_PARENT_DATA_SET_UTCREASONABLE_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_mm_parent_data_set_grandmastercommunicationtechnology,
+ tvb, PTP_MM_PARENT_DATA_SET_GRANDMASTERCOMMUNICATIONTECHNOLOGY_OFFSET, 1,
+ FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_grandmasteruuidfield, tvb,
+ PTP_MM_PARENT_DATA_SET_GRANDMASTERUUIDFIELD_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_grandmasterportidfield, tvb,
+ PTP_MM_PARENT_DATA_SET_GRANDMASTERPORTIDFIELD_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_grandmasterstratum, tvb,
+ PTP_MM_PARENT_DATA_SET_GRANDMASTERSTRATUM_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_grandmasteridentifier, tvb,
+ PTP_MM_PARENT_DATA_SET_GRANDMASTERIDENTIFIER_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_grandmastervariance, tvb,
+ PTP_MM_PARENT_DATA_SET_GRANDMASTERVARIANCE_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_grandmasterpreferred, tvb,
+ PTP_MM_PARENT_DATA_SET_GRANDMASTERPREFERRED_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_grandmasterisboundaryclock, tvb,
+ PTP_MM_PARENT_DATA_SET_GRANDMASTERISBOUNDARYCLOCK_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_parent_data_set_grandmastersequencenumber, tvb,
+ PTP_MM_PARENT_DATA_SET_GRANDMASTERSEQUENCENUMBER_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MM_PORT_DATA_SET:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_returnedportnumber, tvb,
+ PTP_MM_PORT_DATA_SET_RETURNEDPORTNUMBER_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_portstate, tvb,
+ PTP_MM_PORT_DATA_SET_PORTSTATE_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_lastsynceventsequencenumber, tvb,
+ PTP_MM_PORT_DATA_SET_LASTSYNCEVENTSEQUENCENUMBER_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_lastgeneraleventsequencenumber,
+ tvb, PTP_MM_PORT_DATA_SET_LASTGENERALEVENTSEQUENCENUMBER_OFFSET,
+ 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_portcommunicationtechnology, tvb,
+ PTP_MM_PORT_DATA_SET_PORTCOMMUNICATIONTECHNOLOGY_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_portuuidfield, tvb,
+ PTP_MM_PORT_DATA_SET_PORTUUIDFIELD_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_portidfield, tvb,
+ PTP_MM_PORT_DATA_SET_PORTIDFIELD_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_burstenabled, tvb,
+ PTP_MM_PORT_DATA_SET_BURSTENABLED_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_subdomainaddressoctets, tvb,
+ PTP_MM_PORT_DATA_SET_SUBDOMAINADDRESSOCTETS_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_eventportaddressoctets, tvb,
+ PTP_MM_PORT_DATA_SET_EVENTPORTADDRESSOCTETS_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_generalportaddressoctets, tvb,
+ PTP_MM_PORT_DATA_SET_GENERALPORTADDRESSOCTETS_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_subdomainaddress, tvb,
+ PTP_MM_PORT_DATA_SET_SUBDOMAINADDRESS_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_eventportaddress, tvb,
+ PTP_MM_PORT_DATA_SET_EVENTPORTADDRESS_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_port_data_set_generalportaddress, tvb,
+ PTP_MM_PORT_DATA_SET_GENERALPORTADDRESS_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MM_GLOBAL_TIME_DATA_SET:{
+ /* Subtree for local time*/
+ ts.secs = tvb_get_ntohl(tvb, PTP_MM_GLOBAL_TIME_DATA_SET_LOCALTIMESECONDS_OFFSET);
+
+ ts.nsecs = tvb_get_ntohl(tvb,
+ PTP_MM_GLOBAL_TIME_DATA_SET_LOCALTIMENANOSECONDS_OFFSET);
+
+ if(tree){
+ time_ti = proto_tree_add_time(ptp_tree,
+ hf_ptp_mm_global_time_data_set_localtime, tvb,
+ PTP_MM_GLOBAL_TIME_DATA_SET_LOCALTIME_OFFSET, 8, &ts);
+
+ ptp_time_tree = proto_item_add_subtree(time_ti, ett_ptp_time);
+
+ proto_tree_add_item(ptp_time_tree,
+ hf_ptp_mm_global_time_data_set_localtimeseconds, tvb,
+ PTP_MM_GLOBAL_TIME_DATA_SET_LOCALTIMESECONDS_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_time_tree,
+ hf_ptp_mm_global_time_data_set_localtimenanoseconds,
+ tvb, PTP_MM_GLOBAL_TIME_DATA_SET_LOCALTIMENANOSECONDS_OFFSET, 4, FALSE);
+ }
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_global_time_data_set_currentutcoffset, tvb,
+ PTP_MM_GLOBAL_TIME_DATA_SET_CURRENTUTCOFFSET_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_global_time_data_set_leap59, tvb,
+ PTP_MM_GLOBAL_TIME_DATA_SET_LEAP59_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_global_time_data_set_leap61, tvb,
+ PTP_MM_GLOBAL_TIME_DATA_SET_LEAP61_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_global_time_data_set_epochnumber, tvb,
+ PTP_MM_GLOBAL_TIME_DATA_SET_EPOCHNUMBER_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_update_global_time_properties_currentutcoffset,
+ tvb, PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES_CURRENTUTCOFFSET_OFFSET,
+ 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_update_global_time_properties_leap59, tvb,
+ PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES_LEAP59_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_update_global_time_properties_leap61, tvb,
+ PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES_LEAP61_OFFSET, 1, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_get_foreign_data_set_recordkey, tvb,
+ PTP_MM_UPDATE_GLOBAL_TIME_PROPERTIES_EPOCHNUMBER_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MM_GET_FOREIGN_DATA_SET:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_get_foreign_data_set_recordkey, tvb,
+ PTP_MM_GET_FOREIGN_DATA_SET_RECORDKEY_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MM_FOREIGN_DATA_SET:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_foreign_data_set_returnedportnumber, tvb,
+ PTP_MM_FOREIGN_DATA_SET_RETURNEDPORTNUMBER_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_foreign_data_set_returnedrecordnumber, tvb,
+ PTP_MM_FOREIGN_DATA_SET_RETURNEDRECORDNUMBER_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree,
+ hf_ptp_mm_foreign_data_set_foreignmastercommunicationtechnology,
+ tvb, PTP_MM_FOREIGN_DATA_SET_FOREIGNMASTERCOMMUNICATIONTECHNOLOGY_OFFSET, 1,
+ FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_foreign_data_set_foreignmasteruuidfield, tvb,
+ PTP_MM_FOREIGN_DATA_SET_FOREIGNMASTERUUIDFIELD_OFFSET, 6, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_foreign_data_set_foreignmasterportidfield, tvb,
+ PTP_MM_FOREIGN_DATA_SET_FOREIGNMASTERPORTIDFIELD_OFFSET, 2, FALSE);
+
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_foreign_data_set_foreignmastersyncs, tvb,
+ PTP_MM_FOREIGN_DATA_SET_FOREIGNMASTERSYNCS_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MM_SET_SYNC_INTERVAL:{
+ proto_tree_add_item(ptp_tree, hf_ptp_mm_set_sync_interval_syncinterval, tvb,
+ PTP_MM_SET_SYNC_INTERVAL_SYNCINTERVAL_OFFSET, 2, FALSE);
+ break;
+ }
+ case PTP_MM_SET_TIME:{
+ /* Subtree for local time*/
+ ts.secs = tvb_get_ntohl(tvb, PTP_MM_SET_TIME_LOCALTIMESECONDS_OFFSET);
+
+ ts.nsecs = tvb_get_ntohl(tvb, PTP_MM_SET_TIME_LOCALTIMENANOSECONDS_OFFSET);
+
+ if(tree){
+ time_ti = proto_tree_add_time(ptp_tree, hf_ptp_mm_set_time_localtime, tvb,
+ PTP_MM_SET_TIME_LOCALTIME_OFFSET, 8, &ts);
+
+ ptp_time_tree = proto_item_add_subtree(time_ti, ett_ptp_time);
+
+ proto_tree_add_item(ptp_time_tree, hf_ptp_mm_set_time_localtimeseconds, tvb,
+ PTP_MM_SET_TIME_LOCALTIMESECONDS_OFFSET, 4, FALSE);
+
+ proto_tree_add_item(ptp_time_tree, hf_ptp_mm_set_time_localtimenanoseconds,
+ tvb, PTP_MM_SET_TIME_LOCALTIMENANOSECONDS_OFFSET, 4, FALSE);
+ }
+ break;
+ }
+ default :{
+ /*- don't dissect any further. */
+ break;
+ }
+ }
+ break;
+ }
+ default :{
+ /* Not a valid MessageType - can't dissect. */
+ break;
+ }
+ }
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+
+void
+proto_register_ptp(void)
+{
+ static hf_register_info hf[] = {
+ /*Common Fields for all frames*/
+ { &hf_ptp_versionptp,
+ { "versionPTP", "ptp.versionptp",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_versionnetwork,
+ { "versionNetwork", "ptp.versionnetwork",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_subdomain,
+ { "subdomain", "ptp.subdomain",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_messagetype,
+ { "messageType", "ptp.messagetype",
+ FT_UINT8, BASE_DEC, VALS(ptp_messagetype_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sourcecommunicationtechnology,
+ { "sourceCommunicationTechnology", "ptp.sourcecommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sourceuuid,
+ { "sourceUuid", "ptp.sourceuuid",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sourceportid,
+ { "sourcePortId", "ptp.sourceportid",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sequenceid,
+ { "sequenceId", "ptp.sequenceid",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_control,
+ { "control", "ptp.control",
+ FT_UINT8, BASE_DEC, VALS(ptp_control_vals), 0x00,
+ "", HFILL }
+ },
+ /*THE FLAGS-FIELD*/
+ { &hf_ptp_flags,
+ { "flags", "ptp.flags",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_flags_li61,
+ { "PTP_LI61", "ptp.flags.li61",
+ FT_UINT16, BASE_DEC, VALS(ptp_bool_vals), PTP_FLAGS_LI61_BITMASK,
+ "", HFILL }
+ },
+ { &hf_ptp_flags_li59,
+ { "PTP_LI59", "ptp.flags.li59",
+ FT_UINT16, BASE_DEC, VALS(ptp_bool_vals), PTP_FLAGS_LI59_BITMASK,
+ "", HFILL }
+ },
+ { &hf_ptp_flags_boundary_clock,
+ { "PTP_BOUNDARY_CLOCK", "ptp.flags.boundary_clock",
+ FT_UINT16, BASE_DEC, VALS(ptp_bool_vals), PTP_FLAGS_BOUNDARY_CLOCK_BITMASK,
+ "", HFILL }
+ },
+ { &hf_ptp_flags_assist,
+ { "PTP_ASSIST", "ptp.flags.assist",
+ FT_UINT16, BASE_DEC, VALS(ptp_bool_vals), PTP_FLAGS_ASSIST_BITMASK,
+ "", HFILL }
+ },
+ { &hf_ptp_flags_ext_sync,
+ { "PTP_EXT_SYNC", "ptp.flags.ext_sync",
+ FT_UINT16, BASE_DEC, VALS(ptp_bool_vals), PTP_FLAGS_EXT_SYNC_BITMASK,
+ "", HFILL }
+ },
+ { &hf_ptp_flags_parent,
+ { "PTP_PARENT_STATS", "ptp.flags.parent_stats",
+ FT_UINT16, BASE_DEC, VALS(ptp_bool_vals), PTP_FLAGS_PARENT_STATS_BITMASK,
+ "", HFILL }
+ },
+ { &hf_ptp_flags_sync_burst,
+ { "PTP_SYNC_BURST", "ptp.flags.sync_burst",
+ FT_UINT16, BASE_DEC, VALS(ptp_bool_vals), PTP_FLAGS_SYNC_BURST_BITMASK,
+ "", HFILL }
+ },
+ /*END OF THE FLAG-FIELD*/
+
+ /*offsets for ptp_sync and delay_req (=sdr) messages*/
+ { &hf_ptp_origintimestamp,
+ { "originTimestamp", "ptp.sdr.origintimestamp",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_origintimestamp_seconds,
+ { "originTimestamp (seconds)", "ptp.sdr.origintimestamp_seconds",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_origintimestamp_nanoseconds,
+ { "originTimestamp (nanoseconds)", "ptp.sdr.origintimestamp_nanoseconds",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_epochnumber,
+ { "epochNumber", "ptp.sdr.epochnumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_currentutcoffset,
+ { "currentUTCOffset", "ptp.sdr.currentutcoffset",
+ FT_INT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_grandmastercommunicationtechnology,
+ { "grandmasterCommunicationTechnology", "ptp.sdr.grandmastercommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_grandmasterclockuuid,
+ { "grandMasterClockUuid", "ptp.sdr.grandmasterclockuuid",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_grandmasterportid,
+ { "grandmasterPortId", "ptp.sdr.grandmasterportid",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_grandmastersequenceid,
+ { "grandmasterSequenceId", "ptp.sdr.grandmastersequenceid",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_grandmasterclockstratum,
+ { "grandmasterClockStratum", "ptp.sdr.grandmasterclockstratum",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_grandmasterclockidentifier,
+ { "grandmasterClockIdentifier", "ptp.sdr.grandmasterclockidentifier",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_grandmasterclockvariance,
+ { "grandmasterClockVariance", "ptp.sdr.grandmasterclockvariance",
+ FT_INT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_grandmasterpreferred,
+ { "grandmasterPreferred", "ptp.sdr.grandmasterpreferred",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_grandmasterisboundaryclock,
+ { "grandmasterIsBoundaryClock", "ptp.sdr.grandmasterisboundaryclock",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_syncinterval,
+ { "syncInterval", "ptp.sdr.syncinterval",
+ FT_INT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_localclockvariance,
+ { "localClockVariance", "ptp.sdr.localclockvariance",
+ FT_INT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_localstepsremoved,
+ { "localStepsRemoved", "ptp.sdr.localstepsremoved",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_localclockstratum,
+ { "localClockStratum", "ptp.sdr.localclockstratum",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_localclockidentifier,
+ { "localClockIdentifier", "ptp.sdr.localclockidentifier",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_parentcommunicationtechnology,
+ { "parentCommunicationTechnology", "ptp.sdr.parentcommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_parentuuid,
+ { "parentUuid", "ptp.sdr.parentuuid",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_parentportfield,
+ { "parentPortField", "ptp.sdr.parentportfield",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_estimatedmastervariance,
+ { "estimatedMasterVariance", "ptp.sdr.estimatedmastervariance",
+ FT_INT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_estimatedmasterdrift,
+ { "estimatedMasterDrift", "ptp.sdr.estimatedmasterdrift",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_sdr_utcreasonable,
+ { "utcReasonable", "ptp.sdr.utcreasonable",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*offsets for follow_up (=fu) messages*/
+ { &hf_ptp_fu_associatedsequenceid,
+ { "associatedSequenceId", "ptp.fu.associatedsequenceid",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_fu_preciseorigintimestamp,
+ { "preciseOriginTimestamp", "ptp.fu.hf_ptp_fu_preciseorigintimestamp",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_fu_preciseorigintimestamp_seconds,
+ { "preciseOriginTimestamp (seconds)", "ptp.fu.hf_ptp_fu_preciseorigintimestamp_seconds",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_fu_preciseorigintimestamp_nanoseconds,
+ { "preciseOriginTimestamp (nanoseconds)", "ptp.fu.preciseorigintimestamp_nanoseconds",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*offsets for delay_resp (=dr) messages*/
+ { &hf_ptp_dr_delayreceipttimestamp,
+ { "delayReceiptTimestamp", "ptp.dr.delayreceipttimestamp",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_dr_delayreceipttimestamp_seconds,
+ { "delayReceiptTimestamp (Seconds)", "ptp.dr.delayreceipttimestamp_seconds",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_dr_delayreceipttimestamp_nanoseconds,
+ { "delayReceiptTimestamp (nanoseconds)", "ptp.dr.delayreceipttimestamp_nanoseconds",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_dr_requestingsourcecommunicationtechnology,
+ { "requestingSourceCommunicationTechnology", "ptp.dr.requestingsourcecommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_dr_requestingsourceuuid,
+ { "requestingSourceUuid", "ptp.dr.requestingsourceuuid",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_dr_requestingsourceportid,
+ { "requestingSourcePortId", "ptp.dr.requestingsourceportid",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_dr_requestingsourcesequenceid,
+ { "requestingSourceSequenceId", "ptp.dr.requestingsourcesequenceid",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*offsets for management (=mm) messages*/
+ { &hf_ptp_mm_targetcommunicationtechnology,
+ { "targetCommunicationTechnology", "ptp.mm.targetcommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_targetuuid,
+ { "targetUuid", "ptp.mm.targetuuid",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_targetportid,
+ { "targetPortId", "ptp.mm.targetportid",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_boundaryhops,
+ { "boundaryHops", "ptp.mm.boundaryhops",
+ FT_INT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_managementmessagekey,
+ { "managementMessageKey", "ptp.mm.managementmessagekey",
+ FT_UINT8, BASE_DEC, VALS(ptp_managementMessageKey_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parameterlength,
+ { "parameterLength", "ptp.mm.parameterlength",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*parameterlength > 0*/
+ { &hf_ptp_mm_messageparameters,
+ { "messageParameters", "ptp.mm.messageparameters",
+ FT_BYTES, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_clock_identity (parameterlength = 64)*/
+ { &hf_ptp_mm_clock_identity_clockcommunicationtechnology,
+ { "clockCommunicationTechnology", "ptp.mm.clock.identity.clockcommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_clock_identity_clockuuidfield,
+ { "clockUuidField", "ptp.mm.clock.identity.clockuuidfield",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_clock_identity_clockportfield,
+ { "clockPortField", "ptp.mm.clock.identity.clockportfield",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_clock_identity_manufactureridentity,
+ { "manufacturerIdentity", "ptp.mm.clock.identity.manufactureridentity",
+ FT_BYTES, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+
+ /*ptp_mm_initialize_clock (parameterlength = 4)*/
+ { &hf_ptp_mm_initialize_clock_initialisationkey,
+ { "initialisationKey", "ptp.mm.initialize.clock.initialisationkey",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_set_subdomain (parameterlength = 16)*/
+ { &hf_ptp_mm_set_subdomain_subdomainname,
+ { "subdomainName", "ptp.mm.set.subdomain.subdomainname",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_default_data_set (parameterlength = 76)*/
+ { &hf_ptp_mm_default_data_set_clockcommunicationtechnology,
+ { "clockCommunicationTechnology", "ptp.mm.default.data.set.clockcommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_clockuuidfield,
+ { "clockUuidField", "ptp.mm.default.data.set.clockuuidfield",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_clockportfield,
+ { "clockPortField", "ptp.mm.default.data.set.clockportfield",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_clockstratum,
+ { "clockStratum", "ptp.mm.default.data.set.clockstratum",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_clockidentifier,
+ { "clockIdentifier", "ptp.mm.default.data.set.clockidentifier",
+ FT_BYTES, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_clockvariance,
+ { "clockVariance", "ptp.mm.default.data.set.clockvariance",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_clockfollowupcapable,
+ { "clockFollowupCapable", "ptp.mm.default.data.set.clockfollowupcapable",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_preferred,
+ { "preferred", "ptp.mm.default.data.set.preferred",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_initializable,
+ { "initializable", "ptp.mm.default.data.set.initializable",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_externaltiming,
+ { "externalTiming", "ptp.mm.default.data.set.externaltiming",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_isboundaryclock,
+ { "isBoundaryClock", "ptp.mm.default.data.set.isboundaryclock",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_syncinterval,
+ { "syncInterval", "ptp.mm.default.data.set.syncinterval",
+ FT_INT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_subdomainname,
+ { "subDomainName", "ptp.mm.default.data.set.subdomainname",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_numberports,
+ { "numberPorts", "ptp.mm.default.data.set.numberports",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_default_data_set_numberforeignrecords,
+ { "numberForeignRecords", "ptp.mm.default.data.set.numberforeignrecords",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_update_default_data_set (parameterlength = 36)*/
+ { &hf_ptp_mm_update_default_data_set_clockstratum,
+ { "clockStratum", "ptp.mm.update.default.data.set.clockstratum",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_update_default_data_set_clockidentifier,
+ { "clockIdentifier", "ptp.mm.update.default.data.set.clockidentifier",
+ FT_BYTES, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_update_default_data_set_clockvariance,
+ { "clockVariance", "ptp.mm.update.default.data.set.clockvariance",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_update_default_data_set_preferred,
+ { "preferred", "ptp.mm.update.default.data.set.preferred",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_update_default_data_set_syncinterval,
+ { "syncInterval", "ptp.mm.update.default.data.set.syncinterval",
+ FT_INT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_update_default_data_set_subdomainname,
+ { "subdomainName", "ptp.mm.update.default.data.set.subdomainname",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_current_data_set (parameterlength = 20)*/
+ { &hf_ptp_mm_current_data_set_stepsremoved,
+ { "stepsRemoved", "ptp.mm.current.data.set.stepsremoved",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_current_data_set_offsetfrommaster,
+ { "offsetFromMaster", "ptp.mm.current.data.set.offsetfrommaster",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_current_data_set_offsetfrommasterseconds,
+ { "offsetFromMasterSeconds", "ptp.mm.current.data.set.offsetfrommasterseconds",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_current_data_set_offsetfrommasternanoseconds,
+ { "offsetFromMasterNanoseconds", "ptp.mm.current.data.set.offsetfrommasternanoseconds",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_current_data_set_onewaydelay,
+ { "oneWayDelay", "ptp.mm.current.data.set.onewaydelay",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_current_data_set_onewaydelayseconds,
+ { "oneWayDelaySeconds", "ptp.mm.current.data.set.onewaydelayseconds",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_current_data_set_onewaydelaynanoseconds,
+ { "oneWayDelayNanoseconds", "ptp.mm.current.data.set.onewaydelaynanoseconds",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_parent_data_set (parameterlength = 90)*/
+ { &hf_ptp_mm_parent_data_set_parentcommunicationtechnology,
+ { "parentCommunicationTechnology", "ptp.mm.parent.data.set.parentcommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_parentuuid,
+ { "parentUuid", "ptp.mm.parent.data.set.parentuuid",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_parentportid,
+ { "parentPortId", "ptp.mm.parent.data.set.parentportid",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_parentlastsyncsequencenumber,
+ { "parentLastSyncSequenceNumber", "ptp.mm.parent.data.set.parentlastsyncsequencenumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_parentfollowupcapable,
+ { "parentFollowupCapable", "ptp.mm.parent.data.set.parentfollowupcapable",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_parentexternaltiming,
+ { "parentExternalTiming", "ptp.mm.parent.data.set.parentexternaltiming",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_parentvariance,
+ { "parentVariance", "ptp.mm.parent.data.set.parentvariance",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_parentstats,
+ { "parentStats", "ptp.mm.parent.data.set.parentstats",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_observedvariance,
+ { "observedVariance", "ptp.mm.parent.data.set.observedvariance",
+ FT_INT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_observeddrift,
+ { "observedDrift", "ptp.mm.parent.data.set.observeddrift",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_utcreasonable,
+ { "utcReasonable", "ptp.mm.parent.data.set.utcreasonable",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_grandmastercommunicationtechnology,
+ { "grandmasterCommunicationTechnology", "ptp.mm.parent.data.set.grandmastercommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_grandmasteruuidfield,
+ { "grandmasterUuidField", "ptp.mm.parent.data.set.grandmasteruuidfield",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_grandmasterportidfield,
+ { "grandmasterPortIdField", "ptp.mm.parent.data.set.grandmasterportidfield",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_grandmasterstratum,
+ { "grandmasterStratum", "ptp.mm.parent.data.set.grandmasterstratum",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_grandmasteridentifier,
+ { "grandmasterIdentifier", "ptp.mm.parent.data.set.grandmasteridentifier",
+ FT_BYTES, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_grandmastervariance,
+ { "grandmasterVariance", "ptp.mm.parent.data.set.grandmastervariance",
+ FT_INT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_grandmasterpreferred,
+ { "grandmasterPreferred", "ptp.mm.parent.data.set.grandmasterpreferred",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_grandmasterisboundaryclock,
+ { "grandmasterIsBoundaryClock", "ptp.mm.parent.data.set.grandmasterisboundaryclock",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_parent_data_set_grandmastersequencenumber,
+ { "grandmasterSequenceNumber", "ptp.mm.parent.data.set.grandmastersequencenumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_port_data_set (parameterlength = 52)*/
+ { &hf_ptp_mm_port_data_set_returnedportnumber,
+ { "returnedPortNumber", "ptp.mm.port.data.set.returnedportnumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_portstate,
+ { "portState", "ptp.mm.port.data.set.portstate",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_lastsynceventsequencenumber,
+ { "lastSyncEventSequenceNumber", "ptp.mm.port.data.set.lastsynceventsequencenumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_lastgeneraleventsequencenumber,
+ { "lastGeneralEventSequenceNumber", "ptp.mm.port.data.set.lastgeneraleventsequencenumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_portcommunicationtechnology,
+ { "portCommunicationTechnology", "ptp.mm.port.data.set.portcommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_portuuidfield,
+ { "portUuidField", "ptp.mm.port.data.set.portuuidfield",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_portidfield,
+ { "portIdField", "ptp.mm.port.data.set.portidfield",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_burstenabled,
+ { "burstEnabled", "ptp.mm.port.data.set.burstenabled",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_subdomainaddressoctets,
+ { "subdomainAddressOctets", "ptp.mm.port.data.set.subdomainaddressoctets",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_eventportaddressoctets,
+ { "eventPortAddressOctets", "ptp.mm.port.data.set.eventportaddressoctets",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_generalportaddressoctets,
+ { "generalPortAddressOctets", "ptp.mm.port.data.set.generalportaddressoctets",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_subdomainaddress,
+ { "subdomainAddress", "ptp.mm.port.data.set.subdomainaddress",
+ FT_BYTES, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_eventportaddress,
+ { "eventPortAddress", "ptp.mm.port.data.set.eventportaddress",
+ FT_BYTES, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_port_data_set_generalportaddress,
+ { "generalPortAddress", "ptp.mm.port.data.set.generalportaddress",
+ FT_BYTES, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_global_time_data_set (parameterlength = 24)*/
+ { &hf_ptp_mm_global_time_data_set_localtime,
+ { "localTime", "ptp.mm.global.time.data.set.localtime",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_global_time_data_set_localtimeseconds,
+ { "localTimeSeconds", "ptp.mm.global.time.data.set.localtimeseconds",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_global_time_data_set_localtimenanoseconds,
+ { "localTimeNanoseconds", "ptp.mm.global.time.data.set.localtimenanoseconds",
+ FT_INT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_global_time_data_set_currentutcoffset,
+ { "currentUtcOffset", "ptp.mm.global.time.data.set.currentutcoffset",
+ FT_INT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_global_time_data_set_leap59,
+ { "leap59", "ptp.mm.global.time.data.set.leap59",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_global_time_data_set_leap61,
+ { "leap61", "ptp.mm.global.time.data.set.leap61",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_global_time_data_set_epochnumber,
+ { "epochNumber", "ptp.mm.global.time.data.set.epochnumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_update_global_time_properties (parameterlength = 16)*/
+ { &hf_ptp_mm_update_global_time_properties_currentutcoffset,
+ { "currentUtcOffset", "ptp.mm.update.global.time.properties.currentutcoffset",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_update_global_time_properties_leap59,
+ { "leap59", "ptp.mm.update.global.time.properties.leap59",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_update_global_time_properties_leap61,
+ { "leap61", "ptp.mm.update.global.time.properties.leap61",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_update_global_time_properties_epochnumber,
+ { "epochNumber", "ptp.mm.update.global.time.properties.epochnumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_get_foreign_data_set (parameterlength = 4)*/
+ { &hf_ptp_mm_get_foreign_data_set_recordkey,
+ { "recordKey", "ptp.mm.get.foreign.data.set.recordkey",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_foreign_data_set (parameterlength = 28)*/
+ { &hf_ptp_mm_foreign_data_set_returnedportnumber,
+ { "returnedPortNumber", "ptp.mm.foreign.data.set.returnedportnumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_foreign_data_set_returnedrecordnumber,
+ { "returnedRecordNumber", "ptp.mm.foreign.data.set.returnedrecordnumber",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_foreign_data_set_foreignmastercommunicationtechnology,
+ { "foreignMasterCommunicationTechnology",
+ "ptp.mm.foreign.data.set.foreignmastercommunicationtechnology",
+ FT_UINT8, BASE_DEC, VALS(ptp_communicationid_vals), 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_foreign_data_set_foreignmasteruuidfield,
+ { "foreignMasterUuidField", "ptp.mm.foreign.data.set.foreignmasteruuidfield",
+ FT_ETHER, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_foreign_data_set_foreignmasterportidfield,
+ { "foreignMasterPortIdField", "ptp.mm.foreign.data.set.foreignmasterportidfield",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_foreign_data_set_foreignmastersyncs,
+ { "foreignMasterSyncs", "ptp.mm.foreign.data.set.foreignmastersyncs",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_set_sync_interval (parameterlength = 4)*/
+ { &hf_ptp_mm_set_sync_interval_syncinterval,
+ { "syncInterval", "ptp.mm.set.sync.interval.syncinterval",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ /*ptp_mm_set_time (parameterlength = 8)*/
+ { &hf_ptp_mm_set_time_localtime,
+ { "localtime", "ptp.mm.set.time.localtime",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_set_time_localtimeseconds,
+ { "localtimeSeconds", "ptp.mm.set.time.localtimeseconds",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "", HFILL }
+ },
+ { &hf_ptp_mm_set_time_localtimenanoseconds,
+ { "localTimeNanoseconds", "ptp.mm.set.time.localtimenanoseconds",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_ptp,
+ &ett_ptp_flags,
+ &ett_ptp_time,
+ &ett_ptp_time2,
+ };
+
+/* Register the protocol name and description */
+ proto_ptp = proto_register_protocol("Precision Time Protocol (IEEE1588)",
+ "PTP", "ptp");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ptp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ptp(void)
+{
+ dissector_handle_t event_port_ptp_handle;
+ dissector_handle_t general_port_ptp_handle;
+
+ event_port_ptp_handle = create_dissector_handle(dissect_ptp,
+ proto_ptp);
+ general_port_ptp_handle = create_dissector_handle(dissect_ptp,
+ proto_ptp);
+
+ dissector_add("udp.port", EVENT_PORT_PTP, event_port_ptp_handle);
+ dissector_add("udp.port", GENERAL_PORT_PTP, general_port_ptp_handle);
+}
+
diff --git a/epan/dissectors/packet-q2931.c b/epan/dissectors/packet-q2931.c
new file mode 100644
index 0000000000..db34e3286e
--- /dev/null
+++ b/epan/dissectors/packet-q2931.c
@@ -0,0 +1,2189 @@
+/* packet-q2931.c
+ * Routines for Q.2931 frame disassembly
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "oui.h"
+#include "nlpid.h"
+#include "etypes.h"
+#include "packet-q931.h"
+#include "packet-arp.h"
+
+/*
+ * See
+ *
+ * http://www.protocols.com/pbook/atmsig.htm
+ *
+ * for some information on Q.2931, although, alas, not the actual message
+ * type and information element values - those I got from the FreeBSD 3.2
+ * ATM code, and from Q.2931 (and Q.931) itself.
+ */
+
+static int proto_q2931 = -1;
+static int hf_q2931_discriminator = -1;
+static int hf_q2931_call_ref_len = -1;
+static int hf_q2931_call_ref_flag = -1;
+static int hf_q2931_call_ref = -1;
+static int hf_q2931_message_type = -1;
+static int hf_q2931_message_type_ext = -1;
+static int hf_q2931_message_flag = -1;
+static int hf_q2931_message_action_indicator = -1;
+static int hf_q2931_message_len = -1;
+
+static gint ett_q2931 = -1;
+static gint ett_q2931_ext = -1;
+static gint ett_q2931_ie = -1;
+static gint ett_q2931_ie_ext = -1;
+static gint ett_q2931_nsap = -1;
+
+static void dissect_q2931_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, guint8 info_element, guint8 info_element_ext);
+
+/*
+ * Q.2931 message types.
+ */
+#define Q2931_ALERTING 0x01
+#define Q2931_CALL_PROCEEDING 0x02
+#define Q2931_CONNECT 0x07
+#define Q2931_CONNECT_ACK 0x0F
+#define Q2931_PROGRESS 0x03
+#define Q2931_SETUP 0x05
+#define Q2931_SETUP_ACK 0x0B
+#define Q2931_RELEASE 0x4D
+#define Q2931_RELEASE_COMPLETE 0x5A
+#define Q2931_RESTART 0x46
+#define Q2931_RESTART_ACK 0x4E
+#define Q2931_INFORMATION 0x7B
+#define Q2931_NOTIFY 0x6E
+#define Q2931_STATUS 0x7D
+#define Q2931_STATUS_ENQUIRY 0x75
+#define Q2931_ADD_PARTY 0x80
+#define Q2931_ADD_PARTY_ACK 0x81
+#define Q2931_ADD_PARTY_REJ 0x82
+#define Q2931_DROP_PARTY 0x83
+#define Q2931_DROP_PARTY_ACK 0x84
+#define Q2931_LEAF_SETUP_FAIL 0x90
+#define Q2931_LEAF_SETUP_REQ 0x91
+
+static const value_string q2931_message_type_vals[] = {
+ { Q2931_ALERTING, "ALERTING" },
+ { Q2931_CALL_PROCEEDING, "CALL PROCEEDING" },
+ { Q2931_CONNECT, "CONNECT" },
+ { Q2931_CONNECT_ACK, "CONNECT ACKNOWLEDGE" },
+ { Q2931_PROGRESS, "PROGRESS" },
+ { Q2931_SETUP, "SETUP" },
+ { Q2931_SETUP_ACK, "SETUP ACKNOWLEDGE" },
+ { Q2931_RELEASE, "RELEASE" },
+ { Q2931_RELEASE_COMPLETE, "RELEASE COMPLETE" },
+ { Q2931_RESTART, "RESTART" },
+ { Q2931_RESTART_ACK, "RESTART ACKNOWLEDGE" },
+ { Q2931_INFORMATION, "INFORMATION" },
+ { Q2931_NOTIFY, "NOTIFY" },
+ { Q2931_STATUS, "STATUS" },
+ { Q2931_STATUS_ENQUIRY, "STATUS ENQUIRY" },
+ { Q2931_ADD_PARTY, "ADD PARTY" },
+ { Q2931_ADD_PARTY_ACK, "ADD PARTY ACKNOWLEDGE" },
+ { Q2931_ADD_PARTY_REJ, "ADD PARTY REJECT" },
+ { Q2931_DROP_PARTY, "DROP PARTY" },
+ { Q2931_DROP_PARTY_ACK, "DROP PARTY ACKNOWLEDGE" },
+ { Q2931_LEAF_SETUP_FAIL, "LEAF SETUP FAILURE" },
+ { Q2931_LEAF_SETUP_REQ, "LEAF SETUP REQUEST" },
+ { 0, NULL }
+};
+
+static const true_false_string tfs_call_ref_flag = {
+ "Message sent to originating side",
+ "Message sent from originating side"
+};
+
+/*
+ * Bits in the message type extension.
+ */
+#define Q2931_MSG_TYPE_EXT_FOLLOW_INST 0x10 /* follow instructions in action indicator */
+#define Q2931_MSG_TYPE_EXT_ACTION_IND 0x03 /* said instructions */
+
+static const true_false_string tos_msg_flag = {
+ "Regular error handling procedures apply",
+ "Follow explicit error handling instructions"
+};
+
+static const value_string msg_action_ind_vals[] = {
+ { 0x00, "Clear call" },
+ { 0x01, "Discard and ignore" },
+ { 0x02, "Discard and report status" },
+ { 0x00, NULL }
+};
+
+/*
+ * Bits in the compatibility instruction indicator octet of an
+ * information element.
+ */
+#define Q2931_IE_COMPAT_CODING_STD 0x60 /* Coding standard */
+#define Q2931_IE_COMPAT_FOLLOW_INST 0x10 /* follow instructions in action indicator */
+#define Q2931_IE_COMPAT_ACTION_IND 0x07
+
+/*
+ * ITU-standardized coding.
+ */
+#define Q2931_ITU_STANDARDIZED_CODING 0x00
+
+static const value_string coding_std_vals[] = {
+ { 0x00, "ITU-T standardized coding" },
+ { 0x20, "ISO/IEC standard" },
+ { 0x40, "National standard" },
+ { 0x60, "Standard defined for the network" },
+ { 0, NULL }
+};
+
+static const value_string ie_action_ind_vals[] = {
+ { 0x00, "Clear call" },
+ { 0x01, "Discard information element and proceed" },
+ { 0x02, "Discard information element, proceed, and report status" },
+ { 0x05, "Discard message, and ignore" },
+ { 0x06, "Discard message, and report status" },
+ { 0x00, NULL }
+};
+
+/*
+ * Information elements.
+ */
+#define Q2931_IE_EXTENSION 0x80 /* Extension flag */
+
+#define Q2931_IE_NBAND_BEARER_CAP 0x04 /* Narrowband bearer capability */
+#define Q2931_IE_CAUSE 0x08
+#define Q2931_IE_CALL_STATE 0x14
+#define Q2931_IE_PROGRESS_INDICATOR 0x1E
+#define Q2931_IE_NOTIFICATION_INDICATOR 0x27
+#define Q2931_IE_E2E_TRANSIT_DELAY 0x42 /* End-to-end Transit Delay */
+#define Q2931_IE_ENDPOINT_REFERENCE 0x54
+#define Q2931_IE_ENDPOINT_STATE 0x55
+#define Q2931_IE_AAL_PARAMETERS 0x58 /* ATM adaptation layer parameters */
+#define Q2931_IE_ATM_USER_CELL_RATE 0x59 /* ATM traffic descriptor */
+#define Q2931_IE_CONNECTION_IDENTIFIER 0x5A
+#define Q2931_IE_OAM_TRAFFIC_DESCRIPTOR 0x5B
+#define Q2931_IE_QOS_PARAMETER 0x5C /* Quality of Service parameter */
+#define Q2931_IE_BBAND_HI_LAYER_INFO 0x5D /* Broadband high-layer information */
+#define Q2931_IE_BBAND_BEARER_CAP 0x5E /* Broadband bearer capability */
+#define Q2931_IE_BBAND_LOW_LAYER_INFO 0x5F /* Broadband low-layer information */
+#define Q2931_IE_BBAND_LOCKING_SHIFT 0x60 /* Broadband locking shift */
+#define Q2931_IE_BBAND_NLOCKING_SHIFT 0x61 /* Broadband non-locking shift */
+#define Q2931_IE_BBAND_SENDING_COMPL 0x62 /* Broadband sending complete */
+#define Q2931_IE_BBAND_RPT_INDICATOR 0x63 /* Broadband repeat indicator */
+#define Q2931_IE_CALLING_PARTY_NUMBER 0x6C /* Calling Party Number */
+#define Q2931_IE_CALLING_PARTY_SUBADDR 0x6D /* Calling Party Subaddress */
+#define Q2931_IE_CALLED_PARTY_NUMBER 0x70 /* Called Party Number */
+#define Q2931_IE_CALLED_PARTY_SUBADDR 0x71 /* Called Party Subaddress */
+#define Q2931_IE_TRANSIT_NETWORK_SEL 0x78 /* Transit Network Selection */
+#define Q2931_IE_RESTART_INDICATOR 0x79
+#define Q2931_IE_NBAND_LOW_LAYER_COMPAT 0x7C /* Narrowband Low-Layer Compatibility */
+#define Q2931_IE_NBAND_HIGH_LAYER_COMPAT 0x7D /* Narrowband High-Layer Compatibility */
+#define Q2931_IE_GENERIC_IDENT_TRANSPORT 0x7F /* Generic identifier transport */
+
+static const value_string q2931_info_element_vals[] = {
+ { Q2931_IE_NBAND_BEARER_CAP, "Narrowband bearer capability" },
+ { Q2931_IE_CAUSE, "Cause" },
+ { Q2931_IE_CALL_STATE, "Call state" },
+ { Q2931_IE_PROGRESS_INDICATOR, "Progress indicator" },
+ { Q2931_IE_NOTIFICATION_INDICATOR, "Notification indicator" },
+ { Q2931_IE_E2E_TRANSIT_DELAY, "End-to-end transit delay" },
+ { Q2931_IE_ENDPOINT_REFERENCE, "Endpoint reference" },
+ { Q2931_IE_ENDPOINT_STATE, "Endpoint state" },
+ { Q2931_IE_AAL_PARAMETERS, "AAL parameters" },
+ { Q2931_IE_ATM_USER_CELL_RATE, "ATM user cell rate" },
+ { Q2931_IE_CONNECTION_IDENTIFIER, "Connection identifier" },
+ { Q2931_IE_OAM_TRAFFIC_DESCRIPTOR, "OAM traffic descriptor" },
+ { Q2931_IE_QOS_PARAMETER, "Quality of service parameter" },
+ { Q2931_IE_BBAND_HI_LAYER_INFO, "Broadband high-layer information" },
+ { Q2931_IE_BBAND_BEARER_CAP, "Broadband bearer capability" },
+ { Q2931_IE_BBAND_LOW_LAYER_INFO, "Broadband low-layer information" },
+ { Q2931_IE_BBAND_LOCKING_SHIFT, "Broadband locking shift" },
+ { Q2931_IE_BBAND_NLOCKING_SHIFT, "Broadband non-locking shift" },
+ { Q2931_IE_BBAND_SENDING_COMPL, "Broadband sending complete" },
+ { Q2931_IE_BBAND_RPT_INDICATOR, "Broadband repeat indicator" },
+ { Q2931_IE_CALLING_PARTY_NUMBER, "Calling party number" },
+ { Q2931_IE_CALLING_PARTY_SUBADDR, "Calling party subaddress" },
+ { Q2931_IE_CALLED_PARTY_NUMBER, "Called party number" },
+ { Q2931_IE_CALLED_PARTY_SUBADDR, "Called party subaddress" },
+ { Q2931_IE_TRANSIT_NETWORK_SEL, "Transit network selection" },
+ { Q2931_IE_RESTART_INDICATOR, "Restart indicator" },
+ { Q2931_IE_NBAND_LOW_LAYER_COMPAT, "Narrowband low-layer compatibility" },
+ { Q2931_IE_NBAND_HIGH_LAYER_COMPAT, "Narrowband high-layer compatibility" },
+ { Q2931_IE_GENERIC_IDENT_TRANSPORT, "Generic identifier transport" },
+ { 0, NULL }
+};
+
+/*
+ * Dissect a locking or non-locking shift information element.
+ */
+static const value_string q2931_codeset_vals[] = {
+ { 0x00, "Q.2931 information elements" },
+ { 0x04, "Information elements for ISO/IEC use" },
+ { 0x05, "Information elements for national use" },
+ { 0x06, "Information elements specific to the local network" },
+ { 0x07, "User-specific information elements" },
+ { 0x00, NULL },
+};
+
+static void
+dissect_q2931_shift_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, guint8 info_element)
+{
+ gboolean non_locking_shift;
+ guint8 codeset;
+
+ if (len == 0)
+ return;
+ non_locking_shift = (info_element == Q2931_IE_BBAND_NLOCKING_SHIFT);
+ codeset = tvb_get_guint8(tvb, offset) & 0x07;
+ proto_tree_add_text(tree, tvb, offset, 1, "%s shift to codeset %u: %s",
+ (non_locking_shift ? "Non-locking" : "Locking"),
+ codeset,
+ val_to_str(codeset, q2931_codeset_vals, "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect an ATM adaptation layer parameters information element.
+ */
+#define Q2931_AAL_VOICE 0x00
+#define Q2931_AAL1 0x01
+#define Q2931_AAL2 0x02
+#define Q2931_AAL3_4 0x03
+#define Q2931_AAL5 0x05
+#define Q2931_USER_DEFINED_AAL 0x10
+
+static const value_string q9231_aal_type_vals[] = {
+ { 0x00, "AAL for voice" },
+ { 0x01, "AAL type 1" },
+ { 0x02, "AAL type 2" },
+ { 0x03, "AAL type 3/4" },
+ { 0x05, "AAL type 5" },
+ { 0x10, "User-defined AAL" },
+ { 0, NULL }
+};
+
+static const value_string q9231_aal1_subtype_vals[] = {
+ { 0x00, "Null" },
+ { 0x01, "64 kbit/s voice-band signal transport (G.711/G.722)" },
+ { 0x02, "Circuit transport (I.363)" },
+ { 0x03, "Circuit emulation (asynchronous)" },
+ { 0x04, "High-quality audio signal transport (I.363)" },
+ { 0x05, "Video signal transport (I.363)" },
+ { 0x00, NULL }
+};
+
+#define Q2931_AAL1_nx64_KBIT_S 0x40
+#define Q2931_AAL1_nx8_KBIT_S 0x41
+
+static const value_string q9231_aal1_cbr_rate_vals[] = {
+ { 0x01, "64 kbit/s" },
+ { 0x04, "1544 kbit/s" },
+ { 0x05, "6312 kbit/s" },
+ { 0x06, "32064 kbit/s" },
+ { 0x07, "44736 kbit/s" },
+ { 0x08, "97728 kbit/s" },
+ { 0x10, "2048 kbit/s" },
+ { 0x11, "8448 kibt/s" },
+ { 0x12, "34368 kbit/s" },
+ { 0x13, "139264 kbit/s" },
+ { Q2931_AAL1_nx64_KBIT_S, "nx64 kbit/s" },
+ { Q2931_AAL1_nx8_KBIT_S, "nx8 kbit/s" },
+ { 0x00, NULL }
+};
+
+static const value_string q2931_aal1_src_clk_rec_meth_vals[] = {
+ { 0x00, "Null (synchronous circuit transport)" },
+ { 0x01, "SRTS method (asynchronous circuit transport" },
+ { 0x02, "Adaptive clock method" },
+ { 0x00, NULL }
+};
+
+static const value_string q2931_aal1_err_correction_method_vals[] = {
+ { 0x00, "Null" },
+ { 0x01, "FEC method for less sensitive signal transport" },
+ { 0x02, "FEC method for delay-sensitive signal transport" },
+ { 0x00, NULL }
+};
+
+static const value_string q2931_aal_mode_vals[] = {
+ { 0x01, "Message" },
+ { 0x02, "Streaming" },
+ { 0x00, NULL }
+};
+
+static const value_string q2931_sscs_type_vals[] = {
+ { 0x00, "Null" },
+ { 0x01, "Data SSCS based on SSCOP (assured operation)" },
+ { 0x02, "Data SSCS based on SSCOP (non-assured operation)" },
+ { 0x04, "Frame relay SSCS" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q2931_aal_parameters_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 aal_type;
+ guint8 identifier;
+ guint32 value;
+ guint32 low_mid, high_mid;
+
+ if (len == 0)
+ return;
+ aal_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "AAL type: %s",
+ val_to_str(aal_type, q9231_aal_type_vals, "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ /*
+ * Now get the rest of the IE.
+ */
+ if (aal_type == 0x40) {
+ /*
+ * User-defined AAL.
+ */
+ if (len > 4)
+ len = 4;
+ proto_tree_add_text(tree, tvb, offset, len,
+ "User defined AAL information: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+
+ while (len != 0) {
+ identifier = tvb_get_guint8(tvb, offset);
+ switch (identifier) {
+
+ case 0x85: /* Subtype identifier for AAL1 */
+ if (len < 2)
+ return;
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Subtype: %s",
+ val_to_str(value, q9231_aal1_subtype_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ break;
+
+ case 0x86: /* CBR identifier for AAL1 */
+ if (len < 2)
+ return;
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "CBR rate: %s",
+ val_to_str(value, q9231_aal1_cbr_rate_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ break;
+
+ case 0x87: /* Multiplier identifier for AAL1 */
+ if (len < 3)
+ return;
+ value = tvb_get_ntohs(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Multiplier: %u", value);
+ offset += 3;
+ len -= 3;
+ break;
+
+ case 0x88: /* Source clock frequency recovery method identifier for AAL1 */
+ if (len < 2)
+ return;
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Source clock frequency recovery method: %s",
+ val_to_str(value, q2931_aal1_src_clk_rec_meth_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ break;
+
+ case 0x89: /* Error correction method identifier for AAL1 */
+ if (len < 2)
+ return;
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Error correction method: %s",
+ val_to_str(value, q2931_aal1_err_correction_method_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ break;
+
+ case 0x8A: /* Structured data transfer block size identifier for AAL1 */
+ if (len < 3)
+ return;
+ value = tvb_get_ntohs(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Structured data transfer block size: %u", value);
+ offset += 3;
+ len -= 3;
+ break;
+
+ case 0x8B: /* Partially filled cells identifier for AAL1 */
+ if (len < 2)
+ return;
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Partially filled cells method: %u octets", value);
+ offset += 2;
+ len -= 2;
+ break;
+
+ case 0x8C: /* Forward maximum CPCS-SDU size identifier for AAL3/4 and AAL5 */
+ if (len < 3)
+ return;
+ value = tvb_get_ntohs(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Forward maximum CPCS-SDU size: %u", value);
+ offset += 3;
+ len -= 3;
+ break;
+
+ case 0x81: /* Backward maximum CPCS-SDU size identifier for AAL3/4 and AAL5 */
+ if (len < 3)
+ return;
+ value = tvb_get_ntohs(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Backward maximum CPCS-SDU size: %u", value);
+ offset += 3;
+ len -= 3;
+ break;
+
+ case 0x82: /* MID range identifier for AAL3/4 */
+ if (len < 5)
+ return;
+ low_mid = tvb_get_ntohs(tvb, offset + 1);
+ high_mid = tvb_get_ntohs(tvb, offset + 3);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "MID range: %u - %u", low_mid, high_mid);
+ offset += 5;
+ len -= 5;
+ break;
+
+ case 0x83: /* Mode identifier for AAL3/4 and AAL5 */
+ if (len < 2)
+ return;
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Mode: %s",
+ val_to_str(value, q2931_aal_mode_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ break;
+
+ case 0x84: /* SSCS type identifier for AAL3/4 and AAL5 */
+ if (len < 2)
+ return;
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "SSCS type: %s",
+ val_to_str(value, q2931_sscs_type_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ break;
+
+ default: /* unknown AAL parameter */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Unknown AAL parameter (0x%02X)",
+ identifier);
+ return; /* give up */
+ }
+ }
+}
+
+/*
+ * Dissect an ATM traffic descriptor information element.
+ */
+#define Q2931_ATM_CR_FW_PEAK_CLP_0 0x82 /* Forward peak cell rate (CLP = 0) */
+#define Q2931_ATM_CR_BW_PEAK_CLP_0 0x83 /* Backward peak cell rate (CLP = 0) */
+#define Q2931_ATM_CR_FW_PEAK_CLP_0_1 0x84 /* Forward peak cell rate (CLP = 0 + 1) */
+#define Q2931_ATM_CR_BW_PEAK_CLP_0_1 0x85 /* Backward peak cell rate (CLP = 0 + 1) */
+#define Q2931_ATM_CR_FW_SUST_CLP_0 0x88 /* Forward sustainable cell rate (CLP = 0) */
+#define Q2931_ATM_CR_BW_SUST_CLP_0 0x89 /* Backward sustainable cell rate (CLP = 0) */
+#define Q2931_ATM_CR_FW_SUST_CLP_0_1 0x90 /* Forward sustainable cell rate (CLP = 0 + 1) */
+#define Q2931_ATM_CR_BW_SUST_CLP_0_1 0x91 /* Backward sustainable cell rate (CLP = 0 + 1) */
+#define Q2931_ATM_CR_FW_MAXB_CLP_0 0xA0 /* Forward maximum burst size (CLP = 0) */
+#define Q2931_ATM_CR_BW_MAXB_CLP_0 0xA1 /* Backward maximum burst size (CLP = 0) */
+#define Q2931_ATM_CR_FW_MAXB_CLP_0_1 0xB0 /* Forward maximum burst size (CLP = 0 + 1) */
+#define Q2931_ATM_CR_BW_MAXB_CLP_0_1 0xB1 /* Backward maximum burst size (CLP = 0 + 1) */
+#define Q2931_ATM_CR_BEST_EFFORT_IND 0xBE /* Best effort indicator */
+#define Q2931_ATM_CR_TRAFFIC_MGMT_OPT 0xBF /* Traffic management options */
+
+static const value_string q2931_atm_td_subfield_vals[] = {
+ { Q2931_ATM_CR_FW_PEAK_CLP_0, "Forward peak cell rate (CLP = 0)" },
+ { Q2931_ATM_CR_BW_PEAK_CLP_0, "Backward peak cell rate (CLP = 0)" },
+ { Q2931_ATM_CR_FW_PEAK_CLP_0_1, "Forward peak cell rate (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_BW_PEAK_CLP_0_1, "Backward peak cell rate (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_FW_SUST_CLP_0, "Forward sustainable cell rate (CLP = 0)" },
+ { Q2931_ATM_CR_BW_SUST_CLP_0, "Backward sustainable cell rate (CLP = 0)" },
+ { Q2931_ATM_CR_FW_SUST_CLP_0_1, "Forward sustainable cell rate (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_BW_SUST_CLP_0_1, "Backward sustainable cell rate (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_FW_MAXB_CLP_0, "Forward maximum burst size (CLP = 0)" },
+ { Q2931_ATM_CR_BW_MAXB_CLP_0, "Backward maximum burst size (CLP = 0)" },
+ { Q2931_ATM_CR_FW_MAXB_CLP_0_1, "Forward maximum burst size (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_BW_MAXB_CLP_0_1, "Backward maximum burst size (CLP = 0 + 1)" },
+ { Q2931_ATM_CR_BEST_EFFORT_IND, "Best effort indicator" },
+ { Q2931_ATM_CR_TRAFFIC_MGMT_OPT,"Traffic management options" },
+ { 0x0, NULL }
+};
+
+static void
+dissect_q2931_atm_cell_rate_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 identifier;
+ guint32 value;
+
+ while (len != 0) {
+ identifier = tvb_get_guint8(tvb, offset);
+ switch (identifier) {
+
+ case Q2931_ATM_CR_FW_PEAK_CLP_0:
+ case Q2931_ATM_CR_BW_PEAK_CLP_0:
+ case Q2931_ATM_CR_FW_PEAK_CLP_0_1:
+ case Q2931_ATM_CR_BW_PEAK_CLP_0_1:
+ case Q2931_ATM_CR_FW_SUST_CLP_0:
+ case Q2931_ATM_CR_BW_SUST_CLP_0:
+ case Q2931_ATM_CR_FW_SUST_CLP_0_1:
+ case Q2931_ATM_CR_BW_SUST_CLP_0_1:
+ case Q2931_ATM_CR_FW_MAXB_CLP_0:
+ case Q2931_ATM_CR_BW_MAXB_CLP_0:
+ case Q2931_ATM_CR_FW_MAXB_CLP_0_1:
+ case Q2931_ATM_CR_BW_MAXB_CLP_0_1:
+ if (len < 4)
+ return;
+ value = tvb_get_ntoh24(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "%s: %u cell%s/s",
+ val_to_str(identifier, q2931_atm_td_subfield_vals,
+ NULL),
+ value, plurality(value, "", "s"));
+ offset += 4;
+ len -= 4;
+ break;
+
+ case Q2931_ATM_CR_BEST_EFFORT_IND:
+ /* Yes, its value *IS* 0xBE.... */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s",
+ val_to_str(identifier, q2931_atm_td_subfield_vals,
+ NULL));
+ offset += 1;
+ len -= 1;
+ break;
+
+ case Q2931_ATM_CR_TRAFFIC_MGMT_OPT:
+ if (len < 2)
+ return;
+ value = tvb_get_guint8(tvb, offset + 1);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s",
+ val_to_str(identifier, q2931_atm_td_subfield_vals,
+ NULL));
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
+ "%s allowed in forward direction",
+ (value & 0x80) ? "Frame discard" : "No frame discard");
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
+ "%s allowed in backward direction",
+ (value & 0x40) ? "Frame discard" : "No frame discard");
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
+ "Tagging %srequested in backward direction",
+ (value & 0x02) ? "" : "not ");
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
+ "Tagging %srequested in forward direction",
+ (value & 0x01) ? "" : "not ");
+ offset += 2;
+ len -= 2;
+ break;
+
+ default: /* unknown ATM traffic descriptor element */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Unknown ATM traffic descriptor element (0x%02X)",
+ identifier);
+ return; /* give up */
+ }
+ }
+}
+
+/*
+ * Dissect a broadband bearer capability information element.
+ */
+static const value_string q2931_bearer_class_vals[] = {
+ { 0x01, "BCOB-A" },
+ { 0x03, "BCOB-C" },
+ { 0x10, "BCOB-X" },
+ { 0x18, "Transparent VP Service" },
+ { 0x00, NULL }
+};
+
+static const value_string q2931_transfer_capability_vals[] = {
+ { 0x00, "No bit rate indication" },
+ { 0x01, "No bit rate indication, end-to-end timing required" },
+ { 0x02, "No bit rate indication, end-to-end timing not required" },
+ { 0x04, "CBR" },
+ { 0x05, "CBR, end-to-end timing required" },
+ { 0x06, "CBR, end-to-end timing not required" },
+ { 0x07, "CBR with CLR commitment on CLP=0+1" },
+ { 0x08, "VBR, no timing requirements indication" },
+ { 0x09, "Real time VBR" },
+ { 0x0A, "Non-real time VBR" },
+ { 0x0B, "Non-real time VBR with CLR commitment on CLP=0+1" },
+ { 0x0C, "ABR" },
+ { 0x00, NULL }
+};
+
+static const value_string q2931_susc_clip_vals[] = {
+ { 0x00, "Not susceptible to clipping" },
+ { 0x20, "Susceptible to clipping" },
+ { 0x00, NULL }
+};
+
+static const value_string q2931_up_conn_config_vals[] = {
+ { 0x00, "Point-to-point" },
+ { 0x01, "Point-to-multipoint" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q2931_bband_bearer_cap_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Bearer class: %s",
+ val_to_str(octet & 0x1F, q2931_bearer_class_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ if (!(octet & Q2931_IE_EXTENSION)) {
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "ATM Transfer Capability: %s",
+ val_to_str(octet & 0x1F, q2931_transfer_capability_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Susceptibility to clipping: %s",
+ val_to_str(octet & 0x60, q2931_susc_clip_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User-plane connection configuration: %s",
+ val_to_str(octet & 0x03, q2931_up_conn_config_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a broadband high layer information information element.
+ */
+static const value_string q2931_hi_layer_info_type_vals[] = {
+ { 0x00, "ISO/IEC" },
+ { 0x01, "User-specific" },
+ { 0x03, "Vendor-specific" },
+ { 0x04, "ITU-T SG 1 B-ISDN teleservice recommendation" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q2931_bband_hi_layer_info_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "High layer information type: %s",
+ val_to_str(octet & 0x7F, q2931_hi_layer_info_type_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+}
+
+/*
+ * Dissect a Bearer capability or Low-layer compatibility information element.
+ */
+#define Q2931_UIL2_USER_SPEC 0x10
+
+static const value_string q2931_uil2_vals[] = {
+ { 0x01, "Basic mode ISO 1745" },
+ { 0x02, "Q.921/I.441" }, /* LAPD */
+ { 0x06, "X.25, link layer" }, /* LAPB */
+ { 0x07, "X.25 multilink" }, /* or 0x0F? */
+ { 0x08, "T.71 Extended LAPB" },
+ { 0x09, "HDLC ARM" },
+ { 0x0A, "HDLC NRM" },
+ { 0x0B, "HDLC ABM" },
+ { 0x0C, "ISO 8802/2 LLC" },
+ { 0x0D, "X.75 Single Link Procedure" },
+ { 0x0E, "Q.922" },
+ { Q2931_UIL2_USER_SPEC, "User-specified" },
+ { 0x11, "ISO 7776 DTE-DTE operation" },
+ { 0, NULL }
+};
+
+static const value_string q2931_mode_vals[] = {
+ { 0x20, "Normal mode" },
+ { 0x40, "Extended mode" },
+ { 0, NULL }
+};
+
+#define Q2931_UIL3_X25_PL 0x06
+#define Q2931_UIL3_ISO_8208 0x07 /* X.25-based */
+#define Q2931_UIL3_X223 0x08 /* X.25-based */
+#define Q2931_UIL3_TR_9577 0x0B
+#define Q2931_UIL3_USER_SPEC 0x10
+
+static const value_string q2931_uil3_vals[] = {
+ { Q2931_UIL3_X25_PL, "X.25, packet layer" },
+ { Q2931_UIL3_ISO_8208, "ISO/IEC 8208" },
+ { Q2931_UIL3_X223, "X.223/ISO 8878" },
+ { 0x09, "ISO/IEC 8473" },
+ { 0x0A, "T.70" },
+ { Q2931_UIL3_TR_9577, "ISO/IEC TR 9577" },
+ { Q2931_UIL3_USER_SPEC, "User-specified" },
+ { 0, NULL }
+};
+
+static const value_string lane_pid_vals[] = {
+ { 0x0001, "LE Configuration Direct/Control Direct/Control Distribute" },
+ { 0x0002, "Ethernet/IEEE 002.3 LE Data Direct" },
+ { 0x0003, "IEEE 802.5 LE Data Direct" },
+ { 0x0004, "Ethernet/IEEE 802.3 LE Multicast Send/Multicast Forward" },
+ { 0x0005, "IEEE 802.5 LE Multicast Send/Multicast Forward" },
+ { 0, NULL },
+};
+
+/*
+ * Dissect a broadband low layer information information element.
+ */
+static void
+dissect_q2931_bband_low_layer_info_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 uil2_protocol;
+ guint8 uil3_protocol;
+ guint8 add_l3_info;
+ guint32 organization_code;
+ guint16 pid;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0x60) == 0x20) {
+ /*
+ * Layer 1 information.
+ */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User information layer 1 protocol: 0x%02X",
+ octet & 0x1F);
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0x60) == 0x40) {
+ /*
+ * Layer 2 information.
+ */
+ uil2_protocol = octet & 0x1F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User information layer 2 protocol: %s",
+ val_to_str(uil2_protocol, q2931_uil2_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q2931_IE_EXTENSION)
+ goto l2_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if (uil2_protocol == Q2931_UIL2_USER_SPEC) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User-specified layer 2 protocol information: 0x%02X",
+ octet & 0x7F);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Mode: %s",
+ val_to_str(octet & 0x60, q2931_mode_vals,
+ "Unknown (0x%02X)"));
+ }
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q2931_IE_EXTENSION)
+ goto l2_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Window size: %u k", octet & 0x7F);
+ offset += 1;
+ len -= 1;
+ }
+l2_done:
+ ;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0x60) == 0x60) {
+ /*
+ * Layer 3 information.
+ */
+ uil3_protocol = octet & 0x1F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User information layer 3 protocol: %s",
+ val_to_str(uil3_protocol, q2931_uil3_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+
+ /*
+ * XXX - only in Low-layer compatibility information element.
+ */
+ if (octet & Q2931_IE_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ switch (uil3_protocol) {
+
+ case Q2931_UIL3_X25_PL:
+ case Q2931_UIL3_ISO_8208:
+ case Q2931_UIL3_X223:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Mode: %s",
+ val_to_str(octet & 0x60, q2931_mode_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q2931_IE_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Default packet size: %u", octet & 0x0F);
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q2931_IE_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Packet window size: %u", octet & 0x7F);
+ offset += 1;
+ len -= 1;
+ break;
+
+ case Q2931_UIL3_USER_SPEC:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Default packet size: %u octets",
+ 1 << (octet & 0x0F));
+ offset += 1;
+ len -= 1;
+ break;
+
+ case Q2931_UIL3_TR_9577:
+ add_l3_info = (octet & 0x7F) << 1;
+ if (octet & Q2931_IE_EXTENSION)
+ goto l3_done;
+ if (len < 2)
+ return;
+ add_l3_info |= (tvb_get_guint8(tvb, offset + 1) & 0x40) >> 6;
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Additional layer 3 protocol information: %s",
+ val_to_str(add_l3_info, nlpid_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ if (add_l3_info == NLPID_SNAP) {
+ if (len < 6)
+ return;
+ offset += 1;
+ len -= 1;
+ organization_code = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Organization Code: 0x%06X (%s)",
+ organization_code,
+ val_to_str(organization_code, oui_vals,
+ "Unknown"));
+ offset += 3;
+ len -= 3;
+
+ if (len < 2)
+ return;
+ pid = tvb_get_ntohs(tvb, offset);
+ switch (organization_code) {
+
+ case OUI_ENCAP_ETHER:
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Ethernet type: %s",
+ val_to_str(pid, etype_vals,
+ "Unknown (0x%04X)"));
+ break;
+
+ case OUI_ATM_FORUM:
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "LANE Protocol ID: %s",
+ val_to_str(pid, lane_pid_vals,
+ "Unknown (0x%04X)"));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Protocol ID: 0x%04X", pid);
+ break;
+ }
+ }
+ break;
+ }
+ }
+l3_done:
+ ;
+}
+
+/*
+ * Dissect a Cause information element.
+ */
+static const value_string q2931_cause_location_vals[] = {
+ { 0x00, "User (U)" },
+ { 0x01, "Private network serving the local user (LPN)" },
+ { 0x02, "Public network serving the local user (LN)" },
+ { 0x03, "Transit network (TN)" },
+ { 0x04, "Public network serving the remote user (RLN)" },
+ { 0x05, "Private network serving the remote user (RPN)" },
+ { 0x07, "International network (INTL)" },
+ { 0x0A, "Network beyond interworking point (BI)" },
+ { 0, NULL }
+};
+
+/*
+ * Cause codes for Cause.
+ */
+#define Q2931_CAUSE_UNALLOC_NUMBER 0x01
+#define Q2931_CAUSE_NO_ROUTE_TO_DEST 0x03
+#define Q2931_CAUSE_CALL_REJECTED 0x15
+#define Q2931_CAUSE_NUMBER_CHANGED 0x16
+#define Q2931_CAUSE_CELL_RATE_UNAVAIL 0x25
+#define Q2931_CAUSE_ACCESS_INFO_DISC 0x2B
+#define Q2931_CAUSE_QOS_UNAVAILABLE 0x31
+#define Q2931_CAUSE_CHAN_NONEXISTENT 0x52
+#define Q2931_CAUSE_INCOMPATIBLE_DEST 0x58
+#define Q2931_CAUSE_MAND_IE_MISSING 0x60
+#define Q2931_CAUSE_MT_NONEX_OR_UNIMPL 0x61
+#define Q2931_CAUSE_IE_NONEX_OR_UNIMPL 0x63
+#define Q2931_CAUSE_INVALID_IE_CONTENTS 0x64
+#define Q2931_CAUSE_MSG_INCOMPAT_W_CS 0x65
+#define Q2931_CAUSE_REC_TIMER_EXP 0x66
+
+static const value_string q2931_cause_code_vals[] = {
+ { Q2931_CAUSE_UNALLOC_NUMBER, "Unallocated (unassigned) number" },
+ { 0x02, "No route to specified transit network" },
+ { Q2931_CAUSE_NO_ROUTE_TO_DEST, "No route to destination" },
+ { 0x04, "Send special information tone" },
+ { 0x05, "Misdialled trunk prefix" },
+ { 0x06, "Channel unacceptable" },
+ { 0x07, "Call awarded and being delivered in an established channel" },
+ { 0x08, "Preemption" },
+ { 0x09, "Preemption - circuit reserved for reuse" },
+ { 0x0E, "QoR: ported number" },
+ { 0x10, "Normal call clearing" },
+ { 0x11, "User busy" },
+ { 0x12, "No user responding" },
+ { 0x13, "No answer from user (user alerted)" },
+ { 0x14, "Subscriber absent" },
+ { Q2931_CAUSE_CALL_REJECTED, "Call rejected" },
+ { Q2931_CAUSE_NUMBER_CHANGED, "Number changed" },
+ { 0x17, "Redirection to new destination" },
+ { 0x18, "Call rejected due to feature at the destination" },
+ { 0x19, "Exchange routing error" },
+ { 0x1A, "Non-selected user clearing" },
+ { 0x1B, "Destination out of order" },
+ { 0x1C, "Invalid number format (incomplete number)" },
+ { 0x1E, "Response to STATUS ENQUIRY" },
+ { 0x1F, "Normal unspecified" },
+ { 0x20, "Too many pending add party request" },
+ { 0x23, "Requested VPCI/VCI not available" },
+ { 0x24, "VPCI/VCI assignment failure" },
+ { Q2931_CAUSE_CELL_RATE_UNAVAIL,"User cell rate not available" },
+ { 0x26, "Network out of order" },
+ { 0x27, "Permanent frame mode connection out of service" },
+ { 0x28, "Permanent frame mode connection operational" },
+ { 0x29, "Temporary failure" },
+ { 0x2A, "Switching equipment congestion" },
+ { Q2931_CAUSE_ACCESS_INFO_DISC, "Access information discarded" },
+ { 0x2C, "Requested circuit/channel not available" },
+ { 0x2D, "No VPCI/VCI available" },
+ { 0x2F, "Resources unavailable, unspecified" },
+ { Q2931_CAUSE_QOS_UNAVAILABLE, "Quality of service unavailable" },
+ { 0x32, "Requested facility not subscribed" },
+ { 0x35, "Outgoing calls barred within CUG" },
+ { 0x37, "Incoming calls barred within CUG" },
+ { 0x39, "Bearer capability not authorized" },
+ { 0x3A, "Bearer capability not presently available" },
+ { 0x3E, "Inconsistency in designated outgoing access information and subscriber class" },
+ { 0x3F, "Service or option not available, unspecified" },
+ { 0x41, "Bearer capability not implemented" },
+ { 0x42, "Channel type not implemented" },
+ { 0x45, "Requested facility not implemented" },
+ { 0x46, "Only restricted digital information bearer capability is available" },
+ { 0x49, "Unsupported combination of traffic parameters" },
+ { 0x4E, "AAL parameters cannot be supported" },
+ { 0x4F, "Service or option not implemented, unspecified" },
+ { 0x51, "Invalid call reference value" },
+ { Q2931_CAUSE_CHAN_NONEXISTENT, "Identified channel does not exist" },
+ { 0x53, "Call identity does not exist for suspended call" },
+ { 0x54, "Call identity in use" },
+ { 0x55, "No call suspended" },
+ { 0x56, "Call having the requested call identity has been cleared" },
+ { 0x57, "Called user not member of CUG" },
+ { Q2931_CAUSE_INCOMPATIBLE_DEST,"Incompatible destination" },
+ { 0x59, "Invalid endpoint reference" },
+ { 0x5A, "Non-existent CUG" },
+ { 0x5B, "Invalid transit network selection" },
+ { 0x5C, "Too many pending ADD PARTY requests" },
+ { 0x5D, "AAL parameters cannot be supported" },
+ { 0x5F, "Invalid message, unspecified" },
+ { Q2931_CAUSE_MAND_IE_MISSING, "Mandatory information element is missing" },
+ { Q2931_CAUSE_MT_NONEX_OR_UNIMPL,"Message type non-existent or not implemented" },
+ { 0x62, "Message not compatible with call state or message type non-existent or not implemented" },
+ { Q2931_CAUSE_IE_NONEX_OR_UNIMPL,"Information element nonexistant or not implemented" },
+ { Q2931_CAUSE_INVALID_IE_CONTENTS,"Invalid information element contents" },
+ { Q2931_CAUSE_MSG_INCOMPAT_W_CS,"Message not compatible with call state" },
+ { Q2931_CAUSE_REC_TIMER_EXP, "Recovery on timer expiry" },
+ { 0x67, "Parameter non-existent or not implemented - passed on" },
+ { 0x68, "Incorrect message length" },
+ { 0x6E, "Message with unrecognized parameter discarded" },
+ { 0x6F, "Protocol error, unspecified" },
+ { 0x7F, "Internetworking, unspecified" },
+ { 0, NULL }
+};
+
+static const value_string q2931_cause_condition_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Permanent" },
+ { 0x02, "Transient" },
+ { 0x00, NULL }
+};
+
+#define Q2931_REJ_USER_SPECIFIC 0x00
+#define Q2931_REJ_IE_MISSING 0x04
+#define Q2931_REJ_IE_INSUFFICIENT 0x08
+
+static const value_string q2931_rejection_reason_vals[] = {
+ { 0x00, "User specific" },
+ { 0x04, "Information element missing" },
+ { 0x08, "Information element contents are not sufficient" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q2931_cause_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 cause_value;
+ guint8 rejection_reason;
+ guint8 info_element;
+ guint8 info_element_ext;
+ guint16 info_element_len;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Location: %s",
+ val_to_str(octet & 0x0F, q2931_cause_location_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ cause_value = octet & 0x7F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Cause value: %s",
+ val_to_str(cause_value, q2931_cause_code_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (cause_value) {
+
+ case Q2931_CAUSE_UNALLOC_NUMBER:
+ case Q2931_CAUSE_NO_ROUTE_TO_DEST:
+ case Q2931_CAUSE_QOS_UNAVAILABLE:
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Network service: %s",
+ (octet & 0x80) ? "User" : "Provider");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s",
+ (octet & 0x40) ? "Abnormal" : "Normal");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Condition: %s",
+ val_to_str(octet & 0x03, q2931_cause_condition_vals,
+ "Unknown (0x%X)"));
+ break;
+
+ case Q2931_CAUSE_CALL_REJECTED:
+ rejection_reason = octet & 0x7C;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Rejection reason: %s",
+ val_to_str(octet & 0x7C, q2931_rejection_reason_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Condition: %s",
+ val_to_str(octet & 0x03, q2931_cause_condition_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (rejection_reason) {
+
+ case Q2931_REJ_USER_SPECIFIC:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "User specific diagnostic: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+
+ case Q2931_REJ_IE_MISSING:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_info_element_vals,
+ "Unknown (0x%02X)"));
+ break;
+
+ case Q2931_REJ_IE_INSUFFICIENT:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Insufficient information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_info_element_vals,
+ "Unknown (0x%02X)"));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Diagnostic: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+ }
+ break;
+
+ case Q2931_CAUSE_NUMBER_CHANGED:
+ /*
+ * UNI 3.1 claims this "is formatted as the called party
+ * number information element, including information
+ * element identifier.
+ */
+ info_element = tvb_get_guint8(tvb, offset);
+ info_element_ext = tvb_get_guint8(tvb, offset + 1);
+ info_element_len = tvb_get_ntohs(tvb, offset + 2);
+ dissect_q2931_ie(tvb, offset, info_element_len, tree,
+ info_element, info_element_ext);
+ break;
+
+ case Q2931_CAUSE_ACCESS_INFO_DISC:
+ case Q2931_CAUSE_INCOMPATIBLE_DEST:
+ case Q2931_CAUSE_MAND_IE_MISSING:
+ case Q2931_CAUSE_IE_NONEX_OR_UNIMPL:
+ case Q2931_CAUSE_INVALID_IE_CONTENTS:
+ do {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_info_element_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+ } while (len != 0);
+ break;
+
+ case Q2931_CAUSE_CELL_RATE_UNAVAIL:
+ do {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Cell rate subfield identifier: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_atm_td_subfield_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+ } while (len != 0);
+ break;
+
+ case Q2931_CAUSE_CHAN_NONEXISTENT:
+ if (len < 2)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "VPCI: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ len -= 2;
+
+ if (len < 2)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "VCI: %u", tvb_get_ntohs(tvb, offset));
+ break;
+
+ case Q2931_CAUSE_MT_NONEX_OR_UNIMPL:
+ case Q2931_CAUSE_MSG_INCOMPAT_W_CS:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Message type: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q2931_message_type_vals,
+ "Unknown (0x%02X)"));
+ break;
+
+ case Q2931_CAUSE_REC_TIMER_EXP:
+ if (len < 3)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Timer: %.3s", tvb_get_ptr(tvb, offset, 3));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Diagnostics: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ }
+}
+
+/*
+ * Dissect a Call state information element.
+ */
+static const value_string q2931_call_state_vals[] = {
+ { 0x00, "Null" },
+ { 0x01, "Call initiated" },
+ { 0x02, "Overlap sending" },
+ { 0x03, "Outgoing call proceeding" },
+ { 0x04, "Call delivered" },
+ { 0x06, "Call present" },
+ { 0x07, "Call received" },
+ { 0x09, "Connect request" },
+ { 0x0A, "Incoming call proceeding" },
+ { 0x0B, "Active" },
+ { 0x0C, "Disconnect request" },
+ { 0x0F, "Disconnect indication" },
+ { 0x11, "Suspend request" },
+ { 0x13, "Resume request" },
+ { 0x16, "Release request" },
+ { 0x19, "Overlap receiving" },
+ { 0x3D, "Restart request" },
+ { 0x3E, "Restart" },
+ { 0, NULL }
+};
+
+static void
+dissect_q2931_call_state_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Call state: %s",
+ val_to_str(octet & 0x3F, q2931_call_state_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a (phone) number information element.
+ */
+static const value_string q2931_number_type_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x10, "International number" },
+ { 0x20, "National number" },
+ { 0x30, "Network specific number" },
+ { 0x40, "Subscriber number" },
+ { 0x60, "Abbreviated number" },
+ { 0, NULL }
+};
+
+#define Q2931_ISDN_NUMBERING 0x01
+#define Q2931_NSAP_ADDRESSING 0x02
+
+static const value_string q2931_numbering_plan_vals[] = {
+ { 0x00, "Unknown" },
+ { Q2931_ISDN_NUMBERING, "E.164 ISDN/telephony numbering" },
+ { Q2931_NSAP_ADDRESSING, "ISO/IEC 8348 NSAP addressing" },
+ { 0x09, "Private numbering" },
+ { 0, NULL }
+};
+
+static const value_string q2931_presentation_indicator_vals[] = {
+ { 0x00, "Presentation allowed" },
+ { 0x20, "Presentation restricted" },
+ { 0x40, "Number not available" },
+ { 0, NULL }
+};
+
+static const value_string q2931_screening_indicator_vals[] = {
+ { 0x00, "User-provided, not screened" },
+ { 0x01, "User-provided, verified and passed" },
+ { 0x02, "User-provided, verified and failed" },
+ { 0x03, "Network-provided" },
+ { 0, NULL }
+};
+
+static void
+dissect_q2931_number_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 numbering_plan;
+ proto_item *ti;
+ proto_tree *nsap_tree;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Type of number: %s",
+ val_to_str(octet & 0x70, q2931_number_type_vals,
+ "Unknown (0x%02X)"));
+ numbering_plan = octet & 0x0F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Numbering plan: %s",
+ val_to_str(numbering_plan, q2931_numbering_plan_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (!(octet & Q2931_IE_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Presentation indicator: %s",
+ val_to_str(octet & 0x60, q2931_presentation_indicator_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Screening indicator: %s",
+ val_to_str(octet & 0x03, q2931_screening_indicator_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ switch (numbering_plan) {
+
+ case Q2931_ISDN_NUMBERING:
+ proto_tree_add_text(tree, tvb, offset, len, "Number: %.*s",
+ len, tvb_get_ptr(tvb, offset, len));
+ break;
+
+ case Q2931_NSAP_ADDRESSING:
+ if (len < 20) {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Number (too short): %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, len, "Number");
+ nsap_tree = proto_item_add_subtree(ti, ett_q2931_nsap);
+ dissect_atm_nsap(tvb, offset, len, nsap_tree);
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len, "Number: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+ }
+}
+
+/*
+ * Dissect a party subaddress information element.
+ */
+static const value_string q2931_subaddress_type_vals[] = {
+ { 0x00, "X.213/ISO 8348 NSAP" },
+ { 0x10, "User-specified ATM endsystem address" },
+ { 0x20, "User-specified" },
+ { 0, NULL }
+};
+
+static const value_string q2931_odd_even_indicator_vals[] = {
+ { 0x00, "Even number of address signals" },
+ { 0x10, "Odd number of address signals" },
+ { 0, NULL }
+};
+
+static void
+dissect_q2931_party_subaddr_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Type of subaddress: %s",
+ val_to_str(octet & 0x70, q2931_subaddress_type_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Odd/even indicator: %s",
+ val_to_str(octet & 0x10, q2931_odd_even_indicator_vals,
+ NULL));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, len, "Subaddress: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+}
+
+/*
+ * Dissect a connection identifier information element.
+ */
+static const value_string q2931_vp_associated_signalling_vals[] = {
+ { 0x00, "Yes" },
+ { 0x08, "No - explicit indication of VPCI" },
+ { 0x00, NULL }
+};
+
+static const value_string q2931_preferred_exclusive_vals[] = {
+ { 0x00, "Exclusive VPCI; exclusive VCI" },
+ { 0x01, "Exclusive VPCI; any VCI" },
+ { 0x04, "Exclusive VPCI; no VCI" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q2931_connection_identifier_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "VP-associated signalling: %s",
+ val_to_str(octet & 0x18, q2931_vp_associated_signalling_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Preferred/exclusive: %s",
+ val_to_str(octet & 0x07, q2931_preferred_exclusive_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len < 2)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 2, "VPCI: %u",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ len -= 2;
+
+ if (len < 2)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 2, "VCI: %u",
+ tvb_get_ntohs(tvb, offset));
+}
+
+/*
+ * Dissect an End-to-end transit delay information element.
+ */
+static void
+dissect_q2931_e2e_transit_delay_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 identifier;
+ guint16 value;
+
+ while (len >= 3) {
+ identifier = tvb_get_guint8(tvb, offset);
+ value = tvb_get_ntohs(tvb, offset + 1);
+ switch (identifier) {
+
+ case 0x01: /* Cumulative transit delay identifier */
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Cumulative transit delay: %u ms", value);
+ break;
+
+ case 0x03: /* Maximum transit delay identifier */
+ if (value == 0xFFFF) {
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Any end-to-end transit delay value acceptable");
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Maximum end-to-end transit delay: %u ms",
+ value);
+ }
+ break;
+
+ default: /* Unknown transit delay identifier */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Unknown transit delay identifier (0x%02X)",
+ identifier);
+ return; /* give up */
+ }
+ }
+}
+
+/*
+ * Dissect a Quality of Service parameter information element.
+ */
+static const value_string q2931_qos_parameter_vals[] = {
+ { 0x00, "Unspecified QOS class" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q2931_qos_parameter_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "QOS class forward: %s",
+ val_to_str(octet, q2931_qos_parameter_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "QOS class backward: %s",
+ val_to_str(octet, q2931_qos_parameter_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a broadband repeat indicator.
+ */
+static const value_string q2931_bband_rpt_indicator_vals[] = {
+ { 0x02, "Prioritized list for selecting one possibility (descending order)" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q2931_bband_rpt_indicator(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Broadband repeat indicator: %s",
+ val_to_str(octet & 0x0F, q2931_bband_rpt_indicator_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a restart indicator.
+ */
+static const value_string q2931_class_vals[] = {
+ { 0x00, "Indicated VC" },
+ { 0x01, "All VC's in the indicated VPC controlled via this channel" },
+ { 0x02, "All VC's controlled by the L3 entity that sent this message" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q2931_restart_indicator(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Restart indicator: %s",
+ val_to_str(octet & 0x07, q2931_class_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect an broadband sending complete information element.
+ */
+static void
+dissect_q2931_bband_sending_compl_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 identifier;
+
+ while (len != 0) {
+ identifier = tvb_get_guint8(tvb, offset);
+ switch (identifier) {
+
+ case 0xA1: /* Sending complete indication */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Broadband sending complete indication");
+ offset += 1;
+ len -= 1;
+ break;
+
+ default: /* unknown broadband sending complete element */
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Unknown broadband sending complete element (0x%02X)",
+ identifier);
+ return; /* give up */
+ }
+ }
+}
+
+/*
+ * Dissect a Transit network selection information element.
+ */
+static const value_string q2931_netid_type_vals[] = {
+ { 0x00, "User specified" },
+ { 0x20, "National network identification" },
+ { 0x30, "International network identification" },
+ { 0, NULL }
+};
+
+static const value_string q2931_netid_plan_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Carrier Identification Code" },
+ { 0x03, "X.121 data network identification code" },
+ { 0, NULL }
+};
+
+static void
+dissect_q2931_transit_network_sel_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Type of network identification: %s",
+ val_to_str(octet & 0x70, q2931_netid_type_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Network identification plan: %s",
+ val_to_str(octet & 0x0F, q2931_netid_plan_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Network identification: %.*s", len, tvb_get_ptr(tvb, offset, len));
+}
+
+/*
+ * Dissect an OAM traffic descriptor information element.
+ */
+static const value_string q2931_shaping_indicator_vals[] = {
+ { 0x00, "No user specified requirement" },
+ { 0x20, "Aggregate shaping of user and OAM cells not allowed" },
+ { 0, NULL }
+};
+
+static const value_string q2931_user_net_fault_mgmt_vals[] = {
+ { 0x00, "No user-originated fault managment indications" },
+ { 0x01, "User-originated fault management indications, cell rate 1 cell/s" },
+ { 0, NULL }
+};
+
+static const value_string q2931_fwd_e2e_oam_f5_flow_indicator_vals[] = {
+ { 0x00, "0% of the forward cell rate" },
+ { 0x10, "0.1% of the forward cell rate" },
+ { 0x40, "1% of the forward cell rate" },
+ { 0x0, NULL }
+};
+
+static const value_string q2931_bwd_e2e_oam_f5_flow_indicator_vals[] = {
+ { 0x00, "0% of the backward cell rate" },
+ { 0x01, "0.1% of the backward cell rate" },
+ { 0x04, "1% of the backward cell rate" },
+ { 0x0, NULL }
+};
+
+static void
+dissect_q2931_oam_traffic_descriptor_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Shaping indicator: %s",
+ val_to_str(octet & 0x60, q2931_shaping_indicator_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Use of end-to-end OAM F5 flow is %s",
+ (octet & 0x10) ? "mandatory" : "optional");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User-Network fault management indicator: %s",
+ val_to_str(octet & 0x07, q2931_user_net_fault_mgmt_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Forward end-to-end OAM F5 flow indicator: %s",
+ val_to_str(octet & 0x70, q2931_fwd_e2e_oam_f5_flow_indicator_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Backward end-to-end OAM F5 flow indicator: %s",
+ val_to_str(octet & 0x07, q2931_bwd_e2e_oam_f5_flow_indicator_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect an Endpoint reference information element.
+ */
+static const value_string q2931_endpoint_reference_type_vals[] = {
+ { 0x00, "Locally defined integer" },
+ { 0, NULL }
+};
+
+static void
+dissect_q2931_endpoint_reference_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint16 value;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Endpoint reference type: %s",
+ val_to_str(octet, q2931_endpoint_reference_type_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len < 2)
+ return;
+ value = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Endpoint reference flag: %s",
+ (value & 0x8000) ? "Message sent to side that originates the endpoint reference" :
+ "Message sent from side that originates the endpoint reference");
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Endpoint reference identifier value: %u",
+ value & 0x7FFF);
+}
+
+/*
+ * Dissect an Endpoint state information element.
+ */
+static const value_string q2931_endpoint_reference_party_state_vals[] = {
+ { 0x00, "Null" },
+ { 0x01, "ADD PARTY initiated" },
+ { 0x06, "ADD PARTY received" },
+ { 0x0B, "DROP PARTY initiated" },
+ { 0x0C, "DROP PARTY received" },
+ { 0x0A, "Active" },
+ { 0, NULL }
+};
+
+static void
+dissect_q2931_endpoint_state_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Endpoint reference party-state: %s",
+ val_to_str(octet & 0x3F, q2931_endpoint_reference_party_state_vals,
+ "Unknown (0x%02X)"));
+}
+
+static void
+dissect_q2931_ie_contents(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, guint8 info_element)
+{
+ switch (info_element) {
+
+ case Q2931_IE_BBAND_LOCKING_SHIFT:
+ case Q2931_IE_BBAND_NLOCKING_SHIFT:
+ dissect_q2931_shift_ie(tvb, offset, len, tree, info_element);
+ break;
+
+ case Q2931_IE_NBAND_BEARER_CAP:
+ case Q2931_IE_NBAND_LOW_LAYER_COMPAT:
+ dissect_q931_bearer_capability_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_NBAND_HIGH_LAYER_COMPAT:
+ dissect_q931_high_layer_compat_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_PROGRESS_INDICATOR:
+ dissect_q931_progress_indicator_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_AAL_PARAMETERS:
+ dissect_q2931_aal_parameters_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_ATM_USER_CELL_RATE:
+ dissect_q2931_atm_cell_rate_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_BBAND_BEARER_CAP:
+ dissect_q2931_bband_bearer_cap_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_BBAND_HI_LAYER_INFO:
+ dissect_q2931_bband_hi_layer_info_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_BBAND_LOW_LAYER_INFO:
+ dissect_q2931_bband_low_layer_info_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_CALL_STATE:
+ dissect_q2931_call_state_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_CALLED_PARTY_NUMBER:
+ case Q2931_IE_CALLING_PARTY_NUMBER:
+ dissect_q2931_number_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_CALLED_PARTY_SUBADDR:
+ case Q2931_IE_CALLING_PARTY_SUBADDR:
+ dissect_q2931_party_subaddr_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_CAUSE:
+ dissect_q2931_cause_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_CONNECTION_IDENTIFIER:
+ dissect_q2931_connection_identifier_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_E2E_TRANSIT_DELAY:
+ dissect_q2931_e2e_transit_delay_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_QOS_PARAMETER:
+ dissect_q2931_qos_parameter_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_BBAND_RPT_INDICATOR:
+ dissect_q2931_bband_rpt_indicator(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_RESTART_INDICATOR:
+ dissect_q2931_restart_indicator(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_BBAND_SENDING_COMPL:
+ dissect_q2931_bband_sending_compl_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_TRANSIT_NETWORK_SEL:
+ dissect_q2931_transit_network_sel_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_OAM_TRAFFIC_DESCRIPTOR:
+ dissect_q2931_oam_traffic_descriptor_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_ENDPOINT_REFERENCE:
+ dissect_q2931_endpoint_reference_ie(tvb, offset, len, tree);
+ break;
+
+ case Q2931_IE_ENDPOINT_STATE:
+ dissect_q2931_endpoint_state_ie(tvb, offset, len, tree);
+ break;
+ }
+}
+
+static void
+dissect_q2931_ie(tvbuff_t *tvb, int offset, int len, proto_tree *tree,
+ guint8 info_element, guint8 info_element_ext)
+{
+ proto_item *ti;
+ proto_tree *ie_tree;
+ proto_tree *ie_ext_tree;
+
+ ti = proto_tree_add_text(tree, tvb, offset, 1+1+2+len, "%s",
+ val_to_str(info_element, q2931_info_element_vals,
+ "Unknown information element (0x%02X)"));
+ ie_tree = proto_item_add_subtree(ti, ett_q2931_ie);
+ proto_tree_add_text(ie_tree, tvb, offset, 1, "Information element: %s",
+ val_to_str(info_element, q2931_info_element_vals,
+ "Unknown (0x%02X)"));
+ ti = proto_tree_add_text(ie_tree, tvb, offset + 1, 1,
+ "Information element extension: 0x%02x",
+ info_element_ext);
+ ie_ext_tree = proto_item_add_subtree(ti, ett_q2931_ie_ext);
+ proto_tree_add_text(ie_ext_tree, tvb, offset + 1, 1,
+ decode_enumerated_bitfield(info_element_ext,
+ Q2931_IE_COMPAT_CODING_STD, 8,
+ coding_std_vals, "Coding standard: %s"));
+ proto_tree_add_text(ie_ext_tree, tvb, offset + 1, 1,
+ decode_boolean_bitfield(info_element_ext,
+ Q2931_IE_COMPAT_FOLLOW_INST, 8,
+ "Follow explicit error handling instructions",
+ "Regular error handling procedures apply"));
+ if (info_element_ext & Q2931_IE_COMPAT_FOLLOW_INST) {
+ proto_tree_add_text(ie_ext_tree, tvb, offset + 1, 1,
+ decode_enumerated_bitfield(info_element_ext,
+ Q2931_IE_COMPAT_ACTION_IND, 8,
+ ie_action_ind_vals,
+ "Action indicator: %s"));
+ }
+ proto_tree_add_text(ie_tree, tvb, offset + 2, 2, "Length: %u", len);
+
+ if ((info_element_ext & Q2931_IE_COMPAT_CODING_STD)
+ == Q2931_ITU_STANDARDIZED_CODING) {
+ dissect_q2931_ie_contents(tvb, offset + 4,
+ len, ie_tree, info_element);
+ } else {
+ /*
+ * We don't know how it's encoded, so just
+ * dump it as data and be done with it.
+ */
+ proto_tree_add_text(ie_tree, tvb, offset + 4, len,
+ "Data: %s", tvb_bytes_to_str(tvb, offset + 4, len));
+ }
+}
+
+static void
+dissect_q2931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *q2931_tree = NULL;
+ proto_item *ti;
+ proto_tree *ext_tree;
+ guint8 call_ref_len;
+ guint8 call_ref[15];
+ guint8 message_type;
+ guint8 message_type_ext;
+ guint16 message_len;
+ guint8 info_element;
+ guint8 info_element_ext;
+ guint16 info_element_len;
+ int codeset;
+ gboolean non_locking_shift;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Q.2931");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_q2931, tvb, offset, -1,
+ FALSE);
+ q2931_tree = proto_item_add_subtree(ti, ett_q2931);
+
+ proto_tree_add_uint(q2931_tree, hf_q2931_discriminator, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ }
+ offset += 1;
+ call_ref_len = tvb_get_guint8(tvb, offset) & 0xF; /* XXX - do as a bit field? */
+ if (q2931_tree != NULL)
+ proto_tree_add_uint(q2931_tree, hf_q2931_call_ref_len, tvb, offset, 1, call_ref_len);
+ offset += 1;
+ if (call_ref_len != 0) {
+ tvb_memcpy(tvb, call_ref, offset, call_ref_len);
+ if (q2931_tree != NULL) {
+ proto_tree_add_boolean(q2931_tree, hf_q2931_call_ref_flag,
+ tvb, offset, 1, (call_ref[0] & 0x80) != 0);
+ call_ref[0] &= 0x7F;
+ proto_tree_add_bytes(q2931_tree, hf_q2931_call_ref, tvb, offset, call_ref_len, call_ref);
+ }
+ offset += call_ref_len;
+ }
+ message_type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(message_type, q2931_message_type_vals,
+ "Unknown message type (0x%02X)"));
+ }
+ if (q2931_tree != NULL)
+ proto_tree_add_uint(q2931_tree, hf_q2931_message_type, tvb, offset, 1, message_type);
+ offset += 1;
+
+ message_type_ext = tvb_get_guint8(tvb, offset);
+ if (q2931_tree != NULL) {
+ ti = proto_tree_add_uint(q2931_tree, hf_q2931_message_type_ext, tvb,
+ offset, 1, message_type_ext);
+ ext_tree = proto_item_add_subtree(ti, ett_q2931_ext);
+ proto_tree_add_boolean(ext_tree, hf_q2931_message_flag, tvb,
+ offset, 1, message_type_ext);
+ if (message_type_ext & Q2931_MSG_TYPE_EXT_FOLLOW_INST) {
+ proto_tree_add_uint(ext_tree, hf_q2931_message_action_indicator, tvb,
+ offset, 1, message_type_ext);
+ }
+ }
+ offset += 1;
+
+ message_len = tvb_get_ntohs(tvb, offset);
+ if (q2931_tree != NULL)
+ proto_tree_add_uint(q2931_tree, hf_q2931_message_len, tvb, offset, 2, message_len);
+ offset += 2;
+
+ /*
+ * And now for the information elements....
+ */
+ codeset = 0; /* start out in codeset 0 */
+ non_locking_shift = TRUE;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ info_element = tvb_get_guint8(tvb, offset);
+ info_element_ext = tvb_get_guint8(tvb, offset + 1);
+ info_element_len = tvb_get_ntohs(tvb, offset + 2);
+ if (q2931_tree != NULL) {
+ dissect_q2931_ie(tvb, offset, info_element_len,
+ q2931_tree, info_element, info_element_ext);
+ }
+ if (non_locking_shift)
+ codeset = 0;
+
+ /*
+ * Handle shifts.
+ */
+ switch (info_element) {
+
+ case Q2931_IE_BBAND_LOCKING_SHIFT:
+ if (info_element_len >= 1) {
+ non_locking_shift = FALSE;
+ codeset = tvb_get_guint8(tvb, offset + 4) & 0x07;
+ }
+ break;
+
+ case Q2931_IE_BBAND_NLOCKING_SHIFT:
+ if (info_element_len >= 1) {
+ non_locking_shift = TRUE;
+ codeset = tvb_get_guint8(tvb, offset + 4) & 0x07;
+ }
+ break;
+ }
+ offset += 1 + 1 + 2 + info_element_len;
+ }
+}
+
+void
+proto_register_q2931(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_q2931_discriminator,
+ { "Protocol discriminator", "q2931.disc", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_call_ref_len,
+ { "Call reference value length", "q2931.call_ref_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_call_ref_flag,
+ { "Call reference flag", "q2931.call_ref_flag", FT_BOOLEAN, BASE_NONE, TFS(&tfs_call_ref_flag), 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_call_ref,
+ { "Call reference value", "q2931.call_ref", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_message_type,
+ { "Message type", "q2931.message_type", FT_UINT8, BASE_HEX, VALS(q2931_message_type_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_message_type_ext,
+ { "Message type extension", "q2931.message_type_ext", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q2931_message_flag,
+ { "Flag", "q2931.message_flag", FT_BOOLEAN, 8, TFS(&tos_msg_flag), Q2931_MSG_TYPE_EXT_FOLLOW_INST,
+ "", HFILL }},
+
+ { &hf_q2931_message_action_indicator,
+ { "Action indicator", "q2931.message_action_indicator", FT_UINT8, BASE_DEC, VALS(msg_action_ind_vals), Q2931_MSG_TYPE_EXT_ACTION_IND,
+ "", HFILL }},
+
+ { &hf_q2931_message_len,
+ { "Message length", "q2931.message_len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_q2931,
+ &ett_q2931_ext,
+ &ett_q2931_ie,
+ &ett_q2931_ie_ext,
+ &ett_q2931_nsap,
+ };
+
+ proto_q2931 = proto_register_protocol("Q.2931", "Q.2931", "q2931");
+ proto_register_field_array (proto_q2931, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("q2931", dissect_q2931, proto_q2931);
+}
diff --git a/epan/dissectors/packet-q931.c b/epan/dissectors/packet-q931.c
new file mode 100644
index 0000000000..10da9f3c95
--- /dev/null
+++ b/epan/dissectors/packet-q931.c
@@ -0,0 +1,3166 @@
+/* packet-q931.c
+ * Routines for Q.931 frame disassembly
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Modified by Andreas Sikkema for possible use with H.323
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "nlpid.h"
+#include "packet-q931.h"
+#include "packet-e164.h"
+#include "prefs.h"
+#include "reassemble.h"
+
+#include "lapd_sapi.h"
+#include "packet-tpkt.h"
+
+/* Q.931 references:
+ *
+ * http://www.acacia-net.com/Clarinet/Protocol/q9313svn.htm
+ * http://www.acacia-net.com/Clarinet/Protocol/q9311sc3.htm
+ * http://www.acacia-net.com/Clarinet/Protocol/q9317oz7.htm
+ * http://www.protocols.com/pbook/isdn.htm
+ * http://freesoft.org/CIE/Topics/126.htm
+ * http://noc.comstar.ru/miscdocs/ascend-faq-cause-codes.html
+ * http://www.andrews-arnold.co.uk/isdn/q931cause.html
+ * http://www.tulatelecom.ru/staff/german/DSSHelp/MessList/InfEl/InfElList.html
+ */
+
+static int proto_q931 = -1;
+static int hf_q931_discriminator = -1;
+static int hf_q931_coding_standard = -1;
+static int hf_q931_information_transfer_capability = -1;
+static int hf_q931_transfer_mode = -1;
+static int hf_q931_information_transfer_rate = -1;
+static int hf_q931_uil1 = -1;
+static int hf_q931_call_ref_len = -1;
+static int hf_q931_call_ref_flag = -1;
+static int hf_q931_call_ref = -1;
+static int hf_q931_message_type = -1;
+static int hf_q931_segment_type = -1;
+static int hf_q931_cause_location = -1;
+static int hf_q931_cause_value = -1;
+static int hf_q931_number_type = -1;
+static int hf_q931_numbering_plan = -1;
+static int hf_q931_extension_ind = -1;
+static int hf_q931_calling_party_number = -1;
+static int hf_q931_called_party_number = -1;
+static int hf_q931_connected_number = -1;
+static int hf_q931_redirecting_number = -1;
+static int hf_q931_screening_ind = -1;
+static int hf_q931_presentation_ind = -1;
+
+static int hf_q931_segments = -1;
+static int hf_q931_segment = -1;
+static int hf_q931_segment_overlap = -1;
+static int hf_q931_segment_overlap_conflict = -1;
+static int hf_q931_segment_multiple_tails = -1;
+static int hf_q931_segment_too_long_segment = -1;
+static int hf_q931_segment_error = -1;
+static int hf_q931_reassembled_in = -1;
+
+static gint ett_q931 = -1;
+static gint ett_q931_ie = -1;
+
+static gint ett_q931_segments = -1;
+static gint ett_q931_segment = -1;
+
+static const fragment_items q931_frag_items = {
+ &ett_q931_segment,
+ &ett_q931_segments,
+
+ &hf_q931_segments,
+ &hf_q931_segment,
+ &hf_q931_segment_overlap,
+ &hf_q931_segment_overlap_conflict,
+ &hf_q931_segment_multiple_tails,
+ &hf_q931_segment_too_long_segment,
+ &hf_q931_segment_error,
+ &hf_q931_reassembled_in,
+ "segments"
+};
+
+/* Tables for reassembly of fragments. */
+static GHashTable *q931_fragment_table = NULL;
+static GHashTable *q931_reassembled_table = NULL;
+
+/* Preferences */
+static gboolean q931_reassembly = TRUE;
+
+static dissector_table_t codeset_dissector_table;
+static dissector_table_t ie_dissector_table;
+
+/* desegmentation of Q.931 over TPKT over TCP */
+static gboolean q931_desegment = TRUE;
+
+static dissector_handle_t h225_handle;
+static dissector_handle_t q931_tpkt_pdu_handle;
+
+static void
+dissect_q931_IEs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *root_tree,
+ proto_tree *q931_tree, gboolean is_tpkt, int offset, int initial_codeset);
+
+/*
+ * Q.931 message types.
+ */
+#define Q931_ESCAPE 0x00
+#define Q931_ALERTING 0x01
+#define Q931_CALL_PROCEEDING 0x02
+#define Q931_CONNECT 0x07
+#define Q931_CONNECT_ACK 0x0F
+#define Q931_PROGRESS 0x03
+#define Q931_SETUP 0x05
+#define Q931_SETUP_ACK 0x0D
+#define Q931_HOLD 0x24
+#define Q931_HOLD_ACK 0x28
+#define Q931_HOLD_REJECT 0x30
+#define Q931_RESUME 0x26
+#define Q931_RESUME_ACK 0x2E
+#define Q931_RESUME_REJECT 0x22
+#define Q931_RETRIEVE 0x31
+#define Q931_RETRIEVE_ACK 0x33
+#define Q931_RETRIEVE_REJECT 0x37
+#define Q931_SUSPEND 0x25
+#define Q931_SUSPEND_ACK 0x2D
+#define Q931_SUSPEND_REJECT 0x21
+#define Q931_USER_INFORMATION 0x20
+#define Q931_DISCONNECT 0x45
+#define Q931_RELEASE 0x4D
+#define Q931_RELEASE_COMPLETE 0x5A
+#define Q931_RESTART 0x46
+#define Q931_RESTART_ACK 0x4E
+#define Q931_CONGESTION_CONTROL 0x79
+#define Q931_FACILITY 0x62
+#define Q931_INFORMATION 0x7B
+#define Q931_NOTIFY 0x6E
+#define Q931_REGISTER 0x64
+#define Q931_SEGMENT 0x60
+#define Q931_STATUS 0x7D
+#define Q931_STATUS_ENQUIRY 0x75
+
+static const value_string q931_message_type_vals[] = {
+ { Q931_ESCAPE, "ESCAPE" },
+ { Q931_ALERTING, "ALERTING" },
+ { Q931_CALL_PROCEEDING, "CALL PROCEEDING" },
+ { Q931_CONNECT, "CONNECT" },
+ { Q931_CONNECT_ACK, "CONNECT ACKNOWLEDGE" },
+ { Q931_PROGRESS, "PROGRESS" },
+ { Q931_SETUP, "SETUP" },
+ { Q931_SETUP_ACK, "SETUP ACKNOWLEDGE" },
+ { Q931_HOLD, "HOLD" },
+ { Q931_HOLD_ACK, "HOLD_ACKNOWLEDGE" },
+ { Q931_HOLD_REJECT, "HOLD_REJECT" },
+ { Q931_RESUME, "RESUME" },
+ { Q931_RESUME_ACK, "RESUME ACKNOWLEDGE" },
+ { Q931_RESUME_REJECT, "RESUME REJECT" },
+ { Q931_RETRIEVE, "RETRIEVE" },
+ { Q931_RETRIEVE_ACK, "RETRIEVE ACKNOWLEDGE" },
+ { Q931_RETRIEVE_REJECT, "RETRIEVE REJECT" },
+ { Q931_SUSPEND, "SUSPEND" },
+ { Q931_SUSPEND_ACK, "SUSPEND ACKNOWLEDGE" },
+ { Q931_SUSPEND_REJECT, "SUSPEND REJECT" },
+ { Q931_USER_INFORMATION, "USER INFORMATION" },
+ { Q931_DISCONNECT, "DISCONNECT" },
+ { Q931_RELEASE, "RELEASE" },
+ { Q931_RELEASE_COMPLETE, "RELEASE COMPLETE" },
+ { Q931_RESTART, "RESTART" },
+ { Q931_RESTART_ACK, "RESTART ACKNOWLEDGE" },
+ { Q931_CONGESTION_CONTROL, "CONGESTION CONTROL" },
+ { Q931_FACILITY, "FACILITY" },
+ { Q931_INFORMATION, "INFORMATION" },
+ { Q931_NOTIFY, "NOTIFY" },
+ { Q931_REGISTER, "REGISTER" },
+ { Q931_SEGMENT, "SEGMENT" },
+ { Q931_STATUS, "STATUS" },
+ { Q931_STATUS_ENQUIRY, "STATUS ENQUIRY" },
+ { 0, NULL }
+};
+
+static const true_false_string tfs_call_ref_flag = {
+ "Message sent to originating side",
+ "Message sent from originating side"
+};
+
+/*
+ * Information elements.
+ */
+
+/* Shifted codeset values */
+#define CS0 0x000
+#define CS1 0x100
+#define CS2 0x200
+#define CS3 0x300
+#define CS4 0x400
+#define CS5 0x500
+#define CS6 0x600
+#define CS7 0x700
+
+#define Q931_IE_SO_MASK 0x80 /* single-octet/variable-length mask */
+/*
+ * Single-octet IEs.
+ */
+#define Q931_IE_SO_IDENTIFIER_MASK 0xf0 /* IE identifier mask */
+#define Q931_IE_SO_IDENTIFIER_SHIFT 4 /* IE identifier shift */
+#define Q931_IE_SO_IE_MASK 0x0F /* IE mask */
+
+#define Q931_IE_SHIFT 0x90
+#define Q931_IE_SHIFT_NON_LOCKING 0x08 /* non-locking shift */
+#define Q931_IE_SHIFT_CODESET 0x07 /* codeset */
+
+#define Q931_IE_MORE_DATA_OR_SEND_COMP 0xA0 /* More Data or Sending Complete */
+#define Q931_IE_MORE_DATA 0xA0
+#define Q931_IE_SENDING_COMPLETE 0xA1
+
+#define Q931_IE_CONGESTION_LEVEL 0xB0
+#define Q931_IE_REPEAT_INDICATOR 0xD0
+
+/*
+ * Variable-length IEs.
+ */
+#define Q931_IE_VL_EXTENSION 0x80 /* Extension flag */
+/* extension bit. The bit value "0" indicates that the octet continues through the */
+/* next octet. The bit value "1" indicates that this octet is the last octet */
+
+static const true_false_string q931_extension_ind_value = {
+ "last octet",
+ "information continues through the next octet",
+
+};
+
+
+/*
+ * Codeset 0 (default).
+ */
+#define Q931_IE_SEGMENTED_MESSAGE 0x00
+#define Q931_IE_BEARER_CAPABILITY 0x04
+#define Q931_IE_CAUSE 0x08
+#define Q931_IE_CALL_IDENTITY 0x10
+#define Q931_IE_CALL_STATE 0x14
+#define Q931_IE_CHANNEL_IDENTIFICATION 0x18
+#define Q931_IE_FACILITY 0x1C
+#define Q931_IE_PROGRESS_INDICATOR 0x1E
+#define Q931_IE_NETWORK_SPECIFIC_FACIL 0x20 /* Network Specific Facilities */
+#define Q931_IE_NOTIFICATION_INDICATOR 0x27
+#define Q931_IE_DISPLAY 0x28
+#define Q931_IE_DATE_TIME 0x29
+#define Q931_IE_KEYPAD_FACILITY 0x2C
+#define Q931_IE_INFORMATION_REQUEST 0x32
+#define Q931_IE_SIGNAL 0x34
+#define Q931_IE_SWITCHHOOK 0x36
+#define Q931_IE_FEATURE_ACTIVATION 0x38
+#define Q931_IE_FEATURE_INDICATION 0x39
+#define Q931_IE_ENDPOINT_IDENTIFIER 0x3B
+#define Q931_IE_SERVICE_PROFILE_ID 0x3A
+#define Q931_IE_INFORMATION_RATE 0x40
+#define Q931_IE_E2E_TRANSIT_DELAY 0x42 /* End-to-end Transit Delay */
+#define Q931_IE_TD_SELECTION_AND_INT 0x43 /* Transit Delay Selection and Indication */
+#define Q931_IE_PL_BINARY_PARAMETERS 0x44 /* Packet layer binary parameters */
+#define Q931_IE_PL_WINDOW_SIZE 0x45 /* Packet layer window size */
+#define Q931_IE_PACKET_SIZE 0x46 /* Packet size */
+#define Q931_IE_CUG 0x47 /* Closed user group */
+#define Q931_IE_REVERSE_CHARGE_IND 0x4A /* Reverse charging indication */
+#define Q931_IE_CONNECTED_NUMBER_DEFAULT 0x4C /* Connected Number */
+#define Q931_IE_CALLING_PARTY_NUMBER 0x6C /* Calling Party Number */
+#define Q931_IE_CALLING_PARTY_SUBADDR 0x6D /* Calling Party Subaddress */
+#define Q931_IE_CALLED_PARTY_NUMBER 0x70 /* Called Party Number */
+#define Q931_IE_CALLED_PARTY_SUBADDR 0x71 /* Called Party Subaddress */
+#define Q931_IE_REDIRECTING_NUMBER 0x74
+#define Q931_IE_REDIRECTION_NUMBER 0x76
+#define Q931_IE_TRANSIT_NETWORK_SEL 0x78 /* Transit Network Selection */
+#define Q931_IE_RESTART_INDICATOR 0x79
+#define Q931_IE_LOW_LAYER_COMPAT 0x7C /* Low-Layer Compatibility */
+#define Q931_IE_HIGH_LAYER_COMPAT 0x7D /* High-Layer Compatibility */
+#define Q931_IE_USER_USER 0x7E /* User-User */
+#define Q931_IE_ESCAPE 0x7F /* Escape for extension */
+
+/*
+ * Codeset 0 ETSI.
+ */
+#define Q931_IE_CONNECTED_NUMBER 0x8C
+#define Q931_IE_CONNECTED_SUBADDR 0x8D
+
+/*
+ * Codeset 5 (National-specific) Belgium.
+ */
+#define Q931_IE_CHARGING_ADVICE 0x1A
+
+/*
+ * Codeset 5 (National-specific) Bellcore National ISDN.
+ */
+#define Q931_IE_OPERATOR_SYSTEM_ACCESS 0x1D
+
+/*
+ * Codeset 6 (Network-specific) Belgium.
+ */
+/* 0x1A is Charging Advice, as with Codeset 5 */
+#define Q931_IE_REDIRECTING_NUMBER 0x74
+
+/*
+ * Codeset 6 (Network-specific) FT-Numeris.
+ */
+/* 0x1D is User Capability */
+
+/*
+ * Codeset 6 (Network-specific) Bellcore National ISDN.
+ */
+#define Q931_IE_REDIRECTING_SUBADDR 0x75 /* Redirecting Subaddress */
+/* 0x76 is Redirection Number, but that's also Codeset 0 */
+#define Q931_IE_CALL_APPEARANCE 0x7B
+
+/* Codeset 0 */
+static const value_string q931_info_element_vals0[] = {
+ { Q931_IE_SEGMENTED_MESSAGE, "Segmented message" },
+ { Q931_IE_BEARER_CAPABILITY, "Bearer capability" },
+ { Q931_IE_CAUSE, "Cause" },
+ { Q931_IE_CALL_IDENTITY, "Call identity" },
+ { Q931_IE_CALL_STATE, "Call state" },
+ { Q931_IE_CHANNEL_IDENTIFICATION, "Channel identification" },
+ { Q931_IE_FACILITY, "Facility" },
+ { Q931_IE_PROGRESS_INDICATOR, "Progress indicator" },
+ { Q931_IE_NETWORK_SPECIFIC_FACIL, "Network specific facilities" },
+ { Q931_IE_NOTIFICATION_INDICATOR, "Notification indicator" },
+ { Q931_IE_DISPLAY, "Display" },
+ { Q931_IE_DATE_TIME, "Date/Time" },
+ { Q931_IE_KEYPAD_FACILITY, "Keypad facility" },
+ { Q931_IE_INFORMATION_REQUEST, "Information request" },
+ { Q931_IE_SIGNAL, "Signal" },
+ { Q931_IE_SWITCHHOOK, "Switchhook" },
+ { Q931_IE_FEATURE_ACTIVATION, "Feature activation" },
+ { Q931_IE_FEATURE_INDICATION, "Feature Indication" },
+ { Q931_IE_ENDPOINT_IDENTIFIER, "Endpoint identifier" },
+ { Q931_IE_SERVICE_PROFILE_ID, "Service profile ID" },
+ { Q931_IE_INFORMATION_RATE, "Information rate" },
+ { Q931_IE_E2E_TRANSIT_DELAY, "End-to-end transit delay" },
+ { Q931_IE_TD_SELECTION_AND_INT, "Transit delay selection and indication" },
+ { Q931_IE_PL_BINARY_PARAMETERS, "Packet layer binary parameters" },
+ { Q931_IE_PL_WINDOW_SIZE, "Packet layer window size" },
+ { Q931_IE_PACKET_SIZE, "Packet size" },
+ { Q931_IE_CUG, "Closed user group" },
+ { Q931_IE_REVERSE_CHARGE_IND, "Reverse charging indication" },
+ { Q931_IE_CONNECTED_NUMBER_DEFAULT, "Connected number" },
+ { Q931_IE_CALLING_PARTY_NUMBER, "Calling party number" },
+ { Q931_IE_CALLING_PARTY_SUBADDR, "Calling party subaddress" },
+ { Q931_IE_CALLED_PARTY_NUMBER, "Called party number" },
+ { Q931_IE_CALLED_PARTY_SUBADDR, "Called party subaddress" },
+ { Q931_IE_REDIRECTING_NUMBER, "Redirecting number" },
+ { Q931_IE_REDIRECTION_NUMBER, "Redirection number" },
+ { Q931_IE_TRANSIT_NETWORK_SEL, "Transit network selection" },
+ { Q931_IE_RESTART_INDICATOR, "Restart indicator" },
+ { Q931_IE_LOW_LAYER_COMPAT, "Low-layer compatibility" },
+ { Q931_IE_HIGH_LAYER_COMPAT, "High-layer compatibility" },
+ { Q931_IE_USER_USER, "User-user" },
+ { Q931_IE_ESCAPE, "Escape" },
+ { Q931_IE_CONNECTED_NUMBER, "Connected number" },
+ { Q931_IE_CONNECTED_SUBADDR, "Connected subaddress" },
+ { 0, NULL }
+};
+/* Codeset 1 */
+static const value_string q931_info_element_vals1[] = {
+ { 0, NULL }
+};
+/* Codeset 2 */
+static const value_string q931_info_element_vals2[] = {
+ { 0, NULL }
+};
+/* Codeset 3 */
+static const value_string q931_info_element_vals3[] = {
+ { 0, NULL }
+};
+/* Codeset 4 */
+static const value_string q931_info_element_vals4[] = {
+ { 0, NULL }
+};
+/* Codeset 5 */
+static const value_string q931_info_element_vals5[] = {
+ { Q931_IE_CHARGING_ADVICE, "Charging advice" },
+ { Q931_IE_OPERATOR_SYSTEM_ACCESS, "Operator system access" },
+ { 0, NULL }
+};
+/* Codeset 6 */
+static const value_string q931_info_element_vals6[] = {
+ { Q931_IE_REDIRECTING_NUMBER, "Redirecting number" },
+ { Q931_IE_REDIRECTING_SUBADDR, "Redirecting subaddress" },
+ { Q931_IE_CALL_APPEARANCE, "Call appearance" },
+ { 0, NULL }
+};
+/* Codeset 7 */
+static const value_string q931_info_element_vals7[] = {
+ { 0, NULL }
+};
+
+/* Codeset array */
+#define NUM_INFO_ELEMENT_VALS (Q931_IE_SHIFT_CODESET+1)
+static const value_string *q931_info_element_vals[NUM_INFO_ELEMENT_VALS] = {
+ q931_info_element_vals0,
+ q931_info_element_vals1,
+ q931_info_element_vals2,
+ q931_info_element_vals3,
+ q931_info_element_vals4,
+ q931_info_element_vals5,
+ q931_info_element_vals6,
+ q931_info_element_vals7,
+};
+
+static const value_string q931_congestion_level_vals[] = {
+ { 0x0, "Receiver ready" },
+ { 0xF, "Receiver not ready" },
+ { 0, NULL }
+};
+
+static const value_string q931_repeat_indication_vals[] = {
+ { 0x2, "Prioritized list" },
+ { 0, NULL }
+};
+
+/*
+ * ITU-standardized coding.
+ */
+#define Q931_ITU_STANDARDIZED_CODING 0x00
+
+/*
+ * Dissect a Segmented message information element.
+ */
+static void
+dissect_q931_segmented_message_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len != 2) {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Segmented message: length is %d, should be 2", len);
+ return;
+ }
+ if (tvb_get_guint8(tvb, offset) & 0x80) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "First segment: %u segments remaining",
+ tvb_get_guint8(tvb, offset) & 0x7F);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Not first segment: %u segments remaining",
+ tvb_get_guint8(tvb, offset) & 0x7F);
+ }
+ proto_tree_add_item(tree, hf_q931_segment_type, tvb, offset + 1, 1, FALSE);
+}
+
+/*
+ * Dissect a Bearer capability or Low-layer compatibility information element.
+ */
+static const value_string q931_coding_standard_vals[] = {
+ { 0x0, "ITU-T standardized coding" },
+ { 0x1, "ISO/IEC standard" },
+ { 0x2, "National standard" },
+ { 0x3, "Standard defined for this particular network" },
+ { 0, NULL }
+};
+
+static const value_string q931_information_transfer_capability_vals[] = {
+ { 0x00, "Speech" },
+ { 0x08, "Unrestricted digital information" },
+ { 0x09, "Restricted digital information" },
+ { 0x10, "3.1 kHz audio" },
+ { 0x11, "Unrestricted digital information with tones/announcements" },
+ { 0x18, "Video" },
+ { 0, NULL }
+};
+
+static const value_string q931_transfer_mode_vals[] = {
+ { 0x00, "Circuit mode" },
+ { 0x02, "Packet mode" },
+ { 0, NULL }
+};
+
+#define Q931_IT_RATE_MULTIRATE 0x18
+
+static const value_string q931_information_transfer_rate_vals[] = {
+ { 0x00, "Packet mode" },
+ { 0x10, "64 kbit/s" },
+ { 0x11, "2 x 64 kbit/s" },
+ { 0x13, "384 kbit/s" },
+ { 0x15, "1536 kbit/s" },
+ { 0x17, "1920 kbit/s" },
+ { Q931_IT_RATE_MULTIRATE, "Multirate (64 kbit/s base rate)" },
+ { 0, NULL }
+};
+
+static const value_string q931_uil1_vals[] = {
+ { 0x01, "V.110/I.460/X.30 rate adaption" },
+ { 0x02, "Recommendation G.711 u-law" },
+ { 0x03, "Recommendation G.711 A-law" },
+ { 0x04, "Recommendation G.721 32 kbit/s ADPCM and Recommendation I.460" },
+ { 0x05, "Recommendation H.221 and H.242" },
+ { 0x06, "Recommendation H.223 and H.245" },
+ { 0x07, "Non-ITU-T-standardized rate adaption" },
+ { 0x08, "V.120 rate adaption" },
+ { 0x09, "X.31 HDLC flag stuffing" },
+ { 0, NULL },
+};
+
+static const value_string q931_l1_user_rate_vals[] = {
+ { 0x00, "Rate indicated by E-bits" },
+ { 0x01, "0.6 kbit/s" },
+ { 0x02, "1.2 kbit/s" },
+ { 0x03, "2.4 kbit/s" },
+ { 0x04, "3.6 kbit/s" },
+ { 0x05, "4.8 kbit/s" },
+ { 0x06, "7.2 kbit/s" },
+ { 0x07, "8 kbit/s" },
+ { 0x08, "9.6 kbit/s" },
+ { 0x09, "14.4 kbit/s" },
+ { 0x0A, "16 kbit/s" },
+ { 0x0B, "19.2 kbit/s" },
+ { 0x0C, "32 kbit/s" },
+ { 0x0E, "48 kbit/s" },
+ { 0x0F, "56 kbit/s" },
+ { 0x10, "64 kbit/s "},
+ { 0x15, "0.1345 kbit/s" },
+ { 0x16, "0.100 kbit/s" },
+ { 0x17, "0.075/1.2 kbit/s" },
+ { 0x18, "1.2/0.075 kbit/s" },
+ { 0x19, "0.050 kbit/s" },
+ { 0x1A, "0.075 kbit/s" },
+ { 0x1B, "0.110 kbit/s" },
+ { 0x1C, "0.150 kbit/s" },
+ { 0x1D, "0.200 kbit/s" },
+ { 0x1E, "0.300 kbit/s" },
+ { 0x1F, "12 kbit/s" },
+ { 0, NULL }
+};
+
+static const value_string q931_l1_intermediate_rate_vals[] = {
+ { 0x20, "8 kbit/s" },
+ { 0x40, "16 kbit/s" },
+ { 0x60, "32 kbit/s" },
+ { 0, NULL }
+};
+
+static const value_string q931_l1_stop_bits_vals[] = {
+ { 0x20, "1" },
+ { 0x40, "1.5" },
+ { 0x60, "2" },
+ { 0, NULL }
+};
+
+static const value_string q931_l1_data_bits_vals[] = {
+ { 0x08, "5" },
+ { 0x10, "7" },
+ { 0x18, "8" },
+ { 0, NULL }
+};
+
+static const value_string q931_l1_parity_vals[] = {
+ { 0x00, "Odd" },
+ { 0x02, "Even" },
+ { 0x03, "None" },
+ { 0x04, "Forced to 0" },
+ { 0x05, "Forced to 1" },
+ { 0, NULL }
+};
+
+static const value_string q931_l1_modem_type_vals[] = {
+ { 0x11, "V.21" },
+ { 0x12, "V.22" },
+ { 0x13, "V.22 bis" },
+ { 0x14, "V.23" },
+ { 0x15, "V.26" },
+ { 0x16, "V.26 bis" },
+ { 0x17, "V.26 ter" },
+ { 0x18, "V.27" },
+ { 0x19, "V.27 bis" },
+ { 0x1A, "V.27 ter" },
+ { 0x1B, "V.29" },
+ { 0x1C, "V.32" },
+ { 0x1E, "V.34" },
+ { 0, NULL }
+};
+
+#define Q931_UIL2_USER_SPEC 0x10
+
+static const value_string q931_uil2_vals[] = {
+ { 0x01, "Basic mode ISO 1745" },
+ { 0x02, "Q.921/I.441" }, /* LAPD */
+ { 0x06, "X.25, link layer" }, /* LAPB */
+ { 0x07, "X.25 multilink" }, /* or 0x0F? */
+ { 0x08, "T.71 Extended LAPB" },
+ { 0x09, "HDLC ARM" },
+ { 0x0A, "HDLC NRM" },
+ { 0x0B, "HDLC ABM" },
+ { 0x0C, "ISO 8802/2 LLC" },
+ { 0x0D, "X.75 Single Link Procedure" },
+ { 0x0E, "Q.922" },
+ { 0x0F, "Core aspects of Q.922" },
+ { Q931_UIL2_USER_SPEC, "User-specified" },
+ { 0x11, "ISO 7776 DTE-DTE operation" },
+ { 0, NULL }
+};
+
+static const value_string q931_mode_vals[] = {
+ { 0x20, "Normal mode" },
+ { 0x40, "Extended mode" },
+ { 0, NULL }
+};
+
+#define Q931_UIL3_X25_PL 0x06
+#define Q931_UIL3_ISO_8208 0x07 /* X.25-based */
+#define Q931_UIL3_X223 0x08 /* X.25-based */
+#define Q931_UIL3_TR_9577 0x0B
+#define Q931_UIL3_USER_SPEC 0x10
+
+static const value_string q931_uil3_vals[] = {
+ { 0x02, "Q.931/I.451" },
+ { Q931_UIL3_X25_PL, "X.25, packet layer" },
+ { Q931_UIL3_ISO_8208, "ISO/IEC 8208" },
+ { Q931_UIL3_X223, "X.223/ISO 8878" },
+ { 0x09, "ISO/IEC 8473" },
+ { 0x0A, "T.70" },
+ { Q931_UIL3_TR_9577, "ISO/IEC TR 9577" },
+ { Q931_UIL3_USER_SPEC, "User-specified" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_protocol_discriminator(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ unsigned int discriminator = tvb_get_guint8(tvb, offset);
+
+ if (discriminator == NLPID_Q_931) {
+ proto_tree_add_uint_format(tree, hf_q931_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Q.931");
+ } else if (discriminator == NLPID_Q_2931) {
+ proto_tree_add_uint_format(tree, hf_q931_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Q.2931");
+ } else if ((discriminator >= 16 && discriminator < 63)
+ || ((discriminator >= 80) && (discriminator < 254))) {
+ proto_tree_add_uint_format(tree, hf_q931_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Network layer or layer 3 protocol (0x%02X)",
+ discriminator);
+ } else if (discriminator >= 64 && discriminator <= 79) {
+ proto_tree_add_uint_format(tree, hf_q931_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: National use (0x%02X)",
+ discriminator);
+ } else {
+ proto_tree_add_uint_format(tree, hf_q931_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Reserved (0x%02X)",
+ discriminator);
+ }
+}
+
+void
+dissect_q931_bearer_capability_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 coding_standard;
+ guint8 it_rate;
+ guint8 modem_type;
+ guint8 uil2_protocol;
+ guint8 uil3_protocol;
+ guint8 add_l3_info;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ if (coding_standard != Q931_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the bearer capability is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
+ return;
+ }
+ proto_tree_add_uint(tree, hf_q931_information_transfer_capability, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+
+ /*
+ * XXX - only in Low-layer compatibility information element.
+ */
+ if (!(octet & Q931_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Out-band negotiation %spossible",
+ (octet & 0x40) ? "" : "not ");
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_q931_information_transfer_rate, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q931_transfer_mode, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
+ it_rate = octet & 0x1F;
+ offset += 1;
+ len -= 1;
+
+ if (it_rate == Q931_IT_RATE_MULTIRATE) {
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 1, "Rate multiplier: %u", tvb_get_guint8(tvb, offset));
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0x60) == 0x20) {
+ /*
+ * Layer 1 information.
+ */
+ proto_tree_add_uint(tree, hf_q931_uil1, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l1_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Layer 1 is %s",
+ (octet & 0x40) ? "Asynchronous" : "Synchronous");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Layer 1 in-band negotiation is %spossible",
+ (octet & 0x20) ? "" : "not ");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User rate: %s",
+ val_to_str(octet & 0x1F, q931_l1_user_rate_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l1_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Intermediate rate: %s",
+ val_to_str(octet & 0x60, q931_l1_intermediate_rate_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s to send data with network independent clock",
+ (octet & 0x10) ? "Required" : "Not required");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s accept data with network independent clock",
+ (octet & 0x08) ? "Can" : "Cannot");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s to send data with flow control mechanism",
+ (octet & 0x04) ? "Required" : "Not required");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s accept data with flow control mechanism",
+ (octet & 0x02) ? "Can" : "Cannot");
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l1_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Rate adaption header %sincluded",
+ (octet & 0x40) ? "" : "not ");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Multiple frame establishment %ssupported",
+ (octet & 0x20) ? "" : "not ");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s mode of operation",
+ (octet & 0x10) ? "Protocol sensitive" : "Bit transparent");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ (octet & 0x08) ?
+ "Full protocol negotiation" : "LLI = 256 only");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Message originator is %s",
+ (octet & 0x04) ? "Assignor only" : "Default assignee");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Negotiation is done %s",
+ (octet & 0x02) ? "in-band" : "out-of-band");
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l1_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Stop bits: %s",
+ val_to_str(octet & 0x60, q931_l1_stop_bits_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Data bits: %s",
+ val_to_str(octet & 0x18, q931_l1_data_bits_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Parity: %s",
+ val_to_str(octet & 0x07, q931_l1_parity_vals,
+ "Unknown (0x%X)"));
+
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l1_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s duplex",
+ (octet & 0x40) ? "Full" : "Half");
+ modem_type = octet & 0x3F;
+ if (modem_type <= 0x5 ||
+ (modem_type >= 0x20 && modem_type <= 0x2F)) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Modem type: National use 0x%02X", modem_type);
+ } else if (modem_type >= 0x30) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Modem type: User specified 0x%02X", modem_type);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Modem type: %s",
+ val_to_str(modem_type, q931_l1_modem_type_vals,
+ "Unknown (0x%02X)"));
+ }
+ offset += 1;
+ len -= 1;
+ }
+l1_done:
+ ;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0x60) == 0x40) {
+ /*
+ * Layer 2 information.
+ */
+ uil2_protocol = octet & 0x1F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User information layer 2 protocol: %s",
+ val_to_str(uil2_protocol, q931_uil2_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ /*
+ * XXX - only in Low-layer compatibility information element.
+ */
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l2_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if (uil2_protocol == Q931_UIL2_USER_SPEC) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User-specified layer 2 protocol information: 0x%02X",
+ octet & 0x7F);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Mode: %s",
+ val_to_str(octet & 0x60, q931_mode_vals,
+ "Unknown (0x%02X)"));
+ }
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l2_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Window size: %u k", octet & 0x7F);
+ offset += 1;
+ len -= 1;
+ }
+l2_done:
+ ;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0x60) == 0x60) {
+ /*
+ * Layer 3 information.
+ */
+ uil3_protocol = octet & 0x1F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User information layer 3 protocol: %s",
+ val_to_str(uil3_protocol, q931_uil3_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+
+ /*
+ * XXX - only in Low-layer compatibility information element.
+ */
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ switch (uil3_protocol) {
+
+ case Q931_UIL3_X25_PL:
+ case Q931_UIL3_ISO_8208:
+ case Q931_UIL3_X223:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Mode: %s",
+ val_to_str(octet & 0x60, q931_mode_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Default packet size: %u", octet & 0x0F);
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Packet window size: %u", octet & 0x7F);
+ offset += 1;
+ len -= 1;
+ break;
+
+ case Q931_UIL3_USER_SPEC:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Default packet size: %u octets",
+ 1 << (octet & 0x0F));
+ offset += 1;
+ len -= 1;
+ break;
+
+ case Q931_UIL3_TR_9577:
+ add_l3_info = (octet & 0x0F) << 4;
+ if (octet & Q931_IE_VL_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset + 1);
+ add_l3_info |= (octet & 0x0F);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Additional layer 3 protocol information: %s",
+ val_to_str(add_l3_info, nlpid_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ break;
+ }
+ }
+l3_done:
+ ;
+}
+
+/*
+ * Dissect a Cause information element.
+ */
+
+
+const value_string q931_cause_location_vals[] = {
+ { 0x00, "User (U)" },
+ { 0x01, "Private network serving the local user (LPN)" },
+ { 0x02, "Public network serving the local user (LN)" },
+ { 0x03, "Transit network (TN)" },
+ { 0x04, "Public network serving the remote user (RLN)" },
+ { 0x05, "Private network serving the remote user (RPN)" },
+ { 0x07, "International network (INTL)" },
+ { 0x0A, "Network beyond interworking point (BI)" },
+ { 0, NULL }
+};
+
+static const value_string q931_cause_recommendation_vals[] = {
+ { 0x00, "Q.931" },
+ { 0x03, "X.21" },
+ { 0x04, "X.25" },
+ { 0x05, "Q.1031/Q.1051" },
+ { 0, NULL }
+};
+
+/*
+ * Cause codes for Cause.
+ */
+#define Q931_CAUSE_UNALLOC_NUMBER 0x01
+#define Q931_CAUSE_NO_ROUTE_TO_DEST 0x03
+#define Q931_CAUSE_CALL_REJECTED 0x15
+#define Q931_CAUSE_NUMBER_CHANGED 0x16
+#define Q931_CAUSE_ACCESS_INFO_DISC 0x2B
+#define Q931_CAUSE_QOS_UNAVAILABLE 0x31
+#define Q931_CAUSE_CHAN_NONEXISTENT 0x52
+#define Q931_CAUSE_INCOMPATIBLE_DEST 0x58
+#define Q931_CAUSE_MAND_IE_MISSING 0x60
+#define Q931_CAUSE_MT_NONEX_OR_UNIMPL 0x61
+#define Q931_CAUSE_IE_NONEX_OR_UNIMPL 0x63
+#define Q931_CAUSE_INVALID_IE_CONTENTS 0x64
+#define Q931_CAUSE_MSG_INCOMPAT_W_CS 0x65
+#define Q931_CAUSE_REC_TIMER_EXP 0x66
+
+const value_string q931_cause_code_vals[] = {
+ { 0x00, "Valid cause code not yet received" },
+ { Q931_CAUSE_UNALLOC_NUMBER, "Unallocated (unassigned) number" },
+ { 0x02, "No route to specified transit network" },
+ { Q931_CAUSE_NO_ROUTE_TO_DEST, "No route to destination" },
+ { 0x04, "Send special information tone" },
+ { 0x05, "Misdialled trunk prefix" },
+ { 0x06, "Channel unacceptable" },
+ { 0x07, "Call awarded and being delivered in an established channel" },
+ { 0x08, "Prefix 0 dialed but not allowed" },
+ /* Q.850 - "Preemption" */
+ { 0x09, "Prefix 1 dialed but not allowed" },
+ /* Q.850 - "Preemption - circuit reserved for reuse" */
+ { 0x0A, "Prefix 1 dialed but not required" },
+ { 0x0B, "More digits received than allowed, call is proceeding" },
+ { 0x0E, "QoR: ported number" },
+ { 0x10, "Normal call clearing" },
+ { 0x11, "User busy" },
+ { 0x12, "No user responding" },
+ { 0x13, "No answer from user (user alerted)" },
+ { 0x14, "Subscriber absent" },
+ { Q931_CAUSE_CALL_REJECTED, "Call rejected" },
+ { Q931_CAUSE_NUMBER_CHANGED, "Number changed" },
+ { 0x17, "Reverse charging rejected" },
+ /* Q.850 - "Redirection to new destination" */
+ { 0x18, "Call suspended" },
+ /* Q.850 Amendment 1 - "Call rejected due to feature at the destination" */
+ { 0x19, "Call resumed" },
+ /* Q.850 - "Exchange routing error */
+ { 0x1A, "Non-selected user clearing" },
+ { 0x1B, "Destination out of order" },
+ { 0x1C, "Invalid number format (incomplete number)" },
+ { 0x1D, "Facility rejected" },
+ { 0x1E, "Response to STATUS ENQUIRY" },
+ { 0x1F, "Normal unspecified" },
+ { 0x21, "Circuit out of order" },
+ { 0x22, "No circuit/channel available" },
+ { 0x23, "Destination unattainable" },
+ { 0x25, "Degraded service" },
+ { 0x26, "Network out of order" },
+ { 0x27, "Transit delay range cannot be achieved" },
+ /* Q.850 - "Permanent frame mode connection out of service" */
+ { 0x28, "Throughput range cannot be achieved" },
+ /* Q.850 - "Permanent frame mode connection operational" */
+ { 0x29, "Temporary failure" },
+ { 0x2A, "Switching equipment congestion" },
+ { Q931_CAUSE_ACCESS_INFO_DISC, "Access information discarded" },
+ { 0x2C, "Requested circuit/channel not available" },
+ { 0x2D, "Pre-empted" },
+ { 0x2E, "Precedence call blocked" },
+ { 0x2F, "Resources unavailable, unspecified" },
+ { Q931_CAUSE_QOS_UNAVAILABLE, "Quality of service unavailable" },
+ { 0x32, "Requested facility not subscribed" },
+ { 0x33, "Reverse charging not allowed" },
+ { 0x34, "Outgoing calls barred" },
+ { 0x35, "Outgoing calls barred within CUG" },
+ { 0x36, "Incoming calls barred" },
+ { 0x37, "Incoming calls barred within CUG" },
+ { 0x38, "Call waiting not subscribed" },
+ { 0x39, "Bearer capability not authorized" },
+ { 0x3A, "Bearer capability not presently available" },
+ { 0x3E, "Inconsistency in designated outgoing access information and subscriber class" },
+ { 0x3F, "Service or option not available, unspecified" },
+ { 0x41, "Bearer capability not implemented" },
+ { 0x42, "Channel type not implemented" },
+ { 0x43, "Transit network selection not implemented" },
+ { 0x44, "Message not implemented" },
+ { 0x45, "Requested facility not implemented" },
+ { 0x46, "Only restricted digital information bearer capability is available" },
+ { 0x4F, "Service or option not implemented, unspecified" },
+ { 0x51, "Invalid call reference value" },
+ { Q931_CAUSE_CHAN_NONEXISTENT, "Identified channel does not exist" },
+ { 0x53, "Call identity does not exist for suspended call" },
+ { 0x54, "Call identity in use" },
+ { 0x55, "No call suspended" },
+ { 0x56, "Call having the requested call identity has been cleared" },
+ { 0x57, "Called user not member of CUG" },
+ { Q931_CAUSE_INCOMPATIBLE_DEST, "Incompatible destination" },
+ { 0x59, "Non-existent abbreviated address entry" },
+ { 0x5A, "Destination address missing, and direct call not subscribed" },
+ /* Q.850 - "Non-existent CUG" */
+ { 0x5B, "Invalid transit network selection (national use)" },
+ { 0x5C, "Invalid facility parameter" },
+ { 0x5D, "Mandatory information element is missing" },
+ { 0x5F, "Invalid message, unspecified" },
+ { Q931_CAUSE_MAND_IE_MISSING, "Mandatory information element is missing" },
+ { Q931_CAUSE_MT_NONEX_OR_UNIMPL,"Message type non-existent or not implemented" },
+ { 0x62, "Message not compatible with call state or message type non-existent or not implemented" },
+ { Q931_CAUSE_IE_NONEX_OR_UNIMPL,"Information element nonexistant or not implemented" },
+ { Q931_CAUSE_INVALID_IE_CONTENTS,"Invalid information element contents" },
+ { Q931_CAUSE_MSG_INCOMPAT_W_CS, "Message not compatible with call state" },
+ { Q931_CAUSE_REC_TIMER_EXP, "Recovery on timer expiry" },
+ { 0x67, "Parameter non-existent or not implemented - passed on" },
+ { 0x6E, "Message with unrecognized parameter discarded" },
+ { 0x6F, "Protocol error, unspecified" },
+ { 0x7F, "Internetworking, unspecified" },
+ { 0, NULL }
+};
+
+static const value_string q931_cause_condition_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Permanent" },
+ { 0x02, "Transient" },
+ { 0x00, NULL }
+};
+
+#define Q931_REJ_USER_SPECIFIC 0x00
+#define Q931_REJ_IE_MISSING 0x04
+#define Q931_REJ_IE_INSUFFICIENT 0x08
+
+static const value_string q931_rejection_reason_vals[] = {
+ { 0x00, "User specific" },
+ { 0x04, "Information element missing" },
+ { 0x08, "Information element contents are not sufficient" },
+ { 0x00, NULL }
+};
+
+void
+dissect_q931_cause_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, int hf_cause_value)
+{
+ guint8 octet;
+ guint8 cause_value;
+ guint8 coding_standard;
+ guint8 rejection_reason;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ if (coding_standard != Q931_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the cause is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ proto_tree_add_uint(tree, hf_q931_cause_location, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+
+ if (!(octet & Q931_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Recommendation: %s",
+ val_to_str(octet & 0x7F, q931_cause_recommendation_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ cause_value = octet & 0x7F;
+ proto_tree_add_uint(tree, hf_cause_value, tvb, offset, 1, cause_value);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (cause_value) {
+
+ case Q931_CAUSE_UNALLOC_NUMBER:
+ case Q931_CAUSE_NO_ROUTE_TO_DEST:
+ case Q931_CAUSE_QOS_UNAVAILABLE:
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Network service: %s",
+ (octet & 0x80) ? "User" : "Provider");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s",
+ (octet & 0x40) ? "Abnormal" : "Normal");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Condition: %s",
+ val_to_str(octet & 0x03, q931_cause_condition_vals,
+ "Unknown (0x%X)"));
+ break;
+
+ case Q931_CAUSE_CALL_REJECTED:
+ rejection_reason = octet & 0x7C;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Rejection reason: %s",
+ val_to_str(octet & 0x7C, q931_rejection_reason_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Condition: %s",
+ val_to_str(octet & 0x03, q931_cause_condition_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (rejection_reason) {
+
+ case Q931_REJ_USER_SPECIFIC:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "User specific diagnostic: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+
+ case Q931_REJ_IE_MISSING:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q931_info_element_vals0,
+ "Unknown (0x%02X)"));
+ break;
+
+ case Q931_REJ_IE_INSUFFICIENT:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Insufficient information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q931_info_element_vals0,
+ "Unknown (0x%02X)"));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Diagnostic: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+ }
+ break;
+
+ case Q931_CAUSE_ACCESS_INFO_DISC:
+ case Q931_CAUSE_INCOMPATIBLE_DEST:
+ case Q931_CAUSE_MAND_IE_MISSING:
+ case Q931_CAUSE_IE_NONEX_OR_UNIMPL:
+ case Q931_CAUSE_INVALID_IE_CONTENTS:
+ do {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q931_info_element_vals0,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+ } while (len != 0);
+ break;
+
+ case Q931_CAUSE_MT_NONEX_OR_UNIMPL:
+ case Q931_CAUSE_MSG_INCOMPAT_W_CS:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Message type: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q931_message_type_vals,
+ "Unknown (0x%02X)"));
+ break;
+
+ case Q931_CAUSE_REC_TIMER_EXP:
+ if (len < 3)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Timer: %.3s", tvb_get_ptr(tvb, offset, 3));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Diagnostics: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ }
+}
+
+/*
+ * Dissect a Call state information element.
+ */
+static const value_string q931_call_state_vals[] = {
+ { 0x00, "Null" },
+ { 0x01, "Call initiated" },
+ { 0x02, "Overlap sending" },
+ { 0x03, "Outgoing call proceeding" },
+ { 0x04, "Call delivered" },
+ { 0x06, "Call present" },
+ { 0x07, "Call received" },
+ { 0x08, "Connect request" },
+ { 0x09, "Incoming call proceeding" },
+ { 0x0A, "Active" },
+ { 0x0B, "Disconnect request" },
+ { 0x0C, "Disconnect indication" },
+ { 0x0F, "Suspend request" },
+ { 0x12, "Resume request" },
+ { 0x13, "Release request" },
+ { 0x16, "Call abort"},
+ { 0x19, "Overlap receiving" },
+ { 0x3D, "Restart request" },
+ { 0x3E, "Restart" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_call_state_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 coding_standard;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
+ if (coding_standard != Q931_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the call state is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Call state: %s",
+ val_to_str(octet & 0x3F, q931_call_state_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a Channel identification information element.
+ */
+#define Q931_INTERFACE_IDENTIFIED 0x40
+#define Q931_NOT_BASIC_CHANNEL 0x20
+
+static const value_string q931_basic_channel_selection_vals[] = {
+ { 0x00, "No channel" },
+ { 0x01, "B1 channel" },
+ { 0x02, "B2 channel" },
+ { 0x03, "Any channel" },
+ { 0, NULL }
+};
+
+static const value_string q931_not_basic_channel_selection_vals[] = {
+ { 0x00, "No channel" },
+ { 0x01, "Channel indicated in following octets" },
+ { 0x03, "Any channel" },
+ { 0, NULL }
+};
+
+#define Q931_IS_SLOT_MAP 0x10
+
+static const value_string q931_element_type_vals[] = {
+ { 0x03, "B-channel units" },
+ { 0x06, "H0-channel units" },
+ { 0x08, "H11-channel units" },
+ { 0x09, "H12-channel units" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_channel_identification_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ int identifier_offset;
+ int identifier_len;
+ guint8 coding_standard;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Interface %s identified",
+ (octet & Q931_INTERFACE_IDENTIFIED) ? "explicitly" : "implicitly");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s interface",
+ (octet & Q931_NOT_BASIC_CHANNEL) ? "Not basic" : "Basic");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Indicated channel is %s",
+ (octet & 0x08) ? "required" : "preferred");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Indicated channel is %sthe D-channel",
+ (octet & 0x04) ? "" : "not ");
+ if (octet & Q931_NOT_BASIC_CHANNEL) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Channel selection: %s",
+ val_to_str(octet & 0x03, q931_not_basic_channel_selection_vals,
+ "Unknown (0x%X)"));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Channel selection: %s",
+ val_to_str(octet & 0x03, q931_basic_channel_selection_vals,
+ NULL));
+ }
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q931_INTERFACE_IDENTIFIED) {
+ identifier_offset = offset;
+ identifier_len = 0;
+ do {
+ if (len == 0)
+ break;
+ octet = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ len -= 1;
+ identifier_len++;
+ } while (!(octet & Q931_IE_VL_EXTENSION));
+
+ /*
+ * XXX - do we want to strip off the 8th bit on the
+ * last octet of the interface identifier?
+ */
+ if (identifier_len != 0) {
+ proto_tree_add_text(tree, tvb, identifier_offset,
+ identifier_len, "Interface identifier: %s",
+ bytes_to_str(
+ tvb_get_ptr(tvb, identifier_offset, identifier_len),
+ identifier_len));
+ }
+ }
+
+ if (octet & Q931_NOT_BASIC_CHANNEL) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
+ if (coding_standard != Q931_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the channel identifier is
+ * encoded, so just dump it as data and be done
+ * with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Channel is indicated by %s",
+ (octet & Q931_IS_SLOT_MAP) ? "slot map" : "number");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s type: %s",
+ (octet & Q931_IS_SLOT_MAP) ? "Map element" : "Channel",
+ val_to_str(octet & 0x0F, q931_element_type_vals,
+ "Unknown (0x%02X)"));
+
+ /*
+ * XXX - dump the channel number or slot map.
+ */
+ }
+}
+
+/*
+ * Dissect a Progress indicator information element.
+ */
+static const value_string q931_progress_description_vals[] = {
+ { 0x01, "Call is not end-to-end ISDN - progress information available in-band" },
+ { 0x02, "Destination address is non-ISDN" },
+ { 0x03, "Origination address is non-ISDN" },
+ { 0x04, "Call has returned to the ISDN" },
+ { 0x05, "Interworking has occurred and has resulted in a telecommunications service change" },
+ { 0x08, "In-band information or an appropriate pattern is now available" },
+ { 0, NULL }
+};
+
+void
+dissect_q931_progress_indicator_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 coding_standard;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
+ if (coding_standard != Q931_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the progress indicator is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Location: %s",
+ val_to_str(octet & 0x0F, q931_cause_location_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Progress description: %s",
+ val_to_str(octet & 0x7F, q931_progress_description_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a Network-specific facilities or Transit network selection
+ * information element.
+ */
+static const value_string q931_netid_type_vals[] = {
+ { 0x00, "User specified" },
+ { 0x20, "National network identification" },
+ { 0x30, "International network identification" },
+ { 0, NULL }
+};
+
+static const value_string q931_netid_plan_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Carrier Identification Code" },
+ { 0x03, "X.121 data network identification code" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_ns_facilities_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ int netid_len;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ netid_len = octet & 0x7F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Network identification length: %u",
+ netid_len);
+ offset += 1;
+ len -= 1;
+ if (netid_len != 0) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Type of network identification: %s",
+ val_to_str(octet & 0x70, q931_netid_type_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Network identification plan: %s",
+ val_to_str(octet & 0x0F, q931_netid_plan_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+ netid_len--;
+
+ if (len == 0)
+ return;
+ if (netid_len > len)
+ netid_len = len;
+ if (netid_len != 0) {
+ proto_tree_add_text(tree, tvb, offset, netid_len,
+ "Network identification: %s",
+ tvb_format_text(tvb, offset, netid_len));
+ offset += netid_len;
+ len -= netid_len;
+ }
+ }
+
+ /*
+ * Whatever is left is the network-specific facility
+ * specification.
+ */
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Network-specific facility specification: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+}
+
+/*
+ * Dissect a Notification indicator information element.
+ */
+static const value_string q931_notification_description_vals[] = {
+ { 0x00, "User suspended" },
+ { 0x01, "User resumed" },
+ { 0x02, "Bearer service change" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_notification_indicator_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Notification description: %s",
+ val_to_str(octet & 0x7F, q931_notification_description_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a Date/time information element.
+ */
+static void
+dissect_q931_date_time_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len == 6) {
+ /*
+ * XXX - what is "year" relative to? Is "month" 0-origin or
+ * 1-origin? Q.931 doesn't say....
+ */
+ proto_tree_add_text(tree, tvb, offset, 6,
+ "Date/time: %02u-%02u-%02u %02u:%02u:%02u",
+ tvb_get_guint8(tvb, offset + 0), tvb_get_guint8(tvb, offset + 1), tvb_get_guint8(tvb, offset + 2),
+ tvb_get_guint8(tvb, offset + 3), tvb_get_guint8(tvb, offset + 4), tvb_get_guint8(tvb, offset + 5));
+ } else if (len == 5) {
+ proto_tree_add_text(tree, tvb, offset, 5,
+ "Date/time: %02u-%02u-%02u %02u:%02u:00",
+ tvb_get_guint8(tvb, offset + 0), tvb_get_guint8(tvb, offset + 1), tvb_get_guint8(tvb, offset + 2),
+ tvb_get_guint8(tvb, offset + 3), tvb_get_guint8(tvb, offset + 4));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Date/time: length is %d, should be 5 or 6", len);
+ }
+}
+
+/*
+ * Dissect a Signal information element.
+ */
+static const value_string q931_signal_vals[] = {
+ { 0x00, "Dial tone on" },
+ { 0x01, "Ring tone on" },
+ { 0x02, "Intercept tone on" },
+ { 0x03, "Network congestion tone on" }, /* "fast busy" */
+ { 0x04, "Busy tone on" },
+ { 0x05, "Confirm tone on" },
+ { 0x06, "Answer tone on" },
+ { 0x07, "Call waiting tone on" },
+ { 0x08, "Off-hook warning tone on" },
+ { 0x09, "Preemption tone on" },
+ { 0x3F, "Tones off" },
+ { 0x40, "Alerting on - pattern 0" },
+ { 0x41, "Alerting on - pattern 1" },
+ { 0x42, "Alerting on - pattern 2" },
+ { 0x43, "Alerting on - pattern 3" },
+ { 0x44, "Alerting on - pattern 4" },
+ { 0x45, "Alerting on - pattern 5" },
+ { 0x46, "Alerting on - pattern 6" },
+ { 0x47, "Alerting on - pattern 7" },
+ { 0x4F, "Alerting off" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_signal_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len != 1) {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Signal: length is %d, should be 1", len);
+ return;
+ }
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Signal: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q931_signal_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect an Information rate information element.
+ */
+static const value_string q931_throughput_class_vals[] = {
+ { 0x03, "75 bit/s" },
+ { 0x04, "150 bit/s" },
+ { 0x05, "300 bit/s" },
+ { 0x06, "600 bit/s" },
+ { 0x07, "1200 bit/s" },
+ { 0x08, "2400 bit/s" },
+ { 0x09, "4800 bit/s" },
+ { 0x0A, "9600 bit/s" },
+ { 0x0B, "19200 bit/s" },
+ { 0x0C, "48000 bit/s" },
+ { 0x0D, "64000 bit/s" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_information_rate_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len != 4) {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Information rate: length is %d, should be 4", len);
+ return;
+ }
+ proto_tree_add_text(tree, tvb, offset + 0, 1,
+ "Incoming information rate: %s",
+ val_to_str(tvb_get_guint8(tvb, offset + 0) & 0x1F,
+ q931_throughput_class_vals, "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
+ "Outgoing information rate: %s",
+ val_to_str(tvb_get_guint8(tvb, offset + 1) & 0x1F,
+ q931_throughput_class_vals, "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset + 2, 1,
+ "Minimum incoming information rate: %s",
+ val_to_str(tvb_get_guint8(tvb, offset + 2) & 0x1F,
+ q931_throughput_class_vals, "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset + 3, 1,
+ "Minimum outgoing information rate: %s",
+ val_to_str(tvb_get_guint8(tvb, offset + 3) & 0x1F,
+ q931_throughput_class_vals, "Unknown (0x%02X)"));
+}
+
+static int
+dissect_q931_guint16_value(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, char *label)
+{
+ guint8 octet;
+ guint16 value;
+ int value_len;
+
+ value_len = 0;
+
+ octet = tvb_get_guint8(tvb, offset);
+ if (octet & Q931_IE_VL_EXTENSION) {
+ /*
+ * Only one octet long - error.
+ */
+ goto bad_length;
+ }
+ value = (octet & 0x3) << 14;
+ offset += 1;
+ len -= 1;
+ value_len++;
+
+ if (len == 0) {
+ /*
+ * We've reached the end of the information element - error.
+ */
+ goto past_end;
+ }
+ octet = tvb_get_guint8(tvb, offset);
+ if (octet & Q931_IE_VL_EXTENSION) {
+ /*
+ * Only two octets long - error.
+ */
+ goto bad_length;
+ }
+ value |= (octet & 0x7F) << 7;
+ offset += 1;
+ len -= 1;
+ value_len++;
+
+ if (len == 0) {
+ /*
+ * We've reached the end of the information element - error.
+ */
+ goto past_end;
+ }
+ octet = tvb_get_guint8(tvb, offset);
+ if (!(octet & Q931_IE_VL_EXTENSION)) {
+ /*
+ * More than three octets long - error.
+ */
+ goto bad_length;
+ }
+ value |= (octet & 0x7F);
+ offset += 1;
+ len -= 1;
+ value_len++;
+
+ proto_tree_add_text(tree, tvb, offset, value_len, "%s: %u ms", label,
+ value);
+ return value_len;
+
+past_end:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "%s goes past end of information element", label);
+ return -1;
+
+bad_length:
+ proto_tree_add_text(tree, tvb, offset, len, "%s isn't 3 octets long",
+ label);
+ return -1;
+}
+
+/*
+ * Dissect an End-to-end transit delay information element.
+ */
+static void
+dissect_q931_e2e_transit_delay_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ int value_len;
+
+ if (len == 0)
+ return;
+ value_len = dissect_q931_guint16_value(tvb, offset, len, tree,
+ "Cumulative transit delay");
+ if (value_len < 0)
+ return; /* error */
+ offset += value_len;
+ len -= value_len;
+
+ if (len == 0)
+ return;
+ value_len = dissect_q931_guint16_value(tvb, offset, len, tree,
+ "Requested end-to-end transit delay");
+ if (value_len < 0)
+ return; /* error */
+ offset += value_len;
+ len -= value_len;
+
+ if (len == 0)
+ return;
+ value_len = dissect_q931_guint16_value(tvb, offset, len, tree,
+ "Maximum end-to-end transit delay");
+}
+
+/*
+ * Dissect a Transit delay selection and indication information element.
+ */
+static void
+dissect_q931_td_selection_and_int_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len == 0)
+ return;
+ dissect_q931_guint16_value(tvb, offset, len, tree,
+ "Transit delay");
+}
+
+/*
+ * Dissect a Packet layer binary parameters information element.
+ */
+static const value_string q931_fast_selected_vals[] = {
+ { 0x00, "Fast select not requested" },
+ { 0x08, "Fast select not requested" },
+ { 0x10, "Fast select requested with no restriction of response" },
+ { 0x18, "Fast select requested with restrictions of response" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_q931_pl_binary_parameters_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Fast select: %s",
+ val_to_str(octet & 0x18, q931_fast_selected_vals, NULL));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s",
+ (octet & 0x04) ? "No request/request denied" :
+ "Request indicated/request accepted");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s confirmation",
+ (octet & 0x02) ? "Link-by-link" : "End-to-end");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Modulus %u sequencing",
+ (octet & 0x01) ? 8 : 128);
+}
+
+/*
+ * Dissect a Packet layer window size information element.
+ */
+static void
+dissect_q931_pl_window_size_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Forward value: %u", tvb_get_guint8(tvb, offset) & 0x7F);
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Backward value: %u", tvb_get_guint8(tvb, offset) & 0x7F);
+}
+
+/*
+ * Dissect a Packet size information element.
+ */
+static void
+dissect_q931_packet_size_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Forward value: %u", tvb_get_guint8(tvb, offset) & 0x7F);
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Backward value: %u", tvb_get_guint8(tvb, offset) & 0x7F);
+}
+
+/*
+ * Dissect a Closed user group information element.
+ */
+static const value_string q931_cug_indication_vals[] = {
+ { 0x01, "Closed user group selection" },
+ { 0x02, "Closed user group with outgoing access selection and indication" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_cug_ie(tvbuff_t *tvb, int offset, int len, proto_tree *tree)
+{
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "CUG indication: %s",
+ val_to_str(tvb_get_guint8(tvb, offset) & 0x07,
+ q931_cug_indication_vals, "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, len, "CUG index code: %s",
+ tvb_format_text(tvb, offset, len));
+}
+
+/*
+ * Dissect a Reverse charging indication information element.
+ */
+static const value_string q931_reverse_charging_indication_vals[] = {
+ { 0x01, "Reverse charging requested" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_reverse_charge_ind_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Reverse charging indication: %s",
+ val_to_str(tvb_get_guint8(tvb, offset) & 0x07,
+ q931_reverse_charging_indication_vals, "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a (phone) number information element.
+ */
+static const value_string q931_number_type_vals[] = {
+ { 0x0, "Unknown" },
+ { 0x1, "International number" },
+ { 0x2, "National number" },
+ { 0x3, "Network specific number" },
+ { 0x4, "Subscriber number" },
+ { 0x6, "Abbreviated number" },
+ { 0, NULL }
+};
+
+static const value_string q931_numbering_plan_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "E.164 ISDN/telephony numbering" },
+ { 0x03, "X.121 data numbering" },
+ { 0x04, "F.69 Telex numbering" },
+ { 0x08, "National standard numbering" },
+ { 0x09, "Private numbering" },
+ { 0, NULL }
+};
+
+static const value_string q931_presentation_indicator_vals[] = {
+ { 0x00, "Presentation allowed" },
+ { 0x01, "Presentation restricted" },
+ { 0x02, "Number not available due to interworking" },
+ { 0, NULL }
+};
+
+static const value_string q931_screening_indicator_vals[] = {
+ { 0x00, "User-provided, not screened" },
+ { 0x01, "User-provided, verified and passed" },
+ { 0x02, "User-provided, verified and failed" },
+ { 0x03, "Network-provided" },
+ { 0, NULL }
+};
+
+static const value_string q931_redirection_reason_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Call forwarding busy or called DTE busy" },
+ { 0x02, "Call forwarding no reply" },
+ { 0x04, "Call deflection" },
+ { 0x09, "Called DTE out of order" },
+ { 0x0A, "Call forwarding by the called DTE" },
+ { 0x0F, "Call forwarding unconditional or systematic call redirection" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_number_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, int hfindex, e164_info_t e164_info)
+{
+ guint8 octet;
+ gint number_plan;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ number_plan = octet & 0x0f;
+ e164_info.nature_of_address = ( octet & 0x70 ) >> 4;
+ proto_tree_add_uint(tree, hf_q931_numbering_plan, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q931_number_type, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
+
+ offset += 1;
+ len -= 1;
+
+ if (!(octet & Q931_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_q931_screening_ind, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q931_presentation_ind, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q931_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+ }
+
+ /*
+ * XXX - only in a Redirecting number information element.
+ */
+ if (!(octet & Q931_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Reason for redirection: %s",
+ val_to_str(octet & 0x0F, q931_redirection_reason_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ proto_tree_add_item(tree, hfindex, tvb, offset, len, FALSE);
+ proto_item_append_text(proto_tree_get_parent(tree), ": '%s'", tvb_format_text(tvb, offset, len));
+
+ if ( number_plan == 1 ) {
+ if ( e164_info.e164_number_type != NONE ){
+
+ e164_info.E164_number_str = tvb_get_string(tvb, offset, len);
+ e164_info.E164_number_length = len;
+ dissect_e164_number(tvb, tree, offset, len, e164_info);
+ }
+ }
+
+}
+
+/*
+ * Dissect a party subaddress information element.
+ */
+static const value_string q931_subaddress_type_vals[] = {
+ { 0x00, "X.213/ISO 8348 Add.2 NSAP" },
+ { 0x20, "User-specified" },
+ { 0, NULL }
+};
+
+static const value_string q931_odd_even_indicator_vals[] = {
+ { 0x00, "Even number of address signals" },
+ { 0x10, "Odd number of address signals" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_party_subaddr_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Type of subaddress: %s",
+ val_to_str(octet & 0x70, q931_subaddress_type_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Odd/even indicator: %s",
+ val_to_str(octet & 0x10, q931_odd_even_indicator_vals,
+ NULL));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, len, "Subaddress: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+}
+
+/*
+ * Dissect a Restart indicator information element.
+ */
+static const value_string q931_restart_indicator_class_vals[] = {
+ { 0x00, "Indicated channels" },
+ { 0x06, "Single interface" },
+ { 0x07, "All interfaces" },
+ { 0, NULL }
+};
+
+static void
+dissect_q931_restart_indicator_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len != 1) {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Restart indicator: length is %d, should be 1", len);
+ return;
+ }
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Restart indicator: %s",
+ val_to_str(tvb_get_guint8(tvb, offset) & 0x07,
+ q931_restart_indicator_class_vals, "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a High-layer compatibility information element.
+ */
+#define Q931_AUDIOVISUAL 0x60
+static const value_string q931_high_layer_characteristics_vals[] = {
+ { 0x01, "Telephony" },
+ { 0x04, "F.182 Facsimile Group 2/3" },
+ { 0x21, "F.184 Facsimile Group 4 Class I" },
+ { 0x24, "F.230 Teletex, basic and mixed mode, and F.184 Facsimile Group 4, Classes II and III" },
+ { 0x28, "F.220 Teletex, basic and processable mode" },
+ { 0x31, "F.200 Teletex, basic mode" },
+ { 0x32, "F.300 and T.102 syntax-based Videotex" },
+ { 0x33, "F.300 and T.101 international Videotex interworking" },
+ { 0x35, "F.60 Telex" },
+ { 0x38, "X.400 Message Handling Systems" },
+ { 0x41, "X.200 OSI application" },
+ { 0x42, "FTAM application" },
+ { 0x5E, "Reserved for maintenance" },
+ { 0x5F, "Reserved for management" },
+ { Q931_AUDIOVISUAL, "F.720/F.821 and F.731 Profile 1a videotelephony" },
+ { 0x61, "F.702 and F.731 Profile 1b videoconferencing" },
+ { 0x62, "F.702 and F.731 audiographic conferencing" },
+ { 0, NULL }
+};
+
+static const value_string q931_audiovisual_characteristics_vals[] = {
+ { 0x01, "Capability set of initial channel of H.221" },
+ { 0x02, "Capability set of subsequent channel of H.221" },
+ { 0x21, "Capability set of initial channel of an active 3.1kHz audio or speech call" },
+ { 0x00, NULL }
+};
+
+void
+dissect_q931_high_layer_compat_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 coding_standard;
+ guint8 characteristics;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ proto_tree_add_uint(tree, hf_q931_coding_standard, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+ if (coding_standard != Q931_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the call state is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ characteristics = octet & 0x7F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "High layer characteristics identification: %s",
+ val_to_str(characteristics, q931_high_layer_characteristics_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (!(octet & Q931_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if (characteristics == Q931_AUDIOVISUAL) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Extended audiovisual characteristics identification: %s",
+ val_to_str(octet & 0x7F,
+ q931_audiovisual_characteristics_vals,
+ "Unknown (0x%02X)"));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Extended high layer characteristics identification: %s",
+ val_to_str(octet & 0x7F,
+ q931_high_layer_characteristics_vals,
+ "Unknown (0x%02X)"));
+ }
+ }
+}
+
+
+/*
+ * Dissect a User-user information element.
+ */
+#define Q931_PROTOCOL_DISCRIMINATOR_IA5 0x04
+#define Q931_PROTOCOL_DISCRIMINATOR_ASN1 0x05
+
+static const value_string q931_protocol_discriminator_vals[] = {
+ { 0x00, "User-specific protocol" },
+ { 0x01, "OSI high layer protocols" },
+ { 0x02, "X.244" },
+ { Q931_PROTOCOL_DISCRIMINATOR_IA5, "IA5 characters" },
+ { Q931_PROTOCOL_DISCRIMINATOR_ASN1, "X.208 and X.209 coded user information" },
+ { 0x07, "V.120 rate adaption" },
+ { 0x08, "Q.931/I.451 user-network call control messages" },
+ { 0, NULL }
+};
+
+void
+dissect_q931_user_user_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Protocol discriminator: %s",
+ val_to_str(octet, q931_protocol_discriminator_vals,
+ "Unknown (0x%02x)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (octet) {
+
+ case Q931_PROTOCOL_DISCRIMINATOR_IA5:
+ proto_tree_add_text(tree, tvb, offset, len, "User information: %s",
+ tvb_format_text(tvb, offset, len));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len, "User information: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+ }
+}
+
+/*
+ * Dissect information elements consisting of ASCII^H^H^H^H^HIA5 text.
+ */
+static void
+dissect_q931_ia5_ie(tvbuff_t *tvb, int offset, int len, proto_tree *tree,
+ char *label)
+{
+ if (len != 0) {
+ proto_tree_add_text(tree, tvb, offset, len, "%s: %s", label,
+ tvb_format_text(tvb, offset, len));
+ proto_item_append_text(proto_tree_get_parent(tree), " '%s'", tvb_format_text(tvb, offset, len));
+ }
+}
+
+static void
+dissect_q931_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean is_tpkt)
+{
+ int offset = 0;
+ proto_tree *q931_tree = NULL;
+ proto_tree *ie_tree = NULL;
+ proto_item *ti, *ti_ie;
+ guint8 call_ref_len;
+ guint8 call_ref[15];
+ guint32 call_ref_val;
+ guint8 message_type, segmented_message_type;
+ guint8 info_element;
+ guint16 info_element_len;
+ gboolean more_frags;
+ guint32 frag_len;
+ fragment_data *fd_head;
+ tvbuff_t *next_tvb = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Q.931");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_q931, tvb, offset, -1,
+ FALSE);
+ q931_tree = proto_item_add_subtree(ti, ett_q931);
+
+ dissect_q931_protocol_discriminator(tvb, offset, q931_tree);
+ }
+ offset += 1;
+ call_ref_len = tvb_get_guint8(tvb, offset) & 0xF; /* XXX - do as a bit field? */
+ if (q931_tree != NULL)
+ proto_tree_add_uint(q931_tree, hf_q931_call_ref_len, tvb, offset, 1, call_ref_len);
+ offset += 1;
+ switch (call_ref_len) {
+ case 0: call_ref_val = 0; break;
+ case 1: call_ref_val = tvb_get_guint8(tvb, offset); break;
+ case 2: call_ref_val = tvb_get_ntohs(tvb, offset); break;
+ case 3: call_ref_val = tvb_get_ntoh24(tvb, offset); break;
+ default: call_ref_val = tvb_get_ntohl(tvb, offset);
+ }
+ if (call_ref_len != 0) {
+ tvb_memcpy(tvb, call_ref, offset, call_ref_len);
+ if (q931_tree != NULL) {
+ proto_tree_add_boolean(q931_tree, hf_q931_call_ref_flag,
+ tvb, offset, 1, (call_ref[0] & 0x80) != 0);
+ call_ref[0] &= 0x7F;
+ proto_tree_add_bytes(q931_tree, hf_q931_call_ref,
+ tvb, offset, call_ref_len, call_ref);
+ }
+ offset += call_ref_len;
+ }
+ message_type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(message_type, q931_message_type_vals,
+ "Unknown message type (0x%02X)"));
+ }
+ if (q931_tree != NULL)
+ proto_tree_add_uint(q931_tree, hf_q931_message_type, tvb, offset, 1, message_type);
+ offset += 1;
+
+ /*
+ * And now for the information elements....
+ */
+ if ((message_type != Q931_SEGMENT) || !q931_reassembly ||
+ (tvb_reported_length_remaining(tvb, offset) <= 4)) {
+ dissect_q931_IEs(tvb, pinfo, tree, q931_tree, is_tpkt, offset, 0);
+ return;
+ }
+ info_element = tvb_get_guint8(tvb, offset);
+ info_element_len = tvb_get_guint8(tvb, offset + 1);
+ if ((info_element != Q931_IE_SEGMENTED_MESSAGE) || (info_element_len < 2)) {
+ dissect_q931_IEs(tvb, pinfo, tree, q931_tree, is_tpkt, offset, 0);
+ return;
+ }
+ /* Segmented message IE */
+ ti_ie = proto_tree_add_text(q931_tree, tvb, offset, 1+1+info_element_len, "%s",
+ val_to_str(info_element, q931_info_element_vals[0], "Unknown information element (0x%02X)"));
+ ie_tree = proto_item_add_subtree(ti_ie, ett_q931_ie);
+ proto_tree_add_text(ie_tree, tvb, offset, 1, "Information element: %s",
+ val_to_str(info_element, q931_info_element_vals[0], "Unknown (0x%02X)"));
+ proto_tree_add_text(ie_tree, tvb, offset + 1, 1, "Length: %u", info_element_len);
+ dissect_q931_segmented_message_ie(tvb, offset + 2, info_element_len, ie_tree);
+ more_frags = (tvb_get_guint8(tvb, offset + 2) & 0x7F) != 0;
+ segmented_message_type = tvb_get_guint8(tvb, offset + 3);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " of %s",
+ val_to_str(segmented_message_type, q931_message_type_vals, "Unknown message type (0x%02X)"));
+ }
+ offset += 1 + 1 + info_element_len;
+ /* Reassembly */
+ frag_len = tvb_length_remaining(tvb, offset);
+ fd_head = fragment_add_seq_next(tvb, offset, pinfo, call_ref_val,
+ q931_fragment_table, q931_reassembled_table,
+ frag_len, more_frags);
+ if (fd_head) {
+ if (pinfo->fd->num == fd_head->reassembled_in) { /* last fragment */
+ if (fd_head->next != NULL) { /* 2 or more segments */
+ next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb, "Reassembled Q.931 IEs");
+ /* Show all fragments. */
+ if (tree) show_fragment_seq_tree(fd_head, &q931_frag_items, q931_tree, pinfo, next_tvb);
+ } else { /* only 1 segment */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s [reassembled]",
+ val_to_str(segmented_message_type, q931_message_type_vals, "Unknown message type (0x%02X)"));
+ }
+ } else {
+ if (tree) proto_tree_add_uint(q931_tree, hf_q931_reassembled_in, tvb, offset, frag_len, fd_head->reassembled_in);
+ }
+ }
+ if (next_tvb)
+ dissect_q931_IEs(next_tvb, pinfo, tree, q931_tree, is_tpkt, 0, 0);
+}
+
+static const value_string q931_codeset_vals[] = {
+ { 0x00, "Q.931 information elements" },
+ { 0x04, "Information elements for ISO/IEC use" },
+ { 0x05, "Information elements for national use" },
+ { 0x06, "Information elements specific to the local network" },
+ { 0x07, "User-specific information elements" },
+ { 0x00, NULL },
+};
+
+static void
+dissect_q931_IEs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *root_tree,
+ proto_tree *q931_tree, gboolean is_tpkt, int offset, int initial_codeset)
+{
+ proto_item *ti;
+ proto_tree *ie_tree = NULL;
+ guint8 info_element;
+ guint16 info_element_len;
+ int codeset, locked_codeset;
+ gboolean non_locking_shift, first_segment;
+ tvbuff_t *h225_tvb, *next_tvb;
+ e164_info_t e164_info;
+ e164_info.e164_number_type = NONE;
+
+ codeset = locked_codeset = initial_codeset;
+ non_locking_shift = TRUE;
+ first_segment = FALSE;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ info_element = tvb_get_guint8(tvb, offset);
+
+ /* Check for the codeset shift */
+ if ((info_element & Q931_IE_SO_MASK) &&
+ ((info_element & Q931_IE_SO_IDENTIFIER_MASK) == Q931_IE_SHIFT)) {
+ non_locking_shift = info_element & Q931_IE_SHIFT_NON_LOCKING;
+ codeset = info_element & Q931_IE_SHIFT_CODESET;
+ if (!non_locking_shift)
+ locked_codeset = codeset;
+ if (q931_tree != NULL) {
+ proto_tree_add_text(q931_tree, tvb, offset, 1,
+ "%s shift to codeset %u: %s",
+ (non_locking_shift ? "Non-locking" : "Locking"),
+ codeset,
+ val_to_str(codeset, q931_codeset_vals,
+ "Unknown (0x%02X)"));
+ }
+ offset += 1;
+ continue;
+ }
+
+ /*
+ * Check for the single-octet IEs.
+ */
+ if (info_element & Q931_IE_SO_MASK) {
+ /*
+ * Check for subdissectors for this IE or
+ * for all IEs in this codeset.
+ */
+ if (dissector_get_port_handle(codeset_dissector_table, codeset) ||
+ dissector_get_port_handle(ie_dissector_table, (codeset << 8) | (info_element & Q931_IE_SO_IDENTIFIER_MASK))) {
+ next_tvb = tvb_new_subset (tvb, offset, 1, 1);
+ if (dissector_try_port(ie_dissector_table, (codeset << 8) | (info_element & Q931_IE_SO_IDENTIFIER_MASK), next_tvb, pinfo, q931_tree) ||
+ dissector_try_port(codeset_dissector_table, codeset, next_tvb, pinfo, q931_tree)) {
+ offset += 1;
+ codeset = locked_codeset;
+ continue;
+ }
+ }
+
+ switch ((codeset << 8) | (info_element & Q931_IE_SO_IDENTIFIER_MASK)) {
+
+ case CS0 | Q931_IE_MORE_DATA_OR_SEND_COMP:
+ switch (info_element) {
+
+ case Q931_IE_MORE_DATA:
+ if (q931_tree != NULL) {
+ proto_tree_add_text(q931_tree, tvb, offset, 1,
+ "More data");
+ }
+ break;
+
+ case Q931_IE_SENDING_COMPLETE:
+ if (q931_tree != NULL) {
+ proto_tree_add_text(q931_tree, tvb, offset, 1,
+ "Sending complete");
+ }
+ break;
+
+ default:
+ if (q931_tree != NULL) {
+ proto_tree_add_text(q931_tree, tvb, offset, 1,
+ "Unknown information element (0x%02X)",
+ info_element);
+ }
+ break;
+ }
+ break;
+
+ case CS0 | Q931_IE_CONGESTION_LEVEL:
+ if (q931_tree != NULL) {
+ proto_tree_add_text(q931_tree, tvb, offset, 1,
+ "Congestion level: %s",
+ val_to_str(info_element & Q931_IE_SO_IE_MASK,
+ q931_congestion_level_vals,
+ "Unknown (0x%X)"));
+ }
+ break;
+
+ case CS0 | Q931_IE_REPEAT_INDICATOR:
+ if (q931_tree != NULL) {
+ proto_tree_add_text(q931_tree, tvb, offset, 1,
+ "Repeat indicator: %s",
+ val_to_str(info_element & Q931_IE_SO_IE_MASK,
+ q931_repeat_indication_vals,
+ "Unknown (0x%X)"));
+ }
+ break;
+
+ default:
+ if (q931_tree != NULL) {
+ proto_tree_add_text(q931_tree, tvb, offset, 1,
+ "Unknown information element (0x%02X)",
+ info_element);
+ }
+ break;
+ }
+ offset += 1;
+ codeset = locked_codeset;
+ continue;
+ }
+
+ /*
+ * Variable-length IE.
+ *
+ * According to page 18 from Recommendation H.225.0 :
+ * " Length of user-user contents contents
+ * - Shall be 2 octets instead of 1 (as in Figure 4-36/Q.931)"
+ *
+ * We assume that if this is Q.931-over-TPKT, it might
+ * be H.225 traffic, and check for the IE being a user-user
+ * IE with ASN.1 encoding of the user information.
+ */
+ if (is_tpkt && tvb_bytes_exist(tvb, offset, 4) &&
+ codeset == 0 && tvb_get_guint8(tvb, offset) == Q931_IE_USER_USER &&
+ tvb_get_guint8(tvb, offset + 3) == Q931_PROTOCOL_DISCRIMINATOR_ASN1) {
+ info_element_len = tvb_get_ntohs(tvb, offset + 1);
+ if (q931_tree != NULL) {
+ ti = proto_tree_add_text(q931_tree, tvb, offset,
+ 1+2+info_element_len, "%s",
+ val_to_str(info_element,
+ q931_info_element_vals[codeset],
+ "Unknown information element (0x%02X)"));
+ ie_tree = proto_item_add_subtree(ti,
+ ett_q931_ie);
+ proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "Information element: %s",
+ val_to_str(info_element,
+ q931_info_element_vals[codeset], "Unknown (0x%02X)"));
+ proto_tree_add_text(ie_tree, tvb, offset + 1,
+ 2, "Length: %u", info_element_len);
+ proto_tree_add_text(ie_tree, tvb, offset + 3,
+ 1, "Protocol discriminator: %s",
+ val_to_str(tvb_get_guint8(tvb, offset + 3),
+ q931_protocol_discriminator_vals,
+ "Unknown (0x%02x)"));
+ }
+
+ if (info_element_len > 1) {
+ /*
+ * Do we have a handle for the H.225
+ * dissector?
+ */
+ if (h225_handle != NULL) {
+ /*
+ * Yes - call it, regardless of
+ * whether we're building a
+ * protocol tree or not.
+ */
+ h225_tvb = tvb_new_subset(tvb,
+ offset + 4, info_element_len - 1,
+ info_element_len - 1);
+ call_dissector(h225_handle, h225_tvb,
+ pinfo, root_tree);
+ } else {
+ /*
+ * No - just show it as "User
+ * information" (if "ie_tree" is
+ * null, this won't add anything).
+ */
+ proto_tree_add_text(ie_tree, tvb,
+ offset + 4, info_element_len - 1,
+ "User information: %s",
+ tvb_bytes_to_str(tvb, offset + 4,
+ info_element_len - 1));
+ }
+ }
+ offset += 1 + 2 + info_element_len;
+ } else {
+ info_element_len = tvb_get_guint8(tvb, offset + 1);
+
+ if (first_segment && (tvb_reported_length_remaining(tvb, offset + 2) < info_element_len)) { /* incomplete IE at the end of the 1st segment */
+ proto_tree_add_text(q931_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), "Incomplete IE in the 1st segment");
+ break;
+ }
+
+ /*
+ * Check for subdissectors for this IE or
+ * for all IEs in this codeset.
+ */
+ if (dissector_get_port_handle(codeset_dissector_table, codeset) ||
+ dissector_get_port_handle(ie_dissector_table, (codeset << 8) | info_element)) {
+ next_tvb = tvb_new_subset (tvb, offset, info_element_len + 2, info_element_len + 2);
+ if (dissector_try_port(ie_dissector_table, (codeset << 8) | info_element, next_tvb, pinfo, q931_tree) ||
+ dissector_try_port(codeset_dissector_table, codeset, next_tvb, pinfo, q931_tree)) {
+ offset += 2 + info_element_len;
+ codeset = locked_codeset;
+ continue;
+ }
+ }
+
+ ti = proto_tree_add_text(q931_tree, tvb, offset, 1+1+info_element_len, "%s",
+ val_to_str(info_element, q931_info_element_vals[codeset], "Unknown information element (0x%02X)"));
+ ie_tree = proto_item_add_subtree(ti, ett_q931_ie);
+ proto_tree_add_text(ie_tree, tvb, offset, 1, "Information element: %s",
+ val_to_str(info_element, q931_info_element_vals[codeset], "Unknown (0x%02X)"));
+ proto_tree_add_text(ie_tree, tvb, offset + 1, 1, "Length: %u", info_element_len);
+
+ if (((codeset << 8) | info_element) == (CS0 | Q931_IE_SEGMENTED_MESSAGE)) {
+ dissect_q931_segmented_message_ie(tvb, offset + 2, info_element_len, ie_tree);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " of %s",
+ val_to_str(tvb_get_guint8(tvb, offset + 3), q931_message_type_vals, "Unknown message type (0x%02X)"));
+ }
+ if (tvb_get_guint8(tvb, offset + 2) & 0x80) { /* the 1st segment */
+ first_segment = TRUE;
+ } else { /* not the 1st segment */
+ proto_tree_add_text(q931_tree, tvb, offset + 4, tvb_reported_length_remaining(tvb, offset + 4), "Message segment");
+ info_element_len += tvb_reported_length_remaining(tvb, offset + 4);
+ }
+ } else if (q931_tree != NULL) {
+ switch ((codeset << 8) | info_element) {
+
+ case CS0 | Q931_IE_BEARER_CAPABILITY:
+ case CS0 | Q931_IE_LOW_LAYER_COMPAT:
+ dissect_q931_bearer_capability_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_CAUSE:
+ dissect_q931_cause_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree,
+ hf_q931_cause_value);
+ break;
+
+ case CS0 | Q931_IE_CALL_STATE:
+ dissect_q931_call_state_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_CHANNEL_IDENTIFICATION:
+ dissect_q931_channel_identification_ie(
+ tvb, offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_PROGRESS_INDICATOR:
+ dissect_q931_progress_indicator_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_NETWORK_SPECIFIC_FACIL:
+ case CS0 | Q931_IE_TRANSIT_NETWORK_SEL:
+ dissect_q931_ns_facilities_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_NOTIFICATION_INDICATOR:
+ dissect_q931_notification_indicator_ie(
+ tvb, offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_DISPLAY:
+ dissect_q931_ia5_ie(tvb, offset + 2,
+ info_element_len, ie_tree,
+ "Display information");
+ break;
+
+ case CS0 | Q931_IE_DATE_TIME:
+ dissect_q931_date_time_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_KEYPAD_FACILITY:
+ dissect_q931_ia5_ie(tvb, offset + 2,
+ info_element_len, ie_tree,
+ "Keypad facility");
+ break;
+
+ case CS0 | Q931_IE_SIGNAL:
+ dissect_q931_signal_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_INFORMATION_RATE:
+ dissect_q931_information_rate_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_E2E_TRANSIT_DELAY:
+ dissect_q931_e2e_transit_delay_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_TD_SELECTION_AND_INT:
+ dissect_q931_td_selection_and_int_ie(
+ tvb, offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_PL_BINARY_PARAMETERS:
+ dissect_q931_pl_binary_parameters_ie(
+ tvb, offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_PL_WINDOW_SIZE:
+ dissect_q931_pl_window_size_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_PACKET_SIZE:
+ dissect_q931_packet_size_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_CUG:
+ dissect_q931_cug_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_REVERSE_CHARGE_IND:
+ dissect_q931_reverse_charge_ind_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_CALLING_PARTY_NUMBER:
+ e164_info.e164_number_type = CALLING_PARTY_NUMBER;
+ dissect_q931_number_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree,
+ hf_q931_calling_party_number, e164_info);
+ break;
+
+ case CS0 | Q931_IE_CONNECTED_NUMBER_DEFAULT:
+ dissect_q931_number_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree,
+ hf_q931_connected_number, e164_info);
+ break;
+
+ case CS0 | Q931_IE_CALLED_PARTY_NUMBER:
+ e164_info.e164_number_type = CALLED_PARTY_NUMBER;
+ dissect_q931_number_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree,
+ hf_q931_called_party_number, e164_info);
+ break;
+
+ case CS0 | Q931_IE_REDIRECTING_NUMBER:
+ dissect_q931_number_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree,
+ hf_q931_redirecting_number, e164_info);
+ break;
+
+ case CS0 | Q931_IE_CALLING_PARTY_SUBADDR:
+ case CS0 | Q931_IE_CALLED_PARTY_SUBADDR:
+ dissect_q931_party_subaddr_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_RESTART_INDICATOR:
+ dissect_q931_restart_indicator_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_HIGH_LAYER_COMPAT:
+ dissect_q931_high_layer_compat_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q931_IE_USER_USER:
+ dissect_q931_user_user_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ default:
+ proto_tree_add_text(ie_tree, tvb,
+ offset + 2, info_element_len,
+ "Data: %s",
+ bytes_to_str(
+ tvb_get_ptr(tvb, offset + 2,
+ info_element_len),
+ info_element_len));
+ break;
+ }
+ }
+ offset += 1 + 1 + info_element_len;
+ }
+ codeset = locked_codeset;
+ }
+}
+
+/*
+ * Q.931-over-TPKT-over-TCP.
+ */
+static gboolean
+dissect_q931_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int lv_tpkt_len;
+
+ /*
+ * Check whether this looks like a TPKT-encapsulated
+ * Q.931 packet.
+ *
+ * The minimum length of a Q.931 message is 3:
+ * 1 byte for the protocol discriminator,
+ * 1 for the call_reference length,
+ * and one for the message type.
+ */
+ lv_tpkt_len = is_tpkt(tvb, 3);
+ if (lv_tpkt_len == -1) {
+ /*
+ * It's not a TPKT packet; reject it.
+ */
+ return FALSE;
+ }
+
+ /*
+ * If this segment is *exactly* the length of a TPKT header,
+ * we assume that, as it looks like a TPKT header, it
+ * is one, and that the code put a TPKT header in one
+ * segment and the rest of the PDU in another.
+ */
+ if (tvb_length(tvb) == 4) {
+ /*
+ * It is - call the "dissect TPKT over a TCP stream"
+ * routine.
+ */
+ dissect_tpkt_encap(tvb, pinfo, tree, q931_desegment,
+ q931_tpkt_pdu_handle);
+ return TRUE;
+ }
+
+ /*
+ * Well, we have more data than just the TPKT header;
+ * check whether it looks like the beginning of a
+ * Q.931 message.
+ *
+ * The minimum length of a Q.931 message is 3, as per the
+ * above.
+ *
+ * Check that we have that many bytes past the TPKT header in
+ * the tvbuff; we already know that the TPKT header says we
+ * have that many bytes (as we passed 3 as the "min_len" argument
+ * to "is_tpkt()").
+ */
+ if (!tvb_bytes_exist(tvb, 4, 3))
+ return FALSE;
+
+ /* Check the protocol discriminator */
+ if (tvb_get_guint8(tvb, 4) != NLPID_Q_931) {
+ /* Doesn't look like Q.931 inside TPKT */
+ return FALSE;
+ }
+
+ /*
+ * OK, it looks like Q.931-over-TPKT.
+ * Call the "dissect TPKT over a TCP stream" routine.
+ */
+ dissect_tpkt_encap(tvb, pinfo, tree, q931_desegment,
+ q931_tpkt_pdu_handle);
+
+ return TRUE;
+}
+
+static void
+dissect_q931_tpkt_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_q931_pdu(tvb, pinfo, tree, TRUE);
+}
+
+static void
+dissect_q931(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_q931_pdu(tvb, pinfo, tree, FALSE);
+}
+
+static void
+dissect_q931_ie_cs0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_q931_IEs(tvb, pinfo, NULL, tree, FALSE, 0, 0);
+}
+
+static void
+dissect_q931_ie_cs7(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_q931_IEs(tvb, pinfo, NULL, tree, FALSE, 0, 7);
+}
+
+static void
+q931_init(void) {
+ /* Initialize the fragment and reassembly tables */
+ fragment_table_init(&q931_fragment_table);
+ reassembled_table_init(&q931_reassembled_table);
+}
+
+void
+proto_register_q931(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_q931_discriminator,
+ { "Protocol discriminator", "q931.disc", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q931_call_ref_len,
+ { "Call reference value length", "q931.call_ref_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q931_call_ref_flag,
+ { "Call reference flag", "q931.call_ref_flag", FT_BOOLEAN, BASE_NONE, TFS(&tfs_call_ref_flag), 0x0,
+ "", HFILL }},
+
+ { &hf_q931_call_ref,
+ { "Call reference value", "q931.call_ref", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q931_message_type,
+ { "Message type", "q931.message_type", FT_UINT8, BASE_HEX, VALS(q931_message_type_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_q931_segment_type,
+ { "Segmented message type", "q931.segment_type", FT_UINT8, BASE_HEX, VALS(q931_message_type_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_q931_coding_standard,
+ { "Coding standard", "q931.coding_standard", FT_UINT8, BASE_HEX,
+ VALS(q931_coding_standard_vals), 0x60,"", HFILL }},
+
+ { &hf_q931_information_transfer_capability,
+ { "Information transfer capability", "q931.information_transfer_capability", FT_UINT8, BASE_HEX,
+ VALS(q931_information_transfer_capability_vals), 0x1f,"", HFILL }},
+
+ { &hf_q931_transfer_mode,
+ { "Transfer mode", "q931.transfer_mode", FT_UINT8, BASE_HEX,
+ VALS(q931_transfer_mode_vals), 0x60,"", HFILL }},
+
+ { &hf_q931_information_transfer_rate,
+ { "Information transfer rate", "q931.information_transfer_rate", FT_UINT8, BASE_HEX,
+ VALS(q931_information_transfer_rate_vals), 0x1f,"", HFILL }},
+
+ { &hf_q931_uil1,
+ { "User information layer 1 protocol", "q931.uil1", FT_UINT8, BASE_HEX,
+ VALS(q931_uil1_vals), 0x1f,"", HFILL }},
+
+ { &hf_q931_cause_location,
+ { "Cause location", "q931.cause_location", FT_UINT8, BASE_DEC, VALS(q931_cause_location_vals), 0x0f,
+ "", HFILL }},
+
+ { &hf_q931_cause_value,
+ { "Cause value", "q931.cause_value", FT_UINT8, BASE_DEC, VALS(q931_cause_code_vals), 0x7f,
+ "", HFILL }},
+
+ { &hf_q931_number_type,
+ { "Number type", "q931.number_type", FT_UINT8, BASE_HEX, VALS(q931_number_type_vals), 0x70,
+ "", HFILL }},
+
+ { &hf_q931_numbering_plan,
+ { "Numbering plan", "q931.numbering_plan", FT_UINT8, BASE_HEX, VALS(q931_numbering_plan_vals), 0x0f,
+ "", HFILL }},
+
+ { &hf_q931_screening_ind,
+ { "Screening indicator", "q931.screening_ind", FT_UINT8, BASE_HEX, VALS(q931_screening_indicator_vals), 0x03,
+ "", HFILL }},
+
+ { &hf_q931_presentation_ind,
+ { "Presentation indicator", "q931.presentation_ind", FT_UINT8, BASE_HEX, VALS(q931_presentation_indicator_vals), 0x60,
+ "", HFILL }},
+
+ { &hf_q931_extension_ind,
+ { "Extension indicator", "q931.extension_ind",
+ FT_BOOLEAN, 8, TFS(&q931_extension_ind_value), 0x80,
+ "", HFILL }},
+
+ { &hf_q931_calling_party_number,
+ { "Calling party number digits", "q931.calling_party_number.digits", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q931_called_party_number,
+ { "Called party number digits", "q931.called_party_number.digits", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q931_connected_number,
+ { "Connected party number digits", "q931.connected_number.digits", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q931_redirecting_number,
+ { "Redirecting party number digits", "q931.redirecting_number.digits", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ /* desegmentation fields */
+ { &hf_q931_segment_overlap,
+ { "Segment overlap", "q931.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_q931_segment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "q931.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_q931_segment_multiple_tails,
+ { "Multiple tail fragments found", "q931.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_q931_segment_too_long_segment,
+ { "Segment too long", "q931.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment contained data past end of packet", HFILL }},
+
+ { &hf_q931_segment_error,
+ { "Defragmentation error", "q931.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }},
+
+ { &hf_q931_segment,
+ { "Q.931 Segment", "q931.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Q.931 Segment", HFILL }},
+
+ { &hf_q931_segments,
+ { "Q.931 Segments", "q931.segments", FT_NONE, BASE_NONE, NULL, 0x0,
+ "Q.931 Segments", HFILL }},
+
+ { &hf_q931_reassembled_in,
+ { "Reassembled Q.931 in frame", "q931.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This Q.931 message is reassembled in this frame", HFILL}},
+ };
+ static gint *ett[] = {
+ &ett_q931,
+ &ett_q931_ie,
+ &ett_q931_segments,
+ &ett_q931_segment,
+ };
+ module_t *q931_module;
+
+ proto_q931 = proto_register_protocol("Q.931", "Q.931", "q931");
+ proto_register_field_array (proto_q931, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(q931_init);
+
+ register_dissector("q931", dissect_q931, proto_q931);
+ q931_tpkt_pdu_handle = create_dissector_handle(dissect_q931_tpkt_pdu,
+ proto_q931);
+ register_dissector("q931.ie", dissect_q931_ie_cs0, proto_q931);
+ register_dissector("q931.ie.cs7", dissect_q931_ie_cs7, proto_q931);
+
+ /* subdissector code */
+ codeset_dissector_table = register_dissector_table("q931.codeset", "Q.931 Codeset", FT_UINT8, BASE_HEX);
+ ie_dissector_table = register_dissector_table("q931.ie", "Q.931 IE", FT_UINT16, BASE_HEX);
+
+ q931_module = prefs_register_protocol(proto_q931, NULL);
+ prefs_register_bool_preference(q931_module, "desegment_h323_messages",
+ "Desegment all Q.931 messages spanning multiple TCP segments",
+ "Whether the Q.931 dissector should desegment all messages spanning multiple TCP segments",
+ &q931_desegment);
+ prefs_register_bool_preference(q931_module, "reassembly",
+ "Reassemble segmented Q.931 messages",
+ "Reassemble segmented Q.931 messages (Q.931 - Annex H)",
+ &q931_reassembly);
+}
+
+void
+proto_reg_handoff_q931(void)
+{
+ dissector_handle_t q931_handle;
+
+ q931_handle = find_dissector("q931");
+ dissector_add("lapd.sapi", LAPD_SAPI_Q931, q931_handle);
+
+ /*
+ * Attempt to get a handle for the H.225 dissector.
+ * If we can't, the handle we get is null, and we'll just
+ * dissect putatively-H.255 Call Signaling stuff as User
+ * Information.
+ */
+ h225_handle = find_dissector("h225");
+
+ /*
+ * For H.323.
+ */
+ heur_dissector_add("tcp", dissect_q931_tpkt, proto_q931);
+}
diff --git a/epan/dissectors/packet-q931.h b/epan/dissectors/packet-q931.h
new file mode 100644
index 0000000000..c01cb39788
--- /dev/null
+++ b/epan/dissectors/packet-q931.h
@@ -0,0 +1,49 @@
+/* packet-q931.h
+ * Declarations of exported routines and tables for Q.931 and Q.2931 frame
+ * disassembly
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_Q931_H__
+#define __PACKET_Q931_H__
+
+extern void dissect_q931_bearer_capability_ie(tvbuff_t *, int, int,
+ proto_tree *);
+
+extern void dissect_q931_cause_ie(tvbuff_t *, int, int,
+ proto_tree *, int);
+
+extern void dissect_q931_progress_indicator_ie(tvbuff_t *, int, int,
+ proto_tree *);
+
+extern void dissect_q931_high_layer_compat_ie(tvbuff_t *, int, int,
+ proto_tree *);
+
+extern void dissect_q931_user_user_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree);
+
+extern const value_string q931_cause_location_vals[];
+
+extern const value_string q931_cause_code_vals[];
+
+#endif
diff --git a/epan/dissectors/packet-q933.c b/epan/dissectors/packet-q933.c
new file mode 100644
index 0000000000..96b48a528b
--- /dev/null
+++ b/epan/dissectors/packet-q933.c
@@ -0,0 +1,2150 @@
+/* packet-q933.c
+ * Routines for Q.933 frame disassembly
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "nlpid.h"
+
+static int proto_q933 = -1;
+static int hf_q933_discriminator = -1;
+static int hf_q933_coding_standard = -1;
+static int hf_q933_information_transfer_capability = -1;
+static int hf_q933_transfer_mode = -1;
+static int hf_q933_uil1 = -1;
+static int hf_q933_call_ref_len = -1;
+static int hf_q933_call_ref_flag = -1;
+static int hf_q933_call_ref = -1;
+static int hf_q933_message_type = -1;
+static int hf_q933_cause_location = -1;
+static int hf_q933_cause_value = -1;
+static int hf_q933_number_type = -1;
+static int hf_q933_numbering_plan = -1;
+static int hf_q933_extension_ind = -1;
+static int hf_q933_calling_party_number = -1;
+static int hf_q933_called_party_number = -1;
+static int hf_q933_connected_number = -1;
+static int hf_q933_redirecting_number = -1;
+static int hf_q933_screening_ind = -1;
+static int hf_q933_presentation_ind = -1;
+
+static gint ett_q933 = -1;
+static gint ett_q933_ie = -1;
+
+/*
+ * Q.933 message types.
+ */
+#define Q933_ESCAPE 0x00
+#define Q933_ALERTING 0x01
+#define Q933_CALL_PROCEEDING 0x02
+#define Q933_CONNECT 0x07
+#define Q933_CONNECT_ACK 0x0F
+#define Q933_PROGRESS 0x03
+#define Q933_SETUP 0x05
+#define Q933_DISCONNECT 0x45
+#define Q933_RELEASE 0x4D
+#define Q933_RELEASE_COMPLETE 0x5A
+#define Q933_SEGMENT 0x60
+#define Q933_STATUS 0x7D
+#define Q933_STATUS_ENQUIRY 0x75
+
+static const value_string q933_message_type_vals[] = {
+ { Q933_ESCAPE, "ESCAPE" },
+ { Q933_ALERTING, "ALERTING" },
+ { Q933_CALL_PROCEEDING, "CALL PROCEEDING" },
+ { Q933_CONNECT, "CONNECT" },
+ { Q933_CONNECT_ACK, "CONNECT ACKNOWLEDGE" },
+ { Q933_PROGRESS, "PROGRESS" },
+ { Q933_SETUP, "SETUP" },
+ { Q933_DISCONNECT, "DISCONNECT" },
+ { Q933_RELEASE, "RELEASE" },
+ { Q933_RELEASE_COMPLETE, "RELEASE COMPLETE" },
+ { Q933_SEGMENT, "SEGMENT" },
+ { Q933_STATUS, "STATUS" },
+ { Q933_STATUS_ENQUIRY, "STATUS ENQUIRY" },
+ { 0, NULL }
+};
+
+static const true_false_string tfs_call_ref_flag = {
+ "Message sent to originating side",
+ "Message sent from originating side"
+};
+
+/*
+ * Information elements.
+ */
+
+/* Shifted codeset values */
+#define CS0 0x000
+#define CS1 0x100
+#define CS2 0x200
+#define CS3 0x300
+#define CS4 0x400
+#define CS5 0x500
+#define CS6 0x600
+#define CS7 0x700
+
+#define Q933_IE_SO_MASK 0x80 /* single-octet/variable-length mask */
+/*
+ * Single-octet IEs.
+ */
+#define Q933_IE_SO_IDENTIFIER_MASK 0xf0 /* IE identifier mask */
+#define Q933_IE_SO_IDENTIFIER_SHIFT 4 /* IE identifier shift */
+#define Q933_IE_SO_IE_MASK 0x0F /* IE mask */
+
+#define Q933_IE_SHIFT 0x90
+#define Q933_IE_SHIFT_NON_LOCKING 0x08 /* non-locking shift */
+#define Q933_IE_SHIFT_CODESET 0x07 /* codeset */
+
+#define Q933_IE_REPEAT_INDICATOR 0xD0
+
+/*
+ * Variable-length IEs.
+ */
+#define Q933_IE_VL_EXTENSION 0x80 /* Extension flag */
+/* extension bit. The bit value "0" indicates that the octet continues through the */
+/* next octet. The bit value "1" indicates that this octet is the last octet */
+
+static const true_false_string q933_extension_ind_value = {
+ "last octet",
+ "information continues through the next octet",
+
+};
+
+
+/*
+ * Codeset 0 (default).
+ */
+#define Q933_IE_SEGMENTED_MESSAGE 0x00
+#define Q933_IE_BEARER_CAPABILITY 0x04
+#define Q933_IE_CAUSE 0x08
+#define Q933_IE_CALL_STATE 0x14
+#define Q933_IE_CHANNEL_IDENTIFICATION 0x18
+#define Q933_IE_DLCI 0x19
+#define Q933_IE_PROGRESS_INDICATOR 0x1E
+#define Q933_IE_NETWORK_SPECIFIC_FACIL 0x20 /* Network Specific Facilities */
+#define Q933_IE_DISPLAY 0x28
+#define Q933_IE_E2E_TRANSIT_DELAY 0x42 /* End-to-end Transit Delay */
+#define Q933_IE_TD_SELECTION_AND_INT 0x43 /* Transit Delay Selection and Indication */
+#define Q933_IE_PL_BINARY_PARAMETERS 0x44 /* Packet layer binary parameters */
+#define Q933_IE_LL_CORE_PARAMETERS 0x48 /* Link layer core parameters */
+#define Q933_IE_LL_PROTOCOL_PARAMETERS 0x49 /* Link layer protocol parameters */
+#define Q933_IE_REVERSE_CHARGE_IND 0x4A /* Reverse charging indication */
+#define Q933_IE_CONNECTED_NUMBER 0x4C /* Connected Number */
+#define Q933_IE_CONNECTED_SUBADDR 0x4D /* Connected sub-address */
+#define Q933_IE_X_213_PRIORITY 0x50 /* X.213 priority */
+#define Q933_IE_REPORT_TYPE 0x51
+#define Q933_IE_LINK_INTEGRITY_VERF 0x53 /* Link integrity verification */
+#define Q933_IE_PVC_STATUS 0x57
+#define Q933_IE_CALLING_PARTY_NUMBER 0x6C /* Calling Party Number */
+#define Q933_IE_CALLING_PARTY_SUBADDR 0x6D /* Calling Party Subaddress */
+#define Q933_IE_CALLED_PARTY_NUMBER 0x70 /* Called Party Number */
+#define Q933_IE_CALLED_PARTY_SUBADDR 0x71 /* Called Party Subaddress */
+#define Q933_IE_TRANSIT_NETWORK_SEL 0x78 /* Transit Network Selection */
+#define Q933_IE_LOW_LAYER_COMPAT 0x7C /* Low-Layer Compatibility */
+#define Q933_IE_HIGH_LAYER_COMPAT 0x7D /* High-Layer Compatibility */
+#define Q933_IE_USER_USER 0x7E /* User-User */
+#define Q933_IE_ESCAPE 0x7F /* Escape for extension */
+
+/* Codeset 0 */
+static const value_string q933_info_element_vals0[] = {
+ { Q933_IE_SEGMENTED_MESSAGE, "Segmented message" },
+ { Q933_IE_BEARER_CAPABILITY, "Bearer capability" },
+ { Q933_IE_CAUSE, "Cause" },
+ { Q933_IE_CALL_STATE, "Call state" },
+ { Q933_IE_CHANNEL_IDENTIFICATION, "Channel identification" },
+ { Q933_IE_DLCI, "Data link connection identifier" },
+ { Q933_IE_PROGRESS_INDICATOR, "Progress indicator" },
+ { Q933_IE_NETWORK_SPECIFIC_FACIL, "Network specific facilities" },
+ { Q933_IE_E2E_TRANSIT_DELAY, "End-to-end transit delay" },
+ { Q933_IE_TD_SELECTION_AND_INT, "Transit delay selection and indication" },
+ { Q933_IE_PL_BINARY_PARAMETERS, "Packet layer binary parameters" },
+ { Q933_IE_LL_CORE_PARAMETERS, "Link layer core parameters" },
+ { Q933_IE_LL_PROTOCOL_PARAMETERS, "Link layer protocol parameters" },
+ { Q933_IE_REVERSE_CHARGE_IND, "Reverse charging indication" },
+ { Q933_IE_CONNECTED_NUMBER, "Connected number" },
+ { Q933_IE_CONNECTED_SUBADDR, "Connected subaddress" },
+ { Q933_IE_X_213_PRIORITY, "X.213 priority" },
+ { Q933_IE_REPORT_TYPE, "Report type" },
+ { Q933_IE_LINK_INTEGRITY_VERF, "Link integrity verification" },
+ { Q933_IE_PVC_STATUS, "PVC status" },
+ { Q933_IE_CALLING_PARTY_NUMBER, "Calling party number" },
+ { Q933_IE_CALLING_PARTY_SUBADDR, "Calling party subaddress" },
+ { Q933_IE_CALLED_PARTY_NUMBER, "Called party number" },
+ { Q933_IE_CALLED_PARTY_SUBADDR, "Called party subaddress" },
+ { Q933_IE_TRANSIT_NETWORK_SEL, "Transit network selection" },
+ { Q933_IE_LOW_LAYER_COMPAT, "Low-layer compatibility" },
+ { Q933_IE_HIGH_LAYER_COMPAT, "High-layer compatibility" },
+ { Q933_IE_USER_USER, "User-user" },
+ { Q933_IE_ESCAPE, "Escape" },
+ { 0, NULL }
+};
+/* Codeset 1 */
+static const value_string q933_info_element_vals1[] = {
+ { 0, NULL }
+};
+/* Codeset 2 */
+static const value_string q933_info_element_vals2[] = {
+ { 0, NULL }
+};
+/* Codeset 3 */
+static const value_string q933_info_element_vals3[] = {
+ { 0, NULL }
+};
+/* Codeset 4 */
+static const value_string q933_info_element_vals4[] = {
+ { 0, NULL }
+};
+/* Codeset 5 */
+static const value_string q933_info_element_vals5[] = {
+ { 0, NULL }
+};
+/* Codeset 6 */
+static const value_string q933_info_element_vals6[] = {
+ { 0, NULL }
+};
+/* Codeset 7 */
+static const value_string q933_info_element_vals7[] = {
+ { 0, NULL }
+};
+
+/* Codeset array */
+#define NUM_INFO_ELEMENT_VALS (Q933_IE_SHIFT_CODESET+1)
+static const value_string *q933_info_element_vals[NUM_INFO_ELEMENT_VALS] = {
+ q933_info_element_vals0,
+ q933_info_element_vals1,
+ q933_info_element_vals2,
+ q933_info_element_vals3,
+ q933_info_element_vals4,
+ q933_info_element_vals5,
+ q933_info_element_vals6,
+ q933_info_element_vals7,
+};
+
+static const value_string q933_repeat_indication_vals[] = {
+ { 0x2, "Prioritized list" },
+ { 0, NULL }
+};
+
+/*
+ * ITU-standardized coding.
+ */
+#define Q933_ITU_STANDARDIZED_CODING 0x00
+
+/*
+ * Dissect a Segmented message information element.
+ */
+static void
+dissect_q933_segmented_message_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len != 2) {
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Segmented message: length is %d, should be 2", len);
+ return;
+ }
+ if (tvb_get_guint8(tvb, offset) & 0x80) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "First segment: %u segments remaining",
+ tvb_get_guint8(tvb, offset) & 0x7F);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Not first segment: %u segments remaining",
+ tvb_get_guint8(tvb, offset) & 0x7F);
+ }
+ proto_tree_add_text(tree, tvb, offset + 1, 1,
+ "Segmented message type: %u", tvb_get_guint8(tvb, offset + 1));
+}
+
+/*
+ * Dissect a Bearer capability or Low-layer compatibility information element.
+ */
+static const value_string q933_coding_standard_vals[] = {
+ { 0x0, "ITU-T standardized coding" },
+ { 0x1, "ISO/IEC standard" },
+ { 0x2, "National standard" },
+ { 0x3, "Standard defined for this particular network" },
+ { 0, NULL }
+};
+
+static const value_string q933_information_transfer_capability_vals[] = {
+ { 0x08, "Unrestricted digital information" },
+ { 0, NULL }
+};
+
+static const value_string q933_transfer_mode_vals[] = {
+ { 0x01, "Frame mode" },
+ { 0, NULL }
+};
+
+static const value_string q933_uil1_vals[] = {
+ { 0x01, "V.110/I.460/X.30 rate adaption" },
+ { 0x02, "Recommendation G.711 u-law" },
+ { 0x03, "Recommendation G.711 A-law" },
+ { 0x04, "Recommendation G.721 32 kbit/s ADPCM and Recommendation I.460" },
+ { 0x05, "Recommendation H.221 and H.242" },
+ { 0x06, "Recommendation H.223 and H.245" },
+ { 0x07, "Non-ITU-T-standardized rate adaption" },
+ { 0x08, "V.120 rate adaption" },
+ { 0x09, "X.31 HDLC flag stuffing" },
+ { 0, NULL },
+};
+
+static const value_string q933_l1_user_rate_vals[] = {
+ { 0x00, "Rate indicated by E-bits" },
+ { 0x01, "0.6 kbit/s" },
+ { 0x02, "1.2 kbit/s" },
+ { 0x03, "2.4 kbit/s" },
+ { 0x04, "3.6 kbit/s" },
+ { 0x05, "4.8 kbit/s" },
+ { 0x06, "7.2 kbit/s" },
+ { 0x07, "8 kbit/s" },
+ { 0x08, "9.6 kbit/s" },
+ { 0x09, "14.4 kbit/s" },
+ { 0x0A, "16 kbit/s" },
+ { 0x0B, "19.2 kbit/s" },
+ { 0x0C, "32 kbit/s" },
+ { 0x0E, "48 kbit/s" },
+ { 0x0F, "56 kbit/s" },
+ { 0x10, "64 kbit/s "},
+ { 0x15, "0.1345 kbit/s" },
+ { 0x16, "0.100 kbit/s" },
+ { 0x17, "0.075/1.2 kbit/s" },
+ { 0x18, "1.2/0.075 kbit/s" },
+ { 0x19, "0.050 kbit/s" },
+ { 0x1A, "0.075 kbit/s" },
+ { 0x1B, "0.110 kbit/s" },
+ { 0x1C, "0.150 kbit/s" },
+ { 0x1D, "0.200 kbit/s" },
+ { 0x1E, "0.300 kbit/s" },
+ { 0x1F, "12 kbit/s" },
+ { 0, NULL }
+};
+
+static const value_string q933_l1_stop_bits_vals[] = {
+ { 0x20, "1" },
+ { 0x40, "1.5" },
+ { 0x60, "2" },
+ { 0, NULL }
+};
+
+static const value_string q933_l1_data_bits_vals[] = {
+ { 0x08, "5" },
+ { 0x10, "7" },
+ { 0x18, "8" },
+ { 0, NULL }
+};
+
+static const value_string q933_l1_parity_vals[] = {
+ { 0x00, "Odd" },
+ { 0x02, "Even" },
+ { 0x03, "None" },
+ { 0x04, "Forced to 0" },
+ { 0x05, "Forced to 1" },
+ { 0, NULL }
+};
+
+#define Q933_UIL2_USER_SPEC 0x10
+
+static const value_string q933_uil2_vals[] = {
+ { 0x01, "Basic mode ISO 1745" },
+ { 0x06, "X.25, link level" },
+ { 0x07, "X.25 multilink" },
+ { 0x08, "T.71 Extended LAPB" },
+ { 0x09, "HDLC ARM" },
+ { 0x0A, "HDLC NRM" },
+ { 0x0B, "HDLC ABM" },
+ { 0x0C, "ISO 8802/2 LLC" },
+ { 0x0D, "X.75 Single Link Procedure" },
+ { 0x0E, "Q.922" },
+ { 0x0F, "Core aspects of Q.922" },
+ { Q933_UIL2_USER_SPEC, "User-specified" },
+ { 0x11, "ISO 7776 DTE-DTE operation" },
+ { 0, NULL }
+};
+
+static const value_string q933_address_inclusion_vals[] = {
+ { 0x01, "Address included" },
+ { 0x02, "Encapsulation of logical control frame" },
+ { 0, NULL }
+};
+
+static const value_string q933_mode_vals[] = {
+ { 0x20, "Normal mode" },
+ { 0x40, "Extended mode" },
+ { 0, NULL }
+};
+
+#define Q933_UIL3_X25_PL 0x06
+#define Q933_UIL3_ISO_8208 0x07 /* X.25-based */
+#define Q933_UIL3_X223 0x08 /* X.25-based */
+#define Q933_UIL3_TR_9577 0x0B
+#define Q933_UIL3_USER_SPEC 0x10
+
+static const value_string q933_uil3_vals[] = {
+ { Q933_UIL3_X25_PL, "X.25, packet layer" },
+ { Q933_UIL3_ISO_8208, "ISO/IEC 8208" },
+ { Q933_UIL3_X223, "X.223/ISO 8878" },
+ { 0x09, "ISO/IEC 8473" },
+ { 0x0A, "T.70" },
+ { Q933_UIL3_TR_9577, "ISO/IEC TR 9577" },
+ { Q933_UIL3_USER_SPEC, "User-specified" },
+ { 0, NULL }
+};
+
+static void
+dissect_q933_protocol_discriminator(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ unsigned int discriminator = tvb_get_guint8(tvb, offset);
+
+ if (discriminator == NLPID_Q_933) {
+ proto_tree_add_uint_format(tree, hf_q933_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Q.933");
+ } else if (discriminator == NLPID_Q_2931) {
+ proto_tree_add_uint_format(tree, hf_q933_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Q.2931");
+ } else if ((discriminator >= 16 && discriminator < 63)
+ || ((discriminator >= 80) && (discriminator < 254))) {
+ proto_tree_add_uint_format(tree, hf_q933_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Network layer or layer 3 protocol (0x%02X)",
+ discriminator);
+ } else if (discriminator >= 64 && discriminator <= 79) {
+ proto_tree_add_uint_format(tree, hf_q933_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: National use (0x%02X)",
+ discriminator);
+ } else {
+ proto_tree_add_uint_format(tree, hf_q933_discriminator,
+ tvb, offset, 1, discriminator,
+ "Protocol discriminator: Reserved (0x%02X)",
+ discriminator);
+ }
+}
+
+void
+dissect_q933_bearer_capability_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 coding_standard;
+ guint8 modem_type;
+ guint8 uil2_protocol;
+ guint8 uil3_protocol;
+ guint8 add_l3_info;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ if (coding_standard != Q933_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the bearer capability is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ proto_tree_add_uint(tree, hf_q933_coding_standard, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q933_extension_ind, tvb, offset, 1, octet);
+ return;
+ }
+ proto_tree_add_uint(tree, hf_q933_information_transfer_capability, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q933_coding_standard, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q933_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+
+ /*
+ * XXX - only in Low-layer compatibility information element.
+ */
+ if (!(octet & Q933_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Out-band negotiation %spossible",
+ (octet & 0x40) ? "" : "not ");
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_q933_transfer_mode, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q933_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0x60) == 0x20) {
+ /*
+ * Layer 1 information.
+ */
+ proto_tree_add_uint(tree, hf_q933_uil1, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q933_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q933_IE_VL_EXTENSION)
+ goto l1_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Layer 1 is %s",
+ (octet & 0x40) ? "Asynchronous" : "Synchronous");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User rate: %s",
+ val_to_str(octet & 0x1F, q933_l1_user_rate_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q933_IE_VL_EXTENSION)
+ goto l1_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Rate adaption header %sincluded",
+ (octet & 0x40) ? "" : "not ");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Multiple frame establishment %ssupported",
+ (octet & 0x20) ? "" : "not ");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s mode of operation",
+ (octet & 0x10) ? "Protocol sensitive" : "Bit transparent");
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q933_IE_VL_EXTENSION)
+ goto l1_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Stop bits: %s",
+ val_to_str(octet & 0x60, q933_l1_stop_bits_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Data bits: %s",
+ val_to_str(octet & 0x18, q933_l1_data_bits_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Parity: %s",
+ val_to_str(octet & 0x07, q933_l1_parity_vals,
+ "Unknown (0x%X)"));
+
+ if (octet & Q933_IE_VL_EXTENSION)
+ goto l1_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s duplex",
+ (octet & 0x40) ? "Full" : "Half");
+ modem_type = octet & 0x3F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Modem type: Network-specific rules 0x%02X", modem_type);
+ offset += 1;
+ len -= 1;
+ }
+l1_done:
+ ;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0x60) == 0x40) {
+ /*
+ * Layer 2 information.
+ */
+ uil2_protocol = octet & 0x1F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User information layer 2 protocol: %s",
+ val_to_str(uil2_protocol, q933_uil2_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ /*
+ * XXX - only in Low-layer compatibility information element.
+ */
+ if (octet & Q933_IE_VL_EXTENSION)
+ goto l2_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if (uil2_protocol == Q933_UIL2_USER_SPEC) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User-specified layer 2 protocol information: 0x%02X",
+ octet & 0x7F);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Address inclusion: %s",
+ val_to_str(octet & 0x03, q933_address_inclusion_vals,
+ "Unknown (0x%02X)"));
+ }
+ offset += 1;
+ len -= 1;
+ }
+l2_done:
+ ;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0x60) == 0x60) {
+ /*
+ * Layer 3 information.
+ */
+ uil3_protocol = octet & 0x1F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "User information layer 3 protocol: %s",
+ val_to_str(uil3_protocol, q933_uil3_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+
+ /*
+ * XXX - only in Low-layer compatibility information element.
+ */
+ if (octet & Q933_IE_VL_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ switch (uil3_protocol) {
+
+ case Q933_UIL3_X25_PL:
+ case Q933_UIL3_ISO_8208:
+ case Q933_UIL3_X223:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Mode: %s",
+ val_to_str(octet & 0x60, q933_mode_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q933_IE_VL_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Default packet size: %u", octet & 0x0F);
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q933_IE_VL_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Packet window size: %u", octet & 0x7F);
+ offset += 1;
+ len -= 1;
+ break;
+
+ case Q933_UIL3_USER_SPEC:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Default packet size: %u octets",
+ 1 << (octet & 0x0F));
+ offset += 1;
+ len -= 1;
+ break;
+
+ case Q933_UIL3_TR_9577:
+ add_l3_info = (octet & 0x0F) << 4;
+ if (octet & Q933_IE_VL_EXTENSION)
+ goto l3_done;
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset + 1);
+ add_l3_info |= (octet & 0x0F);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Additional layer 3 protocol information: %s",
+ val_to_str(add_l3_info, nlpid_vals,
+ "Unknown (0x%02X)"));
+ offset += 2;
+ len -= 2;
+ break;
+ }
+ }
+l3_done:
+ ;
+}
+
+/*
+ * Dissect a Cause information element.
+ */
+
+
+const value_string q933_cause_location_vals[] = {
+ { 0x00, "User (U)" },
+ { 0x01, "Private network serving the local user (LPN)" },
+ { 0x02, "Public network serving the local user (LN)" },
+ { 0x03, "Transit network (TN)" },
+ { 0x04, "Public network serving the remote user (RLN)" },
+ { 0x05, "Private network serving the remote user (RPN)" },
+ { 0x07, "International network (INTL)" },
+ { 0x0A, "Network beyond interworking point (BI)" },
+ { 0, NULL }
+};
+
+static const value_string q933_cause_recommendation_vals[] = {
+ { 0x00, "Q.933" },
+ { 0x03, "X.21" },
+ { 0x04, "X.25" },
+ { 0x05, "Q.1031/Q.1051" },
+ { 0, NULL }
+};
+
+/*
+ * Cause codes for Cause.
+ */
+#define Q933_CAUSE_UNALLOC_NUMBER 0x01
+#define Q933_CAUSE_NO_ROUTE_TO_DEST 0x03
+#define Q933_CAUSE_CALL_REJECTED 0x15
+#define Q933_CAUSE_NUMBER_CHANGED 0x16
+#define Q933_CAUSE_ACCESS_INFO_DISC 0x2B
+#define Q933_CAUSE_QOS_UNAVAILABLE 0x31
+#define Q933_CAUSE_CHAN_NONEXISTENT 0x52
+#define Q933_CAUSE_INCOMPATIBLE_DEST 0x58
+#define Q933_CAUSE_MAND_IE_MISSING 0x60
+#define Q933_CAUSE_MT_NONEX_OR_UNIMPL 0x61
+#define Q933_CAUSE_IE_NONEX_OR_UNIMPL 0x63
+#define Q933_CAUSE_INVALID_IE_CONTENTS 0x64
+#define Q933_CAUSE_MSG_INCOMPAT_W_CS 0x65
+#define Q933_CAUSE_REC_TIMER_EXP 0x66
+
+const value_string q933_cause_code_vals[] = {
+ { 0x00, "Valid cause code not yet received" },
+ { Q933_CAUSE_UNALLOC_NUMBER, "Unallocated (unassigned) number" },
+ { 0x02, "No route to specified transit network" },
+ { Q933_CAUSE_NO_ROUTE_TO_DEST, "No route to destination" },
+ { 0x04, "Send special information tone" },
+ { 0x05, "Misdialled trunk prefix" },
+ { 0x06, "Channel unacceptable" },
+ { 0x07, "Call awarded and being delivered in an established channel" },
+ { 0x08, "Prefix 0 dialed but not allowed" },
+ /* Q.850 - "Preemption" */
+ { 0x09, "Prefix 1 dialed but not allowed" },
+ /* Q.850 - "Preemption - circuit reserved for reuse" */
+ { 0x0A, "Prefix 1 dialed but not required" },
+ { 0x0B, "More digits received than allowed, call is proceeding" },
+ { 0x0E, "QoR: ported number" },
+ { 0x10, "Normal call clearing" },
+ { 0x11, "User busy" },
+ { 0x12, "No user responding" },
+ { 0x13, "No answer from user (user alerted)" },
+ { 0x14, "Subscriber absent" },
+ { Q933_CAUSE_CALL_REJECTED, "Call rejected" },
+ { Q933_CAUSE_NUMBER_CHANGED, "Number changed" },
+ { 0x17, "Reverse charging rejected" },
+ /* Q.850 - "Redirection to new destination" */
+ { 0x18, "Call suspended" },
+ /* Q.850 Amendment 1 - "Call rejected due to feature at the destination" */
+ { 0x19, "Call resumed" },
+ /* Q.850 - "Exchange routing error */
+ { 0x1A, "Non-selected user clearing" },
+ { 0x1B, "Destination out of order" },
+ { 0x1C, "Invalid number format (incomplete number)" },
+ { 0x1D, "Facility rejected" },
+ { 0x1E, "Response to STATUS ENQUIRY" },
+ { 0x1F, "Normal unspecified" },
+ { 0x21, "Circuit out of order" },
+ { 0x22, "No circuit/channel available" },
+ { 0x23, "Destination unattainable" },
+ { 0x25, "Degraded service" },
+ { 0x26, "Network out of order" },
+ { 0x27, "Transit delay range cannot be achieved" },
+ /* Q.850 - "Permanent frame mode connection out of service" */
+ { 0x28, "Throughput range cannot be achieved" },
+ /* Q.850 - "Permanent frame mode connection operational" */
+ { 0x29, "Temporary failure" },
+ { 0x2A, "Switching equipment congestion" },
+ { Q933_CAUSE_ACCESS_INFO_DISC, "Access information discarded" },
+ { 0x2C, "Requested circuit/channel not available" },
+ { 0x2D, "Pre-empted" },
+ { 0x2E, "Precedence call blocked" },
+ { 0x2F, "Resources unavailable, unspecified" },
+ { Q933_CAUSE_QOS_UNAVAILABLE, "Quality of service unavailable" },
+ { 0x32, "Requested facility not subscribed" },
+ { 0x33, "Reverse charging not allowed" },
+ { 0x34, "Outgoing calls barred" },
+ { 0x35, "Outgoing calls barred within CUG" },
+ { 0x36, "Incoming calls barred" },
+ { 0x37, "Incoming calls barred within CUG" },
+ { 0x38, "Call waiting not subscribed" },
+ { 0x39, "Bearer capability not authorized" },
+ { 0x3A, "Bearer capability not presently available" },
+ { 0x3E, "Inconsistency in designated outgoing access information and subscriber class" },
+ { 0x3F, "Service or option not available, unspecified" },
+ { 0x41, "Bearer capability not implemented" },
+ { 0x42, "Channel type not implemented" },
+ { 0x43, "Transit network selection not implemented" },
+ { 0x44, "Message not implemented" },
+ { 0x45, "Requested facility not implemented" },
+ { 0x46, "Only restricted digital information bearer capability is available" },
+ { 0x4F, "Service or option not implemented, unspecified" },
+ { 0x51, "Invalid call reference value" },
+ { Q933_CAUSE_CHAN_NONEXISTENT, "Identified channel does not exist" },
+ { 0x53, "Call identity does not exist for suspended call" },
+ { 0x54, "Call identity in use" },
+ { 0x55, "No call suspended" },
+ { 0x56, "Call having the requested call identity has been cleared" },
+ { 0x57, "Called user not member of CUG" },
+ { Q933_CAUSE_INCOMPATIBLE_DEST, "Incompatible destination" },
+ { 0x59, "Non-existent abbreviated address entry" },
+ { 0x5A, "Destination address missing, and direct call not subscribed" },
+ /* Q.850 - "Non-existent CUG" */
+ { 0x5B, "Invalid transit network selection (national use)" },
+ { 0x5C, "Invalid facility parameter" },
+ { 0x5D, "Mandatory information element is missing" },
+ { 0x5F, "Invalid message, unspecified" },
+ { Q933_CAUSE_MAND_IE_MISSING, "Mandatory information element is missing" },
+ { Q933_CAUSE_MT_NONEX_OR_UNIMPL,"Message type non-existent or not implemented" },
+ { 0x62, "Message not compatible with call state or message type non-existent or not implemented" },
+ { Q933_CAUSE_IE_NONEX_OR_UNIMPL,"Information element nonexistant or not implemented" },
+ { Q933_CAUSE_INVALID_IE_CONTENTS,"Invalid information element contents" },
+ { Q933_CAUSE_MSG_INCOMPAT_W_CS, "Message not compatible with call state" },
+ { Q933_CAUSE_REC_TIMER_EXP, "Recovery on timer expiry" },
+ { 0x67, "Parameter non-existent or not implemented - passed on" },
+ { 0x6E, "Message with unrecognized parameter discarded" },
+ { 0x6F, "Protocol error, unspecified" },
+ { 0x7F, "Internetworking, unspecified" },
+ { 0, NULL }
+};
+
+static const value_string q933_cause_condition_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Permanent" },
+ { 0x02, "Transient" },
+ { 0x00, NULL }
+};
+
+#define Q933_REJ_USER_SPECIFIC 0x00
+#define Q933_REJ_IE_MISSING 0x04
+#define Q933_REJ_IE_INSUFFICIENT 0x08
+
+static const value_string q933_rejection_reason_vals[] = {
+ { 0x00, "User specific" },
+ { 0x04, "Information element missing" },
+ { 0x08, "Information element contents are not sufficient" },
+ { 0x00, NULL }
+};
+
+void
+dissect_q933_cause_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, int hf_cause_value)
+{
+ guint8 octet;
+ guint8 cause_value;
+ guint8 coding_standard;
+ guint8 rejection_reason;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ if (coding_standard != Q933_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the cause is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_uint(tree, hf_q933_coding_standard, tvb, offset, 1, octet);
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ proto_tree_add_uint(tree, hf_q933_cause_location, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q933_coding_standard, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q933_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+
+ if (!(octet & Q933_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Recommendation: %s",
+ val_to_str(octet & 0x7F, q933_cause_recommendation_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_boolean(tree, hf_q933_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ cause_value = octet & 0x7F;
+ proto_tree_add_uint(tree, hf_cause_value, tvb, offset, 1, cause_value);
+ proto_tree_add_boolean(tree, hf_q933_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (cause_value) {
+
+ case Q933_CAUSE_UNALLOC_NUMBER:
+ case Q933_CAUSE_NO_ROUTE_TO_DEST:
+ case Q933_CAUSE_QOS_UNAVAILABLE:
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Network service: %s",
+ (octet & 0x80) ? "User" : "Provider");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s",
+ (octet & 0x40) ? "Abnormal" : "Normal");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Condition: %s",
+ val_to_str(octet & 0x03, q933_cause_condition_vals,
+ "Unknown (0x%X)"));
+ break;
+
+ case Q933_CAUSE_CALL_REJECTED:
+ rejection_reason = octet & 0x7C;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Rejection reason: %s",
+ val_to_str(octet & 0x7C, q933_rejection_reason_vals,
+ "Unknown (0x%X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Condition: %s",
+ val_to_str(octet & 0x03, q933_cause_condition_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (rejection_reason) {
+
+ case Q933_REJ_USER_SPECIFIC:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "User specific diagnostic: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+
+ case Q933_REJ_IE_MISSING:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Missing information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q933_info_element_vals0,
+ "Unknown (0x%02X)"));
+ break;
+
+ case Q933_REJ_IE_INSUFFICIENT:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Insufficient information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q933_info_element_vals0,
+ "Unknown (0x%02X)"));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Diagnostic: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+ }
+ break;
+
+ case Q933_CAUSE_ACCESS_INFO_DISC:
+ case Q933_CAUSE_INCOMPATIBLE_DEST:
+ case Q933_CAUSE_MAND_IE_MISSING:
+ case Q933_CAUSE_IE_NONEX_OR_UNIMPL:
+ case Q933_CAUSE_INVALID_IE_CONTENTS:
+ do {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Information element: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q933_info_element_vals0,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+ } while (len != 0);
+ break;
+
+ case Q933_CAUSE_MT_NONEX_OR_UNIMPL:
+ case Q933_CAUSE_MSG_INCOMPAT_W_CS:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Message type: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), q933_message_type_vals,
+ "Unknown (0x%02X)"));
+ break;
+
+ case Q933_CAUSE_REC_TIMER_EXP:
+ if (len < 3)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 3,
+ "Timer: %.3s", tvb_get_ptr(tvb, offset, 3));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "Diagnostics: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ }
+}
+
+/*
+ * Dissect a Call state information element.
+ */
+static const value_string q933_call_state_vals[] = {
+ { 0x00, "Null" },
+ { 0x01, "Call initiated" },
+ { 0x02, "Overlap sending" },
+ { 0x03, "Outgoing call proceeding" },
+ { 0x04, "Call delivered" },
+ { 0x06, "Call present" },
+ { 0x07, "Call received" },
+ { 0x08, "Connect request" },
+ { 0x09, "Incoming call proceeding" },
+ { 0x0A, "Active" },
+ { 0x0B, "Disconnect request" },
+ { 0x0C, "Disconnect indication" },
+ { 0x0F, "Suspend request" },
+ { 0x12, "Resume request" },
+ { 0x13, "Release request" },
+ { 0x16, "Call abort"},
+ { 0x19, "Overlap receiving" },
+ { 0x3D, "Restart request" },
+ { 0x3E, "Restart" },
+ { 0, NULL }
+};
+
+static void
+dissect_q933_call_state_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 coding_standard;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ proto_tree_add_uint(tree, hf_q933_coding_standard, tvb, offset, 1, octet);
+ if (coding_standard != Q933_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the call state is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Call state: %s",
+ val_to_str(octet & 0x3F, q933_call_state_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a Channel identification information element.
+ */
+#define Q933_INTERFACE_IDENTIFIED 0x40
+#define Q933_NOT_BASIC_CHANNEL 0x20
+
+static const value_string q933_basic_channel_selection_vals[] = {
+ { 0x00, "No channel" },
+ { 0x01, "B1 channel" },
+ { 0x02, "B2 channel" },
+ { 0x03, "Any channel" },
+ { 0, NULL }
+};
+
+static const value_string q933_not_basic_channel_selection_vals[] = {
+ { 0x00, "No channel" },
+ { 0x01, "Channel indicated in following octets" },
+ { 0x03, "Any channel" },
+ { 0, NULL }
+};
+
+#define Q933_IS_SLOT_MAP 0x10
+
+static const value_string q933_element_type_vals[] = {
+ { 0x03, "B-channel units" },
+ { 0x06, "H0-channel units" },
+ { 0x08, "H11-channel units" },
+ { 0x09, "H12-channel units" },
+ { 0, NULL }
+};
+
+static void
+dissect_q933_channel_identification_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ int identifier_offset;
+ int identifier_len;
+ guint8 coding_standard;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Interface %s identified",
+ (octet & Q933_INTERFACE_IDENTIFIED) ? "explicitly" : "implicitly");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s interface",
+ (octet & Q933_NOT_BASIC_CHANNEL) ? "Not basic" : "Basic");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Indicated channel is %s",
+ (octet & 0x08) ? "required" : "preferred");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Indicated channel is %sthe D-channel",
+ (octet & 0x04) ? "" : "not ");
+ if (octet & Q933_NOT_BASIC_CHANNEL) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Channel selection: %s",
+ val_to_str(octet & 0x03, q933_not_basic_channel_selection_vals,
+ "Unknown (0x%X)"));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Channel selection: %s",
+ val_to_str(octet & 0x03, q933_basic_channel_selection_vals,
+ NULL));
+ }
+ offset += 1;
+ len -= 1;
+
+ if (octet & Q933_INTERFACE_IDENTIFIED) {
+ identifier_offset = offset;
+ identifier_len = 0;
+ do {
+ if (len == 0)
+ break;
+ octet = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ len -= 1;
+ identifier_len++;
+ } while (!(octet & Q933_IE_VL_EXTENSION));
+
+ /*
+ * XXX - do we want to strip off the 8th bit on the
+ * last octet of the interface identifier?
+ */
+ if (identifier_len != 0) {
+ proto_tree_add_text(tree, tvb, identifier_offset,
+ identifier_len, "Interface identifier: %s",
+ bytes_to_str(
+ tvb_get_ptr(tvb, identifier_offset, identifier_len),
+ identifier_len));
+ }
+ }
+
+ if (octet & Q933_NOT_BASIC_CHANNEL) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ proto_tree_add_uint(tree, hf_q933_coding_standard, tvb, offset, 1, octet);
+ if (coding_standard != Q933_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the channel identifier is
+ * encoded, so just dump it as data and be done
+ * with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Channel is indicated by %s",
+ (octet & Q933_IS_SLOT_MAP) ? "slot map" : "number");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s type: %s",
+ (octet & Q933_IS_SLOT_MAP) ? "Map element" : "Channel",
+ val_to_str(octet & 0x0F, q933_element_type_vals,
+ "Unknown (0x%02X)"));
+
+ /*
+ * XXX - dump the channel number or slot map.
+ */
+ }
+}
+
+/*
+ * Dissect a Progress indicator information element.
+ */
+static const value_string q933_progress_description_vals[] = {
+ { 0x01, "Call is not end-to-end ISDN - progress information available in-band" },
+ { 0x02, "Destination address is non-ISDN" },
+ { 0x03, "Origination address is non-ISDN" },
+ { 0x04, "Call has returned to the ISDN" },
+ { 0x05, "Interworking has occurred and has resulted in a telecommunications service change" },
+ { 0x08, "In-band information or an appropriate pattern is now available" },
+ { 0, NULL }
+};
+
+void
+dissect_q933_progress_indicator_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 coding_standard;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ proto_tree_add_uint(tree, hf_q933_coding_standard, tvb, offset, 1, octet);
+ if (coding_standard != Q933_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the progress indicator is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Location: %s",
+ val_to_str(octet & 0x0F, q933_cause_location_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Progress description: %s",
+ val_to_str(octet & 0x7F, q933_progress_description_vals,
+ "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a Network-specific facilities or Transit network selection
+ * information element.
+ */
+static const value_string q933_netid_type_vals[] = {
+ { 0x00, "User specified" },
+ { 0x20, "National network identification" },
+ { 0x30, "International network identification" },
+ { 0, NULL }
+};
+
+static const value_string q933_netid_plan_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Carrier Identification Code" },
+ { 0x03, "X.121 data network identification code" },
+ { 0, NULL }
+};
+
+static void
+dissect_q933_ns_facilities_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ int netid_len;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ netid_len = octet & 0x7F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Network identification length: %u",
+ netid_len);
+ offset += 1;
+ len -= 1;
+ if (netid_len != 0) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Type of network identification: %s",
+ val_to_str(octet & 0x70, q933_netid_type_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Network identification plan: %s",
+ val_to_str(octet & 0x0F, q933_netid_plan_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+ netid_len--;
+
+ if (len == 0)
+ return;
+ if (netid_len > len)
+ netid_len = len;
+ if (netid_len != 0) {
+ proto_tree_add_text(tree, tvb, offset, netid_len,
+ "Network identification: %s",
+ tvb_format_text(tvb, offset, netid_len));
+ offset += netid_len;
+ len -= netid_len;
+ }
+ }
+
+ /*
+ * Whatever is left is the network-specific facility
+ * specification.
+ */
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Network-specific facility specification: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+}
+
+static int
+dissect_q933_guint16_value(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, char *label)
+{
+ guint8 octet;
+ guint16 value;
+ int value_len;
+
+ value_len = 0;
+
+ octet = tvb_get_guint8(tvb, offset);
+ if (octet & Q933_IE_VL_EXTENSION) {
+ /*
+ * Only one octet long - error.
+ */
+ goto bad_length;
+ }
+ value = (octet & 0x3) << 14;
+ offset += 1;
+ len -= 1;
+ value_len++;
+
+ if (len == 0) {
+ /*
+ * We've reached the end of the information element - error.
+ */
+ goto past_end;
+ }
+ octet = tvb_get_guint8(tvb, offset);
+ if (octet & Q933_IE_VL_EXTENSION) {
+ /*
+ * Only two octets long - error.
+ */
+ goto bad_length;
+ }
+ value |= (octet & 0x7F) << 7;
+ offset += 1;
+ len -= 1;
+ value_len++;
+
+ if (len == 0) {
+ /*
+ * We've reached the end of the information element - error.
+ */
+ goto past_end;
+ }
+ octet = tvb_get_guint8(tvb, offset);
+ if (!(octet & Q933_IE_VL_EXTENSION)) {
+ /*
+ * More than three octets long - error.
+ */
+ goto bad_length;
+ }
+ value |= (octet & 0x7F);
+ offset += 1;
+ len -= 1;
+ value_len++;
+
+ proto_tree_add_text(tree, tvb, offset, value_len, "%s: %u ms", label,
+ value);
+ return value_len;
+
+past_end:
+ proto_tree_add_text(tree, tvb, offset, len,
+ "%s goes past end of information element", label);
+ return -1;
+
+bad_length:
+ proto_tree_add_text(tree, tvb, offset, len, "%s isn't 3 octets long",
+ label);
+ return -1;
+}
+
+/*
+ * Dissect an End-to-end transit delay information element.
+ */
+static void
+dissect_q933_e2e_transit_delay_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ int value_len;
+
+ if (len == 0)
+ return;
+ value_len = dissect_q933_guint16_value(tvb, offset, len, tree,
+ "Cumulative transit delay");
+ if (value_len < 0)
+ return; /* error */
+ offset += value_len;
+ len -= value_len;
+
+ if (len == 0)
+ return;
+ value_len = dissect_q933_guint16_value(tvb, offset, len, tree,
+ "Requested end-to-end transit delay");
+ if (value_len < 0)
+ return; /* error */
+ offset += value_len;
+ len -= value_len;
+
+ if (len == 0)
+ return;
+ value_len = dissect_q933_guint16_value(tvb, offset, len, tree,
+ "Maximum end-to-end transit delay");
+}
+
+/*
+ * Dissect a Transit delay selection and indication information element.
+ */
+static void
+dissect_q933_td_selection_and_int_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len == 0)
+ return;
+ dissect_q933_guint16_value(tvb, offset, len, tree,
+ "Transit delay");
+}
+
+static void
+dissect_q933_pl_binary_parameters_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s",
+ (octet & 0x04) ? "No request/request denied" :
+ "Request indicated/request accepted");
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s confirmation",
+ (octet & 0x02) ? "Link-by-link" : "End-to-end");
+}
+
+/*
+ * Dissect a Reverse charging indication information element.
+ */
+static const value_string q933_reverse_charging_indication_vals[] = {
+ { 0x01, "Reverse charging requested" },
+ { 0, NULL }
+};
+
+static void
+dissect_q933_reverse_charge_ind_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Reverse charging indication: %s",
+ val_to_str(tvb_get_guint8(tvb, offset) & 0x07,
+ q933_reverse_charging_indication_vals, "Unknown (0x%02X)"));
+}
+
+/*
+ * Dissect a (phone) number information element.
+ */
+static const value_string q933_number_type_vals[] = {
+ { 0x0, "Unknown" },
+ { 0x1, "International number" },
+ { 0x2, "National number" },
+ { 0x3, "Network specific number" },
+ { 0x4, "Subscriber number" },
+ { 0x6, "Abbreviated number" },
+ { 0, NULL }
+};
+
+static const value_string q933_numbering_plan_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "E.164 ISDN/telephony numbering" },
+ { 0x03, "X.121 data numbering" },
+ { 0x04, "F.69 Telex numbering" },
+ { 0x08, "National standard numbering" },
+ { 0x09, "Private numbering" },
+ { 0, NULL }
+};
+
+static const value_string q933_presentation_indicator_vals[] = {
+ { 0x00, "Presentation allowed" },
+ { 0x01, "Presentation restricted" },
+ { 0x02, "Number not available due to interworking" },
+ { 0, NULL }
+};
+
+static const value_string q933_screening_indicator_vals[] = {
+ { 0x00, "User-provided, not screened" },
+ { 0x01, "User-provided, verified and passed" },
+ { 0x02, "User-provided, verified and failed" },
+ { 0x03, "Network-provided" },
+ { 0, NULL }
+};
+
+static const value_string q933_redirection_reason_vals[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Call forwarding busy or called DTE busy" },
+ { 0x02, "Call forwarding no reply" },
+ { 0x04, "Call deflection" },
+ { 0x09, "Called DTE out of order" },
+ { 0x0A, "Call forwarding by the called DTE" },
+ { 0x0F, "Call forwarding unconditional or systematic call redirection" },
+ { 0, NULL }
+};
+
+static void
+dissect_q933_number_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree, int hfindex)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_q933_numbering_plan, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q933_number_type, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q933_extension_ind, tvb, offset, 1, octet);
+
+ offset += 1;
+ len -= 1;
+
+ if (!(octet & Q933_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_q933_screening_ind, tvb, offset, 1, octet);
+ proto_tree_add_uint(tree, hf_q933_presentation_ind, tvb, offset, 1, octet);
+ proto_tree_add_boolean(tree, hf_q933_extension_ind, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+ }
+
+ /*
+ * XXX - only in a Redirecting number information element.
+ */
+ if (!(octet & Q933_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Reason for redirection: %s",
+ val_to_str(octet & 0x0F, q933_redirection_reason_vals,
+ "Unknown (0x%X)"));
+ offset += 1;
+ len -= 1;
+ }
+
+ if (len == 0)
+ return;
+ proto_tree_add_item(tree, hfindex, tvb, offset, len, FALSE);
+}
+
+/*
+ * Dissect a party subaddress information element.
+ */
+static const value_string q933_subaddress_type_vals[] = {
+ { 0x00, "X.213/ISO 8348 Add.2 NSAP" },
+ { 0x20, "User-specified" },
+ { 0, NULL }
+};
+
+static const value_string q933_odd_even_indicator_vals[] = {
+ { 0x00, "Even number of address signals" },
+ { 0x10, "Odd number of address signals" },
+ { 0, NULL }
+};
+
+static void
+dissect_q933_party_subaddr_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Type of subaddress: %s",
+ val_to_str(octet & 0x70, q933_subaddress_type_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Odd/even indicator: %s",
+ val_to_str(octet & 0x10, q933_odd_even_indicator_vals,
+ NULL));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ proto_tree_add_text(tree, tvb, offset, len, "Subaddress: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+}
+
+/*
+ * Dissect a High-layer compatibility information element.
+ */
+#define Q933_AUDIOVISUAL 0x60
+static const value_string q933_high_layer_characteristics_vals[] = {
+ { 0x01, "Telephony" },
+ { 0x04, "F.182 Facsimile Group 2/3" },
+ { 0x21, "F.184 Facsimile Group 4 Class I" },
+ { 0x24, "F.230 Teletex, basic and mixed mode, and F.184 Facsimile Group 4, Classes II and III" },
+ { 0x28, "F.220 Teletex, basic and processable mode" },
+ { 0x31, "F.200 Teletex, basic mode" },
+ { 0x32, "F.300 and T.102 syntax-based Videotex" },
+ { 0x33, "F.300 and T.101 international Videotex interworking" },
+ { 0x35, "F.60 Telex" },
+ { 0x38, "X.400 Message Handling Systems" },
+ { 0x41, "X.200 OSI application" },
+ { 0x42, "FTAM application" },
+ { 0x5E, "Reserved for maintenance" },
+ { 0x5F, "Reserved for management" },
+ { Q933_AUDIOVISUAL, "F.720/F.821 and F.731 Profile 1a videotelephony" },
+ { 0x61, "F.702 and F.731 Profile 1b videoconferencing" },
+ { 0x62, "F.702 and F.731 audiographic conferencing" },
+ { 0, NULL }
+};
+
+static const value_string q933_audiovisual_characteristics_vals[] = {
+ { 0x01, "Capability set of initial channel of H.221" },
+ { 0x02, "Capability set of subsequent channel of H.221" },
+ { 0x21, "Capability set of initial channel of an active 3.1kHz audio or speech call" },
+ { 0x00, NULL }
+};
+
+void
+dissect_q933_high_layer_compat_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+ guint8 coding_standard;
+ guint8 characteristics;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ coding_standard = octet & 0x60;
+ proto_tree_add_uint(tree, hf_q933_coding_standard, tvb, offset, 1, octet);
+ offset += 1;
+ len -= 1;
+ if (coding_standard != Q933_ITU_STANDARDIZED_CODING) {
+ /*
+ * We don't know how the call state is encoded,
+ * so just dump it as data and be done with it.
+ */
+ proto_tree_add_text(tree, tvb, offset,
+ len, "Data: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ return;
+ }
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ characteristics = octet & 0x7F;
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "High layer characteristics identification: %s",
+ val_to_str(characteristics, q933_high_layer_characteristics_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+ len -= 1;
+
+ if (!(octet & Q933_IE_VL_EXTENSION)) {
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ if (characteristics == Q933_AUDIOVISUAL) {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Extended audiovisual characteristics identification: %s",
+ val_to_str(octet & 0x7F,
+ q933_audiovisual_characteristics_vals,
+ "Unknown (0x%02X)"));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Extended high layer characteristics identification: %s",
+ val_to_str(octet & 0x7F,
+ q933_high_layer_characteristics_vals,
+ "Unknown (0x%02X)"));
+ }
+ }
+}
+
+
+/*
+ * Dissect a User-user information element.
+ */
+#define Q933_PROTOCOL_DISCRIMINATOR_IA5 0x04
+#define Q933_PROTOCOL_DISCRIMINATOR_ASN1 0x05
+
+static const value_string q933_protocol_discriminator_vals[] = {
+ { 0x00, "User-specific protocol" },
+ { 0x01, "OSI high layer protocols" },
+ { 0x02, "X.244" },
+ { Q933_PROTOCOL_DISCRIMINATOR_IA5, "IA5 characters" },
+ { Q933_PROTOCOL_DISCRIMINATOR_ASN1, "X.208 and X.209 coded user information" },
+ { 0x07, "V.120 rate adaption" },
+ { 0x08, "Q.933/I.451 user-network call control messages" },
+ { 0, NULL }
+};
+
+void
+dissect_q933_user_user_ie(tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 octet;
+
+ if (len == 0)
+ return;
+ octet = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Protocol discriminator: %s",
+ val_to_str(octet, q933_protocol_discriminator_vals,
+ "Unknown (0x%02x)"));
+ offset += 1;
+ len -= 1;
+
+ if (len == 0)
+ return;
+ switch (octet) {
+
+ case Q933_PROTOCOL_DISCRIMINATOR_IA5:
+ proto_tree_add_text(tree, tvb, offset, len, "User information: %s",
+ tvb_format_text(tvb, offset, len));
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, len, "User information: %s",
+ tvb_bytes_to_str(tvb, offset, len));
+ break;
+ }
+}
+
+/*
+ * Dissect information elements consisting of ASCII^H^H^H^H^HIA5 text.
+ */
+static void
+dissect_q933_ia5_ie(tvbuff_t *tvb, int offset, int len, proto_tree *tree,
+ char *label)
+{
+ if (len != 0) {
+ proto_tree_add_text(tree, tvb, offset, len, "%s: %s", label,
+ tvb_format_text(tvb, offset, len));
+ }
+}
+
+static const value_string q933_codeset_vals[] = {
+ { 0x00, "Q.933 information elements" },
+ { 0x04, "Information elements for ISO/IEC use" },
+ { 0x05, "Information elements for national use" },
+ { 0x06, "Information elements specific to the local network" },
+ { 0x07, "User-specific information elements" },
+ { 0x00, NULL },
+};
+
+static void
+dissect_q933(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *q933_tree = NULL;
+ proto_item *ti;
+ proto_tree *ie_tree = NULL;
+ guint8 call_ref_len;
+ guint8 call_ref[15];
+ guint8 message_type;
+ guint8 info_element;
+ guint16 info_element_len;
+ int codeset, locked_codeset;
+ gboolean non_locking_shift;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Q.933");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_q933, tvb, offset, -1,
+ FALSE);
+ q933_tree = proto_item_add_subtree(ti, ett_q933);
+
+ dissect_q933_protocol_discriminator(tvb, offset, q933_tree);
+ }
+ offset += 1;
+ call_ref_len = tvb_get_guint8(tvb, offset) & 0xF; /* XXX - do as a bit field? */
+ if (q933_tree != NULL)
+ proto_tree_add_uint(q933_tree, hf_q933_call_ref_len, tvb, offset, 1, call_ref_len);
+ offset += 1;
+ if (call_ref_len != 0) {
+ tvb_memcpy(tvb, call_ref, offset, call_ref_len);
+ if (q933_tree != NULL) {
+ proto_tree_add_boolean(q933_tree, hf_q933_call_ref_flag,
+ tvb, offset, 1, (call_ref[0] & 0x80) != 0);
+ call_ref[0] &= 0x7F;
+ proto_tree_add_bytes(q933_tree, hf_q933_call_ref,
+ tvb, offset, call_ref_len, call_ref);
+ }
+ offset += call_ref_len;
+ }
+ message_type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(message_type, q933_message_type_vals,
+ "Unknown message type (0x%02X)"));
+ }
+ if (q933_tree != NULL)
+ proto_tree_add_uint(q933_tree, hf_q933_message_type, tvb, offset, 1, message_type);
+ offset += 1;
+
+ /*
+ * And now for the information elements....
+ */
+ codeset = locked_codeset = 0; /* start out in codeset 0 */
+ non_locking_shift = TRUE;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ info_element = tvb_get_guint8(tvb, offset);
+
+ /* Check for the codeset shift */
+ if ((info_element & Q933_IE_SO_MASK) &&
+ ((info_element & Q933_IE_SO_IDENTIFIER_MASK) == Q933_IE_SHIFT)) {
+ non_locking_shift = info_element & Q933_IE_SHIFT_NON_LOCKING;
+ codeset = info_element & Q933_IE_SHIFT_CODESET;
+ if (!non_locking_shift)
+ locked_codeset = codeset;
+ if (q933_tree != NULL) {
+ proto_tree_add_text(q933_tree, tvb, offset, 1,
+ "%s shift to codeset %u: %s",
+ (non_locking_shift ? "Non-locking" : "Locking"),
+ codeset,
+ val_to_str(codeset, q933_codeset_vals,
+ "Unknown (0x%02X)"));
+ }
+ offset += 1;
+ continue;
+ }
+
+ /*
+ * Check for the single-octet IEs.
+ */
+ if (info_element & Q933_IE_SO_MASK) {
+ switch ((codeset << 8) | (info_element & Q933_IE_SO_IDENTIFIER_MASK)) {
+
+ case CS0 | Q933_IE_REPEAT_INDICATOR:
+ if (q933_tree != NULL) {
+ proto_tree_add_text(q933_tree, tvb, offset, 1,
+ "Repeat indicator: %s",
+ val_to_str(info_element & Q933_IE_SO_IE_MASK,
+ q933_repeat_indication_vals,
+ "Unknown (0x%X)"));
+ }
+ break;
+
+ default:
+ if (q933_tree != NULL) {
+ proto_tree_add_text(q933_tree, tvb, offset, 1,
+ "Unknown information element (0x%02X)",
+ info_element);
+ }
+ break;
+ }
+ offset += 1;
+ codeset = locked_codeset;
+ continue;
+ }
+
+ /*
+ * Variable-length IE.
+ */
+ info_element_len = tvb_get_guint8(tvb, offset + 1);
+ if (q933_tree != NULL) {
+ ti = proto_tree_add_text(q933_tree, tvb, offset,
+ 1+1+info_element_len, "%s",
+ val_to_str(info_element, q933_info_element_vals[codeset],
+ "Unknown information element (0x%02X)"));
+ ie_tree = proto_item_add_subtree(ti, ett_q933_ie);
+ proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "Information element: %s",
+ val_to_str(info_element, q933_info_element_vals[codeset],
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(ie_tree, tvb, offset + 1, 1,
+ "Length: %u", info_element_len);
+
+ switch ((codeset << 8) | info_element) {
+
+ case CS0 | Q933_IE_SEGMENTED_MESSAGE:
+ dissect_q933_segmented_message_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_BEARER_CAPABILITY:
+ case CS0 | Q933_IE_LOW_LAYER_COMPAT:
+ dissect_q933_bearer_capability_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_CAUSE:
+ dissect_q933_cause_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree,
+ hf_q933_cause_value);
+ break;
+
+ case CS0 | Q933_IE_CALL_STATE:
+ dissect_q933_call_state_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_CHANNEL_IDENTIFICATION:
+ dissect_q933_channel_identification_ie(
+ tvb, offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_PROGRESS_INDICATOR:
+ dissect_q933_progress_indicator_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_NETWORK_SPECIFIC_FACIL:
+ case CS0 | Q933_IE_TRANSIT_NETWORK_SEL:
+ dissect_q933_ns_facilities_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_DISPLAY:
+ dissect_q933_ia5_ie(tvb, offset + 2,
+ info_element_len, ie_tree,
+ "Display information");
+ break;
+
+ case CS0 | Q933_IE_E2E_TRANSIT_DELAY:
+ dissect_q933_e2e_transit_delay_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_TD_SELECTION_AND_INT:
+ dissect_q933_td_selection_and_int_ie(
+ tvb, offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_PL_BINARY_PARAMETERS:
+ dissect_q933_pl_binary_parameters_ie(
+ tvb, offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_REVERSE_CHARGE_IND:
+ dissect_q933_reverse_charge_ind_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_CALLING_PARTY_NUMBER:
+ dissect_q933_number_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree,
+ hf_q933_calling_party_number);
+ break;
+
+ case CS0 | Q933_IE_CONNECTED_NUMBER:
+ dissect_q933_number_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree,
+ hf_q933_connected_number);
+ break;
+
+ case CS0 | Q933_IE_CALLED_PARTY_NUMBER:
+ dissect_q933_number_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree,
+ hf_q933_called_party_number);
+ break;
+
+ case CS0 | Q933_IE_CALLING_PARTY_SUBADDR:
+ case CS0 | Q933_IE_CALLED_PARTY_SUBADDR:
+ dissect_q933_party_subaddr_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_HIGH_LAYER_COMPAT:
+ dissect_q933_high_layer_compat_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ case CS0 | Q933_IE_USER_USER:
+ dissect_q933_user_user_ie(tvb,
+ offset + 2, info_element_len,
+ ie_tree);
+ break;
+
+ default:
+ proto_tree_add_text(ie_tree, tvb,
+ offset + 2, info_element_len,
+ "Data: %s",
+ bytes_to_str(
+ tvb_get_ptr(tvb, offset + 2,
+ info_element_len),
+ info_element_len));
+ break;
+ }
+ }
+ offset += 1 + 1 + info_element_len;
+ codeset = locked_codeset;
+ }
+}
+
+void
+proto_register_q933(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_q933_discriminator,
+ { "Protocol discriminator", "q933.disc", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q933_call_ref_flag,
+ { "Call reference flag", "q933.call_ref_flag", FT_BOOLEAN, BASE_NONE, TFS(&tfs_call_ref_flag), 0x0,
+ "", HFILL }},
+
+ { &hf_q933_call_ref,
+ { "Call reference value", "q933.call_ref", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+
+ { &hf_q933_coding_standard,
+ { "Coding standard", "q933.coding_standard", FT_UINT8, BASE_HEX,
+ VALS(q933_coding_standard_vals), 0x60,"", HFILL }},
+
+ { &hf_q933_information_transfer_capability,
+ { "Information transfer capability", "q933.information_transfer_capability", FT_UINT8, BASE_HEX,
+ VALS(q933_information_transfer_capability_vals), 0x1f,"", HFILL }},
+
+ { &hf_q933_transfer_mode,
+ { "Transfer mode", "q933.transfer_mode", FT_UINT8, BASE_HEX,
+ VALS(q933_transfer_mode_vals), 0x60,"", HFILL }},
+
+ { &hf_q933_uil1,
+ { "User information layer 1 protocol", "q933.uil1", FT_UINT8, BASE_HEX,
+ VALS(q933_uil1_vals), 0x1f,"", HFILL }},
+
+ { &hf_q933_call_ref_len,
+ { "Call reference value length", "q933.call_ref_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q933_message_type,
+ { "Message type", "q933.message_type", FT_UINT8, BASE_HEX, VALS(q933_message_type_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_q933_cause_location,
+ { "Cause location", "q933.cause_location", FT_UINT8, BASE_DEC, VALS(q933_cause_location_vals), 0x0f,
+ "", HFILL }},
+
+ { &hf_q933_cause_value,
+ { "Cause value", "q933.cause_value", FT_UINT8, BASE_DEC, VALS(q933_cause_code_vals), 0x7f,
+ "", HFILL }},
+
+ { &hf_q933_number_type,
+ { "Number type", "q933.number_type", FT_UINT8, BASE_HEX, VALS(q933_number_type_vals), 0x70,
+ "", HFILL }},
+
+ { &hf_q933_numbering_plan,
+ { "numbering plan", "q933.numbering_plan", FT_UINT8, BASE_HEX, VALS(q933_numbering_plan_vals), 0x0f,
+ "", HFILL }},
+
+ { &hf_q933_screening_ind,
+ { "Screening indicator", "q933.screening_ind", FT_UINT8, BASE_HEX, VALS(q933_screening_indicator_vals), 0x03,
+ "", HFILL }},
+
+ { &hf_q933_presentation_ind,
+ { "Presentation indicator", "q933.presentation_ind", FT_UINT8, BASE_HEX, VALS(q933_presentation_indicator_vals), 0x60,
+ "", HFILL }},
+
+ { &hf_q933_extension_ind,
+ { "Extension indicator", "q933.extension_ind",
+ FT_BOOLEAN, 8, TFS(&q933_extension_ind_value), 0x80,
+ "", HFILL }},
+
+ { &hf_q933_calling_party_number,
+ { "Calling party number digits", "q933.calling_party_number.digits", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q933_called_party_number,
+ { "Called party number digits", "q933.called_party_number.digits", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q933_connected_number,
+ { "Connected party number digits", "q933.connected_number.digits", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_q933_redirecting_number,
+ { "Redirecting party number digits", "q933.redirecting_number.digits", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_q933,
+ &ett_q933_ie,
+ };
+
+ proto_q933 = proto_register_protocol("Q.933", "Q.933", "q933");
+ proto_register_field_array (proto_q933, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("q933", dissect_q933, proto_q933);
+}
+
+void
+proto_reg_handoff_q933(void)
+{
+ dissector_handle_t q933_handle;
+
+ q933_handle = create_dissector_handle(dissect_q933, proto_q933);
+ dissector_add("fr.osinl", NLPID_Q_933, q933_handle);
+}
diff --git a/epan/dissectors/packet-qllc.c b/epan/dissectors/packet-qllc.c
new file mode 100644
index 0000000000..f0913ca76b
--- /dev/null
+++ b/epan/dissectors/packet-qllc.c
@@ -0,0 +1,196 @@
+/* packet-qllc.c
+ * Routines for QLLC protocol - Qualified? LLC
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2001 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+static int proto_qllc = -1;
+static int hf_qllc_address = -1;
+static int hf_qllc_control = -1;
+
+static gint ett_qllc = -1;
+
+static dissector_handle_t sna_handle;
+
+#define QSM 0x93
+#define QDISC 0x53
+#define QXID 0xbf
+#define QTEST 0xf3
+#define QRR 0xf1
+#define QRD 0x53
+#define QUA 0x73
+#define QDM 0x1f
+#define QFRMR 0x97
+#define QUI 0x03
+#define QUI_NO_REPLY 0x13
+#define QSIM 0x17
+
+#define QRD_QDISC_VALUE 0x53
+#define QDISC_TEXT "QDISC"
+#define QRD_TEXT "QRD"
+
+/* Control Field */
+static const value_string qllc_control_vals[] = {
+ { QUI, "QUI" },
+ { QUI_NO_REPLY, "QUI - reply required" },
+ { QSIM, "QSIM" },
+ { QDM, "QDM" },
+ { QUA, "QUA" },
+ { QSM, "QSM" },
+ { QFRMR, "QFRMR" },
+ { QXID, "QXID" },
+ { QRR, "QRR" },
+ { QTEST, "QTEST" },
+ { QDISC, QDISC_TEXT },
+ { QRD, QRD_TEXT },
+ { 0x00, NULL },
+};
+
+
+static void
+dissect_qllc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *qllc_tree = NULL;
+ proto_item *qllc_ti = NULL;
+ gboolean *q_bit_set = pinfo->private_data;
+ guint8 address, ctrl;
+ gboolean command = FALSE;
+
+ /*
+ * If the Q bit isn't set, this is just SNA data.
+ */
+ if (!(*q_bit_set)) {
+ call_dissector(sna_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ /* Summary information */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "QLLC");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ qllc_ti = proto_tree_add_item(tree, proto_qllc, tvb, 0, -1, FALSE);
+ qllc_tree = proto_item_add_subtree(qllc_ti, ett_qllc);
+ }
+
+ /* Get the address; we need it to determine if this is a
+ * COMMAND or a RESPONSE */
+ address = tvb_get_guint8(tvb, 0);
+ if (tree) {
+ proto_tree_add_item(qllc_tree, hf_qllc_address, tvb, 0, 1, FALSE);
+ }
+
+ /* The address field equals X'FF' in commands (except QRR)
+ * and anything in responses. */
+ ctrl = tvb_get_guint8(tvb, 1);
+ if (ctrl != QRR && address == 0xff) {
+ command = TRUE;
+ }
+
+
+ /* Disambiguate QRD_QDISC_VALUE, based on whether this packet is
+ * a COMMAND or RESPONSE. */
+ if (ctrl == QRD_QDISC_VALUE) {
+ if (command) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, QDISC_TEXT);
+ }
+ if (tree) {
+ proto_tree_add_text(qllc_tree, tvb,
+ 1, 1, "Control Field: %s (0x%02x)", QDISC_TEXT, ctrl);
+ }
+ }
+ else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, QRD_TEXT);
+ }
+ if (tree) {
+ proto_tree_add_text(qllc_tree, tvb,
+ 1, 1, "Control Field: %s (0x%02x)", QRD_TEXT, ctrl);
+ }
+ }
+
+ /* Add the field for filtering purposes */
+ if (tree) {
+ proto_tree_add_uint_hidden(qllc_tree, hf_qllc_control, tvb,
+ 1, 1, ctrl);
+ }
+ }
+ else {
+ /* Non-ambiguous control field value */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str(ctrl, qllc_control_vals,
+ "Control Field: 0x%02x (unknown)"));
+ }
+ if (tree) {
+ proto_tree_add_uint(qllc_tree, hf_qllc_control, tvb,
+ 1, 1, ctrl);
+ }
+ }
+
+ /* Do we have an I field ? */
+ /* XXX - I field exists for QUI too, but only for subarea nodes.
+ * Need to test for this. */
+ if (ctrl == QXID || ctrl == QTEST || ctrl == QFRMR) {
+ /* yes */
+ }
+}
+
+void
+proto_register_qllc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_qllc_address,
+ { "Address Field", "qllc.address", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_qllc_control,
+ { "Control Field", "qllc.control", FT_UINT8, BASE_HEX,
+ VALS(qllc_control_vals), 0x0, "", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_qllc,
+ };
+
+ proto_qllc = proto_register_protocol("Qualified Logical Link Control",
+ "QLLC", "qllc");
+ proto_register_field_array(proto_qllc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("qllc", dissect_qllc, proto_qllc);
+}
+
+void
+proto_reg_handoff_qllc(void)
+{
+ sna_handle = find_dissector("sna");
+}
diff --git a/epan/dissectors/packet-quake.c b/epan/dissectors/packet-quake.c
new file mode 100644
index 0000000000..752a19b7b8
--- /dev/null
+++ b/epan/dissectors/packet-quake.c
@@ -0,0 +1,667 @@
+/* packet-quake.c
+ * Routines for Quake packet dissection
+ *
+ * Uwe Girlich <uwe@planetquake.com>
+ * http://www.idsoftware.com/q1source/q1source.zip
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "prefs.h"
+
+static int proto_quake = -1;
+static int hf_quake_header_flags = -1;
+static int hf_quake_header_length = -1;
+static int hf_quake_header_sequence = -1;
+static int hf_quake_control_command = -1;
+
+static int hf_quake_CCREQ_CONNECT_game = -1;
+static int hf_quake_CCREQ_CONNECT_version = -1;
+static int hf_quake_CCREQ_SERVER_INFO_game = -1;
+static int hf_quake_CCREQ_SERVER_INFO_version = -1;
+static int hf_quake_CCREQ_PLAYER_INFO_player = -1;
+static int hf_quake_CCREQ_RULE_INFO_lastrule = -1;
+
+static int hf_quake_CCREP_ACCEPT_port = -1;
+static int hf_quake_CCREP_REJECT_reason = -1;
+static int hf_quake_CCREP_SERVER_INFO_address = -1;
+static int hf_quake_CCREP_SERVER_INFO_server = -1;
+static int hf_quake_CCREP_SERVER_INFO_map = -1;
+static int hf_quake_CCREP_SERVER_INFO_num_player = -1;
+static int hf_quake_CCREP_SERVER_INFO_max_player = -1;
+static int hf_quake_CCREP_PLAYER_INFO_name = -1;
+static int hf_quake_CCREP_PLAYER_INFO_colors = -1;
+static int hf_quake_CCREP_PLAYER_INFO_colors_shirt = -1;
+static int hf_quake_CCREP_PLAYER_INFO_colors_pants = -1;
+static int hf_quake_CCREP_PLAYER_INFO_frags = -1;
+static int hf_quake_CCREP_PLAYER_INFO_connect_time = -1;
+static int hf_quake_CCREP_PLAYER_INFO_address = -1;
+static int hf_quake_CCREP_RULE_INFO_rule = -1;
+static int hf_quake_CCREP_RULE_INFO_value = -1;
+
+
+static gint ett_quake = -1;
+static gint ett_quake_control = -1;
+static gint ett_quake_control_colors = -1;
+static gint ett_quake_flags = -1;
+
+static dissector_handle_t quake_handle;
+static dissector_handle_t data_handle;
+
+/* I took these names directly out of the Q1 source. */
+#define NETFLAG_LENGTH_MASK 0x0000ffff
+#define NET_HEADERSIZE 8
+#define DEFAULTnet_hostport 26000
+static unsigned int gbl_quakeServerPort=DEFAULTnet_hostport;
+
+#define NETFLAG_LENGTH_MASK 0x0000ffff
+#define NETFLAG_DATA 0x00010000
+#define NETFLAG_ACK 0x00020000
+#define NETFLAG_NAK 0x00040000
+#define NETFLAG_EOM 0x00080000
+#define NETFLAG_UNRELIABLE 0x00100000
+#define NETFLAG_CTL 0x80000000
+
+
+#define CCREQ_CONNECT 0x01
+#define CCREQ_SERVER_INFO 0x02
+#define CCREQ_PLAYER_INFO 0x03
+#define CCREQ_RULE_INFO 0x04
+
+#define CCREP_ACCEPT 0x81
+#define CCREP_REJECT 0x82
+#define CCREP_SERVER_INFO 0x83
+#define CCREP_PLAYER_INFO 0x84
+#define CCREP_RULE_INFO 0x85
+
+static const value_string names_control_command[] = {
+ { CCREQ_CONNECT, "connect" },
+ { CCREQ_SERVER_INFO, "server_info" },
+ { CCREQ_PLAYER_INFO, "player_info" },
+ { CCREQ_RULE_INFO, "rule_info" },
+ { CCREP_ACCEPT, "accept" },
+ { CCREP_REJECT, "reject" },
+ { CCREP_SERVER_INFO, "server_info" },
+ { CCREP_PLAYER_INFO, "player_info" },
+ { CCREP_RULE_INFO, "rule_info" },
+ { 0, NULL }
+};
+
+#define CCREQ 0x00
+#define CCREP 0x80
+
+#define QUAKE_MAXSTRING 0x800
+
+static const value_string names_control_direction[] = {
+ { CCREQ, "Request" },
+ { CCREP, "Reply" },
+ { 0, NULL }
+};
+
+
+static const value_string names_colors[] = {
+ { 0, "White" },
+ { 1, "Brown" },
+ { 2, "Lavender" },
+ { 3, "Khaki" },
+ { 4, "Red" },
+ { 5, "Lt Brown" },
+ { 6, "Peach" },
+ { 7, "Lt Peach" },
+ { 8, "Purple" },
+ { 9, "Dk Purple" },
+ { 10, "Tan" },
+ { 11, "Green" },
+ { 12, "Yellow" },
+ { 13, "Blue" },
+ { 14, "Blue" },
+ { 15, "Blue" },
+ { 0, NULL }
+};
+
+
+static void dissect_quake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+
+
+static void
+dissect_quake_CCREQ_CONNECT
+(tvbuff_t *tvb, proto_tree *tree)
+{
+ gint offset;
+ proto_item *ti;
+
+ offset = 0;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, hf_quake_CCREQ_CONNECT_game,
+ tvb, offset, -1, TRUE);
+ offset += proto_item_get_len(ti);
+
+ proto_tree_add_item(tree, hf_quake_CCREQ_CONNECT_version,
+ tvb, offset, 1, TRUE);
+ }
+}
+
+
+static void
+dissect_quake_CCREQ_SERVER_INFO
+(tvbuff_t *tvb, proto_tree *tree)
+{
+ gint offset;
+ proto_item *ti;
+
+ offset = 0;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, hf_quake_CCREQ_SERVER_INFO_game,
+ tvb, offset, -1, TRUE);
+ offset += proto_item_get_len(ti);
+ proto_tree_add_item(tree, hf_quake_CCREQ_SERVER_INFO_version,
+ tvb, offset, 1, TRUE);
+ }
+}
+
+
+static void
+dissect_quake_CCREQ_PLAYER_INFO
+(tvbuff_t *tvb, proto_tree *tree)
+{
+ if (tree) {
+ proto_tree_add_item(tree, hf_quake_CCREQ_PLAYER_INFO_player,
+ tvb, 0, 1, TRUE);
+ }
+}
+
+
+static void
+dissect_quake_CCREQ_RULE_INFO
+(tvbuff_t *tvb, proto_tree *tree)
+{
+ if (tree) {
+ proto_tree_add_item(tree, hf_quake_CCREQ_RULE_INFO_lastrule,
+ tvb, 0, -1, TRUE);
+ }
+}
+
+
+static void
+dissect_quake_CCREP_ACCEPT
+(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 port;
+ conversation_t *c;
+
+ port = tvb_get_letohl(tvb, 0);
+ c = conversation_new( &pinfo->src, &pinfo->dst, PT_UDP, port,
+ pinfo->destport, 0);
+ if (c) {
+ conversation_set_dissector(c, quake_handle);
+ }
+ if (tree) {
+ proto_tree_add_uint(tree, hf_quake_CCREP_ACCEPT_port,
+ tvb, 0, 4, port);
+ }
+}
+
+
+static void
+dissect_quake_CCREP_REJECT
+(tvbuff_t *tvb, proto_tree *tree)
+{
+ if (tree) {
+ proto_tree_add_item(tree, hf_quake_CCREP_REJECT_reason,
+ tvb, 0, -1, TRUE);
+ }
+}
+
+
+static void
+dissect_quake_CCREP_SERVER_INFO
+(tvbuff_t *tvb, proto_tree *tree)
+{
+ gint offset;
+ proto_item *ti;
+
+ offset = 0;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree,
+ hf_quake_CCREP_SERVER_INFO_address, tvb, offset, -1,
+ TRUE);
+ offset += proto_item_get_len(ti);
+
+ ti = proto_tree_add_item(tree,
+ hf_quake_CCREP_SERVER_INFO_server, tvb, offset, -1,
+ TRUE);
+ offset += proto_item_get_len(ti);
+
+ ti = proto_tree_add_item(tree, hf_quake_CCREP_SERVER_INFO_map,
+ tvb, offset, -1, TRUE);
+ offset += proto_item_get_len(ti);
+
+ proto_tree_add_item(tree, hf_quake_CCREP_SERVER_INFO_num_player,
+ tvb, offset, 1, TRUE);
+ offset += 1;
+ proto_tree_add_item(tree, hf_quake_CCREP_SERVER_INFO_max_player,
+ tvb, offset, 1, TRUE);
+ offset += 1;
+ proto_tree_add_item(tree, hf_quake_CCREQ_SERVER_INFO_version,
+ tvb, offset, 1, TRUE);
+ }
+}
+
+
+static void
+dissect_quake_CCREP_PLAYER_INFO
+(tvbuff_t *tvb, proto_tree *tree)
+{
+ gint offset;
+ proto_item *ti;
+ guint32 colors;
+ guint32 color_shirt;
+ guint32 color_pants;
+ proto_item *colors_item;
+ proto_tree *colors_tree;
+
+ offset = 0;
+
+ if (tree) {
+ proto_tree_add_item(tree, hf_quake_CCREQ_PLAYER_INFO_player,
+ tvb, offset, 1, TRUE);
+ offset += 1;
+
+ ti = proto_tree_add_item(tree, hf_quake_CCREP_PLAYER_INFO_name,
+ tvb, offset, -1, TRUE);
+ offset += proto_item_get_len(ti);
+
+ colors = tvb_get_letohl(tvb, offset + 0);
+ color_shirt = (colors >> 4) & 0x0f;
+ color_pants = (colors ) & 0x0f;
+
+ colors_item = proto_tree_add_uint(tree,
+ hf_quake_CCREP_PLAYER_INFO_colors,
+ tvb, offset, 4, colors);
+ colors_tree = proto_item_add_subtree(colors_item,
+ ett_quake_control_colors);
+ proto_tree_add_uint(colors_tree,
+ hf_quake_CCREP_PLAYER_INFO_colors_shirt,
+ tvb, offset, 1, color_shirt);
+ proto_tree_add_uint(colors_tree,
+ hf_quake_CCREP_PLAYER_INFO_colors_pants,
+ tvb, offset, 1, color_pants);
+ offset += 4;
+ proto_tree_add_item(tree, hf_quake_CCREP_PLAYER_INFO_frags,
+ tvb, offset, 4, TRUE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_quake_CCREP_PLAYER_INFO_connect_time,
+ tvb, offset, 4, TRUE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_quake_CCREP_PLAYER_INFO_address,
+ tvb, offset, -1, TRUE);
+ }
+}
+
+
+static void
+dissect_quake_CCREP_RULE_INFO
+(tvbuff_t *tvb, proto_tree *tree)
+{
+ gint offset;
+ proto_item *ti;
+
+ if (tvb_reported_length(tvb) == 0) return;
+
+ offset = 0;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, hf_quake_CCREP_RULE_INFO_rule,
+ tvb, offset, -1, TRUE);
+ offset += proto_item_get_len(ti);
+
+ proto_tree_add_item(tree, hf_quake_CCREP_RULE_INFO_value,
+ tvb, offset, -1, TRUE);
+ }
+}
+
+
+static void
+dissect_quake_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 command;
+ int direction;
+ proto_item *control_item = NULL;
+ proto_tree *control_tree = NULL;
+ guint rest_length;
+ tvbuff_t *next_tvb;
+
+ command = tvb_get_guint8(tvb, 0);
+ direction = (command & 0x80) ? CCREP : CCREQ;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ val_to_str(command,names_control_command, "%u"),
+ val_to_str(direction,names_control_direction,"%u"));
+ }
+
+ if (tree) {
+ control_item = proto_tree_add_text(tree, tvb,
+ 0, -1, "Control %s: %s",
+ val_to_str(direction, names_control_direction, "%u"),
+ val_to_str(command, names_control_command, "%u"));
+ if (control_item)
+ control_tree = proto_item_add_subtree(control_item,
+ ett_quake_control);
+ proto_tree_add_uint(control_tree, hf_quake_control_command,
+ tvb, 0, 1, command);
+ }
+
+ rest_length = tvb_reported_length(tvb) - 1;
+ next_tvb = tvb_new_subset(tvb, 1, rest_length , rest_length);
+ switch (command) {
+ case CCREQ_CONNECT:
+ dissect_quake_CCREQ_CONNECT
+ (next_tvb, control_tree);
+ break;
+ case CCREQ_SERVER_INFO:
+ dissect_quake_CCREQ_SERVER_INFO
+ (next_tvb, control_tree);
+ break;
+ case CCREQ_PLAYER_INFO:
+ dissect_quake_CCREQ_PLAYER_INFO
+ (next_tvb, control_tree);
+ break;
+ case CCREQ_RULE_INFO:
+ dissect_quake_CCREQ_RULE_INFO
+ (next_tvb, control_tree);
+ break;
+ case CCREP_ACCEPT:
+ dissect_quake_CCREP_ACCEPT
+ (next_tvb, pinfo, control_tree);
+ break;
+ case CCREP_REJECT:
+ dissect_quake_CCREP_REJECT
+ (next_tvb, control_tree);
+ break;
+ case CCREP_SERVER_INFO:
+ dissect_quake_CCREP_SERVER_INFO
+ (next_tvb, control_tree);
+ break;
+ case CCREP_PLAYER_INFO:
+ dissect_quake_CCREP_PLAYER_INFO
+ (next_tvb, control_tree);
+ break;
+ case CCREP_RULE_INFO:
+ dissect_quake_CCREP_RULE_INFO
+ (next_tvb, control_tree);
+ break;
+ default:
+ call_dissector(data_handle,next_tvb, pinfo, control_tree);
+ break;
+ }
+}
+
+
+static void
+dissect_quake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *quake_tree = NULL;
+ proto_item *quake_item = NULL;
+ guint32 length;
+ guint32 flags;
+ guint32 sequence = 0;
+ guint rest_length;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "QUAKE");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ length = tvb_get_ntohl(tvb, 0);
+ flags = length & (~NETFLAG_LENGTH_MASK);
+ length &= NETFLAG_LENGTH_MASK;
+
+ if (tree) {
+ quake_item = proto_tree_add_item(tree, proto_quake,
+ tvb, 0, -1, FALSE);
+ if (quake_item)
+ quake_tree = proto_item_add_subtree(quake_item, ett_quake);
+ }
+
+ if (quake_tree) {
+ proto_item* flags_item = NULL;
+ proto_tree* flags_tree = NULL;
+
+ flags_item = proto_tree_add_uint(quake_tree, hf_quake_header_flags,
+ tvb, 0, 2, flags);
+ if (flags_item) {
+ flags_tree = proto_item_add_subtree(flags_item, ett_quake_flags);
+ }
+
+ if (flags_tree) {
+ proto_tree_add_text(flags_tree, tvb, 0, 2,
+ decode_boolean_bitfield(flags, NETFLAG_DATA, 32,
+ "Data","-"));
+ proto_tree_add_text(flags_tree, tvb, 0, 2,
+ decode_boolean_bitfield(flags, NETFLAG_ACK, 32,
+ "Acknowledgment","-"));
+ proto_tree_add_text(flags_tree, tvb, 0, 2,
+ decode_boolean_bitfield(flags, NETFLAG_NAK, 32,
+ "No Acknowledgment","-"));
+ proto_tree_add_text(flags_tree, tvb, 0, 2,
+ decode_boolean_bitfield(flags, NETFLAG_EOM, 32,
+ "End Of Message","-"));
+ proto_tree_add_text(flags_tree, tvb, 0, 2,
+ decode_boolean_bitfield(flags, NETFLAG_UNRELIABLE, 32,
+ "Unreliable","-"));
+ proto_tree_add_text(flags_tree, tvb, 0, 2,
+ decode_boolean_bitfield(flags, NETFLAG_CTL, 32,
+ "Control","-"));
+ }
+ proto_tree_add_uint(quake_tree, hf_quake_header_length,
+ tvb, 2, 2, length);
+ }
+
+ if (flags == NETFLAG_CTL) {
+ rest_length = tvb_reported_length(tvb) - 4;
+ next_tvb = tvb_new_subset(tvb, 4, rest_length , rest_length);
+ dissect_quake_control(next_tvb, pinfo, quake_tree);
+ return;
+ }
+
+ sequence = tvb_get_ntohl(tvb, 4);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "seq 0x%x", sequence);
+ }
+ if (quake_tree) {
+ proto_tree_add_uint(quake_tree, hf_quake_header_sequence,
+ tvb, 4, 4, sequence);
+ }
+
+ rest_length = tvb_reported_length(tvb) - 8;
+ next_tvb = tvb_new_subset(tvb, 8, rest_length , rest_length);
+ call_dissector(data_handle,next_tvb, pinfo, quake_tree);
+}
+
+
+void
+proto_reg_handoff_quake(void)
+{
+ static int Initialized=FALSE;
+ static int ServerPort=0;
+
+ if (Initialized) {
+ dissector_delete("udp.port", ServerPort, quake_handle);
+ } else {
+ Initialized=TRUE;
+ }
+
+ /* set port for future deletes */
+ ServerPort=gbl_quakeServerPort;
+
+ dissector_add("udp.port", gbl_quakeServerPort, quake_handle);
+ data_handle = find_dissector("data");
+}
+
+
+void
+proto_register_quake(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_quake_header_flags,
+ { "Flags", "quake.header.flags",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Flags", HFILL }},
+ { &hf_quake_header_length,
+ { "Length", "quake.header.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "full data length", HFILL }},
+ { &hf_quake_header_sequence,
+ { "Sequence", "quake.header.sequence",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Sequence Number", HFILL }},
+ { &hf_quake_control_command,
+ { "Command", "quake.control.command",
+ FT_UINT8, BASE_HEX, VALS(names_control_command), 0x0,
+ "Control Command", HFILL }},
+ { &hf_quake_CCREQ_CONNECT_game,
+ { "Game", "quake.control.connect.game",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Game Name", HFILL }},
+ { &hf_quake_CCREQ_CONNECT_version,
+ { "Version", "quake.control.connect.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Game Protocol Version Number", HFILL }},
+ { &hf_quake_CCREQ_SERVER_INFO_game,
+ { "Game", "quake.control.server_info.game",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Game Name", HFILL }},
+ { &hf_quake_CCREQ_SERVER_INFO_version,
+ { "Version", "quake.control.server_info.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Game Protocol Version Number", HFILL }},
+ { &hf_quake_CCREQ_PLAYER_INFO_player,
+ { "Player", "quake.control.player_info.player",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Player", HFILL }},
+ { &hf_quake_CCREQ_RULE_INFO_lastrule,
+ { "Last Rule", "quake.control.rule_info.lastrule",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Last Rule Name", HFILL }},
+ { &hf_quake_CCREP_ACCEPT_port,
+ { "Port", "quake.control.accept.port",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Game Data Port", HFILL }},
+ { &hf_quake_CCREP_REJECT_reason,
+ { "Reason", "quake.control.reject.reason",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Reject Reason", HFILL }},
+ { &hf_quake_CCREP_SERVER_INFO_address,
+ { "Address", "quake.control.server_info.address",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Server Address", HFILL }},
+ { &hf_quake_CCREP_SERVER_INFO_server,
+ { "Server", "quake.control.server_info.server",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Server Name", HFILL }},
+ { &hf_quake_CCREP_SERVER_INFO_map,
+ { "Map", "quake.control.server_info.map",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Map Name", HFILL }},
+ { &hf_quake_CCREP_SERVER_INFO_num_player,
+ { "Number of Players", "quake.control.server_info.num_player",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Current Number of Players", HFILL }},
+ { &hf_quake_CCREP_SERVER_INFO_max_player,
+ { "Maximal Number of Players", "quake.control.server_info.max_player",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Maximal Number of Players", HFILL }},
+ { &hf_quake_CCREP_PLAYER_INFO_name,
+ { "Name", "quake.control.player_info.name",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Player Name", HFILL }},
+ { &hf_quake_CCREP_PLAYER_INFO_colors,
+ { "Colors", "quake.control.player_info.colors",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Player Colors", HFILL }},
+ { &hf_quake_CCREP_PLAYER_INFO_colors_shirt,
+ { "Shirt", "quake.control.player_info.colors.shirt",
+ FT_UINT8, BASE_DEC, VALS(names_colors), 0x0,
+ "Shirt Color", HFILL }},
+ { &hf_quake_CCREP_PLAYER_INFO_colors_pants,
+ { "Pants", "quake.control.player_info.colors.pants",
+ FT_UINT8, BASE_DEC, VALS(names_colors), 0x0,
+ "Pants Color", HFILL }},
+ { &hf_quake_CCREP_PLAYER_INFO_frags,
+ { "Frags", "quake.control.player_info.frags",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Player Frags", HFILL }},
+ { &hf_quake_CCREP_PLAYER_INFO_connect_time,
+ { "Connect Time", "quake.control.player_info.connect_time",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Player Connect Time", HFILL }},
+ { &hf_quake_CCREP_PLAYER_INFO_address,
+ { "Address", "quake.control.player_info.address",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Player Address", HFILL }},
+ { &hf_quake_CCREP_RULE_INFO_rule,
+ { "Rule", "quake.control.rule_info.rule",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Rule Name", HFILL }},
+ { &hf_quake_CCREP_RULE_INFO_value,
+ { "Value", "quake.control.rule_info.value",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "Rule Value", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_quake,
+ &ett_quake_control,
+ &ett_quake_control_colors,
+ &ett_quake_flags,
+ };
+ module_t *quake_module;
+
+ proto_quake = proto_register_protocol("Quake Network Protocol",
+ "QUAKE", "quake");
+ proto_register_field_array(proto_quake, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ quake_handle = create_dissector_handle(dissect_quake, proto_quake);
+
+ /* Register a configuration option for port */
+ quake_module = prefs_register_protocol(proto_quake,
+ proto_reg_handoff_quake);
+ prefs_register_uint_preference(quake_module, "udp.port",
+ "Quake Server UDP Port",
+ "Set the UDP port for the Quake Server",
+ 10, &gbl_quakeServerPort);
+}
diff --git a/epan/dissectors/packet-quake2.c b/epan/dissectors/packet-quake2.c
new file mode 100644
index 0000000000..188077e3e4
--- /dev/null
+++ b/epan/dissectors/packet-quake2.c
@@ -0,0 +1,932 @@
+/* packet-quake2.c
+ * Routines for Quake II packet dissection
+ *
+ * Uwe Girlich <uwe@planetquake.com>
+ * http://www.idsoftware.com/q1source/q1source.zip
+ * http://www.planetquake.com/demospecs/dm2
+ * http://www.dgs.monash.edu.au/~timf/bottim/
+ * http://www.opt-sci.Arizona.EDU/Pandora/default.asp
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-quakeworld.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+
+static int proto_quake2 = -1;
+
+static int hf_quake2_s2c = -1;
+static int hf_quake2_c2s = -1;
+static int hf_quake2_connectionless = -1;
+static int hf_quake2_game = -1;
+static int hf_quake2_connectionless_marker = -1;
+static int hf_quake2_connectionless_text = -1;
+static int hf_quake2_game_seq1 = -1;
+static int hf_quake2_game_rel1 = -1;
+static int hf_quake2_game_seq2 = -1;
+static int hf_quake2_game_rel2 = -1;
+static int hf_quake2_game_qport = -1;
+static int hf_quake2_game_client_command = -1;
+static int hf_quake2_game_server_command = -1;
+static int hf_quake2_game_client_command_move = -1;
+static int hf_quake2_game_client_command_move_chksum = -1;
+static int hf_quake2_game_client_command_move_lframe = -1;
+static int hf_quake2_game_client_command_move_bitfield_angles1 = -1;
+static int hf_quake2_game_client_command_move_bitfield_angles2 = -1;
+static int hf_quake2_game_client_command_move_bitfield_angles3 = -1;
+static int hf_quake2_game_client_command_move_bitfield_movement_fwd = -1;
+static int hf_quake2_game_client_command_move_bitfield_movement_side = -1;
+static int hf_quake2_game_client_command_move_bitfield_movement_up = -1;
+static int hf_quake2_game_client_command_move_bitfield_buttons = -1;
+static int hf_quake2_game_client_command_move_bitfield_impulse = -1;
+static int hf_quake2_game_client_command_move_msec = -1;
+static int hf_quake2_game_client_command_move_lightlevel = -1;
+
+static gint ett_quake2 = -1;
+static gint ett_quake2_connectionless = -1;
+static gint ett_quake2_game = -1;
+static gint ett_quake2_game_seq1 = -1;
+static gint ett_quake2_game_seq2 = -1;
+static gint ett_quake2_game_clc = -1;
+static gint ett_quake2_game_svc = -1;
+static gint ett_quake2_game_clc_cmd = -1;
+static gint ett_quake2_game_svc_cmd = -1;
+static gint ett_quake2_game_clc_cmd_move_bitfield = -1;
+static gint ett_quake2_game_clc_cmd_move_moves = -1;
+
+
+static dissector_handle_t data_handle;
+
+#define PORT_MASTER 27910
+static unsigned int gbl_quake2ServerPort=PORT_MASTER;
+
+
+static void
+dissect_quake2_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, int direction _U_)
+{
+ proto_tree *cl_tree = NULL;
+ proto_item *cl_item = NULL;
+ guint8 *text;
+ int len;
+ int offset;
+
+ guint32 marker;
+
+ marker = tvb_get_ntohl(tvb, 0);
+ if (tree) {
+ cl_item = proto_tree_add_text(tree, tvb,
+ 0, -1, "Connectionless");
+ if (cl_item)
+ cl_tree = proto_item_add_subtree(
+ cl_item, ett_quake2_connectionless);
+ }
+
+ if (cl_tree) {
+ proto_tree_add_uint(cl_tree, hf_quake2_connectionless_marker,
+ tvb, 0, 4, marker);
+ }
+
+ /* all the rest of the packet is just text */
+ offset = 4;
+
+ len = tvb_length_remaining(tvb, offset);
+ if (cl_tree) {
+ text = tvb_get_string(tvb, offset, len);
+ proto_tree_add_string(cl_tree, hf_quake2_connectionless_text,
+ tvb, offset, len, text);
+ g_free(text);
+ }
+ offset += len;
+
+ /* we should analyse the result 'text' a bit further */
+ /* for this we need the direction parameter */
+}
+
+static const value_string hf_quake2_game_client_command_move_vals[] = {
+ { 0x00, "-" },
+ { 0x01, "set" },
+ { 0, NULL }
+};
+
+static int
+dissect_quake2_client_commands_move(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ #define MOVES 3 /* 3 updates per command */
+
+ /* taken from qcommon.h */
+ #define CM_ANGLE1 (1<<0)
+ #define CM_ANGLE2 (1<<1)
+ #define CM_ANGLE3 (1<<2)
+ #define CM_FORWARD (1<<3)
+ #define CM_SIDE (1<<4)
+ #define CM_UP (1<<5)
+ #define CM_BUTTONS (1<<6)
+ #define CM_IMPULSE (1<<7)
+ /* qshared.h */
+ #define BUTTON_ATTACK 1
+ #define BUTTON_USE 2
+ #define BUTTON_ANY 128
+
+ guint8 chksum;
+ guint32 lastframe;
+ int i, offset = 0;
+ enum { OFFSET, VALUE, SIZE };
+ struct movement {
+ guint8 bits[SIZE];
+ guint16 angles[3][SIZE];
+ gint16 movement[3][SIZE];
+ guint8 buttons[SIZE];
+ guint8 lightlevel[SIZE];
+ guint8 msec[SIZE];
+ guint8 impulse[SIZE];
+ } move[MOVES+1];
+
+ chksum = tvb_get_guint8(tvb, offset);
+ offset++;
+ lastframe = tvb_get_letohl(tvb, offset);
+ offset += 4;
+
+ for (i=0; i < MOVES; i++) {
+ move[i].bits[VALUE] = tvb_get_guint8(tvb, offset);
+ move[i].bits[OFFSET] = offset;
+ offset++;
+ if (move[i].bits[VALUE] & CM_ANGLE1) {
+ move[i].angles[0][VALUE] = tvb_get_letohs(tvb, offset);
+ move[i].angles[0][OFFSET] = offset;
+ offset += 2;
+ }
+ if (move[i].bits[VALUE] & CM_ANGLE2) {
+ move[i].angles[1][VALUE] = tvb_get_letohs(tvb, offset);
+ move[i].angles[1][OFFSET] = offset;
+ offset += 2;
+ }
+ if (move[i].bits[VALUE] & CM_ANGLE3) {
+ move[i].angles[2][VALUE] = tvb_get_letohs(tvb, offset);
+ move[i].angles[2][OFFSET] = offset;
+ offset += 2;
+ }
+ if (move[i].bits[VALUE] & CM_FORWARD) {
+ move[i].movement[0][VALUE] = tvb_get_letohs(tvb, offset);
+ move[i].movement[0][OFFSET] = offset;
+ offset += 2;
+ }
+ if (move[i].bits[VALUE] & CM_SIDE) {
+ move[i].movement[1][VALUE] = tvb_get_letohs(tvb, offset);
+ move[i].movement[1][OFFSET] = offset;
+ offset += 2;
+ }
+ if (move[i].bits[VALUE] & CM_UP) {
+ move[i].movement[2][VALUE] = tvb_get_letohs(tvb, offset);
+ move[i].movement[2][OFFSET] = offset;
+ offset += 2;
+ }
+ if (move[i].bits[VALUE] & CM_BUTTONS) {
+ move[i].buttons[VALUE] = tvb_get_guint8(tvb, offset);
+ move[i].buttons[OFFSET] = offset;
+ offset++;
+ }
+ if (move[i].bits[VALUE] & CM_IMPULSE) {
+ move[i].impulse[VALUE] = tvb_get_guint8(tvb, offset);
+ move[i].impulse[OFFSET] = offset;
+ offset++;
+ }
+
+ move[i].msec[VALUE] = tvb_get_guint8(tvb, offset);
+ move[i].msec[OFFSET] = offset;
+ offset++;
+ move[i].lightlevel[VALUE] = tvb_get_guint8(tvb, offset);
+ move[i].lightlevel[OFFSET] = offset;
+ offset++;
+ }
+
+ if (!tree)
+ return offset;
+
+ proto_tree_add_uint(tree, hf_quake2_game_client_command_move_chksum, tvb,
+ 0, 1, chksum);
+ proto_tree_add_uint(tree, hf_quake2_game_client_command_move_lframe, tvb,
+ 1, 4, lastframe);
+
+ move[MOVES].bits[OFFSET] = offset;
+ for (i=0; i < MOVES; i++) {
+ proto_item *move_item, *movebits_item, *bit_item;
+ proto_item *sub_tree, *field_tree;
+ #define SHORT2ANGLE(x) ((float)x/65536.0*360.0)
+
+ move_item = proto_tree_add_text(tree,
+ tvb,
+ move[i].bits[OFFSET],
+ move[i+1].bits[OFFSET]-move[i].bits[OFFSET],
+ "Move %u", i+1);
+ sub_tree = proto_item_add_subtree(move_item,
+ ett_quake2_game_clc_cmd_move_moves);
+
+ movebits_item =
+ proto_tree_add_uint(sub_tree, hf_quake2_game_client_command_move,
+ tvb,
+ move[i].bits[OFFSET],
+ 1,
+ move[i].bits[VALUE]);
+
+ proto_tree_add_uint(sub_tree,
+ hf_quake2_game_client_command_move_msec,
+ tvb, move[i].msec[OFFSET], 1, move[i].msec[VALUE]);
+ proto_tree_add_uint(sub_tree,
+ hf_quake2_game_client_command_move_lightlevel,
+ tvb, move[i].lightlevel[OFFSET], 1, move[i].lightlevel[VALUE]);
+
+ if (move[i].bits[VALUE] == 0) {
+ proto_item_append_text(movebits_item, " (no moves)");
+ continue;
+ }
+
+ field_tree = proto_item_add_subtree(movebits_item,
+ ett_quake2_game_clc_cmd_move_bitfield);
+
+ if (move[i].bits[VALUE] & CM_ANGLE1) {
+ bit_item = proto_tree_add_uint(field_tree,
+ hf_quake2_game_client_command_move_bitfield_angles1, tvb,
+ move[i].angles[0][OFFSET], 2, move[i].bits[VALUE]);
+ proto_item_append_text(bit_item, " (%d", move[i].angles[0][VALUE]);
+ proto_item_append_text(bit_item, " = %.2f deg)",
+ SHORT2ANGLE(move[i].angles[0][VALUE]));
+ }
+
+ if (move[i].bits[VALUE] & CM_ANGLE2) {
+ bit_item = proto_tree_add_uint(field_tree,
+ hf_quake2_game_client_command_move_bitfield_angles2, tvb,
+ move[i].angles[1][OFFSET], 2, move[i].bits[VALUE]);
+ proto_item_append_text(bit_item, " (%d", move[i].angles[1][VALUE]);
+ proto_item_append_text(bit_item, " = %.2f deg)",
+ SHORT2ANGLE(move[i].angles[1][VALUE]));
+ }
+ if (move[i].bits[VALUE] & CM_ANGLE3) {
+ bit_item = proto_tree_add_uint(field_tree,
+ hf_quake2_game_client_command_move_bitfield_angles3, tvb,
+ move[i].angles[2][OFFSET], 2, move[i].bits[VALUE]);
+ proto_item_append_text(bit_item, " (%d", move[i].angles[2][VALUE]);
+ proto_item_append_text(bit_item, " = %.2f deg)",
+ SHORT2ANGLE(move[i].angles[2][VALUE]));
+ }
+ if (move[i].bits[VALUE] & CM_FORWARD) {
+ bit_item = proto_tree_add_uint(field_tree,
+ hf_quake2_game_client_command_move_bitfield_movement_fwd, tvb,
+ move[i].movement[0][OFFSET], 2, move[i].bits[VALUE]);
+ proto_item_append_text(bit_item, " (%hd)",
+ move[i].movement[0][VALUE]);
+ }
+ if (move[i].bits[VALUE] & CM_SIDE) {
+ bit_item = proto_tree_add_uint(field_tree,
+ hf_quake2_game_client_command_move_bitfield_movement_side, tvb,
+ move[i].movement[1][OFFSET], 2, move[i].bits[VALUE]);
+ proto_item_append_text(bit_item, " (%hd)",
+ move[i].movement[1][VALUE]);
+ }
+ if (move[i].bits[VALUE] & CM_UP) {
+ bit_item = proto_tree_add_uint(field_tree,
+ hf_quake2_game_client_command_move_bitfield_movement_up, tvb,
+ move[i].movement[2][OFFSET], 2, move[i].bits[VALUE]);
+ proto_item_append_text(bit_item, " (%hd)",
+ move[i].movement[2][VALUE]);
+ }
+ if (move[i].bits[VALUE] & CM_BUTTONS) {
+ bit_item = proto_tree_add_uint(field_tree,
+ hf_quake2_game_client_command_move_bitfield_buttons, tvb,
+ move[i].buttons[OFFSET], 1, move[i].bits[VALUE]);
+ proto_item_append_text(bit_item, " (%d)",
+ move[i].buttons[VALUE]);
+ if (move[i].buttons[VALUE] & BUTTON_ATTACK)
+ proto_item_append_text(bit_item, " (Attack)");
+ if (move[i].buttons[VALUE] & BUTTON_USE)
+ proto_item_append_text(bit_item, " (Use)");
+ if (move[i].buttons[VALUE] & BUTTON_ANY)
+ proto_item_append_text(bit_item, " (Any)");
+ }
+ if (move[i].bits[VALUE] & CM_IMPULSE) {
+ bit_item = proto_tree_add_uint(field_tree,
+ hf_quake2_game_client_command_move_bitfield_impulse, tvb,
+ move[i].impulse[OFFSET], 1, move[i].bits[VALUE]);
+ proto_item_append_text(bit_item, " (%d)",
+ move[i].impulse[VALUE]);
+ }
+
+ }
+
+ return offset;
+}
+
+static int
+dissect_quake2_client_commands_uinfo(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint len;
+ proto_item *userinfo_item;
+
+ len = tvb_strsize(tvb, 0);
+
+ if (tree) {
+ userinfo_item = proto_tree_add_text(tree, tvb, 0, len, "Userinfo: %s",
+ tvb_get_ptr(tvb, 0, len));
+ }
+
+ return len;
+}
+
+static int
+dissect_quake2_client_commands_stringcmd(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree)
+{
+ guint len;
+ proto_item *stringcmd_item;
+
+ len = tvb_strsize(tvb, 0);
+
+ if (tree) {
+ stringcmd_item = proto_tree_add_text(tree, tvb, 0, len, "Command: %s",
+ tvb_get_ptr(tvb, 0, len));
+ }
+
+ return len;
+}
+
+static const value_string names_client_cmd[] = {
+ /* qcommon.h */
+#define CLC_BAD 0
+ { CLC_BAD, "clc_bad" },
+#define CLC_NOP 1
+ { CLC_NOP, "clc_nop" },
+#define CLC_MOVE 2
+ { CLC_MOVE, "clc_move" },
+#define CLC_USERINFO 3
+ { CLC_USERINFO, "clc_userinfo" },
+#define CLC_STRINGCMD 4
+ { CLC_STRINGCMD, "clc_stringcmd" },
+ { 0, NULL }
+};
+
+static void
+dissect_quake2_client_commands(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_tree *clc_tree = NULL;
+ tvbuff_t *next_tvb = NULL;
+ guint8 client_cmd_type;
+ guint rest_length = 0;
+ int offset = 0;
+
+ do {
+ client_cmd_type = tvb_get_guint8(tvb, offset);
+
+ if (tree) {
+ proto_item *cmd_type_item = proto_tree_add_uint(tree,
+ hf_quake2_game_client_command, tvb, offset, 1,
+ client_cmd_type);
+
+ if (cmd_type_item) {
+ proto_item_append_text(cmd_type_item, " (%s)",
+ val_to_str(client_cmd_type, names_client_cmd, "%u"));
+ clc_tree = proto_item_add_subtree(
+ cmd_type_item, ett_quake2_game_clc_cmd);
+ }
+ }
+
+ offset++;
+ rest_length = tvb_reported_length(tvb) - offset;
+ if (rest_length)
+ next_tvb = tvb_new_subset(tvb, offset,
+ rest_length, rest_length);
+ else
+ return;
+
+ rest_length = 0;
+ switch (client_cmd_type) {
+ case CLC_BAD:
+ break;
+ case CLC_NOP:
+ break;
+ case CLC_MOVE:
+ rest_length =
+ dissect_quake2_client_commands_move(next_tvb,
+ pinfo, clc_tree);
+ break;
+ case CLC_USERINFO:
+ rest_length =
+ dissect_quake2_client_commands_uinfo(next_tvb,
+ pinfo, clc_tree);
+ break;
+ case CLC_STRINGCMD:
+ rest_length =
+ dissect_quake2_client_commands_stringcmd(next_tvb,
+ pinfo, clc_tree);
+ break;
+ default:
+ break;
+ }
+ offset += rest_length;
+ } while (tvb_reported_length(tvb) - offset > 0);
+}
+
+static const value_string names_server_cmd[] = {
+ /* qcommon.h */
+#define SVC_BAD 0
+ { SVC_BAD, "svc_bad" },
+#define SVC_MUZZLEFLASH 1
+ { SVC_MUZZLEFLASH, "svc_muzzleflash" },
+#define SVC_MUZZLEFLASH2 2
+ { SVC_MUZZLEFLASH2, "svc_muzzleflash2" },
+#define SVC_TEMP_ENTITY 3
+ { SVC_TEMP_ENTITY, "svc_temp_entity" },
+#define SVC_LAYOUT 4
+ { SVC_LAYOUT, "svc_layout" },
+#define SVC_INVENTORY 5
+ { SVC_INVENTORY, "svc_inventory" },
+#define SVC_NOP 6
+ { SVC_NOP, "svc_nop" },
+#define SVC_DISCONNECT 7
+ { SVC_DISCONNECT, "svc_disconnect" },
+#define SVC_RECONNECT 8
+ { SVC_RECONNECT, "svc_reconnect" },
+#define SVC_SOUND 9
+ { SVC_SOUND, "svc_sound" },
+#define SVC_PRINT 10
+ { SVC_PRINT, "svc_print" },
+#define SVC_STUFFTEXT 11
+ { SVC_STUFFTEXT, "svc_stufftext" },
+#define SVC_SERVERDATA 12
+ { SVC_SERVERDATA, "svc_serverdata" },
+#define SVC_CONFIGSTRING 13
+ { SVC_CONFIGSTRING, "svc_configstring" },
+#define SVC_SPAWNBASELINE 14
+ { SVC_SPAWNBASELINE, "svc_spawnbaseline" },
+#define SVC_CENTERPRINT 15
+ { SVC_CENTERPRINT, "svc_centerprint" },
+#define SVC_DOWNLOAD 16
+ { SVC_DOWNLOAD, "svc_download" },
+#define SVC_PLAYERINFO 17
+ { SVC_PLAYERINFO, "svc_playerinfo" },
+#define SVC_PACKETENTITIES 18
+ { SVC_PACKETENTITIES, "svc_packetentities" },
+#define SVC_DELTAPACKETENTITIES 19
+ { SVC_DELTAPACKETENTITIES, "svc_deltapacketentities" },
+#define SVC_FRAME 20
+ { SVC_FRAME, "svc_frame" },
+ { 0, NULL }
+};
+
+static void
+dissect_quake2_server_commands(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ tvbuff_t *next_tvb = NULL;
+ proto_item *cmd_type_item = NULL;
+ guint8 server_cmd_type;
+ guint rest_length = 0;
+ int offset = 0;
+
+ server_cmd_type = tvb_get_guint8(tvb, offset);
+
+ if (tree) {
+ cmd_type_item = proto_tree_add_uint(tree,
+ hf_quake2_game_server_command, tvb, offset, 1, server_cmd_type);
+
+ if (cmd_type_item) {
+ proto_item_append_text(cmd_type_item, " (%s)",
+ val_to_str(server_cmd_type, names_server_cmd, "%u"));
+ }
+ }
+
+ offset++;
+ rest_length = tvb_reported_length(tvb) - offset;
+ if (rest_length)
+ next_tvb = tvb_new_subset(tvb, offset, rest_length, rest_length);
+ else
+ return;
+
+
+ switch (server_cmd_type) {
+ case SVC_BAD:
+ break;
+ case SVC_MUZZLEFLASH:
+ break;
+ case SVC_MUZZLEFLASH2:
+ break;
+ case SVC_TEMP_ENTITY:
+ break;
+ case SVC_LAYOUT:
+ break;
+ case SVC_NOP:
+ break;
+ case SVC_DISCONNECT:
+ break;
+ case SVC_RECONNECT:
+ break;
+ case SVC_SOUND:
+ break;
+ case SVC_PRINT:
+ break;
+ case SVC_STUFFTEXT:
+ break;
+ case SVC_SERVERDATA:
+ break;
+ case SVC_CONFIGSTRING:
+ break;
+ case SVC_SPAWNBASELINE:
+ break;
+ case SVC_CENTERPRINT:
+ break;
+ case SVC_DOWNLOAD:
+ break;
+ case SVC_PLAYERINFO:
+ break;
+ case SVC_PACKETENTITIES:
+ break;
+ case SVC_DELTAPACKETENTITIES:
+ break;
+ case SVC_FRAME:
+ break;
+
+ default:
+ break;
+ }
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+}
+
+
+static const value_string names_reliable[] = {
+ { 0, "Non Reliable" },
+ { 1, "Reliable" },
+ { 0, NULL }
+};
+
+
+static const value_string names_direction[] = {
+#define DIR_C2S 0
+ { DIR_C2S, "Client to Server" },
+#define DIR_S2C 1
+ { DIR_S2C, "Server to Client" },
+ { 0, NULL }
+};
+
+
+static void
+dissect_quake2_GamePacket(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int direction)
+{
+ proto_tree *game_tree = NULL;
+ proto_item *game_item = NULL;
+ guint32 seq1;
+ guint32 seq2;
+ int rel1;
+ int rel2;
+ int offset;
+ guint rest_length;
+
+ direction = (pinfo->destport == gbl_quake2ServerPort) ?
+ DIR_C2S : DIR_S2C;
+
+ if (tree) {
+ game_item = proto_tree_add_text(tree, tvb,
+ 0, -1, "Game");
+ if (game_item)
+ game_tree = proto_item_add_subtree(
+ game_item, ett_quake2_game);
+ }
+
+ offset = 0;
+
+ seq1 = tvb_get_letohl(tvb, offset);
+ rel1 = seq1 & 0x80000000 ? 1 : 0;
+ seq1 &= ~0x80000000;
+ if (game_tree) {
+ proto_item *seq1_item = proto_tree_add_text(game_tree,
+ tvb, offset, 4, "Current Sequence: %u (%s)",
+ seq1, val_to_str(rel1,names_reliable,"%u"));
+ if (seq1_item) {
+ proto_tree *seq1_tree = proto_item_add_subtree(
+ seq1_item, ett_quake2_game_seq1);
+ proto_tree_add_uint(seq1_tree, hf_quake2_game_seq1,
+ tvb, offset, 4, seq1);
+ proto_tree_add_boolean(seq1_tree, hf_quake2_game_rel1,
+ tvb, offset+3, 1, rel1);
+ }
+ }
+ offset += 4;
+
+ seq2 = tvb_get_letohl(tvb, offset);
+ rel2 = seq2 & 0x80000000 ? 1 : 0;
+ seq2 &= ~0x80000000;
+ if (game_tree) {
+ proto_item *seq2_item = proto_tree_add_text(game_tree,
+ tvb, offset, 4, "Acknowledge Sequence: %u (%s)",
+ seq2, val_to_str(rel2,names_reliable,"%u"));
+ if (seq2_item) {
+ proto_tree *seq2_tree = proto_item_add_subtree(
+ seq2_item, ett_quake2_game_seq2);
+ proto_tree_add_uint(seq2_tree, hf_quake2_game_seq2,
+ tvb, offset, 4, seq2);
+ proto_tree_add_boolean(seq2_tree, hf_quake2_game_rel2,
+ tvb, offset+3, 1, rel2);
+ }
+ }
+ offset += 4;
+
+ if (direction == DIR_C2S) {
+ /* client to server */
+ guint16 qport = tvb_get_letohs(tvb, offset);
+ if (game_tree) {
+ proto_tree_add_uint(game_tree, hf_quake2_game_qport,
+ tvb, offset, 2, qport);
+ }
+ offset +=2;
+ }
+
+ /* all the rest is pure game data */
+ rest_length = tvb_reported_length(tvb) - offset;
+ if (rest_length) {
+ tvbuff_t *next_tvb =
+ tvb_new_subset(tvb, offset, rest_length , rest_length);
+
+ if (direction == DIR_C2S) {
+ proto_item *c_item = NULL;
+ proto_tree *c_tree = NULL;
+ if (tree) {
+ c_item = proto_tree_add_text(game_tree, next_tvb,
+ 0, -1, "Client Commands");
+ if (c_item) {
+ c_tree = proto_item_add_subtree(
+ c_item, ett_quake2_game_clc);
+ }
+ }
+ dissect_quake2_client_commands(next_tvb, pinfo, c_tree);
+ }
+ else {
+ proto_item *c_item = NULL;
+ proto_tree *c_tree = NULL;
+ if (tree) {
+ c_item = proto_tree_add_text(game_tree, next_tvb,
+ 0, -1, "Server Commands");
+ if (c_item) {
+ c_tree = proto_item_add_subtree(
+ c_item, ett_quake2_game_svc);
+ }
+ }
+ dissect_quake2_server_commands(next_tvb, pinfo, c_tree);
+ }
+ }
+}
+
+
+static void
+dissect_quake2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *quake2_tree = NULL;
+ proto_item *quake2_item = NULL;
+ int direction;
+
+ direction = (pinfo->destport == gbl_quake2ServerPort) ?
+ DIR_C2S : DIR_S2C;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "QUAKE2");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str(direction,
+ names_direction, "%u"));
+
+ if (tree) {
+ quake2_item = proto_tree_add_item(tree, proto_quake2,
+ tvb, 0, -1, FALSE);
+ if (quake2_item)
+ quake2_tree = proto_item_add_subtree(
+ quake2_item, ett_quake2);
+ if (quake2_tree) {
+ proto_tree_add_uint_format(quake2_tree,
+ direction == DIR_S2C ?
+ hf_quake2_s2c :
+ hf_quake2_c2s,
+ tvb, 0, 0, 1,
+ "Direction: %s", val_to_str(direction, names_direction, "%u"));
+ }
+ }
+
+ if (tvb_get_ntohl(tvb, 0) == 0xffffffff) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, " Connectionless");
+ }
+ if (quake2_tree)
+ proto_tree_add_uint_format(quake2_tree,
+ hf_quake2_connectionless,
+ tvb, 0, 0, 1,
+ "Type: Connectionless");
+ dissect_quake2_ConnectionlessPacket(
+ tvb, pinfo, quake2_tree, direction);
+ }
+ else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, " Game");
+ }
+ if (quake2_tree)
+ proto_tree_add_uint_format(quake2_tree,
+ hf_quake2_game,
+ tvb, 0, 0, 1,
+ "Type: Game");
+ dissect_quake2_GamePacket(
+ tvb, pinfo, quake2_tree, direction);
+ }
+}
+
+
+void
+proto_reg_handoff_quake2(void)
+{
+ static int Initialized=FALSE;
+ static dissector_handle_t quake2_handle;
+ static int ServerPort=0;
+
+ if (!Initialized) {
+ quake2_handle = create_dissector_handle(dissect_quake2,
+ proto_quake2);
+ Initialized=TRUE;
+ } else {
+ dissector_delete("udp.port", ServerPort, quake2_handle);
+ }
+
+ /* set port for future deletes */
+ ServerPort=gbl_quake2ServerPort;
+
+ dissector_add("udp.port", gbl_quake2ServerPort, quake2_handle);
+ data_handle = find_dissector("data");
+}
+
+
+void
+proto_register_quake2(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_quake2_c2s,
+ { "Client to Server", "quake2.c2s",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Client to Server", HFILL }},
+ { &hf_quake2_s2c,
+ { "Server to Client", "quake2.s2c",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Server to Client", HFILL }},
+ { &hf_quake2_connectionless,
+ { "Connectionless", "quake2.connectionless",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Connectionless", HFILL }},
+ { &hf_quake2_game,
+ { "Game", "quake2.game",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Game", HFILL }},
+ { &hf_quake2_connectionless_marker,
+ { "Marker", "quake2.connectionless.marker",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Marker", HFILL }},
+ { &hf_quake2_connectionless_text,
+ { "Text", "quake2.connectionless.text",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Text", HFILL }},
+ { &hf_quake2_game_seq1,
+ { "Sequence Number", "quake2.game.seq1",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sequence number of the current packet", HFILL }},
+ { &hf_quake2_game_rel1,
+ { "Reliable", "quake2.game.rel1",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "Packet is reliable and may be retransmitted", HFILL }},
+ { &hf_quake2_game_seq2,
+ { "Sequence Number", "quake2.game.seq2",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sequence number of the last received packet", HFILL }},
+ { &hf_quake2_game_rel2,
+ { "Reliable", "quake2.game.rel2",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "Packet was reliable and may be retransmitted", HFILL }},
+ { &hf_quake2_game_qport,
+ { "QPort", "quake2.game.qport",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Quake II Client Port", HFILL }},
+ { &hf_quake2_game_client_command,
+ { "Client Command Type", "quake2.game.client.command",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Quake II Client Command", HFILL }},
+ { &hf_quake2_game_server_command,
+ { "Server Command", "quake2.game.server.command",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Quake II Server Command", HFILL }},
+ { &hf_quake2_game_client_command_move_chksum,
+ { "Checksum", "quake2.game.client.command.move.chksum",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Quake II Client Command Move", HFILL }},
+ { &hf_quake2_game_client_command_move_lframe,
+ { "Last Frame", "quake2.game.client.command.move.lframe",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Quake II Client Command Move", HFILL }},
+ { &hf_quake2_game_client_command_move,
+ { "Bitfield", "quake2.game.client.command.move",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Quake II Client Command Move", HFILL }},
+ { &hf_quake2_game_client_command_move_bitfield_angles1,
+ { "Angles (pitch)", "quake2.game.client.command.move.angles",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_quake2_game_client_command_move_vals),
+ CM_ANGLE1, "", HFILL }},
+ { &hf_quake2_game_client_command_move_bitfield_angles2,
+ { "Angles (yaw)", "quake2.game.client.command.move.angles",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_quake2_game_client_command_move_vals),
+ CM_ANGLE2, "", HFILL }},
+ { &hf_quake2_game_client_command_move_bitfield_angles3,
+ { "Angles (roll)", "quake2.game.client.command.move.angles",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_quake2_game_client_command_move_vals),
+ CM_ANGLE3, "", HFILL }},
+ { &hf_quake2_game_client_command_move_bitfield_movement_fwd,
+ { "Movement (fwd)", "quake2.game.client.command.move.movement",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_quake2_game_client_command_move_vals),
+ CM_FORWARD, "", HFILL }},
+ { &hf_quake2_game_client_command_move_bitfield_movement_side,
+ { "Movement (side)", "quake2.game.client.command.move.movement",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_quake2_game_client_command_move_vals),
+ CM_SIDE, "", HFILL }},
+ { &hf_quake2_game_client_command_move_bitfield_movement_up,
+ { "Movement (up)", "quake2.game.client.command.move.movement",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_quake2_game_client_command_move_vals),
+ CM_UP, "", HFILL }},
+ { &hf_quake2_game_client_command_move_bitfield_buttons,
+ { "Buttons", "quake2.game.client.command.move.buttons",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_quake2_game_client_command_move_vals),
+ CM_BUTTONS, "", HFILL }},
+ { &hf_quake2_game_client_command_move_bitfield_impulse,
+ { "Impulse", "quake2.game.client.command.move.impulse",
+ FT_UINT8, BASE_HEX,
+ VALS(hf_quake2_game_client_command_move_vals),
+ CM_IMPULSE, "", HFILL }},
+ { &hf_quake2_game_client_command_move_msec,
+ { "Msec", "quake2.game.client.command.move.msec",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Quake II Client Command Move", HFILL }},
+ { &hf_quake2_game_client_command_move_lightlevel,
+ { "Lightlevel", "quake2.game.client.command.move.lightlevel",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Quake II Client Command Move", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_quake2,
+ &ett_quake2_connectionless,
+ &ett_quake2_game,
+ &ett_quake2_game_seq1,
+ &ett_quake2_game_seq2,
+ &ett_quake2_game_clc,
+ &ett_quake2_game_svc,
+ &ett_quake2_game_clc_cmd,
+ &ett_quake2_game_svc_cmd,
+ &ett_quake2_game_clc_cmd_move_moves,
+ &ett_quake2_game_clc_cmd_move_bitfield
+ };
+ module_t *quake2_module;
+
+ proto_quake2 = proto_register_protocol("Quake II Network Protocol",
+ "QUAKE2", "quake2");
+ proto_register_field_array(proto_quake2, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register a configuration option for port */
+ quake2_module = prefs_register_protocol(proto_quake2,
+ proto_reg_handoff_quake2);
+ prefs_register_uint_preference(quake2_module, "udp.port",
+ "Quake II Server UDP Port",
+ "Set the UDP port for the Quake II Server",
+ 10, &gbl_quake2ServerPort);
+}
diff --git a/epan/dissectors/packet-quake3.c b/epan/dissectors/packet-quake3.c
new file mode 100644
index 0000000000..bb8fbb3403
--- /dev/null
+++ b/epan/dissectors/packet-quake3.c
@@ -0,0 +1,665 @@
+/* packet-quake3.c
+ * Routines for Quake III Arena packet dissection
+ *
+ * Uwe Girlich <uwe@planetquake.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-quake2.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+/*
+ All informations used in this decoding were gathered from
+ * some own captures of a private server,
+ * the "Server commands howto" document written by id Software
+ (http://www.quake3arena.com/tech/ServerCommandsHowto.html)
+ * source code of the game server browser tool qstat
+ (http://www.qstat.org).
+*/
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include <epan/resolv.h>
+
+static int proto_quake3 = -1;
+
+static int hf_quake3_direction = -1;
+static int hf_quake3_connectionless = -1;
+static int hf_quake3_game = -1;
+static int hf_quake3_connectionless_marker = -1;
+static int hf_quake3_connectionless_text = -1;
+static int hf_quake3_connectionless_command = -1;
+static int hf_quake3_server_addr = -1;
+static int hf_quake3_server_port = -1;
+static int hf_quake3_game_seq1 = -1;
+static int hf_quake3_game_rel1 = -1;
+static int hf_quake3_game_seq2 = -1;
+static int hf_quake3_game_rel2 = -1;
+static int hf_quake3_game_qport = -1;
+
+static gint ett_quake3 = -1;
+static gint ett_quake3_connectionless = -1;
+static gint ett_quake3_connectionless_text = -1;
+static gint ett_quake3_server = -1;
+static gint ett_quake3_game = -1;
+static gint ett_quake3_game_seq1 = -1;
+static gint ett_quake3_game_seq2 = -1;
+static gint ett_quake3_game_clc = -1;
+static gint ett_quake3_game_svc = -1;
+
+static dissector_handle_t data_handle;
+
+#define QUAKE3_SERVER_PORT 27960
+#define QUAKE3_MASTER_PORT 27950
+static unsigned int gbl_quake3_server_port=QUAKE3_SERVER_PORT;
+static unsigned int gbl_quake3_master_port=QUAKE3_MASTER_PORT;
+
+
+static const value_string names_direction[] = {
+#define DIR_UNKNOWN 0
+ { DIR_UNKNOWN, "Unknown" },
+#define DIR_C2S 1
+ { DIR_C2S, "Client to Server" },
+#define DIR_S2C 2
+ { DIR_S2C, "Server to Client" },
+#define DIR_C2M 3
+ { DIR_C2M, "Client to Master" },
+#define DIR_M2C 4
+ { DIR_M2C, "Master to Client" },
+ { 0, NULL }
+};
+
+
+#define string_starts_with(s1, s2) (strncmp((s1), (s2), strlen(s2)) == 0)
+
+
+static const value_string names_command[] = {
+#define COMMAND_UNKNOWN 0
+ { COMMAND_UNKNOWN, "Unknown" },
+#define COMMAND_statusResponse 1
+ { COMMAND_statusResponse, "Reply Status" },
+#define COMMAND_getstatus 2
+ { COMMAND_getstatus, "Request Status" },
+#define COMMAND_infoResponse 3
+ { COMMAND_infoResponse, "Reply Info" },
+#define COMMAND_getinfo 4
+ { COMMAND_getinfo, "Request Info" },
+#define COMMAND_challengeResponse 5
+ { COMMAND_challengeResponse, "Reply Challenge" },
+#define COMMAND_getchallenge 6
+ { COMMAND_getchallenge, "Request Challenge" },
+#define COMMAND_connectResponse 7
+ { COMMAND_connectResponse, "Reply Connect" },
+#define COMMAND_connect 8
+ { COMMAND_connect, "Request Connect" },
+#define COMMAND_rconResponse 9
+ { COMMAND_rconResponse, "Reply Remote Command" },
+#define COMMAND_rcon 10
+ { COMMAND_rcon, "Request Remote Command" },
+#define COMMAND_getmotdResponse 11
+ { COMMAND_getmotdResponse, "Reply Motto of the Day" },
+#define COMMAND_getmotd 12
+ { COMMAND_getmotd, "Request Motto of the Day" },
+#define COMMAND_getserversResponse 13
+ { COMMAND_getserversResponse, "Reply Servers" },
+#define COMMAND_getservers 14
+ { COMMAND_getservers, "Request Servers" },
+#define COMMAND_getKeyAuthorize 15
+ { COMMAND_getKeyAuthorize, "Request Key Authorization" },
+#define COMMAND_getIpAuthorize 16
+ { COMMAND_getIpAuthorize, "Request IP Authorization" },
+#define COMMAND_ipAuthorize 17
+ { COMMAND_ipAuthorize, "Reply IP Authorization" },
+ { 0, NULL }
+};
+
+
+static void
+dissect_quake3_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, int* direction)
+{
+ proto_tree *cl_tree = NULL;
+ proto_item *cl_item = NULL;
+ proto_item *text_item = NULL;
+ proto_tree *text_tree = NULL;
+ guint8 text[2048];
+ int len;
+ int offset;
+ guint32 marker;
+ int command;
+ int command_len;
+ int command_finished = FALSE;
+
+ marker = tvb_get_ntohl(tvb, 0);
+ if (tree) {
+ cl_item = proto_tree_add_text(tree, tvb,
+ 0, -1, "Connectionless");
+ if (cl_item)
+ cl_tree = proto_item_add_subtree(
+ cl_item, ett_quake3_connectionless);
+ }
+
+ if (cl_tree) {
+ proto_tree_add_uint(cl_tree, hf_quake3_connectionless_marker,
+ tvb, 0, 4, marker);
+ }
+
+ /* all the rest of the packet is just text */
+ offset = 4;
+
+ len = tvb_get_nstringz0(tvb, offset, sizeof(text), text);
+ if (cl_tree) {
+ text_item = proto_tree_add_string(cl_tree,
+ hf_quake3_connectionless_text,
+ tvb, offset, len + 1, text);
+ if (text_item) {
+ text_tree = proto_item_add_subtree(
+ text_item,
+ ett_quake3_connectionless_text);
+ }
+ }
+
+ command = COMMAND_UNKNOWN;
+ command_len = 0;
+
+ if (strncmp(text, "statusResponse", 14) == 0) {
+ command = COMMAND_statusResponse;
+ *direction = DIR_S2C;
+ command_len = 14;
+ }
+ else if (strncmp(text, "getstatus", 9) == 0) {
+ command = COMMAND_getstatus;
+ *direction = DIR_C2S;
+ command_len = 9;
+ }
+ else if (strncmp(text, "infoResponse", 12) == 0) {
+ command = COMMAND_infoResponse;
+ *direction = DIR_S2C;
+ command_len = 12;
+ }
+ else if (strncmp(text, "getinfo", 7) == 0) {
+ command = COMMAND_getinfo;
+ *direction = DIR_C2S;
+ command_len = 7;
+ }
+ else if (strncmp(text, "challengeResponse", 17) == 0) {
+ command = COMMAND_challengeResponse;
+ *direction = DIR_S2C;
+ command_len = 17;
+ }
+ else if (strncmp(text, "getchallenge", 12) == 0) {
+ command = COMMAND_getchallenge;
+ *direction = DIR_C2S;
+ command_len = 12;
+ }
+ else if (strncmp(text, "connectResponse", 15) == 0) {
+ command = COMMAND_connectResponse;
+ *direction = DIR_S2C;
+ command_len = 15;
+ }
+ else if (strncmp(text, "connect", 7) == 0) {
+ command = COMMAND_connect;
+ *direction = DIR_C2S;
+ command_len = 7;
+ }
+ else if (strncmp(text, "rconResponse", 12) == 0) {
+ command = COMMAND_rconResponse;
+ *direction = DIR_S2C;
+ command_len = 12;
+ }
+ else if (strncmp(text, "rcon", 4) == 0) {
+ command = COMMAND_rcon;
+ *direction = DIR_C2S;
+ command_len = 4;
+ }
+ else if (strncmp(text, "getmotdResponse", 15) == 0) {
+ command = COMMAND_getmotdResponse;
+ *direction = DIR_M2C;
+ command_len = 15;
+ }
+ else if (strncmp(text, "getmotd", 7) == 0) {
+ command = COMMAND_getmotd;
+ *direction = DIR_C2M;
+ command_len = 7;
+ }
+ else if (strncmp(text, "getserversResponse", 18) == 0) {
+ int base;
+ command = COMMAND_getserversResponse;
+ *direction = DIR_M2C;
+ command_len = 18;
+ /* The data can contain 0's, and the text string is binary
+ anyway, so better replace the text string after the first
+ \ with "<DATA>". */
+ if (text_item) {
+ /* first correct the length until the end of the packet */
+ proto_item_set_len(text_item, tvb_length_remaining(tvb, offset));
+ /* then replace the text */
+ proto_item_set_text(text_item, "Text: getserversResponse<DATA>");
+ }
+ if (text_tree)
+ proto_tree_add_string(text_tree, hf_quake3_connectionless_command,
+ tvb, offset, command_len,
+ val_to_str(command, names_command, "Unknown"));
+ command_finished = TRUE;
+
+ /* now we decode all the rest */
+ base = offset + 18;
+ /* '/', ip-address in network order, port in network order */
+ while (tvb_reported_length_remaining(tvb, base) >= 7) {
+ guint32 ip_addr;
+ guint16 udp_port;
+ proto_item *server_item = NULL;
+ proto_tree *server_tree = NULL;
+
+ tvb_memcpy(tvb, (guint8 *)&ip_addr, base + 1, 4);
+ udp_port = tvb_get_ntohs(tvb, base + 5);
+
+ /* It may be a good idea to create a conversation for
+ every server in this list, as we'll see at
+ least a getinfo request to each of them and they
+ may run on totally unusual ports. */
+
+ if (text_tree) {
+ server_item = proto_tree_add_text(text_tree,
+ tvb, base, 7,
+ "Server: %s:%u",
+ get_hostname(ip_addr),
+ udp_port);
+ if (server_item)
+ server_tree = proto_item_add_subtree(
+ server_item,
+ ett_quake3_server);
+ }
+ if (server_tree) {
+ proto_tree_add_ipv4(server_tree, hf_quake3_server_addr,
+ tvb, base + 1, 4, ip_addr);
+ proto_tree_add_uint(server_tree, hf_quake3_server_port,
+ tvb, base + 5, 2, udp_port);
+ }
+
+ base += 7;
+ }
+ }
+ else if (strncmp(text, "getservers", 10) == 0) {
+ command = COMMAND_getservers;
+ *direction = DIR_C2M;
+ command_len = 10;
+ }
+ else if (strncmp(text, "getKeyAuthorize", 15) == 0) {
+ command = COMMAND_getKeyAuthorize;
+ *direction = DIR_C2M;
+ command_len = 15;
+ }
+ else if (strncmp(text, "getIpAuthorize", 14) == 0) {
+ command = COMMAND_getIpAuthorize;
+ *direction = DIR_C2M;
+ command_len = 14;
+ }
+ else if (strncmp(text, "ipAuthorize", 11) == 0) {
+ command = COMMAND_ipAuthorize;
+ *direction = DIR_M2C;
+ command_len = 11;
+ }
+ else {
+ *direction = DIR_UNKNOWN;
+ }
+
+ if (text_tree && command_finished == FALSE) {
+ proto_tree_add_string(text_tree, hf_quake3_connectionless_command,
+ tvb, offset, command_len,
+ val_to_str(command, names_command, "Unknown"));
+ }
+
+ offset += len + 1;
+
+}
+
+
+static void
+dissect_quake3_client_commands(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ /* this shouldn't be too difficult */
+ call_dissector(data_handle,tvb, pinfo, tree);
+}
+
+
+static void
+dissect_quake3_server_commands(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ /* It is totally forbidden to decode this any further,
+ I wont do it. */
+ call_dissector(data_handle,tvb, pinfo, tree);
+}
+
+
+static const value_string names_reliable[] = {
+ { 0, "Non Reliable" },
+ { 1, "Reliable" },
+ { 0, NULL }
+};
+
+
+static void
+dissect_quake3_GamePacket(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int *direction)
+{
+ proto_tree *game_tree = NULL;
+ proto_item *game_item = NULL;
+ guint32 seq1;
+ guint32 seq2;
+ int rel1;
+ int rel2;
+ int offset;
+ guint rest_length;
+
+ *direction = (pinfo->destport == gbl_quake3_server_port) ?
+ DIR_C2S : DIR_S2C;
+
+ if (tree) {
+ game_item = proto_tree_add_text(tree, tvb,
+ 0, -1, "Game");
+ if (game_item)
+ game_tree = proto_item_add_subtree(
+ game_item, ett_quake3_game);
+ }
+
+ offset = 0;
+
+ seq1 = tvb_get_letohs(tvb, offset);
+ rel1 = seq1 & 0x8000 ? 1 : 0;
+ seq1 &= ~0x8000;
+ if (game_tree) {
+ proto_item *seq1_item = proto_tree_add_text(game_tree,
+ tvb, offset, 2, "Current Sequence: %u (%s)",
+ seq1, val_to_str(rel1,names_reliable,"%u"));
+ if (seq1_item) {
+ proto_tree *seq1_tree = proto_item_add_subtree(
+ seq1_item, ett_quake3_game_seq1);
+ proto_tree_add_uint(seq1_tree, hf_quake3_game_seq1,
+ tvb, offset, 2, seq1);
+ proto_tree_add_boolean(seq1_tree, hf_quake3_game_rel1,
+ tvb, offset+1, 1, rel1);
+ }
+ }
+ offset += 2;
+
+ seq2 = tvb_get_letohs(tvb, offset);
+ rel2 = seq2 & 0x8000 ? 1 : 0;
+ seq2 &= ~0x8000;
+ if (game_tree) {
+ proto_item *seq2_item = proto_tree_add_text(game_tree,
+ tvb, offset, 2, "Acknowledge Sequence: %u (%s)",
+ seq2, val_to_str(rel2,names_reliable,"%u"));
+ if (seq2_item) {
+ proto_tree *seq2_tree = proto_item_add_subtree(
+ seq2_item, ett_quake3_game_seq2);
+ proto_tree_add_uint(seq2_tree, hf_quake3_game_seq2,
+ tvb, offset, 2, seq2);
+ proto_tree_add_boolean(seq2_tree, hf_quake3_game_rel2,
+ tvb, offset+1, 1, rel2);
+ }
+ }
+ offset += 2;
+
+ if (*direction == DIR_C2S) {
+ /* client to server */
+ guint16 qport = tvb_get_letohs(tvb, offset);
+ if (game_tree) {
+ proto_tree_add_uint(game_tree, hf_quake3_game_qport,
+ tvb, offset, 2, qport);
+ }
+ offset +=2;
+ }
+
+ /* all the rest is pure game data */
+ rest_length = tvb_reported_length(tvb) - offset;
+ if (rest_length) {
+ tvbuff_t *next_tvb =
+ tvb_new_subset(tvb, offset, rest_length , rest_length);
+
+ if (*direction == DIR_C2S) {
+ proto_item *c_item = NULL;
+ proto_tree *c_tree = NULL;
+ if (tree) {
+ c_item = proto_tree_add_text(game_tree, next_tvb,
+ 0, -1, "Client Commands");
+ if (c_item) {
+ c_tree = proto_item_add_subtree(
+ c_item, ett_quake3_game_clc);
+ }
+ }
+ dissect_quake3_client_commands(next_tvb, pinfo, c_tree);
+ }
+ else {
+ proto_item *c_item = NULL;
+ proto_tree *c_tree = NULL;
+ if (tree) {
+ c_item = proto_tree_add_text(game_tree, next_tvb,
+ 0, -1, "Server Commands");
+ if (c_item) {
+ c_tree = proto_item_add_subtree(
+ c_item, ett_quake3_game_svc);
+ }
+ }
+ dissect_quake3_server_commands(next_tvb, pinfo, c_tree);
+ }
+ }
+}
+
+
+static void
+dissect_quake3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *quake3_tree = NULL;
+ proto_item *quake3_item = NULL;
+ proto_item *dir_item = NULL;
+ int direction;
+
+ direction = DIR_UNKNOWN;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "QUAKE3");
+
+ if (tree) {
+ quake3_item = proto_tree_add_item(tree, proto_quake3,
+ tvb, 0, -1, FALSE);
+ if (quake3_item)
+ quake3_tree = proto_item_add_subtree(
+ quake3_item, ett_quake3);
+
+ if (quake3_tree) {
+ dir_item = proto_tree_add_none_format(
+ quake3_tree,
+ hf_quake3_direction, tvb, 0, 0,
+ "Direction: %s",
+ val_to_str(direction,
+ names_direction, "%u"));
+ }
+ }
+
+ if (tvb_get_ntohl(tvb, 0) == 0xffffffff) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Connectionless ");
+ }
+ if (quake3_tree)
+ proto_tree_add_uint_format(quake3_tree,
+ hf_quake3_connectionless,
+ tvb, 0, 0, 1,
+ "Type: Connectionless");
+ dissect_quake3_ConnectionlessPacket(
+ tvb, pinfo, quake3_tree, &direction);
+ }
+ else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Game ");
+ }
+ if (quake3_tree)
+ proto_tree_add_uint_format(quake3_tree,
+ hf_quake3_game,
+ tvb, 0, 0, 1,
+ "Type: Game");
+ dissect_quake3_GamePacket(
+ tvb, pinfo, quake3_tree, &direction);
+ }
+ if (direction != DIR_UNKNOWN && dir_item)
+ proto_item_set_text(dir_item,
+ "Direction: %s",
+ val_to_str(direction,
+ names_direction, "%u"));
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, val_to_str(direction,
+ names_direction, "%u"));
+}
+
+
+void
+proto_reg_handoff_quake3(void)
+{
+ static int initialized=FALSE;
+ static dissector_handle_t quake3_handle;
+ static int server_port;
+ static int master_port;
+ int i;
+
+ if (!initialized) {
+ quake3_handle = create_dissector_handle(dissect_quake3,
+ proto_quake3);
+ initialized=TRUE;
+ } else {
+ for (i=0;i<4;i++)
+ dissector_delete("udp.port", server_port+i, quake3_handle);
+ for (i=0;i<4;i++)
+ dissector_delete("udp.port", master_port+i, quake3_handle);
+ }
+
+ /* set port for future deletes */
+ server_port = gbl_quake3_server_port;
+ master_port = gbl_quake3_master_port;
+
+ /* add dissectors */
+ for (i=0;i<4;i++)
+ dissector_add("udp.port", gbl_quake3_server_port + i,
+ quake3_handle);
+ for (i=0;i<4;i++)
+ dissector_add("udp.port", gbl_quake3_master_port + i,
+ quake3_handle);
+ data_handle = find_dissector("data");
+}
+
+
+void
+proto_register_quake3(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_quake3_direction,
+ { "Direction", "quake3.direction",
+ FT_NONE, BASE_DEC, NULL, 0x0,
+ "Packet Direction", HFILL }},
+ { &hf_quake3_connectionless,
+ { "Connectionless", "quake3.connectionless",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Connectionless", HFILL }},
+ { &hf_quake3_game,
+ { "Game", "quake3.game",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Game", HFILL }},
+ { &hf_quake3_connectionless_marker,
+ { "Marker", "quake3.connectionless.marker",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Marker", HFILL }},
+ { &hf_quake3_connectionless_text,
+ { "Text", "quake3.connectionless.text",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Text", HFILL }},
+ { &hf_quake3_connectionless_command,
+ { "Command", "quake3.connectionless.command",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Command", HFILL }},
+ { &hf_quake3_server_addr,
+ { "Server Address", "quake3.server.addr",
+ FT_IPv4, BASE_DEC, NULL, 0x0,
+ "Server IP Address", HFILL }},
+ { &hf_quake3_server_port,
+ { "Server Port", "quake3.server.port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Server UDP Port", HFILL }},
+ { &hf_quake3_game_seq1,
+ { "Sequence Number", "quake3.game.seq1",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sequence number of the current packet", HFILL }},
+ { &hf_quake3_game_rel1,
+ { "Reliable", "quake3.game.rel1",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "Packet is reliable and may be retransmitted", HFILL }},
+ { &hf_quake3_game_seq2,
+ { "Sequence Number", "quake3.game.seq2",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sequence number of the last received packet", HFILL }},
+ { &hf_quake3_game_rel2,
+ { "Reliable", "quake3.game.rel2",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "Packet was reliable and may be retransmitted", HFILL }},
+ { &hf_quake3_game_qport,
+ { "QPort", "quake3.game.qport",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Quake III Arena Client Port", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_quake3,
+ &ett_quake3_connectionless,
+ &ett_quake3_connectionless_text,
+ &ett_quake3_server,
+ &ett_quake3_game,
+ &ett_quake3_game_seq1,
+ &ett_quake3_game_seq2,
+ &ett_quake3_game_clc,
+ &ett_quake3_game_svc
+ };
+ module_t *quake3_module;
+
+ proto_quake3 = proto_register_protocol("Quake III Arena Network Protocol",
+ "QUAKE3", "quake3");
+ proto_register_field_array(proto_quake3, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register a configuration option for port */
+ quake3_module = prefs_register_protocol(proto_quake3,
+ proto_reg_handoff_quake3);
+ prefs_register_uint_preference(quake3_module, "udp.arena_port",
+ "Quake III Arena Server UDP Base Port",
+ "Set the UDP base port for the Quake III Arena Server",
+ 10, &gbl_quake3_server_port);
+ prefs_register_uint_preference(quake3_module, "udp.master_port",
+ "Quake III Arena Master Server UDP Base Port",
+ "Set the UDP base port for the Quake III Arena Master Server",
+ 10, &gbl_quake3_master_port);
+}
diff --git a/epan/dissectors/packet-quakeworld.c b/epan/dissectors/packet-quakeworld.c
new file mode 100644
index 0000000000..5af335a52a
--- /dev/null
+++ b/epan/dissectors/packet-quakeworld.c
@@ -0,0 +1,913 @@
+/* packet-quakeworld.c
+ * Routines for QuakeWorld packet dissection
+ *
+ * Uwe Girlich <uwe@planetquake.com>
+ * http://www.idsoftware.com/q1source/q1source.zip
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-quake.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "prefs.h"
+
+static int proto_quakeworld = -1;
+
+static int hf_quakeworld_s2c = -1;
+static int hf_quakeworld_c2s = -1;
+static int hf_quakeworld_connectionless = -1;
+static int hf_quakeworld_game = -1;
+static int hf_quakeworld_connectionless_marker = -1;
+static int hf_quakeworld_connectionless_text = -1;
+static int hf_quakeworld_connectionless_command = -1;
+static int hf_quakeworld_connectionless_arguments = -1;
+static int hf_quakeworld_connectionless_connect_version = -1;
+static int hf_quakeworld_connectionless_connect_qport = -1;
+static int hf_quakeworld_connectionless_connect_challenge = -1;
+static int hf_quakeworld_connectionless_connect_infostring = -1;
+static int hf_quakeworld_connectionless_connect_infostring_key_value = -1;
+static int hf_quakeworld_connectionless_connect_infostring_key = -1;
+static int hf_quakeworld_connectionless_connect_infostring_value = -1;
+static int hf_quakeworld_connectionless_rcon_password = -1;
+static int hf_quakeworld_connectionless_rcon_command = -1;
+static int hf_quakeworld_game_seq1 = -1;
+static int hf_quakeworld_game_rel1 = -1;
+static int hf_quakeworld_game_seq2 = -1;
+static int hf_quakeworld_game_rel2 = -1;
+static int hf_quakeworld_game_qport = -1;
+
+static gint ett_quakeworld = -1;
+static gint ett_quakeworld_connectionless = -1;
+static gint ett_quakeworld_connectionless_text = -1;
+static gint ett_quakeworld_connectionless_arguments = -1;
+static gint ett_quakeworld_connectionless_connect_infostring = -1;
+static gint ett_quakeworld_connectionless_connect_infostring_key_value = -1;
+static gint ett_quakeworld_game = -1;
+static gint ett_quakeworld_game_seq1 = -1;
+static gint ett_quakeworld_game_seq2 = -1;
+static gint ett_quakeworld_game_clc = -1;
+static gint ett_quakeworld_game_svc = -1;
+
+static dissector_handle_t data_handle;
+
+/*
+ helper functions, they may ave to go somewhere else
+ they are mostly copied without change from
+ quakeworldsource/client/cmd.c
+ quakeworldsource/client/common.c
+*/
+
+#define MAX_TEXT_SIZE 2048
+
+static char com_token[MAX_TEXT_SIZE+1];
+static int com_token_start;
+static int com_token_length;
+
+static char *
+COM_Parse (char *data)
+{
+ int c;
+ int len;
+
+ len = 0;
+ com_token[0] = 0;
+ com_token_start = 0;
+ com_token_length = 0;
+
+ if (data == NULL)
+ return NULL;
+
+ /* skip whitespace */
+skipwhite:
+ while ( (c = *data) <= ' ') {
+ if (c == 0)
+ return NULL; /* end of file; */
+ data++;
+ com_token_start++;
+ }
+
+ /* skip // comments */
+ if (c=='/' && data[1] == '/') {
+ while (*data && *data != '\n')
+ data++;
+ com_token_start++;
+ goto skipwhite;
+ }
+
+ /* handle quoted strings specially */
+ if (c == '\"') {
+ data++;
+ com_token_start++;
+ while (1) {
+ c = *data++;
+ if (c=='\"' || c==0) {
+ com_token[len] = 0;
+ return data;
+ }
+ com_token[len] = c;
+ len++;
+ com_token_length++;
+ }
+ }
+
+ /* parse a regular word */
+ do {
+ com_token[len] = c;
+ data++;
+ len++;
+ com_token_length++;
+ c = *data;
+ } while (c>32);
+
+ com_token[len] = 0;
+ return data;
+}
+
+
+#define MAX_ARGS 80
+static int cmd_argc = 0;
+static char *cmd_argv[MAX_ARGS];
+static char *cmd_null_string = "";
+static int cmd_argv_start[MAX_ARGS];
+static int cmd_argv_length[MAX_ARGS];
+
+
+
+static int
+Cmd_Argc(void)
+{
+ return cmd_argc;
+}
+
+
+static char*
+Cmd_Argv(int arg)
+{
+ if ( arg >= cmd_argc )
+ return cmd_null_string;
+ return cmd_argv[arg];
+}
+
+
+static int
+Cmd_Argv_start(int arg)
+{
+ if ( arg >= cmd_argc )
+ return 0;
+ return cmd_argv_start[arg];
+}
+
+
+static int
+Cmd_Argv_length(int arg)
+{
+ if ( arg >= cmd_argc )
+ return 0;
+ return cmd_argv_length[arg];
+}
+
+
+static void
+Cmd_TokenizeString(char* text)
+{
+ int i;
+ int start;
+ int length;
+
+
+ /* clear the args from the last string */
+ for (i=0 ; i<cmd_argc ; i++)
+ g_free(cmd_argv[i]);
+
+ cmd_argc = 0;
+
+ start = 0;
+ while (TRUE) {
+
+ /* skip whitespace up to a \n */
+ while (*text && *text <= ' ' && *text != '\n') {
+ text++;
+ start++;
+ }
+
+ length = 0;
+
+ if (*text == '\n') {
+ /* a newline seperates commands in the buffer */
+ text++;
+ break;
+ }
+
+ if (!*text)
+ return;
+
+ text = COM_Parse (text);
+ if (!text)
+ return;
+
+ if (cmd_argc < MAX_ARGS) {
+ cmd_argv[cmd_argc] = g_strdup(com_token);
+ cmd_argv_start[cmd_argc] = start + com_token_start;
+ cmd_argv_length[cmd_argc] = com_token_length;
+ cmd_argc++;
+ }
+
+ start += com_token_start + com_token_length;
+ }
+}
+
+
+static void
+dissect_id_infostring(tvbuff_t *tvb, proto_tree* tree,
+ int offset, char* infostring,
+ gint ett_key_value, int hf_key_value, int hf_key, int hf_value)
+{
+ char * newpos = infostring;
+ int end_of_info = FALSE;
+
+ /* to look at all the key/value pairs, we destroy infostring */
+ while(!end_of_info) {
+ char* keypos;
+ char* valuepos;
+ int keylength;
+ char* keyvaluesep;
+ int valuelength;
+ char* valueend;
+
+ keypos = newpos;
+ if (*keypos == 0) break;
+ if (*keypos == '\\') keypos++;
+
+ for (keylength = 0
+ ;
+ *(keypos + keylength) != '\\' &&
+ *(keypos + keylength) != 0
+ ;
+ keylength++) ;
+ keyvaluesep = keypos + keylength;
+ if (*keyvaluesep == 0) break;
+ valuepos = keyvaluesep+1;
+ for (valuelength = 0
+ ;
+ *(valuepos + valuelength) != '\\' &&
+ *(valuepos + valuelength) != 0
+ ;
+ valuelength++) ;
+ valueend = valuepos + valuelength;
+ if (*valueend == 0) {
+ end_of_info = TRUE;
+ }
+ *(keyvaluesep) = '=';
+ *(valueend) = 0;
+
+ if (tree) {
+ proto_item* sub_item = NULL;
+ proto_tree* sub_tree = NULL;
+
+ sub_item = proto_tree_add_string(tree,
+ hf_key_value,
+ tvb,
+ offset + (keypos-infostring),
+ keylength + 1 + valuelength, keypos);
+ if (sub_item)
+ sub_tree =
+ proto_item_add_subtree(
+ sub_item,
+ ett_key_value);
+ *(keyvaluesep) = 0;
+ if (sub_tree) {
+ proto_tree_add_string(sub_tree,
+ hf_key,
+ tvb,
+ offset + (keypos-infostring),
+ keylength, keypos);
+ proto_tree_add_string(sub_tree,
+ hf_value,
+ tvb,
+ offset + (valuepos-infostring),
+ valuelength, valuepos);
+ }
+ }
+ newpos = valueend + 1;
+ }
+}
+
+
+static const value_string names_direction[] = {
+#define DIR_C2S 0
+ { DIR_C2S, "Client to Server" },
+#define DIR_S2C 1
+ { DIR_S2C, "Server to Client" },
+ { 0, NULL }
+};
+
+
+/* I took this name and value directly out of the QW source. */
+#define PORT_MASTER 27500
+static unsigned int gbl_quakeworldServerPort=PORT_MASTER;
+
+
+/* out of band message id bytes (taken out of quakeworldsource/client/protocol.h */
+
+/* M = master, S = server, C = client, A = any */
+/* the second character will allways be \n if the message isn't a single */
+/* byte long (?? not true anymore?) */
+
+#define S2C_CHALLENGE 'c'
+#define S2C_CONNECTION 'j'
+#define A2A_PING 'k' /* respond with an A2A_ACK */
+#define A2A_ACK 'l' /* general acknowledgement without info */
+#define A2A_NACK 'm' /* [+ comment] general failure */
+#define A2A_ECHO 'e' /* for echoing */
+#define A2C_PRINT 'n' /* print a message on client */
+
+#define S2M_HEARTBEAT 'a' /* + serverinfo + userlist + fraglist */
+#define A2C_CLIENT_COMMAND 'B' /* + command line */
+#define S2M_SHUTDOWN 'C'
+
+
+static void
+dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int direction)
+{
+ proto_tree *cl_tree = NULL;
+ proto_item *cl_item = NULL;
+ proto_item *text_item = NULL;
+ proto_tree *text_tree = NULL;
+ guint8 text[MAX_TEXT_SIZE+1];
+ int len;
+ int offset;
+ guint32 marker;
+ int command_len;
+ char command[MAX_TEXT_SIZE+1];
+ int command_finished = FALSE;
+
+ marker = tvb_get_ntohl(tvb, 0);
+ if (tree) {
+ cl_item = proto_tree_add_text(tree, tvb,
+ 0, -1, "Connectionless");
+ if (cl_item)
+ cl_tree = proto_item_add_subtree(
+ cl_item, ett_quakeworld_connectionless);
+ }
+
+ if (cl_tree) {
+ proto_tree_add_uint(cl_tree, hf_quakeworld_connectionless_marker,
+ tvb, 0, 4, marker);
+ }
+
+ /* all the rest of the packet is just text */
+ offset = 4;
+
+ len = tvb_get_nstringz0(tvb, offset, sizeof(text), text);
+ /* actually, we should look for a eol char and stop already there */
+
+ if (cl_tree) {
+ text_item = proto_tree_add_string(cl_tree, hf_quakeworld_connectionless_text,
+ tvb, offset, len + 1, text);
+ if (text_item) {
+ text_tree = proto_item_add_subtree(
+ text_item, ett_quakeworld_connectionless_text);
+ }
+ }
+
+ if (direction == DIR_C2S) {
+ /* client to sever commands */
+ char *c;
+
+ Cmd_TokenizeString(text);
+ c = Cmd_Argv(0);
+
+ /* client to sever commands */
+ if (strcmp(c,"ping") == 0) {
+ strcpy(command, "Ping");
+ command_len = 4;
+ } else if (strcmp(c,"status") == 0) {
+ strcpy(command, "Status");
+ command_len = 6;
+ } else if (strcmp(c,"log") == 0) {
+ strcpy(command, "Status");
+ command_len = 3;
+ } else if (strcmp(c,"connect") == 0) {
+ int version;
+ int qport;
+ int challenge;
+ char *infostring;
+ proto_item *argument_item = NULL;
+ proto_tree *argument_tree = NULL;
+ proto_item *info_item = NULL;
+ proto_tree *info_tree = NULL;
+ strcpy(command, "Connect");
+ command_len = Cmd_Argv_length(0);
+ if (text_tree) {
+ proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command,
+ tvb, offset, command_len, command);
+ argument_item = proto_tree_add_string(text_tree,
+ hf_quakeworld_connectionless_arguments,
+ tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1),
+ text + Cmd_Argv_start(1));
+ if (argument_item) {
+ argument_tree =
+ proto_item_add_subtree(argument_item,
+ ett_quakeworld_connectionless_arguments);
+ }
+ command_finished=TRUE;
+ }
+ version = atoi(Cmd_Argv(1));
+ qport = atoi(Cmd_Argv(2));
+ challenge = atoi(Cmd_Argv(3));
+ infostring = Cmd_Argv(4);
+ if (argument_tree) {
+ proto_tree_add_uint(argument_tree,
+ hf_quakeworld_connectionless_connect_version,
+ tvb,
+ offset + Cmd_Argv_start(1),
+ Cmd_Argv_length(1), version);
+ proto_tree_add_uint(argument_tree,
+ hf_quakeworld_connectionless_connect_qport,
+ tvb,
+ offset + Cmd_Argv_start(2),
+ Cmd_Argv_length(2), qport);
+ proto_tree_add_int(argument_tree,
+ hf_quakeworld_connectionless_connect_challenge,
+ tvb,
+ offset + Cmd_Argv_start(3),
+ Cmd_Argv_length(3), challenge);
+ info_item = proto_tree_add_string(argument_tree,
+ hf_quakeworld_connectionless_connect_infostring,
+ tvb,
+ offset + Cmd_Argv_start(4),
+ Cmd_Argv_length(4), infostring);
+ if (info_item)
+ info_tree = proto_item_add_subtree(
+ info_item, ett_quakeworld_connectionless_connect_infostring);
+ dissect_id_infostring(tvb, info_tree, offset + Cmd_Argv_start(4),
+ infostring,
+ ett_quakeworld_connectionless_connect_infostring_key_value,
+ hf_quakeworld_connectionless_connect_infostring_key_value,
+ hf_quakeworld_connectionless_connect_infostring_key,
+ hf_quakeworld_connectionless_connect_infostring_value);
+ }
+ } else if (strcmp(c,"getchallenge") == 0) {
+ strcpy(command, "Get Challenge");
+ command_len = Cmd_Argv_length(0);
+ } else if (strcmp(c,"rcon") == 0) {
+ char* password;
+ int i;
+ char remaining[MAX_TEXT_SIZE+1];
+ proto_item *argument_item = NULL;
+ proto_tree *argument_tree = NULL;
+ strcpy(command, "Remote Command");
+ command_len = Cmd_Argv_length(0);
+ if (text_tree) {
+ proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command,
+ tvb, offset, command_len, command);
+ argument_item = proto_tree_add_string(text_tree,
+ hf_quakeworld_connectionless_arguments,
+ tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1),
+ text + Cmd_Argv_start(1));
+ if (argument_item) {
+ argument_tree =
+ proto_item_add_subtree(argument_item,
+ ett_quakeworld_connectionless_arguments);
+ }
+ command_finished=TRUE;
+ }
+ password = Cmd_Argv(1);
+ if (argument_tree) {
+ proto_tree_add_string(argument_tree,
+ hf_quakeworld_connectionless_rcon_password,
+ tvb,
+ offset + Cmd_Argv_start(1),
+ Cmd_Argv_length(1), password);
+ }
+ for (i=2; i<Cmd_Argc() ; i++) {
+ remaining[0] = 0;
+ strcat (remaining, Cmd_Argv(i) );
+ strcat (remaining, " ");
+ }
+ if (text_tree) {
+ proto_tree_add_string(argument_tree,
+ hf_quakeworld_connectionless_rcon_command,
+ tvb, offset + Cmd_Argv_start(2),
+ Cmd_Argv_start(Cmd_Argc()-1) + Cmd_Argv_length(Cmd_Argc()-1) -
+ Cmd_Argv_start(2),
+ remaining);
+ }
+ } else if (c[0]==A2A_PING && ( c[1]==0 || c[1]=='\n')) {
+ strcpy(command, "Ping");
+ command_len = 1;
+ } else if (c[0]==A2A_ACK && ( c[1]==0 || c[1]=='\n')) {
+ strcpy(command, "Ack");
+ command_len = 1;
+ } else {
+ strcpy(command, "Unknown");
+ command_len = len;
+ }
+ }
+ else {
+ /* server to client commands */
+ if (text[0] == S2C_CONNECTION) {
+ strcpy(command, "Connected");
+ command_len = 1;
+ } else if (text[0] == A2C_CLIENT_COMMAND) {
+ strcpy(command, "Client Command");
+ command_len = 1;
+ /* stringz (command), stringz (localid) */
+ } else if (text[0] == A2C_PRINT) {
+ strcpy(command, "Print");
+ command_len = 1;
+ /* string */
+ } else if (text[0] == A2A_PING) {
+ strcpy(command, "Ping");
+ command_len = 1;
+ } else if (text[0] == S2C_CHALLENGE) {
+ strcpy(command, "Challenge");
+ command_len = 1;
+ /* string, atoi */
+ } else {
+ strcpy(command, "Unknown");
+ command_len = len;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", command);
+ }
+
+ if (text_tree && !command_finished) {
+ proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command,
+ tvb, offset, command_len, command);
+ }
+ offset += len + 1;
+}
+
+
+static void
+dissect_quakeworld_client_commands(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ /* If I have too much time at hand, I'll fill it with all
+ the information from my QWD specs:
+ http://www.planetquake.com/demospecs/qwd/
+ */
+ call_dissector(data_handle,tvb, pinfo, tree);
+}
+
+
+static void
+dissect_quakeworld_server_commands(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ /* If I have too much time at hand, I'll fill it with all
+ the information from my QWD specs:
+ http://www.planetquake.com/demospecs/qwd/
+ */
+ call_dissector(data_handle,tvb, pinfo, tree);
+}
+
+
+static const value_string names_reliable[] = {
+ { 0, "Non Reliable" },
+ { 1, "Reliable" },
+ { 0, NULL }
+};
+
+
+static void
+dissect_quakeworld_GamePacket(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int direction)
+{
+ proto_tree *game_tree = NULL;
+ proto_item *game_item = NULL;
+ guint32 seq1;
+ guint32 seq2;
+ int rel1;
+ int rel2;
+ int offset;
+ guint rest_length;
+
+ direction = (pinfo->destport == gbl_quakeworldServerPort) ?
+ DIR_C2S : DIR_S2C;
+
+ if (tree) {
+ game_item = proto_tree_add_text(tree, tvb,
+ 0, -1, "Game");
+ if (game_item)
+ game_tree = proto_item_add_subtree(
+ game_item, ett_quakeworld_game);
+ }
+
+ offset = 0;
+
+ seq1 = tvb_get_letohl(tvb, offset);
+ rel1 = seq1 & 0x80000000 ? 1 : 0;
+ seq1 &= ~0x80000000;
+ if (game_tree) {
+ proto_item *seq1_item = proto_tree_add_text(game_tree,
+ tvb, offset, 4, "Current Sequence: %u (%s)",
+ seq1, val_to_str(rel1,names_reliable,"%u"));
+ if (seq1_item) {
+ proto_tree *seq1_tree = proto_item_add_subtree(
+ seq1_item, ett_quakeworld_game_seq1);
+ proto_tree_add_uint(seq1_tree, hf_quakeworld_game_seq1,
+ tvb, offset, 4, seq1);
+ proto_tree_add_boolean(seq1_tree, hf_quakeworld_game_rel1,
+ tvb, offset+3, 1, rel1);
+ }
+ }
+ offset += 4;
+
+ seq2 = tvb_get_letohl(tvb, offset);
+ rel2 = seq2 & 0x80000000 ? 1 : 0;
+ seq2 &= ~0x80000000;
+ if (game_tree) {
+ proto_item *seq2_item = proto_tree_add_text(game_tree,
+ tvb, offset, 4, "Acknowledge Sequence: %u (%s)",
+ seq2, val_to_str(rel2,names_reliable,"%u"));
+ if (seq2_item) {
+ proto_tree *seq2_tree = proto_item_add_subtree(
+ seq2_item, ett_quakeworld_game_seq2);
+ proto_tree_add_uint(seq2_tree, hf_quakeworld_game_seq2,
+ tvb, offset, 4, seq2);
+ proto_tree_add_boolean(seq2_tree, hf_quakeworld_game_rel2,
+ tvb, offset+3, 1, rel2);
+ }
+ }
+ offset += 4;
+
+ if (direction == DIR_C2S) {
+ /* client to server */
+ guint16 qport = tvb_get_letohs(tvb, offset);
+ if (game_tree) {
+ proto_tree_add_uint(game_tree, hf_quakeworld_game_qport,
+ tvb, offset, 2, qport);
+ }
+ offset +=2;
+ }
+
+ /* all the rest is pure game data */
+ rest_length = tvb_reported_length(tvb) - offset;
+ if (rest_length) {
+ tvbuff_t *next_tvb =
+ tvb_new_subset(tvb, offset, rest_length , rest_length);
+
+ if (direction == DIR_C2S) {
+ proto_item *c_item = NULL;
+ proto_tree *c_tree = NULL;
+ if (tree) {
+ c_item = proto_tree_add_text(game_tree, next_tvb,
+ 0, -1, "Client Commands");
+ if (c_item) {
+ c_tree = proto_item_add_subtree(
+ c_item, ett_quakeworld_game_clc);
+ }
+ }
+ dissect_quakeworld_client_commands(next_tvb, pinfo, c_tree);
+ }
+ else {
+ proto_item *c_item = NULL;
+ proto_tree *c_tree = NULL;
+ if (tree) {
+ c_item = proto_tree_add_text(game_tree, next_tvb,
+ 0, -1, "Server Commands");
+ if (c_item) {
+ c_tree = proto_item_add_subtree(
+ c_item, ett_quakeworld_game_svc);
+ }
+ }
+ dissect_quakeworld_server_commands(next_tvb, pinfo, c_tree);
+ }
+ }
+}
+
+
+static void
+dissect_quakeworld(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *quakeworld_tree = NULL;
+ proto_item *quakeworld_item = NULL;
+ int direction;
+
+ direction = (pinfo->destport == gbl_quakeworldServerPort) ?
+ DIR_C2S : DIR_S2C;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "QUAKEWORLD");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str(direction,
+ names_direction, "%u"));
+
+ if (tree) {
+ quakeworld_item = proto_tree_add_item(tree, proto_quakeworld,
+ tvb, 0, -1, FALSE);
+ if (quakeworld_item)
+ quakeworld_tree = proto_item_add_subtree(
+ quakeworld_item, ett_quakeworld);
+ if (quakeworld_tree) {
+ proto_tree_add_uint_format(quakeworld_tree,
+ direction == DIR_S2C ?
+ hf_quakeworld_s2c :
+ hf_quakeworld_c2s,
+ tvb, 0, 0, 1,
+ "Direction: %s", val_to_str(direction, names_direction, "%u"));
+ }
+ }
+
+ if (tvb_get_ntohl(tvb, 0) == 0xffffffff) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, " Connectionless");
+ }
+ if (quakeworld_tree)
+ proto_tree_add_uint_format(quakeworld_tree,
+ hf_quakeworld_connectionless,
+ tvb, 0, 0, 1,
+ "Type: Connectionless");
+ dissect_quakeworld_ConnectionlessPacket(
+ tvb, pinfo, quakeworld_tree, direction);
+ }
+ else {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, " Game");
+ }
+ if (quakeworld_tree)
+ proto_tree_add_uint_format(quakeworld_tree,
+ hf_quakeworld_game,
+ tvb, 0, 0, 1,
+ "Type: Game");
+ dissect_quakeworld_GamePacket(
+ tvb, pinfo, quakeworld_tree, direction);
+ }
+}
+
+
+void
+proto_reg_handoff_quakeworld(void)
+{
+ static int Initialized=FALSE;
+ static dissector_handle_t quakeworld_handle;
+ static int ServerPort=0;
+
+ if (!Initialized) {
+ quakeworld_handle = create_dissector_handle(dissect_quakeworld,
+ proto_quakeworld);
+ Initialized=TRUE;
+ } else {
+ dissector_delete("udp.port", ServerPort, quakeworld_handle);
+ }
+
+ /* set port for future deletes */
+ ServerPort=gbl_quakeworldServerPort;
+
+ dissector_add("udp.port", gbl_quakeworldServerPort, quakeworld_handle);
+ data_handle = find_dissector("data");
+}
+
+
+void
+proto_register_quakeworld(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_quakeworld_c2s,
+ { "Client to Server", "quakeworld.c2s",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Client to Server", HFILL }},
+ { &hf_quakeworld_s2c,
+ { "Server to Client", "quakeworld.s2c",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Server to Client", HFILL }},
+ { &hf_quakeworld_connectionless,
+ { "Connectionless", "quakeworld.connectionless",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Connectionless", HFILL }},
+ { &hf_quakeworld_game,
+ { "Game", "quakeworld.game",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Game", HFILL }},
+ { &hf_quakeworld_connectionless_marker,
+ { "Marker", "quakeworld.connectionless.marker",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Marker", HFILL }},
+ { &hf_quakeworld_connectionless_text,
+ { "Text", "quakeworld.connectionless.text",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Text", HFILL }},
+ { &hf_quakeworld_connectionless_command,
+ { "Command", "quakeworld.connectionless.command",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Command", HFILL }},
+ { &hf_quakeworld_connectionless_arguments,
+ { "Arguments", "quakeworld.connectionless.arguments",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Arguments", HFILL }},
+ { &hf_quakeworld_connectionless_connect_version,
+ { "Version", "quakeworld.connectionless.connect.version",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Protocol Version", HFILL }},
+ { &hf_quakeworld_connectionless_connect_qport,
+ { "QPort", "quakeworld.connectionless.connect.qport",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "QPort of the client", HFILL }},
+ { &hf_quakeworld_connectionless_connect_challenge,
+ { "Challenge", "quakeworld.connectionless.connect.challenge",
+ FT_INT32, BASE_DEC, NULL, 0x0,
+ "Challenge from the server", HFILL }},
+ { &hf_quakeworld_connectionless_connect_infostring,
+ { "Infostring", "quakeworld.connectionless.connect.infostring",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Infostring with additional variables", HFILL }},
+ { &hf_quakeworld_connectionless_connect_infostring_key_value,
+ { "Key/Value", "quakeworld.connectionless.connect.infostring.key_value",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Key and Value", HFILL }},
+ { &hf_quakeworld_connectionless_connect_infostring_key,
+ { "Key", "quakeworld.connectionless.connect.infostring.key",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Infostring Key", HFILL }},
+ { &hf_quakeworld_connectionless_connect_infostring_value,
+ { "Value", "quakeworld.connectionless.connect.infostring.value",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Infostring Value", HFILL }},
+ { &hf_quakeworld_connectionless_rcon_password,
+ { "Password", "quakeworld.connectionless.rcon.password",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Rcon Password", HFILL }},
+ { &hf_quakeworld_connectionless_rcon_command,
+ { "Command", "quakeworld.connectionless.rcon.command",
+ FT_STRING, BASE_DEC, NULL, 0x0,
+ "Command", HFILL }},
+ { &hf_quakeworld_game_seq1,
+ { "Sequence Number", "quakeworld.game.seq1",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sequence number of the current packet", HFILL }},
+ { &hf_quakeworld_game_rel1,
+ { "Reliable", "quakeworld.game.rel1",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "Packet is reliable and may be retransmitted", HFILL }},
+ { &hf_quakeworld_game_seq2,
+ { "Sequence Number", "quakeworld.game.seq2",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Sequence number of the last received packet", HFILL }},
+ { &hf_quakeworld_game_rel2,
+ { "Reliable", "quakeworld.game.rel2",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "Packet was reliable and may be retransmitted", HFILL }},
+ { &hf_quakeworld_game_qport,
+ { "QPort", "quakeworld.game.qport",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "QuakeWorld Client Port", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_quakeworld,
+ &ett_quakeworld_connectionless,
+ &ett_quakeworld_connectionless_text,
+ &ett_quakeworld_connectionless_arguments,
+ &ett_quakeworld_connectionless_connect_infostring,
+ &ett_quakeworld_connectionless_connect_infostring_key_value,
+ &ett_quakeworld_game,
+ &ett_quakeworld_game_seq1,
+ &ett_quakeworld_game_seq2,
+ &ett_quakeworld_game_clc,
+ &ett_quakeworld_game_svc
+ };
+ module_t *quakeworld_module;
+
+ proto_quakeworld = proto_register_protocol("QuakeWorld Network Protocol",
+ "QUAKEWORLD", "quakeworld");
+ proto_register_field_array(proto_quakeworld, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register a configuration option for port */
+ quakeworld_module = prefs_register_protocol(proto_quakeworld,
+ proto_reg_handoff_quakeworld);
+ prefs_register_uint_preference(quakeworld_module, "udp.port",
+ "QuakeWorld Server UDP Port",
+ "Set the UDP port for the QuakeWorld Server",
+ 10, &gbl_quakeworldServerPort);
+}
+
diff --git a/epan/dissectors/packet-radiotap.c b/epan/dissectors/packet-radiotap.c
new file mode 100644
index 0000000000..e9adad14a3
--- /dev/null
+++ b/epan/dissectors/packet-radiotap.c
@@ -0,0 +1,459 @@
+/*
+ * packet-radiotap.c
+ * Decode packets with a Radiotap header
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include <epan/packet.h>
+#include "packet-ieee80211.h"
+#include "packet-radiotap.h"
+
+struct ieee80211_radiotap_header {
+ guint8 it_version; /* Version 0. Only increases
+ * for drastic changes,
+ * introduction of compatible
+ * new fields does not count.
+ */
+ guint8 it_pad;
+ guint16 it_len; /* length of the whole
+ * header in bytes, including
+ * it_version, it_pad,
+ * it_len, and data fields.
+ */
+ guint32 it_present; /* A bitmap telling which
+ * fields are present. Set bit 31
+ * (0x80000000) to extend the
+ * bitmap by another 32 bits.
+ * Additional extensions are made
+ * by setting bit 31.
+ */
+};
+
+enum ieee80211_radiotap_type {
+ IEEE80211_RADIOTAP_TSFT = 0,
+ IEEE80211_RADIOTAP_FLAGS = 1,
+ IEEE80211_RADIOTAP_RATE = 2,
+ IEEE80211_RADIOTAP_CHANNEL = 3,
+ IEEE80211_RADIOTAP_FHSS = 4,
+ IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+ IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+ IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+ IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+ IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+ IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+ IEEE80211_RADIOTAP_ANTENNA = 11,
+ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+ IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+ IEEE80211_RADIOTAP_EXT = 31
+};
+
+/* Channel flags. */
+#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */
+#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */
+#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */
+#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
+#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
+#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
+#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */
+#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */
+
+/*
+ * Useful combinations of channel characteristics.
+ */
+#define IEEE80211_CHAN_FHSS \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
+#define IEEE80211_CHAN_A \
+ (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
+#define IEEE80211_CHAN_B \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
+#define IEEE80211_CHAN_PUREG \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
+#define IEEE80211_CHAN_G \
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
+#define IEEE80211_CHAN_T \
+ (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
+#define IEEE80211_CHAN_108G \
+ (IEEE80211_CHAN_G | IEEE80211_CHAN_TURBO)
+#define IEEE80211_CHAN_108PUREG \
+ (IEEE80211_CHAN_PUREG | IEEE80211_CHAN_TURBO)
+
+/* For IEEE80211_RADIOTAP_FLAGS */
+#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
+ * during CFP
+ */
+#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
+ * with short
+ * preamble
+ */
+#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
+ * with WEP encryption
+ */
+#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
+ * with fragmentation
+ */
+
+/* protocol */
+static int proto_radiotap = -1;
+
+static int hf_radiotap_version = -1;
+static int hf_radiotap_length = -1;
+static int hf_radiotap_mactime = -1;
+static int hf_radiotap_channel_frequency = -1;
+static int hf_radiotap_channel_flags = -1;
+static int hf_radiotap_datarate = -1;
+static int hf_radiotap_antenna = -1;
+static int hf_radiotap_antsignal = -1;
+static int hf_radiotap_antnoise = -1;
+static int hf_radiotap_txpower = -1;
+static int hf_radiotap_preamble = -1;
+
+static gint ett_radiotap = -1;
+
+static dissector_handle_t ieee80211_handle;
+
+static void
+dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+void
+capture_radiotap(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ const struct ieee80211_radiotap_header *hdr;
+
+ if(!BYTES_ARE_IN_FRAME(offset, len, (int)sizeof(*hdr))) {
+ ld->other ++;
+ return;
+ }
+ hdr = (const struct ieee80211_radiotap_header *)pd;
+ if(!BYTES_ARE_IN_FRAME(offset, len, hdr->it_len)) {
+ ld->other ++;
+ return;
+ }
+
+ /* 802.11 header follows */
+ capture_ieee80211(pd, offset + hdr->it_len, len, ld);
+}
+
+void
+proto_register_radiotap(void)
+{
+ static const value_string phy_type[] = {
+ { 0, "Unknown" },
+ { IEEE80211_CHAN_A, "802.11a" },
+ { IEEE80211_CHAN_B, "802.11b" },
+ { IEEE80211_CHAN_PUREG, "802.11g (pure-g)" },
+ { IEEE80211_CHAN_G, "802.11g" },
+ { IEEE80211_CHAN_T, "802.11a (turbo)" },
+ { IEEE80211_CHAN_108PUREG, "802.11g (pure-g, turbo)" },
+ { IEEE80211_CHAN_108G, "802.11g (turbo)" },
+ { IEEE80211_CHAN_FHSS, "FHSS" },
+ { 0, NULL },
+ };
+
+ static const value_string preamble_type[] = {
+ { 0, "Long" },
+ { 1, "Short" },
+ { 0, NULL },
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_radiotap_version,
+ { "Header revision", "radiotap.version",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_radiotap_length,
+ { "Header length", "radiotap.length",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+
+ { &hf_radiotap_preamble,
+ { "Preamble", "radiotap.flags.preamble",
+ FT_UINT32, BASE_DEC, VALS(preamble_type), 0x0, "", HFILL } },
+
+ { &hf_radiotap_mactime,
+ { "MAC timestamp", "radiotap.mactime",
+ FT_UINT64, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_radiotap_channel_frequency,
+ { "Channel frequency", "radiotap.channel.freq",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_radiotap_channel_flags,
+ { "Channel type", "radiotap.channel.flags",
+ FT_UINT32, BASE_HEX, VALS(phy_type), 0x0, "", HFILL } },
+ { &hf_radiotap_datarate,
+ { "Data rate", "radiotap.datarate",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_radiotap_antenna,
+ { "Antenna", "radiotap.antenna",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_radiotap_antsignal,
+ { "SSI Signal", "radiotap.antsignal",
+ FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_radiotap_antnoise,
+ { "SSI Noise", "radiotap.antnoise",
+ FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_radiotap_txpower,
+ { "Transmit power", "radiotap.txpower",
+ FT_INT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ };
+ static gint *ett[] = {
+ &ett_radiotap
+ };
+
+ proto_radiotap = proto_register_protocol("IEEE 802.11 Radiotap Capture header", "802.11 Radiotap", "radiotap");
+ proto_register_field_array(proto_radiotap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("radiotap", dissect_radiotap, proto_radiotap);
+
+}
+
+/*
+ * Convert MHz frequency to IEEE channel number.
+ */
+static int
+ieee80211_mhz2ieee(int freq, int flags)
+{
+ if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */
+ if (freq == 2484)
+ return 14;
+ if (freq < 2484)
+ return (freq - 2407) / 5;
+ else
+ return 15 + ((freq - 2512) / 20);
+ } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */
+ return (freq - 5000) / 5;
+ } else { /* either, guess */
+ if (freq == 2484)
+ return 14;
+ if (freq < 2484)
+ return (freq - 2407) / 5;
+ if (freq < 5000)
+ return 15 + ((freq - 2512) / 20);
+ return (freq - 5000) / 5;
+ }
+}
+
+static void
+dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+#define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
+#define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
+#define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
+#define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
+#define BITNO_2(x) (((x) & 2) ? 1 : 0)
+#define BIT(n) (1 << n)
+ proto_tree *radiotap_tree = NULL;
+ proto_item *ti;
+ int offset;
+ guint32 version;
+ guint32 length;
+ guint32 rate, freq, flags;
+ guint32 present, next_present;
+ int bit;
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+ offset = 0;
+
+ version = tvb_get_guint8(tvb, offset);
+ length = tvb_get_letohs(tvb, offset+2);
+ present = tvb_get_letohl(tvb, offset+4);
+ offset+=sizeof(struct ieee80211_radiotap_header);
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Radiotap Capture v%x, Length %d",
+ version, length);
+
+ /* Dissect the packet */
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_radiotap,
+ tvb, 0, length, "Radiotap Header");
+ radiotap_tree = proto_item_add_subtree(ti, ett_radiotap);
+ }
+
+ for (; present; present = next_present) {
+ /* clear the least significant bit that is set */
+ next_present = present & (present - 1);
+
+ /* extract the least significant bit that is set */
+ bit = BITNO_32(present ^ next_present);
+
+ switch (bit) {
+ case IEEE80211_RADIOTAP_FLAGS:
+ if (tree) {
+ proto_tree_add_uint(radiotap_tree, hf_radiotap_preamble,
+ tvb, 0, 0, (tvb_get_guint8(tvb, offset) &
+ IEEE80211_RADIOTAP_F_SHORTPRE) != 0);
+ }
+ offset++;
+ /* XXX CFP, WEP, FRAG */
+#if 0
+ capability = tvb_get_letohs (tvb, offset);
+
+ cap_item = proto_tree_add_uint_format (tree, ff_capture,
+ tvb, offset, 2,
+ capability,
+ "Capability Information: 0x%04X",
+ capability);
+ cap_tree = proto_item_add_subtree (cap_item, ett_cap_tree);
+ proto_tree_add_boolean (cap_tree, ff_cf_ess, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_ibss, tvb, offset, 2,
+ capability);
+ if (ESS_SET (capability) != 0) /* This is an AP */
+ proto_tree_add_uint (cap_tree, ff_cf_ap_poll, tvb, offset, 2,
+ capability);
+
+ else /* This is a STA */
+ proto_tree_add_uint (cap_tree, ff_cf_sta_poll, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_privacy, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_preamble, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_pbcc, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_cf_agility, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_short_slot_time, tvb, offset, 2,
+ capability);
+ proto_tree_add_boolean (cap_tree, ff_dsss_ofdm, tvb, offset, 2,
+ capability);
+#endif
+ break;
+ case IEEE80211_RADIOTAP_RATE:
+ rate = tvb_get_guint8(tvb, offset) & 0x7f;
+ if (check_col(pinfo->cinfo, COL_TX_RATE)) {
+ col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%d.%d",
+ rate / 2, rate & 1 ? 5 : 0);
+ }
+ if (tree) {
+ proto_tree_add_uint_format(radiotap_tree, hf_radiotap_datarate,
+ tvb, offset, 1, tvb_get_guint8(tvb, offset),
+ "Data Rate: %d.%d Mb/s", rate / 2, rate & 1 ? 5 : 0);
+ }
+ offset++;
+ break;
+ case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
+ case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+ /* XXX distinguish units */
+ if (check_col(pinfo->cinfo, COL_RSSI)) {
+ col_add_fstr(pinfo->cinfo, COL_RSSI, "%d",
+ tvb_get_guint8(tvb, offset));
+ }
+ if (tree) {
+ proto_tree_add_int(radiotap_tree, hf_radiotap_antsignal,
+ tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ }
+ offset++;
+ break;
+ case IEEE80211_RADIOTAP_DBM_ANTNOISE:
+ case IEEE80211_RADIOTAP_DB_ANTNOISE:
+ /* XXX distinguish units */
+ if (tree) {
+ proto_tree_add_int(radiotap_tree, hf_radiotap_antnoise,
+ tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ }
+ offset++;
+ break;
+ case IEEE80211_RADIOTAP_ANTENNA:
+ if (tree) {
+ proto_tree_add_uint(radiotap_tree, hf_radiotap_antenna,
+ tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ }
+ offset++;
+ break;
+ case IEEE80211_RADIOTAP_DBM_TX_POWER:
+ if (tree) {
+ proto_tree_add_int(radiotap_tree, hf_radiotap_txpower,
+ tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ }
+ offset++;
+ break;
+ case IEEE80211_RADIOTAP_CHANNEL:
+ if (tree) {
+ freq = tvb_get_letohs(tvb, offset);
+ flags = tvb_get_letohs(tvb, offset+2);
+ proto_tree_add_uint_format(radiotap_tree, hf_radiotap_channel_frequency,
+ tvb, offset, 2, freq,
+ "Channel: %u (chan %u)", freq, ieee80211_mhz2ieee(freq, flags));
+ proto_tree_add_uint(radiotap_tree, hf_radiotap_channel_flags,
+ tvb, offset+2, 2, flags);
+ }
+ offset+=4;
+ break;
+ case IEEE80211_RADIOTAP_FHSS:
+ case IEEE80211_RADIOTAP_LOCK_QUALITY:
+ case IEEE80211_RADIOTAP_TX_ATTENUATION:
+ case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
+#if 0
+ tvb_get_letohs(tvb, offset);
+#endif
+ offset+=2;
+ break;
+ case IEEE80211_RADIOTAP_TSFT:
+ if (tree) {
+ proto_tree_add_item(radiotap_tree, hf_radiotap_mactime,
+ tvb, offset, 8, FALSE);
+ }
+ offset+=8;
+ break;
+ default:
+ /*
+ * This indicates a field whose size we do not
+ * know, so we cannot proceed.
+ */
+ next_present = 0;
+ continue;
+ }
+ }
+
+ /* dissect the 802.11 header next */
+ call_dissector(ieee80211_handle,
+ tvb_new_subset(tvb, length, -1, -1), pinfo, tree);
+#undef BITNO_32
+#undef BITNO_16
+#undef BITNO_8
+#undef BITNO_4
+#undef BITNO_2
+#undef BIT
+}
+
+void
+proto_reg_handoff_radiotap(void)
+{
+ dissector_handle_t radiotap_handle;
+
+ /* handle for 802.11 dissector */
+ ieee80211_handle = find_dissector("wlan");
+
+ radiotap_handle = create_dissector_handle(dissect_radiotap, proto_radiotap);
+
+ dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WLAN_BSD, radiotap_handle);
+}
diff --git a/epan/dissectors/packet-radiotap.h b/epan/dissectors/packet-radiotap.h
new file mode 100644
index 0000000000..c92ecb7762
--- /dev/null
+++ b/epan/dissectors/packet-radiotap.h
@@ -0,0 +1,30 @@
+/*
+ * packet-radiotap.h
+ * Declarations for packet-radiotap.c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+void capture_radiotap(const guchar *pd, int offset, int len, packet_counts *ld);
+void proto_register_radiotap(void);
+void proto_reg_handoff_radiotap(void);
diff --git a/epan/dissectors/packet-radius.c b/epan/dissectors/packet-radius.c
new file mode 100644
index 0000000000..ac561d4990
--- /dev/null
+++ b/epan/dissectors/packet-radius.c
@@ -0,0 +1,3427 @@
+/* packet-radius.c
+ *
+ * Routines for RADIUS packet disassembly
+ * Copyright 1999 Johan Feyaerts
+ * Changed 03/12/2003 Rui Carmo (http://the.taoofmac.com - added all 3GPP VSAs, some parsing)
+ *
+ * RFC 2865, RFC 2866, RFC 2867, RFC 2868, RFC 2869
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <glib.h>
+#include <time.h>
+
+#include "isprint.h"
+
+#include <epan/packet.h>
+#include <epan/resolv.h>
+
+#include "packet-q931.h"
+#include "packet-gtp.h"
+#include "prefs.h"
+#include "crypt-md5.h"
+
+static int proto_radius = -1;
+static int hf_radius_length = -1;
+static int hf_radius_code = -1;
+static int hf_radius_id =-1;
+
+static char *shared_secret = NULL;
+static gpointer authenticator = NULL;
+
+static gint ett_radius = -1;
+static gint ett_radius_avp = -1;
+static gint ett_radius_eap = -1;
+static gint ett_radius_vsa = -1;
+
+static dissector_handle_t eap_fragment_handle;
+
+#define UDP_PORT_RADIUS 1645
+#define UDP_PORT_RADIUS_NEW 1812
+#define UDP_PORT_RADACCT 1646
+#define UDP_PORT_RADACCT_NEW 1813
+
+#define TEXTBUFFER 2000
+#define VSABUFFER 10
+
+typedef struct _e_radiushdr {
+ guint8 rh_code;
+ guint8 rh_ident;
+ guint16 rh_pktlength;
+} e_radiushdr;
+
+typedef struct _e_avphdr {
+ guint8 avp_type;
+ guint8 avp_length;
+} e_avphdr;
+
+typedef struct _radius_attr_info {
+ guint16 attr_type;
+ guint16 value_type;
+ gchar *str;
+ const value_string *vs;
+} radius_attr_info;
+
+typedef struct _rd_vsa_table {
+ guint32 vendor;
+ const radius_attr_info *attrib;
+} rd_vsa_table;
+
+typedef struct _rd_vsa_buffer {
+ gchar *str;
+ int offset;
+ guint8 length;
+} rd_vsa_buffer;
+
+#define AUTHENTICATOR_LENGTH 16
+#define RD_HDR_LENGTH 4
+
+#define RADIUS_ACCESS_REQUEST 1
+#define RADIUS_ACCESS_ACCEPT 2
+#define RADIUS_ACCESS_REJECT 3
+#define RADIUS_ACCOUNTING_REQUEST 4
+#define RADIUS_ACCOUNTING_RESPONSE 5
+#define RADIUS_ACCOUNTING_STATUS 6
+#define RADIUS_ACCESS_PASSWORD_REQUEST 7
+#define RADIUS_ACCESS_PASSWORD_ACK 8
+#define RADIUS_ACCESS_PASSWORD_REJECT 9
+#define RADIUS_ACCOUNTING_MESSAGE 10
+#define RADIUS_ACCESS_CHALLENGE 11
+#define RADIUS_STATUS_SERVER 12
+#define RADIUS_STATUS_CLIENT 13
+
+#define RADIUS_VENDOR_SPECIFIC_CODE 26
+#define RADIUS_ASCEND_ACCESS_NEXT_CODE 29
+#define RADIUS_ASCEND_ACCESS_NEW_PIN 30
+#define RADIUS_ASCEND_PASSWORD_EXPIRED 32
+#define RADIUS_ASCEND_ACCESS_EVENT_REQUEST 33
+#define RADIUS_ASCEND_ACCESS_EVENT_RESPONSE 34
+#define RADIUS_DISCONNECT_REQUEST 40
+#define RADIUS_DISCONNECT_REQUEST_ACK 41
+#define RADIUS_DISCONNECT_REQUEST_NAK 42
+#define RADIUS_CHANGE_FILTER_REQUEST 43
+#define RADIUS_CHANGE_FILTER_REQUEST_ACK 44
+#define RADIUS_CHANGE_FILTER_REQUEST_NAK 45
+#define RADIUS_RESERVED 255
+
+/*
+ * List of types for RADIUS attributes. "Type" refers to how it's
+ * formatted for display in Ethereal.
+ *
+ * Not every RADIUS attribute gets its own type. If an attribute is
+ * an integer or a tagged integer, but happens to have particular strings
+ * associated with particular values, it doesn't get its own type -
+ * you just put a pointer to the appropriate value_string table in
+ * the entry for that attribute in the appropriate radius_attr_info
+ * table. Only if it has to get formatted in some non-standard fashion
+ * (as is the case for the CoSine VPI/VCI attribute) does it get a type
+ * of its own.
+ */
+enum {
+ RADIUS_STRING,
+ RADIUS_BINSTRING,
+ RADIUS_USERPASSWORD,
+ RADIUS_INTEGER4,
+ RADIUS_IP_ADDRESS,
+ RADIUS_IP6_ADDRESS,
+ RADIUS_IP6_PREFIX,
+ RADIUS_IP6_INTF_ID,
+ RADIUS_UNKNOWN,
+ RADIUS_IPX_ADDRESS,
+ RADIUS_STRING_TAGGED,
+ RADIUS_VENDOR_SPECIFIC,
+ RADIUS_TIMESTAMP,
+ RADIUS_INTEGER4_TAGGED,
+ RADIUS_EAP_MESSAGE,
+
+ COSINE_VPI_VCI,
+
+ THE3GPP_IMSI,
+ THE3GPP_QOS,
+ THE3GPP_IMSI_MCC_MNC,
+ THE3GPP_GGSN_MCC_MNC,
+ THE3GPP_NSAPI,
+ THE3GPP_SESSION_STOP_INDICATOR,
+ THE3GPP_SELECTION_MODE,
+ THE3GPP_CHARGING_CHARACTERISTICS,
+ THE3GPP_IPV6_DNS_SERVERS,
+ THE3GPP_SGSN_MCC_MNC
+};
+
+static const value_string radius_vals[] =
+{
+ {RADIUS_ACCESS_REQUEST, "Access Request"},
+ {RADIUS_ACCESS_ACCEPT, "Access Accept"},
+ {RADIUS_ACCESS_REJECT, "Access Reject"},
+ {RADIUS_ACCOUNTING_REQUEST, "Accounting Request"},
+ {RADIUS_ACCOUNTING_RESPONSE, "Accounting Response"},
+ {RADIUS_ACCOUNTING_STATUS, "Accounting Status"},
+ {RADIUS_ACCESS_PASSWORD_REQUEST, "Access Password Request"},
+ {RADIUS_ACCESS_PASSWORD_ACK, "Access Password Ack"},
+ {RADIUS_ACCESS_PASSWORD_REJECT, "Access Password Reject"},
+ {RADIUS_ACCOUNTING_MESSAGE, "Accounting Message"},
+ {RADIUS_ACCESS_CHALLENGE, "Access challenge"},
+ {RADIUS_STATUS_SERVER, "StatusServer"},
+ {RADIUS_STATUS_CLIENT, "StatusClient"},
+ {RADIUS_VENDOR_SPECIFIC_CODE, "Vendor Specific"},
+ {RADIUS_ASCEND_ACCESS_NEXT_CODE, "Ascend Access Next Code"},
+ {RADIUS_ASCEND_ACCESS_NEW_PIN, "Ascend Access New Pin"},
+ {RADIUS_ASCEND_PASSWORD_EXPIRED, "Ascend Password Expired"},
+ {RADIUS_ASCEND_ACCESS_EVENT_REQUEST, "Ascend Access Event Request"},
+ {RADIUS_ASCEND_ACCESS_EVENT_RESPONSE, "Ascend Access Event Response"},
+ {RADIUS_DISCONNECT_REQUEST, "Disconnect Request"},
+ {RADIUS_DISCONNECT_REQUEST_ACK, "Disconnect Request ACK"},
+ {RADIUS_DISCONNECT_REQUEST_NAK, "Disconnect Request NAK"},
+ {RADIUS_CHANGE_FILTER_REQUEST, "Change Filter Request"},
+ {RADIUS_CHANGE_FILTER_REQUEST_ACK, "Change Filter Request ACK"},
+ {RADIUS_CHANGE_FILTER_REQUEST_NAK, "Change Filter Request NAK"},
+ {RADIUS_RESERVED, "Reserved"},
+ {0, NULL}
+};
+
+/*
+ * These are SMI Network Management Private Enterprise Codes for
+ * organizations; see
+ *
+ * http://www.iana.org/assignments/enterprise-numbers
+ *
+ * for a list.
+ *
+ * XXX - these also appear in FreeRadius dictionary files, with items such
+ * as
+ *
+ * VENDOR Cisco 9
+ */
+#define VENDOR_ACC 5
+#define VENDOR_CISCO 9
+#define VENDOR_MERIT 61
+#define VENDOR_SHIVA 166
+#define VENDOR_CISCO_VPN5000 255
+#define VENDOR_LIVINGSTON 307
+#define VENDOR_MICROSOFT 311
+#define VENDOR_3COM 429
+#define VENDOR_ASCEND 529
+#define VENDOR_BAY 1584
+#define VENDOR_FOUNDRY 1991
+#define VENDOR_VERSANET 2180
+#define VENDOR_REDBACK 2352
+#define VENDOR_JUNIPER 2636
+#define VENDOR_APTIS 2637
+#define VENDOR_CISCO_VPN3000 3076
+#define VENDOR_COSINE 3085
+#define VENDOR_SHASTA 3199
+#define VENDOR_NOMADIX 3309
+#define VENDOR_SIEMENS 4329
+#define VENDOR_UNISPHERE 4874
+#define VENDOR_CISCO_BBSM 5263
+#define VENDOR_ISSANNI 5948
+#define VENDOR_QUINTUM 6618
+#define VENDOR_INTERLINK 6728
+#define VENDOR_COLUBRIS 8744
+#define VENDOR_COLUMBIA_UNIVERSITY 11862
+#define VENDOR_THE3GPP 10415
+
+static const value_string radius_vendor_specific_vendors[] =
+{
+ {VENDOR_ACC, "ACC"},
+ {VENDOR_CISCO, "Cisco"},
+ {VENDOR_MERIT, "Merit"},
+ {VENDOR_SHIVA, "Shiva"},
+ {VENDOR_CISCO_VPN5000, "Cisco VPN 5000"},
+ {VENDOR_MICROSOFT, "Microsoft"},
+ {VENDOR_LIVINGSTON, "Livingston"},
+ {VENDOR_3COM, "3Com"},
+ {VENDOR_ASCEND, "Ascend"},
+ {VENDOR_BAY, "Bay Networks"},
+ {VENDOR_FOUNDRY, "Foundry"},
+ {VENDOR_VERSANET, "Versanet"},
+ {VENDOR_REDBACK, "Redback"},
+ {VENDOR_JUNIPER, "Juniper Networks"},
+ {VENDOR_APTIS, "Aptis"},
+ {VENDOR_CISCO_VPN3000, "Cisco VPN 3000"},
+ {VENDOR_COSINE, "CoSine Communications"},
+ {VENDOR_SHASTA, "Shasta"},
+ {VENDOR_NOMADIX, "Nomadix"},
+ {VENDOR_SIEMENS, "SIEMENS"},
+ {VENDOR_UNISPHERE, "Unisphere Networks"},
+ {VENDOR_CISCO_BBSM, "Cisco BBSM"},
+ {VENDOR_ISSANNI, "Issanni Communications"},
+ {VENDOR_QUINTUM, "Quintum"},
+ {VENDOR_INTERLINK, "Interlink"},
+ {VENDOR_COLUBRIS, "Colubris"},
+ {VENDOR_COLUMBIA_UNIVERSITY, "Columbia University"},
+ {VENDOR_THE3GPP, "3GPP"},
+ {0, NULL}
+};
+
+/*
+ * XXX - should we construct these tables in Ethereal at start-up time by
+ * reading files such as FreeRadius dictionary files? For example,
+ * the FreeRadius "dictionary" file has
+ *
+ * ATTRIBUTE User-Name 1 string
+ *
+ * for the attribute that's
+ *
+ * {1, RADIUS_STRING, "User Name"},
+ *
+ * In our tables:
+ *
+ * "string" -> RADIUS_STRING
+ * "octets" -> RADIUS_BINSTRING
+ * "integer" -> RADIUS_INTEGER4
+ * "ipaddr" -> RADIUS_IP_ADDRESS
+ *
+ * In addition, it has entries such as
+ *
+ * VALUE Service-Type Login-User 1
+ *
+ * to handle translation of integral values to strings, which we'd use to
+ * construct value_string tables.
+ */
+static const value_string radius_service_type_vals[] =
+{
+ {1, "Login"},
+ {2, "Framed"},
+ {3, "Callback Login"},
+ {4, "Callback Framed"},
+ {5, "Outbound"},
+ {6, "Administrative"},
+ {7, "NAS Prompt"},
+ {8, "Authenticate Only"},
+ {9, "Callback NAS Prompt"},
+ {10, "Call Check"},
+ {0, NULL}
+};
+
+static const value_string radius_framed_protocol_vals[] =
+{
+ {1, "PPP"},
+ {2, "SLIP"},
+ {3, "Appletalk Remote Access Protocol (ARAP)"},
+ {4, "Gandalf proprietary Singlelink/Multilink Protocol"},
+ {5, "Xylogics proprietary IPX/SLIP"},
+ {6, "X.75 Synchronous"},
+ {255, "Ascend ARA"},
+ {256, "Ascend MPP"},
+ {257, "Ascend EURAW"},
+ {258, "Ascend EUUI"},
+ {259, "Ascend X25"},
+ {260, "Ascend COMB"},
+ {261, "Ascend FR"},
+ {262, "Ascend MP"},
+ {263, "Ascend FR-CIR"},
+ {264, "Ascend ATM-1483"},
+ {265, "Ascend ATM-FR-CIR"},
+ {0, NULL}
+};
+
+static const value_string radius_framed_routing_vals[] =
+{
+ {1, "Send Routing Packets"},
+ {2, "Listen for routing packets"},
+ {3, "Send and Listen"},
+ {0, "None"},
+ {0, NULL}
+};
+
+static const value_string radius_framed_compression_vals[] =
+{
+ {1, "VJ TCP/IP Header Compression"},
+ {2, "IPX Header Compression"},
+ {3, "Stac-LZS compression"},
+ {0, "None"},
+ {0, NULL}
+};
+
+static const value_string radius_login_service_vals[] =
+{
+ {1, "Rlogin"},
+ {2, "TCP Clear"},
+ {3, "Portmaster"},
+ {4, "LAT"},
+ {5, "X.25 PAD"},
+ {6, "X.25 T3POS"},
+ {8, "TCP Clear Quit"},
+ {0, "Telnet"},
+ {0, NULL}
+};
+
+static const value_string radius_terminating_action_vals[] =
+{
+ {1, "RADIUS Request"},
+ {0, "Default"},
+ {0, NULL}
+};
+
+static const value_string radius_accounting_status_type_vals[] =
+{
+ {1, "Start"},
+ {2, "Stop"},
+ {3, "Interim Update"},
+ {7, "Accounting On"},
+ {8, "Accounting Off"},
+ {9, "Tunnel Start"}, /* Tunnel accounting */
+ {10, "Tunnel Stop"}, /* Tunnel accounting */
+ {11, "Tunnel Reject"}, /* Tunnel accounting */
+ {12, "Tunnel Link Start"}, /* Tunnel accounting */
+ {13, "Tunnel Link Stop"}, /* Tunnel accounting */
+ {14, "Tunnel Link Reject"}, /* Tunnel accounting */
+ {0, NULL}
+};
+
+static const value_string radius_accounting_authentication_vals[] =
+{
+ {1, "Radius"},
+ {2, "Local"},
+ {3, "Remote"},
+ /* RFC 2866 says 3 is Remote. Is 7 a mistake? */
+ {7, "Remote"},
+ {0, NULL}
+};
+
+static const value_string radius_acct_terminate_cause_vals[] =
+{
+ {1, "User Request"},
+ {2, "Lost Carrier"},
+ {3, "Lost Service"},
+ {4, "Idle Timeout"},
+ {5, "Session Timeout"},
+ {6, "Admin Reset"},
+ {7, "Admin Reboot"},
+ {8, "Port Error"},
+ {9, "NAS Error"},
+ {10, "NAS Request"},
+ {11, "NAS Reboot"},
+ {12, "Port Unneeded"},
+ {13, "Port Preempted"},
+ {14, "Port Suspended"},
+ {15, "Service Unavailable"},
+ {16, "Callback"},
+ {17, "User Error"},
+ {18, "Host Request"},
+ {0, NULL}
+};
+
+static const value_string radius_tunnel_type_vals[] =
+{
+ {1, "PPTP"},
+ {2, "L2F"},
+ {3, "L2TP"},
+ {4, "ATMP"},
+ {5, "VTP"},
+ {6, "AH"},
+ {7, "IP-IP-Encap"},
+ {8, "MIN-IP-IP"},
+ {9, "ESP"},
+ {10, "GRE"},
+ {11, "DVS"},
+ {12, "IP-IP"},
+ {0, NULL}
+};
+
+static const value_string radius_tunnel_medium_type_vals[] =
+{
+ {1, "IPv4"},
+ {2, "IPv6"},
+ {3, "NSAP"},
+ {4, "HDLC"},
+ {5, "BBN"},
+ {6, "IEEE 802"},
+ {7, "E.163"},
+ {8, "E.164"},
+ {9, "F.69"},
+ {10, "X.121"},
+ {11, "IPX"},
+ {12, "Appletalk"},
+ {13, "Decnet4"},
+ {14, "Vines"},
+ {15, "E.164 NSAP"},
+ {0, NULL}
+};
+
+static const value_string radius_nas_port_type_vals[] =
+{
+ {0, "Async"},
+ {1, "Sync"},
+ {2, "ISDN Sync"},
+ {3, "ISDN Async V.120"},
+ {4, "ISDN Async V.110"},
+ {5, "Virtual"},
+ {6, "PIAFS"},
+ {7, "HDLC Clear Channel"},
+ {8, "X.25"},
+ {9, "X.75"},
+ {10, "G.3 Fax"},
+ {11, "SDSL"},
+ {12, "ADSL CAP"},
+ {13, "ADSL DMT"},
+ {14, "IDSL ISDN"},
+ {15, "Ethernet"},
+ {16, "xDSL"},
+ {17, "Cable"},
+ {18, "Wireless Other"},
+ {19, "Wireless IEEE 802.11"},
+ {0, NULL}
+};
+/*
+ *Values for RADIUS Attribute 101, Error-Cause Attribute [RFC3576]:
+ */
+static const value_string radius_error_cause_attribute_vals[]= {
+ {201,"Residual Session Context Removed"},
+ {202,"Invalid EAP Packet (Ignored)"},
+ {401,"Unsupported Attribute"},
+ {402,"Missing Attribute"},
+ {403,"NAS Identification Mismatch"},
+ {404,"Invalid Request"},
+ {405,"Unsupported Service"},
+ {406,"Unsupported Extension"},
+ {501,"Administratively Prohibited"},
+ {502,"Request Not Routable (Proxy)"},
+ {503,"Session Context Not Found"},
+ {504,"Session Context Not Removable"},
+ {505,"Other Proxy Processing Error"},
+ {506,"Resources Unavailable"},
+ {507,"Request Initiated"},
+ {0,NULL}
+};
+
+static const radius_attr_info radius_attrib[] =
+{
+ {1, RADIUS_STRING, "User Name", NULL},
+ {2, RADIUS_USERPASSWORD, "User Password", NULL},
+ {3, RADIUS_BINSTRING, "CHAP Password", NULL},
+ {4, RADIUS_IP_ADDRESS, "NAS IP Address", NULL},
+ {5, RADIUS_INTEGER4, "NAS Port", NULL},
+ {6, RADIUS_INTEGER4, "Service Type", radius_service_type_vals},
+ {7, RADIUS_INTEGER4, "Framed Protocol", radius_framed_protocol_vals},
+ {8, RADIUS_IP_ADDRESS, "Framed IP Address", NULL},
+ {9, RADIUS_IP_ADDRESS, "Framed IP Netmask", NULL},
+ {10, RADIUS_INTEGER4, "Framed Routing", radius_framed_routing_vals},
+ {11, RADIUS_STRING, "Filter Id", NULL},
+ {12, RADIUS_INTEGER4, "Framed MTU", NULL},
+ {13, RADIUS_INTEGER4, "Framed Compression", radius_framed_compression_vals},
+ {14, RADIUS_IP_ADDRESS, "Login IP Host", NULL},
+ {15, RADIUS_INTEGER4, "Login Service", radius_login_service_vals},
+ {16, RADIUS_INTEGER4, "Login TCP Port", NULL},
+ {17, RADIUS_UNKNOWN, "Unassigned", NULL},
+ {18, RADIUS_STRING, "Reply Message", NULL},
+ {19, RADIUS_STRING, "Callback Number", NULL},
+ {20, RADIUS_STRING, "Callback Id", NULL},
+ {21, RADIUS_UNKNOWN, "Unassigned", NULL},
+ {22, RADIUS_STRING, "Framed Route", NULL},
+ {23, RADIUS_IPX_ADDRESS, "Framed IPX network", NULL},
+ {24, RADIUS_BINSTRING, "State", NULL},
+ {25, RADIUS_BINSTRING, "Class", NULL},
+ {26, RADIUS_VENDOR_SPECIFIC, "Vendor Specific", NULL},
+ {27, RADIUS_INTEGER4, "Session Timeout", NULL},
+ {28, RADIUS_INTEGER4, "Idle Timeout", NULL},
+ {29, RADIUS_INTEGER4, "Terminating Action", radius_terminating_action_vals},
+ {30, RADIUS_STRING, "Called Station Id", NULL},
+ {31, RADIUS_STRING, "Calling Station Id", NULL},
+ {32, RADIUS_STRING, "NAS identifier", NULL},
+ {33, RADIUS_BINSTRING, "Proxy State", NULL},
+ {34, RADIUS_STRING, "Login LAT Service", NULL},
+ {35, RADIUS_STRING, "Login LAT Node", NULL},
+ {36, RADIUS_BINSTRING, "Login LAT Group", NULL},
+ {37, RADIUS_INTEGER4, "Framed AppleTalk Link", NULL},
+ {38, RADIUS_INTEGER4, "Framed AppleTalk Network", NULL},
+ {39, RADIUS_STRING, "Framed AppleTalk Zone", NULL},
+ {40, RADIUS_INTEGER4, "Acct Status Type", radius_accounting_status_type_vals},
+ {41, RADIUS_INTEGER4, "Acct Delay Time", NULL},
+ {42, RADIUS_INTEGER4, "Acct Input Octets", NULL},
+ {43, RADIUS_INTEGER4, "Acct Output Octets", NULL},
+ {44, RADIUS_STRING, "Acct Session Id", NULL},
+ {45, RADIUS_INTEGER4, "Acct Authentic", radius_accounting_authentication_vals},
+ {46, RADIUS_INTEGER4, "Acct Session Time", NULL},
+ {47, RADIUS_INTEGER4, "Acct Input Packets", NULL},
+ {48, RADIUS_INTEGER4, "Acct Output Packets", NULL},
+ {49, RADIUS_INTEGER4, "Acct Terminate Cause", radius_acct_terminate_cause_vals},
+ {50, RADIUS_STRING, "Acct Multi Session Id", NULL},
+ {51, RADIUS_INTEGER4, "Acct Link Count", NULL},
+ {52, RADIUS_INTEGER4, "Acct Input Gigawords", NULL},
+ {53, RADIUS_INTEGER4, "Acct Output Gigawords", NULL},
+ /* 54 Unused */
+ {55, RADIUS_TIMESTAMP, "Event Timestamp", NULL},
+ /* 56-59 Unused */
+ {60, RADIUS_BINSTRING, "CHAP Challenge", NULL},
+ {61, RADIUS_INTEGER4, "NAS Port Type", radius_nas_port_type_vals},
+ {62, RADIUS_INTEGER4, "Port Limit", NULL},
+ {63, RADIUS_BINSTRING, "Login LAT Port", NULL},
+ {64, RADIUS_INTEGER4_TAGGED, "Tunnel Type", radius_tunnel_type_vals},
+ {65, RADIUS_INTEGER4_TAGGED, "Tunnel Medium Type", radius_tunnel_medium_type_vals},
+ {66, RADIUS_STRING_TAGGED, "Tunnel Client Endpoint", NULL},
+ {67, RADIUS_STRING_TAGGED, "Tunnel Server Endpoint", NULL},
+ {68, RADIUS_STRING, "Tunnel Connection", NULL},
+ {69, RADIUS_STRING_TAGGED, "Tunnel Password", NULL},
+ {70, RADIUS_STRING, "ARAP Password", NULL},
+ {71, RADIUS_STRING, "ARAP Features", NULL},
+ {72, RADIUS_INTEGER4, "ARAP Zone-Access", NULL},
+ {73, RADIUS_INTEGER4, "ARAP Security", NULL},
+ {74, RADIUS_STRING, "ARAP Security Data", NULL},
+ {75, RADIUS_INTEGER4, "Password Retry", NULL},
+ {76, RADIUS_INTEGER4, "Prompt", NULL},
+ {77, RADIUS_STRING, "Connect Info", NULL},
+ {78, RADIUS_STRING, "Configuration Token", NULL},
+ {79, RADIUS_EAP_MESSAGE, "EAP Message", NULL},
+ {80, RADIUS_BINSTRING, "Message Authenticator", NULL},
+ {81, RADIUS_STRING_TAGGED, "Tunnel Private Group ID", NULL},
+ {82, RADIUS_STRING_TAGGED, "Tunnel Assignment ID", NULL},
+ {83, RADIUS_INTEGER4_TAGGED, "Tunnel Preference", NULL},
+ {84, RADIUS_STRING, "ARAP Challenge Response", NULL},
+ {85, RADIUS_INTEGER4, "Acct Interim Interval", NULL},
+ {86, RADIUS_INTEGER4, "Tunnel Packets Lost", NULL},
+ {87, RADIUS_STRING, "NAS Port ID", NULL},
+ {88, RADIUS_STRING, "Framed Pool", NULL},
+ {90, RADIUS_STRING_TAGGED, "Tunnel Client Auth ID", NULL},
+ {91, RADIUS_STRING_TAGGED, "Tunnel Server Auth ID", NULL},
+ {95, RADIUS_IP6_ADDRESS, "NAS IPv6 Address", NULL},
+ {96, RADIUS_IP6_INTF_ID, "Framed Interface Id", NULL},
+ {97, RADIUS_IP6_PREFIX, "Framed IPv6 Prefix", NULL},
+ {98, RADIUS_IP6_ADDRESS, "Login IPv6 Host", NULL},
+ {99, RADIUS_STRING, "Framed IPV6 Route", NULL},
+ {100, RADIUS_STRING, "Framed IPV6 Pool", NULL},
+ {101, RADIUS_INTEGER4, "Error-Cause Attribute",radius_error_cause_attribute_vals},/*[RFC3576]*/
+ {120, RADIUS_INTEGER4, "Ascend Modem Port No", NULL},
+ {121, RADIUS_INTEGER4, "Ascend Modem Slot No", NULL},
+ {187, RADIUS_INTEGER4, "Ascend Multilink ID", NULL},
+ {188, RADIUS_INTEGER4, "Ascend Num In Multilink", NULL},
+ {189, RADIUS_IP_ADDRESS, "Ascend First Dest", NULL},
+ {190, RADIUS_INTEGER4, "Ascend Pre Input Octets", NULL},
+ {191, RADIUS_INTEGER4, "Ascend Pre Output Octets", NULL},
+ {192, RADIUS_INTEGER4, "Ascend Pre Input Packets", NULL},
+ {193, RADIUS_INTEGER4, "Ascend Pre Output Packets", NULL},
+ {194, RADIUS_INTEGER4, "Ascend Maximum Time", NULL},
+ {195, RADIUS_INTEGER4, "Ascend Disconnect Cause", NULL},
+ {196, RADIUS_INTEGER4, "Ascend Connect Progress", NULL},
+ {197, RADIUS_INTEGER4, "Ascend Data Rate", NULL},
+ {198, RADIUS_INTEGER4, "Ascend PreSession Time", NULL},
+ {211, RADIUS_STRING, "Merit Proxy-Action", NULL},
+ {218, RADIUS_INTEGER4, "Ascend Assign IP Pool", NULL},
+ {222, RADIUS_STRING, "Merit User-Id", NULL},
+ {223, RADIUS_STRING, "Merit User-Realm", NULL},
+ {255, RADIUS_INTEGER4, "Ascend Xmit Rate", NULL},
+ {0, 0, NULL, NULL}
+};
+
+/*
+reference:
+ 'dictionary.acc' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.acc
+*/
+static const value_string radius_vendor_acc_reason_code_vals[] =
+{
+ {0, "No reason No Failure"},
+ {1, "Resource shortage"},
+ {2, "Session already open"},
+ {3, "Too many RADIUS users"},
+ {4, "No authentification server"},
+ {5, "No authentification response"},
+ {6, "No accounting server"},
+ {7, "No accounting response"},
+ {8, "Access Denied"},
+ {9, "Temporary buffer shortage"},
+ {10, "Protocol error"},
+ {11, "Invalid attribute"},
+ {12, "Invalid service type"},
+ {13, "Invalid framed protocol"},
+ {14, "Invalid attribute value"},
+ {15, "Invalid user information"},
+ {16, "Invalid IP address"},
+ {17, "Invalid integer syntax"},
+ {18, "Invalid NAS port"},
+ {19, "Requested by user"},
+ {20, "Network disconnect"},
+ {21, "Service interruption"},
+ {22, "Physical port error"},
+ {23, "Idle timeout"},
+ {24, "Session timeout"},
+ {25, "Administrative reset"},
+ {26, "NAS reload or reset"},
+ {27, "NAS error"},
+ {28, "NAS request"},
+ {29, "Undefined reason given"},
+ {30, "Conflicting attributes"},
+ {31, "Port limit exceeded"},
+ {32, "Facility not available"},
+ {33, "Internal config error"},
+ {34, "Bad route specification"},
+ {35, "Access Partition bind failure"},
+ {36, "Security violation"},
+ {37, "Request type conflict"},
+ {38, "Configuration disallowed"},
+ {39, "Missing attribute"},
+ {40, "Invalid request"},
+ {41, "Missing parameter"},
+ {42, "Invalid parameter"},
+ {43, "Call cleared with cause"},
+ {44, "Inopportune config request"},
+ {45, "Invalid config parameter"},
+ {46, "Missing config parameter"},
+ {47, "Incompatible service profile"},
+ {48, "Administrative reset"},
+ {49, "Administrative reload"},
+ {50, "Port unneeded"},
+ {51, "Port preempted"},
+ {52, "Port suspended"},
+ {53, "Service unavailable"},
+ {54, "Callback"},
+ {55, "User error"},
+ {56, "Host request"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_ccp_option_vals[] =
+{
+ {1, "Disabled"},
+ {2, "Enabled"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_route_policy_vals[] =
+{
+ {1, "Funnel"},
+ {2, "Direct"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_ml_mlx_admin_state_vals[] =
+{
+ {1, "Enabled"},
+ {2, "Disabled"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_request_type_vals[] =
+{
+ {1, "Ring Indication"},
+ {2, "Dial Request"},
+ {3, "User Authentification"},
+ {4, "Tunnel Authentification"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_bridging_support_vals[] =
+{
+ {1, "Disabled"},
+ {2, "Enabled"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_apsm_oversubscribed_vals[] =
+{
+ {1, "False"},
+ {2, "True"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_acct_on_off_reason_vals[] =
+{
+ {0, "NAS Reset"},
+ {1, "NAS Reload"},
+ {2, "Configuration Reset"},
+ {3, "Configuration Reload"},
+ {4, "Enabled"},
+ {5, "Disabled"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_ip_compression_vals[] =
+{
+ {1, "Disabled"},
+ {2, "Enabled"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_ipx_compression_vals[] =
+{
+ {1, "Disabled"},
+ {2, "Enabled"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_callback_mode_vals[] =
+{
+ {0, "User Auth"},
+ {3, "User Specified E.164"},
+ {6, "CBCP Callback"},
+ {7, "CLI Callback"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_callback_cbcp_type_vals[] =
+{
+ {1, "CBCP None"},
+ {2, "CBCP User Specified"},
+ {3, "CBCP Pre Specified"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_dialout_auth_mode_vals[] =
+{
+ {1, "PAP"},
+ {2, "CHAP"},
+ {3, "CHAP PAP"},
+ {4, "NONE"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_acc_access_community_vals[] =
+{
+ {1, "PUBLIC"},
+ {2, "NETMAN"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_acc_attrib[] =
+{
+ {1, RADIUS_INTEGER4, "Acc Reason Code", radius_vendor_acc_reason_code_vals},
+ {2, RADIUS_INTEGER4, "Acc Ccp Option", radius_vendor_acc_ccp_option_vals},
+ {3, RADIUS_INTEGER4, "Acc Input Errors", NULL},
+ {4, RADIUS_INTEGER4, "Acc Output Errors", NULL},
+ {5, RADIUS_STRING, "Acc Access Partition", NULL},
+ {6, RADIUS_STRING, "Acc Customer Id", NULL},
+ {7, RADIUS_IP_ADDRESS, "Acc Ip Gateway Pri", NULL},
+ {8, RADIUS_IP_ADDRESS, "Acc Ip Gateway Sec", NULL},
+ {9, RADIUS_INTEGER4, "Acc Route Policy", radius_vendor_acc_route_policy_vals},
+ {10, RADIUS_INTEGER4, "Acc ML MLX Admin State", radius_vendor_acc_ml_mlx_admin_state_vals},
+ {11, RADIUS_INTEGER4, "Acc ML Call Threshold", NULL},
+ {12, RADIUS_INTEGER4, "Acc ML Clear Threshold", NULL},
+ {13, RADIUS_INTEGER4, "Acc ML Damping Factor", NULL},
+ {14, RADIUS_STRING, "Acc Tunnel Secret", NULL},
+ {15, RADIUS_INTEGER4, "Acc Clearing Cause", q931_cause_code_vals},
+ {16, RADIUS_INTEGER4, "Acc Clearing Location", q931_cause_location_vals},
+ {17, RADIUS_STRING, "Acc Service Profile", NULL},
+ {18, RADIUS_INTEGER4, "Acc Request Type", radius_vendor_acc_request_type_vals},
+ {19, RADIUS_INTEGER4, "Acc Bridging Support", radius_vendor_acc_bridging_support_vals},
+ {20, RADIUS_INTEGER4, "Acc Apsm Oversubscribed", radius_vendor_acc_apsm_oversubscribed_vals},
+ {21, RADIUS_INTEGER4, "Acc Acct On Off Reason", radius_vendor_acc_acct_on_off_reason_vals},
+ {22, RADIUS_INTEGER4, "Acc Tunnel Port", NULL},
+ {23, RADIUS_IP_ADDRESS, "Acc Dns Server Pri", NULL},
+ {24, RADIUS_IP_ADDRESS, "Acc Dns Server Sec", NULL},
+ {25, RADIUS_IP_ADDRESS, "Acc Nbns Server Pri", NULL},
+ {26, RADIUS_IP_ADDRESS, "Acc Nbns Server Sec", NULL},
+ {27, RADIUS_INTEGER4, "Acc Dial Port Index", NULL},
+ {28, RADIUS_INTEGER4, "Acc Ip Compression", radius_vendor_acc_ip_compression_vals},
+ {29, RADIUS_INTEGER4, "Acc Ipx Compression", radius_vendor_acc_ipx_compression_vals},
+ {30, RADIUS_INTEGER4, "Acc Connect Tx Speed", NULL},
+ {31, RADIUS_INTEGER4, "Acc Connect Rx Speed", NULL},
+ {32, RADIUS_STRING, "Acc Modem Modulation Type", NULL},
+ {33, RADIUS_STRING, "Acc Modem Error Protocol", NULL},
+ {34, RADIUS_INTEGER4, "Acc Callback Delay", NULL},
+ {35, RADIUS_STRING, "Acc Callback Num Valid", NULL},
+ {36, RADIUS_INTEGER4, "Acc Callback Mode", radius_vendor_acc_callback_mode_vals},
+ {37, RADIUS_INTEGER4, "Acc Callback CBCP Type", radius_vendor_acc_callback_cbcp_type_vals},
+ {38, RADIUS_INTEGER4, "Acc Dialout Auth Mode", radius_vendor_acc_dialout_auth_mode_vals},
+ {39, RADIUS_STRING, "Acc Dialout Auth Password", NULL},
+ {40, RADIUS_STRING, "Acc Dialout Auth Username", NULL},
+ {42, RADIUS_INTEGER4, "Acc Access Community", radius_vendor_acc_access_community_vals},
+ {43, RADIUS_INTEGER4, "Acc Vpsm Reject Cause", NULL},
+ {44, RADIUS_STRING, "Acc Ace Token", NULL},
+ {45, RADIUS_INTEGER4, "Acc Ace Token-Ttl", NULL},
+ {46, RADIUS_STRING, "Acc Ip Pool Name", NULL},
+ {47, RADIUS_INTEGER4, "Acc Igmp Admin State", NULL},
+ {48, RADIUS_INTEGER4, "Acc Igmp Version", NULL},
+
+
+ {0, 0, NULL, NULL},
+};
+
+/*
+references:
+ 'dictionary.cisco' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.cisco
+
+ http://www.cisco.com/univercd/cc/td/doc/product/access/acs_serv/vapp_dev/vsaig3.htm
+
+ http://www.cisco.com/univercd/cc/td/doc/product/software/ios122/122cgcr/fsecur_c/fappendx/fradattr/scfrdat3.pdf
+ http://www.missl.cs.umd.edu/wireless/ethereal/cisco-vsa.pdf
+
+*/
+static const value_string radius_vendor_cisco_disconnect_cause_vals[] =
+{
+ {2, "Unknown"},
+ {4, "CLID Authentication Failure"},
+ {10, "No Carrier"},
+ {11, "Lost Carrier"},
+ {12, "No Detected Result Codes"},
+ {20, "User Ends Session"},
+ {21, "Idle Timeout"},
+ {22, "Exit Telnet Session"},
+ {23, "No Remote IP Addr"},
+ {24, "Exit Raw TCP"},
+ {25, "Password Fail"},
+ {26, "Raw TCP Disabled"},
+ {27, "Control C Detected"},
+ {28, "EXEC Program Destroyed"},
+ {40, "Timeout PPP LCP"},
+ {41, "Failed PPP LCP Negotiation"},
+ {42, "Failed PPP PAP Auth Fail"},
+ {43, "Failed PPP CHAP Auth"},
+ {44, "Failed PPP Remote Auth"},
+ {45, "PPP Remote Terminate"},
+ {46, "PPP Closed Event"},
+ {100, "Session Timeout"},
+ {101, "Session Failed Security"},
+ {102, "Session End Callback"},
+ {120, "Invalid Protocol"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_cisco_attrib[] =
+{
+ /* stanard attributes */
+ {1, RADIUS_STRING, "Cisco AV Pair", NULL},
+ {2, RADIUS_STRING, "Cisco NAS Port", NULL},
+ /* fax */
+ {3, RADIUS_STRING, "Fax Account Id Origin", NULL},
+ {4, RADIUS_STRING, "Fax Msg Id", NULL},
+ {5, RADIUS_STRING, "Fax Pages", NULL},
+ {6, RADIUS_STRING, "Fax Cover Page Flag", NULL},
+ {7, RADIUS_STRING, "Fax Modem Time", NULL},
+ {8, RADIUS_STRING, "Fax Connect Speed", NULL},
+ {9, RADIUS_STRING, "Fax Recipent Count", NULL},
+ {10, RADIUS_STRING, "Fax Process Abort Flag", NULL},
+ {11, RADIUS_STRING, "Fax DSN Address", NULL},
+ {12, RADIUS_STRING, "Fax DSN Flag", NULL},
+ {13, RADIUS_STRING, "Fax MDN Address", NULL},
+ {14, RADIUS_STRING, "Fax MDN Flag", NULL},
+ {15, RADIUS_STRING, "Fax Auth Status", NULL},
+ {16, RADIUS_STRING, "Email Server Address", NULL},
+ {17, RADIUS_STRING, "Email Server Ack Flag", NULL},
+ {18, RADIUS_STRING, "Gateway Id", NULL},
+ {19, RADIUS_STRING, "Call Type", NULL},
+ {20, RADIUS_STRING, "Port Used", NULL},
+ {21, RADIUS_STRING, "Abort Cause", NULL},
+ /* #22 */
+ /* H323 - Voice over IP attributes. */
+ {23, RADIUS_STRING, "H323 Remote Address", NULL},
+ {24, RADIUS_STRING, "H323 Conf Id", NULL},
+ {25, RADIUS_STRING, "H323 Setup Time", NULL},
+ {26, RADIUS_STRING, "H323 Call Origin", NULL},
+ {27, RADIUS_STRING, "H323 Call Type", NULL},
+ {28, RADIUS_STRING, "H323 Connect Time", NULL},
+ {29, RADIUS_STRING, "H323 Disconnect Time", NULL},
+ {30, RADIUS_STRING, "H323 Disconnect Cause", NULL},
+ {31, RADIUS_STRING, "H323 Voice Quality", NULL},
+ /* #32 */
+ {33, RADIUS_STRING, "H323 GW Id", NULL},
+ /* #34 */
+ {35, RADIUS_STRING, "H323 Incoming Conf Id", NULL},
+ /* #36-#100 */
+ {101, RADIUS_STRING, "H323 Credit Amount", NULL},
+ {102, RADIUS_STRING, "H323 Credit Time", NULL},
+ {103, RADIUS_STRING, "H323 Return Code", NULL},
+ {104, RADIUS_STRING, "H323 Prompt Id", NULL},
+ {105, RADIUS_STRING, "H323 Time And Day", NULL},
+ {106, RADIUS_STRING, "H323 Redirect Number", NULL},
+ {107, RADIUS_STRING, "H323 Preferred Lang", NULL},
+ {108, RADIUS_STRING, "H323 Redirect Ip Address", NULL},
+ {109, RADIUS_STRING, "H323 Billing Model", NULL},
+ {110, RADIUS_STRING, "H323 Currency Type", NULL},
+ /* #111-#186 */
+/*
+ Extra attributes sent by the Cisco, if you configure
+ "radius-server vsa accounting" (requires IOS11.2+).
+*/
+ {187, RADIUS_INTEGER4, "Cisco Multilink ID", NULL},
+ {188, RADIUS_INTEGER4, "Cisco Num In Multilink", NULL},
+ /* #189 */
+ {190, RADIUS_INTEGER4, "Cisco Pre Input Octets", NULL},
+ {191, RADIUS_INTEGER4, "Cisco Pre Output Octets", NULL},
+ {192, RADIUS_INTEGER4, "Cisco Pre Input Packets", NULL},
+ {193, RADIUS_INTEGER4, "Cisco Pre Output Packets", NULL},
+ {194, RADIUS_INTEGER4, "Cisco Maximum Time", NULL},
+ {195, RADIUS_INTEGER4, "Cisco Disconnect Cause", radius_vendor_cisco_disconnect_cause_vals},
+ /* #196 */
+ {197, RADIUS_INTEGER4, "Cisco Data Rate", NULL},
+ {198, RADIUS_INTEGER4, "Cisco PreSession Time", NULL},
+ /* #199-#207 */
+ {208, RADIUS_INTEGER4, "Cisco PW Lifetime", NULL},
+ {209, RADIUS_INTEGER4, "Cisco IP Direct", NULL},
+ {210, RADIUS_INTEGER4, "Cisco PPP VJ Slot Comp", NULL},
+ /* #211 */
+ {212, RADIUS_INTEGER4, "Cisco PPP Async Map", NULL},
+ /* #213-#216 */
+ {217, RADIUS_INTEGER4, "Cisco IP Pool Definition", NULL},
+ {218, RADIUS_INTEGER4, "Cisco Asing IP Pool", NULL},
+ /* #219-#227 */
+ {228, RADIUS_INTEGER4, "Cisco Route IP", NULL},
+ /* #229-#232 */
+ {233, RADIUS_INTEGER4, "Cisco Link Compression", NULL},
+ {234, RADIUS_INTEGER4, "Cisco Target Util", NULL},
+ {235, RADIUS_INTEGER4, "Cisco Maximum Channels", NULL},
+ /* #236-#241 */
+ {242, RADIUS_INTEGER4, "Cisco Data Filter", NULL},
+ {243, RADIUS_INTEGER4, "Cisco Call Filter", NULL},
+ {244, RADIUS_INTEGER4, "Cisco Idle Limit", NULL},
+ /* Cisco SSG Service Selection Gateway Attributes */
+ {250, RADIUS_STRING, "Cisco Account Info", NULL},
+ {251, RADIUS_STRING, "Cisco Service Info", NULL},
+ {252, RADIUS_BINSTRING, "Cisco Command Info", NULL},
+ {253, RADIUS_STRING, "Cisco Control Info", NULL},
+ {255, RADIUS_INTEGER4, "Cisco Xmit Rate", NULL},
+ {0, 0, NULL, NULL}
+};
+
+/*
+reference:
+ 'dictionary.shiva' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.shiva
+*/
+static const value_string radius_vendor_shiva_type_of_service_vals[] =
+{
+ {1, "Analog"},
+ {2, "Digitized Analog"},
+ {3, "Digital"},
+ {4, "Digital V.110"},
+ {5, "Digital V.120"},
+ {6, "Digital Leased Line"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_shiva_link_protocol_vals[] =
+{
+ {1, "HDLC"},
+ {2, "ARAV1"},
+ {3, "ARAV2"},
+ {4, "SHELL"},
+ {5, "AALAP"},
+ {6, "SLIP"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_shiva_disconnect_reason_vals[] =
+{
+ {1, "Remote"},
+ {2, "Error"},
+ {3, "Idle Timeout"},
+ {4, "Session Timeout"},
+ {5, "Admin Disconnect"},
+ {6, "Dialback"},
+ {7, "Virtual Connection"},
+ {8, "Bandwidth On Demand"},
+ {9, "Failed Authentication"},
+ {10, "Preempted"},
+ {11, "Blocked"},
+ {12, "Tariff Management"},
+ {13, "Backup"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_shiva_function_vals[] =
+{
+ {0, "Unknown"},
+ {1, "Dialin"},
+ {2, "Dialout"},
+ {3, "Lan To Lan"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_shiva_connect_reason_vals[] =
+{
+ {1, "Remote"},
+ {2, "Dialback"},
+ {3, "Virtual Connection"},
+ {4, "Bandwidth On Demand"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_shiva_attrib[] =
+{
+ {1, RADIUS_STRING, "Shiva User Attributes", NULL},
+ {90, RADIUS_STRING, "Shiva Called Number", NULL},
+ {91, RADIUS_STRING, "Shiva Calling Number", NULL},
+ {92, RADIUS_STRING, "Shiva Customer Id", NULL},
+ {93, RADIUS_INTEGER4, "Shiva Type Of Service", radius_vendor_shiva_type_of_service_vals},
+ {94, RADIUS_INTEGER4, "Shiva Link Speed", NULL},
+ {95, RADIUS_INTEGER4, "Shiva Links In Bundle", NULL},
+ {96, RADIUS_INTEGER4, "Shiva Compression Type", NULL},
+ {97, RADIUS_INTEGER4, "Shiva Link Protocol", radius_vendor_shiva_link_protocol_vals},
+ {98, RADIUS_INTEGER4, "Shiva Network Protocols", NULL},
+ {99, RADIUS_INTEGER4, "Shiva Session Id", NULL},
+ {100, RADIUS_INTEGER4, "Shiva Disconnect Reason", radius_vendor_shiva_disconnect_reason_vals},
+ {101, RADIUS_IP_ADDRESS, "Shiva Acct Serv Switch", NULL},
+ {102, RADIUS_INTEGER4, "Shiva Event Flags", NULL},
+ {103, RADIUS_INTEGER4, "Shiva Function", radius_vendor_shiva_function_vals},
+ {104, RADIUS_INTEGER4, "Shiva Connect Reason", radius_vendor_shiva_connect_reason_vals},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ Cisco ACS 3.2 User Guide - Appendix D
+ http://www.cisco.com/univercd/cc/td/doc/product/access/acs_soft/csacs4nt/acs32/user02/ad.htm#wp473517
+*/
+
+
+static const radius_attr_info radius_vendor_cisco_vpn5000_attrib[] =
+{
+ {1, RADIUS_INTEGER4, "CVPN5000-Tunnel-Throughput", NULL},
+ {2, RADIUS_IP_ADDRESS, "CVPN5000-Client-Assigned-IP", NULL},
+ {3, RADIUS_IP_ADDRESS, "CVPN5000-Client-Real-IP", NULL},
+ {4, RADIUS_STRING, "CVPN5000-VPN-GroupInfo", NULL},
+ {5, RADIUS_STRING, "CVPN5000-VPN-Password", NULL},
+ {6, RADIUS_INTEGER4, "CVPN5000-Echo", NULL},
+ {7, RADIUS_INTEGER4, "CVPN5000-Client-Assigned-IPX", NULL},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ 'dictionary.livingston' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.livingston
+*/
+static const value_string radius_vendor_livingston_ipsec_log_options_vals[] =
+{
+ {1, "SA Success On"},
+ {2, "SA Failure On"},
+ {3, "Console On"},
+ {4, "Syslog On"},
+ {5, "SA Success Off"},
+ {6, "SA Failure Off"},
+ {7, "Console Off"},
+ {8, "Syslog Off"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_livingston_ipsec_deny_action_vals[] =
+{
+ {1, "Drop"},
+ {2, "ICMP Reject"},
+ {3, "Pass Through"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_livingston_nat_log_options_vals[] =
+{
+ {1, "Session Success On"},
+ {2, "Session Failure On"},
+ {3, "Console On"},
+ {4, "Syslog On"},
+ {5, "Success Off"},
+ {6, "Failure Off"},
+ {7, "Console Off"},
+ {8, "Syslog Off"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_livingston_nat_sess_dir_fail_action_vals[] =
+{
+ {1, "Drop"},
+ {2, "ICMP Reject"},
+ {3, "Pass Through"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_livingston_multicast_client_vals[] =
+{
+ {1, "On"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_livingston_attrib[] =
+{
+ {2, RADIUS_STRING, "LE Terminate Detail", NULL},
+ {3, RADIUS_STRING, "LE Advice of Charge", NULL},
+ {4, RADIUS_STRING, "LE Connect Detail", NULL},
+ {6, RADIUS_STRING, "LE IP Pool", NULL},
+ {7, RADIUS_IP_ADDRESS, "LE IP Gateway", NULL},
+ {8, RADIUS_STRING, "LE Modem Info", NULL},
+ {9, RADIUS_INTEGER4, "LE IPSec Log Options", radius_vendor_livingston_ipsec_log_options_vals},
+ {10, RADIUS_INTEGER4, "LE IPSec Deny Action", radius_vendor_livingston_ipsec_deny_action_vals},
+ {11, RADIUS_STRING, "LE IPSec Active Profile", NULL},
+ {12, RADIUS_STRING, "LE IPSec Outsource Profile", NULL},
+ {13, RADIUS_STRING, "LE IPSec Passive Profile", NULL},
+ {14, RADIUS_INTEGER4, "LE NAT TCP Session Timeout", NULL},
+ {15, RADIUS_INTEGER4, "LE NAT Other Session Timeout", NULL},
+ {16, RADIUS_INTEGER4, "LE NAT Log Options", radius_vendor_livingston_nat_log_options_vals},
+ {17, RADIUS_INTEGER4, "LE NAT Sess Dir Fail Action", radius_vendor_livingston_nat_sess_dir_fail_action_vals},
+ {18, RADIUS_STRING, "LE NAT Inmap", NULL},
+ {19, RADIUS_STRING, "LE NAT Outmap", NULL},
+ {20, RADIUS_STRING, "LE NAT Outsource Inmap", NULL},
+ {21, RADIUS_STRING, "LE NAT Outsource Outmap", NULL},
+ {22, RADIUS_STRING, "LE Admin Group", NULL},
+ {23, RADIUS_INTEGER4, "LE Multicast Client", radius_vendor_livingston_multicast_client_vals},
+ {0, 0, NULL, NULL},
+};
+
+static const value_string radius_vendor_microsoft_bap_usage_vals[] =
+{
+ {0, "Not Allowed"},
+ {1, "Allowed"},
+ {2, "Required"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_microsoft_arap_pw_change_reason_vals[] =
+{
+ {1, "Just Change Password"},
+ {2, "Expired Password"},
+ {3, "Admin Required Password Change"},
+ {4, "Password Too Short"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_microsoft_acct_auth_type_vals[] =
+{
+ {1, "PAP"},
+ {2, "CHAP"},
+ {3, "MS CHAP 1"},
+ {4, "MS CHAP 2"},
+ {5, "EAP"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_microsoft_acct_eap_type_vals[] =
+{
+ {4, "MD5"},
+ {5, "OTP"},
+ {6, "Generic Token Card"},
+ {13, "TLS"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_microsoft_attrib[] =
+{
+ {1, RADIUS_BINSTRING, "MS CHAP Response", NULL},
+ {2, RADIUS_STRING, "MS CHAP Error", NULL},
+ {3, RADIUS_BINSTRING, "MS CHAP CPW 1", NULL},
+ {4, RADIUS_BINSTRING, "MS CHAP CPW 2", NULL},
+ {5, RADIUS_BINSTRING, "MS CHAP LM Enc PW", NULL},
+ {6, RADIUS_BINSTRING, "MS CHAP NT Enc PW", NULL},
+ {7, RADIUS_BINSTRING, "MS MPPE Encryption Policy", NULL},
+ {8, RADIUS_BINSTRING, "MS MPPE Encryption Type", NULL},
+ {9, RADIUS_INTEGER4, "MS RAS Vendor", NULL},
+ {10, RADIUS_STRING, "MS CHAP Domain", NULL},
+ {11, RADIUS_BINSTRING, "MS CHAP Challenge", NULL},
+ {12, RADIUS_BINSTRING, "MS CHAP MPPE Keys", NULL},
+ {13, RADIUS_INTEGER4, "MS BAP Usage", radius_vendor_microsoft_bap_usage_vals},
+ {14, RADIUS_INTEGER4, "MS Link Utilization Threshold", NULL},
+ {15, RADIUS_INTEGER4, "MS Link Drop Time Limit", NULL},
+ {16, RADIUS_BINSTRING, "MS MPPE Send Key", NULL},
+ {17, RADIUS_BINSTRING, "MS MPPE Recv Key", NULL},
+ {18, RADIUS_STRING, "MS RAS Version", NULL},
+ {19, RADIUS_BINSTRING, "MS Old ARAP Password", NULL},
+ {20, RADIUS_BINSTRING, "MS New ARAP Password", NULL},
+ {21, RADIUS_INTEGER4, "MS ARAP PW Change Reason", radius_vendor_microsoft_arap_pw_change_reason_vals},
+ {22, RADIUS_BINSTRING, "MS Filter", NULL},
+ {23, RADIUS_INTEGER4, "MS Acct Auth Type", radius_vendor_microsoft_acct_auth_type_vals},
+ {24, RADIUS_INTEGER4, "MS Acct EAP Type", radius_vendor_microsoft_acct_eap_type_vals},
+ {25, RADIUS_BINSTRING, "MS CHAP2 Response", NULL},
+ {26, RADIUS_BINSTRING, "MS CHAP2 Success", NULL},
+ {27, RADIUS_BINSTRING, "MS CHAP2 CPW", NULL},
+ {28, RADIUS_IP_ADDRESS, "MS Primary DNS Server", NULL},
+ {29, RADIUS_IP_ADDRESS, "MS Secondary DNS Server", NULL},
+ {30, RADIUS_IP_ADDRESS, "MS Primary NBNS Server", NULL},
+ {31, RADIUS_IP_ADDRESS, "MS Secondary NBNS Server", NULL},
+ {0, 0, NULL, NULL}
+};
+
+static const value_string radius_vendor_ascend_calling_id_type_of_number_vals[] =
+{
+ {0, "Unknown"},
+ {1, "International Number"},
+ {2, "National Number"},
+ {3, "Network Specific"},
+ {4, "Subscriber Number"},
+ {6, "Abbreviated Number"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_ascend_calling_id_numbering_plan_vals[] =
+{
+ {0, "Unknown"},
+ {1, "ISDN Telephony"},
+ {3, "Data"},
+ {4, "Telex"},
+ {8, "National"},
+ {9, "Private"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_ascend_calling_id_presentation_vals[] =
+{
+ {0, "Allowed"},
+ {1, "Restricted"},
+ {2, "Number Not Available"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_ascend_calling_id_screening_vals[] =
+{
+ {0, "User Not Screened"},
+ {1, "User Provided Passed"},
+ {2, "User Provided Failed"},
+ {3, "Network Provided"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_ascend_attrib[] =
+{
+ {7, RADIUS_STRING, "Ascend UU Info", NULL},
+ {9, RADIUS_INTEGER4, "Ascend CIR Timer", NULL},
+ {10, RADIUS_INTEGER4, "Ascend FR 08 Mode", NULL},
+ {11, RADIUS_INTEGER4, "Ascend Destination Nas Port", NULL},
+ {12, RADIUS_STRING, "Ascend FR SVC Addr", NULL},
+ {13, RADIUS_INTEGER4, "Ascend NAS Port Format", NULL},
+ {14, RADIUS_INTEGER4, "Ascend ATM Fault Management", NULL},
+ {15, RADIUS_INTEGER4, "Ascend ATM Loopback Cell Loss", NULL},
+ {16, RADIUS_INTEGER4, "Ascend Ckt Type", NULL},
+ {17, RADIUS_INTEGER4, "Ascend SVC Enabled", NULL},
+ {18, RADIUS_INTEGER4, "Ascend Session Type", NULL},
+ {19, RADIUS_IP_ADDRESS, "Ascend H323 Gatekeeper", NULL},
+ {20, RADIUS_STRING, "Ascend Global Call Id", NULL},
+ {21, RADIUS_INTEGER4, "Ascend H323 Conference Id", NULL},
+ {22, RADIUS_IP_ADDRESS, "Ascend H323 Fegw Address", NULL},
+ {23, RADIUS_INTEGER4, "Ascend H323 Dialed Time", NULL},
+ {24, RADIUS_STRING, "Ascend Dialed Number", NULL},
+ {25, RADIUS_INTEGER4, "Ascend Inter Arrival Jitter", NULL},
+ {26, RADIUS_INTEGER4, "Ascend Dropped Octets", NULL},
+ {27, RADIUS_INTEGER4, "Ascend Dropped Packets", NULL},
+ {29, RADIUS_INTEGER4, "Ascend X25 Pad X3 Profile", NULL},
+ {30, RADIUS_STRING, "Ascend X25 Pad X3 Parameters", NULL},
+ {31, RADIUS_STRING, "Ascend Tunnel VRouter Name", NULL},
+ {32, RADIUS_INTEGER4, "Ascend X25 Reverse Charging", NULL},
+ {33, RADIUS_STRING, "Ascend X25 Nui Prompt", NULL},
+ {34, RADIUS_STRING, "Ascend X25 Nui Password Prompt", NULL},
+ {35, RADIUS_STRING, "Ascend X25 Cug", NULL},
+ {36, RADIUS_STRING, "Ascend X25 Pad Alias 1", NULL},
+ {37, RADIUS_STRING, "Ascend X25 Pad Alias 2", NULL},
+ {38, RADIUS_STRING, "Ascend X25 Pad Alias 3", NULL},
+ {39, RADIUS_STRING, "Ascend X25 X121 Address", NULL},
+ {40, RADIUS_STRING, "Ascend X25 Nui", NULL},
+ {41, RADIUS_STRING, "Ascend X25 Rpoa", NULL},
+ {42, RADIUS_STRING, "Ascend X25 Pad Prompt", NULL},
+ {43, RADIUS_STRING, "Ascend X25 Pad Banner", NULL},
+ {44, RADIUS_STRING, "Ascend X25 Profile Name", NULL},
+ {45, RADIUS_STRING, "Ascend Recv Name", NULL},
+ {46, RADIUS_INTEGER4, "Ascend Bi Directional Auth", NULL},
+ {47, RADIUS_INTEGER4, "Ascend MTU", NULL},
+ {48, RADIUS_INTEGER4, "Ascend Call Direction", NULL},
+ {49, RADIUS_INTEGER4, "Ascend Service Type", NULL},
+ {50, RADIUS_INTEGER4, "Ascend Filter Required", NULL},
+ {51, RADIUS_INTEGER4, "Ascend Traffic Shaper", NULL},
+ {52, RADIUS_STRING, "Ascend Access Intercept LEA", NULL},
+ {53, RADIUS_STRING, "Ascend Access Intercept Log", NULL},
+ {54, RADIUS_STRING, "Ascend Private Route Table ID", NULL},
+ {55, RADIUS_INTEGER4, "Ascend Private Route Required", NULL},
+ {56, RADIUS_INTEGER4, "Ascend Cache Refresh", NULL},
+ {57, RADIUS_INTEGER4, "Ascend Cache Time", NULL},
+ {58, RADIUS_INTEGER4, "Ascend Egress Enabled", NULL},
+ {59, RADIUS_STRING, "Ascend QOS Upstream", NULL},
+ {60, RADIUS_STRING, "Ascend QOS Downstream", NULL},
+ {61, RADIUS_INTEGER4, "Ascend ATM Connect Vpi", NULL},
+ {62, RADIUS_INTEGER4, "Ascend ATM Connect Vci", NULL},
+ {63, RADIUS_INTEGER4, "Ascend ATM Connect Group", NULL},
+ {64, RADIUS_INTEGER4, "Ascend ATM Group", NULL},
+ {65, RADIUS_INTEGER4, "Ascend IPX Header Compression", NULL},
+ {66, RADIUS_INTEGER4, "Ascend Calling Id Type Of Number", radius_vendor_ascend_calling_id_type_of_number_vals},
+ {67, RADIUS_INTEGER4, "Ascend Calling Id Numbering Plan", radius_vendor_ascend_calling_id_numbering_plan_vals},
+ {68, RADIUS_INTEGER4, "Ascend Calling Id Presentation", radius_vendor_ascend_calling_id_presentation_vals},
+ {69, RADIUS_INTEGER4, "Ascend Calling Id Screening", radius_vendor_ascend_calling_id_screening_vals},
+ {70, RADIUS_INTEGER4, "Ascend BIR Enable", NULL},
+ {71, RADIUS_INTEGER4, "Ascend BIR Proxy", NULL},
+ {72, RADIUS_INTEGER4, "Ascend BIR Bridge Group", NULL},
+ {73, RADIUS_STRING, "Ascend IPSEC Profile", NULL},
+ {74, RADIUS_INTEGER4, "Ascend PPPoE Enable", NULL},
+ {75, RADIUS_INTEGER4, "Ascend Bridge Non PPPoE", NULL},
+ {76, RADIUS_INTEGER4, "Ascend ATM Direct", NULL},
+ {77, RADIUS_STRING, "Ascend ATM Direct Profile", NULL},
+ {78, RADIUS_IP_ADDRESS, "Ascend Client Primary WINS", NULL},
+ {79, RADIUS_IP_ADDRESS, "Ascend Client Secondary WINS", NULL},
+ {80, RADIUS_INTEGER4, "Ascend Client Assign WINS", NULL},
+ {81, RADIUS_INTEGER4, "Ascend Auth Type", NULL},
+ {82, RADIUS_INTEGER4, "Ascend Port Redir Protocol", NULL},
+ {83, RADIUS_INTEGER4, "Ascend Port Redir Portnum", NULL},
+ {84, RADIUS_IP_ADDRESS, "Ascend Port Redir Server", NULL},
+ {85, RADIUS_INTEGER4, "Ascend IP Pool Chaining", NULL},
+ {86, RADIUS_IP_ADDRESS, "Ascend Owner IP Addr", NULL},
+ {87, RADIUS_INTEGER4, "Ascend IP TOS", NULL},
+ {88, RADIUS_INTEGER4, "Ascend IP TOS Precedence", NULL},
+ {89, RADIUS_INTEGER4, "Ascend IP TOS Apply To", NULL},
+ {90, RADIUS_STRING, "Ascend Filter", NULL},
+ {91, RADIUS_STRING, "Ascend Telnet Profile", NULL},
+ {92, RADIUS_INTEGER4, "Ascend Dsl Rate Type", NULL},
+ {93, RADIUS_STRING, "Ascend Redirect Number", NULL},
+ {94, RADIUS_INTEGER4, "Ascend ATM Vpi", NULL},
+ {95, RADIUS_INTEGER4, "Ascend ATM Vci", NULL},
+ {96, RADIUS_INTEGER4, "Ascend Source IP Check", NULL},
+ {97, RADIUS_INTEGER4, "Ascend Dsl Rate Mode", NULL},
+ {98, RADIUS_INTEGER4, "Ascend Dsl Upstream Limit", NULL},
+ {99, RADIUS_INTEGER4, "Ascend Dsl Downstream Limit", NULL},
+ {100, RADIUS_INTEGER4, "Ascend Dsl CIR Recv Limit", NULL},
+ {101, RADIUS_INTEGER4, "Ascend Dsl CIR Xmit Limit", NULL},
+ {102, RADIUS_STRING, "Ascend VRouter Name", NULL},
+ {103, RADIUS_STRING, "Ascend Source Auth", NULL},
+ {104, RADIUS_STRING, "Ascend Private Route", NULL},
+ {105, RADIUS_INTEGER4, "Ascend Numbering Plan ID", NULL},
+ {106, RADIUS_INTEGER4, "Ascend FR Link Status DLCI", NULL},
+ {107, RADIUS_STRING, "Ascend Calling Subaddress", NULL},
+ {108, RADIUS_INTEGER4, "Ascend Callback Delay", NULL},
+ {109, RADIUS_STRING, "Ascend Endpoint Disc", NULL},
+ {110, RADIUS_STRING, "Ascend Remote FW", NULL},
+ {111, RADIUS_INTEGER4, "Ascend Multicast GLeave Delay", NULL},
+ {112, RADIUS_INTEGER4, "Ascend CBCP Enable", NULL},
+ {113, RADIUS_INTEGER4, "Ascend CBCP Mode", NULL},
+ {114, RADIUS_INTEGER4, "Ascend CBCP Delay", NULL},
+ {115, RADIUS_INTEGER4, "Ascend CBCP Trunk Group", NULL},
+ {116, RADIUS_STRING, "Ascend Appletalk Route", NULL},
+ {117, RADIUS_INTEGER4, "Ascend Appletalk Peer Mode", NULL},
+ {118, RADIUS_INTEGER4, "Ascend Route Appletalk", NULL},
+ {119, RADIUS_STRING, "Ascend FCP Parameter", NULL},
+ {120, RADIUS_INTEGER4, "Ascend Modem Port No", NULL},
+ {121, RADIUS_INTEGER4, "Ascend Modem Slot No", NULL},
+ {122, RADIUS_INTEGER4, "Ascend Modem Shelf No", NULL},
+ {123, RADIUS_INTEGER4, "Ascend Call Attempt Limit", NULL},
+ {124, RADIUS_INTEGER4, "Ascend Call Block Duration", NULL},
+ {125, RADIUS_INTEGER4, "Ascend Maximum Call Duration", NULL},
+ {126, RADIUS_INTEGER4, "Ascend Temporary Rtes", NULL},
+ {127, RADIUS_INTEGER4, "Ascend Tunneling Protocol", NULL},
+ {128, RADIUS_INTEGER4, "Ascend Shared Profile Enable", NULL},
+ {129, RADIUS_STRING, "Ascend Primary Home Agent", NULL},
+ {130, RADIUS_STRING, "Ascend Secondary Home Agent", NULL},
+ {131, RADIUS_INTEGER4, "Ascend Dialout Allowed", NULL},
+ {132, RADIUS_IP_ADDRESS, "Ascend Client Gateway", NULL},
+ {133, RADIUS_INTEGER4, "Ascend BACP Enable", NULL},
+ {134, RADIUS_INTEGER4, "Ascend DHCP Maximum Leases", NULL},
+ {135, RADIUS_IP_ADDRESS, "Ascend Client Primary DNS", NULL},
+ {136, RADIUS_IP_ADDRESS, "Ascend Client Secondary DNS", NULL},
+ {137, RADIUS_INTEGER4, "Ascend Client Assign DNS", NULL},
+ {138, RADIUS_INTEGER4, "Ascend User Acct Type", NULL},
+ {139, RADIUS_IP_ADDRESS, "Ascend User Acct Host", NULL},
+ {140, RADIUS_INTEGER4, "Ascend User Acct Port", NULL},
+ {141, RADIUS_STRING, "Ascend User Acct Key", NULL},
+ {142, RADIUS_INTEGER4, "Ascend User Acct Base", NULL},
+ {143, RADIUS_INTEGER4, "Ascend User Acct Time", NULL},
+ {144, RADIUS_IP_ADDRESS, "Ascend Assign IP Client", NULL},
+ {145, RADIUS_IP_ADDRESS, "Ascend Assign IP Server", NULL},
+ {146, RADIUS_STRING, "Ascend Assign IP Global Pool", NULL},
+ {147, RADIUS_INTEGER4, "Ascend DHCP Reply", NULL},
+ {148, RADIUS_INTEGER4, "Ascend DHCP Pool Number", NULL},
+ {149, RADIUS_INTEGER4, "Ascend Expect Callback", NULL},
+ {150, RADIUS_INTEGER4, "Ascend Event Type", NULL},
+ {151, RADIUS_STRING, "Ascend Session Svr Key", NULL},
+ {152, RADIUS_INTEGER4, "Ascend Multicast Rate Limit", NULL},
+ {153, RADIUS_IP_ADDRESS, "Ascend IF Netmask", NULL},
+ {154, RADIUS_IP_ADDRESS, "Ascend Remote Addr", NULL},
+ {155, RADIUS_INTEGER4, "Ascend Multicast Client", NULL},
+ {156, RADIUS_STRING, "Ascend FR Circuit Name", NULL},
+ {157, RADIUS_INTEGER4, "Ascend FR LinkUp", NULL},
+ {158, RADIUS_INTEGER4, "Ascend FR Nailed Grp", NULL},
+ {159, RADIUS_INTEGER4, "Ascend FR Type", NULL},
+ {160, RADIUS_INTEGER4, "Ascend FR Link Mgt", NULL},
+ {161, RADIUS_INTEGER4, "Ascend FR N391", NULL},
+ {162, RADIUS_INTEGER4, "Ascend FR DCE N392", NULL},
+ {163, RADIUS_INTEGER4, "Ascend FR DTE N392", NULL},
+ {164, RADIUS_INTEGER4, "Ascend FR DCE N393", NULL},
+ {165, RADIUS_INTEGER4, "Ascend FR DTE N393", NULL},
+ {166, RADIUS_INTEGER4, "Ascend FR T391", NULL},
+ {167, RADIUS_INTEGER4, "Ascend FR T392", NULL},
+ {168, RADIUS_STRING, "Ascend Bridge Address", NULL},
+ {169, RADIUS_INTEGER4, "Ascend TS Idle Limit", NULL},
+ {170, RADIUS_INTEGER4, "Ascend TS Idle Mode", NULL},
+ {171, RADIUS_INTEGER4, "Ascend DBA Monitor", NULL},
+ {172, RADIUS_INTEGER4, "Ascend Base Channel Count", NULL},
+ {173, RADIUS_INTEGER4, "Ascend Minimum Channels", NULL},
+ {174, RADIUS_STRING, "Ascend IPX Route", NULL},
+ {175, RADIUS_INTEGER4, "Ascend FT1 Caller", NULL},
+ {176, RADIUS_STRING, "Ascend Backup", NULL},
+ {177, RADIUS_INTEGER4, "Ascend Call Type", NULL},
+ {178, RADIUS_STRING, "Ascend Group", NULL},
+ {179, RADIUS_INTEGER4, "Ascend FR DLCI", NULL},
+ {180, RADIUS_STRING, "Ascend FR Profile Name", NULL},
+ {181, RADIUS_STRING, "Ascend Ara PW", NULL},
+ {182, RADIUS_STRING, "Ascend IPX Node Addr", NULL},
+ {183, RADIUS_IP_ADDRESS, "Ascend Home Agent IP Addr", NULL},
+ {184, RADIUS_STRING, "Ascend Home Agent Password", NULL},
+ {185, RADIUS_STRING, "Ascend Home Network Name", NULL},
+ {186, RADIUS_INTEGER4, "Ascend Home Agent UDP Port", NULL},
+ {187, RADIUS_INTEGER4, "Ascend Multilink ID", NULL},
+ {188, RADIUS_INTEGER4, "Ascend Num In Multilink", NULL},
+ {189, RADIUS_IP_ADDRESS, "Ascend First Dest", NULL},
+ {190, RADIUS_INTEGER4, "Ascend Pre Input Octets", NULL},
+ {191, RADIUS_INTEGER4, "Ascend Pre Output Octets", NULL},
+ {192, RADIUS_INTEGER4, "Ascend Pre Input Packets", NULL},
+ {193, RADIUS_INTEGER4, "Ascend Pre Output Packets", NULL},
+ {194, RADIUS_INTEGER4, "Ascend Maximum Time", NULL},
+ {195, RADIUS_INTEGER4, "Ascend Disconnect Cause", NULL},
+ {196, RADIUS_INTEGER4, "Ascend Connect Progress", NULL},
+ {197, RADIUS_INTEGER4, "Ascend Data Rate", NULL},
+ {198, RADIUS_INTEGER4, "Ascend PreSession Time", NULL},
+ {199, RADIUS_INTEGER4, "Ascend Token Idle", NULL},
+ {200, RADIUS_INTEGER4, "Ascend Token Immediate", NULL},
+ {201, RADIUS_INTEGER4, "Ascend Require Auth", NULL},
+ {202, RADIUS_STRING, "Ascend Number Sessions", NULL},
+ {203, RADIUS_STRING, "Ascend Authen Alias", NULL},
+ {204, RADIUS_INTEGER4, "Ascend Token Expiry", NULL},
+ {205, RADIUS_STRING, "Ascend Menu Selector", NULL},
+ {206, RADIUS_STRING, "Ascend Menu Item", NULL},
+ {207, RADIUS_INTEGER4, "Ascend PW Warntime", NULL},
+ {208, RADIUS_INTEGER4, "Ascend PW Lifetime", NULL},
+ {209, RADIUS_IP_ADDRESS, "Ascend IP Direct", NULL},
+ {210, RADIUS_INTEGER4, "Ascend PPP VJ Slot Comp", NULL},
+ {211, RADIUS_INTEGER4, "Ascend PPP VJ 1172", NULL},
+ {212, RADIUS_INTEGER4, "Ascend PPP Async Map", NULL},
+ {213, RADIUS_STRING, "Ascend Third Prompt", NULL},
+ {214, RADIUS_STRING, "Ascend Send Secret", NULL},
+ {215, RADIUS_STRING, "Ascend Receive Secret", NULL},
+ {216, RADIUS_INTEGER4, "Ascend IPX Peer Mode", NULL},
+ {217, RADIUS_STRING, "Ascend IP Pool Definition", NULL},
+ {218, RADIUS_INTEGER4, "Ascend Assign IP Pool", NULL},
+ {219, RADIUS_INTEGER4, "Ascend FR Direct", NULL},
+ {220, RADIUS_STRING, "Ascend FR Direct Profile", NULL},
+ {221, RADIUS_INTEGER4, "Ascend FR Direct DLCI", NULL},
+ {222, RADIUS_INTEGER4, "Ascend Handle IPX", NULL},
+ {223, RADIUS_INTEGER4, "Ascend Netware timeout", NULL},
+ {224, RADIUS_INTEGER4, "Ascend IPX Alias", NULL},
+ {225, RADIUS_INTEGER4, "Ascend Metric", NULL},
+ {226, RADIUS_INTEGER4, "Ascend PRI Number Type", NULL},
+ {227, RADIUS_STRING, "Ascend Dial Number", NULL},
+ {228, RADIUS_INTEGER4, "Ascend Route IP", NULL},
+ {229, RADIUS_INTEGER4, "Ascend Route IPX", NULL},
+ {230, RADIUS_INTEGER4, "Ascend Bridge", NULL},
+ {231, RADIUS_INTEGER4, "Ascend Send Auth", NULL},
+ {232, RADIUS_STRING, "Ascend Send Passwd", NULL},
+ {233, RADIUS_INTEGER4, "Ascend Link Compression", NULL},
+ {234, RADIUS_INTEGER4, "Ascend Target Util", NULL},
+ {235, RADIUS_INTEGER4, "Ascend Maximum Channels", NULL},
+ {236, RADIUS_INTEGER4, "Ascend Inc Channel Count", NULL},
+ {237, RADIUS_INTEGER4, "Ascend Dec Channel Count", NULL},
+ {238, RADIUS_INTEGER4, "Ascend Seconds Of History", NULL},
+ {239, RADIUS_INTEGER4, "Ascend History Weigh Type", NULL},
+ {240, RADIUS_INTEGER4, "Ascend Add Seconds", NULL},
+ {241, RADIUS_INTEGER4, "Ascend Remove Seconds", NULL},
+ {242, RADIUS_BINSTRING, "Ascend Data Filter", NULL},
+ {243, RADIUS_BINSTRING, "Ascend Call Filter", NULL},
+ {244, RADIUS_INTEGER4, "Ascend Idle Limit", NULL},
+ {245, RADIUS_INTEGER4, "Ascend Preempt Limit", NULL},
+ {246, RADIUS_INTEGER4, "Ascend Callback", NULL},
+ {247, RADIUS_INTEGER4, "Ascend Data Svc", NULL},
+ {248, RADIUS_INTEGER4, "Ascend Force 56", NULL},
+ {249, RADIUS_STRING, "Ascend Billing Number", NULL},
+ {250, RADIUS_INTEGER4, "Ascend Call By Call", NULL},
+ {251, RADIUS_STRING, "Ascend Transit Number", NULL},
+ {252, RADIUS_STRING, "Ascend Host Info", NULL},
+ {253, RADIUS_IP_ADDRESS, "Ascend PPP Address", NULL},
+ {254, RADIUS_INTEGER4, "Ascend MPP Idle Percent", NULL},
+ {255, RADIUS_INTEGER4, "Ascend Xmit Rate", NULL},
+ {0, 0, NULL, NULL}
+};
+
+/*
+reference:
+ 'dictionary.bay' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.bay
+*/
+static const value_string radius_vendor_bay_tunnel_authen_type_vals[] =
+{
+ {0, "none"},
+ {1, "kmd5 128"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_bay_tunnel_authen_mode_vals[] =
+{
+ {0, "none"},
+ {1, "prefix suffix"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_bay_user_server_location_vals[] =
+{
+ {1, "local"},
+ {2, "remote"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_bay_system_disc_reason_vals[] =
+{
+ {0, "Unknown"},
+ {1, "Line disconnected"},
+ {2, "Dial failed"},
+ {3, "WAN manager error"},
+ {4, "Disconnect reset"},
+ {5, "Error from adm_notify"},
+ {6, "Modem down adm_notify"},
+ {7, "PPP protocol disconnect"},
+ {8, "Inactivity timer"},
+ {9, "CLI Hangup command"},
+ {10, "CLI last job"},
+ {11, "Session timeout"},
+ {12, "Slave termination"},
+ {13, "Abnormal termination"},
+ {14, "DCD wait failed"},
+ {15, "CLI inactivity"},
+ {16, "Admin port reset"},
+ {17, "CLI auth failed"},
+ {18, "Slave auth failed"},
+ {19, "PAP auth failed"},
+ {20, "CHAP auth failed"},
+ {21, "Local modem reset"},
+ {22, "Modem dead"},
+ {23, "PPP LCP failure"},
+ {24, "PPP IPCP failure"},
+ {25, "PPP IPXCP failure"},
+ {26, "PPP ATCP failure"},
+ {27, "PPP CCP failure"},
+ {28, "PPP MP failure"},
+ {29, "PPP IPCP timeout"},
+ {30, "PPP IPXCP timeout"},
+ {31, "PPP ATCP timeout"},
+ {32, "PPP CCP timeout"},
+ {33, "PPP MP timeout"},
+ {34, "PPP init failure"},
+ {35, "PPP Unknown"},
+ {36, "PPP Dialback failed"},
+ {37, "PPP Address In Use"},
+ {38, "PPP No device"},
+ {39, "PPP Modem hangup rcvd"},
+ {40, "PPP Hangup rcvd"},
+ {41, "PPP Termination rcvd"},
+ {42, "PPP Kill rcvd"},
+ {43, "PPP Time rcvd"},
+ {44, "PPP No memory"},
+ {45, "PPP Connection Abort"},
+ {46, "PPP VPN LCP failure"},
+ {47, "PPP VPN Auth failure"},
+ {48, "PPP MP invalid port"},
+ {49, "PPP Invalid device"},
+ {50, "PPP MMP bundle failure"},
+ {51, "DVS Registration failure"},
+ {52, "DVS Home agent dereg"},
+ {53, "DVS Tunnel no renew"},
+ {54, "DVS Tunnel expired"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_bay_modem_disc_reason_vals[] =
+{
+ {0, "Unknown"},
+ {1, "Local disconnect"},
+ {2, "CD Timer Expired"},
+ {4, "Remote protocol disc"},
+ {5, "Clear down"},
+ {6, "Long Space disconnect"},
+ {7, "Carrier Lost"},
+ {8, "Modem Retrain Timeout"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_bay_addr_resolution_protocol_vals[] =
+{
+ {0, "none"},
+ {1, "DHCP"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_bay_user_level_vals[] =
+{
+ {2, "Manager"},
+ {4, "User"},
+ {8, "Operator"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_bay_audit_level_vals[] =
+{
+ {2, "Manager"},
+ {4, "User"},
+ {8, "Operator"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_bay_attrib[] =
+{
+ {28, RADIUS_STRING, "Annex Filter", NULL},
+ {29, RADIUS_STRING, "Annex CLI Command", NULL},
+ {30, RADIUS_STRING, "Annex CLI Filter", NULL},
+ {31, RADIUS_STRING, "Annex Host Restrict", NULL},
+ {32, RADIUS_STRING, "Annex Host Allow", NULL},
+ {33, RADIUS_STRING, "Annex Product Name", NULL},
+ {34, RADIUS_STRING, "Annex SW Version", NULL},
+ {35, RADIUS_IP_ADDRESS, "Annex Local IP Address", NULL},
+ {36, RADIUS_INTEGER4, "Annex Callback Portlist", NULL},
+ {37, RADIUS_INTEGER4, "Annex Sec Profile Index", NULL},
+ {38, RADIUS_INTEGER4, "Annex Tunnel Authen Type", radius_vendor_bay_tunnel_authen_type_vals},
+ {39, RADIUS_INTEGER4, "Annex Tunnel Authen Mode", radius_vendor_bay_tunnel_authen_mode_vals},
+ {40, RADIUS_STRING, "Annex Authen Servers", NULL},
+ {41, RADIUS_STRING, "Annex Acct Servers", NULL},
+ {42, RADIUS_INTEGER4, "Annex User Server Location", radius_vendor_bay_user_server_location_vals},
+ {43, RADIUS_STRING, "Annex Local Username", NULL},
+ {44, RADIUS_INTEGER4, "Annex System Disc Reason", radius_vendor_bay_system_disc_reason_vals},
+ {45, RADIUS_INTEGER4, "Annex Modem Disc Reason", radius_vendor_bay_modem_disc_reason_vals},
+ {46, RADIUS_INTEGER4, "Annex Disconnect Reason", NULL},
+ {47, RADIUS_INTEGER4, "Annex Addr Resolution Protocol", radius_vendor_bay_addr_resolution_protocol_vals},
+ {48, RADIUS_STRING, "Annex Addr Resolution Servers", NULL},
+ {49, RADIUS_STRING, "Annex Domain Name", NULL},
+ {50, RADIUS_INTEGER4, "Annex Transmit Speed", NULL},
+ {51, RADIUS_INTEGER4, "Annex Receive Speed", NULL},
+ {52, RADIUS_STRING, "Annex Input Filter", NULL},
+ {53, RADIUS_STRING, "Annex Output Filter", NULL},
+ {54, RADIUS_IP_ADDRESS, "Annex Primary DNS Server", NULL},
+ {55, RADIUS_IP_ADDRESS, "Annex Secondary DNS Server", NULL},
+ {56, RADIUS_IP_ADDRESS, "Annex Primary NBNS Server", NULL},
+ {57, RADIUS_IP_ADDRESS, "Annex Secondary NBNS Server", NULL},
+ {58, RADIUS_INTEGER4, "Annex Syslog Tap", NULL},
+ {59, RADIUS_INTEGER4, "Annex Keypress Timeout", NULL},
+ {60, RADIUS_INTEGER4, "Annex Unauthenticated Time", NULL},
+ {61, RADIUS_INTEGER4, "Annex Re CHAP Timeout", NULL},
+ {62, RADIUS_INTEGER4, "Annex MRRU", NULL},
+ {63, RADIUS_STRING, "Annex EDO", NULL},
+ {64, RADIUS_INTEGER4, "Annex PPP Trace Level", NULL},
+ {65, RADIUS_INTEGER4, "Annex Pre Input Octets", NULL},
+ {66, RADIUS_INTEGER4, "Annex Pre Output Octets", NULL},
+ {67, RADIUS_INTEGER4, "Annex Pre Input Packets", NULL},
+ {68, RADIUS_INTEGER4, "Annex Pre Output Packets", NULL},
+ {69, RADIUS_INTEGER4, "Annex Connect Progress", NULL},
+ {73, RADIUS_INTEGER4, "Annex Multicast Rate Limit", NULL},
+ {74, RADIUS_INTEGER4, "Annex Maximum Call Duration", NULL},
+ {75, RADIUS_INTEGER4, "Annex Multilink Id", NULL},
+ {76, RADIUS_INTEGER4, "Annex Num In Multilink", NULL},
+ {81, RADIUS_INTEGER4, "Annex Logical Channel Number", NULL},
+ {82, RADIUS_INTEGER4, "Annex Wan Number", NULL},
+ {83, RADIUS_INTEGER4, "Annex Port", NULL},
+ {85, RADIUS_INTEGER4, "Annex Pool Id", NULL},
+ {86, RADIUS_STRING, "Annex Compression Protocol", NULL},
+ {87, RADIUS_INTEGER4, "Annex Transmitted Packets", NULL},
+ {88, RADIUS_INTEGER4, "Annex Retransmitted Packets", NULL},
+ {89, RADIUS_INTEGER4, "Annex Signal to Noise Ratio", NULL},
+ {90, RADIUS_INTEGER4, "Annex Retrain Requests Sent", NULL},
+ {91, RADIUS_INTEGER4, "Annex Retrain Requests Rcvd", NULL},
+ {92, RADIUS_INTEGER4, "Annex Rate Reneg Req Sent", NULL},
+ {93, RADIUS_INTEGER4, "Annex Rate Reneg Req Rcvd", NULL},
+ {94, RADIUS_INTEGER4, "Annex Begin Receive Line Level", NULL},
+ {95, RADIUS_INTEGER4, "Annex End Receive Line Level", NULL},
+ {96, RADIUS_STRING, "Annex Begin Modulation", NULL},
+ {97, RADIUS_STRING, "Annex Error Correction Prot", NULL},
+ {98, RADIUS_STRING, "Annex End Modulation", NULL},
+ {100, RADIUS_INTEGER4, "Annex User Level", radius_vendor_bay_user_level_vals},
+ {101, RADIUS_INTEGER4, "Annex Audit Level", radius_vendor_bay_audit_level_vals},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ 'dictionary.foundry' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.foundry
+*/
+static const radius_attr_info radius_vendor_foundry_attrib[] =
+{
+ {1, RADIUS_INTEGER4, "Foundry Privilege Level", NULL},
+ {2, RADIUS_STRING, "Foundry Command String", NULL},
+ {3, RADIUS_INTEGER4, "Foundry Command Exception Flag", NULL},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ 'dictionary.versanet' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.versanet
+*/
+static const value_string radius_vendor_versanet_termination_cause_vals[] =
+{
+ {0, "Normal Hangup No Error Occurred"},
+ {3, "Call Waiting Caused Disconnect"},
+ {4, "Physical Carrier Loss"},
+ {5, "No err correction at other end"},
+ {6, "No resp to feature negotiation"},
+ {7, "1st modem async only 2nd sync"},
+ {8, "No framing technique in common"},
+ {9, "No protocol in common"},
+ {10, "Bad resp to feature negotiation"},
+ {11, "No sync info from remote modem"},
+ {12, "Normal Hangup by Remote modem"},
+ {13, "Retransmission limit reached"},
+ {14, "Protocol violation occurred"},
+ {15, "Lost DTR"},
+ {16, "Received GSTN cleardown"},
+ {17, "Inactivity timeout"},
+ {18, "Speed not supported"},
+ {19, "Long space disconnect"},
+ {20, "Key abort disconnect"},
+ {21, "Clears previous disc reason"},
+ {22, "No connection established"},
+ {23, "Disconnect after three retrains"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_versanet_attrib[] =
+{
+ {1, RADIUS_INTEGER4, "Versanet Termination Cause", radius_vendor_versanet_termination_cause_vals},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ 'dictionary.redback' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.redback
+*/
+static const value_string radius_vendor_redback_tunnel_function_vals[] =
+{
+ {1, "LAC Only"},
+ {2, "LNS Only"},
+ {3, "LAC LNS"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_redback_mcast_send_vals[] =
+{
+ {1, "NO SEND"},
+ {2, "SEND"},
+ {3, "UNSOLICITED SEND"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_redback_mcast_receive_vals[] =
+{
+ {1, "NO RECEIVE"},
+ {2, "RECEIVE"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_redback_tunnel_dnis_vals[] =
+{
+ {1, "DNIS"},
+ {2, "DNIS Only"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_redback_pvc_encapsulation_type_vals[] =
+{
+ {1, "AAA ENCAPS ATM RAW"},
+ {2, "AAA ENCAPS ATM ROUTE1483"},
+ {3, "AAA ENCAPS ATM AUTO1483"},
+ {4, "AAA ENCAPS ATM MULTI"},
+ {5, "AAA ENCAPS ATM BRIDGE1483"},
+ {6, "AAA ENCAPS ATM PPP"},
+ {7, "AAA ENCAPS ATM PPP SERIAL"},
+ {8, "AAA ENCAPS ATM PPP NLPID"},
+ {9, "AAA ENCAPS ATM PPP AUTO"},
+ {10, "AAA ENCAPS ATM PPPOE"},
+ {11, "AAA ENCAPS ATM L2TP"},
+ {12, "AAA ENCAPS ATM PPP LLC"},
+ {13, "AAA ENCAPS FRAME AUTO1490"},
+ {14, "AAA ENCAPS FRAME MULTI"},
+ {15, "AAA ENCAPS FRAME BRIDGE1490"},
+ {16, "AAA ENCAPS FRAME PPP"},
+ {17, "AAA ENCAPS FRAME PPP AUTO"},
+ {18, "AAA ENCAPS FRAME PPPOE"},
+ {19, "AAA ENCAPS FRAME ROUTE1490"},
+ {20, "AAA ENCAPS FRAME L2TP"},
+ {21, "AAA ENCAPS L2TP VC MUXED"},
+ {22, "AAA ENCAPS ETH"},
+ {23, "AAA ENCAPS ETH PPPOE"},
+ {24, "AAA ENCAPS ETH MULTI"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_redback_pvc_circuit_padding_vals[] =
+{
+ {1, "AAA CIRCUIT PADDING"},
+ {2, "AAA CIRCUIT NO PADDING"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_redback_bind_type_vals[] =
+{
+ {1, "AAA AUTH BIND"},
+ {2, "AAA BYPASS BIND"},
+ {3, "AAA INTERFACE BIND"},
+ {4, "AAA SUBSCRIBE BIND"},
+ {5, "AAA TUNNEL BIND"},
+ {6, "AAA SESSION BIND"},
+ {7, "AAA Q8021 BIND"},
+ {8, "AAA MULTI BIND"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_redback_bind_auth_protocol_vals[] =
+{
+ {1, "AAA PPP PAP"},
+ {2, "AAA PPP CHAP"},
+ {3, "AAA PPP CHAP WAIT"},
+ {4, "AAA PPP CHAP PAP"},
+ {5, "AAA PPP CHAP WAIT PAP"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_redback_lac_port_type_vals[] =
+{
+ {40, "NAS PORT TYPE 10BT"},
+ {41, "NAS PORT TYPE 100BT"},
+ {42, "NAS PORT TYPE DS3 FR"},
+ {43, "NAS PORT TYPE DS3 ATM"},
+ {44, "NAS PORT TYPE OC3"},
+ {45, "NAS PORT TYPE HSSI"},
+ {46, "NAS PORT TYPE EIA530"},
+ {47, "NAS PORT TYPE T1"},
+ {48, "NAS PORT TYPE CHAN T3"},
+ {49, "NAS PORT TYPE DS1 FR"},
+ {50, "NAS PORT TYPE E3 ATM"},
+ {51, "NAS PORT TYPE IMA ATM"},
+ {52, "NAS PORT TYPE DS3 ATM 2"},
+ {53, "NAS PORT TYPE OC3 ATM 2"},
+ {54, "NAS PORT TYPE 1000BSX"},
+ {55, "NAS PORT TYPE E1 FR"},
+ {56, "NAS PORT TYPE E1 ATM"},
+ {57, "NAS PORT TYPE E3 FR"},
+ {58, "NAS PORT TYPE OC3 POS"},
+ {59, "NAS PORT TYPE OC12 POS"},
+ {60, "NAS PORT TYPE PPPOE"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_redback_lac_real_port_type_vals[] =
+{
+ {40, "NAS PORT TYPE 10BT"},
+ {41, "NAS PORT TYPE 100BT"},
+ {42, "NAS PORT TYPE DS3 FR"},
+ {43, "NAS PORT TYPE DS3 ATM"},
+ {44, "NAS PORT TYPE OC3"},
+ {45, "NAS PORT TYPE HSSI"},
+ {46, "NAS PORT TYPE EIA530"},
+ {47, "NAS PORT TYPE T1"},
+ {48, "NAS PORT TYPE CHAN T3"},
+ {49, "NAS PORT TYPE DS1 FR"},
+ {50, "NAS PORT TYPE E3 ATM"},
+ {51, "NAS PORT TYPE IMA ATM"},
+ {52, "NAS PORT TYPE DS3 ATM 2"},
+ {53, "NAS PORT TYPE OC3 ATM 2"},
+ {54, "NAS PORT TYPE 1000BSX"},
+ {55, "NAS PORT TYPE E1 FR"},
+ {56, "NAS PORT TYPE E1 ATM"},
+ {57, "NAS PORT TYPE E3 FR"},
+ {58, "NAS PORT TYPE OC3 POS"},
+ {59, "NAS PORT TYPE OC12 POS"},
+ {60, "NAS PORT TYPE PPPOE"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_redback_attrib[] =
+{
+ {1, RADIUS_IP_ADDRESS, "Client DNS Pri", NULL},
+ {2, RADIUS_IP_ADDRESS, "Client DNS Sec", NULL},
+ {3, RADIUS_INTEGER4, "DHCP Max Leases", NULL},
+ {4, RADIUS_STRING, "Context Name", NULL},
+ {5, RADIUS_STRING, "Bridge Group", NULL},
+ {6, RADIUS_STRING, "BG Aging Time", NULL},
+ {7, RADIUS_STRING, "BG Path Cost", NULL},
+ {8, RADIUS_STRING, "BG Span Dis", NULL},
+ {9, RADIUS_STRING, "BG Trans BPDU", NULL},
+ {10, RADIUS_INTEGER4, "Rate Limit Rate", NULL},
+ {11, RADIUS_INTEGER4, "Rate Limit Burst", NULL},
+ {12, RADIUS_INTEGER4, "Police Rate", NULL},
+ {13, RADIUS_INTEGER4, "Police Burst", NULL},
+ {14, RADIUS_INTEGER4, "Source Validation", NULL},
+ {15, RADIUS_INTEGER4, "Tunnel Domain", NULL},
+ {16, RADIUS_STRING, "Tunnel Local Name", NULL},
+ {17, RADIUS_STRING, "Tunnel Remote Name", NULL},
+ {18, RADIUS_INTEGER4, "Tunnel Function", radius_vendor_redback_tunnel_function_vals},
+ {21, RADIUS_INTEGER4, "Tunnel Max Sessions", NULL},
+ {22, RADIUS_INTEGER4, "Tunnel Max Tunnels", NULL},
+ {23, RADIUS_INTEGER4, "Tunnel Session Auth", NULL},
+ {24, RADIUS_INTEGER4, "Tunnel Window", NULL},
+ {25, RADIUS_INTEGER4, "Tunnel Retransmit", NULL},
+ {26, RADIUS_INTEGER4, "Tunnel Cmd Timeout", NULL},
+ {27, RADIUS_STRING, "PPPOE URL", NULL},
+ {28, RADIUS_STRING, "PPPOE MOTM", NULL},
+ {29, RADIUS_INTEGER4, "Tunnel Group", NULL},
+ {30, RADIUS_STRING, "Tunnel Context", NULL},
+ {31, RADIUS_INTEGER4, "Tunnel Algorithm", NULL},
+ {32, RADIUS_INTEGER4, "Tunnel Deadtime", NULL},
+ {33, RADIUS_INTEGER4, "Mcast Send", radius_vendor_redback_mcast_send_vals},
+ {34, RADIUS_INTEGER4, "Mcast Receive", radius_vendor_redback_mcast_receive_vals},
+ {35, RADIUS_INTEGER4, "Mcast MaxGroups", NULL},
+ {36, RADIUS_STRING, "Ip Address Pool Name", NULL},
+ {37, RADIUS_INTEGER4, "Tunnel DNIS", radius_vendor_redback_tunnel_dnis_vals},
+ {38, RADIUS_INTEGER4, "Medium Type", NULL},
+ {39, RADIUS_INTEGER4, "PVC Encapsulation Type", radius_vendor_redback_pvc_encapsulation_type_vals},
+ {40, RADIUS_STRING, "PVC Profile Name", NULL},
+ {41, RADIUS_INTEGER4, "PVC Circuit Padding", radius_vendor_redback_pvc_circuit_padding_vals},
+ {42, RADIUS_INTEGER4, "Bind Type", radius_vendor_redback_bind_type_vals},
+ {43, RADIUS_INTEGER4, "Bind Auth Protocol", radius_vendor_redback_bind_auth_protocol_vals},
+ {44, RADIUS_INTEGER4, "Bind Auth Max Sessions", NULL},
+ {45, RADIUS_STRING, "Bind Bypass Bypass", NULL},
+ {46, RADIUS_STRING, "Bind Auth Context", NULL},
+ {47, RADIUS_STRING, "Bind Auth Service Grp", NULL},
+ {48, RADIUS_STRING, "Bind Bypass Context", NULL},
+ {49, RADIUS_STRING, "Bind Int Context", NULL},
+ {50, RADIUS_STRING, "Bind Tun Context", NULL},
+ {51, RADIUS_STRING, "Bind Ses Context", NULL},
+ {52, RADIUS_INTEGER4, "Bind Dot1q Slot", NULL},
+ {53, RADIUS_INTEGER4, "Bind Dot1q Port", NULL},
+ {54, RADIUS_INTEGER4, "Bind Dot1q Vlan Tag Id", NULL},
+ {55, RADIUS_STRING, "Bind Int Interface Name", NULL},
+ {56, RADIUS_STRING, "Bind L2TP Tunnel Name", NULL},
+ {57, RADIUS_INTEGER4, "Bind L2TP Flow Control", NULL},
+ {58, RADIUS_STRING, "Bind Sub User At Context", NULL},
+ {59, RADIUS_STRING, "Bind Sub Password", NULL},
+ {60, RADIUS_STRING, "Ip Host Addr", NULL},
+ {61, RADIUS_INTEGER4, "IP TOS Field", NULL},
+ {62, RADIUS_INTEGER4, "NAS Real Port", NULL},
+ {63, RADIUS_STRING, "Tunnel Session Auth Ctx", NULL},
+ {64, RADIUS_STRING, "Tunnel Session Auth Service Grp", NULL},
+ {65, RADIUS_INTEGER4, "Tunnel Rate Limit Rate", NULL},
+ {66, RADIUS_INTEGER4, "Tunnel Rate Limit Burst", NULL},
+ {67, RADIUS_INTEGER4, "Tunnel Police Rate", NULL},
+ {68, RADIUS_INTEGER4, "Tunnel Police Burst", NULL},
+ {69, RADIUS_STRING, "Tunnel L2F Second Password", NULL},
+ {128, RADIUS_INTEGER4, "Acct Input Octets 64", NULL},
+ {129, RADIUS_INTEGER4, "Acct Output Octets 64", NULL},
+ {130, RADIUS_INTEGER4, "Acct Input Packets 64", NULL},
+ {131, RADIUS_INTEGER4, "Acct Output Packets 64", NULL},
+ {132, RADIUS_IP_ADDRESS, "Assigned IP Address", NULL},
+ {133, RADIUS_INTEGER4, "Acct Mcast In Octets", NULL},
+ {134, RADIUS_INTEGER4, "Acct Mcast Out Octets", NULL},
+ {135, RADIUS_INTEGER4, "Acct Mcast In Packets", NULL},
+ {136, RADIUS_INTEGER4, "Acct Mcast Out Packets", NULL},
+ {137, RADIUS_INTEGER4, "LAC Port", NULL},
+ {138, RADIUS_INTEGER4, "LAC Real Port", NULL},
+ {139, RADIUS_INTEGER4, "LAC Port Type", radius_vendor_redback_lac_port_type_vals},
+ {140, RADIUS_INTEGER4, "LAC Real Port Type", radius_vendor_redback_lac_real_port_type_vals},
+ {141, RADIUS_STRING, "Acct Dyn Ac Ent", NULL},
+ {142, RADIUS_INTEGER4, "Session Error Code", NULL},
+ {143, RADIUS_STRING, "Session Error Msg", NULL},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ http://www.juniper.net/techpubs/software/junos/junos62/swconfig62-system-basics/frameset.htm
+*/
+static const radius_attr_info radius_vendor_juniper_attrib[] =
+{
+ {1, RADIUS_STRING, "Juniper Local User Name", NULL},
+ {2, RADIUS_STRING, "Juniper Allow Commands", NULL},
+ {3, RADIUS_STRING, "Juniper Deny Commands", NULL},
+ {4, RADIUS_STRING, "Juniper Allow Configuration", NULL},
+ {5, RADIUS_STRING, "Juniper Deny Configuration", NULL},
+ {0, 0, NULL, NULL}
+};
+
+/*
+reference:
+ 'dictionary.aptis' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.aptis
+*/
+static const radius_attr_info radius_vendor_aptis_attrib[] =
+{
+ {1, RADIUS_STRING, "CVX Identification", NULL},
+ {2, RADIUS_INTEGER4, "CVX VPOP ID", NULL},
+ {3, RADIUS_INTEGER4, "CVX SS7 Session ID Type", NULL},
+ {4, RADIUS_INTEGER4, "CVX Radius Redirect", NULL},
+ {5, RADIUS_INTEGER4, "CVX IPSVC AZNLVL", NULL},
+ {6, RADIUS_INTEGER4, "CVX IPSVC Mask", NULL},
+ {7, RADIUS_INTEGER4, "CVX Multilink Match Info", NULL},
+ {8, RADIUS_INTEGER4, "CVX Multilink Group Number", NULL},
+ {9, RADIUS_INTEGER4, "CVX PPP Log Mask", NULL},
+ {10, RADIUS_STRING, "CVX Modem Begin Modulation", NULL},
+ {11, RADIUS_STRING, "CVX Modem End Modulation", NULL},
+ {12, RADIUS_STRING, "CVX Modem Error Correction", NULL},
+ {13, RADIUS_STRING, "CVX Modem Data Compression", NULL},
+ {14, RADIUS_INTEGER4, "CVX Modem Tx Packets", NULL},
+ {15, RADIUS_INTEGER4, "CVX Modem ReTx Packets", NULL},
+ {16, RADIUS_INTEGER4, "CVX Modem SNR", NULL},
+ {17, RADIUS_INTEGER4, "CVX Modem Local Retrains", NULL},
+ {18, RADIUS_INTEGER4, "CVX Modem Remote Retrains", NULL},
+ {19, RADIUS_INTEGER4, "CVX Modem Local Rate Negs", NULL},
+ {20, RADIUS_INTEGER4, "CVX Modem Remote Rate Negs", NULL},
+ {21, RADIUS_INTEGER4, "CVX Modem Begin Recv Line Lvl", NULL},
+ {22, RADIUS_INTEGER4, "CVX Modem End Recv Line Lvl", NULL},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ Dictonary of Cisco ACS 3.1
+ http://www.cisco.com/en/US/products/sw/secursw/ps2086/products_user_guide_chapter09186a0080102172.html#984410
+*/
+
+
+static const value_string radius_vendor_cisco_vpn3000_sep_card_assignment_vals[] =
+{
+ {1, "SEP 1"},
+ {2, "SEP 2"},
+ {3, "SEP 1 + SEP 2"},
+ {4, "SEP 3"},
+ {5, "SEP 1 + SEP 3"},
+ {6, "SEP 2 + SEP 3"},
+ {7, "SEP 1 + SEP 2 + SEP 3"},
+ {8, "SEP 4"},
+ {9, "SEP 1 + SEP 4"},
+ {10, "SEP 2 + SEP 4"},
+ {11, "SEP 1 + SEP 2 + SEP 4"},
+ {12, "SEP 3 + SEP 4"},
+ {13, "SEP 1 + SEP 3 + SEP 4"},
+ {14, "SEP 2 + SEP 3 + SEP 4"},
+ {15, "Any SEP"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_tunneling_protocols_vals[] =
+{
+ {1, "PPTP"},
+ {2, "L2TP"},
+ {3, "PPTP and L2TP"},
+ {4, "IPSec"},
+ {5, "PPTP and IPSec"},
+ {6, "L2TP and IPSec"},
+ {7, "PPTP - L2TP - IPSec"},
+ {8, "L2TP/IPSec"},
+ {9, "PPTP and L2TP/IPSec"},
+ {10, "L2TP and L2TP/IPSec"},
+ {11, "PPTP - L2TP - L2TP/IPSec"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ipsec_authentication_vals[] =
+{
+ {0, "None"},
+ {1, "RADIUS"},
+ {3, "NT Domain"},
+ {4, "SDI"},
+ {5, "Internal"},
+ {6, "Radius with Expiry"},
+ {7, "KERBEROS / Active Directory"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_allow_pw_store_vals[] =
+{
+ {0, "False"},
+ {1, "True"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_use_client_address_vals[] =
+{
+ {0, "False"},
+ {1, "True"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_pptp_encryption_vals[] =
+{
+ {1, "Encryption required"},
+ {2, "40 Bits"},
+ {3, "40 Bits - Encryption required"},
+ {4, "128 Bits"},
+ {5, "128 Bits - Encryption required"},
+ {6, "40 or 128 Bits"},
+ {7, "40 or 128 Bits - Encryption required"},
+ {8, "Stateless Required"},
+ {9, "Encryption / Stateless required"},
+ {10, "40 Bits - Stateless required"},
+ {11, "40 Bits Encryption / Stateless required"},
+ {12, "128 Bits - Stateless required"},
+ {13, "128 Bits - Encryption / Stateless required"},
+ {14, "40/128 Bits - Stateless required"},
+ {15, "40/128 Bits - Encryption / Stateless required"},
+ {0, NULL}
+};
+
+
+static const value_string radius_vendor_cisco_vpn3000_l2tp_encryption_vals[] =
+{
+ {1, "Encryption required"},
+ {2, "40 Bits"},
+ {3, "40 Bits - Encryption required"},
+ {4, "128 Bits"},
+ {5, "128 Bits - Encryption required"},
+ {6, "40 or 128 Bits"},
+ {7, "40 or 128 Bits - Encryption required"},
+ {8, "Stateless Required"},
+ {9, "Encryption / Stateless required"},
+ {10, "40 Bits - Stateless required"},
+ {11, "40 Bits Encryption / Stateless required"},
+ {12, "128 Bits - Stateless required"},
+ {13, "128 Bits - Encryption / Stateless required"},
+ {14, "40/128 Bits - Stateless required"},
+ {15, "40/128 Bits - Encryption / Stateless required"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_tunnel_type_vals[] =
+{
+ {1, "LAN-to-LAN"},
+ {2, "Remote Access"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_mode_config_vals[] =
+{
+ {0, "OFF"},
+ {1, "ON"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_user_group_lock_vals[] =
+{
+ {0, "OFF"},
+ {1, "ON"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ipsec_over_udp_vals[] =
+{
+ {0, "OFF"},
+ {1, "ON"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_pptp_mppc_compression_vals[] =
+{
+ {1, "ON"},
+ {2, "OFF"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_l2tp_mppc_compression_vals[] =
+{
+ {0, "ON"},
+ {1, "OFF"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ipsec_ip_compression_vals[] =
+{
+ {0, "None"},
+ {1, "LZS"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ipsec_ike_peer_idcheck_vals[] =
+{
+ {1, "Required"},
+ {2, "If supported by certifiate"},
+ {3, "Do not check"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ike_keep_alives_vals[] =
+{
+ {0, "OFF"},
+ {1, "ON"},
+ {0, NULL}
+};
+
+
+static const value_string radius_vendor_cisco_vpn3000_auth_on_rekey_vals[] =
+{
+ {0, "OFF"},
+ {1, "ON"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_required_client_fw_vendor_code_vals[] =
+{
+ {1, "Cisco Systems (with CIC) "},
+ {2, "Zone Labs"},
+ {3, "Network ICE"},
+ {4, "Sygate"},
+ {5, "Cisco Systems (with CSA) "},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_hw_client_auth_vals[] =
+{
+ {0, "OFF"},
+ {1, "ON"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn_req_user_auth_vals[] =
+{
+ {0, "No"},
+ {1, "Yes"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ip_phone_bypass_vals[] =
+{
+ {0, "No"},
+ {1, "Yes"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ipsec_split_tunneling_policy_vals[] =
+{
+ {0, "Tunnel everything"},
+ {1, "Only tunnel networks in list"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ipsec_required_client_fw_capability_vals[] =
+{
+ {0, "None"},
+ {1, "Policy defined by remote FW AYT"},
+ {2, "Policy pushed CPP"},
+ {4, "Policy from Server"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ipsec_client_fw_filter_optional_vals[] =
+{
+ {0, "Required"},
+ {1, "Optional"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ipsec_backup_servers_vals[] =
+{
+ {1, "User Client-configured list"},
+ {2, "Disable and clear client list"},
+ {3, "Use Backup server list"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_ms_client_intercept_dhcp_configure_message_vals[] =
+{
+ {0, "No"},
+ {1, "Yes"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_allow_network_extension_mode_vals[] =
+{
+ {0, "No"},
+ {1, "Yes"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_webvpn_content_filter_parameters_vals[] =
+{
+ {1, "Java & ActiveX"},
+ {2, "JavaScript"},
+ {3, "Java & ActiveX - JavaScript"},
+ {4, "Images"},
+ {5, "Java & ActiveX - Images"},
+ {6, "JavaScript - Images"},
+ {7, "Java & ActiveX - JavaScript - Images"},
+ {8, "Cookies"},
+ {9, "Cookies - Java & ActiveX"},
+ {10, "Cookies - Javascript"},
+ {11, "Cookies - Java & ActiveX - JavaScript"},
+ {12, "Cookies - Images"},
+ {13, "Cookies - Images - Java &ActiveX"},
+ {14, "Cookies - Images - JavaScript"},
+ {15, "Cookies - Images - Java &ActiveX - JavaScript"},
+ {0, NULL}
+};
+
+static const value_string radius_vendor_cisco_vpn3000_strip_realm_vals[] =
+{
+ {0, "No"},
+ {1, "Yes"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_cisco_vpn3000_attrib[] =
+{
+ {1, RADIUS_STRING, "CVPN3000-Access-Hours", NULL},
+ {2, RADIUS_INTEGER4, "CVPN3000-Simultaneous-Logins", NULL},
+ {5, RADIUS_IP_ADDRESS, "CVPN3000-Primary-DNS", NULL},
+ {6, RADIUS_IP_ADDRESS, "CVPN3000-Secondary-DNS", NULL},
+ {7, RADIUS_IP_ADDRESS, "CVPN3000-Primary-WINS", NULL},
+ {8, RADIUS_IP_ADDRESS, "CVPN3000-Secondary-WINS", NULL},
+ {9, RADIUS_INTEGER4, "CVPN3000-SEP-Card-Assignment", radius_vendor_cisco_vpn3000_sep_card_assignment_vals},
+ {11, RADIUS_INTEGER4, "CVPN3000-Tunneling-Protocols", radius_vendor_cisco_vpn3000_tunneling_protocols_vals},
+ {12, RADIUS_STRING, "CVPN3000-IPSec-Sec-Association", NULL},
+ {13, RADIUS_INTEGER4, "CVPN3000-IPSec-Authentication", radius_vendor_cisco_vpn3000_ipsec_authentication_vals},
+ {15, RADIUS_STRING, "CVPN3000-IPSec-Banner1", NULL},
+ {16, RADIUS_INTEGER4, "CVPN3000-IPSec-Allow-Passwd-Store", radius_vendor_cisco_vpn3000_allow_pw_store_vals},
+ {17, RADIUS_INTEGER4, "CVPN3000-Use-Client-Address", radius_vendor_cisco_vpn3000_use_client_address_vals},
+ {20, RADIUS_INTEGER4, "CVPN3000-PPTP-Encryption", radius_vendor_cisco_vpn3000_pptp_encryption_vals},
+ {21, RADIUS_INTEGER4, "CVPN3000-L2TP-Encryption", radius_vendor_cisco_vpn3000_l2tp_encryption_vals},
+ {27, RADIUS_STRING, "CVPN3000-IPSec-Split-Tunnel-List", NULL},
+ {28, RADIUS_STRING, "CVPN3000-IPSec-Default-Domain", NULL},
+ {29, RADIUS_STRING, "CVPN3000-IPSec-Split-DNS-Names", NULL},
+ {30, RADIUS_INTEGER4, "CVPN3000-IPSec-Tunnel-Type", radius_vendor_cisco_vpn3000_tunnel_type_vals},
+ {31, RADIUS_INTEGER4, "CVPN3000-IPSec-Mode-Config", radius_vendor_cisco_vpn3000_mode_config_vals},
+ {33, RADIUS_INTEGER4, "CVPN3000-IPSec-User-Group-Lock", radius_vendor_cisco_vpn3000_user_group_lock_vals},
+ {34, RADIUS_INTEGER4, "CVPN3000-IPSec-Over-UDP", radius_vendor_cisco_vpn3000_ipsec_over_udp_vals},
+ {35, RADIUS_INTEGER4, "CVPN3000-IPSec-Over-UDP-Port", NULL},
+ {36, RADIUS_STRING, "CVPN3000-IPSec-Banner2", NULL},
+ {37, RADIUS_INTEGER4, "CVPN3000-PPTP-MPPC-Compression", radius_vendor_cisco_vpn3000_pptp_mppc_compression_vals},
+ {38, RADIUS_INTEGER4, "CVPN3000-L2TP-MPPC-Compression", radius_vendor_cisco_vpn3000_l2tp_mppc_compression_vals},
+ {39, RADIUS_INTEGER4, "CVPN3000-IPSec-IP-Compression", radius_vendor_cisco_vpn3000_ipsec_ip_compression_vals},
+ {40, RADIUS_INTEGER4, "CVPN3000-IPSec-IKE-Peer-IDCheck", radius_vendor_cisco_vpn3000_ipsec_ike_peer_idcheck_vals},
+ {41, RADIUS_INTEGER4, "CVPN3000-IKE-Keep-Alives", radius_vendor_cisco_vpn3000_ike_keep_alives_vals},
+ {42, RADIUS_INTEGER4, "CVPN3000-IPSec-Auth-On-Rekey", radius_vendor_cisco_vpn3000_auth_on_rekey_vals},
+ {45, RADIUS_INTEGER4, "CVPN3000-Required-Client-Firewall-Vendor-Code", radius_vendor_cisco_vpn3000_required_client_fw_vendor_code_vals},
+ {46, RADIUS_INTEGER4, "CVPN3000-Required-Client-Firewall-Product-Code", NULL},
+ {47, RADIUS_STRING, "CVPN3000-Required-Client-Firewall-Description", NULL},
+ {48, RADIUS_INTEGER4, "CVPN3000-Require-HW-Client-Auth", radius_vendor_cisco_vpn3000_hw_client_auth_vals},
+ {49, RADIUS_INTEGER4, "CVPN3000-Required-Individual-User-Auth", radius_vendor_cisco_vpn_req_user_auth_vals},
+ {50, RADIUS_INTEGER4, "CVPN3000-Authenticated-User-Idle-Timeout", NULL},
+ {51, RADIUS_INTEGER4, "CVPN3000-Cisco-IP-Phone-Bypass", radius_vendor_cisco_vpn3000_ip_phone_bypass_vals},
+ {52, RADIUS_STRING, "CVPN3000-User-Auth-Server-Name", NULL},
+ {53, RADIUS_INTEGER4, "CVPN3000-User-Auth-Server-Port", NULL},
+ {54, RADIUS_STRING, "CVPN3000-User-Auth-Server-Secret", NULL},
+ {55, RADIUS_INTEGER4, "CVPN3000-IPSec-Split-Tunneling-Policy", radius_vendor_cisco_vpn3000_ipsec_split_tunneling_policy_vals},
+ {56, RADIUS_INTEGER4, "CVPN3000-IPSec-Required-Client-Firewall-Capability", radius_vendor_cisco_vpn3000_ipsec_required_client_fw_capability_vals},
+ {57, RADIUS_STRING, "CVPN3000-IPSec-Client-Firewall-Filter-Name", NULL},
+ {58, RADIUS_INTEGER4, "CVPN3000-IPSec-Client-Firewall-Filter-Optional", radius_vendor_cisco_vpn3000_ipsec_client_fw_filter_optional_vals},
+ {59, RADIUS_INTEGER4, "CVPN3000-IPSec-Backup-Servers", radius_vendor_cisco_vpn3000_ipsec_backup_servers_vals},
+ {60, RADIUS_STRING, "CVPN3000-IPSec-Backup-Server-List", NULL},
+ {62, RADIUS_INTEGER4, "CVPN3000-MS-Client-Intercept-DHCP-Configure-Message", radius_vendor_cisco_vpn3000_ms_client_intercept_dhcp_configure_message_vals},
+ {63, RADIUS_IP_ADDRESS, "CVPN3000-MS-Client-Subnet-Mask", NULL},
+ {64, RADIUS_INTEGER4, "CVPN3000-Allow-Network-Extension-Mode", radius_vendor_cisco_vpn3000_allow_network_extension_mode_vals},
+ {68, RADIUS_INTEGER4, "CVPN3000-Confidence-Interval", NULL},
+ {69, RADIUS_INTEGER4, "CVPN3000-WebVPN-Content-Filter-Parameters", radius_vendor_cisco_vpn3000_webvpn_content_filter_parameters_vals},
+ {70, RADIUS_INTEGER4, "CVPN3000-WebVPN-Enable-functions", NULL},
+ {74, RADIUS_STRING, "CVPN3000-WebVPN-Exchange-Server-Address", NULL},
+ {75, RADIUS_INTEGER4, "CVPN3000-Cisco-LEAP-Bypass", NULL},
+ {77, RADIUS_STRING, "CVPN3000-Client-Type-Version-Limiting", NULL},
+ {78, RADIUS_STRING, "CVPN3000-WebVPN-ExchangeServer-NETBIOS-Name", NULL},
+ {79, RADIUS_STRING, "CVPN3000-Port-Forwarding-Name", NULL},
+ {135, RADIUS_INTEGER4, "CVPN3000-Strip-Realm", radius_vendor_cisco_vpn3000_strip_realm_vals},
+ {0, 0, NULL, NULL}
+};
+
+static const radius_attr_info radius_vendor_cosine_attrib[] =
+{
+ {1, RADIUS_STRING, "Connection Profile Name", NULL},
+ {2, RADIUS_STRING, "Enterprise ID", NULL},
+ {3, RADIUS_STRING, "Address Pool Name", NULL},
+ {4, RADIUS_INTEGER4, "DS Byte", NULL},
+ {5, COSINE_VPI_VCI, "VPI/VCI", NULL},
+ {6, RADIUS_INTEGER4, "DLCI", NULL},
+ {7, RADIUS_IP_ADDRESS, "LNS IP Address", NULL},
+ {8, RADIUS_STRING, "CLI User Permission ID", NULL},
+ {0, 0, NULL, NULL}
+};
+
+/*
+reference:
+ 'dictionary.shasta' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.shasta
+*/
+static const value_string radius_vendor_shasta_user_privilege_vals[] =
+{
+ {1, "User"},
+ {2, "Super User"},
+ {3, "SSuper User"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_shasta_attrib[] =
+{
+ {1, RADIUS_INTEGER4, "Shasta User Privilege", radius_vendor_shasta_user_privilege_vals},
+ {2, RADIUS_STRING, "Shasta Service Profile", NULL},
+ {3, RADIUS_STRING, "Shasta VPN Name", NULL},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ 'dictionary.nomadix' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.nomadix
+*/
+static const radius_attr_info radius_vendor_nomadix_attrib[] =
+{
+ {1, RADIUS_INTEGER4, "Nomadix Bw Up", NULL},
+ {2, RADIUS_INTEGER4, "Nomadix Bw Down", NULL},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ 'unisphere5-2.dct' file from Juniper Networks
+ http://www.juniper.net/techpubs/software/erx/junose52/unisphere5-2.dct
+*/
+
+static const value_string radius_vendor_unisphere_ingress_statistics_vals[] =
+{
+ {0, "Disable"},
+ {1, "Enable"}
+};
+
+static const value_string radius_vendor_unisphere_egress_statistics_vals[] =
+{
+ {0, "Disable"},
+ {1, "Enable"}
+};
+
+static const value_string radius_vendor_unisphere_atm_service_category_vals[] =
+{
+ {1, "UBR"},
+ {2, "UBRPCR"},
+ {3, "nrtVBR"},
+ {4, "CBR"},
+ {0, "NULL"}
+};
+
+static const value_string radius_vendor_unisphere_cli_allow_all_vr_access_vals[] =
+{
+ {0, "Disable"},
+ {1, "Enable"},
+};
+
+static const value_string radius_vendor_unisphere_sa_validate_vals[] =
+{
+ {0, "Disable"},
+ {1, "Enable"},
+};
+
+static const value_string radius_vendor_unisphere_igmp_enable_vals[] =
+{
+ {0, "Disable"},
+ {1, "Enable"},
+};
+
+static const value_string radius_vendor_unisphere_ppp_protocol_vals[] =
+{
+ {0, "none"},
+ {1, "pap"},
+ {2, "chap"},
+ {3, "pap-chap"},
+ {4, "chap-pap"}
+};
+
+static const value_string radius_vendor_unisphere_tunnel_bearer_type_vals[] =
+{
+ {0, "none"},
+ {1, "analog"},
+ {2, "digital"},
+};
+
+
+static const radius_attr_info radius_vendor_unisphere_attrib[] =
+{
+ {1, RADIUS_STRING, "ERX Virtual Router Name", NULL},
+ {2, RADIUS_STRING, "ERX Address Pool Name", NULL},
+ {3, RADIUS_STRING, "ERX Local Loopback Interface", NULL},
+ {4, RADIUS_IP_ADDRESS, "ERX Primary Dns", NULL},
+ {5, RADIUS_IP_ADDRESS, "ERX Primary Wins", NULL},
+ {6, RADIUS_IP_ADDRESS, "ERX Secondary Dns", NULL},
+ {7, RADIUS_IP_ADDRESS, "ERX Secondary Wins", NULL},
+ {8, RADIUS_STRING, "ERX Tunnel Virtual Router", NULL},
+ {9, RADIUS_STRING, "ERX Tunnel Password", NULL},
+ {10, RADIUS_STRING, "ERX Ingress Policy Name", NULL},
+ {11, RADIUS_STRING, "ERX Egress Policy Name", NULL},
+ {12, RADIUS_STRING, "ERX Ingress Statistics", radius_vendor_unisphere_ingress_statistics_vals},
+ {13, RADIUS_STRING, "ERX Egress Statistics", radius_vendor_unisphere_egress_statistics_vals},
+ {14, RADIUS_STRING, "ERX Atm Service Category", radius_vendor_unisphere_atm_service_category_vals},
+ {15, RADIUS_STRING, "ERX Atm PCR", NULL},
+ {16, RADIUS_STRING, "ERX Atm SCR", NULL},
+ {17, RADIUS_STRING, "ERX Atm MBS", NULL},
+ {18, RADIUS_STRING, "ERX Cli Initial Access Level", NULL},
+ {19, RADIUS_INTEGER4, "ERX Cli Allow All VR Access", radius_vendor_unisphere_cli_allow_all_vr_access_vals},
+ {20, RADIUS_STRING, "ERX Alternate Cli Access Level", NULL},
+ {21, RADIUS_STRING, "ERX Alternate Cli Vrouter Name", NULL},
+ {22, RADIUS_INTEGER4, "ERX Sa Validate", radius_vendor_unisphere_sa_validate_vals},
+ {23, RADIUS_INTEGER4, "ERX Igmp Enable", radius_vendor_unisphere_igmp_enable_vals},
+ {24, RADIUS_STRING, "ERX PPPoE Description", NULL},
+ {25, RADIUS_STRING, "ERX Redirect Virtual Router Name", NULL},
+ {26, RADIUS_STRING, "ERX Qos Profile Name", NULL},
+ /* 27 Unused */
+ {28, RADIUS_STRING, "ERX PPPoE URL", NULL},
+ /* 29,30 Unused */
+ {31, RADIUS_STRING, "ERX Service Bundle", NULL},
+ /* 32 Unused */
+ {33, RADIUS_INTEGER4, "ERX Tunnel Max Sessions", NULL},
+ {34, RADIUS_INTEGER4, "ERX Framed IP Route Tag", NULL},
+ {35, RADIUS_STRING, "ERX Tunnel Dialout Number", NULL},
+ {36, RADIUS_STRING, "ERX PPP Username", NULL},
+ {37, RADIUS_STRING, "ERX PPP Password", NULL},
+ {38, RADIUS_INTEGER4, "ERX PPP Protocol", radius_vendor_unisphere_ppp_protocol_vals},
+ {39, RADIUS_INTEGER4, "ERX Tunnel Min Bps", NULL},
+ {40, RADIUS_INTEGER4, "ERX Tunnel Max Bps", NULL},
+ {41, RADIUS_INTEGER4, "ERX Tunnel Bearer Type", radius_vendor_unisphere_tunnel_bearer_type_vals},
+ {42, RADIUS_INTEGER4, "ERX Input Gigapackets", NULL},
+ {43, RADIUS_INTEGER4, "ERX Output Gigapackets", NULL},
+ {44, RADIUS_STRING, "ERX Tunnel Interface Id", NULL},
+ {45, RADIUS_STRING, "ERX IPV6 Virtual Router", NULL},
+ {46, RADIUS_STRING, "ERX IPV6 Local Interface", NULL},
+ {47, RADIUS_IP6_ADDRESS, "ERX IPV6 Primary Dns", NULL},
+ {48, RADIUS_IP6_ADDRESS, "ERX IPV6 Secondary Dns", NULL},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ Cisco ACS 3.2 User Guide - Appendix D
+ http://www.cisco.com/univercd/cc/td/doc/product/access/acs_soft/csacs4nt/acs32/user02/ad.htm#wp473531
+*/
+
+static const radius_attr_info radius_vendor_cisco_bbsm_attrib[] =
+{
+ {1, RADIUS_INTEGER4, "CBBSM-Bandwidth", NULL},
+ {0, 0, NULL, NULL},
+};
+
+static const radius_attr_info radius_vendor_issanni_attrib[] =
+{
+ {1, RADIUS_STRING, "Softflow Template", NULL},
+ {2, RADIUS_STRING, "NAT Pool", NULL},
+ {3, RADIUS_STRING, "Virtual Routing Domain", NULL},
+ {4, RADIUS_STRING, "Tunnel Name", NULL},
+ {5, RADIUS_STRING, "IP Pool Name", NULL},
+ {6, RADIUS_STRING, "PPPoE URL", NULL},
+ {7, RADIUS_STRING, "PPPoE MOTM", NULL},
+ {8, RADIUS_STRING, "PPPoE Service", NULL},
+ {9, RADIUS_IP_ADDRESS, "Primary DNS", NULL},
+ {10, RADIUS_IP_ADDRESS, "Secondary DNS", NULL},
+ {11, RADIUS_IP_ADDRESS, "Primary NBNS", NULL},
+ {12, RADIUS_IP_ADDRESS, "Secondary NBNS", NULL},
+ {13, RADIUS_STRING, "Policing Traffic Class", NULL},
+ {14, RADIUS_INTEGER4, "Tunnel Type", NULL},
+ {15, RADIUS_INTEGER4, "NAT Type", NULL},
+ {16, RADIUS_STRING, "QoS Traffic Class", NULL},
+ {17, RADIUS_STRING, "Interface Name", NULL},
+ {0, 0, NULL, NULL}
+};
+
+/*
+reference:
+ 'dictionary.quintum' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.quintum
+*/
+static const radius_attr_info radius_vendor_quintum_attrib[] =
+{
+ {1, RADIUS_STRING, "Quintum AVPair", NULL},
+ {2, RADIUS_STRING, "Quintum NAS Port", NULL},
+ {23, RADIUS_STRING, "Quintum h323 remote address", NULL},
+ {24, RADIUS_STRING, "Quintum h323 conf id", NULL},
+ {25, RADIUS_STRING, "Quintum h323 setup time", NULL},
+ {26, RADIUS_STRING, "Quintum h323 call origin", NULL},
+ {27, RADIUS_STRING, "Quintum h323 call type", NULL},
+ {28, RADIUS_STRING, "Quintum h323 connect time", NULL},
+ {29, RADIUS_STRING, "Quintum h323 disconnect time", NULL},
+ {30, RADIUS_STRING, "Quintum h323 disconnect cause", NULL},
+ {31, RADIUS_STRING, "Quintum h323 voice quality", NULL},
+ {33, RADIUS_STRING, "Quintum h323 gw id", NULL},
+ {35, RADIUS_STRING, "Quintum h323 incoming conf id", NULL},
+ {101, RADIUS_STRING, "Quintum h323 credit amount", NULL},
+ {102, RADIUS_STRING, "Quintum h323 credit time", NULL},
+ {103, RADIUS_STRING, "Quintum h323 return code", NULL},
+ {104, RADIUS_STRING, "Quintum h323 prompt id", NULL},
+ {105, RADIUS_STRING, "Quintum h323 time and day", NULL},
+ {106, RADIUS_STRING, "Quintum h323 redirect number", NULL},
+ {107, RADIUS_STRING, "Quintum h323 preferred lang", NULL},
+ {108, RADIUS_STRING, "Quintum h323 redirect ip address", NULL},
+ {109, RADIUS_STRING, "Quintum h323 billing model", NULL},
+ {110, RADIUS_STRING, "Quintum h323 currency type", NULL},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ http://download.colubris.com/library/product_doc/CN3500_AdminGuide.pdf
+*/
+static const radius_attr_info radius_vendor_colubris_attrib[] =
+{
+ {0, RADIUS_STRING, "Colubris AV Pair", NULL},
+ {0, 0, NULL, NULL},
+};
+
+/*
+reference:
+ 'dictionary.columbia_university' file from FreeRADIUS
+ http://www.freeradius.org/radiusd/raddb/dictionary.columbia_university
+*/
+static const value_string radius_vendor_columbia_university_sip_method_vals[] =
+{
+ {0, "INVITE"},
+ {1, "BYE"},
+ {2, "REGISTER"},
+ {3, "OTHER"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_columbia_university_attrib[] =
+{
+ {0, RADIUS_INTEGER4, "SIP Method", radius_vendor_columbia_university_sip_method_vals},
+ {1, RADIUS_STRING, "SIP From", NULL},
+ {2, RADIUS_STRING, "SIP To", NULL},
+ {4, RADIUS_STRING, "SIP Translated Request URI", NULL},
+ {0, 0, NULL, NULL},
+};
+
+static const value_string the3gpp_pdp_type_vals[] = {
+ {0, "IP"},
+ {1, "PPP"},
+ {2, "IPv6"},
+ {0, NULL}
+};
+
+static const radius_attr_info radius_vendor_3gpp_attrib[] =
+{
+ /* According to 3GPP TS 29.061 V4.8.0 (2003-06) */
+ {1, THE3GPP_IMSI, "IMSI", NULL},
+ {2, RADIUS_INTEGER4, "Charging ID", NULL},
+ {3, RADIUS_INTEGER4, "PDP Type", the3gpp_pdp_type_vals},
+ {4, RADIUS_IP_ADDRESS, "Charging Gateway Address", NULL},
+ {5, THE3GPP_QOS, "QoS Profile", NULL},
+ {6, RADIUS_IP_ADDRESS, "SGSN Address", NULL},
+ {7, RADIUS_IP_ADDRESS, "GGSN Address", NULL},
+ {8, THE3GPP_IMSI_MCC_MNC, "IMSI MCC-MNC", NULL},
+ {9, THE3GPP_GGSN_MCC_MNC, "GGSN MCC-MNC", NULL},
+ {10, THE3GPP_NSAPI, "NSAPI", NULL},
+ {11, THE3GPP_SESSION_STOP_INDICATOR, "Session Stop Indicator", NULL},
+ {12, THE3GPP_SELECTION_MODE, "Selection Mode", NULL},
+ {13, THE3GPP_CHARGING_CHARACTERISTICS, "Charging Characteristics", NULL},
+ {14, RADIUS_IP6_ADDRESS, "Charging Gateway IPv6 Address", NULL},
+ {15, RADIUS_IP6_ADDRESS, "SGSN IPv6 Address", NULL},
+ {16, RADIUS_IP6_ADDRESS, "GGSN IPv6 Address", NULL},
+ {17, THE3GPP_IPV6_DNS_SERVERS, "IPv6 DNS Servers", NULL},
+ {18, THE3GPP_SGSN_MCC_MNC, "SGSN MCC-MNC", NULL},
+ {0, 0, NULL, NULL},
+};
+
+static rd_vsa_table radius_vsa_table[] =
+{
+ {VENDOR_ACC, radius_vendor_acc_attrib},
+ {VENDOR_CISCO, radius_vendor_cisco_attrib},
+ {VENDOR_SHIVA, radius_vendor_shiva_attrib},
+ {VENDOR_CISCO_VPN5000, radius_vendor_cisco_vpn5000_attrib},
+ {VENDOR_LIVINGSTON, radius_vendor_livingston_attrib},
+ {VENDOR_MICROSOFT, radius_vendor_microsoft_attrib},
+ {VENDOR_ASCEND, radius_vendor_ascend_attrib},
+ {VENDOR_BAY, radius_vendor_bay_attrib},
+ {VENDOR_FOUNDRY, radius_vendor_foundry_attrib},
+ {VENDOR_VERSANET, radius_vendor_versanet_attrib},
+ {VENDOR_REDBACK, radius_vendor_redback_attrib},
+ {VENDOR_JUNIPER, radius_vendor_juniper_attrib},
+ {VENDOR_CISCO_VPN3000, radius_vendor_cisco_vpn3000_attrib},
+ {VENDOR_APTIS, radius_vendor_aptis_attrib},
+ {VENDOR_COSINE, radius_vendor_cosine_attrib},
+ {VENDOR_SHASTA, radius_vendor_shasta_attrib},
+ {VENDOR_NOMADIX, radius_vendor_nomadix_attrib},
+ {VENDOR_UNISPHERE, radius_vendor_unisphere_attrib},
+ {VENDOR_CISCO_BBSM, radius_vendor_cisco_bbsm_attrib},
+ {VENDOR_ISSANNI, radius_vendor_issanni_attrib},
+ {VENDOR_QUINTUM, radius_vendor_quintum_attrib},
+ {VENDOR_COLUBRIS, radius_vendor_colubris_attrib},
+ {VENDOR_COLUMBIA_UNIVERSITY, radius_vendor_columbia_university_attrib},
+ {VENDOR_THE3GPP, radius_vendor_3gpp_attrib},
+ {0, NULL},
+};
+
+static const radius_attr_info *get_attr_info_table(guint32 vendor)
+{
+ guint32 i;
+
+ for (i = 0; radius_vsa_table[i].vendor; i++)
+ if (radius_vsa_table[i].vendor == vendor)
+ return(radius_vsa_table[i].attrib);
+
+ return(NULL);
+}
+
+static const radius_attr_info *
+find_radius_attr_info(guint32 attr_type, const radius_attr_info *table)
+{
+ guint32 i;
+
+ for (i = 0; table[i].str; i++)
+ if (table[i].attr_type == attr_type)
+ return(&table[i]);
+
+ return(NULL);
+}
+
+static void
+rdconvertbufftostr(gchar *dest, tvbuff_t *tvb, int offset, int length)
+{
+/*converts the raw buffer into printable text */
+ guint32 i;
+ guint32 totlen=0;
+ const guint8 *pd = tvb_get_ptr(tvb, offset, length);
+
+ dest[0]='"';
+ dest[1]=0;
+ totlen=1;
+ for (i=0; i < (guint32)length; i++)
+ {
+ if( isprint((int)pd[i])) {
+ dest[totlen]=(gchar)pd[i];
+ totlen++;
+ }
+ else
+ {
+ sprintf(&(dest[totlen]), "\\%03o", pd[i]);
+ totlen=totlen+strlen(&(dest[totlen]));
+ }
+ }
+ dest[totlen]='"';
+ dest[totlen+1]=0;
+}
+
+static void
+rdconvertbufftobinstr(gchar *dest, tvbuff_t *tvb, int offset, int length)
+{
+/*converts the raw buffer into printable hex display */
+ guint32 i;
+ guint32 totlen=0;
+ const guint8 *pd = tvb_get_ptr(tvb, offset, length);
+ static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ for (i=0; i < (guint32)length; i++)
+ {
+ dest[totlen] = hex[pd[i] >> 4];
+ totlen++;
+ dest[totlen] = hex[pd[i] & 0xF];
+ totlen++;
+ }
+ dest[totlen]='\0';
+}
+
+static void
+rddecryptpass(gchar *dest,tvbuff_t *tvb,int offset,int length)
+{
+ md5_state_t md_ctx;
+ md5_byte_t digest[16];
+ guint32 i;
+ guint32 totlen;
+ const guint8 *pd;
+ guchar c;
+
+ if (shared_secret[0] == '\0' || !authenticator ) {
+ rdconvertbufftobinstr(dest,tvb,offset,length);
+ return;
+ }
+
+ dest[0] = '"';
+ dest[1] = '\0';
+ totlen = 1;
+
+ md5_init(&md_ctx);
+ md5_append(&md_ctx,shared_secret,strlen(shared_secret));
+ md5_append(&md_ctx,authenticator,16);
+ md5_finish(&md_ctx,digest);
+
+ pd = tvb_get_ptr(tvb,offset,length);
+ for( i = 0 ; i < 16 && i < (guint32)length ; i++ ) {
+ c = pd[i] ^ digest[i];
+ if ( isprint(c)) {
+ dest[totlen] = c;
+ totlen++;
+ } else {
+ sprintf(&(dest[totlen]),"\\%03o",c);
+ totlen += strlen(&(dest[totlen]));
+ }
+ }
+ while(i<(guint32)length) {
+ if ( isprint(pd[i]) ) {
+ dest[totlen] = (gchar)pd[i];
+ totlen++;
+ } else {
+ sprintf(&(dest[totlen]), "\\%03o", pd[i]);
+ totlen=totlen+strlen(&(dest[totlen]));
+ }
+ i++;
+ }
+ dest[totlen]='"';
+ dest[totlen+1] = '\0';
+}
+
+static gchar *rd_match_strval(guint32 val, const value_string *vs) {
+ return val_to_str(val, vs, "Undefined");
+}
+
+/* NOTE: This function's signature has been changed with the addition of the
+ * tree parameter at the end.
+ *
+ * The function behaves EXACTLY AS BEFORE for parameters which do not
+ * imply THE3GPP_QOS; I had to change the signature because the function
+ * decode_qos_umts() wants to write on the protocol tree :)
+ *
+ * If you think it is better to DUPLICATE the code copying decode_qos_umts
+ * here, and adapting it, feel free; only keep in mind that changes will have
+ * to be doubled if any bug is found.
+ *
+ * At last, forgive me if I've messed up some indentation...
+ * */
+static void rd_value_to_str(gchar *dest, rd_vsa_buffer (*vsabuffer)[VSABUFFER],
+ const e_avphdr *avph, tvbuff_t *tvb,
+ int offset, const radius_attr_info *attr_info,
+ proto_tree *tree)
+{
+ /* Variable to peek which will be the next print_type for VENDOR-SPECIFIC
+ * RADIUS attributes
+ * */
+ const radius_attr_info *next_attr_info;
+
+ /* Temporary variable to perform some trick on the cont variable; again, this
+ * is needed only when THE3GPP_QOS in involved.
+ * */
+ gchar *tmp_punt;
+
+ gchar *cont;
+ guint32 intval;
+ gint32 timeval;
+ const guint8 *pd;
+ guint8 tag;
+ guint8 ipv6_prefix_length;
+ guint8 ipv6_addr_temp[16];
+
+ int vsa_length;
+ int vsa_len;
+ int vsa_index;
+ const radius_attr_info *vsa_attr_info_table;
+ const e_avphdr *vsa_avph;
+
+ /* Default begin */
+ strcpy(dest, "Value:");
+ cont=&dest[strlen(dest)];
+ if(attr_info == NULL) {
+ strcpy(cont,"Unknown Value Type");
+ return;
+ }
+ switch(attr_info->value_type)
+ {
+ case( RADIUS_STRING ):
+ rdconvertbufftostr(cont,tvb,offset+2,avph->avp_length-2);
+ break;
+
+ case( RADIUS_BINSTRING ):
+ rdconvertbufftobinstr(cont,tvb,offset+2,avph->avp_length-2);
+ break;
+
+ case( RADIUS_USERPASSWORD ):
+ rddecryptpass(cont,tvb,offset+2,avph->avp_length-2);
+ break;
+
+ case( RADIUS_INTEGER4 ):
+ intval = tvb_get_ntohl(tvb,offset+2);
+ if (attr_info->vs != NULL)
+ sprintf(cont, "%s(%u)", rd_match_strval(intval, attr_info->vs), intval);
+ else
+ sprintf(cont,"%u", intval);
+ break;
+
+ case( RADIUS_IP_ADDRESS ):
+ ip_to_str_buf(tvb_get_ptr(tvb,offset+2,4),cont);
+ break;
+
+ case( RADIUS_IP6_ADDRESS ):
+ ip6_to_str_buf((const struct e_in6_addr *)tvb_get_ptr(tvb,offset+2,16),cont);
+ break;
+
+ case( RADIUS_IP6_PREFIX ):
+ ipv6_prefix_length = tvb_get_guint8(tvb,offset+3);
+ memset(ipv6_addr_temp, 0, 16);
+ if (ipv6_prefix_length > 16) ipv6_prefix_length = 16;
+ tvb_memcpy(tvb, ipv6_addr_temp, offset+4, ipv6_prefix_length);
+ ip6_to_str_buf((const struct e_in6_addr *)ipv6_addr_temp, cont);
+ break;
+
+ case( RADIUS_IP6_INTF_ID ):
+ ipv6_prefix_length = tvb_get_guint8(tvb,offset+1);
+ memset(ipv6_addr_temp, 0, 16);
+ if (ipv6_prefix_length > 16) ipv6_prefix_length = 16;
+ tvb_memcpy(tvb, ipv6_addr_temp, offset+2, ipv6_prefix_length);
+ ip6_to_str_buf((const struct e_in6_addr *)ipv6_addr_temp, cont);
+ break;
+
+ case( RADIUS_IPX_ADDRESS ):
+ pd = tvb_get_ptr(tvb,offset+2,4);
+ sprintf(cont,"%u:%u:%u:%u",pd[0],pd[1],pd[2],pd[3]);
+ break;
+
+ case( RADIUS_STRING_TAGGED ):
+ /* Tagged ? */
+ tag = tvb_get_guint8(tvb,offset+2);
+ if (tag > 0 && tag <= 0x1f) {
+ sprintf(dest, "Tag:%u, Value:",
+ tag);
+ cont=&cont[strlen(cont)];
+ rdconvertbufftostr(cont,tvb,offset+3,avph->avp_length-3);
+ break;
+ }
+ rdconvertbufftostr(cont,tvb,offset+2,avph->avp_length-2);
+ break;
+
+ case ( RADIUS_VENDOR_SPECIFIC ):
+ intval = tvb_get_ntohl(tvb,offset+2);
+ sprintf(dest, "Vendor:%s(%u)", rd_match_strval(intval,radius_vendor_specific_vendors), intval);
+ cont = &dest[strlen(dest)];
+ vsa_length = avph->avp_length;
+ vsa_len = 6;
+ vsa_index = 0;
+ vsa_attr_info_table = get_attr_info_table(intval);
+ do
+ {
+ vsa_avph = (const e_avphdr*)tvb_get_ptr(tvb, offset+vsa_len,
+ avph->avp_length-vsa_len);
+ if (vsa_attr_info_table)
+ next_attr_info = find_radius_attr_info(vsa_avph->avp_type,
+ vsa_attr_info_table);
+ else
+ next_attr_info = NULL;
+ cont = &cont[strlen(cont)+1];
+ tmp_punt = cont;
+ (*vsabuffer)[vsa_index].str = cont;
+ (*vsabuffer)[vsa_index].offset = offset+vsa_len;
+ (*vsabuffer)[vsa_index].length = vsa_avph->avp_length;
+ sprintf(cont, "t:%s(%u) l:%u, ",
+ (next_attr_info
+ ? next_attr_info->str
+ : "Unknown Type"),
+ vsa_avph->avp_type, vsa_avph->avp_length);
+ cont = &cont[strlen(cont)];
+ rd_value_to_str(cont, vsabuffer, vsa_avph, tvb,
+ offset+vsa_len, next_attr_info,
+ tree);
+ vsa_index++;
+ vsa_len += vsa_avph->avp_length;
+ if (next_attr_info != NULL &&
+ next_attr_info->value_type == THE3GPP_QOS )
+ {
+ cont = tmp_punt;
+ vsa_index--;
+ (*vsabuffer)[vsa_index].str = 0;
+ }
+ } while (vsa_length > vsa_len && vsa_index < VSABUFFER);
+ break;
+
+ case( COSINE_VPI_VCI ):
+ sprintf(cont,"%u/%u",
+ tvb_get_ntohs(tvb,offset+2),
+ tvb_get_ntohs(tvb,offset+4));
+ break;
+
+ case( THE3GPP_IMSI ):
+ case( THE3GPP_IMSI_MCC_MNC ):
+ case( THE3GPP_GGSN_MCC_MNC ):
+ case( THE3GPP_SGSN_MCC_MNC ):
+ case( THE3GPP_SELECTION_MODE ):
+ case( THE3GPP_CHARGING_CHARACTERISTICS ):
+ sprintf(cont,"(encoded in UTF-8 format)");
+ break;
+
+ case( THE3GPP_NSAPI ):
+ case( THE3GPP_SESSION_STOP_INDICATOR ):
+ sprintf(cont,"(not parsed)");
+ break;
+
+ case( THE3GPP_IPV6_DNS_SERVERS ):
+ /* XXX - this is described as a list of IPv6 addresses of
+ DNS servers, so we probably need to process more than
+ one IPv6 address. */
+ ip6_to_str_buf((const struct e_in6_addr *)tvb_get_ptr(tvb,offset+2,16),cont);
+ break;
+
+ case( THE3GPP_QOS ):
+ /* Find the ponter to the already-built label
+ * */
+ tmp_punt = dest - 2;
+ while (*tmp_punt)
+ tmp_punt--;
+ tmp_punt++;
+
+ /* Call decode_qos_umts from packet-gtp package
+ * */
+ decode_qos_umts(tvb, offset + 1, tree, tmp_punt, 3);
+ break;
+
+ case( RADIUS_TIMESTAMP ):
+ timeval=tvb_get_ntohl(tvb,offset+2);
+ sprintf(cont,"%d (%s)", timeval, abs_time_secs_to_str(timeval));
+ break;
+
+ case( RADIUS_INTEGER4_TAGGED ):
+ tag = tvb_get_guint8(tvb,offset+2);
+ intval = tvb_get_ntoh24(tvb,offset+3);
+ /* Tagged ? */
+ if (tag) {
+ if (attr_info->vs != NULL) {
+ sprintf(dest, "Tag:%u, Value:%s(%u)",
+ tag,
+ rd_match_strval(intval, attr_info->vs),
+ intval);
+ } else {
+ sprintf(dest, "Tag:%u, Value:%u",
+ tag, intval);
+ }
+ } else {
+ if (attr_info->vs != NULL)
+ sprintf(cont, "%s(%u)",
+ rd_match_strval(intval, attr_info->vs),
+ intval);
+ else
+ sprintf(cont,"%u", intval);
+ }
+ break;
+
+ case( RADIUS_UNKNOWN ):
+ strcpy(cont,"Unknown Value Type");
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ cont=&cont[strlen(cont)];
+ if (cont == dest) {
+ strcpy(cont,"Unknown Value");
+ }
+}
+
+static void
+dissect_attribute_value_pairs(tvbuff_t *tvb, int offset,proto_tree *tree,
+ int avplength,packet_info *pinfo)
+{
+/* adds the attribute value pairs to the tree */
+ e_avphdr avph;
+ const radius_attr_info *attr_info;
+ proto_item *ti = NULL;
+ guint8 *reassembled_data = NULL;
+ int reassembled_data_len = 0;
+ int data_needed = 0;
+ char *attr_info_str = "(Invalid)";
+
+ if (avplength==0)
+ {
+ if (tree)
+ proto_tree_add_text(tree, tvb,offset,0,"No Attribute Value Pairs Found");
+ return;
+ }
+
+ /*
+ * In case we throw an exception, clean up whatever stuff we've
+ * allocated (if any).
+ */
+ CLEANUP_PUSH(g_free, reassembled_data);
+
+ while (avplength > 0)
+ {
+ tvb_memcpy(tvb,(guint8 *)&avph,offset,sizeof(e_avphdr));
+ attr_info = find_radius_attr_info(avph.avp_type, radius_attrib);
+ if (avph.avp_length < 2) {
+ /*
+ * This AVP is bogus - the length includes the type and length
+ * fields, so it must be >= 2.
+ */
+ if (tree) {
+ if (attr_info) {
+ attr_info_str = attr_info->str;
+ }
+ proto_tree_add_text(tree, tvb, offset, avph.avp_length,
+ "t:%s(%u) l:%u (length not >= 2)",
+ attr_info_str, avph.avp_type, avph.avp_length);
+ }
+ break;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, avph.avp_length,
+ "t:%s(%u) l:%u",
+ attr_info ? attr_info->str : "Unknown Type",
+ avph.avp_type, avph.avp_length);
+ }
+ if (attr_info != NULL && attr_info->value_type == RADIUS_EAP_MESSAGE) {
+ /* EAP Message */
+ proto_tree *eap_tree = NULL;
+ gint tvb_len;
+ tvbuff_t *next_tvb;
+ int data_len;
+ int result;
+
+ if (tree)
+ eap_tree = proto_item_add_subtree(ti, ett_radius_eap);
+ tvb_len = tvb_length_remaining(tvb, offset+2);
+ data_len = avph.avp_length-2;
+ if (data_len < tvb_len)
+ tvb_len = data_len;
+ next_tvb = tvb_new_subset(tvb, offset+2, tvb_len, data_len);
+
+ /*
+ * Set the columns non-writable, so that the packet list
+ * shows this as an RADIUS packet, not as an EAP packet.
+ */
+ col_set_writable(pinfo->cinfo, FALSE);
+
+ /*
+ * RFC 2869 says, in section 5.13, describing the EAP-Message
+ * attribute:
+ *
+ * The String field contains EAP packets, as defined in [3]. If
+ * multiple EAP-Message attributes are present in a packet their
+ * values should be concatenated; this allows EAP packets longer than
+ * 253 octets to be passed by RADIUS.
+ *
+ * Do reassembly of EAP-Message attributes.
+ */
+
+ /* Are we in the process of reassembling? */
+ if (reassembled_data != NULL) {
+ /* Yes - show this as an EAP fragment. */
+ if (tree)
+ proto_tree_add_text(eap_tree, next_tvb, 0, -1, "EAP fragment");
+
+ /*
+ * Do we have all of the data in this fragment?
+ */
+ if (tvb_len >= data_len) {
+ /*
+ * Yes - add it to the reassembled data.
+ */
+ tvb_memcpy(next_tvb, reassembled_data + reassembled_data_len,
+ 0, data_len);
+ reassembled_data_len += data_len;
+ data_needed -= data_len;
+ if (data_needed <= 0) {
+ /*
+ * We got at least as much data as we needed; we're done
+ * reassembling.
+ * XXX - what if we got more?
+ */
+
+ /*
+ * Allocate a new tvbuff, referring to the reassembled payload.
+ */
+ next_tvb = tvb_new_real_data(reassembled_data, reassembled_data_len,
+ reassembled_data_len);
+
+ /*
+ * We have a tvbuff that refers to this data, so we shouldn't
+ * free this data if we throw an exception; clear
+ * "reassembled_data", so the cleanup handler won't free it.
+ */
+ reassembled_data = NULL;
+ reassembled_data_len = 0;
+ data_needed = 0;
+
+ /*
+ * Arrange that the allocated packet data copy be freed when the
+ * tvbuff is freed.
+ */
+ tvb_set_free_cb(next_tvb, g_free);
+
+ /*
+ * Add the tvbuff to the list of tvbuffs to which the tvbuff we
+ * were handed refers, so it'll get cleaned up when that tvbuff
+ * is cleaned up.
+ */
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+
+ /* Add the defragmented data to the data source list. */
+ add_new_data_source(pinfo, next_tvb, "Reassembled EAP");
+
+ /* Now dissect it. */
+ call_dissector(eap_fragment_handle, next_tvb, pinfo, eap_tree);
+ }
+ }
+ } else {
+ /*
+ * No - hand it to the dissector.
+ */
+ result = call_dissector(eap_fragment_handle, next_tvb, pinfo, eap_tree);
+ if (result < 0) {
+ /* This is only part of the full EAP packet; start reassembly. */
+ proto_tree_add_text(eap_tree, next_tvb, 0, -1, "EAP fragment");
+ reassembled_data_len = data_len;
+ data_needed = -result;
+ reassembled_data = g_malloc(reassembled_data_len + data_needed);
+ tvb_memcpy(next_tvb, reassembled_data, 0, reassembled_data_len);
+ }
+ }
+ } else {
+ if (tree) {
+ proto_tree *vsa_tree = NULL;
+ int i;
+ gchar textbuffer[TEXTBUFFER];
+ rd_vsa_buffer vsabuffer[VSABUFFER];
+
+ /* We pre-add a text and a subtree to allow 3GPP QoS decoding
+ * to access the protocol tree.
+ * */
+ vsa_tree = proto_item_add_subtree(ti, ett_radius_vsa);
+ for (i = 0; i < VSABUFFER; i++)
+ vsabuffer[i].str = NULL;
+ rd_value_to_str(textbuffer, &vsabuffer, &avph, tvb, offset,
+ attr_info, vsa_tree);
+ proto_item_append_text(ti, ", %s", textbuffer);
+ for (i = 0; vsabuffer[i].str && i < VSABUFFER; i++)
+ proto_tree_add_text(vsa_tree, tvb, vsabuffer[i].offset,
+ vsabuffer[i].length, "%s", vsabuffer[i].str);
+ }
+ }
+
+ offset = offset+avph.avp_length;
+ avplength = avplength-avph.avp_length;
+ }
+
+ /*
+ * Call the cleanup handler to free any reassembled data we haven't
+ * attached to a tvbuff, and pop the handler.
+ */
+ CLEANUP_CALL_AND_POP;
+}
+
+static void dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *radius_tree = NULL, *avptree = NULL;
+ proto_item *ti,*avptf;
+ guint rhlength;
+ guint rhcode;
+ guint rhident;
+ guint avplength,hdrlength;
+ e_radiushdr rh;
+ gchar *hex_authenticator;
+
+ gchar *codestrval;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RADIUS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tvb_memcpy(tvb,(guint8 *)&rh,0,sizeof(e_radiushdr));
+
+ rhcode= rh.rh_code;
+ rhident= rh.rh_ident;
+ rhlength= g_ntohs(rh.rh_pktlength);
+ codestrval= match_strval(rhcode,radius_vals);
+ if (codestrval==NULL)
+ {
+ codestrval="Unknown Packet";
+ }
+ /* XXX Check for valid length value:
+ * Length
+ *
+ * The Length field is two octets. It indicates the length of the
+ * packet including the Code, Identifier, Length, Authenticator and
+ * Attribute fields. Octets outside the range of the Length field
+ * MUST be treated as padding and ignored on reception. If the
+ * packet is shorter than the Length field indicates, it MUST be
+ * silently discarded. The minimum length is 20 and maximum length
+ * is 4096.
+ */
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_add_fstr(pinfo->cinfo,COL_INFO,"%s(%d) (id=%d, l=%d)",
+ codestrval, rhcode, rhident, rhlength);
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree,proto_radius, tvb, 0, rhlength, FALSE);
+
+ radius_tree = proto_item_add_subtree(ti, ett_radius);
+
+ proto_tree_add_uint(radius_tree,hf_radius_code, tvb, 0, 1,
+ rh.rh_code);
+ proto_tree_add_uint_format(radius_tree,hf_radius_id, tvb, 1, 1,
+ rh.rh_ident, "Packet identifier: 0x%01x (%d)",
+ rhident,rhident);
+
+ proto_tree_add_uint(radius_tree, hf_radius_length, tvb,
+ 2, 2, rhlength);
+ if ( authenticator ) {
+ g_free(authenticator);
+ }
+ authenticator = g_malloc(AUTHENTICATOR_LENGTH);
+ if ( authenticator ) {
+ memcpy(authenticator,tvb_get_ptr(tvb,4,AUTHENTICATOR_LENGTH),AUTHENTICATOR_LENGTH);
+ }
+ hex_authenticator = g_malloc(AUTHENTICATOR_LENGTH * 2 + 1);
+ rdconvertbufftobinstr(hex_authenticator, tvb, 4, AUTHENTICATOR_LENGTH);
+ proto_tree_add_text(radius_tree, tvb, 4,
+ AUTHENTICATOR_LENGTH,
+ "Authenticator: 0x%s", hex_authenticator);
+ g_free(hex_authenticator);
+ }
+
+ hdrlength=RD_HDR_LENGTH+AUTHENTICATOR_LENGTH;
+ avplength= rhlength -hdrlength;
+
+ if (avplength > 0) {
+ /* list the attribute value pairs */
+
+ if (tree)
+ {
+ avptf = proto_tree_add_text(radius_tree,
+ tvb,hdrlength,avplength,
+ "Attribute value pairs");
+ avptree = proto_item_add_subtree(avptf, ett_radius_avp);
+ }
+
+ dissect_attribute_value_pairs(tvb, hdrlength, avptree, avplength, pinfo);
+ }
+
+}
+/* registration with the filtering engine */
+void
+proto_register_radius(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_radius_code,
+ { "Code","radius.code", FT_UINT8, BASE_DEC, VALS(radius_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_radius_id,
+ { "Identifier", "radius.id", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_radius_length,
+ { "Length","radius.length", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_radius,
+ &ett_radius_avp,
+ &ett_radius_eap,
+ &ett_radius_vsa,
+ };
+
+ module_t *radius_module;
+
+ proto_radius = proto_register_protocol("Radius Protocol", "RADIUS",
+ "radius");
+ proto_register_field_array(proto_radius, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ radius_module = prefs_register_protocol(proto_radius,NULL);
+ prefs_register_string_preference(radius_module,"shared_secret","Shared Secret",
+ "Shared secret used to decode User Passwords",
+ &shared_secret);
+}
+
+void
+proto_reg_handoff_radius(void)
+{
+ dissector_handle_t radius_handle;
+
+ /*
+ * Get a handle for the EAP fragment dissector.
+ */
+ eap_fragment_handle = find_dissector("eap_fragment");
+
+ radius_handle = create_dissector_handle(dissect_radius, proto_radius);
+ dissector_add("udp.port", UDP_PORT_RADIUS, radius_handle);
+ dissector_add("udp.port", UDP_PORT_RADIUS_NEW, radius_handle);
+ dissector_add("udp.port", UDP_PORT_RADACCT, radius_handle);
+ dissector_add("udp.port", UDP_PORT_RADACCT_NEW, radius_handle);
+}
diff --git a/epan/dissectors/packet-ranap.c b/epan/dissectors/packet-ranap.c
new file mode 100644
index 0000000000..2ec6df5edc
--- /dev/null
+++ b/epan/dissectors/packet-ranap.c
@@ -0,0 +1,4872 @@
+/* packet-ranap.c
+ * Routines for Radio Access Network Application Part Protocol dissection
+ * Based on 3GPP TS 25.413 V3.4.0
+ * Copyright 2001, Martin Held <Martin.Held@icn.siemens.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+
+
+#define SCCP_SSN_RANAP 0x8E
+
+/* description of PDU header */
+#define PDU_NUMBER_OF_OCTETS_OFFSET 3
+
+/* PDU Index Values */
+#define InitiatingMessage 0
+#define SuccessfulOutcome 1
+#define UnsuccessfulOutcome 2
+#define Outcome 3
+
+static const value_string ranap_pdu_index_values[] = {
+ {InitiatingMessage, "InitiatingMessage"},
+ {SuccessfulOutcome, "SuccessfulOutcome"},
+ {UnsuccessfulOutcome, "UnsuccessfulOutcome"},
+ {Outcome, "Outcome"},
+ { 0, NULL}
+};
+
+
+/* Procedure Code Values */
+#define PC_RAB_Assignment 0
+#define PC_Iu_Release 1
+#define PC_RelocationPreparation 2
+#define PC_RelocationResourceAllocation 3
+#define PC_RelocationCancel 4
+#define PC_SRNS_ContextTransfer 5
+#define PC_SecurityModeControl 6
+#define PC_DataVolumeReport 7
+#define PC_CN_InformationBroadcast 8
+#define PC_Reset 9
+#define PC_RAB_ReleaseRequest 10
+#define PC_Iu_ReleaseRequest 11
+#define PC_RelocationDetect 12
+#define PC_RelocationComplete 13
+#define PC_Paging 14
+#define PC_CommonID 15
+#define PC_CN_InvokeTrace 16
+#define PC_LocationReportingControl 17
+#define PC_LocationReport 18
+#define PC_InitialUE_Message 19
+#define PC_DirectTransfer 20
+#define PC_OverloadControl 21
+#define PC_ErrorIndication 22
+#define PC_SRNS_DataForward 23
+#define PC_ForwardSRNS_Context 24
+#define PC_privateMessage 25
+#define PC_CN_DeactivateTrace 26
+#define PC_ResetResource 27
+#define PC_RANAP_Relocation 28
+#define PC_max 28
+
+static const value_string ranap_procedure_code_values[] = {
+ {PC_RAB_Assignment, "RAB-Assignment"},
+ {PC_Iu_Release, "IU-Release"},
+ {PC_RelocationPreparation, "RelocationPreparation"},
+ {PC_RelocationResourceAllocation, "RelocationResourceAllocation"},
+ {PC_RelocationCancel, "RelocationCancel"},
+ {PC_SRNS_ContextTransfer, "SRNS-ContextTransfer"},
+ {PC_SecurityModeControl, "SecurityModeControl"},
+ {PC_DataVolumeReport, "DataVolumeReport"},
+ {PC_CN_InformationBroadcast, "CN-InformationBroadcast"},
+ {PC_Reset, "Reset"},
+ {PC_RAB_ReleaseRequest, "RAB-ReleaseRequest"},
+ {PC_Iu_ReleaseRequest, "Iu-ReleaseRequest"},
+ {PC_RelocationDetect, "RelocationDetect"},
+ {PC_RelocationComplete, "RelocationComplete"},
+ {PC_Paging, "Paging"},
+ {PC_CommonID, "CommonID"},
+ {PC_CN_InvokeTrace, "CN-InvokeTrace"},
+ {PC_LocationReportingControl, "LocationReportingControl"},
+ {PC_LocationReport, "LocationReport"},
+ {PC_InitialUE_Message, "InitialUE_Message"},
+ {PC_DirectTransfer, "DirectTransfer"},
+ {PC_OverloadControl, "OverloadControl"},
+ {PC_ErrorIndication, "ErrorIndication"},
+ {PC_SRNS_DataForward, "SRNS-DataForward"},
+ {PC_ForwardSRNS_Context, "ForwardSRNS-Context"},
+ {PC_privateMessage, "privateMessage"},
+ {PC_CN_DeactivateTrace, "CN-DeactivateTrace"},
+ {PC_ResetResource, "ResetResource"},
+ {PC_RANAP_Relocation, "RANAP-Relocation"},
+ {0, NULL}
+};
+
+
+static const value_string ranap_message_names[][5] = {
+ {/* PC_RAB_Assignment */
+ { InitiatingMessage, "RAB-AssignmentRequest"},
+ { SuccessfulOutcome, "undefined message"},
+ { UnsuccessfulOutcome, "undefined message"},
+ { Outcome, "RAB-AssignmentResponse"},
+ { 0, NULL}, },
+ { /* PC_Iu_Release */
+ { InitiatingMessage, "Iu-ReleaseCommand"},
+ { SuccessfulOutcome, "Iu-ReleaseComplete"},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_RelocationPreparation */
+ { InitiatingMessage, "RelocationRequired"},
+ { SuccessfulOutcome, "RelocationCommand"},
+ { UnsuccessfulOutcome, "RelocationPreparationFailure"},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_RelocationResourceAllocation */
+ { InitiatingMessage, "RelocationRequest"},
+ { SuccessfulOutcome, "RelocationRequestAcknowledge"},
+ { UnsuccessfulOutcome, "RelocationFailure"},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_RelocationCancel */
+ { InitiatingMessage, "RelocationCancel"},
+ { SuccessfulOutcome, "RelocationCancelAcknowledge"},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_SRNS_ContextTransfer */
+ { InitiatingMessage, "SRNS-ContextRequest"},
+ { SuccessfulOutcome, "SRNS-ContextResponse"},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_SecurityModeControl */
+ { InitiatingMessage, "SecurityModeCommand"},
+ { SuccessfulOutcome, "SecurityModeComplete"},
+ { UnsuccessfulOutcome, "SecurityModeReject"},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_DataVolumeReport */
+ { InitiatingMessage, "DataVolumeReportRequest"},
+ { SuccessfulOutcome, "DataVolumeReport"},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_CN_InformationBroadcast */
+ { InitiatingMessage, "CN-InformationBroadcastRequest"},
+ { SuccessfulOutcome, "CN-InformationBroadcastConfirm"},
+ { UnsuccessfulOutcome, "CN-InformationBroadcastReject"},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_Reset */
+ { InitiatingMessage, "Reset"},
+ { SuccessfulOutcome, "ResetAcknowledge"},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_RAB_ReleaseRequest */
+ { InitiatingMessage, "RAB-ReleaseRequest"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_Iu_ReleaseRequest */
+ { InitiatingMessage, "Iu-ReleaseRequest"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_RelocationDetect */
+ { InitiatingMessage, "RelocationDetect"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_RelocationComplete */
+ { InitiatingMessage, "RelocationComplete"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_Paging */
+ { InitiatingMessage, "Paging"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_CommonID */
+ { InitiatingMessage, "CommonID"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_CN_InvokeTrace */
+ { InitiatingMessage, "CN-InvokeTrace"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ {/* PC_LocationReportingControl */
+ { InitiatingMessage, "LocationReportingControl"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_LocationReport */
+ { InitiatingMessage, "LocationReport"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_InitialUE_Message */
+ { InitiatingMessage, "InitialUE-Message"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_DirectTransfer */
+ { InitiatingMessage, "DirectTransfer"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_OverloadControl */
+ { InitiatingMessage, "Overload"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_ErrorIndication */
+ { InitiatingMessage, "ErrorIndication"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_SRNS_DataForward */
+ { InitiatingMessage, "SRNS-DataForwardCommand"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_ForwardSRNS_Context */
+ { InitiatingMessage, "ForwardSRNS-Context"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_privateMessage */
+ { InitiatingMessage, "PrivateMessage"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_CN_DeactivateTrace */
+ { InitiatingMessage, "CN-DeactivateTrace"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_ResetResource */
+ { InitiatingMessage, "ResetResource"},
+ { SuccessfulOutcome, "ResetResourceAcknowledge"},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, },
+ { /* PC_RANAP_Relocation */
+ { InitiatingMessage, "RANAP-RelocationInformation"},
+ { SuccessfulOutcome, NULL},
+ { UnsuccessfulOutcome, NULL},
+ { Outcome, NULL},
+ { 0, NULL}, }
+};
+
+
+/* Criticality Values */
+#define CR_reject 0
+#define CR_ignore 1
+#define CR_notify 2
+
+static const value_string ranap_criticality_values[] = {
+ {CR_reject, "reject"},
+ {CR_ignore, "ignore"},
+ {CR_notify, "notify"},
+ {0, NULL}};
+
+
+/* presence values for optional components */
+#define PR_not_present 0
+#define PR_present 1
+
+static const value_string ranap_presence_values[] = {
+ {PR_not_present, "not present"},
+ {PR_present, "present"},
+ {0, NULL}};
+
+
+/* description of IE Header */
+#define IE_ID_LENGTH 2
+#define IE_CRITICALITY_LENGTH 1
+
+
+/* description of IE-ID values */
+#define IE_AreaIdentity 0
+#define IE_CN_BroadcastInformationPiece 1
+#define IE_CN_BroadcastInformationPieceList 2
+#define IE_CN_DomainIndicator 3
+#define IE_Cause 4
+#define IE_ChosenEncryptionAlgorithm 5
+#define IE_ChosenIntegrityProtectionAlgorithm 6
+#define IE_ClassmarkInformation2 7
+#define IE_ClassmarkInformation3 8
+#define IE_CriticalityDiagnostics 9
+#define IE_DL_GTP_PDU_SequenceNumber 10
+#define IE_EncryptionInformation 11
+#define IE_IntegrityProtectionInformation 12
+#define IE_IuTransportAssociation 13
+#define IE_L3_Information 14
+#define IE_LAI 15
+#define IE_NAS_PDU 16
+#define IE_NonSearchingIndication 17
+#define IE_NumberOfSteps 18
+#define IE_OMC_ID 19
+#define IE_OldBSS_ToNewBSS_Information 20
+#define IE_PagingAreaID 21
+#define IE_PagingCause 22
+#define IE_PermanentNAS_UE_ID 23
+#define IE_RAB_ContextItem 24
+#define IE_RAB_ContextList 25
+#define IE_RAB_DataForwardingItem 26
+#define IE_RAB_DataForwardingItem_SRNS_CtxReq 27
+#define IE_RAB_DataForwardingList 28
+#define IE_RAB_DataForwardingList_SRNS_CtxReq 29
+#define IE_RAB_DataVolumeReportItem 30
+#define IE_RAB_DataVolumeReportList 31
+#define IE_RAB_DataVolumeReportRequestItem 32
+#define IE_RAB_DataVolumeReportRequestList 33
+#define IE_RAB_FailedItem 34
+#define IE_RAB_FailedList 35
+#define IE_RAB_ID 36
+#define IE_RAB_QueuedItem 37
+#define IE_RAB_QueuedList 38
+#define IE_RAB_ReleaseFailedList 39
+#define IE_RAB_ReleaseItem 40
+#define IE_RAB_ReleaseList 41
+#define IE_RAB_ReleasedItem 42
+#define IE_RAB_ReleasedList 43
+#define IE_RAB_ReleasedList_IuRelComp 44
+#define IE_RAB_RelocationReleaseItem 45
+#define IE_RAB_RelocationReleaseList 46
+#define IE_RAB_SetupItem_RelocReq 47
+#define IE_RAB_SetupItem_RelocReqAck 48
+#define IE_RAB_SetupList_RelocReq 49
+#define IE_RAB_SetupList_RelocReqAck 50
+#define IE_RAB_SetupOrModifiedItem 51
+#define IE_RAB_SetupOrModifiedList 52
+#define IE_RAB_SetupOrModifyItem 53
+#define IE_RAB_SetupOrModifyList 54
+#define IE_RAC 55
+#define IE_RelocationType 56
+#define IE_RequestType 57
+#define IE_SAI 58
+#define IE_SAPI 59
+#define IE_SourceID 60
+#define IE_SourceRNC_ToTargetRNC_TransparentContainer 61
+#define IE_TargetID 62
+#define IE_TargetRNC_ToSourceRNC_TransparentContainer 63
+#define IE_TemporaryUE_ID 64
+#define IE_TraceReference 65
+#define IE_TraceType 66
+#define IE_TransportLayerAddress 67
+#define IE_TriggerID 68
+#define IE_UE_ID 69
+#define IE_UL_GTP_PDU_SequenceNumber 70
+#define IE_RAB_FailedtoReportItem 71
+#define IE_RAB_FailedtoReportList 72
+#define IE_KeyStatus 75
+#define IE_DRX_CycleLengthCoefficient 76
+#define IE_IuSigConIdList 77
+#define IE_IuSigConIdItem 78
+#define IE_IuSigConId 79
+#define IE_DirectTransferInformationItem_RANAP_RelocInf 80
+#define IE_DirectTransferInformationList_RANAP_RelocInf 81
+#define IE_RAB_ContextItem_RANAP_RelocInf 82
+#define IE_RAB_ContextList_RANAP_RelocInf 83
+#define IE_RAB_ContextFailedtoTransferItem 84
+#define IE_RAB_ContextFailedtoTransferList 85
+#define IE_GlobalRNC_ID 86
+#define IE_RAB_ReleasedItem_IuRelComp 87
+
+static const value_string ranap_ie_id_values[] = {
+ {IE_AreaIdentity, "AreaIdentity"},
+ {IE_CN_BroadcastInformationPiece, "CN_BroadcastInformationPiece"},
+ {IE_CN_BroadcastInformationPieceList, "CN_BroadcastInformationPieceList"},
+ {IE_CN_DomainIndicator, "CN_DomainIndicator"},
+ {IE_Cause, "Cause"},
+ {IE_ChosenEncryptionAlgorithm, "ChosenEncryptionAlgorithm"},
+ {IE_ChosenIntegrityProtectionAlgorithm, "ChosenIntegrityProtectionAlgorithm"},
+ {IE_ClassmarkInformation2, "ClassmarkInformation2"},
+ {IE_ClassmarkInformation3, "ClassmarkInformation3"},
+ {IE_CriticalityDiagnostics, "CriticalityDiagnostics"},
+ {IE_DL_GTP_PDU_SequenceNumber, "DL_GTP_PDU_SequenceNumber"},
+ {IE_EncryptionInformation, "EncryptionInformation"},
+ {IE_IntegrityProtectionInformation, "IntegrityProtectionInformation"},
+ {IE_IuTransportAssociation, "IuTransportAssociation"},
+ {IE_L3_Information, "L3_Information"},
+ {IE_LAI, "LAI"},
+ {IE_NAS_PDU, "NAS_PDU"},
+ {IE_NonSearchingIndication, "NonSearchingIndication"},
+ {IE_NumberOfSteps, "NumberOfSteps"},
+ {IE_OMC_ID, "OMC_ID"},
+ {IE_OldBSS_ToNewBSS_Information, "OldBSS_ToNewBSS_Information"},
+ {IE_PagingAreaID, "PagingAreaID"},
+ {IE_PagingCause, "PagingCause"},
+ {IE_PermanentNAS_UE_ID, "PermanentNAS_UE_ID"},
+ {IE_RAB_ContextItem, "RAB_ContextItem"},
+ {IE_RAB_ContextList, "RAB_ContextList"},
+ {IE_RAB_DataForwardingItem, "RAB_DataForwardingItem"},
+ {IE_RAB_DataForwardingItem_SRNS_CtxReq, "RAB_DataForwardingItem_SRNS_CtxReq"},
+ {IE_RAB_DataForwardingList, "RAB_DataForwardingList"},
+ {IE_RAB_DataForwardingList_SRNS_CtxReq, "RAB_DataForwardingList_SRNS_CtxReq"},
+ {IE_RAB_DataVolumeReportItem, "RAB_DataVolumeReportItem"},
+ {IE_RAB_DataVolumeReportList, "RAB_DataVolumeReportList"},
+ {IE_RAB_DataVolumeReportRequestItem, "RAB_DataVolumeReportRequestItem"},
+ {IE_RAB_DataVolumeReportRequestList, "RAB_DataVolumeReportRequestList"},
+ {IE_RAB_FailedItem, "RAB_FailedItem"},
+ {IE_RAB_FailedList, "RAB_FailedList"},
+ {IE_RAB_ID, "RAB_ID"},
+ {IE_RAB_QueuedItem, "RAB_QueuedItem"},
+ {IE_RAB_QueuedList, "RAB_QueuedList"},
+ {IE_RAB_ReleaseFailedList, "RAB_ReleaseFailedList"},
+ {IE_RAB_ReleaseItem, "RAB_ReleaseItem"},
+ {IE_RAB_ReleaseList, "RAB_ReleaseList"},
+ {IE_RAB_ReleasedItem, "RAB_ReleasedItem"},
+ {IE_RAB_ReleasedList, "RAB_ReleasedList"},
+ {IE_RAB_ReleasedList_IuRelComp, "RAB_ReleasedList_IuRelComp"},
+ {IE_RAB_RelocationReleaseItem, "RAB_RelocationReleaseItem"},
+ {IE_RAB_RelocationReleaseList, "RAB_RelocationReleaseList"},
+ {IE_RAB_SetupItem_RelocReq, "RAB_SetupItem_RelocReq"},
+ {IE_RAB_SetupItem_RelocReqAck, "RAB_SetupItem_RelocReqAck"},
+ {IE_RAB_SetupList_RelocReq, "RAB_SetupList_RelocReq"},
+ {IE_RAB_SetupList_RelocReqAck, "RAB_SetupList_RelocReqAck"},
+ {IE_RAB_SetupOrModifiedItem, "RAB_SetupOrModifiedItem"},
+ {IE_RAB_SetupOrModifiedList, "RAB_SetupOrModifiedList"},
+ {IE_RAB_SetupOrModifyItem, "RAB_SetupOrModifyItem"},
+ {IE_RAB_SetupOrModifyList, "RAB_SetupOrModifyList"},
+ {IE_RAC, "RAC"},
+ {IE_RelocationType, "RelocationType"},
+ {IE_RequestType, "RequestType"},
+ {IE_SAI, "SAI"},
+ {IE_SAPI, "SAPI"},
+ {IE_SourceID, "SourceID"},
+ {IE_SourceRNC_ToTargetRNC_TransparentContainer,
+ "SourceRNC_ToTargetRNC_TransparentContainer"},
+ {IE_TargetID, "TargetID"},
+ {IE_TargetRNC_ToSourceRNC_TransparentContainer,
+ "TargetRNC_ToSourceRNC_TransparentContainer"},
+ {IE_TemporaryUE_ID, "TemporaryUE_ID"},
+ {IE_TraceReference, "TraceReference"},
+ {IE_TraceType, "TraceType"},
+ {IE_TransportLayerAddress, "TransportLayerAddress"},
+ {IE_TriggerID, "TriggerID"},
+ {IE_UE_ID, "UE_ID"},
+ {IE_UL_GTP_PDU_SequenceNumber, "UL_GTP_PDU_SequenceNumber"},
+ {IE_RAB_FailedtoReportItem, "RAB_FailedtoReportItem"},
+ {IE_RAB_FailedtoReportList, "RAB_FailedtoReportList"},
+ {IE_KeyStatus, "KeyStatus"},
+ {IE_DRX_CycleLengthCoefficient, "DRX_CycleLengthCoefficient"},
+ {IE_IuSigConIdList, "IuSigConIdList"},
+ {IE_IuSigConIdItem, "IuSigConIdItem"},
+ {IE_IuSigConId, "IuSigConId"},
+ {IE_DirectTransferInformationItem_RANAP_RelocInf,
+ "DirectTransferInformationItem_RANAP_RelocInf"},
+ {IE_DirectTransferInformationList_RANAP_RelocInf,
+ "DirectTransferInformationList_RANAP_RelocInf"},
+ {IE_RAB_ContextItem_RANAP_RelocInf, "RAB_ContextItem_RANAP_RelocInf"},
+ {IE_RAB_ContextList_RANAP_RelocInf, "RAB_ContextList_RANAP_RelocInf"},
+ {IE_RAB_ContextFailedtoTransferItem, "RAB_ContextFailedtoTransferItem"},
+ {IE_RAB_ContextFailedtoTransferList, "RAB_ContextFailedtoTransferList"},
+ {IE_GlobalRNC_ID, "GlobalRNC_ID"},
+ {IE_RAB_ReleasedItem_IuRelComp, "RAB_ReleasedItem_IuRelComp"},
+ {0, NULL}
+};
+
+
+/* Description of IE-Contents */
+
+/* Length of fields within IEs */
+#define RAB_ID_LENGTH 1
+#define PLMN_ID_LENGTH 3
+#define LAC_LENGTH 2
+#define IE_PROTOCOL_EXTENSION_LENGTH 1
+#define RAC_LENGTH 1
+#define SAC_LENGTH 2
+#define NUM_RABS_LENGTH 1
+
+
+/* Traffic Class values */
+#define TC_conversational 0
+#define TC_streaming 1
+#define TC_interactive 2
+#define TC_background 3
+
+static const value_string ranap_trafficClass_values[] = {
+ {TC_conversational, "conversational"},
+ {TC_streaming, "streaming"},
+ {TC_interactive, "interactive"},
+ {TC_background, "background"},
+ {0, NULL}};
+
+
+/* rAB-AsymmetryIndicator values */
+#define AI_symmetric_bidirectional 0
+#define AI_asymmetric_unidirectional_downlink 1
+#define AI_asymmetric_unidirectional_uplink 2
+#define AI_asymmetric_bidirectional 3
+
+static const value_string ranap_rAB_AsymmetryIndicator_values[] = {
+ {AI_symmetric_bidirectional, "symmetric-bidirectional"},
+ {AI_asymmetric_unidirectional_downlink, "asymmetric-unidirectional-downlink"},
+ {AI_asymmetric_unidirectional_uplink, "asymmetric-unidirectional-uplink"},
+ {AI_asymmetric_bidirectional, "asymmetric-bidirectional"},
+ {0, NULL}};
+
+
+/* DeliveryOrder values */
+#define DO_delivery_order_requested 0
+#define DO_delivery_order_not_requested 1
+
+static const value_string ranap_DeliveryOrder_values[] = {
+ {DO_delivery_order_requested, "delivery-order-requested"},
+ {DO_delivery_order_not_requested, "delivery-order-not-requested"},
+ {0, NULL}};
+
+#define maxSDU_Size_LENGTH 2
+
+/* deliveryOfErroneousSDU values */
+#define DOES_yes 0
+#define DOES_no 1
+#define DOES_no_error_detection_consideration 2
+
+static const value_string ranap_deliveryOfErroneousSDU_values[] = {
+ {DOES_yes, "yes"},
+ {DOES_no, "no"},
+ {DOES_no_error_detection_consideration, "no-error-detection-consideration"},
+ {0, NULL}};
+
+
+#define subflowSDU_Size_LENGTH 2
+#define transferDelay_LENGTH 2
+
+
+/* trafficHandlingPriority values */
+static const value_string ranap_priority_values[] = {
+ { 0, "spare"},
+ { 1, "highest"},
+ { 2, ""},
+ { 3, ""},
+ { 4, ""},
+ { 5, ""},
+ { 6, ""},
+ { 7, ""},
+ { 8, ""},
+ { 9, ""},
+ { 10, ""},
+ { 11, ""},
+ { 12, ""},
+ { 13, ""},
+ { 14, "lowest"},
+ { 15, "no-priority-used"},
+ { 0, NULL}};
+
+
+/* pre-emptionCapability values */
+static const value_string ranap_pre_emptionCapability_values[] = {
+ { 0, "shall-not-trigger-pre-emption"},
+ { 1, "may-trigger-pre-emption"},
+ { 0, NULL}};
+
+/* pre-emptionVulnerability values */
+static const value_string ranap_pre_emptionVulnerability_values[] = {
+ { 0, "not-pre-emptable"},
+ { 1, "pre-emptable"},
+ { 0, NULL}};
+
+
+/* queuingAllowed values */
+static const value_string ranap_queuingAllowed_values[] = {
+ { 0, "queueing-not-allowed"},
+ { 1, "queueing-allowed"},
+ { 0, NULL}};
+
+
+/* sourceStatisticsDescriptor values */
+static const value_string ranap_sourceStatisticsDescriptor_values[] = {
+ { 0, "speech"},
+ { 1, "unknown"},
+ { 0, NULL}};
+
+/* relocationRequirement values */
+static const value_string ranap_relocationRequirement_values[] = {
+ { 0, "lossless"},
+ { 1, "none"},
+ { 0, NULL}};
+
+/* userPlaneMode values */
+static const value_string ranap_userPlaneMode_values[] = {
+ { 0, "transparent-mode"},
+ { 1, "support-mode-for-predefined-SDU-sizes"},
+ { 0, NULL}};
+
+/* PDP_Type values */
+static const value_string ranap_PDP_Type_values[] = {
+ { 0, "empty"},
+ { 1, "ppp"},
+ { 2, "osp-ihoss"},
+ { 3, "ipv4"},
+ { 4, "ipv6"},
+ { 0, NULL}};
+
+/* dataVolumeReportingIndication values */
+static const value_string ranap_dataVolumeReportingIndication_values[] = {
+ { 0, "do-report"},
+ { 1, "do-not-report"},
+ { 0, NULL}};
+
+
+/* cause_choice values */
+#define CC_CauseRadioNetwork 0
+#define CC_CauseTransmissionNetwork 1
+#define CC_CauseNAS 2
+#define CC_CauseProtocol 3
+#define CC_CauseMisc 4
+#define CC_CauseNon_Standard 5
+
+static const value_string ranap_cause_choice_values[] = {
+ { CC_CauseRadioNetwork, "CauseRadioNetwork"},
+ { CC_CauseTransmissionNetwork, "CauseTransmissionNetwork"},
+ { CC_CauseNAS, "CauseNAS"},
+ { CC_CauseProtocol, "CauseProtocol"},
+ { CC_CauseMisc, "CauseMisc"},
+ { CC_CauseNon_Standard, "CauseNon-Standard"},
+ { 0, NULL}};
+
+
+/* cause values */
+static const value_string ranap_cause_value_str[] = {
+/* CauseRadioNetwork (1..64) */
+ { 1, "rab-pre-empted"},
+ { 2, "trelocoverall-expiry"},
+ { 3, "trelocprep-expiry"},
+ { 4, "treloccomplete-expiry"},
+ { 5, "tqueing-expiry"},
+ { 6, "relocation-triggered"},
+ { 7, "trellocalloc-expiry"},
+ { 8, "unable-to-establish-during-relocation"},
+ { 9, "unknown-target-rnc"},
+ { 10, "relocation-cancelled"},
+ { 11, "successful-relocation"},
+ { 12, "requested-ciphering-and-or-integrity-protection-algorithms-not-supported"},
+ { 13, "change-of-ciphering-and-or-integrity-protection-is-not-supported"},
+ { 14, "failure-in-the-radio-interface-procedure"},
+ { 15, "release-due-to-utran-generated-reason"},
+ { 16, "user-inactivity"},
+ { 17, "time-critical-relocation"},
+ { 18, "requested-traffic-class-not-available"},
+ { 19, "invalid-rab-parameters-value"},
+ { 20, "requested-maximum-bit-rate-not-available"},
+ { 21, "requested-guaranteed-bit-rate-not-available"},
+ { 22, "requested-transfer-delay-not-achievable"},
+ { 23, "invalid-rab-parameters-combination"},
+ { 24, "condition-violation-for-sdu-parameters"},
+ { 25, "condition-violation-for-traffic-handling-priority"},
+ { 26, "condition-violation-for-guaranteed-bit-rate"},
+ { 27, "user-plane-versions-not-supported"},
+ { 28, "iu-up-failure"},
+ { 29, "relocation-failure-in-target-CN-RNC-or-target-system"},
+ { 30, "invalid-RAB-ID"},
+ { 31, "no-remaining-rab"},
+ { 32, "interaction-with-other-procedure"},
+ { 33, "requested-maximum-bit-rate-for-dl-not-available"},
+ { 34, "requested-maximum-bit-rate-for-ul-not-available"},
+ { 35, "requested-guaranteed-bit-rate-for-dl-not-available"},
+ { 36, "requested-guaranteed-bit-rate-for-ul-not-available"},
+ { 37, "repeated-integrity-checking-failure"},
+ { 38, "requested-report-type-not-supported"},
+ { 39, "request-superseded"},
+ { 40, "release-due-to-UE-generated-signalling-connection-release"},
+ { 41, "resource-optimisation-relocation"},
+ { 42, "requested-information-not-available"},
+ { 43, "relocation-desirable-for-radio-reasons"},
+ { 44, "relocation-not-supported-in-target-RNC-or-target-system"},
+ { 45, "directed-retry"},
+ { 46, "radio-connection-with-UE-Lost"},
+
+/* CauseTransmissionNetwork (65..80) */
+ { 65, "logical-error-unknown-iu-transport-association"},
+ { 66, "iu-transport-connection-failed-to-establish"},
+
+/* CauseNAS (81..96) */
+ { 81, "user-restriction-start-indication"},
+ { 82, "user-restriction-end-indication"},
+ { 83, "normal-release"},
+
+/* CauseProtocol (97..112) */
+ { 97, "transfer-syntax-error"},
+ { 98, "semantic-error"},
+ { 99, "message-not-compatible-with-receiver-state"},
+ {100, "abstract-syntax-error-reject"},
+ {101, "abstract-syntax-error-ignore-and-notify"},
+ {102, "abstract-syntax-error-falsely-constructed-message"},
+
+/* CauseMisc (113..128) */
+ {113, "om-intervention"},
+ {114, "no-resource-available"},
+ {115, "unspecified-failure"},
+ {116, "network-optimisation"},
+ { 0, NULL}};
+
+
+/* CN_DomainIndicator_values */
+static const value_string ranap_CN_DomainIndicator_values[] = {
+ { 0, "cs-domain"},
+ { 1, "ps-domain"},
+ { 0, NULL}};
+
+
+/* SAPI_values */
+static const value_string ranap_SAPI_values[] = {
+ { 0, "sapi-0"},
+ { 1, "sapi-3"},
+ { 0, NULL}};
+
+/* service_Handover_values */
+static const value_string ranap_service_Handover_values[] = {
+ { 0, "handover-to-GSM-should-be-performed"},
+ { 1, "handover-to-GSM-should-not-be-performed"},
+ { 2, "handover-to-GSM-shall-not-be-performed"},
+ { 0, NULL}};
+
+/* Initialize the protocol and registered fields */
+/* protocol */
+static int proto_ranap = -1;
+
+static dissector_table_t nas_pdu_dissector_table;
+
+packet_info *g_pinfo = NULL;
+proto_tree *g_tree = NULL;
+
+/* pdu header fields */
+static int hf_ranap_pdu_number_of_octets = -1;
+static int hf_ranap_pdu_index = -1;
+static int hf_ranap_procedure_code = -1;
+static int hf_ranap_pdu_criticality = -1;
+static int hf_ranap_number_of_ies = -1;
+
+/* ie header fields */
+static int hf_ranap_ie_ie_id = -1;
+static int hf_ranap_ie_criticality = -1;
+static int hf_ranap_ie_number_of_octets = -1;
+static int hf_ranap_ie_protocol_extension = -1;
+
+/*ie contents fields */
+static int hf_ranap_number_of_ies_in_list = -1;
+static int hf_ranap_ie_pair_first_criticality = -1;
+static int hf_ranap_ie_pair_second_criticality = -1;
+static int hf_ranap_first_value_number_of_octets = -1;
+static int hf_ranap_second_value_number_of_octets = -1;
+static int hf_ranap_rab_id = -1;
+static int hf_ranap_nas_pdu = -1;
+static int hf_ranap_plmn_id = -1;
+static int hf_ranap_lac = -1;
+static int hf_ranap_sac = -1;
+static int hf_ranap_rac = -1;
+static int hf_ranap_nAS_SynchronisationIndicator = -1;
+static int hf_ranap_trafficClass = -1;
+static int hf_ranap_deliveryOrder = -1;
+static int hf_ranap_iE_Extensions_present = -1;
+static int hf_ranap_num_rabs = -1;
+static int hf_ranap_nAS_SynchronisationIndicator_present = -1;
+static int hf_ranap_rAB_Parameters_present = -1;
+static int hf_ranap_userPlaneInformation_present = -1;
+static int hf_ranap_transportLayerInformation_present = -1;
+static int hf_ranap_service_Handover_present = -1;
+static int hf_ranap_guaranteedBitRate_present = -1;
+static int hf_ranap_transferDelay_present = -1;
+static int hf_ranap_trafficHandlingPriority_present = -1;
+static int hf_ranap_allocationOrRetentionPriority_present = -1;
+static int hf_ranap_sourceStatisticsDescriptor_present = -1;
+static int hf_ranap_relocationRequirement_present = -1;
+static int hf_ranap_rAB_AsymmetryIndicator = -1;
+static int hf_ranap_maxBitrate = -1;
+static int hf_ranap_guaranteedBitrate = -1;
+static int hf_ranap_maxSDU_Size = -1;
+static int hf_ranap_sDU_ErrorRatio_mantissa = -1;
+static int hf_ranap_sDU_ErrorRatio_exponent = -1;
+static int hf_ranap_residualBitErrorRatio_mantissa = -1;
+static int hf_ranap_residualBitErrorRatio_exponent = -1;
+static int hf_ranap_deliveryOfErroneousSDU = -1;
+static int hf_ranap_subflowSDU_Size = -1;
+static int hf_ranap_rAB_SubflowCombinationBitRate = -1;
+static int hf_ranap_sDU_ErrorRatio_present = -1;
+static int hf_ranap_sDU_FormatInformationParameters_present = -1;
+static int hf_ranap_subflowSDU_Size_present = -1;
+static int hf_ranap_rAB_SubflowCombinationBitRate_present = -1;
+static int hf_ranap_transferDelay = -1;
+static int hf_ranap_trafficHandlingPriority = -1;
+static int hf_ranap_priorityLevel = -1;
+static int hf_ranap_pre_emptionCapability = -1;
+static int hf_ranap_pre_emptionVulnerability = -1;
+static int hf_ranap_queuingAllowed = -1;
+static int hf_ranap_sourceStatisticsDescriptor = -1;
+static int hf_ranap_userPlaneMode = -1;
+static int hf_ranap_uP_ModeVersions = -1;
+static int hf_ranap_number_of_ProtocolExtensionFields = -1;
+static int hf_ranap_ext_field_id = -1;
+static int hf_ranap_ext_field_criticality = -1;
+static int hf_ranap_ext_field_number_of_octets = -1;
+static int hf_ranap_transportLayerAddress = -1;
+static int hf_ranap_transportLayerAddress_length = -1;
+static int hf_ranap_gTP_TEI = -1;
+static int hf_ranap_bindingID = -1;
+static int hf_ranap_pDP_TypeInformation_present = -1;
+static int hf_ranap_dataVolumeReportingIndication_present = -1;
+static int hf_ranap_dl_GTP_PDU_SequenceNumber_present = -1;
+static int hf_ranap_ul_GTP_PDU_SequenceNumber_present = -1;
+static int hf_ranap_dl_N_PDU_SequenceNumber_present = -1;
+static int hf_ranap_ul_N_PDU_SequenceNumber_present = -1;
+static int hf_ranap_PDP_Type = -1;
+static int hf_ranap_dataVolumeReportingIndication = -1;
+static int hf_ranap_dl_GTP_PDU_SequenceNumber = -1;
+static int hf_ranap_ul_GTP_PDU_SequenceNumber = -1;
+static int hf_ranap_dl_N_PDU_SequenceNumber = -1;
+static int hf_ranap_ul_N_PDU_SequenceNumber = -1;
+static int hf_ranap_cause_choice = -1;
+static int hf_ranap_cause_value = -1;
+static int hf_ranap_transportLayerAddress_present = -1;
+static int hf_ranap_iuTransportAssociation_present = -1;
+static int hf_ranap_dl_dataVolumes_present = -1;
+static int hf_ranap_dataVolumeReference_present = -1;
+static int hf_ranap_dl_UnsuccessfullyTransmittedDataVolume = -1;
+static int hf_ranap_dataVolumeReference = -1;
+static int hf_ranap_procedureCode_present = -1;
+static int hf_ranap_triggeringMessage_present = -1;
+static int hf_ranap_procedureCriticality_present = -1;
+static int hf_ranap_iEsCriticalityDiagnostics_present = -1;
+static int hf_ranap_triggeringMessage = -1;
+static int hf_ranap_iECriticality = -1;
+static int hf_ranap_procedureCriticality = -1;
+static int hf_ranap_repetitionNumber = -1;
+static int hf_ranap_num_of_CriticalityDiagnostics_IEs = -1;
+static int hf_ranap_repetitionNumber_present = -1;
+static int hf_ranap_dl_UnsuccessfullyTransmittedDataVolume_present = -1;
+static int hf_ranap_CN_DomainIndicator = -1;
+static int hf_ranap_IuSigConId = -1;
+static int hf_ranap_SAPI = -1;
+static int hf_ranap_msg_extension_present = -1;
+static int hf_ranap_ProtocolExtensionContainer_present = -1;
+static int hf_ranap_nas_pdu_length = -1;
+static int hf_ranap_relocationRequirement = -1;
+static int hf_ranap_service_Handover = -1;
+static int hf_ranap_extension_field = -1;
+static int hf_ranap_RNC_ID = -1;
+
+
+/* subtrees */
+static gint ett_ranap = -1;
+static gint ett_ranap_optionals = -1;
+static gint ett_ranap_iE_Extension = -1;
+static gint ett_ranap_ie = -1;
+static gint ett_ranap_ie_pair = -1;
+static gint ett_ranap_rab = -1;
+static gint ett_ranap_ie_pair_first_value = -1;
+static gint ett_ranap_ie_pair_second_value = -1;
+static gint ett_ranap_rAB_Parameters = -1;
+static gint ett_ranap_sDU = -1;
+static gint ett_ranap_allocationOrRetentionPriority = -1;
+static gint ett_ranap_CriticalityDiagnostics_IE = -1;
+
+
+
+/*****************************************************************************/
+/* */
+/* Utility Functions */
+/* */
+/*****************************************************************************/
+
+/* sets *offset and *bitoffset n bits further */
+static void
+proceed_nbits(gint *offset, gint *bitoffset, gint n)
+{
+ *bitoffset += n;
+ *offset += *bitoffset / 8;
+ *bitoffset %= 8;
+}
+
+/* sets *offset and *bitoffset to the next byte boundary */
+static void allign(gint *offset, gint *bitoffset)
+{
+ if ( *bitoffset != 0 )
+ {
+ (*offset)++;
+ *bitoffset=0;
+ }
+}
+
+/* sets *offset and *bitoffset behind the following integer */
+static void
+proceed_perint32(gint *offset, gint *bitoffset, gint length)
+{
+ proceed_nbits(offset, bitoffset, 2);
+ allign(offset, bitoffset);
+ *offset += length;
+}
+
+
+/* extract length field found at offset */
+/* if length field spans more than two bytes -1 is returned and the field is not decoded */
+static guint8
+extract_length(tvbuff_t *tvb, gint offset, gint *length, gint *length_size)
+{
+ guint8 tmp_length8;
+ guint16 tmp_length16;
+
+ tmp_length8 = tvb_get_guint8(tvb, offset);
+ if ((tmp_length8 & 0x80) == 0)
+ {
+ /* length coded in one byte */
+ *length = tmp_length8;
+ *length_size = 1;
+ }
+ else
+ {
+ tmp_length16 = tvb_get_ntohs(tvb, offset);
+ if ( ((tmp_length16 & 0x8000) == 0x8000) && ((tmp_length16 & 0x4000) == 0) )
+ {
+ /* length coded in two bytes */
+ *length = tmp_length16 & 0x3FFF;
+ *length_size = 2;
+ }
+ else
+ { /* length is coded in more than 2 bytes */
+ return (-1);
+ }
+ }
+ return(0);
+}
+
+/* extract the next n bits and return them alligned to the LSB */
+static guint8
+extract_nbits(tvbuff_t *tvb, gint offset, gint bitoffset, gint n)
+{
+ guint8 uint_bits;
+ guint16 tmp_2bytes;
+
+ /* extract value */
+ if (bitoffset + n <= 8)
+ {
+ /* all bits contained in one byte */
+ uint_bits = tvb_get_guint8(tvb, offset);
+ uint_bits <<= bitoffset; /* remove bitoffset */
+ uint_bits >>= 8-n; /* allign to LSB */
+ }
+ else
+ {
+ /* bits contained within 2 bytes */
+ tmp_2bytes = tvb_get_ntohs(tvb, offset);
+ tmp_2bytes <<= bitoffset; /* remove bitoffset */
+ uint_bits = tmp_2bytes >> ( 8 + (8-n)); /* allign to LSB */
+ }
+
+ return(uint_bits);
+}
+
+
+/* extract an integer with 2bit length field and return the int value*/
+static guint32
+extract_int32(tvbuff_t *tvb, gint offset, gint bitoffset, gint *length)
+{
+ guint16 tmp_2byte;
+ guint32 result = 0;
+
+ tmp_2byte = tvb_get_ntohs(tvb, offset);
+
+ tmp_2byte <<= bitoffset; /* remove bitoffset */
+ *length = tmp_2byte >> (6 + 8); /* allign 2bit length field to LSB */
+ (*length)++; /* now we have the length of the int value */
+
+ proceed_nbits(&offset, &bitoffset, 2);
+ allign(&offset, &bitoffset);
+
+ switch (*length)
+ {
+ case 1:
+ result = tvb_get_guint8(tvb, offset);
+ break;
+ case 2:
+ result = tvb_get_ntohs(tvb, offset);
+ break;
+ case 3:
+ result = tvb_get_ntoh24(tvb, offset);
+ break;
+ case 4:
+ result = tvb_get_ntohl(tvb, offset);
+ break;
+ }
+
+ return(result);
+}
+
+
+/* return bitmask string looking like "..01 0..." */
+static char *
+bitmaskstr(guint bitoffset, guint bitlength, guint16 value, guint *length)
+{
+ static char maskstr[20];
+ guint i;
+
+
+ strcpy(maskstr, " ");
+
+ for (i=0; i<16; i++)
+ {
+ if ( i < bitoffset || i > bitoffset+bitlength-1 )
+ {
+ /* i is outside extracted bitfield */
+ maskstr[i + i/4] = '.';
+ }
+ else
+ { /* i is inside extracted bitfield */
+ if ( ((0x8000 >> i) & value) != 0x0000 )
+ {
+ /* bit is set */
+ maskstr[i + i/4] = '1';
+ }
+ else
+ {
+ /* bit is not set */
+ maskstr[i + i/4] = '0';
+ }
+ }
+ }
+ if (bitoffset + bitlength <= 8)
+ {
+ /* bitfield is located within first byte only */
+ maskstr[9] = '\0';
+ *length = 1;
+ }
+ else
+ {
+ /* bitfield is located within first & second byte */
+ maskstr[19] = '\0';
+ *length = 2;
+ }
+
+ return(maskstr);
+}
+
+/* add bitstring */
+static proto_item *
+proto_tree_add_bitstring(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint offset,
+ gint bitoffset, gint bitlength)
+{
+ guint16 read_2bytes;
+ guint16 alligned_2bytes;
+ guint8 one_byte;
+ char *maskstr;
+ char maskstr_buf[56] = "\0";
+ guint length;
+ int i;
+ guint8 bitstr[128];
+ char buf[256] = "\0";
+ header_field_info *hf_info_p;
+ gint byte_span;
+ gint initial_offset = offset;
+
+ memset(bitstr, 0, 128);
+
+ /* create bitmask string for first byte */
+ read_2bytes = tvb_get_ntohs(tvb, offset);
+ maskstr = bitmaskstr(bitoffset, (bitoffset+bitlength >8) ? 8-bitoffset : bitlength, read_2bytes, &length);
+ if (bitoffset+bitlength > 8)
+ {
+ sprintf(maskstr_buf, "%s + %d Bits = ", maskstr, bitlength - (8-bitoffset));
+ }
+ else
+ {
+ sprintf(maskstr_buf, "%s = ", maskstr);
+ }
+
+
+ /* print all but the last byte to buf */
+ byte_span = (bitoffset + bitlength + 7) / 8;
+ for (i=0; i < byte_span - 1; i++, offset++)
+ {
+ read_2bytes = tvb_get_ntohs(tvb, offset);
+ alligned_2bytes = read_2bytes << bitoffset; /* remove bitoffset */
+ one_byte = alligned_2bytes >> 8; /* move to low byte */
+
+ bitstr[i]=one_byte;
+ sprintf(&(buf[2*i]), "%02X", one_byte);
+ }
+
+ /* add last byte if it contains bits which have not yet been shifted in */
+ if ( ((bitlength + 7) / 8 ) == byte_span )
+ {
+ read_2bytes = tvb_get_ntohs(tvb, offset);
+ alligned_2bytes = read_2bytes << bitoffset; /* remove bitoffset */
+ one_byte = alligned_2bytes >> 8; /* move to low byte */
+ one_byte >>= (8 - (bitlength%8)); /*cut off surplus bits */
+ one_byte <<= (8 - (bitlength%8)); /* allign to MSB in low byte*/
+
+ bitstr[i]=one_byte;
+ sprintf(&(buf[2*i]), "%02X", one_byte);
+ }
+
+ /* get header field info */
+ hf_info_p = proto_registrar_get_nth(hfindex);
+
+
+ return ( proto_tree_add_bytes_format(tree, hfindex, tvb, initial_offset,
+ byte_span , bitstr, "%s %s: %s", maskstr_buf, hf_info_p->name, buf) );
+
+}
+
+
+/* add unsigned int, 1-8 bits long */
+static proto_item *
+proto_tree_add_uint_bits(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint offset,
+ gint bitoffset, gint bitlength, gint min)
+{
+ guint8 uint_bits;
+ guint16 read_2bytes, alligned_2bytes;
+ char *maskstr;
+ guint length;
+ header_field_info *hf_info_p;
+
+
+ /* extract value */
+ if (bitoffset + bitlength <= 8)
+ {
+ /* all bits contained in one byte */
+ uint_bits = tvb_get_guint8(tvb, offset);
+ read_2bytes = uint_bits;
+ read_2bytes <<= 8;
+ }
+ else
+ {
+ /* bits contained within 2 bytes */
+ read_2bytes = tvb_get_ntohs(tvb, offset);
+ }
+ alligned_2bytes = read_2bytes << bitoffset; /* remove bitoffset */
+ uint_bits = alligned_2bytes >> ( 8 + (8-bitlength)); /* allign to LSB */
+
+ uint_bits += min;
+
+ /* create bitmask string */
+ maskstr = bitmaskstr(bitoffset, bitlength, read_2bytes, &length);
+
+ /* get header field info */
+ hf_info_p = proto_registrar_get_nth(hfindex);
+
+ if (hf_info_p->strings != NULL)
+ {
+ /* string representation for decoded header field present */
+ return ( proto_tree_add_uint_format(tree, hfindex, tvb, offset,
+ length, uint_bits, "%s = %s: %s (%d)", maskstr, hf_info_p->name,
+ val_to_str(uint_bits, hf_info_p->strings, "%d"), uint_bits) );
+ }
+ else
+ {
+ /* no string representation */
+ return ( proto_tree_add_uint_format(tree, hfindex, tvb, offset,
+ length, uint_bits, "%s = %s: %d", maskstr, hf_info_p->name, uint_bits) );
+ }
+}
+
+/* add PER encoded integer (maximum length of value: 4 bytes) */
+static proto_item *
+proto_tree_add_PERint32(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint offset,
+ gint bitoffset, gint *length, gint min)
+{
+ guint32 value;
+ guint16 tmp_2bytes;
+ char *maskstr;
+ guint length_size;
+ header_field_info *hf_info_p;
+
+ /* get value */
+ value = extract_int32(tvb, offset, bitoffset, length);
+ value += min;
+
+ /* create bitmask string for 2 bit length field */
+ tmp_2bytes = tvb_get_ntohs(tvb, offset);
+ maskstr = bitmaskstr(bitoffset, 2, tmp_2bytes, &length_size);
+
+ /* get header field info */
+ hf_info_p = proto_registrar_get_nth(hfindex);
+
+ return ( proto_tree_add_uint_format(tree, hfindex, tvb, offset,
+ (*length) + length_size, value,
+ "%s + %d Bytes = %s: %d", maskstr, *length, hf_info_p->name, value) );
+}
+
+
+
+/*****************************************************************************/
+/* */
+/* Dissecting Functions for single parameters */
+/* */
+/*****************************************************************************/
+static int
+dissect_iE_Extension(tvbuff_t *tvb, proto_tree *tree, gint *offset, gint *bitoffset, char *description)
+{
+ proto_item *ext_item = NULL;
+ proto_tree *ext_tree = NULL;
+ guint16 number_of_extFields;
+ gint number_of_octets = 0;
+ gint number_of_octets_size = 0;
+ int i;
+
+ allign(offset, bitoffset);
+
+ /* create subtree for iE_Extension */
+ if (tree)
+ {
+ ext_item = proto_tree_add_text(tree, tvb, *offset, 0, "%s iE-Extensions", description);
+ ext_tree = proto_item_add_subtree(ext_item, ett_ranap_iE_Extension);
+ }
+
+ /* number of extension fields */
+ number_of_extFields = tvb_get_ntohs(tvb, *offset) + 1;
+ if (ext_tree)
+ {
+ proto_tree_add_uint(ext_tree, hf_ranap_number_of_ProtocolExtensionFields,
+ tvb, *offset, 2, number_of_extFields);
+ }
+
+ *offset += 2;
+
+ /* for each extension field */
+ for (i=1; i <= number_of_extFields; i++)
+ {
+ /* add fields to ie subtee */
+ /* Extension Field ID */
+ if (ext_tree)
+ {
+ proto_tree_add_item(ext_tree, hf_ranap_ext_field_id, tvb,
+ *offset, IE_ID_LENGTH, FALSE);
+ }
+ *offset += IE_ID_LENGTH;
+
+ /* criticality */
+ if (ext_tree)
+ {
+ proto_tree_add_uint_bits(ext_tree, hf_ranap_ext_field_criticality, tvb,
+ *offset, *bitoffset, 2, 0);
+ }
+ proceed_nbits(offset, bitoffset, 2);
+
+ /* number of octets in the IE */
+ allign(offset, bitoffset);
+ if (0 == extract_length(tvb, *offset, &number_of_octets, &number_of_octets_size))
+ {
+ if (ext_tree)
+ {
+ proto_tree_add_uint(ext_tree, hf_ranap_ext_field_number_of_octets, tvb,
+ *offset, number_of_octets_size, number_of_octets);
+ }
+ }
+ else
+ {
+ /* decoding is not supported */
+ if (ext_tree)
+ {
+ proto_tree_add_text(ext_tree, tvb, *offset, 0,
+ "Number of Octets greater than 0x3FFF, dissection not supported");
+ }
+ return(-1);
+ }
+
+ *offset += number_of_octets_size;
+ if (ext_tree)
+ {
+ proto_tree_add_item(ext_tree, hf_ranap_extension_field, tvb,
+ *offset, number_of_octets, FALSE);
+
+ }
+
+ *offset += number_of_octets;
+ }
+
+ return(0);
+}
+
+
+static int
+dissect_userPlaneInformation(tvbuff_t *tvb, proto_tree *tree, gint *offset, gint *bitoffset)
+{
+ int extension_present;
+ int iE_Extensions_present;
+ int tmp_extension_present;
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* userPlaneMode */
+ tmp_extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ proto_tree_add_uint_bits(tree, hf_ranap_userPlaneMode, tvb, *offset,
+ *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* uP-ModeVersions */
+ proto_tree_add_bitstring(tree, hf_ranap_uP_ModeVersions, tvb, *offset,
+ *bitoffset, 16);
+ proceed_nbits(offset, bitoffset, 16);
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ return(dissect_iE_Extension(tvb, tree, offset, bitoffset, "UserPlaneInformation"));
+ }
+ return(0);
+}
+
+
+
+static int
+dissect_sDU_Parameters(tvbuff_t *tvb, proto_tree *ie_tree, gint *offset, gint *bitoffset)
+{
+ proto_item *sDU_item = NULL;
+ proto_tree *sDU_tree = NULL;
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int ret;
+ int extension_present;
+ int sDU_ErrorRatio_present;
+ int sDU_FormatInformationParameters_present;
+ int iE_Extensions_present;
+ int sDU_ErrorRatio_iE_Extensions_present;
+ int residualBitErrorRatio_iE_Extensions_present;
+ gint length;
+ gint number_of_sDU_FormatInformationParameters;
+ int sDU_FormatInformationParameters_extension_present;
+ int subflowSDU_Size_present;
+ int rAB_SubflowCombinationBitRate_present;
+ int sDU_FormatInformationParameters_iE_Extensions_present;
+ gint i;
+
+ /* create subtree for sDU_Parameters */
+ sDU_item = proto_tree_add_text(ie_tree, tvb, *offset, 0,
+ "sDU Parameters");
+ sDU_tree = proto_item_add_subtree(sDU_item, ett_ranap_sDU);
+
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(sDU_tree, tvb, *offset, 1,
+ "sDU_Parameters Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* sDU_ErrorRatio present ? */
+ sDU_ErrorRatio_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_sDU_ErrorRatio_present, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* sDU_FormatInformationParameters present ? */
+ sDU_FormatInformationParameters_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_sDU_FormatInformationParameters_present, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+
+ /* sDU_ErrorRatio */
+ if (sDU_ErrorRatio_present)
+ {
+ sDU_ErrorRatio_iE_Extensions_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ proto_tree_add_uint_bits(sDU_tree, hf_ranap_sDU_ErrorRatio_mantissa, tvb, *offset,
+ *bitoffset, 4, 1);
+ proceed_nbits(offset, bitoffset, 4);
+
+ proto_tree_add_uint_bits(sDU_tree, hf_ranap_sDU_ErrorRatio_exponent, tvb, *offset,
+ *bitoffset, 3, 1);
+ proceed_nbits(offset, bitoffset, 3);
+
+ if (sDU_ErrorRatio_iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, sDU_tree, offset, bitoffset, "sDU_ErrorRatio")) != 0)
+ return (ret);
+ }
+ }
+
+ /* residualBitErrorRatio */
+ residualBitErrorRatio_iE_Extensions_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ proto_tree_add_uint_bits(sDU_tree, hf_ranap_residualBitErrorRatio_mantissa, tvb, *offset,
+ *bitoffset, 4, 1);
+ proceed_nbits(offset, bitoffset, 4);
+
+ proto_tree_add_uint_bits(sDU_tree, hf_ranap_sDU_ErrorRatio_exponent, tvb, *offset,
+ *bitoffset, 3, 1);
+ proceed_nbits(offset, bitoffset, 3);
+
+
+ if (residualBitErrorRatio_iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, sDU_tree, offset, bitoffset, "residualBitErrorRatio")) != 0)
+ return(ret);
+ }
+
+
+ /* deliveryOfErroneousSDU */
+ proto_tree_add_uint_bits(sDU_tree, hf_ranap_deliveryOfErroneousSDU, tvb, *offset,
+ *bitoffset, 2, 0);
+ proceed_nbits(offset, bitoffset, 2);
+
+
+ /* sDU_FormatInformationParameters */
+ if (sDU_FormatInformationParameters_present)
+ {
+ number_of_sDU_FormatInformationParameters = extract_nbits(tvb, *offset, *bitoffset, 6) + 1;
+ proceed_nbits(offset, bitoffset, 6);
+
+ for (i=1; i<= number_of_sDU_FormatInformationParameters; i++)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(sDU_tree, tvb, *offset, 1,
+ "sDU_FormatInformationParameters Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol extension present ? */
+ sDU_FormatInformationParameters_extension_present =
+ extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* subflowSDU_Size present ? */
+ subflowSDU_Size_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_subflowSDU_Size_present, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* rAB_SubflowCombinationBitRate present ? */
+ rAB_SubflowCombinationBitRate_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_rAB_SubflowCombinationBitRate_present, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* ie_Extension present ? */
+ sDU_FormatInformationParameters_iE_Extensions_present =
+ extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ if (subflowSDU_Size_present)
+ {
+ allign(offset, bitoffset);
+ proto_tree_add_item(sDU_tree, hf_ranap_subflowSDU_Size,
+ tvb, *offset, subflowSDU_Size_LENGTH, FALSE);
+ offset += subflowSDU_Size_LENGTH;
+ }
+
+ if (rAB_SubflowCombinationBitRate_present)
+ {
+ proto_tree_add_PERint32(sDU_tree, hf_ranap_rAB_SubflowCombinationBitRate,
+ tvb, *offset, *bitoffset, &length, 0);
+ proceed_perint32(offset, bitoffset, length);
+ }
+
+ if (sDU_FormatInformationParameters_iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, sDU_tree, offset, bitoffset,
+ "sDU_FormatInformationParameters" )) != 0)
+ return (ret);
+ }
+ }
+ }
+
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for sDU_FormatInformationParameters present, dissection not supported");
+ return(-1);
+ }
+
+ return (0);
+
+}
+
+
+static int
+dissect_rAB_Parameters(tvbuff_t *tvb, proto_tree *ie_tree, gint *offset, gint *bitoffset)
+{
+ guint8 tmp_byte;
+ proto_item *rab_item = NULL;
+ proto_tree *rab_tree = NULL;
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ proto_item *prio_item = NULL;
+ proto_tree *prio_tree = NULL;
+ int ret;
+ int extension_present;
+ int tmp_extension_present;
+ int guaranteedBitRate_present;
+ int transferDelay_present;
+ int trafficHandlingPriority_present;
+ int allocationOrRetentionPriority_present;
+ int sourceStatisticsDescriptor_present;
+ int relocationRequirement_present;
+ int iE_Extensions_present;
+ int tmp_iE_Extensions_present;
+ int i;
+ gint length;
+
+ /* create subtree for rAB_Parameters */
+ rab_item = proto_tree_add_text(ie_tree, tvb, *offset, 0,
+ "rAB_Parameters");
+ rab_tree = proto_item_add_subtree(rab_item, ett_ranap_rAB_Parameters);
+
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(rab_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "rAB_Parameters Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol extension present ? */
+ extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* guaranteedBitRate present ? */
+ guaranteedBitRate_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_guaranteedBitRate_present,
+ tvb, *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* transferDelay present ? */
+ transferDelay_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_transferDelay_present,
+ tvb, *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* trafficHandlingPriority present ? */
+ trafficHandlingPriority_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_trafficHandlingPriority_present,
+ tvb, *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* allocationOrRetentionPriority present ? */
+ allocationOrRetentionPriority_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_allocationOrRetentionPriority_present,
+ tvb, *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* sourceStatisticsDescriptor present ? */
+ sourceStatisticsDescriptor_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_sourceStatisticsDescriptor_present,
+ tvb, *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* relocationRequirement present ? */
+ relocationRequirement_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_relocationRequirement_present,
+ tvb, *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* iE-Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present,
+ tvb, *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+
+ /* trafficClass */
+ tmp_extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ proto_tree_add_uint_bits(rab_tree, hf_ranap_trafficClass,
+ tvb, *offset, *bitoffset, 2, 0);
+ proceed_nbits(offset, bitoffset, 2);
+
+ if (tmp_extension_present)
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(rab_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for trafficClass present, dissection not supported");
+ return(-1);
+ }
+
+
+ /* rAB-AsymmetryIndicator */
+ tmp_extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ proto_tree_add_uint_bits(rab_tree, hf_ranap_rAB_AsymmetryIndicator,
+ tvb, *offset, *bitoffset, 2, 0);
+ proceed_nbits(offset, bitoffset, 2);
+
+ if (tmp_extension_present)
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(rab_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for rAB-AsymmetryIndicator present, dissection not supported");
+ return(-1);
+ }
+
+
+ /* maxBitrate */
+ tmp_byte = extract_nbits(tvb, *offset, *bitoffset, 1) +1 ; /*sequence 1..2 */
+ proceed_nbits(offset, bitoffset, 1);
+
+ for (i=1; i<= tmp_byte; i++)
+ {
+ proto_tree_add_PERint32(rab_tree, hf_ranap_maxBitrate,
+ tvb, *offset, *bitoffset, &length, 1);
+ proceed_perint32(offset, bitoffset, length);
+ }
+
+
+ /* guaranteedBitRate */
+ if (guaranteedBitRate_present)
+ {
+ tmp_byte = extract_nbits(tvb, *offset, *bitoffset, 1) +1 ; /*sequence 1..2 */
+ proceed_nbits(offset, bitoffset, 1);
+
+ for (i=1; i<= tmp_byte; i++)
+ {
+ proto_tree_add_PERint32(rab_tree, hf_ranap_guaranteedBitrate,
+ tvb, *offset, *bitoffset, &length, 0);
+ proceed_perint32(offset, bitoffset, length);
+ }
+ }
+
+ /* deliveryOrder */
+ proto_tree_add_uint_bits(rab_tree, hf_ranap_deliveryOrder, tvb, *offset,
+ *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+
+ /* maxSDU-Size */
+ allign(offset, bitoffset);
+ proto_tree_add_item(rab_tree, hf_ranap_maxSDU_Size,
+ tvb, *offset, maxSDU_Size_LENGTH, FALSE);
+ *offset += maxSDU_Size_LENGTH;
+
+ /* sDU-Parameters */
+ tmp_byte = extract_nbits(tvb, *offset, *bitoffset, 3) + 1; /*sequence 1..7 */
+ proceed_nbits(offset, bitoffset, 3);
+ for (i=1; i<= tmp_byte; i++)
+ {
+ if ((ret=dissect_sDU_Parameters(tvb, rab_tree, offset, bitoffset))!=0) return(ret);
+ }
+
+ /* transferDelay */
+ if (transferDelay_present)
+ {
+ allign(offset, bitoffset);
+ proto_tree_add_item(rab_tree, hf_ranap_transferDelay,
+ tvb, *offset, transferDelay_LENGTH, FALSE);
+ *offset += transferDelay_LENGTH;
+ }
+
+
+ /* trafficHandlingPriority */
+ if (trafficHandlingPriority_present)
+ {
+ proto_tree_add_uint_bits(rab_tree, hf_ranap_trafficHandlingPriority, tvb, *offset,
+ *bitoffset, 4, 0);
+ proceed_nbits(offset, bitoffset, 4);
+ }
+
+ /* allocationOrRetentionPriority */
+ if (allocationOrRetentionPriority_present)
+ {
+ /* create subtree for */
+ prio_item = proto_tree_add_text(rab_tree, tvb, *offset, 0,
+ "allocationOrRetentionPriority");
+ prio_tree = proto_item_add_subtree(prio_item, ett_ranap_allocationOrRetentionPriority);
+
+ /* protocol extension present ? */
+ tmp_extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* iE Extension present ? */
+ tmp_iE_Extensions_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* allocationOrRetentionPriority */
+ proto_tree_add_uint_bits(prio_tree, hf_ranap_priorityLevel, tvb, *offset,
+ *bitoffset, 4, 0);
+ proceed_nbits(offset, bitoffset, 4);
+
+ /* pre-emptionCapability */
+ proto_tree_add_uint_bits(prio_tree, hf_ranap_pre_emptionCapability, tvb, *offset,
+ *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* pre-emptionVulnerability */
+ proto_tree_add_uint_bits(prio_tree, hf_ranap_pre_emptionVulnerability, tvb, *offset,
+ *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* queuingAllowed */
+ proto_tree_add_uint_bits(prio_tree, hf_ranap_queuingAllowed, tvb, *offset,
+ *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ if (tmp_iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, prio_tree, offset, bitoffset,
+ "AllocationOrRetentionPriority")) != 0)
+ return (ret);
+ }
+
+ if (tmp_extension_present)
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(prio_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for rAB-allocationOrRetentionPriority present, dissection not supported");
+ return(-1);
+ }
+ }
+
+ /* sourceStatisticsDescriptor */
+ if (sourceStatisticsDescriptor_present)
+ {
+ /* protocol extension */
+ tmp_extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ if (tmp_extension_present)
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(prio_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for sourceStatisticsDescriptor present, dissection not supported");
+ return(-1);
+ }
+
+ proto_tree_add_uint_bits(rab_tree, hf_ranap_sourceStatisticsDescriptor, tvb, *offset,
+ *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+ }
+
+ /* relocationRequirement */
+ if (relocationRequirement_present)
+ {
+ /* protocol extension */
+ tmp_extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+
+ if (tmp_extension_present)
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(prio_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for relocationRequirement present, dissection not supported");
+ return(-1);
+ }
+
+ proto_tree_add_uint_bits(rab_tree, hf_ranap_relocationRequirement, tvb, *offset,
+ *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+ }
+
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, rab_tree, offset, bitoffset, "rAB_Parameters" )) != 0 )
+ return (ret);
+ }
+
+ /* extended */
+ if (extension_present)
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(rab_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for rAB_Parameters present, dissection not supported");
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+
+static int
+dissect_TransportLayerAddress(tvbuff_t *tvb, proto_tree *ie_tree, gint *offset, gint *bitoffset)
+{
+ gint extension_present;
+ gint str_length;
+
+ extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+ if (extension_present)
+ {
+ /* extended integer */
+ proto_tree_add_text(ie_tree, tvb, *offset, 0,
+ "extension present for TransportLayerAddress, dissection not supported");
+ return (-1);
+ }
+
+ /* extract and add length of transportLayerAddress bitstring */
+ str_length = extract_nbits(tvb, *offset, *bitoffset, 8) + 1;
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_transportLayerAddress_length,
+ tvb, *offset, *bitoffset, 8, 1);
+ proceed_nbits(offset, bitoffset, 8);
+ allign(offset, bitoffset);
+
+ /* add transportLayerAddress */
+ proto_tree_add_bitstring(ie_tree, hf_ranap_transportLayerAddress, tvb, *offset,
+ *bitoffset, str_length);
+ proceed_nbits(offset, bitoffset, str_length);
+
+ return (0);
+}
+
+
+
+static int
+dissect_iuTransportAssociation(tvbuff_t *tvb, proto_tree *ie_tree, gint *offset, gint *bitoffset)
+{
+ guint extension_present;
+ guint choice_value;
+
+ /* extension present ? */
+ extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ if (extension_present)
+ {
+ /* extended choice */
+ proto_tree_add_text(ie_tree, tvb, *offset, 0,
+ "extension present for IuTransportAssociation, dissection not supported");
+ return (-1);
+ }
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* choice */
+ choice_value = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+ allign(offset, bitoffset);
+ if (choice_value == 0)
+ {
+ /* gTP-TEI */
+ proto_tree_add_item(ie_tree, hf_ranap_gTP_TEI, tvb, *offset, 4, FALSE);
+ *offset += 4;
+ }
+ else
+ {
+ /* bindingID */
+ proto_tree_add_item(ie_tree, hf_ranap_bindingID, tvb, *offset, 4, FALSE);
+ *offset += 4;
+ }
+
+ return (0);
+}
+
+
+static int
+dissect_transportLayerInformation(tvbuff_t *tvb, proto_tree *ie_tree, gint *offset, gint *bitoffset)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int extension_present;
+ int iE_Extensions_present;
+ int ret;
+
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "TransportLayerInformation Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+
+ /* protocol extension present ? */
+ extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* iE-Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present,
+ tvb, *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+
+ /* transportLayerAddress */
+ if ((ret=dissect_TransportLayerAddress(tvb, ie_tree, offset, bitoffset)) != 0)
+ return (ret);
+
+ /* iuTransportAssociation */
+ if ((ret=dissect_iuTransportAssociation(tvb, ie_tree, offset, bitoffset)) != 0)
+ return (ret);
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, offset, bitoffset, "TransportLayerInformation" )) != 0 )
+ return (ret);
+ }
+
+ /* protocol extension */
+ if (extension_present)
+ {
+ /* extended sequence */
+ proto_tree_add_text(ie_tree, tvb, *offset, 0,
+ "extension present for TransportLayerInformation, dissection not supported");
+ return (-1);
+ }
+
+ return(0);
+}
+
+
+static int
+dissect_dataVolumeList (tvbuff_t *tvb, proto_tree *ie_tree, gint *offset, gint *bitoffset, char *parname)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ gint extension_present;
+ gint dataVolumeReference_present;
+ gint iE_Extensions_present;
+ gint number_vol;
+ gint length;
+ gint i;
+ int ret;
+
+ /* number of volumes */
+ number_vol = extract_nbits(tvb, *offset, *bitoffset, 1) + 1;
+ proceed_nbits(offset, bitoffset, 1);
+
+ for (i=1; i<=number_vol; i++)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, *offset, 1,
+ "%d. %s Extension/Optional/Default bitmap",
+ i, parname);
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* dataVolumeReference present ? */
+ dataVolumeReference_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_dataVolumeReference_present, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+
+ /* UnsuccessfullyTransmittedDataVolume */
+ proto_tree_add_PERint32(ie_tree, hf_ranap_dl_UnsuccessfullyTransmittedDataVolume,
+ tvb, *offset, *bitoffset, &length, 0);
+ proceed_perint32(offset, bitoffset, length);
+
+ /* DataVolumeReference */
+ if (dataVolumeReference_present)
+ {
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_dataVolumeReference, tvb,
+ *offset, *bitoffset, 8, 0);
+ proceed_nbits(offset, bitoffset, 8);
+ }
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, offset, bitoffset, "dl-dataVolumes" )) != 0)
+ return(ret);
+ }
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for dl-dataVolumes present, dissection not supported");
+ return(-1);
+ }
+ }
+
+ return (0);
+
+}
+
+static int
+dissect_cause(tvbuff_t *tvb, proto_tree *ie_tree, gint *offset, gint *bitoffset)
+{
+ gint extension_present;
+ int cause_choice;
+
+ /* protocol extension present ? */
+ extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proceed_nbits(offset, bitoffset, 1);
+ if (extension_present)
+ {
+ /* choice extension present */
+ proto_tree_add_text(ie_tree, tvb, *offset, 0,
+ "extension present for cause, dissection not supported");
+ return (-1);
+ }
+ cause_choice = extract_nbits(tvb, *offset, *bitoffset, 3);
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_cause_choice,
+ tvb, *offset, *bitoffset, 3, 0);
+ proceed_nbits(offset, bitoffset, 3);
+
+ switch (cause_choice)
+ {
+ case CC_CauseRadioNetwork:
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_cause_value,
+ tvb, *offset, *bitoffset, 6, 1);
+ proceed_nbits(offset, bitoffset, 6);
+ break;
+ case CC_CauseTransmissionNetwork:
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_cause_value,
+ tvb, *offset, *bitoffset, 4, 65);
+ proceed_nbits(offset, bitoffset, 4);
+ break;
+ case CC_CauseNAS:
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_cause_value,
+ tvb, *offset, *bitoffset, 4, 81);
+ proceed_nbits(offset, bitoffset, 4);
+ break;
+ case CC_CauseProtocol:
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_cause_value,
+ tvb, *offset, *bitoffset, 4, 97);
+ proceed_nbits(offset, bitoffset, 4);
+ case CC_CauseMisc:
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_cause_value,
+ tvb, *offset, *bitoffset, 4, 113);
+ proceed_nbits(offset, bitoffset, 4);
+ break;
+ case CC_CauseNon_Standard:
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_cause_value,
+ tvb, *offset, *bitoffset, 7, 129);
+ proceed_nbits(offset, bitoffset, 7);
+ break;
+ default:
+ proto_tree_add_text(ie_tree, tvb, *offset, 0,
+ "unexpected cause choice value, dissection not supported");
+ return(-1);
+ }
+ return(0);
+}
+
+
+static int
+dissect_iEsCriticalityDiagnostics(tvbuff_t *tvb, proto_tree *ie_tree, gint *offset, gint *bitoffset)
+{
+ proto_item *diag_item = NULL;
+ proto_tree *diag_tree = NULL;
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int extension_present;
+ int repetitionNumber_present;
+ int iE_Extensions_present;
+ int num_of_errors;
+ int i;
+
+ allign(offset, bitoffset);
+ num_of_errors = extract_nbits(tvb, *offset, *bitoffset, 8) + 1;
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_num_of_CriticalityDiagnostics_IEs, tvb,
+ *offset, *bitoffset, 8, 1);
+ proceed_nbits(offset, bitoffset, 8);
+
+ for ( i= 1; i <= num_of_errors; i++)
+ {
+ /* add subtree for CriticalityDiagnostics-IE */
+ diag_item = proto_tree_add_text(ie_tree, tvb, *offset, 0,
+ "%d. CriticalityDiagnostics-IE", i);
+ diag_tree = proto_item_add_subtree(diag_item, ett_ranap_CriticalityDiagnostics_IE);
+
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(diag_tree, tvb, *offset, 1,
+ "CriticalityDiagnostics-IE Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* repetitionNumber present ? */
+ repetitionNumber_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_repetitionNumber_present, tvb,
+ *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, *offset, *bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present,
+ tvb, *offset, *bitoffset, 1, 0);
+ proceed_nbits(offset, bitoffset, 1);
+
+ /* iECriticality */
+ proto_tree_add_uint_bits(diag_tree, hf_ranap_iECriticality,
+ tvb, *offset, *bitoffset, 2, 0);
+ proceed_nbits(offset, bitoffset, 2);
+
+ /* iE-ID */
+ allign(offset, bitoffset);
+ proto_tree_add_item(diag_tree, hf_ranap_ie_ie_id, tvb,
+ *offset, IE_ID_LENGTH, FALSE);
+ *offset += IE_ID_LENGTH;
+
+ /* repetitionNumber */
+ if (repetitionNumber_present)
+ {
+ allign(offset, bitoffset);
+ proto_tree_add_uint_bits(diag_tree, hf_ranap_repetitionNumber,
+ tvb, *offset, *bitoffset, 8, 1);
+ proceed_nbits(offset, bitoffset, 8);
+ }
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ return(dissect_iE_Extension(tvb, diag_tree, offset, bitoffset, "CriticalityDiagnostics-IE"));
+ }
+
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(diag_tree, tvb, *offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for CriticalityDiagnostics-IE present, dissection not supported");
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+
+
+/*****************************************************************************/
+/* */
+/* Dissecting Functions for IEs */
+/* */
+/*****************************************************************************/
+
+static int
+dissect_IE_RAB_ID(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ if (ie_tree)
+ {
+ proto_tree_add_item(ie_tree, hf_ranap_rab_id, tvb,
+ 0, RAB_ID_LENGTH, FALSE);
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_RAC(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ if (ie_tree)
+ {
+ proto_tree_add_item(ie_tree, hf_ranap_rac, tvb,
+ 0, RAC_LENGTH, FALSE);
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_LAI(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+ int ret;
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "LAI Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* iE_Extensions_present present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* plmn_id */
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_plmn_id, tvb,
+ offset, PLMN_ID_LENGTH, FALSE);
+ offset += PLMN_ID_LENGTH;
+
+ /* lac */
+ proto_tree_add_item(ie_tree, hf_ranap_lac, tvb,
+ offset, LAC_LENGTH, FALSE);
+ offset += LAC_LENGTH;
+
+ /* iE_Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "LAI")) != 0)
+ return (ret);
+ }
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_GlobalRNC_ID(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ gint offset = 0;
+
+ if (ie_tree)
+ {
+ /* plmn_id */
+ proto_tree_add_item(ie_tree, hf_ranap_plmn_id, tvb,
+ offset, PLMN_ID_LENGTH, FALSE);
+ offset += PLMN_ID_LENGTH;
+
+ /* RNC ID */
+ proto_tree_add_item(ie_tree, hf_ranap_RNC_ID, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ return(0);
+}
+
+
+static int
+dissect_IE_SAI(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+ int ret;
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "SAI Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* iE_Extensions_present present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* plmn_id */
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_plmn_id, tvb,
+ offset, PLMN_ID_LENGTH, FALSE);
+ offset += PLMN_ID_LENGTH;
+
+ /* lac */
+ proto_tree_add_item(ie_tree, hf_ranap_lac, tvb,
+ offset, LAC_LENGTH, FALSE);
+ offset += LAC_LENGTH;
+
+ /* sac */
+ proto_tree_add_item(ie_tree, hf_ranap_sac, tvb,
+ offset, SAC_LENGTH, FALSE);
+ offset += SAC_LENGTH;
+
+ /* iE_Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "SAI")) != 0)
+ return (ret);
+ }
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_NAS_PDU(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ tvbuff_t *next_tvb;
+ gint length;
+ gint length_size;
+
+ if (extract_length(tvb, 0, &length, &length_size) != 0)
+ {
+ if (ie_tree)
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, 0,
+ 2, "Number of Octets greater than 0x3FFF, dissection not supported");
+ }
+ return(-1);
+ }
+
+ if (ie_tree)
+ {
+ /* NAS - PDU length */
+ proto_tree_add_item(ie_tree, hf_ranap_nas_pdu_length, tvb,
+ 0, length_size, FALSE);
+ }
+
+ if (ie_tree)
+ {
+ /* NAS - PDU */
+ proto_tree_add_item(ie_tree, hf_ranap_nas_pdu, tvb,
+ length_size, length, FALSE);
+ }
+
+ /* call NAS dissector */
+ next_tvb = tvb_new_subset(tvb, length_size, length, length);
+
+ if (dissector_try_port(nas_pdu_dissector_table, 0x1, next_tvb, g_pinfo, g_tree)) return(0);
+ return(0);
+}
+
+
+static int
+dissect_IE_CN_DomainIndicator(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ gint offset = 0;
+ gint bitoffset = 0;
+
+ if (ie_tree)
+ {
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_CN_DomainIndicator, tvb,
+ offset, bitoffset, 1, 0);
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_IuSigConId(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ guint32 value;
+
+ if (ie_tree)
+ {
+ value = tvb_get_ntoh24(tvb, 0);
+ proto_tree_add_uint(ie_tree, hf_ranap_IuSigConId,
+ tvb, 0, 3, value);
+
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_SAPI(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ gint offset = 0;
+ gint bitoffset = 0;
+ int extension_present;
+
+ if (ie_tree)
+ {
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ if (extension_present)
+ {
+ /* extended enum */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for IE_SAPI present, dissection not supported");
+ return(-1);
+ }
+
+ /* SAPI */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_SAPI, tvb,
+ offset, bitoffset, 1, 0);
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_TransportLayerAddress(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ gint offset = 0;
+ gint bitoffset = 0;
+
+ if (ie_tree)
+ {
+ return(dissect_TransportLayerAddress(tvb, ie_tree, &offset, &bitoffset));
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_IuTransportAssociation(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ gint offset = 0;
+ gint bitoffset = 0;
+
+ if (ie_tree)
+ {
+ return(dissect_iuTransportAssociation(tvb, ie_tree, &offset, &bitoffset));
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_Cause(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ gint offset = 0;
+ gint bitoffset = 0;
+
+ if (ie_tree)
+ {
+ return(dissect_cause(tvb, ie_tree, &offset, &bitoffset));
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_RAB_ReleasedItem_IuRelComp(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int extension_present;
+ int dl_GTP_PDU_SequenceNumber_present;
+ int ul_GTP_PDU_SequenceNumber_present;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+ int ret;
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "RAB_ReleasedItem_IuRelComp Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* dl_GTP_PDU_SequenceNumber present ? */
+ dl_GTP_PDU_SequenceNumber_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_dl_GTP_PDU_SequenceNumber_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* ul_GTP_PDU_SequenceNumber present ? */
+ ul_GTP_PDU_SequenceNumber_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ul_GTP_PDU_SequenceNumber_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iE_Extensions_present present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+
+ /* rAB-ID */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_rab_id,
+ tvb, offset, bitoffset, 8, 0);
+ proceed_nbits(&offset, &bitoffset, 8);
+
+ /* dl-GTP-PDU-SequenceNumber */
+ if (dl_GTP_PDU_SequenceNumber_present)
+ {
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_dl_GTP_PDU_SequenceNumber, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /* ul-GTP-PDU-SequenceNumber */
+ if (ul_GTP_PDU_SequenceNumber_present)
+ {
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_ul_GTP_PDU_SequenceNumber, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "RAB_ReleasedItem_IuRelComp")) != 0)
+ return (ret);
+ }
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for RAB_ReleasedItem_IuRelComp present, dissection not supported");
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_RAB_DataVolumeReportItem(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int extension_present;
+ int dl_UnsuccessfullyTransmittedDataVolume_present;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+ int ret;
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "RAB_DataVolumeReportItem Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* dl_UnsuccessfullyTransmittedDataVolume present ? */
+ dl_UnsuccessfullyTransmittedDataVolume_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_dl_UnsuccessfullyTransmittedDataVolume_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iE_Extensions_present present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+
+ /* rAB-ID */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_rab_id,
+ tvb, offset, bitoffset, 8, 0);
+ proceed_nbits(&offset, &bitoffset, 8);
+
+ /* dl_UnsuccessfullyTransmittedDataVolume */
+ if (dl_UnsuccessfullyTransmittedDataVolume_present)
+ {
+
+ if ((ret = dissect_dataVolumeList(tvb, ie_tree, &offset, &bitoffset,
+ "dl_UnsuccessfullyTransmittedDataVolume")) != 0)
+ return (ret);
+ }
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "IE_RAB_DataVolumeReportItem")) != 0)
+ return (ret);
+ }
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended enum */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for IE_RAB_DataVolumeReportItem present, dissection not supported");
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_RAB_SetupOrModifyItemSecond(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int extension_present;
+ int tmp_extension;
+ int pDP_TypeInformation_present;
+ int dataVolumeReportingIndication_present;
+ int dl_GTP_PDU_SequenceNumber_present;
+ int ul_GTP_PDU_SequenceNumber_present;
+ int dl_N_PDU_SequenceNumber_present;
+ int ul_N_PDU_SequenceNumber_present;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+ gint8 tmp_byte;
+ gint i;
+ int ret;
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "SetupOrModifyItemSecond Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* pDP_TypeInformation present ? */
+ pDP_TypeInformation_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_pDP_TypeInformation_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* dataVolumeReportingIndication present ? */
+ dataVolumeReportingIndication_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_dataVolumeReportingIndication_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* dl_GTP_PDU_SequenceNumber present present ? */
+ dl_GTP_PDU_SequenceNumber_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_dl_GTP_PDU_SequenceNumber_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+
+ /* ul_GTP_PDU_SequenceNumber present ? */
+ ul_GTP_PDU_SequenceNumber_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ul_GTP_PDU_SequenceNumber_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* dl_N_PDU_SequenceNumber present ? */
+ dl_N_PDU_SequenceNumber_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_dl_N_PDU_SequenceNumber_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* ul_N_PDU_SequenceNumber present ? */
+ ul_N_PDU_SequenceNumber_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ul_N_PDU_SequenceNumber_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* pDP-TypeInformation */
+ if (pDP_TypeInformation_present)
+ {
+ tmp_byte = extract_nbits(tvb, offset, bitoffset, 1) + 1; /* Sequence 1..2 */
+ proceed_nbits(&offset, &bitoffset, 1);
+ for (i=1; i<=tmp_byte; i++)
+ {
+ tmp_extension = extract_nbits(tvb, offset, bitoffset, 1);
+ proceed_nbits(&offset, &bitoffset, 1);
+ if (tmp_extension != 0)
+ {
+ /* extended enum */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for PDP-Type present, dissection not supported");
+ return(-1);
+ }
+
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_PDP_Type, tvb,
+ offset, bitoffset, 3, 0);
+ proceed_nbits(&offset, &bitoffset, 3);
+ }
+ }
+
+ /* dataVolumeReportingIndication */
+ if (dataVolumeReportingIndication_present)
+ {
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_dataVolumeReportingIndication, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+ }
+
+ /* dl-GTP-PDU-SequenceNumber */
+ if (dl_GTP_PDU_SequenceNumber_present)
+ {
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_dl_GTP_PDU_SequenceNumber, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /* ul-GTP-PDU-SequenceNumber */
+ if (ul_GTP_PDU_SequenceNumber_present)
+ {
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_ul_GTP_PDU_SequenceNumber, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /* dl-N-PDU-SequenceNumber */
+ if (dl_N_PDU_SequenceNumber_present)
+ {
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_dl_N_PDU_SequenceNumber, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /* ul-N-PDU-SequenceNumber */
+ if (ul_N_PDU_SequenceNumber_present)
+ {
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_ul_N_PDU_SequenceNumber, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "SetupOrModifyItemSecond")) != 0)
+ return (ret);
+ }
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended enum */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for SetupOrModifyItemSecond present, dissection not supported");
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_RAB_SetupOrModifiedItem (tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int ret;
+ int extension_present;
+ int transportLayerAddress_present;
+ int iuTransportAssociation_present;
+ int dl_dataVolumes_present;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "RAB-SetupOrModifiedItem Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* transportLayerAddress present ? */
+ transportLayerAddress_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_transportLayerAddress_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iuTransportAssociation present ? */
+ iuTransportAssociation_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iuTransportAssociation_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* dl_dataVolumes present ? */
+ dl_dataVolumes_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_dl_dataVolumes_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+
+ /* rAB-ID */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_rab_id,
+ tvb, offset, bitoffset, 8, 0);
+ proceed_nbits(&offset, &bitoffset, 8);
+
+ /* transportLayerAddress */
+ if (transportLayerAddress_present)
+ {
+ if ((ret=dissect_TransportLayerAddress(tvb, ie_tree, &offset, &bitoffset)) != 0)
+ return (ret);
+ }
+
+ /* iuTransportAssociation */
+ if (iuTransportAssociation_present)
+ {
+ if ((ret=dissect_iuTransportAssociation(tvb, ie_tree, &offset, &bitoffset)) != 0)
+ return (ret);
+ }
+
+ /* dl-dataVolumes */
+ if (dl_dataVolumes_present)
+ {
+ if ((ret = dissect_dataVolumeList(tvb, ie_tree, &offset, &bitoffset,
+ "dl-dataVolumes")) != 0)
+ return (ret);
+ }
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "RAB_SetupOrModifiedItem")) != 0)
+ return (ret);
+ }
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for RAB_SetupOrModifiedItem present, dissection not supported");
+ return(-1);
+ }
+ }
+
+ return (0);
+}
+
+
+static int
+dissect_IE_RAB_SetupOrModifyItemFirst (tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ gint offset;
+ gint bitoffset;
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int extension_present;
+ int nAS_SynchronisationIndicator_present;
+ int rAB_Parameters_present;
+ int userPlaneInformation_present;
+ int transportLayerInformation_present;
+ int service_Handover_present;
+ int iE_Extensions_present;
+ int tmp_extension_present;
+ int ret;
+
+ if (ie_tree)
+ {
+ offset = 0; bitoffset = 0;
+
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset,IE_PROTOCOL_EXTENSION_LENGTH,
+ "RAB_SetupOrModifyItemFirst Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* nAS_SynchronisationIndicator present ? */
+ nAS_SynchronisationIndicator_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_nAS_SynchronisationIndicator_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* rAB_Parameters present ? */
+ rAB_Parameters_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_rAB_Parameters_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* userPlaneInformation present ? */
+ userPlaneInformation_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_userPlaneInformation_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* transportLayerInformation present ? */
+ transportLayerInformation_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_transportLayerInformation_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* service_Handover present ? */
+ service_Handover_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_service_Handover_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+
+ /* add RAB-ID */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_rab_id,
+ tvb, offset, bitoffset, 8, 0);
+ proceed_nbits(&offset, &bitoffset, 8);
+
+ /* nAS-SynchronisationIndicator */
+ if (nAS_SynchronisationIndicator_present)
+ {
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_nAS_SynchronisationIndicator,
+ tvb, offset, bitoffset, 4, 0);
+ proceed_nbits(&offset, &bitoffset, 4);
+ }
+
+ /* rAB-Parameters */
+ if (rAB_Parameters_present)
+ {
+ if ((ret=dissect_rAB_Parameters(tvb, ie_tree, &offset, &bitoffset)) != 0)
+ return(ret);
+ }
+
+ /* userPlaneInformation */
+ if (userPlaneInformation_present)
+ {
+ if ((ret=dissect_userPlaneInformation(tvb, ie_tree, &offset, &bitoffset)) != 0)
+ return(ret);
+ }
+
+ /* transportLayerInformation */
+ if (transportLayerInformation_present)
+ {
+ if ((ret=dissect_transportLayerInformation(tvb, ie_tree, &offset, &bitoffset)) != 0)
+ return(ret);
+ }
+
+ /* service_Handover */
+ if (service_Handover_present)
+ {
+ tmp_extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ if (tmp_extension_present)
+ {
+ /* extended enum */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for service_Handover present, dissection not supported");
+ return(-1);
+ }
+
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_service_Handover,
+ tvb, offset, bitoffset, 2, 0);
+ proceed_nbits(&offset, &bitoffset, 2);
+ }
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "SetupOrModifyItemFirst" )) != 0)
+ return(ret);
+ }
+
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_RAB_ReleaseItem(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ gint offset = 0;
+ gint bitoffset = 0;
+ int extension_present;
+ int iE_Extensions_present;
+ int ret;
+
+
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset,IE_PROTOCOL_EXTENSION_LENGTH,
+ "RAB_ReleaseItem Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+
+ /* add RAB-ID */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_rab_id,
+ tvb, offset, bitoffset, 8, 0);
+ proceed_nbits(&offset, &bitoffset, 8);
+
+
+ /* add cause */
+ if ((ret=dissect_cause(tvb, ie_tree, &offset, &bitoffset)) != 0)
+ return (ret);
+
+ /* iE Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "RAB_ReleasedItem")) != 0)
+ return (ret);
+ }
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for RAB_ReleasedItem present, dissection not supported");
+ return(-1);
+ }
+
+ return(0);
+}
+
+
+static int
+dissect_IE_RAB_ReleasedItem (tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int ret;
+ int extension_present;
+ int dl_dataVolumes_present;
+ int dl_GTP_PDU_SequenceNumber_present;
+ int ul_GTP_PDU_SequenceNumber_present;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "RAB-ReleasedItem Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* dl_dataVolumes present ? */
+ dl_dataVolumes_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_dl_dataVolumes_present, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* dL_GTP_PDU_SequenceNumber present ? */
+ dl_GTP_PDU_SequenceNumber_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_dl_GTP_PDU_SequenceNumber_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* uL_GTP_PDU_SequenceNumber present ? */
+ ul_GTP_PDU_SequenceNumber_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ul_GTP_PDU_SequenceNumber_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* rAB-ID */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_rab_id,
+ tvb, offset, bitoffset, 8, 0);
+ proceed_nbits(&offset, &bitoffset, 8);
+
+ /* dl-dataVolumes */
+ if (dl_dataVolumes_present)
+ {
+ if ((ret=dissect_dataVolumeList(tvb, ie_tree, &offset, &bitoffset,
+ "dl-dataVolumes")) != 0)
+ return (ret);
+ }
+
+ /* dL-GTP-PDU-SequenceNumber */
+ if (dl_GTP_PDU_SequenceNumber_present)
+ {
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_dl_GTP_PDU_SequenceNumber, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /* uL-GTP-PDU-SequenceNumber */
+ if (ul_GTP_PDU_SequenceNumber_present)
+ {
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_ul_GTP_PDU_SequenceNumber, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "UserPlaneInformation")) != 0)
+ return(ret);
+ }
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for RAB_ReleasedItem present, dissection not supported");
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+
+static int
+dissect_IE_RAB_QueuedItem (tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int ret;
+ int extension_present;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "RAB-QueuedItem Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* rAB-ID */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_rab_id,
+ tvb, offset, bitoffset, 8, 0);
+ proceed_nbits(&offset, &bitoffset, 8);
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "RAB_QueuedItem" )) != 0 )
+ return (ret);
+ }
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for RAB_QueuedItem present, dissection not supported");
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+
+static int
+dissect_IE_RAB_FailedItem(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int ret;
+ int extension_present;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "RAB-FailedItem Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* rAB-ID */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_rab_id,
+ tvb, offset, bitoffset, 8, 0);
+ proceed_nbits(&offset, &bitoffset, 8);
+
+ /* cause */
+ if ((ret=dissect_cause(tvb, ie_tree, &offset, &bitoffset)) != 0)
+ return (ret);
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "RAB-FailedItem")) != 0)
+ return (ret);
+ }
+
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for RAB-FailedItem present, dissection not supported");
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+
+static int
+dissect_IE_CriticalityDiagnostics(tvbuff_t *tvb, proto_tree *ie_tree)
+
+{
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+ int ret;
+ int extension_present;
+ int procedureCode_present;
+ int triggeringMessage_present;
+ int procedureCriticality_present;
+ int iEsCriticalityDiagnostics_present;
+ int iE_Extensions_present;
+ gint offset = 0;
+ gint bitoffset = 0;
+
+
+ if (ie_tree)
+ {
+ /* create subtree for extension/optional/default bitmap */
+ optionals_item = proto_tree_add_text(ie_tree, tvb, offset, 1,
+ "IE-CriticalityDiagnostics Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ie_protocol_extension, tvb,
+ offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* procedureCode present ? */
+ procedureCode_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_procedureCode_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* triggeringMessage present ? */
+ triggeringMessage_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_triggeringMessage_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* procedureCriticality present ? */
+ procedureCriticality_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_procedureCriticality_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iEsCriticalityDiagnostics present ? */
+ iEsCriticalityDiagnostics_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iEsCriticalityDiagnostics_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* iE_Extensions present ? */
+ iE_Extensions_present = extract_nbits(tvb, offset, bitoffset, 1);
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_iE_Extensions_present,
+ tvb, offset, bitoffset, 1, 0);
+ proceed_nbits(&offset, &bitoffset, 1);
+
+
+ /* procedureCode */
+ if (procedureCode_present)
+ {
+ allign (&offset, &bitoffset);
+ proto_tree_add_item(ie_tree, hf_ranap_procedure_code, tvb, offset, 1, FALSE);
+ offset += 1;
+ }
+
+ /* triggeringMessage */
+ if (triggeringMessage_present)
+ {
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_triggeringMessage,
+ tvb, offset, bitoffset, 2, 0);
+ proceed_nbits(&offset, &bitoffset, 2);
+ }
+
+ /* procedureCriticality */
+ if (procedureCriticality_present)
+ {
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_procedureCriticality,
+ tvb, offset, bitoffset, 2, 0);
+ proceed_nbits(&offset, &bitoffset, 2);
+ }
+
+ /* iEsCriticalityDiagnostics */
+ if (iEsCriticalityDiagnostics_present)
+ {
+ if ((ret=dissect_iEsCriticalityDiagnostics(tvb, ie_tree, &offset, &bitoffset)) != 0)
+ return(ret);
+ }
+
+ /* iE-Extensions */
+ if (iE_Extensions_present)
+ {
+ if ((ret=dissect_iE_Extension(tvb, ie_tree, &offset, &bitoffset, "IE_CriticalityDiagnostics")) != 0)
+ return(ret);
+ }
+
+
+ /* protocol extended */
+ if (extension_present)
+ {
+ /* extended sequence */
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset, IE_PROTOCOL_EXTENSION_LENGTH,
+ "Protocol extension for IE CriticalityDiagnostics present, dissection not supported");
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+
+static int
+dissect_unknown_IE(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ if (ie_tree)
+ {
+ proto_tree_add_text(ie_tree, tvb, 0, -1,
+ "IE Contents (dissection not implemented)");
+ }
+ return(0);
+}
+
+
+
+/*****************************************************************************/
+/* */
+/* Dissecting Functions for IE Lists / Containers */
+/* */
+/*****************************************************************************/
+
+static int
+dissect_RAB_IE_ContainerPairList(tvbuff_t *tvb, proto_tree *ie_tree)
+{
+ proto_item *rab_item = NULL;
+ proto_tree *rab_tree = NULL;
+ proto_item *ie_pair_item = NULL;
+ proto_tree *ie_pair_tree = NULL;
+ proto_item *first_value_item = NULL;
+ proto_tree *first_value_tree = NULL;
+ proto_item *second_value_item = NULL;
+ proto_tree *second_value_tree = NULL;
+ guint number_of_RABs, currentRAB;
+ guint number_of_IEs, currentIE;
+ gint number_of_octets_first, number_of_octets_second;
+ gint number_of_octets_first_size, number_of_octets_second_size ;
+ gint offset = 0;
+ gint bitoffset = 0;
+ gint tmp_offset;
+ guint16 ie_id;
+ tvbuff_t *first_value_tvb;
+ tvbuff_t *second_value_tvb;
+
+ if (ie_tree)
+ {
+ /* number of RABs in the list */
+ number_of_RABs = 1 + tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(ie_tree, hf_ranap_num_rabs,
+ tvb, offset,
+ NUM_RABS_LENGTH, number_of_RABs);
+
+ offset += NUM_RABS_LENGTH;
+
+ /* do for each RAB */
+ for (currentRAB=1; currentRAB<=number_of_RABs; currentRAB++)
+ {
+ /* create subtree for RAB */
+ rab_item = proto_tree_add_text(ie_tree, tvb, offset, 0, "%d. RAB", currentRAB);
+ rab_tree = proto_item_add_subtree(rab_item, ett_ranap_rab);
+
+ /* number of IE pairs for this RAB */
+ number_of_IEs = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(rab_tree, hf_ranap_number_of_ies_in_list,
+ tvb, offset, 2, number_of_IEs);
+
+ offset += 2; /*points now to beginning of first IE pair */
+
+ /* do for each IE pair */
+ for (currentIE=1; currentIE<=number_of_IEs; currentIE++)
+ {
+ /* use tmp_offset to point to current field */
+ tmp_offset = offset;
+ /* IE pair ID */
+ ie_id = tvb_get_ntohs(tvb, tmp_offset);
+ tmp_offset += IE_ID_LENGTH;
+
+ tmp_offset += 1; /* skip first criticality byte */
+ /* number of octets in first value */
+ extract_length(tvb, tmp_offset, &number_of_octets_first, &number_of_octets_first_size);
+ tmp_offset += number_of_octets_first_size + number_of_octets_first;
+
+ tmp_offset += 1; /* skip second criticality byte */
+ /* number of octets in second value */
+ extract_length(tvb, tmp_offset, &number_of_octets_second, &number_of_octets_second_size);
+ tmp_offset += number_of_octets_second_size + number_of_octets_second;
+
+ /* create subtree for ie_pair */
+ ie_pair_item = proto_tree_add_text(rab_tree, tvb, offset,
+ tmp_offset - offset,
+ "%s IE Pair (%u)",
+ val_to_str(ie_id, ranap_ie_id_values, "Unknown"),
+ ie_id);
+ ie_pair_tree = proto_item_add_subtree(ie_pair_item, ett_ranap_ie_pair);
+
+ /* add fields to ie pair subtee */
+ /* use offset to point to current field */
+ /* IE ID */
+ proto_tree_add_item(ie_pair_tree, hf_ranap_ie_ie_id, tvb, offset, IE_ID_LENGTH, FALSE);
+ offset += IE_ID_LENGTH;
+
+ /* first criticality */
+ proto_tree_add_uint_bits(ie_pair_tree, hf_ranap_ie_pair_first_criticality, tvb,
+ offset, bitoffset, 2, 0);
+ proceed_nbits(&offset, &bitoffset, 2);
+
+ /* number of octets in first value */
+ allign(&offset, &bitoffset);
+ if (number_of_octets_first != 0)
+ {
+ proto_tree_add_uint(ie_pair_tree, hf_ranap_first_value_number_of_octets,
+ tvb, offset,
+ number_of_octets_first_size,
+ number_of_octets_first);
+ }
+ else
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(ie_pair_tree, tvb, offset,
+ 2, "Number of Octets greater than 0x3FFF, dissection not supported");
+ return(-1);
+ }
+ offset += number_of_octets_first_size;
+
+ /* add subtree for first value */
+ first_value_item = proto_tree_add_text(ie_pair_tree, tvb, offset,
+ number_of_octets_first,
+ "%sFirst",
+ val_to_str(ie_id, ranap_ie_id_values, "Unknown"));
+ first_value_tree = proto_item_add_subtree(first_value_item, ett_ranap_ie_pair_first_value);
+
+ /* create tvb containing first value */
+ first_value_tvb = tvb_new_subset(tvb, offset, number_of_octets_first, number_of_octets_first);
+
+ /* add fields of first value */
+ switch (ie_id)
+ {
+ case IE_RAB_SetupOrModifyItem:
+ dissect_IE_RAB_SetupOrModifyItemFirst (first_value_tvb, first_value_tree);
+ break;
+
+ default:
+ dissect_unknown_IE(first_value_tvb, first_value_tree);
+ break;
+ }
+
+ offset += number_of_octets_first;
+
+
+ /* second criticality */
+ proto_tree_add_uint_bits(ie_pair_tree, hf_ranap_ie_pair_second_criticality, tvb,
+ offset, bitoffset, 2, 0);
+ proceed_nbits(&offset, &bitoffset, 2);
+
+ /* number of octets of second value */
+ allign(&offset, &bitoffset);
+ if (number_of_octets_second != 0)
+ {
+ proto_tree_add_uint(ie_pair_tree, hf_ranap_second_value_number_of_octets,
+ tvb, offset,
+ number_of_octets_second_size,
+ number_of_octets_second);
+ }
+ else
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(ie_pair_tree, tvb, offset,
+ 2, "Number of Octets greater than 0x3FFF, dissection not supported");
+ return(-1);
+ }
+ offset += number_of_octets_second_size;
+
+ /* add subtree for second value */
+ second_value_item = proto_tree_add_text(ie_pair_tree, tvb, offset,
+ number_of_octets_second,
+ "%sSecond",
+ val_to_str(ie_id, ranap_ie_id_values, "Unknown"));
+ second_value_tree = proto_item_add_subtree(second_value_item, ett_ranap_ie_pair_second_value);
+
+ /* create tvb containing first value */
+ second_value_tvb = tvb_new_subset(tvb, offset, number_of_octets_second, number_of_octets_second);
+
+ /* add fields of second value */
+ switch (ie_id)
+ {
+ case IE_RAB_SetupOrModifyItem:
+ dissect_IE_RAB_SetupOrModifyItemSecond (second_value_tvb, second_value_tree);
+ break;
+
+ default:
+ dissect_unknown_IE(second_value_tvb, second_value_tree);
+ break;
+ }
+
+ offset += number_of_octets_second;
+
+ }/* for each IE ... */
+ }/* for each RAB ... */
+ }
+ return(0);
+}
+
+
+static int
+dissect_RAB_IE_ContainerList(tvbuff_t *tvb, proto_tree *list_tree)
+{
+ proto_item *rab_item = NULL;
+ proto_tree *rab_tree = NULL;
+ proto_item *ie_item = NULL;
+ proto_tree *ie_tree = NULL;
+
+ guint number_of_RABs, currentRAB;
+ guint number_of_IEs, currentIE;
+ gint ie_number_of_octets = 0;
+ gint ie_number_of_octets_size = 0;
+ gint offset = 0;
+ gint bitoffset = 0;
+ gint ie_offset = 0;
+ gint ie_header_length;
+ guint16 ie_id;
+ tvbuff_t *ie_tvb;
+
+
+ if (list_tree)
+ {
+ /* number of RABs in the list */
+ number_of_RABs = 1 + tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(list_tree, hf_ranap_num_rabs,
+ tvb, offset,
+ NUM_RABS_LENGTH, number_of_RABs);
+
+ offset += NUM_RABS_LENGTH;
+
+ /* do for each RAB */
+ for (currentRAB=1; currentRAB<=number_of_RABs; currentRAB++)
+ {
+ /* create subtree for RAB */
+ rab_item = proto_tree_add_text(list_tree, tvb, offset, 0, "%d. RAB", currentRAB);
+ rab_tree = proto_item_add_subtree(rab_item, ett_ranap_rab);
+
+ /* number of IEs for this RAB */
+ number_of_IEs = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(rab_tree, hf_ranap_number_of_ies_in_list,
+ tvb, offset, 2, number_of_IEs);
+
+ offset += 2; /*points now to beginning of first IE in list */
+ ie_offset = offset;
+
+ /* do for each IE */
+ for (currentIE=1; currentIE<=number_of_IEs; currentIE++)
+ {
+ /* extract IE ID */
+ ie_id = tvb_get_ntohs(tvb, offset);
+ offset += IE_ID_LENGTH;
+
+ offset += IE_CRITICALITY_LENGTH; /* skip criticality byte */
+
+ /* number of octets */
+ extract_length(tvb, offset, &ie_number_of_octets, &ie_number_of_octets_size);
+ ie_header_length = IE_ID_LENGTH + IE_CRITICALITY_LENGTH + ie_number_of_octets_size;
+
+ /* reset offset to beginning of ie */
+ offset = ie_offset;
+
+ /* create subtree for ie */
+ ie_item = proto_tree_add_text(rab_tree, tvb, offset,
+ ie_header_length + ie_number_of_octets,
+ "%s IE (%u)",
+ val_to_str(ie_id, ranap_ie_id_values, "Unknown"),
+ ie_id);
+ ie_tree = proto_item_add_subtree(ie_item, ett_ranap_ie);
+
+ /* IE ID */
+ proto_tree_add_item(ie_tree, hf_ranap_ie_ie_id, tvb,
+ offset, IE_ID_LENGTH, FALSE);
+ offset += IE_ID_LENGTH;
+
+ /* criticality */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_ie_criticality, tvb,
+ offset, bitoffset, 2, 0);
+ proceed_nbits(&offset, &bitoffset, 2);
+
+ allign(&offset, &bitoffset);
+ if (ie_number_of_octets != 0)
+ {
+ proto_tree_add_uint(ie_tree, hf_ranap_ie_number_of_octets, tvb,
+ offset, ie_number_of_octets_size, ie_number_of_octets);
+ }
+ else
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(ie_tree, tvb, offset,
+ 0, "Number of Octets greater than 0x3FFF, dissection not supported");
+ return(-1);
+ }
+ offset += ie_number_of_octets_size;
+
+
+ /* create tvb containing ie */
+ ie_tvb = tvb_new_subset(tvb, offset, ie_number_of_octets, ie_number_of_octets);
+
+ /* add fields of ie */
+ switch (ie_id)
+ {
+ case IE_RAB_SetupOrModifiedItem:
+ dissect_IE_RAB_SetupOrModifiedItem(ie_tvb, ie_tree);
+ break;
+ case IE_RAB_ReleaseItem:
+ dissect_IE_RAB_ReleaseItem(ie_tvb, ie_tree);
+ break;
+ case IE_RAB_ReleasedItem:
+ dissect_IE_RAB_ReleasedItem(ie_tvb, ie_tree);
+ break;
+ case IE_RAB_ReleasedItem_IuRelComp:
+ dissect_IE_RAB_ReleasedItem_IuRelComp(ie_tvb, ie_tree);
+ break;
+ case IE_RAB_QueuedItem:
+ dissect_IE_RAB_QueuedItem(ie_tvb, ie_tree);
+ break;
+ case IE_RAB_FailedItem:
+ dissect_IE_RAB_FailedItem(ie_tvb, ie_tree);
+ break;
+ case IE_RAB_DataVolumeReportItem:
+ dissect_IE_RAB_DataVolumeReportItem(ie_tvb, ie_tree);
+ break;
+ default:
+ dissect_unknown_IE(ie_tvb, ie_tree);
+ break;
+ }
+
+ ie_offset += (ie_header_length + ie_number_of_octets);
+ offset = ie_offset;
+ } /* for each IE */
+ } /* for each RAB */
+ }
+ return (0);
+}
+
+
+static int
+dissect_ranap_ie(guint16 ie_id, tvbuff_t *ie_contents_tvb, proto_tree *ie_tree)
+{
+ /* call specific dissection function for ie contents */
+ switch(ie_id)
+ {
+ case IE_RAB_ID:
+ return(dissect_IE_RAB_ID(ie_contents_tvb, ie_tree));
+ break;
+ case IE_NAS_PDU:
+ return(dissect_IE_NAS_PDU(ie_contents_tvb, ie_tree));
+ break;
+ case IE_LAI:
+ return(dissect_IE_LAI(ie_contents_tvb, ie_tree));
+ break;
+ case IE_RAC:
+ return(dissect_IE_RAC(ie_contents_tvb, ie_tree));
+ break;
+ case IE_SAI:
+ return(dissect_IE_SAI(ie_contents_tvb, ie_tree));
+ break;
+ case IE_GlobalRNC_ID:
+ return(dissect_IE_GlobalRNC_ID(ie_contents_tvb, ie_tree));
+ break;
+ case IE_CN_DomainIndicator:
+ return(dissect_IE_CN_DomainIndicator(ie_contents_tvb, ie_tree));
+ break;
+ case IE_IuSigConId:
+ return(dissect_IE_IuSigConId(ie_contents_tvb, ie_tree));
+ break;
+ case IE_SAPI:
+ return(dissect_IE_SAPI(ie_contents_tvb, ie_tree));
+ break;
+ case IE_TransportLayerAddress:
+ return(dissect_IE_TransportLayerAddress(ie_contents_tvb, ie_tree));
+ break;
+ case IE_IuTransportAssociation:
+ return(dissect_IE_IuTransportAssociation(ie_contents_tvb, ie_tree));
+ break;
+ case IE_RAB_SetupOrModifyList:
+ return(dissect_RAB_IE_ContainerPairList(ie_contents_tvb, ie_tree));
+ break;
+ case IE_RAB_SetupOrModifiedList:
+ case IE_RAB_ReleaseList:
+ case IE_RAB_ReleasedList:
+ case IE_RAB_QueuedList:
+ case IE_RAB_FailedList:
+ case IE_RAB_ReleaseFailedList:
+ case IE_RAB_DataVolumeReportList:
+ case IE_RAB_ReleasedList_IuRelComp:
+ case IE_RAB_RelocationReleaseList:
+ case IE_RAB_DataForwardingList:
+ case IE_RAB_SetupList_RelocReq:
+ case IE_RAB_SetupList_RelocReqAck:
+ case IE_RAB_DataForwardingList_SRNS_CtxReq:
+ case IE_RAB_ContextList:
+ case IE_RAB_ContextFailedtoTransferList:
+ case IE_RAB_DataVolumeReportRequestList:
+ case IE_RAB_FailedtoReportList:
+ case IE_RAB_ContextList_RANAP_RelocInf:
+ return(dissect_RAB_IE_ContainerList(ie_contents_tvb, ie_tree));
+ break;
+ case IE_CriticalityDiagnostics:
+ return(dissect_IE_CriticalityDiagnostics(ie_contents_tvb, ie_tree));
+ break;
+ case IE_Cause:
+ return(dissect_IE_Cause(ie_contents_tvb, ie_tree));
+ break;
+ default:
+ return(dissect_unknown_IE(ie_contents_tvb, ie_tree));
+ break;
+ }
+}
+
+
+static int
+dissect_ranap_ie_container(tvbuff_t *tvb, proto_tree *ranap_tree)
+{
+ proto_item *ie_item = NULL;
+ proto_tree *ie_tree = NULL;
+ proto_item *optionals_item = NULL;
+ proto_tree *optionals_tree = NULL;
+
+ int msg_extension_present;
+ int ProtocolExtensionContainer_present;
+
+ guint16 number_of_ies;
+ guint16 ie_id;
+ gint ie_number_of_octets = 0;
+ gint ie_number_of_octets_size = 0;
+ guint16 ie_header_length;
+ gint offset = 0;
+ gint bitoffset = 0;
+ gint i, ie_offset;
+ tvbuff_t *ie_contents_tvb;
+
+ if (ranap_tree)
+ {
+ /* create subtree for extension/optional bitmap of message */
+ optionals_item = proto_tree_add_text(ranap_tree, tvb, offset, 1,
+ "Message Extension/Optional/Default bitmap");
+ optionals_tree = proto_item_add_subtree(optionals_item, ett_ranap_optionals);
+ }
+
+ /* msg_extension present ? */
+ msg_extension_present = extract_nbits(tvb, offset, bitoffset, 1);
+
+ if (ranap_tree)
+ {
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_msg_extension_present, tvb,
+ offset, bitoffset, 1, 0);
+ }
+ proceed_nbits(&offset, &bitoffset, 1);
+
+ /* ProtocolExtensionContainer present ? */
+ ProtocolExtensionContainer_present = extract_nbits(tvb, offset, bitoffset, 1);
+ if (ranap_tree)
+ {
+ proto_tree_add_uint_bits(optionals_tree, hf_ranap_ProtocolExtensionContainer_present,
+ tvb, offset, bitoffset, 1, 0);
+ }
+ proceed_nbits(&offset, &bitoffset, 1);
+
+
+ /* extract ie container data */
+ /* number of ies */
+ allign(&offset, &bitoffset);
+ number_of_ies = tvb_get_ntohs(tvb, offset);
+ if (ranap_tree)
+ {
+ proto_tree_add_uint(ranap_tree, hf_ranap_number_of_ies,
+ tvb, offset, 2, number_of_ies);
+ }
+ offset += 2;
+
+ ie_offset = offset; /* ie_offset marks beginning of IE-Header */
+
+ /* do the following for each IE in the PDU */
+ for (i=1; i <= number_of_ies; i++)
+ {
+ /* extract IE header fields which are needed even if no ranap tree exists*/
+ /* IE-ID */
+ ie_id = tvb_get_ntohs(tvb, offset);
+ offset += IE_ID_LENGTH;
+
+ /* number of octets in the IE */
+ offset += IE_CRITICALITY_LENGTH; /* skip criticality byte */
+ ie_number_of_octets = 0;
+ extract_length(tvb, offset, &ie_number_of_octets, &ie_number_of_octets_size);
+ ie_header_length = IE_ID_LENGTH + IE_CRITICALITY_LENGTH + ie_number_of_octets_size;
+
+ if (ranap_tree)
+ {
+ offset = ie_offset; /* start from beginning of IE */
+ /* create subtree for ie */
+ ie_item = proto_tree_add_text(ranap_tree, tvb, offset,
+ ie_header_length + ie_number_of_octets,
+ "%s IE (%u)",
+ val_to_str(ie_id, ranap_ie_id_values, "Unknown"),
+ ie_id);
+ ie_tree = proto_item_add_subtree(ie_item, ett_ranap_ie);
+
+ /* add fields to ie subtee */
+ /* IE ID */
+ proto_tree_add_item(ie_tree, hf_ranap_ie_ie_id, tvb,
+ offset, IE_ID_LENGTH, FALSE);
+ offset += IE_ID_LENGTH;
+
+ /* criticality */
+ proto_tree_add_uint_bits(ie_tree, hf_ranap_ie_criticality, tvb,
+ offset, bitoffset, 2, 0);
+ proceed_nbits(&offset, &bitoffset, 2);
+
+ /* number of octets */
+ allign(&offset, &bitoffset);
+ if (ie_number_of_octets != 0)
+ {
+ proto_tree_add_uint(ie_tree, hf_ranap_ie_number_of_octets, tvb,
+ offset, ie_number_of_octets_size, ie_number_of_octets);
+ offset += ie_number_of_octets_size;
+ }
+ else
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(ranap_tree, tvb, offset,
+ 2, "Number of Octets greater than 0x3FFF, dissection not supported");
+ return(-1);
+ }
+ }
+
+ /* check if number_of_octets could be decoded */
+ /* in case we skipped if (ranap_tree) {....} */
+ if (ie_number_of_octets == 0) return (-1);
+
+ /* create tvb containing the ie contents */
+ ie_contents_tvb = tvb_new_subset(tvb, ie_offset + ie_header_length,
+ ie_number_of_octets, ie_number_of_octets);
+
+ /* call specific dissection function for ie contents */
+ dissect_ranap_ie(ie_id, ie_contents_tvb, ie_tree);
+
+ /* set ie_offset to beginning of next ie */
+ ie_offset += (ie_header_length + ie_number_of_octets);
+ offset = ie_offset;
+ }
+
+ /* protocol Extensions */
+ if (ProtocolExtensionContainer_present)
+ {
+ return(dissect_iE_Extension(tvb, ranap_tree, &offset, &bitoffset, "PDU"));
+ }
+
+ return(0);
+
+}
+
+
+static void
+dissect_ranap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ranap_item = NULL;
+ proto_tree *ranap_tree = NULL;
+
+ guint procedure_code;
+ guint pdu_index;
+ gint number_of_octets = 0;
+ gint number_of_octets_size = 0;
+ gint offset = 0;
+ gint tmp_offset = 0;
+ gint bitoffset = 0;
+ gint tmp_bitoffset = 0;
+ guint extension_present;
+
+ tvbuff_t *ie_tvb;
+
+
+ g_pinfo = pinfo;
+
+ /* make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RANAP");
+
+ /* extract header fields which are needed even if no tree exists */
+
+ /* protocol_extension present ? */
+ extension_present = extract_nbits(tvb, tmp_offset, tmp_bitoffset, 1);
+ proceed_nbits(&tmp_offset, &tmp_bitoffset, 1);
+ if (extension_present)
+ {
+ /* extended choice */
+ /* decoding is not supported */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, "RANAP-PDU Protocol extension present, dissection not supported");
+ }
+
+ if (tree)
+ {
+ proto_tree_add_text(tree, tvb, 0, -1, "RANAP Message");
+ }
+ return;
+ }
+
+ /* pdu_index choice 0..3 */
+ pdu_index = extract_nbits(tvb, tmp_offset, tmp_bitoffset, 2);
+ proceed_nbits(&tmp_offset, &tmp_bitoffset, 2);
+
+ /* procedure code */
+ allign(&tmp_offset, &tmp_bitoffset);
+ procedure_code = tvb_get_guint8(tvb, tmp_offset);
+ tmp_offset += 1;
+
+ /* add Procedure Code to Info Column */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ if (procedure_code <= PC_max)
+ {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(pdu_index, ranap_message_names[procedure_code],
+ "unknown message"));
+ }
+ }
+
+ /* extract number of octets */
+ tmp_offset += 1; /* leave out criticality byte */
+ extract_length(tvb, tmp_offset, &number_of_octets, &number_of_octets_size);
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree)
+ {
+ g_tree = tree;
+
+ /* create the ranap protocol tree */
+ ranap_item = proto_tree_add_item(tree, proto_ranap, tvb, 0, -1, FALSE);
+ ranap_tree = proto_item_add_subtree(ranap_item, ett_ranap);
+
+ /* Add fields to ranap protocol tree */
+ /* PDU Index */
+ proceed_nbits(&offset, &bitoffset, 1); /* leave out extension bit, checked above */
+ proto_tree_add_uint_bits(ranap_tree, hf_ranap_pdu_index, tvb,
+ offset, bitoffset, 2, 0);
+ proceed_nbits(&offset, &bitoffset, 2);
+
+
+ /* Procedure Code */
+ allign(&offset, &bitoffset);
+ proto_tree_add_item(ranap_tree, hf_ranap_procedure_code, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* PDU Criticality */
+ proto_tree_add_uint_bits(ranap_tree, hf_ranap_pdu_criticality, tvb,
+ offset, bitoffset, 2, 0);
+ proceed_nbits(&offset, &bitoffset, 2);
+
+ /* number of octets */
+ allign(&offset, &bitoffset);
+ if (number_of_octets != 0)
+ {
+ proto_tree_add_uint(ranap_tree, hf_ranap_pdu_number_of_octets,
+ tvb, offset,
+ number_of_octets_size, number_of_octets);
+ offset += number_of_octets_size;
+ }
+ else
+ {
+ /* decoding is not supported */
+ proto_tree_add_text(ranap_tree, tvb, offset,
+ 2, "Number of Octets greater than 0x3FFF, dissection not supported");
+ return;
+ }
+ }
+
+ /* set offset to the beginning of ProtocolIE-Container */
+ /* in case we skipped "if(tree){...}" above */
+ offset = PDU_NUMBER_OF_OCTETS_OFFSET + number_of_octets_size;
+
+ /* create a tvb containing the remainder of the PDU */
+ ie_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ /* dissect the ies */
+ dissect_ranap_ie_container(ie_tvb, ranap_tree);
+}
+
+
+static gboolean
+dissect_sccp_ranap_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 temp;
+
+ /* Is it a ranap packet?
+ *
+ * 4th octet should be the length of the rest of the message.
+ * note: I believe the length octet may actually be represented
+ * by more than one octet. Something like...
+ * bit 01234567 octets
+ * 0xxxxxxx 1
+ * 10xxxxxx xxxxxxxx 2
+ * For now, we have ignored this. I hope that's safe.
+ *
+ * 2nd octet is the message-type e Z[0, 28]
+ * (obviously there must be at least four octets)
+ *
+ * If both hold true we'll assume its RANAP
+ */
+
+ #define LENGTH_OFFSET 3
+ #define MSG_TYPE_OFFSET 1
+ if (tvb_length(tvb) < 4) { return FALSE; }
+ if (tvb_get_guint8(tvb, LENGTH_OFFSET) != (tvb_length(tvb) - 4)) { return FALSE; }
+ temp = tvb_get_guint8(tvb, MSG_TYPE_OFFSET);
+ if (temp > 28) { return FALSE; }
+
+ dissect_ranap(tvb, pinfo, tree);
+
+ return TRUE;
+}
+
+
+/*****************************************************************************/
+/* */
+/* Protocol Registration Functions */
+/* */
+/*****************************************************************************/
+
+void
+proto_register_ranap(void)
+{
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_ranap_pdu_index,
+ { "RANAP-PDU Index",
+ "ranap.ranap_pdu_index",
+ FT_UINT8, BASE_HEX, VALS(&ranap_pdu_index_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_procedure_code,
+ { "Procedure Code",
+ "ranap.procedure_code",
+ FT_UINT8, BASE_DEC, VALS(&ranap_procedure_code_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_pdu_criticality,
+ { "Criticality of PDU",
+ "ranap.pdu.criticality",
+ FT_UINT8, BASE_HEX, VALS(&ranap_criticality_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_pdu_number_of_octets,
+ { "Number of Octets in PDU",
+ "ranap.pdu.num_of_octets",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ie_protocol_extension,
+ { "Protocol Extension",
+ "ranap.ie.protocol_extension_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_number_of_ies,
+ { "Number of IEs in PDU",
+ "ranap.pdu.number_of_ies",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_number_of_ies_in_list,
+ { "Number of IEs in list",
+ "ranap.number_of_ies",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ie_ie_id,
+ { "IE-ID",
+ "ranap.ie.ie_id",
+ FT_UINT16, BASE_DEC, VALS(&ranap_ie_id_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ext_field_id,
+ { "ProtocolExtensionField ID",
+ "ranap.ie.ProtocolExtensionFields.Id",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ie_criticality,
+ { "Criticality of IE",
+ "ranap.ie.criticality",
+ FT_UINT8, BASE_HEX, VALS(&ranap_criticality_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ext_field_criticality,
+ { "Criticality of ProtocolExtensionField",
+ "ranap.ie.ProtocolExtensionFields.criticality",
+ FT_UINT8, BASE_HEX, VALS(&ranap_criticality_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ie_pair_first_criticality,
+ { "First Criticality",
+ "ranap.ie_pair.first_criticality",
+ FT_UINT8, BASE_HEX, VALS(&ranap_criticality_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ie_pair_second_criticality,
+ { "Second Criticality",
+ "ranap.ie_pair.second_criticality",
+ FT_UINT8, BASE_HEX, VALS(&ranap_criticality_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ie_number_of_octets,
+ { "Number of Octets in IE",
+ "ranap.ie.number_of_octets",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_first_value_number_of_octets,
+ { "Number of Octets in first value",
+ "ranap.ie_pair.first_value.number_of_octets",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_second_value_number_of_octets,
+ { "Number of Octets in second value",
+ "ranap.ie_pair.second_value.number_of_octets",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_rab_id,
+ { "RAB-ID",
+ "ranap.RAB_ID",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_nas_pdu,
+ { "NAS-PDU",
+ "ranap.NAS_PDU",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_extension_field,
+ { "Extension Field Value",
+ "ranap.Extension_Field_Value",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_plmn_id,
+ { "PLMN-ID",
+ "ranap.PLMN_ID",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_lac,
+ { "LAC",
+ "ranap.LAC",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_sac,
+ { "SAC",
+ "ranap.SAC",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_rac,
+ { "RAC",
+ "ranap.RAC",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_num_rabs,
+ { "Number of RABs",
+ "ranap.number_of_RABs",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_nAS_SynchronisationIndicator_present,
+ { "nAS-SynchronisationIndicator",
+ "ranap.nAS-SynchronisationIndicator_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_rAB_Parameters_present,
+ { "rAB-Parameters",
+ "ranap.rAB_Parameters_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_userPlaneInformation_present,
+ { "userPlaneInformation",
+ "ranap.userPlaneInformation_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_transportLayerInformation_present,
+ { "transportLayerInformation",
+ "ranap.transportLayerInformation_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_service_Handover_present,
+ { "service-Handover",
+ "ranap.service_Handover_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_iE_Extensions_present,
+ { "iE-Extensions",
+ "ranap.ie.iE-Extensions_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_nAS_SynchronisationIndicator,
+ { "nAS-SynchronisationIndicator",
+ "ranap.nAS-SynchronisationIndicator",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_guaranteedBitRate_present,
+ { "guaranteedBitRate",
+ "ranap.guaranteedBitRate_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_transferDelay_present,
+ { "transferDelay",
+ "ranap.transferDelay_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_trafficHandlingPriority_present,
+ { "trafficHandlingPriority",
+ "ranap.trafficHandlingPriority_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_allocationOrRetentionPriority_present,
+ { "allocationOrRetentionPriority",
+ "ranap.allocationOrRetentionPriority_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_sourceStatisticsDescriptor_present,
+ { "sourceStatisticsDescriptor",
+ "ranap.sourceStatisticsDescriptor_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_relocationRequirement_present,
+ { "relocationRequirement",
+ "ranap.relocationRequirement_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_trafficClass,
+ { "Traffic Class",
+ "ranap.rab_Parameters.trafficClass",
+ FT_UINT8, BASE_DEC, VALS(&ranap_trafficClass_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_rAB_AsymmetryIndicator,
+ { "rAB_AsymmetryIndicator",
+ "ranap.rab_Parameters.rAB_AsymmetryIndicator",
+ FT_UINT8, BASE_DEC, VALS(&ranap_rAB_AsymmetryIndicator_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_maxBitrate,
+ { "maxBitrate",
+ "ranap.rab_Parameters.maxBitrate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_guaranteedBitrate,
+ { "guaranteedBitrate",
+ "ranap.rab_Parameters.guaranteedBitrate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_deliveryOrder,
+ { "deliveryOrder",
+ "ranap.rab_Parameters.deliveryOrder",
+ FT_UINT8, BASE_DEC, VALS(&ranap_DeliveryOrder_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_maxSDU_Size,
+ { "maxSDU_Size",
+ "ranap.rab_Parameters.maxSDU_Size",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_sDU_ErrorRatio_mantissa,
+ { "sDU_ErrorRatio: mantissa",
+ "ranap.rab_Parameters.sDU_ErrorRatio.mantissa",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_sDU_ErrorRatio_exponent,
+ { "sDU_ErrorRatio: exponent",
+ "ranap.rab_Parameters.sDU_ErrorRatio.exponent",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_residualBitErrorRatio_mantissa,
+ { "residualBitErrorRatio: mantissa",
+ "ranap.rab_Parameters.residualBitErrorRatio.mantissa",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_residualBitErrorRatio_exponent,
+ { "residualBitErrorRatio: exponent",
+ "ranap.rab_Parameters.residualBitErrorRatio.exponent",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_deliveryOfErroneousSDU,
+ { "deliveryOfErroneousSDU",
+ "ranap.rab_Parameters.ranap_deliveryOfErroneousSDU",
+ FT_UINT8, BASE_DEC, VALS(&ranap_deliveryOfErroneousSDU_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_subflowSDU_Size,
+ { "subflowSDU_Size",
+ "ranap.rab_Parameters.subflowSDU_Size",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_rAB_SubflowCombinationBitRate,
+ { "rAB_SubflowCombinationBitRate",
+ "ranap.rab_Parameters.rAB_SubflowCombinationBitRate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_sDU_ErrorRatio_present,
+ { "sDU_ErrorRatio",
+ "ranap.sDU_ErrorRatio_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_sDU_FormatInformationParameters_present,
+ { "sDU_FormatInformationParameters",
+ "ranap.sDU_FormatInformationParameters_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_subflowSDU_Size_present,
+ { "subflowSDU_Size",
+ "ranap.subflowSDU_Size_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_rAB_SubflowCombinationBitRate_present,
+ { "subflowSDU_Size",
+ "ranap.rAB_SubflowCombinationBitRate_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_transferDelay,
+ { "transferDelay",
+ "ranap.rab_Parameters.transferDelay",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_trafficHandlingPriority,
+ { "trafficHandlingPriority",
+ "ranap.rab_Parameters.trafficHandlingPriority",
+ FT_UINT8, BASE_DEC, VALS(&ranap_priority_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_priorityLevel,
+ { "priorityLevel",
+ "ranap.rab_Parameters.allocationOrRetentionPriority.priorityLevel",
+ FT_UINT8, BASE_DEC, VALS(&ranap_priority_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_pre_emptionCapability,
+ { "pre-emptionCapability",
+ "ranap.rab_Parameters.allocationOrRetentionPriority.pre_emptionCapability",
+ FT_UINT8, BASE_DEC, VALS(&ranap_pre_emptionCapability_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_pre_emptionVulnerability,
+ { "pre-emptionVulnerability",
+ "ranap.rab_Parameters.allocationOrRetentionPriority.pre_emptionVulnerability",
+ FT_UINT8, BASE_DEC, VALS(&ranap_pre_emptionVulnerability_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_queuingAllowed,
+ { "queuingAllowed",
+ "ranap.rab_Parameters.allocationOrRetentionPriority.queuingAllowed",
+ FT_UINT8, BASE_DEC, VALS(&ranap_queuingAllowed_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_sourceStatisticsDescriptor,
+ { "sourceStatisticsDescriptor",
+ "ranap.rab_Parameters.sourceStatisticsDescriptor",
+ FT_UINT8, BASE_DEC, VALS(&ranap_sourceStatisticsDescriptor_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_relocationRequirement,
+ { "relocationRequirement",
+ "ranap.rab_Parameters.relocationRequirement",
+ FT_UINT8, BASE_DEC, VALS(&ranap_relocationRequirement_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_userPlaneMode,
+ { "userPlaneMode",
+ "ranap.userPlaneMode",
+ FT_UINT8, BASE_DEC, VALS(&ranap_userPlaneMode_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_uP_ModeVersions,
+ { "uP_ModeVersions",
+ "ranap.uP_ModeVersions",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_number_of_ProtocolExtensionFields,
+ { "Number of ProtocolExtensionFields",
+ "ranap.number_of_ProtocolExtensionFields",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ext_field_number_of_octets,
+ { "Number of octets",
+ "ranap.ProtocolExtensionFields.octets",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_transportLayerAddress_length,
+ { "bit length of transportLayerAddress",
+ "ranap.transportLayerAddress_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_transportLayerAddress,
+ { "transportLayerAddress",
+ "ranap.transportLayerAddress",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_gTP_TEI,
+ { "gTP_TEI",
+ "ranap.gTP_TEI",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_bindingID,
+ { "bindingID",
+ "ranap.bindingID",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_pDP_TypeInformation_present,
+ { "pDP_TypeInformation",
+ "ranap.pDP_TypeInformation_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dataVolumeReportingIndication_present,
+ { "dataVolumeReportingIndication",
+ "ranap.dataVolumeReportingIndication_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dl_GTP_PDU_SequenceNumber_present,
+ { "dl_GTP_PDU_SequenceNumber",
+ "ranap.dl_GTP_PDU_SequenceNumber_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ul_GTP_PDU_SequenceNumber_present,
+ { "ul_GTP_PDU_SequenceNumber",
+ "ranap.ul_GTP_PDU_SequenceNumber_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dl_N_PDU_SequenceNumber_present,
+ { "dl_N_PDU_SequenceNumber",
+ "ranap.dl_N_PDU_SequenceNumber_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ul_N_PDU_SequenceNumber_present,
+ { "ul_N_PDU_SequenceNumber",
+ "ranap.ul_N_PDU_SequenceNumber_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_PDP_Type,
+ { "PDP-Type",
+ "ranap.RAB_SetupOrModifyItemSecond.PDP_Type",
+ FT_UINT8, BASE_HEX, VALS(&ranap_PDP_Type_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dataVolumeReportingIndication,
+ { "dataVolumeReportingIndication",
+ "ranap.RAB_SetupOrModifyItemSecond.dataVolumeReportingIndication",
+ FT_UINT8, BASE_HEX, VALS(&ranap_dataVolumeReportingIndication_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dl_GTP_PDU_SequenceNumber,
+ { "dl_GTP_PDU_SequenceNumber",
+ "ranap.RAB_SetupOrModifyItemSecond.dl_GTP_PDU_SequenceNumber",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ul_GTP_PDU_SequenceNumber,
+ { "ul_GTP_PDU_SequenceNumber",
+ "ranap.RAB_SetupOrModifyItemSecond.ul_GTP_PDU_SequenceNumber",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dl_N_PDU_SequenceNumber,
+ { "ul_GTP_PDU_SequenceNumber",
+ "ranap.RAB_SetupOrModifyItemSecond.ul_GTP_PDU_SequenceNumber",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ul_N_PDU_SequenceNumber,
+ { "ul_GTP_PDU_SequenceNumber",
+ "ranap.RAB_SetupOrModifyItemSecond.ul_GTP_PDU_SequenceNumber",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_cause_choice,
+ { "cause choice",
+ "ranap.cause_choice",
+ FT_UINT8, BASE_HEX, VALS(&ranap_cause_choice_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_cause_value,
+ { "cause value",
+ "ranap.cause_value",
+ FT_UINT8, BASE_DEC,VALS(&ranap_cause_value_str), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_transportLayerAddress_present,
+ { "transportLayerAddress",
+ "ranap.transportLayerAddress_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_iuTransportAssociation_present,
+ { "iuTransportAssociation",
+ "ranap.iuTransportAssociation_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dl_dataVolumes_present,
+ { "dl_dataVolumes",
+ "ranap.dl_dataVolumes_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dataVolumeReference_present,
+ { "dataVolumeReference",
+ "ranap.dataVolumeReference_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dl_UnsuccessfullyTransmittedDataVolume,
+ { "dl-UnsuccessfullyTransmittedDataVolume",
+ "ranap.dl-UnsuccessfullyTransmittedDataVolume",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dataVolumeReference,
+ { "dataVolumeReference",
+ "ranap.dataVolumeReference",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_procedureCode_present,
+ { "procedureCode",
+ "ranap.procedureCode_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_triggeringMessage_present,
+ { "triggeringMessage",
+ "ranap.triggeringMessage_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_procedureCriticality_present,
+ { "procedureCriticality",
+ "ranap.procedureCriticality_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_iEsCriticalityDiagnostics_present,
+ { "iEsCriticalityDiagnostics",
+ "ranap.iEsCriticalityDiagnostics_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_triggeringMessage,
+ { "triggeringMessage",
+ "ranap.triggeringMessage",
+ FT_UINT8, BASE_HEX, VALS(&ranap_pdu_index_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_procedureCriticality,
+ { "procedureCriticality",
+ "ranap.procedureCriticality",
+ FT_UINT8, BASE_HEX, VALS(&ranap_criticality_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_iECriticality,
+ { "iECriticality",
+ "ranap.iECriticality",
+ FT_UINT8, BASE_HEX, VALS(&ranap_criticality_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_repetitionNumber,
+ { "repetitionNumber",
+ "ranap.repetitionNumber",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_num_of_CriticalityDiagnostics_IEs,
+ { "Number of CriticalityDiagnostics-IEs",
+ "ranap.num_of_CriticalityDiagnostics_IEs",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_repetitionNumber_present,
+ { "repetitionNumber",
+ "ranap.repetitionNumber_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_dl_UnsuccessfullyTransmittedDataVolume_present,
+ { "dl-UnsuccessfullyTransmittedDataVolume",
+ "ranap.dl_UnsuccessfullyTransmittedDataVolume_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_CN_DomainIndicator,
+ { "CN-DomainIndicator",
+ "ranap.CN_DomainIndicator",
+ FT_UINT8, BASE_HEX, VALS(&ranap_CN_DomainIndicator_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_service_Handover,
+ { "service-Handover",
+ "ranap.service_Handover",
+ FT_UINT8, BASE_HEX, VALS(&ranap_service_Handover_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_IuSigConId,
+ { "IuSigConId",
+ "ranap.IuSigConId",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_SAPI,
+ { "SAPI",
+ "ranap.sapi",
+ FT_UINT8, BASE_HEX, VALS(&ranap_SAPI_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_msg_extension_present,
+ { "Message Extension",
+ "ranap.msg_extension_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_ProtocolExtensionContainer_present,
+ { "ProtocolExtensionContainer",
+ "ranap.ProtocolExtensionContainer_present",
+ FT_UINT8, BASE_HEX, VALS(&ranap_presence_values), 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_nas_pdu_length,
+ { "length of NAS-PDU",
+ "ranap.nas_pdu_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_ranap_RNC_ID,
+ { "RNC ID",
+ "ranap.RNC_ID",
+ FT_UINT16, BASE_DEC, NULL, 0x0fff,
+ "", HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_ranap,
+ &ett_ranap_optionals,
+ &ett_ranap_iE_Extension,
+ &ett_ranap_ie,
+ &ett_ranap_ie_pair,
+ &ett_ranap_rab,
+ &ett_ranap_ie_pair_first_value,
+ &ett_ranap_ie_pair_second_value,
+ &ett_ranap_sDU,
+ &ett_ranap_rAB_Parameters,
+ &ett_ranap_allocationOrRetentionPriority ,
+ &ett_ranap_CriticalityDiagnostics_IE
+ };
+
+
+ /* Register the protocol name and description */
+ proto_ranap = proto_register_protocol("Radio Access Network Application Part",
+ "RANAP", "ranap");
+
+ /* Register the header fields and subtrees */
+ proto_register_field_array(proto_ranap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ nas_pdu_dissector_table = register_dissector_table("ranap.nas_pdu", "RANAP NAS PDU", FT_UINT8, BASE_DEC);
+}
+
+
+void
+proto_reg_handoff_ranap(void)
+{
+ dissector_handle_t ranap_handle;
+
+ ranap_handle = create_dissector_handle(dissect_ranap, proto_ranap);
+ /*
+ dissector_add("sua.ssn", SCCP_SSN_RANAP, ranap_handle);
+ */
+ dissector_add("sccp.ssn", SCCP_SSN_RANAP, ranap_handle);
+
+ /* Add heuristic dissector
+ * Perhaps we want a preference whether the heuristic dissector
+ * is or isn't enabled
+ */
+ heur_dissector_add("sccp", dissect_sccp_ranap_heur, proto_ranap);
+}
diff --git a/epan/dissectors/packet-raw.c b/epan/dissectors/packet-raw.c
new file mode 100644
index 0000000000..77939b5cf7
--- /dev/null
+++ b/epan/dissectors/packet-raw.c
@@ -0,0 +1,204 @@
+/* packet-raw.c
+ * Routines for raw packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ *
+ * This file created and by Mike Hall <mlh@io.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "packet-raw.h"
+#include "packet-ip.h"
+#include "packet-ppp.h"
+
+static int proto_raw = -1;
+static gint ett_raw = -1;
+
+static const char zeroes[10];
+
+static dissector_handle_t ip_handle;
+static dissector_handle_t ipv6_handle;
+static dissector_handle_t data_handle;
+static dissector_handle_t ppp_hdlc_handle;
+
+void
+capture_raw(const guchar *pd, int len, packet_counts *ld)
+{
+ /* So far, the only time we get raw connection types are with Linux and
+ * Irix PPP connections. We can't tell what type of data is coming down
+ * the line, so our safest bet is IP. - GCC
+ */
+
+ /* Currently, the Linux 2.1.xxx PPP driver passes back some of the header
+ * sometimes. This check should be removed when 2.2 is out.
+ */
+ if (BYTES_ARE_IN_FRAME(0,len,2) && pd[0] == 0xff && pd[1] == 0x03) {
+ capture_ppp_hdlc(pd, 0, len, ld);
+ }
+ /* The Linux ISDN driver sends a fake MAC address before the PPP header
+ * on its ippp interfaces... */
+ else if (BYTES_ARE_IN_FRAME(0,len,8) && pd[6] == 0xff && pd[7] == 0x03) {
+ capture_ppp_hdlc(pd, 6, len, ld);
+ }
+ /* ...except when it just puts out one byte before the PPP header... */
+ else if (BYTES_ARE_IN_FRAME(0,len,3) && pd[1] == 0xff && pd[2] == 0x03) {
+ capture_ppp_hdlc(pd, 1, len, ld);
+ }
+ /* ...and if the connection is currently down, it sends 10 bytes of zeroes
+ * instead of a fake MAC address and PPP header. */
+ else if (BYTES_ARE_IN_FRAME(0,len,10) && memcmp(pd, zeroes, 10) == 0) {
+ capture_ip(pd, 10, len, ld);
+ }
+ else {
+ /*
+ * OK, is this IPv4 or IPv6?
+ */
+ if (BYTES_ARE_IN_FRAME(0,len,1)) {
+ switch (pd[0] & 0xF0) {
+
+ case 0x40:
+ /* IPv4 */
+ capture_ip(pd, 0, len, ld);
+ break;
+
+#if 0
+ case 0x60:
+ /* IPv6 */
+ capture_ipv6(pd, 0, len, ld);
+ break;
+#endif
+ }
+ }
+ }
+}
+
+static void
+dissect_raw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *fh_tree;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+
+ /* load the top pane info. This should be overwritten by
+ the next protocol in the stack */
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A" );
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A" );
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "N/A" );
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Raw packet data" );
+
+ /* populate a tree in the second pane with the status of the link
+ layer (ie none) */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_raw, tvb, 0, 0, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_raw);
+ proto_tree_add_text(fh_tree, tvb, 0, 0, "No link information available");
+ }
+
+ /* So far, the only time we get raw connection types are with Linux and
+ * Irix PPP connections. We can't tell what type of data is coming down
+ * the line, so our safest bet is IP. - GCC
+ */
+
+ /* Currently, the Linux 2.1.xxx PPP driver passes back some of the header
+ * sometimes. This check should be removed when 2.2 is out.
+ */
+ if (tvb_get_ntohs(tvb, 0) == 0xff03) {
+ call_dissector(ppp_hdlc_handle, tvb, pinfo, tree);
+ }
+ /* The Linux ISDN driver sends a fake MAC address before the PPP header
+ * on its ippp interfaces... */
+ else if (tvb_get_ntohs(tvb, 6) == 0xff03) {
+ next_tvb = tvb_new_subset(tvb, 6, -1, -1);
+ call_dissector(ppp_hdlc_handle, next_tvb, pinfo, tree);
+ }
+ /* ...except when it just puts out one byte before the PPP header... */
+ else if (tvb_get_ntohs(tvb, 1) == 0xff03) {
+ next_tvb = tvb_new_subset(tvb, 1, -1, -1);
+ call_dissector(ppp_hdlc_handle, next_tvb, pinfo, tree);
+ }
+ /* ...and if the connection is currently down, it sends 10 bytes of zeroes
+ * instead of a fake MAC address and PPP header. */
+ else if (memcmp(tvb_get_ptr(tvb, 0, 10), zeroes, 10) == 0) {
+ next_tvb = tvb_new_subset(tvb, 10, -1, -1);
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+ }
+ else {
+ /*
+ * OK, is this IPv4 or IPv6?
+ */
+ switch (tvb_get_guint8(tvb, 0) & 0xF0) {
+
+ case 0x40:
+ /* IPv4 */
+ call_dissector(ip_handle, tvb, pinfo, tree);
+ break;
+
+ case 0x60:
+ /* IPv6 */
+ call_dissector(ipv6_handle, tvb, pinfo, tree);
+ break;
+
+ default:
+ /* None of the above. */
+ call_dissector(data_handle, tvb, pinfo, tree);
+ break;
+ }
+ }
+}
+
+void
+proto_register_raw(void)
+{
+ static gint *ett[] = {
+ &ett_raw,
+ };
+
+ proto_raw = proto_register_protocol("Raw packet data", "Raw", "raw");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_raw(void)
+{
+ dissector_handle_t raw_handle;
+
+ /*
+ * Get handles for the IP, IPv6, undissected-data, and
+ * PPP-in-HDLC-like-framing dissectors.
+ */
+ ip_handle = find_dissector("ip");
+ ipv6_handle = find_dissector("ipv6");
+ data_handle = find_dissector("data");
+ ppp_hdlc_handle = find_dissector("ppp_hdlc");
+ raw_handle = create_dissector_handle(dissect_raw, proto_raw);
+ dissector_add("wtap_encap", WTAP_ENCAP_RAW_IP, raw_handle);
+}
diff --git a/epan/dissectors/packet-raw.h b/epan/dissectors/packet-raw.h
new file mode 100644
index 0000000000..40480ec0cc
--- /dev/null
+++ b/epan/dissectors/packet-raw.h
@@ -0,0 +1,29 @@
+/* packet-raw.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_RAW_H__
+#define __PACKET_RAW_H__
+
+void capture_raw(const guchar *, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-rip.c b/epan/dissectors/packet-rip.c
new file mode 100644
index 0000000000..a39a14a841
--- /dev/null
+++ b/epan/dissectors/packet-rip.c
@@ -0,0 +1,405 @@
+/* packet-rip.c
+ * Routines for RIPv1 and RIPv2 packet disassembly
+ * RFC1058, RFC2453
+ * (c) Copyright Hannes R. Boehm <hannes@boehm.org>
+ *
+ * RFC2082 ( Keyed Message Digest Algorithm )
+ * Emanuele Caratti <wiz@iol.it>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+#define UDP_PORT_RIP 520
+
+#define RIPv1 1
+#define RIPv2 2
+
+static const value_string version_vals[] = {
+ { RIPv1, "RIPv1" },
+ { RIPv2, "RIPv2" },
+ { 0, NULL }
+};
+
+static const value_string command_vals[] = {
+ { 1, "Request" },
+ { 2, "Response" },
+ { 3, "Traceon" },
+ { 4, "Traceoff" },
+ { 5, "Vendor specific (Sun)" },
+ { 0, NULL }
+};
+
+#define AFVAL_UNSPEC 0
+#define AFVAL_IP 2
+
+static const value_string family_vals[] = {
+ { AFVAL_UNSPEC, "Unspecified" },
+ { AFVAL_IP, "IP" },
+ { 0, NULL }
+};
+
+#define AUTH_IP_ROUTE 1
+#define AUTH_PASSWORD 2
+#define AUTH_KEYED_MSG_DIGEST 3
+
+static const value_string rip_auth_type[] = {
+ { AUTH_IP_ROUTE, "IP Route" },
+ { AUTH_PASSWORD, "Simple Password" },
+ { AUTH_KEYED_MSG_DIGEST, "Keyed Message Digest" },
+ { 0, NULL }
+};
+
+#define RIP_HEADER_LENGTH 4
+#define RIP_ENTRY_LENGTH 20
+#define MD5_AUTH_DATA_LEN 16
+
+static int proto_rip = -1;
+static int hf_rip_command = -1;
+static int hf_rip_version = -1;
+static int hf_rip_routing_domain = -1;
+static int hf_rip_ip = -1;
+static int hf_rip_netmask = -1;
+static int hf_rip_next_hop = -1;
+static int hf_rip_metric = -1;
+static int hf_rip_auth = -1;
+static int hf_rip_auth_passwd = -1;
+static int hf_rip_family = -1;
+static int hf_rip_route_tag = -1;
+
+static gint ett_rip = -1;
+static gint ett_rip_vec = -1;
+static gint ett_auth_vec = -1;
+
+static void dissect_unspec_rip_vektor(tvbuff_t *tvb, int offset, guint8 version,
+ proto_tree *tree);
+static void dissect_ip_rip_vektor(tvbuff_t *tvb, int offset, guint8 version,
+ proto_tree *tree);
+static gint dissect_rip_authentication(tvbuff_t *tvb, int offset,
+ proto_tree *tree);
+
+static void
+dissect_rip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *rip_tree = NULL;
+ proto_item *ti;
+ guint8 command;
+ guint8 version;
+ guint16 family;
+ gint trailer_len = 0;
+ gboolean is_md5_auth = FALSE;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RIP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ command = tvb_get_guint8(tvb, 0);
+ version = tvb_get_guint8(tvb, 1);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_add_str(pinfo->cinfo, COL_PROTOCOL,
+ val_to_str(version, version_vals, "RIP"));
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(command, command_vals, "Unknown command (%u)"));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_rip, tvb, 0, -1, FALSE);
+ rip_tree = proto_item_add_subtree(ti, ett_rip);
+
+ proto_tree_add_uint(rip_tree, hf_rip_command, tvb, 0, 1, command);
+ proto_tree_add_uint(rip_tree, hf_rip_version, tvb, 1, 1, version);
+ if (version == RIPv2)
+ proto_tree_add_uint(rip_tree, hf_rip_routing_domain, tvb, 2, 2,
+ tvb_get_ntohs(tvb, 2));
+
+ /* skip header */
+ offset = RIP_HEADER_LENGTH;
+
+ /* zero or more entries */
+ while (tvb_reported_length_remaining(tvb, offset) > trailer_len ) {
+ family = tvb_get_ntohs(tvb, offset);
+ switch (family) {
+ case AFVAL_UNSPEC: /* Unspecified */
+ /*
+ * There should be one entry in the request, and a metric
+ * of infinity, meaning "show the entire routing table".
+ */
+ dissect_unspec_rip_vektor(tvb, offset, version, rip_tree);
+ break;
+ case AFVAL_IP: /* IP */
+ dissect_ip_rip_vektor(tvb, offset, version, rip_tree);
+ break;
+ case 0xFFFF:
+ if( offset == RIP_HEADER_LENGTH ) {
+ trailer_len=dissect_rip_authentication(tvb, offset, rip_tree);
+ is_md5_auth = TRUE;
+ break;
+ }
+ if(is_md5_auth && tvb_reported_length_remaining(tvb, offset) == 20)
+ break;
+ /* Intentional fall through: auth Entry MUST be the first! */
+ default:
+ proto_tree_add_text(rip_tree, tvb, offset,
+ RIP_ENTRY_LENGTH, "Unknown address family %u",
+ family);
+ break;
+ }
+
+ offset += RIP_ENTRY_LENGTH;
+ }
+ }
+}
+
+static void
+dissect_unspec_rip_vektor(tvbuff_t *tvb, int offset, guint8 version,
+ proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *rip_vektor_tree;
+ guint32 metric;
+
+ metric = tvb_get_ntohl(tvb, offset+16);
+ ti = proto_tree_add_text(tree, tvb, offset,
+ RIP_ENTRY_LENGTH, "Address not specified, Metric: %u",
+ metric);
+ rip_vektor_tree = proto_item_add_subtree(ti, ett_rip_vec);
+
+ proto_tree_add_item(rip_vektor_tree, hf_rip_family, tvb, offset, 2, FALSE);
+ if (version == RIPv2) {
+ proto_tree_add_item(rip_vektor_tree, hf_rip_route_tag, tvb, offset+2, 2,
+ FALSE);
+ proto_tree_add_item(rip_vektor_tree, hf_rip_netmask, tvb, offset+8, 4,
+ FALSE);
+ proto_tree_add_item(rip_vektor_tree, hf_rip_next_hop, tvb, offset+12, 4,
+ FALSE);
+ }
+ proto_tree_add_uint(rip_vektor_tree, hf_rip_metric, tvb,
+ offset+16, 4, metric);
+}
+
+static void
+dissect_ip_rip_vektor(tvbuff_t *tvb, int offset, guint8 version,
+ proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *rip_vektor_tree;
+ guint32 metric;
+
+ metric = tvb_get_ntohl(tvb, offset+16);
+ ti = proto_tree_add_text(tree, tvb, offset,
+ RIP_ENTRY_LENGTH, "IP Address: %s, Metric: %u",
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)), metric);
+ rip_vektor_tree = proto_item_add_subtree(ti, ett_rip_vec);
+
+ proto_tree_add_item(rip_vektor_tree, hf_rip_family, tvb, offset, 2, FALSE);
+ if (version == RIPv2) {
+ proto_tree_add_item(rip_vektor_tree, hf_rip_route_tag, tvb, offset+2, 2,
+ FALSE);
+ }
+
+ proto_tree_add_item(rip_vektor_tree, hf_rip_ip, tvb, offset+4, 4, FALSE);
+
+ if (version == RIPv2) {
+ proto_tree_add_item(rip_vektor_tree, hf_rip_netmask, tvb, offset+8, 4,
+ FALSE);
+ proto_tree_add_item(rip_vektor_tree, hf_rip_next_hop, tvb, offset+12, 4,
+ FALSE);
+ }
+ proto_tree_add_uint(rip_vektor_tree, hf_rip_metric, tvb,
+ offset+16, 4, metric);
+}
+
+static gchar *
+rip_bytestring_to_str(const guint8 *ad, guint32 len, char punct) {
+ static gchar *str=NULL;
+ static guint str_len;
+ gchar *p;
+ int i;
+ guint32 octet;
+ /* At least one version of Apple's C compiler/linker is buggy, causing
+ a complaint from the linker about the "literal C string section"
+ not ending with '\0' if we initialize a 16-element "char" array with
+ a 16-character string, the fact that initializing such an array with
+ such a string is perfectly legitimate ANSI C nonwithstanding, the 17th
+ '\0' byte in the string nonwithstanding. */
+ static const gchar hex_digits[16] =
+ { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ if( !str ) {
+ str_len=sizeof(gchar)*len*(punct?3:2);
+ str=g_malloc(str_len);
+ } else {
+ if( str_len < (sizeof(gchar)*len*(punct?3:2)) ) {
+ g_free(str);
+ str_len=sizeof(gchar)*len*(punct?3:2);
+ str=g_malloc(str_len);
+ }
+ }
+ len--;
+
+ p = &str[str_len];
+ *--p = '\0';
+ i = len;
+ for (;;) {
+ octet = ad[i];
+ *--p = hex_digits[octet&0xF];
+ octet >>= 4;
+ *--p = hex_digits[octet&0xF];
+ if (i == 0)
+ break;
+ if (punct)
+ *--p = punct;
+ i--;
+ }
+ return p;
+}
+
+static gint
+dissect_rip_authentication(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *rip_authentication_tree;
+ guint16 authtype;
+ guint32 val, digest_off, auth_data_len;
+
+ auth_data_len = 0;
+ authtype = tvb_get_ntohs(tvb, offset + 2);
+
+ ti = proto_tree_add_text(tree, tvb, offset, RIP_ENTRY_LENGTH,
+ "Authentication: %s", val_to_str( authtype, rip_auth_type, "Unknown (%u)" ) );
+ rip_authentication_tree = proto_item_add_subtree(ti, ett_rip_vec);
+
+ proto_tree_add_uint(rip_authentication_tree, hf_rip_auth, tvb, offset+2, 2,
+ authtype);
+
+ switch ( authtype ) {
+
+ case AUTH_PASSWORD: /* Plain text password */
+ proto_tree_add_item(rip_authentication_tree, hf_rip_auth_passwd,
+ tvb, offset+4, 16, FALSE);
+ break;
+
+ case AUTH_KEYED_MSG_DIGEST: /* Keyed MD5 rfc 2082 */
+ digest_off = tvb_get_ntohs( tvb, offset+4 );
+ proto_tree_add_text( rip_authentication_tree, tvb, offset+4, 2,
+ "Digest Offset: %u" , digest_off );
+ val = tvb_get_guint8( tvb, offset+6 );
+ proto_tree_add_text( rip_authentication_tree, tvb, offset+6, 1,
+ "Key ID: %u" , val );
+ auth_data_len = tvb_get_guint8( tvb, offset+7 );
+ proto_tree_add_text( rip_authentication_tree, tvb, offset+7, 1,
+ "Auth Data Len: %u" , auth_data_len );
+ val = tvb_get_ntohl( tvb, offset+8 );
+ proto_tree_add_text( rip_authentication_tree, tvb, offset+8, 4,
+ "Seq num: %u" , val );
+ proto_tree_add_text( rip_authentication_tree, tvb, offset+12, 8,
+ "Zero Padding" );
+ ti = proto_tree_add_text( rip_authentication_tree, tvb, offset-4+digest_off,
+ MD5_AUTH_DATA_LEN+4, "Authentication Data Trailer" );
+ rip_authentication_tree = proto_item_add_subtree(ti, ett_auth_vec );
+ proto_tree_add_text( rip_authentication_tree, tvb, offset-4+digest_off+4,
+ MD5_AUTH_DATA_LEN, "Authentication Data: %s",
+ rip_bytestring_to_str(
+ tvb_get_ptr( tvb, offset-4+digest_off+4,MD5_AUTH_DATA_LEN),
+ MD5_AUTH_DATA_LEN, ' '));
+ break;
+ }
+ return auth_data_len;
+}
+
+void
+proto_register_rip(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rip_command,
+ { "Command", "rip.command", FT_UINT8, BASE_DEC,
+ VALS(command_vals), 0, "What type of RIP Command is this", HFILL }},
+
+ { &hf_rip_version,
+ { "Version", "rip.version", FT_UINT8, BASE_DEC,
+ VALS(version_vals), 0, "Version of the RIP protocol", HFILL }},
+
+ { &hf_rip_family,
+ { "Address Family", "rip.family", FT_UINT16, BASE_DEC,
+ VALS(family_vals), 0, "Address family", HFILL }},
+
+ { &hf_rip_routing_domain,
+ { "Routing Domain", "rip.routing_domain", FT_UINT16, BASE_DEC,
+ NULL, 0, "RIPv2 Routing Domain", HFILL }},
+
+ { &hf_rip_ip,
+ { "IP Address", "rip.ip", FT_IPv4, BASE_NONE,
+ NULL, 0, "IP Address", HFILL}},
+
+ { &hf_rip_netmask,
+ { "Netmask", "rip.netmask", FT_IPv4, BASE_NONE,
+ NULL, 0, "Netmask", HFILL}},
+
+ { &hf_rip_next_hop,
+ { "Next Hop", "rip.next_hop", FT_IPv4, BASE_NONE,
+ NULL, 0, "Next Hop router for this route", HFILL}},
+
+ { &hf_rip_metric,
+ { "Metric", "rip.metric", FT_UINT16, BASE_DEC,
+ NULL, 0, "Metric for this route", HFILL }},
+
+ { &hf_rip_auth,
+ { "Authentication type", "rip.auth.type", FT_UINT16, BASE_DEC,
+ VALS(rip_auth_type), 0, "Type of authentication", HFILL }},
+
+ { &hf_rip_auth_passwd,
+ { "Password", "rip.auth.passwd", FT_STRING, BASE_DEC,
+ NULL, 0, "Authentication password", HFILL }},
+
+ { &hf_rip_route_tag,
+ { "Route Tag", "rip.route_tag", FT_UINT16, BASE_DEC,
+ NULL, 0, "Route Tag", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_rip,
+ &ett_rip_vec,
+ &ett_auth_vec,
+ };
+
+ proto_rip = proto_register_protocol("Routing Information Protocol",
+ "RIP", "rip");
+ proto_register_field_array(proto_rip, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_rip(void)
+{
+ dissector_handle_t rip_handle;
+
+ rip_handle = create_dissector_handle(dissect_rip, proto_rip);
+ dissector_add("udp.port", UDP_PORT_RIP, rip_handle);
+}
diff --git a/epan/dissectors/packet-ripng.c b/epan/dissectors/packet-ripng.c
new file mode 100644
index 0000000000..7ed7526e92
--- /dev/null
+++ b/epan/dissectors/packet-ripng.c
@@ -0,0 +1,155 @@
+/* packet-ripng.c
+ * Routines for RIPng disassembly
+ * (c) Copyright Jun-ichiro itojun Hagino <itojun@itojun.org>
+ * derived from packet-rip.c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ripng.h"
+
+#ifndef offsetof
+#define offsetof(type, member) ((size_t)(&((type *)0)->member))
+#endif
+
+static int proto_ripng = -1;
+static int hf_ripng_cmd = -1;
+static int hf_ripng_version = -1;
+
+static gint ett_ripng = -1;
+static gint ett_ripng_addr = -1;
+
+#define UDP_PORT_RIPNG 521
+
+static const value_string cmdvals[] = {
+ { RIP6_REQUEST, "Request" },
+ { RIP6_RESPONSE, "Response" },
+ { 0, NULL },
+};
+
+static void
+dissect_ripng(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+ int offset = 0;
+ struct rip6 rip6;
+ struct netinfo6 ni6;
+ proto_tree *ripng_tree = NULL;
+ proto_tree *subtree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RIPng");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* avoid alignment problem */
+ tvb_memcpy(tvb, (guint8 *)&rip6, offset, sizeof(rip6));
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "RIPng version %u", rip6.rip6_vers);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(rip6.rip6_cmd, cmdvals, "Unknown command (%u)"));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ripng, tvb, offset, -1, FALSE);
+ ripng_tree = proto_item_add_subtree(ti, ett_ripng);
+
+ proto_tree_add_uint(ripng_tree, hf_ripng_cmd, tvb, offset, 1,
+ rip6.rip6_cmd);
+ proto_tree_add_uint(ripng_tree, hf_ripng_version, tvb, offset + 1, 1,
+ rip6.rip6_vers);
+
+ offset += 4;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ tvb_memcpy(tvb, (guint8 *)&ni6, offset, sizeof(ni6));
+ if (ni6.rip6_tag) {
+ ti = proto_tree_add_text(ripng_tree, tvb, offset,
+ sizeof(ni6), "IP Address: %s/%u, Metric: %u, tag: 0x%04x",
+ ip6_to_str(&ni6.rip6_dest),
+ ni6.rip6_plen,
+ ni6.rip6_metric,
+ g_ntohs(ni6.rip6_tag));
+ } else {
+ ti = proto_tree_add_text(ripng_tree, tvb, offset,
+ sizeof(ni6), "IP Address: %s/%u, Metric: %u",
+ ip6_to_str(&ni6.rip6_dest),
+ ni6.rip6_plen,
+ ni6.rip6_metric);
+ }
+ subtree = proto_item_add_subtree(ti, ett_ripng_addr);
+ proto_tree_add_text(subtree, tvb,
+ offset + offsetof(struct netinfo6, rip6_dest),
+ sizeof(ni6.rip6_dest), "IP Address: %s",
+ ip6_to_str(&ni6.rip6_dest));
+ proto_tree_add_text(subtree, tvb,
+ offset + offsetof(struct netinfo6, rip6_tag),
+ sizeof(ni6.rip6_tag), "Tag: 0x%04x",
+ g_ntohs(ni6.rip6_tag));
+ proto_tree_add_text(subtree, tvb,
+ offset + offsetof(struct netinfo6, rip6_plen),
+ sizeof(ni6.rip6_plen), "Prefix length: %u",
+ ni6.rip6_plen);
+ proto_tree_add_text(subtree, tvb,
+ offset + offsetof(struct netinfo6, rip6_metric),
+ sizeof(ni6.rip6_metric), "Metric: %u",
+ ni6.rip6_metric);
+
+ offset += sizeof(ni6);
+ }
+ }
+}
+
+void
+proto_register_ripng(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ripng_cmd,
+ { "Command", "ripng.cmd",
+ FT_UINT8, BASE_DEC, VALS(cmdvals),
+ 0x0, "", HFILL }},
+ { &hf_ripng_version,
+ { "Version", "ripng.version",
+ FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ripng,
+ &ett_ripng_addr,
+ };
+
+ proto_ripng = proto_register_protocol("RIPng", "RIPng", "ripng");
+ proto_register_field_array(proto_ripng, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ripng(void)
+{
+ dissector_handle_t ripng_handle;
+
+ ripng_handle = create_dissector_handle(dissect_ripng, proto_ripng);
+ dissector_add("udp.port", UDP_PORT_RIPNG, ripng_handle);
+}
diff --git a/epan/dissectors/packet-ripng.h b/epan/dissectors/packet-ripng.h
new file mode 100644
index 0000000000..1dc0b4f641
--- /dev/null
+++ b/epan/dissectors/packet-ripng.h
@@ -0,0 +1,116 @@
+/* packet-ripng.h
+ * RIPng definition
+ * (c) Copyright Jun-ichiro itojun Hagino <itojun@itojun.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_RIPNG_H_DEFINED__
+#define __PACKET_RIPNG_H_DEFINED__
+
+#include "globals.h"
+#include "packet-ipv6.h"
+
+/*
+ * KAME Header: /cvsroot/kame/kame/kame/kame/route6d/route6d.h,v 1.1.1.1 1999/08/08 23:31:35 itojun Exp
+ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define RIP6_VERSION 1
+
+#define RIP6_REQUEST 1
+#define RIP6_RESPONSE 2
+
+struct netinfo6 {
+ struct e_in6_addr rip6_dest;
+ gushort rip6_tag;
+ guchar rip6_plen;
+ guchar rip6_metric;
+};
+
+struct rip6 {
+ guchar rip6_cmd;
+ guchar rip6_vers;
+ guchar rip6_res1[2];
+ union {
+ struct netinfo6 ru6_nets[1];
+ char ru6_tracefile[1];
+ } rip6un;
+#define rip6_nets rip6un.ru6_nets
+#define rip6_tracefile rip6un.ru6_tracefile
+};
+
+#define HOPCNT_INFINITY6 16
+#define NEXTHOP_METRIC 0xff
+#define RIP6_MAXMTU 1500
+
+#define IFMINMTU 576
+
+#ifndef DEBUG
+#define SUPPLY_INTERVAL6 30
+#define RIP_LIFETIME 180
+#define RIP_HOLDDOWN 120
+#define RIP_TRIG_INT6_MAX 5
+#define RIP_TRIG_INT6_MIN 1
+#else
+/* only for debugging; can not wait for 30sec to appear a bug */
+#define SUPPLY_INTERVAL6 10
+#define RIP_LIFETIME 60
+#define RIP_HOLDDOWN 40
+#define RIP_TRIG_INT6_MAX 5
+#define RIP_TRIG_INT6_MIN 1
+#endif
+
+#define RIP6_PORT 521
+#define RIP6_DEST "ff02::9"
+
+#define LOOPBACK_IF "lo0"
+
+#endif /* __PACKET_RIPNG_H_DEFINED__ */
diff --git a/epan/dissectors/packet-rlogin.c b/epan/dissectors/packet-rlogin.c
new file mode 100644
index 0000000000..5f09780830
--- /dev/null
+++ b/epan/dissectors/packet-rlogin.c
@@ -0,0 +1,481 @@
+/* packet-rlogin.c
+ * Routines for unix rlogin packet dissection
+ * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Based upon RFC-1282 - BSD Rlogin
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include "packet-tcp.h"
+
+#define TCP_PORT_RLOGIN 513
+
+static int proto_rlogin = -1;
+
+static int ett_rlogin = -1;
+static int ett_rlogin_window = -1;
+static int ett_rlogin_user_info = -1;
+static int ett_rlogin_window_rows = -1;
+static int ett_rlogin_window_cols = -1;
+static int ett_rlogin_window_x_pixels = -1;
+static int ett_rlogin_window_y_pixels = -1;
+
+static int hf_user_info = -1;
+static int hf_window_info = -1;
+static int hf_window_info_rows = -1;
+static int hf_window_info_cols = -1;
+static int hf_window_info_x_pixels = -1;
+static int hf_window_info_y_pixels = -1;
+
+#define RLOGIN_PORT 513
+
+#define NAME_LEN 32
+
+typedef struct {
+ int state;
+ guint32 info_framenum;
+ char name[ NAME_LEN];
+
+} rlogin_hash_entry_t;
+
+#define NONE 0
+#define USER_INFO_WAIT 1
+#define DONE 2
+#define BAD 2
+
+static GMemChunk *rlogin_vals = NULL;
+
+#define rlogin_hash_init_count 20
+
+static guint32 last_abs_sec = 0;
+static guint32 last_abs_usec= 0;
+
+static void
+rlogin_init(void)
+{
+
+/* Routine to initialize rlogin protocol before each capture or filter pass. */
+/* Release any memory if needed. Then setup the memory chunks. */
+
+ last_abs_sec = 0;
+ last_abs_usec= 0;
+
+ if (rlogin_vals)
+ g_mem_chunk_destroy(rlogin_vals);
+
+ rlogin_vals = g_mem_chunk_new("rlogin_vals",
+ sizeof( rlogin_hash_entry_t),
+ rlogin_hash_init_count * sizeof( rlogin_hash_entry_t),
+ G_ALLOC_AND_FREE);
+}
+
+
+/**************** Decoder State Machine ******************/
+
+static void
+rlogin_state_machine( rlogin_hash_entry_t *hash_info, tvbuff_t *tvb,
+ packet_info *pinfo)
+{
+ guint length;
+ gint stringlen;
+
+/* rlogin stream decoder */
+/* Just watched for second packet from client with the user name and */
+/* terminal type information. */
+
+
+ if ( pinfo->destport != RLOGIN_PORT) /* not from client */
+ return;
+ /* exit if not needed */
+ if (( hash_info->state == DONE) || ( hash_info->state == BAD))
+ return;
+
+ /* test timestamp */
+ if (( last_abs_sec > pinfo->fd->abs_secs) ||
+ (( last_abs_sec == pinfo->fd->abs_secs) &&
+ ( last_abs_usec >= pinfo->fd->abs_usecs)))
+ return;
+
+ last_abs_sec = pinfo->fd->abs_secs; /* save timestamp */
+ last_abs_usec = pinfo->fd->abs_usecs;
+
+ length = tvb_length(tvb);
+ if ( length == 0) /* exit if no data */
+ return;
+
+ if ( hash_info->state == NONE){ /* new connection*/
+ if (tvb_get_guint8(tvb, 0) != '\0') {
+ /*
+ * We expected a NUL, but didn't get one; quit.
+ */
+ hash_info->state = DONE;
+ return;
+ }
+ else {
+ if (length <= 1) /* if no data */
+ hash_info->state = USER_INFO_WAIT;
+ else {
+ hash_info->state = DONE;
+ hash_info->info_framenum = pinfo->fd->num;
+ }
+ }
+ } /* expect user data here */
+/*$$$ may need to do more checking here */
+ else if ( hash_info->state == USER_INFO_WAIT) {
+ hash_info->state = DONE;
+ hash_info->info_framenum = pinfo->fd->num;
+ /* save name for later*/
+ stringlen = tvb_strnlen(tvb, 0, NAME_LEN);
+ if (stringlen == -1)
+ stringlen = NAME_LEN - 1; /* no '\0' found */
+ else if (stringlen > NAME_LEN - 1)
+ stringlen = NAME_LEN - 1; /* name too long */
+ tvb_memcpy(tvb, (guint8 *)hash_info->name, 0, stringlen);
+ hash_info->name[stringlen] = '\0';
+
+ if (check_col(pinfo->cinfo, COL_INFO)) /* update summary */
+ col_append_str(pinfo->cinfo, COL_INFO,
+ ", User information");
+ }
+}
+
+static void rlogin_display( rlogin_hash_entry_t *hash_info, tvbuff_t *tvb,
+ packet_info *pinfo, proto_tree *tree, struct tcpinfo *tcpinfo)
+{
+/* Display the proto tree */
+ int offset = 0;
+ proto_tree *rlogin_tree, *user_info_tree, *window_tree;
+ proto_item *ti;
+ guint length;
+ int str_len;
+ gint ti_offset;
+ proto_item *user_info_item, *window_info_item;
+
+ ti = proto_tree_add_item( tree, proto_rlogin, tvb, 0, -1, FALSE);
+
+ rlogin_tree = proto_item_add_subtree(ti, ett_rlogin);
+
+ length = tvb_length(tvb);
+ if ( length == 0) /* exit if no captured data */
+ return;
+
+ /*
+ * XXX - this works only if the urgent pointer points to something
+ * in this segment; to make it work if the urgent pointer points
+ * to something past this segment, we'd have to remember the urgent
+ * pointer setting for this conversation.
+ */
+ if ( tcpinfo->urgent && /* if urgent pointer set */
+ length >= tcpinfo->urgent_pointer) { /* and it's in this frame */
+
+ int urgent_offset = tcpinfo->urgent_pointer - 1;
+ guint8 Temp = tvb_get_guint8(tvb, urgent_offset);
+
+ if (urgent_offset > offset) /* check for data in front */
+ proto_tree_add_text( rlogin_tree, tvb, offset,
+ urgent_offset, "Data");
+
+ proto_tree_add_text( rlogin_tree, tvb, urgent_offset, 1,
+ "Control byte: %u (%s)",
+ Temp,
+ (Temp == 0x02) ? "Clear buffer" :
+ (Temp == 0x10) ? "Raw mode" :
+ (Temp == 0x20) ? "Cooked mode" :
+ (Temp == 0x80) ? "Window size request" :
+ "Unknown");
+ offset = urgent_offset + 1; /* adjust offset */
+ }
+ else if ( tvb_get_guint8(tvb, offset) == '\0'){ /* startup */
+ if ( pinfo->srcport== RLOGIN_PORT) /* from server */
+ proto_tree_add_text(rlogin_tree, tvb, offset, 1,
+ "Startup info received flag (0x00)");
+
+ else
+ proto_tree_add_text(rlogin_tree, tvb, offset, 1,
+ "Client Startup Flag (0x00)");
+ ++offset;
+ }
+
+ if (!tvb_offset_exists(tvb, offset))
+ return; /* No more data to check */
+
+ if ( hash_info->info_framenum == pinfo->fd->num){
+ /*
+ * First frame of conversation, hence user info?
+ */
+ user_info_item = proto_tree_add_item( rlogin_tree, hf_user_info, tvb,
+ offset, -1, FALSE);
+
+ /*
+ * Do server user name.
+ */
+ str_len = tvb_strsize(tvb, offset);
+ user_info_tree = proto_item_add_subtree( user_info_item,
+ ett_rlogin_user_info);
+ proto_tree_add_text(user_info_tree, tvb, offset, str_len,
+ "Server User Name: %.*s", str_len - 1,
+ tvb_get_ptr(tvb, offset, str_len - 1));
+ offset += str_len;
+
+ /*
+ * Do client user name.
+ */
+ str_len = tvb_strsize(tvb, offset);
+ proto_tree_add_text(user_info_tree, tvb, offset, str_len,
+ "Client User Name: %.*s", str_len - 1,
+ tvb_get_ptr(tvb, offset, str_len - 1));
+ offset += str_len;
+
+ /*
+ * Do terminal type/speed.
+ */
+ str_len = tvb_strsize(tvb, offset);
+ proto_tree_add_text(user_info_tree, tvb, offset, str_len,
+ "Terminal Type/Speed: %.*s", str_len - 1,
+ tvb_get_ptr(tvb, offset, str_len - 1));
+ offset += str_len;
+ }
+
+ if (!tvb_offset_exists(tvb, offset))
+ return; /* No more data to check */
+
+/* test for terminal information, the data will have 2 0xff bytes */
+
+ /* look for first 0xff byte */
+ ti_offset = tvb_find_guint8(tvb, offset, -1, 0xff);
+
+ if (ti_offset != -1 &&
+ tvb_bytes_exist(tvb, ti_offset + 1, 1) &&
+ tvb_get_guint8(tvb, ti_offset + 1) == 0xff) {
+ /*
+ * Found terminal info.
+ */
+ if (ti_offset > offset) {
+ /*
+ * There's data before the terminal info.
+ */
+ proto_tree_add_text( rlogin_tree, tvb, offset,
+ (ti_offset - offset), "Data");
+ offset = ti_offset;
+ }
+
+ window_info_item = proto_tree_add_item(rlogin_tree,
+ hf_window_info, tvb, offset, 12, FALSE );
+
+ window_tree = proto_item_add_subtree(window_info_item,
+ ett_rlogin_window);
+
+ proto_tree_add_text(window_tree, tvb, offset, 2,
+ "Magic Cookie: (0xff, 0xff)");
+ offset += 2;
+
+ proto_tree_add_text(window_tree, tvb, offset, 2,
+ "Window size marker: 'ss'");
+ offset += 2;
+
+ proto_tree_add_item(window_tree, hf_window_info_rows, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(window_tree, hf_window_info_cols, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(window_tree, hf_window_info_x_pixels, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(window_tree, hf_window_info_y_pixels, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+ }
+
+ if (tvb_offset_exists(tvb, offset)) {
+ /*
+ * There's more data in the frame.
+ */
+ proto_tree_add_text(rlogin_tree, tvb, offset, -1, "Data");
+ }
+}
+
+static void
+dissect_rlogin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct tcpinfo *tcpinfo = pinfo->private_data;
+ conversation_t *conversation;
+ rlogin_hash_entry_t *hash_info;
+ guint length;
+ gint ti_offset;
+
+ /* Lookup this connection*/
+ conversation = find_conversation( &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+
+ if ( !conversation) {
+ conversation = conversation_new( &pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ hash_info = conversation_get_proto_data(conversation, proto_rlogin);
+ if ( !hash_info) {
+ hash_info = g_mem_chunk_alloc(rlogin_vals);
+ hash_info->state = NONE;
+ hash_info->info_framenum = 0; /* no frame has the number 0 */
+ hash_info->name[ 0] = 0;
+ conversation_add_proto_data(conversation, proto_rlogin,
+ hash_info);
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) /* update protocol */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Rlogin");
+
+ if (check_col(pinfo->cinfo, COL_INFO)){ /* display packet info*/
+
+ char temp[1000];
+
+ col_clear(pinfo->cinfo, COL_INFO);
+ if ( hash_info->name[0]) {
+ strcpy( temp, "User name: ");
+ strcat( temp, hash_info->name);
+ strcat( temp, ", ");
+ }
+ else
+ temp[0] = 0;
+
+ length = tvb_length(tvb);
+ if (length != 0) {
+ if ( tvb_get_guint8(tvb, 0) == '\0')
+ strcat( temp, "Start Handshake");
+ else if ( tcpinfo->urgent &&
+ length >= tcpinfo->urgent_pointer )
+ strcat( temp, "Control Message");
+
+ else { /* check for terminal info */
+ ti_offset = tvb_find_guint8(tvb, 0, -1, 0xff);
+ if (ti_offset != -1 &&
+ tvb_bytes_exist(tvb, ti_offset + 1, 1) &&
+ tvb_get_guint8(tvb, ti_offset + 1) == 0xff)
+ strcat( temp, "Terminal Info");
+ else {
+ int i;
+ int bytes_to_copy;
+
+ strcat( temp, "Data: ");
+ i = strlen( temp);
+ bytes_to_copy = tvb_length(tvb);
+ if (bytes_to_copy > 128)
+ bytes_to_copy = 128;
+ tvb_memcpy(tvb, (guint8 *)&temp[i], 0,
+ bytes_to_copy);
+ temp[i + bytes_to_copy] = '\0';
+ }
+ }
+ }
+
+ col_add_str(pinfo->cinfo, COL_INFO, temp);
+ }
+
+ rlogin_state_machine( hash_info, tvb, pinfo);
+
+ if ( tree) /* if proto tree, decode data */
+ rlogin_display( hash_info, tvb, pinfo, tree, tcpinfo);
+}
+
+
+void
+proto_register_rlogin( void){
+
+/* Prep the rlogin protocol, for now, just register it */
+
+ static gint *ett[] = {
+ &ett_rlogin,
+ &ett_rlogin_window,
+ &ett_rlogin_window_rows,
+ &ett_rlogin_window_cols,
+ &ett_rlogin_window_x_pixels,
+ &ett_rlogin_window_y_pixels,
+ &ett_rlogin_user_info
+ };
+
+ static hf_register_info hf[] = {
+
+ { &hf_user_info,
+ { "User Info", "rlogin.user_info", FT_NONE, BASE_NONE,
+ NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_window_info,
+ { "Window Info", "rlogin.window_size", FT_NONE, BASE_NONE,
+ NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_window_info_rows,
+ { "Rows", "rlogin.window_size.rows", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_window_info_cols,
+ { "Columns", "rlogin.window_size.cols", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_window_info_x_pixels,
+ { "X Pixels", "rlogin.window_size.x_pixels", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_window_info_y_pixels,
+ { "Y Pixels", "rlogin.window_size.y_pixels", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL
+ }
+ }
+ };
+
+ proto_rlogin = proto_register_protocol (
+ "Rlogin Protocol", "Rlogin", "rlogin");
+
+ proto_register_field_array(proto_rlogin, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine( &rlogin_init); /* register re-init routine */
+}
+
+void
+proto_reg_handoff_rlogin(void) {
+
+ /* dissector install routine */
+
+ dissector_handle_t rlogin_handle;
+
+ rlogin_handle = create_dissector_handle(dissect_rlogin, proto_rlogin);
+ dissector_add("tcp.port", TCP_PORT_RLOGIN, rlogin_handle);
+}
diff --git a/epan/dissectors/packet-rmcp.c b/epan/dissectors/packet-rmcp.c
new file mode 100644
index 0000000000..eb03f595b8
--- /dev/null
+++ b/epan/dissectors/packet-rmcp.c
@@ -0,0 +1,191 @@
+/* packet-rmcp.c
+ * Routines for RMCP packet dissection
+ *
+ * Duncan Laurie <duncan@sun.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+/*
+ * See
+ *
+ * http://www.dmtf.org/standards/standard_alert.php
+ *
+ * (the ASF specification includes RMCP)
+ */
+
+static int proto_rmcp = -1;
+static int hf_rmcp_version = -1;
+static int hf_rmcp_sequence = -1;
+static int hf_rmcp_class = -1;
+static int hf_rmcp_type = -1;
+
+static gint ett_rmcp = -1;
+static gint ett_rmcp_typeclass = -1;
+
+static dissector_handle_t data_handle;
+static dissector_table_t rmcp_dissector_table;
+
+#define UDP_PORT_RMCP 623
+#define UDP_PORT_RMCP_SECURE 664
+
+#define RMCP_TYPE_MASK 0x80
+#define RMCP_TYPE_NORM 0x00
+#define RMCP_TYPE_ACK 0x01
+
+static const value_string rmcp_type_vals[] = {
+ { RMCP_TYPE_NORM, "Normal RMCP" },
+ { RMCP_TYPE_ACK, "RMCP ACK" },
+ { 0, NULL }
+};
+
+#define RMCP_CLASS_MASK 0x1f
+#define RMCP_CLASS_ASF 0x06
+#define RMCP_CLASS_IPMI 0x07
+#define RMCP_CLASS_OEM 0x08
+
+static const value_string rmcp_class_vals[] = {
+ { RMCP_CLASS_ASF, "ASF" },
+ { RMCP_CLASS_IPMI, "IPMI" },
+ { RMCP_CLASS_OEM, "OEM" },
+ { 0, NULL }
+};
+
+static int
+dissect_rmcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *rmcp_tree = NULL, *field_tree;
+ proto_item *ti, *tf;
+ tvbuff_t *next_tvb;
+ guint8 class;
+ gchar *class_str;
+ guint8 type;
+
+ /*
+ * Check whether it's a known class value; if not, assume it's
+ * not RMCP.
+ */
+ if (!tvb_bytes_exist(tvb, 3, 1))
+ return 0; /* class value byte not present */
+ class = tvb_get_guint8(tvb, 3);
+
+ /* Get the normal/ack bit from the RMCP class */
+ type = (class & RMCP_TYPE_MASK) >> 7;
+ class &= RMCP_CLASS_MASK;
+
+ class_str = match_strval(class, rmcp_class_vals);
+ if (class_str == NULL)
+ return 0; /* unknown class value */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RMCP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s, Class: %s",
+ val_to_str(type, rmcp_type_vals, "Unknown (0x%02x)"),
+ class_str);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_rmcp, tvb, 0, 4,
+ "Remote Management Control Protocol, Class: %s",
+ class_str);
+ rmcp_tree = proto_item_add_subtree(ti, ett_rmcp);
+
+ proto_tree_add_item(rmcp_tree, hf_rmcp_version, tvb, 0, 1, TRUE);
+ proto_tree_add_item(rmcp_tree, hf_rmcp_sequence, tvb, 2, 1, TRUE);
+
+ tf = proto_tree_add_text(rmcp_tree, tvb, 3, 1, "Type: %s, Class: %s",
+ val_to_str(type, rmcp_type_vals, "Unknown (0x%02x)"),
+ class_str);
+
+ field_tree = proto_item_add_subtree(tf, ett_rmcp_typeclass);
+
+ proto_tree_add_item(field_tree, hf_rmcp_class, tvb, 3, 1, TRUE);
+ proto_tree_add_item(field_tree, hf_rmcp_type, tvb, 3, 1, TRUE);
+ }
+
+ next_tvb = tvb_new_subset(tvb, 4, -1, -1);
+
+ if (!dissector_try_port(rmcp_dissector_table, class, next_tvb, pinfo,
+ tree))
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+
+ return tvb_length(tvb);
+}
+
+void
+proto_register_rmcp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rmcp_version, {
+ "Version", "rmcp.version",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "RMCP Version", HFILL }},
+ { &hf_rmcp_sequence, {
+ "Sequence", "rmcp.sequence",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "RMCP Sequence", HFILL }},
+ { &hf_rmcp_class, {
+ "Class", "rmcp.class",
+ FT_UINT8, BASE_HEX,
+ VALS(rmcp_class_vals), RMCP_CLASS_MASK,
+ "RMCP Class", HFILL }},
+ { &hf_rmcp_type, {
+ "Message Type", "rmcp.type",
+ FT_UINT8, BASE_HEX,
+ VALS(rmcp_type_vals), RMCP_TYPE_MASK,
+ "RMCP Message Type", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_rmcp,
+ &ett_rmcp_typeclass,
+ };
+
+ proto_rmcp = proto_register_protocol(
+ "Remote Management Control Protocol", "RMCP", "rmcp");
+
+ proto_register_field_array(proto_rmcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ rmcp_dissector_table = register_dissector_table(
+ "rmcp.class", "RMCP Class", FT_UINT8, BASE_HEX);
+}
+
+void
+proto_reg_handoff_rmcp(void)
+{
+ dissector_handle_t rmcp_handle;
+
+ data_handle = find_dissector("data");
+
+ rmcp_handle = new_create_dissector_handle(dissect_rmcp, proto_rmcp);
+ dissector_add("udp.port", UDP_PORT_RMCP, rmcp_handle);
+ dissector_add("udp.port", UDP_PORT_RMCP_SECURE, rmcp_handle);
+}
diff --git a/epan/dissectors/packet-rmi.c b/epan/dissectors/packet-rmi.c
new file mode 100644
index 0000000000..ca1ed61d2a
--- /dev/null
+++ b/epan/dissectors/packet-rmi.c
@@ -0,0 +1,384 @@
+/* packet-rmi.c
+ * Routines for java rmiregistry dissection
+ * Copyright 2002, Michael Stiller <ms@2scale.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+#include "packet-rmi.h"
+
+static void
+dissect_ser(tvbuff_t *tvb, proto_tree *tree);
+
+static rmi_type
+get_rmi_type(const guchar *data, int datalen);
+
+/* Initialize the protocol and registered fields */
+static int proto_rmi = -1;
+static int proto_ser = -1;
+static int hf_rmi_magic = -1;
+static int hf_rmi_version = -1;
+static int hf_rmi_protocol = -1;
+static int hf_rmi_inputmessage = -1;
+static int hf_rmi_outputmessage = -1;
+static int hf_rmi_epid_length = -1;
+static int hf_rmi_epid_hostname = -1;
+static int hf_rmi_epid_port = -1;
+
+static int hf_ser_magic = -1;
+static int hf_ser_version = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_rmi = -1;
+static gint ett_rmi_magic = -1;
+static gint ett_rmi_version = -1;
+static gint ett_rmi_inputmessage = -1;
+static gint ett_rmi_outputmessage = -1;
+static gint ett_rmi_epid_length = -1;
+static gint ett_rmi_epid_hostname = -1;
+static gint ett_rmi_epid_port = -1;
+
+static gint ett_ser = -1;
+
+/*
+ * See
+ *
+ * http://java.sun.com/products/jdk/1.2/docs/guide/rmi/spec/rmi-protocol.doc1.html
+ *
+ * for RMI, and
+ *
+ * http://java.sun.com/products/jdk/1.2/docs/guide/serialization/spec/protocol.doc.html
+ *
+ * for the serialization protocol.
+ */
+
+#define TCP_PORT_RMI 1099
+
+static const value_string rmi_protocol_str[] = {
+ {RMI_OUTPUTSTREAM_PROTOCOL_STREAM, "StreamProtocol"},
+ {RMI_OUTPUTSTREAM_PROTOCOL_SINGLEOP, "SingleOpProtocol"},
+ {RMI_OUTPUTSTREAM_PROTOCOL_MULTIPLEX, "MultiPlexProtocol"},
+ {0, NULL}
+};
+
+static const value_string rmi_output_message_str[] = {
+ {RMI_OUTPUTSTREAM_MESSAGE_CALL, "Call"},
+ {RMI_OUTPUTSTREAM_MESSAGE_PING, "Ping"},
+ {RMI_OUTPUTSTREAM_MESSAGE_DGCACK, "DgcAck"},
+ {0, NULL}
+};
+
+static const value_string rmi_input_message_str[] = {
+ {RMI_INPUTSTREAM_MESSAGE_ACK, "ProtocolAck"},
+ {RMI_INPUTSTREAM_MESSAGE_NOTSUPPORTED, "ProtocolNotSupported"},
+ {RMI_INPUTSTREAM_MESSAGE_RETURNDATA, "ReturnData"},
+ {RMI_INPUTSTREAM_MESSAGE_PINGACK, "PingAck"},
+ {0, NULL}
+};
+
+static void
+dissect_rmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *rmi_tree;
+
+ tvbuff_t *next_tvb;
+
+ gint offset;
+ gint next_offset;
+ int datalen;
+ const guchar *data;
+
+ guint16 version, len, port;
+ guint8 message, proto;
+
+ rmi_type rmitype;
+
+ char epid_hostname[256];
+
+ offset = 0;
+ rmitype = 0;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RMI");
+
+ datalen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ data = tvb_get_ptr(tvb, offset, datalen);
+
+ rmitype = get_rmi_type(data, datalen);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ switch(rmitype) {
+ case RMI_OUTPUTSTREAM:
+ version = tvb_get_ntohs(tvb,4);
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "JRMI, Version: %d, ", version);
+
+ proto = tvb_get_guint8(tvb, 6);
+ col_append_str(pinfo->cinfo, COL_INFO,
+ val_to_str(proto, rmi_protocol_str,
+ "Unknown protocol"));
+ break;
+ case RMI_OUTPUTMESSAGE:
+ message = tvb_get_guint8(tvb,0);
+ col_add_str(pinfo->cinfo, COL_INFO,
+ "JRMI, ");
+ col_append_str(pinfo->cinfo, COL_INFO,
+ val_to_str(message, rmi_output_message_str,
+ "Unknown message"));
+ break;
+ case RMI_INPUTSTREAM:
+ message = tvb_get_guint8(tvb,0);
+ col_add_str(pinfo->cinfo, COL_INFO,
+ "JRMI, ");
+ col_append_str(pinfo->cinfo, COL_INFO,
+ val_to_str(message, rmi_input_message_str,
+ "Unknown message"));
+ break;
+ case SERIALIZATION_DATA:
+ version = tvb_get_ntohs(tvb,2);
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Serialization data, Version: %d", version);
+ break;
+ default:
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+ break;
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_rmi, tvb, 0, -1, FALSE);
+ rmi_tree = proto_item_add_subtree(ti, ett_rmi);
+ switch(rmitype) {
+ case RMI_OUTPUTSTREAM:
+ /* XXX - uint, or string? */
+ proto_tree_add_uint(rmi_tree, hf_rmi_magic,
+ tvb, offset, 4, tvb_get_ntohl(tvb,0));
+ proto_tree_add_item(rmi_tree, hf_rmi_version,
+ tvb, offset + 4, 2, FALSE);
+ proto_tree_add_item(rmi_tree, hf_rmi_protocol,
+ tvb, offset + 6, 1, FALSE);
+ break;
+ case RMI_INPUTSTREAM:
+ message = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(rmi_tree, hf_rmi_inputmessage,
+ tvb, offset, 1, message);
+ if(message == RMI_INPUTSTREAM_MESSAGE_ACK) {
+ proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
+ "EndPointIdentifier");
+ /* MESSAGE_ACK should include EndpointIdentifier */
+ len = tvb_get_ntohs(tvb, 1);
+ proto_tree_add_uint(rmi_tree, hf_rmi_epid_length,
+ tvb, offset + 1, 2, len);
+ memset(epid_hostname, 0, sizeof(epid_hostname));
+ if (len < sizeof(epid_hostname)) {
+ strncpy(epid_hostname,tvb_get_ptr(tvb, offset + 3, len),
+ sizeof(epid_hostname));
+ } else {
+ strncpy(epid_hostname,
+ "<string too long>", sizeof(epid_hostname));
+ }
+ epid_hostname[sizeof(epid_hostname)-1] = '\0';
+ proto_tree_add_string(rmi_tree, hf_rmi_epid_hostname,
+ tvb, offset + 3, strlen(epid_hostname),
+ epid_hostname);
+
+ port = tvb_get_ntohs(tvb, offset + len + 5);
+ proto_tree_add_uint(rmi_tree, hf_rmi_epid_port,
+ tvb, offset + len + 5, 2, port);
+ }
+ if(message == RMI_INPUTSTREAM_MESSAGE_RETURNDATA) {
+ proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
+ "Serialization Data");
+ next_tvb = tvb_new_subset(tvb, offset + 1, -1, -1);
+ dissect_ser(next_tvb, tree);
+ }
+ break;
+ case RMI_OUTPUTMESSAGE:
+ message = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(rmi_tree, hf_rmi_outputmessage,
+ tvb, offset, 1, message);
+ if(message == RMI_OUTPUTSTREAM_MESSAGE_CALL) {
+ proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
+ "Serialization Data");
+ /* XXX */
+ next_tvb = tvb_new_subset(tvb, offset + 1, -1, -1);
+ dissect_ser(next_tvb, tree);
+ }
+ if(message == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
+ proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
+ "UniqueIdentifier");
+ }
+ break;
+ case SERIALIZATION_DATA:
+ dissect_ser(tvb, tree);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
+dissect_ser(tvbuff_t *tvb, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *ser_tree;
+
+ gint offset;
+
+ offset = 0;
+
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_ser, tvb, 0, -1, FALSE);
+ ser_tree = proto_item_add_subtree(ti, ett_ser);
+ proto_tree_add_item(ser_tree, hf_ser_magic,
+ tvb, offset, 2, FALSE);
+ proto_tree_add_item(ser_tree, hf_ser_version,
+ tvb, offset + 2, 2, FALSE);
+
+ }
+}
+
+static rmi_type
+get_rmi_type(const guchar *data, int datalen)
+{
+ guint16 ser_magic;
+
+ if (datalen >= 2) {
+ ser_magic = data[0] << 8 | data[1];
+ if (ser_magic == SER_STREAM_MAGIC) {
+ return SERIALIZATION_DATA;
+ }
+ }
+ if (datalen >= 4) {
+ if(strncmp(data, RMI_MAGIC, 4) == 0) {
+ return RMI_OUTPUTSTREAM;
+ }
+ }
+ if (datalen >= 1) {
+ if (data[0] == RMI_INPUTSTREAM_MESSAGE_ACK ||
+ data[0] == RMI_INPUTSTREAM_MESSAGE_NOTSUPPORTED ||
+ data[0] == RMI_INPUTSTREAM_MESSAGE_RETURNDATA ||
+ data[0] == RMI_INPUTSTREAM_MESSAGE_PINGACK) {
+ return RMI_INPUTSTREAM;
+ }
+ }
+ if (datalen >= 1) {
+ if (data[0] == RMI_OUTPUTSTREAM_MESSAGE_CALL ||
+ data[0] == RMI_OUTPUTSTREAM_MESSAGE_PING ||
+ data[0] == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
+ return RMI_OUTPUTMESSAGE;
+ }
+ }
+ return CONTINUATION;
+}
+
+void
+proto_register_rmi(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_rmi_magic,
+ { "Magic", "rmi.magic",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "RMI Header Magic", HFILL }},
+ { &hf_rmi_version,
+ { "Version", "rmi.version",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "RMI Protocol Version", HFILL }},
+ { &hf_rmi_protocol,
+ { "Protocol","rmi.protocol",
+ FT_UINT8, BASE_HEX, VALS(rmi_protocol_str), 0x0,
+ "RMI Protocol Type", HFILL }},
+ { &hf_rmi_inputmessage,
+ { "Input Stream Message", "rmi.inputstream.message",
+ FT_UINT8, BASE_HEX, VALS(rmi_input_message_str), 0x0,
+ "RMI Inputstream Message Token", HFILL }},
+ { &hf_rmi_outputmessage,
+ { "Output Stream Message", "rmi.outputstream.message",
+ FT_UINT8, BASE_HEX, VALS(rmi_output_message_str), 0x0,
+ "RMI Outputstream Message token", HFILL }},
+ { &hf_rmi_epid_length,
+ { "Length", "rmi.endpoint_id.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "RMI Endpointidentifier Length", HFILL }},
+ { &hf_rmi_epid_hostname,
+ { "Hostname", "rmi.endpoint_id.hostname",
+ FT_STRING, BASE_HEX, NULL, 0x0,
+ "RMI Endpointidentifier Hostname", HFILL }},
+ { &hf_rmi_epid_port,
+ { "Port", "rmi.endpoint_id.port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "RMI Endpointindentifier Port", HFILL }},
+
+ { &hf_ser_magic,
+ { "Magic", "rmi.ser.magic",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Java Serialization Magic", HFILL }},
+ { &hf_ser_version,
+ { "Version", "rmi.ser.version",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Java Serialization Version", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_rmi,
+ &ett_rmi_magic,
+ &ett_rmi_version,
+ &ett_rmi_inputmessage,
+ &ett_rmi_outputmessage,
+ &ett_rmi_epid_length,
+ &ett_rmi_epid_hostname,
+ &ett_rmi_epid_port,
+ &ett_ser,
+ };
+
+ proto_rmi = proto_register_protocol("Java RMI", "RMI", "rmi");
+ proto_ser = proto_register_protocol("Java Serialization", "Serialization",
+ "serialization");
+ proto_register_field_array(proto_rmi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_rmi(void)
+{
+ dissector_handle_t rmi_handle;
+
+ rmi_handle = create_dissector_handle(dissect_rmi, proto_rmi);
+ dissector_add("tcp.port", TCP_PORT_RMI, rmi_handle);
+}
diff --git a/epan/dissectors/packet-rmi.h b/epan/dissectors/packet-rmi.h
new file mode 100644
index 0000000000..80ed7b357a
--- /dev/null
+++ b/epan/dissectors/packet-rmi.h
@@ -0,0 +1,69 @@
+/* packet-rmi.h
+ * header file for java rmiregistry dissection
+ * Copyright 2002, Michael Stiller <ms@2scale.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __PACKET_RMI_H__
+#define __PACKET_RMI_H__
+
+#define SER_STREAM_MAGIC 0xaced
+
+#define SER_STREAM_VERSION 5
+
+#define SER_TC_NULL 0x70
+#define SER_TC_REFERENCE 0x71
+#define SER_TC_CLASSDESC 0x72
+#define SER_TC_OBJECT 0x73
+#define SER_TC_STRING 0x74
+#define SER_TC_ARRAY 0x75
+#define SER_TC_CLASS 0x76
+#define SER_TC_BLOCKDATA 0x77
+#define SER_TC_ENDBLOCKDATA 0x78
+#define SER_TC_RESET 0x79
+#define SER_TC_BLOCKDATALONG 0x7A
+#define SER_TC_EXCEPTION 0x7B
+
+#define RMI_MAGIC "JRMI"
+#define RMI_MAGIC_HEX 0x4a524d49
+
+#define RMI_OUTPUTSTREAM_PROTOCOL_STREAM 0x4b
+#define RMI_OUTPUTSTREAM_PROTOCOL_SINGLEOP 0x4c
+#define RMI_OUTPUTSTREAM_PROTOCOL_MULTIPLEX 0x4d
+
+#define RMI_OUTPUTSTREAM_MESSAGE_CALL 0x50
+#define RMI_OUTPUTSTREAM_MESSAGE_PING 0x52
+#define RMI_OUTPUTSTREAM_MESSAGE_DGCACK 0x54
+
+#define RMI_INPUTSTREAM_MESSAGE_ACK 0x4e
+#define RMI_INPUTSTREAM_MESSAGE_NOTSUPPORTED 0x4f
+#define RMI_INPUTSTREAM_MESSAGE_RETURNDATA 0x51
+#define RMI_INPUTSTREAM_MESSAGE_PINGACK 0x53
+
+typedef enum {
+ CONTINUATION = 1,
+ RMI_OUTPUTSTREAM = 2,
+ RMI_OUTPUTMESSAGE = 3,
+ RMI_INPUTSTREAM = 16,
+ SERIALIZATION_DATA = 128
+} rmi_type;
+
+#endif
diff --git a/epan/dissectors/packet-rmp.c b/epan/dissectors/packet-rmp.c
new file mode 100644
index 0000000000..bef7158581
--- /dev/null
+++ b/epan/dissectors/packet-rmp.c
@@ -0,0 +1,270 @@
+/* packet-rmp.c
+ * Routines for HP remote management protocol
+ * Gilbert Ramirez <jochen@scram.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "etypes.h"
+
+#include "packet-hpext.h"
+
+static dissector_handle_t data_handle;
+
+static int proto_rmp = -1;
+
+static int hf_rmp_type = -1;
+static int hf_rmp_retcode = -1;
+static int hf_rmp_seqnum = -1;
+static int hf_rmp_sessionid = -1;
+static int hf_rmp_version = -1;
+static int hf_rmp_machtype = -1;
+static int hf_rmp_filename = -1;
+static int hf_rmp_offset = -1;
+static int hf_rmp_size = -1;
+
+static gint ett_rmp = -1;
+
+/*
+ * Possible values for "rmp_type" fields.
+ */
+
+#define RMP_BOOT_REQ 1 /* boot request packet */
+#define RMP_BOOT_REPL 129 /* boot reply packet */
+#define RMP_READ_REQ 2 /* read request packet */
+#define RMP_READ_REPL 130 /* read reply packet */
+#define RMP_BOOT_DONE 3 /* boot complete packet */
+
+/*
+ * RMP error codes
+ */
+
+#define RMP_E_OKAY 0
+#define RMP_E_EOF 2 /* read reply: returned end of file */
+#define RMP_E_ABORT 3 /* abort operation */
+#define RMP_E_BUSY 4 /* boot reply: server busy */
+#define RMP_E_TIMEOUT 5 /* lengthen time out (not implemented) */
+#define RMP_E_NOFILE 16 /* boot reply: file does not exist */
+#define RMP_E_OPENFILE 17 /* boot reply: file open failed */
+#define RMP_E_NODFLT 18 /* boot reply: default file does not exist */
+#define RMP_E_OPENDFLT 19 /* boot reply: default file open failed */
+#define RMP_E_BADSID 25 /* read reply: bad session ID */
+#define RMP_E_BADPACKET 27 /* Bad packet detected */
+
+const value_string rmp_type_vals[] = {
+ { RMP_BOOT_REQ, "Boot Request" },
+ { RMP_BOOT_REPL, "Boot Reply" },
+ { RMP_READ_REQ, "Read Request" },
+ { RMP_READ_REPL, "Read Reply" },
+ { RMP_BOOT_DONE, "Boot Done" },
+ { 0x00, NULL }
+};
+
+const value_string rmp_error_vals[] = {
+ { RMP_E_OKAY, "OK" },
+ { RMP_E_EOF, "End Of File" },
+ { RMP_E_ABORT, "Abort Operation" },
+ { RMP_E_BUSY, "Server Busy" },
+ { RMP_E_TIMEOUT, "Lengthen Time Out" },
+ { RMP_E_NOFILE, "File Does Not Exist" },
+ { RMP_E_OPENFILE, "File Open Failed" },
+ { RMP_E_NODFLT, "Default File Does Not Exist" },
+ { RMP_E_OPENDFLT, "Default File Open Failed" },
+ { RMP_E_BADSID, "Bad Session Id" },
+ { RMP_E_OPENDFLT, "Bad Packet Detected" },
+ { 0x00, NULL }
+};
+
+static void
+dissect_rmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *rmp_tree = NULL;
+ proto_item *ti = NULL;
+ guint8 type, len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RMP");
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ type = tvb_get_guint8(tvb, 0);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str(type, rmp_type_vals, "Unknown Type"));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_rmp, tvb, 0, -1, FALSE);
+ rmp_tree = proto_item_add_subtree(ti, ett_rmp);
+ proto_tree_add_uint(rmp_tree, hf_rmp_type, tvb, 0, 1, type);
+
+ switch (type) {
+ case RMP_BOOT_REQ:
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_retcode, tvb, 1, 1, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_seqnum, tvb, 2, 4, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_sessionid, tvb, 6, 2, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_version, tvb, 8, 2, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_machtype, tvb, 10, 20, FALSE);
+ /* The remaining fields are optional */
+ if(!tvb_offset_exists(tvb, 30))
+ return;
+ len = tvb_get_guint8(tvb, 30);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_filename, tvb, 30, 1, FALSE);
+ if(tvb_offset_exists(tvb, len+31))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, len+31, -1, -1),
+ pinfo, tree);
+ break;
+
+ case RMP_BOOT_REPL:
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_retcode, tvb, 1, 1, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_seqnum, tvb, 2, 4, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_sessionid, tvb, 6, 2, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_version, tvb, 8, 2, FALSE);
+ len = tvb_get_guint8(tvb, 10);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_filename, tvb, 10, 1, FALSE);
+ if(tvb_offset_exists(tvb, len+11))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, len+11, -1, -1),
+ pinfo, tree);
+ break;
+
+ case RMP_READ_REQ:
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_retcode, tvb, 1, 1, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_offset, tvb, 2, 4, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_sessionid, tvb, 6, 2, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_size, tvb, 8, 2, FALSE);
+ if(tvb_offset_exists(tvb, 10))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 10, -1, -1),
+ pinfo, tree);
+ break;
+
+ case RMP_READ_REPL:
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_retcode, tvb, 1, 1, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_offset, tvb, 2, 4, FALSE);
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_sessionid, tvb, 6, 2, FALSE);
+ call_dissector(data_handle, tvb_new_subset(tvb,
+ 8, -1, -1), pinfo, rmp_tree);
+ break;
+
+ case RMP_BOOT_DONE:
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_retcode, tvb, 1, 1, FALSE);
+ proto_tree_add_text(rmp_tree,
+ tvb, 2, 4, "Reserved");
+ proto_tree_add_item(rmp_tree,
+ hf_rmp_sessionid, tvb, 6, 2, FALSE);
+ if(tvb_offset_exists(tvb, 8))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 6, -1, -1),
+ pinfo, tree);
+ break;
+ default:
+ call_dissector(data_handle, tvb_new_subset(tvb,
+ 1, -1, -1), pinfo, tree);
+ }
+ }
+}
+
+void
+proto_register_rmp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rmp_type,
+ { "Type", "rmp.type", FT_UINT8, BASE_HEX,
+ VALS(rmp_type_vals), 0x0, "", HFILL }},
+ { &hf_rmp_retcode,
+ { "Returncode", "rmp.retcode", FT_UINT8, BASE_HEX,
+ VALS(rmp_error_vals), 0x0, "", HFILL }},
+ { &hf_rmp_seqnum,
+ { "Sequence Number", "rmp.seqnum", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_rmp_sessionid,
+ { "Session ID", "rmp.sessionid", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_rmp_version,
+ { "Version", "rmp.version", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_rmp_machtype,
+ { "Machine Type", "rmp.machtype", FT_STRING, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_rmp_filename,
+ { "Filename", "rmp.filename", FT_UINT_STRING, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ { &hf_rmp_offset,
+ { "Offset", "rmp.offset", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_rmp_size,
+ { "Size", "rmp.size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_rmp,
+ };
+
+ proto_rmp = proto_register_protocol(
+ "HP Remote Maintenance Protocol", "RMP", "rmp");
+ proto_register_field_array(proto_rmp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("rmp", dissect_rmp, proto_rmp);
+}
+
+void
+proto_reg_handoff_rmp(void)
+{
+ dissector_handle_t rmp_handle;
+
+ data_handle = find_dissector("data");
+
+ rmp_handle = find_dissector("rmp");
+ dissector_add("hpext.dxsap", HPEXT_DXSAP, rmp_handle);
+ dissector_add("hpext.dxsap", HPEXT_SXSAP, rmp_handle);
+}
diff --git a/epan/dissectors/packet-rpc.c b/epan/dissectors/packet-rpc.c
new file mode 100644
index 0000000000..07de41b8f5
--- /dev/null
+++ b/epan/dissectors/packet-rpc.c
@@ -0,0 +1,3560 @@
+/* packet-rpc.c
+ * Routines for rpc dissection
+ * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-smb.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "packet-rpc.h"
+#include "packet-frame.h"
+#include "packet-tcp.h"
+#include "prefs.h"
+#include "reassemble.h"
+#include "rpc_defrag.h"
+#include "packet-nfs.h"
+#include "tap.h"
+
+/*
+ * See:
+ *
+ * RFC 1831, "RPC: Remote Procedure Call Protocol Specification
+ * Version 2";
+ *
+ * RFC 1832, "XDR: External Data Representation Standard";
+ *
+ * RFC 2203, "RPCSEC_GSS Protocol Specification".
+ *
+ * See also
+ *
+ * RFC 2695, "Authentication Mechanisms for ONC RPC"
+ *
+ * although we don't currently dissect AUTH_DES or AUTH_KERB.
+ */
+
+/* desegmentation of RPC over TCP */
+static gboolean rpc_desegment = TRUE;
+
+/* defragmentation of fragmented RPC over TCP records */
+static gboolean rpc_defragment = FALSE;
+
+/* try to dissect RPC packets for programs that are not known
+ * (proprietary ones) by ethereal.
+ */
+static gboolean rpc_dissect_unknown_programs = FALSE;
+
+
+static struct true_false_string yesno = { "Yes", "No" };
+
+static int rpc_tap = -1;
+
+static const value_string rpc_msg_type[] = {
+ { RPC_CALL, "Call" },
+ { RPC_REPLY, "Reply" },
+ { 0, NULL }
+};
+
+static const value_string rpc_reply_state[] = {
+ { MSG_ACCEPTED, "accepted" },
+ { MSG_DENIED, "denied" },
+ { 0, NULL }
+};
+
+const value_string rpc_auth_flavor[] = {
+ { AUTH_NULL, "AUTH_NULL" },
+ { AUTH_UNIX, "AUTH_UNIX" },
+ { AUTH_SHORT, "AUTH_SHORT" },
+ { AUTH_DES, "AUTH_DES" },
+ { RPCSEC_GSS, "RPCSEC_GSS" },
+ { AUTH_GSSAPI, "AUTH_GSSAPI" },
+ { 0, NULL }
+};
+
+static const value_string rpc_authgss_proc[] = {
+ { RPCSEC_GSS_DATA, "RPCSEC_GSS_DATA" },
+ { RPCSEC_GSS_INIT, "RPCSEC_GSS_INIT" },
+ { RPCSEC_GSS_CONTINUE_INIT, "RPCSEC_GSS_CONTINUE_INIT" },
+ { RPCSEC_GSS_DESTROY, "RPCSEC_GSS_DESTROY" },
+ { 0, NULL }
+};
+
+static const value_string rpc_authgssapi_proc[] = {
+ { AUTH_GSSAPI_EXIT, "AUTH_GSSAPI_EXIT" },
+ { AUTH_GSSAPI_INIT, "AUTH_GSSAPI_INIT" },
+ { AUTH_GSSAPI_CONTINUE_INIT, "AUTH_GSSAPI_CONTINUE_INIT" },
+ { AUTH_GSSAPI_MSG, "AUTH_GSSAPI_MSG" },
+ { AUTH_GSSAPI_DESTROY, "AUTH_GSSAPI_DESTROY" },
+ { 0, NULL }
+};
+
+value_string rpc_authgss_svc[] = {
+ { RPCSEC_GSS_SVC_NONE, "rpcsec_gss_svc_none" },
+ { RPCSEC_GSS_SVC_INTEGRITY, "rpcsec_gss_svc_integrity" },
+ { RPCSEC_GSS_SVC_PRIVACY, "rpcsec_gss_svc_privacy" },
+ { 0, NULL }
+};
+
+static const value_string rpc_accept_state[] = {
+ { SUCCESS, "RPC executed successfully" },
+ { PROG_UNAVAIL, "remote hasn't exported program" },
+ { PROG_MISMATCH, "remote can't support version #" },
+ { PROC_UNAVAIL, "program can't support procedure" },
+ { GARBAGE_ARGS, "procedure can't decode params" },
+ { 0, NULL }
+};
+
+static const value_string rpc_reject_state[] = {
+ { RPC_MISMATCH, "RPC_MISMATCH" },
+ { AUTH_ERROR, "AUTH_ERROR" },
+ { 0, NULL }
+};
+
+static const value_string rpc_auth_state[] = {
+ { AUTH_BADCRED, "bad credential (seal broken)" },
+ { AUTH_REJECTEDCRED, "client must begin new session" },
+ { AUTH_BADVERF, "bad verifier (seal broken)" },
+ { AUTH_REJECTEDVERF, "verifier expired or replayed" },
+ { AUTH_TOOWEAK, "rejected for security reasons" },
+ { RPCSEC_GSSCREDPROB, "GSS credential problem" },
+ { RPCSEC_GSSCTXPROB, "GSS context problem" },
+ { 0, NULL }
+};
+
+static const value_string rpc_authdes_namekind[] = {
+ { AUTHDES_NAMEKIND_FULLNAME, "ADN_FULLNAME" },
+ { AUTHDES_NAMEKIND_NICKNAME, "ADN_NICKNAME" },
+ { 0, NULL }
+};
+
+/* the protocol number */
+static int proto_rpc = -1;
+static int hf_rpc_reqframe = -1;
+static int hf_rpc_repframe = -1;
+static int hf_rpc_lastfrag = -1;
+static int hf_rpc_fraglen = -1;
+static int hf_rpc_xid = -1;
+static int hf_rpc_msgtype = -1;
+static int hf_rpc_version = -1;
+static int hf_rpc_version_min = -1;
+static int hf_rpc_version_max = -1;
+static int hf_rpc_program = -1;
+static int hf_rpc_programversion = -1;
+static int hf_rpc_programversion_min = -1;
+static int hf_rpc_programversion_max = -1;
+static int hf_rpc_procedure = -1;
+static int hf_rpc_auth_flavor = -1;
+static int hf_rpc_auth_length = -1;
+static int hf_rpc_auth_machinename = -1;
+static int hf_rpc_auth_stamp = -1;
+static int hf_rpc_auth_uid = -1;
+static int hf_rpc_auth_gid = -1;
+static int hf_rpc_authgss_v = -1;
+static int hf_rpc_authgss_proc = -1;
+static int hf_rpc_authgss_seq = -1;
+static int hf_rpc_authgss_svc = -1;
+static int hf_rpc_authgss_ctx = -1;
+static int hf_rpc_authgss_major = -1;
+static int hf_rpc_authgss_minor = -1;
+static int hf_rpc_authgss_window = -1;
+static int hf_rpc_authgss_token_length = -1;
+static int hf_rpc_authgss_data_length = -1;
+static int hf_rpc_authgss_data = -1;
+static int hf_rpc_authgss_checksum = -1;
+static int hf_rpc_authgssapi_v = -1;
+static int hf_rpc_authgssapi_msg = -1;
+static int hf_rpc_authgssapi_msgv = -1;
+static int hf_rpc_authgssapi_handle = -1;
+static int hf_rpc_authgssapi_isn = -1;
+static int hf_rpc_authdes_namekind = -1;
+static int hf_rpc_authdes_netname = -1;
+static int hf_rpc_authdes_convkey = -1;
+static int hf_rpc_authdes_window = -1;
+static int hf_rpc_authdes_nickname = -1;
+static int hf_rpc_authdes_timestamp = -1;
+static int hf_rpc_authdes_windowverf = -1;
+static int hf_rpc_authdes_timeverf = -1;
+static int hf_rpc_state_accept = -1;
+static int hf_rpc_state_reply = -1;
+static int hf_rpc_state_reject = -1;
+static int hf_rpc_state_auth = -1;
+static int hf_rpc_dup = -1;
+static int hf_rpc_call_dup = -1;
+static int hf_rpc_reply_dup = -1;
+static int hf_rpc_value_follows = -1;
+static int hf_rpc_array_len = -1;
+static int hf_rpc_time = -1;
+static int hf_rpc_fragments = -1;
+static int hf_rpc_fragment = -1;
+static int hf_rpc_fragment_overlap = -1;
+static int hf_rpc_fragment_overlap_conflict = -1;
+static int hf_rpc_fragment_multiple_tails = -1;
+static int hf_rpc_fragment_too_long_fragment = -1;
+static int hf_rpc_fragment_error = -1;
+
+static gint ett_rpc = -1;
+static gint ett_rpc_unknown_program = -1;
+static gint ett_rpc_fragments = -1;
+static gint ett_rpc_fragment = -1;
+static gint ett_rpc_fraghdr = -1;
+static gint ett_rpc_string = -1;
+static gint ett_rpc_cred = -1;
+static gint ett_rpc_verf = -1;
+static gint ett_rpc_gids = -1;
+static gint ett_rpc_gss_token = -1;
+static gint ett_rpc_gss_data = -1;
+static gint ett_rpc_array = -1;
+static gint ett_rpc_authgssapi_msg = -1;
+
+static dissector_handle_t rpc_tcp_handle;
+static dissector_handle_t rpc_handle;
+static dissector_handle_t gssapi_handle;
+static dissector_handle_t data_handle;
+
+static int max_rpc_tcp_pdu_size = 262144;
+
+static const fragment_items rpc_frag_items = {
+ &ett_rpc_fragment,
+ &ett_rpc_fragments,
+ &hf_rpc_fragments,
+ &hf_rpc_fragment,
+ &hf_rpc_fragment_overlap,
+ &hf_rpc_fragment_overlap_conflict,
+ &hf_rpc_fragment_multiple_tails,
+ &hf_rpc_fragment_too_long_fragment,
+ &hf_rpc_fragment_error,
+ NULL,
+ "fragments"
+};
+
+/* Hash table with info on RPC program numbers */
+GHashTable *rpc_progs;
+
+/* Hash table with info on RPC procedure numbers */
+GHashTable *rpc_procs;
+
+static void dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static void dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/***********************************/
+/* Hash array with procedure names */
+/***********************************/
+
+/* compare 2 keys */
+static gint
+rpc_proc_equal(gconstpointer k1, gconstpointer k2)
+{
+ const rpc_proc_info_key* key1 = (const rpc_proc_info_key*) k1;
+ const rpc_proc_info_key* key2 = (const rpc_proc_info_key*) k2;
+
+ return ((key1->prog == key2->prog &&
+ key1->vers == key2->vers &&
+ key1->proc == key2->proc) ?
+ TRUE : FALSE);
+}
+
+/* calculate a hash key */
+static guint
+rpc_proc_hash(gconstpointer k)
+{
+ const rpc_proc_info_key* key = (const rpc_proc_info_key*) k;
+
+ return (key->prog ^ (key->vers<<16) ^ (key->proc<<24));
+}
+
+
+/* insert some entries */
+void
+rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table,
+ int procedure_hf)
+{
+ rpc_prog_info_key rpc_prog_key;
+ rpc_prog_info_value *rpc_prog;
+ const vsff *proc;
+
+ /*
+ * Add the operation number hfinfo value for this version of the
+ * program.
+ */
+ rpc_prog_key.prog = prog;
+ rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key);
+ g_assert(rpc_prog != NULL);
+ rpc_prog->procedure_hfs = g_array_set_size(rpc_prog->procedure_hfs,
+ vers);
+ g_array_insert_val(rpc_prog->procedure_hfs, vers, procedure_hf);
+
+ for (proc = proc_table ; proc->strptr!=NULL; proc++) {
+ rpc_proc_info_key *key;
+ rpc_proc_info_value *value;
+
+ key = (rpc_proc_info_key *) g_malloc(sizeof(rpc_proc_info_key));
+ key->prog = prog;
+ key->vers = vers;
+ key->proc = proc->value;
+
+ value = (rpc_proc_info_value *) g_malloc(sizeof(rpc_proc_info_value));
+ value->name = proc->strptr;
+ value->dissect_call = proc->dissect_call;
+ value->dissect_reply = proc->dissect_reply;
+
+ g_hash_table_insert(rpc_procs,key,value);
+ }
+}
+
+
+/* return the name associated with a previously registered procedure. */
+char *rpc_proc_name(guint32 prog, guint32 vers, guint32 proc)
+{
+ rpc_proc_info_key key;
+ rpc_proc_info_value *value;
+ char *procname;
+ static char procname_static[20];
+
+ key.prog = prog;
+ key.vers = vers;
+ key.proc = proc;
+
+ if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL)
+ procname = value->name;
+ else {
+ /* happens only with strange program versions or
+ non-existing dissectors */
+ sprintf(procname_static, "proc-%u", key.proc);
+ procname = procname_static;
+ }
+ return procname;
+}
+
+/*----------------------------------------*/
+/* end of Hash array with procedure names */
+/*----------------------------------------*/
+
+
+/*********************************/
+/* Hash array with program names */
+/*********************************/
+
+/* compare 2 keys */
+static gint
+rpc_prog_equal(gconstpointer k1, gconstpointer k2)
+{
+ const rpc_prog_info_key* key1 = (const rpc_prog_info_key*) k1;
+ const rpc_prog_info_key* key2 = (const rpc_prog_info_key*) k2;
+
+ return ((key1->prog == key2->prog) ?
+ TRUE : FALSE);
+}
+
+
+/* calculate a hash key */
+static guint
+rpc_prog_hash(gconstpointer k)
+{
+ const rpc_prog_info_key* key = (const rpc_prog_info_key*) k;
+
+ return (key->prog);
+}
+
+
+void
+rpc_init_prog(int proto, guint32 prog, int ett)
+{
+ rpc_prog_info_key *key;
+ rpc_prog_info_value *value;
+
+ key = (rpc_prog_info_key *) g_malloc(sizeof(rpc_prog_info_key));
+ key->prog = prog;
+
+ value = (rpc_prog_info_value *) g_malloc(sizeof(rpc_prog_info_value));
+ value->proto = find_protocol_by_id(proto);
+ value->proto_id = proto;
+ value->ett = ett;
+ value->progname = proto_get_protocol_short_name(value->proto);
+ value->procedure_hfs = g_array_new(FALSE, TRUE, sizeof (int));
+
+ g_hash_table_insert(rpc_progs,key,value);
+}
+
+
+
+/* return the hf_field associated with a previously registered program.
+*/
+int rpc_prog_hf(guint32 prog, guint32 vers)
+{
+ rpc_prog_info_key rpc_prog_key;
+ rpc_prog_info_value *rpc_prog;
+
+ rpc_prog_key.prog = prog;
+ if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key))) {
+ return g_array_index(rpc_prog->procedure_hfs, int, vers);
+ }
+ return -1;
+}
+
+/* return the name associated with a previously registered program. This
+ should probably eventually be expanded to use the rpc YP/NIS map
+ so that it can give names for programs not handled by ethereal */
+char *rpc_prog_name(guint32 prog)
+{
+ char *progname = NULL;
+ rpc_prog_info_key rpc_prog_key;
+ rpc_prog_info_value *rpc_prog;
+
+ rpc_prog_key.prog = prog;
+ if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
+ progname = "Unknown";
+ }
+ else {
+ progname = rpc_prog->progname;
+ }
+ return progname;
+}
+
+
+/*--------------------------------------*/
+/* end of Hash array with program names */
+/*--------------------------------------*/
+
+typedef struct _rpc_call_info_key {
+ guint32 xid;
+ conversation_t *conversation;
+} rpc_call_info_key;
+
+static GMemChunk *rpc_call_info_key_chunk;
+
+static GMemChunk *rpc_call_info_value_chunk;
+
+static GHashTable *rpc_calls;
+
+static GHashTable *rpc_indir_calls;
+
+/* compare 2 keys */
+static gint
+rpc_call_equal(gconstpointer k1, gconstpointer k2)
+{
+ const rpc_call_info_key* key1 = (const rpc_call_info_key*) k1;
+ const rpc_call_info_key* key2 = (const rpc_call_info_key*) k2;
+
+ return (key1->xid == key2->xid &&
+ key1->conversation == key2->conversation);
+}
+
+
+/* calculate a hash key */
+static guint
+rpc_call_hash(gconstpointer k)
+{
+ const rpc_call_info_key* key = (const rpc_call_info_key*) k;
+
+ return key->xid + GPOINTER_TO_UINT(key->conversation);
+}
+
+
+unsigned int
+rpc_roundup(unsigned int a)
+{
+ unsigned int mod = a % 4;
+ return a + ((mod)? 4-mod : 0);
+}
+
+
+int
+dissect_rpc_bool(tvbuff_t *tvb, proto_tree *tree,
+int hfindex, int offset)
+{
+ if (tree)
+ proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
+ return offset + 4;
+}
+
+
+int
+dissect_rpc_uint32(tvbuff_t *tvb, proto_tree *tree,
+int hfindex, int offset)
+{
+ if (tree)
+ proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
+ return offset + 4;
+}
+
+
+int
+dissect_rpc_uint64(tvbuff_t *tvb, proto_tree *tree,
+int hfindex, int offset)
+{
+ header_field_info *hfinfo;
+
+ hfinfo = proto_registrar_get_nth(hfindex);
+ g_assert(hfinfo->type == FT_UINT64);
+ if (tree)
+ proto_tree_add_item(tree, hfindex, tvb, offset, 8, FALSE);
+
+ return offset + 8;
+}
+
+/*
+ * We want to make this function available outside this file and
+ * allow callers to pass a dissection function for the opaque data
+ */
+int
+dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
+ proto_tree *tree,
+ packet_info *pinfo,
+ int hfindex,
+ gboolean fixed_length, guint32 length,
+ gboolean string_data, char **string_buffer_ret,
+ dissect_function_t *dissect_it)
+{
+ int data_offset;
+ proto_item *string_item = NULL;
+ proto_tree *string_tree = NULL;
+
+ guint32 string_length;
+ guint32 string_length_full;
+ guint32 string_length_packet;
+ guint32 string_length_captured;
+ guint32 string_length_copy;
+
+ int fill_truncated;
+ guint32 fill_length;
+ guint32 fill_length_packet;
+ guint32 fill_length_captured;
+ guint32 fill_length_copy;
+
+ int exception = 0;
+
+ char *string_buffer = NULL;
+ char *string_buffer_print = NULL;
+
+ if (fixed_length) {
+ string_length = length;
+ data_offset = offset;
+ }
+ else {
+ string_length = tvb_get_ntohl(tvb,offset+0);
+ data_offset = offset + 4;
+ }
+ string_length_captured = tvb_length_remaining(tvb, data_offset);
+ string_length_packet = tvb_reported_length_remaining(tvb, data_offset);
+ string_length_full = rpc_roundup(string_length);
+ if (string_length_captured < string_length) {
+ /* truncated string */
+ string_length_copy = string_length_captured;
+ fill_truncated = 2;
+ fill_length = 0;
+ fill_length_copy = 0;
+ if (string_length_packet < string_length)
+ exception = ReportedBoundsError;
+ else
+ exception = BoundsError;
+ }
+ else {
+ /* full string data */
+ string_length_copy = string_length;
+ fill_length = string_length_full - string_length;
+ fill_length_captured = tvb_length_remaining(tvb,
+ data_offset + string_length);
+ fill_length_packet = tvb_reported_length_remaining(tvb,
+ data_offset + string_length);
+ if (fill_length_captured < fill_length) {
+ /* truncated fill bytes */
+ fill_length_copy = fill_length_packet;
+ fill_truncated = 1;
+ if (fill_length_packet < fill_length)
+ exception = ReportedBoundsError;
+ else
+ exception = BoundsError;
+ }
+ else {
+ /* full fill bytes */
+ fill_length_copy = fill_length;
+ fill_truncated = 0;
+ }
+ }
+
+ /*
+ * If we were passed a dissection routine, make a TVB of the data
+ * and call the dissection routine
+ */
+
+ if (dissect_it) {
+ tvbuff_t *opaque_tvb;
+
+ opaque_tvb = tvb_new_subset(tvb, data_offset, string_length_copy,
+ string_length);
+
+ return (*dissect_it)(opaque_tvb, offset, pinfo, tree);
+
+ }
+
+ if (string_data) {
+ string_buffer = tvb_get_string(tvb, data_offset,
+ string_length_copy);
+ } else {
+ string_buffer = tvb_memdup(tvb, data_offset,
+ string_length_copy);
+ }
+ /* calculate a nice printable string */
+ if (string_length) {
+ if (string_length != string_length_copy) {
+ if (string_data) {
+ /* alloc maximum data area */
+ string_buffer_print = (char*)g_malloc(string_length_copy + 12 + 1);
+ /* copy over the data */
+ memcpy(string_buffer_print,string_buffer,string_length_copy);
+ /* append a 0 byte for sure printing */
+ string_buffer_print[string_length_copy] = '\0';
+ /* append <TRUNCATED> */
+ /* This way, we get the TRUNCATED even
+ in the case of totally wrong packets,
+ where \0 are inside the string.
+ TRUNCATED will appear at the
+ first \0 or at the end (where we
+ put the securing \0).
+ */
+ strcat(string_buffer_print,"<TRUNCATED>");
+ }
+ else {
+ string_buffer_print = g_strdup("<DATA><TRUNCATED>");
+ }
+ }
+ else {
+ if (string_data) {
+ string_buffer_print = g_strdup(string_buffer);
+ }
+ else {
+ string_buffer_print = g_strdup("<DATA>");
+ }
+ }
+ }
+ else {
+ string_buffer_print = g_strdup("<EMPTY>");
+ }
+
+ if (tree) {
+ string_item = proto_tree_add_text(tree, tvb,offset+0, -1,
+ "%s: %s", proto_registrar_get_name(hfindex),
+ string_buffer_print);
+ string_tree = proto_item_add_subtree(string_item,
+ ett_rpc_string);
+ }
+ if (!fixed_length) {
+ if (string_tree)
+ proto_tree_add_text(string_tree, tvb,offset+0,4,
+ "length: %u", string_length);
+ offset += 4;
+ }
+
+ if (string_tree) {
+ if (string_data) {
+ proto_tree_add_string_format(string_tree,
+ hfindex, tvb, offset, string_length_copy,
+ string_buffer,
+ "contents: %s", string_buffer_print);
+ } else {
+ proto_tree_add_bytes_format(string_tree,
+ hfindex, tvb, offset, string_length_copy,
+ string_buffer,
+ "contents: %s", string_buffer_print);
+ }
+ }
+
+ offset += string_length_copy;
+
+ if (fill_length) {
+ if (string_tree) {
+ if (fill_truncated) {
+ proto_tree_add_text(string_tree, tvb,
+ offset,fill_length_copy,
+ "fill bytes: opaque data<TRUNCATED>");
+ }
+ else {
+ proto_tree_add_text(string_tree, tvb,
+ offset,fill_length_copy,
+ "fill bytes: opaque data");
+ }
+ }
+ offset += fill_length_copy;
+ }
+
+ if (string_item)
+ proto_item_set_end(string_item, tvb, offset);
+
+ if (string_buffer != NULL)
+ g_free(string_buffer);
+ if (string_buffer_print != NULL) {
+ if (string_buffer_ret != NULL)
+ *string_buffer_ret = string_buffer_print;
+ else
+ g_free(string_buffer_print);
+ }
+
+ /*
+ * If the data was truncated, throw the appropriate exception,
+ * so that dissection stops and the frame is properly marked.
+ */
+ if (exception != 0)
+ THROW(exception);
+ return offset;
+}
+
+
+int
+dissect_rpc_string(tvbuff_t *tvb, proto_tree *tree,
+ int hfindex, int offset, char **string_buffer_ret)
+{
+ offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
+ hfindex, FALSE, 0, TRUE, string_buffer_ret, NULL);
+ return offset;
+}
+
+
+int
+dissect_rpc_data(tvbuff_t *tvb, proto_tree *tree,
+ int hfindex, int offset)
+{
+ offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
+ hfindex, FALSE, 0, FALSE, NULL, NULL);
+ return offset;
+}
+
+
+int
+dissect_rpc_bytes(tvbuff_t *tvb, proto_tree *tree,
+ int hfindex, int offset, guint32 length,
+ gboolean string_data, char **string_buffer_ret)
+{
+ offset = dissect_rpc_opaque_data(tvb, offset, tree, NULL,
+ hfindex, TRUE, length, string_data, string_buffer_ret, NULL);
+ return offset;
+}
+
+
+int
+dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, dissect_function_t *rpc_list_dissector)
+{
+ guint32 value_follows;
+
+ while (1) {
+ value_follows = tvb_get_ntohl(tvb, offset+0);
+ proto_tree_add_boolean(tree,hf_rpc_value_follows, tvb,
+ offset+0, 4, value_follows);
+ offset += 4;
+ if (value_follows == 1) {
+ offset = rpc_list_dissector(tvb, offset, pinfo, tree);
+ }
+ else {
+ break;
+ }
+ }
+
+ return offset;
+}
+
+int
+dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, dissect_function_t *rpc_array_dissector,
+ int hfindex)
+{
+ proto_item* lock_item;
+ proto_tree* lock_tree;
+ guint32 num;
+
+ num = tvb_get_ntohl(tvb, offset);
+
+ if( num == 0 ){
+ proto_tree_add_none_format(tree, hfindex, tvb, offset, 4,
+ "no values");
+ offset += 4;
+
+ return offset;
+ }
+
+ lock_item = proto_tree_add_item(tree, hfindex, tvb, offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_rpc_array);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rpc_array_len, offset);
+
+ while (num--) {
+ offset = rpc_array_dissector(tvb, offset, pinfo, lock_tree);
+ }
+
+ proto_item_set_end(lock_item, tvb, offset);
+ return offset;
+}
+
+static int
+dissect_rpc_authunix_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
+{
+ guint stamp;
+ guint uid;
+ guint gid;
+ guint gids_count;
+ guint gids_i;
+ guint gids_entry;
+ proto_item *gitem;
+ proto_tree *gtree = NULL;
+
+ stamp = tvb_get_ntohl(tvb,offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_auth_stamp, tvb,
+ offset+0, 4, stamp);
+ offset += 4;
+
+ offset = dissect_rpc_string(tvb, tree,
+ hf_rpc_auth_machinename, offset, NULL);
+
+ uid = tvb_get_ntohl(tvb,offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_auth_uid, tvb,
+ offset+0, 4, uid);
+ offset += 4;
+
+ gid = tvb_get_ntohl(tvb,offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_auth_gid, tvb,
+ offset+0, 4, gid);
+ offset += 4;
+
+ gids_count = tvb_get_ntohl(tvb,offset+0);
+ if (tree) {
+ gitem = proto_tree_add_text(tree, tvb,
+ offset, 4+gids_count*4, "Auxiliary GIDs");
+ gtree = proto_item_add_subtree(gitem, ett_rpc_gids);
+ }
+ offset += 4;
+
+ for (gids_i = 0 ; gids_i < gids_count ; gids_i++) {
+ gids_entry = tvb_get_ntohl(tvb,offset+0);
+ if (gtree)
+ proto_tree_add_uint(gtree, hf_rpc_auth_gid, tvb,
+ offset, 4, gids_entry);
+ offset+=4;
+ }
+ /* how can I NOW change the gitem to print a list with
+ the first 16 gids? */
+
+ return offset;
+}
+
+static int
+dissect_rpc_authgss_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
+{
+ guint agc_v;
+ guint agc_proc;
+ guint agc_seq;
+ guint agc_svc;
+
+ agc_v = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_authgss_v,
+ tvb, offset+0, 4, agc_v);
+ offset += 4;
+
+ agc_proc = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_authgss_proc,
+ tvb, offset+0, 4, agc_proc);
+ offset += 4;
+
+ agc_seq = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_authgss_seq,
+ tvb, offset+0, 4, agc_seq);
+ offset += 4;
+
+ agc_svc = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_authgss_svc,
+ tvb, offset+0, 4, agc_svc);
+ offset += 4;
+
+ offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_ctx,
+ offset);
+
+ return offset;
+}
+
+static int
+dissect_rpc_authdes_desblock(tvbuff_t *tvb, proto_tree *tree,
+int hfindex, int offset)
+{
+ guint32 value_low;
+ guint32 value_high;
+
+ value_high = tvb_get_ntohl(tvb, offset + 0);
+ value_low = tvb_get_ntohl(tvb, offset + 4);
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, 8,
+ "%s: 0x%x%08x", proto_registrar_get_name(hfindex), value_high,
+ value_low);
+ }
+
+ return offset + 8;
+}
+
+static int
+dissect_rpc_authdes_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
+{
+ guint adc_namekind;
+ guint window = 0;
+ guint nickname = 0;
+
+ adc_namekind = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_authdes_namekind,
+ tvb, offset+0, 4, adc_namekind);
+ offset += 4;
+
+ switch(adc_namekind)
+ {
+ case AUTHDES_NAMEKIND_FULLNAME:
+ offset = dissect_rpc_string(tvb, tree,
+ hf_rpc_authdes_netname, offset, NULL);
+ offset = dissect_rpc_authdes_desblock(tvb, tree,
+ hf_rpc_authdes_convkey, offset);
+ window = tvb_get_ntohl(tvb, offset+0);
+ proto_tree_add_uint(tree, hf_rpc_authdes_window, tvb, offset+0, 4,
+ window);
+ offset += 4;
+ break;
+
+ case AUTHDES_NAMEKIND_NICKNAME:
+ nickname = tvb_get_ntohl(tvb, offset+0);
+ proto_tree_add_uint(tree, hf_rpc_authdes_nickname, tvb, offset+0, 4,
+ nickname);
+ offset += 4;
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_rpc_authgssapi_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
+{
+ guint agc_v;
+ guint agc_msg;
+
+ agc_v = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_authgssapi_v,
+ tvb, offset+0, 4, agc_v);
+ offset += 4;
+
+ agc_msg = tvb_get_ntohl(tvb, offset+0);
+ if (tree)
+ proto_tree_add_boolean(tree, hf_rpc_authgssapi_msg,
+ tvb, offset+0, 4, agc_msg);
+ offset += 4;
+
+ offset = dissect_rpc_data(tvb, tree, hf_rpc_authgssapi_handle,
+ offset);
+
+ return offset;
+}
+
+static int
+dissect_rpc_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
+{
+ guint flavor;
+ guint length;
+
+ proto_item *citem;
+ proto_tree *ctree;
+
+ flavor = tvb_get_ntohl(tvb,offset+0);
+ length = tvb_get_ntohl(tvb,offset+4);
+ length = rpc_roundup(length);
+
+ if (tree) {
+ citem = proto_tree_add_text(tree, tvb, offset,
+ 8+length, "Credentials");
+ ctree = proto_item_add_subtree(citem, ett_rpc_cred);
+ proto_tree_add_uint(ctree, hf_rpc_auth_flavor, tvb,
+ offset+0, 4, flavor);
+ proto_tree_add_uint(ctree, hf_rpc_auth_length, tvb,
+ offset+4, 4, length);
+
+ switch (flavor) {
+ case AUTH_UNIX:
+ dissect_rpc_authunix_cred(tvb, ctree, offset+8);
+ break;
+ /*
+ case AUTH_SHORT:
+
+ break;
+ */
+ case AUTH_DES:
+ dissect_rpc_authdes_cred(tvb, ctree, offset+8);
+ break;
+
+ case RPCSEC_GSS:
+ dissect_rpc_authgss_cred(tvb, ctree, offset+8);
+ break;
+
+ case AUTH_GSSAPI:
+ dissect_rpc_authgssapi_cred(tvb, ctree, offset+8);
+ break;
+
+ default:
+ if (length)
+ proto_tree_add_text(ctree, tvb, offset+8,
+ length,"opaque data");
+ break;
+ }
+ }
+ offset += 8 + length;
+
+ return offset;
+}
+
+/*
+ * XDR opaque object, the contents of which are interpreted as a GSS-API
+ * token.
+ */
+static int
+dissect_rpc_authgss_token(tvbuff_t* tvb, proto_tree* tree, int offset,
+ packet_info *pinfo)
+{
+ guint32 opaque_length, rounded_length;
+ gint len_consumed, length, reported_length;
+ tvbuff_t *new_tvb;
+
+ proto_item *gitem;
+ proto_tree *gtree = NULL;
+
+ opaque_length = tvb_get_ntohl(tvb, offset+0);
+ rounded_length = rpc_roundup(opaque_length);
+ if (tree) {
+ gitem = proto_tree_add_text(tree, tvb, offset,
+ 4+rounded_length, "GSS Token");
+ gtree = proto_item_add_subtree(gitem, ett_rpc_gss_token);
+ proto_tree_add_uint(gtree, hf_rpc_authgss_token_length,
+ tvb, offset+0, 4, opaque_length);
+ }
+ offset += 4;
+ length = tvb_length_remaining(tvb, offset);
+ reported_length = tvb_reported_length_remaining(tvb, offset);
+ g_assert(length >= 0);
+ g_assert(reported_length >= 0);
+ if (length > reported_length)
+ length = reported_length;
+ if ((guint32)length > opaque_length)
+ length = opaque_length;
+ if ((guint32)reported_length > opaque_length)
+ reported_length = opaque_length;
+ new_tvb = tvb_new_subset(tvb, offset, length, reported_length);
+ len_consumed = call_dissector(gssapi_handle, new_tvb, pinfo, gtree);
+ offset += len_consumed;
+ offset = rpc_roundup(offset);
+ return offset;
+}
+
+/* AUTH_DES verifiers are asymmetrical, so we need to know what type of
+ * verifier we're decoding (CALL or REPLY).
+ */
+static int
+dissect_rpc_verf(tvbuff_t* tvb, proto_tree* tree, int offset, int msg_type,
+ packet_info *pinfo)
+{
+ guint flavor;
+ guint length;
+
+ proto_item *vitem;
+ proto_tree *vtree;
+
+ flavor = tvb_get_ntohl(tvb,offset+0);
+ length = tvb_get_ntohl(tvb,offset+4);
+ length = rpc_roundup(length);
+
+ if (tree) {
+ vitem = proto_tree_add_text(tree, tvb, offset,
+ 8+length, "Verifier");
+ vtree = proto_item_add_subtree(vitem, ett_rpc_verf);
+ proto_tree_add_uint(vtree, hf_rpc_auth_flavor, tvb,
+ offset+0, 4, flavor);
+
+ switch (flavor) {
+ case AUTH_UNIX:
+ proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
+ offset+4, 4, length);
+ dissect_rpc_authunix_cred(tvb, vtree, offset+8);
+ break;
+ case AUTH_DES:
+ proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
+ offset+4, 4, length);
+
+ if (msg_type == RPC_CALL)
+ {
+ guint window;
+
+ dissect_rpc_authdes_desblock(tvb, vtree,
+ hf_rpc_authdes_timestamp, offset+8);
+ window = tvb_get_ntohl(tvb, offset+16);
+ proto_tree_add_uint(vtree, hf_rpc_authdes_windowverf, tvb,
+ offset+16, 4, window);
+ }
+ else
+ {
+ /* must be an RPC_REPLY */
+ guint nickname;
+
+ dissect_rpc_authdes_desblock(tvb, vtree,
+ hf_rpc_authdes_timeverf, offset+8);
+ nickname = tvb_get_ntohl(tvb, offset+16);
+ proto_tree_add_uint(vtree, hf_rpc_authdes_nickname, tvb,
+ offset+16, 4, nickname);
+ }
+ break;
+ case RPCSEC_GSS:
+ dissect_rpc_authgss_token(tvb, vtree, offset+4, pinfo);
+ break;
+ default:
+ proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
+ offset+4, 4, length);
+ if (length)
+ proto_tree_add_text(vtree, tvb, offset+8,
+ length, "opaque data");
+ break;
+ }
+ }
+ offset += 8 + length;
+
+ return offset;
+}
+
+static int
+dissect_rpc_authgss_initarg(tvbuff_t* tvb, proto_tree* tree, int offset,
+ packet_info *pinfo)
+{
+ return dissect_rpc_authgss_token(tvb, tree, offset, pinfo);
+}
+
+static int
+dissect_rpc_authgss_initres(tvbuff_t* tvb, proto_tree* tree, int offset,
+ packet_info *pinfo)
+{
+ int major, minor, window;
+
+ offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_ctx,
+ offset);
+
+ major = tvb_get_ntohl(tvb,offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_authgss_major, tvb,
+ offset+0, 4, major);
+ offset += 4;
+
+ minor = tvb_get_ntohl(tvb,offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_authgss_minor, tvb,
+ offset+0, 4, minor);
+ offset += 4;
+
+ window = tvb_get_ntohl(tvb,offset+0);
+ if (tree)
+ proto_tree_add_uint(tree, hf_rpc_authgss_window, tvb,
+ offset+0, 4, window);
+ offset += 4;
+
+ offset = dissect_rpc_authgss_token(tvb, tree, offset, pinfo);
+
+ return offset;
+}
+
+static int
+dissect_rpc_authgssapi_initarg(tvbuff_t* tvb, proto_tree* tree, int offset,
+ packet_info *pinfo)
+{
+ guint version;
+ proto_item *mitem;
+ proto_tree *mtree = NULL;
+
+ if (tree) {
+ mitem = proto_tree_add_text(tree, tvb, offset, -1,
+ "AUTH_GSSAPI Msg");
+ mtree = proto_item_add_subtree(mitem, ett_rpc_authgssapi_msg);
+ }
+ version = tvb_get_ntohl(tvb, offset+0);
+ if (mtree) {
+ proto_tree_add_uint(mtree, hf_rpc_authgssapi_msgv, tvb,
+ offset+0, 4, version);
+ }
+ offset += 4;
+
+ offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo);
+
+ return offset;
+}
+
+static int
+dissect_rpc_authgssapi_initres(tvbuff_t* tvb, proto_tree* tree, int offset,
+ packet_info *pinfo)
+{
+ guint version;
+ guint major, minor;
+ proto_item *mitem;
+ proto_tree *mtree = NULL;
+
+ if (tree) {
+ mitem = proto_tree_add_text(tree, tvb, offset, -1,
+ "AUTH_GSSAPI Msg");
+ mtree = proto_item_add_subtree(mitem, ett_rpc_authgssapi_msg);
+ }
+
+ version = tvb_get_ntohl(tvb,offset+0);
+ if (mtree) {
+ proto_tree_add_uint(mtree, hf_rpc_authgssapi_msgv, tvb,
+ offset+0, 4, version);
+ }
+ offset += 4;
+
+ offset = dissect_rpc_data(tvb, mtree, hf_rpc_authgssapi_handle,
+ offset);
+
+ major = tvb_get_ntohl(tvb,offset+0);
+ if (mtree) {
+ proto_tree_add_uint(mtree, hf_rpc_authgss_major, tvb,
+ offset+0, 4, major);
+ }
+ offset += 4;
+
+ minor = tvb_get_ntohl(tvb,offset+0);
+ if (mtree) {
+ proto_tree_add_uint(mtree, hf_rpc_authgss_minor, tvb,
+ offset+0, 4, minor);
+ }
+ offset += 4;
+
+ offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo);
+
+ offset = dissect_rpc_data(tvb, mtree, hf_rpc_authgssapi_isn, offset);
+
+ return offset;
+}
+
+static int
+dissect_auth_gssapi_data(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_data,
+ offset);
+ return offset;
+}
+
+static int
+call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, dissect_function_t* dissect_function, const char *progname)
+{
+ const char *saved_proto;
+
+ if (dissect_function != NULL) {
+ /* set the current protocol name */
+ saved_proto = pinfo->current_proto;
+ if (progname != NULL)
+ pinfo->current_proto = progname;
+
+ /* call the dissector for the next level */
+ offset = dissect_function(tvb, offset, pinfo, tree);
+
+ /* restore the protocol name */
+ pinfo->current_proto = saved_proto;
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_rpc_authgss_integ_data(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int offset,
+ dissect_function_t* dissect_function,
+ const char *progname)
+{
+ guint32 length, rounded_length, seq;
+
+ proto_item *gitem;
+ proto_tree *gtree = NULL;
+
+ length = tvb_get_ntohl(tvb, offset+0);
+ rounded_length = rpc_roundup(length);
+ seq = tvb_get_ntohl(tvb, offset+4);
+
+ if (tree) {
+ gitem = proto_tree_add_text(tree, tvb, offset,
+ 4+rounded_length, "GSS Data");
+ gtree = proto_item_add_subtree(gitem, ett_rpc_gss_data);
+ proto_tree_add_uint(gtree, hf_rpc_authgss_data_length,
+ tvb, offset+0, 4, length);
+ proto_tree_add_uint(gtree, hf_rpc_authgss_seq,
+ tvb, offset+4, 4, seq);
+ }
+ offset += 8;
+
+ if (dissect_function != NULL) {
+ /* offset = */
+ call_dissect_function(tvb, pinfo, gtree, offset,
+ dissect_function, progname);
+ }
+ offset += rounded_length - 4;
+ offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_checksum,
+ offset);
+ return offset;
+}
+
+
+static int
+dissect_rpc_authgss_priv_data(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_data,
+ offset);
+ return offset;
+}
+
+/*
+ * Dissect the arguments to an indirect call; used by the portmapper/RPCBIND
+ * dissector.
+ *
+ * Record this call in a hash table, similar to the hash table for
+ * direct calls, so we can find it when dissecting an indirect call reply.
+ */
+int
+dissect_rpc_indir_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int args_id, guint32 prog, guint32 vers, guint32 proc)
+{
+ conversation_t* conversation;
+ static address null_address = { AT_NONE, 0, NULL };
+ rpc_proc_info_key key;
+ rpc_proc_info_value *value;
+ rpc_call_info_value *rpc_call;
+ rpc_call_info_key rpc_call_key;
+ rpc_call_info_key *new_rpc_call_key;
+ dissect_function_t *dissect_function = NULL;
+
+ key.prog = prog;
+ key.vers = vers;
+ key.proc = proc;
+ if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
+ dissect_function = value->dissect_call;
+
+ /* Keep track of the address and port whence the call came,
+ and the port to which the call is being sent, so that
+ we can match up calls with replies.
+
+ If the transport is connection-oriented (we check, for
+ now, only for "pinfo->ptype" of PT_TCP), we take
+ into account the address from which the call was sent
+ and the address to which the call was sent, because
+ the addresses of the two endpoints should be the same
+ for all calls and replies.
+
+ If the transport is connectionless, we don't worry
+ about the address to which the call was sent and from
+ which the reply was sent, because there's no
+ guarantee that the reply will come from the address
+ to which the call was sent. */
+ if (pinfo->ptype == PT_TCP) {
+ conversation = find_conversation(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ } else {
+ /*
+ * XXX - can we just use NO_ADDR_B? Unfortunately,
+ * you currently still have to pass a non-null
+ * pointer for the second address argument even
+ * if you do that.
+ */
+ conversation = find_conversation(&pinfo->src,
+ &null_address, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ if (conversation == NULL) {
+ /* It's not part of any conversation - create a new
+ one.
+
+ XXX - this should never happen, as we should've
+ created a conversation for it in the RPC
+ dissector. */
+ if (pinfo->ptype == PT_TCP) {
+ conversation = conversation_new(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ } else {
+ conversation = conversation_new(&pinfo->src,
+ &null_address, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ }
+
+ /* Make the dissector for this conversation the non-heuristic
+ RPC dissector. */
+ conversation_set_dissector(conversation,
+ (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
+
+ /* Prepare the key data.
+
+ Dissectors for RPC procedure calls and replies shouldn't
+ create new tvbuffs, and we don't create one ourselves,
+ so we should have been handed the tvbuff for this RPC call;
+ as such, the XID is at offset 0 in this tvbuff. */
+ rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
+ rpc_call_key.conversation = conversation;
+
+ /* look up the request */
+ rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
+ if (rpc_call == NULL) {
+ /* We didn't find it; create a new entry.
+ Prepare the value data.
+ Not all of it is needed for handling indirect
+ calls, so we set a bunch of items to 0. */
+ new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
+ *new_rpc_call_key = rpc_call_key;
+ rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
+ rpc_call->req_num = 0;
+ rpc_call->rep_num = 0;
+ rpc_call->prog = prog;
+ rpc_call->vers = vers;
+ rpc_call->proc = proc;
+ rpc_call->private_data = NULL;
+
+ /*
+ * XXX - what about RPCSEC_GSS?
+ * Do we have to worry about it?
+ */
+ rpc_call->flavor = FLAVOR_NOT_GSSAPI;
+ rpc_call->gss_proc = 0;
+ rpc_call->gss_svc = 0;
+ rpc_call->proc_info = value;
+ /* store it */
+ g_hash_table_insert(rpc_indir_calls, new_rpc_call_key,
+ rpc_call);
+ }
+ }
+ else {
+ /* We don't know the procedure.
+ Happens only with strange program versions or
+ non-existing dissectors.
+ Just show the arguments as opaque data. */
+ offset = dissect_rpc_data(tvb, tree, args_id,
+ offset);
+ return offset;
+ }
+
+ if ( tree )
+ {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Argument length: %u",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+
+ /* Dissect the arguments */
+ offset = call_dissect_function(tvb, pinfo, tree, offset,
+ dissect_function, NULL);
+ return offset;
+}
+
+/*
+ * Dissect the results in an indirect reply; used by the portmapper/RPCBIND
+ * dissector.
+ */
+int
+dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, int result_id, int prog_id, int vers_id, int proc_id)
+{
+ conversation_t* conversation;
+ static address null_address = { AT_NONE, 0, NULL };
+ rpc_call_info_key rpc_call_key;
+ rpc_call_info_value *rpc_call;
+ char *procname = NULL;
+ char procname_static[20];
+ dissect_function_t *dissect_function = NULL;
+
+ /* Look for the matching call in the hash table of indirect
+ calls. A reply must match a call that we've seen, and the
+ reply must be sent to the same port and address that the
+ call came from, and must come from the port to which the
+ call was sent.
+
+ If the transport is connection-oriented (we check, for
+ now, only for "pinfo->ptype" of PT_TCP), we take
+ into account the address from which the call was sent
+ and the address to which the call was sent, because
+ the addresses of the two endpoints should be the same
+ for all calls and replies.
+
+ If the transport is connectionless, we don't worry
+ about the address to which the call was sent and from
+ which the reply was sent, because there's no
+ guarantee that the reply will come from the address
+ to which the call was sent. */
+ if (pinfo->ptype == PT_TCP) {
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ } else {
+ /*
+ * XXX - can we just use NO_ADDR_B? Unfortunately,
+ * you currently still have to pass a non-null
+ * pointer for the second address argument even
+ * if you do that.
+ */
+ conversation = find_conversation(&null_address, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ if (conversation == NULL) {
+ /* We haven't seen an RPC call for that conversation,
+ so we can't check for a reply to that call.
+ Just show the reply stuff as opaque data. */
+ offset = dissect_rpc_data(tvb, tree, result_id,
+ offset);
+ return offset;
+ }
+
+ /* The XIDs of the call and reply must match. */
+ rpc_call_key.xid = tvb_get_ntohl(tvb, 0);
+ rpc_call_key.conversation = conversation;
+ rpc_call = g_hash_table_lookup(rpc_indir_calls, &rpc_call_key);
+ if (rpc_call == NULL) {
+ /* The XID doesn't match a call from that
+ conversation, so it's probably not an RPC reply.
+ Just show the reply stuff as opaque data. */
+ offset = dissect_rpc_data(tvb, tree, result_id,
+ offset);
+ return offset;
+ }
+
+ if (rpc_call->proc_info != NULL) {
+ dissect_function = rpc_call->proc_info->dissect_reply;
+ if (rpc_call->proc_info->name != NULL) {
+ procname = rpc_call->proc_info->name;
+ }
+ else {
+ sprintf(procname_static, "proc-%u", rpc_call->proc);
+ procname = procname_static;
+ }
+ }
+ else {
+#if 0
+ dissect_function = NULL;
+#endif
+ sprintf(procname_static, "proc-%u", rpc_call->proc);
+ procname = procname_static;
+ }
+
+ if ( tree )
+ {
+ /* Put the program, version, and procedure into the tree. */
+ proto_tree_add_uint_format(tree, prog_id, tvb,
+ 0, 0, rpc_call->prog, "Program: %s (%u)",
+ rpc_prog_name(rpc_call->prog), rpc_call->prog);
+ proto_tree_add_uint(tree, vers_id, tvb, 0, 0, rpc_call->vers);
+ proto_tree_add_uint_format(tree, proc_id, tvb,
+ 0, 0, rpc_call->proc, "Procedure: %s (%u)",
+ procname, rpc_call->proc);
+ }
+
+ if (dissect_function == NULL) {
+ /* We don't know how to dissect the reply procedure.
+ Just show the reply stuff as opaque data. */
+ offset = dissect_rpc_data(tvb, tree, result_id,
+ offset);
+ return offset;
+ }
+
+ if (tree) {
+ /* Put the length of the reply value into the tree. */
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Argument length: %u",
+ tvb_get_ntohl(tvb, offset));
+ }
+ offset += 4;
+
+ /* Dissect the return value */
+ offset = call_dissect_function(tvb, pinfo, tree, offset,
+ dissect_function, NULL);
+ return offset;
+}
+
+/*
+ * Just mark this as a continuation of an earlier packet.
+ */
+static void
+dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *rpc_item;
+ proto_tree *rpc_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+
+ if (tree) {
+ rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
+ FALSE);
+ rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
+ proto_tree_add_text(rpc_tree, tvb, 0, -1, "Continuation data");
+ }
+}
+
+static gboolean
+dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ tvbuff_t *frag_tvb, fragment_data *ipfd_head, gboolean is_tcp,
+ guint32 rpc_rm, gboolean first_pdu)
+{
+ guint32 msg_type;
+ rpc_call_info_key rpc_call_key;
+ rpc_call_info_value *rpc_call = NULL;
+ rpc_prog_info_value *rpc_prog = NULL;
+ rpc_prog_info_key rpc_prog_key;
+
+ unsigned int xid;
+ unsigned int rpcvers;
+ unsigned int prog = 0;
+ unsigned int vers = 0;
+ unsigned int proc = 0;
+ flavor_t flavor = FLAVOR_UNKNOWN;
+ unsigned int gss_proc = 0;
+ unsigned int gss_svc = 0;
+ protocol_t *proto = NULL;
+ int proto_id = 0;
+ int ett = 0;
+ int procedure_hf;
+
+ unsigned int reply_state;
+ unsigned int accept_state;
+ unsigned int reject_state;
+
+ char *msg_type_name = NULL;
+ char *progname = NULL;
+ char *procname = NULL;
+ static char procname_static[20];
+
+ unsigned int vers_low;
+ unsigned int vers_high;
+
+ unsigned int auth_state;
+
+ proto_item *rpc_item = NULL;
+ proto_tree *rpc_tree = NULL;
+
+ proto_item *pitem = NULL;
+ proto_tree *ptree = NULL;
+ int offset = (is_tcp && tvb == frag_tvb) ? 4 : 0;
+
+ rpc_call_info_key *new_rpc_call_key;
+ rpc_proc_info_key key;
+ rpc_proc_info_value *value = NULL;
+ conversation_t* conversation;
+ static address null_address = { AT_NONE, 0, NULL };
+ nstime_t ns;
+
+ dissect_function_t *dissect_function = NULL;
+ gboolean dissect_rpc = TRUE;
+
+
+ /*
+ * Check to see whether this looks like an RPC call or reply.
+ */
+ if (!tvb_bytes_exist(tvb, offset, 8)) {
+ /* Captured data in packet isn't enough to let us tell. */
+ return FALSE;
+ }
+
+ /* both directions need at least this */
+ msg_type = tvb_get_ntohl(tvb, offset + 4);
+
+ switch (msg_type) {
+
+ case RPC_CALL:
+ /* check for RPC call */
+ if (!tvb_bytes_exist(tvb, offset, 16)) {
+ /* Captured data in packet isn't enough to let us
+ tell. */
+ return FALSE;
+ }
+
+ /* XID can be anything, so dont check it.
+ We already have the message type.
+ Check whether an RPC version number of 2 is in the
+ location where it would be, and that an RPC program
+ number we know about is in the location where it would be.
+
+ XXX - Sun's snoop appears to recognize as RPC even calls
+ to stuff it doesn't dissect; does it just look for a 2
+ at that location, which seems far to weak a heuristic
+ (too many false positives), or does it have some additional
+ checks it does?
+
+ We could conceivably check for any of the program numbers
+ in the list at
+
+ ftp://ftp.tau.ac.il/pub/users/eilon/rpc/rpc
+
+ and report it as RPC (but not dissect the payload if
+ we don't have a subdissector) if it matches. */
+ rpc_prog_key.prog = tvb_get_ntohl(tvb, offset + 12);
+
+ /* we only dissect version 2 */
+ if (tvb_get_ntohl(tvb, offset + 8) != 2 ){
+ return FALSE;
+ }
+ /* let the user be able to weaken the heuristics if he need
+ * to look at proprietary protocols not known
+ * to ethereal.
+ */
+ if(rpc_dissect_unknown_programs){
+ /* if the user has specified that he wants to try to
+ * dissect even completely unknown RPC program numbers
+ * then let him do that.
+ * In this case we only check that the program number
+ * is neither 0 nor -1 which is better than nothing.
+ */
+ if(rpc_prog_key.prog==0 || rpc_prog_key.prog==0xffffffff){
+ return FALSE;
+ }
+ if( (rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key)) == NULL) {
+ /* ok this is not a known rpc program so we
+ * will have to fake it.
+ */
+ int proto_rpc_unknown_program;
+ char *NAME, *Name, *name;
+ static const vsff unknown_proc[] = {
+ { 0,"NULL",NULL,NULL },
+ { 0,NULL,NULL,NULL }
+ };
+
+ NAME=g_malloc(36);
+ Name=g_malloc(32);
+ name=g_malloc(32);
+ sprintf(NAME, "Unknown RPC Program:%d",rpc_prog_key.prog);
+ sprintf(Name, "RPC:%d",rpc_prog_key.prog);
+ sprintf(name, "rpc%d",rpc_prog_key.prog);
+ proto_rpc_unknown_program = proto_register_protocol(NAME, Name, name);
+
+ rpc_init_prog(proto_rpc_unknown_program, rpc_prog_key.prog, ett_rpc_unknown_program);
+ rpc_init_proc_table(rpc_prog_key.prog, tvb_get_ntohl(tvb, offset + 16), unknown_proc, hf_rpc_procedure);
+
+ }
+ }
+ if( (rpc_prog = g_hash_table_lookup(rpc_progs, &rpc_prog_key)) == NULL) {
+ /* They're not, so it's probably not an RPC call. */
+ return FALSE;
+ }
+ break;
+
+ case RPC_REPLY:
+ /* Check for RPC reply. A reply must match a call that
+ we've seen, and the reply must be sent to the same
+ port and address that the call came from, and must
+ come from the port to which the call was sent.
+
+ If the transport is connection-oriented (we check, for
+ now, only for "pinfo->ptype" of PT_TCP), we take
+ into account the address from which the call was sent
+ and the address to which the call was sent, because
+ the addresses of the two endpoints should be the same
+ for all calls and replies.
+
+ If the transport is connectionless, we don't worry
+ about the address to which the call was sent and from
+ which the reply was sent, because there's no
+ guarantee that the reply will come from the address
+ to which the call was sent. */
+ if (pinfo->ptype == PT_TCP) {
+ conversation = find_conversation(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ } else {
+ /*
+ * XXX - can we just use NO_ADDR_B? Unfortunately,
+ * you currently still have to pass a non-null
+ * pointer for the second address argument even
+ * if you do that.
+ */
+ conversation = find_conversation(&null_address,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ if (conversation == NULL) {
+ /* We haven't seen an RPC call for that conversation,
+ so we can't check for a reply to that call. */
+ return FALSE;
+ }
+
+ /* The XIDs of the call and reply must match. */
+ rpc_call_key.xid = tvb_get_ntohl(tvb, offset + 0);
+ rpc_call_key.conversation = conversation;
+ rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
+ if (rpc_call == NULL) {
+ /* The XID doesn't match a call from that
+ conversation, so it's probably not an RPC reply. */
+ return FALSE;
+ }
+ /* pass rpc_info to subdissectors */
+ rpc_call->request=FALSE;
+ pinfo->private_data=rpc_call;
+ break;
+
+ default:
+ /* The putative message type field contains neither
+ RPC_CALL nor RPC_REPLY, so it's not an RPC call or
+ reply. */
+ return FALSE;
+ }
+
+ if (is_tcp) {
+ /*
+ * This is RPC-over-TCP; check if this is the last
+ * fragment.
+ */
+ if (!(rpc_rm & RPC_RM_LASTFRAG)) {
+ /*
+ * This isn't the last fragment.
+ * If we're doing reassembly, just return
+ * TRUE to indicate that this looks like
+ * the beginning of an RPC message,
+ * and let them do fragment reassembly.
+ */
+ if (rpc_defragment)
+ return TRUE;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
+
+ if (tree) {
+ rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
+ FALSE);
+ rpc_tree = proto_item_add_subtree(rpc_item, ett_rpc);
+
+ if (is_tcp) {
+ show_rpc_fraginfo(tvb, frag_tvb, rpc_tree, rpc_rm,
+ ipfd_head, pinfo);
+ }
+ }
+
+ xid = tvb_get_ntohl(tvb, offset + 0);
+ if (rpc_tree) {
+ proto_tree_add_uint_format(rpc_tree,hf_rpc_xid, tvb,
+ offset+0, 4, xid, "XID: 0x%x (%u)", xid, xid);
+ }
+
+ msg_type_name = val_to_str(msg_type,rpc_msg_type,"%u");
+ if (rpc_tree) {
+ proto_tree_add_uint(rpc_tree, hf_rpc_msgtype, tvb,
+ offset+4, 4, msg_type);
+ proto_item_append_text(rpc_item, ", Type:%s XID:0x%08x", msg_type_name, xid);
+ }
+
+ offset += 8;
+
+ switch (msg_type) {
+
+ case RPC_CALL:
+ /* we know already the proto-entry, the ETT-const,
+ and "rpc_prog" */
+ proto = rpc_prog->proto;
+ proto_id = rpc_prog->proto_id;
+ ett = rpc_prog->ett;
+ progname = rpc_prog->progname;
+
+ rpcvers = tvb_get_ntohl(tvb, offset + 0);
+ if (rpc_tree) {
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_version, tvb, offset+0, 4, rpcvers);
+ }
+
+ prog = tvb_get_ntohl(tvb, offset + 4);
+
+ if (rpc_tree) {
+ proto_tree_add_uint_format(rpc_tree,
+ hf_rpc_program, tvb, offset+4, 4, prog,
+ "Program: %s (%u)", progname, prog);
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ /* Set the protocol name to the underlying
+ program name. */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
+ }
+
+ vers = tvb_get_ntohl(tvb, offset+8);
+ if (rpc_tree) {
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_programversion, tvb, offset+8, 4, vers);
+ }
+
+ proc = tvb_get_ntohl(tvb, offset+12);
+
+ key.prog = prog;
+ key.vers = vers;
+ key.proc = proc;
+
+ if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
+ dissect_function = value->dissect_call;
+ procname = value->name;
+ }
+ else {
+ /* happens only with strange program versions or
+ non-existing dissectors */
+#if 0
+ dissect_function = NULL;
+#endif
+ sprintf(procname_static, "proc-%u", proc);
+ procname = procname_static;
+ }
+
+ /* Check for RPCSEC_GSS and AUTH_GSSAPI */
+ if (tvb_bytes_exist(tvb, offset+16, 4)) {
+ switch (tvb_get_ntohl(tvb, offset+16)) {
+
+ case RPCSEC_GSS:
+ /*
+ * It's GSS-API authentication...
+ */
+ if (tvb_bytes_exist(tvb, offset+28, 8)) {
+ /*
+ * ...and we have the procedure
+ * and service information for it.
+ */
+ flavor = FLAVOR_GSSAPI;
+ gss_proc = tvb_get_ntohl(tvb, offset+28);
+ gss_svc = tvb_get_ntohl(tvb, offset+36);
+ } else {
+ /*
+ * ...but the procedure and service
+ * information isn't available.
+ */
+ flavor = FLAVOR_GSSAPI_NO_INFO;
+ }
+ break;
+
+ case AUTH_GSSAPI:
+ /*
+ * AUTH_GSSAPI flavor. If auth_msg is TRUE,
+ * then this is an AUTH_GSSAPI message and
+ * not an application level message.
+ */
+ if (tvb_bytes_exist(tvb, offset+28, 4)) {
+ if (tvb_get_ntohl(tvb, offset+28)) {
+ flavor = FLAVOR_AUTHGSSAPI_MSG;
+ gss_proc = proc;
+ procname =
+ match_strval(gss_proc,
+ rpc_authgssapi_proc);
+ } else {
+ flavor = FLAVOR_AUTHGSSAPI;
+ }
+ }
+ break;
+
+ default:
+ /*
+ * It's not GSS-API authentication.
+ */
+ flavor = FLAVOR_NOT_GSSAPI;
+ break;
+ }
+ }
+
+ if (rpc_tree) {
+ proto_tree_add_uint_format(rpc_tree,
+ hf_rpc_procedure, tvb, offset+12, 4, proc,
+ "Procedure: %s (%u)", procname, proc);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (first_pdu)
+ col_clear(pinfo->cinfo, COL_INFO);
+ else
+ col_append_fstr(pinfo->cinfo, COL_INFO, " ; ");
+ col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s",
+ vers,
+ procname,
+ msg_type_name);
+ }
+
+ /* Keep track of the address and port whence the call came,
+ and the port to which the call is being sent, so that
+ we can match up calls with replies.
+
+ If the transport is connection-oriented (we check, for
+ now, only for "pinfo->ptype" of PT_TCP), we take
+ into account the address from which the call was sent
+ and the address to which the call was sent, because
+ the addresses of the two endpoints should be the same
+ for all calls and replies.
+
+ If the transport is connectionless, we don't worry
+ about the address to which the call was sent and from
+ which the reply was sent, because there's no
+ guarantee that the reply will come from the address
+ to which the call was sent. */
+ if (pinfo->ptype == PT_TCP) {
+ conversation = find_conversation(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ } else {
+ /*
+ * XXX - can we just use NO_ADDR_B? Unfortunately,
+ * you currently still have to pass a non-null
+ * pointer for the second address argument even
+ * if you do that.
+ */
+ conversation = find_conversation(&pinfo->src,
+ &null_address, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ if (conversation == NULL) {
+ /* It's not part of any conversation - create a new
+ one. */
+ if (pinfo->ptype == PT_TCP) {
+ conversation = conversation_new(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ } else {
+ conversation = conversation_new(&pinfo->src,
+ &null_address, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+ }
+
+ /* Make the dissector for this conversation the non-heuristic
+ RPC dissector. */
+ conversation_set_dissector(conversation,
+ (pinfo->ptype == PT_TCP) ? rpc_tcp_handle : rpc_handle);
+
+ /* prepare the key data */
+ rpc_call_key.xid = xid;
+ rpc_call_key.conversation = conversation;
+
+ /* look up the request */
+ rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
+ if (rpc_call) {
+ /* We've seen a request with this XID, with the same
+ source and destination, before - but was it
+ *this* request? */
+ if (pinfo->fd->num != rpc_call->req_num) {
+ /* No, so it's a duplicate request.
+ Mark it as such. */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_prepend_fstr(pinfo->cinfo, COL_INFO,
+ "[RPC retransmission of #%d]", rpc_call->req_num);
+ }
+ proto_tree_add_item(rpc_tree,
+ hf_rpc_dup, tvb, 0,0, TRUE);
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_call_dup, tvb, 0,0, rpc_call->req_num);
+ }
+ if(rpc_call->rep_num){
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," (Reply In %d)", rpc_call->rep_num);
+ }
+ }
+ } else {
+ /* Prepare the value data.
+ "req_num" and "rep_num" are frame numbers;
+ frame numbers are 1-origin, so we use 0
+ to mean "we don't yet know in which frame
+ the reply for this call appears". */
+ new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
+ *new_rpc_call_key = rpc_call_key;
+ rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
+ rpc_call->req_num = pinfo->fd->num;
+ rpc_call->rep_num = 0;
+ rpc_call->prog = prog;
+ rpc_call->vers = vers;
+ rpc_call->proc = proc;
+ rpc_call->private_data = NULL;
+ rpc_call->xid = xid;
+ rpc_call->flavor = flavor;
+ rpc_call->gss_proc = gss_proc;
+ rpc_call->gss_svc = gss_svc;
+ rpc_call->proc_info = value;
+ rpc_call->req_time.secs=pinfo->fd->abs_secs;
+ rpc_call->req_time.nsecs=pinfo->fd->abs_usecs*1000;
+
+ /* store it */
+ g_hash_table_insert(rpc_calls, new_rpc_call_key,
+ rpc_call);
+ }
+
+ if(rpc_call && rpc_call->rep_num){
+ proto_tree_add_uint_format(rpc_tree, hf_rpc_repframe,
+ tvb, 0, 0, rpc_call->rep_num,
+ "The reply to this request is in frame %u",
+ rpc_call->rep_num);
+ }
+
+ offset += 16;
+
+ offset = dissect_rpc_cred(tvb, rpc_tree, offset);
+ offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
+
+ /* pass rpc_info to subdissectors */
+ rpc_call->request=TRUE;
+ pinfo->private_data=rpc_call;
+
+ /* go to the next dissector */
+
+ break; /* end of RPC call */
+
+ case RPC_REPLY:
+ /* we know already the type from the calling routine,
+ and we already have "rpc_call" set above. */
+ prog = rpc_call->prog;
+ vers = rpc_call->vers;
+ proc = rpc_call->proc;
+ flavor = rpc_call->flavor;
+ gss_proc = rpc_call->gss_proc;
+ gss_svc = rpc_call->gss_svc;
+
+ if (rpc_call->proc_info != NULL) {
+ dissect_function = rpc_call->proc_info->dissect_reply;
+ if (rpc_call->proc_info->name != NULL) {
+ procname = rpc_call->proc_info->name;
+ }
+ else {
+ sprintf(procname_static, "proc-%u", proc);
+ procname = procname_static;
+ }
+ }
+ else {
+#if 0
+ dissect_function = NULL;
+#endif
+ sprintf(procname_static, "proc-%u", proc);
+ procname = procname_static;
+ }
+
+ /*
+ * If this is an AUTH_GSSAPI message, then the RPC procedure
+ * is not an application procedure, but rather an auth level
+ * procedure, so it would be misleading to print the RPC
+ * procname. Replace the RPC procname with the corresponding
+ * AUTH_GSSAPI procname.
+ */
+ if (flavor == FLAVOR_AUTHGSSAPI_MSG) {
+ procname = match_strval(gss_proc, rpc_authgssapi_proc);
+ }
+
+ rpc_prog_key.prog = prog;
+ if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
+ proto = NULL;
+ proto_id = 0;
+ ett = 0;
+ progname = "Unknown";
+ }
+ else {
+ proto = rpc_prog->proto;
+ proto_id = rpc_prog->proto_id;
+ ett = rpc_prog->ett;
+ progname = rpc_prog->progname;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ /* Set the protocol name to the underlying
+ program name. */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (first_pdu)
+ col_clear(pinfo->cinfo, COL_INFO);
+ else
+ col_append_fstr(pinfo->cinfo, COL_INFO, " ; ");
+ col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s",
+ vers,
+ procname,
+ msg_type_name);
+ }
+
+ if (rpc_tree) {
+ proto_tree_add_uint_format(rpc_tree,
+ hf_rpc_program, tvb, 0, 0, prog,
+ "Program: %s (%u)", progname, prog);
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_programversion, tvb, 0, 0, vers);
+ proto_tree_add_uint_format(rpc_tree,
+ hf_rpc_procedure, tvb, 0, 0, proc,
+ "Procedure: %s (%u)", procname, proc);
+ }
+
+ reply_state = tvb_get_ntohl(tvb,offset+0);
+ if (rpc_tree) {
+ proto_tree_add_uint(rpc_tree, hf_rpc_state_reply, tvb,
+ offset+0, 4, reply_state);
+ }
+ offset += 4;
+
+ /* Indicate the frame to which this is a reply. */
+ if(rpc_call && rpc_call->req_num){
+ proto_tree_add_uint_format(rpc_tree, hf_rpc_reqframe,
+ tvb, 0, 0, rpc_call->req_num,
+ "This is a reply to a request in frame %u",
+ rpc_call->req_num);
+ ns.secs= pinfo->fd->abs_secs-rpc_call->req_time.secs;
+ ns.nsecs=pinfo->fd->abs_usecs*1000-rpc_call->req_time.nsecs;
+ if(ns.nsecs<0){
+ ns.nsecs+=1000000000;
+ ns.secs--;
+ }
+ proto_tree_add_time(rpc_tree, hf_rpc_time, tvb, offset, 0,
+ &ns);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO," (Call In %d)", rpc_call->req_num);
+ }
+ }
+
+
+ if ((!rpc_call) || (rpc_call->rep_num == 0)) {
+ /* We have not yet seen a reply to that call, so
+ this must be the first reply; remember its
+ frame number. */
+ rpc_call->rep_num = pinfo->fd->num;
+ } else {
+ /* We have seen a reply to this call - but was it
+ *this* reply? */
+ if (rpc_call->rep_num != pinfo->fd->num) {
+ /* No, so it's a duplicate reply.
+ Mark it as such. */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_prepend_fstr(pinfo->cinfo, COL_INFO,
+ "[RPC duplicate of #%d]", rpc_call->rep_num);
+ }
+ proto_tree_add_item(rpc_tree,
+ hf_rpc_dup, tvb, 0,0, TRUE);
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_reply_dup, tvb, 0,0, rpc_call->rep_num);
+ }
+ }
+
+ switch (reply_state) {
+
+ case MSG_ACCEPTED:
+ offset = dissect_rpc_verf(tvb, rpc_tree, offset, msg_type, pinfo);
+ accept_state = tvb_get_ntohl(tvb,offset+0);
+ if (rpc_tree) {
+ proto_tree_add_uint(rpc_tree, hf_rpc_state_accept, tvb,
+ offset+0, 4, accept_state);
+ }
+ offset += 4;
+ switch (accept_state) {
+
+ case SUCCESS:
+ /* go to the next dissector */
+ break;
+
+ case PROG_MISMATCH:
+ vers_low = tvb_get_ntohl(tvb,offset+0);
+ vers_high = tvb_get_ntohl(tvb,offset+4);
+ if (rpc_tree) {
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_programversion_min,
+ tvb, offset+0, 4, vers_low);
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_programversion_max,
+ tvb, offset+4, 4, vers_high);
+ }
+ offset += 8;
+
+ /*
+ * There's no protocol reply, so don't
+ * try to dissect it.
+ */
+ dissect_rpc = FALSE;
+ break;
+
+ default:
+ /*
+ * There's no protocol reply, so don't
+ * try to dissect it.
+ */
+ dissect_rpc = FALSE;
+ break;
+ }
+ break;
+
+ case MSG_DENIED:
+ reject_state = tvb_get_ntohl(tvb,offset+0);
+ if (rpc_tree) {
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_state_reject, tvb, offset+0, 4,
+ reject_state);
+ }
+ offset += 4;
+
+ if (reject_state==RPC_MISMATCH) {
+ vers_low = tvb_get_ntohl(tvb,offset+0);
+ vers_high = tvb_get_ntohl(tvb,offset+4);
+ if (rpc_tree) {
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_version_min,
+ tvb, offset+0, 4, vers_low);
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_version_max,
+ tvb, offset+4, 4, vers_high);
+ }
+ offset += 8;
+ } else if (reject_state==AUTH_ERROR) {
+ auth_state = tvb_get_ntohl(tvb,offset+0);
+ if (rpc_tree) {
+ proto_tree_add_uint(rpc_tree,
+ hf_rpc_state_auth, tvb, offset+0, 4,
+ auth_state);
+ }
+ offset += 4;
+ }
+
+ /*
+ * There's no protocol reply, so don't
+ * try to dissect it.
+ */
+ dissect_rpc = FALSE;
+ break;
+
+ default:
+ /*
+ * This isn't a valid reply state, so we have
+ * no clue what's going on; don't try to dissect
+ * the protocol reply.
+ */
+ dissect_rpc = FALSE;
+ break;
+ }
+ break; /* end of RPC reply */
+
+ default:
+ /*
+ * The switch statement at the top returned if
+ * this was neither an RPC call nor a reply.
+ */
+ g_assert_not_reached();
+ }
+
+ /* now we know, that RPC was shorter */
+ if (rpc_item) {
+ proto_item_set_end(rpc_item, tvb, offset);
+ }
+
+ if (!dissect_rpc) {
+ /*
+ * There's no RPC call or reply here; just dissect
+ * whatever's left as data.
+ */
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, rpc_tree);
+ return TRUE;
+ }
+
+ /* create here the program specific sub-tree */
+ if (tree && (flavor != FLAVOR_AUTHGSSAPI_MSG)) {
+ pitem = proto_tree_add_item(tree, proto_id, tvb, offset, -1,
+ FALSE);
+ if (pitem) {
+ ptree = proto_item_add_subtree(pitem, ett);
+ }
+
+ if (ptree) {
+ proto_tree_add_uint(ptree,
+ hf_rpc_programversion, tvb, 0, 0, vers);
+ if (rpc_prog->procedure_hfs->len > vers)
+ procedure_hf = g_array_index(rpc_prog->procedure_hfs, int, vers);
+ else {
+ /*
+ * No such element in the GArray.
+ */
+ procedure_hf = 0;
+ }
+ if (procedure_hf != 0 && procedure_hf != -1) {
+ proto_tree_add_uint(ptree,
+ procedure_hf, tvb, 0, 0, proc);
+ } else {
+ proto_tree_add_uint_format(ptree,
+ hf_rpc_procedure, tvb, 0, 0, proc,
+ "Procedure: %s (%u)", procname, proc);
+ }
+ }
+ }
+
+ /* we must queue this packet to the tap system before we actually
+ call the subdissectors since short packets (i.e. nfs read reply)
+ will cause an exception and execution would never reach the call
+ to tap_queue_packet() in that case
+ */
+ tap_queue_packet(rpc_tap, pinfo, rpc_call);
+
+ /* proto==0 if this is an unknown program */
+ if( (proto==0) || !proto_is_protocol_enabled(proto)){
+ dissect_function = NULL;
+ }
+
+ /*
+ * Handle RPCSEC_GSS and AUTH_GSSAPI specially.
+ */
+ switch (flavor) {
+
+ case FLAVOR_UNKNOWN:
+ /*
+ * We don't know the authentication flavor, so we can't
+ * dissect the payload.
+ */
+ proto_tree_add_text(ptree, tvb, offset, -1,
+ "Unknown authentication flavor - cannot dissect");
+ return TRUE;
+
+ case FLAVOR_NOT_GSSAPI:
+ /*
+ * It's not GSS-API authentication. Just dissect the
+ * payload.
+ */
+ offset = call_dissect_function(tvb, pinfo, ptree, offset,
+ dissect_function, progname);
+ break;
+
+ case FLAVOR_GSSAPI_NO_INFO:
+ /*
+ * It's GSS-API authentication, but we don't have the
+ * procedure and service information, so we can't dissect
+ * the payload.
+ */
+ proto_tree_add_text(ptree, tvb, offset, -1,
+ "GSS-API authentication, but procedure and service unknown - cannot dissect");
+ return TRUE;
+
+ case FLAVOR_GSSAPI:
+ /*
+ * It's GSS-API authentication, and we have the procedure
+ * and service information; process the GSS-API stuff,
+ * and process the payload if there is any.
+ */
+ switch (gss_proc) {
+
+ case RPCSEC_GSS_INIT:
+ case RPCSEC_GSS_CONTINUE_INIT:
+ if (msg_type == RPC_CALL) {
+ offset = dissect_rpc_authgss_initarg(tvb,
+ ptree, offset, pinfo);
+ }
+ else {
+ offset = dissect_rpc_authgss_initres(tvb,
+ ptree, offset, pinfo);
+ }
+ break;
+
+ case RPCSEC_GSS_DATA:
+ if (gss_svc == RPCSEC_GSS_SVC_NONE) {
+ offset = call_dissect_function(tvb,
+ pinfo, ptree, offset,
+ dissect_function,
+ progname);
+ }
+ else if (gss_svc == RPCSEC_GSS_SVC_INTEGRITY) {
+ offset = dissect_rpc_authgss_integ_data(tvb,
+ pinfo, ptree, offset,
+ dissect_function,
+ progname);
+ }
+ else if (gss_svc == RPCSEC_GSS_SVC_PRIVACY) {
+ offset = dissect_rpc_authgss_priv_data(tvb,
+ ptree, offset);
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case FLAVOR_AUTHGSSAPI_MSG:
+ /*
+ * This is an AUTH_GSSAPI message. It contains data
+ * only for the authentication procedure and not for the
+ * application level RPC procedure. Reset the column
+ * protocol and info fields to indicate that this is
+ * an RPC auth level message, then process the args.
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "%s %s XID 0x%x",
+ match_strval(gss_proc, rpc_authgssapi_proc),
+ msg_type_name, xid);
+ }
+
+ switch (gss_proc) {
+
+ case AUTH_GSSAPI_INIT:
+ case AUTH_GSSAPI_CONTINUE_INIT:
+ case AUTH_GSSAPI_MSG:
+ if (msg_type == RPC_CALL) {
+ offset = dissect_rpc_authgssapi_initarg(tvb,
+ rpc_tree, offset, pinfo);
+ } else {
+ offset = dissect_rpc_authgssapi_initres(tvb,
+ rpc_tree, offset, pinfo);
+ }
+ break;
+
+ case AUTH_GSSAPI_DESTROY:
+ offset = dissect_rpc_data(tvb, rpc_tree,
+ hf_rpc_authgss_data, offset);
+ break;
+
+ case AUTH_GSSAPI_EXIT:
+ break;
+ }
+
+ /* Adjust the length to account for the auth message. */
+ if (rpc_item) {
+ proto_item_set_end(rpc_item, tvb, offset);
+ }
+ break;
+
+ case FLAVOR_AUTHGSSAPI:
+ /*
+ * An RPC with AUTH_GSSAPI authentication. The data
+ * portion is always private, so don't call the dissector.
+ */
+ offset = dissect_auth_gssapi_data(tvb, ptree, offset);
+ break;
+ }
+
+ if (tvb_length_remaining(tvb, offset) > 0) {
+ /*
+ * dissect any remaining bytes (incomplete dissection) as pure
+ * data in the ptree
+ */
+
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, ptree);
+ }
+
+ /* XXX this should really loop over all fhandles registred for the frame */
+ if(nfs_fhandle_reqrep_matching){
+ nfs_fhandle_data_t *fhd;
+ switch (msg_type) {
+ case RPC_CALL:
+ if(rpc_call && rpc_call->rep_num){
+ fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
+ nfs_fhandle_frame_table,
+ (gconstpointer)rpc_call->rep_num);
+ if(fhd){
+ dissect_fhandle_hidden(pinfo,
+ ptree, fhd);
+ }
+ }
+ break;
+ case RPC_REPLY:
+ if(rpc_call && rpc_call->req_num){
+ fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
+ nfs_fhandle_frame_table,
+ (gconstpointer)rpc_call->req_num);
+ if(fhd){
+ dissect_fhandle_hidden(pinfo,
+ ptree, fhd);
+ }
+ }
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+dissect_rpc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
+ TRUE);
+}
+
+static void
+dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (!dissect_rpc_message(tvb, pinfo, tree, NULL, NULL, FALSE, 0,
+ TRUE)) {
+ if (tvb_length(tvb) != 0)
+ dissect_rpc_continuation(tvb, pinfo, tree);
+ }
+}
+
+
+/* Defragmentation of RPC-over-TCP records */
+/* table to hold defragmented RPC records */
+static GHashTable *rpc_fragment_table = NULL;
+
+static GHashTable *rpc_reassembly_table = NULL;
+static GMemChunk *rpc_fragment_key_chunk = NULL;
+static int rpc_fragment_init_count = 200;
+
+typedef struct _rpc_fragment_key {
+ guint32 conv_id;
+ guint32 seq;
+ guint32 offset;
+ /* xxx */
+ guint32 start_seq;
+} rpc_fragment_key;
+
+static guint
+rpc_fragment_hash(gconstpointer k)
+{
+ const rpc_fragment_key *key = (const rpc_fragment_key *)k;
+
+ return key->conv_id + key->seq;
+}
+
+static gint
+rpc_fragment_equal(gconstpointer k1, gconstpointer k2)
+{
+ const rpc_fragment_key *key1 = (const rpc_fragment_key *)k1;
+ const rpc_fragment_key *key2 = (const rpc_fragment_key *)k2;
+
+ return key1->conv_id == key2->conv_id &&
+ key1->seq == key2->seq;
+}
+
+static void
+show_rpc_fragheader(tvbuff_t *tvb, proto_tree *tree, guint32 rpc_rm)
+{
+ proto_item *hdr_item;
+ proto_tree *hdr_tree;
+ guint32 fraglen;
+
+ if (tree) {
+ fraglen = rpc_rm & RPC_RM_FRAGLEN;
+
+ hdr_item = proto_tree_add_text(tree, tvb, 0, 4,
+ "Fragment header: %s%u %s",
+ (rpc_rm & RPC_RM_LASTFRAG) ? "Last fragment, " : "",
+ fraglen, plurality(fraglen, "byte", "bytes"));
+ hdr_tree = proto_item_add_subtree(hdr_item, ett_rpc_fraghdr);
+
+ proto_tree_add_boolean(hdr_tree, hf_rpc_lastfrag, tvb, 0, 4,
+ rpc_rm);
+ proto_tree_add_uint(hdr_tree, hf_rpc_fraglen, tvb, 0, 4,
+ rpc_rm);
+ }
+}
+
+static void
+show_rpc_fragment(tvbuff_t *tvb, proto_tree *tree, guint32 rpc_rm)
+{
+ if (tree) {
+ /*
+ * Show the fragment header and the data for the fragment.
+ */
+ show_rpc_fragheader(tvb, tree, rpc_rm);
+ proto_tree_add_text(tree, tvb, 4, -1, "Fragment Data");
+ }
+}
+
+static void
+make_frag_tree(tvbuff_t *tvb, proto_tree *tree, int proto, gint ett,
+ guint32 rpc_rm)
+{
+ proto_item *frag_item;
+ proto_tree *frag_tree;
+
+ if (tree == NULL)
+ return; /* nothing to do */
+
+ frag_item = proto_tree_add_protocol_format(tree, proto, tvb, 0, -1,
+ "%s Fragment", proto_get_protocol_name(proto));
+ frag_tree = proto_item_add_subtree(frag_item, ett);
+ show_rpc_fragment(tvb, frag_tree, rpc_rm);
+}
+
+void
+show_rpc_fraginfo(tvbuff_t *tvb, tvbuff_t *frag_tvb, proto_tree *tree,
+ guint32 rpc_rm, fragment_data *ipfd_head, packet_info *pinfo)
+{
+ if (tree == NULL)
+ return; /* don't do any work */
+
+ if (tvb != frag_tvb) {
+ /*
+ * This message was not all in one fragment,
+ * so show the fragment header *and* the data
+ * for the fragment (which is the last fragment),
+ * and a tree with information about all fragments.
+ */
+ show_rpc_fragment(frag_tvb, tree, rpc_rm);
+
+ /*
+ * Show a tree with information about all fragments.
+ */
+ show_fragment_tree(ipfd_head, &rpc_frag_items, tree, pinfo, tvb);
+ } else {
+ /*
+ * This message was all in one fragment, so just show
+ * the fragment header.
+ */
+ show_rpc_fragheader(tvb, tree, rpc_rm);
+ }
+}
+
+static gboolean
+call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
+ proto_tree *tree, tvbuff_t *frag_tvb, rec_dissector_t dissector,
+ fragment_data *ipfd_head, guint32 rpc_rm, gboolean first_pdu)
+{
+ const char *saved_proto;
+ volatile gboolean rpc_succeeded;
+
+ /*
+ * Catch the ReportedBoundsError exception; if
+ * this particular message happens to get a
+ * ReportedBoundsError exception, that doesn't
+ * mean that we should stop dissecting RPC
+ * messages within this frame or chunk of
+ * reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's
+ * nothing more to see, so we just re-throw it.
+ */
+ saved_proto = pinfo->current_proto;
+ rpc_succeeded = FALSE;
+ TRY {
+ rpc_succeeded = (*dissector)(rec_tvb, pinfo, tree,
+ frag_tvb, ipfd_head, TRUE, rpc_rm, first_pdu);
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ pinfo->current_proto = saved_proto;
+
+ /*
+ * We treat this as a "successful" dissection of
+ * an RPC packet, as "dissect_rpc_message()"
+ * *did* decide it was an RPC packet, throwing
+ * an exception while dissecting it as such.
+ */
+ rpc_succeeded = TRUE;
+ }
+ ENDTRY;
+ return rpc_succeeded;
+}
+
+int
+dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, rec_dissector_t dissector, gboolean is_heur,
+ int proto, int ett, gboolean defragment, gboolean first_pdu)
+{
+ struct tcpinfo *tcpinfo = pinfo->private_data;
+ guint32 seq = tcpinfo->seq + offset;
+ guint32 rpc_rm;
+ volatile gint32 len;
+ gint32 seglen;
+ gint tvb_len, tvb_reported_len;
+ tvbuff_t *frag_tvb;
+ gboolean rpc_succeeded;
+ gboolean save_fragmented;
+ rpc_fragment_key old_rfk, *rfk, *new_rfk;
+ conversation_t *conversation;
+ fragment_data *ipfd_head;
+ tvbuff_t *rec_tvb;
+
+ /*
+ * Get the record mark.
+ */
+ if (!tvb_bytes_exist(tvb, offset, 4)) {
+ /*
+ * XXX - we should somehow arrange to handle
+ * a record mark split across TCP segments.
+ */
+ return 0; /* not enough to tell if it's valid */
+ }
+ rpc_rm = tvb_get_ntohl(tvb, offset);
+
+ len = rpc_rm & RPC_RM_FRAGLEN;
+
+ /*
+ * Do TCP desegmentation, if enabled.
+ *
+ * reject fragments bigger than this preference setting.
+ * This is arbitrary, but should at least prevent
+ * some crashes from either packets with really
+ * large RPC-over-TCP fragments or from stuff that's
+ * not really valid for this protocol.
+ */
+ if (len > max_rpc_tcp_pdu_size)
+ return 0; /* pretend it's not valid */
+ if (rpc_desegment) {
+ seglen = tvb_length_remaining(tvb, offset + 4);
+
+ if (len > seglen && pinfo->can_desegment) {
+ /*
+ * This frame doesn't have all of the
+ * data for this message, but we can do
+ * reassembly on it.
+ *
+ * If this is a heuristic dissector, just
+ * return 0 - we don't want to try to get
+ * more data, as that's too likely to cause
+ * us to misidentify this as valid.
+ *
+ * XXX - this means that we won't
+ * recognize the first fragment of a
+ * multi-fragment RPC operation unless
+ * we've already identified this
+ * conversation as being an RPC
+ * conversation (and thus aren't running
+ * heuristically) - that would be a problem
+ * if, for example, the first segment were
+ * the beginning of a large NFS WRITE.
+ *
+ * If this isn't a heuristic dissector,
+ * we've already identified this conversation
+ * as containing data for this protocol, as we
+ * saw valid data in previous frames. Try to
+ * get more data.
+ */
+ if (is_heur)
+ return 0; /* not valid */
+ else {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = len - seglen;
+ return -((gint32) pinfo->desegment_len);
+ }
+ }
+ }
+ len += 4; /* include record mark */
+ tvb_len = tvb_length_remaining(tvb, offset);
+ tvb_reported_len = tvb_reported_length_remaining(tvb, offset);
+ if (tvb_len > len)
+ tvb_len = len;
+ if (tvb_reported_len > len)
+ tvb_reported_len = len;
+ frag_tvb = tvb_new_subset(tvb, offset, tvb_len,
+ tvb_reported_len);
+
+ /*
+ * If we're not defragmenting, just hand this to the
+ * disssector.
+ */
+ if (!defragment) {
+ /*
+ * This is the first fragment we've seen, and it's also
+ * the last fragment; that means the record wasn't
+ * fragmented. Hand the dissector the tvbuff for the
+ * fragment as the tvbuff for the record.
+ */
+ rec_tvb = frag_tvb;
+ ipfd_head = NULL;
+
+ /*
+ * Mark this as fragmented, so if somebody throws an
+ * exception, we don't report it as a malformed frame.
+ */
+ save_fragmented = pinfo->fragmented;
+ pinfo->fragmented = TRUE;
+ rpc_succeeded = call_message_dissector(tvb, rec_tvb, pinfo,
+ tree, frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu);
+ pinfo->fragmented = save_fragmented;
+ if (!rpc_succeeded)
+ return 0; /* not RPC */
+ return len;
+ }
+
+ /*
+ * First, we check to see if this fragment is part of a record
+ * that we're in the process of defragmenting.
+ *
+ * The key is the conversation ID for the conversation to which
+ * the packet belongs and the current sequence number.
+ * We must first find the conversation and, if we don't find
+ * one, create it. We know this is running over TCP, so the
+ * conversation should not wildcard either address or port.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL) {
+ /*
+ * It's not part of any conversation - create a new one.
+ */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ old_rfk.conv_id = conversation->index;
+ old_rfk.seq = seq;
+ rfk = g_hash_table_lookup(rpc_reassembly_table, &old_rfk);
+
+ if (rfk == NULL) {
+ /*
+ * This fragment was not found in our table, so it doesn't
+ * contain a continuation of a higher-level PDU.
+ * Is it the last fragment?
+ */
+ if (!(rpc_rm & RPC_RM_LASTFRAG)) {
+ /*
+ * This isn't the last fragment, so we don't
+ * have the complete record.
+ *
+ * It's the first fragment we've seen, so if
+ * it's truly the first fragment of the record,
+ * and it has enough data, the dissector can at
+ * least check whether it looks like a valid
+ * message, as it contains the start of the
+ * message.
+ *
+ * The dissector should not dissect anything
+ * if the "last fragment" flag isn't set in
+ * the record marker, so it shouldn't throw
+ * an exception.
+ */
+ if (!(*dissector)(frag_tvb, pinfo, tree, frag_tvb,
+ NULL, TRUE, rpc_rm, first_pdu))
+ return 0; /* not valid */
+
+ /*
+ * OK, now start defragmentation with that
+ * fragment. Add this fragment, and set up
+ * next packet/sequence number as well.
+ *
+ * We must remember this fragment.
+ */
+
+ rfk = g_mem_chunk_alloc(rpc_fragment_key_chunk);
+ rfk->conv_id = conversation->index;
+ rfk->seq = seq;
+ rfk->offset = 0;
+ rfk->start_seq = seq;
+ g_hash_table_insert(rpc_reassembly_table, rfk, rfk);
+
+ /*
+ * Start defragmentation.
+ */
+ ipfd_head = fragment_add_multiple_ok(tvb, offset + 4,
+ pinfo, rfk->start_seq, rpc_fragment_table,
+ rfk->offset, len - 4, TRUE);
+
+ /*
+ * Make sure that defragmentation isn't complete;
+ * it shouldn't be, as this is the first fragment
+ * we've seen, and the "last fragment" bit wasn't
+ * set on it.
+ */
+ g_assert(ipfd_head == NULL);
+
+ new_rfk = g_mem_chunk_alloc(rpc_fragment_key_chunk);
+ new_rfk->conv_id = rfk->conv_id;
+ new_rfk->seq = seq + len;
+ new_rfk->offset = rfk->offset + len - 4;
+ new_rfk->start_seq = rfk->start_seq;
+ g_hash_table_insert(rpc_reassembly_table, new_rfk,
+ new_rfk);
+
+ /*
+ * This is part of a fragmented record,
+ * but it's not the first part.
+ * Show it as a record marker plus data, under
+ * a top-level tree for this protocol.
+ */
+ make_frag_tree(frag_tvb, tree, proto, ett,rpc_rm);
+
+ /*
+ * No more processing need be done, as we don't
+ * have a complete record.
+ */
+ return len;
+ }
+
+ /*
+ * This is the first fragment we've seen, and it's also
+ * the last fragment; that means the record wasn't
+ * fragmented. Hand the dissector the tvbuff for the
+ * fragment as the tvbuff for the record.
+ */
+ rec_tvb = frag_tvb;
+ ipfd_head = NULL;
+ } else {
+ /*
+ * OK, this fragment was found, which means it continues
+ * a record. This means we must defragment it.
+ * Add it to the defragmentation lists.
+ */
+ ipfd_head = fragment_add_multiple_ok(tvb, offset + 4, pinfo,
+ rfk->start_seq, rpc_fragment_table,
+ rfk->offset, len - 4, !(rpc_rm & RPC_RM_LASTFRAG));
+
+ if (ipfd_head == NULL) {
+ /*
+ * fragment_add_multiple_ok() returned NULL.
+ * This means that defragmentation is not
+ * completed yet.
+ *
+ * We must add an entry to the hash table with
+ * the sequence number following this fragment
+ * as the starting sequence number, so that when
+ * we see that fragment we'll find that entry.
+ *
+ * XXX - as TCP stream data is not currently
+ * guaranteed to be provided in order to dissectors,
+ * RPC fragments aren't guaranteed to be provided
+ * in order, either.
+ */
+ new_rfk = g_mem_chunk_alloc(rpc_fragment_key_chunk);
+ new_rfk->conv_id = rfk->conv_id;
+ new_rfk->seq = seq + len;
+ new_rfk->offset = rfk->offset + len - 4;
+ new_rfk->start_seq = rfk->start_seq;
+ g_hash_table_insert(rpc_reassembly_table, new_rfk,
+ new_rfk);
+
+ /*
+ * This is part of a fragmented record,
+ * but it's not the first part.
+ * Show it as a record marker plus data, under
+ * a top-level tree for this protocol,
+ * but don't hand it to the dissector
+ */
+ make_frag_tree(frag_tvb, tree, proto, ett, rpc_rm);
+
+ /*
+ * No more processing need be done, as we don't
+ * have a complete record.
+ */
+ return len;
+ }
+
+ /*
+ * It's completely defragmented.
+ *
+ * We only call subdissector for the last fragment.
+ * XXX - this assumes in-order delivery of RPC
+ * fragments, which requires in-order delivery of TCP
+ * segments.
+ */
+ if (!(rpc_rm & RPC_RM_LASTFRAG)) {
+ /*
+ * Well, it's defragmented, but this isn't
+ * the last fragment; this probably means
+ * this isn't the first pass, so we don't
+ * need to start defragmentation.
+ *
+ * This is part of a fragmented record,
+ * but it's not the first part.
+ * Show it as a record marker plus data, under
+ * a top-level tree for this protocol,
+ * but don't show it to the dissector.
+ */
+ make_frag_tree(frag_tvb, tree, proto, ett, rpc_rm);
+
+ /*
+ * No more processing need be done, as we
+ * only disssect the data with the last
+ * fragment.
+ */
+ return len;
+ }
+
+ /*
+ * OK, this is the last segment.
+ * Create a tvbuff for the defragmented
+ * record.
+ */
+
+ /*
+ * Create a new TVB structure for
+ * defragmented data.
+ */
+ rec_tvb = tvb_new_real_data(ipfd_head->data,
+ ipfd_head->datalen, ipfd_head->datalen);
+
+ /*
+ * Add this tvb as a child to the original
+ * one.
+ */
+ tvb_set_child_real_data_tvbuff(tvb, rec_tvb);
+
+ /*
+ * Add defragmented data to the data source list.
+ */
+ add_new_data_source(pinfo, rec_tvb, "Defragmented");
+ }
+
+ /*
+ * We have something to hand to the RPC message
+ * dissector.
+ */
+ if (!call_message_dissector(tvb, rec_tvb, pinfo, tree,
+ frag_tvb, dissector, ipfd_head, rpc_rm, first_pdu))
+ return 0; /* not RPC */
+ return len;
+}
+
+/*
+ * Can return:
+ *
+ * NEED_MORE_DATA, if we don't have enough data to dissect anything;
+ *
+ * IS_RPC, if we dissected at least one message in its entirety
+ * as RPC;
+ *
+ * IS_NOT_RPC, if we found no RPC message.
+ */
+typedef enum {
+ NEED_MORE_DATA,
+ IS_RPC,
+ IS_NOT_RPC
+} rpc_tcp_return_t;
+
+static rpc_tcp_return_t
+dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean is_heur)
+{
+ int offset = 0;
+ gboolean saw_rpc = FALSE;
+ gboolean first_pdu = TRUE;
+ int len;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * Process this fragment.
+ */
+ len = dissect_rpc_fragment(tvb, offset, pinfo, tree,
+ dissect_rpc_message, is_heur, proto_rpc, ett_rpc,
+ rpc_defragment, first_pdu);
+ first_pdu = FALSE;
+ if (len < 0) {
+ /*
+ * We need more data from the TCP stream for
+ * this fragment.
+ */
+ return NEED_MORE_DATA;
+ }
+ if (len == 0) {
+ /*
+ * It's not RPC. Stop processing.
+ */
+ break;
+ }
+
+ /* PDU tracking
+ If the length indicates that the PDU continues beyond
+ the end of this tvb, then tell TCP about it so that it
+ knows where the next PDU starts.
+ This is to help TCP detect when PDUs are not aligned to
+ segment boundaries and allow it to find RPC headers
+ that starts in the middle of a TCP segment.
+ */
+ if(!pinfo->fd->flags.visited){
+ if(len>tvb_reported_length_remaining(tvb, offset)){
+ pinfo->want_pdu_tracking=2;
+ pinfo->bytes_until_next_pdu=len-tvb_reported_length_remaining(tvb, offset);
+ }
+ }
+ offset += len;
+ saw_rpc = TRUE;
+ }
+ return saw_rpc ? IS_RPC : IS_NOT_RPC;
+}
+
+static gboolean
+dissect_rpc_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ switch (dissect_rpc_tcp_common(tvb, pinfo, tree, TRUE)) {
+
+ case IS_RPC:
+ return TRUE;
+
+ case IS_NOT_RPC:
+ return FALSE;
+
+ default:
+ /* "Can't happen" */
+ g_assert_not_reached();
+ return FALSE;
+ }
+}
+
+static void
+dissect_rpc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (dissect_rpc_tcp_common(tvb, pinfo, tree, FALSE) == IS_NOT_RPC)
+ dissect_rpc_continuation(tvb, pinfo, tree);
+}
+
+/* Discard any state we've saved. */
+static void
+rpc_init_protocol(void)
+{
+ if (rpc_calls != NULL) {
+ g_hash_table_destroy(rpc_calls);
+ rpc_calls = NULL;
+ }
+ if (rpc_indir_calls != NULL) {
+ g_hash_table_destroy(rpc_indir_calls);
+ rpc_indir_calls = NULL;
+ }
+ if (rpc_call_info_key_chunk != NULL) {
+ g_mem_chunk_destroy(rpc_call_info_key_chunk);
+ rpc_call_info_key_chunk = NULL;
+ }
+ if (rpc_call_info_value_chunk != NULL) {
+ g_mem_chunk_destroy(rpc_call_info_value_chunk);
+ rpc_call_info_value_chunk = NULL;
+ }
+ if (rpc_fragment_key_chunk != NULL) {
+ g_mem_chunk_destroy(rpc_fragment_key_chunk);
+ rpc_fragment_key_chunk = NULL;
+ }
+ if (rpc_reassembly_table != NULL) {
+ g_hash_table_destroy(rpc_reassembly_table);
+ rpc_reassembly_table = NULL;
+ }
+
+ rpc_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
+ rpc_indir_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
+ rpc_call_info_key_chunk = g_mem_chunk_new("call_info_key_chunk",
+ sizeof(rpc_call_info_key),
+ 200 * sizeof(rpc_call_info_key),
+ G_ALLOC_ONLY);
+ rpc_call_info_value_chunk = g_mem_chunk_new("call_info_value_chunk",
+ sizeof(rpc_call_info_value),
+ 200 * sizeof(rpc_call_info_value),
+ G_ALLOC_ONLY);
+ rpc_fragment_key_chunk = g_mem_chunk_new("rpc_fragment_key_chunk",
+ sizeof(rpc_fragment_key),
+ rpc_fragment_init_count*sizeof(rpc_fragment_key),
+ G_ALLOC_ONLY);
+ rpc_reassembly_table = g_hash_table_new(rpc_fragment_hash,
+ rpc_fragment_equal);
+
+ fragment_table_init(&rpc_fragment_table);
+}
+
+/* will be called once from register.c at startup time */
+void
+proto_register_rpc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rpc_reqframe, {
+ "Request Frame", "rpc.reqframe", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "Request Frame", HFILL }},
+ { &hf_rpc_repframe, {
+ "Reply Frame", "rpc.repframe", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "Reply Frame", HFILL }},
+ { &hf_rpc_lastfrag, {
+ "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, 32,
+ &yesno, RPC_RM_LASTFRAG, "Last Fragment", HFILL }},
+ { &hf_rpc_fraglen, {
+ "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
+ NULL, RPC_RM_FRAGLEN, "Fragment Length", HFILL }},
+ { &hf_rpc_xid, {
+ "XID", "rpc.xid", FT_UINT32, BASE_HEX,
+ NULL, 0, "XID", HFILL }},
+ { &hf_rpc_msgtype, {
+ "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
+ VALS(rpc_msg_type), 0, "Message Type", HFILL }},
+ { &hf_rpc_state_reply, {
+ "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
+ VALS(rpc_reply_state), 0, "Reply State", HFILL }},
+ { &hf_rpc_state_accept, {
+ "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
+ VALS(rpc_accept_state), 0, "Accept State", HFILL }},
+ { &hf_rpc_state_reject, {
+ "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
+ VALS(rpc_reject_state), 0, "Reject State", HFILL }},
+ { &hf_rpc_state_auth, {
+ "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
+ VALS(rpc_auth_state), 0, "Auth State", HFILL }},
+ { &hf_rpc_version, {
+ "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
+ NULL, 0, "RPC Version", HFILL }},
+ { &hf_rpc_version_min, {
+ "RPC Version (Minimum)", "rpc.version.min", FT_UINT32,
+ BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
+ { &hf_rpc_version_max, {
+ "RPC Version (Maximum)", "rpc.version.max", FT_UINT32,
+ BASE_DEC, NULL, 0, "RPC Version (Maximum)", HFILL }},
+ { &hf_rpc_program, {
+ "Program", "rpc.program", FT_UINT32, BASE_DEC,
+ NULL, 0, "Program", HFILL }},
+ { &hf_rpc_programversion, {
+ "Program Version", "rpc.programversion", FT_UINT32,
+ BASE_DEC, NULL, 0, "Program Version", HFILL }},
+ { &hf_rpc_programversion_min, {
+ "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32,
+ BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
+ { &hf_rpc_programversion_max, {
+ "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32,
+ BASE_DEC, NULL, 0, "Program Version (Maximum)", HFILL }},
+ { &hf_rpc_procedure, {
+ "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
+ NULL, 0, "Procedure", HFILL }},
+ { &hf_rpc_auth_flavor, {
+ "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
+ VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
+ { &hf_rpc_auth_length, {
+ "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length", HFILL }},
+ { &hf_rpc_auth_stamp, {
+ "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
+ NULL, 0, "Stamp", HFILL }},
+ { &hf_rpc_auth_uid, {
+ "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
+ NULL, 0, "UID", HFILL }},
+ { &hf_rpc_auth_gid, {
+ "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
+ NULL, 0, "GID", HFILL }},
+ { &hf_rpc_authgss_v, {
+ "GSS Version", "rpc.authgss.version", FT_UINT32,
+ BASE_DEC, NULL, 0, "GSS Version", HFILL }},
+ { &hf_rpc_authgss_proc, {
+ "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
+ BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure", HFILL }},
+ { &hf_rpc_authgss_seq, {
+ "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
+ BASE_DEC, NULL, 0, "GSS Sequence Number", HFILL }},
+ { &hf_rpc_authgss_svc, {
+ "GSS Service", "rpc.authgss.service", FT_UINT32,
+ BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service", HFILL }},
+ { &hf_rpc_authgss_ctx, {
+ "GSS Context", "rpc.authgss.context", FT_BYTES,
+ BASE_HEX, NULL, 0, "GSS Context", HFILL }},
+ { &hf_rpc_authgss_major, {
+ "GSS Major Status", "rpc.authgss.major", FT_UINT32,
+ BASE_DEC, NULL, 0, "GSS Major Status", HFILL }},
+ { &hf_rpc_authgss_minor, {
+ "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
+ BASE_DEC, NULL, 0, "GSS Minor Status", HFILL }},
+ { &hf_rpc_authgss_window, {
+ "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
+ BASE_DEC, NULL, 0, "GSS Sequence Window", HFILL }},
+ { &hf_rpc_authgss_token_length, {
+ "GSS Token Length", "rpc.authgss.token_length", FT_UINT32,
+ BASE_DEC, NULL, 0, "GSS Token Length", HFILL }},
+ { &hf_rpc_authgss_data_length, {
+ "Length", "rpc.authgss.data.length", FT_UINT32,
+ BASE_DEC, NULL, 0, "Length", HFILL }},
+ { &hf_rpc_authgss_data, {
+ "GSS Data", "rpc.authgss.data", FT_BYTES,
+ BASE_HEX, NULL, 0, "GSS Data", HFILL }},
+ { &hf_rpc_authgss_checksum, {
+ "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
+ BASE_HEX, NULL, 0, "GSS Checksum", HFILL }},
+ { &hf_rpc_authgssapi_v, {
+ "AUTH_GSSAPI Version", "rpc.authgssapi.version",
+ FT_UINT32, BASE_DEC, NULL, 0, "AUTH_GSSAPI Version",
+ HFILL }},
+ { &hf_rpc_authgssapi_msg, {
+ "AUTH_GSSAPI Message", "rpc.authgssapi.message",
+ FT_BOOLEAN, BASE_NONE, &yesno, 0, "AUTH_GSSAPI Message",
+ HFILL }},
+ { &hf_rpc_authgssapi_msgv, {
+ "Msg Version", "rpc.authgssapi.msgversion",
+ FT_UINT32, BASE_DEC, NULL, 0, "Msg Version",
+ HFILL }},
+ { &hf_rpc_authgssapi_handle, {
+ "Client Handle", "rpc.authgssapi.handle",
+ FT_BYTES, BASE_HEX, NULL, 0, "Client Handle", HFILL }},
+ { &hf_rpc_authgssapi_isn, {
+ "Signed ISN", "rpc.authgssapi.isn",
+ FT_BYTES, BASE_HEX, NULL, 0, "Signed ISN", HFILL }},
+ { &hf_rpc_authdes_namekind, {
+ "Namekind", "rpc.authdes.namekind", FT_UINT32, BASE_DEC,
+ VALS(rpc_authdes_namekind), 0, "Namekind", HFILL }},
+ { &hf_rpc_authdes_netname, {
+ "Netname", "rpc.authdes.netname", FT_STRING,
+ BASE_DEC, NULL, 0, "Netname", HFILL }},
+ { &hf_rpc_authdes_convkey, {
+ "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT32,
+ BASE_HEX, NULL, 0, "Conversation Key (encrypted)", HFILL }},
+ { &hf_rpc_authdes_window, {
+ "Window (encrypted)", "rpc.authdes.window", FT_UINT32,
+ BASE_HEX, NULL, 0, "Windows (encrypted)", HFILL }},
+ { &hf_rpc_authdes_nickname, {
+ "Nickname", "rpc.authdes.nickname", FT_UINT32,
+ BASE_HEX, NULL, 0, "Nickname", HFILL }},
+ { &hf_rpc_authdes_timestamp, {
+ "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT32,
+ BASE_HEX, NULL, 0, "Timestamp (encrypted)", HFILL }},
+ { &hf_rpc_authdes_windowverf, {
+ "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32,
+ BASE_HEX, NULL, 0, "Window verifier (encrypted)", HFILL }},
+ { &hf_rpc_authdes_timeverf, {
+ "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT32,
+ BASE_HEX, NULL, 0, "Timestamp verifier (encrypted)", HFILL }},
+ { &hf_rpc_auth_machinename, {
+ "Machine Name", "rpc.auth.machinename", FT_STRING,
+ BASE_DEC, NULL, 0, "Machine Name", HFILL }},
+ { &hf_rpc_dup, {
+ "Duplicate Call/Reply", "rpc.dup", FT_NONE, BASE_NONE,
+ NULL, 0, "Duplicate Call/Reply", HFILL }},
+ { &hf_rpc_call_dup, {
+ "Duplicate to the call in", "rpc.call.dup", FT_FRAMENUM, BASE_DEC,
+ NULL, 0, "This is a duplicate to the call in frame", HFILL }},
+ { &hf_rpc_reply_dup, {
+ "Duplicate to the reply in", "rpc.reply.dup", FT_FRAMENUM, BASE_DEC,
+ NULL, 0, "This is a duplicate to the reply in frame", HFILL }},
+ { &hf_rpc_value_follows, {
+ "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "Value Follows", HFILL }},
+ { &hf_rpc_array_len, {
+ "num", "rpc.array.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of RPC array", HFILL }},
+
+ { &hf_rpc_time, {
+ "Time from request", "rpc.time", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Time between Request and Reply for ONC-RPC calls", HFILL }},
+
+ { &hf_rpc_fragment_overlap,
+ { "Fragment overlap", "rpc.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_rpc_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "rpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_rpc_fragment_multiple_tails,
+ { "Multiple tail fragments found", "rpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_rpc_fragment_too_long_fragment,
+ { "Fragment too long", "rpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+
+ { &hf_rpc_fragment_error,
+ { "Defragmentation error", "rpc.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }},
+
+ { &hf_rpc_fragment,
+ { "RPC Fragment", "rpc.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "RPC Fragment", HFILL }},
+
+ { &hf_rpc_fragments,
+ { "RPC Fragments", "rpc.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
+ "RPC Fragments", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_rpc,
+ &ett_rpc_fragments,
+ &ett_rpc_fragment,
+ &ett_rpc_fraghdr,
+ &ett_rpc_string,
+ &ett_rpc_cred,
+ &ett_rpc_verf,
+ &ett_rpc_gids,
+ &ett_rpc_gss_token,
+ &ett_rpc_gss_data,
+ &ett_rpc_array,
+ &ett_rpc_authgssapi_msg,
+ &ett_rpc_unknown_program,
+ };
+ module_t *rpc_module;
+
+ proto_rpc = proto_register_protocol("Remote Procedure Call",
+ "RPC", "rpc");
+ /* this is a dummy dissector for all those unknown rpc programs */
+ proto_register_field_array(proto_rpc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&rpc_init_protocol);
+
+ rpc_module = prefs_register_protocol(proto_rpc, NULL);
+ prefs_register_bool_preference(rpc_module, "desegment_rpc_over_tcp",
+ "Desegment all RPC-over-TCP messages",
+ "Whether the RPC dissector should desegment all RPC-over-TCP messages",
+ &rpc_desegment);
+ prefs_register_bool_preference(rpc_module, "defragment_rpc_over_tcp",
+ "Defragment all RPC-over-TCP messages",
+ "Whether the RPC dissector should defragment multi-fragment RPC-over-TCP messages",
+ &rpc_defragment);
+
+ prefs_register_uint_preference(rpc_module, "max_tcp_pdu_size", "Maximum size of a RPC-over-TCP PDU",
+ "Set the maximum size of RPCoverTCP PDUs. "
+ " If the size field of the record marker is larger "
+ "than this value it will not be considered a valid RPC PDU",
+ 10, &max_rpc_tcp_pdu_size);
+
+ prefs_register_bool_preference(rpc_module, "dissect_unknown_programs",
+ "Dissect unknown RPC program numbers",
+ "Whether the RPC dissector should attempt to dissect RPC PDUs containing programs that are not known to Ethereal. This will make the heuristics significantly weaker and elevate the risk for falsely identifying and misdissecting packets significantly.",
+ &rpc_dissect_unknown_programs);
+
+ register_dissector("rpc", dissect_rpc, proto_rpc);
+ rpc_handle = find_dissector("rpc");
+ register_dissector("rpc-tcp", dissect_rpc_tcp, proto_rpc);
+ rpc_tcp_handle = find_dissector("rpc-tcp");
+ rpc_tap = register_tap("rpc");
+
+ /*
+ * Init the hash tables. Dissectors for RPC protocols must
+ * have a "handoff registration" routine that registers the
+ * protocol with RPC; they must not do it in their protocol
+ * registration routine, as their protocol registration
+ * routine might be called before this routine is called and
+ * thus might be called before the hash tables are initialized,
+ * but it's guaranteed that all protocol registration routines
+ * will be called before any handoff registration routines
+ * are called.
+ */
+ rpc_progs = g_hash_table_new(rpc_prog_hash, rpc_prog_equal);
+ rpc_procs = g_hash_table_new(rpc_proc_hash, rpc_proc_equal);
+}
+
+void
+proto_reg_handoff_rpc(void)
+{
+ dissector_handle_t rpc_tcp_handle;
+ dissector_handle_t rpc_udp_handle;
+
+ /* tcp/udp port 111 is used by portmapper which is an onc-rpc service.
+ we register onc-rpc on this port so that we can choose RPC in
+ the list offered by DecodeAs, and so that traffic to or from
+ port 111 from or to a higher-numbered port is dissected as RPC
+ even if there's a dissector registered on the other port (it's
+ probably RPC traffic from some randomly-chosen port that happens
+ to match some port for which we have a dissector)
+ */
+ rpc_tcp_handle = create_dissector_handle(dissect_rpc_tcp, proto_rpc);
+ dissector_add("tcp.port", 111, rpc_tcp_handle);
+ rpc_udp_handle = create_dissector_handle(dissect_rpc, proto_rpc);
+ dissector_add("udp.port", 111, rpc_udp_handle);
+
+ heur_dissector_add("tcp", dissect_rpc_tcp_heur, proto_rpc);
+ heur_dissector_add("udp", dissect_rpc_heur, proto_rpc);
+ gssapi_handle = find_dissector("gssapi");
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-rpc.h b/epan/dissectors/packet-rpc.h
new file mode 100644
index 0000000000..3eb5312e8b
--- /dev/null
+++ b/epan/dissectors/packet-rpc.h
@@ -0,0 +1,196 @@
+/* packet-rpc.h
+ *
+ * $Id$
+ *
+ * (c) 1999 Uwe Girlich
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_RPC_H__
+#define __PACKET_RPC_H__
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#define RPC_CALL 0
+#define RPC_REPLY 1
+
+#define AUTH_NULL 0
+#define AUTH_UNIX 1
+#define AUTH_SHORT 2
+#define AUTH_DES 3
+#define RPCSEC_GSS 6
+#define AUTH_GSSAPI 300001
+
+#define MSG_ACCEPTED 0
+#define MSG_DENIED 1
+
+#define SUCCESS 0
+#define PROG_UNAVAIL 1
+#define PROG_MISMATCH 2
+#define PROC_UNAVAIL 3
+#define GARBAGE_ARGS 4
+
+#define RPC_MISMATCH 0
+#define AUTH_ERROR 1
+
+#define AUTH_BADCRED 1
+#define AUTH_REJECTEDCRED 2
+#define AUTH_BADVERF 3
+#define AUTH_REJECTEDVERF 4
+#define AUTH_TOOWEAK 5
+#define RPCSEC_GSSCREDPROB 13
+#define RPCSEC_GSSCTXPROB 14
+
+#define RPCSEC_GSS_DATA 0
+#define RPCSEC_GSS_INIT 1
+#define RPCSEC_GSS_CONTINUE_INIT 2
+#define RPCSEC_GSS_DESTROY 3
+
+#define AUTH_GSSAPI_EXIT 0
+#define AUTH_GSSAPI_INIT 1
+#define AUTH_GSSAPI_CONTINUE_INIT 2
+#define AUTH_GSSAPI_MSG 3
+#define AUTH_GSSAPI_DESTROY 4
+
+#define RPCSEC_GSS_SVC_NONE 1
+#define RPCSEC_GSS_SVC_INTEGRITY 2
+#define RPCSEC_GSS_SVC_PRIVACY 3
+
+#define AUTHDES_NAMEKIND_FULLNAME 0
+#define AUTHDES_NAMEKIND_NICKNAME 1
+
+extern value_string rpc_authgss_svc[];
+typedef enum {
+ FLAVOR_UNKNOWN, /* authentication flavor unknown */
+ FLAVOR_NOT_GSSAPI, /* flavor isn't GSSAPI */
+ FLAVOR_GSSAPI_NO_INFO, /* flavor is GSSAPI, procedure & service unknown */
+ FLAVOR_GSSAPI, /* flavor is GSSAPI, procedure & service known */
+ FLAVOR_AUTHGSSAPI, /* AUTH_GSSAPI flavor */
+ FLAVOR_AUTHGSSAPI_MSG /* AUTH_GSSAPI flavor, AUTH_GSSAPI message */
+} flavor_t;
+
+typedef struct _rpc_call_info_value {
+ guint32 req_num; /* frame number of first request seen */
+ guint32 rep_num; /* frame number of first reply seen */
+ guint32 prog;
+ guint32 vers;
+ guint32 proc;
+ guint32 xid;
+ flavor_t flavor;
+ guint32 gss_proc;
+ guint32 gss_svc;
+ struct _rpc_proc_info_value* proc_info;
+ gboolean request; /* Is this a request or not ?*/
+ nstime_t req_time;
+ void *private_data;
+} rpc_call_info_value;
+
+
+typedef int (dissect_function_t)(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree* tree);
+
+typedef struct _vsff {
+ guint32 value;
+ gchar *strptr;
+ dissect_function_t *dissect_call;
+ dissect_function_t *dissect_reply;
+} vsff;
+
+extern const value_string rpc_auth_flavor[];
+
+extern void rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table,
+ int procedure_hf);
+extern void rpc_init_prog(int proto, guint32 prog, int ett);
+extern char *rpc_prog_name(guint32 prog);
+extern char *rpc_proc_name(guint32 prog, guint32 vers, guint32 proc);
+extern int rpc_prog_hf(guint32 prog, guint32 vers);
+
+extern unsigned int rpc_roundup(unsigned int a);
+extern int dissect_rpc_bool(tvbuff_t *tvb,
+ proto_tree *tree, int hfindex, int offset);
+extern int dissect_rpc_string(tvbuff_t *tvb,
+ proto_tree *tree, int hfindex, int offset, char **string_buffer_ret);
+int dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
+ proto_tree *tree,
+ packet_info *pinfo,
+ int hfindex,
+ gboolean fixed_length, guint32 length,
+ gboolean string_data, char **string_buffer_ret,
+ dissect_function_t *dissect_it);
+extern int dissect_rpc_data(tvbuff_t *tvb,
+ proto_tree *tree, int hfindex, int offset);
+extern int dissect_rpc_bytes(tvbuff_t *tvb,
+ proto_tree *tree, int hfindex, int offset, guint32 length,
+ gboolean string_data, char **string_buffer_ret);
+extern int dissect_rpc_list(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int offset, dissect_function_t *rpc_list_dissector);
+extern int dissect_rpc_array(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int offset, dissect_function_t *rpc_array_dissector,
+ int hfindex);
+extern int dissect_rpc_uint32(tvbuff_t *tvb,
+ proto_tree *tree, int hfindex, int offset);
+extern int dissect_rpc_uint64(tvbuff_t *tvb,
+ proto_tree *tree, int hfindex, int offset);
+
+extern int dissect_rpc_indir_call(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int offset, int args_id, guint32 prog, guint32 vers,
+ guint32 proc);
+extern int dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int offset, int result_id, int prog_id, int vers_id,
+ int proc_id);
+
+
+typedef struct _rpc_prog_info_key {
+ guint32 prog;
+} rpc_prog_info_key;
+
+typedef struct _rpc_prog_info_value {
+ protocol_t *proto;
+ int proto_id;
+ int ett;
+ char* progname;
+ GArray *procedure_hfs;
+} rpc_prog_info_value;
+
+/* rpc_progs is also used in tap. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT GHashTable *rpc_progs;
+
+typedef struct _rpc_proc_info_key {
+ guint32 prog;
+ guint32 vers;
+ guint32 proc;
+} rpc_proc_info_key;
+
+typedef struct _rpc_proc_info_value {
+ gchar *name;
+ dissect_function_t *dissect_call;
+ dissect_function_t *dissect_reply;
+} rpc_proc_info_value;
+
+/* rpc_procs is also used in tap. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT GHashTable *rpc_procs;
+
+#endif /* packet-rpc.h */
+
diff --git a/epan/dissectors/packet-rpl.c b/epan/dissectors/packet-rpl.c
new file mode 100644
index 0000000000..9fc84ac5af
--- /dev/null
+++ b/epan/dissectors/packet-rpl.c
@@ -0,0 +1,415 @@
+/* packet-rpl.c
+ * Routines for RPL
+ * Jochen Friedrich <jochen@scram.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include "llcsaps.h"
+#include "packet-llc.h"
+
+static int proto_rpl = -1;
+
+static int hf_rpl_type = -1;
+static int hf_rpl_corrval = -1;
+static int hf_rpl_respval = -1;
+static int hf_rpl_maxframe = -1;
+static int hf_rpl_connclass = -1;
+static int hf_rpl_lmac = -1;
+static int hf_rpl_smac = -1;
+static int hf_rpl_sap = -1;
+static int hf_rpl_equipment = -1;
+static int hf_rpl_memsize = -1;
+static int hf_rpl_bsmversion = -1;
+static int hf_rpl_adapterid = -1;
+static int hf_rpl_shortname = -1;
+static int hf_rpl_laddress = -1;
+static int hf_rpl_xaddress = -1;
+static int hf_rpl_sequence = -1;
+static int hf_rpl_config = -1;
+static int hf_rpl_flags = -1;
+static int hf_rpl_data = -1;
+static int hf_rpl_ec = -1;
+
+static gint ett_rpl = -1;
+static gint ett_rpl_0004 = -1;
+static gint ett_rpl_0008 = -1;
+static gint ett_rpl_4003 = -1;
+static gint ett_rpl_4006 = -1;
+static gint ett_rpl_4007 = -1;
+static gint ett_rpl_4009 = -1;
+static gint ett_rpl_400a = -1;
+static gint ett_rpl_400b = -1;
+static gint ett_rpl_400c = -1;
+static gint ett_rpl_4011 = -1;
+static gint ett_rpl_4018 = -1;
+static gint ett_rpl_c005 = -1;
+static gint ett_rpl_c014 = -1;
+static gint ett_rpl_unkn = -1;
+
+static const value_string rpl_type_vals[] = {
+ { 1, "FIND Command" },
+ { 2, "FOUND Frame" },
+ { 4, "Search Vector" },
+ { 8, "Connect Info Vector" },
+ { 0x10, "Send File Request" },
+ { 0x20, "File Data Response" },
+ { 0x4003, "Correlator Vector" },
+ { 0x4006, "Loader Address Vector" },
+ { 0x4007, "Loader SAP Vector" },
+ { 0x4009, "Frame Size Sub-Vector" },
+ { 0x400a, "Connect Class Sub-Vector" },
+ { 0x400b, "Response Correlator" },
+ { 0x400c, "Set Address Vector" },
+ { 0x4011, "Sequence Header" },
+ { 0x4018, "File Data Vector" },
+ { 0xc005, "Loader Info Sub-Vector" },
+ { 0xc014, "Loader Header" },
+ { 0x0, NULL }
+};
+
+static dissector_handle_t data_handle;
+
+static void
+dissect_rpl_container(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 len, type, sublen, subtyp;
+ proto_item *ti;
+ proto_tree *rpl_container_tree;
+ guint16 offset;
+ gint ett_type;
+ gint length, reported_length;
+
+ len = tvb_get_ntohs(tvb, 0);
+ proto_tree_add_text(tree, tvb, 0, 2, "Length: %u", len);
+
+ type = tvb_get_ntohs(tvb, 2);
+ proto_tree_add_text(tree, tvb, 2, 2, "Type: %s",
+ val_to_str(type, rpl_type_vals, "Unknown Type"));
+ offset = 4;
+
+ switch (type) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 0x10:
+ case 0x20:
+ while (len >= offset+4) {
+ sublen = tvb_get_ntohs(tvb, offset);
+ subtyp = tvb_get_ntohs(tvb, offset+2);
+ ett_type = ett_rpl_unkn;
+ if(subtyp == 0x0004) ett_type = ett_rpl_0004;
+ if(subtyp == 0x0008) ett_type = ett_rpl_0008;
+ if(subtyp == 0x4003) ett_type = ett_rpl_4003;
+ if(subtyp == 0x4006) ett_type = ett_rpl_4006;
+ if(subtyp == 0x4007) ett_type = ett_rpl_4007;
+ if(subtyp == 0x4009) ett_type = ett_rpl_4009;
+ if(subtyp == 0x400a) ett_type = ett_rpl_400a;
+ if(subtyp == 0x400b) ett_type = ett_rpl_400b;
+ if(subtyp == 0x400c) ett_type = ett_rpl_400c;
+ if(subtyp == 0x4011) ett_type = ett_rpl_4011;
+ if(subtyp == 0x4018) ett_type = ett_rpl_4018;
+ if(subtyp == 0xc005) ett_type = ett_rpl_c005;
+ if(subtyp == 0xc014) ett_type = ett_rpl_c014;
+ ti = proto_tree_add_text(tree, tvb,
+ offset, sublen, val_to_str(subtyp,
+ rpl_type_vals, "Unknown Type"));
+ rpl_container_tree = proto_item_add_subtree(ti,
+ ett_type);
+ length = tvb_length_remaining(tvb, offset);
+ if (length > sublen)
+ length = sublen;
+ reported_length = tvb_reported_length_remaining(tvb, offset);
+ if (reported_length > sublen)
+ reported_length = sublen;
+ dissect_rpl_container(tvb_new_subset(tvb,
+ offset, length, reported_length),
+ pinfo, rpl_container_tree);
+
+ offset += sublen;
+ }
+ break;
+
+ case 0x4003:
+ proto_tree_add_item(tree, hf_rpl_corrval,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ break;
+
+ case 0x4006:
+ proto_tree_add_item(tree, hf_rpl_lmac,
+ tvb, offset, 6, FALSE);
+ offset += 6;
+ break;
+
+ case 0x4007:
+ proto_tree_add_item(tree, hf_rpl_sap,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ break;
+
+ case 0x4009:
+ proto_tree_add_item(tree, hf_rpl_maxframe,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+
+ case 0x400a:
+ proto_tree_add_item(tree, hf_rpl_connclass,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+
+ case 0x400b:
+ proto_tree_add_item(tree, hf_rpl_respval,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ break;
+
+ case 0x400c:
+ proto_tree_add_item(tree, hf_rpl_smac,
+ tvb, offset, 6, FALSE);
+ offset += 6;
+ break;
+
+ case 0x4011:
+ proto_tree_add_item(tree, hf_rpl_sequence,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ break;
+
+ case 0x4018:
+ proto_tree_add_item(tree, hf_rpl_data,
+ tvb, offset, len-4, FALSE);
+ offset += len - 4;
+ break;
+
+ case 0xc005:
+ proto_tree_add_item(tree, hf_rpl_config,
+ tvb, offset, 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(tree, hf_rpl_equipment,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_rpl_memsize,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_rpl_bsmversion,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_rpl_ec,
+ tvb, offset, 6, FALSE);
+ offset += 6;
+ proto_tree_add_item(tree, hf_rpl_adapterid,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(tree, hf_rpl_shortname,
+ tvb, offset, 10, FALSE);
+ offset += 10;
+ break;
+
+ case 0xc014:
+ proto_tree_add_item(tree, hf_rpl_laddress,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_rpl_xaddress,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_rpl_flags,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ break;
+
+ default:
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 4, -1, -1), pinfo,
+ tree);
+ break;
+ }
+ if (tvb_reported_length(tvb) > offset)
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+}
+
+static void
+dissect_rpl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 rpl_len, rpl_type;
+ proto_item *ti;
+ proto_tree *rpl_tree;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPL");
+
+ rpl_len = tvb_get_ntohs(tvb, 0);
+ rpl_type = tvb_get_ntohs(tvb, 2);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str(rpl_type, rpl_type_vals, "Unknown Type"));
+ }
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_rpl, tvb, 0,
+ rpl_len, FALSE);
+ rpl_tree = proto_item_add_subtree(ti, ett_rpl);
+ proto_tree_add_uint_hidden(rpl_tree, hf_rpl_type, tvb, 2, 2,
+ rpl_type);
+ next_tvb = tvb_new_subset(tvb, 0, -1, -1);
+ set_actual_length(next_tvb, rpl_len);
+ dissect_rpl_container(next_tvb, pinfo, rpl_tree);
+
+ if (tvb_reported_length(tvb) > rpl_len)
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, rpl_len, -1, -1), pinfo,
+ tree);
+ }
+}
+
+void
+proto_register_rpl(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rpl_type,
+ { "Type", "rpl.type",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "RPL Packet Type", HFILL }},
+ { &hf_rpl_corrval,
+ { "Correlator Value", "rpl.corrval",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "RPL Correlator Value", HFILL }},
+ { &hf_rpl_respval,
+ { "Response Code", "rpl.respval",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "RPL Response Code", HFILL }},
+ { &hf_rpl_maxframe,
+ { "Maximum Frame Size", "rpl.maxframe",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "RPL Maximum Frame Size", HFILL }},
+ { &hf_rpl_connclass,
+ { "Connection Class", "rpl.connclass",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "RPL Connection Class", HFILL }},
+ { &hf_rpl_lmac,
+ { "Loader MAC Address", "rpl.lmac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "RPL Loader MAC Address", HFILL }},
+ { &hf_rpl_smac,
+ { "Set MAC Address", "rpl.smac",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "RPL Set MAC Address", HFILL }},
+ { &hf_rpl_sap,
+ { "SAP", "rpl.sap",
+ FT_UINT8, BASE_HEX, VALS(sap_vals), 0x0,
+ "RPL SAP", HFILL }},
+ { &hf_rpl_equipment,
+ { "Equipment", "rpl.equipment",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "RPL Equipment - AX from INT 11h", HFILL }},
+ { &hf_rpl_memsize,
+ { "Memory Size", "rpl.memsize",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "RPL Memory Size - AX from INT 12h MINUS 32k"
+ " MINUS the Boot ROM Size", HFILL }},
+ { &hf_rpl_bsmversion,
+ { "BSM Version", "rpl.bsmversion",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "RPL Version of BSM.obj", HFILL }},
+ { &hf_rpl_adapterid,
+ { "Adapter ID", "rpl.adapterid",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "RPL Adapter ID", HFILL }},
+ { &hf_rpl_shortname,
+ { "Short Name", "rpl.shortname",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "RPL BSM Short Name", HFILL }},
+ { &hf_rpl_laddress,
+ { "Locate Address", "rpl.laddress",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "RPL Locate Address", HFILL }},
+ { &hf_rpl_xaddress,
+ { "XFER Address", "rpl.xaddress",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "RPL Transfer Control Address", HFILL }},
+ { &hf_rpl_sequence,
+ { "Sequence Number", "rpl.sequence",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "RPL Sequence Number", HFILL }},
+ { &hf_rpl_config,
+ { "Configuration", "rpl.config",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "RPL Configuration", HFILL }},
+ { &hf_rpl_flags,
+ { "Flags", "rpl.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "RPL Bit Significant Option Flags", HFILL }},
+ { &hf_rpl_data,
+ { "Data", "rpl.data",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "RPL Binary File Data", HFILL }},
+ { &hf_rpl_ec,
+ { "EC", "rpl.ec",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "RPL EC", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_rpl,
+ &ett_rpl_0004,
+ &ett_rpl_0008,
+ &ett_rpl_4003,
+ &ett_rpl_4006,
+ &ett_rpl_4007,
+ &ett_rpl_4009,
+ &ett_rpl_400a,
+ &ett_rpl_400b,
+ &ett_rpl_400c,
+ &ett_rpl_4011,
+ &ett_rpl_4018,
+ &ett_rpl_c005,
+ &ett_rpl_c014,
+ &ett_rpl_unkn
+ };
+
+ proto_rpl = proto_register_protocol("Remote Program Load",
+ "RPL", "rpl");
+ proto_register_field_array(proto_rpl, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("rpl", dissect_rpl, proto_rpl);
+}
+
+void
+proto_reg_handoff_rpl(void)
+{
+ dissector_handle_t rpl_handle;
+
+ data_handle = find_dissector("data");
+ rpl_handle = find_dissector("rpl");
+ dissector_add("llc.dsap", SAP_RPL, rpl_handle);
+}
diff --git a/epan/dissectors/packet-rquota.c b/epan/dissectors/packet-rquota.c
new file mode 100644
index 0000000000..98f3fc7d62
--- /dev/null
+++ b/epan/dissectors/packet-rquota.c
@@ -0,0 +1,253 @@
+/* packet-rquota.c
+ * Routines for rquota dissection
+ * Copyright 2001, Mike Frisch <frisch@hummingbird.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-ypxfr.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-rquota.h"
+
+static int proto_rquota = -1;
+static int hf_rquota_procedure_v1 = -1;
+static int hf_rquota_pathp = -1;
+static int hf_rquota_uid = -1;
+static int hf_rquota_status = -1;
+static int hf_rquota_rquota = -1;
+static int hf_rquota_bsize = -1;
+static int hf_rquota_active = -1;
+static int hf_rquota_bhardlimit = -1;
+static int hf_rquota_bsoftlimit = -1;
+static int hf_rquota_curblocks = -1;
+static int hf_rquota_fhardlimit = -1;
+static int hf_rquota_fsoftlimit = -1;
+static int hf_rquota_curfiles = -1;
+static int hf_rquota_btimeleft = -1;
+static int hf_rquota_ftimeleft = -1;
+
+static gint ett_rquota = -1;
+static gint ett_rquota_rquota = -1;
+
+static const value_string names_rquota_status[] =
+{
+#define Q_OK 1
+ { Q_OK, "OK" },
+#define Q_NOQUOTA 2
+ { Q_NOQUOTA, "NOQUOTA" },
+#define Q_EPERM 3
+ { Q_EPERM, "EPERM" },
+ { 0, NULL }
+};
+
+
+static int
+dissect_rquota(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+
+ proto_item *lock_item = NULL;
+ proto_tree *lock_tree = NULL;
+
+ lock_item = proto_tree_add_item(tree, hf_rquota_rquota, tvb,
+ offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_rquota_rquota);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rquota_bsize, offset);
+
+ offset = dissect_rpc_bool(tvb, lock_tree,
+ hf_rquota_active, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rquota_bhardlimit, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rquota_bsoftlimit, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rquota_curblocks, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rquota_fhardlimit, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rquota_fsoftlimit, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rquota_curfiles, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rquota_btimeleft, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_rquota_ftimeleft, offset);
+
+ return offset;
+}
+
+static int
+dissect_getquota_result(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ gint32 status;
+
+ status = tvb_get_ntohl(tvb, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_rquota_status, offset);
+
+ if (status==Q_OK) {
+ offset = dissect_rquota(tvb, offset, tree);
+ }
+
+ return offset;
+}
+
+static int
+dissect_getquota_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree,
+ hf_rquota_pathp, offset, NULL);
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_rquota_uid, offset);
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff rquota1_proc[] = {
+ { RQUOTAPROC_NULL, "NULL",
+ NULL, NULL },
+ { RQUOTAPROC_GETQUOTA, "GETQUOTA",
+ dissect_getquota_call, dissect_getquota_result },
+ { RQUOTAPROC_GETACTIVEQUOTA, "GETACTIVEQUOTA",
+ dissect_getquota_call, dissect_getquota_result },
+ { 0, NULL,
+ NULL, NULL }
+};
+static const value_string rquota1_proc_vals[] = {
+ { RQUOTAPROC_NULL, "NULL" },
+ { RQUOTAPROC_GETQUOTA, "GETQUOTA" },
+ { RQUOTAPROC_GETACTIVEQUOTA, "GETACTIVEQUOTA" },
+ { 0, NULL }
+};
+/* end of RQUOTA version 1 */
+
+void
+proto_register_rquota(void)
+{
+ static struct true_false_string tfs_active = { "Quota is ACTIVE", "Quota is NOT active" };
+
+ static hf_register_info hf[] = {
+ { &hf_rquota_procedure_v1, {
+ "V1 Procedure", "rquota.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(rquota1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_rquota_uid, {
+ "uid", "rquota.uid", FT_UINT32, BASE_DEC,
+ NULL, 0, "User ID", HFILL }},
+
+ { &hf_rquota_pathp, {
+ "pathp", "rquota.pathp", FT_STRING, BASE_DEC,
+ NULL, 0, "Filesystem of interest", HFILL }},
+
+ { &hf_rquota_status, {
+ "status", "rquota.status", FT_UINT32, BASE_DEC,
+ VALS(names_rquota_status), 0, "Status code", HFILL }},
+
+ { &hf_rquota_rquota, {
+ "rquota", "rquota.rquota", FT_NONE, BASE_NONE,
+ NULL, 0, "Rquota structure", HFILL }},
+
+ { &hf_rquota_bsize, {
+ "bsize", "rquota.bsize", FT_UINT32, BASE_DEC,
+ NULL, 0, "Block size", HFILL }},
+
+ { &hf_rquota_active, {
+ "active", "rquota.active", FT_BOOLEAN, BASE_NONE,
+ &tfs_active, 0, "Indicates whether quota is active", HFILL }},
+
+ { &hf_rquota_bhardlimit, {
+ "bhardlimit", "rquota.bhardlimit", FT_UINT32, BASE_DEC,
+ NULL, 0, "Hard limit for blocks", HFILL }},
+
+ { &hf_rquota_bsoftlimit, {
+ "bsoftlimit", "rquota.bsoftlimit", FT_UINT32, BASE_DEC,
+ NULL, 0, "Soft limit for blocks", HFILL }},
+
+ { &hf_rquota_curblocks, {
+ "curblocks", "rquota.curblocks", FT_UINT32, BASE_DEC,
+ NULL, 0, "Current block count", HFILL }},
+
+ { &hf_rquota_fhardlimit, {
+ "fhardlimit", "rquota.fhardlimit", FT_UINT32, BASE_DEC,
+ NULL, 0, "Hard limit on allocated files", HFILL }},
+
+ { &hf_rquota_fsoftlimit, {
+ "fsoftlimit", "rquota.fsoftlimit", FT_UINT32, BASE_DEC,
+ NULL, 0, "Soft limit of allocated files", HFILL }},
+
+ { &hf_rquota_curfiles, {
+ "curfiles", "rquota.curfiles", FT_UINT32, BASE_DEC,
+ NULL, 0, "Current # allocated files", HFILL }},
+
+ { &hf_rquota_btimeleft, {
+ "btimeleft", "rquota.btimeleft", FT_UINT32, BASE_DEC,
+ NULL, 0, "Time left for excessive disk use", HFILL }},
+
+ { &hf_rquota_ftimeleft, {
+ "ftimeleft", "rquota.ftimeleft", FT_UINT32, BASE_DEC,
+ NULL, 0, "Time left for excessive files", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_rquota,
+ &ett_rquota_rquota,
+ };
+
+ proto_rquota = proto_register_protocol("Remote Quota",
+ "RQUOTA", "rquota");
+
+ proto_register_field_array(proto_rquota, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_rquota(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_rquota, RQUOTA_PROGRAM, ett_rquota);
+ /* Register the procedure tables */
+ rpc_init_proc_table(RQUOTA_PROGRAM, 1, rquota1_proc, hf_rquota_procedure_v1);
+}
+
+
+
diff --git a/epan/dissectors/packet-rquota.h b/epan/dissectors/packet-rquota.h
new file mode 100644
index 0000000000..3bfdaced7f
--- /dev/null
+++ b/epan/dissectors/packet-rquota.h
@@ -0,0 +1,34 @@
+/* packet-rquota.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_RQUOTA_H
+#define PACKET_RQUOTA_H
+
+#define RQUOTAPROC_NULL 0
+#define RQUOTAPROC_GETQUOTA 1
+#define RQUOTAPROC_GETACTIVEQUOTA 2
+
+#define RQUOTA_PROGRAM 100011
+
+#endif
diff --git a/epan/dissectors/packet-rsh.c b/epan/dissectors/packet-rsh.c
new file mode 100644
index 0000000000..856588a085
--- /dev/null
+++ b/epan/dissectors/packet-rsh.c
@@ -0,0 +1,133 @@
+/* packet-rsh.c
+ * Routines for rsh packet disassembly
+ *
+ * Robert Tsai <rtsai@netapp.com>
+ * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+static int proto_rsh = -1;
+static int hf_rsh_response = -1;
+static int hf_rsh_request = -1;
+static gint ett_rsh = -1;
+
+#define TCP_PORT_RSH 514
+
+static void
+dissect_rsh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *rsh_tree;
+ proto_item *ti;
+ gint offset = 0;
+ gint next_offset;
+ int linelen;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSH");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /* Put the first line from the buffer into the summary. */
+ tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ linelen = next_offset - offset; /* include the line terminator */
+
+ /*
+ * Make sure the line terminator isn't past the end of
+ * the captured data in the packet, so we don't throw
+ * an exception in the "tvb_get_ptr()" call.
+ */
+ if (linelen > (int) tvb_length(tvb))
+ linelen = tvb_length(tvb);
+ col_add_str(pinfo->cinfo, COL_INFO,
+ tvb_format_text(tvb, offset, linelen));
+ }
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_rsh, tvb, offset, -1,
+ FALSE);
+ rsh_tree = proto_item_add_subtree(ti, ett_rsh);
+
+ /*
+ * Process the packet data, a line at a time.
+ */
+ while (tvb_offset_exists(tvb, offset)) {
+ /*
+ * Find the end of the line.
+ */
+ tvb_find_line_end(tvb, offset, -1, &next_offset,
+ FALSE);
+
+ /*
+ * Put this line.
+ */
+ proto_tree_add_text(rsh_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ offset = next_offset;
+ }
+
+ if (pinfo->match_port == pinfo->destport)
+ proto_tree_add_boolean_hidden(rsh_tree,
+ hf_rsh_request, tvb, 0, 0, 1);
+ else
+ proto_tree_add_boolean_hidden(rsh_tree,
+ hf_rsh_response, tvb, 0, 0, 1);
+ }
+}
+
+void
+proto_register_rsh(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_rsh_response,
+ { "Response", "rsh.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if rsh response", HFILL }},
+ { &hf_rsh_request,
+ { "Request", "rsh.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if rsh request", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_rsh,
+ };
+
+ proto_rsh = proto_register_protocol("Remote Shell", "RSH", "rsh");
+ proto_register_field_array(proto_rsh, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_rsh(void)
+{
+ dissector_handle_t rsh_handle;
+
+ rsh_handle = create_dissector_handle(dissect_rsh, proto_rsh);
+ dissector_add("tcp.port", TCP_PORT_RSH, rsh_handle);
+}
diff --git a/epan/dissectors/packet-rstat.c b/epan/dissectors/packet-rstat.c
new file mode 100644
index 0000000000..8401651576
--- /dev/null
+++ b/epan/dissectors/packet-rstat.c
@@ -0,0 +1,152 @@
+/* packet-rstat.c
+ * Stubs for Sun's remote statistics RPC service
+ *
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+
+static int proto_rstat = -1;
+static int hf_rstat_procedure_v1 = -1;
+static int hf_rstat_procedure_v2 = -1;
+static int hf_rstat_procedure_v3 = -1;
+static int hf_rstat_procedure_v4 = -1;
+
+static gint ett_rstat = -1;
+
+#define RSTAT_PROGRAM 100001
+
+#define RSTATPROC_NULL 0
+#define RSTATPROC_STATS 1
+#define RSTATPROC_HAVEDISK 2
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff rstat1_proc[] = {
+ { RSTATPROC_NULL, "NULL",
+ NULL, NULL },
+ { RSTATPROC_STATS, "STATS",
+ NULL, NULL },
+ { RSTATPROC_HAVEDISK, "HAVEDISK",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string rstat1_proc_vals[] = {
+ { RSTATPROC_NULL, "NULL" },
+ { RSTATPROC_STATS, "STATS" },
+ { RSTATPROC_HAVEDISK, "HAVEDISK" },
+ { 0, NULL }
+};
+
+static const vsff rstat2_proc[] = {
+ { RSTATPROC_NULL, "NULL",
+ NULL, NULL },
+ { RSTATPROC_STATS, "STATS",
+ NULL, NULL },
+ { RSTATPROC_HAVEDISK, "HAVEDISK",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string rstat2_proc_vals[] = {
+ { RSTATPROC_NULL, "NULL" },
+ { RSTATPROC_STATS, "STATS" },
+ { RSTATPROC_HAVEDISK, "HAVEDISK" },
+ { 0, NULL }
+};
+
+static const vsff rstat3_proc[] = {
+ { RSTATPROC_NULL, "NULL",
+ NULL, NULL },
+ { RSTATPROC_STATS, "STATS",
+ NULL, NULL },
+ { RSTATPROC_HAVEDISK, "HAVEDISK",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string rstat3_proc_vals[] = {
+ { RSTATPROC_NULL, "NULL" },
+ { RSTATPROC_STATS, "STATS" },
+ { RSTATPROC_HAVEDISK, "HAVEDISK" },
+ { 0, NULL }
+};
+
+static const vsff rstat4_proc[] = {
+ { RSTATPROC_NULL, "NULL",
+ NULL, NULL },
+ { RSTATPROC_STATS, "STATS",
+ NULL, NULL },
+ { RSTATPROC_HAVEDISK, "HAVEDISK",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string rstat4_proc_vals[] = {
+ { RSTATPROC_NULL, "NULL" },
+ { RSTATPROC_STATS, "STATS" },
+ { RSTATPROC_HAVEDISK, "HAVEDISK" },
+ { 0, NULL }
+};
+
+void
+proto_register_rstat(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rstat_procedure_v1, {
+ "V1 Procedure", "rstat.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(rstat1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_rstat_procedure_v2, {
+ "V2 Procedure", "rstat.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(rstat2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_rstat_procedure_v3, {
+ "V3 Procedure", "rstat.procedure_v3", FT_UINT32, BASE_DEC,
+ VALS(rstat3_proc_vals), 0, "V3 Procedure", HFILL }},
+ { &hf_rstat_procedure_v4, {
+ "V4 Procedure", "rstat.procedure_v4", FT_UINT32, BASE_DEC,
+ VALS(rstat4_proc_vals), 0, "V4 Procedure", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_rstat,
+ };
+
+ proto_rstat = proto_register_protocol("RSTAT", "RSTAT", "rstat");
+ proto_register_field_array(proto_rstat, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_rstat(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_rstat, RSTAT_PROGRAM, ett_rstat);
+ /* Register the procedure tables */
+ rpc_init_proc_table(RSTAT_PROGRAM, 1, rstat1_proc, hf_rstat_procedure_v1);
+ rpc_init_proc_table(RSTAT_PROGRAM, 2, rstat2_proc, hf_rstat_procedure_v2);
+ rpc_init_proc_table(RSTAT_PROGRAM, 3, rstat3_proc, hf_rstat_procedure_v3);
+ rpc_init_proc_table(RSTAT_PROGRAM, 4, rstat4_proc, hf_rstat_procedure_v4);
+}
diff --git a/epan/dissectors/packet-rsvp.c b/epan/dissectors/packet-rsvp.c
new file mode 100644
index 0000000000..dec783e763
--- /dev/null
+++ b/epan/dissectors/packet-rsvp.c
@@ -0,0 +1,4609 @@
+/* packet-rsvp.c
+ * Routines for RSVP packet disassembly
+ *
+ * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * NOTES
+ *
+ * This module defines routines to disassemble RSVP packets, as defined in
+ * RFC 2205. All objects from RFC2205 are supported, in IPv4 and IPv6 mode.
+ * In addition, the Integrated Services traffic specification objects
+ * defined in RFC2210 are also supported.
+ *
+ * IPv6 support is not completely tested
+ *
+ * Mar 3, 2000: Added support for MPLS/TE objects, as defined in
+ * <draft-ietf-mpls-rsvp-lsp-tunnel-04.txt>
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/tvbuff.h>
+#include <epan/packet.h>
+#include <prefs.h>
+#include "in_cksum.h"
+#include "etypes.h"
+#include "ipproto.h"
+
+#include "packet-rsvp.h"
+#include "packet-ip.h"
+#include "packet-frame.h"
+#include "packet-diffserv-mpls-common.h"
+
+static int proto_rsvp = -1;
+
+/*
+ * The list of tree types
+ */
+enum {
+ TT_RSVP,
+ TT_HDR,
+ TT_SESSION,
+ TT_HOP,
+ TT_HOP_SUBOBJ,
+ TT_TIME_VALUES,
+ TT_ERROR,
+ TT_ERROR_SUBOBJ,
+ TT_SCOPE,
+ TT_STYLE,
+ TT_CONFIRM,
+ TT_SENDER_TEMPLATE,
+ TT_FILTER_SPEC,
+ TT_TSPEC,
+ TT_TSPEC_SUBTREE,
+ TT_FLOWSPEC,
+ TT_FLOWSPEC_SUBTREE,
+ TT_ADSPEC,
+ TT_ADSPEC_SUBTREE,
+ TT_INTEGRITY,
+ TT_INTEGRITY_FLAGS,
+ TT_DCLASS,
+ TT_LSP_TUNNEL_IF_ID,
+ TT_POLICY,
+ TT_MESSAGE_ID,
+ TT_MESSAGE_ID_ACK,
+ TT_MESSAGE_ID_LIST,
+ TT_LABEL,
+ TT_LABEL_REQUEST,
+ TT_SESSION_ATTRIBUTE,
+ TT_SESSION_ATTRIBUTE_FLAGS,
+ TT_HELLO_OBJ,
+ TT_EXPLICIT_ROUTE,
+ TT_EXPLICIT_ROUTE_SUBOBJ,
+ TT_RECORD_ROUTE,
+ TT_RECORD_ROUTE_SUBOBJ,
+ TT_RECORD_ROUTE_SUBOBJ_FLAGS,
+ TT_ADMIN_STATUS,
+ TT_ADMIN_STATUS_FLAGS,
+ TT_GEN_UNI,
+ TT_GEN_UNI_SUBOBJ,
+ TT_BUNDLE_COMPMSG,
+ TT_RESTART_CAP,
+ TT_PROTECTION_INFO,
+ TT_FAST_REROUTE,
+ TT_FAST_REROUTE_FLAGS,
+ TT_DETOUR,
+ TT_DIFFSERV,
+ TT_DIFFSERV_MAP,
+ TT_DIFFSERV_MAP_PHBID,
+ TT_UNKNOWN_CLASS,
+
+ TT_MAX
+};
+static gint ett_treelist[TT_MAX];
+static gint *ett_tree[TT_MAX];
+#define TREE(X) ett_treelist[(X)]
+
+/* Should we dissect bundle messages? */
+static gboolean rsvp_bundle_dissect = TRUE;
+
+/*
+ * RSVP message types.
+ * See
+ *
+ * http://www.iana.org/assignments/rsvp-parameters
+ */
+typedef enum {
+ RSVP_MSG_PATH=1, /* RFC 2205 */
+ RSVP_MSG_RESV, /* RFC 2205 */
+ RSVP_MSG_PERR, /* RFC 2205 */
+ RSVP_MSG_RERR, /* RFC 2205 */
+ RSVP_MSG_PTEAR, /* RFC 2205 */
+ RSVP_MSG_RTEAR, /* RFC 2205 */
+ RSVP_MSG_CONFIRM, /* XXX - DREQ, RFC 2745? */
+ /* 9 is DREP, RFC 2745 */
+ RSVP_MSG_RTEAR_CONFIRM=10, /* from Fred Baker at Cisco */
+ /* 11 is unassigned */
+ RSVP_MSG_BUNDLE = 12, /* RFC 2961 */
+ RSVP_MSG_ACK, /* RFC 2961 */
+ /* 14 is reserved */
+ RSVP_MSG_SREFRESH = 15, /* RFC 2961 */
+ /* 16, 17, 18, 19 not listed */
+ RSVP_MSG_HELLO = 20 /* RFC 3209 */
+ /* 25 is Integrity Challenge
+ RFC 2747, RFC 3097 */
+ /* 26 is Integrity Response
+ RFC 2747, RFC 3097 */
+ /* 66 is DSBM_willing [SBM] */
+ /* 67 is I_AM_DSBM [SBM] */
+ /* [SBM] is Subnet Bandwidth
+ Manager ID from July 1997 */
+} rsvp_message_types;
+
+static value_string message_type_vals[] = {
+ {RSVP_MSG_PATH, "PATH Message. "},
+ {RSVP_MSG_RESV, "RESV Message. "},
+ {RSVP_MSG_PERR, "PATH ERROR Message. "},
+ {RSVP_MSG_RERR, "RESV ERROR Message. "},
+ {RSVP_MSG_PTEAR, "PATH TEAR Message. "},
+ {RSVP_MSG_RTEAR, "RESV TEAR Message. "},
+ {RSVP_MSG_CONFIRM, "CONFIRM Message. "},
+ {RSVP_MSG_RTEAR_CONFIRM, "RESV TEAR CONFIRM Message. "},
+ {RSVP_MSG_BUNDLE, "BUNDLE Message. "},
+ {RSVP_MSG_ACK, "ACK Message. "},
+ {RSVP_MSG_SREFRESH, "SREFRESH Message. "},
+ {RSVP_MSG_HELLO, "HELLO Message. "},
+ {0, NULL}
+};
+
+/*
+ * RSVP classes
+ */
+#define MAX_RSVP_CLASS 15
+
+enum rsvp_classes {
+ RSVP_CLASS_NULL=0,
+ RSVP_CLASS_SESSION,
+
+ RSVP_CLASS_HOP=3,
+ RSVP_CLASS_INTEGRITY,
+ RSVP_CLASS_TIME_VALUES,
+ RSVP_CLASS_ERROR,
+ RSVP_CLASS_SCOPE,
+ RSVP_CLASS_STYLE,
+ RSVP_CLASS_FLOWSPEC,
+ RSVP_CLASS_FILTER_SPEC,
+ RSVP_CLASS_SENDER_TEMPLATE,
+ RSVP_CLASS_SENDER_TSPEC,
+ RSVP_CLASS_ADSPEC,
+ RSVP_CLASS_POLICY,
+ RSVP_CLASS_CONFIRM,
+ RSVP_CLASS_LABEL,
+
+ RSVP_CLASS_LABEL_REQUEST=19,
+ RSVP_CLASS_EXPLICIT_ROUTE,
+ RSVP_CLASS_RECORD_ROUTE,
+
+ RSVP_CLASS_HELLO,
+
+ RSVP_CLASS_MESSAGE_ID,
+ RSVP_CLASS_MESSAGE_ID_ACK,
+ RSVP_CLASS_MESSAGE_ID_LIST,
+
+ RSVP_CLASS_RECOVERY_LABEL = 34,
+ RSVP_CLASS_UPSTREAM_LABEL,
+ RSVP_CLASS_LABEL_SET,
+ RSVP_CLASS_PROTECTION,
+
+ RSVP_CLASS_DETOUR = 63,
+
+ RSVP_CLASS_DIFFSERV = 65,
+
+ RSVP_CLASS_SUGGESTED_LABEL = 129,
+ RSVP_CLASS_ACCEPTABLE_LABEL_SET,
+ RSVP_CLASS_RESTART_CAP,
+
+ RSVP_CLASS_NOTIFY_REQUEST = 195,
+ RSVP_CLASS_ADMIN_STATUS,
+
+ RSVP_CLASS_FAST_REROUTE = 205,
+ RSVP_CLASS_SESSION_ATTRIBUTE = 207,
+ RSVP_CLASS_DCLASS = 225,
+ RSVP_CLASS_LSP_TUNNEL_IF_ID = 227,
+ RSVP_CLASS_GENERALIZED_UNI = 229
+
+};
+
+static value_string rsvp_class_vals[] = {
+ {RSVP_CLASS_NULL, "NULL object"},
+ {RSVP_CLASS_SESSION, "SESSION object"},
+ {RSVP_CLASS_HOP, "HOP object"},
+ {RSVP_CLASS_INTEGRITY, "INTEGRITY object"},
+ {RSVP_CLASS_TIME_VALUES, "TIME VALUES object"},
+ {RSVP_CLASS_ERROR, "ERROR object"},
+ {RSVP_CLASS_SCOPE, "SCOPE object"},
+ {RSVP_CLASS_STYLE, "STYLE object"},
+ {RSVP_CLASS_FLOWSPEC, "FLOWSPEC object"},
+ {RSVP_CLASS_FILTER_SPEC, "FILTER SPEC object"},
+ {RSVP_CLASS_SENDER_TEMPLATE, "SENDER TEMPLATE object"},
+ {RSVP_CLASS_SENDER_TSPEC, "SENDER TSPEC object"},
+ {RSVP_CLASS_ADSPEC, "ADSPEC object"},
+ {RSVP_CLASS_POLICY, "POLICY object"},
+ {RSVP_CLASS_CONFIRM, "CONFIRM object"},
+ {RSVP_CLASS_LABEL, "LABEL object"},
+ {RSVP_CLASS_LABEL_REQUEST, "LABEL REQUEST object"},
+ {RSVP_CLASS_EXPLICIT_ROUTE, "EXPLICIT ROUTE object"},
+ {RSVP_CLASS_RECORD_ROUTE, "RECORD ROUTE object"},
+ {RSVP_CLASS_SESSION_ATTRIBUTE, "SESSION ATTRIBUTE object"},
+ {RSVP_CLASS_MESSAGE_ID, "MESSAGE-ID object"},
+ {RSVP_CLASS_MESSAGE_ID_ACK, "MESSAGE-ID ACK/NACK object"},
+ {RSVP_CLASS_MESSAGE_ID_LIST, "MESSAGE-ID LIST object"},
+ {RSVP_CLASS_HELLO, "HELLO object"},
+ {RSVP_CLASS_RECOVERY_LABEL, "RECOVERY-LABEL object"},
+ {RSVP_CLASS_UPSTREAM_LABEL, "UPSTREAM-LABEL object"},
+ {RSVP_CLASS_LABEL_SET, "LABEL-SET object"},
+ {RSVP_CLASS_PROTECTION, "PROTECTION object"},
+ {RSVP_CLASS_DIFFSERV, "DIFFSERV object"},
+ {RSVP_CLASS_SUGGESTED_LABEL, "SUGGESTED-LABEL object"},
+ {RSVP_CLASS_ACCEPTABLE_LABEL_SET, "ACCEPTABLE-LABEL-SET object"},
+ {RSVP_CLASS_RESTART_CAP, "RESTART-CAPABILITY object"},
+ {RSVP_CLASS_DCLASS, "DCLASS object"},
+ {RSVP_CLASS_LSP_TUNNEL_IF_ID, "LSP-TUNNEL INTERFACE-ID object"},
+ {RSVP_CLASS_NOTIFY_REQUEST, "NOTIFY-REQUEST object"},
+ {RSVP_CLASS_ADMIN_STATUS, "ADMIN-STATUS object"},
+ {RSVP_CLASS_GENERALIZED_UNI, "GENERALIZED-UNI object"},
+ {RSVP_CLASS_DETOUR, "DETOUR object"},
+ {RSVP_CLASS_FAST_REROUTE, "FAST-REROUTE object"},
+ {0, NULL}
+};
+
+/*
+ * RSVP error values
+ */
+enum rsvp_error_types {
+ RSVP_ERROR_CONFIRM = 0,
+ RSVP_ERROR_ADMISSION,
+ RSVP_ERROR_POLICY,
+ RSVP_ERROR_NO_PATH,
+ RSVP_ERROR_NO_SENDER,
+ RSVP_ERROR_CONFLICT_RESV_STYLE,
+ RSVP_ERROR_UNKNOWN_RESV_STYLE,
+ RSVP_ERROR_CONFLICT_DEST_PORTS,
+ RSVP_ERROR_CONFLICT_SRC_PORTS,
+ RSVP_ERROR_PREEMPTED=12,
+ RSVP_ERROR_UNKNOWN_CLASS,
+ RSVP_ERROR_UNKNOWN_C_TYPE,
+ RSVP_ERROR_TRAFFIC = 21,
+ RSVP_ERROR_TRAFFIC_SYSTEM,
+ RSVP_ERROR_SYSTEM,
+ RSVP_ERROR_ROUTING,
+ RSVP_ERROR_NOTIFY,
+ RSVP_ERROR_DIFFSERV = 27
+};
+
+enum {
+ RSVP_AC_ERROR_DELAY_BOUND_ERROR = 1,
+ RSVP_AC_ERROR_BANDWITH_UNAVAILABLE,
+ RSVP_AC_ERROR_LARGE_MTU
+};
+
+enum {
+ RSVP_TRAFFIC_CONTROL_ERROR_SERVICE_CONFLICT = 1,
+ RSVP_TRAFFIC_CONTROL_ERROR_SERVIEC_UNSUPPORTED,
+ RSVP_TRAFFIC_CONTROL_ERROR_BAD_FLOWSPEC,
+ RSVP_TRAFFIC_CONTROL_ERROR_BAD_TSPEC,
+ RSVP_TRAFFIC_CONTROL_ERROR_BAD_ADSPEC
+};
+
+enum {
+ RSVP_ROUTING_ERROR_BAD_ERO = 1,
+ RSVP_ROUTING_ERROR_BAD_STRICT,
+ RSVP_ROUTING_ERROR_BAD_LOOSE,
+ RSVP_ROUTING_ERROR_BAD_INITIAL_SUBOBJ,
+ RSVP_ROUTING_ERROR_NO_ROUTE,
+ RSVP_ROUTING_ERROR_UNACCEPTABLE_LABEL,
+ RSVP_ROUTING_ERROR_RRO_LOOP,
+ RSVP_ROUTING_ERROR_NON_RSVP_CAPABLE_ROUTER,
+ RSVP_ROUTING_ERROR_LABEL_ALLOC_FAIL,
+ RSVP_ROUTING_ERROR_UNSUPPORTED_L3PID
+};
+
+enum {
+ RSVP_NOTIFY_ERROR_RRO_TOO_LARGE = 1,
+ RSVP_NOTIFY_ERROR_RRO_NOTIFICATION,
+ RSVP_NOTIFY_ERROR_RRO_TUNNEL_LOCAL_REPAIRED
+};
+
+enum {
+ RSVP_DIFFSERV_ERROR_UNEXPECTED_DIFFSERVOBJ = 1,
+ RSVP_DIFFSERV_ERROR_UNSUPPORTED_PHB,
+ RSVP_DIFFSERV_ERROR_INVALID_EXP_PHB_MAPPING,
+ RSVP_DIFFSERV_ERROR_UNSUPPORTED_PSC,
+ RSVP_DIFFSERV_ERROR_PERLSP_CONTEXT_ALLOC_FAIL
+};
+
+static value_string rsvp_error_codes[] = {
+ {RSVP_ERROR_CONFIRM, "Confirmation"},
+ {RSVP_ERROR_ADMISSION, "Admission Control Failure "},
+ {RSVP_ERROR_POLICY, "Policy Control Failure"},
+ {RSVP_ERROR_NO_PATH, "No PATH information for this RESV message"},
+ {RSVP_ERROR_NO_SENDER, "No sender information for this RESV message"},
+ {RSVP_ERROR_CONFLICT_RESV_STYLE, "Conflicting reservation styles"},
+ {RSVP_ERROR_UNKNOWN_RESV_STYLE, "Unknown reservation style"},
+ {RSVP_ERROR_CONFLICT_DEST_PORTS, "Conflicting destination ports"},
+ {RSVP_ERROR_CONFLICT_SRC_PORTS, "Conflicting source ports"},
+ {RSVP_ERROR_PREEMPTED, "Service preempted"},
+ {RSVP_ERROR_UNKNOWN_CLASS, "Unknown object class"},
+ {RSVP_ERROR_UNKNOWN_C_TYPE, "Unknown object C-type"},
+ {RSVP_ERROR_TRAFFIC, "Traffic Control Error"},
+ {RSVP_ERROR_TRAFFIC_SYSTEM, "Traffic Control System Error"},
+ {RSVP_ERROR_SYSTEM, "RSVP System Error"},
+ {RSVP_ERROR_ROUTING, "Routing Error"},
+ {RSVP_ERROR_NOTIFY, "RSVP Notify Error"},
+ {RSVP_ERROR_DIFFSERV, "RSVP Diff-Serv Error"},
+ {0, NULL}
+};
+
+static value_string rsvp_admission_control_error_vals[] = {
+ {RSVP_AC_ERROR_DELAY_BOUND_ERROR, "Delay bound cannot be met"},
+ {RSVP_AC_ERROR_BANDWITH_UNAVAILABLE, "Requested bandwidth unavailable"},
+ {RSVP_AC_ERROR_LARGE_MTU, "MTU in flowspec larger than interface MTU"},
+ {0, NULL}
+};
+
+static value_string rsvp_traffic_control_error_vals[] = {
+ {RSVP_TRAFFIC_CONTROL_ERROR_SERVICE_CONFLICT, "Service conflict"},
+ {RSVP_TRAFFIC_CONTROL_ERROR_SERVIEC_UNSUPPORTED, "Service unsupported"},
+ {RSVP_TRAFFIC_CONTROL_ERROR_BAD_FLOWSPEC, "Bad Flowspec value"},
+ {RSVP_TRAFFIC_CONTROL_ERROR_BAD_TSPEC, "Bad Tspec value"},
+ {RSVP_TRAFFIC_CONTROL_ERROR_BAD_ADSPEC, "Bad Adspec value"},
+ {0, NULL}
+};
+
+static value_string rsvp_routing_error_vals[] = {
+ {RSVP_ROUTING_ERROR_BAD_ERO, "Bad EXPLICIT_ROUTE object"},
+ {RSVP_ROUTING_ERROR_BAD_STRICT, "Bad strict node"},
+ {RSVP_ROUTING_ERROR_BAD_LOOSE, "Bad loose node"},
+ {RSVP_ROUTING_ERROR_BAD_INITIAL_SUBOBJ, "Bad initial subobject"},
+ {RSVP_ROUTING_ERROR_NO_ROUTE, "No route available toward destination"},
+ {RSVP_ROUTING_ERROR_UNACCEPTABLE_LABEL, "Unacceptable label value"},
+ {RSVP_ROUTING_ERROR_RRO_LOOP, "RRO indicated routing loops"},
+ {RSVP_ROUTING_ERROR_NON_RSVP_CAPABLE_ROUTER, "non-RSVP-capable router stands in the path"},
+ {RSVP_ROUTING_ERROR_LABEL_ALLOC_FAIL, "MPLS label allocation failure"},
+ {RSVP_ROUTING_ERROR_UNSUPPORTED_L3PID, "Unsupported L3PID"},
+ {0, NULL}
+};
+
+static value_string rsvp_notify_error_vals[] = {
+ {RSVP_NOTIFY_ERROR_RRO_TOO_LARGE, "RRO too large for MTU"},
+ {RSVP_NOTIFY_ERROR_RRO_NOTIFICATION, "RRO Notification"},
+ {RSVP_NOTIFY_ERROR_RRO_TUNNEL_LOCAL_REPAIRED, "Tunnel locally repaired"},
+ {0, NULL}
+};
+
+static value_string rsvp_diffserv_error_vals[] = {
+ {RSVP_DIFFSERV_ERROR_UNEXPECTED_DIFFSERVOBJ, "Unexpected DIFFSERV object"},
+ {RSVP_DIFFSERV_ERROR_UNSUPPORTED_PHB, "Unsupported PHB"},
+ {RSVP_DIFFSERV_ERROR_INVALID_EXP_PHB_MAPPING, "Invalid `EXP<->PHB mapping'"},
+ {RSVP_DIFFSERV_ERROR_UNSUPPORTED_PSC, "Unsupported PSC"},
+ {RSVP_DIFFSERV_ERROR_PERLSP_CONTEXT_ALLOC_FAIL, "Per-LSP context allocation failure"},
+ {0, NULL}
+};
+
+/*
+ * Defines the reservation style plus style-specific information that
+ * is not a FLOWSPEC or FILTER_SPEC object, in a RESV message.
+ */
+#define RSVP_DISTINCT (1 << 3)
+#define RSVP_SHARED (2 << 3)
+#define RSVP_SHARING_MASK (RSVP_DISTINCT | RSVP_SHARED)
+
+#define RSVP_SCOPE_WILD 1
+#define RSVP_SCOPE_EXPLICIT 2
+#define RSVP_SCOPE_MASK 0x07
+
+#define RSVP_WF (RSVP_SHARED | RSVP_SCOPE_WILD)
+#define RSVP_FF (RSVP_DISTINCT | RSVP_SCOPE_EXPLICIT)
+#define RSVP_SE (RSVP_SHARED | RSVP_SCOPE_EXPLICIT)
+
+static value_string style_vals[] = {
+ { RSVP_WF, "Wildcard Filter" },
+ { RSVP_FF, "Fixed Filter" },
+ { RSVP_SE, "Shared-Explicit" },
+ { 0, NULL }
+};
+
+enum {
+ RSVP_SESSION_TYPE_IPV4 = 1,
+ RSVP_SESSION_TYPE_IPV6,
+
+ RSVP_SESSION_TYPE_IPV4_LSP = 7,
+ RSVP_SESSION_TYPE_IPV6_LSP,
+
+ RSVP_SESSION_TYPE_IPV4_UNI = 9
+};
+
+/*
+ * Defines a desired QoS, in a RESV message.
+ */
+enum qos_service_type {
+ QOS_QUALITATIVE = 128, /* Qualitative service */
+ QOS_NULL = 6, /* Null service (RFC2997) */
+ QOS_CONTROLLED_LOAD= 5, /* Controlled Load Service */
+ QOS_GUARANTEED = 2, /* Guaranteed service */
+ QOS_TSPEC = 1 /* Traffic specification */
+ };
+
+static value_string qos_vals[] = {
+ { QOS_QUALITATIVE, "Qualitative QoS" },
+ { QOS_NULL, "Null-Service QoS" },
+ { QOS_CONTROLLED_LOAD, "Controlled-load QoS" },
+ { QOS_GUARANTEED, "Guaranteed rate QoS" },
+ { QOS_TSPEC, "Traffic specification" },
+ { 0, NULL }
+};
+
+static value_string svc_vals[] = {
+ { 126, "Compression Hint" },
+ { 127, "Token bucket" },
+ { 128, "Null Service" },
+ { 130, "Guaranteed-rate RSpec" },
+ { 0, NULL }
+};
+
+enum rsvp_spec_types { INTSRV = 2 };
+
+enum intsrv_services {
+ INTSRV_GENERAL = 1,
+ INTSRV_GTD = 2,
+ INTSRV_CLOAD = 5,
+ INTSRV_NULL = 6,
+ INTSRV_QUALITATIVE = 128
+};
+
+static value_string intsrv_services_str[] = {
+ {INTSRV_GENERAL, "Default General Parameters"},
+ {INTSRV_GTD, "Guaranteed Rate"},
+ {INTSRV_CLOAD, "Controlled Load"},
+ {INTSRV_NULL, "Null Service"},
+ {INTSRV_QUALITATIVE, "Null Service"},
+ { 0, NULL }
+};
+
+#if 0
+enum intsrv_field_name {
+ INTSRV_NON_IS_HOPS = 1, INTSRV_COMPOSED_NON_IS_HOPS,
+ INTSRV_IS_HOPS, INTSRV_COMPOSED_IS_HOPS,
+ INTSRV_PATH_BANDWIDTH, INTSRV_MIN_PATH_BANDWIDTH,
+ INTSRV_IF_LATENCY, INTSRV_PATH_LATENCY,
+ INTSRV_MTU, INTSRV_COMPOSED_MTU,
+
+ INTSRV_TOKEN_BUCKET_TSPEC = 127,
+ INTSRV_QUALITATIVE_TSPEC = 128,
+ INTSRV_GTD_RSPEC = 130,
+
+ INTSRV_DELAY = 131, /* Gtd Parameter C - Max Delay Bound - bytes */
+ INTSRV_MAX_JITTER, /* Gtd Parameter D - Max Jitter */
+ INTSRV_E2E_DELAY, /* Gtd Parameter Ctot */
+ INTSRV_E2E_MAX_JITTER, /* Gtd Parameter Dtot */
+ INTSRV_SHP_DELAY, /* Gtd Parameter Csum */
+ INTSRV_SHP_MAX_JITTER /* Gtd Parameter Dsum */
+};
+#endif
+
+static value_string adspec_params[] = {
+ {4, "IS Hop Count"},
+ {6, "Path b/w estimate"},
+ {8, "Minimum path latency"},
+ {10, "Composed MTU"},
+ {133, "End-to-end composed value for C"},
+ {134, "End-to-end composed value for D"},
+ {135, "Since-last-reshaping point composed C"},
+ {136, "Since-last-reshaping point composed D"},
+ { 0, NULL }
+};
+
+const value_string gmpls_lsp_enc_str[] = {
+ { 1, "Packet"},
+ { 2, "Ethernet v2/DIX"},
+ { 3, "ANSI PDH"},
+ { 5, "SONET/SDH"},
+ { 7, "Digital Wrapper"},
+ { 8, "Lambda (photonic)"},
+ { 9, "Fiber"},
+ {11, "FiberChannel"},
+ { 0, NULL }
+};
+
+const value_string gmpls_switching_type_str[] = {
+ { 1, "Packet-Switch Capable-1 (PSC-1)"},
+ { 2, "Packet-Switch Capable-2 (PSC-2)"},
+ { 3, "Packet-Switch Capable-3 (PSC-3)"},
+ { 4, "Packet-Switch Capable-4 (PSC-4)"},
+ { 51, "Layer-2 Switch Capable (L2SC)"},
+ {100, "Time-Division-Multiplex Capable (TDM)"},
+ {150, "Lambda-Switch Capable (LSC)"},
+ {200, "Fiber-Switch Capable (FSC)"},
+ { 0, NULL }
+};
+
+const value_string gmpls_protection_cap_str[] = {
+ { 1, "Extra Traffic"},
+ { 2, "Unprotected"},
+ { 4, "Shared"},
+ { 8, "Dedicated 1:1"},
+ {16, "Dedicated 1+1"},
+ {32, "Enhanced"},
+ {64, "Reserved"},
+ {128,"Reserved"},
+ { 0, NULL }
+};
+
+static const value_string gmpls_gpid_str[] = {
+ { 5, "Asynchronous mapping of E3 (SDH)"},
+ { 8, "Bit synchronous mapping of E3 (SDH)"},
+ { 9, "Byte synchronous mapping of E3 (SDH)"},
+ {10, "Asynchronous mapping of DS2/T2 (SDH)"},
+ {11, "Bit synchronous mapping of DS2/T2 (SONET, SDH)"},
+ {13, "Asynchronous mapping of E1 (SONET, SDH)"},
+ {14, "Byte synchronous mapping of E1 (SONET, SDH)"},
+ {15, "Byte synchronous mapping of 31 * DS0 (SONET, SDH)"},
+ {16, "Asynchronous mapping of DS1/T1 (SONET, SDH)"},
+ {17, "Bit synchronous mapping of DS1/T1 (SONET, SDH)"},
+ {18, "Byte synchronous mapping of DS1/T1 (SONET, SDH)"},
+ {19, "VC-11 in VC-12 (SDH)"},
+ {22, "DS1 SF Asynchronous (SONET)"},
+ {23, "DS1 ESF Asynchronous (SONET)"},
+ {24, "DS3 M23 Asynchronous (SONET)"},
+ {25, "DS3 C-Bit Parity Asynchronous (SONET)"},
+ {26, "VT/LOVC (SONET, SDH)"},
+ {27, "STS SPE/HOVC (SONET, SDH)"},
+ {28, "POS - No Scrambling, 16 bit CRC (SONET, SDH)"},
+ {29, "POS - No Scrambling, 32 bit CRC (SONET, SDH)"},
+ {30, "POS - Scrambling, 16 bit CRC (SONET, SDH)"},
+ {31, "POS - Scrambling, 32 bit CRC (SONET, SDH)"},
+ {32, "ATM Mapping (SONET, SDH)"},
+ {33, "Ethernet (SDH, Lambda, Fiber)"},
+ {34, "SDH (Lambda, Fiber)"},
+ {35, "SONET (Lambda, Fiber)"},
+ {36, "Digital Wrapper (Lambda, Fiber)"},
+ {37, "Lambda (Fiber)"},
+ {38, "ETSI PDH (SDH)"},
+ {39, "ANSI PDH (SONET, SDH)"},
+ {40, "Link Access Protocol SDH: LAPS - X.85 and X.86 (SONET, SDH)"},
+ {41, "FDDI (SONET, SDH, Lambda, Fiber)"},
+ {42, "DQDB: ETSI ETS 300 216 (SONET, SDH)"},
+ {43, "FiberChannel-3 Services (FiberChannel)"},
+ {44, "HDLC"},
+ {45, "Ethernet V2/DIX (only)"},
+ {46, "Ethernet 802.3 (only)"},
+ { 0, NULL },
+};
+
+static const value_string gmpls_sonet_signal_type_str[] = {
+ { 1, "VT1.5 SPE / VC-11"},
+ { 2, "VT2 SPE / VC-12"},
+ { 3, "VT3 SPE"},
+ { 4, "VT6 SPE / VC-2"},
+ { 5, "STS-1 SPE / VC-3"},
+ { 6, "STS-3c SPE / VC-4"},
+ { 7, "STS-1 / STM-0 (transp)"},
+ { 8, "STS-3 / STM-1 (transp)"},
+ { 9, "STS-12 / STM-4 (transp)"},
+ {10, "STS-48 / STM-16 (transp)"},
+ {11, "STS-192 / STM-64 (transp)"},
+ {12, "STS-768 / STM-256 (transp)"},
+
+ /* Extended non-SONET signal types */
+ {13, "VTG / TUG-2"},
+ {14, "TUG-3"},
+ {15, "STSG-3 / AUG-1"},
+ {16, "STSG-12 / AUG-4"},
+ {17, "STSG-48 / AUG-16"},
+ {18, "STSG-192 / AUG-64"},
+ {19, "STSG-768 / AUG-256"},
+};
+
+static const value_string ouni_guni_diversity_str[] = {
+ {1, "Node Diverse"},
+ {2, "Link Diverse"},
+ {3, "Shared-Risk Link Group Diverse"},
+ {4, "Shared Path"},
+};
+
+/* -------------------- Stuff for MPLS/TE objects -------------------- */
+
+static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
+ {IP_PROTO_IGMP, "IGMP"},
+ {IP_PROTO_TCP, "TCP" },
+ {IP_PROTO_UDP, "UDP" },
+ {IP_PROTO_OSPF, "OSPF"},
+ {0, NULL } };
+
+/* Filter keys */
+enum rsvp_filter_keys {
+
+ /* Message types */
+ RSVPF_MSG, /* Message type */
+ /* Shorthand for message types */
+ RSVPF_PATH,
+ RSVPF_RESV,
+ RSVPF_PATHERR,
+ RSVPF_RESVERR,
+ RSVPF_PATHTEAR,
+ RSVPF_RESVTEAR,
+ RSVPF_RCONFIRM,
+ RSVPF_JUNK_MSG8,
+ RSVPF_JUNK_MSG9,
+ RSVPF_RTEARCONFIRM,
+ RSVPF_JUNK11,
+ RSVPF_BUNDLE,
+ RSVPF_ACK,
+ RSVPF_JUNK14,
+ RSVPF_SREFRESH,
+ RSVPF_JUNK16,
+ RSVPF_JUNK17,
+ RSVPF_JUNK18,
+ RSVPF_JUNK19,
+ RSVPF_HELLO,
+ /* Does the message contain an object of this type? */
+ RSVPF_OBJECT,
+ /* Object present shorthands */
+ RSVPF_SESSION,
+ RSVPF_DUMMY_1,
+ RSVPF_HOP,
+ RSVPF_INTEGRITY,
+ RSVPF_TIME_VALUES,
+ RSVPF_ERROR,
+ RSVPF_SCOPE,
+ RSVPF_STYLE,
+ RSVPF_FLOWSPEC,
+ RSVPF_FILTER_SPEC,
+ RSVPF_SENDER,
+ RSVPF_TSPEC,
+ RSVPF_ADSPEC,
+ RSVPF_POLICY,
+ RSVPF_CONFIRM,
+ RSVPF_LABEL,
+ RSVPF_DUMMY_2,
+ RSVPF_DUMMY_3,
+ RSVPF_LABEL_REQUEST,
+ RSVPF_EXPLICIT_ROUTE,
+ RSVPF_RECORD_ROUTE,
+ RSVPF_HELLO_OBJ,
+ RSVPF_MESSAGE_ID,
+ RSVPF_MESSAGE_ID_ACK,
+ RSVPF_MESSAGE_ID_LIST,
+ RSVPF_RECOVERY_LABEL,
+ RSVPF_UPSTREAM_LABEL,
+ RSVPF_LABEL_SET,
+ RSVPF_PROTECTION,
+ RSVPF_DIFFSERV,
+
+ RSVPF_SUGGESTED_LABEL,
+ RSVPF_ACCEPTABLE_LABEL_SET,
+ RSVPF_RESTART_CAP,
+
+ RSVPF_SESSION_ATTRIBUTE,
+ RSVPF_DCLASS,
+ RSVPF_LSP_TUNNEL_IF_ID,
+ RSVPF_NOTIFY_REQUEST,
+ RSVPF_ADMIN_STATUS,
+ RSVPF_GENERALIZED_UNI,
+ RSVPF_UNKNOWN_OBJ,
+
+ /* Session object */
+ RSVPF_SESSION_IP,
+ RSVPF_SESSION_PROTO,
+ RSVPF_SESSION_PORT,
+ RSVPF_SESSION_TUNNEL_ID,
+ RSVPF_SESSION_EXT_TUNNEL_ID,
+
+ /* Sender template */
+ RSVPF_SENDER_IP,
+ RSVPF_SENDER_PORT,
+ RSVPF_SENDER_LSP_ID,
+
+ /* Diffserv object */
+ RSVPF_DIFFSERV_MAPNB,
+ RSVPF_DIFFSERV_MAP,
+ RSVPF_DIFFSERV_MAP_EXP,
+ RSVPF_DIFFSERV_PHBID,
+ RSVPF_DIFFSERV_PHBID_DSCP,
+ RSVPF_DIFFSERV_PHBID_CODE,
+ RSVPF_DIFFSERV_PHBID_BIT14,
+ RSVPF_DIFFSERV_PHBID_BIT15,
+
+ /* Sentinel */
+ RSVPF_MAX
+};
+
+static int rsvp_filter[RSVPF_MAX];
+
+static hf_register_info rsvpf_info[] = {
+
+ /* Message type number */
+ {&rsvp_filter[RSVPF_MSG],
+ { "Message Type", "rsvp.msg", FT_UINT8, BASE_DEC, VALS(message_type_vals), 0x0,
+ "", HFILL }},
+
+ /* Message type shorthands */
+ {&rsvp_filter[RSVPF_PATH],
+ { "Path Message", "rsvp.path", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_RESV],
+ { "Resv Message", "rsvp.resv", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_PATHERR],
+ { "Path Error Message", "rsvp.perr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_RESVERR],
+ { "Resv Error Message", "rsvp.rerr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_PATHTEAR],
+ { "Path Tear Message", "rsvp.ptear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_RESVTEAR],
+ { "Resv Tear Message", "rsvp.rtear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_RCONFIRM],
+ { "Resv Confirm Message", "rsvp.resvconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_RTEARCONFIRM],
+ { "Resv Tear Confirm Message", "rsvp.rtearconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_BUNDLE],
+ { "Bundle Message", "rsvp.bundle", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_ACK],
+ { "Ack Message", "rsvp.ack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SREFRESH],
+ { "Srefresh Message", "rsvp.srefresh", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_HELLO],
+ { "HELLO Message", "rsvp.hello", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ /* Object class */
+ {&rsvp_filter[RSVPF_OBJECT],
+ { "Object class", "rsvp.object", FT_UINT8, BASE_DEC, VALS(rsvp_class_vals), 0x0,
+ "", HFILL }},
+
+ /* Object present shorthands */
+ {&rsvp_filter[RSVPF_SESSION],
+ { "SESSION", "rsvp.session", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_HOP],
+ { "HOP", "rsvp.hop", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_HELLO_OBJ],
+ { "HELLO Request/Ack", "rsvp.hello_obj", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_INTEGRITY],
+ { "INTEGRITY", "rsvp.integrity", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_TIME_VALUES],
+ { "TIME VALUES", "rsvp.time", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_ERROR],
+ { "ERROR", "rsvp.error", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SCOPE],
+ { "SCOPE", "rsvp.scope", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_STYLE],
+ { "STYLE", "rsvp.style", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_FLOWSPEC],
+ { "FLOWSPEC", "rsvp.flowspec", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_FILTER_SPEC],
+ { "FILTERSPEC", "rsvp.filter", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SENDER],
+ { "SENDER TEMPLATE", "rsvp.sender", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_TSPEC],
+ { "SENDER TSPEC", "rsvp.tspec", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_ADSPEC],
+ { "ADSPEC", "rsvp.adspec", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_POLICY],
+ { "POLICY", "rsvp.policy", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_CONFIRM],
+ { "CONFIRM", "rsvp.confirm", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_LABEL],
+ { "LABEL", "rsvp.label", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_RECOVERY_LABEL],
+ { "RECOVERY LABEL", "rsvp.recovery_label", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_UPSTREAM_LABEL],
+ { "UPSTREAM LABEL", "rsvp.upstream_label", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SUGGESTED_LABEL],
+ { "SUGGESTED LABEL", "rsvp.suggested_label", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_LABEL_SET],
+ { "RESTRICTED LABEL SET", "rsvp.label_set", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_ACCEPTABLE_LABEL_SET],
+ { "ACCEPTABLE LABEL SET", "rsvp.acceptable_label_set", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_PROTECTION],
+ { "PROTECTION", "rsvp.protection", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_DIFFSERV],
+ { "DIFFSERV", "rsvp.diffserv", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_RESTART_CAP],
+ { "RESTART CAPABILITY", "rsvp.restart", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_LABEL_REQUEST],
+ { "LABEL REQUEST", "rsvp.label_request", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SESSION_ATTRIBUTE],
+ { "SESSION ATTRIBUTE", "rsvp.session_attribute", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_EXPLICIT_ROUTE],
+ { "EXPLICIT ROUTE", "rsvp.explicit_route", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_RECORD_ROUTE],
+ { "RECORD ROUTE", "rsvp.record_route", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_MESSAGE_ID],
+ { "MESSAGE-ID", "rsvp.msgid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_MESSAGE_ID_ACK],
+ { "MESSAGE-ID ACK", "rsvp.ack", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_MESSAGE_ID_LIST],
+ { "MESSAGE-ID LIST", "rsvp.msgid_list", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_DCLASS],
+ { "DCLASS", "rsvp.dclass", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_LSP_TUNNEL_IF_ID],
+ { "LSP INTERFACE-ID", "rsvp.lsp_tunnel_if_id", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_ADMIN_STATUS],
+ { "ADMIN STATUS", "rsvp.admin_status", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_NOTIFY_REQUEST],
+ { "NOTIFY REQUEST", "rsvp.notify_request", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_GENERALIZED_UNI],
+ { "GENERALIZED UNI", "rsvp.generalized_uni", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_UNKNOWN_OBJ],
+ { "Unknown object", "rsvp.obj_unknown", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ /* Session fields */
+ {&rsvp_filter[RSVPF_SESSION_IP],
+ { "Destination address", "rsvp.session.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SESSION_PORT],
+ { "Port number", "rsvp.session.port", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SESSION_PROTO],
+ { "Protocol", "rsvp.session.proto", FT_UINT8, BASE_DEC, VALS(proto_vals), 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
+ { "Tunnel ID", "rsvp.session.tunnel_id", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
+ { "Extended tunnel ID", "rsvp.session.ext_tunnel_id", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ /* Sender template/Filterspec fields */
+ {&rsvp_filter[RSVPF_SENDER_IP],
+ { "Sender IPv4 address", "rsvp.sender.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SENDER_PORT],
+ { "Sender port number", "rsvp.sender.port", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ {&rsvp_filter[RSVPF_SENDER_LSP_ID],
+ { "Sender LSP ID", "rsvp.sender.lsp_id", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ /* Diffserv object fields */
+ {&rsvp_filter[RSVPF_DIFFSERV_MAPNB],
+ { "MAPnb", "rsvp.diffserv.mapnb", FT_UINT8, BASE_DEC, NULL, 0x0,
+ MAPNB_DESCRIPTION, HFILL }},
+
+ {&rsvp_filter[RSVPF_DIFFSERV_MAP],
+ { "MAP", "rsvp.diffserv.map", FT_NONE, BASE_NONE, NULL, 0x0,
+ MAP_DESCRIPTION, HFILL }},
+
+ {&rsvp_filter[RSVPF_DIFFSERV_MAP_EXP],
+ { "EXP", "rsvp.diffserv.map.exp", FT_UINT8, BASE_DEC, NULL, 0x0,
+ EXP_DESCRIPTION, HFILL }},
+
+ {&rsvp_filter[RSVPF_DIFFSERV_PHBID],
+ { "PHBID", "rsvp.diffserv.phbid", FT_NONE, BASE_NONE, NULL, 0x0,
+ PHBID_DESCRIPTION, HFILL }},
+
+ {&rsvp_filter[RSVPF_DIFFSERV_PHBID_DSCP],
+ { PHBID_DSCP_DESCRIPTION, "rsvp.diffserv.phbid.dscp", FT_UINT16,
+ BASE_DEC, NULL, PHBID_DSCP_MASK, "DSCP", HFILL }},
+
+ {&rsvp_filter[RSVPF_DIFFSERV_PHBID_CODE],
+ { PHBID_CODE_DESCRIPTION, "rsvp.diffserv.phbid.code", FT_UINT16,
+ BASE_DEC, NULL, PHBID_CODE_MASK, "PHB id code", HFILL }},
+
+ {&rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT14],
+ { PHBID_BIT14_DESCRIPTION, "rsvp.diffserv.phbid.bit14", FT_UINT16,
+ BASE_DEC, VALS(phbid_bit14_vals), PHBID_BIT14_MASK, "Bit 14", HFILL }},
+
+ {&rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT15],
+ { PHBID_BIT15_DESCRIPTION, "rsvp.diffserv.phbid.bit15", FT_UINT16,
+ BASE_DEC, VALS(phbid_bit15_vals), PHBID_BIT15_MASK, "Bit 15", HFILL }}
+
+};
+
+static inline int rsvp_class_to_filter_num(int classnum)
+{
+ switch(classnum) {
+ case RSVP_CLASS_SESSION :
+ case RSVP_CLASS_HOP :
+ case RSVP_CLASS_INTEGRITY :
+ case RSVP_CLASS_TIME_VALUES :
+ case RSVP_CLASS_ERROR :
+ case RSVP_CLASS_SCOPE :
+ case RSVP_CLASS_STYLE :
+ case RSVP_CLASS_FLOWSPEC :
+ case RSVP_CLASS_FILTER_SPEC :
+ case RSVP_CLASS_SENDER_TEMPLATE :
+ case RSVP_CLASS_SENDER_TSPEC :
+ case RSVP_CLASS_ADSPEC :
+ case RSVP_CLASS_POLICY :
+ case RSVP_CLASS_CONFIRM :
+ case RSVP_CLASS_LABEL :
+ case RSVP_CLASS_LABEL_REQUEST :
+ case RSVP_CLASS_HELLO :
+ case RSVP_CLASS_EXPLICIT_ROUTE :
+ case RSVP_CLASS_RECORD_ROUTE :
+ case RSVP_CLASS_MESSAGE_ID :
+ case RSVP_CLASS_MESSAGE_ID_ACK :
+ case RSVP_CLASS_MESSAGE_ID_LIST :
+ return classnum + RSVPF_OBJECT;
+ break;
+
+ case RSVP_CLASS_RECOVERY_LABEL :
+ case RSVP_CLASS_UPSTREAM_LABEL :
+ case RSVP_CLASS_LABEL_SET :
+ case RSVP_CLASS_PROTECTION :
+ return RSVPF_RECOVERY_LABEL + (classnum - RSVP_CLASS_RECOVERY_LABEL);
+
+ case RSVP_CLASS_SUGGESTED_LABEL :
+ case RSVP_CLASS_ACCEPTABLE_LABEL_SET :
+ case RSVP_CLASS_RESTART_CAP :
+ return RSVPF_SUGGESTED_LABEL + (classnum - RSVP_CLASS_SUGGESTED_LABEL);
+
+ case RSVP_CLASS_DIFFSERV :
+ return RSVPF_DIFFSERV;
+
+ case RSVP_CLASS_NOTIFY_REQUEST :
+ return RSVPF_NOTIFY_REQUEST;
+ case RSVP_CLASS_ADMIN_STATUS :
+ return RSVPF_ADMIN_STATUS;
+
+ case RSVP_CLASS_SESSION_ATTRIBUTE :
+ return RSVPF_SESSION_ATTRIBUTE;
+ case RSVP_CLASS_GENERALIZED_UNI :
+ return RSVPF_GENERALIZED_UNI;
+ case RSVP_CLASS_DCLASS :
+ return RSVPF_DCLASS;
+ case RSVP_CLASS_LSP_TUNNEL_IF_ID :
+ return RSVPF_LSP_TUNNEL_IF_ID;
+
+ default:
+ return RSVPF_UNKNOWN_OBJ;
+ }
+}
+
+static void
+find_rsvp_session_tempfilt(tvbuff_t *tvb, int hdr_offset, int *session_offp, int *tempfilt_offp)
+{
+ int s_off = 0, t_off = 0;
+ int len, off;
+ guint16 obj_length;
+
+ if (!tvb_bytes_exist(tvb, hdr_offset+6, 2))
+ goto done;
+
+ len = tvb_get_ntohs(tvb, hdr_offset+6) + hdr_offset;
+ off = hdr_offset + 8;
+ for (off = hdr_offset + 8; off < len && tvb_bytes_exist(tvb, off, 3);
+ off += obj_length) {
+ obj_length = tvb_get_ntohs(tvb, off);
+ if (obj_length == 0)
+ break;
+ switch(tvb_get_guint8(tvb, off+2)) {
+ case RSVP_CLASS_SESSION:
+ s_off = off;
+ break;
+ case RSVP_CLASS_SENDER_TEMPLATE:
+ case RSVP_CLASS_FILTER_SPEC:
+ t_off = off;
+ break;
+ default:
+ break;
+ }
+ }
+
+ done:
+ if (session_offp) *session_offp = s_off;
+ if (tempfilt_offp) *tempfilt_offp = t_off;
+}
+
+static char *summary_session (tvbuff_t *tvb, int offset)
+{
+ static char buf[80];
+
+ switch(tvb_get_guint8(tvb, offset+3)) {
+ case RSVP_SESSION_TYPE_IPV4:
+ snprintf(buf, 80, "SESSION: IPv4, Destination %s, Protocol %d, Port %d. ",
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
+ tvb_get_guint8(tvb, offset+8),
+ tvb_get_ntohs(tvb, offset+10));
+ break;
+ case RSVP_SESSION_TYPE_IPV4_LSP:
+ snprintf(buf, 80, "SESSION: IPv4-LSP, Destination %s, Tunnel ID %d, Ext ID %0x. ",
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
+ tvb_get_ntohs(tvb, offset+10),
+ tvb_get_ntohl(tvb, offset+12));
+ break;
+ case RSVP_SESSION_TYPE_IPV4_UNI:
+ snprintf(buf, 80, "SESSION: IPv4-UNI, Destination %s, Tunnel ID %d, Ext Address %s. ",
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
+ tvb_get_ntohs(tvb, offset+10),
+ ip_to_str(tvb_get_ptr(tvb, offset+12, 4)));
+ break;
+ default:
+ snprintf(buf, 80, "SESSION: Type %d. ", tvb_get_guint8(tvb, offset+3));
+ }
+
+ return buf;
+}
+
+static char *summary_template (tvbuff_t *tvb, int offset)
+{
+ static char buf[80];
+ char *objtype;
+
+ if (tvb_get_guint8(tvb, offset+2) == RSVP_CLASS_FILTER_SPEC)
+ objtype = "FILTERSPEC";
+ else
+ objtype = "SENDER TEMPLATE";
+
+ switch(tvb_get_guint8(tvb, offset+3)) {
+ case 1:
+ snprintf(buf, 80, "%s: IPv4, Sender %s, Port %d. ", objtype,
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
+ tvb_get_ntohs(tvb, offset+10));
+ break;
+ case 7:
+ snprintf(buf, 80, "%s: IPv4-LSP, Tunnel Source: %s, LSP ID: %d. ", objtype,
+ ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
+ tvb_get_ntohs(tvb, offset+10));
+ break;
+ default:
+ snprintf(buf, 80, "%s: Type %d. ", objtype, tvb_get_guint8(tvb, offset+3));
+ }
+
+ return buf;
+}
+
+/*------------------------------------------------------------------------------
+ * SESSION
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_session (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_SESSION));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, summary_session(tvb, offset));
+
+ switch(type) {
+ case RSVP_SESSION_TYPE_IPV4:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 - IPv4");
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SESSION_IP],
+ tvb, offset2, 4, FALSE);
+
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SESSION_PROTO], tvb,
+ offset2+4, 1, FALSE);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
+ "Flags: %x",
+ tvb_get_guint8(tvb, offset2+5));
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SESSION_PORT], tvb,
+ offset2+6, 2, FALSE);
+ break;
+
+ case RSVP_SESSION_TYPE_IPV6:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2 - IPv6");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
+ "Destination address: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 1,
+ "Protocol: %u",
+ tvb_get_guint8(tvb, offset2+16));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+17, 1,
+ "Flags: %x",
+ tvb_get_guint8(tvb, offset2+17));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
+ "Destination port: %u",
+ tvb_get_ntohs(tvb, offset2+18));
+ break;
+
+ case RSVP_SESSION_TYPE_IPV4_LSP:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 7 - IPv4 LSP");
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SESSION_IP],
+ tvb, offset2, 4, FALSE);
+
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
+ tvb, offset2+6, 2, FALSE);
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
+ "Extended Tunnel ID: %u (%s)",
+ tvb_get_ntohl(tvb, offset2+8),
+ ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
+ proto_tree_add_item_hidden(rsvp_object_tree,
+ rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
+ tvb, offset2+8, 4, FALSE);
+ break;
+
+ case RSVP_SESSION_TYPE_IPV4_UNI:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 9 - IPv4 UNI");
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SESSION_IP],
+ tvb, offset2, 4, FALSE);
+
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
+ tvb, offset2+6, 2, FALSE);
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
+ "Extended IPv4 Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
+ proto_tree_add_item_hidden(rsvp_object_tree,
+ rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
+ tvb, offset2+8, 4, FALSE);
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length-4,
+ "Data (%d bytes)", obj_length-4);
+ }
+}
+
+
+/*------------------------------------------------------------------------------
+ * TLVs for HOP, ERROR and other IF_ID extended objects
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_ifid_tlv (proto_tree *ti, proto_tree *rsvp_object_tree,
+ tvbuff_t *tvb, int offset, int obj_length,
+ int subtree_type)
+{
+ guint16 tlv_off;
+ guint16 tlv_type;
+ guint16 tlv_len;
+ char *ifindex_name;
+ proto_tree *rsvp_ifid_subtree, *ti2;
+ int offset2 = offset + 4;
+
+ for (tlv_off = 0; tlv_off < obj_length - 12; ) {
+ tlv_type = tvb_get_ntohs(tvb, offset+tlv_off);
+ tlv_len = tvb_get_ntohs(tvb, offset+tlv_off+2);
+ switch(tlv_type) {
+ case 1:
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset+tlv_off, 8,
+ "IPv4 TLV - %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
+
+ rsvp_ifid_subtree = proto_item_add_subtree(ti2, subtree_type);
+ proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off, 2,
+ "Type: 1 (IPv4)");
+ proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+2, 2,
+ "Length: %u",
+ tvb_get_ntohs(tvb, offset+tlv_off+2));
+ proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+4, 4,
+ "IPv4 address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
+ proto_item_append_text(ti, "Data IPv4: %s. ",
+ ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
+ break;
+
+ case 3:
+ ifindex_name = "";
+ goto ifid_ifindex;
+ case 4:
+ ifindex_name = " Forward";
+ goto ifid_ifindex;
+ case 5:
+ ifindex_name = " Reverse";
+ ifid_ifindex:
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset+tlv_off, 12,
+ "Interface-Index%s TLV - %s, %d",
+ ifindex_name,
+ ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)),
+ tvb_get_ntohl(tvb, offset+tlv_off+8));
+ rsvp_ifid_subtree = proto_item_add_subtree(ti2, subtree_type);
+ proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off, 2,
+ "Type: %d (Interface Index%s)", tlv_type, ifindex_name);
+ proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+2, 2,
+ "Length: %u",
+ tvb_get_ntohs(tvb, offset+tlv_off+2));
+ proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+4, 4,
+ "IPv4 address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
+ proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+8, 4,
+ "Interface-ID: %d",
+ tvb_get_ntohl(tvb, offset+tlv_off+8));
+ proto_item_append_text(ti, "Data If-Index%s: %s, %d. ", ifindex_name,
+ ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)),
+ tvb_get_ntohl(tvb, offset+tlv_off+8));
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
+ "Logical interface: %u",
+ tvb_get_ntohl(tvb, offset2+4));
+ }
+ tlv_off += tlv_len;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * HOP
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_hop (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree= proto_item_add_subtree(ti, TREE(TT_HOP));
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 - IPv4");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Neighbor address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
+ "Logical interface: %u",
+ tvb_get_ntohl(tvb, offset2+4));
+ proto_item_set_text(ti, "HOP: IPv4, %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ break;
+
+ case 2:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2 - IPv6");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
+ "Neighbor address: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 4,
+ "Logical interface: 0x%08x",
+ tvb_get_ntohl(tvb, offset2+16));
+ break;
+
+ case 3:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 3 - IPv4 IF-ID");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Neighbor address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
+ "Logical interface: %u",
+ tvb_get_ntohl(tvb, offset2+4));
+
+ proto_item_set_text(ti, "HOP: IPv4 IF-ID. Control IPv4: %s. ",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+
+ dissect_rsvp_ifid_tlv(ti, rsvp_object_tree, tvb, offset+12, obj_length,
+ TREE(TT_HOP_SUBOBJ));
+
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * TIME VALUES
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_time_values (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_TIME_VALUES));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Refresh interval: %u ms (%u seconds)",
+ tvb_get_ntohl(tvb, offset2),
+ tvb_get_ntohl(tvb, offset2)/1000);
+ proto_item_set_text(ti, "TIME VALUES: %d ms",
+ tvb_get_ntohl(tvb, offset2));
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * Error value field in ERROR object
+ *------------------------------------------------------------------------------*/
+static guint16
+dissect_rsvp_error_value (proto_tree *ti, tvbuff_t *tvb,
+ int offset, guint8 error_code)
+{
+ guint16 error_val;
+ value_string *rsvp_error_vals = NULL;
+
+ error_val = tvb_get_ntohs(tvb, offset);
+ switch (error_code) {
+ case RSVP_ERROR_ADMISSION:
+ rsvp_error_vals = rsvp_admission_control_error_vals;
+ break;
+ case RSVP_ERROR_TRAFFIC:
+ rsvp_error_vals = rsvp_traffic_control_error_vals;
+ break;
+ case RSVP_ERROR_ROUTING:
+ rsvp_error_vals = rsvp_routing_error_vals;
+ break;
+ case RSVP_ERROR_NOTIFY:
+ rsvp_error_vals = rsvp_notify_error_vals;
+ break;
+ case RSVP_ERROR_DIFFSERV:
+ rsvp_error_vals = rsvp_diffserv_error_vals;
+ }
+ switch (error_code) {
+ case RSVP_ERROR_ADMISSION:
+ case RSVP_ERROR_TRAFFIC:
+ case RSVP_ERROR_NOTIFY:
+ case RSVP_ERROR_ROUTING:
+ case RSVP_ERROR_DIFFSERV:
+ if ((error_val & 0xc0) == 0) {
+ proto_tree_add_text(ti, tvb, offset, 2,
+ "Error value: %u - %s", error_val,
+ val_to_str(error_val, rsvp_error_vals, "Unknown (%d)"));
+ break;
+ }
+ default:
+ proto_tree_add_text(ti, tvb, offset, 2,
+ "Error value: %u", error_val);
+ }
+ return error_val;
+}
+
+/*------------------------------------------------------------------------------
+ * ERROR
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_error (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_ERROR));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1: {
+ guint8 error_code;
+ guint16 error_val;
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 - IPv4");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Error node: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 1,
+ "Flags: 0x%02x",
+ tvb_get_guint8(tvb, offset2+4));
+ error_code = tvb_get_guint8(tvb, offset2+5);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
+ "Error code: %u - %s", error_code,
+ val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"));
+ error_val = dissect_rsvp_error_value(rsvp_object_tree, tvb, offset2+6, error_code);
+ proto_item_set_text(ti, "ERROR: IPv4, Error code: %s, Value: %d, Error Node: %s",
+ val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"),
+ error_val, ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ break;
+ }
+
+ case 2: {
+ guint8 error_code;
+ guint16 error_val;
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2 - IPv6");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
+ "Error node: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 1,
+ "Flags: 0x%02x",
+ tvb_get_guint8(tvb, offset2+16));
+ error_code = tvb_get_guint8(tvb, offset2+17);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+17, 1,
+ "Error code: %u - %s",
+ error_code,
+ val_to_str(error_code, rsvp_error_codes, "Unknown"));
+ error_val = dissect_rsvp_error_value(ti, tvb, offset2+18, error_code);
+ break;
+ }
+
+ case 3: {
+ guint8 error_code;
+ guint16 error_val;
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 3 - IPv4 IF-ID");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Error node: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 1,
+ "Flags: 0x%02x",
+ tvb_get_guint8(tvb, offset2+4));
+ error_code = tvb_get_guint8(tvb, offset2+5);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
+ "Error code: %u - %s", error_code,
+ val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"));
+ error_val = dissect_rsvp_error_value(ti, tvb, offset2+6, error_code);
+ proto_item_set_text(ti, "ERROR: IPv4 IF-ID, Error code: %s, Value: %d, Control Node: %s. ",
+ val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"),
+ error_val, ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ dissect_rsvp_ifid_tlv(ti, rsvp_object_tree, tvb, offset+12, obj_length,
+ TREE(TT_ERROR_SUBOBJ));
+ break;
+ }
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * SCOPE
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_scope (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ int mylen;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_SCOPE));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ mylen = obj_length - 4;
+ switch(type) {
+ case 1: {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 - IPv4");
+ while (mylen > 0) {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "IPv4 Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ offset2 += 4;
+ mylen -= 4;
+ }
+ break;
+ }
+
+ case 2: {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2 - IPv6");
+ while (mylen > 0) {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
+ "IPv6 Address: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ offset2 += 16;
+ mylen -= 16;
+ }
+ break;
+ }
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * STYLE
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_style (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_STYLE));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1: {
+ guint32 style;
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Flags: 0x%02x",
+ tvb_get_guint8(tvb, offset2));
+ style = tvb_get_ntoh24(tvb, offset2+1);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+1,
+ 3, "Style: 0x%06X - %s", style,
+ val_to_str(style, style_vals, "Unknown"));
+ proto_item_set_text(ti, "STYLE: %s (%d)",
+ val_to_str(style, style_vals, "Unknown"),
+ style);
+ break;
+ }
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * CONFIRM
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_confirm (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_CONFIRM));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1: {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 - IPv4");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Receiver address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_item_set_text(ti, "CONFIRM: Receiver %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ break;
+ }
+
+ case 2: {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2 - IPv6");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
+ "Receiver address: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ break;
+ }
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * SENDER TEMPLATE and FILTERSPEC
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_template_filter (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ switch(class) {
+ case RSVP_CLASS_SENDER_TEMPLATE :
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_SENDER_TEMPLATE));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ break;
+
+ default:
+ case RSVP_CLASS_FILTER_SPEC :
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_FILTER_SPEC));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ break;
+ }
+
+ proto_item_set_text(ti, summary_template(tvb, offset));
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 - IPv4");
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SENDER_IP],
+ tvb, offset2, 4, FALSE);
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SENDER_PORT],
+ tvb, offset2+6, 2, FALSE);
+ break;
+
+ case 2:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2 - IPv6");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
+ "Source address: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
+ "Source port: %u",
+ tvb_get_ntohs(tvb, offset2+18));
+ break;
+
+ case 7:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 7 - IPv4 LSP");
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SENDER_IP],
+ tvb, offset2, 4, FALSE);
+ proto_tree_add_item(rsvp_object_tree,
+ rsvp_filter[RSVPF_SENDER_LSP_ID],
+ tvb, offset2+6, 2, FALSE);
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * SENDER TSPEC
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_tspec (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ int mylen;
+ proto_tree *tspec_tree, *ti2;
+ guint8 signal_type;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_TSPEC));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ mylen = obj_length - 4;
+
+ switch(type) {
+ case 2:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 - Integrated Services");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Message format version: %u",
+ tvb_get_guint8(tvb, offset2)>>4);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "Data length: %u words, not including header",
+ tvb_get_ntohs(tvb, offset2+2));
+
+ mylen -= 4;
+ offset2 += 4;
+
+ proto_item_set_text(ti, "SENDER TSPEC: IntServ: ");
+
+ while (mylen > 0) {
+ guint8 service_num;
+ guint8 param_id;
+ guint16 param_len;
+ guint16 param_len_processed;
+ guint16 length;
+
+ service_num = tvb_get_guint8(tvb, offset2);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Service header: %u - %s",
+ service_num,
+ val_to_str(service_num, qos_vals, "Unknown"));
+ length = tvb_get_ntohs(tvb, offset2+2);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "Length of service %u data: %u words, "
+ "not including header",
+ service_num, length);
+
+ mylen -= 4;
+ offset2 += 4;
+
+ /* Process all known service headers as a set of parameters */
+ param_len_processed = 0;
+ while (param_len_processed < length) {
+ param_id = tvb_get_guint8(tvb, offset2);
+ param_len = tvb_get_ntohs(tvb, offset2+2) + 1;
+ switch(param_id) {
+ case 127:
+ /* Token Bucket */
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2, param_len*4,
+ "Token Bucket TSpec: ");
+ tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
+
+ proto_tree_add_text(tspec_tree, tvb, offset2, 1,
+ "Parameter %u - %s",
+ param_id,
+ val_to_str(param_id, svc_vals, "Unknown"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
+ "Parameter %u flags: 0x%02x",
+ param_id,
+ tvb_get_guint8(tvb, offset2+1));
+ proto_tree_add_text(tspec_tree, tvb, offset2+2, 2,
+ "Parameter %u data length: %u words, "
+ "not including header",
+ param_id,
+ tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
+ "Token bucket rate: %.10g",
+ tvb_get_ntohieee_float(tvb, offset2+4));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ "Token bucket size: %.10g",
+ tvb_get_ntohieee_float(tvb, offset2+8));
+ proto_tree_add_text(tspec_tree, tvb, offset2+12, 4,
+ "Peak data rate: %.10g",
+ tvb_get_ntohieee_float(tvb, offset2+12));
+ proto_tree_add_text(tspec_tree, tvb, offset2+16, 4,
+ "Minimum policed unit [m]: %u",
+ tvb_get_ntohl(tvb, offset2+16));
+ proto_tree_add_text(tspec_tree, tvb, offset2+20, 4,
+ "Maximum packet size [M]: %u",
+ tvb_get_ntohl(tvb, offset2+20));
+ proto_item_append_text(ti, "Token Bucket, %.10g bytes/sec. ",
+ tvb_get_ntohieee_float(tvb, offset2+4));
+ proto_item_append_text(ti2, "Rate=%.10g Burst=%.10g Peak=%.10g m=%u M=%u",
+ tvb_get_ntohieee_float(tvb, offset2+4),
+ tvb_get_ntohieee_float(tvb, offset2+8),
+ tvb_get_ntohieee_float(tvb, offset2+12),
+ tvb_get_ntohl(tvb, offset2+16),
+ tvb_get_ntohl(tvb, offset2+20));
+ break;
+
+ case 128:
+ /* Null Service (RFC2997) */
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2, param_len*4,
+ "Null Service TSpec: ");
+ tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
+
+ proto_tree_add_text(tspec_tree, tvb, offset2, 1,
+ "Parameter %u - %s",
+ param_id,
+ val_to_str(param_id, svc_vals, "Unknown"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
+ "Parameter %u flags: %x",
+ param_id,
+ tvb_get_guint8(tvb, offset2+1));
+ proto_tree_add_text(tspec_tree, tvb, offset2+2, 2,
+ "Parameter %u data length: %u words, "
+ "not including header",
+ param_id,
+ tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
+ "Maximum packet size [M]: %u",
+ tvb_get_ntohl(tvb, offset2+4));
+ proto_item_append_text(ti, "Null Service. M=%u",
+ tvb_get_ntohl(tvb, offset2+4));
+ proto_item_append_text(ti2, "Max pkt size=%u",
+ tvb_get_ntohl(tvb, offset2+4));
+ break;
+
+ case 126:
+ /* Compression hint (RFC3006) */
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2, param_len*4,
+ "Compression Hint: ");
+ tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
+
+ proto_tree_add_text(tspec_tree, tvb, offset2, 1,
+ "Parameter %u - %s",
+ param_id,
+ val_to_str(param_id, svc_vals, "Unknown"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
+ "Parameter %u flags: %x",
+ param_id,
+ tvb_get_guint8(tvb, offset2+1));
+ proto_tree_add_text(tspec_tree, tvb, offset2+2, 2,
+ "Parameter %u data length: %u words, "
+ "not including header",
+ param_id,
+ tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
+ "Hint: %u",
+ tvb_get_ntohl(tvb, offset2+4));
+ proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
+ "Compression Factor: %u",
+ tvb_get_ntohl(tvb, offset2+8));
+ proto_item_append_text(ti, "Compression Hint. Hint=%u, Factor=%u",
+ tvb_get_ntohl(tvb, offset2+4),
+ tvb_get_ntohl(tvb, offset2+8));
+ proto_item_append_text(ti2, "Hint=%u, Factor=%u",
+ tvb_get_ntohl(tvb, offset2+4),
+ tvb_get_ntohl(tvb, offset2+8));
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, param_len*4,
+ "Unknown parameter %d, %d words",
+ param_id, param_len);
+ break;
+ }
+ param_len_processed += param_len;
+ offset2 += param_len*4;
+ }
+ mylen -= length*4;
+ }
+ break;
+
+ case 4: /* SONET/SDH Tspec */
+ proto_item_set_text(ti, "SENDER TSPEC: SONET/SDH: ");
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 4 - SONET/SDH");
+ signal_type = tvb_get_guint8(tvb, offset2);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Signal Type: %d - %s", signal_type,
+ val_to_str(signal_type,
+ gmpls_sonet_signal_type_str, "Unknown"));
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
+ "Requested Concatenation (RCC): %d", tvb_get_guint8(tvb, offset2+1));
+ tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
+ proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x01, 8,
+ "Standard contiguous concatenation",
+ "No standard contiguous concatenation"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x02, 8,
+ "Arbitrary contiguous concatenation",
+ "No arbitrary contiguous concatenation"));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "Number of Contiguous Components (NCC): %d", tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2,
+ "Number of Virtual Components (NVC): %d", tvb_get_ntohs(tvb, offset2+4));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
+ "Multiplier (MT): %d", tvb_get_ntohs(tvb, offset2+6));
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
+ "Transparency (T): 0x%0x", tvb_get_ntohl(tvb, offset2+8));
+ tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_ntohl(tvb, offset2+8), 0x0001, 32,
+ "Section/Regenerator Section layer transparency",
+ "No Section/Regenerator Section layer transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0002, 32,
+ "Line/Multiplex Section layer transparency",
+ "No Line/Multiplex Section layer transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0004, 32,
+ "J0 transparency",
+ "No J0 transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0008, 32,
+ "SOH/RSOH DCC transparency",
+ "No SOH/RSOH DCC transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0010, 32,
+ "LOH/MSOH DCC transparency",
+ "No LOH/MSOH DCC transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0020, 32,
+ "LOH/MSOH Extended DCC transparency",
+ "No LOH/MSOH Extended DCC transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0040, 32,
+ "K1/K2 transparency",
+ "No K1/K2 transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0080, 32,
+ "E1 transparency",
+ "No E1 transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0100, 32,
+ "F1 transparency",
+ "No F1 transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0200, 32,
+ "E2 transparency",
+ "No E2 transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0400, 32,
+ "B1 transparency",
+ "No B1 transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0800, 32,
+ "B2 transparency",
+ "No B2 transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x1000, 32,
+ "M0 transparency",
+ "No M0 transparency"));
+ proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x2000, 32,
+ "M1 transparency",
+ "No M1 transparency"));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+12, 4,
+ "Profile (P): %d", tvb_get_ntohl(tvb, offset2+12));
+
+ proto_item_append_text(ti, "Signal [%s], RCC %d, NCC %d, NVC %d, MT %d, Transparency %d, Profile %d",
+ val_to_str(signal_type, gmpls_sonet_signal_type_str, "Unknown"),
+ tvb_get_guint8(tvb, offset2+1), tvb_get_ntohs(tvb, offset2+2),
+ tvb_get_ntohs(tvb, offset2+4), tvb_get_ntohs(tvb, offset2+6),
+ tvb_get_ntohl(tvb, offset2+8), tvb_get_ntohl(tvb, offset2+12));
+ break;
+
+ default: /* Unknown TSpec */
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * FLOWSPEC
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_flowspec (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ int mylen, signal_type;
+ proto_tree *flowspec_tree, *ti2;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_FLOWSPEC));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: %u", type);
+ mylen = obj_length - 4;
+
+ switch(type) {
+
+ case 2:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Message format version: %u",
+ tvb_get_guint8(tvb, offset2)>>4);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "Data length: %u words, not including header",
+ tvb_get_ntohs(tvb, offset2+2));
+
+ proto_item_set_text(ti, "FLOWSPEC: ");
+
+ mylen -= 4;
+ offset2+= 4;
+ while (mylen > 0) {
+ guint8 service_num;
+ guint16 length;
+ guint8 param_id;
+ guint16 param_len;
+ guint16 param_len_processed;
+
+ service_num = tvb_get_guint8(tvb, offset2);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Service header: %u - %s",
+ service_num,
+ val_to_str(service_num, intsrv_services_str, "Unknown"));
+ length = tvb_get_ntohs(tvb, offset2+2);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "Length of service %u data: %u words, "
+ "not including header",
+ service_num,
+ length);
+
+ mylen -= 4;
+ offset2 += 4;
+
+ proto_item_append_text(ti, "%s: ",
+ val_to_str(service_num, intsrv_services_str,
+ "Unknown (%d)"));
+
+ /* Process all known service headers as a set of parameters */
+ param_len_processed = 0;
+ while (param_len_processed < length) {
+ param_id = tvb_get_guint8(tvb, offset2);
+ param_len = tvb_get_ntohs(tvb, offset2+2) + 1;
+ switch(param_id) {
+ case 127:
+ /* Token Bucket */
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2, param_len*4,
+ "Token Bucket: ");
+ flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
+
+ proto_tree_add_text(flowspec_tree, tvb, offset2, 1,
+ "Parameter %u - %s",
+ param_id,
+ val_to_str(param_id, svc_vals, "Unknown"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
+ "Parameter %u flags: 0x%02x",
+ param_id,
+ tvb_get_guint8(tvb, offset2+1));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+2, 2,
+ "Parameter %u data length: %u words, "
+ "not including header",
+ param_id,
+ tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+4, 4,
+ "Token bucket rate: %.10g",
+ tvb_get_ntohieee_float(tvb, offset2+4));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ "Token bucket size: %.10g",
+ tvb_get_ntohieee_float(tvb, offset2+8));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+12, 4,
+ "Peak data rate: %.10g",
+ tvb_get_ntohieee_float(tvb, offset2+12));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+16, 4,
+ "Minimum policed unit [m]: %u",
+ tvb_get_ntohl(tvb, offset2+16));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+20, 4,
+ "Maximum packet size [M]: %u",
+ tvb_get_ntohl(tvb, offset2+20));
+ proto_item_append_text(ti, "Token Bucket, %.10g bytes/sec. ",
+ tvb_get_ntohieee_float(tvb, offset2+4));
+ proto_item_append_text(ti2, "Rate=%.10g Burst=%.10g Peak=%.10g m=%u M=%u",
+ tvb_get_ntohieee_float(tvb, offset2+4),
+ tvb_get_ntohieee_float(tvb, offset2+8),
+ tvb_get_ntohieee_float(tvb, offset2+12),
+ tvb_get_ntohl(tvb, offset2+16),
+ tvb_get_ntohl(tvb, offset2+20));
+ break;
+
+ case 130:
+ /* Guaranteed-rate RSpec */
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2, param_len*4,
+ "Guaranteed-Rate RSpec: ");
+ flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
+ proto_tree_add_text(flowspec_tree, tvb, offset2, 1,
+ "Parameter %u - %s",
+ param_id,
+ val_to_str(param_id, svc_vals, "Unknown"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
+ "Parameter %u flags: %x",
+ param_id,
+ tvb_get_guint8(tvb, offset2+1));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+2, 2,
+ "Parameter %u data length: %u words, "
+ "not including header",
+ param_id,
+ tvb_get_ntohs(tvb, offset2+2));
+
+ proto_tree_add_text(flowspec_tree, tvb, offset2+4, 4,
+ "Rate: %.10g",
+ tvb_get_ntohieee_float(tvb, offset2+4));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ "Slack term: %u",
+ tvb_get_ntohl(tvb, offset2+8));
+ proto_item_append_text(ti, "RSpec, %.10g bytes/sec. ",
+ tvb_get_ntohieee_float(tvb, offset2+4));
+ proto_item_append_text(ti2, "R=%.10g, s=%u",
+ tvb_get_ntohieee_float(tvb, offset2+4),
+ tvb_get_ntohl(tvb, offset2+8));
+ break;
+
+ case 128:
+ /* Null Service (RFC2997) */
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2, param_len*4,
+ "Null Service Flowspec: ");
+ flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
+
+ proto_tree_add_text(flowspec_tree, tvb, offset2, 1,
+ "Parameter %u - %s",
+ param_id,
+ val_to_str(param_id, svc_vals, "Unknown"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
+ "Parameter %u flags: %x",
+ param_id,
+ tvb_get_guint8(tvb, offset2+1));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+2, 2,
+ "Parameter %u data length: %u words, "
+ "not including header",
+ param_id,
+ tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+4, 4,
+ "Maximum packet size [M]: %u",
+ tvb_get_ntohl(tvb, offset2+4));
+ proto_item_append_text(ti, "Null Service. M=%u",
+ tvb_get_ntohl(tvb, offset2+4));
+ proto_item_append_text(ti2, "Max pkt size=%u",
+ tvb_get_ntohl(tvb, offset2+4));
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, param_len*4,
+ "Unknown parameter %d, %d words",
+ param_id, param_len);
+ break;
+ }
+ param_len_processed += param_len;
+ offset2 += param_len * 4;
+ }
+
+ /* offset2 += length*4; */
+ mylen -= length*4;
+ }
+ break;
+
+ case 4:
+ proto_item_set_text(ti, "FLOWSPEC: SONET/SDH: ");
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 4 - SONET/SDH");
+ signal_type = tvb_get_guint8(tvb, offset2);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Signal Type: %d - %s", signal_type,
+ val_to_str(signal_type,
+ gmpls_sonet_signal_type_str, "Unknown"));
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
+ "Requested Concatenation (RCC): %d", tvb_get_guint8(tvb, offset2+1));
+ flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x01, 8,
+ "Standard contiguous concatenation",
+ "No standard contiguous concatenation"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x02, 8,
+ "Arbitrary contiguous concatenation",
+ "No arbitrary contiguous concatenation"));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "Number of Contiguous Components (NCC): %d", tvb_get_ntohs(tvb, offset2+2));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2,
+ "Number of Virtual Components (NVC): %d", tvb_get_ntohs(tvb, offset2+4));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
+ "Multiplier (MT): %d", tvb_get_ntohs(tvb, offset2+6));
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
+ "Transparency (T): 0x%0x", tvb_get_ntohl(tvb, offset2+8));
+ flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_ntohl(tvb, offset2+8), 0x0001, 32,
+ "Section/Regenerator Section layer transparency",
+ "No Section/Regenerator Section layer transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0002, 32,
+ "Line/Multiplex Section layer transparency",
+ "No Line/Multiplex Section layer transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0004, 32,
+ "J0 transparency",
+ "No J0 transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0008, 32,
+ "SOH/RSOH DCC transparency",
+ "No SOH/RSOH DCC transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0010, 32,
+ "LOH/MSOH DCC transparency",
+ "No LOH/MSOH DCC transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0020, 32,
+ "LOH/MSOH Extended DCC transparency",
+ "No LOH/MSOH Extended DCC transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0040, 32,
+ "K1/K2 transparency",
+ "No K1/K2 transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0080, 32,
+ "E1 transparency",
+ "No E1 transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0100, 32,
+ "F1 transparency",
+ "No F1 transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0200, 32,
+ "E2 transparency",
+ "No E2 transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0400, 32,
+ "B1 transparency",
+ "No B1 transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0800, 32,
+ "B2 transparency",
+ "No B2 transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x1000, 32,
+ "M0 transparency",
+ "No M0 transparency"));
+ proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
+ decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x2000, 32,
+ "M1 transparency",
+ "No M1 transparency"));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+12, 4,
+ "Profile (P): %d", tvb_get_ntohl(tvb, offset2+12));
+
+ proto_item_append_text(ti, "Signal [%s], RCC %d, NCC %d, NVC %d, MT %d, Transparency %d, Profile %d",
+ val_to_str(signal_type, gmpls_sonet_signal_type_str, "Unknown"),
+ tvb_get_guint8(tvb, offset2+1), tvb_get_ntohs(tvb, offset2+2),
+ tvb_get_ntohs(tvb, offset2+4), tvb_get_ntohs(tvb, offset2+6),
+ tvb_get_ntohl(tvb, offset2+8), tvb_get_ntohl(tvb, offset2+12));
+ break;
+
+ default:
+ break;
+ }
+
+
+}
+
+/*------------------------------------------------------------------------------
+ * ADSPEC
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_adspec (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ int mylen, i;
+ proto_tree *adspec_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_ADSPEC));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: %u", type);
+ mylen = obj_length - 4;
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Message format version: %u",
+ tvb_get_guint8(tvb, offset2)>>4);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "Data length: %u words, not including header",
+ tvb_get_ntohs(tvb, offset2+2));
+ mylen -= 4;
+ offset2 += 4;
+ while (mylen > 0) {
+ guint8 service_num;
+ guint8 break_bit;
+ guint16 length;
+ char *str;
+
+ service_num = tvb_get_guint8(tvb, offset2);
+ str = val_to_str(service_num, intsrv_services_str, "Unknown");
+ break_bit = tvb_get_guint8(tvb, offset2+1);
+ length = tvb_get_ntohs(tvb, offset2+2);
+ ti = proto_tree_add_text(rsvp_object_tree, tvb, offset2,
+ (length+1)*4,
+ str);
+ adspec_tree = proto_item_add_subtree(ti,
+ TREE(TT_ADSPEC_SUBTREE));
+ proto_tree_add_text(adspec_tree, tvb, offset2, 1,
+ "Service header %u - %s",
+ service_num, str);
+ proto_tree_add_text(adspec_tree, tvb, offset2+1, 1,
+ (break_bit&0x80)?
+ "Break bit set":"Break bit not set");
+ proto_tree_add_text(adspec_tree, tvb, offset2+2, 2,
+ "Data length: %u words, not including header",
+ length);
+ mylen -= 4;
+ offset2 += 4;
+ i = length*4;
+ while (i > 0) {
+ guint8 id;
+ guint16 phdr_length;
+
+ id = tvb_get_guint8(tvb, offset2);
+ phdr_length = tvb_get_ntohs(tvb, offset2+2);
+ str = match_strval(id, adspec_params);
+ if (str) {
+ switch(id) {
+ case 4:
+ case 8:
+ case 10:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ /* 32-bit unsigned integer */
+ proto_tree_add_text(adspec_tree, tvb, offset2,
+ (phdr_length+1)<<2,
+ "%s - %u (type %u, length %u)",
+ str,
+ tvb_get_ntohl(tvb, offset2+4),
+ id, phdr_length);
+ break;
+
+ case 6:
+ /* IEEE float */
+ proto_tree_add_text(adspec_tree, tvb, offset2,
+ (phdr_length+1)<<2,
+ "%s - %.10g (type %u, length %u)",
+ str,
+ tvb_get_ntohieee_float(tvb, offset2+4),
+ id, phdr_length);
+ break;
+ default:
+ proto_tree_add_text(adspec_tree, tvb, offset2,
+ (phdr_length+1)<<2,
+ "%s (type %u, length %u)",
+ str,
+ id, phdr_length);
+ }
+ } else {
+ proto_tree_add_text(adspec_tree, tvb, offset2,
+ (phdr_length+1)<<2,
+ "Unknown (type %u, length %u)",
+ id, phdr_length);
+ }
+ offset2 += (phdr_length+1)<<2;
+ i -= (phdr_length+1)<<2;
+ mylen -= (phdr_length+1)<<2;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * INTEGRITY
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_integrity (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ proto_tree *ti2, *rsvp_integ_flags_tree;
+ int flags;
+ guint64 sequence_number;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_INTEGRITY));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: %u", type);
+ flags = tvb_get_guint8(tvb, offset2);
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Flags: 0x%02x", flags);
+ rsvp_integ_flags_tree = proto_item_add_subtree(ti2, TREE(TT_INTEGRITY_FLAGS));
+ proto_tree_add_text(rsvp_integ_flags_tree, tvb, offset2, 1,
+ decode_boolean_bitfield(flags, 0x01, 8, "Handshake capable", "Handshake not capable"));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 6,
+ "Key Identifier: %s", tvb_bytes_to_str(tvb, offset2+2, 6));
+ sequence_number = tvb_get_ntohl(tvb, offset2+8);
+ sequence_number <<= 32;
+ sequence_number = tvb_get_ntohl(tvb, offset2+12);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 8,
+ "Sequence Number: %" PRIu64, sequence_number);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, obj_length - 20,
+ "Hash: %s", tvb_bytes_to_str(tvb, offset2+16, obj_length - 20));
+}
+
+/*------------------------------------------------------------------------------
+ * POLICY
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_policy (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_POLICY));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: %u", type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+}
+
+/*------------------------------------------------------------------------------
+ * LABEL_REQUEST
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_label_request (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_LABEL_REQUEST));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1: {
+ unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "L3PID: %s (0x%04x)",
+ val_to_str(l3pid, etype_vals, "Unknown"),
+ l3pid);
+ proto_item_set_text(ti, "LABEL REQUEST: Basic: L3PID: %s (0x%04x)",
+ val_to_str(l3pid, etype_vals, "Unknown"),
+ l3pid);
+ break;
+ }
+
+ case 2: {
+ unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
+ unsigned short min_vpi, min_vci, max_vpi, max_vci;
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2 (Label Request with ATM label Range)");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "L3PID: %s (0x%04x)",
+ val_to_str(l3pid, etype_vals, "Unknown"),
+ l3pid);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 1,
+ "M: %s Merge in Data Plane",
+ (tvb_get_guint8(tvb, offset2+4) & 0x80) ?
+ "1: Can" : "0: Cannot");
+ min_vpi = tvb_get_ntohs(tvb, offset2+4) & 0x7f;
+ min_vci = tvb_get_ntohs(tvb, offset2+6);
+ max_vpi = tvb_get_ntohs(tvb, offset2+8) & 0x7f;
+ max_vci = tvb_get_ntohs(tvb, offset2+10);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2,
+ "Min VPI: %d", min_vpi);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
+ "Min VCI: %d", min_vci);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 2,
+ "Max VPI: %d", max_vpi);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+10, 2,
+ "Max VCI: %d", max_vci);
+ proto_item_set_text(ti, "LABEL REQUEST: ATM: L3PID: %s (0x%04x). VPI/VCI: Min: %d/%d, Max: %d/%d. %s Merge. ",
+ val_to_str(l3pid, etype_vals, "Unknown"), l3pid,
+ min_vpi, min_vci, max_vpi, max_vci,
+ (tvb_get_guint8(tvb, offset2+4) & 0x80) ? "Can" : "Cannot");
+ break;
+ }
+
+ case 3: {
+ guint16 l3pid = tvb_get_ntohs(tvb, offset2+2);
+ guint32 min_dlci, max_dlci, dlci_len, dlci_len_code;
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2 (Label Request with ATM label Range)");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "L3PID: %s (0x%04x)",
+ val_to_str(l3pid, etype_vals, "Unknown"),
+ l3pid);
+ dlci_len_code = (tvb_get_ntohs(tvb, offset2+4) & 0x0180) >> 7;
+ min_dlci = tvb_get_ntohl(tvb, offset2+4) & 0x7fffff;
+ max_dlci = tvb_get_ntohl(tvb, offset2+8) & 0x7fffff;
+ switch(dlci_len_code) {
+ case 0:
+ /* 10-bit DLCIs */
+ dlci_len = 10;
+ min_dlci &= 0x3ff;
+ max_dlci &= 0x3ff;
+ case 2:
+ dlci_len = 23;
+ default:
+ dlci_len = 0;
+ min_dlci = 0;
+ max_dlci = 0;
+ }
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2,
+ "DLCI Length: %s (%d)",
+ dlci_len==10 ? "10 bits" :
+ dlci_len==23 ? "23 bits" :
+ "INVALID", dlci_len_code);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 3,
+ "Min DLCI: %d", min_dlci);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 2,
+ "Max DLCI: %d", max_dlci);
+ proto_item_set_text(ti, "LABEL REQUEST: Frame: L3PID: %s (0x%04x). DLCI Len: %s. Min DLCI: %d. Max DLCI: %d",
+ val_to_str(l3pid, etype_vals, "Unknown"), l3pid,
+ dlci_len==10 ? "10 bits" :
+ dlci_len==23 ? "23 bits" :
+ "INVALID", min_dlci, max_dlci);
+ break;
+ }
+ case 4: {
+ unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
+ unsigned char lsp_enc = tvb_get_guint8(tvb,offset2);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 4 (Generalized Label Request)");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "LSP Encoding Type: %s",
+ val_to_str(lsp_enc, gmpls_lsp_enc_str, "Unknown (%d)"));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
+ "Switching Type: %s",
+ val_to_str(tvb_get_guint8(tvb,offset2+1),
+ gmpls_switching_type_str, "Unknown (%d)"));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
+ "G-PID: %s (0x%0x)",
+ val_to_str(l3pid, gmpls_gpid_str,
+ val_to_str(l3pid, etype_vals,
+ "Unknown G-PID(0x%04x)")),
+ l3pid);
+ proto_item_set_text(ti, "LABEL REQUEST: Generalized: LSP Encoding=%s, "
+ "Switching Type=%s, G-PID=%s ",
+ val_to_str(lsp_enc, gmpls_lsp_enc_str, "Unknown (%d)"),
+ val_to_str(tvb_get_guint8(tvb,offset2+1),
+ gmpls_switching_type_str, "Unknown (%d)"),
+ val_to_str(l3pid, gmpls_gpid_str,
+ val_to_str(l3pid, etype_vals,
+ "Unknown (0x%04x)")));
+ break;
+ }
+
+ default: {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * LABEL
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_label (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ int mylen, i;
+ char *name;
+
+ name = (class==RSVP_CLASS_SUGGESTED_LABEL ? "SUGGESTED LABEL":
+ (class==RSVP_CLASS_UPSTREAM_LABEL ? "UPSTREAM LABEL":
+ "LABEL"));
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_LABEL));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ mylen = obj_length - 4;
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 (Packet Label)");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Label: %u",
+ tvb_get_ntohl(tvb, offset2));
+ proto_item_set_text(ti, "%s: %d", name,
+ tvb_get_ntohl(tvb, offset2));
+ break;
+
+ case 2:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2 (Generalized Label)");
+ proto_item_set_text(ti, "%s: Generalized: ", name);
+ for (i = 0; i < mylen; i += 4) {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+i, 4,
+ "Generalized Label: %u",
+ tvb_get_ntohl(tvb, offset2+i));
+ if (i < 16) {
+ proto_item_append_text(ti, "%d%s",
+ tvb_get_ntohl(tvb, offset2+i),
+ i+4<mylen?", ":"");
+ } else if (i == 16) {
+ proto_item_append_text(ti, "...");
+ }
+ }
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * SESSION ATTRIBUTE
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_session_attribute (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ guint8 flags;
+ guint8 name_len;
+ proto_tree *ti2, *rsvp_sa_flags_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_SESSION_ATTRIBUTE));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1:
+ case 7:
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: %u - IPv4 LSP (%sResource Affinities)",
+ type, (type == 1) ? "" : "No ");
+
+ if (type == 1) {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Exclude-Any: 0x%0x", tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
+ "Include-Any: 0x%0x", tvb_get_ntohl(tvb, offset2+4));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
+ "Include-All: 0x%0x", tvb_get_ntohl(tvb, offset2+8));
+ offset2 = offset2+12;
+ }
+
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
+ "Setup priority: %u",
+ tvb_get_guint8(tvb, offset2));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
+ "Hold priority: %u",
+ tvb_get_guint8(tvb, offset2+1));
+ flags = tvb_get_guint8(tvb, offset2+2);
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 1,
+ "Flags: 0x%02x", flags);
+ rsvp_sa_flags_tree = proto_item_add_subtree(ti2,
+ TREE(TT_SESSION_ATTRIBUTE_FLAGS));
+ proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
+ decode_boolean_bitfield(flags, 0x01, 8,
+ "Local protection desired",
+ "Local protection not desired"));
+ proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
+ decode_boolean_bitfield(flags, 0x02, 8,
+ "Label recording desired",
+ "Label recording not desired"));
+ proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
+ decode_boolean_bitfield(flags, 0x04, 8,
+ "SE style desired",
+ "SE style not desired"));
+ proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
+ decode_boolean_bitfield(flags, 0x08, 8,
+ "Bandwidth protection desired",
+ "Bandwidth protection not desired"));
+ proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
+ decode_boolean_bitfield(flags, 0x10, 8,
+ "Node protection desired",
+ "Node protection not desired"));
+
+ name_len = tvb_get_guint8(tvb, offset2+3);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+3, 1,
+ "Name length: %u", name_len);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, name_len,
+ "Name: %s",
+ tvb_format_text(tvb, offset2+4, name_len));
+
+ proto_item_set_text(ti, "SESSION ATTRIBUTE: SetupPrio %d, HoldPrio %d, %s%s%s%s%s [%s]",
+ tvb_get_guint8(tvb, offset2),
+ tvb_get_guint8(tvb, offset2+1),
+ flags &0x01 ? "Local Protection, " : "",
+ flags &0x02 ? "Label Recording, " : "",
+ flags &0x04 ? "SE Style, " : "",
+ flags &0x08 ? "Bandwidth Protection, " : "",
+ flags &0x10 ? "Node Protection, " : "",
+ name_len ? tvb_format_text(tvb, offset2+4, name_len) : "");
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * EXPLICIT ROUTE AND RECORD ROUTE SUBOBJECTS
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree,
+ tvbuff_t *tvb,
+ int offset, int obj_length, int class)
+{
+ int i, j, k, l, flags;
+ proto_tree *ti2, *rsvp_ro_subtree, *rsvp_rro_flags_subtree;
+ int tree_type;
+
+ switch(class) {
+ case RSVP_CLASS_EXPLICIT_ROUTE:
+ tree_type = TREE(TT_EXPLICIT_ROUTE_SUBOBJ);
+ break;
+ case RSVP_CLASS_RECORD_ROUTE:
+ tree_type = TREE(TT_RECORD_ROUTE_SUBOBJ);
+ break;
+ default:
+ /* Bail out */
+ return;
+ }
+
+ for (i=1, l = 0; l < obj_length - 4; i++) {
+ j = tvb_get_guint8(tvb, offset+l) & 0x7f;
+ switch(j) {
+ case 1: /* IPv4 */
+ k = tvb_get_guint8(tvb, offset+l) & 0x80;
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset+l, 8,
+ "IPv4 Subobject - %s%s",
+ ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
+ class == RSVP_CLASS_EXPLICIT_ROUTE ?
+ (k ? ", Loose" : ", Strict") : "");
+ rsvp_ro_subtree =
+ proto_item_add_subtree(ti2, tree_type);
+ if (class == RSVP_CLASS_EXPLICIT_ROUTE)
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ k ? "Loose Hop " : "Strict Hop");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ "Type: 1 (IPv4)");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
+ "Length: %u",
+ tvb_get_guint8(tvb, offset+l+1));
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 4,
+ "IPv4 hop: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)));
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+6, 1,
+ "Prefix length: %u",
+ tvb_get_guint8(tvb, offset+l+6));
+ if (i < 4) {
+ proto_item_append_text(ti, "IPv4 %s%s",
+ ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
+ k ? " [L]" : "");
+ }
+ if (class == RSVP_CLASS_RECORD_ROUTE) {
+ flags = tvb_get_guint8(tvb, offset+l+7);
+ if (flags&0x10) {
+ proto_item_append_text(ti, " (Node-id)");
+ proto_item_append_text(ti2, " (Node-id)");
+ }
+ if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
+ if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
+ if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
+ if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
+ ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+7, 1,
+ "Flags: 0x%02x", flags);
+ rsvp_rro_flags_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
+ decode_boolean_bitfield(flags, 0x01, 8,
+ "Local Protection Available",
+ "Local Protection Not Available"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
+ decode_boolean_bitfield(flags, 0x02, 8,
+ "Local Protection In Use",
+ "Local Protection Not In Use"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
+ decode_boolean_bitfield(flags, 0x04, 8,
+ "Bandwidth Protection Available",
+ "Bandwidth Protection Not Available"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
+ decode_boolean_bitfield(flags, 0x08, 8,
+ "Node Protection Available",
+ "Node Protection Not Available"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
+ decode_boolean_bitfield(flags, 0x10, 8,
+ "Address Specifies a Node-id Address",
+ "Address Doesn't Specify a Node-id Address"));
+ }
+
+ break;
+
+ case 2: /* IPv6 */
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset+l, 20,
+ "IPv6 Subobject");
+ rsvp_ro_subtree =
+ proto_item_add_subtree(ti2, tree_type);
+ k = tvb_get_guint8(tvb, offset+l) & 0x80;
+ if (class == RSVP_CLASS_EXPLICIT_ROUTE)
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ k ? "Loose Hop " : "Strict Hop");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ "Type: 2 (IPv6)");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
+ "Length: %u",
+ tvb_get_guint8(tvb, offset+l+1));
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 16,
+ "IPv6 hop: %s",
+ ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset+l+2, 16)));
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+18, 1,
+ "Prefix length: %u",
+ tvb_get_guint8(tvb, offset+l+18));
+ if (i < 4) {
+ proto_item_append_text(ti, "IPv6 [...]%s", k ? " [L]":"");
+ }
+ if (class == RSVP_CLASS_RECORD_ROUTE) {
+ flags = tvb_get_guint8(tvb, offset+l+19);
+ if (flags&0x10) {
+ proto_item_append_text(ti, " (Node-id)");
+ proto_item_append_text(ti2, " (Node-id)");
+ }
+ if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
+ if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
+ if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
+ if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
+ ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+19, 1,
+ "Flags: 0x%02x", flags);
+ rsvp_rro_flags_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
+ decode_boolean_bitfield(flags, 0x01, 8,
+ "Local Protection Available",
+ "Local Protection Not Available"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
+ decode_boolean_bitfield(flags, 0x02, 8,
+ "Local Protection In Use",
+ "Local Protection Not In Use"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
+ decode_boolean_bitfield(flags, 0x04, 8,
+ "Backup Tunnel Has Bandwidth",
+ "Backup Tunnel Does Not Have Bandwidth"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
+ decode_boolean_bitfield(flags, 0x08, 8,
+ "Backup Tunnel Goes To Next-Next-Hop",
+ "Backup Tunnel Goes To Next-Hop"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
+ decode_boolean_bitfield(flags, 0x10, 8,
+ "Address Specifies a Node-id Address",
+ "Address Doesn't Specify a Node-id Address"));
+ }
+
+ break;
+
+ case 3: /* Label */
+ k = tvb_get_guint8(tvb, offset+l) & 0x80;
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset+l, 8,
+ "Label Subobject - %d, %s",
+ tvb_get_ntohl(tvb, offset+l+4),
+ class == RSVP_CLASS_EXPLICIT_ROUTE ?
+ (k ? "Loose" : "Strict") : "");
+ rsvp_ro_subtree =
+ proto_item_add_subtree(ti2, tree_type);
+ if (class == RSVP_CLASS_EXPLICIT_ROUTE)
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ k ? "Loose Hop " : "Strict Hop");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ "Type: 3 (Label)");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
+ "Length: %u",
+ tvb_get_guint8(tvb, offset+l+1));
+ if (class == RSVP_CLASS_RECORD_ROUTE) {
+ flags = tvb_get_guint8(tvb, offset+l+2);
+ if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
+ if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
+ if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
+ if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
+ ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
+ "Flags: 0x%02x", flags);
+ rsvp_rro_flags_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
+ decode_boolean_bitfield(flags, 0x01, 8,
+ "Local Protection Available",
+ "Local Protection Not Available"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
+ decode_boolean_bitfield(flags, 0x02, 8,
+ "Local Protection In Use",
+ "Local Protection Not In Use"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
+ decode_boolean_bitfield(flags, 0x04, 8,
+ "Backup Tunnel Has Bandwidth",
+ "Backup Tunnel Does Not Have Bandwidth"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
+ decode_boolean_bitfield(flags, 0x08, 8,
+ "Backup Tunnel Goes To Next-Next-Hop",
+ "Backup Tunnel Goes To Next-Hop"));
+ }
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+3, 1,
+ "C-Type: %u",
+ tvb_get_guint8(tvb, offset+l+3));
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+4, 4,
+ "Label: %d",
+ tvb_get_ntohl(tvb, offset+l+4));
+ if (i < 4) {
+ proto_item_append_text(ti, "Label %d%s",
+ tvb_get_ntohl(tvb, offset+l+4),
+ k ? " [L]":"");
+ }
+ break;
+
+ case 4: /* Unnumbered Interface-ID */
+ k = tvb_get_guint8(tvb, offset+l) & 0x80;
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset+l, 8,
+ "Unnumbered Interface-ID - %s, %d, %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)),
+ tvb_get_ntohl(tvb, offset+l+8),
+ class == RSVP_CLASS_EXPLICIT_ROUTE ?
+ (k ? "Loose" : "Strict") : "");
+ rsvp_ro_subtree =
+ proto_item_add_subtree(ti2, tree_type);
+ if (class == RSVP_CLASS_EXPLICIT_ROUTE)
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ k ? "Loose Hop " : "Strict Hop");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ "Type: 4 (Unnumbered Interface-ID)");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
+ "Length: %u",
+ tvb_get_guint8(tvb, offset+l+1));
+ if (class == RSVP_CLASS_RECORD_ROUTE) {
+ flags = tvb_get_guint8(tvb, offset+l+2);
+ if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
+ if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
+ if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
+ if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
+ ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
+ "Flags: 0x%02x", flags);
+ rsvp_rro_flags_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
+ decode_boolean_bitfield(flags, 0x01, 8,
+ "Local Protection Available",
+ "Local Protection Not Available"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
+ decode_boolean_bitfield(flags, 0x02, 8,
+ "Local Protection In Use",
+ "Local Protection Not In Use"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
+ decode_boolean_bitfield(flags, 0x04, 8,
+ "Backup Tunnel Has Bandwidth",
+ "Backup Tunnel Does Not Have Bandwidth"));
+ proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
+ decode_boolean_bitfield(flags, 0x08, 8,
+ "Backup Tunnel Goes To Next-Next-Hop",
+ "Backup Tunnel Goes To Next-Hop"));
+ }
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+4, 4,
+ "Router-ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)));
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+8, 4,
+ "Interface-ID: %d",
+ tvb_get_ntohl(tvb, offset+l+8));
+ if (i < 4) {
+ proto_item_append_text(ti, "Unnum %s/%d%s",
+ ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)),
+ tvb_get_ntohl(tvb, offset+l+8),
+ k ? " [L]":"");
+ }
+
+ break;
+
+ case 32: /* AS */
+ if (class == RSVP_CLASS_RECORD_ROUTE) goto defaultsub;
+ k = tvb_get_ntohs(tvb, offset+l+2);
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset+l, 4,
+ "Autonomous System %u",
+ k);
+ rsvp_ro_subtree =
+ proto_item_add_subtree(ti2, tree_type);
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ "Type: 32 (Autonomous System Number)");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
+ "Length: %u",
+ tvb_get_guint8(tvb, offset+l+1));
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 2,
+ "Autonomous System %u", k);
+ if (i < 4) {
+ proto_item_append_text(ti, "AS %d",
+ tvb_get_ntohs(tvb, offset+l+2));
+ }
+
+ break;
+
+ default: /* Unknown subobject */
+ defaultsub:
+ k = tvb_get_guint8(tvb, offset+l) & 0x80;
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset+l,
+ tvb_get_guint8(tvb, offset+l+1),
+ "Unknown subobject: %d", j);
+ rsvp_ro_subtree =
+ proto_item_add_subtree(ti2, tree_type);
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ k ? "Loose Hop " : "Strict Hop");
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
+ "Type: %u (Unknown)", j);
+ proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
+ "Length: %u",
+ tvb_get_guint8(tvb, offset+l+1));
+
+ }
+
+ l += tvb_get_guint8(tvb, offset+l+1);
+ if (l < obj_length - 4) {
+ if (i < 4)
+ proto_item_append_text(ti, ", ");
+ else if (i==4)
+ proto_item_append_text(ti, "...");
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * EXPLICIT ROUTE OBJECT
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_explicit_route (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ /* int offset2 = offset + 4; */
+ proto_tree *rsvp_object_tree;
+ /* int mylen, i, j, k, l; */
+ /* proto_tree *ti2, *rsvp_ero_subtree; */
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_EXPLICIT_ROUTE));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ /* mylen = obj_length - 4; */
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ proto_item_set_text(ti, "EXPLICIT ROUTE: ");
+
+ dissect_rsvp_ero_rro_subobjects(ti, rsvp_object_tree, tvb,
+ offset + 4, obj_length, class);
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * RECORD ROUTE OBJECT
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_record_route (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ /* int offset2 = offset + 4; */
+ proto_tree *rsvp_object_tree;
+ /* int mylen, i, j, l; */
+ /* proto_tree *ti2, *rsvp_rro_subtree; */
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_RECORD_ROUTE));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "RECORD ROUTE: ");
+ /* mylen = obj_length - 4; */
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+
+ dissect_rsvp_ero_rro_subobjects(ti, rsvp_object_tree, tvb,
+ offset + 4, obj_length, class);
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * MESSAGE ID
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_message_id (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_MESSAGE_ID));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
+ "Flags: %d", tvb_get_guint8(tvb, offset+4));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
+ "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
+ "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
+ proto_item_set_text(ti, "MESSAGE-ID: %d %s",
+ tvb_get_ntohl(tvb, offset+8),
+ tvb_get_guint8(tvb, offset+4) & 1 ? "(Ack Desired)" : "");
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * MESSAGE ID ACK
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_message_id_ack (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_MESSAGE_ID_ACK));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
+ "Flags: %d", tvb_get_guint8(tvb, offset+4));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
+ "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
+ "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
+ proto_item_set_text(ti, "MESSAGE-ID ACK: %d", tvb_get_ntohl(tvb, offset+8));
+ break;
+
+ case 2:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 2");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
+ "Flags: %d", tvb_get_guint8(tvb, offset+4));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
+ "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
+ "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
+ proto_item_set_text(ti, "MESSAGE-ID NACK: %d", tvb_get_ntohl(tvb, offset+8));
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * MESSAGE ID LIST
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_message_id_list (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ int mylen;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_MESSAGE_ID_LIST));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
+ "Flags: %d", tvb_get_guint8(tvb, offset+4));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
+ "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
+ for (mylen = 8; mylen < obj_length; mylen += 4)
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen, 4,
+ "Message-ID: %d", tvb_get_ntohl(tvb, offset+mylen));
+ proto_item_set_text(ti, "MESSAGE-ID LIST: %d IDs",
+ (obj_length - 8)/4);
+ break;
+
+ default:
+ mylen = obj_length - 4;
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * HELLO
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_hello (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_HELLO_OBJ));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ switch(type) {
+ case 1:
+ case 2:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-Type: 1 - HELLO %s object",
+ type==1 ? "REQUEST" : "ACK");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 4,
+ "Source Instance: 0x%x",tvb_get_ntohl(tvb, offset+4));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
+ "Destination Instance: 0x%x",tvb_get_ntohl(tvb, offset+8));
+ proto_item_append_text(ti, ": %s. Src Instance: 0x%0x. Dest Instance: 0x%0x. ",
+ type==1 ? "REQUEST" : "ACK",
+ tvb_get_ntohl(tvb, offset+4),
+ tvb_get_ntohl(tvb, offset+8));
+ break;
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-Type: %d - UNKNOWN", type);
+ break;
+ };
+}
+
+/*------------------------------------------------------------------------------
+ * DCLASS
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_dclass (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ int mylen;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DCLASS));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "DCLASS: ");
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ for (mylen = 4; mylen < obj_length; mylen += 4) {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen+3, 1,
+ "DSCP: %s",
+ val_to_str(tvb_get_guint8(tvb, offset+mylen+3),
+ dscp_vals, "Unknown (%d)"));
+ proto_item_append_text(ti, "%d%s",
+ tvb_get_guint8(tvb, offset+mylen+3)>>2,
+ mylen==obj_length-4 ? "":
+ mylen<16 ? ", ":
+ mylen==16 ? ", ..." : "");
+ }
+ break;
+
+ default:
+ mylen = obj_length - 4;
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * ADMINISTRATIVE STATUS
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_admin_status (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ proto_tree *ti2, *rsvp_admin_subtree;
+ int mylen;
+ guint32 status;
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_ADMIN_STATUS));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "ADMIN STATUS: ");
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ status = tvb_get_ntohl(tvb, offset2);
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Admin Status: 0x%08x", status);
+ rsvp_admin_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_ADMIN_STATUS_FLAGS));
+ proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
+ decode_boolean_bitfield(status, 0x80000000, 32,
+ "R: Reflect",
+ "R: Do not reflect"));
+ proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
+ decode_boolean_bitfield(status, 0x04, 32,
+ "T: Testing",
+ "T: "));
+ proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
+ decode_boolean_bitfield(status, 0x02, 32,
+ "A: Administratively Down",
+ "A: "));
+ proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
+ decode_boolean_bitfield(status, 0x01, 32,
+ "D: Delete In Progress",
+ "D: "));
+ proto_item_set_text(ti, "ADMIN-STATUS: %s %s %s %s",
+ (status & (1<<31)) ? "Reflect" : "",
+ (status & (1<<2)) ? "Testing" : "",
+ (status & (1<<1)) ? "Admin-Down" : "",
+ (status & (1<<0)) ? "Deleting" : "");
+ break;
+
+ default:
+ mylen = obj_length - 4;
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * LSP TUNNEL INTERFACE ID
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_lsp_tunnel_if_id (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_LSP_TUNNEL_IF_ID));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "LSP INTERFACE-ID: ");
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 - IPv4");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Router ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
+ "Interface ID: %u", tvb_get_ntohl(tvb, offset2+4));
+ proto_item_set_text(ti, "LSP INTERFACE-ID: IPv4, Router-ID %s, Interface-ID %d",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)),
+ tvb_get_ntohl(tvb, offset2+4));
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * GENERALIZED UNI
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_gen_uni (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+ int mylen, i, j, k, l, m;
+ proto_tree *ti2, *rsvp_gen_uni_subtree;
+ int s_len, s_class, s_type;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_GEN_UNI));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "GENERALIZED UNI: ");
+
+ mylen = obj_length - 4;
+ switch(type) {
+ case 1: {
+ char *c;
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ for (i=1, l = 0; l < mylen; i++) {
+ j = tvb_get_guint8(tvb, offset2+l+2);
+ switch(j) {
+ case 1:
+ case 2: /* We do source and destination TNA together */
+ c = (j==1) ? "Source" : "Destination";
+ k = tvb_get_guint8(tvb, offset2+l+3);
+ switch(k) {
+ case 1:
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2+l, 8,
+ "%s IPv4 TNA - %s", c,
+ ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
+ rsvp_gen_uni_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
+ "Class: %d (%s)", j, c);
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
+ "Type: 1 (IPv4)");
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
+ "Length: %u",
+ tvb_get_ntohs(tvb, offset2+l));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 4,
+ "IPv4 hop: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
+ if (i < 4) {
+ proto_item_append_text(ti, "%s IPv4 %s", c,
+ ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
+ }
+ break;
+
+ case 2:
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2+l, 20,
+ "%s IPv6 TNA", c);
+ rsvp_gen_uni_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
+ "Class: %d (%s)", j, c);
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
+ "Type: 2 (IPv6)");
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
+ "Length: %u",
+ tvb_get_ntohs(tvb, offset2+l));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 4,
+ "Data");
+ if (i < 4) {
+ proto_item_append_text(ti, "%s IPv6", c);
+ }
+ break;
+
+ case 3:
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2+l, tvb_get_ntohs(tvb, offset2+l),
+ "%s NSAP TNA", c);
+ rsvp_gen_uni_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
+ "Class: %d (%s)", j, c);
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
+ "Type: 3 (NSAP)");
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
+ "Length: %u",
+ tvb_get_ntohs(tvb, offset2+l));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4,
+ tvb_get_ntohs(tvb, offset2+l)-4,
+ "Data");
+ if (i < 4) {
+ proto_item_append_text(ti, "%s NSAP", c);
+ }
+ break;
+
+ default:
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2+l, tvb_get_ntohs(tvb, offset2+l),
+ "%s UNKNOWN TNA", c);
+ rsvp_gen_uni_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
+ "Class: %d (%s)", j, c);
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
+ "Type: %d (UNKNOWN)", j);
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
+ "Length: %u",
+ tvb_get_ntohs(tvb, offset2+l));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4,
+ tvb_get_ntohs(tvb, offset2+l)-4,
+ "Data");
+ if (i < 4) {
+ proto_item_append_text(ti, "%s UNKNOWN", c);
+ }
+ break;
+ }
+ break;
+
+ case 3: /* Diversity subobject */
+ k = tvb_get_guint8(tvb, offset2+l+3);
+ switch(k) {
+ default:
+ case 1:
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2+l, tvb_get_ntohs(tvb, offset2+l),
+ "Diversity Subobject");
+ rsvp_gen_uni_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
+ "Class: %d (Diversity)", j);
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
+ "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
+ "Length: %u",
+ tvb_get_ntohs(tvb, offset2+l));
+ m = tvb_get_guint8(tvb, offset2+l+4) >> 4;
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
+ "Diversity: %d - %s", m,
+ val_to_str(m, ouni_guni_diversity_str, "Unknown"));
+ s_len = tvb_get_ntohs(tvb, offset2+l+8);
+ s_class = tvb_get_guint8(tvb, offset2+l+10);
+ s_type = tvb_get_guint8(tvb, offset2+l+11);
+ ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8,
+ s_len, "Session");
+ dissect_rsvp_session(ti2, tvb, offset2+l+8, s_len, s_class, s_type,
+ val_to_str(s_class, rsvp_class_vals, "Unknown"));
+ offset2 += s_len;
+ s_len = tvb_get_ntohs(tvb, offset2+l+8);
+ s_class = tvb_get_guint8(tvb, offset2+l+10);
+ s_type = tvb_get_guint8(tvb, offset2+l+11);
+ ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8,
+ s_len, "Template");
+ dissect_rsvp_template_filter(ti2, tvb, offset2+l+8, s_len, s_class, s_type,
+ val_to_str(s_class, rsvp_class_vals, "Unknown"));
+
+ if (i < 4) {
+ proto_item_append_text(ti, "Diversity");
+ }
+ break;
+
+ }
+ break;
+
+ case 4: /* Egress Label */
+ k = tvb_get_guint8(tvb, offset2+l+3);
+ switch(k) {
+ default:
+ case 1:
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2+l, tvb_get_ntohs(tvb, offset2+l),
+ "Egress Label Subobject");
+ rsvp_gen_uni_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
+ "Class: %d (Egress Label)", j);
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
+ "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
+ "Length: %u",
+ tvb_get_ntohs(tvb, offset2+l));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
+ "Direction: %s",
+ decode_boolean_bitfield(
+ tvb_get_guint8(tvb, offset2+l+4), 0x80, 8,
+ "U: 1 - Upstream label/port ID",
+ "U: 0 - Downstream label/port ID"));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+7, 1,
+ "Label type: %u", tvb_get_guint8(tvb, offset2+l+7));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 4,
+ "Logical Port ID: %u", tvb_get_ntohl(tvb, offset2+l+8));
+ proto_item_append_text(ti2, ": %s, Label type %d, Port ID %d, Label ",
+ tvb_get_guint8(tvb, offset2+l+4) & 0x80 ?
+ "Upstream" : "Downstream",
+ tvb_get_guint8(tvb, offset2+l+7),
+ tvb_get_ntohl(tvb, offset2+l+8));
+ for (j=12; j < tvb_get_ntohs(tvb, offset2+l); j+=4) {
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 4,
+ "Label: %u", tvb_get_ntohl(tvb, offset2+l+j));
+ proto_item_append_text(ti2, "%u ", tvb_get_ntohl(tvb, offset2+l+j));
+ }
+ if (i < 4) {
+ proto_item_append_text(ti, "Egress Label");
+ }
+ break;
+ }
+ break;
+
+ case 5: /* Service Level */
+ k = tvb_get_guint8(tvb, offset2+l+3);
+ switch(k) {
+ default:
+ case 1:
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2+l, tvb_get_ntohs(tvb, offset2+l),
+ "Service Level Subobject");
+ rsvp_gen_uni_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
+ "Class: %d (Egress Label)", j);
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
+ "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
+ "Length: %u",
+ tvb_get_ntohs(tvb, offset2+l));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
+ "Service Level: %u", tvb_get_guint8(tvb, offset2+l+4));
+ proto_item_append_text(ti2, ": %u", tvb_get_guint8(tvb, offset2+l+4));
+ if (i < 4) {
+ proto_item_append_text(ti, "Service Level %d", tvb_get_guint8(tvb, offset2+l+4));
+ }
+ break;
+ }
+ break;
+
+ default: /* Unknown subobject */
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
+ offset2+l,
+ tvb_get_ntohs(tvb, offset2+l),
+ "Unknown subobject: %u",
+ j);
+ rsvp_gen_uni_subtree =
+ proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 1,
+ "Type: %u (Unknown)", j);
+ proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+1, 1,
+ "Length: %u",
+ tvb_get_guint8(tvb, offset2+l+1));
+
+ }
+
+ l += tvb_get_guint8(tvb, offset2+l+1);
+ if (l < mylen) {
+ if (i < 4)
+ proto_item_append_text(ti, ", ");
+ else if (i==4)
+ proto_item_append_text(ti, "...");
+ }
+ }
+ break;
+ }
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
+ "Data (%d bytes)", mylen);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * RESTART CAPABILITY
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_restart_cap (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_RESTART_CAP));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "RESTART CAPABILITY: ");
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Restart Time: %d ms",
+ tvb_get_ntohl(tvb, offset2));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
+ "Recovery Time: %d ms",
+ tvb_get_ntohl(tvb, offset2+4));
+ proto_item_append_text(ti, "Restart Time: %d ms. Recovery Time: %d ms.",
+ tvb_get_ntohl(tvb, offset2), tvb_get_ntohl(tvb, offset2+4));
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * PROTECTION INFORMATION
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_protection_info (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ int offset2 = offset + 4;
+ proto_tree *rsvp_object_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_PROTECTION_INFO));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "PROTECTION_INFO: ");
+ switch(type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: 1 - IPv4");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
+ "Router ID: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
+ "Interface ID: %u", tvb_get_ntohl(tvb, offset2+4));
+ proto_item_append_text(ti, "Router-ID %s, Interface-ID %d",
+ ip_to_str(tvb_get_ptr(tvb, offset2, 4)),
+ tvb_get_ntohl(tvb, offset2+4));
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * FAST REROUTE
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_fast_reroute (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ proto_tree *rsvp_object_tree;
+ guint8 flags;
+ proto_tree *ti2, *rsvp_frr_flags_tree;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_FAST_REROUTE));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "FAST_REROUTE: ");
+ switch(type) {
+ case 1:
+ case 7:
+ if ((type==1 && obj_length!=24) || (type==7 && obj_length!=20)) {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, obj_length,
+ "<<<Invalid length: cannot decode>>>");
+ proto_item_append_text(ti, "Invalid length");
+ break;
+ }
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: %u", type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
+ "Setup Priority: %d", tvb_get_guint8(tvb, offset+4));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 1,
+ "Hold Priority: %d", tvb_get_guint8(tvb, offset+5));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+6, 1,
+ "Hop Limit: %d", tvb_get_guint8(tvb, offset+6));
+
+ flags = tvb_get_guint8(tvb, offset+7);
+ ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset+7, 1,
+ "Flags: 0x%02x", flags);
+ rsvp_frr_flags_tree = proto_item_add_subtree(ti2,
+ TREE(TT_FAST_REROUTE_FLAGS));
+ proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
+ decode_boolean_bitfield(flags, 0x01, 8,
+ "One-to-One Backup desired",
+ "One-to-One Backup not desired"));
+ proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
+ decode_boolean_bitfield(flags, 0x02, 8,
+ "Facility Backup desired",
+ "Facility Backup not desired"));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
+ "Bandwidth: %.10g", tvb_get_ntohieee_float(tvb, offset+8));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+12, 4,
+ "Exclude-Any: 0x%0x", tvb_get_ntohl(tvb, offset+12));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+16, 4,
+ "Include-Any: 0x%0x", tvb_get_ntohl(tvb, offset+16));
+ if (type==1) {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+20, 4,
+ "Include-All: 0x%0x", tvb_get_ntohl(tvb, offset+20));
+ }
+
+ proto_item_append_text(ti, "%s%s",
+ flags &0x01 ? "One-to-One Backup, " : "",
+ flags &0x02 ? "Facility Backup" : "");
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * DETOUR
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_detour (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str)
+{
+ proto_tree *rsvp_object_tree;
+ int remaining_length, count;
+ int iter;
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DETOUR));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "DETOUR: ");
+ switch(type) {
+ case 7:
+ iter = 0;
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: %u", type);
+ for (remaining_length = obj_length - 4, count = 1;
+ remaining_length > 0; remaining_length -= 8, count++) {
+ if (remaining_length < 8) {
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+remaining_length,
+ obj_length-remaining_length,
+ "<<<Invalid length: cannot decode>>>");
+ proto_item_append_text(ti, "Invalid length");
+ break;
+ }
+ iter++;
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
+ "PLR ID %d: %s", count,
+ ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
+ iter++;
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
+ "Avoid Node ID %d: %s", count,
+ ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
+ }
+ break;
+
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
+ "C-type: Unknown (%u)",
+ type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * DIFFSERV
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_diffserv (proto_tree *ti, tvbuff_t *tvb,
+ int offset, int obj_length,
+ int class, int type,
+ char *type_str
+ )
+{
+ proto_tree *rsvp_object_tree;
+ int mapnb, count;
+ int *hfindexes[] = {
+ &rsvp_filter[RSVPF_DIFFSERV_MAP],
+ &rsvp_filter[RSVPF_DIFFSERV_MAP_EXP],
+ &rsvp_filter[RSVPF_DIFFSERV_PHBID],
+ &rsvp_filter[RSVPF_DIFFSERV_PHBID_DSCP],
+ &rsvp_filter[RSVPF_DIFFSERV_PHBID_CODE],
+ &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT14],
+ &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT15]
+ };
+ gint *etts[] = {
+ &TREE(TT_DIFFSERV_MAP),
+ &TREE(TT_DIFFSERV_MAP_PHBID)
+ };
+
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DIFFSERV));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_item_set_text(ti, "DIFFSERV: ");
+ offset += 3;
+ switch (type) {
+ case 1:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
+ "C-type: 1 - E-LSP");
+ proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_DIFFSERV_MAPNB],
+ tvb, offset + 4, 1,
+ mapnb = tvb_get_guint8(tvb, offset + 4) & 15);
+ proto_item_append_text(ti, "E-LSP, %u MAP%s", mapnb,
+ (mapnb == 0) ? "" : "s");
+ offset += 5;
+
+ for (count = 0; count < mapnb; count++) {
+ dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
+ offset, hfindexes, etts);
+ offset += 4;
+ }
+ break;
+ case 2:
+ proto_item_append_text(ti, "L-LSP");
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
+ "C-type: 2 - L-LSP");
+ dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
+ offset + 3, hfindexes, etts);
+ break;
+ default:
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
+ "C-type: Unknown (%u)", type);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset + 1, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * Dissect a single RSVP message in a tree
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp_msg_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int tree_mode)
+{
+ proto_tree *rsvp_tree = NULL;
+ proto_tree *rsvp_header_tree;
+ proto_tree *rsvp_object_tree;
+ proto_tree *ti;
+ guint16 cksum, computed_cksum;
+ vec_t cksum_vec[1];
+ int offset = 0;
+ int len;
+ guint8 ver_flags;
+ guint8 message_type;
+ int session_off, tempfilt_off;
+ int msg_length;
+ int obj_length;
+ int offset2;
+
+ offset = 0;
+ len = 0;
+ ver_flags = tvb_get_guint8(tvb, 0);
+ msg_length = tvb_get_ntohs(tvb, 6);
+ message_type = tvb_get_guint8(tvb, 1);
+
+ ti = proto_tree_add_item(tree, proto_rsvp, tvb, offset, msg_length,
+ FALSE);
+ rsvp_tree = proto_item_add_subtree(ti, tree_mode);
+ proto_item_append_text(rsvp_tree, ": ");
+ proto_item_append_text(rsvp_tree, val_to_str(message_type, message_type_vals,
+ "Unknown (%u). "));
+ find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
+ if (session_off)
+ proto_item_append_text(rsvp_tree, summary_session(tvb, session_off));
+ if (tempfilt_off)
+ proto_item_append_text(rsvp_tree, summary_template(tvb, tempfilt_off));
+
+ ti = proto_tree_add_text(rsvp_tree, tvb, offset, 8, "RSVP Header. %s",
+ val_to_str(message_type, message_type_vals,
+ "Unknown Message (%u). "));
+ rsvp_header_tree = proto_item_add_subtree(ti, TREE(TT_HDR));
+
+ proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "RSVP Version: %u",
+ (ver_flags & 0xf0)>>4);
+ proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "Flags: %02x",
+ ver_flags & 0xf);
+ proto_tree_add_uint(rsvp_header_tree, rsvp_filter[RSVPF_MSG], tvb,
+ offset+1, 1, message_type);
+ switch (RSVPF_MSG + message_type) {
+
+ case RSVPF_PATH:
+ case RSVPF_RESV:
+ case RSVPF_PATHERR:
+ case RSVPF_RESVERR:
+ case RSVPF_PATHTEAR:
+ case RSVPF_RESVTEAR:
+ case RSVPF_RCONFIRM:
+ case RSVPF_RTEARCONFIRM:
+ case RSVPF_BUNDLE:
+ case RSVPF_ACK:
+ case RSVPF_SREFRESH:
+ case RSVPF_HELLO:
+ proto_tree_add_boolean_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + message_type], tvb,
+ offset+1, 1, 1);
+ break;
+
+ default:
+ proto_tree_add_protocol_format(rsvp_header_tree, proto_malformed, tvb, offset+1, 1,
+ "Invalid message type: %u", message_type);
+ return;
+ }
+
+ cksum = tvb_get_ntohs(tvb, offset+2);
+ if (!pinfo->fragmented && (int) tvb_length(tvb) >= msg_length) {
+ /* The packet isn't part of a fragmented datagram and isn't
+ truncated, so we can checksum it. */
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, msg_length);
+ cksum_vec[0].len = msg_length;
+ computed_cksum = in_cksum(&cksum_vec[0], 1);
+ if (computed_cksum == 0) {
+ proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
+ "Message Checksum: 0x%04x (correct)",
+ cksum);
+ } else {
+ proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
+ "Message Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ cksum,
+ in_cksum_shouldbe(cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
+ "Message Checksum: 0x%04x",
+ cksum);
+ }
+ proto_tree_add_text(rsvp_header_tree, tvb, offset+4, 1,
+ "Sending TTL: %u",
+ tvb_get_guint8(tvb, offset+4));
+ proto_tree_add_text(rsvp_header_tree, tvb, offset+6, 2,
+ "Message length: %u", msg_length);
+
+ offset = 8;
+ len = 8;
+
+ if (message_type == RSVP_MSG_BUNDLE) {
+ /* Bundle message. Dissect component messages */
+ if (rsvp_bundle_dissect) {
+ int len = 8;
+ while (len < msg_length) {
+ gint sub_len;
+ tvbuff_t *tvb_sub;
+ sub_len = tvb_get_ntohs(tvb, len+6);
+ tvb_sub = tvb_new_subset(tvb, len, sub_len, sub_len);
+ dissect_rsvp_msg_tree(tvb_sub, pinfo, rsvp_tree, TREE(TT_BUNDLE_COMPMSG));
+ len += sub_len;
+ }
+ } else {
+ proto_tree_add_text(rsvp_tree, tvb, offset, msg_length - len,
+ "Bundle Component Messages Not Dissected");
+ }
+ return;
+ }
+
+ while (len < msg_length) {
+ guint8 class;
+ guint8 type;
+ char *type_str;
+
+ obj_length = tvb_get_ntohs(tvb, offset);
+ class = tvb_get_guint8(tvb, offset+2);
+ type = tvb_get_guint8(tvb, offset+3);
+ type_str = val_to_str(class, rsvp_class_vals, "Unknown");
+ proto_tree_add_uint_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], tvb,
+ offset, obj_length, class);
+ ti = proto_tree_add_item(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(class)],
+ tvb, offset, obj_length, FALSE);
+
+ offset2 = offset+4;
+
+ switch(class) {
+
+ case RSVP_CLASS_SESSION:
+ dissect_rsvp_session(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_HOP:
+ dissect_rsvp_hop(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_TIME_VALUES:
+ dissect_rsvp_time_values(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_ERROR:
+ dissect_rsvp_error(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_SCOPE:
+ dissect_rsvp_scope(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_STYLE:
+ dissect_rsvp_style(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_CONFIRM:
+ dissect_rsvp_confirm(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_SENDER_TEMPLATE:
+ case RSVP_CLASS_FILTER_SPEC:
+ dissect_rsvp_template_filter(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_SENDER_TSPEC:
+ dissect_rsvp_tspec(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_FLOWSPEC:
+ dissect_rsvp_flowspec(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_ADSPEC:
+ dissect_rsvp_adspec(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_INTEGRITY:
+ dissect_rsvp_integrity(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_POLICY:
+ dissect_rsvp_policy(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_LABEL_REQUEST:
+ dissect_rsvp_label_request(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_UPSTREAM_LABEL:
+ case RSVP_CLASS_SUGGESTED_LABEL:
+ case RSVP_CLASS_LABEL:
+ dissect_rsvp_label(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_SESSION_ATTRIBUTE:
+ dissect_rsvp_session_attribute(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_EXPLICIT_ROUTE:
+ dissect_rsvp_explicit_route(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_RECORD_ROUTE:
+ dissect_rsvp_record_route(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_MESSAGE_ID:
+ dissect_rsvp_message_id(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_MESSAGE_ID_ACK:
+ dissect_rsvp_message_id_ack(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_MESSAGE_ID_LIST:
+ dissect_rsvp_message_id_list(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_HELLO:
+ dissect_rsvp_hello(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_DCLASS:
+ dissect_rsvp_dclass(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_ADMIN_STATUS:
+ dissect_rsvp_admin_status(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_LSP_TUNNEL_IF_ID:
+ dissect_rsvp_lsp_tunnel_if_id(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_GENERALIZED_UNI:
+ dissect_rsvp_gen_uni(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_RESTART_CAP:
+ dissect_rsvp_restart_cap(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_PROTECTION:
+ dissect_rsvp_protection_info(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_FAST_REROUTE:
+ dissect_rsvp_fast_reroute(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_DETOUR:
+ dissect_rsvp_detour(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_DIFFSERV:
+ dissect_rsvp_diffserv(ti, tvb, offset, obj_length, class, type, type_str);
+ break;
+
+ case RSVP_CLASS_NULL:
+ default:
+ rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_UNKNOWN_CLASS));
+ proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
+ "Length: %u", obj_length);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
+ "Class number: %u - %s",
+ class, type_str);
+ proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
+ "Data (%d bytes)", obj_length - 4);
+ break;
+ }
+
+ if (obj_length == 0)
+ break;
+ offset += obj_length;
+ len += obj_length;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * The main loop
+ *------------------------------------------------------------------------------*/
+static void
+dissect_rsvp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 ver_flags;
+ guint8 message_type;
+ int msg_length;
+ int session_off, tempfilt_off;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSVP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ver_flags = tvb_get_guint8(tvb, 0);
+ message_type = tvb_get_guint8(tvb, 1);
+ msg_length = tvb_get_ntohs(tvb, 6);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(message_type, message_type_vals, "Unknown (%u). "));
+ find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
+ if (session_off)
+ col_append_str(pinfo->cinfo, COL_INFO, summary_session(tvb, session_off));
+ if (tempfilt_off)
+ col_append_str(pinfo->cinfo, COL_INFO, summary_template(tvb, tempfilt_off));
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(message_type, message_type_vals, "Unknown (%u). "));
+ if (message_type == RSVP_MSG_BUNDLE) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ rsvp_bundle_dissect ?
+ "Component Messages Dissected" :
+ "Component Messages Not Dissected");
+ } else {
+ find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
+ if (session_off)
+ col_append_str(pinfo->cinfo, COL_INFO, summary_session(tvb, session_off));
+ if (tempfilt_off)
+ col_append_str(pinfo->cinfo, COL_INFO, summary_template(tvb, tempfilt_off));
+ }
+ }
+
+ if (tree) {
+ dissect_rsvp_msg_tree(tvb, pinfo, tree, TREE(TT_RSVP));
+ }
+}
+
+static void
+register_rsvp_prefs (void)
+{
+ module_t *rsvp_module;
+
+ rsvp_module = prefs_register_protocol(proto_rsvp, NULL);
+ prefs_register_bool_preference(
+ rsvp_module, "process_bundle",
+ "Dissect sub-messages in BUNDLE message",
+ "Specifies whether Ethereal should decode and display sub-messages within BUNDLE messages",
+ &rsvp_bundle_dissect);
+}
+
+void
+proto_register_rsvp(void)
+{
+ gint i;
+
+ /* Build the tree array */
+ for (i=0; i<TT_MAX; i++)
+ ett_tree[i] = &(ett_treelist[i]);
+
+ proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)",
+ "RSVP", "rsvp");
+ proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
+ proto_register_subtree_array(ett_tree, array_length(ett_tree));
+ register_rsvp_prefs();
+}
+
+void
+proto_reg_handoff_rsvp(void)
+{
+ dissector_handle_t rsvp_handle;
+
+ rsvp_handle = create_dissector_handle(dissect_rsvp, proto_rsvp);
+ dissector_add("ip.proto", IP_PROTO_RSVP, rsvp_handle);
+}
diff --git a/epan/dissectors/packet-rsvp.h b/epan/dissectors/packet-rsvp.h
new file mode 100644
index 0000000000..020d74c30c
--- /dev/null
+++ b/epan/dissectors/packet-rsvp.h
@@ -0,0 +1,32 @@
+/* packet-rsvp.h
+ * Declarations of variables exported by "packet-rsvp.c"
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_RSVP_H
+#define PACKET_RSVP_H
+
+extern const value_string gmpls_switching_type_str[];
+extern const value_string gmpls_lsp_enc_str[];
+extern const value_string gmpls_protection_cap_str[];
+
+#endif
diff --git a/epan/dissectors/packet-rsync.c b/epan/dissectors/packet-rsync.c
new file mode 100644
index 0000000000..0195e06ed3
--- /dev/null
+++ b/epan/dissectors/packet-rsync.c
@@ -0,0 +1,338 @@
+/* packet-rsync.c
+ * Routines for rsync dissection
+ * [ very rough, but mininally functional ]
+ * Copyright 2003, Brad Hards <bradh@frogmouth.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <time.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/conversation.h>
+
+#include "prefs.h"
+
+
+/* what states make sense here ? */
+typedef enum _rsync_state {
+ RSYNC_INIT = 0,
+ RSYNC_SERV_INIT = 1,
+ RSYNC_CLIENT_QUERY = 2,
+ RSYNC_SERV_RESPONSE = 4,
+ RSYNC_COMMAND = 5,
+ RSYNC_SERV_MOTD = 6,
+ RSYNC_DATA = 7
+} rsync_state_t;
+
+static gboolean rsync_desegment = TRUE;
+
+/* this is a guide to the current conversation state */
+struct rsync_conversation_data {
+ rsync_state_t state;
+};
+
+struct rsync_frame_data {
+ rsync_state_t state;
+};
+
+static int proto_rsync = -1;
+
+static int hf_rsync_hdr_magic = -1;
+static int hf_rsync_hdr_version = -1;
+static int hf_rsync_query_string = -1;
+static int hf_rsync_motd_string = -1;
+static int hf_rsync_response_string = -1;
+static int hf_rsync_rsyncdok_string = -1;
+static int hf_rsync_command_string = -1;
+static int hf_rsync_data = -1;
+
+static gint ett_rsync = -1;
+
+dissector_handle_t rsync_handle;
+
+
+#define TCP_PORT_RSYNC 873
+
+static unsigned int glb_rsync_tcp_port = TCP_PORT_RSYNC;
+
+/* Packet dissection routine called by tcp (& udp) when port 873 detected */
+static void
+dissect_rsync_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean desegment _U_)
+{
+ conversation_t *conversation;
+ struct rsync_conversation_data *conversation_data;
+ struct rsync_frame_data *frame_data;
+ proto_item *ti;
+ proto_tree *rsync_tree;
+ int offset = 0;
+ gchar version[5];
+ gchar auth_string[10];
+ guint buff_length;
+ gchar magic_string[14];
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSYNC");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL) {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+
+ conversation_data = conversation_get_proto_data(conversation, proto_rsync);
+
+ if (conversation_data == NULL) {
+ conversation_data = g_malloc(sizeof(struct rsync_conversation_data));
+ conversation_data->state = RSYNC_INIT;
+ conversation_add_proto_data(conversation, proto_rsync, conversation_data);
+ }
+
+ conversation_set_dissector(conversation, rsync_handle);
+
+ ti = proto_tree_add_item(tree, proto_rsync, tvb, 0, -1, FALSE);
+
+ rsync_tree = proto_item_add_subtree(ti, ett_rsync);
+
+ frame_data = p_get_proto_data(pinfo->fd, proto_rsync);
+ if (!frame_data) {
+ /* then we haven't seen this frame before */
+ frame_data = g_malloc(sizeof(struct rsync_frame_data));
+ frame_data->state = conversation_data->state;
+ p_add_proto_data(pinfo->fd, proto_rsync, frame_data);
+ }
+
+ switch (frame_data->state) {
+ case RSYNC_INIT:
+ proto_tree_add_item(rsync_tree, hf_rsync_hdr_magic, tvb, offset, 8, TRUE);
+ offset += 8;
+ proto_tree_add_item(rsync_tree, hf_rsync_hdr_version, tvb, offset, 4, TRUE);
+ tvb_get_nstringz0(tvb, offset, sizeof(version), version);
+ offset += 4;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "Client Initialisation (Version %s)",
+ version);
+ }
+
+ conversation_data->state = RSYNC_SERV_INIT;
+ conversation_add_proto_data(conversation, proto_rsync, conversation_data);
+
+ break;
+ case RSYNC_SERV_INIT:
+ proto_tree_add_item(rsync_tree, hf_rsync_hdr_magic, tvb, offset, 8, TRUE);
+ offset += 8;
+ proto_tree_add_item(rsync_tree, hf_rsync_hdr_version, tvb, offset, 4, TRUE);
+ tvb_get_nstringz0(tvb, offset, sizeof(version), version);
+ offset += 4;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "Server Initialisation (Version %s)",
+ version);
+ }
+
+ conversation_data->state = RSYNC_CLIENT_QUERY;
+ conversation_add_proto_data(conversation, proto_rsync, conversation_data);
+
+ break;
+ case RSYNC_CLIENT_QUERY:
+ proto_tree_add_item(rsync_tree, hf_rsync_query_string, tvb, offset, -1, TRUE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, "Client Query");
+ }
+
+ conversation_data->state = RSYNC_SERV_MOTD;
+ conversation_add_proto_data(conversation, proto_rsync, conversation_data);
+
+ break;
+ case RSYNC_SERV_MOTD:
+ proto_tree_add_item(rsync_tree, hf_rsync_motd_string, tvb, offset, -1, TRUE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Server MOTD");
+ }
+
+ conversation_data->state = RSYNC_SERV_RESPONSE;
+ conversation_add_proto_data(conversation, proto_rsync, conversation_data);
+
+ break;
+ case RSYNC_SERV_RESPONSE:
+ /* there are two cases - file list, or authentication */
+ tvb_get_nstringz0(tvb, offset, sizeof(auth_string), auth_string);
+ if (0 == strncmp("@RSYNCD:", auth_string, 8)) {
+ /* matches, so we assume its an authentication message */
+ /* needs to handle the AUTHREQD case, but doesn't - FIXME */
+ proto_tree_add_item(rsync_tree, hf_rsync_rsyncdok_string, tvb, offset, -1, TRUE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, "Authenication");
+ }
+ conversation_data->state = RSYNC_COMMAND;
+
+ } else { /* it didn't match, so it is probably a module list */
+
+ proto_tree_add_item(rsync_tree, hf_rsync_response_string, tvb, offset, -1, TRUE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Module list");
+ }
+
+ /* we need to check the end of the buffer for magic string */
+ buff_length = tvb_length_remaining(tvb, offset);
+ tvb_get_nstringz0(tvb, buff_length-14, sizeof(magic_string), magic_string);
+ if (0 == strncmp("@RSYNCD: EXIT", magic_string, 14)) {
+ /* that's all, folks */
+ conversation_data->state = RSYNC_COMMAND;
+ } else { /* there must be more data */
+ conversation_data->state = RSYNC_SERV_RESPONSE;
+ }
+ }
+
+ conversation_add_proto_data(conversation, proto_rsync, conversation_data);
+
+ break;
+
+ case RSYNC_COMMAND:
+ if (pinfo->destport == glb_rsync_tcp_port) {
+ /* then we are still sending commands */
+ proto_tree_add_item(rsync_tree, hf_rsync_command_string, tvb, offset, -1, TRUE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, "Command");
+ }
+
+ conversation_data->state = RSYNC_COMMAND;
+ conversation_add_proto_data(conversation, proto_rsync, conversation_data);
+
+ break;
+ } /* else we fall through to the data phase */
+
+ case RSYNC_DATA:
+ /* then we are still sending commands */
+ proto_tree_add_item(rsync_tree, hf_rsync_data, tvb, offset, -1, TRUE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, "Data");
+ }
+
+ conversation_data->state = RSYNC_DATA;
+ conversation_add_proto_data(conversation, proto_rsync, conversation_data);
+
+ break;
+
+ }
+
+}
+
+/* Packet dissection routine called by tcp (& udp) when port 873 detected */
+static void
+dissect_rsync(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_rsync_encap(tvb, pinfo, tree, rsync_desegment);
+}
+
+/* Register protocol with Ethereal. */
+void
+proto_register_rsync(void)
+{
+ static hf_register_info hf[] = {
+ {&hf_rsync_hdr_magic,
+ {"Magic Header", "rsync.hdr_magic",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ {&hf_rsync_hdr_version,
+ {"Header Version", "rsync.hdr_version",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ {&hf_rsync_query_string,
+ {"Client Query String", "rsync.query",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ {&hf_rsync_response_string,
+ {"Server Response String", "rsync.response",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ {&hf_rsync_motd_string,
+ {"Server MOTD String", "rsync.motd",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ {&hf_rsync_rsyncdok_string,
+ {"RSYNCD Response String", "rsync.response",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ {&hf_rsync_command_string,
+ {"Command String", "rsync.command",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ {&hf_rsync_data,
+ {"rsync data", "rsync.data",
+ FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+
+ };
+
+ static gint *ett[] = {
+ &ett_rsync,
+ };
+
+ module_t *rsync_module;
+
+ proto_rsync = proto_register_protocol("RSYNC File Synchroniser",
+ "RSYNC", "rsync");
+ proto_register_field_array(proto_rsync, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ rsync_module = prefs_register_protocol(proto_rsync, NULL);
+ prefs_register_uint_preference(rsync_module, "tcp_port",
+ "rsync TCP Port",
+ "Set the TCP port for RSYNC messages",
+ 10,
+ &glb_rsync_tcp_port);
+ prefs_register_bool_preference(rsync_module, "desegment",
+ "Desegment all RSYNC messages\nspanning multiple TCP segments",
+ "Whether the RSYNC dissector should desegment all messages spanning multiple TCP segments",
+ &rsync_desegment);
+}
+void
+proto_reg_handoff_rsync(void)
+{
+ rsync_handle = create_dissector_handle(dissect_rsync, proto_rsync);
+ dissector_add("tcp.port", glb_rsync_tcp_port, rsync_handle);
+}
diff --git a/epan/dissectors/packet-rtcp.c b/epan/dissectors/packet-rtcp.c
new file mode 100644
index 0000000000..86a826f7e6
--- /dev/null
+++ b/epan/dissectors/packet-rtcp.c
@@ -0,0 +1,1655 @@
+/* packet-rtcp.c
+ *
+ * $Id$
+ *
+ * Routines for RTCP dissection
+ * RTCP = Real-time Transport Control Protocol
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Written by Andreas Sikkema <h323@ramdyne.nl>
+ *
+ * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect the RTCP protocol according to Annex A
+ * of ITU-T Recommendation H.225.0 (02/98) and RFC 1889
+ * H.225.0 literally copies RFC 1889, but omitting a few sections.
+ *
+ * RTCP traffic is handled by an uneven UDP portnumber. This can be any
+ * port number, but there is a registered port available, port 5005
+ * See Annex B of ITU-T Recommendation H.225.0, section B.7
+ *
+ * See also http://www.iana.org/assignments/rtp-parameters
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-rtcp.h"
+#if 0
+#include "packet-ntp.h"
+#endif
+#include <epan/conversation.h>
+
+#include "prefs.h"
+
+
+/* Version is the first 2 bits of the first octet*/
+#define RTCP_VERSION(octet) ((octet) >> 6)
+
+/* Padding is the third bit; no need to shift, because true is any value
+ other than 0! */
+#define RTCP_PADDING(octet) ((octet) & 0x20)
+
+/* Receiver/ Sender count is the 5 last bits */
+#define RTCP_COUNT(octet) ((octet) & 0x1F)
+
+static dissector_handle_t rtcp_handle;
+
+static const value_string rtcp_version_vals[] =
+{
+ { 0, "Old VAT Version" },
+ { 1, "First Draft Version" },
+ { 2, "RFC 1889 Version" },
+ { 0, NULL },
+};
+
+/* RTCP packet types according to Section A.11.1 */
+/* And http://www.iana.org/assignments/rtp-parameters */
+#define RTCP_SR 200
+#define RTCP_RR 201
+#define RTCP_SDES 202
+#define RTCP_BYE 203
+#define RTCP_APP 204
+#define RTCP_XR 207
+/* Supplemental H.261 specific RTCP packet types according to Section C.3.5 */
+#define RTCP_FIR 192
+#define RTCP_NACK 193
+
+static const value_string rtcp_packet_type_vals[] =
+{
+ { RTCP_SR, "Sender Report" },
+ { RTCP_RR, "Receiver Report" },
+ { RTCP_SDES, "Source description" },
+ { RTCP_BYE, "Goodbye" },
+ { RTCP_APP, "Application specific" },
+ { RTCP_FIR, "Full Intra-frame Request (H.261)" },
+ { RTCP_NACK, "Negative Acknowledgement (H.261)" },
+ { RTCP_XR, "Extended report"},
+ { 0, NULL },
+};
+
+/* RTCP SDES types (Section A.11.2) */
+#define RTCP_SDES_END 0
+#define RTCP_SDES_CNAME 1
+#define RTCP_SDES_NAME 2
+#define RTCP_SDES_EMAIL 3
+#define RTCP_SDES_PHONE 4
+#define RTCP_SDES_LOC 5
+#define RTCP_SDES_TOOL 6
+#define RTCP_SDES_NOTE 7
+#define RTCP_SDES_PRIV 8
+#define RTCP_SDES_H323_CADDR 9
+
+static const value_string rtcp_sdes_type_vals[] =
+{
+ { RTCP_SDES_END, "END" },
+ { RTCP_SDES_CNAME, "CNAME (user and domain)" },
+ { RTCP_SDES_NAME, "NAME (common name)" },
+ { RTCP_SDES_EMAIL, "EMAIL (e-mail address)" },
+ { RTCP_SDES_PHONE, "PHONE (phone number)" },
+ { RTCP_SDES_LOC, "LOC (geographic location)" },
+ { RTCP_SDES_TOOL, "TOOL (name/version of source app)" },
+ { RTCP_SDES_NOTE, "NOTE (note about source)" },
+ { RTCP_SDES_PRIV, "PRIV (private extensions)" },
+ { RTCP_SDES_H323_CADDR,"H323-CADDR (H.323 callable address)"},
+ { 0, NULL },
+};
+/* RTCP Application PoC1 Value strings */
+static const value_string rtcp_app_poc1_floor_cnt_type_vals[] =
+{
+ { 0, "Floor Request"},
+ { 1, "Floor Grant"},
+ { 2, "Floor Taken"},
+ { 3, "Floor Deny"},
+ { 4, "Floor Release"},
+ { 5, "Floor Idle"},
+ { 6, "Floor Revoke"},
+ { 0, NULL },
+};
+
+static const value_string rtcp_app_poc1_reason_code1_vals[] =
+{
+ { 1, "Floor already in use"},
+ { 2, "Internal PoC server error"},
+ { 0, NULL },
+};
+
+static const value_string rtcp_app_poc1_reason_code2_vals[] =
+{
+ { 1, "Only one user"},
+ { 2, "Talk burst too long"},
+ { 0, NULL },
+};
+/* RTCP header fields */
+static int proto_rtcp = -1;
+static int hf_rtcp_version = -1;
+static int hf_rtcp_padding = -1;
+static int hf_rtcp_rc = -1;
+static int hf_rtcp_sc = -1;
+static int hf_rtcp_pt = -1;
+static int hf_rtcp_length = -1;
+static int hf_rtcp_ssrc_sender = -1;
+static int hf_rtcp_ntp = -1;
+static int hf_rtcp_rtp_timestamp = -1;
+static int hf_rtcp_sender_pkt_cnt = -1;
+static int hf_rtcp_sender_oct_cnt = -1;
+static int hf_rtcp_ssrc_source = -1;
+static int hf_rtcp_ssrc_fraction = -1;
+static int hf_rtcp_ssrc_cum_nr = -1;
+/* First the 32 bit number, then the split
+ * up 16 bit values */
+/* These two are added to a subtree */
+static int hf_rtcp_ssrc_ext_high_seq = -1;
+static int hf_rtcp_ssrc_high_seq = -1;
+static int hf_rtcp_ssrc_high_cycles = -1;
+static int hf_rtcp_ssrc_jitter = -1;
+static int hf_rtcp_ssrc_lsr = -1;
+static int hf_rtcp_ssrc_dlsr = -1;
+static int hf_rtcp_ssrc_csrc = -1;
+static int hf_rtcp_ssrc_type = -1;
+static int hf_rtcp_ssrc_length = -1;
+static int hf_rtcp_ssrc_text = -1;
+static int hf_rtcp_ssrc_prefix_len = -1;
+static int hf_rtcp_ssrc_prefix_string= -1;
+static int hf_rtcp_subtype = -1;
+static int hf_rtcp_name_ascii = -1;
+static int hf_rtcp_app_data = -1;
+static int hf_rtcp_fsn = -1;
+static int hf_rtcp_blp = -1;
+static int hf_rtcp_padding_count = -1;
+static int hf_rtcp_padding_data = -1;
+static int hf_rtcp_app_poc1_subtype = -1;
+static int hf_rtcp_app_poc1_sip_uri = -1;
+static int hf_rtcp_app_poc1_disp_name = -1;
+static int hf_rtcp_app_poc1_last_pkt_seq_no = -1;
+static int hf_rtcp_app_poc1_reason_code1 = -1;
+static int hf_rtcp_app_poc1_item_len = -1;
+static int hf_rtcp_app_poc1_reason1_phrase = -1;
+static int hf_rtcp_app_poc1_reason_code2 = -1;
+static int hf_rtcp_app_poc1_additionalinfo = -1;
+
+/* RTCP setup fields */
+static int hf_rtcp_setup = -1;
+static int hf_rtcp_setup_frame = -1;
+static int hf_rtcp_setup_method = -1;
+
+
+/* RTCP fields defining a sub tree */
+static gint ett_rtcp = -1;
+static gint ett_ssrc = -1;
+static gint ett_ssrc_item = -1;
+static gint ett_ssrc_ext_high = -1;
+static gint ett_sdes = -1;
+static gint ett_sdes_item = -1;
+static gint ett_PoC1 = -1;
+static gint ett_rtcp_setup = -1;
+
+static address fake_addr;
+static int heur_init = FALSE;
+
+static gboolean dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree );
+static void dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree );
+static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/* Preferences bool to control whether or not setup info should be shown */
+static gboolean global_rtcp_show_setup_info = TRUE;
+
+/* Memory chunk for storing conversation and per-packet info */
+static GMemChunk *rtcp_conversations = NULL;
+
+
+void rtcp_add_address( packet_info *pinfo,
+ const unsigned char* ip_addr, int port,
+ int other_port,
+ gchar *setup_method, guint32 setup_frame_number)
+{
+ address src_addr;
+ conversation_t* p_conv;
+ struct _rtcp_conversation_info *p_conv_data = NULL;
+
+ /*
+ * If this isn't the first time this packet has been processed,
+ * we've already done this work, so we don't need to do it
+ * again.
+ */
+ if (pinfo->fd->flags.visited)
+ {
+ return;
+ }
+
+ src_addr.type = pinfo->net_src.type;
+ src_addr.len = pinfo->net_src.len;
+ src_addr.data = ip_addr;
+
+ /*
+ * The first time the function is called let the udp dissector
+ * know that we're interested in traffic
+ * TODO???
+ *
+ if ( ! heur_init ) {
+ heur_dissector_add( "udp", dissect_rtcp_heur, proto_rtcp );
+ heur_init = TRUE;
+ }
+ */
+
+ /*
+ * Check if the ip address and port combination is not
+ * already registered
+ */
+ p_conv = find_conversation( &src_addr, &src_addr, PT_UDP, port, other_port,
+ NO_ADDR_B | (!other_port ? NO_PORT_B : 0));
+
+ /*
+ * If not, add
+ */
+ if ( ! p_conv ) {
+ /* Create conversation data */
+ p_conv_data = g_mem_chunk_alloc(rtcp_conversations);
+
+ /* Check length first time we look at method string */
+ strncpy(p_conv_data->method, setup_method,
+ (strlen(setup_method)+1 <= MAX_RTCP_SETUP_METHOD_SIZE) ?
+ strlen(setup_method)+1 :
+ MAX_RTCP_SETUP_METHOD_SIZE);
+ p_conv_data->method[MAX_RTCP_SETUP_METHOD_SIZE] = '\0';
+ p_conv_data->frame_number = setup_frame_number;
+
+ /* Create conversation with this data */
+ p_conv = conversation_new( &src_addr, &src_addr, PT_UDP,
+ (guint32)port, (guint32)other_port,
+ NO_ADDR2 | (!other_port ? NO_PORT2 : 0));
+ conversation_add_proto_data(p_conv, proto_rtcp, p_conv_data);
+
+ /* Set dissector */
+ conversation_set_dissector(p_conv, rtcp_handle);
+ }
+ else
+ {
+ /* Update existing conversation data */
+ p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
+ strcpy(p_conv_data->method, setup_method);
+ p_conv_data->frame_number = setup_frame_number;
+ }
+}
+
+static void rtcp_init( void )
+{
+ unsigned char* tmp_data;
+ int i;
+
+ /* (Re)allocate mem chunk for conversations */
+ if (rtcp_conversations)
+ {
+ g_mem_chunk_destroy(rtcp_conversations);
+ }
+ rtcp_conversations = g_mem_chunk_new("rtcp_conversations",
+ sizeof(struct _rtcp_conversation_info),
+ 20 * sizeof(struct _rtcp_conversation_info),
+ G_ALLOC_ONLY);
+
+
+ /* Create a fake adddress... */
+ fake_addr.type = AT_IPv4;
+ fake_addr.len = 4;
+
+ tmp_data = g_malloc( fake_addr.len );
+ for ( i = 0; i < fake_addr.len; i++) {
+ tmp_data[i] = 0;
+ }
+ fake_addr.data = tmp_data;
+}
+
+static gboolean
+dissect_rtcp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ conversation_t* pconv;
+
+ /* This is a heuristic dissector, which means we get all the UDP
+ * traffic not sent to a known dissector and not claimed by
+ * a heuristic dissector called before us!
+ * So we first check if the frame is really meant for us.
+ */
+ if ( ( pconv = find_conversation( &pinfo->src, &fake_addr, pinfo->ptype,
+ pinfo->srcport, 0, 0 ) ) == NULL ) {
+ /*
+ * The source ip:port combination was not what we were
+ * looking for, check the destination
+ */
+ if ( ( pconv = find_conversation( &pinfo->dst, &fake_addr,
+ pinfo->ptype, pinfo->destport, 0, 0 ) ) == NULL ) {
+ return FALSE;
+ }
+ }
+
+
+ /*
+ * An RTCP conversation always has a data item for RTCP.
+ * (Its existence is sufficient to indicate that this is an RTCP
+ * conversation.)
+ */
+ if (conversation_get_proto_data(pconv, proto_rtcp) == NULL)
+ return FALSE;
+
+ /*
+ * The message is a valid RTCP message!
+ */
+ dissect_rtcp( tvb, pinfo, tree );
+
+ return TRUE;
+}
+
+
+static int
+dissect_rtcp_nack( tvbuff_t *tvb, int offset, proto_tree *tree )
+{
+ /* Packet type = FIR (H261) */
+ proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
+ offset++;
+ /* Packet type, 8 bits = APP */
+ proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+
+ /* Packet length in 32 bit words minus one */
+ proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ /* SSRC */
+ proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ /* FSN, 16 bits */
+ proto_tree_add_uint( tree, hf_rtcp_fsn, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ /* BLP, 16 bits */
+ proto_tree_add_uint( tree, hf_rtcp_blp, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ return offset;
+}
+
+static int
+dissect_rtcp_fir( tvbuff_t *tvb, int offset, proto_tree *tree )
+{
+ /* Packet type = FIR (H261) */
+ proto_tree_add_uint( tree, hf_rtcp_rc, tvb, offset, 1, tvb_get_guint8( tvb, offset ) );
+ offset++;
+ /* Packet type, 8 bits = APP */
+ proto_tree_add_item( tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+
+ /* Packet length in 32 bit words minus one */
+ proto_tree_add_uint( tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ /* SSRC */
+ proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree,
+ unsigned int padding, unsigned int packet_len, guint rtcp_subtype )
+{
+ unsigned int counter = 0;
+ char ascii_name[5];
+ guint sdes_type = 0;
+ guint item_len = 0;
+ guint items_start_offset;
+ proto_tree *PoC1_tree;
+ proto_item *PoC1_item;
+
+ /* XXX If more application types are to be dissected it may be useful to use a table like in packet-sip.c */
+ static const char app_name_str[] = "PoC1";
+
+
+ /* SSRC / CSRC */
+ proto_tree_add_uint( tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+ packet_len -= 4;
+
+ /* Name (ASCII) */
+ for( counter = 0; counter < 4; counter++ )
+ ascii_name[ counter ] = tvb_get_guint8( tvb, offset + counter );
+ /* strncpy( ascii_name, pd + offset, 4 ); */
+ ascii_name[4] = '\0';
+ proto_tree_add_string( tree, hf_rtcp_name_ascii, tvb, offset, 4,
+ ascii_name );
+ if ( strncasecmp(ascii_name,app_name_str,4 ) != 0 ){ /* Not PoC1 */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,"( %s ) subtype=%u",ascii_name, rtcp_subtype);
+ offset += 4;
+ packet_len -= 4;
+ /* Applications specific data */
+ if ( padding ) {
+ /* If there's padding present, we have to remove that from the data part
+ * The last octet of the packet contains the length of the padding
+ */
+ packet_len -= tvb_get_guint8( tvb, offset + packet_len - 1 );
+ }
+ proto_tree_add_item( tree, hf_rtcp_app_data, tvb, offset, packet_len, FALSE );
+ offset += packet_len;
+
+ return offset;
+ }else{/* PoC1 Application */
+ proto_item *item;
+ item = proto_tree_add_uint( tree, hf_rtcp_app_poc1_subtype, tvb, offset - 8, 1, rtcp_subtype );
+ PROTO_ITEM_SET_GENERATED(item);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,"(%s) subtype=%s",ascii_name,
+ val_to_str(rtcp_subtype,rtcp_app_poc1_floor_cnt_type_vals,"unknown (%u)") );
+ offset += 4;
+ packet_len -= 4;
+ /* Applications specific data */
+ if ( padding ) {
+ /* If there's padding present, we have to remove that from the data part
+ * The last octet of the packet contains the length of the padding
+ */
+ packet_len -= tvb_get_guint8( tvb, offset + packet_len - 1 );
+ }
+ /* Create a subtree for the PoC1 Application items; we don't yet know
+ the length */
+ items_start_offset = offset;
+
+ PoC1_item = proto_tree_add_text(tree, tvb, offset, packet_len,
+ "PoC1 Application specific data");
+ PoC1_tree = proto_item_add_subtree( PoC1_item, ett_PoC1 );
+
+
+ proto_tree_add_item( PoC1_tree, hf_rtcp_app_data, tvb, offset, packet_len, FALSE );
+ switch ( rtcp_subtype ) {
+ case 2:
+ sdes_type = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
+ offset++;
+ packet_len--;
+ /* Item length, 8 bits */
+ item_len = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
+ offset++;
+ packet_len--;
+ proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_sip_uri, tvb, offset, item_len, FALSE );
+ offset = offset + item_len;
+ packet_len = packet_len - item_len;
+ sdes_type = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
+ offset++;
+ packet_len--;
+ /* Item length, 8 bits */
+ item_len = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( PoC1_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
+ offset++;
+ packet_len--;
+ if ( item_len != 0 )
+ proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_disp_name, tvb, offset, item_len, FALSE );
+ offset = offset + item_len;
+ packet_len = packet_len - item_len;
+ break;
+ case 3:
+ proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason_code1, tvb, offset, 1, FALSE );
+ offset++;
+ packet_len--;
+ /* Item length, 8 bits */
+ item_len = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_item_len, tvb, offset, 1, FALSE );
+ offset++;
+ packet_len--;
+ if ( item_len != 0 )
+ proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason1_phrase, tvb, offset, item_len, FALSE );
+ offset = offset + item_len;
+ packet_len = packet_len - item_len;
+ break;
+ case 4:
+ proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_last_pkt_seq_no, tvb, offset, 2, FALSE );
+ proto_tree_add_text(PoC1_tree, tvb, offset + 2, 2, "Padding 2 bytes");
+ offset += 4;
+ packet_len-=4;
+ break;
+ case 6:
+ proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_reason_code2, tvb, offset, 2, FALSE );
+ proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_additionalinfo, tvb, offset + 2, 2, FALSE );
+ offset += 4;
+ packet_len-=4;
+ break;
+ default:
+ break;
+ }
+ offset += packet_len;
+ return offset;
+ }
+}
+
+
+static int
+dissect_rtcp_bye( tvbuff_t *tvb, int offset, proto_tree *tree,
+ unsigned int count )
+{
+ unsigned int chunk = 1;
+ unsigned int reason_length = 0;
+ char* reason_text = NULL;
+
+ while ( chunk <= count ) {
+ /* source identifier, 32 bits */
+ proto_tree_add_item( tree, hf_rtcp_ssrc_source, tvb, offset, 4, FALSE);
+ offset += 4;
+ chunk++;
+ }
+
+ if ( tvb_reported_length_remaining( tvb, offset ) > 0 ) {
+ /* Bye reason consists of an 8 bit length l and a string with length l */
+ reason_length = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
+ offset++;
+
+ reason_text = tvb_get_string(tvb, offset, reason_length);
+ proto_tree_add_string( tree, hf_rtcp_ssrc_text, tvb, offset, reason_length, reason_text );
+ g_free( reason_text );
+ offset += reason_length;
+ }
+
+ return offset;
+
+}
+
+static void
+dissect_rtcp_sdes( tvbuff_t *tvb, int offset, proto_tree *tree,
+ unsigned int count )
+{
+ unsigned int chunk = 1;
+ proto_item *sdes_item;
+ proto_tree *sdes_tree;
+ proto_tree *sdes_item_tree;
+ proto_item *ti;
+ int start_offset;
+ int items_start_offset;
+ guint32 ssrc;
+ unsigned int item_len = 0;
+ unsigned int sdes_type = 0;
+ unsigned int counter = 0;
+ unsigned int prefix_len = 0;
+ char *prefix_string = NULL;
+
+ while ( chunk <= count ) {
+ /* Create a subtree for this chunk; we don't yet know
+ the length. */
+ start_offset = offset;
+
+ ssrc = tvb_get_ntohl( tvb, offset );
+ if (ssrc == 0) {
+ /* According to RFC1889 section 6.4:
+ * "The list of items in each chunk is terminated by one or more
+ * null octets, the first of which is interpreted as an item type
+ * of zero to denote the end of the list, and the remainder as
+ * needed to pad until the next 32-bit boundary.
+ *
+ * A chunk with zero items (four null octets) is valid but useless."
+ */
+ proto_tree_add_text(tree, tvb, offset, 4, "Padding");
+ offset += 4;
+ continue;
+ }
+ sdes_item = proto_tree_add_text(tree, tvb, offset, -1,
+ "Chunk %u, SSRC/CSRC %u", chunk, ssrc);
+ sdes_tree = proto_item_add_subtree( sdes_item, ett_sdes );
+
+ /* SSRC_n source identifier, 32 bits */
+ proto_tree_add_uint( sdes_tree, hf_rtcp_ssrc_source, tvb, offset, 4, ssrc );
+ offset += 4;
+
+ /* Create a subtree for the SDES items; we don't yet know
+ the length */
+ items_start_offset = offset;
+ ti = proto_tree_add_text(sdes_tree, tvb, offset, -1,
+ "SDES items" );
+ sdes_item_tree = proto_item_add_subtree( ti, ett_sdes_item );
+
+ /*
+ * Not every message is ended with "null" bytes, so check for
+ * end of frame instead.
+ */
+ while ( ( tvb_reported_length_remaining( tvb, offset ) > 0 )
+ && ( tvb_get_guint8( tvb, offset ) != RTCP_SDES_END ) ) {
+ /* ID, 8 bits */
+ sdes_type = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_type, tvb, offset, 1, FALSE );
+ offset++;
+
+ /* Item length, 8 bits */
+ item_len = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_length, tvb, offset, 1, FALSE );
+ offset++;
+
+ if ( sdes_type == RTCP_SDES_PRIV ) {
+ /* PRIV adds two items between the SDES length
+ * and value - an 8 bit length giving the
+ * length of a "prefix string", and the string.
+ */
+ prefix_len = tvb_get_guint8( tvb, offset );
+ proto_tree_add_item( sdes_item_tree, hf_rtcp_ssrc_prefix_len, tvb, offset, 1, FALSE );
+ offset++;
+
+ prefix_string = g_malloc( prefix_len + 1 );
+ for ( counter = 0; counter < prefix_len; counter++ )
+ prefix_string[ counter ] =
+ tvb_get_guint8( tvb, offset + counter );
+ /* strncpy( prefix_string, pd + offset, prefix_len ); */
+ prefix_string[ prefix_len ] = '\0';
+ proto_tree_add_string( sdes_item_tree, hf_rtcp_ssrc_prefix_string, tvb, offset, prefix_len, prefix_string );
+ g_free( prefix_string );
+ offset += prefix_len;
+ }
+ prefix_string = g_malloc( item_len + 1 );
+ for ( counter = 0; counter < item_len; counter++ )
+ prefix_string[ counter ] =
+ tvb_get_guint8( tvb, offset + counter );
+ /* strncpy( prefix_string, pd + offset, item_len ); */
+ prefix_string[ item_len] = 0;
+ proto_tree_add_string( sdes_item_tree, hf_rtcp_ssrc_text, tvb, offset, item_len, prefix_string );
+ g_free( prefix_string );
+ offset += item_len;
+ }
+
+ /* Set the length of the items subtree. */
+ proto_item_set_len(ti, offset - items_start_offset);
+
+ /* 32 bits = 4 bytes, so.....
+ * If offset % 4 != 0, we divide offset by 4, add one and then
+ * multiply by 4 again to reach the boundary
+ */
+ if ( offset % 4 != 0 )
+ offset = ((offset / 4) + 1 ) * 4;
+
+ /* Set the length of this chunk. */
+ proto_item_set_len(sdes_item, offset - start_offset);
+
+ chunk++;
+ }
+}
+
+static int
+dissect_rtcp_rr( tvbuff_t *tvb, int offset, proto_tree *tree,
+ unsigned int count )
+{
+ unsigned int counter = 1;
+ proto_tree *ssrc_tree = (proto_tree*) NULL;
+ proto_tree *ssrc_sub_tree = (proto_tree*) NULL;
+ proto_tree *high_sec_tree = (proto_tree*) NULL;
+ proto_item *ti = (proto_item*) NULL;
+ guint8 rr_flt;
+ unsigned int cum_nr = 0;
+
+ while ( counter <= count ) {
+ /* Create a new subtree for a length of 24 bytes */
+ ti = proto_tree_add_text(tree, tvb, offset, 24,
+ "Source %u", counter );
+ ssrc_tree = proto_item_add_subtree( ti, ett_ssrc );
+
+ /* SSRC_n source identifier, 32 bits */
+ proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_source, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ ti = proto_tree_add_text(ssrc_tree, tvb, offset, 20, "SSRC contents" );
+ ssrc_sub_tree = proto_item_add_subtree( ti, ett_ssrc_item );
+
+ /* Fraction lost, 8bits */
+ rr_flt = tvb_get_guint8( tvb, offset );
+ proto_tree_add_uint_format( ssrc_sub_tree, hf_rtcp_ssrc_fraction, tvb,
+ offset, 1, rr_flt, "Fraction lost: %u / 256", rr_flt );
+ offset++;
+
+ /* Cumulative number of packets lost, 24 bits */
+ cum_nr = tvb_get_ntohl( tvb, offset ) >> 8;
+ proto_tree_add_uint( ssrc_sub_tree, hf_rtcp_ssrc_cum_nr, tvb,
+ offset, 3, cum_nr );
+ offset += 3;
+
+ /* Extended highest sequence nr received, 32 bits
+ * Just for the sake of it, let's add another subtree
+ * because this might be a little clearer
+ */
+ ti = proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_ext_high_seq,
+ tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ high_sec_tree = proto_item_add_subtree( ti, ett_ssrc_ext_high );
+ /* Sequence number cycles */
+ proto_tree_add_uint( high_sec_tree, hf_rtcp_ssrc_high_cycles,
+ tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ /* highest sequence number received */
+ proto_tree_add_uint( high_sec_tree, hf_rtcp_ssrc_high_seq,
+ tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ /* Interarrival jitter */
+ proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_jitter, tvb,
+ offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ /* Last SR timestamp */
+ proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_lsr, tvb,
+ offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ /* Delay since last SR timestamp */
+ proto_tree_add_uint( ssrc_tree, hf_rtcp_ssrc_dlsr, tvb,
+ offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+ counter++;
+ }
+
+ return offset;
+}
+
+static int
+dissect_rtcp_sr( tvbuff_t *tvb, int offset, proto_tree *tree,
+ unsigned int count )
+{
+#if 0
+ gchar buff[ NTP_TS_SIZE ];
+ char* ptime = tvb_get_ptr( tvb, offset, 8 );
+
+ /* Retreive the NTP timestamp. Using the NTP dissector for this */
+ ntp_fmt_ts( ptime, buff );
+ proto_tree_add_string_format( tree, hf_rtcp_ntp, tvb, offset, 8, ( const char* ) &buff, "NTP timestamp: %s", &buff );
+ free( ptime ); ??????????????????????????????????????????????????????????????????
+ offset += 8;
+#else
+ /*
+ * XXX - RFC 1889 says this is an NTP timestamp, but that appears
+ * not to be the case.
+ */
+ proto_tree_add_text(tree, tvb, offset, 4, "Timestamp, MSW: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_text(tree, tvb, offset, 4, "Timestamp, LSW: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+#endif
+ /* RTP timestamp, 32 bits */
+ proto_tree_add_uint( tree, hf_rtcp_rtp_timestamp, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+ /* Sender's packet count, 32 bits */
+ proto_tree_add_uint( tree, hf_rtcp_sender_pkt_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+ /* Sender's octet count, 32 bits */
+ proto_tree_add_uint( tree, hf_rtcp_sender_oct_cnt, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ /* The rest of the packet is equal to the RR packet */
+ if ( count != 0 )
+ offset = dissect_rtcp_rr( tvb, offset, tree, count );
+
+ return offset;
+}
+
+/* Look for conversation info and display any setup info found */
+void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Conversation and current data */
+ conversation_t *p_conv = NULL;
+ struct _rtcp_conversation_info *p_conv_data = NULL;
+
+ /* Use existing packet data if available */
+ p_conv_data = p_get_proto_data(pinfo->fd, proto_rtcp);
+
+ if (!p_conv_data)
+ {
+ /* First time, get info from conversation */
+ p_conv = find_conversation(&pinfo->net_dst, &pinfo->net_src,
+ pinfo->ptype,
+ pinfo->destport, pinfo->srcport, NO_ADDR_B);
+
+ if (p_conv)
+ {
+ /* Create space for packet info */
+ struct _rtcp_conversation_info *p_conv_packet_data;
+ p_conv_data = conversation_get_proto_data(p_conv, proto_rtcp);
+
+ /* Save this conversation info into packet info */
+ p_conv_packet_data = g_mem_chunk_alloc(rtcp_conversations);
+ strcpy(p_conv_packet_data->method, p_conv_data->method);
+ p_conv_packet_data->frame_number = p_conv_data->frame_number;
+ p_add_proto_data(pinfo->fd, proto_rtcp, p_conv_packet_data);
+ }
+ }
+
+ /* Create setup info subtree with summary info. */
+ if (p_conv_data)
+ {
+ proto_tree *rtcp_setup_tree;
+ proto_item *ti = proto_tree_add_string_format(tree, hf_rtcp_setup, tvb, 0, 0,
+ "",
+ "Stream setup by %s (frame %d)",
+ p_conv_data->method,
+ p_conv_data->frame_number);
+ PROTO_ITEM_SET_GENERATED(ti);
+ rtcp_setup_tree = proto_item_add_subtree(ti, ett_rtcp_setup);
+ if (rtcp_setup_tree)
+ {
+ /* Add details into subtree */
+ proto_item* item = proto_tree_add_uint(rtcp_setup_tree, hf_rtcp_setup_frame,
+ tvb, 0, 0, p_conv_data->frame_number);
+ PROTO_ITEM_SET_GENERATED(item);
+ item = proto_tree_add_string(rtcp_setup_tree, hf_rtcp_setup_method,
+ tvb, 0, 0, p_conv_data->method);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ }
+}
+
+
+static void
+dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *rtcp_tree = NULL;
+ unsigned int temp_byte = 0;
+ unsigned int padding_set = 0;
+ unsigned int elem_count = 0;
+ unsigned int packet_type = 0;
+ unsigned int offset = 0;
+ guint16 packet_length = 0;
+ guint rtcp_subtype = 0;
+
+ if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) {
+ col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTCP" );
+ }
+
+ if ( check_col( pinfo->cinfo, COL_INFO) ) {
+ /* The second octet contains the packet type */
+ /* switch ( pd[ offset + 1 ] ) { */
+ switch ( tvb_get_guint8( tvb, 1 ) ) {
+ case RTCP_SR:
+ col_set_str( pinfo->cinfo, COL_INFO, "Sender Report");
+ break;
+ case RTCP_RR:
+ col_set_str( pinfo->cinfo, COL_INFO, "Receiver Report");
+ break;
+ case RTCP_SDES:
+ col_set_str( pinfo->cinfo, COL_INFO, "Source Description");
+ break;
+ case RTCP_BYE:
+ col_set_str( pinfo->cinfo, COL_INFO, "Goodbye");
+ break;
+ case RTCP_APP:
+ col_set_str( pinfo->cinfo, COL_INFO, "Application defined");
+ break;
+ case RTCP_XR:
+ col_set_str( pinfo->cinfo, COL_INFO, "Extended report");
+ break;
+ case RTCP_FIR:
+ col_set_str( pinfo->cinfo, COL_INFO, "Full Intra-frame Request (H.261)");
+ break;
+ case RTCP_NACK:
+ col_set_str( pinfo->cinfo, COL_INFO, "Negative Acknowledgement (H.261)");
+ break;
+ default:
+ col_set_str( pinfo->cinfo, COL_INFO, "Unknown packet type");
+ break;
+ }
+ }
+
+ if ( tree ) {
+ /*
+ * Check if there are at least 4 bytes left in the frame,
+ * the last 16 bits of those is the length of the current
+ * RTCP message. The last compound message contains padding,
+ * that enables us to break from the while loop.
+ */
+ while ( tvb_bytes_exist( tvb, offset, 4) ) {
+ /*
+ * First retreive the packet_type
+ */
+ packet_type = tvb_get_guint8( tvb, offset + 1 );
+
+ /*
+ * Check if it's a valid type
+ */
+ if ( ( packet_type < 192 ) || ( packet_type > 204 ) )
+ break;
+
+ /*
+ * get the packet-length for the complete RTCP packet
+ */
+ packet_length = ( tvb_get_ntohs( tvb, offset + 2 ) + 1 ) * 4;
+
+ ti = proto_tree_add_item(tree, proto_rtcp, tvb, offset, packet_length, FALSE );
+ rtcp_tree = proto_item_add_subtree( ti, ett_rtcp );
+
+
+ /* Conversation setup info */
+ if (global_rtcp_show_setup_info)
+ {
+ show_setup_info(tvb, pinfo, rtcp_tree);
+ }
+
+
+ temp_byte = tvb_get_guint8( tvb, offset );
+
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_version, tvb,
+ offset, 1, temp_byte);
+ padding_set = RTCP_PADDING( temp_byte );
+ proto_tree_add_boolean( rtcp_tree, hf_rtcp_padding, tvb,
+ offset, 1, temp_byte );
+ elem_count = RTCP_COUNT( temp_byte );
+
+ switch ( packet_type ) {
+ case RTCP_SR:
+ case RTCP_RR:
+ /* Receiver report count, 5 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_rc, tvb, offset, 1, temp_byte );
+ offset++;
+ /* Packet type, 8 bits */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+ /* Packet length in 32 bit words MINUS one, 16 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ /* Sender Synchronization source, 32 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_ssrc_sender, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+
+ if ( packet_type == RTCP_SR ) offset = dissect_rtcp_sr( tvb, offset, rtcp_tree, elem_count );
+ else offset = dissect_rtcp_rr( tvb, offset, rtcp_tree, elem_count );
+ break;
+ case RTCP_SDES:
+ /* Source count, 5 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, temp_byte );
+ offset++;
+ /* Packet type, 8 bits */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+ /* Packet length in 32 bit words MINUS one, 16 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ dissect_rtcp_sdes( tvb, offset, rtcp_tree, elem_count );
+ offset += packet_length - 4;
+ break;
+ case RTCP_BYE:
+ /* Source count, 5 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_sc, tvb, offset, 1, temp_byte );
+ offset++;
+ /* Packet type, 8 bits */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+ /* Packet length in 32 bit words MINUS one, 16 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ offset = dissect_rtcp_bye( tvb, offset, rtcp_tree, elem_count );
+ break;
+ case RTCP_APP:
+ /* Subtype, 5 bits */
+ rtcp_subtype = elem_count;
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_subtype, tvb, offset, 1, elem_count );
+ offset++;
+ /* Packet type, 8 bits */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_pt, tvb, offset, 1, FALSE );
+ offset++;
+ /* Packet length in 32 bit words MINUS one, 16 bits */
+ proto_tree_add_uint( rtcp_tree, hf_rtcp_length, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+ offset = dissect_rtcp_app( tvb, pinfo, offset,
+ rtcp_tree, padding_set,
+ packet_length - 4, rtcp_subtype );
+ break;
+ case RTCP_FIR:
+ offset = dissect_rtcp_fir( tvb, offset, rtcp_tree );
+ break;
+ case RTCP_NACK:
+ offset = dissect_rtcp_nack( tvb, offset, rtcp_tree );
+ break;
+ default:
+ /*
+ * To prevent endless loops in case of an unknown message type
+ * increase offset. Some time the while will end :-)
+ */
+ offset++;
+ break;
+ }
+ }
+ /* If the padding bit is set, the last octet of the
+ * packet contains the length of the padding
+ * We only have to check for this at the end of the LAST RTCP message
+ */
+ if ( padding_set ) {
+ /* If everything went according to plan offset should now point to the
+ * first octet of the padding
+ */
+ proto_tree_add_item( rtcp_tree, hf_rtcp_padding_data, tvb, offset, tvb_length_remaining( tvb, offset) - 1, FALSE );
+ offset += tvb_length_remaining( tvb, offset) - 1;
+ proto_tree_add_item( rtcp_tree, hf_rtcp_padding_count, tvb, offset, 1, FALSE );
+ }
+ }
+}
+
+void
+proto_register_rtcp(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_rtcp_version,
+ {
+ "Version",
+ "rtcp.version",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(rtcp_version_vals),
+ 0xC0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_padding,
+ {
+ "Padding",
+ "rtcp.padding",
+ FT_BOOLEAN,
+ 8,
+ NULL,
+ 0x20,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_rc,
+ {
+ "Reception report count",
+ "rtcp.rc",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x1F,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_sc,
+ {
+ "Source count",
+ "rtcp.sc",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x1F,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_pt,
+ {
+ "Packet type",
+ "rtcp.pt",
+ FT_UINT8,
+ BASE_DEC,
+ VALS( rtcp_packet_type_vals ),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_length,
+ {
+ "Length",
+ "rtcp.length",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_sender,
+ {
+ "Sender SSRC",
+ "rtcp.senderssrc",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ntp,
+ {
+ "NTP timestamp",
+ "rtcp.timestamp.ntp",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_rtp_timestamp,
+ {
+ "RTP timestamp",
+ "rtcp.timestamp.rtp",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_sender_pkt_cnt,
+ {
+ "Sender's packet count",
+ "rtcp.sender.packetcount",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_sender_oct_cnt,
+ {
+ "Sender's octet count",
+ "rtcp.sender.octetcount",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_source,
+ {
+ "Identifier",
+ "rtcp.ssrc.identifier",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_fraction,
+ {
+ "Fraction lost",
+ "rtcp.ssrc.fraction",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_cum_nr,
+ {
+ "Cumulative number of packets lost",
+ "rtcp.ssrc.cum_nr",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_ext_high_seq,
+ {
+ "Extended highest sequence number received",
+ "rtcp.ssrc.ext_high",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_high_seq,
+ {
+ "Highest sequence number received",
+ "rtcp.ssrc.high_seq",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_high_cycles,
+ {
+ "Sequence number cycles count",
+ "rtcp.ssrc.high_cycles",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_jitter,
+ {
+ "Interarrival jitter",
+ "rtcp.ssrc.jitter",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_lsr,
+ {
+ "Last SR timestamp",
+ "rtcp.ssrc.lsr",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_dlsr,
+ {
+ "Delay since last SR timestamp",
+ "rtcp.ssrc.dlsr",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_csrc,
+ {
+ "SSRC / CSRC identifier",
+ "rtcp.sdes.ssrc_csrc",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_type,
+ {
+ "Type",
+ "rtcp.sdes.type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS( rtcp_sdes_type_vals ),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_length,
+ {
+ "Length",
+ "rtcp.sdes.length",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_text,
+ {
+ "Text",
+ "rtcp.sdes.text",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_prefix_len,
+ {
+ "Prefix length",
+ "rtcp.sdes.prefix.length",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_ssrc_prefix_string,
+ {
+ "Prefix string",
+ "rtcp.sdes.prefix.string",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_subtype,
+ {
+ "Subtype",
+ "rtcp.app.subtype",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_name_ascii,
+ {
+ "Name (ASCII)",
+ "rtcp.app.name",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_data,
+ {
+ "Application specific data",
+ "rtcp.app.data",
+ FT_BYTES,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_poc1_subtype,
+ {
+ "Subtype",
+ "rtcp.app.PoC1.subtype",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(rtcp_app_poc1_floor_cnt_type_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_poc1_sip_uri,
+ {
+ "SIP URI",
+ "rtcp.app.poc1.sip.uri",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_poc1_disp_name,
+ {
+ "Display Name",
+ "rtcp.app.poc1.disp.name",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_poc1_last_pkt_seq_no,
+ {
+ "Seq. no of last RTP packet",
+ "rtcp.app.poc1.last.pkt.seq.no",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_poc1_reason_code1,
+ {
+ "Reason code",
+ "rtcp.app.poc1.reason.code",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(rtcp_app_poc1_reason_code1_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_poc1_item_len,
+ {
+ "Item length",
+ "rtcp.app.poc1.item.len",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_poc1_reason1_phrase,
+ {
+ "Reason Phrase",
+ "rtcp.app.poc1.reason.phrase",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_poc1_reason_code2,
+ {
+ "Reason code",
+ "rtcp.app.poc1.reason.code",
+ FT_UINT16,
+ BASE_DEC,
+ VALS(rtcp_app_poc1_reason_code2_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_app_poc1_additionalinfo,
+ {
+ "additional information",
+ "rtcp.app.poc1.add.info",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_fsn,
+ {
+ "First sequence number",
+ "rtcp.nack.fsn",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_blp,
+ {
+ "Bitmask of following lost packets",
+ "rtcp.nack.blp",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_padding_count,
+ {
+ "Padding count",
+ "rtcp.padding.count",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_padding_data,
+ {
+ "Padding data",
+ "rtcp.padding.data",
+ FT_BYTES,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtcp_setup,
+ {
+ "Stream setup",
+ "rtcp.setup",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Stream setup, method and frame number", HFILL
+ }
+ },
+ {
+ &hf_rtcp_setup_frame,
+ {
+ "Setup frame",
+ "rtcp.setup-frame",
+ FT_FRAMENUM,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Frame that set up this stream", HFILL
+ }
+ },
+ {
+ &hf_rtcp_setup_method,
+ {
+ "Setup Method",
+ "rtcp.setup-method",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Method used to set up this stream", HFILL
+ }
+ }
+
+ };
+
+ static gint *ett[] =
+ {
+ &ett_rtcp,
+ &ett_ssrc,
+ &ett_ssrc_item,
+ &ett_ssrc_ext_high,
+ &ett_sdes,
+ &ett_sdes_item,
+ &ett_PoC1,
+ &ett_rtcp_setup
+ };
+
+ module_t *rtcp_module;
+
+ proto_rtcp = proto_register_protocol("Real-time Transport Control Protocol",
+ "RTCP", "rtcp");
+ proto_register_field_array(proto_rtcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("rtcp", dissect_rtcp, proto_rtcp);
+
+ rtcp_module = prefs_register_protocol(proto_rtcp, NULL);
+
+ prefs_register_bool_preference(rtcp_module, "show_setup_info",
+ "Show stream setup information",
+ "Where available, show which protocol and frame caused "
+ "this RTCP stream to be created",
+ &global_rtcp_show_setup_info);
+
+ register_init_routine( &rtcp_init );
+}
+
+void
+proto_reg_handoff_rtcp(void)
+{
+ /*
+ * Register this dissector as one that can be selected by a
+ * UDP port number.
+ */
+ rtcp_handle = find_dissector("rtcp");
+ dissector_add_handle("udp.port", rtcp_handle);
+}
diff --git a/epan/dissectors/packet-rtcp.h b/epan/dissectors/packet-rtcp.h
new file mode 100644
index 0000000000..30e0ee5dd9
--- /dev/null
+++ b/epan/dissectors/packet-rtcp.h
@@ -0,0 +1,44 @@
+/* packet-rtcp.h
+ *
+ * $Id$
+ *
+ * Routines for RTCP dissection
+ * RTCP = Real-time Transport Control Protocol
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Written by Andreas Sikkema <andreas.sikkema@philips.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Info to save in RTCP conversation / packet-info */
+#define MAX_RTCP_SETUP_METHOD_SIZE 8
+struct _rtcp_conversation_info
+{
+ gchar method[MAX_RTCP_SETUP_METHOD_SIZE];
+ guint32 frame_number;
+};
+
+
+/* Add an RTCP conversation with the given details */
+void rtcp_add_address(packet_info *pinfo,
+ const unsigned char* ip_addr, int port,
+ int other_port,
+ gchar *setup_method, guint32 setup_frame_number);
+
diff --git a/epan/dissectors/packet-rtp-events.c b/epan/dissectors/packet-rtp-events.c
new file mode 100644
index 0000000000..13630e462a
--- /dev/null
+++ b/epan/dissectors/packet-rtp-events.c
@@ -0,0 +1,240 @@
+/* packet-rtp-events.c
+ *
+ * Routines for RFC 2833 RTP Events dissection
+ * Copyright 2003, Kevin A. Noll <knoll[AT]poss.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect RTP Events.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "prefs.h"
+
+#include <stdio.h>
+#include <string.h>
+#include "packet-rtp-events.h"
+
+/* rtp_event_payload_type_value is the value used globally
+ to set the appropriate payload type
+ saved_pt_value is a temporary place to save the value
+ so we can properly reinitialize when the settings
+ get changed
+*/
+static guint rtp_event_payload_type_value = 101;
+static guint saved_payload_type_value;
+
+
+/* RTP Event Fields */
+
+static int proto_rtp_events = -1;
+
+static int hf_rtp_events_event = -1; /* one byte */
+static int hf_rtp_events_end = -1; /* one bit */
+static int hf_rtp_events_reserved = -1; /* one bit */
+static int hf_rtp_events_volume = -1; /* six bits */
+static int hf_rtp_events_duration = -1; /* sixteen bits */
+
+
+/* RTP Events fields defining a subtree */
+
+static gint ett_rtp_events = -1;
+
+void
+proto_reg_handoff_rtp_events(void);
+
+static void
+dissect_rtp_events( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *rtp_events_tree = NULL;
+ unsigned int offset = 0;
+
+ guint8 rtp_evt;
+ guint8 octet;
+
+ if ( check_col( pinfo->cinfo, COL_PROTOCOL ) )
+ {
+ col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTP EVENT" );
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+
+ /* Get event fields */
+
+ rtp_evt = tvb_get_guint8(tvb, offset );
+
+ if ( check_col( pinfo->cinfo, COL_INFO) )
+ {
+ col_add_fstr( pinfo->cinfo, COL_INFO,
+ "Payload type=RTP Event, %s",
+ val_to_str( rtp_evt, rtp_event_type_values, "Unknown (%u)" ));
+
+
+ }
+
+ if ( tree )
+ {
+ ti = proto_tree_add_item( tree, proto_rtp_events, tvb, offset, -1, FALSE );
+ rtp_events_tree = proto_item_add_subtree( ti, ett_rtp_events );
+
+ proto_tree_add_uint ( rtp_events_tree, hf_rtp_events_event, tvb, offset, 1, rtp_evt);
+
+ octet = tvb_get_guint8(tvb, offset +1 );
+ proto_tree_add_boolean (rtp_events_tree, hf_rtp_events_end, tvb, offset+1, 1, octet);
+ proto_tree_add_boolean (rtp_events_tree, hf_rtp_events_reserved, tvb, offset+1, 1, octet);
+ proto_tree_add_uint ( rtp_events_tree, hf_rtp_events_volume, tvb, offset+1, 1, octet);
+
+ proto_tree_add_item ( rtp_events_tree, hf_rtp_events_duration, tvb, offset+2, 2, FALSE);
+
+ /* Make end-of-event packets obvious in the info column */
+ if ((octet & 0x80) && check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, " (end)");
+ }
+
+ }
+}
+
+
+void
+proto_register_rtp_events(void)
+{
+
+ module_t *rtp_events_module;
+
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_rtp_events_event,
+ {
+ "Event ID",
+ "rtpevent.event_id",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(rtp_event_type_values),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_events_end,
+ {
+ "End of Event",
+ "rtpevent.end_of_event",
+ FT_BOOLEAN,
+ 8,
+ NULL,
+ 0x80,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_events_reserved,
+ {
+ "Reserved",
+ "rtpevent.reserved",
+ FT_BOOLEAN,
+ 8,
+ NULL,
+ 0x40,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_events_volume,
+ {
+ "Volume",
+ "rtpevent.volume",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x3F,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_rtp_events_duration,
+ {
+ "Event Duration",
+ "rtpevent.duration",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ };
+
+ static gint *ett[] =
+ {
+ &ett_rtp_events,
+ };
+
+
+ proto_rtp_events = proto_register_protocol("RFC 2833 RTP Event", "RTP Event", "rtpevent");
+ proto_register_field_array(proto_rtp_events, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+
+ /* Register preferences */
+ rtp_events_module = prefs_register_protocol (proto_rtp_events, proto_reg_handoff_rtp_events);
+ prefs_register_uint_preference (rtp_events_module,
+ "event_payload_type_value", "Payload Type for RFC2833 RTP Events",
+ "This is the value of the Payload Type field"
+ "that specifies RTP Events", 10,
+ &rtp_event_payload_type_value);
+}
+
+
+
+void
+proto_reg_handoff_rtp_events(void)
+{
+ static dissector_handle_t rtp_events_handle;
+ static int rtp_events_prefs_initialized = FALSE;
+
+ if (!rtp_events_prefs_initialized) {
+ rtp_events_handle = create_dissector_handle(dissect_rtp_events, proto_rtp_events);
+ rtp_events_prefs_initialized = TRUE;
+ }
+ else {
+ dissector_delete("rtp.pt", saved_payload_type_value, rtp_events_handle);
+ }
+
+ saved_payload_type_value = rtp_event_payload_type_value;
+ /* rtp_event_payload_type_value is set from preferences */
+
+ dissector_add("rtp.pt", saved_payload_type_value, rtp_events_handle);
+
+}
diff --git a/epan/dissectors/packet-rtp-events.h b/epan/dissectors/packet-rtp-events.h
new file mode 100644
index 0000000000..76c972f1d1
--- /dev/null
+++ b/epan/dissectors/packet-rtp-events.h
@@ -0,0 +1,253 @@
+/* packet-rtp-events.h
+ *
+ * Defines for RFC 2833 RTP Events dissection
+ * Copyright 2003, Kevin A. Noll <knoll[AT]poss.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#define RTP_DTMF_0 0
+#define RTP_DTMF_1 1
+#define RTP_DTMF_2 2
+#define RTP_DTMF_3 3
+#define RTP_DTMF_4 4
+#define RTP_DTMF_5 5
+#define RTP_DTMF_6 6
+#define RTP_DTMF_7 7
+#define RTP_DTMF_8 8
+#define RTP_DTMF_9 9
+#define RTP_DTMF_STAR 10
+#define RTP_DTMF_POUND 11
+#define RTP_DTMF_A 12
+#define RTP_DTMF_B 13
+#define RTP_DTMF_C 14
+#define RTP_DTMF_D 15
+#define RTP_DTMF_FLASH 16
+
+#define RTP_ANS 32
+#define RTP_ANSREV 33
+#define RTP_ANSAM 34
+#define RTP_ANSAMREV 35
+#define RTP_CNG 36
+#define RTP_V21C1B0 37
+#define RTP_V21C1B1 38
+#define RTP_V21C2B0 39
+#define RTP_V21C2B1 40
+#define RTP_CRDI 41
+#define RTP_CRDR 42
+#define RTP_CRE 43
+#define RTP_ESI 44
+#define RTP_ESR 45
+#define RTP_MRDI 46
+#define RTP_MRDR 47
+#define RTP_MRE 48
+#define RTP_CT 49
+
+#define RTP_OFFHOOK 64
+#define RTP_ONHOOK 65
+#define RTP_DIALTONE 66
+#define RTP_INTDT 67
+#define RTP_SPCDT 68
+#define RTP_2NDDT 69
+#define RTP_RGTONE 70
+#define RTP_SPRGTONE 71
+#define RTP_BUSYTONE 72
+#define RTP_CNGTONE 73
+#define RTP_SPINFOTN 74
+#define RTP_CMFTTONE 75
+#define RTP_HOLDTONE 76
+#define RTP_RECTONE 77
+#define RTP_CLRWTTONE 78
+#define RTP_CWTONE 79
+#define RTP_PAYTONE 80
+#define RTP_POSINDTONE 81
+#define RTP_NEGINDTONE 82
+#define RTP_WARNTONE 83
+#define RTP_INTRTONE 84
+#define RTP_CALLCDTONE 85
+#define RTP_PAYPHONE 86
+#define RTP_CAS 87
+#define RTP_OFFHKWARN 88
+#define RTP_RING 89
+
+#define RTP_ACCPTTONE 96
+#define RTP_CONFIRMTN 97
+#define RTP_DLTNRECALL 98
+#define RTP_END3WAYTN 99
+#define RTP_FACTONE 100
+#define RTP_LNLOCKTN 101
+#define RTP_NUMUNOBT 102
+#define RTP_OFFERGTONE 103
+#define RTP_PERMSIGTN 104
+#define RTP_PREEMPTTN 105
+#define RTP_QUETONE 106
+#define RTP_REFUSALTN 107
+#define RTP_ROUTETONE 108
+#define RTP_VALIDTONE 109
+#define RTP_WAITGTONE 110
+#define RTP_WARNEOPTN 111
+#define RTP_WARNPIPTN 112
+
+#define RTP_MF0 128
+#define RTP_MF1 129
+#define RTP_MF2 130
+#define RTP_MF3 131
+#define RTP_MF4 132
+#define RTP_MF5 133
+#define RTP_MF6 134
+#define RTP_MF7 135
+#define RTP_MF8 136
+#define RTP_MF9 137
+#define RTP_K0 138
+#define RTP_K1 139
+#define RTP_K2 140
+#define RTP_S0 141
+#define RTP_S1 142
+#define RTP_S3 143
+
+#define RTP_WINK 160
+#define RTP_WINKOFF 161
+#define RTP_INCSEIZ 162
+#define RTP_SEIZURE 163
+#define RTP_UNSEIZE 164
+#define RTP_COT 165
+#define RTP_DEFCOT 166
+#define RTP_COTTONE 167
+#define RTP_COTSEND 168
+
+#define RTP_COTVERFD 170
+#define RTP_LOOPBACK 171
+#define RTP_MWATTTONE 172
+#define RTP_NEWMWATTTN 173
+
+static const value_string rtp_event_type_values[] =
+{
+
+ { RTP_DTMF_0, "DTMF Zero 0" },
+ { RTP_DTMF_1, "DTMF One 1" },
+ { RTP_DTMF_2, "DTMF Two 2" },
+ { RTP_DTMF_3, "DTMF Three 3" },
+ { RTP_DTMF_4, "DTMF Four 4" },
+ { RTP_DTMF_5, "DTMF Five 5" },
+ { RTP_DTMF_6, "DTMF Six 6" },
+ { RTP_DTMF_7, "DTMF Seven 7" },
+ { RTP_DTMF_8, "DTMF Eight 8" },
+ { RTP_DTMF_9, "DTMF Nine 9" },
+ { RTP_DTMF_STAR, "DTMF Star *" },
+ { RTP_DTMF_POUND, "DTMF Pound #" },
+ { RTP_DTMF_A, "DTMF A" },
+ { RTP_DTMF_B, "DTMF B" },
+ { RTP_DTMF_C, "DTMF C" },
+ { RTP_DTMF_D, "DTMF D" },
+ { RTP_DTMF_FLASH, "Flash" },
+ { RTP_ANS, "Fax ANS"},
+ { RTP_ANSREV, "Fax /ANS"},
+ { RTP_ANSAM, "Fax ANSam"},
+ { RTP_ANSAMREV, "Fax /ANSam"},
+ { RTP_CNG, "Fax CNG"},
+ { RTP_V21C1B0, "V.21 channel 1, 0 bit"},
+ { RTP_V21C1B1, "V.21 channel 1, 1 bit"},
+ { RTP_V21C2B0, "V.21 channel 2, 0 bit"},
+ { RTP_V21C2B1, "V.21 channel 2, 1 bit"},
+ { RTP_CRDI, "Fax CRdi"},
+ { RTP_CRDR, "Fax CRdr"},
+ { RTP_CRE, "Fax CRe"},
+ { RTP_ESI, "Fax ESi"},
+ { RTP_ESR, "Fax ESr"},
+ { RTP_MRDI, "Fax MRdi"},
+ { RTP_MRDR, "Fax MRdr"},
+ { RTP_MRE, "Fax MRe"},
+ { RTP_CT, "Fax CT"},
+ { RTP_OFFHOOK, "Off Hook"},
+ { RTP_ONHOOK, "On Hook"},
+ { RTP_DIALTONE, "Dial tone"},
+ { RTP_INTDT, "PABX internal dial tone"},
+ { RTP_SPCDT, "Special dial tone"},
+ { RTP_2NDDT, "Second dial tone"},
+ { RTP_RGTONE, "Ringing tone"},
+ { RTP_SPRGTONE, "Special ringing tone"},
+ { RTP_BUSYTONE, "Busy tone"},
+ { RTP_CNGTONE, "Congestion tone"},
+ { RTP_SPINFOTN, "Special information tone"},
+ { RTP_CMFTTONE, "Comfort tone"},
+ { RTP_HOLDTONE, "Hold tone"},
+ { RTP_RECTONE, "Record tone"},
+ { RTP_CLRWTTONE, "Caller waiting tone"},
+ { RTP_CWTONE, "Call waiting tone"},
+ { RTP_PAYTONE, "Pay tone"},
+ { RTP_POSINDTONE, "Positive indication tone"},
+ { RTP_NEGINDTONE, "Negative indication tone"},
+ { RTP_WARNTONE, "Warning tone"},
+ { RTP_INTRTONE, "Intrusion tone"},
+ { RTP_CALLCDTONE, "Calling card service tone"},
+ { RTP_PAYPHONE, "Payphone recognition tone"},
+ { RTP_CAS, "CPE alerting signal (CAS)"},
+ { RTP_OFFHKWARN, "Off-hook warning tone"},
+ { RTP_RING, "Ring"},
+ { RTP_ACCPTTONE, "Acceptance tone"},
+ { RTP_CONFIRMTN, "Confirmation tone"},
+ { RTP_DLTNRECALL, "Dial tone, recall"},
+ { RTP_END3WAYTN, "End of three party service tone"},
+ { RTP_FACTONE, "Facilities tone"},
+ { RTP_LNLOCKTN, "Line lockout tone"},
+ { RTP_NUMUNOBT, "Number unobtainable tone"},
+ { RTP_OFFERGTONE, "Offering tone"},
+ { RTP_PERMSIGTN, "Permanent signal tone"},
+ { RTP_PREEMPTTN, "Preemption tone"},
+ { RTP_QUETONE, "Queue tone"},
+ { RTP_REFUSALTN, "Refusal tone"},
+ { RTP_ROUTETONE, "Route tone"},
+ { RTP_VALIDTONE, "Valid tone"},
+ { RTP_WAITGTONE, "Waiting tone"},
+ { RTP_WARNEOPTN, "Warning tone (end of period)"},
+ { RTP_WARNPIPTN, "Warning Tone (PIP tone)"},
+ { RTP_MF0, "MF 0"},
+ { RTP_MF1, "MF 1"},
+ { RTP_MF2, "MF 2"},
+ { RTP_MF3, "MF 3"},
+ { RTP_MF4, "MF 4"},
+ { RTP_MF5, "MF 5"},
+ { RTP_MF6, "MF 6"},
+ { RTP_MF7, "MF 7"},
+ { RTP_MF8, "MF 8"},
+ { RTP_MF9, "MF 9"},
+ { RTP_K0, "MF K0 or KP (start-of-pulsing)"},
+ { RTP_K1, "MF K1"},
+ { RTP_K2, "MF K2"},
+ { RTP_S0, "MF S0 to ST (end-of-pulsing)"},
+ { RTP_S1, "MF S1"},
+ { RTP_S3, "MF S3"},
+ { RTP_WINK, "Wink"},
+ { RTP_WINKOFF, "Wink off"},
+ { RTP_INCSEIZ, "Incoming seizure"},
+ { RTP_SEIZURE, "Seizure"},
+ { RTP_UNSEIZE, "Unseize circuit"},
+ { RTP_COT, "Continuity test"},
+ { RTP_DEFCOT, "Default continuity tone"},
+ { RTP_COTTONE, "Continuity tone (single tone)"},
+ { RTP_COTSEND, "Continuity test send"},
+ { RTP_COTVERFD, "Continuity verified"},
+ { RTP_LOOPBACK, "Loopback"},
+ { RTP_MWATTTONE, "Old milliwatt tone (1000 Hz)"},
+ { RTP_NEWMWATTTN, "New milliwatt tone (1004 Hz)"},
+ { 0, NULL },
+};
diff --git a/epan/dissectors/packet-rtp.c b/epan/dissectors/packet-rtp.c
new file mode 100644
index 0000000000..900b01c2be
--- /dev/null
+++ b/epan/dissectors/packet-rtp.c
@@ -0,0 +1,979 @@
+/* packet-rtp.c
+ *
+ * Routines for RTP dissection
+ * RTP = Real time Transport Protocol
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Written by Andreas Sikkema <h323@ramdyne.nl>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This dissector tries to dissect the RTP protocol according to Annex A
+ * of ITU-T Recommendation H.225.0 (02/98) or RFC 1889
+ *
+ * RTP traffic is handled by an even UDP portnumber. This can be any
+ * port number, but there is a registered port available, port 5004
+ * See Annex B of ITU-T Recommendation H.225.0, section B.7
+ *
+ * This doesn't dissect older versions of RTP, such as:
+ *
+ * the vat protocol ("version 0") - see
+ *
+ * ftp://ftp.ee.lbl.gov/conferencing/vat/alpha-test/vatsrc-4.0b2.tar.gz
+ *
+ * and look in "session-vat.cc" if you want to write a dissector
+ * (have fun - there aren't any nice header files showing the packet
+ * format);
+ *
+ * version 1, as documented in
+ *
+ * ftp://gaia.cs.umass.edu/pub/hgschulz/rtp/draft-ietf-avt-rtp-04.txt
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-rtp.h"
+#include "rtp_pt.h"
+#include <epan/conversation.h>
+#include "tap.h"
+
+#include "prefs.h"
+
+static dissector_handle_t rtp_handle;
+
+static int rtp_tap = -1;
+
+static dissector_table_t rtp_pt_dissector_table;
+
+/* RTP header fields */
+static int proto_rtp = -1;
+static int hf_rtp_version = -1;
+static int hf_rtp_padding = -1;
+static int hf_rtp_extension = -1;
+static int hf_rtp_csrc_count = -1;
+static int hf_rtp_marker = -1;
+static int hf_rtp_payload_type = -1;
+static int hf_rtp_seq_nr = -1;
+static int hf_rtp_timestamp = -1;
+static int hf_rtp_ssrc = -1;
+static int hf_rtp_csrc_item = -1;
+static int hf_rtp_data = -1;
+static int hf_rtp_padding_data = -1;
+static int hf_rtp_padding_count= -1;
+
+/* RTP header extension fields */
+static int hf_rtp_prof_define = -1;
+static int hf_rtp_length = -1;
+static int hf_rtp_hdr_ext = -1;
+
+/* RTP setup fields */
+static int hf_rtp_setup = -1;
+static int hf_rtp_setup_frame = -1;
+static int hf_rtp_setup_method = -1;
+
+/* RTP fields defining a sub tree */
+static gint ett_rtp = -1;
+static gint ett_csrc_list = -1;
+static gint ett_hdr_ext = -1;
+static gint ett_rtp_setup = -1;
+
+static dissector_handle_t data_handle;
+
+static gboolean dissect_rtp_heur( tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree );
+static void dissect_rtp( tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree );
+static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/* Preferences bool to control whether or not setup info should be shown */
+static gboolean global_rtp_show_setup_info = TRUE;
+
+/* Try heuristic RTP decode */
+static gboolean global_rtp_heur = FALSE;
+
+/* Memory chunk for storing conversation and per-packet info */
+static GMemChunk *rtp_conversations = NULL;
+
+/*
+ * Fields in the first octet of the RTP header.
+ */
+
+/* Version is the first 2 bits of the first octet*/
+#define RTP_VERSION(octet) ((octet) >> 6)
+
+/* Padding is the third bit; No need to shift, because true is any value
+ other than 0! */
+#define RTP_PADDING(octet) ((octet) & 0x20)
+
+/* Extension bit is the fourth bit */
+#define RTP_EXTENSION(octet) ((octet) & 0x10)
+
+/* CSRC count is the last four bits */
+#define RTP_CSRC_COUNT(octet) ((octet) & 0xF)
+
+static const value_string rtp_version_vals[] =
+{
+ { 0, "Old VAT Version" },
+ { 1, "First Draft Version" },
+ { 2, "RFC 1889 Version" },
+ { 0, NULL },
+};
+
+/*
+ * Fields in the second octet of the RTP header.
+ */
+
+/* Marker is the first bit of the second octet */
+#define RTP_MARKER(octet) ((octet) & 0x80)
+
+/* Payload type is the last 7 bits */
+#define RTP_PAYLOAD_TYPE(octet) ((octet) & 0x7F)
+
+const value_string rtp_payload_type_vals[] =
+{
+ { PT_PCMU, "ITU-T G.711 PCMU" },
+ { PT_1016, "USA Federal Standard FS-1016" },
+ { PT_G721, "ITU-T G.721" },
+ { PT_GSM, "GSM 06.10" },
+ { PT_G723, "ITU-T G.723" },
+ { PT_DVI4_8000, "DVI4 8000 samples/s" },
+ { PT_DVI4_16000, "DVI4 16000 samples/s" },
+ { PT_LPC, "Experimental linear predictive encoding from Xerox PARC" },
+ { PT_PCMA, "ITU-T G.711 PCMA" },
+ { PT_G722, "ITU-T G.722" },
+ { PT_L16_STEREO, "16-bit uncompressed audio, stereo" },
+ { PT_L16_MONO, "16-bit uncompressed audio, monaural" },
+ { PT_QCELP, "Qualcomm Code Excited Linear Predictive coding" },
+ { PT_CN, "Comfort noise" },
+ { PT_MPA, "MPEG-I/II Audio"},
+ { PT_G728, "ITU-T G.728" },
+ { PT_DVI4_11025, "DVI4 11025 samples/s" },
+ { PT_DVI4_22050, "DVI4 22050 samples/s" },
+ { PT_G729, "ITU-T G.729" },
+ { PT_CN_OLD, "Comfort noise (old)" },
+ { PT_CELB, "Sun CellB video encoding" },
+ { PT_JPEG, "JPEG-compressed video" },
+ { PT_NV, "'nv' program" },
+ { PT_H261, "ITU-T H.261" },
+ { PT_MPV, "MPEG-I/II Video"},
+ { PT_MP2T, "MPEG-II transport streams"},
+ { PT_H263, "ITU-T H.263" },
+ { 0, NULL },
+};
+
+static address fake_addr;
+
+/* Set up an RTP conversation */
+void rtp_add_address(packet_info *pinfo,
+ const unsigned char* ip_addr, int port,
+ int other_port,
+ gchar *setup_method, guint32 setup_frame_number)
+{
+ address src_addr;
+ conversation_t* p_conv = NULL;
+ struct _rtp_conversation_info *p_conv_data = NULL;
+
+ /*
+ * If this isn't the first time this packet has been processed,
+ * we've already done this work, so we don't need to do it
+ * again.
+ */
+ if (pinfo->fd->flags.visited)
+ {
+ return;
+ }
+
+ src_addr.type = pinfo->net_src.type;
+ src_addr.len = pinfo->net_src.len;
+ src_addr.data = ip_addr;
+
+ /*
+ * Check if the ip address and port combination is not
+ * already registered
+ */
+ p_conv = find_conversation( &src_addr, &src_addr, PT_UDP, port, other_port,
+ NO_ADDR_B | (!other_port ? NO_PORT_B : 0));
+
+ /*
+ * If not, add
+ */
+ if ( ! p_conv ) {
+ /* Create conversation data */
+ p_conv_data = g_mem_chunk_alloc(rtp_conversations);
+
+ /* Check length first time we look at method string */
+ strncpy(p_conv_data->method, setup_method,
+ (strlen(setup_method)+1 <= MAX_RTP_SETUP_METHOD_SIZE) ?
+ strlen(setup_method)+1 :
+ MAX_RTP_SETUP_METHOD_SIZE);
+ p_conv_data->method[MAX_RTP_SETUP_METHOD_SIZE] = '\0';
+ p_conv_data->frame_number = setup_frame_number;
+
+ /* Create conversation with this data */
+ p_conv = conversation_new( &src_addr, &src_addr, PT_UDP,
+ (guint32)port, (guint32)other_port,
+ NO_ADDR2 | (!other_port ? NO_PORT2 : 0));
+ conversation_add_proto_data(p_conv, proto_rtp, p_conv_data);
+
+ /* Set dissector */
+ conversation_set_dissector(p_conv, rtp_handle);
+ }
+ else
+ {
+ /* Update existing conversation data */
+ p_conv_data = conversation_get_proto_data(p_conv, proto_rtp);
+ strcpy(p_conv_data->method, setup_method);
+ p_conv_data->frame_number = setup_frame_number;
+ }
+}
+
+static void rtp_init( void )
+{
+ unsigned char* tmp_data;
+ int i;
+
+ /* (Re)allocate mem chunk for conversations */
+ if (rtp_conversations)
+ {
+ g_mem_chunk_destroy(rtp_conversations);
+ }
+ rtp_conversations = g_mem_chunk_new("rtp_conversations",
+ sizeof(struct _rtp_conversation_info),
+ 20 * sizeof(struct _rtp_conversation_info),
+ G_ALLOC_ONLY);
+
+ /* Create a fake adddress... */
+ fake_addr.type = AT_IPv4;
+ fake_addr.len = 4;
+
+ tmp_data = malloc( fake_addr.len );
+ for ( i = 0; i < fake_addr.len; i++) {
+ tmp_data[i] = 0;
+ }
+ fake_addr.data = tmp_data;
+}
+
+static gboolean
+dissect_rtp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ guint8 octet1, octet2;
+ unsigned int version;
+ unsigned int payload_type;
+ unsigned int offset = 0;
+
+ /* This is a heuristic dissector, which means we get all the UDP
+ * traffic not sent to a known dissector and not claimed by
+ * a heuristic dissector called before us!
+ */
+
+ if (! global_rtp_heur)
+ return FALSE;
+
+ /* Get the fields in the first octet */
+ octet1 = tvb_get_guint8( tvb, offset );
+ version = RTP_VERSION( octet1 );
+
+ if (version != 2) {
+ /* Unknown or unsupported version */
+ return FALSE;
+ }
+
+ /* Get the fields in the second octet */
+ octet2 = tvb_get_guint8( tvb, offset + 1 );
+ payload_type = RTP_PAYLOAD_TYPE( octet2 );
+ /* if (payload_type == PT_PCMU ||
+ * payload_type == PT_PCMA)
+ * payload_type == PT_G729)
+ * */
+ if (payload_type <= PT_H263) {
+ dissect_rtp( tvb, pinfo, tree );
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+static void
+dissect_rtp_data( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *rtp_tree, int offset, unsigned int data_len,
+ unsigned int data_reported_len, unsigned int payload_type )
+{
+ tvbuff_t *newtvb;
+
+ newtvb = tvb_new_subset( tvb, offset, data_len, data_reported_len );
+ if (!dissector_try_port(rtp_pt_dissector_table, payload_type, newtvb,
+ pinfo, tree))
+ proto_tree_add_item( rtp_tree, hf_rtp_data, newtvb, 0, -1, FALSE );
+}
+
+static void
+dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+ proto_item *ti = NULL;
+ proto_tree *rtp_tree = NULL;
+ proto_tree *rtp_csrc_tree = NULL;
+ guint8 octet1, octet2;
+ unsigned int version;
+ gboolean padding_set;
+ gboolean extension_set;
+ unsigned int csrc_count;
+ gboolean marker_set;
+ unsigned int payload_type;
+ unsigned int i = 0;
+ unsigned int hdr_extension= 0;
+ unsigned int padding_count;
+ gint length, reported_length;
+ int data_len;
+ unsigned int offset = 0;
+ guint16 seq_num;
+ guint32 timestamp;
+ guint32 sync_src;
+ guint32 csrc_item;
+
+ static struct _rtp_info rtp_info;
+
+ /* Get the fields in the first octet */
+ octet1 = tvb_get_guint8( tvb, offset );
+ version = RTP_VERSION( octet1 );
+
+ if (version != 2) {
+ /*
+ * Unknown or unsupported version.
+ */
+ if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) {
+ col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTP" );
+ }
+
+ if ( check_col( pinfo->cinfo, COL_INFO) ) {
+ col_add_fstr( pinfo->cinfo, COL_INFO,
+ "Unknown RTP version %u", version);
+ }
+
+ if ( tree ) {
+ ti = proto_tree_add_item( tree, proto_rtp, tvb, offset, -1, FALSE );
+ rtp_tree = proto_item_add_subtree( ti, ett_rtp );
+
+ proto_tree_add_uint( rtp_tree, hf_rtp_version, tvb,
+ offset, 1, octet1);
+ }
+ return;
+ }
+
+ padding_set = RTP_PADDING( octet1 );
+ extension_set = RTP_EXTENSION( octet1 );
+ csrc_count = RTP_CSRC_COUNT( octet1 );
+
+ /* Get the fields in the second octet */
+ octet2 = tvb_get_guint8( tvb, offset + 1 );
+ marker_set = RTP_MARKER( octet2 );
+ payload_type = RTP_PAYLOAD_TYPE( octet2 );
+
+ /* Get the subsequent fields */
+ seq_num = tvb_get_ntohs( tvb, offset + 2 );
+ timestamp = tvb_get_ntohl( tvb, offset + 4 );
+ sync_src = tvb_get_ntohl( tvb, offset + 8 );
+
+ /* fill in the rtp_info structure */
+ rtp_info.info_padding_set = padding_set;
+ rtp_info.info_padding_count = 0;
+ rtp_info.info_marker_set = marker_set;
+ rtp_info.info_payload_type = payload_type;
+ rtp_info.info_seq_num = seq_num;
+ rtp_info.info_timestamp = timestamp;
+ rtp_info.info_sync_src = sync_src;
+
+ /*
+ * Do we have all the data?
+ */
+ length = tvb_length_remaining(tvb, offset);
+ reported_length = tvb_reported_length_remaining(tvb, offset);
+ if (reported_length >= 0 && length >= reported_length) {
+ /*
+ * Yes.
+ */
+ rtp_info.info_all_data_present = TRUE;
+ rtp_info.info_data_len = reported_length;
+
+ /*
+ * Save the pointer to raw rtp data (header + payload incl.
+ * padding).
+ * That should be safe because the "epan_dissect_t"
+ * constructed for the packet has not yet been freed when
+ * the taps are called.
+ * (Destroying the "epan_dissect_t" will end up freeing
+ * all the tvbuffs and hence invalidating pointers to
+ * their data.)
+ * See "add_packet_to_packet_list()" for details.
+ */
+ rtp_info.info_data = tvb_get_ptr(tvb, 0, -1);
+ } else {
+ /*
+ * No - packet was cut short at capture time.
+ */
+ rtp_info.info_all_data_present = FALSE;
+ rtp_info.info_data_len = 0;
+ rtp_info.info_data = NULL;
+ }
+
+ if ( check_col( pinfo->cinfo, COL_PROTOCOL ) ) {
+ col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTP" );
+ }
+
+ if ( check_col( pinfo->cinfo, COL_INFO) ) {
+ col_add_fstr( pinfo->cinfo, COL_INFO,
+ "Payload type=%s, SSRC=%u, Seq=%u, Time=%u%s",
+ val_to_str( payload_type, rtp_payload_type_vals,
+ "Unknown (%u)" ),
+ sync_src,
+ seq_num,
+ timestamp,
+ marker_set ? ", Mark" : "");
+ }
+ if ( tree ) {
+ /* Create RTP protocol tree */
+ ti = proto_tree_add_item(tree, proto_rtp, tvb, offset, -1, FALSE );
+ rtp_tree = proto_item_add_subtree(ti, ett_rtp );
+
+ /* Conversation setup info */
+ if (global_rtp_show_setup_info)
+ {
+ show_setup_info(tvb, pinfo, rtp_tree);
+ }
+
+ proto_tree_add_uint( rtp_tree, hf_rtp_version, tvb,
+ offset, 1, octet1 );
+ proto_tree_add_boolean( rtp_tree, hf_rtp_padding, tvb,
+ offset, 1, octet1 );
+ proto_tree_add_boolean( rtp_tree, hf_rtp_extension, tvb,
+ offset, 1, octet1 );
+ proto_tree_add_uint( rtp_tree, hf_rtp_csrc_count, tvb,
+ offset, 1, octet1 );
+ offset++;
+
+ proto_tree_add_boolean( rtp_tree, hf_rtp_marker, tvb, offset,
+ 1, octet2 );
+ proto_tree_add_uint( rtp_tree, hf_rtp_payload_type, tvb,
+ offset, 1, octet2 );
+ offset++;
+
+ /* Sequence number 16 bits (2 octets) */
+ proto_tree_add_uint( rtp_tree, hf_rtp_seq_nr, tvb, offset, 2, seq_num );
+ offset += 2;
+
+ /* Timestamp 32 bits (4 octets) */
+ proto_tree_add_uint( rtp_tree, hf_rtp_timestamp, tvb, offset, 4, timestamp );
+ offset += 4;
+
+ /* Synchronization source identifier 32 bits (4 octets) */
+ proto_tree_add_uint( rtp_tree, hf_rtp_ssrc, tvb, offset, 4, sync_src );
+ offset += 4;
+ } else {
+ offset += 12;
+ }
+ /* CSRC list*/
+ if ( csrc_count > 0 ) {
+ if ( tree ) {
+ ti = proto_tree_add_text(rtp_tree, tvb, offset, csrc_count * 4, "Contributing Source identifiers");
+ rtp_csrc_tree = proto_item_add_subtree( ti, ett_csrc_list );
+ }
+ for (i = 0; i < csrc_count; i++ ) {
+ csrc_item = tvb_get_ntohl( tvb, offset );
+ if ( tree ) proto_tree_add_uint_format( rtp_csrc_tree,
+ hf_rtp_csrc_item, tvb, offset, 4,
+ csrc_item,
+ "CSRC item %d: %u",
+ i, csrc_item );
+ offset += 4;
+ }
+ }
+
+ /* Optional RTP header extension */
+ if ( extension_set ) {
+ /* Defined by profile field is 16 bits (2 octets) */
+ if ( tree ) proto_tree_add_uint( rtp_tree, hf_rtp_prof_define, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
+ offset += 2;
+
+ hdr_extension = tvb_get_ntohs( tvb, offset );
+ if ( tree ) proto_tree_add_uint( rtp_tree, hf_rtp_length, tvb,
+ offset, 2, hdr_extension);
+ offset += 2;
+ if ( hdr_extension > 0 ) {
+ if ( tree ) {
+ ti = proto_tree_add_text(rtp_tree, tvb, offset, csrc_count * 4, "Header extensions");
+ /* I'm re-using the old tree variable here
+ from the CSRC list!*/
+ rtp_csrc_tree = proto_item_add_subtree( ti,
+ ett_hdr_ext );
+ }
+ for (i = 0; i < hdr_extension; i++ ) {
+ if ( tree ) proto_tree_add_uint( rtp_csrc_tree, hf_rtp_hdr_ext, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
+ offset += 4;
+ }
+ }
+ }
+
+ if ( padding_set ) {
+ /*
+ * This RTP frame has padding - find it.
+ *
+ * The padding count is found in the LAST octet of
+ * the packet; it contains the number of octets
+ * that can be ignored at the end of the packet.
+ */
+ if (tvb_length(tvb) < tvb_reported_length(tvb)) {
+ /*
+ * We don't *have* the last octet of the
+ * packet, so we can't get the padding
+ * count.
+ *
+ * Put an indication of that into the
+ * tree, and just put in a raw data
+ * item.
+ */
+ if ( tree ) proto_tree_add_text(rtp_tree, tvb, 0, 0,
+ "Frame has padding, but not all the frame data was captured");
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1),
+ pinfo, rtp_tree);
+ return;
+ }
+
+ padding_count = tvb_get_guint8( tvb,
+ tvb_reported_length( tvb ) - 1 );
+ data_len =
+ tvb_reported_length_remaining( tvb, offset ) - padding_count;
+
+ rtp_info.info_payload_offset = offset;
+ rtp_info.info_payload_len = tvb_length_remaining(tvb, offset);
+ rtp_info.info_padding_count = padding_count;
+
+ if (data_len > 0) {
+ /*
+ * There's data left over when you take out
+ * the padding; dissect it.
+ */
+ dissect_rtp_data( tvb, pinfo, tree, rtp_tree,
+ offset,
+ data_len,
+ data_len,
+ payload_type );
+ offset += data_len;
+ } else if (data_len < 0) {
+ /*
+ * The padding count is bigger than the
+ * amount of RTP payload in the packet!
+ * Clip the padding count.
+ *
+ * XXX - put an item in the tree to indicate
+ * that the padding count is bogus?
+ */
+ padding_count =
+ tvb_reported_length_remaining(tvb, offset);
+ }
+ if (padding_count > 1) {
+ /*
+ * There's more than one byte of padding;
+ * show all but the last byte as padding
+ * data.
+ */
+ if ( tree ) proto_tree_add_item( rtp_tree, hf_rtp_padding_data,
+ tvb, offset, padding_count - 1, FALSE );
+ offset += padding_count - 1;
+ }
+ /*
+ * Show the last byte in the PDU as the padding
+ * count.
+ */
+ if ( tree ) proto_tree_add_item( rtp_tree, hf_rtp_padding_count,
+ tvb, offset, 1, FALSE );
+ }
+ else {
+ /*
+ * No padding.
+ */
+ dissect_rtp_data( tvb, pinfo, tree, rtp_tree, offset,
+ tvb_length_remaining( tvb, offset ),
+ tvb_reported_length_remaining( tvb, offset ),
+ payload_type );
+ rtp_info.info_payload_offset = offset;
+ rtp_info.info_payload_len = tvb_length_remaining(tvb, offset);
+ }
+ if (!pinfo->in_error_pkt)
+ tap_queue_packet(rtp_tap, pinfo, &rtp_info);
+}
+
+
+/* Look for conversation info and display any setup info found */
+void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* Conversation and current data */
+ conversation_t *p_conv = NULL;
+ struct _rtp_conversation_info *p_conv_data = NULL;
+
+ /* Use existing packet info if available */
+ p_conv_data = p_get_proto_data(pinfo->fd, proto_rtp);
+
+ if (!p_conv_data)
+ {
+ /* First time, get info from conversation */
+ p_conv = find_conversation(&pinfo->net_dst, &pinfo->net_src,
+ pinfo->ptype,
+ pinfo->destport, pinfo->srcport, NO_ADDR_B);
+ if (p_conv)
+ {
+ /* Create space for packet info */
+ struct _rtp_conversation_info *p_conv_packet_data;
+ p_conv_data = conversation_get_proto_data(p_conv, proto_rtp);
+
+ /* Save this conversation info into packet info */
+ p_conv_packet_data = g_mem_chunk_alloc(rtp_conversations);
+ strcpy(p_conv_packet_data->method, p_conv_data->method);
+ p_conv_packet_data->frame_number = p_conv_data->frame_number;
+ p_add_proto_data(pinfo->fd, proto_rtp, p_conv_packet_data);
+ }
+ }
+
+ /* Create setup info subtree with summary info. */
+ if (p_conv_data)
+ {
+ proto_tree *rtp_setup_tree;
+ proto_item *ti = proto_tree_add_string_format(tree, hf_rtp_setup, tvb, 0, 0,
+ "",
+ "Stream setup by %s (frame %d)",
+ p_conv_data->method,
+ p_conv_data->frame_number);
+ PROTO_ITEM_SET_GENERATED(ti);
+ rtp_setup_tree = proto_item_add_subtree(ti, ett_rtp_setup);
+ if (rtp_setup_tree)
+ {
+ /* Add details into subtree */
+ proto_item* item = proto_tree_add_uint(rtp_setup_tree, hf_rtp_setup_frame,
+ tvb, 0, 0, p_conv_data->frame_number);
+ PROTO_ITEM_SET_GENERATED(item);
+ item = proto_tree_add_string(rtp_setup_tree, hf_rtp_setup_method,
+ tvb, 0, 0, p_conv_data->method);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ }
+}
+
+
+void
+proto_register_rtp(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_rtp_version,
+ {
+ "Version",
+ "rtp.version",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(rtp_version_vals),
+ 0xC0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_padding,
+ {
+ "Padding",
+ "rtp.padding",
+ FT_BOOLEAN,
+ 8,
+ NULL,
+ 0x20,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_extension,
+ {
+ "Extension",
+ "rtp.ext",
+ FT_BOOLEAN,
+ 8,
+ NULL,
+ 0x10,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_csrc_count,
+ {
+ "Contributing source identifiers count",
+ "rtp.cc",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0F,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_marker,
+ {
+ "Marker",
+ "rtp.marker",
+ FT_BOOLEAN,
+ 8,
+ NULL,
+ 0x80,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_payload_type,
+ {
+ "Payload type",
+ "rtp.p_type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(rtp_payload_type_vals),
+ 0x7F,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_seq_nr,
+ {
+ "Sequence number",
+ "rtp.seq",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_timestamp,
+ {
+ "Timestamp",
+ "rtp.timestamp",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_ssrc,
+ {
+ "Synchronization Source identifier",
+ "rtp.ssrc",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_prof_define,
+ {
+ "Defined by profile",
+ "rtp.ext.profile",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_length,
+ {
+ "Extension length",
+ "rtp.ext.len",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_csrc_item,
+ {
+ "CSRC item",
+ "rtp.csrc.item",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_hdr_ext,
+ {
+ "Header extension",
+ "rtp.hdr_ext",
+ FT_UINT32,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_data,
+ {
+ "Payload",
+ "rtp.payload",
+ FT_BYTES,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_padding_data,
+ {
+ "Padding data",
+ "rtp.padding.data",
+ FT_BYTES,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_padding_count,
+ {
+ "Padding count",
+ "rtp.padding.count",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_rtp_setup,
+ {
+ "Stream setup",
+ "rtp.setup",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Stream setup, method and frame number", HFILL
+ }
+ },
+ {
+ &hf_rtp_setup_frame,
+ {
+ "Setup frame",
+ "rtp.setup-frame",
+ FT_FRAMENUM,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Frame that set up this stream", HFILL
+ }
+ },
+ {
+ &hf_rtp_setup_method,
+ {
+ "Setup Method",
+ "rtp.setup-method",
+ FT_STRING,
+ BASE_NONE,
+ NULL,
+ 0x0,
+ "Method used to set up this stream", HFILL
+ }
+ }
+
+ };
+
+ static gint *ett[] =
+ {
+ &ett_rtp,
+ &ett_csrc_list,
+ &ett_hdr_ext,
+ &ett_rtp_setup
+ };
+
+ module_t *rtp_module;
+
+
+ proto_rtp = proto_register_protocol("Real-Time Transport Protocol",
+ "RTP", "rtp");
+ proto_register_field_array(proto_rtp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("rtp", dissect_rtp, proto_rtp);
+ rtp_tap = register_tap("rtp");
+
+ rtp_pt_dissector_table = register_dissector_table("rtp.pt",
+ "RTP payload type", FT_UINT8, BASE_DEC);
+
+ rtp_module = prefs_register_protocol(proto_rtp, NULL);
+
+ prefs_register_bool_preference(rtp_module, "show_setup_info",
+ "Show stream setup information",
+ "Where available, show which protocol and frame caused "
+ "this RTP stream to be created",
+ &global_rtp_show_setup_info);
+
+ prefs_register_bool_preference(rtp_module, "heuristic_rtp",
+ "Try to decode RTP outside of conversations ",
+ "If call control SIP/H323/RTSP/.. messages are missing in the trace, "
+ "RTP isn't decoded without this",
+ &global_rtp_heur);
+
+ register_init_routine( &rtp_init );
+}
+
+void
+proto_reg_handoff_rtp(void)
+{
+ data_handle = find_dissector("data");
+
+ /*
+ * Register this dissector as one that can be selected by a
+ * UDP port number.
+ */
+ rtp_handle = find_dissector("rtp");
+ dissector_add_handle("udp.port", rtp_handle);
+
+ heur_dissector_add( "udp", dissect_rtp_heur, proto_rtp);
+}
diff --git a/epan/dissectors/packet-rtp.h b/epan/dissectors/packet-rtp.h
new file mode 100644
index 0000000000..788e060f1c
--- /dev/null
+++ b/epan/dissectors/packet-rtp.h
@@ -0,0 +1,65 @@
+/* packet-rtp.h
+ *
+ * Routines for RTP dissection
+ * RTP = Real time Transport Protocol
+ *
+ * $Id$
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Written by Andreas Sikkema <andreas.sikkema@philips.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+struct _rtp_info {
+ gboolean info_padding_set;
+ gboolean info_marker_set;
+ unsigned int info_payload_type;
+ unsigned int info_padding_count;
+ guint16 info_seq_num;
+ guint32 info_timestamp;
+ guint32 info_sync_src;
+ guint info_data_len; /* length of raw rtp data as reported */
+ gboolean info_all_data_present; /* FALSE if data is cut off */
+ guint info_payload_offset; /* start of payload relative to info_data */
+ guint info_payload_len; /* length of payload (incl padding) */
+ const guint8* info_data; /* pointer to raw rtp data */
+ /*
+ * info_data: pointer to raw rtp data = header + payload incl. padding.
+ * That should be safe because the "epan_dissect_t" constructed for the packet
+ * has not yet been freed when the taps are called.
+ * (destroying the "epan_dissect_t" will end up freeing all the tvbuffs
+ * and hence invalidating pointers to their data).
+ * See "add_packet_to_packet_list()" for details.
+ */
+};
+
+/* Info to save in RTP conversation / packet-info */
+#define MAX_RTP_SETUP_METHOD_SIZE 8
+struct _rtp_conversation_info
+{
+ gchar method[MAX_RTP_SETUP_METHOD_SIZE];
+ guint32 frame_number;
+};
+
+/* Add an RTP conversation with the given details */
+void rtp_add_address(packet_info *pinfo,
+ const unsigned char* ip_addr, int port,
+ int other_port,
+ gchar *setup_method, guint32 setup_frame_number);
diff --git a/epan/dissectors/packet-rtps.c b/epan/dissectors/packet-rtps.c
new file mode 100644
index 0000000000..6adcf73806
--- /dev/null
+++ b/epan/dissectors/packet-rtps.c
@@ -0,0 +1,1993 @@
+/* packet-rtps.c
+ * Routines for Real-Time Publish-Subscribe Protocol (RTPS) dissection
+ *
+ * Copyright 2003, LUKAS POKORNY <maskis@seznam.cz>
+ * PETR SMOLIK <petr.smolik@wo.cz>
+ * ZDENEK SEBEK <sebek@fel.cvut.cz>
+ *
+ * Czech Technical University in Prague
+ * Faculty of Electrical Engineering <www.fel.cvut.cz>
+ * Department of Control Engineering <dce.felk.cvut.cz>
+ *
+ * version: 2004/04/15 9:40:45
+ * dedication to Kj :]
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-udp.c, packet-tftp.c, packet-x25.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * *********************************************************************** */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include <epan/conversation.h>
+
+
+/* *********************************************************************** *
+ RTPS protocol was developed by Real Time Innovation, Inc.
+
+ Protocol specifikation and documenation you can find on these addresses:
+
+ http://www.rti.com/
+
+ http://www.rti.com/products/ndds/literature.html
+
+ http://www.schneider-electric.com.au/Products/Automation/TF_RealTime/
+ /technical%20library/specifications/WireProtocolExternal.pdf
+
+
+ * *********************************************************************** */
+
+
+
+/* redefine types because of definitions in 'packet-rtps.h' */
+/*
+#define u_int8_t guint8
+#define int8_t gint8
+
+#define u_int16_t guint16
+#define int16_t gint16
+
+#define u_int32_t guint32
+#define int32_t gint32
+*/
+
+#include "packet-rtps.h"
+
+/* number of APP_KIND byte in packet header */
+#define APP_KIND_BYTE 15
+
+
+/* definitions of flags */
+#define FLAG_E 0x01
+#define FLAG_F 0x02
+#define FLAG_I 0x02
+#define FLAG_M 0x02
+#define FLAG_P 0x02
+#define FLAG_A 0x04
+#define FLAG_H 0x08
+
+
+/* submessageId's ranges */
+#define SUBMSG_ID_MIN PAD
+#define SUBMSG_ID_MAX INFO_DST
+
+/* Vendor specific submessageId's ranges */
+#define VENDOR_SUBMSG_ID_MIN 0x80
+#define VENDOR_SUBMSG_ID_MAX 0xff
+
+/* *********************************************************************** */
+
+
+/* initialize the protocol and registered fields */
+static int proto_rtps = -1;
+static int hf_rtps_submessage_id = -1;
+static int hf_rtps_submessage_flags = -1;
+static int hf_rtps_octets_to_next_header = -1;
+static int hf_rtps_parameter_id = -1;
+static int hf_rtps_parameter_length = -1;
+static int hf_rtps_issue_data = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_rtps = -1;
+static gint ett_rtps_submessage = -1;
+static gint ett_rtps_bitmap = -1;
+static gint ett_rtps_parameter_sequence = -1;
+static gint ett_rtps_parameter = -1;
+
+/* Functions declarations */
+static void dissect_PAD(tvbuff_t *tvb,gint offset,guint8 flags,
+ int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+static void dissect_VAR(tvbuff_t *tvb,gint offset,guint8 flags,
+ gboolean little_endian,int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+static void dissect_ISSUE(tvbuff_t *tvb,gint offset,guint8 flags,
+ gboolean little_endian,int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+static void dissect_ACK(tvbuff_t *tvb,gint offset,guint8 flags,
+ gboolean little_endian,int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+static void dissect_HEARTBEAT(tvbuff_t *tvb,gint offset,guint8 flags,
+ gboolean little_endian,int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+static void dissect_GAP(tvbuff_t *tvb,gint offset,guint8 flags,
+ gboolean little_endian,int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+static void dissect_INFO_TS(tvbuff_t *tvb,gint offset,guint8 flags,
+ gboolean little_endian,int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+static void dissect_INFO_SRC(tvbuff_t *tvb,gint offset,guint8 flags,
+ gboolean little_endian,int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+static void dissect_INFO_REPLY(tvbuff_t *tvb,gint offset,guint8 flags,
+ gboolean little_endian,int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+static void dissect_INFO_DST(tvbuff_t *tvb,gint offset,guint8 flags,
+ int next_submsg_offset,
+ proto_tree *rtps_submessage_tree);
+
+static guint16 get_guint16(tvbuff_t *tvb, gint offset, gboolean little_endian);
+static guint32 get_guint32(tvbuff_t *tvb, gint offset, gboolean little_endian);
+
+static char *protocol_version_to_string(gint offset,tvbuff_t *tvb,char *buff);
+static char *vendor_id_to_string(gint offset, tvbuff_t *tvb, char *buff);
+
+static char *host_id_to_string(gint offset,tvbuff_t *tvb, char buff[]);
+static char *app_id_to_string(gint offset,tvbuff_t *tvb,char buff[]);
+static char *object_id_to_string(gint offset, tvbuff_t *tvb, char buff[]);
+
+static char *IP_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[]);
+static char *port_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[]);
+static char *get_NtpTime(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[]);
+
+static void get_bitmap(tvbuff_t *tvb, gint *p_offset, gboolean little_endian,
+ gint next_submsg, proto_tree *tree);
+
+static void get_parameter_sequence(tvbuff_t *tvb, gint *p_offset,
+ gboolean little_endian,
+ gint next_submsg_offset, proto_tree *tree);
+
+static gint seq_nr_to_string( gint offset, gboolean little_endian, tvbuff_t *tvb,
+ SequenceNumber *p_seqNumber);
+
+static const value_string submessage_id_vals[] = {
+ { PAD, "PAD" },
+ { VAR, "VAR" },
+ { ISSUE, "ISSUE" },
+ { ACK, "ACK" },
+ { HEARTBEAT, "HEARTBEAT" },
+ { GAP, "GAP" },
+ { INFO_TS, "INFO_TS" },
+ { INFO_SRC, "INFO_SRC" },
+ { INFO_REPLY, "INFO_REPLY" },
+ { INFO_DST, "INFO_DST" },
+ { APP_QUIT, "APP_QUIT" },
+ { 0, NULL }
+};
+
+static const value_string parameter_id_vals[] = {
+ { PID_PAD, "PID_PAD" },
+ { PID_SENTINEL, "PID_SENTINEL" },
+ { PID_EXPIRATION_TIME, "PID_EXPIRATION_TIME" },
+ { PID_PERSISTENCE, "PID_PERSISTENCE" },
+ { PID_MINIMUM_SEPARATION, "PID_MINIMUM_SEPARATION" },
+ { PID_TOPIC, "PID_TOPIC" },
+ { PID_STRENGTH, "PID_STRENGTH" },
+ { PID_TYPE_NAME, "PID_TYPE_NAME" },
+ { PID_TYPE_CHECKSUM, "PID_TYPE_CHECKSUM" },
+ { RTPS_PID_TYPE2_NAME, "RTPS_PID_TYPE2_NAME" },
+ { RTPS_PID_TYPE2_CHECKSUM, "RTPS_PID_TYPE2_CHECKSUM" },
+ { PID_METATRAFFIC_MULTICAST_IPADDRESS, "PID_METATRAFFIC_MULTICAST_IPADDRESS" },
+ { PID_APP_IPADDRESS, "PID_APP_IPADDRESS" },
+ { PID_METATRAFFIC_UNICAST_PORT, "PID_METATRAFFIC_UNICAST_PORT" },
+ { PID_USERDATA_UNICAST_PORT, "PID_USERDATA_UNICAST_PORT" },
+ { PID_IS_RELIABLE, "PID_IS_RELIABLE" },
+ { PID_EXPECTS_ACK, "PID_EXPECTS_ACK" },
+ { PID_USERDATA_MULTICAST_IPADDRESS, "PID_USERDATA_MULTICAST_IPADDRESS" },
+ { PID_MANAGER_KEY, "PID_MANAGER_KEY" },
+ { PID_SEND_QUEUE_SIZE, "PID_SEND_QUEUE_SIZE" },
+ { PID_RELIABILITY_ENABLED, "PID_RELIABILITY_ENABLED" },
+ { PID_PROTOCOL_VERSION, "PID_PROTOCOL_VERSION" },
+ { PID_VENDOR_ID, "PID_VENDOR_ID" },
+ { PID_VARGAPPS_SEQUENCE_NUMBER_LAST, "PID_VARGAPPS_SEQUENCE_NUMBER_LAST" },
+ { PID_RECV_QUEUE_SIZE, "PID_RECV_QUEUE_SIZE" },
+ { PID_RELIABILITY_OFFERED, "PID_RELIABILITY_OFFERED" },
+ { PID_RELIABILITY_REQUESTED, "PID_RELIABILITY_REQUESTED" },
+ { 0, NULL }
+};
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * Code to actually dissect the packets *
+ * *
+ * *********************************************************************** */
+
+static gboolean
+dissect_rtps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *rtps_tree=NULL;
+ gint offset = 0;
+ gint appKind;
+ proto_tree *rtps_submessage_tree;
+ guint8 submessageId;
+ guint8 flags;
+ gboolean little_endian;
+ int next_submsg;
+ int count_msg_type[11];
+ char buff[200], buff_tmp[30];/* buffers */
+
+ /* offset is the byte offset of 'tvb' at which the new tvbuff
+ should start. The first byte is the 0th byte. */
+
+ /* --- making disition if protocol is RTPS protocol --- */
+ if (!tvb_bytes_exist(tvb, offset, 4)) return FALSE;
+ if (tvb_get_guint8(tvb,offset++) != 'R') return FALSE;
+ if (tvb_get_guint8(tvb,offset++) != 'T') return FALSE;
+ if (tvb_get_guint8(tvb,offset++) != 'P') return FALSE;
+ if (tvb_get_guint8(tvb,offset++) != 'S') return FALSE;
+
+ /* --- Make entries in Protocol column ---*/
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPS");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ memset(count_msg_type, 0, sizeof(count_msg_type));
+
+ if (tree) {
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_rtps, tvb, 0, -1, FALSE);
+ rtps_tree = proto_item_add_subtree(ti, ett_rtps);
+
+ /* Protocol Version */
+ proto_tree_add_text(rtps_tree, tvb, offset, 2,
+ "Protocol RTPS, version %s",
+ protocol_version_to_string(offset, tvb, buff));
+ offset +=2;
+
+ /* Vendor Id */
+ proto_tree_add_text(rtps_tree, tvb, offset, 2,
+ "VendorId: %s",
+ vendor_id_to_string(offset, tvb, buff));
+ offset +=2;
+
+ /* Host Id */
+ proto_tree_add_text(rtps_tree, tvb, offset, 4,
+ "HostId: %s",
+ host_id_to_string(offset,tvb,buff));
+ offset +=4;
+
+ /* App Id */
+ proto_tree_add_text(rtps_tree, tvb, offset, 4,
+ "App ID: %s",
+ app_id_to_string(offset, tvb, buff));
+
+ }
+
+ /* offset behind RTPS's Header */
+ offset=16;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ submessageId = tvb_get_guint8(tvb, offset);
+ if (submessageId & 0x80) {
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "Submessage: %s",
+ val_to_str(submessageId, submessage_id_vals,
+ "Vendor-specific (0x%02X)"));
+ } else {
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "Submessage: %s",
+ val_to_str(submessageId, submessage_id_vals,
+ "Unknown (0x%02X)"));
+ }
+ rtps_submessage_tree = proto_item_add_subtree(ti, ett_rtps_submessage);
+ if (submessageId & 0x80) {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_submessage_id,
+ tvb, offset, 1, submessageId,
+ "Submessage Id: Vendor-specific (0x%02x)",
+ submessageId);
+ } else {
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_id,
+ tvb, offset, 1, submessageId);
+ }
+
+ flags = tvb_get_guint8(tvb, offset + 1);
+ /* E flag |XXXX|HAPE| => masks with 000000001b = 1 */
+ if ((flags & FLAG_E) != 0) little_endian = TRUE;
+ else little_endian = FALSE;
+
+ next_submsg = get_guint16(tvb, offset + 2, little_endian);
+ proto_item_set_len(ti, next_submsg);
+
+ switch (submessageId)
+ {
+ case PAD:
+ if (tree)
+ dissect_PAD(tvb, offset + 1, flags, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[0]++;
+ break;
+ case VAR:
+ if (tree)
+ dissect_VAR(tvb, offset + 1, flags, little_endian, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[1]++;
+ break;
+ case ISSUE:
+ if (tree)
+ dissect_ISSUE(tvb, offset + 1, flags, little_endian, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[2]++;
+ break;
+ case ACK:
+ if (tree)
+ dissect_ACK(tvb, offset + 1, flags, little_endian, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[3]++;
+ break;
+ case HEARTBEAT:
+ if (tree)
+ dissect_HEARTBEAT(tvb, offset + 1, flags, little_endian, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[4]++;
+ break;
+ case GAP:
+ if (tree)
+ dissect_GAP(tvb, offset + 1, flags, little_endian, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[5]++;
+ break;
+ case INFO_TS:
+ if (tree)
+ dissect_INFO_TS(tvb, offset + 1, flags, little_endian, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[6]++;
+ break;
+ case INFO_SRC:
+ if (tree)
+ dissect_INFO_SRC(tvb, offset + 1, flags, little_endian, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[7]++;
+ break;
+ case INFO_REPLY:
+ if (tree)
+ dissect_INFO_REPLY(tvb, offset + 1, flags, little_endian, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[8]++;
+ break;
+ case INFO_DST:
+ if (tree)
+ dissect_INFO_DST(tvb, offset + 1, flags, next_submsg,
+ rtps_submessage_tree);
+ count_msg_type[9]++;
+ break;
+ default:
+ if (tree) {
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset + 1, 1, flags);
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset + 2, 2, next_submsg);
+ }
+ break;
+ }
+
+ /* next submessage's offset */
+ offset += next_submsg+4;
+
+ }
+
+ /* --- and Info column on summary display ---*/
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ appKind = tvb_get_guint8(tvb, APP_KIND_BYTE);
+
+ if (appKind == MANAGEDAPPLICATION ) {sprintf(buff,"App: ");}
+ if (appKind == MANAGER) {sprintf(buff,"Man: ");}
+ if (appKind == AID_UNKNOWN) {sprintf(buff,"Unknown:");}
+
+ if (appKind != MANAGEDAPPLICATION && appKind != MANAGER &&
+ appKind != AID_UNKNOWN) {sprintf(buff,"ERROR in APP type");}
+
+ /* -- counts of submessages - for Information Frame */
+ if (count_msg_type[0]>0) {
+ sprintf(buff_tmp,"PAD(%d) ",count_msg_type[0]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[1]>0) {
+ sprintf(buff_tmp,"VAR(%d) ",count_msg_type[1]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[2]>0) {
+ sprintf(buff_tmp,"ISSUE(%d) ",count_msg_type[2]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[3]>0) {
+ sprintf(buff_tmp,"ACK(%d) ",count_msg_type[3]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[4]>0) {
+ sprintf(buff_tmp,"HEARTBEAT(%d) ",count_msg_type[4]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[5]>0) {
+ sprintf(buff_tmp,"GAP(%d) ",count_msg_type[5]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[6]>0) {
+ sprintf(buff_tmp,"INFO_TS(%d) ",count_msg_type[6]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[7]>0) {
+ sprintf(buff_tmp, "INFO_SRC(%d) ",count_msg_type[7]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[8]>0) {
+ sprintf(buff_tmp,"INFO_REPLY(%d) ",count_msg_type[8]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[9]>0) {
+ sprintf(buff_tmp,"INFO_DST(%d) ",count_msg_type[9]);
+ strcat(buff,buff_tmp);
+ }
+
+ if (count_msg_type[10]>0) {
+ sprintf(buff_tmp,"vendor specific(%d) ",count_msg_type[10]);
+ strcat(buff,buff_tmp);
+ }
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, buff);
+
+ }
+
+
+ return TRUE;
+
+} /* end dissect_rtps(...) */
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get 16 bit from the stream *
+ * *
+ * *********************************************************************** */
+
+static guint16 get_guint16(tvbuff_t *tvb, gint offset, gboolean little_endian)
+{
+ guint16 value;
+
+ if (little_endian)
+ value = tvb_get_letohs(tvb, offset);
+ else
+ value = tvb_get_ntohs(tvb, offset);
+
+ return(value);
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get 32 bit from the stream *
+ * *
+ * *********************************************************************** */
+
+static guint32 get_guint32(tvbuff_t *tvb, gint offset, gboolean little_endian)
+{
+ guint32 value;
+
+ if (little_endian)
+ value = tvb_get_letohl(tvb, offset);
+ else
+ value = tvb_get_ntohl(tvb, offset);
+
+ return(value);
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get Protocol version *
+ * *
+ * *********************************************************************** */
+
+static char *
+protocol_version_to_string(gint offset,tvbuff_t *tvb,char *buff)
+{
+ guint8 major, minor;
+
+ /* protocol verzion = major.minor */
+ major = tvb_get_guint8(tvb, offset);
+ minor = tvb_get_guint8(tvb, (offset+1));
+
+ sprintf(buff,"%d.%d", major, minor);
+ return(buff);
+
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get Vendor Id *
+ * *
+ * *********************************************************************** */
+
+static char *
+vendor_id_to_string(gint offset, tvbuff_t *tvb, char *buff)
+{
+ guint8 major, minor;
+ VendorId vendorId_rti;
+
+ VENDOR_ID_RTI(vendorId_rti);
+
+ major = tvb_get_guint8(tvb, offset);
+ minor = tvb_get_guint8(tvb, (offset+1));
+
+ if (major == vendorId_rti.major &&
+ minor == vendorId_rti.minor)
+ { sprintf(buff,"Real-Time Innovations,Inc.,CA,USA");
+ return(buff); }
+
+ sprintf(buff,"Vendor unknown");
+ return(buff);
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get IP Address *
+ * *
+ * *********************************************************************** */
+
+static char *
+IP_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[])
+{
+ IPAddress ip;
+ guint8 a = 0, b = 0, c = 0, d = 0; /* IP Adresss = a.b.c.d */
+
+ ip = get_guint32(tvb, offset, little_endian);
+ /* get_guint32() - reads + endian conversion */
+ a = (ip >> 24);
+ b = (ip >> 16) & 0xff;
+ c = (ip >> 8) & 0xff;
+ d = ip & 0xff;
+
+ sprintf(buff,"%d.%d.%d.%d", a, b, c, d);
+ return(buff);
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get Port *
+ * *
+ * *********************************************************************** */
+
+static char *
+port_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[])
+{
+ Port port = get_guint32(tvb, offset, little_endian);
+ /* get_guint32() - reads + endian conversion */
+
+ if (port == PORT_INVALID)
+ sprintf(buff,"PORT_INVALID");
+ else
+ sprintf(buff,"0x%X",port);
+
+ return(buff);
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get NTP Time *
+ * *
+ * *********************************************************************** */
+
+static char *
+get_NtpTime(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[])
+{
+ NtpTime ntpTime;
+ float time;
+
+ /* get_guint32() - reads + endian conversion */
+ ntpTime.seconds = get_guint32(tvb, offset, little_endian);
+ ntpTime.fraction = get_guint32(tvb, (offset + 4), little_endian);
+ time = (float) ntpTime.seconds + (ntpTime.fraction / 2^(32));
+
+ sprintf(buff,"%f", time);
+ return(buff);
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get Host Id *
+ * *
+ * *********************************************************************** */
+
+static char *
+host_id_to_string(gint offset,tvbuff_t *tvb, char buff[])
+{
+ guint32 hostId = tvb_get_ntohl(tvb, offset);
+ /* get_ntohl() automaticaly convert data to BIG ENDIAN */
+
+ sprintf(buff,"0x%X", hostId);
+ return(buff);
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get AppID *
+ * *
+ * *********************************************************************** */
+
+static char *
+app_id_to_string(gint offset,tvbuff_t *tvb,char buff[])
+{
+ guint32 appId = tvb_get_ntohl(tvb, offset);
+ /* get_ntohl() automaticaly convert data to BIG ENDIAN */
+
+ /* Instance Id */
+ guint32 instanceId = (appId >> 8);
+ /* applicatin Kind */
+ guint8 appKind = (appId & 0xff);
+
+ if (appKind == MANAGEDAPPLICATION)
+ {
+ sprintf(buff,"Managed App, InstanceId: 0x%X",instanceId);
+ return(buff);
+ }
+
+ if (appKind == MANAGER)
+ {
+ sprintf(buff,"Manager, InstanceId: 0x%X",instanceId);
+ return(buff);
+ }
+
+ sprintf(buff,"Unknown");
+ return(buff);
+
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get Object_Id (32 bit) *
+ * *
+ * *********************************************************************** */
+
+static char *
+object_id_to_string(gint offset, tvbuff_t *tvb, char buff[])
+{
+ guint32 objectId = tvb_get_ntohl(tvb, offset);
+ /* get_ntohl() automaticaly convert data to BIG ENDIAN */
+
+ if (objectId == OID_UNKNOWN) { sprintf(buff,"Unknown ObjectId");
+ return(buff);}
+ if (objectId == OID_APP) { sprintf(buff,"applicationSelf");
+ return(buff);}
+ if (objectId == OID_WRITE_APPSELF){ sprintf(buff,"writerApplicationSelf");
+ return(buff);}
+ if (objectId == OID_WRITE_APP) { sprintf(buff,"writerApplications");
+ return(buff);}
+ if (objectId == OID_READ_APP) { sprintf(buff,"readerApplications");
+ return(buff);}
+ if (objectId == OID_WRITE_MGR) { sprintf(buff,"writerManagers");
+ return(buff);}
+ if (objectId == OID_READ_MGR) { sprintf(buff,"readerManagers ");
+ return(buff);}
+ if (objectId == OID_WRITE_PUBL) { sprintf(buff,"writerPublications");
+ return(buff);}
+ if (objectId == OID_READ_PUBL) { sprintf(buff,"readerPublications");
+ return(buff);}
+ if (objectId == OID_WRITE_SUBS) { sprintf(buff,"writerSubscriptions");
+ return(buff);}
+ if (objectId == OID_READ_SUBS) { sprintf(buff,"readerSubscriptions");
+ return(buff);}
+
+ /* nothing from the possibilites above */
+ sprintf(buff,"instanceId: 0x%X, objKind: 0x%X",
+ (objectId >> 8),(objectId & 0xff));
+ return(buff);
+
+/* for the future
+//Kind
+#define OID_APPLICATION 0x01
+#define OID_CSTWRITER 0x02
+#define OID_PUBLICATION 0x03
+#define OID_SUBSCRIPTION 0x04
+#define OID_CSTREADER 0x07
+//
+#define OID_USEROBJ 0x00
+#define OID_RESUSEROBJ 0x40
+#define OID_METAOBJ 0x80
+#define OID_RESMETAOBJ 0xC0
+*/
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get Sequence Number (64 bit) *
+ * *
+ * *********************************************************************** */
+
+static gint
+seq_nr_to_string(gint offset, gboolean little_endian, tvbuff_t *tvb,
+ SequenceNumber *p_seqNumber)
+{
+ p_seqNumber->high = get_guint32(tvb, offset, little_endian);
+ p_seqNumber->low = get_guint32(tvb, offset + 4, little_endian);
+
+ return(1);
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * get_Bitmap *
+ * *
+ * *********************************************************************** */
+
+static void
+get_bitmap(tvbuff_t *tvb, gint *p_offset, gboolean little_endian,
+ gint next_submsg, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *rtps_bitmap_tree;
+ gint i = 0;
+ gint offset = *p_offset;
+ SequenceNumber sequenceNumber;
+ guint32 num_bits;
+ guint num_longs;
+
+ /* making subtree for the bitmap */
+ ti = proto_tree_add_text(tree,tvb,offset,(next_submsg-offset),"Bitmap");
+ rtps_bitmap_tree = proto_item_add_subtree(ti, ett_rtps_bitmap);
+
+ /* SekvenceNumber bitmapBase */
+ seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
+ proto_tree_add_text(rtps_bitmap_tree, tvb, offset, 8,
+ "bitmapBase: 0x%X%X",
+ sequenceNumber.high, sequenceNumber.low);
+ offset +=8;
+
+ num_bits = get_guint32(tvb, offset, little_endian);
+ proto_tree_add_text(rtps_bitmap_tree, tvb, offset, 4,
+ "numBits: %u",
+ num_bits);
+ offset += 4;
+
+ if (num_bits+31 < num_bits)
+ num_longs = UINT_MAX; /* overflow */
+ else
+ num_longs = (num_bits+31)/32;
+ while (num_longs != 0)
+ {
+ if (next_submsg-offset < 4)
+ {
+ proto_tree_add_text(rtps_bitmap_tree, tvb, offset, next_submsg-offset,
+ "bitmap[%d]: < 4 bytes remain in message", i);
+ offset = next_submsg;
+ break;
+ }
+ proto_tree_add_text(rtps_bitmap_tree, tvb, offset, 4,
+ "bitmap[%d]: 0x%08X",
+ i, get_guint32(tvb, offset, little_endian));
+ offset +=4;
+ ++i;
+ --num_longs;
+ } /* end while */
+
+ *p_offset = offset;
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * dissect submessage: PAD *
+ * *
+ * (this submessage has no meaning and it is always valid) *
+ * *********************************************************************** */
+
+static void
+dissect_PAD(tvbuff_t *tvb, gint offset, guint8 flags,
+ int next_submsg_offset, proto_tree *rtps_submessage_tree)
+{
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset += 1;
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * dissect submessage: VAR *
+ * *
+ * *********************************************************************** */
+
+static void
+dissect_VAR(tvbuff_t *tvb, gint offset, guint8 flags, gboolean little_endian,
+ int next_submsg_offset, proto_tree *rtps_submessage_tree)
+{
+ int min_len;
+ char buff[200];
+ SequenceNumber writerSeqNumber;
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset +=1;
+
+ min_len = 20;
+ if ((flags & FLAG_H) != 0)
+ min_len += 8;
+ if ((flags & FLAG_P) != 0)
+ min_len += 4;
+ if (next_submsg_offset < min_len)
+ {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset,
+ "Octets to next header: %u (bogus, must be >= %u)",
+ next_submsg_offset, min_len);
+ return;
+ }
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+
+ /* readerObjectId*/
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Reader Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ /* writerObjectId*/
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Writer Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset+=4;
+
+ /* H flag |XXXX|HAPE| => masks with 00001000b = 8 */
+ if ((flags & FLAG_H) != 0)
+ {
+ /* HostId */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Host ID: %s",
+ host_id_to_string(offset,tvb,buff));
+ offset+=4;
+
+ /* App Id */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "App ID: %s",
+ app_id_to_string(offset, tvb, buff));
+ offset +=4;
+ }
+
+ /* Object Id */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ /* WriterSequence Number */
+ seq_nr_to_string(offset, little_endian, tvb, &writerSeqNumber);
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
+ "WriterSeqNumber: 0x%X%X",
+ writerSeqNumber.high, writerSeqNumber.low);
+ offset +=8;
+
+ /* P flag |XXXX|HAPE| => masks with 00000010b = 2 */
+ if ((flags & FLAG_P) != 0)
+ {
+ get_parameter_sequence(tvb, &offset, little_endian, next_submsg_offset,
+ rtps_submessage_tree);
+ }
+}
+
+/* *********************************************************************** */
+
+/* *********************************************************************** *
+ * *
+ * get_ParameterSequence *
+ * *
+ * *********************************************************************** */
+
+
+static void
+get_parameter_sequence(tvbuff_t *tvb, gint *p_offset, gboolean little_endian,
+ gint next_submsg_offset, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *rtps_parameter_sequence_tree;
+ proto_tree *rtps_parameter_tree;
+ gint offset = *p_offset;
+ guint16 parameter, param_length;
+ gint str_length;
+ SequenceNumber seqNumber;
+ char buff_tmp[MAX_PATHNAME];
+ int i;
+ char sep;
+
+ ti = proto_tree_add_text(tree, tvb, offset, (next_submsg_offset - offset),
+ "Parameters:");
+ rtps_parameter_sequence_tree = proto_item_add_subtree(ti,
+ ett_rtps_parameter_sequence);
+ for (;;)
+ {
+ if (next_submsg_offset-offset < 2)
+ {
+ proto_tree_add_text(rtps_parameter_sequence_tree, tvb, offset,
+ next_submsg_offset-offset,
+ "Parameter: < 2 bytes remain in message");
+ offset = next_submsg_offset;
+ break;
+ }
+ parameter = get_guint16(tvb, offset, little_endian);
+ ti = proto_tree_add_text(rtps_parameter_sequence_tree, tvb, offset, 2,
+ "%s",
+ val_to_str(parameter, parameter_id_vals,
+ "Unknown parameter (0x%04X)"));
+ rtps_parameter_tree = proto_item_add_subtree(ti, ett_rtps_parameter);
+ proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id,
+ tvb, offset, 2, parameter);
+ offset +=2;
+ if (next_submsg_offset-offset < 2)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset,
+ next_submsg_offset-offset,
+ "Parameter length: < 2 bytes remain in message");
+ offset = next_submsg_offset;
+ proto_item_set_end(ti, tvb, offset);
+ break;
+ }
+ param_length = get_guint16(tvb, offset, little_endian);
+ proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_length,
+ tvb, offset, 2, param_length);
+ offset +=2;
+
+ if (parameter == PID_SENTINEL) {
+ proto_item_set_end(ti, tvb, offset);
+ break;
+ }
+
+ if (next_submsg_offset-offset < param_length)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset,
+ next_submsg_offset-offset,
+ "Parameter value: < %u bytes remain in message",
+ param_length);
+ offset = next_submsg_offset;
+ proto_item_set_end(ti, tvb, offset);
+ break;
+ }
+ proto_item_set_end(ti, tvb, offset + param_length);
+
+ switch (parameter)
+ {
+ case PID_PAD:
+ proto_item_append_text(ti, ": -");
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Padding");
+ break;
+
+ case PID_EXPIRATION_TIME:
+ if (param_length < 8)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 8");
+ }
+ else
+ {
+ char *ntp_time_str;
+
+ ntp_time_str = get_NtpTime(offset, tvb, little_endian,buff_tmp);
+ proto_item_append_text(ti, ": %s", ntp_time_str);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Expiration time: %s", ntp_time_str);
+ }
+ break;
+
+ case PID_PERSISTENCE:
+ if (param_length < 8)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 8");
+ }
+ else
+ {
+ char *ntp_time_str;
+
+ ntp_time_str = get_NtpTime(offset, tvb, little_endian,buff_tmp);
+ proto_item_append_text(ti, ": %s", ntp_time_str);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Persistence: %s", ntp_time_str);
+ }
+ break;
+
+ case PID_MINIMUM_SEPARATION:
+ if (param_length < 8)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 8");
+ }
+ else
+ {
+ char *ntp_time_str;
+
+ ntp_time_str = get_NtpTime(offset, tvb, little_endian,buff_tmp);
+ proto_item_append_text(ti, ": %s", ntp_time_str);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Minimum separation: %s", ntp_time_str);
+ }
+ break;
+
+ case PID_TOPIC: /* --- ?? funguje spravne ?? */
+ str_length = tvb_strnlen(tvb, offset, param_length);
+ if (str_length == -1)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: Terminating zero missing");
+ }
+ else
+ {
+ char *str;
+
+ str = tvb_format_text(tvb, offset, str_length);
+ proto_item_append_text(ti, ": %s", str);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Topic: %s", str);
+ }
+ break;
+
+ case PID_STRENGTH:
+ if (param_length < 4)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 4");
+ }
+ else
+ {
+ guint32 strength;
+
+ strength = get_guint32(tvb, offset, little_endian);
+ proto_item_append_text(ti, ": 0x%X", strength);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Strength: 0x%X", strength);
+ }
+ break;
+
+ case PID_TYPE_NAME: /* --- ?? funguje spravne ?? */
+ str_length = tvb_strnlen(tvb, offset, param_length);
+ if (str_length == -1)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: Terminating zero missing");
+ }
+ else
+ {
+ char *str;
+
+ str = tvb_format_text(tvb, offset, str_length);
+ proto_item_append_text(ti, ": %s", str);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Type name: %s", str);
+ }
+ break;
+
+ case PID_TYPE_CHECKSUM:
+ /* nacitam jako UNSIGNED - nemuze to byt i zaporne cislo?? */
+ if (param_length < 4)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 4");
+ }
+ else
+ {
+ guint32 checksum;
+
+ checksum = get_guint32(tvb, offset, little_endian);
+ proto_item_append_text(ti, ": 0x%X", checksum);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Checksum: 0x%X", checksum);
+ }
+ break;
+
+ case RTPS_PID_TYPE2_NAME:
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Parameter data");
+ break;
+
+ case RTPS_PID_TYPE2_CHECKSUM:
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Parameter data");
+ break;
+
+ case PID_METATRAFFIC_MULTICAST_IPADDRESS:
+ i = 0;
+ sep = ':';
+ while (param_length >= 4)
+ {
+ char *ip_string;
+
+ ip_string = IP_to_string(offset, tvb, little_endian,buff_tmp);
+ proto_item_append_text(ti, "%c %s", sep, ip_string);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Address[%d]: %s", i, ip_string);
+ ++i;
+ offset +=4;
+ sep = ',';
+ param_length -= 4; /* decrement count */
+ }
+ offset += param_length;
+ break;
+
+ case PID_APP_IPADDRESS:
+ i = 0;
+ sep = ':';
+ while (param_length >= 4)
+ {
+ char *ip_string;
+
+ ip_string = IP_to_string(offset, tvb, little_endian,buff_tmp);
+ proto_item_append_text(ti, "%c %s", sep, ip_string);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Address[%d]: %s", i, ip_string);
+ ++i;
+ offset +=4;
+ sep = ',';
+ param_length -= 4; /* decrement count */
+ }
+ offset += param_length;
+ break;
+
+ case PID_METATRAFFIC_UNICAST_PORT:
+ if (param_length < 4)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 4");
+ }
+ else
+ {
+ char *port_str;
+
+ port_str = port_to_string(offset, tvb, little_endian,buff_tmp);
+ proto_item_append_text(ti, ": %s", port_str);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Port: %s", port_str);
+ }
+ break;
+
+ case PID_USERDATA_UNICAST_PORT:
+ if (param_length < 4)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 4");
+ }
+ else
+ {
+ char *port_str;
+
+ port_str = port_to_string(offset, tvb, little_endian,buff_tmp);
+ proto_item_append_text(ti, ": %s", port_str);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Port: %s", port_str);
+ }
+ break;
+
+ case PID_EXPECTS_ACK:
+ if (param_length < 1)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 1");
+ }
+ else
+ {
+ if (tvb_get_guint8(tvb, offset) == 0)
+ {
+ proto_item_append_text(ti, ": No");
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "ACK expected: No");
+ }
+ else
+ {
+ proto_item_append_text(ti, ": Yes");
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "ACK expected: Yes");
+ }
+ }
+ break;
+
+ case PID_USERDATA_MULTICAST_IPADDRESS:
+ i = 0;
+ sep = ':';
+ while (param_length >= 4)
+ {
+ char *ip_string;
+
+ ip_string = IP_to_string(offset, tvb, little_endian,buff_tmp);
+ proto_item_append_text(ti, "%c %s", sep, ip_string);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Address[%d]: %s", i, ip_string);
+ ++i;
+ offset +=4;
+ param_length -= 4; /* decrement count */
+ }
+ offset += param_length;
+ break;
+
+ case PID_MANAGER_KEY:
+ i = 0;
+ sep = ':';
+ while (param_length >= 4)
+ {
+ guint32 manager_key;
+
+ manager_key = get_guint32(tvb, offset, little_endian);
+ proto_item_append_text(ti, "%c 0x%X", sep, manager_key);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Key[%d]: 0x%X", i, manager_key);
+ ++i;
+ offset +=4;
+ sep = ',';
+ param_length -= 4; /* decrement count */
+ }
+ offset += param_length;
+ break;
+
+ case PID_SEND_QUEUE_SIZE:
+ if (param_length < 4)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 4");
+ }
+ else
+ {
+ guint32 send_queue_size;
+
+ send_queue_size = get_guint32(tvb, offset, little_endian);
+ proto_item_append_text(ti, ": %u", send_queue_size);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Send queue size: %u", send_queue_size);
+ }
+ break;
+
+ case PID_PROTOCOL_VERSION:
+ if (param_length < 2)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 2");
+ }
+ else
+ {
+ char *protocol_version_str;
+
+ protocol_version_str = protocol_version_to_string(offset, tvb, buff_tmp);
+ proto_item_append_text(ti, ": %s", protocol_version_str);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Protocol version: %s", protocol_version_str);
+ }
+ break;
+
+ case PID_VENDOR_ID:
+ if (param_length < 2)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 2");
+ }
+ else
+ {
+ char *vendor_id_str;
+
+ vendor_id_str = vendor_id_to_string(offset, tvb, buff_tmp);
+ proto_item_append_text(ti, ": %s", vendor_id_str);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Vendor ID: %s", vendor_id_str);
+ }
+ break;
+
+ case PID_VARGAPPS_SEQUENCE_NUMBER_LAST:
+ if (param_length < 8)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 8");
+ }
+ else
+ {
+ seq_nr_to_string(offset, little_endian, tvb, &seqNumber);
+ proto_item_append_text(ti, ": 0x%X%X",
+ seqNumber.high, seqNumber.low);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Sequence number: 0x%X%X",
+ seqNumber.high, seqNumber.low);
+ }
+ break;
+
+ case PID_RECV_QUEUE_SIZE:
+ if (param_length < 4)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 4");
+ }
+ else
+ {
+ guint32 recv_queue_size;
+
+ recv_queue_size = get_guint32(tvb, offset, little_endian);
+ proto_item_append_text(ti, ": %u", recv_queue_size);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Receive queue size: %u", recv_queue_size);
+ }
+ break;
+
+ case PID_RELIABILITY_OFFERED:
+ if (param_length < 4)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 4");
+ }
+ else
+ {
+ guint32 reliability_offered;
+
+ reliability_offered = get_guint32(tvb, offset, little_endian);
+ proto_item_append_text(ti, ": 0x%X", reliability_offered);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Reliability offered: 0x%X", reliability_offered);
+ }
+ break;
+
+ case PID_RELIABILITY_REQUESTED:
+ if (param_length < 4)
+ {
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Bad parameter: length < 4");
+ }
+ else
+ {
+ guint32 reliability_requested;
+
+ reliability_requested = get_guint32(tvb, offset, little_endian);
+ proto_item_append_text(ti, ": 0x%X", reliability_requested);
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Reliability requested: 0x%X", reliability_requested);
+ }
+ break;
+
+ default:
+ proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
+ "Unknown parameter value");
+ break;
+ } /* end switch */
+
+ offset += param_length;
+ }
+
+ *p_offset = offset;
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * subdissector for submessage: ISSUE *
+ * *
+ * *********************************************************************** */
+ /* hotovo 12.01.04 - JEN OTESTOVAT :] */
+static void
+dissect_ISSUE(tvbuff_t *tvb, gint offset, guint8 flags,
+ gboolean little_endian, int next_submsg_offset,
+ proto_tree *rtps_submessage_tree)
+{
+ int min_len;
+ char buff[40];
+ SequenceNumber sequenceNumber; /* type struct */
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset +=1;
+
+ min_len = 16;
+ if ((flags & FLAG_P) != 0)
+ min_len += 4;
+ if (next_submsg_offset < min_len)
+ {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset,
+ "Octets to next header: %u (bogus, must be >= %u)",
+ next_submsg_offset, min_len);
+ return;
+ }
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+
+ /* Reader Object ID */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Reader Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ /* Writer Object ID */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Writer Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ /* Sequence Number */
+ seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
+ "firstSeqNumber: 0x%X%X",
+ sequenceNumber.high, sequenceNumber.low);
+ offset += 8;
+
+ /* Parameters */
+/* *********************************************************************** *
+ * - for future extension of the protocol - in *
+ * implementation of RTPS 1.0 can ignore the content *
+ * *********************************************************************** */
+
+ /* -- P flag |XXXX|HAPE| => masks with 00000010b = 2 */
+ if ((flags & FLAG_P) != 0)
+ {
+ get_parameter_sequence(tvb, &offset, little_endian, next_submsg_offset,
+ rtps_submessage_tree);
+ }
+
+ /* Issue Data */
+ proto_tree_add_item(rtps_submessage_tree, hf_rtps_issue_data, tvb,
+ offset, (next_submsg_offset - offset), FALSE);
+
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * subdissector for submessage: ACK *
+ * *
+ * *********************************************************************** */
+ /* hotovo 12.01.04 - JEN OTESTOVAT :] */
+static void
+dissect_ACK(tvbuff_t *tvb, gint offset, guint8 flags,
+ gboolean little_endian, int next_submsg_offset,
+ proto_tree *rtps_submessage_tree)
+{
+ char buff[40];
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset +=1;
+
+ if (next_submsg_offset < 20)
+ {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset,
+ "Octets to next header: %u (bogus, must be >= 20)",
+ next_submsg_offset);
+ return;
+ }
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+
+ /* Reader Object ID */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Reader Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ /* Writer Object ID */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Writer Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ get_bitmap(tvb,&offset,little_endian,next_submsg_offset,rtps_submessage_tree);
+
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * subdissector for submessage: HEARTBEAT *
+ * *
+ * *********************************************************************** */
+ /* hotovo 12.01.04 - JEN OTESTOVAT :] */
+static void
+dissect_HEARTBEAT(tvbuff_t *tvb, gint offset, guint8 flags,
+ gboolean little_endian, int next_submsg_offset,
+ proto_tree *rtps_submessage_tree)
+{
+ char buff[40];
+ SequenceNumber sequenceNumber; /* type struct */
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset +=1;
+
+ if (next_submsg_offset < 24)
+ {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset,
+ "Octets to next header: %u (bogus, must be >= 24)",
+ next_submsg_offset);
+ return;
+ }
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+
+ /* Reader Object ID */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Reader Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ /* Writer Object ID */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Writer Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ /* firstSeqNumber */
+ seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
+ "firstSeqNumber: 0x%X%X",
+ sequenceNumber.high, sequenceNumber.low);
+ offset +=8;
+
+ /* lastSeqNumber */
+ seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
+ "lastSeqNumber: 0x%X%X",
+ sequenceNumber.high, sequenceNumber.low);
+ offset +=8;
+
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * subdissector for submessage: GAP *
+ * *
+ * *********************************************************************** */
+ /* hotovo 12.01.04 - JEN OTESTOVAT :] */
+static void
+dissect_GAP(tvbuff_t *tvb, gint offset, guint8 flags,
+ gboolean little_endian, int next_submsg_offset,
+ proto_tree *rtps_submessage_tree)
+{
+ char buff[40];
+ SequenceNumber sequenceNumber; /* type struct */
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset +=1;
+
+ if (next_submsg_offset < 28)
+ {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset,
+ "Octets to next header: %u (bogus, must be >= 28)",
+ next_submsg_offset);
+ return;
+ }
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+
+ /* Reader Object ID */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Reader Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ /* Writer Object ID */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Writer Object ID: %s ",
+ object_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+ /* Sequence Number */
+ seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
+ "firstSeqNumber: 0x%X%X",
+ sequenceNumber.high, sequenceNumber.low);
+ offset +=8;
+
+ get_bitmap(tvb,&offset,little_endian,next_submsg_offset,rtps_submessage_tree);
+
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * subdissector for submessage: INFO_TS *
+ * *
+ * *********************************************************************** */
+ /* hotovo 12.01.04 - JEN OTESTOVAT :] */
+
+static void
+dissect_INFO_TS(tvbuff_t *tvb, gint offset, guint8 flags,
+ gboolean little_endian, int next_submsg_offset,
+ proto_tree *rtps_submessage_tree)
+{
+ char buff[10];
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset +=1;
+
+ /* npTimestamp - valid if flag I = 1 *
+ * |XXXX|XXIE| => masks with 00000010b = 2 */
+ if ((flags & FLAG_I) != 0)
+ {
+ if (next_submsg_offset < 8)
+ {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset,
+ "Octets to next header: %u (bogus, must be >= 8)",
+ next_submsg_offset);
+ return;
+ }
+ }
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+
+ /* npTimestamp - valid if flag I = 1 *
+ * |XXXX|XXIE| => masks with 00000010b = 2 */
+ if ((flags & FLAG_I) != 0)
+ {
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
+ "ntpTimestamp: %s (sec)",
+ get_NtpTime(offset, tvb, little_endian,buff));
+ offset +=8;
+ }
+
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * subdissector for submessage: INFO_SRC *
+ * *
+ * *********************************************************************** */
+/* hotovo 12.01.04 JEN OTESTOVAT :] */
+static void
+dissect_INFO_SRC(tvbuff_t *tvb, gint offset, guint8 flags,
+ gboolean little_endian, int next_submsg_offset,
+ proto_tree *rtps_submessage_tree)
+{
+ char buff[200];
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset +=1;
+
+ if (next_submsg_offset < 16)
+ {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset,
+ "Octets to next header: %u (bogus, must be >= 16)",
+ next_submsg_offset);
+ return;
+ }
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+
+ /* IPAddress */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "appIP address: %s",
+ IP_to_string(offset, tvb, little_endian,buff));
+ offset +=4;
+
+ /* Protocol Version */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 2,
+ "Protocol RTPS version %s -new",
+ protocol_version_to_string(offset, tvb, buff));
+ offset +=2;
+
+ /* Vendor Id */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 2,
+ "VendorId: %s -new",
+ vendor_id_to_string(offset, tvb, buff));
+ offset +=2;
+
+ /* Host Id */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Host ID: %s",
+ host_id_to_string(offset,tvb,buff));
+ offset+=4;
+
+ /* App Id */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "App ID: %s-new",
+ app_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * subdissector for submessage: INFO_REPLY *
+ * *
+ * *********************************************************************** */
+ /* hotovo 11.01.04 :] */
+static void
+dissect_INFO_REPLY(tvbuff_t *tvb, gint offset, guint8 flags,
+ gboolean little_endian, int next_submsg_offset,
+ proto_tree *rtps_submessage_tree)
+{
+ int min_len;
+ char buff_ip[10], buff_port[10];
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset +=1;
+
+ /* 'multicastReplyAdress' and 'multicastReplyPort' are *
+ * parts of submessage INFO REPLY which are available *
+ * only when FLAG M=1 flags: XXXX XXME */
+
+ if ((flags & FLAG_M) != 0)
+ min_len = 16;
+ else
+ min_len = 8;
+ if (next_submsg_offset < min_len)
+ {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset,
+ "Octets to next header: %u (bogus, must be >= %u)",
+ next_submsg_offset, min_len);
+ return;
+ }
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+
+ /* Unicat Reply IPAddress */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Unicast Reply IP Adress: %s",
+ IP_to_string(offset, tvb, little_endian,buff_ip));
+ offset +=4;
+
+
+ /* Unicast Reply Port */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Unicast Reply IP Port: %s",
+ port_to_string(offset, tvb, little_endian,buff_port));
+ offset +=4;
+
+
+ /* 'multicastReplyAdress' and 'multicastReplyPort' are *
+ * parts of submessage INFO REPLY which are available *
+ * only when FLAG M=1 flags: XXXX XXME */
+
+ if ((flags & FLAG_M) != 0)
+ {
+ /* Multicast Reply IPAddress */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Multicast Reply IP Adress: %s",
+ IP_to_string(offset, tvb, little_endian,buff_ip));
+ offset +=4;
+
+ /* Multicast Reply Port */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Multicast Reply IP Port: %s",
+ port_to_string(offset, tvb, little_endian,buff_port));
+ offset +=4;
+
+ }
+}
+
+/* *********************************************************************** */
+
+
+/* *********************************************************************** *
+ * *
+ * subdissector for submessage: INFO_DST *
+ * *
+ * *********************************************************************** */
+ /* HOTOVO 12.01.04 - JEN OTESOVAT :]*/
+static void
+dissect_INFO_DST(tvbuff_t *tvb, gint offset, guint8 flags,
+ int next_submsg_offset,
+ proto_tree *rtps_submessage_tree)
+{
+ char buff[200];
+
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
+ tvb, offset, 1, flags);
+ offset +=1;
+
+ if (next_submsg_offset < 8)
+ {
+ proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset,
+ "Octets to next header: %u (bogus, must be >= 8)",
+ next_submsg_offset);
+ return;
+ }
+ proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
+ tvb, offset, 2, next_submsg_offset);
+ offset +=2;
+ next_submsg_offset += offset;
+
+ /* Host Id */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "Host ID: %s",
+ host_id_to_string(offset,tvb,buff));
+ offset+=4;
+
+ /* App Id */
+ proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
+ "App ID: %s-new",
+ app_id_to_string(offset, tvb, buff));
+ offset +=4;
+
+}
+
+/* *********************************************************************** *
+ * *
+ * Register the protocol with Ethereal *
+ * *
+ * *********************************************************************** */
+
+void proto_register_rtps(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_rtps_submessage_id,
+ { "Submessage Id", "rtps.submessage_id",
+ FT_UINT8, BASE_HEX, VALS(submessage_id_vals), 0x0,
+ "Submessage flags", HFILL }},
+
+ { &hf_rtps_submessage_flags,
+ { "Submessage flags", "rtps.submessage_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Submessage flags", HFILL }},
+
+ { &hf_rtps_octets_to_next_header,
+ { "Octets to next header", "rtps.octets_to_next_header",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Octets to next header", HFILL }},
+
+ { &hf_rtps_parameter_id,
+ { "Parameter Id", "rtps.parameter_id",
+ FT_UINT16, BASE_HEX, VALS(parameter_id_vals), 0x0,
+ "Parameter Id", HFILL }},
+
+ { &hf_rtps_parameter_length,
+ { "Parameter Length", "rtps.parameter_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Parameter Length", HFILL }},
+
+ { &hf_rtps_issue_data,
+ { "User Data", "rtps.issue_data",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Issue Data", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_rtps,
+ &ett_rtps_submessage,
+ &ett_rtps_bitmap,
+ &ett_rtps_parameter_sequence,
+ &ett_rtps_parameter,
+ };
+
+ proto_rtps = proto_register_protocol("Real-Time Publish-Subscribe Wire Protocol",
+ "RTPS", "rtps");
+ proto_register_field_array(proto_rtps, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+void
+proto_reg_handoff_rtps(void)
+{
+ heur_dissector_add("udp", dissect_rtps, proto_rtps);
+}
+
diff --git a/epan/dissectors/packet-rtps.h b/epan/dissectors/packet-rtps.h
new file mode 100644
index 0000000000..cbd768f2e3
--- /dev/null
+++ b/epan/dissectors/packet-rtps.h
@@ -0,0 +1,250 @@
+/*
+ * $Id$
+ *
+ * AUTHOR: Petr Smolik petr.smolik@wo.cz
+ *
+ * ORTE - OCERA Real-Time Ethernet http://www.ocera.org/
+ * --------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _TYPEDEFS_DEFINES_RTPS_H
+#define _TYPEDEFS_DEFINES_RTPS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTPS_HEADER_LENGTH 16
+
+#define MAX_PATHNAME 128
+#define MAX_TYPENAME 128
+#define ORTE_TRUE 1
+#define ORTE_FALSE 0
+
+typedef gint8 Boolean;
+
+typedef gint8 PathName[MAX_PATHNAME];
+typedef gint8 TypeName[MAX_TYPENAME];
+
+typedef gint32 TypeChecksum;
+
+/*****************************************************************/
+/* Wire Protocol Specification (WPS) */
+/*****************************************************************/
+
+
+/**
+ Host identifier.
+
+ for example: IP address working nodes
+*/
+typedef gint32 HostId;
+#define HID_UNKNOWN 0x00
+
+/**
+ Application identifier.
+
+ composed from: 3 bytes - instance Id
+ 1 byte - appKind (1 - ManagedApplication, 2 - Manager)
+*/
+typedef gint32 AppId;
+#define AID_UNKNOWN 0x00
+#define MANAGEDAPPLICATION 0x01
+#define MANAGER 0x02
+
+/**
+ Object identifier.
+
+ composed from: 3 bytes - instance Id
+ 1 byte - objKind
+*/
+typedef gint32 ObjectId;
+
+#define OID_UNKNOWN 0x00000000
+#define OID_APP 0x000001C1
+#define OID_WRITE_APPSELF 0x000008C2
+#define OID_READ_APPSELF 0x000008C7
+#define OID_WRITE_APP 0x000001C2
+#define OID_READ_APP 0x000001C7
+#define OID_WRITE_MGR 0x000007C2
+#define OID_READ_MGR 0x000007C7
+#define OID_WRITE_PUBL 0x000003C2
+#define OID_READ_PUBL 0x000003C7
+#define OID_WRITE_SUBS 0x000004C2
+#define OID_READ_SUBS 0x000004C7
+/* Kind */
+#define OID_APPLICATION 0x01
+#define OID_CSTWRITER 0x02
+#define OID_PUBLICATION 0x03
+#define OID_SUBSCRIPTION 0x04
+#define OID_CSTREADER 0x07
+
+#define OID_USEROBJ 0x00
+#define OID_RESUSEROBJ 0x40
+#define OID_METAOBJ 0x80
+#define OID_RESMETAOBJ 0xC0
+
+typedef struct {
+ HostId hid;
+ AppId aid;
+ ObjectId oid;
+ } GUID_RTPS;
+
+typedef struct {
+ gint8 major;
+ gint8 minor;
+ } VendorId;
+
+#define VENDOR_ID_UNKNOWN(id) {id.major=0;id.minor=0;}
+#define VENDOR_ID_RTI(id) {id.major=1;id.minor=1;}
+#define VENDOR_ID_OCERA(id) {id.major=0;id.minor=0;}
+
+typedef struct {
+ gint8 major;
+ gint8 minor;
+ } ProtocolVersion;
+
+#define PROTOCOL_VERSION_1_0(pv) {pv.major=1;pv.minor=0;}
+
+typedef struct {
+ gint32 high;
+ gint32 low;
+ } SequenceNumber;
+
+
+#define SEQUENCE_NUMBER_NONE(sn) {sn.high=0;sn.low=0;}
+#define SEQUENCE_NUMBER_UNKNOWN(sn) {sn.high=0x7fffffff;sn.low=0xffffffff;}
+
+
+typedef struct {
+ gint32 seconds; /* time in seconds */
+ guint32 fraction; /* time in seconds / 2^32 */
+ } NtpTime;
+
+#define NTPTIME_ZERO(t) {t.seconds=0;t.fraction=0;}
+#define NTPTIME_BUILD(t,s) {t.seconds=s;t.fraction=0;}
+#define NTPTIME_INFINITE(t) {t.seconds=0xffffffff;t.fraction=0;}
+
+typedef gint32 IPAddress;
+
+#define IPADDRESS_INVALID 0
+
+typedef gint32 Port;
+
+#define PORT_INVALID 0
+
+typedef enum {
+ PAD = 0x01,
+ VAR = 0x02,
+ ISSUE = 0x03,
+ ACK = 0x06,
+ HEARTBEAT = 0x07,
+ GAP = 0x08,
+ INFO_TS = 0x09,
+ INFO_SRC = 0x0c,
+ INFO_REPLY = 0x0d,
+ INFO_DST = 0x0e,
+ APP_QUIT = 0x90
+ } SubmessageId;
+
+typedef struct {
+ ProtocolVersion sourceVersion;
+ VendorId sourceVendorId;
+ HostId sourceHostId;
+ AppId sourceAppId;
+ HostId destHostId;
+ AppId destAppId;
+ IPAddress unicastReplyIPAddress;
+ Port unicastReplyPort;
+ IPAddress multicastReplyIPAddress;
+ Port multicastReplyPort;
+ Boolean haveTimestamp;
+ NtpTime timestamp;
+ } MessageInterpret;
+
+
+#define PID_PAD 0x00
+#define PID_SENTINEL 0x01
+#define PID_EXPIRATION_TIME 0x02
+#define PID_PERSISTENCE 0x03
+#define PID_MINIMUM_SEPARATION 0x04
+#define PID_TOPIC 0x05
+#define PID_STRENGTH 0x06
+#define PID_TYPE_NAME 0x07
+#define PID_TYPE_CHECKSUM 0x08
+#define RTPS_PID_TYPE2_NAME 0x09
+#define RTPS_PID_TYPE2_CHECKSUM 0x0a
+#define PID_METATRAFFIC_MULTICAST_IPADDRESS 0x0b /*tady byla chyba MATA_TRAFF....*/
+#define PID_APP_IPADDRESS 0x0c
+#define PID_METATRAFFIC_UNICAST_PORT 0x0d
+#define PID_USERDATA_UNICAST_PORT 0x0e
+#define PID_IS_RELIABLE 0x0f
+#define PID_EXPECTS_ACK 0x10
+#define PID_USERDATA_MULTICAST_IPADDRESS 0x11
+#define PID_MANAGER_KEY 0x12
+#define PID_SEND_QUEUE_SIZE 0x13
+#define PID_RELIABILITY_ENABLED 0x14
+#define PID_PROTOCOL_VERSION 0x15
+#define PID_VENDOR_ID 0x16
+#define PID_VARGAPPS_SEQUENCE_NUMBER_LAST 0x17
+#define PID_RECV_QUEUE_SIZE 0x18
+#define PID_RELIABILITY_OFFERED 0x19
+#define PID_RELIABILITY_REQUESTED 0x1a
+
+/* possible values for PID_RELIABILITY_REQUEST */
+#define PID_VALUE_RELIABILITY_BEST_EFFORTS 0x01
+#define PID_VALUE_RELIABILITY_STRICT 0x02
+
+typedef guint16 ParameterId;
+typedef guint16 ParameterLength;
+
+/* State Machines */
+typedef enum {
+ MAYSENDHB = 0x01,
+ MUSTSENDHB = 0x02,
+ SENDHB = 0x03
+ } StateMachineHB;
+
+typedef enum {
+ NOTHNIGTOSEND = 0x01,
+ MUSTSENDDATA = 0x02
+ } StateMachineSend;
+
+typedef enum {
+ NEW = 0x01,
+ TOSEND = 0x02,
+ UNDERWAY = 0x03,
+ UNACKNOWLEDGED = 0x04,
+ ANNOUCED = 0x05,
+ ACKNOWLEDGED = 0x06
+ } StateMachineChFReader;
+
+typedef enum {
+ WAITING = 0x01,
+ PULLING = 0x02,
+ ACKPENDING = 0x03
+ } StateMachineACK;
+
+typedef enum {
+ FUTURE = 0x01,
+ REQUESTED = 0x02,
+ MISSING = 0x03,
+ RECEIVED = 0x04
+ } StateMachineChFWriter;
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /* _TYPEDEFS_DEFINES_RTPS_H */
diff --git a/epan/dissectors/packet-rtsp.c b/epan/dissectors/packet-rtsp.c
new file mode 100644
index 0000000000..1a1453494e
--- /dev/null
+++ b/epan/dissectors/packet-rtsp.c
@@ -0,0 +1,1217 @@
+/* packet-rtsp.c
+ * Routines for RTSP packet disassembly (RFC 2326)
+ *
+ * Jason Lango <jal@netapp.com>
+ * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * References:
+ * RTSP is defined in RFC 2326, http://www.ietf.org/rfc/rfc2326.txt?number=2326
+ * http://www.iana.org/assignments/rsvp-parameters
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "prefs.h"
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "req_resp_hdrs.h"
+#include "packet-rtp.h"
+#include "packet-rtcp.h"
+#include <epan/conversation.h>
+#include <epan/strutil.h>
+#include "packet-e164.h"
+
+static int proto_rtsp = -1;
+
+static gint ett_rtsp = -1;
+static gint ett_rtspframe = -1;
+static gint ett_rtsp_method = -1;
+
+static int hf_rtsp_method = -1;
+static int hf_rtsp_url = -1;
+static int hf_rtsp_status = -1;
+static int hf_rtsp_session = -1;
+static int hf_rtsp_X_Vig_Msisdn = -1;
+
+static dissector_handle_t sdp_handle;
+static dissector_handle_t rtp_handle;
+static dissector_handle_t rtcp_handle;
+
+void proto_reg_handoff_rtsp(void);
+
+static GMemChunk *rtsp_vals = NULL;
+#define rtsp_hash_init_count 20
+
+/*
+ * desegmentation of RTSP headers
+ * (when we are over TCP or another protocol providing the desegmentation API)
+ */
+static gboolean rtsp_desegment_headers = FALSE;
+
+/*
+ * desegmentation of RTSP bodies
+ * (when we are over TCP or another protocol providing the desegmentation API)
+ * TODO let the user filter on content-type the bodies he wants desegmented
+ */
+static gboolean rtsp_desegment_body = FALSE;
+
+/* http://www.iana.org/assignments/port-numberslists two rtsp ports */
+#define TCP_PORT_RTSP 554
+#define TCP_ALTERNATE_PORT_RTSP 8554
+static guint global_rtsp_tcp_port = TCP_PORT_RTSP;
+static guint global_rtsp_tcp_alternate_port = TCP_ALTERNATE_PORT_RTSP;
+/*
+* Variables to allow for proper deletion of dissector registration when
+* the user changes port from the gui.
+*/
+static guint tcp_port = 0;
+static guint tcp_alternate_port = 0;
+
+/*
+ * Takes an array of bytes, assumed to contain a null-terminated
+ * string, as an argument, and returns the length of the string -
+ * i.e., the size of the array, minus 1 for the null terminator.
+ */
+#define STRLEN_CONST(str) (sizeof (str) - 1)
+
+#define RTSP_FRAMEHDR ('$')
+
+typedef struct {
+ dissector_handle_t dissector;
+} rtsp_interleaved_t;
+
+#define RTSP_MAX_INTERLEAVED (8)
+
+/*
+ * Careful about dynamically allocating memory in this structure (say
+ * for dynamically increasing the size of the 'interleaved' array) -
+ * the containing structure is garbage collected and contained
+ * pointers will not be freed.
+ */
+typedef struct {
+ rtsp_interleaved_t interleaved[RTSP_MAX_INTERLEAVED];
+} rtsp_conversation_data_t;
+
+static int
+dissect_rtspinterleaved(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ guint length_remaining;
+ proto_item *ti;
+ proto_tree *rtspframe_tree = NULL;
+ int orig_offset;
+ guint8 rf_start; /* always RTSP_FRAMEHDR */
+ guint8 rf_chan; /* interleaved channel id */
+ guint16 rf_len; /* packet length */
+ tvbuff_t *next_tvb;
+ conversation_t *conv;
+ rtsp_conversation_data_t *data;
+ dissector_handle_t dissector;
+
+ /*
+ * This will throw an exception if we don't have any data left.
+ * That's what we want. (See "tcp_dissect_pdus()", which is
+ * similar.)
+ */
+ length_remaining = tvb_ensure_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (rtsp_desegment_headers && pinfo->can_desegment) {
+ /*
+ * Yes - would an RTSP multiplexed header starting at
+ * this offset be split across segment boundaries?
+ */
+ if (length_remaining < 4) {
+ /*
+ * Yes. Tell the TCP dissector where the data
+ * for this message starts in the data it handed
+ * us, and how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4 - length_remaining;
+ return -1;
+ }
+ }
+
+ /*
+ * Get the "$", channel, and length from the header.
+ */
+ orig_offset = offset;
+ rf_start = tvb_get_guint8(tvb, offset);
+ rf_chan = tvb_get_guint8(tvb, offset+1);
+ rf_len = tvb_get_ntohs(tvb, offset+2);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (rtsp_desegment_body && pinfo->can_desegment) {
+ /*
+ * Yes - is the header + encapsulated packet split
+ * across segment boundaries?
+ */
+ if (length_remaining < 4U + rf_len) {
+ /*
+ * Yes. Tell the TCP dissector where the data
+ * for this message starts in the data it handed
+ * us, and how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4U + rf_len - length_remaining;
+ return -1;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Interleaved channel 0x%02x, %u bytes",
+ rf_chan, rf_len);
+
+ if (tree != NULL) {
+ ti = proto_tree_add_protocol_format(tree, proto_rtsp, tvb,
+ offset, 4,
+ "RTSP Interleaved Frame, Channel: 0x%02x, %u bytes",
+ rf_chan, rf_len);
+ rtspframe_tree = proto_item_add_subtree(ti, ett_rtspframe);
+
+ proto_tree_add_text(rtspframe_tree, tvb, offset, 1,
+ "Magic: 0x%02x",
+ rf_start);
+ }
+ offset += 1;
+
+ if (tree != NULL) {
+ proto_tree_add_text(rtspframe_tree, tvb, offset, 1,
+ "Channel: 0x%02x",
+ rf_chan);
+ }
+ offset += 1;
+
+ if (tree != NULL) {
+ proto_tree_add_text(rtspframe_tree, tvb, offset, 2,
+ "Length: %u bytes",
+ rf_len);
+ }
+ offset += 2;
+
+ /*
+ * We set the actual length of the tvbuff for the interleaved
+ * stuff to the minimum of what's left in the tvbuff and the
+ * length in the header.
+ *
+ * XXX - what if there's nothing left in the tvbuff?
+ * We'd want a BoundsError exception to be thrown, so
+ * that a Short Frame would be reported.
+ */
+ if (length_remaining > rf_len)
+ length_remaining = rf_len;
+ next_tvb = tvb_new_subset(tvb, offset, length_remaining, rf_len);
+
+ conv = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if (conv &&
+ (data = conversation_get_proto_data(conv, proto_rtsp)) &&
+ rf_chan < RTSP_MAX_INTERLEAVED &&
+ (dissector = data->interleaved[rf_chan].dissector)) {
+ call_dissector(dissector, next_tvb, pinfo, tree);
+ } else {
+ proto_tree_add_text(rtspframe_tree, tvb, offset, rf_len,
+ "Data (%u bytes)", rf_len);
+ }
+
+ offset += rf_len;
+
+ return offset - orig_offset;
+}
+
+static void process_rtsp_request(tvbuff_t *tvb, int offset, const guchar *data,
+ size_t linelen, proto_tree *tree);
+
+static void process_rtsp_reply(tvbuff_t *tvb, int offset, const guchar *data,
+ size_t linelen, proto_tree *tree);
+
+typedef enum {
+ RTSP_REQUEST,
+ RTSP_REPLY,
+ NOT_RTSP
+} rtsp_type_t;
+
+static const char *rtsp_methods[] = {
+ "DESCRIBE",
+ "ANNOUNCE",
+ "GET_PARAMETER",
+ "OPTIONS",
+ "PAUSE",
+ "PLAY",
+ "RECORD",
+ "REDIRECT",
+ "SETUP",
+ "SET_PARAMETER",
+ "TEARDOWN"
+};
+
+#define RTSP_NMETHODS (sizeof rtsp_methods / sizeof rtsp_methods[0])
+
+static gboolean
+is_rtsp_request_or_reply(const guchar *line, size_t linelen, rtsp_type_t *type)
+{
+ unsigned ii;
+
+ /* Is this an RTSP reply? */
+ if (linelen >= 5 && strncasecmp("RTSP/", line, 5) == 0) {
+ /*
+ * Yes.
+ */
+ *type = RTSP_REPLY;
+ return TRUE;
+ }
+
+ /*
+ * Is this an RTSP request?
+ * Check whether the line begins with one of the RTSP request
+ * methods.
+ */
+ for (ii = 0; ii < RTSP_NMETHODS; ii++) {
+ size_t len = strlen(rtsp_methods[ii]);
+ if (linelen >= len &&
+ strncasecmp(rtsp_methods[ii], line, len) == 0 &&
+ (len == linelen || isspace(line[len]))) {
+ *type = RTSP_REQUEST;
+ return TRUE;
+ }
+ }
+ *type = NOT_RTSP;
+ return FALSE;
+}
+
+static const char rtsp_content_type[] = "Content-Type:";
+
+static int
+is_content_sdp(const guchar *line, size_t linelen)
+{
+ static const char type[] = "application/sdp";
+ size_t typelen = STRLEN_CONST(type);
+
+ line += STRLEN_CONST(rtsp_content_type);
+ linelen -= STRLEN_CONST(rtsp_content_type);
+ while (linelen > 0 && (*line == ' ' || *line == '\t')) {
+ line++;
+ linelen--;
+ }
+
+ if (linelen < typelen || strncasecmp(type, line, typelen))
+ return FALSE;
+
+ line += typelen;
+ linelen -= typelen;
+ if (linelen > 0 && !isspace(*line))
+ return FALSE;
+
+ return TRUE;
+}
+
+static const char rtsp_transport[] = "Transport:";
+static const char rtsp_sps[] = "server_port=";
+static const char rtsp_cps[] = "client_port=";
+static const char rtsp_rtp[] = "rtp/";
+static const char rtsp_inter[] = "interleaved=";
+
+static void
+rtsp_create_conversation(packet_info *pinfo, const guchar *line_begin,
+ size_t line_len)
+{
+ conversation_t *conv;
+ guchar buf[256];
+ guchar *tmp;
+ guint c_data_port, c_mon_port;
+ guint s_data_port, s_mon_port;
+ address null_addr;
+
+ if (line_len > sizeof(buf) - 1) {
+ /*
+ * Don't overflow the buffer.
+ */
+ line_len = sizeof(buf) - 1;
+ }
+ memcpy(buf, line_begin, line_len);
+ buf[line_len] = '\0';
+
+ tmp = buf + STRLEN_CONST(rtsp_transport);
+ while (*tmp && isspace(*tmp))
+ tmp++;
+ if (strncasecmp(tmp, rtsp_rtp, strlen(rtsp_rtp)) != 0) {
+ g_warning("Frame %u: rtsp: unknown transport", pinfo->fd->num);
+ return;
+ }
+
+ c_data_port = c_mon_port = 0;
+ s_data_port = s_mon_port = 0;
+ if ((tmp = strstr(buf, rtsp_sps))) {
+ tmp += strlen(rtsp_sps);
+ if (sscanf(tmp, "%u-%u", &s_data_port, &s_mon_port) < 1) {
+ g_warning("Frame %u: rtsp: bad server_port",
+ pinfo->fd->num);
+ return;
+ }
+ }
+ if ((tmp = strstr(buf, rtsp_cps))) {
+ tmp += strlen(rtsp_cps);
+ if (sscanf(tmp, "%u-%u", &c_data_port, &c_mon_port) < 1) {
+ g_warning("Frame %u: rtsp: bad client_port",
+ pinfo->fd->num);
+ return;
+ }
+ }
+ if (!c_data_port) {
+ rtsp_conversation_data_t *data;
+ guint s_data_chan, s_mon_chan;
+ int i;
+
+ /*
+ * Deal with RTSP TCP-interleaved conversations.
+ */
+ if ((tmp = strstr(buf, rtsp_inter)) == NULL) {
+ /*
+ * No interleaved or server_port - probably a
+ * SETUP request, rather than reply.
+ */
+ return;
+ }
+ tmp += strlen(rtsp_inter);
+ i = sscanf(tmp, "%u-%u", &s_data_chan, &s_mon_chan);
+ if (i < 1) {
+ g_warning("Frame %u: rtsp: bad interleaved",
+ pinfo->fd->num);
+ return;
+ }
+ conv = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (!conv) {
+ conv = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport,
+ 0);
+ }
+ data = conversation_get_proto_data(conv, proto_rtsp);
+ if (!data) {
+ data = g_mem_chunk_alloc(rtsp_vals);
+ conversation_add_proto_data(conv, proto_rtsp, data);
+ }
+ if (s_data_chan < RTSP_MAX_INTERLEAVED) {
+ data->interleaved[s_data_chan].dissector =
+ rtp_handle;
+ }
+ if (i > 1 && s_mon_chan < RTSP_MAX_INTERLEAVED) {
+ data->interleaved[s_mon_chan].dissector =
+ rtcp_handle;
+ }
+ return;
+ }
+
+ /*
+ * We only want to match on the destination address, not the
+ * source address, because the server might send back a packet
+ * from an address other than the address to which its client
+ * sent the packet, so we construct a conversation with no
+ * second address.
+ */
+ SET_ADDRESS(&null_addr, pinfo->src.type, 0, NULL);
+
+ rtp_add_address(pinfo, (char *)pinfo->dst.data, c_data_port, s_data_port,
+ "RTSP", pinfo->fd->num);
+
+ if (!c_mon_port)
+ return;
+
+ rtcp_add_address(pinfo, (char *)pinfo->dst.data, c_mon_port, s_mon_port,
+ "RTSP", pinfo->fd->num);
+}
+
+static const char rtsp_content_length[] = "Content-Length:";
+
+static int
+rtsp_get_content_length(const guchar *line_begin, size_t line_len)
+{
+ guchar buf[256];
+ guchar *tmp;
+ long content_length;
+ char *p;
+ guchar *up;
+
+ if (line_len > sizeof(buf) - 1) {
+ /*
+ * Don't overflow the buffer.
+ */
+ line_len = sizeof(buf) - 1;
+ }
+ memcpy(buf, line_begin, line_len);
+ buf[line_len] = '\0';
+
+ tmp = buf + STRLEN_CONST(rtsp_content_length);
+ while (*tmp && isspace(*tmp))
+ tmp++;
+ content_length = strtol(tmp, &p, 10);
+ up = p;
+ if (up == tmp || (*up != '\0' && !isspace(*up)))
+ return -1; /* not a valid number */
+ return content_length;
+}
+
+static const char rtsp_Session[] = "Session:";
+static const char rtsp_X_Vig_Msisdn[] = "X-Vig-Msisdn";
+
+static int
+dissect_rtspmessage(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree)
+{
+ proto_tree *rtsp_tree = NULL;
+ proto_tree *sub_tree = NULL;
+ proto_item *ti = NULL;
+ const guchar *line;
+ gint next_offset;
+ const guchar *linep, *lineend;
+ int orig_offset;
+ int first_linelen, linelen;
+ int line_end_offset;
+ int colon_offset;
+ gboolean is_request_or_reply;
+ gboolean body_requires_content_len;
+ gboolean saw_req_resp_or_header;
+ guchar c;
+ rtsp_type_t rtsp_type;
+ gboolean is_header;
+ int is_sdp = FALSE;
+ int datalen;
+ int content_length;
+ int reported_datalen;
+ int value_offset;
+ int value_len;
+ e164_info_t e164_info;
+ /*
+ * Is this a request or response?
+ *
+ * Note that "tvb_find_line_end()" will return a value that
+ * is not longer than what's in the buffer, so the
+ * "tvb_get_ptr()" call won't throw an exception.
+ */
+ first_linelen = tvb_find_line_end(tvb, offset,
+ tvb_ensure_length_remaining(tvb, offset), &next_offset,
+ FALSE);
+ /*
+ * Is the first line a request or response?
+ */
+ line = tvb_get_ptr(tvb, offset, first_linelen);
+ is_request_or_reply = is_rtsp_request_or_reply(line, first_linelen,
+ &rtsp_type);
+ if (is_request_or_reply) {
+ /*
+ * Yes, it's a request or response.
+ * Do header desegmentation if we've been told to,
+ * and do body desegmentation if we've been told to and
+ * we find a Content-Length header.
+ */
+ if (!req_resp_hdrs_do_reassembly(tvb, pinfo,
+ rtsp_desegment_headers, rtsp_desegment_body)) {
+ /*
+ * More data needed for desegmentation.
+ */
+ return -1;
+ }
+ }
+
+ /*
+ * RFC 2326 says that a content length must be specified
+ * in requests that have a body, although section 4.4 speaks
+ * of a server closing the connection indicating the end of
+ * a reply body.
+ *
+ * We assume that an absent content length in a request means
+ * that we don't have a body, and that an absent content length
+ * in a reply means that the reply body runs to the end of
+ * the connection. If the first line is neither, we assume
+ * that whatever follows a blank line should be treated as a
+ * body; there's not much else we can do, as we're jumping
+ * into the message in the middle.
+ *
+ * XXX - if there was no Content-Length entity header, we should
+ * accumulate all data until the end of the connection.
+ * That'd require that the TCP dissector call subdissectors
+ * for all frames with FIN, even if they contain no data,
+ * which would require subdissectors to deal intelligently
+ * with empty segments.
+ */
+ if (rtsp_type == RTSP_REQUEST)
+ body_requires_content_len = TRUE;
+ else
+ body_requires_content_len = FALSE;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTSP");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /*
+ * Put the first line from the buffer into the summary
+ * if it's an RTSP request or reply (but leave out the
+ * line terminator).
+ * Otherwise, just call it a continuation.
+ *
+ * Note that "tvb_find_line_end()" will return a value that
+ * is not longer than what's in the buffer, so the
+ * "tvb_get_ptr()" call won't throw an exception.
+ */
+ line = tvb_get_ptr(tvb, offset, first_linelen);
+ if (is_request_or_reply)
+ if ( rtsp_type == RTSP_REPLY ) {
+ col_add_str(pinfo->cinfo, COL_INFO, "Reply: ");
+ col_append_str(pinfo->cinfo, COL_INFO,
+ format_text(line, first_linelen));
+ }
+ else
+ col_add_str(pinfo->cinfo, COL_INFO,
+ format_text(line, first_linelen));
+
+ else
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+
+ }
+
+ orig_offset = offset;
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_rtsp, tvb, offset, -1,
+ FALSE);
+ rtsp_tree = proto_item_add_subtree(ti, ett_rtsp);
+ }
+
+ /*
+ * We haven't yet seen a Content-Length header.
+ */
+ content_length = -1;
+
+ /*
+ * Process the packet data, a line at a time.
+ */
+ saw_req_resp_or_header = FALSE; /* haven't seen anything yet */
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * We haven't yet concluded that this is a header.
+ */
+ is_header = FALSE;
+
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset,
+ tvb_ensure_length_remaining(tvb, offset), &next_offset,
+ FALSE);
+ if (linelen < 0)
+ return -1;
+ line_end_offset = offset + linelen;
+ /*
+ * colon_offset may be -1
+ */
+ colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
+
+
+ /*
+ * Get a buffer that refers to the line.
+ */
+ line = tvb_get_ptr(tvb, offset, linelen);
+ lineend = line + linelen;
+
+ /*
+ * OK, does it look like an RTSP request or response?
+ */
+ is_request_or_reply = is_rtsp_request_or_reply(line, linelen,
+ &rtsp_type);
+ if (is_request_or_reply)
+ goto is_rtsp;
+
+ /*
+ * No. Does it look like a blank line (as would appear
+ * at the end of an RTSP request)?
+ */
+ if (linelen == 0)
+ goto is_rtsp; /* Yes. */
+
+ /*
+ * No. Does it look like a header?
+ */
+ linep = line;
+ while (linep < lineend) {
+ c = *linep++;
+
+ /*
+ * This must be a CHAR to be part of a token; that
+ * means it must be ASCII.
+ */
+ if (!isascii(c))
+ break; /* not ASCII, thus not a CHAR */
+
+ /*
+ * This mustn't be a CTL to be part of a token.
+ *
+ * XXX - what about leading LWS on continuation
+ * lines of a header?
+ */
+ if (iscntrl(c))
+ break; /* CTL, not part of a header */
+
+ switch (c) {
+
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '@':
+ case ',':
+ case ';':
+ case '\\':
+ case '"':
+ case '/':
+ case '[':
+ case ']':
+ case '?':
+ case '=':
+ case '{':
+ case '}':
+ /*
+ * It's a tspecial, so it's not
+ * part of a token, so it's not
+ * a field name for the beginning
+ * of a header.
+ */
+ goto not_rtsp;
+
+ case ':':
+ /*
+ * This ends the token; we consider
+ * this to be a header.
+ */
+ is_header = TRUE;
+ goto is_rtsp;
+
+ case ' ':
+ case '\t':
+ /*
+ * LWS (RFC-2616, 4.2); continue the previous
+ * header.
+ */
+ goto is_rtsp;
+ }
+ }
+
+ /*
+ * We haven't seen the colon, but everything else looks
+ * OK for a header line.
+ *
+ * If we've already seen an RTSP request or response
+ * line, or a header line, and we're at the end of
+ * the tvbuff, we assume this is an incomplete header
+ * line. (We quit this loop after seeing a blank line,
+ * so if we've seen a request or response line, or a
+ * header line, this is probably more of the request
+ * or response we're presumably seeing. There is some
+ * risk of false positives, but the same applies for
+ * full request or response lines or header lines,
+ * although that's less likely.)
+ *
+ * We throw an exception in that case, by checking for
+ * the existence of the next byte after the last one
+ * in the line. If it exists, "tvb_ensure_bytes_exist()"
+ * throws no exception, and we fall through to the
+ * "not RTSP" case. If it doesn't exist,
+ * "tvb_ensure_bytes_exist()" will throw the appropriate
+ * exception.
+ */
+ if (saw_req_resp_or_header)
+ tvb_ensure_bytes_exist(tvb, offset, linelen + 1);
+
+ not_rtsp:
+ /*
+ * We don't consider this part of an RTSP request or
+ * reply, so we don't display it.
+ */
+ break;
+
+ is_rtsp:
+ /*
+ * Process this line.
+ */
+ if (linelen == 0) {
+ /*
+ * This is a blank line, which means that
+ * whatever follows it isn't part of this
+ * request or reply.
+ */
+ proto_tree_add_text(rtsp_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ offset = next_offset;
+ break;
+ }
+
+ /*
+ * Not a blank line - either a request, a reply, or a header
+ * line.
+ */
+ saw_req_resp_or_header = TRUE;
+ if (rtsp_tree) {
+ ti = proto_tree_add_text(rtsp_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+
+ sub_tree = proto_item_add_subtree(ti, ett_rtsp_method);
+
+ switch (rtsp_type) {
+
+ case RTSP_REQUEST:
+ process_rtsp_request(tvb, offset, line, linelen,
+ sub_tree);
+ break;
+
+ case RTSP_REPLY:
+ process_rtsp_reply(tvb, offset, line, linelen,
+ sub_tree);
+ break;
+
+ case NOT_RTSP:
+ break;
+ }
+ }
+ if (is_header) {
+ /*
+ * Process some headers specially.
+ */
+#define HDR_MATCHES(header) \
+ (linelen > STRLEN_CONST(header) && \
+ strncasecmp(line, (header), STRLEN_CONST(header)) == 0)
+
+ if (HDR_MATCHES(rtsp_transport)) {
+ /*
+ * Based on the port numbers specified
+ * in the Transport: header, set up
+ * a conversation that will be dissected
+ * with the appropriate dissector.
+ */
+ rtsp_create_conversation(pinfo, line, linelen);
+ } else if (HDR_MATCHES(rtsp_content_type)) {
+ /*
+ * If the Content-Type: header says this
+ * is SDP, dissect the payload as SDP.
+ *
+ * XXX - we should just do the same
+ * sort of header processing
+ * that HTTP does, and use the
+ * "media_type" dissector table on
+ * the content type.
+ *
+ * We should use those for Transport:
+ * and Content-Length: as well (and
+ * should process Content-Length: in
+ * HTTP).
+ */
+ if (is_content_sdp(line, linelen))
+ is_sdp = TRUE;
+ } else if (HDR_MATCHES(rtsp_content_length)) {
+ /*
+ * Only the amount specified by the
+ * Content-Length: header should be treated
+ * as payload.
+ */
+ content_length = rtsp_get_content_length(line,
+ linelen);
+
+ } else if (HDR_MATCHES(rtsp_Session)) {
+ /*
+ * Extract the session string
+
+ */
+
+ if ( colon_offset != -1 ){
+ /*
+ * Skip whitespace after the colon.
+ * (Code from SIP dissector )
+ */
+ value_offset = colon_offset + 1;
+ while (value_offset < line_end_offset
+ && ((c = tvb_get_guint8(tvb,
+ value_offset)) == ' '
+ || c == '\t'))
+ value_offset++;
+ /*
+ * Put the value into the protocol tree
+ */
+ value_len = line_end_offset - value_offset;
+ proto_tree_add_string(sub_tree, hf_rtsp_session,tvb,
+ value_offset, value_len ,
+ tvb_format_text(tvb, value_offset, value_len));
+ }
+
+ } else if (HDR_MATCHES(rtsp_X_Vig_Msisdn)) {
+ /*
+ * Extract the X_Vig_Msisdn string
+ */
+ if ( colon_offset != -1 ){
+ /*
+ * Skip whitespace after the colon.
+ * (Code from SIP dissector )
+ */
+ value_offset = colon_offset + 1;
+ while (value_offset < line_end_offset
+ && ((c = tvb_get_guint8(tvb,
+ value_offset)) == ' '
+ || c == '\t'))
+ value_offset++;
+ /*
+ * Put the value into the protocol tree
+ */
+ value_len = line_end_offset - value_offset;
+ proto_tree_add_string(sub_tree, hf_rtsp_X_Vig_Msisdn,tvb,
+ value_offset, value_len ,
+ tvb_format_text(tvb, value_offset, value_len));
+
+ e164_info.e164_number_type = CALLING_PARTY_NUMBER;
+ e164_info.nature_of_address = 0;
+
+ e164_info.E164_number_str = tvb_get_string(tvb, value_offset,
+ value_len);
+ e164_info.E164_number_length = value_len;
+ dissect_e164_number(tvb, sub_tree, value_offset,
+ value_len, e164_info);
+ g_free(e164_info.E164_number_str);
+
+
+ }
+ }
+
+ }
+ offset = next_offset;
+ }
+
+ /*
+ * If a content length was supplied, the amount of data to be
+ * processed as RTSP payload is the minimum of the content
+ * length and the amount of data remaining in the frame.
+ *
+ * If no content length was supplied (or if a bad content length
+ * was supplied), the amount of data to be processed is the amount
+ * of data remaining in the frame.
+ */
+ datalen = tvb_length_remaining(tvb, offset);
+ reported_datalen = tvb_reported_length_remaining(tvb, offset);
+ if (content_length != -1) {
+ /*
+ * Content length specified; display only that amount
+ * as payload.
+ */
+ if (datalen > content_length)
+ datalen = content_length;
+
+ /*
+ * XXX - limit the reported length in the tvbuff we'll
+ * hand to a subdissector to be no greater than the
+ * content length.
+ *
+ * We really need both unreassembled and "how long it'd
+ * be if it were reassembled" lengths for tvbuffs, so
+ * that we throw the appropriate exceptions for
+ * "not enough data captured" (running past the length),
+ * "packet needed reassembly" (within the length but
+ * running past the unreassembled length), and
+ * "packet is malformed" (running past the reassembled
+ * length).
+ */
+ if (reported_datalen > content_length)
+ reported_datalen = content_length;
+ } else {
+ /*
+ * No content length specified; if this message doesn't
+ * have a body if no content length is specified, process
+ * nothing as payload.
+ */
+ if (body_requires_content_len)
+ datalen = 0;
+ }
+
+ if (datalen > 0) {
+ /*
+ * There's stuff left over; process it.
+ */
+ if (is_sdp) {
+ tvbuff_t *new_tvb;
+
+ /*
+ * Fix up the top-level item so that it doesn't
+ * include the SDP stuff.
+ */
+ if (ti != NULL)
+ proto_item_set_len(ti, offset);
+
+ /*
+ * Now create a tvbuff for the SDP stuff and
+ * dissect it.
+ *
+ * The amount of data to be processed that's
+ * available in the tvbuff is "datalen", which
+ * is the minimum of the amount of data left in
+ * the tvbuff and any specified content length.
+ *
+ * The amount of data to be processed that's in
+ * this frame, regardless of whether it was
+ * captured or not, is "reported_datalen",
+ * which, if no content length was specified,
+ * is -1, i.e. "to the end of the frame.
+ */
+ new_tvb = tvb_new_subset(tvb, offset, datalen,
+ reported_datalen);
+ call_dissector(sdp_handle, new_tvb, pinfo, tree);
+ } else {
+ if (tvb_get_guint8(tvb, offset) == RTSP_FRAMEHDR) {
+ /*
+ * This is interleaved stuff; don't
+ * treat it as raw data - set "datalen"
+ * to 0, so we won't skip the offset
+ * past it, which will cause our
+ * caller to process that stuff itself.
+ */
+ datalen = 0;
+ } else {
+ proto_tree_add_text(rtsp_tree, tvb, offset,
+ datalen, "Data (%d bytes)",
+ reported_datalen);
+ }
+ }
+
+ /*
+ * We've processed "datalen" bytes worth of data
+ * (which may be no data at all); advance the
+ * offset past whatever data we've processed.
+ */
+ offset += datalen;
+ }
+ return offset - orig_offset;
+}
+
+static void
+process_rtsp_request(tvbuff_t *tvb, int offset, const guchar *data,
+ size_t linelen, proto_tree *tree)
+{
+ const guchar *lineend = data + linelen;
+ unsigned ii;
+ const guchar *url;
+ const guchar *url_start;
+ guchar *tmp_url;
+
+ /* Request Methods */
+ for (ii = 0; ii < RTSP_NMETHODS; ii++) {
+ size_t len = strlen(rtsp_methods[ii]);
+ if (linelen >= len &&
+ strncasecmp(rtsp_methods[ii], data, len) == 0 &&
+ (len == linelen || isspace(data[len])))
+ break;
+ }
+ if (ii == RTSP_NMETHODS) {
+ /*
+ * We got here because "is_rtsp_request_or_reply()" returned
+ * RTSP_REQUEST, so we know one of the request methods
+ * matched, so we "can't get here".
+ */
+ g_assert_not_reached();
+ }
+
+ /* Method name */
+ proto_tree_add_string(tree, hf_rtsp_method, tvb, offset,
+ strlen(rtsp_methods[ii]), rtsp_methods[ii]);
+
+
+ /* URL */
+ url = data;
+ while (url < lineend && !isspace(*url))
+ url++;
+ while (url < lineend && isspace(*url))
+ url++;
+ url_start = url;
+ while (url < lineend && !isspace(*url))
+ url++;
+ tmp_url = g_malloc(url - url_start + 1);
+ memcpy(tmp_url, url_start, url - url_start);
+ tmp_url[url - url_start] = 0;
+ proto_tree_add_string(tree, hf_rtsp_url, tvb,
+ offset + (url_start - data), url - url_start, tmp_url);
+ g_free(tmp_url);
+}
+
+static void
+process_rtsp_reply(tvbuff_t *tvb, int offset, const guchar *data,
+ size_t linelen, proto_tree *tree)
+{
+ const guchar *lineend = data + linelen;
+ const guchar *status = data;
+ const guchar *status_start;
+ unsigned int status_i;
+
+ /* status code */
+ while (status < lineend && !isspace(*status))
+ status++;
+ while (status < lineend && isspace(*status))
+ status++;
+ status_start = status;
+ status_i = 0;
+ while (status < lineend && isdigit(*status))
+ status_i = status_i * 10 + *status++ - '0';
+ proto_tree_add_uint(tree, hf_rtsp_status, tvb,
+ offset + (status_start - data),
+ status - status_start, status_i);
+}
+
+static void
+dissect_rtsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ int len;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ len = (tvb_get_guint8(tvb, offset) == RTSP_FRAMEHDR)
+ ? dissect_rtspinterleaved(tvb, offset, pinfo, tree)
+ : dissect_rtspmessage(tvb, offset, pinfo, tree);
+ if (len == -1)
+ break;
+ offset += len;
+
+ /*
+ * OK, we've set the Protocol and Info columns for the
+ * first RTSP message; make the columns non-writable,
+ * so that we don't change it for subsequent RTSP messages.
+ */
+ col_set_writable(pinfo->cinfo, FALSE);
+ }
+}
+
+static void
+rtsp_init(void)
+{
+/* Routine to initialize rtsp protocol before each capture or filter pass. */
+/* Release any memory if needed. Then setup the memory chunks. */
+
+ if (rtsp_vals)
+ g_mem_chunk_destroy(rtsp_vals);
+
+ rtsp_vals = g_mem_chunk_new("rtsp_vals",
+ sizeof(rtsp_conversation_data_t),
+ rtsp_hash_init_count * sizeof(rtsp_conversation_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+void
+proto_register_rtsp(void)
+{
+ static gint *ett[] = {
+ &ett_rtspframe,
+ &ett_rtsp,
+ &ett_rtsp_method,
+ };
+ static hf_register_info hf[] = {
+ { &hf_rtsp_method,
+ { "Method", "rtsp.method", FT_STRING, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_rtsp_url,
+ { "URL", "rtsp.url", FT_STRING, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_rtsp_status,
+ { "Status", "rtsp.status", FT_UINT32, BASE_DEC, NULL, 0,
+ "", HFILL }},
+ { &hf_rtsp_session,
+ { "Session", "rtsp.session", FT_STRING, BASE_NONE, NULL, 0,
+ "", HFILL }},
+ { &hf_rtsp_X_Vig_Msisdn,
+ { "X-Vig-Msisdn", "X_Vig_Msisdn", FT_STRING, BASE_NONE, NULL, 0,
+ "", HFILL }},
+
+
+ };
+ module_t *rtsp_module;
+
+ proto_rtsp = proto_register_protocol("Real Time Streaming Protocol",
+ "RTSP", "rtsp");
+ proto_register_field_array(proto_rtsp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register our configuration options, particularly our ports */
+
+ rtsp_module = prefs_register_protocol(proto_rtsp, proto_reg_handoff_rtsp);
+ prefs_register_uint_preference(rtsp_module, "tcp.port",
+ "RTSP TCP Port",
+ "Set the TCP port for RTSP messages",
+ 10, &global_rtsp_tcp_port);
+ prefs_register_uint_preference(rtsp_module, "tcp.alternate_port",
+ "Alternate RTSP TCP Port",
+ "Set the alternate TCP port for RTSP messages",
+ 10, &global_rtsp_tcp_alternate_port);
+ prefs_register_bool_preference(rtsp_module, "desegment_headers",
+ "Desegment all RTSP headers\nspanning multiple TCP segments",
+ "Whether the RTSP dissector should desegment all headers "
+ "of a request spanning multiple TCP segments",
+ &rtsp_desegment_headers);
+ prefs_register_bool_preference(rtsp_module, "desegment_body",
+ "Trust the \"Content-length:\" header and\ndesegment RTSP "
+ "bodies\nspanning multiple TCP segments",
+ "Whether the RTSP dissector should use the "
+ "\"Content-length:\" value to desegment the body "
+ "of a request spanning multiple TCP segments",
+ &rtsp_desegment_body);
+
+ register_init_routine(rtsp_init); /* register re-init routine */
+}
+
+void
+proto_reg_handoff_rtsp(void)
+{
+ dissector_handle_t rtsp_handle;
+ static int rtsp_prefs_initialized = FALSE;
+
+ rtsp_handle = create_dissector_handle(dissect_rtsp, proto_rtsp);
+
+ if (!rtsp_prefs_initialized) {
+ rtsp_prefs_initialized = TRUE;
+ }
+ else {
+ dissector_delete("tcp.port", tcp_port, rtsp_handle);
+ dissector_delete("tcp.port", tcp_alternate_port, rtsp_handle);
+ }
+ /* Set our port number for future use */
+
+ tcp_port = global_rtsp_tcp_port;
+ tcp_alternate_port = global_rtsp_tcp_alternate_port;
+
+ dissector_add("tcp.port", tcp_port, rtsp_handle);
+ dissector_add("tcp.port", tcp_alternate_port, rtsp_handle);
+
+ sdp_handle = find_dissector("sdp");
+ rtp_handle = find_dissector("rtp");
+ rtcp_handle = find_dissector("rtcp");
+}
diff --git a/epan/dissectors/packet-rwall.c b/epan/dissectors/packet-rwall.c
new file mode 100644
index 0000000000..531bb0d80f
--- /dev/null
+++ b/epan/dissectors/packet-rwall.c
@@ -0,0 +1,89 @@
+/* packet-rwall.c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-rwall.h"
+
+static int proto_rwall = -1;
+static int hf_rwall_procedure_v1 = -1;
+static int hf_rwall_message = -1;
+
+static gint ett_rwall = -1;
+
+static int
+dissect_rwall_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_string(tvb, tree, hf_rwall_message, offset, NULL);
+
+ return offset;
+}
+
+static const vsff rwall1_proc[] = {
+ { RWALL_WALL, "RWALL",
+ dissect_rwall_call, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string rwall1_proc_vals[] = {
+ { RWALL_WALL, "RWALL" },
+ { 0, NULL }
+};
+
+
+void
+proto_register_rwall(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rwall_procedure_v1, {
+ "V1 Procedure", "rwall.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(rwall1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_rwall_message, {
+ "Message", "rwall.message", FT_STRING, BASE_DEC,
+ NULL, 0, "Message", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_rwall,
+ };
+
+ proto_rwall = proto_register_protocol("Remote Wall protocol",
+ "RWALL", "rwall");
+ proto_register_field_array(proto_rwall, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_rwall(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_rwall, RWALL_PROGRAM, ett_rwall);
+ /* Register the procedure tables */
+ rpc_init_proc_table(RWALL_PROGRAM, 1, rwall1_proc, hf_rwall_procedure_v1);
+}
+
+
diff --git a/epan/dissectors/packet-rwall.h b/epan/dissectors/packet-rwall.h
new file mode 100644
index 0000000000..f63d3c88eb
--- /dev/null
+++ b/epan/dissectors/packet-rwall.h
@@ -0,0 +1,32 @@
+/* packet-rwall.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_RWALL_H
+#define PACKET_RWALL_H
+
+/* there is no procedure 1 */
+#define RWALL_WALL 2
+
+#define RWALL_PROGRAM 100008
+
+#endif
diff --git a/epan/dissectors/packet-rx.c b/epan/dissectors/packet-rx.c
new file mode 100644
index 0000000000..8600c38635
--- /dev/null
+++ b/epan/dissectors/packet-rx.c
@@ -0,0 +1,781 @@
+/* packet-rx.c
+ * Routines for RX packet dissection
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ * Based on routines from tcpdump patches by
+ * Ken Hornstein <kenh@cmf.nrl.navy.mil>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-rx.h"
+#include <epan/resolv.h>
+
+#define UDP_PORT_RX_LOW 7000
+#define UDP_PORT_RX_HIGH 7009
+#define UDP_PORT_RX_AFS_BACKUPS 7021
+
+static const value_string rx_types[] = {
+ { RX_PACKET_TYPE_DATA, "data" },
+ { RX_PACKET_TYPE_ACK, "ack" },
+ { RX_PACKET_TYPE_BUSY, "busy" },
+ { RX_PACKET_TYPE_ABORT, "abort" },
+ { RX_PACKET_TYPE_ACKALL, "ackall" },
+ { RX_PACKET_TYPE_CHALLENGE, "challenge" },
+ { RX_PACKET_TYPE_RESPONSE, "response" },
+ { RX_PACKET_TYPE_DEBUG, "debug" },
+ { RX_PACKET_TYPE_PARAMS, "params" },
+ { RX_PACKET_TYPE_VERSION, "version" },
+ { 0, NULL },
+};
+
+static const value_string rx_reason[] = {
+ { RX_ACK_REQUESTED, "Ack Requested" },
+ { RX_ACK_DUPLICATE, "Duplicate Packet" },
+ { RX_ACK_OUT_OF_SEQUENCE, "Out Of Sequence" },
+ { RX_ACK_EXEEDS_WINDOW, "Exceeds Window" },
+ { RX_ACK_NOSPACE, "No Space" },
+ { RX_ACK_PING, "Ping" },
+ { RX_ACK_PING_RESPONSE, "Ping Response" },
+ { RX_ACK_DELAY, "Delay" },
+ { RX_ACK_IDLE, "Idle" },
+ { 0, NULL }
+};
+
+static const value_string rx_ack_type[] = {
+ { RX_ACK_TYPE_NACK, "NACK" },
+ { RX_ACK_TYPE_ACK, "ACK" },
+ { 0, NULL }
+};
+
+static int proto_rx = -1;
+static int hf_rx_epoch = -1;
+static int hf_rx_cid = -1;
+static int hf_rx_seq = -1;
+static int hf_rx_serial = -1;
+static int hf_rx_callnumber = -1;
+static int hf_rx_type = -1;
+static int hf_rx_flags = -1;
+static int hf_rx_flags_clientinit = -1;
+static int hf_rx_flags_request_ack = -1;
+static int hf_rx_flags_last_packet = -1;
+static int hf_rx_flags_more_packets = -1;
+static int hf_rx_flags_free_packet = -1;
+static int hf_rx_userstatus = -1;
+static int hf_rx_securityindex = -1;
+static int hf_rx_spare = -1;
+static int hf_rx_serviceid = -1;
+static int hf_rx_bufferspace = -1;
+static int hf_rx_maxskew = -1;
+static int hf_rx_first_packet = -1;
+static int hf_rx_prev_packet = -1;
+static int hf_rx_reason = -1;
+static int hf_rx_numacks = -1;
+static int hf_rx_ack_type = -1;
+static int hf_rx_ack = -1;
+static int hf_rx_challenge = -1;
+static int hf_rx_version = -1;
+static int hf_rx_nonce = -1;
+static int hf_rx_inc_nonce = -1;
+static int hf_rx_min_level = -1;
+static int hf_rx_level = -1;
+static int hf_rx_response = -1;
+static int hf_rx_encrypted = -1;
+static int hf_rx_kvno = -1;
+static int hf_rx_ticket_len = -1;
+static int hf_rx_ticket = -1;
+static int hf_rx_ifmtu = -1;
+static int hf_rx_maxmtu = -1;
+static int hf_rx_rwind = -1;
+static int hf_rx_maxpackets = -1;
+static int hf_rx_abort = -1;
+static int hf_rx_abortcode = -1;
+
+static gint ett_rx = -1;
+static gint ett_rx_flags = -1;
+static gint ett_rx_ack = -1;
+static gint ett_rx_challenge = -1;
+static gint ett_rx_response = -1;
+static gint ett_rx_encrypted = -1;
+static gint ett_rx_abort = -1;
+
+static dissector_handle_t afs_handle;
+
+static int
+dissect_rx_response_encrypted(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree;
+ proto_item *item;
+ int old_offset=offset;
+ int i;
+ guint32 callnumber;
+
+ item = proto_tree_add_item(parent_tree, hf_rx_encrypted, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_rx_encrypted);
+
+ /* epoch : 4 bytes */
+ {
+ nstime_t ts;
+ ts.secs = tvb_get_ntohl(tvb, offset);
+ ts.nsecs = 0;
+
+ proto_tree_add_time(tree, hf_rx_epoch, tvb,
+ offset, 4, &ts);
+ offset += 4;
+ }
+
+ /* cid : 4 bytes */
+ proto_tree_add_item(tree, hf_rx_cid, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /*FIXME dont know how to handle this checksum, skipping it */
+ offset += 4;
+
+ /* sequrityindex : 1 byte */
+ proto_tree_add_item(tree, hf_rx_securityindex, tvb, offset, 1, FALSE);
+ offset += 4;
+
+ for (i=0; i<RX_MAXCALLS; i++) {
+ /* callnumber : 4 bytes */
+ callnumber = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_rx_callnumber, tvb,
+ offset, 4, callnumber);
+ offset += 4;
+ }
+
+ /* inc nonce : 4 bytes */
+ proto_tree_add_item(tree, hf_rx_inc_nonce, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* level : 4 bytes */
+ proto_tree_add_item(tree, hf_rx_level, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+dissect_rx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
+{
+ proto_tree *tree;
+ proto_item *item;
+ guint32 version, tl;
+ int old_offset=offset;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "RESPONSE "
+ "Seq: %lu "
+ "Call: %lu "
+ "Source Port: %s "
+ "Destination Port: %s ",
+ (unsigned long)seq,
+ (unsigned long)callnumber,
+ get_udp_port(pinfo->srcport),
+ get_udp_port(pinfo->destport)
+ );
+ }
+
+ item = proto_tree_add_item(parent_tree, hf_rx_response, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_rx_response);
+
+ version = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_rx_version, tvb,
+ offset, 4, version);
+ offset += 4;
+
+ if (version==2) {
+ /* skip unused */
+ offset += 4;
+
+ /* encrypted : struct */
+ offset = dissect_rx_response_encrypted(tvb, tree, offset);
+
+ /* kvno */
+ proto_tree_add_item(tree, hf_rx_kvno, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* ticket_len */
+ tl = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_rx_ticket_len, tvb,
+ offset, 4, tl);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_rx_ticket, tvb, offset, tl, FALSE);
+ offset += tl;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_rx_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
+{
+ proto_tree *tree;
+ proto_item *item;
+ int old_offset=offset;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "ABORT "
+ "Seq: %lu "
+ "Call: %lu "
+ "Source Port: %s "
+ "Destination Port: %s ",
+ (unsigned long)seq,
+ (unsigned long)callnumber,
+ get_udp_port(pinfo->srcport),
+ get_udp_port(pinfo->destport)
+ );
+ }
+
+ item = proto_tree_add_item(parent_tree, hf_rx_abort, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_rx_abort);
+
+ /* kvno */
+ proto_tree_add_item(tree, hf_rx_abortcode, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+dissect_rx_challenge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
+{
+ proto_tree *tree;
+ proto_item *item;
+ guint32 version;
+ int old_offset=offset;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "CHALLENGE "
+ "Seq: %lu "
+ "Call: %lu "
+ "Source Port: %s "
+ "Destination Port: %s ",
+ (unsigned long)seq,
+ (unsigned long)callnumber,
+ get_udp_port(pinfo->srcport),
+ get_udp_port(pinfo->destport)
+ );
+ }
+
+ item = proto_tree_add_item(parent_tree, hf_rx_challenge, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_rx_challenge);
+
+ version = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_rx_version, tvb,
+ offset, 4, version);
+ offset += 4;
+
+ if (version==2) {
+ proto_tree_add_item(tree, hf_rx_nonce, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_rx_min_level, tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static int
+dissect_rx_acks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
+{
+ proto_tree *tree;
+ proto_item *item;
+ guint8 num;
+ int old_offset = offset;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "ACK "
+ "Seq: %lu "
+ "Call: %lu "
+ "Source Port: %s "
+ "Destination Port: %s ",
+ (unsigned long)seq,
+ (unsigned long)callnumber,
+ get_udp_port(pinfo->srcport),
+ get_udp_port(pinfo->destport)
+ );
+ }
+
+ item = proto_tree_add_item(parent_tree, hf_rx_ack, tvb, offset, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_rx_ack);
+
+
+ /* bufferspace: 2 bytes*/
+ proto_tree_add_item(tree, hf_rx_bufferspace, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* maxskew: 2 bytes*/
+ proto_tree_add_item(tree, hf_rx_maxskew, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* first packet: 4 bytes*/
+ proto_tree_add_item(tree, hf_rx_first_packet, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* prev packet: 4 bytes*/
+ proto_tree_add_item(tree, hf_rx_prev_packet, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* serial : 4 bytes */
+ proto_tree_add_item(tree, hf_rx_serial, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* reason : 1 byte */
+ proto_tree_add_item(tree, hf_rx_reason, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* nACKs */
+ num = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_rx_numacks, tvb, offset, 1, num);
+ offset += 1;
+
+ while(num--){
+ proto_tree_add_item(tree, hf_rx_ack_type, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+ }
+
+ /* Some implementations adds some extra fields.
+ * As far as I can see, these first add 3 padding bytes and then
+ * up to 4 32-bit values. (0,3,4 have been witnessed)
+ *
+ * RX as a protocol seems to be completely nondefined and seems to lack
+ * any sort of documentation other than "read the source of any of the
+ * (compatible?) implementations.
+ */
+ if (tvb_length_remaining(tvb, offset)>3) {
+ offset += 3; /* guess. some implementations adds 3 bytes */
+
+ if (tvb_reported_length_remaining(tvb, offset) >= 4){
+ proto_tree_add_item(tree, hf_rx_ifmtu, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ }
+ if (tvb_reported_length_remaining(tvb, offset) >= 4){
+ proto_tree_add_item(tree, hf_rx_maxmtu, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ }
+ if (tvb_reported_length_remaining(tvb, offset) >= 4){
+ proto_tree_add_item(tree, hf_rx_rwind, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ }
+ if (tvb_reported_length_remaining(tvb, offset) >= 4){
+ proto_tree_add_item(tree, hf_rx_maxpackets, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ }
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+
+static int
+dissect_rx_flags(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree;
+ proto_item *item;
+ guint8 flags;
+
+ flags = tvb_get_guint8(tvb, offset);
+ rxinfo->flags = flags;
+
+ item = proto_tree_add_uint(parent_tree, hf_rx_flags, tvb,
+ offset, 1, flags);
+ tree = proto_item_add_subtree(item, ett_rx_flags);
+
+ proto_tree_add_boolean(tree, hf_rx_flags_free_packet, tvb,
+ offset, 1, flags);
+ proto_tree_add_boolean(tree, hf_rx_flags_more_packets, tvb,
+ offset, 1, flags);
+ proto_tree_add_boolean(tree, hf_rx_flags_last_packet, tvb,
+ offset, 1, flags);
+ proto_tree_add_boolean(tree, hf_rx_flags_request_ack, tvb,
+ offset, 1, flags);
+ proto_tree_add_boolean(tree, hf_rx_flags_clientinit, tvb,
+ offset, 1, flags);
+
+ offset += 1;
+ return offset;
+}
+
+static void
+dissect_rx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ proto_tree *tree;
+ proto_item *item;
+ int offset = 0;
+ struct rxinfo rxinfo;
+ guint8 type;
+ guint32 seq, callnumber;
+ guint16 serviceid;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RX");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ item = proto_tree_add_protocol_format(parent_tree, proto_rx, tvb,
+ offset, 28, "RX Protocol");
+ tree = proto_item_add_subtree(item, ett_rx);
+
+ /* epoch : 4 bytes */
+ {
+ nstime_t ts;
+ ts.secs = tvb_get_ntohl(tvb, offset);
+ ts.nsecs = 0;
+
+ proto_tree_add_time(tree, hf_rx_epoch, tvb,
+ offset, 4, &ts);
+ offset += 4;
+ }
+
+ /* cid : 4 bytes */
+ proto_tree_add_item(tree, hf_rx_cid, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* callnumber : 4 bytes */
+ callnumber = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_rx_callnumber, tvb,
+ offset, 4, callnumber);
+ offset += 4;
+ rxinfo.callnumber = callnumber;
+
+ /* seq : 4 bytes */
+ seq = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_rx_seq, tvb,
+ offset, 4, seq);
+ offset += 4;
+ rxinfo.seq = seq;
+
+ /* serial : 4 bytes */
+ proto_tree_add_item(tree, hf_rx_serial, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* type : 1 byte */
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_rx_type, tvb,
+ offset, 1, type);
+ offset += 1;
+ rxinfo.type = type;
+
+ /* flags : 1 byte */
+ offset = dissect_rx_flags(tvb, &rxinfo, tree, offset);
+
+ /* userstatus : 1 byte */
+ proto_tree_add_item(tree, hf_rx_userstatus, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* sequrityindex : 1 byte */
+ proto_tree_add_item(tree, hf_rx_securityindex, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /*
+ * How clever: even though the AFS header files indicate that the
+ * serviceId is first, it's really encoded _after_ the spare field.
+ * I wasted a day figuring that out!
+ */
+
+ /* spare */
+ proto_tree_add_item(tree, hf_rx_spare, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* service id : 2 bytes */
+ serviceid = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_rx_serviceid, tvb,
+ offset, 2, serviceid);
+ offset += 2;
+ rxinfo.serviceid = serviceid;
+
+ switch (type) {
+ case RX_PACKET_TYPE_ACK:
+ /*dissect_rx_acks(tvb, pinfo, parent_tree, offset,
+ cant create it in a parallell tree, then ett seasrch
+ wont work */
+ dissect_rx_acks(tvb, pinfo, tree, offset,
+ seq, callnumber);
+ break;
+ case RX_PACKET_TYPE_ACKALL:
+ /* does not contain any payload */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "ACKALL "
+ "Seq: %lu "
+ "Call: %lu "
+ "Source Port: %s "
+ "Destination Port: %s ",
+ (unsigned long)seq,
+ (unsigned long)callnumber,
+ get_udp_port(pinfo->srcport),
+ get_udp_port(pinfo->destport)
+ );
+ }
+ break;
+ case RX_PACKET_TYPE_CHALLENGE:
+ dissect_rx_challenge(tvb, pinfo, tree, offset, seq, callnumber);
+ break;
+ case RX_PACKET_TYPE_RESPONSE:
+ dissect_rx_response(tvb, pinfo, tree, offset, seq, callnumber);
+ break;
+ case RX_PACKET_TYPE_DATA: {
+ tvbuff_t *next_tvb;
+ pinfo->private_data = &rxinfo;
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(afs_handle, next_tvb, pinfo, parent_tree);
+ };
+ break;
+ case RX_PACKET_TYPE_ABORT:
+ dissect_rx_abort(tvb, pinfo, tree, offset, seq, callnumber);
+ break;
+ }
+
+}
+
+void
+proto_register_rx(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rx_epoch, {
+ "Epoch", "rx.epoch", FT_ABSOLUTE_TIME, BASE_DEC,
+ NULL, 0, "Epoch", HFILL }},
+
+ { &hf_rx_cid, {
+ "CID", "rx.cid", FT_UINT32, BASE_DEC,
+ NULL, 0, "CID", HFILL }},
+
+ { &hf_rx_callnumber, {
+ "Call Number", "rx.callnumber", FT_UINT32, BASE_DEC,
+ NULL, 0, "Call Number", HFILL }},
+
+ { &hf_rx_seq, {
+ "Sequence Number", "rx.seq", FT_UINT32, BASE_DEC,
+ NULL, 0, "Sequence Number", HFILL }},
+
+ { &hf_rx_serial, {
+ "Serial", "rx.serial", FT_UINT32, BASE_DEC,
+ NULL, 0, "Serial", HFILL }},
+
+ { &hf_rx_type, {
+ "Type", "rx.type", FT_UINT8, BASE_DEC,
+ VALS(rx_types), 0, "Type", HFILL }},
+
+ { &hf_rx_flags, {
+ "Flags", "rx.flags", FT_UINT8, BASE_HEX,
+ NULL, 0, "Flags", HFILL }},
+
+ { &hf_rx_flags_clientinit, {
+ "Client Initiated", "rx.flags.client_init", FT_BOOLEAN, 8,
+ NULL, RX_CLIENT_INITIATED, "Client Initiated", HFILL }},
+
+ { &hf_rx_flags_request_ack, {
+ "Request Ack", "rx.flags.request_ack", FT_BOOLEAN, 8,
+ NULL, RX_REQUEST_ACK, "Request Ack", HFILL }},
+
+ { &hf_rx_flags_last_packet, {
+ "Last Packet", "rx.flags.last_packet", FT_BOOLEAN, 8,
+ NULL, RX_LAST_PACKET, "Last Packet", HFILL }},
+
+ { &hf_rx_flags_more_packets, {
+ "More Packets", "rx.flags.more_packets", FT_BOOLEAN, 8,
+ NULL, RX_MORE_PACKETS, "More Packets", HFILL }},
+
+ { &hf_rx_flags_free_packet, {
+ "Free Packet", "rx.flags.free_packet", FT_BOOLEAN, 8,
+ NULL, RX_FREE_PACKET, "Free Packet", HFILL }},
+
+ /* XXX - what about RX_SLOW_START_OR_JUMBO? */
+
+ { &hf_rx_userstatus, {
+ "User Status", "rx.userstatus", FT_UINT32, BASE_DEC,
+ NULL, 0, "User Status", HFILL }},
+
+ { &hf_rx_securityindex, {
+ "Security Index", "rx.securityindex", FT_UINT32, BASE_DEC,
+ NULL, 0, "Security Index", HFILL }},
+
+ { &hf_rx_spare, {
+ "Spare/Checksum", "rx.spare", FT_UINT16, BASE_DEC,
+ NULL, 0, "Spare/Checksum", HFILL }},
+
+ { &hf_rx_serviceid, {
+ "Service ID", "rx.serviceid", FT_UINT16, BASE_DEC,
+ NULL, 0, "Service ID", HFILL }},
+
+ { &hf_rx_bufferspace, {
+ "Bufferspace", "rx.bufferspace", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number Of Packets Available", HFILL }},
+
+ { &hf_rx_maxskew, {
+ "Max Skew", "rx.maxskew", FT_UINT16, BASE_DEC,
+ NULL, 0, "Max Skew", HFILL }},
+
+ { &hf_rx_first_packet, {
+ "First Packet", "rx.first", FT_UINT32, BASE_DEC,
+ NULL, 0, "First Packet", HFILL }},
+
+ { &hf_rx_prev_packet, {
+ "Prev Packet", "rx.prev", FT_UINT32, BASE_DEC,
+ NULL, 0, "Previous Packet", HFILL }},
+
+ { &hf_rx_reason, {
+ "Reason", "rx.reason", FT_UINT8, BASE_DEC,
+ VALS(rx_reason), 0, "Reason For This ACK", HFILL }},
+
+ { &hf_rx_numacks, {
+ "Num ACKs", "rx.num_acks", FT_UINT8, BASE_DEC,
+ NULL, 0, "Number Of ACKs", HFILL }},
+
+ { &hf_rx_ack_type, {
+ "ACK Type", "rx.ack_type", FT_UINT8, BASE_DEC,
+ VALS(rx_ack_type), 0, "Type Of ACKs", HFILL }},
+
+ { &hf_rx_ack, {
+ "ACK Packet", "rx.ack", FT_NONE, BASE_NONE,
+ NULL, 0, "ACK Packet", HFILL }},
+
+ { &hf_rx_challenge, {
+ "CHALLENGE Packet", "rx.challenge", FT_NONE, BASE_NONE,
+ NULL, 0, "CHALLENGE Packet", HFILL }},
+
+ { &hf_rx_version, {
+ "Version", "rx.version", FT_UINT32, BASE_DEC,
+ NULL, 0, "Version Of Challenge/Response", HFILL }},
+
+ { &hf_rx_nonce, {
+ "Nonce", "rx.nonce", FT_UINT32, BASE_HEX,
+ NULL, 0, "Nonce", HFILL }},
+
+ { &hf_rx_inc_nonce, {
+ "Inc Nonce", "rx.inc_nonce", FT_UINT32, BASE_HEX,
+ NULL, 0, "Incremented Nonce", HFILL }},
+
+ { &hf_rx_min_level, {
+ "Min Level", "rx.min_level", FT_UINT32, BASE_DEC,
+ NULL, 0, "Min Level", HFILL }},
+
+ { &hf_rx_level, {
+ "Level", "rx.level", FT_UINT32, BASE_DEC,
+ NULL, 0, "Level", HFILL }},
+
+ { &hf_rx_response, {
+ "RESPONSE Packet", "rx.response", FT_NONE, BASE_NONE,
+ NULL, 0, "RESPONSE Packet", HFILL }},
+
+ { &hf_rx_abort, {
+ "ABORT Packet", "rx.abort", FT_NONE, BASE_NONE,
+ NULL, 0, "ABORT Packet", HFILL }},
+
+ { &hf_rx_encrypted, {
+ "Encrypted", "rx.encrypted", FT_NONE, BASE_NONE,
+ NULL, 0, "Encrypted part of response packet", HFILL }},
+
+ { &hf_rx_kvno, {
+ "kvno", "rx.kvno", FT_UINT32, BASE_DEC,
+ NULL, 0, "kvno", HFILL }},
+
+ { &hf_rx_ticket_len, {
+ "Ticket len", "rx.ticket_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Ticket Length", HFILL }},
+
+ { &hf_rx_ticket, {
+ "ticket", "rx.ticket", FT_BYTES, BASE_HEX,
+ NULL, 0, "Ticket", HFILL }},
+
+ { &hf_rx_ifmtu, {
+ "Interface MTU", "rx.if_mtu", FT_UINT32, BASE_DEC,
+ NULL, 0, "Interface MTU", HFILL }},
+
+ { &hf_rx_maxmtu, {
+ "Max MTU", "rx.max_mtu", FT_UINT32, BASE_DEC,
+ NULL, 0, "Max MTU", HFILL }},
+
+ { &hf_rx_rwind, {
+ "rwind", "rx.rwind", FT_UINT32, BASE_DEC,
+ NULL, 0, "rwind", HFILL }},
+
+ { &hf_rx_maxpackets, {
+ "Max Packets", "rx.max_packets", FT_UINT32, BASE_DEC,
+ NULL, 0, "Max Packets", HFILL }},
+
+ { &hf_rx_abortcode, {
+ "Abort Code", "rx.abort_code", FT_UINT32, BASE_DEC,
+ NULL, 0, "Abort Code", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_rx,
+ &ett_rx_flags,
+ &ett_rx_ack,
+ &ett_rx_challenge,
+ &ett_rx_response,
+ &ett_rx_encrypted,
+ &ett_rx_abort
+ };
+
+ proto_rx = proto_register_protocol("RX Protocol", "RX", "rx");
+ proto_register_field_array(proto_rx, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_rx(void)
+{
+ dissector_handle_t rx_handle;
+
+ int port;
+
+ /*
+ * Get handle for the AFS dissector.
+ */
+ afs_handle = find_dissector("afs");
+
+ /* Ports in the range UDP_PORT_RX_LOW to UDP_PORT_RX_HIGH
+ are all used for various AFS services. */
+ rx_handle = create_dissector_handle(dissect_rx, proto_rx);
+ for (port = UDP_PORT_RX_LOW; port <= UDP_PORT_RX_HIGH; port++)
+ dissector_add("udp.port", port, rx_handle);
+ dissector_add("udp.port", UDP_PORT_RX_AFS_BACKUPS, rx_handle);
+}
diff --git a/epan/dissectors/packet-rx.h b/epan/dissectors/packet-rx.h
new file mode 100644
index 0000000000..9824675b1f
--- /dev/null
+++ b/epan/dissectors/packet-rx.h
@@ -0,0 +1,82 @@
+/* packet-rx.h
+ * Definitions for packet disassembly structures and routines
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_RX_H
+#define PACKET_RX_H
+
+/*
+ * Private data passed from the RX dissector to the AFS dissector.
+ */
+struct rxinfo {
+ guint8 type;
+ guint8 flags;
+ guint16 serviceid;
+ guint32 callnumber;
+ guint32 seq;
+};
+
+/*
+ * RX protocol definitions.
+ */
+
+/*
+ * Packet types.
+ */
+#define RX_PACKET_TYPE_DATA 1
+#define RX_PACKET_TYPE_ACK 2
+#define RX_PACKET_TYPE_BUSY 3
+#define RX_PACKET_TYPE_ABORT 4
+#define RX_PACKET_TYPE_ACKALL 5
+#define RX_PACKET_TYPE_CHALLENGE 6
+#define RX_PACKET_TYPE_RESPONSE 7
+#define RX_PACKET_TYPE_DEBUG 8
+#define RX_PACKET_TYPE_PARAMS 9
+#define RX_PACKET_TYPE_VERSION 13
+
+/*
+ * Flag bits in the RX header.
+ */
+#define RX_CLIENT_INITIATED 1
+#define RX_REQUEST_ACK 2
+#define RX_LAST_PACKET 4
+#define RX_MORE_PACKETS 8
+#define RX_FREE_PACKET 16
+#define RX_SLOW_START_OR_JUMBO 32
+
+#define RX_ACK_TYPE_NACK 0
+#define RX_ACK_TYPE_ACK 1
+
+#define RX_ACK_REQUESTED 1
+#define RX_ACK_DUPLICATE 2
+#define RX_ACK_OUT_OF_SEQUENCE 3
+#define RX_ACK_EXEEDS_WINDOW 4
+#define RX_ACK_NOSPACE 5
+#define RX_ACK_PING 6
+#define RX_ACK_PING_RESPONSE 7
+#define RX_ACK_DELAY 8
+#define RX_ACK_IDLE 9
+
+#define RX_MAXCALLS 4
+
+#endif
diff --git a/epan/dissectors/packet-sadmind.c b/epan/dissectors/packet-sadmind.c
new file mode 100644
index 0000000000..ffcf2a065c
--- /dev/null
+++ b/epan/dissectors/packet-sadmind.c
@@ -0,0 +1,111 @@
+/* packet-sadmind.c
+ * Stubs for the Solstice admin daemon RPC service
+ *
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+
+static int proto_sadmind = -1;
+static int hf_sadmind_procedure_v1 = -1;
+static int hf_sadmind_procedure_v2 = -1;
+static int hf_sadmind_procedure_v3 = -1;
+
+static gint ett_sadmind = -1;
+
+#define SADMIND_PROGRAM 100232
+
+#define SADMINDPROC_NULL 0
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff sadmind1_proc[] = {
+ { SADMINDPROC_NULL, "NULL",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string sadmind1_proc_vals[] = {
+ { SADMINDPROC_NULL, "NULL" },
+ { 0, NULL }
+};
+
+static const vsff sadmind2_proc[] = {
+ { SADMINDPROC_NULL, "NULL",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string sadmind2_proc_vals[] = {
+ { SADMINDPROC_NULL, "NULL" },
+ { 0, NULL }
+};
+
+static const vsff sadmind3_proc[] = {
+ { SADMINDPROC_NULL, "NULL",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string sadmind3_proc_vals[] = {
+ { SADMINDPROC_NULL, "NULL" },
+ { 0, NULL }
+};
+
+void
+proto_register_sadmind(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_sadmind_procedure_v1, {
+ "V1 Procedure", "sadmind.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(sadmind1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_sadmind_procedure_v2, {
+ "V2 Procedure", "sadmind.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(sadmind2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_sadmind_procedure_v3, {
+ "V3 Procedure", "sadmind.procedure_v3", FT_UINT32, BASE_DEC,
+ VALS(sadmind3_proc_vals), 0, "V3 Procedure", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_sadmind,
+ };
+
+ proto_sadmind = proto_register_protocol("SADMIND", "SADMIND", "sadmind");
+ proto_register_field_array(proto_sadmind, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_sadmind(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_sadmind, SADMIND_PROGRAM, ett_sadmind);
+ /* Register the procedure tables */
+ rpc_init_proc_table(SADMIND_PROGRAM, 1, sadmind1_proc, hf_sadmind_procedure_v1);
+ rpc_init_proc_table(SADMIND_PROGRAM, 2, sadmind2_proc, hf_sadmind_procedure_v2);
+ rpc_init_proc_table(SADMIND_PROGRAM, 3, sadmind3_proc, hf_sadmind_procedure_v3);
+}
diff --git a/epan/dissectors/packet-sap.c b/epan/dissectors/packet-sap.c
new file mode 100644
index 0000000000..c54ad1ecd8
--- /dev/null
+++ b/epan/dissectors/packet-sap.c
@@ -0,0 +1,362 @@
+/* packet-sap.c
+ * Routines for sap packet dissection
+ * RFC 2974
+ *
+ * Heikki Vatiainen <hessu@cs.tut.fi>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ipv6.h"
+
+#define UDP_PORT_SAP 9875
+
+#define MCAST_SAP_VERSION_MASK 0xE0 /* 3 bits for SAP version*/
+#define MCAST_SAP_VERSION_SHIFT 5 /* Right shift 5 bits to get the version */
+#define MCAST_SAP_VER0 0 /* Version 0 */
+#define MCAST_SAP_VER1PLUS 1 /* Version 1 or later */
+static const value_string mcast_sap_ver[] = {
+ { MCAST_SAP_VER0, "SAPv0"},
+ { MCAST_SAP_VER1PLUS, "SAPv1 or later"},
+ { 0, NULL} };
+
+static const true_false_string mcast_sap_address_type = {
+ "IPv6",
+ "IPv4"
+};
+
+static const true_false_string mcast_sap_message_type = {
+ "Deletion",
+ "Announcement"
+};
+
+static const true_false_string mcast_sap_crypt_type = {
+ "Payload encrypted",
+ "Payload not encrypted "
+};
+
+static const true_false_string mcast_sap_comp_type = {
+ "Payload compressed",
+ "Payload not compressed"
+};
+
+static const value_string mcast_sap_auth_ver[] = {
+ { 1, "SAP authentication header v1"},
+ { 0, NULL} };
+
+static const true_false_string mcast_sap_auth_pad = {
+ "Authentication subheader padded to 32 bits",
+ "No padding required for the authentication subheader"
+};
+
+#define MCAST_SAP_AUTH_TYPE_MASK 0x0F /* 4 bits for the type of the authentication header */
+#define MCAST_SAP_AUTH_TYPE_PGP 0
+#define MCAST_SAP_AUTH_TYPE_CMS 1
+static const value_string mcast_sap_auth_type[] = {
+ { MCAST_SAP_AUTH_TYPE_PGP, "PGP"},
+ { MCAST_SAP_AUTH_TYPE_CMS, "CMS"},
+ { 0, NULL} };
+
+#define MCAST_SAP_BIT_A 0x10 /* Address type: 0 IPv4, 1 IPv6 */
+#define MCAST_SAP_BIT_R 0x08 /* Reserved: Must be 0 */
+#define MCAST_SAP_BIT_T 0x04 /* Message Type: 0 announcement, 1 deletion */
+#define MCAST_SAP_BIT_E 0x02 /* Encryption Bit: 1 payload encrypted */
+#define MCAST_SAP_BIT_C 0x01 /* Compressed Bit: 1 payload zlib compressed */
+
+#define MCAST_SAP_AUTH_BIT_P 0x10 /* Padding required for the authentication header */
+
+
+static int proto_sap = -1;
+static int hf_sap_flags = -1;
+static int hf_sap_flags_v = -1;
+static int hf_sap_flags_a = -1;
+static int hf_sap_flags_r = -1;
+static int hf_sap_flags_t = -1;
+static int hf_sap_flags_e = -1;
+static int hf_sap_flags_c = -1;
+static int hf_auth_data = -1;
+static int hf_auth_flags = -1;
+static int hf_auth_flags_v = -1;
+static int hf_auth_flags_p = -1;
+static int hf_auth_flags_t = -1;
+
+static gint ett_sap = -1;
+static gint ett_sap_flags = -1;
+static gint ett_sap_auth = -1;
+static gint ett_sap_authf = -1;
+
+static dissector_handle_t sdp_handle;
+
+static void
+dissect_sap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ int sap_version, is_ipv6, is_del, is_enc, is_comp, addr_len;
+ guint8 vers_flags;
+ guint8 auth_len;
+ guint16 tmp1;
+ const guint8 *addr;
+ guint8 auth_flags;
+ tvbuff_t *next_tvb;
+
+ proto_item *si, *sif;
+ proto_tree *sap_tree, *sap_flags_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SAP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ vers_flags = tvb_get_guint8(tvb, offset);
+ is_ipv6 = vers_flags&MCAST_SAP_BIT_A;
+ is_del = vers_flags&MCAST_SAP_BIT_T;
+ is_enc = vers_flags&MCAST_SAP_BIT_E;
+ is_comp = vers_flags&MCAST_SAP_BIT_C;
+
+ sap_version = (vers_flags&MCAST_SAP_VERSION_MASK)>>MCAST_SAP_VERSION_SHIFT;
+ addr_len = (is_ipv6) ? sizeof(struct e_in6_addr) : 4;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (v%u)",
+ (is_del) ? "Deletion" : "Announcement", sap_version);
+ }
+
+ if (tree) {
+ si = proto_tree_add_item(tree, proto_sap, tvb, offset, -1, FALSE);
+ sap_tree = proto_item_add_subtree(si, ett_sap);
+
+ sif = proto_tree_add_uint(sap_tree, hf_sap_flags, tvb, offset, 1, vers_flags);
+ sap_flags_tree = proto_item_add_subtree(sif, ett_sap_flags);
+ proto_tree_add_uint(sap_flags_tree, hf_sap_flags_v, tvb, offset, 1, vers_flags);
+ proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_a, tvb, offset, 1, vers_flags);
+ proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_r, tvb, offset, 1, vers_flags);
+ proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_t, tvb, offset, 1, vers_flags);
+ proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_e, tvb, offset, 1, vers_flags);
+ proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_c, tvb, offset, 1, vers_flags);
+ offset++;
+
+ auth_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(sap_tree, tvb, offset, 1, "Authentication Length: %u", auth_len);
+ offset++;
+
+ tmp1 = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(sap_tree, tvb, offset, 2, "Message Identifier Hash: 0x%x", tmp1);
+ offset +=2;
+
+ addr = tvb_get_ptr(tvb, offset, addr_len);
+ proto_tree_add_text(sap_tree, tvb, offset, addr_len, "Originating Source: %s",
+ (is_ipv6) ? ip6_to_str((const struct e_in6_addr*)addr) : ip_to_str(addr));
+ offset += addr_len;
+
+ /* Authentication data lives in its own subtree */
+ if (auth_len > 0) {
+ guint32 auth_data_len;
+ proto_item *sdi, *sai;
+ proto_tree *sa_tree, *saf_tree;
+ int has_pad;
+ guint8 pad_len = 0;
+
+ auth_data_len = auth_len * sizeof(guint32);
+
+ sdi = proto_tree_add_item(sap_tree, hf_auth_data, tvb, offset, auth_data_len, FALSE);
+ sa_tree = proto_item_add_subtree(sdi, ett_sap_auth);
+
+ auth_flags = tvb_get_guint8(tvb, offset);
+ sai = proto_tree_add_uint(sa_tree, hf_auth_flags, tvb, offset, 1, auth_flags);
+ saf_tree = proto_item_add_subtree(sai, ett_sap_authf);
+ proto_tree_add_uint(saf_tree, hf_auth_flags_v, tvb, offset, 1, auth_flags);
+ proto_tree_add_boolean(saf_tree, hf_auth_flags_p, tvb, offset, 1, auth_flags);
+ proto_tree_add_uint(saf_tree, hf_auth_flags_t, tvb, offset, 1, auth_flags);
+
+ has_pad = auth_flags&MCAST_SAP_AUTH_BIT_P;
+ if (has_pad)
+ pad_len = tvb_get_guint8(tvb, offset+auth_data_len-1);
+
+ proto_tree_add_text(sa_tree, tvb, offset+1, auth_data_len-pad_len-1,
+ "Authentication subheader: (%u byte%s)",
+ auth_data_len-1, plurality(auth_data_len-1, "", "s"));
+ if (has_pad) {
+ proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-pad_len, pad_len,
+ "Authentication data padding: (%u byte%s)",
+ pad_len, plurality(pad_len, "", "s"));
+ proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-1, 1,
+ "Authentication data pad count: %u byte%s",
+ pad_len, plurality(pad_len, "", "s"));
+ }
+
+ offset += auth_data_len;
+ }
+ if (is_enc || is_comp) {
+ char *mangle;
+ if (is_enc && is_comp) mangle = "compressed and encrypted";
+ else if (is_enc) mangle = "encrypted";
+ else mangle = "compressed";
+ proto_tree_add_text(sap_tree, tvb, offset, -1,
+ "The rest of the packet is %s", mangle);
+ return;
+ }
+
+ /* Do we have the optional payload type aka. MIME content specifier */
+ if (tvb_strneql(tvb, offset, "v=", strlen("v="))) {
+ gint remaining_len;
+ guint32 pt_len;
+ int pt_string_len;
+
+ remaining_len = tvb_length_remaining(tvb, offset);
+ if (remaining_len == 0) {
+ /*
+ * "tvb_strneql()" failed because there was no
+ * data left in the packet.
+ *
+ * Set the remaining length to 1, so that
+ * we throw the appropriate exception in
+ * "tvb_get_ptr()", rather than displaying
+ * the payload type.
+ */
+ remaining_len = 1;
+ }
+ pt_string_len = tvb_strnlen(tvb, offset, remaining_len);
+ if (pt_string_len == -1) {
+ /*
+ * We didn't find a terminating '\0'; run to the
+ * end of the buffer.
+ */
+ pt_string_len = remaining_len;
+ pt_len = pt_string_len;
+ } else {
+ /*
+ * Include the '\0' in the total item length.
+ */
+ pt_len = pt_string_len + 1;
+ }
+ proto_tree_add_text(sap_tree, tvb, offset, pt_len,
+ "Payload type: %.*s", pt_string_len,
+ tvb_get_ptr(tvb, offset, pt_string_len));
+ offset += pt_len;
+ }
+ }
+
+ /* Done with SAP */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(sdp_handle, next_tvb, pinfo, tree);
+
+ return;
+}
+
+void proto_register_sap(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_sap_flags,
+ { "Flags", "sap.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Bits in the beginning of the SAP header", HFILL }},
+
+ { &hf_sap_flags_v,
+ { "Version Number", "sap.flags.v",
+ FT_UINT8, BASE_DEC, VALS(mcast_sap_ver), MCAST_SAP_VERSION_MASK,
+ "3 bit version field in the SAP header", HFILL }},
+
+ { &hf_sap_flags_a,
+ { "Address Type", "sap.flags.a",
+ FT_BOOLEAN, 8, TFS(&mcast_sap_address_type), MCAST_SAP_BIT_A,
+ "Originating source address type", HFILL }},
+
+ { &hf_sap_flags_r,
+ { "Reserved", "sap.flags.r",
+ FT_BOOLEAN, 8, TFS(&flags_set_truth), MCAST_SAP_BIT_R,
+ "Reserved", HFILL }},
+
+ { &hf_sap_flags_t,
+ { "Message Type", "sap.flags.t",
+ FT_BOOLEAN, 8, TFS(&mcast_sap_message_type), MCAST_SAP_BIT_T,
+ "Announcement type", HFILL }},
+
+ { &hf_sap_flags_e,
+ { "Encryption Bit", "sap.flags.e",
+ FT_BOOLEAN, 8, TFS(&mcast_sap_crypt_type), MCAST_SAP_BIT_E,
+ "Encryption", HFILL }},
+
+ { &hf_sap_flags_c,
+ { "Compression Bit", "sap.flags.c",
+ FT_BOOLEAN, 8, TFS(&mcast_sap_comp_type), MCAST_SAP_BIT_C,
+ "Compression", HFILL }},
+
+ { &hf_auth_data,
+ { "Authentication data", "sap.auth",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Auth data", HFILL }},
+
+ { &hf_auth_flags,
+ { "Authentication data flags", "sap.auth.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Auth flags", HFILL }},
+
+ { &hf_auth_flags_v,
+ { "Version Number", "sap.auth.flags.v",
+ FT_UINT8, BASE_DEC, VALS(&mcast_sap_auth_ver), MCAST_SAP_VERSION_MASK,
+ "Version", HFILL }},
+
+ { &hf_auth_flags_p,
+ { "Padding Bit", "sap.auth.flags.p",
+ FT_BOOLEAN, 8, TFS(&mcast_sap_auth_pad), MCAST_SAP_AUTH_BIT_P,
+ "Compression", HFILL }},
+
+ { &hf_auth_flags_t,
+ { "Authentication Type", "sap.auth.flags.t",
+ FT_UINT8, BASE_DEC, VALS(&mcast_sap_auth_type), MCAST_SAP_AUTH_TYPE_MASK,
+ "Auth type", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_sap,
+ &ett_sap_flags,
+ &ett_sap_auth,
+ &ett_sap_authf,
+ };
+
+ proto_sap = proto_register_protocol("Session Announcement Protocol", "SAP",
+ "sap");
+ proto_register_field_array(proto_sap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_sap(void)
+{
+ dissector_handle_t sap_handle;
+
+ sap_handle = create_dissector_handle(dissect_sap, proto_sap);
+ dissector_add("udp.port", UDP_PORT_SAP, sap_handle);
+
+ /*
+ * Get a handle for the SDP dissector.
+ */
+ sdp_handle = find_dissector("sdp");
+}
diff --git a/epan/dissectors/packet-sccp.c b/epan/dissectors/packet-sccp.c
new file mode 100644
index 0000000000..88dee1a850
--- /dev/null
+++ b/epan/dissectors/packet-sccp.c
@@ -0,0 +1,2366 @@
+/* packet-sccp.c
+ * Routines for Signalling Connection Control Part (SCCP) dissection
+ *
+ * It is hopefully compliant to:
+ * ANSI T1.112.3-1996
+ * ITU-T Q.713 7/1996
+ * YDN 038-1997 (Chinese ITU variant)
+ *
+ * Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-m2pa.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+#include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "packet-mtp3.h"
+#include "prefs.h"
+
+#define SCCP_SI 3
+
+#define MESSAGE_TYPE_OFFSET 0
+#define MESSAGE_TYPE_LENGTH 1
+#define POINTER_LENGTH 1
+#define POINTER_LENGTH_LONG 2
+
+#define MESSAGE_TYPE_CR 0x01
+#define MESSAGE_TYPE_CC 0x02
+#define MESSAGE_TYPE_CREF 0x03
+#define MESSAGE_TYPE_RLSD 0x04
+#define MESSAGE_TYPE_RLC 0x05
+#define MESSAGE_TYPE_DT1 0x06
+#define MESSAGE_TYPE_DT2 0x07
+#define MESSAGE_TYPE_AK 0x08
+#define MESSAGE_TYPE_UDT 0x09
+#define MESSAGE_TYPE_UDTS 0x0a
+#define MESSAGE_TYPE_ED 0x0b
+#define MESSAGE_TYPE_EA 0x0c
+#define MESSAGE_TYPE_RSR 0x0d
+#define MESSAGE_TYPE_RSC 0x0e
+#define MESSAGE_TYPE_ERR 0x0f
+#define MESSAGE_TYPE_IT 0x10
+#define MESSAGE_TYPE_XUDT 0x11
+#define MESSAGE_TYPE_XUDTS 0x12
+/* The below 2 are ITU only */
+#define MESSAGE_TYPE_LUDT 0x13
+#define MESSAGE_TYPE_LUDTS 0x14
+
+/* Same as below but with names typed out */
+static const value_string sccp_message_type_values[] = {
+ { MESSAGE_TYPE_CR, "Connection Request" },
+ { MESSAGE_TYPE_CC, "Connection Confirm" },
+ { MESSAGE_TYPE_CREF, "Connection Refused" },
+ { MESSAGE_TYPE_RLSD, "Released" },
+ { MESSAGE_TYPE_RLC, "Release Complete" },
+ { MESSAGE_TYPE_DT1, "Data Form 1" },
+ { MESSAGE_TYPE_DT2, "Data Form 2" },
+ { MESSAGE_TYPE_AK, "Data Acknowledgement" },
+ { MESSAGE_TYPE_UDT, "Unitdata" },
+ { MESSAGE_TYPE_UDTS, "Unitdata Service" },
+ { MESSAGE_TYPE_ED, "Expedited Data" },
+ { MESSAGE_TYPE_EA, "Expedited Data Acknowledgement" },
+ { MESSAGE_TYPE_RSR, "Reset Request" },
+ { MESSAGE_TYPE_RSC, "Reset Confirmation" },
+ { MESSAGE_TYPE_ERR, "Error" },
+ { MESSAGE_TYPE_IT, "Inactivity Timer" },
+ { MESSAGE_TYPE_XUDT, "Extended Unitdata" },
+ { MESSAGE_TYPE_XUDTS, "Extended Unitdata Service" },
+ { MESSAGE_TYPE_LUDT, "Long Unitdata (ITU)" },
+ { MESSAGE_TYPE_LUDTS, "Long Unitdata Service (ITU)" },
+ { 0, NULL } };
+
+/* Same as above but in acronym form (for the Info column) */
+static const value_string sccp_message_type_acro_values[] = {
+ { MESSAGE_TYPE_CR, "CR" },
+ { MESSAGE_TYPE_CC, "CC" },
+ { MESSAGE_TYPE_CREF, "CREF" },
+ { MESSAGE_TYPE_RLSD, "RLSD" },
+ { MESSAGE_TYPE_RLC, "RLC" },
+ { MESSAGE_TYPE_DT1, "DT1" },
+ { MESSAGE_TYPE_DT2, "DT2" },
+ { MESSAGE_TYPE_AK, "AK" },
+ { MESSAGE_TYPE_UDT, "UDT" },
+ { MESSAGE_TYPE_UDTS, "UDTS" },
+ { MESSAGE_TYPE_ED, "ED" },
+ { MESSAGE_TYPE_EA, "EA" },
+ { MESSAGE_TYPE_RSR, "RSR" },
+ { MESSAGE_TYPE_RSC, "RSC" },
+ { MESSAGE_TYPE_ERR, "ERR" },
+ { MESSAGE_TYPE_IT, "IT" },
+ { MESSAGE_TYPE_XUDT, "XUDT" },
+ { MESSAGE_TYPE_XUDTS, "XUDTS" },
+ { MESSAGE_TYPE_LUDT, "LUDT" },
+ { MESSAGE_TYPE_LUDTS, "LUDTS" },
+ { 0, NULL } };
+
+#define PARAMETER_LENGTH_LENGTH 1
+#define PARAMETER_LONG_DATA_LENGTH_LENGTH 2
+#define PARAMETER_TYPE_LENGTH 1
+
+#define PARAMETER_END_OF_OPTIONAL_PARAMETERS 0x00
+#define PARAMETER_DESTINATION_LOCAL_REFERENCE 0x01
+#define PARAMETER_SOURCE_LOCAL_REFERENCE 0x02
+#define PARAMETER_CALLED_PARTY_ADDRESS 0x03
+#define PARAMETER_CALLING_PARTY_ADDRESS 0x04
+#define PARAMETER_CLASS 0x05
+#define PARAMETER_SEGMENTING_REASSEMBLING 0x06
+#define PARAMETER_RECEIVE_SEQUENCE_NUMBER 0x07
+#define PARAMETER_SEQUENCING_SEGMENTING 0x08
+#define PARAMETER_CREDIT 0x09
+#define PARAMETER_RELEASE_CAUSE 0x0a
+#define PARAMETER_RETURN_CAUSE 0x0b
+#define PARAMETER_RESET_CAUSE 0x0c
+#define PARAMETER_ERROR_CAUSE 0x0d
+#define PARAMETER_REFUSAL_CAUSE 0x0e
+#define PARAMETER_DATA 0x0f
+#define PARAMETER_SEGMENTATION 0x10
+#define PARAMETER_HOP_COUNTER 0x11
+/* The below 2 are ITU only */
+#define PARAMETER_IMPORTANCE 0x12
+#define PARAMETER_LONG_DATA 0x13
+/* ISNI is ANSI only */
+#define PARAMETER_ISNI 0xfa
+
+static const value_string sccp_parameter_values[] = {
+ { PARAMETER_END_OF_OPTIONAL_PARAMETERS, "End of Optional Parameters" },
+ { PARAMETER_DESTINATION_LOCAL_REFERENCE, "Destination Local Reference" },
+ { PARAMETER_SOURCE_LOCAL_REFERENCE, "Source Local Reference" },
+ { PARAMETER_CALLED_PARTY_ADDRESS, "Called Party Address" },
+ { PARAMETER_CALLING_PARTY_ADDRESS, "Calling Party Address" },
+ { PARAMETER_CLASS, "Protocol Class" },
+ { PARAMETER_SEGMENTING_REASSEMBLING, "Segmenting/Reassembling" },
+ { PARAMETER_RECEIVE_SEQUENCE_NUMBER, "Receive Sequence Number" },
+ { PARAMETER_SEQUENCING_SEGMENTING, "Sequencing/Segmenting" },
+ { PARAMETER_CREDIT, "Credit" },
+ { PARAMETER_RELEASE_CAUSE, "Release Cause" },
+ { PARAMETER_RETURN_CAUSE, "Return Cause" },
+ { PARAMETER_RESET_CAUSE, "Reset Cause" },
+ { PARAMETER_ERROR_CAUSE, "Error Cause" },
+ { PARAMETER_REFUSAL_CAUSE, "Refusal Cause" },
+ { PARAMETER_DATA, "Data" },
+ { PARAMETER_SEGMENTATION, "Segmentation" },
+ { PARAMETER_HOP_COUNTER, "Hop Counter" },
+ { PARAMETER_IMPORTANCE, "Importance (ITU)" },
+ { PARAMETER_LONG_DATA, "Long Data (ITU)" },
+ { PARAMETER_ISNI, "Intermediate Signaling Network Identification (ANSI)" },
+ { 0, NULL } };
+
+
+#define END_OF_OPTIONAL_PARAMETERS_LENGTH 1
+#define DESTINATION_LOCAL_REFERENCE_LENGTH 3
+#define SOURCE_LOCAL_REFERENCE_LENGTH 3
+#define PROTOCOL_CLASS_LENGTH 1
+#define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
+#define CREDIT_LENGTH 1
+#define RELEASE_CAUSE_LENGTH 1
+#define RETURN_CAUSE_LENGTH 1
+#define RESET_CAUSE_LENGTH 1
+#define ERROR_CAUSE_LENGTH 1
+#define REFUSAL_CAUSE_LENGTH 1
+#define HOP_COUNTER_LENGTH 1
+#define IMPORTANCE_LENGTH 1
+
+
+/* Parts of the Called and Calling Address parameters */
+/* Address Indicator */
+#define ADDRESS_INDICATOR_LENGTH 1
+#define ITU_RESERVED_MASK 0x80
+#define ANSI_NATIONAL_MASK 0x80
+#define ROUTING_INDICATOR_MASK 0x40
+#define GTI_MASK 0x3C
+#define GTI_SHIFT 2
+#define ITU_SSN_INDICATOR_MASK 0x02
+#define ITU_PC_INDICATOR_MASK 0x01
+#define ANSI_PC_INDICATOR_MASK 0x02
+#define ANSI_SSN_INDICATOR_MASK 0x01
+
+static const value_string sccp_national_indicator_values[] = {
+ { 0x0, "Address coded to International standard" },
+ { 0x1, "Address coded to National standard" },
+ { 0, NULL } };
+
+static const value_string sccp_routing_indicator_values[] = {
+ { 0x0, "Route on GT" },
+ { 0x1, "Route on SSN" },
+ { 0, NULL } };
+
+#define AI_GTI_NO_GT 0x0
+#define ITU_AI_GTI_NAI 0x1
+#define AI_GTI_TT 0x2
+#define ITU_AI_GTI_TT_NP_ES 0x3
+#define ITU_AI_GTI_TT_NP_ES_NAI 0x4
+static const value_string sccp_itu_global_title_indicator_values[] = {
+ { AI_GTI_NO_GT, "No Global Title" },
+ { ITU_AI_GTI_NAI, "Nature of Address Indicator only" },
+ { AI_GTI_TT, "Translation Type only" },
+ { ITU_AI_GTI_TT_NP_ES, "Translation Type, Numbering Plan, and Encoding Scheme included" },
+ { ITU_AI_GTI_TT_NP_ES_NAI, "Translation Type, Numbering Plan, Encoding Scheme, and Nature of Address Indicator included" },
+ { 0, NULL } };
+
+/* #define AI_GTI_NO_GT 0x0 */
+#define ANSI_AI_GTI_TT_NP_ES 0x1
+/* #define AI_GTI_TT 0x2 */
+static const value_string sccp_ansi_global_title_indicator_values[] = {
+ { AI_GTI_NO_GT, "No Global Title" },
+ { ANSI_AI_GTI_TT_NP_ES, "Translation Type, Numbering Plan, and Encoding Scheme included" },
+ { AI_GTI_TT, "Translation Type only" },
+ { 0, NULL } };
+
+static const value_string sccp_ai_pci_values[] = {
+ { 0x1, "Point Code present" },
+ { 0x0, "Point Code not present" },
+ { 0, NULL } };
+
+static const value_string sccp_ai_ssni_values[] = {
+ { 0x1, "SSN present" },
+ { 0x0, "SSN not present" },
+ { 0, NULL } };
+
+#define ADDRESS_SSN_LENGTH 1
+#define INVALID_SSN 0xff
+static const value_string sccp_ssn_values[] = {
+ { 0x00, "SSN not known/not used" },
+ { 0x01, "SCCP management" },
+ { 0x02, "Reserved for ITU-T allocation" },
+ { 0x03, "ISDN User Part" },
+ { 0x04, "OMAP (Operation, Maintenance, and Administration Part)" },
+ { 0x05, "MAP (Mobile Application Part)" },
+ { 0x06, "HLR (Home Location Register)" },
+ { 0x07, "VLR (Visitor Location Register)" },
+ { 0x08, "MSC (Mobile Switching Center)" },
+ { 0x09, "EIC/EIR (Equipment Identifier Center/Equipment Identification Register)" },
+ { 0x0a, "AUC/AC (Authentication Center)" },
+ { 0x0b, "ISDN supplementary services (ITU only)" },
+ { 0x0c, "Reserved for international use (ITU only)" },
+ { 0x0d, "Broadband ISDN edge-to-edge applications (ITU only)" },
+ { 0x0e, "TC test responder (ITU only)" },
+ { 0x8e, "RANAP" },
+ { 0xfc, "IOS" },
+ { 0xfe, "BSSAP/BSAP" },
+ { 0, NULL } };
+
+
+/* * * * * * * * * * * * * * * * *
+ * Global Title: ITU GTI == 0001 *
+ * * * * * * * * * * * * * * * * */
+#define GT_NAI_MASK 0x7F
+#define GT_NAI_LENGTH 1
+static const value_string sccp_nai_values[] = {
+ { 0x00, "NAI unknown" },
+ { 0x01, "Subscriber Number" },
+ { 0x02, "Reserved for national use" },
+ { 0x03, "National significant number" },
+ { 0x04, "International number" },
+ { 0, NULL } };
+
+
+#define GT_OE_MASK 0x80
+#define GT_OE_EVEN 0
+#define GT_OE_ODD 1
+static const value_string sccp_oe_values[] = {
+ { GT_OE_EVEN, "Even number of address signals" },
+ { GT_OE_ODD, "Odd number of address signals" },
+ { 0, NULL } };
+
+#define GT_SIGNAL_LENGTH 1
+#define GT_ODD_SIGNAL_MASK 0x0f
+#define GT_EVEN_SIGNAL_MASK 0xf0
+#define GT_EVEN_SIGNAL_SHIFT 4
+#define GT_MAX_SIGNALS 32
+static const value_string sccp_address_signal_values[] = {
+ { 0, "0" },
+ { 1, "1" },
+ { 2, "2" },
+ { 3, "3" },
+ { 4, "4" },
+ { 5, "5" },
+ { 6, "6" },
+ { 7, "7" },
+ { 8, "8" },
+ { 9, "9" },
+ { 10, "(spare)" },
+ { 11, "11" },
+ { 12, "12" },
+ { 13, "(spare)" },
+ { 14, "(spare)" },
+ { 15, "ST" },
+ { 0, NULL } };
+
+
+/* * * * * * * * * * * * * * * * * * * * *
+ * Global Title: ITU and ANSI GTI == 0010 *
+ * * * * * * * * * * * * * * * * * * * * */
+#define GT_TT_LENGTH 1
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Global Title: ITU GTI == 0011, ANSI GTI == 0001 *
+ * * * * * * * * * * * * * * * * * * * * * * * * * */
+#define GT_NP_MASK 0xf0
+#define GT_NP_ES_LENGTH 1
+static const value_string sccp_np_values[] = {
+ { 0x0, "Unknown" },
+ { 0x1, "ISDN/telephony" },
+ { 0x2, "Generic (ITU)/Reserved (ANSI)" },
+ { 0x3, "Data" },
+ { 0x4, "Telex" },
+ { 0x5, "Maritime mobile" },
+ { 0x6, "Land mobile" },
+ { 0x7, "ISDN/mobile" },
+ { 0xe, "Private network or network-specific" },
+ { 0xf, "Reserved" },
+ { 0, NULL } };
+
+#define GT_ES_MASK 0x0f
+#define GT_ES_UNKNOWN 0x0
+#define GT_ES_BCD_ODD 0x1
+#define GT_ES_BCD_EVEN 0x2
+#define GT_ES_NATIONAL 0x3
+#define GT_ES_RESERVED 0xf
+static const value_string sccp_es_values[] = {
+ { GT_ES_UNKNOWN, "Unknown" },
+ { GT_ES_BCD_ODD, "BCD, odd number of digits" },
+ { GT_ES_BCD_EVEN, "BCD, even number of digits" },
+ { GT_ES_NATIONAL, "National specific" },
+ { GT_ES_RESERVED, "Reserved (ITU)/Spare (ANSI)" },
+ { 0, NULL } };
+
+/* Address signals above */
+
+
+/* * * * * * * * * * * * * * * * *
+ * Global Title: ITU GTI == 0100 *
+ * * * * * * * * * * * * * * * * */
+/* NP above */
+/* ES above */
+/* NAI above */
+/* Address signals above */
+
+
+#define CLASS_CLASS_MASK 0xf
+#define CLASS_SPARE_HANDLING_MASK 0xf0
+static const value_string sccp_class_handling_values [] = {
+ { 0x0, "No special options" },
+ { 0x8, "Return message on error" },
+ { 0, NULL } };
+
+
+#define SEGMENTING_REASSEMBLING_LENGTH 1
+#define SEGMENTING_REASSEMBLING_MASK 0x01
+#define NO_MORE_DATA 0
+#define MORE_DATA 1
+/* This is also used by sequencing-segmenting parameter */
+static const value_string sccp_segmenting_reassembling_values [] = {
+ { NO_MORE_DATA, "No more data" },
+ { MORE_DATA, "More data" },
+ { 0, NULL } };
+
+
+#define RECEIVE_SEQUENCE_NUMBER_LENGTH 1
+#define RSN_MASK 0xfe
+
+#define SEQUENCING_SEGMENTING_LENGTH 2
+#define SEQUENCING_SEGMENTING_SSN_LENGTH 1
+#define SEQUENCING_SEGMENTING_RSN_LENGTH 1
+#define SEND_SEQUENCE_NUMBER_MASK 0xfe
+#define RECEIVE_SEQUENCE_NUMBER_MASK 0xfe
+#define SEQUENCING_SEGMENTING_MORE_MASK 0x01
+
+
+#define CREDIT_LENGTH 1
+
+#define RELEASE_CAUSE_LENGTH 1
+static const value_string sccp_release_cause_values [] = {
+ { 0x00, "End user originated" },
+ { 0x01, "End user congestion" },
+ { 0x02, "End user failure" },
+ { 0x03, "SCCP user originated" },
+ { 0x04, "Remote procedure error" },
+ { 0x05, "Inconsistent connection data" },
+ { 0x06, "Access failure" },
+ { 0x07, "Access congestion" },
+ { 0x08, "Subsystem failure" },
+ { 0x09, "Subsystem congestion" },
+ { 0x0a, "MTP failure" },
+ { 0x0b, "Netowrk congestion" },
+ { 0x0c, "Expiration of reset timer" },
+ { 0x0d, "Expiration of receive inactivity timer" },
+ { 0x0e, "Reserved" },
+ { 0x0f, "Unqualified" },
+ { 0x10, "SCCP failure (ITU only)" },
+ { 0, NULL } };
+
+
+#define RETURN_CAUSE_LENGTH 1
+static const value_string sccp_return_cause_values [] = {
+ { 0x00, "No translation for an address of such nature" },
+ { 0x01, "No translation for this specific address" },
+ { 0x02, "Subsystem congestion" },
+ { 0x03, "Subsystem failure" },
+ { 0x04, "Unequipped failure" },
+ { 0x05, "MTP failure" },
+ { 0x06, "Network congestion" },
+ { 0x07, "Unqualified" },
+ { 0x08, "Error in message transport" },
+ { 0x09, "Error in local processing" },
+ { 0x0a, "Destination cannot perform reassembly" },
+ { 0x0b, "SCCP failure" },
+ { 0x0c, "Hop counter violation" },
+ { 0x0d, "Segmentation not supported (ITU only)" },
+ { 0x0e, "Segmentation failure (ITU only)" },
+ { 0xf9, "Invalid ISNI routing request (ANSI only)"},
+ { 0xfa, "Unauthorized message (ANSI only)" },
+ { 0xfb, "Message incompatibility (ANSI only)" },
+ { 0xfc, "Cannot perform ISNI constrained routing (ANSI only)" },
+ { 0xfd, "Unable to perform ISNI identification (ANSI only)" },
+ { 0, NULL } };
+
+
+#define RESET_CAUSE_LENGTH 1
+static const value_string sccp_reset_cause_values [] = {
+ { 0x00, "End user originated" },
+ { 0x01, "SCCP user originated" },
+ { 0x02, "Message out of order - incorrect send sequence number" },
+ { 0x03, "Message out of order - incorrect receive sequence number" },
+ { 0x04, "Remote procedure error - message out of window" },
+ { 0x05, "Remote procedure error - incorrect send sequence number after (re)initialization" },
+ { 0x06, "Remote procedure error - general" },
+ { 0x07, "Remote end user operational" },
+ { 0x08, "Network operational" },
+ { 0x09, "Access operational" },
+ { 0x0a, "Network congestion" },
+ { 0x0b, "Reserved (ITU)/Not obtainable (ANSI)" },
+ { 0x0c, "Unqualified" },
+ { 0, NULL } };
+
+
+#define ERROR_CAUSE_LENGTH 1
+static const value_string sccp_error_cause_values [] = {
+ { 0x00, "Local Reference Number (LRN) mismatch - unassigned destination LRN" },
+ { 0x01, "Local Reference Number (LRN) mismatch - inconsistent source LRN" },
+ { 0x02, "Point code mismatch" },
+ { 0x03, "Service class mismatch" },
+ { 0x04, "Unqualified" },
+ { 0, NULL } };
+
+
+#define REFUSAL_CAUSE_LENGTH 1
+static const value_string sccp_refusal_cause_values [] = {
+ { 0x00, "End user originated" },
+ { 0x01, "End user congestion" },
+ { 0x02, "End user failure" },
+ { 0x03, "SCCP user originated" },
+ { 0x04, "Destination address unknown" },
+ { 0x05, "Destination inaccessible" },
+ { 0x06, "Network resource - QOS not available/non-transient" },
+ { 0x07, "Network resource - QOS not available/transient" },
+ { 0x08, "Access failure" },
+ { 0x09, "Access congestion" },
+ { 0x0a, "Subsystem failure" },
+ { 0x0b, "Subsystem congestion" },
+ { 0x0c, "Expiration of connection establishment timer" },
+ { 0x0d, "Incompatible user data" },
+ { 0x0e, "Reserved" },
+ { 0x0f, "Unqualified" },
+ { 0x10, "Hop counter violation" },
+ { 0x11, "SCCP failure (ITU only)" },
+ { 0x12, "No translation for an address of such nature" },
+ { 0x13, "Unequipped user" },
+ { 0, NULL } };
+
+
+#define SEGMENTATION_LENGTH 4
+#define SEGMENTATION_FIRST_SEGMENT_MASK 0x80
+#define SEGMENTATION_CLASS_MASK 0x40
+#define SEGMENTATION_SPARE_MASK 0x30
+#define SEGMENTATION_REMAINING_MASK 0x0f
+static const value_string sccp_segmentation_first_segment_values [] = {
+ { 1, "First segment" },
+ { 0, "Not first segment" },
+ { 0, NULL } };
+static const value_string sccp_segmentation_class_values [] = {
+ { 0, "Class 0 selected" },
+ { 1, "Class 1 selected" },
+ { 0, NULL } };
+
+
+#define HOP_COUNTER_LENGTH 1
+
+#define IMPORTANCE_LENGTH 1
+#define IMPORTANCE_IMPORTANCE_MASK 0x7
+
+
+#define ANSI_ISNI_ROUTING_CONTROL_LENGTH 1
+#define ANSI_ISNI_MI_MASK 0x01
+#define ANSI_ISNI_IRI_MASK 0x06
+#define ANSI_ISNI_RES_MASK 0x08
+#define ANSI_ISNI_TI_MASK 0x10
+#define ANSI_ISNI_TI_SHIFT 4
+#define ANSI_ISNI_COUNTER_MASK 0xe0
+
+#define ANSI_ISNI_NETSPEC_MASK 0x03
+
+static const value_string sccp_isni_mark_for_id_values [] = {
+ { 0x0, "Do not identify networks" },
+ { 0x1, "Identify networks" },
+ { 0, NULL } };
+
+static const value_string sccp_isni_iri_values [] = {
+ { 0x0, "Neither constrained nor suggested ISNI routing" },
+ { 0x1, "Constrained ISNI routing" },
+ { 0x2, "Reserved for suggested ISNI routing" },
+ { 0x3, "Spare" },
+ { 0, NULL } };
+
+#define ANSI_ISNI_TYPE_0 0x0
+#define ANSI_ISNI_TYPE_1 0x1
+static const value_string sccp_isni_ti_values [] = {
+ { ANSI_ISNI_TYPE_0, "Type zero ISNI parameter format" },
+ { ANSI_ISNI_TYPE_1, "Type one ISNI parameter format" },
+ { 0, NULL } };
+
+
+/* Initialize the protocol and registered fields */
+static int proto_sccp = -1;
+static int hf_sccp_message_type = -1;
+static int hf_sccp_variable_pointer1 = -1;
+static int hf_sccp_variable_pointer2 = -1;
+static int hf_sccp_variable_pointer3 = -1;
+static int hf_sccp_optional_pointer = -1;
+static int hf_sccp_ssn = -1;
+static int hf_sccp_gt_digits = -1;
+
+/* Called Party address */
+static int hf_sccp_called_national_indicator = -1;
+static int hf_sccp_called_routing_indicator = -1;
+static int hf_sccp_called_itu_global_title_indicator = -1;
+static int hf_sccp_called_ansi_global_title_indicator = -1;
+static int hf_sccp_called_itu_ssn_indicator = -1;
+static int hf_sccp_called_itu_point_code_indicator = -1;
+static int hf_sccp_called_ansi_ssn_indicator = -1;
+static int hf_sccp_called_ansi_point_code_indicator = -1;
+static int hf_sccp_called_ssn = -1;
+static int hf_sccp_called_pc_member = -1;
+static int hf_sccp_called_pc_cluster = -1;
+static int hf_sccp_called_pc_network = -1;
+static int hf_sccp_called_ansi_pc = -1;
+static int hf_sccp_called_chinese_pc = -1;
+static int hf_sccp_called_itu_pc = -1;
+static int hf_sccp_called_gt_nai = -1;
+static int hf_sccp_called_gt_oe = -1;
+static int hf_sccp_called_gt_tt = -1;
+static int hf_sccp_called_gt_np = -1;
+static int hf_sccp_called_gt_es = -1;
+static int hf_sccp_called_gt_digits = -1;
+
+/* Calling party address */
+static int hf_sccp_calling_national_indicator = -1;
+static int hf_sccp_calling_routing_indicator = -1;
+static int hf_sccp_calling_itu_global_title_indicator = -1;
+static int hf_sccp_calling_ansi_global_title_indicator = -1;
+static int hf_sccp_calling_itu_ssn_indicator = -1;
+static int hf_sccp_calling_itu_point_code_indicator = -1;
+static int hf_sccp_calling_ansi_ssn_indicator = -1;
+static int hf_sccp_calling_ansi_point_code_indicator = -1;
+static int hf_sccp_calling_ssn = -1;
+static int hf_sccp_calling_pc_member = -1;
+static int hf_sccp_calling_pc_cluster = -1;
+static int hf_sccp_calling_pc_network = -1;
+static int hf_sccp_calling_ansi_pc = -1;
+static int hf_sccp_calling_chinese_pc = -1;
+static int hf_sccp_calling_itu_pc = -1;
+static int hf_sccp_calling_gt_nai = -1;
+static int hf_sccp_calling_gt_oe = -1;
+static int hf_sccp_calling_gt_tt = -1;
+static int hf_sccp_calling_gt_np = -1;
+static int hf_sccp_calling_gt_es = -1;
+static int hf_sccp_calling_gt_digits = -1;
+
+/* Other parameter values */
+static int hf_sccp_dlr = -1;
+static int hf_sccp_slr = -1;
+static int hf_sccp_class = -1;
+static int hf_sccp_handling = -1;
+static int hf_sccp_more = -1;
+static int hf_sccp_rsn = -1;
+static int hf_sccp_sequencing_segmenting_ssn = -1;
+static int hf_sccp_sequencing_segmenting_rsn = -1;
+static int hf_sccp_sequencing_segmenting_more = -1;
+static int hf_sccp_credit = -1;
+static int hf_sccp_release_cause = -1;
+static int hf_sccp_return_cause = -1;
+static int hf_sccp_reset_cause = -1;
+static int hf_sccp_error_cause = -1;
+static int hf_sccp_refusal_cause = -1;
+static int hf_sccp_segmentation_first = -1;
+static int hf_sccp_segmentation_class = -1;
+static int hf_sccp_segmentation_remaining = -1;
+static int hf_sccp_segmentation_slr = -1;
+static int hf_sccp_hop_counter = -1;
+static int hf_sccp_importance = -1;
+static int hf_sccp_ansi_isni_mi = -1;
+static int hf_sccp_ansi_isni_iri = -1;
+static int hf_sccp_ansi_isni_ti = -1;
+static int hf_sccp_ansi_isni_netspec = -1;
+static int hf_sccp_ansi_isni_counter = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_sccp = -1;
+static gint ett_sccp_called = -1;
+static gint ett_sccp_called_ai = -1;
+static gint ett_sccp_called_pc = -1;
+static gint ett_sccp_called_gt = -1;
+static gint ett_sccp_calling = -1;
+static gint ett_sccp_calling_ai = -1;
+static gint ett_sccp_calling_pc = -1;
+static gint ett_sccp_calling_gt = -1;
+static gint ett_sccp_sequencing_segmenting = -1;
+static gint ett_sccp_segmentation = -1;
+static gint ett_sccp_ansi_isni_routing_control = -1;
+
+/*
+ * Here are the global variables associated with
+ * the various user definable characteristics of the dissection
+ */
+static guint32 sccp_source_pc_global = 0;
+static gboolean sccp_show_length = FALSE;
+
+static module_t *sccp_module;
+static heur_dissector_list_t heur_subdissector_list;
+
+/* Keep track of SSN value of current message so if/when we get to the data
+ * parameter, we can call appropriate sub-dissector. TODO: can this info
+ * be stored elsewhere?
+ */
+static guint8 called_ssn = INVALID_SSN;
+static guint8 calling_ssn = INVALID_SSN;
+
+static dissector_handle_t data_handle;
+static dissector_table_t sccp_ssn_dissector_table;
+
+static void
+dissect_sccp_unknown_message(tvbuff_t *message_tvb, proto_tree *sccp_tree)
+{
+ guint32 message_length;
+
+ message_length = tvb_length(message_tvb);
+
+ proto_tree_add_text(sccp_tree, message_tvb, 0, message_length,
+ "Unknown message (%u byte%s)",
+ message_length, plurality(message_length, "", "s"));
+}
+
+static void
+dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint length)
+{
+ proto_tree_add_text(tree, tvb, 0, length, "Unknown parameter 0x%x (%u byte%s)",
+ type, length, plurality(length, "", "s"));
+}
+
+static void
+dissect_sccp_dlr_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint32 reference;
+
+ reference = tvb_get_letoh24(tvb, 0);
+ proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, reference);
+}
+
+static void
+dissect_sccp_slr_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint32 reference;
+
+ reference = tvb_get_letoh24(tvb, 0);
+ proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, reference);
+}
+
+static void
+dissect_sccp_gt_address_information(tvbuff_t *tvb, proto_tree *tree,
+ guint length, gboolean even_length,
+ gboolean called)
+{
+ guint offset = 0;
+ guint8 odd_signal, even_signal = 0x0f;
+ char gt_digits[GT_MAX_SIGNALS] = { 0 };
+
+ while(offset < length)
+ {
+ odd_signal = tvb_get_guint8(tvb, offset) & GT_ODD_SIGNAL_MASK;
+ even_signal = tvb_get_guint8(tvb, offset) & GT_EVEN_SIGNAL_MASK;
+ even_signal >>= GT_EVEN_SIGNAL_SHIFT;
+
+ strcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values,
+ "Unknown"));
+
+ /* If the last signal is NOT filler */
+ if (offset != (length - 1) || even_length == TRUE)
+ strcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values,
+ "Unknown"));
+
+ offset += GT_SIGNAL_LENGTH;
+ }
+
+ proto_tree_add_string_format(tree, called ? hf_sccp_called_gt_digits
+ : hf_sccp_calling_gt_digits,
+ tvb, 0, length,
+ gt_digits,
+ "Address information (digits): %s", gt_digits);
+ proto_tree_add_string_hidden(tree, called ? hf_sccp_gt_digits
+ : hf_sccp_gt_digits,
+ tvb, 0, length,
+ gt_digits);
+}
+
+static void
+dissect_sccp_global_title(tvbuff_t *tvb, proto_tree *tree, guint length,
+ guint8 gti, gboolean called)
+{
+ proto_item *gt_item = 0;
+ proto_tree *gt_tree = 0;
+ tvbuff_t *signals_tvb;
+ guint offset = 0;
+ guint8 odd_even, nai, tt, np, es;
+ gboolean even = TRUE;
+
+ /* Shift GTI to where we can work with it */
+ gti >>= GTI_SHIFT;
+
+ gt_item = proto_tree_add_text(tree, tvb, offset, length,
+ "Global Title 0x%x (%u byte%s)",
+ gti, length, plurality(length,"", "s"));
+ gt_tree = proto_item_add_subtree(gt_item, called ? ett_sccp_called_gt
+ : ett_sccp_calling_gt);
+
+ /* Decode Transation Type (if present) */
+ switch (gti) {
+ case AI_GTI_TT:
+
+ /* Protocol doesn't tell us, so we ASSUME even... */
+ even = TRUE;
+ /* Fall through */
+ case ITU_AI_GTI_TT_NP_ES:
+ case ITU_AI_GTI_TT_NP_ES_NAI:
+ case ANSI_AI_GTI_TT_NP_ES:
+
+ tt = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_tt
+ : hf_sccp_calling_gt_tt,
+ tvb, offset, GT_TT_LENGTH, tt);
+ offset += GT_TT_LENGTH;
+ }
+
+ /* Decode Numbering Plan and Encoding Scheme (if present) */
+ switch (gti) {
+ case ITU_AI_GTI_TT_NP_ES:
+ case ITU_AI_GTI_TT_NP_ES_NAI:
+ case ANSI_AI_GTI_TT_NP_ES:
+
+ np = tvb_get_guint8(tvb, offset) & GT_NP_MASK;
+ proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_np
+ : hf_sccp_calling_gt_np,
+ tvb, offset, GT_NP_ES_LENGTH, np);
+
+ es = tvb_get_guint8(tvb, offset) & GT_ES_MASK;
+ proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_es
+ : hf_sccp_calling_gt_es,
+ tvb, offset, GT_NP_ES_LENGTH, es);
+
+ even = (es == GT_ES_BCD_EVEN) ? TRUE : FALSE;
+
+ offset += GT_NP_ES_LENGTH;
+ }
+
+ /* Decode Odd/Even Indicator (if present) */
+ if (gti == ITU_AI_GTI_NAI) {
+ odd_even = tvb_get_guint8(tvb, offset) & GT_OE_MASK;
+ proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_oe
+ : hf_sccp_calling_gt_oe,
+ tvb, offset, GT_NAI_LENGTH, odd_even);
+ even = (odd_even == GT_OE_EVEN) ? TRUE : FALSE;
+
+ /* offset doesn't change */
+ }
+
+ /* Decode Nature of Address Indicator (if present) */
+ switch (gti) {
+ case ITU_AI_GTI_NAI:
+ case ITU_AI_GTI_TT_NP_ES_NAI:
+ nai = tvb_get_guint8(tvb, offset) & GT_NAI_MASK;
+ proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_nai
+ : hf_sccp_calling_gt_nai,
+ tvb, offset, GT_NAI_LENGTH, nai);
+
+ offset += GT_NAI_LENGTH;
+ }
+
+ /* Decode address signal(s) */
+ if (length < offset)
+ return;
+ signals_tvb = tvb_new_subset(tvb, offset, (length - offset),
+ (length - offset));
+ dissect_sccp_gt_address_information(signals_tvb, gt_tree, (length - offset),
+ even,
+ called);
+}
+
+static int
+dissect_sccp_3byte_pc(tvbuff_t *tvb, proto_tree *call_tree, guint offset,
+ gboolean called)
+{
+ guint32 dpc;
+ proto_item *call_pc_item = 0;
+ proto_tree *call_pc_tree = 0;
+ char pc[ANSI_PC_STRING_LENGTH];
+ int *hf_pc;
+
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ if (called)
+ hf_pc = &hf_sccp_called_ansi_pc;
+ else
+ hf_pc = &hf_sccp_calling_ansi_pc;
+ } else /* CHINESE_ITU_STANDARD */ {
+ if (called)
+ hf_pc = &hf_sccp_called_chinese_pc;
+ else
+ hf_pc = &hf_sccp_calling_chinese_pc;
+ }
+
+ /* create the DPC tree; modified from that in packet-mtp3.c */
+ dpc = tvb_get_ntoh24(tvb, offset);
+ snprintf(pc, sizeof(pc), "%d-%d-%d", (dpc & ANSI_NETWORK_MASK),
+ ((dpc & ANSI_CLUSTER_MASK) >> 8),
+ ((dpc & ANSI_MEMBER_MASK) >> 16));
+
+ call_pc_item = proto_tree_add_string_format(call_tree, *hf_pc,
+ tvb, offset, ANSI_PC_LENGTH,
+ pc, "PC (%s)", pc);
+
+ call_pc_tree = proto_item_add_subtree(call_pc_item,
+ called ? ett_sccp_called_pc
+ : ett_sccp_calling_pc);
+
+ proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_member
+ : hf_sccp_calling_pc_member,
+ tvb, offset, ANSI_NCM_LENGTH, dpc);
+ offset += ANSI_NCM_LENGTH;
+ proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_cluster
+ : hf_sccp_calling_pc_cluster,
+ tvb, offset, ANSI_NCM_LENGTH, dpc);
+ offset += ANSI_NCM_LENGTH;
+ proto_tree_add_uint(call_pc_tree, called ? hf_sccp_called_pc_network
+ : hf_sccp_calling_pc_network,
+ tvb, offset, ANSI_NCM_LENGTH, dpc);
+ offset += ANSI_NCM_LENGTH;
+
+ return(offset);
+}
+
+/* FUNCTION dissect_sccp_called_calling_param():
+ * Dissect the Calling or Called Party Address parameters.
+ *
+ * The boolean 'called' describes whether this function is decoding a
+ * called (TRUE) or calling (FALSE) party address. There is simply too
+ * much code in this function to have 2 copies of it (one for called, one
+ * for calling).
+ *
+ * NOTE: this function is called even when (!tree) so that we can get
+ * the SSN and subsequently call subdissectors (if and when there's a data
+ * parameter). Realistically we should put if (!tree)'s around a lot of the
+ * code, but I think that would make it unreadable--and the expense of not
+ * doing so does not appear to be very high.
+ */
+static void
+dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree,
+ guint length, gboolean called)
+{
+ proto_item *call_item = 0, *call_ai_item = 0;
+ proto_tree *call_tree = 0, *call_ai_tree = 0;
+ guint offset;
+ guint8 national = -1, routing_ind, gti, pci, ssni, ssn;
+ guint32 dpc;
+ tvbuff_t *gt_tvb;
+
+ call_item = proto_tree_add_text(tree, tvb, 0, length,
+ "%s Party address (%u byte%s)",
+ called ? "Called" : "Calling", length,
+ plurality(length, "", "s"));
+ call_tree = proto_item_add_subtree(call_item, called ? ett_sccp_called
+ : ett_sccp_calling);
+
+ call_ai_item = proto_tree_add_text(call_tree, tvb, 0,
+ ADDRESS_INDICATOR_LENGTH,
+ "Address Indicator");
+ call_ai_tree = proto_item_add_subtree(call_ai_item, called ? ett_sccp_called_ai
+ : ett_sccp_calling_ai);
+
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ national = tvb_get_guint8(tvb, 0) & ANSI_NATIONAL_MASK;
+ proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_national_indicator
+ : hf_sccp_calling_national_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, national);
+ }
+
+ routing_ind = tvb_get_guint8(tvb, 0) & ROUTING_INDICATOR_MASK;
+ proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator
+ : hf_sccp_calling_routing_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind);
+
+ gti = tvb_get_guint8(tvb, 0) & GTI_MASK;
+
+ if (mtp3_standard == ITU_STANDARD ||
+ mtp3_standard == CHINESE_ITU_STANDARD ||
+ national == 0) {
+
+ proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_global_title_indicator
+ : hf_sccp_called_itu_global_title_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
+
+ ssni = tvb_get_guint8(tvb, 0) & ITU_SSN_INDICATOR_MASK;
+ proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_ssn_indicator
+ : hf_sccp_calling_itu_ssn_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+
+ pci = tvb_get_guint8(tvb, 0) & ITU_PC_INDICATOR_MASK;
+ proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator
+ : hf_sccp_calling_itu_point_code_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
+
+ offset = ADDRESS_INDICATOR_LENGTH;
+
+ /* Dissect PC (if present) */
+ if (pci) {
+ if (mtp3_standard == ITU_STANDARD)
+ {
+
+ dpc = tvb_get_letohs(tvb, offset) & ITU_PC_MASK;
+ proto_tree_add_uint(call_tree, called ? hf_sccp_called_itu_pc
+ : hf_sccp_calling_itu_pc,
+ tvb, offset, ITU_PC_LENGTH, dpc);
+ offset += ITU_PC_LENGTH;
+
+ } else /* CHINESE_ITU_STANDARD */ {
+
+ offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
+
+ }
+ }
+
+ /* Dissect SSN (if present) */
+ if (ssni) {
+ ssn = tvb_get_guint8(tvb, offset);
+ if (called) {
+ called_ssn = ssn;
+ }
+ else {
+ calling_ssn = ssn;
+ }
+
+ proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
+ : hf_sccp_calling_ssn,
+ tvb, offset, ADDRESS_SSN_LENGTH, ssn);
+ proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
+ ADDRESS_SSN_LENGTH, ssn);
+ offset += ADDRESS_SSN_LENGTH;
+ }
+
+ if (!tree)
+ return; /* got SSN, that's all we need here... */
+
+ /* Dissect GT (if present) */
+ if (gti != AI_GTI_NO_GT) {
+ if (length < offset)
+ return;
+ gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
+ (length - offset));
+ dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
+ called);
+ }
+
+ } else if (mtp3_standard == ANSI_STANDARD) {
+
+ proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_global_title_indicator
+ : hf_sccp_calling_ansi_global_title_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, gti);
+
+ pci = tvb_get_guint8(tvb, 0) & ANSI_PC_INDICATOR_MASK;
+ proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_point_code_indicator
+ : hf_sccp_calling_ansi_point_code_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, pci);
+
+ ssni = tvb_get_guint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK;
+ proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator
+ : hf_sccp_calling_ansi_ssn_indicator,
+ tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni);
+
+ offset = ADDRESS_INDICATOR_LENGTH;
+
+ /* Dissect SSN (if present) */
+ if (ssni) {
+ ssn = tvb_get_guint8(tvb, offset);
+ if (called) {
+ called_ssn = ssn;
+ }
+ else {
+ calling_ssn = ssn;
+ }
+
+ proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn
+ : hf_sccp_calling_ssn,
+ tvb, offset, ADDRESS_SSN_LENGTH, ssn);
+ proto_tree_add_uint_hidden(call_tree, hf_sccp_ssn, tvb, offset,
+ ADDRESS_SSN_LENGTH, ssn);
+ offset += ADDRESS_SSN_LENGTH;
+ }
+
+ if (!tree)
+ return; /* got SSN, that's all we need here... */
+
+ /* Dissect PC (if present) */
+ if (pci) {
+ offset = dissect_sccp_3byte_pc(tvb, call_tree, offset, called);
+ }
+
+ /* Dissect GT (if present) */
+ if (gti != AI_GTI_NO_GT) {
+ if (length < offset)
+ return;
+ gt_tvb = tvb_new_subset(tvb, offset, (length - offset),
+ (length - offset));
+ dissect_sccp_global_title(gt_tvb, call_tree, (length - offset), gti,
+ called);
+ }
+
+ }
+
+}
+
+static void
+dissect_sccp_called_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ dissect_sccp_called_calling_param(tvb, tree, length, TRUE);
+}
+
+static void
+dissect_sccp_calling_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ dissect_sccp_called_calling_param(tvb, tree, length, FALSE);
+}
+
+static void
+dissect_sccp_class_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 class, handling;
+
+ class = tvb_get_guint8(tvb, 0) & CLASS_CLASS_MASK;
+ handling = tvb_get_guint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK;
+
+ proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, class);
+
+ if (class == 0 || class == 1)
+ proto_tree_add_uint(tree, hf_sccp_handling, tvb, 0, length, handling);
+}
+
+static void
+dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 more;
+
+ more = tvb_get_guint8(tvb, 0) & SEGMENTING_REASSEMBLING_MASK;
+ proto_tree_add_uint(tree, hf_sccp_more, tvb, 0, length, more);
+}
+
+static void
+dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 rsn;
+
+ rsn = tvb_get_guint8(tvb, 0) >> 1;
+ proto_tree_add_uint(tree, hf_sccp_rsn, tvb, 0, length, rsn);
+}
+
+static void
+dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 rsn, ssn, more;
+ proto_item *param_item;
+ proto_tree *param_tree;
+
+ ssn = tvb_get_guint8(tvb, 0) >> 1;
+ rsn = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) >> 1;
+ more = tvb_get_guint8(tvb, SEQUENCING_SEGMENTING_SSN_LENGTH) & SEQUENCING_SEGMENTING_MORE_MASK;
+
+ param_item = proto_tree_add_text(tree, tvb, 0, length,
+ val_to_str(PARAMETER_SEQUENCING_SEGMENTING,
+ sccp_parameter_values, "Unknown"));
+ param_tree = proto_item_add_subtree(param_item,
+ ett_sccp_sequencing_segmenting);
+
+ proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_ssn, tvb, 0,
+ SEQUENCING_SEGMENTING_SSN_LENGTH, ssn);
+ proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_rsn, tvb,
+ SEQUENCING_SEGMENTING_SSN_LENGTH,
+ SEQUENCING_SEGMENTING_RSN_LENGTH, rsn);
+ proto_tree_add_uint(param_tree, hf_sccp_sequencing_segmenting_more, tvb,
+ SEQUENCING_SEGMENTING_SSN_LENGTH,
+ SEQUENCING_SEGMENTING_RSN_LENGTH, more);
+}
+
+static void
+dissect_sccp_credit_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 credit;
+
+ credit = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(tree, hf_sccp_credit, tvb, 0, length, credit);
+}
+
+static void
+dissect_sccp_release_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 cause;
+
+ cause = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(tree, hf_sccp_release_cause, tvb, 0, length, cause);
+}
+
+static void
+dissect_sccp_return_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 cause;
+
+ cause = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(tree, hf_sccp_return_cause, tvb, 0, length, cause);
+}
+
+static void
+dissect_sccp_reset_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 cause;
+
+ cause = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(tree, hf_sccp_reset_cause, tvb, 0, length, cause);
+}
+
+static void
+dissect_sccp_error_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 cause;
+
+ cause = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(tree, hf_sccp_error_cause, tvb, 0, length, cause);
+}
+
+static void
+dissect_sccp_refusal_cause_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 cause;
+
+ cause = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(tree, hf_sccp_refusal_cause, tvb, 0, length, cause);
+}
+
+/* This function is used for both data and long data (ITU only) parameters */
+static void
+dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ /* Try subdissectors (if we found a valid SSN on the current message) */
+ if ((called_ssn != INVALID_SSN &&
+ dissector_try_port(sccp_ssn_dissector_table, called_ssn, tvb, pinfo,
+ tree)) ||
+ (calling_ssn != INVALID_SSN &&
+ dissector_try_port(sccp_ssn_dissector_table, calling_ssn, tvb, pinfo,
+ tree)))
+ return;
+
+ /* try heuristic subdissector list to see if there are any takers */
+ if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree))
+ {
+ return;
+ }
+
+ /* No sub-dissection occured, treat it as raw data */
+ call_dissector(data_handle, tvb, pinfo, tree);
+}
+
+static void
+dissect_sccp_segmentation_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 first, class, remaining;
+ guint32 slr;
+ proto_item *param_item;
+ proto_tree *param_tree;
+
+ first = tvb_get_guint8(tvb, 0) & SEGMENTATION_FIRST_SEGMENT_MASK;
+ class = tvb_get_guint8(tvb, 0) & SEGMENTATION_CLASS_MASK;
+ remaining = tvb_get_guint8(tvb, 0) & SEGMENTATION_REMAINING_MASK;
+
+ slr = tvb_get_letoh24(tvb, 1);
+
+ param_item = proto_tree_add_text(tree, tvb, 0, length,
+ val_to_str(PARAMETER_SEGMENTATION,
+ sccp_parameter_values, "Unknown"));
+ param_tree = proto_item_add_subtree(param_item, ett_sccp_segmentation);
+
+ proto_tree_add_uint(param_tree, hf_sccp_segmentation_first, tvb, 0, length,
+ first);
+ proto_tree_add_uint(param_tree, hf_sccp_segmentation_class, tvb, 0, length,
+ class);
+ proto_tree_add_uint(param_tree, hf_sccp_segmentation_remaining, tvb, 0,
+ length, remaining);
+ proto_tree_add_uint(param_tree, hf_sccp_segmentation_slr, tvb, 1, length,
+ slr);
+}
+
+static void
+dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 hops;
+
+ hops = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(tree, hf_sccp_hop_counter, tvb, 0, length, hops);
+}
+
+static void
+dissect_sccp_importance_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 importance;
+
+ importance = tvb_get_guint8(tvb, 0) & IMPORTANCE_IMPORTANCE_MASK;
+ proto_tree_add_uint(tree, hf_sccp_importance, tvb, 0, length, importance);
+}
+
+static void
+dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, guint length)
+{
+ guint8 mi, iri, ti, network, netspec;
+ guint offset = 0;
+ proto_item *param_item;
+ proto_tree *param_tree;
+
+ /* Create a subtree for ISNI Routing Control */
+ param_item = proto_tree_add_text(tree, tvb, offset, ANSI_ISNI_ROUTING_CONTROL_LENGTH,
+ "ISNI Routing Control");
+ param_tree = proto_item_add_subtree(param_item,
+ ett_sccp_ansi_isni_routing_control);
+
+ mi = tvb_get_guint8(tvb, offset) & ANSI_ISNI_MI_MASK;
+ proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_mi, tvb, offset,
+ ANSI_ISNI_ROUTING_CONTROL_LENGTH, mi);
+
+ iri = tvb_get_guint8(tvb, offset) & ANSI_ISNI_IRI_MASK;
+ proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_iri, tvb, offset,
+ ANSI_ISNI_ROUTING_CONTROL_LENGTH, iri);
+
+ ti = tvb_get_guint8(tvb, offset) & ANSI_ISNI_TI_MASK;
+ proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_ti, tvb, offset,
+ ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
+
+ offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
+
+ if ((ti >> ANSI_ISNI_TI_SHIFT) == ANSI_ISNI_TYPE_1) {
+ netspec = tvb_get_guint8(tvb, offset) & ANSI_ISNI_NETSPEC_MASK;
+ proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_netspec, tvb, offset,
+ ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti);
+ offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH;
+ }
+
+ while (offset < length) {
+
+ network = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
+ "Network ID network: %d", network);
+ offset++;
+
+ network = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, ANSI_NCM_LENGTH,
+ "Network ID cluster: %d", network);
+ offset++;
+ }
+
+}
+
+/* FUNCTION dissect_sccp_parameter():
+ * Dissect a parameter given its type, offset into tvb, and length.
+ */
+static guint16
+dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
+ proto_tree *tree, guint8 parameter_type, guint16 offset,
+ guint16 parameter_length)
+{
+ tvbuff_t *parameter_tvb;
+
+ switch (parameter_type) {
+ case PARAMETER_CALLED_PARTY_ADDRESS:
+ case PARAMETER_CALLING_PARTY_ADDRESS:
+ case PARAMETER_DATA:
+ case PARAMETER_LONG_DATA:
+ /* These parameters must be dissected even if !sccp_tree (so that
+ * subdissectors can be called).
+ */
+ break;
+
+ default:
+ if (!sccp_tree)
+ return(parameter_length);
+
+ }
+
+ parameter_tvb = tvb_new_subset(tvb, offset, parameter_length, parameter_length);
+
+ switch (parameter_type) {
+
+ case PARAMETER_END_OF_OPTIONAL_PARAMETERS:
+ proto_tree_add_text(sccp_tree, tvb, offset, parameter_length,
+ "End of Optional");
+ break;
+
+ case PARAMETER_DESTINATION_LOCAL_REFERENCE:
+ dissect_sccp_dlr_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_SOURCE_LOCAL_REFERENCE:
+ dissect_sccp_slr_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_CALLED_PARTY_ADDRESS:
+ dissect_sccp_called_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_CALLING_PARTY_ADDRESS:
+ dissect_sccp_calling_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_CLASS:
+ dissect_sccp_class_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_SEGMENTING_REASSEMBLING:
+ dissect_sccp_segmenting_reassembling_param(parameter_tvb, sccp_tree,
+ parameter_length);
+ break;
+
+ case PARAMETER_RECEIVE_SEQUENCE_NUMBER:
+ dissect_sccp_receive_sequence_number_param(parameter_tvb, sccp_tree,
+ parameter_length);
+ break;
+
+ case PARAMETER_SEQUENCING_SEGMENTING:
+ dissect_sccp_sequencing_segmenting_param(parameter_tvb, sccp_tree,
+ parameter_length);
+ break;
+
+ case PARAMETER_CREDIT:
+ dissect_sccp_credit_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_RELEASE_CAUSE:
+ dissect_sccp_release_cause_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_RETURN_CAUSE:
+ dissect_sccp_return_cause_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_RESET_CAUSE:
+ dissect_sccp_reset_cause_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_ERROR_CAUSE:
+ dissect_sccp_error_cause_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_REFUSAL_CAUSE:
+ dissect_sccp_refusal_cause_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_DATA:
+ dissect_sccp_data_param(parameter_tvb, pinfo, tree);
+
+ /* TODO? Re-adjust length of SCCP item since it may be sub-dissected */
+ /* sccp_length = proto_item_get_len(sccp_item);
+ * sccp_length -= parameter_length;
+ * proto_item_set_len(sccp_item, sccp_length);
+ */
+ break;
+
+ case PARAMETER_SEGMENTATION:
+ dissect_sccp_segmentation_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_HOP_COUNTER:
+ dissect_sccp_hop_counter_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ case PARAMETER_IMPORTANCE:
+ if (mtp3_standard != ANSI_STANDARD)
+ dissect_sccp_importance_param(parameter_tvb, sccp_tree, parameter_length);
+ else
+ dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
+ parameter_length);
+ break;
+
+ case PARAMETER_LONG_DATA:
+ if (mtp3_standard != ANSI_STANDARD)
+ dissect_sccp_data_param(parameter_tvb, pinfo, tree);
+ else
+ dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
+ parameter_length);
+ break;
+
+ case PARAMETER_ISNI:
+ if (mtp3_standard != ANSI_STANDARD)
+ dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
+ parameter_length);
+ else
+ dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length);
+ break;
+
+ default:
+ dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type,
+ parameter_length);
+ break;
+ }
+
+ return(parameter_length);
+}
+
+/* FUNCTION dissect_sccp_variable_parameter():
+ * Dissect a variable parameter given its type and offset into tvb. Length
+ * of the parameter is gotten from tvb[0].
+ * Length returned is sum of (length + parameter).
+ */
+static guint16
+dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *sccp_tree, proto_tree *tree,
+ guint8 parameter_type, guint16 offset)
+{
+ guint16 parameter_length;
+ guint8 length_length;
+
+ if (parameter_type != PARAMETER_LONG_DATA)
+ {
+ parameter_length = tvb_get_guint8(tvb, offset);
+ length_length = PARAMETER_LENGTH_LENGTH;
+ }
+ else
+ {
+ /* Long data parameter has 16 bit length */
+ parameter_length = tvb_get_letohs(tvb, offset);
+ length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH;
+ }
+
+ if (sccp_tree &&
+ sccp_show_length)
+ {
+ proto_tree_add_text(sccp_tree, tvb, offset, length_length,
+ "%s length: %d",
+ val_to_str(parameter_type, sccp_parameter_values,
+ "Unknown"),
+ parameter_length);
+ }
+
+ offset += length_length;
+
+ dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
+ parameter_length);
+
+ return(parameter_length + length_length);
+}
+
+/* FUNCTION dissect_sccp_optional_parameters():
+ * Dissect all the optional parameters given the start of the optional
+ * parameters into tvb. Parameter types and lengths are read from tvb.
+ */
+static void
+dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *sccp_tree, proto_tree *tree,
+ guint16 offset)
+{
+ guint8 parameter_type;
+
+ while ((parameter_type = tvb_get_guint8(tvb, offset)) !=
+ PARAMETER_END_OF_OPTIONAL_PARAMETERS) {
+
+ offset += PARAMETER_TYPE_LENGTH;
+ offset += dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ parameter_type, offset);
+ }
+
+ /* Process end of optional parameters */
+ dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset,
+ END_OF_OPTIONAL_PARAMETERS_LENGTH);
+
+}
+
+
+static void
+dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
+ proto_tree *tree)
+{
+ guint8 message_type;
+ guint16 variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0;
+ guint16 optional_pointer = 0;
+ guint16 offset = 0;
+
+/* Macro for getting pointer to mandatory variable parameters */
+#define VARIABLE_POINTER(var, hf_var, ptr_size) \
+ if (ptr_size == POINTER_LENGTH) \
+ var = tvb_get_guint8(tvb, offset); \
+ else \
+ var = tvb_get_letohs(tvb, offset); \
+ proto_tree_add_uint(sccp_tree, hf_var, tvb, \
+ offset, ptr_size, var); \
+ var += offset; \
+ if (ptr_size == POINTER_LENGTH_LONG) \
+ var += 1; \
+ offset += ptr_size;
+
+/* Macro for getting pointer to optional parameters */
+#define OPTIONAL_POINTER(ptr_size) \
+ if (ptr_size == POINTER_LENGTH) \
+ optional_pointer = tvb_get_guint8(tvb, offset); \
+ else \
+ optional_pointer = tvb_get_letohs(tvb, offset); \
+ proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \
+ offset, ptr_size, optional_pointer); \
+ optional_pointer += offset; \
+ if (ptr_size == POINTER_LENGTH_LONG) \
+ optional_pointer += 1; \
+ offset += ptr_size;
+
+
+ /* Extract the message type; all other processing is based on this */
+ message_type = tvb_get_guint8(tvb, MESSAGE_TYPE_OFFSET);
+ offset = MESSAGE_TYPE_LENGTH;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
+ val_to_str(message_type, sccp_message_type_acro_values, "Unknown"));
+
+ if (sccp_tree) {
+ /* add the message type to the protocol tree */
+ proto_tree_add_uint(sccp_tree, hf_sccp_message_type, tvb,
+ MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type);
+
+ };
+
+ /* Starting a new message dissection; clear the global SSN values */
+ called_ssn = INVALID_SSN;
+ calling_ssn = INVALID_SSN;
+
+ switch(message_type) {
+ case MESSAGE_TYPE_CR:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SOURCE_LOCAL_REFERENCE,
+ offset, SOURCE_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CLASS, offset,
+ PROTOCOL_CLASS_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ OPTIONAL_POINTER(POINTER_LENGTH)
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLED_PARTY_ADDRESS,
+ variable_pointer1);
+ break;
+
+ case MESSAGE_TYPE_CC:
+ /* TODO: connection has been established; theoretically we could keep
+ * keep track of the SLR/DLR with the called/calling from the CR and
+ * track the connection (e.g., on subsequent messages regarding this
+ * SLR we could set the global vars "call*_ssn" so data could get
+ * sub-dissected).
+ */
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SOURCE_LOCAL_REFERENCE,
+ offset, SOURCE_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CLASS, offset,
+ PROTOCOL_CLASS_LENGTH);
+ OPTIONAL_POINTER(POINTER_LENGTH)
+ break;
+
+ case MESSAGE_TYPE_CREF:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_REFUSAL_CAUSE, offset,
+ REFUSAL_CAUSE_LENGTH);
+ OPTIONAL_POINTER(POINTER_LENGTH)
+ break;
+
+ case MESSAGE_TYPE_RLSD:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SOURCE_LOCAL_REFERENCE,
+ offset, SOURCE_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_RELEASE_CAUSE, offset,
+ RELEASE_CAUSE_LENGTH);
+
+ OPTIONAL_POINTER(POINTER_LENGTH)
+ break;
+
+ case MESSAGE_TYPE_RLC:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SOURCE_LOCAL_REFERENCE,
+ offset, SOURCE_LOCAL_REFERENCE_LENGTH);
+ break;
+
+ case MESSAGE_TYPE_DT1:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SEGMENTING_REASSEMBLING,
+ offset, SEGMENTING_REASSEMBLING_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
+ variable_pointer1);
+ break;
+
+ case MESSAGE_TYPE_DT2:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SEQUENCING_SEGMENTING, offset,
+ SEQUENCING_SEGMENTING_LENGTH);
+ break;
+
+ case MESSAGE_TYPE_AK:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_RECEIVE_SEQUENCE_NUMBER,
+ offset, RECEIVE_SEQUENCE_NUMBER_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CREDIT, offset, CREDIT_LENGTH);
+ break;
+
+ case MESSAGE_TYPE_UDT:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CLASS, offset,
+ PROTOCOL_CLASS_LENGTH);
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLED_PARTY_ADDRESS,
+ variable_pointer1);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLING_PARTY_ADDRESS,
+ variable_pointer2);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
+ variable_pointer3);
+ break;
+
+ case MESSAGE_TYPE_UDTS:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_RETURN_CAUSE, offset,
+ RETURN_CAUSE_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLED_PARTY_ADDRESS,
+ variable_pointer1);
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLING_PARTY_ADDRESS,
+ variable_pointer2);
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
+ variable_pointer3);
+ break;
+
+ case MESSAGE_TYPE_ED:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
+ variable_pointer1);
+ break;
+
+ case MESSAGE_TYPE_EA:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ break;
+
+ case MESSAGE_TYPE_RSR:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SOURCE_LOCAL_REFERENCE,
+ offset, SOURCE_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_RESET_CAUSE, offset,
+ RESET_CAUSE_LENGTH);
+ break;
+
+ case MESSAGE_TYPE_RSC:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SOURCE_LOCAL_REFERENCE,
+ offset, SOURCE_LOCAL_REFERENCE_LENGTH);
+ break;
+
+ case MESSAGE_TYPE_ERR:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_ERROR_CAUSE, offset,
+ ERROR_CAUSE_LENGTH);
+ break;
+
+ case MESSAGE_TYPE_IT:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_DESTINATION_LOCAL_REFERENCE,
+ offset,
+ DESTINATION_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SOURCE_LOCAL_REFERENCE,
+ offset, SOURCE_LOCAL_REFERENCE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CLASS, offset,
+ PROTOCOL_CLASS_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_SEQUENCING_SEGMENTING,
+ offset, SEQUENCING_SEGMENTING_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CREDIT, offset, CREDIT_LENGTH);
+ break;
+
+ case MESSAGE_TYPE_XUDT:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CLASS, offset,
+ PROTOCOL_CLASS_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_HOP_COUNTER, offset,
+ HOP_COUNTER_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
+ OPTIONAL_POINTER(POINTER_LENGTH)
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLED_PARTY_ADDRESS,
+ variable_pointer1);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLING_PARTY_ADDRESS,
+ variable_pointer2);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
+ variable_pointer3);
+ break;
+
+ case MESSAGE_TYPE_XUDTS:
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_RETURN_CAUSE, offset,
+ RETURN_CAUSE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_HOP_COUNTER, offset,
+ HOP_COUNTER_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH)
+ OPTIONAL_POINTER(POINTER_LENGTH)
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLED_PARTY_ADDRESS,
+ variable_pointer1);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLING_PARTY_ADDRESS,
+ variable_pointer2);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA,
+ variable_pointer3);
+ break;
+
+ case MESSAGE_TYPE_LUDT:
+ if (mtp3_standard != ANSI_STANDARD)
+ {
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CLASS, offset,
+ PROTOCOL_CLASS_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_HOP_COUNTER, offset,
+ HOP_COUNTER_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
+ OPTIONAL_POINTER(POINTER_LENGTH_LONG)
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLED_PARTY_ADDRESS,
+ variable_pointer1);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLING_PARTY_ADDRESS,
+ variable_pointer2);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_LONG_DATA, variable_pointer3);
+ } else
+ dissect_sccp_unknown_message(tvb, sccp_tree);
+ break;
+
+ case MESSAGE_TYPE_LUDTS:
+ if (mtp3_standard != ANSI_STANDARD)
+ {
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_RETURN_CAUSE, offset,
+ RETURN_CAUSE_LENGTH);
+ offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_HOP_COUNTER, offset,
+ HOP_COUNTER_LENGTH);
+
+ VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH_LONG)
+ VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH_LONG)
+ VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH_LONG)
+ OPTIONAL_POINTER(POINTER_LENGTH_LONG)
+
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLED_PARTY_ADDRESS,
+ variable_pointer1);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_CALLING_PARTY_ADDRESS,
+ variable_pointer2);
+ dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree,
+ PARAMETER_LONG_DATA, variable_pointer3);
+ } else
+ dissect_sccp_unknown_message(tvb, sccp_tree);
+ break;
+
+ default:
+ dissect_sccp_unknown_message(tvb, sccp_tree);
+ }
+
+ if (optional_pointer)
+ dissect_sccp_optional_parameters(tvb, pinfo, sccp_tree, tree,
+ optional_pointer);
+
+}
+
+static void
+dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *sccp_item;
+ proto_tree *sccp_tree = NULL;
+ const mtp3_addr_pc_t *mtp3_addr_p;
+
+ /* Make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ switch(mtp3_standard) {
+ case ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Int. ITU)");
+ break;
+ case ANSI_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (ANSI)");
+ break;
+ case CHINESE_ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Chin. ITU)");
+ break;
+ };
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the sccp protocol tree */
+ sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, FALSE);
+ sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp);
+ }
+
+ /* Set whether message is UPLINK, DOWNLINK, or of UNKNOWN direction */
+
+ if (pinfo->net_src.type == AT_SS7PC)
+ {
+ /*
+ * XXX - we assume that the "data" pointers of the source and destination
+ * addresses are set to point to "mtp3_addr_pc_t" structures, so that
+ * we can safely cast them.
+ */
+ mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->net_src.data;
+
+ if (sccp_source_pc_global == mtp3_addr_p->pc)
+ {
+ pinfo->p2p_dir = P2P_DIR_SENT;
+ }
+ else
+ {
+ /* assuming if net_src was SS7 PC then net_dst will be too */
+ mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->net_dst.data;
+
+ if (sccp_source_pc_global == mtp3_addr_p->pc)
+ {
+ pinfo->p2p_dir = P2P_DIR_RECV;
+ }
+ else
+ {
+ pinfo->p2p_dir = P2P_DIR_UNKNOWN;
+ }
+ }
+ }
+
+ /* dissect the message */
+ dissect_sccp_message(tvb, pinfo, sccp_tree, tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_sccp(void)
+{
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_sccp_message_type,
+ { "Message Type", "sccp.message_type",
+ FT_UINT8, BASE_HEX, VALS(sccp_message_type_values), 0x0,
+ "", HFILL}},
+ { &hf_sccp_variable_pointer1,
+ { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_variable_pointer2,
+ { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_variable_pointer3,
+ { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_optional_pointer,
+ { "Pointer to Optional parameter", "sccp.optional_pointer",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_ssn,
+ { "Called or Calling SubSystem Number", "sccp.ssn",
+ FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
+ "", HFILL}},
+ { &hf_sccp_gt_digits,
+ { "Called or Calling GT Digits",
+ "sccp.digits",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_sccp_called_national_indicator,
+ { "National Indicator", "sccp.called.ni",
+ FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
+ "", HFILL}},
+ { &hf_sccp_called_routing_indicator,
+ { "Routing Indicator", "sccp.called.ri",
+ FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_called_itu_global_title_indicator,
+ { "Global Title Indicator", "sccp.called.gti",
+ FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
+ "", HFILL}},
+ { &hf_sccp_called_ansi_global_title_indicator,
+ { "Global Title Indicator", "sccp.called.gti",
+ FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
+ "", HFILL}},
+ { &hf_sccp_called_itu_ssn_indicator,
+ { "SubSystem Number Indicator", "sccp.called.ssni",
+ FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_called_itu_point_code_indicator,
+ { "Point Code Indicator", "sccp.called.pci",
+ FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_called_ansi_ssn_indicator,
+ { "SubSystem Number Indicator", "sccp.called.ssni",
+ FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_called_ansi_point_code_indicator,
+ { "Point Code Indicator", "sccp.called.pci",
+ FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_called_ssn,
+ { "SubSystem Number", "sccp.called.ssn",
+ FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
+ "", HFILL}},
+ { &hf_sccp_called_itu_pc,
+ { "PC", "sccp.called.pc",
+ FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
+ "", HFILL}},
+ { &hf_sccp_called_ansi_pc,
+ { "PC", "sccp.called.ansi_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_called_chinese_pc,
+ { "PC", "sccp.called.chinese_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_called_pc_network,
+ { "PC Network",
+ "sccp.called.network",
+ FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
+ "", HFILL }},
+ { &hf_sccp_called_pc_cluster,
+ { "PC Cluster",
+ "sccp.called.cluster",
+ FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
+ "", HFILL }},
+ { &hf_sccp_called_pc_member,
+ { "PC Member",
+ "sccp.called.member",
+ FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
+ "", HFILL }},
+ { &hf_sccp_called_gt_nai,
+ { "Nature of Address Indicator",
+ "sccp.called.nai",
+ FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
+ "", HFILL }},
+ { &hf_sccp_called_gt_oe,
+ { "Odd/Even Indicator",
+ "sccp.called.oe",
+ FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
+ "", HFILL }},
+ { &hf_sccp_called_gt_tt,
+ { "Translation Type",
+ "sccp.called.tt",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_sccp_called_gt_np,
+ { "Numbering Plan",
+ "sccp.called.np",
+ FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
+ "", HFILL }},
+ { &hf_sccp_called_gt_es,
+ { "Encoding Scheme",
+ "sccp.called.es",
+ FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
+ "", HFILL }},
+ { &hf_sccp_called_gt_digits,
+ { "GT Digits",
+ "sccp.called.digits",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_sccp_calling_national_indicator,
+ { "National Indicator", "sccp.calling.ni",
+ FT_UINT8, BASE_HEX, VALS(sccp_national_indicator_values), ANSI_NATIONAL_MASK,
+ "", HFILL}},
+ { &hf_sccp_calling_routing_indicator,
+ { "Routing Indicator", "sccp.calling.ri",
+ FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_calling_itu_global_title_indicator,
+ { "Global Title Indicator", "sccp.calling.gti",
+ FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK,
+ "", HFILL}},
+ { &hf_sccp_calling_ansi_global_title_indicator,
+ { "Global Title Indicator", "sccp.calling.gti",
+ FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK,
+ "", HFILL}},
+ { &hf_sccp_calling_itu_ssn_indicator,
+ { "SubSystem Number Indicator", "sccp.calling.ssni",
+ FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_calling_itu_point_code_indicator,
+ { "Point Code Indicator", "sccp.calling.pci",
+ FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_calling_ansi_ssn_indicator,
+ { "SubSystem Number Indicator", "sccp.calling.ssni",
+ FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_calling_ansi_point_code_indicator,
+ { "Point Code Indicator", "sccp.calling.pci",
+ FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK,
+ "", HFILL}},
+ { &hf_sccp_calling_ssn,
+ { "SubSystem Number", "sccp.calling.ssn",
+ FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0,
+ "", HFILL}},
+ { &hf_sccp_calling_itu_pc,
+ { "PC", "sccp.calling.pc",
+ FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
+ "", HFILL}},
+ { &hf_sccp_calling_ansi_pc,
+ { "PC", "sccp.calling.ansi_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_calling_chinese_pc,
+ { "PC", "sccp.calling.chinese_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_calling_pc_network,
+ { "PC Network",
+ "sccp.calling.network",
+ FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
+ "", HFILL }},
+ { &hf_sccp_calling_pc_cluster,
+ { "PC Cluster",
+ "sccp.calling.cluster",
+ FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
+ "", HFILL }},
+ { &hf_sccp_calling_pc_member,
+ { "PC Member",
+ "sccp.calling.member",
+ FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
+ "", HFILL }},
+ { &hf_sccp_calling_gt_nai,
+ { "Nature of Address Indicator",
+ "sccp.calling.nai",
+ FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK,
+ "", HFILL }},
+ { &hf_sccp_calling_gt_oe,
+ { "Odd/Even Indicator",
+ "sccp.calling.oe",
+ FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK,
+ "", HFILL }},
+ { &hf_sccp_calling_gt_tt,
+ { "Translation Type",
+ "sccp.calling.tt",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_sccp_calling_gt_np,
+ { "Numbering Plan",
+ "sccp.calling.np",
+ FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK,
+ "", HFILL }},
+ { &hf_sccp_calling_gt_es,
+ { "Encoding Scheme",
+ "sccp.calling.es",
+ FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK,
+ "", HFILL }},
+ { &hf_sccp_calling_gt_digits,
+ { "GT Digits",
+ "sccp.calling.digits",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_sccp_dlr,
+ { "Destination Local Reference", "sccp.dlr",
+ FT_UINT24, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_slr,
+ { "Source Local Reference", "sccp.slr",
+ FT_UINT24, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_class,
+ { "Class", "sccp.class",
+ FT_UINT8, BASE_HEX, NULL, CLASS_CLASS_MASK,
+ "", HFILL}},
+ { &hf_sccp_handling,
+ { "Message handling", "sccp.handling",
+ FT_UINT8, BASE_HEX, VALS(sccp_class_handling_values), CLASS_SPARE_HANDLING_MASK,
+ "", HFILL}},
+ { &hf_sccp_more,
+ { "More data", "sccp.more",
+ FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEGMENTING_REASSEMBLING_MASK,
+ "", HFILL}},
+ { &hf_sccp_rsn,
+ { "Receive Sequence Number", "sccp.rsn",
+ FT_UINT8, BASE_HEX, NULL, RSN_MASK,
+ "", HFILL}},
+ { &hf_sccp_sequencing_segmenting_ssn,
+ { "Sequencing Segmenting: Send Sequence Number", "sccp.sequencing_segmenting.ssn",
+ FT_UINT8, BASE_HEX, NULL, SEND_SEQUENCE_NUMBER_MASK,
+ "", HFILL}},
+ { &hf_sccp_sequencing_segmenting_rsn,
+ { "Sequencing Segmenting: Receive Sequence Number", "sccp.sequencing_segmenting.rsn",
+ FT_UINT8, BASE_HEX, NULL, RECEIVE_SEQUENCE_NUMBER_MASK,
+ "", HFILL}},
+ { &hf_sccp_sequencing_segmenting_more,
+ { "Sequencing Segmenting: More", "sccp.sequencing_segmenting.more",
+ FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEQUENCING_SEGMENTING_MORE_MASK,
+ "", HFILL}},
+ { &hf_sccp_credit,
+ { "Credit", "sccp.credit",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_release_cause,
+ { "Release Cause", "sccp.release_cause",
+ FT_UINT8, BASE_HEX, VALS(sccp_release_cause_values), 0x0,
+ "", HFILL}},
+ { &hf_sccp_return_cause,
+ { "Return Cause", "sccp.return_cause",
+ FT_UINT8, BASE_HEX, VALS(sccp_return_cause_values), 0x0,
+ "", HFILL}},
+ { &hf_sccp_reset_cause,
+ { "Reset Cause", "sccp.reset_cause",
+ FT_UINT8, BASE_HEX, VALS(sccp_reset_cause_values), 0x0,
+ "", HFILL}},
+ { &hf_sccp_error_cause,
+ { "Error Cause", "sccp.error_cause",
+ FT_UINT8, BASE_HEX, VALS(sccp_error_cause_values), 0x0,
+ "", HFILL}},
+ { &hf_sccp_refusal_cause,
+ { "Refusal Cause", "sccp.refusal_cause",
+ FT_UINT8, BASE_HEX, VALS(sccp_refusal_cause_values), 0x0,
+ "", HFILL}},
+ { &hf_sccp_segmentation_first,
+ { "Segmentation: First", "sccp.segmentation.first",
+ FT_UINT8, BASE_HEX, VALS(sccp_segmentation_first_segment_values), SEGMENTATION_FIRST_SEGMENT_MASK,
+ "", HFILL}},
+ { &hf_sccp_segmentation_class,
+ { "Segmentation: Class", "sccp.segmentation.class",
+ FT_UINT8, BASE_HEX, VALS(sccp_segmentation_class_values), SEGMENTATION_CLASS_MASK,
+ "", HFILL}},
+ { &hf_sccp_segmentation_remaining,
+ { "Segmentation: Remaining", "sccp.segmentation.remaining",
+ FT_UINT8, BASE_HEX, NULL, SEGMENTATION_REMAINING_MASK,
+ "", HFILL}},
+ { &hf_sccp_segmentation_slr,
+ { "Segmentation: Source Local Reference", "sccp.segmentation.slr",
+ FT_UINT24, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_hop_counter,
+ { "Hop Counter", "sccp.hops",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccp_importance,
+ { "Importance", "sccp.importance",
+ FT_UINT8, BASE_HEX, NULL, IMPORTANCE_IMPORTANCE_MASK,
+ "", HFILL}},
+
+ /* ISNI is ANSI only */
+ { &hf_sccp_ansi_isni_mi,
+ { "ISNI Mark for Identification Indicator", "sccp.isni.mi",
+ FT_UINT8, BASE_HEX, VALS(sccp_isni_mark_for_id_values), ANSI_ISNI_MI_MASK,
+ "", HFILL}},
+ { &hf_sccp_ansi_isni_iri,
+ { "ISNI Routing Indicator", "sccp.isni.iri",
+ FT_UINT8, BASE_HEX, VALS(sccp_isni_iri_values), ANSI_ISNI_IRI_MASK,
+ "", HFILL}},
+ { &hf_sccp_ansi_isni_ti,
+ { "ISNI Type Indicator", "sccp.isni.ti",
+ FT_UINT8, BASE_HEX, VALS(sccp_isni_ti_values), ANSI_ISNI_TI_MASK,
+ "", HFILL}},
+ { &hf_sccp_ansi_isni_netspec,
+ { "ISNI Network Specific (Type 1)", "sccp.isni.netspec",
+ FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_NETSPEC_MASK,
+ "", HFILL}},
+ { &hf_sccp_ansi_isni_counter,
+ { "ISNI Counter", "sccp.isni.counter",
+ FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_COUNTER_MASK,
+ "", HFILL}},
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_sccp,
+ &ett_sccp_called,
+ &ett_sccp_called_ai,
+ &ett_sccp_called_pc,
+ &ett_sccp_called_gt,
+ &ett_sccp_calling,
+ &ett_sccp_calling_ai,
+ &ett_sccp_calling_pc,
+ &ett_sccp_calling_gt,
+ &ett_sccp_sequencing_segmenting,
+ &ett_sccp_segmentation,
+ &ett_sccp_ansi_isni_routing_control,
+ };
+
+ /* Register the protocol name and description */
+ proto_sccp = proto_register_protocol("Signalling Connection Control Part",
+ "SCCP", "sccp");
+
+ register_dissector("sccp", dissect_sccp, proto_sccp);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_sccp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ sccp_ssn_dissector_table = register_dissector_table("sccp.ssn", "SCCP SSN", FT_UINT8, BASE_DEC);
+
+ register_heur_dissector_list("sccp", &heur_subdissector_list);
+
+ sccp_module = prefs_register_protocol(proto_sccp, NULL);
+
+ prefs_register_uint_preference(sccp_module, "source_pc",
+ "Source PC",
+ "The source point code (usually MSC) (to determine whether message is uplink or downlink)",
+ 16, &sccp_source_pc_global);
+
+ prefs_register_bool_preference(sccp_module, "show_length",
+ "Show length",
+ "Show parameter length in the protocol tree",
+ &sccp_show_length);
+}
+
+void
+proto_reg_handoff_sccp(void)
+{
+ dissector_handle_t sccp_handle;
+
+ sccp_handle = find_dissector("sccp");
+
+ dissector_add("mtp3.service_indicator", SCCP_SI, sccp_handle);
+ dissector_add("m3ua.protocol_data_si", SCCP_SI, sccp_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-sccpmg.c b/epan/dissectors/packet-sccpmg.c
new file mode 100644
index 0000000000..a0f90fcdba
--- /dev/null
+++ b/epan/dissectors/packet-sccpmg.c
@@ -0,0 +1,388 @@
+/* packet-sccp.c
+ * Routines for Signalling Connection Control Part (SCCP) Management dissection
+ *
+ * It is hopefully compliant to:
+ * ANSI T1.112.3-1996
+ * ITU-T Q.713 7/1996
+ * YDN 038-1997 (Chinese ITU variant)
+ *
+ * Copyright 2002, Jeff Morriss <jeff.morriss[AT]ulticom.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+#include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "packet-mtp3.h"
+
+#define SCCPMG_SSN 1
+
+#define SCCPMG_MESSAGE_TYPE_SSA 0x01
+#define SCCPMG_MESSAGE_TYPE_SSP 0x02
+#define SCCPMG_MESSAGE_TYPE_SST 0x03
+#define SCCPMG_MESSAGE_TYPE_SOR 0x04
+#define SCCPMG_MESSAGE_TYPE_SOG 0x05
+/* SSC is ITU only */
+#define SCCPMG_MESSAGE_TYPE_SSC 0x06
+/* Below are ANSI only */
+#define SCCPMG_MESSAGE_TYPE_SBR 0xfd
+#define SCCPMG_MESSAGE_TYPE_SNR 0xfe
+#define SCCPMG_MESSAGE_TYPE_SRT 0xff
+
+/* Same as below but with names typed out */
+static const value_string sccpmg_message_type_values[] = {
+ { SCCPMG_MESSAGE_TYPE_SSA, "SubSystem Allowed" },
+ { SCCPMG_MESSAGE_TYPE_SSP, "SubSystem Prohibited" },
+ { SCCPMG_MESSAGE_TYPE_SST, "Subsystem Status Test" },
+ { SCCPMG_MESSAGE_TYPE_SOR, "Subsystem Out of service Request" },
+ { SCCPMG_MESSAGE_TYPE_SOG, "Subsystem Out of service Grant" },
+ { SCCPMG_MESSAGE_TYPE_SSC, "SubSystem Congested (ITU)" },
+ { SCCPMG_MESSAGE_TYPE_SBR, "Subsystem Backup Routing (ANSI)" },
+ { SCCPMG_MESSAGE_TYPE_SNR, "Subsystem Normal Routing (ANSI)" },
+ { SCCPMG_MESSAGE_TYPE_SRT, "Subsystem Routing status Test (ANSI)" },
+ { 0, NULL } };
+
+/* Same as above but in acronym for (for the Info column) */
+static const value_string sccpmg_message_type_acro_values[] = {
+ { SCCPMG_MESSAGE_TYPE_SSA, "SSA" },
+ { SCCPMG_MESSAGE_TYPE_SSP, "SSP" },
+ { SCCPMG_MESSAGE_TYPE_SST, "SST" },
+ { SCCPMG_MESSAGE_TYPE_SOR, "SOR" },
+ { SCCPMG_MESSAGE_TYPE_SOG, "SOG" },
+ { SCCPMG_MESSAGE_TYPE_SSC, "SSC" },
+ { SCCPMG_MESSAGE_TYPE_SBR, "SBR" },
+ { SCCPMG_MESSAGE_TYPE_SNR, "SNR" },
+ { SCCPMG_MESSAGE_TYPE_SRT, "SRT" },
+ { 0, NULL } };
+
+
+#define SCCPMG_MESSAGE_TYPE_OFFSET 0
+#define SCCPMG_MESSAGE_TYPE_LENGTH 1
+
+#define SCCPMG_AFFECTED_SSN_OFFSET SCCPMG_MESSAGE_TYPE_LENGTH
+#define SCCPMG_AFFECTED_SSN_LENGTH 1
+
+#define SCCPMG_AFFECTED_PC_OFFSET (SCCPMG_AFFECTED_SSN_OFFSET + SCCPMG_AFFECTED_SSN_LENGTH)
+#define ITU_SCCPMG_AFFECTED_PC_LENGTH 2
+#define ANSI_SCCPMG_AFFECTED_PC_LENGTH 3
+
+#define ITU_SCCPMG_SMI_OFFSET (SCCPMG_AFFECTED_PC_OFFSET + ITU_SCCPMG_AFFECTED_PC_LENGTH)
+#define ANSI_SCCPMG_SMI_OFFSET (SCCPMG_AFFECTED_PC_OFFSET + ANSI_SCCPMG_AFFECTED_PC_LENGTH)
+#define SCCPMG_SMI_LENGTH 1
+#define SCCPMG_SMI_MASK 0x3
+
+#define ITU_SCCPMG_CONGESTION_OFFSET (ITU_SCCPMG_SMI_OFFSET + SCCPMG_SMI_LENGTH)
+#define ITU_SCCPMG_CONGESTION_LENGTH 1
+#define ITU_SCCPMG_CONGESTION_MASK 0x0f
+#define CHINESE_ITU_SCCPMG_CONGESTION_OFFSET (ANSI_SCCPMG_SMI_OFFSET + SCCPMG_SMI_LENGTH)
+
+#define SCCPMG_SSN_LENGTH 1
+
+/* Initialize the protocol and registered fields */
+static int proto_sccpmg = -1;
+static int hf_sccpmg_message_type = -1;
+static int hf_sccpmg_affected_ssn = -1;
+static int hf_sccpmg_affected_pc = -1;
+static int hf_sccpmg_affected_ansi_pc = -1;
+static int hf_sccpmg_affected_chinese_pc = -1;
+static int hf_sccpmg_affected_pc_member = -1;
+static int hf_sccpmg_affected_pc_cluster = -1;
+static int hf_sccpmg_affected_pc_network = -1;
+static int hf_sccpmg_smi = -1;
+static int hf_sccpmg_congestion_level = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_sccpmg = -1;
+static gint ett_sccpmg_affected_pc = -1;
+
+static void
+dissect_sccpmg_unknown_message(tvbuff_t *message_tvb, proto_tree *sccpmg_tree)
+{
+ guint32 message_length;
+
+ message_length = tvb_length(message_tvb);
+
+ proto_tree_add_text(sccpmg_tree, message_tvb, 0, message_length,
+ "Unknown message (%u byte%s)", message_length,
+ plurality(message_length, "", "s"));
+}
+
+static void
+dissect_sccpmg_affected_ssn(tvbuff_t *tvb, proto_tree *sccpmg_tree)
+{
+ proto_tree_add_item(sccpmg_tree, hf_sccpmg_affected_ssn, tvb,
+ SCCPMG_AFFECTED_SSN_OFFSET, SCCPMG_SSN_LENGTH,
+ FALSE);
+}
+
+static void
+dissect_sccpmg_affected_pc(tvbuff_t *tvb, proto_tree *sccpmg_tree)
+{
+ proto_item *pc_item = 0;
+ proto_tree *pc_tree = 0;
+ guint32 dpc;
+ guint8 offset = SCCPMG_AFFECTED_PC_OFFSET;
+ char pc[ANSI_PC_STRING_LENGTH];
+
+ if (mtp3_standard == ITU_STANDARD) {
+ proto_tree_add_item(sccpmg_tree, hf_sccpmg_affected_pc, tvb,
+ offset, ITU_PC_LENGTH, TRUE);
+ } else /* ANSI_STANDARD and CHINESE_ITU_STANDARD */ {
+ int *hf_affected_pc;
+
+ if (mtp3_standard == ANSI_STANDARD)
+ {
+ hf_affected_pc = &hf_sccpmg_affected_ansi_pc;
+ } else /* CHINESE_ITU_STANDARD */ {
+ hf_affected_pc = &hf_sccpmg_affected_chinese_pc;
+ }
+
+ /* create the DPC tree; modified from that in packet-sccp.c */
+ dpc = tvb_get_ntoh24(tvb, offset);
+ snprintf(pc, sizeof(pc), "%d-%d-%d",
+ (dpc & ANSI_NETWORK_MASK),
+ ((dpc & ANSI_CLUSTER_MASK) >> 8),
+ ((dpc & ANSI_MEMBER_MASK) >> 16));
+
+ pc_item = proto_tree_add_string_format(sccpmg_tree,
+ *hf_affected_pc,
+ tvb, offset,
+ ANSI_PC_LENGTH, pc,
+ "PC (%s)", pc);
+
+ pc_tree = proto_item_add_subtree(pc_item,
+ ett_sccpmg_affected_pc);
+
+ proto_tree_add_uint(pc_tree, hf_sccpmg_affected_pc_member, tvb,
+ offset, ANSI_NCM_LENGTH, dpc);
+ offset += ANSI_NCM_LENGTH;
+ proto_tree_add_uint(pc_tree, hf_sccpmg_affected_pc_cluster, tvb,
+ offset, ANSI_NCM_LENGTH, dpc);
+ offset += ANSI_NCM_LENGTH;
+ proto_tree_add_uint(pc_tree, hf_sccpmg_affected_pc_network,
+ tvb, offset, ANSI_NCM_LENGTH, dpc);
+ }
+}
+
+static void
+dissect_sccpmg_smi(tvbuff_t *tvb, proto_tree *sccpmg_tree)
+{
+ guint8 offset = 0;
+
+ if (mtp3_standard == ITU_STANDARD)
+ offset = ITU_SCCPMG_SMI_OFFSET;
+ else /* ANSI_STANDARD and CHINESE_ITU_STANDARD */
+ offset = ANSI_SCCPMG_SMI_OFFSET;
+
+ proto_tree_add_item(sccpmg_tree, hf_sccpmg_smi, tvb, offset,
+ SCCPMG_SMI_LENGTH, FALSE);
+}
+
+static void
+dissect_sccpmg_congestion_level(tvbuff_t *tvb, proto_tree *sccpmg_tree)
+{
+ guint8 offset = 0;
+
+ if (mtp3_standard == CHINESE_ITU_STANDARD)
+ offset = CHINESE_ITU_SCCPMG_CONGESTION_OFFSET;
+ else /* ITU_STANDARD */
+ offset = ITU_SCCPMG_CONGESTION_OFFSET;
+
+ proto_tree_add_item(sccpmg_tree, hf_sccpmg_congestion_level, tvb,
+ offset, ITU_SCCPMG_CONGESTION_LENGTH, FALSE);
+}
+
+static void
+dissect_sccpmg_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccpmg_tree)
+{
+ guint8 message_type;
+ guint8 offset = 0;
+
+ /* Extract the message type; all other processing is based on this */
+ message_type = tvb_get_guint8(tvb, SCCPMG_MESSAGE_TYPE_OFFSET);
+ offset = SCCPMG_MESSAGE_TYPE_LENGTH;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_type, sccpmg_message_type_acro_values, "Unknown"));
+
+ if (sccpmg_tree) {
+ /* add the message type to the protocol tree */
+ proto_tree_add_uint(sccpmg_tree, hf_sccpmg_message_type, tvb,
+ SCCPMG_MESSAGE_TYPE_OFFSET,
+ SCCPMG_MESSAGE_TYPE_LENGTH, message_type);
+ }
+
+ switch(message_type) {
+ case SCCPMG_MESSAGE_TYPE_SBR:
+ case SCCPMG_MESSAGE_TYPE_SNR:
+ case SCCPMG_MESSAGE_TYPE_SRT:
+ if (mtp3_standard != ANSI_STANDARD)
+ {
+ dissect_sccpmg_unknown_message(tvb, sccpmg_tree);
+ break;
+ }
+ /* else fallthrough */
+ case SCCPMG_MESSAGE_TYPE_SSA:
+ case SCCPMG_MESSAGE_TYPE_SSP:
+ case SCCPMG_MESSAGE_TYPE_SST:
+ case SCCPMG_MESSAGE_TYPE_SOR:
+ case SCCPMG_MESSAGE_TYPE_SOG:
+ dissect_sccpmg_affected_ssn(tvb, sccpmg_tree);
+ dissect_sccpmg_affected_pc(tvb, sccpmg_tree);
+ dissect_sccpmg_smi(tvb, sccpmg_tree);
+
+ break;
+ case SCCPMG_MESSAGE_TYPE_SSC:
+ if (mtp3_standard != ANSI_STANDARD)
+ {
+ dissect_sccpmg_affected_ssn(tvb, sccpmg_tree);
+ dissect_sccpmg_affected_pc(tvb, sccpmg_tree);
+ dissect_sccpmg_smi(tvb, sccpmg_tree);
+ dissect_sccpmg_congestion_level(tvb, sccpmg_tree);
+ }
+ /* else fallthrough */
+
+ default:
+ dissect_sccpmg_unknown_message(tvb, sccpmg_tree);
+ }
+}
+
+static void
+dissect_sccpmg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *sccpmg_item;
+ proto_tree *sccpmg_tree = NULL;
+
+ /* Make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ switch(mtp3_standard) {
+ case ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCPMG (Int. ITU)");
+ break;
+ case ANSI_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCPMG (ANSI)");
+ break;
+ case CHINESE_ITU_STANDARD:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCPMG (Chin. ITU)");
+ break;
+ };
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the sccpmg protocol tree */
+ sccpmg_item = proto_tree_add_item(tree, proto_sccpmg, tvb, 0,
+ -1, FALSE);
+ sccpmg_tree = proto_item_add_subtree(sccpmg_item, ett_sccpmg);
+ }
+
+ /* dissect the message */
+ dissect_sccpmg_message(tvb, pinfo, sccpmg_tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_sccpmg(void)
+{
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_sccpmg_message_type,
+ { "Message Type", "sccpmg.message_type",
+ FT_UINT8, BASE_HEX, VALS(sccpmg_message_type_values), 0x0,
+ "", HFILL}},
+ { &hf_sccpmg_affected_ssn,
+ { "Affected SubSystem Number", "sccpmg.ssn",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccpmg_affected_pc,
+ { "Affected Point Code", "sccpmg.pc",
+ FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
+ "", HFILL}},
+ { &hf_sccpmg_affected_ansi_pc,
+ { "Affected Point Code", "sccpmg.ansi_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccpmg_affected_chinese_pc,
+ { "Affected Point Code", "sccpmg.chinese_pc",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}},
+ { &hf_sccpmg_affected_pc_network,
+ { "Affected PC Network", "sccpmg.network",
+ FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
+ "", HFILL}},
+ { &hf_sccpmg_affected_pc_cluster,
+ { "Affected PC Cluster", "sccpmg.cluster",
+ FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
+ "", HFILL}},
+ { &hf_sccpmg_affected_pc_member,
+ { "Affected PC Member", "sccpmg.member",
+ FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
+ "", HFILL}},
+ { &hf_sccpmg_smi,
+ { "Subsystem Multiplicity Indicator", "sccpmg.smi",
+ FT_UINT8, BASE_DEC, NULL, SCCPMG_SMI_MASK,
+ "", HFILL}},
+ { &hf_sccpmg_congestion_level,
+ { "SCCP Congestionl Level (ITU)", "sccpmg.congestion",
+ FT_UINT8, BASE_DEC, NULL, ITU_SCCPMG_CONGESTION_MASK,
+ "", HFILL}}
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_sccpmg,
+ &ett_sccpmg_affected_pc
+ };
+
+ /* Register the protocol name and description */
+ proto_sccpmg = proto_register_protocol("Signalling Connection Control Part Management",
+ "SCCPMG", "sccpmg");
+
+ /* Required function calls to register the header fields and subtrees
+ used */
+ proto_register_field_array(proto_sccpmg, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_sccpmg(void)
+{
+ dissector_handle_t sccpmg_handle;
+
+ sccpmg_handle = create_dissector_handle(dissect_sccpmg, proto_sccpmg);
+
+ /* Register for SCCP SSN=1 messages */
+ dissector_add("sccp.ssn", SCCPMG_SSN, sccpmg_handle);
+}
+
diff --git a/epan/dissectors/packet-scsi.c b/epan/dissectors/packet-scsi.c
new file mode 100644
index 0000000000..0e34fb9d70
--- /dev/null
+++ b/epan/dissectors/packet-scsi.c
@@ -0,0 +1,5337 @@
+/* packet-scsi.c
+ * Routines for decoding SCSI CDBs and responses
+ * Author: Dinesh G Dutt (ddutt@cisco.com)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2002 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Some Notes on using the SCSI Decoder:
+ *
+ * The SCSI decoder has been built right now that it is invoked directly by the
+ * SCSI transport layers as compared to the standard mechanism of being invoked
+ * via a dissector chain. There are multiple reasons for this:
+ * - The SCSI CDB is typically embedded inside the transport along with other
+ * header fields that have nothing to do with SCSI. So, it is required to be
+ * invoked on a embedded subset of the packet.
+ * - Originally, Ethereal couldn't do filtering on protocol trees that were not
+ * on the top level.
+ *
+ * There are four main routines that are provided:
+ * o dissect_scsi_cdb - invoked on receiving a SCSI Command
+ * void dissect_scsi_cdb (tvbuff_t *, packet_info *, proto_tree *, guint,
+ * guint);
+ * o dissect_scsi_payload - invoked to decode SCSI responses
+ * void dissect_scsi_payload (tvbuff_t *, packet_info *, proto_tree *, guint,
+ * gboolean, guint32);
+ * The final parameter is the length of the response field that is negotiated
+ * as part of the SCSI transport layer. If this is not tracked by the
+ * transport, it can be set to 0.
+ * o dissect_scsi_rsp - invoked to destroy the data structures associated with a
+ * SCSI task.
+ * void dissect_scsi_rsp (tvbuff_t *, packet_info *, proto_tree *);
+ * o dissect_scsi_snsinfo - invoked to decode the sense data provided in case of
+ * an error.
+ * void dissect_scsi_snsinfo (tvbuff_t *, packet_info *, proto_tree *, guint,
+ * guint);
+ *
+ * In addition to this, the other requirement made from the transport is to
+ * provide a unique way to determine a SCSI task. In Fibre Channel networks,
+ * this is the exchange ID pair alongwith the source/destination addresses; in
+ * iSCSI it is the initiator task tag along with the src/dst address and port
+ * numbers. This is to be provided to the SCSI decoder via the private_data
+ * field in the packet_info data structure. The private_data field is treated
+ * as a pointer to a "scsi_task_id_t" structure, containing a conversation
+ * ID (a number uniquely identifying a conversation between a particular
+ * initiator and target, e.g. between two Fibre Channel addresses or between
+ * two TCP address/port pairs for iSCSI or NDMP) and a task ID (a number
+ * uniquely identifying a task within that conversation).
+ *
+ * This decoder attempts to track the type of SCSI device based on the response
+ * to the Inquiry command. If the trace does not contain an Inquiry command,
+ * the decoding of the commands is done as per a user preference. Currently,
+ * only SBC (disks) and SSC (tapes) are the alternatives offered. The basic
+ * SCSI command set (SPC-2/3) is decoded for all SCSI devices. If there is a
+ * mixture of devices in the trace, some with Inquiry response and some
+ * without, the user preference is used only for those devices whose type the
+ * decoder has not been able to determine.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <epan/strutil.h>
+#include <epan/packet.h>
+#include <epan/int-64bit.h>
+#include "prefs.h"
+#include "packet-scsi.h"
+
+static int proto_scsi = -1;
+static int hf_scsi_spcopcode = -1;
+static int hf_scsi_sbcopcode = -1;
+static int hf_scsi_sscopcode = -1;
+static int hf_scsi_smcopcode = -1;
+static int hf_scsi_control = -1;
+static int hf_scsi_inquiry_flags = -1;
+static int hf_scsi_inquiry_evpd_page = -1;
+static int hf_scsi_inquiry_cmdt_page = -1;
+static int hf_scsi_alloclen = -1;
+static int hf_scsi_logsel_flags = -1;
+static int hf_scsi_logsel_pc = -1;
+static int hf_scsi_paramlen = -1;
+static int hf_scsi_logsns_flags = -1;
+static int hf_scsi_logsns_pc = -1;
+static int hf_scsi_logsns_pagecode = -1;
+static int hf_scsi_paramlen16 = -1;
+static int hf_scsi_modesel_flags = -1;
+static int hf_scsi_alloclen16 = -1;
+static int hf_scsi_modesns_pc = -1;
+static int hf_scsi_spcpagecode = -1;
+static int hf_scsi_sbcpagecode = -1;
+static int hf_scsi_sscpagecode = -1;
+static int hf_scsi_smcpagecode = -1;
+static int hf_scsi_modesns_flags = -1;
+static int hf_scsi_persresvin_svcaction = -1;
+static int hf_scsi_persresvout_svcaction = -1;
+static int hf_scsi_persresv_scope = -1;
+static int hf_scsi_persresv_type = -1;
+static int hf_scsi_release_flags = -1;
+static int hf_scsi_release_thirdpartyid = -1;
+static int hf_scsi_alloclen32 = -1;
+static int hf_scsi_formatunit_flags = -1;
+static int hf_scsi_formatunit_interleave = -1;
+static int hf_scsi_formatunit_vendor = -1;
+static int hf_scsi_rdwr6_lba = -1;
+static int hf_scsi_rdwr6_xferlen = -1;
+static int hf_scsi_rdwr10_lba = -1;
+static int hf_scsi_read_flags = -1;
+static int hf_scsi_rdwr12_xferlen = -1;
+static int hf_scsi_rdwr16_lba = -1;
+static int hf_scsi_readcapacity_flags = -1;
+static int hf_scsi_readcapacity_lba = -1;
+static int hf_scsi_readcapacity_pmi = -1;
+static int hf_scsi_rdwr10_xferlen = -1;
+static int hf_scsi_readdefdata_flags = -1;
+static int hf_scsi_cdb_defectfmt = -1;
+static int hf_scsi_reassignblks_flags = -1;
+static int hf_scsi_inq_qualifier = -1;
+static int hf_scsi_inq_devtype = -1;
+static int hf_scsi_inq_version = -1;
+static int hf_scsi_rluns_lun = -1;
+static int hf_scsi_rluns_multilun = -1;
+static int hf_scsi_modesns_errrep = -1;
+static int hf_scsi_modesns_tst = -1;
+static int hf_scsi_modesns_qmod = -1;
+static int hf_scsi_modesns_qerr = -1;
+static int hf_scsi_modesns_rac = -1;
+static int hf_scsi_modesns_tas = -1;
+static int hf_scsi_protocol = -1;
+static int hf_scsi_sns_errtype = -1;
+static int hf_scsi_snskey = -1;
+static int hf_scsi_snsinfo = -1;
+static int hf_scsi_addlsnslen = -1;
+static int hf_scsi_asc = -1;
+static int hf_scsi_ascascq = -1;
+static int hf_scsi_ascq = -1;
+static int hf_scsi_fru = -1;
+static int hf_scsi_sksv = -1;
+static int hf_scsi_inq_normaca = -1;
+static int hf_scsi_persresv_key = -1;
+static int hf_scsi_persresv_scopeaddr = -1;
+static int hf_scsi_add_cdblen = -1;
+static int hf_scsi_svcaction = -1;
+static int hf_scsi_ssu_immed = -1;
+static int hf_scsi_ssu_pwr_cond = -1;
+static int hf_scsi_ssu_loej = -1;
+static int hf_scsi_ssu_start = -1;
+static int hf_scsi_wb_mode = -1;
+static int hf_scsi_wb_bufferid = -1;
+static int hf_scsi_wb_bufoffset = -1;
+static int hf_scsi_paramlen24 = -1;
+static int hf_scsi_senddiag_st_code = -1;
+static int hf_scsi_senddiag_pf = -1;
+static int hf_scsi_senddiag_st = -1;
+static int hf_scsi_senddiag_devoff = -1;
+static int hf_scsi_senddiag_unitoff = -1;
+
+static gint ett_scsi = -1;
+static gint ett_scsi_page = -1;
+
+typedef guint32 scsi_cmnd_type;
+typedef guint32 scsi_device_type;
+
+/* Valid SCSI Command Types */
+#define SCSI_CMND_SPC2 1
+#define SCSI_CMND_SBC2 2
+#define SCSI_CMND_SSC2 3
+#define SCSI_CMND_SMC2 4
+
+/* SPC and SPC-2 Commands */
+
+#define SCSI_SPC_CHANGE_DEFINITION 0x40
+#define SCSI_SPC_COMPARE 0x39
+#define SCSI_SPC_COPY 0x18
+#define SCSI_SPC_COPY_AND_VERIFY 0x3A
+#define SCSI_SPC2_INQUIRY 0x12
+#define SCSI_SPC2_EXTCOPY 0x83
+#define SCSI_SPC2_LOGSELECT 0x4C
+#define SCSI_SPC2_LOGSENSE 0x4D
+#define SCSI_SPC2_MODESELECT6 0x15
+#define SCSI_SPC2_MODESELECT10 0x55
+#define SCSI_SPC2_MODESENSE6 0x1A
+#define SCSI_SPC2_MODESENSE10 0x5A
+#define SCSI_SPC2_PERSRESVIN 0x5E
+#define SCSI_SPC2_PERSRESVOUT 0x5F
+#define SCSI_SPC2_PREVMEDREMOVAL 0x1E
+#define SCSI_SPC2_READBUFFER 0x3C
+#define SCSI_SPC2_RCVCOPYRESULTS 0x84
+#define SCSI_SPC2_RCVDIAGRESULTS 0x1C
+#define SCSI_SPC2_RELEASE6 0x17
+#define SCSI_SPC2_RELEASE10 0x57
+#define SCSI_SPC2_REPORTDEVICEID 0xA3
+#define SCSI_SPC2_REPORTLUNS 0xA0
+#define SCSI_SPC2_REQSENSE 0x03
+#define SCSI_SPC2_RESERVE6 0x16
+#define SCSI_SPC2_RESERVE10 0x56
+#define SCSI_SPC2_SENDDIAG 0x1D
+#define SCSI_SPC2_SETDEVICEID 0xA4
+#define SCSI_SPC2_TESTUNITRDY 0x00
+#define SCSI_SPC2_WRITEBUFFER 0x3B
+#define SCSI_SPC2_VARLENCDB 0x7F
+
+static const value_string scsi_spc2_val[] = {
+ {SCSI_SPC_CHANGE_DEFINITION , "Change Definition"},
+ {SCSI_SPC_COMPARE , "Compare"},
+ {SCSI_SPC_COPY , "Copy"},
+ {SCSI_SPC_COPY_AND_VERIFY , "Copy And Verify"},
+ {SCSI_SPC2_EXTCOPY , "Extended Copy"},
+ {SCSI_SPC2_INQUIRY , "Inquiry"},
+ {SCSI_SPC2_LOGSELECT , "Log Select"},
+ {SCSI_SPC2_LOGSENSE , "Log Sense"},
+ {SCSI_SPC2_MODESELECT6 , "Mode Select(6)"},
+ {SCSI_SPC2_MODESELECT10 , "Mode Select(10)"},
+ {SCSI_SPC2_MODESENSE6 , "Mode Sense(6)"},
+ {SCSI_SPC2_MODESENSE10 , "Mode Sense(10)"},
+ {SCSI_SPC2_PERSRESVIN , "Persistent Reserve In"},
+ {SCSI_SPC2_PERSRESVOUT , "Persistent Reserve Out"},
+ {SCSI_SPC2_PREVMEDREMOVAL , "Prevent/Allow Medium Removal"},
+ {SCSI_SPC2_RCVCOPYRESULTS , "Receive Copy Results"},
+ {SCSI_SPC2_RCVDIAGRESULTS , "Receive Diagnostics Results"},
+ {SCSI_SPC2_READBUFFER , "Read Buffer"},
+ {SCSI_SPC2_RELEASE6 , "Release(6)"},
+ {SCSI_SPC2_RELEASE10 , "Release(10)"},
+ {SCSI_SPC2_REPORTDEVICEID , "Report Device ID"},
+ {SCSI_SPC2_REPORTLUNS , "Report LUNs"},
+ {SCSI_SPC2_REQSENSE , "Request Sense"},
+ {SCSI_SPC2_RESERVE6 , "Reserve(6)"},
+ {SCSI_SPC2_RESERVE10 , "Reserve(10)"},
+ {SCSI_SPC2_SENDDIAG , "Send Diagnostic"},
+ {SCSI_SPC2_TESTUNITRDY , "Test Unit Ready"},
+ {SCSI_SPC2_WRITEBUFFER , "Write Buffer"},
+ {SCSI_SPC2_VARLENCDB , "Variable Length CDB"},
+ {0, NULL},
+};
+
+/* SBC-2 Commands */
+#define SCSI_SBC2_FORMATUNIT 0x04
+#define SCSI_SBC2_LOCKUNLKCACHE10 0x36
+#define SCSI_SBC2_LOCKUNLKCACHE16 0x92
+#define SCSI_SBC2_PREFETCH10 0x34
+#define SCSI_SBC2_PREFETCH16 0x90
+#define SCSI_SBC2_READ6 0x08
+#define SCSI_SBC2_READ10 0x28
+#define SCSI_SBC2_READ12 0xA8
+#define SCSI_SBC2_READ16 0x88
+#define SCSI_SBC2_READCAPACITY 0x25
+#define SCSI_SBC2_READDEFDATA10 0x37
+#define SCSI_SBC2_READDEFDATA12 0xB7
+#define SCSI_SBC2_READLONG 0x3E
+#define SCSI_SBC2_REASSIGNBLKS 0x07
+#define SCSI_SBC2_REBUILD16 0x81
+#define SCSI_SBC2_REBUILD32 0x7F
+#define SCSI_SBC2_REGENERATE16 0x82
+#define SCSI_SBC2_REGENERATE32 0x7F
+#define SCSI_SBC2_SEEK10 0x2B
+#define SCSI_SBC2_SETLIMITS10 0x33
+#define SCSI_SBC2_SETLIMITS12 0xB3
+#define SCSI_SBC2_STARTSTOPUNIT 0x1B
+#define SCSI_SBC2_SYNCCACHE10 0x35
+#define SCSI_SBC2_SYNCCACHE16 0x91
+#define SCSI_SBC2_VERIFY10 0x2F
+#define SCSI_SBC2_VERIFY12 0xAF
+#define SCSI_SBC2_VERIFY16 0x8F
+#define SCSI_SBC2_WRITE6 0x0A
+#define SCSI_SBC2_WRITE10 0x2A
+#define SCSI_SBC2_WRITE12 0xAA
+#define SCSI_SBC2_WRITE16 0x8A
+#define SCSI_SBC2_WRITENVERIFY10 0x2E
+#define SCSI_SBC2_WRITENVERIFY12 0xAE
+#define SCSI_SBC2_WRITENVERIFY16 0x8E
+#define SCSI_SBC2_WRITELONG 0x3F
+#define SCSI_SBC2_WRITESAME10 0x41
+#define SCSI_SBC2_WRITESAME16 0x93
+#define SCSI_SBC2_XDREAD10 0x52
+#define SCSI_SBC2_XDREAD32 0x7F
+#define SCSI_SBC2_XDWRITE10 0x50
+#define SCSI_SBC2_XDWRITE32 0x7F
+#define SCSI_SBC2_XDWRITEREAD10 0x53
+#define SCSI_SBC2_XDWRITEREAD32 0x7F
+#define SCSI_SBC2_XDWRITEEXTD16 0x80
+#define SCSI_SBC2_XDWRITEEXTD32 0x7F
+#define SCSI_SBC2_XPWRITE10 0x51
+#define SCSI_SBC2_XPWRITE32 0x7F
+
+
+static const value_string scsi_sbc2_val[] = {
+ {SCSI_SBC2_FORMATUNIT , "Format Unit"},
+ {SCSI_SBC2_LOCKUNLKCACHE10, "Lock Unlock Cache(10)"},
+ {SCSI_SBC2_LOCKUNLKCACHE16, "Lock Unlock Cache(16)"},
+ {SCSI_SBC2_PREFETCH10, "Pre-Fetch(10)"},
+ {SCSI_SBC2_PREFETCH16, "Pre-Fetch(16)"},
+ {SCSI_SBC2_READ6 , "Read(6)"},
+ {SCSI_SBC2_READ10 , "Read(10)"},
+ {SCSI_SBC2_READ12 , "Read(12)"},
+ {SCSI_SBC2_READ16 , "Read(16)"},
+ {SCSI_SBC2_READCAPACITY , "Read Capacity"},
+ {SCSI_SBC2_READDEFDATA10 , "Read Defect Data(10)"},
+ {SCSI_SBC2_READDEFDATA12 , "Read Defect Data(12)"},
+ {SCSI_SBC2_READLONG, "Read Long"},
+ {SCSI_SBC2_REASSIGNBLKS , "Reassign Blocks"},
+ {SCSI_SBC2_REBUILD16, "Rebuild(16)"},
+ {SCSI_SBC2_REBUILD32, "Rebuild(32)"},
+ {SCSI_SBC2_REGENERATE16, "Regenerate(16)"},
+ {SCSI_SBC2_REGENERATE32, "Regenerate(32)"},
+ {SCSI_SBC2_SEEK10, "Seek(10)"},
+ {SCSI_SBC2_SETLIMITS10, "Set Limits(10)"},
+ {SCSI_SBC2_SETLIMITS12, "Set Limits(12)"},
+ {SCSI_SBC2_STARTSTOPUNIT, "Start Stop Unit"},
+ {SCSI_SBC2_SYNCCACHE10, "Synchronize Cache(10)"},
+ {SCSI_SBC2_SYNCCACHE16, "Synchronize Cache(16)"},
+ {SCSI_SBC2_VERIFY10, "Verify(10)"},
+ {SCSI_SBC2_VERIFY12, "Verify(12)"},
+ {SCSI_SBC2_VERIFY16, "Verify(16)"},
+ {SCSI_SBC2_WRITE6 , "Write(6)"},
+ {SCSI_SBC2_WRITE10 , "Write(10)"},
+ {SCSI_SBC2_WRITE12 , "Write(12)"},
+ {SCSI_SBC2_WRITE16 , "Write(16)"},
+ {SCSI_SBC2_WRITENVERIFY10, "Write & Verify(10)"},
+ {SCSI_SBC2_WRITENVERIFY12, "Write & Verify(12)"},
+ {SCSI_SBC2_WRITENVERIFY16, "Write & Verify(16)"},
+ {SCSI_SBC2_WRITELONG, "Write Long"},
+ {SCSI_SBC2_WRITESAME10, "Write Same(10)"},
+ {SCSI_SBC2_WRITESAME16, "Write Same(16)"},
+ {SCSI_SBC2_XDREAD10, "XdRead(10)"},
+ {SCSI_SBC2_XDREAD32, "XdRead(32)"},
+ {SCSI_SBC2_XDWRITE10, "XdWrite(10)"},
+ {SCSI_SBC2_XDWRITE32, "XdWrite(32)"},
+ {SCSI_SBC2_XDWRITEREAD10, "XdWriteRead(10)"},
+ {SCSI_SBC2_XDWRITEREAD32, "XdWriteRead(32)"},
+ {SCSI_SBC2_XDWRITEEXTD16, "XdWrite Extended(16)"},
+ {SCSI_SBC2_XDWRITEEXTD32, "XdWrite Extended(32)"},
+ {SCSI_SBC2_XPWRITE10, "XpWrite(10)"},
+ {SCSI_SBC2_XPWRITE32, "XpWrite(32)"},
+ {0, NULL},
+};
+
+/* SSC2 Commands */
+#define SCSI_SSC2_ERASE_16 0x93
+#define SCSI_SSC2_FORMAT_MEDIUM 0x04
+#define SCSI_SSC2_LOAD_UNLOAD 0x1B
+#define SCSI_SSC2_LOCATE_16 0x92
+#define SCSI_SSC2_READ_16 0x88
+#define SCSI_SSC2_READ_BLOCK_LIMITS 0x05
+#define SCSI_SSC2_READ_POSITION 0x34
+#define SCSI_SSC2_READ_REVERSE_16 0x81
+#define SCSI_SSC2_RECOVER_BUFFERED_DATA 0x14
+#define SCSI_SSC2_REPORT_DENSITY_SUPPORT 0x44
+#define SCSI_SSC2_REWIND 0x01
+#define SCSI_SSC2_SET_CAPACITY 0x0B
+#define SCSI_SSC2_SPACE_16 0x91
+#define SCSI_SSC2_VERIFY_16 0x8F
+#define SCSI_SSC2_WRITE_16 0x8A
+#define SCSI_SSC2_WRITE_FILEMARKS_16 0x80
+#define SCSI_SSC2_ERASE_6 0x19
+#define SCSI_SSC2_LOCATE_10 0x2B
+#define SCSI_SSC2_LOCATE_16 0x92
+#define SCSI_SSC2_READ6 0x08
+#define SCSI_SSC2_READ_REVERSE_6 0x0F
+#define SCSI_SSC2_SPACE_6 0x11
+#define SCSI_SSC2_VERIFY_6 0x13
+#define SCSI_SSC2_WRITE6 0x0A
+#define SCSI_SSC2_WRITE_FILEMARKS_6 0x10
+
+static const value_string scsi_ssc2_val[] = {
+ {SCSI_SSC2_ERASE_16 , "Erase(16)"},
+ {SCSI_SSC2_FORMAT_MEDIUM , "Format Medium"},
+ {SCSI_SSC2_LOAD_UNLOAD , "Load Unload"},
+ {SCSI_SSC2_LOCATE_16 , "Locate(16)"},
+ {SCSI_SSC2_READ_16 , "Read(16)"},
+ {SCSI_SSC2_READ_BLOCK_LIMITS , "Read Block Limits"},
+ {SCSI_SSC2_READ_POSITION , "Read Position"},
+ {SCSI_SSC2_READ_REVERSE_16 , "Read Reverse(16)"},
+ {SCSI_SSC2_RECOVER_BUFFERED_DATA , "Recover Buffered Data"},
+ {SCSI_SSC2_REPORT_DENSITY_SUPPORT , "Report Density Support"},
+ {SCSI_SSC2_REWIND , "Rewind"},
+ {SCSI_SSC2_SET_CAPACITY , "Set Capacity"},
+ {SCSI_SSC2_SPACE_16 , "Space(16)"},
+ {SCSI_SSC2_VERIFY_16 , "Verify(16)"},
+ {SCSI_SSC2_WRITE_16 , "Write(16)"},
+ {SCSI_SSC2_WRITE_FILEMARKS_16 , "Write Filemarks(16)"},
+ {SCSI_SSC2_ERASE_6 , "Erase(6)"},
+ {SCSI_SSC2_LOCATE_10 , "Locate(10)"},
+ {SCSI_SSC2_LOCATE_16 , "Locate(16)"},
+ {SCSI_SSC2_READ6 , "Read(6)"},
+ {SCSI_SSC2_READ_REVERSE_6 , "Read Reverse(6)"},
+ {SCSI_SSC2_SPACE_6 , "Space(6)"},
+ {SCSI_SSC2_VERIFY_6 , "Verify(6)"},
+ {SCSI_SSC2_WRITE6 , "Write(6)"},
+ {SCSI_SSC2_WRITE_FILEMARKS_6 , "Write Filemarks(6)"},
+ {0, NULL},
+};
+
+/* SMC2 Commands */
+#define SCSI_SMC2_EXCHANGE_MEDIUM 0x40
+#define SCSI_SMC2_INITIALIZE_ELEMENT_STATUS 0x07
+#define SCSI_SMC2_INITIALIZE_ELEMENT_STATUS_RANGE 0x37
+#define SCSI_SMC2_MOVE_MEDIUM 0xA5
+#define SCSI_SMC2_MOVE_MEDIUM_ATTACHED 0xA7
+#define SCSI_SMC2_POSITION_TO_ELEMENT 0x2B
+#define SCSI_SMC2_READ_ATTRIBUTE 0x8C
+#define SCSI_SMC2_READ_ELEMENT_STATUS 0xB8
+#define SCSI_SMC2_READ_ELEMENT_STATUS_ATTACHED 0xB4
+#define SCSI_SMC2_REQUEST_VOLUME_ELEMENT_ADDRESS 0xB5
+#define SCSI_SMC2_SEND_VOLUME_TAG 0xB6
+#define SCSI_SMC2_WRITE_ATTRIBUTE 0x8D
+
+static const value_string scsi_smc2_val[] = {
+ {SCSI_SMC2_EXCHANGE_MEDIUM , "Exchange Medium"},
+ {SCSI_SMC2_INITIALIZE_ELEMENT_STATUS , "Initialize Element Status"},
+ {SCSI_SMC2_INITIALIZE_ELEMENT_STATUS_RANGE, "Initialize Element Status With Range"},
+ {SCSI_SMC2_MOVE_MEDIUM , "Move Medium"},
+ {SCSI_SMC2_MOVE_MEDIUM_ATTACHED , "Move Medium Attached"},
+ {SCSI_SMC2_POSITION_TO_ELEMENT , "Position To Element"},
+ {SCSI_SMC2_READ_ATTRIBUTE , "Read Attribute"},
+ {SCSI_SMC2_READ_ELEMENT_STATUS , "Read Element Status"},
+ {SCSI_SMC2_READ_ELEMENT_STATUS_ATTACHED , "Read Element Status Attached"},
+ {SCSI_SMC2_REQUEST_VOLUME_ELEMENT_ADDRESS , "Request Volume Element Address"},
+ {SCSI_SMC2_SEND_VOLUME_TAG , "Send Volume Tag"},
+ {SCSI_SMC2_WRITE_ATTRIBUTE , "Write Attribute"},
+ {0, NULL},
+};
+
+#define SCSI_EVPD_SUPPPG 0x00
+#define SCSI_EVPD_DEVSERNUM 0x80
+#define SCSI_EVPD_OPER 0x81
+#define SCSI_EVPD_ASCIIOPER 0x82
+#define SCSI_EVPD_DEVID 0x83
+
+static const value_string scsi_evpd_pagecode_val[] = {
+ {SCSI_EVPD_SUPPPG, "Supported Vital Product Data Pages"},
+ {0x01, "ASCII Information Page"},
+ {0x02, "ASCII Information Page"},
+ {0x03, "ASCII Information Page"},
+ {0x04, "ASCII Information Page"},
+ {0x05, "ASCII Information Page"},
+ {0x06, "ASCII Information Page"},
+ {0x07, "ASCII Information Page"},
+ /* XXX - 0x01 through 0x7F are all ASCII information pages */
+ {SCSI_EVPD_DEVSERNUM, "Unit Serial Number Page"},
+ {SCSI_EVPD_OPER, "Implemented Operating Definition Page"},
+ {SCSI_EVPD_ASCIIOPER, "ASCII Implemented Operating Definition Page"},
+ {SCSI_EVPD_DEVID, "Device Identification Page"},
+ {0, NULL},
+};
+
+static const value_string scsi_logsel_pc_val[] = {
+ {0, "Current Threshold Values"},
+ {1, "Current Cumulative Values"},
+ {2, "Default Threshold Values"},
+ {3, "Default Cumulative Values"},
+ {0, NULL},
+};
+
+static const value_string scsi_logsns_pc_val[] = {
+ {0, "Threshold Values"},
+ {1, "Cumulative Values"},
+ {2, "Default Threshold Values"},
+ {3, "Default Cumulative Values"},
+ {0, NULL},
+};
+
+static const value_string scsi_logsns_page_val[] = {
+ {0xF, "Application Client Page"},
+ {0x1, "Buffer Overrun/Underrun Page"},
+ {0x3, "Error Counter (read) Page"},
+ {0x4, "Error Counter (read reverse) Page"},
+ {0x5, "Error Counter (verify) Page"},
+ {0x1, "Error Counter (write) Page"},
+ {0xB, "Last n Deferred Errors or Async Events Page"},
+ {0x7, "Last n Error Events Page"},
+ {0x6, "Non-medium Error Page"},
+ {0x10, "Self-test Results Page"},
+ {0xE, "Start-Stop Cycle Counter Page"},
+ {0x0, "Supported Log Pages"},
+ {0xD, "Temperature Page"},
+ {0, NULL},
+};
+
+static const value_string scsi_modesns_pc_val[] = {
+ {0, "Current Values"},
+ {1, "Changeable Values"},
+ {2, "Default Values"},
+ {3, "Saved Values"},
+ {0, NULL},
+};
+
+#define SCSI_SPC2_MODEPAGE_CTL 0x0A
+#define SCSI_SPC2_MODEPAGE_DISCON 0x02
+#define SCSI_SCSI2_MODEPAGE_PERDEV 0x09 /* Obsolete in SPC-2; generic in SCSI-2 */
+#define SCSI_SPC2_MODEPAGE_INFOEXCP 0x1C
+#define SCSI_SPC2_MODEPAGE_PWR 0x1A
+#define SCSI_SPC2_MODEPAGE_LUN 0x18
+#define SCSI_SPC2_MODEPAGE_PORT 0x19
+#define SCSI_SPC2_MODEPAGE_VEND 0x00
+
+static const value_string scsi_spc2_modepage_val[] = {
+ {SCSI_SPC2_MODEPAGE_CTL, "Control"},
+ {SCSI_SPC2_MODEPAGE_DISCON, "Disconnect-Reconnect"},
+ {SCSI_SCSI2_MODEPAGE_PERDEV, "Peripheral Device"},
+ {SCSI_SPC2_MODEPAGE_INFOEXCP, "Informational Exceptions Control"},
+ {SCSI_SPC2_MODEPAGE_PWR, "Power Condition"},
+ {SCSI_SPC2_MODEPAGE_LUN, "Protocol Specific LUN"},
+ {SCSI_SPC2_MODEPAGE_PORT, "Protocol-Specific Port"},
+ {SCSI_SPC2_MODEPAGE_VEND, "Vendor Specific Page"},
+ {0x3F, "Return All Mode Pages"},
+ {0, NULL},
+};
+
+#define SCSI_SBC2_MODEPAGE_RDWRERR 0x01
+#define SCSI_SBC2_MODEPAGE_FMTDEV 0x03
+#define SCSI_SBC2_MODEPAGE_DISKGEOM 0x04
+#define SCSI_SBC2_MODEPAGE_FLEXDISK 0x05
+#define SCSI_SBC2_MODEPAGE_VERERR 0x07
+#define SCSI_SBC2_MODEPAGE_CACHE 0x08
+#define SCSI_SBC2_MODEPAGE_MEDTYPE 0x0B
+#define SCSI_SBC2_MODEPAGE_NOTPART 0x0C
+#define SCSI_SBC2_MODEPAGE_XORCTL 0x10
+
+static const value_string scsi_sbc2_modepage_val[] = {
+ {SCSI_SBC2_MODEPAGE_RDWRERR, "Read/Write Error Recovery"},
+ {SCSI_SBC2_MODEPAGE_FMTDEV, "Format Device"},
+ {SCSI_SBC2_MODEPAGE_DISKGEOM, "Rigid Disk Geometry"},
+ {SCSI_SBC2_MODEPAGE_FLEXDISK, "Flexible Disk"},
+ {SCSI_SBC2_MODEPAGE_VERERR, "Verify Error Recovery"},
+ {SCSI_SBC2_MODEPAGE_CACHE, "Caching"},
+ {SCSI_SBC2_MODEPAGE_MEDTYPE, "Medium Types Supported"},
+ {SCSI_SBC2_MODEPAGE_NOTPART, "Notch & Partition"},
+ {SCSI_SBC2_MODEPAGE_XORCTL, "XOR Control"},
+ {0x3F, "Return All Mode Pages"},
+ {0, NULL},
+};
+
+#define SCSI_SSC2_MODEPAGE_DATACOMP 0x0F /* data compression */
+#define SCSI_SSC2_MODEPAGE_DEVCONF 0x10 /* device configuration */
+#define SCSI_SSC2_MODEPAGE_MEDPAR1 0x11 /* medium partition (1) */
+#define SCSI_SSC2_MODEPAGE_MEDPAR2 0x12 /* medium partition (2) */
+#define SCSI_SSC2_MODEPAGE_MEDPAR3 0x13 /* medium partition (3) */
+#define SCSI_SSC2_MODEPAGE_MEDPAR4 0x14 /* medium partition (4) */
+
+static const value_string scsi_ssc2_modepage_val[] = {
+ {SCSI_SSC2_MODEPAGE_DATACOMP, "Data Compression"},
+ {SCSI_SSC2_MODEPAGE_DEVCONF, "Device Configuration"},
+ {SCSI_SSC2_MODEPAGE_MEDPAR1, "Medium Partition (1)"},
+ {SCSI_SSC2_MODEPAGE_MEDPAR2, "Medium Partition (2)"},
+ {SCSI_SSC2_MODEPAGE_MEDPAR3, "Medium Partition (3)"},
+ {SCSI_SSC2_MODEPAGE_MEDPAR4, "Medium Partition (4)"},
+ {0x3F, "Return All Mode Pages"},
+ {0, NULL},
+};
+
+#define SCSI_SMC2_MODEPAGE_EAA 0x1D /* element address assignment */
+#define SCSI_SMC2_MODEPAGE_TRANGEOM 0x1E /* transport geometry parameters */
+#define SCSI_SMC2_MODEPAGE_DEVCAP 0x1F /* device capabilities */
+
+static const value_string scsi_smc2_modepage_val[] = {
+ {SCSI_SMC2_MODEPAGE_EAA, "Element Address Assignment"},
+ {SCSI_SMC2_MODEPAGE_TRANGEOM, "Transport Geometry Parameters"},
+ {SCSI_SMC2_MODEPAGE_DEVCAP, "Device Capabilities"},
+ {0x3F, "Return All Mode Pages"},
+ {0, NULL},
+};
+
+#define SCSI_SPC2_RESVIN_SVCA_RDKEYS 0
+#define SCSI_SPC2_RESVIN_SVCA_RDRESV 1
+
+static const value_string scsi_persresvin_svcaction_val[] = {
+ {SCSI_SPC2_RESVIN_SVCA_RDKEYS, "Read Keys"},
+ {SCSI_SPC2_RESVIN_SVCA_RDRESV, "Read Reservation"},
+ {0, NULL},
+};
+
+static const value_string scsi_persresvout_svcaction_val[] = {
+ {0, "Register"},
+ {1, "Reserve"},
+ {2, "Release"},
+ {3, "Clear"},
+ {4, "Preempt"},
+ {5, "Preempt & Abort"},
+ {6, "Register & Ignore Existing Key"},
+ {0, NULL},
+};
+
+static const value_string scsi_persresv_scope_val[] = {
+ {0, "LU Scope"},
+ {1, "Obsolete"},
+ {2, "Element Scope"},
+ {0, NULL},
+};
+
+static const value_string scsi_persresv_type_val[] = {
+ {1, "Write Excl"},
+ {3, "Excl Access"},
+ {5, "Write Excl, Registrants Only"},
+ {7, "Excl Access, Registrants Only"},
+ {0, NULL},
+};
+
+static const value_string scsi_qualifier_val[] = {
+ {0x0, "Device type is connected to logical unit"},
+ {0x1, "Device type is supported by server but is not connected to logical unit"},
+ {0x3, "Device type is not supported by server"},
+};
+
+static const value_string scsi_devtype_val[] = {
+ {SCSI_DEV_SBC , "Direct Access Device"},
+ {SCSI_DEV_SSC , "Sequential Access Device"},
+ {SCSI_DEV_PRNT , "Printer"},
+ {SCSI_DEV_PROC , "Processor"},
+ {SCSI_DEV_WORM , "WORM"},
+ {SCSI_DEV_CDROM , "CD-ROM"},
+ {SCSI_DEV_SCAN , "Scanner"},
+ {SCSI_DEV_OPTMEM, "Optical Memory"},
+ {SCSI_DEV_SMC , "Medium Changer"},
+ {SCSI_DEV_COMM , "Communication"},
+ {SCSI_DEV_RAID , "Storage Array"},
+ {SCSI_DEV_SES , "Enclosure Services"},
+ {SCSI_DEV_RBC , "Simplified Block Device"},
+ {SCSI_DEV_OCRW , "Optical Card Reader/Writer"},
+ {SCSI_DEV_OSD , "Object-based Storage Device"},
+ {SCSI_DEV_ADC , "Automation/Drive Interface"},
+ {0x1E , "Well known logical unit"},
+ {SCSI_DEV_NOLUN , "Unknown or no device type"},
+ {0, NULL},
+};
+
+static const enum_val_t scsi_devtype_options[] = {
+ {"block", "Block Device", SCSI_DEV_SBC},
+ {"sequential", "Sequential Device", SCSI_DEV_SSC},
+ {NULL, NULL, -1},
+};
+
+static const value_string scsi_inquiry_vers_val[] = {
+ {0, "No Compliance to any Standard"},
+ {2, "Compliance to ANSI X3.131:1994"},
+ {3, "Compliance to ANSI X3.301:1997"},
+ {4, "Compliance to SPC-2"},
+ {0x80, "Compliance to ISO/IEC 9316:1995"},
+ {0x82, "Compliance to ISO/IEC 9316:1995 and to ANSI X3.131:1994"},
+ {0x83, "Compliance to ISO/IEC 9316:1995 and to ANSI X3.301:1997"},
+ {0x84, "Compliance to ISO/IEC 9316:1995 and SPC-2"},
+ {0, NULL},
+};
+
+static const value_string scsi_modesense_medtype_sbc_val[] = {
+ {0x00, "Default"},
+ {0x01, "Flexible disk, single-sided; unspecified medium"},
+ {0x02, "Flexible disk, double-sided; unspecified medium"},
+ {0x05, "Flexible disk, single-sided, single density; 200mm/8in diameter"},
+ {0x06, "Flexible disk, double-sided, single density; 200mm/8in diameter"},
+ {0x09, "Flexible disk, single-sided, double density; 200mm/8in diameter"},
+ {0x0A, "Flexible disk, double-sided, double density; 200mm/8in diameter"},
+ {0x0D, "Flexible disk, single-sided, single density; 130mm/5.25in diameter"},
+ {0x12, "Flexible disk, double-sided, single density; 130mm/5.25in diameter"},
+ {0x16, "Flexible disk, single-sided, double density; 130mm/5.25in diameter"},
+ {0x1A, "Flexible disk, double-sided, double density; 130mm/5.25in diameter"},
+ {0x1E, "Flexible disk, double-sided; 90mm/3.5in diameter"},
+ {0x40, "Direct-access magnetic tape, 12 tracks"},
+ {0x44, "Direct-access magnetic tape, 24 tracks"},
+ {0, NULL},
+};
+
+static const value_string scsi_verdesc_val[] = {
+ {0x0d40, "FC-AL (No Version)"},
+ {0x0d5c, "FC-AL ANSI X3.272:1996"},
+ {0x0d60, "FC-AL-2 (no version claimed)"},
+ {0x0d7c, "FC-AL-2 ANSI NCITS.332:1999"},
+ {0x0d61, "FC-AL-2 T11/1133 revision 7.0"},
+ {0x1320, "FC-FLA (no version claimed)"},
+ {0x133c, "FC-FLA ANSI NCITS TR-20:1998"},
+ {0x133b, "FC-FLA T11/1235 revision 7"},
+ {0x0da0, "FC-FS (no version claimed)"},
+ {0x0db7, "FC-FS T11/1331 revision 1.2"},
+ {0x08c0, "FCP (no version claimed)"},
+ {0x08dc, "FCP ANSI X3.269:1996"},
+ {0x08db, "FCP T10/0993 revision 12"},
+ {0x1340, "FC-PLDA (no version claimed)"},
+ {0x135c, "FC-PLDA ANSI NCITS TR-19:1998"},
+ {0x135b, "FC-PLDA T11/1162 revision 2.1"},
+ {0x0900, "FCP-2 (no version claimed)"},
+ {0x0901, "FCP-2 T10/1144 revision 4"},
+ {0x003c, "SAM ANSI X3.270:1996"},
+ {0x003b, "SAM T10/0994 revision 18"},
+ {0x0040, "SAM-2 (no version claimed)"},
+ {0x0020, "SAM (no version claimed)"},
+ {0x0180, "SBC (no version claimed)"},
+ {0x019c, "SBC ANSI NCITS.306:1998"},
+ {0x019b, "SBC T10/0996 revision 08c"},
+ {0x0320, "SBC-2 (no version claimed)"},
+ {0x01c0, "SES (no version claimed)"},
+ {0x01dc, "SES ANSI NCITS.305:1998"},
+ {0x01db, "SES T10/1212 revision 08b"},
+ {0x01de, "SES ANSI NCITS.305:1998 w/ Amendment ANSI NCITS.305/AM1:2000"},
+ {0x01dd, "SES T10/1212 revision 08b w/ Amendment ANSI NCITS.305/AM1:2000"},
+ {0x0120, "SPC (no version claimed)"},
+ {0x013c, "SPC ANSI X3.301:1997"},
+ {0x013b, "SPC T10/0995 revision 11a"},
+ {0x0260, "SPC-2 (no version claimed)"},
+ {0x0267, "SPC-2 T10/1236 revision 12"},
+ {0x0269, "SPC-2 T10/1236 revision 18"},
+ {0x0300, "SPC-3 (no version claimed)"},
+ {0x0960, "iSCSI (no version claimed)"},
+ {0x0d80, "FC-PH-3 (no version claimed)"},
+ {0x0d9c, "FC-PH-3 ANSI X3.303-1998"},
+ {0x0d20, "FC-PH (no version claimed)"},
+ {0, NULL},
+};
+
+/* Command Support Data "Support" field definitions */
+static const value_string scsi_cmdt_supp_val[] = {
+ {0, "Data not currently available"},
+ {1, "SCSI Command not supported"},
+ {2, "Reserved"},
+ {3, "SCSI Command supported in conformance with a SCSI standard"},
+ {4, "Vendor Specific"},
+ {5, "SCSI Command supported in a vendor specific manner"},
+ {6, "Vendor Specific"},
+ {7, "Reserved"},
+ {0, NULL},
+};
+
+#define CODESET_BINARY 1
+#define CODESET_ASCII 2
+
+static const value_string scsi_devid_codeset_val[] = {
+ {0, "Reserved"},
+ {CODESET_BINARY, "Identifier field contains binary values"},
+ {CODESET_ASCII, "Identifier field contains ASCII graphic codes"},
+ {0, NULL},
+};
+
+static const value_string scsi_devid_assoc_val[] = {
+ {0, "Identifier is associated with addressed logical/physical device"},
+ {1, "Identifier is associated with the port that received the request"},
+ {0, NULL},
+};
+
+static const value_string scsi_devid_idtype_val[] = {
+ {0, "Vendor-specific ID (non-globally unique)"},
+ {1, "Vendor-ID + vendor-specific ID (globally unique)"},
+ {2, "EUI-64 ID"},
+ {3, "WWN"},
+ {4, "4-byte Binary Number/Reserved"},
+ {0, NULL},
+};
+
+static const value_string scsi_modesns_mrie_val[] = {
+ {0, "No Reporting of Informational Exception Condition"},
+ {1, "Asynchronous Error Reporting"},
+ {2, "Generate Unit Attention"},
+ {3, "Conditionally Generate Recovered Error"},
+ {4, "Unconditionally Generate Recovered Error"},
+ {5, "Generate No Sense"},
+ {6, "Only Report Informational Exception Condition on Request"},
+ {0, NULL},
+};
+
+static const value_string scsi_modesns_tst_val[] = {
+ {0, "Task Set Per LU For All Initiators"},
+ {1, "Task Set Per Initiator Per LU"},
+ {0, NULL},
+};
+
+static const value_string scsi_modesns_qmod_val[] = {
+ {0, "Restricted reordering"},
+ {1, "Unrestricted reordering"},
+ {0, NULL},
+};
+
+static const true_false_string scsi_modesns_qerr_val = {
+ "All blocked tasks shall be aborted on CHECK CONDITION",
+ "Blocked tasks shall resume after ACA/CA is cleared",
+};
+
+static const true_false_string scsi_modesns_tas_val = {
+ "Terminated tasks aborted without informing initiators",
+ "Tasks aborted by another initiator terminated with TASK ABORTED",
+};
+
+static const true_false_string scsi_modesns_rac_val = {
+ "Report a CHECK CONDITION Instead of Long Busy Condition",
+ "Long Busy Conditions Maybe Reported",
+};
+
+/* SCSI Transport Protocols */
+#define SCSI_PROTO_FCP 0
+#define SCSI_PROTO_iSCSI 5
+
+static const value_string scsi_proto_val[] = {
+ {0, "FCP"},
+ {5, "iSCSI"},
+ {0, NULL},
+};
+
+static const value_string scsi_fcp_rrtov_val[] = {
+ {0, "No Timer Specified"},
+ {1, "0.001 secs"},
+ {3, "0.1 secs"},
+ {5, "10 secs"},
+ {0, NULL},
+};
+
+static const value_string scsi_sensekey_val[] = {
+ {0x0, "No Sense"},
+ {0x1, "Recovered Error"},
+ {0x2, "Not Ready"},
+ {0x3, "Medium Error"},
+ {0x4, "Hardware Error"},
+ {0x5, "Illegal Request"},
+ {0x6, "Unit Attention"},
+ {0x7, "Data Protection"},
+ {0x8, "Blank Check"},
+ {0x9, "Vendor Specific"},
+ {0xA, "Copy Aborted"},
+ {0xB, "Command Aborted"},
+ {0xC, "Obsolete Error Code"},
+ {0xD, "Overflow Command"},
+ {0xE, "Miscompare"},
+ {0xF, "Reserved"},
+ {0, NULL},
+};
+
+static const value_string scsi_sns_errtype_val[] = {
+ {0x70, "Current Error"},
+ {0x71, "Deferred Error"},
+ {0x7F, "Vendor Specific"},
+ {0, NULL},
+};
+
+static const value_string scsi_asc_val[] = {
+ {0x0000, "No Additional Sense Information"},
+ {0x0006, "I/O Process Terminated"},
+ {0x0016, "Operation In Progress"},
+ {0x0017, "Cleaning Requested"},
+ {0x0100, "No Index/Sector Signal"},
+ {0x0200, "No Seek Complete"},
+ {0x0300, "Peripheral Device Write Fault"},
+ {0x0400, "Logical Unit Not Ready, Cause Not Reportable"},
+ {0x0401, "Logical Unit Is In Process Of Becoming Ready"},
+ {0x0402, "Logical Unit Not Ready, Initializing Cmd. Required"},
+ {0x0403, "Logical Unit Not Ready, Manual Intervention Required"},
+ {0x0404, "Logical Unit Not Ready, Format In Progress"},
+ {0x0405, "Logical Unit Not Ready, Rebuild In Progress"},
+ {0x0406, "Logical Unit Not Ready, Recalculation In Progress"},
+ {0x0407, "Logical Unit Not Ready, Operation In Progress"},
+ {0x0409, "Logical Unit Not Ready, Self-Test In Progress"},
+ {0x0500, "Logical Unit Does Not Respond To Selection"},
+ {0x0600, "No Reference Position Found"},
+ {0x0700, "Multiple Peripheral Devices Selected"},
+ {0x0800, "Logical Unit Communication Failure"},
+ {0x0801, "Logical Unit Communication Time-Out"},
+ {0x0802, "Logical Unit Communication Parity Error"},
+ {0x0803, "Logical Unit Communication Crc Error (Ultra-Dma/32)"},
+ {0x0804, "Unreachable Copy Target"},
+ {0x0900, "Track Following Error"},
+ {0x0904, "Head Select Fault"},
+ {0x0A00, "Error Log Overflow"},
+ {0x0B00, "Warning"},
+ {0x0B01, "Warning - Specified Temperature Exceeded"},
+ {0x0B02, "Warning - Enclosure Degraded"},
+ {0x0C02, "Write Error - Auto Reallocation Failed"},
+ {0x0C03, "Write Error - Recommend Reassignment"},
+ {0x0C04, "Compression Check Miscompare Error"},
+ {0x0C05, "Data Expansion Occurred During Compression"},
+ {0x0C06, "Block Not Compressible"},
+ {0x0D00, "Error Detected By Third Party Temporary Initiator"},
+ {0x0D01, "Third Party Device Failure"},
+ {0x0D02, "Copy Target Device Not Reachable"},
+ {0x0D03, "Incorrect Copy Target Device Type"},
+ {0x0D04, "Copy Target Device Data Underrun"},
+ {0x0D05, "Copy Target Device Data Overrun"},
+ {0x1000, "Id Crc Or Ecc Error"},
+ {0x1100, "Unrecovered Read Error"},
+ {0x1101, "Read Retries Exhausted"},
+ {0x1102, "Error Too Long To Correct"},
+ {0x1103, "Multiple Read Errors"},
+ {0x1104, "Unrecovered Read Error - Auto Reallocate Failed"},
+ {0x110A, "Miscorrected Error"},
+ {0x110B, "Unrecovered Read Error - Recommend Reassignment"},
+ {0x110C, "Unrecovered Read Error - Recommend Rewrite The Data"},
+ {0x110D, "De-Compression Crc Error"},
+ {0x110E, "Cannot Decompress Using Declared Algorithm"},
+ {0x1200, "Address Mark Not Found For Id Field"},
+ {0x1300, "Address Mark Not Found For Data Field"},
+ {0x1400, "Recorded Entity Not Found"},
+ {0x1401, "Record Not Found"},
+ {0x1405, "Record Not Found - Recommend Reassignment"},
+ {0x1406, "Record Not Found - Data Auto-Reallocated"},
+ {0x1500, "Random Positioning Error"},
+ {0x1501, "Mechanical Positioning Error"},
+ {0x1502, "Positioning Error Detected By Read Of Medium"},
+ {0x1600, "Data Synchronization Mark Error"},
+ {0x1601, "Data Sync Error - Data Rewritten"},
+ {0x1602, "Data Sync Error - Recommend Rewrite"},
+ {0x1603, "Data Sync Error - Data Auto-Reallocated"},
+ {0x1604, "Data Sync Error - Recommend Reassignment"},
+ {0x1700, "Recovered Data With No Error Correction Applied"},
+ {0x1701, "Recovered Data With Retries"},
+ {0x1702, "Recovered Data With Positive Head Offset"},
+ {0x1703, "Recovered Data With Negative Head Offset"},
+ {0x1705, "Recovered Data Using Previous Sector Id"},
+ {0x1706, "Recovered Data Without Ecc - Data Auto-Reallocated"},
+ {0x1707, "Recovered Data Without Ecc - Recommend Reassignment"},
+ {0x1708, "Recovered Data Without Ecc - Recommend Rewrite"},
+ {0x1709, "Recovered Data Without Ecc - Data Rewritten"},
+ {0x1800, "Recovered Data With Error Correction Applied"},
+ {0x1801, "Recovered Data With Error Corr. & Retries Applied"},
+ {0x1802, "Recovered Data - Data Auto-Reallocated"},
+ {0x1805, "Recovered Data - Recommend Reassignment"},
+ {0x1806, "Recovered Data - Recommend Rewrite"},
+ {0x1807, "Recovered Data With Ecc - Data Rewritten"},
+ {0x1900, "List Error"},
+ {0x1901, "List Not Available"},
+ {0x1902, "List Error In Primary List"},
+ {0x1903, "List Error In Grown List"},
+ {0x1A00, "Parameter List Length Error"},
+ {0x1B00, "Synchronous Data Transfer Error"},
+ {0x1C00, "Defect List Not Found"},
+ {0x1C01, "Primary Defect List Not Found"},
+ {0x1C02, "Grown Defect List Not Found"},
+ {0x1D00, "Miscompare During Verify Operation"},
+ {0x1E00, "Recovered Id With Ecc Correction"},
+ {0x1F00, "Defect List Transfer"},
+ {0x2000, "Invalid Command Operation Code"},
+ {0x2100, "Logical Block Address Out Of Range"},
+ {0x2101, "Invalid Element Address"},
+ {0x2400, "Invalid Field In Cdb"},
+ {0x2401, "Cdb Decryption Error"},
+ {0x2500, "Logical Unit Not Supported"},
+ {0x2600, "Invalid Field In Parameter List"},
+ {0x2601, "Parameter Not Supported"},
+ {0x2602, "Parameter Value Invalid"},
+ {0x2603, "Threshold Parameters Not Supported"},
+ {0x2604, "Invalid Release Of Persistent Reservation"},
+ {0x2605, "Data Decryption Error"},
+ {0x2606, "Too Many Target Descriptors"},
+ {0x2607, "Unsupported Target Descriptor Type Code"},
+ {0x2608, "Too Many Segment Descriptors"},
+ {0x2609, "Unsupported Segment Descriptor Type Code"},
+ {0x260A, "Unexpected Inexact Segment"},
+ {0x260B, "Inline Data Length Exceeded"},
+ {0x260C, "Invalid Operation For Copy Source Or Destination"},
+ {0x260D, "Copy Segment Granularity Violation"},
+ {0x2700, "Write Protected"},
+ {0x2701, "Hardware Write Protected"},
+ {0x2702, "Logical Unit Software Write Protected"},
+ {0x2800, "Not Ready To Ready Change, Medium May Have Changed"},
+ {0x2801, "Import Or Export Element Accessed"},
+ {0x2900, "Power On, Reset, Or Bus Device Reset Occurred"},
+ {0x2901, "Power On Occurred"},
+ {0x2902, "Scsi Bus Reset Occurred"},
+ {0x2903, "Bus Device Reset Function Occurred"},
+ {0x2904, "Device Internal Reset"},
+ {0x2905, "Transceiver Mode Changed To Single-Ended"},
+ {0x2906, "Transceiver Mode Changed To Lvd"},
+ {0x2A00, "Parameters Changed"},
+ {0x2A01, "Mode Parameters Changed"},
+ {0x2A02, "Log Parameters Changed"},
+ {0x2A03, "Reservations Preempted"},
+ {0x2A04, "Reservations Released"},
+ {0x2A05, "Registrations Preempted"},
+ {0x2B00, "Copy Cannot Execute Since Host Cannot Disconnect"},
+ {0x2C00, "Command Sequence Error"},
+ {0x2F00, "Commands Cleared By Another Initiator"},
+ {0x3000, "Incompatible Medium Installed"},
+ {0x3001, "Cannot Read Medium - Unknown Format"},
+ {0x3002, "Cannot Read Medium - Incompatible Format"},
+ {0x3003, "Cleaning Cartridge Installed"},
+ {0x3004, "Cannot Write Medium - Unknown Format"},
+ {0x3005, "Cannot Write Medium - Incompatible Format"},
+ {0x3006, "Cannot Format Medium - Incompatible Medium"},
+ {0x3007, "Cleaning Failure"},
+ {0x3100, "Medium Format Corrupted"},
+ {0x3101, "Format Command Failed"},
+ {0x3200, "No Defect Spare Location Available"},
+ {0x3201, "Defect List Update Failure"},
+ {0x3400, "Enclosure Failure"},
+ {0x3500, "Enclosure Services Failure"},
+ {0x3501, "Unsupported Enclosure Function"},
+ {0x3502, "Enclosure Services Unavailable"},
+ {0x3503, "Enclosure Services Transfer Failure"},
+ {0x3504, "Enclosure Services Transfer Refused"},
+ {0x3700, "Rounded Parameter"},
+ {0x3900, "Saving Parameters Not Supported"},
+ {0x3A00, "Medium Not Present"},
+ {0x3A01, "Medium Not Present - Tray Closed"},
+ {0x3A02, "Medium Not Present - Tray Open"},
+ {0x3A03, "Medium Not Present - Loadable"},
+ {0x3A04, "Medium Not Present - Medium Auxiliary Memory Accessible"},
+ {0x3B0D, "Medium Destination Element Full"},
+ {0x3B0E, "Medium Source Element Empty"},
+ {0x3B11, "Medium Magazine Not Accessible"},
+ {0x3B12, "Medium Magazine Removed"},
+ {0x3B13, "Medium Magazine Inserted"},
+ {0x3B14, "Medium Magazine Locked"},
+ {0x3B15, "Medium Magazine Unlocked"},
+ {0x3D00, "Invalid Bits In Identify Message"},
+ {0x3E00, "Logical Unit Has Not Self-Configured Yet"},
+ {0x3E01, "Logical Unit Failure"},
+ {0x3E02, "Timeout On Logical Unit"},
+ {0x3E03, "Logical Unit Failed Self-Test"},
+ {0x3E04, "Logical Unit Unable To Update Self-Test Log"},
+ {0x3F00, "Target Operating Conditions Have Changed"},
+ {0x3F01, "Microcode Has Been Changed"},
+ {0x3F02, "Changed Operating Definition"},
+ {0x3F03, "Inquiry Data Has Changed"},
+ {0x3F04, "Component Device Attached"},
+ {0x3F05, "Device Identifier Changed"},
+ {0x3F06, "Redundancy Group Created Or Modified"},
+ {0x3F07, "Redundancy Group Deleted"},
+ {0x3F08, "Spare Created Or Modified"},
+ {0x3F09, "Spare Deleted"},
+ {0x3F0A, "Volume Set Created Or Modified"},
+ {0x3F0B, "Volume Set Deleted"},
+ {0x3F0C, "Volume Set Deassigned"},
+ {0x3F0D, "Volume Set Reassigned"},
+ {0x3F0E, "Reported Luns Data Has Changed"},
+ {0x3F0F, "Echo Buffer Overwritten"},
+ {0x3F10, "Medium Loadable"},
+ {0x3F11, "Medium Auxiliary Memory Accessible"},
+ {0x4200, "Self-Test Failure (Should Use 40 Nn)"},
+ {0x4300, "Message Error"},
+ {0x4400, "Internal Target Failure"},
+ {0x4500, "Select Or Reselect Failure"},
+ {0x4600, "Unsuccessful Soft Reset"},
+ {0x4700, "Scsi Parity Error"},
+ {0x4701, "Data Phase Crc Error Detected"},
+ {0x4702, "Scsi Parity Error Detected During St Data Phase"},
+ {0x4703, "Information Unit Crc Error Detected"},
+ {0x4704, "Asynchronous Information Protection Error Detected"},
+ {0x4800, "Initiator Detected Error Message Received"},
+ {0x4900, "Invalid Message Error"},
+ {0x4A00, "Command Phase Error"},
+ {0x4B00, "Data Phase Error"},
+ {0x4C00, "Logical Unit Failed Self-Configuration"},
+ {0x4D00, "Tagged Overlapped Commands (Nn = Queue Tag)"},
+ {0x4E00, "Overlapped Commands Attempted"},
+ {0x5300, "Media Load Or Eject Failed"},
+ {0x5302, "Medium Removal Prevented"},
+ {0x5501, "System Buffer Full"},
+ {0x5502, "Insufficient Reservation Resources"},
+ {0x5503, "Insufficient Resources"},
+ {0x5504, "Insufficient Registration Resources"},
+ {0x5A00, "Operator Request Or State Change Input"},
+ {0x5A01, "Operator Medium Removal Request"},
+ {0x5A02, "Operator Selected Write Protect"},
+ {0x5A03, "Operator Selected Write Permit"},
+ {0x5B00, "Log Exception"},
+ {0x5B01, "Threshold Condition Met"},
+ {0x5B02, "Log Counter At Maximum"},
+ {0x5B03, "Log List Codes Exhausted"},
+ {0x5C00, "Change"},
+ {0x5C02, "Synchronized"},
+ {0x5D00, "Failure Prediction Threshold Exceeded"},
+ {0x5D10, "Failure General Hard Drive Failure"},
+ {0x5D11, "Failure Drive Error Rate Too High"},
+ {0x5D12, "Failure Data Error Rate Too High"},
+ {0x5D13, "Failure Seek Error Rate Too High"},
+ {0x5D14, "Failure Too Many Block Reassigns"},
+ {0x5D15, "Failure Access Times Too High"},
+ {0x5D16, "Failure Start Unit Times Too High"},
+ {0x5D17, "Failure Channel Parametrics"},
+ {0x5D18, "Failure Controller Detected"},
+ {0x5D19, "Failure Throughput Performance"},
+ {0x5D1A, "Failure Seek Time Performance"},
+ {0x5D1B, "Failure Spin-Up Retry Count"},
+ {0x5D1C, "Failure Drive Calibration Retry"},
+ {0x5D20, "Failure General Hard Drive Failure"},
+ {0x5D21, "Failure Drive Error Rate Too High"},
+ {0x5D22, "Failure Data Error Rate Too High"},
+ {0x5D23, "Failure Seek Error Rate Too High"},
+ {0x5D24, "Failure Too Many Block Reassigns"},
+ {0x5D25, "Failure Access Times Too High"},
+ {0x5D26, "Failure Start Unit Times Too High"},
+ {0x5D27, "Failure Channel Parametrics"},
+ {0x5D28, "Failure Controller Detected"},
+ {0x5D29, "Failure Throughput Performance"},
+ {0x5D2A, "Failure Seek Time Performance"},
+ {0x5D2B, "Failure Spin-Up Retry Count"},
+ {0x5D2C, "Failure Drive Calibration Retry"},
+ {0x5D30, "Impending Failure General Hard Drive"},
+ {0x5D31, "Impending Failure Drive Error Rate Too High"},
+ {0x5D32, "Impending Failure Data Error Rate Too High"},
+ {0x5D33, "Impending Failure Seek Error Rate Too High"},
+ {0x5D34, "Impending Failure Too Many Block Reassigns"},
+ {0x5D35, "Impending Failure Access Times Too High"},
+ {0x5D36, "Impending Failure Start Unit Times Too High"},
+ {0x5D37, "Impending Failure Channel Parametrics"},
+ {0x5D38, "Impending Failure Controller Detected"},
+ {0x5D39, "Impending Failure Throughput Performance"},
+ {0x5D3A, "Impending Failure Seek Time Performance"},
+ {0x5D3B, "Impending Failure Spin-Up Retry Count"},
+ {0x5D3C, "Impending Failure Drive Calibration Retry"},
+ {0x5D40, "Failure General Hard Drive Failure"},
+ {0x5D41, "Failure Drive Error Rate Too High"},
+ {0x5D42, "Failure Data Error Rate Too High"},
+ {0x5D43, "Failure Seek Error Rate Too High"},
+ {0x5D44, "Failure Too Many Block Reassigns"},
+ {0x5D45, "Failure Access Times Too High"},
+ {0x5D46, "Failure Start Unit Times Too High"},
+ {0x5D47, "Failure Channel Parametrics"},
+ {0x5D48, "Failure Controller Detected"},
+ {0x5D49, "Failure Throughput Performance"},
+ {0x5D4A, "Failure Seek Time Performance"},
+ {0x5D4B, "Failure Spin-Up Retry Count"},
+ {0x5D4C, "Failure Drive Calibration Retry Count"},
+ {0x5D50, "Failure General Hard Drive Failure"},
+ {0x5D51, "Failure Drive Error Rate Too High"},
+ {0x5D52, "Failure Data Error Rate Too High"},
+ {0x5D53, "Failure Seek Error Rate Too High"},
+ {0x5D54, "Failure Too Many Block Reassigns"},
+ {0x5D55, "Failure Access Times Too High"},
+ {0x5D56, "Failure Start Unit Times Too High"},
+ {0x5D57, "Failure Channel Parametrics"},
+ {0x5D58, "Failure Controller Detected"},
+ {0x5D59, "Failure Throughput Performance"},
+ {0x5D5A, "Failure Seek Time Performance"},
+ {0x5D5B, "Failure Spin-Up Retry Count"},
+ {0x5D5C, "Failure Drive Calibration Retry Count"},
+ {0x5D60, "Failure General Hard Drive Failure"},
+ {0x5D61, "Failure Drive Error Rate Too High"},
+ {0x5D62, "Failure Data Error Rate Too High"},
+ {0x5D63, "Failure Seek Error Rate Too High"},
+ {0x5D64, "Failure Too Many Block Reassigns"},
+ {0x5D65, "Failure Access Times Too High"},
+ {0x5D66, "Failure Start Unit Times Too High"},
+ {0x5D67, "Failure Channel Parametrics"},
+ {0x5D68, "Failure Controller Detected"},
+ {0x5D69, "Failure Throughput Performance"},
+ {0x5D6A, "Failure Seek Time Performance"},
+ {0x5D6B, "Failure Spin-Up Retry Count"},
+ {0x5D6C, "Failure Drive Calibration Retry Count"},
+ {0x5DFF, "Failure Prediction Threshold Exceeded (False)"},
+ {0x5E00, "Low Power Condition On"},
+ {0x5E01, "Idle Condition Activated By Timer"},
+ {0x5E02, "Standby Condition Activated By Timer"},
+ {0x5E03, "Idle Condition Activated By Command"},
+ {0x5E04, "Standby Condition Activated By Command"},
+ {0x6500, "Voltage Fault"},
+ {0, NULL},
+};
+
+/* SCSI Status Codes */
+const value_string scsi_status_val[] = {
+ {0x00, "Good"},
+ {0x02, "Check Condition"},
+ {0x04, "Condition Met"},
+ {0x08, "Busy"},
+ {0x10, "Intermediate"},
+ {0x14, "Intermediate Condition Met"},
+ {0x18, "Reservation Conflict"},
+ {0x28, "Task Set Full"},
+ {0x30, "ACA Active"},
+ {0x40, "Task Aborted"},
+ {0, NULL},
+};
+
+const value_string scsi_ssu_pwrcnd_val[] = {
+ {0x0, "No Change"},
+ {0x1, "Place Device In Active Condition"},
+ {0x2, "Place device into Idle condition"},
+ {0x3, "Place device into Standby condition"},
+ {0x4, "Reserved"},
+ {0x5, "Place device into Sleep condition"},
+ {0x6, "Reserved"},
+ {0x7, "Transfer control of power conditions to block device"},
+ {0x8, "Reserved"},
+ {0x9, "Reserved"},
+ {0xA, "Force Idle Condition Timer to zero"},
+ {0xB, "Force Standby Condition Timer to zero"},
+ {0, NULL},
+};
+
+const value_string scsi_wb_mode_val[] = {
+ {0x0, "Write combined header and data"},
+ {0x1, "Vendor specific"},
+ {0x2, "Write data"},
+ {0x3, "Reserved"},
+ {0x4, "Download microcode"},
+ {0x5, "Download microcode and save"},
+ {0x6, "Download microcode with offsets"},
+ {0x7, "Download microcode with offsets and save"},
+ {0x8, "Reserved"},
+ {0x9, "Reserved"},
+ {0xA, "Echo buffer"},
+ {0, NULL},
+};
+
+const value_string scsi_senddiag_st_code_val[] = {
+ {0, ""},
+ {0x1, "Start short self-test in background"},
+ {0x2, "Start extended self-test in background"},
+ {0x3, "Reserved"},
+ {0x4, "Abort background self-test"},
+ {0x5, "Foreground short self-test"},
+ {0x6, "Foreground extended self-test"},
+ {0x7, "Reserved"},
+ {0, NULL},
+};
+
+const true_false_string scsi_senddiag_pf_val = {
+ "Vendor-specific Page Format",
+ "Standard Page Format",
+};
+
+static gint scsi_def_devtype = SCSI_DEV_SBC;
+
+/*
+ * We track SCSI requests and responses with a hash table.
+ * The key is a "scsi_task_id_t" structure; the data is a
+ * "scsi_task_data_t" structure.
+ *
+ * We remember:
+ *
+ * the command code and type of command (it's not present in the
+ * response, and we need it to dissect the response);
+ * the type of device it's on;
+ *
+ * and we also have a field to record flags in case the interpretation
+ * of the response data depends on data from the command.
+ */
+typedef struct _scsi_task_data {
+ guint32 opcode;
+ scsi_cmnd_type cmd;
+ scsi_device_type devtype;
+ guint8 flags;
+} scsi_task_data_t;
+
+/*
+ * The next two data structures are used to track SCSI device type.
+ *
+ * XXX - it might not be sufficient to use the address of the server
+ * to which SCSI CDBs are being sent to identify the device, as
+ *
+ * 1) a server might have multiple targets or logical units;
+ *
+ * 2) a server might make a different logical unit refer to
+ * different devices for different clients;
+ *
+ * so we should really base this on the connection index for the
+ * connection and on a device identifier supplied to us by our caller,
+ * not on a network-layer address.
+ */
+typedef struct _scsi_devtype_key {
+ address devid;
+} scsi_devtype_key_t;
+
+typedef struct _scsi_devtype_data {
+ scsi_device_type devtype;
+} scsi_devtype_data_t;
+
+static GHashTable *scsi_req_hash = NULL;
+static GMemChunk *scsi_req_keys = NULL;
+static GMemChunk *scsi_req_vals = NULL;
+static guint32 scsi_init_count = 25;
+
+static GHashTable *scsidev_req_hash = NULL;
+static GMemChunk *scsidev_req_keys = NULL;
+static GMemChunk *scsidev_req_vals = NULL;
+static guint32 scsidev_init_count = 25;
+
+static dissector_handle_t data_handle;
+
+/*
+ * Hash Functions
+ */
+static gint
+scsi_equal(gconstpointer v, gconstpointer w)
+{
+ const scsi_task_id_t *v1 = (const scsi_task_id_t *)v;
+ const scsi_task_id_t *v2 = (const scsi_task_id_t *)w;
+
+ return (v1->conv_id == v2->conv_id && v1->task_id == v2->task_id);
+}
+
+static guint
+scsi_hash (gconstpointer v)
+{
+ const scsi_task_id_t *key = (const scsi_task_id_t *)v;
+ guint val;
+
+ val = key->conv_id + key->task_id;
+
+ return val;
+}
+
+static gint
+scsidev_equal (gconstpointer v, gconstpointer w)
+{
+ const scsi_devtype_key_t *k1 = (const scsi_devtype_key_t *)v;
+ const scsi_devtype_key_t *k2 = (const scsi_devtype_key_t *)w;
+
+ if (ADDRESSES_EQUAL (&k1->devid, &k2->devid))
+ return 1;
+ else
+ return 0;
+}
+
+static guint
+scsidev_hash (gconstpointer v)
+{
+ const scsi_devtype_key_t *key = (const scsi_devtype_key_t *)v;
+ guint val;
+ int i;
+
+ val = 0;
+ for (i = 0; i < key->devid.len; i++)
+ val += key->devid.data[i];
+ val += key->devid.type;
+
+ return val;
+}
+
+static scsi_task_data_t *
+scsi_new_task (packet_info *pinfo)
+{
+ scsi_task_data_t *cdata = NULL;
+ scsi_task_id_t ckey, *req_key;
+
+ if ((pinfo != NULL) && (pinfo->private_data)) {
+ ckey = *(scsi_task_id_t *)pinfo->private_data;
+
+ cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
+ &ckey);
+ if (!cdata) {
+ req_key = g_mem_chunk_alloc (scsi_req_keys);
+ *req_key = *(scsi_task_id_t *)pinfo->private_data;
+
+ cdata = g_mem_chunk_alloc (scsi_req_vals);
+
+ g_hash_table_insert (scsi_req_hash, req_key, cdata);
+ }
+ }
+ return (cdata);
+}
+
+static scsi_task_data_t *
+scsi_find_task (packet_info *pinfo)
+{
+ scsi_task_data_t *cdata = NULL;
+ scsi_task_id_t ckey;
+
+ if ((pinfo != NULL) && (pinfo->private_data)) {
+ ckey = *(scsi_task_id_t *)pinfo->private_data;
+
+ cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
+ &ckey);
+ }
+ return (cdata);
+}
+
+static void
+scsi_end_task (packet_info *pinfo)
+{
+ scsi_task_data_t *cdata = NULL;
+ scsi_task_id_t ckey;
+
+ if ((pinfo != NULL) && (pinfo->private_data)) {
+ ckey = *(scsi_task_id_t *)pinfo->private_data;
+ cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
+ &ckey);
+ if (cdata) {
+ g_mem_chunk_free (scsi_req_vals, cdata);
+ g_hash_table_remove (scsi_req_hash, &ckey);
+ }
+ }
+}
+
+/*
+ * Protocol initialization
+ */
+static void
+free_devtype_key_dev_info(gpointer key_arg, gpointer value_arg _U_,
+ gpointer user_data _U_)
+{
+ scsi_devtype_key_t *key = key_arg;
+
+ if (key->devid.data != NULL) {
+ g_free((gpointer)key->devid.data);
+ key->devid.data = NULL;
+ }
+}
+
+static void
+scsi_init_protocol(void)
+{
+ /*
+ * First, free up the data for the addresses attached to
+ * scsi_devtype_key_t structures. Do so before we free
+ * those structures or destroy the hash table in which
+ * they're stored.
+ */
+ if (scsidev_req_hash != NULL) {
+ g_hash_table_foreach(scsidev_req_hash, free_devtype_key_dev_info,
+ NULL);
+ }
+
+ if (scsi_req_keys)
+ g_mem_chunk_destroy(scsi_req_keys);
+ if (scsi_req_vals)
+ g_mem_chunk_destroy(scsi_req_vals);
+ if (scsidev_req_keys)
+ g_mem_chunk_destroy (scsidev_req_keys);
+ if (scsidev_req_vals)
+ g_mem_chunk_destroy (scsidev_req_vals);
+ if (scsi_req_hash)
+ g_hash_table_destroy(scsi_req_hash);
+ if (scsidev_req_hash)
+ g_hash_table_destroy (scsidev_req_hash);
+
+ scsi_req_hash = g_hash_table_new(scsi_hash, scsi_equal);
+ scsi_req_keys = g_mem_chunk_new("scsi_req_keys",
+ sizeof(scsi_task_id_t),
+ scsi_init_count *
+ sizeof(scsi_task_id_t),
+ G_ALLOC_AND_FREE);
+ scsi_req_vals = g_mem_chunk_new("scsi_req_vals",
+ sizeof(scsi_task_data_t),
+ scsi_init_count *
+ sizeof(scsi_task_data_t),
+ G_ALLOC_AND_FREE);
+ scsidev_req_hash = g_hash_table_new (scsidev_hash, scsidev_equal);
+ scsidev_req_keys = g_mem_chunk_new("scsidev_req_keys",
+ sizeof(scsi_devtype_key_t),
+ scsidev_init_count *
+ sizeof(scsi_devtype_key_t),
+ G_ALLOC_AND_FREE);
+ scsidev_req_vals = g_mem_chunk_new("scsidev_req_vals",
+ sizeof(scsi_devtype_data_t),
+ scsidev_init_count *
+ sizeof(scsi_devtype_data_t),
+ G_ALLOC_AND_FREE);
+}
+
+static void
+dissect_scsi_evpd (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, guint tot_len _U_)
+{
+ proto_tree *evpd_tree;
+ proto_item *ti;
+ guint pcode, plen, i, idlen;
+ guint8 codeset, flags;
+ const char *str;
+
+ if (tree) {
+ pcode = tvb_get_guint8 (tvb, offset+1);
+ plen = tvb_get_guint8 (tvb, offset+3);
+ ti = proto_tree_add_text (tree, tvb, offset, plen+4, "Page Code: %s",
+ val_to_str (pcode, scsi_evpd_pagecode_val,
+ "Unknown (0x%08x)"));
+ evpd_tree = proto_item_add_subtree (ti, ett_scsi_page);
+
+ proto_tree_add_item (evpd_tree, hf_scsi_inq_qualifier, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (evpd_tree, hf_scsi_inq_devtype, tvb, offset,
+ 1, 0);
+ proto_tree_add_text (evpd_tree, tvb, offset+1, 1,
+ "Page Code: %s",
+ val_to_str (pcode, scsi_evpd_pagecode_val,
+ "Unknown (0x%02x)"));
+ proto_tree_add_text (evpd_tree, tvb, offset+3, 1,
+ "Page Length: %u", plen);
+ offset += 4;
+ switch (pcode) {
+ case SCSI_EVPD_SUPPPG:
+ for (i = 0; i < plen; i++) {
+ proto_tree_add_text (evpd_tree, tvb, offset+i, 1,
+ "Supported Page: %s",
+ val_to_str (tvb_get_guint8 (tvb, offset+i),
+ scsi_evpd_pagecode_val,
+ "Unknown (0x%02x)"));
+ }
+ break;
+ case SCSI_EVPD_DEVID:
+ while (plen != 0) {
+ codeset = tvb_get_guint8 (tvb, offset) & 0x0F;
+ proto_tree_add_text (evpd_tree, tvb, offset, 1,
+ "Code Set: %s",
+ val_to_str (codeset,
+ scsi_devid_codeset_val,
+ "Unknown (0x%02x)"));
+ plen -= 1;
+ offset += 1;
+
+ if (plen < 1) {
+ proto_tree_add_text (evpd_tree, tvb, offset, 0,
+ "Product data goes past end of page");
+ break;
+ }
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (evpd_tree, tvb, offset, 1,
+ "Association: %s",
+ val_to_str ((flags & 0x30) >> 4,
+ scsi_devid_assoc_val,
+ "Unknown (0x%02x)"));
+ proto_tree_add_text (evpd_tree, tvb, offset, 1,
+ "Identifier Type: %s",
+ val_to_str ((flags & 0x0F),
+ scsi_devid_idtype_val,
+ "Unknown (0x%02x)"));
+ plen -= 1;
+ offset += 1;
+
+ /* Skip reserved byte */
+ if (plen < 1) {
+ proto_tree_add_text (evpd_tree, tvb, offset, 0,
+ "Product data goes past end of page");
+ break;
+ }
+ plen -= 1;
+ offset += 1;
+
+ if (plen < 1) {
+ proto_tree_add_text (evpd_tree, tvb, offset, 0,
+ "Product data goes past end of page");
+ break;
+ }
+ idlen = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (evpd_tree, tvb, offset, 1,
+ "Identifier Length: %u", idlen);
+ plen -= 1;
+ offset += 1;
+
+ if (idlen != 0) {
+ if (plen < idlen) {
+ proto_tree_add_text (evpd_tree, tvb, offset, 0,
+ "Product data goes past end of page");
+ break;
+ }
+ if (codeset == CODESET_ASCII) {
+ proto_tree_add_text (evpd_tree, tvb, offset, idlen,
+ "Identifier: %s",
+ tvb_format_text (tvb, offset,
+ idlen));
+ } else {
+ /*
+ * XXX - decode this based on the identifier type,
+ * if the codeset is CODESET_BINARY?
+ */
+ proto_tree_add_text (evpd_tree, tvb, offset, idlen,
+ "Identifier: %s",
+ tvb_bytes_to_str (tvb, offset,
+ idlen));
+ }
+ plen -= idlen;
+ offset += idlen;
+ }
+ }
+ break;
+ case SCSI_EVPD_DEVSERNUM:
+ if (plen > 0) {
+ str = tvb_get_ptr (tvb, offset, plen);
+ proto_tree_add_text (evpd_tree, tvb, offset, plen,
+ "Product Serial Number: %.*s", (int)plen,
+ str);
+ }
+ break;
+ }
+ }
+}
+
+static void
+dissect_scsi_cmddt (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, guint tot_len _U_)
+{
+ proto_tree *cmdt_tree;
+ proto_item *ti;
+ guint plen;
+
+ if (tree) {
+ plen = tvb_get_guint8 (tvb, offset+5);
+ ti = proto_tree_add_text (tree, tvb, offset, plen, "Command Data");
+ cmdt_tree = proto_item_add_subtree (ti, ett_scsi_page);
+
+ proto_tree_add_item (cmdt_tree, hf_scsi_inq_qualifier, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (cmdt_tree, hf_scsi_inq_devtype, tvb, offset,
+ 1, 0);
+ proto_tree_add_text (cmdt_tree, tvb, offset+1, 1, "Support: %s",
+ match_strval (tvb_get_guint8 (tvb, offset+1) & 0x7,
+ scsi_cmdt_supp_val));
+ proto_tree_add_text (cmdt_tree, tvb, offset+2, 1, "Version: %s",
+ val_to_str (tvb_get_guint8 (tvb, offset+2),
+ scsi_verdesc_val,
+ "Unknown (0x%02x)"));
+ proto_tree_add_text (cmdt_tree, tvb, offset+5, 1, "CDB Size: %u",
+ plen);
+ }
+}
+
+static void
+dissect_scsi_inquiry (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb,
+ guint32 payload_len, scsi_task_data_t *cdata)
+{
+ guint8 flags, i, devtype;
+ gchar str[32];
+ guint tot_len;
+ scsi_devtype_data_t *devdata = NULL;
+ scsi_devtype_key_t dkey, *req_key;
+
+ if (!isreq && (cdata == NULL || !(cdata->flags & 0x3))) {
+ /*
+ * INQUIRY response with device type information; add device type
+ * to list of known devices & their types if not already known.
+ *
+ * We don't use COPY_ADDRESS because "dkey.devid" isn't
+ * persistent, and therefore it can point to the stuff
+ * in "pinfo->src". (Were we to use COPY_ADDRESS, we'd
+ * have to free the address data it allocated before we return.)
+ */
+ dkey.devid = pinfo->src;
+ devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
+ &dkey);
+ if (!devdata) {
+ req_key = g_mem_chunk_alloc (scsidev_req_keys);
+ COPY_ADDRESS (&(req_key->devid), &(pinfo->src));
+
+ devdata = g_mem_chunk_alloc (scsidev_req_vals);
+ devdata->devtype = tvb_get_guint8 (tvb, offset) & SCSI_DEV_BITS;
+
+ g_hash_table_insert (scsidev_req_hash, req_key, devdata);
+ }
+ else {
+ devtype = tvb_get_guint8 (tvb, offset);
+ if ((devtype & SCSI_DEV_BITS) != SCSI_DEV_NOLUN) {
+ /* Some initiators probe more than the available LUNs which
+ * results in Inquiry data being returned indicating that a LUN
+ * is not supported. We don't want to overwrite the device type
+ * with such responses.
+ */
+ devdata->devtype = (devtype & SCSI_DEV_BITS);
+ }
+ }
+ }
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+ if (cdata != NULL) {
+ cdata->flags = flags;
+ }
+
+ proto_tree_add_uint_format (tree, hf_scsi_inquiry_flags, tvb, offset, 1,
+ flags, "CMDT = %u, EVPD = %u",
+ flags & 0x2, flags & 0x1);
+ if (flags & 0x1) {
+ proto_tree_add_item (tree, hf_scsi_inquiry_evpd_page, tvb, offset+1,
+ 1, 0);
+ }
+ else if (flags & 0x2) {
+ proto_tree_add_item (tree, hf_scsi_inquiry_cmdt_page, tvb, offset+1,
+ 1, 0);
+ }
+
+ proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else if (!isreq) {
+ if (cdata && (cdata->flags & 0x1)) {
+ dissect_scsi_evpd (tvb, pinfo, tree, offset, payload_len);
+ return;
+ }
+ else if (cdata && (cdata->flags & 0x2)) {
+ dissect_scsi_cmddt (tvb, pinfo, tree, offset, payload_len);
+ return;
+ }
+
+ proto_tree_add_item (tree, hf_scsi_inq_qualifier, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_scsi_inq_devtype, tvb, offset, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_inq_version, tvb, offset+2, 1, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+3);
+ proto_tree_add_item_hidden (tree, hf_scsi_inq_normaca, tvb,
+ offset+3, 1, 0);
+ proto_tree_add_text (tree, tvb, offset+3, 1, "NormACA: %u, HiSup: %u",
+ ((flags & 0x20) >> 5), ((flags & 0x10) >> 4));
+ tot_len = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_text (tree, tvb, offset+4, 1, "Additional Length: %u",
+ tot_len);
+ flags = tvb_get_guint8 (tvb, offset+6);
+ proto_tree_add_text (tree, tvb, offset+6, 1,
+ "BQue: %u, SES: %u, MultiP: %u, Addr16: %u",
+ ((flags & 0x80) >> 7), (flags & 0x40) >> 6,
+ (flags & 10) >> 4, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+7);
+ proto_tree_add_text (tree, tvb, offset+7, 1,
+ "RelAdr: %u, Linked: %u, CmdQue: %u",
+ (flags & 0x80) >> 7, (flags & 0x08) >> 3,
+ (flags & 0x02) >> 1);
+ tvb_memcpy (tvb, str, offset+8, 8);
+ str[8] = '\0';
+ proto_tree_add_text (tree, tvb, offset+8, 8, "Vendor Id: %s", str);
+ tvb_memcpy (tvb, str, offset+16, 16);
+ str[16] = '\0';
+ proto_tree_add_text (tree, tvb, offset+16, 16, "Product ID: %s", str);
+ tvb_memcpy (tvb, str, offset+32, 4);
+ str[4] = '\0';
+ proto_tree_add_text (tree, tvb, offset+32, 4, "Product Revision: %s",
+ str);
+
+ offset += 58;
+ if ((tot_len > 58) && tvb_bytes_exist (tvb, offset, 16)) {
+ for (i = 0; i < 8; i++) {
+ proto_tree_add_text (tree, tvb, offset, 2,
+ "Vendor Descriptor %u: %s",
+ i,
+ val_to_str (tvb_get_ntohs (tvb, offset),
+ scsi_verdesc_val,
+ "Unknown (0x%04x)"));
+ offset += 2;
+ }
+ }
+ }
+}
+
+static void
+dissect_scsi_extcopy (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
+ proto_tree *tree _U_, guint offset _U_,
+ gboolean isreq _U_, gboolean iscdb _U_)
+{
+
+}
+
+static void
+dissect_scsi_logselect (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_logsel_flags, tvb, offset, 1,
+ flags, "PCR = %u, SP = %u", flags & 0x2,
+ flags & 0x1);
+ proto_tree_add_uint_format (tree, hf_scsi_logsel_pc, tvb, offset+1, 1,
+ tvb_get_guint8 (tvb, offset+1),
+ "PC: 0x%x", flags & 0xC0);
+ proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else {
+ }
+}
+
+static void
+dissect_scsi_logsense (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_logsns_flags, tvb, offset, 1,
+ flags, "PPC = %u, SP = %u", flags & 0x2,
+ flags & 0x1);
+ proto_tree_add_uint_format (tree, hf_scsi_logsns_pc, tvb, offset+1, 1,
+ tvb_get_guint8 (tvb, offset+1),
+ "PC: 0x%x", flags & 0xC0);
+ proto_tree_add_item (tree, hf_scsi_logsns_pagecode, tvb, offset+1,
+ 1, 0);
+ proto_tree_add_text (tree, tvb, offset+4, 2, "Parameter Pointer: 0x%04x",
+ tvb_get_ntohs (tvb, offset+4));
+ proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else {
+ }
+}
+
+static gboolean
+dissect_scsi_blockdescs (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *scsi_tree, guint offset,
+ guint payload_len, guint desclen,
+ scsi_device_type devtype, gboolean longlba)
+{
+ while (desclen != 0) {
+ if (longlba) {
+ if (payload_len < 8)
+ return FALSE;
+ if (desclen < 8) {
+ offset += desclen;
+ payload_len -= desclen;
+ break;
+ }
+ proto_tree_add_text (scsi_tree, tvb, offset, 8, "No. of Blocks: %s",
+ u64toa (tvb_get_ptr (tvb, offset, 8)));
+ offset += 8;
+ payload_len -= 8;
+ desclen -= 8;
+
+ if (payload_len < 1)
+ return FALSE;
+ if (desclen < 1)
+ break;
+ proto_tree_add_text (scsi_tree, tvb, offset, 1, "Density Code: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+ payload_len -= 1;
+ desclen -= 1;
+
+ if (payload_len < 3)
+ return FALSE;
+ if (desclen < 3) {
+ offset += desclen;
+ payload_len -= desclen;
+ break;
+ }
+ /* 3 reserved bytes */
+ offset += 3;
+ payload_len -= 3;
+ desclen -= 3;
+
+ if (payload_len < 4)
+ return FALSE;
+ if (desclen < 4) {
+ offset += desclen;
+ payload_len -= desclen;
+ break;
+ }
+ proto_tree_add_text (scsi_tree, tvb, offset, 4, "Block Length: %u",
+ tvb_get_ntohl (tvb, offset));
+ offset += 4;
+ payload_len -= 4;
+ desclen -= 4;
+ } else {
+ if (devtype == SCSI_DEV_SBC) {
+ if (payload_len < 4)
+ return FALSE;
+ if (desclen < 4) {
+ offset += desclen;
+ payload_len -= desclen;
+ break;
+ }
+ proto_tree_add_text (scsi_tree, tvb, offset, 4, "No. of Blocks: %u",
+ tvb_get_ntohl (tvb, offset));
+ offset += 4;
+ payload_len -= 4;
+ desclen -= 4;
+
+ if (payload_len < 1)
+ return FALSE;
+ if (desclen < 1)
+ break;
+ proto_tree_add_text (scsi_tree, tvb, offset, 1, "Density Code: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+ payload_len -= 1;
+ desclen -= 1;
+
+ if (payload_len < 3)
+ return FALSE;
+ if (desclen < 3) {
+ offset += desclen;
+ payload_len -= desclen;
+ break;
+ }
+ proto_tree_add_text (scsi_tree, tvb, offset, 3, "Block Length: %u",
+ tvb_get_ntoh24 (tvb, offset));
+ offset += 3;
+ payload_len -= 3;
+ desclen -= 3;
+ } else {
+ if (payload_len < 1)
+ return FALSE;
+ if (desclen < 1)
+ break;
+ proto_tree_add_text (scsi_tree, tvb, offset, 1, "Density Code: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+ payload_len -= 1;
+ desclen -= 1;
+
+ if (payload_len < 3)
+ return FALSE;
+ if (desclen < 3) {
+ offset += desclen;
+ payload_len -= desclen;
+ break;
+ }
+ proto_tree_add_text (scsi_tree, tvb, offset, 3, "No. of Blocks: %u",
+ tvb_get_ntoh24 (tvb, offset));
+ offset += 3;
+ payload_len -= 3;
+ desclen -= 3;
+
+ if (payload_len < 1)
+ return FALSE;
+ if (desclen < 1)
+ break;
+ /* Reserved byte */
+ offset += 1;
+ payload_len -= 1;
+ desclen -= 1;
+
+ if (payload_len < 3)
+ return FALSE;
+ if (desclen < 3) {
+ offset += desclen;
+ payload_len -= desclen;
+ break;
+ }
+ proto_tree_add_text (scsi_tree, tvb, offset, 3, "Block Length: %u",
+ tvb_get_ntoh24 (tvb, offset));
+ offset += 3;
+ payload_len -= 3;
+ desclen -= 3;
+ }
+ }
+ }
+ return TRUE;
+}
+
+static gboolean
+dissect_scsi_spc2_modepage (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, guint8 pcode)
+{
+ guint8 flags, proto;
+
+ switch (pcode) {
+ case SCSI_SPC2_MODEPAGE_CTL:
+ flags = tvb_get_guint8 (tvb, offset+2);
+ proto_tree_add_item (tree, hf_scsi_modesns_tst, tvb, offset+2, 1, 0);
+ proto_tree_add_text (tree, tvb, offset+2, 1,
+ "Global Logging Target Save Disable: %u, Report Log Exception Condition: %u",
+ (flags & 0x2) >> 1, (flags & 0x1));
+ flags = tvb_get_guint8 (tvb, offset+3);
+ proto_tree_add_item (tree, hf_scsi_modesns_qmod, tvb, offset+3, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_modesns_qerr, tvb, offset+3, 1, 0);
+ proto_tree_add_text (tree, tvb, offset+3, 1, "Disable Queuing: %u",
+ flags & 0x1);
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_item (tree, hf_scsi_modesns_rac, tvb, offset+4, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_modesns_tas, tvb, offset+4, 1, 0);
+ proto_tree_add_text (tree, tvb, offset+4, 1,
+ "SWP: %u, RAERP: %u, UAAERP: %u, EAERP: %u",
+ (flags & 0x8) >> 3, (flags & 0x4) >> 2,
+ (flags & 0x2) >> 2, (flags & 0x1));
+ proto_tree_add_text (tree, tvb, offset+5, 1, "Autoload Mode: 0x%x",
+ tvb_get_guint8 (tvb, offset+5) & 0x7);
+ proto_tree_add_text (tree, tvb, offset+6, 2,
+ "Ready AER Holdoff Period: %u ms",
+ tvb_get_ntohs (tvb, offset+6));
+ proto_tree_add_text (tree, tvb, offset+8, 2,
+ "Busy Timeout Period: %u ms",
+ tvb_get_ntohs (tvb, offset+8)*100);
+ proto_tree_add_text (tree, tvb, offset+10, 2,
+ "Extended Self-Test Completion Time: %u",
+ tvb_get_ntohs (tvb, offset+10));
+ break;
+ case SCSI_SPC2_MODEPAGE_DISCON:
+ proto_tree_add_text (tree, tvb, offset+2, 1, "Buffer Full Ratio: %u",
+ tvb_get_guint8 (tvb, offset+2));
+ proto_tree_add_text (tree, tvb, offset+3, 1, "Buffer Empty Ratio: %u",
+ tvb_get_guint8 (tvb, offset+3));
+ proto_tree_add_text (tree, tvb, offset+4, 2, "Bus Inactivity Limit: %u",
+ tvb_get_ntohs (tvb, offset+4));
+ proto_tree_add_text (tree, tvb, offset+6, 2, "Disconnect Time Limit: %u",
+ tvb_get_ntohs (tvb, offset+6));
+ proto_tree_add_text (tree, tvb, offset+8, 2, "Connect Time Limit: %u",
+ tvb_get_ntohs (tvb, offset+8));
+ proto_tree_add_text (tree, tvb, offset+10, 2,
+ "Maximum Burst Size: %u bytes",
+ tvb_get_ntohs (tvb, offset+10)*512);
+ flags = tvb_get_guint8 (tvb, offset+12);
+ proto_tree_add_text (tree, tvb, offset+12, 1,
+ "EMDP: %u, FAA: %u, FAB: %u, FAC: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & 0x20) >> 5, (flags & 0x10) >> 4);
+ proto_tree_add_text (tree, tvb, offset+14, 2,
+ "First Burst Size: %u bytes",
+ tvb_get_ntohs (tvb, offset+14)*512);
+ break;
+ case SCSI_SPC2_MODEPAGE_INFOEXCP:
+ flags = tvb_get_guint8 (tvb, offset+2);
+ proto_tree_add_text (tree, tvb, offset+2, 1,
+ "Perf: %u, EBF: %u, EWasc: %u, DExcpt: %u, Test: %u, LogErr: %u",
+ (flags & 0x80) >> 7, (flags & 0x20) >> 5,
+ (flags & 0x10) >> 4, (flags & 0x08) >> 3,
+ (flags & 0x04) >> 2, (flags & 0x01));
+ if (!((flags & 0x10) >> 4) && ((flags & 0x08) >> 3)) {
+ proto_tree_add_item_hidden (tree, hf_scsi_modesns_errrep, tvb,
+ offset+3, 1, 0);
+ }
+ else {
+ proto_tree_add_item (tree, hf_scsi_modesns_errrep, tvb, offset+3, 1, 0);
+ }
+ proto_tree_add_text (tree, tvb, offset+4, 4, "Interval Timer: %u",
+ tvb_get_ntohl (tvb, offset+4));
+ proto_tree_add_text (tree, tvb, offset+8, 4, "Report Count: %u",
+ tvb_get_ntohl (tvb, offset+8));
+ break;
+ case SCSI_SPC2_MODEPAGE_PWR:
+ flags = tvb_get_guint8 (tvb, offset+3);
+ proto_tree_add_text (tree, tvb, offset+3, 1, "Idle: %u, Standby: %u",
+ (flags & 0x2) >> 1, (flags & 0x1));
+ proto_tree_add_text (tree, tvb, offset+4, 2,
+ "Idle Condition Timer: %u ms",
+ tvb_get_ntohs (tvb, offset+4) * 100);
+ proto_tree_add_text (tree, tvb, offset+6, 2,
+ "Standby Condition Timer: %u ms",
+ tvb_get_ntohs (tvb, offset+6) * 100);
+ break;
+ case SCSI_SPC2_MODEPAGE_LUN:
+ return FALSE;
+ case SCSI_SPC2_MODEPAGE_PORT:
+ proto = tvb_get_guint8 (tvb, offset+2) & 0x0F;
+ proto_tree_add_item (tree, hf_scsi_protocol, tvb, offset+2, 1, 0);
+ if (proto == SCSI_PROTO_FCP) {
+ flags = tvb_get_guint8 (tvb, offset+3);
+ proto_tree_add_text (tree, tvb, offset+3, 1,
+ "DTFD: %u, PLPB: %u, DDIS: %u, DLM: %u, RHA: %u, ALWI: %u, DTIPE: %u, DTOLI:%u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & 0x20) >> 5, (flags & 0x10) >> 4,
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x1));
+ proto_tree_add_text (tree, tvb, offset+6, 1, "RR_TOV Units: %s",
+ val_to_str (tvb_get_guint8 (tvb, offset+6) & 0x7,
+ scsi_fcp_rrtov_val,
+ "Unknown (0x%02x)"));
+ proto_tree_add_text (tree, tvb, offset+7, 1, "RR_TOV: %u",
+ tvb_get_guint8 (tvb, offset+7));
+ }
+ else if (proto == SCSI_PROTO_iSCSI) {
+ return FALSE;
+ }
+ else {
+ return FALSE;
+ }
+ break;
+ case SCSI_SCSI2_MODEPAGE_PERDEV:
+ return FALSE;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+dissect_scsi_sbc2_modepage (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, guint8 pcode)
+{
+ guint8 flags;
+
+ switch (pcode) {
+ case SCSI_SBC2_MODEPAGE_FMTDEV:
+ proto_tree_add_text (tree, tvb, offset+2, 2, "Tracks Per Zone: %u",
+ tvb_get_ntohs (tvb, offset+2));
+ proto_tree_add_text (tree, tvb, offset+4, 2,
+ "Alternate Sectors Per Zone: %u",
+ tvb_get_ntohs (tvb, offset+4));
+ proto_tree_add_text (tree, tvb, offset+6, 2,
+ "Alternate Tracks Per Zone: %u",
+ tvb_get_ntohs (tvb, offset+6));
+ proto_tree_add_text (tree, tvb, offset+8, 2,
+ "Alternate Tracks Per LU: %u",
+ tvb_get_ntohs (tvb, offset+8));
+ proto_tree_add_text (tree, tvb, offset+10, 2, "Sectors Per Track: %u",
+ tvb_get_ntohs (tvb, offset+10));
+ proto_tree_add_text (tree, tvb, offset+12, 2,
+ "Data Bytes Per Physical Sector: %u",
+ tvb_get_ntohs (tvb, offset+12));
+ proto_tree_add_text (tree, tvb, offset+14, 2, "Interleave: %u",
+ tvb_get_ntohs (tvb, offset+14));
+ proto_tree_add_text (tree, tvb, offset+16, 2, "Track Skew Factor: %u",
+ tvb_get_ntohs (tvb, offset+16));
+ proto_tree_add_text (tree, tvb, offset+18, 2,
+ "Cylinder Skew Factor: %u",
+ tvb_get_ntohs (tvb, offset+18));
+ flags = tvb_get_guint8 (tvb, offset+20);
+ proto_tree_add_text (tree, tvb, offset+20, 1,
+ "SSEC: %u, HSEC: %u, RMB: %u, SURF: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & 0x20) >> 5, (flags & 0x10) >> 4);
+ break;
+ case SCSI_SBC2_MODEPAGE_RDWRERR:
+ flags = tvb_get_guint8 (tvb, offset+2);
+ proto_tree_add_text (tree, tvb, offset+2, 1,
+ "AWRE: %u, ARRE: %u, TB: %u, RC: %u, EER: %u, PER: %u, DTE: %u, DCR: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & 0x20) >> 5, (flags & 0x10) >> 4,
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ proto_tree_add_text (tree, tvb, offset+3, 1, "Read Retry Count: %u",
+ tvb_get_guint8 (tvb, offset+3));
+ proto_tree_add_text (tree, tvb, offset+4, 1, "Correction Span: %u",
+ tvb_get_guint8 (tvb, offset+4));
+ proto_tree_add_text (tree, tvb, offset+5, 1, "Head Offset Count: %u",
+ tvb_get_guint8 (tvb, offset+5));
+ proto_tree_add_text (tree, tvb, offset+6, 1,
+ "Data Strobe Offset Count: %u",
+ tvb_get_guint8 (tvb, offset+6));
+ proto_tree_add_text (tree, tvb, offset+8, 1, "Write Retry Count: %u",
+ tvb_get_guint8 (tvb, offset+8));
+ proto_tree_add_text (tree, tvb, offset+10, 2,
+ "Recovery Time Limit: %u ms",
+ tvb_get_ntohs (tvb, offset+10));
+ break;
+ case SCSI_SBC2_MODEPAGE_DISKGEOM:
+ proto_tree_add_text (tree, tvb, offset+2, 3, "Number of Cylinders: %u",
+ tvb_get_ntoh24 (tvb, offset+2));
+ proto_tree_add_text (tree, tvb, offset+5, 1, "Number of Heads: %u",
+ tvb_get_guint8 (tvb, offset+5));
+ proto_tree_add_text (tree, tvb, offset+6, 3,
+ "Starting Cyl Pre-compensation: %u",
+ tvb_get_ntoh24 (tvb, offset+6));
+ proto_tree_add_text (tree, tvb, offset+9, 3,
+ "Starting Cyl-reduced Write Current: %u",
+ tvb_get_ntoh24 (tvb, offset+9));
+ proto_tree_add_text (tree, tvb, offset+12, 2, "Device Step Rate: %u",
+ tvb_get_ntohs (tvb, offset+12));
+ proto_tree_add_text (tree, tvb, offset+14, 3, "Landing Zone Cyl: %u",
+ tvb_get_ntoh24 (tvb, offset+14));
+ proto_tree_add_text (tree, tvb, offset+18, 1, "Rotational Offset: %u",
+ tvb_get_guint8 (tvb, offset+18));
+ proto_tree_add_text (tree, tvb, offset+20, 2,
+ "Medium Rotation Rate: %u",
+ tvb_get_ntohs (tvb, offset+20));
+ break;
+ case SCSI_SBC2_MODEPAGE_FLEXDISK:
+ return FALSE;
+ case SCSI_SBC2_MODEPAGE_VERERR:
+ return FALSE;
+ case SCSI_SBC2_MODEPAGE_CACHE:
+ flags = tvb_get_guint8 (tvb, offset+2);
+ proto_tree_add_text (tree, tvb, offset+2, 1,
+ "IC: %u, ABPF: %u, CAP %u, Disc: %u, Size: %u, WCE: %u, MF: %u, RCD: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & 0x20) >> 5, (flags & 0x10) >> 4,
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+3);
+ proto_tree_add_text (tree, tvb, offset+3, 1,
+ "Demand Read Retention Priority: %u, Write Retention Priority: %u",
+ (flags & 0xF0) >> 4, (flags & 0x0F));
+ proto_tree_add_text (tree, tvb, offset+4, 2,
+ "Disable Pre-fetch Xfer Len: %u",
+ tvb_get_ntohs (tvb, offset+4));
+ proto_tree_add_text (tree, tvb, offset+6, 2, "Minimum Pre-Fetch: %u",
+ tvb_get_ntohs (tvb, offset+6));
+ proto_tree_add_text (tree, tvb, offset+8, 2, "Maximum Pre-Fetch: %u",
+ tvb_get_ntohs (tvb, offset+8));
+ proto_tree_add_text (tree, tvb, offset+10, 2,
+ "Maximum Pre-Fetch Ceiling: %u",
+ tvb_get_ntohs (tvb, offset+10));
+ flags = tvb_get_guint8 (tvb, offset+12);
+ proto_tree_add_text (tree, tvb, offset+12, 1,
+ "FSW: %u, LBCSS: %u, DRA: %u, Vendor Specific: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & 0x20) >> 5, (flags & 0x1F) >> 4);
+ proto_tree_add_text (tree, tvb, offset+13, 1,
+ "Number of Cache Segments: %u",
+ tvb_get_guint8 (tvb, offset+13));
+ proto_tree_add_text (tree, tvb, offset+14, 2, "Cache Segment Size: %u",
+ tvb_get_ntohs (tvb, offset+14));
+ proto_tree_add_text (tree, tvb, offset+17, 3,
+ "Non-Cache Segment Size: %u",
+ tvb_get_ntoh24 (tvb, offset+17));
+ break;
+ case SCSI_SBC2_MODEPAGE_MEDTYPE:
+ return FALSE;
+ case SCSI_SBC2_MODEPAGE_NOTPART:
+ return FALSE;
+ case SCSI_SBC2_MODEPAGE_XORCTL:
+ return FALSE;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static const value_string compression_algorithm_vals[] = {
+ {0x00, "No algorithm selected"},
+ {0x01, "Default algorithm"},
+ {0x03, "IBM ALDC with 512-byte buffer"},
+ {0x04, "IBM ALDC with 1024-byte buffer"},
+ {0x05, "IBM ALDC with 2048-byte buffer"},
+ {0x10, "IBM IDRC"},
+ {0x20, "DCLZ"},
+ {0xFF, "Unregistered algorithm"},
+ {0, NULL}
+};
+
+static gboolean
+dissect_scsi_ssc2_modepage (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
+ proto_tree *tree _U_, guint offset _U_,
+ guint8 pcode)
+{
+ guint8 flags;
+
+ switch (pcode) {
+ case SCSI_SSC2_MODEPAGE_DATACOMP:
+ flags = tvb_get_guint8 (tvb, offset+2);
+ proto_tree_add_text (tree, tvb, offset+2, 1,
+ "DCE: %u, DCC: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6);
+ flags = tvb_get_guint8 (tvb, offset+3);
+ proto_tree_add_text (tree, tvb, offset+3, 1,
+ "DDE: %u, RED: %u",
+ (flags & 0x80) >> 7, (flags & 0x60) >> 5);
+ proto_tree_add_text (tree, tvb, offset+4, 4,
+ "Compression algorithm: %s",
+ val_to_str (tvb_get_ntohl (tvb, offset+4),
+ compression_algorithm_vals,
+ "Unknown (0x%08x)"));
+ proto_tree_add_text (tree, tvb, offset+8, 4,
+ "Decompression algorithm: %s",
+ val_to_str (tvb_get_ntohl (tvb, offset+4),
+ compression_algorithm_vals,
+ "Unknown (0x%08x)"));
+ break;
+ case SCSI_SSC2_MODEPAGE_DEVCONF:
+ return FALSE;
+ case SCSI_SSC2_MODEPAGE_MEDPAR1:
+ return FALSE;
+ case SCSI_SSC2_MODEPAGE_MEDPAR2:
+ return FALSE;
+ case SCSI_SSC2_MODEPAGE_MEDPAR3:
+ return FALSE;
+ case SCSI_SSC2_MODEPAGE_MEDPAR4:
+ return FALSE;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+dissect_scsi_smc2_modepage (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, guint8 pcode)
+{
+ guint8 flags;
+ guint8 param_list_len;
+
+ switch (pcode) {
+ case SCSI_SMC2_MODEPAGE_EAA:
+ param_list_len = tvb_get_guint8 (tvb, offset+2);
+ proto_tree_add_text (tree, tvb, offset+2, 1, "Parameter List Length: %u",
+ param_list_len);
+ if (param_list_len < 2)
+ break;
+ proto_tree_add_text (tree, tvb, offset+3, 2, "First Medium Transport Element Address: %u",
+ tvb_get_ntohs (tvb, offset+3));
+ param_list_len -= 2;
+ if (param_list_len < 2)
+ break;
+ proto_tree_add_text (tree, tvb, offset+5, 2, "Number of Medium Transport Elements: %u",
+ tvb_get_ntohs (tvb, offset+5));
+ param_list_len -= 2;
+ if (param_list_len < 2)
+ break;
+ proto_tree_add_text (tree, tvb, offset+7, 2, "First Storage Element Address: %u",
+ tvb_get_ntohs (tvb, offset+7));
+ param_list_len -= 2;
+ if (param_list_len < 2)
+ break;
+ proto_tree_add_text (tree, tvb, offset+9, 2, "Number of Storage Elements: %u",
+ tvb_get_ntohs (tvb, offset+9));
+ param_list_len -= 2;
+ if (param_list_len < 2)
+ break;
+ proto_tree_add_text (tree, tvb, offset+11, 2, "First Import/Export Element Address: %u",
+ tvb_get_ntohs (tvb, offset+11));
+ param_list_len -= 2;
+ if (param_list_len < 2)
+ break;
+ proto_tree_add_text (tree, tvb, offset+13, 2, "Number of Import/Export Elements: %u",
+ tvb_get_ntohs (tvb, offset+13));
+ param_list_len -= 2;
+ if (param_list_len < 2)
+ break;
+ proto_tree_add_text (tree, tvb, offset+15, 2, "First Data Transfer Element Address: %u",
+ tvb_get_ntohs (tvb, offset+15));
+ param_list_len -= 2;
+ if (param_list_len < 2)
+ break;
+ proto_tree_add_text (tree, tvb, offset+17, 2, "Number of Data Transfer Elements: %u",
+ tvb_get_ntohs (tvb, offset+17));
+ break;
+ case SCSI_SMC2_MODEPAGE_TRANGEOM:
+ return FALSE;
+ case SCSI_SMC2_MODEPAGE_DEVCAP:
+ flags = tvb_get_guint8 (tvb, offset+2);
+ proto_tree_add_text (tree, tvb, offset+2, 1,
+ "STORDT: %u, STORI/E: %u, STORST: %u, STORMT: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_text (tree, tvb, offset+4, 1,
+ "MT->DT: %u, MT->I/E: %u, MT->ST: %u, MT->MT: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+5);
+ proto_tree_add_text (tree, tvb, offset+5, 1,
+ "ST->DT: %u, ST->I/E: %u, ST->ST: %u, ST->MT: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+6);
+ proto_tree_add_text (tree, tvb, offset+6, 1,
+ "I/E->DT: %u, I/E->I/E: %u, I/E->ST: %u, I/E->MT: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+7);
+ proto_tree_add_text (tree, tvb, offset+7, 1,
+ "DT->DT: %u, DT->I/E: %u, DT->ST: %u, DT->MT: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+12);
+ proto_tree_add_text (tree, tvb, offset+12, 1,
+ "MT<>DT: %u, MT<>I/E: %u, MT<>ST: %u, MT<>MT: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+13);
+ proto_tree_add_text (tree, tvb, offset+13, 1,
+ "ST<>DT: %u, ST<>I/E: %u, ST<>ST: %u, ST<>MT: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+14);
+ proto_tree_add_text (tree, tvb, offset+14, 1,
+ "I/E<>DT: %u, I/E<>I/E: %u, I/E<>ST: %u, I/E<>MT: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+15);
+ proto_tree_add_text (tree, tvb, offset+15, 1,
+ "DT<>DT: %u, DT<>I/E: %u, DT<>ST: %u, DT<>MT: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static guint
+dissect_scsi_modepage (tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *scsi_tree, guint offset,
+ scsi_device_type devtype)
+{
+ guint8 pcode, plen;
+ proto_tree *tree;
+ proto_item *ti;
+ const value_string *modepage_val;
+ int hf_pagecode;
+ gboolean (*dissect_modepage)(tvbuff_t *, packet_info *, proto_tree *,
+ guint, guint8);
+
+ pcode = tvb_get_guint8 (tvb, offset);
+ plen = tvb_get_guint8 (tvb, offset+1);
+
+ if (match_strval (pcode & SCSI_MS_PCODE_BITS,
+ scsi_spc2_modepage_val) == NULL) {
+ /*
+ * This isn't a generic mode page that applies to all SCSI
+ * device types; try to interpret it based on what we deduced,
+ * or were told, the device type is.
+ */
+ switch (devtype) {
+ case SCSI_DEV_SBC:
+ modepage_val = scsi_sbc2_modepage_val;
+ hf_pagecode = hf_scsi_sbcpagecode;
+ dissect_modepage = dissect_scsi_sbc2_modepage;
+ break;
+
+ case SCSI_DEV_SSC:
+ modepage_val = scsi_ssc2_modepage_val;
+ hf_pagecode = hf_scsi_sscpagecode;
+ dissect_modepage = dissect_scsi_ssc2_modepage;
+ break;
+
+ case SCSI_DEV_SMC:
+ modepage_val = scsi_smc2_modepage_val;
+ hf_pagecode = hf_scsi_smcpagecode;
+ dissect_modepage = dissect_scsi_smc2_modepage;
+ break;
+
+ default:
+ /*
+ * The "val_to_str()" lookup will fail in this table
+ * (it failed in "match_strval()"), so it'll return
+ * "Unknown (XXX)", which is what we want.
+ */
+ modepage_val = scsi_spc2_modepage_val;
+ hf_pagecode = hf_scsi_spcpagecode;
+ dissect_modepage = dissect_scsi_spc2_modepage;
+ break;
+ }
+ } else {
+ modepage_val = scsi_spc2_modepage_val;
+ hf_pagecode = hf_scsi_spcpagecode;
+ dissect_modepage = dissect_scsi_spc2_modepage;
+ }
+ ti = proto_tree_add_text (scsi_tree, tvb, offset, plen+2, "%s Mode Page",
+ val_to_str (pcode & SCSI_MS_PCODE_BITS,
+ modepage_val, "Unknown (0x%08x)"));
+ tree = proto_item_add_subtree (ti, ett_scsi_page);
+ proto_tree_add_text (tree, tvb, offset, 1, "PS: %u", (pcode & 0x80) >> 7);
+
+ proto_tree_add_item (tree, hf_pagecode, tvb, offset, 1, 0);
+ proto_tree_add_text (tree, tvb, offset+1, 1, "Page Length: %u",
+ plen);
+
+ if (!tvb_bytes_exist (tvb, offset, plen)) {
+ /* XXX - why not just drive on and throw an exception? */
+ return (plen + 2);
+ }
+
+ if (!(*dissect_modepage)(tvb, pinfo, tree, offset,
+ (guint8) (pcode & SCSI_MS_PCODE_BITS))) {
+ proto_tree_add_text (tree, tvb, offset+2, plen,
+ "Unknown Page");
+ }
+ return (plen+2);
+}
+
+static void
+dissect_scsi_modeselect6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb,
+ scsi_device_type devtype, guint payload_len)
+{
+ guint8 flags;
+ guint tot_len, desclen, plen;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_modesel_flags, tvb, offset, 1,
+ flags, "PF = %u, SP = %u", flags & 0x10,
+ flags & 0x1);
+ proto_tree_add_item (tree, hf_scsi_paramlen, tvb, offset+3, 1, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else {
+ /* Mode Parameter has the following format:
+ * Mode Parameter Header
+ * - Mode Data Len, Medium Type, Dev Specific Parameter,
+ * Blk Desc Len
+ * Block Descriptor (s)
+ * - Number of blocks, density code, block length
+ * Page (s)
+ * - Page code, Page length, Page Parameters
+ */
+ if (payload_len < 1)
+ return;
+ tot_len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1, "Mode Data Length: %u",
+ tot_len);
+ offset += 1;
+ payload_len -= 1;
+ /* The mode data length is reserved for MODE SELECT, so we just
+ use the payload length. */
+
+ if (payload_len < 1)
+ return;
+ switch (devtype) {
+
+ case SCSI_DEV_SBC:
+ proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: %s",
+ val_to_str(tvb_get_guint8 (tvb, offset),
+ scsi_modesense_medtype_sbc_val,
+ "Unknown (0x%02x)"));
+ break;
+
+ default:
+ proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ break;
+ }
+ offset += 1;
+ payload_len -= 1;
+
+ if (payload_len < 1)
+ return;
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Device-Specific Parameter: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+ payload_len -= 1;
+
+ if (payload_len < 1)
+ return;
+ desclen = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Block Descriptor Length: %u", desclen);
+ offset += 1;
+ payload_len -= 1;
+
+ if (!dissect_scsi_blockdescs (tvb, pinfo, tree, offset, payload_len,
+ desclen, devtype, FALSE))
+ return;
+ offset += desclen;
+ payload_len -= desclen;
+
+ /* offset points to the start of the mode page */
+ while ((payload_len > 0) && tvb_bytes_exist (tvb, offset, 2)) {
+ plen = dissect_scsi_modepage (tvb, pinfo, tree, offset, devtype);
+ offset += plen;
+ payload_len -= plen;
+ }
+ }
+}
+
+static void
+dissect_scsi_modeselect10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb,
+ scsi_device_type devtype, guint payload_len)
+{
+ guint8 flags;
+ gboolean longlba;
+ guint tot_len, desclen, plen;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_modesel_flags, tvb, offset, 1,
+ flags, "PF = %u, SP = %u", flags & 0x10,
+ flags & 0x1);
+ proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else {
+ /* Mode Parameter has the following format:
+ * Mode Parameter Header
+ * - Mode Data Len, Medium Type, Dev Specific Parameter,
+ * Blk Desc Len
+ * Block Descriptor (s)
+ * - Number of blocks, density code, block length
+ * Page (s)
+ * - Page code, Page length, Page Parameters
+ */
+ if (payload_len < 1)
+ return;
+ tot_len = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 2, "Mode Data Length: %u",
+ tot_len);
+ offset += 2;
+ payload_len -= 2;
+ /* The mode data length is reserved for MODE SELECT, so we just
+ use the payload length. */
+
+ if (payload_len < 1)
+ return;
+ switch (devtype) {
+
+ case SCSI_DEV_SBC:
+ proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: %s",
+ val_to_str(tvb_get_guint8 (tvb, offset),
+ scsi_modesense_medtype_sbc_val,
+ "Unknown (0x%02x)"));
+ break;
+
+ default:
+ proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ break;
+ }
+ offset += 1;
+ payload_len -= 1;
+
+ if (payload_len < 1)
+ return;
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Device-Specific Parameter: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+ payload_len -= 1;
+
+ if (payload_len < 1)
+ return;
+ longlba = tvb_get_guint8 (tvb, offset) & 0x1;
+ proto_tree_add_text (tree, tvb, offset, 1, "LongLBA: %u", longlba);
+ offset += 2; /* skip LongLBA byte and reserved byte */
+ payload_len -= 2;
+
+ if (payload_len < 1)
+ return;
+ desclen = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Block Descriptor Length: %u", desclen);
+ offset += 2;
+ payload_len -= 2;
+
+ if (!dissect_scsi_blockdescs (tvb, pinfo, tree, offset, payload_len,
+ desclen, devtype, longlba))
+ return;
+ offset += desclen;
+ payload_len -= desclen;
+
+ /* offset points to the start of the mode page */
+ while ((payload_len > 0) && tvb_bytes_exist (tvb, offset, 2)) {
+ plen = dissect_scsi_modepage (tvb, pinfo, tree, offset, devtype);
+ offset += plen;
+ payload_len -= plen;
+ }
+ }
+}
+
+static void
+dissect_scsi_pagecode (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset,
+ scsi_device_type devtype)
+{
+ guint8 pcode;
+ gchar *valstr;
+ int hf_pagecode;
+
+ pcode = tvb_get_guint8 (tvb, offset);
+ if ((valstr = match_strval (pcode & SCSI_MS_PCODE_BITS,
+ scsi_spc2_modepage_val)) == NULL) {
+ /*
+ * This isn't a generic mode page that applies to all SCSI
+ * device types; try to interpret it based on what we deduced,
+ * or were told, the device type is.
+ */
+ switch (devtype) {
+ case SCSI_DEV_SBC:
+ hf_pagecode = hf_scsi_sbcpagecode;
+ break;
+
+ case SCSI_DEV_SSC:
+ hf_pagecode = hf_scsi_sscpagecode;
+ break;
+
+ case SCSI_DEV_SMC:
+ hf_pagecode = hf_scsi_smcpagecode;
+ break;
+
+ default:
+ hf_pagecode = hf_scsi_spcpagecode;
+ break;
+ }
+ } else {
+ hf_pagecode = hf_scsi_spcpagecode;
+ }
+ proto_tree_add_uint (tree, hf_pagecode, tvb, offset, 1, pcode);
+}
+
+static void
+dissect_scsi_modesense6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb,
+ scsi_device_type devtype, guint payload_len)
+{
+ guint8 flags;
+ guint tot_len, desclen, plen;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_modesns_flags, tvb, offset, 1,
+ flags, "DBD = %u", flags & 0x8);
+ proto_tree_add_item (tree, hf_scsi_modesns_pc, tvb, offset+1, 1, 0);
+ dissect_scsi_pagecode (tvb, pinfo, tree, offset+1, devtype);
+ proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else {
+ /* Mode sense response has the following format:
+ * Mode Parameter Header
+ * - Mode Data Len, Medium Type, Dev Specific Parameter,
+ * Blk Desc Len
+ * Block Descriptor (s)
+ * - Number of blocks, density code, block length
+ * Page (s)
+ * - Page code, Page length, Page Parameters
+ */
+ tot_len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1, "Mode Data Length: %u",
+ tot_len);
+ offset += 1;
+
+ /* The actual payload is the min of the length in the response & the
+ * space allocated by the initiator as specified in the request.
+ *
+ * XXX - the payload length includes the length field, so we
+ * really should subtract the length of the length field from
+ * the payload length - but can it really be zero here?
+ */
+ if (payload_len && (tot_len > payload_len))
+ tot_len = payload_len;
+
+ if (tot_len < 1)
+ return;
+ proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+ tot_len -= 1;
+
+ if (tot_len < 1)
+ return;
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Device-Specific Parameter: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+ tot_len -= 1;
+
+ if (tot_len < 1)
+ return;
+ desclen = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Block Descriptor Length: %u", desclen);
+ offset += 1;
+ tot_len -= 1;
+
+ if (!dissect_scsi_blockdescs (tvb, pinfo, tree, offset, tot_len,
+ desclen, devtype, FALSE))
+ return;
+ offset += desclen;
+ tot_len -= desclen;
+
+ /* offset points to the start of the mode page */
+ while ((tot_len > 0) && tvb_bytes_exist (tvb, offset, 2)) {
+ plen = dissect_scsi_modepage (tvb, pinfo, tree, offset, devtype);
+ offset += plen;
+ tot_len -= plen;
+ }
+ }
+}
+
+static void
+dissect_scsi_modesense10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb,
+ scsi_device_type devtype, guint payload_len)
+{
+ guint8 flags;
+ gboolean longlba;
+ guint tot_len, desclen, plen;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_modesns_flags, tvb, offset, 1,
+ flags, "LLBAA = %u, DBD = %u", flags & 0x10,
+ flags & 0x8);
+ proto_tree_add_item (tree, hf_scsi_modesns_pc, tvb, offset+1, 1, 0);
+ dissect_scsi_pagecode (tvb, pinfo, tree, offset+1, devtype);
+ proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else {
+ /* Mode sense response has the following format:
+ * Mode Parameter Header
+ * - Mode Data Len, Medium Type, Dev Specific Parameter,
+ * Blk Desc Len
+ * Block Descriptor (s)
+ * - Number of blocks, density code, block length
+ * Page (s)
+ * - Page code, Page length, Page Parameters
+ */
+ tot_len = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 2, "Mode Data Length: %u",
+ tot_len);
+ offset += 2;
+ /* The actual payload is the min of the length in the response & the
+ * space allocated by the initiator as specified in the request.
+ *
+ * XXX - the payload length includes the length field, so we
+ * really should subtract the length of the length field from
+ * the payload length - but can it really be zero here?
+ */
+ if (payload_len && (tot_len > payload_len))
+ tot_len = payload_len;
+
+ if (tot_len < 1)
+ return;
+ proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+ tot_len -= 1;
+
+ if (tot_len < 1)
+ return;
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Device-Specific Parameter: 0x%02x",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+ tot_len -= 1;
+
+ if (tot_len < 1)
+ return;
+ longlba = tvb_get_guint8 (tvb, offset) & 0x1;
+ proto_tree_add_text (tree, tvb, offset, 1, "LongLBA: %u", longlba);
+ offset += 2; /* skip LongLBA byte and reserved byte */
+ tot_len -= 2;
+
+ if (tot_len < 1)
+ return;
+ desclen = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Block Descriptor Length: %u", desclen);
+ offset += 2;
+ tot_len -= 2;
+
+ if (!dissect_scsi_blockdescs (tvb, pinfo, tree, offset, tot_len,
+ desclen, devtype, longlba))
+ return;
+ offset += desclen;
+ tot_len -= desclen;
+
+ /* offset points to the start of the mode page */
+ while ((tot_len > 0) && tvb_bytes_exist (tvb, offset, 2)) {
+ plen = dissect_scsi_modepage (tvb, pinfo, tree, offset, devtype);
+ offset += plen;
+ tot_len -= plen;
+ }
+ }
+}
+
+static void
+dissect_scsi_persresvin (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb, scsi_task_data_t *cdata,
+ guint payload_len)
+{
+ guint8 flags;
+ int numrec, i;
+ guint len;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ proto_tree_add_item (tree, hf_scsi_persresvin_svcaction, tvb, offset+1,
+ 1, 0);
+ proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ /* We store the service action since we want to interpret the data */
+ cdata->flags = tvb_get_guint8 (tvb, offset+1);
+ }
+ else {
+ if (cdata) {
+ flags = cdata->flags;
+ }
+ else {
+ flags = 0xFF;
+ }
+ proto_tree_add_text (tree, tvb, offset, 4, "Generation Number: 0x%08x",
+ tvb_get_ntohl (tvb, offset));
+ len = tvb_get_ntohl (tvb, offset+4);
+ proto_tree_add_text (tree, tvb, offset, 4, "Additional Length: %u",
+ len);
+ len = (payload_len > len) ? len : payload_len;
+
+ if ((flags & 0x1F) == SCSI_SPC2_RESVIN_SVCA_RDKEYS) {
+ /* XXX - what if len is < 8? That may be illegal, but
+ that doesn't make it impossible.... */
+ numrec = (len - 8)/8;
+ offset += 8;
+
+ for (i = 0; i < numrec; i++) {
+ proto_tree_add_item (tree, hf_scsi_persresv_key, tvb, offset,
+ 8, 0);
+ offset -= 8;
+ }
+ }
+ else if ((flags & 0x1F) == SCSI_SPC2_RESVIN_SVCA_RDRESV) {
+ proto_tree_add_item (tree, hf_scsi_persresv_key, tvb, offset+8,
+ 8, 0);
+ proto_tree_add_item (tree, hf_scsi_persresv_scopeaddr, tvb,
+ offset+8, 4, 0);
+ proto_tree_add_item (tree, hf_scsi_persresv_scope, tvb, offset+13,
+ 1, 0);
+ proto_tree_add_item (tree, hf_scsi_persresv_type, tvb, offset+13,
+ 1, 0);
+ }
+ }
+}
+
+static void
+dissect_scsi_persresvout (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb, scsi_task_data_t *cdata _U_,
+ guint payload_len _U_)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ proto_tree_add_item (tree, hf_scsi_persresvin_svcaction, tvb, offset,
+ 1, 0);
+ proto_tree_add_item (tree, hf_scsi_persresv_scope, tvb, offset+1, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_persresv_type, tvb, offset+1, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else {
+ }
+}
+
+static void
+dissect_scsi_release6 (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_release10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_release_flags, tvb, offset, 1,
+ flags,
+ "Flags: 3rd Party ID = %u, LongID = %u",
+ flags & 0x10, flags & 0x2);
+ if ((flags & 0x12) == 0x10) {
+ proto_tree_add_item (tree, hf_scsi_release_thirdpartyid, tvb,
+ offset+2, 1, 0);
+ }
+ proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_reportdeviceid (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
+ proto_tree *tree _U_, guint offset _U_,
+ gboolean isreq _U_, gboolean iscdb _U_)
+{
+
+}
+
+static void
+dissect_scsi_reportluns (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb, guint payload_len)
+{
+ guint8 flags;
+ guint listlen, i;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ proto_tree_add_item (tree, hf_scsi_alloclen32, tvb, offset+5, 4, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+10);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else if (!isreq) {
+ listlen = tvb_get_ntohl (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 4, "LUN List Length: %u",
+ listlen);
+ offset += 8;
+ payload_len -= 8;
+ if (payload_len != 0) {
+ listlen = (listlen < payload_len) ? listlen : payload_len;
+ }
+
+ for (i = 0; i < listlen/8; i++) {
+ if (!tvb_get_guint8 (tvb, offset))
+ proto_tree_add_item (tree, hf_scsi_rluns_lun, tvb, offset+1, 1,
+ 0);
+ else
+ proto_tree_add_item (tree, hf_scsi_rluns_multilun, tvb, offset,
+ 8, 0);
+ offset += 8;
+ }
+ }
+}
+
+static void
+dissect_scsi_reqsense (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_reserve6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_reserve10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_release_flags, tvb, offset, 1,
+ flags,
+ "Flags: 3rd Party ID = %u, LongID = %u",
+ flags & 0x10, flags & 0x2);
+ if ((flags & 0x12) == 0x10) {
+ proto_tree_add_item (tree, hf_scsi_release_thirdpartyid, tvb,
+ offset+2, 1, 0);
+ }
+ proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_startstopunit (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq _U_,
+ gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree || !iscdb)
+ return;
+
+ proto_tree_add_boolean (tree, hf_scsi_ssu_immed, tvb, offset, 1, 0);
+ proto_tree_add_uint (tree, hf_scsi_ssu_pwr_cond, tvb, offset+3, 1, 0);
+ proto_tree_add_boolean (tree, hf_scsi_ssu_loej, tvb, offset+3, 1, 0);
+ proto_tree_add_boolean (tree, hf_scsi_ssu_start, tvb, offset+3, 1, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+}
+
+static void
+dissect_scsi_testunitrdy (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_formatunit (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_uint_format (tree, hf_scsi_formatunit_flags, tvb, offset,
+ 1, flags,
+ "Flags: Longlist = %u, FMTDATA = %u, CMPLIST = %u",
+ flags & 0x20, flags & 0x8, flags & 0x4);
+ proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_formatunit_vendor, tvb, offset+1,
+ 1, 0);
+ proto_tree_add_item (tree, hf_scsi_formatunit_interleave, tvb, offset+2,
+ 2, 0);
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_sbc2_rdwr6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (isreq) {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%06x, Len: %u)",
+ tvb_get_ntoh24 (tvb, offset),
+ tvb_get_guint8 (tvb, offset+3));
+ }
+
+ if (tree && isreq && iscdb) {
+ proto_tree_add_item (tree, hf_scsi_rdwr6_lba, tvb, offset, 3, 0);
+ proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+3, 1, 0);
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_rdwr10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (isreq) {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%08x, Len: %u)",
+ tvb_get_ntohl (tvb, offset+1),
+ tvb_get_ntohs (tvb, offset+6));
+ }
+
+ if (tree && isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
+ flags,
+ "DPO = %u, FUA = %u, RelAddr = %u",
+ flags & 0x10, flags & 0x8, flags & 0x1);
+ proto_tree_add_item (tree, hf_scsi_rdwr10_lba, tvb, offset+1, 4, 0);
+ proto_tree_add_item (tree, hf_scsi_rdwr10_xferlen, tvb, offset+6, 2, 0);
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_rdwr12 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (isreq) {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%08x, Len: %u)",
+ tvb_get_ntohl (tvb, offset+1),
+ tvb_get_ntohl (tvb, offset+5));
+ }
+
+ if (tree && isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
+ flags,
+ "DPO = %u, FUA = %u, RelAddr = %u",
+ flags & 0x10, flags & 0x8, flags & 0x1);
+ proto_tree_add_item (tree, hf_scsi_rdwr10_lba, tvb, offset+1, 4, 0);
+ proto_tree_add_item (tree, hf_scsi_rdwr12_xferlen, tvb, offset+5, 4, 0);
+ flags = tvb_get_guint8 (tvb, offset+10);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_rdwr16 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (tree && isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
+ flags,
+ "DPO = %u, FUA = %u, RelAddr = %u",
+ flags & 0x10, flags & 0x8, flags & 0x1);
+ proto_tree_add_item (tree, hf_scsi_rdwr16_lba, tvb, offset+1, 8, 0);
+ proto_tree_add_item (tree, hf_scsi_rdwr12_xferlen, tvb, offset+9, 4, 0);
+ flags = tvb_get_guint8 (tvb, offset+14);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+14, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_readcapacity (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb)
+{
+ guint8 flags;
+ guint32 len, block_len, tot_len;
+ char *un;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_readcapacity_flags, tvb,
+ offset, 1, flags,
+ "LongLBA = %u, RelAddr = %u",
+ flags & 0x2, flags & 0x1);
+ proto_tree_add_item (tree, hf_scsi_readcapacity_lba, tvb, offset+1,
+ 4, 0);
+ proto_tree_add_item (tree, hf_scsi_readcapacity_pmi, tvb, offset+7,
+ 1, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else if (!iscdb) {
+ len = tvb_get_ntohl (tvb, offset);
+ block_len = tvb_get_ntohl (tvb, offset+4);
+ tot_len=((len/1024)*block_len)/1024; /*MB*/
+ un="MB";
+ if(tot_len>20000){
+ tot_len/=1024;
+ un="GB";
+ }
+ proto_tree_add_text (tree, tvb, offset, 4, "LBA: %u (%u %s)",
+ len, tot_len, un);
+ proto_tree_add_text (tree, tvb, offset+4, 4, "Block Length: %u bytes",
+ block_len);
+ }
+}
+
+static void
+dissect_scsi_readdefdata10 (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_readdefdata_flags, tvb,
+ offset, 1, flags, "PLIST = %u, GLIST = %u",
+ flags & 0x10, flags & 0x8);
+ proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_readdefdata12 (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_readdefdata_flags, tvb,
+ offset, 1, flags, "PLIST = %u, GLIST = %u",
+ flags & 0x10, flags & 0x8);
+ proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_alloclen32, tvb, offset+5, 4, 0);
+ flags = tvb_get_guint8 (tvb, offset+10);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_reassignblks (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb)
+{
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+
+ proto_tree_add_uint_format (tree, hf_scsi_reassignblks_flags, tvb,
+ offset, 1, flags,
+ "LongLBA = %u, LongList = %u",
+ flags & 0x2, flags & 0x1);
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_senddiag (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb _U_)
+{
+ guint8 flags;
+
+ if (!tree && !isreq)
+ return;
+
+ proto_tree_add_uint (tree, hf_scsi_senddiag_st_code, tvb, offset, 1, 0);
+ proto_tree_add_boolean (tree, hf_scsi_senddiag_pf, tvb, offset, 1, 0);
+ proto_tree_add_boolean (tree, hf_scsi_senddiag_st, tvb, offset, 1, 0);
+ proto_tree_add_boolean (tree, hf_scsi_senddiag_devoff, tvb, offset, 1, 0);
+ proto_tree_add_boolean (tree, hf_scsi_senddiag_unitoff, tvb, offset, 1, 0);
+ proto_tree_add_uint (tree, hf_scsi_paramlen16, tvb, offset+2, 2, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+}
+
+static void
+dissect_scsi_writebuffer (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb _U_)
+{
+ guint8 flags;
+
+ if (!tree && !isreq)
+ return;
+
+ proto_tree_add_uint (tree, hf_scsi_wb_mode, tvb, offset, 1, 0);
+ proto_tree_add_uint (tree, hf_scsi_wb_bufferid, tvb, offset+1, 1, 0);
+ proto_tree_add_uint (tree, hf_scsi_wb_bufoffset, tvb, offset+2, 3, 0);
+ proto_tree_add_uint (tree, hf_scsi_paramlen24, tvb, offset+5, 3, 0);
+
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+}
+
+static void
+dissect_scsi_varlencdb (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ proto_tree_add_item (tree, hf_scsi_control, tvb, offset, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_add_cdblen, tvb, offset+6, 1, 0);
+ proto_tree_add_item (tree, hf_scsi_svcaction, tvb, offset+7, 2, 0);
+
+ }
+}
+
+static void
+dissect_scsi_ssc2_read6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (isreq) {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "(Len: %u)",
+ tvb_get_ntoh24 (tvb, offset+1));
+ }
+
+ if (tree && isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "SILI: %u, FIXED: %u",
+ (flags & 0x02) >> 1, flags & 0x01);
+ proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 3, 0);
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_ssc2_write6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (isreq) {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "(Len: %u)",
+ tvb_get_ntoh24 (tvb, offset+1));
+ }
+
+ if (tree && isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "FIXED: %u", flags & 0x01);
+ proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 3,
+ FALSE);
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_ssc2_writefilemarks6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (isreq) {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "(Len: %u)",
+ tvb_get_ntoh24 (tvb, offset+1));
+ }
+
+ if (tree && isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "WSMK: %u, IMMED: %u",
+ (flags & 0x02) >> 1, flags & 0x01);
+ proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 3,
+ FALSE);
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_ssc2_loadunload (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (isreq && iscdb) {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "(Immed: %u)",
+ tvb_get_guint8 (tvb, offset) & 0x01);
+
+ if (!tree)
+ return;
+
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Immed: %u", tvb_get_guint8 (tvb, offset) & 0x01);
+ flags = tvb_get_guint8 (tvb, offset+3);
+ proto_tree_add_text (tree, tvb, offset+3, 1,
+ "Hold: %u, EOT: %u, Reten: %u, Load: %u",
+ (flags & 0x08) >> 3, (flags & 0x04) >> 2,
+ (flags & 0x02) >> 1, (flags & 0x01));
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_ssc2_readblocklimits (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags, granularity;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else if (!iscdb) {
+ granularity = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1, "Granularity: %u (%u %s)",
+ granularity, 1 << granularity,
+ plurality(1 << granularity, "byte", "bytes"));
+ proto_tree_add_text (tree, tvb, offset+1, 3, "Maximum Block Length Limit: %u bytes",
+ tvb_get_ntoh24 (tvb, offset+1));
+ proto_tree_add_text (tree, tvb, offset+4, 2, "Minimum Block Length Limit: %u bytes",
+ tvb_get_ntohs (tvb, offset+4));
+ }
+}
+
+#define SHORT_FORM_BLOCK_ID 0x00
+#define SHORT_FORM_VENDOR_SPECIFIC 0x01
+#define LONG_FORM 0x06
+#define EXTENDED_FORM 0x08
+
+static const value_string service_action_vals[] = {
+ {SHORT_FORM_BLOCK_ID, "Short Form - Block ID"},
+ {SHORT_FORM_VENDOR_SPECIFIC, "Short Form - Vendor-Specific"},
+ {LONG_FORM, "Long Form"},
+ {EXTENDED_FORM, "Extended Form"},
+ {0, NULL}
+};
+
+#define BCU 0x20
+#define BYCU 0x10
+#define MPU 0x08
+#define BPU 0x04
+
+static void
+dissect_scsi_ssc2_readposition (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb,
+ scsi_task_data_t *cdata)
+{
+ gint service_action;
+ guint8 flags;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ service_action = tvb_get_guint8 (tvb, offset) & 0x1F;
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Service Action: %s",
+ val_to_str (service_action,
+ service_action_vals,
+ "Unknown (0x%02x)"));
+ /* Remember the service action so we can decode the reply */
+ if (cdata != NULL) {
+ cdata->flags = service_action;
+ }
+ proto_tree_add_text (tree, tvb, offset+6, 2,
+ "Parameter Len: %u",
+ tvb_get_ntohs (tvb, offset+6));
+ flags = tvb_get_guint8 (tvb, offset+8);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else if (!isreq) {
+ if (cdata)
+ service_action = cdata->flags;
+ else
+ service_action = -1; /* unknown */
+ switch (service_action) {
+ case SHORT_FORM_BLOCK_ID:
+ case SHORT_FORM_VENDOR_SPECIFIC:
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "BOP: %u, EOP: %u, BCU: %u, BYCU: %u, BPU: %u, PERR: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & BCU) >> 5, (flags & BYCU) >> 4,
+ (flags & BPU) >> 2, (flags & 0x02) >> 1);
+ offset += 1;
+
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Partition Number: %u",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+
+ offset += 2; /* reserved */
+
+ if (!(flags & BPU)) {
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "First Block Location: %u",
+ tvb_get_ntohl (tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Last Block Location: %u",
+ tvb_get_ntohl (tvb, offset));
+ offset += 4;
+ } else
+ offset += 8;
+
+ offset += 1; /* reserved */
+
+ if (!(flags & BCU)) {
+ proto_tree_add_text (tree, tvb, offset, 3,
+ "Number of Blocks in Buffer: %u",
+ tvb_get_ntoh24 (tvb, offset));
+ }
+ offset += 3;
+
+ if (!(flags & BYCU)) {
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Number of Bytes in Buffer: %u",
+ tvb_get_ntohl (tvb, offset));
+ }
+ offset += 4;
+ break;
+
+ case LONG_FORM:
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "BOP: %u, EOP: %u, MPU: %u, BPU: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & MPU) >> 3, (flags & BPU) >> 2);
+ offset += 1;
+
+ offset += 3; /* reserved */
+
+ if (!(flags & BPU)) {
+ proto_tree_add_text (tree, tvb, offset, 4,
+ "Partition Number: %u",
+ tvb_get_ntohl (tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text (tree, tvb, offset, 8,
+ "Block Number: %s",
+ u64toa (tvb_get_ptr (tvb, offset, 8)));
+ offset += 8;
+ } else
+ offset += 12;
+
+ if (!(flags & MPU)) {
+ proto_tree_add_text (tree, tvb, offset, 8,
+ "File Number: %s",
+ u64toa (tvb_get_ptr (tvb, offset, 8)));
+ offset += 8;
+
+ proto_tree_add_text (tree, tvb, offset, 8,
+ "Set Number: %s",
+ u64toa (tvb_get_ptr (tvb, offset, 8)));
+ offset += 8;
+ } else
+ offset += 16;
+ break;
+
+ case EXTENDED_FORM:
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "BOP: %u, EOP: %u, BCU: %u, BYCU: %u, MPU: %u, BPU: %u, PERR: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & BCU) >> 5, (flags & BYCU) >> 4,
+ (flags & MPU) >> 3, (flags & BPU) >> 2,
+ (flags & 0x02) >> 1);
+ offset += 1;
+
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Partition Number: %u",
+ tvb_get_guint8 (tvb, offset));
+ offset += 1;
+
+ proto_tree_add_text (tree, tvb, offset, 2,
+ "Additional Length: %u",
+ tvb_get_ntohs (tvb, offset));
+ offset += 2;
+
+ offset += 1; /* reserved */
+
+ if (!(flags & BCU)) {
+ proto_tree_add_text (tree, tvb, offset, 3,
+ "Number of Blocks in Buffer: %u",
+ tvb_get_ntoh24 (tvb, offset));
+ }
+ offset += 3;
+
+ if (!(flags & BPU)) {
+ proto_tree_add_text (tree, tvb, offset, 8,
+ "First Block Location: %s",
+ u64toa (tvb_get_ptr (tvb, offset, 8)));
+ offset += 8;
+
+ proto_tree_add_text (tree, tvb, offset, 8,
+ "Last Block Location: %s",
+ u64toa (tvb_get_ptr (tvb, offset, 8)));
+ offset += 8;
+ } else
+ offset += 16;
+
+ offset += 1; /* reserved */
+
+ if (!(flags & BYCU)) {
+ proto_tree_add_text (tree, tvb, offset, 8,
+ "Number of Bytes in Buffer: %s",
+ u64toa (tvb_get_ptr (tvb, offset, 8)));
+ }
+ offset += 8;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+static void
+dissect_scsi_ssc2_rewind (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (isreq && iscdb) {
+ if (check_col (pinfo->cinfo, COL_INFO))
+ col_append_fstr (pinfo->cinfo, COL_INFO, "(Immed: %u)",
+ tvb_get_guint8 (tvb, offset) & 0x01);
+
+ if (!tree)
+ return;
+
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Immed: %u", tvb_get_guint8 (tvb, offset) & 0x01);
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+static void
+dissect_scsi_smc2_movemedium (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ guint offset, gboolean isreq, gboolean iscdb)
+{
+ guint8 flags;
+
+ if (tree && isreq && iscdb) {
+ proto_tree_add_text (tree, tvb, offset+1, 2,
+ "Medium Transport Address: %u",
+ tvb_get_ntohs (tvb, offset+1));
+ proto_tree_add_text (tree, tvb, offset+3, 2,
+ "Source Address: %u",
+ tvb_get_ntohs (tvb, offset+3));
+ proto_tree_add_text (tree, tvb, offset+5, 2,
+ "Destination Address: %u",
+ tvb_get_ntohs (tvb, offset+5));
+ flags = tvb_get_guint8 (tvb, offset+9);
+ proto_tree_add_text (tree, tvb, offset+9, 1,
+ "INV: %u", flags & 0x01);
+ flags = tvb_get_guint8 (tvb, offset+10);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+}
+
+#define MT_ELEM 0x1
+#define ST_ELEM 0x2
+#define I_E_ELEM 0x3
+#define DT_ELEM 0x4
+
+static const value_string element_type_code_vals[] = {
+ {0x0, "All element types"},
+ {MT_ELEM, "Medium transport element"},
+ {ST_ELEM, "Storage element"},
+ {I_E_ELEM, "Import/export element"},
+ {DT_ELEM, "Data transfer element"},
+ {0, NULL}
+};
+
+#define PVOLTAG 0x80
+#define AVOLTAG 0x40
+
+#define EXCEPT 0x04
+
+#define ID_VALID 0x20
+#define LU_VALID 0x10
+
+#define SVALID 0x80
+
+static void
+dissect_scsi_smc2_volume_tag (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset,
+ const char *name)
+{
+ char volid[32+1];
+ char *p;
+
+ tvb_memcpy (tvb, (guint8 *)volid, offset, 32);
+ p = &volid[32];
+ for (;;) {
+ *p = '\0';
+ if (p == volid)
+ break;
+ if (*(p - 1) != ' ')
+ break;
+ p--;
+ }
+ proto_tree_add_text (tree, tvb, offset, 36,
+ "%s: Volume Identification = \"%s\", Volume Sequence Number = %u",
+ name, volid, tvb_get_ntohs (tvb, offset+34));
+}
+
+static void
+dissect_scsi_smc2_element (tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, guint offset,
+ guint elem_bytecnt, guint8 elem_type,
+ guint8 voltag_flags)
+{
+ guint8 flags;
+ guint8 ident_len;
+
+ if (elem_bytecnt < 2)
+ return;
+ proto_tree_add_text (tree, tvb, offset, 2,
+ "Element Address: %u",
+ tvb_get_ntohs (tvb, offset));
+ offset += 2;
+ elem_bytecnt -= 2;
+
+ if (elem_bytecnt < 1)
+ return;
+ flags = tvb_get_guint8 (tvb, offset);
+ switch (elem_type) {
+
+ case MT_ELEM:
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "EXCEPT: %u, FULL: %u",
+ (flags & EXCEPT) >> 2, flags & 0x01);
+ break;
+
+ case ST_ELEM:
+ case DT_ELEM:
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "ACCESS: %u, EXCEPT: %u, FULL: %u",
+ (flags & 0x08) >> 3,
+ (flags & EXCEPT) >> 2, flags & 0x01);
+ break;
+
+ case I_E_ELEM:
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "cmc: %u, INENAB: %u, EXENAB: %u, ACCESS: %u, EXCEPT: %u, IMPEXP: %u, FULL: %u",
+ (flags & 0x40) >> 6,
+ (flags & 0x20) >> 5,
+ (flags & 0x10) >> 4,
+ (flags & 0x08) >> 3,
+ (flags & EXCEPT) >> 2,
+ (flags & 0x02) >> 1,
+ flags & 0x01);
+ break;
+ }
+ offset += 1;
+ elem_bytecnt -= 1;
+
+ if (elem_bytecnt < 1)
+ return;
+ offset += 1; /* reserved */
+ elem_bytecnt -= 1;
+
+ if (elem_bytecnt < 2)
+ return;
+ if (flags & EXCEPT) {
+ proto_tree_add_text (tree, tvb, offset, 2,
+ "Additional Sense Code+Qualifier: %s",
+ val_to_str (tvb_get_ntohs (tvb, offset),
+ scsi_asc_val, "Unknown (0x%04x)"));
+ }
+ offset += 2;
+ elem_bytecnt -= 2;
+
+ if (elem_bytecnt < 3)
+ return;
+ switch (elem_type) {
+
+ case DT_ELEM:
+ flags = tvb_get_guint8 (tvb, offset);
+ if (flags & LU_VALID) {
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "NOT BUS: %u, ID VALID: %u, LU VALID: 1, LUN: %u",
+ (flags & 0x80) >> 7,
+ (flags & ID_VALID) >> 5,
+ flags & 0x07);
+ } else if (flags & ID_VALID) {
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "ID VALID: 1, LU VALID: 0");
+ } else {
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "ID VALID: 0, LU VALID: 0");
+ }
+ offset += 1;
+ if (flags & ID_VALID) {
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "SCSI Bus Address: %u",
+ tvb_get_guint8 (tvb, offset));
+ }
+ offset += 1;
+ offset += 1; /* reserved */
+ break;
+
+ default:
+ offset += 3; /* reserved */
+ break;
+ }
+ elem_bytecnt -= 3;
+
+ if (elem_bytecnt < 3)
+ return;
+ flags = tvb_get_guint8 (tvb, offset);
+ if (flags & SVALID) {
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "SVALID: 1, INVERT: %u",
+ (flags & 0x40) >> 6);
+ offset += 1;
+ proto_tree_add_text (tree, tvb, offset, 2,
+ "Source Storage Element Address: %u",
+ tvb_get_ntohs (tvb, offset));
+ offset += 2;
+ } else {
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "SVALID: 0");
+ offset += 3;
+ }
+ elem_bytecnt -= 3;
+
+ if (voltag_flags & PVOLTAG) {
+ if (elem_bytecnt < 36)
+ return;
+ dissect_scsi_smc2_volume_tag (tvb, pinfo, tree, offset,
+ "Primary Volume Tag Information");
+ offset += 36;
+ elem_bytecnt -= 36;
+ }
+
+ if (voltag_flags & AVOLTAG) {
+ if (elem_bytecnt < 36)
+ return;
+ dissect_scsi_smc2_volume_tag (tvb, pinfo, tree, offset,
+ "Alternate Volume Tag Information");
+ offset += 36;
+ elem_bytecnt -= 36;
+ }
+
+ if (elem_bytecnt < 1)
+ return;
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Code Set: %s",
+ val_to_str (flags & 0x0F,
+ scsi_devid_codeset_val,
+ "Unknown (0x%02x)"));
+ offset += 1;
+ elem_bytecnt -= 1;
+
+ if (elem_bytecnt < 1)
+ return;
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Identifier Type: %s",
+ val_to_str ((flags & 0x0F),
+ scsi_devid_idtype_val,
+ "Unknown (0x%02x)"));
+ offset += 1;
+ elem_bytecnt -= 1;
+
+ if (elem_bytecnt < 1)
+ return;
+ offset += 1; /* reserved */
+ elem_bytecnt -= 1;
+
+ if (elem_bytecnt < 1)
+ return;
+ ident_len = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Identifier Length: %u",
+ ident_len);
+ offset += 1;
+ elem_bytecnt -= 1;
+
+ if (ident_len != 0) {
+ if (elem_bytecnt < ident_len)
+ return;
+ proto_tree_add_text (tree, tvb, offset, ident_len,
+ "Identifier: %s",
+ tvb_bytes_to_str (tvb, offset, ident_len));
+ offset += ident_len;
+ elem_bytecnt -= ident_len;
+ }
+ if (elem_bytecnt != 0) {
+ proto_tree_add_text (tree, tvb, offset, elem_bytecnt,
+ "Vendor-specific Data: %s",
+ tvb_bytes_to_str (tvb, offset, elem_bytecnt));
+ }
+}
+
+static void
+dissect_scsi_smc2_elements (tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint offset,
+ guint desc_bytecnt, guint8 elem_type,
+ guint8 voltag_flags, guint16 elem_desc_len)
+{
+ guint elem_bytecnt;
+
+ while (desc_bytecnt != 0) {
+ elem_bytecnt = elem_desc_len;
+ if (elem_bytecnt > desc_bytecnt)
+ elem_bytecnt = desc_bytecnt;
+ dissect_scsi_smc2_element (tvb, pinfo, tree, offset, elem_bytecnt,
+ elem_type, voltag_flags);
+ offset += elem_bytecnt;
+ desc_bytecnt -= elem_bytecnt;
+ }
+}
+
+static void
+dissect_scsi_smc2_readelementstatus (tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint offset, gboolean isreq,
+ gboolean iscdb)
+{
+ guint8 flags;
+ guint numelem, bytecnt, desc_bytecnt;
+ guint8 elem_type;
+ guint8 voltag_flags;
+ guint16 elem_desc_len;
+
+ if (!tree)
+ return;
+
+ if (isreq && iscdb) {
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "VOLTAG: %u, Element Type Code: %s",
+ (flags & 0x10) >> 4,
+ val_to_str (flags & 0xF, element_type_code_vals,
+ "Unknown (0x%x)"));
+ proto_tree_add_text (tree, tvb, offset+1, 2,
+ "Starting Element Address: %u",
+ tvb_get_ntohs (tvb, offset+1));
+ proto_tree_add_text (tree, tvb, offset+3, 2,
+ "Number of Elements: %u",
+ tvb_get_ntohs (tvb, offset+3));
+ flags = tvb_get_guint8 (tvb, offset+4);
+ proto_tree_add_text (tree, tvb, offset+4, 1,
+ "CURDATA: %u, DVCID: %u",
+ (flags & 0x02) >> 1, flags & 0x01);
+ proto_tree_add_text (tree, tvb, offset+5, 3,
+ "Allocation Length: %u",
+ tvb_get_ntoh24 (tvb, offset+5));
+ flags = tvb_get_guint8 (tvb, offset+10);
+ proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
+ flags,
+ "Vendor Unique = %u, NACA = %u, Link = %u",
+ flags & 0xC0, flags & 0x4, flags & 0x1);
+ }
+ else if (!isreq) {
+ proto_tree_add_text (tree, tvb, offset, 2,
+ "First Element Address Reported: %u",
+ tvb_get_ntohs (tvb, offset));
+ offset += 2;
+ numelem = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 2,
+ "Number of Elements Available: %u", numelem);
+ offset += 2;
+ offset += 1; /* reserved */
+ bytecnt = tvb_get_ntoh24 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 3,
+ "Byte Count of Report Available: %u", bytecnt);
+ offset += 3;
+ while (bytecnt != 0) {
+ if (bytecnt < 1)
+ break;
+ elem_type = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "Element Type Code: %s",
+ val_to_str (elem_type, element_type_code_vals,
+ "Unknown (0x%x)"));
+ offset += 1;
+ bytecnt -= 1;
+
+ if (bytecnt < 1)
+ break;
+ voltag_flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 1,
+ "PVOLTAG: %u, AVOLTAG: %u",
+ (voltag_flags & PVOLTAG) >> 7,
+ (voltag_flags & AVOLTAG) >> 6);
+ offset += 1;
+ bytecnt -= 1;
+
+ if (bytecnt < 2)
+ break;
+ elem_desc_len = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 2,
+ "Element Descriptor Length: %u",
+ elem_desc_len);
+ offset += 2;
+ bytecnt -= 2;
+
+ if (bytecnt < 1)
+ break;
+ offset += 1; /* reserved */
+ bytecnt -= 1;
+
+ if (bytecnt < 3)
+ break;
+ desc_bytecnt = tvb_get_ntoh24 (tvb, offset);
+ proto_tree_add_text (tree, tvb, offset, 3,
+ "Byte Count Of Descriptor Data Available: %u",
+ desc_bytecnt);
+ offset += 3;
+ bytecnt -= 3;
+
+ if (desc_bytecnt > bytecnt)
+ desc_bytecnt = bytecnt;
+ dissect_scsi_smc2_elements (tvb, pinfo, tree, offset,
+ desc_bytecnt, elem_type,
+ voltag_flags, elem_desc_len);
+ offset += desc_bytecnt;
+ bytecnt -= desc_bytecnt;
+ }
+ }
+}
+
+void
+dissect_scsi_rsp (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
+ proto_tree *tree _U_)
+{
+ /* Nothing to do here, just blow up the data structures for this SCSI
+ * transaction
+ if (tree)
+ scsi_end_task (pinfo);
+ */
+}
+
+void
+dissect_scsi_snsinfo (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint offset, guint snslen)
+{
+ guint8 flags;
+ proto_item *ti;
+ proto_tree *sns_tree;
+
+ scsi_end_task (pinfo);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
+ snslen, "SCSI: SNS Info");
+ sns_tree = proto_item_add_subtree (ti, ett_scsi);
+
+ flags = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_text (sns_tree, tvb, offset, 1, "Valid: %u",
+ (flags & 0x80) >> 7);
+ proto_tree_add_item (sns_tree, hf_scsi_sns_errtype, tvb, offset, 1, 0);
+ flags = tvb_get_guint8 (tvb, offset+2);
+ proto_tree_add_text (sns_tree, tvb, offset+2, 1,
+ "Filemark: %u, EOM: %u, ILI: %u",
+ (flags & 0x80) >> 7, (flags & 0x40) >> 6,
+ (flags & 0x20) >> 5);
+ proto_tree_add_item (sns_tree, hf_scsi_snskey, tvb, offset+2, 1, 0);
+ proto_tree_add_item (sns_tree, hf_scsi_snsinfo, tvb, offset+3, 4, 0);
+ proto_tree_add_item (sns_tree, hf_scsi_addlsnslen, tvb, offset+7, 1, 0);
+ proto_tree_add_text (sns_tree, tvb, offset+8, 4,
+ "Command-Specific Information: %s",
+ tvb_bytes_to_str (tvb, offset+8, 4));
+ proto_tree_add_item (sns_tree, hf_scsi_ascascq, tvb, offset+12, 2, 0);
+ proto_tree_add_item_hidden (sns_tree, hf_scsi_asc, tvb, offset+12, 1, 0);
+ proto_tree_add_item_hidden (sns_tree, hf_scsi_ascq, tvb, offset+13,
+ 1, 0);
+ proto_tree_add_item (sns_tree, hf_scsi_fru, tvb, offset+14, 1, 0);
+ proto_tree_add_item (sns_tree, hf_scsi_sksv, tvb, offset+15, 1, 0);
+ proto_tree_add_text (sns_tree, tvb, offset+15, 3,
+ "Sense Key Specific: %s",
+ tvb_bytes_to_str (tvb, offset+15, 3));
+ }
+}
+
+void
+dissect_scsi_cdb (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint start, guint cdblen, gint devtype_arg)
+{
+ int offset = start;
+ proto_item *ti;
+ proto_tree *scsi_tree = NULL;
+ guint8 opcode;
+ scsi_device_type devtype;
+ scsi_cmnd_type cmd = 0; /* 0 is undefined type */
+ gchar *valstr;
+ scsi_task_data_t *cdata;
+ scsi_devtype_key_t dkey;
+ scsi_devtype_data_t *devdata;
+
+ opcode = tvb_get_guint8 (tvb, offset);
+
+ if (devtype_arg != SCSI_DEV_UNKNOWN)
+ devtype = devtype_arg;
+ else {
+ /*
+ * Try to look up the device data for this device.
+ *
+ * We don't use COPY_ADDRESS because "dkey.devid" isn't
+ * persistent, and therefore it can point to the stuff
+ * in "pinfo->src". (Were we to use COPY_ADDRESS, we'd
+ * have to free the address data it allocated before we return.)
+ */
+ dkey.devid = pinfo->dst;
+
+ devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
+ &dkey);
+ if (devdata != NULL) {
+ devtype = devdata->devtype;
+ }
+ else {
+ devtype = (scsi_device_type)scsi_def_devtype;
+ }
+ }
+
+ if ((valstr = match_strval (opcode, scsi_spc2_val)) == NULL) {
+ /*
+ * This isn't a generic command that applies to all SCSI
+ * device types; try to interpret it based on what we deduced,
+ * or were told, the device type is.
+ *
+ * Right now, the only choices are SBC or SSC. If we ever expand
+ * this to decode other device types, this piece of code needs to
+ * be modified.
+ */
+ switch (devtype) {
+ case SCSI_DEV_SBC:
+ valstr = match_strval (opcode, scsi_sbc2_val);
+ cmd = SCSI_CMND_SBC2;
+ break;
+
+ case SCSI_DEV_SSC:
+ valstr = match_strval (opcode, scsi_ssc2_val);
+ cmd = SCSI_CMND_SSC2;
+ break;
+
+ case SCSI_DEV_SMC:
+ valstr = match_strval (opcode, scsi_smc2_val);
+ cmd = SCSI_CMND_SMC2;
+ break;
+
+ default:
+ cmd = SCSI_CMND_SPC2;
+ break;
+ }
+ }
+ else {
+ cmd = SCSI_CMND_SPC2;
+ }
+
+ if (valstr != NULL) {
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "SCSI: %s", valstr);
+ }
+ }
+ else {
+ if (check_col (pinfo->cinfo, COL_INFO)) {
+ col_add_fstr (pinfo->cinfo, COL_INFO, "SCSI Command: 0x%02x", opcode);
+ }
+ }
+
+ cdata = scsi_new_task (pinfo);
+
+ if (cdata) {
+ cdata->opcode = opcode;
+ cdata->cmd = cmd;
+ cdata->devtype = devtype;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, start,
+ cdblen, "SCSI CDB");
+ scsi_tree = proto_item_add_subtree (ti, ett_scsi);
+
+ if (valstr != NULL) {
+ if (cmd == SCSI_CMND_SPC2) {
+ proto_tree_add_uint_format (scsi_tree, hf_scsi_spcopcode, tvb,
+ offset, 1,
+ tvb_get_guint8 (tvb, offset),
+ "Opcode: %s (0x%02x)", valstr,
+ opcode);
+ }
+ else if (cmd == SCSI_CMND_SBC2) {
+ proto_tree_add_uint_format (scsi_tree, hf_scsi_sbcopcode, tvb,
+ offset, 1,
+ tvb_get_guint8 (tvb, offset),
+ "Opcode: %s (0x%02x)", valstr,
+ opcode);
+ }
+ else if (cmd == SCSI_CMND_SSC2) {
+ proto_tree_add_uint_format (scsi_tree, hf_scsi_sscopcode, tvb,
+ offset, 1,
+ tvb_get_guint8 (tvb, offset),
+ "Opcode: %s (0x%02x)", valstr,
+ opcode);
+ }
+ else if (cmd == SCSI_CMND_SMC2) {
+ proto_tree_add_uint_format (scsi_tree, hf_scsi_smcopcode, tvb,
+ offset, 1,
+ tvb_get_guint8 (tvb, offset),
+ "Opcode: %s (0x%02x)", valstr,
+ opcode);
+ }
+ else {
+ /* "Can't happen" */
+ g_assert_not_reached();
+ }
+ }
+ else {
+ proto_tree_add_item (scsi_tree, hf_scsi_spcopcode, tvb, offset, 1, 0);
+ }
+ }
+
+ switch (cmd) {
+ case SCSI_CMND_SPC2:
+ switch (opcode) {
+ case SCSI_SPC2_INQUIRY:
+ dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE, 0, cdata);
+ break;
+
+ case SCSI_SPC2_EXTCOPY:
+ dissect_scsi_extcopy (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_LOGSELECT:
+ dissect_scsi_logselect (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_LOGSENSE:
+ dissect_scsi_logsense (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_MODESELECT6:
+ dissect_scsi_modeselect6 (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE, devtype, 0);
+ break;
+
+ case SCSI_SPC2_MODESELECT10:
+ dissect_scsi_modeselect10 (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE, devtype, 0);
+ break;
+
+ case SCSI_SPC2_MODESENSE6:
+ dissect_scsi_modesense6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE, devtype, 0);
+ break;
+
+ case SCSI_SPC2_MODESENSE10:
+ dissect_scsi_modesense10 (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE, devtype, 0);
+ break;
+
+ case SCSI_SPC2_PERSRESVIN:
+ dissect_scsi_persresvin (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE, cdata, 0);
+ break;
+
+ case SCSI_SPC2_PERSRESVOUT:
+ dissect_scsi_persresvout (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE, cdata, 0);
+ break;
+
+ case SCSI_SPC2_RELEASE6:
+ dissect_scsi_release6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_RELEASE10:
+ dissect_scsi_release10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_REPORTDEVICEID:
+ dissect_scsi_reportdeviceid (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE);
+ break;
+
+ case SCSI_SPC2_REPORTLUNS:
+ dissect_scsi_reportluns (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE, 0);
+ break;
+
+ case SCSI_SPC2_REQSENSE:
+ dissect_scsi_reqsense (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_RESERVE6:
+ dissect_scsi_reserve6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_RESERVE10:
+ dissect_scsi_reserve10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_SENDDIAG:
+ dissect_scsi_senddiag (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_TESTUNITRDY:
+ dissect_scsi_testunitrdy (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE);
+ break;
+
+ case SCSI_SPC2_WRITEBUFFER:
+ dissect_scsi_writebuffer (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SPC2_VARLENCDB:
+ dissect_scsi_varlencdb (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE);
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+ break;
+
+ case SCSI_CMND_SBC2:
+ switch (opcode) {
+
+ case SCSI_SBC2_FORMATUNIT:
+ dissect_scsi_formatunit (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SBC2_STARTSTOPUNIT:
+ dissect_scsi_startstopunit (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SBC2_READ6:
+ dissect_scsi_sbc2_rdwr6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SBC2_READ10:
+ dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SBC2_READ12:
+ dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SBC2_READ16:
+ dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SBC2_READCAPACITY:
+ dissect_scsi_readcapacity (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE);
+ break;
+
+ case SCSI_SBC2_READDEFDATA10:
+ dissect_scsi_readdefdata10 (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE);
+ break;
+
+ case SCSI_SBC2_READDEFDATA12:
+ dissect_scsi_readdefdata12 (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE);
+ break;
+
+ case SCSI_SBC2_REASSIGNBLKS:
+ dissect_scsi_reassignblks (tvb, pinfo, scsi_tree, offset+1,
+ TRUE, TRUE);
+ break;
+
+ case SCSI_SBC2_WRITE6:
+ dissect_scsi_sbc2_rdwr6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SBC2_WRITE10:
+ dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SBC2_WRITE12:
+ dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SBC2_WRITE16:
+ dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+ break;
+
+ case SCSI_CMND_SSC2:
+ switch (opcode) {
+
+ case SCSI_SSC2_READ6:
+ dissect_scsi_ssc2_read6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SSC2_WRITE6:
+ dissect_scsi_ssc2_write6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SSC2_WRITE_FILEMARKS_6:
+ dissect_scsi_ssc2_writefilemarks6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SSC2_LOAD_UNLOAD:
+ dissect_scsi_ssc2_loadunload (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SSC2_READ_BLOCK_LIMITS:
+ dissect_scsi_ssc2_readblocklimits (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SSC2_READ_POSITION:
+ dissect_scsi_ssc2_readposition (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE, cdata);
+ break;
+
+ case SCSI_SSC2_REWIND:
+ dissect_scsi_ssc2_rewind (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+ break;
+
+ case SCSI_CMND_SMC2:
+ switch (opcode) {
+
+ case SCSI_SMC2_MOVE_MEDIUM:
+ case SCSI_SMC2_MOVE_MEDIUM_ATTACHED:
+ dissect_scsi_smc2_movemedium (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ case SCSI_SMC2_READ_ELEMENT_STATUS:
+ case SCSI_SMC2_READ_ELEMENT_STATUS_ATTACHED:
+ dissect_scsi_smc2_readelementstatus (tvb, pinfo, scsi_tree, offset+1, TRUE,
+ TRUE);
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+}
+
+void
+dissect_scsi_payload (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint offset, gboolean isreq, guint32 payload_len)
+{
+ proto_item *ti;
+ proto_tree *scsi_tree = NULL;
+ guint8 opcode = 0xFF;
+ scsi_cmnd_type cmd = 0; /* 0 is undefined type */
+ scsi_device_type devtype;
+ scsi_task_data_t *cdata = NULL;
+
+ cdata = scsi_find_task (pinfo);
+
+ if (!cdata) {
+ /* we have no record of this exchange and so we can't dissect the
+ * payload
+ */
+ return;
+ }
+
+ opcode = cdata->opcode;
+ cmd = cdata->cmd;
+ devtype = cdata->devtype;
+
+ if (tree) {
+ switch (cmd) {
+ case SCSI_CMND_SPC2:
+ ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
+ payload_len,
+ "SCSI Payload (%s %s)",
+ val_to_str (opcode,
+ scsi_spc2_val,
+ "0x%02x"),
+ isreq ? "Request" : "Response");
+ break;
+
+ case SCSI_CMND_SBC2:
+ ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
+ payload_len,
+ "SCSI Payload (%s %s)",
+ val_to_str (opcode,
+ scsi_sbc2_val,
+ "0x%02x"),
+ isreq ? "Request" : "Response");
+ break;
+
+ case SCSI_CMND_SSC2:
+ ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
+ payload_len,
+ "SCSI Payload (%s %s)",
+ val_to_str (opcode,
+ scsi_ssc2_val,
+ "0x%02x"),
+ isreq ? "Request" : "Response");
+ break;
+
+ case SCSI_CMND_SMC2:
+ ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
+ payload_len,
+ "SCSI Payload (%s %s)",
+ val_to_str (opcode,
+ scsi_smc2_val,
+ "0x%02x"),
+ isreq ? "Request" : "Response");
+ break;
+
+ default:
+ ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
+ payload_len,
+ "SCSI Payload (0x%02x %s)",
+ opcode,
+ isreq ? "Request" : "Response");
+ break;
+ }
+
+ scsi_tree = proto_item_add_subtree (ti, ett_scsi);
+ }
+
+ if (tree == NULL) {
+ /*
+ * We have to dissect INQUIRY responses, in order to determine the
+ * types of devices.
+ *
+ * We don't bother dissecting other payload if we're not buildng
+ * a protocol tree.
+ */
+ if (cmd == SCSI_CMND_SPC2 && opcode == SCSI_SPC2_INQUIRY) {
+ dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE, payload_len, cdata);
+ }
+ } else {
+ switch (cmd) {
+ case SCSI_CMND_SPC2:
+ switch (opcode) {
+ case SCSI_SPC2_INQUIRY:
+ dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE, payload_len, cdata);
+ break;
+
+ case SCSI_SPC2_EXTCOPY:
+ dissect_scsi_extcopy (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SPC2_LOGSELECT:
+ dissect_scsi_logselect (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SPC2_LOGSENSE:
+ dissect_scsi_logsense (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SPC2_MODESELECT6:
+ dissect_scsi_modeselect6 (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE, devtype, payload_len);
+ break;
+
+ case SCSI_SPC2_MODESELECT10:
+ dissect_scsi_modeselect10 (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE, devtype, payload_len);
+ break;
+
+ case SCSI_SPC2_MODESENSE6:
+ dissect_scsi_modesense6 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE, devtype, payload_len);
+ break;
+
+ case SCSI_SPC2_MODESENSE10:
+ dissect_scsi_modesense10 (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE, devtype, payload_len);
+ break;
+
+ case SCSI_SPC2_PERSRESVIN:
+ dissect_scsi_persresvin (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE, cdata, payload_len);
+ break;
+
+ case SCSI_SPC2_PERSRESVOUT:
+ dissect_scsi_persresvout (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE, cdata, payload_len);
+ break;
+
+ case SCSI_SPC2_RELEASE6:
+ dissect_scsi_release6 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SPC2_RELEASE10:
+ dissect_scsi_release10 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SPC2_REPORTDEVICEID:
+ dissect_scsi_reportdeviceid (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE);
+ break;
+
+ case SCSI_SPC2_REPORTLUNS:
+ dissect_scsi_reportluns (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE, payload_len);
+ break;
+
+ case SCSI_SPC2_REQSENSE:
+ dissect_scsi_reqsense (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SPC2_RESERVE6:
+ dissect_scsi_reserve6 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SPC2_RESERVE10:
+ dissect_scsi_reserve10 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SPC2_TESTUNITRDY:
+ dissect_scsi_testunitrdy (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE);
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+ break;
+
+ case SCSI_CMND_SBC2:
+ switch (opcode) {
+
+ case SCSI_SBC2_FORMATUNIT:
+ dissect_scsi_formatunit (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SBC2_STARTSTOPUNIT:
+ dissect_scsi_startstopunit (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SBC2_READ6:
+ dissect_scsi_sbc2_rdwr6 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SBC2_READ10:
+ dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SBC2_READ12:
+ dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SBC2_READ16:
+ dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SBC2_READCAPACITY:
+ dissect_scsi_readcapacity (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE);
+ break;
+
+ case SCSI_SBC2_READDEFDATA10:
+ dissect_scsi_readdefdata10 (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE);
+ break;
+
+ case SCSI_SBC2_READDEFDATA12:
+ dissect_scsi_readdefdata12 (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE);
+ break;
+
+ case SCSI_SBC2_REASSIGNBLKS:
+ dissect_scsi_reassignblks (tvb, pinfo, scsi_tree, offset,
+ isreq, FALSE);
+ break;
+
+ case SCSI_SBC2_WRITE6:
+ dissect_scsi_sbc2_rdwr6 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SBC2_WRITE10:
+ dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SBC2_WRITE12:
+ dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SBC2_WRITE16:
+ dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+ break;
+
+ case SCSI_CMND_SSC2:
+ switch (opcode) {
+
+ case SCSI_SSC2_READ6:
+ dissect_scsi_ssc2_read6 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SSC2_WRITE6:
+ dissect_scsi_ssc2_write6 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SSC2_WRITE_FILEMARKS_6:
+ dissect_scsi_ssc2_writefilemarks6 (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SSC2_LOAD_UNLOAD:
+ dissect_scsi_ssc2_loadunload (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SSC2_READ_BLOCK_LIMITS:
+ dissect_scsi_ssc2_readblocklimits (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SSC2_READ_POSITION:
+ dissect_scsi_ssc2_readposition (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE, cdata);
+ break;
+
+ case SCSI_SSC2_REWIND:
+ dissect_scsi_ssc2_rewind (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+ break;
+
+ case SCSI_CMND_SMC2:
+ switch (opcode) {
+
+ case SCSI_SMC2_MOVE_MEDIUM:
+ case SCSI_SMC2_MOVE_MEDIUM_ATTACHED:
+ dissect_scsi_smc2_movemedium (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ case SCSI_SMC2_READ_ELEMENT_STATUS:
+ case SCSI_SMC2_READ_ELEMENT_STATUS_ATTACHED:
+ dissect_scsi_smc2_readelementstatus (tvb, pinfo, scsi_tree, offset, isreq,
+ FALSE);
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+ break;
+
+ default:
+ call_dissector (data_handle, tvb, pinfo, scsi_tree);
+ break;
+ }
+ }
+}
+
+void
+proto_register_scsi (void)
+{
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_scsi_spcopcode,
+ {"SPC-2 Opcode", "scsi.spc.opcode", FT_UINT8, BASE_HEX,
+ VALS (scsi_spc2_val), 0x0, "", HFILL}},
+ { &hf_scsi_sbcopcode,
+ {"SBC-2 Opcode", "scsi.sbc.opcode", FT_UINT8, BASE_HEX,
+ VALS (scsi_sbc2_val), 0x0, "", HFILL}},
+ { &hf_scsi_sscopcode,
+ {"SSC-2 Opcode", "scsi.ssc.opcode", FT_UINT8, BASE_HEX,
+ VALS (scsi_ssc2_val), 0x0, "", HFILL}},
+ { &hf_scsi_smcopcode,
+ {"SMC-2 Opcode", "scsi.smc.opcode", FT_UINT8, BASE_HEX,
+ VALS (scsi_smc2_val), 0x0, "", HFILL}},
+ { &hf_scsi_control,
+ {"Control", "scsi.cdb.control", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_inquiry_flags,
+ {"Flags", "scsi.inquiry.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_inquiry_evpd_page,
+ {"EVPD Page Code", "scsi.inquiry.evpd.pagecode", FT_UINT8, BASE_HEX,
+ VALS (scsi_evpd_pagecode_val), 0x0, "", HFILL}},
+ { &hf_scsi_inquiry_cmdt_page,
+ {"CMDT Page Code", "scsi.inquiry.cmdt.pagecode", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_alloclen,
+ {"Allocation Length", "scsi.cdb.alloclen", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_logsel_flags,
+ {"Flags", "scsi.logsel.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_logsel_pc,
+ {"Page Control", "scsi.logsel.pc", FT_UINT8, BASE_DEC,
+ VALS (scsi_logsel_pc_val), 0xC0, "", HFILL}},
+ { &hf_scsi_paramlen,
+ {"Parameter Length", "scsi.cdb.paramlen", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_logsns_flags,
+ {"Flags", "scsi.logsns.flags", FT_UINT16, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_logsns_pc,
+ {"Page Control", "scsi.logsns.pc", FT_UINT8, BASE_DEC,
+ VALS (scsi_logsns_pc_val), 0xC0, "", HFILL}},
+ { &hf_scsi_logsns_pagecode,
+ {"Page Code", "scsi.logsns.pagecode", FT_UINT8, BASE_HEX,
+ VALS (scsi_logsns_page_val), 0x3F0, "", HFILL}},
+ { &hf_scsi_paramlen16,
+ {"Parameter Length", "scsi.cdb.paramlen16", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_modesel_flags,
+ {"Mode Sense/Select Flags", "scsi.cdb.mode.flags", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_alloclen16,
+ {"Allocation Length", "scsi.cdb.alloclen16", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_modesns_pc,
+ {"Page Control", "scsi.mode.pc", FT_UINT8, BASE_DEC,
+ VALS (scsi_modesns_pc_val), 0xC0, "", HFILL}},
+ { &hf_scsi_spcpagecode,
+ {"SPC-2 Page Code", "scsi.mode.spc.pagecode", FT_UINT8, BASE_HEX,
+ VALS (scsi_spc2_modepage_val), 0x3F, "", HFILL}},
+ { &hf_scsi_sbcpagecode,
+ {"SBC-2 Page Code", "scsi.mode.sbc.pagecode", FT_UINT8, BASE_HEX,
+ VALS (scsi_sbc2_modepage_val), 0x3F, "", HFILL}},
+ { &hf_scsi_sscpagecode,
+ {"SSC-2 Page Code", "scsi.mode.ssc.pagecode", FT_UINT8, BASE_HEX,
+ VALS (scsi_ssc2_modepage_val), 0x3F, "", HFILL}},
+ { &hf_scsi_smcpagecode,
+ {"SMC-2 Page Code", "scsi.mode.smc.pagecode", FT_UINT8, BASE_HEX,
+ VALS (scsi_smc2_modepage_val), 0x3F, "", HFILL}},
+ { &hf_scsi_modesns_flags,
+ {"Flags", "scsi.mode.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_persresvin_svcaction,
+ {"Service Action", "scsi.persresvin.svcaction", FT_UINT8, BASE_HEX,
+ VALS (scsi_persresvin_svcaction_val), 0x0F, "", HFILL}},
+ { &hf_scsi_persresvout_svcaction,
+ {"Service Action", "scsi.persresvout.svcaction", FT_UINT8, BASE_HEX,
+ VALS (scsi_persresvout_svcaction_val), 0x0F, "", HFILL}},
+ { &hf_scsi_persresv_scope,
+ {"Reservation Scope", "scsi.persresv.scope", FT_UINT8, BASE_HEX,
+ VALS (scsi_persresv_scope_val), 0xF0, "", HFILL}},
+ { &hf_scsi_persresv_type,
+ {"Reservation Type", "scsi.persresv.type", FT_UINT8, BASE_HEX,
+ VALS (scsi_persresv_type_val), 0x0F, "", HFILL}},
+ { &hf_scsi_release_flags,
+ {"Release Flags", "scsi.release.flags", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_release_thirdpartyid,
+ {"Third-Party ID", "scsi.release.thirdpartyid", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_alloclen32,
+ {"Allocation Length", "scsi.cdb.alloclen32", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_formatunit_flags,
+ {"Flags", "scsi.formatunit.flags", FT_UINT8, BASE_HEX, NULL, 0xF8,
+ "", HFILL}},
+ { &hf_scsi_cdb_defectfmt,
+ {"Defect List Format", "scsi.cdb.defectfmt", FT_UINT8, BASE_DEC,
+ NULL, 0x7, "", HFILL}},
+ { &hf_scsi_formatunit_interleave,
+ {"Interleave", "scsi.formatunit.interleave", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_formatunit_vendor,
+ {"Vendor Unique", "scsi.formatunit.vendor", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_rdwr6_lba,
+ {"Logical Block Address (LBA)", "scsi.rdwr6.lba", FT_UINT24, BASE_DEC,
+ NULL, 0x0FFFFF, "", HFILL}},
+ { &hf_scsi_rdwr6_xferlen,
+ {"Transfer Length", "scsi.rdwr6.xferlen", FT_UINT24, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_scsi_rdwr10_lba,
+ {"Logical Block Address (LBA)", "scsi.rdwr10.lba", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_rdwr10_xferlen,
+ {"Transfer Length", "scsi.rdwr10.xferlen", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_read_flags,
+ {"Flags", "scsi.read.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_rdwr12_xferlen,
+ {"Transfer Length", "scsi.rdwr12.xferlen", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_rdwr16_lba,
+ {"Logical Block Address (LBA)", "scsi.rdwr16.lba", FT_BYTES, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_readcapacity_flags,
+ {"Flags", "scsi.readcapacity.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL}},
+ { &hf_scsi_readcapacity_lba,
+ {"Logical Block Address", "scsi.readcapacity.lba", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_readcapacity_pmi,
+ {"PMI", "scsi.readcapacity.pmi", FT_UINT8, BASE_DEC, NULL, 0x1, "",
+ HFILL}},
+ { &hf_scsi_readdefdata_flags,
+ {"Flags", "scsi.readdefdata.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_reassignblks_flags,
+ {"Flags", "scsi.reassignblks.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_inq_qualifier,
+ {"Peripheral Qualifier", "scsi.inquiry.qualifier", FT_UINT8, BASE_HEX,
+ VALS (scsi_qualifier_val), 0xE0, "", HFILL}},
+ { &hf_scsi_inq_devtype,
+ {"Peripheral Device Type", "scsi.inquiry.devtype", FT_UINT8, BASE_HEX,
+ VALS (scsi_devtype_val), SCSI_DEV_BITS, "", HFILL}},
+ { & hf_scsi_inq_version,
+ {"Version", "scsi.inquiry.version", FT_UINT8, BASE_HEX,
+ VALS (scsi_inquiry_vers_val), 0x0, "", HFILL}},
+ { &hf_scsi_inq_normaca,
+ {"NormACA", "scsi.inquiry.normaca", FT_UINT8, BASE_HEX, NULL, 0x20,
+ "", HFILL}},
+ { &hf_scsi_rluns_lun,
+ {"LUN", "scsi.reportluns.lun", FT_UINT8, BASE_DEC, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_rluns_multilun,
+ {"Multi-level LUN", "scsi.reportluns.mlun", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_modesns_errrep,
+ {"MRIE", "scsi.mode.mrie", FT_UINT8, BASE_HEX,
+ VALS (scsi_modesns_mrie_val), 0x0F, "", HFILL}},
+ { &hf_scsi_modesns_tst,
+ {"Task Set Type", "scsi.mode.tst", FT_UINT8, BASE_DEC,
+ VALS (scsi_modesns_tst_val), 0xE0, "", HFILL}},
+ { &hf_scsi_modesns_qmod,
+ {"Queue Algorithm Modifier", "scsi.mode.qmod", FT_UINT8, BASE_HEX,
+ VALS (scsi_modesns_qmod_val), 0xF0, "", HFILL}},
+ { &hf_scsi_modesns_qerr,
+ {"Queue Error Management", "scsi.mode.qerr", FT_BOOLEAN, BASE_HEX,
+ TFS (&scsi_modesns_qerr_val), 0x2, "", HFILL}},
+ { &hf_scsi_modesns_tas,
+ {"Task Aborted Status", "scsi.mode.tac", FT_BOOLEAN, BASE_HEX,
+ TFS (&scsi_modesns_tas_val), 0x80, "", HFILL}},
+ { &hf_scsi_modesns_rac,
+ {"Report a Check", "ssci.mode.rac", FT_BOOLEAN, BASE_HEX,
+ TFS (&scsi_modesns_rac_val), 0x40, "", HFILL}},
+ { &hf_scsi_protocol,
+ {"Protocol", "scsi.proto", FT_UINT8, BASE_DEC, VALS (scsi_proto_val),
+ 0x0F, "", HFILL}},
+ { &hf_scsi_sns_errtype,
+ {"SNS Error Type", "scsi.sns.errtype", FT_UINT8, BASE_HEX,
+ VALS (scsi_sns_errtype_val), 0x7F, "", HFILL}},
+ { &hf_scsi_snskey,
+ {"Sense Key", "scsi.sns.key", FT_UINT8, BASE_HEX,
+ VALS (scsi_sensekey_val), 0x0F, "", HFILL}},
+ { &hf_scsi_snsinfo,
+ {"Sense Info", "scsi.sns.info", FT_UINT32, BASE_HEX, NULL, 0x0, "",
+ HFILL}},
+ { &hf_scsi_addlsnslen,
+ {"Additional Sense Length", "scsi.sns.addlen", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_asc,
+ {"Additional Sense Code", "scsi.sns.asc", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_ascq,
+ {"Additional Sense Code Qualifier", "scsi.sns.ascq", FT_UINT8,
+ BASE_HEX, NULL, 0x0, "", HFILL}},
+ { &hf_scsi_ascascq,
+ {"Additional Sense Code+Qualifier", "scsi.sns.ascascq", FT_UINT16,
+ BASE_HEX, VALS (scsi_asc_val), 0x0, "", HFILL}},
+ { &hf_scsi_fru,
+ {"Field Replaceable Unit Code", "scsi.sns.fru", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_sksv,
+ {"SKSV", "scsi.sns.sksv", FT_BOOLEAN, BASE_HEX, NULL, 0x80, "",
+ HFILL}},
+ { &hf_scsi_persresv_key,
+ {"Reservation Key", "scsi.spc2.resv.key", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_persresv_scopeaddr,
+ {"Scope Address", "scsi.spc2.resv.scopeaddr", FT_BYTES, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_add_cdblen,
+ {"Additional CDB Length", "scsi.spc2.addcdblen", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_svcaction,
+ {"Service Action", "scsi.spc2.svcaction", FT_UINT16, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_ssu_immed,
+ {"Immediate", "scsi.sbc2.ssu.immediate", FT_BOOLEAN, BASE_DEC, NULL,
+ 0x1, "", HFILL}},
+ { &hf_scsi_ssu_pwr_cond,
+ {"Power Conditions", "scsi.sbc2.ssu.pwr", FT_UINT8, BASE_HEX,
+ VALS (scsi_ssu_pwrcnd_val), 0xF0, "", HFILL}},
+ { &hf_scsi_ssu_loej,
+ {"LOEJ", "scsi.sbc2.ssu.loej", FT_BOOLEAN, BASE_HEX, NULL, 0x2, "",
+ HFILL}},
+ { &hf_scsi_ssu_start,
+ {"Start", "scsi.sbc2.ssu.start", FT_BOOLEAN, BASE_HEX, NULL, 0x1,
+ "", HFILL}},
+ { &hf_scsi_wb_mode,
+ {"Mode", "scsi.spc2.wb.mode", FT_UINT8, BASE_HEX,
+ VALS (scsi_wb_mode_val), 0xF, "", HFILL}},
+ { &hf_scsi_wb_bufferid,
+ {"Buffer ID", "scsi.spc2.sb.bufid", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+ { &hf_scsi_wb_bufoffset,
+ {"Buffer Offset", "scsi.spc2.wb.bufoff", FT_UINT24, BASE_HEX, NULL,
+ 0x0, "", HFILL}},
+ { &hf_scsi_paramlen24,
+ {"Paremeter List Length", "scsi.cdb.paramlen24", FT_UINT24, BASE_HEX,
+ NULL, 0x0, "", HFILL}},
+ { &hf_scsi_senddiag_st_code,
+ {"Self-Test Code", "scsi.spc2.senddiag.code", FT_UINT8, BASE_HEX,
+ VALS (scsi_senddiag_st_code_val), 0xE0, "", HFILL}},
+ { &hf_scsi_senddiag_pf,
+ {"PF", "scsi.spc2.senddiag.pf", FT_BOOLEAN, BASE_HEX,
+ TFS (&scsi_senddiag_pf_val), 0x10, "", HFILL}},
+ { &hf_scsi_senddiag_st,
+ {"Self Test", "scsi.spc2.senddiag.st", FT_BOOLEAN, BASE_HEX, NULL,
+ 0x4, "", HFILL}},
+ { &hf_scsi_senddiag_devoff,
+ {"Device Offline", "scsi.spc2.senddiag.devoff", FT_BOOLEAN, BASE_HEX,
+ NULL, 0x2, "", HFILL}},
+ { &hf_scsi_senddiag_unitoff,
+ {"Unit Offline", "scsi.spc2.senddiag.unitoff", FT_BOOLEAN, BASE_HEX,
+ NULL, 0x1, "", HFILL}},
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_scsi,
+ &ett_scsi_page,
+ };
+ module_t *scsi_module;
+
+ /* Register the protocol name and description */
+ proto_scsi = proto_register_protocol("SCSI", "SCSI", "scsi");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_scsi, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine (&scsi_init_protocol);
+ data_handle = find_dissector ("data");
+
+ /* add preferences to decode SCSI message */
+ scsi_module = prefs_register_protocol (proto_scsi, NULL);
+ prefs_register_enum_preference (scsi_module, "decode_scsi_messages_as",
+ "Decode SCSI Messages As",
+ "When Target Cannot Be Identified, Decode SCSI Messages As",
+ &scsi_def_devtype, scsi_devtype_options, TRUE);
+}
diff --git a/epan/dissectors/packet-scsi.h b/epan/dissectors/packet-scsi.h
new file mode 100644
index 0000000000..ed2ff42e7c
--- /dev/null
+++ b/epan/dissectors/packet-scsi.h
@@ -0,0 +1,83 @@
+/* packet-scsi.h
+ * Author: Dinesh G Dutt (ddutt@cisco.com)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2002 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_SCSI_H_
+#define __PACKET_SCSI_H_
+
+extern const value_string scsi_status_val[];
+
+/*
+ * SCSI Device Types.
+ *
+ * These can be supplied to the dissection routines if the caller happens
+ * to know the device type (e.g., NDMP assumes that a "jukebox" is a
+ * media changer, SCSI_DEV_SMC, and a "tape" is a sequential access device,
+ * SCSI_DEV_SSC).
+ *
+ * If the caller doesn't know the device type, it supplies SCSI_DEV_UNKNOWN.
+ */
+#define SCSI_DEV_UNKNOWN -1
+#define SCSI_DEV_SBC 0x0
+#define SCSI_DEV_SSC 0x1
+#define SCSI_DEV_PRNT 0x2
+#define SCSI_DEV_PROC 0x3
+#define SCSI_DEV_WORM 0x4
+#define SCSI_DEV_CDROM 0x5
+#define SCSI_DEV_SCAN 0x6
+#define SCSI_DEV_OPTMEM 0x7
+#define SCSI_DEV_SMC 0x8
+#define SCSI_DEV_COMM 0x9
+#define SCSI_DEV_RAID 0xC
+#define SCSI_DEV_SES 0xD
+#define SCSI_DEV_RBC 0xE
+#define SCSI_DEV_OCRW 0xF
+#define SCSI_DEV_OSD 0x11
+#define SCSI_DEV_ADC 0x12
+#define SCSI_DEV_NOLUN 0x1F
+
+#define SCSI_DEV_BITS 0x1F /* the lower 5 bits indicate device type */
+#define SCSI_MS_PCODE_BITS 0x3F /* Page code bits in Mode Sense */
+
+/* Function Decls; functions invoked by SAM-2 transport protocols such as
+ * FCP/iSCSI
+ */
+void dissect_scsi_cdb (tvbuff_t *, packet_info *, proto_tree *, guint, guint,
+ gint);
+void dissect_scsi_rsp (tvbuff_t *, packet_info *, proto_tree *);
+void dissect_scsi_payload (tvbuff_t *, packet_info *, proto_tree *, guint,
+ gboolean, guint32);
+void dissect_scsi_snsinfo (tvbuff_t *, packet_info *, proto_tree *, guint, guint);
+
+/*
+ * Private data to be supplied to those functions via "pinfo->private_data";
+ * the structure contains a 32-bit conversation ID and a 32-bit task
+ * ID, where the former identifies a conversation between initiator and
+ * target and the latter identifies a SCSI task within that conversation.
+ */
+typedef struct {
+ guint32 conv_id;
+ guint32 task_id;
+} scsi_task_id_t;
+
+#endif
diff --git a/epan/dissectors/packet-sctp.c b/epan/dissectors/packet-sctp.c
new file mode 100644
index 0000000000..4e2712db3d
--- /dev/null
+++ b/epan/dissectors/packet-sctp.c
@@ -0,0 +1,2292 @@
+/* packet-sctp.c
+ * Routines for Stream Control Transmission Protocol dissection
+ * It should be compilant to
+ * - RFC 2960
+ * - RFC 3309
+ * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctpimpguide-09.txt
+ * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-08.txt for the add-IP extension
+ * - http://www.ietf.org/internet-drafts/draft-stewart-tsvwg-prsctp-04.txt for the 'Partial Reliability' extension
+ * - another upcoming ID on packetdrop stuff.
+ * Copyright 2000, 2001, 2002, 2003, 2004 Michael Tuexen <tuexen [AT] fh-muenster.de>
+ * Still to do (so stay tuned)
+ * - support for reassembly
+ * - error checking mode
+ * * padding errors
+ * * length errors
+ * * bundling errors
+ * * value errors
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include "prefs.h"
+#include <epan/packet.h>
+#include "tap.h"
+#include "ipproto.h"
+#include "packet-sctp.h"
+#include "sctpppids.h"
+
+#define NETWORK_BYTE_ORDER FALSE
+#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
+#define UDP_TUNNELING_PORT 9899
+
+/* Initialize the protocol and registered fields */
+static int proto_sctp = -1;
+static int hf_port = -1;
+static int hf_source_port = -1;
+static int hf_destination_port = -1;
+static int hf_verification_tag = -1;
+static int hf_checksum = -1;
+static int hf_checksum_bad = -1;
+
+static int hf_chunk_type = -1;
+static int hf_chunk_flags = -1;
+static int hf_chunk_bit_1 = -1;
+static int hf_chunk_bit_2 = -1;
+static int hf_chunk_length = -1;
+static int hf_chunk_padding = -1;
+static int hf_chunk_value = -1;
+
+static int hf_initiate_tag = -1;
+static int hf_init_chunk_initiate_tag = -1;
+static int hf_init_chunk_adv_rec_window_credit = -1;
+static int hf_init_chunk_number_of_outbound_streams = -1;
+static int hf_init_chunk_number_of_inbound_streams = -1;
+static int hf_init_chunk_initial_tsn = -1;
+
+static int hf_initack_chunk_initiate_tag = -1;
+static int hf_initack_chunk_adv_rec_window_credit = -1;
+static int hf_initack_chunk_number_of_outbound_streams = -1;
+static int hf_initack_chunk_number_of_inbound_streams = -1;
+static int hf_initack_chunk_initial_tsn = -1;
+
+static int hf_cumulative_tsn_ack = -1;
+
+static int hf_data_chunk_tsn = -1;
+static int hf_data_chunk_stream_id = -1;
+static int hf_data_chunk_stream_seq_number = -1;
+static int hf_data_chunk_payload_proto_id = -1;
+
+static int hf_data_chunk_e_bit = -1;
+static int hf_data_chunk_b_bit = -1;
+static int hf_data_chunk_u_bit = -1;
+
+static int hf_sack_chunk_cumulative_tsn_ack = -1;
+static int hf_sack_chunk_adv_rec_window_credit = -1;
+static int hf_sack_chunk_number_of_gap_blocks = -1;
+static int hf_sack_chunk_number_of_dup_tsns = -1;
+static int hf_sack_chunk_gap_block_start = -1;
+static int hf_sack_chunk_gap_block_end = -1;
+static int hf_sack_chunk_duplicate_tsn = -1;
+
+static int hf_shutdown_chunk_cumulative_tsn_ack = -1;
+static int hf_cookie = -1;
+static int hf_cwr_chunk_lowest_tsn = -1;
+
+static int hf_ecne_chunk_lowest_tsn = -1;
+static int hf_abort_chunk_t_bit = -1;
+static int hf_shutdown_complete_chunk_t_bit = -1;
+
+static int hf_parameter_type = -1;
+static int hf_parameter_length = -1;
+static int hf_parameter_value = -1;
+static int hf_parameter_padding = -1;
+static int hf_parameter_bit_1 = -1;
+static int hf_parameter_bit_2 = -1;
+static int hf_ipv4_address = -1;
+static int hf_ipv6_address = -1;
+static int hf_heartbeat_info = -1;
+static int hf_state_cookie = -1;
+static int hf_cookie_preservative_increment = -1;
+static int hf_hostname = -1;
+static int hf_supported_address_type = -1;
+
+static int hf_cause_code = -1;
+static int hf_cause_length = -1;
+static int hf_cause_padding = -1;
+static int hf_cause_info = -1;
+
+static int hf_cause_stream_identifier = -1;
+static int hf_cause_reserved = -1;
+
+static int hf_cause_number_of_missing_parameters = -1;
+static int hf_cause_missing_parameter_type = -1;
+
+static int hf_cause_measure_of_staleness = -1;
+
+static int hf_cause_tsn = -1;
+
+static int hf_forward_tsn_chunk_tsn = -1;
+static int hf_forward_tsn_chunk_sid = -1;
+static int hf_forward_tsn_chunk_ssn = -1;
+
+static int hf_asconf_ack_serial = -1;
+static int hf_asconf_serial = -1;
+static int hf_correlation_id = -1;
+
+static int hf_adap_indication = -1;
+
+static int hf_pktdrop_chunk_m_bit = -1;
+/*
+static int hf_pktdrop_chunk_s_bit = -1;
+*/
+static int hf_pktdrop_chunk_b_bit = -1;
+static int hf_pktdrop_chunk_t_bit = -1;
+static int hf_pktdrop_chunk_bandwidth = -1;
+static int hf_pktdrop_chunk_queuesize = -1;
+static int hf_pktdrop_chunk_truncated_length = -1;
+static int hf_pktdrop_chunk_reserved = -1;
+static int hf_pktdrop_chunk_data_field = -1;
+
+static dissector_table_t sctp_port_dissector_table;
+static dissector_table_t sctp_ppi_dissector_table;
+static heur_dissector_list_t sctp_heur_subdissector_list;
+static int sctp_tap = -1;
+static module_t *sctp_module;
+
+/* Initialize the subtree pointers */
+static gint ett_sctp = -1;
+static gint ett_sctp_chunk = -1;
+static gint ett_sctp_chunk_parameter = -1;
+static gint ett_sctp_chunk_cause = -1;
+static gint ett_sctp_chunk_type = -1;
+static gint ett_sctp_data_chunk_flags = -1;
+static gint ett_sctp_abort_chunk_flags = -1;
+static gint ett_sctp_shutdown_complete_chunk_flags = -1;
+static gint ett_sctp_pktdrop_chunk_flags = -1;
+static gint ett_sctp_parameter_type= -1;
+static gint ett_sctp_sack_chunk_gap_block = -1;
+static gint ett_sctp_unrecognized_parameter_parameter = -1;
+
+static dissector_handle_t data_handle;
+
+#define SCTP_DATA_CHUNK_ID 0
+#define SCTP_INIT_CHUNK_ID 1
+#define SCTP_INIT_ACK_CHUNK_ID 2
+#define SCTP_SACK_CHUNK_ID 3
+#define SCTP_HEARTBEAT_CHUNK_ID 4
+#define SCTP_HEARTBEAT_ACK_CHUNK_ID 5
+#define SCTP_ABORT_CHUNK_ID 6
+#define SCTP_SHUTDOWN_CHUNK_ID 7
+#define SCTP_SHUTDOWN_ACK_CHUNK_ID 8
+#define SCTP_ERROR_CHUNK_ID 9
+#define SCTP_COOKIE_ECHO_CHUNK_ID 10
+#define SCTP_COOKIE_ACK_CHUNK_ID 11
+#define SCTP_ECNE_CHUNK_ID 12
+#define SCTP_CWR_CHUNK_ID 13
+#define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14
+#define SCTP_FORWARD_TSN_CHUNK_ID 192
+#define SCTP_ASCONF_ACK_CHUNK_ID 0x80
+#define SCTP_PKTDROP_CHUNK_ID 0X81
+#define SCTP_ASCONF_CHUNK_ID 0XC1
+#define SCTP_IETF_EXT 255
+
+static const value_string chunk_type_values[] = {
+ { SCTP_DATA_CHUNK_ID, "DATA" },
+ { SCTP_INIT_CHUNK_ID, "INIT" },
+ { SCTP_INIT_ACK_CHUNK_ID, "INIT_ACK" },
+ { SCTP_SACK_CHUNK_ID, "SACK" },
+ { SCTP_HEARTBEAT_CHUNK_ID, "HEARTBEAT" },
+ { SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT_ACK" },
+ { SCTP_ABORT_CHUNK_ID, "ABORT" },
+ { SCTP_SHUTDOWN_CHUNK_ID, "SHUTDOWN" },
+ { SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN_ACK" },
+ { SCTP_ERROR_CHUNK_ID, "ERROR" },
+ { SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE_ECHO" },
+ { SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE_ACK" },
+ { SCTP_ECNE_CHUNK_ID, "ECNE" },
+ { SCTP_CWR_CHUNK_ID, "CWR" },
+ { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
+ { SCTP_FORWARD_TSN_CHUNK_ID, "FORWARD TSN" },
+ { SCTP_ASCONF_ACK_CHUNK_ID, "ASCONF_ACK" },
+ { SCTP_PKTDROP_CHUNK_ID, "PKTDROP" },
+ { SCTP_ASCONF_CHUNK_ID, "ASCONF" },
+ { SCTP_IETF_EXT, "IETF_EXTENSION" },
+ { 0, NULL } };
+
+static const value_string sctp_payload_proto_id_values[] = {
+ { NOT_SPECIFIED_PROTOCOL_ID, "not specified" },
+ { IUA_PAYLOAD_PROTOCOL_ID, "IUA" },
+ { M2UA_PAYLOAD_PROTOCOL_ID, "M2UA" },
+ { M3UA_PAYLOAD_PROTOCOL_ID, "M3UA" },
+ { SUA_PAYLOAD_PROTOCOL_ID, "SUA" },
+ { M2PA_PAYLOAD_PROTOCOL_ID, "M2PA" },
+ { V5UA_PAYLOAD_PROTOCOL_ID, "V5UA" },
+ { H248_PAYLOAD_PROTOCOL_ID, "H.248/MEGACO" },
+ { BICC_PAYLOAD_PROTOCOL_ID, "BICC/Q.2150.3" },
+ { TALI_PAYLOAD_PROTOCOL_ID, "TALI" },
+ { DUA_PAYLOAD_PROTOCOL_ID, "DUA" },
+ { ASAP_PAYLOAD_PROTOCOL_ID, "ASAP" },
+ { ENRP_PAYLOAD_PROTOCOL_ID, "ENRP" },
+ { H323_PAYLOAD_PROTOCOL_ID, "H.323" },
+ { 0, NULL } };
+
+
+#define CHUNK_TYPE_LENGTH 1
+#define CHUNK_FLAGS_LENGTH 1
+#define CHUNK_LENGTH_LENGTH 2
+#define CHUNK_HEADER_LENGTH (CHUNK_TYPE_LENGTH + \
+ CHUNK_FLAGS_LENGTH + \
+ CHUNK_LENGTH_LENGTH)
+#define CHUNK_HEADER_OFFSET 0
+#define CHUNK_TYPE_OFFSET CHUNK_HEADER_OFFSET
+#define CHUNK_FLAGS_OFFSET (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
+#define CHUNK_LENGTH_OFFSET (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
+#define CHUNK_VALUE_OFFSET (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
+
+#define PARAMETER_TYPE_LENGTH 2
+#define PARAMETER_LENGTH_LENGTH 2
+#define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
+
+#define PARAMETER_HEADER_OFFSET 0
+#define PARAMETER_TYPE_OFFSET PARAMETER_HEADER_OFFSET
+#define PARAMETER_LENGTH_OFFSET (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
+#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
+
+#define SOURCE_PORT_LENGTH 2
+#define DESTINATION_PORT_LENGTH 2
+#define VERIFICATION_TAG_LENGTH 4
+#define CHECKSUM_LENGTH 4
+#define COMMON_HEADER_LENGTH (SOURCE_PORT_LENGTH + \
+ DESTINATION_PORT_LENGTH + \
+ VERIFICATION_TAG_LENGTH + \
+ CHECKSUM_LENGTH)
+#define SOURCE_PORT_OFFSET 0
+#define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
+#define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
+#define CHECKSUM_OFFSET (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
+
+#define SCTP_CHECKSUM_NONE 0
+#define SCTP_CHECKSUM_ADLER32 1
+#define SCTP_CHECKSUM_CRC32C 2
+#define SCTP_CHECKSUM_AUTOMATIC 3
+
+static gboolean show_always_control_chunks = TRUE;
+static gint sctp_checksum = SCTP_CHECKSUM_CRC32C;
+static struct _sctp_info sctp_info;
+
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ * available, e.g. from http://www.cdrom.com/pub/infozip/zlib/
+ *
+ * It was modified for the use in this dissector.
+ */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5540 /* NMAX is the largest n - 12 such that */
+ /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+static unsigned int
+sctp_adler32(const unsigned char* buf, unsigned int len)
+{
+ unsigned int s1 = 1L;
+ unsigned int s2 = 0L;
+ int k;
+
+ /* handle the first 8 bytes of the datagram */
+ DO8(buf,0);
+ buf += SOURCE_PORT_LENGTH +
+ DESTINATION_PORT_LENGTH +
+ VERIFICATION_TAG_LENGTH;
+
+ /* handle four 0 bytes as checksum */
+ s2 += CHECKSUM_LENGTH * s1;
+ buf += CHECKSUM_LENGTH;
+
+ /* now we have 12 bytes handled */
+ len -= COMMON_HEADER_LENGTH;
+
+ /* handle the rest of the datagram */
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ buf += 16;
+ k -= 16;
+ }
+ if (k != 0) do {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
+
+/* The CRC32C code is taken from draft-ietf-tsvwg-sctpcsum-01.txt.
+ * That code is copyrighted by D. Otis and has been modified.
+ *
+ * Polynomial is
+ *
+ * x^32 + x^28 + x^27 + x^26 + x^25 + x^23 + x^22 + x^20 + x^19 +
+ * x^18 + x^14 + x^13 + x^11 + x^10 + x^9 + x^8 + x^6 + 1
+ *
+ * Note that this is not the AUTODIN/HDLC/802.x CRC - it uses a different
+ * polynomial.
+ */
+
+#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
+static guint32 crc_c[256] =
+{
+0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
+0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
+0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
+0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
+0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
+0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
+0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
+0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
+0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
+0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
+0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
+0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
+0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
+0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
+0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
+0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
+0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
+0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
+0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
+0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
+0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
+0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
+0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
+0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
+0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
+0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
+0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
+0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
+0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
+0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
+0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
+0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
+0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
+0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
+0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
+0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
+0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
+0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
+0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
+0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
+0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
+0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
+0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
+0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
+0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
+0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
+0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
+0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
+0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
+0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
+0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
+0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
+};
+
+static guint32
+sctp_crc32c(const unsigned char* buf, unsigned int len)
+{
+ unsigned int i;
+ guint32 crc32 = ~0L;
+ guint32 result;
+ unsigned char byte0,byte1,byte2,byte3;
+
+ for (i = 0; i < SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH; i++)
+ {
+ CRC32C(crc32, buf[i]);
+ }
+ CRC32C(crc32, 0);
+ CRC32C(crc32, 0);
+ CRC32C(crc32, 0);
+ CRC32C(crc32, 0);
+ for (i = COMMON_HEADER_LENGTH; i < len; i++)
+ {
+ CRC32C(crc32, buf[i]);
+ }
+ result = ~crc32;
+
+ byte0 = result & 0xff;
+ byte1 = (result>>8) & 0xff;
+ byte2 = (result>>16) & 0xff;
+ byte3 = (result>>24) & 0xff;
+ crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
+ return ( crc32 );
+}
+
+/*
+ * Routines for dissecting parameters
+ */
+
+static void
+dissect_parameter(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
+
+static void
+dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_item *, gboolean);
+
+static void
+dissect_error_cause(tvbuff_t *, packet_info *, proto_tree *);
+
+static void
+dissect_error_causes(tvbuff_t *, packet_info *, proto_tree *);
+
+static gboolean
+dissect_sctp_chunk(tvbuff_t *, packet_info *, proto_tree *, proto_tree *, gboolean);
+
+static void
+dissect_sctp_packet(tvbuff_t *, packet_info *, proto_tree *, gboolean);
+
+
+
+#define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 heartbeat_info_length;
+
+ heartbeat_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ if (heartbeat_info_length > 0)
+ proto_tree_add_item(parameter_tree, hf_heartbeat_info, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (Information: %u byte%s)", heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
+}
+
+#define IPV4_ADDRESS_LENGTH 4
+#define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
+{
+ proto_tree_add_item(parameter_tree, hf_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (Address: %s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
+ if (additional_item)
+ proto_item_append_text(additional_item, "%s", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
+ if (dissecting_init_init_ack_chunk) {
+ if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
+ sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
+ else
+ sctp_info.incomplete = TRUE;
+ }
+}
+
+#define IPV6_ADDRESS_LENGTH 16
+#define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
+{
+ proto_tree_add_item(parameter_tree, hf_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (Address: %s)", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
+ if (additional_item)
+ proto_item_append_text(additional_item, "%s", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
+ if (dissecting_init_init_ack_chunk) {
+ if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
+ sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
+ else
+ sctp_info.incomplete = TRUE;
+ }
+}
+
+#define STATE_COOKIE_PARAMETER_COOKIE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 state_cookie_length;
+
+ state_cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ if (state_cookie_length > 0)
+ proto_tree_add_item(parameter_tree, hf_state_cookie, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (Cookie length: %u byte%s)", state_cookie_length, plurality(state_cookie_length, "", "s"));
+}
+
+static void
+dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
+{
+ /* FIXME: Does it contain one or more parameters? */
+ dissect_parameter(tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1), pinfo, parameter_tree, NULL, FALSE);
+}
+
+#define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
+#define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_cookie_preservative_increment, parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (Increment :%u msec)", tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET));
+}
+
+#define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 hostname_length;
+
+ hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (Hostname: %.*s)", hostname_length, (const char *)tvb_get_ptr(parameter_tvb, HOSTNAME_OFFSET, hostname_length));
+
+}
+
+#define IPv4_ADDRESS_TYPE 5
+#define IPv6_ADDRESS_TYPE 6
+#define HOSTNAME_ADDRESS_TYPE 11
+
+static const value_string address_types_values[] = {
+ { IPv4_ADDRESS_TYPE, "IPv4 address" },
+ { IPv6_ADDRESS_TYPE, "IPv6 address" },
+ { HOSTNAME_ADDRESS_TYPE, "Hostname address" },
+ { 0, NULL }
+};
+
+#define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
+
+static void
+dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 address_type, number_of_address_types, address_type_number;
+ guint offset;
+
+ number_of_address_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH)
+ / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
+
+ offset = PARAMETER_VALUE_OFFSET;
+ proto_item_append_text(parameter_item, " (Supported types: ");
+ for(address_type_number = 1; address_type_number <= number_of_address_types; address_type_number++) {
+ proto_tree_add_item(parameter_tree, hf_supported_address_type, parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ address_type = tvb_get_ntohs(parameter_tvb, offset);
+ switch (address_type) {
+ case IPv4_ADDRESS_TYPE:
+ proto_item_append_text(parameter_item, "IPv4");
+ break;
+ case IPv6_ADDRESS_TYPE:
+ proto_item_append_text(parameter_item, "IPv6");
+ break;
+ case HOSTNAME_ADDRESS_TYPE:
+ proto_item_append_text(parameter_item, "hostname");
+ break;
+ default:
+ proto_item_append_text(parameter_item, "%u", address_type);
+ }
+ if (address_type_number < number_of_address_types)
+ proto_item_append_text(parameter_item, ", ");
+ offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
+ };
+ proto_item_append_text(parameter_item, ")");
+}
+
+static void
+dissect_ecn_parameter(tvbuff_t *parameter_tvb _U_)
+{
+}
+
+static void
+dissect_forward_tsn_supported_parameter(tvbuff_t *parameter_tvb _U_)
+{
+}
+
+#define CORRELATION_ID_LENGTH 4
+#define CORRELATION_ID_OFFSET PARAMETER_VALUE_OFFSET
+#define ADDRESS_PARAMETER_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
+
+static void
+dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 address_length;
+ tvbuff_t *address_tvb;
+
+ address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
+
+ proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
+ address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
+ proto_item_append_text(parameter_item, " (Address: ");
+ dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
+ proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
+}
+
+static void
+dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 address_length;
+ tvbuff_t *address_tvb;
+
+ address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
+
+ proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
+ address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
+ proto_item_append_text(parameter_item, " (Address: ");
+ dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
+ proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
+}
+
+#define ERROR_CAUSE_IND_CASUES_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
+
+static void
+dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
+{
+ guint16 causes_length;
+ tvbuff_t *causes_tvb;
+
+ proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
+ causes_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
+ causes_tvb = tvb_new_subset(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET, causes_length, causes_length);
+ dissect_error_causes(causes_tvb, pinfo, parameter_tree);
+}
+
+static void
+dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 address_length;
+ tvbuff_t *address_tvb;
+
+ address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
+
+ proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
+ address_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETER_OFFSET, address_length, address_length);
+ proto_item_append_text(parameter_item, " (Address: ");
+ dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, FALSE);
+ proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
+}
+
+static void
+dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (Correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
+}
+
+#define ADAP_INDICATION_LENGTH 4
+#define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (Indication: %u)", tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET));
+}
+
+static void
+dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 type, parameter_value_length;
+
+ type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
+ parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+
+ if (parameter_value_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
+
+ proto_item_append_text(parameter_item, " (Type %u, value length: %u byte%s)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
+}
+
+#define HEARTBEAT_INFO_PARAMETER_ID 0x0001
+#define IPV4ADDRESS_PARAMETER_ID 0x0005
+#define IPV6ADDRESS_PARAMETER_ID 0x0006
+#define STATE_COOKIE_PARAMETER_ID 0x0007
+#define UNREC_PARA_PARAMETER_ID 0x0008
+#define COOKIE_PRESERVATIVE_PARAMETER_ID 0x0009
+#define HOSTNAME_ADDRESS_PARAMETER_ID 0x000b
+#define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID 0x000c
+#define ECN_PARAMETER_ID 0x8000
+#define FORWARD_TSN_SUPPORTED_PARAMETER_ID 0xC000
+#define ADD_IP_ADDRESS_PARAMETER_ID 0xC001
+#define DEL_IP_ADDRESS_PARAMETER_ID 0xC002
+#define ERROR_CAUSE_INDICATION_PARAMETER_ID 0xC003
+#define SET_PRIMARY_ADDRESS_PARAMETER_ID 0xC004
+#define SUCCESS_REPORT_PARAMETER_ID 0xC005
+#define ADAP_LAYER_INDICATION_PARAMETER_ID 0xC006
+
+static const value_string parameter_identifier_values[] = {
+ { HEARTBEAT_INFO_PARAMETER_ID, "Heartbeat info" },
+ { IPV4ADDRESS_PARAMETER_ID, "IPv4 address" },
+ { IPV6ADDRESS_PARAMETER_ID, "IPv6 address" },
+ { STATE_COOKIE_PARAMETER_ID, "State cookie" },
+ { UNREC_PARA_PARAMETER_ID, "Unrecognized parameter" },
+ { COOKIE_PRESERVATIVE_PARAMETER_ID, "Cookie preservative" },
+ { HOSTNAME_ADDRESS_PARAMETER_ID, "Hostname address" },
+ { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID, "Supported address types" },
+ { ECN_PARAMETER_ID, "ECN" },
+ { FORWARD_TSN_SUPPORTED_PARAMETER_ID, "Forward TSN supported" },
+ { ADD_IP_ADDRESS_PARAMETER_ID, "Add IP address" },
+ { DEL_IP_ADDRESS_PARAMETER_ID, "Delete IP address" },
+ { ERROR_CAUSE_INDICATION_PARAMETER_ID, "Error cause indication" },
+ { SET_PRIMARY_ADDRESS_PARAMETER_ID, "Set primary address" },
+ { SUCCESS_REPORT_PARAMETER_ID, "Success report" },
+ { ADAP_LAYER_INDICATION_PARAMETER_ID, "Adaptation Layer Indication" },
+ { 0, NULL } };
+
+#define SCTP_PARAMETER_BIT_1 0x8000
+#define SCTP_PARAMETER_BIT_2 0x4000
+
+static const true_false_string sctp_parameter_bit_1_value = {
+ "Skip parameter and continue processing of the chunk",
+ "Stop processing of chunk"
+};
+
+static const true_false_string sctp_parameter_bit_2_value = {
+ "Do report",
+ "Do not report"
+};
+
+static void
+dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
+{
+ guint16 type, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+ proto_item *type_item;
+ proto_tree *type_tree;
+
+ type = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = tvb_length(parameter_tvb) - length;
+
+ parameter_item = proto_tree_add_text(chunk_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), "%s parameter", val_to_str(type, parameter_identifier_values, "Unknown"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_sctp_chunk_parameter);
+
+ type_item = proto_tree_add_item(parameter_tree, hf_parameter_type, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ type_tree = proto_item_add_subtree(type_item, ett_sctp_parameter_type);
+ proto_tree_add_item(type_tree, hf_parameter_bit_1, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(type_tree, hf_parameter_bit_2, parameter_tvb, PARAMETER_TYPE_OFFSET, PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(type) {
+ case HEARTBEAT_INFO_PARAMETER_ID:
+ dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case IPV4ADDRESS_PARAMETER_ID:
+ dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
+ break;
+ case IPV6ADDRESS_PARAMETER_ID:
+ dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
+ break;
+ case STATE_COOKIE_PARAMETER_ID:
+ dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case UNREC_PARA_PARAMETER_ID:
+ dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo, parameter_tree);
+ break;
+ case COOKIE_PRESERVATIVE_PARAMETER_ID:
+ dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case HOSTNAME_ADDRESS_PARAMETER_ID:
+ dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
+ dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ECN_PARAMETER_ID:
+ dissect_ecn_parameter(parameter_tvb);
+ break;
+ case FORWARD_TSN_SUPPORTED_PARAMETER_ID:
+ dissect_forward_tsn_supported_parameter(parameter_tvb);
+ break;
+ case ADD_IP_ADDRESS_PARAMETER_ID:
+ dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
+ break;
+ case DEL_IP_ADDRESS_PARAMETER_ID:
+ dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
+ break;
+ case ERROR_CAUSE_INDICATION_PARAMETER_ID:
+ dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree);
+ break;
+ case SET_PRIMARY_ADDRESS_PARAMETER_ID:
+ dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
+ break;
+ case SUCCESS_REPORT_PARAMETER_ID:
+ dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ case ADAP_LAYER_INDICATION_PARAMETER_ID:
+ dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ default:
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ break;
+ }
+
+ if (padding_length > 0)
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_item *additional_item, gboolean dissecting_init_init_ack_chunk)
+{
+ gint offset, length, total_length, remaining_length;
+ tvbuff_t *parameter_tvb;
+
+ offset = 0;
+ while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
+ if ((offset > 0) && additional_item)
+ proto_item_append_text(additional_item, " ");
+ length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ if (remaining_length >= length)
+ total_length = MIN(total_length, remaining_length);
+ /* create a tvb for the parameter including the padding bytes */
+ parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
+ dissect_parameter(parameter_tvb, pinfo, tree, additional_item, dissecting_init_init_ack_chunk);
+ /* get rid of the handled parameter */
+ offset += total_length;
+ }
+}
+
+
+/*
+ * Code to handle error causes for ABORT and ERROR chunks
+ */
+
+
+#define CAUSE_CODE_LENGTH 2
+#define CAUSE_LENGTH_LENGTH 2
+#define CAUSE_HEADER_LENGTH (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
+
+#define CAUSE_HEADER_OFFSET 0
+#define CAUSE_CODE_OFFSET CAUSE_HEADER_OFFSET
+#define CAUSE_LENGTH_OFFSET (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
+#define CAUSE_INFO_OFFSET (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
+
+
+#define CAUSE_STREAM_IDENTIFIER_LENGTH 2
+#define CAUSE_RESERVED_LENGTH 2
+#define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
+#define CAUSE_RESERVED_OFFSET (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
+
+static void
+dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
+{
+ proto_tree_add_item(cause_tree, hf_cause_stream_identifier, cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(cause_tree, hf_cause_reserved, cause_tvb, CAUSE_RESERVED_OFFSET, CAUSE_RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(cause_item, " (SID: %u)", tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET));
+}
+
+#define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
+#define CAUSE_MISSING_PARAMETER_TYPE_LENGTH 2
+
+#define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
+#define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
+ CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
+
+static void
+dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
+{
+ guint32 number_of_missing_parameters, missing_parameter_number;
+ guint offset;
+
+ number_of_missing_parameters = tvb_get_ntohl(cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET);
+ proto_tree_add_item(cause_tree, hf_cause_number_of_missing_parameters, cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET, CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH, NETWORK_BYTE_ORDER);
+ offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
+ for(missing_parameter_number = 1; missing_parameter_number <= number_of_missing_parameters; missing_parameter_number++) {
+ proto_tree_add_item(cause_tree, hf_cause_missing_parameter_type, cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ offset += CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
+ }
+}
+
+#define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
+#define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
+
+static void
+dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
+{
+ proto_tree_add_item(cause_tree, hf_cause_measure_of_staleness, cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET, CAUSE_MEASURE_OF_STALENESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(cause_item, " (Measure: %u usec)", tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET));
+}
+
+static void
+dissect_out_of_resource_cause(tvbuff_t *cause_tvb _U_)
+{
+}
+
+static void
+dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
+{
+ guint16 parameter_length;
+ tvbuff_t *parameter_tvb;
+
+ parameter_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, parameter_length, parameter_length);
+ proto_item_append_text(cause_item, " (Address: ");
+ dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
+ proto_item_append_text(cause_item, ")");
+}
+
+static void
+dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
+{
+ guint16 chunk_length;
+ guint8 unrecognized_type;
+ tvbuff_t *unrecognized_chunk_tvb;
+
+ chunk_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ unrecognized_chunk_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, chunk_length, chunk_length);
+ dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree, FALSE);
+ unrecognized_type = tvb_get_guint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
+ proto_item_append_text(cause_item, " (Type: %u (%s))", unrecognized_type, val_to_str(unrecognized_type, chunk_type_values, "unknown"));
+}
+
+static void
+dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb _U_)
+{
+}
+
+static void
+dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
+{
+ guint16 cause_info_length;
+ tvbuff_t *unrecognized_parameters_tvb;
+
+ cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+
+ unrecognized_parameters_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
+ dissect_parameters(unrecognized_parameters_tvb, pinfo, cause_tree, NULL, FALSE);
+}
+
+#define CAUSE_TSN_LENGTH 4
+#define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
+
+static void
+dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
+{
+ proto_tree_add_item(cause_tree, hf_cause_tsn, cause_tvb, CAUSE_TSN_OFFSET, CAUSE_TSN_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(cause_item, " (TSN: %u)", tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET));
+}
+
+static void
+dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb _U_)
+{
+}
+
+static void
+dissect_restart_with_new_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree* cause_tree, proto_item *cause_item)
+{
+ guint16 cause_info_length;
+ tvbuff_t *parameter_tvb;
+
+ cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
+ proto_item_append_text(cause_item, " (New addresses: ");
+ dissect_parameters(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
+ proto_item_append_text(cause_item, ")");
+}
+
+static void
+dissect_user_initiated_abort_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
+{
+ guint16 cause_info_length;
+
+ cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ if (cause_info_length > 0)
+ proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_protocol_violation_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
+{
+ guint16 cause_info_length;
+
+ cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ if (cause_info_length > 0)
+ proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
+{
+ guint16 cause_info_length;
+ tvbuff_t *parameter_tvb;
+
+ cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
+ proto_item_append_text(cause_item, " (Last address: ");
+ dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
+ proto_item_append_text(cause_item, ")");
+}
+
+static void
+dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
+{
+ guint16 cause_info_length;
+ tvbuff_t *parameter_tvb;
+
+ cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
+ dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
+}
+
+static void
+dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
+{
+ guint16 cause_info_length;
+ tvbuff_t *parameter_tvb;
+
+ cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
+ proto_item_append_text(cause_item, " (Deleted address: ");
+ dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, FALSE);
+ proto_item_append_text(cause_item, ")");
+}
+
+static void
+dissect_request_refused_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
+{
+ guint16 cause_info_length;
+ tvbuff_t *parameter_tvb;
+
+ cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ parameter_tvb = tvb_new_subset(cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, cause_info_length);
+ dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, FALSE);
+}
+
+static void
+dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
+{
+ guint16 cause_info_length;
+
+ cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
+ if (cause_info_length > 0)
+ proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(cause_item, "Code: %u, information length: %u byte%s)", tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET), cause_info_length, plurality(cause_info_length, "", "s"));
+}
+
+#define INVALID_STREAM_IDENTIFIER 0x01
+#define MISSING_MANDATORY_PARAMETERS 0x02
+#define STALE_COOKIE_ERROR 0x03
+#define OUT_OF_RESOURCE 0x04
+#define UNRESOLVABLE_ADDRESS 0x05
+#define UNRECOGNIZED_CHUNK_TYPE 0x06
+#define INVALID_MANDATORY_PARAMETER 0x07
+#define UNRECOGNIZED_PARAMETERS 0x08
+#define NO_USER_DATA 0x09
+#define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN 0x0a
+#define RESTART_WITH_NEW_ADDRESSES 0x0b
+#define USER_INITIATED_ABORT 0x0c
+#define PROTOCOL_VIOLATION 0x0d
+#define REQUEST_TO_DELETE_LAST_ADDRESS 0x0100
+#define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0X0101
+#define REQUEST_TO_DELETE_SOURCE_ADDRESS 0x0102
+#define ABORT_DUE_TO_ILLEGAL_ASCONF 0x0103
+#define REQUESTION_REFUSED 0x0104
+
+static const value_string cause_code_values[] = {
+ { INVALID_STREAM_IDENTIFIER, "Invalid stream identifier" },
+ { MISSING_MANDATORY_PARAMETERS, "Missing mandatory parameter" },
+ { STALE_COOKIE_ERROR, "Stale cookie error" },
+ { OUT_OF_RESOURCE, "Out of resource" },
+ { UNRESOLVABLE_ADDRESS, "Unresolvable address" },
+ { UNRECOGNIZED_CHUNK_TYPE, "Unrecognized chunk type" },
+ { INVALID_MANDATORY_PARAMETER, "Invalid mandatory parameter" },
+ { UNRECOGNIZED_PARAMETERS, "Unrecognized parameters" },
+ { NO_USER_DATA, "No user data" },
+ { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN, "Cookie received while shutting down" },
+ { RESTART_WITH_NEW_ADDRESSES, "Restart of an association with new addresses" },
+ { USER_INITIATED_ABORT, "User initiated ABORT" },
+ { PROTOCOL_VIOLATION, "Protocol violation" },
+ { REQUEST_TO_DELETE_LAST_ADDRESS, "Request to delete last address" },
+ { OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE, "Operation refused due to resource shortage" },
+ { REQUEST_TO_DELETE_SOURCE_ADDRESS, "Request to delete source address" },
+ { ABORT_DUE_TO_ILLEGAL_ASCONF, "Association Aborted due to illegal ASCONF-ACK" },
+ { REQUESTION_REFUSED, "Request refused - no authorization" },
+ { 0, NULL } };
+
+
+static void
+dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
+{
+ guint16 code, length, padding_length;
+ proto_item *cause_item;
+ proto_tree *cause_tree;
+
+ code = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
+ length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
+ padding_length = tvb_length(cause_tvb) - length;
+
+ cause_item = proto_tree_add_text(chunk_tree, cause_tvb, CAUSE_HEADER_OFFSET, tvb_length(cause_tvb), "%s cause", val_to_str(code, cause_code_values, "Unknown"));
+ cause_tree = proto_item_add_subtree(cause_item, ett_sctp_chunk_cause);
+
+ proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb, CAUSE_CODE_OFFSET, CAUSE_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+
+ switch(code) {
+ case INVALID_STREAM_IDENTIFIER:
+ dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
+ break;
+ case MISSING_MANDATORY_PARAMETERS:
+ dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree);
+ break;
+ case STALE_COOKIE_ERROR:
+ dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
+ break;
+ case OUT_OF_RESOURCE:
+ dissect_out_of_resource_cause(cause_tvb);
+ break;
+ case UNRESOLVABLE_ADDRESS:
+ dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
+ break;
+ case UNRECOGNIZED_CHUNK_TYPE:
+ dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
+ break;
+ case INVALID_MANDATORY_PARAMETER:
+ dissect_invalid_mandatory_parameter_cause(cause_tvb);
+ break;
+ case UNRECOGNIZED_PARAMETERS:
+ dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree);
+ break;
+ case NO_USER_DATA:
+ dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
+ break;
+ case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
+ dissect_cookie_received_while_shutting_down_cause(cause_tvb);
+ break;
+ case RESTART_WITH_NEW_ADDRESSES:
+ dissect_restart_with_new_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
+ break;
+ case USER_INITIATED_ABORT:
+ dissect_user_initiated_abort_cause(cause_tvb, cause_tree);
+ break;
+ case PROTOCOL_VIOLATION:
+ dissect_protocol_violation_cause(cause_tvb, cause_tree);
+ break;
+ case REQUEST_TO_DELETE_LAST_ADDRESS:
+ dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
+ break;
+ case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
+ dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree);
+ break;
+ case REQUEST_TO_DELETE_SOURCE_ADDRESS:
+ dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
+ break;
+ case REQUESTION_REFUSED:
+ dissect_request_refused_cause(cause_tvb, pinfo, cause_tree);
+ break;
+ default:
+ dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
+ break;
+ }
+
+ if (padding_length > 0)
+ proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_error_causes(tvbuff_t *causes_tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gint offset, length, total_length, remaining_length;
+ tvbuff_t *cause_tvb;
+
+ offset = 0;
+ while((remaining_length = tvb_length_remaining(causes_tvb, offset))) {
+ length = tvb_get_ntohs(causes_tvb, offset + CAUSE_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ if (remaining_length >= length)
+ total_length = MIN(total_length, remaining_length);
+ /* create a tvb for the parameter including the padding bytes */
+ cause_tvb = tvb_new_subset(causes_tvb, offset, total_length, total_length);
+ dissect_error_cause(cause_tvb, pinfo, tree);
+ /* get rid of the handled cause */
+ offset += total_length;
+ }
+}
+
+
+/*
+ * Code to actually dissect the packets
+*/
+
+static gboolean try_heuristic_first = FALSE;
+
+static gboolean
+dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint32 ppi)
+{
+ guint32 low_port, high_port;
+
+ if (try_heuristic_first) {
+ /* do lookup with the heuristic subdissector table */
+ if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
+ return TRUE;
+ }
+
+ /* Do lookups with the subdissector table.
+
+ When trying port numbers, we try the port number with the lower value
+ first, followed by the port number with the higher value. This means
+ that, for packets where a dissector is registered for *both* port
+ numbers, and where there's no match on the PPI:
+
+ 1) we pick the same dissector for traffic going in both directions;
+
+ 2) we prefer the port number that's more likely to be the right
+ one (as that prefers well-known ports to reserved ports);
+
+ although there is, of course, no guarantee that any such strategy
+ will always pick the right port number.
+
+ XXX - we ignore port numbers of 0, as some dissectors use a port
+ number of 0 to disable the port. */
+ if (dissector_try_port(sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree))
+ return TRUE;
+ if (pinfo->srcport > pinfo->destport) {
+ low_port = pinfo->destport;
+ high_port = pinfo->srcport;
+ } else {
+ low_port = pinfo->srcport;
+ high_port = pinfo->destport;
+ }
+ if (low_port != 0 &&
+ dissector_try_port(sctp_port_dissector_table, low_port, payload_tvb, pinfo, tree))
+ return TRUE;
+ if (high_port != 0 &&
+ dissector_try_port(sctp_port_dissector_table, high_port, payload_tvb, pinfo, tree))
+ return TRUE;
+
+ if (!try_heuristic_first) {
+ /* do lookup with the heuristic subdissector table */
+ if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree))
+ return TRUE;
+ }
+
+ /* Oh, well, we don't know this; dissect it as data. */
+ call_dissector(data_handle, payload_tvb, pinfo, tree);
+ return TRUE;
+}
+
+#define DATA_CHUNK_TSN_LENGTH 4
+#define DATA_CHUNK_STREAM_ID_LENGTH 2
+#define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
+#define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
+
+#define DATA_CHUNK_TSN_OFFSET (CHUNK_VALUE_OFFSET + 0)
+#define DATA_CHUNK_STREAM_ID_OFFSET (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
+#define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
+ DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
+#define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
+ DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
+#define DATA_CHUNK_PAYLOAD_OFFSET (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
+ DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
+
+#define DATA_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
+ DATA_CHUNK_TSN_LENGTH + \
+ DATA_CHUNK_STREAM_ID_LENGTH + \
+ DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
+ DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
+
+#define SCTP_DATA_CHUNK_E_BIT 0x01
+#define SCTP_DATA_CHUNK_B_BIT 0x02
+#define SCTP_DATA_CHUNK_U_BIT 0x04
+
+static const true_false_string sctp_data_chunk_e_bit_value = {
+ "Last segment",
+ "Not the last segment"
+};
+
+static const true_false_string sctp_data_chunk_b_bit_value = {
+ "First segment",
+ "Subsequent segment"
+};
+
+static const true_false_string sctp_data_chunk_u_bit_value = {
+ "Unordered delivery",
+ "Ordered deliviery"
+};
+
+static gboolean
+dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
+{
+ guint16 payload_length;
+ guint32 payload_proto_id;
+ tvbuff_t *payload_tvb;
+ proto_tree *flags_tree;
+ guint8 e_bit, b_bit, u_bit;
+
+ payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
+
+ if (chunk_tree) {
+ proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
+ flags_tree = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
+ proto_tree_add_item(flags_tree, hf_data_chunk_e_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(flags_tree, hf_data_chunk_b_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(flags_tree, hf_data_chunk_u_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_data_chunk_tsn, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_data_chunk_stream_id, chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_data_chunk_stream_seq_number, chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET, DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_data_chunk_payload_proto_id, chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH, NETWORK_BYTE_ORDER);
+
+ e_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_E_BIT;
+ b_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_B_BIT;
+ u_bit = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_DATA_CHUNK_U_BIT;
+
+ proto_item_append_text(chunk_item, "(%s, ", (u_bit) ? "unordered" : "ordered");
+ if (b_bit) {
+ if (e_bit)
+ proto_item_append_text(chunk_item, "complete");
+ else
+ proto_item_append_text(chunk_item, "first");
+ } else {
+ if (e_bit)
+ proto_item_append_text(chunk_item, "last");
+ else
+ proto_item_append_text(chunk_item, "middle");
+ }
+
+ proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, SSN: %u, PPID: %u",
+ tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET),
+ tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
+ tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET),
+ payload_proto_id);
+ }
+ payload_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+ if (payload_length < DATA_CHUNK_HEADER_LENGTH) {
+ if (chunk_tree) {
+ proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
+ payload_length, DATA_CHUNK_HEADER_LENGTH);
+ }
+ return TRUE;
+ }
+ payload_length -= DATA_CHUNK_HEADER_LENGTH;
+ if (chunk_tree) {
+ proto_item_append_text(chunk_item, ", payload length: %u byte%s)",
+ payload_length, plurality(payload_length, "", "s"));
+ }
+ payload_tvb = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET, payload_length, payload_length);
+ return dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
+}
+
+#define INIT_CHUNK_INITIATE_TAG_LENGTH 4
+#define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
+#define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
+#define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH 2
+#define INIT_CHUNK_INITIAL_TSN_LENGTH 4
+#define INIT_CHUNK_FIXED_PARAMTERS_LENGTH (INIT_CHUNK_INITIATE_TAG_LENGTH + \
+ INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
+ INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
+ INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
+ INIT_CHUNK_INITIAL_TSN_LENGTH)
+
+#define INIT_CHUNK_INITIATE_TAG_OFFSET CHUNK_VALUE_OFFSET
+#define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (INIT_CHUNK_INITIATE_TAG_OFFSET + \
+ INIT_CHUNK_INITIATE_TAG_LENGTH )
+#define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
+ INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
+#define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
+ INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
+#define INIT_CHUNK_INITIAL_TSN_OFFSET (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
+ INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
+#define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET (INIT_CHUNK_INITIAL_TSN_OFFSET + \
+ INIT_CHUNK_INITIAL_TSN_LENGTH )
+
+static void
+dissect_init_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ gint parameters_length;
+ tvbuff_t *parameters_tvb;
+
+ if (chunk_tree) {
+ /* handle fixed parameters */
+ proto_tree_add_item(chunk_tree, hf_init_chunk_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item_hidden(chunk_tree, hf_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_init_chunk_adv_rec_window_credit, chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_inbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_init_chunk_initial_tsn, chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH, NETWORK_BYTE_ORDER);
+
+ /* handle variable paramters */
+ parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
+
+ proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
+ tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
+ tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
+ }
+}
+
+static void
+dissect_init_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ gint parameters_length;
+ tvbuff_t *parameters_tvb;
+
+ if (chunk_tree) {
+ /* handle fixed parameters */
+ proto_tree_add_item(chunk_tree, hf_initack_chunk_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item_hidden(chunk_tree, hf_initiate_tag, chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET, INIT_CHUNK_INITIATE_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_initack_chunk_adv_rec_window_credit, chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_inbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_initack_chunk_initial_tsn, chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET, INIT_CHUNK_INITIAL_TSN_LENGTH, NETWORK_BYTE_ORDER);
+
+ /* handle variable paramters */
+ parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - INIT_CHUNK_FIXED_PARAMTERS_LENGTH - CHUNK_HEADER_LENGTH;
+ parameters_tvb = tvb_new_subset(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, TRUE);
+
+ proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
+ tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
+ tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
+ }
+}
+
+#define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
+#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
+#define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH 2
+#define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH 2
+#define SACK_CHUNK_GAP_BLOCK_LENGTH 4
+#define SACK_CHUNK_GAP_BLOCK_START_LENGTH 2
+#define SACK_CHUNK_GAP_BLOCK_END_LENGTH 2
+#define SACK_CHUNK_DUP_TSN_LENGTH 4
+
+#define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
+#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
+ SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
+#define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
+ SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
+#define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
+ SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
+#define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
+ SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
+
+
+static void
+dissect_sack_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ guint16 number_of_gap_blocks, number_of_dup_tsns;
+ guint16 gap_block_number, dup_tsn_number, start, end;
+ gint gap_block_offset, dup_tsn_offset;
+ guint32 cum_tsn_ack;
+ proto_item *block_item;
+ proto_tree *block_tree;
+
+ if (chunk_tree) {
+ proto_tree_add_item(chunk_tree, hf_sack_chunk_cumulative_tsn_ack, chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_sack_chunk_adv_rec_window_credit, chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_gap_blocks, chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_dup_tsns, chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH, NETWORK_BYTE_ORDER);
+
+ /* handle the gap acknowledgement blocks */
+ number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
+ gap_block_offset = SACK_CHUNK_GAP_BLOCK_OFFSET;
+ cum_tsn_ack = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
+ for(gap_block_number = 1; gap_block_number <= number_of_gap_blocks; gap_block_number++) {
+ start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
+ end = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
+ block_item = proto_tree_add_text(chunk_tree, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
+ block_tree = proto_item_add_subtree(block_item, ett_sctp_sack_chunk_gap_block);
+ proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_start, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_end, chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH, SACK_CHUNK_GAP_BLOCK_END_LENGTH, NETWORK_BYTE_ORDER);
+ gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
+ }
+
+ /* handle the duplicate TSNs */
+ number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
+ dup_tsn_offset = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
+ for(dup_tsn_number = 1; dup_tsn_number <= number_of_dup_tsns; dup_tsn_number++) {
+ proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, SACK_CHUNK_DUP_TSN_LENGTH, NETWORK_BYTE_ORDER);
+ dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
+ }
+
+ proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, duplicate TSNs: %u)",
+ tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
+ tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET),
+ number_of_gap_blocks, number_of_dup_tsns);
+ }
+}
+
+#define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
+
+static void
+dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ tvbuff_t *parameter_tvb;
+ guint info_length;
+
+ if (chunk_tree) {
+ info_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
+ proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
+ parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
+ /* FIXME: Parameters or parameter? */
+ dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
+ }
+}
+
+static void
+dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ tvbuff_t *parameter_tvb;
+ guint info_length;
+
+ if (chunk_tree) {
+ info_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
+ proto_item_append_text(chunk_item, " (Information: %u byte%s)", info_length, plurality(info_length, "", "s"));
+ parameter_tvb = tvb_new_subset(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET, info_length, info_length);
+ /* FIXME: Parameters or parameter? */
+ dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, FALSE);
+ }
+}
+#define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
+
+static void
+dissect_abort_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
+{
+ guint16 causes_length;
+ tvbuff_t *causes_tvb;
+ proto_tree *flags_tree;
+
+ if (chunk_tree) {
+ flags_tree = proto_item_add_subtree(flags_item, ett_sctp_abort_chunk_flags);
+ proto_tree_add_item(flags_tree, hf_abort_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+
+ causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
+ causes_tvb = tvb_new_subset(chunk_tvb, CHUNK_VALUE_OFFSET, causes_length, causes_length);
+ dissect_error_causes(causes_tvb, pinfo, chunk_tree);
+ }
+}
+
+#define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
+#define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
+
+static void
+dissect_shutdown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ if (chunk_tree) {
+ proto_tree_add_item(chunk_tree, hf_shutdown_chunk_cumulative_tsn_ack, chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(chunk_item, " (Cumulative TSN ack: %u)", tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET));
+ }
+}
+
+static void
+dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb _U_)
+{
+}
+
+#define ERROR_CAUSE_IND_CAUSES_OFFSET CHUNK_VALUE_OFFSET
+
+static void
+dissect_error_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
+{
+ guint16 causes_length;
+ tvbuff_t *causes_tvb;
+
+ if (chunk_tree) {
+ causes_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
+ causes_tvb = tvb_new_subset(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET, causes_length, causes_length);
+ dissect_error_causes(causes_tvb, pinfo, chunk_tree);
+ }
+}
+
+#define COOKIE_OFFSET CHUNK_VALUE_OFFSET
+
+static void
+dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ guint cookie_length;
+
+ if (chunk_tree) {
+ cookie_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
+ proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, cookie_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", cookie_length, plurality(cookie_length, "", "s"));
+ }
+}
+
+static void
+dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb _U_)
+{
+}
+
+#define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
+#define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
+
+static void
+dissect_ecne_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ if (chunk_tree)
+ proto_tree_add_item(chunk_tree, hf_ecne_chunk_lowest_tsn, chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET));
+}
+
+#define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
+#define CWR_CHUNK_LOWEST_TSN_LENGTH 4
+
+static void
+dissect_cwr_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ if (chunk_tree)
+ proto_tree_add_item(chunk_tree, hf_cwr_chunk_lowest_tsn, chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET));
+}
+
+#define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
+
+
+static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
+ "No TCB destroyed",
+ "TCB destroyed"
+};
+
+
+static void
+dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *flags_item)
+{
+ proto_tree *flags_tree;
+
+ if (chunk_tree) {
+ flags_tree = proto_item_add_subtree(flags_item, ett_sctp_shutdown_complete_chunk_flags);
+ proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ }
+}
+
+#define FORWARD_TSN_CHUNK_TSN_LENGTH 4
+#define FORWARD_TSN_CHUNK_SID_LENGTH 2
+#define FORWARD_TSN_CHUNK_SSN_LENGTH 2
+#define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
+#define FORWARD_TSN_CHUNK_SID_OFFSET 0
+#define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
+
+static void
+dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ guint offset;
+ guint16 number_of_affected_streams, affected_stream, length;
+
+ if (chunk_tree) {
+ proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, NETWORK_BYTE_ORDER);
+ length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+ number_of_affected_streams = (length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
+ (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
+ offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
+
+ for(affected_stream = 0; affected_stream < number_of_affected_streams; affected_stream++) {
+ proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_sid, chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET, FORWARD_TSN_CHUNK_SID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_ssn, chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET, FORWARD_TSN_CHUNK_SSN_LENGTH, NETWORK_BYTE_ORDER);
+ offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
+ }
+ proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET));
+ }
+}
+
+#define SERIAL_NUMBER_LENGTH 4
+#define SERIAL_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
+#define ASCONF_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
+
+static void
+dissect_asconf_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
+{
+ guint parameters_length;
+ tvbuff_t *parameters_tvb;
+
+ if (chunk_tree) {
+ proto_tree_add_item(chunk_tree, hf_asconf_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
+ parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
+ parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
+ }
+}
+
+#define ASCONF_ACK_CHUNK_PARAMETERS_OFFSET (SERIAL_NUMBER_OFFSET + SERIAL_NUMBER_LENGTH)
+
+static void
+dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree)
+{
+ guint parameters_length;
+ tvbuff_t *parameters_tvb;
+
+ if (chunk_tree) {
+ proto_tree_add_item(chunk_tree, hf_asconf_ack_serial, chunk_tvb, SERIAL_NUMBER_OFFSET, SERIAL_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
+ parameters_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH - SERIAL_NUMBER_LENGTH;
+ parameters_tvb = tvb_new_subset(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET, parameters_length, parameters_length);
+ dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, FALSE);
+ }
+}
+
+#define PKTDROP_CHUNK_BANDWIDTH_LENGTH 4
+#define PKTDROP_CHUNK_QUEUESIZE_LENGTH 4
+#define PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH 2
+#define PKTDROP_CHUNK_RESERVED_SIZE_LENGTH 2
+
+#define PKTDROP_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
+ PKTDROP_CHUNK_BANDWIDTH_LENGTH + \
+ PKTDROP_CHUNK_QUEUESIZE_LENGTH + \
+ PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH + \
+ PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
+
+#define PKTDROP_CHUNK_BANDWIDTH_OFFSET CHUNK_VALUE_OFFSET
+#define PKTDROP_CHUNK_QUEUESIZE_OFFSET (PKTDROP_CHUNK_BANDWIDTH_OFFSET + PKTDROP_CHUNK_BANDWIDTH_LENGTH)
+#define PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET (PKTDROP_CHUNK_QUEUESIZE_OFFSET + PKTDROP_CHUNK_QUEUESIZE_LENGTH)
+#define PKTDROP_CHUNK_RESERVED_SIZE_OFFSET (PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET + PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH)
+#define PKTDROP_CHUNK_DATA_FIELD_OFFSET (PKTDROP_CHUNK_RESERVED_SIZE_OFFSET + PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
+
+#define SCTP_PKTDROP_CHUNK_M_BIT 0x01
+#define SCTP_PKTDROP_CHUNK_B_BIT 0x02
+#define SCTP_PKTDROP_CHUNK_T_BIT 0x04
+
+static const true_false_string sctp_pktdropk_m_bit_value = {
+ "Source is a middlebox",
+ "Source is an endhost"
+};
+
+/*
+static const true_false_string sctp_pktdropk_s_bit_value = {
+ "This is a summary",
+ "This is not a summary"
+};
+*/
+
+static const true_false_string sctp_pktdropk_b_bit_value = {
+ "SCTP checksum was incorrect",
+ "SCTP checksum was correct"
+};
+
+static const true_false_string sctp_pktdropk_t_bit_value = {
+ "Packet is truncated",
+ "Packet is not truncated"
+};
+
+static void
+dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
+{
+ guint16 data_field_length;
+ tvbuff_t *data_field_tvb;
+ proto_tree *flags_tree;
+
+ data_field_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - PKTDROP_CHUNK_HEADER_LENGTH;
+ data_field_tvb = tvb_new_subset(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, data_field_length, data_field_length);
+
+ if (chunk_tree) {
+ flags_tree = proto_item_add_subtree(flags_item, ett_sctp_pktdrop_chunk_flags);
+
+ proto_tree_add_item(flags_tree, hf_pktdrop_chunk_m_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+/*
+ proto_tree_add_item(flags_tree, hf_pktdrop_chunk_s_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+*/
+ proto_tree_add_item(flags_tree, hf_pktdrop_chunk_b_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(flags_tree, hf_pktdrop_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_bandwidth, chunk_tvb, PKTDROP_CHUNK_BANDWIDTH_OFFSET, PKTDROP_CHUNK_BANDWIDTH_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_queuesize, chunk_tvb, PKTDROP_CHUNK_QUEUESIZE_OFFSET, PKTDROP_CHUNK_QUEUESIZE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_truncated_length, chunk_tvb, PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET, PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_reserved, chunk_tvb, PKTDROP_CHUNK_RESERVED_SIZE_OFFSET, PKTDROP_CHUNK_RESERVED_SIZE_LENGTH, NETWORK_BYTE_ORDER);
+ if (tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_PKTDROP_CHUNK_T_BIT)
+ proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field, chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET, data_field_length, NETWORK_BYTE_ORDER);
+ else
+ dissect_sctp_packet(data_field_tvb, pinfo, chunk_tree, TRUE);
+ }
+}
+
+static void
+dissect_unknown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
+{
+ guint chunk_value_length;
+
+ if (chunk_tree) {
+ chunk_value_length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET) - CHUNK_HEADER_LENGTH;
+ if (chunk_value_length > 0)
+ proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, chunk_value_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(chunk_item, " (Type: %u, value length: %u byte%s)", tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET), chunk_value_length, plurality(chunk_value_length, "", "s"));
+ }
+}
+
+#define SCTP_CHUNK_BIT_1 0x80
+#define SCTP_CHUNK_BIT_2 0x40
+
+static const true_false_string sctp_chunk_bit_1_value = {
+ "Skip chunk and continue processing of the packet",
+ "Stop processing of the packet"
+};
+
+static const true_false_string sctp_chunk_bit_2_value = {
+ "Do report",
+ "Do not report"
+};
+
+
+static gboolean
+dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree, gboolean useinfo)
+{
+ guint8 type, flags;
+ guint16 length, padding_length;
+ gboolean result;
+ proto_item *flags_item;
+ proto_item *chunk_item;
+ proto_tree *chunk_tree;
+ proto_item *type_item;
+ proto_tree *type_tree;
+
+ result = FALSE;
+
+ /* first extract the chunk header */
+ type = tvb_get_guint8(chunk_tvb, CHUNK_TYPE_OFFSET);
+ flags = tvb_get_guint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
+ length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+ padding_length = tvb_length(chunk_tvb) - length;
+
+ if (useinfo && (check_col(pinfo->cinfo, COL_INFO)))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, chunk_type_values, "RESERVED"));
+
+ if (tree) {
+ /* create proto_tree stuff */
+ chunk_item = proto_tree_add_text(sctp_tree, chunk_tvb, CHUNK_HEADER_OFFSET, tvb_length(chunk_tvb), "%s chunk", val_to_str(type, chunk_type_values, "RESERVED"));
+ chunk_tree = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
+
+ /* then insert the chunk header components into the protocol tree */
+ type_item = proto_tree_add_item(chunk_tree, hf_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ type_tree = proto_item_add_subtree(type_item, ett_sctp_chunk_type);
+ proto_tree_add_item(type_tree, hf_chunk_bit_1, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(type_tree, hf_chunk_bit_2, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ flags_item = proto_tree_add_item(chunk_tree, hf_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ } else {
+ chunk_tree = NULL;
+ chunk_item = NULL;
+ flags_item = NULL;
+ };
+
+ /* now dissect the chunk value */
+
+ switch(type) {
+ case SCTP_DATA_CHUNK_ID:
+ result = dissect_data_chunk(chunk_tvb, pinfo, tree, chunk_tree, chunk_item, flags_item);
+ break;
+ case SCTP_INIT_CHUNK_ID:
+ dissect_init_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
+ break;
+ case SCTP_INIT_ACK_CHUNK_ID:
+ dissect_init_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
+ break;
+ case SCTP_SACK_CHUNK_ID:
+ dissect_sack_chunk(chunk_tvb, chunk_tree, chunk_item);
+ break;
+ case SCTP_HEARTBEAT_CHUNK_ID:
+ dissect_heartbeat_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
+ break;
+ case SCTP_HEARTBEAT_ACK_CHUNK_ID:
+ dissect_heartbeat_ack_chunk(chunk_tvb, pinfo, chunk_tree, chunk_item);
+ break;
+ case SCTP_ABORT_CHUNK_ID:
+ dissect_abort_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
+ break;
+ case SCTP_SHUTDOWN_CHUNK_ID:
+ dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item);
+ break;
+ case SCTP_SHUTDOWN_ACK_CHUNK_ID:
+ dissect_shutdown_ack_chunk(chunk_tvb);
+ break;
+ case SCTP_ERROR_CHUNK_ID:
+ dissect_error_chunk(chunk_tvb, pinfo, chunk_tree);
+ break;
+ case SCTP_COOKIE_ECHO_CHUNK_ID:
+ dissect_cookie_echo_chunk(chunk_tvb, chunk_tree, chunk_item);
+ break;
+ case SCTP_COOKIE_ACK_CHUNK_ID:
+ dissect_cookie_ack_chunk(chunk_tvb);
+ break;
+ case SCTP_ECNE_CHUNK_ID:
+ dissect_ecne_chunk(chunk_tvb, chunk_tree, chunk_item);
+ break;
+ case SCTP_CWR_CHUNK_ID:
+ dissect_cwr_chunk(chunk_tvb, chunk_tree, chunk_item);
+ break;
+ case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
+ dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, flags_item);
+ break;
+ case SCTP_FORWARD_TSN_CHUNK_ID:
+ dissect_forward_tsn_chunk(chunk_tvb, chunk_tree, chunk_item);
+ break;
+ case SCTP_ASCONF_ACK_CHUNK_ID:
+ dissect_asconf_ack_chunk(chunk_tvb, pinfo, chunk_tree);
+ break;
+ case SCTP_ASCONF_CHUNK_ID:
+ dissect_asconf_chunk(chunk_tvb, pinfo, chunk_tree);
+ break;
+ case SCTP_PKTDROP_CHUNK_ID:
+ col_set_writable(pinfo->cinfo, FALSE);
+ dissect_pktdrop_chunk(chunk_tvb, pinfo, chunk_tree, flags_item);
+ col_set_writable(pinfo->cinfo, TRUE);
+ break;
+ default:
+ dissect_unknown_chunk(chunk_tvb, chunk_tree, chunk_item);
+ break;
+ }
+
+ if (padding_length > 0)
+ proto_tree_add_item(chunk_tree, hf_chunk_padding, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+
+ if (useinfo && ((type == SCTP_DATA_CHUNK_ID) || show_always_control_chunks))
+ col_set_fence(pinfo->cinfo, COL_INFO);
+
+ return result;
+}
+
+static void
+dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *sctp_item, proto_tree *sctp_tree, gboolean encapsulated)
+{
+ tvbuff_t *chunk_tvb;
+ guint16 length, total_length, remaining_length;
+ gint last_offset, offset;
+ gboolean sctp_item_length_set;
+
+ /* the common header of the datagram is already handled */
+ last_offset = 0;
+ offset = COMMON_HEADER_LENGTH;
+ sctp_item_length_set = FALSE;
+
+ while((remaining_length = tvb_length_remaining(tvb, offset))) {
+ /* extract the chunk length and compute number of padding bytes */
+ length = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ if (remaining_length >= length)
+ total_length = MIN(total_length, remaining_length);
+ /* create a tvb for the chunk including the padding bytes */
+ chunk_tvb = tvb_new_subset(tvb, offset, total_length, total_length);
+
+ /* save it in the sctp_info structure */
+ if (!encapsulated) {
+ if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
+ sctp_info.tvb[sctp_info.number_of_tvbs++] = chunk_tvb;
+ else
+ sctp_info.incomplete = TRUE;
+ }
+
+ /* call dissect_sctp_chunk for the actual work */
+ if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree, !encapsulated) && (tree)) {
+ proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
+ sctp_item_length_set = TRUE;
+ offset += total_length;
+ last_offset = offset;
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, FALSE);
+ sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
+ sctp_item_length_set = FALSE;
+ }
+ } else {
+ /* get rid of the dissected chunk */
+ offset += total_length;
+ }
+ }
+ if (!sctp_item_length_set && (tree)) {
+ proto_item_set_len(sctp_item, offset - last_offset);
+ }
+}
+
+static void
+dissect_sctp_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean encapsulated)
+{
+ guint32 checksum = 0, calculated_crc32c = 0, calculated_adler32 = 0;
+ guint length;
+ gboolean crc32c_correct = FALSE, adler32_correct = FALSE;
+ proto_item *sctp_item;
+ proto_tree *sctp_tree;
+
+ length = tvb_length(tvb);
+ checksum = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
+ switch(sctp_checksum) {
+ case SCTP_CHECKSUM_NONE:
+ break;
+ case SCTP_CHECKSUM_ADLER32:
+ calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
+ adler32_correct = (checksum == calculated_adler32);
+ sctp_info.adler32_calculated = TRUE;
+ sctp_info.adler32_correct = adler32_correct;
+ break;
+ case SCTP_CHECKSUM_CRC32C:
+ calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
+ crc32c_correct = (checksum == calculated_crc32c);
+ sctp_info.crc32c_calculated = TRUE;
+ sctp_info.crc32c_correct = crc32c_correct;
+ break;
+ case SCTP_CHECKSUM_AUTOMATIC:
+ calculated_adler32 = sctp_adler32(tvb_get_ptr(tvb, 0, length), length);
+ adler32_correct = (checksum == calculated_adler32);
+ calculated_crc32c = sctp_crc32c(tvb_get_ptr(tvb, 0, length), length);
+ crc32c_correct = (checksum == calculated_crc32c);
+ sctp_info.adler32_calculated = TRUE;
+ sctp_info.adler32_correct = adler32_correct;
+ sctp_info.crc32c_calculated = TRUE;
+ sctp_info.crc32c_correct = crc32c_correct;
+ break;
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the sctp protocol tree */
+ sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, FALSE);
+ sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
+
+ /* add the components of the common header to the protocol tree */
+ proto_tree_add_item(sctp_tree, hf_source_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(sctp_tree, hf_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(sctp_tree, hf_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item_hidden(sctp_tree, hf_port, tvb, SOURCE_PORT_OFFSET, SOURCE_PORT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item_hidden(sctp_tree, hf_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, NETWORK_BYTE_ORDER);
+
+ length = tvb_length(tvb);
+ checksum = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
+ switch(sctp_checksum) {
+ case SCTP_CHECKSUM_NONE:
+ proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, checksum, "Checksum: 0x%08x (not verified)", checksum);
+ break;
+ case SCTP_CHECKSUM_ADLER32:
+ if (adler32_correct)
+ proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
+ checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
+ else
+ proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
+ checksum, "Checksum: 0x%08x (incorrect Adler32, should be 0x%08x)", checksum, calculated_adler32);
+ proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(adler32_correct));
+ break;
+ case SCTP_CHECKSUM_CRC32C:
+ if (crc32c_correct)
+ proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
+ checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
+ else
+ proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
+ checksum, "Checksum: 0x%08x (incorrect CRC32C, should be 0x%08x)", checksum, calculated_crc32c);
+ proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct));
+ break;
+ case SCTP_CHECKSUM_AUTOMATIC:
+ if ((adler32_correct) && !(crc32c_correct))
+ proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
+ checksum, "Checksum: 0x%08x (correct Adler32)", checksum);
+ else if (!(adler32_correct) && (crc32c_correct))
+ proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
+ checksum, "Checksum: 0x%08x (correct CRC32C)", checksum);
+ else if ((adler32_correct) && (crc32c_correct))
+ proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
+ checksum, "Checksum: 0x%08x (correct Adler32 and CRC32C)", checksum);
+ else
+ proto_tree_add_uint_format(sctp_tree, hf_checksum, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH,
+ checksum, "Checksum: 0x%08x (incorrect, should be 0x%08x (Adler32) or 0x%08x (CRC32C))",
+ checksum, calculated_adler32, calculated_crc32c);
+ proto_tree_add_boolean_hidden(sctp_tree, hf_checksum_bad, tvb, CHECKSUM_OFFSET, CHECKSUM_LENGTH, !(crc32c_correct || adler32_correct));
+ break;
+ }
+ } else {
+ sctp_tree = NULL;
+ sctp_item = NULL;
+ };
+ /* add all chunks of the sctp datagram to the protocol tree */
+ dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree, encapsulated);
+}
+
+static void
+dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 source_port, destination_port;
+
+ /* Extract the common header */
+ source_port = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
+ destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
+
+ /* update pi structure */
+ pinfo->ptype = PT_SCTP;
+ pinfo->srcport = source_port;
+ pinfo->destport = destination_port;
+
+ /* make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
+
+ /* Clear entries in Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "");
+
+ memset(&sctp_info, 0, sizeof(struct _sctp_info));
+ sctp_info.verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
+ dissect_sctp_packet(tvb, pinfo, tree, FALSE);
+ if (!pinfo->in_error_pkt)
+ tap_queue_packet(sctp_tap, pinfo, &sctp_info);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_sctp(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_source_port, { "Source port", "sctp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_destination_port, { "Destination port", "sctp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_port, { "Port", "sctp.port", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_verification_tag, { "Verification tag", "sctp.verification_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_checksum, { "Checksum", "sctp.checksum", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_checksum_bad, { "Bad checksum", "sctp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_chunk_type, { "Chunk type", "sctp.chunk_type", FT_UINT8, BASE_DEC, VALS(chunk_type_values), 0x0, "", HFILL } },
+ { &hf_chunk_flags, { "Chunk flags", "sctp.chunk_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_chunk_bit_1, { "Bit", "sctp.chunk_bit_1", FT_BOOLEAN, 8, TFS(&sctp_chunk_bit_1_value), SCTP_CHUNK_BIT_1, "", HFILL } },
+ { &hf_chunk_bit_2, { "Bit", "sctp.chunk_bit_2", FT_BOOLEAN, 8, TFS(&sctp_chunk_bit_2_value), SCTP_CHUNK_BIT_2, "", HFILL } },
+ { &hf_chunk_length, { "Chunk length", "sctp.chunk_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_chunk_padding, { "Chunk padding", "sctp.chunk_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_chunk_value, { "Chunk value", "sctp.chunk_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_cookie, { "Cookie", "sctp.cookie", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_initiate_tag, { "Initiate tag", "sctp.initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_init_chunk_initiate_tag, { "Initiate tag", "sctp.init_initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_init_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.init_credit", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_init_chunk_number_of_outbound_streams, { "Number of outbound streams", "sctp.init_nr_out_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_init_chunk_number_of_inbound_streams, { "Number of inbound streams", "sctp.init_nr_in_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_init_chunk_initial_tsn, { "Initial TSN", "sctp.init_initial_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_initack_chunk_initiate_tag, { "Initiate tag", "sctp.initack_initiate_tag", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_initack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.initack_credit", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_initack_chunk_number_of_outbound_streams, { "Number of outbound streams", "sctp.initack_nr_out_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_initack_chunk_number_of_inbound_streams, { "Number of inbound streams", "sctp.initack_nr_in_streams", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_initack_chunk_initial_tsn, { "Initial TSN", "sctp.initack_initial_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cumulative_tsn_ack, { "Cumulative TSN Ack", "sctp.cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_data_chunk_tsn, { "TSN", "sctp.data_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_data_chunk_stream_id, { "Stream Identifier", "sctp.data_sid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_data_chunk_stream_seq_number, { "Stream sequence number", "sctp.data_ssn", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_data_chunk_payload_proto_id, { "Payload protocol identifier", "sctp.data_payload_proto_id", FT_UINT32, BASE_DEC, VALS(sctp_payload_proto_id_values), 0x0, "", HFILL } },
+ { &hf_data_chunk_e_bit, { "E-Bit", "sctp.data_e_bit", FT_BOOLEAN, 8, TFS(&sctp_data_chunk_e_bit_value), SCTP_DATA_CHUNK_E_BIT, "", HFILL } },
+ { &hf_data_chunk_b_bit, { "B-Bit", "sctp.data_b_bit", FT_BOOLEAN, 8, TFS(&sctp_data_chunk_b_bit_value), SCTP_DATA_CHUNK_B_BIT, "", HFILL } },
+ { &hf_data_chunk_u_bit, { "U-Bit", "sctp.data_u_bit", FT_BOOLEAN, 8, TFS(&sctp_data_chunk_u_bit_value), SCTP_DATA_CHUNK_U_BIT, "", HFILL } },
+ { &hf_sack_chunk_cumulative_tsn_ack, { "Cumulative TSN ACK", "sctp.sack_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_sack_chunk_adv_rec_window_credit, { "Advertised receiver window credit (a_rwnd)", "sctp.sack_a_rwnd", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_sack_chunk_number_of_gap_blocks, { "Number of gap acknowldgement blocks ", "sctp.sack_number_of_gap_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_sack_chunk_number_of_dup_tsns, { "Number of duplicated TSNs", "sctp.sack_number_of_duplicated_tsns", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_sack_chunk_gap_block_start, { "Start", "sctp.sack_gap_block_start", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_sack_chunk_gap_block_end, { "End", "sctp.sack_gap_block_end", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_sack_chunk_duplicate_tsn, { "Duplicate TSN", "sctp.sack_duplicate_tsn", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_shutdown_chunk_cumulative_tsn_ack, { "Cumulative TSN Ack", "sctp.shutdown_cumulative_tsn_ack", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_ecne_chunk_lowest_tsn, { "Lowest TSN", "sctp.ecne_lowest_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cwr_chunk_lowest_tsn, { "Lowest TSN", "sctp.cwr_lowest_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_shutdown_complete_chunk_t_bit, { "T-Bit", "sctp.shutdown_complete_t_bit", FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT, "", HFILL } },
+ { &hf_abort_chunk_t_bit, { "T-Bit", "sctp.abort_t_bit", FT_BOOLEAN, 8, TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT, "", HFILL } },
+ { &hf_forward_tsn_chunk_tsn, { "New cumulative TSN", "sctp.forward_tsn_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_forward_tsn_chunk_sid, { "Stream identifier", "sctp.forward_tsn_sid", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_forward_tsn_chunk_ssn, { "Stream sequence number", "sctp.forward_tsn_ssn", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_type, { "Parameter type", "sctp.parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_identifier_values), 0x0, "", HFILL } },
+ { &hf_parameter_length, { "Parameter length", "sctp.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_value, { "Parameter value", "sctp.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_padding, { "Parameter padding", "sctp.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_bit_1, { "Bit", "sctp.parameter_bit_1", FT_BOOLEAN, 16, TFS(&sctp_parameter_bit_1_value), SCTP_PARAMETER_BIT_1, "", HFILL } },
+ { &hf_parameter_bit_2, { "Bit", "sctp.parameter_bit_2", FT_BOOLEAN, 16, TFS(&sctp_parameter_bit_2_value), SCTP_PARAMETER_BIT_2, "", HFILL } },
+ { &hf_ipv4_address, { "IP Version 4 address", "sctp.parameter_ipv4_address", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_ipv6_address, { "IP Version 6 address", "sctp.parameter_ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_heartbeat_info, { "Heartbeat information", "sctp.parameter_heartbeat_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_state_cookie, { "State cookie", "sctp.parameter_state_cookie", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_cookie_preservative_increment, { "Suggested Cookie life-span increment (msec)", "sctp.parameter_cookie_preservative_incr", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_hostname, { "Hostname", "sctp.parameter_hostname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_supported_address_type, { "Supported address type", "sctp.parameter_supported_addres_type", FT_UINT16, BASE_DEC, VALS(address_types_values), 0x0, "", HFILL } },
+ { &hf_asconf_serial, { "Serial Number", "sctp.asconf_serial_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_asconf_ack_serial, { "Serial Number", "sctp.asconf_ack_serial_number", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_correlation_id, { "Correlation_id", "sctp.correlation_id", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_adap_indication, { "Indication", "sctp.adapation_layer_indication", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_cause_code, { "Cause code", "sctp.cause_code", FT_UINT16, BASE_HEX, VALS(cause_code_values), 0x0, "", HFILL } },
+ { &hf_cause_length, { "Cause length", "sctp.cause_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause_info, { "Cause information", "sctp.cause_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_cause_padding, { "Cause padding", "sctp.cause_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_cause_stream_identifier, { "Stream identifier", "sctp.cause_stream_identifier", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause_reserved, { "Reserved", "sctp.cause_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause_number_of_missing_parameters, { "Number of missing parameters", "sctp.cause_nr_of_missing_parameters", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause_missing_parameter_type, { "Missing parameter type", "sctp.cause_missing_parameter_type", FT_UINT16, BASE_HEX, VALS(parameter_identifier_values), 0x0, "", HFILL } },
+ { &hf_cause_measure_of_staleness, { "Measure of staleness in usec", "sctp.cause_measure_of_staleness", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause_tsn, { "TSN", "sctp.cause_tsn", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_pktdrop_chunk_m_bit, { "M-Bit", "sctp.pckdrop_m_bit", FT_BOOLEAN, 8, TFS(&sctp_pktdropk_m_bit_value), SCTP_PKTDROP_CHUNK_M_BIT, "", HFILL } },
+ { &hf_pktdrop_chunk_b_bit, { "B-Bit", "sctp.pckdrop_b_bit", FT_BOOLEAN, 8, TFS(&sctp_pktdropk_b_bit_value), SCTP_PKTDROP_CHUNK_B_BIT, "", HFILL } },
+ { &hf_pktdrop_chunk_t_bit, { "T-Bit", "sctp.pckdrop_t_bit", FT_BOOLEAN, 8, TFS(&sctp_pktdropk_t_bit_value), SCTP_PKTDROP_CHUNK_T_BIT, "", HFILL } },
+ { &hf_pktdrop_chunk_bandwidth, { "Bandwidth", "sctp.pktdrop_bandwidth", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_pktdrop_chunk_queuesize, { "Queuesize", "sctp.pktdrop_queuesize", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_pktdrop_chunk_truncated_length, { "Truncated length", "sctp.pktdrop_truncated_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_pktdrop_chunk_reserved, { "Reserved", "sctp.pktdrop_reserved", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_pktdrop_chunk_data_field, { "Data field", "sctp.pktdrop_datafield", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_sctp,
+ &ett_sctp_chunk,
+ &ett_sctp_chunk_parameter,
+ &ett_sctp_chunk_cause,
+ &ett_sctp_chunk_type,
+ &ett_sctp_data_chunk_flags,
+ &ett_sctp_abort_chunk_flags,
+ &ett_sctp_shutdown_complete_chunk_flags,
+ &ett_sctp_pktdrop_chunk_flags,
+ &ett_sctp_parameter_type,
+ &ett_sctp_sack_chunk_gap_block,
+ &ett_sctp_unrecognized_parameter_parameter,
+ };
+
+ static enum_val_t sctp_checksum_options[] = {
+ { "none", "None", SCTP_CHECKSUM_NONE },
+ { "adler-32", "Adler 32", SCTP_CHECKSUM_ADLER32 },
+ { "crc-32c", "CRC 32c", SCTP_CHECKSUM_CRC32C },
+ { "automatic", "Automatic", SCTP_CHECKSUM_AUTOMATIC},
+ { NULL, NULL, 0 }
+ };
+
+ /* Register the protocol name and description */
+ proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
+ sctp_module = prefs_register_protocol(proto_sctp, NULL);
+ prefs_register_enum_preference(sctp_module, "checksum", "Checksum type",
+ "The type of checksum used in SCTP packets",
+ &sctp_checksum, sctp_checksum_options, FALSE);
+ prefs_register_bool_preference(sctp_module, "show_always_control_chunks",
+ "Show always control chunks",
+ "Show always SCTP control chunks in the Info column",
+ &show_always_control_chunks);
+ prefs_register_bool_preference(sctp_module, "try_heuristic_first",
+ "Try heuristic sub-dissectors first",
+ "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port or PPI",
+ &try_heuristic_first);
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_sctp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ sctp_tap = register_tap("sctp");
+ /* subdissector code */
+ sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", FT_UINT16, BASE_DEC);
+ sctp_ppi_dissector_table = register_dissector_table("sctp.ppi", "SCTP payload protocol identifier", FT_UINT32, BASE_HEX);
+ register_heur_dissector_list("sctp", &sctp_heur_subdissector_list);
+}
+
+void
+proto_reg_handoff_sctp(void)
+{
+ dissector_handle_t sctp_handle;
+
+ data_handle = find_dissector("data");
+ sctp_handle = create_dissector_handle(dissect_sctp, proto_sctp);
+ dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);
+ dissector_add("udp.port", UDP_TUNNELING_PORT, sctp_handle);
+}
diff --git a/epan/dissectors/packet-sctp.h b/epan/dissectors/packet-sctp.h
new file mode 100644
index 0000000000..72e5cd594f
--- /dev/null
+++ b/epan/dissectors/packet-sctp.h
@@ -0,0 +1,43 @@
+/* packet-sctp.h
+ *
+ * Defintion of SCTP specific structures used b tap listeners.
+ *
+ * $Id$
+ * Copyright 2004 Michael Tuexen <tuexen [AT] fh-muenster.de>
+
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_SCTP_H__
+#define __PACKET_SCTP_H__
+
+#define MAXIMUM_NUMBER_OF_TVBS 2048
+
+struct _sctp_info {
+ gboolean incomplete;
+ gboolean adler32_calculated;
+ gboolean adler32_correct;
+ gboolean crc32c_calculated;
+ gboolean crc32c_correct;
+ guint32 verification_tag;
+ guint32 number_of_tvbs;
+ tvbuff_t *tvb[MAXIMUM_NUMBER_OF_TVBS];
+};
+
+#endif
diff --git a/epan/dissectors/packet-sdlc.c b/epan/dissectors/packet-sdlc.c
new file mode 100644
index 0000000000..12a6e2c140
--- /dev/null
+++ b/epan/dissectors/packet-sdlc.c
@@ -0,0 +1,222 @@
+/* packet-sdlc.c
+ * Routines for SDLC frame disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "xdlc.h"
+
+/*
+ * See
+ *
+ * http://www.protocols.com/pbook/sna.htm
+ */
+
+static int proto_sdlc = -1;
+static int hf_sdlc_address = -1;
+static int hf_sdlc_control = -1;
+static int hf_sdlc_n_r = -1;
+static int hf_sdlc_n_s = -1;
+static int hf_sdlc_p = -1;
+static int hf_sdlc_f = -1;
+static int hf_sdlc_s_ftype = -1;
+static int hf_sdlc_u_modifier_cmd = -1;
+static int hf_sdlc_u_modifier_resp = -1;
+static int hf_sdlc_ftype_i = -1;
+static int hf_sdlc_ftype_s_u = -1;
+
+static gint ett_sdlc = -1;
+static gint ett_sdlc_control = -1;
+
+static dissector_handle_t sna_handle;
+static dissector_handle_t data_handle;
+
+static const xdlc_cf_items sdlc_cf_items = {
+ &hf_sdlc_n_r,
+ &hf_sdlc_n_s,
+ &hf_sdlc_p,
+ &hf_sdlc_f,
+ &hf_sdlc_s_ftype,
+ &hf_sdlc_u_modifier_cmd,
+ &hf_sdlc_u_modifier_resp,
+ &hf_sdlc_ftype_i,
+ &hf_sdlc_ftype_s_u
+};
+
+static void
+dissect_sdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *sdlc_tree;
+ proto_item *sdlc_ti;
+ guint8 address;
+ guint16 control;
+ int sdlc_header_len;
+ gboolean is_response;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SDLC");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ address = tvb_get_guint8(tvb, 0);
+ sdlc_header_len = 1; /* address */
+
+ /*
+ * XXX - is there something in the SDLC header that indicates
+ * how to interpret "command vs. response" based on the
+ * direction?
+ */
+ if (pinfo->p2p_dir == P2P_DIR_SENT) {
+ is_response = FALSE;
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
+ }
+ else {
+ /* XXX - what if the direction is unknown? */
+ is_response = TRUE;
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
+ }
+
+ if (tree) {
+ sdlc_ti = proto_tree_add_item(tree, proto_sdlc, tvb, 0, -1,
+ FALSE);
+ sdlc_tree = proto_item_add_subtree(sdlc_ti, ett_sdlc);
+
+ proto_tree_add_uint(sdlc_tree, hf_sdlc_address, tvb, 0, 1,
+ address);
+ } else {
+ sdlc_ti = NULL;
+ sdlc_tree = NULL;
+ }
+
+ /*
+ * XXX - SDLC has a mod-128 mode as well as a mod-7 mode.
+ * We can infer the mode from an SNRM/SRME frame, but if
+ * we don't see one of them, we may have to have a preference
+ * to control what to use.
+ */
+ control = dissect_xdlc_control(tvb, 1, pinfo, sdlc_tree, hf_sdlc_control,
+ ett_sdlc_control, &sdlc_cf_items, NULL, NULL, NULL,
+ is_response, FALSE, FALSE);
+ sdlc_header_len += XDLC_CONTROL_LEN(control, FALSE);
+
+ if (tree)
+ proto_item_set_len(sdlc_ti, sdlc_header_len);
+
+ /*
+ * XXX - is there an FCS at the end, at least in Sniffer
+ * captures? (There doesn't appear to be.)
+ */
+ next_tvb = tvb_new_subset(tvb, sdlc_header_len, -1, -1);
+ if (XDLC_IS_INFORMATION(control)) {
+ /* call the SNA dissector */
+ call_dissector(sna_handle, next_tvb, pinfo, tree);
+ } else
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_register_sdlc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_sdlc_address,
+ { "Address Field", "sdlc.address", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Address", HFILL }},
+
+ { &hf_sdlc_control,
+ { "Control Field", "sdlc.control", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Control field", HFILL }},
+
+ { &hf_sdlc_n_r,
+ { "N(R)", "sdlc.control.n_r", FT_UINT8, BASE_DEC,
+ NULL, XDLC_N_R_MASK, "", HFILL }},
+
+ { &hf_sdlc_n_s,
+ { "N(S)", "sdlc.control.n_s", FT_UINT8, BASE_DEC,
+ NULL, XDLC_N_S_MASK, "", HFILL }},
+
+ { &hf_sdlc_p,
+ { "Poll", "sdlc.control.p", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+
+ { &hf_sdlc_f,
+ { "Final", "sdlc.control.f", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+
+ { &hf_sdlc_s_ftype,
+ { "Supervisory frame type", "sdlc.control.s_ftype", FT_UINT8, BASE_HEX,
+ VALS(stype_vals), XDLC_S_FTYPE_MASK, "", HFILL }},
+
+ { &hf_sdlc_u_modifier_cmd,
+ { "Command", "sdlc.control.u_modifier_cmd", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, "", HFILL }},
+
+ { &hf_sdlc_u_modifier_resp,
+ { "Response", "sdlc.control.u_modifier_resp", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, "", HFILL }},
+
+ { &hf_sdlc_ftype_i,
+ { "Frame type", "sdlc.control.ftype", FT_UINT8, BASE_HEX,
+ VALS(ftype_vals), XDLC_I_MASK, "", HFILL }},
+
+ { &hf_sdlc_ftype_s_u,
+ { "Frame type", "sdlc.control.ftype", FT_UINT8, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_sdlc,
+ &ett_sdlc_control,
+ };
+
+ proto_sdlc = proto_register_protocol(
+ "Synchronous Data Link Control (SDLC)", "SDLC", "sdlc");
+ proto_register_field_array(proto_sdlc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_sdlc(void)
+{
+ dissector_handle_t sdlc_handle;
+
+ /*
+ * Get handle for the SNA dissector.
+ */
+ sna_handle = find_dissector("sna");
+ data_handle = find_dissector("data");
+
+ sdlc_handle = create_dissector_handle(dissect_sdlc, proto_sdlc);
+ dissector_add("wtap_encap", WTAP_ENCAP_SDLC, sdlc_handle);
+}
diff --git a/epan/dissectors/packet-sdp.c b/epan/dissectors/packet-sdp.c
new file mode 100644
index 0000000000..3460bca5f7
--- /dev/null
+++ b/epan/dissectors/packet-sdp.c
@@ -0,0 +1,1154 @@
+/* packet-sdp.c
+ * Routines for SDP packet disassembly (RFC 2327)
+ *
+ * Jason Lango <jal@netapp.com>
+ * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef NEED_INET_ATON_H
+# include <epan/inet_aton.h>
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include <epan/strutil.h>
+
+#include "packet-rtp.h"
+#include "rtp_pt.h"
+#include "packet-rtcp.h"
+
+
+static dissector_handle_t rtp_handle=NULL;
+static dissector_handle_t rtcp_handle=NULL;
+
+static int proto_sdp = -1;
+
+/* Top level fields */
+static int hf_protocol_version = -1;
+static int hf_owner = -1;
+static int hf_session_name = -1;
+static int hf_session_info = -1;
+static int hf_uri = -1;
+static int hf_email = -1;
+static int hf_phone = -1;
+static int hf_connection_info = -1;
+static int hf_bandwidth = -1;
+static int hf_timezone = -1;
+static int hf_encryption_key = -1;
+static int hf_session_attribute = -1;
+static int hf_media_attribute = -1;
+static int hf_time = -1;
+static int hf_repeat_time = -1;
+static int hf_media = -1;
+static int hf_media_title = -1;
+static int hf_unknown = -1;
+static int hf_invalid = -1;
+
+/* hf_owner subfields*/
+static int hf_owner_username = -1;
+static int hf_owner_sessionid = -1;
+static int hf_owner_version = -1;
+static int hf_owner_network_type = -1;
+static int hf_owner_address_type = -1;
+static int hf_owner_address = -1;
+
+/* hf_connection_info subfields */
+static int hf_connection_info_network_type = -1;
+static int hf_connection_info_address_type = -1;
+static int hf_connection_info_connection_address = -1;
+static int hf_connection_info_ttl = -1;
+static int hf_connection_info_num_addr = -1;
+
+/* hf_bandwidth subfields */
+static int hf_bandwidth_modifier = -1;
+static int hf_bandwidth_value = -1;
+
+/* hf_time subfields */
+static int hf_time_start = -1;
+static int hf_time_stop = -1;
+
+/* hf_repeat_time subfield */
+static int hf_repeat_time_interval = -1;
+static int hf_repeat_time_duration = -1;
+static int hf_repeat_time_offset = -1;
+
+/* hf_timezone subfields */
+static int hf_timezone_time = -1;
+static int hf_timezone_offset = -1;
+
+/* hf_encryption_key subfields */
+static int hf_encryption_key_type = -1;
+static int hf_encryption_key_data = -1;
+
+/* hf_session_attribute subfields */
+static int hf_session_attribute_field = -1;
+static int hf_session_attribute_value = -1;
+
+/* hf_media subfields */
+static int hf_media_media = -1;
+static int hf_media_port = -1;
+static int hf_media_portcount = -1;
+static int hf_media_proto = -1;
+static int hf_media_format = -1;
+
+/* hf_session_attribute subfields */
+static int hf_media_attribute_field = -1;
+static int hf_media_attribute_value = -1;
+
+/* trees */
+static int ett_sdp = -1;
+static int ett_sdp_owner = -1;
+static int ett_sdp_connection_info = -1;
+static int ett_sdp_bandwidth = -1;
+static int ett_sdp_time = -1;
+static int ett_sdp_repeat_time = -1;
+static int ett_sdp_timezone = -1;
+static int ett_sdp_encryption_key = -1;
+static int ett_sdp_session_attribute = -1;
+static int ett_sdp_media = -1;
+static int ett_sdp_media_attribute = -1;
+
+
+#define SDP_MAX_RTP_CHANNELS 4
+
+typedef struct {
+ char *connection_address;
+ char *connection_type;
+ char *media_port[SDP_MAX_RTP_CHANNELS];
+ char *media_proto[SDP_MAX_RTP_CHANNELS];
+ gint8 media_count;
+} transport_info_t;
+
+/* static functions */
+
+static void call_sdp_subdissector(tvbuff_t *tvb, int hf, proto_tree* ti,
+ transport_info_t *transport_info);
+
+/* Subdissector functions */
+static void dissect_sdp_owner(tvbuff_t *tvb, proto_item* ti);
+static void dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
+ transport_info_t *transport_info);
+static void dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti);
+static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti);
+static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti);
+static void dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti);
+static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti);
+static void dissect_sdp_session_attribute(tvbuff_t *tvb, proto_item *ti);
+static void dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
+ transport_info_t *transport_info);
+static void dissect_sdp_media_attribute(tvbuff_t *tvb, proto_item *ti);
+
+static void
+dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *sdp_tree;
+ proto_item *ti, *sub_ti;
+ gint offset = 0;
+ gint next_offset;
+ int linelen;
+ gboolean in_media_description;
+ guchar type;
+ guchar delim;
+ int datalen;
+ int tokenoffset;
+ int hf = -1;
+ char *string;
+
+ address src_addr;
+
+ transport_info_t transport_info;
+
+ guint32 ipv4_address=0;
+ guint32 ipv4_port=0;
+ gboolean is_rtp=FALSE;
+ gboolean is_ipv4_addr=FALSE;
+ struct in_addr ipaddr;
+ gint n;
+
+ /* Initialise RTP channel info */
+ transport_info.connection_address=NULL;
+ transport_info.connection_type=NULL;
+ for (n=0; n < SDP_MAX_RTP_CHANNELS; n++)
+ {
+ transport_info.media_port[n]=NULL;
+ transport_info.media_proto[n]=NULL;
+ }
+ transport_info.media_count = 0;
+
+
+ /*
+ * As RFC 2327 says, "SDP is purely a format for session
+ * description - it does not incorporate a transport protocol,
+ * and is intended to use different transport protocols as
+ * appropriate including the Session Announcement Protocol,
+ * Session Initiation Protocol, Real-Time Streaming Protocol,
+ * electronic mail using the MIME extensions, and the
+ * Hypertext Transport Protocol."
+ *
+ * We therefore don't set the protocol or info columns;
+ * instead, we append to them, so that we don't erase
+ * what the protocol inside which the SDP stuff resides
+ * put there.
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /* XXX: Needs description. */
+ col_append_str(pinfo->cinfo, COL_INFO, ", with session description");
+ }
+
+ ti = proto_tree_add_item(tree, proto_sdp, tvb, offset, -1, FALSE);
+ sdp_tree = proto_item_add_subtree(ti, ett_sdp);
+
+ /*
+ * Show the SDP message a line at a time.
+ */
+ in_media_description = FALSE;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end_unquoted(tvb, offset, -1,
+ &next_offset);
+
+ /*
+ * Line must contain at least e.g. "v=".
+ */
+ if (linelen < 2)
+ break;
+
+ type = tvb_get_guint8(tvb,offset);
+ delim = tvb_get_guint8(tvb,offset + 1);
+ if (delim != '=') {
+ proto_tree_add_item(sdp_tree,hf_invalid,tvb, offset,
+ linelen, FALSE);
+ offset = next_offset;
+ continue;
+ }
+
+ /*
+ * Attributes.
+ */
+ switch (type) {
+ case 'v':
+ hf = hf_protocol_version;
+ break;
+ case 'o':
+ hf = hf_owner;
+ break;
+ case 's':
+ hf = hf_session_name;
+ break;
+ case 'i':
+ if (in_media_description) {
+ hf = hf_media_title;
+ }
+ else{
+ hf = hf_session_info;
+ }
+ break;
+ case 'u':
+ hf = hf_uri;
+ break;
+ case 'e':
+ hf = hf_email;
+ break;
+ case 'p':
+ hf = hf_phone;
+ break;
+ case 'c':
+ hf = hf_connection_info;
+ break;
+ case 'b':
+ hf = hf_bandwidth;
+ break;
+ case 't':
+ hf = hf_time;
+ break;
+ case 'r':
+ hf = hf_repeat_time;
+ break;
+ case 'm':
+ hf = hf_media;
+ in_media_description = TRUE;
+ break;
+ case 'k':
+ hf = hf_encryption_key;
+ break;
+ case 'a':
+ if (in_media_description) {
+ hf = hf_media_attribute;
+ }
+ else{
+ hf = hf_session_attribute;
+ }
+ break;
+ case 'z':
+ hf = hf_timezone;
+ break;
+ default:
+ hf = hf_unknown;
+ break;
+ }
+ tokenoffset = 2;
+ if (hf == hf_unknown)
+ tokenoffset = 0;
+ string = tvb_get_string(tvb, offset + tokenoffset,
+ linelen - tokenoffset);
+ sub_ti = proto_tree_add_string_format(sdp_tree,hf,tvb, offset,
+ linelen, string,
+ "%s: %s",
+ proto_registrar_get_name(hf),
+ format_text(string,
+ linelen - tokenoffset));
+ g_free(string);
+ call_sdp_subdissector(tvb_new_subset(tvb,offset+tokenoffset,
+ linelen-tokenoffset,
+ linelen-tokenoffset),
+ hf,sub_ti,&transport_info),
+ offset = next_offset;
+ }
+
+
+ /* Now look, if we have strings collected.
+ * Try to convert ipv4 addresses and ports into binary format,
+ * so we can use them to detect rtp and rtcp streams.
+ * Don't forget to free the strings!
+ */
+
+ for (n = 0; n < transport_info.media_count; n++)
+ {
+ if(transport_info.media_port[n]!=NULL) {
+ ipv4_port = atol(transport_info.media_port[n]);
+ g_free(transport_info.media_port[n]);
+ }
+ if(transport_info.media_proto[n]!=NULL) {
+ /* Check if media protocol is RTP */
+ is_rtp = (strcmp(transport_info.media_proto[n],"RTP/AVP")==0);
+ g_free(transport_info.media_proto[n]);
+ }
+ if(transport_info.connection_address!=NULL) {
+ if(transport_info.connection_type!=NULL &&
+ strcmp(transport_info.connection_type,"IP4")==0) {
+ if(inet_aton(transport_info.connection_address, &ipaddr)
+ !=0 ) {
+ /* connection_address could be converted to a valid ipv4 address*/
+ is_ipv4_addr=TRUE;
+ ipv4_address = ipaddr.s_addr;
+ }
+ }
+ }
+
+ /* Add rtp and rtcp conversation, if available */
+ if((!pinfo->fd->flags.visited) && ipv4_address!=0 && ipv4_port!=0 && is_rtp && is_ipv4_addr){
+ src_addr.type=AT_IPv4;
+ src_addr.len=4;
+ src_addr.data=(char *)&ipv4_address;
+
+ if(rtp_handle){
+ rtp_add_address(pinfo, (char *)&ipv4_address, ipv4_port, 0,
+ "SDP", pinfo->fd->num);
+ }
+
+ if(rtcp_handle){
+ ipv4_port++;
+ rtcp_add_address(pinfo, (char *)&ipv4_address, ipv4_port, 0,
+ "SDP", pinfo->fd->num);
+ }
+ }
+ }
+
+ /* Free up 'connection info' strings */
+ if(transport_info.connection_address) {
+ g_free(transport_info.connection_address);
+ }
+ if(transport_info.connection_type!=NULL) {
+ g_free(transport_info.connection_type);
+ }
+
+
+ datalen = tvb_length_remaining(tvb, offset);
+ if (datalen > 0) {
+ proto_tree_add_text(sdp_tree, tvb, offset, datalen,
+ "Data (%d bytes)", datalen);
+ }
+}
+
+static void
+call_sdp_subdissector(tvbuff_t *tvb, int hf, proto_tree* ti,
+ transport_info_t *transport_info){
+ if(hf == hf_owner){
+ dissect_sdp_owner(tvb,ti);
+ } else if ( hf == hf_connection_info) {
+ dissect_sdp_connection_info(tvb,ti,transport_info);
+ } else if ( hf == hf_bandwidth) {
+ dissect_sdp_bandwidth(tvb,ti);
+ } else if ( hf == hf_time) {
+ dissect_sdp_time(tvb,ti);
+ } else if ( hf == hf_repeat_time ){
+ dissect_sdp_repeat_time(tvb,ti);
+ } else if ( hf == hf_timezone ) {
+ dissect_sdp_timezone(tvb,ti);
+ } else if ( hf == hf_encryption_key ) {
+ dissect_sdp_encryption_key(tvb,ti);
+ } else if ( hf == hf_session_attribute ){
+ dissect_sdp_session_attribute(tvb,ti);
+ } else if ( hf == hf_media ) {
+ dissect_sdp_media(tvb,ti,transport_info);
+ } else if ( hf == hf_media_attribute ){
+ dissect_sdp_media_attribute(tvb,ti);
+ }
+}
+
+static void
+dissect_sdp_owner(tvbuff_t *tvb, proto_item *ti){
+ proto_tree *sdp_owner_tree;
+ gint offset,next_offset,tokenlen;
+
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_owner_tree = proto_item_add_subtree(ti,ett_sdp_owner);
+
+ /* Find the username */
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_owner_tree,hf_owner_username,tvb, offset,tokenlen,
+ FALSE);
+ offset = next_offset + 1;
+
+ /* Find the session id */
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_owner_tree,hf_owner_sessionid, tvb,
+ offset,tokenlen,FALSE);
+ offset = next_offset + 1;
+
+ /* Find the version */
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_owner_tree,hf_owner_version, tvb,
+ offset,tokenlen,FALSE);
+ offset = next_offset + 1;
+
+ /* Find the network type */
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_owner_tree,hf_owner_network_type, tvb,
+ offset,tokenlen,FALSE);
+ offset = next_offset + 1;
+
+ /* Find the address type */
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_owner_tree,hf_owner_address_type, tvb,
+ offset,tokenlen,FALSE);
+ offset = next_offset + 1;
+
+ /* Find the address */
+ proto_tree_add_item(sdp_owner_tree,hf_owner_address, tvb, offset, -1, FALSE);
+}
+
+/*
+ * XXX - this can leak memory if an exception is thrown after we've fetched
+ * a string.
+ */
+static void
+dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
+ transport_info_t *transport_info){
+ proto_tree *sdp_connection_info_tree;
+ gint offset,next_offset,tokenlen;
+
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_connection_info_tree = proto_item_add_subtree(ti,
+ ett_sdp_connection_info);
+
+ /* Find the network type */
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_connection_info_tree,
+ hf_connection_info_network_type,tvb,
+ offset,tokenlen,FALSE);
+ offset = next_offset + 1;
+
+ /* Find the address type */
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+ tokenlen = next_offset - offset;
+ /* Save connection address type */
+ transport_info->connection_type = tvb_get_string(tvb, offset, tokenlen);
+
+
+ proto_tree_add_item(sdp_connection_info_tree,
+ hf_connection_info_address_type,tvb,
+ offset,tokenlen,FALSE);
+ offset = next_offset + 1;
+
+ /* Find the connection address */
+ /* XXX - what if there's a <number of addresses> value? */
+ next_offset = tvb_find_guint8(tvb,offset,-1,'/');
+ if( next_offset == -1){
+ tokenlen = -1; /* end of tvbuff */
+ /* Save connection address */
+ transport_info->connection_address =
+ tvb_get_string(tvb, offset, tvb_length_remaining(tvb, offset));
+ } else {
+ tokenlen = next_offset - offset;
+ /* Save connection address */
+ transport_info->connection_address = tvb_get_string(tvb, offset, tokenlen);
+ }
+
+ proto_tree_add_item(sdp_connection_info_tree,
+ hf_connection_info_connection_address, tvb,
+ offset,tokenlen,FALSE);
+ if(next_offset != -1){
+ offset = next_offset + 1;
+ next_offset = tvb_find_guint8(tvb,offset,-1,'/');
+ if( next_offset == -1){
+ tokenlen = -1; /* end of tvbuff */
+ } else {
+ tokenlen = next_offset - offset;
+ }
+ proto_tree_add_item(sdp_connection_info_tree,
+ hf_connection_info_ttl,tvb,offset,tokenlen,FALSE);
+ if(next_offset != -1){
+ offset = next_offset + 1;
+ proto_tree_add_item(sdp_connection_info_tree,
+ hf_connection_info_num_addr, tvb,
+ offset, -1, FALSE);
+ }
+ }
+}
+
+static void
+dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti){
+ proto_tree * sdp_bandwidth_tree;
+ gint offset, next_offset, tokenlen;
+
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_bandwidth_tree = proto_item_add_subtree(ti,ett_sdp_bandwidth);
+
+ /* find the modifier */
+ next_offset = tvb_find_guint8(tvb,offset,-1,':');
+
+ if( next_offset == -1)
+ return;
+
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_modifier,
+ tvb, offset, tokenlen, FALSE);
+
+ offset = next_offset + 1;
+
+ proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_value,
+ tvb, offset, -1, FALSE);
+
+}
+
+static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti){
+ proto_tree *sdp_time_tree;
+ gint offset,next_offset, tokenlen;
+
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_time_tree = proto_item_add_subtree(ti,ett_sdp_time);
+
+ /* get start time */
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+
+ tokenlen = next_offset - offset;
+ proto_tree_add_item(sdp_time_tree, hf_time_start, tvb,
+ offset, tokenlen, FALSE);
+
+ /* get stop time */
+ offset = next_offset + 1;
+ proto_tree_add_item(sdp_time_tree, hf_time_stop, tvb,
+ offset, -1, FALSE);
+}
+
+static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti){
+ proto_tree *sdp_repeat_time_tree;
+ gint offset,next_offset, tokenlen;
+
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_repeat_time_tree = proto_item_add_subtree(ti,ett_sdp_time);
+
+ /* get interval */
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+
+ tokenlen = next_offset - offset;
+ proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_interval, tvb,
+ offset, tokenlen, FALSE);
+
+ /* get duration */
+ offset = next_offset + 1;
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if( next_offset == -1 )
+ return;
+
+ tokenlen = next_offset - offset;
+ proto_tree_add_item(sdp_repeat_time_tree,hf_repeat_time_duration, tvb,
+ offset, tokenlen, FALSE);
+
+ /* get offsets */
+ do{
+ offset = next_offset +1;
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if(next_offset != -1){
+ tokenlen = next_offset - offset;
+ } else {
+ tokenlen = -1; /* end of tvbuff */
+ }
+ proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_offset,
+ tvb, offset, tokenlen, FALSE);
+ } while( next_offset != -1 );
+
+}
+static void
+dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti){
+ proto_tree* sdp_timezone_tree;
+ gint offset, next_offset, tokenlen;
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_timezone_tree = proto_item_add_subtree(ti,ett_sdp_timezone);
+
+ do{
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if(next_offset == -1)
+ break;
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_timezone_tree,hf_timezone_time,tvb,
+ offset, tokenlen, FALSE);
+ offset = next_offset + 1;
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+ if(next_offset != -1){
+ tokenlen = next_offset - offset;
+ } else {
+ tokenlen = -1; /* end of tvbuff */
+ }
+ proto_tree_add_item(sdp_timezone_tree,hf_timezone_offset,tvb,
+ offset, tokenlen, FALSE);
+ offset = next_offset + 1;
+ } while (next_offset != -1);
+
+}
+
+
+static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti){
+ proto_tree *sdp_encryption_key_tree;
+ gint offset, next_offset, tokenlen;
+
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_encryption_key_tree = proto_item_add_subtree(ti,ett_sdp_encryption_key);
+
+ next_offset = tvb_find_guint8(tvb,offset,-1,':');
+
+ if(next_offset == -1)
+ return;
+
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_encryption_key_tree,hf_encryption_key_type,
+ tvb, offset, tokenlen, FALSE);
+
+ offset = next_offset + 1;
+ proto_tree_add_item(sdp_encryption_key_tree,hf_encryption_key_data,
+ tvb, offset, -1, FALSE);
+
+}
+
+
+
+static void dissect_sdp_session_attribute(tvbuff_t *tvb, proto_item * ti){
+ proto_tree *sdp_session_attribute_tree;
+ gint offset, next_offset, tokenlen;
+
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_session_attribute_tree = proto_item_add_subtree(ti,
+ ett_sdp_session_attribute);
+
+ next_offset = tvb_find_guint8(tvb,offset,-1,':');
+
+ if(next_offset == -1)
+ return;
+
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_session_attribute_tree,
+ hf_session_attribute_field,
+ tvb, offset, tokenlen, FALSE);
+
+ offset = next_offset + 1;
+ proto_tree_add_item(sdp_session_attribute_tree,
+ hf_session_attribute_value,
+ tvb, offset, -1, FALSE);
+
+}
+
+static void
+dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
+ transport_info_t *transport_info){
+ proto_tree *sdp_media_tree;
+ gint offset, next_offset, tokenlen;
+ guint8 *media_format;
+
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_media_tree = proto_item_add_subtree(ti,ett_sdp_media);
+
+ next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
+
+ if(next_offset == -1)
+ return;
+
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_media_tree, hf_media_media, tvb,
+ offset, tokenlen, FALSE);
+
+ offset = next_offset + 1;
+
+ next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
+ if(next_offset == -1)
+ return;
+ tokenlen = next_offset - offset;
+ next_offset = tvb_find_guint8(tvb,offset, tokenlen, '/');
+
+ if(next_offset != -1){
+ tokenlen = next_offset - offset;
+ /* Save port info */
+ transport_info->media_port[transport_info->media_count] = tvb_get_string(tvb, offset, tokenlen);
+
+ proto_tree_add_item(sdp_media_tree, hf_media_port, tvb,
+ offset, tokenlen, FALSE);
+ offset = next_offset + 1;
+ next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
+ if(next_offset == -1)
+ return;
+ tokenlen = next_offset - offset;
+ proto_tree_add_item(sdp_media_tree, hf_media_portcount, tvb,
+ offset, tokenlen, FALSE);
+ offset = next_offset + 1;
+ } else {
+ next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
+
+ if(next_offset == -1)
+ return;
+ tokenlen = next_offset - offset;
+ /* Save port info */
+ transport_info->media_port[transport_info->media_count] = tvb_get_string(tvb, offset, tokenlen);
+
+ /* XXX Remember Port */
+ proto_tree_add_item(sdp_media_tree, hf_media_port, tvb,
+ offset, tokenlen, FALSE);
+ offset = next_offset + 1;
+ }
+
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+
+ if( next_offset == -1)
+ return;
+
+ tokenlen = next_offset - offset;
+ /* Save port protocol */
+ transport_info->media_proto[transport_info->media_count] = tvb_get_string(tvb, offset, tokenlen);
+
+ /* XXX Remember Protocol */
+ proto_tree_add_item(sdp_media_tree, hf_media_proto, tvb,
+ offset, tokenlen, FALSE);
+
+ do{
+ offset = next_offset + 1;
+ next_offset = tvb_find_guint8(tvb,offset,-1,' ');
+
+ if(next_offset == -1){
+ tokenlen = tvb_length_remaining(tvb, offset); /* End of tvbuff */
+ if (tokenlen == 0)
+ break; /* Nothing more left */
+ } else {
+ tokenlen = next_offset - offset;
+ }
+
+ media_format = tvb_get_string(tvb, offset, tokenlen);
+ if (!strcmp(transport_info->media_proto[transport_info->media_count], "RTP/AVP")) {
+ proto_tree_add_string(sdp_media_tree, hf_media_format, tvb,
+ offset, tokenlen, val_to_str(atol(media_format), rtp_payload_type_vals, "%u"));
+ } else {
+ proto_tree_add_item(sdp_media_tree, hf_media_format, tvb,
+ offset, tokenlen, FALSE);
+ }
+ } while (next_offset != -1);
+
+ /* Increase the count of media channels, but don't walk off the end
+ of the arrays. */
+ if (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1)){
+ transport_info->media_count++;
+ }
+
+ /* XXX Dissect traffic to "Port" as "Protocol"
+ * Remember this Port/Protocol pair so we can tear it down again later
+ * Actually, it's harder than that:
+ * We need to find out the address of the other side first and it
+ * looks like that info can be found in SIP headers only.
+ */
+
+}
+
+static void dissect_sdp_media_attribute(tvbuff_t *tvb, proto_item * ti){
+ proto_tree *sdp_media_attribute_tree;
+ gint offset, next_offset, tokenlen;
+
+ offset = 0;
+ next_offset = 0;
+ tokenlen = 0;
+
+ sdp_media_attribute_tree = proto_item_add_subtree(ti,
+ ett_sdp_media_attribute);
+
+ next_offset = tvb_find_guint8(tvb,offset,-1,':');
+
+ if(next_offset == -1)
+ return;
+
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(sdp_media_attribute_tree,
+ hf_media_attribute_field,
+ tvb, offset, tokenlen, FALSE);
+
+ offset = next_offset + 1;
+ proto_tree_add_item(sdp_media_attribute_tree,
+ hf_media_attribute_value,
+ tvb, offset, -1, FALSE);
+
+}
+
+void
+proto_register_sdp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_protocol_version,
+ { "Session Description Protocol Version (v)",
+ "sdp.version", FT_STRING, BASE_NONE,NULL,0x0,
+ "Session Description Protocol Version", HFILL }},
+ { &hf_owner,
+ { "Owner/Creator, Session Id (o)",
+ "sdp.owner", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Owner/Creator, Session Id", HFILL}},
+ { &hf_session_name,
+ { "Session Name (s)",
+ "sdp.session_name", FT_STRING, BASE_NONE,NULL, 0x0,
+ "Session Name", HFILL }},
+ { &hf_session_info,
+ { "Session Information (i)",
+ "sdp.session_info", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Session Information", HFILL }},
+ { &hf_uri,
+ { "URI of Description (u)",
+ "sdp.uri", FT_STRING, BASE_NONE,NULL, 0x0,
+ "URI of Description", HFILL }},
+ { &hf_email,
+ { "E-mail Address (e)",
+ "sdp.email", FT_STRING, BASE_NONE, NULL, 0x0,
+ "E-mail Address", HFILL }},
+ { &hf_phone,
+ { "Phone Number (p)",
+ "sdp.phone", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Phone Number", HFILL }},
+ { &hf_connection_info,
+ { "Connection Information (c)",
+ "sdp.connection_info", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Connection Information", HFILL }},
+ { &hf_bandwidth,
+ { "Bandwidth Information (b)",
+ "sdp.bandwidth", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Bandwidth Information", HFILL }},
+ { &hf_timezone,
+ { "Time Zone Adjustments (z)",
+ "sdp.timezone", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Time Zone Adjustments", HFILL }},
+ { &hf_encryption_key,
+ { "Encryption Key (k)",
+ "sdp.encryption_key", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Encryption Key", HFILL }},
+ { &hf_session_attribute,
+ { "Session Attribute (a)",
+ "sdp.session_attr", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Session Attribute", HFILL }},
+ { &hf_media_attribute,
+ { "Media Attribute (a)",
+ "sdp.media_attr", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Attribute", HFILL }},
+ { &hf_time,
+ { "Time Description, active time (t)",
+ "sdp.time", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Time Description, active time", HFILL }},
+ { &hf_repeat_time,
+ { "Repeat Time (r)",
+ "sdp.repeat_time", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Repeat Time", HFILL }},
+ { &hf_media,
+ { "Media Description, name and address (m)",
+ "sdp.media", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Description, name and address", HFILL }},
+ { &hf_media_title,
+ { "Media Title (i)",
+ "sdp.media_title",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Title", HFILL }},
+ { &hf_unknown,
+ { "Unknown",
+ "sdp.unknown",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Unknown", HFILL }},
+ { &hf_invalid,
+ { "Invalid line",
+ "sdp.invalid",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Invalid line", HFILL }},
+ { &hf_owner_username,
+ { "Owner Username",
+ "sdp.owner.username",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Owner Username", HFILL }},
+ { &hf_owner_sessionid,
+ { "Session ID",
+ "sdp.owner.sessionid",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Session ID", HFILL }},
+ { &hf_owner_version,
+ { "Session Version",
+ "sdp.owner.version",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Session Version", HFILL }},
+ { &hf_owner_network_type,
+ { "Owner Network Type",
+ "sdp.owner.network_type",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Owner Network Type", HFILL }},
+ { &hf_owner_address_type,
+ { "Owner Address Type",
+ "sdp.owner.address_type",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Owner Address Type", HFILL }},
+ { &hf_owner_address,
+ { "Owner Address",
+ "sdp.owner.address",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Owner Address", HFILL }},
+ { &hf_connection_info_network_type,
+ { "Connection Network Type",
+ "sdp.connection_info.network_type",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Connection Network Type", HFILL }},
+ { &hf_connection_info_address_type,
+ { "Connection Address Type",
+ "sdp.connection_info.address_type",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Connection Address Type", HFILL }},
+ { &hf_connection_info_connection_address,
+ { "Connection Address",
+ "sdp.connection_info.address",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Connection Address", HFILL }},
+ { &hf_connection_info_ttl,
+ { "Connection TTL",
+ "sdp.connection_info.ttl",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Connection TTL", HFILL }},
+ { &hf_connection_info_num_addr,
+ { "Connection Number of Addresses",
+ "sdp.connection_info.num_addr",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Connection Number of Addresses", HFILL }},
+ { &hf_bandwidth_modifier,
+ { "Bandwidth Modifier",
+ "sdp.bandwidth.modifier",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Bandwidth Modifier", HFILL }},
+ { &hf_bandwidth_value,
+ { "Bandwidth Value",
+ "sdp.bandwidth.value",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Bandwidth Value (in kbits/s)", HFILL }},
+ { &hf_time_start,
+ { "Session Start Time",
+ "sdp.time.start",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Session Start Time", HFILL }},
+ { &hf_time_stop,
+ { "Session Stop Time",
+ "sdp.time.stop",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Session Stop Time", HFILL }},
+ { &hf_repeat_time_interval,
+ { "Repeat Interval",
+ "sdp.repeat_time.interval",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Repeat Interval", HFILL }},
+ { &hf_repeat_time_duration,
+ { "Repeat Duration",
+ "sdp.repeat_time.duration",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Repeat Duration", HFILL }},
+ { &hf_repeat_time_offset,
+ { "Repeat Offset",
+ "sdp.repeat_time.offset",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Repeat Offset", HFILL }},
+ { &hf_timezone_time,
+ { "Timezone Time",
+ "sdp.timezone.time",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Timezone Time", HFILL }},
+ { &hf_timezone_offset,
+ { "Timezone Offset",
+ "sdp.timezone.offset",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Timezone Offset", HFILL }},
+ { &hf_encryption_key_type,
+ { "Key Type",
+ "sdp.encryption_key.type",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Type", HFILL }},
+ { &hf_encryption_key_data,
+ { "Key Data",
+ "sdp.encryption_key.data",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Data", HFILL }},
+ { &hf_session_attribute_field,
+ { "Session Attribute Fieldname",
+ "sdp.session_attr.field",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Session Attribute Fieldname", HFILL }},
+ { &hf_session_attribute_value,
+ { "Session Attribute Value",
+ "sdp.session_attr.value",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Session Attribute Value", HFILL }},
+ { &hf_media_media,
+ { "Media Type",
+ "sdp.media.media",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Type", HFILL }},
+ { &hf_media_port,
+ { "Media Port",
+ "sdp.media.port",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Port", HFILL }},
+ { &hf_media_portcount,
+ { "Media Port Count",
+ "sdp.media.portcount",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Port Count", HFILL }},
+ { &hf_media_proto,
+ { "Media Proto",
+ "sdp.media.proto",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Protocol", HFILL }},
+ { &hf_media_format,
+ { "Media Format",
+ "sdp.media.format",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Format", HFILL }},
+ { &hf_media_attribute_field,
+ { "Media Attribute Fieldname",
+ "sdp.media_attribute.field",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Attribute Fieldname", HFILL }},
+ { &hf_media_attribute_value,
+ { "Media Attribute Value",
+ "sdp.media_attribute.value",FT_STRING, BASE_NONE, NULL, 0x0,
+ "Media Attribute Value", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_sdp,
+ &ett_sdp_owner,
+ &ett_sdp_connection_info,
+ &ett_sdp_bandwidth,
+ &ett_sdp_time,
+ &ett_sdp_repeat_time,
+ &ett_sdp_timezone,
+ &ett_sdp_encryption_key,
+ &ett_sdp_session_attribute,
+ &ett_sdp_media,
+ &ett_sdp_media_attribute,
+ };
+
+ proto_sdp = proto_register_protocol("Session Description Protocol",
+ "SDP", "sdp");
+ proto_register_field_array(proto_sdp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /*
+ * Register the dissector by name, so other dissectors can
+ * grab it by name rather than just referring to it directly
+ * (you can't refer to it directly from a plugin dissector
+ * on Windows without stuffing it into the Big Transfer Vector).
+ */
+ register_dissector("sdp", dissect_sdp, proto_sdp);
+}
+
+void
+proto_reg_handoff_sdp(void)
+{
+ dissector_handle_t sdp_handle;
+
+ rtp_handle = find_dissector("rtp");
+ rtcp_handle = find_dissector("rtcp");
+
+ sdp_handle = find_dissector("sdp");
+ dissector_add_string("media_type", "application/sdp", sdp_handle);
+}
diff --git a/epan/dissectors/packet-sebek.c b/epan/dissectors/packet-sebek.c
new file mode 100644
index 0000000000..7ba6882965
--- /dev/null
+++ b/epan/dissectors/packet-sebek.c
@@ -0,0 +1,210 @@
+/* packet-sebek.c
+ * Routines for Sebek - Kernel based data capture - packet dissection
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ *
+ * See: http://project.honeynet.org/tools/sebek/ for more details
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/resolv.h>
+
+/*
+ IP address: 32bit unsigned
+ MAGIC Val: 32bit unsigned
+ Sebek Ver: 16bit unsigned
+ Type 16bit unsigned
+ Counter: 32bit unsigned
+ Time_sec: 32bit unsigned
+ Time_usec: 32bit unsigned
+ Proc ID: 32bit unsigned
+ User ID: 32bit unsigned
+ File Desc: 32bit unsigned
+ Command: 12char array
+ Length: Data Length
+
+ Data: Variable Length data
+
+ *
+ */
+
+/* By default, but can be completely different */
+#define UDP_PORT_SEBEK 1101
+
+static int proto_sebek = -1;
+
+static int hf_sebek_magic = -1;
+static int hf_sebek_version = -1;
+static int hf_sebek_type = -1;
+static int hf_sebek_counter = -1;
+static int hf_sebek_time = -1;
+static int hf_sebek_pid = -1;
+static int hf_sebek_uid = -1;
+static int hf_sebek_fd = -1;
+static int hf_sebek_cmd = -1;
+static int hf_sebek_len = -1;
+static int hf_sebek_data = -1;
+
+static gint ett_sebek = -1;
+
+/* dissect_sebek - dissects sebek packet data
+ * tvb - tvbuff for packet data (IN)
+ * pinfo - packet info
+ * proto_tree - resolved protocol tree
+ */
+static void
+dissect_sebek(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *sebek_tree;
+ proto_item *ti;
+ int offset = 0;
+ int datalen = 0;
+ nstime_t ts;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SEBEK");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_set_str(pinfo->cinfo, COL_INFO, "SEBEK - ");
+ col_append_fstr(pinfo->cinfo, COL_INFO, " pid(%d)", tvb_get_ntohl(tvb, 20));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " uid(%d)", tvb_get_ntohl(tvb, 24));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " fd(%d)", tvb_get_ntohl(tvb, 28));
+ col_append_fstr(pinfo->cinfo, COL_INFO, " cmd: %s", tvb_get_string(tvb, 32, 12));
+ }
+
+
+ if (tree) {
+ /* Adding NTP item and subtree */
+ ti = proto_tree_add_item(tree, proto_sebek, tvb, 0, -1, FALSE);
+ sebek_tree = proto_item_add_subtree(ti, ett_sebek);
+
+ proto_tree_add_item(sebek_tree, hf_sebek_magic, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(sebek_tree, hf_sebek_version, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(sebek_tree, hf_sebek_type, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(sebek_tree, hf_sebek_counter, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ ts.secs = tvb_get_ntohl(tvb, offset);
+ ts.nsecs = tvb_get_ntohl(tvb, offset+4);
+ proto_tree_add_time(sebek_tree, hf_sebek_time, tvb, offset, 8, &ts);
+ offset += 8;
+
+ proto_tree_add_item(sebek_tree, hf_sebek_pid, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(sebek_tree, hf_sebek_uid, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(sebek_tree, hf_sebek_fd, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(sebek_tree, hf_sebek_cmd, tvb, offset, 12, FALSE);
+ offset += 12;
+
+ datalen = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(sebek_tree, hf_sebek_len, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(sebek_tree, hf_sebek_data, tvb, offset, -1, FALSE);
+
+ }
+}
+
+void
+proto_register_sebek(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_sebek_magic, {
+ "Magic", "sebek.magic", FT_UINT32, BASE_HEX,
+ NULL, 0, "Magic Number", HFILL }},
+ { &hf_sebek_version, {
+ "Version", "sebek.version", FT_UINT16, BASE_DEC,
+ NULL, 0, "Version Number", HFILL }},
+ { &hf_sebek_type, {
+ "Type", "sebek.type", FT_UINT16, BASE_DEC,
+ NULL, 0, "Type", HFILL }},
+ { &hf_sebek_counter, {
+ "Counter", "sebek.counter", FT_UINT32, BASE_DEC,
+ NULL, 0, "Counter", HFILL }},
+ { &hf_sebek_time, {
+ "Time", "sebek.time.sec", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time", HFILL }},
+ { &hf_sebek_pid, {
+ "Process ID", "sebek.pid", FT_UINT32, BASE_DEC,
+ NULL, 0, "Process ID", HFILL }},
+ { &hf_sebek_uid, {
+ "User ID", "sebek.uid", FT_UINT32, BASE_DEC,
+ NULL, 0, "User ID", HFILL }},
+ { &hf_sebek_fd, {
+ "File Descriptor", "sebek.fd", FT_UINT32, BASE_DEC,
+ NULL, 0, "File Descriptor Number", HFILL }},
+ { &hf_sebek_cmd, {
+ "Command Name", "sebek.cmd", FT_STRING, 0,
+ NULL, 0, "Command Name", HFILL }},
+ { &hf_sebek_len, {
+ "Data Length", "sebek.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Data Length", HFILL }},
+ { &hf_sebek_data, {
+ "Data", "sebek.data", FT_STRING, 0,
+ NULL, 0, "Data", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_sebek,
+ };
+
+ proto_sebek = proto_register_protocol("SEBEK - Kernel Data Capture", "SEBEK",
+ "sebek");
+ proto_register_field_array(proto_sebek, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_sebek(void)
+{
+ dissector_handle_t sebek_handle;
+
+ sebek_handle = create_dissector_handle(dissect_sebek, proto_sebek);
+ dissector_add("udp.port", UDP_PORT_SEBEK, sebek_handle);
+}
diff --git a/epan/dissectors/packet-ses.c b/epan/dissectors/packet-ses.c
new file mode 100644
index 0000000000..b1f00d845c
--- /dev/null
+++ b/epan/dissectors/packet-ses.c
@@ -0,0 +1,1786 @@
+/* packet-ses.c
+*
+* Routine to dissect ISO 8327-1 OSI Session Protocol packets
+*
+* $Id$
+*
+* Yuriy Sidelnikov <YSidelnikov@hotmail.com>
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-ses.h"
+#include "packet-frame.h"
+#include "prefs.h"
+
+#include <epan/strutil.h>
+
+/* ses header fields */
+static int proto_ses = -1;
+static int hf_ses_type = -1;
+static int hf_ses_type_0 = -1;
+static int hf_ses_length = -1;
+static int hf_ses_version = -1;
+static int hf_ses_reserved = -1;
+
+/* ses fields defining a sub tree */
+static gint ett_ses = -1;
+static gint ett_ses_param = -1;
+
+/*
+----------------------------------------------------------------------------------------------------------*/
+static dissector_handle_t pres_handle = NULL;
+/*
+----------------------------------------------------------------------------------------------------------*/
+
+
+/* flags */
+static int hf_connect_protocol_options_flags = -1;
+static int hf_version_number_options_flags = -1;
+static int hf_enclosure_item_options_flags = -1;
+static int hf_token_item_options_flags = -1;
+
+static gint ett_connect_protocol_options_flags = -1;
+static gint ett_protocol_version_flags = -1;
+static gint ett_enclosure_item_flags = -1;
+static gint ett_token_item_flags = -1;
+static gint ett_ses_req_options_flags = -1;
+
+/* called SS user reference */
+static int hf_called_ss_user_reference = -1;
+
+/* calling SS user reference */
+static int hf_calling_ss_user_reference = -1;
+
+/* common reference */
+static int hf_common_reference = -1;
+
+/* additional reference information */
+static int hf_additional_reference_information = -1;
+
+/* token item */
+static int hf_release_token = -1;
+static int hf_major_activity_token = -1;
+static int hf_synchronize_minor_token = -1;
+static int hf_data_token = -1;
+
+/* protocol options */
+static int hf_able_to_receive_extended_concatenated_SPDU = -1;
+
+/* session requirement */
+static int hf_session_user_req_flags = -1;
+static int hf_session_exception_report= -1;
+static int hf_data_separation_function_unit= -1;
+static int hf_symmetric_synchronize_function_unit= -1;
+static int hf_typed_data_function_unit= -1;
+static int hf_exception_function_unit= -1;
+static int hf_capability_function_unit=-1;
+static int hf_negotiated_release_function_unit= -1;
+static int hf_activity_management_function_unit= -1;
+static int hf_resynchronize_function_unit= -1;
+static int hf_major_resynchronize_function_unit= -1;
+static int hf_minor_resynchronize_function_unit= -1;
+static int hf_expedited_data_resynchronize_function_unit= -1;
+static int hf_duplex_function_unit= -1;
+static int hf_half_duplex_function_unit = -1;
+
+/* TSDU maximum size */
+static int hf_proposed_tsdu_maximum_size_i2r = -1;
+static int hf_proposed_tsdu_maximum_size_r2i = -1;
+
+/* protocol version */
+static int hf_protocol_version_1 = -1;
+static int hf_protocol_version_2 = -1;
+
+/* initial serial number */
+static int hf_initial_serial_number = -1;
+
+/* enclosure item */
+static int hf_beginning_of_SSDU = -1;
+static int hf_end_of_SSDU = -1;
+
+/* token setting item */
+
+static const value_string token_setting_vals[] = {
+ { 0x00, "initiator's side" },
+ { 0x01, "responder's side" },
+ { 0x02, "called SS user's choice" },
+ { 0x03, "reserved" },
+ { 0, NULL }
+};
+
+static int hf_release_token_setting = -1;
+static int hf_major_activity_token_setting = -1;
+static int hf_synchronize_minor_token_setting = -1;
+static int hf_data_token_setting = -1;
+
+/* calling session selector */
+static int hf_calling_session_selector = -1;
+
+/* called session selector */
+static int hf_called_session_selector = -1;
+
+/* serial number */
+static int hf_serial_number = -1;
+
+/* second serial number */
+static int hf_second_serial_number = -1;
+
+/* second initial serial number */
+static int hf_second_initial_serial_number = -1;
+
+/* large initial serial number */
+static int hf_large_initial_serial_number = -1;
+
+/* large second initial serial number */
+static int hf_large_second_initial_serial_number = -1;
+
+const value_string ses_vals[] =
+{
+ {SES_CONNECTION_REQUEST, "Connection request PDU" },
+ {SES_CONNECTION_ACCEPT, "Connection accept PDU" },
+ {SES_EXCEPTION_REPORT, "Exception report PDU" },
+ {SES_DATA_TRANSFER, "Data transfer PDU" },
+ {SES_PLEASE_TOKENS, "Please tokens PDU" },
+ {SES_EXPEDITED, "Expedited PDU" },
+ {SES_PREPARE, "Prepare PDU" },
+ {SES_NOT_FINISHED, "Not finished PDU" },
+ {SES_FINISH, "Finish PDU" },
+ {SES_DISCONNECT, "Disconnect PDU" },
+ {SES_REFUSE, "Refuse PDU" },
+ {SES_CONNECTION_DATA_OVERFLOW, "Data overflow PDU" },
+ {SES_OVERFLOW_ACCEPT, "Overflow accept PDU" },
+ {SES_GIVE_TOKENS_CONFIRM, "Tokens confirm PDU" },
+ {SES_GIVE_TOKENS_ACK, "Give tokens ACK PDU" },
+ {SES_ABORT, "Abort PDU" },
+ {SES_ABORT_ACCEPT, "Abort accept PDU" },
+ {SES_ACTIVITY_RESUME, "Activity resume PDU" },
+ {SES_TYPED_DATA, "Typed data PDU" },
+ {SES_RESYNCHRONIZE_ACK, "Resynchronize ACK PDU" },
+ {SES_MAJOR_SYNC_POINT, "Session major sync point PDU" },
+ {SES_MAJOR_SYNC_ACK, "Session major sync ACK PDU" },
+ {SES_ACTIVITY_START, "Activity start PDU" },
+ {SES_EXCEPTION_DATA, "Exception data PDU" },
+ {SES_MINOR_SYNC_POINT, "Minor sync point PDU" },
+ {SES_MINOR_SYNC_ACK, "Minor sync ACK PDU" },
+ {SES_RESYNCHRONIZE, "Resynchronize PDU" },
+ {SES_ACTIVITY_DISCARD, "Activity discard PDU" },
+ {SES_ACTIVITY_DISCARD_ACK, "Activity discard ACK PDU" },
+ {SES_CAPABILITY, "Capability PDU" },
+ {SES_CAPABILITY_DATA_ACK, "Capability data ACK PDU" },
+ {0, NULL }
+};
+
+static const value_string ses_category0_vals[] =
+{
+ {SES_PLEASE_TOKENS, "Please tokens PDU" },
+ {SES_GIVE_TOKENS, "Give tokens PDU" },
+ {0, NULL }
+};
+
+
+static const value_string param_vals[] =
+{
+ {Connection_Identifier, "Connection Identifier"},
+ {Connect_Accept_Item, "Connect Accept Item"},
+ {Called_SS_user_Reference, "Called SS user Reference"},
+ {Calling_SS_user_Reference, "Calling SS user Reference"},
+ {Common_Reference, "Common Reference"},
+ {Sync_Type_Item, "Sync Type Item"},
+ {Token_Item, "Token Item"},
+ {Transport_Disconnect, "Transport_Disconnect"},
+ {Additional_Reference_Information, "Additional Reference Information"},
+ {Protocol_Options, "Protocol Options"},
+ {TSDU_Maximum_Size, "TSDU Maximum Size"},
+ {Version_Number, "Version Number"},
+ {Initial_Serial_Number, "Initial Serial Number"},
+ {Prepare_Type, "Prepare Type"},
+ {EnclosureItem, "Enclosure Item"},
+ {Token_Setting_Item, "Token Setting Item"},
+ {Resync_Type, "Resync Type"},
+ {Serial_Number, "Serial Number"},
+ {Linking_Information, "Linking Information"},
+ {Reflect_Parameter, "Reflect Parameter"},
+ {Reason_Code, "Reason Code"},
+ {Calling_Session_Selector, "Calling Session Selector"},
+ {Called_Session_Selector, "Called Session Selector"},
+ {Second_Resync_Type, "Second Resync Type"},
+ {Second_Serial_Number, "Second Serial Number"},
+ {Second_Initial_Serial_Number, "Second Initial Serial Number"},
+ {Upper_Limit_Serial_Number, "Upper Limit Serial Number"},
+ {Large_Initial_Serial_Number, "Large Initial Serial Number"},
+ {Large_Second_Initial_Serial_Number, "Large Second Initial Serial Number"},
+ {Data_Overflow, "Data Overflow"},
+ {Session_Requirement, "Session Requirement"},
+ {User_Data, "Session user data"},
+ {Extended_User_Data, "Session extended user data"},
+ {0, NULL}
+};
+
+static const value_string reason_vals[] =
+{
+ {reason_not_specified, "Rejection by called SS-user; reason not specified" },
+ {temporary_congestion, "Rejection by called SS-user due to temporary congestion" },
+ {Subsequent, "Rejection by called SS-user." },
+ {Session_Selector_unknown, "Session Selector unknown" },
+ {SS_user_not_attached_to_SSAP, "SS-user not attached to SSAP" },
+ {SPM_congestion_at_connect_time, "SPM congestion at connect time" },
+ {versions_not_supported, "Proposed protocol versions not supported" },
+ {SPM_reason_not_specified, "Rejection by the SPM; reason not specified" },
+ {SPM_implementation_restriction, "Finish PDU" },
+ {SES_DISCONNECT, "Rejection by the SPM; implementation restriction stated in the PICS" },
+ {0, NULL }
+};
+
+/* desegmentation of OSI over ses */
+/*static gboolean ses_desegment = TRUE;*/
+
+
+/* find the dissector for data */
+static dissector_handle_t data_handle;
+
+static void
+call_pres_dissector(tvbuff_t *tvb, int offset, guint16 param_len,
+ packet_info *pinfo, proto_tree *tree, proto_tree *param_tree,
+ struct SESSION_DATA_STRUCTURE *session)
+{
+ void *saved_private_data;
+
+ /* do we have OSI presentation packet dissector ? */
+ if(!pres_handle)
+ {
+ /* No - display as data */
+ if (tree)
+ {
+ proto_tree_add_text(param_tree, tvb, offset, param_len,
+ "User data");
+ }
+ }
+ else
+ {
+ /* Yes - call presentation dissector */
+ tvbuff_t *next_tvb;
+
+ next_tvb = tvb_new_subset(tvb, offset, param_len, param_len);
+ TRY
+ {
+ /* save type of session pdu. We'll need it in the presentation dissector */
+ saved_private_data = pinfo->private_data;
+ pinfo->private_data = session;
+ call_dissector(pres_handle, next_tvb, pinfo, tree);
+ pinfo->private_data = saved_private_data;
+ }
+ CATCH_ALL
+ {
+ show_exception(tvb, pinfo, tree, EXCEPT_CODE);
+ }
+ ENDTRY;
+ }
+}
+
+/* this routine returns length of parameter field, parameter group,
+ or parameter */
+static int
+get_item_len(tvbuff_t *tvb, int offset, int *len_len)
+{
+ guint16 len;
+
+ len = tvb_get_guint8(tvb, offset);
+ if(len == TWO_BYTE_LEN)
+ {
+ len = tvb_get_ntohs(tvb, offset+1);
+ *len_len = 3;
+ }
+ else
+ *len_len = 1;
+ return len;
+}
+
+static gboolean
+dissect_parameter(tvbuff_t *tvb, int offset, proto_tree *tree,
+ proto_tree *param_tree, packet_info *pinfo, guint8 param_type,
+ guint16 param_len, struct SESSION_DATA_STRUCTURE *session)
+{
+ gboolean has_user_information = TRUE;
+ guint16 flags;
+ proto_item *tf;
+ proto_tree *flags_tree;
+
+ switch (param_type)
+ {
+ case Called_SS_user_Reference:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_called_ss_user_reference,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Calling_SS_user_Reference:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_calling_ss_user_reference,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Common_Reference:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_common_reference,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Additional_Reference_Information:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_additional_reference_information,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Token_Item:
+ if (param_len != 1)
+ {
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len, "Length is %u, should be 1",
+ param_len);
+ break;
+ }
+ if (tree)
+ {
+ flags = tvb_get_guint8(tvb, offset);
+ tf = proto_tree_add_uint(param_tree,
+ hf_token_item_options_flags, tvb, offset, 1,
+ flags);
+ flags_tree = proto_item_add_subtree(tf,
+ ett_token_item_flags);
+ proto_tree_add_boolean(flags_tree, hf_release_token,
+ tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_major_activity_token, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_synchronize_minor_token, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_data_token, tvb,
+ offset, 1, flags);
+ }
+ break;
+
+ case Transport_Disconnect:
+ if (param_len != 1)
+ {
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len, "Length is %u, should be 1",
+ param_len);
+ break;
+ }
+ if (tree)
+ {
+ guint8 flags;
+
+ flags = tvb_get_guint8(tvb, offset);
+ if(flags & transport_connection_is_released )
+ {
+ proto_tree_add_text(param_tree, tvb, offset, 1,
+ "transport connection is released");
+ }
+ else
+ {
+ proto_tree_add_text(param_tree, tvb, offset, 1,
+ "transport connection is kept");
+ }
+
+ if(flags & user_abort )
+ {
+ proto_tree_add_text(param_tree, tvb, offset, 1,
+ "user abort");
+ session->abort_type = SESSION_USER_ABORT;
+ }
+ else
+ {
+ session->abort_type = SESSION_PROVIDER_ABORT;
+ }
+
+ if(flags & protocol_error )
+ {
+ proto_tree_add_text(param_tree, tvb, offset, 1,
+ "protocol error");
+ }
+
+ if(flags & no_reason )
+ {
+ proto_tree_add_text(param_tree, tvb, offset, 1,
+ "no reason");
+ }
+
+ if(flags & implementation_restriction )
+ {
+ proto_tree_add_text(param_tree, tvb, offset, 1,
+ "implementation restriction");
+ }
+ }
+ break;
+
+ case Protocol_Options:
+ if (param_len != 1)
+ {
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len, "Length is %u, should be 1",
+ param_len);
+ break;
+ }
+ if (tree)
+ {
+ flags = tvb_get_guint8(tvb, offset);
+ tf = proto_tree_add_uint(param_tree,
+ hf_connect_protocol_options_flags, tvb, offset, 1,
+ flags);
+ flags_tree = proto_item_add_subtree(tf,
+ ett_connect_protocol_options_flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_able_to_receive_extended_concatenated_SPDU,
+ tvb, offset, 1, flags);
+ }
+ break;
+
+ case Session_Requirement:
+ if (param_len != 2)
+ {
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len, "Length is %u, should be 2",
+ param_len);
+ break;
+ }
+ if (tree)
+ {
+ flags = tvb_get_ntohs(tvb, offset);
+ tf = proto_tree_add_uint(param_tree,
+ hf_session_user_req_flags, tvb, offset, 2,
+ flags);
+ flags_tree = proto_item_add_subtree(tf,
+ ett_ses_req_options_flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_session_exception_report, tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_data_separation_function_unit, tvb, offset, 2,
+ flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_symmetric_synchronize_function_unit,
+ tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_typed_data_function_unit, tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_exception_function_unit, tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_capability_function_unit, tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_negotiated_release_function_unit,
+ tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_activity_management_function_unit,
+ tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_resynchronize_function_unit, tvb, offset, 2,
+ flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_major_resynchronize_function_unit,
+ tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_minor_resynchronize_function_unit,
+ tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_expedited_data_resynchronize_function_unit,
+ tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_duplex_function_unit, tvb, offset, 2, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_half_duplex_function_unit,
+ tvb, offset, 2, flags);
+ }
+ break;
+
+ case TSDU_Maximum_Size:
+ if (param_len != 4)
+ {
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len, "Length is %u, should be 4",
+ param_len);
+ break;
+ }
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_proposed_tsdu_maximum_size_i2r,
+ tvb, offset, 2, FALSE);
+ proto_tree_add_item(param_tree,
+ hf_proposed_tsdu_maximum_size_r2i,
+ tvb, offset+2, 2, FALSE);
+ }
+ break;
+
+ case Version_Number:
+ if (param_len != 1)
+ {
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len, "Length is %u, should be 1",
+ param_len);
+ break;
+ }
+ if (tree)
+ {
+ flags = tvb_get_guint8(tvb, offset);
+ tf = proto_tree_add_uint(param_tree,
+ hf_version_number_options_flags, tvb, offset, 1,
+ flags);
+ flags_tree = proto_item_add_subtree(tf,
+ ett_protocol_version_flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_protocol_version_2, tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree,
+ hf_protocol_version_1, tvb, offset, 1, flags);
+ }
+ break;
+
+ case Initial_Serial_Number:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_initial_serial_number,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case EnclosureItem:
+ if (param_len != 1)
+ {
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len, "Length is %u, should be 1",
+ param_len);
+ break;
+ }
+ flags = tvb_get_guint8(tvb, offset);
+ if (tree)
+ {
+ tf = proto_tree_add_uint(param_tree,
+ hf_enclosure_item_options_flags, tvb, offset, 1,
+ flags);
+ flags_tree = proto_item_add_subtree(tf,
+ ett_enclosure_item_flags);
+ proto_tree_add_boolean(flags_tree, hf_end_of_SSDU,
+ tvb, offset, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_beginning_of_SSDU,
+ tvb, offset, 1, flags);
+ }
+ if (flags & END_SPDU) {
+ /*
+ * In Data Transfer and Typed Data SPDUs,
+ * "The User Information Field shall be present
+ * if the Enclosure Item is not present, or has
+ * bit 2 = 0", which presumably means it shall
+ * *not* be present if the Enclosure item *is*
+ * present and has bit 2 = 1.
+ */
+ has_user_information = FALSE;
+ }
+ break;
+
+ case Token_Setting_Item:
+ if (param_len != 1)
+ {
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len, "Length is %u, should be 1",
+ param_len);
+ break;
+ }
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_release_token_setting,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_item(param_tree,
+ hf_major_activity_token_setting,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_item(param_tree,
+ hf_synchronize_minor_token_setting,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_item(param_tree,
+ hf_data_token_setting,
+ tvb, offset, 1, FALSE);
+ }
+ break;
+
+ case Serial_Number:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_serial_number,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Reason_Code:
+/*
+ 0: Rejection by called SS-user; reason not specified.
+ 1: Rejection by called SS-user due to temporary congestion.
+ 2: Rejection by called SS-user. Subsequent octets may be used for user data
+up to a length of 512 octets if Protocol Version 1 has been selected, and up
+to a length such that the total length (including SI and LI) of the SPDU
+does not exceed 65 539 octets if Protocol Version 2 has been selected.
+ 128 + 1: Session Selector unknown.
+ 128 + 2: SS-user not attached to SSAP.
+ 128 + 3: SPM congestion at connect time.
+ 128 + 4: Proposed protocol versions not supported.
+ 128 + 5: Rejection by the SPM; reason not specified.
+ 128 + 6: Rejection by the SPM; implementation restriction stated in the
+PICS. */
+ if (param_len < 1)
+ {
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len, "Length is %u, should be >= 1",
+ param_len);
+ break;
+ }
+ if (tree)
+ {
+ guint8 reason_code;
+
+ reason_code = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(param_tree, tvb, offset, 1,
+ "Reason Code: %s",
+ val_to_str(reason_code, reason_vals, "Unknown (%u)"));
+ }
+ offset++;
+ param_len--;
+ if (param_len != 0)
+ {
+ call_pres_dissector(tvb, offset, param_len,
+ pinfo, tree, param_tree, session);
+ }
+ break;
+
+ case Calling_Session_Selector:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_calling_session_selector,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Called_Session_Selector:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_called_session_selector,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Second_Serial_Number:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_second_serial_number,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Second_Initial_Serial_Number:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_second_initial_serial_number,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Large_Initial_Serial_Number:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_large_initial_serial_number,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ case Large_Second_Initial_Serial_Number:
+ if (param_len == 0)
+ break;
+ if (tree)
+ {
+ proto_tree_add_item(param_tree,
+ hf_large_second_initial_serial_number,
+ tvb, offset, param_len, FALSE);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return has_user_information;
+}
+
+static gboolean
+dissect_parameter_group(tvbuff_t *tvb, int offset, proto_tree *tree,
+ proto_tree *pg_tree, packet_info *pinfo, guint16 pg_len,
+ struct SESSION_DATA_STRUCTURE *session)
+{
+ gboolean has_user_information = TRUE;
+ proto_item *ti;
+ proto_tree *param_tree;
+ guint8 param_type;
+ char *param_str;
+ int len_len;
+ guint16 param_len;
+
+ while(pg_len != 0)
+ {
+ param_type = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(pg_tree, tvb, offset, -1,
+ val_to_str(param_type, param_vals,
+ "Unknown parameter type (0x%02x)"));
+ param_tree = proto_item_add_subtree(ti, ett_ses_param);
+ param_str = match_strval(param_type, param_vals);
+ proto_tree_add_text(param_tree, tvb, offset, 1,
+ "Parameter type: %s",
+ param_str != NULL ? param_str : "Unknown");
+ offset++;
+ pg_len--;
+ param_len = get_item_len(tvb, offset, &len_len);
+ if (len_len > pg_len) {
+ proto_item_set_len(ti, pg_len + 1);
+ proto_tree_add_text(param_tree, tvb, offset, pg_len,
+ "Parameter length doesn't fit in parameter");
+ return has_user_information;
+ }
+ pg_len -= len_len;
+ if (param_len > pg_len) {
+ proto_item_set_len(ti, pg_len + 1 + len_len);
+ proto_tree_add_text(param_tree, tvb, offset, pg_len,
+ "Parameter length: %u, should be <= %u",
+ param_len, pg_len);
+ return has_user_information;
+ }
+ proto_item_set_len(ti, 1 + len_len + param_len);
+ proto_tree_add_text(param_tree, tvb, offset, len_len,
+ "Parameter length: %u", param_len);
+ offset += len_len;
+
+ if (param_str != NULL)
+ {
+ switch(param_type)
+ {
+ /* PG's in PG's are invalid, presumably */
+ case Extended_User_Data:
+ case User_Data:
+ case Connect_Accept_Item:
+ case Connection_Identifier:
+ case Linking_Information:
+ proto_tree_add_text(param_tree, tvb, offset,
+ param_len,
+ "Parameter group inside parameter group");
+ break;
+
+ default:
+ if (!dissect_parameter(tvb, offset, tree,
+ param_tree, pinfo, param_type, param_len,
+ session))
+ has_user_information = FALSE;
+ break;
+ }
+ }
+ offset += param_len;
+ pg_len -= param_len;
+ }
+ return has_user_information;
+}
+
+/*
+ * Returns TRUE if there's a User Information field in this SPDU, FALSE
+ * otherwise.
+ */
+static gboolean
+dissect_parameters(tvbuff_t *tvb, int offset, guint16 len, proto_tree *tree,
+ proto_tree *ses_tree, packet_info *pinfo,
+ struct SESSION_DATA_STRUCTURE *session)
+{
+ gboolean has_user_information = TRUE;
+ proto_item *ti;
+ proto_tree *param_tree;
+ guint8 param_type;
+ char *param_str;
+ int len_len;
+ guint16 param_len;
+
+ while(len != 0)
+ {
+ param_type = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(ses_tree, tvb, offset, -1,
+ val_to_str(param_type, param_vals,
+ "Unknown parameter type (0x%02x)"));
+ param_tree = proto_item_add_subtree(ti, ett_ses_param);
+ param_str = match_strval(param_type, param_vals);
+ proto_tree_add_text(param_tree, tvb, offset, 1,
+ "Parameter type: %s",
+ param_str != NULL ? param_str : "Unknown");
+ offset++;
+ len--;
+ param_len = get_item_len(tvb, offset, &len_len);
+ if (len_len > len) {
+ proto_item_set_len(ti, len + 1 );
+ proto_tree_add_text(param_tree, tvb, offset, len,
+ "Parameter length doesn't fit in parameter");
+ return has_user_information;
+ }
+ len -= len_len;
+ if (param_len > len) {
+ proto_item_set_len(ti, len + 1 + len_len);
+ proto_tree_add_text(param_tree, tvb, offset, len,
+ "Parameter length: %u, should be <= %u",
+ param_len, len);
+ return has_user_information;
+ }
+ proto_item_set_len(ti, 1 + len_len + param_len);
+ proto_tree_add_text(param_tree, tvb, offset, len_len,
+ "Parameter length: %u", param_len);
+ offset += len_len;
+
+ if (param_str != NULL)
+ {
+ switch(param_type)
+ {
+ case Extended_User_Data:
+ break;
+
+ case User_Data:
+ call_pres_dissector(tvb, offset, param_len,
+ pinfo, tree, param_tree, session);
+ break;
+
+ /* handle PGI's */
+ case Connect_Accept_Item:
+ case Connection_Identifier:
+ case Linking_Information:
+ /* Yes. */
+ if (!dissect_parameter_group(tvb, offset, tree,
+ param_tree, pinfo, param_len, session))
+ has_user_information = FALSE;
+ break;
+
+ /* everything else is a PI */
+ default:
+ if (!dissect_parameter(tvb, offset, tree,
+ param_tree, pinfo, param_type, param_len,
+ session))
+ has_user_information = FALSE;
+ break;
+ }
+ }
+ offset += param_len;
+ len -= param_len;
+ }
+ return has_user_information;
+}
+
+/*
+ * Dissect an SPDU.
+ */
+static int
+dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
+ gboolean tokens)
+{
+ gboolean has_user_information = FALSE;
+ guint8 type;
+ proto_item *ti = NULL;
+ proto_tree *ses_tree = NULL;
+ int len_len;
+ guint16 parameters_len;
+ tvbuff_t *next_tvb;
+ void *save_private_data;
+ struct SESSION_DATA_STRUCTURE session;
+
+ /*
+ * Get SPDU type.
+ */
+ type = tvb_get_guint8(tvb, offset);
+ session.spdu_type = type;
+ session.abort_type = SESSION_NO_ABORT;
+
+ if (tokens) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(type, ses_category0_vals, "Unknown SPDU type (0x%02x)"));
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
+ -1, FALSE);
+ ses_tree = proto_item_add_subtree(ti, ett_ses);
+ proto_tree_add_uint(ses_tree, hf_ses_type_0, tvb,
+ offset, 1, type);
+ }
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
+ -1, FALSE);
+ ses_tree = proto_item_add_subtree(ti, ett_ses);
+ proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
+ offset, 1, type);
+ }
+
+ /*
+ * Might this SPDU have a User Information field?
+ */
+ switch (type) {
+
+ case SES_DATA_TRANSFER:
+ case SES_EXPEDITED:
+ case SES_TYPED_DATA:
+ has_user_information = TRUE;
+ break;
+ }
+ }
+ offset++;
+
+ /* get length of SPDU parameter field */
+ parameters_len = get_item_len(tvb, offset, &len_len);
+ if (tree)
+ proto_tree_add_uint(ses_tree, hf_ses_length, tvb, offset,
+ len_len, parameters_len);
+ offset += len_len;
+
+ /* Dissect parameters. */
+ if (!dissect_parameters(tvb, offset, parameters_len, tree, ses_tree,
+ pinfo, &session))
+ has_user_information = FALSE;
+ offset += parameters_len;
+
+ proto_item_set_end(ti, tvb, offset);
+
+ /* Dissect user information, if present */
+ if (has_user_information) {
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ /* do we have OSI presentation packet dissector ? */
+ if(!pres_handle)
+ {
+ call_dissector(data_handle, next_tvb, pinfo,
+ tree);
+ }
+ else
+ {
+ /* save type of session pdu. We'll need it in the presentation dissector */
+ save_private_data = pinfo->private_data;
+ pinfo->private_data = &session;
+ call_dissector(pres_handle, next_tvb, pinfo,
+ tree);
+ pinfo->private_data = save_private_data;
+ }
+
+ /*
+ * No more SPDUs to dissect. Set the offset to the
+ * end of the tvbuff.
+ */
+ offset = tvb_length(tvb);
+ }
+ }
+ return offset;
+}
+
+/*
+ * Dissect SPDUs inside a TSDU.
+ */
+static void
+dissect_ses(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint8 type;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SES");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /*
+ * Do we have a category 0 SPDU (GIVE_TOKENS/PLEASE_TOKENS) as
+ * the first SPDU?
+ *
+ * If so, dissect it as such (GIVE_TOKENS and DATA_TRANSFER have
+ * the same SPDU type value).
+ */
+ type = tvb_get_guint8(tvb, offset);
+ if (type == SES_PLEASE_TOKENS || type == SES_GIVE_TOKENS)
+ offset = dissect_spdu(tvb, offset, pinfo, tree, TOKENS_SPDU);
+
+ /* Dissect the remaining SPDUs. */
+ while (tvb_reported_length_remaining(tvb, offset) > 0)
+ offset = dissect_spdu(tvb, offset, pinfo, tree, NON_TOKENS_SPDU);
+}
+
+void
+proto_register_ses(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_ses_type,
+ {
+ "SPDU Type",
+ "ses.type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(ses_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_ses_type_0,
+ {
+ "SPDU Type",
+ "ses.type",
+ FT_UINT8,
+ BASE_DEC,
+ VALS(ses_category0_vals),
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_ses_length,
+ {
+ "Length",
+ "ses.length",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+
+ {
+ &hf_ses_version,
+ {
+ "Version",
+ "ses.version",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_ses_reserved,
+ {
+ "Reserved",
+ "ses.reserved",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_called_ss_user_reference,
+ {
+ "Called SS User Reference",
+ "ses.called_ss_user_reference",
+ FT_BYTES, BASE_NONE,
+ NULL,
+ 0x0,
+ "Called SS User Reference",
+ HFILL
+ }
+ },
+ {
+ &hf_calling_ss_user_reference,
+ {
+ "Calling SS User Reference",
+ "ses.calling_ss_user_reference",
+ FT_BYTES, BASE_NONE,
+ NULL,
+ 0x0,
+ "Calling SS User Reference",
+ HFILL
+ }
+ },
+ {
+ &hf_common_reference,
+ {
+ "Common Reference",
+ "ses.common_reference",
+ FT_BYTES, BASE_NONE,
+ NULL,
+ 0x0,
+ "Common Reference",
+ HFILL
+ }
+ },
+ {
+ &hf_additional_reference_information,
+ {
+ "Additional Reference Information",
+ "ses.additional_reference_information",
+ FT_BYTES, BASE_NONE,
+ NULL,
+ 0x0,
+ "Additional Reference Information",
+ HFILL
+ }
+ },
+ {
+ &hf_release_token,
+ {
+ "release token",
+ "ses.release_token",
+ FT_BOOLEAN, 8,
+ NULL,
+ RELEASE_TOKEN,
+ "release token",
+ HFILL
+ }
+ },
+ {
+ &hf_major_activity_token,
+ {
+ "major/activity token",
+ "ses.major.token",
+ FT_BOOLEAN, 8,
+ NULL,
+ MAJOR_ACTIVITY_TOKEN,
+ "major/activity token",
+ HFILL
+ }
+ },
+ {
+ &hf_synchronize_minor_token,
+ {
+ "synchronize minor token",
+ "ses.synchronize_token",
+ FT_BOOLEAN, 8,
+ NULL,
+ SYNCHRONIZE_MINOR_TOKEN,
+ "synchronize minor token",
+ HFILL
+ }
+ },
+ {
+ &hf_data_token,
+ {
+ "data token",
+ "ses.data_token",
+ FT_BOOLEAN, 8,
+ NULL,
+ DATA_TOKEN,
+ "data token",
+ HFILL
+ }
+ },
+ {
+ &hf_able_to_receive_extended_concatenated_SPDU,
+ {
+ "Able to receive extended concatenated SPDU",
+ "ses.connect.f1",
+ FT_BOOLEAN, 8,
+ NULL,
+ SES_EXT_CONT,
+ "Able to receive extended concatenated SPDU",
+ HFILL
+ }
+ },
+ {
+ &hf_session_user_req_flags,
+ {
+ "Flags",
+ "ses.req.flags",
+ FT_UINT16,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ "",
+ HFILL
+ }
+ },
+ {
+ &hf_session_exception_report,
+ {
+ "Session exception report",
+ "ses.exception_report.",
+ FT_BOOLEAN, 16,
+ NULL,
+ SES_EXCEPTION_REPORT,
+ "Session exception report",
+ HFILL
+ }
+ },
+ {
+ &hf_data_separation_function_unit,
+ {
+ "Data separation function unit",
+ "ses.data_sep",
+ FT_BOOLEAN, 16,
+ NULL,
+ DATA_SEPARATION_FUNCTION_UNIT,
+ "Data separation function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_symmetric_synchronize_function_unit,
+ {
+ "Symmetric synchronize function unit",
+ "ses.symm_sync",
+ FT_BOOLEAN, 16,
+ NULL,
+ SYMMETRIC_SYNCHRONIZE_FUNCTION_UNIT,
+ "Symmetric synchronize function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_typed_data_function_unit,
+ {
+ "Typed data function unit",
+ "ses.typed_data",
+ FT_BOOLEAN, 16,
+ NULL,
+ TYPED_DATA_FUNCTION_UNIT,
+ "Typed data function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_exception_function_unit,
+ {
+ "Exception function unit",
+ "ses.exception_data",
+ FT_BOOLEAN, 16,
+ NULL,
+ EXCEPTION_FUNCTION_UNIT,
+ "Exception function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_capability_function_unit,
+ {
+ "Capability function unit",
+ "ses.capability_data",
+ FT_BOOLEAN, 16,
+ NULL,
+ CAPABILITY_DATA_FUNCTION_UNIT,
+ "Capability function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_negotiated_release_function_unit,
+ {
+ "Negotiated release function unit",
+ "ses.negotiated_release",
+ FT_BOOLEAN, 16,
+ NULL,
+ NEGOTIATED_RELEASE_FUNCTION_UNIT,
+ "Negotiated release function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_activity_management_function_unit,
+ {
+ "Activity management function unit",
+ "ses.activity_management",
+ FT_BOOLEAN, 16,
+ NULL,
+ ACTIVITY_MANAGEMENT_FUNCTION_UNIT,
+ "Activity management function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_resynchronize_function_unit,
+ {
+ "Resynchronize function unit",
+ "ses.resynchronize",
+ FT_BOOLEAN, 16,
+ NULL,
+ RESYNCHRONIZE_FUNCTION_UNIT,
+ "Resynchronize function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_major_resynchronize_function_unit,
+ {
+ "Major resynchronize function unit",
+ "ses.major_resynchronize",
+ FT_BOOLEAN, 16,
+ NULL,
+ MAJOR_SYNCHRONIZE_FUNCTION_UNIT,
+ "Major resynchronize function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_minor_resynchronize_function_unit,
+ {
+ "Minor resynchronize function unit",
+ "ses.minor_resynchronize",
+ FT_BOOLEAN, 16,
+ NULL,
+ MINOR_SYNCHRONIZE_FUNCTION_UNIT,
+ "Minor resynchronize function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_expedited_data_resynchronize_function_unit,
+ {
+ "Expedited data function unit",
+ "ses.expedited_data",
+ FT_BOOLEAN, 16,
+ NULL,
+ EXPEDITED_DATA_FUNCTION_UNIT,
+ "Expedited data function unit",
+ HFILL
+ }
+ },
+ {
+ &hf_duplex_function_unit,
+ {
+ "Duplex functional unit",
+ "ses.duplex",
+ FT_BOOLEAN, 16,
+ NULL,
+ DUPLEX_FUNCTION_UNIT,
+ "Duplex functional unit",
+ HFILL
+ }
+ },
+ {
+ &hf_half_duplex_function_unit,
+ {
+ "Half-duplex functional unit",
+ "ses.half_duplex",
+ FT_BOOLEAN, 16,
+ NULL,
+ HALF_DUPLEX_FUNCTION_UNIT,
+ "Half-duplex functional unit",
+ HFILL
+ }
+ },
+ {
+ &hf_proposed_tsdu_maximum_size_i2r,
+ {
+ "Proposed TSDU Maximum Size, Initiator to Responder",
+ "ses.proposed_tsdu_maximum_size_i2r",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Proposed TSDU Maximum Size, Initiator to Responder",
+ HFILL
+ }
+ },
+ {
+ &hf_proposed_tsdu_maximum_size_r2i,
+ {
+ "Proposed TSDU Maximum Size, Responder to Initiator",
+ "ses.proposed_tsdu_maximum_size_r2i",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "Proposed TSDU Maximum Size, Responder to Initiator",
+ HFILL
+ }
+ },
+ {
+ &hf_protocol_version_1,
+ {
+ "Protocol Version 1",
+ "ses.protocol_version1",
+ FT_BOOLEAN, 8,
+ NULL,
+ PROTOCOL_VERSION_1,
+ "Protocol Version 1",
+ HFILL
+ }
+ },
+ {
+ &hf_protocol_version_2,
+ {
+ "Protocol Version 2",
+ "ses.protocol_version2",
+ FT_BOOLEAN, 8,
+ NULL,
+ PROTOCOL_VERSION_2,
+ "Protocol Version 2",
+ HFILL
+ }
+ },
+ {
+ &hf_initial_serial_number,
+ {
+ "Initial Serial Number",
+ "ses.initial_serial_number",
+ FT_STRING, BASE_NONE,
+ NULL,
+ 0x0,
+ "Initial Serial Number",
+ HFILL
+ }
+ },
+ {
+ &hf_beginning_of_SSDU,
+ {
+ "beginning of SSDU",
+ "ses.begininng_of_SSDU",
+ FT_BOOLEAN, 8,
+ NULL,
+ BEGINNING_SPDU,
+ "beginning of SSDU",
+ HFILL
+ }
+ },
+ {
+ &hf_end_of_SSDU,
+ {
+ "end of SSDU",
+ "ses.end_of_SSDU",
+ FT_BOOLEAN, 8,
+ NULL,
+ END_SPDU,
+ "end of SSDU",
+ HFILL
+ }
+ },
+ {
+ &hf_release_token_setting,
+ {
+ "release token setting",
+ "ses.release_token_setting",
+ FT_UINT8, BASE_HEX,
+ VALS(token_setting_vals),
+ 0xC0,
+ "release token setting",
+ HFILL
+ }
+ },
+ {
+ &hf_major_activity_token_setting,
+ {
+ "major/activity setting",
+ "ses.major_activity_token_setting",
+ FT_UINT8, BASE_HEX,
+ VALS(token_setting_vals),
+ 0x30,
+ "major/activity token setting",
+ HFILL
+ }
+ },
+ {
+ &hf_synchronize_minor_token_setting,
+ {
+ "synchronize-minor token setting",
+ "ses.synchronize_minor_token_setting",
+ FT_UINT8, BASE_HEX,
+ VALS(token_setting_vals),
+ 0x0C,
+ "synchronize-minor token setting",
+ HFILL
+ }
+ },
+ {
+ &hf_data_token_setting,
+ {
+ "data token setting",
+ "ses.data_token_setting",
+ FT_UINT8, BASE_HEX,
+ VALS(token_setting_vals),
+ 0x03,
+ "data token setting",
+ HFILL
+ }
+ },
+ {
+ &hf_serial_number,
+ {
+ "Serial Number",
+ "ses.serial_number",
+ FT_STRING, BASE_NONE,
+ NULL,
+ 0x0,
+ "Serial Number",
+ HFILL
+ }
+ },
+ {
+ &hf_calling_session_selector,
+ {
+ "Calling Session Selector",
+ "ses.calling_session_selector",
+ FT_BYTES, BASE_NONE,
+ NULL,
+ 0x0,
+ "Calling Session Selector",
+ HFILL
+ }
+ },
+ {
+ &hf_called_session_selector,
+ {
+ "Called Session Selector",
+ "ses.called_session_selector",
+ FT_BYTES, BASE_NONE,
+ NULL,
+ 0x0,
+ "Called Session Selector",
+ HFILL
+ }
+ },
+ {
+ &hf_second_serial_number,
+ {
+ "Second Serial Number",
+ "ses.second_serial_number",
+ FT_STRING, BASE_NONE,
+ NULL,
+ 0x0,
+ "Second Serial Number",
+ HFILL
+ }
+ },
+ {
+ &hf_second_initial_serial_number,
+ {
+ "Second Initial Serial Number",
+ "ses.second_initial_serial_number",
+ FT_STRING, BASE_NONE,
+ NULL,
+ 0x0,
+ "Second Initial Serial Number",
+ HFILL
+ }
+ },
+ {
+ &hf_large_initial_serial_number,
+ {
+ "Large Initial Serial Number",
+ "ses.large_initial_serial_number",
+ FT_STRING, BASE_NONE,
+ NULL,
+ 0x0,
+ "Large Initial Serial Number",
+ HFILL
+ }
+ },
+ {
+ &hf_large_second_initial_serial_number,
+ {
+ "Large Second Initial Serial Number",
+ "ses.large_second_initial_serial_number",
+ FT_STRING, BASE_NONE,
+ NULL,
+ 0x0,
+ "Large Second Initial Serial Number",
+ HFILL
+ }
+ },
+ {
+ &hf_connect_protocol_options_flags,
+ {
+ "Flags",
+ "ses.connect.flags",
+ FT_UINT8,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ "",
+ HFILL
+ }
+ },
+ {
+ &hf_version_number_options_flags,
+
+ {
+ "Flags",
+ "ses.version.flags",
+ FT_UINT8,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ "",
+ HFILL
+ }
+ },
+
+ {
+ &hf_token_item_options_flags,
+
+ {
+ "Flags",
+ "ses.tken_item.flags",
+ FT_UINT8,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ "",
+ HFILL
+ }
+ },
+
+ {
+ &hf_enclosure_item_options_flags,
+
+ {
+ "Flags",
+ "ses.enclosure.flags",
+ FT_UINT8,
+ BASE_HEX,
+ NULL,
+ 0x0,
+ "",
+ HFILL
+ }
+ },
+ };
+
+ static gint *ett[] =
+ {
+ &ett_ses,
+ &ett_ses_param,
+ &ett_connect_protocol_options_flags,
+ &ett_protocol_version_flags,
+ &ett_enclosure_item_flags,
+ &ett_token_item_flags,
+ &ett_ses_req_options_flags,
+ };
+ module_t *ses_module;
+
+
+ proto_ses = proto_register_protocol(PROTO_STRING_SES, "SES", "ses");
+ proto_register_field_array(proto_ses, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ses_module = prefs_register_protocol(proto_ses, NULL);
+/*
+ prefs_register_bool_preference(ses_module, "desegment",
+ "Desegment all session packets ",
+ "Whether the session dissector should desegment all messages spanning multiple SES segments",
+ &ses_desegment); */
+
+ /*
+ * Register the dissector by name, so other dissectors can
+ * grab it by name rather than just referring to it directly
+ * (you can't refer to it directly from a plugin dissector
+ * on Windows without stuffing it into the Big Transfer Vector).
+ */
+ register_dissector("ses", dissect_ses, proto_ses);
+}
+
+static gboolean
+dissect_ses_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ /* must check that this really is a ses packet */
+ int offset = 0;
+ guint8 type;
+ int len_len;
+ guint16 len;
+
+ /* first, check do we have at least 4 bytes (type+length) */
+ if (!tvb_bytes_exist(tvb, 0, 4))
+ return FALSE; /* no */
+
+ /* can we recognize session PDU ? Return FALSE if not */
+ /* get SPDU type */
+ type = tvb_get_guint8(tvb, offset);
+ /* check SPDU type */
+ if (match_strval(type, ses_vals) == NULL)
+ {
+ return FALSE; /* no, it isn't a session PDU */
+ }
+
+ /* OK,let's check SPDU length */
+ /* get length of SPDU */
+ len = get_item_len(tvb, offset+1, &len_len);
+ /* add header length */
+ len+=len_len;
+ /* do we have enough bytes ? */
+ if (!tvb_bytes_exist(tvb, 0, len))
+ return FALSE; /* no */
+
+ dissect_ses(tvb, pinfo, parent_tree);
+ return TRUE;
+}
+
+void
+proto_reg_handoff_ses(void)
+{
+ /* find data dissector */
+ data_handle = find_dissector("data");
+
+ /* define sub dissector */
+ pres_handle = find_dissector("pres");
+
+ /* add our session dissector to cotp dissector list */
+ heur_dissector_add("cotp", dissect_ses_heur, proto_ses);
+}
diff --git a/epan/dissectors/packet-ses.h b/epan/dissectors/packet-ses.h
new file mode 100644
index 0000000000..7a8830fd6f
--- /dev/null
+++ b/epan/dissectors/packet-ses.h
@@ -0,0 +1,198 @@
+/* packet-ses.h
+*
+* Routine to dissect ISO 8327-1 OSI Session Protocol packets
+*
+* $Id$
+*
+* Yuriy Sidelnikov <YSidelnikov@hotmail.com>
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998 Gerald Combs
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define PROTO_STRING_SES "ISO 8327-1 OSI Session Protocol"
+#define PROTO_STRING_SES_INFO "ISO 8327-1 OSI Session Protocol."
+/*
+* Dissect ses-encapsulated data in a TCP stream.
+*/
+
+/* session parms */
+#define SES_EXT_CONT 0x01
+
+/* protocol versions */
+#define PROTOCOL_VERSION_1 0x01
+#define PROTOCOL_VERSION_2 0x02
+
+/* enclosure item */
+#define BEGINNING_SPDU 0x01
+#define END_SPDU 0x02
+
+#define DATA_TOKEN 0x01
+#define RELEASE_TOKEN 0x40
+#define SYNCHRONIZE_MINOR_TOKEN 0x04
+#define MAJOR_ACTIVITY_TOKEN 0x10
+
+/* session user req flag */
+#define HALF_DUPLEX_FUNCTION_UNIT 0x0001
+#define DUPLEX_FUNCTION_UNIT 0x0002
+#define EXPEDITED_DATA_FUNCTION_UNIT 0x0004
+#define MINOR_SYNCHRONIZE_FUNCTION_UNIT 0x0008
+#define MAJOR_SYNCHRONIZE_FUNCTION_UNIT 0x0010
+#define RESYNCHRONIZE_FUNCTION_UNIT 0x0020
+#define ACTIVITY_MANAGEMENT_FUNCTION_UNIT 0x0040
+#define NEGOTIATED_RELEASE_FUNCTION_UNIT 0x0080
+#define CAPABILITY_DATA_FUNCTION_UNIT 0x0100
+#define EXCEPTION_FUNCTION_UNIT 0x0200
+#define TYPED_DATA_FUNCTION_UNIT 0x0400
+#define SYMMETRIC_SYNCHRONIZE_FUNCTION_UNIT 0x0800
+#define DATA_SEPARATION_FUNCTION_UNIT 0x1000
+
+#define SES_EXCEPTION_REPORT 0x2000
+/*define SES_EXCEPTION_REPORT 0 */
+#define SES_DATA_TRANSFER 1
+#define SES_GIVE_TOKENS 1
+#define SES_PLEASE_TOKENS 2
+#define SES_EXPEDITED 5
+#define SES_PREPARE 7
+#define SES_NOT_FINISHED 8
+#define SES_FINISH 9
+#define SES_DISCONNECT 10
+#define SES_REFUSE 12
+#define SES_CONNECTION_REQUEST 13
+#define SES_CONNECTION_ACCEPT 14
+#define SES_CONNECTION_DATA_OVERFLOW 15
+#define SES_OVERFLOW_ACCEPT 16
+#define SES_GIVE_TOKENS_CONFIRM 21
+#define SES_GIVE_TOKENS_ACK 22
+#define SES_ABORT 25
+#define SES_ABORT_ACCEPT 26
+/*#define SES_ACTIVITY_INTERRUPT 25
+#define SES_ACTIVITY_INTERRUPT_ACK 26 */
+#define SES_ACTIVITY_RESUME 29
+#define SES_TYPED_DATA 33
+#define SES_RESYNCHRONIZE_ACK 34
+#define SES_MAJOR_SYNC_POINT 41
+/*#define SES_MAJOR_SYNC_POINT 41
+#define SES_ACTIVITY_END 41 */
+#define SES_MAJOR_SYNC_ACK 42
+#define SES_ACTIVITY_START 45
+#define SES_EXCEPTION_DATA 48
+#define SES_MINOR_SYNC_POINT 49
+#define SES_MINOR_SYNC_ACK 50
+#define SES_RESYNCHRONIZE 53
+#define SES_ACTIVITY_DISCARD 57
+#define SES_ACTIVITY_DISCARD_ACK 58
+#define SES_CAPABILITY 61
+#define SES_CAPABILITY_DATA_ACK 62
+
+/*
+reason code
+ 0: Rejection by called SS-user; reason not specified.
+ 1: Rejection by called SS-user due to temporary congestion.
+ 2: Rejection by called SS-user. Subsequent octets may be used
+ for user data up to a length of 512 octets if Protocol
+ Version 1 has been selected, and up to a length such that
+ the total length (including SI and LI) of the SPDU does
+ not exceed 65 539 octets if Protocol Version 2 has been
+ selected.
+ 128 + 1: Session Selector unknown.
+ 128 + 2: SS-user not attached to SSAP.
+ 128 + 3: SPM congestion at connect time.
+ 128 + 4: Proposed protocol versions not supported.
+ 128 + 5: Rejection by the SPM; reason not specified.
+ 128 + 6: Rejection by the SPM; implementation restriction stated in the
+ PICS.
+*/
+#define reason_not_specified 0
+#define temporary_congestion 1
+#define Subsequent 2
+#define Session_Selector_unknown 128+1
+#define SS_user_not_attached_to_SSAP 128+2
+#define SPM_congestion_at_connect_time 128+3
+#define versions_not_supported 128+4
+#define SPM_reason_not_specified 128+5
+#define SPM_implementation_restriction 128+6
+
+#define NON_TOKENS_SPDU FALSE
+#define TOKENS_SPDU TRUE
+
+#define TWO_BYTE_LEN 0xff
+
+/* PGI's */
+
+#define Connection_Identifier 1
+#define Connect_Accept_Item 5
+#define Linking_Information 33
+#define User_Data 193
+#define Extended_User_Data 194
+
+/* PI's */
+
+#define Called_SS_user_Reference 9
+#define Calling_SS_user_Reference 10
+#define Common_Reference 11
+#define Additional_Reference_Information 12
+
+#define Sync_Type_Item 15
+#define Token_Item 16
+#define Transport_Disconnect 17
+
+#define Protocol_Options 19
+#define Session_Requirement 20
+#define TSDU_Maximum_Size 21
+#define Version_Number 22
+#define Initial_Serial_Number 23
+#define Prepare_Type 24
+#define EnclosureItem 25
+#define Token_Setting_Item 26
+#define Resync_Type 27
+
+#define Serial_Number 42
+
+#define Reflect_Parameter 49
+
+#define Reason_Code 50
+#define Calling_Session_Selector 51
+#define Called_Session_Selector 52
+#define Second_Resync_Type 53
+#define Second_Serial_Number 54
+#define Second_Initial_Serial_Number 55
+#define Upper_Limit_Serial_Number 56
+#define Large_Initial_Serial_Number 57
+#define Large_Second_Initial_Serial_Number 58
+
+#define Data_Overflow 60
+
+/* transport disconnect values */
+#define transport_connection_is_released 0x01
+#define user_abort 0x02
+#define protocol_error 0x04
+#define no_reason 0x08
+
+
+#define SESSION_NO_ABORT 0
+#define SESSION_USER_ABORT 1
+#define SESSION_PROVIDER_ABORT 2
+
+/* data for presentation selector */
+struct SESSION_DATA_STRUCTURE
+{
+ guint8 spdu_type;
+ guint8 abort_type;
+};
+#define implementation_restriction 0x10
diff --git a/epan/dissectors/packet-sflow.c b/epan/dissectors/packet-sflow.c
new file mode 100644
index 0000000000..9177a7be74
--- /dev/null
+++ b/epan/dissectors/packet-sflow.c
@@ -0,0 +1,1068 @@
+/* packet-sflow.c
+ * Routines for sFlow dissection
+ * Copyright 2003, Jeff Rizzo <riz@boogers.sf.ca.us>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This file (mostly) implements a dissector for sFlow (RFC3176),
+ * from the version 4 spec at http://www.sflow.org/SFLOW-DATAGRAM.txt .
+ *
+ * TODO:
+ * Fix the highlighting of the datastream when bits are selected
+ * split things out into packet-sflow.h ?
+ * make routines more consistent as to whether they return
+ * 'offset' or bytes consumed ('len')
+ * implement sampled_ipv4 and sampled_ipv6 packet data types
+ * implement extended_gateway
+ * implement extended_user
+ * implement extended_url
+ * implement non-generic counters sampling
+ * implement the draft version 5 spec
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+/*#include "packet-sflow.h"*/
+
+#define UDP_PORT_SFLOW 6343
+
+#define ADDRESS_IPV4 1
+#define ADDRESS_IPV6 2
+
+#define FLOWSAMPLE 1
+#define COUNTERSSAMPLE 2
+
+static const value_string sflow_sampletype[] = {
+ { FLOWSAMPLE, "Flow sample" },
+ { COUNTERSSAMPLE, "Counters sample" },
+ { 0, NULL }
+};
+
+/* interface counter types */
+#define SFLOW_COUNTERS_GENERIC 1
+#define SFLOW_COUNTERS_ETHERNET 2
+#define SFLOW_COUNTERS_TOKENRING 3
+#define SFLOW_COUNTERS_FDDI 4
+#define SFLOW_COUNTERS_VG 5
+#define SFLOW_COUNTERS_WAN 6
+#define SFLOW_COUNTERS_VLAN 7
+
+static const value_string sflow_counterstype [] = {
+ { SFLOW_COUNTERS_GENERIC, "Generic counters" },
+ { SFLOW_COUNTERS_ETHERNET, "Ethernet counters" },
+ { SFLOW_COUNTERS_FDDI, "FDDI counters" },
+ { SFLOW_COUNTERS_VG, "100baseVG counters" },
+ { SFLOW_COUNTERS_WAN, "WAN counters" },
+ { SFLOW_COUNTERS_VLAN, "VLAN counters" },
+ { 0, NULL }
+};
+
+#define MAX_HEADER_SIZE 256
+
+#define SFLOW_PACKET_DATA_TYPE_HEADER 1
+#define SFLOW_PACKET_DATA_TYPE_IPV4 2
+#define SFLOW_PACKET_DATA_TYPE_IPV6 3
+
+static const value_string sflow_packet_information_type [] = {
+ { SFLOW_PACKET_DATA_TYPE_HEADER, "Packet headers are sampled" },
+ { SFLOW_PACKET_DATA_TYPE_IPV4, "IP Version 4 data" },
+ { SFLOW_PACKET_DATA_TYPE_IPV6, "IP Version 6 data" },
+ { 0, NULL}
+};
+
+#define SFLOW_HEADER_ETHERNET 1
+#define SFLOW_HEADER_TOKENBUS 2
+#define SFLOW_HEADER_TOKENRING 3
+#define SFLOW_HEADER_FDDI 4
+#define SFLOW_HEADER_FRAME_RELAY 5
+#define SFLOW_HEADER_X25 6
+#define SFLOW_HEADER_PPP 7
+#define SFLOW_HEADER_SMDS 8
+#define SFLOW_HEADER_AAL5 9
+#define SFLOW_HEADER_AAL5_IP 10
+#define SFLOW_HEADER_IPv4 11
+#define SFLOW_HEADER_IPv6 12
+#define SFLOW_HEADER_MPLS 13
+
+static const value_string sflow_header_protocol[] = {
+ { SFLOW_HEADER_ETHERNET, "Ethernet" },
+ { SFLOW_HEADER_TOKENBUS, "Token Bus" },
+ { SFLOW_HEADER_TOKENRING, "Token Ring" },
+ { SFLOW_HEADER_FDDI, "FDDI" },
+ { SFLOW_HEADER_FRAME_RELAY, "Frame Relay" },
+ { SFLOW_HEADER_X25, "X.25" },
+ { SFLOW_HEADER_PPP, "PPP" },
+ { SFLOW_HEADER_SMDS, "SMDS" },
+ { SFLOW_HEADER_AAL5, "ATM AAL5" },
+ { SFLOW_HEADER_AAL5_IP, "ATM AAL5-IP (e.g., Cisco AAL5 mux)" },
+ { SFLOW_HEADER_IPv4, "IPv4" },
+ { SFLOW_HEADER_IPv6, "IPv6" },
+ { SFLOW_HEADER_MPLS, "MPLS" },
+ { 0, NULL }
+};
+
+/* extended data types */
+#define SFLOW_EXTENDED_SWITCH 1
+#define SFLOW_EXTENDED_ROUTER 2
+#define SFLOW_EXTENDED_GATEWAY 3
+#define SFLOW_EXTENDED_USER 4
+#define SFLOW_EXTENDED_URL 5
+
+static const value_string sflow_extended_data_types[] = {
+ { SFLOW_EXTENDED_SWITCH, "Extended switch information" },
+ { SFLOW_EXTENDED_ROUTER, "Extended router information" },
+ { SFLOW_EXTENDED_GATEWAY, "Extended gateway information" },
+ { SFLOW_EXTENDED_USER, "Extended user information" },
+ { SFLOW_EXTENDED_URL, "Extended URL information" },
+ { 0, NULL }
+};
+
+
+/* flow sample header */
+struct sflow_flow_sample_header {
+ guint32 sequence_number;
+ guint32 source_id;
+ guint32 sampling_rate;
+ guint32 sample_pool;
+ guint32 drops;
+ guint32 input;
+ guint32 output;
+};
+
+/* counters sample header */
+struct sflow_counters_sample_header {
+ guint32 sequence_number;
+ guint32 source_id;
+ guint32 sampling_interval;
+ guint32 counters_type;
+};
+
+/* generic interface counters */
+struct if_counters {
+ guint32 ifIndex;
+ guint32 ifType;
+ guint64 ifSpeed;
+ guint32 ifDirection;
+ guint32 ifStatus;
+ guint64 ifInOctets;
+ guint32 ifInUcastPkts;
+ guint32 ifInMulticastPkts;
+ guint32 ifInBroadcastPkts;
+ guint32 ifInDiscards;
+ guint32 ifInErrors;
+ guint32 ifInUnknownProtos;
+ guint64 ifOutOctets;
+ guint32 ifOutUcastPkts;
+ guint32 ifOutMulticastPkts;
+ guint32 ifOutBroadcastPkts;
+ guint32 ifOutDiscards;
+ guint32 ifOutErrors;
+ guint32 ifPromiscuousMode;
+};
+
+/* ethernet counters. These will be preceded by generic counters. */
+struct ethernet_counters {
+ guint32 dot3StatsAlignmentErrors;
+ guint32 dot3StatsFCSErrors;
+ guint32 dot3StatsSingleCollisionFrames;
+ guint32 dot3StatsMultipleCollisionFrames;
+ guint32 dot3StatsSQETestErrors;
+ guint32 dot3StatsDeferredTransmissions;
+ guint32 dot3StatsLateCollisions;
+ guint32 dot3StatsExcessiveCollisions;
+ guint32 dot3StatsInternalMacTransmitErrors;
+ guint32 dot3StatsCarrierSenseErrors;
+ guint32 dot3StatsFrameTooLongs;
+ guint32 dot3StatsInternalMacReceiveErrors;
+ guint32 dot3StatsSymbolErrors;
+};
+
+/* Token Ring counters */
+struct token_ring_counters {
+ guint32 dot5StatsLineErrors;
+ guint32 dot5StatsBurstErrors;
+ guint32 dot5StatsACErrors;
+ guint32 dot5StatsAbortTransErrors;
+ guint32 dot5StatsInternalErrors;
+ guint32 dot5StatsLostFrameErrors;
+ guint32 dot5StatsReceiveCongestions;
+ guint32 dot5StatsFrameCopiedErrors;
+ guint32 dot5StatsTokenErrors;
+ guint32 dot5StatsSoftErrors;
+ guint32 dot5StatsHardErrors;
+ guint32 dot5StatsSignalLoss;
+ guint32 dot5StatsTransmitBeacons;
+ guint32 dot5StatsRecoverys;
+ guint32 dot5StatsLobeWires;
+ guint32 dot5StatsRemoves;
+ guint32 dot5StatsSingles;
+ guint32 dot5StatsFreqErrors;
+};
+
+/* 100BaseVG counters */
+
+struct vg_counters {
+ guint32 dot12InHighPriorityFrames;
+ guint64 dot12InHighPriorityOctets;
+ guint32 dot12InNormPriorityFrames;
+ guint64 dot12InNormPriorityOctets;
+ guint32 dot12InIPMErrors;
+ guint32 dot12InOversizeFrameErrors;
+ guint32 dot12InDataErrors;
+ guint32 dot12InNullAddressedFrames;
+ guint32 dot12OutHighPriorityFrames;
+ guint64 dot12OutHighPriorityOctets;
+ guint32 dot12TransitionIntoTrainings;
+ guint64 dot12HCInHighPriorityOctets;
+ guint64 dot12HCInNormPriorityOctets;
+ guint64 dot12HCOutHighPriorityOctets;
+};
+
+/* VLAN counters */
+
+struct vlan_counters {
+ guint32 vlan_id;
+ guint32 octets;
+ guint32 ucastPkts;
+ guint32 multicastPkts;
+ guint32 broadcastPkts;
+ guint32 discards;
+};
+
+/* Initialize the protocol and registered fields */
+static int proto_sflow = -1;
+static int hf_sflow_version = -1;
+/*static int hf_sflow_agent_address_type = -1; */
+static int hf_sflow_agent_address_v4 = -1;
+static int hf_sflow_agent_address_v6 = -1;
+static int hf_sflow_seqnum = -1;
+static int hf_sflow_sysuptime = -1;
+static int hf_sflow_numsamples = -1;
+static int hf_sflow_header_protocol = -1;
+static int hf_sflow_sampletype = -1;
+static int hf_sflow_header = -1;
+static int hf_sflow_packet_information_type = -1;
+static int hf_sflow_vlan_in = -1; /* incoming 802.1q VLAN ID */
+static int hf_sflow_vlan_out = -1; /* outgoing 802.1q VLAN ID */
+static int hf_sflow_pri_in = -1; /* incominging 802.1p priority */
+static int hf_sflow_pri_out = -1; /* outgoing 802.1p priority */
+static int hf_sflow_nexthop_v4 = -1; /* nexthop address */
+static int hf_sflow_nexthop_v6 = -1; /* nexthop address */
+static int hf_sflow_ifindex = -1;
+static int hf_sflow_iftype = -1;
+static int hf_sflow_ifspeed = -1;
+static int hf_sflow_ifdirection = -1;
+static int hf_sflow_ifstatus = -1;
+static int hf_sflow_ifinoct = -1;
+static int hf_sflow_ifinpkt = -1;
+static int hf_sflow_ifinmcast = -1;
+static int hf_sflow_ifinbcast = -1;
+static int hf_sflow_ifinerr = -1;
+static int hf_sflow_ifindisc = -1;
+static int hf_sflow_ifinunk = -1;
+static int hf_sflow_ifoutoct = -1;
+static int hf_sflow_ifoutpkt = -1;
+static int hf_sflow_ifoutmcast = -1;
+static int hf_sflow_ifoutbcast = -1;
+static int hf_sflow_ifoutdisc = -1;
+static int hf_sflow_ifouterr = -1;
+static int hf_sflow_ifpromisc = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_sflow = -1;
+static gint ett_sflow_sample = -1;
+static gint ett_sflow_extended_data = -1;
+static gint ett_sflow_sampled_header = -1;
+
+/* dissectors for other protocols */
+static dissector_handle_t eth_handle;
+static dissector_handle_t tr_handle;
+static dissector_handle_t fddi_handle;
+static dissector_handle_t fr_handle;
+static dissector_handle_t x25_handle;
+static dissector_handle_t ppp_handle;
+static dissector_handle_t smds_handle;
+static dissector_handle_t aal5_handle;
+static dissector_handle_t ipv4_handle;
+static dissector_handle_t ipv6_handle;
+static dissector_handle_t mpls_handle;
+
+/* dissect a sampled header - layer 2 protocols */
+static gint
+dissect_sflow_sampled_header(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, volatile gint offset)
+{
+ guint32 header_proto, frame_length;
+ volatile guint32 header_length;
+ tvbuff_t *next_tvb;
+ proto_tree *sflow_header_tree;
+ proto_item *ti;
+ /* stuff for saving column state before calling other dissectors.
+ * Thanks to Guy Harris for the tip. */
+ gboolean save_writable;
+ volatile address save_dl_src;
+ volatile address save_dl_dst;
+ volatile address save_net_src;
+ volatile address save_net_dst;
+ volatile address save_src;
+ volatile address save_dst;
+
+ header_proto = tvb_get_ntohl(tvb,offset);
+ proto_tree_add_item(tree, hf_sflow_header_protocol, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ frame_length = tvb_get_ntohl(tvb,offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Frame Length: %d bytes",
+ frame_length);
+ offset += 4;
+ header_length = tvb_get_ntohl(tvb,offset);
+ offset += 4;
+
+ if (header_length % 4) /* XDR requires 4-byte alignment */
+ header_length += 4 - (header_length % 4);
+
+
+ ti = proto_tree_add_item(tree, hf_sflow_header, tvb, offset,
+ header_length, FALSE);
+ sflow_header_tree = proto_item_add_subtree(ti, ett_sflow_sampled_header);
+
+ /* hand the header off to the appropriate dissector. It's probably
+ * a short frame, so ignore any exceptions. */
+ next_tvb = tvb_new_subset(tvb, offset, header_length, frame_length);
+
+ /* save some state */
+ save_writable = col_get_writable(pinfo->cinfo);
+ col_set_writable(pinfo->cinfo, FALSE);
+ save_dl_src = pinfo->dl_src;
+ save_dl_dst = pinfo->dl_dst;
+ save_net_src = pinfo->net_src;
+ save_net_dst = pinfo->net_dst;
+ save_src = pinfo->src;
+ save_dst = pinfo->dst;
+
+ TRY {
+ switch (header_proto) {
+ case SFLOW_HEADER_ETHERNET:
+ call_dissector(eth_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_TOKENRING:
+ call_dissector(tr_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_FDDI:
+ call_dissector(fddi_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_FRAME_RELAY:
+ call_dissector(fr_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_X25:
+ call_dissector(x25_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_PPP:
+ call_dissector(ppp_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_SMDS:
+ call_dissector(smds_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_AAL5:
+ case SFLOW_HEADER_AAL5_IP:
+ /* I'll be surprised if this works! I have no AAL5 captures
+ * to test with, and I'm not sure how the encapsulation goes */
+ call_dissector(aal5_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_IPv4:
+ call_dissector(ipv4_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_IPv6:
+ call_dissector(ipv6_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ case SFLOW_HEADER_MPLS:
+ call_dissector(mpls_handle, next_tvb, pinfo, sflow_header_tree);
+ break;
+ default:
+ /* some of the protocols, I have no clue where to begin. */
+ break;
+ };
+ }
+ CATCH2(BoundsError, ReportedBoundsError) {
+ ; /* do nothing */
+ }
+ ENDTRY;
+
+ /* restore saved state */
+ col_set_writable(pinfo->cinfo, save_writable);
+ pinfo->dl_src = save_dl_src;
+ pinfo->dl_dst = save_dl_dst;
+ pinfo->net_src = save_net_src;
+ pinfo->net_dst = save_net_dst;
+ pinfo->src = save_src;
+ pinfo->dst = save_dst;
+
+ offset += header_length;
+ return offset;
+}
+
+/* extended switch data, after the packet data */
+static gint
+dissect_sflow_extended_switch(tvbuff_t *tvb, proto_tree *tree, gint offset)
+{
+ gint32 len = 0;
+
+ proto_tree_add_item(tree, hf_sflow_vlan_in, tvb, offset + len, 4, FALSE);
+ len += 4;
+ proto_tree_add_item(tree, hf_sflow_vlan_out, tvb, offset + len, 4, FALSE);
+ len += 4;
+ proto_tree_add_item(tree, hf_sflow_pri_in, tvb, offset + len, 4, FALSE);
+ len += 4;
+ proto_tree_add_item(tree, hf_sflow_pri_out, tvb, offset + len, 4, FALSE);
+ len += 4;
+
+ return len;
+}
+
+/* extended router data, after the packet data */
+static gint
+dissect_sflow_extended_router(tvbuff_t *tvb, proto_tree *tree, gint offset)
+{
+ gint32 len = 0;
+ guint32 address_type, mask_bits;
+
+ address_type = tvb_get_ntohl(tvb, offset);
+ switch (address_type) {
+ case ADDRESS_IPV4:
+ proto_tree_add_ipv4(tree, hf_sflow_nexthop_v4, tvb, offset + len,
+ 8, FALSE);
+ len += 8;
+ break;
+ case ADDRESS_IPV6:
+ proto_tree_add_ipv6(tree, hf_sflow_nexthop_v6, tvb, offset + len,
+ 20, FALSE);
+ len += 20;
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset + len, 4,
+ "Unknown address type (%d)", address_type);
+ len += 4; /* not perfect, but what else to do? */
+ return len; /* again, this is wrong. but... ? */
+ break;
+ };
+
+ mask_bits = tvb_get_ntohl(tvb, offset + len);
+ proto_tree_add_text(tree, tvb, offset + len, 4,
+ "Source address prefix is %d bits long", mask_bits);
+ len += 4;
+ mask_bits = tvb_get_ntohl(tvb, offset + len);
+ proto_tree_add_text(tree, tvb, offset + len, 4,
+ "Destination address prefix is %d bits long",
+ mask_bits);
+ len += 4;
+ return len;
+}
+
+/* dissect a flow sample */
+static gint
+dissect_sflow_flow_sample(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, gint offset, proto_item *parent)
+{
+ struct sflow_flow_sample_header flow_header;
+ proto_tree *sflow_sample_tree;
+ proto_item *ti;
+ guint32 packet_type, extended_data, ext_type, i;
+
+ /* grab the flow header. This will remain in network byte
+ order, so must convert each item before use */
+ tvb_memcpy(tvb,(guint8 *)&flow_header,offset,sizeof(flow_header));
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Sequence number: %u",
+ g_ntohl(flow_header.sequence_number));
+ proto_item_append_text(parent, ", seq %u",
+ g_ntohl(flow_header.sequence_number));
+ proto_tree_add_text(tree, tvb, offset+4, 4,
+ "Source ID class: %u index: %u",
+ g_ntohl(flow_header.source_id) >> 24,
+ g_ntohl(flow_header.source_id) & 0x00ffffff);
+ proto_tree_add_text(tree, tvb, offset+8, 4,
+ "Sampling rate: 1 out of %u packets",
+ g_ntohl(flow_header.sampling_rate));
+ proto_tree_add_text(tree, tvb, offset+12, 4,
+ "Sample pool: %u total packets",
+ g_ntohl(flow_header.sample_pool));
+ proto_tree_add_text(tree, tvb, offset+16, 4,
+ "Dropped packets: %u",
+ g_ntohl(flow_header.drops));
+ proto_tree_add_text(tree, tvb, offset+20, 4,
+ "Input Interface: ifIndex %u",
+ g_ntohl(flow_header.input));
+ if (g_ntohl(flow_header.output) >> 31)
+ proto_tree_add_text(tree, tvb, offset+24, 4,
+ "multiple outputs: %u interfaces",
+ g_ntohl(flow_header.output) & 0x00ffffff);
+ else
+ proto_tree_add_text(tree, tvb, offset+24, 4,
+ "Output interface: ifIndex %u",
+ g_ntohl(flow_header.output) & 0x00ffffff);
+ offset += sizeof(flow_header);
+
+ /* what kind of flow sample is it? */
+ packet_type = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ switch (packet_type) {
+ case SFLOW_PACKET_DATA_TYPE_HEADER:
+ offset = dissect_sflow_sampled_header(tvb, pinfo, tree, offset);
+ break;
+ case SFLOW_PACKET_DATA_TYPE_IPV4:
+ case SFLOW_PACKET_DATA_TYPE_IPV6:
+ default:
+ break;
+ };
+ /* still need to dissect extended data */
+ extended_data = tvb_get_ntohl(tvb,offset);
+ offset += 4;
+
+ for (i=0; i < extended_data; i++) {
+ /* figure out what kind of extended data it is */
+ ext_type = tvb_get_ntohl(tvb,offset);
+
+ /* create a subtree. Might want to move this to
+ * the end, so more info can be correct.
+ */
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "%s",
+ val_to_str(ext_type,
+ sflow_extended_data_types,
+ "Unknown extended information"));
+ offset += 4;
+ sflow_sample_tree = proto_item_add_subtree(ti, ett_sflow_sample);
+
+ switch (ext_type) {
+ case SFLOW_EXTENDED_SWITCH:
+ offset += dissect_sflow_extended_switch(tvb, sflow_sample_tree,
+ offset);
+ break;
+ case SFLOW_EXTENDED_ROUTER:
+ offset += dissect_sflow_extended_router(tvb, sflow_sample_tree,
+ offset);
+ break;
+ case SFLOW_EXTENDED_GATEWAY:
+ break;
+ case SFLOW_EXTENDED_USER:
+ break;
+ case SFLOW_EXTENDED_URL:
+ break;
+ default:
+ break;
+ }
+ }
+ return offset;
+
+}
+
+/* dissect a counters sample */
+static gint
+dissect_sflow_counters_sample(tvbuff_t *tvb, proto_tree *tree,
+ gint offset, proto_item *parent)
+{
+ struct sflow_counters_sample_header counters_header;
+ struct if_counters ifc;
+ struct ethernet_counters ethc;
+ struct token_ring_counters tokc;
+ struct vg_counters vgc;
+ struct vlan_counters vlanc;
+
+ /* grab the flow header. This will remain in network byte
+ order, so must convert each item before use */
+ tvb_memcpy(tvb,(guint8 *)&counters_header,offset,sizeof(counters_header));
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Sequence number: %u",
+ g_ntohl(counters_header.sequence_number));
+ proto_item_append_text(parent, ", seq %u",
+ g_ntohl(counters_header.sequence_number));
+ proto_tree_add_text(tree, tvb, offset + 4, 4,
+ "Source ID class: %u index: %u",
+ g_ntohl(counters_header.source_id) >> 24,
+ g_ntohl(counters_header.source_id) & 0x00ffffff);
+ proto_tree_add_text(tree, tvb, offset + 8, 4,
+ "Sampling Interval: %u",
+ g_ntohl(counters_header.sampling_interval));
+ proto_tree_add_text(tree, tvb, offset + 12, 4, "Counters type: %s",
+ val_to_str(g_ntohl(counters_header.counters_type),
+ sflow_counterstype, "Unknown type"));
+
+ offset += sizeof(counters_header);
+
+ /* most counters types have the "generic" counters first */
+ switch (g_ntohl(counters_header.counters_type)) {
+ case SFLOW_COUNTERS_GENERIC:
+ case SFLOW_COUNTERS_ETHERNET:
+ case SFLOW_COUNTERS_TOKENRING:
+ case SFLOW_COUNTERS_FDDI:
+ case SFLOW_COUNTERS_VG:
+ case SFLOW_COUNTERS_WAN:
+ tvb_memcpy(tvb,(guint8 *)&ifc, offset, sizeof(ifc));
+ proto_item_append_text(parent, ", ifIndex %u",
+ g_ntohl(ifc.ifIndex));
+ proto_tree_add_item(tree, hf_sflow_ifindex, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_iftype, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifspeed, tvb, offset, 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(tree, hf_sflow_ifdirection, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifstatus, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifinoct, tvb, offset, 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(tree, hf_sflow_ifinpkt, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifinmcast, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifinbcast, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifindisc, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifinerr, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifinunk, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifoutoct, tvb, offset, 8, FALSE);
+ offset += 8;
+ proto_tree_add_item(tree, hf_sflow_ifoutpkt, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifoutmcast, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifoutbcast, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifoutdisc, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifouterr, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(tree, hf_sflow_ifpromisc, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ break;
+ };
+
+ /* Some counter types have other info to gather */
+ switch (g_ntohl(counters_header.counters_type)) {
+ case SFLOW_COUNTERS_ETHERNET:
+ tvb_memcpy(tvb,(guint8 *)&ethc, offset, sizeof(ethc));
+ offset += sizeof(ethc);
+ break;
+ case SFLOW_COUNTERS_TOKENRING:
+ tvb_memcpy(tvb,(guint8 *)&tokc, offset, sizeof(tokc));
+ offset += sizeof(tokc);
+ break;
+ case SFLOW_COUNTERS_VG:
+ tvb_memcpy(tvb,(guint8 *)&vgc, offset, sizeof(vgc));
+ offset += sizeof(vgc);
+ break;
+ case SFLOW_COUNTERS_VLAN:
+ tvb_memcpy(tvb,(guint8 *)&vlanc, offset, sizeof(vlanc));
+ offset += sizeof(vlanc);
+ break;
+ default:
+ break;
+ }
+ return offset;
+}
+
+/* Code to dissect the sflow samples */
+static gint
+dissect_sflow_samples(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, gint offset)
+{
+ proto_tree *sflow_sample_tree;
+ proto_item *ti; /* tree item */
+ guint32 sample_type;
+
+ /* decide what kind of sample it is. */
+ sample_type = tvb_get_ntohl(tvb,offset);
+
+ ti = proto_tree_add_text(tree, tvb, offset, 4, "%s",
+ val_to_str(sample_type, sflow_sampletype,
+ "Unknown sample type"));
+ sflow_sample_tree = proto_item_add_subtree(ti, ett_sflow_sample);
+
+ proto_tree_add_item(sflow_sample_tree, hf_sflow_sampletype, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ switch (sample_type) {
+ case FLOWSAMPLE:
+ return dissect_sflow_flow_sample(tvb, pinfo, sflow_sample_tree,
+ offset, ti);
+ break;
+ case COUNTERSSAMPLE:
+ return dissect_sflow_counters_sample(tvb, sflow_sample_tree,
+ offset, ti);
+ break;
+ default:
+ break;
+ };
+ return offset;
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_sflow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *sflow_tree;
+ guint32 version, seqnum;
+ guint32 agent_address_type;
+ union {
+ guint8 v4[4];
+ guint8 v6[16];
+ } agent_address;
+ guint32 numsamples;
+ volatile guint offset=0;
+ guint i=0;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "sflow");
+
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_sflow, tvb, 0, -1, FALSE);
+
+ sflow_tree = proto_item_add_subtree(ti, ett_sflow);
+
+ version = tvb_get_ntohl(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "sFlow V%u",
+ version);
+ proto_tree_add_item(sflow_tree,
+ hf_sflow_version, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ agent_address_type = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ switch (agent_address_type) {
+ case ADDRESS_IPV4:
+ tvb_memcpy(tvb, agent_address.v4, offset, 4);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", agent %s",
+ ip_to_str(agent_address.v4));
+ proto_tree_add_item(sflow_tree,
+ hf_sflow_agent_address_v4, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ break;
+ case ADDRESS_IPV6:
+ tvb_memcpy(tvb, agent_address.v6, offset, 16);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", agent %s",
+ ip6_to_str((struct e_in6_addr *)agent_address.v6));
+ proto_tree_add_item(sflow_tree,
+ hf_sflow_agent_address_v6, tvb, offset,
+ 16, FALSE);
+ offset += 16;
+ break;
+ default:
+ /* unknown address. this will cause a malformed packet. */
+ break;
+ };
+
+ seqnum = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(sflow_tree, hf_sflow_seqnum, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(sflow_tree, hf_sflow_sysuptime, tvb,
+ offset+4, 4, FALSE);
+ offset += 4;
+ numsamples = tvb_get_ntohl(tvb,offset);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", seq %u, %u samples",
+ seqnum, numsamples);
+ proto_tree_add_item(sflow_tree, hf_sflow_numsamples, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ /* Ok, we're now at the end of the sflow datagram header;
+ * everything from here out should be samples. Loop over
+ * the expected number of samples, and pass them to the appropriate
+ * dissectors.
+ */
+ for (i=0; i < numsamples; i++) {
+ offset = dissect_sflow_samples(tvb, pinfo, sflow_tree, offset);
+ }
+
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_sflow(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_sflow_version,
+ { "datagram version", "sflow.version",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "sFlow datagram version", HFILL }
+ },
+ { &hf_sflow_agent_address_v4,
+ { "agent address", "sflow.agent",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "sFlow Agent IP address", HFILL }
+ },
+ { &hf_sflow_agent_address_v6,
+ { "agent address", "sflow.agent.v6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "sFlow Agent IPv6 address", HFILL }
+ },
+ { &hf_sflow_seqnum,
+ { "Sequence number", "sflow.sequence_number",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "sFlow datagram sequence number", HFILL }
+ },
+ { &hf_sflow_sysuptime,
+ { "SysUptime", "sflow.sysuptime",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "System Uptime", HFILL }
+ },
+ { &hf_sflow_numsamples,
+ { "NumSamples", "sflow.numsamples",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of samples in sFlow datagram", HFILL }
+ },
+ { &hf_sflow_sampletype,
+ { "sFlow sample type", "sflow.sampletype",
+ FT_UINT32, BASE_DEC, VALS(sflow_sampletype), 0x0,
+ "Type of sFlow sample", HFILL }
+ },
+ { &hf_sflow_header_protocol,
+ { "Header protocol", "sflow.header_protocol",
+ FT_UINT32, BASE_DEC, VALS(sflow_header_protocol), 0x0,
+ "Protocol of sampled header", HFILL }
+ },
+ { &hf_sflow_header,
+ { "Header of sampled packet", "sflow.header",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Data from sampled header", HFILL }
+ },
+ { &hf_sflow_packet_information_type,
+ { "Sample type", "sflow.packet_information_type",
+ FT_UINT32, BASE_DEC, VALS(sflow_packet_information_type), 0x0,
+ "Type of sampled information", HFILL }
+ },
+ { &hf_sflow_vlan_in,
+ { "Incoming 802.1q VLAN", "sflow.vlan.in",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Incoming VLAN ID", HFILL }
+ },
+ { &hf_sflow_vlan_out,
+ { "Outgoing 802.1q VLAN", "sflow.vlan.out",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Outgoing VLAN ID", HFILL }
+ },
+ { &hf_sflow_pri_in,
+ { "Incoming 802.1p priority", "sflow.pri.in",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Incoming 802.1p priority", HFILL }
+ },
+ { &hf_sflow_pri_out,
+ { "Outgoing 802.1p priority", "sflow.pri.out",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Outgoing 802.1p priority", HFILL }
+ },
+ { &hf_sflow_nexthop_v4,
+ { "Next Hop", "sflow.nexthop",
+ FT_IPv4, BASE_DEC, NULL, 0x0,
+ "Next Hop address", HFILL }
+ },
+ { &hf_sflow_nexthop_v6,
+ { "Next Hop", "sflow.nexthop",
+ FT_IPv6, BASE_HEX, NULL, 0x0,
+ "Next Hop address", HFILL }
+ },
+ { &hf_sflow_ifindex,
+ { "Interface index", "sflow.ifindex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Index", HFILL }
+ },
+ { &hf_sflow_iftype,
+ { "Interface Type", "sflow.iftype",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Type", HFILL }
+ },
+ { &hf_sflow_ifspeed,
+ { "Interface Speed", "sflow.ifspeed",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Interface Speed", HFILL }
+ },
+ { &hf_sflow_ifdirection,
+ { "Interface Direction", "sflow.ifdirection",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Direction", HFILL }
+ },
+ { &hf_sflow_ifstatus,
+ { "Interface Status", "sflow.ifstatus",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Status", HFILL }
+ },
+ { &hf_sflow_ifinoct,
+ { "Input Octets", "sflow.ifinoct",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Interface Input Octets", HFILL }
+ },
+ { &hf_sflow_ifinpkt,
+ { "Input Packets", "sflow.ifinpkt",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Input Packets", HFILL }
+ },
+ { &hf_sflow_ifinmcast,
+ { "Input Multicast Packets", "sflow.ifinmcast",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Input Multicast Packets", HFILL }
+ },
+ { &hf_sflow_ifinbcast,
+ { "Input Broadcast Packets", "sflow.ifinbcast",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Input Broadcast Packets", HFILL }
+ },
+ { &hf_sflow_ifindisc,
+ { "Input Discarded Packets", "sflow.ifindisc",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Input Discarded Packets", HFILL }
+ },
+ { &hf_sflow_ifinerr,
+ { "Input Errors", "sflow.ifinerr",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Input Errors", HFILL }
+ },
+ { &hf_sflow_ifinunk,
+ { "Input Unknown Protocol Packets", "sflow.ifinunk",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Input Unknown Protocol Packets", HFILL }
+ },
+ { &hf_sflow_ifoutoct,
+ { "Output Octets", "sflow.ifoutoct",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "Outterface Output Octets", HFILL }
+ },
+ { &hf_sflow_ifoutpkt,
+ { "Output Packets", "sflow.ifoutpkt",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Output Packets", HFILL }
+ },
+ { &hf_sflow_ifoutmcast,
+ { "Output Multicast Packets", "sflow.ifoutmcast",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Output Multicast Packets", HFILL }
+ },
+ { &hf_sflow_ifoutbcast,
+ { "Output Broadcast Packets", "sflow.ifoutbcast",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Output Broadcast Packets", HFILL }
+ },
+ { &hf_sflow_ifoutdisc,
+ { "Output Discarded Packets", "sflow.ifoutdisc",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Output Discarded Packets", HFILL }
+ },
+ { &hf_sflow_ifouterr,
+ { "Output Errors", "sflow.ifouterr",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Output Errors", HFILL }
+ },
+ { &hf_sflow_ifpromisc,
+ { "Promiscuous Mode", "sflow.ifpromisc",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Interface Promiscuous Mode", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_sflow,
+ &ett_sflow_sample,
+ &ett_sflow_extended_data,
+ &ett_sflow_sampled_header,
+ };
+
+/* Register the protocol name and description */
+ proto_sflow = proto_register_protocol("InMon sFlow",
+ "sFlow", "sflow");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_sflow, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_sflow(void)
+{
+ dissector_handle_t sflow_handle;
+
+ eth_handle = find_dissector("eth");
+ tr_handle = find_dissector("tr");
+ fddi_handle = find_dissector("fddi");
+ fr_handle = find_dissector("fr");
+ x25_handle = find_dissector("x25");
+ ppp_handle = find_dissector("ppp");
+ smds_handle = find_dissector("smds");
+ aal5_handle = find_dissector("atm");
+ ipv4_handle = find_dissector("ip");
+ ipv6_handle = find_dissector("ipv6");
+ mpls_handle = find_dissector("mpls");
+
+ sflow_handle = create_dissector_handle(dissect_sflow,
+ proto_sflow);
+ dissector_add("udp.port", UDP_PORT_SFLOW, sflow_handle);
+}
diff --git a/epan/dissectors/packet-sigcomp.c b/epan/dissectors/packet-sigcomp.c
new file mode 100644
index 0000000000..8cbbcc824c
--- /dev/null
+++ b/epan/dissectors/packet-sigcomp.c
@@ -0,0 +1,1975 @@
+/* packet-sigcomp.c
+ * Routines for Signaling Compression (SigComp) dissection.
+ * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * References:
+ * http://www.ietf.org/rfc/rfc3320.txt?number=3320
+ * http://www.ietf.org/rfc/rfc3321.txt?number=3321
+ * Useful links :
+ * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-impl-guide-02.txt
+ * http://www.ietf.org/internet-drafts/draft-ietf-rohc-sigcomp-sip-01.txt
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "prefs.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_sigcomp = -1;
+static int hf_sigcomp_t_bit = -1;
+static int hf_sigcomp_len = -1;
+static int hf_sigcomp_returned_feedback_item = -1;
+static int hf_sigcomp_returned_feedback_item_len = -1;
+static int hf_sigcomp_code_len = -1;
+static int hf_sigcomp_destination = -1;
+static int hf_sigcomp_partial_state = -1;
+static int hf_sigcomp_udvm_instr = -1;
+static int hf_udvm_multitype_bytecode = -1;
+static int hf_udvm_reference_bytecode = -1;
+static int hf_udvm_literal_bytecode = -1;
+static int hf_udvm_operand = -1;
+static int hf_udvm_length = -1;
+static int hf_udvm_destination = -1;
+static int hf_udvm_at_address = -1;
+static int hf_udvm_address = -1;
+static int hf_udvm_literal_num = -1;
+static int hf_udvm_value = -1;
+static int hf_udvm_addr_value = -1;
+static int hf_partial_identifier_start = -1;
+static int hf_partial_identifier_length = -1;
+static int hf_state_begin = -1;
+static int hf_udvm_state_length = -1;
+static int hf_udvm_state_length_addr = -1;
+static int hf_udvm_state_address = -1;
+static int hf_udvm_state_address_addr = -1;
+static int hf_udvm_state_instr = -1;
+static int hf_udvm_operand_1 = -1;
+static int hf_udvm_operand_2 = -1;
+static int hf_udvm_operand_2_addr = -1;
+static int hf_udvm_j = -1;
+static int hf_udvm_output_start = -1;
+static int hf_udvm_output_start_addr = -1;
+static int hf_udvm_output_length = -1;
+static int hf_udvm_output_length_addr = -1;
+static int hf_udvm_req_feedback_loc = -1;
+static int hf_udvm_min_acc_len = -1;
+static int hf_udvm_state_ret_pri = -1;
+static int hf_udvm_ret_param_loc = -1;
+static int hf_udvm_position = -1;
+static int hf_udvm_ref_dest = -1;
+static int hf_udvm_bits = -1;
+static int hf_udvm_lower_bound = -1;
+static int hf_udvm_upper_bound = -1;
+static int hf_udvm_uncompressed = -1;
+static int hf_udvm_offset = -1;
+static int hf_udvm_start_value = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_sigcomp = -1;
+static gint ett_sigcomp_udvm = -1;
+
+
+/* set the tcp port */
+static guint SigCompUDPPort1 = 5555;
+static guint SigCompUDPPort2 = 6666;
+
+/* Default preference wether to display the bytecode in UDVM operands or not */
+static gboolean display_udvm_bytecode = FALSE;
+/* Default preference wether to dissect the UDVM code or not */
+static gboolean dissect_udvm_code = TRUE;
+
+/* Value strings */
+static const value_string length_encoding_vals[] = {
+ { 0x00, "No partial state(Message type 2)" },
+ { 0x01, "6 bytes)" },
+ { 0x02, "9 bytes)" },
+ { 0x03, "12 bytes)" },
+ { 0, NULL }
+};
+
+
+static const value_string destination_address_encoding_vals[] = {
+ { 0x00, "Reserved" },
+ { 0x01, "128" },
+ { 0x02, "192" },
+ { 0x03, "256" },
+ { 0x04, "320" },
+ { 0x05, "384" },
+ { 0x06, "448" },
+ { 0x07, "512" },
+ { 0x08, "576" },
+ { 0x09, "640" },
+ { 0x0a, "704" },
+ { 0x0b, "768" },
+ { 0x0c, "832" },
+ { 0x0d, "896" },
+ { 0x0e, "960" },
+ { 0x0F, "1024" },
+ { 0, NULL }
+};
+
+static const value_string udvm_instruction_code_vals[] = {
+ { 0, "DECOMPRESSION-FAILURE" },
+ { 1, "AND" },
+ { 2, "OR" },
+ { 3, "NOT" },
+ { 4, "LSHIFT" },
+ { 5, "RSHIFT" },
+ { 6, "ADD" },
+ { 7, "SUBTRACT" },
+ { 8, "MULTIPLY" },
+ { 9, "DIVIDE" },
+ { 10, "REMAINDER" },
+ { 11, "SORT-ASCENDING" },
+ { 12, "SORT-DESCENDING" },
+ { 13, "SHA-1" },
+ { 14, "LOAD" },
+ { 15, "MULTILOAD" },
+ { 16, "PUSH" },
+ { 17, "POP" },
+ { 18, "COPY" },
+ { 19, "COPY-LITERAL" },
+ { 20, "COPY-OFFSET" },
+ { 21, "MEMSET" },
+ { 22, "JUMP" },
+ { 23, "COMPARE" },
+ { 24, "CALL" },
+ { 25, "RETURN" },
+ { 26, "SWITCH" },
+ { 27, "CRC" },
+ { 28, "INPUT-BYTES" },
+ { 29, "INPUT-BITS" },
+ { 30, "INPUT-HUFFMAN" },
+ { 31, "STATE-ACCESS" },
+ { 32, "STATE-CREATE" },
+ { 33, "STATE-FREE" },
+ { 34, "OUTPUT" },
+ { 35, "END-MESSAGE" },
+ { 0, NULL }
+};
+ /* RFC3320
+ * Figure 10: Bytecode for a multitype (%) operand
+ * Bytecode: Operand value: Range: HEX val
+ * 00nnnnnn N 0 - 63 0x00
+ * 01nnnnnn memory[2 * N] 0 - 65535 0x40
+ * 1000011n 2 ^ (N + 6) 64 , 128 0x86
+ * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
+ * 111nnnnn N + 65504 65504 - 65535 0xe0
+ * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
+ * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
+ * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
+ * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
+ * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
+ */
+
+static const value_string display_bytecode_vals[] = {
+ { 0x00, "00nnnnnn, N, 0 - 63" },
+ { 0x40, "01nnnnnn, memory[2 * N],0 - 65535" },
+ { 0x86, "1000011n, 2 ^ (N + 6), 64 , 128" },
+ { 0x88, "10001nnn, 2 ^ (N + 8), 256,..., 32768" },
+ { 0xe0, "111nnnnn N + 65504, 65504 - 65535" },
+ { 0x90, "1001nnnn nnnnnnnn, N + 61440, 61440 - 65535" },
+ { 0xa0, "101nnnnn nnnnnnnn, N, 0 - 8191" },
+ { 0xc0, "110nnnnn nnnnnnnn, memory[N], 0 - 65535" },
+ { 0x80, "10000000 nnnnnnnn nnnnnnnn, N, 0 - 65535" },
+ { 0x81, "10000001 nnnnnnnn nnnnnnnn, memory[N], 0 - 65535" },
+ { 0, NULL }
+};
+/* RFC3320
+ * 0nnnnnnn memory[2 * N] 0 - 65535
+ * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
+ * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
+ */
+static const value_string display_ref_bytecode_vals[] = {
+ { 0x00, "0nnnnnnn memory[2 * N] 0 - 65535" },
+ { 0x80, "10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535" },
+ { 0xc0, "11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535" },
+ { 0, NULL }
+};
+ /* The simplest operand type is the literal (#), which encodes a
+ * constant integer from 0 to 65535 inclusive. A literal operand may
+ * require between 1 and 3 bytes depending on its value.
+ * Bytecode: Operand value: Range:
+ * 0nnnnnnn N 0 - 127
+ * 10nnnnnn nnnnnnnn N 0 - 16383
+ * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
+ *
+ * Figure 8: Bytecode for a literal (#) operand
+ *
+ */
+
+static const value_string display_lit_bytecode_vals[] = {
+ { 0x00, "0nnnnnnn N 0 - 127" },
+ { 0x80, "10nnnnnn nnnnnnnn N 0 - 16383" },
+ { 0xc0, "11000000 nnnnnnnn nnnnnnnn N 0 - 65535" },
+ { 0, NULL }
+};
+
+static void dissect_udvm_bytecode(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree, guint destination);
+
+static int dissect_udvm_multitype_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree,
+ gint offset,gboolean is_addr,gint *start_offset,
+ guint16 *value, gboolean *is_memory_address );
+
+static int dissect_udvm_literal_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree,
+ gint offset, gint *start_offset, guint16 *value);
+
+static int dissect_udvm_reference_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree,
+ gint offset, gint *start_offset, guint16 *value);
+
+
+/* Code to actually dissect the packets */
+static int
+dissect_sigcomp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ tvbuff_t *udvm_tvb;
+ proto_item *ti, *udvm_item;
+ proto_tree *sigcomp_tree, *sigcomp_udvm_tree;
+ gint offset = 0;
+ gint partial_state_len;
+ guint octet;
+ guint8 returned_feedback_field[128];
+ guint8 partial_state[9];
+ guint tbit;
+ guint16 len = 0;
+ guint destination;
+/* Is this a SigComp message or not ? */
+ octet = tvb_get_guint8(tvb, offset);
+ if ((octet & 0xf8) != 0xf8)
+ return 0;
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIGCOMP");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+
+
+
+/* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_sigcomp, tvb, 0, -1, FALSE);
+ sigcomp_tree = proto_item_add_subtree(ti, ett_sigcomp);
+
+/* add an item to the subtree, see section 1.6 for more information */
+ octet = tvb_get_guint8(tvb, offset);
+
+/* A SigComp message takes one of two forms depending on whether it
+ * accesses a state item at the receiving endpoint. The two variants of
+ * a SigComp message are given in Figure 3. (The T-bit controls the
+ * format of the returned feedback item and is defined in Section 7.1.)
+ *
+ * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * | 1 1 1 1 1 | T | len | | 1 1 1 1 1 | T | 0 |
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * | | | |
+ * : returned feedback item : : returned feedback item :
+ * | | | |
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * | | | code_len |
+ * : partial state identifier : +---+---+---+---+---+---+---+---+
+ *
+ * | | | code_len | destination |
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * | | | |
+ * : remaining SigComp message : : uploaded UDVM bytecode :
+ * | | | |
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * | |
+ * : remaining SigComp message :
+ * | |
+ * +---+---+---+---+---+---+---+---+
+ *
+ */
+
+ proto_tree_add_item(sigcomp_tree,hf_sigcomp_t_bit, tvb, offset, 1, FALSE);
+ proto_tree_add_item(sigcomp_tree,hf_sigcomp_len, tvb, offset, 1, FALSE);
+ tbit = ( octet & 0x04)>>2;
+ partial_state_len = octet & 0x03;
+ offset ++;
+ if ( partial_state_len != 0 ){
+ /*
+ * The len field encodes the number of transmitted bytes as follows:
+ *
+ * Encoding: Length of partial state identifier
+ *
+ * 01 6 bytes
+ * 10 9 bytes
+ * 11 12 bytes
+ *
+ */
+ partial_state_len = partial_state_len * 3 + 3;
+
+ /*
+ * Message format 1
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Msg format 1");
+
+ if ( tbit == 1 ) {
+ /*
+ * Returned feedback item exists
+ */
+ len = 1;
+ octet = tvb_get_guint8(tvb, offset);
+ /* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * | 0 | returned_feedback_field | | 1 | returned_feedback_length |
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * | |
+ * : returned_feedback_field :
+ * | |
+ * +---+---+---+---+---+---+---+---+
+ * Figure 4: Format of returned feedback item
+ */
+
+ if ( (octet & 0x80) != 0 ){
+ len = octet & 0x7f;
+ proto_tree_add_uint(sigcomp_tree,hf_sigcomp_returned_feedback_item_len,
+ tvb, offset, 1, len);
+ offset ++;
+ tvb_memcpy(tvb,returned_feedback_field,offset, len);
+ } else {
+ returned_feedback_field[0] = tvb_get_guint8(tvb, offset) & 0x7f;
+ }
+ proto_tree_add_bytes(sigcomp_tree,hf_sigcomp_returned_feedback_item,
+ tvb, offset, len, returned_feedback_field);
+ offset = offset + len;
+ tvb_memcpy(tvb, partial_state, offset, partial_state_len);
+ proto_tree_add_bytes(sigcomp_tree,hf_sigcomp_partial_state,
+ tvb, offset, partial_state_len, partial_state);
+ offset = offset + partial_state_len;
+ proto_tree_add_text(sigcomp_tree, tvb, offset, -1, "Remaining SigComp message %u bytes",
+ tvb_reported_length_remaining(tvb, offset));
+ }
+
+ }
+ else{
+ /*
+ * Message format 2
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Msg format 2");
+ if ( tbit == 1 ) {
+ /*
+ * Returned feedback item exists
+ */
+ len = 1;
+ octet = tvb_get_guint8(tvb, offset);
+ if ( (octet & 0x80) != 0 ){
+ len = octet & 0x7f;
+ proto_tree_add_uint(sigcomp_tree,hf_sigcomp_returned_feedback_item_len,
+ tvb, offset, 1, len);
+ offset ++;
+ }
+ tvb_memcpy(tvb,returned_feedback_field,offset, len);
+ proto_tree_add_bytes(sigcomp_tree,hf_sigcomp_returned_feedback_item,
+ tvb, offset, 1, returned_feedback_field);
+ offset = offset + len;
+ }
+ len = tvb_get_ntohs(tvb, offset) >> 4;
+ octet = tvb_get_guint8(tvb, (offset + 1));
+ destination = (octet & 0x0f);
+ if ( destination != 0 )
+ destination = 64 + ( destination * 64 );
+ proto_tree_add_uint(sigcomp_tree,hf_sigcomp_code_len, tvb, offset, 2, len);
+ proto_tree_add_item(sigcomp_tree,hf_sigcomp_destination, tvb, (offset+ 1), 1, FALSE);
+ offset = offset +2;
+
+ udvm_item = proto_tree_add_text(sigcomp_tree, tvb, offset, len,
+ "Uploaded UDVM bytecode %u (0x%x) bytes", len, len);
+ sigcomp_udvm_tree = proto_item_add_subtree( udvm_item, ett_sigcomp_udvm);
+
+ udvm_tvb = tvb_new_subset(tvb, offset, len, len);
+ if ( dissect_udvm_code )
+ dissect_udvm_bytecode(udvm_tvb, sigcomp_udvm_tree, destination);
+ offset = offset + len;
+
+ proto_tree_add_text(sigcomp_tree, tvb, offset, -1, "Remaining SigComp message %u bytes",
+ tvb_reported_length_remaining(tvb, offset));
+ }
+ return tvb_length(tvb);
+}
+
+
+
+/* Continue adding tree items to process the packet here */
+/* If this protocol has a sub-dissector call it here, see section 1.8 */
+
+#define SIGCOMP_INSTR_DECOMPRESSION_FAILURE 0
+#define SIGCOMP_INSTR_AND 1
+#define SIGCOMP_INSTR_OR 2
+#define SIGCOMP_INSTR_NOT 3
+#define SIGCOMP_INSTR_LSHIFT 4
+#define SIGCOMP_INSTR_RSHIFT 5
+#define SIGCOMP_INSTR_ADD 6
+#define SIGCOMP_INSTR_SUBTRACT 7
+#define SIGCOMP_INSTR_MULTIPLY 8
+#define SIGCOMP_INSTR_DIVIDE 9
+#define SIGCOMP_INSTR_REMAINDER 10
+#define SIGCOMP_INSTR_SORT_ASCENDING 11
+#define SIGCOMP_INSTR_SORT_DESCENDING 12
+#define SIGCOMP_INSTR_SHA_1 13
+#define SIGCOMP_INSTR_LOAD 14
+#define SIGCOMP_INSTR_MULTILOAD 15
+#define SIGCOMP_INSTR_PUSH 16
+#define SIGCOMP_INSTR_POP 17
+#define SIGCOMP_INSTR_COPY 18
+#define SIGCOMP_INSTR_COPY_LITERAL 19
+#define SIGCOMP_INSTR_COPY_OFFSET 20
+#define SIGCOMP_INSTR_MEMSET 21
+#define SIGCOMP_INSTR_JUMP 22
+#define SIGCOMP_INSTR_COMPARE 23
+#define SIGCOMP_INSTR_CALL 24
+#define SIGCOMP_INSTR_RETURN 25
+#define SIGCOMP_INSTR_SWITCH 26
+#define SIGCOMP_INSTR_CRC 27
+#define SIGCOMP_INSTR_INPUT_BYTES 28
+#define SIGCOMP_INSTR_INPUT_BITS 29
+#define SIGCOMP_INSTR_INPUT_HUFFMAN 30
+#define SIGCOMP_INSTR_STATE_ACCESS 31
+#define SIGCOMP_INSTR_STATE_CREATE 32
+#define SIGCOMP_INSTR_STATE_FREE 33
+#define SIGCOMP_INSTR_OUTPUT 34
+#define SIGCOMP_INSTR_END_MESSAGE 35
+
+
+static void
+dissect_udvm_bytecode(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree,guint start_address)
+{
+ guint instruction;
+ gint offset = 0;
+ gint start_offset;
+ gint len;
+ gint n;
+ guint instruction_no = 0;
+ guint16 value = 0;
+ proto_item *item, *item2;
+ guint UDVM_address = start_address;
+ gboolean is_memory_address;
+
+
+ while (tvb_reported_length_remaining(udvm_tvb, offset) > 0) {
+ instruction = tvb_get_guint8(udvm_tvb, offset);
+ instruction_no ++;
+ UDVM_address = start_address + offset;
+;
+
+ item = proto_tree_add_text(sigcomp_udvm_tree, udvm_tvb, offset, 1,
+ "######### UDVM instruction %u at UDVM-address %u (0x%x) #########",
+ instruction_no,UDVM_address,UDVM_address);
+ PROTO_ITEM_SET_GENERATED(item);
+ proto_tree_add_item(sigcomp_udvm_tree, hf_sigcomp_udvm_instr, udvm_tvb, offset, 1, FALSE);
+ offset ++;
+ switch ( instruction ) {
+
+ case SIGCOMP_INSTR_AND: /* 1 AND ($operand_1, %operand_2) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ /* %operand_2*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_OR: /* 2 OR ($operand_1, %operand_2) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ /* %operand_2*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_NOT: /* 3 NOT ($operand_1) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ break;
+
+ case SIGCOMP_INSTR_LSHIFT: /* 4 LSHIFT ($operand_1, %operand_2) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ /* %operand_2*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_RSHIFT: /* 5 RSHIFT ($operand_1, %operand_2) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ /* %operand_2*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_ADD: /* 6 ADD ($operand_1, %operand_2) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ /* %operand_2*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_SUBTRACT: /* 7 SUBTRACT ($operand_1, %operand_2) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ /* %operand_2*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_MULTIPLY: /* 8 MULTIPLY ($operand_1, %operand_2) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ /* %operand_2*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_DIVIDE: /* 9 DIVIDE ($operand_1, %operand_2) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ /* %operand_2*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_REMAINDER: /* 10 REMAINDER ($operand_1, %operand_2) */
+ /* $operand_1*/
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_1,
+ udvm_tvb, start_offset, len, value);
+ /* %operand_2*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_operand_2,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+ case SIGCOMP_INSTR_SORT_ASCENDING: /* 11 SORT-ASCENDING (%start, %n, %k) */
+ /* while programming stop while loop */
+ offset = offset + tvb_reported_length_remaining(udvm_tvb, offset);
+ break;
+
+ case SIGCOMP_INSTR_SORT_DESCENDING: /* 12 SORT-DESCENDING (%start, %n, %k) */
+ /* while programming stop while loop */
+ offset = offset + tvb_reported_length_remaining(udvm_tvb, offset);
+ break;
+ case SIGCOMP_INSTR_SHA_1: /* 13 SHA-1 (%position, %length, %destination) */
+ /* %position */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position,
+ udvm_tvb, start_offset, len, value);
+
+ /* %length, */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length,
+ udvm_tvb, start_offset, len, value);
+
+ /* $destination */
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest,
+ udvm_tvb, start_offset, len, value);
+ break;
+
+ case SIGCOMP_INSTR_LOAD: /* 14 LOAD (%address, %value) */
+ /* %address */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address,
+ udvm_tvb, start_offset, len, value);
+ /* %value */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_MULTILOAD: /* 15 MULTILOAD (%address, #n, %value_0, ..., %value_n-1) */
+ /* %address */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address,
+ udvm_tvb, start_offset, len, value);
+ /* #n */
+ offset = dissect_udvm_literal_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_num,
+ udvm_tvb, start_offset, len, value);
+ n = value;
+ while ( n > 0) {
+ n = n -1;
+ /* %value */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value,
+ udvm_tvb, start_offset, len, value);
+ }
+ }
+ break;
+
+ case SIGCOMP_INSTR_PUSH: /* 16 PUSH (%value) */
+ /* %value */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_POP: /* 17 POP (%address) */
+ /* %address */ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address,
+ udvm_tvb, start_offset, len, value);
+ break;
+
+ case SIGCOMP_INSTR_COPY: /* 18 COPY (%position, %length, %destination) */
+ /* %position */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position,
+ udvm_tvb, start_offset, len, value);
+
+ /* %length, */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length,
+ udvm_tvb, start_offset, len, value);
+
+ /* $destination */
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest,
+ udvm_tvb, start_offset, len, value);
+ break;
+
+ case SIGCOMP_INSTR_COPY_LITERAL: /* 19 COPY-LITERAL (%position, %length, $destination) */
+ /* %position */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position,
+ udvm_tvb, start_offset, len, value);
+
+ /* %length, */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length,
+ udvm_tvb, start_offset, len, value);
+
+ /* $destination */
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest,
+ udvm_tvb, start_offset, len, value);
+ break;
+
+ case SIGCOMP_INSTR_COPY_OFFSET: /* 20 COPY-OFFSET (%offset, %length, $destination) */
+ /* %offset */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_offset,
+ udvm_tvb, start_offset, len, value);
+
+ /* %length, */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length,
+ udvm_tvb, start_offset, len, value);
+
+ /* $destination */
+ offset = dissect_udvm_reference_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ref_dest,
+ udvm_tvb, start_offset, len, value);
+ break;
+ case SIGCOMP_INSTR_MEMSET: /* 21 MEMSET (%address, %length, %start_value, %offset) */
+
+ /* %address */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_address,
+ udvm_tvb, start_offset, len, value);
+
+ /* %length, */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length,
+ udvm_tvb, start_offset, len, value);
+
+ /* %start_value */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_start_value,
+ udvm_tvb, start_offset, len, value);
+
+ /* %offset */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_offset,
+ udvm_tvb, start_offset, len, value);
+ break;
+
+
+ case SIGCOMP_INSTR_JUMP: /* 22 JUMP (@address) */
+ /* @address */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+ break;
+
+ case SIGCOMP_INSTR_COMPARE: /* 23 */
+ /* COMPARE (%value_1, %value_2, @address_1, @address_2, @address_3)
+ */
+ /* %value_1 */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value,
+ udvm_tvb, start_offset, len, value);
+ }
+
+ /* %value_2 */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value,
+ udvm_tvb, start_offset, len, value);
+ }
+
+ /* @address_1 */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+
+ /* @address_2 */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+
+ /* @address_3 */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+ break;
+
+ case SIGCOMP_INSTR_CALL: /* 24 CALL (@address) (PUSH addr )*/
+ /* @address */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+ break;
+ case SIGCOMP_INSTR_RETURN: /* 25 POP and return */
+ break;
+
+ case SIGCOMP_INSTR_SWITCH: /* 26 SWITCH (#n, %j, @address_0, @address_1, ... , @address_n-1) */
+ /* #n */
+ offset = dissect_udvm_literal_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_num,
+ udvm_tvb, start_offset, len, value);
+
+ /* Number of addresses in the instruction */
+ n = value;
+ /* %j */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value,
+ udvm_tvb, start_offset, len, value);
+ }
+
+ while ( n > 0) {
+ n = n -1;
+ /* @address_n-1 */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+ case SIGCOMP_INSTR_CRC: /* 27 CRC (%value, %position, %length, @address) */
+ /* %value */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ){
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_addr_value,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_value,
+ udvm_tvb, start_offset, len, value);
+ }
+
+ /* %position */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_position,
+ udvm_tvb, start_offset, len, value);
+
+ /* %length */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length,
+ udvm_tvb, start_offset, len, value);
+
+ /* @address */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+ break;
+
+
+ case SIGCOMP_INSTR_INPUT_BYTES: /* 28 INPUT-BYTES (%length, %destination, @address) */
+ /* %length */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length,
+ udvm_tvb, start_offset, len, value);
+
+ /* %destination */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_destination,
+ udvm_tvb, start_offset, len, value);
+
+ /* @address */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+ break;
+ case SIGCOMP_INSTR_INPUT_BITS:/* 29 INPUT-BITS (%length, %destination, @address) */
+ /* %length */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_length,
+ udvm_tvb, start_offset, len, value);
+
+ /* %destination */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_destination,
+ udvm_tvb, start_offset, len, value);
+
+ /* @address */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+ break;
+ case SIGCOMP_INSTR_INPUT_HUFFMAN: /* 30 */
+ /*
+ * INPUT-HUFFMAN (%destination, @address, #n, %bits_1, %lower_bound_1,
+ * %upper_bound_1, %uncompressed_1, ... , %bits_n, %lower_bound_n,
+ * %upper_bound_n, %uncompressed_n)
+ */
+ /* %destination */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_destination,
+ udvm_tvb, start_offset, len, value);
+
+ /* @address */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ /* operand_value = (memory_address_of_instruction + D) modulo 2^16 */
+ value = ( value + UDVM_address ) & 0xffff;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_at_address,
+ udvm_tvb, start_offset, len, value);
+ /* #n */
+ offset = dissect_udvm_literal_operand(udvm_tvb, sigcomp_udvm_tree, offset, &start_offset, &value);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_num,
+ udvm_tvb, start_offset, len, value);
+ n = value;
+ while ( n > 0) {
+ n = n -1;
+ /* %bits_n */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_bits,
+ udvm_tvb, start_offset, len, value);
+ /* %lower_bound_n*/
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_lower_bound,
+ udvm_tvb, start_offset, len, value);
+ /* %upper_bound_n */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_upper_bound,
+ udvm_tvb, start_offset, len, value);
+ /* %uncompressed_n */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, FALSE,&start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_uncompressed,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+
+ case SIGCOMP_INSTR_STATE_ACCESS: /* 31 */
+ /* STATE-ACCESS (%partial_identifier_start, %partial_identifier_length,
+ * %state_begin, %state_length, %state_address, %state_instruction)
+ */
+
+ /*
+ * %partial_identifier_start
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value ,&is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_start,
+ udvm_tvb, start_offset, len, value);
+
+ /*
+ * %partial_identifier_length
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value ,&is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_length,
+ udvm_tvb, start_offset, len, value);
+ /*
+ * %state_begin
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_state_begin,
+ udvm_tvb, start_offset, len, value);
+
+ /*
+ * %state_length
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ) {
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length,
+ udvm_tvb, start_offset, len, value);
+ }
+ /*
+ * %state_address
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value ,&is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ) {
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address,
+ udvm_tvb, start_offset, len, value);
+ }
+ /*
+ * %state_instruction
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_instr,
+ udvm_tvb, start_offset, len, value);
+ break;
+ case SIGCOMP_INSTR_STATE_CREATE: /* 32 */
+ /*
+ * STATE-CREATE (%state_length, %state_address, %state_instruction,
+ * %minimum_access_length, %state_retention_priority)
+ */
+
+ /*
+ * %state_length
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ) {
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length,
+ udvm_tvb, start_offset, len, value);
+ }
+ /*
+ * %state_address
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ) {
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address,
+ udvm_tvb, start_offset, len, value);
+ }
+ /*
+ * %state_instruction
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_instr,
+ udvm_tvb, start_offset, len, value);
+ /*
+ * %minimum_access_length
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_min_acc_len,
+ udvm_tvb, start_offset, len, value);
+ /*
+ * %state_retention_priority
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_ret_pri,
+ udvm_tvb, start_offset, len, value);
+
+ break;
+ case SIGCOMP_INSTR_STATE_FREE: /* 33 */
+ /*
+ * STATE-FREE (%partial_identifier_start, %partial_identifier_length)
+ */
+ /*
+ * %partial_identifier_start
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_start,
+ udvm_tvb, start_offset, len, value);
+
+ /*
+ * %partial_identifier_length
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_partial_identifier_length,
+ udvm_tvb, start_offset, len, value);
+ break;
+ case SIGCOMP_INSTR_OUTPUT: /* 34 OUTPUT (%output_start, %output_length) */
+ /*
+ * %output_start
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ) {
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_start,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_start,
+ udvm_tvb, start_offset, len, value);
+ }
+ /*
+ * %output_length
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ) {
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_length_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_output_length,
+ udvm_tvb, start_offset, len, value);
+ }
+ break;
+ case SIGCOMP_INSTR_END_MESSAGE: /* 35 */
+ /*
+ * END-MESSAGE (%requested_feedback_location,
+ * %returned_parameters_location, %state_length, %state_address,
+ * %state_instruction, %minimum_access_length,
+ * %state_retention_priority)
+ */
+ /* %requested_feedback_location */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_req_feedback_loc,
+ udvm_tvb, start_offset, len, value);
+ /* returned_parameters_location */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_ret_param_loc,
+ udvm_tvb, start_offset, len, value);
+ /*
+ * %state_length
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ) {
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_length,
+ udvm_tvb, start_offset, len, value);
+ }
+ /*
+ * %state_address
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ if ( is_memory_address ) {
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address_addr,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_address,
+ udvm_tvb, start_offset, len, value);
+ }
+ /*
+ * %state_instruction
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_instr,
+ udvm_tvb, start_offset, len, value);
+ /*
+ * %minimum_access_length
+ */
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_min_acc_len,
+ udvm_tvb, start_offset, len, value);
+ /*
+ * %state_retention_priority
+ */
+ if ( tvb_reported_length_remaining(udvm_tvb, offset) != 0 ){
+ offset = dissect_udvm_multitype_operand(udvm_tvb, sigcomp_udvm_tree, offset, TRUE, &start_offset, &value, &is_memory_address);
+ len = offset - start_offset;
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_state_ret_pri,
+ udvm_tvb, start_offset, len, value);
+ }else{
+ item2 = proto_tree_add_text(sigcomp_udvm_tree, udvm_tvb, offset, 1,
+ "state_retention_priority = 0(Not in the uploaded code as UDVM buffer initalized to Zero");
+ PROTO_ITEM_SET_GENERATED(item2);
+ }
+ if ( tvb_reported_length_remaining(udvm_tvb, offset) != 0 ){
+ len = tvb_reported_length_remaining(udvm_tvb, offset);
+ UDVM_address = start_address + offset;
+ proto_tree_add_text(sigcomp_udvm_tree, udvm_tvb, offset, len,
+ "Remaning %u bytes starting at UDVM addr %u (0x%x)- State information ?",len, UDVM_address, UDVM_address);
+ }
+ offset = offset + tvb_reported_length_remaining(udvm_tvb, offset);
+ break;
+
+ default:
+ /* while programming stop while loop */
+ offset = offset + tvb_reported_length_remaining(udvm_tvb, offset);
+ break;
+ }
+
+
+ }
+ return;
+}
+ /* The simplest operand type is the literal (#), which encodes a
+ * constant integer from 0 to 65535 inclusive. A literal operand may
+ * require between 1 and 3 bytes depending on its value.
+ * Bytecode: Operand value: Range:
+ * 0nnnnnnn N 0 - 127
+ * 10nnnnnn nnnnnnnn N 0 - 16383
+ * 11000000 nnnnnnnn nnnnnnnn N 0 - 65535
+ *
+ * Figure 8: Bytecode for a literal (#) operand
+ *
+ */
+static int
+dissect_udvm_literal_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree,
+ gint offset, gint *start_offset, guint16 *value)
+{
+ guint bytecode;
+ guint16 operand;
+ guint test_bits;
+ guint display_bytecode;
+
+ bytecode = tvb_get_guint8(udvm_tvb, offset);
+ test_bits = bytecode >> 7;
+ if (test_bits == 1){
+ test_bits = bytecode >> 6;
+ if (test_bits == 2){
+ /*
+ * 10nnnnnn nnnnnnnn N 0 - 16383
+ */
+ display_bytecode = bytecode & 0xc0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = tvb_get_ntohs(udvm_tvb, offset) & 0x3fff;
+ *value = operand;
+ *start_offset = offset;
+ offset = offset + 2;
+
+ }else{
+ /*
+ * 111000000 nnnnnnnn nnnnnnnn N 0 - 65535
+ */
+ display_bytecode = bytecode & 0xc0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ offset ++;
+ operand = tvb_get_ntohs(udvm_tvb, offset);
+ *value = operand;
+ *start_offset = offset;
+ offset = offset + 2;
+
+ }
+ }else{
+ /*
+ * 0nnnnnnn N 0 - 127
+ */
+ display_bytecode = bytecode & 0xc0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_literal_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = ( bytecode & 0x7f);
+ *value = operand;
+ *start_offset = offset;
+ offset ++;
+ }
+
+ return offset;
+
+}
+/*
+ * The second operand type is the reference ($), which is always used to
+ * access a 2-byte value located elsewhere in the UDVM memory. The
+ * bytecode for a reference operand is decoded to be a constant integer
+ * from 0 to 65535 inclusive, which is interpreted as the memory address
+ * containing the actual value of the operand.
+ * Bytecode: Operand value: Range:
+ *
+ * 0nnnnnnn memory[2 * N] 0 - 65535
+ * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
+ * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
+ *
+ * Figure 9: Bytecode for a reference ($) operand
+ */
+static int
+dissect_udvm_reference_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree,
+ gint offset, gint *start_offset, guint16 *value)
+{
+ guint bytecode;
+ guint16 operand;
+ guint test_bits;
+ guint display_bytecode;
+
+ bytecode = tvb_get_guint8(udvm_tvb, offset);
+ test_bits = bytecode >> 7;
+ if (test_bits == 1){
+ test_bits = bytecode >> 6;
+ if (test_bits == 2){
+ /*
+ * 10nnnnnn nnnnnnnn memory[2 * N] 0 - 65535
+ */
+ display_bytecode = bytecode & 0xc0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_reference_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = tvb_get_ntohs(udvm_tvb, offset) & 0x3fff;
+ *value = (operand * 2);
+ *start_offset = offset;
+ offset = offset + 2;
+
+ }else{
+ /*
+ * 11000000 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
+ */
+ display_bytecode = bytecode & 0xc0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_reference_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ offset ++;
+ operand = tvb_get_ntohs(udvm_tvb, offset);
+ *value = operand;
+ *start_offset = offset;
+ offset = offset + 2;
+
+ }
+ }else{
+ /*
+ * 0nnnnnnn memory[2 * N] 0 - 65535
+ */
+ display_bytecode = bytecode & 0xc0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_reference_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = ( bytecode & 0x3f);
+ *value = (operand * 2);
+ *start_offset = offset;
+ offset ++;
+ }
+
+ return offset;
+}
+
+/*
+ *The fourth operand type is the address (@). This operand is decoded
+ * as a multitype operand followed by a further step: the memory address
+ * of the UDVM instruction containing the address operand is added to
+ * obtain the correct operand value. So if the operand value from
+ * Figure 10 is D then the actual operand value of an address is
+ * calculated as follows:
+ *
+ * operand_value = (is_memory_address_of_instruction + D) modulo 2^16
+ * TODO calculate correct value for operand in case of ADDR
+ */
+static int
+dissect_udvm_multitype_operand(tvbuff_t *udvm_tvb, proto_tree *sigcomp_udvm_tree,
+ gint offset, gboolean is_addr, gint *start_offset, guint16 *value, gboolean *is_memory_address )
+{
+ guint bytecode;
+ guint display_bytecode;
+ guint16 operand;
+ guint32 result;
+ guint test_bits;
+ /* RFC3320
+ * Figure 10: Bytecode for a multitype (%) operand
+ * Bytecode: Operand value: Range: HEX val
+ * 00nnnnnn N 0 - 63 0x00
+ * 01nnnnnn memory[2 * N] 0 - 65535 0x40
+ * 1000011n 2 ^ (N + 6) 64 , 128 0x86
+ * 10001nnn 2 ^ (N + 8) 256 , ... , 32768 0x88
+ * 111nnnnn N + 65504 65504 - 65535 0xe0
+ * 1001nnnn nnnnnnnn N + 61440 61440 - 65535 0x90
+ * 101nnnnn nnnnnnnn N 0 - 8191 0xa0
+ * 110nnnnn nnnnnnnn memory[N] 0 - 65535 0xc0
+ * 10000000 nnnnnnnn nnnnnnnn N 0 - 65535 0x80
+ * 10000001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535 0x81
+ */
+ *is_memory_address = FALSE;
+ bytecode = tvb_get_guint8(udvm_tvb, offset);
+ test_bits = ( bytecode & 0xc0 ) >> 6;
+ switch (test_bits ){
+ case 0:
+ /*
+ * 00nnnnnn N 0 - 63
+ */
+ display_bytecode = bytecode & 0xc0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = ( bytecode & 0x3f);
+ *value = operand;
+ *start_offset = offset;
+ offset ++;
+ break;
+ case 1:
+ /*
+ * 01nnnnnn memory[2 * N] 0 - 65535
+ */
+ display_bytecode = bytecode & 0xc0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = ( bytecode & 0x3f) * 2;
+ *is_memory_address = TRUE;
+ *value = operand;
+ *start_offset = offset;
+ offset ++;
+ break;
+ case 2:
+ /* Check tree most significant bits */
+ test_bits = ( bytecode & 0xe0 ) >> 5;
+ if ( test_bits == 5 ){
+ /*
+ * 101nnnnn nnnnnnnn N 0 - 8191
+ */
+ display_bytecode = bytecode & 0xe0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = tvb_get_ntohs(udvm_tvb, offset) & 0x1fff;
+ *value = operand;
+ *start_offset = offset;
+ offset = offset + 2;
+ }else{
+ test_bits = ( bytecode & 0xf0 ) >> 4;
+ if ( test_bits == 9 ){
+ /*
+ * 1001nnnn nnnnnnnn N + 61440 61440 - 65535
+ */
+ display_bytecode = bytecode & 0xf0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = (tvb_get_ntohs(udvm_tvb, offset) & 0x0fff) + 61440;
+ *start_offset = offset;
+ *value = operand;
+ offset = offset + 2;
+ }else{
+ test_bits = ( bytecode & 0x08 ) >> 3;
+ if ( test_bits == 1){
+ /*
+ * 10001nnn 2 ^ (N + 8) 256 , ... , 32768
+ */
+ display_bytecode = bytecode & 0xf8;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ result = (guint32)pow(2,( bytecode & 0x07) + 8);
+ operand = result & 0xffff;
+ *start_offset = offset;
+ *value = operand;
+ offset ++;
+ }else{
+ test_bits = ( bytecode & 0x0e ) >> 1;
+ if ( test_bits == 3 ){
+ /*
+ * 1000 011n 2 ^ (N + 6) 64 , 128
+ */
+ display_bytecode = bytecode & 0xfe;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ result = (guint32)pow(2,( bytecode & 0x01) + 6);
+ operand = result & 0xffff;
+ *start_offset = offset;
+ *value = operand;
+ offset ++;
+ }else{
+ /*
+ * 1000 0000 nnnnnnnn nnnnnnnn N 0 - 65535
+ * 1000 0001 nnnnnnnn nnnnnnnn memory[N] 0 - 65535
+ */
+ display_bytecode = bytecode;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ if ( (bytecode & 0x01) == 1 )
+ *is_memory_address = TRUE;
+ offset ++;
+ operand = tvb_get_ntohs(udvm_tvb, offset);
+ *value = operand;
+ *start_offset = offset;
+ offset = offset +2;
+ }
+
+
+ }
+ }
+ }
+ break;
+
+ case 3:
+ test_bits = ( bytecode & 0x20 ) >> 5;
+ if ( test_bits == 1 ){
+ /*
+ * 111nnnnn N + 65504 65504 - 65535
+ */
+ display_bytecode = bytecode & 0xe0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = ( bytecode & 0x1f) + 65504;
+ *start_offset = offset;
+ *value = operand;
+ offset ++;
+ }else{
+ /*
+ * 110nnnnn nnnnnnnn memory[N] 0 - 65535
+ */
+ display_bytecode = bytecode & 0xe0;
+ if ( display_udvm_bytecode )
+ proto_tree_add_uint(sigcomp_udvm_tree, hf_udvm_multitype_bytecode,
+ udvm_tvb, offset, 1, display_bytecode);
+ operand = (tvb_get_ntohs(udvm_tvb, offset) & 0x1fff);
+ *is_memory_address = TRUE;
+ *start_offset = offset;
+ *value = operand;
+ offset = offset +2;
+ }
+
+ default :
+ break;
+ }
+ return offset;
+}
+/* Register the protocol with Ethereal */
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_sigcomp(void)
+{
+ static dissector_handle_t sigcomp_handle;
+ static int Initialized=FALSE;
+ static int udp_port1 = 5555;
+ static int udp_port2 = 6666;
+
+ if (!Initialized) {
+ sigcomp_handle = new_create_dissector_handle(dissect_sigcomp,
+ proto_sigcomp);
+ Initialized=TRUE;
+ }else{
+ dissector_delete("udp.port", udp_port1, sigcomp_handle);
+ dissector_delete("udp.port", udp_port2, sigcomp_handle);
+ }
+
+ udp_port1 = SigCompUDPPort1;
+ udp_port2 = SigCompUDPPort2;
+
+
+ dissector_add("udp.port", SigCompUDPPort1, sigcomp_handle);
+ dissector_add("udp.port", SigCompUDPPort2, sigcomp_handle);
+
+
+}
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_sigcomp(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_sigcomp_t_bit,
+ { "T bit", "sigcomp.t.bit",
+ FT_UINT8, BASE_DEC, NULL, 0x04,
+ "Sigcomp T bit", HFILL }
+ },
+ { &hf_sigcomp_len,
+ { "Partial state id. len.","sigcomp.length",
+ FT_UINT8, BASE_HEX, VALS(&length_encoding_vals), 0x03,
+ "Sigcomp length", HFILL }
+ },
+ { &hf_sigcomp_returned_feedback_item,
+ { "Returned_feedback item", "sigcomp.returned.feedback.item",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Returned feedback item", HFILL }
+ },
+ { &hf_sigcomp_partial_state,
+ { "Partial state identifier", "sigcomp.partial.state.identifier",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Partial state identifier", HFILL }
+ },
+ { &hf_sigcomp_returned_feedback_item_len,
+ { "Returned feedback item length", "sigcomp.returned.feedback.item.len",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Returned feedback item length", HFILL }
+ },
+ { &hf_sigcomp_code_len,
+ { "Code length","sigcomp.code.len",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Code length", HFILL }
+ },
+ { &hf_sigcomp_destination,
+ { "Destination","sigcomp.destination",
+ FT_UINT8, BASE_HEX, VALS(&destination_address_encoding_vals), 0xf,
+ "Destination", HFILL }
+ },
+ { &hf_sigcomp_udvm_instr,
+ { "UDVM instruction code","sigcomp.udvm.instr",
+ FT_UINT8, BASE_DEC, VALS(&udvm_instruction_code_vals), 0x0,
+ "UDVM instruction code", HFILL }
+ },
+ { &hf_udvm_multitype_bytecode,
+ { "UDVM bytecode", "sigcomp.udvm.multyt.bytecode",
+ FT_UINT8, BASE_HEX, VALS(&display_bytecode_vals), 0x0,
+ "UDVM bytecode", HFILL }
+ },
+ { &hf_udvm_reference_bytecode,
+ { "UDVM bytecode", "sigcomp.udvm.ref.bytecode",
+ FT_UINT8, BASE_HEX, VALS(&display_ref_bytecode_vals), 0x0,
+ "UDVM bytecode", HFILL }
+ },
+ { &hf_udvm_literal_bytecode,
+ { "UDVM bytecode", "sigcomp.udvm.lit.bytecode",
+ FT_UINT8, BASE_HEX, VALS(&display_lit_bytecode_vals), 0x0,
+ "UDVM bytecode", HFILL }
+ },
+ { &hf_udvm_operand,
+ { "UDVM operand", "sigcomp.udvm.operand",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "UDVM operand", HFILL }
+ },
+ { &hf_udvm_length,
+ { " %Length", "sigcomp.udvm.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length", HFILL }
+ },
+ { &hf_udvm_destination,
+ { " %Destination", "sigcomp.udvm.destination",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Destination", HFILL }
+ },
+ { &hf_udvm_at_address,
+ { " @Address(mem_add_of_inst + D) mod 2^16)", "sigcomp.udvm.at.address",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Address", HFILL }
+ },
+ { &hf_udvm_address,
+ { " %Address", "sigcomp.udvm.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Address", HFILL }
+ },
+ { &hf_udvm_literal_num,
+ { " #n", "sigcomp.udvm.literal-num",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Literal number", HFILL }
+ },
+ { &hf_udvm_value,
+ { " %Value", "sigcomp.udvm.value",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Value", HFILL }
+ },
+ { &hf_udvm_addr_value,
+ { " %Value[memory address]", "sigcomp.udvm.value",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Value", HFILL }
+ },
+ { &hf_partial_identifier_start,
+ { " %Partial identifier start", "sigcomp.udvm.partial.identifier.start",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Partial identifier start", HFILL }
+ },
+ { &hf_partial_identifier_length,
+ { " %Partial identifier length", "sigcomp.udvm.partial.identifier.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Partial identifier length", HFILL }
+ },
+ { &hf_state_begin,
+ { " %State begin", "sigcomp.udvm.state.begin",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "State begin", HFILL }
+ },
+ { &hf_udvm_state_length,
+ { " %State length", "sigcomp.udvm.state.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "State length", HFILL }
+ },
+
+ { &hf_udvm_state_length_addr,
+ { " %State length[memory address]", "sigcomp.udvm.state.length.addr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "State length", HFILL }
+ },
+ { &hf_udvm_state_address,
+ { " %State address", "sigcomp.udvm.start.address",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "State address", HFILL }
+ },
+ { &hf_udvm_state_address_addr,
+ { " %State address[memory address]", "sigcomp.udvm.start.address.addr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "State address", HFILL }
+ },
+ { &hf_udvm_state_instr,
+ { " %State instruction", "sigcomp.udvm.start.instr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "State instruction", HFILL }
+ },
+ { &hf_udvm_operand_1,
+ { " $Operand 1[memory address]", "sigcomp.udvm.operand.1",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Reference $ Operand 1", HFILL }
+ },
+ { &hf_udvm_operand_2,
+ { " %Operand 2", "sigcomp.udvm.operand.2",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operand 2", HFILL }
+ },
+ { &hf_udvm_operand_2_addr,
+ { " %Operand 2[memory address]", "sigcomp.udvm.operand.2.addr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Operand 2", HFILL }
+ },
+ { &hf_udvm_j,
+ { " %j", "sigcomp.udvm.j",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "j", HFILL }
+ },
+ { &hf_udvm_output_start,
+ { " %Output_start", "sigcomp.output.start",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Output start", HFILL }
+ },
+ { &hf_udvm_output_start_addr,
+ { " %Output_start[memory address]", "sigcomp.output.start.addr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Output start", HFILL }
+ },
+ { &hf_udvm_output_length,
+ { " %Output_length", "sigcomp.output.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Output length", HFILL }
+ },
+ { &hf_udvm_output_length_addr,
+ { " %Output_length[memory address]", "sigcomp.output.length.addr",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Output length", HFILL }
+ },
+ { &hf_udvm_req_feedback_loc,
+ { " %Requested feedback location", "sigcomp.req.feedback.loc",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Requested feedback location", HFILL }
+ },
+ { &hf_udvm_min_acc_len,
+ { " %Minimum access length", "sigcomp.min.acc.len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Output length", HFILL }
+ },
+ { &hf_udvm_state_ret_pri,
+ { " %State retention priority", "sigcomp.udvm.state.ret.pri",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Output length", HFILL }
+ },
+ { &hf_udvm_ret_param_loc,
+ { " %Returned parameters location", "sigcomp.ret.param.loc",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Output length", HFILL }
+ },
+ { &hf_udvm_position,
+ { " %Position", "sigcomp.udvm.position",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Position", HFILL }
+ },
+ { &hf_udvm_ref_dest,
+ { " $Destination[memory address]", "sigcomp.udvm.ref.destination",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "(reference)Destination", HFILL }
+ },
+ { &hf_udvm_bits,
+ { " %Bits", "sigcomp.udvm.bits",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Bits", HFILL }
+ },
+ { &hf_udvm_lower_bound,
+ { " %Lower bound", "sigcomp.udvm.lower.bound",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Lower_bound", HFILL }
+ },
+ { &hf_udvm_upper_bound,
+ { " %Upper bound", "sigcomp.udvm.upper.bound",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Upper bound", HFILL }
+ },
+ { &hf_udvm_uncompressed,
+ { " %Uncompressed", "sigcomp.udvm.uncompressed",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Uncompressed", HFILL }
+ },
+ { &hf_udvm_start_value,
+ { " %Start value", "sigcomp.udvm.start.value",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Start value", HFILL }
+ },
+ { &hf_udvm_offset,
+ { " %Offset", "sigcomp.udvm.offset",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Offset", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_sigcomp,
+ &ett_sigcomp_udvm,
+ };
+
+ module_t *sigcomp_module;
+
+/* Register the protocol name and description */
+ proto_sigcomp = proto_register_protocol("Signaling Compression",
+ "SIGCOMP", "sigcomp");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_sigcomp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+/* Register a configuration option for port */
+ sigcomp_module = prefs_register_protocol(proto_sigcomp,
+ proto_reg_handoff_sigcomp);
+
+ prefs_register_uint_preference(sigcomp_module, "udp.port",
+ "Sigcomp UDP Port 1",
+ "Set UDP port 1 for SigComp messages",
+ 10,
+ &SigCompUDPPort1);
+
+ prefs_register_uint_preference(sigcomp_module, "udp.port2",
+ "Sigcomp UDP Port 2",
+ "Set UDP port 2 for SigComp messages",
+ 10,
+ &SigCompUDPPort2);
+ prefs_register_bool_preference(sigcomp_module, "display.udvm.code",
+ "Dissect the UDVM code",
+ "Preference wether to Dissect the UDVM code or not",
+ &dissect_udvm_code);
+
+ prefs_register_bool_preference(sigcomp_module, "display.bytecode",
+ "Display the bytecode of operands",
+ "preference wether to display the bytecode in UDVM operands or not",
+ &display_udvm_bytecode);
+
+
+}
diff --git a/epan/dissectors/packet-sip.c b/epan/dissectors/packet-sip.c
new file mode 100644
index 0000000000..e6eba141cf
--- /dev/null
+++ b/epan/dissectors/packet-sip.c
@@ -0,0 +1,2063 @@
+/* packet-sip.c
+ * Routines for the Session Initiation Protocol (SIP) dissection.
+ * RFCs 3261-3264
+ *
+ * TODO: Pay attention to Content-Type: It might not always be SDP.
+ * Content-Type is fixed, mixed/mode is not handled though.
+ * hf_ display filters for headers of SIP extension RFCs:
+ * Done for RFC 3265, RFC 3262
+ * Use hash table for list of headers
+ * Add sip msg body dissection based on Content-Type for:
+ * SDP, MIME, and other types
+ * Align SIP methods with recent Internet Drafts or RFC
+ * (SIP INFO, rfc2976 - done)
+ * (SIP SUBSCRIBE-NOTIFY - done)
+ * (SIP REFER - done)
+ * check for other
+ *
+ * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
+ * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-cops.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "prefs.h"
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include "packet-sip.h"
+#include "tap.h"
+
+#define TCP_PORT_SIP 5060
+#define UDP_PORT_SIP 5060
+
+static gint sip_tap = -1;
+
+/* Initial size of hash table tracking state of calls */
+#define SIP_INIT_HASH_TABLE_SIZE 50
+
+/* Initialize the protocol and registered fields */
+static gint proto_sip = -1;
+static gint proto_raw_sip = -1;
+static gint hf_msg_hdr = -1;
+static gint hf_Method = -1;
+static gint hf_Request_Line = -1;
+static gint hf_Status_Code = -1;
+static gint hf_Status_Line = -1;
+static gint hf_sip_display = -1;
+static gint hf_sip_to_addr = -1;
+static gint hf_sip_from_addr = -1;
+static gint hf_sip_tag = -1;
+static gint hf_sip_resend = -1;
+static gint hf_sip_original_frame = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_sip = -1;
+static gint ett_sip_reqresp = -1;
+static gint ett_sip_hdr = -1;
+static gint ett_raw_text = -1;
+static gint ett_sip_element = -1;
+static gint ett_sip_message_body = -1;
+
+/* PUBLISH method added as per http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
+static const char *sip_methods[] = {
+ "<Invalid method>", /* Pad so that the real methods start at index 1 */
+ "ACK",
+ "BYE",
+ "CANCEL",
+ "DO",
+ "INFO",
+ "INVITE",
+ "MESSAGE",
+ "NOTIFY",
+ "OPTIONS",
+ "PRACK",
+ "QAUTH",
+ "REFER",
+ "REGISTER",
+ "SPRACK",
+ "SUBSCRIBE",
+ "UPDATE",
+ "PUBLISH"
+};
+
+/* from RFC 3261 */
+/* Updated with info from http://www.iana.org/assignments/sip-parameters */
+/* (last updated 2003-10-31) */
+/* Added two headsers ( Etag and If-Match )from http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
+typedef struct {
+ char *name;
+ char *compact_name;
+} sip_header_t;
+static const sip_header_t sip_headers[] = {
+ { "Unknown-header", NULL }, /* Pad so that the real headers start at index 1 */
+ { "Accept", NULL },
+ { "Accept-Encoding", NULL },
+ { "Accept-Language", NULL },
+ { "Alert-Info", NULL },
+ { "Allow", NULL },
+ { "Allow-Events", NULL },
+ { "Authentication-Info", NULL },
+ { "Authorization", NULL },
+ { "Call-ID", "i" },
+ { "Call-Info", NULL },
+ { "Contact", "m" },
+ { "Content-Disposition", NULL },
+ { "Content-Encoding", "e" },
+ { "Content-Language", NULL },
+ { "Content-Length", "l" },
+ { "Content-Type", "c" },
+ { "CSeq", NULL },
+ { "Date", NULL },
+ { "Error-Info", NULL },
+ { "Event", "o" },
+ { "Expires", NULL },
+ { "From", "f" },
+ { "In-Reply-To", NULL },
+ { "Max-Forwards", NULL },
+ { "MIME-Version", NULL },
+ { "Min-Expires", NULL },
+ { "Organization", NULL },
+ { "Priority", NULL },
+ { "Proxy-Authenticate", NULL },
+ { "Proxy-Authorization", NULL },
+ { "Proxy-Require", NULL },
+ { "RAck", NULL },
+ { "RSeq", NULL },
+ { "Record-Route", NULL },
+ { "Reply-To", NULL },
+ { "Require", NULL },
+ { "Retry-After", NULL },
+ { "Route", NULL },
+ { "Server", NULL },
+ { "Subject", "s" },
+ { "Subscription-State", NULL },
+ { "Supported", "k" },
+ { "Timestamp", NULL },
+ { "To", "t" },
+ { "Unsupported", NULL },
+ { "User-Agent", NULL },
+ { "Via", "v" },
+ { "Warning", NULL },
+ { "WWW-Authenticate", NULL },
+ { "P-Access-Network-Info", NULL }, /* RFC3455 */
+ { "P-Asserted-Identity", NULL }, /* RFC3325 */
+ { "P-Associated-URI", NULL }, /* RFC3455 */
+ { "P-Called-Party-ID", NULL }, /* RFC3455 */
+ { "P-Charging-Function-Addresses",NULL }, /* RFC3455 */
+ { "P-Charging-Vector", NULL }, /* RFC3455 */
+ { "P-DCS-Trace-Party-ID", NULL }, /* RFC3603 */
+ { "P-DCS-OSPS", NULL }, /* RFC3603 */
+ { "P-DCS-Billing-Info", NULL }, /* RFC3603 */
+ { "P-DCS-LAES", NULL }, /* RFC3603 */
+ { "P-DCS-Redirect", NULL }, /* RFC3603 */
+ { "P-Media-Authorization", NULL }, /* RFC3313 */
+ { "P-Preferred-Identity", NULL }, /* RFC3325 */
+ { "P-Visited-Network-ID", NULL }, /* RFC3455 */
+ { "Path", NULL }, /* RFC3327 */
+ { "Privacy", NULL }, /* RFC3323 */
+ { "Reason", NULL }, /* RFC3326 */
+ { "Refer-To", "r" }, /* RFC3515 */
+ { "Service-Route", NULL }, /* RFC3608 */
+ { "SIP-ETag", NULL }, /* draft-ietf-sip-publish-03 */
+ { "SIP-If-Match", NULL }, /* draft-ietf-sip-publish-03 */
+
+};
+
+
+#define POS_ACCEPT 1
+#define POS_ACCEPT_ENCODING 2
+#define POS_ACCEPT_LANGUAGE 3
+#define POS_ALERT_INFO 4
+#define POS_ALLOW 5
+#define POS_ALLOW_EVENTS 6
+#define POS_AUTHENTICATION_INFO 7
+#define POS_AUTHORIZATION 8
+#define POS_CALL_ID 9
+#define POS_CALL_INFO 10
+#define POS_CONTACT 11
+#define POS_CONTENT_DISPOSITION 12
+#define POS_CONTENT_ENCODING 13
+#define POS_CONTENT_LANGUAGE 14
+#define POS_CONTENT_LENGTH 15
+#define POS_CONTENT_TYPE 16
+#define POS_CSEQ 17
+#define POS_DATE 18
+#define POS_ERROR_INFO 19
+#define POS_EVENT 20
+#define POS_EXPIRES 21
+#define POS_FROM 22
+#define POS_IN_REPLY_TO 23
+#define POS_MAX_FORWARDS 24
+#define POS_MIME_VERSION 25
+#define POS_MIN_EXPIRES 26
+#define POS_ORGANIZATION 27
+#define POS_PRIORITY 28
+#define POS_PROXY_AUTHENTICATE 29
+#define POS_PROXY_AUTHORIZATION 30
+#define POS_PROXY_REQUIRE 31
+#define POS_RACK 32
+#define POS_RSEQ 33
+#define POS_RECORD_ROUTE 34
+#define POS_REPLY_TO 35
+#define POS_REQUIRE 36
+#define POS_RETRY_AFTER 37
+#define POS_ROUTE 38
+#define POS_SERVER 39
+#define POS_SUBJECT 40
+#define POS_SUBSCRIPTION_STATE 41
+#define POS_SUPPORTED 42
+#define POS_TIMESTAMP 43
+#define POS_TO 44
+#define POS_UNSUPPORTED 45
+#define POS_USER_AGENT 46
+#define POS_VIA 47
+#define POS_WARNING 48
+#define POS_WWW_AUTHENTICATE 49
+
+#define POS_P_ACCESS_NETWORK_INFO 50
+#define POS_P_ASSERTED_IDENTITY 51
+#define POS_P_ASSOCIATED_URI 52
+#define POS_P_CALLED_PARTY_ID 53
+#define POS_P_CHARGING_FUNCTION_ADDRESSES 54
+#define POS_P_CHARGING_VECTOR 55
+#define POS_P_DCS_TRACE_PARTY_ID 56
+#define POS_P_DCS_OSPS 57
+#define POS_P_DCS_BILLING_INFO 58
+#define POS_P_DCS_LAES 59
+#define POS_P_DCS_REDIRECT 60
+#define POS_P_MEDIA_AUTHORIZATION 61
+#define POS_P_PREFERRED_IDENTITY 62
+#define POS_P_VISITED_NETWORK_ID 63
+#define POS_PATH 64
+#define POS_PRIVACY 65
+#define POS_REASON 66
+#define POS_REFER_TO 67
+#define POS_SERVICE_ROUTE 68
+#define POS_SIP_ETAG 69
+#define POS_SIP_IF_MATCH 70
+
+static gint hf_header_array[] = {
+ -1, /* "Unknown-header" - Pad so that the real headers start at index 1 */
+ -1, /* "Accept" */
+ -1, /* "Accept-Encoding" */
+ -1, /* "Accept-Language" */
+ -1, /* "Alert-Info" */
+ -1, /* "Allow" */
+ -1, /* "Allow-Events" - RFC 3265 */
+ -1, /* "Authentication-Info" */
+ -1, /* "Authorization" */
+ -1, /* "Call-ID" */
+ -1, /* "Call-Info" */
+ -1, /* "Contact" */
+ -1, /* "Content-Disposition" */
+ -1, /* "Content-Encoding" */
+ -1, /* "Content-Language" */
+ -1, /* "Content-Length" */
+ -1, /* "Content-Type" */
+ -1, /* "CSeq" */
+ -1, /* "Date" */
+ -1, /* "Error-Info" */
+ -1, /* "Expires" */
+ -1, /* "Event" - RFC 3265 */
+ -1, /* "From" */
+ -1, /* "In-Reply-To" */
+ -1, /* "Max-Forwards" */
+ -1, /* "MIME-Version" */
+ -1, /* "Min-Expires" */
+ -1, /* "Organization" */
+ -1, /* "Priority" */
+ -1, /* "Proxy-Authenticate" */
+ -1, /* "Proxy-Authorization" */
+ -1, /* "Proxy-Require" */
+ -1, /* "RAck" - RFC 3262 */
+ -1, /* "RSeq" - RFC 3261 */
+ -1, /* "Record-Route" */
+ -1, /* "Reply-To" */
+ -1, /* "Require" */
+ -1, /* "Retry-After" */
+ -1, /* "Route" */
+ -1, /* "Server" */
+ -1, /* "Subject" */
+ -1, /* "Subscription-State" - RFC 3265 */
+ -1, /* "Supported" */
+ -1, /* "Timestamp" */
+ -1, /* "To" */
+ -1, /* "Unsupported" */
+ -1, /* "User-Agent" */
+ -1, /* "Via" */
+ -1, /* "Warning" */
+ -1, /* "WWW-Authenticate" */
+ -1, /* "P-Access-Network-Info" - RFC3455 */
+ -1, /* "P-Asserted-Identity" - RFC3325 */
+ -1, /* "P-Associated-URI" - RFC3455 */
+ -1, /* "P-Called-Party-ID" - RFC3455 */
+ -1, /* "P-Charging-Function-Addresses" - RFC3455 */
+ -1, /* "P-Charging-Vector" - RFC3455 */
+ -1, /* "P-DCS-Trace-Party-ID" - RFC3603 */
+ -1, /* "P-DCS-OSPS" - RFC3603 */
+ -1, /* "P-DCS-Billing-Info" - RFC3603 */
+ -1, /* "P-DCS-LAES" - RFC3603 */
+ -1, /* "P-DCS-Redirect" - RFC3603 */
+ -1, /* "P-Media-Authorization" - RFC3313 */
+ -1, /* "P-Preferred-Identity" - RFC3325 */
+ -1, /* "P-Visited-Network-ID" - RFC3455 */
+ -1, /* "Path" - RFC3327 */
+ -1, /* "Privacy" - RFC3323 */
+ -1, /* "Reason" - RFC3326 */
+ -1, /* "Refer-To" - RFC3515 */
+ -1, /* "Service-Route" - RFC3608 */
+ -1, /* "ETag" draft-ietf-sip-publish-01 */
+ -1, /* "If-Match draft-ietf-sip-publish-01 */
+
+};
+
+/*
+ * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
+ * another type of line.
+ */
+typedef enum {
+ REQUEST_LINE,
+ STATUS_LINE,
+ OTHER_LINE
+} line_type_t;
+
+/* global_sip_raw_text determines whether we are going to display */
+/* the raw text of the SIP message, much like the MEGACO dissector does. */
+static gboolean global_sip_raw_text = FALSE;
+/* strict_sip_version determines whether the SIP dissector enforces
+ * the SIP version to be "SIP/2.0". */
+static gboolean strict_sip_version = TRUE;
+
+static gboolean dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, gboolean is_heur);
+static line_type_t sip_parse_line(tvbuff_t *tvb, gint linelen,
+ guint *token_1_len);
+static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
+ guint meth_len, guint *meth_idx);
+static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset,
+ guint header_len);
+static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree,
+ guint meth_len);
+static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree);
+static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
+static guint sip_is_packet_resend(packet_info *pinfo,
+ gchar* cseq_method,
+ gchar* call_id,
+ guchar cseq_number_set, guint32 cseq_number,
+ line_type_t line_type);
+
+
+/* SIP content type and internet media type used by other dissectors
+ * are the same. List of media types from IANA at:
+ * http://www.iana.org/assignments/media-types/index.html */
+static dissector_table_t media_type_dissector_table;
+
+#define SIP2_HDR "SIP/2.0"
+#define SIP2_HDR_LEN (strlen (SIP2_HDR))
+
+/* Store the info needed by the SIP tap for one packet */
+static sip_info_value_t *stat_info;
+
+
+/****************************************************************************
+ * Conversation-type definitions
+ *
+ * For each call, keep track of the current cseq number and state of
+ * transaction, in order to be able to detect retransmissions.
+ *
+ * Don't use the conservation mechanism, but instead:
+ * - store with each dissected packet original frame (if any)
+ * - maintain a global hash table of
+ * (call_id, source_addr, dest_addr) -> (cseq, transaction_state, frame)
+ ****************************************************************************/
+
+static GHashTable *sip_hash = NULL; /* Hash table */
+static GMemChunk *sip_hash_keys = NULL; /* Hash key chunk */
+static GMemChunk *sip_hash_values = NULL; /* Hash value chunk */
+
+/* Types for hash table keys and values */
+#define MAX_CALL_ID_SIZE 128
+typedef struct
+{
+ char call_id[MAX_CALL_ID_SIZE];
+ address source_address;
+ guint32 source_port;
+ address dest_address;
+ guint32 dest_port;
+} sip_hash_key;
+
+
+typedef enum
+{
+ nothing_seen,
+ request_seen,
+ provisional_response_seen,
+ final_response_seen
+} transaction_state_t;
+
+typedef struct
+{
+ guint32 cseq;
+ transaction_state_t transaction_state;
+ gint frame_number;
+} sip_hash_value;
+
+
+/************************/
+/* Hash table functions */
+
+/* Equal keys */
+gint sip_equal(gconstpointer v, gconstpointer v2)
+{
+ const sip_hash_key* val1 = (sip_hash_key*)v;
+ const sip_hash_key* val2 = (sip_hash_key*)v2;
+
+ /* Call id must match */
+ if (strcmp(val1->call_id, val2->call_id) != 0)
+ {
+ return 0;
+ }
+
+ /* Addresses must match */
+ return (ADDRESSES_EQUAL(&(val1->source_address), &(val2->source_address))) &&
+ (val1->source_port == val2->source_port) &&
+ (ADDRESSES_EQUAL(&(val1->dest_address), &(val2->dest_address))) &&
+ (val1->dest_port == val2->dest_port);
+}
+
+/* Compute a hash value for a given key. */
+/* Don't try to use addresses here, call-id should be almost unique. */
+guint sip_hash_func(gconstpointer v)
+{
+ gint n;
+ sip_hash_key *key = (sip_hash_key*)v;
+ guint value = strlen(key->call_id);
+ gint chars_to_use = value / 4;
+
+ /* First few characters from the call-id should be enough... */
+ for (n=0; n < chars_to_use; n++)
+ {
+ value += key->call_id[n];
+ }
+
+ return value;
+}
+
+
+/* Initializes the hash table and the mem_chunk area each time a new
+ * file is loaded or re-loaded in ethereal */
+static void
+sip_init_protocol(void)
+{
+ /* Destroy any existing memory chunks / hashes. */
+ if (sip_hash)
+ g_hash_table_destroy(sip_hash);
+ if (sip_hash_keys)
+ g_mem_chunk_destroy(sip_hash_keys);
+ if (sip_hash_values)
+ g_mem_chunk_destroy(sip_hash_values);
+
+ /* Now create them over */
+ sip_hash = g_hash_table_new(sip_hash_func, sip_equal);
+ sip_hash_keys = g_mem_chunk_new("sip_hash_keys",
+ sizeof(sip_hash_key),
+ SIP_INIT_HASH_TABLE_SIZE * sizeof(sip_hash_key),
+ G_ALLOC_ONLY);
+ sip_hash_values = g_mem_chunk_new("sip_hash_values",
+ sizeof(sip_hash_value),
+ SIP_INIT_HASH_TABLE_SIZE * sizeof(sip_hash_value),
+ G_ALLOC_ONLY);
+}
+
+
+
+/* Code to actually dissect the packets */
+static int
+dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (!dissect_sip_common(tvb, pinfo, tree, FALSE))
+ return 0;
+
+ return tvb_length(tvb);
+}
+
+static void
+dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_sip_common(tvb, pinfo, tree, TRUE);
+}
+
+static gboolean
+dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ return dissect_sip_common(tvb, pinfo, tree, FALSE);
+}
+
+static gboolean
+dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean dissect_other_as_continuation)
+{
+ int offset;
+ gint next_offset, linelen;
+ line_type_t line_type;
+ tvbuff_t *next_tvb;
+ gboolean is_known_request;
+ gboolean found_match = FALSE;
+ char *descr;
+ guint token_1_len;
+ guint current_method_idx = 0;
+ proto_item *ts = NULL, *ti = NULL, *th = NULL, *sip_element_item = NULL;
+ proto_tree *sip_tree = NULL, *reqresp_tree = NULL , *hdr_tree = NULL, *sip_element_tree = NULL, *message_body_tree = NULL;
+ guchar contacts = 0, contact_is_star = 0, expires_is_0 = 0;
+ guint32 cseq_number = 0;
+ guchar cseq_number_set = 0;
+ char cseq_method[16] = "";
+ char call_id[MAX_CALL_ID_SIZE] = "";
+ char *media_type_str = NULL;
+ char *media_type_str_lower_case = NULL;
+ char *content_type_parameter_str = NULL;
+ guint resend_for_packet = 0;
+
+ /* Initialise stat info for passing to tap */
+ stat_info = g_malloc(sizeof(sip_info_value_t));
+ stat_info->response_code = 0;
+ stat_info->request_method = NULL;
+ stat_info->resend = 0;
+
+ /*
+ * Note that "tvb_find_line_end()" will return a value that
+ * is not longer than what's in the buffer, so the
+ * "tvb_get_ptr()" calls below won't throw exceptions.
+ *
+ * Note that "tvb_strneql()" doesn't throw exceptions, so
+ * "sip_parse_line()" won't throw an exception.
+ */
+ offset = 0;
+ linelen = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
+ line_type = sip_parse_line(tvb, linelen, &token_1_len);
+ if (line_type == OTHER_LINE) {
+ /*
+ * This is neither a SIP request nor response.
+ */
+ if (!dissect_other_as_continuation) {
+ /*
+ * We were asked to reject this.
+ */
+ return FALSE;
+ }
+
+ /*
+ * Just dissect it as a continuation.
+ */
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
+
+ switch (line_type) {
+
+ case REQUEST_LINE:
+ is_known_request = sip_is_known_request(tvb, 0, token_1_len, &current_method_idx);
+ descr = is_known_request ? "Request" : "Unknown request";
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
+ descr,
+ tvb_format_text(tvb, 0, linelen - SIP2_HDR_LEN - 1));
+ }
+ break;
+
+ case STATUS_LINE:
+ descr = "Status";
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
+ tvb_format_text(tvb, SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
+ }
+ break;
+
+ case OTHER_LINE:
+ default: /* Squelch compiler complaints */
+ descr = "Continuation";
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+ break;
+ }
+
+ if (tree) {
+ ts = proto_tree_add_item(tree, proto_sip, tvb, 0, -1, FALSE);
+ sip_tree = proto_item_add_subtree(ts, ett_sip);
+ }
+
+ switch (line_type) {
+
+ case REQUEST_LINE:
+ if (sip_tree) {
+ ti = proto_tree_add_string(sip_tree, hf_Request_Line, tvb, 0, linelen,
+ tvb_format_text(tvb, 0, linelen));
+ reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
+ }
+ dfilter_sip_request_line(tvb, reqresp_tree, token_1_len);
+ break;
+
+ case STATUS_LINE:
+ if (sip_tree) {
+ ti = proto_tree_add_string(sip_tree, hf_Status_Line, tvb, 0, linelen,
+ tvb_format_text(tvb, 0, linelen));
+ reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
+ }
+ dfilter_sip_status_line(tvb, reqresp_tree);
+ break;
+
+ case OTHER_LINE:
+ if (sip_tree) {
+ ti = proto_tree_add_text(sip_tree, tvb, 0, next_offset,
+ "%s line: %s", descr,
+ tvb_format_text(tvb, 0, linelen));
+ reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
+ proto_tree_add_text(sip_tree, tvb, 0, -1,
+ "Continuation data");
+ }
+ return TRUE;
+ }
+
+ offset = next_offset;
+ if (sip_tree) {
+ th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, -1, FALSE);
+ hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
+ }
+
+ /*
+ * Process the headers - if we're not building a protocol tree,
+ * we just do this to find the blank line separating the
+ * headers from the message body.
+ */
+ next_offset = offset;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ gint line_end_offset;
+ gint colon_offset;
+ gint semi_colon_offset;
+ gint len;
+ gint parameter_offset;
+ gint parameter_end_offset;
+ gint parameter_len;
+ gint content_type_len, content_type_parameter_str_len;
+ gint header_len;
+ gint hf_index;
+ gint value_offset;
+ guchar c;
+ size_t value_len;
+ char *value;
+
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
+ FALSE);
+ if (linelen == 0) {
+ /*
+ * This is a blank line separating the
+ * message header from the message body.
+ */
+ break;
+ }
+ line_end_offset = offset + linelen;
+ colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
+ if (colon_offset == -1) {
+ /*
+ * Malformed header - no colon after the name.
+ */
+ if(hdr_tree) {
+ proto_tree_add_text(hdr_tree, tvb, offset,
+ next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, linelen));
+ }
+ } else {
+ header_len = colon_offset - offset;
+ hf_index = sip_is_known_sip_header(tvb,
+ offset, header_len);
+
+ if (hf_index == -1) {
+ if(hdr_tree) {
+ proto_tree_add_text(hdr_tree, tvb,
+ offset, next_offset - offset, "%s",
+ tvb_format_text(tvb, offset, linelen));
+ }
+ } else {
+ /*
+ * Skip whitespace after the colon.
+ */
+ value_offset = colon_offset + 1;
+ while (value_offset < line_end_offset
+ && ((c = tvb_get_guint8(tvb,
+ value_offset)) == ' '
+ || c == '\t'))
+ value_offset++;
+ /*
+ * Fetch the value.
+ */
+ value_len = line_end_offset - value_offset;
+ value = tvb_get_string(tvb, value_offset,
+ value_len);
+
+ /*
+ * Add it to the protocol tree,
+ * but display the line as is.
+ */
+ switch ( hf_index ) {
+
+ case POS_TO :
+ if(hdr_tree) {
+ sip_element_item = proto_tree_add_string_format(hdr_tree,
+ hf_header_array[hf_index], tvb,
+ offset, next_offset - offset,
+ value, "%s",
+ tvb_format_text(tvb, offset, linelen));
+ sip_element_tree = proto_item_add_subtree( sip_element_item,
+ ett_sip_element);
+ }
+ /* See if we have a SIP/SIPS uri enclosed in <>, if so anything in front is
+ * display info.
+ */
+ parameter_offset = tvb_find_guint8(tvb, value_offset,value_len, '<');
+ if ( parameter_offset != -1){
+ len = parameter_offset - value_offset;
+ if ( len > 1){
+ /* Something in front, must be display info
+ * TODO: Get rid of trailing space(s)
+ */
+ proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
+ len, FALSE);
+ }
+ parameter_offset ++;
+ parameter_end_offset = parameter_offset;
+ /* RFC3261 paragraph 20
+ * The Contact, From, and To header fields contain a URI. If the URI
+ * contains a comma, question mark or semicolon, the URI MUST be
+ * enclosed in angle brackets (< and >). Any URI parameters are
+ * contained within these brackets. If the URI is not enclosed in angle
+ * brackets, any semicolon-delimited parameters are header-parameters,
+ * not URI parameters.
+ */
+ while (parameter_end_offset < line_end_offset){
+ parameter_end_offset++;
+ c = tvb_get_guint8(tvb, parameter_end_offset);
+ switch (c) {
+ case '>':
+ case ',':
+ case ';':
+ case '?':
+ goto separator_found;
+ default :
+ break;
+ }
+ }
+ separator_found:
+ parameter_len = parameter_end_offset - parameter_offset;
+ proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset,
+ parameter_len, FALSE);
+ parameter_offset = parameter_end_offset + 1;
+ /*
+ * URI parameters ?
+ */
+ parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,( line_end_offset - parameter_offset), ';');
+ if ( parameter_end_offset == -1)
+ parameter_end_offset = line_end_offset;
+
+ offset = parameter_end_offset;
+ }
+ else
+ {
+ /* Extract SIP/SIPS URI */
+ parameter_offset = value_offset;
+ while (parameter_offset < line_end_offset
+ && (tvb_strneql(tvb, parameter_offset, "sip", 3) != 0))
+ parameter_offset++;
+ len = parameter_offset - value_offset;
+ if ( len > 1){
+ /* Something in front, must be display info
+ * TODO: Get rid of trailing space(s)
+ */
+ proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
+ len, FALSE);
+ }
+ parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
+ ( line_end_offset - parameter_offset), ';');
+ if ( parameter_end_offset == -1)
+ parameter_end_offset = line_end_offset;
+ parameter_len = parameter_end_offset - parameter_offset;
+ proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset,
+ parameter_len, FALSE);
+ offset = parameter_end_offset;
+ }
+ /* Find parameter tag if present.
+ * TODO make this generic to find any interesting parameter
+ * use the same method as for SIP headers ?
+ */
+
+ parameter_offset = offset;
+ while (parameter_offset < line_end_offset
+ && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
+ parameter_offset++;
+ if ( parameter_offset < line_end_offset ){ /* Tag found */
+ parameter_offset = parameter_offset + 4;
+ parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
+ ( line_end_offset - parameter_offset), ';');
+ if ( parameter_end_offset == -1)
+ parameter_end_offset = line_end_offset;
+ parameter_len = parameter_end_offset - parameter_offset;
+ proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
+ parameter_len, FALSE);
+
+ }
+ break;
+
+ case POS_FROM :
+ if(hdr_tree) {
+ sip_element_item = proto_tree_add_string_format(hdr_tree,
+ hf_header_array[hf_index], tvb,
+ offset, next_offset - offset,
+ value, "%s",
+ tvb_format_text(tvb, offset, linelen));
+ sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
+ }
+ /* See if we have a SIP/SIPS uri enclosed in <>, if so anything in front is
+ * display info.
+ */
+ parameter_offset = tvb_find_guint8(tvb, value_offset,value_len, '<');
+ if ( parameter_offset != -1){
+ len = parameter_offset - value_offset;
+ if ( len > 1){
+ /* Something in front, must be display info
+ * TODO: Get rid of trailing space(s)
+ */
+ proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
+ len, FALSE);
+ }
+ parameter_offset ++;
+ parameter_end_offset = parameter_offset;
+ /* RFC3261 paragraph 20
+ * The Contact, From, and To header fields contain a URI. If the URI
+ * contains a comma, question mark or semicolon, the URI MUST be
+ * enclosed in angle brackets (< and >). Any URI parameters are
+ * contained within these brackets. If the URI is not enclosed in angle
+ * brackets, any semicolon-delimited parameters are header-parameters,
+ * not URI parameters.
+ */
+ while (parameter_end_offset < line_end_offset){
+ parameter_end_offset++;
+ c = tvb_get_guint8(tvb, parameter_end_offset);
+ switch (c) {
+ case '>':
+ case ',':
+ case ';':
+ case '?':
+ goto separator_found2;
+ default :
+ break;
+ }
+ }
+ separator_found2:
+ parameter_len = parameter_end_offset - parameter_offset;
+ dfilter_store_sip_from_addr(tvb, sip_element_tree,
+ parameter_offset, parameter_len);
+ parameter_offset = parameter_end_offset + 1;
+ /*
+ * URI parameters ?
+ */
+ parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,( line_end_offset - parameter_offset), ';');
+ if ( parameter_end_offset == -1)
+ parameter_end_offset = line_end_offset;
+
+ offset = parameter_end_offset;
+ }
+ else
+ {
+ /* Extract SIP/SIPS URI */
+ parameter_offset = value_offset;
+ while (parameter_offset < line_end_offset
+ && (tvb_strneql(tvb, parameter_offset, "sip", 3) != 0))
+ parameter_offset++;
+ len = parameter_offset - value_offset;
+ if ( len > 1){
+ /* Something in front, must be display info
+ * TODO: Get rid of trailing space(s)
+ */
+ proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
+ len, FALSE);
+ }
+ parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
+ ( line_end_offset - parameter_offset), ';');
+ if ( parameter_end_offset == -1)
+ parameter_end_offset = line_end_offset;
+ parameter_len = parameter_end_offset - parameter_offset;
+ proto_tree_add_item(sip_element_tree, hf_sip_from_addr, tvb, parameter_offset,
+ parameter_len, FALSE);
+ offset = parameter_end_offset;
+ }
+ /* Find parameter tag if present.
+ * TODO make this generic to find any interesting parameter
+ * use the same method as for SIP headers ?
+ */
+
+ parameter_offset = offset;
+ while (parameter_offset < line_end_offset
+ && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
+ parameter_offset++;
+ if ( parameter_offset < line_end_offset ){ /* Tag found */
+ parameter_offset = parameter_offset + 4;
+ parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
+ ( line_end_offset - parameter_offset), ';');
+ if ( parameter_end_offset == -1)
+ parameter_end_offset = line_end_offset;
+ parameter_len = parameter_end_offset - parameter_offset;
+ proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
+ parameter_len, FALSE);
+
+ }
+ break;
+
+ case POS_CSEQ :
+ /* Store the sequence number */
+ cseq_number = atoi(value);
+ cseq_number_set = 1;
+
+ /* Extract method name from value */
+ for (value_offset = 0; value_offset < (gint)strlen(value); value_offset++)
+ {
+ if (isalpha((guchar)value[value_offset]))
+ {
+ strcpy(cseq_method,value+value_offset);
+ break;
+ }
+ }
+ /* Add 'CSeq' string item to tree */
+ if(hdr_tree) {
+ proto_tree_add_string_format(hdr_tree,
+ hf_header_array[hf_index], tvb,
+ offset, next_offset - offset,
+ value, "%s",
+ tvb_format_text(tvb, offset, linelen));
+ }
+ break;
+
+ case POS_CALL_ID :
+ /* Store the Call-id */
+ strncpy(call_id, value,
+ strlen(value)+1 < MAX_CALL_ID_SIZE ?
+ strlen(value)+1 :
+ MAX_CALL_ID_SIZE);
+
+ /* Add 'Call-id' string item to tree */
+ if(hdr_tree) {
+ proto_tree_add_string_format(hdr_tree,
+ hf_header_array[hf_index], tvb,
+ offset, next_offset - offset,
+ value, "%s",
+ tvb_format_text(tvb, offset, linelen));
+ }
+ break;
+
+ case POS_EXPIRES :
+ if (strcmp(value, "0") == 0)
+ {
+ expires_is_0 = 1;
+ }
+ /* Add 'Expires' string item to tree */
+ if(hdr_tree) {
+ proto_tree_add_string_format(hdr_tree,
+ hf_header_array[hf_index], tvb,
+ offset, next_offset - offset,
+ value, "%s",
+ tvb_format_text(tvb, offset, linelen));
+ }
+ break;
+
+ /*
+ * Content-Type is the same as Internet
+ * media type used by other dissectors,
+ * appropriate dissector found by
+ * lookup in "media_type" dissector table.
+ */
+ case POS_CONTENT_TYPE :
+ if(hdr_tree) {
+ proto_tree_add_string_format(hdr_tree,
+ hf_header_array[hf_index], tvb,
+ offset, next_offset - offset,
+ value, "%s",
+ tvb_format_text(tvb, offset, linelen));
+ }
+ content_type_len = value_len;
+ semi_colon_offset = tvb_find_guint8(tvb, value_offset,linelen, ';');
+ if ( semi_colon_offset != -1) {
+ parameter_offset = semi_colon_offset +1;
+ /*
+ * Skip whitespace after the semicolon.
+ */
+ while (parameter_offset < line_end_offset
+ && ((c = tvb_get_guint8(tvb,
+ parameter_offset)) == ' '
+ || c == '\t'))
+ parameter_offset++;
+ content_type_len = semi_colon_offset - value_offset;
+ content_type_parameter_str_len = line_end_offset - parameter_offset;
+ content_type_parameter_str = tvb_get_string(tvb, parameter_offset,
+ content_type_parameter_str_len);
+ }
+ media_type_str = tvb_get_string(tvb, value_offset, content_type_len);
+#if GLIB_MAJOR_VERSION < 2
+ media_type_str_lower_case = g_strdup(media_type_str);
+ g_strdown(media_type_str_lower_case);
+#else
+ media_type_str_lower_case = g_ascii_strdown(media_type_str, -1);
+#endif
+ g_free(media_type_str);
+ break;
+
+ case POS_CONTACT :
+ contacts++;
+ if (strcmp(value, "*") == 0)
+ {
+ contact_is_star = 1;
+ }
+ /* Fall through to default case to add string to tree */
+
+ default :
+ if(hdr_tree) {
+ proto_tree_add_string_format(hdr_tree,
+ hf_header_array[hf_index], tvb,
+ offset, next_offset - offset,
+ value, "%s",
+ tvb_format_text(tvb, offset, linelen));
+ }
+ break;
+ }/* end switch */
+ g_free(value);
+ }/*if HF_index */
+ }/* if colon_offset */
+ offset = next_offset;
+ }/* End while */
+
+ if (tvb_offset_exists(tvb, next_offset)) {
+
+ /*
+ * There's a message body starting at "next_offset".
+ * Set the length of the header item.
+ */
+ proto_item_set_end(th, tvb, next_offset);
+ next_tvb = tvb_new_subset(tvb, next_offset, -1, -1);
+ if(sip_tree) {
+ ti = proto_tree_add_text(sip_tree, next_tvb, 0, -1,
+ "Message body");
+ message_body_tree = proto_item_add_subtree(ti, ett_sip_message_body);
+ }
+
+ /* give the content type parameters to sub dissectors */
+
+ if ( media_type_str_lower_case != NULL ) {
+ void *save_private_data = pinfo->private_data;
+ pinfo->private_data = content_type_parameter_str;
+ found_match = dissector_try_string(media_type_dissector_table,
+ media_type_str_lower_case,
+ next_tvb, pinfo,
+ message_body_tree);
+ g_free(media_type_str_lower_case);
+ g_free(content_type_parameter_str);
+ pinfo->private_data = save_private_data;
+ /* If no match dump as text */
+ }
+ if ( found_match != TRUE )
+ {
+ offset = 0;
+ while (tvb_offset_exists(next_tvb, offset)) {
+ tvb_find_line_end(next_tvb, offset, -1, &next_offset, FALSE);
+ linelen = next_offset - offset;
+ if(message_body_tree) {
+ proto_tree_add_text(message_body_tree, next_tvb, offset, linelen,
+ "%s", tvb_format_text(next_tvb, offset, linelen));
+ }
+ offset = next_offset;
+ }/* end while */
+ }
+ }
+
+
+ /* Add to info column interesting things learned from header fields. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ /* Registration requests */
+ if (strcmp(sip_methods[current_method_idx], "REGISTER") == 0)
+ {
+ if (contact_is_star && expires_is_0)
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, " (remove all bindings)");
+ }
+ else
+ if (!contacts)
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, " (fetch bindings)");
+ }
+ }
+
+ /* Registration responses */
+ if (line_type == STATUS_LINE && (strcmp(cseq_method, "REGISTER") == 0))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (%d bindings)", contacts);
+ }
+ }
+
+ /* Check if this packet is a resend. */
+ resend_for_packet = sip_is_packet_resend(pinfo, cseq_method, call_id,
+ cseq_number_set, cseq_number,
+ line_type);
+ /* Mark whether this is a resend for the tap */
+ stat_info->resend = (resend_for_packet > 0);
+
+ /* And add the filterable field to the request/response line */
+ if (reqresp_tree)
+ {
+ proto_item *item;
+ item = proto_tree_add_boolean(reqresp_tree, hf_sip_resend, tvb, 0, 0,
+ resend_for_packet > 0);
+ PROTO_ITEM_SET_GENERATED(item);
+ if (resend_for_packet > 0)
+ {
+ item = proto_tree_add_uint(reqresp_tree, hf_sip_original_frame,
+ tvb, 0, 0, resend_for_packet);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ }
+
+
+ if (global_sip_raw_text)
+ tvb_raw_text_add(tvb, tree);
+
+ /* Report this packet to the tap */
+ if (!pinfo->in_error_pkt)
+ {
+ tap_queue_packet(sip_tap, pinfo, stat_info);
+ }
+
+ return TRUE;
+}
+
+/* Display filter for SIP Request-Line */
+static void
+dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len)
+{
+ char *string;
+
+ /*
+ * We know we have the entire method; otherwise, "sip_parse_line()"
+ * would have returned OTHER_LINE.
+ */
+ string = tvb_get_string(tvb, 0, meth_len);
+ if (tree) {
+ proto_tree_add_string(tree, hf_Method, tvb, 0, meth_len, string);
+ }
+ /* Copy request method for telling tap */
+ stat_info->request_method = g_malloc(meth_len+1);
+ strncpy(stat_info->request_method, string, meth_len+1);
+
+ /* String no longer needed */
+ g_free(string);
+}
+
+/* Display filter for SIP Status-Line */
+static void
+dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
+{
+ char string[3+1];
+ gint response_code = 0;
+
+ /*
+ * We know we have the entire status code; otherwise,
+ * "sip_parse_line()" would have returned OTHER_LINE.
+ * We also know that we have a version string followed by a
+ * space at the beginning of the line, for the same reason.
+ */
+ tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
+ string[3] = '\0';
+ response_code = atoi(string);
+
+ /* Add numerical response code to tree */
+ if (tree) {
+ proto_tree_add_uint(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
+ 3, response_code);
+ }
+
+ /* Add response code for sending to tap */
+ stat_info->response_code = response_code;
+}
+
+void dfilter_store_sip_from_addr(tvbuff_t *tvb,proto_tree *tree,guint parameter_offset,
+ guint parameter_len)
+{
+ proto_tree_add_item(tree, hf_sip_from_addr, tvb, parameter_offset,
+ parameter_len, FALSE);
+
+}
+/* From section 4.1 of RFC 2543:
+ *
+ * Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ *
+ * From section 5.1 of RFC 2543:
+ *
+ * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF
+ *
+ * From section 7.1 of RFC 3261:
+ *
+ * Unlike HTTP, SIP treats the version number as a literal string.
+ * In practice, this should make no difference.
+ */
+static line_type_t
+sip_parse_line(tvbuff_t *tvb, gint linelen, guint *token_1_lenp)
+{
+ gint space_offset;
+ guint token_1_len;
+ gint token_2_start;
+ guint token_2_len;
+ gint token_3_start;
+ guint token_3_len;
+ gint colon_pos;
+
+ space_offset = tvb_find_guint8(tvb, 0, -1, ' ');
+ if (space_offset <= 0) {
+ /*
+ * Either there's no space in the line (which means
+ * the line is empty or doesn't have a token followed
+ * by a space; neither is valid for a request or status), or
+ * the first character in the line is a space (meaning
+ * the method is empty, which isn't valid for a request,
+ * or the SIP version is empty, which isn't valid for a
+ * status).
+ */
+ return OTHER_LINE;
+ }
+ token_1_len = space_offset;
+ token_2_start = space_offset + 1;
+ space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
+ if (space_offset == -1) {
+ /*
+ * There's no space after the second token, so we don't
+ * have a third token.
+ */
+ return OTHER_LINE;
+ }
+ token_2_len = space_offset - token_2_start;
+ token_3_start = space_offset + 1;
+ token_3_len = linelen - token_3_start;
+
+ *token_1_lenp = token_1_len;
+
+ /*
+ * Is the first token a version string?
+ */
+ if ( (strict_sip_version && (
+ token_1_len == SIP2_HDR_LEN
+ && tvb_strneql(tvb, 0, SIP2_HDR, SIP2_HDR_LEN) == 0)
+ ) || (! strict_sip_version && (
+ tvb_strneql(tvb, 0, "SIP/", 4) == 0)
+ )) {
+ /*
+ * Yes, so this is either a Status-Line or something
+ * else other than a Request-Line. To be a Status-Line,
+ * the second token must be a 3-digit number.
+ */
+ if (token_2_len != 3) {
+ /*
+ * We don't have 3-character status code.
+ */
+ return OTHER_LINE;
+ }
+ if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
+ !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
+ !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
+ /*
+ * 3 characters yes, 3 digits no.
+ */
+ return OTHER_LINE;
+ }
+ return STATUS_LINE;
+ } else {
+ /*
+ * No, so this is either a Request-Line or something
+ * other than a Status-Line. To be a Request-Line, the
+ * second token must be a URI and the third token must
+ * be a version string.
+ */
+ if (token_2_len < 3) {
+ /*
+ * We don't have a URI consisting of at least 3
+ * characters.
+ */
+ return OTHER_LINE;
+ }
+ colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
+ if (colon_pos == -1) {
+ /*
+ * There is no colon after the method, so the URI
+ * doesn't have a colon in it, so it's not valid.
+ */
+ return OTHER_LINE;
+ }
+ if (colon_pos >= token_3_start) {
+ /*
+ * The colon is in the version string, not the URI.
+ */
+ return OTHER_LINE;
+ }
+ /* XXX - Check for a proper URI prefix? */
+ if ( (strict_sip_version && (
+ token_3_len != SIP2_HDR_LEN
+ || tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1)
+ ) || (! strict_sip_version && (
+ tvb_strneql(tvb, token_3_start, "SIP/", 4) == -1)
+ )) {
+ /*
+ * The version string isn't an SIP version 2.0 version
+ * string.
+ */
+ return OTHER_LINE;
+ }
+ return REQUEST_LINE;
+ }
+}
+
+static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
+ guint meth_len, guint *meth_idx)
+{
+ guint i;
+
+ for (i = 1; i < array_length(sip_methods); i++) {
+ if (meth_len == strlen(sip_methods[i]) &&
+ tvb_strneql(tvb, meth_offset, sip_methods[i], meth_len) == 0)
+ {
+ *meth_idx = i;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/* Returns index of method in sip_headers */
+static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len)
+{
+ guint i;
+
+ for (i = 1; i < array_length(sip_headers); i++) {
+ if (header_len == strlen(sip_headers[i].name) &&
+ tvb_strncaseeql(tvb, offset, sip_headers[i].name, header_len) == 0)
+ return i;
+ if (sip_headers[i].compact_name != NULL &&
+ header_len == strlen(sip_headers[i].compact_name) &&
+ tvb_strncaseeql(tvb, offset, sip_headers[i].compact_name, header_len) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+/*
+ * Display the entire message as raw text.
+ */
+static void
+tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
+{
+ proto_tree *raw_tree = NULL;
+ proto_item *ti = NULL;
+ int offset, next_offset, linelen;
+
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_raw_sip, tvb, 0, -1, FALSE);
+ raw_tree = proto_item_add_subtree(ti, ett_raw_text);
+ }
+
+ offset = 0;
+
+ while (tvb_offset_exists(tvb, offset)) {
+ tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ linelen = next_offset - offset;
+ if(raw_tree) {
+ proto_tree_add_text(raw_tree, tvb, offset, linelen,
+ "%s", tvb_format_text(tvb, offset, linelen));
+ }
+ offset = next_offset;
+ }
+}
+
+/* Check to see if this packet is a resent request. Return value is number
+ of the original frame this packet seems to be resending (0 = no resend). */
+guint sip_is_packet_resend(packet_info *pinfo,
+ gchar *cseq_method,
+ gchar *call_id,
+ guchar cseq_number_set,
+ guint32 cseq_number, line_type_t line_type)
+{
+ guint32 cseq_to_compare = 0;
+ sip_hash_key key;
+ sip_hash_key *p_key = 0;
+ sip_hash_value *p_val = 0;
+ guint result = 0;
+
+ /* Only consider retransmission of UDP packets */
+ if (pinfo->ptype != PT_UDP)
+ {
+ return 0;
+ }
+
+ /* Don't consider packets that appear to be resent only because
+ they are e.g. returned in ICMP unreachable messages. */
+ if (pinfo->in_error_pkt)
+ {
+ return 0;
+ }
+
+ /* A broken packet may have no cseq number set. Don't consider it as
+ a resend */
+ if (!cseq_number_set)
+ {
+ return 0;
+ }
+
+ /* Return any answer stored from previous dissection */
+ if (pinfo->fd->flags.visited)
+ {
+ return (guint)(p_get_proto_data(pinfo->fd, proto_sip));
+ }
+
+ /* No packet entry found, consult global hash table */
+
+ /* Prepare the key */
+ strncpy(key.call_id, call_id,
+ (strlen(call_id)+1 <= MAX_CALL_ID_SIZE) ?
+ strlen(call_id)+1 :
+ MAX_CALL_ID_SIZE);
+ COPY_ADDRESS(&key.dest_address, &pinfo->net_dst);
+ COPY_ADDRESS(&key.source_address, &pinfo->net_src);
+ key.dest_port = pinfo->destport;
+ key.source_port = pinfo->srcport;
+
+ /* Do the lookup */
+ p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
+
+ if (p_val)
+ {
+ /* Table entry found, we'll use its value for comparison */
+ cseq_to_compare = p_val->cseq;
+ }
+ else
+ {
+ /* Need to create a new table entry */
+
+ /* Allocate a new key and value */
+ p_key = g_mem_chunk_alloc(sip_hash_keys);
+ p_val = g_mem_chunk_alloc(sip_hash_values);
+
+ /* Just give up if allocations failed */
+ if (!p_key || !p_val)
+ {
+ return 0;
+ }
+
+ /* Fill in key and value details */
+ strcpy(p_key->call_id, call_id);
+ COPY_ADDRESS(&(p_key->dest_address), &pinfo->net_dst);
+ COPY_ADDRESS(&(p_key->source_address), &pinfo->net_src);
+ p_key->dest_port = pinfo->destport;
+ p_key->source_port = pinfo->srcport;
+
+ p_val->cseq = cseq_number;
+ p_val->transaction_state = nothing_seen;
+ p_val->frame_number = 0;
+
+ /* Add entry */
+ g_hash_table_insert(sip_hash, p_key, p_val);
+
+ /* Assume have seen no cseq yet */
+ cseq_to_compare = 0;
+ }
+
+
+ /******************************************/
+ /* Is it a resend??? */
+
+ /* Does this look like a resent request ? */
+ if ((line_type == REQUEST_LINE) && (cseq_number == cseq_to_compare) &&
+ (p_val->transaction_state == request_seen) &&
+ (strcmp(cseq_method, "ACK") != 0))
+ {
+ result = p_val->frame_number;
+ }
+
+ /* Does this look like a resent final response ? */
+ if ((line_type == STATUS_LINE) && (cseq_number == cseq_to_compare) &&
+ (p_val->transaction_state == final_response_seen) &&
+ (stat_info->response_code >= 200))
+ {
+ result = p_val->frame_number;
+ }
+
+ /* Update state for this entry */
+ p_val->cseq = cseq_number;
+
+ switch (line_type)
+ {
+ case REQUEST_LINE:
+ p_val->transaction_state = request_seen;
+ if (!result)
+ {
+ p_val->frame_number = pinfo->fd->num;
+ }
+ break;
+ case STATUS_LINE:
+ if (stat_info->response_code >= 200)
+ {
+ p_val->transaction_state = final_response_seen;
+ if (!result)
+ {
+ p_val->frame_number = pinfo->fd->num;
+ }
+ }
+ else
+ {
+ p_val->transaction_state = provisional_response_seen;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Store return value with this packet */
+ p_add_proto_data(pinfo->fd, proto_sip, (void*)result);
+
+ return result;
+}
+
+
+/* Register the protocol with Ethereal */
+void proto_register_sip(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+
+ { &hf_msg_hdr,
+ { "Message Header", "sip.msg_hdr",
+ FT_NONE, 0, NULL, 0,
+ "Message Header in SIP message", HFILL }
+ },
+ { &hf_Method,
+ { "Method", "sip.Method",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "SIP Method", HFILL }
+ },
+ { &hf_Request_Line,
+ { "Request-Line", "sip.Request-Line",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "SIP Request-Line", HFILL }
+ },
+ { &hf_Status_Code,
+ { "Status-Code", "sip.Status-Code",
+ FT_UINT32, BASE_DEC,NULL,0x0,
+ "SIP Status Code", HFILL }
+ },
+ { &hf_Status_Line,
+ { "Status-Line", "sip.Status-Line",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "SIP Status-Line", HFILL }
+ },
+ { &hf_sip_display,
+ { "SIP Display info", "sip.display.info",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Display info", HFILL }
+ },
+ { &hf_sip_to_addr,
+ { "SIP to address", "sip.to.addr",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: to addr", HFILL }
+ },
+ { &hf_sip_from_addr,
+ { "SIP from address", "sip.from.addr",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: from addr", HFILL }
+ },
+ { &hf_sip_tag,
+ { "SIP tag", "sip.tag",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: tag", HFILL }
+ },
+ { &hf_header_array[POS_ACCEPT],
+ { "Accept", "sip.Accept",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Accept Header", HFILL }
+ },
+ { &hf_header_array[POS_ACCEPT_ENCODING],
+ { "Accept-Encoding", "sip.Accept-Encoding",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Accept-Encoding Header", HFILL }
+ },
+ { &hf_header_array[POS_ACCEPT_LANGUAGE],
+ { "Accept-Language", "sip.Accept-Language",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Accept-Language Header", HFILL }
+ },
+ { &hf_header_array[POS_ALERT_INFO],
+ { "Alert-Info", "sip.Alert-Info",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Alert-Info Header", HFILL }
+ },
+ { &hf_header_array[POS_ALLOW],
+ { "Allow", "sip.Allow",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Allow Header", HFILL }
+ },
+ { &hf_header_array[POS_ALLOW_EVENTS],
+ { "Allow-Events", "sip.Allow-Events",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3265: Allow-Events Header", HFILL }
+ },
+ { &hf_header_array[POS_AUTHENTICATION_INFO],
+ { "Authentication-Info", "sip.Authentication-Info",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Authentication-Info Header", HFILL }
+ },
+ { &hf_header_array[POS_AUTHORIZATION],
+ { "Authorization", "sip.Authorization",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Authorization Header", HFILL }
+ },
+ { &hf_header_array[POS_CALL_ID],
+ { "Call-ID", "sip.Call-ID",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Call-ID Header", HFILL }
+ },
+ { &hf_header_array[POS_CALL_INFO],
+ { "Call-Info", "sip.Call-Info",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Call-Info Header", HFILL }
+ },
+ { &hf_header_array[POS_CONTACT],
+ { "Contact", "sip.Contact",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Contact Header", HFILL }
+ },
+ { &hf_header_array[POS_CONTENT_DISPOSITION],
+ { "Content-Disposition", "sip.Content-Disposition",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Content-Disposition Header", HFILL }
+ },
+ { &hf_header_array[POS_CONTENT_ENCODING],
+ { "Content-Encoding", "sip.Content-Encoding",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Content-Encoding Header", HFILL }
+ },
+ { &hf_header_array[POS_CONTENT_LANGUAGE],
+ { "Content-Language", "sip.Content-Language",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Content-Language Header", HFILL }
+ },
+ { &hf_header_array[POS_CONTENT_LENGTH],
+ { "Content-Length", "sip.Content-Length",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Content-Length Header", HFILL }
+ },
+ { &hf_header_array[POS_CONTENT_TYPE],
+ { "Content-Type", "sip.Content-Type",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Content-Type Header", HFILL }
+ },
+ { &hf_header_array[POS_CSEQ],
+ { "CSeq", "sip.CSeq",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: CSeq Header", HFILL }
+ },
+ { &hf_header_array[POS_DATE],
+ { "Date", "sip.Date",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Date Header", HFILL }
+ },
+ { &hf_header_array[POS_ERROR_INFO],
+ { "Error-Info", "sip.Error-Info",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Error-Info Header", HFILL }
+ },
+ { &hf_header_array[POS_EVENT],
+ { "Event", "sip.Event",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3265: Event Header", HFILL }
+ },
+ { &hf_header_array[POS_EXPIRES],
+ { "Expires", "sip.Expires",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Expires Header", HFILL }
+ },
+ { &hf_header_array[POS_FROM],
+ { "From", "sip.From",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: From Header", HFILL }
+ },
+ { &hf_header_array[POS_IN_REPLY_TO],
+ { "In-Reply-To", "sip.In-Reply-To",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: In-Reply-To Header", HFILL }
+ },
+ { &hf_header_array[POS_MAX_FORWARDS],
+ { "Max-Forwards", "sip.Max-Forwards",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Max-Forwards Header", HFILL }
+ },
+ { &hf_header_array[POS_MIME_VERSION],
+ { "MIME-Version", "sip.MIME-Version",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: MIME-Version Header", HFILL }
+ },
+ { &hf_header_array[POS_MIN_EXPIRES],
+ { "Min-Expires", "sip.Min-Expires",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Min-Expires Header", HFILL }
+ },
+ { &hf_header_array[POS_ORGANIZATION],
+ { "Organization", "sip.Organization",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Organization Header", HFILL }
+ },
+ { &hf_header_array[POS_PRIORITY],
+ { "Priority", "sip.Priority",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Priority Header", HFILL }
+ },
+ { &hf_header_array[POS_PROXY_AUTHENTICATE],
+ { "Proxy-Authenticate", "sip.Proxy-Authenticate",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Proxy-Authenticate Header", HFILL }
+ },
+ { &hf_header_array[POS_PROXY_AUTHORIZATION],
+ { "Proxy-Authorization", "sip.Proxy-Authorization",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Proxy-Authorization Header", HFILL }
+ },
+ { &hf_header_array[POS_RACK],
+ { "RAck", "sip.RAck",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3262: RAck Header", HFILL }
+ },
+ { &hf_header_array[POS_RSEQ],
+ { "RSeq", "sip.RSeq",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3262: RSeq Header", HFILL }
+ },
+ { &hf_header_array[POS_PROXY_REQUIRE],
+ { "Proxy-Require", "sip.Proxy-Require",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Proxy-Require Header", HFILL }
+ },
+ { &hf_header_array[POS_RECORD_ROUTE],
+ { "Record-Route", "sip.Record-Route",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Record-Route Header", HFILL }
+ },
+ { &hf_header_array[POS_REPLY_TO],
+ { "Reply-To", "sip.Reply-To",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Reply-To Header", HFILL }
+ },
+ { &hf_header_array[POS_REQUIRE],
+ { "Require", "sip.Require",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Require Header", HFILL }
+ },
+ { &hf_header_array[POS_RETRY_AFTER],
+ { "Retry-After", "sip.Retry-After",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Retry-After Header", HFILL }
+ },
+ { &hf_header_array[POS_ROUTE],
+ { "Route", "sip.Route",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Route Header", HFILL }
+ },
+ { &hf_header_array[POS_SERVER],
+ { "Server", "sip.Server",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Server Header", HFILL }
+ },
+ { &hf_header_array[POS_SUBJECT],
+ { "Subject", "sip.Subject",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Subject Header", HFILL }
+ },
+ { &hf_header_array[POS_SUBSCRIPTION_STATE],
+ { "Subscription-State", "sip.Subscription-State",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3265: Subscription-State Header", HFILL }
+ },
+ { &hf_header_array[POS_SUPPORTED],
+ { "Supported", "sip.Supported",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Supported Header", HFILL }
+ },
+ { &hf_header_array[POS_TIMESTAMP],
+ { "Timestamp", "sip.Timestamp",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Timestamp Header", HFILL }
+ },
+ { &hf_header_array[POS_TO],
+ { "To", "sip.To",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: To Header", HFILL }
+ },
+ { &hf_header_array[POS_UNSUPPORTED],
+ { "Unsupported", "sip.Unsupported",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Unsupported Header", HFILL }
+ },
+ { &hf_header_array[POS_USER_AGENT],
+ { "User-Agent", "sip.User-Agent",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: User-Agent Header", HFILL }
+ },
+ { &hf_header_array[POS_VIA],
+ { "Via", "sip.Via",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Via Header", HFILL }
+ },
+ { &hf_header_array[POS_WARNING],
+ { "Warning", "sip.Warning",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: Warning Header", HFILL }
+ },
+ { &hf_header_array[POS_WWW_AUTHENTICATE],
+ { "WWW-Authenticate", "sip.WWW-Authenticate",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "RFC 3261: WWW-Authenticate Header", HFILL }
+ },
+ { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
+ { "P-Access-Network-Info", "sip.P-Access-Network-Info",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-Access-Network-Info Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_ASSERTED_IDENTITY],
+ { "P-Asserted-Identity", "sip.P-Asserted-Identity",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-Asserted-Identity Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_ASSOCIATED_URI],
+ { "P-Associated-URI", "sip.P-Associated-URI",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-Associated-URI Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_CALLED_PARTY_ID],
+ { "P-Called-Party-ID", "sip.P-Called-Party-ID",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-Called-Party-ID Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_CHARGING_FUNCTION_ADDRESSES],
+ { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-Charging-Function-Addresses", HFILL }
+ },
+
+ { &hf_header_array[POS_P_CHARGING_VECTOR],
+ { "P-Charging-Vector", "sip.P-Charging-Vector",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-Charging-Vector Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
+ { "P-DCS-Trace-Party-ID", "sip.P-DCS-Trace-Party-ID",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-DCS-Trace-Party-ID Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_DCS_OSPS],
+ { "P-DCS-OSPS", "sip.P-DCS-OSPS",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-DCS-OSPS Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_DCS_BILLING_INFO],
+ { "P-DCS-Billing-Info", "sip.P-DCS-Billing-Info",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-DCS-Billing-Info Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_DCS_LAES],
+ { "P-DCS-LAES", "sip.P-DCS-LAES",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-DCS-LAES Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_DCS_REDIRECT],
+ { "P-DCS-Redirect", "sip.P-DCS-Redirect",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-DCS-Redirect Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
+ { "P-Media-Authorization", "sip.P-Media-Authorization",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-Media-Authorization Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_PREFERRED_IDENTITY],
+ { "P-Preferred-Identity", "sip.P-Preferred-Identity",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-Preferred-Identity Header", HFILL }
+ },
+
+ { &hf_header_array[POS_P_VISITED_NETWORK_ID],
+ { "P-Visited-Network-ID", "sip.P-Visited-Network-ID",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "P-Visited-Network-ID Header", HFILL }
+ },
+
+ { &hf_header_array[POS_PATH],
+ { "Path", "sip.Path",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "Path Header", HFILL }
+ },
+
+ { &hf_header_array[POS_PRIVACY],
+ { "Privacy", "sip.Privacy",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "Privacy Header", HFILL }
+ },
+
+ { &hf_header_array[POS_REASON],
+ { "Reason", "sip.Reason",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "Reason Header", HFILL }
+ },
+
+ { &hf_header_array[POS_REFER_TO],
+ { "Refer-To", "sip.Refer-To",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "Refer-To Header", HFILL }
+ },
+
+ { &hf_header_array[POS_SERVICE_ROUTE],
+ { "Service-Route", "sip.Service-Route",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "Service-Route Header", HFILL }
+ },
+
+ { &hf_header_array[POS_SIP_ETAG],
+ { "ETag", "sip.ETag",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "SIP-ETag Header", HFILL }
+ },
+ { &hf_header_array[POS_SIP_IF_MATCH],
+ { "If_Match", "sip.If_Match",
+ FT_STRING, BASE_NONE,NULL,0x0,
+ "SIP-If-Match Header", HFILL }
+ },
+ { &hf_sip_resend,
+ { "Resent Packet", "sip.resend",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ { &hf_sip_original_frame,
+ { "Suspected resend of frame", "sip.resend-original",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Original transmission of frame", HFILL}}
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_sip,
+ &ett_sip_reqresp,
+ &ett_sip_hdr,
+ &ett_sip_element,
+ &ett_sip_message_body,
+ };
+ static gint *ett_raw[] = {
+ &ett_raw_text,
+ };
+
+ module_t *sip_module;
+
+ /* Register the protocol name and description */
+ proto_sip = proto_register_protocol("Session Initiation Protocol",
+ "SIP", "sip");
+ proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
+ "Raw_SIP", "raw_sip");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_sip, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ proto_register_subtree_array(ett_raw, array_length(ett_raw));
+
+ /* SIP content type and internet media type used by other dissectors are the same */
+
+ media_type_dissector_table = find_dissector_table("media_type");
+
+
+ sip_module = prefs_register_protocol(proto_sip, NULL);
+
+ prefs_register_bool_preference(sip_module, "display_raw_text",
+ "Display raw text for SIP message",
+ "Specifies that the raw text of the "
+ "SIP message should be displayed "
+ "in addition to the dissection tree",
+ &global_sip_raw_text);
+ prefs_register_bool_preference(sip_module, "strict_sip_version",
+ "Enforce strict SIP version check (" SIP2_HDR ")",
+ "If enabled, only " SIP2_HDR " traffic will be dissected as SIP. "
+ "Disable it to allow SIP traffic with a different version "
+ "to be dissected as SIP.",
+ &strict_sip_version);
+
+ register_init_routine(&sip_init_protocol);
+
+ /* Register for tapping */
+ sip_tap = register_tap("sip");
+}
+
+void
+proto_reg_handoff_sip(void)
+{
+ dissector_handle_t sip_handle, sip_tcp_handle;
+
+ sip_handle = new_create_dissector_handle(dissect_sip, proto_sip);
+ dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
+ dissector_add_string("media_type", "message/sip", sip_handle);
+
+ sip_tcp_handle = create_dissector_handle(dissect_sip_tcp, proto_sip);
+ dissector_add("tcp.port", TCP_PORT_SIP, sip_tcp_handle);
+
+ heur_dissector_add("udp", dissect_sip_heur, proto_sip);
+ heur_dissector_add("tcp", dissect_sip_heur, proto_sip);
+ heur_dissector_add("sctp", dissect_sip_heur, proto_sip);
+}
diff --git a/epan/dissectors/packet-sip.h b/epan/dissectors/packet-sip.h
new file mode 100644
index 0000000000..e8702758e5
--- /dev/null
+++ b/epan/dissectors/packet-sip.h
@@ -0,0 +1,39 @@
+/* packet-sip.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_SIP_H__
+#define __PACKET_SIP_H__
+
+#include <epan/packet.h>
+
+typedef struct _sip_info_value_t
+{
+ gchar *request_method;
+ guint response_code;
+ guchar resend;
+} sip_info_value_t;
+
+extern void dfilter_store_sip_from_addr(tvbuff_t *tvb,proto_tree *tree,guint parameter_offset,
+ guint parameter_len);
+
+#endif
diff --git a/epan/dissectors/packet-sipfrag.c b/epan/dissectors/packet-sipfrag.c
new file mode 100644
index 0000000000..c40bfaf89f
--- /dev/null
+++ b/epan/dissectors/packet-sipfrag.c
@@ -0,0 +1,140 @@
+/* Routines for sipfrag packet disassembly (RFC 3420)
+ *
+ * Martin Mathieson
+ * Based on packet-sdp.c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+
+/*
+ * TODO:
+ * Doesn't currently dissect the lines of the message.
+ * Need to refactor SIP dissector and make its functionality available here
+ */
+
+
+/* Initialize the protocol and registered fields. */
+static int proto_sipfrag = -1;
+static int hf_line = -1;
+
+/* Protocol subtree. */
+static int ett_sipfrag = -1;
+
+
+/* Main dissection function. */
+static void
+dissect_sipfrag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *sipfrag_tree;
+ proto_item *ti;
+ gint offset = 0;
+ gint next_offset;
+ int linelen;
+ char *string;
+ gint lines = 0;
+
+ /* Append this protocol name rather than replace. */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_append_str(pinfo->cinfo, COL_PROTOCOL, "/sipfrag");
+
+ /* Add mention of this protocol to info column */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, ", with Sipfrag");
+ }
+
+ /* Create sipfrag tree. */
+ ti = proto_tree_add_item(tree, proto_sipfrag, tvb, offset, -1, FALSE);
+ sipfrag_tree = proto_item_add_subtree(ti, ett_sipfrag);
+
+ /* Show the sipfrag message a line at a time. */
+ while (tvb_reported_length_remaining(tvb, offset) > 0)
+ {
+ /* Find the end of the line. */
+ linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
+
+ /* For now, add all lines as unparsed strings */
+
+ /* Extract & add the string. */
+ string = tvb_get_string(tvb, offset, linelen);
+ proto_tree_add_string_format(sipfrag_tree, hf_line,
+ tvb, offset,
+ linelen, string,
+ "%s", string);
+ lines++;
+
+ /* Show first line in info column */
+ if (lines == 1 && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "(%s", string);
+ }
+
+ /* Finished with this string now. */
+ g_free(string);
+
+ /* Move onto next line. */
+ offset = next_offset;
+ }
+
+ /* Close off summary of sipfrag in info column */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, (lines > 1) ? "...)" : ")");
+ }
+}
+
+void
+proto_register_sipfrag(void)
+{
+ static hf_register_info hf[] =
+ {
+ { &hf_line,
+ { "Line",
+ "sipfrag.line",FT_STRING, BASE_NONE, NULL, 0x0, "Line", HFILL
+ }
+ },
+ };
+
+ static gint *ett[] =
+ {
+ &ett_sipfrag
+ };
+
+ /* Register protocol. */
+ proto_sipfrag = proto_register_protocol("Sipfrag", "SIPFRAG", "sipfrag");
+ proto_register_field_array(proto_sipfrag, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Allow other dissectors to find this one by name. */
+ register_dissector("sipfrag", dissect_sipfrag, proto_sipfrag);
+}
+
+void
+proto_reg_handoff_sipfrag(void)
+{
+ dissector_handle_t sipfrag_handle = find_dissector("sipfrag");
+ dissector_add_string("media_type", "message/sipfrag", sipfrag_handle);
+}
+
+
diff --git a/epan/dissectors/packet-skinny.c b/epan/dissectors/packet-skinny.c
new file mode 100644
index 0000000000..ff8b025799
--- /dev/null
+++ b/epan/dissectors/packet-skinny.c
@@ -0,0 +1,4402 @@
+/* packet-skinny.c
+ *
+ * Dissector for the Skinny Client Control Protocol
+ * (The "D-Channel"-Protocol for Cisco Systems' IP-Phones)
+ * Copyright 2001, Joerg Mayer (email: see AUTHORS file)
+ *
+ * Paul E. Erkkila (pee@erkkila.org) - fleshed out the decode
+ * skeleton to report values for most message/message fields.
+ * Much help from Guy Harris on figuring out the ethereal api.
+ *
+ * This file is based on packet-aim.c, which is
+ * Copyright 2000, Ralf Hoelzer <ralf@well.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This implementation is based on a draft version of the 3.0
+ * specification
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include <epan/packet.h>
+#include "prefs.h"
+
+#include "packet-rtp.h"
+#include "packet-tcp.h"
+
+#define TCP_PORT_SKINNY 2000
+
+#define SKINNY_SOFTKEY0 0x01
+#define SKINNY_SOFTKEY1 0x02
+#define SKINNY_SOFTKEY2 0x04
+#define SKINNY_SOFTKEY3 0x08
+#define SKINNY_SOFTKEY4 0x10
+#define SKINNY_SOFTKEY5 0x20
+#define SKINNY_SOFTKEY6 0x40
+#define SKINNY_SOFTKEY7 0x80
+#define SKINNY_SOFTKEY8 0x100
+#define SKINNY_SOFTKEY9 0x200
+#define SKINNY_SOFTKEY10 0x400
+#define SKINNY_SOFTKEY11 0x800
+#define SKINNY_SOFTKEY12 0x1000
+#define SKINNY_SOFTKEY13 0x2000
+#define SKINNY_SOFTKEY14 0x4000
+#define SKINNY_SOFTKEY15 0x8000
+
+/* KeyMap Show/No Show */
+static const true_false_string softKeyMapValues = {
+ "Show",
+ "Do Not Show"
+};
+
+
+/* I will probably need this again when I change things
+ * to function pointers, but let me use the existing
+ * infrastructure for now
+ *
+ * typedef struct {
+ * guint32 id;
+ * char * name;
+ * } message_id_t;
+ */
+
+static const value_string message_id[] = {
+
+ /* Station -> Callmanager */
+ {0x0000, "KeepAliveMessage"},
+ {0x0001, "RegisterMessage"},
+ {0x0002, "IpPortMessage"},
+ {0x0003, "KeypadButtonMessage"},
+ {0x0004, "EnblocCallMessage"},
+ {0x0005, "StimulusMessage"},
+ {0x0006, "OffHookMessage"},
+ {0x0007, "OnHookMessage"},
+ {0x0008, "HookFlashMessage"},
+ {0x0009, "ForwardStatReqMessage"},
+ {0x000A, "SpeedDialStatReqMessage"},
+ {0x000B, "LineStatReqMessage"},
+ {0x000C, "ConfigStatReqMessage"},
+ {0x000D, "TimeDateReqMessage"},
+ {0x000E, "ButtonTemplateReqMessage"},
+ {0x000F, "VersionReqMessage"},
+ {0x0010, "CapabilitiesResMessage"},
+ {0x0011, "MediaPortListMessage"},
+ {0x0012, "ServerReqMessage"},
+ {0x0020, "AlarmMessage"},
+ {0x0021, "MulticastMediaReceptionAck"},
+ {0x0022, "OpenReceiveChannelAck"},
+ {0x0023, "ConnectionStatisticsRes"},
+ {0x0024, "OffHookWithCgpnMessage"},
+ {0x0025, "SoftKeySetReqMessage"},
+ {0x0026, "SoftKeyEventMessage"},
+ {0x0027, "UnregisterMessage"},
+ {0x0028, "SoftKeyTemplateReqMessage"},
+ {0x0029, "RegisterTokenReq"},
+ {0x002A, "MediaTransmissionFailure"},
+ {0x002B, "HeadsetStatusMessage"},
+ {0x002C, "MediaResourceNotification"},
+ {0x002D, "RegisterAvailableLinesMessage"},
+ {0x002E, "DeviceToUserDataMessage"},
+ {0x002F, "DeviceToUserDataResponseMessage"},
+ {0x0030, "UpdateCapabilitiesMessage"},
+ {0x0031, "OpenMultiMediaReceiveChannelAckMessage"},
+ {0x0032, "ClearConferenceMessage"},
+ {0x0033, "ServiceURLStatReqMessage"},
+ {0x0034, "FeatureStatReqMessage"},
+ {0x0035, "CreateConferenceResMessage"},
+ {0x0036, "DeleteConferenceResMessage"},
+ {0x0037, "ModifyConferenceResMessage"},
+ {0x0038, "AddParticipantResMessage"},
+ {0x0039, "AuditConferenceResMessage"},
+ {0x0040, "AuditParticipantResMessage"},
+ {0x0041, "DeviceToUserDataVersion1Message"},
+ {0x0042, "DeviceToUserDataResponseVersion1Message"},
+
+ /* Callmanager -> Station */
+ /* 0x0000, 0x0003? */
+ {0x0081, "RegisterAckMessage"},
+ {0x0082, "StartToneMessage"},
+ {0x0083, "StopToneMessage"},
+ {0x0085, "SetRingerMessage"},
+ {0x0086, "SetLampMessage"},
+ {0x0087, "SetHkFDetectMessage"},
+ {0x0088, "SetSpeakerModeMessage"},
+ {0x0089, "SetMicroModeMessage"},
+ {0x008A, "StartMediaTransmission"},
+ {0x008B, "StopMediaTransmission"},
+ {0x008C, "StartMediaReception"},
+ {0x008D, "StopMediaReception"},
+ {0x008F, "CallInfoMessage"},
+ {0x0090, "ForwardStatMessage"},
+ {0x0091, "SpeedDialStatMessage"},
+ {0x0092, "LineStatMessage"},
+ {0x0093, "ConfigStatMessage"},
+ {0x0094, "DefineTimeDate"},
+ {0x0095, "StartSessionTransmission"},
+ {0x0096, "StopSessionTransmission"},
+ {0x0097, "ButtonTemplateMessage"},
+ {0x0098, "VersionMessage"},
+ {0x0099, "DisplayTextMessage"},
+ {0x009A, "ClearDisplay"},
+ {0x009B, "CapabilitiesReqMessage"},
+ {0x009C, "EnunciatorCommandMessage"},
+ {0x009D, "RegisterRejectMessage"},
+ {0x009E, "ServerResMessage"},
+ {0x009F, "Reset"},
+ {0x0100, "KeepAliveAckMessage"},
+ {0x0101, "StartMulticastMediaReception"},
+ {0x0102, "StartMulticastMediaTransmission"},
+ {0x0103, "StopMulticastMediaReception"},
+ {0x0104, "StopMulticastMediaTransmission"},
+ {0x0105, "OpenReceiveChannel"},
+ {0x0106, "CloseReceiveChannel"},
+ {0x0107, "ConnectionStatisticsReq"},
+ {0x0108, "SoftKeyTemplateResMessage"},
+ {0x0109, "SoftKeySetResMessage"},
+ {0x0110, "SelectSoftKeysMessage"},
+ {0x0111, "CallStateMessage"},
+ {0x0112, "DisplayPromptStatusMessage"},
+ {0x0113, "ClearPromptStatusMessage"},
+ {0x0114, "DisplayNotifyMessage"},
+ {0x0115, "ClearNotifyMessage"},
+ {0x0116, "ActivateCallPlaneMessage"},
+ {0x0117, "DeactivateCallPlaneMessage"},
+ {0x0118, "UnregisterAckMessage"},
+ {0x0119, "BackSpaceReqMessage"},
+ {0x011A, "RegisterTokenAck"},
+ {0x011B, "RegisterTokenReject"},
+
+ {0x011C, "StartMediaFailureDetection"},
+ {0x011D, "DialedNumberMessage"},
+ {0x011E, "UserToDeviceDataMessage"},
+ {0x011F, "FeatureStatMessage"},
+ {0x0120, "DisplayPriNotifyMessage"},
+ {0x0121, "ClearPriNotifyMessage"},
+ {0x0122, "StartAnnouncementMessage"},
+ {0x0123, "StopAnnouncementMessage"},
+ {0x0124, "AnnouncementFinishMessage"},
+ {0x0127, "NotifyDtmfToneMessage"},
+ {0x0128, "SendDtmfToneMessage"},
+ {0x0129, "SubscribeDtmfPayloadReqMessage"},
+ {0x012A, "SubscribeDtmfPayloadResMessage"},
+ {0x012B, "SubscribeDtmfPayloadErrMessage"},
+ {0x012C, "UnSubscribeDtmfPayloadReqMessage"},
+ {0x012D, "UnSubscribeDtmfPayloadResMessage"},
+ {0x012E, "UnSubscribeDtmfPayloadErrMessage"},
+ {0x012F, "ServiceURLStatMessage"},
+ {0x0130, "CallSelectStatMessage"},
+ {0x0131, "OpenMultiMediaChannelMessage"},
+ {0x0132, "StartMultiMediaTransmission"},
+ {0x0133, "StopMultiMediaTransmission"},
+ {0x0134, "MiscellaneousCommandMessage"},
+ {0x0135, "FlowControlCommandMessage"},
+ {0x0136, "CloseMultiMediaReceiveChannel"},
+ {0x0137, "CreateConferenceReqMessage"},
+ {0x0138, "DeleteConferenceReqMessage"},
+ {0x0139, "ModifyConferenceReqMessage"},
+ {0x013A, "AddParticipantReqMessage"},
+ {0x013B, "DropParticipantReqMessage"},
+ {0x013C, "AuditConferenceReqMessage"},
+ {0x013D, "AuditParticipantReqMessage"},
+ {0x013F, "UserToDeviceDataVersion1Message"},
+
+ {0 , NULL} /* terminator */
+};
+
+/*
+ * Device type to text conversion table
+ */
+static const value_string deviceTypes[] = {
+ {1 , "30SPplus"},
+ {2 , "12SPplus"},
+ {3 , "12SP"},
+ {4 , "12"},
+ {5 , "30VIP"},
+ {6 , "Telecaster"},
+ {7 , "TelecasterMgr"},
+ {8 , "TelecasterBus"},
+ {9 , "Polycom"},
+ {10 , "VGC"},
+ {12 , "ATA"},
+ {20 , "Virtual30SPplus"},
+ {21 , "PhoneApplication"},
+ {30 , "AnalogAccess"},
+ {40 , "DigitalAccessPRI"},
+ {41 , "DigitalAccessT1"},
+ {42 , "DigitalAccessTitan2"},
+ {43 , "DigitalAccessLennon"},
+ {47 , "AnalogAccessElvis"},
+ {50 , "ConferenceBridge"},
+ {51 , "ConferenceBridgeYoko"},
+ {52 , "ConferenceBridgeDixieLand"},
+ {53 , "ConferenceBridgeSummit"},
+ {60 , "H225"},
+ {61 , "H323Phone"},
+ {62 , "H323Trunk"},
+ {70 , "MusicOnHold"},
+ {71 , "Pilot"},
+ {72 , "TapiPort"},
+ {73 , "TapiRoutePoint"},
+ {80 , "VoiceInBox"},
+ {81 , "VoiceInboxAdmin"},
+ {82 , "LineAnnunciator"},
+ {83 , "SoftwareMtpDixieLand"},
+ {84 , "CiscoMediaServer"},
+ {85 , "ConferenceBridgeFlint"},
+ {90 , "RouteList"},
+ {100, "LoadSimulator"},
+ {110, "MediaTerminationPoint"},
+ {111, "MediaTerminationPointYoko"},
+ {112, "MediaTerminationPointDixieLand"},
+ {113, "MediaTerminationPointSummit"},
+ {120, "MGCPStation"},
+ {121, "MGCPTrunk"},
+ {122, "RASProxy"},
+ {125, "Trunk"},
+ {126, "Annunciator"},
+ {127, "MonitorBridge"},
+ {128, "Recorder"},
+ {129, "MonitorBridgeYoko"},
+ {131, "SipTrunk"},
+ {254, "UnknownMGCPGateway"},
+ {255, "NotDefined"},
+ { 0 , NULL}
+};
+
+/*
+ * keypad button -> text conversion
+ */
+static const value_string keypadButtons[] = {
+ {0x0 , "Zero"},
+ {0x1 , "One"},
+ {0x2 , "Two"},
+ {0x3 , "Three"},
+ {0x4 , "Four"},
+ {0x5 , "Five"},
+ {0x6 , "Six"},
+ {0x7 , "Seven"},
+ {0x8 , "Eight"},
+ {0x9 , "Nine"},
+ {0xa , "A"},
+ {0xb , "B"},
+ {0xc , "C"},
+ {0xd , "D"},
+ {0xe , "Star"},
+ {0xf , "Pound"},
+ {0 , NULL}
+};
+
+static const value_string deviceStimuli[] = {
+ {1 , "LastNumberRedial"},
+ {2 , "SpeedDial"},
+ {3 , "Hold"},
+ {4 , "Transfer"},
+ {5 , "ForwardAll"},
+ {6 , "ForwardBusy"},
+ {7 , "ForwardNoAnswer"},
+ {8 , "Display"},
+ {9 , "Line"},
+ {0xa , "T120Chat"},
+ {0xb , "T120Whiteboard"},
+ {0xc , "T120ApplicationSharing"},
+ {0xd , "T120FileTransfer"},
+ {0xe , "Video"},
+ {0xf , "VoiceMail"},
+ {0x10 , "AutoAnswerRelease"},
+ {0x11 , "AutoAnswer"},
+ {0x12 , "Select"},
+ {0x13 , "Privacy"},
+ {0x14 , "ServiceURL"},
+ {0x1B , "MaliciousCall"},
+ {0x21 , "GenericAppB1"},
+ {0x22 , "GenericAppB2"},
+ {0x23 , "GenericAppB3"},
+ {0x24 , "GenericAppB4"},
+ {0x25 , "GenericAppB5"},
+ {0x7b , "MeetMeConference"},
+ {0x7d , "Conference=0x7d"},
+ {0x7e , "CallPark=0x7e"},
+ {0x7f , "CallPickup"},
+ {0x80 , "GroupCallPickup=80"},
+ {0,NULL}
+};
+
+
+/* Note i'm only using 7 later on cuz i'm lazy ;) */
+#define DeviceMaxCapabilities 18 /* max capabilities allowed in Cap response message */
+
+static const value_string mediaPayloads[] = {
+ {1 , "Non-standard codec"},
+ {2 , "G.711 A-law 64k"},
+ {3 , "G.711 A-law 56k"},
+ {4 , "G.711 u-law 64k"},
+ {5 , "G.711 u-law 56k"},
+ {6 , "G.722 64k"},
+ {7 , "G.722 56k"},
+ {8 , "G.722 48k"},
+ {9 , "G.723.1"},
+ {10 , "G.728"},
+ {11 , "G.729"},
+ {12 , "G.729 Annex A"},
+ {13 , "IS11172 AudioCap"}, /* IS11172 is an ISO MPEG standard */
+ {14 , "IS13818 AudioCap"}, /* IS13818 is an ISO MPEG standard */
+ {15 , "G.729 Annex B"},
+ {16 , "G.729 Annex A+Annex B"},
+ {18 , "GSM Full Rate"},
+ {19 , "GSM Half Rate"},
+ {20 , "GSM Enhanced Full Rate"},
+ {25 , "Wideband 256k"},
+ {32 , "Data 64k"},
+ {33 , "Data 56k"},
+ {80 , "GSM"},
+ {81 , "ActiveVoice"},
+ {82 , "G.726 32K"},
+ {83 , "G.726 24K"},
+ {84 , "G.726 16K"},
+ {85 , "G.729B"},
+ {86 , "G.729B Low Complexity"},
+ {100 , "H261"},
+ {101 , "H263"},
+ {102 , "Vieo"},
+ {105 , "T120"},
+ {106 , "H224"},
+ {257 , "RFC2833_DynPayload"},
+ {0 , NULL}
+};
+
+static const value_string alarmSeverities[] = {
+ {0 , "Critical"},
+ {1 , "Warning"},
+ {2 , "Informational"},
+ {4 , "Unknown"},
+ {7 , "Major"},
+ {8 , "Minor"},
+ {10 , "Marginal"},
+ {20 , "TraceInfo"},
+ {0 , NULL}
+};
+
+static const value_string multicastMediaReceptionStatus[] = {
+ {0 , "Ok"},
+ {1 , "Error"},
+ {0 , NULL}
+};
+
+static const value_string openReceiveChanStatus[] = {
+ {0 , "orcOk"},
+ {1 , "orcError"},
+ {0 , NULL}
+};
+
+
+static const value_string statsProcessingTypes[] = {
+ {0 , "clearStats"},
+ {1 , "doNotClearStats"},
+ {0 , NULL}
+};
+
+#define SkMaxSoftKeyCount 18 /* this value should be the same as the max soft key value */
+static const value_string softKeyEvents[] = {
+ {1 , "Redial"},
+ {2 , "NewCall"},
+ {3 , "Hold"},
+ {4 , "Trnsfer"},
+ {5 , "CFwdAll"},
+ {6 , "CFwdBusy"},
+ {7 , "CFwdNoAnswer"},
+ {8 , "BackSpace"},
+ {9 , "EndCall"},
+ {10 , "Resume"},
+ {11 , "Answer"},
+ {12 , "Info"},
+ {13 , "Confrn"},
+ {14 , "Park"},
+ {15 , "Join"},
+ {16 , "MeetMeConfrn"},
+ {17 , "CallPickUp"},
+ {18 , "GrpCallPickUp"},
+ {0 , NULL}
+};
+
+/* Define info index for each softkey event for Telecaster station. */
+static const value_string softKeyIndexes[] = {
+ {301 , "RedialInfoIndex"},
+ {302 , "NewCallInfoIndex"},
+ {303 , "HoldInfoIndex"},
+ {304 , "TrnsferInfoIndex"},
+ {305 , "CFwdAllInfoIndex"},
+ {306 , "CFwdBusyInfoIndex"}, /* not used yet */
+ {307 , "CFwdNoAnswerInfoIndex"}, /* not used yet */
+ {308 , "BackSpaceInfoIndex"},
+ {309 , "EndCallInfoIndex"},
+ {310 , "ResumeInfoIndex"},
+ {311 , "AnswerInfoIndex"},
+ {312 , "InfoInfoIndex"},
+ {313 , "ConfrnInfoIndex"},
+ {314 , "ParkInfoIndex"},
+ {315 , "JoinInfoIndex"},
+ {316 , "MeetMeConfrnInfoIndex"},
+ {317 , "CallPickUpInfoIndex"},
+ {318 , "GrpCallPickUpInfoIndex"},
+ {0 , NULL}
+};
+
+
+static const value_string buttonDefinitions[] = {
+ {1 , "LastNumberRedial"},
+ {2 , "SpeedDial"},
+ {3 , "Hold"},
+ {4 , "Transfer"},
+ {5 , "ForwardAll"},
+ {6 , "ForwardBusy"},
+ {7 , "ForwardNoAnswer"},
+ {8 , "Display"},
+ {9 , "Line"},
+ {0xa , "T120Chat"},
+ {0xb , "T120Whiteboard"},
+ {0xc , "T120ApplicationSharing"},
+ {0xd , "T120FileTransfer"},
+ {0xe , "Video"},
+ {0x10 , "AnswerRelease"},
+ {0xf0 , "Keypad"},
+ {0xfd , "AEC"},
+ {0xff , "Undefined"},
+ {0 , NULL}
+};
+
+#define StationTotalSoftKeySets 10 /* total number of the soft key sets */
+static const value_string keySetNames[] = {
+ {0 , "OnHook"},
+ {1 , "Connected"},
+ {2 , "OnHold"},
+ {3 , "RingIn"},
+ {4 , "OffHook"},
+ {5 , "Connected with transfer"},
+ {6 , "Digits after dialing first digit"},
+ {7 , "Connected with conference"},
+ {8 , "RingOut"},
+ {9 , "OffHook with features"},
+ {0 , NULL}
+};
+
+/* Define soft key labels for the Telecaster station */
+static const value_string softKeyLabel[] = {
+ {0 , "undefined"},
+ {1 , "Redial"},
+ {2 , "NewCall"},
+ {3 , "Hold"},
+ {4 , "Trnsfer"},
+ {5 , "CFwdAll"},
+ {6 , "CFwdBusy"},
+ {7 , "CFwdNoAnswer"},
+ {8 , "<<"},
+ {9 , "EndCall"},
+ {10 , "Resume"},
+ {11 , "Answer"},
+ {12 , "Info"},
+ {13 , "Confrn"},
+ {14 , "Park"},
+ {15 , "Join"},
+ {16 , "MeetMe"},
+ {17 , "PickUp"},
+ {18 , "GPickUp"},
+ {0 , NULL}
+};
+
+
+/*
+ * define lamp modes;
+ * lamp cadence is defined as follows
+ * Wink (on 80%) = 448msec on / 64msec off
+ * Flash (fast flash) = 32msec on / 32msec off
+ * Blink (on 50%) = 512msec on / 512msec off
+ * On (on steady)
+ */
+static const value_string stationLampModes[] = {
+ {0 , "Undefined"},
+ {0x1 , "Off"},
+ {0x2 , "On"},
+ {0x3 , "Wink"},
+ {0x4 , "Flash"},
+ {0x5 , "Blink"},
+ {0 , NULL}
+};
+
+/* Defined the Call States to be sent to the Telecaste station.
+ * These are NOT the call states used in CM internally. Instead,
+ * they are the call states sent from CM and understood by the Telecaster station
+ */
+static const value_string skinny_stationCallStates[] = {
+ {1 , "OffHook"},
+ {2 , "OnHook"},
+ {3 , "RingOut"},
+ {4 , "RingIn"},
+ {5 , "Connected"},
+ {6 , "Busy"},
+ {7 , "Congestion"},
+ {8 , "Hold"},
+ {9 , "CallWaiting"},
+ {10 , "CallTransfer"},
+ {11 , "CallPark"},
+ {12 , "Proceed"},
+ {13 , "CallRemoteMultiline"},
+ {14 , "InvalidNumber"},
+ {0 , NULL}
+};
+
+/* Defined Call Type */
+static const value_string skinny_callTypes[] = {
+ {1 , "InBoundCall"},
+ {2 , "OutBoundCall"},
+ {3 , "ForwardCall"},
+ {0 , NULL}
+};
+
+/*
+ * define station-playable tones;
+ * for tone definitions see SR-TSV-002275, "BOC Notes on the LEC Networks -- 1994"
+ */
+static const value_string skinny_deviceTones[] = {
+ {0 , "Silence"},
+ {1 , "Dtmf1"},
+ {2 , "Dtmf2"},
+ {3 , "Dtmf3"},
+ {4 , "Dtmf4"},
+ {5 , "Dtmf5"},
+ {6 , "Dtmf6"},
+ {7 , "Dtmf7"},
+ {8 , "Dtmf8"},
+ {9 , "Dtmf9"},
+ {0xa , "Dtmf0"},
+ {0xe , "DtmfStar"},
+ {0xf , "DtmfPound"},
+ {0x10 , "DtmfA"},
+ {0x11 , "DtmfB"},
+ {0x12 , "DtmfC"},
+ {0x13 , "DtmfD"},
+ {0x21 , "InsideDialTone"},
+ {0x22 , "OutsideDialTone"},
+ {0x23 , "LineBusyTone"},
+ {0x24 , "AlertingTone"},
+ {0x25 , "ReorderTone"},
+ {0x26 , "RecorderWarningTone"},
+ {0x27 , "RecorderDetectedTone"},
+ {0x28 , "RevertingTone"},
+ {0x29 , "ReceiverOffHookTone"},
+ {0x2a , "PartialDialTone"},
+ {0x2b , "NoSuchNumberTone"},
+ {0x2c , "BusyVerificationTone"},
+ {0x2d , "CallWaitingTone"},
+ {0x2e , "ConfirmationTone"},
+ {0x2f , "CampOnIndicationTone"},
+ {0x30 , "RecallDialTone"},
+ {0x31 , "ZipZip"},
+ {0x32 , "Zip"},
+ {0x33 , "BeepBonk"},
+ {0x34 , "MusicTone"},
+ {0x35 , "HoldTone"},
+ {0x36 , "TestTone"},
+ {0x37 , "DtMoniterWarningTone"},
+ {0x40 , "AddCallWaiting"},
+ {0x41 , "PriorityCallWait"},
+ {0x42 , "RecallDial"},
+ {0x43 , "BargIn"},
+ {0x44 , "DistinctAlert"},
+ {0x45 , "PriorityAlert"},
+ {0x46 , "ReminderRing"},
+ {0x47 , "PrecedenceRingBack"},
+ {0x48 , "PreemptionTone"},
+ {0x50 , "MF1"},
+ {0x51 , "MF2"},
+ {0x52 , "MF3"},
+ {0x53 , "MF4"},
+ {0x54 , "MF5"},
+ {0x55 , "MF6"},
+ {0x56 , "MF7"},
+ {0x57 , "MF8"},
+ {0x58 , "MF9"},
+ {0x59 , "MF0"},
+ {0x5a , "MFKP1"},
+ {0x5b , "MFST"},
+ {0x5c , "MFKP2"},
+ {0x5d , "MFSTP"},
+ {0x5e , "MFST3P"},
+ {0x5f , "MILLIWATT"},
+ {0x60 , "MILLIWATTTEST"},
+ {0x61 , "HIGHTONE"},
+ {0x62 , "FLASHOVERRIDE"},
+ {0x63 , "FLASH"},
+ {0x64 , "PRIORITY"},
+ {0x65 , "IMMEDIATE"},
+ {0x66 , "PREAMPWARN"},
+ {0x67 , "2105HZ"},
+ {0x68 , "2600HZ"},
+ {0x69 , "440HZ"},
+ {0x6a , "300HZ"},
+ {0x77 , "MLPP_PALA"},
+ {0x78 , "MLPP_ICA"},
+ {0x79 , "MLPP_VCA"},
+ {0x7A , "MLPP_BPA"},
+ {0x7B , "MLPP_BNEA"},
+ {0x7C , "MLPP_UPA"},
+ {0x7f , "NoTone"},
+ {0 , NULL}
+};
+
+/* define ring types */
+static const value_string skinny_ringTypes[] = {
+ {0x1 , "RingOff"},
+ {0x2 , "InsideRing"},
+ {0x3 , "OutsideRing"},
+ {0x4 , "FeatureRing"},
+ {0x5 , "FlashOnly"},
+ {0x6 , "PrecedenceRing"},
+ {0 , NULL}
+};
+
+static const value_string skinny_speakerModes[] = {
+ {1 , "SpeakerOn"},
+ {2 , "SpeakerOff"},
+ {0 , NULL}
+};
+
+static const value_string skinny_silenceSuppressionModes[] = {
+ {0 , "Media_SilenceSuppression_Off"},
+ {1 , "Media_SilenceSuppression_On"},
+ {0 , NULL}
+};
+
+static const value_string skinny_g723BitRates[] = {
+ {1 , "Media_G723BRate_5_3"},
+ {2 , "Media_G723BRate_6_4"},
+ {0 , NULL}
+};
+
+/* define device reset types */
+static const value_string skinny_deviceResetTypes[] = {
+ {1 , "DEVICE_RESET"},
+ {2 , "DEVICE_RESTART"},
+ {0 , NULL}
+};
+
+static const value_string skinny_echoCancelTypes[] = {
+ {0 , "Media_EchoCancellation_Off"},
+ {1 , "Media_EchoCancellation_On"},
+ {0 , NULL}
+};
+
+static const value_string skinny_deviceUnregisterStatusTypes[] = {
+ {0 , "Ok"},
+ {1 , "Error"},
+ {2 , "NAK"}, /* Unregister request is rejected for reaso n such as existence of a call */
+ {0 , NULL}
+};
+
+static const value_string skinny_createConfResults[] = {
+ {0 , "Ok"},
+ {1 , "ResourceNotAvailable"},
+ {2 , "ConferenceAlreadyExist"},
+ {3 , "SystemErr"},
+ {0 , NULL}
+};
+
+static const value_string skinny_modifyConfResults[] = {
+ {0 , "Ok"},
+ {1 , "ResourceNotAvailable"},
+ {2 , "ConferenceNotExist"},
+ {3 , "InvalidParameter"},
+ {4 , "MoreActiveCallsThanReserved"},
+ {5 , "InvalidResourceType"},
+ {6 , "SystemErr"},
+ {0 , NULL}
+};
+
+static const value_string skinny_deleteConfResults[] = {
+ {0 , "Ok"},
+ {1 , "ConferenceNotExist"},
+ {2 , "SystemErr"},
+ {0 , NULL}
+};
+
+static const value_string skinny_addParticipantResults[] = {
+ {0 , "Ok"},
+ {1 , "ResourceNotAvailable"},
+ {2 , "ConferenceNotExist"},
+ {3 , "DuplicateCallRef"},
+ {4 , "SystemErr"},
+ {0 , NULL}
+};
+
+static const value_string skinny_auditParticipantResults[] = {
+ {0 , "Ok"},
+ {1 , "ConferenceNotExist"},
+ {0 , NULL}
+};
+
+/* define hook flash detection mode */
+static const value_string skinny_hookFlashDetectModes[] = {
+ {1 , "HookFlashOn"},
+ {2 , "HookFlashOff"},
+ {0 , NULL}
+};
+
+/* define headset mode */
+static const value_string skinny_headsetModes[] = {
+ {1 , "HeadsetOn"},
+ {2 , "HeadsetOff"},
+ {0 , NULL}
+};
+
+/* define station microphone modes;
+ * Mic On - The speakerphone's microphone is turned on ONLY if the phone is in the "Speaker On (Off Hook)"
+ * state (see above).
+ * Mic Off - The microphone is turned off or, if it's not on, the command is ignored.
+ */
+static const value_string skinny_microphoneModes[] = {
+ {1 , "MicOn"},
+ {2 , "MicOff"},
+ {0 , NULL}
+};
+
+/* define the session request types */
+static const value_string skinny_sessionTypes[] = {
+ {1 , "Chat"},
+ {2 , "Whiteboard"},
+ {4 , "ApplicationSharing"},
+ {8 , "FileTransfer"},
+ {10 , "Video"},
+ {0 , NULL}
+};
+
+static const value_string skinny_mediaEnunciationTypes[] = {
+ {1 , "None"},
+ {2 , "CallPark"},
+ {0 , NULL}
+};
+
+static const value_string skinny_resourceTypes[] = {
+ {1 , "Conference"},
+ {2 , "IVR"},
+ {0 , NULL}
+};
+
+static const value_string skinny_sequenceFlags[] = {
+ {0 , "StationSequenceFirst"},
+ {1 , "StationSequenceMore"},
+ {2 , "StationSequenceLast"},
+ {0 , NULL}
+};
+
+static const value_string skinny_Layouts[] = {
+ {0 , "NoLayout"},
+ {1 , "OneByOne"},
+ {2 , "OneByTwo"},
+ {3 , "TwoByTwo"},
+ {4 , "TwoByTwo3Alt1"},
+ {5 , "TwoByTwo3Alt2"},
+ {6 , "ThreeByThree"},
+ {7 , "ThreeByThree6Alt1"},
+ {8 , "ThreeByThree6Alt2"},
+ {9 , "ThreeByThree4Alt1"},
+ {10 , "ThreeByThree4Alt2"},
+ {0 , NULL}
+};
+
+static const value_string skinny_transmitOrReceive[] = {
+ {1 , "Station_Receive_only"},
+ {2 , "Station_Transmit_only"},
+ {3 , "Station_Receive_Transmit"},
+ {0 , NULL}
+};
+
+static const value_string skinny_endOfAnnAck[] = {
+ {0 , "NoAnnAckRequired"},
+ {1 , "AnnAckRequired"},
+ {0 , NULL}
+};
+
+static const value_string skinny_annPlayMode[] = {
+ {0 , "AnnXmlConfigMode"},
+ {1 , "AnnOneShotMode"},
+ {2 , "AnnContinuousMode"},
+ {0 , NULL}
+};
+
+static const value_string skinny_annPlayStatus[] = {
+ {0 , "PlayToneOK"},
+ {1 , "PlayToneErr"},
+ {0 , NULL}
+};
+
+static const value_string skinny_miscCommandType[] = {
+ {0 , "videoFreezePicture"},
+ {1 , "videoFastUpdatePicture"},
+ {2 , "videoFastUpdateGOB"},
+ {3 , "videoFastUpdateMB"},
+ {4 , "lostPicture"},
+ {5 , "lostPartialPicture"},
+ {6 , "recoveryReferencePicture"},
+ {7 , "temporalSpatialTradeOff"},
+ {0 , NULL}
+};
+
+static const value_string skinny_formatTypes[] = {
+ {1 , "sqcif (128x96)"},
+ {2 , "qcif (176x144)"},
+ {3 , "cif (352x288)"},
+ {4 , "4cif (704x576)"},
+ {5 , "16cif (1408x1152)"},
+ {6 , "custom_base"},
+ {0 , NULL}
+};
+
+static const value_string cast_callSecurityStatusTypes[] = {
+ {0 , "CallSecurityStatusUnknown"},
+ {1 , "CallSecurityStatusNotAuthenticated"},
+ {2 , "CallSecurityStatusAuthenticated"},
+ {0 , NULL}
+};
+
+#define StationMaxDirnumSize 24 /* max size of calling or called party dirnum */
+#define StationMaxNameSize 40 /* max size of calling party's name */
+#define StationMaxDeviceNameSize 16 /* max size of station's IP name */
+#define StationMaxSpeedDials 10 /* max number of speed dial numbers allowed on a station */
+#define StationMaxVersionSize 16 /* max chars in version string */
+#define StationMaxButtonTemplateSize 42 /* max button template size */
+#define StationMaxDisplayTextSize 33 /* max text size in DisplayText message */
+#define StationMaxPorts 10 /* max number of ports on one device */
+#define StationDateTemplateSize 6 /* date template in the form M/D/Y, D/M/Y, ... */
+#define StationMaxServerNameSize 48 /* max size of server name */
+#define StationMaxServers 5 /* max servers */
+#define StationMaxDeviceDirnums 1024 /* max dir numbers per SCM device */
+#define StationMaxDirnums 64 /* max dir numbers per physical station (also used in db request msg); */
+#define StationMaxSoftKeyLabelSize 16 /* max label size in the message */
+#define StationMaxSoftKeyDefinition 32 /* max number of soft key definition in the message */
+#define StationMaxSoftKeySetDefinition 16 /* max number of soft key set definition in the message */
+#define StationMaxSoftKeyIndex 16 /* max number of soft key indices in a station soft key set */
+#define StationMaxDisplayPromptStatusSize 32 /* max status text size in the display status message */
+#define StationMaxDisplayNotifySize 32 /* max prompt text size in the display prompt message */
+#define StationMaxAlarmMessageSize 80 /* max size for an alarm message */
+#define StationMaxUserDeviceDataSize 2000 /* max size of user data between application and device */
+#define StationMaxConference 32
+#define AppConferenceIDSize 32
+#define AppDataSize 24
+#define MAX_CUSTOM_PICTURES 6
+#define MAX_LAYOUT_WITH_SAME_SERVICE 5
+#define MAX_SERVICE_TYPE 4
+#define DeviceMaxCapabilities 18 /* max capabilities allowed in Cap response message */
+#define StationMaxCapabilities DeviceMaxCapabilities
+#define StationMaxVideoCapabilities 10
+#define StationMaxDataCapabilities 5
+#define MAX_LEVEL_PREFERENCE 4
+#define MaxAnnouncementList 32
+#define StationMaxMonitorParties 16 /* Max Monitor Bridge whisper matrix parties, rm, M&R in Parche */
+#define StationMaxServiceURLSize 256 /* max number of service URLs length */
+#define MAX_PICTURE_FORMAT 5
+#define MAX_REFERENCE_PICTURE 4
+
+static void dissect_skinny(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/* Initialize the protocol and registered fields */
+static int proto_skinny = -1;
+static int hf_skinny_data_length = -1;
+static int hf_skinny_reserved = -1;
+static int hf_skinny_messageid = -1;
+static int hf_skinny_deviceName = -1;
+static int hf_skinny_stationUserId = -1;
+static int hf_skinny_stationInstance = -1;
+static int hf_skinny_deviceType = -1;
+static int hf_skinny_maxStreams = -1;
+static int hf_skinny_stationIpPort = -1;
+static int hf_skinny_stationKeypadButton = -1;
+static int hf_skinny_calledParty = -1;
+static int hf_skinny_stimulus = -1;
+static int hf_skinny_stimulusInstance = -1;
+static int hf_skinny_lineNumber = -1;
+static int hf_skinny_speedDialNumber = -1;
+static int hf_skinny_capCount = -1;
+static int hf_skinny_payloadCapability = -1;
+static int hf_skinny_maxFramesPerPacket = -1;
+static int hf_skinny_alarmSeverity = -1;
+static int hf_skinny_alarmParam1 = -1;
+static int hf_skinny_alarmParam2 = -1;
+static int hf_skinny_receptionStatus = -1;
+static int hf_skinny_passThruPartyID = -1;
+static int hf_skinny_ORCStatus = -1;
+static int hf_skinny_ipAddress = -1;
+static int hf_skinny_portNumber = -1;
+static int hf_skinny_statsProcessingType = -1;
+static int hf_skinny_callIdentifier = -1;
+static int hf_skinny_packetsSent = -1;
+static int hf_skinny_octetsSent = -1;
+static int hf_skinny_packetsRecv = -1;
+static int hf_skinny_octetsRecv = -1;
+static int hf_skinny_packetsLost = -1;
+static int hf_skinny_latency = -1;
+static int hf_skinny_jitter = -1;
+static int hf_skinny_directoryNumber = -1;
+static int hf_skinny_softKeyEvent = -1;
+static int hf_skinny_lineInstance = -1;
+static int hf_skinny_keepAliveInterval = -1;
+static int hf_skinny_dateTemplate = -1;
+static int hf_skinny_secondaryKeepAliveInterval = -1;
+static int hf_skinny_buttonOffset = -1;
+static int hf_skinny_buttonCount = -1;
+static int hf_skinny_totalButtonCount = -1;
+static int hf_skinny_buttonInstanceNumber = -1;
+static int hf_skinny_buttonDefinition = -1;
+static int hf_skinny_softKeyOffset = -1;
+static int hf_skinny_softKeyCount = -1;
+static int hf_skinny_totalSoftKeyCount = -1;
+static int hf_skinny_softKeyLabel = -1;
+static int hf_skinny_softKeySetOffset = -1;
+static int hf_skinny_softKeySetCount = -1;
+static int hf_skinny_totalSoftKeySetCount = -1;
+static int hf_skinny_softKeyTemplateIndex = -1;
+static int hf_skinny_softKeyInfoIndex = -1;
+static int hf_skinny_softKeySetDescription = -1;
+static int hf_skinny_softKeyMap = -1;
+static int hf_skinny_softKey0 = -1;
+static int hf_skinny_softKey1 = -1;
+static int hf_skinny_softKey2 = -1;
+static int hf_skinny_softKey3 = -1;
+static int hf_skinny_softKey4 = -1;
+static int hf_skinny_softKey5 = -1;
+static int hf_skinny_softKey6 = -1;
+static int hf_skinny_softKey7 = -1;
+static int hf_skinny_softKey8 = -1;
+static int hf_skinny_softKey9 = -1;
+static int hf_skinny_softKey10 = -1;
+static int hf_skinny_softKey11 = -1;
+static int hf_skinny_softKey12 = -1;
+static int hf_skinny_softKey13 = -1;
+static int hf_skinny_softKey14 = -1;
+static int hf_skinny_softKey15 = -1;
+static int hf_skinny_lampMode = -1;
+static int hf_skinny_messageTimeOutValue = -1;
+static int hf_skinny_displayMessage = -1;
+static int hf_skinny_lineDirNumber = -1;
+static int hf_skinny_lineFullyQualifiedDisplayName = -1;
+static int hf_skinny_speedDialDirNumber = -1;
+static int hf_skinny_speedDialDisplayName = -1;
+static int hf_skinny_dateYear = -1;
+static int hf_skinny_dateMonth = -1;
+static int hf_skinny_dayOfWeek = -1;
+static int hf_skinny_dateDay = -1;
+static int hf_skinny_dateHour = -1;
+static int hf_skinny_dateMinute = -1;
+static int hf_skinny_dateSeconds = -1;
+static int hf_skinny_dateMilliseconds = -1;
+static int hf_skinny_timeStamp = -1;
+static int hf_skinny_callState = -1;
+static int hf_skinny_deviceTone = -1;
+static int hf_skinny_callingPartyName = -1;
+static int hf_skinny_callingParty = -1;
+static int hf_skinny_calledPartyName = -1;
+static int hf_skinny_callType = -1;
+static int hf_skinny_originalCalledPartyName = -1;
+static int hf_skinny_originalCalledParty = -1;
+static int hf_skinny_ringType = -1;
+static int hf_skinny_speakerMode = -1;
+static int hf_skinny_remoteIpAddr = -1;
+static int hf_skinny_remotePortNumber = -1;
+static int hf_skinny_millisecondPacketSize = -1;
+static int hf_skinny_precedenceValue = -1;
+static int hf_skinny_silenceSuppression = -1;
+static int hf_skinny_g723BitRate = -1;
+static int hf_skinny_conferenceID = -1;
+static int hf_skinny_deviceResetType = -1;
+static int hf_skinny_echoCancelType = -1;
+static int hf_skinny_deviceUnregisterStatus = -1;
+static int hf_skinny_hookFlashDetectMode = -1;
+static int hf_skinny_detectInterval = -1;
+static int hf_skinny_microphoneMode = -1;
+static int hf_skinny_headsetMode = -1;
+static int hf_skinny_unknown = -1;
+static int hf_skinny_data = -1;
+static int hf_skinny_activeForward = -1;
+static int hf_skinny_forwardAllActive = -1;
+static int hf_skinny_forwardBusyActive = -1;
+static int hf_skinny_forwardNoAnswerActive = -1;
+static int hf_skinny_forwardNumber = -1;
+static int hf_skinny_serverName = -1;
+static int hf_skinny_numberLines = -1;
+static int hf_skinny_numberSpeedDials = -1;
+static int hf_skinny_userName = -1;
+static int hf_skinny_sessionType = -1;
+static int hf_skinny_version = -1;
+static int hf_skinny_mediaEnunciationType = -1;
+static int hf_skinny_serverIdentifier = -1;
+static int hf_skinny_serverListenPort = -1;
+static int hf_skinny_serverIpAddress = -1;
+static int hf_skinny_multicastIpAddress = -1;
+static int hf_skinny_multicastPort = -1;
+static int hf_skinny_tokenRejWaitTime = -1;
+static int hf_skinny_numberOfInServiceStreams = -1;
+static int hf_skinny_maxStreamsPerConf = -1;
+static int hf_skinny_numberOfOutOfServiceStreams = -1;
+static int hf_skinny_applicationID = -1;
+static int hf_skinny_serviceNum = -1;
+static int hf_skinny_serviceURLIndex = -1;
+static int hf_skinny_featureIndex = -1;
+static int hf_skinny_createConfResults = -1;
+static int hf_skinny_modifyConfResults = -1;
+static int hf_skinny_deleteConfResults = -1;
+static int hf_skinny_addParticipantResults = -1;
+static int hf_skinny_passThruData = -1;
+static int hf_skinny_last = -1;
+static int hf_skinny_numberOfEntries = -1;
+static int hf_skinny_auditParticipantResults = -1;
+static int hf_skinny_participantEntry = -1;
+static int hf_skinny_resourceTypes = -1;
+static int hf_skinny_numberOfReservedParticipants = -1;
+static int hf_skinny_numberOfActiveParticipants = -1;
+static int hf_skinny_appID = -1;
+static int hf_skinny_appData = -1;
+static int hf_skinny_appConfID = -1;
+static int hf_skinny_sequenceFlag = -1;
+static int hf_skinny_displayPriority = -1;
+static int hf_skinny_appInstanceID = -1;
+static int hf_skinny_routingID = -1;
+static int hf_skinny_audioCapCount = -1;
+static int hf_skinny_videoCapCount = -1;
+static int hf_skinny_dataCapCount = -1;
+static int hf_skinny_RTPPayloadFormat = -1;
+static int hf_skinny_customPictureFormatCount = -1;
+static int hf_skinny_pictureWidth = -1;
+static int hf_skinny_pictureHeight = -1;
+static int hf_skinny_pixelAspectRatio = -1;
+static int hf_skinny_clockConversionCode = -1;
+static int hf_skinny_clockDivisor = -1;
+static int hf_skinny_activeStreamsOnRegistration = -1;
+static int hf_skinny_maxBW = -1;
+static int hf_skinny_serviceResourceCount = -1;
+static int hf_skinny_layoutCount = -1;
+static int hf_skinny_layout = -1;
+static int hf_skinny_maxConferences = -1;
+static int hf_skinny_activeConferenceOnRegistration = -1;
+static int hf_skinny_transmitOrReceive = -1;
+static int hf_skinny_levelPreferenceCount = -1;
+static int hf_skinny_transmitPreference = -1;
+static int hf_skinny_format = -1;
+static int hf_skinny_maxBitRate = -1;
+static int hf_skinny_minBitRate = -1;
+static int hf_skinny_MPI = -1;
+static int hf_skinny_serviceNumber = -1;
+static int hf_skinny_temporalSpatialTradeOffCapability = -1;
+static int hf_skinny_stillImageTransmission = -1;
+static int hf_skinny_h263_capability_bitfield = -1;
+static int hf_skinny_annexNandWFutureUse = -1;
+static int hf_skinny_modelNumber = -1;
+static int hf_skinny_bandwidth = -1;
+static int hf_skinny_protocolDependentData = -1;
+static int hf_skinny_priority = -1;
+static int hf_skinny_payloadDtmf = -1;
+static int hf_skinny_featureID = -1;
+static int hf_skinny_featureTextLabel = -1;
+static int hf_skinny_featureStatus = -1;
+static int hf_skinny_notify = -1;
+static int hf_skinny_endOfAnnAck = -1;
+static int hf_skinny_annPlayMode = -1;
+static int hf_skinny_annPlayStatus = -1;
+static int hf_skinny_locale = -1;
+static int hf_skinny_country = -1;
+static int hf_skinny_matrixConfPartyID = -1;
+static int hf_skinny_hearingConfPartyMask = -1;
+static int hf_skinny_serviceURL = -1;
+static int hf_skinny_serviceURLDisplayName = -1;
+static int hf_skinny_callSelectStat = -1;
+static int hf_skinny_isConferenceCreator = -1;
+static int hf_skinny_payload_rfc_number = -1;
+static int hf_skinny_payloadType = -1;
+static int hf_skinny_bitRate = -1;
+static int hf_skinny_pictureFormatCount = -1;
+static int hf_skinny_confServiceNum = -1;
+static int hf_skinny_DSCPValue = -1;
+static int hf_skinny_miscCommandType = -1;
+static int hf_skinny_temporalSpatialTradeOff = -1;
+static int hf_skinny_firstGOB = -1;
+static int hf_skinny_numberOfGOBs = -1;
+static int hf_skinny_firstMB = -1;
+static int hf_skinny_numberOfMBs = -1;
+static int hf_skinny_pictureNumber = -1;
+static int hf_skinny_longTermPictureIndex = -1;
+static int hf_skinny_recoveryReferencePictureCount = -1;
+static int hf_skinny_transactionID = -1;
+static int hf_cast_lastRedirectingPartyName = -1;
+static int hf_cast_lastRedirectingParty = -1;
+static int hf_cast_cgpnVoiceMailbox = -1;
+static int hf_cast_cdpnVoiceMailbox = -1;
+static int hf_cast_originalCdpnVoiceMailbox = -1;
+static int hf_cast_lastRedirectingVoiceMailbox = -1;
+static int hf_cast_originalCdpnRedirectReason = -1;
+static int hf_cast_lastRedirectingReason = -1;
+static int hf_cast_callInstance = -1;
+static int hf_cast_callSecurityStatus = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_skinny = -1;
+static gint ett_skinny_tree = -1;
+static gint ett_skinny_softKeyMap = -1;
+
+/* desegmentation of SCCP */
+static gboolean skinny_desegment = TRUE;
+
+static dissector_handle_t data_handle;
+static dissector_handle_t rtp_handle=NULL;
+
+/* Get the length of a single SCCP PDU */
+static guint get_skinny_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint32 hdr_data_length;
+
+ /*
+ * Get the length of the SCCP packet.
+ */
+ hdr_data_length = tvb_get_letohl(tvb, offset);
+
+ /*
+ * That length doesn't include the length of the header itself;
+ * add that in.
+ */
+ return hdr_data_length + 8;
+}
+
+/* Dissect a single SCCP PDU */
+static void dissect_skinny_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+
+ /* Header fields */
+ guint32 hdr_data_length;
+ guint32 hdr_reserved;
+ guint32 data_messageid;
+ gchar *messageid_str;
+ /* guint32 data_size; */
+
+ guint i = 0;
+ guint t = 0;
+ int j = 0;
+ guint count;
+ int val;
+
+ guint32 capCount;
+ guint32 softKeyCount;
+ guint32 softKeySetCount;
+ guint16 validKeyMask;
+
+ /* Set up structures we will need to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *skinny_tree = NULL;
+ proto_item *ti_sub;
+ proto_tree *skinny_sub_tree;
+ proto_tree *skinny_sub_tree_sav;
+ proto_tree *skinny_sub_tree_sav_sav;
+
+ proto_item *skm = NULL;
+ proto_item *skm_tree = NULL;
+
+ hdr_data_length = tvb_get_letohl(tvb, offset);
+ hdr_reserved = tvb_get_letohl(tvb, offset+4);
+ data_messageid = tvb_get_letohl(tvb, offset+8);
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items. */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_skinny, tvb, offset, hdr_data_length+8, FALSE);
+ skinny_tree = proto_item_add_subtree(ti, ett_skinny);
+ proto_tree_add_uint(skinny_tree, hf_skinny_data_length, tvb, offset, 4, hdr_data_length);
+ proto_tree_add_uint(skinny_tree, hf_skinny_reserved, tvb, offset+4, 4, hdr_reserved);
+ }
+
+ messageid_str = val_to_str(data_messageid, message_id, "0x%08X (Unknown)");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, messageid_str);
+ }
+
+ if (tree) {
+ proto_tree_add_uint(skinny_tree, hf_skinny_messageid, tvb,offset+8, 4, data_messageid );
+ }
+
+ if (tree) {
+ switch(data_messageid) {
+
+ /* cases that do not need to be decoded */
+ case 0x0 : /* keepAlive */
+ break;
+
+ case 0x6 : /* offHook */
+ break;
+
+ case 0x7 : /* onHook */
+ break;
+
+ case 0x8 : /* hookFlash */
+ break;
+
+ case 0xc : /* configStateReqMessage */
+ break;
+
+ case 0xd : /* timeDateReqMessage */
+ break;
+
+ case 0xe : /* buttoneTemplateReqMessage */
+ break;
+
+ case 0xf : /* stationVersionReqMessage */
+ break;
+
+ case 0x12 : /* stationServerReqMessage */
+ break;
+
+ case 0x25 : /* softKeySetReqMessage */
+ break;
+
+ case 0x27 : /* unregisterMessage */
+ break;
+
+ case 0x28 : /* softKeyTemplateRequest */
+ break;
+
+ case 0x83 : /* stopTone */
+ break;
+
+ case 0x9a : /* clearDisplay */
+ break;
+
+ case 0x9b : /* capabilitiesReqMessage */
+ break;
+
+ case 0x100 : /* keepAliveAck */
+ break;
+
+ case 0x115 : /* clearNotifyDisplay */
+ break;
+
+ case 0x117 : /* deactivateCallPlane */
+ break;
+
+ case 0x11a : /* registerTokenAck */
+ break;
+
+ case 0x13C : /* AuditConferenceReqMessage */
+ break;
+
+ /*
+ ** cases that need decode
+ **
+ */
+
+ case 0x1 : /* register message */
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, StationMaxDeviceNameSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceType, tvb, offset+40, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_maxStreams, tvb, offset+44, 4, TRUE);
+ break;
+
+ case 0x2 : /* ipPortMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_stationIpPort, tvb, offset+12, 2, FALSE);
+ break;
+
+ case 0x3 : /* keyPadButtonMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_stationKeypadButton, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x4 : /* stationEnblocCallMessage -- This decode NOT verified*/
+ proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, offset+12, StationMaxDirnumSize, TRUE);
+ break;
+
+ case 0x5 : /* stationStimulusMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_stimulus, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_stimulusInstance, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x9 : /* stationForwardStatReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0xa : /* speedDialStatReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_speedDialNumber, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0xb : /* LineStatReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x10 : /* capabilitiesResMessage - VERIFIED AS IS*/
+ /* FIXME -- we are only going to decode the first 7 protocol fields for now cuz that's all it sent me
+ * on the phone i was working with. I should probably skip the struct decode and use a more piece
+ * type method using the capCount definition to control the decode loop
+ *
+ * basically changing StationMaxCapabilities definition
+ *
+ */
+ capCount = tvb_get_letohl(tvb, offset+12);
+ proto_tree_add_uint(skinny_tree, hf_skinny_capCount, tvb, offset+12, 4, capCount);
+ for (i = 0; i < capCount; i++) {
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+(i*16)+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket, tvb, offset+(i*16)+20, 2, TRUE);
+ /* FIXME -- decode the union under here as required, is always 0 on my equipment */
+ }
+ break;
+
+ case 0x11 : /* mediaPortList */
+ break;
+
+ case 0x20 : /* stationAlarmMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_alarmSeverity, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxAlarmMessageSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_alarmParam1, tvb, offset+96, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_alarmParam2, tvb, offset+100, 4, TRUE);
+ break;
+
+ case 0x21 : /* stationMulticastMediaReceptionAck - This decode NOT verified*/
+ proto_tree_add_item(skinny_tree, hf_skinny_receptionStatus, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x22 : /* stationOpenReceiveChannelAck */
+ proto_tree_add_item(skinny_tree, hf_skinny_ORCStatus, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_portNumber, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+24, 4, TRUE);
+ if((!pinfo->fd->flags.visited) && rtp_handle){
+ guint32 ipv4_address;
+ tvb_memcpy(tvb, (char*)&ipv4_address, offset+16, 4);
+ rtp_add_address(pinfo, (char *)&ipv4_address, tvb_get_letohl(tvb, offset+20), 0, "Skinny", pinfo->fd->num);
+ }
+ break;
+
+ case 0x23 : /* stationConnectionStatisticsRes */
+ proto_tree_add_item(skinny_tree, hf_skinny_directoryNumber, tvb, offset+12, StationMaxDirnumSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_statsProcessingType, tvb, offset+40, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_packetsSent, tvb, offset+44, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_octetsSent, tvb, offset+48, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_packetsRecv, tvb, offset+52, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_octetsRecv, tvb, offset+56, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_packetsLost, tvb, offset+60, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_jitter, tvb, offset+64, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_latency, tvb, offset+68, 4, TRUE);
+ break;
+
+ case 0x24 : /* offHookWithCgpn */
+ proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, offset+12,StationMaxDirnumSize, TRUE);
+ break;
+
+ case 0x26 : /* softKeyEventMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_softKeyEvent, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x29 : /* registerTokenREq */
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, 4, TRUE);
+ i = offset+12+StationMaxDeviceNameSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, i, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, i+4, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, i+8, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceType, tvb, i+12, 4, TRUE);
+ break;
+
+ case 0x2A : /* MediaTransmissionFailure */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_portNumber, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+28, 4, TRUE);
+ break;
+
+ case 0x2B : /* HeadsetStatusMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_headsetMode, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x2C : /* MediaResourceNotification */
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceType, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_numberOfInServiceStreams, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_maxStreamsPerConf, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_numberOfOutOfServiceStreams, tvb, offset+24, 4, TRUE);
+ break;
+
+ case 0x2D : /* RegisterAvailableLinesMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_numberLines, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x2E : /* DeviceToUserDataMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_applicationID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_transactionID, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, offset+28, 4, TRUE);
+ count = tvb_get_letohl( tvb, offset+28);
+ proto_tree_add_uint(skinny_tree, hf_skinny_data, tvb, offset+30, 1, count);
+ break;
+
+ case 0x2F : /* DeviceToUserDataResponseMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_applicationID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_transactionID, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, offset+28, 4, TRUE);
+ count = tvb_get_letohl( tvb, offset+28);
+ proto_tree_add_uint(skinny_tree, hf_skinny_data, tvb, offset+30, 1, count);
+ break;
+
+ case 0x30 : /* UpdateCapabilitiesMessage */
+ /* to do - this message is very large and will span multiple packets, it would be nice to someday */
+ /* find out a way to join the next packet and get the complete message to decode */
+ proto_tree_add_item(skinny_tree, hf_skinny_audioCapCount, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_videoCapCount, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_dataCapCount, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_RTPPayloadFormat, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_customPictureFormatCount, tvb, offset+28, 4, TRUE);
+ count = offset+32;
+ for ( i = 0; i < MAX_CUSTOM_PICTURES; i++ ) {
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 20, "customPictureFormat[%d]", i);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_pictureWidth, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_pictureHeight, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_pixelAspectRatio, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_clockConversionCode, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_clockDivisor, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 8, "confResources");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_activeStreamsOnRegistration, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_maxBW, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_serviceResourceCount, tvb, count, 4, TRUE);
+ count+= 4;
+ skinny_sub_tree_sav = skinny_sub_tree;
+ for ( i = 0; i < MAX_SERVICE_TYPE; i++ ) {
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 20, "serviceResource[%d]", i);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_layoutCount, tvb, count, 4, TRUE);
+ count+= 4;
+ skinny_sub_tree_sav_sav = skinny_sub_tree_sav;
+ for ( t = 0; t < MAX_LAYOUT_WITH_SAME_SERVICE; t++ ) {
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 20, "layouts[%d]", t);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_layout, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ skinny_sub_tree = skinny_sub_tree_sav_sav;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_serviceNum, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_maxStreams, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_maxConferences, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_activeConferenceOnRegistration, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ for ( i = 0; i < StationMaxCapabilities; i++ ) {
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 20, "audiocaps[%d]", i);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_payloadCapability, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_maxFramesPerPacket, tvb, count, 2, TRUE);
+ count+= 4;
+ /* skip past union it is only for G723 */
+ count+= 8;
+ }
+ for ( i = 0; i < StationMaxVideoCapabilities; i++ ) {
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 20, "vidCaps[%d]", i);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_payloadCapability, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_transmitOrReceive, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_levelPreferenceCount, tvb, count, 4, TRUE);
+ count+= 4;
+ skinny_sub_tree_sav = skinny_sub_tree;
+ for ( t = 0; t < MAX_LEVEL_PREFERENCE; t++ ) {
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 20, "levelPreference[%d]", t);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_transmitPreference, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_format, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_maxBitRate, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_minBitRate, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_MPI, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_serviceNumber, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ val = count;
+
+ /* H.261 */
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "h261VideoCapability");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_temporalSpatialTradeOffCapability, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_stillImageTransmission, tvb, count, 4, TRUE);
+ count+= 4;
+
+ /* H.263 */
+ count = val;
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "h263VideoCapability");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_h263_capability_bitfield, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_annexNandWFutureUse, tvb, count, 4, TRUE);
+ count+= 4;
+
+ /* Video */
+ count = val;
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "vieoVideoCapability");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_modelNumber, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_bandwidth, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ for ( i = 0; i < StationMaxDataCapabilities; i++ ) {
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 20, "dataCaps[%d]", i);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_payloadCapability, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_transmitOrReceive, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_protocolDependentData, tvb, count, 4, TRUE);
+ count+= 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_maxBitRate, tvb, count, 4, TRUE);
+ count+= 4;
+ }
+ break;
+
+ case 0x31 : /* OpenMultiMediaReceiveChannelAckMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_ORCStatus, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_portNumber, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+28, 4, TRUE);
+ break;
+
+ case 0x32 : /* ClearConferenceMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_serviceNum, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x33 : /* ServiceURLStatReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_serviceURLIndex, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x34 : /* FeatureStatReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_featureIndex, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x35 : /* CreateConferenceResMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_createConfResults, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, offset+20, 4, TRUE);
+ count = tvb_get_letohl( tvb, offset+20);
+ proto_tree_add_uint(skinny_tree, hf_skinny_passThruData, tvb, offset+24, 1, count);
+ break;
+
+ case 0x36 : /* DeleteConferenceResMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_deleteConfResults, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x37 : /* ModifyConferenceResMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_createConfResults, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, offset+20, 4, TRUE);
+ count = tvb_get_letohl( tvb, offset+20);
+ proto_tree_add_uint(skinny_tree, hf_skinny_passThruData, tvb, offset+24, 1, count);
+ break;
+
+ case 0x38 : /* AddParticipantResMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_addParticipantResults, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x39 : /* AuditConferenceResMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_last, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_numberOfEntries, tvb, offset+16, 4, TRUE);
+ count = offset+20;
+ for ( i = 0; i < StationMaxConference; i++ ) {
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_resourceTypes, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_numberOfReservedParticipants, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_numberOfActiveParticipants, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_appID, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_uint(skinny_tree, hf_skinny_appConfID, tvb, count, 1, AppConferenceIDSize);
+ count += AppConferenceIDSize;
+ proto_tree_add_uint(skinny_tree, hf_skinny_appData, tvb, count, 1, AppDataSize);
+ count += AppDataSize;
+ }
+ break;
+
+ case 0x40 : /* AuditParticipantResMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_auditParticipantResults, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_last, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_numberOfEntries, tvb, offset+24, 4, TRUE);
+ count = tvb_get_letohl( tvb, offset+24);
+ for ( i = 0; i < count; i++ ) {
+ proto_tree_add_item(skinny_tree, hf_skinny_participantEntry, tvb, offset+28+(i*4), 4, TRUE);
+ }
+ break;
+
+ case 0x41 : /* DeviceToUserDataVersion1Message */
+ proto_tree_add_item(skinny_tree, hf_skinny_applicationID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_transactionID, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, offset+28, 4, TRUE);
+ count = tvb_get_letohl( tvb, offset+28);
+ proto_tree_add_item(skinny_tree, hf_skinny_sequenceFlag, tvb, offset+30, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_displayPriority, tvb, offset+34, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+38, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_appInstanceID, tvb, offset+42, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_routingID, tvb, offset+46, 4, TRUE);
+ proto_tree_add_uint(skinny_tree, hf_skinny_data, tvb, offset+50, 1, count);
+ break;
+
+ case 0x42 : /* DeviceToUserDataResponseVersion1Message */
+ proto_tree_add_item(skinny_tree, hf_skinny_applicationID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_transactionID, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, offset+28, 4, TRUE);
+ count = tvb_get_letohl( tvb, offset+28);
+ proto_tree_add_item(skinny_tree, hf_skinny_sequenceFlag, tvb, offset+30, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_displayPriority, tvb, offset+34, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+38, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_appInstanceID, tvb, offset+42, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_routingID, tvb, offset+46, 4, TRUE);
+ proto_tree_add_uint(skinny_tree, hf_skinny_data, tvb, offset+50, 1, count);
+ break;
+
+
+ /*
+ *
+ * Call manager -> client messages start here(ish)
+ *
+ */
+ case 0x81 : /* registerAck */
+ proto_tree_add_item(skinny_tree, hf_skinny_keepAliveInterval, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_dateTemplate, tvb, offset+16, StationDateTemplateSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_secondaryKeepAliveInterval, tvb, offset+24, 4, TRUE);
+ break;
+
+ case 0x82 : /* startTone */
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceTone, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x85 : /* setRingerMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_ringType, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x86 : /* setLampMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_stimulus, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_stimulusInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lampMode, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x87 : /* stationHookFlashDetectMode */
+ proto_tree_add_item(skinny_tree, hf_skinny_hookFlashDetectMode, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_detectInterval, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x88 : /* setSpeakerMode */
+
+ proto_tree_add_item(skinny_tree, hf_skinny_speakerMode, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x89 : /* setMicroMode */
+ proto_tree_add_item(skinny_tree, hf_skinny_microphoneMode, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x8a : /* startMediaTransmistion */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_remotePortNumber, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_precedenceValue, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_silenceSuppression, tvb, offset+40, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket, tvb, offset+44, 2, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+48, 4, TRUE);
+ if((!pinfo->fd->flags.visited) && rtp_handle){
+ guint32 ipv4_address;
+ tvb_memcpy(tvb, (char*)&ipv4_address, offset+20, 4);
+ rtp_add_address(pinfo, (char *)&ipv4_address, tvb_get_letohl(tvb, offset+24), 0, "Skinny", pinfo->fd->num);
+ }
+ break;
+
+ case 0x8b : /* stopMediaTransmission */
+
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x8c : /* startMediaReception */
+ break;
+
+ case 0x8d : /* stopMediaReception */
+ break;
+
+ case 0x8e : /* reservered */
+ break;
+
+ case 0x8f : /* callInfo */
+ i = offset+12;
+ proto_tree_add_item(skinny_tree, hf_skinny_callingPartyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_callingParty, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_calledPartyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_callType, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_originalCalledPartyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_originalCalledParty, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_cast_lastRedirectingPartyName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(skinny_tree, hf_cast_lastRedirectingParty, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_cast_originalCdpnRedirectReason, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_cast_lastRedirectingReason, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_cast_cgpnVoiceMailbox, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_cast_cdpnVoiceMailbox, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_cast_originalCdpnVoiceMailbox, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_cast_lastRedirectingVoiceMailbox, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_cast_callInstance, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_cast_callSecurityStatus, tvb, i, 4, TRUE);
+ i += 4;
+ val = tvb_get_letohl( tvb, i);
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 8, "partyPIRestrictionBits");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_text(skinny_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x01, 4*8, "Does RestrictCallingPartyName", "Doesn't RestrictCallingPartyName"));
+ proto_tree_add_text(skinny_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x02, 4*8, "Does RestrictCallingPartyNumber", "Doesn't RestrictCallingPartyNumber"));
+ proto_tree_add_text(skinny_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x04, 4*8, "Does RestrictCalledPartyName", "Doesn't RestrictCalledPartyName"));
+ proto_tree_add_text(skinny_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x08, 4*8, "Does RestrictCalledPartyNumber", "Doesn't RestrictCalledPartyNumber"));
+ proto_tree_add_text(skinny_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x10, 4*8, "Does RestrictOriginalCalledPartyName", "Doesn't RestrictOriginalCalledPartyName"));
+ proto_tree_add_text(skinny_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x20, 4*8, "Does RestrictOriginalCalledPartyNumber", "Doesn't RestrictOriginalCalledPartyNumber"));
+ proto_tree_add_text(skinny_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x40, 4*8, "Does RestrictLastRedirectPartyName", "Doesn't RestrictLastRedirectPartyName"));
+ proto_tree_add_text(skinny_sub_tree, tvb, i, 4,
+ decode_boolean_bitfield( val, 0x80, 4*8, "Does RestrictLastRedirectPartyNumber", "Doesn't RestrictLastRedirectPartyNumber"));
+ break;
+
+ case 0x90 : /* forwardStat */
+ proto_tree_add_item(skinny_tree, hf_skinny_activeForward, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_forwardAllActive, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, offset+24, StationMaxDirnumSize, TRUE);
+ i = offset+24+StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_forwardBusyActive, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, i, StationMaxDirnumSize, TRUE);
+ i += StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_forwardNoAnswerActive, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_forwardNumber, tvb, i, StationMaxDirnumSize, TRUE);
+ break;
+
+ case 0x91 : /* speedDialStatMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_speedDialNumber, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_speedDialDirNumber, tvb, offset+16, StationMaxDirnumSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_speedDialDisplayName, tvb, offset+40, StationMaxNameSize, TRUE);
+ break;
+
+ case 0x92 : /* lineStatMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_lineNumber, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineDirNumber, tvb, offset+16, StationMaxDirnumSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineFullyQualifiedDisplayName, tvb, offset+16+StationMaxDirnumSize, StationMaxNameSize, TRUE);
+ break;
+
+ case 0x93 : /* configStat */
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceName, tvb, offset+12, StationMaxDeviceNameSize, TRUE);
+ i = offset+12+StationMaxDeviceNameSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_stationUserId, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_stationInstance, tvb, i, 4, TRUE);
+ i += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_userName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_serverName, tvb, i, StationMaxNameSize, TRUE);
+ i += StationMaxNameSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_numberLines, tvb, i, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_numberSpeedDials, tvb, i+4, 4, TRUE);
+ break;
+
+ case 0x94 : /* stationDefineTimeDate */
+ proto_tree_add_item(skinny_tree, hf_skinny_dateYear, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_dateMonth, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_dayOfWeek, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_dateDay, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_dateHour, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_dateMinute, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_dateSeconds,tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_dateMilliseconds,tvb, offset+40, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_timeStamp, tvb, offset+44, 4, TRUE);
+ break;
+
+ case 0x95 : /* startSessionTransmission */
+ proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_sessionType, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x96 : /* stopSessionTransmission */
+ proto_tree_add_item(skinny_tree, hf_skinny_remoteIpAddr, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_sessionType, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x97 : /* buttonTemplateMessage */
+ /*
+ * FIXME
+ * This decode prints out oogly subtree maybe? or something besides the VALS...
+ * note to self: uint8 != 4 kk thx info ^_^
+ *
+ */
+ proto_tree_add_item(skinny_tree, hf_skinny_buttonOffset, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_buttonCount, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_totalButtonCount, tvb, offset+20, 4, TRUE);
+ for (i = 0; i < StationMaxButtonTemplateSize; i++) {
+ proto_tree_add_item(skinny_tree, hf_skinny_buttonInstanceNumber, tvb, offset+(i*2)+24, 1, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_buttonDefinition, tvb, offset+(i*2)+25, 1, TRUE);
+ }
+ break;
+
+ case 0x98 : /* version */
+ proto_tree_add_item(skinny_tree, hf_skinny_version, tvb, offset+12, StationMaxVersionSize, TRUE);
+ break;
+
+ case 0x99 : /* displayTextMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+12, StationMaxDisplayTextSize, TRUE);
+ break;
+
+ case 0x9c : /* enunciatorCommand */
+ proto_tree_add_item(skinny_tree, hf_skinny_mediaEnunciationType, tvb, offset+12, 4, TRUE);
+ for (i = 0; i < StationMaxDirnumSize; i++) {
+ proto_tree_add_item(skinny_tree, hf_skinny_unknown, tvb, offset+16+(i*4), 4, TRUE);
+ }
+ i = offset+16+StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_mediaEnunciationType, tvb, i, 4, TRUE);
+ break;
+
+ case 0x9d : /* stationRegisterReject */
+ proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+12, StationMaxDisplayTextSize, TRUE);
+ break;
+
+ case 0x9e : /* serverRes */
+ for (i = 0; i < StationMaxServers; i++) {
+ proto_tree_add_item(skinny_tree, hf_skinny_serverIdentifier, tvb, offset+12+(i*StationMaxServers), StationMaxServerNameSize, TRUE);
+ }
+ j = offset+12+(i*StationMaxServers);
+ for (i = 0; i < StationMaxServers; i++) {
+ proto_tree_add_item(skinny_tree, hf_skinny_serverListenPort, tvb, j+(i*4), 4, TRUE);
+ }
+ j = j+(i*4);
+ for (i = 0; i < StationMaxServers; i++) {
+ proto_tree_add_item(skinny_tree, hf_skinny_serverIpAddress, tvb, j+(i*4), 4, TRUE);
+ }
+ break;
+
+ case 0x9f : /* reset */
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceResetType, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x101 : /* startMulticastMediaReception*/
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_multicastIpAddress, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_multicastPort, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_echoCancelType, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+40, 4, TRUE);
+ break;
+
+ case 0x102 : /* startMulticateMediaTermination*/
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_multicastIpAddress, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_multicastPort, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_precedenceValue, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_silenceSuppression, tvb, offset+40, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_maxFramesPerPacket, tvb, offset+44, 2, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+48, 4, TRUE);
+ break;
+
+ case 0x103 : /* stopMulticastMediaReception*/
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x104 : /* stopMulticastMediaTermination*/
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x105 : /* open receive channel */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_echoCancelType, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+32, 4, TRUE);
+ break;
+
+ case 0x106 : /* closeReceiveChannel */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x107 : /* connectionStatisticsReq */
+
+ i = 12;
+ proto_tree_add_item(skinny_tree, hf_skinny_directoryNumber, tvb, i, StationMaxDirnumSize, TRUE);
+ i = 12 + StationMaxDirnumSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, i, 4, TRUE);
+ i = i+4;
+ proto_tree_add_item(skinny_tree, hf_skinny_statsProcessingType, tvb, i, 4, TRUE);
+ break;
+
+ case 0x108 : /* softkeyTemplateResMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_softKeyOffset, tvb, offset+12, 4, TRUE);
+ softKeyCount = tvb_get_letohl(tvb, offset+16);
+ proto_tree_add_uint(skinny_tree, hf_skinny_softKeyCount, tvb, offset+16, 4, softKeyCount);
+ proto_tree_add_item(skinny_tree, hf_skinny_totalSoftKeyCount, tvb, offset+20, 4, TRUE);
+ for (i = 0; ((i < StationMaxSoftKeyDefinition) && (i < softKeyCount)); i++){
+ proto_tree_add_item(skinny_tree, hf_skinny_softKeyLabel, tvb, offset+(i*20)+24, StationMaxSoftKeyLabelSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_softKeyEvent, tvb, offset+(i*20)+40, 4, TRUE);
+ }
+ /* there is more data here, but it doesn't make a whole lot of sense, I imagine
+ * it's just some not zero'd out stuff in the packet or...
+ */
+ break;
+
+ case 0x109 : /* softkeysetres */
+ proto_tree_add_item(skinny_tree, hf_skinny_softKeySetOffset, tvb, offset+12, 4, TRUE);
+ softKeySetCount = tvb_get_letohl(tvb, offset+16);
+ proto_tree_add_uint(skinny_tree, hf_skinny_softKeySetCount, tvb, offset+16, 4, softKeySetCount);
+ proto_tree_add_item(skinny_tree, hf_skinny_totalSoftKeySetCount, tvb, offset+20, 4, TRUE);
+ for (i = 0; ((i < StationMaxSoftKeySetDefinition) && (i < softKeySetCount)); i++) {
+ proto_tree_add_uint(skinny_tree, hf_skinny_softKeySetDescription, tvb, offset+24+(i*48) , 1, i);
+ for (j = 0; j < StationMaxSoftKeyIndex; j++) {
+ proto_tree_add_item(skinny_tree, hf_skinny_softKeyTemplateIndex, tvb, offset+24+(i*48)+j, 1, TRUE);
+ }
+ for (j = 0; j < StationMaxSoftKeyIndex; j++) {
+ proto_tree_add_item(skinny_tree, hf_skinny_softKeyInfoIndex, tvb, offset+24+(i*48)+StationMaxSoftKeyIndex+(j*2), 2, TRUE);
+ }
+ }
+ break;
+
+ case 0x110 : /* selectSoftKeys */
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_softKeySetDescription, tvb, offset+20, 4, TRUE);
+ validKeyMask = tvb_get_letohs(tvb, offset + 24);
+ skm = proto_tree_add_uint(skinny_tree, hf_skinny_softKeyMap, tvb, offset + 24, 1, validKeyMask);
+ skm_tree = proto_item_add_subtree(skm, ett_skinny_softKeyMap);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey0, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey1, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey2, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey3, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey4, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey5, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey6, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey7, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey8, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey9, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey10, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey11, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey12, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey13, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey14, tvb, offset + 24, 1, validKeyMask);
+ proto_tree_add_boolean(skm_tree, hf_skinny_softKey15, tvb, offset + 24, 1, validKeyMask);
+ break;
+
+ case 0x111 : /* callState */
+ proto_tree_add_item(skinny_tree, hf_skinny_callState, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x112 : /* displayPromptStatus */
+ proto_tree_add_item(skinny_tree, hf_skinny_messageTimeOutValue, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxDisplayPromptStatusSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+48, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+52, 4, TRUE);
+ break;
+
+ case 0x113: /* clearPrompt */
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance , tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x114 : /* displayNotify */
+ proto_tree_add_item(skinny_tree, hf_skinny_messageTimeOutValue, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_displayMessage, tvb, offset+16, StationMaxDisplayNotifySize , TRUE);
+ break;
+
+ case 0x116 : /* activateCallPlane */
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x118 : /* unregisterAckMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceUnregisterStatus, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x119 : /* backSpaceReq */
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x11B : /* registerTokenReject */
+ proto_tree_add_item(skinny_tree, hf_skinny_tokenRejWaitTime, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x11C : /* StartMediaFailureDetection */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_millisecondPacketSize, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_echoCancelType, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_g723BitRate, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+34, 4, TRUE);
+ break;
+
+ case 0x11D : /* DialedNumberMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_calledParty, tvb, offset+12, StationMaxDirnumSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16+StationMaxDirnumSize, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20+StationMaxDirnumSize, 4, TRUE);
+ break;
+
+ case 0x11E : /* UserToDeviceDataMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_applicationID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_transactionID, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, offset+28, 4, TRUE);
+ count = tvb_get_letohl( tvb, offset+28);
+ proto_tree_add_uint(skinny_tree, hf_skinny_data, tvb, offset+30, 1, count);
+ break;
+
+ case 0x11F : /* FeatureStatMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_featureIndex, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_featureID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_featureTextLabel, tvb, offset+20, StationMaxNameSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_featureStatus, tvb, offset+20+StationMaxNameSize, 4, TRUE);
+ break;
+
+ case 0x120 : /* DisplayPriNotifyMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_messageTimeOutValue, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_priority, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_notify, tvb, offset+16, StationMaxDisplayNotifySize, TRUE);
+ break;
+
+ case 0x121 : /* ClearPriNotifyMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_priority, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x122 : /* StartAnnouncementMessage */
+ count = offset+12;
+ for ( i = 0; i < MaxAnnouncementList; i++ ) {
+ proto_tree_add_item(skinny_tree, hf_skinny_locale, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_country, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceTone, tvb, count, 4, TRUE);
+ count += 4;
+ }
+ proto_tree_add_item(skinny_tree, hf_skinny_endOfAnnAck, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, count, 4, TRUE);
+ count += 4;
+
+ for ( i = 0; i < StationMaxMonitorParties; i++ ) {
+ proto_tree_add_item(skinny_tree, hf_skinny_matrixConfPartyID, tvb, count, 4, TRUE);
+ count += 4;
+ }
+ proto_tree_add_item(skinny_tree, hf_skinny_hearingConfPartyMask, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_tree, hf_skinny_annPlayMode, tvb, count, 4, TRUE);
+ break;
+
+ case 0x123 : /* StopAnnouncementMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x124 : /* AnnouncementFinishMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_annPlayStatus, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x127 : /* NotifyDtmfToneMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceTone, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x128 : /* SendDtmfToneMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_deviceTone, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x129 : /* SubscribeDtmfPayloadReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadDtmf, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x12A : /* SubscribeDtmfPayloadResMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadDtmf, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x12B : /* SubscribeDtmfPayloadErrMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadDtmf, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x12C : /* UnSubscribeDtmfPayloadReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadDtmf, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x12D : /* UnSubscribeDtmfPayloadResMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadDtmf, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x12E : /* UnSubscribeDtmfPayloadErrMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadDtmf, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x12F : /* ServiceURLStatMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_serviceURLIndex, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_serviceURL, tvb, offset+12, StationMaxServiceURLSize, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_serviceURLDisplayName, tvb, offset+12, StationMaxNameSize, TRUE);
+ break;
+
+ case 0x130 : /* CallSelectStatMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_callSelectStat, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x131 : /* OpenMultiMediaChannelMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payload_rfc_number, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadType, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_isConferenceCreator, tvb, offset+40, 4, TRUE);
+
+ /* add audio part of union */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 12, "audioParameters");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_millisecondPacketSize, tvb, offset+44, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_echoCancelType, tvb, offset+48, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_g723BitRate, tvb, offset+52, 4, TRUE);
+
+ /* add video part of union */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 30, "vidParameters");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_bitRate, tvb, offset+44, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_pictureFormatCount, tvb, offset+48, 4, TRUE);
+ skinny_sub_tree_sav = skinny_sub_tree;
+ count = offset+52;
+ for ( i = 0; i < MAX_PICTURE_FORMAT; i++ ) {
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8 * MAX_PICTURE_FORMAT, "pictureFormat[%d]", i);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_format, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_MPI, tvb, count, 4, TRUE);
+ count += 4;
+ }
+ skinny_sub_tree = skinny_sub_tree_sav;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_confServiceNum, tvb, count, 4, TRUE);
+ count += 4;
+
+ val = count;
+ /* add H261 part of union */
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "h261VideoCapability");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_temporalSpatialTradeOffCapability, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_stillImageTransmission, tvb, count, 4, TRUE);
+
+ /* add H263 part of union */
+ count = val;
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "h263VideoCapability");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_h263_capability_bitfield, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_annexNandWFutureUse, tvb, count, 4, TRUE);
+
+ /* add Vieo part of union */
+ count = val;
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "vieoVideoCapability");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_modelNumber, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_bandwidth, tvb, count, 4, TRUE);
+
+ /* add data part of union */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 8, "dataParameters");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_protocolDependentData, tvb, offset+44, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_maxBitRate, tvb, offset+48, 4, TRUE);
+ break;
+
+ case 0x132 : /* StartMultiMediaTransmission */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadCapability, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_ipAddress, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_portNumber, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payload_rfc_number, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_payloadType, tvb, offset+40, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_DSCPValue, tvb, offset+44, 4, TRUE);
+
+ /* add audio part of union */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 12, "audioParameters");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_millisecondPacketSize, tvb, offset+48, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_echoCancelType, tvb, offset+52, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_g723BitRate, tvb, offset+56, 4, TRUE);
+
+ /* add video part of union */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 30, "vidParameters");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_bitRate, tvb, offset+48, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_pictureFormatCount, tvb, offset+52, 4, TRUE);
+ skinny_sub_tree_sav = skinny_sub_tree;
+ count = offset+56;
+ for ( i = 0; i < MAX_PICTURE_FORMAT; i++ ) {
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8 * MAX_PICTURE_FORMAT, "pictureFormat[%d]", i);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_format, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_MPI, tvb, count, 4, TRUE);
+ count += 4;
+ }
+ skinny_sub_tree = skinny_sub_tree_sav;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_confServiceNum, tvb, count, 4, TRUE);
+ count += 4;
+
+ val = count;
+ /* add H261 part of union */
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "h261VideoCapability");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_temporalSpatialTradeOffCapability, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_stillImageTransmission, tvb, count, 4, TRUE);
+
+ /* add H263 part of union */
+ count = val;
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "h263VideoCapability");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_h263_capability_bitfield, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_annexNandWFutureUse, tvb, count, 4, TRUE);
+
+ /* add Vieo part of union */
+ count = val;
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "vieoVideoCapability");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_modelNumber, tvb, count, 4, TRUE);
+ count += 4;
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_bandwidth, tvb, count, 4, TRUE);
+
+ /* add data part of union */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 8, "dataParameters");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_protocolDependentData, tvb, offset+48, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_maxBitRate, tvb, offset+52, 4, TRUE);
+ break;
+
+ case 0x133 : /* StopMultiMediaTransmission */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x134 : /* MiscellaneousCommandMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_miscCommandType, tvb, offset+24, 4, TRUE);
+
+ /* show videoFreezePicture */
+ /* not sure of format */
+
+ /* show videoFastUpdatePicture */
+ /* not sure of format */
+
+ /* show videoFastUpdateGOB */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 8, "videoFastUpdateGOB");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_firstGOB, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_numberOfGOBs, tvb, offset+32, 4, TRUE);
+
+ /* show videoFastUpdateMB */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 8, "videoFastUpdateGOB");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_firstGOB, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_firstMB, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_numberOfMBs, tvb, offset+36, 4, TRUE);
+
+ /* show lostPicture */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 8, "lostPicture");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_pictureNumber, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_longTermPictureIndex, tvb, offset+32, 4, TRUE);
+
+ /* show lostPartialPicture */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 8, "lostPartialPicture");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_pictureNumber, tvb, offset+28, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_longTermPictureIndex, tvb, offset+32, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_firstMB, tvb, offset+36, 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_numberOfMBs, tvb, offset+40, 4, TRUE);
+
+ /* show recoveryReferencePicture */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 8, "recoveryReferencePicture");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_recoveryReferencePictureCount, tvb, offset+28, 4, TRUE);
+ skinny_sub_tree_sav = skinny_sub_tree;
+ for ( i = 0; i < MAX_REFERENCE_PICTURE; i++ ) {
+ ti_sub = proto_tree_add_text(skinny_sub_tree_sav, tvb, offset, 8, "recoveryReferencePicture[%d]", i);
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_pictureNumber, tvb, offset+32+(i*8), 4, TRUE);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_longTermPictureIndex, tvb, offset+36+(i*8), 4, TRUE);
+ }
+
+ /* show temporalSpatialTradeOff */
+ ti_sub = proto_tree_add_text(skinny_tree, tvb, offset, 4, "temporalSpatialTradeOff");
+ skinny_sub_tree = proto_item_add_subtree(ti_sub, ett_skinny_tree);
+ proto_tree_add_item(skinny_sub_tree, hf_skinny_temporalSpatialTradeOff, tvb, offset+28, 4, TRUE);
+ break;
+
+ case 0x135 : /* FlowControlCommandMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_maxBitRate, tvb, offset+24, 4, TRUE);
+ break;
+
+ case 0x136 : /* CloseMultiMediaReceiveChannel */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_passThruPartyID, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ break;
+
+ case 0x137 : /* CreateConferenceReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_numberOfReservedParticipants, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_resourceTypes, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_appID, tvb, offset+20, 4, TRUE);
+ count = offset+24;
+ proto_tree_add_uint(skinny_tree, hf_skinny_appConfID, tvb, count, 1, AppConferenceIDSize);
+ count += AppConferenceIDSize;
+ proto_tree_add_uint(skinny_tree, hf_skinny_appData, tvb, count, 1, AppDataSize);
+ count += AppDataSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, count, 4, TRUE);
+ val = tvb_get_letohl( tvb, count);
+ count += 4;
+ proto_tree_add_uint(skinny_tree, hf_skinny_passThruData, tvb, count, 1, val);
+ break;
+
+ case 0x138 : /* DeleteConferenceReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x139 : /* ModifyConferenceReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_numberOfReservedParticipants, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_appID, tvb, offset+20, 4, TRUE);
+ count = offset+24;
+ proto_tree_add_uint(skinny_tree, hf_skinny_appConfID, tvb, count, 1, AppConferenceIDSize);
+ count += AppConferenceIDSize;
+ proto_tree_add_uint(skinny_tree, hf_skinny_appData, tvb, count, 1, AppDataSize);
+ count += AppDataSize;
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, count, 4, TRUE);
+ val = tvb_get_letohl( tvb, count);
+ count += 4;
+ proto_tree_add_uint(skinny_tree, hf_skinny_passThruData, tvb, count, 1, val);
+ break;
+
+ case 0x13A : /* AddParticipantReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x13B : /* DropParticipantReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+16, 4, TRUE);
+ break;
+
+ case 0x13D : /* AuditParticipantReqMessage */
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+12, 4, TRUE);
+ break;
+
+ case 0x13F : /* UserToDeviceDataVersion1Message */
+ proto_tree_add_item(skinny_tree, hf_skinny_applicationID, tvb, offset+12, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_lineInstance, tvb, offset+16, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_callIdentifier, tvb, offset+20, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_transactionID, tvb, offset+24, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_data_length, tvb, offset+28, 4, TRUE);
+ count = tvb_get_letohl( tvb, offset+28);
+ proto_tree_add_item(skinny_tree, hf_skinny_sequenceFlag, tvb, offset+30, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_displayPriority, tvb, offset+34, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_conferenceID, tvb, offset+38, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_appInstanceID, tvb, offset+42, 4, TRUE);
+ proto_tree_add_item(skinny_tree, hf_skinny_routingID, tvb, offset+46, 4, TRUE);
+ proto_tree_add_uint(skinny_tree, hf_skinny_data, tvb, offset+50, 1, count);
+ break;
+
+
+ default:
+ break;
+ }
+ }
+}
+
+/* Code to actually dissect the packets */
+static void dissect_skinny(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /* The general structure of a packet: {IP-Header|TCP-Header|n*SKINNY}
+ * SKINNY-Packet: {Header(Size, Reserved)|Data(MessageID, Message-Data)}
+ */
+ /* Header fields */
+ volatile guint32 hdr_data_length;
+ guint32 hdr_reserved;
+
+ /* check, if this is really an SKINNY packet, they start with a length + 0 */
+
+ /* get relevant header information */
+ hdr_data_length = tvb_get_letohl(tvb, 0);
+ hdr_reserved = tvb_get_letohl(tvb, 4);
+
+ /* data_size = MIN(8+hdr_data_length, tvb_length(tvb)) - 0xC; */
+
+ if (hdr_data_length < 4 || hdr_reserved != 0) {
+ /* Not an SKINNY packet, just happened to use the same port */
+ call_dissector(data_handle,tvb, pinfo, tree);
+ return;
+ }
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SKINNY");
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Skinny Client Control Protocol");
+ }
+
+ tcp_dissect_pdus(tvb, pinfo, tree, skinny_desegment, 4,
+ get_skinny_pdu_len, dissect_skinny_pdu);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_skinny(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_skinny_data_length,
+ { "Data Length", "skinny.data_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of bytes in the data portion.",
+ HFILL }
+ },
+ { &hf_skinny_reserved,
+ { "Reserved", "skinny.reserved",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Reserved for future(?) use.",
+ HFILL }
+ },
+ /* FIXME: Enable use of message name ??? */
+ { &hf_skinny_messageid,
+ { "Message ID", "skinny.messageid",
+ FT_UINT32, BASE_HEX, VALS(message_id), 0x0,
+ "The function requested/done with this message.",
+ HFILL }
+ },
+
+ { &hf_skinny_deviceName,
+ { "DeviceName", "skinny.deviceName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The device name of the phone.",
+ HFILL }
+ },
+
+ { &hf_skinny_stationUserId,
+ { "StationUserId", "skinny.stationUserId",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The station user id.",
+ HFILL }
+ },
+
+ { &hf_skinny_stationInstance,
+ { "StationInstance", "skinny.stationInstance",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The stations instance.",
+ HFILL }
+ },
+
+ { &hf_skinny_deviceType,
+ { "DeviceType", "skinny.deviceType",
+ FT_UINT32, BASE_DEC, VALS(deviceTypes), 0x0,
+ "DeviceType of the station.",
+ HFILL }
+ },
+
+ { &hf_skinny_maxStreams,
+ { "MaxStreams", "skinny.maxStreams",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "32 bit unsigned integer indicating the maximum number of simultansous RTP duplex streams that the client can handle.",
+ HFILL }
+ },
+
+ { &hf_skinny_stationIpPort,
+ { "StationIpPort", "skinny.stationIpPort",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The station IP port",
+ HFILL }
+ },
+
+ { &hf_skinny_stationKeypadButton,
+ { "KeypadButton", "skinny.stationKeypadButton",
+ FT_UINT32, BASE_HEX, VALS(keypadButtons), 0x0,
+ "The button pressed on the phone.",
+ HFILL }
+ },
+
+ { &hf_skinny_calledParty,
+ { "CalledParty", "skinny.calledParty",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The number called.",
+ HFILL }
+ },
+
+ { &hf_skinny_stimulus,
+ { "Stimulus", "skinny.stimulus",
+ FT_UINT32, BASE_HEX, VALS(deviceStimuli), 0x0,
+ "Reason for the device stimulus message.",
+ HFILL }
+ },
+
+ { &hf_skinny_stimulusInstance,
+ { "StimulusInstance", "skinny.stimulusInstance",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The instance of the stimulus",
+ HFILL }
+ },
+
+ { &hf_skinny_lineNumber,
+ { "LineNumber", "skinny.lineNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Line Number",
+ HFILL }
+ },
+
+ { &hf_skinny_speedDialNumber,
+ { "SpeedDialNumber", "skinny.speedDialNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Which speed dial number",
+ HFILL }
+ },
+
+ { &hf_skinny_capCount,
+ { "CapCount", "skinny.capCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "How many capabilities",
+ HFILL }
+ },
+
+ { &hf_skinny_payloadCapability,
+ { "PayloadCapability", "skinny.payloadCapability",
+ FT_UINT32, BASE_DEC, VALS(mediaPayloads), 0x0,
+ "The payload capability for this media capability structure.",
+ HFILL }
+ },
+
+ { &hf_skinny_maxFramesPerPacket,
+ { "MaxFramesPerPacket", "skinny.maxFramesPerPacket",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Max frames per packet",
+ HFILL }
+ },
+
+ { &hf_skinny_alarmSeverity,
+ { "AlarmSeverity", "skinny.alarmSeverity",
+ FT_UINT32, BASE_DEC, VALS(alarmSeverities), 0x0,
+ "The severity of the reported alarm.",
+ HFILL }
+ },
+
+ { &hf_skinny_alarmParam1,
+ { "AlarmParam1", "skinny.alarmParam1",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "An as yet undecoded param1 value from the alarm message",
+ HFILL }
+ },
+
+ { &hf_skinny_alarmParam2,
+ { "AlarmParam2", "skinny.alarmParam2",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "This is the second alarm parameter i think it's an ip address",
+ HFILL }
+ },
+
+ { &hf_skinny_receptionStatus,
+ { "ReceptionStatus", "skinny.receptionStatus",
+ FT_UINT32, BASE_DEC, VALS(multicastMediaReceptionStatus), 0x0,
+ "The current status of the multicast media.",
+ HFILL }
+ },
+
+ { &hf_skinny_passThruPartyID,
+ { "PassThruPartyID", "skinny.passThruPartyID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The pass thru party id",
+ HFILL }
+ },
+
+ { &hf_skinny_ORCStatus,
+ { "OpenReceiveChannelStatus", "skinny.openReceiveChannelStatus",
+ FT_UINT32, BASE_DEC, VALS(openReceiveChanStatus), 0x0,
+ "The status of the opened receive channel.",
+ HFILL }
+ },
+
+ { &hf_skinny_ipAddress,
+ { "IP Address", "skinny.ipAddress",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "An IP address",
+ HFILL }
+ },
+
+ { &hf_skinny_portNumber,
+ { "Port Number", "skinny.portNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "A port number",
+ HFILL }
+ },
+
+ { &hf_skinny_statsProcessingType,
+ { "StatsProcessingType", "skinny.statsProcessingType",
+ FT_UINT32, BASE_DEC, VALS(statsProcessingTypes), 0x0,
+ "What do do after you send the stats.",
+ HFILL }
+ },
+
+ { &hf_skinny_callIdentifier,
+ { "Call Identifier", "skinny.callIdentifier",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Call identifier for this call.",
+ HFILL }
+ },
+
+ { &hf_skinny_packetsSent,
+ { "Packets Sent", "skinny.packetsSent",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Packets Sent during the call.",
+ HFILL }
+ },
+
+ { &hf_skinny_octetsSent,
+ { "Octets Sent", "skinny.octetsSent",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Octets sent during the call.",
+ HFILL }
+ },
+
+ { &hf_skinny_packetsRecv,
+ { "Packets Received", "skinny.packetsRecv",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Packets received during the call.",
+ HFILL }
+ },
+
+ { &hf_skinny_octetsRecv,
+ { "Octets Received", "skinny.octetsRecv",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Octets received during the call.",
+ HFILL }
+ },
+
+ { &hf_skinny_packetsLost,
+ { "Packets Lost", "skinny.packetsLost",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Packets lost during the call.",
+ HFILL }
+ },
+
+ { &hf_skinny_latency,
+ { "Latency(ms)", "skinny.latency",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Average packet latency during the call.",
+ HFILL }
+ },
+
+ { &hf_skinny_jitter,
+ { "Jitter", "skinny.jitter",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Average jitter during the call.",
+ HFILL }
+ },
+
+ { &hf_skinny_directoryNumber,
+ { "Directory Number", "skinny.directoryNumber",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The number we are reporting statistics for.",
+ HFILL }
+ },
+
+ { &hf_skinny_lineInstance,
+ { "Line Instance", "skinny.lineInstance",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The display call plane associated with this call.",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeyEvent,
+ { "SoftKeyEvent", "skinny.softKeyEvent",
+ FT_UINT32, BASE_DEC, VALS(softKeyEvents), 0x0,
+ "Which softkey event is being reported.",
+ HFILL }
+ },
+
+ { &hf_skinny_keepAliveInterval,
+ { "KeepAliveInterval", "skinny.keepAliveInterval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "How often are keep alives exchanges between the client and the call manager.",
+ HFILL }
+ },
+
+ { &hf_skinny_secondaryKeepAliveInterval,
+ { "SecondaryKeepAliveInterval", "skinny.secondaryKeepAliveInterval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "How often are keep alives exchanges between the client and the secondary call manager.",
+ HFILL }
+ },
+
+ { &hf_skinny_dateTemplate,
+ { "DateTemplate", "skinny.dateTemplate",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The display format for the date/time on the phone.",
+ HFILL }
+ },
+
+ { &hf_skinny_buttonOffset,
+ { "ButtonOffset", "skinny.buttonOffset",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Offset is the number of the first button referenced by this message.",
+ HFILL }
+ },
+
+ { &hf_skinny_buttonCount,
+ { "ButtonCount", "skinny.buttonCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of (VALID) button definitions in this message.",
+ HFILL }
+ },
+
+ { &hf_skinny_totalButtonCount,
+ { "TotalButtonCount", "skinny.totalButtonCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The total number of buttons defined for this phone.",
+ HFILL }
+ },
+
+ { &hf_skinny_buttonInstanceNumber,
+ { "InstanceNumber", "skinny.buttonInstanceNumber",
+ FT_UINT8, BASE_HEX, VALS(keypadButtons), 0x0,
+ "The button instance number for a button or the StationKeyPad value, repeats allowed.",
+ HFILL }
+ },
+
+ { &hf_skinny_buttonDefinition,
+ { "ButtonDefinition", "skinny.buttonDefinition",
+ FT_UINT8, BASE_HEX, VALS(buttonDefinitions), 0x0,
+ "The button type for this instance (ie line, speed dial, ....",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeyOffset,
+ { "SoftKeyOffset", "skinny.softKeyOffset",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The offset for the first soft key in this message.",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeyCount,
+ { "SoftKeyCount", "skinny.softKeyCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The number of valid softkeys in this message.",
+ HFILL }
+ },
+
+ { &hf_skinny_totalSoftKeyCount,
+ { "TotalSoftKeyCount", "skinny.totalSoftKeyCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The total number of softkeys for this device.",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeyLabel,
+ { "SoftKeyLabel", "skinny.softKeyLabel",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The text label for this soft key.",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeySetOffset,
+ { "SoftKeySetOffset", "skinny.softKeySetOffset",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The offset for the first soft key set in this message.",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeySetCount,
+ { "SoftKeySetCount", "skinny.softKeySetCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The number of valid softkey sets in this message.",
+ HFILL }
+ },
+
+ { &hf_skinny_totalSoftKeySetCount,
+ { "TotalSoftKeySetCount", "skinny.totalSoftKeySetCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The total number of softkey sets for this device.",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeyTemplateIndex,
+ { "SoftKeyTemplateIndex", "skinny.softKeyTemplateIndex",
+ FT_UINT8, BASE_DEC, VALS(softKeyEvents), 0x0,
+ "Array of size 16 8-bit unsigned ints containing an index into the softKeyTemplate.",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeyInfoIndex,
+ { "SoftKeyInfoIndex", "skinny.softKeyInfoIndex",
+ FT_UINT16, BASE_DEC, VALS(softKeyIndexes), 0x0,
+ "Array of size 16 16-bit unsigned integers containing an index into the soft key description information.",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeySetDescription,
+ { "SoftKeySet", "skinny.softKeySetDescription",
+ FT_UINT8, BASE_DEC, VALS(keySetNames), 0x0,
+ "A text description of what this softkey when this softkey set is displayed",
+ HFILL }
+ },
+
+ { &hf_skinny_softKeyMap,
+ { "SoftKeyMap","skinny.softKeyMap",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey0,
+ { "SoftKey0", "skinny.softKeyMap.0",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY0,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey1,
+ { "SoftKey1", "skinny.softKeyMap.1",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY1,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey2,
+ { "SoftKey2", "skinny.softKeyMap.2",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY2,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey3,
+ { "SoftKey3", "skinny.softKeyMap.3",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY3,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey4,
+ { "SoftKey4", "skinny.softKeyMap.4",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY4,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey5,
+ { "SoftKey5", "skinny.softKeyMap.5",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY5,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey6,
+ { "SoftKey6", "skinny.softKeyMap.6",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY6,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey7,
+ { "SoftKey7", "skinny.softKeyMap.7",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY7,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey8,
+ { "SoftKey8", "skinny.softKeyMap.8",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY8,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey9,
+ { "SoftKey9", "skinny.softKeyMap.9",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY9,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey10,
+ { "SoftKey10", "skinny.softKeyMap.10",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY10,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey11,
+ { "SoftKey11", "skinny.softKeyMap.11",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY11,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey12,
+ { "SoftKey12", "skinny.softKeyMap.12",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY12,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey13,
+ { "SoftKey13", "skinny.softKeyMap.13",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY13,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey14,
+ { "SoftKey14", "skinny.softKeyMap.14",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY14,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_softKey15,
+ { "SoftKey15", "skinny.softKeyMap.15",
+ FT_BOOLEAN, 16, TFS(&softKeyMapValues), SKINNY_SOFTKEY15,
+ "",
+ HFILL }
+ },
+
+ { &hf_skinny_lampMode,
+ { "LampMode", "skinny.lampMode",
+ FT_UINT32, BASE_DEC, VALS(stationLampModes), 0x0,
+ "The lamp mode",
+ HFILL }
+ },
+
+ { &hf_skinny_messageTimeOutValue,
+ { "Message Timeout", "skinny.messageTimeOutValue",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The timeout in seconds for this message",
+ HFILL }
+ },
+
+ { &hf_skinny_displayMessage,
+ { "DisplayMessage", "skinny.displayMessage",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The message displayed on the phone.",
+ HFILL }
+ },
+
+ { &hf_skinny_lineDirNumber,
+ { "Line Dir Number", "skinny.lineDirNumber",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The directory number for this line.",
+ HFILL }
+ },
+
+ { &hf_skinny_lineFullyQualifiedDisplayName,
+ { "DisplayName", "skinny.fqdn",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The full display name for this line.",
+ HFILL }
+ },
+
+ { &hf_skinny_speedDialDirNumber,
+ { "SpeedDial Number", "skinny.speedDialDirNum",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "the number to dial for this speed dial.",
+ HFILL }
+ },
+
+ { &hf_skinny_speedDialDisplayName,
+ { "SpeedDial Display", "skinny.speedDialDisplay",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The text to display for this speed dial.",
+ HFILL }
+ },
+
+ { &hf_skinny_dateYear,
+ { "Year", "skinny.year",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The current year",
+ HFILL }
+ },
+
+ { &hf_skinny_dateMonth,
+ { "Month", "skinny.month",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The current month",
+ HFILL }
+ },
+
+ { &hf_skinny_dayOfWeek,
+ { "DayOfWeek", "skinny.dayOfWeek",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The day of the week",
+ HFILL }
+ },
+
+ { &hf_skinny_dateDay,
+ { "Day", "skinny.day",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The day of the current month",
+ HFILL }
+ },
+
+ { &hf_skinny_dateHour,
+ { "Hour", "skinny.hour",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Hour of the day",
+ HFILL }
+ },
+
+ { &hf_skinny_dateMinute,
+ { "Minute", "skinny.minute",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Minute",
+ HFILL }
+ },
+
+ { &hf_skinny_dateSeconds,
+ { "Seconds", "skinny.dateSeconds",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Seconds",
+ HFILL }
+ },
+
+ { &hf_skinny_dateMilliseconds,
+ { "Milliseconds", "skinny.dateMilliseconds",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Milliseconds",
+ HFILL }
+ },
+
+ { &hf_skinny_timeStamp,
+ { "Timestamp", "skinny.timeStamp",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Time stamp for the call reference",
+ HFILL }
+ },
+ { &hf_skinny_callState,
+ { "CallState", "skinny.callState",
+ FT_UINT32, BASE_DEC, VALS(skinny_stationCallStates), 0x0,
+ "The D channel call state of the call",
+ HFILL }
+ },
+
+ { &hf_skinny_deviceTone,
+ { "Tone", "skinny.deviceTone",
+ FT_UINT32, BASE_HEX, VALS(skinny_deviceTones), 0x0,
+ "Which tone to play",
+ HFILL }
+ },
+
+ { &hf_skinny_callingPartyName,
+ { "Calling Party Name", "skinny.callingPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The passed name of the calling party.",
+ HFILL }
+ },
+
+ { &hf_skinny_callingParty,
+ { "Calling Party", "skinny.callingPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The passed number of the calling party.",
+ HFILL }
+ },
+
+ { &hf_skinny_calledPartyName,
+ { "Called Party Name", "skinny.calledPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The name of the party we are calling.",
+ HFILL }
+ },
+
+ { &hf_skinny_callType,
+ { "Call Type", "skinny.callType",
+ FT_UINT32, BASE_DEC, VALS(skinny_callTypes), 0x0,
+ "What type of call, in/out/etc",
+ HFILL }
+ },
+
+ { &hf_skinny_originalCalledPartyName,
+ { "Original Called Party Name", "skinny.originalCalledPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "name of the original person who placed the call.",
+ HFILL }
+ },
+
+ { &hf_skinny_originalCalledParty,
+ { "Original Called Party", "skinny.originalCalledParty",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The number of the original calling party.",
+ HFILL }
+ },
+
+ { &hf_skinny_ringType,
+ { "Ring Type", "skinny.ringType",
+ FT_UINT32, BASE_HEX, VALS(skinny_ringTypes), 0x0,
+ "What type of ring to play",
+ HFILL }
+ },
+
+ { &hf_skinny_speakerMode,
+ { "Speaker", "skinny.speakerMode",
+ FT_UINT32, BASE_HEX, VALS(skinny_speakerModes), 0x0,
+ "This message sets the speaker mode on/off",
+ HFILL }
+ },
+
+ { &hf_skinny_remoteIpAddr,
+ { "Remote Ip Address", "skinny.remoteIpAddr",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "The remote end ip address for this stream",
+ HFILL }
+ },
+
+ { &hf_skinny_remotePortNumber,
+ { "Remote Port", "skinny.remotePortNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The remote port number listening for this stream",
+ HFILL }
+ },
+
+ { &hf_skinny_millisecondPacketSize,
+ { "MS/Packet", "skinny.millisecondPacketSize",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The number of milliseconds of conversation in each packet",
+ HFILL }
+ },
+
+ { &hf_skinny_precedenceValue,
+ { "Precedence", "skinny.precedenceValue",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Precedence value",
+ HFILL }
+ },
+
+ { &hf_skinny_silenceSuppression,
+ { "Silence Suppression", "skinny.silenceSuppression",
+ FT_UINT32, BASE_HEX, VALS(skinny_silenceSuppressionModes), 0x0,
+ "Mode for silence suppression",
+ HFILL }
+ },
+
+ { &hf_skinny_g723BitRate,
+ { "G723 BitRate", "skinny.g723BitRate",
+ FT_UINT32, BASE_DEC, VALS(skinny_g723BitRates), 0x0,
+ "The G723 bit rate for this stream/JUNK if not g723 stream",
+ HFILL }
+ },
+
+ { &hf_skinny_conferenceID,
+ { "Conference ID", "skinny.conferenceID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The conference ID",
+ HFILL }
+ },
+
+ { &hf_skinny_deviceResetType,
+ { "Reset Type", "skinny.deviceResetType",
+ FT_UINT32, BASE_DEC, VALS(skinny_deviceResetTypes), 0x0,
+ "How the devices it to be reset (reset/restart)",
+ HFILL }
+ },
+
+ { &hf_skinny_echoCancelType,
+ { "Echo Cancel Type", "skinny.echoCancelType",
+ FT_UINT32, BASE_DEC, VALS(skinny_echoCancelTypes), 0x0,
+ "Is echo cancelling enabled or not",
+ HFILL }
+ },
+
+ { &hf_skinny_deviceUnregisterStatus,
+ { "Unregister Status", "skinny.deviceUnregisterStatus",
+ FT_UINT32, BASE_DEC, VALS(skinny_deviceUnregisterStatusTypes), 0x0,
+ "The status of the device unregister request (*CAN* be refused)",
+ HFILL }
+ },
+
+ { &hf_skinny_hookFlashDetectMode,
+ { "Hook Flash Mode", "skinny.hookFlashDetectMode",
+ FT_UINT32, BASE_DEC, VALS(skinny_hookFlashDetectModes), 0x0,
+ "Which method to use to detect that a hook flash has occured",
+ HFILL }
+ },
+
+ { &hf_skinny_detectInterval,
+ { "HF Detect Interval", "skinny.detectInterval",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The number of milliseconds that determines a hook flash has occured",
+ HFILL }
+ },
+
+ { &hf_skinny_headsetMode,
+ { "Headset Mode", "skinny.headsetMode",
+ FT_UINT32, BASE_DEC, VALS(skinny_headsetModes), 0x0,
+ "Turns on and off the headset on the set",
+ HFILL }
+ },
+
+ { &hf_skinny_microphoneMode,
+ { "Microphone Mode", "skinny.microphoneMode",
+ FT_UINT32, BASE_DEC, VALS(skinny_microphoneModes), 0x0,
+ "Turns on and off the microphone on the set",
+ HFILL }
+ },
+
+ { &hf_skinny_activeForward,
+ { "Active Forward", "skinny.activeForward",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "This is non zero to indicate that a forward is active on the line",
+ HFILL }
+ },
+
+ { &hf_skinny_forwardAllActive,
+ { "Forward All", "skinny.forwardAllActive",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Forward all calls",
+ HFILL }
+ },
+
+ { &hf_skinny_forwardBusyActive,
+ { "Forward Busy", "skinny.forwardBusyActive",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Forward calls when busy",
+ HFILL }
+ },
+
+ { &hf_skinny_forwardNoAnswerActive,
+ { "Forward NoAns", "skinny.forwardNoAnswerActive",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Forward only when no answer",
+ HFILL }
+ },
+
+ { &hf_skinny_forwardNumber,
+ { "Forward Number", "skinny.forwardNumber",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The number to forward calls to.",
+ HFILL }
+ },
+
+ { &hf_skinny_userName,
+ { "Username", "skinny.userName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Username for this device.",
+ HFILL }
+ },
+
+ { &hf_skinny_serverName,
+ { "Server Name", "skinny.serverName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The server name for this device.",
+ HFILL }
+ },
+
+ { &hf_skinny_numberLines,
+ { "Number of Lines", "skinny.numberLines",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "How many lines this device has",
+ HFILL }
+ },
+
+ { &hf_skinny_numberSpeedDials,
+ { "Number of SpeedDials", "skinny.numberSpeedDials",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The number of speed dials this device has",
+ HFILL }
+ },
+
+ { &hf_skinny_sessionType,
+ { "Session Type", "skinny.sessionType",
+ FT_UINT32, BASE_DEC, VALS(skinny_sessionTypes), 0x0,
+ "The type of this session.",
+ HFILL }
+ },
+
+ { &hf_skinny_version,
+ { "Version", "skinny.version",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Version.",
+ HFILL }
+ },
+
+ { &hf_skinny_mediaEnunciationType,
+ { "Enunciation Type", "skinny.mediaEnunciationType",
+ FT_UINT32, BASE_DEC, VALS(skinny_mediaEnunciationTypes), 0x0,
+ "No clue.",
+ HFILL }
+ },
+
+ { &hf_skinny_serverIdentifier,
+ { "Server Identifier", "skinny.serverIdentifier",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Server Identifier.",
+ HFILL }
+ },
+
+ { &hf_skinny_serverListenPort,
+ { "Server Port", "skinny.serverListenPort",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The port the server listens on.",
+ HFILL }
+ },
+
+ { &hf_skinny_serverIpAddress,
+ { "Server Ip Address", "skinny.serverIpAddress",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "The IP address for this server",
+ HFILL }
+ },
+
+ { &hf_skinny_multicastPort,
+ { "Multicast Port", "skinny.multicastPort",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The multicast port the to listens on.",
+ HFILL }
+ },
+
+ { &hf_skinny_multicastIpAddress,
+ { "Multicast Ip Address", "skinny.multicastIpAddress",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "The multicast address for this conference",
+ HFILL }
+ },
+
+ { &hf_skinny_tokenRejWaitTime,
+ { "Retry Wait Time", "skinny.tokenRejWaitTime",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "The time to wait before retrying this token request.",
+ HFILL }
+ },
+
+ { &hf_skinny_unknown,
+ { "Data", "skinny.unknown",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Place holder for unknown data.",
+ HFILL }
+ },
+
+ { &hf_skinny_data,
+ { "Data", "skinny.data",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "dataPlace holder for unknown data.",
+ HFILL }
+ },
+
+ { &hf_skinny_numberOfInServiceStreams,
+ { "NumberOfInServiceStreams", "skinny.numberOfInServiceStreams",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of in service streams.",
+ HFILL }
+ },
+
+ { &hf_skinny_maxStreamsPerConf,
+ { "MaxStreamsPerConf", "skinny.maxStreamsPerConf",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Maximum number of streams per conference.",
+ HFILL }
+ },
+
+ { &hf_skinny_numberOfOutOfServiceStreams,
+ { "NumberOfOutOfServiceStreams", "skinny.numberOfOutOfServiceStreams",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of out of service streams.",
+ HFILL }
+ },
+
+ { &hf_skinny_applicationID,
+ { "ApplicationID", "skinny.applicationID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Application ID.",
+ HFILL }
+ },
+
+ { &hf_skinny_transactionID,
+ { "TransactionID", "skinny.transactionID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Transaction ID.",
+ HFILL }
+ },
+
+ { &hf_skinny_serviceNum,
+ { "ServiceNum", "skinny.serviceNum",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ServiceNum.",
+ HFILL }
+ },
+
+ { &hf_skinny_serviceURLIndex,
+ { "serviceURLIndex", "skinny.serviceURLIndex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "serviceURLIndex.",
+ HFILL }
+ },
+
+ { &hf_skinny_featureIndex,
+ { "FeatureIndex", "skinny.featureIndex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "FeatureIndex.",
+ HFILL }
+ },
+
+ { &hf_skinny_createConfResults,
+ { "CreateConfResults", "skinny.createConfResults",
+ FT_UINT32, BASE_DEC, VALS(skinny_createConfResults), 0x0,
+ "The create conference results",
+ HFILL }
+ },
+
+ { &hf_skinny_modifyConfResults,
+ { "ModifyConfResults", "skinny.modifyConfResults",
+ FT_UINT32, BASE_DEC, VALS(skinny_modifyConfResults), 0x0,
+ "The modify conference results",
+ HFILL }
+ },
+
+ { &hf_skinny_deleteConfResults,
+ { "DeleteConfResults", "skinny.deleteConfResults",
+ FT_UINT32, BASE_DEC, VALS(skinny_deleteConfResults), 0x0,
+ "The delete conference results",
+ HFILL }
+ },
+
+ { &hf_skinny_addParticipantResults,
+ { "AddParticipantResults", "skinny.addParticipantResults",
+ FT_UINT32, BASE_DEC, VALS(skinny_addParticipantResults), 0x0,
+ "The add conference participant results",
+ HFILL }
+ },
+
+ { &hf_skinny_passThruData,
+ { "PassThruData", "skinny.passThruData",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Pass Through data.",
+ HFILL }
+ },
+
+ { &hf_skinny_auditParticipantResults,
+ { "AuditParticipantResults", "skinny.auditParticipantResults",
+ FT_UINT32, BASE_DEC, VALS(skinny_auditParticipantResults), 0x0,
+ "The audit participant results",
+ HFILL }
+ },
+
+ { &hf_skinny_last,
+ { "Last", "skinny.last",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Last.",
+ HFILL }
+ },
+
+ { &hf_skinny_numberOfEntries,
+ { "NumberOfEntries", "skinny.numberOfEntries",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Number of entries in list.",
+ HFILL }
+ },
+
+ { &hf_skinny_participantEntry,
+ { "ParticipantEntry", "skinny.participantEntry",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Participant Entry.",
+ HFILL }
+ },
+
+ { &hf_skinny_resourceTypes,
+ { "ResourceType", "skinny.resourceTypes",
+ FT_UINT32, BASE_DEC, VALS(skinny_resourceTypes), 0x0,
+ "Resource Type",
+ HFILL }
+ },
+
+ { &hf_skinny_numberOfReservedParticipants,
+ { "NumberOfReservedParticipants", "skinny.numberOfReservedParticipants",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "numberOfReservedParticipants.",
+ HFILL }
+ },
+
+ { &hf_skinny_numberOfActiveParticipants,
+ { "NumberOfActiveParticipants", "skinny.numberOfActiveParticipants",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "numberOfActiveParticipants.",
+ HFILL }
+ },
+
+ { &hf_skinny_appID,
+ { "AppID", "skinny.appID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "AppID.",
+ HFILL }
+ },
+
+ { &hf_skinny_appData,
+ { "AppData", "skinny.appData",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "App data.",
+ HFILL }
+ },
+
+ { &hf_skinny_appConfID,
+ { "AppConfID", "skinny.appConfID",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "App Conf ID Data.",
+ HFILL }
+ },
+
+ { &hf_skinny_sequenceFlag,
+ { "SequenceFlag", "skinny.sequenceFlag",
+ FT_UINT32, BASE_DEC, VALS(skinny_sequenceFlags), 0x0,
+ "Sequence Flag",
+ HFILL }
+ },
+
+ { &hf_skinny_displayPriority,
+ { "DisplayPriority", "skinny.displayPriority",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Display Priority.",
+ HFILL }
+ },
+
+ { &hf_skinny_appInstanceID,
+ { "AppInstanceID", "skinny.appInstanceID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "appInstanceID.",
+ HFILL }
+ },
+
+ { &hf_skinny_routingID,
+ { "routingID", "skinny.routingID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "routingID.",
+ HFILL }
+ },
+
+ { &hf_skinny_audioCapCount,
+ { "AudioCapCount", "skinny.audioCapCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "AudioCapCount.",
+ HFILL }
+ },
+
+ { &hf_skinny_videoCapCount,
+ { "VideoCapCount", "skinny.videoCapCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "VideoCapCount.",
+ HFILL }
+ },
+
+ { &hf_skinny_dataCapCount,
+ { "DataCapCount", "skinny.dataCapCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "DataCapCount.",
+ HFILL }
+ },
+
+ { &hf_skinny_RTPPayloadFormat,
+ { "RTPPayloadFormat", "skinny.RTPPayloadFormat",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "RTPPayloadFormat.",
+ HFILL }
+ },
+
+ { &hf_skinny_customPictureFormatCount,
+ { "CustomPictureFormatCount", "skinny.customPictureFormatCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "CustomPictureFormatCount.",
+ HFILL }
+ },
+
+ { &hf_skinny_pictureWidth,
+ { "PictureWidth", "skinny.pictureWidth",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PictureWidth.",
+ HFILL }
+ },
+
+ { &hf_skinny_pictureHeight,
+ { "PictureHeight", "skinny.pictureHeight",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PictureHeight.",
+ HFILL }
+ },
+
+ { &hf_skinny_pixelAspectRatio,
+ { "PixelAspectRatio", "skinny.pixelAspectRatio",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PixelAspectRatio.",
+ HFILL }
+ },
+
+ { &hf_skinny_clockConversionCode,
+ { "ClockConversionCode", "skinny.clockConversionCode",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ClockConversionCode.",
+ HFILL }
+ },
+
+ { &hf_skinny_clockDivisor,
+ { "ClockDivisor", "skinny.clockDivisor",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Clock Divisor.",
+ HFILL }
+ },
+
+ { &hf_skinny_activeStreamsOnRegistration,
+ { "ActiveStreamsOnRegistration", "skinny.activeStreamsOnRegistration",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ActiveStreamsOnRegistration.",
+ HFILL }
+ },
+
+ { &hf_skinny_maxBW,
+ { "MaxBW", "skinny.maxBW",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MaxBW.",
+ HFILL }
+ },
+
+ { &hf_skinny_serviceResourceCount,
+ { "ServiceResourceCount", "skinny.serviceResourceCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ServiceResourceCount.",
+ HFILL }
+ },
+
+ { &hf_skinny_layoutCount,
+ { "LayoutCount", "skinny.layoutCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LayoutCount.",
+ HFILL }
+ },
+
+ { &hf_skinny_layout,
+ { "Layout", "skinny.layout",
+ FT_UINT32, BASE_DEC, VALS(skinny_Layouts), 0x0,
+ "Layout",
+ HFILL }
+ },
+
+ { &hf_skinny_maxConferences,
+ { "MaxConferences", "skinny.maxConferences",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MaxConferences.",
+ HFILL }
+ },
+
+ { &hf_skinny_activeConferenceOnRegistration,
+ { "ActiveConferenceOnRegistration", "skinny.activeConferenceOnRegistration",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ActiveConferenceOnRegistration.",
+ HFILL }
+ },
+
+ { &hf_skinny_transmitOrReceive,
+ { "TransmitOrReceive", "skinny.transmitOrReceive",
+ FT_UINT32, BASE_DEC, VALS(skinny_transmitOrReceive), 0x0,
+ "TransmitOrReceive",
+ HFILL }
+ },
+
+ { &hf_skinny_levelPreferenceCount,
+ { "LevelPreferenceCount", "skinny.levelPreferenceCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LevelPreferenceCount.",
+ HFILL }
+ },
+
+ { &hf_skinny_transmitPreference,
+ { "TransmitPreference", "skinny.transmitPreference",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "TransmitPreference.",
+ HFILL }
+ },
+
+ { &hf_skinny_format,
+ { "Format", "skinny.format",
+ FT_UINT32, BASE_DEC, VALS(skinny_formatTypes), 0x0,
+ "Format.",
+ HFILL }
+ },
+
+ { &hf_skinny_maxBitRate,
+ { "MaxBitRate", "skinny.maxBitRate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MaxBitRate.",
+ HFILL }
+ },
+
+ { &hf_skinny_minBitRate,
+ { "MinBitRate", "skinny.minBitRate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MinBitRate.",
+ HFILL }
+ },
+
+ { &hf_skinny_MPI,
+ { "MPI", "skinny.MPI",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MPI.",
+ HFILL }
+ },
+
+ { &hf_skinny_serviceNumber,
+ { "ServiceNumber", "skinny.serviceNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ServiceNumber.",
+ HFILL }
+ },
+
+ { &hf_skinny_temporalSpatialTradeOffCapability,
+ { "TemporalSpatialTradeOffCapability", "skinny.temporalSpatialTradeOffCapability",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "TemporalSpatialTradeOffCapability.",
+ HFILL }
+ },
+
+ { &hf_skinny_stillImageTransmission,
+ { "StillImageTransmission", "skinny.stillImageTransmission",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "StillImageTransmission.",
+ HFILL }
+ },
+
+ { &hf_skinny_h263_capability_bitfield,
+ { "H263_capability_bitfield", "skinny.h263_capability_bitfield",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "H263_capability_bitfield.",
+ HFILL }
+ },
+
+ { &hf_skinny_annexNandWFutureUse,
+ { "AnnexNandWFutureUse", "skinny.annexNandWFutureUse",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "AnnexNandWFutureUse.",
+ HFILL }
+ },
+
+ { &hf_skinny_modelNumber,
+ { "ModelNumber", "skinny.modelNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ModelNumber.",
+ HFILL }
+ },
+
+ { &hf_skinny_bandwidth,
+ { "Bandwidth", "skinny.bandwidth",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Bandwidth.",
+ HFILL }
+ },
+
+ { &hf_skinny_protocolDependentData,
+ { "ProtocolDependentData", "skinny.protocolDependentData",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ProtocolDependentData.",
+ HFILL }
+ },
+
+ { &hf_skinny_priority,
+ { "Priority", "skinny.priority",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Priority.",
+ HFILL }
+ },
+
+ { &hf_skinny_payloadDtmf,
+ { "PayloadDtmf", "skinny.payloadDtmf",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "RTP payload type.",
+ HFILL }
+ },
+
+ { &hf_skinny_featureID,
+ { "FeatureID", "skinny.featureID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "FeatureID.",
+ HFILL }
+ },
+
+ { &hf_skinny_featureTextLabel,
+ { "FeatureTextLabel", "skinny.featureTextLabel",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The feature lable text that is displayed on the phone.",
+ HFILL }
+ },
+
+ { &hf_skinny_featureStatus,
+ { "FeatureStatus", "skinny.featureStatus",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "FeatureStatus.",
+ HFILL }
+ },
+
+ { &hf_skinny_notify,
+ { "Notify", "skinny.notify",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "The message notify text that is displayed on the phone.",
+ HFILL }
+ },
+
+ { &hf_skinny_endOfAnnAck,
+ { "EndOfAnnAck", "skinny.endOfAnnAck",
+ FT_UINT32, BASE_DEC, VALS(skinny_endOfAnnAck), 0x0,
+ "EndOfAnnAck",
+ HFILL }
+ },
+
+ { &hf_skinny_annPlayMode,
+ { "annPlayMode", "skinny.annPlayMode",
+ FT_UINT32, BASE_DEC, VALS(skinny_annPlayMode), 0x0,
+ "AnnPlayMode",
+ HFILL }
+ },
+
+ { &hf_skinny_annPlayStatus,
+ { "AnnPlayStatus", "skinny.annPlayStatus",
+ FT_UINT32, BASE_DEC, VALS(skinny_annPlayStatus), 0x0,
+ "AnnPlayStatus",
+ HFILL }
+ },
+
+ { &hf_skinny_locale,
+ { "Locale", "skinny.locale",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "User locale ID.",
+ HFILL }
+ },
+
+ { &hf_skinny_country,
+ { "Country", "skinny.country",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Country ID (Network locale).",
+ HFILL }
+ },
+
+ { &hf_skinny_matrixConfPartyID,
+ { "MatrixConfPartyID", "skinny.matrixConfPartyID",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "existing conference parties.",
+ HFILL }
+ },
+
+ { &hf_skinny_hearingConfPartyMask,
+ { "HearingConfPartyMask", "skinny.hearingConfPartyMask",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Bit mask of conference parties to hear media received on this stream. Bit0 = matrixConfPartyID[0], Bit1 = matrixConfPartiID[1].",
+ HFILL }
+ },
+
+ { &hf_skinny_serviceURL,
+ { "ServiceURL", "skinny.serviceURL",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "ServiceURL.",
+ HFILL }
+ },
+
+ { &hf_skinny_serviceURLDisplayName,
+ { "ServiceURLDisplayName", "skinny.serviceURLDisplayName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "ServiceURLDisplayName.",
+ HFILL }
+ },
+
+ { &hf_skinny_callSelectStat,
+ { "CallSelectStat", "skinny.callSelectStat",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "CallSelectStat.",
+ HFILL }
+ },
+
+ { &hf_skinny_isConferenceCreator,
+ { "IsConferenceCreator", "skinny.isConferenceCreator",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "IsConferenceCreator.",
+ HFILL }
+ },
+
+ { &hf_skinny_payload_rfc_number,
+ { "Payload_rfc_number", "skinny.payload_rfc_number",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Payload_rfc_number.",
+ HFILL }
+ },
+
+ { &hf_skinny_payloadType,
+ { "PayloadType", "skinny.payloadType",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PayloadType.",
+ HFILL }
+ },
+
+ { &hf_skinny_bitRate,
+ { "BitRate", "skinny.bitRate",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "BitRate.",
+ HFILL }
+ },
+
+ { &hf_skinny_pictureFormatCount,
+ { "PictureFormatCount", "skinny.pictureFormatCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PictureFormatCount.",
+ HFILL }
+ },
+
+ { &hf_skinny_confServiceNum,
+ { "ConfServiceNum", "skinny.confServiceNum",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "ConfServiceNum.",
+ HFILL }
+ },
+
+ { &hf_skinny_DSCPValue,
+ { "DSCPValue", "skinny.DSCPValue",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "DSCPValue.",
+ HFILL }
+ },
+
+ { &hf_skinny_miscCommandType,
+ { "MiscCommandType", "skinny.miscCommandType",
+ FT_UINT32, BASE_DEC, VALS(skinny_miscCommandType), 0x0,
+ "MiscCommandType",
+ HFILL }
+ },
+
+ { &hf_skinny_temporalSpatialTradeOff,
+ { "TemporalSpatialTradeOff", "skinny.temporalSpatialTradeOff",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "TemporalSpatialTradeOff.",
+ HFILL }
+ },
+
+ { &hf_skinny_firstGOB,
+ { "FirstGOB", "skinny.firstGOB",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "FirstGOB.",
+ HFILL }
+ },
+
+ { &hf_skinny_numberOfGOBs,
+ { "NumberOfGOBs", "skinny.numberOfGOBs",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "NumberOfGOBs.",
+ HFILL }
+ },
+
+ { &hf_skinny_firstMB,
+ { "FirstMB", "skinny.firstMB",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "FirstMB.",
+ HFILL }
+ },
+
+ { &hf_skinny_numberOfMBs,
+ { "NumberOfMBs", "skinny.numberOfMBs",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "NumberOfMBs.",
+ HFILL }
+ },
+
+ { &hf_skinny_pictureNumber,
+ { "PictureNumber", "skinny.pictureNumber",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "PictureNumber.",
+ HFILL }
+ },
+
+ { &hf_skinny_longTermPictureIndex,
+ { "LongTermPictureIndex", "skinny.longTermPictureIndex",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LongTermPictureIndex.",
+ HFILL }
+ },
+
+ { &hf_skinny_recoveryReferencePictureCount,
+ { "RecoveryReferencePictureCount", "skinny.recoveryReferencePictureCount",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "RecoveryReferencePictureCount.",
+ HFILL }
+ },
+
+ { &hf_cast_lastRedirectingPartyName,
+ { "LastRedirectingPartyName", "cast.lastRedirectingPartyName",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LastRedirectingPartyName.",
+ HFILL }
+ },
+
+ { &hf_cast_lastRedirectingParty,
+ { "LastRedirectingParty", "cast.lastRedirectingParty",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LastRedirectingParty.",
+ HFILL }
+ },
+
+ { &hf_cast_cgpnVoiceMailbox,
+ { "CgpnVoiceMailbox", "cast.cgpnVoiceMailbox",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "CgpnVoiceMailbox.",
+ HFILL }
+ },
+
+ { &hf_cast_cdpnVoiceMailbox,
+ { "CdpnVoiceMailbox", "cast.cdpnVoiceMailbox",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "CdpnVoiceMailbox.",
+ HFILL }
+ },
+
+ { &hf_cast_originalCdpnVoiceMailbox,
+ { "OriginalCdpnVoiceMailbox", "cast.originalCdpnVoiceMailbox",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "OriginalCdpnVoiceMailbox.",
+ HFILL }
+ },
+
+ { &hf_cast_lastRedirectingVoiceMailbox,
+ { "LastRedirectingVoiceMailbox", "cast.lastRedirectingVoiceMailbox",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "LastRedirectingVoiceMailbox.",
+ HFILL }
+ },
+
+ { &hf_cast_originalCdpnRedirectReason,
+ { "OriginalCdpnRedirectReason", "cast.originalCdpnRedirectReason",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "OriginalCdpnRedirectReason.",
+ HFILL }
+ },
+
+ { &hf_cast_lastRedirectingReason,
+ { "LastRedirectingReason", "cast.lastRedirectingReason",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "LastRedirectingReason.",
+ HFILL }
+ },
+
+ { &hf_cast_callInstance,
+ { "CallInstance", "cast.callInstance",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "CallInstance.",
+ HFILL }
+ },
+
+ { &hf_cast_callSecurityStatus,
+ { "CallSecurityStatus", "cast.callSecurityStatus",
+ FT_UINT32, BASE_DEC, VALS(cast_callSecurityStatusTypes), 0x0,
+ "CallSecurityStatus.",
+ HFILL }
+ },
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_skinny,
+ &ett_skinny_tree,
+ &ett_skinny_softKeyMap,
+ };
+
+ module_t *skinny_module;
+
+ /* Register the protocol name and description */
+ proto_skinny = proto_register_protocol("Skinny Client Control Protocol",
+ "SKINNY", "skinny");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_skinny, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ skinny_module = prefs_register_protocol(proto_skinny, NULL);
+ prefs_register_bool_preference(skinny_module, "desegment",
+ "Desegment all SCCP messages spanning multiple TCP segments",
+ "Whether the SCCP dissector should desegment all messages spanning multiple TCP segments",
+ &skinny_desegment);
+}
+
+void
+proto_reg_handoff_skinny(void)
+{
+ dissector_handle_t skinny_handle;
+
+ data_handle = find_dissector("data");
+ rtp_handle = find_dissector("rtp");
+ skinny_handle = create_dissector_handle(dissect_skinny, proto_skinny);
+ dissector_add("tcp.port", TCP_PORT_SKINNY, skinny_handle);
+}
+
+/*
+ * FIXME:
+ *
+ * This is the status of this decode.
+ * Items marked as N/A in the decode field have no params to test
+ * implemented for N/A means they exist in the switch statement
+ * S = stubbed
+ *
+ * id message implemented decode tested (via capture)
+ * ---------------------------------------------------------------------------
+ * 0x0 keepAlive Y N/A
+ * 0x1 register Y Y
+ * 0x2 ipPort Y Y
+ * 0x3 keypadButton Y Y
+ * 0x4 enblocCall Y N
+ * 0x5 stimulus Y N
+ * 0x6 offHook Y N/A
+ * 0x7 onHook Y N/A
+ * 0x8 hookFlash Y N/A
+ * 0x9 forwardStatReq Y N
+ * 0xa speedDialStatReq Y Y
+ * 0xb lineStatReq Y Y
+ * 0xc configStatReq Y N/A
+ * 0xd timeDateReq Y N/A
+ * 0xe buttonTemplateReq Y N/A
+ * 0xf versionReq Y N/A
+ * 0x10 capabilitiesRes Y Y -- would like more decodes
+ * 0x11 mediaPortList S N -- no info
+ * 0x12 serverReq Y N/A
+ * 0x20 alarmMessage Y Y
+ * 0x21 multicastMediaReceptionAck Y N
+ * 0x22 openReceiveChannelAck Y Y
+ * 0x23 connectionStatisticsRes Y Y
+ * 0x24 offHookWithCgpn Y N
+ * 0x25 softKeySetReq Y N/A
+ * 0x26 softKeyEvent Y Y
+ * 0x27 unregister Y N/A
+ * 0x28 softKeytemplateReq Y N/A
+ * 0x29 registerTokenReq Y N
+ * 0x2A mediaTransmissionFailure
+ * 0x2B headsetStatus
+ * 0x2C mediaResourceNotification
+ * 0x2D registerAvailableLines
+ * 0x2E deviceToUserData
+ * 0x2F deviceToUserDataResponse
+ * 0x30 updateCapabilities
+ * 0x31 openMultiMediaReceiveChannelAck
+ * 0x32 clearConference
+ * 0x33 serviceURLStatReq
+ * 0x34 featureStatReq
+ * 0x35 createConferenceRes
+ * 0x36 deleteConferenceRes
+ * 0x37 modifyConferenceRes
+ * 0x38 addParticipantRes
+ * 0x39 auditConferenceRes
+ * 0x40 auditParticipantRes
+ * 0x41 deviceToUserDataVersion1
+ * 0x42 deviceToUserDataResponseVersion1
+ * 0x81 registerAck Y Y
+ * 0x82 startTone Y Y
+ * 0x83 stopTone Y N/A
+ * 0x85 setRinger Y Y
+ * 0x86 setLamp Y Y
+ * 0x87 setHkFDetect Y N
+ * 0x88 setSpeakerMode Y Y
+ * 0x89 setMicroMode Y N
+ * 0x8A startMediaTransmission Y Y
+ * 0x8B stopMediaTransmission Y Y
+ * 0x8C startMediaReception S N
+ * 0x8D stopMediaReception S N
+ * 0x8E *reserved* S *
+ * 0x8F callInfo Y Y
+ * 0x90 forwardStat Y N
+ * 0x91 speedDialStat Y Y
+ * 0x92 lineStat Y Y
+ * 0x93 configStat Y N
+ * 0x94 defineTimeDate Y Y
+ * 0x95 startSessionTransmission Y N
+ * 0x96 stopSessionTransmission Y N
+ * 0x97 buttonTemplate Y Y -- ugly =)
+ * 0x98 version Y N
+ * 0x99 displayText Y Y
+ * 0x9A clearDisplay Y N/A
+ * 0x9B capabilitiesReq Y N/A
+ * 0x9C enunciatorCommand Y N (inner loop unknown)
+ * 0x9D registerReject Y N
+ * 0x9E serverRes Y N
+ * 0x9F reset Y Y
+ * 0x100 keepAliveAck Y N/A
+ * 0x101 startMulticastMediaReception Y N
+ * 0x102 startMulticastMediaTransmission Y N
+ * 0x103 stopMulticastMediaReception Y N
+ * 0x104 stopMulticastMediaTransmission Y N
+ * 0x105 openreceiveChannel Y Y
+ * 0x106 closeReceiveChannel Y Y
+ * 0x107 connectionStatisticsReq Y Y
+ * 0x108 softKeyTemplateRes Y Y
+ * 0x109 softKeySetRes Y Y
+ * 0x110 selectSoftKeys Y Y
+ * 0x111 callState Y Y
+ * 0x112 displayPromptStatus Y Y
+ * 0x113 clearPromptStatus Y Y
+ * 0x114 displayNotify Y Y
+ * 0x115 clearNotify Y Y
+ * 0x116 activateCallPlane Y Y
+ * 0x117 deactivateCallPlane Y N/A
+ * 0x118 unregisterAck Y Y
+ * 0x119 backSpaceReq Y Y
+ * 0x11A registerTokenAck Y N
+ * 0x11B registerTokenReject Y N
+ * 0x11C startMediaFailureDetection
+ * 0x11D dialedNumber
+ * 0x11E userToDeviceData
+ * 0x11F featureStat
+ * 0x120 displayPriNotify
+ * 0x121 clearPriNotify
+ * 0x122 startAnnouncement
+ * 0x123 stopAnnouncement
+ * 0x124 announcementFinish
+ * 0x127 notifyDtmfTone
+ * 0x128 sendDtmfTone
+ * 0x129 subscribeDtmfPayloadReq
+ * 0x12A subscribeDtmfPayloadRes
+ * 0x12B subscribeDtmfPayloadErr
+ * 0x12C unSubscribeDtmfPayloadReq
+ * 0x12D unSubscribeDtmfPayloadRes
+ * 0x12E unSubscribeDtmfPayloadErr
+ * 0x12F serviceURLStat
+ * 0x130 callSelectStat
+ * 0x131 openMultiMediaChannel
+ * 0x132 startMultiMediaTransmission
+ * 0x133 stopMultiMediaTransmission
+ * 0x134 miscellaneousCommand
+ * 0x135 flowControlCommand
+ * 0x136 closeMultiMediaReceiveChannel
+ * 0x137 createConferenceReq
+ * 0x138 deleteConferenceReq
+ * 0x139 modifyConferenceReq
+ * 0x13A addParticipantReq
+ * 0x13B dropParticipantReq
+ * 0x13C auditConferenceReq
+ * 0x13D auditParticipantReq
+ * 0x13F userToDeviceDataVersion1
+ *
+ *
+ */
diff --git a/epan/dissectors/packet-slimp3.c b/epan/dissectors/packet-slimp3.c
new file mode 100644
index 0000000000..89071840eb
--- /dev/null
+++ b/epan/dissectors/packet-slimp3.c
@@ -0,0 +1,731 @@
+/* packet-slimp3.c
+ * Routines for SliMP3 protocol dissection
+ *
+ * Ashok Narayanan <ashokn@cisco.com>
+ *
+ * Adds support for the data packet protocol for the SliMP3
+ * See www.slimdevices.com for details.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+
+static int proto_slimp3 = -1;
+static int hf_slimp3_opcode = -1;
+static int hf_slimp3_ir = -1;
+static int hf_slimp3_display = -1;
+static int hf_slimp3_control = -1;
+static int hf_slimp3_hello = -1;
+static int hf_slimp3_i2c = -1;
+static int hf_slimp3_data_request = -1;
+static int hf_slimp3_data = -1;
+static int hf_slimp3_discover_request = -1;
+static int hf_slimp3_discover_response = -1;
+static int hf_slimp3_data_ack = -1;
+
+static gint ett_slimp3 = -1;
+
+static dissector_handle_t slimp3_handle;
+
+#define UDP_PORT_SLIMP3_V1 1069
+#define UDP_PORT_SLIMP3_V2 3483
+
+#define SLIMP3_IR 'i'
+#define SLIMP3_CONTROL 's'
+#define SLIMP3_HELLO 'h'
+#define SLIMP3_DATA 'm'
+#define SLIMP3_DATA_REQ 'r'
+#define SLIMP3_DISPLAY 'l'
+#define SLIMP3_I2C '2'
+#define SLIMP3_DISC_REQ 'd'
+#define SLIMP3_DISC_RSP 'D'
+#define SLIMP3_DATA_ACK 'a'
+
+static const value_string slimp3_opcode_vals[] = {
+ { SLIMP3_IR, "Infrared Remote Code" },
+ { SLIMP3_CONTROL, "Stream Control" },
+ { SLIMP3_DATA, "MPEG Data" },
+ { SLIMP3_DATA_REQ, "Data Request" },
+ { SLIMP3_HELLO, "Hello" },
+ { SLIMP3_DISPLAY, "Display" },
+ { SLIMP3_I2C, "I2C" },
+ { SLIMP3_DISC_REQ, "Discovery Request" },
+ { SLIMP3_DISC_RSP, "Discovery Response" },
+ { SLIMP3_DATA_ACK, "Ack" },
+ { 0, NULL }
+};
+
+/* IR remote control types */
+static const value_string slimp3_ir_types[] = {
+ { 0x02, "SLIMP3" },
+ { 0xff, "JVC DVD Player" },
+
+ { 0, NULL }
+};
+
+/* IR codes for the custom SLIMP3 remote control */
+static const value_string slimp3_ir_codes_slimp3[] = {
+ { 0x76899867, "0" },
+ { 0x7689f00f, "1" },
+ { 0x768908f7, "2" },
+ { 0x76898877, "3" },
+ { 0x768948b7, "4" },
+ { 0x7689c837, "5" },
+ { 0x768928d7, "6" },
+ { 0x7689a857, "7" },
+ { 0x76896897, "8" },
+ { 0x7689e817, "9" },
+ { 0x7689b04f, "arrow_down" },
+ { 0x7689906f, "arrow_left" },
+ { 0x7689d02f, "arrow_right" },
+ { 0x7689e01f, "arrow_up" },
+ { 0x768900ff, "voldown" },
+ { 0x7689807f, "volup" },
+ { 0x768940bf, "power" },
+ { 0x7689c03f, "rew" },
+ { 0x768920df, "pause" },
+ { 0x7689a05f, "fwd" },
+ { 0x7689609f, "add" },
+ { 0x768910ef, "play" },
+ { 0x768958a7, "search" },
+ { 0x7689d827, "shuffle" },
+ { 0x768938c7, "repeat" },
+ { 0x7689b847, "sleep" },
+ { 0x76897887, "now_playing" },
+ { 0x7689f807, "size" },
+ { 0x768904fb, "brightness" },
+
+ { 0, NULL }
+};
+
+/* IR codes for the JVC remote control */
+static const value_string slimp3_ir_codes_jvc[] = {
+ { 0xf786, "One" },
+ { 0xf746, "Two" },
+ { 0xf7c6, "Three" },
+ { 0xf726, "Four" },
+ { 0xf7a6, "Five" },
+ { 0xf766, "Six" },
+ { 0xf7e6, "Seven" },
+ { 0xf716, "Eight" },
+ { 0xf796, "Nine" },
+ { 0xf776, "Ten" },
+
+ { 0xf7f6, "Picture-In-Picture" },
+ /* { 0xf7XX, "Enter" }, */
+ { 0xf70e, "Back" },
+ { 0xf732, "Play" },
+ { 0xf76e, "Forward" },
+ { 0xf743, "Record" },
+ { 0xf7c2, "Stop" },
+ { 0xf7b2, "Pause" },
+ /* { 0xf7XX, "TV/Video" }, */
+ { 0xf703, "Display" },
+ { 0xf7b3, "Sleep" },
+ { 0xf7b6, "Guide" },
+ { 0xf70b, "Up" },
+ { 0xf74b, "Left" },
+ { 0xf7cb, "Right" },
+ { 0xf78b, "Down" },
+ { 0xf783, "Menu" },
+ { 0xf72b, "OK" },
+ { 0xf778, "Volume Up" },
+ { 0xf7f8, "Volume Down" },
+ { 0xf70d, "Channel Up" },
+ { 0xf78d, "Channel Down" },
+ /* { 0xf7XX, "Mute" }, */
+ { 0xf7ab, "Recall" },
+ { 0xf702, "Power" },
+
+ { 0, NULL }
+};
+
+
+static const value_string slimp3_display_commands[] = {
+ { 0x1, "Clear Display"},
+ { 0x2, "Cursor to 1st Line Home"},
+
+ { 0x4, "Mode: Decrement Address, Shift Cursor"},
+ { 0x5, "Mode: Decrement Address, Shift Display"},
+ { 0x6, "Mode: Increment Address, Shift Cursor"},
+ { 0x7, "Mode: Increment Address, Shift Display"},
+
+ { 0x8, "Display Off"},
+ { 0xd, "Display On, With Blinking"},
+ { 0xe, "Display On, With Cursor"},
+ { 0xf, "Display On, With Cursor And Blinking"},
+
+ { 0x10, "Move Cursor Left"},
+ { 0x14, "Move Cursor Right"},
+ { 0x18, "Shift Display Left"},
+ { 0x1b, "Shift Display Right"},
+
+ { 0x30, "Set (8-bit)"},
+ { 0x20, "Set (4-bit)"},
+
+ { 0xa0, "Cursor to Top Right"},
+ { 0xc0, "Cursor to 2nd Line Home"},
+
+ { 0, NULL},
+};
+
+static const value_string slimp3_display_fset8[] = {
+ { 0x0, "Brightness 100%"},
+ { 0x1, "Brightness 75%"},
+ { 0x2, "Brightness 50%"},
+ { 0x3, "Brightness 25%"},
+
+ { 0, NULL },
+};
+
+static const value_string slimp3_stream_control[] = {
+ { 1, "Reset buffer, Start New Stream"},
+ { 2, "Pause Playback"},
+ { 4, "Resume Playback"},
+ { 0, NULL },
+};
+
+
+static const value_string slimp3_mpg_control[] = {
+ { 0, "Go"}, /* Run the decoder */
+ { 1, "Stop"}, /* Halt decoder but don't reset rptr */
+ { 3, "Reset"}, /* Halt decoder and reset rptr */
+
+ { 0, NULL }
+};
+
+static void
+dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *slimp3_tree = NULL;
+ proto_item *ti = NULL;
+ gint i1;
+ gint offset = 0;
+ guint16 opcode;
+ char addc_str[101];
+ char *addc_strp;
+ int to_server = FALSE;
+ int old_protocol = FALSE;
+ address tmp_addr;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SliMP3");
+
+ opcode = tvb_get_guint8(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(opcode, slimp3_opcode_vals, "Unknown (%c)"));
+
+ }
+
+ addc_strp = addc_str;
+ if (tree) {
+
+ ti = proto_tree_add_item(tree, proto_slimp3, tvb, offset, -1, FALSE);
+ slimp3_tree = proto_item_add_subtree(ti, ett_slimp3);
+
+ proto_tree_add_uint(slimp3_tree, hf_slimp3_opcode, tvb,
+ offset, 1, opcode);
+ }
+
+ /* The new protocol (v1.3 and later) uses an IANA-assigned port number.
+ * It usually uses the same number for both sizes of the conversation, so
+ * the port numbers can't always be used to determine client and server.
+ * The new protocol places the clients MAC address in the packet, so that
+ * is used to identify packets originating at the client.
+ */
+ if ((pinfo->destport == UDP_PORT_SLIMP3_V2) && (pinfo->srcport == UDP_PORT_SLIMP3_V2)) {
+ SET_ADDRESS(&tmp_addr, AT_ETHER, 6, tvb_get_ptr(tvb, offset+12, 6));
+ to_server = ADDRESSES_EQUAL(&tmp_addr, &pinfo->dl_src);
+ }
+ else if (pinfo->destport == UDP_PORT_SLIMP3_V2) {
+ to_server = TRUE;
+ }
+ else if (pinfo->srcport == UDP_PORT_SLIMP3_V2) {
+ to_server = FALSE;
+ }
+ if (pinfo->destport == UDP_PORT_SLIMP3_V1) {
+ to_server = TRUE;
+ old_protocol = TRUE;
+ }
+ else if (pinfo->srcport == UDP_PORT_SLIMP3_V1) {
+ to_server = FALSE;
+ old_protocol = TRUE;
+ }
+
+ switch (opcode) {
+
+ case SLIMP3_IR:
+ /* IR code
+ *
+ * [0] 'i' as in "IR"
+ * [1] 0x00
+ * [2..5] player's time since startup in ticks @625 KHz
+ * [6] IR code id, ff=JVC, 02=SLIMP3
+ * [7] number of meaningful bits - 16 for JVC, 32 for SLIMP3
+ * [8..11] the 32-bit IR code
+ * [12..17] reserved
+ */
+ if (tree) {
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_ir, tvb, offset+8, 4, FALSE);
+
+ i1 = tvb_get_ntohl(tvb, offset+2);
+ proto_tree_add_text(slimp3_tree, tvb, offset+2, 4, "Uptime: %u sec (%u ticks)",
+ i1/625000, i1);
+ i1 = tvb_get_guint8(tvb, offset+6);
+ proto_tree_add_text(slimp3_tree, tvb, offset+6, 1, "Code identifier: 0x%0x: %s",
+ i1, val_to_str(i1, slimp3_ir_types, "Unknown"));
+ proto_tree_add_text(slimp3_tree, tvb, offset+7, 1, "Code bits: %d",
+ tvb_get_guint8(tvb, offset+7));
+
+ i1 = tvb_get_ntohl(tvb, offset+8);
+ /* Check the code to figure out which remote is being used. */
+ if (tvb_get_guint8(tvb, offset+6) == 0x02 &&
+ tvb_get_guint8(tvb, offset+7) == 32) {
+ /* This is the custom SLIMP3 remote. */
+ proto_tree_add_text(slimp3_tree, tvb, offset+8, 4,
+ "Infrared Code: %s: 0x%0x",
+ val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown"), i1);
+ }
+ else if (tvb_get_guint8(tvb, offset+6) == 0xff &&
+ tvb_get_guint8(tvb, offset+7) == 16) {
+ /* This is a JVC DVD player remote */
+ proto_tree_add_text(slimp3_tree, tvb, offset+8, 4,
+ "Infrared Code: %s: 0x%0x",
+ val_to_str(i1, slimp3_ir_codes_jvc, "Unknown"), i1);
+ } else {
+ /* Unknown code; just write it */
+ proto_tree_add_text(slimp3_tree, tvb, offset+8, 4, "Infrared Code: 0x%0x", i1);
+ }
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ i1 = tvb_get_ntohl(tvb, offset+8);
+ if (tvb_get_guint8(tvb, offset+6) == 0x02 &&
+ tvb_get_guint8(tvb, offset+7) == 32) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", SLIMP3: %s",
+ val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown (0x%0x)"));
+ }
+ else if (tvb_get_guint8(tvb, offset+6) == 0xff &&
+ tvb_get_guint8(tvb, offset+7) == 16) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", JVC: %s",
+ val_to_str(i1, slimp3_ir_codes_jvc, "Unknown (0x%0x)"));
+ } else {
+ /* Unknown code; just write it */
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", 0x%0x", i1);
+ }
+ }
+ break;
+
+ case SLIMP3_DISPLAY:
+ if (tree) {
+ gboolean in_str;
+ int str_len;
+
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_display,
+ tvb, offset, 1, FALSE);
+
+ /* Loop through the commands */
+ i1 = 18;
+ in_str = FALSE;
+ str_len = 0;
+ while (i1 < tvb_reported_length_remaining(tvb, offset)) {
+ switch(tvb_get_guint8(tvb, offset + i1)) {
+ case 0:
+ in_str = FALSE;
+ str_len = 0;
+ proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
+ "Delay (%d ms)", tvb_get_guint8(tvb, offset + i1 + 1));
+ i1 += 2;
+ break;
+ case 3:
+ if (ti && in_str) {
+ str_len += 2;
+ proto_item_append_text(ti, "%c",
+ tvb_get_guint8(tvb, offset + i1 + 1));
+ proto_item_set_len(ti, str_len);
+ } else {
+ ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
+ "String: %c",
+ tvb_get_guint8(tvb, offset + i1 + 1));
+ in_str = TRUE;
+ str_len = 2;
+ }
+ i1 += 2;
+ break;
+
+ case 2:
+ in_str = FALSE;
+ str_len = 0;
+ ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
+ "Command: %s",
+ val_to_str(tvb_get_guint8(tvb, offset + i1 + 1),
+ slimp3_display_commands,
+ "Unknown (0x%0x)"));
+ if ((tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30) {
+ proto_item_append_text(ti, ": %s",
+ val_to_str(tvb_get_guint8(tvb, offset + i1 + 2),
+ slimp3_display_fset8,
+ "Unknown (0x%0x)"));
+ i1 += 2;
+ }
+ i1 += 2;
+ break;
+
+ default:
+ proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
+ "Unknown 0x%0x, 0x%0x",
+ tvb_get_guint8(tvb, offset + i1),
+ tvb_get_guint8(tvb, offset + i1 + 1));
+ i1 += 2;
+ break;
+ }
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ i1 = 18;
+ addc_strp = addc_str;
+ while (tvb_offset_exists(tvb, offset + i1)) {
+ switch (tvb_get_guint8(tvb, offset + i1)) {
+
+ case 0:
+ *addc_strp++ = '.';
+ break;
+
+ case 2:
+ *addc_strp++ = '|';
+ if (tvb_offset_exists(tvb, offset + i1 + 1) &&
+ (tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30)
+ i1 += 2;
+ break;
+
+ case 3:
+ if (tvb_offset_exists(tvb, offset + i1 + 1)) {
+ if (addc_strp == addc_str ||
+ *(addc_strp-1) != ' ' ||
+ tvb_get_guint8(tvb, offset + i1 + 1) != ' ')
+ *addc_strp++ = tvb_get_guint8(tvb, offset + i1 + 1);
+ }
+ }
+ i1 += 2;
+ }
+ *addc_strp = 0;
+ if (addc_strp - addc_str > 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", addc_str);
+ }
+
+ break;
+
+ case SLIMP3_CONTROL:
+ if (tree) {
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_control,
+ tvb, offset+1, 1, FALSE);
+ proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s",
+ val_to_str(tvb_get_guint8(tvb, offset+1),
+ slimp3_stream_control, "Unknown (0x%0x)"));
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(tvb_get_guint8(tvb, offset+1),
+ slimp3_stream_control, "Unknown (0x%0x)"));
+ }
+ break;
+
+ case SLIMP3_HELLO:
+ if (tree) {
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_hello,
+ tvb, offset+1, 1, FALSE);
+ if (to_server) {
+ guint8 fw_ver = 0;
+ /* Hello response; client->server */
+ proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Response (Client --> Server)");
+ proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Device ID: %d",
+ tvb_get_guint8(tvb, offset+1));
+ fw_ver = tvb_get_guint8(tvb, offset+2);
+ proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)",
+ fw_ver>>4, fw_ver & 0xf, fw_ver);
+ } else {
+ /* Hello request; server->client */
+ proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Request (Server --> Client)");
+ }
+ }
+ break;
+
+ case SLIMP3_I2C:
+ if (tree) {
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_i2c,
+ tvb, offset, 1, FALSE);
+ if (to_server) {
+ /* Hello response; client->server */
+ proto_tree_add_text(slimp3_tree, tvb, offset, -1,
+ "I2C Response (Client --> Server)");
+ } else {
+ /* Hello request; server->client */
+ proto_tree_add_text(slimp3_tree, tvb, offset, -1,
+ "I2C Request (Server --> Client)");
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (to_server) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Response");
+ } else {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Request");
+ }
+ }
+ break;
+
+ case SLIMP3_DATA_REQ:
+ if (tree) {
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_data_request,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_text(slimp3_tree, tvb, offset+2, 2,
+ "Requested offset: %d bytes.",
+ tvb_get_ntohs(tvb, offset+2)*2);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Offset: %d bytes",
+ tvb_get_ntohs(tvb, offset+2)*2);
+ }
+ break;
+
+ case SLIMP3_DATA:
+ /* MPEG data (v1.3 and later)
+ *
+ * [0] 'm'
+ * [1..5] reserved
+ * [6..7] Write pointer (in words)
+ * [8..9] reserved
+ * [10..11] Sequence number
+ * [12..17] reserved
+ * [18..] MPEG data
+ */
+ if (tree) {
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_data,
+ tvb, offset, 1, FALSE);
+ if (old_protocol) {
+ proto_tree_add_text(slimp3_tree, tvb, offset, -1,
+ "Length: %d bytes",
+ tvb_reported_length_remaining(tvb, offset+18));
+ proto_tree_add_text(slimp3_tree, tvb, offset+2, 2,
+ "Buffer offset: %d bytes.",
+ tvb_get_ntohs(tvb, offset+2) * 2);
+ }
+ else {
+ proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s",
+ val_to_str(tvb_get_guint8(tvb, offset+1),
+ slimp3_mpg_control, "Unknown (0x%0x)"));
+ proto_tree_add_text(slimp3_tree, tvb, offset, -1,
+ "Length: %d bytes",
+ tvb_reported_length_remaining(tvb, offset+18));
+ proto_tree_add_text(slimp3_tree, tvb, offset+6, 2,
+ "Write Pointer: %d",
+ tvb_get_ntohs(tvb, offset+6) * 2);
+ proto_tree_add_text(slimp3_tree, tvb, offset+10, 2,
+ "Sequence: %d",
+ tvb_get_ntohs(tvb, offset+10));
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (old_protocol) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", Length: %d bytes, Offset: %d bytes.",
+ tvb_reported_length_remaining(tvb, offset+18),
+ tvb_get_ntohs(tvb, offset+2) * 2);
+ }
+ else {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %s, %d bytes at %d, Sequence: %d",
+ val_to_str(tvb_get_guint8(tvb, offset+1),
+ slimp3_mpg_control, "Unknown (0x%0x)"),
+ tvb_reported_length_remaining(tvb, offset+18),
+ tvb_get_ntohs(tvb, offset+6) * 2,
+ tvb_get_ntohs(tvb, offset+10));
+ }
+ }
+ break;
+
+ case SLIMP3_DISC_REQ:
+ if (tree) {
+ guint8 fw_ver;
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_discover_request,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_text(slimp3_tree, tvb, offset+1, 1,
+ "Device ID: %d.", tvb_get_guint8(tvb, offset+1));
+ fw_ver = tvb_get_guint8(tvb, offset+2);
+ proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)",
+ fw_ver>>4, fw_ver & 0xf, fw_ver);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ guint8 fw_ver = tvb_get_guint8(tvb, offset+2);
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Device ID: %d. Firmware: %d.%d",
+ tvb_get_guint8(tvb, offset+1), fw_ver>>4, fw_ver & 0xf);
+ }
+ break;
+
+ case SLIMP3_DISC_RSP:
+ if (tree) {
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_discover_response,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_text(slimp3_tree, tvb, offset+2, 4,
+ "Server Address: %s.",
+ ip_to_str(tvb_get_ptr(tvb, offset+2, 4)));
+ proto_tree_add_text(slimp3_tree, tvb, offset+6, 2,
+ "Server Port: %d", tvb_get_ntohs(tvb, offset + 6));
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Server Address: %s. Server Port: %d",
+ ip_to_str(tvb_get_ptr(tvb, offset+2, 4)),
+ tvb_get_ntohs(tvb, offset + 6));
+ }
+ break;
+
+ case SLIMP3_DATA_ACK:
+ /* Acknowledge MPEG data
+ *
+ * [0] 'a'
+ * [1..5]
+ * [6..7] Write pointer (in words)
+ * [8..9] Read pointer (in words)
+ * [10..11] Sequence number
+ * [12..17] client MAC address (v1.3 and later)
+ */
+ if (tree) {
+ proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_data_ack,
+ tvb, offset, 1, FALSE);
+ proto_tree_add_text(slimp3_tree, tvb, offset+6, 2,
+ "Write Pointer: %d",
+ tvb_get_ntohs(tvb, offset+6) * 2);
+ proto_tree_add_text(slimp3_tree, tvb, offset+8, 2,
+ "Read Pointer: %d",
+ tvb_get_ntohs(tvb, offset+8) * 2);
+ proto_tree_add_text(slimp3_tree, tvb, offset+10, 2,
+ "Sequence: %d",
+ tvb_get_ntohs(tvb, offset+10));
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Sequence: %d",
+ tvb_get_ntohs(tvb, offset+10));
+ }
+ break;
+
+ default:
+ if (tree) {
+ proto_tree_add_text(slimp3_tree, tvb, offset, -1,
+ "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
+ }
+ break;
+
+ }
+}
+
+void
+proto_register_slimp3(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_slimp3_opcode,
+ { "Opcode", "slimp3.opcode",
+ FT_UINT8, BASE_DEC, VALS(slimp3_opcode_vals), 0x0,
+ "SLIMP3 message type", HFILL }},
+
+ { &hf_slimp3_ir,
+ { "Infrared", "slimp3.ir",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "SLIMP3 Infrared command", HFILL }},
+
+ { &hf_slimp3_control,
+ { "Control Packet", "slimp3.control",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "SLIMP3 control", HFILL }},
+
+ { &hf_slimp3_display,
+ { "Display", "slimp3.display",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "SLIMP3 display", HFILL }},
+
+ { &hf_slimp3_hello,
+ { "Hello", "slimp3.hello",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "SLIMP3 hello", HFILL }},
+
+ { &hf_slimp3_i2c,
+ { "I2C", "slimp3.i2c",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "SLIMP3 I2C", HFILL }},
+
+ { &hf_slimp3_data,
+ { "Data", "slimp3.data",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "SLIMP3 Data", HFILL }},
+
+ { &hf_slimp3_data_request,
+ { "Data Request", "slimp3.data_req",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "SLIMP3 Data Request", HFILL }},
+
+ { &hf_slimp3_discover_request,
+ { "Discovery Request", "slimp3.discovery_req",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "SLIMP3 Discovery Request", HFILL }},
+
+ { &hf_slimp3_discover_response,
+ { "Discovery Response", "slimp3.discovery_response",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "SLIMP3 Discovery Response", HFILL }},
+
+ { &hf_slimp3_data_ack,
+ { "Data Ack", "slimp3.data_ack",
+ FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+ "SLIMP3 Data Ack", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_slimp3,
+ };
+
+ proto_slimp3 = proto_register_protocol("SliMP3 Communication Protocol",
+ "SliMP3", "slimp3");
+ proto_register_field_array(proto_slimp3, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ slimp3_handle = create_dissector_handle(dissect_slimp3, proto_slimp3);
+}
+
+void
+proto_reg_handoff_slimp3(void)
+{
+ dissector_add("udp.port", UDP_PORT_SLIMP3_V1, slimp3_handle);
+ dissector_add("udp.port", UDP_PORT_SLIMP3_V2, slimp3_handle);
+}
diff --git a/epan/dissectors/packet-sll.c b/epan/dissectors/packet-sll.c
new file mode 100644
index 0000000000..d1fb2a968f
--- /dev/null
+++ b/epan/dissectors/packet-sll.c
@@ -0,0 +1,307 @@
+/* packet-sll.c
+ * Routines for disassembly of packets from Linux "cooked mode" captures
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-sll.h"
+#include "packet-ipx.h"
+#include "packet-llc.h"
+#include <epan/resolv.h>
+#include "etypes.h"
+
+static int proto_sll = -1;
+static int hf_sll_pkttype = -1;
+static int hf_sll_hatype = -1;
+static int hf_sll_halen = -1;
+static int hf_sll_src_eth = -1;
+static int hf_sll_src_other = -1;
+static int hf_sll_ltype = -1;
+static int hf_sll_etype = -1;
+static int hf_sll_trailer = -1;
+
+static gint ett_sll = -1;
+
+/*
+ * A DLT_LINUX_SLL fake link-layer header.
+ */
+#define SLL_HEADER_SIZE 16 /* total header length */
+#define SLL_ADDRLEN 8 /* length of address field */
+
+/*
+ * The LINUX_SLL_ values for "sll_pkttype".
+ */
+#define LINUX_SLL_HOST 0
+#define LINUX_SLL_BROADCAST 1
+#define LINUX_SLL_MULTICAST 2
+#define LINUX_SLL_OTHERHOST 3
+#define LINUX_SLL_OUTGOING 4
+
+static const value_string packet_type_vals[] = {
+ { LINUX_SLL_HOST, "Unicast to us" },
+ { LINUX_SLL_BROADCAST, "Broadcast" },
+ { LINUX_SLL_MULTICAST, "Multicast" },
+ { LINUX_SLL_OTHERHOST, "Unicast to another host" },
+ { LINUX_SLL_OUTGOING, "Sent by us" },
+ { 0, NULL }
+};
+
+/*
+ * The LINUX_SLL_ values for "sll_protocol".
+ */
+#define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */
+#define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */
+
+static const value_string ltype_vals[] = {
+ { LINUX_SLL_P_802_3, "Raw 802.3" },
+ { LINUX_SLL_P_802_2, "802.2 LLC" },
+ { 0, NULL }
+};
+
+static dissector_handle_t ipx_handle;
+static dissector_handle_t llc_handle;
+static dissector_handle_t data_handle;
+
+void
+capture_sll(const guchar *pd, int len, packet_counts *ld)
+{
+ guint16 protocol;
+
+ if (!BYTES_ARE_IN_FRAME(0, len, SLL_HEADER_SIZE)) {
+ ld->other++;
+ return;
+ }
+ protocol = pntohs(&pd[14]);
+ if (protocol <= 1536) { /* yes, 1536 - that's how Linux does it */
+ /*
+ * "proto" is *not* a length field, it's a Linux internal
+ * protocol type.
+ */
+ switch (protocol) {
+
+ case LINUX_SLL_P_802_2:
+ /*
+ * 802.2 LLC.
+ */
+ capture_llc(pd, len, SLL_HEADER_SIZE, ld);
+ break;
+
+ case LINUX_SLL_P_802_3:
+ /*
+ * Novell IPX inside 802.3 with no 802.2 LLC
+ * header.
+ */
+ capture_ipx(ld);
+ break;
+
+ default:
+ ld->other++;
+ break;
+ }
+ } else
+ capture_ethertype(protocol, pd, SLL_HEADER_SIZE, len, ld);
+}
+
+static void
+dissect_sll(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 pkttype;
+ guint16 protocol;
+ guint16 hatype, halen;
+ const guint8 *src;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+ proto_tree *fh_tree = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SLL");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ pkttype = tvb_get_ntohs(tvb, 0);
+
+ /*
+ * Set "pinfo->p2p_dir" if the packet wasn't received
+ * promiscuously.
+ */
+ switch (pkttype) {
+
+ case LINUX_SLL_HOST:
+ case LINUX_SLL_BROADCAST:
+ case LINUX_SLL_MULTICAST:
+ pinfo->p2p_dir = P2P_DIR_RECV;
+ break;
+
+ case LINUX_SLL_OUTGOING:
+ pinfo->p2p_dir = P2P_DIR_SENT;
+ break;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(pkttype, packet_type_vals, "Unknown (%u)"));
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_sll, tvb, 0,
+ SLL_HEADER_SIZE, "Linux cooked capture");
+ fh_tree = proto_item_add_subtree(ti, ett_sll);
+ proto_tree_add_item(fh_tree, hf_sll_pkttype, tvb, 0, 2, FALSE);
+ }
+
+ /*
+ * XXX - check the link-layer address type value?
+ * For now, we just assume 6 means Ethernet.
+ */
+ hatype = tvb_get_ntohs(tvb, 2);
+ halen = tvb_get_ntohs(tvb, 4);
+ if (tree) {
+ proto_tree_add_uint(fh_tree, hf_sll_hatype, tvb, 2, 2, hatype);
+ proto_tree_add_uint(fh_tree, hf_sll_halen, tvb, 4, 2, halen);
+ }
+ if (halen == 6) {
+ src = tvb_get_ptr(tvb, 6, 6);
+ SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src);
+ SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src);
+ if (tree) {
+ proto_tree_add_ether(fh_tree, hf_sll_src_eth, tvb,
+ 6, 6, src);
+ }
+ } else {
+ if (tree) {
+ proto_tree_add_item(fh_tree, hf_sll_src_other, tvb,
+ 6, halen, FALSE);
+ }
+ }
+
+ protocol = tvb_get_ntohs(tvb, 14);
+ if (protocol <= 1536) { /* yes, 1536 - that's how Linux does it */
+ /*
+ * "proto" is *not* a length field, it's a Linux internal
+ * protocol type.
+ * We therefore cannot say how much of the packet will
+ * be trailer data.
+ * XXX - do the same thing we do for packets with Ethertypes?
+ */
+ proto_tree_add_uint(fh_tree, hf_sll_ltype, tvb, 14, 2,
+ protocol);
+
+ next_tvb = tvb_new_subset(tvb, SLL_HEADER_SIZE, -1, -1);
+ switch (protocol) {
+
+ case LINUX_SLL_P_802_2:
+ /*
+ * 802.2 LLC.
+ */
+ call_dissector(llc_handle, next_tvb, pinfo, tree);
+ break;
+
+ case LINUX_SLL_P_802_3:
+ /*
+ * Novell IPX inside 802.3 with no 802.2 LLC
+ * header.
+ */
+ call_dissector(ipx_handle, next_tvb, pinfo, tree);
+ break;
+
+ default:
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ break;
+ }
+ } else {
+ ethertype(protocol, tvb, SLL_HEADER_SIZE, pinfo, tree,
+ fh_tree, hf_sll_etype, hf_sll_trailer, 0);
+ }
+}
+
+void
+proto_register_sll(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_sll_pkttype,
+ { "Packet type", "sll.pkttype", FT_UINT16, BASE_DEC,
+ VALS(packet_type_vals), 0x0, "Packet type", HFILL }},
+
+ /* ARP hardware type? With Linux extensions? */
+ { &hf_sll_hatype,
+ { "Link-layer address type", "sll.hatype", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Link-layer address type", HFILL }},
+
+ { &hf_sll_halen,
+ { "Link-layer address length", "sll.halen", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Link-layer address length", HFILL }},
+
+ /* Source address if it's an Ethernet-type address */
+ { &hf_sll_src_eth,
+ { "Source", "sll.src.eth", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Source link-layer address", HFILL }},
+
+ /* Source address if it's not an Ethernet-type address */
+ { &hf_sll_src_other,
+ { "Source", "sll.src.other", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Source link-layer address", HFILL }},
+
+ /* if the protocol field is an internal Linux protocol type */
+ { &hf_sll_ltype,
+ { "Protocol", "sll.ltype", FT_UINT16, BASE_HEX,
+ VALS(ltype_vals), 0x0, "Linux protocol type", HFILL }},
+
+ /* registered here but handled in ethertype.c */
+ { &hf_sll_etype,
+ { "Protocol", "sll.etype", FT_UINT16, BASE_HEX,
+ VALS(etype_vals), 0x0, "Ethernet protocol type", HFILL }},
+
+ { &hf_sll_trailer,
+ { "Trailer", "sll.trailer", FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Trailer", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_sll,
+ };
+
+ proto_sll = proto_register_protocol("Linux cooked-mode capture",
+ "SLL", "sll" );
+ proto_register_field_array(proto_sll, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_sll(void)
+{
+ dissector_handle_t sll_handle;
+
+ /*
+ * Get handles for the IPX and LLC dissectors.
+ */
+ llc_handle = find_dissector("llc");
+ ipx_handle = find_dissector("ipx");
+ data_handle = find_dissector("data");
+
+ sll_handle = create_dissector_handle(dissect_sll, proto_sll);
+ dissector_add("wtap_encap", WTAP_ENCAP_SLL, sll_handle);
+}
diff --git a/epan/dissectors/packet-sll.h b/epan/dissectors/packet-sll.h
new file mode 100644
index 0000000000..e108e9f13d
--- /dev/null
+++ b/epan/dissectors/packet-sll.h
@@ -0,0 +1,29 @@
+/* packet-sll.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 2001 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_SLL_H__
+#define __PACKET_SLL_H__
+
+void capture_sll(const guchar *, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-slowprotocols.c b/epan/dissectors/packet-slowprotocols.c
new file mode 100644
index 0000000000..aa50a31b3a
--- /dev/null
+++ b/epan/dissectors/packet-slowprotocols.c
@@ -0,0 +1,819 @@
+/* packet-slowprotocols.c
+ * Routines for EtherType (0x8809) Slow Protocols disassembly.
+ *
+ * $Id$
+ *
+ * Copyright 2002 Steve Housley <steve_housley@3com.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+ /* *** WARNING!! *** Only a dissector for LACPDU (Link Aggregation Control
+ * Protocol Data Unit) disassembly has currently been implemented.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "etypes.h"
+#include "llcsaps.h"
+#include "ppptypes.h"
+#include <epan/resolv.h>
+
+/* Offsets of fields within a LACPDU */
+
+#define LACPDU_SUBTYPE 0
+#define LACPDU_VERSION_NUMBER 1
+
+#define LACPDU_ACTOR_TYPE 2
+#define LACPDU_ACTOR_INFO_LEN 3
+#define LACPDU_ACTOR_SYS_PRIORITY 4
+#define LACPDU_ACTOR_SYSTEM 6
+#define LACPDU_ACTOR_KEY 12
+#define LACPDU_ACTOR_PORT_PRIORITY 14
+#define LACPDU_ACTOR_PORT 16
+#define LACPDU_ACTOR_STATE 18
+#define LACPDU_ACTOR_RESERVED 19
+
+#define LACPDU_PARTNER_TYPE 22
+#define LACPDU_PARTNER_INFO_LEN 23
+#define LACPDU_PARTNER_SYS_PRIORITY 24
+#define LACPDU_PARTNER_SYSTEM 26
+#define LACPDU_PARTNER_KEY 32
+#define LACPDU_PARTNER_PORT_PRIORITY 34
+#define LACPDU_PARTNER_PORT 36
+#define LACPDU_PARTNER_STATE 38
+#define LACPDU_PARTNER_RESERVED 39
+
+#define LACPDU_COLL_TYPE 42
+#define LACPDU_COLL_INFO_LEN 43
+#define LACPDU_COLL_MAX_DELAY 44
+#define LACPDU_COLL_RESERVED 46
+
+#define LACPDU_TERM_TYPE 58
+#define LACPDU_TERM_LEN 59
+#define LACPDU_TERM_RESERVED 60
+
+/* Actor and Partner Flag bits */
+
+#define LACPDU_FLAGS_ACTIVITY 0x01
+#define LACPDU_FLAGS_TIMEOUT 0x02
+#define LACPDU_FLAGS_AGGREGATION 0x04
+#define LACPDU_FLAGS_SYNC 0x08
+#define LACPDU_FLAGS_COLLECTING 0x10
+#define LACPDU_FLAGS_DISTRIB 0x20
+#define LACPDU_FLAGS_DEFAULTED 0x40
+#define LACPDU_FLAGS_EXPIRED 0x80
+
+/* Initialise the protocol and registered fields */
+
+static int proto_lacpdu = -1;
+
+static int hf_lacpdu_subtype = -1;
+static int hf_lacpdu_version_number = -1;
+
+static int hf_lacpdu_actor_type = -1;
+static int hf_lacpdu_actor_info_len = -1;
+static int hf_lacpdu_actor_sys_priority = -1;
+static int hf_lacpdu_actor_sys = -1;
+static int hf_lacpdu_actor_key = -1;
+static int hf_lacpdu_actor_port_priority = -1;
+static int hf_lacpdu_actor_port = -1;
+static int hf_lacpdu_actor_state = -1;
+static int hf_lacpdu_flags_a_activity = -1;
+static int hf_lacpdu_flags_a_timeout = -1;
+static int hf_lacpdu_flags_a_aggregation = -1;
+static int hf_lacpdu_flags_a_sync = -1;
+static int hf_lacpdu_flags_a_collecting = -1;
+static int hf_lacpdu_flags_a_distrib = -1;
+static int hf_lacpdu_flags_a_defaulted = -1;
+static int hf_lacpdu_flags_a_expired = -1;
+static int hf_lacpdu_actor_reserved = -1;
+
+static int hf_lacpdu_partner_type = -1;
+static int hf_lacpdu_partner_info_len = -1;
+static int hf_lacpdu_partner_sys_priority = -1;
+static int hf_lacpdu_partner_sys = -1;
+static int hf_lacpdu_partner_key = -1;
+static int hf_lacpdu_partner_port_priority = -1;
+static int hf_lacpdu_partner_port = -1;
+static int hf_lacpdu_partner_state = -1;
+static int hf_lacpdu_flags_p_activity = -1;
+static int hf_lacpdu_flags_p_timeout = -1;
+static int hf_lacpdu_flags_p_aggregation = -1;
+static int hf_lacpdu_flags_p_sync = -1;
+static int hf_lacpdu_flags_p_collecting = -1;
+static int hf_lacpdu_flags_p_distrib = -1;
+static int hf_lacpdu_flags_p_defaulted = -1;
+static int hf_lacpdu_flags_p_expired = -1;
+static int hf_lacpdu_partner_reserved = -1;
+
+static int hf_lacpdu_coll_type = -1;
+static int hf_lacpdu_coll_info_len = -1;
+static int hf_lacpdu_coll_max_delay = -1;
+static int hf_lacpdu_coll_reserved = -1;
+
+static int hf_lacpdu_term_type = -1;
+static int hf_lacpdu_term_len = -1;
+static int hf_lacpdu_term_reserved = -1;
+
+/* Initialise the subtree pointers */
+
+static gint ett_lacpdu = -1;
+static gint ett_lacpdu_a_flags = -1;
+static gint ett_lacpdu_p_flags = -1;
+
+/* General declarations and macros */
+
+#define LACP_SUBTYPE 0x1
+
+static const char initial_sep[] = " (";
+static const char cont_sep[] = ", ";
+
+#define APPEND_BOOLEAN_FLAG(flag, item, string) \
+ if(flag){ \
+ if(item) \
+ proto_item_append_text(item, string, sep); \
+ sep = cont_sep; \
+ }
+
+/* Code to actually dissect the LACPDU packets */
+static void
+dissect_lacpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 raw_word;
+ guint8 raw_octet;
+
+ guint8 flags;
+
+ const guint8 *a_sys;
+ const guint8 *p_sys;
+ const guint8 *resv_bytes;
+
+ proto_tree *lacpdu_tree;
+ proto_item *lacpdu_item;
+ proto_tree *actor_flags_tree;
+ proto_item *actor_flags_item;
+ proto_tree *partner_flags_tree;
+ proto_item *partner_flags_item;
+
+
+ const char *sep;
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LACP"); /* LACP Protocol */
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ if (tree)
+ {
+ /* Add LACP Heading */
+ lacpdu_item = proto_tree_add_protocol_format(tree, proto_lacpdu, tvb,
+ 0, -1, "Link Aggregation Control Protocol");
+ lacpdu_tree = proto_item_add_subtree(lacpdu_item, ett_lacpdu);
+
+ /* Version Number */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_VERSION_NUMBER);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_version_number, tvb,
+ LACPDU_VERSION_NUMBER, 1, raw_octet);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Version %d. ", raw_octet);
+ }
+
+ /* Actor Type */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_ACTOR_TYPE);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_type, tvb,
+ LACPDU_ACTOR_TYPE, 1, raw_octet);
+
+ /* Actor Info Length */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_ACTOR_INFO_LEN);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_info_len, tvb,
+ LACPDU_ACTOR_INFO_LEN, 1, raw_octet);
+
+ /* Actor System Priority */
+
+ raw_word = tvb_get_ntohs(tvb, LACPDU_ACTOR_SYS_PRIORITY);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_sys_priority, tvb,
+ LACPDU_ACTOR_SYS_PRIORITY, 2, raw_word);
+ /* Actor System */
+
+ a_sys = tvb_get_ptr(tvb, LACPDU_ACTOR_SYSTEM , 6);
+ proto_tree_add_ether(lacpdu_tree, hf_lacpdu_actor_sys, tvb,
+ LACPDU_ACTOR_SYSTEM, 6, a_sys);
+
+ /* Actor Key */
+
+ raw_word = tvb_get_ntohs(tvb, LACPDU_ACTOR_KEY);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_key, tvb,
+ LACPDU_ACTOR_KEY, 2, raw_word);
+
+ /* Actor Port Priority */
+
+ raw_word = tvb_get_ntohs(tvb, LACPDU_ACTOR_PORT_PRIORITY);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_port_priority, tvb,
+ LACPDU_ACTOR_PORT_PRIORITY, 2, raw_word);
+
+ /* Actor Port */
+
+ raw_word = tvb_get_ntohs(tvb, LACPDU_ACTOR_PORT);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_port, tvb,
+ LACPDU_ACTOR_PORT, 2, raw_word);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Actor Port = %d ", raw_word);
+ }
+
+ /* Actor State */
+
+ flags = tvb_get_guint8(tvb, LACPDU_ACTOR_STATE);
+ actor_flags_item = proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_state, tvb,
+ LACPDU_ACTOR_STATE, 1, flags);
+ actor_flags_tree = proto_item_add_subtree(actor_flags_item, ett_lacpdu_a_flags);
+
+ sep = initial_sep;
+
+ /* Activity Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_ACTIVITY, actor_flags_item,
+ "%sActivity");
+ proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_activity, tvb,
+ LACPDU_ACTOR_STATE, 1, flags);
+
+ /* Timeout Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_TIMEOUT, actor_flags_item,
+ "%sTimeout");
+ proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_timeout, tvb,
+ LACPDU_ACTOR_STATE, 1, flags);
+
+ /* Aggregation Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_AGGREGATION, actor_flags_item,
+ "%sAggregation");
+ proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_aggregation, tvb,
+ LACPDU_ACTOR_STATE, 1, flags);
+
+ /* Synchronization Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_SYNC, actor_flags_item,
+ "%sSynchronization");
+ proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_sync, tvb,
+ LACPDU_ACTOR_STATE, 1, flags);
+
+ /* Collecting Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_COLLECTING, actor_flags_item,
+ "%sCollecting");
+ proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_collecting, tvb,
+ LACPDU_ACTOR_STATE, 1, flags);
+
+
+ /* Distributing Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_DISTRIB, actor_flags_item,
+ "%sDistributing");
+ proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_distrib, tvb,
+ LACPDU_ACTOR_STATE, 1, flags);
+
+ /* Defaulted Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_DEFAULTED, actor_flags_item,
+ "%sDefaulted");
+ proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_defaulted, tvb,
+ LACPDU_ACTOR_STATE, 1, flags);
+
+ /* Expired Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_EXPIRED, actor_flags_item,
+ "%sExpired");
+ proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_expired, tvb,
+ LACPDU_ACTOR_STATE, 1, flags);
+
+ sep = cont_sep;
+ if (sep != initial_sep)
+ {
+ /* We put something in; put in the terminating ")" */
+ proto_item_append_text(actor_flags_item, ")");
+ }
+
+ /* Actor Reserved */
+
+ resv_bytes = tvb_get_ptr(tvb, LACPDU_ACTOR_RESERVED, 3);
+ proto_tree_add_bytes(lacpdu_tree, hf_lacpdu_actor_reserved, tvb,
+ LACPDU_ACTOR_RESERVED, 3, resv_bytes);
+
+
+ /* Partner Type */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_PARTNER_TYPE);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_type, tvb,
+ LACPDU_PARTNER_TYPE, 1, raw_octet);
+
+ /* Partner Info Length */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_PARTNER_INFO_LEN);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_info_len, tvb,
+ LACPDU_PARTNER_INFO_LEN, 1, raw_octet);
+
+ /* Partner System Priority */
+
+ raw_word = tvb_get_ntohs(tvb, LACPDU_PARTNER_SYS_PRIORITY);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_sys_priority, tvb,
+ LACPDU_PARTNER_SYS_PRIORITY, 2, raw_word);
+
+ /* Partner System */
+
+ p_sys = tvb_get_ptr(tvb, LACPDU_PARTNER_SYSTEM, 6);
+ proto_tree_add_ether(lacpdu_tree, hf_lacpdu_partner_sys, tvb,
+ LACPDU_PARTNER_SYSTEM, 6, p_sys);
+
+ /* Partner Key */
+
+ raw_word = tvb_get_ntohs(tvb, LACPDU_PARTNER_KEY);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_key, tvb,
+ LACPDU_PARTNER_KEY, 2, raw_word);
+
+ /* Partner Port Priority */
+
+ raw_word = tvb_get_ntohs(tvb, LACPDU_PARTNER_PORT_PRIORITY);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_port_priority, tvb,
+ LACPDU_PARTNER_PORT_PRIORITY, 2, raw_word);
+
+ /* Partner Port */
+
+ raw_word = tvb_get_ntohs(tvb, LACPDU_PARTNER_PORT);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_port, tvb,
+ LACPDU_PARTNER_PORT, 2, raw_word);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Partner Port = %d ", raw_word);
+ }
+
+ /* Partner State */
+
+ flags = tvb_get_guint8(tvb, LACPDU_PARTNER_STATE);
+ partner_flags_item = proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_state, tvb,
+ LACPDU_PARTNER_STATE, 1, flags);
+ partner_flags_tree = proto_item_add_subtree(partner_flags_item, ett_lacpdu_p_flags);
+
+ sep = initial_sep;
+
+ /* Activity Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_ACTIVITY, partner_flags_item,
+ "%sActivity");
+ proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_activity, tvb,
+ LACPDU_PARTNER_STATE, 1, flags);
+
+ /* Timeout Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_TIMEOUT, partner_flags_item,
+ "%sTimeout");
+ proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_timeout, tvb,
+ LACPDU_PARTNER_STATE, 1, flags);
+
+ /* Aggregation Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_AGGREGATION, partner_flags_item,
+ "%sAggregation");
+ proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_aggregation, tvb,
+ LACPDU_PARTNER_STATE, 1, flags);
+
+ /* Synchronization Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_SYNC, partner_flags_item,
+ "%sSynchronization");
+ proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_sync, tvb,
+ LACPDU_PARTNER_STATE, 1, flags);
+
+ /* Collecting Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_COLLECTING, partner_flags_item,
+ "%sCollecting");
+ proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_collecting, tvb,
+ LACPDU_PARTNER_STATE, 1, flags);
+
+
+ /* Distributing Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_DISTRIB, partner_flags_item,
+ "%sDistributing");
+ proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_distrib, tvb,
+ LACPDU_PARTNER_STATE, 1, flags);
+
+ /* Defaulted Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_DEFAULTED, partner_flags_item,
+ "%sDefaulted");
+ proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_defaulted, tvb,
+ LACPDU_PARTNER_STATE, 1, flags);
+
+ /* Expired Flag */
+
+ APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_EXPIRED, partner_flags_item,
+ "%sExpired");
+ proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_expired, tvb,
+ LACPDU_PARTNER_STATE, 1, flags);
+
+ sep = cont_sep;
+ if (sep != initial_sep)
+ {
+ /* We put something in; put in the terminating ")" */
+ proto_item_append_text(partner_flags_item, ")");
+ }
+
+ /* Partner Reserved */
+
+ resv_bytes = tvb_get_ptr(tvb, LACPDU_PARTNER_RESERVED, 3);
+ proto_tree_add_bytes(lacpdu_tree, hf_lacpdu_partner_reserved, tvb,
+ LACPDU_PARTNER_RESERVED, 3, resv_bytes);
+
+
+ /* Collector Type */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_COLL_TYPE);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_coll_type, tvb,
+ LACPDU_COLL_TYPE, 1, raw_octet);
+
+ /* Collector Info Length */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_COLL_INFO_LEN);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_coll_info_len, tvb,
+ LACPDU_COLL_INFO_LEN, 1, raw_octet);
+
+ /* Collector Max Delay */
+
+ raw_word = tvb_get_ntohs(tvb, LACPDU_COLL_MAX_DELAY);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_coll_max_delay, tvb,
+ LACPDU_COLL_MAX_DELAY, 2, raw_word);
+
+ /* Collector Reserved */
+
+ resv_bytes = tvb_get_ptr(tvb, LACPDU_COLL_RESERVED, 12);
+ proto_tree_add_bytes(lacpdu_tree, hf_lacpdu_coll_reserved, tvb,
+ LACPDU_COLL_RESERVED, 12, resv_bytes);
+
+ /* Terminator Type */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_TERM_TYPE);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_term_type, tvb,
+ LACPDU_TERM_TYPE, 1, raw_octet);
+
+ /* Terminator Info Length */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_TERM_LEN);
+ proto_tree_add_uint(lacpdu_tree, hf_lacpdu_term_len, tvb,
+ LACPDU_TERM_LEN, 1, raw_octet);
+
+ /* Terminator Reserved */
+
+ resv_bytes = tvb_get_ptr(tvb, LACPDU_TERM_RESERVED, 50);
+ proto_tree_add_bytes(lacpdu_tree, hf_lacpdu_term_reserved, tvb,
+ LACPDU_TERM_RESERVED, 50, resv_bytes);
+ }
+}
+
+
+/* Code to dissect the Slow Protocol packets */
+static void
+dissect_slow_protocols(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 raw_octet;
+
+ if (tree)
+ {
+
+ /* Get the Slow Protocol Subtype value */
+ raw_octet = tvb_get_guint8(tvb, LACPDU_SUBTYPE);
+
+ if (raw_octet != LACP_SUBTYPE)
+ {
+ /* This is not a LACPDU. Do not disassemble. */
+ /* Requires implementation at a later date. */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Slow Protocols"); /* Slow Protocols */
+ }
+
+ /* Display the subtype value to aid the user. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Subtype = %u.", raw_octet);
+ }
+ return;
+ }
+ }
+
+ /* This is a LACPDU so decode it! */
+ dissect_lacpdu(tvb, pinfo, tree);
+}
+
+
+
+/* Register the protocol with Ethereal */
+
+static const value_string subtype_vals[] = {
+ { 1, "LACP" },
+ { 2, "Marker Protocol" },
+ { 0, NULL }
+};
+
+static const true_false_string yesno = {
+ "Yes",
+ "No"
+};
+
+void
+proto_register_lacpdu(void)
+{
+/* Setup list of header fields */
+
+ static hf_register_info hf[] = {
+
+ { &hf_lacpdu_subtype,
+ { "Subtype", "lacp.subtype",
+ FT_UINT8, BASE_HEX, VALS(subtype_vals), 0x0,
+ "The specific Slow Protocol being used", HFILL }},
+
+ { &hf_lacpdu_version_number,
+ { "LACP Version Number", "lacp.version",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Identifies the LACP version", HFILL }},
+
+ { &hf_lacpdu_actor_type,
+ { "Actor Information", "lacp.actorInfo",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "TLV type = Actor", HFILL }},
+
+ { &hf_lacpdu_actor_info_len,
+ { "Actor Information Length", "lacp.actorInfoLen",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "The length of the Actor TLV", HFILL }},
+
+ { &hf_lacpdu_actor_sys_priority,
+ { "Actor System Priority", "lacp.actorSysPriority",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The priority assigned to this System by management or admin", HFILL }},
+
+ { &hf_lacpdu_actor_sys,
+ { "Actor System", "lacp.actorSystem",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "The Actor's System ID encoded as a MAC address", HFILL }},
+
+ { &hf_lacpdu_actor_key,
+ { "Actor Key", "lacp.actorKey",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The operational Key value assigned to the port by the Actor", HFILL }},
+
+ { &hf_lacpdu_actor_port_priority,
+ { "Actor Port Priority", "lacp.actorPortPriority",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The priority assigned to the port by the Actor (via Management or Admin)", HFILL }},
+
+ { &hf_lacpdu_actor_port,
+ { "Actor Port", "lacp.actorPort",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The port number assigned to the port by the Actor (via Management or Admin)", HFILL }},
+
+ { &hf_lacpdu_actor_state,
+ { "Actor State", "lacp.actorState",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "The Actor's state variables for the port, encoded as bits within a single octet", HFILL }},
+
+ { &hf_lacpdu_flags_a_activity,
+ { "LACP Activity", "lacp.actorState.activity",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_ACTIVITY,
+ "Activity control value for this link. Active = 1, Passive = 0", HFILL }},
+
+ { &hf_lacpdu_flags_a_timeout,
+ { "LACP Timeout", "lacp.actorState.timeout",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_TIMEOUT,
+ "Timeout control value for this link. Short Timeout = 1, Long Timeout = 0", HFILL }},
+
+
+ { &hf_lacpdu_flags_a_aggregation,
+ { "Aggregation", "lacp.actorState.aggregation",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_AGGREGATION,
+ "Aggregatable = 1, Individual = 0", HFILL }},
+
+
+ { &hf_lacpdu_flags_a_sync,
+ { "Synchronization", "lacp.actorState.synchronization",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_SYNC,
+ "In Sync = 1, Out of Sync = 0", HFILL }},
+
+
+ { &hf_lacpdu_flags_a_collecting,
+ { "Collecting", "lacp.actorState.collecting",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_COLLECTING,
+ "Collection of incoming frames is: Enabled = 1, Disabled = 0", HFILL }},
+
+
+ { &hf_lacpdu_flags_a_distrib,
+ { "Distributing", "lacp.actorState.distributing",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_DISTRIB,
+ "Distribution of outgoing frames is: Enabled = 1, Disabled = 0", HFILL }},
+
+
+
+ { &hf_lacpdu_flags_a_defaulted,
+ { "Defaulted", "lacp.actorState.defaulted",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_DEFAULTED,
+ "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
+
+
+ { &hf_lacpdu_flags_a_expired,
+ { "Expired", "lacp.actorState.expired",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_EXPIRED,
+ "1 = Actor Rx machine is EXPIRED, 0 = is NOT EXPIRED", HFILL }},
+
+
+ { &hf_lacpdu_actor_reserved,
+ { "Reserved", "lacp.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_lacpdu_partner_type,
+ { "Partner Information", "lacp.partnerInfo",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "TLV type = Partner", HFILL }},
+
+ { &hf_lacpdu_partner_info_len,
+ { "Partner Information Length", "lacp.partnerInfoLen",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "The length of the Partner TLV", HFILL }},
+
+ { &hf_lacpdu_partner_sys_priority,
+ { "Partner System Priority", "lacp.partnerSysPriority",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The priority assigned to the Partner System by management or admin", HFILL }},
+
+ { &hf_lacpdu_partner_sys,
+ { "Partner System", "lacp.partnerSystem",
+ FT_ETHER, BASE_NONE, NULL, 0x0,
+ "The Partner's System ID encoded as a MAC address", HFILL }},
+
+ { &hf_lacpdu_partner_key,
+ { "Partner Key", "lacp.partnerKey",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The operational Key value assigned to the port associated with this link by the Partner", HFILL }},
+
+ { &hf_lacpdu_partner_port_priority,
+ { "Partner Port Priority", "lacp.partnerPortPriority",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The priority assigned to the port by the Partner (via Management or Admin)", HFILL }},
+
+ { &hf_lacpdu_partner_port,
+ { "Partner Port", "lacp.partnerPort",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The port number associated with this link assigned to the port by the Partner (via Management or Admin)", HFILL }},
+
+ { &hf_lacpdu_partner_state,
+ { "Partner State", "lacp.partnerState",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "The Partner's state variables for the port, encoded as bits within a single octet", HFILL }},
+
+ { &hf_lacpdu_flags_p_activity,
+ { "LACP Activity", "lacp.partnerState.activity",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_ACTIVITY,
+ "Activity control value for this link. Active = 1, Passive = 0", HFILL }},
+
+ { &hf_lacpdu_flags_p_timeout,
+ { "LACP Timeout", "lacp.partnerState.timeout",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_TIMEOUT,
+ "Timeout control value for this link. Short Timeout = 1, Long Timeout = 0", HFILL }},
+
+
+ { &hf_lacpdu_flags_p_aggregation,
+ { "Aggregation", "lacp.partnerState.aggregation",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_AGGREGATION,
+ "Aggregatable = 1, Individual = 0", HFILL }},
+
+
+ { &hf_lacpdu_flags_p_sync,
+ { "Synchronization", "lacp.partnerState.synchronization",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_SYNC,
+ "In Sync = 1, Out of Sync = 0", HFILL }},
+
+
+ { &hf_lacpdu_flags_p_collecting,
+ { "Collecting", "lacp.partnerState.collecting",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_COLLECTING,
+ "Collection of incoming frames is: Enabled = 1, Disabled = 0", HFILL }},
+
+
+ { &hf_lacpdu_flags_p_distrib,
+ { "Distributing", "lacp.partnerState.distributing",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_DISTRIB,
+ "Distribution of outgoing frames is: Enabled = 1, Disabled = 0", HFILL }},
+
+
+
+ { &hf_lacpdu_flags_p_defaulted,
+ { "Defaulted", "lacp.partnerState.defaulted",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_DEFAULTED,
+ "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
+
+
+ { &hf_lacpdu_flags_p_expired,
+ { "Expired", "lacp.partnerState.expired",
+ FT_BOOLEAN, 8, TFS(&yesno), LACPDU_FLAGS_EXPIRED,
+ "1 = Actor Rx machine is EXPIRED, 0 = is NOT EXPIRED", HFILL }},
+
+
+ { &hf_lacpdu_partner_reserved,
+ { "Reserved", "lacp.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_lacpdu_coll_type,
+ { "Collector Information", "lacp.collectorInfo",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "TLV type = Collector", HFILL }},
+
+ { &hf_lacpdu_coll_info_len,
+ { "Collector Information Length", "lacp.collectorInfoLen",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "The length of the Collector TLV", HFILL }},
+
+ { &hf_lacpdu_coll_max_delay,
+ { "Collector Max Delay", "lacp.collectorMaxDelay",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "The max delay of the station tx'ing the LACPDU (in tens of usecs)", HFILL }},
+
+ { &hf_lacpdu_coll_reserved,
+ { "Reserved", "lacp.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+
+ { &hf_lacpdu_term_type,
+ { "Terminator Information", "lacp.termInfo",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "TLV type = Terminator", HFILL }},
+
+ { &hf_lacpdu_term_len,
+ { "Terminator Length", "lacp.termLen",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "The length of the Terminator TLV", HFILL }},
+
+ { &hf_lacpdu_term_reserved,
+ { "Reserved", "lacp.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ };
+
+ /* Setup protocol subtree array */
+
+ static gint *ett[] = {
+ &ett_lacpdu,
+ &ett_lacpdu_a_flags,
+ &ett_lacpdu_p_flags,
+ };
+
+ /* Register the protocol name and description */
+
+ proto_lacpdu = proto_register_protocol("Link Aggregation Control Protocol", "LACP", "lacp");
+
+ /* Required function calls to register the header fields and subtrees used */
+
+ proto_register_field_array(proto_lacpdu, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+void
+proto_reg_handoff_lacpdu(void)
+{
+ dissector_handle_t slow_protocols_handle;
+
+ slow_protocols_handle = create_dissector_handle(dissect_slow_protocols, proto_lacpdu);
+ dissector_add("ethertype", ETHERTYPE_SLOW_PROTOCOLS, slow_protocols_handle);
+}
diff --git a/epan/dissectors/packet-slsk.c b/epan/dissectors/packet-slsk.c
new file mode 100644
index 0000000000..a9f75795e8
--- /dev/null
+++ b/epan/dissectors/packet-slsk.c
@@ -0,0 +1,2480 @@
+/* packet-slsk.c
+ * Routines for SoulSeek Protocol dissection
+ * Copyright 2003, Christian Wagner <Christian.Wagner@stud.uni-karlsruhe.de>
+ * Institute of Telematics - University of Karlsruhe
+ * part of this work supported by
+ * Deutsche Forschungsgemeinschaft (DFG) Grant Number FU448/1
+ *
+ * SoulSeek Protocol dissector based on protocol descriptions from SoleSeek Project:
+ * http://cvs.sourceforge.net/viewcvs.py/soleseek/SoleSeek/doc/protocol.html?rev=HEAD
+ * Updated for SoulSeek client version 151
+ *
+ * $Id$
+ *
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/tvbuff.h>
+#include "packet-tcp.h"
+#include "prefs.h"
+
+/* Initialize the protocol and registered fields */
+static int proto_slsk = -1;
+
+static int hf_slsk_integer = -1;
+static int hf_slsk_string = -1;
+static int hf_slsk_byte = -1;
+static int hf_slsk_message_length = -1;
+static int hf_slsk_message_code = -1;
+static int hf_slsk_client_ip = -1;
+static int hf_slsk_server_ip = -1;
+static int hf_slsk_string_length = -1;
+static int hf_slsk_username = -1;
+static int hf_slsk_password = -1;
+static int hf_slsk_version = -1;
+static int hf_slsk_login_successfull = -1;
+static int hf_slsk_login_message = -1;
+static int hf_slsk_port = -1;
+static int hf_slsk_ip = -1;
+static int hf_slsk_user_exists = -1;
+static int hf_slsk_status_code = -1;
+static int hf_slsk_room = -1;
+static int hf_slsk_chat_message = -1;
+static int hf_slsk_users_in_room = -1;
+static int hf_slsk_token = -1;
+static int hf_slsk_connection_type = -1;
+static int hf_slsk_chat_message_id = -1;
+static int hf_slsk_timestamp = -1;
+static int hf_slsk_search_text = -1;
+static int hf_slsk_folder_count = -1;
+static int hf_slsk_file_count = -1;
+static int hf_slsk_average_speed = -1;
+static int hf_slsk_download_number = -1;
+static int hf_slsk_files = -1;
+static int hf_slsk_directories = -1;
+static int hf_slsk_slotsfull = -1;
+static int hf_slsk_place_in_queue = -1;
+static int hf_slsk_number_of_rooms = -1;
+static int hf_slsk_filename = -1;
+static int hf_slsk_directory = -1;
+static int hf_slsk_size = -1;
+static int hf_slsk_checksum = -1;
+static int hf_slsk_code = -1;
+static int hf_slsk_number_of_users = -1;
+static int hf_slsk_number_of_days = -1;
+static int hf_slsk_transfer_direction = -1;
+static int hf_slsk_user_description = -1;
+static int hf_slsk_picture_exists = -1;
+static int hf_slsk_picture = -1;
+static int hf_slsk_user_uploads = -1;
+static int hf_slsk_total_uploads = -1;
+static int hf_slsk_queued_uploads = -1;
+static int hf_slsk_slots_available = -1;
+static int hf_slsk_allowed = -1;
+static int hf_slsk_compr_packet = -1;
+static int hf_slsk_parent_min_speed = -1;
+static int hf_slsk_parent_speed_connection_ratio = -1;
+static int hf_slsk_seconds_parent_inactivity_before_disconnect = -1;
+static int hf_slsk_seconds_server_inactivity_before_disconnect = -1;
+static int hf_slsk_nodes_in_cache_before_disconnect = -1;
+static int hf_slsk_seconds_before_ping_children = -1;
+static int hf_slsk_recommendation = -1;
+static int hf_slsk_ranking = -1;
+
+
+/* Initialize the subtree pointers */
+static gint ett_slsk = -1;
+static gint ett_slsk_compr_packet = -1;
+
+#define TCP_PORT_SLSK_1 2234
+#define TCP_PORT_SLSK_2 5534
+#define TCP_PORT_SLSK_3 2240
+
+
+/* desegmentation of SoulSeek Message over TCP */
+static gboolean slsk_desegment = TRUE;
+#ifdef HAVE_LIBZ
+static gboolean slsk_decompress = TRUE;
+#else
+static gboolean slsk_decompress = FALSE;
+#endif
+
+static const value_string slsk_tcp_msgs[] = {
+ { 1, "Login"},
+ { 2, "Set Wait Port"},
+ { 3, "Get Peer Address"},
+ { 4, "Get Shared File List"},
+ { 5, "User Exists / Shared File List"},
+ { 7, "Get User Status"},
+ { 9, "File Search Result"},
+ { 13, "Say ChatRoom"},
+ { 14, "Join Room"},
+ { 15, "Leave Room / User Info Request"},
+ { 16, "User Joined Room / User Info Reply"},
+ { 17, "User Left Room"},
+ { 18, "Connect To Peer"},
+ { 22, "Message User"},
+ { 23, "Message User Ack"},
+ { 26, "File Search"},
+ { 28, "Set Status"},
+ { 32, "Ping"},
+ { 34, "Update Upload Speed"},
+ { 35, "Shared Files & Folders"},
+ { 36, "Get User Stats / Folder Contents Request"},
+ { 37, "Folder Contents Response"},
+ { 40, "Queued Downloads / Transfer Request"},
+ { 41, "Transfer Response"},
+ { 42, "Placehold Upload"},
+ { 43, "Queue Upload"},
+ { 44, "Place In Queue"},
+ { 46, "Upload Failed"},
+ { 50, "Queue Failed / Own Recommendation"},
+ { 51, "Add Things I like / Place In Queue Request"},
+ { 52, "Remove Things I like"},
+ { 54, "Get Recommendations"},
+ { 55, "Type 55"},
+ { 56, "Get Global Rankings"},
+ { 57, "Get User Recommendations"},
+ { 58, "Admin Command"},
+ { 60, "Place In Line Response"},
+ { 62, "Room Added"},
+ { 63, "Room Removed"},
+ { 64, "Room List"},
+ { 65, "Exact File Search"},
+ { 66, "Admin Message"},
+ { 67, "Global User List"},
+ { 68, "Tunneled Message"},
+ { 69, "Privileged User List"},
+ { 71, "Get Parent List"},
+ { 73, "Type 73"},
+ { 83, "Parent Min Speed"},
+ { 84, "Parent Speed Connection Ratio"},
+ { 86, "Parent Inactivity Before Disconnect"},
+ { 87, "Server Inactivity Before Disconnect"},
+ { 88, "Nodes In Cache Before Disconnect"},
+ { 90, "Seconds Before Ping Children"},
+ { 91, "Add To Privileged"},
+ { 92, "Check Privileges"},
+ { 93, "Embedded Message"},
+ { 100, "Become Parent"},
+ { 102, "Random Parent Addresses"},
+ { 103, "Send Wishlist Entry"},
+ { 104, "Type 104"},
+ { 110, "Get Similar Users"},
+ { 111, "Get Recommendations for Item"},
+ { 112, "Get Similar Users for Item"},
+ { 1001, "Can't Connect To Peer"},
+};
+
+static const value_string slsk_status_codes[] = {
+ { -1, "Unknown"},
+ { 0, "Offline"},
+ { 1, "Away"},
+ { 2, "Online"},
+};
+
+static const value_string slsk_transfer_direction[] = {
+ { 0, "Download"},
+ { 1, "Upload"},
+};
+
+static const value_string slsk_yes_no[] = {
+ { 0, "No"},
+ { 1, "Yes"},
+};
+
+static const value_string slsk_attr_type[] = {
+ { 0, "Bitrate"},
+ { 1, "Length"},
+ { 2, "VBR"},
+};
+
+static char* connection_type(char con_type[]) {
+ if (strlen(con_type) != 1) return "Unknown";
+ if (con_type[0] == 'D') return "Distributed Search";
+ if (con_type[0] == 'P') return "Peer Connection"; /* "File Search Result / User Info Request / Get Shared File List" */
+ if (con_type[0] == 'F') return "File Transfer";
+ return "Unknown";
+}
+
+static gboolean check_slsk_format(tvbuff_t *tvb, int offset, char format[]){
+
+ /*
+ * Returns TRUE if tvbuff beginning at offset matches a certain format
+ * The format is given by an array of characters standing for a special field type
+ * i - integer (4 bytes)
+ * b - byte (1 byte)
+ * s - string (string_length + 4 bytes)
+ *
+ * * - can be used at the end of a format to ignore any following bytes
+ */
+
+ switch ( format[0] ) {
+ case 'i':
+ if (tvb_length_remaining(tvb, offset) < 4) return FALSE;
+ offset += 4;
+ break;
+ case 'b':
+ if (tvb_length_remaining(tvb, offset) < 1) return FALSE;
+ offset += 1;
+ break;
+ case 's':
+ if (tvb_length_remaining(tvb, offset) < 4) return FALSE;
+ if (tvb_length_remaining(tvb, offset) < (int)tvb_get_letohl(tvb, offset)+4) return FALSE;
+ offset += tvb_get_letohl(tvb, offset)+4;
+ break;
+ case '*':
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+
+ if (format[1] == '\0' ) {
+ if (tvb_length_remaining(tvb, offset) != 0) return FALSE; /* Checks for additional bytes at the end */
+ return TRUE;
+ }
+ return check_slsk_format(tvb, offset, &format[1]);
+
+}
+
+static char* get_message_type(tvbuff_t *tvb) {
+ /*
+ * Checks if the Message Code is known.
+ * If unknown checks if the Message Code is stored in a byte.
+ * Returns the Message Type.
+ */
+ int msg_code = tvb_get_letohl(tvb, 4);
+ gchar *message_type = val_to_str(msg_code, slsk_tcp_msgs, "Unknown");
+ if (strcmp(message_type, "Unknown") == 0) {
+ if (check_slsk_format(tvb, 4, "bisis")) message_type = "Distributed Search";
+ if (check_slsk_format(tvb, 4, "bssi")) message_type = "Peer Init";
+ if (check_slsk_format(tvb, 4, "bi")) message_type = "Pierce Fw";
+ }
+ return message_type;
+}
+
+static guint get_slsk_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint32 msg_len;
+ msg_len = tvb_get_letohl(tvb, offset);
+ /* That length doesn't include the length field itself; add that in. */
+ msg_len += 4;
+ return msg_len;
+}
+
+/* Code to actually dissect the packets */
+
+static void dissect_slsk_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+/* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *slsk_tree;
+
+ int offset, i, j;
+ guint32 msg_len, msg_code;
+ gchar *message_type;
+
+ int comprlen = 0;
+ int uncomprlen = 0;
+ int uncompr_tvb_offset = 0;
+ int i2 = 0;
+ int j2 = 0;
+ int i3 = 0;
+ int j3 = 0;
+
+ offset = 0;
+
+ msg_len = tvb_get_letohl(tvb, offset);
+ msg_code = tvb_get_letohl(tvb, offset+4);
+ message_type = get_message_type(tvb);
+
+/* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "slsk");
+
+/* This field shows up as the "Info" column in the display */
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "SoulSeek Message");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", message_type);
+ }
+
+
+ if (tree) {
+
+/* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_slsk, tvb, 0, -1, FALSE);
+ slsk_tree = proto_item_add_subtree(ti, ett_slsk);
+
+/* Continue adding tree items to process the packet here */
+
+ proto_tree_add_uint(slsk_tree, hf_slsk_message_length, tvb, offset, 4, msg_len);
+ offset += 4;
+
+ switch (msg_code) {
+
+ case 1:
+ if (check_slsk_format(tvb, offset, "issi")) {
+ /* Client-to-Server */
+ message_type = "Login";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_password, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_version, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "ibs") || check_slsk_format(tvb, offset, "ibsi")) {
+ /* Server-to-Client */
+ message_type = "Login Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ i=tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_login_successfull, tvb, offset, 1, tvb_get_guint8(tvb, offset),
+ "Login successfull: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
+ offset += 1;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_login_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ if (i == 1){
+ proto_tree_add_ipv4(slsk_tree, hf_slsk_client_ip, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ }
+ }
+ break;
+
+ case 2:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Client-to-Server */
+ message_type = "Set Wait Port";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_port, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 3:
+ if (check_slsk_format(tvb, offset, "isii")) {
+ /* Server-to-Client */
+ message_type = "Get Peer Address Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_ipv4(slsk_tree, hf_slsk_ip, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_port, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server */
+ message_type = "Get Peer Address";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 4:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Client */
+ message_type = "Get Shared File List";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ break;
+
+ case 5:
+ if (check_slsk_format(tvb, offset, "isb")) {
+ /* Server-to-Client */
+ message_type = "User Exists Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_user_exists, tvb, offset, 1, tvb_get_guint8(tvb, offset),
+ "User exists: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
+ offset += 1;
+ }
+ else if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server */
+ message_type = "User Exists Request";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "i*")) {
+ /* Client-to-Client */
+ message_type = "Shared File List";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+
+ /* [zlib compressed] */
+ comprlen = tvb_length_remaining(tvb, offset);
+
+ if (slsk_decompress == TRUE){
+
+ tvbuff_t *uncompr_tvb = tvb_uncompress(tvb, offset, comprlen);
+
+ if (uncompr_tvb == NULL) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "[zlib compressed packet]");
+ offset += tvb_length_remaining(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, 0, 0, 0,
+ "(uncompression failed !)");
+ } else {
+
+ proto_item *ti2 = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, FALSE);
+ proto_tree *slsk_compr_packet_tree = proto_item_add_subtree(ti2, ett_slsk_compr_packet);
+
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "( compressed packet length: %d)", comprlen);
+ uncomprlen = tvb_length_remaining(uncompr_tvb, 0);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "(uncompressed packet length: %d)", uncomprlen);
+
+ /* Dissects the uncompressed tvbuffer */
+ uncompr_tvb_offset = 0;
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "i*")) {
+ i=0; j = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Number of directories: %d", tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ while (i<j){
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "si*")) {
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Directory #%d String Length: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Directory #%d Name: %s", i+1, tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ i2=0;
+ j2 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Directory #%d Number of files: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ while (i2<j2){
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "bsiisi*")) {
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_byte, uncompr_tvb, 0, 0, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Code: %d", i+1, i2+1, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 1;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d String Length: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Filename: %s", i+1, i2+1, tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Size1: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Size2: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d String Length: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d ext: %s", i+1, i2+1, tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ i3=0;
+ j3 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Number of attributes: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ while (i3<j3){
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "ii*")) {
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Attr #%d type: %s (Code: %d)", i+1, i2+1, i3+1, val_to_str(tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset), slsk_attr_type, "Unknown"), tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Attr #%d value: %d", i+1, i2+1, i3+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ i3++;
+ }
+ }
+ }
+ i2++;
+ }
+ }
+ i++;
+ }
+ }
+ }
+ }else {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "[zlib compressed packet]");
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "( compressed packet length: %d)", comprlen);
+ offset += tvb_length_remaining(tvb, offset);
+ }
+ }
+ break;
+
+ case 7:
+ if (check_slsk_format(tvb, offset, "isi")) {
+ /* Server-to-Client */
+ message_type = "Get User Status Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_status_code, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Status: %s (Code: %d)", val_to_str(tvb_get_letohl(tvb, offset), slsk_status_codes, "Unknown"), tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server */
+ message_type = "Get User Status";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 9:
+ if (check_slsk_format(tvb, offset, "i*")) {
+ /* Client-to-Client */
+ message_type = "File Search Result";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+
+ /* [zlib compressed] */
+ comprlen = tvb_length_remaining(tvb, offset);
+
+ if (slsk_decompress == TRUE){
+
+ tvbuff_t *uncompr_tvb = tvb_uncompress(tvb, offset, comprlen);
+
+ if (uncompr_tvb == NULL) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "[zlib compressed packet]");
+ offset += tvb_length_remaining(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, 0, 0, 0,
+ "(uncompression failed !)");
+ } else {
+
+ proto_item *ti2 = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, FALSE);
+ proto_tree *slsk_compr_packet_tree = proto_item_add_subtree(ti2, ett_slsk_compr_packet);
+
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "( compressed packet length: %d)", comprlen);
+ uncomprlen = tvb_length_remaining(uncompr_tvb, 0);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "(uncompressed packet length: %d)", uncomprlen);
+
+ /* Dissects the uncompressed tvbuffer */
+ uncompr_tvb_offset = 0;
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "sii*")) {
+ proto_tree_add_uint(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Username: %s", tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint(slsk_compr_packet_tree, hf_slsk_token, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ i=0; j = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Number of files: %d", tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ while (i<j){
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "bsiisi*")) {
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_byte, uncompr_tvb, 0, 0, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d Code: %d", i+1, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 1;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d String Length: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d Filename: %s", i+1, tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d Size1: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d Size2: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d String Length: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d ext: %s", i+1, tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ i2=0;
+ j2 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d Number of attributes: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ while (i2<j2){
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "ii*")) {
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d Attr #%d type: %s (Code: %d)", i+1, i2+1, val_to_str(tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset), slsk_attr_type, "Unknown"), tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "File #%d Attr #%d value: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ }
+ i2++;
+ }
+ }
+ i++;
+ }
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_byte, uncompr_tvb, 0, 0, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset),
+ "Free upload slots: %s (Byte: %d)", val_to_str(tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset), slsk_yes_no, "Unknown"), tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 1;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Upload speed: %d", tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "In Queue: %d", tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ }
+ }
+ }else {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "[zlib compressed packet]");
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "( compressed packet length: %d)", comprlen);
+ offset += tvb_length_remaining(tvb, offset);
+ }
+ }
+ break;
+
+ case 13:
+ if (check_slsk_format(tvb, offset, "isss")) {
+ /* Server-to-Client */
+ message_type = "Say ChatRoom";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "iss")) {
+ /* Client-to-Server */
+ message_type = "Say ChatRoom";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 14:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server */
+ message_type = "Join/Add Room";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "isi*")) {
+ /* Server-to-Client */
+ message_type = "Join Room User List";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "s*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "User #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ i++;
+ }
+ if (check_slsk_format(tvb, offset, "i*")) {
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "i*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_status_code, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Status of User #%d: %s (Code: %d)", i+1, val_to_str(tvb_get_letohl(tvb, offset), slsk_status_codes, "Unknown"), tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ if (check_slsk_format(tvb, offset, "i*")) {
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "iiiii*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Average Speed of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Downloadnum of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Something of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Files of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Folders of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ if (check_slsk_format(tvb, offset, "i*")) {
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Slotsfull Records: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "i*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Slots full of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ }
+ break;
+
+ case 15:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server & Server-to-Client */
+ message_type = "Leave Room";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Client */
+ message_type = "User Info Request";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ break;
+
+ case 16:
+ if (check_slsk_format(tvb, offset, "issiiiiiii")) {
+ /* Server-to-Client */
+ message_type = "User Joined Room";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_total_uploads, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_average_speed, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_download_number, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_files, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_directories, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_slotsfull, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "isbiib") || check_slsk_format(tvb, offset, "isbsiib")) {
+ /* Client-to-Client */
+ message_type = "User Info Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_user_description, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_picture_exists, tvb, offset, 1, tvb_get_guint8(tvb, offset),
+ "Picture exists: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
+ offset += 1;
+ if ( tvb_get_guint8(tvb, offset -1 ) == 1 ) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Picture Size: %d", tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_picture, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ proto_tree_add_uint(slsk_tree, hf_slsk_total_uploads, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_queued_uploads, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_slots_available, tvb, offset, 1, tvb_get_guint8(tvb, offset),
+ "Upload Slots available: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
+ offset += 1;
+ }
+ break;
+
+ case 17:
+ if (check_slsk_format(tvb, offset, "iss")) {
+ /* Server-to-Client */
+ message_type = "User Left Room";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 18:
+ if (check_slsk_format(tvb, offset, "iiss")) {
+ /* Client-to-Server */
+ message_type = "Connect To Peer";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_string_format(slsk_tree, hf_slsk_connection_type, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)),
+ "Connection Type: %s (Char: %s)", connection_type(tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset))), tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "issiii")) {
+ /* Server-to-Client */
+ message_type = "Connect To Peer";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_string_format(slsk_tree, hf_slsk_connection_type, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)),
+ "Connection Type: %s (Char: %s)", connection_type(tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset))), tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_ipv4(slsk_tree, hf_slsk_ip, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_port, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 22:
+ if (check_slsk_format(tvb, offset, "iss")) {
+ /* Client-to-Server */
+ message_type = "Message User Send";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "iiiss")) {
+ /* Server-to-Client */
+ message_type = "Message User Receive";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_chat_message_id, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_timestamp, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 23:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Client-to-Server */
+ message_type = "Message User Receive Ack";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_chat_message_id, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 26:
+ if (check_slsk_format(tvb, offset, "iis")) {
+ /* Client-to-Server */
+ message_type = "File Search";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_search_text, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 28:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Client-to-Server */
+ message_type = "Set Status";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_status_code, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Status: %s (Code: %d)", val_to_str(tvb_get_letohl(tvb, offset), slsk_status_codes, "Unknown"), tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 32:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Server */
+ message_type = "Ping";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ break;
+
+ case 34:
+ if (check_slsk_format(tvb, offset, "isi")) {
+ /* Client-to-Server */
+ message_type = "Update Upload Speed";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_average_speed, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 35:
+ if (check_slsk_format(tvb, offset, "iii")) {
+ /* Client-to-Server */
+ message_type = "Shared Files & Folders ";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_folder_count, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_file_count, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 36:
+ if (check_slsk_format(tvb, offset, "isiiiii")) {
+ /* Server-to-Client */
+ message_type = "Get User Stats Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_average_speed, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_download_number, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_files, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_directories, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Client */
+ /* Client-to-Server: send after login successfull */
+ message_type = "Get User Stats";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "iis")) {
+ /* Client-to-Client */
+ message_type = "Folder Contents Request";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_directory, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 37:
+ if (check_slsk_format(tvb, offset, "i*")) {
+ /* Client-to-Client */
+ message_type = "Folder Contents Response";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+
+ /* [zlib compressed] */
+ comprlen = tvb_length_remaining(tvb, offset);
+
+ if (slsk_decompress == TRUE){
+
+ tvbuff_t *uncompr_tvb = tvb_uncompress(tvb, offset, comprlen);
+
+ if (uncompr_tvb == NULL) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "[zlib compressed packet]");
+ offset += tvb_length_remaining(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, 0, 0, 0,
+ "(uncompression failed !)");
+ } else {
+
+ proto_item *ti2 = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, FALSE);
+ proto_tree *slsk_compr_packet_tree = proto_item_add_subtree(ti2, ett_slsk_compr_packet);
+
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "( compressed packet length: %d)", comprlen);
+ uncomprlen = tvb_length_remaining(uncompr_tvb, 0);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "(uncompressed packet length: %d)", uncomprlen);
+
+ /* Dissects the uncompressed tvbuffer */
+ uncompr_tvb_offset = 0;
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "isi*")) {
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Token: %d", tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Directory Name: %s", tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+
+ i=0; j = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Number of directories: %d", tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ while (i<j){
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "si*")) {
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Directory #%d Name: %s", i+1, tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ i2 = 0;
+ j2 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Directory #%d Number of files: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ while (i2<j2){
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "bsiisi*")) {
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_byte, uncompr_tvb, 0, 0, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Code: %d", i+1, i2+1, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 1;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d String Length: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Filename: %s", i+1, i2+1, tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Size1: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Size2: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d String Length: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d ext: %s", i+1, i2+1, tvb_get_string(uncompr_tvb, uncompr_tvb_offset+4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset)));
+ uncompr_tvb_offset += 4+tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ i3 = 0;
+ j3 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Number of attributes: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ while (i3<j3){
+ if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "ii*")) {
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Attr #%d type: %s (Code: %d)", i+1, i2+1, i3+1, val_to_str(tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset), slsk_attr_type, "Unknown"), tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, 0, 0, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
+ "Dir #%d File #%d Attr #%d value: %d", i+1, i2+1, i3+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
+ uncompr_tvb_offset += 4;
+ }
+ i3++;
+ }
+ }
+ i2++;
+ }
+ }
+ i++;
+ }
+ }
+ }
+ }else {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "[zlib compressed packet]");
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
+ "( compressed packet length: %d)", comprlen);
+ offset += tvb_length_remaining(tvb, offset);
+ }
+ }
+ break;
+
+ case 40:
+ if (check_slsk_format(tvb, offset, "isi")) {
+ /* Server-to-Client */
+ message_type = "Queued Downloads";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_slotsfull, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "iiis") || check_slsk_format(tvb, offset, "iiisii")) {
+ /* Client-to-Client */
+ message_type = "Transfer Request";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ i = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_transfer_direction, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Transfer Direction: %s (Code: %d)", val_to_str(tvb_get_letohl(tvb, offset), slsk_transfer_direction, "Unknown"), tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ if (i == 1){
+ proto_tree_add_uint(slsk_tree, hf_slsk_size, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ }
+
+ break;
+
+ case 41:
+ if (check_slsk_format(tvb, offset, "iibs") || check_slsk_format(tvb, offset, "iibii") || check_slsk_format(tvb, offset, "iib")) {
+ /* Client-to-Client */
+ message_type = "Transfer Response";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ i = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_allowed, tvb, offset, 1, tvb_get_guint8(tvb, offset),
+ "Download allowed: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
+ offset += 1;
+ if ( i == 1 ) {
+ if ( tvb_length_remaining(tvb, offset) == 8 ) {
+ proto_tree_add_uint(slsk_tree, hf_slsk_size, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ } else {
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_string, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ }
+ break;
+
+ case 42:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Client */
+ message_type = "Placehold Upload";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 43:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Client */
+ message_type = "Queue Upload";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 44:
+ if (check_slsk_format(tvb, offset, "isi")) {
+ /* Client-to-Client */
+ message_type = "Place In Queue";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_place_in_queue, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 46:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Client */
+ message_type = "Upload Failed";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 50:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server */
+ message_type = "Make Own Recommendation";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "isi")) {
+ /* Client-to-Server */
+ message_type = "Remove Own Recommendation";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_ranking, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "iss")) {
+ /* Client-to-Client */
+ message_type = "Queue Failed";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_string, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 51:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server: "Add Things I like" */
+ /* Client-to-Client: "Place In Queue Request" */
+ message_type = "Add Things I like / Place In Queue Request";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 52:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server */
+ message_type = "Remove Things I like";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 54:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Server */
+ message_type = "Get Recommendations";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "ii*")) {
+ /* Server-to-Client */
+ message_type = "Get Recommendations Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "si*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "Recommendation #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_ranking, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Ranking #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ break;
+
+ case 55:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Server */
+ message_type = "Type 55";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ break;
+
+ case 56:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Server */
+ message_type = "Get Global Rankings";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "ii*")) {
+ /* Server-to-Client */
+ message_type = "Get Global Rankings Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "si*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "Recommendation #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_ranking, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Ranking #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ break;
+
+ case 57:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server */
+ message_type = "Get User Recommendations";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "isi*")) {
+ /* Server-to-Client */
+ message_type = "Get User Recommendations Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "s*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "Recommendation #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ i++;
+ }
+ }
+ break;
+
+ case 58:
+ if (check_slsk_format(tvb, offset, "isi*")) {
+ /* Client-to-Server */
+ message_type = "Admin Command";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_string, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_number_of_users, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Strings: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "s*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "String #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ i++;
+ }
+ }
+ break;
+
+ case 60:
+ if (check_slsk_format(tvb, offset, "isii")) {
+ /* Client-to-Server & Server-to-Client */
+ message_type = "Place In Line Response";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_place_in_queue, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 62:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Server-to-Client */
+ message_type = "Room Added";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 63:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Server-to-Client */
+ message_type = "Room Removed";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 64:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Server */
+ message_type = "Room List Request";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "ii*")) {
+ /* Server-to-Client */
+ message_type = "Room List";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_number_of_rooms, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "s*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "Room #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ i++;
+ }
+ if (check_slsk_format(tvb, offset, "i*")) {
+ i=0;
+ proto_tree_add_uint(slsk_tree, hf_slsk_number_of_rooms, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "i*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Users in Room #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ }
+ break;
+
+ case 65:
+ if (check_slsk_format(tvb, offset, "isissiii")) {
+ /* Server-to-Client */
+ message_type = "Exact File Search";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_directory, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 16, 0,
+ "(+12 0 bytes)");
+ offset += 12;
+ }
+ else if (check_slsk_format(tvb, offset, "iissiiib")) {
+ /* Client-to-Server */
+ message_type = "Exact File Search";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_directory, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 13, 0,
+ "(+13 0 bytes)");
+ offset += 13;
+ }
+ break;
+
+ case 66:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Server-to-Client */
+ message_type = "Admin Message";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 67:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Server */
+ message_type = "Global User List Request";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "isi*")) { /* same as case 14 */
+ /* Server-to-Client */
+ message_type = "Global User List";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "s*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "User #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ i++;
+ }
+ if (check_slsk_format(tvb, offset, "i*")) {
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "i*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_status_code, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Status of User #%d: %s (Code: %d)", i+1, val_to_str(tvb_get_letohl(tvb, offset), slsk_status_codes, "Unknown"), tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ if (check_slsk_format(tvb, offset, "i*")) {
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "iiiii*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Average Speed of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Downloadnum of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Something of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Files of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Folders of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ if (check_slsk_format(tvb, offset, "i*")) {
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Slotsfull Records: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "i*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Slots full of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ }
+ break;
+
+ case 68:
+ if (check_slsk_format(tvb, offset, "isiiiis")) {
+ message_type = "Tunneled Message";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_code, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_ipv4(slsk_tree, hf_slsk_ip, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_port, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 69:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Server */
+ message_type = "Privileged User List Request";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "ii*")) {
+ /* Server-to-Client */
+ message_type = "Privileged User List";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_number_of_users, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Priviledged Users: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "s*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "User #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ i++;
+ }
+ }
+ break;
+
+ case 71:
+ if (check_slsk_format(tvb, offset, "ib")) {
+ /* Client-to-Server */
+ message_type = "Get Parent List";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_byte, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ offset += 1;
+ }
+ break;
+
+ case 73:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Client-to-Server */
+ message_type = "Type 73";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 83:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Server-to-Client */
+ message_type = "Parent Min Speed";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_parent_min_speed, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 84:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Server-to-Client */
+ message_type = "Parent Speed Connection Ratio";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_parent_speed_connection_ratio, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 86:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Server-to-Client */
+ message_type = "Parent Inactivity Before Disconnect";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_seconds_parent_inactivity_before_disconnect, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 87:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Server-to-Client */
+ message_type = "Server Inactivity Before Disconnect";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_seconds_server_inactivity_before_disconnect, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 88:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Server-to-Client */
+ message_type = "Nodes In Cache Before Disconnect";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_nodes_in_cache_before_disconnect, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 90:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Server-to-Client */
+ message_type = "Seconds Before Ping Children";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_seconds_before_ping_children, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 91:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Server-to-Client */
+ message_type = "Add To Privileged";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 92:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Server */
+ message_type = "Check Privileges";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "ii")) {
+ /* Server-to-Client */
+ message_type = "Check Privileges Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_number_of_days, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 93:
+ if (check_slsk_format(tvb, offset, "ibisis")) {
+ /* Server-to-Client */
+ message_type = "Embedded Message";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ if ( tvb_get_guint8(tvb, offset) == 3 ){
+ /* Client-to-Client */
+ message_type = "Distributed Search";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
+ "Embedded Message Type: %s (Byte: %d)", message_type, 3);
+ offset += 1;
+ proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_search_text, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ }
+ break;
+
+ case 100:
+ if (check_slsk_format(tvb, offset, "ib")) {
+ /* Client-to-Server */
+ message_type = "Become Parent";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_byte, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ offset += 1;
+ }
+ break;
+
+ case 102:
+ if (check_slsk_format(tvb, offset, "ii*")) {
+ /* Server-to-Client */
+ message_type = "Random Parent Addresses";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_number_of_users, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Parent Addresses: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "sii*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "User #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_ipv4(slsk_tree, hf_slsk_ip, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_port, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Port Number #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ break;
+
+ case 103:
+ if (check_slsk_format(tvb, offset, "iis")) {
+ /* Server-to-Client */
+ message_type = "Send Wishlist Entry";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_search_text, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ break;
+
+ case 104:
+ if (check_slsk_format(tvb, offset, "ii")) {
+ /* Server-to-Client */
+ message_type = "Type 104";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ case 110:
+ if (check_slsk_format(tvb, offset, "i")) {
+ /* Client-to-Server */
+ message_type = "Get Similar Users";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ else if (check_slsk_format(tvb, offset, "ii*")) {
+ /* Server-to-Client */
+ message_type = "Get Similar Users Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_number_of_users, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Users: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "si*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "User #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Same Recommendations #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ break;
+
+ case 111:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server */
+ message_type = "Get Recommendations for Item";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "isi*")) {
+ /* Server-to-Client */
+ message_type = "Get Recommendations for Item Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "si*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "Recommendation #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_ranking, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Ranking #%d: %d", i+1, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ i++;
+ }
+ }
+ break;
+
+ case 112:
+ if (check_slsk_format(tvb, offset, "is")) {
+ /* Client-to-Server */
+ message_type = "Get Similar Users for Item";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "isi*")) {
+ /* Server-to-Client */
+ message_type = "Get Similar Users for Item Reply";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ i=0; j = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ while (i<j){
+ if (check_slsk_format(tvb, offset, "s*")) {
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
+ "String #%d Length: %d", i+1, tvb_get_letohl(tvb, offset));
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_letohl(tvb, offset),
+ "Username #%d: %s", i+1, tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ i++;
+ }
+ }
+ break;
+
+ case 1001:
+ if (check_slsk_format(tvb, offset, "iis")) {
+ /* Client-to-Server */
+ message_type = "Can't Connect To Peer";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ else if (check_slsk_format(tvb, offset, "ii")) {
+ /* Server-to-Client */
+ message_type = "Can't Connect To Peer";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ break;
+
+ default:
+ if (check_slsk_format(tvb, offset, "bisis")) {
+ if ( tvb_get_guint8(tvb, offset) == 3 ){
+ /* Client-to-Client */
+ message_type = "Distributed Search";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
+ "Message Type: %s (Byte: %d)", message_type, 3);
+ offset += 1;
+ proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_search_text, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ }
+ }
+ else if (check_slsk_format(tvb, offset, "bssi")) {
+ if ( tvb_get_guint8(tvb, offset) == 1 ){
+ /* Client-to-Client */
+ message_type = "Peer Init";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
+ "Message Type: %s (Byte: %d)", message_type, 1);
+ offset += 1;
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ proto_tree_add_string_format(slsk_tree, hf_slsk_connection_type, tvb, offset+4, tvb_get_letohl(tvb, offset), tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)),
+ "Connection Type: %s (Char: %s)", connection_type(tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset))), tvb_get_string(tvb, offset+4, tvb_get_letohl(tvb, offset)));
+ offset += 4+tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ }
+ else if (check_slsk_format(tvb, offset, "bi")) {
+ if ( tvb_get_guint8(tvb, offset) == 0 ){
+ /* Client-to-Client */
+ message_type = "Pierce Fw";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
+ "Message Type: %s (Byte: %d)", message_type, 0);
+ offset += 1;
+ proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+ offset += 4;
+ }
+ }
+ else {
+ message_type = "Unknown";
+ proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
+ "Message Type: %s (Code: %02d)", message_type, msg_code);
+ offset += 4;
+ }
+ break;
+
+ }
+
+ }
+
+
+}
+
+
+static void dissect_slsk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, slsk_desegment, 4, get_slsk_pdu_len, dissect_slsk_pdu);
+
+}
+
+
+/* Register the protocol with Ethereal */
+
+void
+proto_register_slsk(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_slsk_integer,
+ { "Integer", "slsk.integer",
+ FT_UINT32, BASE_DEC, NULL, 0, "Integer", HFILL } },
+ { &hf_slsk_string,
+ { "String", "slsk.string",
+ FT_STRING, BASE_NONE, NULL, 0, "String", HFILL } },
+ { &hf_slsk_byte,
+ { "Byte", "slsk.byte",
+ FT_UINT8, BASE_DEC, NULL, 0, "Byte", HFILL } },
+ { &hf_slsk_message_length,
+ { "Message Length", "slsk.message.length",
+ FT_UINT32, BASE_DEC, NULL, 0, "Message Length", HFILL } },
+ { &hf_slsk_message_code,
+ { "Message Code", "slsk.message.code",
+ FT_UINT32, BASE_DEC, NULL, 0, "Message Code", HFILL } },
+ { &hf_slsk_client_ip,
+ { "Client IP", "slsk.server.ip",
+ FT_IPv4, BASE_DEC, NULL, 0, "Client IP Address", HFILL } },
+ { &hf_slsk_server_ip,
+ { "SoulSeek Server IP", "slsk.server.ip",
+ FT_UINT32, BASE_DEC, NULL, 0, "SoulSeek Server IP", HFILL } },
+ { &hf_slsk_string_length,
+ { "String Length", "slsk.string.length",
+ FT_UINT32, BASE_DEC, NULL, 0, "String Length", HFILL } },
+ { &hf_slsk_username,
+ { "Username", "slsk.username",
+ FT_STRING, BASE_NONE, NULL, 0, "Username", HFILL } },
+ { &hf_slsk_password,
+ { "Password", "slsk.password",
+ FT_STRING, BASE_NONE, NULL, 0, "Password", HFILL } },
+ { &hf_slsk_version,
+ { "Version", "slsk.version",
+ FT_UINT32, BASE_DEC, NULL, 0, "Version", HFILL } },
+ { &hf_slsk_login_successfull,
+ { "Login successfull", "slsk.login.successfull",
+ FT_UINT8, BASE_DEC, NULL, 0, "Login Successfull", HFILL } },
+ { &hf_slsk_login_message,
+ { "Login Message", "slsk.login.message",
+ FT_STRING, BASE_NONE, NULL, 0, "Login Message", HFILL } },
+ { &hf_slsk_port,
+ { "Port Number", "slsk.port.number",
+ FT_UINT32, BASE_DEC, NULL, 0, "Port Number", HFILL } },
+ { &hf_slsk_ip,
+ { "IP Address", "slsk.ip.address",
+ FT_IPv4, BASE_DEC, NULL, 0, "IP Address", HFILL } },
+ { &hf_slsk_user_exists,
+ { "user exists", "slsk.user.exists",
+ FT_UINT8, BASE_DEC, NULL, 0, "User exists", HFILL } },
+ { &hf_slsk_status_code,
+ { "Status Code", "slsk.status.code",
+ FT_UINT32, BASE_DEC, NULL, 0, "Status Code", HFILL } },
+ { &hf_slsk_room,
+ { "Room", "slsk.room",
+ FT_STRING, BASE_NONE, NULL, 0, "Room", HFILL } },
+ { &hf_slsk_chat_message,
+ { "Chat Message", "slsk.chat.message",
+ FT_STRING, BASE_NONE, NULL, 0, "Chat Message", HFILL } },
+ { &hf_slsk_users_in_room,
+ { "Users in Room", "slsk.room.users",
+ FT_UINT32, BASE_DEC, NULL, 0, "Number of Users in Room", HFILL } },
+ { &hf_slsk_token,
+ { "Token", "slsk.token",
+ FT_UINT32, BASE_DEC, NULL, 0, "Token", HFILL } },
+ { &hf_slsk_connection_type,
+ { "Connection Type", "slsk.connection.type",
+ FT_STRING, BASE_NONE, NULL, 0, "Connection Type", HFILL } },
+ { &hf_slsk_chat_message_id,
+ { "Chat Message ID", "slsk.chat.message.id",
+ FT_UINT32, BASE_DEC, NULL, 0, "Chat Message ID", HFILL } },
+ { &hf_slsk_timestamp,
+ { "Timestamp", "slsk.timestamp",
+ FT_UINT32, BASE_DEC, NULL, 0, "Timestamp", HFILL } },
+ { &hf_slsk_search_text,
+ { "Search Text", "slsk.search.text",
+ FT_STRING, BASE_NONE, NULL, 0, "Search Text", HFILL } },
+ { &hf_slsk_folder_count,
+ { "Folder Count", "slsk.folder.count",
+ FT_UINT32, BASE_DEC, NULL, 0, "Folder Count", HFILL } },
+ { &hf_slsk_file_count,
+ { "File Count", "slsk.file.count",
+ FT_UINT32, BASE_DEC, NULL, 0, "File Count", HFILL } },
+ { &hf_slsk_average_speed,
+ { "Average Speed", "slsk.average.speed",
+ FT_UINT32, BASE_DEC, NULL, 0, "Average Speed", HFILL } },
+ { &hf_slsk_download_number,
+ { "Download Number", "slsk.download.number",
+ FT_UINT32, BASE_DEC, NULL, 0, "Download Number", HFILL } },
+ { &hf_slsk_files,
+ { "Files", "slsk.files",
+ FT_UINT32, BASE_DEC, NULL, 0, "Files", HFILL } },
+ { &hf_slsk_directories,
+ { "Directories", "slsk.directories",
+ FT_UINT32, BASE_DEC, NULL, 0, "Directories", HFILL } },
+ { &hf_slsk_slotsfull,
+ { "Slots full", "slsk.slots.full",
+ FT_UINT32, BASE_DEC, NULL, 0, "Upload Slots Full", HFILL } },
+ { &hf_slsk_place_in_queue,
+ { "Place in Queue", "slsk.queue.place",
+ FT_UINT32, BASE_DEC, NULL, 0, "Place in Queue", HFILL } },
+ { &hf_slsk_number_of_rooms,
+ { "Number of Rooms", "slsk.room.count",
+ FT_UINT32, BASE_DEC, NULL, 0, "Number of Rooms", HFILL } },
+ { &hf_slsk_filename,
+ { "Filename", "slsk.filename",
+ FT_STRING, BASE_NONE, NULL, 0, "Filename", HFILL } },
+ { &hf_slsk_directory,
+ { "Directory", "slsk.directory",
+ FT_STRING, BASE_NONE, NULL, 0, "Directory", HFILL } },
+ { &hf_slsk_size,
+ { "Size", "slsk.size",
+ FT_UINT32, BASE_DEC, NULL, 0, "File Size", HFILL } },
+ { &hf_slsk_checksum,
+ { "Checksum", "slsk.checksum",
+ FT_UINT32, BASE_DEC, NULL, 0, "Checksum", HFILL } },
+ { &hf_slsk_code,
+ { "Code", "slsk.code",
+ FT_UINT32, BASE_DEC, NULL, 0, "Code", HFILL } },
+ { &hf_slsk_number_of_users,
+ { "Number of Users", "slsk.user.count",
+ FT_UINT32, BASE_DEC, NULL, 0, "Number of Users", HFILL } },
+ { &hf_slsk_number_of_days,
+ { "Number of Days", "slsk.day.count",
+ FT_UINT32, BASE_DEC, NULL, 0, "Number of Days", HFILL } },
+ { &hf_slsk_transfer_direction,
+ { "Transfer Direction", "slsk.transfer.direction",
+ FT_UINT32, BASE_DEC, NULL, 0, "Transfer Direction", HFILL } },
+ { &hf_slsk_user_description,
+ { "User Description", "slsk.user.description",
+ FT_STRING, BASE_NONE, NULL, 0, "User Description", HFILL } },
+ { &hf_slsk_picture_exists,
+ { "Picture exists", "slsk.user.picture.exists",
+ FT_UINT8, BASE_DEC, NULL, 0, "User has a picture", HFILL } },
+ { &hf_slsk_picture,
+ { "Picture", "slsk.user.picture",
+ FT_STRING, BASE_NONE, NULL, 0, "User Picture", HFILL } },
+ { &hf_slsk_user_uploads,
+ { "User uploads", "slsk.uploads.user",
+ FT_UINT32, BASE_DEC, NULL, 0, "User uploads", HFILL } },
+ { &hf_slsk_total_uploads,
+ { "Total uploads allowed", "slsk.uploads.total",
+ FT_UINT32, BASE_DEC, NULL, 0, "Total uploads allowed", HFILL } },
+ { &hf_slsk_queued_uploads,
+ { "Queued uploads", "slsk.uploads.queued",
+ FT_UINT32, BASE_DEC, NULL, 0, "Queued uploads", HFILL } },
+ { &hf_slsk_slots_available,
+ { "Upload Slots available", "slsk.uploads.available",
+ FT_UINT8, BASE_DEC, NULL, 0, "Upload Slots available", HFILL } },
+ { &hf_slsk_allowed,
+ { "Download allowed", "slsk.user.allowed",
+ FT_UINT8, BASE_DEC, NULL, 0, "allowed", HFILL } },
+ { &hf_slsk_compr_packet,
+ { "[zlib compressed packet]", "slsk.compr.packet",
+ FT_NONE, BASE_NONE, NULL, 0, "zlib compressed packet", HFILL } },
+ { &hf_slsk_parent_min_speed,
+ { "Parent Min Speed", "slsk.parent.min.speed",
+ FT_UINT32, BASE_DEC, NULL, 0, "Parent Min Speed", HFILL } },
+ { &hf_slsk_parent_speed_connection_ratio,
+ { "Parent Speed Connection Ratio", "slsk.parent.speed.connection.ratio",
+ FT_UINT32, BASE_DEC, NULL, 0, "Parent Speed Connection Ratio", HFILL } },
+ { &hf_slsk_seconds_parent_inactivity_before_disconnect,
+ { "Seconds Parent Inactivity Before Disconnect", "slsk.seconds.parent.inactivity.before.disconnect",
+ FT_UINT32, BASE_DEC, NULL, 0, "Seconds Parent Inactivity Before Disconnect", HFILL } },
+ { &hf_slsk_seconds_server_inactivity_before_disconnect,
+ { "Seconds Server Inactivity Before Disconnect", "slsk.seconds.server.inactivity.before.disconnect",
+ FT_UINT32, BASE_DEC, NULL, 0, "Seconds Server Inactivity Before Disconnect", HFILL } },
+ { &hf_slsk_nodes_in_cache_before_disconnect,
+ { "Nodes In Cache Before Disconnect", "slsk.nodes.in.cache.before.disconnect",
+ FT_UINT32, BASE_DEC, NULL, 0, "Nodes In Cache Before Disconnect", HFILL } },
+ { &hf_slsk_seconds_before_ping_children,
+ { "Seconds Before Ping Children", "slsk.seconds.before.ping.children",
+ FT_UINT32, BASE_DEC, NULL, 0, "Seconds Before Ping Children", HFILL } },
+ { &hf_slsk_recommendation,
+ { "Recommendation", "slsk.recommendation",
+ FT_STRING, BASE_NONE, NULL, 0, "Recommendation", HFILL } },
+ { &hf_slsk_ranking,
+ { "Ranking", "slsk.ranking",
+ FT_UINT32, BASE_DEC, NULL, 0, "Ranking", HFILL } },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_slsk,
+ &ett_slsk_compr_packet,
+ };
+ module_t *slsk_module;
+
+/* Registers the protocol name and description */
+ proto_slsk = proto_register_protocol("SoulSeek Protocol", "SoulSeek", "slsk");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_slsk, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ slsk_module = prefs_register_protocol(proto_slsk, NULL);
+
+/* Registers the options in the menu preferences */
+ prefs_register_bool_preference(slsk_module, "desegment",
+ "Desegment all SoulSeek messages spanning multiple TCP segments",
+ "Whether the SoulSeek dissector should desegment all messages spanning multiple TCP segments",
+ &slsk_desegment);
+#ifdef HAVE_LIBZ
+ prefs_register_bool_preference(slsk_module, "decompress",
+ "Decompress zlib compressed packets inside SoulSeek messages",
+ "Whether the SoulSeek dissector should decompress all zlib compressed packets inside messages",
+ &slsk_decompress);
+#endif
+
+}
+
+
+void
+proto_reg_handoff_slsk(void)
+{
+ dissector_handle_t slsk_handle;
+
+ slsk_handle = create_dissector_handle(dissect_slsk, proto_slsk);
+ dissector_add("tcp.port", TCP_PORT_SLSK_1, slsk_handle);
+ dissector_add("tcp.port", TCP_PORT_SLSK_2, slsk_handle);
+ dissector_add("tcp.port", TCP_PORT_SLSK_3, slsk_handle);
+}
+
diff --git a/epan/dissectors/packet-smb-browse.c b/epan/dissectors/packet-smb-browse.c
new file mode 100644
index 0000000000..103e7799aa
--- /dev/null
+++ b/epan/dissectors/packet-smb-browse.c
@@ -0,0 +1,1166 @@
+/* packet-smb-browse.c
+ * Routines for SMB Browser packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+#include <ctype.h>
+#include <epan/packet.h>
+#include "smb.h"
+
+#include "packet-smb-browse.h"
+#include "packet-dcerpc.h"
+
+static int proto_smb_browse = -1;
+static int hf_command = -1;
+static int hf_update_count = -1;
+static int hf_periodicity = -1;
+static int hf_server_name = -1;
+static int hf_mb_server_name = -1;
+static int hf_mb_reset_command = -1;
+static int hf_mb_reset_demote = -1;
+static int hf_mb_reset_flush = -1;
+static int hf_mb_reset_stop = -1;
+static int hf_os_major = -1;
+static int hf_os_minor = -1;
+static int hf_server_type = -1;
+static int hf_server_type_workstation = -1;
+static int hf_server_type_server = -1;
+static int hf_server_type_sql = -1;
+static int hf_server_type_domain = -1;
+static int hf_server_type_backup = -1;
+static int hf_server_type_time = -1;
+static int hf_server_type_apple = -1;
+static int hf_server_type_novell = -1;
+static int hf_server_type_member = -1;
+static int hf_server_type_print = -1;
+static int hf_server_type_dialin = -1;
+static int hf_server_type_xenix = -1;
+static int hf_server_type_ntw = -1;
+static int hf_server_type_wfw = -1;
+static int hf_server_type_nts = -1;
+static int hf_server_type_potentialb = -1;
+static int hf_server_type_backupb = -1;
+static int hf_server_type_masterb = -1;
+static int hf_server_type_domainmasterb = -1;
+static int hf_server_type_osf = -1;
+static int hf_server_type_vms = -1;
+static int hf_server_type_w95 = -1;
+static int hf_server_type_local = -1;
+static int hf_server_type_domainenum = -1;
+static int hf_election_version = -1;
+static int hf_proto_major = -1;
+static int hf_proto_minor = -1;
+static int hf_sig_const = -1;
+static int hf_server_comment = -1;
+static int hf_unused_flags = -1;
+static int hf_response_computer_name = -1;
+static int hf_election_criteria = -1;
+static int hf_election_desire = -1;
+static int hf_election_desire_flags_backup = -1;
+static int hf_election_desire_flags_standby = -1;
+static int hf_election_desire_flags_master = -1;
+static int hf_election_desire_flags_domain_master = -1;
+static int hf_election_desire_flags_wins = -1;
+static int hf_election_desire_flags_nt = -1;
+static int hf_election_revision = -1;
+static int hf_election_os = -1;
+static int hf_election_os_wfw = -1;
+static int hf_election_os_ntw = -1;
+static int hf_election_os_nts = -1;
+static int hf_server_uptime = -1;
+static int hf_backup_count = -1;
+static int hf_backup_token = -1;
+static int hf_backup_server = -1;
+static int hf_browser_to_promote = -1;
+
+static gint ett_browse = -1;
+static gint ett_browse_flags = -1;
+static gint ett_browse_election_criteria = -1;
+static gint ett_browse_election_os = -1;
+static gint ett_browse_election_desire = -1;
+static gint ett_browse_reset_cmd_flags = -1;
+
+#define SERVER_WORKSTATION 0
+#define SERVER_SERVER 1
+#define SERVER_SQL_SERVER 2
+#define SERVER_DOMAIN_CONTROLLER 3
+#define SERVER_BACKUP_CONTROLLER 4
+#define SERVER_TIME_SOURCE 5
+#define SERVER_APPLE_SERVER 6
+#define SERVER_NOVELL_SERVER 7
+#define SERVER_DOMAIN_MEMBER_SERVER 8
+#define SERVER_PRINT_QUEUE_SERVER 9
+#define SERVER_DIALIN_SERVER 10
+#define SERVER_XENIX_SERVER 11
+#define SERVER_NT_WORKSTATION 12
+#define SERVER_WINDOWS_FOR_WORKGROUPS 13
+#define SERVER_NT_SERVER 15
+#define SERVER_POTENTIAL_BROWSER 16
+#define SERVER_BACKUP_BROWSER 17
+#define SERVER_MASTER_BROWSER 18
+#define SERVER_DOMAIN_MASTER_BROWSER 19
+#define SERVER_OSF 20
+#define SERVER_VMS 21
+#define SERVER_WINDOWS_95 22
+#define SERVER_LOCAL_LIST_ONLY 30
+#define SERVER_DOMAIN_ENUM 31
+
+static const value_string server_types[] = {
+ {SERVER_WORKSTATION, "Workstation"},
+ {SERVER_SERVER, "Server"},
+ {SERVER_SQL_SERVER, "SQL Server"},
+ {SERVER_DOMAIN_CONTROLLER, "Domain Controller"},
+ {SERVER_BACKUP_CONTROLLER, "Backup Controller"},
+ {SERVER_TIME_SOURCE, "Time Source"},
+ {SERVER_APPLE_SERVER, "Apple Server"},
+ {SERVER_NOVELL_SERVER, "Novell Server"},
+ {SERVER_DOMAIN_MEMBER_SERVER, "Domain Member Server"},
+ {SERVER_PRINT_QUEUE_SERVER, "Print Queue Server"},
+ {SERVER_DIALIN_SERVER, "Dialin Server"},
+ {SERVER_XENIX_SERVER, "Xenix Server"},
+ {SERVER_NT_WORKSTATION, "NT Workstation"},
+ {SERVER_WINDOWS_FOR_WORKGROUPS, "Windows for Workgroups"},
+ {SERVER_NT_SERVER, "NT Server"},
+ {SERVER_POTENTIAL_BROWSER, "Potential Browser"},
+ {SERVER_BACKUP_BROWSER, "Backup Browser"},
+ {SERVER_MASTER_BROWSER, "Master Browser"},
+ {SERVER_DOMAIN_MASTER_BROWSER, "Domain Master Browser"},
+ {SERVER_OSF, "OSF"},
+ {SERVER_VMS, "VMS"},
+ {SERVER_WINDOWS_95, "Windows 95 or above"},
+ {SERVER_LOCAL_LIST_ONLY, "Local List Only"},
+ {SERVER_DOMAIN_ENUM, "Domain Enum"},
+ {0, NULL}
+};
+
+static const value_string resetbrowserstate_command_names[] = {
+ { 0x01, "Stop being a master browser and become a backup browser"},
+ { 0x02, "Discard browse lists, stop being a master browser, and try again"},
+ { 0x04, "Stop being a master browser for ever"},
+ { 0, NULL}
+};
+
+static true_false_string tfs_demote_to_backup = {
+ "Demote an LMB to a Backup Browser",
+ "Do not demote an LMB to a Backup Browser"
+};
+
+static true_false_string tfs_flush_browse_list = {
+ "Flush the Browse List",
+ "Do not Flush the Browse List"
+};
+
+static true_false_string tfs_stop_being_lmb = {
+ "Stop Being a Local Master Browser",
+ "Do not Stop Being a Local Master Browser"
+};
+
+static const true_false_string tfs_workstation = {
+ "This is a Workstation",
+ "This is NOT a Workstation"
+};
+static const true_false_string tfs_server = {
+ "This is a Server",
+ "This is NOT a Server"
+};
+static const true_false_string tfs_sql = {
+ "This is an SQL server",
+ "This is NOT an SQL server"
+};
+static const true_false_string tfs_domain = {
+ "This is a Domain Controller",
+ "This is NOT a Domain Controller"
+};
+static const true_false_string tfs_backup = {
+ "This is a Backup Controller",
+ "This is NOT a Backup Controller"
+};
+static const true_false_string tfs_time = {
+ "This is a Time Source",
+ "This is NOT a Time Source"
+};
+static const true_false_string tfs_apple = {
+ "This is an Apple host",
+ "This is NOT an Apple host"
+};
+static const true_false_string tfs_novell = {
+ "This is a Novell server",
+ "This is NOT a Novell server"
+};
+static const true_false_string tfs_member = {
+ "This is a Domain Member server",
+ "This is NOT a Domain Member server"
+};
+static const true_false_string tfs_print = {
+ "This is a Print Queue server",
+ "This is NOT a Print Queue server"
+};
+static const true_false_string tfs_dialin = {
+ "This is a Dialin server",
+ "This is NOT a Dialin server"
+};
+static const true_false_string tfs_xenix = {
+ "This is a Xenix server",
+ "This is NOT a Xenix server"
+};
+static const true_false_string tfs_ntw = {
+ "This is an NT Workstation",
+ "This is NOT an NT Workstation"
+};
+static const true_false_string tfs_wfw = {
+ "This is a WfW host",
+ "This is NOT a WfW host"
+};
+static const true_false_string tfs_nts = {
+ "This is an NT Server",
+ "This is NOT an NT Server"
+};
+static const true_false_string tfs_potentialb = {
+ "This is a Potential Browser",
+ "This is NOT a Potential Browser"
+};
+static const true_false_string tfs_backupb = {
+ "This is a Backup Browser",
+ "This is NOT a Backup Browser"
+};
+static const true_false_string tfs_masterb = {
+ "This is a Master Browser",
+ "This is NOT a Master Browser"
+};
+static const true_false_string tfs_domainmasterb = {
+ "This is a Domain Master Browser",
+ "This is NOT a Domain Master Browser"
+};
+static const true_false_string tfs_osf = {
+ "This is an OSF host",
+ "This is NOT an OSF host"
+};
+static const true_false_string tfs_vms = {
+ "This is a VMS host",
+ "This is NOT a VMS host"
+};
+static const true_false_string tfs_w95 = {
+ "This is a Windows 95 or above host",
+ "This is NOT a Windows 95 or above host"
+};
+static const true_false_string tfs_local = {
+ "This is a local list only request",
+ "This is NOT a local list only request"
+};
+static const true_false_string tfs_domainenum = {
+ "This is a Domain Enum request",
+ "This is NOT a Domain Enum request"
+};
+
+#define DESIRE_BACKUP 0
+#define DESIRE_STANDBY 1
+#define DESIRE_MASTER 2
+#define DESIRE_DOMAIN_MASTER 3
+#define DESIRE_WINS 5
+#define DESIRE_NT 7
+
+static const value_string desire_flags[] = {
+ {DESIRE_BACKUP, "Backup Browse Server"},
+ {DESIRE_STANDBY, "Standby Browse Server"},
+ {DESIRE_MASTER, "Master Browser"},
+ {DESIRE_DOMAIN_MASTER, "Domain Master Browse Server"},
+ {DESIRE_WINS, "WINS Client"},
+ {DESIRE_NT, "Windows NT Advanced Server"},
+ {0, NULL}
+};
+
+static const true_false_string tfs_desire_backup = {
+ "Backup Browse Server",
+ "NOT Backup Browse Server"
+ };
+static const true_false_string tfs_desire_standby = {
+ "Standby Browse Server",
+ "NOT Standby Browse Server"
+};
+static const true_false_string tfs_desire_master = {
+ "Master Browser",
+ "NOT Master Browser"
+};
+static const true_false_string tfs_desire_domain_master = {
+ "Domain Master Browse Server",
+ "NOT Domain Master Browse Server"
+};
+static const true_false_string tfs_desire_wins = {
+ "WINS Client",
+ "NOT WINS Client"
+};
+static const true_false_string tfs_desire_nt = {
+ "Windows NT Advanced Server",
+ "NOT Windows NT Advanced Server"
+};
+
+#define BROWSE_HOST_ANNOUNCE 1
+#define BROWSE_REQUEST_ANNOUNCE 2
+#define BROWSE_ELECTION_REQUEST 8
+#define BROWSE_BACKUP_LIST_REQUEST 9
+#define BROWSE_BACKUP_LIST_RESPONSE 10
+#define BROWSE_BECOME_BACKUP 11
+#define BROWSE_DOMAIN_ANNOUNCEMENT 12
+#define BROWSE_MASTER_ANNOUNCEMENT 13
+#define BROWSE_RESETBROWSERSTATE_ANNOUNCEMENT 14
+#define BROWSE_LOCAL_MASTER_ANNOUNCEMENT 15
+
+static const value_string commands[] = {
+ {BROWSE_HOST_ANNOUNCE, "Host Announcement"},
+ {BROWSE_REQUEST_ANNOUNCE, "Request Announcement"},
+ {BROWSE_ELECTION_REQUEST, "Browser Election Request"},
+ {BROWSE_BACKUP_LIST_REQUEST, "Get Backup List Request"},
+ {BROWSE_BACKUP_LIST_RESPONSE, "Get Backup List Response"},
+ {BROWSE_BECOME_BACKUP, "Become Backup Browser"},
+ {BROWSE_DOMAIN_ANNOUNCEMENT, "Domain/Workgroup Announcement"},
+ {BROWSE_MASTER_ANNOUNCEMENT, "Master Announcement"},
+ {BROWSE_RESETBROWSERSTATE_ANNOUNCEMENT, "Reset Browser State Announcement"},
+ {BROWSE_LOCAL_MASTER_ANNOUNCEMENT,"Local Master Announcement"},
+ {0, NULL}
+};
+
+#define OS_WFW 0
+#define OS_NTW 4
+#define OS_NTS 5
+
+static const value_string os_flags[] = {
+ {OS_WFW, "Windows for Workgroups"},
+ {OS_NTW, "Windows NT Workstation"},
+ {OS_NTS, "Windows NT Server"},
+ {0, NULL}
+};
+
+static const true_false_string tfs_os_wfw = {
+ "Windows for Workgroups",
+ "Not Windows for Workgroups"
+};
+static const true_false_string tfs_os_ntw = {
+ "Windows NT Workstation",
+ "Not Windows NT Workstation"
+};
+static const true_false_string tfs_os_nts = {
+ "Windows NT Server",
+ "Not Windows NT Server"
+};
+
+static void
+dissect_election_criterion_os(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ guint8 os;
+
+ os = tvb_get_guint8(tvb, offset);
+
+ if (parent_tree) {
+ item = proto_tree_add_uint(parent_tree, hf_election_os, tvb, offset, 1, os);
+ tree = proto_item_add_subtree(item, ett_browse_election_os);
+ }
+
+ proto_tree_add_boolean(tree, hf_election_os_wfw,
+ tvb, offset, 1, os);
+ proto_tree_add_boolean(tree, hf_election_os_ntw,
+ tvb, offset, 1, os);
+ proto_tree_add_boolean(tree, hf_election_os_nts,
+ tvb, offset, 1, os);
+
+}
+
+static void
+dissect_election_criterion_desire(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ guint8 desire;
+
+ desire = tvb_get_guint8(tvb, offset);
+
+ if (parent_tree) {
+ item = proto_tree_add_uint(parent_tree, hf_election_desire, tvb, offset, 1, desire);
+ tree = proto_item_add_subtree(item, ett_browse_election_desire);
+ }
+
+ proto_tree_add_boolean(tree, hf_election_desire_flags_backup,
+ tvb, offset, 1, desire);
+ proto_tree_add_boolean(tree, hf_election_desire_flags_standby,
+ tvb, offset, 1, desire);
+ proto_tree_add_boolean(tree, hf_election_desire_flags_master,
+ tvb, offset, 1, desire);
+ proto_tree_add_boolean(tree, hf_election_desire_flags_domain_master,
+ tvb, offset, 1, desire);
+ proto_tree_add_boolean(tree, hf_election_desire_flags_wins,
+ tvb, offset, 1, desire);
+ proto_tree_add_boolean(tree, hf_election_desire_flags_nt,
+ tvb, offset, 1, desire);
+
+}
+
+static void
+dissect_election_criterion(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ guint32 criterion;
+
+ criterion = tvb_get_letohl(tvb, offset);
+
+ if (parent_tree) {
+ item = proto_tree_add_uint(parent_tree, hf_election_criteria, tvb, offset, 4, criterion);
+ tree = proto_item_add_subtree(item, ett_browse_election_criteria);
+ }
+
+ /* election desire */
+ dissect_election_criterion_desire(tvb, tree, offset);
+ offset += 1;
+
+ /* browser protocol major version */
+ proto_tree_add_item(tree, hf_proto_major, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* browser protocol minor version */
+ proto_tree_add_item(tree, hf_proto_minor, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* election os */
+ dissect_election_criterion_os(tvb, tree, offset);
+ offset += 1;
+
+}
+
+/*
+ * XXX - this causes non-browser packets to have browser fields.
+ */
+int
+dissect_smb_server_type_flags(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep,
+ gboolean infoflag)
+{
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ guint32 flags;
+ int i;
+
+ if (drep != NULL) {
+ /*
+ * Called from a DCE RPC protocol dissector, for a
+ * protocol where a 32-bit NDR integer contains
+ * an server type mask; extract the server type mask
+ * with an NDR call.
+ */
+ offset = dissect_ndr_uint32(
+ tvb, offset, pinfo, tree, drep, hf_server_type, &flags);
+ } else {
+ /*
+ * Called from SMB browser or RAS, where the server type
+ * mask is just a 4-byte little-endian quantity with no
+ * special NDR alignment requirement; extract it with
+ * "tvb_get_letohl()".
+ */
+ flags = tvb_get_letohl(tvb, offset);
+ offset += 4;
+ }
+
+ if (parent_tree) {
+ item = proto_tree_add_uint(parent_tree, hf_server_type, tvb, offset, 4, flags);
+ tree = proto_item_add_subtree(item, ett_browse_flags);
+ }
+
+ if (infoflag) {
+ /* Append the type(s) of the system to the COL_INFO line ... */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ for (i = 0; i < 32; i++) {
+ if (flags & (1<<i)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(i, server_types,
+ "Unknown server type:%d"));
+ }
+ }
+ }
+ }
+
+ proto_tree_add_boolean(tree, hf_server_type_workstation,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_server,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_sql,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_domain,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_backup,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_time,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_apple,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_novell,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_member,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_print,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_dialin,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_xenix,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_ntw,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_wfw,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_nts,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_potentialb,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_backupb,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_masterb,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_domainmasterb,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_osf,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_vms,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_w95,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_local,
+ tvb, offset, 4, flags);
+ proto_tree_add_boolean(tree, hf_server_type_domainenum,
+ tvb, offset, 4, flags);
+
+ return offset;
+}
+
+
+static void
+dissect_mailslot_browse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ int offset = 0;
+ guint8 cmd;
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ guint32 periodicity;
+ guint8 host_name[17];
+ gint namelen;
+ guint8 server_count, reset_cmd;
+ int i;
+ guint32 uptime;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BROWSER");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ cmd = tvb_get_guint8(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /* Put in something, and replace it later */
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, commands, "Unknown command:0x%02x"));
+ }
+
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, proto_smb_browse, tvb, offset, -1, TRUE);
+
+ tree = proto_item_add_subtree(item, ett_browse);
+ }
+
+ /* command */
+ proto_tree_add_uint(tree, hf_command, tvb, offset, 1, cmd);
+ offset += 1;
+
+ switch (cmd) {
+ case BROWSE_DOMAIN_ANNOUNCEMENT:
+ case BROWSE_LOCAL_MASTER_ANNOUNCEMENT:
+ case BROWSE_HOST_ANNOUNCE: {
+ /* update count */
+ proto_tree_add_item(tree, hf_update_count, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* periodicity (in milliseconds) */
+ periodicity = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_periodicity, tvb, offset, 4,
+ periodicity,
+ "Update Periodicity: %s",
+ time_msecs_to_str(periodicity));
+ offset += 4;
+
+ /* server name */
+ tvb_get_nstringz0(tvb, offset, sizeof(host_name), host_name);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", host_name);
+ }
+ proto_tree_add_string_format(tree, hf_server_name,
+ tvb, offset, 16,
+ host_name,
+ (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)?
+ "Domain/Workgroup: %s":
+ "Host Name: %s",
+ host_name);
+ offset += 16;
+
+ /* OS major version */
+ proto_tree_add_item(tree, hf_os_major, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* OS minor version */
+ proto_tree_add_item(tree, hf_os_minor, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* server type flags */
+ offset = dissect_smb_server_type_flags(
+ tvb, offset, pinfo, tree, NULL, TRUE);
+
+ if (cmd == BROWSE_DOMAIN_ANNOUNCEMENT) {
+ /*
+ * Network Monitor claims this is a "Comment
+ * Pointer". I don't believe it.
+ *
+ * It's not a browser protocol major/minor
+ * version number, and signature constant,
+ * however.
+ */
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Mysterious Field: 0x%08x",
+ tvb_get_letohl(tvb, offset));
+ offset += 4;
+ } else {
+ /* browser protocol major version */
+ proto_tree_add_item(tree, hf_proto_major, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* browser protocol minor version */
+ proto_tree_add_item(tree, hf_proto_minor, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* signature constant */
+ proto_tree_add_item(tree, hf_sig_const, tvb, offset, 2, TRUE);
+ offset += 2;
+ }
+
+ /* master browser server name or server comment */
+ namelen = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree,
+ (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)?
+ hf_mb_server_name : hf_server_comment,
+ tvb, offset, namelen, TRUE);
+ offset += namelen;
+ break;
+ }
+ case BROWSE_REQUEST_ANNOUNCE: {
+ guint8 *computer_name;
+
+ /* unused/unknown flags */
+ proto_tree_add_item(tree, hf_unused_flags,
+ tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* name of computer to which to send reply */
+ computer_name = tvb_get_stringz(tvb, offset, &namelen);
+ proto_tree_add_string(tree, hf_response_computer_name,
+ tvb, offset, namelen, computer_name);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, " %s", computer_name);
+ g_free(computer_name);
+ offset += namelen;
+ break;
+ }
+
+ case BROWSE_ELECTION_REQUEST:
+ /* election version */
+ proto_tree_add_item(tree, hf_election_version, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* criterion */
+ dissect_election_criterion(tvb, tree, offset);
+ offset += 4;
+
+ /* server uptime */
+ uptime = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_server_uptime,
+ tvb, offset, 4, uptime,
+ "Uptime: %s",
+ time_msecs_to_str(uptime));
+ offset += 4;
+
+ /* next 4 bytes must be zero */
+ offset += 4;
+
+ /* server name */
+ namelen = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_server_name,
+ tvb, offset, namelen, TRUE);
+ offset += namelen;
+ break;
+
+ case BROWSE_BACKUP_LIST_REQUEST:
+ /* backup list requested count */
+ proto_tree_add_item(tree, hf_backup_count, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* backup requested token */
+ proto_tree_add_item(tree, hf_backup_token, tvb, offset, 4, TRUE);
+ offset += 4;
+ break;
+
+ case BROWSE_BACKUP_LIST_RESPONSE:
+ /* backup list requested count */
+ server_count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_backup_count, tvb, offset, 1,
+ server_count);
+ offset += 1;
+
+ /* backup requested token */
+ proto_tree_add_item(tree, hf_backup_token, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* backup server names */
+ for (i = 0; i < server_count; i++) {
+ namelen = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_backup_server,
+ tvb, offset, namelen, TRUE);
+ offset += namelen;
+ }
+ break;
+
+ case BROWSE_MASTER_ANNOUNCEMENT:
+ /* master browser server name */
+ namelen = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_mb_server_name,
+ tvb, offset, namelen, TRUE);
+ offset += namelen;
+ break;
+
+ case BROWSE_RESETBROWSERSTATE_ANNOUNCEMENT: {
+ proto_tree *sub_tree;
+ proto_item *reset_item;
+
+ /* the subcommand follows ... one of three values */
+
+ reset_cmd = tvb_get_guint8(tvb, offset);
+ reset_item = proto_tree_add_uint(tree, hf_mb_reset_command, tvb,
+ offset, 1, reset_cmd);
+ sub_tree = proto_item_add_subtree(item, ett_browse_reset_cmd_flags);
+ proto_tree_add_boolean(sub_tree, hf_mb_reset_demote, tvb,
+ offset, 1, reset_cmd);
+ proto_tree_add_boolean(sub_tree, hf_mb_reset_flush, tvb,
+ offset, 1, reset_cmd);
+ proto_tree_add_boolean(sub_tree, hf_mb_reset_stop, tvb,
+ offset, 1, reset_cmd);
+ offset += 1;
+ break;
+ }
+
+ case BROWSE_BECOME_BACKUP:
+ /* name of browser to promote */
+ namelen = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree, hf_browser_to_promote,
+ tvb, offset, namelen, TRUE);
+ offset += namelen;
+ break;
+ }
+}
+
+/*
+ * It appears that browser announcements sent to \MAILSLOT\LANMAN aren't
+ * the same as browser announcements sent to \MAILSLOT\BROWSE.
+ * Was that an older version of the protocol?
+ *
+ * The document at
+ *
+ * http://www.samba.org/samba/ftp/specs/brow_rev.txt
+ *
+ * gives both formats of host announcement packets, saying that
+ * "[The first] format seems wrong", that one being what appears to
+ * show up in \MAILSLOT\LANMAN packets, and that "[The second one]
+ * may be better", that one being what appears to show up in
+ * \MAILSLOT\BROWSE packets.
+ *
+ * XXX - what other browser packets go out to that mailslot?
+ */
+static void
+dissect_mailslot_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ int offset = 0;
+ guint8 cmd;
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ guint32 periodicity;
+ const guint8 *host_name;
+ guint namelen;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BROWSER");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ cmd = tvb_get_guint8(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ /* Put in something, and replace it later */
+ col_set_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, commands, "Unknown command:0x%02x"));
+ }
+
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, proto_smb_browse, tvb, offset, -1, TRUE);
+
+ tree = proto_item_add_subtree(item, ett_browse);
+ }
+
+ /* command */
+ proto_tree_add_uint(tree, hf_command, tvb, offset, 1, cmd);
+ offset += 1;
+
+ switch (cmd) {
+ case BROWSE_DOMAIN_ANNOUNCEMENT:
+ case BROWSE_LOCAL_MASTER_ANNOUNCEMENT:
+ case BROWSE_HOST_ANNOUNCE:
+
+ /* update count */
+ proto_tree_add_item(tree, hf_update_count, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* server type flags */
+ offset = dissect_smb_server_type_flags(
+ tvb, offset, pinfo, tree, NULL, TRUE);
+
+ /* OS major version */
+ proto_tree_add_item(tree, hf_os_major, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* OS minor version */
+ proto_tree_add_item(tree, hf_os_minor, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* periodicity (in seconds; convert to milliseconds) */
+ periodicity = tvb_get_letohs(tvb, offset)*1000;
+ proto_tree_add_uint_format(tree, hf_periodicity, tvb, offset, 2,
+ periodicity,
+ "Update Periodicity: %s",
+ time_msecs_to_str(periodicity));
+ offset += 2;
+
+ /* server name */
+ namelen = tvb_strsize(tvb, offset);
+ host_name = tvb_get_ptr(tvb, offset, namelen);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", host_name);
+ }
+ proto_tree_add_item(tree, hf_server_name,
+ tvb, offset, namelen, TRUE);
+ offset += namelen;
+
+ /* master browser server name or server comment */
+ namelen = tvb_strsize(tvb, offset);
+ proto_tree_add_item(tree,
+ (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)?
+ hf_mb_server_name : hf_server_comment,
+ tvb, offset, namelen, TRUE);
+ offset += namelen;
+ break;
+ }
+}
+
+void
+proto_register_smb_browse(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_command,
+ { "Command", "browser.command", FT_UINT8, BASE_HEX,
+ VALS(commands), 0, "Browse command opcode", HFILL }},
+
+ { &hf_update_count,
+ { "Update Count", "browser.update_count", FT_UINT8, BASE_DEC,
+ NULL, 0, "Browse Update Count", HFILL }},
+
+ { &hf_periodicity,
+ { "Update Periodicity", "browser.period", FT_UINT32, BASE_DEC,
+ NULL, 0, "Update Periodicity in ms", HFILL }},
+
+ { &hf_server_name,
+ { "Server Name", "browser.server", FT_STRING, BASE_NONE,
+ NULL, 0, "BROWSE Server Name", HFILL }},
+
+ { &hf_mb_server_name,
+ { "Master Browser Server Name", "browser.mb_server", FT_STRING, BASE_NONE,
+ NULL, 0, "BROWSE Master Browser Server Name", HFILL }},
+
+ { &hf_mb_reset_command,
+ { "ResetBrowserState Command", "browser.reset_cmd", FT_UINT8,
+ BASE_HEX, VALS(&resetbrowserstate_command_names), 0,
+ "ResetBrowserState Command", HFILL }},
+ { &hf_mb_reset_demote,
+ { "Demote LMB", "browser.reset_cmd.demote", FT_BOOLEAN,
+ 8, TFS(&tfs_demote_to_backup), 0x01, "Demote LMB", HFILL}},
+ { &hf_mb_reset_flush,
+ { "Flush Browse List", "browser.reset_cmd.flush", FT_BOOLEAN,
+ 8, TFS(&tfs_flush_browse_list), 0x02, "Flush Browse List", HFILL}},
+ { &hf_mb_reset_stop,
+ { "Stop Being LMB", "browser.reset_cmd.stop_lmb", FT_BOOLEAN,
+ 8, TFS(&tfs_stop_being_lmb), 0x04, "Stop Being LMB", HFILL}},
+ { &hf_os_major,
+ { "OS Major Version", "browser.os_major", FT_UINT8, BASE_DEC,
+ NULL, 0, "Operating System Major Version", HFILL }},
+
+ { &hf_os_minor,
+ { "OS Minor Version", "browser.os_minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "Operating System Minor Version", HFILL }},
+
+ { &hf_server_type,
+ { "Server Type", "browser.server_type", FT_UINT32, BASE_HEX,
+ NULL, 0, "Server Type Flags", HFILL }},
+
+ { &hf_server_type_workstation,
+ { "Workstation", "browser.server_type.workstation", FT_BOOLEAN, 32,
+ TFS(&tfs_workstation), 1<<SERVER_WORKSTATION, "Is This A Workstation?", HFILL }},
+
+ { &hf_server_type_server,
+ { "Server", "browser.server_type.server", FT_BOOLEAN, 32,
+ TFS(&tfs_server), 1<<SERVER_SERVER, "Is This A Server?", HFILL }},
+
+ { &hf_server_type_sql,
+ { "SQL", "browser.server_type.sql", FT_BOOLEAN, 32,
+ TFS(&tfs_sql), 1<<SERVER_SQL_SERVER, "Is This A SQL Server?", HFILL }},
+
+ { &hf_server_type_domain,
+ { "Domain Controller", "browser.server_type.domain_controller", FT_BOOLEAN, 32,
+ TFS(&tfs_domain), 1<<SERVER_DOMAIN_CONTROLLER, "Is This A Domain Controller?", HFILL }},
+
+ { &hf_server_type_backup,
+ { "Backup Controller", "browser.server_type.backup_controller", FT_BOOLEAN, 32,
+ TFS(&tfs_backup), 1<<SERVER_BACKUP_CONTROLLER, "Is This A Backup Domain Controller?", HFILL }},
+
+ { &hf_server_type_time,
+ { "Time Source", "browser.server_type.time", FT_BOOLEAN, 32,
+ TFS(&tfs_time), 1<<SERVER_TIME_SOURCE, "Is This A Time Source?", HFILL }},
+
+ { &hf_server_type_apple,
+ { "Apple", "browser.server_type.apple", FT_BOOLEAN, 32,
+ TFS(&tfs_apple), 1<<SERVER_APPLE_SERVER, "Is This An Apple Server ?", HFILL }},
+
+ { &hf_server_type_novell,
+ { "Novell", "browser.server_type.novell", FT_BOOLEAN, 32,
+ TFS(&tfs_novell), 1<<SERVER_NOVELL_SERVER, "Is This A Novell Server?", HFILL }},
+
+ { &hf_server_type_member,
+ { "Member", "browser.server_type.member", FT_BOOLEAN, 32,
+ TFS(&tfs_member), 1<<SERVER_DOMAIN_MEMBER_SERVER, "Is This A Domain Member Server?", HFILL }},
+
+ { &hf_server_type_print,
+ { "Print", "browser.server_type.print", FT_BOOLEAN, 32,
+ TFS(&tfs_print), 1<<SERVER_PRINT_QUEUE_SERVER, "Is This A Print Server?", HFILL }},
+
+ { &hf_server_type_dialin,
+ { "Dialin", "browser.server_type.dialin", FT_BOOLEAN, 32,
+ TFS(&tfs_dialin), 1<<SERVER_DIALIN_SERVER, "Is This A Dialin Server?", HFILL }},
+
+ { &hf_server_type_xenix,
+ { "Xenix", "browser.server_type.xenix", FT_BOOLEAN, 32,
+ TFS(&tfs_xenix), 1<<SERVER_XENIX_SERVER, "Is This A Xenix Server?", HFILL }},
+
+ { &hf_server_type_ntw,
+ { "NT Workstation", "browser.server_type.ntw", FT_BOOLEAN, 32,
+ TFS(&tfs_ntw), 1<<SERVER_NT_WORKSTATION, "Is This A NT Workstation?", HFILL }},
+
+ { &hf_server_type_wfw,
+ { "WfW", "browser.server_type.wfw", FT_BOOLEAN, 32,
+ TFS(&tfs_wfw), 1<<SERVER_WINDOWS_FOR_WORKGROUPS, "Is This A Windows For Workgroups Server?", HFILL }},
+
+ { &hf_server_type_nts,
+ { "NT Server", "browser.server_type.nts", FT_BOOLEAN, 32,
+ TFS(&tfs_nts), 1<<SERVER_NT_SERVER, "Is This A NT Server?", HFILL }},
+
+ { &hf_server_type_potentialb,
+ { "Potential Browser", "browser.server_type.browser.potential", FT_BOOLEAN, 32,
+ TFS(&tfs_potentialb), 1<<SERVER_POTENTIAL_BROWSER, "Is This A Potential Browser?", HFILL }},
+
+ { &hf_server_type_backupb,
+ { "Backup Browser", "browser.server_type.browser.backup", FT_BOOLEAN, 32,
+ TFS(&tfs_backupb), 1<<SERVER_BACKUP_BROWSER, "Is This A Backup Browser?", HFILL }},
+
+ { &hf_server_type_masterb,
+ { "Master Browser", "browser.server_type.browser.master", FT_BOOLEAN, 32,
+ TFS(&tfs_masterb), 1<<SERVER_MASTER_BROWSER, "Is This A Master Browser?", HFILL }},
+
+ { &hf_server_type_domainmasterb,
+ { "Domain Master Browser", "browser.server_type.browser.domain_master", FT_BOOLEAN, 32,
+ TFS(&tfs_domainmasterb), 1<<SERVER_DOMAIN_MASTER_BROWSER, "Is This A Domain Master Browser?", HFILL }},
+
+ { &hf_server_type_osf,
+ { "OSF", "browser.server_type.osf", FT_BOOLEAN, 32,
+ TFS(&tfs_osf), 1<<SERVER_OSF, "Is This An OSF server ?", HFILL }},
+
+ { &hf_server_type_vms,
+ { "VMS", "browser.server_type.vms", FT_BOOLEAN, 32,
+ TFS(&tfs_vms), 1<<SERVER_VMS, "Is This A VMS Server?", HFILL }},
+
+ { &hf_server_type_w95,
+ { "Windows 95+", "browser.server_type.w95", FT_BOOLEAN, 32,
+ TFS(&tfs_w95), 1<<SERVER_WINDOWS_95, "Is This A Windows 95 or above server?", HFILL }},
+
+ { &hf_server_type_local,
+ { "Local", "browser.server_type.local", FT_BOOLEAN, 32,
+ TFS(&tfs_local), 1<<SERVER_LOCAL_LIST_ONLY, "Is This A Local List Only request?", HFILL }},
+
+ { &hf_server_type_domainenum,
+ { "Domain Enum", "browser.server_type.domainenum", FT_BOOLEAN, 32,
+ TFS(&tfs_domainenum), 1<<SERVER_DOMAIN_ENUM, "Is This A Domain Enum request?", HFILL }},
+
+ { &hf_election_version,
+ { "Election Version", "browser.election.version", FT_UINT8, BASE_DEC,
+ NULL, 0, "Election Version", HFILL }},
+
+ { &hf_proto_major,
+ { "Browser Protocol Major Version", "browser.proto_major", FT_UINT8, BASE_DEC,
+ NULL, 0, "Browser Protocol Major Version", HFILL }},
+
+ { &hf_proto_minor,
+ { "Browser Protocol Minor Version", "browser.proto_minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "Browser Protocol Minor Version", HFILL }},
+
+ { &hf_sig_const,
+ { "Signature", "browser.sig", FT_UINT16, BASE_HEX,
+ NULL, 0, "Signature Constant", HFILL }},
+
+ { &hf_server_comment,
+ { "Host Comment", "browser.comment", FT_STRINGZ, BASE_NONE,
+ NULL, 0, "Server Comment", HFILL }},
+
+ { &hf_unused_flags,
+ { "Unused flags", "browser.unused", FT_UINT8, BASE_HEX,
+ NULL, 0, "Unused/unknown flags", HFILL }},
+
+ { &hf_response_computer_name,
+ { "Response Computer Name", "browser.response_computer_name", FT_STRINGZ, BASE_NONE,
+ NULL, 0, "Response Computer Name", HFILL }},
+
+ { &hf_election_criteria,
+ { "Election Criteria", "browser.election.criteria", FT_UINT32, BASE_HEX,
+ NULL, 0, "Election Criteria", HFILL }},
+
+ { &hf_election_desire,
+ { "Election Desire", "browser.election.desire", FT_UINT8, BASE_HEX,
+ NULL, 0, "Election Desire", HFILL }},
+
+ { &hf_election_desire_flags_backup,
+ { "Backup", "browser.election.desire.backup", FT_BOOLEAN, 8,
+ TFS(&tfs_desire_backup), 1<<DESIRE_BACKUP, "Is this a backup server", HFILL }},
+
+ { &hf_election_desire_flags_standby,
+ { "Standby", "browser.election.desire.standby", FT_BOOLEAN, 8,
+ TFS(&tfs_desire_standby), 1<<DESIRE_STANDBY, "Is this a standby server?", HFILL }},
+
+ { &hf_election_desire_flags_master,
+ { "Master", "browser.election.desire.master", FT_BOOLEAN, 8,
+ TFS(&tfs_desire_master), 1<<DESIRE_MASTER, "Is this a master server", HFILL }},
+
+ { &hf_election_desire_flags_domain_master,
+ { "Domain Master", "browser.election.desire.domain_master", FT_BOOLEAN, 8,
+ TFS(&tfs_desire_domain_master), 1<<DESIRE_DOMAIN_MASTER, "Is this a domain master", HFILL }},
+
+ { &hf_election_desire_flags_wins,
+ { "WINS", "browser.election.desire.wins", FT_BOOLEAN, 8,
+ TFS(&tfs_desire_wins), 1<<DESIRE_WINS, "Is this a WINS server", HFILL }},
+
+ { &hf_election_desire_flags_nt,
+ { "NT", "browser.election.desire.nt", FT_BOOLEAN, 8,
+ TFS(&tfs_desire_nt), 1<<DESIRE_NT, "Is this a NT server", HFILL }},
+
+ { &hf_election_revision,
+ { "Election Revision", "browser.election.revision", FT_UINT16, BASE_DEC,
+ NULL, 0, "Election Revision", HFILL }},
+
+ { &hf_election_os,
+ { "Election OS", "browser.election.os", FT_UINT8, BASE_HEX,
+ NULL, 0, "Election OS", HFILL }},
+
+ { &hf_election_os_wfw,
+ { "WfW", "browser.election.os.wfw", FT_BOOLEAN, 8,
+ TFS(&tfs_os_wfw), 1<<OS_WFW, "Is this a WfW host?", HFILL }},
+
+ { &hf_election_os_ntw,
+ { "NT Workstation", "browser.election.os.ntw", FT_BOOLEAN, 8,
+ TFS(&tfs_os_ntw), 1<<OS_NTW, "Is this a NT Workstation?", HFILL }},
+
+ { &hf_election_os_nts,
+ { "NT Server", "browser.election.os.nts", FT_BOOLEAN, 8,
+ TFS(&tfs_os_nts), 1<<OS_NTS, "Is this a NT Server?", HFILL }},
+
+ { &hf_server_uptime,
+ { "Uptime", "browser.uptime", FT_UINT32, BASE_DEC,
+ NULL, 0, "Server uptime in ms", HFILL }},
+
+ { &hf_backup_count,
+ { "Backup List Requested Count", "browser.backup.count", FT_UINT8, BASE_DEC,
+ NULL, 0, "Backup list requested count", HFILL }},
+
+ { &hf_backup_token,
+ { "Backup Request Token", "browser.backup.token", FT_UINT32, BASE_DEC,
+ NULL, 0, "Backup requested/response token", HFILL }},
+
+ { &hf_backup_server,
+ { "Backup Server", "browser.backup.server", FT_STRING, BASE_NONE,
+ NULL, 0, "Backup Server Name", HFILL }},
+
+ { &hf_browser_to_promote,
+ { "Browser to Promote", "browser.browser_to_promote", FT_STRINGZ, BASE_NONE,
+ NULL, 0, "Browser to Promote", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_browse,
+ &ett_browse_flags,
+ &ett_browse_election_criteria,
+ &ett_browse_election_os,
+ &ett_browse_election_desire,
+ &ett_browse_reset_cmd_flags,
+ };
+
+ proto_smb_browse = proto_register_protocol("Microsoft Windows Browser Protocol",
+ "BROWSER", "browser");
+
+ proto_register_field_array(proto_smb_browse, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("mailslot_browse", dissect_mailslot_browse,
+ proto_smb_browse);
+ register_dissector("mailslot_lanman", dissect_mailslot_lanman,
+ proto_smb_browse);
+}
diff --git a/epan/dissectors/packet-smb-browse.h b/epan/dissectors/packet-smb-browse.h
new file mode 100644
index 0000000000..20385fe949
--- /dev/null
+++ b/epan/dissectors/packet-smb-browse.h
@@ -0,0 +1,34 @@
+/* packet-smb-browse.h
+ * Declaration of routines for SMB Browser packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_SMB_BROWSE_H_
+#define _PACKET_SMB_BROWSE_H_
+
+int
+dissect_smb_server_type_flags(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep,
+ gboolean infoflag);
+
+#endif
diff --git a/epan/dissectors/packet-smb-common.c b/epan/dissectors/packet-smb-common.c
new file mode 100644
index 0000000000..f5e4d09275
--- /dev/null
+++ b/epan/dissectors/packet-smb-common.c
@@ -0,0 +1,490 @@
+/* packet-smb-common.c
+ * Common routines for smb packet dissection
+ * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "packet-smb-common.h"
+
+/*
+ * Share type values - used in LANMAN and in SRVSVC.
+ *
+ * XXX - should we dissect share type values, at least in SRVSVC, as
+ * a subtree with bitfields, as the 0x80000000 bit appears to be a
+ * hidden bit, with some number of bits at the bottom being the share
+ * type?
+ *
+ * Does LANMAN use that bit?
+ */
+const value_string share_type_vals[] = {
+ {0, "Directory tree"},
+ {1, "Printer queue"},
+ {2, "Communications device"},
+ {3, "IPC"},
+ {0x80000000, "Hidden Directory tree"},
+ {0x80000001, "Hidden Printer queue"},
+ {0x80000002, "Hidden Communications device"},
+ {0x80000003, "Hidden IPC"},
+ {0, NULL}
+};
+
+int display_ms_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data)
+{
+ char *str;
+ gint len;
+
+ /* display a string from the tree and return the new offset */
+
+ str = tvb_get_stringz(tvb, offset, &len);
+ proto_tree_add_string(tree, hf_index, tvb, offset, len, str);
+
+ /* Return a copy of the string if requested */
+
+ if (data)
+ *data = str;
+ else
+ g_free(str);
+
+ return offset+len;
+}
+
+
+int display_unicode_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data)
+{
+ char *str, *p;
+ int len;
+ int charoffset;
+ guint16 character;
+
+ /* display a unicode string from the tree and return new offset */
+
+ /*
+ * Get the length of the string.
+ * XXX - is it a bug or a feature that this will throw an exception
+ * if we don't find the '\0'? I think it's a feature.
+ */
+ len = 0;
+ while ((character = tvb_get_letohs(tvb, offset + len)) != '\0')
+ len += 2;
+ len += 2; /* count the '\0' too */
+
+ /*
+ * Allocate a buffer for the string; "len" is the length in
+ * bytes, not the length in characters.
+ */
+ str = g_malloc(len/2);
+
+ /*
+ * XXX - this assumes the string is just ISO 8859-1; we need
+ * to better handle multiple character sets in Ethereal,
+ * including Unicode/ISO 10646, and multiple encodings of
+ * that character set (UCS-2, UTF-8, etc.).
+ */
+ charoffset = offset;
+ p = str;
+ while ((character = tvb_get_letohs(tvb, charoffset)) != '\0') {
+ *p++ = (char) character;
+ charoffset += 2;
+ }
+ *p = '\0';
+
+ proto_tree_add_string(tree, hf_index, tvb, offset, len, str);
+
+ if (data)
+ *data = str;
+ else
+ g_free(str);
+
+ return offset+len;
+}
+
+/* Max string length for displaying Unicode strings. */
+#define MAX_UNICODE_STR_LEN 256
+
+/* Turn a little-endian Unicode '\0'-terminated string into a string we
+ can display.
+ XXX - for now, we just handle the ISO 8859-1 characters.
+ If exactlen==TRUE then us_lenp contains the exact len of the string in
+ bytes. It might not be null terminated !
+ bc specifies the number of bytes in the byte parameters; Windows 2000,
+ at least, appears, in some cases, to put only 1 byte of 0 at the end
+ of a Unicode string if the byte count
+*/
+static gchar *
+unicode_to_str(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen,
+ guint16 bc)
+{
+ static gchar str[3][MAX_UNICODE_STR_LEN+3+1];
+ static gchar *cur;
+ gchar *p;
+ guint16 uchar;
+ int len;
+ int us_len;
+ gboolean overflow = FALSE;
+
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+ p = cur;
+ len = MAX_UNICODE_STR_LEN;
+ us_len = 0;
+ for (;;) {
+ if (bc == 0)
+ break;
+ if (bc == 1) {
+ /* XXX - explain this */
+ if (!exactlen)
+ us_len += 1; /* this is a one-byte null terminator */
+ break;
+ }
+ uchar = tvb_get_letohs(tvb, offset);
+ if (uchar == 0) {
+ us_len += 2; /* this is a two-byte null terminator */
+ break;
+ }
+ if (len > 0) {
+ if ((uchar & 0xFF00) == 0)
+ *p++ = (gchar) uchar; /* ISO 8859-1 */
+ else
+ *p++ = '?'; /* not 8859-1 */
+ len--;
+ } else
+ overflow = TRUE;
+ offset += 2;
+ bc -= 2;
+ us_len += 2;
+ if(exactlen){
+ if(us_len>= *us_lenp){
+ break;
+ }
+ }
+ }
+ if (overflow) {
+ /* Note that we're not showing the full string. */
+ *p++ = '.';
+ *p++ = '.';
+ *p++ = '.';
+ }
+ *p = '\0';
+ *us_lenp = us_len;
+ return cur;
+}
+
+/* nopad == TRUE : Do not add any padding before this string
+ * exactlen == TRUE : len contains the exact len of the string in bytes.
+ * bc: pointer to variable with amount of data left in the byte parameters
+ * region
+ */
+const gchar *
+get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp,
+ gboolean useunicode, int *len, gboolean nopad, gboolean exactlen,
+ guint16 *bcp)
+{
+ static gchar str[3][MAX_UNICODE_STR_LEN+3+1];
+ static gchar *cur;
+ const gchar *string;
+ int string_len;
+ int copylen;
+ gboolean overflow = FALSE;
+
+ if (*bcp == 0) {
+ /* Not enough data in buffer */
+ return NULL;
+ }
+ if (useunicode) {
+ if ((!nopad) && (*offsetp % 2)) {
+ /*
+ * XXX - this should be an offset relative to the beginning of the SMB,
+ * not an offset relative to the beginning of the frame; if the stuff
+ * before the SMB has an odd number of bytes, an offset relative to
+ * the beginning of the frame will give the wrong answer.
+ */
+ (*offsetp)++; /* Looks like a pad byte there sometimes */
+ (*bcp)--;
+ if (*bcp == 0) {
+ /* Not enough data in buffer */
+ return NULL;
+ }
+ }
+ if(exactlen){
+ string_len = *len;
+ if (string_len < 0) {
+ /* This probably means it's a very large unsigned number; just set
+ it to the largest signed number, so that we throw the appropriate
+ exception. */
+ string_len = INT_MAX;
+ }
+ }
+ string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp);
+ } else {
+ if(exactlen){
+ /*
+ * The string we return must be null-terminated.
+ */
+ if (cur == &str[0][0]) {
+ cur = &str[1][0];
+ } else if (cur == &str[1][0]) {
+ cur = &str[2][0];
+ } else {
+ cur = &str[0][0];
+ }
+ copylen = *len;
+ if (copylen < 0) {
+ /* This probably means it's a very large unsigned number; just set
+ it to the largest signed number, so that we throw the appropriate
+ exception. */
+ copylen = INT_MAX;
+ }
+ tvb_ensure_bytes_exist(tvb, *offsetp, copylen);
+ if (copylen > MAX_UNICODE_STR_LEN) {
+ copylen = MAX_UNICODE_STR_LEN;
+ overflow = TRUE;
+ }
+ tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen);
+ cur[copylen] = '\0';
+ if (overflow)
+ strcat(cur, "...");
+ string_len = *len;
+ string = cur;
+ } else {
+ string_len = tvb_strsize(tvb, *offsetp);
+ string = tvb_get_ptr(tvb, *offsetp, string_len);
+ }
+ }
+ *len = string_len;
+ return string;
+}
+
+int
+dissect_smb_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /* display data as unknown */
+
+ proto_tree_add_text(tree, tvb, offset, -1, "Data (%u bytes)",
+ tvb_reported_length_remaining(tvb, offset));
+
+ return offset+tvb_length_remaining(tvb, offset);
+}
+
+/* Dissect a NTLM response. This is documented at
+ http://ubiqx.org/cifs/SMB.html#8, para 2.8.5.3 */
+
+static int hf_ntlmv2_response = -1;
+static int hf_ntlmv2_response_hmac = -1;
+static int hf_ntlmv2_response_header = -1;
+static int hf_ntlmv2_response_reserved = -1;
+static int hf_ntlmv2_response_time = -1;
+static int hf_ntlmv2_response_chal = -1;
+static int hf_ntlmv2_response_unknown = -1;
+static int hf_ntlmv2_response_name = -1;
+static int hf_ntlmv2_response_name_type = -1;
+static int hf_ntlmv2_response_name_len = -1;
+
+static gint ett_ntlmv2_response = -1;
+static gint ett_ntlmv2_response_name = -1;
+
+/* Name types */
+
+const value_string ntlm_name_types[] = {
+ { NTLM_NAME_END, "End of list" },
+ { NTLM_NAME_NB_HOST, "NetBIOS host name" },
+ { NTLM_NAME_NB_DOMAIN, "NetBIOS domain name" },
+ { NTLM_NAME_DNS_HOST, "DNS host name" },
+ { NTLM_NAME_DNS_DOMAIN, "DNS domain name" },
+ { 0, NULL }
+};
+
+int
+dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
+{
+ proto_item *ntlmv2_item = NULL;
+ proto_tree *ntlmv2_tree = NULL;
+
+ /* Dissect NTLMv2 bits&pieces */
+
+ if (tree) {
+ ntlmv2_item = proto_tree_add_item(
+ tree, hf_ntlmv2_response, tvb,
+ offset, len, TRUE);
+ ntlmv2_tree = proto_item_add_subtree(
+ ntlmv2_item, ett_ntlmv2_response);
+ }
+
+ proto_tree_add_item(
+ ntlmv2_tree, hf_ntlmv2_response_hmac, tvb,
+ offset, 16, TRUE);
+
+ offset += 16;
+
+ proto_tree_add_item(
+ ntlmv2_tree, hf_ntlmv2_response_header, tvb,
+ offset, 4, TRUE);
+
+ offset += 4;
+
+ proto_tree_add_item(
+ ntlmv2_tree, hf_ntlmv2_response_reserved, tvb,
+ offset, 4, TRUE);
+
+ offset += 4;
+
+ offset = dissect_smb_64bit_time(
+ tvb, ntlmv2_tree, offset, hf_ntlmv2_response_time);
+
+ proto_tree_add_item(
+ ntlmv2_tree, hf_ntlmv2_response_chal, tvb,
+ offset, 8, TRUE);
+
+ offset += 8;
+
+ proto_tree_add_item(
+ ntlmv2_tree, hf_ntlmv2_response_unknown, tvb,
+ offset, 4, TRUE);
+
+ offset += 4;
+
+ /* Variable length list of names */
+
+ while(1) {
+ guint16 name_type = tvb_get_letohs(tvb, offset);
+ guint16 name_len = tvb_get_letohs(tvb, offset + 2);
+ proto_tree *name_tree = NULL;
+ proto_item *name_item = NULL;
+ char *name = NULL;
+
+ if (ntlmv2_tree) {
+ name_item = proto_tree_add_item(
+ ntlmv2_tree, hf_ntlmv2_response_name,
+ tvb, offset, 0, TRUE);
+ name_tree = proto_item_add_subtree(
+ name_item, ett_ntlmv2_response_name);
+ }
+
+ /* Dissect name header */
+
+ proto_tree_add_item(
+ name_tree, hf_ntlmv2_response_name_type, tvb,
+ offset, 2, TRUE);
+
+ offset += 2;
+
+ proto_tree_add_item(
+ name_tree, hf_ntlmv2_response_name_len, tvb,
+ offset, 2, TRUE);
+
+ offset += 2;
+
+ /* Dissect name */
+
+ if (name_len > 0) {
+ name = tvb_fake_unicode(
+ tvb, offset, name_len / 2, TRUE);
+
+ proto_tree_add_text(
+ name_tree, tvb, offset, name_len,
+ "Name: %s", name);
+ } else
+ name = g_strdup("NULL");
+
+ if (name_type == 0)
+ proto_item_append_text(
+ name_item, "%s",
+ val_to_str(name_type, ntlm_name_types,
+ "Unknown"));
+ else
+ proto_item_append_text(
+ name_item, "%s, %s",
+ val_to_str(name_type, ntlm_name_types,
+ "Unknown"), name);
+
+ g_free(name);
+
+ offset += name_len;
+
+ proto_item_set_len(name_item, name_len + 4);
+
+ if (name_type == 0) /* End of list */
+ break;
+ };
+
+ return offset;
+}
+
+void register_smb_common(int proto_smb)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_ntlmv2_response,
+ { "NTLMv2 Response", "smb.ntlmv2response", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ntlmv2_response_hmac,
+ { "HMAC", "smb.ntlmv2response.hmac", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_ntlmv2_response_header,
+ { "Header", "smb.ntlmv2response.header", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ntlmv2_response_reserved,
+ { "Reserved", "smb.ntlmv2response.reserved", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ntlmv2_response_time,
+ { "Time", "smb.ntlmv2response.time", FT_ABSOLUTE_TIME,
+ BASE_NONE, NULL, 0, "", HFILL }},
+
+ { &hf_ntlmv2_response_chal,
+ { "Client challenge", "smb.ntlmv2response.chal", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ntlmv2_response_unknown,
+ { "Unknown", "smb.ntlmv2response.unknown", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_ntlmv2_response_name,
+ { "Name", "smb.ntlmv2response.name", FT_STRING, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_ntlmv2_response_name_type,
+ { "Name type", "smb.ntlmv2response.name.type", FT_UINT32,
+ BASE_DEC, VALS(ntlm_name_types), 0x0, "", HFILL }},
+
+ { &hf_ntlmv2_response_name_len,
+ { "Name len", "smb.ntlmv2response.name.len", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_ntlmv2_response,
+ &ett_ntlmv2_response_name
+ };
+
+ proto_register_subtree_array(ett, array_length(ett));
+ proto_register_field_array(proto_smb, hf, array_length(hf));
+}
diff --git a/epan/dissectors/packet-smb-common.h b/epan/dissectors/packet-smb-common.h
new file mode 100644
index 0000000000..94d0a4b889
--- /dev/null
+++ b/epan/dissectors/packet-smb-common.h
@@ -0,0 +1,121 @@
+/* packet-smb-common.h
+ * Routines for SMB packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_SMB_COMMON_H__
+#define __PACKET_SMB_COMMON_H__
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+#include <ctype.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "smb.h"
+
+int dissect_smb_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+
+int display_unicode_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data);
+
+int display_ms_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data);
+
+const gchar *get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp,
+ gboolean useunicode, int *len, gboolean nopad, gboolean exactlen,
+ guint16 *bcp);
+
+int dissect_smb_64bit_time(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date);
+
+int dissect_nt_sid(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
+ char *name, char **sid_str, int hf_sid);
+
+/*
+ * Stuff for dissecting NT access masks
+ */
+
+typedef void (nt_access_mask_fn_t)(tvbuff_t *tvb, gint offset,
+ proto_tree *tree, guint32 access);
+
+/* Map generic access permissions to specific permissions */
+
+struct generic_mapping {
+ guint32 generic_read;
+ guint32 generic_write;
+ guint32 generic_execute;
+ guint32 generic_all;
+};
+
+/* Map standard access permissions to specific permissions */
+
+struct standard_mapping {
+ guint32 std_read;
+ guint32 std_write;
+ guint32 std_execute;
+ guint32 std_all;
+};
+
+struct access_mask_info {
+ char *specific_rights_name;
+ nt_access_mask_fn_t *specific_rights_fn;
+ struct generic_mapping *generic_mapping;
+ struct standard_mapping *standard_mapping;
+};
+
+int
+dissect_nt_access_mask(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, int hfindex,
+ struct access_mask_info *ami,
+ guint32 *perms);
+
+int
+dissect_nt_sec_desc(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep, int len,
+ struct access_mask_info *ami);
+
+extern const value_string share_type_vals[];
+
+/* Dissect a ntlmv2 response */
+
+int
+dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *ntlmssp_tree, int offset,
+ int len);
+
+void register_smb_common(int proto_smb);
+
+extern const value_string ntlm_name_types[];
+
+#define NTLM_NAME_END 0x0000
+#define NTLM_NAME_NB_HOST 0x0001
+#define NTLM_NAME_NB_DOMAIN 0x0002
+#define NTLM_NAME_DNS_HOST 0x0003
+#define NTLM_NAME_DNS_DOMAIN 0x0004
+
+#endif
diff --git a/epan/dissectors/packet-smb-logon.c b/epan/dissectors/packet-smb-logon.c
new file mode 100644
index 0000000000..a1060353f0
--- /dev/null
+++ b/epan/dissectors/packet-smb-logon.c
@@ -0,0 +1,1032 @@
+/* packet-smb-logon.c
+ * Routines for SMB net logon packet dissection
+ * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "packet-smb-common.h"
+
+static int proto_smb_logon = -1;
+static int hf_command = -1;
+static int hf_computer_name = -1;
+static int hf_unicode_computer_name = -1;
+static int hf_server_name = -1;
+static int hf_user_name = -1;
+static int hf_domain_name = -1;
+static int hf_mailslot_name = -1;
+static int hf_pdc_name = -1;
+static int hf_unicode_pdc_name = -1;
+static int hf_script_name = -1;
+static int hf_nt_version = -1;
+static int hf_lmnt_token = -1;
+static int hf_lm_token = -1;
+static int hf_major_version = -1;
+static int hf_minor_version = -1;
+static int hf_os_version = -1;
+static int hf_date_time = -1;
+static int hf_update_type = -1;
+static int hf_request_count = -1;
+static int hf_flags_autolock = -1;
+static int hf_flags_expire = -1;
+static int hf_flags_server_trust = -1;
+static int hf_flags_workstation_trust = -1;
+static int hf_flags_interdomain_trust = -1;
+static int hf_flags_mns_user = -1;
+static int hf_flags_normal_user = -1;
+static int hf_flags_temp_dup_user = -1;
+static int hf_flags_password_required = -1;
+static int hf_flags_homedir_required = -1;
+static int hf_flags_enabled = -1;
+static int hf_domain_sid_size = -1;
+static int hf_low_serial = -1;
+static int hf_pulse = -1;
+static int hf_random = -1;
+static int hf_db_count = -1;
+static int hf_db_index = -1;
+static int hf_large_serial = -1;
+static int hf_nt_date_time = -1;
+
+static int ett_smb_logon = -1;
+static int ett_smb_account_flags = -1;
+static int ett_smb_db_info = -1;
+
+#define ACC_FLAG_AUTO_LOCKED 0x0400
+#define ACC_FLAG_EXPIRE 0x0200
+#define ACC_FLAG_SERVER_TRUST 0x0100
+#define ACC_FLAG_WORKSTATION_TRUST 0x0080
+#define ACC_FLAG_INTERDOMAIN_TRUST 0x0040
+#define ACC_FLAG_MNS_USER 0x0020
+#define ACC_FLAG_NORMAL_USER 0x0010
+#define ACC_FLAG_TEMP_DUP_USER 0x0008
+#define ACC_FLAG_PASSWORD_REQUIRED 0x0004
+#define ACC_FLAG_HOMEDIR_REQUIRED 0x0002
+#define ACC_FLAG_ENABLED 0x0001
+
+static const true_false_string tfs_flags_autolock = {
+ "User account auto-locked",
+ "User account NOT auto-locked"
+};
+static const true_false_string tfs_flags_expire = {
+ "User password will NOT expire",
+ "User password will expire"
+};
+static const true_false_string tfs_flags_server_trust = {
+ "Server Trust user account",
+ "NOT a Server Trust user account"
+};
+static const true_false_string tfs_flags_workstation_trust = {
+ "Workstation Trust user account",
+ "NOT a Workstation Trust user account"
+};
+static const true_false_string tfs_flags_interdomain_trust = {
+ "Inter-domain Trust user account",
+ "NOT a Inter-domain Trust user account"
+};
+static const true_false_string tfs_flags_mns_user = {
+ "MNS Logon user account",
+ "NOT a MNS Logon user account"
+};
+static const true_false_string tfs_flags_normal_user = {
+ "Normal user account",
+ "NOT a normal user account"
+};
+static const true_false_string tfs_flags_temp_dup_user = {
+ "Temp duplicate user account",
+ "NOT a temp duplicate user account"
+};
+static const true_false_string tfs_flags_password_required = {
+ "NO password required",
+ "Password required"
+};
+static const true_false_string tfs_flags_homedir_required = {
+ "NO homedir required",
+ "Homedir required"
+};
+static const true_false_string tfs_flags_enabled = {
+ "User account enabled",
+ "User account disabled"
+};
+
+
+
+static int
+dissect_account_control(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ /* display the Allowable Account control bits */
+
+ proto_item *ti = NULL;
+ proto_tree *flags_tree = NULL;
+ guint32 flags;
+
+ flags = tvb_get_letohl(tvb, offset);
+
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, 4,
+ "Account control = 0x%04x", flags);
+
+ flags_tree = proto_item_add_subtree(ti, ett_smb_account_flags);
+ }
+
+ proto_tree_add_boolean(flags_tree, hf_flags_autolock, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_expire, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_server_trust, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_workstation_trust, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_interdomain_trust, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_mns_user, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_normal_user, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_temp_dup_user, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_password_required, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_homedir_required, tvb, offset, 4, flags);
+ proto_tree_add_boolean(flags_tree, hf_flags_enabled, tvb, offset, 4, flags);
+
+ offset += 4;
+
+ return offset;
+}
+
+static int
+display_LM_token(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint16 Token;
+
+ Token = tvb_get_letohs(tvb, offset);
+
+ if (Token & 0x01) {
+ proto_tree_add_uint_format(tree, hf_lm_token, tvb, offset, 2,
+ Token,
+ "LM20 Token: 0x%04x (LanMan 2.0 or higher)", Token);
+ } else {
+ /*
+ * XXX - are all values with the lower bit set LM 2.0,
+ * and all values with it not set LM 1.0?
+ * What do the other bits mean, if anything?
+ */
+ proto_tree_add_uint_format(tree, hf_lm_token, tvb, offset, 2,
+ Token,
+ "LM10 Token: 0x%04x (WFW Networking)", Token);
+ }
+
+ offset += 2;
+
+ return offset;
+}
+
+static int
+display_LMNT_token(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint16 Token;
+
+ Token = tvb_get_letohs(tvb, offset);
+
+ if (Token == 0xffff) {
+ proto_tree_add_uint_format(tree, hf_lmnt_token, tvb, offset, 2,
+ Token,
+ "LMNT Token: 0x%04x (Windows NT Networking)", Token);
+ } else {
+ /*
+ * XXX - what is it if it's not 0xffff?
+ */
+ proto_tree_add_uint_format(tree, hf_lm_token, tvb, offset, 2,
+ Token,
+ "LMNT Token: 0x%04x (Unknown)", Token);
+ }
+
+ offset += 2;
+
+ return offset;
+}
+
+static int
+dissect_smb_logon_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /*** 0x00 (LM1.0/LM2.0 LOGON Request) ***/
+
+ /* computer name */
+ offset = display_ms_string(tvb, tree, offset, hf_computer_name, NULL);
+
+ /* user name */
+ offset = display_ms_string(tvb, tree, offset, hf_user_name, NULL);
+
+ /* mailslot name */
+ offset = display_ms_string(tvb, tree, offset, hf_mailslot_name, NULL);
+
+ /*$$$$$ here add the Mailslot to the response list (if needed) */
+
+ /* Request count */
+ proto_tree_add_item(tree, hf_request_count, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_logon_LM10_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /*** 0x01 LanMan 1.0 Logon response ***/
+
+ /* user name */
+ offset = display_ms_string(tvb, tree, offset, hf_user_name, NULL);
+
+ /* script name */
+ offset = display_ms_string(tvb, tree, offset, hf_script_name, NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_smb_logon_2(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /*** 0x02 LM1.0 Query - Centralized Initialization ***/
+ /*** 0x03 LM1.0 Query - Distributed Initialization ***/
+ /*** 0x04 LM1.0 Query - Centralized Query Response ***/
+ /*** 0x04 LM1.0 Query - Distributed Query Response ***/
+
+ /* computer name */
+ offset = display_ms_string(tvb, tree, offset, hf_computer_name, NULL);
+
+ /* mailslot name */
+ offset = display_ms_string(tvb, tree, offset, hf_mailslot_name, NULL);
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_logon_LM20_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /*** 0x06 (LM2.0 LOGON Response) ***/
+
+ /* server name */
+ offset = display_ms_string(tvb, tree, offset, hf_server_name, NULL);
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_pdc_query(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ char *name;
+
+ /*** 0x07 Query for Primary PDC ***/
+
+ /* computer name */
+ offset = display_ms_string(tvb, tree, offset, hf_computer_name, &name);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " from %s", name);
+
+ g_free(name);
+
+ /* mailslot name */
+ offset = display_ms_string(tvb, tree, offset, hf_mailslot_name, NULL);
+
+ if (tvb_reported_length_remaining(tvb, offset) > 2) {
+ /*
+ * NT-style Query for PDC?
+ * If only 2 bytes remain, it's probably a Windows 95-style
+ * query, which has only an LM token after the mailslot
+ * name.
+ *
+ * XXX - base this on flags in the SMB header, e.g.
+ * the ASCII/Unicode strings flag?
+ */
+ if (offset % 2) offset++; /* word align ... */
+
+ /* Unicode computer name */
+ offset = display_unicode_string(tvb, tree, offset, hf_unicode_computer_name, NULL);
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LMNT token */
+ offset = display_LMNT_token(tvb, offset, tree);
+ }
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_pdc_startup(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /*** 0x08 Announce startup of PDC ***/
+
+ /* pdc name */
+ offset = display_ms_string(tvb, tree, offset, hf_pdc_name, NULL);
+
+ /* A short Announce will not have the rest */
+
+ if (tvb_reported_length_remaining(tvb, offset) != 0) {
+ char *name = NULL;
+
+ if (offset % 2) offset++; /* word align ... */
+
+ /* pdc name */
+ offset = display_unicode_string(tvb, tree, offset, hf_unicode_pdc_name, &name);
+
+ if (name && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": host %s", name);
+ g_free(name);
+ name = NULL;
+ }
+
+ if (offset % 2) offset++;
+
+ /* domain name */
+ offset = display_unicode_string(tvb, tree, offset, hf_domain_name, &name);
+
+ if (name && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", domain %s", name);
+ g_free(name);
+ name = NULL;
+ }
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LMNT token */
+ offset = display_LMNT_token(tvb, offset, tree);
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+ }
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_pdc_failure(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /*** 0x09 Announce failure of the PDC ***/
+ /*** 0x0F LM2.0 Resp. during LOGON pause ***/
+ /*** 0x10 (LM 2.0 Unknown user response) ***/
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+static int
+dissect_announce_change(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /*** 0x0A ( Announce change to UAS or SAM ) ***/
+ guint32 info_count;
+ proto_item *ti = NULL;
+ proto_tree *info_tree = NULL;
+ guint32 db_index;
+ guint32 domain_sid_size;
+
+ /* low serial number */
+ proto_tree_add_item(tree, hf_low_serial, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* date/time */
+ /* XXX - what format is this? Neither SMB_Date/SMB_Time nor
+ "time_t but in the local time zone" appear to be correct. */
+ proto_tree_add_item(tree, hf_date_time, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* pulse */
+ proto_tree_add_item(tree, hf_pulse, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* random */
+ proto_tree_add_item(tree, hf_random, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* pdc name */
+ offset = display_ms_string(tvb, tree, offset, hf_pdc_name, NULL);
+
+ /* domain name */
+ offset = display_ms_string(tvb, tree, offset, hf_domain_name, NULL);
+
+ if (offset % 2) offset++; /* word align ... */
+
+ if (tvb_reported_length_remaining(tvb, offset) > 2) {
+ /*
+ * XXX - older protocol versions don't have this stuff?
+ */
+ /* pdc name */
+ offset = display_unicode_string(tvb, tree, offset, hf_unicode_pdc_name, NULL);
+
+ /* domain name */
+ offset = display_unicode_string(tvb, tree, offset, hf_domain_name, NULL);
+
+ /* DB count */
+ info_count = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_db_count, tvb, offset, 4, info_count);
+ offset += 4;
+
+ while (info_count != 0) {
+ db_index = tvb_get_letohl(tvb, offset);
+ if (tree) {
+ ti = proto_tree_add_text(tree, tvb, offset, 20,
+ "DBChange Info Structure: index %u", db_index);
+ info_tree = proto_item_add_subtree(ti, ett_smb_db_info);
+ }
+
+ proto_tree_add_uint(info_tree, hf_db_index, tvb, offset, 4,
+ db_index);
+ offset += 4;
+
+ proto_tree_add_item(info_tree, hf_large_serial, tvb, offset, 8,
+ TRUE);
+ offset += 8;
+
+ offset = dissect_smb_64bit_time(tvb, info_tree, offset,
+ hf_nt_date_time);
+
+ info_count--;
+ }
+
+ /* Domain SID Size */
+ domain_sid_size = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_domain_sid_size, tvb, offset, 4,
+ domain_sid_size);
+ offset += 4;
+
+ if (domain_sid_size != 0) {
+ /* Align to four-byte boundary */
+ offset = ((offset + 3)/4)*4;
+
+ /* Domain SID */
+ offset = dissect_nt_sid(
+ tvb, offset, tree, "Domain", NULL, -1);
+ }
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LMNT token */
+ offset = display_LMNT_token(tvb, offset, tree);
+ }
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_sam_logon_req(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /* Netlogon command 0x12 - decode the SAM logon request from client */
+
+ guint32 domain_sid_size;
+
+ /* Request count */
+ proto_tree_add_item(tree, hf_request_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* computer name */
+ offset = display_unicode_string(tvb, tree, offset, hf_unicode_computer_name, NULL);
+
+ /* user name */
+ offset = display_unicode_string(tvb, tree, offset, hf_user_name, NULL);
+
+ /* mailslot name */
+ offset = display_ms_string(tvb, tree, offset, hf_mailslot_name, NULL);
+
+ /* account control */
+ offset = dissect_account_control(tvb, tree, offset);
+
+ /* Domain SID Size */
+ domain_sid_size = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_domain_sid_size, tvb, offset, 4,
+ domain_sid_size);
+ offset += 4;
+
+ if (domain_sid_size != 0) {
+ /* Align to four-byte boundary */
+ offset = ((offset + 3)/4)*4;
+
+ /* Domain SID */
+ offset = dissect_nt_sid(tvb, offset, tree, "Domain", NULL, -1);
+ }
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LMNT token */
+ offset = display_LMNT_token(tvb, offset, tree);
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_no_user(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /* 0x0B (Announce no user on machine) */
+
+ /* computer name */
+ offset = display_ms_string(tvb, tree, offset, hf_computer_name, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_relogon_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /*** 0x0d LanMan Response to relogon request ***/
+
+ /* Major version */
+ proto_tree_add_item(tree, hf_major_version, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* Minor version */
+ proto_tree_add_item(tree, hf_minor_version, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* OS version */
+ proto_tree_add_item(tree, hf_os_version, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_acc_update(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /*** 0x11 LM2.1 Announce Acc updates ***/
+
+ guint32 Temp1, Temp2;
+
+ Temp1 = tvb_get_letohl(tvb, offset);
+ Temp2 = tvb_get_letohl(tvb, offset + 4);
+
+ /* signature */
+ proto_tree_add_text(tree, tvb, offset, 8, "Signature: 0x%08x%08x",
+ Temp1, Temp2);
+ offset += 8;
+
+ /* date/time */
+ /* XXX - what format is this? Neither SMB_Date/SMB_Time nor
+ "time_t but in the local time zone" appear to be correct. */
+ proto_tree_add_item(tree, hf_date_time, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* computer name */
+ offset = display_ms_string(tvb, tree, offset, hf_computer_name, NULL);
+
+ /* user name */
+ offset = display_ms_string(tvb, tree, offset, hf_user_name, NULL);
+
+ /* update type */
+ proto_tree_add_item(tree, hf_update_type, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+
+static int
+dissect_smb_inter_resp(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ /* 0x0e LanMan Response to interrogate request */
+
+ /* Major version */
+ proto_tree_add_item(tree, hf_major_version, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* Minor version */
+ proto_tree_add_item(tree, hf_minor_version, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* OS version */
+ proto_tree_add_item(tree, hf_os_version, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LMNT token */
+ offset = display_LMNT_token(tvb, offset, tree);
+
+ /* XXX - no LM token? Every other packet has one after the LMNT
+ token. */
+
+ return offset;
+}
+
+
+static int
+dissect_smb_sam_logon_resp(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, int offset)
+{
+ /* Netlogon command 0x13 - decode the SAM logon response from server */
+
+ /* server name */
+ offset = display_unicode_string(tvb, tree, offset, hf_server_name, NULL);
+
+ /* user name */
+ offset = display_unicode_string(tvb, tree, offset, hf_user_name, NULL);
+
+ /* domain name */
+ offset = display_unicode_string(tvb, tree, offset, hf_domain_name, NULL);
+
+ /* NT version */
+ proto_tree_add_item(tree, hf_nt_version, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* LMNT token */
+ offset = display_LMNT_token(tvb, offset, tree);
+
+ /* LM token */
+ offset = display_LM_token(tvb, offset, tree);
+
+ return offset;
+}
+
+
+#define LOGON_LM10_LOGON_REQUEST 0x00
+#define LOGON_LM10_LOGON_RESPONSE 0x01
+#define LOGON_LM10_QUERY_CI 0x02
+#define LOGON_LM10_QUERY_DI 0x03
+#define LOGON_LM10_RESPONSE_CI 0x04
+#define LOGON_LM10_RESPONSE_DI 0x05
+#define LOGON_LM20_LOGON_RESPONSE 0x06
+#define LOGON_PDC_QUERY 0x07
+#define LOGON_PDC_STARTUP 0x08
+#define LOGON_PDC_FAILED 0x09
+#define LOGON_UAS_SAM 0x0a
+#define LOGON_NO_USER 0x0b
+#define LOGON_PDC_RESPONSE 0x0c
+#define LOGON_RELOGON_RESPONSE 0x0d
+#define LOGON_INTERROGATE_RESPONSE 0x0e
+#define LOGON_LM20_RESPONSE_DURING_LOGON 0x0f
+#define LOGON_LM20_USER_UNKNOWN 0x10
+#define LOGON_LM20_ACCOUNT_UPDATE 0x11
+#define LOGON_SAM_LOGON_REQUEST 0x12
+#define LOGON_SAM_LOGON_RESPONSE 0x13
+#define LOGON_SAM_RESPONSE_DURING_LOGON 0x14
+#define LOGON_SAM_USER_UNKNOWN 0x15
+#define LOGON_SAM_INTERROGATE_RESPONSE 0x16
+#define LOGON_SAM_AD_USER_UNKNOWN 0x17
+#define LOGON_SAM_UNKNOWN_18 0x18
+#define LOGON_SAM_AD_LOGON_RESPONSE 0x19
+#define LOGON_LAST_CMD 0x20
+
+static const value_string commands[] = {
+ {LOGON_LM10_LOGON_REQUEST, "LM1.0/LM2.0 LOGON Request"},
+ {LOGON_LM10_LOGON_RESPONSE, "LM1.0 LOGON Response"},
+ {LOGON_LM10_QUERY_CI, "LM1.0 Query - Centralized Initialization"},
+ {LOGON_LM10_QUERY_DI, "LM1.0 Query - Distributed Initialization"},
+ {LOGON_LM10_RESPONSE_CI, "LM1.0 Response - Centralized Query"},
+ {LOGON_LM10_RESPONSE_DI, "LM1.0 Response - Distributed Initialization"},
+ {LOGON_LM20_LOGON_RESPONSE, "LM2.0 Response to LOGON Request"},
+ {LOGON_PDC_QUERY, "Query for PDC"},
+ {LOGON_PDC_STARTUP, "Announce Startup of PDC"},
+ {LOGON_PDC_FAILED, "Announce Failed PDC"},
+ {LOGON_UAS_SAM, "Announce Change to UAS or SAM"},
+ {LOGON_NO_USER, "Announce no user on machine"},
+ {LOGON_PDC_RESPONSE, "Response from PDC"},
+ {LOGON_RELOGON_RESPONSE, "LM1.0/LM2.0 Response to re-LOGON Request"},
+ {LOGON_INTERROGATE_RESPONSE, "LM1.0/LM2.0 Response to Interrogate Request"},
+ {LOGON_LM20_RESPONSE_DURING_LOGON,"LM2.0 Response during LOGON pause"},
+ {LOGON_LM20_USER_UNKNOWN, "LM2.0 Response - user unknown"},
+ {LOGON_LM20_ACCOUNT_UPDATE, "LM2.0 Announce account updates"},
+ {LOGON_SAM_LOGON_REQUEST, "SAM LOGON request from client"},
+ {LOGON_SAM_LOGON_RESPONSE, "Response to SAM LOGON request"},
+ {LOGON_SAM_RESPONSE_DURING_LOGON,"SAM Response during LOGON pause"},
+ {LOGON_SAM_USER_UNKNOWN, "SAM Response - user unknown"},
+ {LOGON_SAM_INTERROGATE_RESPONSE,"SAM Response to Interrogate Request"},
+ {LOGON_SAM_AD_USER_UNKNOWN, "SAM Active Directory Response - user unknown"},
+ {LOGON_SAM_UNKNOWN_18, "SAM unknown command 0x18"},
+ {LOGON_SAM_AD_LOGON_RESPONSE, "Active Directory Response to SAM LOGON request"},
+ {0, NULL}
+};
+
+
+static int (*dissect_smb_logon_cmds[])(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) = {
+ dissect_smb_logon_request, /* 0x00 (LM1.0/LM2.0 LOGON Request) */
+ dissect_smb_logon_LM10_resp,/* 0x01 (LM1.0 LOGON Response) */
+ dissect_smb_logon_2, /* 0x02 (LM1.0 Query Centralized Init.)*/
+ dissect_smb_logon_2, /* 0x03 (LM1.0 Query Distributed Init.)*/
+ dissect_smb_logon_2, /* 0x04 (LM1.0 Centralized Query Resp.)*/
+ dissect_smb_logon_2, /* 0x05 (LM1.0 Distributed Query Resp.) */
+ dissect_smb_logon_LM20_resp,/* 0x06 (LM2.0 LOGON Response) */
+ dissect_smb_pdc_query, /* 0x07 (Query for PDC) */
+ dissect_smb_pdc_startup, /* 0x08 (Announce PDC startup) */
+ dissect_smb_pdc_failure, /* 0x09 (Announce Failed PDC) */
+ dissect_announce_change, /* 0x0A (Announce Change to UAS or SAM)*/
+ dissect_smb_no_user, /* 0x0B (Announce no user on machine)*/
+ dissect_smb_pdc_startup, /* 0x0C (Response from PDC) */
+ dissect_smb_relogon_resp, /* 0x0D (Relogon response) */
+ dissect_smb_inter_resp, /* 0x0E (Interrogate response) */
+ dissect_smb_pdc_failure, /* 0x0F (LM2.0 Resp. during LOGON pause*/
+ dissect_smb_pdc_failure, /* 0x10 (LM 2.0 Unknown user response)*/
+ dissect_smb_acc_update, /* 0x11 (LM2.1 Announce Acc updates)*/
+ dissect_smb_sam_logon_req, /* 0x12 (SAM LOGON request ) */
+ dissect_smb_sam_logon_resp, /* 0x13 (SAM LOGON response) */
+ dissect_smb_unknown, /* 0x14 (SAM Response during LOGON Pause) */
+ dissect_smb_unknown, /* 0x15 (SAM Response User Unknown) */
+ dissect_smb_unknown, /* 0x16 (SAM Response to Interrogate)*/
+ dissect_smb_unknown, /* 0x17 (SAM AD response User Unknown*/
+ dissect_smb_unknown, /* 0x18 (Unknown command) */
+ dissect_smb_unknown /* 0x19 (SAM LOGON AD response) */
+};
+
+
+static void
+dissect_smb_logon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint8 cmd;
+ proto_tree *smb_logon_tree = NULL;
+ proto_item *item = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "NETLOGON");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* get the Command field */
+ cmd = tvb_get_guint8(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, commands, "Unknown Command:%02x") );
+
+ if (tree) {
+ item = proto_tree_add_item(tree, proto_smb_logon, tvb,
+ offset, -1, FALSE);
+
+ smb_logon_tree = proto_item_add_subtree(item, ett_smb_logon);
+ }
+
+ /* command */
+ proto_tree_add_uint(smb_logon_tree, hf_command, tvb, offset, 1, cmd);
+ offset += 1;
+
+ /* skip next byte */
+ offset += 1;
+
+ if (cmd<LOGON_LAST_CMD) {
+ offset = (dissect_smb_logon_cmds[cmd])(tvb, pinfo,
+ smb_logon_tree, offset);
+ } else {
+ /* unknown command */
+ offset = dissect_smb_unknown(tvb, pinfo, smb_logon_tree,
+ offset);
+ }
+}
+
+void
+proto_register_smb_logon( void)
+{
+ static hf_register_info hf[] = {
+ { &hf_command,
+ { "Command", "netlogon.command", FT_UINT8, BASE_HEX,
+ VALS(commands), 0, "NETLOGON Command", HFILL }},
+
+ { &hf_computer_name,
+ { "Computer Name", "netlogon.computer_name", FT_STRING, BASE_NONE,
+ NULL, 0, "NETLOGON Computer Name", HFILL }},
+
+ { &hf_unicode_computer_name,
+ { "Unicode Computer Name", "netlogon.unicode_computer_name", FT_STRING, BASE_NONE,
+ NULL, 0, "NETLOGON Unicode Computer Name", HFILL }},
+
+ { &hf_server_name,
+ { "Server Name", "netlogon.server_name", FT_STRING, BASE_NONE,
+ NULL, 0, "NETLOGON Server Name", HFILL }},
+
+ { &hf_user_name,
+ { "User Name", "netlogon.user_name", FT_STRING, BASE_NONE,
+ NULL, 0, "NETLOGON User Name", HFILL }},
+
+ { &hf_domain_name,
+ { "Domain Name", "netlogon.domain_name", FT_STRING, BASE_NONE,
+ NULL, 0, "NETLOGON Domain Name", HFILL }},
+
+ { &hf_mailslot_name,
+ { "Mailslot Name", "netlogon.mailslot_name", FT_STRING, BASE_NONE,
+ NULL, 0, "NETLOGON Mailslot Name", HFILL }},
+
+ { &hf_pdc_name,
+ { "PDC Name", "netlogon.pdc_name", FT_STRING, BASE_NONE,
+ NULL, 0, "NETLOGON PDC Name", HFILL }},
+
+ { &hf_unicode_pdc_name,
+ { "Unicode PDC Name", "netlogon.unicode_pdc_name", FT_STRING, BASE_NONE,
+ NULL, 0, "NETLOGON Unicode PDC Name", HFILL }},
+
+ { &hf_script_name,
+ { "Script Name", "netlogon.script_name", FT_STRING, BASE_NONE,
+ NULL, 0, "NETLOGON Script Name", HFILL }},
+
+ { &hf_nt_version,
+ { "NT Version", "netlogon.nt_version", FT_UINT32, BASE_DEC,
+ NULL, 0, "NETLOGON NT Version", HFILL }},
+
+ /* An LMNT Token, if 0xffff, is "WindowsNT Networking";
+ what is it otherwise? */
+ { &hf_lmnt_token,
+ { "LMNT Token", "netlogon.lmnt_token", FT_UINT16, BASE_HEX,
+ NULL, 0, "NETLOGON LMNT Token", HFILL }},
+
+ { &hf_lm_token,
+ { "LM Token", "netlogon.lm_token", FT_UINT16, BASE_HEX,
+ NULL, 0, "NETLOGON LM Token", HFILL }},
+
+ { &hf_major_version,
+ { "Workstation Major Version", "netlogon.major_version", FT_UINT8, BASE_DEC,
+ NULL, 0, "NETLOGON Workstation Major Version", HFILL }},
+
+ { &hf_minor_version,
+ { "Workstation Minor Version", "netlogon.minor_version", FT_UINT8, BASE_DEC,
+ NULL, 0, "NETLOGON Workstation Minor Version", HFILL }},
+
+ { &hf_os_version,
+ { "Workstation OS Version", "netlogon.os_version", FT_UINT8, BASE_DEC,
+ NULL, 0, "NETLOGON Workstation OS Version", HFILL }},
+
+ { &hf_date_time,
+ { "Date/Time", "netlogon.date_time", FT_UINT32, BASE_DEC,
+ NULL, 0, "NETLOGON Date/Time", HFILL }},
+
+ { &hf_update_type,
+ { "Update Type", "netlogon.update", FT_UINT16, BASE_DEC,
+ NULL, 0, "NETLOGON Update Type", HFILL }},
+
+ { &hf_request_count,
+ { "Request Count", "netlogon.request_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "NETLOGON Request Count", HFILL }},
+
+ { &hf_flags_autolock,
+ { "Autolock", "netlogon.flags.autolock", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_autolock), ACC_FLAG_AUTO_LOCKED, "NETLOGON Account Autolock", HFILL}},
+
+ { &hf_flags_expire,
+ { "Expire", "netlogon.flags.expire", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_expire), ACC_FLAG_EXPIRE, "NETLOGON Will Account Expire", HFILL}},
+
+ { &hf_flags_server_trust,
+ { "Server Trust", "netlogon.flags.server", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_server_trust), ACC_FLAG_SERVER_TRUST, "NETLOGON Server Trust Account", HFILL}},
+
+ { &hf_flags_workstation_trust,
+ { "Workstation Trust", "netlogon.flags.workstation", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_workstation_trust), ACC_FLAG_WORKSTATION_TRUST, "NETLOGON Workstation Trust Account", HFILL}},
+
+ { &hf_flags_interdomain_trust,
+ { "Interdomain Trust", "netlogon.flags.interdomain", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_interdomain_trust), ACC_FLAG_INTERDOMAIN_TRUST, "NETLOGON Inter-domain Trust Account", HFILL}},
+
+ { &hf_flags_mns_user,
+ { "MNS User", "netlogon.flags.mns", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_mns_user), ACC_FLAG_MNS_USER, "NETLOGON MNS User Account", HFILL}},
+
+ { &hf_flags_normal_user,
+ { "Normal User", "netlogon.flags.normal", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_normal_user), ACC_FLAG_NORMAL_USER, "NETLOGON Normal User Account", HFILL}},
+
+ { &hf_flags_temp_dup_user,
+ { "Temp Duplicate User", "netlogon.flags.temp_dup", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_temp_dup_user), ACC_FLAG_TEMP_DUP_USER, "NETLOGON Temp Duplicate User Account", HFILL}},
+
+ { &hf_flags_password_required,
+ { "Password", "netlogon.flags.password", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_password_required), ACC_FLAG_PASSWORD_REQUIRED, "NETLOGON Password Required", HFILL}},
+
+ { &hf_flags_homedir_required,
+ { "Homedir", "netlogon.flags.homedir", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_homedir_required), ACC_FLAG_HOMEDIR_REQUIRED, "NETLOGON Homedir Required", HFILL}},
+
+ { &hf_flags_enabled,
+ { "Enabled", "netlogon.flags.enabled", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_enabled), ACC_FLAG_ENABLED, "NETLOGON Is This Account Enabled", HFILL}},
+
+ { &hf_domain_sid_size,
+ { "Domain SID Size", "netlogon.domain_sid_size", FT_UINT32, BASE_DEC,
+ NULL, 0, "NETLOGON Domain SID Size", HFILL }},
+
+ { &hf_low_serial,
+ { "Low Serial Number", "netlogon.low_serial", FT_UINT32, BASE_DEC,
+ NULL, 0, "NETLOGON Low Serial Number", HFILL }},
+
+ { &hf_pulse,
+ { "Pulse", "netlogon.pulse", FT_UINT32, BASE_DEC,
+ NULL, 0, "NETLOGON Pulse", HFILL }},
+
+ { &hf_random,
+ { "Random", "netlogon.random", FT_UINT32, BASE_DEC,
+ NULL, 0, "NETLOGON Random", HFILL }},
+
+ { &hf_db_count,
+ { "DB Count", "netlogon.db_count", FT_UINT32, BASE_DEC,
+ NULL, 0, "NETLOGON DB Count", HFILL }},
+
+ { &hf_db_index,
+ { "Database Index", "netlogon.db_index", FT_UINT32, BASE_DEC,
+ NULL, 0, "NETLOGON Database Index", HFILL }},
+
+ { &hf_large_serial,
+ { "Large Serial Number", "netlogon.large_serial", FT_UINT64, BASE_DEC,
+ NULL, 0, "NETLOGON Large Serial Number", HFILL }},
+
+ { &hf_nt_date_time,
+ { "NT Date/Time", "netlogon.nt_date_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "NETLOGON NT Date/Time", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_smb_logon,
+ &ett_smb_account_flags,
+ &ett_smb_db_info
+ };
+
+ proto_smb_logon = proto_register_protocol(
+ "Microsoft Windows Logon Protocol", "NETLOGON", "netlogon");
+
+ proto_register_field_array(proto_smb_logon, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("netlogon", dissect_smb_logon, proto_smb_logon);
+}
diff --git a/epan/dissectors/packet-smb-mailslot.c b/epan/dissectors/packet-smb-mailslot.c
new file mode 100644
index 0000000000..9ad7db08ed
--- /dev/null
+++ b/epan/dissectors/packet-smb-mailslot.c
@@ -0,0 +1,265 @@
+/* packet-smb-mailslot.c
+ * Routines for SMB mailslot packet dissection
+ * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include "packet-smb-common.h"
+#include "packet-smb-mailslot.h"
+#include "packet-smb-browse.h"
+#include "packet-smb-pipe.h"
+
+static int proto_smb_msp = -1;
+static int hf_opcode = -1;
+static int hf_priority = -1;
+static int hf_class = -1;
+static int hf_size = -1;
+static int hf_name = -1;
+
+static int ett_smb_msp = -1;
+
+static dissector_handle_t mailslot_browse_handle;
+static dissector_handle_t mailslot_lanman_handle;
+static dissector_handle_t netlogon_handle;
+static dissector_handle_t data_handle;
+
+#define MAILSLOT_UNKNOWN 0
+#define MAILSLOT_BROWSE 1
+#define MAILSLOT_LANMAN 2
+#define MAILSLOT_NET 3
+#define MAILSLOT_TEMP_NETLOGON 4
+#define MAILSLOT_MSSP 5
+
+static const value_string opcode_vals[] = {
+ {1, "Write Mail Slot"},
+ {0, NULL}
+};
+
+static const value_string class_vals[] = {
+ {1, "Reliable"},
+ {2, "Unreliable & Broadcast"},
+ {0, NULL}
+};
+
+/* decode the SMB mail slot protocol
+ for requests
+ mailslot is the name of the mailslot, e.g. BROWSE
+ si->trans_subcmd is set to the symbolic constant matching the mailslot name.
+ for responses
+ mailslot is NULL
+ si->trans_subcmd gives us which mailslot this response refers to.
+*/
+
+gboolean
+dissect_mailslot_smb(tvbuff_t *mshdr_tvb, tvbuff_t *setup_tvb,
+ tvbuff_t *tvb, const char *mailslot, packet_info *pinfo,
+ proto_tree *parent_tree)
+{
+ smb_info_t *smb_info;
+ smb_transact_info_t *tri;
+ int trans_subcmd;
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ guint16 opcode;
+ int offset = 0;
+ int len;
+
+ if (!proto_is_protocol_enabled(find_protocol_by_id(proto_smb_msp))) {
+ return FALSE;
+ }
+ pinfo->current_proto = "SMB Mailslot";
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMB Mailslot");
+ }
+
+ if ((tvb==NULL) || (tvb_reported_length(tvb)==0)) {
+ /* Interim reply */
+ col_set_str(pinfo->cinfo, COL_INFO, "Interim reply");
+ return TRUE;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ smb_info = pinfo->private_data;
+ if (smb_info->sip != NULL)
+ tri = smb_info->sip->extra_info;
+ else
+ tri = NULL;
+
+ /* check which mailslot this is about */
+ trans_subcmd=MAILSLOT_UNKNOWN;
+ if(smb_info->request){
+ if(strncmp(mailslot,"BROWSE",6) == 0){
+ trans_subcmd=MAILSLOT_BROWSE;
+ } else if(strncmp(mailslot,"LANMAN",6) == 0){
+ trans_subcmd=MAILSLOT_LANMAN;
+ } else if(strncmp(mailslot,"NET",3) == 0){
+ trans_subcmd=MAILSLOT_NET;
+ } else if(strncmp(mailslot,"TEMP\\NETLOGON",13) == 0){
+ trans_subcmd=MAILSLOT_TEMP_NETLOGON;
+ } else if(strncmp(mailslot,"MSSP",4) == 0){
+ trans_subcmd=MAILSLOT_MSSP;
+ }
+ if (!pinfo->fd->flags.visited) {
+ if (tri != NULL)
+ tri->trans_subcmd = trans_subcmd;
+ }
+ } else {
+ trans_subcmd = tri->trans_subcmd;
+ }
+
+ /* Only do these ones if we have them. For fragmented SMB Transactions
+ we may only have the setup area for the first fragment
+ */
+ if(mshdr_tvb && setup_tvb){
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, proto_smb_msp,
+ mshdr_tvb, 0, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_smb_msp);
+ }
+
+ /* do the opcode field */
+ opcode = tvb_get_letohs(setup_tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(opcode, opcode_vals, "Unknown opcode: 0x%04x"));
+ }
+
+
+ /* These are in the setup words; use "setup_tvb". */
+
+ /* opcode */
+ proto_tree_add_uint(tree, hf_opcode, setup_tvb, offset, 2,
+ opcode);
+ offset += 2;
+
+ /* priority */
+ proto_tree_add_item(tree, hf_priority, setup_tvb, offset, 2,
+ TRUE);
+ offset += 2;
+
+ /* class */
+ proto_tree_add_item(tree, hf_class, setup_tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* These are in the rest of the data; use "mshdr_tvb", which
+ starts at the same place "setup_tvb" does. */
+
+ /* size */
+ /* this is actually bytecount in the SMB Transaction command */
+ proto_tree_add_item(tree, hf_size, mshdr_tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* mailslot name */
+ len = tvb_strsize(mshdr_tvb, offset);
+ proto_tree_add_item(tree, hf_name, mshdr_tvb, offset, len, TRUE);
+ offset += len;
+ proto_item_set_len(item, offset);
+ }
+
+ switch(trans_subcmd){
+ case MAILSLOT_BROWSE:
+ call_dissector(mailslot_browse_handle, tvb, pinfo,
+ parent_tree);
+ break;
+
+ case MAILSLOT_LANMAN:
+ call_dissector(mailslot_lanman_handle, tvb, pinfo,
+ parent_tree);
+ break;
+
+ case MAILSLOT_NET:
+ case MAILSLOT_TEMP_NETLOGON:
+ case MAILSLOT_MSSP:
+ call_dissector(netlogon_handle, tvb, pinfo,
+ parent_tree);
+ break;
+
+ default:
+ /*
+ * We dissected the mailslot header, but we don't know
+ * how to dissect the message; dissect the latter as data,
+ * but indicate that we successfully dissected the mailslot
+ * stuff.
+ */
+ call_dissector(data_handle,tvb, pinfo, parent_tree);
+ break;
+ }
+ return TRUE;
+}
+
+void
+proto_register_smb_mailslot(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_opcode,
+ { "Opcode", "mailslot.opcode", FT_UINT16, BASE_DEC,
+ VALS(opcode_vals), 0, "MAILSLOT OpCode", HFILL }},
+
+ { &hf_priority,
+ { "Priority", "mailslot.priority", FT_UINT16, BASE_DEC,
+ NULL, 0, "MAILSLOT Priority of transaction", HFILL }},
+
+ { &hf_class,
+ { "Class", "mailslot.class", FT_UINT16, BASE_DEC,
+ VALS(class_vals), 0, "MAILSLOT Class of transaction", HFILL }},
+
+ { &hf_size,
+ { "Size", "mailslot.size", FT_UINT16, BASE_DEC,
+ NULL, 0, "MAILSLOT Total size of mail data", HFILL }},
+
+ { &hf_name,
+ { "Mailslot Name", "mailslot.name", FT_STRING, BASE_NONE,
+ NULL, 0, "MAILSLOT Name of mailslot", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_smb_msp
+ };
+
+ proto_smb_msp = proto_register_protocol(
+ "SMB MailSlot Protocol", "SMB Mailslot", "mailslot");
+
+ proto_register_field_array(proto_smb_msp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_smb_mailslot(void)
+{
+ mailslot_browse_handle = find_dissector("mailslot_browse");
+ mailslot_lanman_handle = find_dissector("mailslot_lanman");
+ netlogon_handle = find_dissector("netlogon");
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-smb-mailslot.h b/epan/dissectors/packet-smb-mailslot.h
new file mode 100644
index 0000000000..aa8cf9a9d7
--- /dev/null
+++ b/epan/dissectors/packet-smb-mailslot.h
@@ -0,0 +1,34 @@
+/* packet-smb-mailslot.h
+ * Declaration of routines for SMB mailslot packet dissection
+ * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_SMB_MAILSLOT_H_
+#define _PACKET_SMB_MAILSLOT_H_
+
+gboolean
+dissect_mailslot_smb(tvbuff_t *total_tvb, tvbuff_t *setup_tvb,
+ tvbuff_t *tvb, const char *mailslot,
+ packet_info *pinfo, proto_tree *tree);
+
+#endif
diff --git a/epan/dissectors/packet-smb-pipe.c b/epan/dissectors/packet-smb-pipe.c
new file mode 100644
index 0000000000..b7ba500976
--- /dev/null
+++ b/epan/dissectors/packet-smb-pipe.c
@@ -0,0 +1,3931 @@
+/*
+XXX Fixme : shouldnt show [malformed frame] for long packets
+*/
+
+/* packet-smb-pipe.c
+ * Routines for SMB named pipe packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ * significant rewrite to tvbuffify the dissector, Ronnie Sahlberg and
+ * Guy Harris 2001
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+#include <ctype.h>
+#include <epan/packet.h>
+#include "smb.h"
+#include "packet-smb-pipe.h"
+#include "packet-smb-browse.h"
+#include "packet-smb-common.h"
+#include "packet-dcerpc.h"
+#include "reassemble.h"
+
+static int proto_smb_pipe = -1;
+static int hf_pipe_function = -1;
+static int hf_pipe_priority = -1;
+static int hf_pipe_peek_available = -1;
+static int hf_pipe_peek_remaining = -1;
+static int hf_pipe_peek_status = -1;
+static int hf_pipe_getinfo_info_level = -1;
+static int hf_pipe_getinfo_output_buffer_size = -1;
+static int hf_pipe_getinfo_input_buffer_size = -1;
+static int hf_pipe_getinfo_maximum_instances = -1;
+static int hf_pipe_getinfo_current_instances = -1;
+static int hf_pipe_getinfo_pipe_name_length = -1;
+static int hf_pipe_getinfo_pipe_name = -1;
+static int hf_pipe_write_raw_bytes_written = -1;
+static int hf_pipe_fragments = -1;
+static int hf_pipe_fragment = -1;
+static int hf_pipe_fragment_overlap = -1;
+static int hf_pipe_fragment_overlap_conflict = -1;
+static int hf_pipe_fragment_multiple_tails = -1;
+static int hf_pipe_fragment_too_long_fragment = -1;
+static int hf_pipe_fragment_error = -1;
+static int hf_pipe_reassembled_in = -1;
+
+static gint ett_smb_pipe = -1;
+static gint ett_smb_pipe_fragment = -1;
+static gint ett_smb_pipe_fragments = -1;
+
+static const fragment_items smb_pipe_frag_items = {
+ &ett_smb_pipe_fragment,
+ &ett_smb_pipe_fragments,
+ &hf_pipe_fragments,
+ &hf_pipe_fragment,
+ &hf_pipe_fragment_overlap,
+ &hf_pipe_fragment_overlap_conflict,
+ &hf_pipe_fragment_multiple_tails,
+ &hf_pipe_fragment_too_long_fragment,
+ &hf_pipe_fragment_error,
+ NULL,
+ "fragments"
+};
+
+static int proto_smb_lanman = -1;
+static int hf_function_code = -1;
+static int hf_param_desc = -1;
+static int hf_return_desc = -1;
+static int hf_aux_data_desc = -1;
+static int hf_detail_level = -1;
+static int hf_recv_buf_len = -1;
+static int hf_send_buf_len = -1;
+static int hf_continuation_from = -1;
+static int hf_status = -1;
+static int hf_convert = -1;
+static int hf_ecount = -1;
+static int hf_acount = -1;
+static int hf_share_name = -1;
+static int hf_share_type = -1;
+static int hf_share_comment = -1;
+static int hf_share_permissions = -1;
+static int hf_share_max_uses = -1;
+static int hf_share_current_uses = -1;
+static int hf_share_path = -1;
+static int hf_share_password = -1;
+static int hf_server_name = -1;
+static int hf_server_major = -1;
+static int hf_server_minor = -1;
+static int hf_server_comment = -1;
+static int hf_abytes = -1;
+static int hf_current_time = -1;
+static int hf_msecs = -1;
+static int hf_hour = -1;
+static int hf_minute = -1;
+static int hf_second = -1;
+static int hf_hundredths = -1;
+static int hf_tzoffset = -1;
+static int hf_timeinterval = -1;
+static int hf_day = -1;
+static int hf_month = -1;
+static int hf_year = -1;
+static int hf_weekday = -1;
+static int hf_enumeration_domain = -1;
+static int hf_last_entry = -1;
+static int hf_computer_name = -1;
+static int hf_user_name = -1;
+static int hf_group_name = -1;
+static int hf_workstation_domain = -1;
+static int hf_workstation_major = -1;
+static int hf_workstation_minor = -1;
+static int hf_logon_domain = -1;
+static int hf_other_domains = -1;
+static int hf_password = -1;
+static int hf_workstation_name = -1;
+static int hf_ustruct_size = -1;
+static int hf_logon_code = -1;
+static int hf_privilege_level = -1;
+static int hf_operator_privileges = -1;
+static int hf_num_logons = -1;
+static int hf_bad_pw_count = -1;
+static int hf_last_logon = -1;
+static int hf_last_logoff = -1;
+static int hf_logoff_time = -1;
+static int hf_kickoff_time = -1;
+static int hf_password_age = -1;
+static int hf_password_can_change = -1;
+static int hf_password_must_change = -1;
+static int hf_script_path = -1;
+static int hf_logoff_code = -1;
+static int hf_duration = -1;
+static int hf_comment = -1;
+static int hf_user_comment = -1;
+static int hf_full_name = -1;
+static int hf_homedir = -1;
+static int hf_parameters = -1;
+static int hf_logon_server = -1;
+static int hf_country_code = -1;
+static int hf_workstations = -1;
+static int hf_max_storage = -1;
+static int hf_units_per_week = -1;
+static int hf_logon_hours = -1;
+static int hf_code_page = -1;
+static int hf_new_password = -1;
+static int hf_old_password = -1;
+static int hf_reserved = -1;
+
+static gint ett_lanman = -1;
+static gint ett_lanman_unknown_entries = -1;
+static gint ett_lanman_unknown_entry = -1;
+static gint ett_lanman_shares = -1;
+static gint ett_lanman_share = -1;
+static gint ett_lanman_groups = -1;
+static gint ett_lanman_servers = -1;
+static gint ett_lanman_server = -1;
+
+static dissector_handle_t data_handle;
+
+/*
+ * See
+ *
+ * ftp://ftp.microsoft.com/developr/drg/CIFS/cifsrap2.txt
+ *
+ * among other documents.
+ */
+
+static const value_string status_vals[] = {
+ {0, "Success"},
+ {5, "User has insufficient privilege"},
+ {65, "Network access is denied"},
+ {86, "The specified password is invalid"},
+ {SMBE_moredata, "Additional data is available"},
+ {2114, "Service is not running on the remote computer"},
+ {2123, "Supplied buffer is too small"},
+ {2141, "Server is not configured for transactions (IPC$ not shared)"},
+ {2212, "An error occurred while loading or running the logon script"},
+ {2214, "The logon was not validated by any server"},
+ {2217, "The logon server is running an older software version"},
+ {2221, "The user name was not found"},
+ {2226, "Operation not permitted on Backup Domain Controller"},
+ {2240, "The user is not allowed to logon from this computer"},
+ {2241, "The user is not allowed to logon at this time"},
+ {2242, "The user password has expired"},
+ {2243, "The password cannot be changed"},
+ {2246, "The password is too short"},
+ {0, NULL}
+};
+
+static const value_string privilege_vals[] = {
+ {0, "Guest"},
+ {1, "User"},
+ {2, "Administrator"},
+ {0, NULL}
+};
+
+static const value_string op_privilege_vals[] = {
+ {0, "Print operator"},
+ {1, "Communications operator"},
+ {2, "Server operator"},
+ {3, "Accounts operator"},
+ {0, NULL}
+};
+
+static const value_string weekday_vals[] = {
+ {0, "Sunday"},
+ {1, "Monday"},
+ {2, "Tuesday"},
+ {3, "Wednesday"},
+ {4, "Thursday"},
+ {5, "Friday"},
+ {6, "Saturday"},
+ {0, NULL}
+};
+
+static int
+add_word_param(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
+{
+ guint16 WParam;
+
+ if (hf_index != -1)
+ proto_tree_add_item(tree, hf_index, tvb, offset, 2, TRUE);
+ else {
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Word Param: %u (0x%04X)", WParam, WParam);
+ }
+ offset += 2;
+ return offset;
+}
+
+static int
+add_dword_param(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
+{
+ guint32 LParam;
+
+ if (hf_index != -1)
+ proto_tree_add_item(tree, hf_index, tvb, offset, 4, TRUE);
+ else {
+ LParam = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Doubleword Param: %u (0x%08X)", LParam, LParam);
+ }
+ offset += 4;
+ return offset;
+}
+
+static int
+add_byte_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo _U_,
+ proto_tree *tree, int convert _U_, int hf_index)
+{
+ guint8 BParam;
+
+ if (hf_index != -1)
+ proto_tree_add_item(tree, hf_index, tvb, offset, count, TRUE);
+ else {
+ if (count == 1) {
+ BParam = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, count,
+ "Byte Param: %u (0x%02X)",
+ BParam, BParam);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, count,
+ "Byte Param: %s",
+ tvb_bytes_to_str(tvb, offset, count));
+ }
+ }
+ offset += count;
+ return offset;
+}
+
+static int
+add_pad_param(tvbuff_t *tvb _U_, int offset, int count, packet_info *pinfo _U_,
+ proto_tree *tree _U_, int convert _U_, int hf_index _U_)
+{
+ /*
+ * This is for parameters that have descriptor entries but that
+ * are, in practice, just padding.
+ */
+ offset += count;
+ return offset;
+}
+
+static void
+add_null_pointer_param(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
+{
+ if (hf_index != -1) {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "%s (Null pointer)",
+ proto_registrar_get_name(hf_index));
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "String Param (Null pointer)");
+ }
+}
+
+static int
+add_string_param(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
+{
+ guint string_len;
+
+ string_len = tvb_strsize(tvb, offset);
+ if (hf_index != -1) {
+ proto_tree_add_item(tree, hf_index, tvb, offset, string_len,
+ TRUE);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, string_len,
+ "String Param: %s",
+ tvb_format_text(tvb, offset, string_len));
+ }
+ offset += string_len;
+ return offset;
+}
+
+static const char *
+get_stringz_pointer_value(tvbuff_t *tvb, int offset, int convert, int *cptrp,
+ int *lenp)
+{
+ int cptr;
+ gint string_len;
+
+ /* pointer to string */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ *cptrp = cptr;
+
+ /* string */
+ if (tvb_offset_exists(tvb, cptr) &&
+ (string_len = tvb_strnlen(tvb, cptr, -1)) != -1) {
+ string_len++; /* include the terminating '\0' */
+ *lenp = string_len;
+ return tvb_format_text(tvb, cptr, string_len - 1);
+ } else
+ return NULL;
+}
+
+static int
+add_stringz_pointer_param(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo _U_, proto_tree *tree, int convert, int hf_index)
+{
+ int cptr;
+ const char *string;
+ gint string_len;
+
+ string = get_stringz_pointer_value(tvb, offset, convert, &cptr,
+ &string_len);
+ offset += 4;
+
+ /* string */
+ if (string != NULL) {
+ if (hf_index != -1) {
+ proto_tree_add_item(tree, hf_index, tvb, cptr,
+ string_len, TRUE);
+ } else {
+ proto_tree_add_text(tree, tvb, cptr, string_len,
+ "String Param: %s", string);
+ }
+ } else {
+ if (hf_index != -1) {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "%s: <String goes past end of frame>",
+ proto_registrar_get_name(hf_index));
+ } else {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "String Param: <String goes past end of frame>");
+ }
+ }
+
+ return offset;
+}
+
+static int
+add_bytes_pointer_param(tvbuff_t *tvb, int offset, int count,
+ packet_info *pinfo _U_, proto_tree *tree, int convert, int hf_index)
+{
+ int cptr;
+
+ /* pointer to byte array */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ offset += 4;
+
+ /* bytes */
+ if (tvb_bytes_exist(tvb, cptr, count)) {
+ if (hf_index != -1) {
+ proto_tree_add_item(tree, hf_index, tvb, cptr,
+ count, TRUE);
+ } else {
+ proto_tree_add_text(tree, tvb, cptr, count,
+ "Byte Param: %s",
+ tvb_bytes_to_str(tvb, cptr, count));
+ }
+ } else {
+ if (hf_index != -1) {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "%s: <Bytes go past end of frame>",
+ proto_registrar_get_name(hf_index));
+ } else {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "Byte Param: <Bytes goes past end of frame>");
+ }
+ }
+
+ return offset;
+}
+
+static int
+add_detail_level(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo,
+ proto_tree *tree, int convert _U_, int hf_index)
+{
+ struct smb_info *smb_info = pinfo->private_data;
+ smb_transact_info_t *trp = smb_info->sip->extra_info;
+ guint16 level;
+
+ level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ trp->info_level = level; /* remember this for the response */
+ proto_tree_add_uint(tree, hf_index, tvb, offset, 2, level);
+ offset += 2;
+ return offset;
+}
+
+static int
+add_max_uses(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
+ proto_tree *tree, int convert _U_, int hf_index)
+{
+ guint16 WParam;
+
+ WParam = tvb_get_letohs(tvb, offset);
+ if (WParam == 0xffff) { /* -1 */
+ proto_tree_add_uint_format(tree, hf_index, tvb,
+ offset, 2, WParam,
+ "%s: No limit",
+ proto_registrar_get_name(hf_index));
+ } else {
+ proto_tree_add_uint(tree, hf_index, tvb,
+ offset, 2, WParam);
+ }
+ offset += 2;
+ return offset;
+}
+
+static int
+add_server_type(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo, proto_tree *tree, int convert _U_, int hf_index _U_)
+{
+ offset = dissect_smb_server_type_flags(
+ tvb, offset, pinfo, tree, NULL, FALSE);
+ return offset;
+}
+
+static int
+add_server_type_info(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo, proto_tree *tree, int convert _U_, int hf_index _U_)
+{
+ offset = dissect_smb_server_type_flags(
+ tvb, offset, pinfo, tree, NULL, TRUE);
+ return offset;
+}
+
+static int
+add_reltime(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
+ proto_tree *tree, int convert _U_, int hf_index)
+{
+ nstime_t nstime;
+
+ nstime.secs = tvb_get_letohl(tvb, offset);
+ nstime.nsecs = 0;
+ proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
+ &nstime, "%s: %s", proto_registrar_get_name(hf_index),
+ time_secs_to_str(nstime.secs));
+ offset += 4;
+ return offset;
+}
+
+/*
+ * Sigh. These are for handling Microsoft's annoying almost-UNIX-time-but-
+ * it's-local-time-not-UTC time.
+ */
+static int
+add_abstime_common(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_index,
+ const char *absent_name)
+{
+ nstime_t nstime;
+ struct tm *tmp;
+
+ nstime.secs = tvb_get_letohl(tvb, offset);
+ nstime.nsecs = 0;
+ /*
+ * Sigh. Sometimes it appears that -1 means "unknown", and
+ * sometimes it appears that 0 means "unknown", for the last
+ * logoff date/time.
+ */
+ if (nstime.secs == -1 || nstime.secs == 0) {
+ proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
+ &nstime, "%s: %s", proto_registrar_get_name(hf_index),
+ absent_name);
+ } else {
+ /*
+ * Run it through "gmtime()" to break it down, and then
+ * run it through "mktime()" to put it back together
+ * as UTC.
+ */
+ tmp = gmtime(&nstime.secs);
+ tmp->tm_isdst = -1; /* we don't know if it's DST or not */
+ nstime.secs = mktime(tmp);
+ proto_tree_add_time(tree, hf_index, tvb, offset, 4,
+ &nstime);
+ }
+ offset += 4;
+ return offset;
+}
+
+static int
+add_abstime_absent_never(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
+{
+ return add_abstime_common(tvb, offset, tree, hf_index, "Never");
+}
+
+static int
+add_abstime_absent_unknown(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
+{
+ return add_abstime_common(tvb, offset, tree, hf_index, "Unknown");
+}
+
+static int
+add_nlogons(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
+ proto_tree *tree, int convert _U_, int hf_index)
+{
+ guint16 nlogons;
+
+ nlogons = tvb_get_letohs(tvb, offset);
+ if (nlogons == 0xffff) /* -1 */
+ proto_tree_add_uint_format(tree, hf_index, tvb, offset, 2,
+ nlogons, "%s: Unknown",
+ proto_registrar_get_name(hf_index));
+ else
+ proto_tree_add_uint(tree, hf_index, tvb, offset, 2,
+ nlogons);
+ offset += 2;
+ return offset;
+}
+
+static int
+add_max_storage(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
+{
+ guint32 max_storage;
+
+ max_storage = tvb_get_letohl(tvb, offset);
+ if (max_storage == 0xffffffff)
+ proto_tree_add_uint_format(tree, hf_index, tvb, offset, 4,
+ max_storage, "%s: No limit",
+ proto_registrar_get_name(hf_index));
+ else
+ proto_tree_add_uint(tree, hf_index, tvb, offset, 4,
+ max_storage);
+ offset += 4;
+ return offset;
+}
+
+static int
+add_logon_hours(tvbuff_t *tvb, int offset, int count, packet_info *pinfo _U_,
+ proto_tree *tree, int convert, int hf_index)
+{
+ int cptr;
+
+ /* pointer to byte array */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ offset += 4;
+
+ /* bytes */
+ if (tvb_bytes_exist(tvb, cptr, count)) {
+ if (count == 21) {
+ /*
+ * The logon hours should be exactly 21 bytes long.
+ *
+ * XXX - should actually carve up the bits;
+ * we need the units per week to do that, though.
+ */
+ proto_tree_add_item(tree, hf_index, tvb, cptr, count,
+ TRUE);
+ } else {
+ proto_tree_add_bytes_format(tree, hf_index, tvb,
+ cptr, count, tvb_get_ptr(tvb, cptr, count),
+ "%s: %s (wrong length, should be 21, is %d",
+ proto_registrar_get_name(hf_index),
+ tvb_bytes_to_str(tvb, cptr, count), count);
+ }
+ } else {
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "%s: <Bytes go past end of frame>",
+ proto_registrar_get_name(hf_index));
+ }
+
+ return offset;
+}
+
+static int
+add_tzoffset(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
+ proto_tree *tree, int convert _U_, int hf_index)
+{
+ gint16 tzoffset;
+
+ tzoffset = tvb_get_letohs(tvb, offset);
+ if (tzoffset < 0) {
+ proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
+ tzoffset, "%s: %s east of UTC",
+ proto_registrar_get_name(hf_index),
+ time_secs_to_str(-tzoffset*60));
+ } else if (tzoffset > 0) {
+ proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
+ tzoffset, "%s: %s west of UTC",
+ proto_registrar_get_name(hf_index),
+ time_secs_to_str(tzoffset*60));
+ } else {
+ proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
+ tzoffset, "%s: at UTC",
+ proto_registrar_get_name(hf_index));
+ }
+ offset += 2;
+ return offset;
+}
+
+static int
+add_timeinterval(tvbuff_t *tvb, int offset, int count _U_,
+ packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
+{
+ guint16 timeinterval;
+
+ timeinterval = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_timeinterval, tvb, offset, 2,
+ timeinterval, "%s: %f seconds", proto_registrar_get_name(hf_index),
+ timeinterval*.0001);
+ offset += 2;
+ return offset;
+}
+
+static int
+add_logon_args(tvbuff_t *tvb, int offset, int count, packet_info *pinfo _U_,
+ proto_tree *tree, int convert _U_, int hf_index _U_)
+{
+ if (count != 54) {
+ proto_tree_add_text(tree, tvb, offset, count,
+ "Bogus NetWkstaUserLogon parameters: length is %d, should be 54",
+ count);
+ offset += count;
+ return offset;
+ }
+
+ /* user name */
+ proto_tree_add_item(tree, hf_user_name, tvb, offset, 21, TRUE);
+ offset += 21;
+
+ /* pad1 */
+ offset += 1;
+
+ /* password */
+ proto_tree_add_item(tree, hf_password, tvb, offset, 15, TRUE);
+ offset += 15;
+
+ /* pad2 */
+ offset += 1;
+
+ /* workstation name */
+ proto_tree_add_item(tree, hf_workstation_name, tvb, offset, 16, TRUE);
+ offset += 16;
+ return offset;
+}
+
+/*
+ * The following data structure describes the Remote API requests we
+ * understand.
+ *
+ * Simply fill in the number and parameter information.
+ * Try to keep them in order.
+ *
+ * We will extend this data structure as we try to decode more.
+ */
+
+/*
+ * This is a pointer to a function to process an item.
+ */
+typedef int (*item_func)(tvbuff_t *, int, int, packet_info *, proto_tree *,
+ int, int);
+
+/*
+ * Type of an item; determines what parameter strings are valid for
+ * the item.
+ */
+typedef enum {
+ PARAM_NONE, /* for the end-of-list stopper */
+ PARAM_WORD, /* 'W' or 'h' - 16-bit word */
+ PARAM_DWORD, /* 'D' or 'i' - 32-bit word */
+ PARAM_BYTES, /* 'B' or 'b' or 'g' or 'O' - one or more bytes */
+ PARAM_STRINGZ /* 'z' or 'O' - null-terminated string */
+} param_type_t;
+
+/*
+ * This structure describes an item; "hf_index" points to the index
+ * for the field corresponding to that item, "func" points to the
+ * function to use to add that item to the tree, and "type" is the
+ * type that the item is supposed to have.
+ */
+typedef struct {
+ int *hf_index;
+ item_func func;
+ param_type_t type;
+} item_t;
+
+/*
+ * This structure describes a list of items; each list of items
+ * has a corresponding detail level.
+ */
+typedef struct {
+ int level;
+ const item_t *item_list;
+} item_list_t;
+
+struct lanman_desc {
+ int lanman_num;
+ const item_t *req;
+ proto_item *(*req_data_item)(tvbuff_t *, packet_info *,
+ proto_tree *, int);
+ gint *ett_req_data;
+ const item_t *req_data;
+ const item_t *req_aux_data;
+ const item_t *resp;
+ const gchar *resp_data_entry_list_label;
+ gint *ett_data_entry_list;
+ proto_item *(*resp_data_element_item)(tvbuff_t *, proto_tree *,
+ int);
+ gint *ett_resp_data_element_item;
+ const item_list_t *resp_data_list;
+ const item_t *resp_aux_data;
+};
+
+static int no_hf = -1; /* for padding crap */
+
+static const item_t lm_params_req_netshareenum[] = {
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { &hf_recv_buf_len, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_params_resp_netshareenum[] = {
+ { &hf_acount, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+/*
+ * Create a subtree for a share.
+ */
+static proto_item *
+netshareenum_share_entry(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ if (tree) {
+ return proto_tree_add_text(tree, tvb, offset, -1,
+ "Share %.13s", tvb_get_ptr(tvb, offset, 13));
+ } else
+ return NULL;
+}
+
+static const item_t lm_null[] = {
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_null_list[] = {
+ { -1, lm_null }
+};
+
+static const item_t lm_data_resp_netshareenum_1[] = {
+ { &hf_share_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_share_type, add_word_param, PARAM_WORD },
+ { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_data_resp_netshareenum[] = {
+ { 1, lm_data_resp_netshareenum_1 },
+ { -1, lm_null }
+};
+
+static const item_t lm_params_req_netsharegetinfo[] = {
+ { &hf_share_name, add_string_param, PARAM_STRINGZ },
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_params_resp_netsharegetinfo[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_resp_netsharegetinfo_0[] = {
+ { &hf_share_name, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_resp_netsharegetinfo_1[] = {
+ { &hf_share_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_share_type, add_word_param, PARAM_WORD },
+ { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_resp_netsharegetinfo_2[] = {
+ { &hf_share_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_share_type, add_word_param, PARAM_WORD },
+ { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_share_permissions, add_word_param, PARAM_WORD }, /* XXX - do as bit fields */
+ { &hf_share_max_uses, add_max_uses, PARAM_WORD },
+ { &hf_share_current_uses, add_word_param, PARAM_WORD },
+ { &hf_share_path, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_share_password, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_data_resp_netsharegetinfo[] = {
+ { 0, lm_data_resp_netsharegetinfo_0 },
+ { 1, lm_data_resp_netsharegetinfo_1 },
+ { 2, lm_data_resp_netsharegetinfo_2 },
+ { -1, lm_null }
+};
+
+static const item_t lm_params_req_netservergetinfo[] = {
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_params_resp_netservergetinfo[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_serverinfo_0[] = {
+ { &hf_server_name, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_serverinfo_1[] = {
+ { &hf_server_name, add_byte_param, PARAM_BYTES },
+ { &hf_server_major, add_byte_param, PARAM_BYTES },
+ { &hf_server_minor, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_server_type, PARAM_DWORD },
+ { &hf_server_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_data_serverinfo[] = {
+ { 0, lm_data_serverinfo_0 },
+ { 1, lm_data_serverinfo_1 },
+ { -1, lm_null }
+};
+
+static const item_t lm_params_req_netusergetinfo[] = {
+ { &hf_user_name, add_string_param, PARAM_STRINGZ },
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_params_resp_netusergetinfo[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_resp_netusergetinfo_11[] = {
+ { &hf_user_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_user_comment, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_full_name, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_privilege_level, add_word_param, PARAM_WORD },
+ { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
+ { &hf_password_age, add_reltime, PARAM_DWORD },
+ { &hf_homedir, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_parameters, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_bad_pw_count, add_word_param, PARAM_WORD },
+ { &hf_num_logons, add_nlogons, PARAM_WORD },
+ { &hf_logon_server, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_country_code, add_word_param, PARAM_WORD },
+ { &hf_workstations, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_max_storage, add_max_storage, PARAM_DWORD },
+ { &hf_units_per_week, add_word_param, PARAM_WORD },
+ { &hf_logon_hours, add_logon_hours, PARAM_BYTES },
+ { &hf_code_page, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_data_resp_netusergetinfo[] = {
+ { 11, lm_data_resp_netusergetinfo_11 },
+ { -1, lm_null }
+};
+
+static const item_t lm_params_req_netusergetgroups[] = {
+ { &hf_user_name, add_string_param, PARAM_STRINGZ },
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_params_resp_netusergetgroups[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_resp_netusergetgroups_0[] = {
+ { &hf_group_name, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_data_resp_netusergetgroups[] = {
+ { 0, lm_data_resp_netusergetgroups_0 },
+ { -1, lm_null }
+};
+
+/*
+ * Has no detail level; make it the default.
+ */
+static const item_t lm_data_resp_netremotetod_nolevel[] = {
+ { &hf_current_time, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_msecs, add_dword_param, PARAM_DWORD },
+ { &hf_hour, add_byte_param, PARAM_BYTES },
+ { &hf_minute, add_byte_param, PARAM_BYTES },
+ { &hf_second, add_byte_param, PARAM_BYTES },
+ { &hf_hundredths, add_byte_param, PARAM_BYTES },
+ { &hf_tzoffset, add_tzoffset, PARAM_WORD },
+ { &hf_timeinterval, add_timeinterval, PARAM_WORD },
+ { &hf_day, add_byte_param, PARAM_BYTES },
+ { &hf_month, add_byte_param, PARAM_BYTES },
+ { &hf_year, add_word_param, PARAM_WORD },
+ { &hf_weekday, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_data_resp_netremotetod[] = {
+ { -1, lm_data_resp_netremotetod_nolevel },
+};
+
+static const item_t lm_params_req_netserverenum2[] = {
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { &no_hf, add_server_type_info, PARAM_DWORD },
+ { &hf_enumeration_domain, add_string_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
+
+/*
+ * Create a subtree for a server.
+ */
+static proto_item *
+netserverenum2_server_entry(tvbuff_t *tvb, proto_tree *tree, int offset)
+{
+ if (tree) {
+ return proto_tree_add_text(tree, tvb, offset, -1,
+ "Server %.16s", tvb_get_ptr(tvb, offset, 16));
+ } else
+ return NULL;
+}
+
+static const item_t lm_params_resp_netserverenum2[] = {
+ { &hf_acount, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+
+static const item_t lm_params_req_netserverenum3[] = {
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { &no_hf, add_server_type_info, PARAM_DWORD },
+ { &hf_enumeration_domain, add_string_param, PARAM_STRINGZ },
+ { &hf_last_entry, add_string_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
+
+
+static const item_t lm_params_req_netwkstagetinfo[] = {
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_params_resp_netwkstagetinfo[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_resp_netwkstagetinfo_10[] = {
+ { &hf_computer_name, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_user_name, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_workstation_domain, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_workstation_major, add_byte_param, PARAM_BYTES },
+ { &hf_workstation_minor, add_byte_param, PARAM_BYTES },
+ { &hf_logon_domain, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_other_domains, add_stringz_pointer_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_data_resp_netwkstagetinfo[] = {
+ { 10, lm_data_resp_netwkstagetinfo_10 },
+ { -1, lm_null }
+};
+
+static const item_t lm_params_req_netwkstauserlogon[] = {
+ { &no_hf, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &no_hf, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_detail_level, add_detail_level, PARAM_WORD },
+ { &no_hf, add_logon_args, PARAM_BYTES },
+ { &hf_ustruct_size, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_params_resp_netwkstauserlogon[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_resp_netwkstauserlogon_1[] = {
+ { &hf_logon_code, add_word_param, PARAM_WORD },
+ { &hf_user_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_privilege_level, add_word_param, PARAM_WORD },
+ { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
+ { &hf_num_logons, add_nlogons, PARAM_WORD },
+ { &hf_bad_pw_count, add_word_param, PARAM_WORD },
+ { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
+ { &hf_logoff_time, add_abstime_absent_never, PARAM_DWORD },
+ { &hf_kickoff_time, add_abstime_absent_never, PARAM_DWORD },
+ { &hf_password_age, add_reltime, PARAM_DWORD },
+ { &hf_password_can_change, add_abstime_absent_never, PARAM_DWORD },
+ { &hf_password_must_change, add_abstime_absent_never, PARAM_DWORD },
+ { &hf_server_name, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_logon_domain, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_script_path, add_stringz_pointer_param, PARAM_STRINGZ },
+ { &hf_reserved, add_dword_param, PARAM_DWORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_data_resp_netwkstauserlogon[] = {
+ { 1, lm_data_resp_netwkstauserlogon_1 },
+ { -1, lm_null }
+};
+
+static const item_t lm_params_req_netwkstauserlogoff[] = {
+ { &hf_user_name, add_byte_param, PARAM_BYTES },
+ { &no_hf, add_pad_param, PARAM_BYTES },
+ { &hf_workstation_name, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_params_resp_netwkstauserlogoff[] = {
+ { &hf_abytes, add_word_param, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_resp_netwkstauserlogoff_1[] = {
+ { &hf_logoff_code, add_word_param, PARAM_WORD },
+ { &hf_duration, add_reltime, PARAM_DWORD },
+ { &hf_num_logons, add_nlogons, PARAM_WORD },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_list_t lm_data_resp_netwkstauserlogoff[] = {
+ { 1, lm_data_resp_netwkstauserlogoff_1 },
+ { -1, lm_null }
+};
+
+static const item_t lm_params_req_samoemchangepassword[] = {
+ { &hf_user_name, add_string_param, PARAM_STRINGZ },
+ { NULL, NULL, PARAM_NONE }
+};
+
+static const item_t lm_data_req_samoemchangepassword[] = {
+ { &hf_new_password, add_byte_param, PARAM_BYTES },
+ { &hf_old_password, add_byte_param, PARAM_BYTES },
+ { NULL, NULL, PARAM_NONE }
+};
+
+#define API_NetShareEnum 0
+#define API_NetShareGetInfo 1
+#define API_NetShareSetInfo 2
+#define API_NetShareAdd 3
+#define API_NetShareDel 4
+#define API_NetShareCheck 5
+#define API_NetSessionEnum 6
+#define API_NetSessionGetInfo 7
+#define API_NetSessionDel 8
+#define API_WconnectionEnum 9
+#define API_NetFileEnum 10
+#define API_NetFileGetInfo 11
+#define API_NetFileClose 12
+#define API_NetServerGetInfo 13
+#define API_NetServerSetInfo 14
+#define API_NetServerDiskEnum 15
+#define API_NetServerAdminCommand 16
+#define API_NetAuditOpen 17
+#define API_NetAuditClear 18
+#define API_NetErrorLogOpen 19
+#define API_NetErrorLogClear 20
+#define API_NetCharDevEnum 21
+#define API_NetCharDevGetInfo 22
+#define API_NetCharDevControl 23
+#define API_NetCharDevQEnum 24
+#define API_NetCharDevQGetInfo 25
+#define API_NetCharDevQSetInfo 26
+#define API_NetCharDevQPurge 27
+#define API_NetCharDevQPurgeSelf 28
+#define API_NetMessageNameEnum 29
+#define API_NetMessageNameGetInfo 30
+#define API_NetMessageNameAdd 31
+#define API_NetMessageNameDel 32
+#define API_NetMessageNameFwd 33
+#define API_NetMessageNameUnFwd 34
+#define API_NetMessageBufferSend 35
+#define API_NetMessageFileSend 36
+#define API_NetMessageLogFileSet 37
+#define API_NetMessageLogFileGet 38
+#define API_NetServiceEnum 39
+#define API_NetServiceInstall 40
+#define API_NetServiceControl 41
+#define API_NetAccessEnum 42
+#define API_NetAccessGetInfo 43
+#define API_NetAccessSetInfo 44
+#define API_NetAccessAdd 45
+#define API_NetAccessDel 46
+#define API_NetGroupEnum 47
+#define API_NetGroupAdd 48
+#define API_NetGroupDel 49
+#define API_NetGroupAddUser 50
+#define API_NetGroupDelUser 51
+#define API_NetGroupGetUsers 52
+#define API_NetUserEnum 53
+#define API_NetUserAdd 54
+#define API_NetUserDel 55
+#define API_NetUserGetInfo 56
+#define API_NetUserSetInfo 57
+#define API_NetUserPasswordSet 58
+#define API_NetUserGetGroups 59
+/*This line and number replaced a Dead Entry for 60 */
+/*This line and number replaced a Dead Entry for 61 */
+#define API_NetWkstaSetUID 62
+#define API_NetWkstaGetInfo 63
+#define API_NetWkstaSetInfo 64
+#define API_NetUseEnum 65
+#define API_NetUseAdd 66
+#define API_NetUseDel 67
+#define API_NetUseGetInfo 68
+#define API_WPrintQEnum 69
+#define API_WPrintQGetInfo 70
+#define API_WPrintQSetInfo 71
+#define API_WPrintQAdd 72
+#define API_WPrintQDel 73
+#define API_WPrintQPause 74
+#define API_WPrintQContinue 75
+#define API_WPrintJobEnum 76
+#define API_WPrintJobGetInfo 77
+#define API_WPrintJobSetInfo_OLD 78
+/* This line and number replaced a Dead Entry for 79 */
+/* This line and number replaced a Dead Entry for 80 */
+#define API_WPrintJobDel 81
+#define API_WPrintJobPause 82
+#define API_WPrintJobContinue 83
+#define API_WPrintDestEnum 84
+#define API_WPrintDestGetInfo 85
+#define API_WPrintDestControl 86
+#define API_NetProfileSave 87
+#define API_NetProfileLoad 88
+#define API_NetStatisticsGet 89
+#define API_NetStatisticsClear 90
+#define API_NetRemoteTOD 91
+#define API_WNetBiosEnum 92
+#define API_WNetBiosGetInfo 93
+#define API_NetServerEnum 94
+#define API_I_NetServerEnum 95
+#define API_NetServiceGetInfo 96
+/* This line and number replaced a Dead Entry for 97 */
+/* This line and number replaced a Dead Entry for 98 */
+/* This line and number replaced a Dead Entry for 99 */
+/* This line and number replaced a Dead Entry for 100 */
+/* This line and number replaced a Dead Entry for 101 */
+/* This line and number replaced a Dead Entry for 102 */
+#define API_WPrintQPurge 103
+#define API_NetServerEnum2 104
+#define API_NetAccessGetUserPerms 105
+#define API_NetGroupGetInfo 106
+#define API_NetGroupSetInfo 107
+#define API_NetGroupSetUsers 108
+#define API_NetUserSetGroups 109
+#define API_NetUserModalsGet 110
+#define API_NetUserModalsSet 111
+#define API_NetFileEnum2 112
+#define API_NetUserAdd2 113
+#define API_NetUserSetInfo2 114
+#define API_NetUserPasswordSet2 115
+#define API_I_NetServerEnum2 116
+#define API_NetConfigGet2 117
+#define API_NetConfigGetAll2 118
+#define API_NetGetDCName 119
+#define API_NetHandleGetInfo 120
+#define API_NetHandleSetInfo 121
+#define API_NetStatisticsGet2 122
+#define API_WBuildGetInfo 123
+#define API_NetFileGetInfo2 124
+#define API_NetFileClose2 125
+#define API_NetServerReqChallenge 126
+#define API_NetServerAuthenticate 127
+#define API_NetServerPasswordSet 128
+#define API_WNetAccountDeltas 129
+#define API_WNetAccountSync 130
+#define API_NetUserEnum2 131
+#define API_NetWkstaUserLogon 132
+#define API_NetWkstaUserLogoff 133
+#define API_NetLogonEnum 134
+#define API_NetErrorLogRead 135
+#define API_I_NetPathType 136
+#define API_I_NetPathCanonicalize 137
+#define API_I_NetPathCompare 138
+#define API_I_NetNameValidate 139
+#define API_I_NetNameCanonicalize 140
+#define API_I_NetNameCompare 141
+#define API_NetAuditRead 142
+#define API_WPrintDestAdd 143
+#define API_WPrintDestSetInfo 144
+#define API_WPrintDestDel 145
+#define API_NetUserValidate2 146
+#define API_WPrintJobSetInfo 147
+#define API_TI_NetServerDiskEnum 148
+#define API_TI_NetServerDiskGetInfo 149
+#define API_TI_FTVerifyMirror 150
+#define API_TI_FTAbortVerify 151
+#define API_TI_FTGetInfo 152
+#define API_TI_FTSetInfo 153
+#define API_TI_FTLockDisk 154
+#define API_TI_FTFixError 155
+#define API_TI_FTAbortFix 156
+#define API_TI_FTDiagnoseError 157
+#define API_TI_FTGetDriveStats 158
+/* This line and number replaced a Dead Entry for 159 */
+#define API_TI_FTErrorGetInfo 160
+/* This line and number replaced a Dead Entry for 161 */
+/* This line and number replaced a Dead Entry for 162 */
+#define API_NetAccessCheck 163
+#define API_NetAlertRaise 164
+#define API_NetAlertStart 165
+#define API_NetAlertStop 166
+#define API_NetAuditWrite 167
+#define API_NetIRemoteAPI 168
+#define API_NetServiceStatus 169
+#define API_I_NetServerRegister 170
+#define API_I_NetServerDeregister 171
+#define API_I_NetSessionEntryMake 172
+#define API_I_NetSessionEntryClear 173
+#define API_I_NetSessionEntryGetInfo 174
+#define API_I_NetSessionEntrySetInfo 175
+#define API_I_NetConnectionEntryMake 176
+#define API_I_NetConnectionEntryClear 177
+#define API_I_NetConnectionEntrySetInfo 178
+#define API_I_NetConnectionEntryGetInfo 179
+#define API_I_NetFileEntryMake 180
+#define API_I_NetFileEntryClear 181
+#define API_I_NetFileEntrySetInfo 182
+#define API_I_NetFileEntryGetInfo 183
+#define API_AltSrvMessageBufferSend 184
+#define API_AltSrvMessageFileSend 185
+#define API_wI_NetRplWkstaEnum 186
+#define API_wI_NetRplWkstaGetInfo 187
+#define API_wI_NetRplWkstaSetInfo 188
+#define API_wI_NetRplWkstaAdd 189
+#define API_wI_NetRplWkstaDel 190
+#define API_wI_NetRplProfileEnum 191
+#define API_wI_NetRplProfileGetInfo 192
+#define API_wI_NetRplProfileSetInfo 193
+#define API_wI_NetRplProfileAdd 194
+#define API_wI_NetRplProfileDel 195
+#define API_wI_NetRplProfileClone 196
+#define API_wI_NetRplBaseProfileEnum 197
+/* This line and number replaced a Dead Entry for 198 */
+/* This line and number replaced a Dead Entry for 199 */
+/* This line and number replaced a Dead Entry for 200 */
+#define API_WIServerSetInfo 201
+/* This line and number replaced a Dead Entry for 202 */
+/* This line and number replaced a Dead Entry for 203 */
+/* This line and number replaced a Dead Entry for 204 */
+#define API_WPrintDriverEnum 205
+#define API_WPrintQProcessorEnum 206
+#define API_WPrintPortEnum 207
+#define API_WNetWriteUpdateLog 208
+#define API_WNetAccountUpdate 209
+#define API_WNetAccountConfirmUpdate 210
+#define API_NetConfigSet 211
+#define API_WAccountsReplicate 212
+/* 213 is used by WfW */
+#define API_SamOEMChgPasswordUser2_P 214
+#define API_NetServerEnum3 215
+/* XXX - what about 216 through 249? */
+#define API_WPrintDriverGetInfo 250
+#define API_WPrintDriverSetInfo 251
+#define API_NetAliasAdd 252
+#define API_NetAliasDel 253
+#define API_NetAliasGetInfo 254
+#define API_NetAliasSetInfo 255
+#define API_NetAliasEnum 256
+#define API_NetUserGetLogonAsn 257
+#define API_NetUserSetLogonAsn 258
+#define API_NetUserGetAppSel 259
+#define API_NetUserSetAppSel 260
+#define API_NetAppAdd 261
+#define API_NetAppDel 262
+#define API_NetAppGetInfo 263
+#define API_NetAppSetInfo 264
+#define API_NetAppEnum 265
+#define API_NetUserDCDBInit 266
+#define API_NetDASDAdd 267
+#define API_NetDASDDel 268
+#define API_NetDASDGetInfo 269
+#define API_NetDASDSetInfo 270
+#define API_NetDASDEnum 271
+#define API_NetDASDCheck 272
+#define API_NetDASDCtl 273
+#define API_NetUserRemoteLogonCheck 274
+#define API_NetUserPasswordSet3 275
+#define API_NetCreateRIPLMachine 276
+#define API_NetDeleteRIPLMachine 277
+#define API_NetGetRIPLMachineInfo 278
+#define API_NetSetRIPLMachineInfo 279
+#define API_NetEnumRIPLMachine 280
+#define API_I_ShareAdd 281
+#define API_I_AliasEnum 282
+#define API_NetAccessApply 283
+#define API_WPrt16Query 284
+#define API_WPrt16Set 285
+#define API_NetUserDel100 286
+#define API_NetUserRemoteLogonCheck2 287
+#define API_WRemoteTODSet 294
+#define API_WPrintJobMoveAll 295
+#define API_W16AppParmAdd 296
+#define API_W16AppParmDel 297
+#define API_W16AppParmGet 298
+#define API_W16AppParmSet 299
+#define API_W16RIPLMachineCreate 300
+#define API_W16RIPLMachineGetInfo 301
+#define API_W16RIPLMachineSetInfo 302
+#define API_W16RIPLMachineEnum 303
+#define API_W16RIPLMachineListParmEnum 304
+#define API_W16RIPLMachClassGetInfo 305
+#define API_W16RIPLMachClassEnum 306
+#define API_W16RIPLMachClassCreate 307
+#define API_W16RIPLMachClassSetInfo 308
+#define API_W16RIPLMachClassDelete 309
+#define API_W16RIPLMachClassLPEnum 310
+#define API_W16RIPLMachineDelete 311
+#define API_W16WSLevelGetInfo 312
+#define API_NetServerNameAdd 313
+#define API_NetServerNameDel 314
+#define API_NetServerNameEnum 315
+#define API_I_WDASDEnum 316
+#define API_I_WDASDEnumTerminate 317
+#define API_I_WDASDSetInfo2 318
+
+static const struct lanman_desc lmd[] = {
+ { API_NetShareEnum,
+ lm_params_req_netshareenum,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netshareenum,
+ "Available Shares",
+ &ett_lanman_shares,
+ netshareenum_share_entry,
+ &ett_lanman_share,
+ lm_data_resp_netshareenum,
+ lm_null },
+
+ { API_NetShareGetInfo,
+ lm_params_req_netsharegetinfo,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netsharegetinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netsharegetinfo,
+ lm_null },
+
+ { API_NetServerGetInfo,
+ lm_params_req_netservergetinfo,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netservergetinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_serverinfo,
+ lm_null },
+
+ { API_NetUserGetInfo,
+ lm_params_req_netusergetinfo,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netusergetinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netusergetinfo,
+ lm_null },
+
+ { API_NetUserGetGroups,
+ lm_params_req_netusergetgroups,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netusergetgroups,
+ "Groups",
+ &ett_lanman_groups,
+ NULL,
+ NULL,
+ lm_data_resp_netusergetgroups,
+ lm_null },
+
+ { API_NetRemoteTOD,
+ lm_null,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_null,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netremotetod,
+ lm_null },
+
+ { API_NetServerEnum2,
+ lm_params_req_netserverenum2,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netserverenum2,
+ "Servers",
+ &ett_lanman_servers,
+ netserverenum2_server_entry,
+ &ett_lanman_server,
+ lm_data_serverinfo,
+ lm_null },
+
+ { API_NetWkstaGetInfo,
+ lm_params_req_netwkstagetinfo,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netwkstagetinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netwkstagetinfo,
+ lm_null },
+
+ { API_NetWkstaUserLogon,
+ lm_params_req_netwkstauserlogon,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netwkstauserlogon,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netwkstauserlogon,
+ lm_null },
+
+ { API_NetWkstaUserLogoff,
+ lm_params_req_netwkstauserlogoff,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netwkstauserlogoff,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_data_resp_netwkstauserlogoff,
+ lm_null },
+
+ { API_SamOEMChgPasswordUser2_P,
+ lm_params_req_samoemchangepassword,
+ NULL,
+ NULL,
+ lm_data_req_samoemchangepassword,
+ lm_null,
+ lm_null,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ lm_null_list,
+ lm_null },
+
+ { API_NetServerEnum3,
+ lm_params_req_netserverenum3,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_params_resp_netserverenum2,
+ "Servers",
+ &ett_lanman_servers,
+ netserverenum2_server_entry,
+ &ett_lanman_server,
+ lm_data_serverinfo,
+ lm_null },
+
+ { -1,
+ lm_null,
+ NULL,
+ NULL,
+ lm_null,
+ lm_null,
+ lm_null,
+ NULL,
+ NULL,
+ NULL,
+ &ett_lanman_unknown_entry,
+ lm_null_list,
+ lm_null }
+};
+
+static const struct lanman_desc *
+find_lanman(int lanman_num)
+{
+ int i;
+
+ for (i = 0; lmd[i].lanman_num != -1; i++) {
+ if (lmd[i].lanman_num == lanman_num)
+ break;
+ }
+ return &lmd[i];
+}
+
+static const guchar *
+get_count(const guchar *desc, int *countp)
+{
+ int count = 0;
+ guchar c;
+
+ if (!isdigit(*desc)) {
+ *countp = 1; /* no count was supplied */
+ return desc;
+ }
+
+ while ((c = *desc) != '\0' && isdigit(c)) {
+ count = (count * 10) + c - '0';
+ desc++;
+ }
+
+ *countp = count; /* XXX - what if it's 0? */
+ return desc;
+}
+
+static int
+dissect_request_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const guchar *desc, const item_t *items,
+ gboolean *has_data_p)
+{
+ guint c;
+ guint16 WParam;
+ guint32 LParam;
+ guint string_len;
+ int count;
+
+ *has_data_p = FALSE;
+ while ((c = *desc++) != '\0') {
+ switch (c) {
+
+ case 'W':
+ /*
+ * A 16-bit word value in the request.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_word_param(tvb, offset, 0, pinfo,
+ tree, 0, -1);
+ } else if (items->type != PARAM_WORD) {
+ /*
+ * Descriptor character is 'W', but this
+ * isn't a word parameter.
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%04X), type is wrong (W)",
+ (*items->hf_index == -1) ?
+ "Word Param" :
+ proto_registrar_get_name(*items->hf_index),
+ WParam, WParam);
+ offset += 2;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'D':
+ /*
+ * A 32-bit doubleword value in the request.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_dword_param(tvb, offset, 0, pinfo,
+ tree, 0, -1);
+ } else if (items->type != PARAM_DWORD) {
+ /*
+ * Descriptor character is 'D', but this
+ * isn't a doubleword parameter.
+ */
+ LParam = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%08X), type is wrong (D)",
+ (*items->hf_index == -1) ?
+ "Doubleword Param" :
+ proto_registrar_get_name(*items->hf_index),
+ LParam, LParam);
+ offset += 4;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'b':
+ /*
+ * A byte or multi-byte value in the request.
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_byte_param(tvb, offset, count,
+ pinfo, tree, 0, -1);
+ } else if (items->type != PARAM_BYTES) {
+ /*
+ * Descriptor character is 'b', but this
+ * isn't a byte/bytes parameter.
+ */
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s: Value is %s, type is wrong (b)",
+ (*items->hf_index == -1) ?
+ "Byte Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_bytes_to_str(tvb, offset, count));
+ offset += count;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, count,
+ pinfo, tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'O':
+ /*
+ * A null pointer.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ add_null_pointer_param(tvb, offset, 0,
+ pinfo, tree, 0, -1);
+ } else {
+ /*
+ * If "*items->hf_index" is -1, this is
+ * a reserved must-be-null field; don't
+ * clutter the protocol tree by putting
+ * it in.
+ */
+ if (*items->hf_index != -1) {
+ add_null_pointer_param(tvb,
+ offset, 0, pinfo, tree, 0,
+ *items->hf_index);
+ }
+ items++;
+ }
+ break;
+
+ case 'z':
+ /*
+ * A null-terminated ASCII string.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_string_param(tvb, offset, 0,
+ pinfo, tree, 0, -1);
+ } else if (items->type != PARAM_STRINGZ) {
+ /*
+ * Descriptor character is 'z', but this
+ * isn't a string parameter.
+ */
+ string_len = tvb_strsize(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, string_len,
+ "%s: Value is %s, type is wrong (z)",
+ (*items->hf_index == -1) ?
+ "String Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_format_text(tvb, offset, string_len));
+ offset += string_len;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0,
+ pinfo, tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'F':
+ /*
+ * One or more pad bytes.
+ */
+ desc = get_count(desc, &count);
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s", "Padding");
+ offset += count;
+ break;
+
+ case 'L':
+ /*
+ * 16-bit receive buffer length.
+ */
+ proto_tree_add_item(tree, hf_recv_buf_len, tvb,
+ offset, 2, TRUE);
+ offset += 2;
+ break;
+
+ case 's':
+ /*
+ * 32-bit send buffer offset.
+ * This appears not to be sent over the wire.
+ */
+ *has_data_p = TRUE;
+ break;
+
+ case 'T':
+ /*
+ * 16-bit send buffer length.
+ */
+ proto_tree_add_item(tree, hf_send_buf_len, tvb,
+ offset, 2, TRUE);
+ offset += 2;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return offset;
+}
+
+static int
+dissect_response_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const guchar *desc, const item_t *items,
+ gboolean *has_data_p, gboolean *has_ent_count_p, guint16 *ent_count_p)
+{
+ guint c;
+ guint16 WParam;
+ guint32 LParam;
+ int count;
+
+ *has_data_p = FALSE;
+ *has_ent_count_p = FALSE;
+ while ((c = *desc++) != '\0') {
+ switch (c) {
+
+ case 'r':
+ /*
+ * 32-bit receive buffer offset.
+ */
+ *has_data_p = TRUE;
+ break;
+
+ case 'g':
+ /*
+ * A byte or series of bytes is returned.
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_byte_param(tvb, offset, count,
+ pinfo, tree, 0, -1);
+ } else if (items->type != PARAM_BYTES) {
+ /*
+ * Descriptor character is 'b', but this
+ * isn't a byte/bytes parameter.
+ */
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s: Value is %s, type is wrong (g)",
+ (*items->hf_index == -1) ?
+ "Byte Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_bytes_to_str(tvb, offset, count));
+ offset += count;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, count,
+ pinfo, tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'h':
+ /*
+ * A 16-bit word is received.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_word_param(tvb, offset, 0, pinfo,
+ tree, 0, -1);
+ } else if (items->type != PARAM_WORD) {
+ /*
+ * Descriptor character is 'h', but this
+ * isn't a word parameter.
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%04X), type is wrong (W)",
+ (*items->hf_index == -1) ?
+ "Word Param" :
+ proto_registrar_get_name(*items->hf_index),
+ WParam, WParam);
+ offset += 2;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'i':
+ /*
+ * A 32-bit doubleword is received.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_dword_param(tvb, offset, 0, pinfo,
+ tree, 0, -1);
+ } else if (items->type != PARAM_DWORD) {
+ /*
+ * Descriptor character is 'i', but this
+ * isn't a doubleword parameter.
+ */
+ LParam = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%08X), type is wrong (i)",
+ (*items->hf_index == -1) ?
+ "Doubleword Param" :
+ proto_registrar_get_name(*items->hf_index),
+ LParam, LParam);
+ offset += 4;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, 0, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'e':
+ /*
+ * A 16-bit entry count is returned.
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ecount, tvb, offset, 2,
+ WParam);
+ offset += 2;
+ *has_ent_count_p = TRUE;
+ *ent_count_p = WParam; /* Save this for later retrieval */
+ break;
+
+ default:
+ break;
+ }
+ }
+ return offset;
+}
+
+static int
+dissect_transact_data(tvbuff_t *tvb, int offset, int convert,
+ packet_info *pinfo, proto_tree *tree, const guchar *desc,
+ const item_t *items, guint16 *aux_count_p)
+{
+ guint c;
+ guint16 WParam;
+ guint32 LParam;
+ int count;
+ int cptr;
+ const char *string;
+ gint string_len;
+
+ if (aux_count_p != NULL)
+ *aux_count_p = 0;
+
+ while ((c = *desc++) != '\0') {
+ switch (c) {
+
+ case 'W':
+ /*
+ * A 16-bit word value.
+ * XXX - handle the count?
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_word_param(tvb, offset, 0, pinfo,
+ tree, convert, -1);
+ } else if (items->type != PARAM_WORD) {
+ /*
+ * Descriptor character is 'W', but this
+ * isn't a word parameter.
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%04X), type is wrong (W)",
+ (*items->hf_index == -1) ?
+ "Word Param" :
+ proto_registrar_get_name(*items->hf_index),
+ WParam, WParam);
+ offset += 2;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'D':
+ /*
+ * A 32-bit doubleword value.
+ * XXX - handle the count?
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_dword_param(tvb, offset, 0, pinfo,
+ tree, convert, -1);
+ } else if (items->type != PARAM_DWORD) {
+ /*
+ * Descriptor character is 'D', but this
+ * isn't a doubleword parameter.
+ */
+ LParam = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: Value is %u (0x%08X), type is wrong (D)",
+ (*items->hf_index == -1) ?
+ "Doubleword Param" :
+ proto_registrar_get_name(*items->hf_index),
+ LParam, LParam);
+ offset += 4;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0, pinfo,
+ tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'B':
+ /*
+ * A byte or multi-byte value.
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_byte_param(tvb, offset, count,
+ pinfo, tree, convert, -1);
+ } else if (items->type != PARAM_BYTES) {
+ /*
+ * Descriptor character is 'B', but this
+ * isn't a byte/bytes parameter.
+ */
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s: Value is %s, type is wrong (B)",
+ (*items->hf_index == -1) ?
+ "Byte Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_bytes_to_str(tvb, offset, count));
+ offset += count;
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, count,
+ pinfo, tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'O':
+ /*
+ * A null pointer.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ add_null_pointer_param(tvb, offset, 0,
+ pinfo, tree, convert, -1);
+ } else {
+ /*
+ * If "*items->hf_index" is -1, this is
+ * a reserved must-be-null field; don't
+ * clutter the protocol tree by putting
+ * it in.
+ */
+ if (*items->hf_index != -1) {
+ add_null_pointer_param(tvb,
+ offset, 0, pinfo, tree, convert,
+ *items->hf_index);
+ }
+ items++;
+ }
+ break;
+
+ case 'z':
+ /*
+ * A pointer to a null-terminated ASCII string.
+ */
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_stringz_pointer_param(tvb, offset,
+ 0, pinfo, tree, convert, -1);
+ } else if (items->type != PARAM_STRINGZ) {
+ /*
+ * Descriptor character is 'z', but this
+ * isn't a string parameter.
+ */
+ string = get_stringz_pointer_value(tvb, offset,
+ convert, &cptr, &string_len);
+ offset += 4;
+ proto_tree_add_text(tree, tvb, cptr, string_len,
+ "%s: Value is %s, type is wrong (z)",
+ (*items->hf_index == -1) ?
+ "String Param" :
+ proto_registrar_get_name(*items->hf_index),
+ string);
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, 0,
+ pinfo, tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'b':
+ /*
+ * A pointer to a byte or multi-byte value.
+ */
+ desc = get_count(desc, &count);
+ if (items->func == NULL) {
+ /*
+ * We've run out of items in the table;
+ * fall back on the default.
+ */
+ offset = add_bytes_pointer_param(tvb, offset,
+ count, pinfo, tree, convert, -1);
+ } else if (items->type != PARAM_BYTES) {
+ /*
+ * Descriptor character is 'b', but this
+ * isn't a byte/bytes parameter.
+ */
+ cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
+ offset += 4;
+ proto_tree_add_text(tree, tvb, offset, count,
+ "%s: Value is %s, type is wrong (b)",
+ (*items->hf_index == -1) ?
+ "Byte Param" :
+ proto_registrar_get_name(*items->hf_index),
+ tvb_bytes_to_str(tvb, cptr, count));
+ items++;
+ } else {
+ offset = (*items->func)(tvb, offset, count,
+ pinfo, tree, convert, *items->hf_index);
+ items++;
+ }
+ break;
+
+ case 'N':
+ /*
+ * 16-bit auxiliary data structure count.
+ * XXX - hf_acount?
+ */
+ WParam = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "%s: %u (0x%04X)",
+ "Auxiliary data structure count",
+ WParam, WParam);
+ offset += 2;
+ if (aux_count_p != NULL)
+ *aux_count_p = WParam; /* Save this for later retrieval */
+ break;
+
+ default:
+ break;
+ }
+ }
+ return offset;
+}
+
+static const value_string commands[] = {
+ {API_NetShareEnum, "NetShareEnum"},
+ {API_NetShareGetInfo, "NetShareGetInfo"},
+ {API_NetShareSetInfo, "NetShareSetInfo"},
+ {API_NetShareAdd, "NetShareAdd"},
+ {API_NetShareDel, "NetShareDel"},
+ {API_NetShareCheck, "NetShareCheck"},
+ {API_NetSessionEnum, "NetSessionEnum"},
+ {API_NetSessionGetInfo, "NetSessionGetInfo"},
+ {API_NetSessionDel, "NetSessionDel"},
+ {API_WconnectionEnum, "NetConnectionEnum"},
+ {API_NetFileEnum, "NetFileEnum"},
+ {API_NetFileGetInfo, "NetFileGetInfo"},
+ {API_NetFileClose, "NetFileClose"},
+ {API_NetServerGetInfo, "NetServerGetInfo"},
+ {API_NetServerSetInfo, "NetServerSetInfo"},
+ {API_NetServerDiskEnum, "NetServerDiskEnum"},
+ {API_NetServerAdminCommand, "NetServerAdminCommand"},
+ {API_NetAuditOpen, "NetAuditOpen"},
+ {API_NetAuditClear, "NetAuditClear"},
+ {API_NetErrorLogOpen, "NetErrorLogOpen"},
+ {API_NetErrorLogClear, "NetErrorLogClear"},
+ {API_NetCharDevEnum, "NetCharDevEnum"},
+ {API_NetCharDevGetInfo, "NetCharDevGetInfo"},
+ {API_NetCharDevControl, "NetCharDevControl"},
+ {API_NetCharDevQEnum, "NetCharDevQEnum"},
+ {API_NetCharDevQGetInfo, "NetCharDevQGetInfo"},
+ {API_NetCharDevQSetInfo, "NetCharDevQSetInfo"},
+ {API_NetCharDevQPurge, "NetCharDevQPurge"},
+ {API_NetCharDevQPurgeSelf, "NetCharDevQPurgeSelf"},
+ {API_NetMessageNameEnum, "NetMessageNameEnum"},
+ {API_NetMessageNameGetInfo, "NetMessageNameGetInfo"},
+ {API_NetMessageNameAdd, "NetMessageNameAdd"},
+ {API_NetMessageNameDel, "NetMessageNameDel"},
+ {API_NetMessageNameFwd, "NetMessageNameFwd"},
+ {API_NetMessageNameUnFwd, "NetMessageNameUnFwd"},
+ {API_NetMessageBufferSend, "NetMessageBufferSend"},
+ {API_NetMessageFileSend, "NetMessageFileSend"},
+ {API_NetMessageLogFileSet, "NetMessageLogFileSet"},
+ {API_NetMessageLogFileGet, "NetMessageLogFileGet"},
+ {API_NetServiceEnum, "NetServiceEnum"},
+ {API_NetServiceInstall, "NetServiceInstall"},
+ {API_NetServiceControl, "NetServiceControl"},
+ {API_NetAccessEnum, "NetAccessEnum"},
+ {API_NetAccessGetInfo, "NetAccessGetInfo"},
+ {API_NetAccessSetInfo, "NetAccessSetInfo"},
+ {API_NetAccessAdd, "NetAccessAdd"},
+ {API_NetAccessDel, "NetAccessDel"},
+ {API_NetGroupEnum, "NetGroupEnum"},
+ {API_NetGroupAdd, "NetGroupAdd"},
+ {API_NetGroupDel, "NetGroupDel"},
+ {API_NetGroupAddUser, "NetGroupAddUser"},
+ {API_NetGroupDelUser, "NetGroupDelUser"},
+ {API_NetGroupGetUsers, "NetGroupGetUsers"},
+ {API_NetUserEnum, "NetUserEnum"},
+ {API_NetUserAdd, "NetUserAdd"},
+ {API_NetUserDel, "NetUserDel"},
+ {API_NetUserGetInfo, "NetUserGetInfo"},
+ {API_NetUserSetInfo, "NetUserSetInfo"},
+ {API_NetUserPasswordSet, "NetUserPasswordSet"},
+ {API_NetUserGetGroups, "NetUserGetGroups"},
+ {API_NetWkstaSetUID, "NetWkstaSetUID"},
+ {API_NetWkstaGetInfo, "NetWkstaGetInfo"},
+ {API_NetWkstaSetInfo, "NetWkstaSetInfo"},
+ {API_NetUseEnum, "NetUseEnum"},
+ {API_NetUseAdd, "NetUseAdd"},
+ {API_NetUseDel, "NetUseDel"},
+ {API_NetUseGetInfo, "NetUseGetInfo"},
+ {API_WPrintQEnum, "WPrintQEnum"},
+ {API_WPrintQGetInfo, "WPrintQGetInfo"},
+ {API_WPrintQSetInfo, "WPrintQSetInfo"},
+ {API_WPrintQAdd, "WPrintQAdd"},
+ {API_WPrintQDel, "WPrintQDel"},
+ {API_WPrintQPause, "WPrintQPause"},
+ {API_WPrintQContinue, "WPrintQContinue"},
+ {API_WPrintJobEnum, "WPrintJobEnum"},
+ {API_WPrintJobGetInfo, "WPrintJobGetInfo"},
+ {API_WPrintJobSetInfo_OLD, "WPrintJobSetInfo_OLD"},
+ {API_WPrintJobDel, "WPrintJobDel"},
+ {API_WPrintJobPause, "WPrintJobPause"},
+ {API_WPrintJobContinue, "WPrintJobContinue"},
+ {API_WPrintDestEnum, "WPrintDestEnum"},
+ {API_WPrintDestGetInfo, "WPrintDestGetInfo"},
+ {API_WPrintDestControl, "WPrintDestControl"},
+ {API_NetProfileSave, "NetProfileSave"},
+ {API_NetProfileLoad, "NetProfileLoad"},
+ {API_NetStatisticsGet, "NetStatisticsGet"},
+ {API_NetStatisticsClear, "NetStatisticsClear"},
+ {API_NetRemoteTOD, "NetRemoteTOD"},
+ {API_WNetBiosEnum, "WNetBiosEnum"},
+ {API_WNetBiosGetInfo, "WNetBiosGetInfo"},
+ {API_NetServerEnum, "NetServerEnum"},
+ {API_I_NetServerEnum, "I_NetServerEnum"},
+ {API_NetServiceGetInfo, "NetServiceGetInfo"},
+ {API_WPrintQPurge, "WPrintQPurge"},
+ {API_NetServerEnum2, "NetServerEnum2"},
+ {API_NetAccessGetUserPerms, "NetAccessGetUserPerms"},
+ {API_NetGroupGetInfo, "NetGroupGetInfo"},
+ {API_NetGroupSetInfo, "NetGroupSetInfo"},
+ {API_NetGroupSetUsers, "NetGroupSetUsers"},
+ {API_NetUserSetGroups, "NetUserSetGroups"},
+ {API_NetUserModalsGet, "NetUserModalsGet"},
+ {API_NetUserModalsSet, "NetUserModalsSet"},
+ {API_NetFileEnum2, "NetFileEnum2"},
+ {API_NetUserAdd2, "NetUserAdd2"},
+ {API_NetUserSetInfo2, "NetUserSetInfo2"},
+ {API_NetUserPasswordSet2, "SetUserPassword"},
+ {API_I_NetServerEnum2, "I_NetServerEnum2"},
+ {API_NetConfigGet2, "NetConfigGet2"},
+ {API_NetConfigGetAll2, "NetConfigGetAll2"},
+ {API_NetGetDCName, "NetGetDCName"},
+ {API_NetHandleGetInfo, "NetHandleGetInfo"},
+ {API_NetHandleSetInfo, "NetHandleSetInfo"},
+ {API_NetStatisticsGet2, "NetStatisticsGet2"},
+ {API_WBuildGetInfo, "WBuildGetInfo"},
+ {API_NetFileGetInfo2, "NetFileGetInfo2"},
+ {API_NetFileClose2, "NetFileClose2"},
+ {API_NetServerReqChallenge, "NetServerReqChallenge"},
+ {API_NetServerAuthenticate, "NetServerAuthenticate"},
+ {API_NetServerPasswordSet, "NetServerPasswordSet"},
+ {API_WNetAccountDeltas, "WNetAccountDeltas"},
+ {API_WNetAccountSync, "WNetAccountSync"},
+ {API_NetUserEnum2, "NetUserEnum2"},
+ {API_NetWkstaUserLogon, "NetWkstaUserLogon"},
+ {API_NetWkstaUserLogoff, "NetWkstaUserLogoff"},
+ {API_NetLogonEnum, "NetLogonEnum"},
+ {API_NetErrorLogRead, "NetErrorLogRead"},
+ {API_I_NetPathType, "I_NetPathType"},
+ {API_I_NetPathCanonicalize, "I_NetPathCanonicalize"},
+ {API_I_NetPathCompare, "I_NetPathCompare"},
+ {API_I_NetNameValidate, "I_NetNameValidate"},
+ {API_I_NetNameCanonicalize, "I_NetNameCanonicalize"},
+ {API_I_NetNameCompare, "I_NetNameCompare"},
+ {API_NetAuditRead, "NetAuditRead"},
+ {API_WPrintDestAdd, "WPrintDestAdd"},
+ {API_WPrintDestSetInfo, "WPrintDestSetInfo"},
+ {API_WPrintDestDel, "WPrintDestDel"},
+ {API_NetUserValidate2, "NetUserValidate2"},
+ {API_WPrintJobSetInfo, "WPrintJobSetInfo"},
+ {API_TI_NetServerDiskEnum, "TI_NetServerDiskEnum"},
+ {API_TI_NetServerDiskGetInfo, "TI_NetServerDiskGetInfo"},
+ {API_TI_FTVerifyMirror, "TI_FTVerifyMirror"},
+ {API_TI_FTAbortVerify, "TI_FTAbortVerify"},
+ {API_TI_FTGetInfo, "TI_FTGetInfo"},
+ {API_TI_FTSetInfo, "TI_FTSetInfo"},
+ {API_TI_FTLockDisk, "TI_FTLockDisk"},
+ {API_TI_FTFixError, "TI_FTFixError"},
+ {API_TI_FTAbortFix, "TI_FTAbortFix"},
+ {API_TI_FTDiagnoseError, "TI_FTDiagnoseError"},
+ {API_TI_FTGetDriveStats, "TI_FTGetDriveStats"},
+ {API_TI_FTErrorGetInfo, "TI_FTErrorGetInfo"},
+ {API_NetAccessCheck, "NetAccessCheck"},
+ {API_NetAlertRaise, "NetAlertRaise"},
+ {API_NetAlertStart, "NetAlertStart"},
+ {API_NetAlertStop, "NetAlertStop"},
+ {API_NetAuditWrite, "NetAuditWrite"},
+ {API_NetIRemoteAPI, "NetIRemoteAPI"},
+ {API_NetServiceStatus, "NetServiceStatus"},
+ {API_I_NetServerRegister, "I_NetServerRegister"},
+ {API_I_NetServerDeregister, "I_NetServerDeregister"},
+ {API_I_NetSessionEntryMake, "I_NetSessionEntryMake"},
+ {API_I_NetSessionEntryClear, "I_NetSessionEntryClear"},
+ {API_I_NetSessionEntryGetInfo, "I_NetSessionEntryGetInfo"},
+ {API_I_NetSessionEntrySetInfo, "I_NetSessionEntrySetInfo"},
+ {API_I_NetConnectionEntryMake, "I_NetConnectionEntryMake"},
+ {API_I_NetConnectionEntryClear, "I_NetConnectionEntryClear"},
+ {API_I_NetConnectionEntrySetInfo, "I_NetConnectionEntrySetInfo"},
+ {API_I_NetConnectionEntryGetInfo, "I_NetConnectionEntryGetInfo"},
+ {API_I_NetFileEntryMake, "I_NetFileEntryMake"},
+ {API_I_NetFileEntryClear, "I_NetFileEntryClear"},
+ {API_I_NetFileEntrySetInfo, "I_NetFileEntrySetInfo"},
+ {API_I_NetFileEntryGetInfo, "I_NetFileEntryGetInfo"},
+ {API_AltSrvMessageBufferSend, "AltSrvMessageBufferSend"},
+ {API_AltSrvMessageFileSend, "AltSrvMessageFileSend"},
+ {API_wI_NetRplWkstaEnum, "wI_NetRplWkstaEnum"},
+ {API_wI_NetRplWkstaGetInfo, "wI_NetRplWkstaGetInfo"},
+ {API_wI_NetRplWkstaSetInfo, "wI_NetRplWkstaSetInfo"},
+ {API_wI_NetRplWkstaAdd, "wI_NetRplWkstaAdd"},
+ {API_wI_NetRplWkstaDel, "wI_NetRplWkstaDel"},
+ {API_wI_NetRplProfileEnum, "wI_NetRplProfileEnum"},
+ {API_wI_NetRplProfileGetInfo, "wI_NetRplProfileGetInfo"},
+ {API_wI_NetRplProfileSetInfo, "wI_NetRplProfileSetInfo"},
+ {API_wI_NetRplProfileAdd, "wI_NetRplProfileAdd"},
+ {API_wI_NetRplProfileDel, "wI_NetRplProfileDel"},
+ {API_wI_NetRplProfileClone, "wI_NetRplProfileClone"},
+ {API_wI_NetRplBaseProfileEnum, "wI_NetRplBaseProfileEnum"},
+ {API_WIServerSetInfo, "WIServerSetInfo"},
+ {API_WPrintDriverEnum, "WPrintDriverEnum"},
+ {API_WPrintQProcessorEnum, "WPrintQProcessorEnum"},
+ {API_WPrintPortEnum, "WPrintPortEnum"},
+ {API_WNetWriteUpdateLog, "WNetWriteUpdateLog"},
+ {API_WNetAccountUpdate, "WNetAccountUpdate"},
+ {API_WNetAccountConfirmUpdate, "WNetAccountConfirmUpdate"},
+ {API_NetConfigSet, "NetConfigSet"},
+ {API_WAccountsReplicate, "WAccountsReplicate"},
+ {API_SamOEMChgPasswordUser2_P, "SamOEMChangePassword"},
+ {API_NetServerEnum3, "NetServerEnum3"},
+ {API_WPrintDriverGetInfo, "WPrintDriverGetInfo"},
+ {API_WPrintDriverSetInfo, "WPrintDriverSetInfo"},
+ {API_NetAliasAdd, "NetAliasAdd"},
+ {API_NetAliasDel, "NetAliasDel"},
+ {API_NetAliasGetInfo, "NetAliasGetInfo"},
+ {API_NetAliasSetInfo, "NetAliasSetInfo"},
+ {API_NetAliasEnum, "NetAliasEnum"},
+ {API_NetUserGetLogonAsn, "NetUserGetLogonAsn"},
+ {API_NetUserSetLogonAsn, "NetUserSetLogonAsn"},
+ {API_NetUserGetAppSel, "NetUserGetAppSel"},
+ {API_NetUserSetAppSel, "NetUserSetAppSel"},
+ {API_NetAppAdd, "NetAppAdd"},
+ {API_NetAppDel, "NetAppDel"},
+ {API_NetAppGetInfo, "NetAppGetInfo"},
+ {API_NetAppSetInfo, "NetAppSetInfo"},
+ {API_NetAppEnum, "NetAppEnum"},
+ {API_NetUserDCDBInit, "NetUserDCDBInit"},
+ {API_NetDASDAdd, "NetDASDAdd"},
+ {API_NetDASDDel, "NetDASDDel"},
+ {API_NetDASDGetInfo, "NetDASDGetInfo"},
+ {API_NetDASDSetInfo, "NetDASDSetInfo"},
+ {API_NetDASDEnum, "NetDASDEnum"},
+ {API_NetDASDCheck, "NetDASDCheck"},
+ {API_NetDASDCtl, "NetDASDCtl"},
+ {API_NetUserRemoteLogonCheck, "NetUserRemoteLogonCheck"},
+ {API_NetUserPasswordSet3, "NetUserPasswordSet3"},
+ {API_NetCreateRIPLMachine, "NetCreateRIPLMachine"},
+ {API_NetDeleteRIPLMachine, "NetDeleteRIPLMachine"},
+ {API_NetGetRIPLMachineInfo, "NetGetRIPLMachineInfo"},
+ {API_NetSetRIPLMachineInfo, "NetSetRIPLMachineInfo"},
+ {API_NetEnumRIPLMachine, "NetEnumRIPLMachine"},
+ {API_I_ShareAdd, "I_ShareAdd"},
+ {API_I_AliasEnum, "I_AliasEnum"},
+ {API_NetAccessApply, "NetAccessApply"},
+ {API_WPrt16Query, "WPrt16Query"},
+ {API_WPrt16Set, "WPrt16Set"},
+ {API_NetUserDel100, "NetUserDel100"},
+ {API_NetUserRemoteLogonCheck2, "NetUserRemoteLogonCheck2"},
+ {API_WRemoteTODSet, "WRemoteTODSet"},
+ {API_WPrintJobMoveAll, "WPrintJobMoveAll"},
+ {API_W16AppParmAdd, "W16AppParmAdd"},
+ {API_W16AppParmDel, "W16AppParmDel"},
+ {API_W16AppParmGet, "W16AppParmGet"},
+ {API_W16AppParmSet, "W16AppParmSet"},
+ {API_W16RIPLMachineCreate, "W16RIPLMachineCreate"},
+ {API_W16RIPLMachineGetInfo, "W16RIPLMachineGetInfo"},
+ {API_W16RIPLMachineSetInfo, "W16RIPLMachineSetInfo"},
+ {API_W16RIPLMachineEnum, "W16RIPLMachineEnum"},
+ {API_W16RIPLMachineListParmEnum, "W16RIPLMachineListParmEnum"},
+ {API_W16RIPLMachClassGetInfo, "W16RIPLMachClassGetInfo"},
+ {API_W16RIPLMachClassEnum, "W16RIPLMachClassEnum"},
+ {API_W16RIPLMachClassCreate, "W16RIPLMachClassCreate"},
+ {API_W16RIPLMachClassSetInfo, "W16RIPLMachClassSetInfo"},
+ {API_W16RIPLMachClassDelete, "W16RIPLMachClassDelete"},
+ {API_W16RIPLMachClassLPEnum, "W16RIPLMachClassLPEnum"},
+ {API_W16RIPLMachineDelete, "W16RIPLMachineDelete"},
+ {API_W16WSLevelGetInfo, "W16WSLevelGetInfo"},
+ {API_NetServerNameAdd, "NetServerNameAdd"},
+ {API_NetServerNameDel, "NetServerNameDel"},
+ {API_NetServerNameEnum, "NetServerNameEnum"},
+ {API_I_WDASDEnum, "I_WDASDEnum"},
+ {API_I_WDASDEnumTerminate, "I_WDASDEnumTerminate"},
+ {API_I_WDASDSetInfo2, "I_WDASDSetInfo2"},
+ {0, NULL}
+};
+
+static void
+dissect_response_data(tvbuff_t *tvb, packet_info *pinfo, int convert,
+ proto_tree *tree, struct smb_info *smb_info,
+ const struct lanman_desc *lanman, gboolean has_ent_count,
+ guint16 ent_count)
+{
+ smb_transact_info_t *trp = smb_info->sip->extra_info;
+ const item_list_t *resp_data_list;
+ int offset, start_offset;
+ const char *label;
+ gint ett;
+ const item_t *resp_data;
+ proto_item *data_item;
+ proto_tree *data_tree;
+ proto_item *entry_item;
+ proto_tree *entry_tree;
+ guint i, j;
+ guint16 aux_count;
+
+ /*
+ * Find the item table for the matching request's detail level.
+ */
+ for (resp_data_list = lanman->resp_data_list;
+ resp_data_list->level != -1; resp_data_list++) {
+ if (resp_data_list->level == trp->info_level)
+ break;
+ }
+ resp_data = resp_data_list->item_list;
+
+ offset = 0;
+ if (has_ent_count) {
+ /*
+ * The data is a list of entries; create a protocol tree item
+ * for it.
+ */
+ if (tree) {
+ label = lanman->resp_data_entry_list_label;
+ if (label == NULL)
+ label = "Entries";
+ if (lanman->ett_data_entry_list != NULL)
+ ett = *lanman->ett_data_entry_list;
+ else
+ ett = ett_lanman_unknown_entries;
+ data_item = proto_tree_add_text(tree, tvb, offset, -1,
+ label);
+ data_tree = proto_item_add_subtree(data_item, ett);
+ } else {
+ data_item = NULL;
+ data_tree = NULL;
+ }
+ } else {
+ /*
+ * Just leave it at the top level.
+ */
+ data_item = NULL;
+ data_tree = tree;
+ }
+
+ if (trp->data_descrip == NULL) {
+ /*
+ * This could happen if we only dissected
+ * part of the request to which this is a
+ * reply, e.g. if the request was split
+ * across TCP segments and we weren't doing
+ * TCP desegmentation, or if we had a snapshot
+ * length that was too short.
+ *
+ * We can't dissect the data; just show it as raw data or,
+ * if we've already created a top-level item, note that
+ * no descriptor is available.
+ */
+ if (has_ent_count) {
+ if (data_item != NULL) {
+ proto_item_append_text(data_item,
+ " (No descriptor available)");
+ }
+ } else {
+ proto_tree_add_text(data_tree, tvb, offset, -1,
+ "Data (no descriptor available)");
+ }
+ offset += tvb_length_remaining(tvb, offset);
+ } else {
+ /*
+ * If we have an entry count, show all the entries,
+ * with each one having a protocol tree item.
+ *
+ * Otherwise, we just show one returned item, with
+ * no protocol tree item.
+ */
+ if (!has_ent_count)
+ ent_count = 1;
+ for (i = 0; i < ent_count; i++) {
+ start_offset = offset;
+ if (has_ent_count &&
+ lanman->resp_data_element_item != NULL) {
+ /*
+ * Create a protocol tree item for the
+ * entry.
+ */
+ entry_item =
+ (*lanman->resp_data_element_item)
+ (tvb, data_tree, offset);
+ entry_tree = proto_item_add_subtree(
+ entry_item,
+ *lanman->ett_resp_data_element_item);
+ } else {
+ /*
+ * Just leave it at the current
+ * level.
+ */
+ entry_item = NULL;
+ entry_tree = data_tree;
+ }
+
+ offset = dissect_transact_data(tvb, offset,
+ convert, pinfo, entry_tree,
+ trp->data_descrip, resp_data, &aux_count);
+
+ /* auxiliary data */
+ if (trp->aux_data_descrip != NULL) {
+ for (j = 0; j < aux_count; j++) {
+ offset = dissect_transact_data(
+ tvb, offset, convert,
+ pinfo, entry_tree,
+ trp->data_descrip,
+ lanman->resp_aux_data, NULL);
+ }
+ }
+
+ if (entry_item != NULL) {
+ /*
+ * Set the length of the protocol tree
+ * item for the entry.
+ */
+ proto_item_set_len(entry_item,
+ offset - start_offset);
+ }
+ }
+ }
+
+ if (data_item != NULL) {
+ /*
+ * Set the length of the protocol tree item
+ * for the data.
+ */
+ proto_item_set_len(data_item, offset);
+ }
+}
+
+static gboolean
+dissect_pipe_lanman(tvbuff_t *pd_tvb, tvbuff_t *p_tvb, tvbuff_t *d_tvb,
+ packet_info *pinfo, proto_tree *parent_tree)
+{
+ smb_info_t *smb_info = pinfo->private_data;
+ smb_transact_info_t *trp = smb_info->sip->extra_info;
+ int offset = 0, start_offset;
+ guint16 cmd;
+ guint16 status;
+ int convert;
+ const struct lanman_desc *lanman;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ guint descriptor_len;
+ const gchar *param_descrip, *data_descrip, *aux_data_descrip = NULL;
+ gboolean has_data;
+ gboolean has_ent_count;
+ guint16 ent_count, aux_count;
+ guint i;
+ proto_item *data_item;
+ proto_tree *data_tree;
+
+ if (!proto_is_protocol_enabled(find_protocol_by_id(proto_smb_lanman)))
+ return FALSE;
+ if (smb_info->request && p_tvb == NULL) {
+ /*
+ * Requests must have parameters.
+ */
+ return FALSE;
+ }
+ pinfo->current_proto = "LANMAN";
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LANMAN");
+ }
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, proto_smb_lanman,
+ pd_tvb, 0, -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_lanman);
+ }
+
+ if (smb_info->request) { /* this is a request */
+ /* function code */
+ cmd = tvb_get_letohs(p_tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Request", val_to_str(cmd, commands, "Unknown Command (%u)"));
+ }
+ proto_tree_add_uint(tree, hf_function_code, p_tvb, offset, 2,
+ cmd);
+ offset += 2;
+
+ /*
+ * If we haven't already done so, save the function code in
+ * the structure we were handed, so that it's available to
+ * the code parsing the reply, and initialize the detail
+ * level to -1, meaning "unknown".
+ */
+ if (!pinfo->fd->flags.visited) {
+ trp->lanman_cmd = cmd;
+ trp->info_level = -1;
+ trp->param_descrip=NULL;
+ trp->data_descrip=NULL;
+ trp->aux_data_descrip=NULL;
+ }
+
+ /* parameter descriptor */
+ descriptor_len = tvb_strsize(p_tvb, offset);
+ proto_tree_add_item(tree, hf_param_desc, p_tvb, offset,
+ descriptor_len, TRUE);
+ param_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * Save the parameter descriptor for future use.
+ */
+ g_assert(trp->param_descrip == NULL);
+ trp->param_descrip = g_strdup(param_descrip);
+ }
+ offset += descriptor_len;
+
+ /* return descriptor */
+ descriptor_len = tvb_strsize(p_tvb, offset);
+ proto_tree_add_item(tree, hf_return_desc, p_tvb, offset,
+ descriptor_len, TRUE);
+ data_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * Save the return descriptor for future use.
+ */
+ g_assert(trp->data_descrip == NULL);
+ trp->data_descrip = g_strdup(data_descrip);
+ }
+ offset += descriptor_len;
+
+ lanman = find_lanman(cmd);
+
+ /* request parameters */
+ start_offset = offset;
+ offset = dissect_request_parameters(p_tvb, offset, pinfo, tree,
+ param_descrip, lanman->req, &has_data);
+
+ /* auxiliary data descriptor */
+ if (tvb_reported_length_remaining(p_tvb, offset) > 0){
+ /*
+ * There are more parameters left, so the next
+ * item is the auxiliary data descriptor.
+ */
+ descriptor_len = tvb_strsize(p_tvb, offset);
+ proto_tree_add_item(tree, hf_aux_data_desc, p_tvb, offset,
+ descriptor_len, TRUE);
+ aux_data_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * Save the auxiliary data descriptor for
+ * future use.
+ */
+ g_assert(trp->aux_data_descrip == NULL);
+ trp->aux_data_descrip =
+ g_strdup(aux_data_descrip);
+ }
+ offset += descriptor_len;
+ }
+
+ /* reset offset, we now start dissecting the data area */
+ offset = 0;
+ if (has_data && d_tvb && tvb_reported_length(d_tvb) != 0) {
+ /*
+ * There's a send buffer item in the descriptor
+ * string, and the data count in the transaction
+ * is non-zero, so there's data to dissect.
+ */
+
+ if (lanman->req_data_item != NULL) {
+ /*
+ * Create a protocol tree item for the data.
+ */
+ data_item = (*lanman->req_data_item)(d_tvb,
+ pinfo, tree, offset);
+ data_tree = proto_item_add_subtree(data_item,
+ *lanman->ett_req_data);
+ } else {
+ /*
+ * Just leave it at the top level.
+ */
+ data_item = NULL;
+ data_tree = tree;
+ }
+
+ /* data */
+ offset = dissect_transact_data(d_tvb, offset, -1,
+ pinfo, data_tree, data_descrip, lanman->req_data,
+ &aux_count); /* XXX - what about strings? */
+
+ /* auxiliary data */
+ if (aux_data_descrip != NULL) {
+ for (i = 0; i < aux_count; i++) {
+ offset = dissect_transact_data(d_tvb,
+ offset, -1, pinfo, data_tree,
+ aux_data_descrip,
+ lanman->req_aux_data, NULL);
+ }
+ }
+
+ if (data_item != NULL) {
+ /*
+ * Set the length of the protocol tree item
+ * for the data.
+ */
+ proto_item_set_len(data_item, offset);
+ }
+ }
+ } else {
+ /*
+ * This is a response.
+ * Have we seen the request to which it's a response?
+ */
+ if (trp == NULL)
+ return FALSE; /* no - can't dissect it */
+
+ /* ok we have seen this one before */
+
+ /* if it looks like an interim response, update COL_INFO and return */
+ if( ( (p_tvb==NULL) || (tvb_reported_length(p_tvb)==0) )
+ && ( (d_tvb==NULL) || (tvb_reported_length(d_tvb)==0) ) ){
+ /* command */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Interim Response",
+ val_to_str(trp->lanman_cmd, commands, "Unknown Command (%u)"));
+ }
+ proto_tree_add_uint(tree, hf_function_code, p_tvb, 0, 0, trp->lanman_cmd);
+ return TRUE;
+ }
+
+ /* command */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Response",
+ val_to_str(trp->lanman_cmd, commands, "Unknown Command (%u)"));
+ }
+ proto_tree_add_uint(tree, hf_function_code, p_tvb, 0, 0,
+ trp->lanman_cmd);
+
+ lanman = find_lanman(trp->lanman_cmd);
+
+ /* response parameters */
+
+ /* status */
+ status = tvb_get_letohs(p_tvb, offset);
+ proto_tree_add_uint(tree, hf_status, p_tvb, offset, 2, status);
+ offset += 2;
+
+ /* convert */
+ convert = tvb_get_letohs(p_tvb, offset);
+ proto_tree_add_uint(tree, hf_convert, p_tvb, offset, 2, convert);
+ offset += 2;
+
+ if (trp->param_descrip == NULL) {
+ /*
+ * This could happen if we only dissected
+ * part of the request to which this is a
+ * reply, e.g. if the request was split
+ * across TCP segments and we weren't doing
+ * TCP desegmentation, or if we had a snapshot
+ * length that was too short.
+ *
+ * We can't dissect the parameters; just show them
+ * as raw data.
+ */
+ proto_tree_add_text(tree, p_tvb, offset, -1,
+ "Parameters (no descriptor available)");
+
+ /*
+ * We don't know whether we have a receive buffer,
+ * as we don't have the descriptor; just show what
+ * bytes purport to be data.
+ */
+ if (d_tvb && tvb_reported_length(d_tvb) > 0) {
+ proto_tree_add_text(tree, d_tvb, 0, -1,
+ "Data (no descriptor available)");
+ }
+ } else {
+ /* rest of the parameters */
+ offset = dissect_response_parameters(p_tvb, offset,
+ pinfo, tree, trp->param_descrip, lanman->resp,
+ &has_data, &has_ent_count, &ent_count);
+
+ /* reset offset, we now start dissecting the data area */
+ offset = 0;
+ /* data */
+ if (d_tvb && tvb_reported_length(d_tvb) > 0) {
+ /*
+ * Well, there are bytes that purport to
+ * be data, at least.
+ */
+ if (has_data) {
+ /*
+ * There's a receive buffer item
+ * in the descriptor string, so
+ * dissect it as response data.
+ */
+ dissect_response_data(d_tvb, pinfo,
+ convert, tree, smb_info, lanman,
+ has_ent_count, ent_count);
+ } else {
+ /*
+ * There's no receive buffer item,
+ * but we do have data, so just
+ * show what bytes are data.
+ */
+ proto_tree_add_text(tree, d_tvb, 0, -1,
+ "Data (no receive buffer)");
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+void
+proto_register_pipe_lanman(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_function_code,
+ { "Function Code", "lanman.function_code", FT_UINT16, BASE_DEC,
+ VALS(commands), 0, "LANMAN Function Code/Command", HFILL }},
+
+ { &hf_param_desc,
+ { "Parameter Descriptor", "lanman.param_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Parameter Descriptor", HFILL }},
+
+ { &hf_return_desc,
+ { "Return Descriptor", "lanman.ret_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Return Descriptor", HFILL }},
+
+ { &hf_aux_data_desc,
+ { "Auxiliary Data Descriptor", "lanman.aux_data_desc", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Auxiliary Data Descriptor", HFILL }},
+
+ { &hf_detail_level,
+ { "Detail Level", "lanman.level", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Detail Level", HFILL }},
+
+ { &hf_recv_buf_len,
+ { "Receive Buffer Length", "lanman.recv_buf_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Receive Buffer Length", HFILL }},
+
+ { &hf_send_buf_len,
+ { "Send Buffer Length", "lanman.send_buf_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Send Buffer Length", HFILL }},
+
+ { &hf_continuation_from,
+ { "Continuation from message in frame", "lanman.continuation_from", FT_UINT32, BASE_DEC,
+ NULL, 0, "This is a LANMAN continuation from the message in the frame in question", HFILL }},
+
+ { &hf_status,
+ { "Status", "lanman.status", FT_UINT16, BASE_DEC,
+ VALS(status_vals), 0, "LANMAN Return status", HFILL }},
+
+ { &hf_convert,
+ { "Convert", "lanman.convert", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Convert", HFILL }},
+
+ { &hf_ecount,
+ { "Entry Count", "lanman.entry_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Entries", HFILL }},
+
+ { &hf_acount,
+ { "Available Entries", "lanman.available_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Available Entries", HFILL }},
+
+ { &hf_share_name,
+ { "Share Name", "lanman.share.name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Name of Share", HFILL }},
+
+ { &hf_share_type,
+ { "Share Type", "lanman.share.type", FT_UINT16, BASE_DEC,
+ VALS(share_type_vals), 0, "LANMAN Type of Share", HFILL }},
+
+ { &hf_share_comment,
+ { "Share Comment", "lanman.share.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Share Comment", HFILL }},
+
+ { &hf_share_permissions,
+ { "Share Permissions", "lanman.share.permissions", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Permissions on share", HFILL }},
+
+ { &hf_share_max_uses,
+ { "Share Max Uses", "lanman.share.max_uses", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Max connections allowed to share", HFILL }},
+
+ { &hf_share_current_uses,
+ { "Share Current Uses", "lanman.share.current_uses", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Current connections to share", HFILL }},
+
+ { &hf_share_path,
+ { "Share Path", "lanman.share.path", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Share Path", HFILL }},
+
+ { &hf_share_password,
+ { "Share Password", "lanman.share.password", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Share Password", HFILL }},
+
+ { &hf_server_name,
+ { "Server Name", "lanman.server.name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Name of Server", HFILL }},
+
+ { &hf_server_major,
+ { "Major Version", "lanman.server.major", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Server Major Version", HFILL }},
+
+ { &hf_server_minor,
+ { "Minor Version", "lanman.server.minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Server Minor Version", HFILL }},
+
+ { &hf_server_comment,
+ { "Server Comment", "lanman.server.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Server Comment", HFILL }},
+
+ { &hf_abytes,
+ { "Available Bytes", "lanman.available_bytes", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Available Bytes", HFILL }},
+
+ { &hf_current_time,
+ { "Current Date/Time", "lanman.current_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Current date and time, in seconds since 00:00:00, January 1, 1970", HFILL }},
+
+ { &hf_msecs,
+ { "Milliseconds", "lanman.msecs", FT_UINT32, BASE_DEC,
+ NULL, 0, "LANMAN Milliseconds since arbitrary time in the past (typically boot time)", HFILL }},
+
+ { &hf_hour,
+ { "Hour", "lanman.hour", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current hour", HFILL }},
+
+ { &hf_minute,
+ { "Minute", "lanman.minute", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current minute", HFILL }},
+
+ { &hf_second,
+ { "Second", "lanman.second", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current second", HFILL }},
+
+ { &hf_hundredths,
+ { "Hundredths of a second", "lanman.hundredths", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current hundredths of a second", HFILL }},
+
+ { &hf_tzoffset,
+ { "Time Zone Offset", "lanman.tzoffset", FT_INT16, BASE_DEC,
+ NULL, 0, "LANMAN Offset of time zone from GMT, in minutes", HFILL }},
+
+ { &hf_timeinterval,
+ { "Time Interval", "lanman.timeinterval", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN .0001 second units per clock tick", HFILL }},
+
+ { &hf_day,
+ { "Day", "lanman.day", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current day", HFILL }},
+
+ { &hf_month,
+ { "Month", "lanman.month", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Current month", HFILL }},
+
+ { &hf_year,
+ { "Year", "lanman.year", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Current year", HFILL }},
+
+ { &hf_weekday,
+ { "Weekday", "lanman.weekday", FT_UINT8, BASE_DEC,
+ VALS(weekday_vals), 0, "LANMAN Current day of the week", HFILL }},
+
+ { &hf_enumeration_domain,
+ { "Enumeration Domain", "lanman.enumeration_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Domain in which to enumerate servers", HFILL }},
+
+ { &hf_last_entry,
+ { "Last Entry", "lanman.last_entry", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN last reported entry of the enumerated servers", HFILL }},
+
+ { &hf_computer_name,
+ { "Computer Name", "lanman.computer_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Computer Name", HFILL }},
+
+ { &hf_user_name,
+ { "User Name", "lanman.user_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN User Name", HFILL }},
+
+ { &hf_group_name,
+ { "Group Name", "lanman.group_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Group Name", HFILL }},
+
+ { &hf_workstation_domain,
+ { "Workstation Domain", "lanman.workstation_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Workstation Domain", HFILL }},
+
+ { &hf_workstation_major,
+ { "Workstation Major Version", "lanman.workstation_major", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Workstation Major Version", HFILL }},
+
+ { &hf_workstation_minor,
+ { "Workstation Minor Version", "lanman.workstation_minor", FT_UINT8, BASE_DEC,
+ NULL, 0, "LANMAN Workstation Minor Version", HFILL }},
+
+ { &hf_logon_domain,
+ { "Logon Domain", "lanman.logon_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Logon Domain", HFILL }},
+
+ { &hf_other_domains,
+ { "Other Domains", "lanman.other_domains", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Other Domains", HFILL }},
+
+ { &hf_password,
+ { "Password", "lanman.password", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Password", HFILL }},
+
+ { &hf_workstation_name,
+ { "Workstation Name", "lanman.workstation_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Workstation Name", HFILL }},
+
+ { &hf_ustruct_size,
+ { "Length of UStruct", "lanman.ustruct_size", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN UStruct Length", HFILL }},
+
+ { &hf_logon_code,
+ { "Logon Code", "lanman.logon_code", FT_UINT16, BASE_DEC,
+ VALS(status_vals), 0, "LANMAN Logon Code", HFILL }},
+
+ { &hf_privilege_level,
+ { "Privilege Level", "lanman.privilege_level", FT_UINT16, BASE_DEC,
+ VALS(privilege_vals), 0, "LANMAN Privilege Level", HFILL }},
+
+ { &hf_operator_privileges,
+ { "Operator Privileges", "lanman.operator_privileges", FT_UINT32, BASE_DEC,
+ VALS(op_privilege_vals), 0, "LANMAN Operator Privileges", HFILL }},
+
+ { &hf_num_logons,
+ { "Number of Logons", "lanman.num_logons", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of Logons", HFILL }},
+
+ { &hf_bad_pw_count,
+ { "Bad Password Count", "lanman.bad_pw_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Number of incorrect passwords entered since last successful login", HFILL }},
+
+ { &hf_last_logon,
+ { "Last Logon Date/Time", "lanman.last_logon", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time of last logon", HFILL }},
+
+ { &hf_last_logoff,
+ { "Last Logoff Date/Time", "lanman.last_logoff", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time of last logoff", HFILL }},
+
+ { &hf_logoff_time,
+ { "Logoff Date/Time", "lanman.logoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user should log off", HFILL }},
+
+ { &hf_kickoff_time,
+ { "Kickoff Date/Time", "lanman.kickoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user will be logged off", HFILL }},
+
+ { &hf_password_age,
+ { "Password Age", "lanman.password_age", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Time since user last changed his/her password", HFILL }},
+
+ { &hf_password_can_change,
+ { "Password Can Change", "lanman.password_can_change", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user can change their password", HFILL }},
+
+ { &hf_password_must_change,
+ { "Password Must Change", "lanman.password_must_change", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Date and time when user must change their password", HFILL }},
+
+ { &hf_script_path,
+ { "Script Path", "lanman.script_path", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Pathname of user's logon script", HFILL }},
+
+ { &hf_logoff_code,
+ { "Logoff Code", "lanman.logoff_code", FT_UINT16, BASE_DEC,
+ VALS(status_vals), 0, "LANMAN Logoff Code", HFILL }},
+
+ { &hf_duration,
+ { "Duration of Session", "lanman.duration", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "LANMAN Number of seconds the user was logged on", HFILL }},
+
+ { &hf_comment,
+ { "Comment", "lanman.comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Comment", HFILL }},
+
+ { &hf_user_comment,
+ { "User Comment", "lanman.user_comment", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN User Comment", HFILL }},
+
+ { &hf_full_name,
+ { "Full Name", "lanman.full_name", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Full Name", HFILL }},
+
+ { &hf_homedir,
+ { "Home Directory", "lanman.homedir", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Home Directory", HFILL }},
+
+ { &hf_parameters,
+ { "Parameters", "lanman.parameters", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Parameters", HFILL }},
+
+ { &hf_logon_server,
+ { "Logon Server", "lanman.logon_server", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Logon Server", HFILL }},
+
+ /* XXX - we should have a value_string table for this */
+ { &hf_country_code,
+ { "Country Code", "lanman.country_code", FT_UINT16, BASE_DEC,
+ VALS(ms_country_codes), 0, "LANMAN Country Code", HFILL }},
+
+ { &hf_workstations,
+ { "Workstations", "lanman.workstations", FT_STRING, BASE_NONE,
+ NULL, 0, "LANMAN Workstations", HFILL }},
+
+ { &hf_max_storage,
+ { "Max Storage", "lanman.max_storage", FT_UINT32, BASE_DEC,
+ NULL, 0, "LANMAN Max Storage", HFILL }},
+
+ { &hf_units_per_week,
+ { "Units Per Week", "lanman.units_per_week", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Units Per Week", HFILL }},
+
+ { &hf_logon_hours,
+ { "Logon Hours", "lanman.logon_hours", FT_BYTES, BASE_NONE,
+ NULL, 0, "LANMAN Logon Hours", HFILL }},
+
+ /* XXX - we should have a value_string table for this */
+ { &hf_code_page,
+ { "Code Page", "lanman.code_page", FT_UINT16, BASE_DEC,
+ NULL, 0, "LANMAN Code Page", HFILL }},
+
+ { &hf_new_password,
+ { "New Password", "lanman.new_password", FT_BYTES, BASE_HEX,
+ NULL, 0, "LANMAN New Password (encrypted)", HFILL }},
+
+ { &hf_old_password,
+ { "Old Password", "lanman.old_password", FT_BYTES, BASE_HEX,
+ NULL, 0, "LANMAN Old Password (encrypted)", HFILL }},
+
+ { &hf_reserved,
+ { "Reserved", "lanman.reserved", FT_UINT32, BASE_HEX,
+ NULL, 0, "LANMAN Reserved", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_lanman,
+ &ett_lanman_unknown_entries,
+ &ett_lanman_unknown_entry,
+ &ett_lanman_servers,
+ &ett_lanman_server,
+ &ett_lanman_groups,
+ &ett_lanman_shares,
+ &ett_lanman_share,
+ };
+
+ proto_smb_lanman = proto_register_protocol(
+ "Microsoft Windows Lanman Remote API Protocol", "LANMAN", "lanman");
+ proto_register_field_array(proto_smb_lanman, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+static heur_dissector_list_t smb_transact_heur_subdissector_list;
+
+static GHashTable *dcerpc_fragment_table = NULL;
+static GHashTable *dcerpc_reassembled_table = NULL;
+
+static void
+smb_dcerpc_reassembly_init(void)
+{
+ fragment_table_init(&dcerpc_fragment_table);
+ reassembled_table_init(&dcerpc_reassembled_table);
+}
+
+gboolean
+dissect_pipe_dcerpc(tvbuff_t *d_tvb, packet_info *pinfo, proto_tree *parent_tree,
+ proto_tree *tree, guint32 fid)
+{
+ dcerpc_private_info dcerpc_priv;
+ smb_info_t *smb_priv = (smb_info_t *)pinfo->private_data;
+ gboolean result=0;
+ gboolean save_fragmented;
+ guint reported_len;
+ guint32 hash_key;
+ fragment_data *fd_head;
+ tvbuff_t *new_tvb;
+
+ dcerpc_priv.fid = fid;
+
+ pinfo->private_data = &dcerpc_priv;
+
+
+ /*
+ * Offer desegmentation service to DCERPC if we have all the
+ * data. Otherwise, reassembly is (probably) impossible.
+ */
+ pinfo->can_desegment=0;
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
+ reported_len = tvb_reported_length(d_tvb);
+ if(smb_dcerpc_reassembly && tvb_bytes_exist(d_tvb, 0, reported_len)){
+ pinfo->can_desegment=2;
+ }
+
+ save_fragmented = pinfo->fragmented;
+
+
+ /* if we are not offering desegmentation, just try the heuristics
+ and bail out
+ */
+ if(!pinfo->can_desegment){
+ result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
+ goto clean_up_and_exit;
+ }
+
+
+ /* below this line, we know we are doing reassembly */
+
+ /*
+ * We have to keep track of reassemblies by FID, because
+ * we could have more than one pipe operation in a frame
+ * with NetBIOS-over-TCP.
+ *
+ * We also have to keep track of them by direction, as
+ * we might have reassemblies in progress in both directions.
+ *
+ * We do that by combining the FID and the direction and
+ * using that as the reassembly ID.
+ *
+ * The direction is indicated by the SMB request/reply flag - data
+ * from client to server is carried in requests, data from server
+ * to client is carried in replies.
+ *
+ * We know that the FID is only 16 bits long, so we put the
+ * direction in bit 17.
+ */
+ hash_key = fid;
+ if (smb_priv->request)
+ hash_key |= 0x10000;
+
+ /* this is a new packet, see if we are already reassembling this
+ pdu and if not, check if the dissector wants us
+ to reassemble it
+ */
+ if(!pinfo->fd->flags.visited){
+ /*
+ * This is the first pass.
+ *
+ * Check if we are already reassembling this PDU or not;
+ * we check for an in-progress reassembly for this FID
+ * in this direction, by searching for its reassembly
+ * structure.
+ */
+ fd_head=fragment_get(pinfo, fid, dcerpc_fragment_table);
+ if(!fd_head){
+ /* No reassembly, so this is a new pdu. check if the
+ dissector wants us to reassemble it or if we
+ already got the full pdu in this tvb.
+ */
+
+ /*
+ * First, just check if it looks like dcerpc or not.
+ *
+ * XXX - this assumes that the dissector is idempotent,
+ * as it's doing a "trial" dissection building no
+ * tree; that's not necessarily the case.
+ */
+ result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, NULL);
+
+ /* no this didnt look like something we know */
+ if(!result){
+ goto clean_up_and_exit;
+ }
+
+ /* did the subdissector want us to reassemble any
+ more data ?
+ */
+ if(pinfo->desegment_len){
+ fragment_add_check(d_tvb, 0, pinfo, fid,
+ dcerpc_fragment_table,
+ dcerpc_reassembled_table,
+ 0, reported_len, TRUE);
+ fragment_set_tot_len(pinfo, fid,
+ dcerpc_fragment_table,
+ pinfo->desegment_len+reported_len);
+ goto clean_up_and_exit;
+ }
+
+ /* guess we have the full pdu in this tvb then,
+ just dissect it and continue.
+ */
+ result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
+ goto clean_up_and_exit;
+ }
+
+ /* OK, we're already doing a reassembly for this FID.
+ skip to last segment in the existing reassembly structure
+ and add this fragment there
+
+ XXX we might add code here to use any offset values
+ we might pick up from the Read/Write calls instead of
+ assuming we always get them in the correct order
+ */
+ while(fd_head->next){
+ fd_head=fd_head->next;
+ }
+ fd_head=fragment_add_check(d_tvb, 0, pinfo, fid,
+ dcerpc_fragment_table, dcerpc_reassembled_table,
+ fd_head->offset+fd_head->len,
+ reported_len, TRUE);
+
+ /* if we completed reassembly */
+ if(fd_head){
+ new_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->datalen, fd_head->datalen);
+ tvb_set_child_real_data_tvbuff(d_tvb, new_tvb);
+ add_new_data_source(pinfo, new_tvb,
+ "DCERPC over SMB");
+ pinfo->fragmented=FALSE;
+
+ d_tvb=new_tvb;
+
+ /* list what segments we have */
+ show_fragment_tree(fd_head, &smb_pipe_frag_items,
+ tree, pinfo, d_tvb);
+
+ /* dissect the full PDU */
+ result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
+ }
+ goto clean_up_and_exit;
+ }
+
+ /*
+ * This is not the first pass; see if it's in the table of
+ * reassembled packets.
+ *
+ * XXX - we know that several of the arguments aren't going to
+ * be used, so we pass bogus variables. Can we clean this
+ * up so that we don't have to distinguish between the first
+ * pass and subsequent passes?
+ */
+ fd_head=fragment_add_check(d_tvb, 0, pinfo, fid, dcerpc_fragment_table,
+ dcerpc_reassembled_table, 0, 0, TRUE);
+ if(!fd_head){
+ /* we didnt find it, try any of the heuristic dissectors
+ and bail out
+ */
+ result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
+ goto clean_up_and_exit;
+ }
+ if(!fd_head->flags&FD_DEFRAGMENTED){
+ /* we dont have a fully reassembled frame */
+ result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
+ goto clean_up_and_exit;
+ }
+
+ /* it is reassembled but it was reassembled in a different frame */
+ if(pinfo->fd->num!=fd_head->reassembled_in){
+ proto_tree_add_uint(parent_tree, hf_pipe_reassembled_in, d_tvb, 0, 0, fd_head->reassembled_in);
+ goto clean_up_and_exit;
+ }
+
+
+ /* display the reassembled pdu */
+ new_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->datalen, fd_head->datalen);
+ tvb_set_child_real_data_tvbuff(d_tvb, new_tvb);
+ add_new_data_source(pinfo, new_tvb,
+ "DCERPC over SMB");
+ pinfo->fragmented=FALSE;
+
+ d_tvb=new_tvb;
+
+ /* list what segments we have */
+ show_fragment_tree(fd_head, &smb_pipe_frag_items,
+ tree, pinfo, d_tvb);
+
+ /* dissect the full PDU */
+ result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
+
+
+
+clean_up_and_exit:
+ /* clear out the variables */
+ pinfo->private_data = smb_priv;
+ pinfo->can_desegment=0;
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
+
+ if (!result)
+ call_dissector(data_handle, d_tvb, pinfo, parent_tree);
+
+ pinfo->fragmented = save_fragmented;
+ return TRUE;
+}
+
+void
+proto_register_pipe_dcerpc(void)
+{
+ register_heur_dissector_list("smb_transact", &smb_transact_heur_subdissector_list);
+ register_init_routine(smb_dcerpc_reassembly_init);
+}
+
+#define CALL_NAMED_PIPE 0x54
+#define WAIT_NAMED_PIPE 0x53
+#define PEEK_NAMED_PIPE 0x23
+#define Q_NM_P_HAND_STATE 0x21
+#define SET_NM_P_HAND_STATE 0x01
+#define Q_NM_PIPE_INFO 0x22
+#define TRANSACT_NM_PIPE 0x26
+#define RAW_READ_NM_PIPE 0x11
+#define RAW_WRITE_NM_PIPE 0x31
+
+static const value_string functions[] = {
+ {CALL_NAMED_PIPE, "CallNamedPipe"},
+ {WAIT_NAMED_PIPE, "WaitNamedPipe"},
+ {PEEK_NAMED_PIPE, "PeekNamedPipe"},
+ {Q_NM_P_HAND_STATE, "QNmPHandState"},
+ {SET_NM_P_HAND_STATE, "SetNmPHandState"},
+ {Q_NM_PIPE_INFO, "QNmPipeInfo"},
+ {TRANSACT_NM_PIPE, "TransactNmPipe"},
+ {RAW_READ_NM_PIPE, "RawReadNmPipe"},
+ {RAW_WRITE_NM_PIPE, "RawWriteNmPipe"},
+ {0, NULL}
+};
+
+static const value_string pipe_status[] = {
+ {1, "Disconnected by server"},
+ {2, "Listening"},
+ {3, "Connection to server is OK"},
+ {4, "Server end of pipe is closed"},
+ {0, NULL}
+};
+
+#define PIPE_LANMAN 1
+#define PIPE_DCERPC 2
+
+/* decode the SMB pipe protocol
+ for requests
+ pipe is the name of the pipe, e.g. LANMAN
+ smb_info->trans_subcmd is set to the symbolic constant matching the mailslot name
+ for responses
+ pipe is NULL
+ smb_info->trans_subcmd gives us which pipe this response is for
+*/
+gboolean
+dissect_pipe_smb(tvbuff_t *sp_tvb, tvbuff_t *s_tvb, tvbuff_t *pd_tvb,
+ tvbuff_t *p_tvb, tvbuff_t *d_tvb, const char *pipe,
+ packet_info *pinfo, proto_tree *tree)
+{
+ smb_info_t *smb_info;
+ smb_transact_info_t *tri;
+ guint sp_len;
+ proto_item *pipe_item = NULL;
+ proto_tree *pipe_tree = NULL;
+ int offset;
+ int trans_subcmd;
+ int function;
+ int fid = -1;
+ guint16 info_level;
+
+ if (!proto_is_protocol_enabled(find_protocol_by_id(proto_smb_pipe)))
+ return FALSE;
+ pinfo->current_proto = "SMB Pipe";
+
+ smb_info = pinfo->private_data;
+
+ /*
+ * Set the columns.
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMB Pipe");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ smb_info->request ? "Request" : "Response");
+ }
+
+ if (smb_info->sip != NULL)
+ tri = smb_info->sip->extra_info;
+ else
+ tri = NULL;
+
+ /*
+ * Set up a subtree for the pipe protocol. (It might not contain
+ * anything.)
+ */
+ if (sp_tvb != NULL)
+ sp_len = tvb_length(sp_tvb);
+ else
+ sp_len = 0;
+ if (tree) {
+ pipe_item = proto_tree_add_item(tree, proto_smb_pipe,
+ sp_tvb, 0, sp_len, FALSE);
+ pipe_tree = proto_item_add_subtree(pipe_item, ett_smb_pipe);
+ }
+ offset = 0;
+
+ /*
+ * Do we have any setup words at all?
+ */
+ if (s_tvb != NULL && tvb_length(s_tvb) != 0) {
+ /*
+ * Yes. The first of them is the function.
+ */
+ function = tvb_get_letohs(s_tvb, offset);
+ proto_tree_add_uint(pipe_tree, hf_pipe_function, s_tvb,
+ offset, 2, function);
+ offset += 2;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ val_to_str(function, functions, "Unknown function (0x%04x)"),
+ smb_info->request ? "Request" : "Response");
+ }
+ if (tri != NULL)
+ tri->function = function;
+
+ /*
+ * The second of them depends on the function.
+ */
+ switch (function) {
+
+ case CALL_NAMED_PIPE:
+ case WAIT_NAMED_PIPE:
+ /*
+ * It's a priority.
+ */
+ proto_tree_add_item(pipe_tree, hf_pipe_priority, s_tvb,
+ offset, 2, TRUE);
+ break;
+
+ case PEEK_NAMED_PIPE:
+ case Q_NM_P_HAND_STATE:
+ case SET_NM_P_HAND_STATE:
+ case Q_NM_PIPE_INFO:
+ case TRANSACT_NM_PIPE:
+ case RAW_READ_NM_PIPE:
+ case RAW_WRITE_NM_PIPE:
+ /*
+ * It's a FID.
+ */
+ fid = tvb_get_letohs(s_tvb, 2);
+ add_fid(s_tvb, pinfo, pipe_tree, offset, 2, (guint16) fid);
+ if (tri != NULL)
+ tri->fid = fid;
+ break;
+
+ default:
+ /*
+ * It's something unknown.
+ * XXX - put it into the tree?
+ */
+ break;
+ }
+ offset += 2;
+ } else {
+ /*
+ * This is either a response or a pipe transaction with
+ * no setup information.
+ *
+ * In the former case, we can get that information from
+ * the matching request, if we saw it.
+ *
+ * In the latter case, there is no function or FID.
+ */
+ if (tri != NULL && tri->function != -1) {
+ function = tri->function;
+ proto_tree_add_uint(pipe_tree, hf_pipe_function, NULL,
+ 0, 0, function);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ val_to_str(function, functions, "Unknown function (0x%04x)"),
+ smb_info->request ? "Request" : "Response");
+ }
+ fid = tri->fid;
+ if (fid != -1)
+ add_fid(NULL, pinfo, pipe_tree, 0, 0, (guint16) fid);
+ } else {
+ function = -1;
+ fid = -1;
+ }
+ }
+
+ /*
+ * XXX - put the byte count and the pipe name into the tree as well;
+ * that requires us to fetch a possibly-Unicode string.
+ */
+
+ if(smb_info->request){
+ if(strncmp(pipe,"LANMAN",6) == 0){
+ trans_subcmd=PIPE_LANMAN;
+ } else {
+ /* assume it is DCERPC */
+ trans_subcmd=PIPE_DCERPC;
+ }
+
+ if (!pinfo->fd->flags.visited)
+ tri->trans_subcmd = trans_subcmd;
+ } else
+ trans_subcmd = tri->trans_subcmd;
+
+ if (tri == NULL) {
+ /*
+ * We don't know what type of pipe transaction this
+ * was, so indicate that we didn't dissect it.
+ */
+ return FALSE;
+ }
+
+ switch (function) {
+
+ case CALL_NAMED_PIPE:
+ case TRANSACT_NM_PIPE:
+ switch(trans_subcmd){
+
+ case PIPE_LANMAN:
+ return dissect_pipe_lanman(pd_tvb, p_tvb, d_tvb, pinfo,
+ tree);
+ break;
+
+ case PIPE_DCERPC:
+ /*
+ * Only dissect this if we know the FID.
+ */
+ if (fid != -1) {
+ if (d_tvb == NULL)
+ return FALSE;
+ return dissect_pipe_dcerpc(d_tvb, pinfo, tree,
+ pipe_tree, fid);
+ }
+ break;
+ }
+ break;
+
+ case -1:
+ /*
+ * We don't know the function; we dissect only LANMAN
+ * pipe messages, not RPC pipe messages, in that case.
+ */
+ switch(trans_subcmd){
+ case PIPE_LANMAN:
+ return dissect_pipe_lanman(pd_tvb, p_tvb, d_tvb, pinfo,
+ tree);
+ break;
+ }
+ break;
+
+ case WAIT_NAMED_PIPE:
+ break;
+
+ case PEEK_NAMED_PIPE:
+ /*
+ * Request contains no parameters or data.
+ */
+ if (!smb_info->request) {
+ if (p_tvb == NULL)
+ return FALSE;
+ offset = 0;
+ proto_tree_add_item(pipe_tree, hf_pipe_peek_available,
+ p_tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(pipe_tree, hf_pipe_peek_remaining,
+ p_tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(pipe_tree, hf_pipe_peek_status,
+ p_tvb, offset, 2, TRUE);
+ offset += 2;
+ }
+ break;
+
+ case Q_NM_P_HAND_STATE:
+ /*
+ * Request contains no parameters or data.
+ */
+ if (!smb_info->request) {
+ if (p_tvb == NULL)
+ return FALSE;
+ offset = dissect_ipc_state(p_tvb, pipe_tree, 0, FALSE);
+ }
+ break;
+
+ case SET_NM_P_HAND_STATE:
+ /*
+ * Response contains no parameters or data.
+ */
+ if (smb_info->request) {
+ if (p_tvb == NULL)
+ return FALSE;
+ offset = dissect_ipc_state(p_tvb, pipe_tree, 0, TRUE);
+ }
+ break;
+
+ case Q_NM_PIPE_INFO:
+ offset = 0;
+ if (smb_info->request) {
+ if (p_tvb == NULL)
+ return FALSE;
+
+ /*
+ * Request contains an information level.
+ */
+ info_level = tvb_get_letohs(p_tvb, offset);
+ proto_tree_add_uint(pipe_tree, hf_pipe_getinfo_info_level,
+ p_tvb, offset, 2, info_level);
+ offset += 2;
+ if (!pinfo->fd->flags.visited)
+ tri->info_level = info_level;
+ } else {
+ guint8 pipe_namelen;
+
+ if (d_tvb == NULL)
+ return FALSE;
+
+ switch (tri->info_level) {
+
+ case 1:
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_output_buffer_size,
+ d_tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_input_buffer_size,
+ d_tvb, offset, 2, TRUE);
+ offset += 2;
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_maximum_instances,
+ d_tvb, offset, 1, TRUE);
+ offset += 1;
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_current_instances,
+ d_tvb, offset, 1, TRUE);
+ offset += 1;
+ pipe_namelen = tvb_get_guint8(d_tvb, offset);
+ proto_tree_add_uint(pipe_tree,
+ hf_pipe_getinfo_pipe_name_length,
+ d_tvb, offset, 1, pipe_namelen);
+ offset += 1;
+ /* XXX - can this be Unicode? */
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_getinfo_pipe_name,
+ d_tvb, offset, pipe_namelen, TRUE);
+ break;
+ }
+ }
+ break;
+
+ case RAW_READ_NM_PIPE:
+ /*
+ * Request contains no parameters or data.
+ */
+ if (!smb_info->request) {
+ if (d_tvb == NULL)
+ return FALSE;
+
+ offset = dissect_file_data(d_tvb, pipe_tree, 0,
+ (guint16) tvb_reported_length(d_tvb),
+ (guint16) tvb_reported_length(d_tvb));
+ }
+ break;
+
+ case RAW_WRITE_NM_PIPE:
+ offset = 0;
+ if (smb_info->request) {
+ if (d_tvb == NULL)
+ return FALSE;
+
+ offset = dissect_file_data(d_tvb, pipe_tree,
+ offset, (guint16) tvb_reported_length(d_tvb),
+ (guint16) tvb_reported_length(d_tvb));
+ } else {
+ if (p_tvb == NULL)
+ return FALSE;
+ proto_tree_add_item(pipe_tree,
+ hf_pipe_write_raw_bytes_written,
+ p_tvb, offset, 2, TRUE);
+ offset += 2;
+ }
+ break;
+ }
+ return TRUE;
+}
+
+void
+proto_register_smb_pipe(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_pipe_function,
+ { "Function", "pipe.function", FT_UINT16, BASE_HEX,
+ VALS(functions), 0, "SMB Pipe Function Code", HFILL }},
+ { &hf_pipe_priority,
+ { "Priority", "pipe.priority", FT_UINT16, BASE_DEC,
+ NULL, 0, "SMB Pipe Priority", HFILL }},
+ { &hf_pipe_peek_available,
+ { "Available Bytes", "pipe.peek.available_bytes", FT_UINT16, BASE_DEC,
+ NULL, 0, "Total number of bytes available to be read from the pipe", HFILL }},
+ { &hf_pipe_peek_remaining,
+ { "Bytes Remaining", "pipe.peek.remaining_bytes", FT_UINT16, BASE_DEC,
+ NULL, 0, "Total number of bytes remaining in the message at the head of the pipe", HFILL }},
+ { &hf_pipe_peek_status,
+ { "Pipe Status", "pipe.peek.status", FT_UINT16, BASE_DEC,
+ VALS(pipe_status), 0, "Pipe status", HFILL }},
+ { &hf_pipe_getinfo_info_level,
+ { "Information Level", "pipe.getinfo.info_level", FT_UINT16, BASE_DEC,
+ NULL, 0, "Information level of information to return", HFILL }},
+ { &hf_pipe_getinfo_output_buffer_size,
+ { "Output Buffer Size", "pipe.getinfo.output_buffer_size", FT_UINT16, BASE_DEC,
+ NULL, 0, "Actual size of buffer for outgoing (server) I/O", HFILL }},
+ { &hf_pipe_getinfo_input_buffer_size,
+ { "Input Buffer Size", "pipe.getinfo.input_buffer_size", FT_UINT16, BASE_DEC,
+ NULL, 0, "Actual size of buffer for incoming (client) I/O", HFILL }},
+ { &hf_pipe_getinfo_maximum_instances,
+ { "Maximum Instances", "pipe.getinfo.maximum_instances", FT_UINT8, BASE_DEC,
+ NULL, 0, "Maximum allowed number of instances", HFILL }},
+ { &hf_pipe_getinfo_current_instances,
+ { "Current Instances", "pipe.getinfo.current_instances", FT_UINT8, BASE_DEC,
+ NULL, 0, "Current number of instances", HFILL }},
+ { &hf_pipe_getinfo_pipe_name_length,
+ { "Pipe Name Length", "pipe.getinfo.pipe_name_length", FT_UINT8, BASE_DEC,
+ NULL, 0, "Length of pipe name", HFILL }},
+ { &hf_pipe_getinfo_pipe_name,
+ { "Pipe Name", "pipe.getinfo.pipe_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of pipe", HFILL }},
+ { &hf_pipe_write_raw_bytes_written,
+ { "Bytes Written", "pipe.write_raw.bytes_written", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of bytes written to the pipe", HFILL }},
+ { &hf_pipe_fragment_overlap,
+ { "Fragment overlap", "pipe.fragment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+ { &hf_pipe_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "pipe.fragment.overlap.conflict", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
+ { &hf_pipe_fragment_multiple_tails,
+ { "Multiple tail fragments found", "pipe.fragment.multipletails", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
+ { &hf_pipe_fragment_too_long_fragment,
+ { "Fragment too long", "pipe.fragment.toolongfragment", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
+ { &hf_pipe_fragment_error,
+ { "Defragmentation error", "pipe.fragment.error", FT_FRAMENUM,
+ BASE_NONE, NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
+ { &hf_pipe_fragment,
+ { "Fragment", "pipe.fragment", FT_FRAMENUM,
+ BASE_NONE, NULL, 0x0, "Pipe Fragment", HFILL }},
+ { &hf_pipe_fragments,
+ { "Fragments", "pipe.fragments", FT_NONE,
+ BASE_NONE, NULL, 0x0, "Pipe Fragments", HFILL }},
+ { &hf_pipe_reassembled_in,
+ { "This PDU is reassembled in", "pipe.reassembled_in", FT_FRAMENUM,
+ BASE_NONE, NULL, 0x0, "The DCE/RPC PDU is completely reassembled in this frame", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_smb_pipe,
+ &ett_smb_pipe_fragment,
+ &ett_smb_pipe_fragments,
+ };
+
+ proto_smb_pipe = proto_register_protocol(
+ "SMB Pipe Protocol", "SMB Pipe", "pipe");
+
+ proto_register_field_array(proto_smb_pipe, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_smb_pipe(void)
+{
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-smb-pipe.h b/epan/dissectors/packet-smb-pipe.h
new file mode 100644
index 0000000000..5df9511689
--- /dev/null
+++ b/epan/dissectors/packet-smb-pipe.h
@@ -0,0 +1,37 @@
+/* packet-smb-pipe.h
+ * Declarations of routines for SMB named pipe packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_SMB_PIPE_H_
+#define _PACKET_SMB_PIPE_H_
+
+extern gboolean
+dissect_pipe_smb(tvbuff_t *sp_tvb, tvbuff_t *s_tvb, tvbuff_t *pd_tvb,
+ tvbuff_t *p_tvb, tvbuff_t *d_tvb, const char *pipe,
+ packet_info *pinfo, proto_tree *tree);
+gboolean
+dissect_pipe_dcerpc(tvbuff_t *d_tvb, packet_info *pinfo, proto_tree *parent_tree,
+ proto_tree *tree, guint32 fid);
+
+#endif
diff --git a/epan/dissectors/packet-smb-sidsnooping.c b/epan/dissectors/packet-smb-sidsnooping.c
new file mode 100644
index 0000000000..84cdb8125e
--- /dev/null
+++ b/epan/dissectors/packet-smb-sidsnooping.c
@@ -0,0 +1,457 @@
+/* packet-smb-sidsnooping.c
+ * Routines for snooping SID to name mappings
+ * Copyright 2003, Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "epan/packet_info.h"
+#include "epan/epan_dissect.h"
+#include "epan/proto.h"
+#include "tap.h"
+#include "packet-dcerpc.h"
+#include "packet-dcerpc-nt.h"
+#include "register.h"
+#include "smb.h"
+#include "packet-smb-sidsnooping.h"
+
+static int hf_lsa = -1;
+static int hf_lsa_info_level = -1;
+static int hf_lsa_opnum = -1;
+static int hf_lsa_domain = -1;
+static int hf_nt_domain_sid = -1;
+static int hf_samr_hnd = -1;
+static int hf_samr_rid = -1;
+static int hf_samr_acct_name = -1;
+static int hf_samr_level = -1;
+
+
+
+GHashTable *sid_name_table = NULL;
+static GMemChunk *sid_name_chunk = NULL;
+static int sid_name_init_count = 200;
+
+
+
+static GMemChunk *ctx_handle_chunk = NULL;
+static int ctx_handle_init_count = 200;
+static GHashTable *ctx_handle_table = NULL;
+
+
+static void *lsa_policy_information_flag = NULL;
+static void *samr_query_dispinfo_flag = NULL;
+
+
+char *
+find_sid_name(char *sid)
+{
+ sid_name *sn;
+ sid_name old_sn;
+
+ old_sn.sid=sid;
+ sn=g_hash_table_lookup(sid_name_table, &old_sn);
+ if(!sn){
+ return NULL;
+ }
+ return sn->name;
+}
+
+static void
+add_sid_name_mapping(char *sid, char *name)
+{
+ sid_name *sn;
+ sid_name old_sn;
+
+ old_sn.sid=sid;
+ sn=g_hash_table_lookup(sid_name_table, &old_sn);
+ if(sn){
+ return;
+ }
+
+ sn=g_mem_chunk_alloc(sid_name_chunk);
+ sn->sid=g_strdup(sid);
+ sn->name=g_strdup(name);
+ g_hash_table_insert(sid_name_table, sn, sn);
+}
+
+
+
+/*
+ * QueryDispInfo :
+ * level 1 : user displayinfo 1
+ */
+static int
+samr_query_dispinfo(void *dummy _U_, packet_info *pinfo, epan_dissect_t *edt, void *pri)
+{
+ dcerpc_info *ri=pri;
+ void *old_ctx=NULL;
+ char *pol_name;
+ char *sid;
+ int sid_len;
+ int num_rids;
+ int num_names;
+ GPtrArray *gp;
+ GPtrArray *gp_rids;
+ GPtrArray *gp_names;
+ field_info *fi;
+ field_info *fi_rid;
+ field_info *fi_name;
+ char sid_name[256];
+ int info_level;
+
+ gp=proto_get_finfo_ptr_array(edt->tree, hf_samr_level);
+ if(!gp || gp->len!=1){
+ return 0;
+ }
+ fi=gp->pdata[0];
+ info_level=fi->value.value.integer;
+
+ if(info_level!=1){
+ return 0;
+ }
+
+ if(!ri){
+ return 0;
+ }
+ if(!ri->call_data){
+ return 0;
+ }
+ if(ri->ptype == PDU_REQ){
+ gp=proto_get_finfo_ptr_array(edt->tree, hf_samr_hnd);
+ if(!gp || gp->len!=1){
+ return 0;
+ }
+ fi=gp->pdata[0];
+
+ old_ctx=g_hash_table_lookup(ctx_handle_table, (gpointer)pinfo->fd->num);
+ if(old_ctx){
+ g_hash_table_remove(ctx_handle_table, (gpointer)pinfo->fd->num);
+ }
+ if(!old_ctx){
+ old_ctx=g_mem_chunk_alloc(ctx_handle_chunk);
+ memcpy(old_ctx, fi->value.value.bytes->data, 20);
+ }
+ g_hash_table_insert(ctx_handle_table, (gpointer)pinfo->fd->num, old_ctx);
+
+ return 0;
+ }
+
+ if(!ri->call_data->req_frame){
+ return 0;
+ }
+
+ old_ctx=g_hash_table_lookup(ctx_handle_table, (gpointer)ri->call_data->req_frame);
+ if(!old_ctx){
+ return 0;
+ }
+
+ if (!dcerpc_smb_fetch_pol(old_ctx, &pol_name, NULL, NULL, ri->call_data->req_frame)) {
+ return 0;
+ }
+
+ if (!pol_name)
+ return 0;
+
+ sid=strstr(pol_name,"S-1-5");
+ if(!sid){
+ return 0;
+ }
+
+ for(sid_len=4;1;sid_len++){
+ if((sid[sid_len]>='0') && (sid[sid_len]<='9')){
+ continue;
+ }
+ if(sid[sid_len]=='-'){
+ continue;
+ }
+ break;
+ }
+
+ gp_rids=proto_get_finfo_ptr_array(edt->tree, hf_samr_rid);
+ if(!gp_rids || gp_rids->len<1){
+ return 0;
+ }
+ num_rids=gp_rids->len;
+ gp_names=proto_get_finfo_ptr_array(edt->tree, hf_samr_acct_name);
+ if(!gp_names || gp_names->len<1){
+ return 0;
+ }
+ num_names=gp_names->len;
+
+ if(num_rids>num_names){
+ num_rids=num_names;
+ }
+
+ for(;num_rids;num_rids--){
+ int len=sid_len;
+
+ fi_rid=gp_rids->pdata[num_rids-1];
+ fi_name=gp_names->pdata[num_rids-1];
+ strncpy(sid_name, sid, len);
+ sid_name[len++]='-';
+ len+=sprintf(sid_name+len,"%d",fi_rid->value.value.integer);
+ sid_name[len]=0;
+ add_sid_name_mapping(sid_name, fi_name->value.value.string);
+ }
+ return 1;
+}
+
+/*
+ * PolicyInformation :
+ * level 3 : PRIMARY_DOMAIN_INFO lsa.domain_sid -> lsa.domain
+ * level 5 : ACCOUNT_DOMAIN_INFO lsa.domain_sid -> lsa.domain
+ * level 12 : DNS_DOMAIN_INFO lsa.domain_sid -> lsa.domain
+ */
+static int
+lsa_policy_information(void *dummy _U_, packet_info *pinfo _U_, epan_dissect_t *edt, void *pri _U_)
+{
+ GPtrArray *gp;
+ field_info *fi;
+ char *domain;
+ char *sid;
+ int info_level;
+
+ gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_info_level);
+ if(!gp || gp->len!=1){
+ return 0;
+ }
+ fi=gp->pdata[0];
+ info_level=fi->value.value.integer;
+
+ switch(info_level){
+ case 3:
+ case 5:
+ case 12:
+ gp=proto_get_finfo_ptr_array(edt->tree, hf_lsa_domain);
+ if(!gp || gp->len!=1){
+ return 0;
+ }
+ fi=gp->pdata[0];
+ domain=fi->value.value.string;
+
+ gp=proto_get_finfo_ptr_array(edt->tree, hf_nt_domain_sid);
+ if(!gp || gp->len!=1){
+ return 0;
+ }
+ fi=gp->pdata[0];
+ sid=fi->value.value.string;
+
+ add_sid_name_mapping(sid, domain);
+ break;
+ }
+ return 0;
+}
+
+static gboolean
+free_all_sid_names(gpointer key_arg, gpointer value _U_, gpointer user_data _U_)
+{
+ sid_name *sn = (sid_name *)key_arg;
+
+ if(sn->sid){
+ g_free((gpointer)sn->sid);
+ sn->sid=NULL;
+ }
+ if(sn->name){
+ g_free((gpointer)sn->name);
+ sn->name=NULL;
+ }
+ return TRUE;
+}
+
+static gint
+sid_name_equal(gconstpointer k1, gconstpointer k2)
+{
+ const sid_name *sn1 = (const sid_name *)k1;
+ const sid_name *sn2 = (const sid_name *)k2;
+
+ return !strcmp(sn1->sid, sn2->sid);
+}
+
+static guint
+sid_name_hash(gconstpointer k)
+{
+ const sid_name *sn = (const sid_name *)k;
+ int i, sum;
+
+ for(sum=0,i=strlen(sn->sid)-1;i>=0;i--){
+ sum+=sn->sid[i];
+ }
+
+ return sum;
+}
+
+
+static gboolean
+free_all_ctx_handle(gpointer key_arg _U_, gpointer value _U_, gpointer user_data _U_)
+{
+ return TRUE;
+}
+static gint
+ctx_handle_equal(gconstpointer k1, gconstpointer k2)
+{
+ int sn1 = (int)k1;
+ int sn2 = (int)k2;
+
+ return sn1==sn2;
+}
+
+static guint
+ctx_handle_hash(gconstpointer k)
+{
+ int sn = (int)k;
+
+ return sn;
+}
+
+
+static void
+sid_snooping_init(void)
+{
+ header_field_info *hfi;
+ GString *error_string;
+
+ if(lsa_policy_information_flag){
+ remove_tap_listener(lsa_policy_information_flag);
+ lsa_policy_information_flag=NULL;
+ }
+ if(samr_query_dispinfo_flag){
+ remove_tap_listener(samr_query_dispinfo_flag);
+ samr_query_dispinfo_flag=NULL;
+ }
+
+ if(sid_name_table){
+ g_hash_table_foreach_remove(sid_name_table, free_all_sid_names, NULL);
+ sid_name_table=NULL;
+ }
+ if(sid_name_chunk){
+ g_mem_chunk_destroy(sid_name_chunk);
+ sid_name_chunk=NULL;
+ }
+ if(ctx_handle_table){
+ g_hash_table_foreach_remove(ctx_handle_table, free_all_ctx_handle, NULL);
+ ctx_handle_table=NULL;
+ }
+ if(ctx_handle_chunk){
+ g_mem_chunk_destroy(ctx_handle_chunk);
+ ctx_handle_chunk=NULL;
+ }
+
+
+ if(!sid_name_snooping){
+ return;
+ }
+
+
+ sid_name_table=g_hash_table_new(sid_name_hash, sid_name_equal);
+ sid_name_chunk = g_mem_chunk_new("sid_name_chunk",
+ sizeof(sid_name),
+ sid_name_init_count * sizeof(sid_name),
+ G_ALLOC_ONLY);
+
+
+ ctx_handle_table=g_hash_table_new(ctx_handle_hash, ctx_handle_equal);
+ ctx_handle_chunk = g_mem_chunk_new("ctx_handle_chunk",
+ 20, /* our dcerpc context handles are 20 bytes */
+ ctx_handle_init_count * 20,
+ G_ALLOC_ONLY);
+
+
+ hf_lsa=proto_get_id_by_filter_name("lsa");
+
+ hfi=proto_registrar_get_byname("lsa.opnum");
+ if(hfi){
+ hf_lsa_opnum=hfi->id;
+ }
+
+ hfi=proto_registrar_get_byname("nt.domain_sid");
+ if(hfi){
+ hf_nt_domain_sid=hfi->id;
+ }
+
+ hfi=proto_registrar_get_byname("lsa.domain");
+ if(hfi){
+ hf_lsa_domain=hfi->id;
+ }
+
+ hfi=proto_registrar_get_byname("lsa.info.level");
+ if(hfi){
+ hf_lsa_info_level=hfi->id;
+ }
+
+ hfi=proto_registrar_get_byname("samr.hnd");
+ if(hfi){
+ hf_samr_hnd=hfi->id;
+ }
+ hfi=proto_registrar_get_byname("samr.rid");
+ if(hfi){
+ hf_samr_rid=hfi->id;
+ }
+ hfi=proto_registrar_get_byname("samr.acct_name");
+ if(hfi){
+ hf_samr_acct_name=hfi->id;
+ }
+ hfi=proto_registrar_get_byname("samr.level");
+ if(hfi){
+ hf_samr_level=hfi->id;
+ }
+
+
+
+ error_string=register_tap_listener("dcerpc", lsa_policy_information, "lsa.policy_information and ( lsa.info.level or lsa.domain or nt.domain_sid )", NULL, lsa_policy_information, NULL);
+ if(error_string){
+ /* error, we failed to attach to the tap. clean up */
+
+ fprintf(stderr, "tethereal: Couldn't register proto_reg_handoff_smb_sidsnooping()/lsa_policy_information tap: %s\n",
+ error_string->str);
+ g_string_free(error_string, TRUE);
+ exit(1);
+ }
+ lsa_policy_information_flag=lsa_policy_information;
+
+ error_string=register_tap_listener("dcerpc", samr_query_dispinfo, "samr and samr.opnum==40 and ( samr.hnd or samr.rid or samr.acct_name or samr.level )", NULL, samr_query_dispinfo, NULL);
+ if(error_string){
+ /* error, we failed to attach to the tap. clean up */
+
+ fprintf(stderr, "tethereal: Couldn't register proto_reg_handoff_smb_sidsnooping()/samr_query_dispinfo tap: %s\n",
+ error_string->str);
+ g_string_free(error_string, TRUE);
+ exit(1);
+ }
+ samr_query_dispinfo_flag=samr_query_dispinfo;
+}
+
+void
+proto_register_smb_sidsnooping(void)
+{
+ register_init_routine(sid_snooping_init);
+}
+
+void
+proto_reg_handoff_smb_sidsnooping(void)
+{
+}
+
diff --git a/epan/dissectors/packet-smb-sidsnooping.h b/epan/dissectors/packet-smb-sidsnooping.h
new file mode 100644
index 0000000000..b369b525fe
--- /dev/null
+++ b/epan/dissectors/packet-smb-sidsnooping.h
@@ -0,0 +1,41 @@
+/* packet-smb-sidsnooping.h
+ * Routines for snooping SID to name mappings
+ * Copyright 2003, Ronnie Sahlberg
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _PACKET_SMB_SID_SNOOPING_H_
+#define _PACKET_SMB_SID_SNOOPING_H_
+
+/* With MSVC and a libethereal.dll, we need a
+ * special declaration for sid_name_table.
+ */
+ETH_VAR_IMPORT GHashTable *sid_name_table;
+
+typedef struct _sid_name {
+ char *sid;
+ char *name;
+} sid_name;
+
+char *find_sid_name(char *sid);
+
+#endif
diff --git a/epan/dissectors/packet-smb.c b/epan/dissectors/packet-smb.c
new file mode 100644
index 0000000000..33d1c8fca3
--- /dev/null
+++ b/epan/dissectors/packet-smb.c
@@ -0,0 +1,19418 @@
+/* packet-smb.c
+ * Routines for smb packet dissection
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ * 2001 Rewrite by Ronnie Sahlberg and Guy Harris
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+#include <ctype.h>
+#include <epan/int-64bit.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include "smb.h"
+#include <epan/strutil.h>
+#include "prefs.h"
+#include "reassemble.h"
+#include "tap.h"
+#include "packet-ipx.h"
+
+#include "packet-smb-common.h"
+#include "packet-smb-mailslot.h"
+#include "packet-smb-pipe.h"
+#include "packet-dcerpc.h"
+#include "packet-smb-sidsnooping.h"
+
+/*
+ * Various specifications and documents about SMB can be found in
+ *
+ * ftp://ftp.microsoft.com/developr/drg/CIFS/
+ *
+ * and a CIFS specification from the Storage Networking Industry Association
+ * can be found on a link from the page at
+ *
+ * http://www.snia.org/tech_activities/CIFS
+ *
+ * (it supercedes the document at
+ *
+ * ftp://ftp.microsoft.com/developr/drg/CIFS/draft-leach-cifs-v1-spec-01.txt
+ *
+ * ).
+ *
+ * There are also some Open Group publications documenting CIFS available
+ * for download; catalog entries for them are at:
+ *
+ * http://www.opengroup.org/products/publications/catalog/c209.htm
+ *
+ * http://www.opengroup.org/products/publications/catalog/c195.htm
+ *
+ * The document "NT LAN Manager SMB File Sharing Protocol Extensions"
+ * can be found at
+ *
+ * http://www.samba.org/samba/ftp/specs/smb-nt01.doc
+ *
+ * (or, presumably a similar path under the Samba mirrors). As the
+ * ".doc" indicates, it's a Word document. Some of the specs from the
+ * Microsoft FTP site can be found in the
+ *
+ * http://www.samba.org/samba/ftp/specs/
+ *
+ * directory as well.
+ *
+ * Beware - these specs may have errors.
+ */
+static int proto_smb = -1;
+static int hf_smb_cmd = -1;
+static int hf_smb_key = -1;
+static int hf_smb_session_id = -1;
+static int hf_smb_sequence_num = -1;
+static int hf_smb_group_id = -1;
+static int hf_smb_pid = -1;
+static int hf_smb_tid = -1;
+static int hf_smb_uid = -1;
+static int hf_smb_mid = -1;
+static int hf_smb_pid_high = -1;
+static int hf_smb_sig = -1;
+static int hf_smb_response_to = -1;
+static int hf_smb_time = -1;
+static int hf_smb_response_in = -1;
+static int hf_smb_continuation_to = -1;
+static int hf_smb_nt_status = -1;
+static int hf_smb_error_class = -1;
+static int hf_smb_error_code = -1;
+static int hf_smb_reserved = -1;
+static int hf_smb_flags_lock = -1;
+static int hf_smb_flags_receive_buffer = -1;
+static int hf_smb_flags_caseless = -1;
+static int hf_smb_flags_canon = -1;
+static int hf_smb_flags_oplock = -1;
+static int hf_smb_flags_notify = -1;
+static int hf_smb_flags_response = -1;
+static int hf_smb_flags2_long_names_allowed = -1;
+static int hf_smb_flags2_ea = -1;
+static int hf_smb_flags2_sec_sig = -1;
+static int hf_smb_flags2_long_names_used = -1;
+static int hf_smb_flags2_esn = -1;
+static int hf_smb_flags2_dfs = -1;
+static int hf_smb_flags2_roe = -1;
+static int hf_smb_flags2_nt_error = -1;
+static int hf_smb_flags2_string = -1;
+static int hf_smb_word_count = -1;
+static int hf_smb_byte_count = -1;
+static int hf_smb_buffer_format = -1;
+static int hf_smb_dialect_name = -1;
+static int hf_smb_dialect_index = -1;
+static int hf_smb_max_trans_buf_size = -1;
+static int hf_smb_max_mpx_count = -1;
+static int hf_smb_max_vcs_num = -1;
+static int hf_smb_session_key = -1;
+static int hf_smb_server_timezone = -1;
+static int hf_smb_encryption_key_length = -1;
+static int hf_smb_encryption_key = -1;
+static int hf_smb_primary_domain = -1;
+static int hf_smb_server = -1;
+static int hf_smb_max_raw_buf_size = -1;
+static int hf_smb_server_guid = -1;
+static int hf_smb_security_blob_len = -1;
+static int hf_smb_security_blob = -1;
+static int hf_smb_sm_mode16 = -1;
+static int hf_smb_sm_password16 = -1;
+static int hf_smb_sm_mode = -1;
+static int hf_smb_sm_password = -1;
+static int hf_smb_sm_signatures = -1;
+static int hf_smb_sm_sig_required = -1;
+static int hf_smb_rm_read = -1;
+static int hf_smb_rm_write = -1;
+static int hf_smb_server_date_time = -1;
+static int hf_smb_server_smb_date = -1;
+static int hf_smb_server_smb_time = -1;
+static int hf_smb_server_cap_raw_mode = -1;
+static int hf_smb_server_cap_mpx_mode = -1;
+static int hf_smb_server_cap_unicode = -1;
+static int hf_smb_server_cap_large_files = -1;
+static int hf_smb_server_cap_nt_smbs = -1;
+static int hf_smb_server_cap_rpc_remote_apis = -1;
+static int hf_smb_server_cap_nt_status = -1;
+static int hf_smb_server_cap_level_ii_oplocks = -1;
+static int hf_smb_server_cap_lock_and_read = -1;
+static int hf_smb_server_cap_nt_find = -1;
+static int hf_smb_server_cap_dfs = -1;
+static int hf_smb_server_cap_infolevel_passthru = -1;
+static int hf_smb_server_cap_large_readx = -1;
+static int hf_smb_server_cap_large_writex = -1;
+static int hf_smb_server_cap_unix = -1;
+static int hf_smb_server_cap_reserved = -1;
+static int hf_smb_server_cap_bulk_transfer = -1;
+static int hf_smb_server_cap_compressed_data = -1;
+static int hf_smb_server_cap_extended_security = -1;
+static int hf_smb_system_time = -1;
+static int hf_smb_unknown = -1;
+static int hf_smb_dir_name = -1;
+static int hf_smb_echo_count = -1;
+static int hf_smb_echo_data = -1;
+static int hf_smb_echo_seq_num = -1;
+static int hf_smb_max_buf_size = -1;
+static int hf_smb_password = -1;
+static int hf_smb_password_len = -1;
+static int hf_smb_ansi_password = -1;
+static int hf_smb_ansi_password_len = -1;
+static int hf_smb_unicode_password = -1;
+static int hf_smb_unicode_password_len = -1;
+static int hf_smb_path = -1;
+static int hf_smb_service = -1;
+static int hf_smb_move_flags_file = -1;
+static int hf_smb_move_flags_dir = -1;
+static int hf_smb_move_flags_verify = -1;
+static int hf_smb_files_moved = -1;
+static int hf_smb_copy_flags_file = -1;
+static int hf_smb_copy_flags_dir = -1;
+static int hf_smb_copy_flags_dest_mode = -1;
+static int hf_smb_copy_flags_source_mode = -1;
+static int hf_smb_copy_flags_verify = -1;
+static int hf_smb_copy_flags_tree_copy = -1;
+static int hf_smb_copy_flags_ea_action = -1;
+static int hf_smb_count = -1;
+static int hf_smb_count_low = -1;
+static int hf_smb_count_high = -1;
+static int hf_smb_file_name = -1;
+static int hf_smb_open_function_open = -1;
+static int hf_smb_open_function_create = -1;
+static int hf_smb_fid = -1;
+static int hf_smb_file_attr_read_only_16bit = -1;
+static int hf_smb_file_attr_read_only_8bit = -1;
+static int hf_smb_file_attr_hidden_16bit = -1;
+static int hf_smb_file_attr_hidden_8bit = -1;
+static int hf_smb_file_attr_system_16bit = -1;
+static int hf_smb_file_attr_system_8bit = -1;
+static int hf_smb_file_attr_volume_16bit = -1;
+static int hf_smb_file_attr_volume_8bit = -1;
+static int hf_smb_file_attr_directory_16bit = -1;
+static int hf_smb_file_attr_directory_8bit = -1;
+static int hf_smb_file_attr_archive_16bit = -1;
+static int hf_smb_file_attr_archive_8bit = -1;
+static int hf_smb_file_attr_device = -1;
+static int hf_smb_file_attr_normal = -1;
+static int hf_smb_file_attr_temporary = -1;
+static int hf_smb_file_attr_sparse = -1;
+static int hf_smb_file_attr_reparse = -1;
+static int hf_smb_file_attr_compressed = -1;
+static int hf_smb_file_attr_offline = -1;
+static int hf_smb_file_attr_not_content_indexed = -1;
+static int hf_smb_file_attr_encrypted = -1;
+static int hf_smb_file_size = -1;
+static int hf_smb_search_attribute_read_only = -1;
+static int hf_smb_search_attribute_hidden = -1;
+static int hf_smb_search_attribute_system = -1;
+static int hf_smb_search_attribute_volume = -1;
+static int hf_smb_search_attribute_directory = -1;
+static int hf_smb_search_attribute_archive = -1;
+static int hf_smb_access_mode = -1;
+static int hf_smb_access_sharing = -1;
+static int hf_smb_access_locality = -1;
+static int hf_smb_access_caching = -1;
+static int hf_smb_access_writetru = -1;
+static int hf_smb_create_time = -1;
+static int hf_smb_modify_time = -1;
+static int hf_smb_backup_time = -1;
+static int hf_smb_mac_alloc_block_count = -1;
+static int hf_smb_mac_alloc_block_size = -1;
+static int hf_smb_mac_free_block_count = -1;
+static int hf_smb_mac_fndrinfo = -1;
+static int hf_smb_mac_root_file_count = -1;
+static int hf_smb_mac_root_dir_count = -1;
+static int hf_smb_mac_file_count = -1;
+static int hf_smb_mac_dir_count = -1;
+static int hf_smb_mac_support_flags = -1;
+static int hf_smb_mac_sup_access_ctrl = -1;
+static int hf_smb_mac_sup_getset_comments = -1;
+static int hf_smb_mac_sup_desktopdb_calls = -1;
+static int hf_smb_mac_sup_unique_ids = -1;
+static int hf_smb_mac_sup_streams = -1;
+static int hf_smb_create_dos_date = -1;
+static int hf_smb_create_dos_time = -1;
+static int hf_smb_last_write_time = -1;
+static int hf_smb_last_write_dos_date = -1;
+static int hf_smb_last_write_dos_time = -1;
+static int hf_smb_access_time = -1;
+static int hf_smb_access_dos_date = -1;
+static int hf_smb_access_dos_time = -1;
+static int hf_smb_old_file_name = -1;
+static int hf_smb_offset = -1;
+static int hf_smb_remaining = -1;
+static int hf_smb_padding = -1;
+static int hf_smb_file_data = -1;
+static int hf_smb_total_data_len = -1;
+static int hf_smb_data_len = -1;
+static int hf_smb_data_len_low = -1;
+static int hf_smb_data_len_high = -1;
+static int hf_smb_seek_mode = -1;
+static int hf_smb_data_size = -1;
+static int hf_smb_alloc_size = -1;
+static int hf_smb_alloc_size64 = -1;
+static int hf_smb_max_count = -1;
+static int hf_smb_max_count_low = -1;
+static int hf_smb_max_count_high = -1;
+static int hf_smb_min_count = -1;
+static int hf_smb_timeout = -1;
+static int hf_smb_high_offset = -1;
+static int hf_smb_units = -1;
+static int hf_smb_bpu = -1;
+static int hf_smb_blocksize = -1;
+static int hf_smb_freeunits = -1;
+static int hf_smb_data_offset = -1;
+static int hf_smb_dcm = -1;
+static int hf_smb_request_mask = -1;
+static int hf_smb_response_mask = -1;
+static int hf_smb_search_id = -1;
+static int hf_smb_write_mode_write_through = -1;
+static int hf_smb_write_mode_return_remaining = -1;
+static int hf_smb_write_mode_raw = -1;
+static int hf_smb_write_mode_message_start = -1;
+static int hf_smb_write_mode_connectionless = -1;
+static int hf_smb_resume_key_len = -1;
+static int hf_smb_resume_find_id = -1;
+static int hf_smb_resume_server_cookie = -1;
+static int hf_smb_resume_client_cookie = -1;
+static int hf_smb_andxoffset = -1;
+static int hf_smb_lock_type_large = -1;
+static int hf_smb_lock_type_cancel = -1;
+static int hf_smb_lock_type_change = -1;
+static int hf_smb_lock_type_oplock = -1;
+static int hf_smb_lock_type_shared = -1;
+static int hf_smb_locking_ol = -1;
+static int hf_smb_number_of_locks = -1;
+static int hf_smb_number_of_unlocks = -1;
+static int hf_smb_lock_long_offset = -1;
+static int hf_smb_lock_long_length = -1;
+static int hf_smb_file_type = -1;
+static int hf_smb_ipc_state_nonblocking = -1;
+static int hf_smb_ipc_state_endpoint = -1;
+static int hf_smb_ipc_state_pipe_type = -1;
+static int hf_smb_ipc_state_read_mode = -1;
+static int hf_smb_ipc_state_icount = -1;
+static int hf_smb_server_fid = -1;
+static int hf_smb_open_flags_add_info = -1;
+static int hf_smb_open_flags_ex_oplock = -1;
+static int hf_smb_open_flags_batch_oplock = -1;
+static int hf_smb_open_flags_ealen = -1;
+static int hf_smb_open_action_open = -1;
+static int hf_smb_open_action_lock = -1;
+static int hf_smb_vc_num = -1;
+static int hf_smb_account = -1;
+static int hf_smb_os = -1;
+static int hf_smb_lanman = -1;
+static int hf_smb_setup_action_guest = -1;
+static int hf_smb_fs = -1;
+static int hf_smb_connect_flags_dtid = -1;
+static int hf_smb_connect_support_search = -1;
+static int hf_smb_connect_support_in_dfs = -1;
+static int hf_smb_max_setup_count = -1;
+static int hf_smb_total_param_count = -1;
+static int hf_smb_total_data_count = -1;
+static int hf_smb_max_param_count = -1;
+static int hf_smb_max_data_count = -1;
+static int hf_smb_param_disp16 = -1;
+static int hf_smb_param_count16 = -1;
+static int hf_smb_param_offset16 = -1;
+static int hf_smb_param_disp32 = -1;
+static int hf_smb_param_count32 = -1;
+static int hf_smb_param_offset32 = -1;
+static int hf_smb_data_disp16 = -1;
+static int hf_smb_data_count16 = -1;
+static int hf_smb_data_offset16 = -1;
+static int hf_smb_data_disp32 = -1;
+static int hf_smb_data_count32 = -1;
+static int hf_smb_data_offset32 = -1;
+static int hf_smb_setup_count = -1;
+static int hf_smb_nt_trans_subcmd = -1;
+static int hf_smb_nt_ioctl_function_code = -1;
+static int hf_smb_nt_ioctl_isfsctl = -1;
+static int hf_smb_nt_ioctl_flags_root_handle = -1;
+static int hf_smb_nt_ioctl_data = -1;
+#ifdef SMB_UNUSED_HANDLES
+static int hf_smb_nt_security_information = -1;
+#endif
+static int hf_smb_nt_notify_action = -1;
+static int hf_smb_nt_notify_watch_tree = -1;
+static int hf_smb_nt_notify_stream_write = -1;
+static int hf_smb_nt_notify_stream_size = -1;
+static int hf_smb_nt_notify_stream_name = -1;
+static int hf_smb_nt_notify_security = -1;
+static int hf_smb_nt_notify_ea = -1;
+static int hf_smb_nt_notify_creation = -1;
+static int hf_smb_nt_notify_last_access = -1;
+static int hf_smb_nt_notify_last_write = -1;
+static int hf_smb_nt_notify_size = -1;
+static int hf_smb_nt_notify_attributes = -1;
+static int hf_smb_nt_notify_dir_name = -1;
+static int hf_smb_nt_notify_file_name = -1;
+static int hf_smb_root_dir_fid = -1;
+static int hf_smb_nt_create_disposition = -1;
+static int hf_smb_sd_length = -1;
+static int hf_smb_ea_list_length = -1;
+static int hf_smb_ea_flags = -1;
+static int hf_smb_ea_name_length = -1;
+static int hf_smb_ea_data_length = -1;
+static int hf_smb_ea_name = -1;
+static int hf_smb_ea_data = -1;
+static int hf_smb_file_name_len = -1;
+static int hf_smb_nt_impersonation_level = -1;
+static int hf_smb_nt_security_flags_context_tracking = -1;
+static int hf_smb_nt_security_flags_effective_only = -1;
+static int hf_smb_nt_access_mask_generic_read = -1;
+static int hf_smb_nt_access_mask_generic_write = -1;
+static int hf_smb_nt_access_mask_generic_execute = -1;
+static int hf_smb_nt_access_mask_generic_all = -1;
+static int hf_smb_nt_access_mask_maximum_allowed = -1;
+static int hf_smb_nt_access_mask_system_security = -1;
+static int hf_smb_nt_access_mask_synchronize = -1;
+static int hf_smb_nt_access_mask_write_owner = -1;
+static int hf_smb_nt_access_mask_write_dac = -1;
+static int hf_smb_nt_access_mask_read_control = -1;
+static int hf_smb_nt_access_mask_delete = -1;
+static int hf_smb_nt_access_mask_write_attributes = -1;
+static int hf_smb_nt_access_mask_read_attributes = -1;
+static int hf_smb_nt_access_mask_delete_child = -1;
+static int hf_smb_nt_access_mask_execute = -1;
+static int hf_smb_nt_access_mask_write_ea = -1;
+static int hf_smb_nt_access_mask_read_ea = -1;
+static int hf_smb_nt_access_mask_append = -1;
+static int hf_smb_nt_access_mask_write = -1;
+static int hf_smb_nt_access_mask_read = -1;
+static int hf_smb_nt_create_bits_oplock = -1;
+static int hf_smb_nt_create_bits_boplock = -1;
+static int hf_smb_nt_create_bits_dir = -1;
+static int hf_smb_nt_create_bits_ext_resp = -1;
+static int hf_smb_nt_create_options_directory_file = -1;
+static int hf_smb_nt_create_options_write_through = -1;
+static int hf_smb_nt_create_options_sequential_only = -1;
+static int hf_smb_nt_create_options_sync_io_alert = -1;
+static int hf_smb_nt_create_options_sync_io_nonalert = -1;
+static int hf_smb_nt_create_options_non_directory_file = -1;
+static int hf_smb_nt_create_options_no_ea_knowledge = -1;
+static int hf_smb_nt_create_options_eight_dot_three_only = -1;
+static int hf_smb_nt_create_options_random_access = -1;
+static int hf_smb_nt_create_options_delete_on_close = -1;
+static int hf_smb_nt_share_access_read = -1;
+static int hf_smb_nt_share_access_write = -1;
+static int hf_smb_nt_share_access_delete = -1;
+static int hf_smb_file_eattr_read_only = -1;
+static int hf_smb_file_eattr_hidden = -1;
+static int hf_smb_file_eattr_system = -1;
+static int hf_smb_file_eattr_volume = -1;
+static int hf_smb_file_eattr_directory = -1;
+static int hf_smb_file_eattr_archive = -1;
+static int hf_smb_file_eattr_device = -1;
+static int hf_smb_file_eattr_normal = -1;
+static int hf_smb_file_eattr_temporary = -1;
+static int hf_smb_file_eattr_sparse = -1;
+static int hf_smb_file_eattr_reparse = -1;
+static int hf_smb_file_eattr_compressed = -1;
+static int hf_smb_file_eattr_offline = -1;
+static int hf_smb_file_eattr_not_content_indexed = -1;
+static int hf_smb_file_eattr_encrypted = -1;
+static int hf_smb_sec_desc_len = -1;
+static int hf_smb_sec_desc_revision = -1;
+static int hf_smb_sec_desc_type_owner_defaulted = -1;
+static int hf_smb_sec_desc_type_group_defaulted = -1;
+static int hf_smb_sec_desc_type_dacl_present = -1;
+static int hf_smb_sec_desc_type_dacl_defaulted = -1;
+static int hf_smb_sec_desc_type_sacl_present = -1;
+static int hf_smb_sec_desc_type_sacl_defaulted = -1;
+static int hf_smb_sec_desc_type_dacl_auto_inherit_req = -1;
+static int hf_smb_sec_desc_type_sacl_auto_inherit_req = -1;
+static int hf_smb_sec_desc_type_dacl_auto_inherited = -1;
+static int hf_smb_sec_desc_type_sacl_auto_inherited = -1;
+static int hf_smb_sec_desc_type_dacl_protected = -1;
+static int hf_smb_sec_desc_type_sacl_protected = -1;
+static int hf_smb_sec_desc_type_self_relative = -1;
+static int hf_smb_sid = -1;
+static int hf_smb_sid_revision = -1;
+static int hf_smb_sid_num_auth = -1;
+static int hf_smb_acl_revision = -1;
+static int hf_smb_acl_size = -1;
+static int hf_smb_acl_num_aces = -1;
+static int hf_smb_ace_type = -1;
+static int hf_smb_ace_size = -1;
+static int hf_smb_ace_flags_object_inherit = -1;
+static int hf_smb_ace_flags_container_inherit = -1;
+static int hf_smb_ace_flags_non_propagate_inherit = -1;
+static int hf_smb_ace_flags_inherit_only = -1;
+static int hf_smb_ace_flags_inherited_ace = -1;
+static int hf_smb_ace_flags_successful_access = -1;
+static int hf_smb_ace_flags_failed_access = -1;
+static int hf_smb_nt_qsd_owner = -1;
+static int hf_smb_nt_qsd_group = -1;
+static int hf_smb_nt_qsd_dacl = -1;
+static int hf_smb_nt_qsd_sacl = -1;
+static int hf_smb_extended_attributes = -1;
+static int hf_smb_oplock_level = -1;
+static int hf_smb_create_action = -1;
+static int hf_smb_file_id = -1;
+static int hf_smb_ea_error_offset = -1;
+static int hf_smb_end_of_file = -1;
+static int hf_smb_replace = -1;
+static int hf_smb_root_dir_handle = -1;
+static int hf_smb_target_name_len = -1;
+static int hf_smb_target_name = -1;
+static int hf_smb_device_type = -1;
+static int hf_smb_is_directory = -1;
+static int hf_smb_next_entry_offset = -1;
+static int hf_smb_change_time = -1;
+static int hf_smb_setup_len = -1;
+static int hf_smb_print_mode = -1;
+static int hf_smb_print_identifier = -1;
+static int hf_smb_restart_index = -1;
+static int hf_smb_print_queue_date = -1;
+static int hf_smb_print_queue_dos_date = -1;
+static int hf_smb_print_queue_dos_time = -1;
+static int hf_smb_print_status = -1;
+static int hf_smb_print_spool_file_number = -1;
+static int hf_smb_print_spool_file_size = -1;
+static int hf_smb_print_spool_file_name = -1;
+static int hf_smb_start_index = -1;
+static int hf_smb_originator_name = -1;
+static int hf_smb_destination_name = -1;
+static int hf_smb_message_len = -1;
+static int hf_smb_message = -1;
+static int hf_smb_mgid = -1;
+static int hf_smb_forwarded_name = -1;
+static int hf_smb_machine_name = -1;
+static int hf_smb_cancel_to = -1;
+static int hf_smb_trans2_subcmd = -1;
+static int hf_smb_trans_name = -1;
+static int hf_smb_transaction_flags_dtid = -1;
+static int hf_smb_transaction_flags_owt = -1;
+static int hf_smb_search_count = -1;
+static int hf_smb_search_pattern = -1;
+static int hf_smb_ff2_backup = -1;
+static int hf_smb_ff2_continue = -1;
+static int hf_smb_ff2_resume = -1;
+static int hf_smb_ff2_close_eos = -1;
+static int hf_smb_ff2_close = -1;
+static int hf_smb_ff2_information_level = -1;
+static int hf_smb_qpi_loi = -1;
+static int hf_smb_spi_loi = -1;
+#if 0
+static int hf_smb_sfi_writetru = -1;
+static int hf_smb_sfi_caching = -1;
+#endif
+static int hf_smb_storage_type = -1;
+static int hf_smb_resume = -1;
+static int hf_smb_max_referral_level = -1;
+static int hf_smb_qfsi_information_level = -1;
+static int hf_smb_number_of_links = -1;
+static int hf_smb_delete_pending = -1;
+static int hf_smb_index_number = -1;
+static int hf_smb_current_offset = -1;
+static int hf_smb_t2_alignment = -1;
+static int hf_smb_t2_stream_name_length = -1;
+static int hf_smb_t2_stream_size = -1;
+static int hf_smb_t2_stream_name = -1;
+static int hf_smb_t2_compressed_file_size = -1;
+static int hf_smb_t2_compressed_format = -1;
+static int hf_smb_t2_compressed_unit_shift = -1;
+static int hf_smb_t2_compressed_chunk_shift = -1;
+static int hf_smb_t2_compressed_cluster_shift = -1;
+static int hf_smb_t2_marked_for_deletion = -1;
+static int hf_smb_dfs_path_consumed = -1;
+static int hf_smb_dfs_num_referrals = -1;
+static int hf_smb_get_dfs_server_hold_storage = -1;
+static int hf_smb_get_dfs_fielding = -1;
+static int hf_smb_dfs_referral_version = -1;
+static int hf_smb_dfs_referral_size = -1;
+static int hf_smb_dfs_referral_server_type = -1;
+static int hf_smb_dfs_referral_flags_strip = -1;
+static int hf_smb_dfs_referral_node_offset = -1;
+static int hf_smb_dfs_referral_node = -1;
+static int hf_smb_dfs_referral_proximity = -1;
+static int hf_smb_dfs_referral_ttl = -1;
+static int hf_smb_dfs_referral_path_offset = -1;
+static int hf_smb_dfs_referral_path = -1;
+static int hf_smb_dfs_referral_alt_path_offset = -1;
+static int hf_smb_dfs_referral_alt_path = -1;
+static int hf_smb_end_of_search = -1;
+static int hf_smb_last_name_offset = -1;
+static int hf_smb_fn_information_level = -1;
+static int hf_smb_monitor_handle = -1;
+static int hf_smb_change_count = -1;
+static int hf_smb_file_index = -1;
+static int hf_smb_short_file_name = -1;
+static int hf_smb_short_file_name_len = -1;
+static int hf_smb_fs_id = -1;
+static int hf_smb_fs_guid = -1;
+static int hf_smb_sector_unit = -1;
+static int hf_smb_fs_units = -1;
+static int hf_smb_fs_sector = -1;
+static int hf_smb_avail_units = -1;
+static int hf_smb_volume_serial_num = -1;
+static int hf_smb_volume_label_len = -1;
+static int hf_smb_volume_label = -1;
+static int hf_smb_free_alloc_units64 = -1;
+static int hf_smb_caller_free_alloc_units64 = -1;
+static int hf_smb_actual_free_alloc_units64 = -1;
+static int hf_smb_max_name_len = -1;
+static int hf_smb_fs_name_len = -1;
+static int hf_smb_fs_name = -1;
+static int hf_smb_device_char_removable = -1;
+static int hf_smb_device_char_read_only = -1;
+static int hf_smb_device_char_floppy = -1;
+static int hf_smb_device_char_write_once = -1;
+static int hf_smb_device_char_remote = -1;
+static int hf_smb_device_char_mounted = -1;
+static int hf_smb_device_char_virtual = -1;
+static int hf_smb_fs_attr_css = -1;
+static int hf_smb_fs_attr_cpn = -1;
+static int hf_smb_fs_attr_pacls = -1;
+static int hf_smb_fs_attr_fc = -1;
+static int hf_smb_fs_attr_vq = -1;
+static int hf_smb_fs_attr_dim = -1;
+static int hf_smb_fs_attr_vic = -1;
+static int hf_smb_quota_flags_enabled = -1;
+static int hf_smb_quota_flags_deny_disk = -1;
+static int hf_smb_quota_flags_log_limit = -1;
+static int hf_smb_quota_flags_log_warning = -1;
+static int hf_smb_soft_quota_limit = -1;
+static int hf_smb_hard_quota_limit = -1;
+static int hf_smb_user_quota_used = -1;
+static int hf_smb_user_quota_offset = -1;
+static int hf_smb_nt_rename_level = -1;
+static int hf_smb_cluster_count = -1;
+static int hf_smb_segments = -1;
+static int hf_smb_segment = -1;
+static int hf_smb_segment_overlap = -1;
+static int hf_smb_segment_overlap_conflict = -1;
+static int hf_smb_segment_multiple_tails = -1;
+static int hf_smb_segment_too_long_fragment = -1;
+static int hf_smb_segment_error = -1;
+static int hf_smb_pipe_write_len = -1;
+static int hf_smb_unix_major_version = -1;
+static int hf_smb_unix_minor_version = -1;
+static int hf_smb_unix_capability_fcntl = -1;
+static int hf_smb_unix_capability_posix_acl = -1;
+static int hf_smb_unix_file_size = -1;
+static int hf_smb_unix_file_num_bytes = -1;
+static int hf_smb_unix_file_last_status = -1;
+static int hf_smb_unix_file_last_access = -1;
+static int hf_smb_unix_file_last_change = -1;
+static int hf_smb_unix_file_uid = -1;
+static int hf_smb_unix_file_gid = -1;
+static int hf_smb_unix_file_type = -1;
+static int hf_smb_unix_file_dev_major = -1;
+static int hf_smb_unix_file_dev_minor = -1;
+static int hf_smb_unix_file_unique_id = -1;
+static int hf_smb_unix_file_permissions = -1;
+static int hf_smb_unix_file_nlinks = -1;
+static int hf_smb_unix_file_link_dest = -1;
+static int hf_smb_unix_find_file_nextoffset = -1;
+static int hf_smb_unix_find_file_resumekey = -1;
+
+static gint ett_smb = -1;
+static gint ett_smb_hdr = -1;
+static gint ett_smb_command = -1;
+static gint ett_smb_fileattributes = -1;
+static gint ett_smb_capabilities = -1;
+static gint ett_smb_aflags = -1;
+static gint ett_smb_dialect = -1;
+static gint ett_smb_dialects = -1;
+static gint ett_smb_mode = -1;
+static gint ett_smb_rawmode = -1;
+static gint ett_smb_flags = -1;
+static gint ett_smb_flags2 = -1;
+static gint ett_smb_desiredaccess = -1;
+static gint ett_smb_search = -1;
+static gint ett_smb_file = -1;
+static gint ett_smb_openfunction = -1;
+static gint ett_smb_filetype = -1;
+static gint ett_smb_openaction = -1;
+static gint ett_smb_writemode = -1;
+static gint ett_smb_lock_type = -1;
+static gint ett_smb_ssetupandxaction = -1;
+static gint ett_smb_optionsup = -1;
+static gint ett_smb_time_date = -1;
+static gint ett_smb_move_copy_flags = -1;
+static gint ett_smb_file_attributes = -1;
+static gint ett_smb_search_resume_key = -1;
+static gint ett_smb_search_dir_info = -1;
+static gint ett_smb_unlocks = -1;
+static gint ett_smb_unlock = -1;
+static gint ett_smb_locks = -1;
+static gint ett_smb_lock = -1;
+static gint ett_smb_open_flags = -1;
+static gint ett_smb_ipc_state = -1;
+static gint ett_smb_open_action = -1;
+static gint ett_smb_setup_action = -1;
+static gint ett_smb_connect_flags = -1;
+static gint ett_smb_connect_support_bits = -1;
+static gint ett_smb_nt_access_mask = -1;
+static gint ett_smb_nt_create_bits = -1;
+static gint ett_smb_nt_create_options = -1;
+static gint ett_smb_nt_share_access = -1;
+static gint ett_smb_nt_security_flags = -1;
+static gint ett_smb_nt_trans_setup = -1;
+static gint ett_smb_nt_trans_data = -1;
+static gint ett_smb_nt_trans_param = -1;
+static gint ett_smb_nt_notify_completion_filter = -1;
+static gint ett_smb_nt_ioctl_flags = -1;
+static gint ett_smb_security_information_mask = -1;
+static gint ett_smb_print_queue_entry = -1;
+static gint ett_smb_transaction_flags = -1;
+static gint ett_smb_transaction_params = -1;
+static gint ett_smb_find_first2_flags = -1;
+static gint ett_smb_mac_support_flags = -1;
+#if 0
+static gint ett_smb_ioflag = -1;
+#endif
+static gint ett_smb_transaction_data = -1;
+static gint ett_smb_stream_info = -1;
+static gint ett_smb_dfs_referrals = -1;
+static gint ett_smb_dfs_referral = -1;
+static gint ett_smb_dfs_referral_flags = -1;
+static gint ett_smb_get_dfs_flags = -1;
+static gint ett_smb_ff2_data = -1;
+static gint ett_smb_device_characteristics = -1;
+static gint ett_smb_fs_attributes = -1;
+static gint ett_smb_segments = -1;
+static gint ett_smb_segment = -1;
+static gint ett_smb_sec_desc = -1;
+static gint ett_smb_sid = -1;
+static gint ett_smb_acl = -1;
+static gint ett_smb_ace = -1;
+static gint ett_smb_ace_flags = -1;
+static gint ett_smb_sec_desc_type = -1;
+static gint ett_smb_quotaflags = -1;
+static gint ett_smb_secblob = -1;
+static gint ett_smb_unicode_password = -1;
+static gint ett_smb_ea = -1;
+static gint ett_smb_unix_capabilities = -1;
+
+static int smb_tap = -1;
+
+static dissector_handle_t gssapi_handle = NULL;
+static dissector_handle_t ntlmssp_handle = NULL;
+
+static const fragment_items smb_frag_items = {
+ &ett_smb_segment,
+ &ett_smb_segments,
+
+ &hf_smb_segments,
+ &hf_smb_segment,
+ &hf_smb_segment_overlap,
+ &hf_smb_segment_overlap_conflict,
+ &hf_smb_segment_multiple_tails,
+ &hf_smb_segment_too_long_fragment,
+ &hf_smb_segment_error,
+ NULL,
+
+ "segments"
+};
+
+proto_tree *top_tree=NULL; /* ugly */
+
+static char *decode_smb_name(guint8);
+static int dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *smb_tree, guint8 cmd, gboolean first_pdu);
+
+/*
+ * Macros for use in the main dissector routines for an SMB.
+ */
+
+#define WORD_COUNT \
+ /* Word Count */ \
+ wc = tvb_get_guint8(tvb, offset); \
+ proto_tree_add_uint(tree, hf_smb_word_count, \
+ tvb, offset, 1, wc); \
+ offset += 1; \
+ if(wc==0) goto bytecount;
+
+#define BYTE_COUNT \
+ bytecount: \
+ bc = tvb_get_letohs(tvb, offset); \
+ proto_tree_add_uint(tree, hf_smb_byte_count, \
+ tvb, offset, 2, bc); \
+ offset += 2; \
+ if(bc==0) goto endofcommand;
+
+#define CHECK_BYTE_COUNT(len) \
+ if (bc < len) goto endofcommand;
+
+#define COUNT_BYTES(len) {\
+ int tmp; \
+ tmp=len; \
+ offset += tmp; \
+ bc -= tmp; \
+ }
+
+#define END_OF_SMB \
+ if (bc != 0) { \
+ gint bc_remaining; \
+ bc_remaining=tvb_length_remaining(tvb, offset); \
+ if( ((gint)bc) > bc_remaining){ \
+ bc=bc_remaining; \
+ } \
+ if(bc){ \
+ proto_tree_add_text(tree, tvb, offset, bc, \
+ "Extra byte parameters"); \
+ } \
+ offset += bc; \
+ } \
+ endofcommand:
+
+/*
+ * Macros for use in routines called by them.
+ */
+#define CHECK_BYTE_COUNT_SUBR(len) \
+ if (*bcp < len) { \
+ *trunc = TRUE; \
+ return offset; \
+ }
+
+#define CHECK_STRING_SUBR(fn) \
+ if (fn == NULL) { \
+ *trunc = TRUE; \
+ return offset; \
+ }
+
+#define COUNT_BYTES_SUBR(len) \
+ offset += len; \
+ *bcp -= len;
+
+/*
+ * Macros for use when dissecting transaction parameters and data
+ */
+#define CHECK_BYTE_COUNT_TRANS(len) \
+ if (bc < len) return offset;
+
+#define CHECK_STRING_TRANS(fn) \
+ if (fn == NULL) return offset;
+
+#define COUNT_BYTES_TRANS(len) \
+ offset += len; \
+ bc -= len;
+
+/*
+ * Macros for use in subrroutines dissecting transaction parameters or data
+ */
+#define CHECK_BYTE_COUNT_TRANS_SUBR(len) \
+ if (*bcp < len) return offset;
+
+#define CHECK_STRING_TRANS_SUBR(fn) \
+ if (fn == NULL) return offset;
+
+#define COUNT_BYTES_TRANS_SUBR(len) \
+ offset += len; \
+ *bcp -= len;
+
+
+gboolean sid_name_snooping = FALSE;
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ These are needed by the reassembly of SMB Transaction payload and DCERPC over SMB
+ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+static gboolean smb_trans_reassembly = FALSE;
+gboolean smb_dcerpc_reassembly = FALSE;
+
+static GHashTable *smb_trans_fragment_table = NULL;
+
+static void
+smb_trans_reassembly_init(void)
+{
+ fragment_table_init(&smb_trans_fragment_table);
+}
+
+static fragment_data *
+smb_trans_defragment(proto_tree *tree _U_, packet_info *pinfo, tvbuff_t *tvb,
+ int offset, int count, int pos, int totlen)
+{
+ fragment_data *fd_head=NULL;
+ smb_info_t *si;
+ int more_frags;
+
+ more_frags=totlen>(pos+count);
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip == NULL) {
+ /*
+ * We don't have the frame number of the request.
+ *
+ * XXX - is there truly nothing we can do here?
+ * Can we not separately keep track of the original
+ * transaction and its continuations, as we did
+ * at one time?
+ *
+ * It is probably not much point in even trying to do something here
+ * if we have never seen the initial request. Without the initial
+ * request we probably miss all parameters and the begining of data
+ * so we cant even call a subdissector since we can not determine
+ * which type of transaction call this is.
+ */
+ return NULL;
+ }
+
+ if(!pinfo->fd->flags.visited){
+ fd_head = fragment_add(tvb, offset, pinfo,
+ si->sip->frame_req, smb_trans_fragment_table,
+ pos, count, more_frags);
+ } else {
+ fd_head = fragment_get(pinfo, si->sip->frame_req, smb_trans_fragment_table);
+ }
+
+ /* we only show the defragmented packet for the first fragment,
+ or else we might end up with dissecting one HUGE transaction PDU
+ a LOT of times. (first fragment is the only one containing the setup
+ bytes)
+ I have seen ONE Transaction PDU that is ~60kb, spanning many Transaction
+ SMBs. Takes a LOT of time dissecting and is not fun.
+ */
+ if( (pos==0) && fd_head && fd_head->flags&FD_DEFRAGMENTED){
+ return fd_head;
+ } else {
+ return NULL;
+ }
+}
+
+
+
+
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ These variables and functions are used to match
+ responses with calls
+ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+/*
+ * The information we need to save about a request in order to show the
+ * frame number of the request in the dissection of the reply.
+ */
+typedef struct {
+ guint32 frame;
+ guint32 pid_mid;
+} smb_saved_info_key_t;
+
+static GMemChunk *smb_saved_info_key_chunk = NULL;
+static GMemChunk *smb_saved_info_chunk = NULL;
+static int smb_saved_info_init_count = 200;
+
+/* unmatched smb_saved_info structures.
+ For unmatched smb_saved_info structures we store the smb_saved_info
+ structure using the MID and the PID as the key.
+
+ Oh, yes, the key is really a pointer, but we use it as if it was an integer.
+ Ugly, yes. Not portable to DEC-20 Yes. But it saves a few bytes.
+ The key is the PID in the upper 16 bits and the MID in the lower 16 bits.
+*/
+static gint
+smb_saved_info_equal_unmatched(gconstpointer k1, gconstpointer k2)
+{
+ register guint32 key1 = (guint32)k1;
+ register guint32 key2 = (guint32)k2;
+ return key1==key2;
+}
+static guint
+smb_saved_info_hash_unmatched(gconstpointer k)
+{
+ register guint32 key = (guint32)k;
+ return key;
+}
+
+/* matched smb_saved_info structures.
+ For matched smb_saved_info structures we store the smb_saved_info
+ structure twice in the table using the frame number, and a combination
+ of the MID and the PID, as the key.
+ The frame number is guaranteed to be unique but if ever someone makes
+ some change that will renumber the frames in a capture we are in BIG trouble.
+ This is not likely though since that would break (among other things) all the
+ reassembly routines as well.
+
+ We also need the MID as there may be more than one SMB request or reply
+ in a single frame, and we also need the PID as there may be more than
+ one outstanding request with the same MID and different PIDs.
+*/
+static gint
+smb_saved_info_equal_matched(gconstpointer k1, gconstpointer k2)
+{
+ const smb_saved_info_key_t *key1 = k1;
+ const smb_saved_info_key_t *key2 = k2;
+ return key1->frame == key2->frame && key1->pid_mid == key2->pid_mid;
+}
+static guint
+smb_saved_info_hash_matched(gconstpointer k)
+{
+ const smb_saved_info_key_t *key = k;
+ return key->frame + key->pid_mid;
+}
+
+static GMemChunk *smb_nt_transact_info_chunk = NULL;
+static int smb_nt_transact_info_init_count = 200;
+
+static GMemChunk *smb_transact2_info_chunk = NULL;
+static int smb_transact2_info_init_count = 200;
+
+/*
+ * The information we need to save about a Transaction request in order
+ * to dissect the reply; this includes information for use by the
+ * Remote API dissector.
+ */
+static GMemChunk *smb_transact_info_chunk = NULL;
+static int smb_transact_info_init_count = 200;
+
+static GMemChunk *conv_tables_chunk = NULL;
+static GSList *conv_tables = NULL;
+static int conv_tables_count = 10;
+
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ End of request/response matching functions
+ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+
+static const value_string buffer_format_vals[] = {
+ {1, "Data Block"},
+ {2, "Dialect"},
+ {3, "Pathname"},
+ {4, "ASCII"},
+ {5, "Variable Block"},
+ {0, NULL}
+};
+
+/*
+ * UTIME - this is *almost* like a UNIX time stamp, except that it's
+ * in seconds since January 1, 1970, 00:00:00 *local* time, not since
+ * January 1, 1970, 00:00:00 GMT.
+ *
+ * This means we have to do some extra work to convert it. This code is
+ * based on the Samba code:
+ *
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * time handling functions
+ * Copyright (C) Andrew Tridgell 1992-1998
+ */
+
+/*
+ * Yield the difference between *A and *B, in seconds, ignoring leap
+ * seconds.
+ */
+#define TM_YEAR_BASE 1900
+
+static int
+tm_diff(struct tm *a, struct tm *b)
+{
+ int ay = a->tm_year + (TM_YEAR_BASE - 1);
+ int by = b->tm_year + (TM_YEAR_BASE - 1);
+ int intervening_leap_days =
+ (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
+ int years = ay - by;
+ int days =
+ 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
+ int hours = 24*days + (a->tm_hour - b->tm_hour);
+ int minutes = 60*hours + (a->tm_min - b->tm_min);
+ int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
+
+ return seconds;
+}
+
+/*
+ * Return the UTC offset in seconds west of UTC, or 0 if it cannot be
+ * determined.
+ */
+static int
+TimeZone(time_t t)
+{
+ struct tm *tm = gmtime(&t);
+ struct tm tm_utc;
+
+ if (tm == NULL)
+ return 0;
+ tm_utc = *tm;
+ tm = localtime(&t);
+ if (tm == NULL)
+ return 0;
+ return tm_diff(&tm_utc,tm);
+}
+
+/*
+ * Return the same value as TimeZone, but it should be more efficient.
+ *
+ * We keep a table of DST offsets to prevent calling localtime() on each
+ * call of this function. This saves a LOT of time on many unixes.
+ *
+ * Updated by Paul Eggert <eggert@twinsun.com>
+ */
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#ifndef TIME_T_MIN
+#define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
+ : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
+#endif
+#ifndef TIME_T_MAX
+#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
+#endif
+
+static int
+TimeZoneFaster(time_t t)
+{
+ static struct dst_table {time_t start,end; int zone;} *tdt;
+ static struct dst_table *dst_table = NULL;
+ static int table_size = 0;
+ int i;
+ int zone = 0;
+
+ if (t == 0)
+ t = time(NULL);
+
+ /* Tunis has a 8 day DST region, we need to be careful ... */
+#define MAX_DST_WIDTH (365*24*60*60)
+#define MAX_DST_SKIP (7*24*60*60)
+
+ for (i = 0; i < table_size; i++) {
+ if (t >= dst_table[i].start && t <= dst_table[i].end)
+ break;
+ }
+
+ if (i < table_size) {
+ zone = dst_table[i].zone;
+ } else {
+ time_t low,high;
+
+ zone = TimeZone(t);
+ if (dst_table == NULL)
+ tdt = g_malloc(sizeof(dst_table[0])*(i+1));
+ else
+ tdt = g_realloc(dst_table, sizeof(dst_table[0])*(i+1));
+ if (tdt == NULL) {
+ if (dst_table)
+ g_free(dst_table);
+ table_size = 0;
+ } else {
+ dst_table = tdt;
+ table_size++;
+
+ dst_table[i].zone = zone;
+ dst_table[i].start = dst_table[i].end = t;
+
+ /* no entry will cover more than 6 months */
+ low = t - MAX_DST_WIDTH/2;
+ if (t < low)
+ low = TIME_T_MIN;
+
+ high = t + MAX_DST_WIDTH/2;
+ if (high < t)
+ high = TIME_T_MAX;
+
+ /*
+ * Widen the new entry using two bisection searches.
+ */
+ while (low+60*60 < dst_table[i].start) {
+ if (dst_table[i].start - low > MAX_DST_SKIP*2)
+ t = dst_table[i].start - MAX_DST_SKIP;
+ else
+ t = low + (dst_table[i].start-low)/2;
+ if (TimeZone(t) == zone)
+ dst_table[i].start = t;
+ else
+ low = t;
+ }
+
+ while (high-60*60 > dst_table[i].end) {
+ if (high - dst_table[i].end > MAX_DST_SKIP*2)
+ t = dst_table[i].end + MAX_DST_SKIP;
+ else
+ t = high - (high-dst_table[i].end)/2;
+ if (TimeZone(t) == zone)
+ dst_table[i].end = t;
+ else
+ high = t;
+ }
+ }
+ }
+ return zone;
+}
+
+/*
+ * Return the UTC offset in seconds west of UTC, adjusted for extra time
+ * offset, for a local time value. If ut = lt + LocTimeDiff(lt), then
+ * lt = ut - TimeDiff(ut), but the converse does not necessarily hold near
+ * daylight savings transitions because some local times are ambiguous.
+ * LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions.
+ */
+static int
+LocTimeDiff(time_t lt)
+{
+ int d = TimeZoneFaster(lt);
+ time_t t = lt + d;
+
+ /* if overflow occurred, ignore all the adjustments so far */
+ if (((t < lt) ^ (d < 0)))
+ t = lt;
+
+ /*
+ * Now t should be close enough to the true UTC to yield the
+ * right answer.
+ */
+ return TimeZoneFaster(t);
+}
+
+static int
+dissect_smb_UTIME(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date)
+{
+ guint32 timeval;
+ nstime_t ts;
+
+ timeval = tvb_get_letohl(tvb, offset);
+ if (timeval == 0xffffffff) {
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "%s: No time specified (0xffffffff)",
+ proto_registrar_get_name(hf_date));
+ offset += 4;
+ return offset;
+ }
+
+ /*
+ * We add the local time offset.
+ */
+ ts.secs = timeval + LocTimeDiff(timeval);
+ ts.nsecs = 0;
+
+ proto_tree_add_time(tree, hf_date, tvb, offset, 4, &ts);
+ offset += 4;
+
+ return offset;
+}
+
+#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
+
+/*
+ * Translate an 8-byte FILETIME value, given as the upper and lower 32 bits,
+ * to an "nstime_t".
+ * A FILETIME is a 64-bit integer, giving the time since Jan 1, 1601,
+ * midnight "UTC", in 100ns units.
+ * Return TRUE if the conversion succeeds, FALSE otherwise.
+ *
+ * According to the Samba code, it appears to be kludge-GMT (at least for
+ * file listings). This means it's the GMT you get by taking a local time
+ * and adding the server time zone offset. This is NOT the same as GMT in
+ * some cases. However, we don't know the server time zone, so we don't
+ * do that adjustment.
+ *
+ * This code is based on the Samba code:
+ *
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * time handling functions
+ * Copyright (C) Andrew Tridgell 1992-1998
+ */
+static gboolean
+nt_time_to_nstime(guint32 filetime_high, guint32 filetime_low, nstime_t *tv)
+{
+ double d;
+ /* The next two lines are a fix needed for the
+ broken SCO compiler. JRA. */
+ time_t l_time_min = TIME_T_MIN;
+ time_t l_time_max = TIME_T_MAX;
+
+ if (filetime_high == 0)
+ return FALSE;
+
+ /*
+ * Get the time as a double, in seconds and fractional seconds.
+ */
+ d = ((double)filetime_high)*4.0*(double)(1<<30);
+ d += filetime_low;
+ d *= 1.0e-7;
+
+ /* Now adjust by 369 years, to make the seconds since 1970. */
+ d -= TIME_FIXUP_CONSTANT;
+
+ if (!(l_time_min <= d && d <= l_time_max))
+ return FALSE;
+
+ /*
+ * Get the time as seconds and nanoseconds.
+ */
+ tv->secs = (time_t) d;
+ tv->nsecs = (int) ((d - tv->secs)*1000000000);
+
+ return TRUE;
+}
+
+int
+dissect_smb_64bit_time(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_date)
+{
+ guint32 filetime_high, filetime_low;
+ nstime_t ts;
+
+ /* XXX there seems also to be another special time value which is fairly common :
+ 0x40000000 00000000
+ the meaning of this one is yet unknown
+ */
+ if (tree) {
+ filetime_low = tvb_get_letohl(tvb, offset);
+ filetime_high = tvb_get_letohl(tvb, offset + 4);
+ if (filetime_low == 0 && filetime_high == 0) {
+ proto_tree_add_text(tree, tvb, offset, 8,
+ "%s: No time specified (0)",
+ proto_registrar_get_name(hf_date));
+ } else if(filetime_low==0 && filetime_high==0x80000000){
+ proto_tree_add_text(tree, tvb, offset, 8,
+ "%s: Infinity (relative time)",
+ proto_registrar_get_name(hf_date));
+ } else if(filetime_low==0xffffffff && filetime_high==0x7fffffff){
+ proto_tree_add_text(tree, tvb, offset, 8,
+ "%s: Infinity (absolute time)",
+ proto_registrar_get_name(hf_date));
+ } else {
+ if (nt_time_to_nstime(filetime_high, filetime_low, &ts)) {
+ proto_tree_add_time(tree, hf_date, tvb,
+ offset, 8, &ts);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 8,
+ "%s: Time can't be converted",
+ proto_registrar_get_name(hf_date));
+ }
+ }
+ }
+
+ offset += 8;
+ return offset;
+}
+
+static int
+dissect_smb_datetime(tvbuff_t *tvb, proto_tree *parent_tree, int offset,
+ int hf_date, int hf_dos_date, int hf_dos_time, gboolean time_first)
+{
+ guint16 dos_time, dos_date;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ struct tm tm;
+ time_t t;
+ static const int mday_noleap[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ static const int mday_leap[12] = {
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+#define ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+ nstime_t tv;
+
+ if (time_first) {
+ dos_time = tvb_get_letohs(tvb, offset);
+ dos_date = tvb_get_letohs(tvb, offset+2);
+ } else {
+ dos_date = tvb_get_letohs(tvb, offset);
+ dos_time = tvb_get_letohs(tvb, offset+2);
+ }
+
+ if ((dos_date == 0xffff && dos_time == 0xffff) ||
+ (dos_date == 0 && dos_time == 0)) {
+ /*
+ * No date/time specified.
+ */
+ if(parent_tree){
+ proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "%s: No time specified (0x%08x)",
+ proto_registrar_get_name(hf_date),
+ (dos_date << 16) | dos_time);
+ }
+ offset += 4;
+ return offset;
+ }
+
+ tm.tm_sec = (dos_time&0x1f)*2;
+ tm.tm_min = (dos_time>>5)&0x3f;
+ tm.tm_hour = (dos_time>>11)&0x1f;
+ tm.tm_mday = dos_date&0x1f;
+ tm.tm_mon = ((dos_date>>5)&0x0f) - 1;
+ tm.tm_year = ((dos_date>>9)&0x7f) + 1980 - 1900;
+ tm.tm_isdst = -1;
+
+ /*
+ * Do some sanity checks before calling "mktime()";
+ * "mktime()" doesn't do them, it "normalizes" out-of-range
+ * values.
+ */
+ if (tm.tm_sec > 59 || tm.tm_min > 59 || tm.tm_hour > 23 ||
+ tm.tm_mon < 0 || tm.tm_mon > 11 ||
+ (ISLEAP(tm.tm_year + 1900) ?
+ tm.tm_mday > mday_leap[tm.tm_mon] :
+ tm.tm_mday > mday_noleap[tm.tm_mon]) ||
+ (t = mktime(&tm)) == -1) {
+ /*
+ * Invalid date/time.
+ */
+ if (parent_tree) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "%s: Invalid time",
+ proto_registrar_get_name(hf_date));
+ tree = proto_item_add_subtree(item, ett_smb_time_date);
+ if (time_first) {
+ proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
+ proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset+2, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
+ } else {
+ proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
+ proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset+2, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
+ }
+ }
+ offset += 4;
+ return offset;
+ }
+
+ tv.secs = t;
+ tv.nsecs = 0;
+
+ if(parent_tree){
+ item = proto_tree_add_time(parent_tree, hf_date, tvb, offset, 4, &tv);
+ tree = proto_item_add_subtree(item, ett_smb_time_date);
+ if (time_first) {
+ proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
+ proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset+2, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
+ } else {
+ proto_tree_add_uint_format(tree, hf_dos_date, tvb, offset, 2, dos_date, "DOS Date: %04d-%02d-%02d (0x%04x)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, dos_date);
+ proto_tree_add_uint_format(tree, hf_dos_time, tvb, offset+2, 2, dos_time, "DOS Time: %02d:%02d:%02d (0x%04x)", tm.tm_hour, tm.tm_min, tm.tm_sec, dos_time);
+ }
+ }
+
+ offset += 4;
+
+ return offset;
+}
+
+
+static const value_string da_access_vals[] = {
+ { 0, "Open for reading"},
+ { 1, "Open for writing"},
+ { 2, "Open for reading and writing"},
+ { 3, "Open for execute"},
+ {0, NULL}
+};
+static const value_string da_sharing_vals[] = {
+ { 0, "Compatibility mode"},
+ { 1, "Deny read/write/execute (exclusive)"},
+ { 2, "Deny write"},
+ { 3, "Deny read/execute"},
+ { 4, "Deny none"},
+ {0, NULL}
+};
+static const value_string da_locality_vals[] = {
+ { 0, "Locality of reference unknown"},
+ { 1, "Mainly sequential access"},
+ { 2, "Mainly random access"},
+ { 3, "Random access with some locality"},
+ {0, NULL}
+};
+static const true_false_string tfs_da_caching = {
+ "Do not cache this file",
+ "Caching permitted on this file"
+};
+static const true_false_string tfs_da_writetru = {
+ "Write through enabled",
+ "Write through disabled"
+};
+static int
+dissect_access(tvbuff_t *tvb, proto_tree *parent_tree, int offset, char *type)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "%s Access: 0x%04x", type, mask);
+ tree = proto_item_add_subtree(item, ett_smb_desiredaccess);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_access_writetru,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_access_caching,
+ tvb, offset, 2, mask);
+ proto_tree_add_uint(tree, hf_smb_access_locality,
+ tvb, offset, 2, mask);
+ proto_tree_add_uint(tree, hf_smb_access_sharing,
+ tvb, offset, 2, mask);
+ proto_tree_add_uint(tree, hf_smb_access_mode,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+#define SMB_FILE_ATTRIBUTE_READ_ONLY 0x00000001
+#define SMB_FILE_ATTRIBUTE_HIDDEN 0x00000002
+#define SMB_FILE_ATTRIBUTE_SYSTEM 0x00000004
+#define SMB_FILE_ATTRIBUTE_VOLUME 0x00000008
+#define SMB_FILE_ATTRIBUTE_DIRECTORY 0x00000010
+#define SMB_FILE_ATTRIBUTE_ARCHIVE 0x00000020
+#define SMB_FILE_ATTRIBUTE_DEVICE 0x00000040
+#define SMB_FILE_ATTRIBUTE_NORMAL 0x00000080
+#define SMB_FILE_ATTRIBUTE_TEMPORARY 0x00000100
+#define SMB_FILE_ATTRIBUTE_SPARSE 0x00000200
+#define SMB_FILE_ATTRIBUTE_REPARSE 0x00000400
+#define SMB_FILE_ATTRIBUTE_COMPRESSED 0x00000800
+#define SMB_FILE_ATTRIBUTE_OFFLINE 0x00001000
+#define SMB_FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
+#define SMB_FILE_ATTRIBUTE_ENCRYPTED 0x00004000
+
+static const true_false_string tfs_file_attribute_read_only = {
+ "This file is READ ONLY",
+ "This file is NOT read only",
+};
+static const true_false_string tfs_file_attribute_hidden = {
+ "This is a HIDDEN file",
+ "This is NOT a hidden file"
+};
+static const true_false_string tfs_file_attribute_system = {
+ "This is a SYSTEM file",
+ "This is NOT a system file"
+};
+static const true_false_string tfs_file_attribute_volume = {
+ "This is a VOLUME ID",
+ "This is NOT a volume ID"
+};
+static const true_false_string tfs_file_attribute_directory = {
+ "This is a DIRECTORY",
+ "This is NOT a directory"
+};
+static const true_false_string tfs_file_attribute_archive = {
+ "This file has been modified since last ARCHIVE",
+ "This file has NOT been modified since last archive"
+};
+static const true_false_string tfs_file_attribute_device = {
+ "This is a DEVICE",
+ "This is NOT a device"
+};
+static const true_false_string tfs_file_attribute_normal = {
+ "This file is an ordinary file",
+ "This file has some attribute set"
+};
+static const true_false_string tfs_file_attribute_temporary = {
+ "This is a TEMPORARY file",
+ "This is NOT a temporary file"
+};
+static const true_false_string tfs_file_attribute_sparse = {
+ "This is a SPARSE file",
+ "This is NOT a sparse file"
+};
+static const true_false_string tfs_file_attribute_reparse = {
+ "This file has an associated REPARSE POINT",
+ "This file does NOT have an associated reparse point"
+};
+static const true_false_string tfs_file_attribute_compressed = {
+ "This is a COMPRESSED file",
+ "This is NOT a compressed file"
+};
+static const true_false_string tfs_file_attribute_offline = {
+ "This file is OFFLINE",
+ "This file is NOT offline"
+};
+static const true_false_string tfs_file_attribute_not_content_indexed = {
+ "This file MAY NOT be indexed by the CONTENT INDEXING service",
+ "This file MAY be indexed by the content indexing service"
+};
+static const true_false_string tfs_file_attribute_encrypted = {
+ "This is an ENCRYPTED file",
+ "This is NOT an encrypted file"
+};
+
+/*
+ * In some places in the CIFS_TR_1p00.pdf, from SNIA, file attributes are
+ * listed as USHORT, and seem to be in packets in the wild, while in other
+ * places they are listed as ULONG, and also seem to be.
+ *
+ * So, I (Richard Sharpe), added a parameter to allow us to specify how many
+ * bytes to consume.
+ */
+
+static int
+dissect_file_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset,
+ int bytes)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ if (bytes != 2 && bytes != 4) {
+
+ fprintf(stderr, "Incorrect number of bytes passed to dissect_file_attributes.\nMust be 2 or 4, was %d\n", bytes);
+ exit(1);
+
+ }
+
+ /*
+ * The actual bits of interest appear to only be a USHORT
+ */
+ /* FIXME if this ever changes! */
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, bytes,
+ "File Attributes: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_file_attributes);
+ }
+ proto_tree_add_boolean(tree, hf_smb_file_attr_encrypted,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_not_content_indexed,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_offline,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_compressed,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_reparse,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_sparse,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_temporary,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_normal,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_device,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
+ tvb, offset, bytes, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
+ tvb, offset, bytes, mask);
+
+ offset += bytes;
+
+ return offset;
+}
+
+/* 3.11 */
+static int
+dissect_file_ext_attr(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "File Attributes: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_file_attributes);
+ }
+
+ /*
+ * XXX - Network Monitor disagrees on some of the
+ * bits, e.g. the bits above temporary are "atomic write"
+ * and "transaction write", and it says nothing about the
+ * bits above that.
+ *
+ * Does the Win32 API documentation, or the NT Native API book,
+ * suggest anything?
+ */
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_encrypted,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_not_content_indexed,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_offline,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_compressed,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_reparse,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_sparse,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_temporary,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_normal,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_device,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_archive,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_directory,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_volume,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_system,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_hidden,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_eattr_read_only,
+ tvb, offset, 4, mask);
+
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_dir_info_file_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint8 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_guint8(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+ "File Attributes: 0x%02x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_file_attributes);
+ }
+ proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_8bit,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_8bit,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_system_8bit,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_volume_8bit,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_directory_8bit,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_archive_8bit,
+ tvb, offset, 1, mask);
+
+ offset += 1;
+
+ return offset;
+}
+
+static const true_false_string tfs_search_attribute_read_only = {
+ "Include READ ONLY files in search results",
+ "Do NOT include read only files in search results",
+};
+static const true_false_string tfs_search_attribute_hidden = {
+ "Include HIDDEN files in search results",
+ "Do NOT include hidden files in search results"
+};
+static const true_false_string tfs_search_attribute_system = {
+ "Include SYSTEM files in search results",
+ "Do NOT include system files in search results"
+};
+static const true_false_string tfs_search_attribute_volume = {
+ "Include VOLUME IDs in search results",
+ "Do NOT include volume IDs in search results"
+};
+static const true_false_string tfs_search_attribute_directory = {
+ "Include DIRECTORIES in search results",
+ "Do NOT include directories in search results"
+};
+static const true_false_string tfs_search_attribute_archive = {
+ "Include ARCHIVE files in search results",
+ "Do NOT include archive files in search results"
+};
+
+static int
+dissect_search_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Search Attributes: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_search);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_search_attribute_read_only,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_search_attribute_hidden,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_search_attribute_system,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_search_attribute_volume,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_search_attribute_directory,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_search_attribute_archive,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+ return offset;
+}
+
+#if 0
+/*
+ * XXX - this isn't used.
+ * Is this used for anything? NT Create AndX doesn't use it.
+ * Is there some 16-bit attribute field with more bits than Read Only,
+ * Hidden, System, Volume ID, Directory, and Archive?
+ */
+static int
+dissect_extended_file_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "File Attributes: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_file_attributes);
+ }
+ proto_tree_add_boolean(tree, hf_smb_file_attr_read_only_16bit,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_hidden_16bit,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_system_16bit,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_volume_16bit,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_directory_16bit,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_archive_16bit,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_device,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_normal,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_temporary,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_sparse,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_reparse,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_compressed,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_offline,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_not_content_indexed,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_file_attr_encrypted,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+#endif
+
+
+#define SERVER_CAP_RAW_MODE 0x00000001
+#define SERVER_CAP_MPX_MODE 0x00000002
+#define SERVER_CAP_UNICODE 0x00000004
+#define SERVER_CAP_LARGE_FILES 0x00000008
+#define SERVER_CAP_NT_SMBS 0x00000010
+#define SERVER_CAP_RPC_REMOTE_APIS 0x00000020
+#define SERVER_CAP_STATUS32 0x00000040
+#define SERVER_CAP_LEVEL_II_OPLOCKS 0x00000080
+#define SERVER_CAP_LOCK_AND_READ 0x00000100
+#define SERVER_CAP_NT_FIND 0x00000200
+#define SERVER_CAP_DFS 0x00001000
+#define SERVER_CAP_INFOLEVEL_PASSTHRU 0x00002000
+#define SERVER_CAP_LARGE_READX 0x00004000
+#define SERVER_CAP_LARGE_WRITEX 0x00008000
+#define SERVER_CAP_UNIX 0x00800000
+#define SERVER_CAP_RESERVED 0x02000000
+#define SERVER_CAP_BULK_TRANSFER 0x20000000
+#define SERVER_CAP_COMPRESSED_DATA 0x40000000
+#define SERVER_CAP_EXTENDED_SECURITY 0x80000000
+static const true_false_string tfs_server_cap_raw_mode = {
+ "Read Raw and Write Raw are supported",
+ "Read Raw and Write Raw are not supported"
+};
+static const true_false_string tfs_server_cap_mpx_mode = {
+ "Read Mpx and Write Mpx are supported",
+ "Read Mpx and Write Mpx are not supported"
+};
+static const true_false_string tfs_server_cap_unicode = {
+ "Unicode strings are supported",
+ "Unicode strings are not supported"
+};
+static const true_false_string tfs_server_cap_large_files = {
+ "Large files are supported",
+ "Large files are not supported",
+};
+static const true_false_string tfs_server_cap_nt_smbs = {
+ "NT SMBs are supported",
+ "NT SMBs are not supported"
+};
+static const true_false_string tfs_server_cap_rpc_remote_apis = {
+ "RPC remote APIs are supported",
+ "RPC remote APIs are not supported"
+};
+static const true_false_string tfs_server_cap_nt_status = {
+ "NT status codes are supported",
+ "NT status codes are not supported"
+};
+static const true_false_string tfs_server_cap_level_ii_oplocks = {
+ "Level 2 oplocks are supported",
+ "Level 2 oplocks are not supported"
+};
+static const true_false_string tfs_server_cap_lock_and_read = {
+ "Lock and Read is supported",
+ "Lock and Read is not supported"
+};
+static const true_false_string tfs_server_cap_nt_find = {
+ "NT Find is supported",
+ "NT Find is not supported"
+};
+static const true_false_string tfs_server_cap_dfs = {
+ "Dfs is supported",
+ "Dfs is not supported"
+};
+static const true_false_string tfs_server_cap_infolevel_passthru = {
+ "NT information level request passthrough is supported",
+ "NT information level request passthrough is not supported"
+};
+static const true_false_string tfs_server_cap_large_readx = {
+ "Large Read andX is supported",
+ "Large Read andX is not supported"
+};
+static const true_false_string tfs_server_cap_large_writex = {
+ "Large Write andX is supported",
+ "Large Write andX is not supported"
+};
+static const true_false_string tfs_server_cap_unix = {
+ "UNIX extensions are supported",
+ "UNIX extensions are not supported"
+};
+static const true_false_string tfs_server_cap_reserved = {
+ "Reserved",
+ "Reserved"
+};
+static const true_false_string tfs_server_cap_bulk_transfer = {
+ "Bulk Read and Bulk Write are supported",
+ "Bulk Read and Bulk Write are not supported"
+};
+static const true_false_string tfs_server_cap_compressed_data = {
+ "Compressed data transfer is supported",
+ "Compressed data transfer is not supported"
+};
+static const true_false_string tfs_server_cap_extended_security = {
+ "Extended security exchanges are supported",
+ "Extended security exchanges are not supported"
+};
+static int
+dissect_negprot_capabilities(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4, "Capabilities: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_capabilities);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_server_cap_raw_mode,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_mpx_mode,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_unicode,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_large_files,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_nt_smbs,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_rpc_remote_apis,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_nt_status,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_level_ii_oplocks,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_lock_and_read,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_nt_find,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_dfs,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_infolevel_passthru,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_large_readx,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_large_writex,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_unix,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_reserved,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_bulk_transfer,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_compressed_data,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_server_cap_extended_security,
+ tvb, offset, 4, mask);
+
+ return mask;
+}
+
+#define RAWMODE_READ 0x01
+#define RAWMODE_WRITE 0x02
+static const true_false_string tfs_rm_read = {
+ "Read Raw is supported",
+ "Read Raw is not supported"
+};
+static const true_false_string tfs_rm_write = {
+ "Write Raw is supported",
+ "Write Raw is not supported"
+};
+
+static int
+dissect_negprot_rawmode(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2, "Raw Mode: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_rawmode);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_rm_read, tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_rm_write, tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+#define SECURITY_MODE_MODE 0x01
+#define SECURITY_MODE_PASSWORD 0x02
+#define SECURITY_MODE_SIGNATURES 0x04
+#define SECURITY_MODE_SIG_REQUIRED 0x08
+static const true_false_string tfs_sm_mode = {
+ "USER security mode",
+ "SHARE security mode"
+};
+static const true_false_string tfs_sm_password = {
+ "ENCRYPTED password. Use challenge/response",
+ "PLAINTEXT password"
+};
+static const true_false_string tfs_sm_signatures = {
+ "Security signatures ENABLED",
+ "Security signatures NOT enabled"
+};
+static const true_false_string tfs_sm_sig_required = {
+ "Security signatures REQUIRED",
+ "Security signatures NOT required"
+};
+
+static int
+dissect_negprot_security_mode(tvbuff_t *tvb, proto_tree *parent_tree, int offset, int wc)
+{
+ guint16 mask = 0;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ switch(wc){
+ case 13:
+ mask = tvb_get_letohs(tvb, offset);
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Security Mode: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_mode);
+ proto_tree_add_boolean(tree, hf_smb_sm_mode16, tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_sm_password16, tvb, offset, 2, mask);
+ offset += 2;
+ break;
+
+ case 17:
+ mask = tvb_get_guint8(tvb, offset);
+ item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+ "Security Mode: 0x%02x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_mode);
+ proto_tree_add_boolean(tree, hf_smb_sm_mode, tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_sm_password, tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_sm_signatures, tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_sm_sig_required, tvb, offset, 1, mask);
+ offset += 1;
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_negprot_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ proto_item *it = NULL;
+ proto_tree *tr = NULL;
+ guint16 bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ if(tree){
+ it = proto_tree_add_text(tree, tvb, offset, bc,
+ "Requested Dialects");
+ tr = proto_item_add_subtree(it, ett_smb_dialects);
+ }
+
+ while(bc){
+ int len;
+ const guint8 *str;
+ proto_item *dit = NULL;
+ proto_tree *dtr = NULL;
+
+ /* XXX - what if this runs past bc? */
+ len = tvb_strsize(tvb, offset+1);
+ str = tvb_get_ptr(tvb, offset+1, len);
+
+ if(tr){
+ dit = proto_tree_add_text(tr, tvb, offset, len+1,
+ "Dialect: %s", str);
+ dtr = proto_item_add_subtree(dit, ett_smb_dialect);
+ }
+
+ /* Buffer Format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(dtr, hf_smb_buffer_format, tvb, offset, 1,
+ TRUE);
+ COUNT_BYTES(1);
+
+ /*Dialect Name */
+ CHECK_BYTE_COUNT(len);
+ proto_tree_add_string(dtr, hf_smb_dialect_name, tvb, offset,
+ len, str);
+ COUNT_BYTES(len);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_negprot_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ guint8 wc;
+ guint16 dialect;
+ const char *dn;
+ int dn_len;
+ guint16 bc;
+ guint16 ekl=0;
+ guint32 caps=0;
+ gint16 tz;
+
+ WORD_COUNT;
+
+ /* Dialect Index */
+ dialect = tvb_get_letohs(tvb, offset);
+ switch(wc){
+ case 1:
+ if(dialect==0xffff){
+ proto_tree_add_uint_format(tree, hf_smb_dialect_index,
+ tvb, offset, 2, dialect,
+ "Selected Index: -1, PC NETWORK PROGRAM 1.0 choosen");
+ } else {
+ proto_tree_add_uint(tree, hf_smb_dialect_index,
+ tvb, offset, 2, dialect);
+ }
+ break;
+ case 13:
+ proto_tree_add_uint_format(tree, hf_smb_dialect_index,
+ tvb, offset, 2, dialect,
+ "Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", dialect);
+ break;
+ case 17:
+ proto_tree_add_uint_format(tree, hf_smb_dialect_index,
+ tvb, offset, 2, dialect,
+ "Dialect Index: %u, greater than LANMAN2.1", dialect);
+ break;
+ default:
+ proto_tree_add_text(tree, tvb, offset, wc*2,
+ "Words for unknown response format");
+ offset += wc*2;
+ goto bytecount;
+ }
+ offset += 2;
+
+ switch(wc){
+ case 13:
+ /* Security Mode */
+ offset = dissect_negprot_security_mode(tvb, tree, offset, wc);
+
+ /* Maximum Transmit Buffer Size */
+ proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
+ tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* Maximum Multiplex Count */
+ proto_tree_add_item(tree, hf_smb_max_mpx_count,
+ tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* Maximum Vcs Number */
+ proto_tree_add_item(tree, hf_smb_max_vcs_num,
+ tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* raw mode */
+ offset = dissect_negprot_rawmode(tvb, tree, offset);
+
+ /* session key */
+ proto_tree_add_item(tree, hf_smb_session_key,
+ tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* current time and date at server */
+ offset = dissect_smb_datetime(tvb, tree, offset, hf_smb_server_date_time, hf_smb_server_smb_date, hf_smb_server_smb_time,
+ TRUE);
+
+ /* time zone */
+ tz = tvb_get_letohs(tvb, offset);
+ proto_tree_add_int_format(tree, hf_smb_server_timezone, tvb, offset, 2, tz, "Server Time Zone: %d min from UTC", tz);
+ offset += 2;
+
+ /* encryption key length */
+ ekl = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_encryption_key_length, tvb, offset, 2, ekl);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ break;
+
+ case 17:
+ /* Security Mode */
+ offset = dissect_negprot_security_mode(tvb, tree, offset, wc);
+
+ /* Maximum Multiplex Count */
+ proto_tree_add_item(tree, hf_smb_max_mpx_count,
+ tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* Maximum Vcs Number */
+ proto_tree_add_item(tree, hf_smb_max_vcs_num,
+ tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* Maximum Transmit Buffer Size */
+ proto_tree_add_item(tree, hf_smb_max_trans_buf_size,
+ tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* maximum raw buffer size */
+ proto_tree_add_item(tree, hf_smb_max_raw_buf_size,
+ tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* session key */
+ proto_tree_add_item(tree, hf_smb_session_key,
+ tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* server capabilities */
+ caps = dissect_negprot_capabilities(tvb, tree, offset);
+ offset += 4;
+
+ /* system time */
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_system_time);
+
+ /* time zone */
+ tz = tvb_get_letohs(tvb, offset);
+ proto_tree_add_int_format(tree, hf_smb_server_timezone,
+ tvb, offset, 2, tz,
+ "Server Time Zone: %d min from UTC", tz);
+ offset += 2;
+
+ /* encryption key length */
+ ekl = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_encryption_key_length,
+ tvb, offset, 1, ekl);
+ offset += 1;
+
+ break;
+ }
+
+ BYTE_COUNT;
+
+ switch(wc){
+ case 13:
+ /* challenge/response encryption key */
+ if(ekl){
+ CHECK_BYTE_COUNT(ekl);
+ proto_tree_add_item(tree, hf_smb_encryption_key, tvb, offset, ekl, TRUE);
+ COUNT_BYTES(ekl);
+ }
+
+ /*
+ * Primary domain.
+ *
+ * XXX - not present if negotiated dialect isn't
+ * "DOS LANMAN 2.1" or "LANMAN2.1", but we'd either
+ * have to see the request, or assume what dialect strings
+ * were sent, to determine that.
+ *
+ * Is this something other than a primary domain if the
+ * negotiated dialect is Windows for Workgroups 3.1a?
+ * It appears to be 8 bytes of binary data in at least
+ * one capture - is that an encryption key or something
+ * such as that?
+ */
+ dn = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &dn_len, FALSE, FALSE, &bc);
+ if (dn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
+ offset, dn_len,dn);
+ COUNT_BYTES(dn_len);
+ break;
+
+ case 17:
+ if(!(caps&SERVER_CAP_EXTENDED_SECURITY)){
+ /* challenge/response encryption key */
+ /* XXX - is this aligned on an even boundary? */
+ if(ekl){
+ CHECK_BYTE_COUNT(ekl);
+ proto_tree_add_item(tree, hf_smb_encryption_key,
+ tvb, offset, ekl, TRUE);
+ COUNT_BYTES(ekl);
+ }
+
+ /* domain */
+ /* this string is special, unicode is flagged in caps */
+ /* This string is NOT padded to be 16bit aligned.
+ (seen in actual capture)
+ XXX - I've seen a capture where it appears to be
+ so aligned, but I've also seen captures where
+ it is. The captures where it appeared to be
+ aligned may have been from buggy servers. */
+ /* However, don't get rid of existing setting */
+ si->unicode = (caps&SERVER_CAP_UNICODE) ||
+ si->unicode;
+
+ dn = get_unicode_or_ascii_string(tvb,
+ &offset, si->unicode, &dn_len, TRUE, FALSE,
+ &bc);
+ if (dn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_primary_domain,
+ tvb, offset, dn_len, dn);
+ COUNT_BYTES(dn_len);
+
+ /* server name, seen in w2k pro capture */
+ dn = get_unicode_or_ascii_string(tvb,
+ &offset, si->unicode, &dn_len, TRUE, FALSE,
+ &bc);
+ if (dn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_server,
+ tvb, offset, dn_len, dn);
+ COUNT_BYTES(dn_len);
+
+ } else {
+ proto_item *blob_item;
+ guint16 sbloblen;
+
+ /* guid */
+ /* XXX - show it in the standard Microsoft format
+ for GUIDs? */
+ CHECK_BYTE_COUNT(16);
+ proto_tree_add_item(tree, hf_smb_server_guid,
+ tvb, offset, 16, TRUE);
+ COUNT_BYTES(16);
+
+ /* security blob */
+ /* If it runs past the end of the captured data, don't
+ * try to put all of it into the protocol tree as the
+ * raw security blob; we might get an exception on
+ * short frames and then we will not see anything at all
+ * of the security blob.
+ */
+ sbloblen=bc;
+ if(sbloblen>tvb_length_remaining(tvb, offset)){
+ sbloblen=tvb_length_remaining(tvb,offset);
+ }
+ blob_item = proto_tree_add_item(
+ tree, hf_smb_security_blob,
+ tvb, offset, sbloblen, TRUE);
+
+ /*
+ * If Extended security and BCC == 16, then raw
+ * NTLMSSP is in use. We need to save this info
+ */
+
+ if(bc){
+ tvbuff_t *gssapi_tvb;
+ proto_tree *gssapi_tree;
+
+ gssapi_tree = proto_item_add_subtree(
+ blob_item, ett_smb_secblob);
+
+ /*
+ * Set the reported length of this to
+ * the reported length of the blob,
+ * rather than the amount of data
+ * available from the blob, so that
+ * we'll throw the right exception if
+ * it's too short.
+ */
+ gssapi_tvb = tvb_new_subset(
+ tvb, offset, sbloblen, bc);
+
+ call_dissector(
+ gssapi_handle, gssapi_tvb, pinfo,
+ gssapi_tree);
+
+ if (si->ct)
+ si->ct->raw_ntlmssp = 0;
+
+ COUNT_BYTES(bc);
+ }
+ else {
+
+ /*
+ * There is no blob. We just have to make sure
+ * that subsequent routines know to call the
+ * right things ...
+ */
+
+ if (si->ct)
+ si->ct->raw_ntlmssp = 1;
+
+ }
+ }
+ break;
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static int
+dissect_old_dir_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int dn_len;
+ const char *dn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* dir name */
+ dn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &dn_len,
+ FALSE, FALSE, &bc);
+ if (dn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, dn_len,
+ dn);
+ COUNT_BYTES(dn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Directory: %s", dn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_empty(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_echo_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint16 ec, bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ /* echo count */
+ ec = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_echo_count, tvb, offset, 2, ec);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ if (bc != 0) {
+ /* echo data */
+ proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
+ COUNT_BYTES(bc);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_echo_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint16 bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ /* echo sequence number */
+ proto_tree_add_item(tree, hf_smb_echo_seq_num, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ if (bc != 0) {
+ /* echo data */
+ proto_tree_add_item(tree, hf_smb_echo_data, tvb, offset, bc, TRUE);
+ COUNT_BYTES(bc);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_tree_connect_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int an_len, pwlen;
+ const char *an;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* Path */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_path, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", an);
+ }
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* password, ANSI */
+ /* XXX - what if this runs past bc? */
+ pwlen = tvb_strsize(tvb, offset);
+ CHECK_BYTE_COUNT(pwlen);
+ proto_tree_add_item(tree, hf_smb_password,
+ tvb, offset, pwlen, TRUE);
+ COUNT_BYTES(pwlen);
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* Service */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_service, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_tree_connect_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* Maximum Buffer Size */
+ proto_tree_add_item(tree, hf_smb_max_buf_size, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* tid */
+ proto_tree_add_item(tree, hf_smb_tid, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static const true_false_string tfs_of_create = {
+ "Create file if it does not exist",
+ "Fail if file does not exist"
+};
+static const value_string of_open[] = {
+ { 0, "Fail if file exists"},
+ { 1, "Open file if it exists"},
+ { 2, "Truncate file if it exists"},
+ {0, NULL}
+};
+static int
+dissect_open_function(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Open Function: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_openfunction);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_open_function_create,
+ tvb, offset, 2, mask);
+ proto_tree_add_uint(tree, hf_smb_open_function_open,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+
+static const true_false_string tfs_mf_file = {
+ "Target must be a file",
+ "Target needn't be a file"
+};
+static const true_false_string tfs_mf_dir = {
+ "Target must be a directory",
+ "Target needn't be a directory"
+};
+static const true_false_string tfs_mf_verify = {
+ "MUST verify all writes",
+ "Don't have to verify writes"
+};
+static int
+dissect_move_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Flags: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_move_copy_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_move_flags_verify,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_move_flags_dir,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_move_flags_file,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+static const true_false_string tfs_cf_mode = {
+ "ASCII",
+ "Binary"
+};
+static const true_false_string tfs_cf_tree_copy = {
+ "Copy is a tree copy",
+ "Copy is a file copy"
+};
+static const true_false_string tfs_cf_ea_action = {
+ "Fail copy",
+ "Discard EAs"
+};
+static int
+dissect_copy_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Flags: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_move_copy_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_copy_flags_ea_action,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_copy_flags_tree_copy,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_copy_flags_verify,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_copy_flags_source_mode,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_copy_flags_dest_mode,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_copy_flags_dir,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_copy_flags_file,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+static int
+dissect_move_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ guint16 tid;
+ guint16 bc;
+ guint8 wc;
+ const char *fn;
+
+ WORD_COUNT;
+
+ /* tid */
+ tid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_smb_tid, tvb, offset, 2, tid,
+ "TID (target): 0x%04x", tid);
+ offset += 2;
+
+ /* open function */
+ offset = dissect_open_function(tvb, tree, offset);
+
+ /* move flags */
+ offset = dissect_move_flags(tvb, tree, offset);
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
+ fn_len, fn, "Old File Name: %s", fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
+ }
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
+ fn_len, fn, "New File Name: %s", fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_copy_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ guint16 tid;
+ guint16 bc;
+ guint8 wc;
+ const char *fn;
+
+ WORD_COUNT;
+
+ /* tid */
+ tid = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_smb_tid, tvb, offset, 2, tid,
+ "TID (target): 0x%04x", tid);
+ offset += 2;
+
+ /* open function */
+ offset = dissect_open_function(tvb, tree, offset);
+
+ /* copy flags */
+ offset = dissect_copy_flags(tvb, tree, offset);
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
+ fn_len, fn, "Source File Name: %s", fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Source Name: %s", fn);
+ }
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string_format(tree, hf_smb_file_name, tvb, offset,
+ fn_len, fn, "Destination File Name: %s", fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Destination Name: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_move_copy_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* # of files moved */
+ proto_tree_add_item(tree, hf_smb_files_moved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_open_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* desired access */
+ offset = dissect_access(tvb, tree, offset, "Desired");
+
+ /* Search Attributes */
+ offset = dissect_search_attributes(tvb, tree, offset);
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+void
+add_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
+ int len, guint16 fid)
+{
+ proto_tree_add_uint(tree, hf_smb_fid, tvb, offset, len, fid);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", FID: 0x%04x", fid);
+}
+
+static int
+dissect_open_file_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+ guint16 fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* File Attributes */
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+
+ /* last write time */
+ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
+
+ /* File Size */
+ proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* granted access */
+ offset = dissect_access(tvb, tree, offset, "Granted");
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_fid(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+ guint16 fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_create_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* file attributes */
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+
+ /* creation time */
+ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_create_time);
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* File Name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_close_file_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc, fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* last write time */
+ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_delete_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* search attributes */
+ offset = dissect_search_attributes(tvb, tree, offset);
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_rename_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* search attributes */
+ offset = dissect_search_attributes(tvb, tree, offset);
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* old file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_old_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
+ }
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_nt_rename_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* search attributes */
+ offset = dissect_search_attributes(tvb, tree, offset);
+
+ proto_tree_add_uint(tree, hf_smb_nt_rename_level, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_smb_cluster_count, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* old file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_old_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
+ }
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static int
+dissect_query_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ guint16 bc;
+ guint8 wc;
+ const char *fn;
+ int fn_len;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ /* Buffer Format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* File Name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_query_information_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint16 bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ /* File Attributes */
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+
+ /* Last Write Time */
+ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
+
+ /* File Size */
+ proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* 10 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
+ offset += 10;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_set_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* file attributes */
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+
+ /* last write time */
+ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
+
+ /* 10 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
+ offset += 10;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_read_file_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 cnt=0, bc;
+ guint32 ofs=0;
+ smb_info_t *si;
+ unsigned int fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, (guint16) fid);
+ offset += 2;
+ if (!pinfo->fd->flags.visited) {
+ /* remember the FID for the processing of the response */
+ si = (smb_info_t *)pinfo->private_data;
+ si->sip->extra_info=(void *)fid;
+ }
+
+ /* read count */
+ cnt = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* offset */
+ ofs = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %u byte%s at offset %u", cnt,
+ (cnt == 1) ? "" : "s", ofs);
+
+ /* remaining */
+ proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+int
+dissect_file_data(tvbuff_t *tvb, proto_tree *tree, int offset, guint16 bc, guint16 datalen)
+{
+ int tvblen;
+
+ if(bc>datalen){
+ /* We have some initial padding bytes. */
+ /* XXX - use the data offset here instead? */
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, bc-datalen,
+ TRUE);
+ offset += bc-datalen;
+ bc = datalen;
+ }
+ tvblen = tvb_length_remaining(tvb, offset);
+ if(bc>tvblen){
+ proto_tree_add_bytes_format(tree, hf_smb_file_data, tvb, offset, tvblen, tvb_get_ptr(tvb, offset, tvblen),"File Data: Incomplete. Only %d of %u bytes", tvblen, bc);
+ offset += tvblen;
+ } else {
+ proto_tree_add_item(tree, hf_smb_file_data, tvb, offset, bc, TRUE);
+ offset += bc;
+ }
+ return offset;
+}
+
+static int
+dissect_file_data_dcerpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *top_tree, int offset, guint16 bc, guint16 datalen, guint16 fid)
+{
+ int tvblen;
+ tvbuff_t *dcerpc_tvb;
+
+ if(bc>datalen){
+ /* We have some initial padding bytes. */
+ /* XXX - use the data offset here instead? */
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, bc-datalen,
+ TRUE);
+ offset += bc-datalen;
+ bc = datalen;
+ }
+ tvblen = tvb_length_remaining(tvb, offset);
+ dcerpc_tvb = tvb_new_subset(tvb, offset, tvblen, bc);
+ dissect_pipe_dcerpc(dcerpc_tvb, pinfo, top_tree, tree, fid);
+ if(bc>tvblen)
+ offset += tvblen;
+ else
+ offset += bc;
+ return offset;
+}
+
+/*
+ * transporting DCERPC over SMB seems to be implemented in various
+ * ways. We might just assume it can be done by an almost random
+ * mix of Trans/Read/Write calls
+ *
+ * if we suspect dcerpc, just send them all down to packet-smb-pipe.c
+ * and let him sort them out
+ */
+static int
+dissect_file_data_maybe_dcerpc(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, proto_tree *top_tree, int offset, guint16 bc,
+ guint16 datalen, guint32 ofs, guint16 fid)
+{
+ smb_info_t *si = (smb_info_t *)pinfo->private_data;
+
+ if( (si->sip && si->sip->flags&SMB_SIF_TID_IS_IPC) && (ofs==0) ){
+ /* dcerpc call */
+ return dissect_file_data_dcerpc(tvb, pinfo, tree,
+ top_tree, offset, bc, datalen, fid);
+ } else {
+ /* ordinary file data */
+ return dissect_file_data(tvb, tree, offset, bc, datalen);
+ }
+}
+
+static int
+dissect_read_file_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint16 cnt=0, bc;
+ guint8 wc;
+ smb_info_t *si = (smb_info_t *)pinfo->private_data;
+ int fid=0;
+
+ WORD_COUNT;
+
+ /* read count */
+ cnt = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+ offset += 2;
+
+ /* 8 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
+ offset += 8;
+
+ /* If we have seen the request, then print which FID this refers to */
+ /* first check if we have seen the request */
+ if(si->sip != NULL && si->sip->frame_req>0){
+ fid=(int)si->sip->extra_info;
+ add_fid(tvb, pinfo, tree, 0, 0, (guint16) fid);
+ }
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* data len */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ /* file data, might be DCERPC on a pipe */
+ if(bc){
+ offset = dissect_file_data_maybe_dcerpc(tvb, pinfo, tree,
+ top_tree, offset, bc, bc, 0, (guint16) fid);
+ bc = 0;
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_lock_and_read_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint16 cnt, bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ /* read count */
+ cnt = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+ offset += 2;
+
+ /* 8 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
+ offset += 8;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* data len */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static int
+dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint32 ofs=0;
+ guint16 cnt=0, bc, fid=0;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* write count */
+ cnt = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+ offset += 2;
+
+ /* offset */
+ ofs = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %u byte%s at offset %u", cnt,
+ (cnt == 1) ? "" : "s", ofs);
+
+ /* remaining */
+ proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* data len */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ /* file data, might be DCERPC on a pipe */
+ if (bc != 0) {
+ offset = dissect_file_data_maybe_dcerpc(tvb, pinfo, tree,
+ top_tree, offset, bc, bc, ofs, fid);
+ bc = 0;
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_write_file_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc, cnt;
+
+ WORD_COUNT;
+
+ /* write count */
+ cnt = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %u byte%s", cnt, (cnt == 1) ? "" : "s");
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_lock_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc, fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* lock count */
+ proto_tree_add_item(tree, hf_smb_count, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* offset */
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_create_temporary_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* Creation time */
+ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_create_time);
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* directory name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_create_temporary_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc, fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static const value_string seek_mode_vals[] = {
+ {0, "From Start Of File"},
+ {1, "From Current Position"},
+ {2, "From End Of File"},
+ {0, NULL}
+};
+
+static int
+dissect_seek_file_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc, fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* Seek Mode */
+ proto_tree_add_item(tree, hf_smb_seek_mode, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* offset */
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_seek_file_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* offset */
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_set_information2_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc, fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* create time */
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_create_time,
+ hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
+
+ /* access time */
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_access_time,
+ hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
+
+ /* last write time */
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_last_write_time,
+ hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_query_information2_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* create time */
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_create_time,
+ hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
+
+ /* access time */
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_access_time,
+ hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
+
+ /* last write time */
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_last_write_time,
+ hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
+
+ /* data size */
+ proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* allocation size */
+ proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* File Attributes */
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_write_and_close_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 cnt=0;
+ guint16 bc, fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* write count */
+ cnt = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+ offset += 2;
+
+ /* offset */
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* last write time */
+ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
+
+ if(wc==12){
+ /* 12 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 12, TRUE);
+ offset += 12;
+ }
+
+ BYTE_COUNT;
+
+ /* 1 pad byte */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ offset = dissect_file_data(tvb, tree, offset, cnt, cnt);
+ bc = 0; /* XXX */
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_write_and_close_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* write count */
+ proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_read_raw_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc, fid;
+ guint32 to;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* offset */
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* max count */
+ proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* min count */
+ proto_tree_add_item(tree, hf_smb_min_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* timeout */
+ to = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+ offset += 4;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ if(wc==10){
+ /* high offset */
+ proto_tree_add_item(tree, hf_smb_high_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+ }
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_query_information_disk_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* units */
+ proto_tree_add_item(tree, hf_smb_units, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* bpu */
+ proto_tree_add_item(tree, hf_smb_bpu, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* block size */
+ proto_tree_add_item(tree, hf_smb_blocksize, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* free units */
+ proto_tree_add_item(tree, hf_smb_freeunits, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_read_mpx_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc, fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* offset */
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* max count */
+ proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* min count */
+ proto_tree_add_item(tree, hf_smb_min_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* 6 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 6, TRUE);
+ offset += 6;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_read_mpx_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint16 datalen=0, bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ /* offset */
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* count */
+ proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* data compaction mode */
+ proto_tree_add_item(tree, hf_smb_dcm, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* data len */
+ datalen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
+ offset += 2;
+
+ /* data offset */
+ proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* file data */
+ offset = dissect_file_data(tvb, tree, offset, bc, datalen);
+ bc = 0;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static const true_false_string tfs_write_mode_write_through = {
+ "WRITE THROUGH requested",
+ "Write through not requested"
+};
+static const true_false_string tfs_write_mode_return_remaining = {
+ "RETURN REMAINING (pipe/dev) requested",
+ "DON'T return remaining (pipe/dev)"
+};
+static const true_false_string tfs_write_mode_raw = {
+ "Use WriteRawNamedPipe (pipe)",
+ "DON'T use WriteRawNamedPipe (pipe)"
+};
+static const true_false_string tfs_write_mode_message_start = {
+ "This is the START of a MESSAGE (pipe)",
+ "This is NOT the start of a message (pipe)"
+};
+static const true_false_string tfs_write_mode_connectionless = {
+ "CONNECTIONLESS mode requested",
+ "Connectionless mode NOT requested"
+};
+
+#define WRITE_MODE_CONNECTIONLESS 0x0080
+#define WRITE_MODE_MESSAGE_START 0x0008
+#define WRITE_MODE_RAW 0x0004
+#define WRITE_MODE_RETURN_REMAINING 0x0002
+#define WRITE_MODE_WRITE_THROUGH 0x0001
+
+static int
+dissect_write_mode(tvbuff_t *tvb, proto_tree *parent_tree, int offset, int bm)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Write Mode: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_rawmode);
+ }
+
+ if(bm&WRITE_MODE_CONNECTIONLESS){
+ proto_tree_add_boolean(tree, hf_smb_write_mode_connectionless,
+ tvb, offset, 2, mask);
+ }
+ if(bm&WRITE_MODE_MESSAGE_START){
+ proto_tree_add_boolean(tree, hf_smb_write_mode_message_start,
+ tvb, offset, 2, mask);
+ }
+ if(bm&WRITE_MODE_RAW){
+ proto_tree_add_boolean(tree, hf_smb_write_mode_raw,
+ tvb, offset, 2, mask);
+ }
+ if(bm&WRITE_MODE_RETURN_REMAINING){
+ proto_tree_add_boolean(tree, hf_smb_write_mode_return_remaining,
+ tvb, offset, 2, mask);
+ }
+ if(bm&WRITE_MODE_WRITE_THROUGH){
+ proto_tree_add_boolean(tree, hf_smb_write_mode_write_through,
+ tvb, offset, 2, mask);
+ }
+
+ offset += 2;
+ return offset;
+}
+
+static int
+dissect_write_raw_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint32 to;
+ guint16 datalen=0, bc, fid;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* total data length */
+ proto_tree_add_item(tree, hf_smb_total_data_len, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* offset */
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* timeout */
+ to = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+ offset += 4;
+
+ /* mode */
+ offset = dissect_write_mode(tvb, tree, offset, 0x0003);
+
+ /* 4 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* data len */
+ datalen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
+ offset += 2;
+
+ /* data offset */
+ proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* file data */
+ /* XXX - use the data offset to determine where the data starts? */
+ offset = dissect_file_data(tvb, tree, offset, bc, datalen);
+ bc = 0;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_write_raw_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* remaining */
+ proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_write_mpx_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint32 to;
+ guint16 datalen=0, bc, fid;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* total data length */
+ proto_tree_add_item(tree, hf_smb_total_data_len, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* offset */
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* timeout */
+ to = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+ offset += 4;
+
+ /* mode */
+ offset = dissect_write_mode(tvb, tree, offset, 0x0083);
+
+ /* request mask */
+ proto_tree_add_item(tree, hf_smb_request_mask, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* data len */
+ datalen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, datalen);
+ offset += 2;
+
+ /* data offset */
+ proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* file data */
+ /* XXX - use the data offset to determine where the data starts? */
+ offset = dissect_file_data(tvb, tree, offset, bc, datalen);
+ bc = 0;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_write_mpx_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* response mask */
+ proto_tree_add_item(tree, hf_smb_response_mask, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_sid(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* sid */
+ proto_tree_add_item(tree, hf_smb_search_id, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_search_resume_key(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *parent_tree, int offset, guint16 *bcp, gboolean *trunc,
+ gboolean has_find_id)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ char fname[11+1];
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 21,
+ "Resume Key");
+ tree = proto_item_add_subtree(item, ett_smb_search_resume_key);
+ }
+
+ /* reserved byte */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* file name */
+ fn_len = 11;
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ TRUE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ /* ensure that it's null-terminated */
+ strncpy(fname, fn, 11);
+ fname[11] = '\0';
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, 11,
+ fname);
+ COUNT_BYTES_SUBR(fn_len);
+
+ if (has_find_id) {
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_resume_find_id, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* server cookie */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_resume_server_cookie, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+ } else {
+ /* server cookie */
+ CHECK_BYTE_COUNT_SUBR(5);
+ proto_tree_add_item(tree, hf_smb_resume_server_cookie, tvb, offset, 5, TRUE);
+ COUNT_BYTES_SUBR(5);
+ }
+
+ /* client cookie */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_resume_client_cookie, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+static int
+dissect_search_dir_info(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *parent_tree, int offset, guint16 *bcp, gboolean *trunc,
+ gboolean has_find_id)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ char fname[13+1];
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 46,
+ "Directory Information");
+ tree = proto_item_add_subtree(item, ett_smb_search_dir_info);
+ }
+
+ /* resume key */
+ offset = dissect_search_resume_key(tvb, pinfo, tree, offset, bcp,
+ trunc, has_find_id);
+ if (*trunc)
+ return offset;
+
+ /* File Attributes */
+ CHECK_BYTE_COUNT_SUBR(1);
+ offset = dissect_dir_info_file_attributes(tvb, tree, offset);
+ *bcp -= 1;
+
+ /* last write time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_last_write_time,
+ hf_smb_last_write_dos_date, hf_smb_last_write_dos_time,
+ TRUE);
+ *bcp -= 4;
+
+ /* File Size */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* file name */
+ fn_len = 13;
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ TRUE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ /* ensure that it's null-terminated */
+ strncpy(fname, fn, 13);
+ fname[13] = '\0';
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fname);
+ COUNT_BYTES_SUBR(fn_len);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+
+static int
+dissect_search_find_request(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int offset, proto_tree *smb_tree _U_,
+ gboolean has_find_id)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint16 rkl;
+ guint8 wc;
+ guint16 bc;
+ gboolean trunc;
+
+ WORD_COUNT;
+
+ /* max count */
+ proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* Search Attributes */
+ offset = dissect_search_attributes(tvb, tree, offset);
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ TRUE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s", fn);
+ }
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* resume key length */
+ CHECK_BYTE_COUNT(2);
+ rkl = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_resume_key_len, tvb, offset, 2, rkl);
+ COUNT_BYTES(2);
+
+ /* resume key */
+ if(rkl){
+ offset = dissect_search_resume_key(tvb, pinfo, tree, offset,
+ &bc, &trunc, has_find_id);
+ if (trunc)
+ goto endofcommand;
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_search_dir_request(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ return dissect_search_find_request(tvb, pinfo, tree, offset,
+ smb_tree, FALSE);
+}
+
+static int
+dissect_find_request(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ return dissect_search_find_request(tvb, pinfo, tree, offset,
+ smb_tree, TRUE);
+}
+
+static int
+dissect_find_close_request(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ return dissect_search_find_request(tvb, pinfo, tree, offset,
+ smb_tree, TRUE);
+}
+
+static int
+dissect_search_find_response(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, int offset, proto_tree *smb_tree _U_,
+ gboolean has_find_id)
+{
+ guint16 count=0;
+ guint8 wc;
+ guint16 bc;
+ gboolean trunc;
+
+ WORD_COUNT;
+
+ /* count */
+ count = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, count);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* data len */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ while(count--){
+ offset = dissect_search_dir_info(tvb, pinfo, tree, offset,
+ &bc, &trunc, has_find_id);
+ if (trunc)
+ goto endofcommand;
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_search_dir_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ return dissect_search_find_response(tvb, pinfo, tree, offset, smb_tree,
+ FALSE);
+}
+
+static int
+dissect_find_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ return dissect_search_find_response(tvb, pinfo, tree, offset, smb_tree,
+ TRUE);
+}
+
+static int
+dissect_find_close_response(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+ guint16 data_len;
+
+ WORD_COUNT;
+
+ /* reserved */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* data len */
+ CHECK_BYTE_COUNT(2);
+ data_len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, data_len);
+ COUNT_BYTES(2);
+
+ if (data_len != 0) {
+ CHECK_BYTE_COUNT(data_len);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset,
+ data_len, TRUE);
+ COUNT_BYTES(data_len);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static const value_string locking_ol_vals[] = {
+ {0, "Client is not holding oplock on this file"},
+ {1, "Level 2 oplock currently held by client"},
+ {0, NULL}
+};
+
+static const true_false_string tfs_lock_type_large = {
+ "Large file locking format requested",
+ "Large file locking format not requested"
+};
+static const true_false_string tfs_lock_type_cancel = {
+ "Cancel outstanding lock request",
+ "Don't cancel outstanding lock request"
+};
+static const true_false_string tfs_lock_type_change = {
+ "Change lock type",
+ "Don't change lock type"
+};
+static const true_false_string tfs_lock_type_oplock = {
+ "This is an oplock break notification/response",
+ "This is not an oplock break notification/response"
+};
+static const true_false_string tfs_lock_type_shared = {
+ "This is a shared lock",
+ "This is an exclusive lock"
+};
+static int
+dissect_locking_andx_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff, lt=0;
+ guint16 andxoffset=0, un=0, ln=0, bc, fid;
+ guint32 to;
+ proto_item *litem = NULL;
+ proto_tree *ltree = NULL;
+ proto_item *it = NULL;
+ proto_tree *tr = NULL;
+ int old_offset = offset;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* lock type */
+ lt = tvb_get_guint8(tvb, offset);
+ if(tree){
+ litem = proto_tree_add_text(tree, tvb, offset, 1,
+ "Lock Type: 0x%02x", lt);
+ ltree = proto_item_add_subtree(litem, ett_smb_lock_type);
+ }
+ proto_tree_add_boolean(ltree, hf_smb_lock_type_large,
+ tvb, offset, 1, lt);
+ proto_tree_add_boolean(ltree, hf_smb_lock_type_cancel,
+ tvb, offset, 1, lt);
+ proto_tree_add_boolean(ltree, hf_smb_lock_type_change,
+ tvb, offset, 1, lt);
+ proto_tree_add_boolean(ltree, hf_smb_lock_type_oplock,
+ tvb, offset, 1, lt);
+ proto_tree_add_boolean(ltree, hf_smb_lock_type_shared,
+ tvb, offset, 1, lt);
+ offset += 1;
+
+ /* oplock level */
+ proto_tree_add_item(tree, hf_smb_locking_ol, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* timeout */
+ to = tvb_get_letohl(tvb, offset);
+ if (to == 0)
+ proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: Return immediately (0)");
+ else if (to == 0xffffffff)
+ proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: Wait indefinitely (-1)");
+ else
+ proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+ offset += 4;
+
+ /* number of unlocks */
+ un = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_number_of_unlocks, tvb, offset, 2, un);
+ offset += 2;
+
+ /* number of locks */
+ ln = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_number_of_locks, tvb, offset, 2, ln);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* unlocks */
+ if(un){
+ old_offset = offset;
+
+ it = proto_tree_add_text(tree, tvb, offset, -1,
+ "Unlocks");
+ tr = proto_item_add_subtree(it, ett_smb_unlocks);
+ while(un--){
+ proto_item *litem = NULL;
+ proto_tree *ltree = NULL;
+ if(lt&0x10){
+ guint8 buf[8];
+ guint32 val;
+
+ /* large lock format */
+ litem = proto_tree_add_text(tr, tvb, offset, 20,
+ "Unlock");
+ ltree = proto_item_add_subtree(litem, ett_smb_unlock);
+
+ /* PID */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(ltree, hf_smb_pid, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ /* 2 reserved bytes */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(ltree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ /* offset */
+ CHECK_BYTE_COUNT(8);
+ val=tvb_get_letohl(tvb, offset);
+ buf[3]=(val>>24)&0xff;
+ buf[2]=(val>>16)&0xff;
+ buf[1]=(val>> 8)&0xff;
+ buf[0]=(val )&0xff;
+ val=tvb_get_letohl(tvb, offset+4);
+ buf[7]=(val>>24)&0xff;
+ buf[6]=(val>>16)&0xff;
+ buf[5]=(val>> 8)&0xff;
+ buf[4]=(val )&0xff;
+ proto_tree_add_string(ltree, hf_smb_lock_long_offset, tvb, offset, 8, u64toa(buf));
+ COUNT_BYTES(8);
+
+ /* length */
+ CHECK_BYTE_COUNT(8);
+ val=tvb_get_letohl(tvb, offset);
+ buf[3]=(val>>24)&0xff;
+ buf[2]=(val>>16)&0xff;
+ buf[1]=(val>> 8)&0xff;
+ buf[0]=(val )&0xff;
+ val=tvb_get_letohl(tvb, offset+4);
+ buf[7]=(val>>24)&0xff;
+ buf[6]=(val>>16)&0xff;
+ buf[5]=(val>> 8)&0xff;
+ buf[4]=(val )&0xff;
+ proto_tree_add_string(ltree, hf_smb_lock_long_length, tvb, offset, 8, u64toa(buf));
+ COUNT_BYTES(8);
+ } else {
+ /* normal lock format */
+ litem = proto_tree_add_text(tr, tvb, offset, 10,
+ "Unlock");
+ ltree = proto_item_add_subtree(litem, ett_smb_unlock);
+
+ /* PID */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(ltree, hf_smb_pid, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ /* offset */
+ CHECK_BYTE_COUNT(4);
+ proto_tree_add_item(ltree, hf_smb_offset, tvb, offset, 4, TRUE);
+ COUNT_BYTES(4);
+
+ /* lock count */
+ CHECK_BYTE_COUNT(4);
+ proto_tree_add_item(ltree, hf_smb_count, tvb, offset, 4, TRUE);
+ COUNT_BYTES(4);
+ }
+ }
+ proto_item_set_len(it, offset-old_offset);
+ it = NULL;
+ }
+
+ /* locks */
+ if(ln){
+ old_offset = offset;
+
+ it = proto_tree_add_text(tree, tvb, offset, -1,
+ "Locks");
+ tr = proto_item_add_subtree(it, ett_smb_locks);
+ while(ln--){
+ proto_item *litem = NULL;
+ proto_tree *ltree = NULL;
+ if(lt&0x10){
+ guint8 buf[8];
+ guint32 val;
+
+ /* large lock format */
+ litem = proto_tree_add_text(tr, tvb, offset, 20,
+ "Lock");
+ ltree = proto_item_add_subtree(litem, ett_smb_lock);
+
+ /* PID */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(ltree, hf_smb_pid, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ /* 2 reserved bytes */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(ltree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ /* offset */
+ CHECK_BYTE_COUNT(8);
+ val=tvb_get_letohl(tvb, offset);
+ buf[3]=(val )&0xff;
+ buf[2]=(val>> 8)&0xff;
+ buf[1]=(val>>16)&0xff;
+ buf[0]=(val>>24)&0xff;
+ val=tvb_get_letohl(tvb, offset+4);
+ buf[7]=(val )&0xff;
+ buf[6]=(val>> 8)&0xff;
+ buf[5]=(val>>16)&0xff;
+ buf[4]=(val>>24)&0xff;
+ proto_tree_add_string(ltree, hf_smb_lock_long_offset, tvb, offset, 8, u64toa(buf));
+ COUNT_BYTES(8);
+
+ /* length */
+ CHECK_BYTE_COUNT(8);
+ val=tvb_get_letohl(tvb, offset);
+ buf[3]=(val )&0xff;
+ buf[2]=(val>> 8)&0xff;
+ buf[1]=(val>>16)&0xff;
+ buf[0]=(val>>24)&0xff;
+ val=tvb_get_letohl(tvb, offset+4);
+ buf[7]=(val )&0xff;
+ buf[6]=(val>> 8)&0xff;
+ buf[5]=(val>>16)&0xff;
+ buf[4]=(val>>24)&0xff;
+ proto_tree_add_string(ltree, hf_smb_lock_long_length, tvb, offset, 8, u64toa(buf));
+ COUNT_BYTES(8);
+ } else {
+ /* normal lock format */
+ litem = proto_tree_add_text(tr, tvb, offset, 10,
+ "Unlock");
+ ltree = proto_item_add_subtree(litem, ett_smb_unlock);
+
+ /* PID */
+ CHECK_BYTE_COUNT(2);
+ proto_tree_add_item(ltree, hf_smb_pid, tvb, offset, 2, TRUE);
+ COUNT_BYTES(2);
+
+ /* offset */
+ CHECK_BYTE_COUNT(4);
+ proto_tree_add_item(ltree, hf_smb_offset, tvb, offset, 4, TRUE);
+ COUNT_BYTES(4);
+
+ /* lock count */
+ CHECK_BYTE_COUNT(4);
+ proto_tree_add_item(ltree, hf_smb_count, tvb, offset, 4, TRUE);
+ COUNT_BYTES(4);
+ }
+ }
+ proto_item_set_len(it, offset-old_offset);
+ it = NULL;
+ }
+
+ END_OF_SMB
+
+ if (it != NULL) {
+ /*
+ * We ran out of byte count in the middle of dissecting
+ * the locks or the unlocks; set the site of the item
+ * we were dissecting.
+ */
+ proto_item_set_len(it, offset-old_offset);
+ }
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+static int
+dissect_locking_andx_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+
+static const value_string oa_open_vals[] = {
+ { 0, "No action taken?"},
+ { 1, "The file existed and was opened"},
+ { 2, "The file did not exist but was created"},
+ { 3, "The file existed and was truncated"},
+ { 0x8001, "The file existed and was opened, and an OpLock was granted"},
+ { 0x8002, "The file did not exist but was created, and an OpLock was granted"},
+ { 0x8002, "The file existed and was truncated, and an OpLock was granted"},
+ {0, NULL}
+};
+static const true_false_string tfs_oa_lock = {
+ "File is currently opened only by this user",
+ "File is opened by another user (or mode not supported by server)"
+};
+static int
+dissect_open_action(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Action: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_open_action);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_open_action_lock,
+ tvb, offset, 2, mask);
+ proto_tree_add_uint(tree, hf_smb_open_action_open,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+static const true_false_string tfs_open_flags_add_info = {
+ "Additional information requested",
+ "Additional information not requested"
+};
+static const true_false_string tfs_open_flags_ex_oplock = {
+ "Exclusive oplock requested",
+ "Exclusive oplock not requested"
+};
+static const true_false_string tfs_open_flags_batch_oplock = {
+ "Batch oplock requested",
+ "Batch oplock not requested"
+};
+static const true_false_string tfs_open_flags_ealen = {
+ "Total length of EAs requested",
+ "Total length of EAs not requested"
+};
+static int
+dissect_open_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset, int bm)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Flags: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_open_flags);
+ }
+
+ if(bm&0x0001){
+ proto_tree_add_boolean(tree, hf_smb_open_flags_add_info,
+ tvb, offset, 2, mask);
+ }
+ if(bm&0x0002){
+ proto_tree_add_boolean(tree, hf_smb_open_flags_ex_oplock,
+ tvb, offset, 2, mask);
+ }
+ if(bm&0x0004){
+ proto_tree_add_boolean(tree, hf_smb_open_flags_batch_oplock,
+ tvb, offset, 2, mask);
+ }
+ if(bm&0x0008){
+ proto_tree_add_boolean(tree, hf_smb_open_flags_ealen,
+ tvb, offset, 2, mask);
+ }
+
+ offset += 2;
+
+ return offset;
+}
+
+static const value_string filetype_vals[] = {
+ { 0, "Disk file or directory"},
+ { 1, "Named pipe in byte mode"},
+ { 2, "Named pipe in message mode"},
+ { 3, "Spooled printer"},
+ {0, NULL}
+};
+static int
+dissect_open_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0, bc;
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* open flags */
+ offset = dissect_open_flags(tvb, tree, offset, 0x0007);
+
+ /* desired access */
+ offset = dissect_access(tvb, tree, offset, "Desired");
+
+ /* Search Attributes */
+ offset = dissect_search_attributes(tvb, tree, offset);
+
+ /* File Attributes */
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+
+ /* creation time */
+ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_create_time);
+
+ /* open function */
+ offset = dissect_open_function(tvb, tree, offset);
+
+ /* allocation size */
+ proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* 8 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
+ offset += 8;
+
+ BYTE_COUNT;
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
+ }
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+static const true_false_string tfs_ipc_state_nonblocking = {
+ "Reads/writes return immediately if no data available",
+ "Reads/writes block if no data available"
+};
+static const value_string ipc_state_endpoint_vals[] = {
+ { 0, "Consumer end of pipe"},
+ { 1, "Server end of pipe"},
+ {0, NULL}
+};
+static const value_string ipc_state_pipe_type_vals[] = {
+ { 0, "Byte stream pipe"},
+ { 1, "Message pipe"},
+ {0, NULL}
+};
+static const value_string ipc_state_read_mode_vals[] = {
+ { 0, "Read pipe as a byte stream"},
+ { 1, "Read messages from pipe"},
+ {0, NULL}
+};
+
+int
+dissect_ipc_state(tvbuff_t *tvb, proto_tree *parent_tree, int offset,
+ gboolean setstate)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "IPC State: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_ipc_state);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_ipc_state_nonblocking,
+ tvb, offset, 2, mask);
+ if (!setstate) {
+ proto_tree_add_uint(tree, hf_smb_ipc_state_endpoint,
+ tvb, offset, 2, mask);
+ proto_tree_add_uint(tree, hf_smb_ipc_state_pipe_type,
+ tvb, offset, 2, mask);
+ }
+ proto_tree_add_uint(tree, hf_smb_ipc_state_read_mode,
+ tvb, offset, 2, mask);
+ if (!setstate) {
+ proto_tree_add_uint(tree, hf_smb_ipc_state_icount,
+ tvb, offset, 2, mask);
+ }
+
+ offset += 2;
+
+ return offset;
+}
+
+static int
+dissect_open_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0, bc;
+ guint16 fid;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* File Attributes */
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+
+ /* last write time */
+ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time);
+
+ /* File Size */
+ proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* granted access */
+ offset = dissect_access(tvb, tree, offset, "Granted");
+
+ /* File Type */
+ proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* IPC State */
+ offset = dissect_ipc_state(tvb, tree, offset, FALSE);
+
+ /* open_action */
+ offset = dissect_open_action(tvb, tree, offset);
+
+ /* server fid */
+ proto_tree_add_item(tree, hf_smb_server_fid, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+static int
+dissect_read_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0, bc, maxcnt_low;
+ guint32 maxcnt_high;
+ guint32 maxcnt=0;
+ guint32 ofs = 0;
+ smb_info_t *si;
+ unsigned int fid;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, (guint16) fid);
+ offset += 2;
+ if (!pinfo->fd->flags.visited) {
+ /* remember the FID for the processing of the response */
+ si = (smb_info_t *)pinfo->private_data;
+ si->sip->extra_info=(void *)fid;
+ }
+
+ /* offset */
+ ofs = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* max count low */
+ maxcnt_low = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_max_count_low, tvb, offset, 2, maxcnt_low);
+ offset += 2;
+
+ /* min count */
+ proto_tree_add_item(tree, hf_smb_min_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /*
+ * max count high
+ *
+ * XXX - we should really only do this in case we have seen
+ * LARGE FILE being negotiated. Unfortunately, we might not
+ * have seen the negotiation phase in the capture....
+ *
+ * XXX - this is shown as a ULONG in the SNIA SMB spec, i.e.
+ * it's 32 bits, but the description says "High 16 bits of
+ * MaxCount if CAP_LARGE_READX".
+ *
+ * The SMB File Sharing Protocol Extensions Version 2.0,
+ * Document Version 3.3 spec doesn't speak of an extra 16
+ * bits in max count, but it does show a 32-bit timeout
+ * after the min count field.
+ *
+ * Perhaps the 32-bit timeout field was hijacked as a 16-bit
+ * high count and a 16-bit reserved field.
+ *
+ * We fetch and display it as 32 bits.
+ *
+ * XXX if maxcount high is 0xFFFFFFFF we assume it is just padding
+ * bytes and we just ignore it.
+ */
+ maxcnt_high = tvb_get_letohl(tvb, offset);
+ if(maxcnt_high==0xffffffff){
+ maxcnt_high=0;
+ } else {
+ proto_tree_add_uint(tree, hf_smb_max_count_high, tvb, offset, 4, maxcnt_high);
+ }
+
+ offset += 4;
+
+ maxcnt=maxcnt_high;
+ maxcnt=(maxcnt<<16)|maxcnt_low;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %u byte%s at offset %u", maxcnt,
+ (maxcnt == 1) ? "" : "s", ofs);
+
+ /* remaining */
+ proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ if(wc==12){
+ /* high offset */
+ proto_tree_add_item(tree, hf_smb_high_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+ }
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+static int
+dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0, bc, datalen_low, dataoffset=0;
+ guint32 datalen=0, datalen_high;
+ smb_info_t *si = (smb_info_t *)pinfo->private_data;
+ int fid=0;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* If we have seen the request, then print which FID this refers to */
+ /* first check if we have seen the request */
+ if(si->sip != NULL && si->sip->frame_req>0){
+ fid=(int)si->sip->extra_info;
+ add_fid(tvb, pinfo, tree, 0, 0, (guint16) fid);
+ }
+
+ /* remaining */
+ proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* data compaction mode */
+ proto_tree_add_item(tree, hf_smb_dcm, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* data len low */
+ datalen_low = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_len_low, tvb, offset, 2, datalen_low);
+ offset += 2;
+
+ /* data offset */
+ dataoffset=tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_offset, tvb, offset, 2, dataoffset);
+ offset += 2;
+
+ /* XXX we should really only do this in case we have seen LARGE FILE being negotiated */
+ /* data length high */
+ datalen_high = tvb_get_letohl(tvb, offset);
+ if(datalen_high==0xffffffff){
+ datalen_high=0;
+ } else {
+ proto_tree_add_uint(tree, hf_smb_data_len_high, tvb, offset, 4, datalen_high);
+ }
+ offset += 4;
+
+ datalen=datalen_high;
+ datalen=(datalen<<16)|datalen_low;
+
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %u byte%s", datalen,
+ (datalen == 1) ? "" : "s");
+
+
+ /* 6 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 6, TRUE);
+ offset += 6;
+
+ BYTE_COUNT;
+
+ /* file data, might be DCERPC on a pipe */
+ if(bc){
+ offset = dissect_file_data_maybe_dcerpc(tvb, pinfo, tree,
+ top_tree, offset, bc, (guint16) datalen, 0, (guint16) fid);
+ bc = 0;
+ }
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+static int
+dissect_write_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint32 ofs=0;
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0, bc, dataoffset=0, datalen_low, datalen_high;
+ guint32 datalen=0;
+ smb_info_t *si = (smb_info_t *)pinfo->private_data;
+ unsigned int fid=0;
+ guint16 mode = 0;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, (guint16) fid);
+ offset += 2;
+ if (!pinfo->fd->flags.visited) {
+ /* remember the FID for the processing of the response */
+ si->sip->extra_info=(void *)fid;
+ }
+
+ /* offset */
+ ofs = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* reserved */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* mode */
+ mode = tvb_get_letohs(tvb, offset);
+ offset = dissect_write_mode(tvb, tree, offset, 0x000f);
+
+ /* remaining */
+ proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* XXX we should really only do this in case we have seen LARGE FILE being negotiated */
+ /* data length high */
+ datalen_high = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_len_high, tvb, offset, 2, datalen_high);
+ offset += 2;
+
+ /* data len low */
+ datalen_low = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_len_low, tvb, offset, 2, datalen_low);
+ offset += 2;
+
+ datalen=datalen_high;
+ datalen=(datalen<<16)|datalen_low;
+
+ /* data offset */
+ dataoffset=tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_offset, tvb, offset, 2, dataoffset);
+ offset += 2;
+
+ /* FIXME: handle Large (48-bit) byte/offset to COL_INFO */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %u byte%s at offset %u", datalen,
+ (datalen == 1) ? "" : "s", ofs);
+
+ if(wc==14){
+ /* high offset */
+ proto_tree_add_item(tree, hf_smb_high_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+ }
+
+ BYTE_COUNT;
+
+ /* if both the MessageStart and the WriteRawNamedPipe flags are set
+ the first two bytes of the payload is the length of the data.
+ Assume that all WriteAndX PDUs that have MESSAGE_START set to
+ be over the IPC$ share and thus they all transport DCERPC.
+ (if we didnt already know that from the TreeConnect call)
+ */
+ if(mode&WRITE_MODE_MESSAGE_START){
+ if(mode&WRITE_MODE_RAW){
+ proto_tree_add_item(tree, hf_smb_pipe_write_len, tvb, offset, 2, TRUE);
+ offset += 2;
+ dataoffset += 2;
+ bc -= 2;
+ datalen -= 2;
+ }
+ if(!pinfo->fd->flags.visited){
+ /* In case we did not see the TreeConnect call,
+ store this TID here as well as a IPC TID
+ so we know that future Read/Writes to this
+ TID is (probably) DCERPC.
+ */
+ if(g_hash_table_lookup(si->ct->tid_service, (void *)si->tid)){
+ g_hash_table_remove(si->ct->tid_service, (void *)si->tid);
+ }
+ g_hash_table_insert(si->ct->tid_service, (void *)si->tid, (void *)TID_IPC);
+ }
+ if(si->sip){
+ si->sip->flags|=SMB_SIF_TID_IS_IPC;
+ }
+ }
+
+ /* file data, might be DCERPC on a pipe */
+ if (bc != 0) {
+ offset = dissect_file_data_maybe_dcerpc(tvb, pinfo, tree,
+ top_tree, offset, bc, (guint16) datalen, 0, (guint16) fid);
+ bc = 0;
+ }
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+static int
+dissect_write_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0, bc, count_low, count_high;
+ guint32 count=0;
+ smb_info_t *si;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* If we have seen the request, then print which FID this refers to */
+ si = (smb_info_t *)pinfo->private_data;
+ /* first check if we have seen the request */
+ if(si->sip != NULL && si->sip->frame_req>0){
+ add_fid(tvb, pinfo, tree, 0, 0, (guint16) GPOINTER_TO_UINT(si->sip->extra_info));
+ }
+
+ /* write count low */
+ count_low = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_count_low, tvb, offset, 2, count_low);
+ offset += 2;
+
+ /* remaining */
+ proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* XXX we should really only do this in case we have seen LARGE FILE being negotiated */
+ /* write count high */
+ count_high = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_count_high, tvb, offset, 2, count_high);
+ offset += 2;
+
+ count=count_high;
+ count=(count<<16)|count_low;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", %u byte%s", count,
+ (count == 1) ? "" : "s");
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+
+static const true_false_string tfs_setup_action_guest = {
+ "Logged in as GUEST",
+ "Not logged in as GUEST"
+};
+static int
+dissect_setup_action(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Action: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_setup_action);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_setup_action_guest,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+
+static int
+dissect_session_setup_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 bc;
+ guint16 andxoffset=0;
+ smb_info_t *si = pinfo->private_data;
+ int an_len;
+ const char *an;
+ int dn_len;
+ const char *dn;
+ guint16 pwlen=0;
+ guint16 sbloblen=0, sbloblen_short;
+ guint16 apwlen=0, upwlen=0;
+ gboolean unicodeflag;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* Maximum Buffer Size */
+ proto_tree_add_item(tree, hf_smb_max_buf_size, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* Maximum Multiplex Count */
+ proto_tree_add_item(tree, hf_smb_max_mpx_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* VC Number */
+ proto_tree_add_item(tree, hf_smb_vc_num, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* session key */
+ proto_tree_add_item(tree, hf_smb_session_key, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ switch (wc) {
+ case 10:
+ /* password length, ASCII*/
+ pwlen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_password_len,
+ tvb, offset, 2, pwlen);
+ offset += 2;
+
+ /* 4 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ break;
+
+ case 12:
+ /* security blob length */
+ sbloblen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_security_blob_len, tvb, offset, 2, sbloblen);
+ offset += 2;
+
+ /* 4 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* capabilities */
+ dissect_negprot_capabilities(tvb, tree, offset);
+ offset += 4;
+
+ break;
+
+ case 13:
+ /* password length, ANSI*/
+ apwlen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_ansi_password_len,
+ tvb, offset, 2, apwlen);
+ offset += 2;
+
+ /* password length, Unicode*/
+ upwlen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_unicode_password_len,
+ tvb, offset, 2, upwlen);
+ offset += 2;
+
+ /* 4 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* capabilities */
+ dissect_negprot_capabilities(tvb, tree, offset);
+ offset += 4;
+
+ break;
+ }
+
+ BYTE_COUNT;
+
+ if (wc==12) {
+ proto_item *blob_item;
+
+ /* security blob */
+ /* If it runs past the end of the captured data, don't
+ * try to put all of it into the protocol tree as the
+ * raw security blob; we might get an exception on
+ * short frames and then we will not see anything at all
+ * of the security blob.
+ */
+ sbloblen_short = sbloblen;
+ if(sbloblen_short>tvb_length_remaining(tvb,offset)){
+ sbloblen_short=tvb_length_remaining(tvb,offset);
+ }
+ blob_item = proto_tree_add_item(tree, hf_smb_security_blob,
+ tvb, offset, sbloblen_short,
+ TRUE);
+
+ /* As an optimization, because Windows is perverse,
+ we check to see if NTLMSSP is the first part of the
+ blob, and if so, call the NTLMSSP dissector,
+ otherwise we call the GSS-API dissector. This is because
+ Windows can request RAW NTLMSSP, but will happily handle
+ a client that wraps NTLMSSP in SPNEGO
+ */
+
+ if(sbloblen){
+ tvbuff_t *blob_tvb;
+ proto_tree *blob_tree;
+
+ blob_tree = proto_item_add_subtree(blob_item,
+ ett_smb_secblob);
+ CHECK_BYTE_COUNT(sbloblen);
+
+ /*
+ * Set the reported length of this to the reported
+ * length of the blob, rather than the amount of
+ * data available from the blob, so that we'll
+ * throw the right exception if it's too short.
+ */
+ blob_tvb = tvb_new_subset(tvb, offset, sbloblen_short,
+ sbloblen);
+
+ if (si && si->ct && si->ct->raw_ntlmssp &&
+ tvb_strneql(tvb, offset, "NTLMSSP", 7) == 0) {
+ call_dissector(ntlmssp_handle, blob_tvb, pinfo,
+ blob_tree);
+
+ }
+ else {
+ call_dissector(gssapi_handle, blob_tvb,
+ pinfo, blob_tree);
+ }
+
+ COUNT_BYTES(sbloblen);
+ }
+
+ /* OS
+ * Eventhough this field should honour the unicode flag
+ * some ms clients gets this wrong.
+ * At least XP SP1 sends this in ASCII
+ * even when the unicode flag is on.
+ * Test if the first three bytes are "Win"
+ * and if so just override the flag.
+ */
+ unicodeflag=si->unicode;
+ if( tvb_strneql(tvb, offset, "Win", 3) == 0 ){
+ unicodeflag=FALSE;
+ }
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ unicodeflag, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_os, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ /* LANMAN */
+ /* XXX - pre-W2K NT systems appear to stick an extra 2 bytes of
+ * padding/null string/whatever in front of this. W2K doesn't
+ * appear to. I suspect that's a bug that got fixed; I also
+ * suspect that, in practice, nobody ever looks at that field
+ * because the bug didn't appear to get fixed until NT 5.0....
+ *
+ * Eventhough this field should honour the unicode flag
+ * some ms clients gets this wrong.
+ * At least XP SP1 sends this in ASCII
+ * even when the unicode flag is on.
+ * Test if the first three bytes are "Win"
+ * and if so just override the flag.
+ */
+ unicodeflag=si->unicode;
+ if( tvb_strneql(tvb, offset, "Win", 3) == 0 ){
+ unicodeflag=FALSE;
+ }
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ unicodeflag, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_lanman, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ /* Primary domain */
+ /* XXX - pre-W2K NT systems sometimes appear to stick an extra
+ * byte in front of this, at least if all the strings are
+ * ASCII and the account name is empty. Another bug?
+ */
+ dn = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &dn_len, FALSE, FALSE, &bc);
+ if (dn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
+ offset, dn_len, dn);
+ COUNT_BYTES(dn_len);
+ } else {
+ switch (wc) {
+
+ case 10:
+ if(pwlen){
+ /* password, ASCII */
+ CHECK_BYTE_COUNT(pwlen);
+ proto_tree_add_item(tree, hf_smb_password,
+ tvb, offset, pwlen, TRUE);
+ COUNT_BYTES(pwlen);
+ }
+
+ break;
+
+ case 13:
+ if(apwlen){
+ /* password, ANSI */
+ CHECK_BYTE_COUNT(apwlen);
+ proto_tree_add_item(tree, hf_smb_ansi_password,
+ tvb, offset, apwlen, TRUE);
+ COUNT_BYTES(apwlen);
+ }
+
+ if(upwlen){
+ proto_item *item;
+
+ /* password, Unicode */
+ CHECK_BYTE_COUNT(upwlen);
+ item = proto_tree_add_item(tree, hf_smb_unicode_password,
+ tvb, offset, upwlen, TRUE);
+
+ if (upwlen > 24) {
+ proto_tree *subtree;
+
+ subtree = proto_item_add_subtree(item, ett_smb_unicode_password);
+
+ dissect_ntlmv2_response(
+ tvb, subtree, offset, upwlen);
+ }
+
+ COUNT_BYTES(upwlen);
+ }
+
+ break;
+ }
+
+ /* Account Name */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_account, tvb, offset, an_len,
+ an);
+ COUNT_BYTES(an_len);
+
+ /* Primary domain */
+ /* XXX - pre-W2K NT systems sometimes appear to stick an extra
+ * byte in front of this, at least if all the strings are
+ * ASCII and the account name is empty. Another bug?
+ */
+ dn = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &dn_len, FALSE, FALSE, &bc);
+ if (dn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
+ offset, dn_len, dn);
+ COUNT_BYTES(dn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", User: ");
+
+ if (!dn[0] && !an[0])
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "anonymous");
+ else
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "%s\\%s", dn,an);
+ }
+
+ /* OS */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_os, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ /* LANMAN */
+ /* XXX - pre-W2K NT systems appear to stick an extra 2 bytes of
+ * padding/null string/whatever in front of this. W2K doesn't
+ * appear to. I suspect that's a bug that got fixed; I also
+ * suspect that, in practice, nobody ever looks at that field
+ * because the bug didn't appear to get fixed until NT 5.0....
+ */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_lanman, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+ }
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+static int
+dissect_session_setup_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0, bc;
+ guint16 sbloblen=0;
+ smb_info_t *si = pinfo->private_data;
+ int an_len;
+ const char *an;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* flags */
+ offset = dissect_setup_action(tvb, tree, offset);
+
+ if(wc==4){
+ /* security blob length */
+ sbloblen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_security_blob_len, tvb, offset, 2, sbloblen);
+ offset += 2;
+ }
+
+ BYTE_COUNT;
+
+ if(wc==4) {
+ proto_item *blob_item;
+
+ /* security blob */
+ /* dont try to eat too much of we might get an exception on
+ * short frames and then we will not see anything at all
+ * of the security blob.
+ */
+ if(sbloblen>tvb_length_remaining(tvb,offset)){
+ sbloblen=tvb_length_remaining(tvb,offset);
+ }
+ blob_item = proto_tree_add_item(tree, hf_smb_security_blob,
+ tvb, offset, sbloblen, TRUE);
+
+ if(sbloblen){
+ tvbuff_t *blob_tvb;
+ proto_tree *blob_tree;
+
+ blob_tree = proto_item_add_subtree(blob_item,
+ ett_smb_secblob);
+ CHECK_BYTE_COUNT(sbloblen);
+
+ blob_tvb = tvb_new_subset(tvb, offset, sbloblen,
+ sbloblen);
+
+ if (si && si->ct && si->ct->raw_ntlmssp &&
+ tvb_strneql(tvb, offset, "NTLMSSP", 7) == 0) {
+ call_dissector(ntlmssp_handle, blob_tvb, pinfo,
+ blob_tree);
+
+ }
+ else {
+ call_dissector(gssapi_handle, blob_tvb, pinfo,
+ blob_tree);
+
+ }
+
+ COUNT_BYTES(sbloblen);
+ }
+ }
+
+ /* OS */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_os, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ /* LANMAN */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_lanman, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ if(wc==3) {
+ /* Primary domain */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_primary_domain, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+ }
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_empty_andx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+
+static const true_false_string tfs_connect_support_search = {
+ "Exclusive search bits supported",
+ "Exclusive search bits not supported"
+};
+static const true_false_string tfs_connect_support_in_dfs = {
+ "Share is in Dfs",
+ "Share isn't in Dfs"
+};
+
+static int
+dissect_connect_support_bits(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Optional Support: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_connect_support_bits);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_connect_support_search,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_connect_support_in_dfs,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+static const true_false_string tfs_disconnect_tid = {
+ "DISCONNECT TID",
+ "Do NOT disconnect TID"
+};
+
+static int
+dissect_connect_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Flags: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_connect_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_connect_flags_dtid,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+static int
+dissect_tree_connect_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 bc;
+ guint16 andxoffset=0, pwlen=0;
+ smb_info_t *si = pinfo->private_data;
+ int an_len;
+ const char *an;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* flags */
+ offset = dissect_connect_flags(tvb, tree, offset);
+
+ /* password length*/
+ pwlen = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_password_len, tvb, offset, 2, pwlen);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* password */
+ CHECK_BYTE_COUNT(pwlen);
+ proto_tree_add_item(tree, hf_smb_password,
+ tvb, offset, pwlen, TRUE);
+ COUNT_BYTES(pwlen);
+
+ /* Path */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_path, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", an);
+ }
+
+ /*
+ * NOTE: the Service string is always ASCII, even if the
+ * "strings are Unicode" bit is set in the flags2 field
+ * of the SMB.
+ */
+
+ /* Service */
+ /* XXX - what if this runs past bc? */
+ an_len = tvb_strsize(tvb, offset);
+ CHECK_BYTE_COUNT(an_len);
+ an = tvb_get_ptr(tvb, offset, an_len);
+ proto_tree_add_string(tree, hf_smb_service, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_tree_connect_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, wleft, cmd=0xff;
+ guint16 andxoffset=0;
+ guint16 bc;
+ int an_len;
+ const char *an;
+ smb_info_t *si = pinfo->private_data;
+
+ WORD_COUNT;
+
+ wleft = wc; /* this is at least 1 */
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ wleft--;
+ if (wleft == 0)
+ goto bytecount;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+ wleft--;
+ if (wleft == 0)
+ goto bytecount;
+
+ /* flags */
+ offset = dissect_connect_support_bits(tvb, tree, offset);
+ wleft--;
+
+ /* XXX - I've seen captures where this is 7, but I have no
+ idea how to dissect it. I'm guessing the third word
+ contains connect support bits, which looks plausible
+ from the values I've seen. */
+
+ while (wleft != 0) {
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Word parameter: 0x%04x", tvb_get_letohs(tvb, offset));
+ offset += 2;
+ wleft--;
+ }
+
+ BYTE_COUNT;
+
+ /*
+ * NOTE: even though the SNIA CIFS spec doesn't say there's
+ * a "Service" string if there's a word count of 2, the
+ * document at
+ *
+ * ftp://ftp.microsoft.com/developr/drg/CIFS/dosextp.txt
+ *
+ * (it's in an ugly format - text intended to be sent to a
+ * printer, with backspaces and overstrikes used for boldfacing
+ * and underlining; UNIX "col -b" can be used to strip the
+ * overstrikes out) says there's a "Service" string there, and
+ * some network traffic has it.
+ */
+
+ /*
+ * NOTE: the Service string is always ASCII, even if the
+ * "strings are Unicode" bit is set in the flags2 field
+ * of the SMB.
+ */
+
+ /* Service */
+ /* XXX - what if this runs past bc? */
+ an_len = tvb_strsize(tvb, offset);
+ CHECK_BYTE_COUNT(an_len);
+ an = tvb_get_ptr(tvb, offset, an_len);
+ proto_tree_add_string(tree, hf_smb_service, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+
+ /* Now when we know the service type, store it so that we know it for later commands down
+ this tree */
+ if(!pinfo->fd->flags.visited){
+ /* Remove any previous entry for this TID */
+ if(g_hash_table_lookup(si->ct->tid_service, (void *)si->tid)){
+ g_hash_table_remove(si->ct->tid_service, (void *)si->tid);
+ }
+ if(strcmp(an,"IPC") == 0){
+ g_hash_table_insert(si->ct->tid_service, (void *)si->tid, (void *)TID_IPC);
+ } else {
+ g_hash_table_insert(si->ct->tid_service, (void *)si->tid, (void *)TID_NORMAL);
+ }
+ }
+
+
+ if(wc==3){
+ if (bc != 0) {
+ /*
+ * Sometimes this isn't present.
+ */
+
+ /* Native FS */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, /*TRUE*/FALSE, FALSE,
+ &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_fs, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+ }
+ }
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ NT Transaction command begins here
+ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+#define NT_TRANS_CREATE 1
+#define NT_TRANS_IOCTL 2
+#define NT_TRANS_SSD 3
+#define NT_TRANS_NOTIFY 4
+#define NT_TRANS_RENAME 5
+#define NT_TRANS_QSD 6
+#define NT_TRANS_GET_USER_QUOTA 7
+#define NT_TRANS_SET_USER_QUOTA 8
+const value_string nt_cmd_vals[] = {
+ {NT_TRANS_CREATE, "NT CREATE"},
+ {NT_TRANS_IOCTL, "NT IOCTL"},
+ {NT_TRANS_SSD, "NT SET SECURITY DESC"},
+ {NT_TRANS_NOTIFY, "NT NOTIFY"},
+ {NT_TRANS_RENAME, "NT RENAME"},
+ {NT_TRANS_QSD, "NT QUERY SECURITY DESC"},
+ {NT_TRANS_GET_USER_QUOTA, "NT GET USER QUOTA"},
+ {NT_TRANS_SET_USER_QUOTA, "NT SET USER QUOTA"},
+ {0, NULL}
+};
+
+static const value_string nt_ioctl_isfsctl_vals[] = {
+ {0, "Device IOCTL"},
+ {1, "FS control : FSCTL"},
+ {0, NULL}
+};
+
+#define NT_IOCTL_FLAGS_ROOT_HANDLE 0x01
+static const true_false_string tfs_nt_ioctl_flags_root_handle = {
+ "Apply the command to share root handle (MUST BE Dfs)",
+ "Apply to this share",
+};
+
+static const value_string nt_notify_action_vals[] = {
+ {1, "ADDED (object was added"},
+ {2, "REMOVED (object was removed)"},
+ {3, "MODIFIED (object was modified)"},
+ {4, "RENAMED_OLD_NAME (this is the old name of object)"},
+ {5, "RENAMED_NEW_NAME (this is the new name of object)"},
+ {6, "ADDED_STREAM (a stream was added)"},
+ {7, "REMOVED_STREAM (a stream was removed)"},
+ {8, "MODIFIED_STREAM (a stream was modified)"},
+ {0, NULL}
+};
+
+static const value_string watch_tree_vals[] = {
+ {0, "Current directory only"},
+ {1, "Subdirectories also"},
+ {0, NULL}
+};
+
+#define NT_NOTIFY_STREAM_WRITE 0x00000800
+#define NT_NOTIFY_STREAM_SIZE 0x00000400
+#define NT_NOTIFY_STREAM_NAME 0x00000200
+#define NT_NOTIFY_SECURITY 0x00000100
+#define NT_NOTIFY_EA 0x00000080
+#define NT_NOTIFY_CREATION 0x00000040
+#define NT_NOTIFY_LAST_ACCESS 0x00000020
+#define NT_NOTIFY_LAST_WRITE 0x00000010
+#define NT_NOTIFY_SIZE 0x00000008
+#define NT_NOTIFY_ATTRIBUTES 0x00000004
+#define NT_NOTIFY_DIR_NAME 0x00000002
+#define NT_NOTIFY_FILE_NAME 0x00000001
+static const true_false_string tfs_nt_notify_stream_write = {
+ "Notify on changes to STREAM WRITE",
+ "Do NOT notify on changes to stream write",
+};
+static const true_false_string tfs_nt_notify_stream_size = {
+ "Notify on changes to STREAM SIZE",
+ "Do NOT notify on changes to stream size",
+};
+static const true_false_string tfs_nt_notify_stream_name = {
+ "Notify on changes to STREAM NAME",
+ "Do NOT notify on changes to stream name",
+};
+static const true_false_string tfs_nt_notify_security = {
+ "Notify on changes to SECURITY",
+ "Do NOT notify on changes to security",
+};
+static const true_false_string tfs_nt_notify_ea = {
+ "Notify on changes to EA",
+ "Do NOT notify on changes to EA",
+};
+static const true_false_string tfs_nt_notify_creation = {
+ "Notify on changes to CREATION TIME",
+ "Do NOT notify on changes to creation time",
+};
+static const true_false_string tfs_nt_notify_last_access = {
+ "Notify on changes to LAST ACCESS TIME",
+ "Do NOT notify on changes to last access time",
+};
+static const true_false_string tfs_nt_notify_last_write = {
+ "Notify on changes to LAST WRITE TIME",
+ "Do NOT notify on changes to last write time",
+};
+static const true_false_string tfs_nt_notify_size = {
+ "Notify on changes to SIZE",
+ "Do NOT notify on changes to size",
+};
+static const true_false_string tfs_nt_notify_attributes = {
+ "Notify on changes to ATTRIBUTES",
+ "Do NOT notify on changes to attributes",
+};
+static const true_false_string tfs_nt_notify_dir_name = {
+ "Notify on changes to DIR NAME",
+ "Do NOT notify on changes to dir name",
+};
+static const true_false_string tfs_nt_notify_file_name = {
+ "Notify on changes to FILE NAME",
+ "Do NOT notify on changes to file name",
+};
+
+static const value_string create_disposition_vals[] = {
+ {0, "Supersede (supersede existing file (if it exists))"},
+ {1, "Open (if file exists open it, else fail)"},
+ {2, "Create (if file exists fail, else create it)"},
+ {3, "Open If (if file exists open it, else create it)"},
+ {4, "Overwrite (if file exists overwrite, else fail)"},
+ {5, "Overwrite If (if file exists overwrite, else create it)"},
+ {0, NULL}
+};
+
+static const value_string impersonation_level_vals[] = {
+ {0, "Anonymous"},
+ {1, "Identification"},
+ {2, "Impersonation"},
+ {3, "Delegation"},
+ {0, NULL}
+};
+
+static const true_false_string tfs_nt_security_flags_context_tracking = {
+ "Security tracking mode is DYNAMIC",
+ "Security tracking mode is STATIC",
+};
+
+static const true_false_string tfs_nt_security_flags_effective_only = {
+ "ONLY ENABLED aspects of the client's security context are available",
+ "ALL aspects of the client's security context are available",
+};
+
+static const true_false_string tfs_nt_create_bits_oplock = {
+ "Requesting OPLOCK",
+ "Does NOT request oplock"
+};
+
+static const true_false_string tfs_nt_create_bits_boplock = {
+ "Requesting BATCH OPLOCK",
+ "Does NOT request batch oplock"
+};
+
+/*
+ * XXX - must be a directory, and can be a file, or can be a directory,
+ * and must be a file?
+ */
+static const true_false_string tfs_nt_create_bits_dir = {
+ "Target of open MUST be a DIRECTORY",
+ "Target of open can be a file"
+};
+
+static const true_false_string tfs_nt_create_bits_ext_resp = {
+ "Extended responses required",
+ "Extended responses NOT required"
+};
+
+static const true_false_string tfs_nt_access_mask_generic_read = {
+ "GENERIC READ is set",
+ "Generic read is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_generic_write = {
+ "GENERIC WRITE is set",
+ "Generic write is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_generic_execute = {
+ "GENERIC EXECUTE is set",
+ "Generic execute is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_generic_all = {
+ "GENERIC ALL is set",
+ "Generic all is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_maximum_allowed = {
+ "MAXIMUM ALLOWED is set",
+ "Maximum allowed is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_system_security = {
+ "SYSTEM SECURITY is set",
+ "System security is NOT set"
+};
+static const true_false_string tfs_nt_access_mask_synchronize = {
+ "Can wait on handle to SYNCHRONIZE on completion of I/O",
+ "Can NOT wait on handle to synchronize on completion of I/O"
+};
+static const true_false_string tfs_nt_access_mask_write_owner = {
+ "Can WRITE OWNER (take ownership)",
+ "Can NOT write owner (take ownership)"
+};
+static const true_false_string tfs_nt_access_mask_write_dac = {
+ "OWNER may WRITE the DAC",
+ "Owner may NOT write to the DAC"
+};
+static const true_false_string tfs_nt_access_mask_read_control = {
+ "READ ACCESS to owner, group and ACL of the SID",
+ "Read access is NOT granted to owner, group and ACL of the SID"
+};
+static const true_false_string tfs_nt_access_mask_delete = {
+ "DELETE access",
+ "NO delete access"
+};
+static const true_false_string tfs_nt_access_mask_write_attributes = {
+ "WRITE ATTRIBUTES access",
+ "NO write attributes access"
+};
+static const true_false_string tfs_nt_access_mask_read_attributes = {
+ "READ ATTRIBUTES access",
+ "NO read attributes access"
+};
+static const true_false_string tfs_nt_access_mask_delete_child = {
+ "DELETE CHILD access",
+ "NO delete child access"
+};
+static const true_false_string tfs_nt_access_mask_execute = {
+ "EXECUTE access",
+ "NO execute access"
+};
+static const true_false_string tfs_nt_access_mask_write_ea = {
+ "WRITE EXTENDED ATTRIBUTES access",
+ "NO write extended attributes access"
+};
+static const true_false_string tfs_nt_access_mask_read_ea = {
+ "READ EXTENDED ATTRIBUTES access",
+ "NO read extended attributes access"
+};
+static const true_false_string tfs_nt_access_mask_append = {
+ "APPEND access",
+ "NO append access"
+};
+static const true_false_string tfs_nt_access_mask_write = {
+ "WRITE access",
+ "NO write access"
+};
+static const true_false_string tfs_nt_access_mask_read = {
+ "READ access",
+ "NO read access"
+};
+
+static const true_false_string tfs_nt_share_access_delete = {
+ "Object can be shared for DELETE",
+ "Object can NOT be shared for delete"
+};
+static const true_false_string tfs_nt_share_access_write = {
+ "Object can be shared for WRITE",
+ "Object can NOT be shared for write"
+};
+static const true_false_string tfs_nt_share_access_read = {
+ "Object can be shared for READ",
+ "Object can NOT be shared for read"
+};
+
+static const value_string oplock_level_vals[] = {
+ {0, "No oplock granted"},
+ {1, "Exclusive oplock granted"},
+ {2, "Batch oplock granted"},
+ {3, "Level II oplock granted"},
+ {0, NULL}
+};
+
+static const value_string device_type_vals[] = {
+ {0x00000001, "Beep"},
+ {0x00000002, "CDROM"},
+ {0x00000003, "CDROM Filesystem"},
+ {0x00000004, "Controller"},
+ {0x00000005, "Datalink"},
+ {0x00000006, "Dfs"},
+ {0x00000007, "Disk"},
+ {0x00000008, "Disk Filesystem"},
+ {0x00000009, "Filesystem"},
+ {0x0000000a, "Inport Port"},
+ {0x0000000b, "Keyboard"},
+ {0x0000000c, "Mailslot"},
+ {0x0000000d, "MIDI-In"},
+ {0x0000000e, "MIDI-Out"},
+ {0x0000000f, "Mouse"},
+ {0x00000010, "Multi UNC Provider"},
+ {0x00000011, "Named Pipe"},
+ {0x00000012, "Network"},
+ {0x00000013, "Network Browser"},
+ {0x00000014, "Network Filesystem"},
+ {0x00000015, "NULL"},
+ {0x00000016, "Parallel Port"},
+ {0x00000017, "Physical card"},
+ {0x00000018, "Printer"},
+ {0x00000019, "Scanner"},
+ {0x0000001a, "Serial Mouse port"},
+ {0x0000001b, "Serial port"},
+ {0x0000001c, "Screen"},
+ {0x0000001d, "Sound"},
+ {0x0000001e, "Streams"},
+ {0x0000001f, "Tape"},
+ {0x00000020, "Tape Filesystem"},
+ {0x00000021, "Transport"},
+ {0x00000022, "Unknown"},
+ {0x00000023, "Video"},
+ {0x00000024, "Virtual Disk"},
+ {0x00000025, "WAVE-In"},
+ {0x00000026, "WAVE-Out"},
+ {0x00000027, "8042 Port"},
+ {0x00000028, "Network Redirector"},
+ {0x00000029, "Battery"},
+ {0x0000002a, "Bus Extender"},
+ {0x0000002b, "Modem"},
+ {0x0000002c, "VDM"},
+ {0, NULL}
+};
+
+static const value_string is_directory_vals[] = {
+ {0, "This is NOT a directory"},
+ {1, "This is a DIRECTORY"},
+ {0, NULL}
+};
+
+typedef struct _nt_trans_data {
+ int subcmd;
+ guint32 sd_len;
+ guint32 ea_len;
+} nt_trans_data;
+
+
+
+static int
+dissect_nt_security_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint8 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_guint8(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+ "Security Flags: 0x%02x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_nt_security_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_nt_security_flags_context_tracking,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_security_flags_effective_only,
+ tvb, offset, 1, mask);
+
+ offset += 1;
+
+ return offset;
+}
+
+static int
+dissect_nt_share_access(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Share Access: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_nt_share_access);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_nt_share_access_delete,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_share_access_write,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_share_access_read,
+ tvb, offset, 4, mask);
+
+ offset += 4;
+
+ return offset;
+}
+
+/* FIXME: need to call dissect_nt_access_mask() instead */
+
+static int
+dissect_smb_access_mask(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Access Mask: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_nt_access_mask);
+ }
+
+ /*
+ * Some of these bits come from
+ *
+ * http://www.samba.org/samba/ftp/specs/smb-nt01.doc
+ *
+ * and others come from the section on ZwOpenFile in "Windows(R)
+ * NT(R)/2000 Native API Reference".
+ */
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_generic_read,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_generic_write,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_generic_execute,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_generic_all,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_maximum_allowed,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_system_security,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_synchronize,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write_owner,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write_dac,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_read_control,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_delete,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write_attributes,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_read_attributes,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_delete_child,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_execute,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write_ea,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_read_ea,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_append,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_write,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_access_mask_read,
+ tvb, offset, 4, mask);
+
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_nt_create_bits(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Create Flags: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_nt_create_bits);
+ }
+
+ /*
+ * XXX - it's 0x00000016 in at least one capture, but
+ * Network Monitor doesn't say what the 0x00000010 bit is.
+ * Does the Win32 API documentation, or NT Native API book,
+ * suggest anything?
+ *
+ * That is the extended response desired bit ... RJS, from Samba
+ * Well, maybe. Samba thinks it is, and uses it to encode
+ * OpLock granted as the high order bit of the Action field
+ * in the response. However, Windows does not do that. Or at least
+ * Win2K doesn't.
+ */
+ proto_tree_add_boolean(tree, hf_smb_nt_create_bits_ext_resp,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_bits_dir,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_bits_boplock,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_bits_oplock,
+ tvb, offset, 4, mask);
+
+ offset += 4;
+
+ return offset;
+}
+
+/*
+ * XXX - there are some more flags in the description of "ZwOpenFile()"
+ * in "Windows(R) NT(R)/2000 Native API Reference"; do those go over
+ * the wire as well? (The spec at
+ *
+ * http://www.samba.org/samba/ftp/specs/smb-nt01.doc
+ *
+ * says that "the FILE_NO_INTERMEDIATE_BUFFERING option is not exported
+ * via the SMB protocol. The NT redirector should convert this option
+ * to FILE_WRITE_THROUGH."
+ *
+ * The "Sync I/O Alert" and "Sync I/O Nonalert" are given the bit
+ * values one would infer from their position in the list of flags for
+ * "ZwOpenFile()". Most of the others probably have those values
+ * as well, although "8.3 only" would collide with FILE_OPEN_FOR_RECOVERY,
+ * which might go over the wire (for the benefit of backup/restore software).
+ */
+static const true_false_string tfs_nt_create_options_directory = {
+ "File being created/opened must be a directory",
+ "File being created/opened must not be a directory"
+};
+static const true_false_string tfs_nt_create_options_write_through = {
+ "Writes should flush buffered data before completing",
+ "Writes need not flush buffered data before completing"
+};
+static const true_false_string tfs_nt_create_options_sequential_only = {
+ "The file will only be accessed sequentially",
+ "The file might not only be accessed sequentially"
+};
+static const true_false_string tfs_nt_create_options_sync_io_alert = {
+ "All operations SYNCHRONOUS, waits subject to termination from alert",
+ "Operations NOT necessarily synchronous"
+};
+static const true_false_string tfs_nt_create_options_sync_io_nonalert = {
+ "All operations SYNCHRONOUS, waits not subject to alert",
+ "Operations NOT necessarily synchronous"
+};
+static const true_false_string tfs_nt_create_options_non_directory = {
+ "File being created/opened must not be a directory",
+ "File being created/opened must be a directory"
+};
+static const true_false_string tfs_nt_create_options_no_ea_knowledge = {
+ "The client does not understand extended attributes",
+ "The client understands extended attributes"
+};
+static const true_false_string tfs_nt_create_options_eight_dot_three_only = {
+ "The client understands only 8.3 file names",
+ "The client understands long file names"
+};
+static const true_false_string tfs_nt_create_options_random_access = {
+ "The file will be accessed randomly",
+ "The file will not be accessed randomly"
+};
+static const true_false_string tfs_nt_create_options_delete_on_close = {
+ "The file should be deleted when it is closed",
+ "The file should not be deleted when it is closed"
+};
+
+static int
+dissect_nt_create_options(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Create Options: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_nt_create_options);
+ }
+
+ /*
+ * From
+ *
+ * http://www.samba.org/samba/ftp/specs/smb-nt01.doc
+ */
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_directory_file,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_write_through,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_sequential_only,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_sync_io_alert,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_sync_io_nonalert,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_non_directory_file,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_no_ea_knowledge,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_eight_dot_three_only,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_random_access,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_create_options_delete_on_close,
+ tvb, offset, 4, mask);
+
+ offset += 4;
+
+ return offset;
+}
+
+static int
+dissect_nt_notify_completion_filter(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Completion Filter: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_nt_notify_completion_filter);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_stream_write,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_stream_size,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_stream_name,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_security,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_ea,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_creation,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_last_access,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_last_write,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_size,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_attributes,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_dir_name,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_notify_file_name,
+ tvb, offset, 4, mask);
+
+ offset += 4;
+ return offset;
+}
+
+static int
+dissect_nt_ioctl_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint8 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_guint8(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+ "Completion Filter: 0x%02x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_nt_ioctl_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_nt_ioctl_flags_root_handle,
+ tvb, offset, 1, mask);
+
+ offset += 1;
+ return offset;
+}
+
+/*
+ * From the section on ZwQuerySecurityObject in "Windows(R) NT(R)/2000
+ * Native API Reference".
+ */
+static const true_false_string tfs_nt_qsd_owner = {
+ "Requesting OWNER security information",
+ "NOT requesting owner security information",
+};
+
+static const true_false_string tfs_nt_qsd_group = {
+ "Requesting GROUP security information",
+ "NOT requesting group security information",
+};
+
+static const true_false_string tfs_nt_qsd_dacl = {
+ "Requesting DACL security information",
+ "NOT requesting DACL security information",
+};
+
+static const true_false_string tfs_nt_qsd_sacl = {
+ "Requesting SACL security information",
+ "NOT requesting SACL security information",
+};
+
+#define NT_QSD_OWNER 0x00000001
+#define NT_QSD_GROUP 0x00000002
+#define NT_QSD_DACL 0x00000004
+#define NT_QSD_SACL 0x00000008
+
+static int
+dissect_security_information_mask(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Security Information: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_security_information_mask);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_nt_qsd_owner,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_qsd_group,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_qsd_dacl,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_nt_qsd_sacl,
+ tvb, offset, 4, mask);
+
+ offset += 4;
+
+ return offset;
+}
+
+static void
+free_g_string(void *arg)
+{
+ g_string_free(arg, TRUE);
+}
+
+/* Dissect a NT SID. Label it with 'name' and return a string version of
+ the SID in the 'sid_str' parameter which must be freed by the caller.
+ hf_sid can be -1 if the caller doesnt care what name is used and then
+ "smb.sid" will be the default instead. If the caller wants a more
+ appropriate hf field, it will just pass a FT_STRING hf field here
+*/
+
+int
+dissect_nt_sid(tvbuff_t *tvb, int offset, proto_tree *parent_tree, char *name,
+ char **sid_str, int hf_sid)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset, sa_offset = offset;
+ gboolean rid_present;
+ guint rid=0;
+ int rid_offset=0;
+ guint8 revision;
+ int rev_offset;
+ guint8 num_auth;
+ int na_offset;
+ guint auth = 0; /* FIXME: What if it is larger than 32-bits */
+ int i;
+ GString *gstr;
+ char sid_string[245];
+ char *sid_name;
+
+ if(hf_sid==-1){
+ hf_sid=hf_smb_sid;
+ }
+
+ /* revision of sid */
+ revision = tvb_get_guint8(tvb, offset);
+ rev_offset = offset;
+ offset += 1;
+
+ switch(revision){
+ case 1:
+ case 2: /* Not sure what the different revision numbers mean */
+ /* number of authorities*/
+ num_auth = tvb_get_guint8(tvb, offset);
+ na_offset = offset;
+ offset += 1;
+
+ /* XXX perhaps we should have these thing searchable?
+ a new FT_xxx thingie? SMB is quite common!*/
+ /* identifier authorities */
+
+ for(i=0;i<6;i++){
+ auth = (auth << 8) + tvb_get_guint8(tvb, offset);
+
+ offset++;
+ }
+
+ sa_offset = offset;
+
+ gstr = g_string_new("");
+
+ CLEANUP_PUSH(free_g_string, gstr);
+
+ /* sub authorities, leave RID to last */
+ for(i=0; i < (num_auth > 4?(num_auth - 1):num_auth); i++){
+ /*
+ * XXX should not be letohl but native byteorder according to
+ * Samba header files.
+ *
+ * However, considering that there were never any NT ports
+ * to big-endian platforms (PowerPC and MIPS ran little-endian,
+ * and IA-64 runs little-endian, as does x86-64), we can (?)
+ * assume that non le byte encodings will be "uncommon"?
+ */
+ g_string_sprintfa(gstr, (i>0 ? "-%u" : "%u"),
+ tvb_get_letohl(tvb, offset));
+ offset+=4;
+ }
+
+
+ if (num_auth > 4) {
+ rid = tvb_get_letohl(tvb, offset);
+ rid_present=TRUE;
+ rid_offset=offset;
+ offset+=4;
+ sprintf(sid_string, "S-1-%u-%s-%u", auth, gstr->str, rid);
+ } else {
+ rid_present=FALSE;
+ sprintf(sid_string, "S-1-%u-%s", auth, gstr->str);
+ }
+
+ sid_name=NULL;
+ if(sid_name_snooping){
+ sid_name=find_sid_name(sid_string);
+ }
+
+ if(parent_tree){
+ if(sid_name){
+ item = proto_tree_add_string_format(parent_tree, hf_sid, tvb, old_offset, offset-old_offset, sid_string, "%s: %s (%s)", name, sid_string, sid_name);
+ } else {
+ item = proto_tree_add_string_format(parent_tree, hf_sid, tvb, old_offset, offset-old_offset, sid_string, "%s: %s", name, sid_string);
+ }
+ tree = proto_item_add_subtree(item, ett_smb_sid);
+ }
+
+ proto_tree_add_item(tree, hf_smb_sid_revision, tvb, rev_offset, 1, TRUE);
+ proto_tree_add_item(tree, hf_smb_sid_num_auth, tvb, na_offset, 1, TRUE);
+ proto_tree_add_text(tree, tvb, na_offset+1, 6, "Authority: %u", auth);
+ proto_tree_add_text(tree, tvb, sa_offset, num_auth * 4, "Sub-authorities: %s", gstr->str);
+
+ if(rid_present){
+ proto_tree_add_text(tree, tvb, rid_offset, 4, "RID: %u", rid);
+ }
+
+ if(sid_str){
+ if(sid_name){
+ *sid_str = g_strdup_printf("%s (%s)", sid_string, sid_name);
+ } else {
+ *sid_str = g_strdup(sid_string);
+ }
+ }
+
+ CLEANUP_CALL_AND_POP;
+ }
+
+
+ return offset;
+}
+
+
+static const value_string ace_type_vals[] = {
+ { 0, "Access Allowed"},
+ { 1, "Access Denied"},
+ { 2, "System Audit"},
+ { 3, "System Alarm"},
+ { 0, NULL}
+};
+static const true_false_string tfs_ace_flags_object_inherit = {
+ "Subordinate files will inherit this ACE",
+ "Subordinate files will not inherit this ACE"
+};
+static const true_false_string tfs_ace_flags_container_inherit = {
+ "Subordinate containers will inherit this ACE",
+ "Subordinate containers will not inherit this ACE"
+};
+static const true_false_string tfs_ace_flags_non_propagate_inherit = {
+ "Subordinate object will not propagate the inherited ACE further",
+ "Subordinate object will propagate the inherited ACE further"
+};
+static const true_false_string tfs_ace_flags_inherit_only = {
+ "This ACE does not apply to the current object",
+ "This ACE applies to the current object"
+};
+static const true_false_string tfs_ace_flags_inherited_ace = {
+ "This ACE was inherited from its parent object",
+ "This ACE was not inherited from its parent object"
+};
+static const true_false_string tfs_ace_flags_successful_access = {
+ "Successful accesses will be audited",
+ "Successful accesses will not be audited"
+};
+static const true_false_string tfs_ace_flags_failed_access = {
+ "Failed accesses will be audited",
+ "Failed accesses will not be audited"
+};
+
+#define APPEND_ACE_TEXT(flag, item, string) \
+ if(flag){ \
+ if(item) \
+ proto_item_append_text(item, string, sep); \
+ sep = ", "; \
+ }
+
+static int
+dissect_nt_v2_ace_flags(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
+ guint8 *data)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ guint8 mask;
+ char *sep = " ";
+
+ mask = tvb_get_guint8(tvb, offset);
+
+ if (data)
+ *data = mask;
+
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+ "NT ACE Flags: 0x%02x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_ace_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_ace_flags_failed_access,
+ tvb, offset, 1, mask);
+ APPEND_ACE_TEXT(mask&0x80, item, "%sFailed Access");
+
+ proto_tree_add_boolean(tree, hf_smb_ace_flags_successful_access,
+ tvb, offset, 1, mask);
+ APPEND_ACE_TEXT(mask&0x40, item, "%sSuccessful Access");
+
+ proto_tree_add_boolean(tree, hf_smb_ace_flags_inherited_ace,
+ tvb, offset, 1, mask);
+ APPEND_ACE_TEXT(mask&0x10, item, "%sInherited ACE");
+
+ proto_tree_add_boolean(tree, hf_smb_ace_flags_inherit_only,
+ tvb, offset, 1, mask);
+ APPEND_ACE_TEXT(mask&0x08, item, "%sInherit Only");
+
+ proto_tree_add_boolean(tree, hf_smb_ace_flags_non_propagate_inherit,
+ tvb, offset, 1, mask);
+ APPEND_ACE_TEXT(mask&0x04, item, "%sNo Propagate Inherit");
+
+ proto_tree_add_boolean(tree, hf_smb_ace_flags_container_inherit,
+ tvb, offset, 1, mask);
+ APPEND_ACE_TEXT(mask&0x02, item, "%sContainer Inherit");
+
+ proto_tree_add_boolean(tree, hf_smb_ace_flags_object_inherit,
+ tvb, offset, 1, mask);
+ APPEND_ACE_TEXT(mask&0x01, item, "%sObject Inherit");
+
+
+ offset += 1;
+ return offset;
+}
+
+/* Dissect an access mask. All this stuff is kind of explained at MSDN:
+
+http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/windows_2000_windows_nt_access_mask_format.asp
+
+*/
+
+static gint ett_nt_access_mask = -1;
+static gint ett_nt_access_mask_generic = -1;
+static gint ett_nt_access_mask_standard = -1;
+static gint ett_nt_access_mask_specific = -1;
+
+static int hf_access_sacl = -1;
+static int hf_access_maximum_allowed = -1;
+static int hf_access_generic_read = -1;
+static int hf_access_generic_write = -1;
+static int hf_access_generic_execute = -1;
+static int hf_access_generic_all = -1;
+static int hf_access_standard_delete = -1;
+static int hf_access_standard_read_control = -1;
+static int hf_access_standard_synchronise = -1;
+static int hf_access_standard_write_dac = -1;
+static int hf_access_standard_write_owner = -1;
+static int hf_access_specific_15 = -1;
+static int hf_access_specific_14 = -1;
+static int hf_access_specific_13 = -1;
+static int hf_access_specific_12 = -1;
+static int hf_access_specific_11 = -1;
+static int hf_access_specific_10 = -1;
+static int hf_access_specific_9 = -1;
+static int hf_access_specific_8 = -1;
+static int hf_access_specific_7 = -1;
+static int hf_access_specific_6 = -1;
+static int hf_access_specific_5 = -1;
+static int hf_access_specific_4 = -1;
+static int hf_access_specific_3 = -1;
+static int hf_access_specific_2 = -1;
+static int hf_access_specific_1 = -1;
+static int hf_access_specific_0 = -1;
+
+/* Map generic permissions to specific permissions */
+
+static void map_generic_access(guint32 *access_mask,
+ struct generic_mapping *mapping)
+{
+ if (*access_mask & GENERIC_READ_ACCESS) {
+ *access_mask &= ~GENERIC_READ_ACCESS;
+ *access_mask |= mapping->generic_read;
+ }
+
+ if (*access_mask & GENERIC_WRITE_ACCESS) {
+ *access_mask &= ~GENERIC_WRITE_ACCESS;
+ *access_mask |= mapping->generic_write;
+ }
+
+ if (*access_mask & GENERIC_EXECUTE_ACCESS) {
+ *access_mask &= ~GENERIC_EXECUTE_ACCESS;
+ *access_mask |= mapping->generic_execute;
+ }
+
+ if (*access_mask & GENERIC_ALL_ACCESS) {
+ *access_mask &= ~GENERIC_ALL_ACCESS;
+ *access_mask |= mapping->generic_all;
+ }
+}
+
+/* Map standard permissions to specific permissions */
+
+static void map_standard_access(guint32 *access_mask,
+ struct standard_mapping *mapping)
+{
+ if (*access_mask & READ_CONTROL_ACCESS) {
+ *access_mask &= ~READ_CONTROL_ACCESS;
+ *access_mask |= mapping->std_read;
+ }
+
+ if (*access_mask & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|
+ SYNCHRONIZE_ACCESS)) {
+ *access_mask &= ~(DELETE_ACCESS|WRITE_DAC_ACCESS|
+ WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS);
+ *access_mask |= mapping->std_all;
+ }
+
+}
+
+int
+dissect_nt_access_mask(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, guint8 *drep, int hfindex,
+ struct access_mask_info *ami, guint32 *perms)
+{
+ proto_item *item;
+ proto_tree *subtree, *generic_tree, *standard_tree, *specific_tree;
+ guint32 access;
+
+ if (drep != NULL) {
+ /*
+ * Called from a DCE RPC protocol dissector, for a
+ * protocol where a 32-bit NDR integer contains
+ * an NT access mask; extract the access mask
+ * with an NDR call.
+ */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hfindex, &access);
+ } else {
+ /*
+ * Called from SMB, where the access mask is just a
+ * 4-byte little-endian quantity with no special
+ * NDR alignment requirement; extract it with
+ * "tvb_get_letohl()".
+ */
+ access = tvb_get_letohl(tvb, offset);
+ offset += 4;
+ }
+
+ if (perms) {
+ *perms = access;
+ }
+
+ item = proto_tree_add_uint(tree, hfindex, tvb, offset - 4, 4, access);
+
+ subtree = proto_item_add_subtree(item, ett_nt_access_mask);
+
+ /* Generic access rights */
+
+ item = proto_tree_add_text(subtree, tvb, offset - 4, 4,
+ "Generic rights: 0x%08x",
+ access & GENERIC_RIGHTS_MASK);
+
+ generic_tree = proto_item_add_subtree(
+ item, ett_nt_access_mask_generic);
+
+ proto_tree_add_boolean(
+ generic_tree, hf_access_generic_read, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ generic_tree, hf_access_generic_write, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ generic_tree, hf_access_generic_execute, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ generic_tree, hf_access_generic_all, tvb, offset - 4, 4,
+ access);
+
+ /* Reserved (??) */
+
+ proto_tree_add_boolean(
+ subtree, hf_access_maximum_allowed, tvb, offset - 4, 4,
+ access);
+
+ /* Access system security */
+
+ proto_tree_add_boolean(
+ subtree, hf_access_sacl, tvb, offset - 4, 4,
+ access);
+
+ /* Standard access rights */
+
+ item = proto_tree_add_text(subtree, tvb, offset - 4, 4,
+ "Standard rights: 0x%08x",
+ access & STANDARD_RIGHTS_MASK);
+
+ standard_tree = proto_item_add_subtree(
+ item, ett_nt_access_mask_standard);
+
+ proto_tree_add_boolean(
+ standard_tree, hf_access_standard_synchronise, tvb,
+ offset - 4, 4, access);
+
+ proto_tree_add_boolean(
+ standard_tree, hf_access_standard_write_owner, tvb,
+ offset - 4, 4, access);
+
+ proto_tree_add_boolean(
+ standard_tree, hf_access_standard_write_dac, tvb,
+ offset - 4, 4, access);
+
+ proto_tree_add_boolean(
+ standard_tree, hf_access_standard_read_control, tvb,
+ offset - 4, 4, access);
+
+ proto_tree_add_boolean(
+ standard_tree, hf_access_standard_delete, tvb, offset - 4, 4,
+ access);
+
+ /* Specific access rights. Call the specific_rights_fn
+ pointer if we have one, otherwise just display bits 0-15 in
+ boring fashion. */
+
+ if (ami && ami->specific_rights_name)
+ item = proto_tree_add_text(subtree, tvb, offset - 4, 4,
+ "%s specific rights: 0x%08x",
+ ami->specific_rights_name,
+ access & SPECIFIC_RIGHTS_MASK);
+ else
+ item = proto_tree_add_text(subtree, tvb, offset - 4, 4,
+ "Specific rights: 0x%08x",
+ access & SPECIFIC_RIGHTS_MASK);
+
+ specific_tree = proto_item_add_subtree(
+ item, ett_nt_access_mask_specific);
+
+ if (ami && ami->specific_rights_fn) {
+ guint32 mapped_access = access;
+ proto_tree *specific_mapped;
+
+ specific_mapped = proto_item_add_subtree(
+ item, ett_nt_access_mask_specific);
+
+ ami->specific_rights_fn(
+ tvb, offset - 4, specific_tree, access);
+
+ if (ami->generic_mapping)
+ map_generic_access(&access, ami->generic_mapping);
+
+ if (ami->standard_mapping)
+ map_standard_access(&access, ami->standard_mapping);
+
+ if (access != mapped_access) {
+ ami->specific_rights_fn(
+ tvb, offset - 4, specific_mapped,
+ mapped_access);
+ }
+
+ return offset;
+ }
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_15, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_14, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_13, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_12, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_11, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_10, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_9, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_8, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_7, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_6, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_5, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_4, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_3, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_2, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_1, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific_tree, hf_access_specific_0, tvb, offset - 4, 4,
+ access);
+
+ return offset;
+}
+
+static int hf_smb_access_mask = -1;
+
+static int
+dissect_nt_v2_ace(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep,
+ struct access_mask_info *ami)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint16 size;
+ char *sid_str = NULL;
+ guint8 type;
+ guint8 flags;
+ guint32 perms = 0;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "NT ACE: ");
+ tree = proto_item_add_subtree(item, ett_smb_ace);
+ }
+
+ /* type */
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_ace_type, tvb, offset, 1, type);
+ offset += 1;
+
+ /* flags */
+ offset = dissect_nt_v2_ace_flags(tvb, offset, tree, &flags);
+
+ /* size */
+ size = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_ace_size, tvb, offset, 2, size);
+ offset += 2;
+
+ /* access mask */
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep,
+ hf_smb_access_mask, ami, &perms);
+
+ /* SID */
+ offset = dissect_nt_sid(tvb, offset, tree, "ACE", &sid_str, -1);
+
+ if (item)
+ proto_item_append_text(
+ item, "%s, flags 0x%02x, %s, mask 0x%08x", sid_str, flags,
+ val_to_str(type, ace_type_vals, "Unknown ACE type (0x%02x)"),
+ perms);
+
+ g_free(sid_str);
+
+ proto_item_set_len(item, offset-old_offset);
+
+ /* Sometimes there is some spare space at the end of the ACE so use
+ the size field to work out where the end is. */
+
+ return old_offset + size;
+}
+
+static int
+dissect_nt_acl(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep, char *name,
+ struct access_mask_info *ami)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ int old_offset = offset;
+ guint8 revision;
+ guint32 num_aces;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
+ "NT %s ACL", name);
+ tree = proto_item_add_subtree(item, ett_smb_acl);
+ }
+
+ /* revision */
+ revision = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_acl_revision,
+ tvb, offset, 1, revision);
+ offset += 2;
+
+ switch(revision){
+ case 2: /* only version we will ever see of this structure?*/
+ case 3:
+ /* size */
+ proto_tree_add_item(tree, hf_smb_acl_size, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* number of ace structures */
+ num_aces = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_acl_num_aces,
+ tvb, offset, 4, num_aces);
+ offset += 4;
+
+ while(num_aces--){
+ offset=dissect_nt_v2_ace(
+ tvb, offset, pinfo, tree, drep, ami);
+ }
+ }
+
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+}
+
+static const true_false_string tfs_sec_desc_type_owner_defaulted = {
+ "OWNER is DEFAULTED",
+ "Owner is NOT defaulted"
+};
+static const true_false_string tfs_sec_desc_type_group_defaulted = {
+ "GROUP is DEFAULTED",
+ "Group is NOT defaulted"
+};
+static const true_false_string tfs_sec_desc_type_dacl_present = {
+ "DACL is PRESENT",
+ "DACL is NOT present"
+};
+static const true_false_string tfs_sec_desc_type_dacl_defaulted = {
+ "DACL is DEFAULTED",
+ "DACL is NOT defaulted"
+};
+static const true_false_string tfs_sec_desc_type_sacl_present = {
+ "SACL is PRESENT",
+ "SACL is NOT present"
+};
+static const true_false_string tfs_sec_desc_type_sacl_defaulted = {
+ "SACL is DEFAULTED",
+ "SACL is NOT defaulted"
+};
+static const true_false_string tfs_sec_desc_type_dacl_auto_inherit_req = {
+ "DACL has AUTO INHERIT REQUIRED",
+ "DACL does NOT require auto inherit"
+};
+static const true_false_string tfs_sec_desc_type_sacl_auto_inherit_req = {
+ "SACL has AUTO INHERIT REQUIRED",
+ "SACL does NOT require auto inherit"
+};
+static const true_false_string tfs_sec_desc_type_dacl_auto_inherited = {
+ "DACL is AUTO INHERITED",
+ "DACL is NOT auto inherited"
+};
+static const true_false_string tfs_sec_desc_type_sacl_auto_inherited = {
+ "SACL is AUTO INHERITED",
+ "SACL is NOT auto inherited"
+};
+static const true_false_string tfs_sec_desc_type_dacl_protected = {
+ "The DACL is PROTECTED",
+ "The DACL is NOT protected"
+};
+static const true_false_string tfs_sec_desc_type_sacl_protected = {
+ "The SACL is PROTECTED",
+ "The SACL is NOT protected"
+};
+static const true_false_string tfs_sec_desc_type_self_relative = {
+ "This SecDesc is SELF RELATIVE",
+ "This SecDesc is NOT self relative"
+};
+
+
+static int
+dissect_nt_sec_desc_type(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ guint16 mask;
+
+ mask = tvb_get_letohs(tvb, offset);
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Type: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_sec_desc_type);
+ }
+
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_self_relative,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_sacl_protected,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_dacl_protected,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_sacl_auto_inherited,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_dacl_auto_inherited,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_sacl_auto_inherit_req,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_dacl_auto_inherit_req,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_sacl_defaulted,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_sacl_present,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_dacl_defaulted,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_dacl_present,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree,hf_smb_sec_desc_type_group_defaulted,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_sec_desc_type_owner_defaulted,
+ tvb, offset, 2, mask);
+
+
+ offset += 2;
+ return offset;
+}
+
+int
+dissect_nt_sec_desc(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, guint8 *drep, int len,
+ struct access_mask_info *ami)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ guint8 revision;
+ int old_offset = offset;
+ guint32 owner_sid_offset;
+ guint32 group_sid_offset;
+ guint32 sacl_offset;
+ guint32 dacl_offset;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ "NT Security Descriptor");
+ tree = proto_item_add_subtree(item, ett_smb_sec_desc);
+ }
+
+ /* revision */
+ revision = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_sec_desc_revision,
+ tvb, offset, 1, revision);
+ offset += 1;
+
+ /* next byte should be zero, for now just ignore it */
+ offset += 1;
+
+
+ switch(revision){
+ case 1: /* only version we will ever see of this structure?*/
+ /* type */
+ offset = dissect_nt_sec_desc_type(tvb, offset, tree);
+
+ /* offset to owner sid */
+ owner_sid_offset = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Offset to owner SID: %u", owner_sid_offset);
+ offset += 4;
+
+ /* offset to group sid */
+ group_sid_offset = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Offset to group SID: %u", group_sid_offset);
+ offset += 4;
+
+ /* offset to sacl */
+ sacl_offset = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Offset to SACL: %u", sacl_offset);
+ offset += 4;
+
+ /* offset to dacl */
+ dacl_offset = tvb_get_letohl(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Offset to DACL: %u", dacl_offset);
+ offset += 4;
+
+ /*owner SID*/
+ if(owner_sid_offset){
+ if (len == -1)
+ offset = dissect_nt_sid(tvb, offset, tree, "Owner", NULL, -1);
+ else
+ dissect_nt_sid(
+ tvb, old_offset+owner_sid_offset, tree, "Owner", NULL, -1);
+ }
+
+ /*group SID*/
+ if(group_sid_offset){
+ dissect_nt_sid(
+ tvb, old_offset+group_sid_offset, tree, "Group", NULL, -1);
+ }
+
+ /* sacl */
+ if(sacl_offset){
+ dissect_nt_acl(tvb, old_offset+sacl_offset, pinfo, tree,
+ drep, "System (SACL)", ami);
+ }
+
+ /* dacl */
+ if(dacl_offset){
+ dissect_nt_acl(tvb, old_offset+dacl_offset, pinfo, tree,
+ drep, "User (DACL)", ami);
+ }
+
+ }
+
+ return offset+len;
+}
+
+static int
+dissect_nt_user_quota(tvbuff_t *tvb, proto_tree *tree, int offset, guint16 *bcp)
+{
+ int old_offset, old_sid_offset;
+ guint32 qsize;
+
+ do {
+ old_offset=offset;
+
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ qsize=tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_user_quota_offset, tvb, offset, 4, qsize);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ /* length of SID */
+ proto_tree_add_text(tree, tvb, offset, 4, "Length of SID: %d", tvb_get_letohl(tvb, offset));
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* 16 unknown bytes */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unknown, tvb,
+ offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* number of bytes for used quota */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_user_quota_used, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* number of bytes for quota warning */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_soft_quota_limit, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* number of bytes for quota limit */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_hard_quota_limit, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* SID of the user */
+ old_sid_offset=offset;
+ offset = dissect_nt_sid(tvb, offset, tree, "Quota", NULL, -1);
+ *bcp -= (offset-old_sid_offset);
+
+ if(qsize){
+ offset = old_offset+qsize;
+ }
+ }while(qsize);
+
+
+ return offset;
+}
+
+
+static int
+dissect_nt_trans_data_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int bc, nt_trans_data *ntd)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ int old_offset = offset;
+ guint16 bcp=bc; /* XXX fixme */
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, bc,
+ "%s Data",
+ val_to_str(ntd->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_data);
+ }
+
+ switch(ntd->subcmd){
+ case NT_TRANS_CREATE:
+ /* security descriptor */
+ if(ntd->sd_len){
+ offset = dissect_nt_sec_desc(
+ tvb, offset, pinfo, tree, NULL, ntd->sd_len,
+ NULL);
+ }
+
+ /* extended attributes */
+ if(ntd->ea_len){
+ proto_tree_add_item(tree, hf_smb_extended_attributes, tvb, offset, ntd->ea_len, TRUE);
+ offset += ntd->ea_len;
+ }
+
+ break;
+ case NT_TRANS_IOCTL:
+ /* ioctl data */
+ proto_tree_add_item(tree, hf_smb_nt_ioctl_data, tvb, offset, bc, TRUE);
+ offset += bc;
+
+ break;
+ case NT_TRANS_SSD:
+ offset = dissect_nt_sec_desc(
+ tvb, offset, pinfo, tree, NULL, bc, NULL);
+ break;
+ case NT_TRANS_NOTIFY:
+ break;
+ case NT_TRANS_RENAME:
+ /* XXX not documented */
+ break;
+ case NT_TRANS_QSD:
+ break;
+ case NT_TRANS_GET_USER_QUOTA:
+ /* unknown 4 bytes */
+ proto_tree_add_item(tree, hf_smb_unknown, tvb,
+ offset, 4, TRUE);
+ offset += 4;
+
+ /* length of SID */
+ proto_tree_add_text(tree, tvb, offset, 4, "Length of SID: %d", tvb_get_letohl(tvb, offset));
+ offset +=4;
+
+ offset = dissect_nt_sid(tvb, offset, tree, "Quota", NULL, -1);
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ offset = dissect_nt_user_quota(tvb, tree, offset, &bcp);
+ break;
+ }
+
+ /* ooops there were data we didnt know how to process */
+ if((offset-old_offset) < bc){
+ proto_tree_add_item(tree, hf_smb_unknown, tvb, offset,
+ bc - (offset-old_offset), TRUE);
+ offset += bc - (offset-old_offset);
+ }
+
+ return offset;
+}
+
+static int
+dissect_nt_trans_param_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len, nt_trans_data *ntd, guint16 bc)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ guint32 fn_len;
+ const char *fn;
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ "%s Parameters",
+ val_to_str(ntd->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_param);
+ }
+
+ switch(ntd->subcmd){
+ case NT_TRANS_CREATE:
+ /* Create flags */
+ offset = dissect_nt_create_bits(tvb, tree, offset);
+ bc -= 4;
+
+ /* root directory fid */
+ proto_tree_add_item(tree, hf_smb_root_dir_fid, tvb, offset, 4, TRUE);
+ COUNT_BYTES(4);
+
+ /* nt access mask */
+ offset = dissect_smb_access_mask(tvb, tree, offset);
+ bc -= 4;
+
+ /* allocation size */
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ COUNT_BYTES(8);
+
+ /* Extended File Attributes */
+ offset = dissect_file_ext_attr(tvb, tree, offset);
+ bc -= 4;
+
+ /* share access */
+ offset = dissect_nt_share_access(tvb, tree, offset);
+ bc -= 4;
+
+ /* create disposition */
+ proto_tree_add_item(tree, hf_smb_nt_create_disposition, tvb, offset, 4, TRUE);
+ COUNT_BYTES(4);
+
+ /* create options */
+ offset = dissect_nt_create_options(tvb, tree, offset);
+ bc -= 4;
+
+ /* sd length */
+ ntd->sd_len = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_sd_length, tvb, offset, 4, ntd->sd_len);
+ COUNT_BYTES(4);
+
+ /* ea length */
+ ntd->ea_len = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_ea_list_length, tvb, offset, 4, ntd->ea_len);
+ COUNT_BYTES(4);
+
+ /* file name len */
+ fn_len = (guint32)tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+ COUNT_BYTES(4);
+
+ /* impersonation level */
+ proto_tree_add_item(tree, hf_smb_nt_impersonation_level, tvb, offset, 4, TRUE);
+ COUNT_BYTES(4);
+
+ /* security flags */
+ offset = dissect_nt_security_flags(tvb, tree, offset);
+ bc -= 1;
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, TRUE, TRUE, &bc);
+ if (fn != NULL) {
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+ }
+
+ break;
+ case NT_TRANS_IOCTL:
+ break;
+ case NT_TRANS_SSD: {
+ guint16 fid;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* security information */
+ offset = dissect_security_information_mask(tvb, tree, offset);
+ break;
+ }
+ case NT_TRANS_NOTIFY:
+ break;
+ case NT_TRANS_RENAME:
+ /* XXX not documented */
+ break;
+ case NT_TRANS_QSD: {
+ guint16 fid;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* security information */
+ offset = dissect_security_information_mask(tvb, tree, offset);
+ break;
+ }
+ case NT_TRANS_GET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_nt_trans_setup_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len, nt_trans_data *ntd)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ int old_offset = offset;
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ "%s Setup",
+ val_to_str(ntd->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+ }
+
+ switch(ntd->subcmd){
+ case NT_TRANS_CREATE:
+ break;
+ case NT_TRANS_IOCTL: {
+ guint16 fid;
+
+ /* function code */
+ proto_tree_add_item(tree, hf_smb_nt_ioctl_function_code, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* isfsctl */
+ proto_tree_add_item(tree, hf_smb_nt_ioctl_isfsctl, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* isflags */
+ offset = dissect_nt_ioctl_flags(tvb, tree, offset);
+
+ break;
+ }
+ case NT_TRANS_SSD:
+ break;
+ case NT_TRANS_NOTIFY: {
+ guint16 fid;
+
+ /* completion filter */
+ offset = dissect_nt_notify_completion_filter(tvb, tree, offset);
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* watch tree */
+ proto_tree_add_item(tree, hf_smb_nt_notify_watch_tree, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ break;
+ }
+ case NT_TRANS_RENAME:
+ /* XXX not documented */
+ break;
+ case NT_TRANS_QSD:
+ break;
+ case NT_TRANS_GET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ }
+
+ return old_offset+len;
+}
+
+
+static int
+dissect_nt_transaction_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc, sc;
+ guint32 pc=0, po=0, pd, dc=0, od=0, dd;
+ smb_info_t *si;
+ smb_saved_info_t *sip;
+ int subcmd;
+ nt_trans_data ntd;
+ guint16 bc;
+ int padcnt;
+ smb_nt_transact_info_t *nti;
+
+ si = (smb_info_t *)pinfo->private_data;
+ sip = si->sip;
+
+ WORD_COUNT;
+
+ if(wc>=19){
+ /* primary request */
+ /* max setup count */
+ proto_tree_add_item(tree, hf_smb_max_setup_count, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+ } else {
+ /* secondary request */
+ /* 3 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 3, TRUE);
+ offset += 3;
+ }
+
+
+ /* total param count */
+ proto_tree_add_item(tree, hf_smb_total_param_count, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* total data count */
+ proto_tree_add_item(tree, hf_smb_total_data_count, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ if(wc>=19){
+ /* primary request */
+ /* max param count */
+ proto_tree_add_item(tree, hf_smb_max_param_count, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* max data count */
+ proto_tree_add_item(tree, hf_smb_max_data_count, tvb, offset, 4, TRUE);
+ offset += 4;
+ }
+
+ /* param count */
+ pc = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_count32, tvb, offset, 4, pc);
+ offset += 4;
+
+ /* param offset */
+ po = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_offset32, tvb, offset, 4, po);
+ offset += 4;
+
+ /* param displacement */
+ if(wc>=19){
+ /* primary request*/
+ pd = 0;
+ } else {
+ /* secondary request */
+ pd = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_disp32, tvb, offset, 4, pd);
+ offset += 4;
+ }
+
+ /* data count */
+ dc = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_count32, tvb, offset, 4, dc);
+ offset += 4;
+
+ /* data offset */
+ od = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_offset32, tvb, offset, 4, od);
+ offset += 4;
+
+ /* data displacement */
+ if(wc>=19){
+ /* primary request */
+ dd = 0;
+ } else {
+ /* secondary request */
+ dd = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_disp32, tvb, offset, 4, dd);
+ offset += 4;
+ }
+
+ /* setup count */
+ if(wc>=19){
+ /* primary request */
+ sc = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_setup_count, tvb, offset, 1, sc);
+ offset += 1;
+ } else {
+ /* secondary request */
+ sc = 0;
+ }
+
+ /* function */
+ if(wc>=19){
+ /* primary request */
+ subcmd = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_nt_trans_subcmd, tvb, offset, 2, subcmd);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(subcmd, nt_cmd_vals, "<unknown>"));
+ }
+ ntd.subcmd = subcmd;
+ if (!si->unidir) {
+ if(!pinfo->fd->flags.visited){
+ /*
+ * Allocate a new smb_nt_transact_info_t
+ * structure.
+ */
+ nti = g_mem_chunk_alloc(smb_nt_transact_info_chunk);
+ nti->subcmd = subcmd;
+ sip->extra_info = nti;
+ }
+ }
+ } else {
+ /* secondary request */
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (secondary request)");
+ }
+ }
+ offset += 2;
+
+ /* this is a padding byte */
+ if(offset%1){
+ /* pad byte */
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, 1, TRUE);
+ offset += 1;
+ }
+
+ /* if there were any setup bytes, decode them */
+ if(sc){
+ dissect_nt_trans_setup_request(tvb, pinfo, offset, tree, sc*2, &ntd);
+ offset += sc*2;
+ }
+
+ BYTE_COUNT;
+
+ /* parameters */
+ if(po>(guint32)offset){
+ /* We have some initial padding bytes.
+ */
+ padcnt = po-offset;
+ if (padcnt > bc)
+ padcnt = bc;
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+ COUNT_BYTES(padcnt);
+ }
+ if(pc){
+ CHECK_BYTE_COUNT(pc);
+ dissect_nt_trans_param_request(tvb, pinfo, offset, tree, pc, &ntd, bc);
+ COUNT_BYTES(pc);
+ }
+
+ /* data */
+ if(od>(guint32)offset){
+ /* We have some initial padding bytes.
+ */
+ padcnt = od-offset;
+ if (padcnt > bc)
+ padcnt = bc;
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+ COUNT_BYTES(padcnt);
+ }
+ if(dc){
+ CHECK_BYTE_COUNT(dc);
+ dissect_nt_trans_data_request(
+ tvb, pinfo, offset, tree, dc, &ntd);
+ COUNT_BYTES(dc);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+
+static int
+dissect_nt_trans_data_response(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *parent_tree, int len,
+ nt_trans_data *ntd _U_)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ smb_nt_transact_info_t *nti;
+ guint16 bcp;
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL)
+ nti = si->sip->extra_info;
+ else
+ nti = NULL;
+
+ if(parent_tree){
+ if(nti != NULL){
+ item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ "%s Data",
+ val_to_str(nti->subcmd, nt_cmd_vals, "Unknown NT Transaction (%u)"));
+ } else {
+ /*
+ * We never saw the request to which this is a
+ * response.
+ */
+ item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ "Unknown NT Transaction Data (matching request not seen)");
+ }
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_data);
+ }
+
+ if (nti == NULL) {
+ offset += len;
+ return offset;
+ }
+ switch(nti->subcmd){
+ case NT_TRANS_CREATE:
+ break;
+ case NT_TRANS_IOCTL:
+ /* ioctl data */
+ proto_tree_add_item(tree, hf_smb_nt_ioctl_data, tvb, offset, len, TRUE);
+ offset += len;
+
+ break;
+ case NT_TRANS_SSD:
+ break;
+ case NT_TRANS_NOTIFY:
+ break;
+ case NT_TRANS_RENAME:
+ /* XXX not documented */
+ break;
+ case NT_TRANS_QSD: {
+ /*
+ * XXX - this is probably a SECURITY_DESCRIPTOR structure,
+ * which may be documented in the Win32 documentation
+ * somewhere.
+ */
+ offset = dissect_nt_sec_desc(
+ tvb, offset, pinfo, tree, NULL, len, NULL);
+ break;
+ }
+ case NT_TRANS_GET_USER_QUOTA:
+ bcp=len;
+ offset = dissect_nt_user_quota(tvb, tree, offset, &bcp);
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_nt_trans_param_response(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *parent_tree,
+ int len, nt_trans_data *ntd _U_, guint16 bc)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ guint32 fn_len;
+ const char *fn;
+ smb_info_t *si;
+ smb_nt_transact_info_t *nti;
+ guint16 fid;
+ int old_offset;
+ guint32 neo;
+ int padcnt;
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL)
+ nti = si->sip->extra_info;
+ else
+ nti = NULL;
+
+ if(parent_tree){
+ if(nti != NULL){
+ item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ "%s Parameters",
+ val_to_str(nti->subcmd, nt_cmd_vals, "Unknown NT Transaction (%u)"));
+ } else {
+ /*
+ * We never saw the request to which this is a
+ * response.
+ */
+ item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ "Unknown NT Transaction Parameters (matching request not seen)");
+ }
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_param);
+ }
+
+ if (nti == NULL) {
+ offset += len;
+ return offset;
+ }
+ switch(nti->subcmd){
+ case NT_TRANS_CREATE:
+ /* oplock level */
+ proto_tree_add_item(tree, hf_smb_oplock_level, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* create action */
+ proto_tree_add_item(tree, hf_smb_create_action, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* ea error offset */
+ proto_tree_add_item(tree, hf_smb_ea_error_offset, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* create time */
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_create_time);
+
+ /* access time */
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_access_time);
+
+ /* last write time */
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_last_write_time);
+
+ /* last change time */
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_change_time);
+
+ /* Extended File Attributes */
+ offset = dissect_file_ext_attr(tvb, tree, offset);
+
+ /* allocation size */
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ offset += 8;
+
+ /* end of file */
+ proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+ offset += 8;
+
+ /* File Type */
+ proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* device state */
+ offset = dissect_ipc_state(tvb, tree, offset, FALSE);
+
+ /* is directory */
+ proto_tree_add_item(tree, hf_smb_is_directory, tvb, offset, 1, TRUE);
+ offset += 1;
+ break;
+ case NT_TRANS_IOCTL:
+ break;
+ case NT_TRANS_SSD:
+ break;
+ case NT_TRANS_NOTIFY:
+ while(len){
+ old_offset = offset;
+
+ /* next entry offset */
+ neo = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+ COUNT_BYTES(4);
+ len -= 4;
+ /* broken implementations */
+ if(len<0)break;
+
+ /* action */
+ proto_tree_add_item(tree, hf_smb_nt_notify_action, tvb, offset, 4, TRUE);
+ COUNT_BYTES(4);
+ len -= 4;
+ /* broken implementations */
+ if(len<0)break;
+
+ /* file name len */
+ fn_len = (guint32)tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+ COUNT_BYTES(4);
+ len -= 4;
+ /* broken implementations */
+ if(len<0)break;
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, TRUE, TRUE, &bc);
+ if (fn == NULL)
+ break;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+ len -= fn_len;
+ /* broken implementations */
+ if(len<0)break;
+
+ if (neo == 0)
+ break; /* no more structures */
+
+ /* skip to next structure */
+ padcnt = (old_offset + neo) - offset;
+ if (padcnt < 0) {
+ /*
+ * XXX - this is bogus; flag it?
+ */
+ padcnt = 0;
+ }
+ if (padcnt != 0) {
+ COUNT_BYTES(padcnt);
+ len -= padcnt;
+ /* broken implementations */
+ if(len<0)break;
+ }
+ }
+ break;
+ case NT_TRANS_RENAME:
+ /* XXX not documented */
+ break;
+ case NT_TRANS_QSD:
+ /*
+ * This appears to be the size of the security
+ * descriptor; the calling sequence of
+ * "ZwQuerySecurityObject()" suggests that it would
+ * be. The actual security descriptor wouldn't
+ * follow if the max data count in the request
+ * was smaller; this lets the client know how
+ * big a buffer it needs to provide.
+ */
+ proto_tree_add_item(tree, hf_smb_sec_desc_len, tvb, offset, 4, TRUE);
+ offset += 4;
+ break;
+ case NT_TRANS_GET_USER_QUOTA:
+ proto_tree_add_text(tree, tvb, offset, 4, "Size of returned Quota data: %d",
+ tvb_get_letohl(tvb, offset));
+ offset += 4;
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_nt_trans_setup_response(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *parent_tree,
+ int len, nt_trans_data *ntd _U_)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ smb_nt_transact_info_t *nti;
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL)
+ nti = si->sip->extra_info;
+ else
+ nti = NULL;
+
+ if(parent_tree){
+ if(nti != NULL){
+ item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ "%s Setup",
+ val_to_str(nti->subcmd, nt_cmd_vals, "Unknown NT Transaction (%u)"));
+ } else {
+ /*
+ * We never saw the request to which this is a
+ * response.
+ */
+ item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ "Unknown NT Transaction Setup (matching request not seen)");
+ }
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+ }
+
+ if (nti == NULL) {
+ offset += len;
+ return offset;
+ }
+ switch(nti->subcmd){
+ case NT_TRANS_CREATE:
+ break;
+ case NT_TRANS_IOCTL:
+ break;
+ case NT_TRANS_SSD:
+ break;
+ case NT_TRANS_NOTIFY:
+ break;
+ case NT_TRANS_RENAME:
+ /* XXX not documented */
+ break;
+ case NT_TRANS_QSD:
+ break;
+ case NT_TRANS_GET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_nt_transaction_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc, sc;
+ guint32 pc=0, po=0, pd=0, dc=0, od=0, dd=0;
+ guint32 td=0, tp=0;
+ smb_info_t *si;
+ smb_nt_transact_info_t *nti;
+ static nt_trans_data ntd;
+ guint16 bc;
+ int padcnt;
+ fragment_data *r_fd = NULL;
+ tvbuff_t *pd_tvb=NULL;
+ gboolean save_fragmented;
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL)
+ nti = si->sip->extra_info;
+ else
+ nti = NULL;
+
+ /* primary request */
+ if(nti != NULL){
+ proto_tree_add_uint(tree, hf_smb_nt_trans_subcmd, tvb, 0, 0, nti->subcmd);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(nti->subcmd, nt_cmd_vals, "<unknown (%u)>"));
+ }
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "Function: <unknown function - could not find matching request>");
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", <unknown>");
+ }
+ }
+
+ WORD_COUNT;
+
+ /* 3 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 3, TRUE);
+ offset += 3;
+
+ /* total param count */
+ tp = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_total_param_count, tvb, offset, 4, tp);
+ offset += 4;
+
+ /* total data count */
+ td = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_total_data_count, tvb, offset, 4, td);
+ offset += 4;
+
+ /* param count */
+ pc = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_count32, tvb, offset, 4, pc);
+ offset += 4;
+
+ /* param offset */
+ po = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_offset32, tvb, offset, 4, po);
+ offset += 4;
+
+ /* param displacement */
+ pd = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_disp32, tvb, offset, 4, pd);
+ offset += 4;
+
+ /* data count */
+ dc = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_count32, tvb, offset, 4, dc);
+ offset += 4;
+
+ /* data offset */
+ od = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_offset32, tvb, offset, 4, od);
+ offset += 4;
+
+ /* data displacement */
+ dd = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_disp32, tvb, offset, 4, dd);
+ offset += 4;
+
+ /* setup count */
+ sc = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_setup_count, tvb, offset, 1, sc);
+ offset += 1;
+
+ /* setup data */
+ if(sc){
+ dissect_nt_trans_setup_response(tvb, pinfo, offset, tree, sc*2, &ntd);
+ offset += sc*2;
+ }
+
+ BYTE_COUNT;
+
+ /* reassembly of SMB NT Transaction data payload.
+ In this section we do reassembly of both the data and parameters
+ blocks of the SMB transaction command.
+ */
+ save_fragmented = pinfo->fragmented;
+ /* do we need reassembly? */
+ if( (td&&(td!=dc)) || (tp&&(tp!=pc)) ){
+ /* oh yeah, either data or parameter section needs
+ reassembly...
+ */
+ pinfo->fragmented = TRUE;
+ if(smb_trans_reassembly){
+ /* ...and we were told to do reassembly */
+ if(pc && ((unsigned int)tvb_length_remaining(tvb, po)>=pc) ){
+ r_fd = smb_trans_defragment(tree, pinfo, tvb,
+ po, pc, pd, td+tp);
+
+ }
+ if((r_fd==NULL) && dc && ((unsigned int)tvb_length_remaining(tvb, od)>=dc) ){
+ r_fd = smb_trans_defragment(tree, pinfo, tvb,
+ od, dc, dd+tp, td+tp);
+ }
+ }
+ }
+
+ /* if we got a reassembled fd structure from the reassembly routine we
+ must create pd_tvb from it
+ */
+ if(r_fd){
+ pd_tvb = tvb_new_real_data(r_fd->data, r_fd->datalen,
+ r_fd->datalen);
+ tvb_set_child_real_data_tvbuff(tvb, pd_tvb);
+ add_new_data_source(pinfo, pd_tvb, "Reassembled SMB");
+
+ show_fragment_tree(r_fd, &smb_frag_items, tree, pinfo, pd_tvb);
+ }
+
+
+ if(pd_tvb){
+ /* we have reassembled data, grab param and data from there */
+ dissect_nt_trans_param_response(pd_tvb, pinfo, 0, tree, tp,
+ &ntd, (guint16) tvb_length(pd_tvb));
+ dissect_nt_trans_data_response(pd_tvb, pinfo, tp, tree, td, &ntd);
+ } else {
+ /* we do not have reassembled data, just use what we have in the
+ packet as well as we can */
+ /* parameters */
+ if(po>(guint32)offset){
+ /* We have some initial padding bytes.
+ */
+ padcnt = po-offset;
+ if (padcnt > bc)
+ padcnt = bc;
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+ COUNT_BYTES(padcnt);
+ }
+ if(pc){
+ CHECK_BYTE_COUNT(pc);
+ dissect_nt_trans_param_response(tvb, pinfo, offset, tree, pc, &ntd, bc);
+ COUNT_BYTES(pc);
+ }
+
+ /* data */
+ if(od>(guint32)offset){
+ /* We have some initial padding bytes.
+ */
+ padcnt = od-offset;
+ if (padcnt > bc)
+ padcnt = bc;
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+ COUNT_BYTES(padcnt);
+ }
+ if(dc){
+ CHECK_BYTE_COUNT(dc);
+ dissect_nt_trans_data_response(tvb, pinfo, offset, tree, dc, &ntd);
+ COUNT_BYTES(dc);
+ }
+ }
+ pinfo->fragmented = save_fragmented;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ NT Transaction command ends here
+ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+
+static const value_string print_mode_vals[] = {
+ {0, "Text Mode"},
+ {1, "Graphics Mode"},
+ {0, NULL}
+};
+
+static int
+dissect_open_print_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* setup len */
+ proto_tree_add_item(tree, hf_smb_setup_len, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* print mode */
+ proto_tree_add_item(tree, hf_smb_print_mode, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* print identifier */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, TRUE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_print_identifier, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static int
+dissect_write_print_file_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ int cnt;
+ guint8 wc;
+ guint16 bc, fid;
+
+ WORD_COUNT;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* data len */
+ CHECK_BYTE_COUNT(2);
+ cnt = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, cnt);
+ COUNT_BYTES(2);
+
+ /* file data */
+ offset = dissect_file_data(tvb, tree, offset, (guint16) cnt, (guint16) cnt);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static const value_string print_status_vals[] = {
+ {1, "Held or Stopped"},
+ {2, "Printing"},
+ {3, "Awaiting print"},
+ {4, "In intercept"},
+ {5, "File had error"},
+ {6, "Printer error"},
+ {0, NULL}
+};
+
+static int
+dissect_get_print_queue_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* max count */
+ proto_tree_add_item(tree, hf_smb_max_count, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* start index */
+ proto_tree_add_item(tree, hf_smb_start_index, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_print_queue_element(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *parent_tree, int offset, guint16 *bcp, gboolean *trunc)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 28,
+ "Queue entry");
+ tree = proto_item_add_subtree(item, ett_smb_print_queue_entry);
+ }
+
+ /* queued time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_print_queue_date,
+ hf_smb_print_queue_dos_date, hf_smb_print_queue_dos_time, FALSE);
+ *bcp -= 4;
+
+ /* status */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_print_status, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* spool file number */
+ CHECK_BYTE_COUNT_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_print_spool_file_number, tvb, offset, 2, TRUE);
+ COUNT_BYTES_SUBR(2);
+
+ /* spool file size */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_print_spool_file_size, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* reserved byte */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* file name */
+ fn_len = 16;
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, TRUE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_print_spool_file_name, tvb, offset, 16,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+static int
+dissect_get_print_queue_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint16 cnt=0, len;
+ guint8 wc;
+ guint16 bc;
+ gboolean trunc;
+
+ WORD_COUNT;
+
+ /* count */
+ cnt = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
+ offset += 2;
+
+ /* restart index */
+ proto_tree_add_item(tree, hf_smb_restart_index, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* data len */
+ CHECK_BYTE_COUNT(2);
+ len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_len, tvb, offset, 2, len);
+ COUNT_BYTES(2);
+
+ /* queue elements */
+ while(cnt--){
+ offset = dissect_print_queue_element(tvb, pinfo, tree, offset,
+ &bc, &trunc);
+ if (trunc)
+ goto endofcommand;
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static int
+dissect_send_single_block_message_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ int name_len;
+ guint16 bc;
+ guint8 wc;
+ guint16 message_len;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* originator name */
+ /* XXX - what if this runs past bc? */
+ name_len = tvb_strsize(tvb, offset);
+ CHECK_BYTE_COUNT(name_len);
+ proto_tree_add_item(tree, hf_smb_originator_name, tvb, offset,
+ name_len, TRUE);
+ COUNT_BYTES(name_len);
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* destination name */
+ /* XXX - what if this runs past bc? */
+ name_len = tvb_strsize(tvb, offset);
+ CHECK_BYTE_COUNT(name_len);
+ proto_tree_add_item(tree, hf_smb_destination_name, tvb, offset,
+ name_len, TRUE);
+ COUNT_BYTES(name_len);
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* message len */
+ CHECK_BYTE_COUNT(2);
+ message_len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_message_len, tvb, offset, 2,
+ message_len);
+ COUNT_BYTES(2);
+
+ /* message */
+ CHECK_BYTE_COUNT(message_len);
+ proto_tree_add_item(tree, hf_smb_message, tvb, offset, message_len,
+ TRUE);
+ COUNT_BYTES(message_len);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_send_multi_block_message_start_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ int name_len;
+ guint16 bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* originator name */
+ /* XXX - what if this runs past bc? */
+ name_len = tvb_strsize(tvb, offset);
+ CHECK_BYTE_COUNT(name_len);
+ proto_tree_add_item(tree, hf_smb_originator_name, tvb, offset,
+ name_len, TRUE);
+ COUNT_BYTES(name_len);
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* destination name */
+ /* XXX - what if this runs past bc? */
+ name_len = tvb_strsize(tvb, offset);
+ CHECK_BYTE_COUNT(name_len);
+ proto_tree_add_item(tree, hf_smb_destination_name, tvb, offset,
+ name_len, TRUE);
+ COUNT_BYTES(name_len);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_message_group_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint16 bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ /* message group ID */
+ proto_tree_add_item(tree, hf_smb_mgid, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_send_multi_block_message_text_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint16 bc;
+ guint8 wc;
+ guint16 message_len;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* message len */
+ CHECK_BYTE_COUNT(2);
+ message_len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_message_len, tvb, offset, 2,
+ message_len);
+ COUNT_BYTES(2);
+
+ /* message */
+ CHECK_BYTE_COUNT(message_len);
+ proto_tree_add_item(tree, hf_smb_message, tvb, offset, message_len,
+ TRUE);
+ COUNT_BYTES(message_len);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_forwarded_name(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ int name_len;
+ guint16 bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* forwarded name */
+ /* XXX - what if this runs past bc? */
+ name_len = tvb_strsize(tvb, offset);
+ CHECK_BYTE_COUNT(name_len);
+ proto_tree_add_item(tree, hf_smb_forwarded_name, tvb, offset,
+ name_len, TRUE);
+ COUNT_BYTES(name_len);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+static int
+dissect_get_machine_name_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ int name_len;
+ guint16 bc;
+ guint8 wc;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* machine name */
+ /* XXX - what if this runs past bc? */
+ name_len = tvb_strsize(tvb, offset);
+ CHECK_BYTE_COUNT(name_len);
+ proto_tree_add_item(tree, hf_smb_machine_name, tvb, offset,
+ name_len, TRUE);
+ COUNT_BYTES(name_len);
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static int
+dissect_nt_create_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0;
+ guint16 bc;
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* file name len */
+ fn_len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 2, fn_len);
+ offset += 2;
+
+ /* Create flags */
+ offset = dissect_nt_create_bits(tvb, tree, offset);
+
+ /* root directory fid */
+ proto_tree_add_item(tree, hf_smb_root_dir_fid, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* nt access mask */
+ offset = dissect_smb_access_mask(tvb, tree, offset);
+
+ /* allocation size */
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ offset += 8;
+
+ /* Extended File Attributes */
+ offset = dissect_file_ext_attr(tvb, tree, offset);
+
+ /* share access */
+ offset = dissect_nt_share_access(tvb, tree, offset);
+
+ /* create disposition */
+ proto_tree_add_item(tree, hf_smb_nt_create_disposition, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* create options */
+ offset = dissect_nt_create_options(tvb, tree, offset);
+
+ /* impersonation level */
+ proto_tree_add_item(tree, hf_smb_nt_impersonation_level, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* security flags */
+ offset = dissect_nt_security_flags(tvb, tree, offset);
+
+ BYTE_COUNT;
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s", fn);
+ }
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_nt_create_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ guint8 wc, cmd=0xff;
+ guint16 andxoffset=0;
+ guint16 bc;
+ guint16 fid;
+
+ WORD_COUNT;
+
+ /* next smb command */
+ cmd = tvb_get_guint8(tvb, offset);
+ if(cmd!=0xff){
+ proto_tree_add_uint_format(tree, hf_smb_cmd, tvb, offset, 1, cmd, "AndXCommand: %s (0x%02x)", decode_smb_name(cmd), cmd);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1, "AndXCommand: No further commands (0xff)");
+ }
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* andxoffset */
+ andxoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_andxoffset, tvb, offset, 2, andxoffset);
+ offset += 2;
+
+ /* oplock level */
+ proto_tree_add_item(tree, hf_smb_oplock_level, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /* create action */
+ /*XXX is this really the same as create disposition in the request? it looks so*/
+ /* No, it is not. It is the same as the create action from an Open&X request ... RJS */
+ proto_tree_add_item(tree, hf_smb_create_action, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* create time */
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_create_time);
+
+ /* access time */
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_access_time);
+
+ /* last write time */
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_last_write_time);
+
+ /* last change time */
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_change_time);
+
+ /* Extended File Attributes */
+ offset = dissect_file_ext_attr(tvb, tree, offset);
+
+ /* allocation size */
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ offset += 8;
+
+ /* end of file */
+ proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+ offset += 8;
+
+ /* File Type */
+ proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* IPC State */
+ offset = dissect_ipc_state(tvb, tree, offset, FALSE);
+
+ /* is directory */
+ proto_tree_add_item(tree, hf_smb_is_directory, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ /* call AndXCommand (if there are any) */
+ dissect_smb_command(tvb, pinfo, andxoffset, smb_tree, cmd, FALSE);
+
+ return offset;
+}
+
+
+static int
+dissect_nt_cancel_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ BEGIN Transaction/Transaction2 Primary and secondary requests
+ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+
+
+const value_string trans2_cmd_vals[] = {
+ { 0x00, "OPEN2" },
+ { 0x01, "FIND_FIRST2" },
+ { 0x02, "FIND_NEXT2" },
+ { 0x03, "QUERY_FS_INFO" },
+ { 0x04, "SET_FS_QUOTA" },
+ { 0x05, "QUERY_PATH_INFO" },
+ { 0x06, "SET_PATH_INFO" },
+ { 0x07, "QUERY_FILE_INFO" },
+ { 0x08, "SET_FILE_INFO" },
+ { 0x09, "FSCTL" },
+ { 0x0A, "IOCTL2" },
+ { 0x0B, "FIND_NOTIFY_FIRST" },
+ { 0x0C, "FIND_NOTIFY_NEXT" },
+ { 0x0D, "CREATE_DIRECTORY" },
+ { 0x0E, "SESSION_SETUP" },
+ { 0x10, "GET_DFS_REFERRAL" },
+ { 0x11, "REPORT_DFS_INCONSISTENCY" },
+ { 0, NULL }
+};
+
+static const true_false_string tfs_tf_dtid = {
+ "Also DISCONNECT TID",
+ "Do NOT disconnect TID"
+};
+static const true_false_string tfs_tf_owt = {
+ "One Way Transaction (NO RESPONSE)",
+ "Two way transaction"
+};
+
+static const true_false_string tfs_ff2_backup = {
+ "Find WITH backup intent",
+ "No backup intent"
+};
+static const true_false_string tfs_ff2_continue = {
+ "CONTINUE search from previous position",
+ "New search, do NOT continue from previous position"
+};
+static const true_false_string tfs_ff2_resume = {
+ "Return RESUME keys",
+ "Do NOT return resume keys"
+};
+static const true_false_string tfs_ff2_close_eos = {
+ "CLOSE search if END OF SEARCH is reached",
+ "Do NOT close search if end of search reached"
+};
+static const true_false_string tfs_ff2_close = {
+ "CLOSE search after this request",
+ "Do NOT close search after this request"
+};
+
+/* used by
+ TRANS2_FIND_FIRST2
+*/
+static const value_string ff2_il_vals[] = {
+ { 1, "Info Standard"},
+ { 2, "Info Query EA Size"},
+ { 3, "Info Query EAs From List"},
+ { 0x0101, "Find File Directory Info"},
+ { 0x0102, "Find File Full Directory Info"},
+ { 0x0103, "Find File Names Info"},
+ { 0x0104, "Find File Both Directory Info"},
+ { 0x0202, "Find File UNIX"},
+ {0, NULL}
+};
+
+/* values used by :
+ TRANS2_QUERY_PATH_INFORMATION
+ TRANS2_QUERY_FILE_INFORMATION
+*/
+static const value_string qpi_loi_vals[] = {
+ { 1, "Info Standard"},
+ { 2, "Info Query EA Size"},
+ { 3, "Info Query EAs From List"},
+ { 4, "Info Query All EAs"},
+ { 6, "Info Is Name Valid"},
+ { 0x0101, "Query File Basic Info"},
+ { 0x0102, "Query File Standard Info"},
+ { 0x0103, "Query File EA Info"},
+ { 0x0104, "Query File Name Info"},
+ { 0x0107, "Query File All Info"},
+ { 0x0108, "Query File Alt Name Info"},
+ { 0x0109, "Query File Stream Info"},
+ { 0x010b, "Query File Compression Info"},
+ { 0x0200, "Query File Unix Basic"},
+ { 0x0201, "Query File Unix Link"},
+ { 1004, "Query File Basic Info"},
+ { 1005, "Query File Standard Info"},
+ { 1006, "Query File Internal Info"},
+ { 1007, "Query File EA Info"},
+ { 1009, "Query File Name Info"},
+ { 1010, "Query File Rename Info"},
+ { 1011, "Query File Link Info"},
+ { 1012, "Query File Names Info"},
+ { 1013, "Query File Disposition Info"},
+ { 1014, "Query File Position Info"},
+ { 1015, "Query File Full EA Info"},
+ { 1016, "Query File Mode Info"},
+ { 1017, "Query File Alignment Info"},
+ { 1018, "Query File All Info"},
+ { 1019, "Query File Allocation Info"},
+ { 1020, "Query File End of File Info"},
+ { 1021, "Query File Alt Name Info"},
+ { 1022, "Query File Stream Info"},
+ { 1023, "Query File Pipe Info"},
+ { 1024, "Query File Pipe Local Info"},
+ { 1025, "Query File Pipe Remote Info"},
+ { 1026, "Query File Mailslot Query Info"},
+ { 1027, "Query File Mailslot Set Info"},
+ { 1028, "Query File Compression Info"},
+ { 1029, "Query File ObjectID Info"},
+ { 1030, "Query File Completion Info"},
+ { 1031, "Query File Move Cluster Info"},
+ { 1032, "Query File Quota Info"},
+ { 1033, "Query File Reparsepoint Info"},
+ { 1034, "Query File Network Open Info"},
+ { 1035, "Query File Attribute Tag Info"},
+ { 1036, "Query File Tracking Info"},
+ { 1037, "Query File Maximum Info"},
+ {0, NULL}
+};
+
+/* values used by :
+ TRANS2_SET_PATH_INFORMATION
+ TRANS2_SET_FILE_INFORMATION
+ (the SNIA CIFS spec lists some only for TRANS2_SET_FILE_INFORMATION,
+ but I'm assuming they apply to TRANS2_SET_PATH_INFORMATION as
+ well; note that they're different from the QUERY_PATH_INFORMATION
+ and QUERY_FILE_INFORMATION values!)
+*/
+static const value_string spi_loi_vals[] = {
+ { 1, "Info Standard"},
+ { 2, "Info Query EA Size"},
+ { 4, "Info Query All EAs"},
+ { 0x0101, "Set File Basic Info"},
+ { 0x0102, "Set File Disposition Info"},
+ { 0x0103, "Set File Allocation Info"},
+ { 0x0104, "Set File End Of File Info"},
+ { 0x0200, "Set File Unix Basic"},
+ { 0x0201, "Set File Unix Link"},
+ { 0x0202, "Set File Unix HardLink"},
+ { 1004, "Set File Basic Info"},
+ { 1010, "Set Rename Information"},
+ { 1013, "Set Disposition Information"},
+ { 1014, "Set Position Information"},
+ { 1016, "Set Mode Information"},
+ { 1019, "Set Allocation Information"},
+ { 1020, "Set EOF Information"},
+ { 1023, "Set File Pipe Information"},
+ { 1025, "Set File Pipe Remote Information"},
+ { 1029, "Set Copy On Write Information"},
+ { 1032, "Set OLE Class ID Information"},
+ { 1039, "Set Inherit Context Index Information"},
+ { 1040, "Set OLE Information (?)"},
+ {0, NULL}
+};
+
+static const value_string qfsi_vals[] = {
+ { 1, "Info Allocation"},
+ { 2, "Info Volume"},
+ { 0x0101, "Query FS Label Info"},
+ { 0x0102, "Query FS Volume Info"},
+ { 0x0103, "Query FS Size Info"},
+ { 0x0104, "Query FS Device Info"},
+ { 0x0105, "Query FS Attribute Info"},
+ { 0x0200, "Unix Query FS Info"},
+ { 0x0301, "Mac Query FS Info"},
+ { 1001, "Query FS Label Info"},
+ { 1002, "Query FS Volume Info"},
+ { 1003, "Query FS Size Info"},
+ { 1004, "Query FS Device Info"},
+ { 1005, "Query FS Attribute Info"},
+ { 1006, "Query FS Quota Info"},
+ { 1007, "Query Full FS Size Info"},
+ { 1008, "Object ID Information"},
+ {0, NULL}
+};
+
+static const value_string nt_rename_vals[] = {
+ { 0x0103, "Create Hard Link"},
+ {0, NULL}
+};
+
+
+static const value_string delete_pending_vals[] = {
+ {0, "Normal, no pending delete"},
+ {1, "This object has DELETE PENDING"},
+ {0, NULL}
+};
+
+static const value_string alignment_vals[] = {
+ {0, "Byte alignment"},
+ {1, "Word (16bit) alignment"},
+ {3, "Long (32bit) alignment"},
+ {7, "8 byte boundary alignment"},
+ {0x0f, "16 byte boundary alignment"},
+ {0x1f, "32 byte boundary alignment"},
+ {0x3f, "64 byte boundary alignment"},
+ {0x7f, "128 byte boundary alignment"},
+ {0xff, "256 byte boundary alignment"},
+ {0x1ff, "512 byte boundary alignment"},
+ {0, NULL}
+};
+
+static const true_false_string tfs_marked_for_deletion = {
+ "File is MARKED FOR DELETION",
+ "File is NOT marked for deletion"
+};
+
+static const true_false_string tfs_get_dfs_server_hold_storage = {
+ "Referral SERVER HOLDS STORAGE for the file",
+ "Referral server does NOT hold storage for the file"
+};
+static const true_false_string tfs_get_dfs_fielding = {
+ "The server in referral is FIELDING CAPABLE",
+ "The server in referrals is NOT fielding capable"
+};
+
+static const true_false_string tfs_dfs_referral_flags_strip = {
+ "STRIP off pathconsumed characters before submitting",
+ "Do NOT strip off any characters"
+};
+
+static const value_string dfs_referral_server_type_vals[] = {
+ {0, "Don't know"},
+ {1, "SMB Server"},
+ {2, "Netware Server"},
+ {3, "Domain Server"},
+ {0, NULL}
+};
+
+
+static const true_false_string tfs_device_char_removable = {
+ "This is a REMOVABLE device",
+ "This is NOT a removable device"
+};
+static const true_false_string tfs_device_char_read_only = {
+ "This is a READ-ONLY device",
+ "This is NOT a read-only device"
+};
+static const true_false_string tfs_device_char_floppy = {
+ "This is a FLOPPY DISK device",
+ "This is NOT a floppy disk device"
+};
+static const true_false_string tfs_device_char_write_once = {
+ "This is a WRITE-ONCE device",
+ "This is NOT a write-once device"
+};
+static const true_false_string tfs_device_char_remote = {
+ "This is a REMOTE device",
+ "This is NOT a remote device"
+};
+static const true_false_string tfs_device_char_mounted = {
+ "This device is MOUNTED",
+ "This device is NOT mounted"
+};
+static const true_false_string tfs_device_char_virtual = {
+ "This is a VIRTUAL device",
+ "This is NOT a virtual device"
+};
+
+
+static const true_false_string tfs_fs_attr_css = {
+ "This FS supports CASE SENSITIVE SEARCHes",
+ "This FS does NOT support case sensitive searches"
+};
+static const true_false_string tfs_fs_attr_cpn = {
+ "This FS supports CASE PRESERVED NAMES",
+ "This FS does NOT support case preserved names"
+};
+static const true_false_string tfs_fs_attr_pacls = {
+ "This FS supports PERSISTENT ACLs",
+ "This FS does NOT support persistent acls"
+};
+static const true_false_string tfs_fs_attr_fc = {
+ "This FS supports COMPRESSED FILES",
+ "This FS does NOT support compressed files"
+};
+static const true_false_string tfs_fs_attr_vq = {
+ "This FS supports VOLUME QUOTAS",
+ "This FS does NOT support volume quotas"
+};
+static const true_false_string tfs_fs_attr_dim = {
+ "This FS is on a MOUNTED DEVICE",
+ "This FS is NOT on a mounted device"
+};
+static const true_false_string tfs_fs_attr_vic = {
+ "This FS is on a COMPRESSED VOLUME",
+ "This FS is NOT on a compressed volume"
+};
+
+#define FF2_RESUME 0x0004
+
+static int
+dissect_ff2_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ smb_transact2_info_t *t2i;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL) {
+ t2i = si->sip->extra_info;
+ if (t2i != NULL) {
+ if (!pinfo->fd->flags.visited)
+ t2i->resume_keys = (mask & FF2_RESUME);
+ }
+ }
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Flags: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_find_first2_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_ff2_backup,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_ff2_continue,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_ff2_resume,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_ff2_close_eos,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_ff2_close,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+#if 0
+static int
+dissect_sfi_ioflag(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "IO Flag: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_ioflag);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_sfi_writetru,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_sfi_caching,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+#endif
+
+static int
+dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *parent_tree, int offset, int subcmd, guint16 bc)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ smb_transact2_info_t *t2i;
+ int fn_len;
+ const char *fn;
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL)
+ t2i = si->sip->extra_info;
+ else
+ t2i = NULL;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, bc,
+ "%s Parameters",
+ val_to_str(subcmd, trans2_cmd_vals,
+ "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_transaction_params);
+ }
+
+ switch(subcmd){
+ case 0x00: /*TRANS2_OPEN2*/
+ /* open flags */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_open_flags(tvb, tree, offset, 0x000f);
+ bc -= 2;
+
+ /* desired access */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_access(tvb, tree, offset, "Desired");
+ bc -= 2;
+
+ /* Search Attributes */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_search_attributes(tvb, tree, offset);
+ bc -= 2;
+
+ /* File Attributes */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+ bc -= 2;
+
+ /* create time */
+ CHECK_BYTE_COUNT_TRANS(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_create_time,
+ hf_smb_create_dos_date, hf_smb_create_dos_time,
+ TRUE);
+ bc -= 4;
+
+ /* open function */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_open_function(tvb, tree, offset);
+ bc -= 2;
+
+ /* allocation size */
+ CHECK_BYTE_COUNT_TRANS(4);
+ proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS(4);
+
+ /* 10 reserved bytes */
+ CHECK_BYTE_COUNT_TRANS(10);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 10, TRUE);
+ COUNT_BYTES_TRANS(10);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, &bc);
+ CHECK_STRING_TRANS(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s",
+ fn);
+ }
+ break;
+ case 0x01: /*TRANS2_FIND_FIRST2*/
+ /* Search Attributes */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_search_attributes(tvb, tree, offset);
+ bc -= 2;
+
+ /* search count */
+ CHECK_BYTE_COUNT_TRANS(2);
+ proto_tree_add_item(tree, hf_smb_search_count, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS(2);
+
+ /* Find First2 flags */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_ff2_flags(tvb, pinfo, tree, offset);
+ bc -= 2;
+
+ /* Find First2 information level */
+ CHECK_BYTE_COUNT_TRANS(2);
+ si->info_level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ t2i->info_level = si->info_level;
+ proto_tree_add_uint(tree, hf_smb_ff2_information_level, tvb, offset, 2, si->info_level);
+ COUNT_BYTES_TRANS(2);
+
+ /* storage type */
+ CHECK_BYTE_COUNT_TRANS(4);
+ proto_tree_add_item(tree, hf_smb_storage_type, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS(4);
+
+ /* search pattern */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, &bc);
+ CHECK_STRING_TRANS(fn);
+ proto_tree_add_string(tree, hf_smb_search_pattern, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Pattern: %s",
+ fn);
+ }
+
+ break;
+ case 0x02: /*TRANS2_FIND_NEXT2*/
+ /* sid */
+ CHECK_BYTE_COUNT_TRANS(2);
+ proto_tree_add_item(tree, hf_smb_search_id, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS(2);
+
+ /* search count */
+ CHECK_BYTE_COUNT_TRANS(2);
+ proto_tree_add_item(tree, hf_smb_search_count, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS(2);
+
+ /* Find First2 information level */
+ CHECK_BYTE_COUNT_TRANS(2);
+ si->info_level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ t2i->info_level = si->info_level;
+ proto_tree_add_uint(tree, hf_smb_ff2_information_level, tvb, offset, 2, si->info_level);
+ COUNT_BYTES_TRANS(2);
+
+ /* resume key */
+ CHECK_BYTE_COUNT_TRANS(4);
+ proto_tree_add_item(tree, hf_smb_resume, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS(4);
+
+ /* Find First2 flags */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_ff2_flags(tvb, pinfo, tree, offset);
+ bc -= 2;
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, &bc);
+ CHECK_STRING_TRANS(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Continue: %s",
+ fn);
+ }
+
+ break;
+ case 0x03: /*TRANS2_QUERY_FS_INFORMATION*/
+ /* level of interest */
+ CHECK_BYTE_COUNT_TRANS(2);
+ si->info_level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ t2i->info_level = si->info_level;
+ proto_tree_add_uint(tree, hf_smb_qfsi_information_level, tvb, offset, 2, si->info_level);
+ COUNT_BYTES_TRANS(2);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(si->info_level, qfsi_vals,
+ "Unknown (0x%02x)"));
+
+ break;
+ case 0x05: /*TRANS2_QUERY_PATH_INFORMATION*/
+ /* level of interest */
+ CHECK_BYTE_COUNT_TRANS(2);
+ si->info_level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ t2i->info_level = si->info_level;
+ proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level);
+ COUNT_BYTES_TRANS(2);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(si->info_level, qpi_loi_vals,
+ "Unknown (%u)"));
+ }
+
+ /* 4 reserved bytes */
+ CHECK_BYTE_COUNT_TRANS(4);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS(4);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, &bc);
+ CHECK_STRING_TRANS(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s",
+ fn);
+ }
+
+ break;
+ case 0x06: /*TRANS2_SET_PATH_INFORMATION*/
+ /* level of interest */
+ CHECK_BYTE_COUNT_TRANS(2);
+ si->info_level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ t2i->info_level = si->info_level;
+ proto_tree_add_uint(tree, hf_smb_spi_loi, tvb, offset, 2, si->info_level);
+ COUNT_BYTES_TRANS(2);
+
+ /* 4 reserved bytes */
+ CHECK_BYTE_COUNT_TRANS(4);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS(4);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, &bc);
+ CHECK_STRING_TRANS(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s",
+ fn);
+ }
+
+ break;
+ case 0x07: { /*TRANS2_QUERY_FILE_INFORMATION*/
+ guint16 fid;
+
+ /* fid */
+ CHECK_BYTE_COUNT_TRANS(2);
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ COUNT_BYTES_TRANS(2);
+
+ /* level of interest */
+ CHECK_BYTE_COUNT_TRANS(2);
+ si->info_level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ t2i->info_level = si->info_level;
+ proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level);
+ COUNT_BYTES_TRANS(2);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(si->info_level, qpi_loi_vals,
+ "Unknown (%u)"));
+ }
+
+ break;
+ }
+ case 0x08: { /*TRANS2_SET_FILE_INFORMATION*/
+ guint16 fid;
+
+ /* fid */
+ CHECK_BYTE_COUNT_TRANS(2);
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ COUNT_BYTES_TRANS(2);
+
+ /* level of interest */
+ CHECK_BYTE_COUNT_TRANS(2);
+ si->info_level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ t2i->info_level = si->info_level;
+ proto_tree_add_uint(tree, hf_smb_spi_loi, tvb, offset, 2, si->info_level);
+ COUNT_BYTES_TRANS(2);
+
+#if 0
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this is I/O flags, but it's
+ * reserved in the SNIA spec, and some clients appear
+ * to leave junk in it.
+ *
+ * Is this some field used only if a particular
+ * dialect was negotiated, so that clients can feel
+ * safe not setting it if they haven't negotiated that
+ * dialect? Or do the (non-OS/2) clients simply not care
+ * about that particular OS/2-oriented dialect?
+ */
+
+ /* IO Flag */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_sfi_ioflag(tvb, tree, offset);
+ bc -= 2;
+#else
+ /* 2 reserved bytes */
+ CHECK_BYTE_COUNT_TRANS(2);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS(2);
+#endif
+
+ break;
+ }
+ case 0x09: /*TRANS2_FSCTL*/
+ /* this call has no parameter block in the request */
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains a
+ * "File system specific parameter block". (That means
+ * we may not be able to dissect it in any case.)
+ */
+ break;
+ case 0x0a: /*TRANS2_IOCTL2*/
+ /* this call has no parameter block in the request */
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains a
+ * "Device/function specific parameter block". (That
+ * means we may not be able to dissect it in any case.)
+ */
+ break;
+ case 0x0b: { /*TRANS2_FIND_NOTIFY_FIRST*/
+ /* Search Attributes */
+ CHECK_BYTE_COUNT_TRANS(2);
+ offset = dissect_search_attributes(tvb, tree, offset);
+ bc -= 2;
+
+ /* Number of changes to wait for */
+ CHECK_BYTE_COUNT_TRANS(2);
+ proto_tree_add_item(tree, hf_smb_change_count, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS(2);
+
+ /* Find Notify information level */
+ CHECK_BYTE_COUNT_TRANS(2);
+ si->info_level = tvb_get_letohs(tvb, offset);
+ if (!pinfo->fd->flags.visited)
+ t2i->info_level = si->info_level;
+ proto_tree_add_uint(tree, hf_smb_fn_information_level, tvb, offset, 2, si->info_level);
+ COUNT_BYTES_TRANS(2);
+
+ /* 4 reserved bytes */
+ CHECK_BYTE_COUNT_TRANS(4);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS(4);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, &bc);
+ CHECK_STRING_TRANS(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s",
+ fn);
+ }
+
+ break;
+ }
+ case 0x0c: { /*TRANS2_FIND_NOTIFY_NEXT*/
+ /* Monitor handle */
+ CHECK_BYTE_COUNT_TRANS(2);
+ proto_tree_add_item(tree, hf_smb_monitor_handle, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS(2);
+
+ /* Number of changes to wait for */
+ CHECK_BYTE_COUNT_TRANS(2);
+ proto_tree_add_item(tree, hf_smb_change_count, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS(2);
+
+ break;
+ }
+ case 0x0d: /*TRANS2_CREATE_DIRECTORY*/
+ /* 4 reserved bytes */
+ CHECK_BYTE_COUNT_TRANS(4);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS(4);
+
+ /* dir name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len,
+ FALSE, FALSE, &bc);
+ CHECK_STRING_TRANS(fn);
+ proto_tree_add_string(tree, hf_smb_dir_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Dir: %s",
+ fn);
+ }
+ break;
+ case 0x0e: /*TRANS2_SESSION_SETUP*/
+ /* XXX unknown structure*/
+ break;
+ case 0x10: /*TRANS2_GET_DFS_REFERRAL*/
+ /* referral level */
+ CHECK_BYTE_COUNT_TRANS(2);
+ proto_tree_add_item(tree, hf_smb_max_referral_level, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS(2);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, &bc);
+ CHECK_STRING_TRANS(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
+ fn);
+ }
+
+ break;
+ case 0x11: /*TRANS2_REPORT_DFS_INCONSISTENCY*/
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, &bc);
+ CHECK_STRING_TRANS(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
+ fn);
+ }
+
+ break;
+ }
+
+ /* ooops there were data we didnt know how to process */
+ if(bc != 0){
+ proto_tree_add_item(tree, hf_smb_unknown, tvb, offset, bc, TRUE);
+ offset += bc;
+ }
+
+ return offset;
+}
+
+/*
+ * XXX - just use "dissect_connect_flags()" here?
+ */
+static guint16
+dissect_transaction_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Flags: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_transaction_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_transaction_flags_owt,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_transaction_flags_dtid,
+ tvb, offset, 2, mask);
+
+ return mask;
+}
+
+
+static int
+dissect_get_dfs_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Flags: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_get_dfs_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_get_dfs_server_hold_storage,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_get_dfs_fielding,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+ return offset;
+}
+
+static int
+dissect_dfs_referral_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Flags: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_dfs_referral_flags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_dfs_referral_flags_strip,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+
+ return offset;
+}
+
+
+/* dfs inconsistency data (4.4.2)
+*/
+static int
+dissect_dfs_inconsistency_data(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int offset, guint16 *bcp)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+
+ /*XXX shouldn this data hold version and size? unclear from doc*/
+ /* referral version */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_dfs_referral_version, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* referral size */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_dfs_referral_size, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* referral server type */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_dfs_referral_server_type, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* referral flags */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ offset = dissect_dfs_referral_flags(tvb, tree, offset);
+ *bcp -= 2;
+
+ /* node name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, bcp);
+ CHECK_STRING_TRANS_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_dfs_referral_node, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS_SUBR(fn_len);
+
+ return offset;
+}
+
+/* get dfs referral data (4.4.1)
+*/
+static int
+dissect_get_dfs_referral_data(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, int offset, guint16 *bcp)
+{
+ smb_info_t *si = pinfo->private_data;
+ guint16 numref;
+ guint16 refsize;
+ guint16 pathoffset;
+ guint16 altpathoffset;
+ guint16 nodeoffset;
+ int fn_len;
+ int stroffset;
+ int offsetoffset;
+ guint16 save_bc;
+ const char *fn;
+ int unklen;
+ int ucstring_end;
+ int ucstring_len;
+
+ /* path consumed */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_dfs_path_consumed, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* num referrals */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ numref = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_dfs_num_referrals, tvb, offset, 2, numref);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* get dfs flags */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ offset = dissect_get_dfs_flags(tvb, tree, offset);
+ *bcp -= 2;
+
+ /* XXX - in at least one capture there appears to be 2 bytes
+ of stuff after the Dfs flags, perhaps so that the header
+ in front of the referral list is a multiple of 4 bytes long. */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* if there are any referrals */
+ if(numref){
+ proto_item *ref_item = NULL;
+ proto_tree *ref_tree = NULL;
+ int old_offset=offset;
+
+ if(tree){
+ ref_item = proto_tree_add_text(tree,
+ tvb, offset, *bcp, "Referrals");
+ ref_tree = proto_item_add_subtree(ref_item,
+ ett_smb_dfs_referrals);
+ }
+ ucstring_end = -1;
+
+ while(numref--){
+ proto_item *ri = NULL;
+ proto_tree *rt = NULL;
+ int old_offset=offset;
+ guint16 version;
+
+ if(tree){
+ ri = proto_tree_add_text(ref_tree,
+ tvb, offset, *bcp, "Referral");
+ rt = proto_item_add_subtree(ri,
+ ett_smb_dfs_referral);
+ }
+
+ /* referral version */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ version = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(rt, hf_smb_dfs_referral_version,
+ tvb, offset, 2, version);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* referral size */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ refsize = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(rt, hf_smb_dfs_referral_size, tvb, offset, 2, refsize);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* referral server type */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(rt, hf_smb_dfs_referral_server_type, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* referral flags */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ offset = dissect_dfs_referral_flags(tvb, rt, offset);
+ *bcp -= 2;
+
+ switch(version){
+
+ case 1:
+ /* node name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, bcp);
+ CHECK_STRING_TRANS_SUBR(fn);
+ proto_tree_add_string(rt, hf_smb_dfs_referral_node, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS_SUBR(fn_len);
+ break;
+
+ case 2:
+ case 3: /* XXX - like version 2, but not identical;
+ seen in a capture, but the format isn't
+ documented */
+ /* proximity */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(rt, hf_smb_dfs_referral_proximity, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* ttl */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(rt, hf_smb_dfs_referral_ttl, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* path offset */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ pathoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(rt, hf_smb_dfs_referral_path_offset, tvb, offset, 2, pathoffset);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* alt path offset */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ altpathoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(rt, hf_smb_dfs_referral_alt_path_offset, tvb, offset, 2, altpathoffset);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* node offset */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ nodeoffset = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(rt, hf_smb_dfs_referral_node_offset, tvb, offset, 2, nodeoffset);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* path */
+ if (pathoffset != 0) {
+ stroffset = old_offset + pathoffset;
+ offsetoffset = stroffset - offset;
+ if (offsetoffset > 0 &&
+ *bcp > offsetoffset) {
+ save_bc = *bcp;
+ *bcp -= offsetoffset;
+ fn = get_unicode_or_ascii_string(tvb, &stroffset, si->unicode, &fn_len, FALSE, FALSE, bcp);
+ CHECK_STRING_TRANS_SUBR(fn);
+ proto_tree_add_string(rt, hf_smb_dfs_referral_path, tvb, stroffset, fn_len,
+ fn);
+ stroffset += fn_len;
+ if (ucstring_end < stroffset)
+ ucstring_end = stroffset;
+ *bcp = save_bc;
+ }
+ }
+
+ /* alt path */
+ if (altpathoffset != 0) {
+ stroffset = old_offset + altpathoffset;
+ offsetoffset = stroffset - offset;
+ if (offsetoffset > 0 &&
+ *bcp > offsetoffset) {
+ save_bc = *bcp;
+ *bcp -= offsetoffset;
+ fn = get_unicode_or_ascii_string(tvb, &stroffset, si->unicode, &fn_len, FALSE, FALSE, bcp);
+ CHECK_STRING_TRANS_SUBR(fn);
+ proto_tree_add_string(rt, hf_smb_dfs_referral_alt_path, tvb, stroffset, fn_len,
+ fn);
+ stroffset += fn_len;
+ if (ucstring_end < stroffset)
+ ucstring_end = stroffset;
+ *bcp = save_bc;
+ }
+ }
+
+ /* node */
+ if (nodeoffset != 0) {
+ stroffset = old_offset + nodeoffset;
+ offsetoffset = stroffset - offset;
+ if (offsetoffset > 0 &&
+ *bcp > offsetoffset) {
+ save_bc = *bcp;
+ *bcp -= offsetoffset;
+ fn = get_unicode_or_ascii_string(tvb, &stroffset, si->unicode, &fn_len, FALSE, FALSE, bcp);
+ CHECK_STRING_TRANS_SUBR(fn);
+ proto_tree_add_string(rt, hf_smb_dfs_referral_node, tvb, stroffset, fn_len,
+ fn);
+ stroffset += fn_len;
+ if (ucstring_end < stroffset)
+ ucstring_end = stroffset;
+ *bcp = save_bc;
+ }
+ }
+ break;
+ }
+
+ /*
+ * Show anything beyond the length of the referral
+ * as unknown data.
+ */
+ unklen = (old_offset + refsize) - offset;
+ if (unklen < 0) {
+ /*
+ * XXX - the length is bogus.
+ */
+ unklen = 0;
+ }
+ if (unklen != 0) {
+ CHECK_BYTE_COUNT_TRANS_SUBR(unklen);
+ proto_tree_add_item(rt, hf_smb_unknown, tvb,
+ offset, unklen, TRUE);
+ COUNT_BYTES_TRANS_SUBR(unklen);
+ }
+
+ proto_item_set_len(ri, offset-old_offset);
+ }
+
+ /*
+ * Treat the offset past the end of the last Unicode
+ * string after the referrals (if any) as the last
+ * offset.
+ */
+ if (ucstring_end > offset) {
+ ucstring_len = ucstring_end - offset;
+ if (*bcp < ucstring_len)
+ ucstring_len = *bcp;
+ offset += ucstring_len;
+ *bcp -= ucstring_len;
+ }
+ proto_item_set_len(ref_item, offset-old_offset);
+ }
+
+ return offset;
+}
+
+
+/* this dissects the SMB_INFO_STANDARD and SMB_INFO_QUERY_EA_SIZE
+ as described in 4.2.16.1
+*/
+static int
+dissect_4_2_16_1(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ /* create time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_create_time, hf_smb_create_dos_date, hf_smb_create_dos_time,
+ FALSE);
+ *bcp -= 4;
+
+ /* access time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_access_time, hf_smb_access_dos_date, hf_smb_access_dos_time,
+ FALSE);
+ *bcp -= 4;
+
+ /* last write time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_last_write_time, hf_smb_last_write_dos_date, hf_smb_last_write_dos_time,
+ FALSE);
+ *bcp -= 4;
+
+ /* data size */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* allocation size */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* File Attributes */
+ CHECK_BYTE_COUNT_SUBR(2);
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+ *bcp -= 2;
+
+ /* ea length */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_ea_list_length, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_INFO_QUERY_EAS_FROM_LIST and SMB_INFO_QUERY_ALL_EAS
+ as described in 4.2.16.2
+*/
+static int
+dissect_4_2_16_2(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ guint8 name_len;
+ guint16 data_len;
+ /* EA size */
+
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_ea_list_length, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ while (*bcp > 0) {
+ proto_item *item;
+ proto_tree *subtree;
+ int start_offset = offset;
+ guint8 *name;
+
+ item = proto_tree_add_text(
+ tree, tvb, offset, 0, "Extended Attribute");
+ subtree = proto_item_add_subtree(item, ett_smb_ea);
+
+ /* EA flags */
+
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(
+ subtree, hf_smb_ea_flags, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* EA name length */
+
+ name_len = tvb_get_guint8(tvb, offset);
+
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(
+ subtree, hf_smb_ea_name_length, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* EA data length */
+
+ data_len = tvb_get_letohs(tvb, offset);
+
+ CHECK_BYTE_COUNT_SUBR(2);
+ proto_tree_add_item(
+ subtree, hf_smb_ea_data_length, tvb, offset, 2, TRUE);
+ COUNT_BYTES_SUBR(2);
+
+ /* EA name */
+
+ name = tvb_get_string(tvb, offset, name_len);
+ proto_item_append_text(item, ": %s", name);
+ g_free(name);
+
+ CHECK_BYTE_COUNT_SUBR(name_len + 1);
+ proto_tree_add_item(
+ subtree, hf_smb_ea_name, tvb, offset, name_len + 1,
+ TRUE);
+ COUNT_BYTES_SUBR(name_len + 1);
+
+ /* EA data */
+
+ CHECK_BYTE_COUNT_SUBR(data_len);
+ proto_tree_add_item(
+ subtree, hf_smb_ea_data, tvb, offset, data_len, TRUE);
+ COUNT_BYTES_SUBR(data_len);
+
+ proto_item_set_len(item, offset - start_offset);
+ }
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_INFO_IS_NAME_VALID
+ as described in 4.2.16.3
+*/
+static int
+dissect_4_2_16_3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_QUERY_FILE_BASIC_INFO
+ as described in 4.2.16.4
+*/
+static int
+dissect_4_2_16_4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ /* create time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_create_time);
+ *bcp -= 8;
+
+ /* access time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_access_time);
+ *bcp -= 8;
+
+ /* last write time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_last_write_time);
+ *bcp -= 8;
+
+ /* last change time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_change_time);
+ *bcp -= 8;
+
+ /* File Attributes */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_file_attributes(tvb, tree, offset, 4);
+ *bcp -= 4;
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_QUERY_FILE_STANDARD_INFO
+ as described in 4.2.16.5
+*/
+static int
+dissect_4_2_16_5(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ /* allocation size */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* end of file */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* number of links */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_number_of_links, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* delete pending */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_delete_pending, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* is directory */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_is_directory, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_QUERY_FILE_EA_INFO
+ as described in 4.2.16.6
+*/
+static int
+dissect_4_2_16_6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ /* ea length */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_ea_list_length, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_QUERY_FILE_NAME_INFO
+ as described in 4.2.16.7
+ this is the same as SMB_QUERY_FILE_ALT_NAME_INFO
+ as described in 4.2.16.9
+*/
+static int
+dissect_4_2_16_7(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+
+ /* file name len */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_file_name_len, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_QUERY_FILE_ALL_INFO
+ as described in 4.2.16.8
+*/
+static int
+dissect_4_2_16_8(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+
+ offset = dissect_4_2_16_4(tvb, pinfo, tree, offset, bcp, trunc);
+ if (*trunc) {
+ return offset;
+ }
+ offset = dissect_4_2_16_5(tvb, pinfo, tree, offset, bcp, trunc);
+ if (*trunc) {
+ return offset;
+ }
+
+ /* index number */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_index_number, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ offset = dissect_4_2_16_6(tvb, pinfo, tree, offset, bcp, trunc);
+ if (*trunc)
+ return offset;
+
+ /* access flags */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_access_mask(tvb, tree, offset);
+ COUNT_BYTES_SUBR(4);
+
+ /* index number */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_index_number, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* current offset */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_current_offset, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* mode */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_nt_create_options(tvb, tree, offset);
+ *bcp -= 4;
+
+ /* alignment */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_t2_alignment, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ offset = dissect_4_2_16_6(tvb, pinfo, tree, offset, bcp, trunc);
+
+ return offset;
+}
+
+/* this dissects the SMB_QUERY_FILE_STREAM_INFO
+ as described in 4.2.16.10
+*/
+static int
+dissect_4_2_16_10(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ proto_item *item;
+ proto_tree *tree;
+ int old_offset;
+ guint32 neo;
+ smb_info_t *si = pinfo->private_data;
+ int fn_len;
+ const char *fn;
+ int padcnt;
+
+ for (;;) {
+ old_offset = offset;
+
+ /* next entry offset */
+ CHECK_BYTE_COUNT_SUBR(4);
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "Stream Info");
+ tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+ } else {
+ item = NULL;
+ tree = NULL;
+ }
+
+ neo = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+ COUNT_BYTES_SUBR(4);
+
+ /* stream name len */
+ CHECK_BYTE_COUNT_SUBR(4);
+ fn_len = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_t2_stream_name_length, tvb, offset, 4, fn_len);
+ COUNT_BYTES_SUBR(4);
+
+ /* stream size */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_t2_stream_size, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* allocation size */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* stream name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_t2_stream_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ proto_item_append_text(item, ": %s", fn);
+ proto_item_set_len(item, offset-old_offset);
+
+ if (neo == 0)
+ break; /* no more structures */
+
+ /* skip to next structure */
+ padcnt = (old_offset + neo) - offset;
+ if (padcnt < 0) {
+ /*
+ * XXX - this is bogus; flag it?
+ */
+ padcnt = 0;
+ }
+ if (padcnt != 0) {
+ CHECK_BYTE_COUNT_SUBR(padcnt);
+ COUNT_BYTES_SUBR(padcnt);
+ }
+ }
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_QUERY_FILE_COMPRESSION_INFO
+ as described in 4.2.16.11
+*/
+static int
+dissect_4_2_16_11(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ /* compressed file size */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_t2_compressed_file_size, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* compression format */
+ CHECK_BYTE_COUNT_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_t2_compressed_format, tvb, offset, 2, TRUE);
+ COUNT_BYTES_SUBR(2);
+
+ /* compression unit shift */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_t2_compressed_unit_shift,tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* compression chunk shift */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_t2_compressed_chunk_shift, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* compression cluster shift */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_t2_compressed_cluster_shift, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* 3 reserved bytes */
+ CHECK_BYTE_COUNT_SUBR(3);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 3, TRUE);
+ COUNT_BYTES_SUBR(3);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* 4.2.16.12 - SMB_QUERY_FILE_UNIX_BASIC */
+
+static const value_string unix_file_type_vals[] = {
+ { 0, "File" },
+ { 1, "Directory" },
+ { 2, "Symbolic link" },
+ { 3, "Character device" },
+ { 4, "Block device" },
+ { 5, "FIFO" },
+ { 6, "Socket" },
+ { 0, NULL }
+};
+
+static int
+dissect_4_2_16_12(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ /* End of file (file size) */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_size, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Number of bytes */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_num_bytes, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Last status change */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_unix_file_last_status);
+ *bcp -= 8; /* dissect_smb_64bit_time() increments offset */
+
+ /* Last access time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_unix_file_last_access);
+ *bcp -= 8;
+
+ /* Last modification time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_unix_file_last_change);
+ *bcp -= 8;
+
+ /* File owner uid */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_uid, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* File group gid */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_gid, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* File type */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_unix_file_type, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* Major device number */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_dev_major, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Minor device number */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_dev_minor, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Unique id */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_unique_id, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Permissions */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_permissions, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Nlinks */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_nlinks, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Sometimes there is one extra byte in the data field which I
+ guess could be padding, but we are only using 4 or 8 byte
+ data types so this is a bit confusing. -tpot */
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* 4.2.16.13 - SMB_QUERY_FILE_UNIX_LINK */
+
+static int
+dissect_4_2_16_13(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ smb_info_t *si = pinfo->private_data;
+ const char *fn;
+ int fn_len;
+
+ /* Link destination */
+
+ fn = get_unicode_or_ascii_string(
+ tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(
+ tree, hf_smb_unix_file_link_dest, tvb, offset, fn_len, fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_SET_FILE_DISPOSITION_INFO
+ as described in 4.2.19.2
+*/
+static int
+dissect_4_2_19_2(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ /* marked for deletion? */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_t2_marked_for_deletion, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_SET_FILE_ALLOCATION_INFO
+ as described in 4.2.19.3
+*/
+static int
+dissect_4_2_19_3(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ /* file allocation size */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* this dissects the SMB_SET_FILE_END_OF_FILE_INFO
+ as described in 4.2.19.4
+*/
+static int
+dissect_4_2_19_4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ /* file end of file offset */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* Set File Rename Info */
+
+static const true_false_string tfs_smb_replace = {
+ "Remove target file if it exists",
+ "Do NOT remove target file if it exists",
+};
+
+static int
+dissect_rename_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ smb_info_t *si = pinfo->private_data;
+ const char *fn;
+ guint32 target_name_len;
+ int fn_len;
+
+ /* Replace flag */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_replace, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* Root directory handle */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_root_dir_handle, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* Target name length */
+ CHECK_BYTE_COUNT_SUBR(4);
+ target_name_len = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_target_name_len, tvb, offset, 4, target_name_len);
+ COUNT_BYTES_SUBR(4);
+
+ /* Target name */
+ fn_len = target_name_len;
+ fn = get_unicode_or_ascii_string(
+ tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(
+ tree, hf_smb_target_name, tvb, offset, fn_len, fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/*dissect the data block for TRANS2_QUERY_PATH_INFORMATION and
+ TRANS2_QUERY_FILE_INFORMATION*/
+static int
+dissect_qpi_loi_vals(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
+ int offset, guint16 *bcp)
+{
+ smb_info_t *si;
+ gboolean trunc;
+
+ if(!*bcp){
+ return offset;
+ }
+
+ si = (smb_info_t *)pinfo->private_data;
+ switch(si->info_level){
+ case 1: /*Info Standard*/
+
+ case 2: /*Info Query EA Size*/
+ offset = dissect_4_2_16_1(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 3: /*Info Query EAs From List*/
+ case 4: /*Info Query All EAs*/
+ offset = dissect_4_2_16_2(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 6: /*Info Is Name Valid*/
+ offset = dissect_4_2_16_3(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0101: /*Query File Basic Info*/
+ case 1004: /* SMB_FILE_BASIC_INFORMATION */
+ offset = dissect_4_2_16_4(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0102: /*Query File Standard Info*/
+ case 1005: /* SMB_FILE_STANDARD_INFORMATION */
+ offset = dissect_4_2_16_5(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0103: /*Query File EA Info*/
+ case 1007: /* SMB_FILE_EA_INFORMATION */
+ offset = dissect_4_2_16_6(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0104: /*Query File Name Info*/
+ case 1009: /* SMB_FILE_NAME_INFORMATION */
+ offset = dissect_4_2_16_7(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0107: /*Query File All Info*/
+ case 1018: /* SMB_FILE_ALL_INFORMATION */
+ offset = dissect_4_2_16_8(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0108: /*Query File Alt File Info*/
+ case 1021: /* SMB_FILE_ALTERNATE_NAME_INFORMATION */
+ offset = dissect_4_2_16_7(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 1022: /* SMB_FILE_STREAM_INFORMATION */
+ ((smb_info_t *)(pinfo->private_data))->unicode = TRUE;
+ case 0x0109: /*Query File Stream Info*/
+ offset = dissect_4_2_16_10(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x010b: /*Query File Compression Info*/
+ case 1028: /* SMB_FILE_COMPRESSION_INFORMATION */
+ offset = dissect_4_2_16_11(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0200: /* Query File Unix Basic*/
+ offset = dissect_4_2_16_12(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0201: /* Query File Unix Link*/
+ offset = dissect_4_2_16_13(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0202: /* Query File Unix HardLink*/
+ /* XXX add this from the SNIA doc */
+ break;
+ }
+
+ return offset;
+}
+
+/*dissect the data block for TRANS2_SET_PATH_INFORMATION and
+ TRANS2_SET_FILE_INFORMATION*/
+static int
+dissect_spi_loi_vals(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
+ int offset, guint16 *bcp)
+{
+ smb_info_t *si;
+ gboolean trunc;
+
+ if(!*bcp){
+ return offset;
+ }
+
+ si = (smb_info_t *)pinfo->private_data;
+ switch(si->info_level){
+ case 1: /*Info Standard*/
+
+ case 2: /*Info Query EA Size*/
+ offset = dissect_4_2_16_1(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 4: /*Info Query All EAs*/
+ offset = dissect_4_2_16_2(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0101: /*Set File Basic Info*/
+ case 1004: /* SMB_FILE_BASIC_INFORMATION */
+ offset = dissect_4_2_16_4(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0102: /*Set File Disposition Info*/
+ offset = dissect_4_2_19_2(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0103: /*Set File Allocation Info*/
+ offset = dissect_4_2_19_3(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0104: /*Set End Of File Info*/
+ offset = dissect_4_2_19_4(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0200: /*Set File Unix Basic. Same as query. */
+ offset = dissect_4_2_16_12(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0201: /*Set File Unix Link. Same as query. */
+ offset = dissect_4_2_16_13(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 0x0203: /*Set File Unix HardLink. Same as link query. */
+ offset = dissect_4_2_16_13(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 1010: /* Set File Rename */
+ offset = dissect_rename_info(tvb, pinfo, tree, offset, bcp,
+ &trunc);
+ break;
+ case 1013:
+ case 1014:
+ case 1016:
+ case 1019:
+ case 1020:
+ case 1023:
+ case 1025:
+ case 1029:
+ case 1032:
+ case 1039:
+ case 1040:
+ /* XXX: TODO, extra levels discovered by tridge */
+ break;
+ }
+
+ return offset;
+}
+
+
+static const true_false_string tfs_quota_flags_deny_disk = {
+ "DENY DISK SPACE for users exceeding quota limit",
+ "Do NOT deny disk space for users exceeding quota limit"
+};
+static const true_false_string tfs_quota_flags_log_limit = {
+ "LOG EVENT when a user exceeds their QUOTA LIMIT",
+ "Do NOT log event when a user exceeds their quota limit"
+};
+static const true_false_string tfs_quota_flags_log_warning = {
+ "LOG EVENT when a user exceeds their WARNING LEVEL",
+ "Do NOT log event when a user exceeds their warning level"
+};
+static const true_false_string tfs_quota_flags_enabled = {
+ "Quotas are ENABLED of this fs",
+ "Quotas are NOT enabled on this fs"
+};
+static void
+dissect_quota_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint8 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_guint8(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+ "Quota Flags: 0x%02x %s", mask,
+ mask?"Enabled":"Disabled");
+ tree = proto_item_add_subtree(item, ett_smb_quotaflags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_quota_flags_log_limit,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_quota_flags_log_warning,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_quota_flags_deny_disk,
+ tvb, offset, 1, mask);
+
+ if(mask && (!(mask&0x01))){
+ proto_tree_add_boolean_hidden(tree, hf_smb_quota_flags_enabled,
+ tvb, offset, 1, 0x01);
+ } else {
+ proto_tree_add_boolean(tree, hf_smb_quota_flags_enabled,
+ tvb, offset, 1, mask);
+ }
+
+}
+
+static int
+dissect_nt_quota(tvbuff_t *tvb, proto_tree *tree, int offset, guint16 *bcp)
+{
+ /* first 24 bytes are unknown */
+ CHECK_BYTE_COUNT_TRANS_SUBR(24);
+ proto_tree_add_item(tree, hf_smb_unknown, tvb,
+ offset, 24, TRUE);
+ COUNT_BYTES_TRANS_SUBR(24);
+
+ /* number of bytes for quota warning */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_soft_quota_limit, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* number of bytes for quota limit */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_hard_quota_limit, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* one byte of quota flags */
+ CHECK_BYTE_COUNT_TRANS_SUBR(1);
+ dissect_quota_flags(tvb, tree, offset);
+ COUNT_BYTES_TRANS_SUBR(1);
+
+ /* these 7 bytes are unknown */
+ CHECK_BYTE_COUNT_TRANS_SUBR(7);
+ proto_tree_add_item(tree, hf_smb_unknown, tvb,
+ offset, 7, TRUE);
+ COUNT_BYTES_TRANS_SUBR(7);
+
+ return offset;
+}
+
+static int
+dissect_transaction2_request_data(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *parent_tree, int offset, int subcmd, guint16 dc)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, dc,
+ "%s Data",
+ val_to_str(subcmd, trans2_cmd_vals,
+ "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_transaction_data);
+ }
+
+ switch(subcmd){
+ case 0x00: /*TRANS2_OPEN2*/
+ /* XXX dont know how to decode FEAList */
+ break;
+ case 0x01: /*TRANS2_FIND_FIRST2*/
+ /* XXX dont know how to decode FEAList */
+ break;
+ case 0x02: /*TRANS2_FIND_NEXT2*/
+ /* XXX dont know how to decode FEAList */
+ break;
+ case 0x03: /*TRANS2_QUERY_FS_INFORMATION*/
+ /* no data field in this request */
+ break;
+ case 0x04: /* TRANS2_SET_QUOTA */
+ offset = dissect_nt_quota(tvb, tree, offset, &dc);
+ break;
+ case 0x05: /*TRANS2_QUERY_PATH_INFORMATION*/
+ /* no data field in this request */
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says there may be "Additional
+ * FileInfoLevel dependent information" here.
+ *
+ * Was that just a cut-and-pasteo?
+ * TRANS2_SET_PATH_INFORMATION *does* have that information
+ * here.
+ */
+ break;
+ case 0x06: /*TRANS2_SET_PATH_INFORMATION*/
+ offset = dissect_spi_loi_vals(tvb, pinfo, tree, offset, &dc);
+ break;
+ case 0x07: /*TRANS2_QUERY_FILE_INFORMATION*/
+ /* no data field in this request */
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says there may be "Additional
+ * FileInfoLevel dependent information" here.
+ *
+ * Was that just a cut-and-pasteo?
+ * TRANS2_SET_FILE_INFORMATION *does* have that information
+ * here.
+ */
+ break;
+ case 0x08: /*TRANS2_SET_FILE_INFORMATION*/
+ offset = dissect_spi_loi_vals(tvb, pinfo, tree, offset, &dc);
+ break;
+ case 0x09: /*TRANS2_FSCTL*/
+ /*XXX dont know how to decode this yet */
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains a
+ * "File system specific data block". (That means we
+ * may not be able to dissect it in any case.)
+ */
+ break;
+ case 0x0a: /*TRANS2_IOCTL2*/
+ /*XXX dont know how to decode this yet */
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains a
+ * "Device/function specific data block". (That
+ * means we may not be able to dissect it in any case.)
+ */
+ break;
+ case 0x0b: /*TRANS2_FIND_NOTIFY_FIRST*/
+ /*XXX dont know how to decode this yet */
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains "additional
+ * level dependent match data".
+ */
+ break;
+ case 0x0c: /*TRANS2_FIND_NOTIFY_NEXT*/
+ /*XXX dont know how to decode this yet */
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains "additional
+ * level dependent monitor information".
+ */
+ break;
+ case 0x0d: /*TRANS2_CREATE_DIRECTORY*/
+ /* XXX optional FEAList, unknown what FEAList looks like*/
+ break;
+ case 0x0e: /*TRANS2_SESSION_SETUP*/
+ /*XXX dont know how to decode this yet */
+ break;
+ case 0x10: /*TRANS2_GET_DFS_REFERRAL*/
+ /* no data field in this request */
+ break;
+ case 0x11: /*TRANS2_REPORT_DFS_INCONSISTENCY*/
+ offset = dissect_dfs_inconsistency_data(tvb, pinfo, tree, offset, &dc);
+ break;
+ }
+
+ /* ooops there were data we didnt know how to process */
+ if(dc != 0){
+ proto_tree_add_item(tree, hf_smb_unknown, tvb, offset, dc, TRUE);
+ offset += dc;
+ }
+
+ return offset;
+}
+
+
+static void
+dissect_trans_data(tvbuff_t *s_tvb, tvbuff_t *p_tvb, tvbuff_t *d_tvb,
+ proto_tree *tree)
+{
+ int i;
+ int offset;
+ guint length;
+
+ /*
+ * Show the setup words.
+ */
+ if (s_tvb != NULL) {
+ length = tvb_reported_length(s_tvb);
+ for (i = 0, offset = 0; length >= 2;
+ i++, offset += 2, length -= 2) {
+ /*
+ * XXX - add a setup word filterable field?
+ */
+ proto_tree_add_text(tree, s_tvb, offset, 2,
+ "Setup Word %d: 0x%04x", i,
+ tvb_get_letohs(s_tvb, offset));
+ }
+ }
+
+ /*
+ * Show the parameters, if any.
+ */
+ if (p_tvb != NULL) {
+ length = tvb_reported_length(p_tvb);
+ if (length != 0) {
+ proto_tree_add_text(tree, p_tvb, 0, length,
+ "Parameters: %s",
+ tvb_bytes_to_str(p_tvb, 0, length));
+ }
+ }
+
+ /*
+ * Show the data, if any.
+ */
+ if (d_tvb != NULL) {
+ length = tvb_reported_length(d_tvb);
+ if (length != 0) {
+ proto_tree_add_text(tree, d_tvb, 0, length,
+ "Data: %s", tvb_bytes_to_str(d_tvb, 0, length));
+ }
+ }
+}
+
+/* This routine handles the following 4 calls
+ Transaction 0x25
+ Transaction Secondary 0x26
+ Transaction2 0x32
+ Transaction2 Secondary 0x33
+*/
+static int
+dissect_transaction_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc, sc=0;
+ int so=offset;
+ int sl=0;
+ int spo=offset;
+ int spc=0;
+ guint16 od=0, tf, po=0, pc=0, dc=0, pd, dd=0;
+ int subcmd = -1;
+ guint32 to;
+ int an_len;
+ const char *an = NULL;
+ smb_info_t *si;
+ smb_transact2_info_t *t2i;
+ smb_transact_info_t *tri;
+ guint16 bc;
+ int padcnt;
+ gboolean dissected_trans;
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ WORD_COUNT;
+
+ if(wc==8){
+ /*secondary client request*/
+
+ /* total param count, only a 16bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_total_param_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* total data count , only 16bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_total_data_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* param count */
+ pc = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_count16, tvb, offset, 2, pc);
+ offset += 2;
+
+ /* param offset */
+ po = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_offset16, tvb, offset, 2, po);
+ offset += 2;
+
+ /* param disp */
+ pd = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_disp16, tvb, offset, 2, pd);
+ offset += 2;
+
+ /* data count */
+ dc = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_count16, tvb, offset, 2, dc);
+ offset += 2;
+
+ /* data offset */
+ od = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_offset16, tvb, offset, 2, od);
+ offset += 2;
+
+ /* data disp */
+ dd = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_disp16, tvb, offset, 2, dd);
+ offset += 2;
+
+ if(si->cmd==SMB_COM_TRANSACTION2){
+ guint16 fid;
+
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+
+ offset += 2;
+ }
+
+ /* There are no setup words. */
+ so = offset;
+ sc = 0;
+ sl = 0;
+ } else {
+ /* it is not a secondary request */
+
+ /* total param count , only a 16 bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_total_param_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* total data count , only 16bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_total_data_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* max param count , only 16bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_max_param_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* max data count, only 16bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_max_data_count, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* max setup count, only 16bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_max_setup_count, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* transaction flags */
+ tf = dissect_transaction_flags(tvb, tree, offset);
+ offset += 2;
+
+ /* timeout */
+ to = tvb_get_letohl(tvb, offset);
+ if (to == 0)
+ proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: Return immediately (0)");
+ else if (to == 0xffffffff)
+ proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: Wait indefinitely (-1)");
+ else
+ proto_tree_add_uint_format(tree, hf_smb_timeout, tvb, offset, 4, to, "Timeout: %s", time_msecs_to_str(to));
+ offset += 4;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* param count */
+ pc = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_count16, tvb, offset, 2, pc);
+ offset += 2;
+
+ /* param offset */
+ po = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_offset16, tvb, offset, 2, po);
+ offset += 2;
+
+ /* param displacement is zero here */
+ pd = 0;
+
+ /* data count */
+ dc = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_count16, tvb, offset, 2, dc);
+ offset += 2;
+
+ /* data offset */
+ od = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_offset16, tvb, offset, 2, od);
+ offset += 2;
+
+ /* data displacement is zero here */
+ dd = 0;
+
+ /* setup count */
+ sc = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_setup_count, tvb, offset, 1, sc);
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* this is where the setup bytes, if any start */
+ so = offset;
+ sl = sc*2;
+
+ /* if there were any setup bytes, decode them */
+ if(sc){
+ switch(si->cmd){
+
+ case SMB_COM_TRANSACTION2:
+ /* TRANSACTION2 only has one setup word and
+ that is the subcommand code.
+
+ XXX - except for TRANS2_FSCTL
+ and TRANS2_IOCTL. */
+ subcmd = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_trans2_subcmd,
+ tvb, offset, 2, subcmd);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(subcmd, trans2_cmd_vals,
+ "Unknown (0x%02x)"));
+ }
+ if (!si->unidir) {
+ if(!pinfo->fd->flags.visited){
+ /*
+ * Allocate a new
+ * smb_transact2_info_t
+ * structure.
+ */
+ t2i = g_mem_chunk_alloc(smb_transact2_info_chunk);
+ t2i->subcmd = subcmd;
+ t2i->info_level = -1;
+ t2i->resume_keys = FALSE;
+ si->sip->extra_info = t2i;
+ }
+ }
+
+ /*
+ * XXX - process TRANS2_FSCTL and
+ * TRANS2_IOCTL setup words here.
+ */
+ break;
+
+ case SMB_COM_TRANSACTION:
+ /* TRANSACTION setup words processed below */
+ break;
+ }
+
+ offset += sl;
+ }
+ }
+
+ BYTE_COUNT;
+
+ if(wc!=8){
+ /* primary request */
+ /* name is NULL if transaction2 */
+ if(si->cmd == SMB_COM_TRANSACTION){
+ /* Transaction Name */
+ an = get_unicode_or_ascii_string(tvb, &offset,
+ si->unicode, &an_len, FALSE, FALSE, &bc);
+ if (an == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_trans_name, tvb,
+ offset, an_len, an);
+ COUNT_BYTES(an_len);
+ }
+ }
+
+ /*
+ * The pipe or mailslot arguments for Transaction start with
+ * the first setup word (or where the first setup word would
+ * be if there were any setup words), and run to the current
+ * offset (which could mean that there aren't any).
+ */
+ spo = so;
+ spc = offset - spo;
+
+ /* parameters */
+ if(po>offset){
+ /* We have some initial padding bytes.
+ */
+ padcnt = po-offset;
+ if (padcnt > bc)
+ padcnt = bc;
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+ COUNT_BYTES(padcnt);
+ }
+ if(pc){
+ CHECK_BYTE_COUNT(pc);
+ switch(si->cmd) {
+
+ case SMB_COM_TRANSACTION2:
+ /* TRANSACTION2 parameters*/
+ offset = dissect_transaction2_request_parameters(tvb,
+ pinfo, tree, offset, subcmd, pc);
+ bc -= pc;
+ break;
+
+ case SMB_COM_TRANSACTION:
+ /* TRANSACTION parameters processed below */
+ COUNT_BYTES(pc);
+ break;
+ }
+ }
+
+ /* data */
+ if(od>offset){
+ /* We have some initial padding bytes.
+ */
+ padcnt = od-offset;
+ if (padcnt > bc)
+ padcnt = bc;
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+ COUNT_BYTES(padcnt);
+ }
+ if(dc){
+ CHECK_BYTE_COUNT(dc);
+ switch(si->cmd){
+
+ case SMB_COM_TRANSACTION2:
+ /* TRANSACTION2 data*/
+ offset = dissect_transaction2_request_data(tvb, pinfo,
+ tree, offset, subcmd, dc);
+ bc -= dc;
+ break;
+
+ case SMB_COM_TRANSACTION:
+ /* TRANSACTION data processed below */
+ COUNT_BYTES(dc);
+ break;
+ }
+ }
+
+ /*TRANSACTION request parameters */
+ if(si->cmd==SMB_COM_TRANSACTION){
+ /*XXX replace this block with a function and use that one
+ for both requests/responses*/
+ if(dd==0){
+ tvbuff_t *p_tvb, *d_tvb, *s_tvb;
+ tvbuff_t *sp_tvb, *pd_tvb;
+
+ if(pc>0){
+ if(pc>tvb_length_remaining(tvb, po)){
+ p_tvb = tvb_new_subset(tvb, po, tvb_length_remaining(tvb, po), pc);
+ } else {
+ p_tvb = tvb_new_subset(tvb, po, pc, pc);
+ }
+ } else {
+ p_tvb = NULL;
+ }
+ if(dc>0){
+ if(dc>tvb_length_remaining(tvb, od)){
+ d_tvb = tvb_new_subset(tvb, od, tvb_length_remaining(tvb, od), dc);
+ } else {
+ d_tvb = tvb_new_subset(tvb, od, dc, dc);
+ }
+ } else {
+ d_tvb = NULL;
+ }
+ if(sl){
+ if(sl>tvb_length_remaining(tvb, so)){
+ s_tvb = tvb_new_subset(tvb, so, tvb_length_remaining(tvb, so), sl);
+ } else {
+ s_tvb = tvb_new_subset(tvb, so, sl, sl);
+ }
+ } else {
+ s_tvb = NULL;
+ }
+
+ if (!si->unidir) {
+ if(!pinfo->fd->flags.visited){
+ /*
+ * Allocate a new smb_transact_info_t
+ * structure.
+ */
+ tri = g_mem_chunk_alloc(smb_transact_info_chunk);
+ tri->subcmd = -1;
+ tri->trans_subcmd = -1;
+ tri->function = -1;
+ tri->fid = -1;
+ tri->lanman_cmd = 0;
+ tri->param_descrip = NULL;
+ tri->data_descrip = NULL;
+ tri->aux_data_descrip = NULL;
+ tri->info_level = -1;
+ si->sip->extra_info = tri;
+ } else {
+ /*
+ * We already filled the structure
+ * in; don't bother doing so again.
+ */
+ tri = NULL;
+ }
+ } else {
+ /*
+ * This is a unidirectional message, for
+ * which there will be no reply; don't
+ * bother allocating an "smb_transact_info_t"
+ * structure for it.
+ */
+ tri = NULL;
+ }
+ dissected_trans = FALSE;
+ if(strncmp("\\PIPE\\", an, 6) == 0){
+ if (tri != NULL)
+ tri->subcmd=TRANSACTION_PIPE;
+
+ /*
+ * A tvbuff containing the setup words and
+ * the pipe path.
+ */
+ sp_tvb = tvb_new_subset(tvb, spo, spc, spc);
+
+ /*
+ * A tvbuff containing the parameters and the
+ * data.
+ */
+ pd_tvb = tvb_new_subset(tvb, po, -1, -1);
+
+ dissected_trans = dissect_pipe_smb(sp_tvb,
+ s_tvb, pd_tvb, p_tvb, d_tvb, an+6, pinfo,
+ top_tree);
+
+ /* In case we did not see the TreeConnect call,
+ store this TID here as well as a IPC TID
+ so we know that future Read/Writes to this
+ TID is (probably) DCERPC.
+ */
+ if(g_hash_table_lookup(si->ct->tid_service, (void *)si->tid)){
+ g_hash_table_remove(si->ct->tid_service, (void *)si->tid);
+ }
+ g_hash_table_insert(si->ct->tid_service, (void *)si->tid, (void *)TID_IPC);
+ } else if(strncmp("\\MAILSLOT\\", an, 10) == 0){
+ if (tri != NULL)
+ tri->subcmd=TRANSACTION_MAILSLOT;
+
+ /*
+ * A tvbuff containing the setup words and
+ * the mailslot path.
+ */
+ sp_tvb = tvb_new_subset(tvb, spo, spc, spc);
+ dissected_trans = dissect_mailslot_smb(sp_tvb,
+ s_tvb, d_tvb, an+10, pinfo, top_tree);
+ }
+ if (!dissected_trans)
+ dissect_trans_data(s_tvb, p_tvb, d_tvb, tree);
+ } else {
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_append_str(pinfo->cinfo, COL_INFO,
+ "[transact continuation]");
+ }
+ }
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
+
+static int
+dissect_4_3_4_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ int fn_len;
+ const char *fn;
+ int old_offset = offset;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ smb_transact2_info_t *t2i;
+ gboolean resume_keys = FALSE;
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL) {
+ t2i = si->sip->extra_info;
+ if (t2i != NULL)
+ resume_keys = t2i->resume_keys;
+ }
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+ val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+ }
+
+ if (resume_keys) {
+ /* resume key */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_resume, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+ }
+
+ /* create time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_create_time,
+ hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
+ *bcp -= 4;
+
+ /* access time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_access_time,
+ hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
+ *bcp -= 4;
+
+ /* last write time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_last_write_time,
+ hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
+ *bcp -= 4;
+
+ /* data size */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* allocation size */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* File Attributes */
+ CHECK_BYTE_COUNT_SUBR(2);
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+ *bcp -= 2;
+
+ /* file name len */
+ CHECK_BYTE_COUNT_SUBR(1);
+ fn_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 1, fn_len);
+ COUNT_BYTES_SUBR(1);
+ if (si->unicode)
+ fn_len += 2; /* include terminating '\0' */
+ else
+ fn_len++; /* include terminating '\0' */
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ fn);
+ }
+
+ proto_item_append_text(item, " File: %s", fn);
+ proto_item_set_len(item, offset-old_offset);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+static int
+dissect_4_3_4_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ int fn_len;
+ const char *fn;
+ int old_offset = offset;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ smb_transact2_info_t *t2i;
+ gboolean resume_keys = FALSE;
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL) {
+ t2i = si->sip->extra_info;
+ if (t2i != NULL)
+ resume_keys = t2i->resume_keys;
+ }
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+ val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+ }
+
+ if (resume_keys) {
+ /* resume key */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_resume, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+ }
+
+ /* create time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_create_time,
+ hf_smb_create_dos_date, hf_smb_create_dos_time, FALSE);
+ *bcp -= 4;
+
+ /* access time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_access_time,
+ hf_smb_access_dos_date, hf_smb_access_dos_time, FALSE);
+ *bcp -= 4;
+
+ /* last write time */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_last_write_time,
+ hf_smb_last_write_dos_date, hf_smb_last_write_dos_time, FALSE);
+ *bcp -= 4;
+
+ /* data size */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* allocation size */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_alloc_size, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* File Attributes */
+ CHECK_BYTE_COUNT_SUBR(2);
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+ *bcp -= 2;
+
+ /* ea length */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_ea_list_length, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* file name len */
+ CHECK_BYTE_COUNT_SUBR(1);
+ fn_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 1, fn_len);
+ COUNT_BYTES_SUBR(1);
+ if (si->unicode)
+ fn_len += 2; /* include terminating '\0' */
+ else
+ fn_len++; /* include terminating '\0' */
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ fn);
+ }
+
+ proto_item_append_text(item, " File: %s", fn);
+ proto_item_set_len(item, offset-old_offset);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+static int
+dissect_4_3_4_4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ int fn_len;
+ const char *fn;
+ int old_offset = offset;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ guint32 neo;
+ int padcnt;
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+ val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+ }
+
+ /*
+ * We assume that the presence of a next entry offset implies the
+ * absence of a resume key, as appears to be the case for 4.3.4.6.
+ */
+
+ /* next entry offset */
+ CHECK_BYTE_COUNT_SUBR(4);
+ neo = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+ COUNT_BYTES_SUBR(4);
+
+ /* file index */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_file_index, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* create time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_create_time);
+ *bcp -= 8;
+
+ /* access time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_access_time);
+ *bcp -= 8;
+
+ /* last write time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_last_write_time);
+ *bcp -= 8;
+
+ /* last change time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_change_time);
+ *bcp -= 8;
+
+ /* end of file */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* allocation size */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Extended File Attributes */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_file_ext_attr(tvb, tree, offset);
+ *bcp -= 4;
+
+ /* file name len */
+ CHECK_BYTE_COUNT_SUBR(4);
+ fn_len = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+ COUNT_BYTES_SUBR(4);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ fn);
+ }
+
+ /* skip to next structure */
+ if(neo){
+ padcnt = (old_offset + neo) - offset;
+ if (padcnt < 0) {
+ /*
+ * XXX - this is bogus; flag it?
+ */
+ padcnt = 0;
+ }
+ if (padcnt != 0) {
+ CHECK_BYTE_COUNT_SUBR(padcnt);
+ COUNT_BYTES_SUBR(padcnt);
+ }
+ }
+
+ proto_item_append_text(item, " File: %s", fn);
+ proto_item_set_len(item, offset-old_offset);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+static int
+dissect_4_3_4_5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ int fn_len;
+ const char *fn;
+ int old_offset = offset;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ guint32 neo;
+ int padcnt;
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+ val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+ }
+
+ /*
+ * We assume that the presence of a next entry offset implies the
+ * absence of a resume key, as appears to be the case for 4.3.4.6.
+ */
+
+ /* next entry offset */
+ CHECK_BYTE_COUNT_SUBR(4);
+ neo = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+ COUNT_BYTES_SUBR(4);
+
+ /* file index */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_file_index, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* create time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_create_time);
+ *bcp -= 8;
+
+ /* access time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_access_time);
+ *bcp -= 8;
+
+ /* last write time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_last_write_time);
+ *bcp -= 8;
+
+ /* last change time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_change_time);
+ *bcp -= 8;
+
+ /* end of file */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* allocation size */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Extended File Attributes */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_file_ext_attr(tvb, tree, offset);
+ *bcp -= 4;
+
+ /* file name len */
+ CHECK_BYTE_COUNT_SUBR(4);
+ fn_len = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+ COUNT_BYTES_SUBR(4);
+
+ /* ea length */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_ea_list_length, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ fn);
+ }
+
+ /* skip to next structure */
+ if(neo){
+ padcnt = (old_offset + neo) - offset;
+ if (padcnt < 0) {
+ /*
+ * XXX - this is bogus; flag it?
+ */
+ padcnt = 0;
+ }
+ if (padcnt != 0) {
+ CHECK_BYTE_COUNT_SUBR(padcnt);
+ COUNT_BYTES_SUBR(padcnt);
+ }
+ }
+
+ proto_item_append_text(item, " File: %s", fn);
+ proto_item_set_len(item, offset-old_offset);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+static int
+dissect_4_3_4_6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ int fn_len, sfn_len;
+ const char *fn, *sfn;
+ int old_offset = offset;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ guint32 neo;
+ int padcnt;
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+ val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+ }
+
+ /*
+ * XXX - I have not seen any of these that contain a resume
+ * key, even though some of the requests had the "return resume
+ * key" flag set.
+ */
+
+ /* next entry offset */
+ CHECK_BYTE_COUNT_SUBR(4);
+ neo = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+ COUNT_BYTES_SUBR(4);
+
+ /* file index */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_file_index, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* create time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_create_time);
+ *bcp -= 8;
+
+ /* access time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_access_time);
+ *bcp -= 8;
+
+ /* last write time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_last_write_time);
+ *bcp -= 8;
+
+ /* last change time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_change_time);
+ *bcp -= 8;
+
+ /* end of file */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* allocation size */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Extended File Attributes */
+ CHECK_BYTE_COUNT_SUBR(4);
+ offset = dissect_file_ext_attr(tvb, tree, offset);
+ *bcp -= 4;
+
+ /* file name len */
+ CHECK_BYTE_COUNT_SUBR(4);
+ fn_len = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+ COUNT_BYTES_SUBR(4);
+
+ /*
+ * EA length.
+ *
+ * XXX - in one captures, this has the topmost bit set, and the
+ * rest of the bits have the value 7. Is the topmost bit being
+ * set some indication that the value *isn't* the length of
+ * the EAs?
+ */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_ea_list_length, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* short file name len */
+ CHECK_BYTE_COUNT_SUBR(1);
+ sfn_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_short_file_name_len, tvb, offset, 1, sfn_len);
+ COUNT_BYTES_SUBR(1);
+
+ /* reserved byte */
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
+
+ /* short file name - it's not always in Unicode */
+ sfn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &sfn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_SUBR(sfn);
+ proto_tree_add_string(tree, hf_smb_short_file_name, tvb, offset, 24,
+ sfn);
+ COUNT_BYTES_SUBR(24);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ fn);
+ }
+
+ /* skip to next structure */
+ if(neo){
+ padcnt = (old_offset + neo) - offset;
+ if (padcnt < 0) {
+ /*
+ * XXX - this is bogus; flag it?
+ */
+ padcnt = 0;
+ }
+ if (padcnt != 0) {
+ CHECK_BYTE_COUNT_SUBR(padcnt);
+ COUNT_BYTES_SUBR(padcnt);
+ }
+ }
+
+ proto_item_append_text(item, " File: %s", fn);
+ proto_item_set_len(item, offset-old_offset);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+static int
+dissect_4_3_4_7(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ int fn_len;
+ const char *fn;
+ int old_offset = offset;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ guint32 neo;
+ int padcnt;
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, *bcp, "%s",
+ val_to_str(si->info_level, ff2_il_vals, "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_ff2_data);
+ }
+
+ /*
+ * We assume that the presence of a next entry offset implies the
+ * absence of a resume key, as appears to be the case for 4.3.4.6.
+ */
+
+ /* next entry offset */
+ CHECK_BYTE_COUNT_SUBR(4);
+ neo = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
+ COUNT_BYTES_SUBR(4);
+
+ /* file index */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_file_index, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* file name len */
+ CHECK_BYTE_COUNT_SUBR(4);
+ fn_len = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_file_name_len, tvb, offset, 4, fn_len);
+ COUNT_BYTES_SUBR(4);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ fn);
+ }
+
+ /* skip to next structure */
+ if(neo){
+ padcnt = (old_offset + neo) - offset;
+ if (padcnt < 0) {
+ /*
+ * XXX - this is bogus; flag it?
+ */
+ padcnt = 0;
+ }
+ if (padcnt != 0) {
+ CHECK_BYTE_COUNT_SUBR(padcnt);
+ COUNT_BYTES_SUBR(padcnt);
+ }
+ }
+
+ proto_item_append_text(item, " File: %s", fn);
+ proto_item_set_len(item, offset-old_offset);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/* 4.3.4.8 - SMB_FIND_FILE_UNIX */
+
+static int
+dissect_4_3_4_8(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
+ proto_tree *tree, int offset, guint16 *bcp,
+ gboolean *trunc)
+{
+ smb_info_t *si = pinfo->private_data;
+ const char *fn;
+ int fn_len;
+
+ /* NextEntryOffset */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_unix_find_file_nextoffset, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* ResumeKey */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_unix_find_file_resumekey, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* End of file (file size) */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_size, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Number of bytes */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_num_bytes, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Last status change */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_unix_file_last_status);
+ *bcp -= 8;
+
+ /* Last access time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_unix_file_last_access);
+ *bcp -= 8;
+
+ /* Last modification time */
+ CHECK_BYTE_COUNT_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_unix_file_last_change);
+ *bcp -= 8;
+
+ /* File owner uid */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_uid, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* File group gid */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_gid, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* File type */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_unix_file_type, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* Major device number */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_dev_major, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Minor device number */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_dev_minor, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Unique id */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_unique_id, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Permissions */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_permissions, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Nlinks */
+ CHECK_BYTE_COUNT_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unix_file_nlinks, tvb, offset, 8, TRUE);
+ COUNT_BYTES_SUBR(8);
+
+ /* Name */
+
+ fn = get_unicode_or_ascii_string(
+ tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, bcp);
+
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(
+ tree, hf_smb_unix_file_link_dest, tvb, offset, fn_len, fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ /* Pad to 4 bytes */
+
+ if (offset % 4)
+ offset += 4 - (offset % 4);
+
+ *trunc = FALSE;
+ return offset;
+}
+
+/*dissect the data block for TRANS2_FIND_FIRST2*/
+static int
+dissect_ff2_response_data(tvbuff_t * tvb, packet_info * pinfo,
+ proto_tree * tree, int offset, guint16 *bcp, gboolean *trunc)
+{
+ smb_info_t *si;
+
+ if(!*bcp){
+ return offset;
+ }
+
+ si = (smb_info_t *)pinfo->private_data;
+ switch(si->info_level){
+ case 1: /*Info Standard*/
+ offset = dissect_4_3_4_1(tvb, pinfo, tree, offset, bcp,
+ trunc);
+ break;
+ case 2: /*Info Query EA Size*/
+ offset = dissect_4_3_4_2(tvb, pinfo, tree, offset, bcp,
+ trunc);
+ break;
+ case 3: /*Info Query EAs From List same as
+ InfoQueryEASize*/
+ offset = dissect_4_3_4_2(tvb, pinfo, tree, offset, bcp,
+ trunc);
+ break;
+ case 0x0101: /*Find File Directory Info*/
+ offset = dissect_4_3_4_4(tvb, pinfo, tree, offset, bcp,
+ trunc);
+ break;
+ case 0x0102: /*Find File Full Directory Info*/
+ offset = dissect_4_3_4_5(tvb, pinfo, tree, offset, bcp,
+ trunc);
+ break;
+ case 0x0103: /*Find File Names Info*/
+ offset = dissect_4_3_4_7(tvb, pinfo, tree, offset, bcp,
+ trunc);
+ break;
+ case 0x0104: /*Find File Both Directory Info*/
+ offset = dissect_4_3_4_6(tvb, pinfo, tree, offset, bcp,
+ trunc);
+ break;
+ case 0x0202: /*Find File UNIX*/
+ offset = dissect_4_3_4_8(tvb, pinfo, tree, offset, bcp,
+ trunc);
+ break;
+ default: /* unknown info level */
+ *trunc = FALSE;
+ break;
+ }
+ return offset;
+}
+
+
+static int
+dissect_fs_attributes(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "FS Attributes: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_fs_attributes);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_fs_attr_css,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_fs_attr_cpn,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_fs_attr_pacls,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_fs_attr_fc,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_fs_attr_vq,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_fs_attr_dim,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_fs_attr_vic,
+ tvb, offset, 4, mask);
+
+ offset += 4;
+ return offset;
+}
+
+
+static int
+dissect_device_characteristics(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint32 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohl(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 4,
+ "Device Characteristics: 0x%08x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_device_characteristics);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_device_char_removable,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_device_char_read_only,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_device_char_floppy,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_device_char_write_once,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_device_char_remote,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_device_char_mounted,
+ tvb, offset, 4, mask);
+ proto_tree_add_boolean(tree, hf_smb_device_char_virtual,
+ tvb, offset, 4, mask);
+
+ offset += 4;
+ return offset;
+}
+
+/*dissect the data block for TRANS2_QUERY_FS_INFORMATION*/
+
+static const true_false_string tfs_smb_mac_access_ctrl = {
+ "Macintosh Access Control Supported",
+ "Macintosh Access Control Not Supported"
+};
+
+static const true_false_string tfs_smb_mac_getset_comments = {
+ "Macintosh Get & Set Comments Supported",
+ "Macintosh Get & Set Comments Not Supported"
+};
+
+static const true_false_string tfs_smb_mac_desktopdb_calls = {
+ "Macintosh Get & Set Desktop Database Info Supported",
+ "Macintosh Get & Set Desktop Database Info Supported"
+};
+
+static const true_false_string tfs_smb_mac_unique_ids = {
+ "Macintosh Unique IDs Supported",
+ "Macintosh Unique IDs Not Supported"
+};
+
+static const true_false_string tfs_smb_mac_streams = {
+ "Macintosh and Streams Extensions Not Supported",
+ "Macintosh and Streams Extensions Supported"
+};
+
+static int
+dissect_qfsi_vals(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
+ int offset, guint16 *bcp)
+{
+ smb_info_t *si;
+ int fn_len, vll, fnl;
+ const char *fn;
+ guint support = 0;
+ proto_item *item = NULL;
+ proto_tree *ti = NULL;
+
+ if(!*bcp){
+ return offset;
+ }
+
+ si = (smb_info_t *)pinfo->private_data;
+ switch(si->info_level){
+ case 1: /* SMB_INFO_ALLOCATION */
+ /* filesystem id */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_fs_id, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* sectors per unit */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_sector_unit, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* units */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_fs_units, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* avail units */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_avail_units, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* bytes per sector, only 16bit integer here */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_uint(tree, hf_smb_fs_sector, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ break;
+ case 2: /* SMB_INFO_VOLUME */
+ /* volume serial number */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_volume_serial_num, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* volume label length, only one byte here */
+ CHECK_BYTE_COUNT_TRANS_SUBR(1);
+ proto_tree_add_uint(tree, hf_smb_volume_label_len, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ COUNT_BYTES_TRANS_SUBR(1);
+
+ /* label */
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, FALSE, bcp);
+ CHECK_STRING_TRANS_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_volume_label, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS_SUBR(fn_len);
+
+ break;
+ case 0x0101: /* SMB_QUERY_FS_LABEL_INFO */
+ case 1002: /* SMB_FS_LABEL_INFORMATION */
+ /* volume label length */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ vll = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_volume_label_len, tvb, offset, 4, vll);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* label */
+ fn_len = vll;
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_TRANS_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_volume_label, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS_SUBR(fn_len);
+
+ break;
+ case 0x0102: /* SMB_QUERY_FS_VOLUME_INFO */
+ case 1001: /* SMB_FS_VOLUME_INFORMATION */
+ /* create time */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset,
+ hf_smb_create_time);
+ *bcp -= 8;
+
+ /* volume serial number */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_volume_serial_num, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* volume label length */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ vll = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_volume_label_len, tvb, offset, 4, vll);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* 2 reserved bytes */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* label */
+ fn_len = vll;
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_TRANS_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_volume_label, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS_SUBR(fn_len);
+
+ break;
+ case 0x0103: /* SMB_QUERY_FS_SIZE_INFO */
+ case 1003: /* SMB_FS_SIZE_INFORMATION */
+ /* allocation size */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* free allocation units */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_free_alloc_units64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* sectors per unit */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_sector_unit, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* bytes per sector */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_fs_sector, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ break;
+ case 0x0104: /* SMB_QUERY_FS_DEVICE_INFO */
+ case 1004: /* SMB_FS_DEVICE_INFORMATION */
+ /* device type */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_device_type, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* device characteristics */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ offset = dissect_device_characteristics(tvb, tree, offset);
+ *bcp -= 4;
+
+ break;
+ case 0x0105: /* SMB_QUERY_FS_ATTRIBUTE_INFO */
+ case 1005: /* SMB_FS_ATTRIBUTE_INFORMATION */
+ /* FS attributes */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ offset = dissect_fs_attributes(tvb, tree, offset);
+ *bcp -= 4;
+
+ /* max name len */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_max_name_len, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* fs name length */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ fnl = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_fs_name_len, tvb, offset, 4, fnl);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* label */
+ fn_len = fnl;
+ fn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+ CHECK_STRING_TRANS_SUBR(fn);
+ proto_tree_add_string(tree, hf_smb_fs_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES_TRANS_SUBR(fn_len);
+
+ break;
+ case 0x200: { /* SMB_QUERY_CIFS_UNIX_INFO */
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+ guint32 caps_lo, caps_hi;
+
+ /* MajorVersionNumber */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_unix_major_version, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* MinorVersionNumber */
+ CHECK_BYTE_COUNT_TRANS_SUBR(2);
+ proto_tree_add_item(tree, hf_smb_unix_minor_version, tvb, offset, 2, TRUE);
+ COUNT_BYTES_TRANS_SUBR(2);
+
+ /* Capability */
+
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+
+ caps_lo = tvb_get_letohl(tvb, offset);
+ caps_hi = tvb_get_letohl(tvb, offset + 4);
+
+ if (tree) {
+ item = proto_tree_add_text(
+ tree, tvb, offset, 8, "Capabilities: 0x%08x%08x",
+ caps_hi, caps_lo);
+ subtree = proto_item_add_subtree(
+ item, ett_smb_unix_capabilities);
+ }
+
+ proto_tree_add_boolean(
+ subtree, hf_smb_unix_capability_fcntl, tvb, offset, 8,
+ caps_lo);
+
+ proto_tree_add_boolean(
+ subtree, hf_smb_unix_capability_posix_acl, tvb, offset, 8,
+ caps_lo);
+
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ break;
+ }
+ case 0x301: /* MAC_QUERY_FS_INFO */
+ /* Create time */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_create_time);
+ *bcp -= 8;
+ /* Modify Time */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_modify_time);
+ *bcp -= 8;
+ /* Backup Time */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ offset = dissect_smb_64bit_time(tvb, tree, offset, hf_smb_backup_time);
+ *bcp -= 8;
+ /* Allocation blocks */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_mac_alloc_block_count, tvb,
+ offset,
+ 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+ /* Allocation Block Size */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_mac_alloc_block_size, tvb,
+ offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+ /* Free Block Count */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_mac_free_block_count, tvb,
+ offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+ /* Finder Info ... */
+ CHECK_BYTE_COUNT_TRANS_SUBR(32);
+ proto_tree_add_bytes_format(tree, hf_smb_mac_fndrinfo, tvb,
+ offset, 32,
+ tvb_get_ptr(tvb, offset,32),
+ "Finder Info: %s",
+ tvb_format_text(tvb, offset, 32));
+ COUNT_BYTES_TRANS_SUBR(32);
+ /* Number Files */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_mac_root_file_count, tvb,
+ offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+ /* Number of Root Directories */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_mac_root_dir_count, tvb,
+ offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+ /* Number of files */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_mac_file_count, tvb,
+ offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+ /* Dir Count */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_mac_dir_count, tvb,
+ offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+ /* Mac Support Flags */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ support = tvb_get_ntohl(tvb, offset);
+ item = proto_tree_add_text(tree, tvb, offset, 4,
+ "Mac Support Flags: 0x%08x", support);
+ ti = proto_item_add_subtree(item, ett_smb_mac_support_flags);
+ proto_tree_add_boolean(ti, hf_smb_mac_sup_access_ctrl,
+ tvb, offset, 4, support);
+ proto_tree_add_boolean(ti, hf_smb_mac_sup_getset_comments,
+ tvb, offset, 4, support);
+ proto_tree_add_boolean(ti, hf_smb_mac_sup_desktopdb_calls,
+ tvb, offset, 4, support);
+ proto_tree_add_boolean(ti, hf_smb_mac_sup_unique_ids,
+ tvb, offset, 4, support);
+ proto_tree_add_boolean(ti, hf_smb_mac_sup_streams,
+ tvb, offset, 4, support);
+ COUNT_BYTES_TRANS_SUBR(4);
+ break;
+ case 1006: /* QUERY_FS_QUOTA_INFO */
+ offset = dissect_nt_quota(tvb, tree, offset, bcp);
+ break;
+ case 1007: /* SMB_FS_FULL_SIZE_INFORMATION */
+ /* allocation size */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* caller free allocation units */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_caller_free_alloc_units64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* actual free allocation units */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_actual_free_alloc_units64, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* sectors per unit */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_sector_unit, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* bytes per sector */
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_fs_sector, tvb, offset, 4, TRUE);
+ COUNT_BYTES_TRANS_SUBR(4);
+ break;
+ case 1008: /* Query Object ID is GUID plus unknown data */ {
+ e_uuid_t fs_id;
+ char uuid_str[DCERPC_UUID_STR_LEN];
+ int uuid_str_len;
+ guint8 drep = 0x10;
+
+ CHECK_BYTE_COUNT_TRANS_SUBR(16);
+
+ dcerpc_tvb_get_uuid (tvb, offset, &drep, &fs_id);
+
+ uuid_str_len = snprintf(
+ uuid_str, DCERPC_UUID_STR_LEN,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ fs_id.Data1, fs_id.Data2, fs_id.Data3,
+ fs_id.Data4[0], fs_id.Data4[1],
+ fs_id.Data4[2], fs_id.Data4[3],
+ fs_id.Data4[4], fs_id.Data4[5],
+ fs_id.Data4[6], fs_id.Data4[7]);
+
+ proto_tree_add_string_format(
+ tree, hf_smb_fs_guid, tvb,
+ offset, 16, uuid_str, "GUID: %s", uuid_str);
+
+ COUNT_BYTES_TRANS_SUBR(16);
+ break;
+ }
+ }
+
+ return offset;
+}
+
+static int
+dissect_transaction2_response_data(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *parent_tree)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ smb_transact2_info_t *t2i;
+ int count;
+ gboolean trunc;
+ int offset = 0;
+ guint16 dc;
+
+ dc = tvb_reported_length(tvb);
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL)
+ t2i = si->sip->extra_info;
+ else
+ t2i = NULL;
+
+ if(parent_tree){
+ if (t2i != NULL && t2i->subcmd != -1) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, dc,
+ "%s Data",
+ val_to_str(t2i->subcmd, trans2_cmd_vals,
+ "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_transaction_data);
+ } else {
+ item = proto_tree_add_text(parent_tree, tvb, offset, dc,
+ "Unknown Transaction2 Data");
+ }
+ }
+
+ if (t2i == NULL) {
+ offset += dc;
+ return offset;
+ }
+ switch(t2i->subcmd){
+ case 0x00: /*TRANS2_OPEN2*/
+ /* XXX not implemented yet. See SNIA doc */
+ break;
+ case 0x01: /*TRANS2_FIND_FIRST2*/
+ /* returned data */
+ count = si->info_count;
+
+ if (count && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", Files:");
+ }
+
+ while(count--){
+ offset = dissect_ff2_response_data(tvb, pinfo, tree,
+ offset, &dc, &trunc);
+ if (trunc)
+ break;
+ }
+ break;
+ case 0x02: /*TRANS2_FIND_NEXT2*/
+ /* returned data */
+ count = si->info_count;
+
+ if (count && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", Files:");
+ }
+
+ while(count--){
+ offset = dissect_ff2_response_data(tvb, pinfo, tree,
+ offset, &dc, &trunc);
+ if (trunc)
+ break;
+ }
+ break;
+ case 0x03: /*TRANS2_QUERY_FS_INFORMATION*/
+ offset = dissect_qfsi_vals(tvb, pinfo, tree, offset, &dc);
+ break;
+ case 0x05: /*TRANS2_QUERY_PATH_INFORMATION*/
+ offset = dissect_qpi_loi_vals(tvb, pinfo, tree, offset, &dc);
+ break;
+ case 0x06: /*TRANS2_SET_PATH_INFORMATION*/
+ /* no data in this response */
+ break;
+ case 0x07: /*TRANS2_QUERY_FILE_INFORMATION*/
+ /* identical to QUERY_PATH_INFO */
+ offset = dissect_qpi_loi_vals(tvb, pinfo, tree, offset, &dc);
+ break;
+ case 0x08: /*TRANS2_SET_FILE_INFORMATION*/
+ /* no data in this response */
+ break;
+ case 0x09: /*TRANS2_FSCTL*/
+ /* XXX dont know how to dissect this one (yet)*/
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains a
+ * "File system specific return data block".
+ * (That means we may not be able to dissect it in any
+ * case.)
+ */
+ break;
+ case 0x0a: /*TRANS2_IOCTL2*/
+ /* XXX dont know how to dissect this one (yet)*/
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains a
+ * "Device/function specific return data block".
+ * (That means we may not be able to dissect it in any
+ * case.)
+ */
+ break;
+ case 0x0b: /*TRANS2_FIND_NOTIFY_FIRST*/
+ /* XXX dont know how to dissect this one (yet)*/
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains "the level
+ * dependent information about the changes which
+ * occurred".
+ */
+ break;
+ case 0x0c: /*TRANS2_FIND_NOTIFY_NEXT*/
+ /* XXX dont know how to dissect this one (yet)*/
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains "the level
+ * dependent information about the changes which
+ * occurred".
+ */
+ break;
+ case 0x0d: /*TRANS2_CREATE_DIRECTORY*/
+ /* no data in this response */
+ break;
+ case 0x0e: /*TRANS2_SESSION_SETUP*/
+ /* XXX dont know how to dissect this one (yet)*/
+ break;
+ case 0x10: /*TRANS2_GET_DFS_REFERRAL*/
+ offset = dissect_get_dfs_referral_data(tvb, pinfo, tree, offset, &dc);
+ break;
+ case 0x11: /*TRANS2_REPORT_DFS_INCONSISTENCY*/
+ /* the SNIA spec appears to say the response has no data */
+ break;
+ case -1:
+ /*
+ * We don't know what the matching request was; don't
+ * bother putting anything else into the tree for the data.
+ */
+ offset += dc;
+ dc = 0;
+ break;
+ }
+
+ /* ooops there were data we didnt know how to process */
+ if(dc != 0){
+ proto_tree_add_item(tree, hf_smb_unknown, tvb, offset, dc, TRUE);
+ offset += dc;
+ }
+
+ return offset;
+}
+
+
+static void
+dissect_transaction2_response_parameters(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+ smb_info_t *si;
+ smb_transact2_info_t *t2i;
+ guint16 fid;
+ int lno;
+ int offset = 0;
+ int pc;
+
+ pc = tvb_reported_length(tvb);
+
+ si = (smb_info_t *)pinfo->private_data;
+ if (si->sip != NULL)
+ t2i = si->sip->extra_info;
+ else
+ t2i = NULL;
+
+ if(parent_tree){
+ if (t2i != NULL && t2i->subcmd != -1) {
+ item = proto_tree_add_text(parent_tree, tvb, offset, pc,
+ "%s Parameters",
+ val_to_str(t2i->subcmd, trans2_cmd_vals,
+ "Unknown (0x%02x)"));
+ tree = proto_item_add_subtree(item, ett_smb_transaction_params);
+ } else {
+ item = proto_tree_add_text(parent_tree, tvb, offset, pc,
+ "Unknown Transaction2 Parameters");
+ }
+ }
+
+ if (t2i == NULL) {
+ offset += pc;
+ return;
+ }
+ switch(t2i->subcmd){
+ case 0x00: /*TRANS2_OPEN2*/
+ /* fid */
+ fid = tvb_get_letohs(tvb, offset);
+ add_fid(tvb, pinfo, tree, offset, 2, fid);
+ offset += 2;
+
+ /*
+ * XXX - Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990 says that the file attributes, create
+ * time (which it says is the last modification time),
+ * data size, granted access, file type, and IPC state
+ * are returned only if bit 0 is set in the open flags,
+ * and that the EA length is returned only if bit 3
+ * is set in the open flags. Does that mean that,
+ * at least in that SMB dialect, those fields are not
+ * present in the reply parameters if the bits in
+ * question aren't set?
+ */
+
+ /* File Attributes */
+ offset = dissect_file_attributes(tvb, tree, offset, 2);
+
+ /* create time */
+ offset = dissect_smb_datetime(tvb, tree, offset,
+ hf_smb_create_time,
+ hf_smb_create_dos_date, hf_smb_create_dos_time, TRUE);
+
+ /* data size */
+ proto_tree_add_item(tree, hf_smb_data_size, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* granted access */
+ offset = dissect_access(tvb, tree, offset, "Granted");
+
+ /* File Type */
+ proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* IPC State */
+ offset = dissect_ipc_state(tvb, tree, offset, FALSE);
+
+ /* open_action */
+ offset = dissect_open_action(tvb, tree, offset);
+
+ /* server unique file ID */
+ proto_tree_add_item(tree, hf_smb_file_id, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ /* ea error offset, only a 16 bit integer here */
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* ea length */
+ proto_tree_add_item(tree, hf_smb_ea_list_length, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ break;
+ case 0x01: /*TRANS2_FIND_FIRST2*/
+ /* Find First2 information level */
+ proto_tree_add_uint(tree, hf_smb_ff2_information_level, tvb, 0, 0, si->info_level);
+
+ /* sid */
+ proto_tree_add_item(tree, hf_smb_search_id, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* search count */
+ si->info_count = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_search_count, tvb, offset, 2, si->info_count);
+ offset += 2;
+
+ /* end of search */
+ proto_tree_add_item(tree, hf_smb_end_of_search, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* ea error offset, only a 16 bit integer here */
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* last name offset */
+ lno = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_last_name_offset, tvb, offset, 2, lno);
+ offset += 2;
+
+ break;
+ case 0x02: /*TRANS2_FIND_NEXT2*/
+ /* search count */
+ si->info_count = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_search_count, tvb, offset, 2, si->info_count);
+ offset += 2;
+
+ /* end of search */
+ proto_tree_add_item(tree, hf_smb_end_of_search, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* ea_error_offset, only a 16 bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ /* last name offset */
+ lno = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_last_name_offset, tvb, offset, 2, lno);
+ offset += 2;
+
+ break;
+ case 0x03: /*TRANS2_QUERY_FS_INFORMATION*/
+ /* no parameter block here */
+ break;
+ case 0x05: /*TRANS2_QUERY_PATH_INFORMATION*/
+ /* ea_error_offset, only a 16 bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ break;
+ case 0x06: /*TRANS2_SET_PATH_INFORMATION*/
+ /* ea_error_offset, only a 16 bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ break;
+ case 0x07: /*TRANS2_QUERY_FILE_INFORMATION*/
+ /* ea_error_offset, only a 16 bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ break;
+ case 0x08: /*TRANS2_SET_FILE_INFORMATION*/
+ /* ea_error_offset, only a 16 bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ break;
+ case 0x09: /*TRANS2_FSCTL*/
+ /* XXX dont know how to dissect this one (yet)*/
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains a
+ * "File system specific return parameter block".
+ * (That means we may not be able to dissect it in any
+ * case.)
+ */
+ break;
+ case 0x0a: /*TRANS2_IOCTL2*/
+ /* XXX dont know how to dissect this one (yet)*/
+
+ /*
+ * XXX - "Microsoft Networks SMB File Sharing Protocol
+ * Extensions Version 3.0, Document Version 1.11,
+ * July 19, 1990" says this this contains a
+ * "Device/function specific return parameter block".
+ * (That means we may not be able to dissect it in any
+ * case.)
+ */
+ break;
+ case 0x0b: /*TRANS2_FIND_NOTIFY_FIRST*/
+ /* Find Notify information level */
+ proto_tree_add_uint(tree, hf_smb_fn_information_level, tvb, 0, 0, si->info_level);
+
+ /* Monitor handle */
+ proto_tree_add_item(tree, hf_smb_monitor_handle, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* Change count */
+ si->info_count = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_change_count, tvb, offset, 2, si->info_count);
+ offset += 2;
+
+ /* ea_error_offset, only a 16 bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ break;
+ case 0x0c: /*TRANS2_FIND_NOTIFY_NEXT*/
+ /* Find Notify information level */
+ proto_tree_add_uint(tree, hf_smb_fn_information_level, tvb, 0, 0, si->info_level);
+
+ /* Change count */
+ si->info_count = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_change_count, tvb, offset, 2, si->info_count);
+ offset += 2;
+
+ /* ea_error_offset, only a 16 bit integer here*/
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ break;
+ case 0x0d: /*TRANS2_CREATE_DIRECTORY*/
+ /* ea error offset, only a 16 bit integer here */
+ proto_tree_add_uint(tree, hf_smb_ea_error_offset, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ break;
+ case 0x0e: /*TRANS2_SESSION_SETUP*/
+ /* XXX dont know how to dissect this one (yet)*/
+ break;
+ case 0x10: /*TRANS2_GET_DFS_REFERRAL*/
+ /* XXX dont know how to dissect this one (yet) see SNIA doc*/
+ break;
+ case 0x11: /*TRANS2_REPORT_DFS_INCONSISTENCY*/
+ /* XXX dont know how to dissect this one (yet) see SNIA doc*/
+ break;
+ case -1:
+ /*
+ * We don't know what the matching request was; don't
+ * bother putting anything else into the tree for the data.
+ */
+ offset += pc;
+ break;
+ }
+
+ /* ooops there were data we didnt know how to process */
+ if(offset<pc){
+ proto_tree_add_item(tree, hf_smb_unknown, tvb, offset, pc-offset, TRUE);
+ offset += pc-offset;
+ }
+}
+
+
+static int
+dissect_transaction_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 sc, wc;
+ guint16 od=0, po=0, pc=0, pd=0, dc=0, dd=0, td=0, tp=0;
+ smb_info_t *si;
+ smb_transact2_info_t *t2i = NULL;
+ guint16 bc;
+ int padcnt;
+ gboolean dissected_trans;
+ fragment_data *r_fd = NULL;
+ tvbuff_t *pd_tvb=NULL, *d_tvb=NULL, *p_tvb=NULL;
+ tvbuff_t *s_tvb=NULL, *sp_tvb=NULL;
+ gboolean save_fragmented;
+
+ si = (smb_info_t *)pinfo->private_data;
+
+ switch(si->cmd){
+ case SMB_COM_TRANSACTION2:
+ /* transaction2 */
+ if (si->sip != NULL) {
+ t2i = si->sip->extra_info;
+ } else
+ t2i = NULL;
+ if (t2i == NULL) {
+ /*
+ * We didn't see the matching request, so we don't
+ * know what type of transaction this is.
+ */
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "Subcommand: <UNKNOWN> since request packet wasn't seen");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "<unknown>");
+ }
+ } else {
+ si->info_level = t2i->info_level;
+ if (t2i->subcmd == -1) {
+ /*
+ * We didn't manage to extract the subcommand
+ * from the matching request (perhaps because
+ * the frame was short), so we don't know what
+ * type of transaction this is.
+ */
+ proto_tree_add_text(tree, tvb, 0, 0,
+ "Subcommand: <UNKNOWN> since transaction code wasn't found in request packet");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "<unknown>");
+ }
+ } else {
+ proto_tree_add_uint(tree, hf_smb_trans2_subcmd, tvb, 0, 0, t2i->subcmd);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(t2i->subcmd,
+ trans2_cmd_vals,
+ "<unknown (0x%02x)>"));
+ }
+ }
+ }
+ break;
+ }
+
+ WORD_COUNT;
+
+ /* total param count, only a 16bit integer here */
+ tp = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_total_param_count, tvb, offset, 2, tp);
+ offset += 2;
+
+ /* total data count, only a 16 bit integer here */
+ td = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_total_data_count, tvb, offset, 2, td);
+ offset += 2;
+
+ /* 2 reserved bytes */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ /* param count */
+ pc = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_count16, tvb, offset, 2, pc);
+ offset += 2;
+
+ /* param offset */
+ po = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_offset16, tvb, offset, 2, po);
+ offset += 2;
+
+ /* param disp */
+ pd = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_param_disp16, tvb, offset, 2, pd);
+ offset += 2;
+
+ /* data count */
+ dc = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_count16, tvb, offset, 2, dc);
+ offset += 2;
+
+ /* data offset */
+ od = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_offset16, tvb, offset, 2, od);
+ offset += 2;
+
+ /* data disp */
+ dd = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_disp16, tvb, offset, 2, dd);
+ offset += 2;
+
+ /* setup count */
+ sc = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_setup_count, tvb, offset, 1, sc);
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+
+ /* if there were any setup bytes, put them in a tvb for later */
+ if(sc){
+ if((2*sc)>tvb_length_remaining(tvb, offset)){
+ s_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), 2*sc);
+ } else {
+ s_tvb = tvb_new_subset(tvb, offset, 2*sc, 2*sc);
+ }
+ sp_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ } else {
+ s_tvb = NULL;
+ sp_tvb=NULL;
+ }
+ offset += 2*sc;
+
+
+ BYTE_COUNT;
+
+
+ /* reassembly of SMB Transaction data payload.
+ In this section we do reassembly of both the data and parameters
+ blocks of the SMB transaction command.
+ */
+ save_fragmented = pinfo->fragmented;
+ /* do we need reassembly? */
+ if( (td!=dc) || (tp!=pc) ){
+ /* oh yeah, either data or parameter section needs
+ reassembly
+ */
+ pinfo->fragmented = TRUE;
+ if(smb_trans_reassembly){
+ /* ...and we were told to do reassembly */
+ if(pc && (tvb_length_remaining(tvb, po)>=pc) ){
+ r_fd = smb_trans_defragment(tree, pinfo, tvb,
+ po, pc, pd, td+tp);
+
+ }
+ if((r_fd==NULL) && dc && (tvb_length_remaining(tvb, od)>=dc) ){
+ r_fd = smb_trans_defragment(tree, pinfo, tvb,
+ od, dc, dd+tp, td+tp);
+ }
+ }
+ }
+
+ /* if we got a reassembled fd structure from the reassembly routine we must
+ create pd_tvb from it
+ */
+ if(r_fd){
+ pd_tvb = tvb_new_real_data(r_fd->data, r_fd->datalen,
+ r_fd->datalen);
+ tvb_set_child_real_data_tvbuff(tvb, pd_tvb);
+ add_new_data_source(pinfo, pd_tvb, "Reassembled SMB");
+ show_fragment_tree(r_fd, &smb_frag_items, tree, pinfo, pd_tvb);
+ }
+
+
+ if(pd_tvb){
+ /* OK we have reassembled data, extract d_tvb and p_tvb from it */
+ if(tp){
+ p_tvb = tvb_new_subset(pd_tvb, 0, tp, tp);
+ }
+ if(td){
+ d_tvb = tvb_new_subset(pd_tvb, tp, td, td);
+ }
+ } else {
+ /* It was not reassembled. Do as best as we can.
+ * in this case we always try to dissect the stuff if
+ * data and param displacement is 0. i.e. for the first
+ * (and maybe only) packet.
+ */
+ if( (pd==0) && (dd==0) ){
+ int min;
+ int reported_min;
+ min = MIN(pc,tvb_length_remaining(tvb,po));
+ reported_min = MIN(pc,tvb_reported_length_remaining(tvb,po));
+ if(min && reported_min) {
+ p_tvb = tvb_new_subset(tvb, po, min, reported_min);
+ }
+ min = MIN(dc,tvb_length_remaining(tvb,od));
+ reported_min = MIN(dc,tvb_reported_length_remaining(tvb,od));
+ if(min && reported_min) {
+ d_tvb = tvb_new_subset(tvb, od, min, reported_min);
+ }
+ /*
+ * A tvbuff containing the parameters
+ * and the data.
+ * XXX - check pc and dc as well?
+ */
+ if (tvb_length_remaining(tvb, po)){
+ pd_tvb = tvb_new_subset(tvb, po, -1, -1);
+ }
+ }
+ }
+
+
+
+ /* parameters */
+ if(po>offset){
+ /* We have some padding bytes.
+ */
+ padcnt = po-offset;
+ if (padcnt > bc)
+ padcnt = bc;
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+ COUNT_BYTES(padcnt);
+ }
+ if(si->cmd==SMB_COM_TRANSACTION2 && p_tvb){
+ /* TRANSACTION2 parameters*/
+ dissect_transaction2_response_parameters(p_tvb, pinfo, tree);
+ }
+ COUNT_BYTES(pc);
+
+
+ /* data */
+ if(od>offset){
+ /* We have some initial padding bytes.
+ */
+ padcnt = od-offset;
+ if (padcnt > bc)
+ padcnt = bc;
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, TRUE);
+ COUNT_BYTES(padcnt);
+ }
+ /*
+ * If the data count is bigger than the count of bytes
+ * remaining, clamp it so that the count of bytes remaining
+ * doesn't go negative.
+ */
+ if (dc > bc)
+ dc = bc;
+ COUNT_BYTES(dc);
+
+
+
+ /* from now on, everything is in separate tvbuffs so we dont count
+ the bytes with COUNT_BYTES any more.
+ neither do we reference offset any more (which by now points to the
+ first byte AFTER this PDU */
+
+
+ if(si->cmd==SMB_COM_TRANSACTION2 && d_tvb){
+ /* TRANSACTION2 parameters*/
+ dissect_transaction2_response_data(d_tvb, pinfo, tree);
+ }
+
+
+ if(si->cmd==SMB_COM_TRANSACTION){
+ smb_transact_info_t *tri;
+
+ dissected_trans = FALSE;
+ if (si->sip != NULL)
+ tri = si->sip->extra_info;
+ else
+ tri = NULL;
+ if (tri != NULL) {
+ switch(tri->subcmd){
+
+ case TRANSACTION_PIPE:
+ /* This function is safe to call for
+ s_tvb==sp_tvb==NULL, i.e. if we don't
+ know them at this point.
+ It's also safe to call if "p_tvb"
+ or "d_tvb" are null.
+ */
+ if( pd_tvb) {
+ dissected_trans = dissect_pipe_smb(
+ sp_tvb, s_tvb, pd_tvb, p_tvb,
+ d_tvb, NULL, pinfo, top_tree);
+ }
+ break;
+
+ case TRANSACTION_MAILSLOT:
+ /* This one should be safe to call
+ even if s_tvb and sp_tvb is NULL
+ */
+ if(d_tvb){
+ dissected_trans = dissect_mailslot_smb(
+ sp_tvb, s_tvb, d_tvb, NULL, pinfo,
+ top_tree);
+ }
+ break;
+ }
+ }
+ if (!dissected_trans) {
+ /* This one is safe to call for s_tvb==p_tvb==d_tvb==NULL */
+ dissect_trans_data(s_tvb, p_tvb, d_tvb, tree);
+ }
+ }
+
+
+ if( (p_tvb==0) && (d_tvb==0) ){
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_append_str(pinfo->cinfo, COL_INFO,
+ "[transact continuation]");
+ }
+ }
+
+ pinfo->fragmented = save_fragmented;
+ END_OF_SMB
+
+ return offset;
+}
+
+
+static int
+dissect_find_notify_close(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* Monitor handle */
+ proto_tree_add_item(tree, hf_smb_monitor_handle, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ BYTE_COUNT;
+
+ END_OF_SMB
+
+ return offset;
+}
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ END Transaction/Transaction2 Primary and secondary requests
+ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+
+
+static int
+dissect_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
+{
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ if (wc != 0) {
+ proto_tree_add_text(tree, tvb, offset, wc*2, "Word parameters");
+ offset += wc*2;
+ }
+
+ BYTE_COUNT;
+
+ if (bc != 0) {
+ proto_tree_add_text(tree, tvb, offset, bc, "Byte parameters");
+ offset += bc;
+ bc = 0;
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+typedef struct _smb_function {
+ int (*request)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree);
+ int (*response)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree);
+} smb_function;
+
+static smb_function smb_dissector[256] = {
+ /* 0x00 Create Dir*/ {dissect_old_dir_request, dissect_empty},
+ /* 0x01 Delete Dir*/ {dissect_old_dir_request, dissect_empty},
+ /* 0x02 Open File*/ {dissect_open_file_request, dissect_open_file_response},
+ /* 0x03 Create File*/ {dissect_create_file_request, dissect_fid},
+ /* 0x04 Close File*/ {dissect_close_file_request, dissect_empty},
+ /* 0x05 Flush File*/ {dissect_fid, dissect_empty},
+ /* 0x06 Delete File*/ {dissect_delete_file_request, dissect_empty},
+ /* 0x07 Rename File*/ {dissect_rename_file_request, dissect_empty},
+ /* 0x08 Query Info*/ {dissect_query_information_request, dissect_query_information_response},
+ /* 0x09 Set Info*/ {dissect_set_information_request, dissect_empty},
+ /* 0x0a Read File*/ {dissect_read_file_request, dissect_read_file_response},
+ /* 0x0b Write File*/ {dissect_write_file_request, dissect_write_file_response},
+ /* 0x0c Lock Byte Range*/ {dissect_lock_request, dissect_empty},
+ /* 0x0d Unlock Byte Range*/ {dissect_lock_request, dissect_empty},
+ /* 0x0e Create Temp*/ {dissect_create_temporary_request, dissect_create_temporary_response},
+ /* 0x0f Create New*/ {dissect_create_file_request, dissect_fid},
+
+ /* 0x10 Check Dir*/ {dissect_old_dir_request, dissect_empty},
+ /* 0x11 Process Exit*/ {dissect_empty, dissect_empty},
+ /* 0x12 Seek File*/ {dissect_seek_file_request, dissect_seek_file_response},
+ /* 0x13 Lock And Read*/ {dissect_read_file_request, dissect_lock_and_read_response},
+ /* 0x14 Write And Unlock*/ {dissect_write_file_request, dissect_write_file_response},
+ /* 0x15 */ {dissect_unknown, dissect_unknown},
+ /* 0x16 */ {dissect_unknown, dissect_unknown},
+ /* 0x17 */ {dissect_unknown, dissect_unknown},
+ /* 0x18 */ {dissect_unknown, dissect_unknown},
+ /* 0x19 */ {dissect_unknown, dissect_unknown},
+ /* 0x1a Read Raw*/ {dissect_read_raw_request, dissect_unknown},
+ /* 0x1b Read MPX*/ {dissect_read_mpx_request, dissect_read_mpx_response},
+ /* 0x1c Read MPX Secondary*/ {dissect_unknown, dissect_unknown},
+ /* 0x1d Write Raw*/ {dissect_write_raw_request, dissect_write_raw_response},
+ /* 0x1e Write MPX*/ {dissect_write_mpx_request, dissect_write_mpx_response},
+ /* 0x1f Write MPX Secondary*/ {dissect_unknown, dissect_unknown},
+
+ /* 0x20 Write Complete*/ {dissect_unknown, dissect_write_and_close_response},
+ /* 0x21 */ {dissect_unknown, dissect_unknown},
+ /* 0x22 Set Info2*/ {dissect_set_information2_request, dissect_empty},
+ /* 0x23 Query Info2*/ {dissect_fid, dissect_query_information2_response},
+ /* 0x24 Locking And X*/ {dissect_locking_andx_request, dissect_locking_andx_response},
+ /* 0x25 Transaction*/ {dissect_transaction_request, dissect_transaction_response},
+ /* 0x26 Transaction Secondary*/ {dissect_transaction_request, dissect_unknown}, /*This SMB has no response */
+ /* 0x27 IOCTL*/ {dissect_unknown, dissect_unknown},
+ /* 0x28 IOCTL Secondary*/ {dissect_unknown, dissect_unknown},
+ /* 0x29 Copy File*/ {dissect_copy_request, dissect_move_copy_response},
+ /* 0x2a Move File*/ {dissect_move_request, dissect_move_copy_response},
+ /* 0x2b Echo*/ {dissect_echo_request, dissect_echo_response},
+ /* 0x2c Write And Close*/ {dissect_write_and_close_request, dissect_write_and_close_response},
+ /* 0x2d Open And X*/ {dissect_open_andx_request, dissect_open_andx_response},
+ /* 0x2e Read And X*/ {dissect_read_andx_request, dissect_read_andx_response},
+ /* 0x2f Write And X*/ {dissect_write_andx_request, dissect_write_andx_response},
+
+ /* 0x30 */ {dissect_unknown, dissect_unknown},
+ /* 0x31 Close And Tree Disconnect */ {dissect_close_file_request, dissect_empty},
+ /* 0x32 Transaction2*/ {dissect_transaction_request, dissect_transaction_response},
+ /* 0x33 Transaction2 Secondary*/ {dissect_transaction_request, dissect_unknown}, /*This SMB has no response */
+ /* 0x34 Find Close2*/ {dissect_sid, dissect_empty},
+ /* 0x35 Find Notify Close*/ {dissect_find_notify_close, dissect_empty},
+ /* 0x36 */ {dissect_unknown, dissect_unknown},
+ /* 0x37 */ {dissect_unknown, dissect_unknown},
+ /* 0x38 */ {dissect_unknown, dissect_unknown},
+ /* 0x39 */ {dissect_unknown, dissect_unknown},
+ /* 0x3a */ {dissect_unknown, dissect_unknown},
+ /* 0x3b */ {dissect_unknown, dissect_unknown},
+ /* 0x3c */ {dissect_unknown, dissect_unknown},
+ /* 0x3d */ {dissect_unknown, dissect_unknown},
+ /* 0x3e */ {dissect_unknown, dissect_unknown},
+ /* 0x3f */ {dissect_unknown, dissect_unknown},
+
+ /* 0x40 */ {dissect_unknown, dissect_unknown},
+ /* 0x41 */ {dissect_unknown, dissect_unknown},
+ /* 0x42 */ {dissect_unknown, dissect_unknown},
+ /* 0x43 */ {dissect_unknown, dissect_unknown},
+ /* 0x44 */ {dissect_unknown, dissect_unknown},
+ /* 0x45 */ {dissect_unknown, dissect_unknown},
+ /* 0x46 */ {dissect_unknown, dissect_unknown},
+ /* 0x47 */ {dissect_unknown, dissect_unknown},
+ /* 0x48 */ {dissect_unknown, dissect_unknown},
+ /* 0x49 */ {dissect_unknown, dissect_unknown},
+ /* 0x4a */ {dissect_unknown, dissect_unknown},
+ /* 0x4b */ {dissect_unknown, dissect_unknown},
+ /* 0x4c */ {dissect_unknown, dissect_unknown},
+ /* 0x4d */ {dissect_unknown, dissect_unknown},
+ /* 0x4e */ {dissect_unknown, dissect_unknown},
+ /* 0x4f */ {dissect_unknown, dissect_unknown},
+
+ /* 0x50 */ {dissect_unknown, dissect_unknown},
+ /* 0x51 */ {dissect_unknown, dissect_unknown},
+ /* 0x52 */ {dissect_unknown, dissect_unknown},
+ /* 0x53 */ {dissect_unknown, dissect_unknown},
+ /* 0x54 */ {dissect_unknown, dissect_unknown},
+ /* 0x55 */ {dissect_unknown, dissect_unknown},
+ /* 0x56 */ {dissect_unknown, dissect_unknown},
+ /* 0x57 */ {dissect_unknown, dissect_unknown},
+ /* 0x58 */ {dissect_unknown, dissect_unknown},
+ /* 0x59 */ {dissect_unknown, dissect_unknown},
+ /* 0x5a */ {dissect_unknown, dissect_unknown},
+ /* 0x5b */ {dissect_unknown, dissect_unknown},
+ /* 0x5c */ {dissect_unknown, dissect_unknown},
+ /* 0x5d */ {dissect_unknown, dissect_unknown},
+ /* 0x5e */ {dissect_unknown, dissect_unknown},
+ /* 0x5f */ {dissect_unknown, dissect_unknown},
+
+ /* 0x60 */ {dissect_unknown, dissect_unknown},
+ /* 0x61 */ {dissect_unknown, dissect_unknown},
+ /* 0x62 */ {dissect_unknown, dissect_unknown},
+ /* 0x63 */ {dissect_unknown, dissect_unknown},
+ /* 0x64 */ {dissect_unknown, dissect_unknown},
+ /* 0x65 */ {dissect_unknown, dissect_unknown},
+ /* 0x66 */ {dissect_unknown, dissect_unknown},
+ /* 0x67 */ {dissect_unknown, dissect_unknown},
+ /* 0x68 */ {dissect_unknown, dissect_unknown},
+ /* 0x69 */ {dissect_unknown, dissect_unknown},
+ /* 0x6a */ {dissect_unknown, dissect_unknown},
+ /* 0x6b */ {dissect_unknown, dissect_unknown},
+ /* 0x6c */ {dissect_unknown, dissect_unknown},
+ /* 0x6d */ {dissect_unknown, dissect_unknown},
+ /* 0x6e */ {dissect_unknown, dissect_unknown},
+ /* 0x6f */ {dissect_unknown, dissect_unknown},
+
+ /* 0x70 Tree Connect*/ {dissect_tree_connect_request, dissect_tree_connect_response},
+ /* 0x71 Tree Disconnect*/ {dissect_empty, dissect_empty},
+ /* 0x72 Negotiate Protocol*/ {dissect_negprot_request, dissect_negprot_response},
+ /* 0x73 Session Setup And X*/ {dissect_session_setup_andx_request, dissect_session_setup_andx_response},
+ /* 0x74 Logoff And X*/ {dissect_empty_andx, dissect_empty_andx},
+ /* 0x75 Tree Connect And X*/ {dissect_tree_connect_andx_request, dissect_tree_connect_andx_response},
+ /* 0x76 */ {dissect_unknown, dissect_unknown},
+ /* 0x77 */ {dissect_unknown, dissect_unknown},
+ /* 0x78 */ {dissect_unknown, dissect_unknown},
+ /* 0x79 */ {dissect_unknown, dissect_unknown},
+ /* 0x7a */ {dissect_unknown, dissect_unknown},
+ /* 0x7b */ {dissect_unknown, dissect_unknown},
+ /* 0x7c */ {dissect_unknown, dissect_unknown},
+ /* 0x7d */ {dissect_unknown, dissect_unknown},
+ /* 0x7e */ {dissect_unknown, dissect_unknown},
+ /* 0x7f */ {dissect_unknown, dissect_unknown},
+
+ /* 0x80 Query Info Disk*/ {dissect_empty, dissect_query_information_disk_response},
+ /* 0x81 Search Dir*/ {dissect_search_dir_request, dissect_search_dir_response},
+ /* 0x82 Find*/ {dissect_find_request, dissect_find_response},
+ /* 0x83 Find Unique*/ {dissect_find_request, dissect_find_response},
+ /* 0x84 Find Close*/ {dissect_find_close_request, dissect_find_close_response},
+ /* 0x85 */ {dissect_unknown, dissect_unknown},
+ /* 0x86 */ {dissect_unknown, dissect_unknown},
+ /* 0x87 */ {dissect_unknown, dissect_unknown},
+ /* 0x88 */ {dissect_unknown, dissect_unknown},
+ /* 0x89 */ {dissect_unknown, dissect_unknown},
+ /* 0x8a */ {dissect_unknown, dissect_unknown},
+ /* 0x8b */ {dissect_unknown, dissect_unknown},
+ /* 0x8c */ {dissect_unknown, dissect_unknown},
+ /* 0x8d */ {dissect_unknown, dissect_unknown},
+ /* 0x8e */ {dissect_unknown, dissect_unknown},
+ /* 0x8f */ {dissect_unknown, dissect_unknown},
+
+ /* 0x90 */ {dissect_unknown, dissect_unknown},
+ /* 0x91 */ {dissect_unknown, dissect_unknown},
+ /* 0x92 */ {dissect_unknown, dissect_unknown},
+ /* 0x93 */ {dissect_unknown, dissect_unknown},
+ /* 0x94 */ {dissect_unknown, dissect_unknown},
+ /* 0x95 */ {dissect_unknown, dissect_unknown},
+ /* 0x96 */ {dissect_unknown, dissect_unknown},
+ /* 0x97 */ {dissect_unknown, dissect_unknown},
+ /* 0x98 */ {dissect_unknown, dissect_unknown},
+ /* 0x99 */ {dissect_unknown, dissect_unknown},
+ /* 0x9a */ {dissect_unknown, dissect_unknown},
+ /* 0x9b */ {dissect_unknown, dissect_unknown},
+ /* 0x9c */ {dissect_unknown, dissect_unknown},
+ /* 0x9d */ {dissect_unknown, dissect_unknown},
+ /* 0x9e */ {dissect_unknown, dissect_unknown},
+ /* 0x9f */ {dissect_unknown, dissect_unknown},
+
+ /* 0xa0 NT Transaction*/ {dissect_nt_transaction_request, dissect_nt_transaction_response},
+ /* 0xa1 NT Trans secondary*/ {dissect_nt_transaction_request, dissect_nt_transaction_response},
+ /* 0xa2 NT CreateAndX*/ {dissect_nt_create_andx_request, dissect_nt_create_andx_response},
+ /* 0xa3 */ {dissect_unknown, dissect_unknown},
+ /* 0xa4 NT Cancel*/ {dissect_nt_cancel_request, dissect_unknown}, /*no response to this one*/
+ /* 0xa5 NT Rename*/ {dissect_nt_rename_file_request, dissect_empty},
+ /* 0xa6 */ {dissect_unknown, dissect_unknown},
+ /* 0xa7 */ {dissect_unknown, dissect_unknown},
+ /* 0xa8 */ {dissect_unknown, dissect_unknown},
+ /* 0xa9 */ {dissect_unknown, dissect_unknown},
+ /* 0xaa */ {dissect_unknown, dissect_unknown},
+ /* 0xab */ {dissect_unknown, dissect_unknown},
+ /* 0xac */ {dissect_unknown, dissect_unknown},
+ /* 0xad */ {dissect_unknown, dissect_unknown},
+ /* 0xae */ {dissect_unknown, dissect_unknown},
+ /* 0xaf */ {dissect_unknown, dissect_unknown},
+
+ /* 0xb0 */ {dissect_unknown, dissect_unknown},
+ /* 0xb1 */ {dissect_unknown, dissect_unknown},
+ /* 0xb2 */ {dissect_unknown, dissect_unknown},
+ /* 0xb3 */ {dissect_unknown, dissect_unknown},
+ /* 0xb4 */ {dissect_unknown, dissect_unknown},
+ /* 0xb5 */ {dissect_unknown, dissect_unknown},
+ /* 0xb6 */ {dissect_unknown, dissect_unknown},
+ /* 0xb7 */ {dissect_unknown, dissect_unknown},
+ /* 0xb8 */ {dissect_unknown, dissect_unknown},
+ /* 0xb9 */ {dissect_unknown, dissect_unknown},
+ /* 0xba */ {dissect_unknown, dissect_unknown},
+ /* 0xbb */ {dissect_unknown, dissect_unknown},
+ /* 0xbc */ {dissect_unknown, dissect_unknown},
+ /* 0xbd */ {dissect_unknown, dissect_unknown},
+ /* 0xbe */ {dissect_unknown, dissect_unknown},
+ /* 0xbf */ {dissect_unknown, dissect_unknown},
+
+ /* 0xc0 Open Print File*/ {dissect_open_print_file_request, dissect_fid},
+ /* 0xc1 Write Print File*/ {dissect_write_print_file_request, dissect_empty},
+ /* 0xc2 Close Print File*/ {dissect_fid, dissect_empty},
+ /* 0xc3 Get Print Queue*/ {dissect_get_print_queue_request, dissect_get_print_queue_response},
+ /* 0xc4 */ {dissect_unknown, dissect_unknown},
+ /* 0xc5 */ {dissect_unknown, dissect_unknown},
+ /* 0xc6 */ {dissect_unknown, dissect_unknown},
+ /* 0xc7 */ {dissect_unknown, dissect_unknown},
+ /* 0xc8 */ {dissect_unknown, dissect_unknown},
+ /* 0xc9 */ {dissect_unknown, dissect_unknown},
+ /* 0xca */ {dissect_unknown, dissect_unknown},
+ /* 0xcb */ {dissect_unknown, dissect_unknown},
+ /* 0xcc */ {dissect_unknown, dissect_unknown},
+ /* 0xcd */ {dissect_unknown, dissect_unknown},
+ /* 0xce */ {dissect_unknown, dissect_unknown},
+ /* 0xcf */ {dissect_unknown, dissect_unknown},
+
+ /* 0xd0 Send Single Block Message*/ {dissect_send_single_block_message_request, dissect_empty},
+ /* 0xd1 Send Broadcast Message*/ {dissect_send_single_block_message_request, dissect_empty},
+ /* 0xd2 Forward User Name*/ {dissect_forwarded_name, dissect_empty},
+ /* 0xd3 Cancel Forward*/ {dissect_forwarded_name, dissect_empty},
+ /* 0xd4 Get Machine Name*/ {dissect_empty, dissect_get_machine_name_response},
+ /* 0xd5 Send Start of Multi-block Message*/ {dissect_send_multi_block_message_start_request, dissect_message_group_id},
+ /* 0xd6 Send End of Multi-block Message*/ {dissect_message_group_id, dissect_empty},
+ /* 0xd7 Send Text of Multi-block Message*/ {dissect_send_multi_block_message_text_request, dissect_empty},
+ /* 0xd8 SMBreadbulk*/ {dissect_unknown, dissect_unknown},
+ /* 0xd9 SMBwritebulk*/ {dissect_unknown, dissect_unknown},
+ /* 0xda SMBwritebulkdata*/ {dissect_unknown, dissect_unknown},
+ /* 0xdb */ {dissect_unknown, dissect_unknown},
+ /* 0xdc */ {dissect_unknown, dissect_unknown},
+ /* 0xdd */ {dissect_unknown, dissect_unknown},
+ /* 0xde */ {dissect_unknown, dissect_unknown},
+ /* 0xdf */ {dissect_unknown, dissect_unknown},
+
+ /* 0xe0 */ {dissect_unknown, dissect_unknown},
+ /* 0xe1 */ {dissect_unknown, dissect_unknown},
+ /* 0xe2 */ {dissect_unknown, dissect_unknown},
+ /* 0xe3 */ {dissect_unknown, dissect_unknown},
+ /* 0xe4 */ {dissect_unknown, dissect_unknown},
+ /* 0xe5 */ {dissect_unknown, dissect_unknown},
+ /* 0xe6 */ {dissect_unknown, dissect_unknown},
+ /* 0xe7 */ {dissect_unknown, dissect_unknown},
+ /* 0xe8 */ {dissect_unknown, dissect_unknown},
+ /* 0xe9 */ {dissect_unknown, dissect_unknown},
+ /* 0xea */ {dissect_unknown, dissect_unknown},
+ /* 0xeb */ {dissect_unknown, dissect_unknown},
+ /* 0xec */ {dissect_unknown, dissect_unknown},
+ /* 0xed */ {dissect_unknown, dissect_unknown},
+ /* 0xee */ {dissect_unknown, dissect_unknown},
+ /* 0xef */ {dissect_unknown, dissect_unknown},
+
+ /* 0xf0 */ {dissect_unknown, dissect_unknown},
+ /* 0xf1 */ {dissect_unknown, dissect_unknown},
+ /* 0xf2 */ {dissect_unknown, dissect_unknown},
+ /* 0xf3 */ {dissect_unknown, dissect_unknown},
+ /* 0xf4 */ {dissect_unknown, dissect_unknown},
+ /* 0xf5 */ {dissect_unknown, dissect_unknown},
+ /* 0xf6 */ {dissect_unknown, dissect_unknown},
+ /* 0xf7 */ {dissect_unknown, dissect_unknown},
+ /* 0xf8 */ {dissect_unknown, dissect_unknown},
+ /* 0xf9 */ {dissect_unknown, dissect_unknown},
+ /* 0xfa */ {dissect_unknown, dissect_unknown},
+ /* 0xfb */ {dissect_unknown, dissect_unknown},
+ /* 0xfc */ {dissect_unknown, dissect_unknown},
+ /* 0xfd */ {dissect_unknown, dissect_unknown},
+ /* 0xfe */ {dissect_unknown, dissect_unknown},
+ /* 0xff */ {dissect_unknown, dissect_unknown},
+};
+
+static int
+dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *smb_tree, guint8 cmd, gboolean first_pdu)
+{
+ smb_info_t *si;
+
+ si = pinfo->private_data;
+ if(cmd!=0xff){
+ proto_item *cmd_item;
+ proto_tree *cmd_tree;
+ int (*dissector)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if(first_pdu){
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "%s %s",
+ decode_smb_name(cmd),
+ (si->request)? "Request" : "Response");
+ } else {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "; %s",
+ decode_smb_name(cmd));
+ }
+
+ }
+
+ cmd_item = proto_tree_add_text(smb_tree, tvb, offset, -1,
+ "%s %s (0x%02x)",
+ decode_smb_name(cmd),
+ (si->request)?"Request":"Response",
+ cmd);
+
+ cmd_tree = proto_item_add_subtree(cmd_item, ett_smb_command);
+
+ dissector = (si->request)?
+ smb_dissector[cmd].request:smb_dissector[cmd].response;
+
+ offset = (*dissector)(tvb, pinfo, cmd_tree, offset, smb_tree);
+ proto_item_set_end(cmd_item, tvb, offset);
+ }
+ return offset;
+}
+
+
+/* NOTE: this value_string array will also be used to access data directly by
+ * index instead of val_to_str() since
+ * 1, the array will always span every value from 0x00 to 0xff and
+ * 2, smb_cmd_vals[i].strptr is much cheaper than val_to_str(i, smb_cmd_vals,)
+ * This means that this value_string array MUST always
+ * 1, contain all entries 0x00 to 0xff
+ * 2, all entries must be in order.
+ */
+const value_string smb_cmd_vals[] = {
+ { 0x00, "Create Directory" },
+ { 0x01, "Delete Directory" },
+ { 0x02, "Open" },
+ { 0x03, "Create" },
+ { 0x04, "Close" },
+ { 0x05, "Flush" },
+ { 0x06, "Delete" },
+ { 0x07, "Rename" },
+ { 0x08, "Query Information" },
+ { 0x09, "Set Information" },
+ { 0x0A, "Read" },
+ { 0x0B, "Write" },
+ { 0x0C, "Lock Byte Range" },
+ { 0x0D, "Unlock Byte Range" },
+ { 0x0E, "Create Temp" },
+ { 0x0F, "Create New" },
+ { 0x10, "Check Directory" },
+ { 0x11, "Process Exit" },
+ { 0x12, "Seek" },
+ { 0x13, "Lock And Read" },
+ { 0x14, "Write And Unlock" },
+ { 0x15, "unknown-0x15" },
+ { 0x16, "unknown-0x16" },
+ { 0x17, "unknown-0x17" },
+ { 0x18, "unknown-0x18" },
+ { 0x19, "unknown-0x19" },
+ { 0x1A, "Read Raw" },
+ { 0x1B, "Read MPX" },
+ { 0x1C, "Read MPX Secondary" },
+ { 0x1D, "Write Raw" },
+ { 0x1E, "Write MPX" },
+ { 0x1F, "Write MPX Secondary" },
+ { 0x20, "Write Complete" },
+ { 0x21, "unknown-0x21" },
+ { 0x22, "Set Information2" },
+ { 0x23, "Query Information2" },
+ { 0x24, "Locking AndX" },
+ { 0x25, "Trans" },
+ { 0x26, "Trans Secondary" },
+ { 0x27, "IOCTL" },
+ { 0x28, "IOCTL Secondary" },
+ { 0x29, "Copy" },
+ { 0x2A, "Move" },
+ { 0x2B, "Echo" },
+ { 0x2C, "Write And Close" },
+ { 0x2D, "Open AndX" },
+ { 0x2E, "Read AndX" },
+ { 0x2F, "Write AndX" },
+ { 0x30, "unknown-0x30" },
+ { 0x31, "Close And Tree Disconnect" },
+ { 0x32, "Trans2" },
+ { 0x33, "Trans2 Secondary" },
+ { 0x34, "Find Close2" },
+ { 0x35, "Find Notify Close" },
+ { 0x36, "unknown-0x36" },
+ { 0x37, "unknown-0x37" },
+ { 0x38, "unknown-0x38" },
+ { 0x39, "unknown-0x39" },
+ { 0x3A, "unknown-0x3A" },
+ { 0x3B, "unknown-0x3B" },
+ { 0x3C, "unknown-0x3C" },
+ { 0x3D, "unknown-0x3D" },
+ { 0x3E, "unknown-0x3E" },
+ { 0x3F, "unknown-0x3F" },
+ { 0x40, "unknown-0x40" },
+ { 0x41, "unknown-0x41" },
+ { 0x42, "unknown-0x42" },
+ { 0x43, "unknown-0x43" },
+ { 0x44, "unknown-0x44" },
+ { 0x45, "unknown-0x45" },
+ { 0x46, "unknown-0x46" },
+ { 0x47, "unknown-0x47" },
+ { 0x48, "unknown-0x48" },
+ { 0x49, "unknown-0x49" },
+ { 0x4A, "unknown-0x4A" },
+ { 0x4B, "unknown-0x4B" },
+ { 0x4C, "unknown-0x4C" },
+ { 0x4D, "unknown-0x4D" },
+ { 0x4E, "unknown-0x4E" },
+ { 0x4F, "unknown-0x4F" },
+ { 0x50, "unknown-0x50" },
+ { 0x51, "unknown-0x51" },
+ { 0x52, "unknown-0x52" },
+ { 0x53, "unknown-0x53" },
+ { 0x54, "unknown-0x54" },
+ { 0x55, "unknown-0x55" },
+ { 0x56, "unknown-0x56" },
+ { 0x57, "unknown-0x57" },
+ { 0x58, "unknown-0x58" },
+ { 0x59, "unknown-0x59" },
+ { 0x5A, "unknown-0x5A" },
+ { 0x5B, "unknown-0x5B" },
+ { 0x5C, "unknown-0x5C" },
+ { 0x5D, "unknown-0x5D" },
+ { 0x5E, "unknown-0x5E" },
+ { 0x5F, "unknown-0x5F" },
+ { 0x60, "unknown-0x60" },
+ { 0x61, "unknown-0x61" },
+ { 0x62, "unknown-0x62" },
+ { 0x63, "unknown-0x63" },
+ { 0x64, "unknown-0x64" },
+ { 0x65, "unknown-0x65" },
+ { 0x66, "unknown-0x66" },
+ { 0x67, "unknown-0x67" },
+ { 0x68, "unknown-0x68" },
+ { 0x69, "unknown-0x69" },
+ { 0x6A, "unknown-0x6A" },
+ { 0x6B, "unknown-0x6B" },
+ { 0x6C, "unknown-0x6C" },
+ { 0x6D, "unknown-0x6D" },
+ { 0x6E, "unknown-0x6E" },
+ { 0x6F, "unknown-0x6F" },
+ { 0x70, "Tree Connect" },
+ { 0x71, "Tree Disconnect" },
+ { 0x72, "Negotiate Protocol" },
+ { 0x73, "Session Setup AndX" },
+ { 0x74, "Logoff AndX" },
+ { 0x75, "Tree Connect AndX" },
+ { 0x76, "unknown-0x76" },
+ { 0x77, "unknown-0x77" },
+ { 0x78, "unknown-0x78" },
+ { 0x79, "unknown-0x79" },
+ { 0x7A, "unknown-0x7A" },
+ { 0x7B, "unknown-0x7B" },
+ { 0x7C, "unknown-0x7C" },
+ { 0x7D, "unknown-0x7D" },
+ { 0x7E, "unknown-0x7E" },
+ { 0x7F, "unknown-0x7F" },
+ { 0x80, "Query Information Disk" },
+ { 0x81, "Search" },
+ { 0x82, "Find" },
+ { 0x83, "Find Unique" },
+ { 0x84, "Find Close" },
+ { 0x85, "unknown-0x85" },
+ { 0x86, "unknown-0x86" },
+ { 0x87, "unknown-0x87" },
+ { 0x88, "unknown-0x88" },
+ { 0x89, "unknown-0x89" },
+ { 0x8A, "unknown-0x8A" },
+ { 0x8B, "unknown-0x8B" },
+ { 0x8C, "unknown-0x8C" },
+ { 0x8D, "unknown-0x8D" },
+ { 0x8E, "unknown-0x8E" },
+ { 0x8F, "unknown-0x8F" },
+ { 0x90, "unknown-0x90" },
+ { 0x91, "unknown-0x91" },
+ { 0x92, "unknown-0x92" },
+ { 0x93, "unknown-0x93" },
+ { 0x94, "unknown-0x94" },
+ { 0x95, "unknown-0x95" },
+ { 0x96, "unknown-0x96" },
+ { 0x97, "unknown-0x97" },
+ { 0x98, "unknown-0x98" },
+ { 0x99, "unknown-0x99" },
+ { 0x9A, "unknown-0x9A" },
+ { 0x9B, "unknown-0x9B" },
+ { 0x9C, "unknown-0x9C" },
+ { 0x9D, "unknown-0x9D" },
+ { 0x9E, "unknown-0x9E" },
+ { 0x9F, "unknown-0x9F" },
+ { 0xA0, "NT Trans" },
+ { 0xA1, "NT Trans Secondary" },
+ { 0xA2, "NT Create AndX" },
+ { 0xA3, "unknown-0xA3" },
+ { 0xA4, "NT Cancel" },
+ { 0xA5, "NT Rename" },
+ { 0xA6, "unknown-0xA6" },
+ { 0xA7, "unknown-0xA7" },
+ { 0xA8, "unknown-0xA8" },
+ { 0xA9, "unknown-0xA9" },
+ { 0xAA, "unknown-0xAA" },
+ { 0xAB, "unknown-0xAB" },
+ { 0xAC, "unknown-0xAC" },
+ { 0xAD, "unknown-0xAD" },
+ { 0xAE, "unknown-0xAE" },
+ { 0xAF, "unknown-0xAF" },
+ { 0xB0, "unknown-0xB0" },
+ { 0xB1, "unknown-0xB1" },
+ { 0xB2, "unknown-0xB2" },
+ { 0xB3, "unknown-0xB3" },
+ { 0xB4, "unknown-0xB4" },
+ { 0xB5, "unknown-0xB5" },
+ { 0xB6, "unknown-0xB6" },
+ { 0xB7, "unknown-0xB7" },
+ { 0xB8, "unknown-0xB8" },
+ { 0xB9, "unknown-0xB9" },
+ { 0xBA, "unknown-0xBA" },
+ { 0xBB, "unknown-0xBB" },
+ { 0xBC, "unknown-0xBC" },
+ { 0xBD, "unknown-0xBD" },
+ { 0xBE, "unknown-0xBE" },
+ { 0xBF, "unknown-0xBF" },
+ { 0xC0, "Open Print File" },
+ { 0xC1, "Write Print File" },
+ { 0xC2, "Close Print File" },
+ { 0xC3, "Get Print Queue" },
+ { 0xC4, "unknown-0xC4" },
+ { 0xC5, "unknown-0xC5" },
+ { 0xC6, "unknown-0xC6" },
+ { 0xC7, "unknown-0xC7" },
+ { 0xC8, "unknown-0xC8" },
+ { 0xC9, "unknown-0xC9" },
+ { 0xCA, "unknown-0xCA" },
+ { 0xCB, "unknown-0xCB" },
+ { 0xCC, "unknown-0xCC" },
+ { 0xCD, "unknown-0xCD" },
+ { 0xCE, "unknown-0xCE" },
+ { 0xCF, "unknown-0xCF" },
+ { 0xD0, "Send Single Block Message" },
+ { 0xD1, "Send Broadcast Message" },
+ { 0xD2, "Forward User Name" },
+ { 0xD3, "Cancel Forward" },
+ { 0xD4, "Get Machine Name" },
+ { 0xD5, "Send Start of Multi-block Message" },
+ { 0xD6, "Send End of Multi-block Message" },
+ { 0xD7, "Send Text of Multi-block Message" },
+ { 0xD8, "SMBreadbulk" },
+ { 0xD9, "SMBwritebulk" },
+ { 0xDA, "SMBwritebulkdata" },
+ { 0xDB, "unknown-0xDB" },
+ { 0xDC, "unknown-0xDC" },
+ { 0xDD, "unknown-0xDD" },
+ { 0xDE, "unknown-0xDE" },
+ { 0xDF, "unknown-0xDF" },
+ { 0xE0, "unknown-0xE0" },
+ { 0xE1, "unknown-0xE1" },
+ { 0xE2, "unknown-0xE2" },
+ { 0xE3, "unknown-0xE3" },
+ { 0xE4, "unknown-0xE4" },
+ { 0xE5, "unknown-0xE5" },
+ { 0xE6, "unknown-0xE6" },
+ { 0xE7, "unknown-0xE7" },
+ { 0xE8, "unknown-0xE8" },
+ { 0xE9, "unknown-0xE9" },
+ { 0xEA, "unknown-0xEA" },
+ { 0xEB, "unknown-0xEB" },
+ { 0xEC, "unknown-0xEC" },
+ { 0xED, "unknown-0xED" },
+ { 0xEE, "unknown-0xEE" },
+ { 0xEF, "unknown-0xEF" },
+ { 0xF0, "unknown-0xF0" },
+ { 0xF1, "unknown-0xF1" },
+ { 0xF2, "unknown-0xF2" },
+ { 0xF3, "unknown-0xF3" },
+ { 0xF4, "unknown-0xF4" },
+ { 0xF5, "unknown-0xF5" },
+ { 0xF6, "unknown-0xF6" },
+ { 0xF7, "unknown-0xF7" },
+ { 0xF8, "unknown-0xF8" },
+ { 0xF9, "unknown-0xF9" },
+ { 0xFA, "unknown-0xFA" },
+ { 0xFB, "unknown-0xFB" },
+ { 0xFC, "unknown-0xFC" },
+ { 0xFD, "unknown-0xFD" },
+ { 0xFE, "SMBinvalid" },
+ { 0xFF, "unknown-0xFF" },
+ { 0x00, NULL },
+};
+
+static char *decode_smb_name(guint8 cmd)
+{
+ return(smb_cmd_vals[cmd].strptr);
+}
+
+
+
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ * Everything TVBUFFIFIED above this line
+ * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+
+
+static void
+free_hash_tables(gpointer ctarg, gpointer user_data _U_)
+{
+ conv_tables_t *ct = ctarg;
+
+ if (ct->unmatched)
+ g_hash_table_destroy(ct->unmatched);
+ if (ct->matched)
+ g_hash_table_destroy(ct->matched);
+ if (ct->tid_service)
+ g_hash_table_destroy(ct->tid_service);
+}
+
+static void
+smb_init_protocol(void)
+{
+ if (smb_saved_info_key_chunk)
+ g_mem_chunk_destroy(smb_saved_info_key_chunk);
+ if (smb_saved_info_chunk)
+ g_mem_chunk_destroy(smb_saved_info_chunk);
+ if (smb_nt_transact_info_chunk)
+ g_mem_chunk_destroy(smb_nt_transact_info_chunk);
+ if (smb_transact2_info_chunk)
+ g_mem_chunk_destroy(smb_transact2_info_chunk);
+ if (smb_transact_info_chunk)
+ g_mem_chunk_destroy(smb_transact_info_chunk);
+
+ /*
+ * Free the hash tables attached to the conversation table
+ * structures, and then free the list of conversation table
+ * data structures (which doesn't free the data structures
+ * themselves; that's done by destroying the chunk from
+ * which they were allocated).
+ */
+ if (conv_tables) {
+ g_slist_foreach(conv_tables, free_hash_tables, NULL);
+ g_slist_free(conv_tables);
+ conv_tables = NULL;
+ }
+
+ /*
+ * Now destroy the chunk from which the conversation table
+ * structures were allocated.
+ */
+ if (conv_tables_chunk)
+ g_mem_chunk_destroy(conv_tables_chunk);
+
+ smb_saved_info_chunk = g_mem_chunk_new("smb_saved_info_chunk",
+ sizeof(smb_saved_info_t),
+ smb_saved_info_init_count * sizeof(smb_saved_info_t),
+ G_ALLOC_ONLY);
+ smb_saved_info_key_chunk = g_mem_chunk_new("smb_saved_info_key_chunk",
+ sizeof(smb_saved_info_key_t),
+ smb_saved_info_init_count * sizeof(smb_saved_info_key_t),
+ G_ALLOC_ONLY);
+ smb_nt_transact_info_chunk = g_mem_chunk_new("smb_nt_transact_info_chunk",
+ sizeof(smb_nt_transact_info_t),
+ smb_nt_transact_info_init_count * sizeof(smb_nt_transact_info_t),
+ G_ALLOC_ONLY);
+ smb_transact2_info_chunk = g_mem_chunk_new("smb_transact2_info_chunk",
+ sizeof(smb_transact2_info_t),
+ smb_transact2_info_init_count * sizeof(smb_transact2_info_t),
+ G_ALLOC_ONLY);
+ smb_transact_info_chunk = g_mem_chunk_new("smb_transact_info_chunk",
+ sizeof(smb_transact_info_t),
+ smb_transact_info_init_count * sizeof(smb_transact_info_t),
+ G_ALLOC_ONLY);
+ conv_tables_chunk = g_mem_chunk_new("conv_tables_chunk",
+ sizeof(conv_tables_t),
+ conv_tables_count * sizeof(conv_tables_t),
+ G_ALLOC_ONLY);
+}
+
+static const value_string errcls_types[] = {
+ { SMB_SUCCESS, "Success"},
+ { SMB_ERRDOS, "DOS Error"},
+ { SMB_ERRSRV, "Server Error"},
+ { SMB_ERRHRD, "Hardware Error"},
+ { SMB_ERRCMD, "Command Error - Not an SMB format command"},
+ { 0, NULL }
+};
+
+const value_string DOS_errors[] = {
+ {0, "Success"},
+ {SMBE_insufficientbuffer, "Insufficient buffer"},
+ {SMBE_badfunc, "Invalid function (or system call)"},
+ {SMBE_badfile, "File not found (pathname error)"},
+ {SMBE_badpath, "Directory not found"},
+ {SMBE_nofids, "Too many open files"},
+ {SMBE_noaccess, "Access denied"},
+ {SMBE_badfid, "Invalid fid"},
+ {SMBE_nomem, "Out of memory"},
+ {SMBE_badmem, "Invalid memory block address"},
+ {SMBE_badenv, "Invalid environment"},
+ {SMBE_badaccess, "Invalid open mode"},
+ {SMBE_baddata, "Invalid data (only from ioctl call)"},
+ {SMBE_res, "Reserved error code?"},
+ {SMBE_baddrive, "Invalid drive"},
+ {SMBE_remcd, "Attempt to delete current directory"},
+ {SMBE_diffdevice, "Rename/move across different filesystems"},
+ {SMBE_nofiles, "No more files found in file search"},
+ {SMBE_badshare, "Share mode on file conflict with open mode"},
+ {SMBE_lock, "Lock request conflicts with existing lock"},
+ {SMBE_unsup, "Request unsupported, returned by Win 95"},
+ {SMBE_nosuchshare, "Requested share does not exist"},
+ {SMBE_filexists, "File in operation already exists"},
+ {SMBE_cannotopen, "Cannot open the file specified"},
+ {SMBE_unknownlevel, "Unknown info level"},
+ {SMBE_invalidname, "Invalid name"},
+ {SMBE_badpipe, "Named pipe invalid"},
+ {SMBE_pipebusy, "All instances of pipe are busy"},
+ {SMBE_pipeclosing, "Named pipe close in progress"},
+ {SMBE_notconnected, "No process on other end of named pipe"},
+ {SMBE_moredata, "More data to be returned"},
+ {SMBE_baddirectory, "Invalid directory name in a path."},
+ {SMBE_eas_didnt_fit, "Extended attributes didn't fit"},
+ {SMBE_eas_nsup, "Extended attributes not supported"},
+ {SMBE_notify_buf_small, "Buffer too small to return change notify."},
+ {SMBE_unknownipc, "Unknown IPC Operation"},
+ {SMBE_noipc, "Don't support ipc"},
+ {SMBE_alreadyexists, "File already exists"},
+ {SMBE_unknownprinterdriver, "Unknown printer driver"},
+ {SMBE_invalidprintername, "Invalid printer name"},
+ {SMBE_printeralreadyexists, "Printer already exists"},
+ {SMBE_invaliddatatype, "Invalid data type"},
+ {SMBE_invalidenvironment, "Invalid environment"},
+ {SMBE_printerdriverinuse, "Printer driver in use"},
+ {SMBE_invalidparam, "Invalid parameter"},
+ {SMBE_invalidformsize, "Invalid form size"},
+ {SMBE_invalidsecuritydescriptor, "Invalid security descriptor"},
+ {SMBE_invalidowner, "Invalid owner"},
+ {SMBE_nomoreitems, "No more items"},
+ {SMBE_serverunavailable, "Server unavailable"},
+ {0, NULL}
+ };
+
+/* Error codes for the ERRSRV class */
+
+static const value_string SRV_errors[] = {
+ {SMBE_error, "Non specific error code"},
+ {SMBE_badpw, "Bad password"},
+ {SMBE_badtype, "Reserved"},
+ {SMBE_access, "No permissions to perform the requested operation"},
+ {SMBE_invnid, "TID invalid"},
+ {SMBE_invnetname, "Invalid network name. Service not found"},
+ {SMBE_invdevice, "Invalid device"},
+ {SMBE_unknownsmb, "Unknown SMB, from NT 3.5 response"},
+ {SMBE_qfull, "Print queue full"},
+ {SMBE_qtoobig, "Queued item too big"},
+ {SMBE_qeof, "EOF on print queue dump"},
+ {SMBE_invpfid, "Invalid print file in smb_fid"},
+ {SMBE_smbcmd, "Unrecognised command"},
+ {SMBE_srverror, "SMB server internal error"},
+ {SMBE_filespecs, "Fid and pathname invalid combination"},
+ {SMBE_badlink, "Bad link in request ???"},
+ {SMBE_badpermits, "Access specified for a file is not valid"},
+ {SMBE_badpid, "Bad process id in request"},
+ {SMBE_setattrmode, "Attribute mode invalid"},
+ {SMBE_paused, "Message server paused"},
+ {SMBE_msgoff, "Not receiving messages"},
+ {SMBE_noroom, "No room for message"},
+ {SMBE_rmuns, "Too many remote usernames"},
+ {SMBE_timeout, "Operation timed out"},
+ {SMBE_noresource, "No resources currently available for request."},
+ {SMBE_toomanyuids, "Too many userids"},
+ {SMBE_baduid, "Bad userid"},
+ {SMBE_useMPX, "Temporarily unable to use raw mode, use MPX mode"},
+ {SMBE_useSTD, "Temporarily unable to use raw mode, use standard mode"},
+ {SMBE_contMPX, "Resume MPX mode"},
+ {SMBE_badPW, "Bad Password???"},
+ {SMBE_nosupport, "Operation not supported"},
+ { 0, NULL}
+};
+
+/* Error codes for the ERRHRD class */
+
+static const value_string HRD_errors[] = {
+ {SMBE_nowrite, "Read only media"},
+ {SMBE_badunit, "Unknown device"},
+ {SMBE_notready, "Drive not ready"},
+ {SMBE_badcmd, "Unknown command"},
+ {SMBE_data, "Data (CRC) error"},
+ {SMBE_badreq, "Bad request structure length"},
+ {SMBE_seek, "Seek error"},
+ {SMBE_badmedia, "Unknown media type"},
+ {SMBE_badsector, "Sector not found"},
+ {SMBE_nopaper, "Printer out of paper"},
+ {SMBE_write, "Write fault"},
+ {SMBE_read, "Read fault"},
+ {SMBE_general, "General failure"},
+ {SMBE_badshare, "A open conflicts with an existing open"},
+ {SMBE_lock, "Lock conflict/invalid mode, or unlock of another process's lock"},
+ {SMBE_wrongdisk, "The wrong disk was found in a drive"},
+ {SMBE_FCBunavail, "No FCBs are available to process request"},
+ {SMBE_sharebufexc, "A sharing buffer has been exceeded"},
+ {SMBE_diskfull, "Disk full???"},
+ {0, NULL}
+};
+
+static char *decode_smb_error(guint8 errcls, guint16 errcode)
+{
+
+ switch (errcls) {
+
+ case SMB_SUCCESS:
+
+ return("No Error"); /* No error ??? */
+ break;
+
+ case SMB_ERRDOS:
+
+ return(val_to_str(errcode, DOS_errors, "Unknown DOS error (%x)"));
+ break;
+
+ case SMB_ERRSRV:
+
+ return(val_to_str(errcode, SRV_errors, "Unknown SRV error (%x)"));
+ break;
+
+ case SMB_ERRHRD:
+
+ return(val_to_str(errcode, HRD_errors, "Unknown HRD error (%x)"));
+ break;
+
+ default:
+
+ return("Unknown error class!");
+
+ }
+
+}
+
+
+/* These are the MS country codes from
+
+ http://www.unicode.org/unicode/onlinedat/countries.html
+
+ For countries that share the same number, I choose to use only the
+ name of the largest country. Apologies for this. If this offends you,
+ here is the table to change that.
+
+ This also includes the code of 0 for "Default", which isn't in
+ that list, but is in Microsoft's SDKs and the Cygnus "winnls.h"
+ header file. Presumably it means "don't override the setting
+ on the user's machine".
+
+ Future versions of Microsoft's "winnls.h" header file might include
+ additional codes; the current version matches the Unicode Consortium's
+ table.
+*/
+const value_string ms_country_codes[] = {
+ { 0, "Default"},
+ { 1, "USA"},
+ { 2, "Canada"},
+ { 7, "Russia"},
+ { 20, "Egypt"},
+ { 27, "South Africa"},
+ { 30, "Greece"},
+ { 31, "Netherlands"},
+ { 32, "Belgium"},
+ { 33, "France"},
+ { 34, "Spain"},
+ { 36, "Hungary"},
+ { 39, "Italy"},
+ { 40, "Romania"},
+ { 41, "Switzerland"},
+ { 43, "Austria"},
+ { 44, "United Kingdom"},
+ { 45, "Denmark"},
+ { 46, "Sweden"},
+ { 47, "Norway"},
+ { 48, "Poland"},
+ { 49, "Germany"},
+ { 51, "Peru"},
+ { 52, "Mexico"},
+ { 54, "Argentina"},
+ { 55, "Brazil"},
+ { 56, "Chile"},
+ { 57, "Colombia"},
+ { 58, "Venezuela"},
+ { 60, "Malaysia"},
+ { 61, "Australia"},
+ { 62, "Indonesia"},
+ { 63, "Philippines"},
+ { 64, "New Zealand"},
+ { 65, "Singapore"},
+ { 66, "Thailand"},
+ { 81, "Japan"},
+ { 82, "South Korea"},
+ { 84, "Viet Nam"},
+ { 86, "China"},
+ { 90, "Turkey"},
+ { 91, "India"},
+ { 92, "Pakistan"},
+ {212, "Morocco"},
+ {213, "Algeria"},
+ {216, "Tunisia"},
+ {218, "Libya"},
+ {254, "Kenya"},
+ {263, "Zimbabwe"},
+ {298, "Faroe Islands"},
+ {351, "Portugal"},
+ {352, "Luxembourg"},
+ {353, "Ireland"},
+ {354, "Iceland"},
+ {355, "Albania"},
+ {358, "Finland"},
+ {359, "Bulgaria"},
+ {370, "Lithuania"},
+ {371, "Latvia"},
+ {372, "Estonia"},
+ {374, "Armenia"},
+ {375, "Belarus"},
+ {380, "Ukraine"},
+ {381, "Serbia"},
+ {385, "Croatia"},
+ {386, "Slovenia"},
+ {389, "Macedonia"},
+ {420, "Czech Republic"},
+ {421, "Slovak Republic"},
+ {501, "Belize"},
+ {502, "Guatemala"},
+ {503, "El Salvador"},
+ {504, "Honduras"},
+ {505, "Nicaragua"},
+ {506, "Costa Rica"},
+ {507, "Panama"},
+ {591, "Bolivia"},
+ {593, "Ecuador"},
+ {595, "Paraguay"},
+ {598, "Uruguay"},
+ {673, "Brunei Darussalam"},
+ {852, "Hong Kong"},
+ {853, "Macau"},
+ {886, "Taiwan"},
+ {960, "Maldives"},
+ {961, "Lebanon"},
+ {962, "Jordan"},
+ {963, "Syria"},
+ {964, "Iraq"},
+ {965, "Kuwait"},
+ {966, "Saudi Arabia"},
+ {967, "Yemen"},
+ {968, "Oman"},
+ {971, "United Arab Emirates"},
+ {972, "Israel"},
+ {973, "Bahrain"},
+ {974, "Qatar"},
+ {976, "Mongolia"},
+ {981, "Iran"},
+ {994, "Azerbaijan"},
+ {995, "Georgia"},
+ {996, "Kyrgyzstan"},
+
+ {0, NULL}
+};
+
+/*
+ * NT error codes.
+ *
+ * From
+ *
+ * http://www.wildpackets.com/elements/SMB_NT_Status_Codes.txt
+ */
+const value_string NT_errors[] = {
+ { 0x00000000, "STATUS_SUCCESS" },
+ { 0x00000000, "STATUS_WAIT_0" },
+ { 0x00000001, "STATUS_WAIT_1" },
+ { 0x00000002, "STATUS_WAIT_2" },
+ { 0x00000003, "STATUS_WAIT_3" },
+ { 0x0000003F, "STATUS_WAIT_63" },
+ { 0x00000080, "STATUS_ABANDONED" },
+ { 0x00000080, "STATUS_ABANDONED_WAIT_0" },
+ { 0x000000BF, "STATUS_ABANDONED_WAIT_63" },
+ { 0x000000C0, "STATUS_USER_APC" },
+ { 0x00000100, "STATUS_KERNEL_APC" },
+ { 0x00000101, "STATUS_ALERTED" },
+ { 0x00000102, "STATUS_TIMEOUT" },
+ { 0x00000103, "STATUS_PENDING" },
+ { 0x00000104, "STATUS_REPARSE" },
+ { 0x00000105, "STATUS_MORE_ENTRIES" },
+ { 0x00000106, "STATUS_NOT_ALL_ASSIGNED" },
+ { 0x00000107, "STATUS_SOME_NOT_MAPPED" },
+ { 0x00000108, "STATUS_OPLOCK_BREAK_IN_PROGRESS" },
+ { 0x00000109, "STATUS_VOLUME_MOUNTED" },
+ { 0x0000010A, "STATUS_RXACT_COMMITTED" },
+ { 0x0000010B, "STATUS_NOTIFY_CLEANUP" },
+ { 0x0000010C, "STATUS_NOTIFY_ENUM_DIR" },
+ { 0x0000010D, "STATUS_NO_QUOTAS_FOR_ACCOUNT" },
+ { 0x0000010E, "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED" },
+ { 0x00000110, "STATUS_PAGE_FAULT_TRANSITION" },
+ { 0x00000111, "STATUS_PAGE_FAULT_DEMAND_ZERO" },
+ { 0x00000112, "STATUS_PAGE_FAULT_COPY_ON_WRITE" },
+ { 0x00000113, "STATUS_PAGE_FAULT_GUARD_PAGE" },
+ { 0x00000114, "STATUS_PAGE_FAULT_PAGING_FILE" },
+ { 0x00000115, "STATUS_CACHE_PAGE_LOCKED" },
+ { 0x00000116, "STATUS_CRASH_DUMP" },
+ { 0x00000117, "STATUS_BUFFER_ALL_ZEROS" },
+ { 0x00000118, "STATUS_REPARSE_OBJECT" },
+ { 0x0000045C, "STATUS_NO_SHUTDOWN_IN_PROGRESS" },
+ { 0x40000000, "STATUS_OBJECT_NAME_EXISTS" },
+ { 0x40000001, "STATUS_THREAD_WAS_SUSPENDED" },
+ { 0x40000002, "STATUS_WORKING_SET_LIMIT_RANGE" },
+ { 0x40000003, "STATUS_IMAGE_NOT_AT_BASE" },
+ { 0x40000004, "STATUS_RXACT_STATE_CREATED" },
+ { 0x40000005, "STATUS_SEGMENT_NOTIFICATION" },
+ { 0x40000006, "STATUS_LOCAL_USER_SESSION_KEY" },
+ { 0x40000007, "STATUS_BAD_CURRENT_DIRECTORY" },
+ { 0x40000008, "STATUS_SERIAL_MORE_WRITES" },
+ { 0x40000009, "STATUS_REGISTRY_RECOVERED" },
+ { 0x4000000A, "STATUS_FT_READ_RECOVERY_FROM_BACKUP" },
+ { 0x4000000B, "STATUS_FT_WRITE_RECOVERY" },
+ { 0x4000000C, "STATUS_SERIAL_COUNTER_TIMEOUT" },
+ { 0x4000000D, "STATUS_NULL_LM_PASSWORD" },
+ { 0x4000000E, "STATUS_IMAGE_MACHINE_TYPE_MISMATCH" },
+ { 0x4000000F, "STATUS_RECEIVE_PARTIAL" },
+ { 0x40000010, "STATUS_RECEIVE_EXPEDITED" },
+ { 0x40000011, "STATUS_RECEIVE_PARTIAL_EXPEDITED" },
+ { 0x40000012, "STATUS_EVENT_DONE" },
+ { 0x40000013, "STATUS_EVENT_PENDING" },
+ { 0x40000014, "STATUS_CHECKING_FILE_SYSTEM" },
+ { 0x40000015, "STATUS_FATAL_APP_EXIT" },
+ { 0x40000016, "STATUS_PREDEFINED_HANDLE" },
+ { 0x40000017, "STATUS_WAS_UNLOCKED" },
+ { 0x40000018, "STATUS_SERVICE_NOTIFICATION" },
+ { 0x40000019, "STATUS_WAS_LOCKED" },
+ { 0x4000001A, "STATUS_LOG_HARD_ERROR" },
+ { 0x4000001B, "STATUS_ALREADY_WIN32" },
+ { 0x4000001C, "STATUS_WX86_UNSIMULATE" },
+ { 0x4000001D, "STATUS_WX86_CONTINUE" },
+ { 0x4000001E, "STATUS_WX86_SINGLE_STEP" },
+ { 0x4000001F, "STATUS_WX86_BREAKPOINT" },
+ { 0x40000020, "STATUS_WX86_EXCEPTION_CONTINUE" },
+ { 0x40000021, "STATUS_WX86_EXCEPTION_LASTCHANCE" },
+ { 0x40000022, "STATUS_WX86_EXCEPTION_CHAIN" },
+ { 0x40000023, "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE" },
+ { 0x40000024, "STATUS_NO_YIELD_PERFORMED" },
+ { 0x40000025, "STATUS_TIMER_RESUME_IGNORED" },
+ { 0x80000001, "STATUS_GUARD_PAGE_VIOLATION" },
+ { 0x80000002, "STATUS_DATATYPE_MISALIGNMENT" },
+ { 0x80000003, "STATUS_BREAKPOINT" },
+ { 0x80000004, "STATUS_SINGLE_STEP" },
+ { 0x80000005, "STATUS_BUFFER_OVERFLOW" },
+ { 0x80000006, "STATUS_NO_MORE_FILES" },
+ { 0x80000007, "STATUS_WAKE_SYSTEM_DEBUGGER" },
+ { 0x8000000A, "STATUS_HANDLES_CLOSED" },
+ { 0x8000000B, "STATUS_NO_INHERITANCE" },
+ { 0x8000000C, "STATUS_GUID_SUBSTITUTION_MADE" },
+ { 0x8000000D, "STATUS_PARTIAL_COPY" },
+ { 0x8000000E, "STATUS_DEVICE_PAPER_EMPTY" },
+ { 0x8000000F, "STATUS_DEVICE_POWERED_OFF" },
+ { 0x80000010, "STATUS_DEVICE_OFF_LINE" },
+ { 0x80000011, "STATUS_DEVICE_BUSY" },
+ { 0x80000012, "STATUS_NO_MORE_EAS" },
+ { 0x80000013, "STATUS_INVALID_EA_NAME" },
+ { 0x80000014, "STATUS_EA_LIST_INCONSISTENT" },
+ { 0x80000015, "STATUS_INVALID_EA_FLAG" },
+ { 0x80000016, "STATUS_VERIFY_REQUIRED" },
+ { 0x80000017, "STATUS_EXTRANEOUS_INFORMATION" },
+ { 0x80000018, "STATUS_RXACT_COMMIT_NECESSARY" },
+ { 0x8000001A, "STATUS_NO_MORE_ENTRIES" },
+ { 0x8000001B, "STATUS_FILEMARK_DETECTED" },
+ { 0x8000001C, "STATUS_MEDIA_CHANGED" },
+ { 0x8000001D, "STATUS_BUS_RESET" },
+ { 0x8000001E, "STATUS_END_OF_MEDIA" },
+ { 0x8000001F, "STATUS_BEGINNING_OF_MEDIA" },
+ { 0x80000020, "STATUS_MEDIA_CHECK" },
+ { 0x80000021, "STATUS_SETMARK_DETECTED" },
+ { 0x80000022, "STATUS_NO_DATA_DETECTED" },
+ { 0x80000023, "STATUS_REDIRECTOR_HAS_OPEN_HANDLES" },
+ { 0x80000024, "STATUS_SERVER_HAS_OPEN_HANDLES" },
+ { 0x80000025, "STATUS_ALREADY_DISCONNECTED" },
+ { 0x80000026, "STATUS_LONGJUMP" },
+ { 0x80040111, "MAPI_E_LOGON_FAILED" },
+ { 0x80090300, "SEC_E_INSUFFICIENT_MEMORY" },
+ { 0x80090301, "SEC_E_INVALID_HANDLE" },
+ { 0x80090302, "SEC_E_UNSUPPORTED_FUNCTION" },
+ { 0x8009030B, "SEC_E_NO_IMPERSONATION" },
+ { 0x8009030D, "SEC_E_UNKNOWN_CREDENTIALS" },
+ { 0x8009030E, "SEC_E_NO_CREDENTIALS" },
+ { 0x8009030F, "SEC_E_MESSAGE_ALTERED" },
+ { 0x80090310, "SEC_E_OUT_OF_SEQUENCE" },
+ { 0x80090311, "SEC_E_NO_AUTHENTICATING_AUTHORITY" },
+ { 0xC0000001, "STATUS_UNSUCCESSFUL" },
+ { 0xC0000002, "STATUS_NOT_IMPLEMENTED" },
+ { 0xC0000003, "STATUS_INVALID_INFO_CLASS" },
+ { 0xC0000004, "STATUS_INFO_LENGTH_MISMATCH" },
+ { 0xC0000005, "STATUS_ACCESS_VIOLATION" },
+ { 0xC0000006, "STATUS_IN_PAGE_ERROR" },
+ { 0xC0000007, "STATUS_PAGEFILE_QUOTA" },
+ { 0xC0000008, "STATUS_INVALID_HANDLE" },
+ { 0xC0000009, "STATUS_BAD_INITIAL_STACK" },
+ { 0xC000000A, "STATUS_BAD_INITIAL_PC" },
+ { 0xC000000B, "STATUS_INVALID_CID" },
+ { 0xC000000C, "STATUS_TIMER_NOT_CANCELED" },
+ { 0xC000000D, "STATUS_INVALID_PARAMETER" },
+ { 0xC000000E, "STATUS_NO_SUCH_DEVICE" },
+ { 0xC000000F, "STATUS_NO_SUCH_FILE" },
+ { 0xC0000010, "STATUS_INVALID_DEVICE_REQUEST" },
+ { 0xC0000011, "STATUS_END_OF_FILE" },
+ { 0xC0000012, "STATUS_WRONG_VOLUME" },
+ { 0xC0000013, "STATUS_NO_MEDIA_IN_DEVICE" },
+ { 0xC0000014, "STATUS_UNRECOGNIZED_MEDIA" },
+ { 0xC0000015, "STATUS_NONEXISTENT_SECTOR" },
+ { 0xC0000016, "STATUS_MORE_PROCESSING_REQUIRED" },
+ { 0xC0000017, "STATUS_NO_MEMORY" },
+ { 0xC0000018, "STATUS_CONFLICTING_ADDRESSES" },
+ { 0xC0000019, "STATUS_NOT_MAPPED_VIEW" },
+ { 0xC000001A, "STATUS_UNABLE_TO_FREE_VM" },
+ { 0xC000001B, "STATUS_UNABLE_TO_DELETE_SECTION" },
+ { 0xC000001C, "STATUS_INVALID_SYSTEM_SERVICE" },
+ { 0xC000001D, "STATUS_ILLEGAL_INSTRUCTION" },
+ { 0xC000001E, "STATUS_INVALID_LOCK_SEQUENCE" },
+ { 0xC000001F, "STATUS_INVALID_VIEW_SIZE" },
+ { 0xC0000020, "STATUS_INVALID_FILE_FOR_SECTION" },
+ { 0xC0000021, "STATUS_ALREADY_COMMITTED" },
+ { 0xC0000022, "STATUS_ACCESS_DENIED" },
+ { 0xC0000023, "STATUS_BUFFER_TOO_SMALL" },
+ { 0xC0000024, "STATUS_OBJECT_TYPE_MISMATCH" },
+ { 0xC0000025, "STATUS_NONCONTINUABLE_EXCEPTION" },
+ { 0xC0000026, "STATUS_INVALID_DISPOSITION" },
+ { 0xC0000027, "STATUS_UNWIND" },
+ { 0xC0000028, "STATUS_BAD_STACK" },
+ { 0xC0000029, "STATUS_INVALID_UNWIND_TARGET" },
+ { 0xC000002A, "STATUS_NOT_LOCKED" },
+ { 0xC000002B, "STATUS_PARITY_ERROR" },
+ { 0xC000002C, "STATUS_UNABLE_TO_DECOMMIT_VM" },
+ { 0xC000002D, "STATUS_NOT_COMMITTED" },
+ { 0xC000002E, "STATUS_INVALID_PORT_ATTRIBUTES" },
+ { 0xC000002F, "STATUS_PORT_MESSAGE_TOO_LONG" },
+ { 0xC0000030, "STATUS_INVALID_PARAMETER_MIX" },
+ { 0xC0000031, "STATUS_INVALID_QUOTA_LOWER" },
+ { 0xC0000032, "STATUS_DISK_CORRUPT_ERROR" },
+ { 0xC0000033, "STATUS_OBJECT_NAME_INVALID" },
+ { 0xC0000034, "STATUS_OBJECT_NAME_NOT_FOUND" },
+ { 0xC0000035, "STATUS_OBJECT_NAME_COLLISION" },
+ { 0xC0000037, "STATUS_PORT_DISCONNECTED" },
+ { 0xC0000038, "STATUS_DEVICE_ALREADY_ATTACHED" },
+ { 0xC0000039, "STATUS_OBJECT_PATH_INVALID" },
+ { 0xC000003A, "STATUS_OBJECT_PATH_NOT_FOUND" },
+ { 0xC000003B, "STATUS_OBJECT_PATH_SYNTAX_BAD" },
+ { 0xC000003C, "STATUS_DATA_OVERRUN" },
+ { 0xC000003D, "STATUS_DATA_LATE_ERROR" },
+ { 0xC000003E, "STATUS_DATA_ERROR" },
+ { 0xC000003F, "STATUS_CRC_ERROR" },
+ { 0xC0000040, "STATUS_SECTION_TOO_BIG" },
+ { 0xC0000041, "STATUS_PORT_CONNECTION_REFUSED" },
+ { 0xC0000042, "STATUS_INVALID_PORT_HANDLE" },
+ { 0xC0000043, "STATUS_SHARING_VIOLATION" },
+ { 0xC0000044, "STATUS_QUOTA_EXCEEDED" },
+ { 0xC0000045, "STATUS_INVALID_PAGE_PROTECTION" },
+ { 0xC0000046, "STATUS_MUTANT_NOT_OWNED" },
+ { 0xC0000047, "STATUS_SEMAPHORE_LIMIT_EXCEEDED" },
+ { 0xC0000048, "STATUS_PORT_ALREADY_SET" },
+ { 0xC0000049, "STATUS_SECTION_NOT_IMAGE" },
+ { 0xC000004A, "STATUS_SUSPEND_COUNT_EXCEEDED" },
+ { 0xC000004B, "STATUS_THREAD_IS_TERMINATING" },
+ { 0xC000004C, "STATUS_BAD_WORKING_SET_LIMIT" },
+ { 0xC000004D, "STATUS_INCOMPATIBLE_FILE_MAP" },
+ { 0xC000004E, "STATUS_SECTION_PROTECTION" },
+ { 0xC000004F, "STATUS_EAS_NOT_SUPPORTED" },
+ { 0xC0000050, "STATUS_EA_TOO_LARGE" },
+ { 0xC0000051, "STATUS_NONEXISTENT_EA_ENTRY" },
+ { 0xC0000052, "STATUS_NO_EAS_ON_FILE" },
+ { 0xC0000053, "STATUS_EA_CORRUPT_ERROR" },
+ { 0xC0000054, "STATUS_FILE_LOCK_CONFLICT" },
+ { 0xC0000055, "STATUS_LOCK_NOT_GRANTED" },
+ { 0xC0000056, "STATUS_DELETE_PENDING" },
+ { 0xC0000057, "STATUS_CTL_FILE_NOT_SUPPORTED" },
+ { 0xC0000058, "STATUS_UNKNOWN_REVISION" },
+ { 0xC0000059, "STATUS_REVISION_MISMATCH" },
+ { 0xC000005A, "STATUS_INVALID_OWNER" },
+ { 0xC000005B, "STATUS_INVALID_PRIMARY_GROUP" },
+ { 0xC000005C, "STATUS_NO_IMPERSONATION_TOKEN" },
+ { 0xC000005D, "STATUS_CANT_DISABLE_MANDATORY" },
+ { 0xC000005E, "STATUS_NO_LOGON_SERVERS" },
+ { 0xC000005F, "STATUS_NO_SUCH_LOGON_SESSION" },
+ { 0xC0000060, "STATUS_NO_SUCH_PRIVILEGE" },
+ { 0xC0000061, "STATUS_PRIVILEGE_NOT_HELD" },
+ { 0xC0000062, "STATUS_INVALID_ACCOUNT_NAME" },
+ { 0xC0000063, "STATUS_USER_EXISTS" },
+ { 0xC0000064, "STATUS_NO_SUCH_USER" },
+ { 0xC0000065, "STATUS_GROUP_EXISTS" },
+ { 0xC0000066, "STATUS_NO_SUCH_GROUP" },
+ { 0xC0000067, "STATUS_MEMBER_IN_GROUP" },
+ { 0xC0000068, "STATUS_MEMBER_NOT_IN_GROUP" },
+ { 0xC0000069, "STATUS_LAST_ADMIN" },
+ { 0xC000006A, "STATUS_WRONG_PASSWORD" },
+ { 0xC000006B, "STATUS_ILL_FORMED_PASSWORD" },
+ { 0xC000006C, "STATUS_PASSWORD_RESTRICTION" },
+ { 0xC000006D, "STATUS_LOGON_FAILURE" },
+ { 0xC000006E, "STATUS_ACCOUNT_RESTRICTION" },
+ { 0xC000006F, "STATUS_INVALID_LOGON_HOURS" },
+ { 0xC0000070, "STATUS_INVALID_WORKSTATION" },
+ { 0xC0000071, "STATUS_PASSWORD_EXPIRED" },
+ { 0xC0000072, "STATUS_ACCOUNT_DISABLED" },
+ { 0xC0000073, "STATUS_NONE_MAPPED" },
+ { 0xC0000074, "STATUS_TOO_MANY_LUIDS_REQUESTED" },
+ { 0xC0000075, "STATUS_LUIDS_EXHAUSTED" },
+ { 0xC0000076, "STATUS_INVALID_SUB_AUTHORITY" },
+ { 0xC0000077, "STATUS_INVALID_ACL" },
+ { 0xC0000078, "STATUS_INVALID_SID" },
+ { 0xC0000079, "STATUS_INVALID_SECURITY_DESCR" },
+ { 0xC000007A, "STATUS_PROCEDURE_NOT_FOUND" },
+ { 0xC000007B, "STATUS_INVALID_IMAGE_FORMAT" },
+ { 0xC000007C, "STATUS_NO_TOKEN" },
+ { 0xC000007D, "STATUS_BAD_INHERITANCE_ACL" },
+ { 0xC000007E, "STATUS_RANGE_NOT_LOCKED" },
+ { 0xC000007F, "STATUS_DISK_FULL" },
+ { 0xC0000080, "STATUS_SERVER_DISABLED" },
+ { 0xC0000081, "STATUS_SERVER_NOT_DISABLED" },
+ { 0xC0000082, "STATUS_TOO_MANY_GUIDS_REQUESTED" },
+ { 0xC0000083, "STATUS_GUIDS_EXHAUSTED" },
+ { 0xC0000084, "STATUS_INVALID_ID_AUTHORITY" },
+ { 0xC0000085, "STATUS_AGENTS_EXHAUSTED" },
+ { 0xC0000086, "STATUS_INVALID_VOLUME_LABEL" },
+ { 0xC0000087, "STATUS_SECTION_NOT_EXTENDED" },
+ { 0xC0000088, "STATUS_NOT_MAPPED_DATA" },
+ { 0xC0000089, "STATUS_RESOURCE_DATA_NOT_FOUND" },
+ { 0xC000008A, "STATUS_RESOURCE_TYPE_NOT_FOUND" },
+ { 0xC000008B, "STATUS_RESOURCE_NAME_NOT_FOUND" },
+ { 0xC000008C, "STATUS_ARRAY_BOUNDS_EXCEEDED" },
+ { 0xC000008D, "STATUS_FLOAT_DENORMAL_OPERAND" },
+ { 0xC000008E, "STATUS_FLOAT_DIVIDE_BY_ZERO" },
+ { 0xC000008F, "STATUS_FLOAT_INEXACT_RESULT" },
+ { 0xC0000090, "STATUS_FLOAT_INVALID_OPERATION" },
+ { 0xC0000091, "STATUS_FLOAT_OVERFLOW" },
+ { 0xC0000092, "STATUS_FLOAT_STACK_CHECK" },
+ { 0xC0000093, "STATUS_FLOAT_UNDERFLOW" },
+ { 0xC0000094, "STATUS_INTEGER_DIVIDE_BY_ZERO" },
+ { 0xC0000095, "STATUS_INTEGER_OVERFLOW" },
+ { 0xC0000096, "STATUS_PRIVILEGED_INSTRUCTION" },
+ { 0xC0000097, "STATUS_TOO_MANY_PAGING_FILES" },
+ { 0xC0000098, "STATUS_FILE_INVALID" },
+ { 0xC0000099, "STATUS_ALLOTTED_SPACE_EXCEEDED" },
+ { 0xC000009A, "STATUS_INSUFFICIENT_RESOURCES" },
+ { 0xC000009B, "STATUS_DFS_EXIT_PATH_FOUND" },
+ { 0xC000009C, "STATUS_DEVICE_DATA_ERROR" },
+ { 0xC000009D, "STATUS_DEVICE_NOT_CONNECTED" },
+ { 0xC000009E, "STATUS_DEVICE_POWER_FAILURE" },
+ { 0xC000009F, "STATUS_FREE_VM_NOT_AT_BASE" },
+ { 0xC00000A0, "STATUS_MEMORY_NOT_ALLOCATED" },
+ { 0xC00000A1, "STATUS_WORKING_SET_QUOTA" },
+ { 0xC00000A2, "STATUS_MEDIA_WRITE_PROTECTED" },
+ { 0xC00000A3, "STATUS_DEVICE_NOT_READY" },
+ { 0xC00000A4, "STATUS_INVALID_GROUP_ATTRIBUTES" },
+ { 0xC00000A5, "STATUS_BAD_IMPERSONATION_LEVEL" },
+ { 0xC00000A6, "STATUS_CANT_OPEN_ANONYMOUS" },
+ { 0xC00000A7, "STATUS_BAD_VALIDATION_CLASS" },
+ { 0xC00000A8, "STATUS_BAD_TOKEN_TYPE" },
+ { 0xC00000A9, "STATUS_BAD_MASTER_BOOT_RECORD" },
+ { 0xC00000AA, "STATUS_INSTRUCTION_MISALIGNMENT" },
+ { 0xC00000AB, "STATUS_INSTANCE_NOT_AVAILABLE" },
+ { 0xC00000AC, "STATUS_PIPE_NOT_AVAILABLE" },
+ { 0xC00000AD, "STATUS_INVALID_PIPE_STATE" },
+ { 0xC00000AE, "STATUS_PIPE_BUSY" },
+ { 0xC00000AF, "STATUS_ILLEGAL_FUNCTION" },
+ { 0xC00000B0, "STATUS_PIPE_DISCONNECTED" },
+ { 0xC00000B1, "STATUS_PIPE_CLOSING" },
+ { 0xC00000B2, "STATUS_PIPE_CONNECTED" },
+ { 0xC00000B3, "STATUS_PIPE_LISTENING" },
+ { 0xC00000B4, "STATUS_INVALID_READ_MODE" },
+ { 0xC00000B5, "STATUS_IO_TIMEOUT" },
+ { 0xC00000B6, "STATUS_FILE_FORCED_CLOSED" },
+ { 0xC00000B7, "STATUS_PROFILING_NOT_STARTED" },
+ { 0xC00000B8, "STATUS_PROFILING_NOT_STOPPED" },
+ { 0xC00000B9, "STATUS_COULD_NOT_INTERPRET" },
+ { 0xC00000BA, "STATUS_FILE_IS_A_DIRECTORY" },
+ { 0xC00000BB, "STATUS_NOT_SUPPORTED" },
+ { 0xC00000BC, "STATUS_REMOTE_NOT_LISTENING" },
+ { 0xC00000BD, "STATUS_DUPLICATE_NAME" },
+ { 0xC00000BE, "STATUS_BAD_NETWORK_PATH" },
+ { 0xC00000BF, "STATUS_NETWORK_BUSY" },
+ { 0xC00000C0, "STATUS_DEVICE_DOES_NOT_EXIST" },
+ { 0xC00000C1, "STATUS_TOO_MANY_COMMANDS" },
+ { 0xC00000C2, "STATUS_ADAPTER_HARDWARE_ERROR" },
+ { 0xC00000C3, "STATUS_INVALID_NETWORK_RESPONSE" },
+ { 0xC00000C4, "STATUS_UNEXPECTED_NETWORK_ERROR" },
+ { 0xC00000C5, "STATUS_BAD_REMOTE_ADAPTER" },
+ { 0xC00000C6, "STATUS_PRINT_QUEUE_FULL" },
+ { 0xC00000C7, "STATUS_NO_SPOOL_SPACE" },
+ { 0xC00000C8, "STATUS_PRINT_CANCELLED" },
+ { 0xC00000C9, "STATUS_NETWORK_NAME_DELETED" },
+ { 0xC00000CA, "STATUS_NETWORK_ACCESS_DENIED" },
+ { 0xC00000CB, "STATUS_BAD_DEVICE_TYPE" },
+ { 0xC00000CC, "STATUS_BAD_NETWORK_NAME" },
+ { 0xC00000CD, "STATUS_TOO_MANY_NAMES" },
+ { 0xC00000CE, "STATUS_TOO_MANY_SESSIONS" },
+ { 0xC00000CF, "STATUS_SHARING_PAUSED" },
+ { 0xC00000D0, "STATUS_REQUEST_NOT_ACCEPTED" },
+ { 0xC00000D1, "STATUS_REDIRECTOR_PAUSED" },
+ { 0xC00000D2, "STATUS_NET_WRITE_FAULT" },
+ { 0xC00000D3, "STATUS_PROFILING_AT_LIMIT" },
+ { 0xC00000D4, "STATUS_NOT_SAME_DEVICE" },
+ { 0xC00000D5, "STATUS_FILE_RENAMED" },
+ { 0xC00000D6, "STATUS_VIRTUAL_CIRCUIT_CLOSED" },
+ { 0xC00000D7, "STATUS_NO_SECURITY_ON_OBJECT" },
+ { 0xC00000D8, "STATUS_CANT_WAIT" },
+ { 0xC00000D9, "STATUS_PIPE_EMPTY" },
+ { 0xC00000DA, "STATUS_CANT_ACCESS_DOMAIN_INFO" },
+ { 0xC00000DB, "STATUS_CANT_TERMINATE_SELF" },
+ { 0xC00000DC, "STATUS_INVALID_SERVER_STATE" },
+ { 0xC00000DD, "STATUS_INVALID_DOMAIN_STATE" },
+ { 0xC00000DE, "STATUS_INVALID_DOMAIN_ROLE" },
+ { 0xC00000DF, "STATUS_NO_SUCH_DOMAIN" },
+ { 0xC00000E0, "STATUS_DOMAIN_EXISTS" },
+ { 0xC00000E1, "STATUS_DOMAIN_LIMIT_EXCEEDED" },
+ { 0xC00000E2, "STATUS_OPLOCK_NOT_GRANTED" },
+ { 0xC00000E3, "STATUS_INVALID_OPLOCK_PROTOCOL" },
+ { 0xC00000E4, "STATUS_INTERNAL_DB_CORRUPTION" },
+ { 0xC00000E5, "STATUS_INTERNAL_ERROR" },
+ { 0xC00000E6, "STATUS_GENERIC_NOT_MAPPED" },
+ { 0xC00000E7, "STATUS_BAD_DESCRIPTOR_FORMAT" },
+ { 0xC00000E8, "STATUS_INVALID_USER_BUFFER" },
+ { 0xC00000E9, "STATUS_UNEXPECTED_IO_ERROR" },
+ { 0xC00000EA, "STATUS_UNEXPECTED_MM_CREATE_ERR" },
+ { 0xC00000EB, "STATUS_UNEXPECTED_MM_MAP_ERROR" },
+ { 0xC00000EC, "STATUS_UNEXPECTED_MM_EXTEND_ERR" },
+ { 0xC00000ED, "STATUS_NOT_LOGON_PROCESS" },
+ { 0xC00000EE, "STATUS_LOGON_SESSION_EXISTS" },
+ { 0xC00000EF, "STATUS_INVALID_PARAMETER_1" },
+ { 0xC00000F0, "STATUS_INVALID_PARAMETER_2" },
+ { 0xC00000F1, "STATUS_INVALID_PARAMETER_3" },
+ { 0xC00000F2, "STATUS_INVALID_PARAMETER_4" },
+ { 0xC00000F3, "STATUS_INVALID_PARAMETER_5" },
+ { 0xC00000F4, "STATUS_INVALID_PARAMETER_6" },
+ { 0xC00000F5, "STATUS_INVALID_PARAMETER_7" },
+ { 0xC00000F6, "STATUS_INVALID_PARAMETER_8" },
+ { 0xC00000F7, "STATUS_INVALID_PARAMETER_9" },
+ { 0xC00000F8, "STATUS_INVALID_PARAMETER_10" },
+ { 0xC00000F9, "STATUS_INVALID_PARAMETER_11" },
+ { 0xC00000FA, "STATUS_INVALID_PARAMETER_12" },
+ { 0xC00000FB, "STATUS_REDIRECTOR_NOT_STARTED" },
+ { 0xC00000FC, "STATUS_REDIRECTOR_STARTED" },
+ { 0xC00000FD, "STATUS_STACK_OVERFLOW" },
+ { 0xC00000FE, "STATUS_NO_SUCH_PACKAGE" },
+ { 0xC00000FF, "STATUS_BAD_FUNCTION_TABLE" },
+ { 0xC0000100, "STATUS_VARIABLE_NOT_FOUND" },
+ { 0xC0000101, "STATUS_DIRECTORY_NOT_EMPTY" },
+ { 0xC0000102, "STATUS_FILE_CORRUPT_ERROR" },
+ { 0xC0000103, "STATUS_NOT_A_DIRECTORY" },
+ { 0xC0000104, "STATUS_BAD_LOGON_SESSION_STATE" },
+ { 0xC0000105, "STATUS_LOGON_SESSION_COLLISION" },
+ { 0xC0000106, "STATUS_NAME_TOO_LONG" },
+ { 0xC0000107, "STATUS_FILES_OPEN" },
+ { 0xC0000108, "STATUS_CONNECTION_IN_USE" },
+ { 0xC0000109, "STATUS_MESSAGE_NOT_FOUND" },
+ { 0xC000010A, "STATUS_PROCESS_IS_TERMINATING" },
+ { 0xC000010B, "STATUS_INVALID_LOGON_TYPE" },
+ { 0xC000010C, "STATUS_NO_GUID_TRANSLATION" },
+ { 0xC000010D, "STATUS_CANNOT_IMPERSONATE" },
+ { 0xC000010E, "STATUS_IMAGE_ALREADY_LOADED" },
+ { 0xC000010F, "STATUS_ABIOS_NOT_PRESENT" },
+ { 0xC0000110, "STATUS_ABIOS_LID_NOT_EXIST" },
+ { 0xC0000111, "STATUS_ABIOS_LID_ALREADY_OWNED" },
+ { 0xC0000112, "STATUS_ABIOS_NOT_LID_OWNER" },
+ { 0xC0000113, "STATUS_ABIOS_INVALID_COMMAND" },
+ { 0xC0000114, "STATUS_ABIOS_INVALID_LID" },
+ { 0xC0000115, "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE" },
+ { 0xC0000116, "STATUS_ABIOS_INVALID_SELECTOR" },
+ { 0xC0000117, "STATUS_NO_LDT" },
+ { 0xC0000118, "STATUS_INVALID_LDT_SIZE" },
+ { 0xC0000119, "STATUS_INVALID_LDT_OFFSET" },
+ { 0xC000011A, "STATUS_INVALID_LDT_DESCRIPTOR" },
+ { 0xC000011B, "STATUS_INVALID_IMAGE_NE_FORMAT" },
+ { 0xC000011C, "STATUS_RXACT_INVALID_STATE" },
+ { 0xC000011D, "STATUS_RXACT_COMMIT_FAILURE" },
+ { 0xC000011E, "STATUS_MAPPED_FILE_SIZE_ZERO" },
+ { 0xC000011F, "STATUS_TOO_MANY_OPENED_FILES" },
+ { 0xC0000120, "STATUS_CANCELLED" },
+ { 0xC0000121, "STATUS_CANNOT_DELETE" },
+ { 0xC0000122, "STATUS_INVALID_COMPUTER_NAME" },
+ { 0xC0000123, "STATUS_FILE_DELETED" },
+ { 0xC0000124, "STATUS_SPECIAL_ACCOUNT" },
+ { 0xC0000125, "STATUS_SPECIAL_GROUP" },
+ { 0xC0000126, "STATUS_SPECIAL_USER" },
+ { 0xC0000127, "STATUS_MEMBERS_PRIMARY_GROUP" },
+ { 0xC0000128, "STATUS_FILE_CLOSED" },
+ { 0xC0000129, "STATUS_TOO_MANY_THREADS" },
+ { 0xC000012A, "STATUS_THREAD_NOT_IN_PROCESS" },
+ { 0xC000012B, "STATUS_TOKEN_ALREADY_IN_USE" },
+ { 0xC000012C, "STATUS_PAGEFILE_QUOTA_EXCEEDED" },
+ { 0xC000012D, "STATUS_COMMITMENT_LIMIT" },
+ { 0xC000012E, "STATUS_INVALID_IMAGE_LE_FORMAT" },
+ { 0xC000012F, "STATUS_INVALID_IMAGE_NOT_MZ" },
+ { 0xC0000130, "STATUS_INVALID_IMAGE_PROTECT" },
+ { 0xC0000131, "STATUS_INVALID_IMAGE_WIN_16" },
+ { 0xC0000132, "STATUS_LOGON_SERVER_CONFLICT" },
+ { 0xC0000133, "STATUS_TIME_DIFFERENCE_AT_DC" },
+ { 0xC0000134, "STATUS_SYNCHRONIZATION_REQUIRED" },
+ { 0xC0000135, "STATUS_DLL_NOT_FOUND" },
+ { 0xC0000136, "STATUS_OPEN_FAILED" },
+ { 0xC0000137, "STATUS_IO_PRIVILEGE_FAILED" },
+ { 0xC0000138, "STATUS_ORDINAL_NOT_FOUND" },
+ { 0xC0000139, "STATUS_ENTRYPOINT_NOT_FOUND" },
+ { 0xC000013A, "STATUS_CONTROL_C_EXIT" },
+ { 0xC000013B, "STATUS_LOCAL_DISCONNECT" },
+ { 0xC000013C, "STATUS_REMOTE_DISCONNECT" },
+ { 0xC000013D, "STATUS_REMOTE_RESOURCES" },
+ { 0xC000013E, "STATUS_LINK_FAILED" },
+ { 0xC000013F, "STATUS_LINK_TIMEOUT" },
+ { 0xC0000140, "STATUS_INVALID_CONNECTION" },
+ { 0xC0000141, "STATUS_INVALID_ADDRESS" },
+ { 0xC0000142, "STATUS_DLL_INIT_FAILED" },
+ { 0xC0000143, "STATUS_MISSING_SYSTEMFILE" },
+ { 0xC0000144, "STATUS_UNHANDLED_EXCEPTION" },
+ { 0xC0000145, "STATUS_APP_INIT_FAILURE" },
+ { 0xC0000146, "STATUS_PAGEFILE_CREATE_FAILED" },
+ { 0xC0000147, "STATUS_NO_PAGEFILE" },
+ { 0xC0000148, "STATUS_INVALID_LEVEL" },
+ { 0xC0000149, "STATUS_WRONG_PASSWORD_CORE" },
+ { 0xC000014A, "STATUS_ILLEGAL_FLOAT_CONTEXT" },
+ { 0xC000014B, "STATUS_PIPE_BROKEN" },
+ { 0xC000014C, "STATUS_REGISTRY_CORRUPT" },
+ { 0xC000014D, "STATUS_REGISTRY_IO_FAILED" },
+ { 0xC000014E, "STATUS_NO_EVENT_PAIR" },
+ { 0xC000014F, "STATUS_UNRECOGNIZED_VOLUME" },
+ { 0xC0000150, "STATUS_SERIAL_NO_DEVICE_INITED" },
+ { 0xC0000151, "STATUS_NO_SUCH_ALIAS" },
+ { 0xC0000152, "STATUS_MEMBER_NOT_IN_ALIAS" },
+ { 0xC0000153, "STATUS_MEMBER_IN_ALIAS" },
+ { 0xC0000154, "STATUS_ALIAS_EXISTS" },
+ { 0xC0000155, "STATUS_LOGON_NOT_GRANTED" },
+ { 0xC0000156, "STATUS_TOO_MANY_SECRETS" },
+ { 0xC0000157, "STATUS_SECRET_TOO_LONG" },
+ { 0xC0000158, "STATUS_INTERNAL_DB_ERROR" },
+ { 0xC0000159, "STATUS_FULLSCREEN_MODE" },
+ { 0xC000015A, "STATUS_TOO_MANY_CONTEXT_IDS" },
+ { 0xC000015B, "STATUS_LOGON_TYPE_NOT_GRANTED" },
+ { 0xC000015C, "STATUS_NOT_REGISTRY_FILE" },
+ { 0xC000015D, "STATUS_NT_CROSS_ENCRYPTION_REQUIRED" },
+ { 0xC000015E, "STATUS_DOMAIN_CTRLR_CONFIG_ERROR" },
+ { 0xC000015F, "STATUS_FT_MISSING_MEMBER" },
+ { 0xC0000160, "STATUS_ILL_FORMED_SERVICE_ENTRY" },
+ { 0xC0000161, "STATUS_ILLEGAL_CHARACTER" },
+ { 0xC0000162, "STATUS_UNMAPPABLE_CHARACTER" },
+ { 0xC0000163, "STATUS_UNDEFINED_CHARACTER" },
+ { 0xC0000164, "STATUS_FLOPPY_VOLUME" },
+ { 0xC0000165, "STATUS_FLOPPY_ID_MARK_NOT_FOUND" },
+ { 0xC0000166, "STATUS_FLOPPY_WRONG_CYLINDER" },
+ { 0xC0000167, "STATUS_FLOPPY_UNKNOWN_ERROR" },
+ { 0xC0000168, "STATUS_FLOPPY_BAD_REGISTERS" },
+ { 0xC0000169, "STATUS_DISK_RECALIBRATE_FAILED" },
+ { 0xC000016A, "STATUS_DISK_OPERATION_FAILED" },
+ { 0xC000016B, "STATUS_DISK_RESET_FAILED" },
+ { 0xC000016C, "STATUS_SHARED_IRQ_BUSY" },
+ { 0xC000016D, "STATUS_FT_ORPHANING" },
+ { 0xC000016E, "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT" },
+ { 0xC0000172, "STATUS_PARTITION_FAILURE" },
+ { 0xC0000173, "STATUS_INVALID_BLOCK_LENGTH" },
+ { 0xC0000174, "STATUS_DEVICE_NOT_PARTITIONED" },
+ { 0xC0000175, "STATUS_UNABLE_TO_LOCK_MEDIA" },
+ { 0xC0000176, "STATUS_UNABLE_TO_UNLOAD_MEDIA" },
+ { 0xC0000177, "STATUS_EOM_OVERFLOW" },
+ { 0xC0000178, "STATUS_NO_MEDIA" },
+ { 0xC000017A, "STATUS_NO_SUCH_MEMBER" },
+ { 0xC000017B, "STATUS_INVALID_MEMBER" },
+ { 0xC000017C, "STATUS_KEY_DELETED" },
+ { 0xC000017D, "STATUS_NO_LOG_SPACE" },
+ { 0xC000017E, "STATUS_TOO_MANY_SIDS" },
+ { 0xC000017F, "STATUS_LM_CROSS_ENCRYPTION_REQUIRED" },
+ { 0xC0000180, "STATUS_KEY_HAS_CHILDREN" },
+ { 0xC0000181, "STATUS_CHILD_MUST_BE_VOLATILE" },
+ { 0xC0000182, "STATUS_DEVICE_CONFIGURATION_ERROR" },
+ { 0xC0000183, "STATUS_DRIVER_INTERNAL_ERROR" },
+ { 0xC0000184, "STATUS_INVALID_DEVICE_STATE" },
+ { 0xC0000185, "STATUS_IO_DEVICE_ERROR" },
+ { 0xC0000186, "STATUS_DEVICE_PROTOCOL_ERROR" },
+ { 0xC0000187, "STATUS_BACKUP_CONTROLLER" },
+ { 0xC0000188, "STATUS_LOG_FILE_FULL" },
+ { 0xC0000189, "STATUS_TOO_LATE" },
+ { 0xC000018A, "STATUS_NO_TRUST_LSA_SECRET" },
+ { 0xC000018B, "STATUS_NO_TRUST_SAM_ACCOUNT" },
+ { 0xC000018C, "STATUS_TRUSTED_DOMAIN_FAILURE" },
+ { 0xC000018D, "STATUS_TRUSTED_RELATIONSHIP_FAILURE" },
+ { 0xC000018E, "STATUS_EVENTLOG_FILE_CORRUPT" },
+ { 0xC000018F, "STATUS_EVENTLOG_CANT_START" },
+ { 0xC0000190, "STATUS_TRUST_FAILURE" },
+ { 0xC0000191, "STATUS_MUTANT_LIMIT_EXCEEDED" },
+ { 0xC0000192, "STATUS_NETLOGON_NOT_STARTED" },
+ { 0xC0000193, "STATUS_ACCOUNT_EXPIRED" },
+ { 0xC0000194, "STATUS_POSSIBLE_DEADLOCK" },
+ { 0xC0000195, "STATUS_NETWORK_CREDENTIAL_CONFLICT" },
+ { 0xC0000196, "STATUS_REMOTE_SESSION_LIMIT" },
+ { 0xC0000197, "STATUS_EVENTLOG_FILE_CHANGED" },
+ { 0xC0000198, "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT" },
+ { 0xC0000199, "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT" },
+ { 0xC000019A, "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT" },
+ { 0xC000019B, "STATUS_DOMAIN_TRUST_INCONSISTENT" },
+ { 0xC000019C, "STATUS_FS_DRIVER_REQUIRED" },
+ { 0xC0000202, "STATUS_NO_USER_SESSION_KEY" },
+ { 0xC0000203, "STATUS_USER_SESSION_DELETED" },
+ { 0xC0000204, "STATUS_RESOURCE_LANG_NOT_FOUND" },
+ { 0xC0000205, "STATUS_INSUFF_SERVER_RESOURCES" },
+ { 0xC0000206, "STATUS_INVALID_BUFFER_SIZE" },
+ { 0xC0000207, "STATUS_INVALID_ADDRESS_COMPONENT" },
+ { 0xC0000208, "STATUS_INVALID_ADDRESS_WILDCARD" },
+ { 0xC0000209, "STATUS_TOO_MANY_ADDRESSES" },
+ { 0xC000020A, "STATUS_ADDRESS_ALREADY_EXISTS" },
+ { 0xC000020B, "STATUS_ADDRESS_CLOSED" },
+ { 0xC000020C, "STATUS_CONNECTION_DISCONNECTED" },
+ { 0xC000020D, "STATUS_CONNECTION_RESET" },
+ { 0xC000020E, "STATUS_TOO_MANY_NODES" },
+ { 0xC000020F, "STATUS_TRANSACTION_ABORTED" },
+ { 0xC0000210, "STATUS_TRANSACTION_TIMED_OUT" },
+ { 0xC0000211, "STATUS_TRANSACTION_NO_RELEASE" },
+ { 0xC0000212, "STATUS_TRANSACTION_NO_MATCH" },
+ { 0xC0000213, "STATUS_TRANSACTION_RESPONDED" },
+ { 0xC0000214, "STATUS_TRANSACTION_INVALID_ID" },
+ { 0xC0000215, "STATUS_TRANSACTION_INVALID_TYPE" },
+ { 0xC0000216, "STATUS_NOT_SERVER_SESSION" },
+ { 0xC0000217, "STATUS_NOT_CLIENT_SESSION" },
+ { 0xC0000218, "STATUS_CANNOT_LOAD_REGISTRY_FILE" },
+ { 0xC0000219, "STATUS_DEBUG_ATTACH_FAILED" },
+ { 0xC000021A, "STATUS_SYSTEM_PROCESS_TERMINATED" },
+ { 0xC000021B, "STATUS_DATA_NOT_ACCEPTED" },
+ { 0xC000021C, "STATUS_NO_BROWSER_SERVERS_FOUND" },
+ { 0xC000021D, "STATUS_VDM_HARD_ERROR" },
+ { 0xC000021E, "STATUS_DRIVER_CANCEL_TIMEOUT" },
+ { 0xC000021F, "STATUS_REPLY_MESSAGE_MISMATCH" },
+ { 0xC0000220, "STATUS_MAPPED_ALIGNMENT" },
+ { 0xC0000221, "STATUS_IMAGE_CHECKSUM_MISMATCH" },
+ { 0xC0000222, "STATUS_LOST_WRITEBEHIND_DATA" },
+ { 0xC0000223, "STATUS_CLIENT_SERVER_PARAMETERS_INVALID" },
+ { 0xC0000224, "STATUS_PASSWORD_MUST_CHANGE" },
+ { 0xC0000225, "STATUS_NOT_FOUND" },
+ { 0xC0000226, "STATUS_NOT_TINY_STREAM" },
+ { 0xC0000227, "STATUS_RECOVERY_FAILURE" },
+ { 0xC0000228, "STATUS_STACK_OVERFLOW_READ" },
+ { 0xC0000229, "STATUS_FAIL_CHECK" },
+ { 0xC000022A, "STATUS_DUPLICATE_OBJECTID" },
+ { 0xC000022B, "STATUS_OBJECTID_EXISTS" },
+ { 0xC000022C, "STATUS_CONVERT_TO_LARGE" },
+ { 0xC000022D, "STATUS_RETRY" },
+ { 0xC000022E, "STATUS_FOUND_OUT_OF_SCOPE" },
+ { 0xC000022F, "STATUS_ALLOCATE_BUCKET" },
+ { 0xC0000230, "STATUS_PROPSET_NOT_FOUND" },
+ { 0xC0000231, "STATUS_MARSHALL_OVERFLOW" },
+ { 0xC0000232, "STATUS_INVALID_VARIANT" },
+ { 0xC0000233, "STATUS_DOMAIN_CONTROLLER_NOT_FOUND" },
+ { 0xC0000234, "STATUS_ACCOUNT_LOCKED_OUT" },
+ { 0xC0000235, "STATUS_HANDLE_NOT_CLOSABLE" },
+ { 0xC0000236, "STATUS_CONNECTION_REFUSED" },
+ { 0xC0000237, "STATUS_GRACEFUL_DISCONNECT" },
+ { 0xC0000238, "STATUS_ADDRESS_ALREADY_ASSOCIATED" },
+ { 0xC0000239, "STATUS_ADDRESS_NOT_ASSOCIATED" },
+ { 0xC000023A, "STATUS_CONNECTION_INVALID" },
+ { 0xC000023B, "STATUS_CONNECTION_ACTIVE" },
+ { 0xC000023C, "STATUS_NETWORK_UNREACHABLE" },
+ { 0xC000023D, "STATUS_HOST_UNREACHABLE" },
+ { 0xC000023E, "STATUS_PROTOCOL_UNREACHABLE" },
+ { 0xC000023F, "STATUS_PORT_UNREACHABLE" },
+ { 0xC0000240, "STATUS_REQUEST_ABORTED" },
+ { 0xC0000241, "STATUS_CONNECTION_ABORTED" },
+ { 0xC0000242, "STATUS_BAD_COMPRESSION_BUFFER" },
+ { 0xC0000243, "STATUS_USER_MAPPED_FILE" },
+ { 0xC0000244, "STATUS_AUDIT_FAILED" },
+ { 0xC0000245, "STATUS_TIMER_RESOLUTION_NOT_SET" },
+ { 0xC0000246, "STATUS_CONNECTION_COUNT_LIMIT" },
+ { 0xC0000247, "STATUS_LOGIN_TIME_RESTRICTION" },
+ { 0xC0000248, "STATUS_LOGIN_WKSTA_RESTRICTION" },
+ { 0xC0000249, "STATUS_IMAGE_MP_UP_MISMATCH" },
+ { 0xC0000250, "STATUS_INSUFFICIENT_LOGON_INFO" },
+ { 0xC0000251, "STATUS_BAD_DLL_ENTRYPOINT" },
+ { 0xC0000252, "STATUS_BAD_SERVICE_ENTRYPOINT" },
+ { 0xC0000253, "STATUS_LPC_REPLY_LOST" },
+ { 0xC0000254, "STATUS_IP_ADDRESS_CONFLICT1" },
+ { 0xC0000255, "STATUS_IP_ADDRESS_CONFLICT2" },
+ { 0xC0000256, "STATUS_REGISTRY_QUOTA_LIMIT" },
+ { 0xC0000257, "STATUS_PATH_NOT_COVERED" },
+ { 0xC0000258, "STATUS_NO_CALLBACK_ACTIVE" },
+ { 0xC0000259, "STATUS_LICENSE_QUOTA_EXCEEDED" },
+ { 0xC000025A, "STATUS_PWD_TOO_SHORT" },
+ { 0xC000025B, "STATUS_PWD_TOO_RECENT" },
+ { 0xC000025C, "STATUS_PWD_HISTORY_CONFLICT" },
+ { 0xC000025E, "STATUS_PLUGPLAY_NO_DEVICE" },
+ { 0xC000025F, "STATUS_UNSUPPORTED_COMPRESSION" },
+ { 0xC0000260, "STATUS_INVALID_HW_PROFILE" },
+ { 0xC0000261, "STATUS_INVALID_PLUGPLAY_DEVICE_PATH" },
+ { 0xC0000262, "STATUS_DRIVER_ORDINAL_NOT_FOUND" },
+ { 0xC0000263, "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND" },
+ { 0xC0000264, "STATUS_RESOURCE_NOT_OWNED" },
+ { 0xC0000265, "STATUS_TOO_MANY_LINKS" },
+ { 0xC0000266, "STATUS_QUOTA_LIST_INCONSISTENT" },
+ { 0xC0000267, "STATUS_FILE_IS_OFFLINE" },
+ { 0xC0000268, "STATUS_EVALUATION_EXPIRATION" },
+ { 0xC0000269, "STATUS_ILLEGAL_DLL_RELOCATION" },
+ { 0xC000026A, "STATUS_LICENSE_VIOLATION" },
+ { 0xC000026B, "STATUS_DLL_INIT_FAILED_LOGOFF" },
+ { 0xC000026C, "STATUS_DRIVER_UNABLE_TO_LOAD" },
+ { 0xC000026D, "STATUS_DFS_UNAVAILABLE" },
+ { 0xC000026E, "STATUS_VOLUME_DISMOUNTED" },
+ { 0xC000026F, "STATUS_WX86_INTERNAL_ERROR" },
+ { 0xC0000270, "STATUS_WX86_FLOAT_STACK_CHECK" },
+ { 0xC0000271, "STATUS_VALIDATE_CONTINUE" },
+ { 0xC0000272, "STATUS_NO_MATCH" },
+ { 0xC0000273, "STATUS_NO_MORE_MATCHES" },
+ { 0xC0000275, "STATUS_NOT_A_REPARSE_POINT" },
+ { 0xC0000276, "STATUS_IO_REPARSE_TAG_INVALID" },
+ { 0xC0000277, "STATUS_IO_REPARSE_TAG_MISMATCH" },
+ { 0xC0000278, "STATUS_IO_REPARSE_DATA_INVALID" },
+ { 0xC0000279, "STATUS_IO_REPARSE_TAG_NOT_HANDLED" },
+ { 0xC0000280, "STATUS_REPARSE_POINT_NOT_RESOLVED" },
+ { 0xC0000281, "STATUS_DIRECTORY_IS_A_REPARSE_POINT" },
+ { 0xC0000282, "STATUS_RANGE_LIST_CONFLICT" },
+ { 0xC0000283, "STATUS_SOURCE_ELEMENT_EMPTY" },
+ { 0xC0000284, "STATUS_DESTINATION_ELEMENT_FULL" },
+ { 0xC0000285, "STATUS_ILLEGAL_ELEMENT_ADDRESS" },
+ { 0xC0000286, "STATUS_MAGAZINE_NOT_PRESENT" },
+ { 0xC0000287, "STATUS_REINITIALIZATION_NEEDED" },
+ { 0x80000288, "STATUS_DEVICE_REQUIRES_CLEANING" },
+ { 0x80000289, "STATUS_DEVICE_DOOR_OPEN" },
+ { 0xC000028A, "STATUS_ENCRYPTION_FAILED" },
+ { 0xC000028B, "STATUS_DECRYPTION_FAILED" },
+ { 0xC000028C, "STATUS_RANGE_NOT_FOUND" },
+ { 0xC000028D, "STATUS_NO_RECOVERY_POLICY" },
+ { 0xC000028E, "STATUS_NO_EFS" },
+ { 0xC000028F, "STATUS_WRONG_EFS" },
+ { 0xC0000290, "STATUS_NO_USER_KEYS" },
+ { 0xC0000291, "STATUS_FILE_NOT_ENCRYPTED" },
+ { 0xC0000292, "STATUS_NOT_EXPORT_FORMAT" },
+ { 0xC0000293, "STATUS_FILE_ENCRYPTED" },
+ { 0x40000294, "STATUS_WAKE_SYSTEM" },
+ { 0xC0000295, "STATUS_WMI_GUID_NOT_FOUND" },
+ { 0xC0000296, "STATUS_WMI_INSTANCE_NOT_FOUND" },
+ { 0xC0000297, "STATUS_WMI_ITEMID_NOT_FOUND" },
+ { 0xC0000298, "STATUS_WMI_TRY_AGAIN" },
+ { 0xC0000299, "STATUS_SHARED_POLICY" },
+ { 0xC000029A, "STATUS_POLICY_OBJECT_NOT_FOUND" },
+ { 0xC000029B, "STATUS_POLICY_ONLY_IN_DS" },
+ { 0xC000029C, "STATUS_VOLUME_NOT_UPGRADED" },
+ { 0xC000029D, "STATUS_REMOTE_STORAGE_NOT_ACTIVE" },
+ { 0xC000029E, "STATUS_REMOTE_STORAGE_MEDIA_ERROR" },
+ { 0xC000029F, "STATUS_NO_TRACKING_SERVICE" },
+ { 0xC00002A0, "STATUS_SERVER_SID_MISMATCH" },
+ { 0xC00002A1, "STATUS_DS_NO_ATTRIBUTE_OR_VALUE" },
+ { 0xC00002A2, "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX" },
+ { 0xC00002A3, "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED" },
+ { 0xC00002A4, "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS" },
+ { 0xC00002A5, "STATUS_DS_BUSY" },
+ { 0xC00002A6, "STATUS_DS_UNAVAILABLE" },
+ { 0xC00002A7, "STATUS_DS_NO_RIDS_ALLOCATED" },
+ { 0xC00002A8, "STATUS_DS_NO_MORE_RIDS" },
+ { 0xC00002A9, "STATUS_DS_INCORRECT_ROLE_OWNER" },
+ { 0xC00002AA, "STATUS_DS_RIDMGR_INIT_ERROR" },
+ { 0xC00002AB, "STATUS_DS_OBJ_CLASS_VIOLATION" },
+ { 0xC00002AC, "STATUS_DS_CANT_ON_NON_LEAF" },
+ { 0xC00002AD, "STATUS_DS_CANT_ON_RDN" },
+ { 0xC00002AE, "STATUS_DS_CANT_MOD_OBJ_CLASS" },
+ { 0xC00002AF, "STATUS_DS_CROSS_DOM_MOVE_FAILED" },
+ { 0xC00002B0, "STATUS_DS_GC_NOT_AVAILABLE" },
+ { 0xC00002B1, "STATUS_DIRECTORY_SERVICE_REQUIRED" },
+ { 0xC00002B2, "STATUS_REPARSE_ATTRIBUTE_CONFLICT" },
+ { 0xC00002B3, "STATUS_CANT_ENABLE_DENY_ONLY" },
+ { 0xC00002B4, "STATUS_FLOAT_MULTIPLE_FAULTS" },
+ { 0xC00002B5, "STATUS_FLOAT_MULTIPLE_TRAPS" },
+ { 0xC00002B6, "STATUS_DEVICE_REMOVED" },
+ { 0xC00002B7, "STATUS_JOURNAL_DELETE_IN_PROGRESS" },
+ { 0xC00002B8, "STATUS_JOURNAL_NOT_ACTIVE" },
+ { 0xC00002B9, "STATUS_NOINTERFACE" },
+ { 0xC00002C1, "STATUS_DS_ADMIN_LIMIT_EXCEEDED" },
+ { 0xC00002C2, "STATUS_DRIVER_FAILED_SLEEP" },
+ { 0xC00002C3, "STATUS_MUTUAL_AUTHENTICATION_FAILED" },
+ { 0xC00002C4, "STATUS_CORRUPT_SYSTEM_FILE" },
+ { 0xC00002C5, "STATUS_DATATYPE_MISALIGNMENT_ERROR" },
+ { 0xC00002C6, "STATUS_WMI_READ_ONLY" },
+ { 0xC00002C7, "STATUS_WMI_SET_FAILURE" },
+ { 0xC00002C8, "STATUS_COMMITMENT_MINIMUM" },
+ { 0xC00002C9, "STATUS_REG_NAT_CONSUMPTION" },
+ { 0xC00002CA, "STATUS_TRANSPORT_FULL" },
+ { 0xC00002CB, "STATUS_DS_SAM_INIT_FAILURE" },
+ { 0xC00002CC, "STATUS_ONLY_IF_CONNECTED" },
+ { 0xC00002CD, "STATUS_DS_SENSITIVE_GROUP_VIOLATION" },
+ { 0xC00002CE, "STATUS_PNP_RESTART_ENUMERATION" },
+ { 0xC00002CF, "STATUS_JOURNAL_ENTRY_DELETED" },
+ { 0xC00002D0, "STATUS_DS_CANT_MOD_PRIMARYGROUPID" },
+ { 0xC00002D1, "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE" },
+ { 0xC00002D2, "STATUS_PNP_REBOOT_REQUIRED" },
+ { 0xC00002D3, "STATUS_POWER_STATE_INVALID" },
+ { 0xC00002D4, "STATUS_DS_INVALID_GROUP_TYPE" },
+ { 0xC00002D5, "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN" },
+ { 0xC00002D6, "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN" },
+ { 0xC00002D7, "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER" },
+ { 0xC00002D8, "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER" },
+ { 0xC00002D9, "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER" },
+ { 0xC00002DA, "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER" },
+ { 0xC00002DB, "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER" },
+ { 0xC00002DC, "STATUS_DS_HAVE_PRIMARY_MEMBERS" },
+ { 0xC00002DD, "STATUS_WMI_NOT_SUPPORTED" },
+ { 0xC00002DE, "STATUS_INSUFFICIENT_POWER" },
+ { 0xC00002DF, "STATUS_SAM_NEED_BOOTKEY_PASSWORD" },
+ { 0xC00002E0, "STATUS_SAM_NEED_BOOTKEY_FLOPPY" },
+ { 0xC00002E1, "STATUS_DS_CANT_START" },
+ { 0xC00002E2, "STATUS_DS_INIT_FAILURE" },
+ { 0xC00002E3, "STATUS_SAM_INIT_FAILURE" },
+ { 0xC00002E4, "STATUS_DS_GC_REQUIRED" },
+ { 0xC00002E5, "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY" },
+ { 0xC00002E6, "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS" },
+ { 0xC00002E7, "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED" },
+ { 0xC00002E8, "STATUS_MULTIPLE_FAULT_VIOLATION" },
+ { 0xC0000300, "STATUS_NOT_SUPPORTED_ON_SBS" },
+ { 0xC0009898, "STATUS_WOW_ASSERTION" },
+ { 0xC0020001, "RPC_NT_INVALID_STRING_BINDING" },
+ { 0xC0020002, "RPC_NT_WRONG_KIND_OF_BINDING" },
+ { 0xC0020003, "RPC_NT_INVALID_BINDING" },
+ { 0xC0020004, "RPC_NT_PROTSEQ_NOT_SUPPORTED" },
+ { 0xC0020005, "RPC_NT_INVALID_RPC_PROTSEQ" },
+ { 0xC0020006, "RPC_NT_INVALID_STRING_UUID" },
+ { 0xC0020007, "RPC_NT_INVALID_ENDPOINT_FORMAT" },
+ { 0xC0020008, "RPC_NT_INVALID_NET_ADDR" },
+ { 0xC0020009, "RPC_NT_NO_ENDPOINT_FOUND" },
+ { 0xC002000A, "RPC_NT_INVALID_TIMEOUT" },
+ { 0xC002000B, "RPC_NT_OBJECT_NOT_FOUND" },
+ { 0xC002000C, "RPC_NT_ALREADY_REGISTERED" },
+ { 0xC002000D, "RPC_NT_TYPE_ALREADY_REGISTERED" },
+ { 0xC002000E, "RPC_NT_ALREADY_LISTENING" },
+ { 0xC002000F, "RPC_NT_NO_PROTSEQS_REGISTERED" },
+ { 0xC0020010, "RPC_NT_NOT_LISTENING" },
+ { 0xC0020011, "RPC_NT_UNKNOWN_MGR_TYPE" },
+ { 0xC0020012, "RPC_NT_UNKNOWN_IF" },
+ { 0xC0020013, "RPC_NT_NO_BINDINGS" },
+ { 0xC0020014, "RPC_NT_NO_PROTSEQS" },
+ { 0xC0020015, "RPC_NT_CANT_CREATE_ENDPOINT" },
+ { 0xC0020016, "RPC_NT_OUT_OF_RESOURCES" },
+ { 0xC0020017, "RPC_NT_SERVER_UNAVAILABLE" },
+ { 0xC0020018, "RPC_NT_SERVER_TOO_BUSY" },
+ { 0xC0020019, "RPC_NT_INVALID_NETWORK_OPTIONS" },
+ { 0xC002001A, "RPC_NT_NO_CALL_ACTIVE" },
+ { 0xC002001B, "RPC_NT_CALL_FAILED" },
+ { 0xC002001C, "RPC_NT_CALL_FAILED_DNE" },
+ { 0xC002001D, "RPC_NT_PROTOCOL_ERROR" },
+ { 0xC002001F, "RPC_NT_UNSUPPORTED_TRANS_SYN" },
+ { 0xC0020021, "RPC_NT_UNSUPPORTED_TYPE" },
+ { 0xC0020022, "RPC_NT_INVALID_TAG" },
+ { 0xC0020023, "RPC_NT_INVALID_BOUND" },
+ { 0xC0020024, "RPC_NT_NO_ENTRY_NAME" },
+ { 0xC0020025, "RPC_NT_INVALID_NAME_SYNTAX" },
+ { 0xC0020026, "RPC_NT_UNSUPPORTED_NAME_SYNTAX" },
+ { 0xC0020028, "RPC_NT_UUID_NO_ADDRESS" },
+ { 0xC0020029, "RPC_NT_DUPLICATE_ENDPOINT" },
+ { 0xC002002A, "RPC_NT_UNKNOWN_AUTHN_TYPE" },
+ { 0xC002002B, "RPC_NT_MAX_CALLS_TOO_SMALL" },
+ { 0xC002002C, "RPC_NT_STRING_TOO_LONG" },
+ { 0xC002002D, "RPC_NT_PROTSEQ_NOT_FOUND" },
+ { 0xC002002E, "RPC_NT_PROCNUM_OUT_OF_RANGE" },
+ { 0xC002002F, "RPC_NT_BINDING_HAS_NO_AUTH" },
+ { 0xC0020030, "RPC_NT_UNKNOWN_AUTHN_SERVICE" },
+ { 0xC0020031, "RPC_NT_UNKNOWN_AUTHN_LEVEL" },
+ { 0xC0020032, "RPC_NT_INVALID_AUTH_IDENTITY" },
+ { 0xC0020033, "RPC_NT_UNKNOWN_AUTHZ_SERVICE" },
+ { 0xC0020034, "EPT_NT_INVALID_ENTRY" },
+ { 0xC0020035, "EPT_NT_CANT_PERFORM_OP" },
+ { 0xC0020036, "EPT_NT_NOT_REGISTERED" },
+ { 0xC0020037, "RPC_NT_NOTHING_TO_EXPORT" },
+ { 0xC0020038, "RPC_NT_INCOMPLETE_NAME" },
+ { 0xC0020039, "RPC_NT_INVALID_VERS_OPTION" },
+ { 0xC002003A, "RPC_NT_NO_MORE_MEMBERS" },
+ { 0xC002003B, "RPC_NT_NOT_ALL_OBJS_UNEXPORTED" },
+ { 0xC002003C, "RPC_NT_INTERFACE_NOT_FOUND" },
+ { 0xC002003D, "RPC_NT_ENTRY_ALREADY_EXISTS" },
+ { 0xC002003E, "RPC_NT_ENTRY_NOT_FOUND" },
+ { 0xC002003F, "RPC_NT_NAME_SERVICE_UNAVAILABLE" },
+ { 0xC0020040, "RPC_NT_INVALID_NAF_ID" },
+ { 0xC0020041, "RPC_NT_CANNOT_SUPPORT" },
+ { 0xC0020042, "RPC_NT_NO_CONTEXT_AVAILABLE" },
+ { 0xC0020043, "RPC_NT_INTERNAL_ERROR" },
+ { 0xC0020044, "RPC_NT_ZERO_DIVIDE" },
+ { 0xC0020045, "RPC_NT_ADDRESS_ERROR" },
+ { 0xC0020046, "RPC_NT_FP_DIV_ZERO" },
+ { 0xC0020047, "RPC_NT_FP_UNDERFLOW" },
+ { 0xC0020048, "RPC_NT_FP_OVERFLOW" },
+ { 0xC0021007, "RPC_P_RECEIVE_ALERTED" },
+ { 0xC0021008, "RPC_P_CONNECTION_CLOSED" },
+ { 0xC0021009, "RPC_P_RECEIVE_FAILED" },
+ { 0xC002100A, "RPC_P_SEND_FAILED" },
+ { 0xC002100B, "RPC_P_TIMEOUT" },
+ { 0xC002100C, "RPC_P_SERVER_TRANSPORT_ERROR" },
+ { 0xC002100E, "RPC_P_EXCEPTION_OCCURED" },
+ { 0xC0021012, "RPC_P_CONNECTION_SHUTDOWN" },
+ { 0xC0021015, "RPC_P_THREAD_LISTENING" },
+ { 0xC0030001, "RPC_NT_NO_MORE_ENTRIES" },
+ { 0xC0030002, "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL" },
+ { 0xC0030003, "RPC_NT_SS_CHAR_TRANS_SHORT_FILE" },
+ { 0xC0030004, "RPC_NT_SS_IN_NULL_CONTEXT" },
+ { 0xC0030005, "RPC_NT_SS_CONTEXT_MISMATCH" },
+ { 0xC0030006, "RPC_NT_SS_CONTEXT_DAMAGED" },
+ { 0xC0030007, "RPC_NT_SS_HANDLES_MISMATCH" },
+ { 0xC0030008, "RPC_NT_SS_CANNOT_GET_CALL_HANDLE" },
+ { 0xC0030009, "RPC_NT_NULL_REF_POINTER" },
+ { 0xC003000A, "RPC_NT_ENUM_VALUE_OUT_OF_RANGE" },
+ { 0xC003000B, "RPC_NT_BYTE_COUNT_TOO_SMALL" },
+ { 0xC003000C, "RPC_NT_BAD_STUB_DATA" },
+ { 0xC0020049, "RPC_NT_CALL_IN_PROGRESS" },
+ { 0xC002004A, "RPC_NT_NO_MORE_BINDINGS" },
+ { 0xC002004B, "RPC_NT_GROUP_MEMBER_NOT_FOUND" },
+ { 0xC002004C, "EPT_NT_CANT_CREATE" },
+ { 0xC002004D, "RPC_NT_INVALID_OBJECT" },
+ { 0xC002004F, "RPC_NT_NO_INTERFACES" },
+ { 0xC0020050, "RPC_NT_CALL_CANCELLED" },
+ { 0xC0020051, "RPC_NT_BINDING_INCOMPLETE" },
+ { 0xC0020052, "RPC_NT_COMM_FAILURE" },
+ { 0xC0020053, "RPC_NT_UNSUPPORTED_AUTHN_LEVEL" },
+ { 0xC0020054, "RPC_NT_NO_PRINC_NAME" },
+ { 0xC0020055, "RPC_NT_NOT_RPC_ERROR" },
+ { 0x40020056, "RPC_NT_UUID_LOCAL_ONLY" },
+ { 0xC0020057, "RPC_NT_SEC_PKG_ERROR" },
+ { 0xC0020058, "RPC_NT_NOT_CANCELLED" },
+ { 0xC0030059, "RPC_NT_INVALID_ES_ACTION" },
+ { 0xC003005A, "RPC_NT_WRONG_ES_VERSION" },
+ { 0xC003005B, "RPC_NT_WRONG_STUB_VERSION" },
+ { 0xC003005C, "RPC_NT_INVALID_PIPE_OBJECT" },
+ { 0xC003005D, "RPC_NT_INVALID_PIPE_OPERATION" },
+ { 0xC003005E, "RPC_NT_WRONG_PIPE_VERSION" },
+ { 0x400200AF, "RPC_NT_SEND_INCOMPLETE" },
+ { 0, NULL }
+};
+
+
+
+static const true_false_string tfs_smb_flags_lock = {
+ "Lock&Read, Write&Unlock are supported",
+ "Lock&Read, Write&Unlock are not supported"
+};
+static const true_false_string tfs_smb_flags_receive_buffer = {
+ "Receive buffer has been posted",
+ "Receive buffer has not been posted"
+};
+static const true_false_string tfs_smb_flags_caseless = {
+ "Path names are caseless",
+ "Path names are case sensitive"
+};
+static const true_false_string tfs_smb_flags_canon = {
+ "Pathnames are canonicalized",
+ "Pathnames are not canonicalized"
+};
+static const true_false_string tfs_smb_flags_oplock = {
+ "OpLock requested/granted",
+ "OpLock not requested/granted"
+};
+static const true_false_string tfs_smb_flags_notify = {
+ "Notify client on all modifications",
+ "Notify client only on open"
+};
+static const true_false_string tfs_smb_flags_response = {
+ "Message is a response to the client/redirector",
+ "Message is a request to the server"
+};
+
+static int
+dissect_smb_flags(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint8 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_guint8(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+ "Flags: 0x%02x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_flags);
+ }
+ proto_tree_add_boolean(tree, hf_smb_flags_response,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags_notify,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags_oplock,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags_canon,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags_caseless,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags_receive_buffer,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags_lock,
+ tvb, offset, 1, mask);
+ offset += 1;
+ return offset;
+}
+
+
+
+static const true_false_string tfs_smb_flags2_long_names_allowed = {
+ "Long file names are allowed in the response",
+ "Long file names are not allowed in the response"
+};
+static const true_false_string tfs_smb_flags2_ea = {
+ "Extended attributes are supported",
+ "Extended attributes are not supported"
+};
+static const true_false_string tfs_smb_flags2_sec_sig = {
+ "Security signatures are supported",
+ "Security signatures are not supported"
+};
+static const true_false_string tfs_smb_flags2_long_names_used = {
+ "Path names in request are long file names",
+ "Path names in request are not long file names"
+};
+static const true_false_string tfs_smb_flags2_esn = {
+ "Extended security negotiation is supported",
+ "Extended security negotiation is not supported"
+};
+static const true_false_string tfs_smb_flags2_dfs = {
+ "Resolve pathnames with Dfs",
+ "Don't resolve pathnames with Dfs"
+};
+static const true_false_string tfs_smb_flags2_roe = {
+ "Permit reads if execute-only",
+ "Don't permit reads if execute-only"
+};
+static const true_false_string tfs_smb_flags2_nt_error = {
+ "Error codes are NT error codes",
+ "Error codes are DOS error codes"
+};
+static const true_false_string tfs_smb_flags2_string = {
+ "Strings are Unicode",
+ "Strings are ASCII"
+};
+static int
+dissect_smb_flags2(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+{
+ guint16 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_letohs(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 2,
+ "Flags2: 0x%04x", mask);
+ tree = proto_item_add_subtree(item, ett_smb_flags2);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_flags2_string,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags2_nt_error,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags2_roe,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags2_dfs,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags2_esn,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags2_long_names_used,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags2_sec_sig,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags2_ea,
+ tvb, offset, 2, mask);
+ proto_tree_add_boolean(tree, hf_smb_flags2_long_names_allowed,
+ tvb, offset, 2, mask);
+
+ offset += 2;
+ return offset;
+}
+
+
+
+#define SMB_FLAGS_DIRN 0x80
+
+
+static void
+dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ int offset = 0;
+ proto_item *item = NULL, *hitem = NULL;
+ proto_tree *tree = NULL, *htree = NULL;
+ guint8 flags;
+ guint16 flags2;
+ static smb_info_t si_arr[20];
+ static int si_counter=0;
+ smb_info_t *si;
+ smb_saved_info_t *sip = NULL;
+ smb_saved_info_key_t key;
+ smb_saved_info_key_t *new_key;
+ guint32 nt_status = 0;
+ guint8 errclass = 0;
+ guint16 errcode = 0;
+ guint32 pid_mid;
+ conversation_t *conversation;
+ nstime_t ns;
+
+ si_counter++;
+ if(si_counter==20){
+ si_counter=0;
+ }
+ si=&si_arr[si_counter];
+
+ top_tree=parent_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)){
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMB");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ /* start off using the local variable, we will allocate a new one if we
+ need to*/
+ si->cmd = tvb_get_guint8(tvb, offset+4);
+ flags = tvb_get_guint8(tvb, offset+9);
+ /*
+ * XXX - in some SMB-over-OSI-transport and SMB-over-Vines traffic,
+ * the direction flag appears never to be set, even for what appear
+ * to be replies. Do some SMB servers fail to set that flag,
+ * under the assumption that the client knows it's a reply because
+ * it received it?
+ */
+ si->request = !(flags&SMB_FLAGS_DIRN);
+ flags2 = tvb_get_letohs(tvb, offset+10);
+ if(flags2 & 0x8000){
+ si->unicode = TRUE; /* Mark them as Unicode */
+ } else {
+ si->unicode = FALSE;
+ }
+ si->tid = tvb_get_letohs(tvb, offset+24);
+ si->pid = tvb_get_letohs(tvb, offset+26);
+ si->uid = tvb_get_letohs(tvb, offset+28);
+ si->mid = tvb_get_letohs(tvb, offset+30);
+ pid_mid = (si->pid << 16) | si->mid;
+ si->info_level = -1;
+ si->info_count = -1;
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, proto_smb, tvb, offset,
+ -1, FALSE);
+ tree = proto_item_add_subtree(item, ett_smb);
+
+ hitem = proto_tree_add_text(tree, tvb, offset, 32,
+ "SMB Header");
+
+ htree = proto_item_add_subtree(hitem, ett_smb_hdr);
+ }
+
+ proto_tree_add_text(htree, tvb, offset, 4, "Server Component: SMB");
+ offset += 4; /* Skip the marker */
+
+ /* find which conversation we are part of and get the tables for that
+ conversation*/
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if(!conversation){
+ /* OK this is a new conversation so lets create it */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ /* see if we already have the smb data for this conversation */
+ si->ct=conversation_get_proto_data(conversation, proto_smb);
+ if(!si->ct){
+ /* No, not yet. create it and attach it to the conversation */
+ si->ct = g_mem_chunk_alloc(conv_tables_chunk);
+ conv_tables = g_slist_prepend(conv_tables, si->ct);
+ si->ct->matched= g_hash_table_new(smb_saved_info_hash_matched,
+ smb_saved_info_equal_matched);
+ si->ct->unmatched= g_hash_table_new(smb_saved_info_hash_unmatched,
+ smb_saved_info_equal_unmatched);
+ si->ct->tid_service=g_hash_table_new(
+ smb_saved_info_hash_unmatched,
+ smb_saved_info_equal_unmatched);
+ conversation_add_proto_data(conversation, proto_smb, si->ct);
+ }
+
+ if( (si->request)
+ && (si->mid==0)
+ && (si->uid==0)
+ && (si->pid==0)
+ && (si->tid==0) ){
+ /* this is a broadcast SMB packet, there will not be a reply.
+ We dont need to do anything
+ */
+ si->unidir = TRUE;
+ } else if( (si->cmd==SMB_COM_NT_CANCEL) /* NT Cancel */
+ ||(si->cmd==SMB_COM_TRANSACTION_SECONDARY) /* Transaction Secondary */
+ ||(si->cmd==SMB_COM_TRANSACTION2_SECONDARY) /* Transaction2 Secondary */
+ ||(si->cmd==SMB_COM_NT_TRANSACT_SECONDARY)){ /* NT Transaction Secondary */
+ /* Ok, we got a special request type. This request is either
+ an NT Cancel or a continuation relative to a real request
+ in an earlier packet. In either case, we don't expect any
+ responses to this packet. For continuations, any later
+ responses we see really just belong to the original request.
+ Anyway, we want to remember this packet somehow and
+ remember which original request it is associated with so
+ we can say nice things such as "This is a Cancellation to
+ the request in frame x", but we don't want the
+ request/response matching to get messed up.
+
+ The only thing we do in this case is trying to find which original
+ request we match with and insert an entry for this "special"
+ request for later reference. We continue to reference the original
+ requests smb_saved_info_t but we dont touch it or change anything
+ in it.
+ */
+
+ si->unidir = TRUE; /*we dont expect an answer to this one*/
+
+ if(!pinfo->fd->flags.visited){
+ /* try to find which original call we match and if we
+ find it add us to the matched table. Dont touch
+ anything else since we dont want this one to mess
+ up the request/response matching. We still consider
+ the initial call the real request and this is only
+ some sort of continuation.
+ */
+ /* we only check the unmatched table and assume that the
+ last seen MID matching ours is the right one.
+ This can fail but is better than nothing
+ */
+ sip=g_hash_table_lookup(si->ct->unmatched, (void *)pid_mid);
+ if(sip!=NULL){
+ new_key = g_mem_chunk_alloc(smb_saved_info_key_chunk);
+ new_key->frame = pinfo->fd->num;
+ new_key->pid_mid = pid_mid;
+ g_hash_table_insert(si->ct->matched, new_key,
+ sip);
+ }
+ } else {
+ /* we have seen this packet before; check the
+ matching table
+ */
+ key.frame = pinfo->fd->num;
+ key.pid_mid = pid_mid;
+ sip=g_hash_table_lookup(si->ct->matched, &key);
+ if(sip==NULL){
+ /*
+ We didn't find it.
+ Too bad, unfortunately there is not really much we can
+ do now since this means that we never saw the initial
+ request.
+ */
+ }
+ }
+
+
+ if(sip && sip->frame_req){
+ switch(si->cmd){
+ case SMB_COM_NT_CANCEL:
+ proto_tree_add_uint(htree, hf_smb_cancel_to,
+ tvb, 0, 0, sip->frame_req);
+ break;
+ case SMB_COM_TRANSACTION_SECONDARY:
+ case SMB_COM_TRANSACTION2_SECONDARY:
+ case SMB_COM_NT_TRANSACT_SECONDARY:
+ proto_tree_add_uint(htree, hf_smb_continuation_to,
+ tvb, 0, 0, sip->frame_req);
+ break;
+ }
+ } else {
+ switch(si->cmd){
+ case SMB_COM_NT_CANCEL:
+ proto_tree_add_text(htree, tvb, 0, 0,
+ "Cancellation to: <unknown frame>");
+ break;
+ case SMB_COM_TRANSACTION_SECONDARY:
+ case SMB_COM_TRANSACTION2_SECONDARY:
+ case SMB_COM_NT_TRANSACT_SECONDARY:
+ proto_tree_add_text(htree, tvb, 0, 0,
+ "Continuation to: <unknown frame>");
+ break;
+ }
+ }
+ } else { /* normal bidirectional request or response */
+ si->unidir = FALSE;
+
+ if(!pinfo->fd->flags.visited){
+ /* first see if we find an unmatched smb "equal" to
+ the current one
+ */
+ sip=g_hash_table_lookup(si->ct->unmatched, (void *)pid_mid);
+ if(sip!=NULL){
+ gboolean cmd_match=FALSE;
+
+ /*
+ * Make sure the SMB we found was the
+ * same command, or a different command
+ * that's another valid type of reply
+ * to that command.
+ */
+ if(si->cmd==sip->cmd){
+ cmd_match=TRUE;
+ }
+ else if(si->cmd==SMB_COM_NT_CANCEL){
+ cmd_match=TRUE;
+ }
+ else if((si->cmd==SMB_COM_TRANSACTION_SECONDARY)
+ && (sip->cmd==SMB_COM_TRANSACTION)){
+ cmd_match=TRUE;
+ }
+ else if((si->cmd==SMB_COM_TRANSACTION2_SECONDARY)
+ && (sip->cmd==SMB_COM_TRANSACTION2)){
+ cmd_match=TRUE;
+ }
+ else if((si->cmd==SMB_COM_NT_TRANSACT_SECONDARY)
+ && (sip->cmd==SMB_COM_NT_TRANSACT)){
+ cmd_match=TRUE;
+ }
+
+ if( (si->request) || (!cmd_match) ) {
+ /* If we are processing an SMB request but there was already
+ another "identical" smb resuest we had not matched yet.
+ This must mean that either we have a retransmission or that the
+ response to the previous one was lost and the client has reused
+ the MID for this conversation. In either case it's not much more
+ we can do than forget the old request and concentrate on the
+ present one instead.
+
+ We also do this cleanup if we see that the cmd in the original
+ request in sip->cmd is not compatible with the current cmd.
+ This is to prevent matching errors such as if there were two
+ SMBs of different cmds but with identical MID and PID values and
+ if ethereal lost the first reply and the second request.
+ */
+ g_hash_table_remove(si->ct->unmatched, (void *)pid_mid);
+ sip=NULL; /* XXX should free it as well */
+ } else {
+ /* we have found a response to some request we have seen earlier.
+ What we do now depends on whether this is the first response
+ to that request we see (id frame_res==0) or not.
+ */
+ if(sip->frame_res==0){
+ /* ok it is the first response we have seen to this packet */
+ sip->frame_res = pinfo->fd->num;
+ new_key = g_mem_chunk_alloc(smb_saved_info_key_chunk);
+ new_key->frame = sip->frame_res;
+ new_key->pid_mid = pid_mid;
+ g_hash_table_insert(si->ct->matched, new_key, sip);
+ } else {
+ /* We have already seen another response to this MID.
+ Since the MID in reality is only something like 10 bits
+ this probably means that we just have a MID that is being
+ reused due to the small MID space and that this is a new
+ command we did not see the original request for.
+ */
+ sip=NULL;
+ }
+ }
+ }
+ if(si->request){
+ sip = g_mem_chunk_alloc(smb_saved_info_chunk);
+ sip->frame_req = pinfo->fd->num;
+ sip->frame_res = 0;
+ sip->req_time.secs=pinfo->fd->abs_secs;
+ sip->req_time.nsecs=pinfo->fd->abs_usecs*1000;
+ sip->flags = 0;
+ if(g_hash_table_lookup(si->ct->tid_service, (void *)si->tid)
+ == (void *)TID_IPC) {
+ sip->flags |= SMB_SIF_TID_IS_IPC;
+ }
+ sip->cmd = si->cmd;
+ sip->extra_info = NULL;
+ g_hash_table_insert(si->ct->unmatched, (void *)pid_mid, sip);
+ new_key = g_mem_chunk_alloc(smb_saved_info_key_chunk);
+ new_key->frame = sip->frame_req;
+ new_key->pid_mid = pid_mid;
+ g_hash_table_insert(si->ct->matched, new_key, sip);
+ }
+ } else {
+ /* we have seen this packet before; check the
+ matching table.
+ If we haven't yet seen the reply, we won't
+ find the info for it; we don't need it, as
+ we only use it to save information, and, as
+ we've seen this packet before, we've already
+ saved the information.
+ */
+ key.frame = pinfo->fd->num;
+ key.pid_mid = pid_mid;
+ sip=g_hash_table_lookup(si->ct->matched, &key);
+ }
+ }
+
+ /*
+ * Pass the "sip" on to subdissectors through "si".
+ */
+ si->sip = sip;
+
+ if (sip != NULL) {
+ /*
+ * Put in fields for the frame number of the frame to which
+ * this is a response or the frame with the response to this
+ * frame - if we know the frame number (i.e., it's not 0).
+ */
+ if(si->request){
+ if (sip->frame_res != 0)
+ proto_tree_add_uint(htree, hf_smb_response_in, tvb, 0, 0, sip->frame_res);
+ } else {
+ if (sip->frame_req != 0) {
+ proto_tree_add_uint(htree, hf_smb_response_to, tvb, 0, 0, sip->frame_req);
+ ns.secs = pinfo->fd->abs_secs - sip->req_time.secs;
+ ns.nsecs = pinfo->fd->abs_usecs*1000 - sip->req_time.nsecs;
+ if(ns.nsecs<0){
+ ns.nsecs+=1000000000;
+ ns.secs--;
+ }
+ proto_tree_add_time(htree, hf_smb_time, tvb,
+ 0, 0, &ns);
+ }
+ }
+ }
+
+ /* smb command */
+ proto_tree_add_uint_format(htree, hf_smb_cmd, tvb, offset, 1, si->cmd, "SMB Command: %s (0x%02x)", decode_smb_name(si->cmd), si->cmd);
+ offset += 1;
+
+ if(flags2 & 0x4000){
+ /* handle NT 32 bit error code */
+
+ nt_status = tvb_get_letohl(tvb, offset);
+
+ proto_tree_add_item(htree, hf_smb_nt_status, tvb, offset, 4,
+ TRUE);
+ offset += 4;
+
+ } else {
+ /* handle DOS error code & class */
+ errclass = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(htree, hf_smb_error_class, tvb, offset, 1,
+ errclass);
+ offset += 1;
+
+ /* reserved byte */
+ proto_tree_add_item(htree, hf_smb_reserved, tvb, offset, 1, TRUE);
+ offset += 1;
+
+ /* error code */
+ /* XXX - the type of this field depends on the value of
+ * "errcls", so there is isn't a single value_string array
+ * fo it, so there can't be a single field for it.
+ */
+ errcode = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint_format(htree, hf_smb_error_code, tvb,
+ offset, 2, errcode, "Error Code: %s",
+ decode_smb_error(errclass, errcode));
+ offset += 2;
+ }
+
+ /* flags */
+ offset = dissect_smb_flags(tvb, htree, offset);
+
+ /* flags2 */
+ offset = dissect_smb_flags2(tvb, htree, offset);
+
+ /*
+ * The document at
+ *
+ * http://www.samba.org/samba/ftp/specs/smbpub.txt
+ *
+ * (a text version of "Microsoft Networks SMB FILE SHARING
+ * PROTOCOL, Document Version 6.0p") says that:
+ *
+ * the first 2 bytes of these 12 bytes are, for NT Create and X,
+ * the "High Part of PID";
+ *
+ * the next four bytes are reserved;
+ *
+ * the next four bytes are, for SMB-over-IPX (with no
+ * NetBIOS involved) two bytes of Session ID and two bytes
+ * of SequenceNumber.
+ *
+ * Network Monitor 2.x dissects the four bytes before the Session ID
+ * as a "Key", and the two bytes after the SequenceNumber as
+ * a "Group ID".
+ *
+ * The "High Part of PID" has been seen in calls other than NT
+ * Create and X, although most of them appear to be I/O on DCE RPC
+ * pipes opened with the NT Create and X in question.
+ */
+ proto_tree_add_item(htree, hf_smb_pid_high, tvb, offset, 2, TRUE);
+ offset += 2;
+
+ if (pinfo->ptype == PT_IPX &&
+ (pinfo->match_port == IPX_SOCKET_NWLINK_SMB_SERVER ||
+ pinfo->match_port == IPX_SOCKET_NWLINK_SMB_REDIR ||
+ pinfo->match_port == IPX_SOCKET_NWLINK_SMB_MESSENGER)) {
+ /*
+ * This is SMB-over-IPX.
+ * XXX - do we have to worry about "sequenced commands",
+ * as per the Samba document? They say that for
+ * "unsequenced commands" (with a sequence number of 0),
+ * the Mid must be unique, but perhaps the Mid doesn't
+ * have to be unique for sequenced commands. In at least
+ * one capture with SMB-over-IPX, however, the Mids
+ * are unique even for sequenced commands.
+ */
+ /* Key */
+ proto_tree_add_item(htree, hf_smb_key, tvb, offset, 4,
+ TRUE);
+ offset += 4;
+
+ /* Session ID */
+ proto_tree_add_item(htree, hf_smb_session_id, tvb, offset, 2,
+ TRUE);
+ offset += 2;
+
+ /* Sequence number */
+ proto_tree_add_item(htree, hf_smb_sequence_num, tvb, offset, 2,
+ TRUE);
+ offset += 2;
+
+ /* Group ID */
+ proto_tree_add_item(htree, hf_smb_group_id, tvb, offset, 2,
+ TRUE);
+ offset += 2;
+ } else {
+ /*
+ * According to http://ubiqx.org/cifs/SMB.html#SMB.4.2.1
+ * and http://ubiqx.org/cifs/SMB.html#SMB.5.5.1 the 8
+ * bytes after the "High part of PID" are an 8-byte
+ * signature ...
+ */
+ proto_tree_add_item(htree, hf_smb_sig, tvb, offset, 8, TRUE);
+ offset += 8;
+
+ proto_tree_add_item(htree, hf_smb_reserved, tvb, offset, 2, TRUE);
+ offset += 2;
+ }
+
+ /* TID */
+ proto_tree_add_uint(htree, hf_smb_tid, tvb, offset, 2, si->tid);
+ offset += 2;
+
+ /* PID */
+ proto_tree_add_uint(htree, hf_smb_pid, tvb, offset, 2, si->pid);
+ offset += 2;
+
+ /* UID */
+ proto_tree_add_uint(htree, hf_smb_uid, tvb, offset, 2, si->uid);
+ offset += 2;
+
+ /* MID */
+ proto_tree_add_uint(htree, hf_smb_mid, tvb, offset, 2, si->mid);
+ offset += 2;
+
+ pinfo->private_data = si;
+
+ /* tap the packet before the dissectors are called so we still get
+ the tap listener called even if there is an exception.
+ */
+ tap_queue_packet(smb_tap, pinfo, si);
+ dissect_smb_command(tvb, pinfo, offset, tree, si->cmd, TRUE);
+
+ /* Append error info from this packet to info string. */
+ if (!si->request && check_col(pinfo->cinfo, COL_INFO)) {
+ if (flags2 & 0x4000) {
+ /*
+ * The status is an NT status code; was there
+ * an error?
+ */
+ if ((nt_status & 0xC0000000) == 0xC0000000) {
+ /*
+ * Yes.
+ */
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", Error: %s",
+ val_to_str(nt_status, NT_errors,
+ "Unknown (0x%08X)"));
+ }
+ } else {
+ /*
+ * The status is a DOS error class and code; was
+ * there an error?
+ */
+ if (errclass != SMB_SUCCESS) {
+ /*
+ * Yes.
+ */
+ col_append_fstr(
+ pinfo->cinfo, COL_INFO, ", Error: %s",
+ decode_smb_error(errclass, errcode));
+ }
+ }
+ }
+}
+
+static gboolean
+dissect_smb_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+ /* must check that this really is a smb packet */
+ if (!tvb_bytes_exist(tvb, 0, 4))
+ return FALSE;
+
+ if( (tvb_get_guint8(tvb, 0) != 0xff)
+ || (tvb_get_guint8(tvb, 1) != 'S')
+ || (tvb_get_guint8(tvb, 2) != 'M')
+ || (tvb_get_guint8(tvb, 3) != 'B') ){
+ return FALSE;
+ }
+
+ dissect_smb(tvb, pinfo, parent_tree);
+ return TRUE;
+}
+
+void
+proto_register_smb(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_smb_cmd,
+ { "SMB Command", "smb.cmd", FT_UINT8, BASE_HEX,
+ VALS(smb_cmd_vals), 0x0, "SMB Command", HFILL }},
+
+ { &hf_smb_word_count,
+ { "Word Count (WCT)", "smb.wct", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Word Count, count of parameter words", HFILL }},
+
+ { &hf_smb_byte_count,
+ { "Byte Count (BCC)", "smb.bcc", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Byte Count, count of data bytes", HFILL }},
+
+ { &hf_smb_response_to,
+ { "Response to", "smb.response_to", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "This packet is a response to the packet in this frame", HFILL }},
+
+ { &hf_smb_time,
+ { "Time from request", "smb.time", FT_RELATIVE_TIME, BASE_NONE,
+ NULL, 0, "Time between Request and Response for SMB cmds", HFILL }},
+
+ { &hf_smb_response_in,
+ { "Response in", "smb.response_in", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "The response to this packet is in this packet", HFILL }},
+
+ { &hf_smb_continuation_to,
+ { "Continuation to", "smb.continuation_to", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "This packet is a continuation to the packet in this frame", HFILL }},
+
+ { &hf_smb_nt_status,
+ { "NT Status", "smb.nt_status", FT_UINT32, BASE_HEX,
+ VALS(NT_errors), 0, "NT Status code", HFILL }},
+
+ { &hf_smb_error_class,
+ { "Error Class", "smb.error_class", FT_UINT8, BASE_HEX,
+ VALS(errcls_types), 0, "DOS Error Class", HFILL }},
+
+ { &hf_smb_error_code,
+ { "Error Code", "smb.error_code", FT_UINT16, BASE_HEX,
+ NULL, 0, "DOS Error Code", HFILL }},
+
+ { &hf_smb_reserved,
+ { "Reserved", "smb.reserved", FT_BYTES, BASE_HEX,
+ NULL, 0, "Reserved bytes, must be zero", HFILL }},
+
+ { &hf_smb_sig,
+ { "Signature", "smb.signature", FT_BYTES, BASE_HEX,
+ NULL, 0, "Signature bytes", HFILL }},
+
+ { &hf_smb_key,
+ { "Key", "smb.key", FT_UINT32, BASE_HEX,
+ NULL, 0, "SMB-over-IPX Key", HFILL }},
+
+ { &hf_smb_session_id,
+ { "Session ID", "smb.sessid", FT_UINT16, BASE_DEC,
+ NULL, 0, "SMB-over-IPX Session ID", HFILL }},
+
+ { &hf_smb_sequence_num,
+ { "Sequence Number", "smb.sequence_num", FT_UINT16, BASE_DEC,
+ NULL, 0, "SMB-over-IPX Sequence Number", HFILL }},
+
+ { &hf_smb_group_id,
+ { "Group ID", "smb.group_id", FT_UINT16, BASE_DEC,
+ NULL, 0, "SMB-over-IPX Group ID", HFILL }},
+
+ { &hf_smb_pid,
+ { "Process ID", "smb.pid", FT_UINT16, BASE_DEC,
+ NULL, 0, "Process ID", HFILL }},
+
+ { &hf_smb_pid_high,
+ { "Process ID High", "smb.pid.high", FT_UINT16, BASE_DEC,
+ NULL, 0, "Process ID High Bytes", HFILL }},
+
+ { &hf_smb_tid,
+ { "Tree ID", "smb.tid", FT_UINT16, BASE_DEC,
+ NULL, 0, "Tree ID", HFILL }},
+
+ { &hf_smb_uid,
+ { "User ID", "smb.uid", FT_UINT16, BASE_DEC,
+ NULL, 0, "User ID", HFILL }},
+
+ { &hf_smb_mid,
+ { "Multiplex ID", "smb.mid", FT_UINT16, BASE_DEC,
+ NULL, 0, "Multiplex ID", HFILL }},
+
+ { &hf_smb_flags_lock,
+ { "Lock and Read", "smb.flags.lock", FT_BOOLEAN, 8,
+ TFS(&tfs_smb_flags_lock), 0x01, "Are Lock&Read and Write&Unlock operations supported?", HFILL }},
+
+ { &hf_smb_flags_receive_buffer,
+ { "Receive Buffer Posted", "smb.flags.receive_buffer", FT_BOOLEAN, 8,
+ TFS(&tfs_smb_flags_receive_buffer), 0x02, "Have receive buffers been reported?", HFILL }},
+
+ { &hf_smb_flags_caseless,
+ { "Case Sensitivity", "smb.flags.caseless", FT_BOOLEAN, 8,
+ TFS(&tfs_smb_flags_caseless), 0x08, "Are pathnames caseless or casesensitive?", HFILL }},
+
+ { &hf_smb_flags_canon,
+ { "Canonicalized Pathnames", "smb.flags.canon", FT_BOOLEAN, 8,
+ TFS(&tfs_smb_flags_canon), 0x10, "Are pathnames canonicalized?", HFILL }},
+
+ { &hf_smb_flags_oplock,
+ { "Oplocks", "smb.flags.oplock", FT_BOOLEAN, 8,
+ TFS(&tfs_smb_flags_oplock), 0x20, "Is an oplock requested/granted?", HFILL }},
+
+ { &hf_smb_flags_notify,
+ { "Notify", "smb.flags.notify", FT_BOOLEAN, 8,
+ TFS(&tfs_smb_flags_notify), 0x40, "Notify on open or all?", HFILL }},
+
+ { &hf_smb_flags_response,
+ { "Request/Response", "smb.flags.response", FT_BOOLEAN, 8,
+ TFS(&tfs_smb_flags_response), 0x80, "Is this a request or a response?", HFILL }},
+
+ { &hf_smb_flags2_long_names_allowed,
+ { "Long Names Allowed", "smb.flags2.long_names_allowed", FT_BOOLEAN, 16,
+ TFS(&tfs_smb_flags2_long_names_allowed), 0x0001, "Are long file names allowed in the response?", HFILL }},
+
+ { &hf_smb_flags2_ea,
+ { "Extended Attributes", "smb.flags2.ea", FT_BOOLEAN, 16,
+ TFS(&tfs_smb_flags2_ea), 0x0002, "Are extended attributes supported?", HFILL }},
+
+ { &hf_smb_flags2_sec_sig,
+ { "Security Signatures", "smb.flags2.sec_sig", FT_BOOLEAN, 16,
+ TFS(&tfs_smb_flags2_sec_sig), 0x0004, "Are security signatures supported?", HFILL }},
+
+ { &hf_smb_flags2_long_names_used,
+ { "Long Names Used", "smb.flags2.long_names_used", FT_BOOLEAN, 16,
+ TFS(&tfs_smb_flags2_long_names_used), 0x0040, "Are pathnames in this request long file names?", HFILL }},
+
+ { &hf_smb_flags2_esn,
+ { "Extended Security Negotiation", "smb.flags2.esn", FT_BOOLEAN, 16,
+ TFS(&tfs_smb_flags2_esn), 0x0800, "Is extended security negotiation supported?", HFILL }},
+
+ { &hf_smb_flags2_dfs,
+ { "Dfs", "smb.flags2.dfs", FT_BOOLEAN, 16,
+ TFS(&tfs_smb_flags2_dfs), 0x1000, "Can pathnames be resolved using Dfs?", HFILL }},
+
+ { &hf_smb_flags2_roe,
+ { "Execute-only Reads", "smb.flags2.roe", FT_BOOLEAN, 16,
+ TFS(&tfs_smb_flags2_roe), 0x2000, "Will reads be allowed for execute-only files?", HFILL }},
+
+ { &hf_smb_flags2_nt_error,
+ { "Error Code Type", "smb.flags2.nt_error", FT_BOOLEAN, 16,
+ TFS(&tfs_smb_flags2_nt_error), 0x4000, "Are error codes NT or DOS format?", HFILL }},
+
+ { &hf_smb_flags2_string,
+ { "Unicode Strings", "smb.flags2.string", FT_BOOLEAN, 16,
+ TFS(&tfs_smb_flags2_string), 0x8000, "Are strings ASCII or Unicode?", HFILL }},
+
+ { &hf_smb_buffer_format,
+ { "Buffer Format", "smb.buffer_format", FT_UINT8, BASE_DEC,
+ VALS(buffer_format_vals), 0x0, "Buffer Format, type of buffer", HFILL }},
+
+ { &hf_smb_dialect_name,
+ { "Name", "smb.dialect.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of dialect", HFILL }},
+
+ { &hf_smb_dialect_index,
+ { "Selected Index", "smb.dialect.index", FT_UINT16, BASE_DEC,
+ NULL, 0, "Index of selected dialect", HFILL }},
+
+ { &hf_smb_max_trans_buf_size,
+ { "Max Buffer Size", "smb.max_bufsize", FT_UINT32, BASE_DEC,
+ NULL, 0, "Maximum transmit buffer size", HFILL }},
+
+ { &hf_smb_max_mpx_count,
+ { "Max Mpx Count", "smb.max_mpx_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum pending multiplexed requests", HFILL }},
+
+ { &hf_smb_max_vcs_num,
+ { "Max VCs", "smb.max_vcs", FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum VCs between client and server", HFILL }},
+
+ { &hf_smb_session_key,
+ { "Session Key", "smb.session_key", FT_UINT32, BASE_HEX,
+ NULL, 0, "Unique token identifying this session", HFILL }},
+
+ { &hf_smb_server_timezone,
+ { "Time Zone", "smb.server_timezone", FT_INT16, BASE_DEC,
+ NULL, 0, "Current timezone at server.", HFILL }},
+
+ { &hf_smb_encryption_key_length,
+ { "Key Length", "smb.encryption_key_length", FT_UINT16, BASE_DEC,
+ NULL, 0, "Encryption key length (must be 0 if not LM2.1 dialect)", HFILL }},
+
+ { &hf_smb_encryption_key,
+ { "Encryption Key", "smb.encryption_key", FT_BYTES, BASE_HEX,
+ NULL, 0, "Challenge/Response Encryption Key (for LM2.1 dialect)", HFILL }},
+
+ { &hf_smb_primary_domain,
+ { "Primary Domain", "smb.primary_domain", FT_STRING, BASE_NONE,
+ NULL, 0, "The server's primary domain", HFILL }},
+
+ { &hf_smb_server,
+ { "Server", "smb.server", FT_STRING, BASE_NONE,
+ NULL, 0, "The name of the DC/server", HFILL }},
+
+ { &hf_smb_max_raw_buf_size,
+ { "Max Raw Buffer", "smb.max_raw", FT_UINT32, BASE_DEC,
+ NULL, 0, "Maximum raw buffer size", HFILL }},
+
+ { &hf_smb_server_guid,
+ { "Server GUID", "smb.server_guid", FT_BYTES, BASE_HEX,
+ NULL, 0, "Globally unique identifier for this server", HFILL }},
+
+ { &hf_smb_security_blob_len,
+ { "Security Blob Length", "smb.security_blob_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Security blob length", HFILL }},
+
+ { &hf_smb_security_blob,
+ { "Security Blob", "smb.security_blob", FT_BYTES, BASE_HEX,
+ NULL, 0, "Security blob", HFILL }},
+
+ { &hf_smb_sm_mode16,
+ { "Mode", "smb.sm.mode", FT_BOOLEAN, 16,
+ TFS(&tfs_sm_mode), SECURITY_MODE_MODE, "User or Share security mode?", HFILL }},
+
+ { &hf_smb_sm_password16,
+ { "Password", "smb.sm.password", FT_BOOLEAN, 16,
+ TFS(&tfs_sm_password), SECURITY_MODE_PASSWORD, "Encrypted or plaintext passwords?", HFILL }},
+
+ { &hf_smb_sm_mode,
+ { "Mode", "smb.sm.mode", FT_BOOLEAN, 8,
+ TFS(&tfs_sm_mode), SECURITY_MODE_MODE, "User or Share security mode?", HFILL }},
+
+ { &hf_smb_sm_password,
+ { "Password", "smb.sm.password", FT_BOOLEAN, 8,
+ TFS(&tfs_sm_password), SECURITY_MODE_PASSWORD, "Encrypted or plaintext passwords?", HFILL }},
+
+ { &hf_smb_sm_signatures,
+ { "Signatures", "smb.sm.signatures", FT_BOOLEAN, 8,
+ TFS(&tfs_sm_signatures), SECURITY_MODE_SIGNATURES, "Are security signatures enabled?", HFILL }},
+
+ { &hf_smb_sm_sig_required,
+ { "Sig Req", "smb.sm.sig_required", FT_BOOLEAN, 8,
+ TFS(&tfs_sm_sig_required), SECURITY_MODE_SIG_REQUIRED, "Are security signatures required?", HFILL }},
+
+ { &hf_smb_rm_read,
+ { "Read Raw", "smb.rm.read", FT_BOOLEAN, 16,
+ TFS(&tfs_rm_read), RAWMODE_READ, "Is Read Raw supported?", HFILL }},
+
+ { &hf_smb_rm_write,
+ { "Write Raw", "smb.rm.write", FT_BOOLEAN, 16,
+ TFS(&tfs_rm_write), RAWMODE_WRITE, "Is Write Raw supported?", HFILL }},
+
+ { &hf_smb_server_date_time,
+ { "Server Date and Time", "smb.server_date_time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Current date and time at server", HFILL }},
+
+ { &hf_smb_server_smb_date,
+ { "Server Date", "smb.server_date_time.smb_date", FT_UINT16, BASE_HEX,
+ NULL, 0, "Current date at server, SMB_DATE format", HFILL }},
+
+ { &hf_smb_server_smb_time,
+ { "Server Time", "smb.server_date_time.smb_time", FT_UINT16, BASE_HEX,
+ NULL, 0, "Current time at server, SMB_TIME format", HFILL }},
+
+ { &hf_smb_server_cap_raw_mode,
+ { "Raw Mode", "smb.server_cap.raw_mode", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_raw_mode), SERVER_CAP_RAW_MODE, "Are Raw Read and Raw Write supported?", HFILL }},
+
+ { &hf_smb_server_cap_mpx_mode,
+ { "MPX Mode", "smb.server_cap.mpx_mode", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_mpx_mode), SERVER_CAP_MPX_MODE, "Are Read Mpx and Write Mpx supported?", HFILL }},
+
+ { &hf_smb_server_cap_unicode,
+ { "Unicode", "smb.server_cap.unicode", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_unicode), SERVER_CAP_UNICODE, "Are Unicode strings supported?", HFILL }},
+
+ { &hf_smb_server_cap_large_files,
+ { "Large Files", "smb.server_cap.large_files", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_large_files), SERVER_CAP_LARGE_FILES, "Are large files (>4GB) supported?", HFILL }},
+
+ { &hf_smb_server_cap_nt_smbs,
+ { "NT SMBs", "smb.server_cap.nt_smbs", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_nt_smbs), SERVER_CAP_NT_SMBS, "Are NT SMBs supported?", HFILL }},
+
+ { &hf_smb_server_cap_rpc_remote_apis,
+ { "RPC Remote APIs", "smb.server_cap.rpc_remote_apis", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_rpc_remote_apis), SERVER_CAP_RPC_REMOTE_APIS, "Are RPC Remote APIs supported?", HFILL }},
+
+ { &hf_smb_server_cap_nt_status,
+ { "NT Status Codes", "smb.server_cap.nt_status", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_nt_status), SERVER_CAP_STATUS32, "Are NT Status Codes supported?", HFILL }},
+
+ { &hf_smb_server_cap_level_ii_oplocks,
+ { "Level 2 Oplocks", "smb.server_cap.level_2_oplocks", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_level_ii_oplocks), SERVER_CAP_LEVEL_II_OPLOCKS, "Are Level 2 oplocks supported?", HFILL }},
+
+ { &hf_smb_server_cap_lock_and_read,
+ { "Lock and Read", "smb.server_cap.lock_and_read", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_lock_and_read), SERVER_CAP_LOCK_AND_READ, "Is Lock and Read supported?", HFILL }},
+
+ { &hf_smb_server_cap_nt_find,
+ { "NT Find", "smb.server_cap.nt_find", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_nt_find), SERVER_CAP_NT_FIND, "Is NT Find supported?", HFILL }},
+
+ { &hf_smb_server_cap_dfs,
+ { "Dfs", "smb.server_cap.dfs", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_dfs), SERVER_CAP_DFS, "Is Dfs supported?", HFILL }},
+
+ { &hf_smb_server_cap_infolevel_passthru,
+ { "Infolevel Passthru", "smb.server_cap.infolevel_passthru", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_infolevel_passthru), SERVER_CAP_INFOLEVEL_PASSTHRU, "Is NT information level request passthrough supported?", HFILL }},
+
+ { &hf_smb_server_cap_large_readx,
+ { "Large ReadX", "smb.server_cap.large_readx", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_large_readx), SERVER_CAP_LARGE_READX, "Is Large Read andX supported?", HFILL }},
+
+ { &hf_smb_server_cap_large_writex,
+ { "Large WriteX", "smb.server_cap.large_writex", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_large_writex), SERVER_CAP_LARGE_WRITEX, "Is Large Write andX supported?", HFILL }},
+
+ { &hf_smb_server_cap_unix,
+ { "UNIX", "smb.server_cap.unix", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_unix), SERVER_CAP_UNIX , "Are UNIX extensions supported?", HFILL }},
+
+ { &hf_smb_server_cap_reserved,
+ { "Reserved", "smb.server_cap.reserved", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_reserved), SERVER_CAP_RESERVED, "RESERVED", HFILL }},
+
+ { &hf_smb_server_cap_bulk_transfer,
+ { "Bulk Transfer", "smb.server_cap.bulk_transfer", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_bulk_transfer), SERVER_CAP_BULK_TRANSFER, "Are Bulk Read and Bulk Write supported?", HFILL }},
+
+ { &hf_smb_server_cap_compressed_data,
+ { "Compressed Data", "smb.server_cap.compressed_data", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_compressed_data), SERVER_CAP_COMPRESSED_DATA, "Is compressed data transfer supported?", HFILL }},
+
+ { &hf_smb_server_cap_extended_security,
+ { "Extended Security", "smb.server_cap.extended_security", FT_BOOLEAN, 32,
+ TFS(&tfs_server_cap_extended_security), SERVER_CAP_EXTENDED_SECURITY, "Are Extended security exchanges supported?", HFILL }},
+
+ { &hf_smb_system_time,
+ { "System Time", "smb.system.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "System Time", HFILL }},
+
+ { &hf_smb_unknown,
+ { "Unknown Data", "smb.unknown", FT_BYTES, BASE_HEX,
+ NULL, 0, "Unknown Data. Should be implemented by someone", HFILL }},
+
+ { &hf_smb_dir_name,
+ { "Directory", "smb.dir_name", FT_STRING, BASE_NONE,
+ NULL, 0, "SMB Directory Name", HFILL }},
+
+ { &hf_smb_echo_count,
+ { "Echo Count", "smb.echo.count", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of times to echo data back", HFILL }},
+
+ { &hf_smb_echo_data,
+ { "Echo Data", "smb.echo.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Data for SMB Echo Request/Response", HFILL }},
+
+ { &hf_smb_echo_seq_num,
+ { "Echo Seq Num", "smb.echo.seq_num", FT_UINT16, BASE_DEC,
+ NULL, 0, "Sequence number for this echo response", HFILL }},
+
+ { &hf_smb_max_buf_size,
+ { "Max Buffer", "smb.max_buf", FT_UINT16, BASE_DEC,
+ NULL, 0, "Max client buffer size", HFILL }},
+
+ { &hf_smb_path,
+ { "Path", "smb.path", FT_STRING, BASE_NONE,
+ NULL, 0, "Path. Server name and share name", HFILL }},
+
+ { &hf_smb_service,
+ { "Service", "smb.service", FT_STRING, BASE_NONE,
+ NULL, 0, "Service name", HFILL }},
+
+ { &hf_smb_password,
+ { "Password", "smb.password", FT_BYTES, BASE_NONE,
+ NULL, 0, "Password", HFILL }},
+
+ { &hf_smb_ansi_password,
+ { "ANSI Password", "smb.ansi_password", FT_BYTES, BASE_NONE,
+ NULL, 0, "ANSI Password", HFILL }},
+
+ { &hf_smb_unicode_password,
+ { "Unicode Password", "smb.unicode_password", FT_BYTES, BASE_NONE,
+ NULL, 0, "Unicode Password", HFILL }},
+
+ { &hf_smb_move_flags_file,
+ { "Must be file", "smb.move.flags.file", FT_BOOLEAN, 16,
+ TFS(&tfs_mf_file), 0x0001, "Must target be a file?", HFILL }},
+
+ { &hf_smb_move_flags_dir,
+ { "Must be directory", "smb.move.flags.dir", FT_BOOLEAN, 16,
+ TFS(&tfs_mf_dir), 0x0002, "Must target be a directory?", HFILL }},
+
+ { &hf_smb_move_flags_verify,
+ { "Verify writes", "smb.move.flags.verify", FT_BOOLEAN, 16,
+ TFS(&tfs_mf_verify), 0x0010, "Verify all writes?", HFILL }},
+
+ { &hf_smb_files_moved,
+ { "Files Moved", "smb.files_moved", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of files moved", HFILL }},
+
+ { &hf_smb_copy_flags_file,
+ { "Must be file", "smb.copy.flags.file", FT_BOOLEAN, 16,
+ TFS(&tfs_mf_file), 0x0001, "Must target be a file?", HFILL }},
+
+ { &hf_smb_copy_flags_dir,
+ { "Must be directory", "smb.copy.flags.dir", FT_BOOLEAN, 16,
+ TFS(&tfs_mf_dir), 0x0002, "Must target be a directory?", HFILL }},
+
+ { &hf_smb_copy_flags_dest_mode,
+ { "Destination mode", "smb.copy.flags.dest_mode", FT_BOOLEAN, 16,
+ TFS(&tfs_cf_mode), 0x0004, "Is destination in ASCII?", HFILL }},
+
+ { &hf_smb_copy_flags_source_mode,
+ { "Source mode", "smb.copy.flags.source_mode", FT_BOOLEAN, 16,
+ TFS(&tfs_cf_mode), 0x0008, "Is source in ASCII?", HFILL }},
+
+ { &hf_smb_copy_flags_verify,
+ { "Verify writes", "smb.copy.flags.verify", FT_BOOLEAN, 16,
+ TFS(&tfs_mf_verify), 0x0010, "Verify all writes?", HFILL }},
+
+ { &hf_smb_copy_flags_tree_copy,
+ { "Tree copy", "smb.copy.flags.tree_copy", FT_BOOLEAN, 16,
+ TFS(&tfs_cf_tree_copy), 0x0010, "Is copy a tree copy?", HFILL }},
+
+ { &hf_smb_copy_flags_ea_action,
+ { "EA action if EAs not supported on dest", "smb.copy.flags.ea_action", FT_BOOLEAN, 16,
+ TFS(&tfs_cf_ea_action), 0x0010, "Fail copy if source file has EAs and dest doesn't support EAs?", HFILL }},
+
+ { &hf_smb_count,
+ { "Count", "smb.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Count number of items/bytes", HFILL }},
+
+ { &hf_smb_count_low,
+ { "Count Low", "smb.count_low", FT_UINT16, BASE_DEC,
+ NULL, 0, "Count number of items/bytes, Low 16 bits", HFILL }},
+
+ { &hf_smb_count_high,
+ { "Count High (multiply with 64K)", "smb.count_high", FT_UINT16, BASE_DEC,
+ NULL, 0, "Count number of items/bytes, High 16 bits", HFILL }},
+
+ { &hf_smb_file_name,
+ { "File Name", "smb.file", FT_STRING, BASE_NONE,
+ NULL, 0, "File Name", HFILL }},
+
+ { &hf_smb_open_function_create,
+ { "Create", "smb.open.function.create", FT_BOOLEAN, 16,
+ TFS(&tfs_of_create), 0x0010, "Create file if it doesn't exist?", HFILL }},
+
+ { &hf_smb_open_function_open,
+ { "Open", "smb.open.function.open", FT_UINT16, BASE_DEC,
+ VALS(of_open), 0x0003, "Action to be taken on open if file exists", HFILL }},
+
+ { &hf_smb_fid,
+ { "FID", "smb.fid", FT_UINT16, BASE_HEX,
+ NULL, 0, "FID: File ID", HFILL }},
+
+ { &hf_smb_file_attr_read_only_16bit,
+ { "Read Only", "smb.file_attribute.read_only", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_read_only), SMB_FILE_ATTRIBUTE_READ_ONLY, "READ ONLY file attribute", HFILL }},
+
+ { &hf_smb_file_attr_read_only_8bit,
+ { "Read Only", "smb.file_attribute.read_only", FT_BOOLEAN, 8,
+ TFS(&tfs_file_attribute_read_only), SMB_FILE_ATTRIBUTE_READ_ONLY, "READ ONLY file attribute", HFILL }},
+
+ { &hf_smb_file_attr_hidden_16bit,
+ { "Hidden", "smb.file_attribute.hidden", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_hidden), SMB_FILE_ATTRIBUTE_HIDDEN, "HIDDEN file attribute", HFILL }},
+
+ { &hf_smb_file_attr_hidden_8bit,
+ { "Hidden", "smb.file_attribute.hidden", FT_BOOLEAN, 8,
+ TFS(&tfs_file_attribute_hidden), SMB_FILE_ATTRIBUTE_HIDDEN, "HIDDEN file attribute", HFILL }},
+
+ { &hf_smb_file_attr_system_16bit,
+ { "System", "smb.file_attribute.system", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_system), SMB_FILE_ATTRIBUTE_SYSTEM, "SYSTEM file attribute", HFILL }},
+
+ { &hf_smb_file_attr_system_8bit,
+ { "System", "smb.file_attribute.system", FT_BOOLEAN, 8,
+ TFS(&tfs_file_attribute_system), SMB_FILE_ATTRIBUTE_SYSTEM, "SYSTEM file attribute", HFILL }},
+
+ { &hf_smb_file_attr_volume_16bit,
+ { "Volume ID", "smb.file_attribute.volume", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_volume), SMB_FILE_ATTRIBUTE_VOLUME, "VOLUME file attribute", HFILL }},
+
+ { &hf_smb_file_attr_volume_8bit,
+ { "Volume ID", "smb.file_attribute.volume", FT_BOOLEAN, 8,
+ TFS(&tfs_file_attribute_volume), SMB_FILE_ATTRIBUTE_VOLUME, "VOLUME ID file attribute", HFILL }},
+
+ { &hf_smb_file_attr_directory_16bit,
+ { "Directory", "smb.file_attribute.directory", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_directory), SMB_FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY file attribute", HFILL }},
+
+ { &hf_smb_file_attr_directory_8bit,
+ { "Directory", "smb.file_attribute.directory", FT_BOOLEAN, 8,
+ TFS(&tfs_file_attribute_directory), SMB_FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY file attribute", HFILL }},
+
+ { &hf_smb_file_attr_archive_16bit,
+ { "Archive", "smb.file_attribute.archive", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_archive), SMB_FILE_ATTRIBUTE_ARCHIVE, "ARCHIVE file attribute", HFILL }},
+
+ { &hf_smb_file_attr_archive_8bit,
+ { "Archive", "smb.file_attribute.archive", FT_BOOLEAN, 8,
+ TFS(&tfs_file_attribute_archive), SMB_FILE_ATTRIBUTE_ARCHIVE, "ARCHIVE file attribute", HFILL }},
+
+ { &hf_smb_file_attr_device,
+ { "Device", "smb.file_attribute.device", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_device), SMB_FILE_ATTRIBUTE_DEVICE, "Is this file a device?", HFILL }},
+
+ { &hf_smb_file_attr_normal,
+ { "Normal", "smb.file_attribute.normal", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_normal), SMB_FILE_ATTRIBUTE_NORMAL, "Is this a normal file?", HFILL }},
+
+ { &hf_smb_file_attr_temporary,
+ { "Temporary", "smb.file_attribute.temporary", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_temporary), SMB_FILE_ATTRIBUTE_TEMPORARY, "Is this a temporary file?", HFILL }},
+
+ { &hf_smb_file_attr_sparse,
+ { "Sparse", "smb.file_attribute.sparse", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_sparse), SMB_FILE_ATTRIBUTE_SPARSE, "Is this a sparse file?", HFILL }},
+
+ { &hf_smb_file_attr_reparse,
+ { "Reparse Point", "smb.file_attribute.reparse", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_reparse), SMB_FILE_ATTRIBUTE_REPARSE, "Does this file have an associated reparse point?", HFILL }},
+
+ { &hf_smb_file_attr_compressed,
+ { "Compressed", "smb.file_attribute.compressed", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_compressed), SMB_FILE_ATTRIBUTE_COMPRESSED, "Is this file compressed?", HFILL }},
+
+ { &hf_smb_file_attr_offline,
+ { "Offline", "smb.file_attribute.offline", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_offline), SMB_FILE_ATTRIBUTE_OFFLINE, "Is this file offline?", HFILL }},
+
+ { &hf_smb_file_attr_not_content_indexed,
+ { "Content Indexed", "smb.file_attribute.not_content_indexed", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_not_content_indexed), SMB_FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, "May this file be indexed by the content indexing service", HFILL }},
+
+ { &hf_smb_file_attr_encrypted,
+ { "Encrypted", "smb.file_attribute.encrypted", FT_BOOLEAN, 16,
+ TFS(&tfs_file_attribute_encrypted), SMB_FILE_ATTRIBUTE_ENCRYPTED, "Is this file encrypted?", HFILL }},
+
+ { &hf_smb_file_size,
+ { "File Size", "smb.file_size", FT_UINT32, BASE_DEC,
+ NULL, 0, "File Size", HFILL }},
+
+ { &hf_smb_search_attribute_read_only,
+ { "Read Only", "smb.search.attribute.read_only", FT_BOOLEAN, 16,
+ TFS(&tfs_search_attribute_read_only), SMB_FILE_ATTRIBUTE_READ_ONLY, "READ ONLY search attribute", HFILL }},
+
+ { &hf_smb_search_attribute_hidden,
+ { "Hidden", "smb.search.attribute.hidden", FT_BOOLEAN, 16,
+ TFS(&tfs_search_attribute_hidden), SMB_FILE_ATTRIBUTE_HIDDEN, "HIDDEN search attribute", HFILL }},
+
+ { &hf_smb_search_attribute_system,
+ { "System", "smb.search.attribute.system", FT_BOOLEAN, 16,
+ TFS(&tfs_search_attribute_system), SMB_FILE_ATTRIBUTE_SYSTEM, "SYSTEM search attribute", HFILL }},
+
+ { &hf_smb_search_attribute_volume,
+ { "Volume ID", "smb.search.attribute.volume", FT_BOOLEAN, 16,
+ TFS(&tfs_search_attribute_volume), SMB_FILE_ATTRIBUTE_VOLUME, "VOLUME ID search attribute", HFILL }},
+
+ { &hf_smb_search_attribute_directory,
+ { "Directory", "smb.search.attribute.directory", FT_BOOLEAN, 16,
+ TFS(&tfs_search_attribute_directory), SMB_FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY search attribute", HFILL }},
+
+ { &hf_smb_search_attribute_archive,
+ { "Archive", "smb.search.attribute.archive", FT_BOOLEAN, 16,
+ TFS(&tfs_search_attribute_archive), SMB_FILE_ATTRIBUTE_ARCHIVE, "ARCHIVE search attribute", HFILL }},
+
+ { &hf_smb_access_mode,
+ { "Access Mode", "smb.access.mode", FT_UINT16, BASE_DEC,
+ VALS(da_access_vals), 0x0007, "Access Mode", HFILL }},
+
+ { &hf_smb_access_sharing,
+ { "Sharing Mode", "smb.access.sharing", FT_UINT16, BASE_DEC,
+ VALS(da_sharing_vals), 0x0070, "Sharing Mode", HFILL }},
+
+ { &hf_smb_access_locality,
+ { "Locality", "smb.access.locality", FT_UINT16, BASE_DEC,
+ VALS(da_locality_vals), 0x0700, "Locality of reference", HFILL }},
+
+ { &hf_smb_access_caching,
+ { "Caching", "smb.access.caching", FT_BOOLEAN, 16,
+ TFS(&tfs_da_caching), 0x1000, "Caching mode?", HFILL }},
+
+ { &hf_smb_access_writetru,
+ { "Writethrough", "smb.access.writethrough", FT_BOOLEAN, 16,
+ TFS(&tfs_da_writetru), 0x4000, "Writethrough mode?", HFILL }},
+
+ { &hf_smb_create_time,
+ { "Created", "smb.create.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Creation Time", HFILL }},
+
+ { &hf_smb_modify_time,
+ { "Modified", "smb.modify.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Modification Time", HFILL }},
+
+ { &hf_smb_backup_time,
+ { "Backed-up", "smb.backup.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Backup time", HFILL}},
+
+ { &hf_smb_mac_alloc_block_count,
+ { "Allocation Block Count", "smb.alloc.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Allocation Block Count", HFILL}},
+
+ { &hf_smb_mac_alloc_block_size,
+ { "Allocation Block Count", "smb.alloc.size", FT_UINT32, BASE_DEC,
+ NULL, 0, "Allocation Block Size", HFILL}},
+
+ { &hf_smb_mac_free_block_count,
+ { "Free Block Count", "smb.free_block.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Free Block Count", HFILL}},
+
+ { &hf_smb_mac_root_file_count,
+ { "Root File Count", "smb.root.file.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Root File Count", HFILL}},
+
+ { &hf_smb_mac_root_dir_count,
+ { "Root Directory Count", "smb.root.dir.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Root Directory Count", HFILL}},
+
+ { &hf_smb_mac_file_count,
+ { "Root File Count", "smb.file.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "File Count", HFILL}},
+
+ { &hf_smb_mac_dir_count,
+ { "Root Directory Count", "smb.dir.count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Directory Count", HFILL}},
+
+ { &hf_smb_mac_support_flags,
+ { "Mac Support Flags", "smb.mac.support.flags", FT_UINT32, BASE_DEC,
+ NULL, 0, "Mac Support Flags", HFILL}},
+
+ { &hf_smb_mac_sup_access_ctrl,
+ { "Mac Access Control", "smb.mac.access_control", FT_BOOLEAN, 32,
+ TFS(&tfs_smb_mac_access_ctrl), 0x0010, "Are Mac Access Control Supported", HFILL }},
+
+ { &hf_smb_mac_sup_getset_comments,
+ { "Get Set Comments", "smb.mac.get_set_comments", FT_BOOLEAN, 32,
+ TFS(&tfs_smb_mac_getset_comments), 0x0020, "Are Mac Get Set Comments supported?", HFILL }},
+
+ { &hf_smb_mac_sup_desktopdb_calls,
+ { "Desktop DB Calls", "smb.mac.desktop_db_calls", FT_BOOLEAN, 32,
+ TFS(&tfs_smb_mac_desktopdb_calls), 0x0040, "Are Macintosh Desktop DB Calls Supported?", HFILL }},
+
+ { &hf_smb_mac_sup_unique_ids,
+ { "Macintosh Unique IDs", "smb.mac.uids", FT_BOOLEAN, 32,
+ TFS(&tfs_smb_mac_unique_ids), 0x0080, "Are Unique IDs supported", HFILL }},
+
+ { &hf_smb_mac_sup_streams,
+ { "Mac Streams", "smb.mac.streams_support", FT_BOOLEAN, 32,
+ TFS(&tfs_smb_mac_streams), 0x0100, "Are Mac Extensions and streams supported?", HFILL }},
+
+ { &hf_smb_create_dos_date,
+ { "Create Date", "smb.create.smb.date", FT_UINT16, BASE_HEX,
+ NULL, 0, "Create Date, SMB_DATE format", HFILL }},
+
+ { &hf_smb_create_dos_time,
+ { "Create Time", "smb.create.smb.time", FT_UINT16, BASE_HEX,
+ NULL, 0, "Create Time, SMB_TIME format", HFILL }},
+
+ { &hf_smb_last_write_time,
+ { "Last Write", "smb.last_write.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Time this file was last written to", HFILL }},
+
+ { &hf_smb_last_write_dos_date,
+ { "Last Write Date", "smb.last_write.smb.date", FT_UINT16, BASE_HEX,
+ NULL, 0, "Last Write Date, SMB_DATE format", HFILL }},
+
+ { &hf_smb_last_write_dos_time,
+ { "Last Write Time", "smb.last_write.smb.time", FT_UINT16, BASE_HEX,
+ NULL, 0, "Last Write Time, SMB_TIME format", HFILL }},
+
+ { &hf_smb_old_file_name,
+ { "Old File Name", "smb.file", FT_STRING, BASE_NONE,
+ NULL, 0, "Old File Name (When renaming a file)", HFILL }},
+
+ { &hf_smb_offset,
+ { "Offset", "smb.offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Offset in file", HFILL }},
+
+ { &hf_smb_remaining,
+ { "Remaining", "smb.remaining", FT_UINT32, BASE_DEC,
+ NULL, 0, "Remaining number of bytes", HFILL }},
+
+ { &hf_smb_padding,
+ { "Padding", "smb.padding", FT_BYTES, BASE_HEX,
+ NULL, 0, "Padding or unknown data", HFILL }},
+
+ { &hf_smb_file_data,
+ { "File Data", "smb.file_data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Data read/written to the file", HFILL }},
+
+ { &hf_smb_mac_fndrinfo,
+ { "Finder Info", "smb.mac.finderinfo", FT_BYTES, BASE_HEX,
+ NULL, 0, "Finder Info", HFILL}},
+
+ { &hf_smb_total_data_len,
+ { "Total Data Length", "smb.total_data_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Total length of data", HFILL }},
+
+ { &hf_smb_data_len,
+ { "Data Length", "smb.data_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of data", HFILL }},
+
+ { &hf_smb_data_len_low,
+ { "Data Length Low", "smb.data_len_low", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of data, Low 16 bits", HFILL }},
+
+ { &hf_smb_data_len_high,
+ { "Data Length High (multiply with 64K)", "smb.data_len_high", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of data, High 16 bits", HFILL }},
+
+ { &hf_smb_seek_mode,
+ { "Seek Mode", "smb.seek_mode", FT_UINT16, BASE_DEC,
+ VALS(seek_mode_vals), 0, "Seek Mode, what type of seek", HFILL }},
+
+ { &hf_smb_access_time,
+ { "Last Access", "smb.access.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Last Access Time", HFILL }},
+
+ { &hf_smb_access_dos_date,
+ { "Last Access Date", "smb.access.smb.date", FT_UINT16, BASE_HEX,
+ NULL, 0, "Last Access Date, SMB_DATE format", HFILL }},
+
+ { &hf_smb_access_dos_time,
+ { "Last Access Time", "smb.access.smb.time", FT_UINT16, BASE_HEX,
+ NULL, 0, "Last Access Time, SMB_TIME format", HFILL }},
+
+ { &hf_smb_data_size,
+ { "Data Size", "smb.data_size", FT_UINT32, BASE_DEC,
+ NULL, 0, "Data Size", HFILL }},
+
+ { &hf_smb_alloc_size,
+ { "Allocation Size", "smb.alloc_size", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of bytes to reserve on create or truncate", HFILL }},
+
+ { &hf_smb_max_count,
+ { "Max Count", "smb.maxcount", FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum Count", HFILL }},
+
+ { &hf_smb_max_count_low,
+ { "Max Count Low", "smb.maxcount_low", FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum Count, Low 16 bits", HFILL }},
+
+ { &hf_smb_max_count_high,
+ { "Max Count High (multiply with 64K)", "smb.maxcount_high", FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum Count, High 16 bits", HFILL }},
+
+ { &hf_smb_min_count,
+ { "Min Count", "smb.mincount", FT_UINT16, BASE_DEC,
+ NULL, 0, "Minimum Count", HFILL }},
+
+ { &hf_smb_timeout,
+ { "Timeout", "smb.timeout", FT_UINT32, BASE_DEC,
+ NULL, 0, "Timeout in miliseconds", HFILL }},
+
+ { &hf_smb_high_offset,
+ { "High Offset", "smb.offset_high", FT_UINT32, BASE_DEC,
+ NULL, 0, "High 32 Bits Of File Offset", HFILL }},
+
+ { &hf_smb_units,
+ { "Total Units", "smb.units", FT_UINT16, BASE_DEC,
+ NULL, 0, "Total number of units at server", HFILL }},
+
+ { &hf_smb_bpu,
+ { "Blocks Per Unit", "smb.bpu", FT_UINT16, BASE_DEC,
+ NULL, 0, "Blocks per unit at server", HFILL }},
+
+ { &hf_smb_blocksize,
+ { "Block Size", "smb.blocksize", FT_UINT16, BASE_DEC,
+ NULL, 0, "Block size (in bytes) at server", HFILL }},
+
+ { &hf_smb_freeunits,
+ { "Free Units", "smb.free_units", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of free units at server", HFILL }},
+
+ { &hf_smb_data_offset,
+ { "Data Offset", "smb.data_offset", FT_UINT16, BASE_DEC,
+ NULL, 0, "Data Offset", HFILL }},
+
+ { &hf_smb_dcm,
+ { "Data Compaction Mode", "smb.dcm", FT_UINT16, BASE_DEC,
+ NULL, 0, "Data Compaction Mode", HFILL }},
+
+ { &hf_smb_request_mask,
+ { "Request Mask", "smb.request.mask", FT_UINT32, BASE_HEX,
+ NULL, 0, "Connectionless mode mask", HFILL }},
+
+ { &hf_smb_response_mask,
+ { "Response Mask", "smb.response.mask", FT_UINT32, BASE_HEX,
+ NULL, 0, "Connectionless mode mask", HFILL }},
+
+ { &hf_smb_search_id,
+ { "Search ID", "smb.search_id", FT_UINT16, BASE_HEX,
+ NULL, 0, "Search ID, handle for find operations", HFILL }},
+
+ { &hf_smb_write_mode_write_through,
+ { "Write Through", "smb.write.mode.write_through", FT_BOOLEAN, 16,
+ TFS(&tfs_write_mode_write_through), WRITE_MODE_WRITE_THROUGH, "Write through mode requested?", HFILL }},
+
+ { &hf_smb_write_mode_return_remaining,
+ { "Return Remaining", "smb.write.mode.return_remaining", FT_BOOLEAN, 16,
+ TFS(&tfs_write_mode_return_remaining), WRITE_MODE_RETURN_REMAINING, "Return remaining data responses?", HFILL }},
+
+ { &hf_smb_write_mode_raw,
+ { "Write Raw", "smb.write.mode.raw", FT_BOOLEAN, 16,
+ TFS(&tfs_write_mode_raw), WRITE_MODE_RAW, "Use WriteRawNamedPipe?", HFILL }},
+
+ { &hf_smb_write_mode_message_start,
+ { "Message Start", "smb.write.mode.message_start", FT_BOOLEAN, 16,
+ TFS(&tfs_write_mode_message_start), WRITE_MODE_MESSAGE_START, "Is this the start of a message?", HFILL }},
+
+ { &hf_smb_write_mode_connectionless,
+ { "Connectionless", "smb.write.mode.connectionless", FT_BOOLEAN, 16,
+ TFS(&tfs_write_mode_connectionless), WRITE_MODE_CONNECTIONLESS, "Connectionless mode requested?", HFILL }},
+
+ { &hf_smb_resume_key_len,
+ { "Resume Key Length", "smb.resume.key_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Resume Key length", HFILL }},
+
+ { &hf_smb_resume_find_id,
+ { "Find ID", "smb.resume.find_id", FT_UINT8, BASE_HEX,
+ NULL, 0, "Handle for Find operation", HFILL }},
+
+ { &hf_smb_resume_server_cookie,
+ { "Server Cookie", "smb.resume.server.cookie", FT_BYTES, BASE_HEX,
+ NULL, 0, "Cookie, must not be modified by the client", HFILL }},
+
+ { &hf_smb_resume_client_cookie,
+ { "Client Cookie", "smb.resume.client.cookie", FT_BYTES, BASE_HEX,
+ NULL, 0, "Cookie, must not be modified by the server", HFILL }},
+
+ { &hf_smb_andxoffset,
+ { "AndXOffset", "smb.andxoffset", FT_UINT16, BASE_DEC,
+ NULL, 0, "Offset to next command in this SMB packet", HFILL }},
+
+ { &hf_smb_lock_type_large,
+ { "Large Files", "smb.lock.type.large", FT_BOOLEAN, 8,
+ TFS(&tfs_lock_type_large), 0x10, "Large file locking requested?", HFILL }},
+
+ { &hf_smb_lock_type_cancel,
+ { "Cancel", "smb.lock.type.cancel", FT_BOOLEAN, 8,
+ TFS(&tfs_lock_type_cancel), 0x08, "Cancel outstanding lock requests?", HFILL }},
+
+ { &hf_smb_lock_type_change,
+ { "Change", "smb.lock.type.change", FT_BOOLEAN, 8,
+ TFS(&tfs_lock_type_change), 0x04, "Change type of lock?", HFILL }},
+
+ { &hf_smb_lock_type_oplock,
+ { "Oplock Break", "smb.lock.type.oplock_release", FT_BOOLEAN, 8,
+ TFS(&tfs_lock_type_oplock), 0x02, "Is this a notification of, or a response to, an oplock break?", HFILL }},
+
+ { &hf_smb_lock_type_shared,
+ { "Shared", "smb.lock.type.shared", FT_BOOLEAN, 8,
+ TFS(&tfs_lock_type_shared), 0x01, "Shared or exclusive lock requested?", HFILL }},
+
+ { &hf_smb_locking_ol,
+ { "Oplock Level", "smb.locking.oplock.level", FT_UINT8, BASE_DEC,
+ VALS(locking_ol_vals), 0, "Level of existing oplock at client (if any)", HFILL }},
+
+ { &hf_smb_number_of_locks,
+ { "Number of Locks", "smb.locking.num_locks", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of lock requests in this request", HFILL }},
+
+ { &hf_smb_number_of_unlocks,
+ { "Number of Unlocks", "smb.locking.num_unlocks", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of unlock requests in this request", HFILL }},
+
+ { &hf_smb_lock_long_length,
+ { "Length", "smb.lock.length", FT_STRING, BASE_DEC,
+ NULL, 0, "Length of lock/unlock region", HFILL }},
+
+ { &hf_smb_lock_long_offset,
+ { "Offset", "smb.lock.offset", FT_STRING, BASE_DEC,
+ NULL, 0, "Offset in the file of lock/unlock region", HFILL }},
+
+ { &hf_smb_file_type,
+ { "File Type", "smb.file_type", FT_UINT16, BASE_DEC,
+ VALS(filetype_vals), 0, "Type of file", HFILL }},
+
+ { &hf_smb_ipc_state_nonblocking,
+ { "Nonblocking", "smb.ipc_state.nonblocking", FT_BOOLEAN, 16,
+ TFS(&tfs_ipc_state_nonblocking), 0x8000, "Is I/O to this pipe nonblocking?", HFILL }},
+
+ { &hf_smb_ipc_state_endpoint,
+ { "Endpoint", "smb.ipc_state.endpoint", FT_UINT16, BASE_DEC,
+ VALS(ipc_state_endpoint_vals), 0x4000, "Which end of the pipe this is", HFILL }},
+
+ { &hf_smb_ipc_state_pipe_type,
+ { "Pipe Type", "smb.ipc_state.pipe_type", FT_UINT16, BASE_DEC,
+ VALS(ipc_state_pipe_type_vals), 0x0c00, "What type of pipe this is", HFILL }},
+
+ { &hf_smb_ipc_state_read_mode,
+ { "Read Mode", "smb.ipc_state.read_mode", FT_UINT16, BASE_DEC,
+ VALS(ipc_state_read_mode_vals), 0x0300, "How this pipe should be read", HFILL }},
+
+ { &hf_smb_ipc_state_icount,
+ { "Icount", "smb.ipc_state.icount", FT_UINT16, BASE_DEC,
+ NULL, 0x00FF, "Count to control pipe instancing", HFILL }},
+
+ { &hf_smb_server_fid,
+ { "Server FID", "smb.server_fid", FT_UINT32, BASE_HEX,
+ NULL, 0, "Server unique File ID", HFILL }},
+
+ { &hf_smb_open_flags_add_info,
+ { "Additional Info", "smb.open.flags.add_info", FT_BOOLEAN, 16,
+ TFS(&tfs_open_flags_add_info), 0x0001, "Additional Information Requested?", HFILL }},
+
+ { &hf_smb_open_flags_ex_oplock,
+ { "Exclusive Oplock", "smb.open.flags.ex_oplock", FT_BOOLEAN, 16,
+ TFS(&tfs_open_flags_ex_oplock), 0x0002, "Exclusive Oplock Requested?", HFILL }},
+
+ { &hf_smb_open_flags_batch_oplock,
+ { "Batch Oplock", "smb.open.flags.batch_oplock", FT_BOOLEAN, 16,
+ TFS(&tfs_open_flags_batch_oplock), 0x0004, "Batch Oplock Requested?", HFILL }},
+
+ { &hf_smb_open_flags_ealen,
+ { "Total EA Len", "smb.open.flags.ealen", FT_BOOLEAN, 16,
+ TFS(&tfs_open_flags_ealen), 0x0008, "Total EA Len Requested?", HFILL }},
+
+ { &hf_smb_open_action_open,
+ { "Open Action", "smb.open.action.open", FT_UINT16, BASE_DEC,
+ VALS(oa_open_vals), 0x0003, "Open Action, how the file was opened", HFILL }},
+
+ { &hf_smb_open_action_lock,
+ { "Exclusive Open", "smb.open.action.lock", FT_BOOLEAN, 16,
+ TFS(&tfs_oa_lock), 0x8000, "Is this file opened by another user?", HFILL }},
+
+ { &hf_smb_vc_num,
+ { "VC Number", "smb.vc", FT_UINT16, BASE_DEC,
+ NULL, 0, "VC Number", HFILL }},
+
+ { &hf_smb_password_len,
+ { "Password Length", "smb.pwlen", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of password", HFILL }},
+
+ { &hf_smb_ansi_password_len,
+ { "ANSI Password Length", "smb.ansi_pwlen", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of ANSI password", HFILL }},
+
+ { &hf_smb_unicode_password_len,
+ { "Unicode Password Length", "smb.unicode_pwlen", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of Unicode password", HFILL }},
+
+ { &hf_smb_account,
+ { "Account", "smb.account", FT_STRING, BASE_NONE,
+ NULL, 0, "Account, username", HFILL }},
+
+ { &hf_smb_os,
+ { "Native OS", "smb.native_os", FT_STRING, BASE_NONE,
+ NULL, 0, "Which OS we are running", HFILL }},
+
+ { &hf_smb_lanman,
+ { "Native LAN Manager", "smb.native_lanman", FT_STRING, BASE_NONE,
+ NULL, 0, "Which LANMAN protocol we are running", HFILL }},
+
+ { &hf_smb_setup_action_guest,
+ { "Guest", "smb.setup.action.guest", FT_BOOLEAN, 16,
+ TFS(&tfs_setup_action_guest), 0x0001, "Client logged in as GUEST?", HFILL }},
+
+ { &hf_smb_fs,
+ { "Native File System", "smb.native_fs", FT_STRING, BASE_NONE,
+ NULL, 0, "Native File System", HFILL }},
+
+ { &hf_smb_connect_flags_dtid,
+ { "Disconnect TID", "smb.connect.flags.dtid", FT_BOOLEAN, 16,
+ TFS(&tfs_disconnect_tid), 0x0001, "Disconnect TID?", HFILL }},
+
+ { &hf_smb_connect_support_search,
+ { "Search Bits", "smb.connect.support.search", FT_BOOLEAN, 16,
+ TFS(&tfs_connect_support_search), 0x0001, "Exclusive Search Bits supported?", HFILL }},
+
+ { &hf_smb_connect_support_in_dfs,
+ { "In Dfs", "smb.connect.support.dfs", FT_BOOLEAN, 16,
+ TFS(&tfs_connect_support_in_dfs), 0x0002, "Is this in a Dfs tree?", HFILL }},
+
+ { &hf_smb_max_setup_count,
+ { "Max Setup Count", "smb.msc", FT_UINT8, BASE_DEC,
+ NULL, 0, "Maximum number of setup words to return", HFILL }},
+
+ { &hf_smb_total_param_count,
+ { "Total Parameter Count", "smb.tpc", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total number of parameter bytes", HFILL }},
+
+ { &hf_smb_total_data_count,
+ { "Total Data Count", "smb.tdc", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total number of data bytes", HFILL }},
+
+ { &hf_smb_max_param_count,
+ { "Max Parameter Count", "smb.mpc", FT_UINT32, BASE_DEC,
+ NULL, 0, "Maximum number of parameter bytes to return", HFILL }},
+
+ { &hf_smb_max_data_count,
+ { "Max Data Count", "smb.mdc", FT_UINT32, BASE_DEC,
+ NULL, 0, "Maximum number of data bytes to return", HFILL }},
+
+ { &hf_smb_param_disp16,
+ { "Parameter Displacement", "smb.pd", FT_UINT16, BASE_DEC,
+ NULL, 0, "Displacement of these parameter bytes", HFILL }},
+
+ { &hf_smb_param_count16,
+ { "Parameter Count", "smb.pc", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of parameter bytes in this buffer", HFILL }},
+
+ { &hf_smb_param_offset16,
+ { "Parameter Offset", "smb.po", FT_UINT16, BASE_DEC,
+ NULL, 0, "Offset (from header start) to parameters", HFILL }},
+
+ { &hf_smb_param_disp32,
+ { "Parameter Displacement", "smb.pd", FT_UINT32, BASE_DEC,
+ NULL, 0, "Displacement of these parameter bytes", HFILL }},
+
+ { &hf_smb_param_count32,
+ { "Parameter Count", "smb.pc", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of parameter bytes in this buffer", HFILL }},
+
+ { &hf_smb_param_offset32,
+ { "Parameter Offset", "smb.po", FT_UINT32, BASE_DEC,
+ NULL, 0, "Offset (from header start) to parameters", HFILL }},
+
+ { &hf_smb_data_count16,
+ { "Data Count", "smb.dc", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of data bytes in this buffer", HFILL }},
+
+ { &hf_smb_data_disp16,
+ { "Data Displacement", "smb.data_disp", FT_UINT16, BASE_DEC,
+ NULL, 0, "Data Displacement", HFILL }},
+
+ { &hf_smb_data_offset16,
+ { "Data Offset", "smb.data_offset", FT_UINT16, BASE_DEC,
+ NULL, 0, "Data Offset", HFILL }},
+
+ { &hf_smb_data_count32,
+ { "Data Count", "smb.dc", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of data bytes in this buffer", HFILL }},
+
+ { &hf_smb_data_disp32,
+ { "Data Displacement", "smb.data_disp", FT_UINT32, BASE_DEC,
+ NULL, 0, "Data Displacement", HFILL }},
+
+ { &hf_smb_data_offset32,
+ { "Data Offset", "smb.data_offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Data Offset", HFILL }},
+
+ { &hf_smb_setup_count,
+ { "Setup Count", "smb.sc", FT_UINT8, BASE_DEC,
+ NULL, 0, "Number of setup words in this buffer", HFILL }},
+
+ { &hf_smb_nt_trans_subcmd,
+ { "Function", "smb.nt.function", FT_UINT16, BASE_DEC,
+ VALS(nt_cmd_vals), 0, "Function for NT Transaction", HFILL }},
+
+ { &hf_smb_nt_ioctl_function_code,
+ { "Function", "smb.nt.ioctl.function", FT_UINT32, BASE_HEX,
+ NULL, 0, "NT IOCTL function code", HFILL }},
+
+ { &hf_smb_nt_ioctl_isfsctl,
+ { "IsFSctl", "smb.nt.ioctl.isfsctl", FT_UINT8, BASE_DEC,
+ VALS(nt_ioctl_isfsctl_vals), 0, "Is this a device IOCTL (FALSE) or FS Control (TRUE)", HFILL }},
+
+ { &hf_smb_nt_ioctl_flags_root_handle,
+ { "Root Handle", "smb.nt.ioctl.flags.root_handle", FT_BOOLEAN, 8,
+ TFS(&tfs_nt_ioctl_flags_root_handle), NT_IOCTL_FLAGS_ROOT_HANDLE, "Apply to this share or root Dfs share", HFILL }},
+
+ { &hf_smb_nt_ioctl_data,
+ { "IOCTL Data", "smb.nt.ioctl.data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Data for the IOCTL call", HFILL }},
+
+ { &hf_smb_nt_notify_action,
+ { "Action", "smb.nt.notify.action", FT_UINT32, BASE_DEC,
+ VALS(nt_notify_action_vals), 0, "Which action caused this notify response", HFILL }},
+
+ { &hf_smb_nt_notify_watch_tree,
+ { "Watch Tree", "smb.nt.notify.watch_tree", FT_UINT8, BASE_DEC,
+ VALS(watch_tree_vals), 0, "Should Notify watch subdirectories also?", HFILL }},
+
+ { &hf_smb_nt_notify_stream_write,
+ { "Stream Write", "smb.nt.notify.stream_write", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_stream_write), NT_NOTIFY_STREAM_WRITE, "Notify on stream write?", HFILL }},
+
+ { &hf_smb_nt_notify_stream_size,
+ { "Stream Size Change", "smb.nt.notify.stream_size", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_stream_size), NT_NOTIFY_STREAM_SIZE, "Notify on changes of stream size", HFILL }},
+
+ { &hf_smb_nt_notify_stream_name,
+ { "Stream Name Change", "smb.nt.notify.stream_name", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_stream_name), NT_NOTIFY_STREAM_NAME, "Notify on changes to stream name?", HFILL }},
+
+ { &hf_smb_nt_notify_security,
+ { "Security Change", "smb.nt.notify.security", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_security), NT_NOTIFY_SECURITY, "Notify on changes to security settings", HFILL }},
+
+ { &hf_smb_nt_notify_ea,
+ { "EA Change", "smb.nt.notify.ea", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_ea), NT_NOTIFY_EA, "Notify on changes to Extended Attributes", HFILL }},
+
+ { &hf_smb_nt_notify_creation,
+ { "Created Change", "smb.nt.notify.creation", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_creation), NT_NOTIFY_CREATION, "Notify on changes to creation time", HFILL }},
+
+ { &hf_smb_nt_notify_last_access,
+ { "Last Access Change", "smb.nt.notify.last_access", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_last_access), NT_NOTIFY_LAST_ACCESS, "Notify on changes to last access", HFILL }},
+
+ { &hf_smb_nt_notify_last_write,
+ { "Last Write Change", "smb.nt.notify.last_write", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_last_write), NT_NOTIFY_LAST_WRITE, "Notify on changes to last write", HFILL }},
+
+ { &hf_smb_nt_notify_size,
+ { "Size Change", "smb.nt.notify.size", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_size), NT_NOTIFY_SIZE, "Notify on changes to size", HFILL }},
+
+ { &hf_smb_nt_notify_attributes,
+ { "Attribute Change", "smb.nt.notify.attributes", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_attributes), NT_NOTIFY_ATTRIBUTES, "Notify on changes to attributes", HFILL }},
+
+ { &hf_smb_nt_notify_dir_name,
+ { "Directory Name Change", "smb.nt.notify.dir_name", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_dir_name), NT_NOTIFY_DIR_NAME, "Notify on changes to directory name", HFILL }},
+
+ { &hf_smb_nt_notify_file_name,
+ { "File Name Change", "smb.nt.notify.file_name", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_notify_file_name), NT_NOTIFY_FILE_NAME, "Notify on changes to file name", HFILL }},
+
+ { &hf_smb_root_dir_fid,
+ { "Root FID", "smb.rfid", FT_UINT32, BASE_HEX,
+ NULL, 0, "Open is relative to this FID (if nonzero)", HFILL }},
+
+ { &hf_smb_alloc_size64,
+ { "Allocation Size", "smb.alloc_size", FT_UINT64, BASE_DEC,
+ NULL, 0, "Number of bytes to reserve on create or truncate", HFILL }},
+
+ { &hf_smb_nt_create_disposition,
+ { "Disposition", "smb.create.disposition", FT_UINT32, BASE_DEC,
+ VALS(create_disposition_vals), 0, "Create disposition, what to do if the file does/does not exist", HFILL }},
+
+ { &hf_smb_sd_length,
+ { "SD Length", "smb.sd.length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total length of security descriptor", HFILL }},
+
+ { &hf_smb_ea_list_length,
+ { "EA List Length", "smb.ea.list_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total length of extended attributes", HFILL }},
+
+ { &hf_smb_ea_flags,
+ { "EA Flags", "smb.ea.flags", FT_UINT8, BASE_HEX,
+ NULL, 0, "EA Flags", HFILL }},
+
+ { &hf_smb_ea_name_length,
+ { "EA Name Length", "smb.ea.name_length", FT_UINT8, BASE_DEC,
+ NULL, 0, "EA Name Length", HFILL }},
+
+ { &hf_smb_ea_data_length,
+ { "EA Data Length", "smb.ea.data_length", FT_UINT16, BASE_DEC,
+ NULL, 0, "EA Data Length", HFILL }},
+
+ { &hf_smb_ea_name,
+ { "EA Name", "smb.ea.name", FT_STRING, BASE_NONE,
+ NULL, 0, "EA Name", HFILL }},
+
+ { &hf_smb_ea_data,
+ { "EA Data", "smb.ea.data", FT_BYTES, BASE_NONE,
+ NULL, 0, "EA Data", HFILL }},
+
+ { &hf_smb_file_name_len,
+ { "File Name Len", "smb.file_name_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of File Name", HFILL }},
+
+ { &hf_smb_nt_impersonation_level,
+ { "Impersonation", "smb.impersonation.level", FT_UINT32, BASE_DEC,
+ VALS(impersonation_level_vals), 0, "Impersonation level", HFILL }},
+
+ { &hf_smb_nt_security_flags_context_tracking,
+ { "Context Tracking", "smb.security.flags.context_tracking", FT_BOOLEAN, 8,
+ TFS(&tfs_nt_security_flags_context_tracking), 0x01, "Is security tracking static or dynamic?", HFILL }},
+
+ { &hf_smb_nt_security_flags_effective_only,
+ { "Effective Only", "smb.security.flags.effective_only", FT_BOOLEAN, 8,
+ TFS(&tfs_nt_security_flags_effective_only), 0x02, "Are only enabled or all aspects uf the users SID available?", HFILL }},
+
+ { &hf_smb_nt_access_mask_generic_read,
+ { "Generic Read", "smb.access.generic_read", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_generic_read), 0x80000000, "Is generic read allowed for this object?", HFILL }},
+
+ { &hf_smb_nt_access_mask_generic_write,
+ { "Generic Write", "smb.access.generic_write", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_generic_write), 0x40000000, "Is generic write allowed for this object?", HFILL }},
+
+ { &hf_smb_nt_access_mask_generic_execute,
+ { "Generic Execute", "smb.access.generic_execute", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_generic_execute), 0x20000000, "Is generic execute allowed for this object?", HFILL }},
+
+ { &hf_smb_nt_access_mask_generic_all,
+ { "Generic All", "smb.access.generic_all", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_generic_all), 0x10000000, "Is generic all allowed for this attribute", HFILL }},
+
+ { &hf_smb_nt_access_mask_maximum_allowed,
+ { "Maximum Allowed", "smb.access.maximum_allowed", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_maximum_allowed), 0x02000000, "?", HFILL }},
+
+ { &hf_smb_nt_access_mask_system_security,
+ { "System Security", "smb.access.system_security", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_system_security), 0x01000000, "Access to a system ACL?", HFILL }},
+
+ { &hf_smb_nt_access_mask_synchronize,
+ { "Synchronize", "smb.access.synchronize", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_synchronize), 0x00100000, "Windows NT: synchronize access", HFILL }},
+
+ { &hf_smb_nt_access_mask_write_owner,
+ { "Write Owner", "smb.access.write_owner", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_write_owner), 0x00080000, "Can owner write to the object?", HFILL }},
+
+ { &hf_smb_nt_access_mask_write_dac,
+ { "Write DAC", "smb.access.write_dac", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_write_dac), 0x00040000, "Is write allowed to the owner group or ACLs?", HFILL }},
+
+ { &hf_smb_nt_access_mask_read_control,
+ { "Read Control", "smb.access.read_control", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_read_control), 0x00020000, "Are reads allowed of owner, group and ACL data of the SID?", HFILL }},
+
+ { &hf_smb_nt_access_mask_delete,
+ { "Delete", "smb.access.delete", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_delete), 0x00010000, "Can object be deleted", HFILL }},
+
+ { &hf_smb_nt_access_mask_write_attributes,
+ { "Write Attributes", "smb.access.write_attributes", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_write_attributes), 0x00000100, "Can object's attributes be written", HFILL }},
+
+ { &hf_smb_nt_access_mask_read_attributes,
+ { "Read Attributes", "smb.access.read_attributes", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_read_attributes), 0x00000080, "Can object's attributes be read", HFILL }},
+
+ { &hf_smb_nt_access_mask_delete_child,
+ { "Delete Child", "smb.access.delete_child", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_delete_child), 0x00000040, "Can object's subdirectories be deleted", HFILL }},
+
+ /*
+ * "Execute" for files, "traverse" for directories.
+ */
+ { &hf_smb_nt_access_mask_execute,
+ { "Execute", "smb.access.execute", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_execute), 0x00000020, "Can object be executed (if file) or traversed (if directory)", HFILL }},
+
+ { &hf_smb_nt_access_mask_write_ea,
+ { "Write EA", "smb.access.write_ea", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_write_ea), 0x00000010, "Can object's extended attributes be written", HFILL }},
+
+ { &hf_smb_nt_access_mask_read_ea,
+ { "Read EA", "smb.access.read_ea", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_read_ea), 0x00000008, "Can object's extended attributes be read", HFILL }},
+
+ /*
+ * "Append data" for files, "add subdirectory" for directories,
+ * "create pipe instance" for named pipes.
+ */
+ { &hf_smb_nt_access_mask_append,
+ { "Append", "smb.access.append", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_append), 0x00000004, "Can object's contents be appended to", HFILL }},
+
+ /*
+ * "Write data" for files and pipes, "add file" for directory.
+ */
+ { &hf_smb_nt_access_mask_write,
+ { "Write", "smb.access.write", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_write), 0x00000002, "Can object's contents be written", HFILL }},
+
+ /*
+ * "Read data" for files and pipes, "list directory" for directory.
+ */
+ { &hf_smb_nt_access_mask_read,
+ { "Read", "smb.access.read", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_access_mask_read), 0x00000001, "Can object's contents be read", HFILL }},
+
+ { &hf_smb_nt_create_bits_oplock,
+ { "Exclusive Oplock", "smb.nt.create.oplock", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_bits_oplock), 0x00000002, "Is an oplock requested", HFILL }},
+
+ { &hf_smb_nt_create_bits_boplock,
+ { "Batch Oplock", "smb.nt.create.batch_oplock", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_bits_boplock), 0x00000004, "Is a batch oplock requested?", HFILL }},
+
+ { &hf_smb_nt_create_bits_dir,
+ { "Create Directory", "smb.nt.create.dir", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_bits_dir), 0x00000008, "Must target of open be a directory?", HFILL }},
+
+ { &hf_smb_nt_create_bits_ext_resp,
+ { "Extended Response", "smb.nt.create.ext", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_bits_ext_resp), 0x00000010, "Extended response required?", HFILL }},
+
+ { &hf_smb_nt_create_options_directory_file,
+ { "Directory", "smb.nt.create_options.directory", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_directory), 0x00000001, "Should file being opened/created be a directory?", HFILL }},
+
+ { &hf_smb_nt_create_options_write_through,
+ { "Write Through", "smb.nt.create_options.write_through", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_write_through), 0x00000002, "Should writes to the file write buffered data out before completing?", HFILL }},
+
+ { &hf_smb_nt_create_options_sequential_only,
+ { "Sequential Only", "smb.nt.create_options.sequential_only", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_sequential_only), 0x00000004, "Will accees to thsis file only be sequential?", HFILL }},
+
+ { &hf_smb_nt_create_options_sync_io_alert,
+ { "Sync I/O Alert", "smb.nt.create_options.sync_io_alert", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_sync_io_alert), 0x00000010, "All operations are performed synchronous", HFILL}},
+
+ { &hf_smb_nt_create_options_sync_io_nonalert,
+ { "Sync I/O Nonalert", "smb.nt.create_options.sync_io_nonalert", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_sync_io_nonalert), 0x00000020, "All operations are synchronous and may block", HFILL}},
+
+ { &hf_smb_nt_create_options_non_directory_file,
+ { "Non-Directory", "smb.nt.create_options.non_directory", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_non_directory), 0x00000040, "Should file being opened/created be a non-directory?", HFILL }},
+
+ /* 0x00000080 is "tree connect", at least in "NtCreateFile()"
+ and "NtOpenFile()"; is that sent over the wire? Network
+ Monitor thinks so, but its author may just have grabbed
+ the flag bits from a system header file. */
+
+ /* 0x00000100 is "complete if oplocked", at least in "NtCreateFile()"
+ and "NtOpenFile()"; is that sent over the wire? NetMon
+ thinks so, but see previous comment. */
+
+ { &hf_smb_nt_create_options_no_ea_knowledge,
+ { "No EA Knowledge", "smb.nt.create_options.no_ea_knowledge", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_no_ea_knowledge), 0x00000200, "Does the client not understand extended attributes?", HFILL }},
+
+ { &hf_smb_nt_create_options_eight_dot_three_only,
+ { "8.3 Only", "smb.nt.create_options.eight_dot_three_only", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_eight_dot_three_only), 0x00000400, "Does the client understand only 8.3 filenames?", HFILL }},
+
+ { &hf_smb_nt_create_options_random_access,
+ { "Random Access", "smb.nt.create_options.random_access", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_random_access), 0x00000800, "Will the client be accessing the file randomly?", HFILL }},
+
+ { &hf_smb_nt_create_options_delete_on_close,
+ { "Delete On Close", "smb.nt.create_options.delete_on_close", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_create_options_delete_on_close), 0x00001000, "Should the file be deleted when closed?", HFILL }},
+
+ /* 0x00002000 is "open by FID", or something such as that (which
+ I suspect is like "open by inumber" on UNIX), at least in
+ "NtCreateFile()" and "NtOpenFile()"; is that sent over the
+ wire? NetMon thinks so, but see previous comment. */
+
+ /* 0x00004000 is "open for backup", at least in "NtCreateFile()"
+ and "NtOpenFile()"; is that sent over the wire? NetMon
+ thinks so, but see previous comment. */
+
+ { &hf_smb_nt_share_access_read,
+ { "Read", "smb.share.access.read", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_share_access_read), 0x00000001, "Can the object be shared for reading?", HFILL }},
+
+ { &hf_smb_nt_share_access_write,
+ { "Write", "smb.share.access.write", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_share_access_write), 0x00000002, "Can the object be shared for write?", HFILL }},
+
+ { &hf_smb_nt_share_access_delete,
+ { "Delete", "smb.share.access.delete", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_share_access_delete), 0x00000004, "", HFILL }},
+
+ { &hf_smb_file_eattr_read_only,
+ { "Read Only", "smb.file_attribute.read_only", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_read_only), SMB_FILE_ATTRIBUTE_READ_ONLY, "READ ONLY file attribute", HFILL }},
+
+ { &hf_smb_file_eattr_hidden,
+ { "Hidden", "smb.file_attribute.hidden", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_hidden), SMB_FILE_ATTRIBUTE_HIDDEN, "HIDDEN file attribute", HFILL }},
+
+ { &hf_smb_file_eattr_system,
+ { "System", "smb.file_attribute.system", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_system), SMB_FILE_ATTRIBUTE_SYSTEM, "SYSTEM file attribute", HFILL }},
+
+ { &hf_smb_file_eattr_volume,
+ { "Volume ID", "smb.file_attribute.volume", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_volume), SMB_FILE_ATTRIBUTE_VOLUME, "VOLUME file attribute", HFILL }},
+
+ { &hf_smb_file_eattr_directory,
+ { "Directory", "smb.file_attribute.directory", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_directory), SMB_FILE_ATTRIBUTE_DIRECTORY, "DIRECTORY file attribute", HFILL }},
+
+ { &hf_smb_file_eattr_archive,
+ { "Archive", "smb.file_attribute.archive", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_archive), SMB_FILE_ATTRIBUTE_ARCHIVE, "ARCHIVE file attribute", HFILL }},
+
+ { &hf_smb_file_eattr_device,
+ { "Device", "smb.file_attribute.device", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_device), SMB_FILE_ATTRIBUTE_DEVICE, "Is this file a device?", HFILL }},
+
+ { &hf_smb_file_eattr_normal,
+ { "Normal", "smb.file_attribute.normal", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_normal), SMB_FILE_ATTRIBUTE_NORMAL, "Is this a normal file?", HFILL }},
+
+ { &hf_smb_file_eattr_temporary,
+ { "Temporary", "smb.file_attribute.temporary", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_temporary), SMB_FILE_ATTRIBUTE_TEMPORARY, "Is this a temporary file?", HFILL }},
+
+ { &hf_smb_file_eattr_sparse,
+ { "Sparse", "smb.file_attribute.sparse", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_sparse), SMB_FILE_ATTRIBUTE_SPARSE, "Is this a sparse file?", HFILL }},
+
+ { &hf_smb_file_eattr_reparse,
+ { "Reparse Point", "smb.file_attribute.reparse", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_reparse), SMB_FILE_ATTRIBUTE_REPARSE, "Does this file have an associated reparse point?", HFILL }},
+
+ { &hf_smb_file_eattr_compressed,
+ { "Compressed", "smb.file_attribute.compressed", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_compressed), SMB_FILE_ATTRIBUTE_COMPRESSED, "Is this file compressed?", HFILL }},
+
+ { &hf_smb_file_eattr_offline,
+ { "Offline", "smb.file_attribute.offline", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_offline), SMB_FILE_ATTRIBUTE_OFFLINE, "Is this file offline?", HFILL }},
+
+ { &hf_smb_file_eattr_not_content_indexed,
+ { "Content Indexed", "smb.file_attribute.not_content_indexed", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_not_content_indexed), SMB_FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, "May this file be indexed by the content indexing service", HFILL }},
+
+ { &hf_smb_file_eattr_encrypted,
+ { "Encrypted", "smb.file_attribute.encrypted", FT_BOOLEAN, 32,
+ TFS(&tfs_file_attribute_encrypted), SMB_FILE_ATTRIBUTE_ENCRYPTED, "Is this file encrypted?", HFILL }},
+
+ { &hf_smb_sec_desc_len,
+ { "NT Security Descriptor Length", "smb.sec_desc_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Security Descriptor Length", HFILL }},
+
+ { &hf_smb_nt_qsd_owner,
+ { "Owner", "smb.nt_qsd.owner", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_qsd_owner), NT_QSD_OWNER, "Is owner security informaton being queried?", HFILL }},
+
+ { &hf_smb_nt_qsd_group,
+ { "Group", "smb.nt_qsd.group", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_qsd_group), NT_QSD_GROUP, "Is group security informaton being queried?", HFILL }},
+
+ { &hf_smb_nt_qsd_dacl,
+ { "DACL", "smb.nt_qsd.dacl", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_qsd_dacl), NT_QSD_DACL, "Is DACL security informaton being queried?", HFILL }},
+
+ { &hf_smb_nt_qsd_sacl,
+ { "SACL", "smb.nt_qsd.sacl", FT_BOOLEAN, 32,
+ TFS(&tfs_nt_qsd_sacl), NT_QSD_SACL, "Is SACL security informaton being queried?", HFILL }},
+
+ { &hf_smb_extended_attributes,
+ { "Extended Attributes", "smb.ext_attr", FT_BYTES, BASE_HEX,
+ NULL, 0, "Extended Attributes", HFILL }},
+
+ { &hf_smb_oplock_level,
+ { "Oplock level", "smb.oplock.level", FT_UINT8, BASE_DEC,
+ VALS(oplock_level_vals), 0, "Level of oplock granted", HFILL }},
+
+ { &hf_smb_create_action,
+ { "Create action", "smb.create.action", FT_UINT32, BASE_DEC,
+ VALS(oa_open_vals), 0, "Type of action taken", HFILL }},
+
+ { &hf_smb_file_id,
+ { "Server unique file ID", "smb.create.file_id", FT_UINT32, BASE_HEX,
+ NULL, 0, "Server unique file ID", HFILL }},
+
+ { &hf_smb_ea_error_offset,
+ { "EA Error offset", "smb.ea.error_offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Offset into EA list if EA error", HFILL }},
+
+ { &hf_smb_end_of_file,
+ { "End Of File", "smb.end_of_file", FT_UINT64, BASE_DEC,
+ NULL, 0, "Offset to the first free byte in the file", HFILL }},
+
+ { &hf_smb_replace,
+ { "Replace", "smb.replace", FT_BOOLEAN, BASE_NONE,
+ TFS(&tfs_smb_replace), 0x0, "Remove target if it exists?", HFILL }},
+
+ { &hf_smb_root_dir_handle,
+ { "Root Directory Handle", "smb.root_dir_handle", FT_UINT32, BASE_HEX,
+ NULL, 0, "Root directory handle", HFILL }},
+
+ { &hf_smb_target_name_len,
+ { "Target name length", "smb.target_name_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of target file name", HFILL }},
+
+ { &hf_smb_target_name,
+ { "Target name", "smb.target_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Target file name", HFILL }},
+
+ { &hf_smb_device_type,
+ { "Device Type", "smb.device.type", FT_UINT32, BASE_HEX,
+ VALS(device_type_vals), 0, "Type of device", HFILL }},
+
+ { &hf_smb_is_directory,
+ { "Is Directory", "smb.is_directory", FT_UINT8, BASE_DEC,
+ VALS(is_directory_vals), 0, "Is this object a directory?", HFILL }},
+
+ { &hf_smb_next_entry_offset,
+ { "Next Entry Offset", "smb.next_entry_offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Offset to next entry", HFILL }},
+
+ { &hf_smb_change_time,
+ { "Change", "smb.change.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Last Change Time", HFILL }},
+
+ { &hf_smb_setup_len,
+ { "Setup Len", "smb.print.setup.len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of printer setup data", HFILL }},
+
+ { &hf_smb_print_mode,
+ { "Mode", "smb.print.mode", FT_UINT16, BASE_DEC,
+ VALS(print_mode_vals), 0, "Text or Graphics mode", HFILL }},
+
+ { &hf_smb_print_identifier,
+ { "Identifier", "smb.print.identifier", FT_STRING, BASE_NONE,
+ NULL, 0, "Identifier string for this print job", HFILL }},
+
+ { &hf_smb_restart_index,
+ { "Restart Index", "smb.print.restart_index", FT_UINT16, BASE_DEC,
+ NULL, 0, "Index of entry after last returned", HFILL }},
+
+ { &hf_smb_print_queue_date,
+ { "Queued", "smb.print.queued.date", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Date when this entry was queued", HFILL }},
+
+ { &hf_smb_print_queue_dos_date,
+ { "Queued Date", "smb.print.queued.smb.date", FT_UINT16, BASE_HEX,
+ NULL, 0, "Date when this print job was queued, SMB_DATE format", HFILL }},
+
+ { &hf_smb_print_queue_dos_time,
+ { "Queued Time", "smb.print.queued.smb.time", FT_UINT16, BASE_HEX,
+ NULL, 0, "Time when this print job was queued, SMB_TIME format", HFILL }},
+
+ { &hf_smb_print_status,
+ { "Status", "smb.print.status", FT_UINT8, BASE_HEX,
+ VALS(print_status_vals), 0, "Status of this entry", HFILL }},
+
+ { &hf_smb_print_spool_file_number,
+ { "Spool File Number", "smb.print.spool.file_number", FT_UINT16, BASE_DEC,
+ NULL, 0, "Spool File Number, assigned by the spooler", HFILL }},
+
+ { &hf_smb_print_spool_file_size,
+ { "Spool File Size", "smb.print.spool.file_size", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of bytes in spool file", HFILL }},
+
+ { &hf_smb_print_spool_file_name,
+ { "Name", "smb.print.spool.name", FT_BYTES, BASE_HEX,
+ NULL, 0, "Name of client that submitted this job", HFILL }},
+
+ { &hf_smb_start_index,
+ { "Start Index", "smb.print.start_index", FT_UINT16, BASE_DEC,
+ NULL, 0, "First queue entry to return", HFILL }},
+
+ { &hf_smb_originator_name,
+ { "Originator Name", "smb.originator_name", FT_STRINGZ, BASE_NONE,
+ NULL, 0, "Name of sender of message", HFILL }},
+
+ { &hf_smb_destination_name,
+ { "Destination Name", "smb.destination_name", FT_STRINGZ, BASE_NONE,
+ NULL, 0, "Name of recipient of message", HFILL }},
+
+ { &hf_smb_message_len,
+ { "Message Len", "smb.message.len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of message", HFILL }},
+
+ { &hf_smb_message,
+ { "Message", "smb.message", FT_STRING, BASE_NONE,
+ NULL, 0, "Message text", HFILL }},
+
+ { &hf_smb_mgid,
+ { "Message Group ID", "smb.mgid", FT_UINT16, BASE_DEC,
+ NULL, 0, "Message group ID for multi-block messages", HFILL }},
+
+ { &hf_smb_forwarded_name,
+ { "Forwarded Name", "smb.forwarded_name", FT_STRINGZ, BASE_NONE,
+ NULL, 0, "Recipient name being forwarded", HFILL }},
+
+ { &hf_smb_machine_name,
+ { "Machine Name", "smb.machine_name", FT_STRINGZ, BASE_NONE,
+ NULL, 0, "Name of target machine", HFILL }},
+
+ { &hf_smb_cancel_to,
+ { "Cancel to", "smb.cancel_to", FT_FRAMENUM, BASE_NONE,
+ NULL, 0, "This packet is a cancellation of the packet in this frame", HFILL }},
+
+ { &hf_smb_trans2_subcmd,
+ { "Subcommand", "smb.trans2.cmd", FT_UINT16, BASE_HEX,
+ VALS(trans2_cmd_vals), 0, "Subcommand for TRANSACTION2", HFILL }},
+
+ { &hf_smb_trans_name,
+ { "Transaction Name", "smb.trans_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of transaction", HFILL }},
+
+ { &hf_smb_transaction_flags_dtid,
+ { "Disconnect TID", "smb.transaction.flags.dtid", FT_BOOLEAN, 16,
+ TFS(&tfs_tf_dtid), 0x0001, "Disconnect TID?", HFILL }},
+
+ { &hf_smb_transaction_flags_owt,
+ { "One Way Transaction", "smb.transaction.flags.owt", FT_BOOLEAN, 16,
+ TFS(&tfs_tf_owt), 0x0002, "One Way Transaction (no response)?", HFILL }},
+
+ { &hf_smb_search_count,
+ { "Search Count", "smb.search_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "Maximum number of search entries to return", HFILL }},
+
+ { &hf_smb_search_pattern,
+ { "Search Pattern", "smb.search_pattern", FT_STRING, BASE_NONE,
+ NULL, 0, "Search Pattern", HFILL }},
+
+ { &hf_smb_ff2_backup,
+ { "Backup Intent", "smb.find_first2.flags.backup", FT_BOOLEAN, 16,
+ TFS(&tfs_ff2_backup), 0x0010, "Find with backup intent", HFILL }},
+
+ { &hf_smb_ff2_continue,
+ { "Continue", "smb.find_first2.flags.continue", FT_BOOLEAN, 16,
+ TFS(&tfs_ff2_continue), 0x0008, "Continue search from previous ending place", HFILL }},
+
+ { &hf_smb_ff2_resume,
+ { "Resume", "smb.find_first2.flags.resume", FT_BOOLEAN, 16,
+ TFS(&tfs_ff2_resume), FF2_RESUME, "Return resume keys for each entry found", HFILL }},
+
+ { &hf_smb_ff2_close_eos,
+ { "Close on EOS", "smb.find_first2.flags.eos", FT_BOOLEAN, 16,
+ TFS(&tfs_ff2_close_eos), 0x0002, "Close search if end of search reached", HFILL }},
+
+ { &hf_smb_ff2_close,
+ { "Close", "smb.find_first2.flags.close", FT_BOOLEAN, 16,
+ TFS(&tfs_ff2_close), 0x0001, "Close search after this request", HFILL }},
+
+ { &hf_smb_ff2_information_level,
+ { "Level of Interest", "smb.ff2_loi", FT_UINT16, BASE_DEC,
+ VALS(ff2_il_vals), 0, "Level of interest for FIND_FIRST2 command", HFILL }},
+
+ { &hf_smb_qpi_loi,
+ { "Level of Interest", "smb.qpi_loi", FT_UINT16, BASE_DEC,
+ VALS(qpi_loi_vals), 0, "Level of interest for TRANSACTION[2] QUERY_{FILE,PATH}_INFO commands", HFILL }},
+
+ { &hf_smb_spi_loi,
+ { "Level of Interest", "smb.spi_loi", FT_UINT16, BASE_DEC,
+ VALS(spi_loi_vals), 0, "Level of interest for TRANSACTION[2] SET_{FILE,PATH}_INFO commands", HFILL }},
+
+#if 0
+ { &hf_smb_sfi_writetru,
+ { "Writethrough", "smb.sfi_writethrough", FT_BOOLEAN, 16,
+ TFS(&tfs_da_writetru), 0x0010, "Writethrough mode?", HFILL }},
+
+ { &hf_smb_sfi_caching,
+ { "Caching", "smb.sfi_caching", FT_BOOLEAN, 16,
+ TFS(&tfs_da_caching), 0x0020, "Caching mode?", HFILL }},
+#endif
+
+ { &hf_smb_storage_type,
+ { "Storage Type", "smb.storage_type", FT_UINT32, BASE_DEC,
+ NULL, 0, "Type of storage", HFILL }},
+
+ { &hf_smb_resume,
+ { "Resume Key", "smb.resume", FT_UINT32, BASE_DEC,
+ NULL, 0, "Resume Key", HFILL }},
+
+ { &hf_smb_max_referral_level,
+ { "Max Referral Level", "smb.max_referral_level", FT_UINT16, BASE_DEC,
+ NULL, 0, "Latest referral version number understood", HFILL }},
+
+ { &hf_smb_qfsi_information_level,
+ { "Level of Interest", "smb.qfi_loi", FT_UINT16, BASE_HEX,
+ VALS(qfsi_vals), 0, "Level of interest for QUERY_FS_INFORMATION2 command", HFILL }},
+
+ { &hf_smb_nt_rename_level,
+ { "Level of Interest", "smb.ntr_loi", FT_UINT16, BASE_DEC,
+ VALS(nt_rename_vals), 0, "NT Rename level", HFILL }},
+
+ { &hf_smb_cluster_count,
+ { "Cluster count", "smb.ntr_clu", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of clusters", HFILL }},
+
+ { &hf_smb_number_of_links,
+ { "Link Count", "smb.link_count", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of hard links to the file", HFILL }},
+
+ { &hf_smb_delete_pending,
+ { "Delete Pending", "smb.delete_pending", FT_UINT16, BASE_DEC,
+ VALS(delete_pending_vals), 0, "Is this object about to be deleted?", HFILL }},
+
+ { &hf_smb_index_number,
+ { "Index Number", "smb.index_number", FT_UINT64, BASE_DEC,
+ NULL, 0, "File system unique identifier", HFILL }},
+
+ { &hf_smb_current_offset,
+ { "Current Offset", "smb.offset", FT_UINT64, BASE_DEC,
+ NULL, 0, "Current offset in the file", HFILL }},
+
+ { &hf_smb_t2_alignment,
+ { "Alignment", "smb.alignment", FT_UINT32, BASE_DEC,
+ VALS(alignment_vals), 0, "What alignment do we require for buffers", HFILL }},
+
+ { &hf_smb_t2_stream_name_length,
+ { "Stream Name Length", "smb.stream_name_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of stream name", HFILL }},
+
+ { &hf_smb_t2_stream_size,
+ { "Stream Size", "smb.stream_size", FT_UINT64, BASE_DEC,
+ NULL, 0, "Size of the stream in number of bytes", HFILL }},
+
+ { &hf_smb_t2_stream_name,
+ { "Stream Name", "smb.stream_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of the stream", HFILL }},
+
+ { &hf_smb_t2_compressed_file_size,
+ { "Compressed Size", "smb.compressed.file_size", FT_UINT64, BASE_DEC,
+ NULL, 0, "Size of the compressed file", HFILL }},
+
+ { &hf_smb_t2_compressed_format,
+ { "Compression Format", "smb.compressed.format", FT_UINT16, BASE_DEC,
+ NULL, 0, "Compression algorithm used", HFILL }},
+
+ { &hf_smb_t2_compressed_unit_shift,
+ { "Unit Shift", "smb.compressed.unit_shift", FT_UINT8, BASE_DEC,
+ NULL, 0, "Size of the stream in number of bytes", HFILL }},
+
+ { &hf_smb_t2_compressed_chunk_shift,
+ { "Chunk Shift", "smb.compressed.chunk_shift", FT_UINT8, BASE_DEC,
+ NULL, 0, "Allocated size of the stream in number of bytes", HFILL }},
+
+ { &hf_smb_t2_compressed_cluster_shift,
+ { "Cluster Shift", "smb.compressed.cluster_shift", FT_UINT8, BASE_DEC,
+ NULL, 0, "Allocated size of the stream in number of bytes", HFILL }},
+
+ { &hf_smb_t2_marked_for_deletion,
+ { "Marked for Deletion", "smb.marked_for_deletion", FT_BOOLEAN, BASE_NONE,
+ TFS(&tfs_marked_for_deletion), 0x0, "Marked for deletion?", HFILL }},
+
+ { &hf_smb_dfs_path_consumed,
+ { "Path Consumed", "smb.dfs.path_consumed", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of RequestFilename bytes client", HFILL }},
+
+ { &hf_smb_dfs_num_referrals,
+ { "Num Referrals", "smb.dfs.num_referrals", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of referrals in this pdu", HFILL }},
+
+ { &hf_smb_get_dfs_server_hold_storage,
+ { "Hold Storage", "smb.dfs.flags.server_hold_storage", FT_BOOLEAN, 16,
+ TFS(&tfs_get_dfs_server_hold_storage), 0x02, "The servers in referrals should hold storage for the file", HFILL }},
+
+ { &hf_smb_get_dfs_fielding,
+ { "Fielding", "smb.dfs.flags.fielding", FT_BOOLEAN, 16,
+ TFS(&tfs_get_dfs_fielding), 0x01, "The servers in referrals are capable of fielding", HFILL }},
+
+ { &hf_smb_dfs_referral_version,
+ { "Version", "smb.dfs.referral.version", FT_UINT16, BASE_DEC,
+ NULL, 0, "Version of referral element", HFILL }},
+
+ { &hf_smb_dfs_referral_size,
+ { "Size", "smb.dfs.referral.size", FT_UINT16, BASE_DEC,
+ NULL, 0, "Size of referral element", HFILL }},
+
+ { &hf_smb_dfs_referral_server_type,
+ { "Server Type", "smb.dfs.referral.server.type", FT_UINT16, BASE_DEC,
+ VALS(dfs_referral_server_type_vals), 0, "Type of referral server", HFILL }},
+
+ { &hf_smb_dfs_referral_flags_strip,
+ { "Strip", "smb.dfs.referral.flags.strip", FT_BOOLEAN, 16,
+ TFS(&tfs_dfs_referral_flags_strip), 0x01, "Should we strip off pathconsumed characters before submitting?", HFILL }},
+
+ { &hf_smb_dfs_referral_node_offset,
+ { "Node Offset", "smb.dfs.referral.node_offset", FT_UINT16, BASE_DEC,
+ NULL, 0, "Offset of name of entity to visit next", HFILL }},
+
+ { &hf_smb_dfs_referral_node,
+ { "Node", "smb.dfs.referral.node", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of entity to visit next", HFILL }},
+
+ { &hf_smb_dfs_referral_proximity,
+ { "Proximity", "smb.dfs.referral.proximity", FT_UINT16, BASE_DEC,
+ NULL, 0, "Hint describing proximity of this server to the client", HFILL }},
+
+ { &hf_smb_dfs_referral_ttl,
+ { "TTL", "smb.dfs.referral.ttl", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of seconds the client can cache this referral", HFILL }},
+
+ { &hf_smb_dfs_referral_path_offset,
+ { "Path Offset", "smb.dfs.referral.path_offset", FT_UINT16, BASE_DEC,
+ NULL, 0, "Offset of Dfs Path that matched pathconsumed", HFILL }},
+
+ { &hf_smb_dfs_referral_path,
+ { "Path", "smb.dfs.referral.path", FT_STRING, BASE_NONE,
+ NULL, 0, "Dfs Path that matched pathconsumed", HFILL }},
+
+ { &hf_smb_dfs_referral_alt_path_offset,
+ { "Alt Path Offset", "smb.dfs.referral.alt_path_offset", FT_UINT16, BASE_DEC,
+ NULL, 0, "Offset of alternative(8.3) Path that matched pathconsumed", HFILL }},
+
+ { &hf_smb_dfs_referral_alt_path,
+ { "Alt Path", "smb.dfs.referral.alt_path", FT_STRING, BASE_NONE,
+ NULL, 0, "Alternative(8.3) Path that matched pathconsumed", HFILL }},
+
+ { &hf_smb_end_of_search,
+ { "End Of Search", "smb.end_of_search", FT_UINT16, BASE_DEC,
+ NULL, 0, "Was last entry returned?", HFILL }},
+
+ { &hf_smb_last_name_offset,
+ { "Last Name Offset", "smb.last_name_offset", FT_UINT16, BASE_DEC,
+ NULL, 0, "If non-0 this is the offset into the datablock for the file name of the last entry", HFILL }},
+
+ { &hf_smb_fn_information_level,
+ { "Level of Interest", "smb.fn_loi", FT_UINT16, BASE_DEC,
+ NULL, 0, "Level of interest for FIND_NOTIFY command", HFILL }},
+
+ { &hf_smb_monitor_handle,
+ { "Monitor Handle", "smb.monitor_handle", FT_UINT16, BASE_HEX,
+ NULL, 0, "Handle for Find Notify operations", HFILL }},
+
+ { &hf_smb_change_count,
+ { "Change Count", "smb.change_count", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of changes to wait for", HFILL }},
+
+ { &hf_smb_file_index,
+ { "File Index", "smb.file_index", FT_UINT32, BASE_DEC,
+ NULL, 0, "File index", HFILL }},
+
+ { &hf_smb_short_file_name,
+ { "Short File Name", "smb.short_file", FT_STRING, BASE_NONE,
+ NULL, 0, "Short (8.3) File Name", HFILL }},
+
+ { &hf_smb_short_file_name_len,
+ { "Short File Name Len", "smb.short_file_name_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of Short (8.3) File Name", HFILL }},
+
+ { &hf_smb_fs_id,
+ { "FS Id", "smb.fs_id", FT_UINT32, BASE_DEC,
+ NULL, 0, "File System ID (NT Server always returns 0)", HFILL }},
+
+ { &hf_smb_fs_guid,
+ { "FS GUID", "smb.fs_guid", FT_STRING, BASE_NONE,
+ NULL, 0, "File System GUID", HFILL }},
+
+ { &hf_smb_sector_unit,
+ { "Sectors/Unit", "smb.fs_sector_per_unit", FT_UINT32, BASE_DEC,
+ NULL, 0, "Sectors per allocation unit", HFILL }},
+
+ { &hf_smb_fs_units,
+ { "Total Units", "smb.fs_units", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total number of units on this filesystem", HFILL }},
+
+ { &hf_smb_fs_sector,
+ { "Bytes per Sector", "smb.fs_bytes_per_sector", FT_UINT32, BASE_DEC,
+ NULL, 0, "Bytes per sector", HFILL }},
+
+ { &hf_smb_avail_units,
+ { "Available Units", "smb.avail.units", FT_UINT32, BASE_DEC,
+ NULL, 0, "Total number of available units on this filesystem", HFILL }},
+
+ { &hf_smb_volume_serial_num,
+ { "Volume Serial Number", "smb.volume.serial", FT_UINT32, BASE_HEX,
+ NULL, 0, "Volume serial number", HFILL }},
+
+ { &hf_smb_volume_label_len,
+ { "Label Length", "smb.volume.label.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of volume label", HFILL }},
+
+ { &hf_smb_volume_label,
+ { "Label", "smb.volume.label", FT_STRING, BASE_DEC,
+ NULL, 0, "Volume label", HFILL }},
+
+ { &hf_smb_free_alloc_units64,
+ { "Free Units", "smb.free_alloc_units", FT_UINT64, BASE_DEC,
+ NULL, 0, "Number of free allocation units", HFILL }},
+
+ { &hf_smb_caller_free_alloc_units64,
+ { "Caller Free Units", "smb.caller_free_alloc_units", FT_UINT64, BASE_DEC,
+ NULL, 0, "Number of caller free allocation units", HFILL }},
+
+ { &hf_smb_actual_free_alloc_units64,
+ { "Actual Free Units", "smb.actual_free_alloc_units", FT_UINT64, BASE_DEC,
+ NULL, 0, "Number of actual free allocation units", HFILL }},
+
+ { &hf_smb_soft_quota_limit,
+ { "(Soft) Quota Treshold", "smb.quota.soft.default", FT_UINT64, BASE_DEC,
+ NULL, 0, "Soft Quota treshold", HFILL }},
+
+ { &hf_smb_hard_quota_limit,
+ { "(Hard) Quota Limit", "smb.quota.hard.default", FT_UINT64, BASE_DEC,
+ NULL, 0, "Hard Quota limit", HFILL }},
+
+ { &hf_smb_user_quota_used,
+ { "Quota Used", "smb.quota.used", FT_UINT64, BASE_DEC,
+ NULL, 0, "How much Quota is used by this user", HFILL }},
+
+ { &hf_smb_max_name_len,
+ { "Max name length", "smb.fs_max_name_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Maximum length of each file name component in number of bytes", HFILL }},
+
+ { &hf_smb_fs_name_len,
+ { "Label Length", "smb.fs_name.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of filesystem name in bytes", HFILL }},
+
+ { &hf_smb_fs_name,
+ { "FS Name", "smb.fs_name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name of filesystem", HFILL }},
+
+ { &hf_smb_device_char_removable,
+ { "Removable", "smb.device.removable", FT_BOOLEAN, 32,
+ TFS(&tfs_device_char_removable), 0x00000001, "Is this a removable device", HFILL }},
+
+ { &hf_smb_device_char_read_only,
+ { "Read Only", "smb.device.read_only", FT_BOOLEAN, 32,
+ TFS(&tfs_device_char_read_only), 0x00000002, "Is this a read-only device", HFILL }},
+
+ { &hf_smb_device_char_floppy,
+ { "Floppy", "smb.device.floppy", FT_BOOLEAN, 32,
+ TFS(&tfs_device_char_floppy), 0x00000004, "Is this a floppy disk", HFILL }},
+
+ { &hf_smb_device_char_write_once,
+ { "Write Once", "smb.device.write_once", FT_BOOLEAN, 32,
+ TFS(&tfs_device_char_write_once), 0x00000008, "Is this a write-once device", HFILL }},
+
+ { &hf_smb_device_char_remote,
+ { "Remote", "smb.device.remote", FT_BOOLEAN, 32,
+ TFS(&tfs_device_char_remote), 0x00000010, "Is this a remote device", HFILL }},
+
+ { &hf_smb_device_char_mounted,
+ { "Mounted", "smb.device.mounted", FT_BOOLEAN, 32,
+ TFS(&tfs_device_char_mounted), 0x00000020, "Is this a mounted device", HFILL }},
+
+ { &hf_smb_device_char_virtual,
+ { "Virtual", "smb.device.virtual", FT_BOOLEAN, 32,
+ TFS(&tfs_device_char_virtual), 0x00000040, "Is this a virtual device", HFILL }},
+
+ { &hf_smb_fs_attr_css,
+ { "Case Sensitive Search", "smb.fs_attr.css", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_attr_css), 0x00000001, "Does this FS support Case Sensitive Search?", HFILL }},
+
+ { &hf_smb_fs_attr_cpn,
+ { "Case Preserving", "smb.fs_attr.cpn", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_attr_cpn), 0x00000002, "Will this FS Preserve Name Case?", HFILL }},
+
+ { &hf_smb_fs_attr_pacls,
+ { "Persistent ACLs", "smb.fs_attr.pacls", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_attr_pacls), 0x00000004, "Does this FS support Persistent ACLs?", HFILL }},
+
+ { &hf_smb_fs_attr_fc,
+ { "Compression", "smb.fs_attr.fc", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_attr_fc), 0x00000008, "Does this FS support File Compression?", HFILL }},
+
+ { &hf_smb_fs_attr_vq,
+ { "Volume Quotas", "smb.fs_attr.vq", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_attr_vq), 0x00000010, "Does this FS support Volume Quotas?", HFILL }},
+
+ { &hf_smb_fs_attr_dim,
+ { "Mounted", "smb.fs_attr.dim", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_attr_dim), 0x00000020, "Is this FS a Mounted Device?", HFILL }},
+
+ { &hf_smb_fs_attr_vic,
+ { "Compressed", "smb.fs_attr.vic", FT_BOOLEAN, 32,
+ TFS(&tfs_fs_attr_vic), 0x00008000, "Is this FS Compressed?", HFILL }},
+
+ { &hf_smb_sec_desc_revision,
+ { "Revision", "smb.sec_desc.revision", FT_UINT8, BASE_DEC,
+ NULL, 0, "Version of NT Security Descriptor structure", HFILL }},
+
+ { &hf_smb_sid,
+ { "SID", "smb.sid", FT_STRING, BASE_DEC,
+ NULL, 0, "SID: Security Identifier", HFILL }},
+
+ { &hf_smb_sid_revision,
+ { "Revision", "smb.sid.revision", FT_UINT8, BASE_DEC,
+ NULL, 0, "Version of SID structure", HFILL }},
+
+ { &hf_smb_sid_num_auth,
+ { "Num Auth", "smb.sid.num_auth", FT_UINT8, BASE_DEC,
+ NULL, 0, "Number of authorities for this SID", HFILL }},
+
+ { &hf_smb_acl_revision,
+ { "Revision", "smb.acl.revision", FT_UINT8, BASE_DEC,
+ NULL, 0, "Version of NT ACL structure", HFILL }},
+
+ { &hf_smb_acl_size,
+ { "Size", "smb.acl.size", FT_UINT16, BASE_DEC,
+ NULL, 0, "Size of NT ACL structure", HFILL }},
+
+ { &hf_smb_acl_num_aces,
+ { "Num ACEs", "smb.acl.num_aces", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of ACE structures for this ACL", HFILL }},
+
+ { &hf_smb_user_quota_offset,
+ { "Next Offset", "smb.quota.user.offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Relative offset to next user quota structure", HFILL }},
+
+ { &hf_smb_ace_type,
+ { "Type", "smb.ace.type", FT_UINT8, BASE_DEC,
+ VALS(ace_type_vals), 0, "Type of ACE", HFILL }},
+
+ { &hf_smb_pipe_write_len,
+ { "Pipe Write Len", "smb.pipe.write_len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Number of bytes written to pipe", HFILL }},
+
+ { &hf_smb_ace_size,
+ { "Size", "smb.ace.size", FT_UINT16, BASE_DEC,
+ NULL, 0, "Size of this ACE", HFILL }},
+
+ { &hf_smb_ace_flags_object_inherit,
+ { "Object Inherit", "smb.ace.flags.object_inherit", FT_BOOLEAN, 8,
+ TFS(&tfs_ace_flags_object_inherit), 0x01, "Will subordinate files inherit this ACE?", HFILL }},
+
+ { &hf_smb_ace_flags_container_inherit,
+ { "Container Inherit", "smb.ace.flags.container_inherit", FT_BOOLEAN, 8,
+ TFS(&tfs_ace_flags_container_inherit), 0x02, "Will subordinate containers inherit this ACE?", HFILL }},
+
+ { &hf_smb_ace_flags_non_propagate_inherit,
+ { "Non-Propagate Inherit", "smb.ace.flags.non_propagate_inherit", FT_BOOLEAN, 8,
+ TFS(&tfs_ace_flags_non_propagate_inherit), 0x04, "Will subordinate object propagate this ACE further?", HFILL }},
+
+ { &hf_smb_ace_flags_inherit_only,
+ { "Inherit Only", "smb.ace.flags.inherit_only", FT_BOOLEAN, 8,
+ TFS(&tfs_ace_flags_inherit_only), 0x08, "Does this ACE apply to the current object?", HFILL }},
+
+ { &hf_smb_ace_flags_inherited_ace,
+ { "Inherited ACE", "smb.ace.flags.inherited_ace", FT_BOOLEAN, 8,
+ TFS(&tfs_ace_flags_inherited_ace), 0x10, "Was this ACE inherited from its parent object?", HFILL }},
+
+ { &hf_smb_ace_flags_successful_access,
+ { "Audit Successful Accesses", "smb.ace.flags.successful_access", FT_BOOLEAN, 8,
+ TFS(&tfs_ace_flags_successful_access), 0x40, "Should successful accesses be audited?", HFILL }},
+
+ { &hf_smb_ace_flags_failed_access,
+ { "Audit Failed Accesses", "smb.ace.flags.failed_access", FT_BOOLEAN, 8,
+ TFS(&tfs_ace_flags_failed_access), 0x80, "Should failed accesses be audited?", HFILL }},
+
+ { &hf_smb_sec_desc_type_owner_defaulted,
+ { "Owner Defaulted", "smb.sec_desc.type.owner_defaulted", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_owner_defaulted), 0x0001, "Is Owner Defaulted set?", HFILL }},
+
+ { &hf_smb_sec_desc_type_group_defaulted,
+ { "Group Defaulted", "smb.sec_desc.type.group_defaulted", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_group_defaulted), 0x0002, "Is Group Defaulted?", HFILL }},
+
+ { &hf_smb_sec_desc_type_dacl_present,
+ { "DACL Present", "smb.sec_desc.type.dacl_present", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_dacl_present), 0x0004, "Does this SecDesc have DACL present?", HFILL }},
+
+ { &hf_smb_sec_desc_type_dacl_defaulted,
+ { "DACL Defaulted", "smb.sec_desc.type.dacl_defaulted", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_dacl_defaulted), 0x0008, "Does this SecDesc have DACL Defaulted?", HFILL }},
+
+ { &hf_smb_sec_desc_type_sacl_present,
+ { "SACL Present", "smb.sec_desc.type.sacl_present", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_sacl_present), 0x0010, "Is the SACL present?", HFILL }},
+
+ { &hf_smb_sec_desc_type_sacl_defaulted,
+ { "SACL Defaulted", "smb.sec_desc.type.sacl_defaulted", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_sacl_defaulted), 0x0020, "Does this SecDesc have SACL Defaulted?", HFILL }},
+
+ { &hf_smb_sec_desc_type_dacl_auto_inherit_req,
+ { "DACL Auto Inherit Required", "smb.sec_desc.type.dacl_auto_inherit_req", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_dacl_auto_inherit_req), 0x0100, "Does this SecDesc have DACL Auto Inherit Required set?", HFILL }},
+
+ { &hf_smb_sec_desc_type_sacl_auto_inherit_req,
+ { "SACL Auto Inherit Required", "smb.sec_desc.type.sacl_auto_inherit_req", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_sacl_auto_inherit_req), 0x0200, "Does this SecDesc have SACL Auto Inherit Required set?", HFILL }},
+
+ { &hf_smb_sec_desc_type_dacl_auto_inherited,
+ { "DACL Auto Inherited", "smb.sec_desc.type.dacl_auto_inherited", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_dacl_auto_inherited), 0x0400, "Is this DACL auto inherited", HFILL }},
+
+ { &hf_smb_sec_desc_type_sacl_auto_inherited,
+ { "SACL Auto Inherited", "smb.sec_desc.type.sacl_auto_inherited", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_sacl_auto_inherited), 0x0800, "Is this SACL auto inherited", HFILL }},
+
+ { &hf_smb_sec_desc_type_dacl_protected,
+ { "DACL Protected", "smb.sec_desc.type.dacl_protected", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_dacl_protected), 0x1000, "Is the DACL structure protected?", HFILL }},
+
+ { &hf_smb_sec_desc_type_sacl_protected,
+ { "SACL Protected", "smb.sec_desc.type.sacl_protected", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_sacl_protected), 0x2000, "Is the SACL structure protected?", HFILL }},
+
+ { &hf_smb_sec_desc_type_self_relative,
+ { "Self Relative", "smb.sec_desc.type.self_relative", FT_BOOLEAN, 16,
+ TFS(&tfs_sec_desc_type_self_relative), 0x8000, "Is this SecDesc self relative?", HFILL }},
+
+ { &hf_smb_quota_flags_deny_disk,
+ { "Deny Disk", "smb.quota.flags.deny_disk", FT_BOOLEAN, 8,
+ TFS(&tfs_quota_flags_deny_disk), 0x02, "Is the default quota limit enforced?", HFILL }},
+
+ { &hf_smb_quota_flags_log_limit,
+ { "Log Limit", "smb.quota.flags.log_limit", FT_BOOLEAN, 8,
+ TFS(&tfs_quota_flags_log_limit), 0x20, "Should the server log an event when the limit is exceeded?", HFILL }},
+
+ { &hf_smb_quota_flags_log_warning,
+ { "Log Warning", "smb.quota.flags.log_warning", FT_BOOLEAN, 8,
+ TFS(&tfs_quota_flags_log_warning), 0x10, "Should the server log an event when the warning level is exceeded?", HFILL }},
+
+ { &hf_smb_quota_flags_enabled,
+ { "Enabled", "smb.quota.flags.enabled", FT_BOOLEAN, 8,
+ TFS(&tfs_quota_flags_enabled), 0x01, "Is quotas enabled of this FS?", HFILL }},
+
+ { &hf_smb_segment_overlap,
+ { "Fragment overlap", "smb.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_smb_segment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "smb.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_smb_segment_multiple_tails,
+ { "Multiple tail fragments found", "smb.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_smb_segment_too_long_fragment,
+ { "Fragment too long", "smb.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+
+ { &hf_smb_segment_error,
+ { "Defragmentation error", "smb.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }},
+
+ { &hf_smb_segment,
+ { "SMB Segment", "smb.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "SMB Segment", HFILL }},
+
+ { &hf_smb_segments,
+ { "SMB Segments", "smb.segment.segments", FT_NONE, BASE_NONE, NULL, 0x0,
+ "SMB Segments", HFILL }},
+
+ { &hf_smb_unix_major_version,
+ { "Major Version", "smb.unix.major_version", FT_UINT16, BASE_DEC,
+ NULL, 0, "UNIX Major Version", HFILL }},
+
+ { &hf_smb_unix_minor_version,
+ { "Minor Version", "smb.unix.minor_version", FT_UINT16, BASE_DEC,
+ NULL, 0, "UNIX Minor Version", HFILL }},
+
+ { &hf_smb_unix_capability_fcntl,
+ { "FCNTL Capability", "smb.unix.capability.fcntl", FT_BOOLEAN, 32,
+ TFS(&flags_set_truth), 0x00000001, "", HFILL }},
+
+ { &hf_smb_unix_capability_posix_acl,
+ { "POSIX ACL Capability", "smb.unix.capability.posix_acl", FT_BOOLEAN, 32,
+ TFS(&flags_set_truth), 0x00000002, "", HFILL }},
+
+ { &hf_smb_unix_file_size,
+ { "File size", "smb.unix.file.size", FT_UINT64, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_num_bytes,
+ { "Number of bytes", "smb.unix.file.num_bytes", FT_UINT64, BASE_DEC,
+ NULL, 0, "Number of bytes used to store the file", HFILL }},
+
+ { &hf_smb_unix_file_last_status,
+ { "Last status change", "smb.unix.file.stime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_last_access,
+ { "Last access", "smb.unix.file.atime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_last_change,
+ { "Last modification", "smb.unix.file.mtime", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_uid,
+ { "UID", "smb.unix.file.uid", FT_UINT64, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_gid,
+ { "GID", "smb.unix.file.gid", FT_UINT64, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_type,
+ { "File type", "smb.unix.file.file_type", FT_UINT32, BASE_DEC,
+ VALS(unix_file_type_vals), 0, "", HFILL }},
+
+ { &hf_smb_unix_file_dev_major,
+ { "Major device", "smb.unix.file.dev_major", FT_UINT64, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_dev_minor,
+ { "Minor device", "smb.unix.file.dev_minor", FT_UINT64, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_unique_id,
+ { "Unique ID", "smb.unix.file.unique_id", FT_UINT64, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_permissions,
+ { "File permissions", "smb.unix.file.perms", FT_UINT64, BASE_HEX,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_nlinks,
+ { "Num links", "smb.unix.file.num_links", FT_UINT64, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_file_link_dest,
+ { "Link destination", "smb.unix.file.link_dest", FT_STRING,
+ BASE_NONE, NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_find_file_nextoffset,
+ { "Next entry offset", "smb.unix.find_file.next_offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ { &hf_smb_unix_find_file_resumekey,
+ { "Resume key", "smb.unix.find_file.resume_key", FT_UINT32, BASE_DEC,
+ NULL, 0, "", HFILL }},
+
+ /* Access masks */
+
+ { &hf_smb_access_mask,
+ { "Access required", "smb.access_mask",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "Access mask",
+ HFILL }},
+ { &hf_access_generic_read,
+ { "Generic read", "nt.access_mask.generic_read",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GENERIC_READ_ACCESS, "Generic read", HFILL }},
+
+ { &hf_access_generic_write,
+ { "Generic write", "nt.access_mask.generic_write",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GENERIC_WRITE_ACCESS, "Generic write", HFILL }},
+
+ { &hf_access_generic_execute,
+ { "Generic execute", "nt.access_mask.generic_execute",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GENERIC_EXECUTE_ACCESS, "Generic execute", HFILL }},
+
+ { &hf_access_generic_all,
+ { "Generic all", "nt.access_mask.generic_all",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GENERIC_ALL_ACCESS, "Generic all", HFILL }},
+
+ { &hf_access_maximum_allowed,
+ { "Maximum allowed", "nt.access_mask.maximum_allowed",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ MAXIMUM_ALLOWED_ACCESS, "Maximum allowed", HFILL }},
+
+ { &hf_access_sacl,
+ { "Access SACL", "nt.access_mask.access_sacl",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ ACCESS_SACL_ACCESS, "Access SACL", HFILL }},
+
+ { &hf_access_standard_read_control,
+ { "Read control", "nt.access_mask.read_control",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ READ_CONTROL_ACCESS, "Read control", HFILL }},
+
+ { &hf_access_standard_delete,
+ { "Delete", "nt.access_mask.delete",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DELETE_ACCESS, "Delete", HFILL }},
+
+ { &hf_access_standard_synchronise,
+ { "Synchronise", "nt.access_mask.synchronise",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SYNCHRONIZE_ACCESS, "Synchronise", HFILL }},
+
+ { &hf_access_standard_write_dac,
+ { "Write DAC", "nt.access_mask.write_dac",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ WRITE_DAC_ACCESS, "Write DAC", HFILL }},
+
+ { &hf_access_standard_write_owner,
+ { "Write owner", "nt.access_mask.write_owner",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ WRITE_OWNER_ACCESS, "Write owner", HFILL }},
+
+ { &hf_access_specific_15,
+ { "Specific access, bit 15", "nt.access_mask.specific_15",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x8000, "Specific access, bit 15", HFILL }},
+
+ { &hf_access_specific_14,
+ { "Specific access, bit 14", "nt.access_mask.specific_14",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x4000, "Specific access, bit 14", HFILL }},
+
+ { &hf_access_specific_13,
+ { "Specific access, bit 13", "nt.access_mask.specific_13",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x2000, "Specific access, bit 13", HFILL }},
+
+ { &hf_access_specific_12,
+ { "Specific access, bit 12", "nt.access_mask.specific_12",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x1000, "Specific access, bit 12", HFILL }},
+
+ { &hf_access_specific_11,
+ { "Specific access, bit 11", "nt.access_mask.specific_11",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0800, "Specific access, bit 11", HFILL }},
+
+ { &hf_access_specific_10,
+ { "Specific access, bit 10", "nt.access_mask.specific_10",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0400, "Specific access, bit 10", HFILL }},
+
+ { &hf_access_specific_9,
+ { "Specific access, bit 9", "nt.access_mask.specific_9",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0200, "Specific access, bit 9", HFILL }},
+
+ { &hf_access_specific_8,
+ { "Specific access, bit 8", "nt.access_mask.specific_8",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0100, "Specific access, bit 8", HFILL }},
+
+ { &hf_access_specific_7,
+ { "Specific access, bit 7", "nt.access_mask.specific_7",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0080, "Specific access, bit 7", HFILL }},
+
+ { &hf_access_specific_6,
+ { "Specific access, bit 6", "nt.access_mask.specific_6",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0040, "Specific access, bit 6", HFILL }},
+
+ { &hf_access_specific_5,
+ { "Specific access, bit 5", "nt.access_mask.specific_5",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0020, "Specific access, bit 5", HFILL }},
+
+ { &hf_access_specific_4,
+ { "Specific access, bit 4", "nt.access_mask.specific_4",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0010, "Specific access, bit 4", HFILL }},
+
+ { &hf_access_specific_3,
+ { "Specific access, bit 3", "nt.access_mask.specific_3",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0008, "Specific access, bit 3", HFILL }},
+
+ { &hf_access_specific_2,
+ { "Specific access, bit 2", "nt.access_mask.specific_2",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0004, "Specific access, bit 2", HFILL }},
+
+ { &hf_access_specific_1,
+ { "Specific access, bit 1", "nt.access_mask.specific_1",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0002, "Specific access, bit 1", HFILL }},
+
+ { &hf_access_specific_0,
+ { "Specific access, bit 0", "nt.access_mask.specific_0",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0001, "Specific access, bit 0", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_smb,
+ &ett_smb_hdr,
+ &ett_smb_command,
+ &ett_smb_fileattributes,
+ &ett_smb_capabilities,
+ &ett_smb_aflags,
+ &ett_smb_dialect,
+ &ett_smb_dialects,
+ &ett_smb_mode,
+ &ett_smb_rawmode,
+ &ett_smb_flags,
+ &ett_smb_flags2,
+ &ett_smb_desiredaccess,
+ &ett_smb_search,
+ &ett_smb_file,
+ &ett_smb_openfunction,
+ &ett_smb_filetype,
+ &ett_smb_openaction,
+ &ett_smb_writemode,
+ &ett_smb_lock_type,
+ &ett_smb_ssetupandxaction,
+ &ett_smb_optionsup,
+ &ett_smb_time_date,
+ &ett_smb_move_copy_flags,
+ &ett_smb_file_attributes,
+ &ett_smb_search_resume_key,
+ &ett_smb_search_dir_info,
+ &ett_smb_unlocks,
+ &ett_smb_unlock,
+ &ett_smb_locks,
+ &ett_smb_lock,
+ &ett_smb_open_flags,
+ &ett_smb_ipc_state,
+ &ett_smb_open_action,
+ &ett_smb_setup_action,
+ &ett_smb_connect_flags,
+ &ett_smb_connect_support_bits,
+ &ett_smb_nt_access_mask,
+ &ett_smb_nt_create_bits,
+ &ett_smb_nt_create_options,
+ &ett_smb_nt_share_access,
+ &ett_smb_nt_security_flags,
+ &ett_smb_nt_trans_setup,
+ &ett_smb_nt_trans_data,
+ &ett_smb_nt_trans_param,
+ &ett_smb_nt_notify_completion_filter,
+ &ett_smb_nt_ioctl_flags,
+ &ett_smb_security_information_mask,
+ &ett_smb_print_queue_entry,
+ &ett_smb_transaction_flags,
+ &ett_smb_transaction_params,
+ &ett_smb_find_first2_flags,
+#if 0
+ &ett_smb_ioflag,
+#endif
+ &ett_smb_transaction_data,
+ &ett_smb_stream_info,
+ &ett_smb_dfs_referrals,
+ &ett_smb_dfs_referral,
+ &ett_smb_dfs_referral_flags,
+ &ett_smb_get_dfs_flags,
+ &ett_smb_ff2_data,
+ &ett_smb_device_characteristics,
+ &ett_smb_fs_attributes,
+ &ett_smb_segments,
+ &ett_smb_segment,
+ &ett_smb_sec_desc,
+ &ett_smb_sid,
+ &ett_smb_acl,
+ &ett_smb_ace,
+ &ett_smb_ace_flags,
+ &ett_smb_sec_desc_type,
+ &ett_smb_quotaflags,
+ &ett_smb_secblob,
+ &ett_smb_mac_support_flags,
+ &ett_nt_access_mask,
+ &ett_nt_access_mask_generic,
+ &ett_nt_access_mask_standard,
+ &ett_nt_access_mask_specific,
+ &ett_smb_unicode_password,
+ &ett_smb_ea,
+ &ett_smb_unix_capabilities
+ };
+ module_t *smb_module;
+
+ proto_smb = proto_register_protocol("SMB (Server Message Block Protocol)",
+ "SMB", "smb");
+ proto_register_subtree_array(ett, array_length(ett));
+ proto_register_field_array(proto_smb, hf, array_length(hf));
+
+ register_smb_common(proto_smb);
+
+ register_init_routine(&smb_init_protocol);
+ smb_module = prefs_register_protocol(proto_smb, NULL);
+ prefs_register_bool_preference(smb_module, "trans_reassembly",
+ "Reassemble SMB Transaction payload",
+ "Whether the dissector should reassemble the payload of SMB Transaction commands spanning multiple SMB PDUs",
+ &smb_trans_reassembly);
+ prefs_register_bool_preference(smb_module, "dcerpc_reassembly",
+ "Reassemble DCERPC over SMB",
+ "Whether the dissector should reassemble DCERPC over SMB commands",
+ &smb_dcerpc_reassembly);
+ prefs_register_bool_preference(smb_module, "sid_name_snooping",
+ "Snoop SID to Name mappings",
+ "Whether the dissector should snoop SMB and related CIFS protocols to discover and display Names associated with SIDs",
+ &sid_name_snooping);
+
+ register_init_routine(smb_trans_reassembly_init);
+ smb_tap = register_tap("smb");
+}
+
+void
+proto_reg_handoff_smb(void)
+{
+ dissector_handle_t smb_handle;
+
+ gssapi_handle = find_dissector("gssapi");
+ ntlmssp_handle = find_dissector("ntlmssp");
+
+ heur_dissector_add("netbios", dissect_smb_heur, proto_smb);
+ heur_dissector_add("cotp", dissect_smb_heur, proto_smb);
+ heur_dissector_add("vines_spp", dissect_smb_heur, proto_smb);
+ smb_handle = create_dissector_handle(dissect_smb, proto_smb);
+ dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_SERVER, smb_handle);
+ dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_REDIR, smb_handle);
+ dissector_add("ipx.socket", IPX_SOCKET_NWLINK_SMB_MESSENGER,
+ smb_handle);
+}
diff --git a/epan/dissectors/packet-smpp.c b/epan/dissectors/packet-smpp.c
new file mode 100644
index 0000000000..5d92afc530
--- /dev/null
+++ b/epan/dissectors/packet-smpp.c
@@ -0,0 +1,2765 @@
+/* packet-smpp.c
+ * Routines for Short Message Peer to Peer dissection
+ * Copyright 2001, Tom Uijldert.
+ *
+ * Data Coding Scheme decoding for GSM (SMS and CBS),
+ * provided by Olivier Biot.
+ *
+ * Dissection of multiple SMPP PDUs within one packet
+ * provided by Chris Wilson.
+ *
+ * $Id$
+ *
+ * Refer to the AUTHORS file or the AUTHORS section in the man page
+ * for contacting the author(s) of this file.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * ----------
+ *
+ * Dissector of an SMPP (Short Message Peer to Peer) PDU, as defined by the
+ * SMS forum (www.smsforum.net) in "SMPP protocol specification v3.4"
+ * (document version: 12-Oct-1999 Issue 1.2)
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#include "prefs.h"
+#include "packet-tcp.h"
+
+/* General-purpose debug logger.
+ * Requires double parentheses because of variable arguments of printf().
+ *
+ * Enable debug logging for SMPP by defining AM_CFLAGS
+ * so that it contains "-DDEBUG_smpp"
+ */
+#ifdef DEBUG_smpp
+#define DebugLog(x) \
+ printf("%s:%u: ", __FILE__, __LINE__); \
+ printf x; \
+ fflush(stdout)
+#else
+#define DebugLog(x) ;
+#endif
+
+/* Forward declarations */
+static void dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+static guint get_smpp_pdu_len(tvbuff_t *tvb, int offset);
+static void dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+/*
+ * Initialize the protocol and registered fields
+ *
+ * Fixed header section
+ */
+static int proto_smpp = -1;
+
+static int hf_smpp_command_id = -1;
+static int hf_smpp_command_length = -1;
+static int hf_smpp_command_status = -1;
+static int hf_smpp_sequence_number = -1;
+
+/*
+ * Fixed body section
+ */
+static int hf_smpp_system_id = -1;
+static int hf_smpp_password = -1;
+static int hf_smpp_system_type = -1;
+static int hf_smpp_interface_version = -1;
+static int hf_smpp_addr_ton = -1;
+static int hf_smpp_addr_npi = -1;
+static int hf_smpp_address_range = -1;
+static int hf_smpp_service_type = -1;
+static int hf_smpp_source_addr_ton = -1;
+static int hf_smpp_source_addr_npi = -1;
+static int hf_smpp_source_addr = -1;
+static int hf_smpp_dest_addr_ton = -1;
+static int hf_smpp_dest_addr_npi = -1;
+static int hf_smpp_destination_addr = -1;
+static int hf_smpp_esm_submit_msg_mode = -1;
+static int hf_smpp_esm_submit_msg_type = -1;
+static int hf_smpp_esm_submit_features = -1;
+static int hf_smpp_protocol_id = -1;
+static int hf_smpp_priority_flag = -1;
+static int hf_smpp_schedule_delivery_time = -1;
+static int hf_smpp_schedule_delivery_time_r = -1;
+static int hf_smpp_validity_period = -1;
+static int hf_smpp_validity_period_r = -1;
+static int hf_smpp_regdel_receipt = -1;
+static int hf_smpp_regdel_acks = -1;
+static int hf_smpp_regdel_notif = -1;
+static int hf_smpp_replace_if_present_flag = -1;
+static int hf_smpp_data_coding = -1;
+static int hf_smpp_sm_default_msg_id = -1;
+static int hf_smpp_sm_length = -1;
+static int hf_smpp_short_message = -1;
+static int hf_smpp_message_id = -1;
+static int hf_smpp_dlist = -1;
+static int hf_smpp_dlist_resp = -1;
+static int hf_smpp_dl_name = -1;
+static int hf_smpp_final_date = -1;
+static int hf_smpp_final_date_r = -1;
+static int hf_smpp_message_state = -1;
+static int hf_smpp_error_code = -1;
+static int hf_smpp_error_status_code = -1;
+static int hf_smpp_esme_addr_ton = -1;
+static int hf_smpp_esme_addr_npi = -1;
+static int hf_smpp_esme_addr = -1;
+
+/*
+ * Optional parameter section
+ */
+static int hf_smpp_opt_param = -1;
+static int hf_smpp_vendor_op = -1;
+static int hf_smpp_reserved_op = -1;
+
+static int hf_smpp_dest_addr_subunit = -1;
+static int hf_smpp_dest_network_type = -1;
+static int hf_smpp_dest_bearer_type = -1;
+static int hf_smpp_dest_telematics_id = -1;
+static int hf_smpp_source_addr_subunit = -1;
+static int hf_smpp_source_network_type = -1;
+static int hf_smpp_source_bearer_type = -1;
+static int hf_smpp_source_telematics_id = -1;
+static int hf_smpp_qos_time_to_live = -1;
+static int hf_smpp_payload_type = -1;
+static int hf_smpp_additional_status_info_text = -1;
+static int hf_smpp_receipted_message_id = -1;
+static int hf_smpp_msg_wait_ind = -1;
+static int hf_smpp_msg_wait_type = -1;
+static int hf_smpp_privacy_indicator = -1;
+static int hf_smpp_source_subaddress = -1;
+static int hf_smpp_dest_subaddress = -1;
+static int hf_smpp_user_message_reference = -1;
+static int hf_smpp_user_response_code = -1;
+static int hf_smpp_source_port = -1;
+static int hf_smpp_destination_port = -1;
+static int hf_smpp_sar_msg_ref_num = -1;
+static int hf_smpp_language_indicator = -1;
+static int hf_smpp_sar_total_segments = -1;
+static int hf_smpp_sar_segment_seqnum = -1;
+static int hf_smpp_SC_interface_version = -1;
+static int hf_smpp_callback_num_pres = -1;
+static int hf_smpp_callback_num_scrn = -1;
+static int hf_smpp_callback_num_atag = -1;
+static int hf_smpp_number_of_messages = -1;
+static int hf_smpp_callback_num = -1;
+static int hf_smpp_dpf_result = -1;
+static int hf_smpp_set_dpf = -1;
+static int hf_smpp_ms_availability_status = -1;
+static int hf_smpp_network_error_type = -1;
+static int hf_smpp_network_error_code = -1;
+static int hf_smpp_message_payload = -1;
+static int hf_smpp_delivery_failure_reason = -1;
+static int hf_smpp_more_messages_to_send = -1;
+static int hf_smpp_ussd_service_op = -1;
+static int hf_smpp_display_time = -1;
+static int hf_smpp_sms_signal = -1;
+static int hf_smpp_ms_validity = -1;
+static int hf_smpp_alert_on_message_delivery = -1;
+static int hf_smpp_its_reply_type = -1;
+static int hf_smpp_its_session_number = -1;
+static int hf_smpp_its_session_sequence = -1;
+static int hf_smpp_its_session_ind = -1;
+
+/*
+ * Data Coding Scheme section
+ */
+static int hf_smpp_dcs = -1;
+static int hf_smpp_dcs_sms_coding_group = -1;
+static int hf_smpp_dcs_text_compression = -1;
+static int hf_smpp_dcs_class_present = -1;
+static int hf_smpp_dcs_charset = -1;
+static int hf_smpp_dcs_class = -1;
+static int hf_smpp_dcs_cbs_coding_group = -1;
+static int hf_smpp_dcs_cbs_language = -1;
+static int hf_smpp_dcs_wap_charset = -1;
+static int hf_smpp_dcs_wap_class = -1;
+static int hf_smpp_dcs_cbs_class = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_smpp = -1;
+static gint ett_dlist = -1;
+static gint ett_dlist_resp = -1;
+static gint ett_opt_param = -1;
+static gint ett_dcs = -1;
+
+/* Reassemble SMPP TCP segments */
+static gboolean reassemble_over_tcp = FALSE;
+
+/*
+ * Value-arrays for field-contents
+ */
+static const value_string vals_command_id[] = { /* Operation */
+ { 0x80000000, "Generic_nack" },
+ { 0x00000001, "Bind_receiver" },
+ { 0x80000001, "Bind_receiver - resp" },
+ { 0x00000002, "Bind_transmitter" },
+ { 0x80000002, "Bind_transmitter - resp" },
+ { 0x00000003, "Query_sm" },
+ { 0x80000003, "Query_sm - resp" },
+ { 0x00000004, "Submit_sm" },
+ { 0x80000004, "Submit_sm - resp" },
+ { 0x00000005, "Deliver_sm" },
+ { 0x80000005, "Deliver_sm - resp" },
+ { 0x00000006, "Unbind" },
+ { 0x80000006, "Unbind - resp" },
+ { 0x00000007, "Replace_sm" },
+ { 0x80000007, "Replace_sm - resp" },
+ { 0x00000008, "Cancel_sm" },
+ { 0x80000008, "Cancel_sm - resp" },
+ { 0x00000009, "Bind_transceiver" },
+ { 0x80000009, "Bind_transceiver - resp" },
+ { 0x0000000B, "Outbind" },
+ { 0x00000015, "Enquire_link" },
+ { 0x80000015, "Enquire_link - resp" },
+ { 0x00000021, "Submit_multi" },
+ { 0x80000021, "Submit_multi - resp" },
+ { 0x00000102, "Alert_notification" },
+ { 0x00000103, "Data_sm" },
+ { 0x80000103, "Data_sm - resp" },
+ { 0, NULL }
+};
+
+static const value_string vals_command_status[] = { /* Status */
+ { 0x00000000, "Ok" },
+ { 0x00000001, "Message length is invalid" },
+ { 0x00000002, "Command length is invalid" },
+ { 0x00000003, "Invalid command ID" },
+ { 0x00000004, "Incorrect BIND status for given command" },
+ { 0x00000005, "ESME already in bound state" },
+ { 0x00000006, "Invalid priority flag" },
+ { 0x00000007, "Invalid registered delivery flag" },
+ { 0x00000008, "System error" },
+ { 0x00000009, "[Reserved]" },
+ { 0x0000000A, "Invalid source address" },
+ { 0x0000000B, "Invalid destination address" },
+ { 0x0000000C, "Message ID is invalid" },
+ { 0x0000000D, "Bind failed" },
+ { 0x0000000E, "Invalid password" },
+ { 0x0000000F, "Invalid system ID" },
+ { 0x00000010, "[Reserved]" },
+ { 0x00000011, "Cancel SM failed" },
+ { 0x00000012, "[Reserved]" },
+ { 0x00000013, "Replace SM failed" },
+ { 0x00000014, "Message queue full" },
+ { 0x00000015, "Invalid service type" },
+ { 0x00000033, "Invalid number of destinations" },
+ { 0x00000034, "Invalid distribution list name" },
+ { 0x00000040, "Destination flag is invalid (submit_multi)" },
+ { 0x00000041, "[Reserved]" },
+ { 0x00000042, "Invalid 'submit with replace' request" },
+ { 0x00000043, "Invalid esm_class field data" },
+ { 0x00000044, "Cannot submit to distribution list" },
+ { 0x00000045, "submit_sm or submit_multi failed" },
+ { 0x00000046, "[Reserved]" },
+ { 0x00000047, "[Reserved]" },
+ { 0x00000048, "Invalid source address TON" },
+ { 0x00000049, "Invalid source address NPI" },
+ { 0x00000050, "Invalid destination address TON" },
+ { 0x00000051, "Invalid destination address NPI" },
+ { 0x00000052, "[Reserved]" },
+ { 0x00000053, "Invalid system_type field" },
+ { 0x00000054, "Invalid replace_if_present flag" },
+ { 0x00000055, "Invalid number of messages" },
+ { 0x00000056, "[Reserved]" },
+ { 0x00000057, "[Reserved]" },
+ { 0x00000058, "Throttling error (ESME exceeded allowed message limits)" },
+ { 0x00000059, "[Reserved]" },
+ { 0x00000060, "[Reserved]" },
+ { 0x00000061, "Invalid scheduled delivery time" },
+ { 0x00000062, "Invalid message validity period (expirey time)" },
+ { 0x00000063, "Predefined message invalid or not found" },
+ { 0x00000064, "ESME receiver temporary app error code" },
+ { 0x00000065, "ESME receiver permanent app error code" },
+ { 0x00000066, "ESME receiver reject message error code" },
+ { 0x00000067, "query_sm request failed" },
+ { 0x000000C0, "Error in the optional part of the PDU body" },
+ { 0x000000C1, "Optional parameter not allowed" },
+ { 0x000000C2, "Invalid parameter length" },
+ { 0x000000C3, "Expected optional parameter missing" },
+ { 0x000000C4, "Invalid optional parameter value" },
+ { 0x000000FE, "Delivery failure (used for data_sm_resp)" },
+ { 0x000000FF, "Unknown error" },
+ { 0, NULL }
+};
+
+static const value_string vals_addr_ton[] = {
+ { 0, "Unknown" },
+ { 1, "International" },
+ { 2, "National" },
+ { 3, "Network specific" },
+ { 4, "Subscriber number" },
+ { 5, "Alphanumeric" },
+ { 6, "Abbreviated" },
+ { 0, NULL }
+};
+
+static const value_string vals_addr_npi[] = {
+ { 0, "Unknown" },
+ { 1, "ISDN (E163/E164)" },
+ { 3, "Data (X.121)" },
+ { 4, "Telex (F.69)" },
+ { 6, "Land mobile (E.212)" },
+ { 8, "National" },
+ { 9, "Private" },
+ { 10, "ERMES" },
+ { 14, "Internet (IP)" },
+ { 18, "WAP client Id" },
+ { 0, NULL }
+};
+
+static const value_string vals_esm_submit_msg_mode[] = {
+ { 0x0, "Default SMSC mode" },
+ { 0x1, "Datagram mode" },
+ { 0x2, "Forward mode" },
+ { 0x3, "Store and forward mode" },
+ { 0, NULL }
+};
+
+static const value_string vals_esm_submit_msg_type[] = {
+ { 0x0, "Default message type" },
+ { 0x1, "Short message contains SMSC Delivery Receipt" },
+ { 0x2, "Short message contains (E)SME delivery acknowledgement" },
+ { 0x3, "Reserved" },
+ { 0x4, "Short message contains (E)SME manual/user acknowledgement" },
+ { 0x5, "Reserved" },
+ { 0x6, "Short message contains conversation abort" },
+ { 0x7, "Reserved" },
+ { 0x8, "Short message contains intermediate delivery notification" },
+ { 0, NULL }
+};
+
+static const value_string vals_esm_submit_features[] = {
+ { 0x0, "No specific features selected" },
+ { 0x1, "UDHI indicator" },
+ { 0x2, "Reply path" },
+ { 0x3, "UDHI and reply path" },
+ { 0, NULL }
+};
+
+static const value_string vals_priority_flag[] = {
+ { 0, "GSM: None ANSI-136: Bulk IS-95: Normal" },
+ { 1, "GSM: priority ANSI-136: Normal IS-95: Interactive" },
+ { 2, "GSM: priority ANSI-136: Urgent IS-95: Urgent" },
+ { 3, "GSM: priority ANSI-136: Very Urgent IS-95: Emergency" },
+ { 0, NULL }
+};
+
+static const value_string vals_regdel_receipt[] = {
+ { 0x0, "No SMSC delivery receipt requested" },
+ { 0x1, "Delivery receipt requested (for success or failure)" },
+ { 0x2, "Delivery receipt requested (for failure)" },
+ { 0x3, "Reserved" },
+ { 0, NULL }
+};
+
+static const value_string vals_regdel_acks[] = {
+ { 0x0, "No recipient SME acknowledgement requested" },
+ { 0x1, "SME delivery acknowledgement requested" },
+ { 0x2, "SME manual/user acknowledgement requested" },
+ { 0x3, "Both delivery and manual/user acknowledgement requested" },
+ { 0, NULL }
+};
+
+static const value_string vals_regdel_notif[] = {
+ { 0x0, "No intermediate notification requested" },
+ { 0x1, "Intermediate notification requested" },
+ { 0, NULL }
+};
+
+static const value_string vals_replace_if_present_flag[] = {
+ { 0x0, "Don't replace" },
+ { 0x1, "Replace" },
+ { 0, NULL }
+};
+
+static const value_string vals_data_coding[] = {
+ { 0, "SMSC default alphabet" },
+ { 1, "IA5 (CCITT T.50/ASCII (ANSI X3.4)" },
+ { 2, "Octet unspecified (8-bit binary)" },
+ { 3, "Latin 1 (ISO-8859-1)" },
+ { 4, "Octet unspecified (8-bit binary)" },
+ { 5, "JIS (X 0208-1990)" },
+ { 6, "Cyrillic (ISO-8859-5)" },
+ { 7, "Latin/Hebrew (ISO-8859-8)" },
+ { 8, "UCS2 (ISO/IEC-10646)" },
+ { 9, "Pictogram encoding" },
+ { 10, "ISO-2022-JP (Music codes)" },
+ { 11, "reserved" },
+ { 12, "reserved" },
+ { 13, "Extended Kanji JIS(X 0212-1990)" },
+ { 14, "KS C 5601" },
+ /*! \todo Rest to be defined (bitmask?) according GSM 03.38 */
+ { 0, NULL }
+};
+
+static const value_string vals_message_state[] = {
+ { 1, "ENROUTE" },
+ { 2, "DELIVERED" },
+ { 3, "EXPIRED" },
+ { 4, "DELETED" },
+ { 5, "UNDELIVERABLE" },
+ { 6, "ACCEPTED" },
+ { 7, "UNKNOWN" },
+ { 8, "REJECTED" },
+ { 0, NULL }
+};
+
+static const value_string vals_addr_subunit[] = {
+ { 0, "Unknown -default-" },
+ { 1, "MS Display" },
+ { 2, "Mobile equipment" },
+ { 3, "Smart card 1" },
+ { 4, "External unit 1" },
+ { 0, NULL }
+};
+
+static const value_string vals_network_type[] = {
+ { 0, "Unknown" },
+ { 1, "GSM" },
+ { 2, "ANSI-136/TDMA" },
+ { 3, "IS-95/CDMA" },
+ { 4, "PDC" },
+ { 5, "PHS" },
+ { 6, "iDEN" },
+ { 7, "AMPS" },
+ { 8, "Paging network" },
+ { 0, NULL }
+};
+
+static const value_string vals_bearer_type[] = {
+ { 0, "Unknown" },
+ { 1, "SMS" },
+ { 2, "Circuit Switched Data (CSD)" },
+ { 3, "Packet data" },
+ { 4, "USSD" },
+ { 5, "CDPD" },
+ { 6, "DataTAC" },
+ { 7, "FLEX/ReFLEX" },
+ { 8, "Cell Broadcast" },
+ { 0, NULL }
+};
+
+static const value_string vals_payload_type[] = {
+ { 0, "Default" },
+ { 1, "WCMP message" },
+ { 0, NULL }
+};
+
+static const value_string vals_privacy_indicator[] = {
+ { 0, "Not restricted -default-" },
+ { 1, "Restricted" },
+ { 2, "Confidential" },
+ { 3, "Secret" },
+ { 0, NULL }
+};
+
+static const value_string vals_language_indicator[] = {
+ { 0, "Unspecified -default-" },
+ { 1, "english" },
+ { 2, "french" },
+ { 3, "spanish" },
+ { 4, "german" },
+ { 5, "portuguese" },
+ { 0, NULL }
+};
+
+static const value_string vals_display_time[] = {
+ { 0, "Temporary" },
+ { 1, "Default -default-" },
+ { 2, "Invoke" },
+ { 0, NULL }
+};
+
+static const value_string vals_ms_validity[] = {
+ { 0, "Store indefinitely -default-" },
+ { 1, "Power down" },
+ { 2, "SID based registration area" },
+ { 3, "Display only" },
+ { 0, NULL }
+};
+
+static const value_string vals_dpf_result[] = {
+ { 0, "DPF not set" },
+ { 1, "DPF set" },
+ { 0, NULL }
+};
+
+static const value_string vals_set_dpf[] = {
+ { 0, "Not requested (Set DPF for delivery failure)" },
+ { 1, "Requested (Set DPF for delivery failure)" },
+ { 0, NULL }
+};
+
+static const value_string vals_ms_availability_status[] = {
+ { 0, "Available -default-" },
+ { 1, "Denied" },
+ { 2, "Unavailable" },
+ { 0, NULL }
+};
+
+static const value_string vals_delivery_failure_reason[] = {
+ { 0, "Destination unavailable" },
+ { 1, "Destination address invalid" },
+ { 2, "Permanent network error" },
+ { 3, "Temporary network error" },
+ { 0, NULL }
+};
+
+static const value_string vals_more_messages_to_send[] = {
+ { 0, "No more messages" },
+ { 1, "More messages -default-" },
+ { 0, NULL }
+};
+
+static const value_string vals_its_reply_type[] = {
+ { 0, "Digit" },
+ { 1, "Number" },
+ { 2, "Telephone no." },
+ { 3, "Password" },
+ { 4, "Character line" },
+ { 5, "Menu" },
+ { 6, "Date" },
+ { 7, "Time" },
+ { 8, "Continue" },
+ { 0, NULL }
+};
+
+static const value_string vals_ussd_service_op[] = {
+ { 0, "PSSD indication" },
+ { 1, "PSSR indication" },
+ { 2, "USSR request" },
+ { 3, "USSN request" },
+ { 16, "PSSD response" },
+ { 17, "PSSR response" },
+ { 18, "USSR confirm" },
+ { 19, "USSN confirm" },
+ { 0, NULL }
+};
+
+static const value_string vals_msg_wait_ind[] = {
+ { 0, "Set indication inactive" },
+ { 1, "Set indication active" },
+ { 0, NULL }
+};
+
+static const value_string vals_msg_wait_type[] = {
+ { 0, "Voicemail message waiting" },
+ { 1, "Fax message waiting" },
+ { 2, "Electronic mail message waiting" },
+ { 3, "Other message waiting" },
+ { 0, NULL }
+};
+
+static const value_string vals_callback_num_pres[] = {
+ { 0, "Presentation allowed" },
+ { 1, "Presentation restricted" },
+ { 2, "Number not available" },
+ { 3, "[Reserved]" },
+ { 0, NULL }
+};
+
+static const value_string vals_callback_num_scrn[] = {
+ { 0, "User provided, not screened" },
+ { 1, "User provided, verified and passed" },
+ { 2, "User provided, verified and failed" },
+ { 3, "Network provided" },
+ { 0, NULL }
+};
+
+static const value_string vals_network_error_type[] = {
+ { 1, "ANSI-136" },
+ { 2, "IS-95" },
+ { 3, "GSM" },
+ { 4, "[Reserved]" },
+ { 0, NULL }
+};
+
+static const value_string vals_its_session_ind[] = {
+ { 0, "End of session indicator inactive" },
+ { 1, "End of session indicator active" },
+ { 0, NULL }
+};
+
+/* Data Coding Scheme: see 3GPP TS 23.040 and 3GPP TS 23.038 */
+static const value_string vals_dcs_sms_coding_group[] = {
+ { 0x00, "SMS DCS: General Data Coding indication - Uncompressed text, no message class" },
+ { 0x01, "SMS DCS: General Data Coding indication - Uncompressed text" },
+ { 0x02, "SMS DCS: General Data Coding indication - Compressed text, no message class" },
+ { 0x03, "SMS DCS: General Data Coding indication - Compressed text" },
+ { 0x04, "SMS DCS: Message Marked for Automatic Deletion - Uncompressed text, no message class" },
+ { 0x05, "SMS DCS: Message Marked for Automatic Deletion - Uncompressed text" },
+ { 0x06, "SMS DCS: Message Marked for Automatic Deletion - Compressed text, no message class" },
+ { 0x07, "SMS DCS: Message Marked for Automatic Deletion - Compressed text" },
+ { 0x08, "SMS DCS: Reserved" },
+ { 0x09, "SMS DCS: Reserved" },
+ { 0x0A, "SMS DCS: Reserved" },
+ { 0x0B, "SMS DCS: Reserved" },
+ { 0x0C, "SMS DCS: Message Waiting Indication - Discard Message" },
+ { 0x0D, "SMS DCS: Message Waiting Indication - Store Message (GSM 7-bit default alphabet)" },
+ { 0x0E, "SMS DCS: Message Waiting Indication - Store Message (UCS-2 character set)" },
+ { 0x0F, "SMS DCS: Data coding / message class" },
+ { 0x00, NULL }
+};
+
+static const true_false_string tfs_dcs_text_compression = {
+ "Compressed text",
+ "Uncompressed text"
+};
+
+static const true_false_string tfs_dcs_class_present = {
+ "Message class is present",
+ "No message class"
+};
+
+static const value_string vals_dcs_charset[] = {
+ { 0x00, "GSM 7-bit default alphabet" },
+ { 0x01, "8-bit data" },
+ { 0x02, "UCS-2 (16-bit) data" },
+ { 0x03, "Reserved" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_dcs_class[] = {
+ { 0x00, "Class 0" },
+ { 0x01, "Class 1 - ME specific" },
+ { 0x02, "Class 2 - (U)SIM specific" },
+ { 0x03, "Class 3 - TE specific" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_dcs_cbs_coding_group[] = {
+ { 0x00, "CBS DCS: Language using the GSM 7-bit default alphabet" },
+ { 0x01, "CBS DCS: Language indication at beginning of message" },
+ { 0x02, "CBS DCS: Language using the GSM 7-bit default alphabet" },
+ { 0x03, "CBS DCS: Reserved" },
+ { 0x04, "CBS DCS: General Data Coding indication - Uncompressed text, no message class" },
+ { 0x05, "CBS DCS: General Data Coding indication - Uncompressed text" },
+ { 0x06, "CBS DCS: General Data Coding indication - Compressed text, no message class" },
+ { 0x07, "CBS DCS: General Data Coding indication - Compressed text" },
+ { 0x08, "CBS DCS: Reserved" },
+ { 0x09, "CBS DCS: Message with User Data Header structure" },
+ { 0x0A, "CBS DCS: Reserved" },
+ { 0x0B, "CBS DCS: Reserved" },
+ { 0x0C, "CBS DCS: Reserved" },
+ { 0x0D, "CBS DCS: Reserved" },
+ { 0x0E, "CBS DCS: Defined by the WAP Forum" },
+ { 0x0F, "SMS DCS: Data coding / message class" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_dcs_cbs_language[] = {
+ { 0x00, "German" },
+ { 0x01, "English" },
+ { 0x02, "Italian" },
+ { 0x03, "French" },
+ { 0x04, "Spanish" },
+ { 0x05, "Dutch" },
+ { 0x06, "Swedish" },
+ { 0x07, "Danish" },
+ { 0x08, "Portuguese" },
+ { 0x09, "Finnish" },
+ { 0x0A, "Norwegian" },
+ { 0x0B, "Greek" },
+ { 0x0C, "Turkish" },
+ { 0x0D, "Hungarian" },
+ { 0x0E, "Polish" },
+ { 0x0F, "Language not specified" },
+ { 0x10, "GSM 7-bit default alphabet - message preceeded by language indication" },
+ { 0x11, "UCS-2 (16-bit) - message preceeded by language indication" },
+ { 0x20, "Czech" },
+ { 0x21, "Hebrew" },
+ { 0x22, "Arabic" },
+ { 0x23, "Russian" },
+ { 0x24, "Icelandic" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_dcs_cbs_class[] = {
+ { 0x00, "No message class" },
+ { 0x01, "Class 1 - User defined" },
+ { 0x02, "Class 2 - User defined" },
+ { 0x03, "Class 3 - TE specific" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_dcs_wap_class[] = {
+ { 0x00, "No message class" },
+ { 0x01, "Class 1 - ME specific" },
+ { 0x02, "Class 2 - (U)SIM specific" },
+ { 0x03, "Class 3 - TE specific" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_dcs_wap_charset[] = {
+ { 0x00, "Reserved" },
+ { 0x01, "8-bit data" },
+ { 0x02, "Reserved" },
+ { 0x03, "Reserved" },
+ { 0x00, NULL }
+};
+
+static dissector_handle_t gsm_sms_handle;
+
+/*!
+ * SMPP equivalent of mktime() (3). Convert date to standard 'time_t' format
+ *
+ * \param datestr The SMPP-formatted date to convert
+ * \param secs Returns the 'time_t' equivalent
+ * \param nsecs Returns the additional nano-seconds
+ *
+ * \return Whether time is specified relative or absolute
+ * \retval TRUE Relative time
+ * \retval FALSE Absolute time
+ */
+static gboolean
+smpp_mktime(const char *datestr, time_t *secs, int *nsecs)
+{
+ struct tm r_time;
+ time_t t_diff;
+ gboolean relative = FALSE;
+
+ r_time.tm_year = 10 * (datestr[0] - '0') + (datestr[1] - '0');
+ /*
+ * Y2K rollover date as recommended in appendix C
+ */
+ if (r_time.tm_year < 38)
+ r_time.tm_year += 100;
+ r_time.tm_mon = 10 * (datestr[2] - '0') + (datestr[3] - '0');
+ r_time.tm_mon--;
+ r_time.tm_mday = 10 * (datestr[4] - '0') + (datestr[5] - '0');
+ r_time.tm_hour = 10 * (datestr[6] - '0') + (datestr[7] - '0');
+ r_time.tm_min = 10 * (datestr[8] - '0') + (datestr[9] - '0');
+ r_time.tm_sec = 10 * (datestr[10] - '0') + (datestr[11] - '0');
+ r_time.tm_isdst = -1;
+ *secs = mktime(&r_time);
+ *nsecs = (datestr[12] - '0') * 100000000;
+ t_diff = (10 * (datestr[13] - '0') + (datestr[14] - '0')) * 900;
+ if (datestr[15] == '+')
+ *secs += t_diff;
+ else if (datestr[15] == '-')
+ *secs -= t_diff;
+ else /* Must be relative ('R') */
+ relative = TRUE;
+ return relative;
+}
+
+/*!
+ * Scanning routines to add standard types (byte, int, string...) to the
+ * protocol tree.
+ *
+ * \param tree The protocol tree to add to
+ * \param tvb Buffer containing the data
+ * \param field Actual field whose value needs displaying
+ * \param offset Location of field in buffer, returns location of
+ * next field
+ */
+static void
+smpp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ guint len;
+
+ len = tvb_strsize(tvb, *offset);
+ if (len > 1) {
+ proto_tree_add_string(tree, field, tvb, *offset, len,
+ (const char *) tvb_get_ptr(tvb, *offset, len));
+ }
+ (*offset) += len;
+}
+
+/* NOTE - caller must free the returned string! */
+static char *
+smpp_handle_string_return(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ gint len;
+ char *str;
+
+ len = tvb_strsize(tvb, *offset);
+ if (len > 1) {
+ str = (char *)tvb_get_stringz(tvb, *offset, &len);
+ proto_tree_add_string(tree, field, tvb, *offset, len, str);
+ } else {
+ str = g_malloc(1 * sizeof(char));
+ str[0] = '\0';
+ }
+ (*offset) += len;
+ return str;
+}
+
+static void
+smpp_handle_string_z(proto_tree *tree, tvbuff_t *tvb, int field, int *offset,
+ const char *null_string)
+{
+ gint len;
+
+ len = tvb_strsize(tvb, *offset);
+ if (len > 1) {
+ proto_tree_add_string(tree, field, tvb, *offset, len,
+ (const char *)tvb_get_ptr(tvb, *offset, len));
+ } else {
+ proto_tree_add_string(tree, field, tvb, *offset, len, null_string);
+ }
+ (*offset) += len;
+}
+
+static void
+smpp_handle_int1(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ guint8 val;
+
+ val = tvb_get_guint8(tvb, *offset);
+ proto_tree_add_uint(tree, field, tvb, *offset, 1, val);
+ (*offset)++;
+}
+
+static void
+smpp_handle_int2(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ guint val;
+
+ val = tvb_get_ntohs(tvb, *offset);
+ proto_tree_add_uint(tree, field, tvb, *offset, 2, val);
+ (*offset) += 2;
+}
+
+static void
+smpp_handle_int4(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ guint val;
+
+ val = tvb_get_ntohl(tvb, *offset);
+ proto_tree_add_uint(tree, field, tvb, *offset, 4, val);
+ (*offset) += 4;
+}
+
+static void
+smpp_handle_time(proto_tree *tree, tvbuff_t *tvb,
+ int field, int field_R, int *offset)
+{
+ char *strval;
+ gint len;
+ nstime_t tmptime;
+
+ strval = (char *) tvb_get_stringz(tvb, *offset, &len);
+ if (*strval)
+ {
+ if (smpp_mktime(strval, &tmptime.secs, &tmptime.nsecs))
+ proto_tree_add_time(tree, field_R, tvb, *offset, len, &tmptime);
+ else
+ proto_tree_add_time(tree, field, tvb, *offset, len, &tmptime);
+ }
+ g_free(strval);
+ *offset += len;
+}
+
+/*!
+ * Scanning routine to handle the destination-list of 'submit_multi'
+ *
+ * \param tree The protocol tree to add to
+ * \param tvb Buffer containing the data
+ * \param offset Location of field in buffer, returns location of
+ * next field
+ */
+static void
+smpp_handle_dlist(proto_tree *tree, tvbuff_t *tvb, int *offset)
+{
+ guint8 entries;
+ int tmpoff = *offset;
+ proto_item *sub_tree = NULL;
+ guint8 dest_flag;
+
+ if ((entries = tvb_get_guint8(tvb, tmpoff++)))
+ {
+ sub_tree = proto_tree_add_item(tree, hf_smpp_dlist,
+ tvb, *offset, 1, FALSE);
+ proto_item_add_subtree(sub_tree, ett_dlist);
+ }
+ while (entries--)
+ {
+ dest_flag = tvb_get_guint8(tvb, tmpoff++);
+ if (dest_flag == 1) /* SME address */
+ {
+ smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
+ smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
+ smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
+ }
+ else /* Distribution list */
+ {
+ smpp_handle_string(sub_tree, tvb, hf_smpp_dl_name, &tmpoff);
+ }
+ }
+ *offset = tmpoff;
+}
+
+/*!
+ * Scanning routine to handle the destination result list
+ * of 'submit_multi_resp'
+ *
+ * \param tree The protocol tree to add to
+ * \param tvb Buffer containing the data
+ * \param offset Location of field in buffer, returns location of
+ * next field
+ */
+static void
+smpp_handle_dlist_resp(proto_tree *tree, tvbuff_t *tvb, int *offset)
+{
+ guint8 entries;
+ int tmpoff = *offset;
+ proto_item *sub_tree = NULL;
+
+ if ((entries = tvb_get_guint8(tvb, tmpoff++)))
+ {
+ sub_tree = proto_tree_add_item(tree, hf_smpp_dlist_resp,
+ tvb, *offset, 1, FALSE);
+ proto_item_add_subtree(sub_tree, ett_dlist_resp);
+ }
+ while (entries--)
+ {
+ smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
+ smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
+ smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
+ smpp_handle_int4(sub_tree, tvb, hf_smpp_error_status_code, &tmpoff);
+ }
+ *offset = tmpoff;
+}
+
+/*!
+ * Scanning routine to handle all optional parameters of SMPP-operations.
+ * The parameters have the format Tag Length Value (TLV), with a 2-byte tag
+ * and 2-byte length.
+ *
+ * \param tree The protocol tree to add to
+ * \param tvb Buffer containing the data
+ * \param offset Location of field in buffer, returns location of
+ * next field
+ */
+static void
+smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset)
+{
+ proto_item *sub_tree = NULL;
+ guint tag;
+ guint length;
+ guint8 field;
+ guint8 major, minor;
+ char strval[BUFSIZ];
+
+ if (tvb_reported_length_remaining(tvb, *offset) >= 4)
+ {
+ sub_tree = proto_tree_add_item(tree, hf_smpp_opt_param,
+ tvb, *offset, 0, FALSE);
+ proto_item_add_subtree(sub_tree, ett_opt_param);
+ }
+
+ while (tvb_reported_length_remaining(tvb, *offset) >= 4)
+ {
+ tag = tvb_get_ntohs(tvb, *offset);
+ *offset += 2;
+ length = tvb_get_ntohs(tvb, *offset);
+ *offset += 2;
+ switch (tag) {
+ case 0x0005: /* dest_addr_subunit */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_dest_addr_subunit, offset);
+ break;
+ case 0x0006: /* dest_network_type */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_dest_network_type, offset);
+ break;
+ case 0x0007: /* dest_bearer_type */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_dest_bearer_type, offset);
+ break;
+ case 0x0008: /* dest_telematics_id */
+ smpp_handle_int2(sub_tree, tvb,
+ hf_smpp_dest_telematics_id, offset);
+ break;
+ case 0x000D: /* source_addr_subunit */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_source_addr_subunit, offset);
+ break;
+ case 0x000E: /* source_network_type */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_source_network_type, offset);
+ break;
+ case 0x000F: /* source_bearer_type */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_source_bearer_type, offset);
+ break;
+ case 0x0010: /* source_telematics_id */
+ smpp_handle_int2(sub_tree, tvb,
+ hf_smpp_source_telematics_id, offset);
+ break;
+ case 0x0017: /* qos_time_to_live */
+ smpp_handle_int4(sub_tree, tvb,
+ hf_smpp_qos_time_to_live, offset);
+ break;
+ case 0x0019: /* payload_type */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_payload_type, offset);
+ break;
+ case 0x001D: /* additional_status_info_text */
+ smpp_handle_string(sub_tree, tvb,
+ hf_smpp_additional_status_info_text, offset);
+ break;
+ case 0x001E: /* receipted_message_id */
+ smpp_handle_string(sub_tree, tvb,
+ hf_smpp_receipted_message_id, offset);
+ break;
+ case 0x0030: /* ms_msg_wait_facilities */
+ field = tvb_get_guint8(tvb, *offset);
+ proto_tree_add_item(sub_tree, hf_smpp_msg_wait_ind,
+ tvb, *offset, 1, field);
+ proto_tree_add_item(sub_tree, hf_smpp_msg_wait_type,
+ tvb, *offset, 1, field);
+ (*offset)++;
+ break;
+ case 0x0201: /* privacy_indicator */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_privacy_indicator, offset);
+ break;
+ case 0x0202: /* source_subaddress */
+ smpp_handle_string(sub_tree, tvb,
+ hf_smpp_source_subaddress, offset);
+ break;
+ case 0x0203: /* dest_subaddress */
+ smpp_handle_string(sub_tree, tvb,
+ hf_smpp_dest_subaddress, offset);
+ break;
+ case 0x0204: /* user_message_reference */
+ smpp_handle_int2(sub_tree, tvb,
+ hf_smpp_user_message_reference, offset);
+ break;
+ case 0x0205: /* user_response_code */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_user_response_code, offset);
+ break;
+ case 0x020A: /* source_port */
+ smpp_handle_int2(sub_tree, tvb,
+ hf_smpp_source_port, offset);
+ break;
+ case 0x020B: /* destination_port */
+ smpp_handle_int2(sub_tree, tvb,
+ hf_smpp_destination_port, offset);
+ break;
+ case 0x020C: /* sar_msg_ref_num */
+ smpp_handle_int2(sub_tree, tvb,
+ hf_smpp_sar_msg_ref_num, offset);
+ break;
+ case 0x020D: /* language_indicator */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_language_indicator, offset);
+ break;
+ case 0x020E: /* sar_total_segments */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_sar_total_segments, offset);
+ break;
+ case 0x020F: /* sar_segment_seqnum */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_sar_segment_seqnum, offset);
+ break;
+ case 0x0210: /* SC_interface_version */
+ field = tvb_get_guint8(tvb, *offset);
+ minor = field & 0x0F;
+ major = (field & 0xF0) >> 4;
+ sprintf(strval, "%u.%u", major, minor);
+ proto_tree_add_string(sub_tree, hf_smpp_SC_interface_version,
+ tvb, *offset, 1, strval);
+ (*offset)++;
+ break;
+ case 0x0302: /* callback_num_pres_ind */
+ field = tvb_get_guint8(tvb, *offset);
+ proto_tree_add_item(sub_tree, hf_smpp_callback_num_pres,
+ tvb, *offset, 1, field);
+ proto_tree_add_item(sub_tree, hf_smpp_callback_num_scrn,
+ tvb, *offset, 1, field);
+ (*offset)++;
+ break;
+ case 0x0303: /* callback_num_atag */
+ if (length)
+ proto_tree_add_item(sub_tree, hf_smpp_callback_num_atag,
+ tvb, *offset, length, FALSE);
+ (*offset) += length;
+ break;
+ case 0x0304: /* number_of_messages */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_number_of_messages, offset);
+ break;
+ case 0x0381: /* callback_num */
+ if (length)
+ proto_tree_add_item(sub_tree, hf_smpp_callback_num,
+ tvb, *offset, length, FALSE);
+ (*offset) += length;
+ break;
+ case 0x0420: /* dpf_result */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_dpf_result, offset);
+ break;
+ case 0x0421: /* set_dpf */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_set_dpf, offset);
+ break;
+ case 0x0422: /* ms_availability_status */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_ms_availability_status, offset);
+ break;
+ case 0x0423: /* network_error_code */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_network_error_type, offset);
+ smpp_handle_int2(sub_tree, tvb,
+ hf_smpp_network_error_code, offset);
+ (*offset) += length;
+ break;
+ case 0x0424: /* message_payload */
+ if (length)
+ proto_tree_add_item(sub_tree, hf_smpp_message_payload,
+ tvb, *offset, length, FALSE);
+ (*offset) += length;
+ break;
+ case 0x0425: /* delivery_failure_reason */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_delivery_failure_reason, offset);
+ break;
+ case 0x0426: /* more_messages_to_send */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_more_messages_to_send, offset);
+ break;
+ case 0x0427: /* message_state */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_message_state, offset);
+ break;
+ case 0x0501: /* ussd_service_op */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_ussd_service_op, offset);
+ break;
+ case 0x1201: /* display_time */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_display_time, offset);
+ break;
+ case 0x1203: /* sms_signal */
+ smpp_handle_int2(sub_tree, tvb,
+ hf_smpp_sms_signal, offset);
+ /*! \todo Fill as per TIA/EIA-136-710-A */
+ break;
+ case 0x1204: /* ms_validity */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_ms_validity, offset);
+ break;
+ case 0x130C: /* alert_on_message_delivery */
+ proto_tree_add_item(sub_tree,
+ hf_smpp_alert_on_message_delivery,
+ tvb, *offset, length, FALSE);
+ (*offset) += length;
+ break;
+ case 0x1380: /* its_reply_type */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_its_reply_type, offset);
+ break;
+ case 0x1383: /* its_session_info */
+ smpp_handle_int1(sub_tree, tvb,
+ hf_smpp_its_session_number, offset);
+ field = tvb_get_guint8(tvb, *offset);
+ proto_tree_add_item(sub_tree, hf_smpp_its_session_sequence,
+ tvb, *offset, 1, field);
+ proto_tree_add_item(sub_tree, hf_smpp_its_session_ind,
+ tvb, *offset, 1, field);
+ (*offset)++;
+ break;
+ default:
+ if ((tag >= 0x1400) && (tag <= 0x3FFF))
+ proto_tree_add_item(sub_tree, hf_smpp_vendor_op, tvb,
+ *offset, length, FALSE);
+ else
+ proto_tree_add_item(sub_tree, hf_smpp_reserved_op, tvb,
+ *offset, length, FALSE);
+ (*offset) += length;
+ break;
+ }
+ }
+}
+
+static void
+smpp_handle_dcs(proto_tree *tree, tvbuff_t *tvb, int *offset)
+{
+ guint8 val;
+ int off = *offset;
+ proto_item *subtree = NULL;
+
+ val = tvb_get_guint8(tvb, off);
+ subtree = proto_tree_add_uint(tree,
+ hf_smpp_data_coding, tvb, off, 1, val);
+ proto_item_add_subtree(subtree, ett_dcs);
+ /* SMPP Data Coding Scheme */
+ proto_tree_add_uint(subtree, hf_smpp_dcs, tvb, off, 1, val);
+ /* GSM SMS Data Coding Scheme */
+ proto_tree_add_text(subtree, tvb, off, 1,
+ "GSM SMS Data Coding");
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_sms_coding_group, tvb, off, 1, val);
+ if (val>>6 == 2) { /* Reserved */
+ ;
+ } else if (val < 0xF0) {
+ proto_tree_add_boolean(subtree,
+ hf_smpp_dcs_text_compression, tvb, off, 1, val);
+ proto_tree_add_boolean(subtree,
+ hf_smpp_dcs_class_present, tvb, off, 1, val);
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_charset, tvb, off, 1, val);
+ if (val & 0x10)
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_class, tvb, off, 1, val);
+ } else {
+ if (val & 0x08)
+ proto_tree_add_text(subtree, tvb, off, 1,
+ "SMPP: Bit .... 1... should be 0 (reserved)");
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_charset, tvb, off, 1, val);
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_class, tvb, off, 1, val);
+ }
+ /* Cell Broadcast Service (CBS) Data Coding Scheme */
+ proto_tree_add_text(subtree, tvb, off, 1,
+ "GSM CBS Data Coding");
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_cbs_coding_group, tvb, off, 1, val);
+ if (val < 0x40) { /* Language specified */
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_cbs_language, tvb, off, 1, val);
+ } else if (val>>6 == 1) { /* General Data Coding indication */
+ proto_tree_add_boolean(subtree,
+ hf_smpp_dcs_text_compression, tvb, off, 1, val);
+ proto_tree_add_boolean(subtree,
+ hf_smpp_dcs_class_present, tvb, off, 1, val);
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_charset, tvb, off, 1, val);
+ if (val & 0x10)
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_class, tvb, off, 1, val);
+ } else if (val>>6 == 2) { /* Message with UDH structure */
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_charset, tvb, off, 1, val);
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_class, tvb, off, 1, val);
+ } else if (val>>4 == 14) { /* WAP Forum */
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_wap_charset, tvb, off, 1, val);
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_wap_class, tvb, off, 1, val);
+ } else if (val>>4 == 15) { /* Data coding / message handling */
+ if (val & 0x08)
+ proto_tree_add_text(subtree, tvb, off, 1,
+ "SMPP: Bit .... 1... should be 0 (reserved)");
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_charset, tvb, off, 1, val);
+ proto_tree_add_uint(subtree,
+ hf_smpp_dcs_cbs_class, tvb, off, 1, val);
+ }
+
+ (*offset)++;
+}
+
+/*!
+ * The next set of routines handle the different operations, associated
+ * with SMPP.
+ */
+static void
+bind_receiver(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+ guint8 field;
+ guint8 major, minor;
+ char strval[BUFSIZ];
+
+ smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_system_type, &offset);
+ field = tvb_get_guint8(tvb, offset++);
+ minor = field & 0x0F;
+ major = (field & 0xF0) >> 4;
+ sprintf(strval, "%u.%u", major, minor);
+ proto_tree_add_string(tree, hf_smpp_interface_version, tvb,
+ offset - 1, 1, strval);
+ smpp_handle_int1(tree, tvb, hf_smpp_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_address_range, &offset);
+}
+
+#define bind_transmitter(a, b) bind_receiver(a, b)
+
+static void
+query_sm(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+
+ smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
+}
+
+#define bind_transceiver(a, b) bind_receiver(a, b)
+
+static void
+outbind(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+
+ smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
+}
+
+static void
+submit_sm(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *top_tree)
+{
+ tvbuff_t *tvb_msg;
+ int offset = 0;
+ guint8 flag, udhi;
+ guint8 length;
+ char *src_str = NULL;
+ char *dst_str = NULL;
+ address save_src, save_dst;
+
+ smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
+ src_str = smpp_handle_string_return(tree, tvb, hf_smpp_source_addr, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
+ dst_str = smpp_handle_string_return(tree, tvb, hf_smpp_destination_addr, &offset);
+ flag = tvb_get_guint8(tvb, offset);
+ udhi = flag & 0x40;
+ proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
+ tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
+ tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_esm_submit_features,
+ tvb, offset, 1, flag);
+ offset++;
+ smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
+ if (tvb_get_guint8(tvb,offset)) {
+ smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
+ hf_smpp_schedule_delivery_time_r, &offset);
+ } else { /* Time = NULL means Immediate delivery */
+ proto_tree_add_text(tree, tvb, offset++, 1,
+ "Scheduled delivery time: Immediate delivery");
+ }
+ if (tvb_get_guint8(tvb,offset)) {
+ smpp_handle_time(tree, tvb, hf_smpp_validity_period,
+ hf_smpp_validity_period_r, &offset);
+ } else { /* Time = NULL means SMSC default validity */
+ proto_tree_add_text(tree, tvb, offset++, 1,
+ "Validity period: SMSC default validity period");
+ }
+ flag = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
+ offset++;
+ smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
+ smpp_handle_dcs(tree, tvb, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
+ length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
+ if (length)
+ {
+ proto_tree_add_item(tree, hf_smpp_short_message,
+ tvb, offset, length, FALSE);
+ if (udhi) /* UDHI indicator present */
+ {
+ DebugLog(("UDHI present - set addresses\n"));
+ /* Save original addresses */
+ COPY_ADDRESS(&save_src, &(pinfo->src));
+ COPY_ADDRESS(&save_dst, &(pinfo->dst));
+ /* Set SMPP source and destination address */
+ SET_ADDRESS(&(pinfo->src), AT_STRINGZ, 1+strlen(src_str), src_str);
+ SET_ADDRESS(&(pinfo->dst), AT_STRINGZ, 1+strlen(dst_str), dst_str);
+ tvb_msg = tvb_new_subset (tvb, offset,
+ MIN(length, tvb_reported_length(tvb) - offset), length);
+ call_dissector (gsm_sms_handle, tvb_msg, pinfo, top_tree);
+ /* Restore original addresses */
+ COPY_ADDRESS(&(pinfo->src), &save_src);
+ COPY_ADDRESS(&(pinfo->dst), &save_dst);
+ /* Get rid of SMPP text string addresses */
+ g_free(src_str);
+ g_free(dst_str);
+ }
+ offset += length;
+ }
+ smpp_handle_tlv(tree, tvb, &offset);
+}
+
+#define deliver_sm(a, b, c, d) submit_sm(a, b, c, d)
+
+static void
+replace_sm(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+ guint8 flag;
+ guint8 length;
+
+ smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
+ if (tvb_get_guint8(tvb,offset)) {
+ smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
+ hf_smpp_schedule_delivery_time_r, &offset);
+ } else { /* Time = NULL */
+ proto_tree_add_text(tree, tvb, offset++, 1,
+ "Scheduled delivery time: Keep initial delivery time setting");
+ }
+ if (tvb_get_guint8(tvb,offset)) {
+ smpp_handle_time(tree, tvb, hf_smpp_validity_period,
+ hf_smpp_validity_period_r, &offset);
+ } else { /* Time = NULL */
+ proto_tree_add_text(tree, tvb, offset++, 1,
+ "Validity period: Keep initial validity period setting");
+ }
+ flag = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
+ offset++;
+ smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
+ length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
+ if (length)
+ proto_tree_add_item(tree, hf_smpp_short_message,
+ tvb, offset, length, FALSE);
+ offset += length;
+}
+
+static void
+cancel_sm(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+
+ smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
+ smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
+}
+
+static void
+submit_multi(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+ guint8 flag;
+ guint8 length;
+
+ smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
+
+ smpp_handle_dlist(tree, tvb, &offset);
+
+ flag = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
+ tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
+ tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_esm_submit_features,
+ tvb, offset, 1, flag);
+ offset++;
+ smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
+ if (tvb_get_guint8(tvb,offset)) {
+ smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
+ hf_smpp_schedule_delivery_time_r, &offset);
+ } else { /* Time = NULL means Immediate delivery */
+ proto_tree_add_text(tree, tvb, offset++, 1,
+ "Scheduled delivery time: Immediate delivery");
+ }
+ if (tvb_get_guint8(tvb,offset)) {
+ smpp_handle_time(tree, tvb, hf_smpp_validity_period,
+ hf_smpp_validity_period_r, &offset);
+ } else { /* Time = NULL means SMSC default validity */
+ proto_tree_add_text(tree, tvb, offset++, 1,
+ "Validity period: SMSC default validity period");
+ }
+ flag = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
+ offset++;
+ smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
+ smpp_handle_dcs(tree, tvb, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
+ length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
+ if (length)
+ proto_tree_add_item(tree, hf_smpp_short_message,
+ tvb, offset, length, FALSE);
+ offset += length;
+ smpp_handle_tlv(tree, tvb, &offset);
+}
+
+static void
+alert_notification(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_esme_addr, &offset);
+ smpp_handle_tlv(tree, tvb, &offset);
+}
+
+static void
+data_sm(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+ guint8 flag;
+
+ smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
+ smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
+ flag = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
+ tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
+ tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_esm_submit_features,
+ tvb, offset, 1, flag);
+ offset++;
+ flag = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
+ proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
+ offset++;
+ smpp_handle_dcs(tree, tvb, &offset);
+ smpp_handle_tlv(tree, tvb, &offset);
+}
+
+/*!
+ * The next set of routines handle the different operation-responses,
+ * associated with SMPP.
+ */
+static void
+bind_receiver_resp(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+
+ smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
+ smpp_handle_tlv(tree, tvb, &offset);
+}
+
+#define bind_transmitter_resp(a, b) bind_receiver_resp(a, b)
+
+static void
+query_sm_resp(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+
+ smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
+ smpp_handle_time(tree, tvb, hf_smpp_final_date,
+ hf_smpp_final_date_r, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_message_state, &offset);
+ smpp_handle_int1(tree, tvb, hf_smpp_error_code, &offset);
+}
+
+#define bind_transceiver_resp(a, b) bind_receiver_resp(a, b)
+
+static void
+submit_sm_resp(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+
+ smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
+}
+
+#define deliver_sm_resp(a, b) submit_sm_resp(a, b)
+
+static void
+submit_multi_resp(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+
+ smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
+ smpp_handle_dlist_resp(tree, tvb, &offset);
+}
+
+static void
+data_sm_resp(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+
+ smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
+ smpp_handle_tlv(tree, tvb, &offset);
+}
+
+/*
+ * A 'heuristic dissector' that attemtps to establish whether we have
+ * a genuine SMPP PDU here.
+ * Only works when:
+ * at least the fixed header is there
+ * it has a correct overall PDU length
+ * it is a 'well-known' operation
+ * has a 'well-known' status
+ */
+static gboolean
+dissect_smpp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint command_id; /* SMPP command */
+ guint command_status; /* Status code */
+ guint command_length; /* length of PDU */
+
+ if (tvb_reported_length(tvb) < 4 * 4) /* Mandatory header */
+ return FALSE;
+ command_length = tvb_get_ntohl(tvb, 0);
+ if (command_length > 64 * 1024)
+ return FALSE;
+ command_id = tvb_get_ntohl(tvb, 4); /* Only known commands */
+ if (match_strval(command_id, vals_command_id) == NULL)
+ return FALSE;
+ command_status = tvb_get_ntohl(tvb, 8); /* ..with known status */
+ if (match_strval(command_status, vals_command_status) == NULL)
+ return FALSE;
+ dissect_smpp(tvb, pinfo, tree);
+ return TRUE;
+}
+
+static guint
+get_smpp_pdu_len(tvbuff_t *tvb, int offset)
+{
+ return tvb_get_ntohl(tvb, offset);
+}
+
+/*
+ * This global SMPP variable is used to determine whether the PDU to dissect
+ * is the first SMPP PDU in the packet (or reassembled buffer), requiring
+ * different column update code than subsequent SMPP PDUs within this packet
+ * (or reassembled buffer).
+ *
+ * FIXME - This approach is NOT dissection multi-thread safe!
+ */
+static gboolean first = TRUE;
+
+static void
+dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ first = TRUE;
+ if (pinfo->ptype == PT_TCP) { /* are we running on top of TCP */
+ tcp_dissect_pdus(tvb, pinfo, tree,
+ reassemble_over_tcp, /* Do we try to reassemble */
+ 16, /* Length of fixed header */
+ get_smpp_pdu_len, /* Function returning PDU len */
+ dissect_smpp_pdu); /* PDU dissector */
+ } else { /* no? probably X.25 */
+ guint32 offset = 0;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ guint16 pdu_len = tvb_get_ntohl(tvb, offset);
+ gint pdu_real_len = tvb_length_remaining(tvb, offset);
+ tvbuff_t *pdu_tvb;
+
+ if (pdu_real_len <= 0)
+ return;
+ if (pdu_real_len > pdu_len)
+ pdu_real_len = pdu_len;
+ pdu_tvb = tvb_new_subset(tvb, offset, pdu_real_len, pdu_len);
+ dissect_smpp_pdu(pdu_tvb, pinfo, tree);
+ offset += pdu_len;
+ first = FALSE;
+ }
+ }
+}
+
+
+/* Dissect a single SMPP PDU contained within "tvb". */
+static void
+dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0; /* Offset within tvbuff */
+ guint command_length; /* length of PDU */
+ guint command_id; /* SMPP command */
+ guint command_status; /* Status code */
+ guint sequence_number; /* ...of command */
+ gchar *command_str;
+ gchar *command_status_str = NULL;
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti = NULL;
+ proto_tree *smpp_tree = NULL;
+
+ /*
+ * Safety: don't even try to dissect the PDU
+ * when the mandatory header isn't present.
+ */
+ if (tvb_reported_length(tvb) < 4 * 4)
+ return;
+ command_length = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ command_id = tvb_get_ntohl(tvb, offset);
+ command_str = val_to_str(command_id, vals_command_id,
+ "(Unknown SMPP Operation 0x%08X)");
+ offset += 4;
+ command_status = tvb_get_ntohl(tvb, offset);
+ if (command_id & 0x80000000) {
+ command_status_str = val_to_str(command_status, vals_command_status,
+ "(Reserved Error 0x%08X)");
+ }
+ offset += 4;
+ sequence_number = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ /*
+ * Update the protocol column.
+ */
+ if (first == TRUE) {
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMPP");
+ }
+
+ /*
+ * Create display subtree for the protocol
+ */
+ if (tree) {
+ ti = proto_tree_add_item (tree, proto_smpp, tvb, 0, tvb->length, FALSE);
+ smpp_tree = proto_item_add_subtree (ti, ett_smpp);
+ }
+
+ /*
+ * Cycle over the encapsulated PDUs
+ */
+ {
+ tvbuff_t *pdu_tvb;
+
+ /*
+ * Make entries in the Info column on the summary display
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (first == TRUE) {
+ /*
+ * First PDU - We already computed the fixed header
+ */
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "SMPP %s", command_str);
+ first = FALSE;
+ } else {
+ /*
+ * Subsequent PDUs
+ */
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", command_str);
+ }
+ /*
+ * Display command status of responses in Info column
+ */
+ if (command_id & 0x80000000) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"",
+ command_status_str);
+ }
+ }
+
+ /*
+ * Create a tvb for the current PDU.
+ * Physical length: at most command_length
+ * Reported length: command_length
+ */
+ if (tvb_length_remaining(tvb, offset - 16 + command_length) > 0) {
+ pdu_tvb = tvb_new_subset(tvb, offset - 16,
+ command_length, /* Physical length */
+ command_length); /* Length reported by the protocol */
+ } else {
+ pdu_tvb = tvb_new_subset(tvb, offset - 16,
+ tvb_length_remaining(tvb, offset - 16),/* Physical length */
+ command_length); /* Length reported by the protocol */
+ }
+
+ /*
+ * Dissect the PDU
+ *
+ * If "tree" is NULL, Ethereal is only interested in creation
+ * of conversations, reassembly and subdissection but not in
+ * the detailed protocol tree.
+ * In the interest of speed, skip the generation of protocol tree
+ * items when "tree" is NULL.
+ *
+ * The only PDU which requires subdissection currently is the
+ * sm_submit PDU (command ID = 0x00000004).
+ */
+ if (tree || (command_id == 4))
+ {
+ /*
+ * Create display subtree for the PDU
+ */
+ if (tree) {
+ proto_tree_add_uint(smpp_tree, hf_smpp_command_length,
+ pdu_tvb, 0, 4, command_length);
+ proto_tree_add_uint(smpp_tree, hf_smpp_command_id,
+ pdu_tvb, 4, 4, command_id);
+ proto_item_append_text(ti, ", Command: %s", command_str);
+
+ /*
+ * Status is only meaningful with responses
+ */
+ if (command_id & 0x80000000) {
+ proto_tree_add_uint(smpp_tree, hf_smpp_command_status,
+ pdu_tvb, 8, 4, command_status);
+ proto_item_append_text (ti, ", Status: \"%s\"",
+ command_status_str);
+ }
+ proto_tree_add_uint(smpp_tree, hf_smpp_sequence_number,
+ pdu_tvb, 12, 4, sequence_number);
+ proto_item_append_text(ti, ", Seq: %u, Len: %u",
+ sequence_number, command_length);
+ }
+
+ /*
+ * End of fixed header.
+ * Don't dissect variable part if it is shortened.
+ *
+ * FIXME - We then do not report a Short Frame or Malformed Packet
+ */
+ if (command_length <= tvb_reported_length(pdu_tvb))
+ {
+ tvbuff_t *tmp_tvb = tvb_new_subset(pdu_tvb, 16,
+ -1, command_length - 16);
+ if (command_id & 0x80000000)
+ {
+ switch (command_id & 0x7FFFFFFF) {
+ /*
+ * All of these only have a fixed header
+ */
+ case 0: /* Generic nack */
+ case 6: /* Unbind resp */
+ case 7: /* Replace SM resp */
+ case 8: /* Cancel SM resp */
+ case 21: /* Enquire link resp */
+ break;
+ case 1:
+ if (!command_status)
+ bind_receiver_resp(smpp_tree, tmp_tvb);
+ break;
+ case 2:
+ if (!command_status)
+ bind_transmitter_resp(smpp_tree, tmp_tvb);
+ break;
+ case 3:
+ if (!command_status)
+ query_sm_resp(smpp_tree, tmp_tvb);
+ break;
+ case 4:
+ if (!command_status)
+ submit_sm_resp(smpp_tree, tmp_tvb);
+ break;
+ case 5:
+ if (!command_status)
+ deliver_sm_resp(smpp_tree, tmp_tvb);
+ break;
+ case 9:
+ if (!command_status)
+ bind_transceiver_resp(smpp_tree, tmp_tvb);
+ break;
+ case 33:
+ if (!command_status)
+ submit_multi_resp(smpp_tree, tmp_tvb);
+ break;
+ case 259:
+ if (!command_status)
+ data_sm_resp(smpp_tree, tmp_tvb);
+ break;
+ default:
+ break;
+ } /* switch (command_id & 0x7FFFFFFF) */
+ }
+ else
+ {
+ switch (command_id) {
+ case 1:
+ bind_receiver(smpp_tree, tmp_tvb);
+ break;
+ case 2:
+ bind_transmitter(smpp_tree, tmp_tvb);
+ break;
+ case 3:
+ query_sm(smpp_tree, tmp_tvb);
+ break;
+ case 4:
+ submit_sm(smpp_tree, tmp_tvb, pinfo, tree);
+ break;
+ case 5:
+ deliver_sm(smpp_tree, tmp_tvb, pinfo, tree);
+ break;
+ case 6: /* Unbind */
+ case 21: /* Enquire link */
+ break;
+ case 7:
+ replace_sm(smpp_tree, tmp_tvb);
+ break;
+ case 8:
+ cancel_sm(smpp_tree, tmp_tvb);
+ break;
+ case 9:
+ bind_transceiver(smpp_tree, tmp_tvb);
+ break;
+ case 11:
+ outbind(smpp_tree, tmp_tvb);
+ break;
+ case 33:
+ submit_multi(smpp_tree, tmp_tvb);
+ break;
+ case 258:
+ alert_notification(smpp_tree, tmp_tvb);
+ break;
+ case 259:
+ data_sm(smpp_tree, tmp_tvb);
+ break;
+ default:
+ break;
+ } /* switch (command_id) */
+ } /* if (command_id & 0x80000000) */
+ } /* if (command_length <= tvb_reported_length(pdu_tvb)) */
+ offset += command_length;
+ } /* if (tree || (command_id == 4)) */
+ first = FALSE;
+ }
+
+ return;
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_smpp(void)
+{
+ module_t *smpp_module; /* Preferences for SMPP */
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_smpp_command_length,
+ { "Length ", "smpp.command_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Total length of the SMPP PDU.",
+ HFILL
+ }
+ },
+ { &hf_smpp_command_id,
+ { "Operation ", "smpp.command_id",
+ FT_UINT32, BASE_HEX, VALS(vals_command_id), 0x00,
+ "Defines the SMPP PDU.",
+ HFILL
+ }
+ },
+ { &hf_smpp_command_status,
+ { "Result ", "smpp.command_status",
+ FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
+ "Indicates success or failure of the SMPP request.",
+ HFILL
+ }
+ },
+ { &hf_smpp_sequence_number,
+ { "Sequence #", "smpp.sequence_number",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "A number to correlate requests with responses.",
+ HFILL
+ }
+ },
+ { &hf_smpp_system_id,
+ { "System ID", "smpp.system_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Identifies a system.",
+ HFILL
+ }
+ },
+ { &hf_smpp_password,
+ { "Password", "smpp.password",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Password used for authentication.",
+ HFILL
+ }
+ },
+ { &hf_smpp_system_type,
+ { "System type", "smpp.system_type",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Categorises the system.",
+ HFILL
+ }
+ },
+ { &hf_smpp_interface_version,
+ { "Version (if)", "smpp.interface_version",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Version of SMPP interface supported.",
+ HFILL
+ }
+ },
+ { &hf_smpp_service_type,
+ { "Service type", "smpp.service_type",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SMS application service associated with the message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_addr_ton,
+ { "Type of number", "smpp.addr_ton",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
+ "Indicates the type of number, given in the address.",
+ HFILL
+ }
+ },
+ { &hf_smpp_source_addr_ton,
+ { "Type of number (originator)", "smpp.source_addr_ton",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
+ "Indicates originator type of number, given in the address.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dest_addr_ton,
+ { "Type of number (recipient)", "smpp.dest_addr_ton",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
+ "Indicates recipient type of number, given in the address.",
+ HFILL
+ }
+ },
+ { &hf_smpp_addr_npi,
+ { "Numbering plan indicator", "smpp.addr_npi",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
+ "Gives the numbering plan this address belongs to.",
+ HFILL
+ }
+ },
+ { &hf_smpp_source_addr_npi,
+ { "Numbering plan indicator (originator)", "smpp.source_addr_npi",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
+ "Gives originator numbering plan this address belongs to.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dest_addr_npi,
+ { "Numbering plan indicator (recipient)", "smpp.dest_addr_npi",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
+ "Gives recipient numbering plan this address belongs to.",
+ HFILL
+ }
+ },
+ { &hf_smpp_address_range,
+ { "Address", "smpp.address_range",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Given address or address range.",
+ HFILL
+ }
+ },
+ { &hf_smpp_source_addr,
+ { "Originator address", "smpp.source_addr",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Address of SME originating this message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_destination_addr,
+ { "Recipient address", "smpp.destination_addr",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Address of SME receiving this message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_esm_submit_msg_mode,
+ { "Messaging mode", "smpp.esm.submit.msg_mode",
+ FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_mode), 0x03,
+ "Mode attribute for this message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_esm_submit_msg_type,
+ { "Message type ", "smpp.esm.submit.msg_type",
+ FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_type), 0x3C,
+ "Type attribute for this message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_esm_submit_features,
+ { "GSM features ", "smpp.esm.submit.features",
+ FT_UINT8, BASE_HEX, VALS(vals_esm_submit_features), 0xC0,
+ "GSM network specific features.",
+ HFILL
+ }
+ },
+ /*! \todo Get proper values from GSM-spec. */
+ { &hf_smpp_protocol_id,
+ { "Protocol id.", "smpp.protocol_id",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Protocol identifier according GSM 03.40.",
+ HFILL
+ }
+ },
+ { &hf_smpp_priority_flag,
+ { "Priority level", "smpp.priority_flag",
+ FT_UINT8, BASE_HEX, VALS(vals_priority_flag), 0x00,
+ "The priority level of the short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_schedule_delivery_time,
+ { "Scheduled delivery time", "smpp.schedule_delivery_time",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Scheduled time for delivery of short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_schedule_delivery_time_r,
+ { "Scheduled delivery time", "smpp.schedule_delivery_time_r",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "Scheduled time for delivery of short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_validity_period,
+ { "Validity period", "smpp.validity_period",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Validity period of this message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_validity_period_r,
+ { "Validity period", "smpp.validity_period_r",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "Validity period of this message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_regdel_receipt,
+ { "Delivery receipt ", "smpp.regdel.receipt",
+ FT_UINT8, BASE_HEX, VALS(vals_regdel_receipt), 0x03,
+ "SMSC delivery receipt request.",
+ HFILL
+ }
+ },
+ { &hf_smpp_regdel_acks,
+ { "Message type ", "smpp.regdel.acks",
+ FT_UINT8, BASE_HEX, VALS(vals_regdel_acks), 0x0C,
+ "SME acknowledgement request.",
+ HFILL
+ }
+ },
+ { &hf_smpp_regdel_notif,
+ { "Intermediate notif", "smpp.regdel.notif",
+ FT_UINT8, BASE_HEX, VALS(vals_regdel_notif), 0x10,
+ "Intermediate notification request.",
+ HFILL
+ }
+ },
+ { &hf_smpp_replace_if_present_flag,
+ { "Replace ", "smpp.replace_if_present_flag",
+ FT_UINT8, BASE_HEX, VALS(vals_replace_if_present_flag), 0x01,
+ "Replace the short message with this one or not.",
+ HFILL
+ }
+ },
+ { &hf_smpp_data_coding,
+ { "Data coding", "smpp.data_coding",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Defines the encoding scheme of the message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_sm_default_msg_id,
+ { "Predefined message", "smpp.sm_default_msg_id",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Index of a predefined ('canned') short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_sm_length,
+ { "Message length", "smpp.sm_length",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Length of the message content.",
+ HFILL
+ }
+ },
+ { &hf_smpp_short_message,
+ { "Message", "smpp.message",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "The actual message or data.",
+ HFILL
+ }
+ },
+ { &hf_smpp_message_id,
+ { "Message id.", "smpp.message_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Identifier of the submitted short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dlist,
+ { "Destination list", "smpp.dlist",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "The list of destinations for a short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dlist_resp,
+ { "Unsuccesfull delivery list", "smpp.dlist_resp",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "The list of unsuccesfull deliveries to destinations.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dl_name,
+ { "Distr. list name", "smpp.dl_name",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "The name of the distribution list.",
+ HFILL
+ }
+ },
+ { &hf_smpp_final_date,
+ { "Final date", "smpp.final_date",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Date-time when the queried message reached a final state.",
+ HFILL
+ }
+ },
+ { &hf_smpp_final_date_r,
+ { "Final date", "smpp.final_date_r",
+ FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
+ "Date-time when the queried message reached a final state.",
+ HFILL
+ }
+ },
+ { &hf_smpp_message_state,
+ { "Message state", "smpp.message_state",
+ FT_UINT8, BASE_DEC, VALS(vals_message_state), 0x00,
+ "Specifies the status of the queried short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_error_code,
+ { "Error code", "smpp.error_code",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Network specific error code defining reason for failure.",
+ HFILL
+ }
+ },
+ { &hf_smpp_error_status_code,
+ { "Status", "smpp.error_status_code",
+ FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
+ "Indicates success/failure of request for this address.",
+ HFILL
+ }
+ },
+ { &hf_smpp_esme_addr_ton,
+ { "Type of number (ESME)", "smpp.esme_addr_ton",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
+ "Indicates recipient type of number, given in the address.",
+ HFILL
+ }
+ },
+ { &hf_smpp_esme_addr_npi,
+ { "Numbering plan indicator (ESME)", "smpp.esme_addr_npi",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
+ "Gives the numbering plan this address belongs to.",
+ HFILL
+ }
+ },
+ { &hf_smpp_esme_addr,
+ { "ESME address", "smpp.esme_addr",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Address of ESME originating this message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dest_addr_subunit,
+ { "Subunit destination", "smpp.dest_addr_subunit",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
+ "Subunit address within mobile to route message to.",
+ HFILL
+ }
+ },
+ { &hf_smpp_source_addr_subunit,
+ { "Subunit origin", "smpp.source_addr_subunit",
+ FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
+ "Subunit address within mobile that generated the message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dest_network_type,
+ { "Destination network", "smpp.dest_network_type",
+ FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
+ "Network associated with the destination address.",
+ HFILL
+ }
+ },
+ { &hf_smpp_source_network_type,
+ { "Originator network", "smpp.source_network_type",
+ FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
+ "Network associated with the originator address.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dest_bearer_type,
+ { "Destination bearer", "smpp.dest_bearer_type",
+ FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
+ "Desired bearer for delivery of message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_source_bearer_type,
+ { "Originator bearer", "smpp.source_bearer_type",
+ FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
+ "Bearer over which the message originated.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dest_telematics_id,
+ { "Telematic interworking (dest)", "smpp.dest_telematics_id",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Telematic interworking to be used for message delivery.",
+ HFILL
+ }
+ },
+ { &hf_smpp_source_telematics_id,
+ { "Telematic interworking (orig)", "smpp.source_telematics_id",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Telematic interworking used for message submission.",
+ HFILL
+ }
+ },
+ { &hf_smpp_qos_time_to_live,
+ { "Validity period", "smpp.qos_time_to_live",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Number of seconds to retain message before expiry.",
+ HFILL
+ }
+ },
+ { &hf_smpp_payload_type,
+ { "Payload", "smpp.payload_type",
+ FT_UINT8, BASE_DEC, VALS(vals_payload_type), 0x00,
+ "PDU type contained in the message payload.",
+ HFILL
+ }
+ },
+ { &hf_smpp_additional_status_info_text,
+ { "Information", "smpp.additional_status_info_text",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Description of the meaning of a response PDU.",
+ HFILL
+ }
+ },
+ { &hf_smpp_receipted_message_id,
+ { "SMSC identifier", "smpp.receipted_message_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "SMSC handle of the message being received.",
+ HFILL
+ }
+ },
+ { &hf_smpp_privacy_indicator,
+ { "Privacy indicator", "smpp.privacy_indicator",
+ FT_UINT8, BASE_DEC, VALS(vals_privacy_indicator), 0x00,
+ "Indicates the privacy level of the message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_user_message_reference,
+ { "Message reference", "smpp.user_message_reference",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Reference to the message, assigned by the user.",
+ HFILL
+ }
+ },
+ { &hf_smpp_user_response_code,
+ { "Application response code", "smpp.user_response_code",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "A response code set by the user.",
+ HFILL
+ }
+ },
+ { &hf_smpp_language_indicator,
+ { "Language", "smpp.language_indicator",
+ FT_UINT8, BASE_DEC, VALS(vals_language_indicator), 0x00,
+ "Indicates the language of the short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_source_port,
+ { "Source port", "smpp.source_port",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Application port associated with the source of the message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_destination_port,
+ { "Destination port", "smpp.destination_port",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Application port associated with the destination of the message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_sar_msg_ref_num,
+ { "SAR reference number", "smpp.sar_msg_ref_num",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Reference number for a concatenated short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_sar_total_segments,
+ { "SAR size", "smpp.sar_total_segments",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Number of segments of a concatenated short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_sar_segment_seqnum,
+ { "SAR sequence number", "smpp.sar_segment_seqnum",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Segment number within a concatenated short message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_display_time,
+ { "Display time", "smpp.display_time",
+ FT_UINT8, BASE_DEC, VALS(vals_display_time), 0x00,
+ "Associates a display time with the message on the handset.",
+ HFILL
+ }
+ },
+ { &hf_smpp_ms_validity,
+ { "Validity info", "smpp.ms_validity",
+ FT_UINT8, BASE_DEC, VALS(vals_ms_validity), 0x00,
+ "Associates validity info with the message on the handset.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dpf_result,
+ { "Delivery pending set?", "smpp.dpf_result",
+ FT_UINT8, BASE_DEC, VALS(vals_dpf_result), 0x00,
+ "Indicates whether Delivery Pending Flag was set.",
+ HFILL
+ }
+ },
+ { &hf_smpp_set_dpf,
+ { "Request DPF set", "smpp.set_dpf",
+ FT_UINT8, BASE_DEC, VALS(vals_set_dpf), 0x00,
+ "Request to set the DPF for certain failure scenario's.",
+ HFILL
+ }
+ },
+ { &hf_smpp_ms_availability_status,
+ { "Availability status", "smpp.ms_availability_status",
+ FT_UINT8, BASE_DEC, VALS(vals_ms_availability_status), 0x00,
+ "Indicates the availability state of the handset.",
+ HFILL
+ }
+ },
+ { &hf_smpp_delivery_failure_reason,
+ { "Delivery failure reason", "smpp.delivery_failure_reason",
+ FT_UINT8, BASE_DEC, VALS(vals_delivery_failure_reason), 0x00,
+ "Indicates the reason for a failed delivery attempt.",
+ HFILL
+ }
+ },
+ { &hf_smpp_more_messages_to_send,
+ { "More messages?", "smpp.more_messages_to_send",
+ FT_UINT8, BASE_DEC, VALS(vals_more_messages_to_send), 0x00,
+ "Indicates more messages pending for the same destination.",
+ HFILL
+ }
+ },
+ { &hf_smpp_number_of_messages,
+ { "Number of messages", "smpp.number_of_messages",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Indicates number of messages stored in a mailbox.",
+ HFILL
+ }
+ },
+ { &hf_smpp_its_reply_type,
+ { "Reply method", "smpp.its_reply_type",
+ FT_UINT8, BASE_DEC, VALS(vals_its_reply_type), 0x00,
+ "Indicates the handset reply method on message receipt.",
+ HFILL
+ }
+ },
+ { &hf_smpp_ussd_service_op,
+ { "USSD service operation", "smpp.ussd_service_op",
+ FT_UINT8, BASE_DEC, VALS(vals_ussd_service_op), 0x00,
+ "Indicates the USSD service operation.",
+ HFILL
+ }
+ },
+ { &hf_smpp_vendor_op,
+ { "Optional parameter - Vendor-specific", "smpp.vendor_op",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "A supplied optional parameter specific to an SMSC-vendor.",
+ HFILL
+ }
+ },
+ { &hf_smpp_reserved_op,
+ { "Optional parameter - Reserved", "smpp.reserved_op",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "An optional parameter that is reserved in this version.",
+ HFILL
+ }
+ },
+ { &hf_smpp_msg_wait_ind,
+ { "Indication", "smpp.msg_wait.ind",
+ FT_UINT8, BASE_HEX, VALS(vals_msg_wait_ind), 0x80,
+ "Indicates to the handset that a message is waiting.",
+ HFILL
+ }
+ },
+ { &hf_smpp_msg_wait_type,
+ { "Type ", "smpp.msg_wait.type",
+ FT_UINT8, BASE_HEX, VALS(vals_msg_wait_type), 0x03,
+ "Indicates type of message that is waiting.",
+ HFILL
+ }
+ },
+ { &hf_smpp_SC_interface_version,
+ { "SMSC-supported version", "smpp.SC_interface_version",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Version of SMPP interface supported by the SMSC.",
+ HFILL
+ }
+ },
+ { &hf_smpp_callback_num_pres,
+ { "Presentation", "smpp.callback_num.pres",
+ FT_UINT8, BASE_HEX, VALS(vals_callback_num_pres), 0x0C,
+ "Controls the presentation indication.",
+ HFILL
+ }
+ },
+ { &hf_smpp_callback_num_scrn,
+ { "Screening ", "smpp.callback_num.scrn",
+ FT_UINT8, BASE_HEX, VALS(vals_callback_num_scrn), 0x03,
+ "Controls screening of the callback-number.",
+ HFILL
+ }
+ },
+ { &hf_smpp_callback_num_atag,
+ { "Callback number - alphanumeric display tag",
+ "smpp.callback_num_atag",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Associates an alphanumeric display with call back number.",
+ HFILL
+ }
+ },
+ { &hf_smpp_callback_num,
+ { "Callback number", "smpp.callback_num",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Associates a call back number with the message.",
+ HFILL
+ }
+ },
+ { &hf_smpp_network_error_type,
+ { "Error type", "smpp.network_error.type",
+ FT_UINT8, BASE_DEC, VALS(vals_network_error_type), 0x00,
+ "Indicates the network type.",
+ HFILL
+ }
+ },
+ { &hf_smpp_network_error_code,
+ { "Error code", "smpp.network_error.code",
+ FT_UINT16, BASE_HEX, NULL, 0x00,
+ "Gives the actual network error code.",
+ HFILL
+ }
+ },
+ { &hf_smpp_message_payload,
+ { "Payload", "smpp.message_payload",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Short message user data.",
+ HFILL
+ }
+ },
+ { &hf_smpp_alert_on_message_delivery,
+ { "Alert on delivery", "smpp.alert_on_message_delivery",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Instructs the handset to alert user on message delivery.",
+ HFILL
+ }
+ },
+ { &hf_smpp_its_session_number,
+ { "Session number", "smpp.its_session.number",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Session number of interactive teleservice.",
+ HFILL
+ }
+ },
+ { &hf_smpp_its_session_sequence,
+ { "Sequence number ", "smpp.its_session.sequence",
+ FT_UINT8, BASE_HEX, NULL, 0xFE,
+ "Sequence number of the dialogue unit.",
+ HFILL
+ }
+ },
+ { &hf_smpp_its_session_ind,
+ { "Session indicator", "smpp.its_session.ind",
+ FT_UINT8, BASE_HEX, VALS(vals_its_session_ind), 0x01,
+ "Indicates whether this message is end of conversation.",
+ HFILL
+ }
+ },
+ { &hf_smpp_opt_param,
+ { "Optional parameters", "smpp.opt_param",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "The list of optional parameters in this operation.",
+ HFILL
+ }
+ },
+ /*
+ * Data Coding Scheme
+ */
+ { &hf_smpp_dcs,
+ { "SMPP Data Coding Scheme", "smpp.dcs",
+ FT_UINT8, BASE_HEX, VALS(vals_data_coding), 0x00,
+ "Data Coding Scheme according to SMPP.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dcs_sms_coding_group,
+ { "DCS Coding Group for SMS", "smpp.dcs.sms_coding_group",
+ FT_UINT8, BASE_HEX, VALS(vals_dcs_sms_coding_group), 0xF0,
+ "Data Coding Scheme coding group for GSM Short Message Service.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dcs_text_compression,
+ { "DCS Text compression", "smpp.dcs.text_compression",
+ FT_BOOLEAN, 8, TFS(&tfs_dcs_text_compression), 0x20,
+ "Indicates if text compression is used.", HFILL
+ }
+ },
+ { &hf_smpp_dcs_class_present,
+ { "DCS Class present", "smpp.dcs.class_present",
+ FT_BOOLEAN, 8, TFS(&tfs_dcs_class_present), 0x10,
+ "Indicates if the message class is present (defined).", HFILL
+ }
+ },
+ { &hf_smpp_dcs_charset,
+ { "DCS Character set", "smpp.dcs.charset",
+ FT_UINT8, BASE_HEX, VALS(vals_dcs_charset), 0x0C,
+ "Specifies the character set used in the message.", HFILL
+ }
+ },
+ { &hf_smpp_dcs_class,
+ { "DCS Message class", "smpp.dcs.class",
+ FT_UINT8, BASE_HEX, VALS(vals_dcs_class), 0x03,
+ "Specifies the message class.", HFILL
+ }
+ },
+ { &hf_smpp_dcs_cbs_coding_group,
+ { "DCS Coding Group for CBS", "smpp.dcs.cbs_coding_group",
+ FT_UINT8, BASE_HEX, VALS(vals_dcs_cbs_coding_group), 0xF0,
+ "Data Coding Scheme coding group for GSM Cell Broadcast Service.",
+ HFILL
+ }
+ },
+ { &hf_smpp_dcs_cbs_language,
+ { "DCS CBS Message language", "smpp.dcs.cbs_language",
+ FT_UINT8, BASE_HEX, VALS(vals_dcs_cbs_language), 0x3F,
+ "Language of the GSM Cell Broadcast Service message.", HFILL
+ }
+ },
+ { &hf_smpp_dcs_cbs_class,
+ { "DCS CBS Message class", "smpp.dcs.cbs_class",
+ FT_UINT8, BASE_HEX, VALS(vals_dcs_cbs_class), 0x03,
+ "Specifies the message class for GSM Cell Broadcast Service, "
+ "for the Data coding / message handling code group.", HFILL
+ }
+ },
+ { &hf_smpp_dcs_wap_charset,
+ { "DCS Message coding", "smpp.dcs.wap_coding",
+ FT_UINT8, BASE_HEX, VALS(vals_dcs_wap_charset), 0x0C,
+ "Specifies the used message encoding, "
+ "as specified by the WAP Forum (WAP over GSM USSD).", HFILL
+ }
+ },
+ { &hf_smpp_dcs_wap_class,
+ { "DCS CBS Message class", "smpp.dcs.wap_class",
+ FT_UINT8, BASE_HEX, VALS(vals_dcs_wap_class), 0x03,
+ "Specifies the message class for GSM Cell Broadcast Service, "
+ "as specified by the WAP Forum (WAP over GSM USSD).", HFILL
+ }
+ },
+ };
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_smpp,
+ &ett_dlist,
+ &ett_dlist_resp,
+ &ett_opt_param,
+ &ett_dcs,
+ };
+ DebugLog(("Registering SMPP dissector\n"));
+ /* Register the protocol name and description */
+ proto_smpp = proto_register_protocol("Short Message Peer to Peer",
+ "SMPP", "smpp");
+
+ /* Required function calls to register header fields and subtrees used */
+ proto_register_field_array(proto_smpp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Preferences */
+ smpp_module = prefs_register_protocol (proto_smpp, NULL);
+ prefs_register_bool_preference (smpp_module,
+ "reassemble_smpp_over_tcp",
+ "Reassemble SMPP over TCP",
+ "Reassemble TCP segments that convey SMPP traffic.",
+ &reassemble_over_tcp);
+}
+
+/*
+ * If dissector uses sub-dissector registration add a registration routine.
+ * This format is required because a script is used to find these routines and
+ * create the code that calls these routines.
+ */
+void
+proto_reg_handoff_smpp(void)
+{
+ dissector_handle_t smpp_handle;
+
+ /*
+ * SMPP can be spoken on any port under TCP or X.25
+ * ...how *do* we do that under X.25?
+ *
+ * We can register the heuristic SMPP dissector with X.25, for one
+ * thing. We don't currently have any mechanism to allow the user
+ * to specify that a given X.25 circuit is to be dissected as SMPP,
+ * however.
+ */
+ smpp_handle = create_dissector_handle(dissect_smpp, proto_smpp);
+ dissector_add_handle("tcp.port", smpp_handle);
+ heur_dissector_add("tcp", dissect_smpp_heur, proto_smpp);
+ heur_dissector_add("x.25", dissect_smpp_heur, proto_smpp);
+
+ /* Required for call_dissector() */
+ DebugLog(("Finding gsm-sms-ud subdissector\n"));
+ gsm_sms_handle = find_dissector("gsm-sms-ud");
+ g_assert (gsm_sms_handle);
+}
diff --git a/epan/dissectors/packet-smtp.c b/epan/dissectors/packet-smtp.c
new file mode 100644
index 0000000000..f95978411c
--- /dev/null
+++ b/epan/dissectors/packet-smtp.c
@@ -0,0 +1,597 @@
+/* packet-smtp.c
+ * Routines for SMTP packet disassembly
+ *
+ * $Id$
+ *
+ * Copyright (c) 2000 by Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1999 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include <epan/resolv.h>
+#include "prefs.h"
+#include <epan/strutil.h>
+
+#define TCP_PORT_SMTP 25
+
+static int proto_smtp = -1;
+
+static int hf_smtp_req = -1;
+static int hf_smtp_rsp = -1;
+static int hf_smtp_req_command = -1;
+static int hf_smtp_req_parameter = -1;
+static int hf_smtp_rsp_code = -1;
+static int hf_smtp_rsp_parameter = -1;
+
+static int ett_smtp = -1;
+static int ett_smtp_cmdresp = -1;
+
+/* desegmentation of SMTP command and response lines */
+static gboolean smtp_desegment = TRUE;
+
+/*
+ * A CMD is an SMTP command, MESSAGE is the message portion, and EOM is the
+ * last part of a message
+ */
+
+#define SMTP_PDU_CMD 0
+#define SMTP_PDU_MESSAGE 1
+#define SMTP_PDU_EOM 2
+
+struct smtp_proto_data {
+ guint16 pdu_type;
+};
+
+static int smtp_packet_init_count = 100;
+
+/*
+ * State information stored with a conversation.
+ */
+struct smtp_request_val {
+ gboolean reading_data; /* Reading message data, not commands */
+ guint16 crlf_seen; /* Have we seen a CRLF on the end of a packet */
+};
+
+static GMemChunk *smtp_request_vals = NULL;
+static GMemChunk *smtp_packet_infos = NULL;
+
+static void
+smtp_init_protocol(void)
+{
+ if (smtp_request_vals)
+ g_mem_chunk_destroy(smtp_request_vals);
+ if (smtp_packet_infos)
+ g_mem_chunk_destroy(smtp_packet_infos);
+
+ smtp_request_vals = g_mem_chunk_new("smtp_request_vals",
+ sizeof(struct smtp_request_val),
+ smtp_packet_init_count * sizeof(struct smtp_request_val), G_ALLOC_AND_FREE);
+ smtp_packet_infos = g_mem_chunk_new("smtp_packet_infos",
+ sizeof(struct smtp_proto_data),
+ smtp_packet_init_count * sizeof(struct smtp_proto_data), G_ALLOC_AND_FREE);
+
+}
+
+static void
+dissect_smtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct smtp_proto_data *frame_data;
+ proto_tree *smtp_tree;
+ proto_tree *cmdresp_tree;
+ proto_item *ti;
+ int offset = 0;
+ int request = 0;
+ conversation_t *conversation;
+ struct smtp_request_val *request_val;
+ const guchar *line;
+ guint32 code;
+ int linelen;
+ gint length_remaining;
+ gboolean eom_seen = FALSE;
+ gint next_offset;
+ gboolean is_continuation_line;
+ int cmdlen;
+
+ /* As there is no guarantee that we will only see frames in the
+ * the SMTP conversation once, and that we will see them in
+ * order - in Ethereal, the user could randomly click on frames
+ * in the conversation in any order in which they choose - we
+ * have to store information with each frame indicating whether
+ * it contains commands or data or an EOM indication.
+ *
+ * XXX - what about frames that contain *both*? TCP is a
+ * byte-stream protocol, and there are no guarantees that
+ * TCP segment boundaries will correspond to SMTP commands
+ * or EOM indications.
+ *
+ * We only need that for the client->server stream; responses
+ * are easy to manage.
+ *
+ * If we have per frame data, use that, else, we must be on the first
+ * pass, so we figure it out on the first pass.
+ */
+
+ /* Find out what conversation this packet is part of ... but only
+ * if we have no information on this packet, so find the per-frame
+ * info first.
+ */
+
+ /* SMTP messages have a simple format ... */
+
+ request = pinfo -> destport == pinfo -> match_port;
+
+ /*
+ * Get the first line from the buffer.
+ *
+ * Note that "tvb_find_line_end()" will, if it doesn't return
+ * -1, return a value that is not longer than what's in the buffer,
+ * and "tvb_find_line_end()" will always return a value that is not
+ * longer than what's in the buffer, so the "tvb_get_ptr()" call
+ * won't throw an exception.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
+ smtp_desegment && pinfo->can_desegment);
+ if (linelen == -1) {
+ /*
+ * We didn't find a line ending, and we're doing desegmentation;
+ * tell the TCP dissector where the data for this message starts
+ * in the data it handed us, and tell it we need one more byte
+ * (we may need more, but we'll try again if what we get next
+ * isn't enough), and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 1;
+ return;
+ }
+ line = tvb_get_ptr(tvb, offset, linelen);
+
+ frame_data = p_get_proto_data(pinfo->fd, proto_smtp);
+
+ if (!frame_data) {
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL) { /* No conversation, create one */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ }
+
+ /*
+ * Is there a request structure attached to this conversation?
+ */
+ request_val = conversation_get_proto_data(conversation, proto_smtp);
+
+ if (!request_val) {
+
+ /*
+ * No - create one and attach it.
+ */
+ request_val = g_mem_chunk_alloc(smtp_request_vals);
+ request_val->reading_data = FALSE;
+ request_val->crlf_seen = 0;
+
+ conversation_add_proto_data(conversation, proto_smtp, request_val);
+
+ }
+
+ /*
+ * Check whether or not this packet is an end of message packet
+ * We should look for CRLF.CRLF and they may be split.
+ * We have to keep in mind that we may see what we want on
+ * two passes through here ...
+ */
+
+ if (request_val->reading_data) {
+
+ /*
+ * The order of these is important ... We want to avoid
+ * cases where there is a CRLF at the end of a packet and a
+ * .CRLF at the begining of the same packet.
+ */
+
+ if ((request_val->crlf_seen && tvb_strneql(tvb, offset, ".\r\n", 3) == 0) ||
+ tvb_strneql(tvb, offset, "\r\n.\r\n", 5) == 0) {
+
+ eom_seen = TRUE;
+
+ }
+
+ length_remaining = tvb_length_remaining(tvb, offset);
+ if (length_remaining == tvb_reported_length_remaining(tvb, offset) &&
+ tvb_strneql(tvb, offset + length_remaining - 2, "\r\n", 2) == 0) {
+
+ request_val->crlf_seen = 1;
+
+ }
+ else {
+
+ request_val->crlf_seen = 0;
+
+ }
+ }
+
+ /*
+ * OK, Check if we have seen a DATA request. We do it here for
+ * simplicity, but we have to be careful below.
+ */
+
+ if (request) {
+
+ frame_data = g_mem_chunk_alloc(smtp_packet_infos);
+
+ if (request_val->reading_data) {
+ /*
+ * This is message data.
+ */
+ if (eom_seen) { /* Seen the EOM */
+ /*
+ * EOM.
+ * Everything that comes after it is commands.
+ *
+ * XXX - what if the EOM isn't at the beginning of
+ * the TCP segment? It can occur anywhere....
+ */
+ frame_data->pdu_type = SMTP_PDU_EOM;
+ request_val->reading_data = FALSE;
+ } else {
+ /*
+ * Message data with no EOM.
+ */
+ frame_data->pdu_type = SMTP_PDU_MESSAGE;
+ }
+ } else {
+ /*
+ * This is commands - unless the capture started in the
+ * middle of a session, and we're in the middle of data.
+ * To quote RFC 821, "Command codes are four alphabetic
+ * characters"; if we don't see four alphabetic characters
+ * and, if there's anything else in the line, a space, we
+ * assume it's not a command.
+ * (We treat only A-Z and a-z as alphabetic.)
+ */
+#define ISALPHA(c) (((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= 'a' && (c) <= 'z'))
+ if (linelen >= 4 && ISALPHA(line[0]) && ISALPHA(line[1]) &&
+ ISALPHA(line[2]) && ISALPHA(line[3]) &&
+ (linelen == 4 || line[4] == ' ')) {
+ if (strncasecmp(line, "DATA", 4) == 0) {
+
+ /*
+ * DATA command.
+ * This is a command, but everything that comes after it,
+ * until an EOM, is data.
+ */
+ frame_data->pdu_type = SMTP_PDU_CMD;
+ request_val->reading_data = TRUE;
+
+ } else {
+
+ /*
+ * Regular command.
+ */
+ frame_data->pdu_type = SMTP_PDU_CMD;
+
+ }
+ } else {
+ if ((linelen >= 7) && line[0] == 'X' && ( (strncasecmp(line, "X-EXPS ", 7) == 0) ||
+ ((linelen >=13) && (strncasecmp(line, "X-LINK2STATE ", 13) == 0)) ||
+ ((linelen >= 8) && (strncasecmp(line, "XEXCH50 ", 8) == 0)) ))
+ frame_data->pdu_type = SMTP_PDU_CMD;
+ else
+ /*
+ * Assume it's message data.
+ */
+
+ frame_data->pdu_type = SMTP_PDU_MESSAGE;
+
+ }
+
+ }
+
+ p_add_proto_data(pinfo->fd, proto_smtp, frame_data);
+
+ }
+ }
+
+ /*
+ * From here, we simply add items to the tree and info to the info
+ * fields ...
+ */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMTP");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) { /* Add the appropriate type here */
+
+ /*
+ * If it is a request, we have to look things up, otherwise, just
+ * display the right things
+ */
+
+ if (request) {
+
+ /* We must have frame_data here ... */
+
+ switch (frame_data->pdu_type) {
+ case SMTP_PDU_MESSAGE:
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Message Body");
+ break;
+
+ case SMTP_PDU_EOM:
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "EOM: %s",
+ format_text(line, linelen));
+ break;
+
+ case SMTP_PDU_CMD:
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Command: %s",
+ format_text(line, linelen));
+ break;
+
+ }
+
+ }
+ else {
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Response: %s",
+ format_text(line, linelen));
+
+ }
+ }
+
+ if (tree) { /* Build the tree info ... */
+
+ ti = proto_tree_add_item(tree, proto_smtp, tvb, offset, -1, FALSE);
+ smtp_tree = proto_item_add_subtree(ti, ett_smtp);
+ if (request) {
+
+ /*
+ * Check out whether or not we can see a command in there ...
+ * What we are looking for is not data_seen and the word DATA
+ * and not eom_seen.
+ *
+ * We will see DATA and request_val->data_seen when we process the
+ * tree view after we have seen a DATA packet when processing
+ * the packet list pane.
+ *
+ * On the first pass, we will not have any info on the packets
+ * On second and subsequent passes, we will.
+ */
+
+ switch (frame_data->pdu_type) {
+
+ case SMTP_PDU_MESSAGE:
+
+ /*
+ * Message body.
+ * Put its lines into the protocol tree, a line at a time.
+ */
+ while (tvb_offset_exists(tvb, offset)) {
+
+ /*
+ * Find the end of the line.
+ */
+ tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+
+ /*
+ * Put this line.
+ */
+ proto_tree_add_text(smtp_tree, tvb, offset, next_offset - offset,
+ "Message: %s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+
+ /*
+ * Step to the next line.
+ */
+ offset = next_offset;
+
+ }
+
+ break;
+
+ case SMTP_PDU_EOM:
+
+ /*
+ * End-of-message-body indicator.
+ *
+ * XXX - what about stuff after the first line?
+ * Unlikely, as the client should wait for a response to the
+ * DATA command this terminates before sending another
+ * request, but we should probably handle it.
+ */
+ proto_tree_add_text(smtp_tree, tvb, offset, linelen,
+ "EOM: %s", format_text(line, linelen));
+
+ break;
+
+ case SMTP_PDU_CMD:
+
+ /*
+ * Command.
+ *
+ * XXX - what about stuff after the first line?
+ * Unlikely, as the client should wait for a response to the
+ * previous command before sending another request, but we
+ * should probably handle it.
+ */
+ if (linelen >= 4)
+ cmdlen = 4;
+ else
+ cmdlen = linelen;
+ proto_tree_add_boolean_hidden(smtp_tree, hf_smtp_req, tvb,
+ 0, 0, TRUE);
+ /*
+ * Put the command line into the protocol tree.
+ */
+ ti = proto_tree_add_text(smtp_tree, tvb, offset, next_offset - offset,
+ "Command: %s",
+ tvb_format_text(tvb, offset, next_offset - offset));
+ cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);
+
+ proto_tree_add_item(cmdresp_tree, hf_smtp_req_command, tvb,
+ offset, cmdlen, FALSE);
+ if (linelen > 5) {
+ proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb,
+ offset + 5, linelen - 5, FALSE);
+ }
+
+ }
+
+ }
+ else {
+
+ /*
+ * Process the response, a line at a time, until we hit a line
+ * that doesn't have a continuation indication on it.
+ */
+ proto_tree_add_boolean_hidden(smtp_tree, hf_smtp_rsp, tvb,
+ 0, 0, TRUE);
+
+ while (tvb_offset_exists(tvb, offset)) {
+
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+
+ /*
+ * Put it into the protocol tree.
+ */
+ ti = proto_tree_add_text(smtp_tree, tvb, offset,
+ next_offset - offset, "Response: %s",
+ tvb_format_text(tvb, offset,
+ next_offset - offset));
+ cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);
+
+ /*
+ * Is it a continuation line?
+ */
+ is_continuation_line =
+ (linelen >= 4 && tvb_get_guint8(tvb, offset + 3) == '-');
+
+ /*
+ * Put the response code and parameters into the protocol tree.
+ */
+ line = tvb_get_ptr(tvb, offset, linelen);
+ if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1])
+ && isdigit(line[2])) {
+ /*
+ * We have a 3-digit response code.
+ */
+ code = (line[0] - '0')*100 + (line[1] - '0')*10 + (line[2] - '0');
+ proto_tree_add_uint(cmdresp_tree, hf_smtp_rsp_code, tvb, offset, 3,
+ code);
+
+ if (linelen >= 4) {
+ proto_tree_add_item(cmdresp_tree, hf_smtp_rsp_parameter, tvb,
+ offset + 4, linelen - 4, FALSE);
+ }
+ }
+
+ /*
+ * Step past this line.
+ */
+ offset = next_offset;
+
+ /*
+ * If it's not a continuation line, quit.
+ */
+ if (!is_continuation_line)
+ break;
+
+ }
+
+ }
+ }
+}
+
+/* Register all the bits needed by the filtering engine */
+
+void
+proto_register_smtp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_smtp_req,
+ { "Request", "smtp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_smtp_rsp,
+ { "Response", "smtp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+ { &hf_smtp_req_command,
+ { "Command", "smtp.req.command", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_smtp_req_parameter,
+ { "Request parameter", "smtp.req.parameter", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_smtp_rsp_code,
+ { "Response code", "smtp.response.code", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_smtp_rsp_parameter,
+ { "Response parameter", "smtp.rsp.parameter", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_smtp,
+ &ett_smtp_cmdresp,
+ };
+ module_t *smtp_module;
+
+ /* No Configuration options to register? */
+
+ proto_smtp = proto_register_protocol("Simple Mail Transfer Protocol",
+ "SMTP", "smtp");
+
+ proto_register_field_array(proto_smtp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&smtp_init_protocol);
+
+ smtp_module = prefs_register_protocol(proto_smtp, NULL);
+ prefs_register_bool_preference(smtp_module, "desegment_lines",
+ "Desegment all SMTP command and response lines\nspanning multiple TCP segments",
+ "Whether the SMTP dissector should desegment all command and response lines spanning multiple TCP segments",
+ &smtp_desegment);
+}
+
+/* The registration hand-off routine */
+void
+proto_reg_handoff_smtp(void)
+{
+ dissector_handle_t smtp_handle;
+
+ smtp_handle = create_dissector_handle(dissect_smtp, proto_smtp);
+ dissector_add("tcp.port", TCP_PORT_SMTP, smtp_handle);
+}
diff --git a/epan/dissectors/packet-sna.c b/epan/dissectors/packet-sna.c
new file mode 100644
index 0000000000..be53b18c43
--- /dev/null
+++ b/epan/dissectors/packet-sna.c
@@ -0,0 +1,3597 @@
+/* packet-sna.c
+ * Routines for SNA
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ * Jochen Friedrich <jochen@scram.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "llcsaps.h"
+#include "ppptypes.h"
+#include <epan/sna-utils.h>
+#include "prefs.h"
+#include "reassemble.h"
+#include "util.h"
+
+/*
+ * http://www.wanresources.com/snacell.html
+ * ftp://ftp.software.ibm.com/networking/pub/standards/aiw/formats/
+ *
+ */
+
+static int proto_sna = -1;
+static int proto_sna_xid = -1;
+static int hf_sna_th = -1;
+static int hf_sna_th_0 = -1;
+static int hf_sna_th_fid = -1;
+static int hf_sna_th_mpf = -1;
+static int hf_sna_th_odai = -1;
+static int hf_sna_th_efi = -1;
+static int hf_sna_th_daf = -1;
+static int hf_sna_th_oaf = -1;
+static int hf_sna_th_snf = -1;
+static int hf_sna_th_dcf = -1;
+static int hf_sna_th_lsid = -1;
+static int hf_sna_th_tg_sweep = -1;
+static int hf_sna_th_er_vr_supp_ind = -1;
+static int hf_sna_th_vr_pac_cnt_ind = -1;
+static int hf_sna_th_ntwk_prty = -1;
+static int hf_sna_th_tgsf = -1;
+static int hf_sna_th_mft = -1;
+static int hf_sna_th_piubf = -1;
+static int hf_sna_th_iern = -1;
+static int hf_sna_th_nlpoi = -1;
+static int hf_sna_th_nlp_cp = -1;
+static int hf_sna_th_ern = -1;
+static int hf_sna_th_vrn = -1;
+static int hf_sna_th_tpf = -1;
+static int hf_sna_th_vr_cwi = -1;
+static int hf_sna_th_tg_nonfifo_ind = -1;
+static int hf_sna_th_vr_sqti = -1;
+static int hf_sna_th_tg_snf = -1;
+static int hf_sna_th_vrprq = -1;
+static int hf_sna_th_vrprs = -1;
+static int hf_sna_th_vr_cwri = -1;
+static int hf_sna_th_vr_rwi = -1;
+static int hf_sna_th_vr_snf_send = -1;
+static int hf_sna_th_dsaf = -1;
+static int hf_sna_th_osaf = -1;
+static int hf_sna_th_snai = -1;
+static int hf_sna_th_def = -1;
+static int hf_sna_th_oef = -1;
+static int hf_sna_th_sa = -1;
+static int hf_sna_th_cmd_fmt = -1;
+static int hf_sna_th_cmd_type = -1;
+static int hf_sna_th_cmd_sn = -1;
+
+static int hf_sna_nlp_nhdr = -1;
+static int hf_sna_nlp_nhdr_0 = -1;
+static int hf_sna_nlp_sm = -1;
+static int hf_sna_nlp_tpf = -1;
+static int hf_sna_nlp_nhdr_1 = -1;
+static int hf_sna_nlp_ft = -1;
+static int hf_sna_nlp_tspi = -1;
+static int hf_sna_nlp_slowdn1 = -1;
+static int hf_sna_nlp_slowdn2 = -1;
+static int hf_sna_nlp_fra = -1;
+static int hf_sna_nlp_anr = -1;
+static int hf_sna_nlp_frh = -1;
+static int hf_sna_nlp_thdr = -1;
+static int hf_sna_nlp_tcid = -1;
+static int hf_sna_nlp_thdr_8 = -1;
+static int hf_sna_nlp_setupi = -1;
+static int hf_sna_nlp_somi = -1;
+static int hf_sna_nlp_eomi = -1;
+static int hf_sna_nlp_sri = -1;
+static int hf_sna_nlp_rasapi = -1;
+static int hf_sna_nlp_retryi = -1;
+static int hf_sna_nlp_thdr_9 = -1;
+static int hf_sna_nlp_lmi = -1;
+static int hf_sna_nlp_cqfi = -1;
+static int hf_sna_nlp_osi = -1;
+static int hf_sna_nlp_offset = -1;
+static int hf_sna_nlp_dlf = -1;
+static int hf_sna_nlp_bsn = -1;
+static int hf_sna_nlp_opti_len = -1;
+static int hf_sna_nlp_opti_type = -1;
+static int hf_sna_nlp_opti_0d_version = -1;
+static int hf_sna_nlp_opti_0d_4 = -1;
+static int hf_sna_nlp_opti_0d_target = -1;
+static int hf_sna_nlp_opti_0d_arb = -1;
+static int hf_sna_nlp_opti_0d_reliable = -1;
+static int hf_sna_nlp_opti_0d_dedicated = -1;
+static int hf_sna_nlp_opti_0e_stat = -1;
+static int hf_sna_nlp_opti_0e_gap = -1;
+static int hf_sna_nlp_opti_0e_idle = -1;
+static int hf_sna_nlp_opti_0e_nabsp = -1;
+static int hf_sna_nlp_opti_0e_sync = -1;
+static int hf_sna_nlp_opti_0e_echo = -1;
+static int hf_sna_nlp_opti_0e_rseq = -1;
+static int hf_sna_nlp_opti_0e_abspbeg = -1;
+static int hf_sna_nlp_opti_0e_abspend = -1;
+static int hf_sna_nlp_opti_0f_bits = -1;
+static int hf_sna_nlp_opti_10_tcid = -1;
+static int hf_sna_nlp_opti_12_sense = -1;
+static int hf_sna_nlp_opti_14_si_len = -1;
+static int hf_sna_nlp_opti_14_si_key = -1;
+static int hf_sna_nlp_opti_14_si_2 = -1;
+static int hf_sna_nlp_opti_14_si_refifo = -1;
+static int hf_sna_nlp_opti_14_si_mobility = -1;
+static int hf_sna_nlp_opti_14_si_dirsearch = -1;
+static int hf_sna_nlp_opti_14_si_limitres = -1;
+static int hf_sna_nlp_opti_14_si_ncescope = -1;
+static int hf_sna_nlp_opti_14_si_mnpsrscv = -1;
+static int hf_sna_nlp_opti_14_si_maxpsize = -1;
+static int hf_sna_nlp_opti_14_si_switch = -1;
+static int hf_sna_nlp_opti_14_si_alive = -1;
+static int hf_sna_nlp_opti_14_rr_len = -1;
+static int hf_sna_nlp_opti_14_rr_key = -1;
+static int hf_sna_nlp_opti_14_rr_2 = -1;
+static int hf_sna_nlp_opti_14_rr_bfe = -1;
+static int hf_sna_nlp_opti_14_rr_num = -1;
+static int hf_sna_nlp_opti_22_2 = -1;
+static int hf_sna_nlp_opti_22_type = -1;
+static int hf_sna_nlp_opti_22_raa = -1;
+static int hf_sna_nlp_opti_22_parity = -1;
+static int hf_sna_nlp_opti_22_arb = -1;
+static int hf_sna_nlp_opti_22_3 = -1;
+static int hf_sna_nlp_opti_22_ratereq = -1;
+static int hf_sna_nlp_opti_22_raterep = -1;
+static int hf_sna_nlp_opti_22_field1 = -1;
+static int hf_sna_nlp_opti_22_field2 = -1;
+static int hf_sna_nlp_opti_22_field3 = -1;
+static int hf_sna_nlp_opti_22_field4 = -1;
+
+static int hf_sna_rh = -1;
+static int hf_sna_rh_0 = -1;
+static int hf_sna_rh_1 = -1;
+static int hf_sna_rh_2 = -1;
+static int hf_sna_rh_rri = -1;
+static int hf_sna_rh_ru_category = -1;
+static int hf_sna_rh_fi = -1;
+static int hf_sna_rh_sdi = -1;
+static int hf_sna_rh_bci = -1;
+static int hf_sna_rh_eci = -1;
+static int hf_sna_rh_dr1 = -1;
+static int hf_sna_rh_lcci = -1;
+static int hf_sna_rh_dr2 = -1;
+static int hf_sna_rh_eri = -1;
+static int hf_sna_rh_rti = -1;
+static int hf_sna_rh_rlwi = -1;
+static int hf_sna_rh_qri = -1;
+static int hf_sna_rh_pi = -1;
+static int hf_sna_rh_bbi = -1;
+static int hf_sna_rh_ebi = -1;
+static int hf_sna_rh_cdi = -1;
+static int hf_sna_rh_csi = -1;
+static int hf_sna_rh_edi = -1;
+static int hf_sna_rh_pdi = -1;
+static int hf_sna_rh_cebi = -1;
+/*static int hf_sna_ru = -1;*/
+
+static int hf_sna_gds = -1;
+static int hf_sna_gds_len = -1;
+static int hf_sna_gds_type = -1;
+static int hf_sna_gds_cont = -1;
+
+static int hf_sna_xid = -1;
+static int hf_sna_xid_0 = -1;
+static int hf_sna_xid_id = -1;
+static int hf_sna_xid_format = -1;
+static int hf_sna_xid_type = -1;
+static int hf_sna_xid_len = -1;
+static int hf_sna_xid_idblock = -1;
+static int hf_sna_xid_idnum = -1;
+static int hf_sna_xid_3_8 = -1;
+static int hf_sna_xid_3_init_self = -1;
+static int hf_sna_xid_3_stand_bind = -1;
+static int hf_sna_xid_3_gener_bind = -1;
+static int hf_sna_xid_3_recve_bind = -1;
+static int hf_sna_xid_3_actpu = -1;
+static int hf_sna_xid_3_nwnode = -1;
+static int hf_sna_xid_3_cp = -1;
+static int hf_sna_xid_3_cpcp = -1;
+static int hf_sna_xid_3_state = -1;
+static int hf_sna_xid_3_nonact = -1;
+static int hf_sna_xid_3_cpchange = -1;
+static int hf_sna_xid_3_10 = -1;
+static int hf_sna_xid_3_asend_bind = -1;
+static int hf_sna_xid_3_arecv_bind = -1;
+static int hf_sna_xid_3_quiesce = -1;
+static int hf_sna_xid_3_pucap = -1;
+static int hf_sna_xid_3_pbn = -1;
+static int hf_sna_xid_3_pacing = -1;
+static int hf_sna_xid_3_11 = -1;
+static int hf_sna_xid_3_tgshare = -1;
+static int hf_sna_xid_3_dedsvc = -1;
+static int hf_sna_xid_3_12 = -1;
+static int hf_sna_xid_3_negcsup = -1;
+static int hf_sna_xid_3_negcomp = -1;
+static int hf_sna_xid_3_15 = -1;
+static int hf_sna_xid_3_partg = -1;
+static int hf_sna_xid_3_dlur = -1;
+static int hf_sna_xid_3_dlus = -1;
+static int hf_sna_xid_3_exbn = -1;
+static int hf_sna_xid_3_genodai = -1;
+static int hf_sna_xid_3_branch = -1;
+static int hf_sna_xid_3_brnn = -1;
+static int hf_sna_xid_3_tg = -1;
+static int hf_sna_xid_3_dlc = -1;
+static int hf_sna_xid_3_dlen = -1;
+
+static int hf_sna_control_len = -1;
+static int hf_sna_control_key = -1;
+static int hf_sna_control_hprkey = -1;
+static int hf_sna_control_05_delay = -1;
+static int hf_sna_control_05_type = -1;
+static int hf_sna_control_05_ptp = -1;
+static int hf_sna_control_0e_type = -1;
+static int hf_sna_control_0e_value = -1;
+
+static gint ett_sna = -1;
+static gint ett_sna_th = -1;
+static gint ett_sna_th_fid = -1;
+static gint ett_sna_nlp_nhdr = -1;
+static gint ett_sna_nlp_nhdr_0 = -1;
+static gint ett_sna_nlp_nhdr_1 = -1;
+static gint ett_sna_nlp_thdr = -1;
+static gint ett_sna_nlp_thdr_8 = -1;
+static gint ett_sna_nlp_thdr_9 = -1;
+static gint ett_sna_nlp_opti_un = -1;
+static gint ett_sna_nlp_opti_0d = -1;
+static gint ett_sna_nlp_opti_0d_4 = -1;
+static gint ett_sna_nlp_opti_0e = -1;
+static gint ett_sna_nlp_opti_0e_stat = -1;
+static gint ett_sna_nlp_opti_0e_absp = -1;
+static gint ett_sna_nlp_opti_0f = -1;
+static gint ett_sna_nlp_opti_10 = -1;
+static gint ett_sna_nlp_opti_12 = -1;
+static gint ett_sna_nlp_opti_14 = -1;
+static gint ett_sna_nlp_opti_14_si = -1;
+static gint ett_sna_nlp_opti_14_si_2 = -1;
+static gint ett_sna_nlp_opti_14_rr = -1;
+static gint ett_sna_nlp_opti_14_rr_2 = -1;
+static gint ett_sna_nlp_opti_22 = -1;
+static gint ett_sna_nlp_opti_22_2 = -1;
+static gint ett_sna_nlp_opti_22_3 = -1;
+static gint ett_sna_rh = -1;
+static gint ett_sna_rh_0 = -1;
+static gint ett_sna_rh_1 = -1;
+static gint ett_sna_rh_2 = -1;
+static gint ett_sna_gds = -1;
+static gint ett_sna_xid_0 = -1;
+static gint ett_sna_xid_id = -1;
+static gint ett_sna_xid_3_8 = -1;
+static gint ett_sna_xid_3_10 = -1;
+static gint ett_sna_xid_3_11 = -1;
+static gint ett_sna_xid_3_12 = -1;
+static gint ett_sna_xid_3_15 = -1;
+static gint ett_sna_control_un = -1;
+static gint ett_sna_control_05 = -1;
+static gint ett_sna_control_05hpr = -1;
+static gint ett_sna_control_05hpr_type = -1;
+static gint ett_sna_control_0e = -1;
+
+static dissector_handle_t data_handle;
+
+/* Defragment fragmented SNA BIUs*/
+static gboolean sna_defragment = FALSE;
+static GHashTable *sna_fragment_table = NULL;
+static GHashTable *sna_reassembled_table = NULL;
+
+/* Format Identifier */
+static const value_string sna_th_fid_vals[] = {
+ { 0x0, "SNA device <--> Non-SNA Device" },
+ { 0x1, "Subarea Nodes, without ER or VR" },
+ { 0x2, "Subarea Node <--> PU2" },
+ { 0x3, "Subarea Node or SNA host <--> Subarea Node" },
+ { 0x4, "Subarea Nodes, supporting ER and VR" },
+ { 0x5, "HPR RTP endpoint nodes" },
+ { 0xa, "HPR NLP Frame Routing" },
+ { 0xb, "HPR NLP Frame Routing" },
+ { 0xc, "HPR NLP Automatic Network Routing" },
+ { 0xd, "HPR NLP Automatic Network Routing" },
+ { 0xf, "Adjaced Subarea Nodes, supporting ER and VR" },
+ { 0x0, NULL }
+};
+
+/* Mapping Field */
+#define MPF_MIDDLE_SEGMENT 0
+#define MPF_LAST_SEGMENT 1
+#define MPF_FIRST_SEGMENT 2
+#define MPF_WHOLE_BIU 3
+
+static const value_string sna_th_mpf_vals[] = {
+ { MPF_MIDDLE_SEGMENT, "Middle segment of a BIU" },
+ { MPF_LAST_SEGMENT, "Last segment of a BIU" },
+ { MPF_FIRST_SEGMENT, "First segment of a BIU" },
+ { MPF_WHOLE_BIU, "Whole BIU" },
+ { 0, NULL }
+};
+
+/* Expedited Flow Indicator */
+static const value_string sna_th_efi_vals[] = {
+ { 0, "Normal Flow" },
+ { 1, "Expedited Flow" },
+ { 0x0, NULL }
+};
+
+/* Request/Response Indicator */
+static const value_string sna_rh_rri_vals[] = {
+ { 0, "Request" },
+ { 1, "Response" },
+ { 0x0, NULL }
+};
+
+/* Request/Response Unit Category */
+static const value_string sna_rh_ru_category_vals[] = {
+ { 0, "Function Management Data (FMD)" },
+ { 1, "Network Control (NC)" },
+ { 2, "Data Flow Control (DFC)" },
+ { 3, "Session Control (SC)" },
+ { 0x0, NULL }
+};
+
+/* Format Indicator */
+static const true_false_string sna_rh_fi_truth =
+ { "FM Header", "No FM Header" };
+
+/* Sense Data Included */
+static const true_false_string sna_rh_sdi_truth =
+ { "Included", "Not Included" };
+
+/* Begin Chain Indicator */
+static const true_false_string sna_rh_bci_truth =
+ { "First in Chain", "Not First in Chain" };
+
+/* End Chain Indicator */
+static const true_false_string sna_rh_eci_truth =
+ { "Last in Chain", "Not Last in Chain" };
+
+/* Lengith-Checked Compression Indicator */
+static const true_false_string sna_rh_lcci_truth =
+ { "Compressed", "Not Compressed" };
+
+/* Response Type Indicator */
+static const true_false_string sna_rh_rti_truth =
+ { "Negative", "Positive" };
+
+/* Queued Response Indicator */
+static const true_false_string sna_rh_qri_truth =
+ { "Enqueue response in TC queues", "Response bypasses TC queues" };
+
+/* Code Selection Indicator */
+static const value_string sna_rh_csi_vals[] = {
+ { 0, "EBCDIC" },
+ { 1, "ASCII" },
+ { 0x0, NULL }
+};
+
+/* TG Sweep */
+static const value_string sna_th_tg_sweep_vals[] = {
+ { 0, "This PIU may overtake any PU ahead of it." },
+ { 1, "This PIU does not ovetake any PIU ahead of it." },
+ { 0x0, NULL }
+};
+
+/* ER_VR_SUPP_IND */
+static const value_string sna_th_er_vr_supp_ind_vals[] = {
+ { 0, "Each node supports ER and VR protocols" },
+ { 1, "Includes at least one node that does not support ER and VR"
+ " protocols" },
+ { 0x0, NULL }
+};
+
+/* VR_PAC_CNT_IND */
+static const value_string sna_th_vr_pac_cnt_ind_vals[] = {
+ { 0, "Pacing count on the VR has not reached 0" },
+ { 1, "Pacing count on the VR has reached 0" },
+ { 0x0, NULL }
+};
+
+/* NTWK_PRTY */
+static const value_string sna_th_ntwk_prty_vals[] = {
+ { 0, "PIU flows at a lower priority" },
+ { 1, "PIU flows at network priority (highest transmission priority)" },
+ { 0x0, NULL }
+};
+
+/* TGSF */
+static const value_string sna_th_tgsf_vals[] = {
+ { 0, "Not segmented" },
+ { 1, "Last segment" },
+ { 2, "First segment" },
+ { 3, "Middle segment" },
+ { 0x0, NULL }
+};
+
+/* PIUBF */
+static const value_string sna_th_piubf_vals[] = {
+ { 0, "Single PIU frame" },
+ { 1, "Last PIU of a multiple PIU frame" },
+ { 2, "First PIU of a multiple PIU frame" },
+ { 3, "Middle PIU of a multiple PIU frame" },
+ { 0x0, NULL }
+};
+
+/* NLPOI */
+static const value_string sna_th_nlpoi_vals[] = {
+ { 0, "NLP starts within this FID4 TH" },
+ { 1, "NLP byte 0 starts after RH byte 0 following NLP C/P pad" },
+ { 0x0, NULL }
+};
+
+/* TPF */
+static const value_string sna_th_tpf_vals[] = {
+ { 0, "Low Priority" },
+ { 1, "Medium Priority" },
+ { 2, "High Priority" },
+ { 3, "Network Priority" },
+ { 0x0, NULL }
+};
+
+/* VR_CWI */
+static const value_string sna_th_vr_cwi_vals[] = {
+ { 0, "Increment window size" },
+ { 1, "Decrement window size" },
+ { 0x0, NULL }
+};
+
+/* TG_NONFIFO_IND */
+static const true_false_string sna_th_tg_nonfifo_ind_truth =
+ { "TG FIFO is not required", "TG FIFO is required" };
+
+/* VR_SQTI */
+static const value_string sna_th_vr_sqti_vals[] = {
+ { 0, "Non-sequenced, Non-supervisory" },
+ { 1, "Non-sequenced, Supervisory" },
+ { 2, "Singly-sequenced" },
+ { 0x0, NULL }
+};
+
+/* VRPRQ */
+static const true_false_string sna_th_vrprq_truth = {
+ "VR pacing request is sent asking for a VR pacing response",
+ "No VR pacing response is requested",
+};
+
+/* VRPRS */
+static const true_false_string sna_th_vrprs_truth = {
+ "VR pacing response is sent in response to a VRPRQ bit set",
+ "No pacing response sent",
+};
+
+/* VR_CWRI */
+static const value_string sna_th_vr_cwri_vals[] = {
+ { 0, "Increment window size by 1" },
+ { 1, "Decrement window size by 1" },
+ { 0x0, NULL }
+};
+
+/* VR_RWI */
+static const true_false_string sna_th_vr_rwi_truth = {
+ "Reset window size to the minimum specified in NC_ACTVR",
+ "Do not reset window size",
+};
+
+/* Switching Mode */
+static const value_string sna_nlp_sm_vals[] = {
+ { 5, "Function routing" },
+ { 6, "Automatic network routing" },
+ { 0x0, NULL }
+};
+
+static const true_false_string sna_nlp_tspi_truth =
+ { "Time sensitive", "Not time sensitive" };
+
+static const true_false_string sna_nlp_slowdn1_truth =
+ { "Minor congestion", "No minor congestion" };
+
+static const true_false_string sna_nlp_slowdn2_truth =
+ { "Major congestion", "No major congestion" };
+
+/* Function Type */
+static const value_string sna_nlp_ft_vals[] = {
+ { 0x10, "LDLC" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_nlp_frh_vals[] = {
+ { 0x03, "XID complete request" },
+ { 0x04, "XID complete response" },
+ { 0x0, NULL }
+};
+
+static const true_false_string sna_nlp_setupi_truth =
+ { "Connection setup segment present", "Connection setup segment not"
+ " present" };
+
+static const true_false_string sna_nlp_somi_truth =
+ { "Start of message", "Not start of message" };
+
+static const true_false_string sna_nlp_eomi_truth =
+ { "End of message", "Not end of message" };
+
+static const true_false_string sna_nlp_sri_truth =
+ { "Status requested", "No status requested" };
+
+static const true_false_string sna_nlp_rasapi_truth =
+ { "Reply as soon as possible", "No need to reply as soon as possible" };
+
+static const true_false_string sna_nlp_retryi_truth =
+ { "Undefined", "Sender will retransmit" };
+
+static const true_false_string sna_nlp_lmi_truth =
+ { "Last message", "Not last message" };
+
+static const true_false_string sna_nlp_cqfi_truth =
+ { "CQFI included", "CQFI not included" };
+
+static const true_false_string sna_nlp_osi_truth =
+ { "Optional segments present", "No optional segments present" };
+
+static const value_string sna_xid_3_state_vals[] = {
+ { 0x00, "Exchange state indicators not supported" },
+ { 0x01, "Negotiation-proceeding exchange" },
+ { 0x02, "Prenegotiation exchange" },
+ { 0x03, "Nonactivation exchange" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_xid_3_branch_vals[] = {
+ { 0x00, "Sender does not support branch extender" },
+ { 0x01, "TG is branch uplink" },
+ { 0x02, "TG is branch downlink" },
+ { 0x03, "TG is neither uplink nor downlink" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_xid_type_vals[] = {
+ { 0x01, "T1 node" },
+ { 0x02, "T2.0 or T2.1 node" },
+ { 0x03, "Reserved" },
+ { 0x04, "T4 or T5 node" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_nlp_opti_vals[] = {
+ { 0x0d, "Connection Setup Segment" },
+ { 0x0e, "Status Segment" },
+ { 0x0f, "Client Out Of Band Bits Segment" },
+ { 0x10, "Connection Identifier Exchange Segment" },
+ { 0x12, "Connection Fault Segment" },
+ { 0x14, "Switching Information Segment" },
+ { 0x22, "Adaptive Rate-Based Segment" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_nlp_opti_0d_version_vals[] = {
+ { 0x0101, "Version 1.1" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_nlp_opti_0f_bits_vals[] = {
+ { 0x0001, "Request Deactivation" },
+ { 0x8000, "Reply - OK" },
+ { 0x8004, "Reply - Reject" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_nlp_opti_22_type_vals[] = {
+ { 0x00, "Setup" },
+ { 0x01, "Rate Reply" },
+ { 0x02, "Rate Request" },
+ { 0x03, "Rate Request/Rate Reply" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_nlp_opti_22_raa_vals[] = {
+ { 0x00, "Normal" },
+ { 0x01, "Restraint" },
+ { 0x02, "Slowdown1" },
+ { 0x03, "Slowdown2" },
+ { 0x04, "Critical" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_nlp_opti_22_arb_vals[] = {
+ { 0x00, "Base Mode ARB" },
+ { 0x01, "Responsive Mode ARB" },
+ { 0x0, NULL }
+};
+
+/* GDS Variable Type */
+static const value_string sna_gds_var_vals[] = {
+ { 0x1210, "Change Number Of Sessions" },
+ { 0x1211, "Exchange Log Name" },
+ { 0x1212, "Control Point Management Services Unit" },
+ { 0x1213, "Compare States" },
+ { 0x1214, "LU Names Position" },
+ { 0x1215, "LU Name" },
+ { 0x1217, "Do Know" },
+ { 0x1218, "Partner Restart" },
+ { 0x1219, "Don't Know" },
+ { 0x1220, "Sign-Off" },
+ { 0x1221, "Sign-On" },
+ { 0x1222, "SNMP-over-SNA" },
+ { 0x1223, "Node Address Service" },
+ { 0x12C1, "CP Capabilities" },
+ { 0x12C2, "Topology Database Update" },
+ { 0x12C3, "Register Resource" },
+ { 0x12C4, "Locate" },
+ { 0x12C5, "Cross-Domain Initiate" },
+ { 0x12C9, "Delete Resource" },
+ { 0x12CA, "Find Resource" },
+ { 0x12CB, "Found Resource" },
+ { 0x12CC, "Notify" },
+ { 0x12CD, "Initiate-Other Cross-Domain" },
+ { 0x12CE, "Route Setup" },
+ { 0x12E1, "Error Log" },
+ { 0x12F1, "Null Data" },
+ { 0x12F2, "User Control Date" },
+ { 0x12F3, "Map Name" },
+ { 0x12F4, "Error Data" },
+ { 0x12F6, "Authentication Token Data" },
+ { 0x12F8, "Service Flow Authentication Token Data" },
+ { 0x12FF, "Application Data" },
+ { 0x1310, "MDS Message Unit" },
+ { 0x1311, "MDS Routing Information" },
+ { 0x1500, "FID2 Encapsulation" },
+ { 0x0, NULL }
+};
+
+/* Control Vector Type */
+static const value_string sna_control_vals[] = {
+ { 0x00, "SSCP-LU Session Capabilities Control Vector" },
+ { 0x01, "Date-Time Control Vector" },
+ { 0x02, "Subarea Routing Control Vector" },
+ { 0x03, "SDLC Secondary Station Control Vector" },
+ { 0x04, "LU Control Vector" },
+ { 0x05, "Channel Control Vector" },
+ { 0x06, "Cross-Domain Resource Manager (CDRM) Control Vector" },
+ { 0x07, "PU FMD-RU-Usage Control Vector" },
+ { 0x08, "Intensive Mode Control Vector" },
+ { 0x09, "Activation Request / Response Sequence Identifier Control"
+ " Vector" },
+ { 0x0a, "User Request Correlator Control Vector" },
+ { 0x0b, "SSCP-PU Session Capabilities Control Vector" },
+ { 0x0c, "LU-LU Session Capabilities Control Vector" },
+ { 0x0d, "Mode / Class-of-Service / Virtual-Route-Identifier List"
+ " Control Vector" },
+ { 0x0e, "Network Name Control Vector" },
+ { 0x0f, "Link Capabilities and Status Control Vector" },
+ { 0x10, "Product Set ID Control Vector" },
+ { 0x11, "Load Module Correlation Control Vector" },
+ { 0x12, "Network Identifier Control Vector" },
+ { 0x13, "Gateway Support Capabilities Control Vector" },
+ { 0x14, "Session Initiation Control Vector" },
+ { 0x15, "Network-Qualified Address Pair Control Vector" },
+ { 0x16, "Names Substitution Control Vector" },
+ { 0x17, "SSCP Identifier Control Vector" },
+ { 0x18, "SSCP Name Control Vector" },
+ { 0x19, "Resource Identifier Control Vector" },
+ { 0x1a, "NAU Address Control Vector" },
+ { 0x1b, "VRID List Control Vector" },
+ { 0x1c, "Network-Qualified Name Pair Control Vector" },
+ { 0x1e, "VR-ER Mapping Data Control Vector" },
+ { 0x1f, "ER Configuration Control Vector" },
+ { 0x23, "Local-Form Session Identifier Control Vector" },
+ { 0x24, "IPL Load Module Request Control Vector" },
+ { 0x25, "Security ID Control Control Vector" },
+ { 0x26, "Network Connection Endpoint Identifier Control Vector" },
+ { 0x27, "XRF Session Activation Control Vector" },
+ { 0x28, "Related Session Identifier Control Vector" },
+ { 0x29, "Session State Data Control Vector" },
+ { 0x2a, "Session Information Control Vector" },
+ { 0x2b, "Route Selection Control Vector" },
+ { 0x2c, "COS/TPF Control Vector" },
+ { 0x2d, "Mode Control Vector" },
+ { 0x2f, "LU Definition Control Vector" },
+ { 0x30, "Assign LU Characteristics Control Vector" },
+ { 0x31, "BIND Image Control Vector" },
+ { 0x32, "Short-Hold Mode Control Vector" },
+ { 0x33, "ENCP Search Control Control Vector" },
+ { 0x34, "LU Definition Override Control Vector" },
+ { 0x35, "Extended Sense Data Control Vector" },
+ { 0x36, "Directory Error Control Vector" },
+ { 0x37, "Directory Entry Correlator Control Vector" },
+ { 0x38, "Short-Hold Mode Emulation Control Vector" },
+ { 0x39, "Network Connection Endpoint (NCE) Instance Identifier"
+ " Control Vector" },
+ { 0x3a, "Route Status Data Control Vector" },
+ { 0x3b, "VR Congestion Data Control Vector" },
+ { 0x3c, "Associated Resource Entry Control Vector" },
+ { 0x3d, "Directory Entry Control Vector" },
+ { 0x3e, "Directory Entry Characteristic Control Vector" },
+ { 0x3f, "SSCP (SLU) Capabilities Control Vector" },
+ { 0x40, "Real Associated Resource Control Vector" },
+ { 0x41, "Station Parameters Control Vector" },
+ { 0x42, "Dynamic Path Update Data Control Vector" },
+ { 0x43, "Extended SDLC Station Control Vector" },
+ { 0x44, "Node Descriptor Control Vector" },
+ { 0x45, "Node Characteristics Control Vector" },
+ { 0x46, "TG Descriptor Control Vector" },
+ { 0x47, "TG Characteristics Control Vector" },
+ { 0x48, "Topology Resource Descriptor Control Vector" },
+ { 0x49, "Multinode Persistent Sessions (MNPS) LU Names Control"
+ " Vector" },
+ { 0x4a, "Real Owning Control Point Control Vector" },
+ { 0x4b, "RTP Transport Connection Identifier Control Vector" },
+ { 0x51, "DLUR/S Capabilities Control Vector" },
+ { 0x52, "Primary Send Pacing Window Size Control Vector" },
+ { 0x56, "Call Security Verification Control Vector" },
+ { 0x57, "DLC Connection Data Control Vector" },
+ { 0x59, "Installation-Defined CDINIT Data Control Vector" },
+ { 0x5a, "Session Services Extension Support Control Vector" },
+ { 0x5b, "Interchange Node Support Control Vector" },
+ { 0x5c, "APPN Message Transport Control Vector" },
+ { 0x5d, "Subarea Message Transport Control Vector" },
+ { 0x5e, "Related Request Control Vector" },
+ { 0x5f, "Extended Fully Qualified PCID Control Vector" },
+ { 0x60, "Fully Qualified PCID Control Vector" },
+ { 0x61, "HPR Capabilities Control Vector" },
+ { 0x62, "Session Address Control Vector" },
+ { 0x63, "Cryptographic Key Distribution Control Vector" },
+ { 0x64, "TCP/IP Information Control Vector" },
+ { 0x65, "Device Characteristics Control Vector" },
+ { 0x66, "Length-Checked Compression Control Vector" },
+ { 0x67, "Automatic Network Routing (ANR) Path Control Vector" },
+ { 0x68, "XRF/Session Cryptography Control Vector" },
+ { 0x69, "Switched Parameters Control Vector" },
+ { 0x6a, "ER Congestion Data Control Vector" },
+ { 0x71, "Triple DES Cryptography Key Continuation Control Vector" },
+ { 0xfe, "Control Vector Keys Not Recognized" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_control_hpr_vals[] = {
+ { 0x00, "Node Identifier Control Vector" },
+ { 0x03, "Network ID Control Vector" },
+ { 0x05, "Network Address Control Vector" },
+ { 0x0, NULL }
+};
+
+static const value_string sna_control_0e_type_vals[] = {
+ { 0xF1, "PU Name" },
+ { 0xF3, "LU Name" },
+ { 0xF4, "CP Name" },
+ { 0xF5, "SSCP Name" },
+ { 0xF6, "NNCP Name" },
+ { 0xF7, "Link Station Name" },
+ { 0xF8, "CP Name of CP(PLU)" },
+ { 0xF9, "CP Name of CP(SLU)" },
+ { 0xFA, "Generic Name" },
+ { 0x0, NULL }
+};
+
+/* Values to direct the top-most dissector what to dissect
+ * after the TH. */
+enum next_dissection_enum {
+ stop_here,
+ rh_only,
+ everything
+};
+
+enum parse {
+ LT,
+ KL
+};
+
+typedef enum next_dissection_enum next_dissection_t;
+
+static void dissect_xid (tvbuff_t*, packet_info*, proto_tree*, proto_tree*);
+static void dissect_fid (tvbuff_t*, packet_info*, proto_tree*, proto_tree*);
+static void dissect_nlp (tvbuff_t*, packet_info*, proto_tree*, proto_tree*);
+static void dissect_gds (tvbuff_t*, packet_info*, proto_tree*, proto_tree*);
+static void dissect_rh (tvbuff_t*, int, proto_tree*);
+static void dissect_control(tvbuff_t*, int, int, proto_tree*, int, enum parse);
+
+/* --------------------------------------------------------------------
+ * Chapter 2 High-Performance Routing (HPR) Headers
+ * --------------------------------------------------------------------
+ */
+
+static void
+dissect_optional_0d(tvbuff_t *tvb, proto_tree *tree)
+{
+ int bits, offset, len, pad;
+ proto_tree *sub_tree;
+ proto_item *sub_ti = NULL;
+
+ if (!tree)
+ return;
+
+ proto_tree_add_item(tree, hf_sna_nlp_opti_0d_version, tvb, 2, 2, FALSE);
+ bits = tvb_get_guint8(tvb, 4);
+
+ sub_ti = proto_tree_add_uint(tree, hf_sna_nlp_opti_0d_4,
+ tvb, 4, 1, bits);
+ sub_tree = proto_item_add_subtree(sub_ti,
+ ett_sna_nlp_opti_0d_4);
+
+ proto_tree_add_boolean(sub_tree, hf_sna_nlp_opti_0d_target,
+ tvb, 4, 1, bits);
+ proto_tree_add_boolean(sub_tree, hf_sna_nlp_opti_0d_arb,
+ tvb, 4, 1, bits);
+ proto_tree_add_boolean(sub_tree, hf_sna_nlp_opti_0d_reliable,
+ tvb, 4, 1, bits);
+ proto_tree_add_boolean(sub_tree, hf_sna_nlp_opti_0d_dedicated,
+ tvb, 4, 1, bits);
+
+ proto_tree_add_text(tree, tvb, 5, 3, "Reserved");
+
+ offset = 8;
+
+ while (tvb_offset_exists(tvb, offset)) {
+ len = tvb_get_guint8(tvb, offset+0);
+ if (len) {
+ dissect_control(tvb, offset, len, tree, 1, LT);
+ pad = (len+3) & 0xfffc;
+ if (pad > len)
+ proto_tree_add_text(tree, tvb, offset+len,
+ pad-len, "Padding");
+ offset += pad;
+ } else {
+ /* Avoid endless loop */
+ return;
+ }
+ }
+}
+
+static void
+dissect_optional_0e(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int bits, offset;
+ proto_tree *sub_tree;
+ proto_item *sub_ti = NULL;
+
+ bits = tvb_get_guint8(tvb, 2);
+ offset = 20;
+
+ if (tree) {
+ sub_ti = proto_tree_add_item(tree, hf_sna_nlp_opti_0e_stat,
+ tvb, 2, 1, FALSE);
+ sub_tree = proto_item_add_subtree(sub_ti,
+ ett_sna_nlp_opti_0e_stat);
+
+ proto_tree_add_boolean(sub_tree, hf_sna_nlp_opti_0e_gap,
+ tvb, 2, 1, bits);
+ proto_tree_add_boolean(sub_tree, hf_sna_nlp_opti_0e_idle,
+ tvb, 2, 1, bits);
+ proto_tree_add_item(tree, hf_sna_nlp_opti_0e_nabsp,
+ tvb, 3, 1, FALSE);
+ proto_tree_add_item(tree, hf_sna_nlp_opti_0e_sync,
+ tvb, 4, 2, FALSE);
+ proto_tree_add_item(tree, hf_sna_nlp_opti_0e_echo,
+ tvb, 6, 2, FALSE);
+ proto_tree_add_item(tree, hf_sna_nlp_opti_0e_rseq,
+ tvb, 8, 4, FALSE);
+ proto_tree_add_text(tree, tvb, 12, 8, "Reserved");
+
+ if (tvb_offset_exists(tvb, offset))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 4, -1, -1), pinfo, tree);
+ }
+ if (bits & 0x40) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ "HPR Idle Message");
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ "HPR Status Message");
+ }
+}
+
+static void
+dissect_optional_0f(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (!tree)
+ return;
+
+ proto_tree_add_item(tree, hf_sna_nlp_opti_0f_bits, tvb, 2, 2, FALSE);
+ if (tvb_offset_exists(tvb, 4))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 4, -1, -1), pinfo, tree);
+}
+
+static void
+dissect_optional_10(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (!tree)
+ return;
+
+ proto_tree_add_text(tree, tvb, 2, 2, "Reserved");
+ proto_tree_add_item(tree, hf_sna_nlp_opti_10_tcid, tvb, 4, 8, FALSE);
+ if (tvb_offset_exists(tvb, 12))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 12, -1, -1), pinfo, tree);
+}
+
+static void
+dissect_optional_12(tvbuff_t *tvb, proto_tree *tree)
+{
+ if (!tree)
+ return;
+
+ proto_tree_add_text(tree, tvb, 2, 2, "Reserved");
+ proto_tree_add_item(tree, hf_sna_nlp_opti_12_sense, tvb, 4, -1, FALSE);
+}
+
+static void
+dissect_optional_14(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *sub_tree, *bf_tree;
+ proto_item *sub_item, *bf_item;
+ int len, pad, type, bits, offset, num, sublen;
+
+ if (!tree)
+ return;
+
+ proto_tree_add_text(tree, tvb, 2, 2, "Reserved");
+
+ offset = 4;
+
+ len = tvb_get_guint8(tvb, offset);
+ type = tvb_get_guint8(tvb, offset+1);
+
+ if ((type != 0x83) || (len <= 16)) {
+ /* Invalid */
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ return;
+ }
+ sub_item = proto_tree_add_text(tree, tvb, offset, len,
+ "Switching Information Control Vector");
+ sub_tree = proto_item_add_subtree(sub_item, ett_sna_nlp_opti_14_si);
+
+ proto_tree_add_uint(sub_tree, hf_sna_nlp_opti_14_si_len,
+ tvb, offset, 1, len);
+ proto_tree_add_uint(sub_tree, hf_sna_nlp_opti_14_si_key,
+ tvb, offset+1, 1, type);
+
+ bits = tvb_get_guint8(tvb, offset+2);
+ bf_item = proto_tree_add_uint(sub_tree, hf_sna_nlp_opti_14_si_2,
+ tvb, offset+2, 1, bits);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_nlp_opti_14_si_2);
+
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_opti_14_si_refifo,
+ tvb, offset+2, 1, bits);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_opti_14_si_mobility,
+ tvb, offset+2, 1, bits);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_opti_14_si_dirsearch,
+ tvb, offset+2, 1, bits);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_opti_14_si_limitres,
+ tvb, offset+2, 1, bits);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_opti_14_si_ncescope,
+ tvb, offset+2, 1, bits);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_opti_14_si_mnpsrscv,
+ tvb, offset+2, 1, bits);
+
+ proto_tree_add_text(sub_tree, tvb, offset+3, 1, "Reserved");
+ proto_tree_add_item(sub_tree, hf_sna_nlp_opti_14_si_maxpsize,
+ tvb, offset+4, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_sna_nlp_opti_14_si_switch,
+ tvb, offset+8, 4, FALSE);
+ proto_tree_add_item(sub_tree, hf_sna_nlp_opti_14_si_alive,
+ tvb, offset+12, 4, FALSE);
+
+ dissect_control(tvb, offset+16, len-16, sub_tree, 1, LT);
+
+ pad = (len+3) & 0xfffc;
+ if (pad > len)
+ proto_tree_add_text(sub_tree, tvb, offset+len, pad-len,
+ "Padding");
+ offset += pad;
+
+ len = tvb_get_guint8(tvb, offset);
+ type = tvb_get_guint8(tvb, offset+1);
+
+ if ((type != 0x85) || ( len < 4)) {
+ /* Invalid */
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ return;
+ }
+ sub_item = proto_tree_add_text(tree, tvb, offset, len,
+ "Return Route TG Descriptor Control Vector");
+ sub_tree = proto_item_add_subtree(sub_item, ett_sna_nlp_opti_14_rr);
+
+ proto_tree_add_uint(sub_tree, hf_sna_nlp_opti_14_rr_len,
+ tvb, offset, 1, len);
+ proto_tree_add_uint(sub_tree, hf_sna_nlp_opti_14_rr_key,
+ tvb, offset+1, 1, type);
+
+ bits = tvb_get_guint8(tvb, offset+2);
+ bf_item = proto_tree_add_uint(sub_tree, hf_sna_nlp_opti_14_rr_2,
+ tvb, offset+2, 1, bits);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_nlp_opti_14_rr_2);
+
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_opti_14_rr_bfe,
+ tvb, offset+2, 1, bits);
+
+ num = tvb_get_guint8(tvb, offset+3);
+
+ proto_tree_add_uint(sub_tree, hf_sna_nlp_opti_14_rr_num,
+ tvb, offset+3, 1, num);
+
+ offset += 4;
+
+ while (num) {
+ sublen = tvb_get_guint8(tvb, offset);
+ if (sublen) {
+ dissect_control(tvb, offset, sublen, sub_tree, 1, LT);
+ } else {
+ /* Invalid */
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ return;
+ }
+ /* No padding here */
+ offset += sublen;
+ num--;
+ }
+}
+
+static void
+dissect_optional_22(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *bf_tree;
+ proto_item *bf_item;
+ int bits, type;
+
+ if (!tree)
+ return;
+
+ bits = tvb_get_guint8(tvb, 2);
+ type = (bits & 0xc0) >> 6;
+
+ bf_item = proto_tree_add_uint(tree, hf_sna_nlp_opti_22_2,
+ tvb, 2, 1, bits);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_nlp_opti_22_2);
+
+ proto_tree_add_uint(bf_tree, hf_sna_nlp_opti_22_type,
+ tvb, 2, 1, bits);
+ proto_tree_add_uint(bf_tree, hf_sna_nlp_opti_22_raa,
+ tvb, 2, 1, bits);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_opti_22_parity,
+ tvb, 2, 1, bits);
+ proto_tree_add_uint(bf_tree, hf_sna_nlp_opti_22_arb,
+ tvb, 2, 1, bits);
+
+ bits = tvb_get_guint8(tvb, 3);
+
+ bf_item = proto_tree_add_uint(tree, hf_sna_nlp_opti_22_3,
+ tvb, 3, 1, bits);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_nlp_opti_22_3);
+
+ proto_tree_add_uint(bf_tree, hf_sna_nlp_opti_22_ratereq,
+ tvb, 3, 1, bits);
+ proto_tree_add_uint(bf_tree, hf_sna_nlp_opti_22_raterep,
+ tvb, 3, 1, bits);
+
+ proto_tree_add_item(tree, hf_sna_nlp_opti_22_field1,
+ tvb, 4, 4, FALSE);
+ proto_tree_add_item(tree, hf_sna_nlp_opti_22_field2,
+ tvb, 8, 4, FALSE);
+
+ if (type == 0) {
+ proto_tree_add_item(tree, hf_sna_nlp_opti_22_field3,
+ tvb, 12, 4, FALSE);
+ proto_tree_add_item(tree, hf_sna_nlp_opti_22_field4,
+ tvb, 16, 4, FALSE);
+
+ if (tvb_offset_exists(tvb, 20))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 20, -1, -1), pinfo, tree);
+ } else {
+ if (tvb_offset_exists(tvb, 12))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 12, -1, -1), pinfo, tree);
+ }
+}
+
+static void
+dissect_optional(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *sub_tree;
+ proto_item *sub_item;
+ int offset, type, len;
+ gint ett;
+
+ sub_tree = NULL;
+
+ offset = 0;
+
+ while (tvb_offset_exists(tvb, offset)) {
+ len = tvb_get_guint8(tvb, offset);
+ type = tvb_get_guint8(tvb, offset+1);
+
+ /* Prevent loop for invalid crap in packet */
+ if (len == 0) {
+ if (tree)
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset,
+ -1, -1), pinfo, tree);
+ return;
+ }
+
+ ett = ett_sna_nlp_opti_un;
+ if(type == 0x0d) ett = ett_sna_nlp_opti_0d;
+ if(type == 0x0e) ett = ett_sna_nlp_opti_0e;
+ if(type == 0x0f) ett = ett_sna_nlp_opti_0f;
+ if(type == 0x10) ett = ett_sna_nlp_opti_10;
+ if(type == 0x12) ett = ett_sna_nlp_opti_12;
+ if(type == 0x14) ett = ett_sna_nlp_opti_14;
+ if(type == 0x22) ett = ett_sna_nlp_opti_22;
+ if (tree) {
+ sub_item = proto_tree_add_text(tree, tvb,
+ offset, len << 2,
+ val_to_str(type, sna_nlp_opti_vals,
+ "Unknown Segment Type"));
+ sub_tree = proto_item_add_subtree(sub_item, ett);
+ proto_tree_add_uint(sub_tree, hf_sna_nlp_opti_len,
+ tvb, offset, 1, len);
+ proto_tree_add_uint(sub_tree, hf_sna_nlp_opti_type,
+ tvb, offset+1, 1, type);
+ }
+ switch(type) {
+ case 0x0d:
+ dissect_optional_0d(tvb_new_subset(tvb, offset,
+ len << 2, -1), sub_tree);
+ break;
+ case 0x0e:
+ dissect_optional_0e(tvb_new_subset(tvb, offset,
+ len << 2, -1), pinfo, sub_tree);
+ break;
+ case 0x0f:
+ dissect_optional_0f(tvb_new_subset(tvb, offset,
+ len << 2, -1), pinfo, sub_tree);
+ break;
+ case 0x10:
+ dissect_optional_10(tvb_new_subset(tvb, offset,
+ len << 2, -1), pinfo, sub_tree);
+ break;
+ case 0x12:
+ dissect_optional_12(tvb_new_subset(tvb, offset,
+ len << 2, -1), sub_tree);
+ break;
+ case 0x14:
+ dissect_optional_14(tvb_new_subset(tvb, offset,
+ len << 2, -1), pinfo, sub_tree);
+ break;
+ case 0x22:
+ dissect_optional_22(tvb_new_subset(tvb, offset,
+ len << 2, -1), pinfo, sub_tree);
+ break;
+ default:
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset,
+ len << 2, -1), pinfo, sub_tree);
+ }
+ offset += (len << 2);
+ }
+}
+
+static void
+dissect_nlp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *parent_tree)
+{
+ proto_tree *nlp_tree, *bf_tree;
+ proto_item *nlp_item, *bf_item, *h_item;
+ guint8 nhdr_0, nhdr_1, nhdr_x, thdr_8, thdr_9, fid;
+ guint32 thdr_len, thdr_dlf;
+ guint16 subindex;
+
+ int index = 0, counter = 0;
+
+ nlp_tree = NULL;
+ nlp_item = NULL;
+
+ nhdr_0 = tvb_get_guint8(tvb, index);
+ nhdr_1 = tvb_get_guint8(tvb, index+1);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "HPR NLP Packet");
+
+ if (tree) {
+ /* Don't bother setting length. We'll set it later after we
+ * find the lengths of NHDR */
+ nlp_item = proto_tree_add_item(tree, hf_sna_nlp_nhdr, tvb,
+ index, -1, FALSE);
+ nlp_tree = proto_item_add_subtree(nlp_item, ett_sna_nlp_nhdr);
+
+ bf_item = proto_tree_add_uint(nlp_tree, hf_sna_nlp_nhdr_0, tvb,
+ index, 1, nhdr_0);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_nlp_nhdr_0);
+
+ proto_tree_add_uint(bf_tree, hf_sna_nlp_sm, tvb, index, 1,
+ nhdr_0);
+ proto_tree_add_uint(bf_tree, hf_sna_nlp_tpf, tvb, index, 1,
+ nhdr_0);
+
+ bf_item = proto_tree_add_uint(nlp_tree, hf_sna_nlp_nhdr_1, tvb,
+ index+1, 1, nhdr_1);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_nlp_nhdr_1);
+
+ proto_tree_add_uint(bf_tree, hf_sna_nlp_ft, tvb,
+ index+1, 1, nhdr_1);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_tspi, tvb,
+ index+1, 1, nhdr_1);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_slowdn1, tvb,
+ index+1, 1, nhdr_1);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_slowdn2, tvb,
+ index+1, 1, nhdr_1);
+ }
+ /* ANR or FR lists */
+
+ index += 2;
+ counter = 0;
+
+ if ((nhdr_0 & 0xe0) == 0xa0) {
+ do {
+ nhdr_x = tvb_get_guint8(tvb, index + counter);
+ counter ++;
+ } while (nhdr_x != 0xff);
+ if (tree)
+ h_item = proto_tree_add_item(nlp_tree,
+ hf_sna_nlp_fra, tvb, index, counter, FALSE);
+ index += counter;
+ if (tree)
+ proto_tree_add_text(nlp_tree, tvb, index, 1,
+ "Reserved");
+ index++;
+
+ if (tree)
+ proto_item_set_len(nlp_item, index);
+
+ if ((nhdr_1 & 0xf0) == 0x10) {
+ nhdr_x = tvb_get_guint8(tvb, index);
+ if (tree)
+ proto_tree_add_uint(tree, hf_sna_nlp_frh,
+ tvb, index, 1, nhdr_x);
+ index ++;
+
+ if (tvb_offset_exists(tvb, index))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, index, -1, -1),
+ pinfo, parent_tree);
+ return;
+ }
+ }
+ if ((nhdr_0 & 0xe0) == 0xc0) {
+ do {
+ nhdr_x = tvb_get_guint8(tvb, index + counter);
+ counter ++;
+ } while (nhdr_x != 0xff);
+ if (tree)
+ h_item = proto_tree_add_item(nlp_tree, hf_sna_nlp_anr,
+ tvb, index, counter, FALSE);
+ index += counter;
+
+ if (tree)
+ proto_tree_add_text(nlp_tree, tvb, index, 1,
+ "Reserved");
+ index++;
+
+ if (tree)
+ proto_item_set_len(nlp_item, index);
+ }
+
+ thdr_8 = tvb_get_guint8(tvb, index+8);
+ thdr_9 = tvb_get_guint8(tvb, index+9);
+ thdr_len = tvb_get_ntohs(tvb, index+10);
+ thdr_dlf = tvb_get_ntohl(tvb, index+12);
+
+ if (tree) {
+ nlp_item = proto_tree_add_item(tree, hf_sna_nlp_thdr, tvb,
+ index, thdr_len << 2, FALSE);
+ nlp_tree = proto_item_add_subtree(nlp_item, ett_sna_nlp_thdr);
+
+ proto_tree_add_item(nlp_tree, hf_sna_nlp_tcid, tvb,
+ index, 8, FALSE);
+ bf_item = proto_tree_add_uint(nlp_tree, hf_sna_nlp_thdr_8, tvb,
+ index+8, 1, thdr_8);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_nlp_thdr_8);
+
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_setupi, tvb,
+ index+8, 1, thdr_8);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_somi, tvb, index+8,
+ 1, thdr_8);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_eomi, tvb, index+8,
+ 1, thdr_8);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_sri, tvb, index+8,
+ 1, thdr_8);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_rasapi, tvb,
+ index+8, 1, thdr_8);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_retryi, tvb,
+ index+8, 1, thdr_8);
+
+ bf_item = proto_tree_add_uint(nlp_tree, hf_sna_nlp_thdr_9, tvb,
+ index+9, 1, thdr_9);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_nlp_thdr_9);
+
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_lmi, tvb, index+9,
+ 1, thdr_9);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_cqfi, tvb, index+9,
+ 1, thdr_9);
+ proto_tree_add_boolean(bf_tree, hf_sna_nlp_osi, tvb, index+9,
+ 1, thdr_9);
+
+ proto_tree_add_uint(nlp_tree, hf_sna_nlp_offset, tvb, index+10,
+ 2, thdr_len);
+ proto_tree_add_uint(nlp_tree, hf_sna_nlp_dlf, tvb, index+12,
+ 4, thdr_dlf);
+ proto_tree_add_item(nlp_tree, hf_sna_nlp_bsn, tvb, index+16,
+ 4, FALSE);
+ }
+ subindex = 20;
+
+ if (((thdr_9 & 0x18) == 0x08) && ((thdr_len << 2) > subindex)) {
+ counter = tvb_get_guint8(tvb, index + subindex);
+ if (tvb_get_guint8(tvb, index+subindex+1) == 5)
+ dissect_control(tvb, index + subindex, counter+2, nlp_tree, 1, LT);
+ else
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, index + subindex, counter+2,
+ -1), pinfo, nlp_tree);
+
+ subindex += (counter+2);
+ }
+ if ((thdr_9 & 0x04) && ((thdr_len << 2) > subindex))
+ dissect_optional(
+ tvb_new_subset(tvb, index + subindex,
+ (thdr_len << 2) - subindex, -1),
+ pinfo, nlp_tree);
+
+ index += (thdr_len << 2);
+ if (((thdr_8 & 0x20) == 0) && thdr_dlf) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "HPR Fragment");
+ if (tvb_offset_exists(tvb, index)) {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, index, -1, -1), pinfo,
+ parent_tree);
+ }
+ return;
+ }
+ if (tvb_offset_exists(tvb, index)) {
+ /* Transmission Header Format Identifier */
+ fid = hi_nibble(tvb_get_guint8(tvb, index));
+ if (fid == 5) /* Only FID5 allowed for HPR */
+ dissect_fid(tvb_new_subset(tvb, index, -1, -1), pinfo,
+ tree, parent_tree);
+ else {
+ if (tvb_get_ntohs(tvb, index+2) == 0x12ce) {
+ /* Route Setup */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ "HPR Route Setup");
+ dissect_gds(tvb_new_subset(tvb, index, -1, -1),
+ pinfo, tree, parent_tree);
+ } else
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, index, -1, -1),
+ pinfo, parent_tree);
+ }
+ }
+}
+
+/* --------------------------------------------------------------------
+ * Chapter 3 Exchange Identification (XID) Information Fields
+ * --------------------------------------------------------------------
+ */
+
+static void
+dissect_xid1(tvbuff_t *tvb, proto_tree *tree)
+{
+ if (!tree)
+ return;
+
+ proto_tree_add_text(tree, tvb, 0, 2, "Reserved");
+
+}
+
+static void
+dissect_xid2(tvbuff_t *tvb, proto_tree *tree)
+{
+ guint dlen, offset;
+
+ if (!tree)
+ return;
+
+ dlen = tvb_get_guint8(tvb, 0);
+
+ offset = dlen;
+
+ while (tvb_offset_exists(tvb, offset)) {
+ dlen = tvb_get_guint8(tvb, offset+1);
+ dissect_control(tvb, offset, dlen+2, tree, 0, KL);
+ offset += (dlen + 2);
+ }
+}
+
+static void
+dissect_xid3(tvbuff_t *tvb, proto_tree *tree)
+{
+ proto_tree *sub_tree;
+ proto_item *sub_ti = NULL;
+ guint val, dlen, offset;
+
+ if (!tree)
+ return;
+
+ proto_tree_add_text(tree, tvb, 0, 2, "Reserved");
+
+ val = tvb_get_ntohs(tvb, 2);
+
+ sub_ti = proto_tree_add_uint(tree, hf_sna_xid_3_8, tvb,
+ 2, 2, val);
+ sub_tree = proto_item_add_subtree(sub_ti, ett_sna_xid_3_8);
+
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_init_self, tvb, 2, 2,
+ val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_stand_bind, tvb, 2, 2,
+ val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_gener_bind, tvb, 2, 2,
+ val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_recve_bind, tvb, 2, 2,
+ val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_actpu, tvb, 2, 2, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_nwnode, tvb, 2, 2, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_cp, tvb, 2, 2, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_cpcp, tvb, 2, 2, val);
+ proto_tree_add_uint(sub_tree, hf_sna_xid_3_state, tvb, 2, 2, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_nonact, tvb, 2, 2, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_cpchange, tvb, 2, 2,
+ val);
+
+ val = tvb_get_guint8(tvb, 4);
+
+ sub_ti = proto_tree_add_uint(tree, hf_sna_xid_3_10, tvb,
+ 4, 1, val);
+ sub_tree = proto_item_add_subtree(sub_ti, ett_sna_xid_3_10);
+
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_asend_bind, tvb, 4, 1,
+ val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_arecv_bind, tvb, 4, 1,
+ val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_quiesce, tvb, 4, 1, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_pucap, tvb, 4, 1, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_pbn, tvb, 4, 1, val);
+ proto_tree_add_uint(sub_tree, hf_sna_xid_3_pacing, tvb, 4, 1, val);
+
+ val = tvb_get_guint8(tvb, 5);
+
+ sub_ti = proto_tree_add_uint(tree, hf_sna_xid_3_11, tvb,
+ 5, 1, val);
+ sub_tree = proto_item_add_subtree(sub_ti, ett_sna_xid_3_11);
+
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_tgshare, tvb, 5, 1, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_dedsvc, tvb, 5, 1, val);
+
+ val = tvb_get_guint8(tvb, 6);
+
+ sub_ti = proto_tree_add_item(tree, hf_sna_xid_3_12, tvb,
+ 6, 1, FALSE);
+ sub_tree = proto_item_add_subtree(sub_ti, ett_sna_xid_3_12);
+
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_negcsup, tvb, 6, 1, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_negcomp, tvb, 6, 1, val);
+
+ proto_tree_add_text(tree, tvb, 7, 2, "Reserved");
+
+ val = tvb_get_guint8(tvb, 9);
+
+ sub_ti = proto_tree_add_item(tree, hf_sna_xid_3_15, tvb,
+ 9, 1, FALSE);
+ sub_tree = proto_item_add_subtree(sub_ti, ett_sna_xid_3_15);
+
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_partg, tvb, 9, 1, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_dlur, tvb, 9, 1, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_dlus, tvb, 9, 1, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_exbn, tvb, 9, 1, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_genodai, tvb, 9, 1, val);
+ proto_tree_add_uint(sub_tree, hf_sna_xid_3_branch, tvb, 9, 1, val);
+ proto_tree_add_boolean(sub_tree, hf_sna_xid_3_brnn, tvb, 9, 1, val);
+
+ proto_tree_add_item(tree, hf_sna_xid_3_tg, tvb, 10, 1, FALSE);
+ proto_tree_add_item(tree, hf_sna_xid_3_dlc, tvb, 11, 1, FALSE);
+
+ dlen = tvb_get_guint8(tvb, 12);
+
+ proto_tree_add_uint(tree, hf_sna_xid_3_dlen, tvb, 12, 1, dlen);
+
+ /* FIXME: DLC Dependent Data Go Here */
+
+ offset = 12 + dlen;
+
+ while (tvb_offset_exists(tvb, offset)) {
+ dlen = tvb_get_guint8(tvb, offset+1);
+ dissect_control(tvb, offset, dlen+2, tree, 0, KL);
+ offset += (dlen+2);
+ }
+}
+
+static void
+dissect_xid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *parent_tree)
+{
+ proto_tree *sub_tree;
+ proto_item *sub_ti = NULL;
+ int format, type, len;
+ guint32 id;
+
+ len = tvb_get_guint8(tvb, 1);
+ type = tvb_get_guint8(tvb, 0);
+ id = tvb_get_ntohl(tvb, 2);
+ format = hi_nibble(type);
+
+ /* Summary information */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "SNA XID Format:%d Type:%s", format,
+ val_to_str(lo_nibble(type), sna_xid_type_vals,
+ "Unknown Type"));
+
+ if (tree) {
+ sub_ti = proto_tree_add_item(tree, hf_sna_xid_0, tvb,
+ 0, 1, FALSE);
+ sub_tree = proto_item_add_subtree(sub_ti, ett_sna_xid_0);
+
+ proto_tree_add_uint(sub_tree, hf_sna_xid_format, tvb, 0, 1,
+ type);
+ proto_tree_add_uint(sub_tree, hf_sna_xid_type, tvb, 0, 1,
+ type);
+
+ proto_tree_add_uint(tree, hf_sna_xid_len, tvb, 1, 1, len);
+
+ sub_ti = proto_tree_add_item(tree, hf_sna_xid_id, tvb,
+ 2, 4, FALSE);
+ sub_tree = proto_item_add_subtree(sub_ti, ett_sna_xid_id);
+
+ proto_tree_add_uint(sub_tree, hf_sna_xid_idblock, tvb, 2, 4,
+ id);
+ proto_tree_add_uint(sub_tree, hf_sna_xid_idnum, tvb, 2, 4,
+ id);
+
+ switch(format) {
+ case 0:
+ break;
+ case 1:
+ dissect_xid1(tvb_new_subset(tvb, 6, len-6, -1),
+ tree);
+ break;
+ case 2:
+ dissect_xid2(tvb_new_subset(tvb, 6, len-6, -1),
+ tree);
+ break;
+ case 3:
+ dissect_xid3(tvb_new_subset(tvb, 6, len-6, -1),
+ tree);
+ break;
+ default:
+ /* external standards organizations */
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 6, len-6, -1),
+ pinfo, tree);
+ }
+ }
+
+ if (format == 0)
+ len = 6;
+
+ if (tvb_offset_exists(tvb, len))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, len, -1, -1), pinfo, parent_tree);
+}
+
+/* --------------------------------------------------------------------
+ * Chapter 4 Transmission Headers (THs)
+ * --------------------------------------------------------------------
+ */
+
+#define RH_LEN 3
+
+static unsigned int
+mpf_value(guint8 th_byte)
+{
+ return (th_byte & 0x0c) >> 2;
+}
+
+#define FIRST_FRAG_NUMBER 0
+#define MIDDLE_FRAG_NUMBER 1
+#define LAST_FRAG_NUMBER 2
+
+/* FID2 is defragged by sequence. The weird thing is that we have neither
+ * absolute sequence numbers, nor byte offets. Other FIDs have byte offsets
+ * (the DCF field), but not FID2. The only thing we have to go with is "FIRST",
+ * "MIDDLE", or "LAST". If the BIU is split into 3 frames, then everything is
+ * fine, * "FIRST", "MIDDLE", and "LAST" map nicely onto frag-number 0, 1,
+ * and 2. However, if the BIU is split into 2 frames, then we only have
+ * "FIRST" and "LAST", and the mapping *should* be frag-number 0 and 1,
+ * *NOT* 0 and 2.
+ *
+ * The SNA docs say "FID2 PIUs cannot be blocked because there is no DCF in the
+ * TH format for deblocking" (note on Figure 4-2 in the IBM SNA documention,
+ * see the FTP URL in the comment near the top of this file). I *think*
+ * this means that the fragmented frames cannot arrive out of order.
+ * Well, I *want* it to mean this, because w/o this limitation, if you
+ * get a "FIRST" frame and a "LAST" frame, how long should you wait to
+ * see if a "MIDDLE" frame every arrives????? Thus, if frames *have* to
+ * arrive in order, then we're saved.
+ *
+ * The problem then boils down to figuring out if "LAST" means frag-number 1
+ * (in the case of a BIU split into 2 frames) or frag-number 2
+ * (in the case of a BIU split into 3 frames).
+ *
+ * Assuming fragmented FID2 BIU frames *do* arrive in order, the obvious
+ * way to handle the mapping of "LAST" to either frag-number 1 or
+ * frag-number 2 is to keep a hash which tracks the frames seen, etc.
+ * This consumes resources. A trickier way, but a way which works, is to
+ * always map the "LAST" BIU segment to frag-number 2. Here's the trickery:
+ * if we add frag-number 2, which we know to be the "LAST" BIU segment,
+ * and the reassembly code tells us that the the BIU is still not reassmebled,
+ * then, owing to the, ahem, /fact/, that fragmented BIU segments arrive
+ * in order :), we know that 1) "FIRST" did come, and 2) there's no "MIDDLE",
+ * because this BIU was fragmented into 2 frames, not 3. So, we'll be
+ * tricky and add a zero-length "MIDDLE" BIU frame (i.e, frag-number 1)
+ * to complete the reassembly.
+ */
+static tvbuff_t*
+defragment_by_sequence(packet_info *pinfo, tvbuff_t *tvb, int offset, int mpf,
+ int id)
+{
+ fragment_data *fd_head;
+ int frag_number = -1;
+ int more_frags = TRUE;
+ tvbuff_t *rh_tvb = NULL;
+ gint frag_len;
+
+ /* Determine frag_number and more_frags */
+ switch(mpf) {
+ case MPF_WHOLE_BIU:
+ /* nothing */
+ break;
+ case MPF_FIRST_SEGMENT:
+ frag_number = FIRST_FRAG_NUMBER;
+ break;
+ case MPF_MIDDLE_SEGMENT:
+ frag_number = MIDDLE_FRAG_NUMBER;
+ break;
+ case MPF_LAST_SEGMENT:
+ frag_number = LAST_FRAG_NUMBER;
+ more_frags = FALSE;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ /* If sna_defragment is on, and this is a fragment.. */
+ if (frag_number > -1) {
+ /* XXX - check length ??? */
+ frag_len = tvb_reported_length_remaining(tvb, offset);
+ if (tvb_bytes_exist(tvb, offset, frag_len)) {
+ fd_head = fragment_add_seq(tvb, offset, pinfo, id,
+ sna_fragment_table, frag_number, frag_len,
+ more_frags);
+
+ /* We added the LAST segment and reassembly didn't
+ * complete. Insert a zero-length MIDDLE segment to
+ * turn a 2-frame BIU-fragmentation into a 3-frame
+ * BIU-fragmentation (empty middle frag).
+ * See above long comment about this trickery. */
+
+ if (mpf == MPF_LAST_SEGMENT && !fd_head) {
+ fd_head = fragment_add_seq(tvb, offset, pinfo,
+ id, sna_fragment_table,
+ MIDDLE_FRAG_NUMBER, 0, TRUE);
+ }
+
+ if (fd_head != NULL) {
+ /* We have the complete reassembled payload. */
+ rh_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->len, fd_head->len);
+
+ /* Add the tvbuff to the chain of tvbuffs
+ * so that it will get cleaned up too. */
+ tvb_set_child_real_data_tvbuff(tvb, rh_tvb);
+
+ /* Add the defragmented data to the data
+ * source list. */
+ add_new_data_source(pinfo, rh_tvb,
+ "Reassembled SNA BIU");
+ }
+ }
+ }
+ return rh_tvb;
+}
+
+#define SNA_FID01_ADDR_LEN 2
+
+/* FID Types 0 and 1 */
+static int
+dissect_fid0_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *bf_tree;
+ proto_item *bf_item;
+ guint8 th_0;
+ const guint8 *ptr;
+
+ const int bytes_in_header = 10;
+
+ if (tree) {
+ /* Byte 0 */
+ th_0 = tvb_get_guint8(tvb, 0);
+ bf_item = proto_tree_add_uint(tree, hf_sna_th_0, tvb, 0, 1,
+ th_0);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ proto_tree_add_uint(bf_tree, hf_sna_th_fid, tvb, 0, 1, th_0);
+ proto_tree_add_uint(bf_tree, hf_sna_th_mpf, tvb, 0, 1, th_0);
+ proto_tree_add_uint(bf_tree, hf_sna_th_efi, tvb, 0, 1, th_0);
+
+ /* Byte 1 */
+ proto_tree_add_text(tree, tvb, 1, 1, "Reserved");
+
+ /* Bytes 2-3 */
+ proto_tree_add_item(tree, hf_sna_th_daf, tvb, 2, 2, FALSE);
+ }
+
+ /* Set DST addr */
+ ptr = tvb_get_ptr(tvb, 2, SNA_FID01_ADDR_LEN);
+ SET_ADDRESS(&pinfo->net_dst, AT_SNA, SNA_FID01_ADDR_LEN, ptr);
+ SET_ADDRESS(&pinfo->dst, AT_SNA, SNA_FID01_ADDR_LEN, ptr);
+
+ if (tree)
+ proto_tree_add_item(tree, hf_sna_th_oaf, tvb, 4, 2, FALSE);
+
+ /* Set SRC addr */
+ ptr = tvb_get_ptr(tvb, 4, SNA_FID01_ADDR_LEN);
+ SET_ADDRESS(&pinfo->net_src, AT_SNA, SNA_FID01_ADDR_LEN, ptr);
+ SET_ADDRESS(&pinfo->src, AT_SNA, SNA_FID01_ADDR_LEN, ptr);
+
+ /* If we're not filling a proto_tree, return now */
+ if (tree)
+ return bytes_in_header;
+
+ proto_tree_add_item(tree, hf_sna_th_snf, tvb, 6, 2, FALSE);
+ proto_tree_add_item(tree, hf_sna_th_dcf, tvb, 8, 2, FALSE);
+
+ return bytes_in_header;
+}
+
+#define SNA_FID2_ADDR_LEN 1
+
+/* FID Type 2 */
+static int
+dissect_fid2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ tvbuff_t **rh_tvb_ptr, next_dissection_t *continue_dissecting)
+{
+ proto_tree *bf_tree;
+ proto_item *bf_item;
+ guint8 th_0=0, daf=0, oaf=0;
+ const guint8 *ptr;
+ unsigned int mpf, id;
+
+ const int bytes_in_header = 6;
+
+ th_0 = tvb_get_guint8(tvb, 0);
+ mpf = mpf_value(th_0);
+
+ if (tree) {
+ daf = tvb_get_guint8(tvb, 2);
+ oaf = tvb_get_guint8(tvb, 3);
+
+ /* Byte 0 */
+ bf_item = proto_tree_add_uint(tree, hf_sna_th_0, tvb, 0, 1,
+ th_0);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ proto_tree_add_uint(bf_tree, hf_sna_th_fid, tvb, 0, 1, th_0);
+ proto_tree_add_uint(bf_tree, hf_sna_th_mpf, tvb, 0, 1, th_0);
+ proto_tree_add_uint(bf_tree, hf_sna_th_odai,tvb, 0, 1, th_0);
+ proto_tree_add_uint(bf_tree, hf_sna_th_efi, tvb, 0, 1, th_0);
+
+
+ /* Byte 1 */
+ proto_tree_add_text(tree, tvb, 1, 1, "Reserved");
+
+ /* Byte 2 */
+ proto_tree_add_uint_format(tree, hf_sna_th_daf, tvb, 2, 1, daf,
+ "Destination Address Field: 0x%02x", daf);
+ }
+
+ /* Set DST addr */
+ ptr = tvb_get_ptr(tvb, 2, SNA_FID2_ADDR_LEN);
+ SET_ADDRESS(&pinfo->net_dst, AT_SNA, SNA_FID2_ADDR_LEN, ptr);
+ SET_ADDRESS(&pinfo->dst, AT_SNA, SNA_FID2_ADDR_LEN, ptr);
+
+ if (tree) {
+ /* Byte 3 */
+ proto_tree_add_uint_format(tree, hf_sna_th_oaf, tvb, 3, 1, oaf,
+ "Origin Address Field: 0x%02x", oaf);
+ }
+
+ /* Set SRC addr */
+ ptr = tvb_get_ptr(tvb, 3, SNA_FID2_ADDR_LEN);
+ SET_ADDRESS(&pinfo->net_src, AT_SNA, SNA_FID2_ADDR_LEN, ptr);
+ SET_ADDRESS(&pinfo->src, AT_SNA, SNA_FID2_ADDR_LEN, ptr);
+
+ id = tvb_get_ntohs(tvb, 4);
+ if (tree)
+ proto_tree_add_uint(tree, hf_sna_th_snf, tvb, 4, 2, id);
+
+ if (mpf != MPF_WHOLE_BIU && !sna_defragment) {
+ if (mpf == MPF_FIRST_SEGMENT) {
+ *continue_dissecting = rh_only;
+ } else {
+ *continue_dissecting = stop_here;
+ }
+
+ }
+ else if (sna_defragment) {
+ *rh_tvb_ptr = defragment_by_sequence(pinfo, tvb,
+ bytes_in_header, mpf, id);
+ }
+
+ return bytes_in_header;
+}
+
+/* FID Type 3 */
+static int
+dissect_fid3(tvbuff_t *tvb, proto_tree *tree)
+{
+ proto_tree *bf_tree;
+ proto_item *bf_item;
+ guint8 th_0;
+
+ const int bytes_in_header = 2;
+
+ /* If we're not filling a proto_tree, return now */
+ if (!tree)
+ return bytes_in_header;
+
+ th_0 = tvb_get_guint8(tvb, 0);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_uint(tree, hf_sna_th_0, tvb, 0, 1, th_0);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ proto_tree_add_uint(bf_tree, hf_sna_th_fid, tvb, 0, 1, th_0);
+ proto_tree_add_uint(bf_tree, hf_sna_th_mpf, tvb, 0, 1, th_0);
+ proto_tree_add_uint(bf_tree, hf_sna_th_efi, tvb, 0, 1, th_0);
+
+ proto_tree_add_item(tree, hf_sna_th_lsid, tvb, 1, 1, FALSE);
+
+ return bytes_in_header;
+}
+
+static int
+dissect_fid4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *bf_tree;
+ proto_item *bf_item;
+ int offset = 0;
+ guint8 th_byte, mft;
+ guint16 th_word;
+ guint16 def, oef;
+ guint32 dsaf, osaf;
+ static struct sna_fid_type_4_addr src, dst;
+
+ const int bytes_in_header = 26;
+
+ /* If we're not filling a proto_tree, return now */
+ if (!tree)
+ return bytes_in_header;
+
+ th_byte = tvb_get_guint8(tvb, offset);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_uint(tree, hf_sna_th_0, tvb, offset,
+ 1, th_byte);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ /* Byte 0 */
+ proto_tree_add_uint(bf_tree, hf_sna_th_fid, tvb,
+ offset, 1, th_byte);
+ proto_tree_add_uint(bf_tree, hf_sna_th_tg_sweep, tvb,
+ offset, 1, th_byte);
+ proto_tree_add_uint(bf_tree, hf_sna_th_er_vr_supp_ind, tvb,
+ offset, 1, th_byte);
+ proto_tree_add_uint(bf_tree, hf_sna_th_vr_pac_cnt_ind, tvb,
+ offset, 1, th_byte);
+ proto_tree_add_uint(bf_tree, hf_sna_th_ntwk_prty, tvb,
+ offset, 1, th_byte);
+
+ offset += 1;
+ th_byte = tvb_get_guint8(tvb, offset);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_text(tree, tvb, offset, 1,
+ "Transmision Header Byte 1");
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ /* Byte 1 */
+ proto_tree_add_uint(bf_tree, hf_sna_th_tgsf, tvb, offset, 1,
+ th_byte);
+ proto_tree_add_boolean(bf_tree, hf_sna_th_mft, tvb, offset, 1,
+ th_byte);
+ proto_tree_add_uint(bf_tree, hf_sna_th_piubf, tvb, offset, 1,
+ th_byte);
+
+ mft = th_byte & 0x04;
+ offset += 1;
+ th_byte = tvb_get_guint8(tvb, offset);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_text(tree, tvb, offset, 1,
+ "Transmision Header Byte 2");
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ /* Byte 2 */
+ if (mft) {
+ proto_tree_add_uint(bf_tree, hf_sna_th_nlpoi, tvb,
+ offset, 1, th_byte);
+ proto_tree_add_uint(bf_tree, hf_sna_th_nlp_cp, tvb,
+ offset, 1, th_byte);
+ } else {
+ proto_tree_add_uint(bf_tree, hf_sna_th_iern, tvb,
+ offset, 1, th_byte);
+ }
+ proto_tree_add_uint(bf_tree, hf_sna_th_ern, tvb, offset, 1,
+ th_byte);
+
+ offset += 1;
+ th_byte = tvb_get_guint8(tvb, offset);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_text(tree, tvb, offset, 1,
+ "Transmision Header Byte 3");
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ /* Byte 3 */
+ proto_tree_add_uint(bf_tree, hf_sna_th_vrn, tvb, offset, 1,
+ th_byte);
+ proto_tree_add_uint(bf_tree, hf_sna_th_tpf, tvb, offset, 1,
+ th_byte);
+
+ offset += 1;
+ th_word = tvb_get_ntohs(tvb, offset);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_text(tree, tvb, offset, 2,
+ "Transmision Header Bytes 4-5");
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ /* Bytes 4-5 */
+ proto_tree_add_uint(bf_tree, hf_sna_th_vr_cwi, tvb,
+ offset, 2, th_word);
+ proto_tree_add_boolean(bf_tree, hf_sna_th_tg_nonfifo_ind, tvb,
+ offset, 2, th_word);
+ proto_tree_add_uint(bf_tree, hf_sna_th_vr_sqti, tvb,
+ offset, 2, th_word);
+
+ /* I'm not sure about byte-order on this one... */
+ proto_tree_add_uint(bf_tree, hf_sna_th_tg_snf, tvb,
+ offset, 2, th_word);
+
+ offset += 2;
+ th_word = tvb_get_ntohs(tvb, offset);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_text(tree, tvb, offset, 2,
+ "Transmision Header Bytes 6-7");
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ /* Bytes 6-7 */
+ proto_tree_add_boolean(bf_tree, hf_sna_th_vrprq, tvb, offset,
+ 2, th_word);
+ proto_tree_add_boolean(bf_tree, hf_sna_th_vrprs, tvb, offset,
+ 2, th_word);
+ proto_tree_add_uint(bf_tree, hf_sna_th_vr_cwri, tvb, offset,
+ 2, th_word);
+ proto_tree_add_boolean(bf_tree, hf_sna_th_vr_rwi, tvb, offset,
+ 2, th_word);
+
+ /* I'm not sure about byte-order on this one... */
+ proto_tree_add_uint(bf_tree, hf_sna_th_vr_snf_send, tvb,
+ offset, 2, th_word);
+
+ offset += 2;
+
+ dsaf = tvb_get_ntohl(tvb, 8);
+ /* Bytes 8-11 */
+ proto_tree_add_uint(tree, hf_sna_th_dsaf, tvb, offset, 4, dsaf);
+
+ offset += 4;
+
+ osaf = tvb_get_ntohl(tvb, 12);
+ /* Bytes 12-15 */
+ proto_tree_add_uint(tree, hf_sna_th_osaf, tvb, offset, 4, osaf);
+
+ offset += 4;
+ th_byte = tvb_get_guint8(tvb, offset);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_text(tree, tvb, offset, 2,
+ "Transmision Header Byte 16");
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ /* Byte 16 */
+ proto_tree_add_boolean(tree, hf_sna_th_snai, tvb, offset, 1, th_byte);
+
+ /* We luck out here because in their infinite wisdom the SNA
+ * architects placed the MPF and EFI fields in the same bitfield
+ * locations, even though for FID4 they're not in byte 0.
+ * Thank you IBM! */
+ proto_tree_add_uint(tree, hf_sna_th_mpf, tvb, offset, 1, th_byte);
+ proto_tree_add_uint(tree, hf_sna_th_efi, tvb, offset, 1, th_byte);
+
+ offset += 2;
+ /* 1 for byte 16, 1 for byte 17 which is reserved */
+
+ def = tvb_get_ntohs(tvb, 18);
+ /* Bytes 18-25 */
+ proto_tree_add_uint(tree, hf_sna_th_def, tvb, offset, 2, def);
+
+ /* Addresses in FID 4 are discontiguous, sigh */
+ dst.saf = dsaf;
+ dst.ef = def;
+ SET_ADDRESS(&pinfo->net_dst, AT_SNA, SNA_FID_TYPE_4_ADDR_LEN,
+ (guint8* )&dst);
+ SET_ADDRESS(&pinfo->dst, AT_SNA, SNA_FID_TYPE_4_ADDR_LEN,
+ (guint8 *)&dst);
+
+ oef = tvb_get_ntohs(tvb, 20);
+ proto_tree_add_uint(tree, hf_sna_th_oef, tvb, offset+2, 2, oef);
+
+ /* Addresses in FID 4 are discontiguous, sigh */
+ src.saf = osaf;
+ src.ef = oef;
+ SET_ADDRESS(&pinfo->net_src, AT_SNA, SNA_FID_TYPE_4_ADDR_LEN,
+ (guint8 *)&src);
+ SET_ADDRESS(&pinfo->src, AT_SNA, SNA_FID_TYPE_4_ADDR_LEN,
+ (guint8 *)&src);
+
+ proto_tree_add_item(tree, hf_sna_th_snf, tvb, offset+4, 2, FALSE);
+ proto_tree_add_item(tree, hf_sna_th_dcf, tvb, offset+6, 2, FALSE);
+
+ return bytes_in_header;
+}
+
+/* FID Type 5 */
+static int
+dissect_fid5(tvbuff_t *tvb, proto_tree *tree)
+{
+ proto_tree *bf_tree;
+ proto_item *bf_item;
+ guint8 th_0;
+
+ const int bytes_in_header = 12;
+
+ /* If we're not filling a proto_tree, return now */
+ if (!tree)
+ return bytes_in_header;
+
+ th_0 = tvb_get_guint8(tvb, 0);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_uint(tree, hf_sna_th_0, tvb, 0, 1, th_0);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ proto_tree_add_uint(bf_tree, hf_sna_th_fid, tvb, 0, 1, th_0);
+ proto_tree_add_uint(bf_tree, hf_sna_th_mpf, tvb, 0, 1, th_0);
+ proto_tree_add_uint(bf_tree, hf_sna_th_efi, tvb, 0, 1, th_0);
+
+ proto_tree_add_text(tree, tvb, 1, 1, "Reserved");
+ proto_tree_add_item(tree, hf_sna_th_snf, tvb, 2, 2, FALSE);
+
+ proto_tree_add_item(tree, hf_sna_th_sa, tvb, 4, 8, FALSE);
+
+ return bytes_in_header;
+
+}
+
+/* FID Type f */
+static int
+dissect_fidf(tvbuff_t *tvb, proto_tree *tree)
+{
+ proto_tree *bf_tree;
+ proto_item *bf_item;
+ guint8 th_0;
+
+ const int bytes_in_header = 26;
+
+ /* If we're not filling a proto_tree, return now */
+ if (!tree)
+ return bytes_in_header;
+
+ th_0 = tvb_get_guint8(tvb, 0);
+
+ /* Create the bitfield tree */
+ bf_item = proto_tree_add_uint(tree, hf_sna_th_0, tvb, 0, 1, th_0);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_th_fid);
+
+ proto_tree_add_uint(bf_tree, hf_sna_th_fid, tvb, 0, 1, th_0);
+ proto_tree_add_text(tree, tvb, 1, 1, "Reserved");
+
+ proto_tree_add_item(tree, hf_sna_th_cmd_fmt, tvb, 2, 1, FALSE);
+ proto_tree_add_item(tree, hf_sna_th_cmd_type, tvb, 3, 1, FALSE);
+ proto_tree_add_item(tree, hf_sna_th_cmd_sn, tvb, 4, 2, FALSE);
+
+ /* Yup, bytes 6-23 are reserved! */
+ proto_tree_add_text(tree, tvb, 6, 18, "Reserved");
+
+ proto_tree_add_item(tree, hf_sna_th_dcf, tvb, 24, 2, FALSE);
+
+ return bytes_in_header;
+}
+
+static void
+dissect_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *parent_tree)
+{
+
+ proto_tree *th_tree = NULL, *rh_tree = NULL;
+ proto_item *th_ti = NULL, *rh_ti = NULL;
+ guint8 th_fid;
+ int th_header_len = 0;
+ int offset, rh_offset;
+ tvbuff_t *rh_tvb = NULL;
+ next_dissection_t continue_dissecting = everything;
+
+ /* Transmission Header Format Identifier */
+ th_fid = hi_nibble(tvb_get_guint8(tvb, 0));
+
+ /* Summary information */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(th_fid, sna_th_fid_vals, "Unknown FID: %01x"));
+
+ if (tree) {
+ /* --- TH --- */
+ /* Don't bother setting length. We'll set it later after we
+ * find the length of TH */
+ th_ti = proto_tree_add_item(tree, hf_sna_th, tvb, 0, -1,
+ FALSE);
+ th_tree = proto_item_add_subtree(th_ti, ett_sna_th);
+ }
+
+ /* Get size of TH */
+ switch(th_fid) {
+ case 0x0:
+ case 0x1:
+ th_header_len = dissect_fid0_1(tvb, pinfo, th_tree);
+ break;
+ case 0x2:
+ th_header_len = dissect_fid2(tvb, pinfo, th_tree,
+ &rh_tvb, &continue_dissecting);
+ break;
+ case 0x3:
+ th_header_len = dissect_fid3(tvb, th_tree);
+ break;
+ case 0x4:
+ th_header_len = dissect_fid4(tvb, pinfo, th_tree);
+ break;
+ case 0x5:
+ th_header_len = dissect_fid5(tvb, th_tree);
+ break;
+ case 0xf:
+ th_header_len = dissect_fidf(tvb, th_tree);
+ break;
+ default:
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, 1, -1, -1), pinfo, parent_tree);
+ return;
+ }
+
+ offset = th_header_len;
+
+ /* Short-circuit ? */
+ if (continue_dissecting == stop_here) {
+ if (tree) {
+ proto_tree_add_text(tree, tvb, offset, -1,
+ "BIU segment data");
+ }
+ return;
+ }
+
+ /* If the FID dissector function didn't create an rh_tvb, then we just
+ * use the rest of our tvbuff as the rh_tvb. */
+ if (!rh_tvb)
+ rh_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ rh_offset = 0;
+
+ /* Process the rest of the SNA packet, starting with RH */
+ if (tree) {
+ proto_item_set_len(th_ti, th_header_len);
+
+ /* --- RH --- */
+ rh_ti = proto_tree_add_item(tree, hf_sna_rh, rh_tvb, rh_offset,
+ RH_LEN, FALSE);
+ rh_tree = proto_item_add_subtree(rh_ti, ett_sna_rh);
+ dissect_rh(rh_tvb, rh_offset, rh_tree);
+ }
+
+ rh_offset += RH_LEN;
+
+ if (tvb_offset_exists(rh_tvb, rh_offset)) {
+ /* Short-circuit ? */
+ if (continue_dissecting == rh_only) {
+ if (tree)
+ proto_tree_add_text(tree, rh_tvb, rh_offset, -1,
+ "BIU segment data");
+ return;
+ }
+
+ call_dissector(data_handle,
+ tvb_new_subset(rh_tvb, rh_offset, -1, -1),
+ pinfo, parent_tree);
+ }
+}
+
+/* --------------------------------------------------------------------
+ * Chapter 5 Request/Response Headers (RHs)
+ * --------------------------------------------------------------------
+ */
+
+static void
+dissect_rh(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree *bf_tree;
+ proto_item *bf_item;
+ gboolean is_response;
+ guint8 rh_0, rh_1, rh_2;
+
+ if (!tree)
+ return;
+
+ /* Create the bitfield tree for byte 0*/
+ rh_0 = tvb_get_guint8(tvb, offset);
+ is_response = (rh_0 & 0x80);
+
+ bf_item = proto_tree_add_uint(tree, hf_sna_rh_0, tvb, offset, 1, rh_0);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_rh_0);
+
+ proto_tree_add_uint(bf_tree, hf_sna_rh_rri, tvb, offset, 1, rh_0);
+ proto_tree_add_uint(bf_tree, hf_sna_rh_ru_category, tvb, offset, 1,
+ rh_0);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_fi, tvb, offset, 1, rh_0);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_sdi, tvb, offset, 1, rh_0);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_bci, tvb, offset, 1, rh_0);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_eci, tvb, offset, 1, rh_0);
+
+ offset += 1;
+ rh_1 = tvb_get_guint8(tvb, offset);
+
+ /* Create the bitfield tree for byte 1*/
+ bf_item = proto_tree_add_uint(tree, hf_sna_rh_1, tvb, offset, 1, rh_1);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_rh_1);
+
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_dr1, tvb, offset, 1, rh_1);
+
+ if (!is_response)
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_lcci, tvb, offset, 1,
+ rh_1);
+
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_dr2, tvb, offset, 1, rh_1);
+
+ if (is_response) {
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_rti, tvb, offset, 1,
+ rh_1);
+ } else {
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_eri, tvb, offset, 1,
+ rh_1);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_rlwi, tvb, offset, 1,
+ rh_1);
+ }
+
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_qri, tvb, offset, 1, rh_1);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_pi, tvb, offset, 1, rh_1);
+
+ offset += 1;
+ rh_2 = tvb_get_guint8(tvb, offset);
+
+ /* Create the bitfield tree for byte 2*/
+ bf_item = proto_tree_add_uint(tree, hf_sna_rh_2, tvb, offset, 1, rh_2);
+
+ if (!is_response) {
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_rh_2);
+
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_bbi, tvb, offset, 1,
+ rh_2);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_ebi, tvb, offset, 1,
+ rh_2);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_cdi, tvb, offset, 1,
+ rh_2);
+ proto_tree_add_uint(bf_tree, hf_sna_rh_csi, tvb, offset, 1,
+ rh_2);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_edi, tvb, offset, 1,
+ rh_2);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_pdi, tvb, offset, 1,
+ rh_2);
+ proto_tree_add_boolean(bf_tree, hf_sna_rh_cebi, tvb, offset, 1,
+ rh_2);
+ }
+
+ /* XXX - check for sdi. If TRUE, the next 4 bytes will be sense data */
+}
+
+/* --------------------------------------------------------------------
+ * Chapter 6 Request/Response Units (RUs)
+ * --------------------------------------------------------------------
+ */
+
+/* --------------------------------------------------------------------
+ * Chapter 9 Common Fields
+ * --------------------------------------------------------------------
+ */
+
+static void
+dissect_control_05hpr(tvbuff_t *tvb, proto_tree *tree, int hpr,
+ enum parse parse)
+{
+ proto_tree *bf_tree;
+ proto_item *bf_item;
+ guint8 type;
+ guint16 offset, len, pad;
+
+ if (!tree)
+ return;
+
+ type = tvb_get_guint8(tvb, 2);
+
+ bf_item = proto_tree_add_uint(tree, hf_sna_control_05_type, tvb,
+ 2, 1, type);
+ bf_tree = proto_item_add_subtree(bf_item, ett_sna_control_05hpr_type);
+
+ proto_tree_add_boolean(bf_tree, hf_sna_control_05_ptp, tvb, 2, 1, type);
+ proto_tree_add_text(tree, tvb, 3, 1, "Reserved");
+
+ offset = 4;
+
+ while (tvb_offset_exists(tvb, offset)) {
+ if (parse == LT) {
+ len = tvb_get_guint8(tvb, offset+0);
+ } else {
+ len = tvb_get_guint8(tvb, offset+1);
+ }
+ if (len) {
+ dissect_control(tvb, offset, len, tree, hpr, parse);
+ pad = (len+3) & 0xfffc;
+ if (pad > len)
+ proto_tree_add_text(tree, tvb, offset+len,
+ pad-len, "Padding");
+ offset += pad;
+ } else {
+ return;
+ }
+ }
+}
+
+static void
+dissect_control_05(tvbuff_t *tvb, proto_tree *tree)
+{
+ if(!tree)
+ return;
+
+ proto_tree_add_item(tree, hf_sna_control_05_delay, tvb, 2, 2, FALSE);
+}
+
+static void
+dissect_control_0e(tvbuff_t *tvb, proto_tree *tree)
+{
+ gint len;
+ guint8 *buf;
+
+ if (!tree)
+ return;
+
+ proto_tree_add_item(tree, hf_sna_control_0e_type, tvb, 2, 1, FALSE);
+
+ len = tvb_reported_length_remaining(tvb, 3);
+ if (len <= 0)
+ return;
+
+ buf = tvb_get_string(tvb, 3, len);
+ EBCDIC_to_ASCII(buf, len);
+ proto_tree_add_string(tree, hf_sna_control_0e_value, tvb, 3, len, buf);
+ g_free(buf);
+}
+
+static void
+dissect_control(tvbuff_t *parent_tvb, int offset, int control_len,
+ proto_tree *tree, int hpr, enum parse parse)
+{
+ tvbuff_t *tvb;
+ gint length, reported_length;
+ proto_tree *sub_tree;
+ proto_item *sub_item;
+ int len, key;
+ gint ett;
+
+ length = tvb_length_remaining(parent_tvb, offset);
+ reported_length = tvb_reported_length_remaining(parent_tvb, offset);
+ if (control_len < length)
+ length = control_len;
+ if (control_len < reported_length)
+ reported_length = control_len;
+ tvb = tvb_new_subset(parent_tvb, offset, length, reported_length);
+
+ sub_tree = NULL;
+
+ if (parse == LT) {
+ len = tvb_get_guint8(tvb, 0);
+ key = tvb_get_guint8(tvb, 1);
+ } else {
+ key = tvb_get_guint8(tvb, 0);
+ len = tvb_get_guint8(tvb, 1);
+ }
+ ett = ett_sna_control_un;
+
+ if (tree) {
+ if (key == 5) {
+ if (hpr) ett = ett_sna_control_05hpr;
+ else ett = ett_sna_control_05;
+ }
+ if (key == 0x0e) ett = ett_sna_control_0e;
+
+ if (((key == 0) || (key == 3) || (key == 5)) && hpr)
+ sub_item = proto_tree_add_text(tree, tvb, 0, -1,
+ val_to_str(key, sna_control_hpr_vals,
+ "Unknown Control Vector"));
+ else
+ sub_item = proto_tree_add_text(tree, tvb, 0, -1,
+ val_to_str(key, sna_control_vals,
+ "Unknown Control Vector"));
+ sub_tree = proto_item_add_subtree(sub_item, ett);
+ if (parse == LT) {
+ proto_tree_add_uint(sub_tree, hf_sna_control_len,
+ tvb, 0, 1, len);
+ if (((key == 0) || (key == 3) || (key == 5)) && hpr)
+ proto_tree_add_uint(sub_tree,
+ hf_sna_control_hprkey, tvb, 1, 1, key);
+ else
+ proto_tree_add_uint(sub_tree,
+ hf_sna_control_key, tvb, 1, 1, key);
+ } else {
+ if (((key == 0) || (key == 3) || (key == 5)) && hpr)
+ proto_tree_add_uint(sub_tree,
+ hf_sna_control_hprkey, tvb, 0, 1, key);
+ else
+ proto_tree_add_uint(sub_tree,
+ hf_sna_control_key, tvb, 0, 1, key);
+ proto_tree_add_uint(sub_tree, hf_sna_control_len,
+ tvb, 1, 1, len);
+ }
+ }
+ switch(key) {
+ case 0x05:
+ if (hpr)
+ dissect_control_05hpr(tvb, sub_tree, hpr,
+ parse);
+ else
+ dissect_control_05(tvb, sub_tree);
+ break;
+ case 0x0e:
+ dissect_control_0e(tvb, sub_tree);
+ break;
+ }
+}
+
+/* --------------------------------------------------------------------
+ * Chapter 11 Function Management (FM) Headers
+ * --------------------------------------------------------------------
+ */
+
+/* --------------------------------------------------------------------
+ * Chapter 12 Presentation Services (PS) Headers
+ * --------------------------------------------------------------------
+ */
+
+/* --------------------------------------------------------------------
+ * Chapter 13 GDS Variables
+ * --------------------------------------------------------------------
+ */
+
+static void
+dissect_gds(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *parent_tree)
+{
+ guint16 length;
+ guint16 type;
+ int cont;
+ int offset;
+ proto_tree *gds_tree;
+ proto_item *gds_item;
+
+ offset = 0;
+ cont = 1;
+ type = tvb_get_ntohs(tvb, offset+2);
+
+ while (cont) {
+ length = tvb_get_ntohs(tvb, offset) & 0x7fff;
+ cont = (tvb_get_ntohs(tvb, offset) & 0x8000) ? 1 : 0;
+ type = tvb_get_ntohs(tvb, offset+2);
+
+ if (length < 2 ) /* escape sequence ? */
+ return;
+ if (tree) {
+ gds_item = proto_tree_add_item(tree, hf_sna_gds, tvb,
+ offset, length, FALSE);
+ gds_tree = proto_item_add_subtree(gds_item,
+ ett_sna_gds);
+
+ proto_tree_add_uint(gds_tree, hf_sna_gds_len, tvb,
+ offset, 2, length);
+ proto_tree_add_boolean(gds_tree, hf_sna_gds_cont, tvb,
+ offset, 2, cont);
+ proto_tree_add_uint(gds_tree, hf_sna_gds_type, tvb,
+ offset+2, 2, type);
+ }
+ offset += length;
+ }
+ if (tvb_offset_exists(tvb, offset))
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, parent_tree);
+}
+
+/* --------------------------------------------------------------------
+ * General stuff
+ * --------------------------------------------------------------------
+ */
+
+static void
+dissect_sna(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 fid;
+ proto_tree *sna_tree = NULL;
+ proto_item *sna_ti = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SNA");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* SNA data should be printed in EBCDIC, not ASCII */
+ pinfo->fd->flags.encoding = CHAR_EBCDIC;
+
+ if (tree) {
+
+ /* Don't bother setting length. We'll set it later after we find
+ * the lengths of TH/RH/RU */
+ sna_ti = proto_tree_add_item(tree, proto_sna, tvb, 0, -1,
+ FALSE);
+ sna_tree = proto_item_add_subtree(sna_ti, ett_sna);
+ }
+
+ /* Transmission Header Format Identifier */
+ fid = hi_nibble(tvb_get_guint8(tvb, 0));
+ switch(fid) {
+ case 0xa: /* HPR Network Layer Packet */
+ case 0xb:
+ case 0xc:
+ case 0xd:
+ dissect_nlp(tvb, pinfo, sna_tree, tree);
+ break;
+ default:
+ dissect_fid(tvb, pinfo, sna_tree, tree);
+ }
+}
+
+static void
+dissect_sna_xid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *sna_tree = NULL;
+ proto_item *sna_ti = NULL;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SNA");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* SNA data should be printed in EBCDIC, not ASCII */
+ pinfo->fd->flags.encoding = CHAR_EBCDIC;
+
+ if (tree) {
+
+ /* Don't bother setting length. We'll set it later after we find
+ * the lengths of XID */
+ sna_ti = proto_tree_add_item(tree, proto_sna_xid, tvb, 0, -1,
+ FALSE);
+ sna_tree = proto_item_add_subtree(sna_ti, ett_sna);
+ }
+ dissect_xid(tvb, pinfo, sna_tree, tree);
+}
+
+static void
+sna_init(void)
+{
+ fragment_table_init(&sna_fragment_table);
+ reassembled_table_init(&sna_reassembled_table);
+}
+
+
+void
+proto_register_sna(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_sna_th,
+ { "Transmission Header", "sna.th", FT_NONE, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_0,
+ { "Transmission Header Byte 0", "sna.th.0", FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ "TH Byte 0", HFILL }},
+
+ { &hf_sna_th_fid,
+ { "Format Identifer", "sna.th.fid", FT_UINT8, BASE_HEX,
+ VALS(sna_th_fid_vals), 0xf0, "", HFILL }},
+
+ { &hf_sna_th_mpf,
+ { "Mapping Field", "sna.th.mpf", FT_UINT8,
+ BASE_DEC, VALS(sna_th_mpf_vals), 0x0c, "", HFILL }},
+
+ { &hf_sna_th_odai,
+ { "ODAI Assignment Indicator", "sna.th.odai", FT_UINT8,
+ BASE_DEC, NULL, 0x02, "", HFILL }},
+
+ { &hf_sna_th_efi,
+ { "Expedited Flow Indicator", "sna.th.efi", FT_UINT8,
+ BASE_DEC, VALS(sna_th_efi_vals), 0x01, "", HFILL }},
+
+ { &hf_sna_th_daf,
+ { "Destination Address Field", "sna.th.daf", FT_UINT16,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_oaf,
+ { "Origin Address Field", "sna.th.oaf", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_snf,
+ { "Sequence Number Field", "sna.th.snf", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_dcf,
+ { "Data Count Field", "sna.th.dcf", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_lsid,
+ { "Local Session Identification", "sna.th.lsid", FT_UINT8,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_tg_sweep,
+ { "Transmission Group Sweep", "sna.th.tg_sweep", FT_UINT8,
+ BASE_DEC, VALS(sna_th_tg_sweep_vals), 0x08, "", HFILL }},
+
+ { &hf_sna_th_er_vr_supp_ind,
+ { "ER and VR Support Indicator", "sna.th.er_vr_supp_ind",
+ FT_UINT8, BASE_DEC, VALS(sna_th_er_vr_supp_ind_vals),
+ 0x04, "", HFILL }},
+
+ { &hf_sna_th_vr_pac_cnt_ind,
+ { "Virtual Route Pacing Count Indicator",
+ "sna.th.vr_pac_cnt_ind", FT_UINT8, BASE_DEC,
+ VALS(sna_th_vr_pac_cnt_ind_vals), 0x02, "", HFILL }},
+
+ { &hf_sna_th_ntwk_prty,
+ { "Network Priority", "sna.th.ntwk_prty", FT_UINT8, BASE_DEC,
+ VALS(sna_th_ntwk_prty_vals), 0x01, "", HFILL }},
+
+ { &hf_sna_th_tgsf,
+ { "Transmission Group Segmenting Field", "sna.th.tgsf",
+ FT_UINT8, BASE_HEX, VALS(sna_th_tgsf_vals), 0xc0,
+ "", HFILL }},
+
+ { &hf_sna_th_mft,
+ { "MPR FID4 Type", "sna.th.mft", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x04, "", HFILL }},
+
+ { &hf_sna_th_piubf,
+ { "PIU Blocking Field", "sna.th.piubf", FT_UINT8, BASE_HEX,
+ VALS(sna_th_piubf_vals), 0x03, "", HFILL }},
+
+ { &hf_sna_th_iern,
+ { "Initial Explicit Route Number", "sna.th.iern", FT_UINT8,
+ BASE_DEC, NULL, 0xf0, "", HFILL }},
+
+ { &hf_sna_th_nlpoi,
+ { "NLP Offset Indicator", "sna.th.nlpoi", FT_UINT8, BASE_DEC,
+ VALS(sna_th_nlpoi_vals), 0x80, "", HFILL }},
+
+ { &hf_sna_th_nlp_cp,
+ { "NLP Count or Padding", "sna.th.nlp_cp", FT_UINT8, BASE_DEC,
+ NULL, 0x70, "", HFILL }},
+
+ { &hf_sna_th_ern,
+ { "Explicit Route Number", "sna.th.ern", FT_UINT8, BASE_DEC,
+ NULL, 0x0f, "", HFILL }},
+
+ { &hf_sna_th_vrn,
+ { "Virtual Route Number", "sna.th.vrn", FT_UINT8, BASE_DEC,
+ NULL, 0xf0, "", HFILL }},
+
+ { &hf_sna_th_tpf,
+ { "Transmission Priority Field", "sna.th.tpf", FT_UINT8,
+ BASE_HEX, VALS(sna_th_tpf_vals), 0x03, "", HFILL }},
+
+ { &hf_sna_th_vr_cwi,
+ { "Virtual Route Change Window Indicator", "sna.th.vr_cwi",
+ FT_UINT16, BASE_DEC, VALS(sna_th_vr_cwi_vals), 0x8000,
+ "Change Window Indicator", HFILL }},
+
+ { &hf_sna_th_tg_nonfifo_ind,
+ { "Transmission Group Non-FIFO Indicator",
+ "sna.th.tg_nonfifo_ind", FT_BOOLEAN, 16,
+ TFS(&sna_th_tg_nonfifo_ind_truth), 0x4000, "", HFILL }},
+
+ { &hf_sna_th_vr_sqti,
+ { "Virtual Route Sequence and Type Indicator", "sna.th.vr_sqti",
+ FT_UINT16, BASE_HEX, VALS(sna_th_vr_sqti_vals), 0x3000,
+ "Route Sequence and Type", HFILL }},
+
+ { &hf_sna_th_tg_snf,
+ { "Transmission Group Sequence Number Field", "sna.th.tg_snf",
+ FT_UINT16, BASE_DEC, NULL, 0x0fff, "", HFILL }},
+
+ { &hf_sna_th_vrprq,
+ { "Virtual Route Pacing Request", "sna.th.vrprq", FT_BOOLEAN,
+ 16, TFS(&sna_th_vrprq_truth), 0x8000, "", HFILL }},
+
+ { &hf_sna_th_vrprs,
+ { "Virtual Route Pacing Response", "sna.th.vrprs", FT_BOOLEAN,
+ 16, TFS(&sna_th_vrprs_truth), 0x4000, "", HFILL }},
+
+ { &hf_sna_th_vr_cwri,
+ { "Virtual Route Change Window Reply Indicator",
+ "sna.th.vr_cwri", FT_UINT16, BASE_DEC,
+ VALS(sna_th_vr_cwri_vals), 0x2000, "", HFILL }},
+
+ { &hf_sna_th_vr_rwi,
+ { "Virtual Route Reset Window Indicator", "sna.th.vr_rwi",
+ FT_BOOLEAN, 16, TFS(&sna_th_vr_rwi_truth), 0x1000,
+ "", HFILL }},
+
+ { &hf_sna_th_vr_snf_send,
+ { "Virtual Route Send Sequence Number Field",
+ "sna.th.vr_snf_send", FT_UINT16, BASE_DEC, NULL, 0x0fff,
+ "Send Sequence Number Field", HFILL }},
+
+ { &hf_sna_th_dsaf,
+ { "Destination Subarea Address Field", "sna.th.dsaf",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_osaf,
+ { "Origin Subarea Address Field", "sna.th.osaf", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_snai,
+ { "SNA Indicator", "sna.th.snai", FT_BOOLEAN, 8, NULL, 0x10,
+ "Used to identify whether the PIU originated or is destined"
+ " for an SNA or non-SNA device.", HFILL }},
+
+ { &hf_sna_th_def,
+ { "Destination Element Field", "sna.th.def", FT_UINT16,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_oef,
+ { "Origin Element Field", "sna.th.oef", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_sa,
+ { "Session Address", "sna.th.sa", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_cmd_fmt,
+ { "Command Format", "sna.th.cmd_fmt", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_cmd_type,
+ { "Command Type", "sna.th.cmd_type", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_th_cmd_sn,
+ { "Command Sequence Number", "sna.th.cmd_sn", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_nhdr,
+ { "Network Layer Packet Header", "sna.nlp.nhdr", FT_NONE,
+ BASE_NONE, NULL, 0x0, "NHDR", HFILL }},
+
+ { &hf_sna_nlp_nhdr_0,
+ { "Network Layer Packet Header Byte 0", "sna.nlp.nhdr.0",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_nhdr_1,
+ { "Network Layer Packet Header Byte 1", "sna.nlp.nhdr.1",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_sm,
+ { "Switching Mode Field", "sna.nlp.nhdr.sm", FT_UINT8,
+ BASE_HEX, VALS(sna_nlp_sm_vals), 0xe0, "", HFILL }},
+
+ { &hf_sna_nlp_tpf,
+ { "Transmission Priority Field", "sna.nlp.nhdr.tpf", FT_UINT8,
+ BASE_HEX, VALS(sna_th_tpf_vals), 0x06, "", HFILL }},
+
+ { &hf_sna_nlp_ft,
+ { "Function Type", "sna.nlp.nhdr.ft", FT_UINT8, BASE_HEX,
+ VALS(sna_nlp_ft_vals), 0xF0, "", HFILL }},
+
+ { &hf_sna_nlp_tspi,
+ { "Time Sensitive Packet Indicator", "sna.nlp.nhdr.tspi",
+ FT_BOOLEAN, 8, TFS(&sna_nlp_tspi_truth), 0x08, "", HFILL }},
+
+ { &hf_sna_nlp_slowdn1,
+ { "Slowdown 1", "sna.nlp.nhdr.slowdn1", FT_BOOLEAN, 8,
+ TFS(&sna_nlp_slowdn1_truth), 0x04, "", HFILL }},
+
+ { &hf_sna_nlp_slowdn2,
+ { "Slowdown 2", "sna.nlp.nhdr.slowdn2", FT_BOOLEAN, 8,
+ TFS(&sna_nlp_slowdn2_truth), 0x02, "", HFILL }},
+
+ { &hf_sna_nlp_fra,
+ { "Function Routing Address Entry", "sna.nlp.nhdr.fra",
+ FT_BYTES, BASE_NONE, NULL, 0, "", HFILL }},
+
+ { &hf_sna_nlp_anr,
+ { "Automatic Network Routing Entry", "sna.nlp.nhdr.anr",
+ FT_BYTES, BASE_HEX, NULL, 0, "", HFILL }},
+
+ { &hf_sna_nlp_frh,
+ { "Transmission Priority Field", "sna.nlp.frh", FT_UINT8,
+ BASE_HEX, VALS(sna_nlp_frh_vals), 0, "", HFILL }},
+
+ { &hf_sna_nlp_thdr,
+ { "RTP Transport Header", "sna.nlp.thdr", FT_NONE, BASE_NONE,
+ NULL, 0x0, "THDR", HFILL }},
+
+ { &hf_sna_nlp_tcid,
+ { "Transport Connection Identifier", "sna.nlp.thdr.tcid",
+ FT_BYTES, BASE_HEX, NULL, 0x0, "TCID", HFILL }},
+
+ { &hf_sna_nlp_thdr_8,
+ { "RTP Transport Packet Header Byte 8", "sna.nlp.thdr.8",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_setupi,
+ { "Setup Indicator", "sna.nlp.thdr.setupi", FT_BOOLEAN, 8,
+ TFS(&sna_nlp_setupi_truth), 0x40, "", HFILL }},
+
+ { &hf_sna_nlp_somi,
+ { "Start Of Message Indicator", "sna.nlp.thdr.somi",
+ FT_BOOLEAN, 8, TFS(&sna_nlp_somi_truth), 0x20, "", HFILL }},
+
+ { &hf_sna_nlp_eomi,
+ { "End Of Message Indicator", "sna.nlp.thdr.eomi", FT_BOOLEAN,
+ 8, TFS(&sna_nlp_eomi_truth), 0x10, "", HFILL }},
+
+ { &hf_sna_nlp_sri,
+ { "Session Request Indicator", "sna.nlp.thdr.sri", FT_BOOLEAN,
+ 8, TFS(&sna_nlp_sri_truth), 0x08, "", HFILL }},
+
+ { &hf_sna_nlp_rasapi,
+ { "Reply ASAP Indicator", "sna.nlp.thdr.rasapi", FT_BOOLEAN,
+ 8, TFS(&sna_nlp_rasapi_truth), 0x04, "", HFILL }},
+
+ { &hf_sna_nlp_retryi,
+ { "Retry Indicator", "sna.nlp.thdr.retryi", FT_BOOLEAN,
+ 8, TFS(&sna_nlp_retryi_truth), 0x02, "", HFILL }},
+
+ { &hf_sna_nlp_thdr_9,
+ { "RTP Transport Packet Header Byte 9", "sna.nlp.thdr.9",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_lmi,
+ { "Last Message Indicator", "sna.nlp.thdr.lmi", FT_BOOLEAN,
+ 8, TFS(&sna_nlp_lmi_truth), 0x80, "", HFILL }},
+
+ { &hf_sna_nlp_cqfi,
+ { "Connection Qualifyer Field Indicator", "sna.nlp.thdr.cqfi",
+ FT_BOOLEAN, 8, TFS(&sna_nlp_cqfi_truth), 0x08, "", HFILL }},
+
+ { &hf_sna_nlp_osi,
+ { "Optional Segments Present Indicator", "sna.nlp.thdr.osi",
+ FT_BOOLEAN, 8, TFS(&sna_nlp_osi_truth), 0x04, "", HFILL }},
+
+ { &hf_sna_nlp_offset,
+ { "Data Offset/4", "sna.nlp.thdr.offset", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Data Offset in Words", HFILL }},
+
+ { &hf_sna_nlp_dlf,
+ { "Data Length Field", "sna.nlp.thdr.dlf", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_bsn,
+ { "Byte Sequence Number", "sna.nlp.thdr.bsn", FT_UINT32,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_len,
+ { "Optional Segment Length/4", "sna.nlp.thdr.optional.len",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_type,
+ { "Optional Segment Type", "sna.nlp.thdr.optional.type",
+ FT_UINT8, BASE_HEX, VALS(sna_nlp_opti_vals), 0x0, "",
+ HFILL }},
+
+ { &hf_sna_nlp_opti_0d_version,
+ { "Version", "sna.nlp.thdr.optional.0d.version",
+ FT_UINT16, BASE_HEX, VALS(sna_nlp_opti_0d_version_vals),
+ 0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0d_4,
+ { "Connection Setup Byte 4", "sna.nlp.thdr.optional.0e.4",
+ FT_UINT8, BASE_HEX, NULL, 0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0d_target,
+ { "Target Resource ID Present",
+ "sna.nlp.thdr.optional.0d.target",
+ FT_BOOLEAN, 8, NULL, 0x80, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0d_arb,
+ { "ARB Flow Control", "sna.nlp.thdr.optional.0d.arb",
+ FT_BOOLEAN, 8, NULL, 0x10, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0d_reliable,
+ { "Reliable Connection", "sna.nlp.thdr.optional.0d.reliable",
+ FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0d_dedicated,
+ { "Dedicated RTP Connection",
+ "sna.nlp.thdr.optional.0d.dedicated",
+ FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0e_stat,
+ { "Status", "sna.nlp.thdr.optional.0e.stat",
+ FT_UINT8, BASE_HEX, NULL, 0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0e_gap,
+ { "Gap Detected", "sna.nlp.thdr.optional.0e.gap",
+ FT_BOOLEAN, 8, NULL, 0x80, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0e_idle,
+ { "RTP Idle Packet", "sna.nlp.thdr.optional.0e.idle",
+ FT_BOOLEAN, 8, NULL, 0x40, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0e_nabsp,
+ { "Number Of ABSP", "sna.nlp.thdr.optional.0e.nabsp",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0e_sync,
+ { "Status Report Number", "sna.nlp.thdr.optional.0e.sync",
+ FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0e_echo,
+ { "Status Acknowledge Number", "sna.nlp.thdr.optional.0e.echo",
+ FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0e_rseq,
+ { "Received Sequence Number", "sna.nlp.thdr.optional.0e.rseq",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0e_abspbeg,
+ { "ABSP Begin", "sna.nlp.thdr.optional.0e.abspbeg",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0e_abspend,
+ { "ABSP End", "sna.nlp.thdr.optional.0e.abspend",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_0f_bits,
+ { "Client Bits", "sna.nlp.thdr.optional.0f.bits",
+ FT_UINT8, BASE_HEX, VALS(sna_nlp_opti_0f_bits_vals),
+ 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_10_tcid,
+ { "Transport Connection Identifier",
+ "sna.nlp.thdr.optional.10.tcid",
+ FT_BYTES, BASE_HEX, NULL, 0x0, "TCID", HFILL }},
+
+ { &hf_sna_nlp_opti_12_sense,
+ { "Sense Data", "sna.nlp.thdr.optional.12.sense",
+ FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_len,
+ { "Length", "sna.nlp.thdr.optional.14.si.len",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_key,
+ { "Key", "sna.nlp.thdr.optional.14.si.key",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_2,
+ { "Switching Information Byte 2",
+ "sna.nlp.thdr.optional.14.si.2",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_refifo,
+ { "Resequencing (REFIFO) Indicator",
+ "sna.nlp.thdr.optional.14.si.refifo",
+ FT_BOOLEAN, 8, NULL, 0x80, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_mobility,
+ { "Mobility Indicator",
+ "sna.nlp.thdr.optional.14.si.mobility",
+ FT_BOOLEAN, 8, NULL, 0x40, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_dirsearch,
+ { "Directory Search Required on Path Switch Indicator",
+ "sna.nlp.thdr.optional.14.si.dirsearch",
+ FT_BOOLEAN, 8, NULL, 0x20, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_limitres,
+ { "Limited Resource Link Indicator",
+ "sna.nlp.thdr.optional.14.si.limitres",
+ FT_BOOLEAN, 8, NULL, 0x10, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_ncescope,
+ { "NCE Scope Indicator",
+ "sna.nlp.thdr.optional.14.si.ncescope",
+ FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_mnpsrscv,
+ { "MNPS RSCV Retention Indicator",
+ "sna.nlp.thdr.optional.14.si.mnpsrscv",
+ FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_maxpsize,
+ { "Maximum Packet Size On Return Path",
+ "sna.nlp.thdr.optional.14.si.maxpsize",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_switch,
+ { "Path Switch Time", "sna.nlp.thdr.optional.14.si.switch",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_si_alive,
+ { "RTP Alive Timer", "sna.nlp.thdr.optional.14.si.alive",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_rr_len,
+ { "Length", "sna.nlp.thdr.optional.14.rr.len",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_rr_key,
+ { "Key", "sna.nlp.thdr.optional.14.rr.key",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_rr_2,
+ { "Return Route TG Descriptor Byte 2",
+ "sna.nlp.thdr.optional.14.rr.2",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_rr_bfe,
+ { "BF Entry Indicator",
+ "sna.nlp.thdr.optional.14.rr.bfe",
+ FT_BOOLEAN, 8, NULL, 0x80, "", HFILL }},
+
+ { &hf_sna_nlp_opti_14_rr_num,
+ { "Number Of TG Control Vectors",
+ "sna.nlp.thdr.optional.14.rr.num",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_2,
+ { "Adaptive Rate Based Segment Byte 2",
+ "sna.nlp.thdr.optional.22.2",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_type,
+ { "Message Type",
+ "sna.nlp.thdr.optional.22.type",
+ FT_UINT8, BASE_HEX,
+ VALS(sna_nlp_opti_22_type_vals), 0xc0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_raa,
+ { "Rate Adjustment Action",
+ "sna.nlp.thdr.optional.22.raa",
+ FT_UINT8, BASE_HEX,
+ VALS(sna_nlp_opti_22_raa_vals), 0x38, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_parity,
+ { "Parity Indicator",
+ "sna.nlp.thdr.optional.22.parity",
+ FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_arb,
+ { "ARB Mode",
+ "sna.nlp.thdr.optional.22.arb",
+ FT_UINT8, BASE_HEX,
+ VALS(sna_nlp_opti_22_arb_vals), 0x03, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_3,
+ { "Adaptive Rate Based Segment Byte 3",
+ "sna.nlp.thdr.optional.22.3",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_ratereq,
+ { "Rate Request Correlator",
+ "sna.nlp.thdr.optional.22.ratereq",
+ FT_UINT8, BASE_DEC, NULL, 0xf0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_raterep,
+ { "Rate Reply Correlator",
+ "sna.nlp.thdr.optional.22.raterep",
+ FT_UINT8, BASE_DEC, NULL, 0x0f, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_field1,
+ { "Field 1", "sna.nlp.thdr.optional.22.field1",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_field2,
+ { "Field 2", "sna.nlp.thdr.optional.22.field2",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_field3,
+ { "Field 3", "sna.nlp.thdr.optional.22.field3",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_nlp_opti_22_field4,
+ { "Field 4", "sna.nlp.thdr.optional.22.field4",
+ FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_rh,
+ { "Request/Response Header", "sna.rh", FT_NONE, BASE_NONE,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_rh_0,
+ { "Request/Response Header Byte 0", "sna.rh.0", FT_UINT8,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_rh_1,
+ { "Request/Response Header Byte 1", "sna.rh.1", FT_UINT8,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_rh_2,
+ { "Request/Response Header Byte 2", "sna.rh.2", FT_UINT8,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_rh_rri,
+ { "Request/Response Indicator", "sna.rh.rri", FT_UINT8,
+ BASE_DEC, VALS(sna_rh_rri_vals), 0x80, "", HFILL }},
+
+ { &hf_sna_rh_ru_category,
+ { "Request/Response Unit Category", "sna.rh.ru_category",
+ FT_UINT8, BASE_HEX, VALS(sna_rh_ru_category_vals), 0x60,
+ "", HFILL }},
+
+ { &hf_sna_rh_fi,
+ { "Format Indicator", "sna.rh.fi", FT_BOOLEAN, 8,
+ TFS(&sna_rh_fi_truth), 0x08, "", HFILL }},
+
+ { &hf_sna_rh_sdi,
+ { "Sense Data Included", "sna.rh.sdi", FT_BOOLEAN, 8,
+ TFS(&sna_rh_sdi_truth), 0x04, "", HFILL }},
+
+ { &hf_sna_rh_bci,
+ { "Begin Chain Indicator", "sna.rh.bci", FT_BOOLEAN, 8,
+ TFS(&sna_rh_bci_truth), 0x02, "", HFILL }},
+
+ { &hf_sna_rh_eci,
+ { "End Chain Indicator", "sna.rh.eci", FT_BOOLEAN, 8,
+ TFS(&sna_rh_eci_truth), 0x01, "", HFILL }},
+
+ { &hf_sna_rh_dr1,
+ { "Definite Response 1 Indicator", "sna.rh.dr1", FT_BOOLEAN,
+ 8, NULL, 0x80, "", HFILL }},
+
+ { &hf_sna_rh_lcci,
+ { "Length-Checked Compression Indicator", "sna.rh.lcci",
+ FT_BOOLEAN, 8, TFS(&sna_rh_lcci_truth), 0x40, "", HFILL }},
+
+ { &hf_sna_rh_dr2,
+ { "Definite Response 2 Indicator", "sna.rh.dr2", FT_BOOLEAN,
+ 8, NULL, 0x20, "", HFILL }},
+
+ { &hf_sna_rh_eri,
+ { "Exception Response Indicator", "sna.rh.eri", FT_BOOLEAN,
+ 8, NULL, 0x10, "", HFILL }},
+
+ { &hf_sna_rh_rti,
+ { "Response Type Indicator", "sna.rh.rti", FT_BOOLEAN,
+ 8, TFS(&sna_rh_rti_truth), 0x10, "", HFILL }},
+
+ { &hf_sna_rh_rlwi,
+ { "Request Larger Window Indicator", "sna.rh.rlwi", FT_BOOLEAN,
+ 8, NULL, 0x04, "", HFILL }},
+
+ { &hf_sna_rh_qri,
+ { "Queued Response Indicator", "sna.rh.qri", FT_BOOLEAN,
+ 8, TFS(&sna_rh_qri_truth), 0x02, "", HFILL }},
+
+ { &hf_sna_rh_pi,
+ { "Pacing Indicator", "sna.rh.pi", FT_BOOLEAN,
+ 8, NULL, 0x01, "", HFILL }},
+
+ { &hf_sna_rh_bbi,
+ { "Begin Bracket Indicator", "sna.rh.bbi", FT_BOOLEAN,
+ 8, NULL, 0x80, "", HFILL }},
+
+ { &hf_sna_rh_ebi,
+ { "End Bracket Indicator", "sna.rh.ebi", FT_BOOLEAN,
+ 8, NULL, 0x40, "", HFILL }},
+
+ { &hf_sna_rh_cdi,
+ { "Change Direction Indicator", "sna.rh.cdi", FT_BOOLEAN,
+ 8, NULL, 0x20, "", HFILL }},
+
+ { &hf_sna_rh_csi,
+ { "Code Selection Indicator", "sna.rh.csi", FT_UINT8, BASE_DEC,
+ VALS(sna_rh_csi_vals), 0x08, "", HFILL }},
+
+ { &hf_sna_rh_edi,
+ { "Enciphered Data Indicator", "sna.rh.edi", FT_BOOLEAN, 8,
+ NULL, 0x04, "", HFILL }},
+
+ { &hf_sna_rh_pdi,
+ { "Padded Data Indicator", "sna.rh.pdi", FT_BOOLEAN, 8, NULL,
+ 0x02, "", HFILL }},
+
+ { &hf_sna_rh_cebi,
+ { "Conditional End Bracket Indicator", "sna.rh.cebi",
+ FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }},
+
+/* { &hf_sna_ru,
+ { "Request/Response Unit", "sna.ru", FT_NONE, BASE_NONE,
+ NULL, 0x0, "", HFILL }},*/
+
+ { &hf_sna_gds,
+ { "GDS Variable", "sna.gds", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_sna_gds_len,
+ { "GDS Variable Length", "sna.gds.len", FT_UINT16, BASE_DEC,
+ NULL, 0x7fff, "", HFILL }},
+
+ { &hf_sna_gds_cont,
+ { "Continuation Flag", "sna.gds.cont", FT_BOOLEAN, 16, NULL,
+ 0x8000, "", HFILL }},
+
+ { &hf_sna_gds_type,
+ { "Type of Variable", "sna.gds.type", FT_UINT16, BASE_HEX,
+ VALS(sna_gds_var_vals), 0x0, "", HFILL }},
+
+ { &hf_sna_xid,
+ { "XID", "sna.xid", FT_NONE, BASE_NONE, NULL, 0x0,
+ "XID Frame", HFILL }},
+
+ { &hf_sna_xid_0,
+ { "XID Byte 0", "sna.xid.0", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_sna_xid_format,
+ { "XID Format", "sna.xid.format", FT_UINT8, BASE_DEC, NULL,
+ 0xf0, "", HFILL }},
+
+ { &hf_sna_xid_type,
+ { "XID Type", "sna.xid.type", FT_UINT8, BASE_DEC,
+ VALS(sna_xid_type_vals), 0x0f, "", HFILL }},
+
+ { &hf_sna_xid_len,
+ { "XID Length", "sna.xid.len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_sna_xid_id,
+ { "Node Identification", "sna.xid.id", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_xid_idblock,
+ { "ID Block", "sna.xid.idblock", FT_UINT32, BASE_HEX, NULL,
+ 0xfff00000, "", HFILL }},
+
+ { &hf_sna_xid_idnum,
+ { "ID Number", "sna.xid.idnum", FT_UINT32, BASE_HEX, NULL,
+ 0x0fffff, "", HFILL }},
+
+ { &hf_sna_xid_3_8,
+ { "Characteristics of XID sender", "sna.xid.type3.8", FT_UINT16,
+ BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_xid_3_init_self,
+ { "INIT-SELF support", "sna.xid.type3.initself",
+ FT_BOOLEAN, 16, NULL, 0x8000, "", HFILL }},
+
+ { &hf_sna_xid_3_stand_bind,
+ { "Stand-Alone BIND Support", "sna.xid.type3.stand_bind",
+ FT_BOOLEAN, 16, NULL, 0x4000, "", HFILL }},
+
+ { &hf_sna_xid_3_gener_bind,
+ { "Whole BIND PIU generated indicator",
+ "sna.xid.type3.gener_bind", FT_BOOLEAN, 16, NULL, 0x2000,
+ "Whole BIND PIU generated", HFILL }},
+
+ { &hf_sna_xid_3_recve_bind,
+ { "Whole BIND PIU required indicator",
+ "sna.xid.type3.recve_bind", FT_BOOLEAN, 16, NULL, 0x1000,
+ "Whole BIND PIU required", HFILL }},
+
+ { &hf_sna_xid_3_actpu,
+ { "ACTPU suppression indicator", "sna.xid.type3.actpu",
+ FT_BOOLEAN, 16, NULL, 0x0080, "", HFILL }},
+
+ { &hf_sna_xid_3_nwnode,
+ { "Sender is network node", "sna.xid.type3.nwnode",
+ FT_BOOLEAN, 16, NULL, 0x0040, "", HFILL }},
+
+ { &hf_sna_xid_3_cp,
+ { "Control Point Services", "sna.xid.type3.cp",
+ FT_BOOLEAN, 16, NULL, 0x0020, "", HFILL }},
+
+ { &hf_sna_xid_3_cpcp,
+ { "CP-CP session support", "sna.xid.type3.cpcp",
+ FT_BOOLEAN, 16, NULL, 0x0010, "", HFILL }},
+
+ { &hf_sna_xid_3_state,
+ { "XID exchange state indicator", "sna.xid.type3.state",
+ FT_UINT16, BASE_HEX, VALS(sna_xid_3_state_vals),
+ 0x000c, "", HFILL }},
+
+ { &hf_sna_xid_3_nonact,
+ { "Nonactivation Exchange", "sna.xid.type3.nonact",
+ FT_BOOLEAN, 16, NULL, 0x0002, "", HFILL }},
+
+ { &hf_sna_xid_3_cpchange,
+ { "CP name change support", "sna.xid.type3.cpchange",
+ FT_BOOLEAN, 16, NULL, 0x0001, "", HFILL }},
+
+ { &hf_sna_xid_3_10,
+ { "XID Type 3 Byte 10", "sna.xid.type3.10", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_xid_3_asend_bind,
+ { "Adaptive BIND pacing support as sender",
+ "sna.xid.type3.asend_bind", FT_BOOLEAN, 8, NULL, 0x80,
+ "Pacing support as sender", HFILL }},
+
+ { &hf_sna_xid_3_arecv_bind,
+ { "Adaptive BIND pacing support as receiver",
+ "sna.xid.type3.asend_recv", FT_BOOLEAN, 8, NULL, 0x40,
+ "Pacing support as receive", HFILL }},
+
+ { &hf_sna_xid_3_quiesce,
+ { "Quiesce TG Request",
+ "sna.xid.type3.quiesce", FT_BOOLEAN, 8, NULL, 0x20,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_pucap,
+ { "PU Capabilities",
+ "sna.xid.type3.pucap", FT_BOOLEAN, 8, NULL, 0x10,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_pbn,
+ { "Peripheral Border Node",
+ "sna.xid.type3.pbn", FT_BOOLEAN, 8, NULL, 0x08,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_pacing,
+ { "Qualifier for adaptive BIND pacing support",
+ "sna.xid.type3.pacing", FT_UINT8, BASE_HEX, NULL, 0x03,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_11,
+ { "XID Type 3 Byte 11", "sna.xid.type3.11", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_xid_3_tgshare,
+ { "TG Sharing Prohibited Indicator",
+ "sna.xid.type3.tgshare", FT_BOOLEAN, 8, NULL, 0x40,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_dedsvc,
+ { "Dedicated SVC Idicator",
+ "sna.xid.type3.dedsvc", FT_BOOLEAN, 8, NULL, 0x20,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_12,
+ { "XID Type 3 Byte 12", "sna.xid.type3.12", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_xid_3_negcsup,
+ { "Negotiation Complete Supported",
+ "sna.xid.type3.negcsup", FT_BOOLEAN, 8, NULL, 0x80,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_negcomp,
+ { "Negotiation Complete",
+ "sna.xid.type3.negcomp", FT_BOOLEAN, 8, NULL, 0x40,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_15,
+ { "XID Type 3 Byte 15", "sna.xid.type3.15", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_xid_3_partg,
+ { "Parallel TG Support",
+ "sna.xid.type3.partg", FT_BOOLEAN, 8, NULL, 0x80,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_dlur,
+ { "Dependent LU Requester Indicator",
+ "sna.xid.type3.dlur", FT_BOOLEAN, 8, NULL, 0x40,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_dlus,
+ { "DLUS Served LU Registration Indicator",
+ "sna.xid.type3.dlus", FT_BOOLEAN, 8, NULL, 0x20,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_exbn,
+ { "Extended HPR Border Node",
+ "sna.xid.type3.exbn", FT_BOOLEAN, 8, NULL, 0x10,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_genodai,
+ { "Generalized ODAI Usage Option",
+ "sna.xid.type3.genodai", FT_BOOLEAN, 8, NULL, 0x08,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_branch,
+ { "Branch Indicator", "sna.xid.type3.branch",
+ FT_UINT8, BASE_HEX, VALS(sna_xid_3_branch_vals),
+ 0x06, "", HFILL }},
+
+ { &hf_sna_xid_3_brnn,
+ { "Option Set 1123 Indicator",
+ "sna.xid.type3.brnn", FT_BOOLEAN, 8, NULL, 0x01,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_tg,
+ { "XID TG", "sna.xid.type3.tg", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_dlc,
+ { "XID DLC", "sna.xid.type3.dlc", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_sna_xid_3_dlen,
+ { "DLC Dependent Section Length", "sna.xid.type3.dlen",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_control_len,
+ { "Control Vector Length", "sna.control.len",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_control_key,
+ { "Control Vector Key", "sna.control.key",
+ FT_UINT8, BASE_HEX, VALS(sna_control_vals), 0x0, "",
+ HFILL }},
+
+ { &hf_sna_control_hprkey,
+ { "Control Vector HPR Key", "sna.control.hprkey",
+ FT_UINT8, BASE_HEX, VALS(sna_control_hpr_vals), 0x0, "",
+ HFILL }},
+
+ { &hf_sna_control_05_delay,
+ { "Channel Delay", "sna.control.05.delay",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_control_05_type,
+ { "Network Address Type", "sna.control.05.type",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+
+ { &hf_sna_control_05_ptp,
+ { "Point-to-point", "sna.control.05.ptp",
+ FT_BOOLEAN, 8, NULL, 0x80, "", HFILL }},
+
+ { &hf_sna_control_0e_type,
+ { "Type", "sna.control.0e.type",
+ FT_UINT8, BASE_HEX, VALS(sna_control_0e_type_vals),
+ 0, "", HFILL }},
+
+ { &hf_sna_control_0e_value,
+ { "Value", "sna.control.0e.value",
+ FT_STRING, BASE_NONE, NULL, 0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_sna,
+ &ett_sna_th,
+ &ett_sna_th_fid,
+ &ett_sna_nlp_nhdr,
+ &ett_sna_nlp_nhdr_0,
+ &ett_sna_nlp_nhdr_1,
+ &ett_sna_nlp_thdr,
+ &ett_sna_nlp_thdr_8,
+ &ett_sna_nlp_thdr_9,
+ &ett_sna_nlp_opti_un,
+ &ett_sna_nlp_opti_0d,
+ &ett_sna_nlp_opti_0d_4,
+ &ett_sna_nlp_opti_0e,
+ &ett_sna_nlp_opti_0e_stat,
+ &ett_sna_nlp_opti_0e_absp,
+ &ett_sna_nlp_opti_0f,
+ &ett_sna_nlp_opti_10,
+ &ett_sna_nlp_opti_12,
+ &ett_sna_nlp_opti_14,
+ &ett_sna_nlp_opti_14_si,
+ &ett_sna_nlp_opti_14_si_2,
+ &ett_sna_nlp_opti_14_rr,
+ &ett_sna_nlp_opti_14_rr_2,
+ &ett_sna_nlp_opti_22,
+ &ett_sna_nlp_opti_22_2,
+ &ett_sna_nlp_opti_22_3,
+ &ett_sna_rh,
+ &ett_sna_rh_0,
+ &ett_sna_rh_1,
+ &ett_sna_rh_2,
+ &ett_sna_gds,
+ &ett_sna_xid_0,
+ &ett_sna_xid_id,
+ &ett_sna_xid_3_8,
+ &ett_sna_xid_3_10,
+ &ett_sna_xid_3_11,
+ &ett_sna_xid_3_12,
+ &ett_sna_xid_3_15,
+ &ett_sna_control_un,
+ &ett_sna_control_05,
+ &ett_sna_control_05hpr,
+ &ett_sna_control_05hpr_type,
+ &ett_sna_control_0e,
+ };
+ module_t *sna_module;
+
+ proto_sna = proto_register_protocol("Systems Network Architecture",
+ "SNA", "sna");
+ proto_register_field_array(proto_sna, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("sna", dissect_sna, proto_sna);
+
+ proto_sna_xid = proto_register_protocol(
+ "Systems Network Architecture XID", "SNA XID", "sna_xid");
+ register_dissector("sna_xid", dissect_sna_xid, proto_sna_xid);
+
+ /* Register configuration options */
+ sna_module = prefs_register_protocol(proto_sna, NULL);
+ prefs_register_bool_preference(sna_module, "defragment",
+ "Reassemble fragmented BIUs",
+ "Whether fragmented BIUs should be reassembled",
+ &sna_defragment);
+}
+
+void
+proto_reg_handoff_sna(void)
+{
+ dissector_handle_t sna_handle;
+ dissector_handle_t sna_xid_handle;
+
+ sna_handle = find_dissector("sna");
+ sna_xid_handle = find_dissector("sna_xid");
+ dissector_add("llc.dsap", SAP_SNA_PATHCTRL, sna_handle);
+ dissector_add("llc.dsap", SAP_SNA1, sna_handle);
+ dissector_add("llc.dsap", SAP_SNA2, sna_handle);
+ dissector_add("llc.dsap", SAP_SNA3, sna_handle);
+ dissector_add("llc.xid_dsap", SAP_SNA_PATHCTRL, sna_xid_handle);
+ dissector_add("llc.xid_dsap", SAP_SNA1, sna_xid_handle);
+ dissector_add("llc.xid_dsap", SAP_SNA2, sna_xid_handle);
+ dissector_add("llc.xid_dsap", SAP_SNA3, sna_xid_handle);
+ /* RFC 2043 */
+ dissector_add("ppp.protocol", PPP_SNA, sna_handle);
+ data_handle = find_dissector("data");
+
+ register_init_routine(sna_init);
+}
diff --git a/epan/dissectors/packet-sna.h b/epan/dissectors/packet-sna.h
new file mode 100644
index 0000000000..47056a5a46
--- /dev/null
+++ b/epan/dissectors/packet-sna.h
@@ -0,0 +1,35 @@
+/* packet-sna.h
+ * Definitions for SNA dissection.
+ *
+ * $Id$
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_SNA_H__
+#define __PACKET_SNA_H__
+
+/*
+ * Structure used to represent an FID Type 4 address; gives the layout of the
+ * data pointed to by an AT_SNA "address" structure if the size is
+ * SNA_FID_TYPE_4_ADDR_LEN.
+ */
+#define SNA_FID_TYPE_4_ADDR_LEN 6
+struct sna_fid_type_4_addr {
+ guint32 saf;
+ guint16 ef;
+};
+
+#endif
diff --git a/epan/dissectors/packet-snaeth.c b/epan/dissectors/packet-snaeth.c
new file mode 100644
index 0000000000..b4e055a917
--- /dev/null
+++ b/epan/dissectors/packet-snaeth.c
@@ -0,0 +1,113 @@
+/* packet-snaeth.c
+ * Routines for SNA-over-Ethernet (Ethernet type 80d5)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "etypes.h"
+
+/*
+ * See
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/product/software/ssr90/rpc_r/18059.pdf
+ */
+
+static int proto_snaeth = -1;
+static int hf_snaeth_len = -1;
+
+static gint ett_snaeth = -1;
+
+static dissector_handle_t llc_handle;
+
+static void
+dissect_snaeth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *snaeth_tree;
+ proto_item *snaeth_ti;
+ guint16 len;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SNAETH");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "SNA over Ethernet");
+
+ /* length */
+ len = tvb_get_ntohs(tvb, 0);
+
+ if (tree) {
+ snaeth_ti = proto_tree_add_item(tree, proto_snaeth, tvb, 0, 3,
+ FALSE);
+ snaeth_tree = proto_item_add_subtree(snaeth_ti, ett_snaeth);
+ proto_tree_add_uint(snaeth_tree, hf_snaeth_len, tvb, 0, 2, len);
+ proto_tree_add_text(snaeth_tree, tvb, 2, 1, "Padding");
+ }
+
+ /*
+ * Adjust the length of this tvbuff to include only the SNA-over-
+ * Ethernet header and data.
+ */
+ set_actual_length(tvb, 3 + len);
+
+ /*
+ * Rest of packet starts with an 802.2 LLC header.
+ */
+ next_tvb = tvb_new_subset(tvb, 3, -1, -1);
+ call_dissector(llc_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_register_snaeth(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_snaeth_len,
+ { "Length", "snaeth_len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of LLC payload", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_snaeth,
+ };
+
+ proto_snaeth = proto_register_protocol("SNA-over-Ethernet",
+ "SNAETH", "snaeth");
+ proto_register_field_array(proto_snaeth, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_snaeth(void)
+{
+ dissector_handle_t snaeth_handle;
+
+ /*
+ * Get handle for the LLC dissector.
+ */
+ llc_handle = find_dissector("llc");
+
+ snaeth_handle = create_dissector_handle(dissect_snaeth, proto_snaeth);
+ dissector_add("ethertype", ETHERTYPE_SNA, snaeth_handle);
+}
diff --git a/epan/dissectors/packet-sndcp.c b/epan/dissectors/packet-sndcp.c
new file mode 100644
index 0000000000..b6123b3310
--- /dev/null
+++ b/epan/dissectors/packet-sndcp.c
@@ -0,0 +1,577 @@
+/* packet-sndcp.c
+ * Routines for Subnetwork Dependent Convergence Protocol (SNDCP) dissection
+ * Copyright 2000, Christian Falckenberg <christian.falckenberg@nortelnetworks.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "reassemble.h"
+
+/* Bitmasks for the bits in the address field
+*/
+#define MASK_X 0x80
+#define MASK_F 0x40
+#define MASK_T 0x20
+#define MASK_M 0x10
+
+/* Initialize the protocol and registered fields
+*/
+static int proto_sndcp = -1;
+static int hf_sndcp_x = -1;
+static int hf_sndcp_f = -1;
+static int hf_sndcp_t = -1;
+static int hf_sndcp_m = -1;
+static int hf_sndcp_nsapi = -1;
+static int hf_sndcp_nsapib = -1;
+static int hf_sndcp_dcomp = -1;
+static int hf_sndcp_pcomp = -1;
+static int hf_sndcp_segment = -1;
+static int hf_sndcp_npdu1 = -1;
+static int hf_sndcp_npdu2 = -1;
+
+/* These fields are used when reassembling N-PDU fragments
+*/
+static int hf_npdu_fragments = -1;
+static int hf_npdu_fragment = -1;
+static int hf_npdu_fragment_overlap = -1;
+static int hf_npdu_fragment_overlap_conflict = -1;
+static int hf_npdu_fragment_multiple_tails = -1;
+static int hf_npdu_fragment_too_long_fragment = -1;
+static int hf_npdu_fragment_error = -1;
+static int hf_npdu_reassembled_in = -1;
+
+/* Initialize the subtree pointers
+*/
+static gint ett_sndcp = -1;
+static gint ett_sndcp_address_field = -1;
+static gint ett_sndcp_compression_field = -1;
+static gint ett_sndcp_npdu_field = -1;
+static gint ett_npdu_fragment = -1;
+static gint ett_npdu_fragments = -1;
+
+/* Structure needed for the fragmentation routines in reassemble.c
+*/
+static const fragment_items npdu_frag_items = {
+ &ett_npdu_fragment,
+ &ett_npdu_fragments,
+ &hf_npdu_fragments,
+ &hf_npdu_fragment,
+ &hf_npdu_fragment_overlap,
+ &hf_npdu_fragment_overlap_conflict,
+ &hf_npdu_fragment_multiple_tails,
+ &hf_npdu_fragment_too_long_fragment,
+ &hf_npdu_fragment_error,
+ &hf_npdu_reassembled_in,
+ "fragments"
+};
+
+/* dissectors for the data portion of this protocol
+ */
+static dissector_handle_t data_handle;
+static dissector_handle_t ip_handle;
+
+/* reassembly of N-PDU
+ */
+static GHashTable *npdu_fragment_table = NULL;
+static void
+sndcp_defragment_init(void)
+{
+ fragment_table_init(&npdu_fragment_table);
+}
+
+/* value strings
+ */
+static const value_string nsapi_t[] = {
+ { 0, "Escape mechanism for future extensions"},
+ { 1, "Point-to-Multipoint (PTM-M) Information" },
+ { 2, "Reserved for future use" },
+ { 3, "Reserved for future use" },
+ { 4, "Reserved for future use" },
+ { 5, "Dynamically allocated"},
+ { 6, "Dynamically allocated"},
+ { 7, "Dynamically allocated"},
+ { 8, "Dynamically allocated"},
+ { 9, "Dynamically allocated"},
+ { 10, "Dynamically allocated"},
+ { 11, "Dynamically allocated"},
+ { 12, "Dynamically allocated"},
+ { 13, "Dynamically allocated"},
+ { 14, "Dynamically allocated"},
+ { 15, "Dynamically allocated"},
+ { 0, NULL },
+};
+
+static const value_string nsapi_abrv[] = {
+ { 0, "0"},
+ { 1, "PTM-M" },
+ { 2, "2" },
+ { 3, "3"},
+ { 4, "4" },
+ { 5, "DYN5" },
+ { 6, "DYN6" },
+ { 7, "DYN7" },
+ { 8, "DYN8" },
+ { 9, "DYN9" },
+ { 10, "DYN10" },
+ { 11, "DYN11" },
+ { 12, "DYN12" },
+ { 13, "DYN13" },
+ { 14, "DYN14" },
+ { 15, "DYN15" },
+ { 0, NULL },
+};
+
+static const value_string compression_vals[] = {
+ { 0, "No compression"},
+ { 1, "Pointer to selected protocol/data compression mechanism" },
+ { 2, "Pointer to selected protocol/data compression mechanism" },
+ { 3, "Pointer to selected protocol/data compression mechanism" },
+ { 4, "Pointer to selected protocol/data compression mechanism" },
+ { 5, "Pointer to selected protocol/data compression mechanism" },
+ { 6, "Pointer to selected protocol/data compression mechanism" },
+ { 7, "Pointer to selected protocol/data compression mechanism" },
+ { 8, "Pointer to selected protocol/data compression mechanism" },
+ { 9, "Pointer to selected protocol/data compression mechanism" },
+ { 10, "Pointer to selected protocol/data compression mechanism" },
+ { 11, "Pointer to selected protocol/data compression mechanism" },
+ { 12, "Pointer to selected protocol/data compression mechanism" },
+ { 13, "Pointer to selected protocol/data compression mechanism" },
+ { 14, "Pointer to selected protocol/data compression mechanism" },
+ { 15, "Pointer to selected protocol/data compression mechanism" },
+ { 0, NULL },
+};
+
+static const true_false_string x_bit = {
+ "Invalid",
+ "Set to 0 by transmitting SNDCP entity (ignored by receiver)"
+};
+static const true_false_string f_bit = {
+ "This SN-PDU is the first segment of an N-PDU",
+ "This SN-PDU is not the first segment of an N-PDU"
+};
+static const true_false_string t_bit = {
+ "SN-UNITDATA PDU",
+ "SN-DATA PDU"
+};
+static const true_false_string m_bit = {
+ "Not the last segment of N-PDU, more segments to follow",
+ "Last segment of N-PDU"
+};
+
+/* Code to actually dissect the packets
+*/
+static void
+dissect_sndcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 addr_field, comp_field, npdu_field1, nsapi, dcomp=0, pcomp=0;
+ guint16 offset=0, npdu=0, segment=0, npdu_field2;
+ tvbuff_t *next_tvb, *npdu_tvb;
+ guint32 len;
+ gboolean first, more_frags, unack;
+
+ /* Set up structures needed to add the protocol subtree and manage it
+ */
+ proto_item *ti, *address_field_item, *compression_field_item, *npdu_field_item;
+ proto_tree *sndcp_tree = NULL, *address_field_tree, *compression_field_tree, *npdu_field_tree;
+
+ /* Make entries in Protocol column and clear Info column on summary display
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SNDCP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* create display subtree for the protocol
+ */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_sndcp, tvb, 0, -1, FALSE);
+ sndcp_tree = proto_item_add_subtree(ti, ett_sndcp);
+ }
+
+ /* get address field from next byte
+ */
+ addr_field = tvb_get_guint8(tvb,offset);
+ nsapi = addr_field & 0xF;
+ first = addr_field & MASK_F;
+ more_frags = addr_field & MASK_M;
+ unack = addr_field & MASK_T;
+
+ /* add subtree for the address field
+ */
+ if (tree) {
+ address_field_item = proto_tree_add_uint_format(sndcp_tree,hf_sndcp_nsapi,
+ tvb, offset,1, nsapi,
+ "Address field NSAPI: %d", nsapi );
+ address_field_tree = proto_item_add_subtree(address_field_item, ett_sndcp_address_field);
+ proto_tree_add_boolean(address_field_tree, hf_sndcp_x, tvb,offset,1, addr_field );
+ proto_tree_add_boolean(address_field_tree, hf_sndcp_f, tvb,offset,1, addr_field );
+ proto_tree_add_boolean(address_field_tree, hf_sndcp_t, tvb,offset,1, addr_field );
+ proto_tree_add_boolean(address_field_tree, hf_sndcp_m, tvb,offset,1, addr_field );
+ proto_tree_add_uint(address_field_tree, hf_sndcp_nsapib, tvb, offset, 1, addr_field );
+ }
+ offset++;
+
+ /* get compression pointers from next byte if this is the first segment
+ */
+ if (first) {
+ comp_field = tvb_get_guint8(tvb,offset);
+ dcomp = comp_field & 0xF0;
+ pcomp = comp_field & 0x0F;
+
+ /* add subtree for the compression field
+ */
+ if (tree) {
+ if (!pcomp) {
+ if (!dcomp) {
+ compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "No compression");
+ }
+ else {
+ compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Data compression");
+ }
+ }
+ else {
+ if (!dcomp) {
+ compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Protocol compression");
+ }
+ else {
+ compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Data and Protocol compression");
+ }
+ }
+ compression_field_tree = proto_item_add_subtree(compression_field_item, ett_sndcp_compression_field);
+ proto_tree_add_uint(compression_field_tree, hf_sndcp_dcomp, tvb, offset, 1, comp_field );
+ proto_tree_add_uint(compression_field_tree, hf_sndcp_pcomp, tvb, offset, 1, comp_field );
+ }
+ offset++;
+
+ /* get N-PDU number from next byte for acknowledged mode (only for first segment)
+ */
+ if (!unack) {
+ npdu = npdu_field1 = tvb_get_guint8(tvb,offset);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "SN-DATA N-PDU %d", npdu_field1);
+ if (tree) {
+ npdu_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Acknowledged mode, N-PDU %d", npdu_field1 );
+ npdu_field_tree = proto_item_add_subtree(npdu_field_item, ett_sndcp_npdu_field);
+ proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu1, tvb, offset, 1, npdu_field1 );
+ offset++;
+ }
+ }
+ }
+
+ /* get segment and N-PDU number from next two bytes for unacknowledged mode
+ */
+ if (unack) {
+ npdu_field2 = tvb_get_ntohs(tvb, offset);
+ segment = (npdu_field2 & 0xF000) >> 12;
+ npdu = (npdu_field2 & 0x0FFF);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "SN-UNITDATA N-PDU %d (segment %d)", npdu, segment);
+ if (tree) {
+ npdu_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,2, "Unacknowledged mode, N-PDU %d (segment %d)", npdu, segment );
+ npdu_field_tree = proto_item_add_subtree(npdu_field_item, ett_sndcp_npdu_field);
+ proto_tree_add_uint(npdu_field_tree, hf_sndcp_segment, tvb, offset, 2, npdu_field2 );
+ proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu2, tvb, offset, 2, npdu_field2 );
+ }
+ offset += 2;
+ }
+
+ /* handle N-PDU data, reassemble if necessary
+ */
+ if (first && !more_frags) {
+ next_tvb = tvb_new_subset (tvb, offset, -1, -1);
+
+ if (!dcomp && !pcomp) {
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+ }
+ else {
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ }
+ else {
+ /* Try reassembling fragments
+ */
+ fragment_data *fd_npdu = NULL;
+ guint32 reassembled_in = 0;
+ gboolean save_fragmented = pinfo->fragmented;
+
+ len = tvb_length_remaining(tvb, offset);
+ pinfo->fragmented = TRUE;
+
+ if (unack)
+ fd_npdu = fragment_add_seq(tvb, offset, pinfo, npdu,
+ npdu_fragment_table, segment, len, more_frags);
+ else
+ fd_npdu = fragment_add(tvb, offset, pinfo, npdu,
+ npdu_fragment_table, offset, len, more_frags);
+
+ npdu_tvb = process_reassembled_data(tvb, offset, pinfo,
+ "Reassembled N-PDU", fd_npdu, &npdu_frag_items,
+ NULL, sndcp_tree);
+ if (fd_npdu) {
+ /* Reassembled
+ */
+ reassembled_in = fd_npdu->reassembled_in;
+ if (pinfo->fd->num == reassembled_in) {
+ /* Reassembled in this very packet:
+ * We can safely hand the tvb to the IP dissector
+ */
+ call_dissector(ip_handle, npdu_tvb, pinfo, tree);
+ }
+ else {
+ /* Not reassembled in this packet
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " (N-PDU payload reassembled in packet %u)",
+ fd_npdu->reassembled_in);
+ }
+ if (tree) {
+ proto_tree_add_text(sndcp_tree, tvb, offset, -1, "Payload");
+ }
+ }
+ } else {
+ /* Not reassembled yet, or not reassembled at all
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (unack)
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (Unreassembled fragment %u)", segment);
+ else
+ col_append_str(pinfo->cinfo, COL_INFO, " (Unreassembled fragment)");
+ }
+ if (tree) {
+ proto_tree_add_text(sndcp_tree, tvb, offset, -1, "Payload");
+ }
+ }
+ /* Now reset fragmentation information in pinfo
+ */
+ pinfo->fragmented = save_fragmented;
+ }
+}
+
+
+/* Register the protocol with Ethereal
+ this format is required because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_sndcp(void)
+{
+ /* Setup list of header fields
+ */
+ static hf_register_info hf[] = {
+ { &hf_sndcp_nsapi,
+ { "NSAPI",
+ "sndcp.nsapi",
+ FT_UINT8, BASE_DEC, VALS(nsapi_abrv), 0x0,
+ "Network Layer Service Access Point Identifier", HFILL
+ }
+ },
+ { &hf_sndcp_x,
+ { "Spare bit",
+ "sndcp.x",
+ FT_BOOLEAN,8, TFS(&x_bit), MASK_X,
+ "Spare bit (should be 0)", HFILL
+ }
+ },
+ { &hf_sndcp_f,
+ { "First segment indicator bit",
+ "sndcp.f",
+ FT_BOOLEAN,8, TFS(&f_bit), MASK_F,
+ "First segment indicator bit", HFILL
+ }
+ },
+ { &hf_sndcp_t,
+ { "Type",
+ "sndcp.t",
+ FT_BOOLEAN,8, TFS(&t_bit), MASK_T,
+ "SN-PDU Type", HFILL
+ }
+ },
+ { &hf_sndcp_m,
+ { "More bit",
+ "sndcp.m",
+ FT_BOOLEAN,8, TFS(&m_bit), MASK_M,
+ "More bit", HFILL
+ }
+ },
+ { &hf_sndcp_dcomp,
+ { "DCOMP",
+ "sndcp.dcomp",
+ FT_UINT8, BASE_DEC, VALS(compression_vals), 0xF0,
+ "Data compression coding", HFILL
+ }
+ },
+ { &hf_sndcp_pcomp,
+ { "PCOMP",
+ "sndcp.pcomp",
+ FT_UINT8, BASE_DEC, VALS(compression_vals), 0x0F,
+ "Protocol compression coding", HFILL
+ }
+ },
+ { &hf_sndcp_nsapib,
+ { "NSAPI",
+ "sndcp.nsapib",
+ FT_UINT8, BASE_DEC , VALS(nsapi_t), 0xf,
+ "Network Layer Service Access Point Identifier ",HFILL
+ }
+ },
+ { &hf_sndcp_segment,
+ { "Segment",
+ "sndcp.segment",
+ FT_UINT16, BASE_DEC, NULL, 0xF000,
+ "Segment number", HFILL
+ }
+ },
+ { &hf_sndcp_npdu1,
+ { "N-PDU",
+ "sndcp.npdu",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ "N-PDU", HFILL
+ }
+ },
+ { &hf_sndcp_npdu2,
+ { "N-PDU",
+ "sndcp.npdu",
+ FT_UINT16, BASE_DEC, NULL, 0x0FFF,
+ "N-PDU", HFILL
+ }
+ },
+
+ /* Fragment fields
+ */
+ { &hf_npdu_fragment_overlap,
+ { "Fragment overlap",
+ "npdu.fragment.overlap",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL
+ }
+ },
+ { &hf_npdu_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap",
+ "npdu.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL
+ }
+ },
+ { &hf_npdu_fragment_multiple_tails,
+ { "Multiple tail fragments found",
+ "npdu.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL
+ }
+ },
+ { &hf_npdu_fragment_too_long_fragment,
+ { "Fragment too long",
+ "npdu.fragment.toolongfragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL
+ }
+ },
+ { &hf_npdu_fragment_error,
+ { "Defragmentation error",
+ "npdu.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL
+ }
+ },
+ { &hf_npdu_reassembled_in,
+ { "Reassembled in",
+ "npdu.reassembled.in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "N-PDU fragments are reassembled in the given packet", HFILL
+ }
+ },
+ { &hf_npdu_fragment,
+ { "N-PDU Fragment",
+ "npdu.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "N-PDU Fragment", HFILL
+ }
+ },
+ { &hf_npdu_fragments,
+ { "N-PDU Fragments",
+ "npdu.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "N-PDU Fragments", HFILL
+ }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_sndcp ,
+ &ett_sndcp_address_field,
+ &ett_sndcp_compression_field,
+ &ett_sndcp_npdu_field,
+ &ett_npdu_fragment,
+ &ett_npdu_fragments,
+ };
+
+ /* Register the protocol name and description */
+ proto_sndcp = proto_register_protocol("Subnetwork Dependent Convergence Protocol",
+ "SNDCP", "sndcp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_sndcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("sndcp", dissect_sndcp, proto_sndcp);
+ register_init_routine(sndcp_defragment_init);
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_sndcp(void)
+{
+ dissector_handle_t sndcp_handle;
+
+ sndcp_handle = create_dissector_handle(dissect_sndcp, proto_sndcp);
+
+ /* Register SNDCP dissector with LLC layer for SAPI 3,5,9 and 11
+ */
+ dissector_add("llcgprs.sapi", 3, sndcp_handle);
+ dissector_add("llcgprs.sapi", 5, sndcp_handle);
+ dissector_add("llcgprs.sapi", 9, sndcp_handle);
+ dissector_add("llcgprs.sapi", 11, sndcp_handle);
+
+ /* Find IP and data handle for upper layer dissectors
+ */
+ ip_handle = find_dissector("ip");
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-snmp.c b/epan/dissectors/packet-snmp.c
new file mode 100644
index 0000000000..fc6d191df8
--- /dev/null
+++ b/epan/dissectors/packet-snmp.c
@@ -0,0 +1,2569 @@
+/* packet-snmp.c
+ * Routines for SNMP (simple network management protocol)
+ * Copyright (C) 1998 Didier Jorand
+ *
+ * See RFC 1157 for SNMPv1.
+ *
+ * See RFCs 1901, 1905, and 1906 for SNMPv2c.
+ *
+ * See RFCs 1905, 1906, 1909, and 1910 for SNMPv2u [historic].
+ *
+ * See RFCs 2570-2576 for SNMPv3
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Some stuff from:
+ *
+ * GXSNMP -- An snmp mangament application
+ * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
+ * Beholder RMON ethernet network monitor,Copyright (C) 1993 DNPAP group
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include "isprint.h"
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include <epan/conversation.h>
+#include "etypes.h"
+#include "prefs.h"
+#include "packet-ipx.h"
+#include "packet-hpext.h"
+#include "packet-frame.h"
+
+#ifdef HAVE_SOME_SNMP
+
+#ifdef HAVE_NET_SNMP
+# include <net-snmp/net-snmp-config.h>
+# include <net-snmp/mib_api.h>
+# include <net-snmp/library/default_store.h>
+# include <net-snmp/config_api.h>
+#else /* HAVE_NET_SNMP */
+# include <ucd-snmp/ucd-snmp-config.h>
+# include <ucd-snmp/asn1.h>
+# include <ucd-snmp/snmp_api.h>
+# include <ucd-snmp/snmp_impl.h>
+# include <ucd-snmp/mib.h>
+# include <ucd-snmp/default_store.h>
+# include <ucd-snmp/read_config.h>
+# include <ucd-snmp/tools.h>
+#endif /* HAVE_NET_SNMP */
+
+#ifndef NETSNMP_DS_LIBRARY_ID
+# define NETSNMP_DS_LIBRARY_ID DS_LIBRARY_ID
+# define NETSNMP_DS_LIB_NO_TOKEN_WARNINGS DS_LIB_NO_TOKEN_WARNINGS
+# define NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY DS_LIB_PRINT_SUFFIX_ONLY
+# define netsnmp_ds_set_boolean ds_set_boolean
+# define netsnmp_ds_set_int ds_set_int
+#endif
+
+#ifdef WIN32
+# include <epan/filesystem.h>
+#endif /* WIN32 */
+
+ /*
+ * Define values "sprint_realloc_value()" expects.
+ */
+# define VALTYPE_INTEGER ASN_INTEGER
+# define VALTYPE_COUNTER ASN_COUNTER
+# define VALTYPE_GAUGE ASN_GAUGE
+# define VALTYPE_TIMETICKS ASN_TIMETICKS
+# define VALTYPE_STRING ASN_OCTET_STR
+# define VALTYPE_IPADDR ASN_IPADDRESS
+# define VALTYPE_OPAQUE ASN_OPAQUE
+# define VALTYPE_NSAP ASN_NSAP
+# define VALTYPE_OBJECTID ASN_OBJECT_ID
+# define VALTYPE_BITSTR ASN_BIT_STR
+# define VALTYPE_COUNTER64 ASN_COUNTER64
+
+#endif /* HAVE_SOME_SNMP */
+
+#include "asn1.h"
+
+#include "packet-snmp.h"
+#include "format-oid.h"
+
+/* Take a pointer that may be null and return a pointer that's not null
+ by turning null pointers into pointers to the above null string,
+ and, if the argument pointer wasn't null, make sure we handle
+ non-printable characters in the string by escaping them. */
+#define SAFE_STRING(s, l) (((s) != NULL) ? format_text((s), (l)) : "")
+
+static int proto_snmp = -1;
+
+/* Default MIB modules to load */
+#define DEF_MIB_MODULES "IP-MIB:IF-MIB:TCP-MIB:UDP-MIB:SNMPv2-MIB:RFC1213-MIB:UCD-SNMP-MIB"
+
+static gchar *mib_modules = DEF_MIB_MODULES;
+static gboolean display_oid = TRUE;
+
+static gint ett_snmp = -1;
+static gint ett_parameters = -1;
+static gint ett_parameters_qos = -1;
+static gint ett_global = -1;
+static gint ett_flags = -1;
+static gint ett_secur = -1;
+
+static int hf_snmp_version = -1;
+static int hf_snmp_community = -1;
+static int hf_snmp_request_id = -1;
+static int hf_snmp_pdutype = -1;
+static int hf_snmp_agent = -1;
+static int hf_snmp_enterprise = -1;
+static int hf_snmp_error_status = -1;
+static int hf_snmp_oid = -1;
+static int hf_snmp_traptype = -1;
+static int hf_snmp_spectraptype = -1;
+static int hf_snmp_timestamp = -1;
+static int hf_snmpv3_flags = -1;
+static int hf_snmpv3_flags_auth = -1;
+static int hf_snmpv3_flags_crypt = -1;
+static int hf_snmpv3_flags_report = -1;
+
+static int proto_smux = -1;
+
+static gint ett_smux = -1;
+
+static int hf_smux_version = -1;
+static int hf_smux_pdutype = -1;
+
+/* desegmentation of SNMP-over-TCP */
+static gboolean snmp_desegment = TRUE;
+
+static dissector_handle_t snmp_handle;
+static dissector_handle_t data_handle;
+
+#define TH_AUTH 0x01
+#define TH_CRYPT 0x02
+#define TH_REPORT 0x04
+
+#define UDP_PORT_SNMP 161
+#define UDP_PORT_SNMP_TRAP 162
+#define TCP_PORT_SNMP 161
+#define TCP_PORT_SNMP_TRAP 162
+#define TCP_PORT_SMUX 199
+
+/* Protocol version numbers */
+#define SNMP_VERSION_1 0
+#define SNMP_VERSION_2c 1
+#define SNMP_VERSION_2u 2
+#define SNMP_VERSION_3 3
+
+static const value_string versions[] = {
+ { SNMP_VERSION_1, "1" },
+ { SNMP_VERSION_2c, "2C" },
+ { SNMP_VERSION_2u, "2U" },
+ { SNMP_VERSION_3, "3" },
+ { 0, NULL },
+};
+
+/* defined in net-SNMP; include/net-snmp/library/snmp.h */
+#undef SNMP_MSG_GET
+#undef SNMP_MSG_SET
+#undef SNMP_MSG_GETNEXT
+#undef SNMP_MSG_RESPONSE
+#undef SNMP_MSG_TRAP
+#undef SNMP_MSG_GETBULK
+#undef SNMP_MSG_INFORM
+#undef SNMP_MSG_TRAP2
+#undef SNMP_MSG_REPORT
+#undef SNMP_NOSUCHOBJECT
+#undef SNMP_NOSUCHINSTANCE
+#undef SNMP_ENDOFMIBVIEW
+
+/* PDU types */
+#define SNMP_MSG_GET 0
+#define SNMP_MSG_GETNEXT 1
+#define SNMP_MSG_RESPONSE 2
+#define SNMP_MSG_SET 3
+#define SNMP_MSG_TRAP 4
+
+#define SNMP_MSG_GETBULK 5
+#define SNMP_MSG_INFORM 6
+#define SNMP_MSG_TRAP2 7
+#define SNMP_MSG_REPORT 8
+
+static const value_string pdu_types[] = {
+ { SNMP_MSG_GET, "GET" },
+ { SNMP_MSG_GETNEXT, "GET-NEXT" },
+ { SNMP_MSG_SET, "SET" },
+ { SNMP_MSG_RESPONSE, "RESPONSE" },
+ { SNMP_MSG_TRAP, "TRAP-V1" },
+ { SNMP_MSG_GETBULK, "GETBULK" },
+ { SNMP_MSG_INFORM, "INFORM" },
+ { SNMP_MSG_TRAP2, "TRAP-V2" },
+ { SNMP_MSG_REPORT, "REPORT" },
+ { 0, NULL }
+};
+
+/* SMUX PDU types */
+#define SMUX_MSG_OPEN 0
+#define SMUX_MSG_CLOSE 1
+#define SMUX_MSG_RREQ 2
+#define SMUX_MSG_RRSP 3
+#define SMUX_MSG_SOUT 4
+
+static const value_string smux_types[] = {
+ { SMUX_MSG_OPEN, "Open" },
+ { SMUX_MSG_CLOSE, "Close" },
+ { SMUX_MSG_RREQ, "Registration Request" },
+ { SMUX_MSG_RRSP, "Registration Response" },
+ { SMUX_MSG_SOUT, "Commit Or Rollback" },
+ { 0, NULL }
+};
+
+/* SMUX Closing causes */
+#define SMUX_CLOSE_DOWN 0
+#define SMUX_CLOSE_VERSION 1
+#define SMUX_CLOSE_PACKET 2
+#define SMUX_CLOSE_PROTOCOL 3
+#define SMUX_CLOSE_INTERNAL 4
+#define SMUX_CLOSE_NOAUTH 5
+
+static const value_string smux_close[] = {
+ { SMUX_CLOSE_DOWN, "Going down" },
+ { SMUX_CLOSE_VERSION, "Unsupported Version" },
+ { SMUX_CLOSE_PACKET, "Packet Format Error" },
+ { SMUX_CLOSE_PROTOCOL, "Protocol Error" },
+ { SMUX_CLOSE_INTERNAL, "Internal Error" },
+ { SMUX_CLOSE_NOAUTH, "Unauthorized" },
+ { 0, NULL }
+};
+
+/* SMUX Request codes */
+#define SMUX_RREQ_DELETE 0
+#define SMUX_RREQ_READONLY 1
+#define SMUX_RREQ_READWRITE 2
+
+static const value_string smux_rreq[] = {
+ { SMUX_RREQ_DELETE, "Delete" },
+ { SMUX_RREQ_READONLY, "Read Only" },
+ { SMUX_RREQ_READWRITE, "Read Write" },
+ { 0, NULL }
+};
+
+static const value_string smux_prio[] = {
+ { -1, "Failure" },
+ { 0, NULL }
+};
+
+/* SMUX SOut codes */
+#define SMUX_SOUT_COMMIT 0
+#define SMUX_SOUT_ROLLBACK 1
+
+static const value_string smux_sout[] = {
+ { SMUX_SOUT_COMMIT, "Commit" },
+ { SMUX_SOUT_ROLLBACK, "Rollback" },
+ { 0, NULL }
+};
+
+/* Error status values */
+#ifndef SNMP_ERR_NOERROR
+#define SNMP_ERR_NOERROR 0
+#endif
+#ifndef SNMP_ERR_TOOBIG
+#define SNMP_ERR_TOOBIG 1
+#endif
+#ifndef SNMP_ERR_NOSUCHNAME
+#define SNMP_ERR_NOSUCHNAME 2
+#endif
+#ifndef SNMP_ERR_BADVALUE
+#define SNMP_ERR_BADVALUE 3
+#endif
+#ifndef SNMP_ERR_READONLY
+#define SNMP_ERR_READONLY 4
+#endif
+#ifndef SNMP_ERR_GENERR
+#define SNMP_ERR_GENERR 5
+#endif
+#ifndef SNMP_ERR_NOACCESS
+#define SNMP_ERR_NOACCESS 6
+#endif
+#ifndef SNMP_ERR_WRONGTYPE
+#define SNMP_ERR_WRONGTYPE 7
+#endif
+#ifndef SNMP_ERR_WRONGLENGTH
+#define SNMP_ERR_WRONGLENGTH 8
+#endif
+#ifndef SNMP_ERR_WRONGENCODING
+#define SNMP_ERR_WRONGENCODING 9
+#endif
+#ifndef SNMP_ERR_WRONGVALUE
+#define SNMP_ERR_WRONGVALUE 10
+#endif
+#ifndef SNMP_ERR_NOCREATION
+#define SNMP_ERR_NOCREATION 11
+#endif
+#ifndef SNMP_ERR_INCONSISTENTVALUE
+#define SNMP_ERR_INCONSISTENTVALUE 12
+#endif
+#ifndef SNMP_ERR_RESOURCEUNAVAILABLE
+#define SNMP_ERR_RESOURCEUNAVAILABLE 13
+#endif
+#ifndef SNMP_ERR_COMMITFAILED
+#define SNMP_ERR_COMMITFAILED 14
+#endif
+#ifndef SNMP_ERR_UNDOFAILED
+#define SNMP_ERR_UNDOFAILED 15
+#endif
+#ifndef SNMP_ERR_AUTHORIZATIONERROR
+#define SNMP_ERR_AUTHORIZATIONERROR 16
+#endif
+#ifndef SNMP_ERR_NOTWRITABLE
+#define SNMP_ERR_NOTWRITABLE 17
+#endif
+#ifndef SNMP_ERR_INCONSISTENTNAME
+#define SNMP_ERR_INCONSISTENTNAME 18
+#endif
+
+static const value_string error_statuses[] = {
+ { SNMP_ERR_NOERROR, "NO ERROR" },
+ { SNMP_ERR_TOOBIG, "TOOBIG" },
+ { SNMP_ERR_NOSUCHNAME, "NO SUCH NAME" },
+ { SNMP_ERR_BADVALUE, "BAD VALUE" },
+ { SNMP_ERR_READONLY, "READ ONLY" },
+ { SNMP_ERR_GENERR, "GENERIC ERROR" },
+ { SNMP_ERR_NOACCESS, "NO ACCESS" },
+ { SNMP_ERR_WRONGTYPE, "WRONG TYPE" },
+ { SNMP_ERR_WRONGLENGTH, "WRONG LENGTH" },
+ { SNMP_ERR_WRONGENCODING, "WRONG ENCODING" },
+ { SNMP_ERR_WRONGVALUE, "WRONG VALUE" },
+ { SNMP_ERR_NOCREATION, "NO CREATION" },
+ { SNMP_ERR_INCONSISTENTVALUE, "INCONSISTENT VALUE" },
+ { SNMP_ERR_RESOURCEUNAVAILABLE, "RESOURCE UNAVAILABLE" },
+ { SNMP_ERR_COMMITFAILED, "COMMIT FAILED" },
+ { SNMP_ERR_UNDOFAILED, "UNDO FAILED" },
+ { SNMP_ERR_AUTHORIZATIONERROR, "AUTHORIZATION ERROR" },
+ { SNMP_ERR_NOTWRITABLE, "NOT WRITABLE" },
+ { SNMP_ERR_INCONSISTENTNAME, "INCONSISTENT NAME" },
+ { 0, NULL }
+};
+
+/* General SNMP V1 Traps */
+
+#ifndef SNMP_TRAP_COLDSTART
+#define SNMP_TRAP_COLDSTART 0
+#endif
+#ifndef SNMP_TRAP_WARMSTART
+#define SNMP_TRAP_WARMSTART 1
+#endif
+#ifndef SNMP_TRAP_LINKDOWN
+#define SNMP_TRAP_LINKDOWN 2
+#endif
+#ifndef SNMP_TRAP_LINKUP
+#define SNMP_TRAP_LINKUP 3
+#endif
+#ifndef SNMP_TRAP_AUTHFAIL
+#define SNMP_TRAP_AUTHFAIL 4
+#endif
+#ifndef SNMP_TRAP_EGPNEIGHBORLOSS
+#define SNMP_TRAP_EGPNEIGHBORLOSS 5
+#endif
+#ifndef SNMP_TRAP_ENTERPRISESPECIFIC
+#define SNMP_TRAP_ENTERPRISESPECIFIC 6
+#endif
+
+static const value_string trap_types[] = {
+ { SNMP_TRAP_COLDSTART, "COLD START" },
+ { SNMP_TRAP_WARMSTART, "WARM START" },
+ { SNMP_TRAP_LINKDOWN, "LINK DOWN" },
+ { SNMP_TRAP_LINKUP, "LINK UP" },
+ { SNMP_TRAP_AUTHFAIL, "AUTHENTICATION FAILED" },
+ { SNMP_TRAP_EGPNEIGHBORLOSS, "EGP NEIGHBORLOSS" },
+ { SNMP_TRAP_ENTERPRISESPECIFIC, "ENTERPRISE SPECIFIC" },
+ { 0, NULL }
+};
+
+/* Security Models */
+
+#define SNMP_SEC_ANY 0
+#define SNMP_SEC_V1 1
+#define SNMP_SEC_V2C 2
+#define SNMP_SEC_USM 3
+
+static const value_string sec_models[] = {
+ { SNMP_SEC_ANY, "Any" },
+ { SNMP_SEC_V1, "V1" },
+ { SNMP_SEC_V2C, "V2C" },
+ { SNMP_SEC_USM, "USM" },
+ { 0, NULL }
+};
+
+/* SNMP Tags */
+
+#define SNMP_IPA 0 /* IP Address */
+#define SNMP_CNT 1 /* Counter (Counter32) */
+#define SNMP_GGE 2 /* Gauge (Gauge32) */
+#define SNMP_TIT 3 /* TimeTicks */
+#define SNMP_OPQ 4 /* Opaque */
+#define SNMP_NSP 5 /* NsapAddress */
+#define SNMP_C64 6 /* Counter64 */
+#define SNMP_U32 7 /* Uinteger32 */
+
+#define SERR_NSO 0
+#define SERR_NSI 1
+#define SERR_EOM 2
+
+/* SNMPv1 Types */
+
+#define SNMP_NULL 0
+#define SNMP_INTEGER 1 /* l */
+#define SNMP_OCTETSTR 2 /* c */
+#define SNMP_DISPLAYSTR 2 /* c */
+#define SNMP_OBJECTID 3 /* ul */
+#define SNMP_IPADDR 4 /* uc */
+#define SNMP_COUNTER 5 /* ul */
+#define SNMP_GAUGE 6 /* ul */
+#define SNMP_TIMETICKS 7 /* ul */
+#define SNMP_OPAQUE 8 /* c */
+
+/* additional SNMPv2 Types */
+
+#define SNMP_UINTEGER 5 /* ul */
+#define SNMP_BITSTR 9 /* uc */
+#define SNMP_NSAP 10 /* uc */
+#define SNMP_COUNTER64 11 /* ul */
+#define SNMP_NOSUCHOBJECT 12
+#define SNMP_NOSUCHINSTANCE 13
+#define SNMP_ENDOFMIBVIEW 14
+
+typedef struct _SNMP_CNV SNMP_CNV;
+
+struct _SNMP_CNV
+{
+ guint class;
+ guint tag;
+ gint syntax;
+ gchar *name;
+};
+
+static SNMP_CNV SnmpCnv [] =
+{
+ {ASN1_UNI, ASN1_NUL, SNMP_NULL, "NULL"},
+ {ASN1_UNI, ASN1_INT, SNMP_INTEGER, "INTEGER"},
+ {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR, "OCTET STRING"},
+ {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID, "OBJECTID"},
+ {ASN1_APL, SNMP_IPA, SNMP_IPADDR, "IPADDR"},
+ {ASN1_APL, SNMP_CNT, SNMP_COUNTER, "COUNTER"}, /* Counter32 */
+ {ASN1_APL, SNMP_GGE, SNMP_GAUGE, "GAUGE"}, /* Gauge32 == Unsigned32 */
+ {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS, "TIMETICKS"},
+ {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE, "OPAQUE"},
+
+/* SNMPv2 data types and errors */
+
+ {ASN1_UNI, ASN1_BTS, SNMP_BITSTR, "BITSTR"},
+ {ASN1_APL, SNMP_C64, SNMP_COUNTER64, "COUNTER64"},
+ {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT, "NOSUCHOBJECT"},
+ {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE, "NOSUCHINSTANCE"},
+ {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW, "ENDOFMIBVIEW"},
+ {0, 0, -1, NULL}
+};
+
+/*
+ * NAME: g_snmp_tag_cls2syntax
+ * SYNOPSIS: gboolean g_snmp_tag_cls2syntax
+ * (
+ * guint tag,
+ * guint cls,
+ * gushort *syntax
+ * )
+ * DESCRIPTION: Converts ASN1 tag and class to Syntax tag and name.
+ * See SnmpCnv for conversion.
+ * RETURNS: name on success, NULL on failure
+ */
+
+static gchar *
+snmp_tag_cls2syntax ( guint tag, guint cls, gushort *syntax)
+{
+ SNMP_CNV *cnv;
+
+ cnv = SnmpCnv;
+ while (cnv->syntax != -1)
+ {
+ if (cnv->tag == tag && cnv->class == cls)
+ {
+ *syntax = cnv->syntax;
+ return cnv->name;
+ }
+ cnv++;
+ }
+ return NULL;
+}
+
+static void
+dissect_snmp_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const char *field_name, int ret)
+{
+ char *errstr;
+
+ errstr = asn1_err_to_str(ret);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "ERROR: Couldn't parse %s: %s", field_name, errstr);
+ }
+ if (tree != NULL) {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "ERROR: Couldn't parse %s: %s", field_name, errstr);
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+}
+
+static void
+dissect_snmp_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const char *message)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, message);
+
+ if (tree != NULL) {
+ proto_tree_add_text(tree, tvb, offset, 0, "%s", message);
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+}
+
+gchar *
+format_oid(subid_t *oid, guint oid_length)
+{
+ char *result;
+ int result_len;
+ int len;
+ unsigned int i;
+ char *buf;
+#ifdef HAVE_SOME_SNMP
+ guchar *oid_string;
+ size_t oid_string_len;
+ size_t oid_out_len;
+#endif
+
+ result_len = oid_length * 22;
+
+#ifdef HAVE_SOME_SNMP
+ /*
+ * Get the decoded form of the OID, and add its length to the
+ * length of the result string.
+ *
+ * XXX - check for "sprint_realloc_objid()" failure.
+ */
+ oid_string_len = 256;
+ oid_string = g_malloc(oid_string_len);
+ *oid_string = '\0';
+ oid_out_len = 0;
+ sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
+ oid, oid_length);
+ result_len += strlen(oid_string) + 3;
+#endif
+
+ result = g_malloc(result_len + 1);
+ buf = result;
+ len = sprintf(buf, "%lu", (unsigned long)oid[0]);
+ buf += len;
+ for (i = 1; i < oid_length;i++) {
+ len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
+ buf += len;
+ }
+
+#ifdef HAVE_SOME_SNMP
+ /*
+ * Append the decoded form of the OID.
+ */
+ sprintf(buf, " (%s)", oid_string);
+ g_free(oid_string);
+#endif
+
+ return result;
+}
+
+/* returns the decoded (can be NULL) and non_decoded OID strings,
+ returned pointers shall be freed by the caller */
+void
+new_format_oid(subid_t *oid, guint oid_length,
+ gchar **non_decoded, gchar **decoded)
+{
+ int len;
+ unsigned int i;
+ char *buf;
+
+#ifdef HAVE_SOME_SNMP
+ guchar *oid_string;
+ size_t oid_string_len;
+ size_t oid_out_len;
+
+ /*
+ * Get the decoded form of the OID, and add its length to the
+ * length of the result string.
+ */
+
+ oid_string_len = 256;
+ oid_string = g_malloc(oid_string_len);
+ *oid_string = '\0';
+ oid_out_len = 0;
+ sprint_realloc_objid(&oid_string, &oid_string_len, &oid_out_len, 1,
+ oid, oid_length);
+ *decoded = oid_string;
+#else
+ *decoded = NULL;
+#endif
+
+ *non_decoded = g_malloc(oid_length * 22 + 1);
+ buf = *non_decoded;
+ len = sprintf(buf, "%lu", (unsigned long)oid[0]);
+ buf += len;
+ for (i = 1; i < oid_length; i++) {
+ len = sprintf(buf, ".%lu", (unsigned long)oid[i]);
+ buf += len;
+ }
+}
+
+#ifdef HAVE_SOME_SNMP
+static guchar *
+check_var_length(guint vb_length, guint required_length)
+{
+ gchar *buf;
+ static const char badlen_fmt[] = "Length is %u, should be %u";
+
+ if (vb_length != required_length) {
+ /* Enough room for the largest "Length is XXX,
+ should be XXX" message - 10 digits for each
+ XXX. */
+ buf = g_malloc(sizeof badlen_fmt + 10 + 10);
+ sprintf(buf, badlen_fmt, vb_length, required_length);
+ return buf;
+ }
+ return NULL; /* length is OK */
+}
+
+static gchar *
+format_var(struct variable_list *variable, subid_t *variable_oid,
+ guint variable_oid_length, gushort vb_type, guint val_len)
+{
+ guchar *buf;
+ size_t buf_len;
+ size_t out_len;
+
+ switch (vb_type) {
+
+ case SNMP_IPADDR:
+ /* Length has to be 4 bytes. */
+ buf = check_var_length(val_len, 4);
+ if (buf != NULL)
+ return buf; /* it's not 4 bytes */
+ break;
+
+#ifdef REMOVED
+ /* not all counters are encoded as a full 64bit integer */
+ case SNMP_COUNTER64:
+ /* Length has to be 8 bytes. */
+ buf = check_var_length(val_len, 8);
+ if (buf != NULL)
+ return buf; /* it's not 8 bytes */
+ break;
+#endif
+ default:
+ break;
+ }
+
+ variable->next_variable = NULL;
+ variable->name = variable_oid;
+ variable->name_length = variable_oid_length;
+ switch (vb_type) {
+
+ case SNMP_INTEGER:
+ variable->type = VALTYPE_INTEGER;
+ break;
+
+ case SNMP_COUNTER:
+ variable->type = VALTYPE_COUNTER;
+ break;
+
+ case SNMP_GAUGE:
+ variable->type = VALTYPE_GAUGE;
+ break;
+
+ case SNMP_TIMETICKS:
+ variable->type = VALTYPE_TIMETICKS;
+ break;
+
+ case SNMP_OCTETSTR:
+ variable->type = VALTYPE_STRING;
+ break;
+
+ case SNMP_IPADDR:
+ variable->type = VALTYPE_IPADDR;
+ break;
+
+ case SNMP_OPAQUE:
+ variable->type = VALTYPE_OPAQUE;
+ break;
+
+ case SNMP_NSAP:
+ variable->type = VALTYPE_NSAP;
+ break;
+
+ case SNMP_OBJECTID:
+ variable->type = VALTYPE_OBJECTID;
+ break;
+
+ case SNMP_BITSTR:
+ variable->type = VALTYPE_BITSTR;
+ break;
+
+ case SNMP_COUNTER64:
+ variable->type = VALTYPE_COUNTER64;
+ break;
+ }
+ variable->val_len = val_len;
+
+ /*
+ * XXX - check for "sprint_realloc_objid()" failure.
+ */
+ buf_len = 256;
+ buf = g_malloc(buf_len);
+ *buf = '\0';
+ out_len = 0;
+ sprint_realloc_value(&buf, &buf_len, &out_len, 1, variable_oid,
+ variable_oid_length, variable);
+ return buf;
+}
+#endif
+
+static int
+snmp_variable_decode(proto_tree *snmp_tree,
+ subid_t *variable_oid
+#ifndef HAVE_SOME_SNMP
+ _U_
+#endif
+ ,
+ guint variable_oid_length
+#ifndef HAVE_SOME_SNMP
+ _U_
+#endif
+ ,
+ ASN1_SCK *asn1, int offset, guint *lengthp)
+{
+ int start;
+ guint length;
+ gboolean def;
+ guint vb_length;
+ gushort vb_type;
+ gchar *vb_type_name;
+ int ret;
+ guint cls, con, tag;
+
+ gint32 vb_integer_value;
+ guint32 vb_uinteger_value;
+
+ guint8 *vb_octet_string;
+
+ subid_t *vb_oid;
+ guint vb_oid_length;
+
+ gchar *vb_display_string;
+
+#ifdef HAVE_SOME_SNMP
+ struct variable_list variable;
+ long value;
+#else /* HAVE_SOME_SNMP */
+ unsigned int i;
+ gchar *buf;
+ int len;
+#endif /* HAVE_SOME_SNMP */
+
+ /* parse the type of the object */
+ start = asn1->offset;
+ ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &vb_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ if (!def)
+ return ASN1_ERR_LENGTH_NOT_DEFINITE;
+
+ /* Convert the class, constructed flag, and tag to a type. */
+ vb_type_name = snmp_tag_cls2syntax(tag, cls, &vb_type);
+ if (vb_type_name == NULL) {
+ /*
+ * Unsupported type.
+ * Dissect the value as an opaque string of octets.
+ */
+ vb_type_name = "unsupported type";
+ vb_type = SNMP_OPAQUE;
+ }
+
+ /* parse the value */
+ switch (vb_type) {
+
+ case SNMP_INTEGER:
+ ret = asn1_int32_value_decode(asn1, vb_length,
+ &vb_integer_value);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1->offset - start;
+ if (snmp_tree) {
+#ifdef HAVE_SOME_SNMP
+ value = vb_integer_value;
+ variable.val.integer = &value;
+ vb_display_string = format_var(&variable,
+ variable_oid, variable_oid_length, vb_type,
+ vb_length);
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset,
+ length,
+ "Value: %s", vb_display_string);
+ g_free(vb_display_string);
+#else /* HAVE_SOME_SNMP */
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset,
+ length,
+ "Value: %s: %d (%#x)", vb_type_name,
+ vb_integer_value, vb_integer_value);
+#endif /* HAVE_SOME_SNMP */
+ }
+ break;
+
+ case SNMP_COUNTER:
+ case SNMP_GAUGE:
+ case SNMP_TIMETICKS:
+ ret = asn1_uint32_value_decode(asn1, vb_length,
+ &vb_uinteger_value);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1->offset - start;
+ if (snmp_tree) {
+#ifdef HAVE_SOME_SNMP
+ value = vb_uinteger_value;
+ variable.val.integer = &value;
+ vb_display_string = format_var(&variable,
+ variable_oid, variable_oid_length, vb_type,
+ vb_length);
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset,
+ length,
+ "Value: %s", vb_display_string);
+ g_free(vb_display_string);
+#else /* HAVE_SOME_SNMP */
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset,
+ length,
+ "Value: %s: %u (%#x)", vb_type_name,
+ vb_uinteger_value, vb_uinteger_value);
+#endif /* HAVE_SOME_SNMP */
+ }
+ break;
+
+ case SNMP_OCTETSTR:
+ case SNMP_IPADDR:
+ case SNMP_OPAQUE:
+ case SNMP_NSAP:
+ case SNMP_BITSTR:
+ case SNMP_COUNTER64:
+ ret = asn1_string_value_decode (asn1, vb_length,
+ &vb_octet_string);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1->offset - start;
+ if (snmp_tree) {
+#ifdef HAVE_SOME_SNMP
+ variable.val.string = vb_octet_string;
+ vb_display_string = format_var(&variable,
+ variable_oid, variable_oid_length, vb_type,
+ vb_length);
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset,
+ length,
+ "Value: %s", vb_display_string);
+ g_free(vb_display_string);
+#else /* HAVE_SOME_SNMP */
+ /*
+ * If some characters are not printable, display
+ * the string as bytes.
+ */
+ for (i = 0; i < vb_length; i++) {
+ if (!(isprint(vb_octet_string[i])
+ || isspace(vb_octet_string[i])))
+ break;
+ }
+ if (i < vb_length) {
+ /*
+ * We stopped, due to a non-printable
+ * character, before we got to the end
+ * of the string.
+ */
+ vb_display_string = g_malloc(4*vb_length);
+ buf = &vb_display_string[0];
+ len = sprintf(buf, "%03u", vb_octet_string[0]);
+ buf += len;
+ for (i = 1; i < vb_length; i++) {
+ len = sprintf(buf, ".%03u",
+ vb_octet_string[i]);
+ buf += len;
+ }
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset,
+ length,
+ "Value: %s: %s", vb_type_name,
+ vb_display_string);
+ g_free(vb_display_string);
+ } else {
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset,
+ length,
+ "Value: %s: %s", vb_type_name,
+ SAFE_STRING(vb_octet_string, vb_length));
+ }
+#endif /* HAVE_SOME_SNMP */
+ }
+ g_free(vb_octet_string);
+ break;
+
+ case SNMP_NULL:
+ ret = asn1_null_decode (asn1, vb_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1->offset - start;
+ if (snmp_tree) {
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
+ "Value: %s", vb_type_name);
+ }
+ break;
+
+ case SNMP_OBJECTID:
+ ret = asn1_oid_value_decode (asn1, vb_length, &vb_oid,
+ &vb_oid_length);
+ if (ret != ASN1_ERR_NOERROR)
+ return ret;
+ length = asn1->offset - start;
+ if (snmp_tree) {
+#ifdef HAVE_SOME_SNMP
+ variable.val.objid = vb_oid;
+ vb_display_string = format_var(&variable,
+ variable_oid, variable_oid_length, vb_type,
+ vb_oid_length * sizeof (subid_t));
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset,
+ length,
+ "Value: %s", vb_display_string);
+ g_free(vb_display_string);
+#else /* HAVE_SOME_SNMP */
+ vb_display_string = format_oid(vb_oid, vb_oid_length);
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset,
+ length,
+ "Value: %s: %s", vb_type_name, vb_display_string);
+ g_free(vb_display_string);
+#endif /* HAVE_SOME_SNMP */
+ }
+ g_free(vb_oid);
+ break;
+
+ case SNMP_NOSUCHOBJECT:
+ length = asn1->offset - start;
+ if (snmp_tree) {
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
+ "Value: %s: no such object", vb_type_name);
+ }
+ break;
+
+ case SNMP_NOSUCHINSTANCE:
+ length = asn1->offset - start;
+ if (snmp_tree) {
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
+ "Value: %s: no such instance", vb_type_name);
+ }
+ break;
+
+ case SNMP_ENDOFMIBVIEW:
+ length = asn1->offset - start;
+ if (snmp_tree) {
+ proto_tree_add_text(snmp_tree, asn1->tvb, offset, length,
+ "Value: %s: end of mib view", vb_type_name);
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ return ASN1_ERR_WRONG_TYPE;
+ }
+ *lengthp = length;
+ return ASN1_ERR_NOERROR;
+}
+
+static void
+dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, ASN1_SCK asn1, guint pdu_type, int start)
+{
+ gboolean def;
+ guint length;
+ guint sequence_length;
+
+ guint32 request_id;
+
+ guint32 error_status;
+
+ guint32 error_index;
+
+ char *pdu_type_string;
+
+ subid_t *enterprise;
+ guint enterprise_length;
+
+ guint32 agent_ipaddr;
+
+ guint8 *agent_address;
+ guint agent_address_length;
+
+ guint32 trap_type;
+
+ guint32 specific_type;
+
+ guint timestamp;
+ guint timestamp_length;
+
+ gchar *oid_string;
+
+ guint variable_bindings_length;
+
+ int vb_index;
+ guint variable_length;
+ subid_t *variable_oid;
+ guint variable_oid_length;
+
+ int ret;
+ guint cls, con, tag;
+
+ pdu_type_string = val_to_str(pdu_type, pdu_types,
+ "Unknown PDU type %#x");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
+ length = asn1.offset - start;
+ if (tree) {
+ proto_tree_add_uint(tree, hf_snmp_pdutype, tvb, offset, length,
+ pdu_type);
+ }
+ offset += length;
+
+ /* get the fields in the PDU preceeding the variable-bindings sequence */
+ switch (pdu_type) {
+
+ case SNMP_MSG_GET:
+ case SNMP_MSG_GETNEXT:
+ case SNMP_MSG_RESPONSE:
+ case SNMP_MSG_SET:
+ case SNMP_MSG_GETBULK:
+ case SNMP_MSG_INFORM:
+ case SNMP_MSG_TRAP2:
+ case SNMP_MSG_REPORT:
+ /* request id */
+ ret = asn1_uint32_decode (&asn1, &request_id, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "request ID", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_uint(tree, hf_snmp_request_id,
+ tvb, offset, length, request_id);
+ }
+ offset += length;
+
+ /* error status, or getbulk non-repeaters */
+ ret = asn1_uint32_decode (&asn1, &error_status, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ (pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
+ : "error status",
+ ret);
+ return;
+ }
+ if (tree) {
+ if (pdu_type == SNMP_MSG_GETBULK) {
+ proto_tree_add_text(tree, tvb, offset,
+ length, "Non-repeaters: %u", error_status);
+ } else {
+ proto_tree_add_uint(tree,
+ hf_snmp_error_status,
+ tvb, offset,
+ length, error_status);
+ }
+ }
+ offset += length;
+
+ /* error index, or getbulk max-repetitions */
+ ret = asn1_uint32_decode (&asn1, &error_index, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ (pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
+ : "error index",
+ ret);
+ return;
+ }
+ if (tree) {
+ if (pdu_type == SNMP_MSG_GETBULK) {
+ proto_tree_add_text(tree, tvb, offset,
+ length, "Max repetitions: %u", error_index);
+ } else {
+ proto_tree_add_text(tree, tvb, offset,
+ length, "Error Index: %u", error_index);
+ }
+ }
+ offset += length;
+ break;
+
+ case SNMP_MSG_TRAP:
+ /* enterprise */
+ ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
+ &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "enterprise OID", ret);
+ return;
+ }
+ if (tree) {
+ oid_string = format_oid(enterprise, enterprise_length);
+ proto_tree_add_string(tree, hf_snmp_enterprise, tvb,
+ offset, length, oid_string);
+ g_free(oid_string);
+ }
+ g_free(enterprise);
+ offset += length;
+
+ /* agent address */
+ start = asn1.offset;
+ ret = asn1_header_decode (&asn1, &cls, &con, &tag,
+ &def, &agent_address_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "agent address", ret);
+ return;
+ }
+ if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
+ (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS))) {
+ /* GXSNMP 0.0.15 says the latter is "needed for
+ Banyan" */
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "agent_address", ASN1_ERR_WRONG_TYPE);
+ return;
+ }
+ if (agent_address_length != 4) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
+ return;
+ }
+ ret = asn1_string_value_decode (&asn1,
+ agent_address_length, &agent_address);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "agent address", ret);
+ return;
+ }
+ length = asn1.offset - start;
+ if (tree) {
+ if (agent_address_length != 4) {
+ proto_tree_add_text(tree, tvb, offset,
+ length,
+ "Agent address: <length is %u, not 4>",
+ agent_address_length);
+ } else {
+ memcpy((guint8 *)&agent_ipaddr, agent_address,
+ agent_address_length);
+ proto_tree_add_ipv4(tree, hf_snmp_agent, tvb,
+ offset, length, agent_ipaddr);
+ }
+ }
+ g_free(agent_address);
+ offset += length;
+
+ /* generic trap type */
+ ret = asn1_uint32_decode (&asn1, &trap_type, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "generic trap type", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_uint(tree, hf_snmp_traptype, tvb,
+ offset, length, trap_type);
+ }
+ offset += length;
+
+ /* specific trap type */
+ ret = asn1_uint32_decode (&asn1, &specific_type, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "specific trap type", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_uint(tree, hf_snmp_spectraptype, tvb,
+ offset, length, specific_type);
+ }
+ offset += length;
+
+ /* timestamp */
+ start = asn1.offset;
+ ret = asn1_header_decode (&asn1, &cls, &con, &tag,
+ &def, &timestamp_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "timestamp", ret);
+ return;
+ }
+ if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
+ (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT))) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "timestamp", ASN1_ERR_WRONG_TYPE);
+ return;
+ }
+ ret = asn1_uint32_value_decode(&asn1, timestamp_length,
+ &timestamp);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "timestamp", ret);
+ return;
+ }
+ length = asn1.offset - start;
+ if (tree) {
+ proto_tree_add_uint(tree, hf_snmp_timestamp, tvb,
+ offset, length, timestamp);
+ }
+ offset += length;
+ break;
+ }
+
+ /* variable bindings */
+ /* get header for variable-bindings sequence */
+ ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "variable bindings header", ret);
+ return;
+ }
+ offset += length;
+
+ /* loop on variable bindings */
+ vb_index = 0;
+ while (variable_bindings_length > 0) {
+ vb_index++;
+ sequence_length = 0;
+
+ /* parse type */
+ ret = asn1_sequence_decode(&asn1, &variable_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "variable binding header", ret);
+ return;
+ }
+ sequence_length += length;
+
+ /* parse object identifier */
+ ret = asn1_oid_decode (&asn1, &variable_oid,
+ &variable_oid_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "variable binding OID", ret);
+ return;
+ }
+ sequence_length += length;
+
+ if (display_oid || tree) {
+
+ gchar *decoded_oid;
+ gchar *non_decoded_oid;
+
+ new_format_oid(variable_oid, variable_oid_length,
+ &non_decoded_oid, &decoded_oid);
+
+ if (display_oid && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ " %s",
+ (decoded_oid == NULL) ? non_decoded_oid :
+ decoded_oid);
+ }
+
+ if (tree) {
+ if (decoded_oid) {
+ proto_tree_add_string_format(tree, hf_snmp_oid,
+ tvb, offset,
+ sequence_length,
+ decoded_oid,
+ "Object identifier %d: %s (%s)",
+ vb_index,
+ non_decoded_oid,
+ decoded_oid);
+ /* add also the non decoded oid string */
+ proto_tree_add_string_hidden(tree, hf_snmp_oid,
+ tvb, offset,
+ sequence_length,
+ non_decoded_oid);
+ } else {
+ proto_tree_add_string_format(tree, hf_snmp_oid,
+ tvb, offset,
+ sequence_length,
+ non_decoded_oid,
+ "Object identifier %d: %s",
+ vb_index,
+ non_decoded_oid);
+ }
+ }
+
+ if (decoded_oid) g_free(decoded_oid);
+ g_free(non_decoded_oid);
+
+ }
+
+ offset += sequence_length;
+ variable_bindings_length -= sequence_length;
+
+ /*
+ * Register a cleanup function in case one of our
+ * tvbuff accesses throws an exception. We need
+ * to clean up variable_oid.
+ */
+ CLEANUP_PUSH(g_free, variable_oid);
+
+ /* Parse the variable's value */
+ ret = snmp_variable_decode(tree, variable_oid,
+ variable_oid_length, &asn1, offset, &length);
+
+ /*
+ * We're done with variable_oid, so we can call the cleanup
+ * handler to free* it, and then pop the cleanup handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, tree,
+ "variable", ret);
+ return;
+ }
+ offset += length;
+ variable_bindings_length -= length;
+ }
+}
+
+static const value_string qos_vals[] = {
+ { 0x0, "No authentication or privacy" },
+ { 0x1, "Authentication, no privacy" },
+ { 0x2, "Authentication and privacy" },
+ { 0x3, "Authentication and privacy" },
+ { 0, NULL },
+};
+
+static void
+dissect_snmp2u_parameters(proto_tree *tree, tvbuff_t *tvb, int offset, int length,
+ guchar *parameters, int parameters_length)
+{
+ proto_item *item;
+ proto_tree *parameters_tree;
+ proto_tree *qos_tree;
+ guint8 model;
+ guint8 qos;
+ guint8 len;
+
+ item = proto_tree_add_text(tree, tvb, offset, length,
+ "Parameters");
+ parameters_tree = proto_item_add_subtree(item, ett_parameters);
+ offset += length - parameters_length;
+
+ if (parameters_length < 1)
+ return;
+ model = *parameters;
+ proto_tree_add_text(parameters_tree, tvb, offset, 1,
+ "model: %u", model);
+ offset += 1;
+ parameters += 1;
+ parameters_length -= 1;
+ if (model != 1) {
+ /* Unknown model. */
+ proto_tree_add_text(parameters_tree, tvb, offset, parameters_length, "parameters: %s",
+ bytes_to_str(parameters, parameters_length));
+ return;
+ }
+
+ if (parameters_length < 1)
+ return;
+ qos = *parameters;
+ item = proto_tree_add_text(parameters_tree, tvb, offset, 1,
+ "qoS: 0x%x", qos);
+ qos_tree = proto_item_add_subtree(item, ett_parameters_qos);
+ proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
+ decode_boolean_bitfield(qos, 0x04,
+ 8, "Generation of report PDU allowed",
+ "Generation of report PDU not allowed"));
+ proto_tree_add_text(qos_tree, tvb, offset, 1, "%s",
+ decode_enumerated_bitfield(qos, 0x03,
+ 8, qos_vals, "%s"));
+ offset += 1;
+ parameters += 1;
+ parameters_length -= 1;
+
+ if (parameters_length < 12)
+ return;
+ proto_tree_add_text(parameters_tree, tvb, offset, 12,
+ "agentID: %s", bytes_to_str(parameters, 12));
+ offset += 12;
+ parameters += 12;
+ parameters_length -= 12;
+
+ if (parameters_length < 4)
+ return;
+ proto_tree_add_text(parameters_tree, tvb, offset, 4,
+ "agentBoots: %u", pntohl(parameters));
+ offset += 4;
+ parameters += 4;
+ parameters_length -= 4;
+
+ if (parameters_length < 4)
+ return;
+ proto_tree_add_text(parameters_tree, tvb, offset, 4,
+ "agentTime: %u", pntohl(parameters));
+ offset += 4;
+ parameters += 4;
+ parameters_length -= 4;
+
+ if (parameters_length < 2)
+ return;
+ proto_tree_add_text(parameters_tree, tvb, offset, 2,
+ "maxSize: %u", pntohs(parameters));
+ offset += 2;
+ parameters += 2;
+ parameters_length -= 2;
+
+ if (parameters_length < 1)
+ return;
+ len = *parameters;
+ proto_tree_add_text(parameters_tree, tvb, offset, 1,
+ "userLen: %u", len);
+ offset += 1;
+ parameters += 1;
+ parameters_length -= 1;
+
+ if (parameters_length < len)
+ return;
+ proto_tree_add_text(parameters_tree, tvb, offset, len,
+ "userName: %.*s", len, parameters);
+ offset += len;
+ parameters += len;
+ parameters_length -= len;
+
+ if (parameters_length < 1)
+ return;
+ len = *parameters;
+ proto_tree_add_text(parameters_tree, tvb, offset, 1,
+ "authLen: %u", len);
+ offset += 1;
+ parameters += 1;
+ parameters_length -= 1;
+
+ if (parameters_length < len)
+ return;
+ proto_tree_add_text(parameters_tree, tvb, offset, len,
+ "authDigest: %s", bytes_to_str(parameters, len));
+ offset += len;
+ parameters += len;
+ parameters_length -= len;
+
+ if (parameters_length < 1)
+ return;
+ proto_tree_add_text(parameters_tree, tvb, offset, parameters_length,
+ "contextSelector: %s", bytes_to_str(parameters, parameters_length));
+}
+
+guint
+dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, int proto, gint ett, gboolean is_tcp)
+{
+ guint length_remaining;
+ ASN1_SCK asn1;
+ int start;
+ gboolean def;
+ gboolean encrypted;
+ guint length;
+ guint message_length;
+ guint global_length;
+
+ guint32 version;
+ guint32 msgid;
+ guint32 msgmax;
+ guint32 msgsec;
+ guint32 engineboots;
+ guint32 enginetime;
+
+ guchar *msgflags;
+ gchar *commustr;
+ guchar *community;
+ guchar *secparm;
+ guchar *cengineid;
+ guchar *cname;
+ guchar *cryptpdu;
+ guchar *aengineid;
+ guchar *username;
+ guchar *authpar;
+ guchar *privpar;
+ guint msgflags_length;
+ guint community_length;
+ guint secparm_length;
+ guint cengineid_length;
+ guint cname_length;
+ guint cryptpdu_length;
+ guint aengineid_length;
+ guint username_length;
+ guint authpar_length;
+ guint privpar_length;
+
+ guint pdu_type;
+ guint pdu_length;
+
+ proto_tree *snmp_tree = NULL;
+ proto_tree *global_tree = NULL;
+ proto_tree *flags_tree = NULL;
+ proto_tree *secur_tree = NULL;
+ proto_item *item = NULL;
+ int ret;
+ guint cls, con, tag;
+
+ /*
+ * This will throw an exception if we don't have any data left.
+ * That's what we want. (See "tcp_dissect_pdus()", which is
+ * similar, but doesn't have to deal with ASN.1.
+ * XXX - can we make "tcp_dissect_pdus()" provide enough
+ * information to the "get_pdu_len" routine so that we could
+ * have that routine deal with ASN.1, and just use
+ * "tcp_dissect_pdus()"?)
+ */
+ length_remaining = tvb_ensure_length_remaining(tvb, offset);
+
+ /* NOTE: we have to parse the message piece by piece, since the
+ * capture length may be less than the message length: a 'global'
+ * parsing is likely to fail.
+ */
+
+ /*
+ * If this is SNMP-over-TCP, we might have to do reassembly
+ * in order to read the "Sequence Of" header.
+ */
+ if (is_tcp && snmp_desegment && pinfo->can_desegment) {
+ /*
+ * This is TCP, and we should, and can, do reassembly.
+ *
+ * Is the "Sequence Of" header split across segment
+ * boundaries? We requre at least 6 bytes for the
+ * header, which allows for a 4-byte length (ASN.1
+ * BER).
+ */
+ if (length_remaining < 6) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 6 - length_remaining;
+
+ /*
+ * Return 0, which means "I didn't dissect anything
+ * because I don't have enough data - we need
+ * to desegment".
+ */
+ return 0;
+ }
+ }
+
+ /*
+ * OK, try to read the "Sequence Of" header; this gets the total
+ * length of the SNMP message.
+ */
+ asn1_open(&asn1, tvb, offset);
+ ret = asn1_sequence_decode(&asn1, &message_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ if (tree) {
+ item = proto_tree_add_item(tree, proto, tvb, offset,
+ -1, FALSE);
+ snmp_tree = proto_item_add_subtree(item, ett);
+ }
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "message header", ret);
+
+ /*
+ * Return the length remaining in the tvbuff, so
+ * if this is SNMP-over-TCP, our caller thinks there's
+ * nothing left to dissect.
+ */
+ return length_remaining;
+ }
+
+ /*
+ * Add the length of the "Sequence Of" header to the message
+ * length.
+ */
+ message_length += length;
+ if (message_length < length) {
+ /*
+ * The message length was probably so large that the
+ * total length overflowed.
+ *
+ * Report this as an error.
+ */
+ show_reported_bounds_error(tvb, pinfo, tree);
+
+ /*
+ * Return the length remaining in the tvbuff, so
+ * if this is SNMP-over-TCP, our caller thinks there's
+ * nothing left to dissect.
+ */
+ return length_remaining;
+ }
+
+ /*
+ * If this is SNMP-over-TCP, we might have to do reassembly
+ * to get all of this message.
+ */
+ if (is_tcp && snmp_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the message split across segment boundaries?
+ */
+ if (length_remaining < message_length) {
+ /*
+ * Yes. Tell the TCP dissector where the data
+ * for this message starts in the data it handed
+ * us, and how many more bytes we need, and
+ * return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len =
+ message_length - length_remaining;
+
+ /*
+ * Return 0, which means "I didn't dissect anything
+ * because I don't have enough data - we need
+ * to desegment".
+ */
+ return 0;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ proto_get_protocol_short_name(find_protocol_by_id(proto)));
+ }
+
+ if (tree) {
+ item = proto_tree_add_item(tree, proto, tvb, offset,
+ message_length, FALSE);
+ snmp_tree = proto_item_add_subtree(item, ett);
+ }
+ offset += length;
+
+ ret = asn1_uint32_decode (&asn1, &version, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "version number", ret);
+ return message_length;
+ }
+ if (snmp_tree) {
+ proto_tree_add_uint(snmp_tree, hf_snmp_version, tvb, offset,
+ length, version);
+ }
+ offset += length;
+
+
+ switch (version) {
+ case SNMP_VERSION_1:
+ case SNMP_VERSION_2c:
+ ret = asn1_octet_string_decode (&asn1, &community,
+ &community_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "community", ret);
+ return message_length;
+ }
+ if (tree) {
+ commustr = g_malloc(community_length+1);
+ memcpy(commustr, community, community_length);
+ commustr[community_length] = '\0';
+
+ proto_tree_add_string(snmp_tree, hf_snmp_community,
+ tvb, offset, length, commustr);
+ g_free(commustr);
+ }
+ g_free(community);
+ offset += length;
+ break;
+ case SNMP_VERSION_2u:
+ ret = asn1_octet_string_decode (&asn1, &community,
+ &community_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "community (2u)", ret);
+ return message_length;
+ }
+ if (tree) {
+ dissect_snmp2u_parameters(snmp_tree, tvb, offset, length,
+ community, community_length);
+ }
+ g_free(community);
+ offset += length;
+ break;
+ case SNMP_VERSION_3:
+ ret = asn1_sequence_decode(&asn1, &global_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "message global header", ret);
+ return message_length;
+ }
+ if (snmp_tree) {
+ item = proto_tree_add_text(snmp_tree, tvb, offset,
+ global_length + length, "Message Global Header");
+ global_tree = proto_item_add_subtree(item, ett_global);
+ proto_tree_add_text(global_tree, tvb, offset,
+ length,
+ "Message Global Header Length: %d", global_length);
+ }
+ offset += length;
+ ret = asn1_uint32_decode (&asn1, &msgid, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "message id", ret);
+ return message_length;
+ }
+ if (global_tree) {
+ proto_tree_add_text(global_tree, tvb, offset,
+ length, "Message ID: %d", msgid);
+ }
+ offset += length;
+ ret = asn1_uint32_decode (&asn1, &msgmax, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "message max size", ret);
+ return message_length;
+ }
+ if (global_tree) {
+ proto_tree_add_text(global_tree, tvb, offset,
+ length, "Message Max Size: %d", msgmax);
+ }
+ offset += length;
+ ret = asn1_octet_string_decode (&asn1, &msgflags,
+ &msgflags_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "message flags", ret);
+ return message_length;
+ }
+ if (msgflags_length != 1) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "message flags wrong length", ret);
+ g_free(msgflags);
+ return message_length;
+ }
+ if (global_tree) {
+ item = proto_tree_add_uint_format(global_tree,
+ hf_snmpv3_flags, tvb, offset, length,
+ msgflags[0], "Flags: 0x%02x", msgflags[0]);
+ flags_tree = proto_item_add_subtree(item, ett_flags);
+ proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_report,
+ tvb, offset, length, msgflags[0]);
+ proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_crypt,
+ tvb, offset, length, msgflags[0]);
+ proto_tree_add_boolean(flags_tree, hf_snmpv3_flags_auth,
+ tvb, offset, length, msgflags[0]);
+ }
+ encrypted = msgflags[0] & TH_CRYPT;
+ g_free(msgflags);
+ offset += length;
+ ret = asn1_uint32_decode (&asn1, &msgsec, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "message security model", ret);
+ return message_length;
+ }
+ if (global_tree) {
+ proto_tree_add_text(global_tree, tvb, offset,
+ length, "Message Security Model: %s",
+ val_to_str(msgsec, sec_models,
+ "Unknown model %#x"));
+ }
+ offset += length;
+ switch(msgsec) {
+ case SNMP_SEC_USM:
+ start = asn1.offset;
+ ret = asn1_header_decode (&asn1, &cls, &con, &tag,
+ &def, &secparm_length);
+ length = asn1.offset - start;
+ if (cls != ASN1_UNI && con != ASN1_PRI &&
+ tag != ASN1_OTS) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "Message Security Parameters",
+ ASN1_ERR_WRONG_TYPE);
+ return message_length;
+ }
+ if (snmp_tree) {
+ item = proto_tree_add_text(snmp_tree, tvb,
+ offset, secparm_length + length,
+ "Message Security Parameters");
+ secur_tree = proto_item_add_subtree(item,
+ ett_secur);
+ proto_tree_add_text(secur_tree, tvb, offset,
+ length,
+ "Message Security Parameters Length: %d",
+ secparm_length);
+ }
+ offset += length;
+ ret = asn1_sequence_decode(&asn1, &secparm_length,
+ &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "USM sequence header", ret);
+ return message_length;
+ }
+ offset += length;
+ ret = asn1_octet_string_decode (&asn1, &aengineid,
+ &aengineid_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "authoritative engine id", ret);
+ return message_length;
+ }
+ if (secur_tree) {
+ proto_tree_add_text(secur_tree, tvb, offset,
+ length, "Authoritative Engine ID: %s",
+ bytes_to_str(aengineid, aengineid_length));
+ }
+ g_free(aengineid);
+ offset += length;
+ ret = asn1_uint32_decode (&asn1, &engineboots, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "engine boots", ret);
+ return message_length;
+ }
+ if (secur_tree) {
+ proto_tree_add_text(secur_tree, tvb,
+ offset, length, "Engine Boots: %d",
+ engineboots);
+ }
+ offset += length;
+ ret = asn1_uint32_decode (&asn1, &enginetime, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "engine time", ret);
+ return message_length;
+ }
+ if (secur_tree) {
+ proto_tree_add_text(secur_tree, tvb,
+ offset, length, "Engine Time: %d",
+ enginetime);
+ }
+ offset += length;
+ ret = asn1_octet_string_decode (&asn1, &username,
+ &username_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "user name", ret);
+ return message_length;
+ }
+ if (secur_tree) {
+ proto_tree_add_text(secur_tree, tvb, offset,
+ length, "User Name: %s",
+ SAFE_STRING(username, username_length));
+ }
+ g_free(username);
+ offset += length;
+ ret = asn1_octet_string_decode (&asn1, &authpar,
+ &authpar_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "authentication parameter", ret);
+ return message_length;
+ }
+ if (secur_tree) {
+ proto_tree_add_text(secur_tree, tvb, offset,
+ length, "Authentication Parameter: %s",
+ bytes_to_str(authpar, authpar_length));
+ }
+ g_free(authpar);
+ offset += length;
+ ret = asn1_octet_string_decode (&asn1, &privpar,
+ &privpar_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "privacy parameter", ret);
+ return message_length;
+ }
+ if (secur_tree) {
+ proto_tree_add_text(secur_tree, tvb, offset,
+ length, "Privacy Parameter: %s",
+ bytes_to_str(privpar, privpar_length));
+ }
+ g_free(privpar);
+ offset += length;
+ break;
+ default:
+ ret = asn1_octet_string_decode (&asn1,
+ &secparm, &secparm_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "Message Security Parameters",
+ ret);
+ return message_length;
+ }
+ if (snmp_tree) {
+ proto_tree_add_text(snmp_tree, tvb, offset,
+ length,
+ "Message Security Parameters Data"
+ " (%d bytes)", secparm_length);
+ }
+ g_free(secparm);
+ offset += length;
+ break;
+ }
+ /* PDU starts here */
+ if (encrypted) {
+ ret = asn1_octet_string_decode (&asn1, &cryptpdu,
+ &cryptpdu_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo,
+ snmp_tree, "encrypted PDU header", ret);
+ return message_length;
+ }
+ proto_tree_add_text(snmp_tree, tvb, offset, length,
+ "Encrypted PDU (%d bytes)", length);
+ g_free(cryptpdu);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Encrypted PDU");
+ return message_length;
+ }
+ ret = asn1_sequence_decode(&asn1, &global_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "PDU header", ret);
+ return message_length;
+ }
+ offset += length;
+ ret = asn1_octet_string_decode (&asn1, &cengineid,
+ &cengineid_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "context engine id", ret);
+ return message_length;
+ }
+ if (snmp_tree) {
+ proto_tree_add_text(snmp_tree, tvb, offset, length,
+ "Context Engine ID: %s",
+ bytes_to_str(cengineid, cengineid_length));
+ }
+ g_free(cengineid);
+ offset += length;
+ ret = asn1_octet_string_decode (&asn1, &cname,
+ &cname_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "context name", ret);
+ return message_length;
+ }
+ if (snmp_tree) {
+ proto_tree_add_text(snmp_tree, tvb, offset, length,
+ "Context Name: %s",
+ SAFE_STRING(cname, cname_length));
+ }
+ g_free(cname);
+ offset += length;
+ break;
+ default:
+ dissect_snmp_error(tvb, offset, pinfo, snmp_tree,
+ "PDU for unknown version of SNMP");
+ return message_length;
+ }
+
+ start = asn1.offset;
+ ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
+ &pdu_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "PDU type", ret);
+ return message_length;
+ }
+ if (cls != ASN1_CTX || con != ASN1_CON) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, snmp_tree,
+ "PDU type", ASN1_ERR_WRONG_TYPE);
+ return message_length;
+ }
+ dissect_common_pdu(tvb, offset, pinfo, snmp_tree, asn1, pdu_type, start);
+ return message_length;
+}
+
+static void
+dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, int proto, gint ett)
+{
+ ASN1_SCK asn1;
+ int start;
+ gboolean def;
+ guint length;
+
+ guint pdu_type;
+ char *pdu_type_string;
+ guint pdu_length;
+
+ guint32 version;
+ guint32 cause;
+ guint32 priority;
+ guint32 operation;
+ guint32 commit;
+
+ guchar *password;
+ guint password_length;
+
+ guchar *application;
+ guint application_length;
+
+ subid_t *regid;
+ guint regid_length;
+
+ gchar *oid_string;
+
+ proto_tree *smux_tree = NULL;
+ proto_item *item = NULL;
+ int ret;
+ guint cls, con;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMUX");
+
+ if (tree) {
+ item = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
+ smux_tree = proto_item_add_subtree(item, ett);
+ }
+
+ /* NOTE: we have to parse the message piece by piece, since the
+ * capture length may be less than the message length: a 'global'
+ * parsing is likely to fail.
+ */
+ /* parse the SNMP header */
+ asn1_open(&asn1, tvb, offset);
+ start = asn1.offset;
+ ret = asn1_header_decode (&asn1, &cls, &con, &pdu_type, &def,
+ &pdu_length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "PDU type", ret);
+ return;
+ }
+
+ /* Dissect SMUX here */
+ if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_OPEN) {
+ pdu_type_string = val_to_str(pdu_type, smux_types,
+ "Unknown PDU type %#x");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
+ length = asn1.offset - start;
+ if (tree) {
+ proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
+ offset, length, pdu_type);
+ }
+ offset += length;
+ ret = asn1_uint32_decode (&asn1, &version, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "version", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_uint(smux_tree, hf_smux_version, tvb,
+ offset, length, version);
+ }
+ offset += length;
+
+ ret = asn1_oid_decode (&asn1, &regid, &regid_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "registration OID", ret);
+ return;
+ }
+ if (tree) {
+ oid_string = format_oid(regid, regid_length);
+ proto_tree_add_text(smux_tree, tvb, offset, length,
+ "Registration: %s", oid_string);
+ g_free(oid_string);
+ }
+ g_free(regid);
+ offset += length;
+
+ ret = asn1_octet_string_decode (&asn1, &application,
+ &application_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "application", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(smux_tree, tvb, offset, length,
+ "Application: %s",
+ SAFE_STRING(application, application_length));
+ }
+ g_free(application);
+ offset += length;
+
+ ret = asn1_octet_string_decode (&asn1, &password,
+ &password_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "password", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(smux_tree, tvb, offset, length,
+ "Password: %s",
+ SAFE_STRING(password, password_length));
+ }
+ g_free(password);
+ offset += length;
+ return;
+ }
+ if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_CLOSE) {
+ pdu_type_string = val_to_str(pdu_type, smux_types,
+ "Unknown PDU type %#x");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
+ length = asn1.offset - start;
+ if (tree) {
+ proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
+ offset, length, pdu_type);
+ }
+ offset += length;
+ ret = asn1_uint32_value_decode (&asn1, pdu_length, &cause);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "cause", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(smux_tree, tvb, offset,
+ pdu_length, "Cause: %s",
+ val_to_str(cause, smux_close,
+ "Unknown cause %#x"));
+ }
+ offset += pdu_length;
+ return;
+ }
+ if (cls == ASN1_APL && con == ASN1_CON && pdu_type == SMUX_MSG_RREQ) {
+ pdu_type_string = val_to_str(pdu_type, smux_types,
+ "Unknown PDU type %#x");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
+ length = asn1.offset - start;
+ if (tree) {
+ proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
+ offset, length, pdu_type);
+ }
+ offset += length;
+ ret = asn1_oid_decode (&asn1, &regid, &regid_length, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "registration subtree", ret);
+ return;
+ }
+ if (tree) {
+ oid_string = format_oid(regid, regid_length);
+ proto_tree_add_text(smux_tree, tvb, offset, length,
+ "Registration: %s", oid_string);
+ g_free(oid_string);
+ }
+ g_free(regid);
+ offset += length;
+
+ ret = asn1_uint32_decode (&asn1, &priority, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "priority", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(smux_tree, tvb, offset, length,
+ "Priority: %d", priority);
+ }
+ offset += length;
+
+ ret = asn1_uint32_decode (&asn1, &operation, &length);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "operation", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(smux_tree, tvb, offset, length,
+ "Operation: %s",
+ val_to_str(operation, smux_rreq,
+ "Unknown operation %#x"));
+ }
+ offset += length;
+ return;
+ }
+ if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_RRSP) {
+ pdu_type_string = val_to_str(pdu_type, smux_types,
+ "Unknown PDU type %#x");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
+ length = asn1.offset - start;
+ if (tree) {
+ proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
+ offset, length, pdu_type);
+ }
+ offset += length;
+ ret = asn1_uint32_value_decode (&asn1, pdu_length, &priority);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "priority", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(smux_tree, tvb, offset,
+ pdu_length, "%s",
+ val_to_str(priority, smux_prio,
+ "Priority: %#x"));
+ }
+ offset += pdu_length;
+ return;
+ }
+ if (cls == ASN1_APL && con == ASN1_PRI && pdu_type == SMUX_MSG_SOUT) {
+ pdu_type_string = val_to_str(pdu_type, smux_types,
+ "Unknown PDU type %#x");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
+ length = asn1.offset - start;
+ if (tree) {
+ proto_tree_add_uint(smux_tree, hf_smux_pdutype, tvb,
+ offset, length, pdu_type);
+ }
+ offset += length;
+ ret = asn1_uint32_value_decode (&asn1, pdu_length, &commit);
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "commit", ret);
+ return;
+ }
+ if (tree) {
+ proto_tree_add_text(smux_tree, tvb, offset,
+ pdu_length, "%s",
+ val_to_str(commit, smux_sout,
+ "Unknown SOUT Value: %#x"));
+ }
+ offset += pdu_length;
+ return;
+ }
+ if (cls != ASN1_CTX || con != ASN1_CON) {
+ dissect_snmp_parse_error(tvb, offset, pinfo, smux_tree,
+ "PDU type", ASN1_ERR_WRONG_TYPE);
+ return;
+ }
+ dissect_common_pdu(tvb, offset, pinfo, smux_tree, asn1, pdu_type, start);
+}
+
+static void
+dissect_snmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ conversation_t *conversation;
+
+ /*
+ * The first SNMP packet goes to the SNMP port; the second one
+ * may come from some *other* port, but goes back to the same
+ * IP address and port as the ones from which the first packet
+ * came; all subsequent packets presumably go between those two
+ * IP addresses and ports.
+ *
+ * If this packet went to the SNMP port, we check to see if
+ * there's already a conversation with one address/port pair
+ * matching the source IP address and port of this packet,
+ * the other address matching the destination IP address of this
+ * packet, and any destination port.
+ *
+ * If not, we create one, with its address 1/port 1 pair being
+ * the source address/port of this packet, its address 2 being
+ * the destination address of this packet, and its port 2 being
+ * wildcarded, and give it the SNMP dissector as a dissector.
+ */
+ if (pinfo->destport == UDP_PORT_SNMP) {
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
+ pinfo->srcport, 0, NO_PORT_B);
+ if (conversation == NULL) {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
+ pinfo->srcport, 0, NO_PORT2);
+ conversation_set_dissector(conversation, snmp_handle);
+ }
+ }
+
+ dissect_snmp_pdu(tvb, 0, pinfo, tree, proto_snmp, ett_snmp, FALSE);
+}
+
+static void
+dissect_snmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint message_len;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ message_len = dissect_snmp_pdu(tvb, 0, pinfo, tree,
+ proto_snmp, ett_snmp, TRUE);
+ if (message_len == 0) {
+ /*
+ * We don't have all the data for that message,
+ * so we need to do desegmentation;
+ * "dissect_snmp_pdu()" has set that up.
+ */
+ break;
+ }
+ offset += message_len;
+ }
+}
+
+static void
+dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_smux_pdu(tvb, 0, pinfo, tree, proto_smux, ett_smux);
+}
+
+static void
+process_prefs(void)
+{
+#ifdef HAVE_SOME_SNMP
+ gchar *tmp_mib_modules;
+ static gboolean mibs_loaded = FALSE;
+
+ if (mibs_loaded) {
+ /*
+ * Unload the MIBs, as we'll be reloading them based on
+ * the current preference setting.
+ */
+ shutdown_mib(); /* unload MIBs */
+ }
+
+ /*
+ * Cannot check if MIBS is already set, as it could be set by Ethereal.
+ *
+ * If we have a list of modules to load, put that list in MIBS,
+ * otherwise clear MIBS.
+ */
+ if (mib_modules != NULL) {
+ tmp_mib_modules = g_strconcat("MIBS=", mib_modules, NULL);
+
+#ifdef WIN32
+ _putenv(tmp_mib_modules);
+#else
+ putenv(tmp_mib_modules);
+#endif /*WIN32*/
+ } else {
+#ifdef WIN32
+ _putenv("MIBS");
+#else
+ putenv("MIBS");
+#endif /* WIN32 */
+ }
+
+ /*
+ * Load the MIBs.
+ */
+ register_mib_handlers();
+ read_premib_configs();
+ init_mib();
+ read_configs();
+ mibs_loaded = TRUE;
+#endif /* HAVE_SOME_SNMP */
+}
+
+void
+proto_register_snmp(void)
+{
+#if defined(WIN32) && defined(HAVE_SOME_SNMP)
+ char *mib_path;
+#define MIB_PATH_APPEND "snmp\\mibs"
+#endif
+ gchar *tmp_mib_modules;
+
+ static hf_register_info hf[] = {
+ { &hf_snmp_version,
+ { "Version", "snmp.version", FT_UINT8, BASE_DEC, VALS(versions),
+ 0x0, "", HFILL }},
+ { &hf_snmp_community,
+ { "Community", "snmp.community", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+ { &hf_snmp_request_id,
+ { "Request Id", "snmp.id", FT_UINT32, BASE_HEX, NULL,
+ 0x0, "Id for this transaction", HFILL }},
+ { &hf_snmp_pdutype,
+ { "PDU type", "snmp.pdutype", FT_UINT8, BASE_DEC, VALS(pdu_types),
+ 0x0, "", HFILL }},
+ { &hf_snmp_agent,
+ { "Agent address", "snmp.agent", FT_IPv4, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+ { &hf_snmp_enterprise,
+ { "Enterprise", "snmp.enterprise", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+ { &hf_snmp_error_status,
+ { "Error Status", "snmp.error", FT_UINT8, BASE_DEC, VALS(error_statuses),
+ 0x0, "", HFILL }},
+ { &hf_snmp_oid,
+ { "Object identifier", "snmp.oid", FT_STRING, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+ { &hf_snmp_traptype,
+ { "Trap type", "snmp.traptype", FT_UINT8, BASE_DEC, VALS(trap_types),
+ 0x0, "", HFILL }},
+ { &hf_snmp_spectraptype,
+ { "Specific trap type", "snmp.spectraptype", FT_UINT32, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+ { &hf_snmp_timestamp,
+ { "Timestamp", "snmp.timestamp", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+ { &hf_snmpv3_flags,
+ { "SNMPv3 Flags", "snmpv3.flags", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL }},
+ { &hf_snmpv3_flags_auth,
+ { "Authenticated", "snmpv3.flags.auth", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), TH_AUTH, "", HFILL }},
+ { &hf_snmpv3_flags_crypt,
+ { "Encrypted", "snmpv3.flags.crypt", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), TH_CRYPT, "", HFILL }},
+ { &hf_snmpv3_flags_report,
+ { "Reportable", "snmpv3.flags.report", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), TH_REPORT, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_snmp,
+ &ett_parameters,
+ &ett_parameters_qos,
+ &ett_global,
+ &ett_flags,
+ &ett_secur,
+ };
+ module_t *snmp_module;
+
+#ifdef HAVE_SOME_SNMP
+
+#ifdef WIN32
+ /* Set MIBDIRS so that the SNMP library can find its mibs. */
+ /* XXX - Should we set MIBS or MIBFILES as well? */
+
+ mib_path = g_malloc (strlen(get_datafile_dir()) + strlen(MIB_PATH_APPEND) + 20);
+ sprintf (mib_path, "MIBDIRS=%s\\%s", get_datafile_dir(), MIB_PATH_APPEND);
+ /* Amazingly enough, Windows does not provide setenv(). */
+ if (getenv("MIBDIRS") == NULL)
+ _putenv(mib_path);
+ g_free(mib_path);
+
+#endif /* WIN32 */
+
+ /*
+ * Suppress warnings about unknown tokens - we aren't initializing
+ * UCD SNMP in its entirety, we're just initializing the
+ * MIB-handling part because that's all we're using, which
+ * means that entries in the configuration file for other
+ * pars of the library will not be handled, and we don't want
+ * the config file reading code to whine about that.
+ */
+ netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
+ NETSNMP_DS_LIB_NO_TOKEN_WARNINGS, TRUE);
+ netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
+ NETSNMP_DS_LIB_PRINT_SUFFIX_ONLY, 2);
+#endif /* HAVE_SOME_SNMP */
+ proto_snmp = proto_register_protocol("Simple Network Management Protocol",
+ "SNMP", "snmp");
+ proto_register_field_array(proto_snmp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ snmp_handle = create_dissector_handle(dissect_snmp, proto_snmp);
+
+ /* Register configuration preferences */
+ snmp_module = prefs_register_protocol(proto_snmp, process_prefs);
+ prefs_register_bool_preference(snmp_module, "display_oid",
+ "Show SNMP OID in info column",
+ "Whether the SNMP OID should be shown in the info column",
+ &display_oid);
+
+ /*
+ * Set the default value of "mib_modules".
+ *
+ * If the MIBS environment variable is set, make its value
+ * the value of "mib_modules", otherwise, set "mib_modules"
+ * to DEF_MIB_MODULES.
+ */
+ tmp_mib_modules = getenv("MIBS");
+ if (tmp_mib_modules != NULL)
+ mib_modules = tmp_mib_modules;
+ prefs_register_string_preference(snmp_module, "mib_modules",
+ "MIB modules to load",
+ "List of MIB modules to load (the list is set to environment variable MIBS if the variable is not already set)",
+ &mib_modules);
+ prefs_register_bool_preference(snmp_module, "desegment",
+ "Desegment all SNMP-over-TCP messages\nspanning multiple TCP segments",
+ "Whether the SNMP dissector should desegment all messages "
+ "spanning multiple TCP segments",
+ &snmp_desegment);
+}
+
+void
+proto_reg_handoff_snmp(void)
+{
+ dissector_handle_t snmp_tcp_handle;
+
+ dissector_add("udp.port", UDP_PORT_SNMP, snmp_handle);
+ dissector_add("udp.port", UDP_PORT_SNMP_TRAP, snmp_handle);
+ dissector_add("ethertype", ETHERTYPE_SNMP, snmp_handle);
+ dissector_add("ipx.socket", IPX_SOCKET_SNMP_AGENT, snmp_handle);
+ dissector_add("ipx.socket", IPX_SOCKET_SNMP_SINK, snmp_handle);
+ dissector_add("hpext.dxsap", HPEXT_SNMP, snmp_handle);
+
+ snmp_tcp_handle = create_dissector_handle(dissect_snmp_tcp, proto_snmp);
+ dissector_add("tcp.port", TCP_PORT_SNMP, snmp_tcp_handle);
+ dissector_add("tcp.port", TCP_PORT_SNMP_TRAP, snmp_tcp_handle);
+
+ data_handle = find_dissector("data");
+
+ /*
+ * Process preference settings.
+ *
+ * We can't do this in the register routine, as preferences aren't
+ * read until all dissector register routines have been called (so
+ * that all dissector preferences have been registered).
+ */
+ process_prefs();
+}
+
+void
+proto_register_smux(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_smux_version,
+ { "Version", "smux.version", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+ { &hf_smux_pdutype,
+ { "PDU type", "smux.pdutype", FT_UINT8, BASE_DEC, VALS(smux_types),
+ 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_smux,
+ };
+
+ proto_smux = proto_register_protocol("SNMP Multiplex Protocol",
+ "SMUX", "smux");
+ proto_register_field_array(proto_smux, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_smux(void)
+{
+ dissector_handle_t smux_handle;
+
+ smux_handle = create_dissector_handle(dissect_smux, proto_smux);
+ dissector_add("tcp.port", TCP_PORT_SMUX, smux_handle);
+}
diff --git a/epan/dissectors/packet-snmp.h b/epan/dissectors/packet-snmp.h
new file mode 100644
index 0000000000..3f4f3feed5
--- /dev/null
+++ b/epan/dissectors/packet-snmp.h
@@ -0,0 +1,36 @@
+/* packet-snmp.h
+ * Exported routines for SNMP (simple network management protocol)
+ * D.Jorand (c) 1998
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Didier Jorand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_SNMP_H__
+#define __PACKET_SNMP_H__
+
+/*
+ * Guts of the SNMP dissector - exported for use by protocols such as
+ * ILMI.
+ */
+extern guint dissect_snmp_pdu(tvbuff_t *, int, packet_info *, proto_tree *tree,
+ int, gint, gboolean);
+
+#endif
diff --git a/epan/dissectors/packet-socks.c b/epan/dissectors/packet-socks.c
new file mode 100644
index 0000000000..502eb68a2b
--- /dev/null
+++ b/epan/dissectors/packet-socks.c
@@ -0,0 +1,1225 @@
+/* packet-socks.c
+ * Routines for socks versions 4 &5 packet dissection
+ * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * The Version 4 decode is based on SOCKS4.protocol and SOCKS4A.protocol.
+ * The Version 5 decoder is based upon rfc-1928
+ * The Version 5 User/Password authentication is based on rfc-1929.
+ *
+ * See
+ *
+ * http://www.socks.permeo.com/TechnicalResources/ProtocolDocuments.asp
+ *
+ * for these and other documents. See
+ *
+ * http://www.socks.nec.com/protocol/socks4a.protocol
+ *
+ * for information on SOCKS version 4a.
+ *
+ * Revisions:
+ *
+ * 2003-09-18 JCFoster Fixed problem with socks tunnel in socks tunnel
+ * causing heap overflow because of an infinite loop
+ * where the socks dissect was call over and over.
+ *
+ * Also remove some old code marked with __JUNK__
+ *
+ * 2001-01-08 JCFoster Fixed problem with NULL pointer for hash data.
+ * Now test and exit if hash_info is null.
+ */
+
+/* Possible enhancements -
+ *
+ * Add GSS-API authentication per rfc-1961
+ * Add CHAP authentication
+ * Decode FLAG bits per
+ * http://archive.socks.permeo.com/draft/draft-ietf-aft-socks-pro-v5-04.txt
+ * In call_next_dissector, could load the destination address into
+ * pinfo->src or pinfo->dst structure before calling next dissector.
+ * remove display_string or at least make it use protocol identifiers
+ * socks_hash_entry_t needs to handle V5 address type and domain names
+*/
+
+
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include <epan/conversation.h>
+
+#include "packet-tcp.h"
+#include "packet-udp.h"
+#include <epan/strutil.h>
+
+
+#define compare_packet(X) (X == (pinfo->fd->num))
+#define get_packet_ptr (pinfo->fd->num)
+#define row_pointer_type guint32
+
+#define TCP_PORT_SOCKS 1080
+
+
+/**************** Socks commands ******************/
+
+#define CONNECT_COMMAND 1
+#define BIND_COMMAND 2
+#define UDP_ASSOCIATE_COMMAND 3
+#define PING_COMMAND 0x80
+#define TRACERT_COMMAND 0x81
+
+
+/********** V5 Authentication methods *************/
+
+#define NO_AUTHENTICATION 0
+#define GSS_API_AUTHENTICATION 1
+#define USER_NAME_AUTHENTICATION 2
+#define CHAP_AUTHENTICATION 3
+#define AUTHENTICATION_FAILED 0xff
+
+/* 2003-09-18 JCFoster Fixed problem with socks tunnel in socks tunnel */
+
+static int in_socks_dissector_flag = 0; /* set to 1 to avoid recursive overflow */
+
+/*********** Header field identifiers *************/
+
+static int proto_socks = -1;
+
+static int ett_socks = -1;
+static int ett_socks_auth = -1;
+static int ett_socks_name = -1;
+
+static int hf_socks_ver = -1;
+static int hf_socks_ip_dst = -1;
+static int hf_socks_ip6_dst = -1;
+static int hf_user_name = -1;
+static int hf_v4a_dns_name = -1;
+static int hf_socks_dstport = -1;
+static int hf_socks_cmd = -1;
+static int hf_socks_results = -1;
+static int hf_socks_results_4 = -1;
+static int hf_socks_results_5 = -1;
+
+
+/************* Dissector handles ***********/
+
+static dissector_handle_t socks_handle;
+static dissector_handle_t socks_udp_handle;
+
+/************* State Machine names ***********/
+
+enum SockState {
+ None = 0,
+ Connecting,
+ V4UserNameWait,
+ V4NameWait,
+ V5Command,
+ V5Reply,
+ V5BindReply,
+ UserNameAuth,
+ UserNameAuthReply,
+ GssApiAuth,
+ AuthReply,
+ Done
+};
+
+
+
+typedef struct {
+ int state;
+ int version;
+ int command;
+ int grant;
+ guint32 port;
+ guint32 udp_port;
+ guint32 udp_remote_port;
+
+ int connect_offset;
+ row_pointer_type v4_name_row;
+ row_pointer_type v4_user_name_row;
+ row_pointer_type connect_row;
+ row_pointer_type cmd_reply_row;
+ row_pointer_type bind_reply_row;
+ row_pointer_type command_row;
+ row_pointer_type auth_method_row;
+ row_pointer_type user_name_auth_row;
+ row_pointer_type auth_version;
+ guint32 start_done_row;
+
+ guint32 dst_addr; /* this needs to handle IPv6 */
+}socks_hash_entry_t;
+
+
+
+
+static char *address_type_table[] = {
+ "Unknown",
+ "IPv4",
+ "Unknown",
+ "Domain Name",
+ "IPv6",
+ "Unknown"
+};
+
+
+/* String table for the V4 reply status messages */
+
+static const value_string reply_table_v4[] = {
+ {90, "Granted"},
+ {91, "Rejected or Failed"},
+ {92, "Rejected because SOCKS server cannot connect to identd on the client"},
+ {93, "Rejected because the client program and identd report different user-ids"},
+ {0, NULL}
+};
+
+/* String table for the V5 reply status messages */
+
+static const value_string reply_table_v5[] = {
+ {0, "Succeeded"},
+ {1, "General SOCKS server failure"},
+ {2, "Connection not allowed by ruleset"},
+ {3, "Network unreachable"},
+ {4, "Host unreachable"},
+ {5, "Connection refused"},
+ {6, "TTL expired"},
+ {7, "Command not supported"},
+ {8, "Address type not supported"},
+ {0, NULL},
+};
+
+static const value_string cmd_strings[] = {
+ {0, "Unknow"},
+ {1, "Connect"},
+ {2, "Bind"},
+ {3, "UdpAssociate"},
+ {0x80, "Ping"},
+ {0x81, "Traceroute"},
+ {0, NULL}
+};
+
+#define socks_hash_init_count 20
+#define socks_hash_val_length (sizeof(socks_hash_entry_t))
+
+static GMemChunk *socks_vals = NULL;
+
+
+/************************* Support routines ***************************/
+
+
+static int display_string(tvbuff_t *tvb, int offset,
+ proto_tree *tree, char *label){
+
+/* display a string with a length, characters encoding */
+/* they are displayed under a tree with the name in Label variable */
+/* return the length of the string and the length byte */
+
+
+ proto_tree *name_tree;
+ proto_item *ti;
+
+ char temp[ 256];
+ int length = tvb_get_guint8(tvb, offset);
+
+ tvb_memcpy(tvb, (guint8 *)temp, offset+1, length);
+ temp[ length ] = 0;
+
+ ti = proto_tree_add_text(tree, tvb, offset, length + 1,
+ "%s: %s" , label, temp);
+
+
+ name_tree = proto_item_add_subtree(ti, ett_socks_name);
+
+ proto_tree_add_text( name_tree, tvb, offset, 1, "Length: %u", length);
+
+ ++offset;
+
+ proto_tree_add_text( name_tree, tvb, offset, length, "String: %s", temp);
+
+ return length + 1;
+}
+
+
+
+static char *get_auth_method_name( guint Number){
+
+/* return the name of the authenication method */
+
+ if ( Number == 0) return "No authentication";
+ if ( Number == 1) return "GSSAPI";
+ if ( Number == 2) return "Username/Password";
+ if ( Number == 3) return "Chap";
+ if (( Number >= 4) && ( Number <= 0x7f))return "IANA assigned";
+ if (( Number >= 0x80) && ( Number <= 0xfe)) return "private method";
+ if ( Number == 0xff) return "no acceptable method";
+
+ /* shouldn't reach here */
+
+ return "Bad method number (not 0-0xff)";
+}
+
+
+static char *get_command_name( guint Number){
+
+/* return the name of the command as a string */
+
+ if ( Number == 0) return "Unknow";
+ if ( Number == 1) return "Connect";
+ if ( Number == 2) return "Bind";
+ if ( Number == 3) return "UdpAssociate";
+ if ( Number == 0x80) return "Ping";
+ if ( Number == 0x81) return "Traceroute";
+ return "Unknown";
+}
+
+
+static int display_address(tvbuff_t *tvb, int offset, proto_tree *tree) {
+
+/* decode and display the v5 address, return offset of next byte */
+
+ int a_type = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "Address Type: %d (%s)", a_type,
+ address_type_table[ MIN( (guint) a_type,
+ array_length( address_type_table)-1) ]);
+
+ ++offset;
+
+ if ( a_type == 1){ /* IPv4 address */
+ proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ }
+ else if ( a_type == 3){ /* domain name address */
+
+ offset += display_string(tvb, offset, tree,
+ "Remote name");
+ }
+ else if ( a_type == 4){ /* IPv6 address */
+ proto_tree_add_item( tree, hf_socks_ip6_dst, tvb, offset,
+ 16, FALSE);
+ offset += 16;
+ }
+
+ return offset;
+}
+
+
+static int get_address_v5(tvbuff_t *tvb, int offset,
+ socks_hash_entry_t *hash_info) {
+
+/* decode the v5 address and return offset of next byte */
+/*XXX this needs to handle IPV6 and domain name addresses */
+
+
+ int a_type = tvb_get_guint8(tvb, offset++);
+
+ if ( a_type == 1){ /* IPv4 address */
+
+ if ( hash_info)
+ tvb_memcpy(tvb, (guint8 *)&hash_info->dst_addr,
+ offset, 4);
+ offset += 4;
+ }
+
+ else if ( a_type == 4) /* IPv6 address */
+ offset += 16;
+
+ else if ( a_type == 3) /* domain name address */
+ offset += tvb_get_guint8(tvb, offset) + 1;
+ return offset;
+}
+
+
+/********************* V5 UDP Associate handlers ***********************/
+
+static void
+socks_udp_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+
+/* Conversation dissector called from UDP dissector. Decode and display */
+/* the socks header, the pass the rest of the data to the udp port */
+/* decode routine to handle the payload. */
+
+ int offset = 0;
+ guint32 *ptr;
+ socks_hash_entry_t *hash_info;
+ conversation_t *conversation;
+ proto_tree *socks_tree;
+ proto_item *ti;
+
+ conversation = find_conversation( &pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ g_assert( conversation); /* should always find a conversation */
+
+ hash_info = conversation_get_proto_data(conversation, proto_socks);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Socks");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Version: 5, UDP Associated packet");
+
+ if ( tree) {
+ ti = proto_tree_add_protocol_format( tree, proto_socks, tvb,
+ offset, -1, "Socks" );
+
+ socks_tree = proto_item_add_subtree(ti, ett_socks);
+
+ proto_tree_add_text( socks_tree, tvb, offset, 2, "Reserved");
+ offset += 2;
+
+ proto_tree_add_text( socks_tree, tvb, offset, 1, "Fragment Number: %u", tvb_get_guint8(tvb, offset));
+ ++offset;
+
+
+ offset = display_address( tvb, offset, socks_tree);
+ hash_info->udp_remote_port = tvb_get_ntohs(tvb, offset);
+
+ proto_tree_add_uint( socks_tree, hf_socks_dstport, tvb,
+ offset, 2, hash_info->udp_remote_port);
+
+ offset += 2;
+ }
+ else { /* no tree, skip past the socks header */
+ offset += 3;
+ offset = get_address_v5( tvb, offset, 0) + 2;
+ }
+
+
+/* set pi src/dst port and call the udp sub-dissector lookup */
+
+ if ( pinfo->srcport == hash_info->port)
+ ptr = &pinfo->destport;
+ else
+ ptr = &pinfo->srcport;
+
+ *ptr = hash_info->udp_remote_port;
+
+ decode_udp_ports( tvb, offset, pinfo, tree, pinfo->srcport, pinfo->destport, -1);
+
+ *ptr = hash_info->udp_port;
+
+}
+
+
+static void
+new_udp_conversation( socks_hash_entry_t *hash_info, packet_info *pinfo){
+
+ conversation_t *conversation = conversation_new( &pinfo->src, &pinfo->dst, PT_UDP,
+ hash_info->udp_port, hash_info->port, 0);
+
+ g_assert( conversation);
+
+ conversation_add_proto_data(conversation, proto_socks, hash_info);
+ conversation_set_dissector(conversation, socks_udp_handle);
+}
+
+
+
+
+/**************** Protocol Tree Display routines ******************/
+
+static void
+display_socks_v4(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, socks_hash_entry_t *hash_info) {
+
+
+/* Display the protocol tree for the V4 version. This routine uses the */
+/* stored conversation information to decide what to do with the row. */
+/* Per packet information would have been better to do this, but we */
+/* didn't have that when I wrote this. And I didn't expect this to get */
+/* so messy. */
+
+
+ guint command;
+ unsigned char ipaddr[4];
+ guint username_len, domainname_len;
+
+ /* Display command from client */
+ if (compare_packet( hash_info->connect_row)){
+
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "Version: %u", hash_info->version);
+ ++offset;
+ command = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "Command: %u (%s)", command,
+ get_command_name( command));
+ ++offset;
+
+ /* Do remote port */
+ proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ /* Do destination address */
+ tvb_memcpy(tvb, ipaddr, offset, 4);
+ proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset,
+ 4, FALSE);
+
+ offset += 4;
+
+/*XXX check this, needs to do length checking */
+/* Should perhaps do TCP reassembly as well */
+ if ( tvb_offset_exists(tvb, offset)) {
+ /* display user name */
+ username_len = tvb_strsize(tvb, offset);
+ proto_tree_add_item( tree, hf_user_name, tvb, offset,
+ username_len, FALSE);
+ offset += username_len;
+ if ( ipaddr[0] == 0 && ipaddr[1] == 0 &&
+ ipaddr[2] == 0 && ipaddr[3] != 0) {
+ /* 0.0.0.x , where x!=0 means v4a support */
+ domainname_len = tvb_strsize(tvb, offset);
+ proto_tree_add_item( tree, hf_v4a_dns_name,
+ tvb, offset, domainname_len,
+ FALSE);
+ }
+ }
+
+ }
+ /*Display command response from server*/
+
+ else if ( compare_packet( hash_info->cmd_reply_row)){
+
+ proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1,
+ FALSE);
+ ++offset;
+ /* Do results code */
+ proto_tree_add_item( tree, hf_socks_results_4, tvb, offset, 1, FALSE);
+ proto_tree_add_item_hidden(tree, hf_socks_results, tvb, offset, 1, FALSE);
+
+ ++offset;
+
+ /* Do remote port */
+ proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ /* Do remote address */
+ proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset, 4,
+ FALSE);
+ }
+
+ else if ( compare_packet( hash_info->v4_user_name_row)){
+
+/*XXX check this, needs to do length checking */
+/* Should perhaps do TCP reassembly as well */
+ if ( tvb_offset_exists(tvb, offset)) {
+ proto_tree_add_text( tree, tvb, offset,
+ tvb_strsize(tvb, offset),
+ "User Name: %s", tvb_get_ptr(tvb, offset, -1));
+ }
+ }
+}
+
+
+static void
+display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, socks_hash_entry_t *hash_info) {
+
+/* Display the protocol tree for the version. This routine uses the */
+/* stored conversation information to decide what to do with the row. */
+/* Per packet information would have been better to do this, but we */
+/* didn't have that when I wrote this. And I didn't expect this to get */
+/* so messy. */
+
+ unsigned int i, command;
+ guint temp;
+ char *AuthMethodStr;
+ guint8 auth_status;
+
+ proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, FALSE);
+ ++offset;
+
+ if (compare_packet( hash_info->connect_row)){
+
+ proto_tree *AuthTree;
+ proto_item *ti;
+
+ temp = tvb_get_guint8(tvb, offset); /* Get Auth method count */
+ /* build auth tree */
+ ti = proto_tree_add_text( tree, tvb, offset, -1,
+ "Client Authentication Methods");
+
+ AuthTree = proto_item_add_subtree(ti, ett_socks_auth);
+
+ proto_tree_add_text( AuthTree, tvb, offset, 1,
+ "Count: %u", temp);
+ ++offset;
+
+ for( i = 0; i < temp; ++i) {
+
+ AuthMethodStr = get_auth_method_name(
+ tvb_get_guint8( tvb, offset));
+ proto_tree_add_text( AuthTree, tvb, offset, 1,
+ "Method[%u]: %u (%s)", i,
+ tvb_get_guint8( tvb, offset), AuthMethodStr);
+ ++offset;
+ }
+ proto_item_set_end( ti, tvb, offset);
+ return;
+ } /* Get accepted auth method */
+ else if (compare_packet( hash_info->auth_method_row)) {
+
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "Accepted Auth Method: 0x%0x (%s)", tvb_get_guint8( tvb, offset),
+ get_auth_method_name( tvb_get_guint8( tvb, offset)));
+
+ return;
+ } /* handle user/password auth */
+ else if (compare_packet( hash_info->user_name_auth_row)) {
+
+ /* process user name */
+ offset += display_string( tvb, offset, tree,
+ "User name");
+ /* process password */
+ offset += display_string( tvb, offset, tree,
+ "Password");
+ }
+ /* command to the server */
+ /* command response from server */
+ else if (compare_packet( hash_info->auth_version)) {
+ auth_status = tvb_get_guint8(tvb, offset);
+ if(auth_status != 0)
+ proto_tree_add_text( tree, tvb, offset, 1, "Status: %u (failure)", auth_status);
+ else
+ proto_tree_add_text( tree, tvb, offset, 1, "Status: success");
+ offset ++;
+ }
+ else if ((compare_packet( hash_info->command_row)) ||
+ (compare_packet( hash_info->cmd_reply_row)) ||
+ (compare_packet( hash_info->bind_reply_row))){
+
+ command = tvb_get_guint8(tvb, offset);
+
+ if (compare_packet( hash_info->command_row))
+ proto_tree_add_uint( tree, hf_socks_cmd, tvb, offset, 1,
+ command);
+
+ else {
+ proto_tree_add_item( tree, hf_socks_results_5, tvb, offset, 1, FALSE);
+ proto_tree_add_item_hidden(tree, hf_socks_results, tvb, offset, 1, FALSE);
+ }
+
+ ++offset;
+
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "Reserved: 0x%0x (should = 0x00)", tvb_get_guint8(tvb, offset));
+ ++offset;
+
+ offset = display_address(tvb, offset, tree);
+/*XXX Add remote port for search somehow */
+ /* Do remote port */
+ proto_tree_add_text( tree, tvb, offset, 2,
+ "%sPort: %u",
+ (compare_packet( hash_info->bind_reply_row) ?
+ "Remote Host " : ""),
+ tvb_get_ntohs(tvb, offset));
+ }
+}
+
+
+
+/**************** Decoder State Machines ******************/
+
+
+static guint
+state_machine_v4( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
+ int offset, packet_info *pinfo) {
+
+/* Decode V4 protocol. This is done on the first pass through the */
+/* list. Based upon the current state, decode the packet and determine */
+/* what the next state should be. If we had per packet information, */
+/* this would be the place to load them up. */
+
+ if ( hash_info->state == None) { /* new connection */
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " Connect to server request");
+
+ hash_info->state = Connecting; /* change state */
+
+ hash_info->command = tvb_get_guint8(tvb, offset + 1);
+ /* get remote port */
+ if ( hash_info->command == CONNECT_COMMAND)
+ hash_info->port = tvb_get_ntohs(tvb, offset + 2);
+ /* get remote address */
+
+ tvb_memcpy(tvb, (guint8 *)&hash_info->dst_addr, offset + 4, 4);
+
+ /* save the packet pointer */
+ hash_info->connect_row = get_packet_ptr;
+
+ /* skip past this stuff */
+ hash_info->connect_offset = offset + 8;
+
+ offset += 8;
+
+ if ( !tvb_offset_exists(tvb, offset)) { /* if no user name */
+ /* change state */
+ hash_info->state = V4UserNameWait;
+ /*
+ * XXX - add 1, or leave it alone?
+ * We were adding "strlen(...) + 1".
+ */
+ hash_info->connect_offset += 1;
+ } else {
+ /*
+ * Add in the length of the user name.
+ * XXX - what if the user name is split between
+ * TCP segments?
+ */
+ hash_info->connect_offset += tvb_strsize(tvb, offset);
+ }
+
+ if ( !hash_info->dst_addr){ /* if no dest address */
+ /* if more data */
+ if ( tvb_offset_exists(tvb, hash_info->connect_offset)) {
+/*XXX copy remote name here ??? */
+ hash_info->state = Connecting;
+ }
+ else
+ hash_info->state = V4NameWait;
+ }
+ /* waiting for V4 user name */
+ }else if ( hash_info->state == V4UserNameWait){
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " Connect Request (User name)");
+
+ hash_info->v4_user_name_row = get_packet_ptr;
+/*XXX may need to check for domain name here */
+ hash_info->state = Connecting;
+ }
+ /* waiting for V4 domain name */
+ else if ( hash_info->state == V4NameWait){
+
+ hash_info->v4_name_row = get_packet_ptr;
+ hash_info->state = Connecting;
+
+ }
+ else if ( hash_info->state == Connecting){
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " Connect Response");
+
+ /* save packet pointer */
+ hash_info->cmd_reply_row = get_packet_ptr;
+ hash_info->state = Done; /* change state */
+ offset = offset + 8;
+ }
+
+ return offset;
+}
+
+
+
+static void
+state_machine_v5( socks_hash_entry_t *hash_info, tvbuff_t *tvb,
+ int offset, packet_info *pinfo) {
+
+/* Decode V5 protocol. This is done on the first pass through the */
+/* list. Based upon the current state, decode the packet and determine */
+/* what the next state should be. If we had per packet information, */
+/* this would be the place to load them up. */
+
+
+ int temp;
+
+ if ( hash_info->state == None) {
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " Connect to server request");
+
+ hash_info->state = Connecting; /* change state */
+ hash_info->connect_row = get_packet_ptr;
+
+ temp = tvb_get_guint8(tvb, offset + 1);
+ /* skip past auth methods */
+ offset = hash_info->connect_offset = offset + 1 + temp;
+ }
+ else if ( hash_info->state == Connecting){
+
+ guint AuthMethod = tvb_get_guint8(tvb, offset + 1);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " Connect to server response");
+
+ hash_info->auth_method_row = get_packet_ptr;
+
+ if ( AuthMethod == NO_AUTHENTICATION)
+ hash_info->state = V5Command;
+
+ else if ( AuthMethod == USER_NAME_AUTHENTICATION)
+ hash_info->state = UserNameAuth;
+
+ else if ( AuthMethod == GSS_API_AUTHENTICATION)
+/*XXX should be this hash_info->state = GssApiAuth; */
+ hash_info->state = Done;
+
+ else hash_info->state = Done; /*Auth failed or error*/
+
+ }
+
+ else if ( hash_info->state == V5Command) { /* Handle V5 Command */
+
+ guint temp;
+
+ hash_info->command = tvb_get_guint8(tvb, offset + 1); /* get command */
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Command Request - %s",
+ get_command_name(hash_info->command));
+
+ hash_info->state = V5Reply;
+ hash_info->command_row = get_packet_ptr;
+
+ offset += 3; /* skip to address type */
+
+ offset = get_address_v5(tvb, offset, hash_info);
+
+ temp = tvb_get_guint8(tvb, offset);
+
+ if (( hash_info->command == CONNECT_COMMAND) ||
+ ( hash_info->command == UDP_ASSOCIATE_COMMAND))
+ /* get remote port */
+ hash_info->port = tvb_get_ntohs(tvb, offset);
+ }
+
+ else if ( hash_info->state == V5Reply) { /* V5 Command Reply */
+
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Command Response - %s",
+ get_command_name(hash_info->command));
+
+ hash_info->cmd_reply_row = get_packet_ptr;
+
+ if (( hash_info->command == CONNECT_COMMAND) ||
+ (hash_info->command == PING_COMMAND) ||
+ (hash_info->command == TRACERT_COMMAND))
+ hash_info->state = Done;
+
+ else if ( hash_info->command == BIND_COMMAND)
+ hash_info->state = V5BindReply;
+
+ else if ( hash_info->command == UDP_ASSOCIATE_COMMAND){
+ offset += 3; /* skip to address type */
+ offset = get_address_v5(tvb, offset, hash_info);
+
+ /* save server udp port and create udp conversation */
+ hash_info->udp_port = tvb_get_ntohs(tvb, offset);
+
+ if (!pinfo->fd->flags.visited)
+ new_udp_conversation( hash_info, pinfo);
+
+/*XXX may need else statement to handle unknows and generate error message */
+
+ }
+ }
+ else if ( hash_info->state == V5BindReply) { /* V5 Bind Second Reply */
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " Command Response: Bind remote host info");
+
+ hash_info->bind_reply_row = get_packet_ptr;
+ hash_info->state = Done;
+ }
+ else if ( hash_info->state == UserNameAuth) { /* Handle V5 User Auth*/
+ hash_info->auth_version = get_packet_ptr;
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO,
+ " User authentication request");
+
+ hash_info->user_name_auth_row = get_packet_ptr;
+ hash_info->state = AuthReply;
+
+ }
+ else if ( hash_info->state == AuthReply){ /* V5 User Auth reply */
+ hash_info->auth_version = get_packet_ptr;
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, " User authentication reply");
+ hash_info->state = V5Command;
+ }
+}
+
+
+
+static void
+display_ping_and_tracert(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, socks_hash_entry_t *hash_info) {
+
+/* Display the ping/trace_route conversation */
+
+
+ const guchar *data, *dataend;
+ const guchar *lineend, *eol;
+ int linelen;
+
+ /* handle the end command */
+ if ( pinfo->destport == TCP_PORT_SOCKS){
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, ", Terminate Request");
+
+ if ( tree)
+ proto_tree_add_text(tree, tvb, offset, 1,
+ (hash_info->command == PING_COMMAND) ?
+ "Ping: End command" :
+ "Traceroute: End command");
+ }
+ else{ /* display the PING or Traceroute results */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, ", Results");
+
+ if ( tree){
+ proto_tree_add_text(tree, tvb, offset, -1,
+ (hash_info->command == PING_COMMAND) ?
+ "Ping Results:" :
+ "Traceroute Results");
+
+ data = tvb_get_ptr(tvb, offset, -1);
+ dataend = data + tvb_length_remaining(tvb, offset);
+
+ while (data < dataend) {
+
+ lineend = find_line_end(data, dataend, &eol);
+ linelen = lineend - data;
+
+ proto_tree_add_text( tree, tvb, offset, linelen,
+ "%s", format_text(data, linelen));
+ offset += linelen;
+ data = lineend;
+ }
+ }
+ }
+}
+
+
+
+static void clear_in_socks_dissector_flag(void *dummy _U_)
+{
+ in_socks_dissector_flag = 0; /* avoid recursive overflow */
+}
+
+static void call_next_dissector(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *socks_tree,
+ socks_hash_entry_t *hash_info)
+{
+
+/* Display the results for PING and TRACERT extensions or */
+/* Call TCP dissector for the port that was passed during the */
+/* connect process */
+/* Load pointer to pinfo->XXXport depending upon the direction, */
+/* change pinfo port to the remote port, call next dissecotr to decode */
+/* the payload, and restore the pinfo port after that is done. */
+
+ guint32 *ptr;
+ struct tcpinfo *tcpinfo = pinfo->private_data;
+ guint16 save_can_desegment;
+
+ if (( hash_info->command == PING_COMMAND) ||
+ ( hash_info->command == TRACERT_COMMAND))
+
+ display_ping_and_tracert(tvb, offset, pinfo, tree, hash_info);
+
+ else { /* call the tcp port decoder to handle the payload */
+
+/*XXX may want to load dest address here */
+
+ if ( pinfo->destport == TCP_PORT_SOCKS)
+ ptr = &pinfo->destport;
+ else
+ ptr = &pinfo->srcport;
+
+ *ptr = hash_info->port;
+
+/* 2003-09-18 JCFoster Fixed problem with socks tunnel in socks tunnel */
+
+ in_socks_dissector_flag = 1; /* avoid recursive overflow */
+ CLEANUP_PUSH(clear_in_socks_dissector_flag, NULL);
+
+ save_can_desegment = pinfo->can_desegment;
+ pinfo->can_desegment = pinfo->saved_can_desegment;
+ dissect_tcp_payload(tvb, pinfo, offset, tcpinfo->seq,
+ tcpinfo->nxtseq, pinfo->srcport, pinfo->destport,
+ tree, socks_tree);
+ pinfo->can_desegment = save_can_desegment;
+
+ CLEANUP_CALL_AND_POP;
+
+ *ptr = TCP_PORT_SOCKS;
+ }
+}
+
+
+
+static void
+dissect_socks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+
+ int offset = 0;
+ proto_tree *socks_tree = NULL;
+ proto_item *ti;
+ socks_hash_entry_t *hash_info;
+ conversation_t *conversation;
+
+/* 2003-09-18 JCFoster Fixed problem with socks tunnel in socks tunnel */
+
+ /* avoid recursive overflow */
+
+ if ( in_socks_dissector_flag) {
+ return;
+ }
+
+ conversation = find_conversation( &pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if ( !conversation){
+ conversation = conversation_new( &pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+ hash_info = conversation_get_proto_data(conversation,proto_socks);
+ if ( !hash_info){
+ hash_info = g_mem_chunk_alloc(socks_vals);
+ hash_info->start_done_row = G_MAXINT;
+ hash_info->state = None;
+ hash_info->port = 0;
+ hash_info->version = tvb_get_guint8(tvb, offset); /* get version*/
+
+ if (( hash_info->version != 4) && /* error test version */
+ ( hash_info->version != 5))
+ hash_info->state = Done;
+
+ conversation_add_proto_data(conversation, proto_socks,
+ hash_info);
+
+ /* set dissector for now */
+ conversation_set_dissector(conversation, socks_handle);
+ }
+
+/* display summary window information */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Socks");
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ if (( hash_info->version == 4) || ( hash_info->version == 5)){
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Version: %d",
+ hash_info->version);
+ }
+ else /* unknown version display error */
+ col_set_str(pinfo->cinfo, COL_INFO, "Unknown");
+
+
+ if ( hash_info->command == PING_COMMAND)
+ col_append_str(pinfo->cinfo, COL_INFO, ", Ping Req");
+ if ( hash_info->command == TRACERT_COMMAND)
+ col_append_str(pinfo->cinfo, COL_INFO, ", Traceroute Req");
+
+/*XXX if ( hash_info->port != -1) */
+ if ( hash_info->port != 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Remote Port: %u",
+ hash_info->port);
+ }
+
+
+/* run state machine if needed */
+
+ if ((hash_info->state != Done) && ( !pinfo->fd->flags.visited)){
+
+ if ( hash_info->version == 4)
+ state_machine_v4( hash_info, tvb, offset, pinfo);
+
+ else if ( hash_info->version == 5)
+ state_machine_v5( hash_info, tvb, offset, pinfo);
+
+ if (hash_info->state == Done) { /* if done now */
+ hash_info->start_done_row = pinfo->fd->num;
+ }
+ }
+
+/* if proto tree, decode and display */
+
+ if (tree) {
+ ti = proto_tree_add_item( tree, proto_socks, tvb, offset, -1,
+ FALSE );
+
+ socks_tree = proto_item_add_subtree(ti, ett_socks);
+
+ if ( hash_info->version == 4)
+ display_socks_v4(tvb, offset, pinfo, socks_tree,
+ hash_info);
+
+ else if ( hash_info->version == 5)
+ display_socks_v5(tvb, offset, pinfo, socks_tree,
+ hash_info);
+
+ /* if past startup, add the faked stuff */
+ if ( pinfo->fd->num > hash_info->start_done_row){
+ /* add info to tree */
+ proto_tree_add_text( socks_tree, tvb, offset, 0,
+ "Command: %d (%s)", hash_info->command,
+ get_command_name(hash_info->command));
+
+ proto_tree_add_ipv4( socks_tree, hf_socks_ip_dst, tvb,
+ offset, 0, hash_info->dst_addr);
+
+ /* no fake address for ping & traceroute */
+
+ if (( hash_info->command != PING_COMMAND) &&
+ ( hash_info->command != TRACERT_COMMAND)){
+ proto_tree_add_uint( socks_tree, hf_socks_dstport, tvb,
+ offset, 0, hash_info->port);
+ }
+ }
+
+ }
+
+
+/* call next dissector if ready */
+
+ if ( pinfo->fd->num > hash_info->start_done_row){
+ call_next_dissector(tvb, offset, pinfo, tree, socks_tree,
+ hash_info);
+ }
+}
+
+
+
+static void socks_reinit( void){
+
+/* Do the cleanup work when a new pass through the packet list is */
+/* performed. Reset the highest row seen counter and re-initialize the */
+/* conversation memory chunks. */
+
+ if (socks_vals)
+ g_mem_chunk_destroy(socks_vals);
+
+ socks_vals = g_mem_chunk_new("socks_vals", socks_hash_val_length,
+ socks_hash_init_count * socks_hash_val_length,
+ G_ALLOC_AND_FREE);
+}
+
+
+void
+proto_register_socks( void){
+
+/*** Prep the socks protocol, register it and a initialization routine */
+/* to clear the hash stuff. */
+
+
+ static gint *ett[] = {
+ &ett_socks,
+ &ett_socks_auth,
+ &ett_socks_name
+
+ };
+
+ static hf_register_info hf[] = {
+
+
+ { &hf_socks_ver,
+ { "Version", "socks.version", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL
+ }
+ },
+ { &hf_socks_ip_dst,
+ { "Remote Address", "socks.dst", FT_IPv4, BASE_NONE, NULL,
+ 0x0, "", HFILL
+ }
+ },
+ { &hf_socks_ip6_dst,
+ { "Remote Address(ipv6)", "socks.dstV6", FT_IPv6, BASE_NONE, NULL,
+ 0x0, "", HFILL
+ }
+ },
+
+ { &hf_user_name,
+ { "User Name", "socks.username", FT_STRINGZ, BASE_NONE,
+ NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_v4a_dns_name,
+ { "SOCKS v4a Remote Domain Name", "socks.v4a_dns_name", FT_STRINGZ, BASE_NONE,
+ NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_socks_dstport,
+ { "Remote Port", "socks.dstport", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ },
+ { &hf_socks_cmd,
+ { "Command", "socks.command", FT_UINT8,
+ BASE_DEC, VALS(cmd_strings), 0x0, "", HFILL
+ }
+ },
+ { &hf_socks_results_4,
+ { "Results(V4)", "socks.results_v4", FT_UINT8,
+ BASE_DEC, VALS(reply_table_v4), 0x0, "", HFILL
+ }
+ },
+ { &hf_socks_results_5,
+ { "Results(V5)", "socks.results_v5", FT_UINT8,
+ BASE_DEC, VALS(reply_table_v5), 0x0, "", HFILL
+ }
+ },
+ { &hf_socks_results,
+ { "Results(V5)", "socks.results", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL
+ }
+ }
+
+ };
+
+
+ proto_socks = proto_register_protocol (
+ "Socks Protocol", "Socks", "socks");
+
+ proto_register_field_array(proto_socks, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine( &socks_reinit); /* register re-init routine */
+
+ socks_udp_handle = create_dissector_handle(socks_udp_dissector,
+ proto_socks);
+ socks_handle = create_dissector_handle(dissect_socks, proto_socks);
+}
+
+
+void
+proto_reg_handoff_socks(void) {
+
+ /* dissector install routine */
+
+ dissector_add("tcp.port", TCP_PORT_SOCKS, socks_handle);
+}
diff --git a/epan/dissectors/packet-spnego.c b/epan/dissectors/packet-spnego.c
new file mode 100644
index 0000000000..70eace5ff2
--- /dev/null
+++ b/epan/dissectors/packet-spnego.c
@@ -0,0 +1,1694 @@
+/* packet-spnego.c
+ * Routines for the simple and protected GSS-API negotiation mechanism
+ * as described in RFC 2478.
+ * Copyright 2002, Tim Potter <tpot@samba.org>
+ * Copyright 2002, Richard Sharpe <rsharpe@ns.aus.com>
+ * Copyright 2003, Richard Sharpe <rsharpe@richardsharpe.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include "asn1.h"
+#include "format-oid.h"
+#include "packet-gssapi.h"
+#include "packet-kerberos.h"
+#include <epan/conversation.h>
+
+#define SPNEGO_negTokenInit 0
+#define SPNEGO_negTokenTarg 1
+#define SPNEGO_mechTypes 0
+#define SPNEGO_reqFlags 1
+#define SPNEGO_mechToken 2
+#define SPNEGO_mechListMIC 3
+#define SPNEGO_negResult 0
+#define SPNEGO_supportedMech 1
+#define SPNEGO_responseToken 2
+#define SPNEGO_negResult_accept_completed 0
+#define SPNEGO_negResult_accept_incomplete 1
+#define SPNEGO_negResult_accept_reject 2
+
+static int proto_spnego = -1;
+static int proto_spnego_krb5 = -1;
+
+static int hf_spnego = -1;
+static int hf_spnego_negtokeninit = -1;
+static int hf_spnego_negtokentarg = -1;
+static int hf_spnego_mechtype = -1;
+static int hf_spnego_mechtoken = -1;
+static int hf_spnego_negtokentarg_negresult = -1;
+static int hf_spnego_mechlistmic = -1;
+static int hf_spnego_responsetoken = -1;
+static int hf_spnego_reqflags = -1;
+static int hf_spnego_wraptoken = -1;
+static int hf_spnego_krb5 = -1;
+static int hf_spnego_krb5_tok_id = -1;
+static int hf_spnego_krb5_sgn_alg = -1;
+static int hf_spnego_krb5_seal_alg = -1;
+static int hf_spnego_krb5_snd_seq = -1;
+static int hf_spnego_krb5_sgn_cksum = -1;
+static int hf_spnego_krb5_confounder = -1;
+static int hf_gssapi_reqflags_deleg = -1;
+static int hf_gssapi_reqflags_mutual = -1;
+static int hf_gssapi_reqflags_replay = -1;
+static int hf_gssapi_reqflags_sequence = -1;
+static int hf_gssapi_reqflags_anon = -1;
+static int hf_gssapi_reqflags_conf = -1;
+static int hf_gssapi_reqflags_integ = -1;
+
+static gint ett_spnego = -1;
+static gint ett_spnego_negtokeninit = -1;
+static gint ett_spnego_negtokentarg = -1;
+static gint ett_spnego_mechtype = -1;
+static gint ett_spnego_mechtoken = -1;
+static gint ett_spnego_mechlistmic = -1;
+static gint ett_spnego_responsetoken = -1;
+static gint ett_spnego_wraptoken = -1;
+static gint ett_spnego_krb5 = -1;
+static gint ett_spnego_reqflags = -1;
+
+static const value_string spnego_negResult_vals[] = {
+ { SPNEGO_negResult_accept_completed, "Accept Completed" },
+ { SPNEGO_negResult_accept_incomplete, "Accept Incomplete" },
+ { SPNEGO_negResult_accept_reject, "Accept Reject"},
+ { 0, NULL}
+};
+
+/*
+ * These should be in the GSSAPI dissector ... XXX
+ */
+
+static const true_false_string tfs_reqflags_deleg = {
+ "Delegation Requested",
+ "Delegation NOT Requested"
+};
+
+static const true_false_string tfs_reqflags_mutual = {
+ "Mutual Authentication Requested",
+ "Mutual Authentication NOT Requested"
+};
+
+static const true_false_string tfs_reqflags_replay = {
+ "Replay Detection Requested",
+ "Replay Detection NOT Requested"
+};
+
+static const true_false_string tfs_reqflags_sequence = {
+ "Out-of-sequence Detection Requested",
+ "Out-of-sequence Detection NOT Requested"
+};
+
+static const true_false_string tfs_reqflags_anon = {
+ "Anonymous Authentication Requested",
+ "Anonymous Authentication NOT Requested"
+};
+
+static const true_false_string tfs_reqflags_conf = {
+ "Per-message Confidentiality Requested",
+ "Per-message Confidentiality NOT Requested"
+};
+
+static const true_false_string tfs_reqflags_integ = {
+ "Per-message Integrity Requested",
+ "Per-message Integrity NOT Requested"
+};
+
+/* Display an ASN1 parse error. Taken from packet-snmp.c */
+
+static dissector_handle_t data_handle;
+
+static dissector_handle_t
+gssapi_dissector_handle(gssapi_oid_value *next_level_value) {
+ if (next_level_value == NULL) {
+ return NULL;
+ }
+ return next_level_value->handle;
+}
+
+static void
+dissect_parse_error(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, const char *field_name, int ret)
+{
+ char *errstr;
+
+ errstr = asn1_err_to_str(ret);
+
+ if (tree != NULL) {
+ proto_tree_add_text(tree, tvb, offset, 0,
+ "ERROR: Couldn't parse %s: %s", field_name, errstr);
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, tree);
+ }
+}
+
+/*
+ * This is the SPNEGO KRB5 dissector. It is not true KRB5, but some ASN.1
+ * wrapped blob with an OID, USHORT token ID, and a Ticket, that is also
+ * ASN.1 wrapped by the looks of it. It conforms to RFC1964.
+ */
+
+#define KRB_TOKEN_AP_REQ 0x0001
+#define KRB_TOKEN_AP_REP 0x0002
+#define KRB_TOKEN_AP_ERR 0x0003
+#define KRB_TOKEN_GETMIC 0x0101
+#define KRB_TOKEN_WRAP 0x0102
+#define KRB_TOKEN_DELETE_SEC_CONTEXT 0x0201
+
+static const value_string spnego_krb5_tok_id_vals[] = {
+ { KRB_TOKEN_AP_REQ, "KRB5_AP_REQ"},
+ { KRB_TOKEN_AP_REP, "KRB5_AP_REP"},
+ { KRB_TOKEN_AP_ERR, "KRB5_ERROR"},
+ { KRB_TOKEN_GETMIC, "KRB5_GSS_GetMIC" },
+ { KRB_TOKEN_WRAP, "KRB5_GSS_Wrap" },
+ { KRB_TOKEN_DELETE_SEC_CONTEXT, "KRB5_GSS_Delete_sec_context" },
+ { 0, NULL}
+};
+
+#define KRB_SGN_ALG_DES_MAC_MD5 0x0000
+#define KRB_SGN_ALG_MD2_5 0x0001
+#define KRB_SGN_ALG_DES_MAC 0x0002
+#define KRB_SGN_ALG_HMAC 0x0011
+
+static const value_string spnego_krb5_sgn_alg_vals[] = {
+ { KRB_SGN_ALG_DES_MAC_MD5, "DES MAC MD5"},
+ { KRB_SGN_ALG_MD2_5, "MD2.5"},
+ { KRB_SGN_ALG_DES_MAC, "DES MAC"},
+ { KRB_SGN_ALG_HMAC, "HMAC"},
+ { 0, NULL}
+};
+
+#define KRB_SEAL_ALG_DES_CBC 0x0000
+#define KRB_SEAL_ALG_RC4 0x0010
+#define KRB_SEAL_ALG_NONE 0xffff
+
+static const value_string spnego_krb5_seal_alg_vals[] = {
+ { KRB_SEAL_ALG_DES_CBC, "DES CBC"},
+ { KRB_SEAL_ALG_RC4, "RC4"},
+ { KRB_SEAL_ALG_NONE, "None"},
+ { 0, NULL}
+};
+
+/*
+ * XXX - is this for SPNEGO or just GSS-API?
+ * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
+ * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
+ * than designating SPNEGO as the mechanism, offering Kerberos V5, and
+ * getting it accepted.
+ */
+static int
+dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static int
+dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree);
+
+static void
+dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ int ret, offset = 0;
+ ASN1_SCK hnd;
+ gboolean def;
+ guint len1, cls, con, tag, oid_len, nbytes;
+ guint16 token_id;
+ subid_t *oid;
+ gchar *oid_string;
+ gssapi_oid_value *value;
+ tvbuff_t *krb5_tvb;
+
+ item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
+ -1, FALSE);
+
+ subtree = proto_item_add_subtree(item, ett_spnego_krb5);
+
+ /*
+ * The KRB5 blob conforms to RFC1964:
+ * [APPLICATION 0] {
+ * OID,
+ * USHORT (0x0001 == AP-REQ, 0x0002 == AP-REP, 0x0003 == ERROR),
+ * OCTET STRING }
+ *
+ * However, for some protocols, the KRB5 blob starts at the SHORT
+ * and has no DER encoded header etc.
+ *
+ * It appears that for some other protocols the KRB5 blob is just
+ * a Kerberos message, with no [APPLICATION 0] header, no OID,
+ * and no USHORT.
+ *
+ * So:
+ *
+ * If we see an [APPLICATION 0] HEADER, we show the OID and
+ * the USHORT, and then dissect the rest as a Kerberos message.
+ *
+ * If we see an [APPLICATION 14] or [APPLICATION 15] header,
+ * we assume it's an AP-REQ or AP-REP message, and dissect
+ * it all as a Kerberos message.
+ *
+ * Otherwise, we show the USHORT, and then dissect the rest
+ * as a Kerberos message.
+ */
+
+ asn1_open(&hnd, tvb, offset);
+
+ /*
+ * Get the first header ...
+ */
+
+ ret = asn1_header_decode(&hnd, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO KRB5 Header", ret);
+ goto done;
+ }
+
+ if (cls == ASN1_APL && con == ASN1_CON) {
+ /*
+ * [APPLICATION <tag>]
+ */
+ switch (tag) {
+
+ case 0:
+ /*
+ * [APPLICATION 0]
+ */
+
+ offset = hnd.offset;
+
+ /* Next, the OID */
+
+ ret = asn1_oid_decode(&hnd, &oid, &oid_len, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO supportedMech token", ret);
+ goto done;
+ }
+
+ oid_string = format_oid(oid, oid_len);
+
+ value = gssapi_lookup_oid(oid, oid_len);
+
+ if (value)
+ proto_tree_add_text(subtree, tvb, offset, nbytes,
+ "OID: %s (%s)",
+ oid_string, value->comment);
+ else
+ proto_tree_add_text(subtree, tvb, offset, nbytes,
+ "OID: %s",
+ oid_string);
+
+ g_free(oid_string);
+
+ offset += nbytes;
+
+ /* Next, the token ID ... */
+
+ token_id = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
+ token_id);
+
+ hnd.offset += 2;
+
+ offset += 2;
+
+ break;
+
+ case 14: /* [APPLICATION 14] */
+ case 15: /* [APPLICATION 15] */
+ /*
+ * No token ID - just dissect as a Kerberos message and
+ * return.
+ */
+ krb5_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
+ return;
+
+ default:
+ proto_tree_add_text(subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+ } else {
+ /* Next, the token ID ... */
+
+ token_id = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
+ token_id);
+
+ hnd.offset += 2;
+
+ offset += 2;
+ }
+
+ switch (token_id) {
+
+ case KRB_TOKEN_AP_REQ:
+ case KRB_TOKEN_AP_REP:
+ case KRB_TOKEN_AP_ERR:
+ krb5_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
+ break;
+
+ case KRB_TOKEN_GETMIC:
+ offset = dissect_spnego_krb5_getmic_base(tvb, offset, pinfo, subtree);
+ break;
+
+ case KRB_TOKEN_WRAP:
+ offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree);
+ break;
+
+ case KRB_TOKEN_DELETE_SEC_CONTEXT:
+
+ break;
+
+ default:
+
+ break;
+ }
+
+ done:
+ return;
+}
+
+/*
+ * XXX - This is for GSSAPI Wrap tokens ...
+ */
+static int
+dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint16 sgn_alg;
+
+ /*
+ * The KRB5 blob conforms to RFC1964:
+ * USHORT (0x0102 == GSS_Wrap)
+ * and so on }
+ */
+
+ /* Now, the sign and seal algorithms ... */
+
+ sgn_alg = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
+ sgn_alg);
+
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_spnego_krb5_seal_alg, tvb, offset, 2,
+ TRUE);
+
+ offset += 2;
+
+ /* Skip the filler */
+
+ offset += 2;
+
+ /* Encrypted sequence number */
+
+ proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
+ TRUE);
+
+ offset += 8;
+
+ /* Checksum of plaintext padded data */
+
+ proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
+ TRUE);
+
+ offset += 8;
+
+ /*
+ * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
+ * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
+ * extra 8 bytes of "Random confounder" after the checksum.
+ * It certainly confounds code expecting all Kerberos 5
+ * GSS_Wrap() tokens to look the same....
+ */
+ if (sgn_alg == KRB_SGN_ALG_HMAC) {
+ proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
+ TRUE);
+
+ offset += 8;
+ }
+
+ /*
+ * Return the offset past the checksum, so that we know where
+ * the data we're wrapped around starts. Also, set the length
+ * of our top-level item to that offset, so it doesn't cover
+ * the data we're wrapped around.
+ */
+ return offset;
+}
+
+/*
+ * XXX - This is for GSSAPI GetMIC tokens ...
+ */
+static int
+dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint16 sgn_alg;
+
+ /*
+ * The KRB5 blob conforms to RFC1964:
+ * USHORT (0x0101 == GSS_GetMIC)
+ * and so on }
+ */
+
+ /* Now, the sign algorithm ... */
+
+ sgn_alg = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_spnego_krb5_sgn_alg, tvb, offset, 2,
+ sgn_alg);
+
+ offset += 2;
+
+ /* Skip the filler */
+
+ offset += 4;
+
+ /* Encrypted sequence number */
+
+ proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
+ TRUE);
+
+ offset += 8;
+
+ /* Checksum of plaintext padded data */
+
+ proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
+ TRUE);
+
+ offset += 8;
+
+ /*
+ * At least according to draft-brezak-win2k-krb-rc4-hmac-04,
+ * if the signing algorithm is KRB_SGN_ALG_HMAC, there's an
+ * extra 8 bytes of "Random confounder" after the checksum.
+ * It certainly confounds code expecting all Kerberos 5
+ * GSS_Wrap() tokens to look the same....
+ */
+ if (sgn_alg == KRB_SGN_ALG_HMAC) {
+ proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
+ TRUE);
+
+ offset += 8;
+ }
+
+ /*
+ * Return the offset past the checksum, so that we know where
+ * the data we're wrapped around starts. Also, set the length
+ * of our top-level item to that offset, so it doesn't cover
+ * the data we're wrapped around.
+ */
+
+ return offset;
+}
+
+/*
+ * XXX - is this for SPNEGO or just GSS-API?
+ * RFC 1964 is "The Kerberos Version 5 GSS-API Mechanism"; presumably one
+ * can directly designate Kerberos V5 as a mechanism in GSS-API, rather
+ * than designating SPNEGO as the mechanism, offering Kerberos V5, and
+ * getting it accepted.
+ */
+static int
+dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ int offset = 0;
+
+ item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, FALSE);
+
+ subtree = proto_item_add_subtree(item, ett_spnego_krb5);
+
+ /*
+ * The KRB5 blob conforms to RFC1964:
+ * USHORT (0x0102 == GSS_Wrap)
+ * and so on }
+ */
+
+ /* First, the token ID ... */
+
+ proto_tree_add_item(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
+ TRUE);
+
+ offset += 2;
+
+ offset = dissect_spnego_krb5_wrap_base(tvb, offset, pinfo, subtree);
+
+ /*
+ * Return the offset past the checksum, so that we know where
+ * the data we're wrapped around starts. Also, set the length
+ * of our top-level item to that offset, so it doesn't cover
+ * the data we're wrapped around.
+ */
+ proto_item_set_len(item, offset);
+ return offset;
+}
+
+/* Spnego stuff from here */
+
+static int
+dissect_spnego_mechTypes(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, ASN1_SCK *hnd,
+ gssapi_oid_value **next_level_value_p)
+{
+ proto_item *item = NULL;
+ proto_tree *subtree = NULL;
+ gboolean def;
+ guint len1, len, cls, con, tag, nbytes;
+ subid_t *oid;
+ gchar *oid_string;
+ int ret;
+ gboolean saw_mechanism = FALSE;
+
+ /*
+ * MechTypeList ::= SEQUENCE OF MechType
+ */
+
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO last sequence header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_UNI && con == ASN1_CON && tag == ASN1_SEQ)) {
+ proto_tree_add_text(
+ subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ offset = hnd->offset;
+
+ item = proto_tree_add_item(tree, hf_spnego_mechtype, tvb, offset,
+ len1, FALSE);
+ subtree = proto_item_add_subtree(item, ett_spnego_mechtype);
+
+ /*
+ * Now, the object IDs ... We should translate them: FIXME
+ */
+
+ while (len1) {
+ gssapi_oid_value *value;
+
+ ret = asn1_oid_decode(hnd, &oid, &len, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO mechTypes token", ret);
+ goto done;
+ }
+
+ oid_string = format_oid(oid, len);
+ value = gssapi_lookup_oid(oid, len);
+ if (value)
+ proto_tree_add_text(subtree, tvb, offset, nbytes, "OID: %s (%s)",
+ oid_string, value->comment);
+ else
+ proto_tree_add_text(subtree, tvb, offset, nbytes, "OID: %s",
+ oid_string);
+
+ g_free(oid_string);
+
+ /*
+ * Tell our caller the first mechanism we see, so that if
+ * this is a negTokenInit with a mechToken, it can interpret
+ * the mechToken according to the first mechType. (There
+ * might not have been any indication of the mechType
+ * in prior frames, so we can't necessarily use the
+ * mechanism from the conversation; i.e., a negTokenInit
+ * can contain the initial security token for the desired
+ * mechanism of the initiator - that's the first mechanism
+ * in the list.)
+ */
+ if (!saw_mechanism) {
+ if (value)
+ *next_level_value_p = value;
+ saw_mechanism = TRUE;
+ }
+
+ offset += nbytes;
+ len1 -= nbytes;
+
+ }
+
+ done:
+
+ return offset;
+
+}
+
+static int
+dissect_spnego_reqFlags(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, ASN1_SCK *hnd)
+{
+ gboolean def;
+ guint len1, cls, con, tag, flags;
+ int ret;
+ proto_item *item;
+ proto_tree *subtree;
+
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, tree,
+ "SPNEGO reqFlags header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_BTS)) {
+ proto_tree_add_text(
+ tree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ /* We must have a Bit String ... insert it */
+
+ offset = hnd->offset;
+
+ flags = tvb_get_guint8(tvb, offset);
+
+ item = proto_tree_add_item(tree, hf_spnego_reqflags, tvb, offset, len1,
+ FALSE);
+
+ subtree = proto_item_add_subtree(item, ett_spnego_reqflags);
+
+ /*
+ * Now, the bits. XXX: Assume 8 bits. FIXME.
+ */
+
+ proto_tree_add_boolean(subtree, hf_gssapi_reqflags_deleg, tvb, offset, len1, flags);
+ proto_tree_add_boolean(subtree, hf_gssapi_reqflags_mutual, tvb, offset, len1, flags);
+ proto_tree_add_boolean(subtree, hf_gssapi_reqflags_replay, tvb, offset, len1, flags);
+ proto_tree_add_boolean(subtree, hf_gssapi_reqflags_sequence, tvb, offset, len1, flags);
+ proto_tree_add_boolean(subtree, hf_gssapi_reqflags_anon, tvb, offset, len1, flags);
+ proto_tree_add_boolean(subtree, hf_gssapi_reqflags_conf, tvb, offset, len1, flags);
+ proto_tree_add_boolean(subtree, hf_gssapi_reqflags_integ, tvb, offset, len1, flags);
+
+ hnd->offset += len1;
+
+ done:
+ return offset + len1;
+
+}
+
+static int
+dissect_spnego_mechToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, ASN1_SCK *hnd,
+ dissector_handle_t next_level_dissector)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean def;
+ int ret;
+ guint cls, con, tag, nbytes;
+ gint length_remaining, reported_length_remaining;
+ tvbuff_t *token_tvb;
+
+ /*
+ * This appears to be a simple octet string ...
+ */
+
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, tree,
+ "SPNEGO sequence header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)) {
+ proto_tree_add_text(
+ tree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ offset = hnd->offset;
+
+
+ /* Dont try to create an item with more bytes than remains in the
+ * frame or we will not even attempt to dissect those bytes we
+ * do have. (since there will be an exception)
+ *
+ * We use "tvb_ensure_length_remaining()" so that we throw
+ * an exception if there's nothing to dissect.
+ */
+ length_remaining = tvb_ensure_length_remaining(tvb,offset);
+ reported_length_remaining = tvb_reported_length_remaining(tvb,offset);
+ if ((guint)length_remaining > nbytes)
+ length_remaining = nbytes;
+ if ((guint)reported_length_remaining > nbytes)
+ reported_length_remaining = nbytes;
+ item = proto_tree_add_item(tree, hf_spnego_mechtoken, tvb, offset,
+ length_remaining, FALSE);
+ subtree = proto_item_add_subtree(item, ett_spnego_mechtoken);
+
+ /*
+ * Now, we should be able to dispatch after creating a new TVB.
+ */
+
+ token_tvb = tvb_new_subset(tvb, offset, length_remaining,
+ reported_length_remaining);
+ if (next_level_dissector)
+ call_dissector(next_level_dissector, token_tvb, pinfo, subtree);
+
+ hnd->offset += nbytes; /* Update this ... */
+
+done:
+ return offset + nbytes;
+}
+
+static int
+dissect_spnego_mechListMIC(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, ASN1_SCK *hnd,
+ dissector_handle_t next_level_dissector)
+{
+ guint len1, cls, con, tag;
+ int ret;
+ gboolean def;
+ proto_tree *subtree = NULL;
+
+ /*
+ * Add the mechListMIC [3] Octet String or General String ...
+ */
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO sequence header", ret);
+ goto done;
+ }
+
+ offset = hnd->offset;
+
+ if (cls == ASN1_UNI && con == ASN1_CON && tag == ASN1_SEQ) {
+
+ /*
+ * There seems to be two different forms this can take
+ * One as an Octet string, and one as a general string in a
+ * sequence ... We will have to dissect this later
+ */
+
+ proto_tree_add_text(tree, tvb, offset + 4, len1 - 4,
+ "mechListMIC: %s",
+ tvb_format_text(tvb, offset + 4, len1 - 4));
+
+ /* Naughty ... but we have to adjust for what we never took */
+
+ hnd->offset += len1;
+ offset += len1;
+
+ }
+ else if (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS) {
+ tvbuff_t *token_tvb;
+ proto_item *item;
+ proto_tree *subtree;
+
+ item = proto_tree_add_item(tree, hf_spnego_mechlistmic, tvb, offset,
+ len1, FALSE);
+ subtree = proto_item_add_subtree(item, ett_spnego_mechlistmic);
+
+ /*
+ * Now, we should be able to dispatch after creating a new TVB.
+ */
+
+ token_tvb = tvb_new_subset(tvb, offset, len1, -1);
+ if (next_level_dissector)
+ call_dissector(next_level_dissector, token_tvb, pinfo, subtree);
+
+ hnd->offset += len1; /* Update this ... */
+ offset += len1;
+
+ }
+ else {
+
+ proto_tree_add_text(subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ done:
+
+ return offset;
+
+}
+
+static int
+dissect_spnego_negTokenInit(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, ASN1_SCK *hnd,
+ gssapi_oid_value **next_level_value_p)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean def;
+ guint len1, len, cls, con, tag;
+ int ret;
+
+ item = proto_tree_add_item( tree, hf_spnego_negtokeninit, tvb, offset,
+ -1, FALSE);
+ subtree = proto_item_add_subtree(item, ett_spnego_negtokeninit);
+
+ /*
+ * Here is what we need to get ...
+ * NegTokenInit ::= SEQUENCE {
+ * mechTypes [0] MechTypeList OPTIONAL,
+ * reqFlags [1] ContextFlags OPTIONAL,
+ * mechToken [2] OCTET STRING OPTIONAL,
+ * mechListMIC [3] OCTET STRING OPTIONAL }
+
+ */
+
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO sequence header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_UNI && con == ASN1_CON && tag == ASN1_SEQ)) {
+ proto_tree_add_text(
+ subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ offset = hnd->offset;
+
+ while (len1) {
+ int hdr_ofs;
+
+ hdr_ofs = hnd->offset;
+
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO context header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_CTX && con == ASN1_CON)) {
+ proto_tree_add_text(subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ /* Adjust for the length of the header */
+
+ len1 -= (hnd->offset - hdr_ofs);
+
+ /* Should be one of the fields */
+
+ switch (tag) {
+
+ case SPNEGO_mechTypes:
+
+ offset = dissect_spnego_mechTypes(tvb, offset, pinfo,
+ subtree, hnd,
+ next_level_value_p);
+
+ break;
+
+ case SPNEGO_reqFlags:
+
+ offset = dissect_spnego_reqFlags(tvb, offset, pinfo, subtree, hnd);
+
+ break;
+
+ case SPNEGO_mechToken:
+
+ offset = dissect_spnego_mechToken(tvb, offset, pinfo, subtree,
+ hnd, gssapi_dissector_handle(*next_level_value_p));
+ break;
+
+ case SPNEGO_mechListMIC:
+
+ offset = dissect_spnego_mechListMIC(tvb, offset, pinfo, subtree,
+ hnd, gssapi_dissector_handle(*next_level_value_p));
+ break;
+
+ default:
+
+ break;
+ }
+
+ len1 -= len;
+
+ }
+
+ done:
+
+ return offset; /* Not sure this is right */
+}
+
+static int
+dissect_spnego_negResult(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, ASN1_SCK *hnd)
+{
+ gboolean def;
+ int ret;
+ guint len, cls, con, tag, val;
+
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, tree,
+ "SPNEGO context header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_ENUM)) {
+ proto_tree_add_text(
+ tree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d) xxx",
+ cls, con, tag);
+ goto done;
+ }
+
+ offset = hnd->offset;
+
+ /* Now, get the value */
+
+ ret = asn1_uint32_value_decode(hnd, len, &val);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, tree,
+ "SPNEGO negResult value", ret);
+ goto done;
+ }
+
+ proto_tree_add_item(tree, hf_spnego_negtokentarg_negresult, tvb,
+ offset, 1, FALSE);
+
+ offset = hnd->offset;
+
+ done:
+ return offset;
+}
+
+static int
+dissect_spnego_supportedMech(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, ASN1_SCK *hnd,
+ gssapi_oid_value **next_level_value_p)
+{
+ int ret;
+ guint oid_len, nbytes;
+ subid_t *oid;
+ gchar *oid_string;
+ gssapi_oid_value *value;
+ conversation_t *conversation;
+
+ /*
+ * Now, get the OID, and find the handle, if any
+ */
+
+ offset = hnd->offset;
+
+ ret = asn1_oid_decode(hnd, &oid, &oid_len, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, tree,
+ "SPNEGO supportedMech token", ret);
+ goto done;
+ }
+
+ oid_string = format_oid(oid, oid_len);
+ value = gssapi_lookup_oid(oid, oid_len);
+
+ if (value)
+ proto_tree_add_text(tree, tvb, offset, nbytes,
+ "supportedMech: %s (%s)",
+ oid_string, value->comment);
+ else
+ proto_tree_add_text(tree, tvb, offset, nbytes, "supportedMech: %s",
+ oid_string);
+
+ g_free(oid_string);
+
+ offset += nbytes;
+
+ /* Should check for an unrecognized OID ... */
+
+ if (value)
+ *next_level_value_p = value;
+
+ /*
+ * Now, we need to save this in per proto info in the
+ * conversation if it exists. We also should create a
+ * conversation if one does not exist. FIXME!
+ * Hmmm, might need to be smarter, because there can be
+ * multiple mechTypes in a negTokenInit with one being the
+ * default used in the Token if present. Then the negTokenTarg
+ * could override that. :-(
+ */
+
+ if ((conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0))) {
+
+
+ conversation_add_proto_data(conversation, proto_spnego,
+ *next_level_value_p);
+ }
+ else {
+
+ }
+
+ done:
+ return offset;
+}
+
+static int
+dissect_spnego_responseToken(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, ASN1_SCK *hnd,
+ dissector_handle_t next_level_dissector)
+{
+ gboolean def;
+ int ret;
+ guint cls, con, tag, nbytes;
+ tvbuff_t *token_tvb;
+ proto_item *item;
+ proto_tree *subtree;
+
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, tree,
+ "SPNEGO sequence header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)) {
+ proto_tree_add_text(
+ tree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ offset = hnd->offset;
+
+ item = proto_tree_add_item(tree, hf_spnego_responsetoken, tvb, offset -2 ,
+ nbytes + 2, FALSE);
+
+ subtree = proto_item_add_subtree(item, ett_spnego_responsetoken);
+
+
+ /*
+ * Now, we should be able to dispatch after creating a new TVB.
+ * However, we should make sure that there is something in the
+ * response token ...
+ */
+
+ if (nbytes) {
+ token_tvb = tvb_new_subset(tvb, offset, nbytes, -1);
+ if (next_level_dissector)
+ call_dissector(next_level_dissector, token_tvb, pinfo, subtree);
+ }
+ else {
+ proto_tree_add_text(subtree, tvb, offset-2, 2, "<Empty String>");
+ }
+ hnd->offset += nbytes; /* Update this ... */
+
+ done:
+ return offset + nbytes;
+}
+
+static int
+dissect_spnego_negTokenTarg(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+ proto_tree *tree, ASN1_SCK *hnd,
+ gssapi_oid_value **next_level_value_p)
+
+{
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean def;
+ int ret;
+ guint len1, len, cls, con, tag;
+
+ item = proto_tree_add_item( tree, hf_spnego_negtokentarg, tvb, offset,
+ -1, FALSE);
+ subtree = proto_item_add_subtree(item, ett_spnego_negtokentarg);
+
+ /*
+ * Here is what we need to get ...
+ * NegTokenTarg ::= SEQUENCE {
+ * negResult [0] ENUMERATED {
+ * accept_completed (0),
+ * accept_incomplete (1),
+ * reject (2) } OPTIONAL,
+ * supportedMech [1] MechType OPTIONAL,
+ * responseToken [2] OCTET STRING OPTIONAL,
+ * mechListMIC [3] OCTET STRING OPTIONAL }
+ */
+
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO sequence header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_UNI && con == ASN1_CON && tag == ASN1_SEQ)) {
+ proto_tree_add_text(
+ subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ offset = hnd->offset;
+
+ while (len1) {
+ int hdr_ofs;
+
+ hdr_ofs = hnd->offset;
+
+ ret = asn1_header_decode(hnd, &cls, &con, &tag, &def, &len);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO context header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_CTX && con == ASN1_CON)) {
+ proto_tree_add_text(
+ subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ /* Adjust for the length of the header */
+
+ len1 -= (hnd->offset - hdr_ofs);
+
+ /* Should be one of the fields */
+
+ switch (tag) {
+
+ case SPNEGO_negResult:
+
+ offset = dissect_spnego_negResult(tvb, offset, pinfo, subtree,
+ hnd);
+ break;
+
+ case SPNEGO_supportedMech:
+
+ offset = dissect_spnego_supportedMech(tvb, offset, pinfo, subtree,
+ hnd, next_level_value_p);
+
+ break;
+
+ case SPNEGO_responseToken:
+
+ offset = dissect_spnego_responseToken(tvb, offset, pinfo, subtree,
+ hnd, gssapi_dissector_handle(*next_level_value_p));
+ break;
+
+ case SPNEGO_mechListMIC:
+
+ offset = dissect_spnego_mechListMIC(tvb, offset, pinfo, subtree,
+ hnd, gssapi_dissector_handle(*next_level_value_p));
+ break;
+
+ default:
+
+ break;
+ }
+
+ len1 -= len;
+
+ }
+
+ done:
+ return offset;
+
+}
+
+static void
+dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ int ret, offset = 0;
+ ASN1_SCK hnd;
+ gboolean def;
+ guint len1, cls, con, tag;
+ conversation_t *conversation;
+ gssapi_oid_value *next_level_value;
+
+ /*
+ * We need this later, so lets get it now ...
+ * It has to be per-frame as there can be more than one GSS-API
+ * negotiation in a conversation.
+ */
+
+ next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
+ if (!next_level_value && !pinfo->fd->flags.visited) {
+ /*
+ * No handle attached to this frame, but it's the first
+ * pass, so it'd be attached to the conversation.
+ * If we have a conversation, try to get the handle,
+ * and if we get one, attach it to the frame.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+
+ if (conversation) {
+ next_level_value = conversation_get_proto_data(conversation,
+ proto_spnego);
+ if (next_level_value)
+ p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
+ }
+ }
+
+ item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
+ -1, FALSE);
+
+ subtree = proto_item_add_subtree(item, ett_spnego);
+
+ /*
+ * The TVB contains a [0] header and a sequence that consists of an
+ * object ID and a blob containing the data ...
+ * Actually, it contains, according to RFC2478:
+ * NegotiationToken ::= CHOICE {
+ * negTokenInit [0] NegTokenInit,
+ * negTokenTarg [1] NegTokenTarg }
+ * NegTokenInit ::= SEQUENCE {
+ * mechTypes [0] MechTypeList OPTIONAL,
+ * reqFlags [1] ContextFlags OPTIONAL,
+ * mechToken [2] OCTET STRING OPTIONAL,
+ * mechListMIC [3] OCTET STRING OPTIONAL }
+ * NegTokenTarg ::= SEQUENCE {
+ * negResult [0] ENUMERATED {
+ * accept_completed (0),
+ * accept_incomplete (1),
+ * reject (2) } OPTIONAL,
+ * supportedMech [1] MechType OPTIONAL,
+ * responseToken [2] OCTET STRING OPTIONAL,
+ * mechListMIC [3] OCTET STRING OPTIONAL }
+ *
+ * Windows typically includes mechTypes and mechListMic ('NONE'
+ * in the case of NTLMSSP only).
+ * It seems to duplicate the responseToken into the mechListMic field
+ * as well. Naughty, naughty.
+ *
+ */
+
+ asn1_open(&hnd, tvb, offset);
+
+ /*
+ * Get the first header ...
+ */
+
+ ret = asn1_header_decode(&hnd, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO context header", ret);
+ goto done;
+ }
+
+ if (!(cls == ASN1_CTX && con == ASN1_CON)) {
+ proto_tree_add_text(
+ subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ goto done;
+ }
+
+ offset = hnd.offset;
+
+ /*
+ * The Tag is one of negTokenInit or negTokenTarg
+ */
+
+ switch (tag) {
+
+ case SPNEGO_negTokenInit:
+
+ offset = dissect_spnego_negTokenInit(tvb, offset, pinfo,
+ subtree, &hnd,
+ &next_level_value);
+
+ break;
+
+ case SPNEGO_negTokenTarg:
+
+ offset = dissect_spnego_negTokenTarg(tvb, offset, pinfo,
+ subtree, &hnd,
+ &next_level_value);
+ break;
+
+ default: /* Broken, what to do? */
+
+ break;
+ }
+
+
+ done:
+ asn1_close(&hnd, &offset);
+
+}
+
+static int
+dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *item;
+ proto_tree *subtree;
+ int ret, offset = 0;
+ int return_offset;
+ ASN1_SCK hnd;
+ gboolean def;
+ guint len1, cls, con, tag, nbytes;
+ guint oid_len;
+ subid_t *oid;
+ gchar *oid_string;
+ conversation_t *conversation;
+ gssapi_oid_value *next_level_value;
+ tvbuff_t *token_tvb;
+ int len;
+
+ /*
+ * We need this later, so lets get it now ...
+ * It has to be per-frame as there can be more than one GSS-API
+ * negotiation in a conversation.
+ */
+
+ next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
+ if (!next_level_value && !pinfo->fd->flags.visited) {
+ /*
+ * No handle attached to this frame, but it's the first
+ * pass, so it'd be attached to the conversation.
+ * If we have a conversation, try to get the handle,
+ * and if we get one, attach it to the frame.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+
+ if (conversation) {
+ next_level_value = conversation_get_proto_data(conversation,
+ proto_spnego);
+ if (next_level_value)
+ p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
+ }
+ }
+
+ item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
+ -1, FALSE);
+
+ subtree = proto_item_add_subtree(item, ett_spnego);
+
+ /*
+ * The TVB contains a [0] header and a sequence that consists of an
+ * object ID and a blob containing the data ...
+ * XXX - is this RFC 2743's "Mechanism-Independent Token Format",
+ * with the "optional" "use in non-initial tokens" being chosen.
+ */
+
+ asn1_open(&hnd, tvb, offset);
+
+ /*
+ * Get the first header ...
+ */
+
+ ret = asn1_header_decode(&hnd, &cls, &con, &tag, &def, &len1);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, subtree,
+ "SPNEGO context header", ret);
+ return_offset = tvb_length(tvb);
+ goto done;
+ }
+
+ if (!(cls == ASN1_APL && con == ASN1_CON && tag == 0)) {
+ proto_tree_add_text(
+ subtree, tvb, offset, 0,
+ "Unknown header (cls=%d, con=%d, tag=%d)",
+ cls, con, tag);
+ return_offset = tvb_length(tvb);
+ goto done;
+ }
+
+ offset = hnd.offset;
+
+ /*
+ * Get the OID, and find the handle, if any
+ */
+
+ ret = asn1_oid_decode(&hnd, &oid, &oid_len, &nbytes);
+
+ if (ret != ASN1_ERR_NOERROR) {
+ dissect_parse_error(tvb, offset, pinfo, tree,
+ "SPNEGO wrap token", ret);
+ return_offset = tvb_length(tvb);
+ goto done;
+ }
+
+ oid_string = format_oid(oid, oid_len);
+ next_level_value = gssapi_lookup_oid(oid, oid_len);
+
+ /*
+ * XXX - what should we do if this doesn't match the value
+ * attached to the frame or conversation? (That would be
+ * bogus, but that's not impossible - some broken implementation
+ * might negotiate some security mechanism but put the OID
+ * for some other security mechanism in GSS_Wrap tokens.)
+ */
+ if (next_level_value)
+ proto_tree_add_text(tree, tvb, offset, nbytes,
+ "thisMech: %s (%s)",
+ oid_string, next_level_value->comment);
+ else
+ proto_tree_add_text(tree, tvb, offset, nbytes, "thisMech: %s",
+ oid_string);
+
+ g_free(oid_string);
+
+ offset += nbytes;
+
+ /*
+ * Now dissect the GSS_Wrap token; it's assumed to be in the
+ * rest of the tvbuff.
+ */
+ item = proto_tree_add_item(tree, hf_spnego_wraptoken, tvb, offset,
+ -1, FALSE);
+
+ subtree = proto_item_add_subtree(item, ett_spnego_wraptoken);
+
+ /*
+ * Now, we should be able to dispatch after creating a new TVB.
+ * The subdissector must return the length of the part of the
+ * token it dissected, so we can return the length of the part
+ * we (and it) dissected.
+ */
+
+ token_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (next_level_value->wrap_handle) {
+ len = call_dissector(next_level_value->wrap_handle, token_tvb, pinfo, subtree);
+ if (len == 0)
+ return_offset = tvb_length(tvb);
+ else
+ return_offset = offset + len;
+ } else
+ return_offset = tvb_length(tvb);
+ done:
+ asn1_close(&hnd, &offset);
+
+ return return_offset;
+}
+
+void
+proto_register_spnego(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_spnego,
+ { "SPNEGO", "spnego", FT_NONE, BASE_NONE, NULL, 0x0,
+ "SPNEGO", HFILL }},
+ { &hf_spnego_negtokeninit,
+ { "negTokenInit", "spnego.negtokeninit", FT_NONE, BASE_NONE,
+ NULL, 0x0, "SPNEGO negTokenInit", HFILL}},
+ { &hf_spnego_negtokentarg,
+ { "negTokenTarg", "spnego.negtokentarg", FT_NONE, BASE_NONE,
+ NULL, 0x0, "SPNEGO negTokenTarg", HFILL}},
+ { &hf_spnego_mechtype,
+ { "mechType", "spnego.negtokeninit.mechtype", FT_NONE,
+ BASE_NONE, NULL, 0x0, "SPNEGO negTokenInit mechTypes", HFILL}},
+ { &hf_spnego_mechtoken,
+ { "mechToken", "spnego.negtokeninit.mechtoken", FT_NONE,
+ BASE_NONE, NULL, 0x0, "SPNEGO negTokenInit mechToken", HFILL}},
+ { &hf_spnego_mechlistmic,
+ { "mechListMIC", "spnego.mechlistmic", FT_NONE,
+ BASE_NONE, NULL, 0x0, "SPNEGO mechListMIC", HFILL}},
+ { &hf_spnego_responsetoken,
+ { "responseToken", "spnego.negtokentarg.responsetoken",
+ FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO responseToken",
+ HFILL}},
+ { &hf_spnego_negtokentarg_negresult,
+ { "negResult", "spnego.negtokeninit.negresult", FT_UINT16,
+ BASE_HEX, VALS(spnego_negResult_vals), 0, "negResult", HFILL}},
+ { &hf_spnego_reqflags,
+ { "reqFlags", "spnego.negtokeninit.reqflags", FT_BYTES,
+ BASE_HEX, NULL, 0, "reqFlags", HFILL }},
+ { &hf_gssapi_reqflags_deleg,
+ { "Delegation", "gssapi.reqflags.deleg", FT_BOOLEAN, 8,
+ TFS(&tfs_reqflags_deleg), 0x01, "Delegation", HFILL }},
+ { &hf_gssapi_reqflags_mutual,
+ { "Mutual Authentication", "gssapi.reqflags.mutual", FT_BOOLEAN,
+ 8, TFS(&tfs_reqflags_mutual), 0x02, "Mutual Authentication", HFILL}},
+ { &hf_gssapi_reqflags_replay,
+ { "Replay Detection", "gssapi.reqflags.replay", FT_BOOLEAN,
+ 8, TFS(&tfs_reqflags_replay), 0x04, "Replay Detection", HFILL}},
+ { &hf_gssapi_reqflags_sequence,
+ { "Out-of-sequence Detection", "gssapi.reqflags.sequence",
+ FT_BOOLEAN, 8, TFS(&tfs_reqflags_sequence), 0x08,
+ "Out-of-sequence Detection", HFILL}},
+ { &hf_gssapi_reqflags_anon,
+ { "Anonymous Authentication", "gssapi.reqflags.anon",
+ FT_BOOLEAN, 8, TFS(&tfs_reqflags_anon), 0x10,
+ "Anonymous Authentication", HFILL}},
+ { &hf_gssapi_reqflags_conf,
+ { "Per-message Confidentiality", "gssapi.reqflags.conf",
+ FT_BOOLEAN, 8, TFS(&tfs_reqflags_conf), 0x20,
+ "Per-message Confidentiality", HFILL}},
+ { &hf_gssapi_reqflags_integ,
+ { "Per-message Integrity", "gssapi.reqflags.integ",
+ FT_BOOLEAN, 8, TFS(&tfs_reqflags_integ), 0x40,
+ "Per-message Integrity", HFILL}},
+ { &hf_spnego_wraptoken,
+ { "wrapToken", "spnego.wraptoken",
+ FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
+ HFILL}},
+ { &hf_spnego_krb5,
+ { "krb5_blob", "spnego.krb5.blob", FT_BYTES,
+ BASE_NONE, NULL, 0, "krb5_blob", HFILL }},
+ { &hf_spnego_krb5_tok_id,
+ { "krb5_tok_id", "spnego.krb5.tok_id", FT_UINT16, BASE_HEX,
+ VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Id", HFILL}},
+ { &hf_spnego_krb5_sgn_alg,
+ { "krb5_sgn_alg", "spnego.krb5.sgn_alg", FT_UINT16, BASE_HEX,
+ VALS(spnego_krb5_sgn_alg_vals), 0, "KRB5 Signing Algorithm", HFILL}},
+ { &hf_spnego_krb5_seal_alg,
+ { "krb5_seal_alg", "spnego.krb5.seal_alg", FT_UINT16, BASE_HEX,
+ VALS(spnego_krb5_seal_alg_vals), 0, "KRB5 Sealing Algorithm", HFILL}},
+ { &hf_spnego_krb5_snd_seq,
+ { "krb5_snd_seq", "spnego.krb5.snd_seq", FT_BYTES, BASE_NONE,
+ NULL, 0, "KRB5 Encrypted Sequence Number", HFILL}},
+ { &hf_spnego_krb5_sgn_cksum,
+ { "krb5_sgn_cksum", "spnego.krb5.sgn_cksum", FT_BYTES, BASE_NONE,
+ NULL, 0, "KRB5 Data Checksum", HFILL}},
+ { &hf_spnego_krb5_confounder,
+ { "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
+ NULL, 0, "KRB5 Confounder", HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_spnego,
+ &ett_spnego_negtokeninit,
+ &ett_spnego_negtokentarg,
+ &ett_spnego_mechtype,
+ &ett_spnego_mechtoken,
+ &ett_spnego_mechlistmic,
+ &ett_spnego_responsetoken,
+ &ett_spnego_wraptoken,
+ &ett_spnego_krb5,
+ };
+
+ proto_spnego = proto_register_protocol(
+ "Spnego", "Spnego", "spnego");
+ proto_spnego_krb5 = proto_register_protocol("SPNEGO-KRB5",
+ "SPNEGO-KRB5",
+ "spnego-krb5");
+
+ proto_register_field_array(proto_spnego, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_spnego(void)
+{
+ dissector_handle_t spnego_handle, spnego_wrap_handle;
+ dissector_handle_t spnego_krb5_handle, spnego_krb5_wrap_handle;
+
+ /* Register protocol with GSS-API module */
+
+ spnego_handle = create_dissector_handle(dissect_spnego, proto_spnego);
+ spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap,
+ proto_spnego);
+ gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
+ spnego_handle, spnego_wrap_handle,
+ "SPNEGO - Simple Protected Negotiation");
+
+ /* Register both the one MS created and the real one */
+ /*
+ * Thanks to Jean-Baptiste Marchand and Richard B Ward, the
+ * mystery of the MS KRB5 OID is cleared up. It was due to a library
+ * that did not handle OID components greater than 16 bits, and was
+ * fixed in Win2K SP2 as well as WinXP.
+ * See the archive of <ietf-krb-wg@anl.gov> for the thread topic
+ * SPNEGO implementation issues. 3-Dec-2002.
+ */
+ spnego_krb5_handle = create_dissector_handle(dissect_spnego_krb5,
+ proto_spnego_krb5);
+ spnego_krb5_wrap_handle = new_create_dissector_handle(dissect_spnego_krb5_wrap,
+ proto_spnego_krb5);
+ gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
+ spnego_krb5_handle, spnego_krb5_wrap_handle,
+ "MS KRB5 - Microsoft Kerberos 5");
+ gssapi_init_oid("1.2.840.113554.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
+ spnego_krb5_handle, spnego_krb5_wrap_handle,
+ "KRB5 - Kerberos 5");
+ gssapi_init_oid("1.2.840.113554.1.2.2.3", proto_spnego_krb5, ett_spnego_krb5,
+ spnego_krb5_handle, spnego_krb5_wrap_handle,
+ "KRB5 - Kerberos 5 - User to User");
+
+ /*
+ * Find the data handle for some calls
+ */
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-spray.c b/epan/dissectors/packet-spray.c
new file mode 100644
index 0000000000..e2b74d3aee
--- /dev/null
+++ b/epan/dissectors/packet-spray.c
@@ -0,0 +1,147 @@
+/* packet-spray.c
+ * 2001 Ronnie Sahlberg <See AUTHORS for email>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-spray.h"
+
+static int proto_spray = -1;
+static int hf_spray_procedure_v1 = -1;
+static int hf_spray_sprayarr = -1;
+static int hf_spray_counter = -1;
+static int hf_spray_clock = -1;
+static int hf_spray_sec = -1;
+static int hf_spray_usec = -1;
+
+static gint ett_spray = -1;
+static gint ett_spray_clock = -1;
+
+
+static int
+dissect_get_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* lock_item = NULL;
+ proto_tree* lock_tree = NULL;
+
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_spray_counter, offset);
+
+ lock_item = proto_tree_add_item(tree, hf_spray_clock, tvb,
+ offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_spray_clock);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_spray_sec, offset);
+
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_spray_usec, offset);
+
+ return offset;
+}
+
+static int
+dissect_spray_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_data(tvb, tree,
+ hf_spray_sprayarr, offset);
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff spray1_proc[] = {
+ { SPRAYPROC_NULL, "NULL",
+ NULL, NULL },
+ { SPRAYPROC_SPRAY, "SPRAY",
+ dissect_spray_call, NULL },
+ { SPRAYPROC_GET, "GET",
+ NULL, dissect_get_reply },
+ { SPRAYPROC_CLEAR, "CLEAR",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string spray1_proc_vals[] = {
+ { SPRAYPROC_NULL, "NULL" },
+ { SPRAYPROC_SPRAY, "SPRAY" },
+ { SPRAYPROC_GET, "GET" },
+ { SPRAYPROC_CLEAR, "CLEAR" },
+ { 0, NULL }
+};
+
+void
+proto_register_spray(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_spray_procedure_v1, {
+ "V1 Procedure", "spray.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(spray1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_spray_sprayarr, {
+ "Data", "spray.sprayarr", FT_BYTES, BASE_DEC,
+ NULL, 0, "Sprayarr data", HFILL }},
+
+ { &hf_spray_counter, {
+ "counter", "spray.counter", FT_UINT32, BASE_DEC,
+ NULL, 0, "Counter", HFILL }},
+
+ { &hf_spray_clock, {
+ "clock", "spray.clock", FT_NONE, BASE_NONE,
+ NULL, 0, "Clock", HFILL }},
+
+ { &hf_spray_sec, {
+ "sec", "spray.sec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Seconds", HFILL }},
+
+ { &hf_spray_usec, {
+ "usec", "spray.usec", FT_UINT32, BASE_DEC,
+ NULL, 0, "Microseconds", HFILL }}
+
+ };
+
+ static gint *ett[] = {
+ &ett_spray,
+ &ett_spray_clock,
+ };
+
+ proto_spray = proto_register_protocol("SPRAY",
+ "SPRAY", "spray");
+ proto_register_field_array(proto_spray, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_spray(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_spray, SPRAY_PROGRAM, ett_spray);
+ /* Register the procedure tables */
+ rpc_init_proc_table(SPRAY_PROGRAM, 1, spray1_proc, hf_spray_procedure_v1);
+}
+
diff --git a/epan/dissectors/packet-spray.h b/epan/dissectors/packet-spray.h
new file mode 100644
index 0000000000..68153ef672
--- /dev/null
+++ b/epan/dissectors/packet-spray.h
@@ -0,0 +1,35 @@
+/* packet-spray.h
+ * 2001 Ronnie Sahlberg <See AUTHORS for email>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_SPRAY_H
+#define PACKET_SPRAY_H
+
+#define SPRAYPROC_NULL 0
+#define SPRAYPROC_SPRAY 1
+#define SPRAYPROC_GET 2
+#define SPRAYPROC_CLEAR 3
+
+#define SPRAY_PROGRAM 100012
+
+#endif
diff --git a/epan/dissectors/packet-srvloc.c b/epan/dissectors/packet-srvloc.c
new file mode 100644
index 0000000000..a5a099b249
--- /dev/null
+++ b/epan/dissectors/packet-srvloc.c
@@ -0,0 +1,1699 @@
+/* packet-srvloc.c
+ * Routines for SRVLOC (Service Location Protocol) packet dissection
+ * Copyright 1999, James Coe <jammer@cin.net>
+ * Copyright 2002, Brad Hards
+ * Updated for TCP segments by Greg Morris <gmorris@novell.com>
+ * Copyright 2003, Greg Morris
+ *
+ * NOTE: This is Alpha software not all features have been verified yet.
+ * In particular I have not had an opportunity to see how it
+ * responds to SRVLOC over TCP.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Service Location Protocol is RFC 2165
+ * Service Location Protocol Version 2 is RFC 2608
+ * - partial support by Brad Hards <bradh@frogmouth.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <time.h>
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "prefs.h"
+#include "packet-tcp.h"
+#include "reassemble.h"
+
+static gboolean srvloc_desegment = TRUE;
+static int proto_srvloc = -1;
+static int hf_srvloc_version = -1;
+static int hf_srvloc_function = -1;
+static int hf_srvloc_pktlen = -1;
+static int hf_srvloc_xid = -1;
+static int hf_srvloc_langtaglen = -1;
+static int hf_srvloc_langtag = -1;
+static int hf_srvloc_nextextoff = -1;
+static int hf_srvloc_flags_v1 = -1;
+static int hf_srvloc_flags_v1_overflow = -1;
+static int hf_srvloc_flags_v1_monolingual = -1;
+static int hf_srvloc_flags_v1_url_auth = -1;
+static int hf_srvloc_flags_v1_attribute_auth = -1;
+static int hf_srvloc_flags_v1_fresh = -1;
+static int hf_srvloc_error = -1;
+static int hf_srvloc_flags_v2 = -1;
+static int hf_srvloc_flags_v2_overflow = -1;
+static int hf_srvloc_flags_v2_fresh = -1;
+static int hf_srvloc_flags_v2_reqmulti = -1;
+static int hf_srvloc_error_v2 = -1;
+static int hf_srvloc_daadvert_timestamp = -1;
+static int hf_srvloc_daadvert_urllen = -1;
+static int hf_srvloc_daadvert_url = -1;
+static int hf_srvloc_daadvert_scopelistlen = -1;
+static int hf_srvloc_daadvert_scopelist = -1;
+static int hf_srvloc_daadvert_attrlistlen = -1;
+static int hf_srvloc_daadvert_attrlist = -1;
+static int hf_srvloc_daadvert_slpspilen = -1;
+static int hf_srvloc_daadvert_slpspi = -1;
+static int hf_srvloc_daadvert_authcount = -1;
+static int hf_srvloc_srvreq_prlistlen = -1;
+static int hf_srvloc_srvreq_prlist = -1;
+static int hf_srvloc_srvreq_srvtypelen = -1;
+static int hf_srvloc_srvreq_srvtypelist = -1;
+static int hf_srvloc_srvreq_scopelistlen = -1;
+static int hf_srvloc_srvreq_scopelist = -1;
+static int hf_srvloc_srvreq_predicatelen = -1;
+static int hf_srvloc_srvreq_predicate = -1;
+static int hf_srvloc_srvreq_slpspilen = -1;
+static int hf_srvloc_srvreq_slpspi = -1;
+static int hf_srvloc_srvrply_urlcount = -1;
+static int hf_srvloc_srvreg_attrlistlen = -1;
+static int hf_srvloc_srvreg_attrlist = -1;
+static int hf_srvloc_srvreg_attrauthcount = -1;
+static int hf_srvloc_srvreg_srvtypelen = -1;
+static int hf_srvloc_srvreg_srvtype = -1;
+static int hf_srvloc_srvreg_scopelistlen = -1;
+static int hf_srvloc_srvreg_scopelist = -1;
+static int hf_srvloc_srvdereg_scopelistlen = -1;
+static int hf_srvloc_srvdereg_scopelist = -1;
+static int hf_srvloc_srvdereg_taglistlen = -1;
+static int hf_srvloc_srvdereg_taglist = -1;
+static int hf_srvloc_attrreq_prlistlen = -1;
+static int hf_srvloc_attrreq_prlist = -1;
+static int hf_srvloc_attrreq_urllen = -1;
+static int hf_srvloc_attrreq_url = -1;
+static int hf_srvloc_attrreq_scopelistlen = -1;
+static int hf_srvloc_attrreq_scopelist = -1;
+static int hf_srvloc_attrreq_attrlistlen = -1;
+static int hf_srvloc_attrreq_attrlist = -1;
+static int hf_srvloc_attrreq_taglistlen = -1;
+static int hf_srvloc_attrreq_taglist = -1;
+static int hf_srvloc_attrreq_slpspilen = -1;
+static int hf_srvloc_attrreq_slpspi = -1;
+static int hf_srvloc_attrrply_attrlistlen = -1;
+static int hf_srvloc_attrrply_attrlist = -1;
+static int hf_srvloc_attrrply_attrauthcount = -1;
+static int hf_srvloc_srvtypereq_prlistlen = -1;
+static int hf_srvloc_srvtypereq_prlist = -1;
+static int hf_srvloc_srvtypereq_nameauthlistlen = -1;
+static int hf_srvloc_srvtypereq_nameauthlistlenall = -1;
+static int hf_srvloc_srvtypereq_nameauthlist = -1;
+static int hf_srvloc_srvtypereq_scopelistlen = -1;
+static int hf_srvloc_srvtypereq_scopelist = -1;
+static int hf_srvloc_srvtyperply_srvtypelen = -1;
+static int hf_srvloc_srvtyperply_srvtype = -1;
+static int hf_srvloc_srvtyperply_srvtypelistlen = -1;
+static int hf_srvloc_srvtyperply_srvtypelist = -1;
+static int hf_srvloc_saadvert_urllen = -1;
+static int hf_srvloc_saadvert_url = -1;
+static int hf_srvloc_saadvert_scopelistlen = -1;
+static int hf_srvloc_saadvert_scopelist = -1;
+static int hf_srvloc_saadvert_attrlistlen = -1;
+static int hf_srvloc_saadvert_attrlist = -1;
+static int hf_srvloc_saadvert_authcount = -1;
+static int hf_srvloc_authblkv2_bsd = -1;
+static int hf_srvloc_authblkv2_len = -1;
+static int hf_srvloc_authblkv2_timestamp = -1;
+static int hf_srvloc_authblkv2_slpspilen = -1;
+static int hf_srvloc_authblkv2_slpspi = -1;
+static int hf_srvloc_url_reserved = -1;
+static int hf_srvloc_url_lifetime = -1;
+static int hf_srvloc_url_urllen = -1;
+static int hf_srvloc_url_url = -1;
+static int hf_srvloc_url_numauths = -1;
+static int hf_srvloc_add_ref_ip = -1;
+
+
+static gint ett_srvloc = -1;
+static gint ett_srvloc_flags = -1;
+
+
+static const true_false_string tfs_srvloc_flags_overflow = {
+ "Message will not fit in datagram",
+ "Message will fit in a datagram"
+};
+static const true_false_string tfs_srvloc_flags_v1_monolingual = {
+ "Only responses in specified language will be accepted",
+ "Responses in any language will be accepted"
+};
+static const true_false_string tfs_srvloc_flags_v1_url_auth = {
+ "URL Authentication Block is present",
+ "URL Authentication Block is absent"
+};
+static const true_false_string tfs_srvloc_flags_v1_attribute_auth = {
+ "Attribute Authentication Block is present",
+ "Attribute Authentication Block is absent"
+};
+static const true_false_string tfs_srvloc_flags_fresh = {
+ "New Service Registration",
+ "Not a new Service Registration"
+};
+static const true_false_string tfs_srvloc_flags_v2_reqmulti = {
+ "Multicast (or broadcast) request",
+ "Not multicast or broadcast"
+};
+
+#define TCP_PORT_SRVLOC 427
+#define UDP_PORT_SRVLOC 427
+
+/* Define function types */
+
+#define SRVREQ 1
+#define SRVRPLY 2
+#define SRVREG 3
+#define SRVDEREG 4
+#define SRVACK 5
+#define ATTRRQST 6
+#define ATTRRPLY 7
+#define DAADVERT 8
+#define SRVTYPERQST 9
+#define SRVTYPERPLY 10
+#define SAADVERT 11 /* SLPv2, section 8 */
+
+/* Create protocol header structure */
+
+/* bradh: looks like never used. */
+/* bradh: comment it out for now since it doesn't work for v2
+struct srvloc_hdr {
+ guint8 version;
+ guint8 function;
+ guint16 length;
+ guint8 flags;
+ guint8 dialect;
+ guchar language[2];
+ guint16 encoding;
+ guint16 xid;
+};
+*/
+
+/* List to resolve function numbers to names */
+
+static const value_string srvloc_functions[] = {
+ { SRVREQ, "Service Request" },
+ { SRVRPLY, "Service Reply" },
+ { SRVREG, "Service Registration" },
+ { SRVDEREG, "Service Deregister" },
+ { SRVACK, "Service Acknowledge" },
+ { ATTRRQST, "Attribute Request" },
+ { ATTRRPLY, "Attribute Reply" },
+ { DAADVERT, "DA Advertisement" },
+ { SRVTYPERQST, "Service Type Request" },
+ { SRVTYPERPLY, "Service Type Reply" },
+ { SAADVERT, "SA Advertisement" }, /* v2 only */
+ { 0, NULL }
+};
+
+/* List to resolve flag values to names */
+
+
+/* Define flag masks */
+
+#define FLAG_O 0x80
+#define FLAG_M 0x40
+#define FLAG_U 0x20
+#define FLAG_A 0x10
+#define FLAG_F 0x08
+
+/* it all changes for Version 2 */
+#define FLAG_O_V2 0x8000
+#define FLAG_F_V2 0x4000
+#define FLAG_R_V2 0x2000
+
+/* Define Error Codes - Version 1*/
+
+#define SUCCESS 0
+#define LANG_NOT_SPTD 1
+#define PROT_PARSE_ERR 2
+#define INVLD_REG 3
+#define SCOPE_NOT_SPTD 4
+#define CHRSET_NOT_UND 5
+#define AUTH_ABSENT 6
+#define AUTH_FAILED 7
+
+/* List to resolve error codes to names */
+
+static const value_string srvloc_errs[] = {
+ { SUCCESS, "No Error" },
+ { LANG_NOT_SPTD, "Language not supported" },
+ { PROT_PARSE_ERR, "Protocol parse error" },
+ { INVLD_REG, "Invalid registration" },
+ { SCOPE_NOT_SPTD, "Scope not supported" },
+ { CHRSET_NOT_UND, "Character set not understood" },
+ { AUTH_ABSENT, "Authentication absent" },
+ { AUTH_FAILED, "Authentication failed" },
+ { 0, NULL }
+};
+
+/* Define Error Codes for Version 2 */
+
+#define LANGUAGE_NOT_SUPPORTED 1
+#define PARSE_ERROR 2
+#define INVALID_REGISTRATION 3
+#define SCOPE_NOT_SUPPORTED 4
+#define AUTHENTICATION_UNKNOWN 5
+#define AUTHENTICATION_ABSENT 6
+#define AUTHENTICATION_FAILED 7
+#define VER_NOT_SUPPORTED 9
+#define INTERNAL_ERROR 10
+#define DA_BUSY_NOW 11
+#define OPTION_NOT_UNDERSTOOD 12
+#define INVALID_UPDATE 13
+#define MSG_NOT_SUPPORTED 14
+#define REFRESH_REJECTED 15
+
+static const value_string srvloc_errs_v2[] = {
+ { SUCCESS, "No Error" },
+ { LANGUAGE_NOT_SUPPORTED, "No data in the requested language" },
+ { PARSE_ERROR, "The message fails to obey SLP syntax." },
+ { INVALID_REGISTRATION, "The SrvReg has problems" },
+ { SCOPE_NOT_SUPPORTED, "Scope list not supported" },
+ { AUTHENTICATION_UNKNOWN, "Unsupported SLP SPI." },
+ { AUTHENTICATION_ABSENT, "URL and ATTR authentication not provided"},
+ { AUTHENTICATION_FAILED, "Authentication error"},
+ { VER_NOT_SUPPORTED, "Unsupported version number in message header" },
+ { INTERNAL_ERROR, "The DA (or SA) is too sick to respond" },
+ { DA_BUSY_NOW, "UA or SA SHOULD retry" },
+ { OPTION_NOT_UNDERSTOOD, "Unknown option from the mandatory range"},
+ { INVALID_UPDATE, "Invalid SrvReg" },
+ { MSG_NOT_SUPPORTED, "No support for AttrRqst or SrvTypeRqst" },
+ { REFRESH_REJECTED, "SrvReg sent too soon"},
+ { 0, NULL }
+};
+
+/*
+ * Character encodings.
+ * This is a small subset of what's in
+ *
+ * http://www.iana.org/assignments/character-sets
+ *
+ * XXX - we should do something useful with this, i.e. properly
+ * handle strings based on the character set they're in.
+ *
+ * XXX - what does "properly handle strings" mean? How do we know
+ * what character set the terminal can handle (for tty-based code)
+ * or the GUI can handle (for GUI code)?
+ *
+ * XXX - the Ethereal core really should be what does all the
+ * character set handling for strings, and it should be stuck with
+ * the task of figuring out how to properly handle them.
+ */
+#define CHARSET_ASCII 3
+#define CHARSET_ISO_10646_UTF_1 27
+#define CHARSET_ISO_646_BASIC 28
+#define CHARSET_ISO_646_IRV 30
+#define CHARSET_ISO_8859_1 4
+#define CHARSET_ISO_10646_UCS_2 1000 /* a/k/a Unicode */
+#define CHARSET_UTF_7 1012
+#define CHARSET_UTF_8 106
+
+static const value_string charsets[] = {
+ { CHARSET_ASCII, "US-ASCII" },
+ { CHARSET_ISO_10646_UTF_1, "ISO 10646 UTF-1" },
+ { CHARSET_ISO_646_BASIC, "ISO 646 basic:1983" },
+ { CHARSET_ISO_646_IRV, "ISO 646 IRV:1983" },
+ { CHARSET_ISO_8859_1, "ISO 8859-1" },
+ { CHARSET_ISO_10646_UCS_2, "Unicode" },
+ { CHARSET_UTF_7, "UTF-7" },
+ { CHARSET_UTF_8, "UTF-8" },
+ { 0, NULL }
+};
+
+static int
+dissect_authblk(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ struct tm *stamp;
+ time_t seconds;
+ double floatsec;
+ guint16 length;
+
+ seconds = tvb_get_ntohl(tvb, offset) - 2208988800ul;
+ stamp = gmtime(&seconds);
+ if (stamp != NULL) {
+ floatsec = stamp->tm_sec + tvb_get_ntohl(tvb, offset + 4) / 4294967296.0;
+ proto_tree_add_text(tree, tvb, offset, 8,
+ "Timestamp: %04d-%02d-%02d %02d:%02d:%07.4f UTC",
+ stamp->tm_year + 1900, stamp->tm_mon + 1,
+ stamp->tm_mday, stamp->tm_hour, stamp->tm_min,
+ floatsec);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 8, "Timestamp not representable");
+ }
+ proto_tree_add_text(tree, tvb, offset + 8, 2, "Block Structure Desciptor: %u",
+ tvb_get_ntohs(tvb, offset + 8));
+ length = tvb_get_ntohs(tvb, offset + 10);
+ proto_tree_add_text(tree, tvb, offset + 10, 2, "Authenticator length: %u",
+ length);
+ offset += 12;
+ proto_tree_add_text(tree, tvb, offset, length, "Authentication block: %s",
+ tvb_format_text(tvb, offset, length));
+ offset += length;
+ return offset;
+}
+
+/* SLPv2 version - Needs to be fixed to match RFC2608 sect 9.2*/
+static int
+dissect_authblk_v2(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint16 length;
+
+ proto_tree_add_item(tree, hf_srvloc_authblkv2_bsd, tvb, offset, 2, FALSE);
+ proto_tree_add_item(tree, hf_srvloc_authblkv2_len, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(tree, hf_srvloc_authblkv2_timestamp, tvb, offset+4, 4, FALSE);
+ length = tvb_get_ntohs(tvb, offset + 8);
+ proto_tree_add_uint(tree, hf_srvloc_authblkv2_slpspilen, tvb, offset + 8, 2, length);
+ offset += 10;
+ proto_tree_add_item(tree, hf_srvloc_authblkv2_slpspi, tvb, offset, length, TRUE);
+ offset += length;
+ /* add code in here to handle Structured Authentication Block */
+ return offset;
+}
+
+static int
+dissect_attrauthblk_v2(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ tvb=tvb; tree=tree; /* silence gcc for now */
+ /* add code in here to handle attribute authentication */
+ return offset;
+}
+
+static void
+add_v1_string(proto_tree *tree, int hf, tvbuff_t *tvb, int offset, int length,
+ guint16 encoding)
+{
+ char *unicode_str;
+
+ switch (encoding) {
+
+ case CHARSET_ISO_10646_UCS_2:
+ unicode_str = tvb_fake_unicode(tvb, offset, length/2, FALSE);
+ proto_tree_add_string(tree, hf, tvb, offset, length,
+ unicode_str);
+ g_free(unicode_str);
+ break;
+
+ default:
+ proto_tree_add_item(tree, hf, tvb, offset, length, TRUE);
+ break;
+ }
+}
+
+static guint8*
+unicode_to_bytes(tvbuff_t *tvb, int offset, int length, gboolean endianness)
+{
+ const char *ascii_text = tvb_get_ptr(tvb, offset, length);
+ guint8 i, j=0;
+ guint8 c_char, c_char1;
+ static guint8 byte_array[255];
+
+ if (endianness) {
+ for (i = length; i > 0; i--) {
+ c_char = ascii_text[i];
+ if (c_char != 0) {
+ i--;
+ c_char1 = ascii_text[i];
+ if (c_char1 == 0) {
+ i--;
+ c_char1 = ascii_text[i];
+ }
+ byte_array[j] = c_char1;
+ j++;
+ byte_array[j] = c_char;
+ j++;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < length; i++) {
+ c_char = ascii_text[i];
+ if (c_char != 0) {
+ byte_array[j] = c_char;
+ j++;
+ }
+ }
+ }
+
+ byte_array[j]=0;
+ return byte_array;
+}
+
+/*
+ * Format of x-x-x-xxxxxxxx. Each of these entries represents the service binding to UDP, TCP, or IPX.
+ * The first digit is the protocol family: 2 for TCP/UPD, 6 for IPX.
+ * The second digit is the socket type: 1 for socket stream (TCP), 2 for datagram (UDP and IPX).
+ * The third is the protocol: 6 for TCP, 17 for UDP, and 1000 for IPX.
+ * Last is the IP address, in hex, of the interface that is registered (or, in the case of IPX, an IPX network number).
+*/
+static void
+attr_list(proto_tree *tree, int hf, tvbuff_t *tvb, int offset, int length,
+ guint16 encoding)
+{
+ char *attr_type;
+ int i, svc, ss, type_len, foffset=offset;
+ guint32 prot;
+ guint8 *byte_value;
+ proto_item *ti;
+ proto_tree *srvloc_tree;
+
+ static const value_string srvloc_svc[] = {
+ { 50, "TCP/UDP" },
+ { 54, "IPX" },
+ { 0, NULL }
+ };
+
+ static const value_string srvloc_ss[] = {
+ { 49, "Socket" },
+ { 50, "Datagram" },
+ { 0, NULL }
+ };
+
+ static const value_string srvloc_prot[] = {
+ { 54, "TCP" },
+ { 17, "UDP" },
+ { 1000, "IPX" },
+ { 0, NULL }
+ };
+
+ switch (encoding) {
+
+ case CHARSET_ISO_10646_UCS_2:
+
+ type_len = strcspn(tvb_fake_unicode(tvb, offset, length/2, FALSE), "=");
+ attr_type = tvb_fake_unicode(tvb, offset+2, type_len-1, FALSE);
+ proto_tree_add_string(tree, hf, tvb, offset, type_len*2, attr_type);
+ i=1;
+ for (foffset = offset + ((type_len*2)+2); foffset<length; foffset += 2) {
+
+ ti = proto_tree_add_text(tree, tvb, foffset, -1, "Item %d", i);
+ srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
+
+ svc = tvb_get_guint8(tvb, foffset+1);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+1, 1,
+ "Service Type: %s", val_to_str(svc, srvloc_svc, "Unknown"));
+ ss = tvb_get_guint8(tvb, foffset+5);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+5, 1,
+ "Communication Type: %s", val_to_str(ss, srvloc_ss, "Unknown"));
+ foffset += 9;
+ if (svc == 50) {
+ if (tvb_get_guint8(tvb, foffset)==54) { /* TCP */
+ prot = tvb_get_guint8(tvb, foffset);
+ proto_tree_add_text(srvloc_tree, tvb, foffset, 1,
+ "Protocol: %s", val_to_str(prot, srvloc_prot, "Unknown"));
+ foffset += 2;
+ }
+ else
+ {
+ byte_value = unicode_to_bytes(tvb, foffset, 4, FALSE); /* UDP */
+ prot = atol(byte_value);
+ proto_tree_add_text(srvloc_tree, tvb, foffset, 4,
+ "Protocol: %s", val_to_str(prot, srvloc_prot, "Unknown"));
+ foffset += 4;
+ }
+ }
+ else
+ {
+ byte_value = unicode_to_bytes(tvb, foffset, 8, FALSE); /* IPX */
+ prot = atol(byte_value);
+ proto_tree_add_text(srvloc_tree, tvb, foffset, 8,
+ "Protocol: %s", val_to_str(prot, srvloc_prot, "Unknown"));
+ foffset += 8;
+ }
+ if (svc == 50) {
+ byte_value = unicode_to_bytes(tvb, foffset, 16, TRUE); /* IP Address */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_ipv4(srvloc_tree, hf_srvloc_add_ref_ip, tvb, foffset+2, 16, prot);
+ byte_value = unicode_to_bytes(tvb, foffset+18, 8, FALSE); /* Port */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+18, 8, "Port: %d", prot);
+ }
+ else
+ {
+ byte_value = unicode_to_bytes(tvb, foffset+2, 16, FALSE); /* IPX Network Address */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+2, 16, "Network: %s", byte_value);
+ byte_value = unicode_to_bytes(tvb, foffset+18, 24, FALSE); /* IPX Node Address */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+18, 24, "Node: %s", byte_value);
+ byte_value = unicode_to_bytes(tvb, foffset+42, 8, FALSE); /* Socket */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+42, 8, "Socket: %s", byte_value);
+ }
+ i++;
+ foffset += 57;
+ }
+ break;
+
+ case CHARSET_UTF_8:
+ type_len = strcspn(tvb_get_ptr(tvb, offset, length), "=");
+ attr_type = unicode_to_bytes(tvb, offset+1, type_len-1, FALSE);
+ proto_tree_add_string(tree, hf, tvb, offset+1, type_len-1, attr_type);
+ i=1;
+ for (foffset = offset + (type_len); foffset<length; foffset++) {
+
+ ti = proto_tree_add_text(tree, tvb, foffset, -1, "Item %d", i);
+ srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
+
+ svc = tvb_get_guint8(tvb, foffset+1);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+1, 1,
+ "Service Type: %s", val_to_str(svc, srvloc_svc, "Unknown"));
+ ss = tvb_get_guint8(tvb, foffset+3);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+3, 1,
+ "Communication Type: %s", val_to_str(ss, srvloc_ss, "Unknown"));
+ foffset += 5;
+ if (svc == 50) {
+ if (tvb_get_guint8(tvb, foffset)==54) { /* TCP */
+ prot = tvb_get_guint8(tvb, foffset);
+ proto_tree_add_text(srvloc_tree, tvb, foffset, 1,
+ "Protocol: %s", val_to_str(prot, srvloc_prot, "Unknown"));
+ foffset += 1;
+ }
+ else
+ {
+ /* UDP */
+ byte_value = unicode_to_bytes(tvb, foffset, 2, FALSE); /* UDP */
+ prot = atol(byte_value);
+ proto_tree_add_text(srvloc_tree, tvb, foffset, 2,
+ "Protocol: %s", val_to_str(prot, srvloc_prot, "Unknown"));
+ foffset += 2;
+ }
+ }
+ else
+ {
+ byte_value = unicode_to_bytes(tvb, foffset, 4, FALSE); /* IPX */
+ prot = atol(byte_value);
+ proto_tree_add_text(srvloc_tree, tvb, foffset, 4,
+ "Protocol: %s", val_to_str(prot, srvloc_prot, "Unknown"));
+ foffset += 4;
+ }
+ if (svc == 50) {
+ byte_value = unicode_to_bytes(tvb, foffset, 8, TRUE); /* IP Address */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_ipv4(srvloc_tree, hf_srvloc_add_ref_ip, tvb, foffset+1, 8, prot);
+ byte_value = unicode_to_bytes(tvb, foffset+9, 4, FALSE); /* Port */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+9, 4, "Port: %d", prot);
+ }
+ else
+ {
+ byte_value = unicode_to_bytes(tvb, foffset+1, 8, FALSE); /* IPX Network Address */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+1, 8, "Network: %s", byte_value);
+ byte_value = unicode_to_bytes(tvb, foffset+9, 12, FALSE); /* IPX Node Address */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+9, 12, "Node: %s", byte_value);
+ byte_value = unicode_to_bytes(tvb, foffset+21, 4, FALSE); /* Socket */
+ sscanf(byte_value,"%x",&prot);
+ proto_tree_add_text(srvloc_tree, tvb, foffset+21, 4, "Socket: %s", byte_value);
+ }
+ i++;
+ foffset += 28;
+ }
+ break;
+
+
+ default:
+ proto_tree_add_item(tree, hf, tvb, offset, length, TRUE);
+ break;
+ }
+}
+
+static int
+dissect_url_entry_v1(tvbuff_t *tvb, int offset, proto_tree *tree,
+ guint16 encoding, guint16 flags)
+{
+ guint16 url_len;
+
+ proto_tree_add_item(tree, hf_srvloc_url_lifetime, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ url_len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2,
+ url_len);
+ offset += 2;
+ add_v1_string(tree, hf_srvloc_url_url, tvb, offset, url_len, encoding);
+ offset += url_len;
+ if ( (flags & FLAG_U) == FLAG_U )
+ offset = dissect_authblk(tvb, offset, tree);
+ return offset;
+}
+
+static int
+dissect_url_entry_v2(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint8 reserved;
+ guint16 url_len;
+ guint8 num_auths;
+
+ reserved = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_srvloc_url_reserved, tvb, offset, 1,
+ reserved);
+ offset += 1;
+ proto_tree_add_item(tree, hf_srvloc_url_lifetime, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ url_len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2,
+ url_len);
+ offset += 2;
+ proto_tree_add_item(tree, hf_srvloc_url_url, tvb, offset, url_len, TRUE);
+ offset += url_len;
+ num_auths = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_srvloc_url_numauths, tvb, offset, 1,
+ num_auths);
+ offset += 1;
+ while (num_auths > 0) {
+ offset = dissect_authblk_v2(tvb, offset, tree);
+ num_auths--;
+ }
+ return offset;
+}
+
+/* Packet dissection routine called by tcp & udp when port 427 detected */
+
+static void
+dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_item *ti, *tf;
+ proto_tree *srvloc_tree, *srvloc_flags;
+ guint8 version;
+ guint8 function;
+ guint16 encoding;
+ guint32 length; /* three bytes needed for v2 */
+ guint16 flags; /* two byes needed for v2 */
+ guint32 count;
+ guint32 next_ext_off; /* three bytes, v2 only */
+ guint16 lang_tag_len;
+ nstime_t ts;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SRVLOC");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ version = tvb_get_guint8(tvb, offset);
+ function = tvb_get_guint8(tvb, offset + 1);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(function, srvloc_functions, "Unknown Function (%u)"));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_srvloc, tvb, offset, -1, FALSE);
+ srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
+
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_version, tvb, offset, 1,
+ version);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_function, tvb, offset + 1, 1,
+ function);
+ if (version < 2) {
+ length = tvb_get_ntohs(tvb, offset + 2);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_pktlen, tvb, offset + 2, 2,
+ length);
+ flags = tvb_get_guint8(tvb, offset + 4);
+ tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags_v1, tvb, offset + 4, 1,
+ flags);
+ srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
+ proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_overflow,
+ tvb, offset+4, 1, flags);
+ proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_monolingual,
+ tvb, offset+4, 1, flags);
+ proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_url_auth,
+ tvb, offset+4, 1, flags);
+ proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_attribute_auth,
+ tvb, offset+4, 1, flags);
+ proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_fresh,
+ tvb, offset+4, 1, flags);
+ proto_tree_add_text(srvloc_tree, tvb, offset + 5, 1, "Dialect: %u",
+ tvb_get_guint8(tvb, offset + 5));
+ proto_tree_add_text(srvloc_tree, tvb, offset + 6, 2, "Language: %s",
+ tvb_format_text(tvb, offset + 6, 2));
+ encoding = tvb_get_ntohs(tvb, offset + 8);
+ proto_tree_add_text(srvloc_tree, tvb, offset + 8, 2, "Encoding: %u (%s)",
+ encoding,
+ val_to_str(encoding, charsets, "Unknown"));
+ proto_tree_add_text(srvloc_tree, tvb, offset + 10, 2, "Transaction ID: %u",
+ tvb_get_ntohs(tvb, offset + 10));
+ offset += 12;
+
+ switch (function) {
+ case SRVREQ:
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_prlistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_srvreq_prlist, tvb, offset, length, encoding);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_predicatelen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_srvreq_predicate, tvb, offset, length, encoding);
+ offset += length;
+ break;
+
+ case SRVRPLY:
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
+ offset += 2;
+ count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvrply_urlcount, tvb, offset, 2, count);
+ offset += 2;
+ while (count > 0) {
+ offset = dissect_url_entry_v1(tvb, offset, srvloc_tree,
+ encoding, flags);
+ count--;
+ };
+ break;
+
+ case SRVREG:
+ offset = dissect_url_entry_v1(tvb, offset, srvloc_tree, encoding,
+ flags);
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrlistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_srvreg_attrlist, tvb, offset, length, encoding);
+ offset += length;
+ if ( (flags & FLAG_A) == FLAG_A )
+ offset = dissect_authblk(tvb, offset, srvloc_tree);
+ break;
+
+ case SRVDEREG:
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(tree, hf_srvloc_url_url, tvb, offset, length, encoding);
+ offset += length;
+ if ( (flags & FLAG_U) == FLAG_U )
+ offset = dissect_authblk(tvb, offset, srvloc_tree);
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_taglistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_srvdereg_taglist, tvb, offset, length, encoding);
+ offset += length;
+ /*
+ * XXX - this was there before, but RFC 2165 doesn't speak
+ * of there being an attribute authentication block in
+ * a Service Deregister message. Is that a post-RFC-2165
+ * addition?
+ */
+ if ( (flags & FLAG_A) == FLAG_A )
+ offset = dissect_authblk(tvb, offset, srvloc_tree);
+ break;
+
+ case SRVACK:
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+
+ case ATTRRQST:
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_prlistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_attrreq_prlist, tvb, offset, length, encoding);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_urllen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_attrreq_url, tvb, offset, length, encoding);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_attrreq_scopelist, tvb, offset, length, encoding);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_attrlistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_attrreq_attrlist, tvb, offset, length, encoding);
+ offset += length;
+ break;
+
+ case ATTRRPLY:
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
+ offset += 2;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrlistlen, tvb, offset, 2, length);
+ if (length > 0) {
+ offset += 2;
+ attr_list(srvloc_tree, hf_srvloc_attrrply_attrlist, tvb, offset, length, encoding);
+ offset += length;
+ if ( (flags & FLAG_A) == FLAG_A )
+ offset = dissect_authblk(tvb, offset, srvloc_tree);
+ }
+ break;
+
+ case DAADVERT:
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
+ offset += 2;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_urllen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_daadvert_url, tvb, offset, length, encoding);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_daadvert_scopelist, tvb, offset, length, encoding);
+ offset += length;
+ break;
+
+ case SRVTYPERQST:
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_prlistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_srvtypereq_prlist, tvb, offset, length, encoding);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ /* Updated by Greg Morris on 1-30-04 */
+ if (0xFFFF == length) {
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlenall, tvb, offset, 2, length);
+ offset += 2;
+ }
+ else
+ {
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_srvtypereq_nameauthlist, tvb, offset, length, encoding);
+ offset += length;
+ }
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_srvtypereq_scopelist, tvb, offset, length, encoding);
+ offset += length;
+ break;
+
+ case SRVTYPERPLY:
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
+ offset += 2;
+ count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type Count: %u",
+ count);
+ offset += 2;
+ while (count > 0) {
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtyperply_srvtypelen, tvb, offset, 2, length);
+ offset += 2;
+ add_v1_string(srvloc_tree, hf_srvloc_srvtyperply_srvtype, tvb, offset, length, encoding);
+ offset += length;
+ count--;
+ };
+ break;
+
+ default:
+ proto_tree_add_text(srvloc_tree, tvb, offset, -1, "Unknown Function Type");
+ };
+ }
+ else { /* Version 2 */
+ length = tvb_get_ntoh24(tvb, offset + 2);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_pktlen, tvb, offset + 2, 3,
+ length);
+ flags = tvb_get_ntohs(tvb, offset + 5);
+ tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags_v2, tvb, offset + 5, 2,
+ flags);
+ srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
+ proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v2_overflow,
+ tvb, offset+5, 1, flags);
+ proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v2_fresh,
+ tvb, offset+5, 1, flags);
+ proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v2_reqmulti,
+ tvb, offset+5, 1, flags);
+
+ next_ext_off = tvb_get_ntoh24(tvb, offset + 7);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_nextextoff, tvb, offset + 7, 3,
+ next_ext_off);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_xid, tvb, offset + 10, 2,
+ tvb_get_ntohs(tvb, offset + 10));
+ lang_tag_len = tvb_get_ntohs(tvb, offset + 12);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_langtaglen, tvb, offset + 12, 2, lang_tag_len);
+ proto_tree_add_item(srvloc_tree, hf_srvloc_langtag, tvb, offset + 14, lang_tag_len, TRUE);
+ offset += 14+lang_tag_len;
+
+ switch (function) {
+ case SRVREQ: /* RFC2608 8.1 */
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_prlistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_prlist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_srvtypelen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_srvtypelist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_scopelist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_predicatelen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_predicate, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_slpspilen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_slpspi, tvb, offset, length, TRUE);
+ offset += length;
+ break;
+
+ case SRVRPLY: /* RFC2608 8.2 */
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
+ offset += 2;
+ count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvrply_urlcount, tvb, offset, 2, count);
+ offset += 2;
+ while (count > 0) {
+ offset = dissect_url_entry_v2(tvb, offset, srvloc_tree);
+ count--;
+ };
+ break;
+
+ case SRVREG: /* RFC2608 8.3 */
+ offset = dissect_url_entry_v2(tvb, offset, srvloc_tree);
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_srvtypelen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_srvtype, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_scopelist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrlistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_attrlist, tvb, offset, length, TRUE);
+ offset += length;
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrauthcount, tvb, offset, 1, count);
+ offset += 1;
+ while (count > 0) {
+ offset = dissect_attrauthblk_v2(tvb, offset, srvloc_tree);
+ count--;
+ }
+ break;
+
+ case SRVDEREG: /* RFC2608 10.6 */
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvdereg_scopelist, tvb, offset, length, TRUE);
+ offset += length;
+ offset = dissect_url_entry_v2(tvb, offset, srvloc_tree);
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_taglistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvdereg_taglist, tvb, offset, length, TRUE);
+ offset += length;
+ break;
+
+ case SRVACK: /* RFC2608 8.4 */
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
+ offset += 2;
+ break;
+
+ case ATTRRQST: /* RFC2608 10.3*/
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_prlistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_prlist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_urllen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_url, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_scopelist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_taglistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_taglist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_slpspilen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_slpspi, tvb, offset, length, TRUE);
+ offset += length;
+ break;
+
+ case ATTRRPLY: /* RFC2608 10.4 */
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
+ offset += 2;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrlistlen, tvb, offset, 2, length);
+ if (length > 0) {
+ offset += 2;
+ attr_list(srvloc_tree, hf_srvloc_attrrply_attrlist, tvb, offset, length, CHARSET_UTF_8);
+ offset += length;
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrauthcount, tvb, offset, 1, count);
+ offset += 1;
+ while (count > 0) {
+ offset = dissect_attrauthblk_v2(tvb, offset, srvloc_tree);
+ count--;
+ }
+ }
+ break;
+
+ case DAADVERT: /* RCC 2608 8.5 */
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
+ offset += 2;
+ ts.nsecs = 0;
+ ts.secs = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_time(srvloc_tree, hf_srvloc_daadvert_timestamp, tvb, offset, 4,
+ &ts);
+ offset += 4;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_urllen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_url, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_scopelist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_attrlistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_attrlist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_slpspilen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_slpspi, tvb, offset, length, TRUE);
+ offset += length;
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_authcount, tvb, offset, 1, count);
+ offset += 1;
+ while (count > 0) {
+ offset = dissect_authblk_v2(tvb, offset, srvloc_tree);
+ count--;
+ }
+ break;
+
+ case SRVTYPERQST: /* RFC2608 10.1 */
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_prlistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_prlist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ if (0xFFFF == length) {
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlenall, tvb, offset, 2, length);
+ offset += 2;
+ } else {
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_nameauthlist, tvb, offset, length, TRUE);
+ offset += length;
+ }
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_scopelist, tvb, offset, length, TRUE);
+ offset += length;
+ break;
+
+ case SRVTYPERPLY: /* rfc2608 10.2 */
+ proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
+ offset += 2;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtyperply_srvtypelistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_srvtyperply_srvtypelist, tvb, offset, length, TRUE);
+ break;
+
+ case SAADVERT: /* rfc2608 10.2 */
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_urllen, tvb, offset, 2,
+ length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_url, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_scopelistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_scopelist, tvb, offset, length, TRUE);
+ offset += length;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_attrlistlen, tvb, offset, 2, length);
+ offset += 2;
+ proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_attrlist, tvb, offset, length, TRUE);
+ offset += length;
+ count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_authcount, tvb, offset, 1, length);
+ offset += 1;
+ while (count > 0) {
+ offset = dissect_authblk_v2(tvb, offset, srvloc_tree);
+ count--;
+ }
+ break;
+
+ default:
+ proto_tree_add_text(srvloc_tree, tvb, offset, -1, "Unknown Function Type");
+ };
+ };
+ }
+}
+
+static guint
+get_srvloc_pdu_len(tvbuff_t *tvb, int offset)
+{
+ /*
+ * Get the length of the SRVLOC packet.
+ * It starts at offset+2, but it's 2 bytes in SLPv1 and 3 bytes
+ * in SLPv2.
+ */
+ if (tvb_get_guint8(tvb, offset) == 2)
+ return tvb_get_ntoh24(tvb, offset + 2);
+ else
+ return tvb_get_ntohs(tvb, offset + 2);
+}
+
+static void
+dissect_srvloc_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *srvloc_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SRVLOC");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_srvloc, tvb, 0, -1, FALSE);
+ srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
+ }
+ dissect_srvloc(tvb, pinfo, srvloc_tree);
+}
+
+static void
+dissect_srvloc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /*
+ * XXX - in SLPv1, the fixed length need only be 4, as the length
+ * is 2 bytes long; however, it must be 5 for SLPv2, as the length
+ * is 3 bytes long, and there's probably no harm in asking for 5
+ * bytes, as even SLPv1 packets start with a 12-byte header,
+ * and if the packet has a length that's 4 or less, it's bogus,
+ * and we can't handle a length < 4 anyway.
+ */
+ tcp_dissect_pdus(tvb, pinfo, tree, srvloc_desegment, 5, get_srvloc_pdu_len,
+ dissect_srvloc_pdu);
+}
+
+/* Register protocol with Ethereal. */
+
+void
+proto_register_srvloc(void)
+{
+ static hf_register_info hf[] = {
+ /* Helper functions for the Version 1 Header*/
+ {&hf_srvloc_error,
+ {"Error Code", "srvloc.err",
+ FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0,
+ "", HFILL }
+ },
+
+ /* Helper function for the Version 2 Header */
+ {&hf_srvloc_error_v2,
+ {"Error Code", "srvloc.errv2",
+ FT_UINT16, BASE_DEC, VALS(srvloc_errs_v2), 0x0,
+ "", HFILL }
+ },
+ {&hf_srvloc_xid,
+ {"XID", "srvloc.xid",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Transaction ID", HFILL }
+ },
+ {&hf_srvloc_langtag,
+ {"Lang Tag", "srvloc.langtag",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ {&hf_srvloc_langtaglen,
+ {"Lang Tag Len", "srvloc.langtaglen",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+ {&hf_srvloc_nextextoff,
+ {"Next Extension Offset", "srvloc.nextextoff",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+
+ /* Helper functions for URL and URL Entry parsing - both versions */
+ {&hf_srvloc_url_reserved,
+ {"Reserved", "srvloc.url.reserved",
+ FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ {&hf_srvloc_url_lifetime,
+ {"URL lifetime", "srvloc.url.lifetime",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ {&hf_srvloc_url_urllen,
+ {"URL Length", "srvloc.url.urllen",
+ FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ {&hf_srvloc_url_url,
+ {"URL", "srvloc.url.url",
+ FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ {&hf_srvloc_url_numauths,
+ {"Num Auths", "srvloc.url.numauths",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+
+ /* Helper functions for the common header fields */
+ {&hf_srvloc_function,
+ {"Function", "srvloc.function",
+ FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0,
+ "", HFILL }
+ },
+
+ {&hf_srvloc_pktlen,
+ {"Packet Length", "srvloc.pktlen",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+
+ { &hf_srvloc_version,
+ { "Version", "srvloc.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }
+ },
+
+ {&hf_srvloc_flags_v1,
+ {"Flags", "srvloc.flags_v1",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ },
+
+ { &hf_srvloc_flags_v1_overflow,
+ { "Overflow", "srvloc.flags_v1.overflow.", FT_BOOLEAN, 8,
+ TFS(&tfs_srvloc_flags_overflow), FLAG_O, "Can whole packet fit into a datagram?", HFILL }},
+
+ { &hf_srvloc_flags_v1_monolingual,
+ { "Monolingual", "srvloc.flags_v1.monolingual", FT_BOOLEAN, 8,
+ TFS(&tfs_srvloc_flags_v1_monolingual), FLAG_M, "Can whole packet fit into a datagram?", HFILL }},
+
+ { &hf_srvloc_flags_v1_url_auth,
+ { "URL Authentication", "srvloc.flags_v1.url_auth", FT_BOOLEAN, 8,
+ TFS(&tfs_srvloc_flags_v1_url_auth), FLAG_U, "Can whole packet fit into a datagram?", HFILL }},
+
+ { &hf_srvloc_flags_v1_attribute_auth,
+ { "Attribute Authentication", "srvloc.flags_v1.attribute_auth", FT_BOOLEAN, 8,
+ TFS(&tfs_srvloc_flags_v1_attribute_auth), FLAG_A, "Can whole packet fit into a datagram?", HFILL }},
+
+ { &hf_srvloc_flags_v1_fresh,
+ { "Fresh Registration", "srvloc.flags_v1.fresh", FT_BOOLEAN, 8,
+ TFS(&tfs_srvloc_flags_fresh), FLAG_F, "Is this a new registration?", HFILL }},
+
+ {&hf_srvloc_flags_v2,
+ {"Flags", "srvloc.flags_v2",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }
+ },
+
+ { &hf_srvloc_flags_v2_overflow,
+ { "Overflow", "srvloc.flags_v2.overflow", FT_BOOLEAN, 16,
+ TFS(&tfs_srvloc_flags_overflow), FLAG_O_V2, "Can whole packet fit into a datagram?", HFILL }},
+
+ { &hf_srvloc_flags_v2_fresh,
+ { "Fresh Registration", "srvloc.flags_v2.fresh", FT_BOOLEAN, 16,
+ TFS(&tfs_srvloc_flags_fresh), FLAG_F_V2, "Is this a new registration?", HFILL }},
+
+ { &hf_srvloc_flags_v2_reqmulti,
+ { "Multicast requested", "srvloc.flags_v2.reqmulti", FT_BOOLEAN, 16,
+ TFS(&tfs_srvloc_flags_v2_reqmulti), FLAG_R_V2, "Do we want multicast?", HFILL }},
+
+ /* collection of helper functions for dissect_authblk_v2 */
+ { &hf_srvloc_authblkv2_bsd,
+ { "BSD", "srvloc.authblkv2_bsd", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Block Structure Descriptor", HFILL}
+ },
+ { &hf_srvloc_authblkv2_len,
+ { "Length", "srvloc.authblkv2_len", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of Authentication Block", HFILL}
+ },
+ { &hf_srvloc_authblkv2_timestamp,
+ { "Timestamp", "srvloc.authblkv2.timestamp", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Timestamp on Authentication Block", HFILL }
+ },
+ { &hf_srvloc_authblkv2_slpspilen,
+ { "SLP SPI Length", "srvloc.authblkv2.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the SLP SPI", HFILL}
+ },
+ { &hf_srvloc_authblkv2_slpspi,
+ { "SLP SPI", "srvloc.authblkv2.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+
+ /* collection of helper functions for Service Request */
+ { &hf_srvloc_srvreq_prlistlen,
+ { "Previous Response List Length", "srvloc.srvreq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of Previous Response List", HFILL}
+ },
+ { &hf_srvloc_srvreq_prlist,
+ { "Previous Response List", "srvloc.srvreq.prlist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Previous Response List", HFILL}
+ },
+ { &hf_srvloc_srvreq_srvtypelen,
+ { "Service Type Length", "srvloc.srvreq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of Service Type List", HFILL}
+ },
+ { &hf_srvloc_srvreq_srvtypelist,
+ { "Service Type List", "srvloc.srvreq.srvtypelist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvreq_scopelistlen,
+ { "Scope List Length", "srvloc.srvreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Scope List", HFILL}
+ },
+ { &hf_srvloc_srvreq_scopelist,
+ { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvreq_predicatelen,
+ { "Predicate Length", "srvloc.srvreq.predicatelen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Predicate", HFILL}
+ },
+ { &hf_srvloc_srvreq_predicate,
+ { "Predicate", "srvloc.srvreq.predicate", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvreq_slpspilen,
+ { "SLP SPI Length", "srvloc.srvreq.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the SLP SPI", HFILL}
+ },
+ { &hf_srvloc_srvreq_slpspi,
+ { "SLP SPI", "srvloc.srvreq.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+
+ /* Helper function for Service Request */
+ { &hf_srvloc_srvrply_urlcount,
+ { "Number of URLs", "srvloc.srvreq.urlcount", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+
+ /* Helper functions for Service Registration */
+ { &hf_srvloc_srvreg_srvtypelen,
+ { "Service Type Length", "srvloc.srvreq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvreg_srvtype,
+ { "Service Type", "srvloc.srvreq.srvtype", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvreg_scopelistlen,
+ { "Scope List Length", "srvloc.srvreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvreg_scopelist,
+ { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvreg_attrlistlen,
+ { "Attribute List Length", "srvloc.srvreq.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvreg_attrlist,
+ { "Attribute List", "srvloc.srvreq.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvreg_attrauthcount,
+ { "Attr Auths", "srvloc.srvreq.attrauthcount", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of Attribute Authentication Blocks", HFILL}
+ },
+
+ /* Helper functions for Service Deregistration */
+ { &hf_srvloc_srvdereg_scopelistlen,
+ { "Scope List Length", "srvloc.srvdereq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvdereg_scopelist,
+ { "Scope List", "srvloc.srvdereq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvdereg_taglistlen,
+ { "Tag List Length", "srvloc.srvdereq.taglistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvdereg_taglist,
+ { "Tag List", "srvloc.srvdereq.taglist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+
+
+ /* collection of helper functions for Attribute Request */
+ { &hf_srvloc_attrreq_prlistlen,
+ { "Previous Response List Length", "srvloc.attrreq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of Previous Response List", HFILL}
+ },
+ { &hf_srvloc_attrreq_prlist,
+ { "Previous Response List", "srvloc.attrreq.prlist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Previous Response List", HFILL}
+ },
+ { &hf_srvloc_attrreq_urllen,
+ { "URL Length", "srvloc.attrreq.urllen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_attrreq_url,
+ { "Service URL", "srvloc.attrreq.url", FT_STRING, BASE_NONE, NULL, 0x0,
+ "URL of service", HFILL}
+ },
+ { &hf_srvloc_attrreq_scopelistlen,
+ { "Scope List Length", "srvloc.attrreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Scope List", HFILL}
+ },
+ { &hf_srvloc_attrreq_scopelist,
+ { "Scope List", "srvloc.attrreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_attrreq_attrlistlen,
+ { "Attribute List Length", "srvloc.attrreq.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_attrreq_attrlist,
+ { "Attribute List", "srvloc.attrreq.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_attrreq_taglistlen,
+ { "Tag List Length", "srvloc.attrreq.taglistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_attrreq_taglist,
+ { "Tag List", "srvloc.attrreq.taglist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_attrreq_slpspilen,
+ { "SLP SPI Length", "srvloc.attrreq.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the SLP SPI", HFILL}
+ },
+ { &hf_srvloc_attrreq_slpspi,
+ { "SLP SPI", "srvloc.attrreq.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+
+ /* collection of helper functions for Attribute Reply */
+ { &hf_srvloc_attrrply_attrlistlen,
+ { "Attribute List Length", "srvloc.attrrply.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of Attribute List", HFILL}
+ },
+ { &hf_srvloc_attrrply_attrlist,
+ { "Attribute List", "srvloc.attrrply.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_attrrply_attrauthcount,
+ { "Attr Auths", "srvloc.srvreq.attrauthcount", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of Attribute Authentication Blocks", HFILL}
+ },
+
+ /* collection of helper functions for DA Advertisement */
+ { &hf_srvloc_daadvert_timestamp,
+ { "DAADVERT Timestamp", "srvloc.daadvert.timestamp", FT_ABSOLUTE_TIME, BASE_NONE,
+ NULL, 0, "Timestamp on DA Advert", HFILL }
+ },
+ { &hf_srvloc_daadvert_urllen,
+ { "URL Length", "srvloc.daadvert.urllen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_daadvert_url,
+ { "URL", "srvloc.daadvert.url", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_daadvert_scopelistlen,
+ { "Scope List Length", "srvloc.daadvert.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Scope List", HFILL}
+ },
+ { &hf_srvloc_daadvert_scopelist,
+ { "Scope List", "srvloc.daadvert.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_daadvert_attrlistlen,
+ { "Attribute List Length", "srvloc.daadvert.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_daadvert_attrlist,
+ { "Attribute List", "srvloc.daadvert.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_daadvert_slpspilen,
+ { "SLP SPI Length", "srvloc.daadvert.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the SLP SPI", HFILL}
+ },
+ { &hf_srvloc_daadvert_slpspi,
+ { "SLP SPI", "srvloc.daadvert.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_daadvert_authcount,
+ { "Auths", "srvloc.daadvert.authcount", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of Authentication Blocks", HFILL}
+ },
+
+ /* collection of helper functions for Service Type Request */
+ { &hf_srvloc_srvtypereq_prlistlen,
+ { "Previous Response List Length", "srvloc.srvtypereq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of Previous Response List", HFILL}
+ },
+ { &hf_srvloc_srvtypereq_prlist,
+ { "Previous Response List", "srvloc.srvtypereq.prlist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "Previous Response List", HFILL}
+ },
+ { &hf_srvloc_srvtypereq_nameauthlistlen,
+ { "Naming Authority List Length", "srvloc.srvtypereq.nameauthlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Naming Authority List", HFILL}
+ },
+ { &hf_srvloc_srvtypereq_nameauthlistlenall,
+ { "Naming Authority List Length (All Naming Authorities)", "srvloc.srvtypereq.nameauthlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Naming Authority List", HFILL}
+ },
+ { &hf_srvloc_srvtypereq_nameauthlist,
+ { "Naming Authority List", "srvloc.srvtypereq.nameauthlist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvtypereq_scopelistlen,
+ { "Scope List Length", "srvloc.srvtypereq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Scope List", HFILL}
+ },
+ { &hf_srvloc_srvtypereq_scopelist,
+ { "Scope List", "srvloc.srvtypereq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+
+ /* collection of helper functions for Service Type Replies */
+ { &hf_srvloc_srvtyperply_srvtypelen,
+ { "Service Type Length", "srvloc.srvtypereq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Service Type", HFILL}
+ },
+ { &hf_srvloc_srvtyperply_srvtype,
+ { "Service Type", "srvloc.srvtyperply.srvtype", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_srvtyperply_srvtypelistlen,
+ { "Service Type List Length", "srvloc.srvtypereq.srvtypelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Service Type List", HFILL}
+ },
+ { &hf_srvloc_srvtyperply_srvtypelist,
+ { "Service Type List", "srvloc.srvtyperply.srvtypelist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+
+ /* collection of helper functions for SA Advertisement */
+ { &hf_srvloc_saadvert_urllen,
+ { "URL Length", "srvloc.saadvert.urllen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_saadvert_url,
+ { "URL", "srvloc.saadvert.url", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_saadvert_scopelistlen,
+ { "Scope List Length", "srvloc.saadvert.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of the Scope List", HFILL}
+ },
+ { &hf_srvloc_saadvert_scopelist,
+ { "Scope List", "srvloc.saadvert.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_saadvert_attrlistlen,
+ { "Attribute List Length", "srvloc.saadvert.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_saadvert_attrlist,
+ { "Attribute List", "srvloc.saadvert.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL}
+ },
+ { &hf_srvloc_saadvert_authcount,
+ { "Auths", "srvloc.saadvert.authcount", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of Authentication Blocks", HFILL}
+ },
+ { &hf_srvloc_add_ref_ip,
+ { "IP Address", "srvloc.list.ipaddr", FT_IPv4, BASE_DEC, NULL, 0x0,
+ "IP Address of SLP server", HFILL}
+ }
+ };
+
+ static gint *ett[] = {
+ &ett_srvloc,
+ &ett_srvloc_flags,
+ };
+ module_t *srvloc_module;
+
+ proto_srvloc = proto_register_protocol("Service Location Protocol",
+ "SRVLOC", "srvloc");
+ proto_register_field_array(proto_srvloc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ srvloc_module = prefs_register_protocol(proto_srvloc, NULL);
+ prefs_register_bool_preference(srvloc_module, "desegment_tcp",
+ "Desegment all SRVLOC messages spanning multiple TCP segments",
+ "Whether the SRVLOC dissector should desegment all messages spanning multiple TCP segments",
+ &srvloc_desegment);
+}
+
+void
+proto_reg_handoff_srvloc(void)
+{
+ dissector_handle_t srvloc_handle, srvloc_tcp_handle;
+ srvloc_handle = create_dissector_handle(dissect_srvloc, proto_srvloc);
+ dissector_add("udp.port", UDP_PORT_SRVLOC, srvloc_handle);
+ srvloc_tcp_handle = create_dissector_handle(dissect_srvloc_tcp,
+ proto_srvloc);
+ dissector_add("tcp.port", TCP_PORT_SRVLOC, srvloc_tcp_handle);
+}
diff --git a/epan/dissectors/packet-sscop.c b/epan/dissectors/packet-sscop.c
new file mode 100644
index 0000000000..ae048ecf36
--- /dev/null
+++ b/epan/dissectors/packet-sscop.c
@@ -0,0 +1,332 @@
+/* packet-sscop.c
+ * Routines for SSCOP (Q.2110, Q.SAAL) frame disassembly
+ * Guy Harris <guy@alum.mit.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+
+static int proto_sscop = -1;
+
+static gint ett_sscop = -1;
+
+static dissector_handle_t q2931_handle;
+static dissector_handle_t data_handle;
+
+/*
+ * See
+ *
+ * http://www.protocols.com/pbook/atmsig.htm
+ *
+ * for some information on SSCOP, although, alas, not the actual PDU
+ * type values - those I got from the FreeBSD 3.2 ATM code.
+ */
+
+/*
+ * SSCOP PDU types.
+ */
+#define SSCOP_TYPE_MASK 0x0f
+
+#define SSCOP_BGN 0x01 /* Begin */
+#define SSCOP_BGAK 0x02 /* Begin Acknowledge */
+#define SSCOP_BGREJ 0x07 /* Begin Reject */
+#define SSCOP_END 0x03 /* End */
+#define SSCOP_ENDAK 0x04 /* End Acknowledge */
+#define SSCOP_RS 0x05 /* Resynchronization */
+#define SSCOP_RSAK 0x06 /* Resynchronization Acknowledge */
+#define SSCOP_SD 0x08 /* Sequenced Data */
+#define SSCOP_SDP 0x09 /* Sequenced Data with Poll */
+#define SSCOP_POLL 0x0a /* Status Request */
+#define SSCOP_STAT 0x0b /* Solicited Status Response */
+#define SSCOP_USTAT 0x0c /* Unsolicited Status Response */
+#define SSCOP_UD 0x0d /* Unnumbered Data */
+#define SSCOP_MD 0x0e /* Management Data */
+#define SSCOP_ER 0x09 /* Error Recovery */
+#define SSCOP_ERAK 0x0f /* Error Acknowledge */
+
+#define SSCOP_S 0x10 /* Source bit in End PDU */
+
+/*
+ * XXX - how to distinguish SDP from ER?
+ */
+static const value_string sscop_type_vals[] = {
+ { SSCOP_BGN, "Begin" },
+ { SSCOP_BGAK, "Begin Acknowledge" },
+ { SSCOP_BGREJ, "Begin Reject" },
+ { SSCOP_END, "End" },
+ { SSCOP_ENDAK, "End Acknowledge" },
+ { SSCOP_RS, "Resynchronization" },
+ { SSCOP_RSAK, "Resynchronization Acknowledge" },
+ { SSCOP_SD, "Sequenced Data" },
+#if 0
+ { SSCOP_SDP, "Sequenced Data with Poll" },
+#endif
+ { SSCOP_POLL, "Status Request" },
+ { SSCOP_STAT, "Solicited Status Response" },
+ { SSCOP_USTAT, "Unsolicited Status Response" },
+ { SSCOP_UD, "Unnumbered Data" },
+ { SSCOP_MD, "Management Data" },
+ { SSCOP_ER, "Error Recovery" },
+ { SSCOP_ERAK, "Error Acknowledge" },
+ { 0, NULL }
+};
+
+/*
+ * The SSCOP "header" is a trailer, so the "offsets" are computed based
+ * on the length of the packet.
+ */
+
+/*
+ * PDU type.
+ */
+#define SSCOP_PDU_TYPE (reported_length - 4) /* single byte */
+
+/*
+ * Begin PDU, Begin Acknowledge PDU (no N(SQ) in it), Resynchronization
+ * PDU, Resynchronization Acknowledge PDU (no N(SQ) in it in Q.SAAL),
+ * Error Recovery PDU, Error Recovery Acknoledge PDU (no N(SQ) in it).
+ */
+#define SSCOP_N_SQ (reported_length - 5) /* One byte */
+#define SSCOP_N_MR (reported_length - 4) /* lower 3 bytes thereof */
+
+/*
+ * Sequenced Data PDU (no N(PS) in it), Sequenced Data with Poll PDU,
+ * Poll PDU.
+ */
+#define SSCOP_N_PS (reported_length - 8) /* lower 3 bytes thereof */
+#define SSCOP_N_S (reported_length - 4) /* lower 3 bytes thereof */
+
+/*
+ * Solicited Status PDU, Unsolicited Status PDU (no N(PS) in it).
+ */
+#define SSCOP_SS_N_PS (reported_length - 12) /* lower 3 bytes thereof */
+#define SSCOP_SS_N_MR (reported_length - 8) /* lower 3 bytes thereof */
+#define SSCOP_SS_N_R (reported_length - 4) /* lower 3 bytes thereof */
+
+static void
+dissect_sscop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint reported_length;
+ proto_item *ti;
+ proto_tree *sscop_tree = NULL;
+ guint8 sscop_pdu_type;
+ guint8 pdu_type;
+ int pdu_len;
+ int pad_len;
+ tvbuff_t *next_tvb;
+
+ reported_length = tvb_reported_length(tvb); /* frame length */
+ sscop_pdu_type = tvb_get_guint8(tvb, SSCOP_PDU_TYPE);
+ pdu_type = sscop_pdu_type & SSCOP_TYPE_MASK;
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSCOP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pdu_type, sscop_type_vals,
+ "Unknown PDU type (0x%02x)"));
+
+ /*
+ * Find the length of the PDU and, if there's any payload and
+ * padding, the length of the padding.
+ */
+ switch (pdu_type) {
+
+ case SSCOP_SD:
+ pad_len = (sscop_pdu_type >> 6) & 0x03;
+ pdu_len = 4;
+ break;
+
+ case SSCOP_BGN:
+ case SSCOP_BGAK:
+ case SSCOP_BGREJ:
+ case SSCOP_END:
+ case SSCOP_RS:
+#if 0
+ case SSCOP_SDP:
+#endif
+ pad_len = (sscop_pdu_type >> 6) & 0x03;
+ pdu_len = 8;
+ break;
+
+ case SSCOP_UD:
+ pad_len = (sscop_pdu_type >> 6) & 0x03;
+ pdu_len = 4;
+ break;
+
+ default:
+ pad_len = 0;
+ pdu_len = reported_length; /* No payload, just SSCOP */
+ break;
+ }
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_sscop, tvb,
+ reported_length - pdu_len,
+ pdu_len, "SSCOP");
+ sscop_tree = proto_item_add_subtree(ti, ett_sscop);
+
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_PDU_TYPE, 1,
+ "PDU Type: %s",
+ val_to_str(pdu_type, sscop_type_vals,
+ "Unknown (0x%02x)"));
+
+ switch (pdu_type) {
+
+ case SSCOP_BGN:
+ case SSCOP_RS:
+ case SSCOP_ER:
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_N_SQ, 1,
+ "N(SQ): %u", tvb_get_guint8(tvb, SSCOP_N_SQ));
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_N_MR + 1, 3,
+ "N(MR): %u", tvb_get_ntohl(tvb, SSCOP_N_MR) & 0xFFFFFF);
+ break;
+
+ case SSCOP_END:
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_PDU_TYPE, 1,
+ "Source: %s", (sscop_pdu_type & SSCOP_S) ? "SSCOP" : "User");
+ break;
+
+ case SSCOP_BGAK:
+ case SSCOP_RSAK:
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_N_MR + 1, 3,
+ "N(MR): %u", tvb_get_ntohl(tvb, SSCOP_N_MR) & 0xFFFFFF);
+ break;
+
+ case SSCOP_ERAK:
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_N_MR + 3, 3,
+ "N(MR): %u", tvb_get_ntohl(tvb, SSCOP_N_MR) & 0xFFFFFF);
+ break;
+
+ case SSCOP_SD:
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_N_S + 1, 3,
+ "N(S): %u", tvb_get_ntohl(tvb, SSCOP_N_S) & 0xFFFFFF);
+ break;
+
+#if 0
+ case SSCOP_SDP:
+#endif
+ case SSCOP_POLL:
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_N_PS + 1, 3,
+ "N(PS): %u", tvb_get_ntohl(tvb, SSCOP_N_PS) & 0xFFFFFF);
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_N_S + 1, 3,
+ "N(S): %u", tvb_get_ntohl(tvb, SSCOP_N_S) & 0xFFFFFF);
+ break;
+
+ case SSCOP_STAT:
+ /*
+ * XXX - dissect the list elements....
+ */
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_SS_N_PS + 1, 3,
+ "N(PS): %u", tvb_get_ntohl(tvb, SSCOP_SS_N_PS) & 0xFFFFFF);
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_SS_N_MR + 1, 3,
+ "N(MR): %u", tvb_get_ntohl(tvb, SSCOP_SS_N_MR) & 0xFFFFFF);
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_SS_N_R + 1, 3,
+ "N(R): %u", tvb_get_ntohl(tvb, SSCOP_SS_N_R) & 0xFFFFFF);
+ break;
+
+ case SSCOP_USTAT:
+ /*
+ * XXX - dissect the list elements....
+ */
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_SS_N_MR + 1, 3,
+ "N(MR): %u", tvb_get_ntohl(tvb, SSCOP_SS_N_MR) & 0xFFFFFF);
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_SS_N_R + 1, 3,
+ "N(R): %u", tvb_get_ntohl(tvb, SSCOP_SS_N_R) & 0xFFFFFF);
+ break;
+ }
+ }
+
+ /*
+ * Dissect the payload, if any.
+ *
+ * XXX - what about a Management Data PDU?
+ */
+ switch (pdu_type) {
+
+ case SSCOP_SD:
+ case SSCOP_UD:
+ case SSCOP_BGN:
+ case SSCOP_BGAK:
+ case SSCOP_BGREJ:
+ case SSCOP_END:
+ case SSCOP_RS:
+#if 0
+ case SSCOP_SDP:
+#endif
+ if (tree) {
+ proto_tree_add_text(sscop_tree, tvb, SSCOP_PDU_TYPE, 1,
+ "Pad length: %u", pad_len);
+ }
+
+ /*
+ * Compute length of data in PDU - subtract the trailer length
+ * and the pad length from the reported length.
+ */
+ reported_length -= (pdu_len + pad_len);
+
+ /*
+ * XXX - if more than just Q.2931 uses SSCOP, we need to tell
+ * SSCOP what dissector to use here.
+ */
+ if (reported_length != 0) {
+ /*
+ * We know that we have all of the payload, because we know we have
+ * at least 4 bytes of data after the payload, i.e. the SSCOP trailer.
+ * Therefore, we know that the captured length of the payload is
+ * equal to the length of the payload.
+ */
+ next_tvb = tvb_new_subset(tvb, 0, reported_length, reported_length);
+ if (pdu_type == SSCOP_SD)
+ call_dissector(q2931_handle, next_tvb, pinfo, tree);
+ else
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ }
+ break;
+ }
+}
+
+void
+proto_register_sscop(void)
+{
+ static gint *ett[] = {
+ &ett_sscop,
+ };
+ proto_sscop = proto_register_protocol("SSCOP", "SSCOP", "sscop");
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("sscop", dissect_sscop, proto_sscop);
+}
+
+void
+proto_reg_handoff_sscop(void)
+{
+ /*
+ * Get handle for the Q.2931 dissector.
+ */
+ q2931_handle = find_dissector("q2931");
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-ssh.c b/epan/dissectors/packet-ssh.c
new file mode 100644
index 0000000000..9cc34d3b6f
--- /dev/null
+++ b/epan/dissectors/packet-ssh.c
@@ -0,0 +1,940 @@
+/* packet-ssh.c
+ * Routines for ssh packet dissection
+ *
+ * Huagang XIE <huagang@intruvert.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-mysql.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Note: support SSH v1 and v2 now.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include "packet-smb-common.h"
+#include "packet-tcp.h"
+#include "reassemble.h"
+#include "prefs.h"
+
+/* get from openssh ssh2.h */
+#define SSH2_MSG_DISCONNECT 1
+#define SSH2_MSG_IGNORE 2
+#define SSH2_MSG_UNIMPLEMENTED 3
+#define SSH2_MSG_DEBUG 4
+#define SSH2_MSG_SERVICE_REQUEST 5
+#define SSH2_MSG_SERVICE_ACCEPT 6
+
+/* transport layer: alg negotiation */
+
+#define SSH2_MSG_KEXINIT 20
+#define SSH2_MSG_NEWKEYS 21
+
+/* transport layer: kex specific messages, can be reused */
+
+#define SSH2_MSG_KEXDH_INIT 30
+#define SSH2_MSG_KEXDH_REPLY 31
+
+/*
+#define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30
+#define SSH2_MSG_KEX_DH_GEX_GROUP 31
+*/
+#define SSH2_MSG_KEX_DH_GEX_INIT 32
+#define SSH2_MSG_KEX_DH_GEX_REPLY 33
+#define SSH2_MSG_KEX_DH_GEX_REQUEST 34
+
+/* SSH Version 1 definition , from openssh ssh1.h */
+
+#define SSH_MSG_NONE 0 /* no message */
+#define SSH_MSG_DISCONNECT 1 /* cause (string) */
+#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
+#define SSH_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
+#define SSH_CMSG_USER 4 /* user (string) */
+
+
+#define SSH_VERSION_UNKNOWN 0
+#define SSH_VERSION_1 1
+#define SSH_VERSION_2 2
+
+/* proto data */
+
+struct ssh_pdu_data{
+ guint counter;
+ guint number;
+};
+
+struct ssh_flow_data {
+ guint req_counter;
+ guint rsp_counter;
+ guint version;
+};
+static GMemChunk *ssh_this_data=NULL;
+static GMemChunk *ssh_global_data = NULL;
+
+static int proto_ssh = -1;
+static int hf_ssh_packet_length= -1;
+static int hf_ssh_padding_length= -1;
+static int hf_ssh_payload= -1;
+static int hf_ssh_protocol= -1;
+static int hf_ssh_encrypted_packet= -1;
+static int hf_ssh_padding_string= -1;
+static int hf_ssh_mac_string= -1;
+static int hf_ssh_msg_code = -1;
+static int hf_ssh_cookie = -1;
+static int hf_ssh_kex_algorithms = -1;
+static int hf_ssh_server_host_key_algorithms = -1;
+static int hf_ssh_encryption_algorithms_client_to_server = -1;
+static int hf_ssh_encryption_algorithms_server_to_client = -1;
+static int hf_ssh_mac_algorithms_client_to_server=-1;
+static int hf_ssh_mac_algorithms_server_to_client=-1;
+static int hf_ssh_compression_algorithms_client_to_server=-1;
+static int hf_ssh_compression_algorithms_server_to_client=-1;
+static int hf_ssh_languages_client_to_server=-1;
+static int hf_ssh_languages_server_to_client=-1;
+static int hf_ssh_kex_algorithms_length= -1;
+static int hf_ssh_server_host_key_algorithms_length= -1;
+static int hf_ssh_encryption_algorithms_client_to_server_length= -1;
+static int hf_ssh_encryption_algorithms_server_to_client_length= -1;
+static int hf_ssh_mac_algorithms_client_to_server_length= -1;
+static int hf_ssh_mac_algorithms_server_to_client_length= -1;
+static int hf_ssh_compression_algorithms_client_to_server_length= -1;
+static int hf_ssh_compression_algorithms_server_to_client_length= -1;
+static int hf_ssh_languages_client_to_server_length= -1;
+static int hf_ssh_languages_server_to_client_length= -1;
+
+static gint ett_ssh = -1;
+static gint ett_key_exchange= -1;
+static gint ett_key_init= -1;
+static gint ett_ssh1= -1;
+static gint ett_ssh2= -1;
+
+static gboolean ssh_desegment = TRUE;
+
+#define TCP_PORT_SSH 22
+
+static const value_string ssh2_msg_vals[] = {
+ {SSH2_MSG_DISCONNECT, "Disconnect"},
+ {SSH2_MSG_IGNORE, "Ignore"},
+ {SSH2_MSG_UNIMPLEMENTED, "Unimplemented"},
+ {SSH2_MSG_DEBUG, "Debug"},
+ {SSH2_MSG_SERVICE_REQUEST, "Service Request"},
+ {SSH2_MSG_SERVICE_ACCEPT, "Service Accept"},
+ {SSH2_MSG_KEXINIT, "Key Exchange Init"},
+ {SSH2_MSG_NEWKEYS, "New Keys"},
+ {SSH2_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init"},
+ {SSH2_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply"},
+ {SSH2_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman GEX Init"},
+ {SSH2_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman GEX Reply"},
+ {SSH2_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman GEX Request"},
+ { 0, NULL }
+};
+
+static const value_string ssh1_msg_vals[] = {
+ {SSH_MSG_NONE,"No Message"},
+ {SSH_MSG_DISCONNECT, "Disconnect"},
+ {SSH_SMSG_PUBLIC_KEY,"Public Key"},
+ {SSH_CMSG_SESSION_KEY,"Session Key"},
+ {SSH_CMSG_USER,"User"},
+};
+
+
+static const value_string ssh_opcode_vals[] = {
+ { 0, NULL }
+};
+
+static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree);
+
+static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree,int is_response,
+ int number, gboolean *need_desegmentation);
+static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree,int is_response,
+ int number, gboolean *need_desegmentation );
+static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree,int is_response,
+ int number, gboolean *need_desegmentation );
+static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree,int is_response,int *version,
+ gboolean *need_desegmentation);
+static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree,int is_response);
+proto_item * ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, gboolean little_endian);
+
+static void
+ssh_init_protocol(void)
+{
+ if (ssh_global_data)
+ g_mem_chunk_destroy(ssh_global_data);
+ if (ssh_this_data)
+ g_mem_chunk_destroy(ssh_this_data);
+
+ ssh_global_data = g_mem_chunk_new("ssh_global_datas",
+ sizeof(struct ssh_flow_data),
+ 100* sizeof(struct ssh_flow_data), G_ALLOC_AND_FREE);
+ ssh_this_data = g_mem_chunk_new("ssh_pku_data",
+ sizeof(struct ssh_pdu_data),
+ 100* sizeof(struct ssh_pdu_data), G_ALLOC_AND_FREE);
+
+}
+
+static void
+dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ proto_tree *ssh_tree = NULL;
+ proto_item *ti;
+ conversation_t *conversation=NULL;
+ gint remain_length;
+ int last_offset;
+ guint this_number,number;
+
+ int offset = 0;
+
+ gboolean is_response;
+ gboolean is_newdata;
+ gboolean need_desegmentation;
+ guint version;
+
+ struct ssh_pdu_data *this_data=NULL;
+ struct ssh_flow_data *global_data=NULL;
+
+ is_newdata = FALSE;
+ this_data = p_get_proto_data(pinfo->fd, proto_ssh);
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if (!conversation) {
+ /* create a new conversation */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+
+ global_data = conversation_get_proto_data(conversation,proto_ssh);
+ if(!global_data ) {
+ global_data = g_mem_chunk_alloc(ssh_global_data);
+ global_data->req_counter=0;
+ global_data->rsp_counter=0;
+ global_data->version=SSH_VERSION_UNKNOWN;
+ conversation_add_proto_data(conversation,proto_ssh,global_data);
+ }
+
+/*
+ * end of attaching data
+ */
+ if (pinfo->destport == pinfo->match_port) {
+ is_response=FALSE;
+ if(!this_data) {
+ this_data = g_mem_chunk_alloc(ssh_this_data);
+ this_data->counter = global_data->req_counter++;
+ p_add_proto_data(pinfo->fd, proto_ssh, this_data);
+ is_newdata = TRUE;
+ }
+ }else {
+ is_response=TRUE;
+ if(!this_data) {
+ this_data = g_mem_chunk_alloc(ssh_global_data);
+ this_data->counter = global_data->rsp_counter++;
+ p_add_proto_data(pinfo->fd, proto_ssh, this_data);
+ is_newdata = TRUE;
+ }
+ }
+ if(tree) {
+ ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, FALSE);
+ ssh_tree = proto_item_add_subtree(ti, ett_ssh);
+ }
+ number = 0;
+
+ version = global_data->version;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ switch(version) {
+ case SSH_VERSION_UNKNOWN:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
+ break;
+ case SSH_VERSION_1:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
+ break;
+ case SSH_VERSION_2:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
+ break;
+
+ }
+ }
+
+ if(this_data->counter != 0 && version == SSH_VERSION_UNKNOWN) {
+ offset = ssh_dissect_encrypted_packet(tvb, pinfo,
+ offset,ssh_tree,is_response);
+ return;
+ }
+
+ while((remain_length = tvb_reported_length_remaining(tvb,offset))> 0 ) {
+ need_desegmentation = FALSE;
+ last_offset = offset;
+ this_number = this_data->counter+number;
+
+ if(number > 1 && is_newdata) {
+ /* update the this_data and flow_data */
+ if(is_response) {
+ global_data->rsp_counter++;
+ } else {
+ global_data->req_counter++;
+ }
+ }
+
+ number++;
+ if(this_number == 0) {
+ offset = ssh_dissect_protocol(tvb, pinfo,
+ offset,ssh_tree, is_response,
+ &version, &need_desegmentation);
+ if(!is_response) {
+ global_data->version= version;
+ }
+ } else {
+ switch(version) {
+
+ case SSH_VERSION_UNKNOWN:
+ /*
+ * We use "tvb_ensure_length_remaining()"
+ * to make sure there actually *is* data
+ * remaining.
+ *
+ * This means we're guaranteed that
+ * "remain_length" is positive.
+ */
+ remain_length = tvb_ensure_length_remaining(tvb,
+ offset);
+ proto_tree_add_text(ssh_tree, tvb, offset,
+ remain_length,
+ "Unknown SSH version data");
+ offset += remain_length;
+ break;
+
+ case SSH_VERSION_1:
+ offset = ssh_dissect_ssh1(tvb, pinfo,
+ offset,ssh_tree,is_response,this_number,
+ &need_desegmentation);
+ break;
+
+ case SSH_VERSION_2:
+ offset = ssh_dissect_ssh2(tvb, pinfo,
+ offset,ssh_tree,is_response,this_number,
+ &need_desegmentation);
+ break;
+ }
+ }
+
+ if(need_desegmentation) return;
+ }
+}
+
+static int
+ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree,int is_response, int this_number,
+ gboolean *need_desegmentation)
+{
+ proto_item *ti;
+ proto_item *ssh2_tree=NULL;
+
+ if(tree) {
+ ti=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 2");
+ ssh2_tree = proto_item_add_subtree(ti ,ett_ssh2);
+ }
+
+ if((is_response && this_number > 3) || (!is_response && this_number>4)) {
+ offset = ssh_dissect_encrypted_packet(tvb, pinfo,
+ offset,ssh2_tree,is_response);
+ } else {
+ offset = ssh_dissect_key_exchange(tvb,pinfo,
+ offset,ssh2_tree,is_response,this_number,
+ need_desegmentation);
+ }
+
+ return offset;
+}
+static int
+ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree,int is_response,
+ int number, gboolean *need_desegmentation)
+{
+ guint plen, padding_length,len;
+ guint8 msg_code;
+ guint remain_length;
+
+ proto_item *ti;
+ proto_item *ssh1_tree =NULL;
+
+ if(tree) {
+ ti=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
+ ssh1_tree = proto_item_add_subtree(ti ,ett_ssh1);
+ }
+
+ /*
+ * We use "tvb_ensure_length_remaining()" to make sure there
+ * actually *is* data remaining.
+ *
+ * This means we're guaranteed that "remain_length" is positive.
+ */
+ remain_length = tvb_ensure_length_remaining(tvb,offset);
+ if (ssh_desegment && pinfo->can_desegment) {
+ if(remain_length < 4) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4-remain_length;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+ plen = tvb_get_ntohl(tvb, offset) ;
+ padding_length = 8 - plen%8;
+
+
+ if (ssh_desegment && pinfo->can_desegment) {
+ if(plen+4+padding_length > remain_length ) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = plen+padding_length - remain_length;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ",
+ is_response?"Server":"Client");
+ }
+
+ if(plen >= 0xffff) {
+ if (ssh1_tree && plen > 0) {
+ proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
+ offset, 4, plen,"Overly large length %x",plen);
+ }
+ plen = remain_length-4-padding_length;
+ } else {
+ if (ssh1_tree && plen > 0) {
+ proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
+ offset, 4, plen);
+ }
+ }
+ offset+=4;
+/* padding length */
+
+ if (tree) {
+ proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
+ offset, padding_length, padding_length);
+ }
+ offset += padding_length;
+/*
+ if(tree) {
+ tf=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
+ ssh1_tree = proto_item_add_subtree(tf ,ett_ssh1);
+ }
+*/
+ /* msg_code */
+ if(number == 1 ) {
+ msg_code = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint_format(ssh1_tree, hf_ssh_msg_code, tvb,
+ offset, 1, msg_code,"Msg code: %s (%u)",
+ val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"),
+ msg_code);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
+ }
+ offset += 1;
+ len = plen -1;
+ } else {
+ len = plen;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Encrypted packet len=%d", len);
+ }
+ }
+ /* payload */
+ if (ssh1_tree ) {
+ ssh_proto_tree_add_item(ssh1_tree, hf_ssh_payload,
+ tvb, offset, len, FALSE);
+ }
+ offset+=len;
+
+ return offset;
+}
+
+static int
+ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree,int is_response,int number,
+ gboolean *need_desegmentation)
+{
+ guint plen,len;
+ guint8 padding_length;
+ guint remain_length;
+ int last_offset=offset;
+ guint msg_code;
+
+ proto_item *tf;
+ proto_item *key_ex_tree =NULL;
+
+ /*
+ * We use "tvb_ensure_length_remaining()" to make sure there
+ * actually *is* data remaining.
+ *
+ * This means we're guaranteed that "remain_length" is positive.
+ */
+ remain_length = tvb_ensure_length_remaining(tvb,offset);
+ if (ssh_desegment && pinfo->can_desegment) {
+ if(remain_length < 4) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4-remain_length;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+ plen = tvb_get_ntohl(tvb, offset) ;
+
+ if (ssh_desegment && pinfo->can_desegment) {
+ if(plen +4 > remain_length ) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = plen+4 - remain_length;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+ /*
+ * Need to check plen > 0x80000000 here
+ */
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ",
+ is_response?"Server":"Client");
+ }
+
+ if(plen >= 0xffff) {
+ if (tree) {
+ proto_tree_add_uint_format(tree, hf_ssh_packet_length, tvb,
+ offset, 4, plen,"Overly large number 0x%x",plen);
+ }
+ plen = remain_length-4;
+ } else {
+ if (tree) {
+ proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
+ offset, 4, plen);
+ }
+ }
+ offset+=4;
+/* padding length */
+ padding_length = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_ssh_padding_length, tvb,
+ offset, 1, padding_length);
+ }
+ offset += 1;
+
+ if(tree) {
+ tf=proto_tree_add_text(tree,tvb,offset,-1,"Key Exchange");
+ key_ex_tree = proto_item_add_subtree(tf ,ett_key_exchange);
+ }
+ /* msg_code */
+ msg_code = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint_format(key_ex_tree, hf_ssh_msg_code, tvb,
+ offset, 1, msg_code,"Msg code: %s (%u)",
+ val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"),
+ msg_code);
+
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
+ }
+ offset += 1;
+
+ /* 16 bytes cookie */
+ if(number == 1) {
+ offset = ssh_dissect_key_init(tvb, offset,key_ex_tree);
+ }
+
+ len = plen+4-padding_length-(offset-last_offset);
+ if (tree ) {
+ ssh_proto_tree_add_item(key_ex_tree, hf_ssh_payload,
+ tvb, offset, len, FALSE);
+ }
+ offset +=len;
+
+ /* padding */
+ if(tree) {
+ ssh_proto_tree_add_item(key_ex_tree, hf_ssh_padding_string,
+ tvb, offset, padding_length, FALSE);
+ }
+ offset+= padding_length;
+
+ /* MAC , if there is still bytes, treat it as 16bytes MAC*/
+ if(msg_code == SSH2_MSG_KEX_DH_GEX_REPLY) {
+ len = tvb_reported_length_remaining(tvb,offset);
+ if(len == 16) {
+ if(tree) {
+ proto_tree_add_item(key_ex_tree, hf_ssh_mac_string,
+ tvb, offset, len , FALSE);
+ }
+ offset+=len;
+ }
+ }
+
+ return offset;
+}
+static int
+ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree,int is_response)
+{
+ gint len;
+
+ len = tvb_reported_length_remaining(tvb,offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Encrypted %s packet len=%d",
+ is_response?"response":"request",len);
+ }
+ if (tree ) {
+ ssh_proto_tree_add_item(tree, hf_ssh_encrypted_packet,
+ tvb, offset, len, FALSE);
+ }
+ offset+=len;
+ return offset;
+}
+
+static int
+ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
+ int offset, proto_tree *tree, int is_response, int * version,
+ gboolean *need_desegmentation)
+{
+ guint remain_length;
+ gint linelen, protolen;
+
+ /*
+ * If the first packet do not contain the banner,
+ * it is dump in the middle of a flow or not a ssh at all
+ */
+ if(tvb_strncaseeql(tvb,offset,"SSH-",4) != 0 ) {
+ offset = ssh_dissect_encrypted_packet(tvb, pinfo,
+ offset,tree,is_response);
+ return offset;
+ }
+
+ if(!is_response) {
+ if(tvb_strncaseeql(tvb,offset,"SSH-2.",6) == 0 ) {
+ *(version) = SSH_VERSION_2;
+ }else if(tvb_strncaseeql(tvb,offset,"SSH-1.99-",9) == 0 ) {
+ *(version) = SSH_VERSION_2;
+ }else if(tvb_strncaseeql(tvb,offset,"SSH-1.",6) == 0 ) {
+ *(version) = SSH_VERSION_1;
+ }
+ }
+
+ /*
+ * We use "tvb_ensure_length_remaining()" to make sure there
+ * actually *is* data remaining.
+ *
+ * This means we're guaranteed that "remain_length" is positive.
+ */
+ remain_length = tvb_ensure_length_remaining(tvb,offset);
+ /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ */
+ linelen = tvb_find_guint8(tvb, offset, -1, '\n');
+
+ if (ssh_desegment && pinfo->can_desegment) {
+ if(linelen == -1 || remain_length < (guint)linelen-offset ) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = linelen-remain_length;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+ if(linelen == -1 ) {
+ /* XXX - reassemble across segment boundaries? */
+ linelen = remain_length;
+ protolen = linelen;
+ } else {
+ linelen = linelen - offset + 1;
+ protolen = linelen - 1;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Protocol: %s",
+ is_response?"Server":"Client",
+ tvb_format_text(tvb,offset,protolen));
+ }
+ if (tree ) {
+ ssh_proto_tree_add_item(tree, hf_ssh_protocol,
+ tvb, offset, linelen, FALSE);
+ }
+ offset+=linelen;
+ return offset;
+}
+
+#define SSH_PROPOSAL(item)\
+ { &hf_ssh_ ## item, &hf_ssh_ ## item ## _length }
+
+static struct {
+ int *value, *length;
+} ssh_proposals[] = {
+ SSH_PROPOSAL(kex_algorithms),
+ SSH_PROPOSAL(server_host_key_algorithms),
+ SSH_PROPOSAL(encryption_algorithms_client_to_server),
+ SSH_PROPOSAL(encryption_algorithms_server_to_client),
+ SSH_PROPOSAL(mac_algorithms_client_to_server),
+ SSH_PROPOSAL(mac_algorithms_server_to_client),
+ SSH_PROPOSAL(compression_algorithms_client_to_server),
+ SSH_PROPOSAL(compression_algorithms_server_to_client),
+ SSH_PROPOSAL(languages_client_to_server),
+ SSH_PROPOSAL(languages_server_to_client),
+ {NULL, NULL}
+};
+
+static int
+ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree )
+{
+ guint len;
+ int i;
+
+ proto_item *tf;
+ proto_item *key_init_tree=NULL;
+
+ if (tree) {
+ tf=proto_tree_add_text(tree,tvb,offset,-1,"Algorithms");
+ key_init_tree = proto_item_add_subtree(tf, ett_key_init);
+ proto_tree_add_item(key_init_tree, hf_ssh_cookie,
+ tvb, offset, 16, FALSE);
+ }
+ offset += 16;
+
+ for (i = 0; ssh_proposals[i].value; i++) {
+ len = tvb_get_ntohl(tvb, offset);
+ if (key_init_tree) {
+ proto_tree_add_uint(key_init_tree,
+ *ssh_proposals[i].length, tvb, offset, 4, len);
+ }
+ offset+=4;
+ if (key_init_tree) {
+ ssh_proto_tree_add_item(key_init_tree,
+ *ssh_proposals[i].value, tvb, offset, len, FALSE);
+ }
+ offset+=len;
+ }
+ return offset;
+}
+proto_item *
+ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ gint start, gint length, gboolean little_endian)
+{
+ if (tree && length <0xffff && length > 0) {
+ return proto_tree_add_item(tree, hfindex, tvb, start, length,little_endian);
+ }
+ return NULL;
+}
+
+void
+proto_register_ssh(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ssh_packet_length,
+ { "Packet Length", "ssh.packet_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH packet length", HFILL }},
+
+ { &hf_ssh_padding_length,
+ { "Padding Length", "ssh.padding_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "SSH Packet Number", HFILL }},
+
+ { &hf_ssh_msg_code,
+ { "Message Code", "ssh.message_code",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "SSH Message Code", HFILL }},
+
+ { &hf_ssh_cookie,
+ { "Cookie", "ssh.cookie",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH Cookie", HFILL }},
+
+ { &hf_ssh_encrypted_packet,
+ { "Encrypted Packet", "ssh.encrypted_packet",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH Protocol Packet", HFILL }},
+
+ { &hf_ssh_protocol,
+ { "Protocol", "ssh.protocol",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "SSH Protocol", HFILL }},
+
+ { &hf_ssh_payload,
+ { "Payload", "ssh.payload",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH Payload", HFILL }},
+
+ { &hf_ssh_padding_string,
+ { "Padding String", "ssh.padding_string",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "SSH Padding String", HFILL }},
+
+ { &hf_ssh_mac_string,
+ { "MAC String", "ssh.mac_string",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "SSH MAC String", HFILL }},
+
+ { &hf_ssh_kex_algorithms,
+ { "kex_algorithms string", "ssh.kex_algorithms",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH kex_algorithms string", HFILL }},
+
+ { &hf_ssh_server_host_key_algorithms,
+ { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH server_host_key_algorithms string", HFILL }},
+
+ { &hf_ssh_encryption_algorithms_client_to_server,
+ { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH encryption_algorithms_client_to_server string", HFILL }},
+
+ { &hf_ssh_encryption_algorithms_server_to_client,
+ { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH encryption_algorithms_server_to_client string", HFILL }},
+
+ { &hf_ssh_mac_algorithms_client_to_server,
+ { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH mac_algorithms_client_to_server string", HFILL }},
+
+ { &hf_ssh_mac_algorithms_server_to_client,
+ { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH mac_algorithms_server_to_client string", HFILL }},
+
+ { &hf_ssh_compression_algorithms_client_to_server,
+ { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH compression_algorithms_client_to_server string", HFILL }},
+
+ { &hf_ssh_compression_algorithms_server_to_client,
+ { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH compression_algorithms_server_to_client string", HFILL }},
+
+ { &hf_ssh_languages_client_to_server,
+ { "languages_client_to_server string", "ssh.languages_client_to_server",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH languages_client_to_server string", HFILL }},
+
+ { &hf_ssh_languages_server_to_client,
+ { "languages_server_to_client string", "ssh.languages_server_to_client",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH languages_server_to_client string", HFILL }},
+
+ { &hf_ssh_kex_algorithms_length,
+ { "kex_algorithms length", "ssh.kex_algorithms_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH kex_algorithms length", HFILL }},
+
+ { &hf_ssh_server_host_key_algorithms_length,
+ { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH server_host_key_algorithms length", HFILL }},
+
+ { &hf_ssh_encryption_algorithms_client_to_server_length,
+ { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH encryption_algorithms_client_to_server length", HFILL }},
+
+ { &hf_ssh_encryption_algorithms_server_to_client_length,
+ { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH encryption_algorithms_server_to_client length", HFILL }},
+
+ { &hf_ssh_mac_algorithms_client_to_server_length,
+ { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH mac_algorithms_client_to_server length", HFILL }},
+
+ { &hf_ssh_mac_algorithms_server_to_client_length,
+ { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH mac_algorithms_server_to_client length", HFILL }},
+
+ { &hf_ssh_compression_algorithms_client_to_server_length,
+ { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH compression_algorithms_client_to_server length", HFILL }},
+
+ { &hf_ssh_compression_algorithms_server_to_client_length,
+ { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH compression_algorithms_server_to_client length", HFILL }},
+
+ { &hf_ssh_languages_client_to_server_length,
+ { "languages_client_to_server length", "ssh.languages_client_to_server_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH languages_client_to_server length", HFILL }},
+
+ { &hf_ssh_languages_server_to_client_length,
+ { "languages_server_to_client length", "ssh.languages_server_to_client_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH languages_server_to_client length", HFILL }},
+
+
+ };
+ static gint *ett[] = {
+ &ett_ssh,
+ &ett_key_exchange,
+ &ett_ssh1,
+ &ett_ssh2,
+ &ett_key_init
+ };
+ module_t *ssh_module;
+
+ proto_ssh = proto_register_protocol("SSH Protocol",
+ "SSH", "ssh");
+ proto_register_field_array(proto_ssh, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&ssh_init_protocol);
+
+ ssh_module = prefs_register_protocol(proto_ssh, NULL);
+ prefs_register_bool_preference(ssh_module, "desegment_buffers",
+ "Desegment all SSH buffers spanning multiple TCP segments",
+ "Whether the SSH dissector should desegment all SSH buffers spanning multiple TCP segments",
+ &ssh_desegment);
+}
+
+void
+proto_reg_handoff_ssh(void)
+{
+ dissector_handle_t ssh_handle;
+
+ ssh_handle = create_dissector_handle(dissect_ssh, proto_ssh);
+
+ dissector_add("tcp.port", TCP_PORT_SSH, ssh_handle);
+}
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
new file mode 100644
index 0000000000..38d1245d57
--- /dev/null
+++ b/epan/dissectors/packet-ssl.c
@@ -0,0 +1,3468 @@
+/* packet-ssl.c
+ * Routines for ssl dissection
+ * Copyright (c) 2000-2001, Scott Renfro <scott@renfro.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * See
+ *
+ * http://www.netscape.com/eng/security/SSL_2.html
+ *
+ * for SSL 2.0 specs.
+ *
+ * See
+ *
+ * http://www.netscape.com/eng/ssl3/
+ *
+ * for SSL 3.0 specs.
+ *
+ * See RFC 2246 for SSL 3.1/TLS 1.0 specs.
+ *
+ * See (among other places)
+ *
+ * http://www.graphcomp.com/info/specs/ms/pct.htm
+ *
+ * for PCT 1 draft specs.
+ *
+ * See
+ *
+ * http://research.sun.com/projects/crypto/draft-ietf-tls-ecc-05.txt
+ *
+ * for Elliptic Curve Cryptography cipher suites.
+ *
+ * See
+ *
+ * http://www.ietf.org/internet-drafts/draft-ietf-tls-camellia-04.txt
+ *
+ * for Camellia-based cipher suites.
+ *
+ * Notes:
+ *
+ * - Uses conversations in a no-malloc fashion. Since we just want to
+ * remember the version of the conversation, we store the version
+ * integer directly in the void *data member of the conversation
+ * structure. This means that we don't have to manage any memory,
+ * but will cause problems if anyone assumes that all data pointers
+ * are actually pointers to memory allocated by g_mem_chunk_alloc.
+ *
+ * - Does not support decryption of encrypted frames, nor dissection
+ * of frames that would require state maintained between frames
+ * (e.g., single ssl records spread across multiple tcp frames)
+ *
+ * - Identifies, but does not fully dissect the following messages:
+ *
+ * - SSLv3/TLS (These need more state from previous handshake msgs)
+ * - Server Key Exchange
+ * - Client Key Exchange
+ * - Certificate Verify
+ *
+ * - SSLv2 (These don't appear in the clear)
+ * - Error
+ * - Client Finished
+ * - Server Verify
+ * - Server Finished
+ * - Request Certificate
+ * - Client Certificate
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/conversation.h>
+#include "prefs.h"
+
+static gboolean ssl_desegment = TRUE;
+
+
+/*********************************************************************
+ *
+ * Protocol Constants, Variables, Data Structures
+ *
+ *********************************************************************/
+
+/* Initialize the protocol and registered fields */
+static int proto_ssl = -1;
+static int hf_ssl_record = -1;
+static int hf_ssl_record_content_type = -1;
+static int hf_ssl_record_version = -1;
+static int hf_ssl_record_length = -1;
+static int hf_ssl_record_appdata = -1;
+static int hf_ssl2_record = -1;
+static int hf_ssl2_record_is_escape = -1;
+static int hf_ssl2_record_padding_length = -1;
+static int hf_ssl2_msg_type = -1;
+static int hf_pct_msg_type = -1;
+static int hf_ssl_change_cipher_spec = -1;
+static int hf_ssl_alert_message = -1;
+static int hf_ssl_alert_message_level = -1;
+static int hf_ssl_alert_message_description = -1;
+static int hf_ssl_handshake_protocol = -1;
+static int hf_ssl_handshake_type = -1;
+static int hf_ssl_handshake_length = -1;
+static int hf_ssl_handshake_client_version = -1;
+static int hf_ssl_handshake_server_version = -1;
+static int hf_ssl_handshake_random_time = -1;
+static int hf_ssl_handshake_random_bytes = -1;
+static int hf_ssl_handshake_cipher_suites_len = -1;
+static int hf_ssl_handshake_cipher_suites = -1;
+static int hf_ssl_handshake_cipher_suite = -1;
+static int hf_ssl_handshake_session_id = -1;
+static int hf_ssl_handshake_comp_methods_len = -1;
+static int hf_ssl_handshake_comp_methods = -1;
+static int hf_ssl_handshake_comp_method = -1;
+static int hf_ssl_handshake_certificates_len = -1;
+static int hf_ssl_handshake_certificates = -1;
+static int hf_ssl_handshake_certificate = -1;
+static int hf_ssl_handshake_certificate_len = -1;
+static int hf_ssl_handshake_cert_types_count = -1;
+static int hf_ssl_handshake_cert_types = -1;
+static int hf_ssl_handshake_cert_type = -1;
+static int hf_ssl_handshake_finished = -1;
+static int hf_ssl_handshake_md5_hash = -1;
+static int hf_ssl_handshake_sha_hash = -1;
+static int hf_ssl_handshake_session_id_len = -1;
+static int hf_ssl_handshake_dnames_len = -1;
+static int hf_ssl_handshake_dnames = -1;
+static int hf_ssl_handshake_dname_len = -1;
+static int hf_ssl_handshake_dname = -1;
+static int hf_ssl2_handshake_cipher_spec_len = -1;
+static int hf_ssl2_handshake_session_id_len = -1;
+static int hf_ssl2_handshake_challenge_len = -1;
+static int hf_ssl2_handshake_cipher_spec = -1;
+static int hf_ssl2_handshake_challenge = -1;
+static int hf_ssl2_handshake_clear_key_len = -1;
+static int hf_ssl2_handshake_enc_key_len = -1;
+static int hf_ssl2_handshake_key_arg_len = -1;
+static int hf_ssl2_handshake_clear_key = -1;
+static int hf_ssl2_handshake_enc_key = -1;
+static int hf_ssl2_handshake_key_arg = -1;
+static int hf_ssl2_handshake_session_id_hit = -1;
+static int hf_ssl2_handshake_cert_type = -1;
+static int hf_ssl2_handshake_connection_id_len = -1;
+static int hf_ssl2_handshake_connection_id = -1;
+static int hf_pct_handshake_cipher_spec = -1;
+static int hf_pct_handshake_hash_spec = -1;
+static int hf_pct_handshake_cert_spec = -1;
+static int hf_pct_handshake_cert = -1;
+static int hf_pct_handshake_exch_spec = -1;
+static int hf_pct_handshake_hash = -1;
+static int hf_pct_handshake_cipher = -1;
+static int hf_pct_handshake_exch = -1;
+static int hf_pct_handshake_sig = -1;
+static int hf_pct_msg_error_type = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_ssl = -1;
+static gint ett_ssl_record = -1;
+static gint ett_ssl_alert = -1;
+static gint ett_ssl_handshake = -1;
+static gint ett_ssl_cipher_suites = -1;
+static gint ett_ssl_comp_methods = -1;
+static gint ett_ssl_certs = -1;
+static gint ett_ssl_cert_types = -1;
+static gint ett_ssl_dnames = -1;
+static gint ett_pct_cipher_suites = -1;
+static gint ett_pct_hash_suites = -1;
+static gint ett_pct_cert_suites = -1;
+static gint ett_pct_exch_suites = -1;
+
+/* The TCP port to associate with by default */
+#define TCP_PORT_SSL 443
+#define TCP_PORT_SSL_LDAP 636
+#define TCP_PORT_SSL_IMAP 993
+#define TCP_PORT_SSL_POP 995
+
+/* version state tables */
+#define SSL_VER_UNKNOWN 0
+#define SSL_VER_SSLv2 1
+#define SSL_VER_SSLv3 2
+#define SSL_VER_TLS 3
+#define SSL_VER_PCT 4
+
+/* corresponds to the #defines above */
+static gchar* ssl_version_short_names[] = {
+ "SSL",
+ "SSLv2",
+ "SSLv3",
+ "TLS",
+ "PCT"
+};
+
+/* other defines */
+#define SSL_ID_CHG_CIPHER_SPEC 0x14
+#define SSL_ID_ALERT 0x15
+#define SSL_ID_HANDSHAKE 0x16
+#define SSL_ID_APP_DATA 0x17
+
+#define SSL_HND_HELLO_REQUEST 0
+#define SSL_HND_CLIENT_HELLO 1
+#define SSL_HND_SERVER_HELLO 2
+#define SSL_HND_CERTIFICATE 11
+#define SSL_HND_SERVER_KEY_EXCHG 12
+#define SSL_HND_CERT_REQUEST 13
+#define SSL_HND_SVR_HELLO_DONE 14
+#define SSL_HND_CERT_VERIFY 15
+#define SSL_HND_CLIENT_KEY_EXCHG 16
+#define SSL_HND_FINISHED 20
+
+#define SSL2_HND_ERROR 0x00
+#define SSL2_HND_CLIENT_HELLO 0x01
+#define SSL2_HND_CLIENT_MASTER_KEY 0x02
+#define SSL2_HND_CLIENT_FINISHED 0x03
+#define SSL2_HND_SERVER_HELLO 0x04
+#define SSL2_HND_SERVER_VERIFY 0x05
+#define SSL2_HND_SERVER_FINISHED 0x06
+#define SSL2_HND_REQUEST_CERTIFICATE 0x07
+#define SSL2_HND_CLIENT_CERTIFICATE 0x08
+
+#define PCT_VERSION_1 0x8001
+
+#define PCT_MSG_CLIENT_HELLO 0x01
+#define PCT_MSG_SERVER_HELLO 0x02
+#define PCT_MSG_CLIENT_MASTER_KEY 0x03
+#define PCT_MSG_SERVER_VERIFY 0x04
+#define PCT_MSG_ERROR 0x05
+
+#define PCT_CH_OFFSET_V1 0xa
+
+#define PCT_CIPHER_DES 0x01
+#define PCT_CIPHER_IDEA 0x02
+#define PCT_CIPHER_RC2 0x03
+#define PCT_CIPHER_RC4 0x04
+#define PCT_CIPHER_DES_112 0x05
+#define PCT_CIPHER_DES_168 0x06
+
+#define PCT_HASH_MD5 0x0001
+#define PCT_HASH_MD5_TRUNC_64 0x0002
+#define PCT_HASH_SHA 0x0003
+#define PCT_HASH_SHA_TRUNC_80 0x0004
+#define PCT_HASH_DES_DM 0x0005
+
+#define PCT_CERT_NONE 0x00
+#define PCT_CERT_X509 0x01
+#define PCT_CERT_PKCS7 0x02
+
+#define PCT_SIG_NONE 0x0000
+#define PCT_SIG_RSA_MD5 0x0001
+#define PCT_SIG_RSA_SHA 0x0002
+#define PCT_SIG_DSA_SHA 0x0003
+
+#define PCT_EXCH_RSA_PKCS1 0x01
+#define PCT_EXCH_RSA_PKCS1_TOKEN_DES 0x02
+#define PCT_EXCH_RSA_PKCS1_TOKEN_DES3 0x03
+#define PCT_EXCH_RSA_PKCS1_TOKEN_RC2 0x04
+#define PCT_EXCH_RSA_PKCS1_TOKEN_RC4 0x05
+#define PCT_EXCH_DH_PKCS3 0x06
+#define PCT_EXCH_DH_PKCS3_TOKEN_DES 0x07
+#define PCT_EXCH_DH_PKCS3_TOKEN_DES3 0x08
+#define PCT_EXCH_FORTEZZA_TOKEN 0x09
+
+#define PCT_ERR_BAD_CERTIFICATE 0x01
+#define PCT_ERR_CLIENT_AUTH_FAILED 0x02
+#define PCT_ERR_ILLEGAL_MESSAGE 0x03
+#define PCT_ERR_INTEGRITY_CHECK_FAILED 0x04
+#define PCT_ERR_SERVER_AUTH_FAILED 0x05
+#define PCT_ERR_SPECS_MISMATCH 0x06
+
+/*
+ * Lookup tables
+ *
+ */
+static const value_string ssl_20_msg_types[] = {
+ { SSL2_HND_ERROR, "Error" },
+ { SSL2_HND_CLIENT_HELLO, "Client Hello" },
+ { SSL2_HND_CLIENT_MASTER_KEY, "Client Master Key" },
+ { SSL2_HND_CLIENT_FINISHED, "Client Finished" },
+ { SSL2_HND_SERVER_HELLO, "Server Hello" },
+ { SSL2_HND_SERVER_VERIFY, "Server Verify" },
+ { SSL2_HND_SERVER_FINISHED, "Server Finished" },
+ { SSL2_HND_REQUEST_CERTIFICATE, "Request Certificate" },
+ { SSL2_HND_CLIENT_CERTIFICATE, "Client Certificate" },
+ { 0x00, NULL },
+};
+
+static const value_string ssl_20_cipher_suites[] = {
+ { 0x010080, "SSL2_RC4_128_WITH_MD5" },
+ { 0x020080, "SSL2_RC4_128_EXPORT40_WITH_MD5" },
+ { 0x030080, "SSL2_RC2_CBC_128_CBC_WITH_MD5" },
+ { 0x040080, "SSL2_RC2_CBC_128_CBC_WITH_MD5" },
+ { 0x050080, "SSL2_IDEA_128_CBC_WITH_MD5" },
+ { 0x060040, "SSL2_DES_64_CBC_WITH_MD5" },
+ { 0x0700c0, "SSL2_DES_192_EDE3_CBC_WITH_MD5" },
+ { 0x080080, "SSL2_RC4_64_WITH_MD5" },
+ { 0x000000, "TLS_NULL_WITH_NULL_NULL" },
+ { 0x000001, "TLS_RSA_WITH_NULL_MD5" },
+ { 0x000002, "TLS_RSA_WITH_NULL_SHA" },
+ { 0x000003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5" },
+ { 0x000004, "TLS_RSA_WITH_RC4_128_MD5" },
+ { 0x000005, "TLS_RSA_WITH_RC4_128_SHA" },
+ { 0x000006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5" },
+ { 0x000007, "TLS_RSA_WITH_IDEA_CBC_SHA" },
+ { 0x000008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x000009, "TLS_RSA_WITH_DES_CBC_SHA" },
+ { 0x00000a, "TLS_RSA_WITH_3DES_EDE_CBC_SHA" },
+ { 0x00000b, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x00000c, "TLS_DH_DSS_WITH_DES_CBC_SHA" },
+ { 0x00000d, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA" },
+ { 0x00000e, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x00000f, "TLS_DH_RSA_WITH_DES_CBC_SHA" },
+ { 0x000010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA" },
+ { 0x000011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x000012, "TLS_DHE_DSS_WITH_DES_CBC_SHA" },
+ { 0x000013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA" },
+ { 0x000014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x000015, "TLS_DHE_RSA_WITH_DES_CBC_SHA" },
+ { 0x000016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA" },
+ { 0x000017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5" },
+ { 0x000018, "TLS_DH_anon_WITH_RC4_128_MD5" },
+ { 0x000019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x00001a, "TLS_DH_anon_WITH_DES_CBC_SHA" },
+ { 0x00001b, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA" },
+ { 0x00001c, "SSL_FORTEZZA_KEA_WITH_NULL_SHA" },
+ { 0x00001d, "SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA" },
+ { 0x00001e, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA" },
+ { 0x00002f, "TLS_RSA_WITH_AES_128_CBC_SHA" },
+ { 0x000030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA" },
+ { 0x000031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA" },
+ { 0x000032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA" },
+ { 0x000033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" },
+ { 0x000034, "TLS_DH_anon_WITH_AES_128_CBC_SHA" },
+ { 0x000035, "TLS_RSA_WITH_AES_256_CBC_SHA" },
+ { 0x000036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA" },
+ { 0x000037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA" },
+ { 0x000038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" },
+ { 0x000039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" },
+ { 0x00003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA" },
+ { 0x000041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x000042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x000043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x000044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x000045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x000046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x000047, "TLS_ECDH_ECDSA_WITH_NULL_SHA" },
+ { 0x000048, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA" },
+ { 0x000049, "TLS_ECDH_ECDSA_WITH_DES_CBC_SHA" },
+ { 0x00004A, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA" },
+ { 0x00004B, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA" },
+ { 0x00004C, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA" },
+ { 0x000060, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5" },
+ { 0x000061, "TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5" },
+ { 0x000062, "TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA" },
+ { 0x000063, "TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA" },
+ { 0x000064, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA" },
+ { 0x000065, "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA" },
+ { 0x000066, "TLS_DHE_DSS_WITH_RC4_128_SHA" },
+ { 0x000084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x000085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x000086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x000087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x000088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x000089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA" },
+ /* these from http://www.mozilla.org/projects/
+ security/pki/nss/ssl/fips-ssl-ciphersuites.html */
+ { 0x00fefe, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
+ { 0x00feff, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
+ { 0x00ffe0, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
+ { 0x00ffe1, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
+ /* Microsoft's old PCT protocol. These are from Eric Rescorla's
+ book "SSL and TLS" */
+ { 0x8f8001, "PCT_SSL_COMPAT | PCT_VERSION_1" },
+ { 0x800003, "PCT_SSL_CERT_TYPE | PCT1_CERT_X509_CHAIN" },
+ { 0x800001, "PCT_SSL_CERT_TYPE | PCT1_CERT_X509" },
+ { 0x810001, "PCT_SSL_HASH_TYPE | PCT1_HASH_MD5" },
+ { 0x810003, "PCT_SSL_HASH_TYPE | PCT1_HASH_SHA" },
+ { 0x820001, "PCT_SSL_EXCH_TYPE | PCT1_EXCH_RSA_PKCS1" },
+ { 0x830004, "PCT_SSL_CIPHER_TYPE_1ST_HALF | PCT1_CIPHER_RC4" },
+ { 0x848040, "PCT_SSL_CIPHER_TYPE_2ND_HALF | PCT1_ENC_BITS_128 | PCT1_MAC_BITS_128" },
+ { 0x842840, "PCT_SSL_CIPHER_TYPE_2ND_HALF | PCT1_ENC_BITS_40 | PCT1_MAC_BITS_128" },
+ /* note that ciphersuites of {0x00????} are TLS cipher suites in
+ * a sslv2 client hello message; the ???? above is the two-byte
+ * tls cipher suite id
+ */
+ { 0x00, NULL }
+};
+
+static const value_string ssl_20_certificate_type[] = {
+ { 0x00, "N/A" },
+ { 0x01, "X.509 Certificate" },
+ { 0x00, NULL },
+};
+
+static const value_string ssl_31_content_type[] = {
+ { 20, "Change Cipher Spec" },
+ { 21, "Alert" },
+ { 22, "Handshake" },
+ { 23, "Application Data" },
+ { 0x00, NULL }
+};
+
+static const value_string ssl_versions[] = {
+ { 0x0301, "TLS 1.0" },
+ { 0x0300, "SSL 3.0" },
+ { 0x0002, "SSL 2.0" },
+ { 0x00, NULL }
+};
+
+#if 0
+/* XXX - would be used if we dissected the body of a Change Cipher Spec
+ message. */
+static const value_string ssl_31_change_cipher_spec[] = {
+ { 1, "Change Cipher Spec" },
+ { 0x00, NULL },
+};
+#endif
+
+static const value_string ssl_31_alert_level[] = {
+ { 1, "Warning" },
+ { 2, "Fatal" },
+ { 0x00, NULL }
+};
+
+static const value_string ssl_31_alert_description[] = {
+ { 0, "Close Notify" },
+ { 10, "Unexpected Message" },
+ { 20, "Bad Record MAC" },
+ { 21, "Decryption Failed" },
+ { 22, "Record Overflow" },
+ { 30, "Decompression Failure" },
+ { 40, "Handshake Failure" },
+ { 42, "Bad Certificate" },
+ { 43, "Unsupported Certificate" },
+ { 44, "Certificate Revoked" },
+ { 45, "Certificate Expired" },
+ { 46, "Certificate Unknown" },
+ { 47, "Illegal Parameter" },
+ { 48, "Unknown CA" },
+ { 49, "Access Denied" },
+ { 50, "Decode Error" },
+ { 51, "Decrypt Error" },
+ { 60, "Export Restriction" },
+ { 70, "Protocol Version" },
+ { 71, "Insufficient Security" },
+ { 80, "Internal Error" },
+ { 90, "User Canceled" },
+ { 100, "No Renegotiation" },
+ { 0x00, NULL }
+};
+
+static const value_string ssl_31_handshake_type[] = {
+ { SSL_HND_HELLO_REQUEST, "Hello Request" },
+ { SSL_HND_CLIENT_HELLO, "Client Hello" },
+ { SSL_HND_SERVER_HELLO, "Server Hello" },
+ { SSL_HND_CERTIFICATE, "Certificate" },
+ { SSL_HND_SERVER_KEY_EXCHG, "Server Key Exchange" },
+ { SSL_HND_CERT_REQUEST, "Certificate Request" },
+ { SSL_HND_SVR_HELLO_DONE, "Server Hello Done" },
+ { SSL_HND_CERT_VERIFY, "Certificate Verify" },
+ { SSL_HND_CLIENT_KEY_EXCHG, "Client Key Exchange" },
+ { SSL_HND_FINISHED, "Finished" },
+ { 0x00, NULL }
+};
+
+static const value_string ssl_31_compression_method[] = {
+ { 0, "null" },
+ { 1, "ZLIB" },
+ { 0x00, NULL }
+};
+
+#if 0
+/* XXX - would be used if we dissected a Signature, as would be
+ seen in a server key exchange or certificate verify message. */
+static const value_string ssl_31_key_exchange_algorithm[] = {
+ { 0, "RSA" },
+ { 1, "Diffie Hellman" },
+ { 0x00, NULL }
+};
+
+static const value_string ssl_31_signature_algorithm[] = {
+ { 0, "Anonymous" },
+ { 1, "RSA" },
+ { 2, "DSA" },
+ { 0x00, NULL }
+};
+#endif
+
+static const value_string ssl_31_client_certificate_type[] = {
+ { 1, "RSA Sign" },
+ { 2, "DSS Sign" },
+ { 3, "RSA Fixed DH" },
+ { 4, "DSS Fixed DH" },
+ { 0x00, NULL }
+};
+
+#if 0
+/* XXX - would be used if we dissected exchnage keys, as would be
+ seen in a client key exchange message. */
+static const value_string ssl_31_public_value_encoding[] = {
+ { 0, "Implicit" },
+ { 1, "Explicit" },
+ { 0x00, NULL }
+};
+#endif
+
+static const value_string ssl_31_ciphersuite[] = {
+ { 0x0000, "TLS_NULL_WITH_NULL_NULL" },
+ { 0x0001, "TLS_RSA_WITH_NULL_MD5" },
+ { 0x0002, "TLS_RSA_WITH_NULL_SHA" },
+ { 0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5" },
+ { 0x0004, "TLS_RSA_WITH_RC4_128_MD5" },
+ { 0x0005, "TLS_RSA_WITH_RC4_128_SHA" },
+ { 0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5" },
+ { 0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA" },
+ { 0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x0009, "TLS_RSA_WITH_DES_CBC_SHA" },
+ { 0x000a, "TLS_RSA_WITH_3DES_EDE_CBC_SHA" },
+ { 0x000b, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x000c, "TLS_DH_DSS_WITH_DES_CBC_SHA" },
+ { 0x000d, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA" },
+ { 0x000e, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x000f, "TLS_DH_RSA_WITH_DES_CBC_SHA" },
+ { 0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA" },
+ { 0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA" },
+ { 0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA" },
+ { 0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA" },
+ { 0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA" },
+ { 0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5" },
+ { 0x0018, "TLS_DH_anon_WITH_RC4_128_MD5" },
+ { 0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA" },
+ { 0x001a, "TLS_DH_anon_WITH_DES_CBC_SHA" },
+ { 0x001b, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA" },
+ { 0x001c, "SSL_FORTEZZA_KEA_WITH_NULL_SHA" },
+ { 0x001d, "SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA" },
+ { 0x001e, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA" },
+ { 0x002f, "TLS_RSA_WITH_AES_128_CBC_SHA" },
+ { 0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA" },
+ { 0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA" },
+ { 0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA" },
+ { 0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" },
+ { 0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA" },
+ { 0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA" },
+ { 0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA" },
+ { 0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA" },
+ { 0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" },
+ { 0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" },
+ { 0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA" },
+ { 0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA" },
+ { 0x0047, "TLS_ECDH_ECDSA_WITH_NULL_SHA" },
+ { 0x0048, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA" },
+ { 0x0049, "TLS_ECDH_ECDSA_WITH_DES_CBC_SHA" },
+ { 0x004A, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA" },
+ { 0x004B, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA" },
+ { 0x004C, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA" },
+ { 0x0060, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5" },
+ { 0x0061, "TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5" },
+ { 0x0062, "TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA" },
+ { 0x0063, "TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA" },
+ { 0x0064, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA" },
+ { 0x0065, "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA" },
+ { 0x0066, "TLS_DHE_DSS_WITH_RC4_128_SHA" },
+ { 0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA" },
+ { 0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA" },
+ /* these from http://www.mozilla.org/projects/
+ security/pki/nss/ssl/fips-ssl-ciphersuites.html */
+ { 0xfefe, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
+ { 0xfeff, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
+ { 0xffe0, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
+ { 0xffe1, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
+ /* note that ciphersuites 0xff00 - 0xffff are private */
+ { 0x00, NULL }
+};
+
+static const value_string pct_msg_types[] = {
+ { PCT_MSG_CLIENT_HELLO, "Client Hello" },
+ { PCT_MSG_SERVER_HELLO, "Server Hello" },
+ { PCT_MSG_CLIENT_MASTER_KEY, "Client Master Key" },
+ { PCT_MSG_SERVER_VERIFY, "Server Verify" },
+ { PCT_MSG_ERROR, "Error" },
+ { 0x00, NULL },
+};
+
+static const value_string pct_cipher_type[] = {
+ { PCT_CIPHER_DES, "DES" },
+ { PCT_CIPHER_IDEA, "IDEA" },
+ { PCT_CIPHER_RC2, "RC2" },
+ { PCT_CIPHER_RC4, "RC4" },
+ { PCT_CIPHER_DES_112, "DES 112 bit" },
+ { PCT_CIPHER_DES_168, "DES 168 bit" },
+ { 0x00, NULL },
+};
+
+static const value_string pct_hash_type[] = {
+ { PCT_HASH_MD5, "MD5" },
+ { PCT_HASH_MD5_TRUNC_64, "MD5_TRUNC_64"},
+ { PCT_HASH_SHA, "SHA"},
+ { PCT_HASH_SHA_TRUNC_80, "SHA_TRUNC_80"},
+ { PCT_HASH_DES_DM, "DES_DM"},
+ { 0x00, NULL },
+};
+
+static const value_string pct_cert_type[] = {
+ { PCT_CERT_NONE, "None" },
+ { PCT_CERT_X509, "X.509" },
+ { PCT_CERT_PKCS7, "PKCS #7" },
+ { 0x00, NULL },
+};
+static const value_string pct_sig_type[] = {
+ { PCT_SIG_NONE, "None" },
+ { PCT_SIG_RSA_MD5, "MD5" },
+ { PCT_SIG_RSA_SHA, "RSA SHA" },
+ { PCT_SIG_DSA_SHA, "DSA SHA" },
+ { 0x00, NULL },
+};
+
+static const value_string pct_exch_type[] = {
+ { PCT_EXCH_RSA_PKCS1, "RSA PKCS#1" },
+ { PCT_EXCH_RSA_PKCS1_TOKEN_DES, "RSA PKCS#1 Token DES" },
+ { PCT_EXCH_RSA_PKCS1_TOKEN_DES3, "RSA PKCS#1 Token 3DES" },
+ { PCT_EXCH_RSA_PKCS1_TOKEN_RC2, "RSA PKCS#1 Token RC-2" },
+ { PCT_EXCH_RSA_PKCS1_TOKEN_RC4, "RSA PKCS#1 Token RC-4" },
+ { PCT_EXCH_DH_PKCS3, "DH PKCS#3" },
+ { PCT_EXCH_DH_PKCS3_TOKEN_DES, "DH PKCS#3 Token DES" },
+ { PCT_EXCH_DH_PKCS3_TOKEN_DES3, "DH PKCS#3 Token 3DES" },
+ { PCT_EXCH_FORTEZZA_TOKEN, "Fortezza" },
+ { 0x00, NULL },
+};
+
+static const value_string pct_error_code[] = {
+ { PCT_ERR_BAD_CERTIFICATE, "PCT_ERR_BAD_CERTIFICATE" },
+ { PCT_ERR_CLIENT_AUTH_FAILED, "PCT_ERR_CLIENT_AUTH_FAILE" },
+ { PCT_ERR_ILLEGAL_MESSAGE, "PCT_ERR_ILLEGAL_MESSAGE" },
+ { PCT_ERR_INTEGRITY_CHECK_FAILED, "PCT_ERR_INTEGRITY_CHECK_FAILED" },
+ { PCT_ERR_SERVER_AUTH_FAILED, "PCT_ERR_SERVER_AUTH_FAILED" },
+ { PCT_ERR_SPECS_MISMATCH, "PCT_ERR_SPECS_MISMATCH" },
+ { 0x00, NULL },
+};
+
+/*********************************************************************
+ *
+ * Forward Declarations
+ *
+ *********************************************************************/
+
+/*
+ * SSL version 3 and TLS dissectors
+ *
+ */
+/* record layer dissector */
+static int dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint *conv_version,
+ gboolean *need_desegmentation);
+
+/* change cipher spec dissector */
+static void dissect_ssl3_change_cipher_spec(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset,
+ guint *conv_version);
+
+/* alert message dissector */
+static void dissect_ssl3_alert(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint *conv_version);
+
+/* handshake protocol dissector */
+static void dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint32 record_length,
+ guint *conv_version);
+
+
+static void dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+
+static void dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+
+static void dissect_ssl3_hnd_cert(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset);
+
+static void dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+
+static void dissect_ssl3_hnd_finished(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset,
+ guint *conv_version);
+
+
+/*
+ * SSL version 2 dissectors
+ *
+ */
+
+/* record layer dissector */
+static int dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint *conv_version,
+ gboolean *need_desegmentation);
+
+/* client hello dissector */
+static void dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+
+static void dissect_pct_msg_client_hello(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+
+/* client master key dissector */
+static void dissect_ssl2_hnd_client_master_key(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+static void dissect_pct_msg_client_master_key(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+
+/* server hello dissector */
+static void dissect_ssl2_hnd_server_hello(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+static void dissect_pct_msg_server_hello(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+
+
+static void dissect_pct_msg_server_verify(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+
+static void dissect_pct_msg_error(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset);
+
+/*
+ * Support Functions
+ *
+ */
+static void ssl_set_conv_version(packet_info *pinfo, guint version);
+static int ssl_is_valid_handshake_type(guint8 type);
+static int ssl_is_valid_content_type(guint8 type);
+static int ssl_is_valid_ssl_version(guint16 version);
+static int ssl_is_authoritative_version_message(guint8 content_type,
+ guint8 next_byte);
+static int ssl_is_v2_client_hello(tvbuff_t *tvb, guint32 offset);
+static int ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset);
+static int ssl_looks_like_sslv3(tvbuff_t *tvb, guint32 offset);
+static int ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb,
+ guint32 offset,
+ guint32 record_length);
+static int ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb,
+ guint32 offset,
+ guint32 record_length);
+
+/*********************************************************************
+ *
+ * Main dissector
+ *
+ *********************************************************************/
+/*
+ * Code to actually dissect the packets
+ */
+static void
+dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ conversation_t *conversation;
+ void *conv_data;
+ guint conv_version = SSL_VER_UNKNOWN;
+ proto_item *ti = NULL;
+ proto_tree *ssl_tree = NULL;
+ guint32 offset = 0;
+ gboolean first_record_in_frame = TRUE;
+ gboolean need_desegmentation;
+
+ /* Track the version using conversations to reduce the
+ * chance that a packet that simply *looks* like a v2 or
+ * v3 packet is dissected improperly. This also allows
+ * us to more frequently set the protocol column properly
+ * for continuation data frames.
+ *
+ * Also: We use the copy in conv_version as our cached copy,
+ * so that we don't have to search the conversation
+ * table every time we want the version; when setting
+ * the conv_version, must set the copy in the conversation
+ * in addition to conv_version
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (!conversation)
+ {
+ /* create a new conversation */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+ conv_data = conversation_get_proto_data(conversation, proto_ssl);
+ if (conv_data != NULL)
+ {
+ conv_version = GPOINTER_TO_UINT(conv_data);
+ }
+
+ /* Initialize the protocol column; we'll set it later when we
+ * figure out what flavor of SSL it is (assuming we don't
+ * throw an exception before we get the chance to do so). */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSL");
+ }
+
+ /* clear the the info column */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* TCP packets and SSL records are orthogonal.
+ * A tcp packet may contain multiple ssl records and an ssl
+ * record may be spread across multiple tcp packets.
+ *
+ * This loop accounts for multiple ssl records in a single
+ * frame, but not a single ssl record across multiple tcp
+ * packets.
+ *
+ * Handling the single ssl record across multiple packets
+ * may be possible using ethereal conversations, but
+ * probably not cleanly. May have to wait for tcp stream
+ * reassembly.
+ */
+
+ /* Create display subtree for SSL as a whole */
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_ssl, tvb, 0, -1, FALSE);
+ ssl_tree = proto_item_add_subtree(ti, ett_ssl);
+ }
+
+ /* iterate through the records in this tvbuff */
+ while (tvb_reported_length_remaining(tvb, offset) != 0)
+ {
+ /* on second and subsequent records per frame
+ * add a delimiter on info column
+ */
+ if (!first_record_in_frame
+ && check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ }
+
+ /*
+ * Assume, for now, that this doesn't need desegmentation.
+ */
+ need_desegmentation = FALSE;
+
+ /* first try to dispatch off the cached version
+ * known to be associated with the conversation
+ */
+ switch(conv_version) {
+ case SSL_VER_SSLv2:
+ case SSL_VER_PCT:
+ offset = dissect_ssl2_record(tvb, pinfo, ssl_tree,
+ offset, &conv_version,
+ &need_desegmentation);
+ break;
+
+ case SSL_VER_SSLv3:
+ case SSL_VER_TLS:
+ /* the version tracking code works too well ;-)
+ * at times, we may visit a v2 client hello after
+ * we already know the version of the connection;
+ * work around that here by detecting and calling
+ * the v2 dissector instead
+ */
+ if (ssl_is_v2_client_hello(tvb, offset))
+ {
+ offset = dissect_ssl2_record(tvb, pinfo, ssl_tree,
+ offset, &conv_version,
+ &need_desegmentation);
+ }
+ else
+ {
+ offset = dissect_ssl3_record(tvb, pinfo, ssl_tree,
+ offset, &conv_version,
+ &need_desegmentation);
+ }
+ break;
+
+ /* that failed, so apply some heuristics based
+ * on this individual packet
+ */
+ default:
+ if (ssl_looks_like_sslv2(tvb, offset))
+ {
+ /* looks like sslv2 or pct client hello */
+ offset = dissect_ssl2_record(tvb, pinfo, ssl_tree,
+ offset, &conv_version,
+ &need_desegmentation);
+ }
+ else if (ssl_looks_like_sslv3(tvb, offset))
+ {
+ /* looks like sslv3 or tls */
+ offset = dissect_ssl3_record(tvb, pinfo, ssl_tree,
+ offset, &conv_version,
+ &need_desegmentation);
+ }
+ else
+ {
+ /* looks like something unknown, so lump into
+ * continuation data
+ */
+ offset = tvb_length(tvb);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO,
+ "Continuation Data");
+
+ /* Set the protocol column */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ ssl_version_short_names[conv_version]);
+ }
+ }
+ break;
+ }
+
+ /* Desegmentation return check */
+ if (need_desegmentation)
+ return;
+
+ /* If we haven't already set the version information for
+ * this conversation, do so. */
+ if (conv_data == NULL)
+ {
+ conv_data = GINT_TO_POINTER(conv_version);
+ conversation_add_proto_data(conversation, proto_ssl, conv_data);
+ }
+
+ /* set up for next record in frame, if any */
+ first_record_in_frame = FALSE;
+ }
+
+}
+
+
+/*********************************************************************
+ *
+ * SSL version 3 and TLS Dissection Routines
+ *
+ *********************************************************************/
+static int
+dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint *conv_version, gboolean *need_desegmentation)
+{
+
+ /*
+ * struct {
+ * uint8 major, minor;
+ * } ProtocolVersion;
+ *
+ *
+ * enum {
+ * change_cipher_spec(20), alert(21), handshake(22),
+ * application_data(23), (255)
+ * } ContentType;
+ *
+ * struct {
+ * ContentType type;
+ * ProtocolVersion version;
+ * uint16 length;
+ * opaque fragment[TLSPlaintext.length];
+ * } TLSPlaintext;
+ */
+ guint32 record_length;
+ guint16 version;
+ guint8 content_type;
+ guint8 next_byte;
+ proto_tree *ti = NULL;
+ proto_tree *ssl_record_tree = NULL;
+ guint32 available_bytes = 0;
+
+ available_bytes = tvb_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (ssl_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the record header split across segment boundaries?
+ */
+ if (available_bytes < 5) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 5 - available_bytes;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+
+ /*
+ * Get the record layer fields of interest
+ */
+ content_type = tvb_get_guint8(tvb, offset);
+ version = tvb_get_ntohs(tvb, offset + 1);
+ record_length = tvb_get_ntohs(tvb, offset + 3);
+
+ if (ssl_is_valid_content_type(content_type)) {
+
+ /*
+ * Can we do reassembly?
+ */
+ if (ssl_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the record split across segment boundaries?
+ */
+ if (available_bytes < record_length + 5) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = (record_length + 5) - available_bytes;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+
+ } else {
+
+ /* if we don't have a valid content_type, there's no sense
+ * continuing any further
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Continuation Data");
+
+ /* Set the protocol column */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ ssl_version_short_names[*conv_version]);
+ }
+ return offset + 5 + record_length;
+ }
+
+ /*
+ * If GUI, fill in record layer part of tree
+ */
+ if (tree)
+ {
+
+ /* add the record layer subtree header */
+ ti = proto_tree_add_item(tree, hf_ssl_record, tvb,
+ offset, 5 + record_length, 0);
+ ssl_record_tree = proto_item_add_subtree(ti, ett_ssl_record);
+ }
+ if (ssl_record_tree)
+ {
+
+ /* show the one-byte content type */
+ proto_tree_add_item(ssl_record_tree, hf_ssl_record_content_type,
+ tvb, offset, 1, 0);
+ offset++;
+
+ /* add the version */
+ proto_tree_add_item(ssl_record_tree, hf_ssl_record_version, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ /* add the length */
+ proto_tree_add_uint(ssl_record_tree, hf_ssl_record_length, tvb,
+ offset, 2, record_length);
+ offset += 2; /* move past length field itself */
+ }
+ else
+ {
+ /* if no GUI tree, then just skip over those fields */
+ offset += 5;
+ }
+
+
+ /*
+ * if we don't already have a version set for this conversation,
+ * but this message's version is authoritative (i.e., it's
+ * not client_hello, then save the version to to conversation
+ * structure and print the column version
+ */
+ next_byte = tvb_get_guint8(tvb, offset);
+ if (*conv_version == SSL_VER_UNKNOWN
+ && ssl_is_authoritative_version_message(content_type, next_byte))
+ {
+ if (version == 0x0300)
+ {
+ *conv_version = SSL_VER_SSLv3;
+ ssl_set_conv_version(pinfo, *conv_version);
+ }
+ else if (version == 0x0301)
+ {
+ *conv_version = SSL_VER_TLS;
+ ssl_set_conv_version(pinfo, *conv_version);
+ }
+ }
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ if (version == 0x0300)
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ ssl_version_short_names[SSL_VER_SSLv3]);
+ }
+ else if (version == 0x0301)
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ ssl_version_short_names[SSL_VER_TLS]);
+ }
+ else
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ ssl_version_short_names[*conv_version]);
+ }
+ }
+
+ /*
+ * now dissect the next layer
+ */
+ switch (content_type) {
+ case SSL_ID_CHG_CIPHER_SPEC:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Change Cipher Spec");
+ dissect_ssl3_change_cipher_spec(tvb, ssl_record_tree,
+ offset, conv_version);
+ break;
+ case SSL_ID_ALERT:
+ dissect_ssl3_alert(tvb, pinfo, ssl_record_tree, offset,
+ conv_version);
+ break;
+ case SSL_ID_HANDSHAKE:
+ dissect_ssl3_handshake(tvb, pinfo, ssl_record_tree, offset,
+ record_length, conv_version);
+ break;
+ case SSL_ID_APP_DATA:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Application Data");
+ if (ssl_record_tree)
+ {
+ proto_item_set_text(ssl_record_tree,
+ "%s Record Layer: Application Data",
+ ssl_version_short_names[*conv_version]);
+ proto_tree_add_item(ssl_record_tree, hf_ssl_record_appdata, tvb,
+ offset, record_length, 0);
+ }
+ break;
+
+ default:
+ /* shouldn't get here since we check above for valid types */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Bad SSLv3 Content Type");
+ break;
+ }
+ offset += record_length; /* skip to end of record */
+
+ return offset;
+}
+
+/* dissects the change cipher spec procotol, filling in the tree */
+static void
+dissect_ssl3_change_cipher_spec(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset,
+ guint *conv_version)
+{
+ /*
+ * struct {
+ * enum { change_cipher_spec(1), (255) } type;
+ * } ChangeCipherSpec;
+ *
+ */
+ if (tree)
+ {
+ proto_item_set_text(tree,
+ "%s Record Layer: Change Cipher Spec",
+ ssl_version_short_names[*conv_version]);
+ proto_tree_add_item(tree, hf_ssl_change_cipher_spec, tvb,
+ offset++, 1, FALSE);
+ }
+}
+
+/* dissects the alert message, filling in the tree */
+static void
+dissect_ssl3_alert(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint *conv_version)
+{
+ /* struct {
+ * AlertLevel level;
+ * AlertDescription description;
+ * } Alert;
+ */
+ proto_tree *ti;
+ proto_tree *ssl_alert_tree = NULL;
+ gchar *level;
+ gchar *desc;
+ guint8 byte;
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, hf_ssl_alert_message, tvb,
+ offset, 2, 0);
+ ssl_alert_tree = proto_item_add_subtree(ti, ett_ssl_alert);
+ }
+
+ /*
+ * set the record layer label
+ */
+
+ /* first lookup the names for the alert level and description */
+ byte = tvb_get_guint8(tvb, offset); /* grab the level byte */
+ level = match_strval(byte, ssl_31_alert_level);
+
+ byte = tvb_get_guint8(tvb, offset+1); /* grab the desc byte */
+ desc = match_strval(byte, ssl_31_alert_description);
+
+ /* now set the text in the record layer line */
+ if (level && desc)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "Alert (Level: %s, Description: %s)",
+ level, desc);
+ }
+ else
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Alert");
+ }
+
+ if (tree)
+ {
+ if (level && desc)
+ {
+ proto_item_set_text(tree, "%s Record Layer: Alert "
+ "(Level: %s, Description: %s)",
+ ssl_version_short_names[*conv_version],
+ level, desc);
+ proto_tree_add_item(ssl_alert_tree, hf_ssl_alert_message_level,
+ tvb, offset++, 1, FALSE);
+
+ proto_tree_add_item(ssl_alert_tree, hf_ssl_alert_message_description,
+ tvb, offset++, 1, FALSE);
+ }
+ else
+ {
+ proto_item_set_text(tree,
+ "%s Record Layer: Encrypted Alert",
+ ssl_version_short_names[*conv_version]);
+ proto_item_set_text(ssl_alert_tree,
+ "Alert Message: Encrypted Alert");
+ }
+ }
+}
+
+
+/* dissects the handshake protocol, filling the tree */
+static void
+dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint32 record_length, guint *conv_version)
+{
+ /* struct {
+ * HandshakeType msg_type;
+ * uint24 length;
+ * select (HandshakeType) {
+ * case hello_request: HelloRequest;
+ * case client_hello: ClientHello;
+ * case server_hello: ServerHello;
+ * case certificate: Certificate;
+ * case server_key_exchange: ServerKeyExchange;
+ * case certificate_request: CertificateRequest;
+ * case server_hello_done: ServerHelloDone;
+ * case certificate_verify: CertificateVerify;
+ * case client_key_exchange: ClientKeyExchange;
+ * case finished: Finished;
+ * } body;
+ * } Handshake;
+ */
+ proto_tree *ti = NULL;
+ proto_tree *ssl_hand_tree = NULL;
+ gchar *msg_type_str = NULL;
+ guint8 msg_type;
+ guint32 length;
+ gboolean first_iteration = TRUE;
+
+
+ /* just as there can be multiple records per packet, there
+ * can be multiple messages per record as long as they have
+ * the same content type
+ *
+ * we really only care about this for handshake messages
+ */
+
+ /* set record_length to the max offset */
+ record_length += offset;
+ while (offset < record_length)
+ {
+ msg_type = tvb_get_guint8(tvb, offset);
+ msg_type_str = match_strval(msg_type, ssl_31_handshake_type);
+ length = tvb_get_ntoh24(tvb, offset + 1);
+
+ if (!msg_type_str && !first_iteration)
+ {
+ /* only dissect / report messages if they're
+ * either the first message in this record
+ * or they're a valid message type
+ */
+ return;
+ }
+
+ /* on second and later iterations, add comma to info col */
+ if (!first_iteration)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", ");
+ }
+
+ /*
+ * Update our info string
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", (msg_type_str != NULL)
+ ? msg_type_str : "Encrypted Handshake Message");
+
+ if (tree)
+ {
+ /* set the label text on the record layer expanding node */
+ if (first_iteration)
+ {
+ proto_item_set_text(tree, "%s Record Layer: %s",
+ ssl_version_short_names[*conv_version],
+ (msg_type_str!=NULL) ? msg_type_str :
+ "Encrypted Handshake Message");
+ }
+ else
+ {
+ proto_item_set_text(tree, "%s Record Layer: %s",
+ ssl_version_short_names[*conv_version],
+ "Multiple Handshake Messages");
+ }
+
+ /* add a subtree for the handshake protocol */
+ ti = proto_tree_add_item(tree, hf_ssl_handshake_protocol, tvb,
+ offset, length + 4, 0);
+ ssl_hand_tree = proto_item_add_subtree(ti, ett_ssl_handshake);
+
+ if (ssl_hand_tree)
+ {
+ /* set the text label on the subtree node */
+ proto_item_set_text(ssl_hand_tree, "Handshake Protocol: %s",
+ (msg_type_str != NULL) ? msg_type_str :
+ "Encrypted Handshake Message");
+ }
+ }
+
+ /* if we don't have a valid handshake type, just quit dissecting */
+ if (!msg_type_str)
+ {
+ return;
+ }
+
+ if (ssl_hand_tree)
+ {
+ /* add nodes for the message type and message length */
+ proto_tree_add_item(ssl_hand_tree, hf_ssl_handshake_type,
+ tvb, offset, 1, msg_type);
+ offset++;
+ proto_tree_add_uint(ssl_hand_tree, hf_ssl_handshake_length,
+ tvb, offset, 3, length);
+ offset += 3;
+
+ /* now dissect the handshake message, if necessary */
+ switch (msg_type) {
+ case SSL_HND_HELLO_REQUEST:
+ /* hello_request has no fields, so nothing to do! */
+ break;
+
+ case SSL_HND_CLIENT_HELLO:
+ dissect_ssl3_hnd_cli_hello(tvb, ssl_hand_tree, offset);
+ break;
+
+ case SSL_HND_SERVER_HELLO:
+ dissect_ssl3_hnd_srv_hello(tvb, ssl_hand_tree, offset);
+ break;
+
+ case SSL_HND_CERTIFICATE:
+ dissect_ssl3_hnd_cert(tvb, ssl_hand_tree, offset);
+ break;
+
+ case SSL_HND_SERVER_KEY_EXCHG:
+ /* unimplemented */
+ break;
+
+ case SSL_HND_CERT_REQUEST:
+ dissect_ssl3_hnd_cert_req(tvb, ssl_hand_tree, offset);
+ break;
+
+ case SSL_HND_SVR_HELLO_DONE:
+ /* server_hello_done has no fields, so nothing to do! */
+ break;
+
+ case SSL_HND_CERT_VERIFY:
+ /* unimplemented */
+ break;
+
+ case SSL_HND_CLIENT_KEY_EXCHG:
+ /* unimplemented */
+ break;
+
+ case SSL_HND_FINISHED:
+ dissect_ssl3_hnd_finished(tvb, ssl_hand_tree,
+ offset, conv_version);
+ break;
+ }
+
+ }
+ else
+ {
+ offset += 4; /* skip the handshake header */
+ }
+ offset += length;
+ first_iteration = FALSE; /* set up for next pass, if any */
+ }
+}
+
+static int
+dissect_ssl3_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
+ guint32 offset)
+{
+ /* show the client's random challenge */
+ guint32 initial_offset = offset;
+ nstime_t gmt_unix_time;
+ guint8 session_id_length = 0;
+
+ if (tree)
+ {
+ /* show the time */
+ gmt_unix_time.secs = tvb_get_ntohl(tvb, offset);
+ gmt_unix_time.nsecs = 0;
+ proto_tree_add_time(tree, hf_ssl_handshake_random_time,
+ tvb, offset, 4, &gmt_unix_time);
+ offset += 4;
+
+ /* show the random bytes */
+ proto_tree_add_item(tree, hf_ssl_handshake_random_bytes,
+ tvb, offset, 28, 0);
+ offset += 28;
+
+ /* show the session id */
+ session_id_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_ssl_handshake_session_id_len,
+ tvb, offset++, 1, 0);
+ if (session_id_length > 0)
+ {
+ proto_tree_add_bytes_format(tree, hf_ssl_handshake_session_id,
+ tvb, offset, session_id_length,
+ tvb_get_ptr(tvb, offset, session_id_length),
+ "Session ID (%u byte%s)",
+ session_id_length,
+ plurality(session_id_length, "", "s"));
+ offset += session_id_length;
+ }
+
+ }
+ return offset - initial_offset;
+}
+
+static void
+dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+ /* struct {
+ * ProtocolVersion client_version;
+ * Random random;
+ * SessionID session_id;
+ * CipherSuite cipher_suites<2..2^16-1>;
+ * CompressionMethod compression_methods<1..2^8-1>;
+ * } ClientHello;
+ *
+ */
+ proto_tree *ti;
+ proto_tree *cs_tree;
+ guint16 cipher_suite_length = 0;
+ guint8 compression_methods_length = 0;
+ guint8 compression_method;
+
+ if (tree)
+ {
+ /* show the client version */
+ proto_tree_add_item(tree, hf_ssl_handshake_client_version, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ /* show the fields in common with server hello */
+ offset += dissect_ssl3_hnd_hello_common(tvb, tree, offset);
+
+ /* tell the user how many cipher suites there are */
+ cipher_suite_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ssl_handshake_cipher_suites_len,
+ tvb, offset, 2, cipher_suite_length);
+ offset += 2; /* skip opaque length */
+
+ if (cipher_suite_length > 0)
+ {
+ ti = proto_tree_add_none_format(tree,
+ hf_ssl_handshake_cipher_suites,
+ tvb, offset, cipher_suite_length,
+ "Cipher Suites (%u suite%s)",
+ cipher_suite_length / 2,
+ plurality(cipher_suite_length/2, "", "s"));
+
+ /* make this a subtree */
+ cs_tree = proto_item_add_subtree(ti, ett_ssl_cipher_suites);
+ if (!cs_tree)
+ {
+ cs_tree = tree; /* failsafe */
+ }
+
+ while (cipher_suite_length > 0)
+ {
+ proto_tree_add_item(cs_tree, hf_ssl_handshake_cipher_suite,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ cipher_suite_length -= 2;
+ }
+ }
+
+ /* tell the user how man compression methods there are */
+ compression_methods_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_ssl_handshake_comp_methods_len,
+ tvb, offset, 1, compression_methods_length);
+ offset++;
+
+ if (compression_methods_length > 0)
+ {
+ ti = proto_tree_add_none_format(tree,
+ hf_ssl_handshake_comp_methods,
+ tvb, offset, compression_methods_length,
+ "Compression Methods (%u method%s)",
+ compression_methods_length,
+ plurality(compression_methods_length,
+ "", "s"));
+
+ /* make this a subtree */
+ cs_tree = proto_item_add_subtree(ti, ett_ssl_comp_methods);
+ if (!cs_tree)
+ {
+ cs_tree = tree; /* failsafe */
+ }
+
+ while (compression_methods_length > 0)
+ {
+ compression_method = tvb_get_guint8(tvb, offset);
+ if (compression_method < 64)
+ proto_tree_add_uint(cs_tree, hf_ssl_handshake_comp_method,
+ tvb, offset, 1, compression_method);
+ else if (compression_method > 63 && compression_method < 193)
+ proto_tree_add_text(cs_tree, tvb, offset, 1,
+ "Compression Method: Reserved - to be assigned by IANA (%u)",
+ compression_method);
+ else
+ proto_tree_add_text(cs_tree, tvb, offset, 1,
+ "Compression Method: Private use range (%u)",
+ compression_method);
+ offset++;
+ compression_methods_length--;
+ }
+ }
+ }
+}
+
+static void
+dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+ /* struct {
+ * ProtocolVersion server_version;
+ * Random random;
+ * SessionID session_id;
+ * CipherSuite cipher_suite;
+ * CompressionMethod compression_method;
+ * } ServerHello;
+ */
+
+ if (tree)
+ {
+ /* show the server version */
+ proto_tree_add_item(tree, hf_ssl_handshake_server_version, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ /* first display the elements conveniently in
+ * common with client hello
+ */
+ offset += dissect_ssl3_hnd_hello_common(tvb, tree, offset);
+
+ /* now the server-selected cipher suite */
+ proto_tree_add_item(tree, hf_ssl_handshake_cipher_suite,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* and the server-selected compression method */
+ proto_tree_add_item(tree, hf_ssl_handshake_comp_method,
+ tvb, offset, 1, FALSE);
+ }
+}
+
+static void
+dissect_ssl3_hnd_cert(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+
+ /* opaque ASN.1Cert<2^24-1>;
+ *
+ * struct {
+ * ASN.1Cert certificate_list<1..2^24-1>;
+ * } Certificate;
+ */
+ guint32 certificate_list_length;
+ proto_tree *ti;
+ proto_tree *subtree;
+
+ if (tree)
+ {
+ certificate_list_length = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_uint(tree, hf_ssl_handshake_certificates_len,
+ tvb, offset, 3, certificate_list_length);
+ offset += 3; /* 24-bit length value */
+
+ if (certificate_list_length > 0)
+ {
+ ti = proto_tree_add_none_format(tree,
+ hf_ssl_handshake_certificates,
+ tvb, offset, certificate_list_length,
+ "Certificates (%u byte%s)",
+ certificate_list_length,
+ plurality(certificate_list_length,
+ "", "s"));
+
+ /* make it a subtree */
+ subtree = proto_item_add_subtree(ti, ett_ssl_certs);
+ if (!subtree)
+ {
+ subtree = tree; /* failsafe */
+ }
+
+ /* iterate through each certificate */
+ while (certificate_list_length > 0)
+ {
+ /* get the length of the current certificate */
+ guint32 cert_length = tvb_get_ntoh24(tvb, offset);
+ certificate_list_length -= 3 + cert_length;
+
+ proto_tree_add_item(subtree, hf_ssl_handshake_certificate_len,
+ tvb, offset, 3, FALSE);
+ offset += 3;
+
+ proto_tree_add_bytes_format(subtree,
+ hf_ssl_handshake_certificate,
+ tvb, offset, cert_length,
+ tvb_get_ptr(tvb, offset, cert_length),
+ "Certificate (%u byte%s)",
+ cert_length,
+ plurality(cert_length, "", "s"));
+
+ offset += cert_length;
+ }
+ }
+
+ }
+}
+
+static void
+dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+ /*
+ * enum {
+ * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
+ * (255)
+ * } ClientCertificateType;
+ *
+ * opaque DistinguishedName<1..2^16-1>;
+ *
+ * struct {
+ * ClientCertificateType certificate_types<1..2^8-1>;
+ * DistinguishedName certificate_authorities<3..2^16-1>;
+ * } CertificateRequest;
+ *
+ */
+ proto_tree *ti;
+ proto_tree *subtree;
+ guint8 cert_types_count = 0;
+ int dnames_length = 0;
+
+ if (tree)
+ {
+ cert_types_count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_ssl_handshake_cert_types_count,
+ tvb, offset, 1, cert_types_count);
+ offset++;
+
+ if (cert_types_count > 0)
+ {
+ ti = proto_tree_add_none_format(tree,
+ hf_ssl_handshake_cert_types,
+ tvb, offset, cert_types_count,
+ "Certificate types (%u type%s)",
+ cert_types_count,
+ plurality(cert_types_count, "", "s"));
+ subtree = proto_item_add_subtree(ti, ett_ssl_cert_types);
+ if (!subtree)
+ {
+ subtree = tree;
+ }
+
+ while (cert_types_count > 0)
+ {
+ proto_tree_add_item(subtree, hf_ssl_handshake_cert_type,
+ tvb, offset, 1, FALSE);
+ offset++;
+ cert_types_count--;
+ }
+ }
+
+ dnames_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ssl_handshake_dnames_len,
+ tvb, offset, 2, dnames_length);
+ offset += 2;
+
+ if (dnames_length > 0)
+ {
+ ti = proto_tree_add_none_format(tree,
+ hf_ssl_handshake_dnames,
+ tvb, offset, dnames_length,
+ "Distinguished Names (%d byte%s)",
+ dnames_length,
+ plurality(dnames_length, "", "s"));
+ subtree = proto_item_add_subtree(ti, ett_ssl_dnames);
+ if (!subtree)
+ {
+ subtree = tree;
+ }
+
+ while (dnames_length > 0)
+ {
+ /* get the length of the current certificate */
+ guint16 name_length = tvb_get_ntohs(tvb, offset);
+ dnames_length -= 2 + name_length;
+
+ proto_tree_add_item(subtree, hf_ssl_handshake_dname_len,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_bytes_format(subtree,
+ hf_ssl_handshake_dname,
+ tvb, offset, name_length,
+ tvb_get_ptr(tvb, offset, name_length),
+ "Distinguished Name (%u byte%s)",
+ name_length,
+ plurality(name_length, "", "s"));
+ offset += name_length;
+ }
+ }
+ }
+
+}
+
+static void
+dissect_ssl3_hnd_finished(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset,
+ guint *conv_version)
+{
+ /* For TLS:
+ * struct {
+ * opaque verify_data[12];
+ * } Finished;
+ *
+ * For SSLv3:
+ * struct {
+ * opaque md5_hash[16];
+ * opaque sha_hash[20];
+ * } Finished;
+ */
+
+ /* this all needs a tree, so bail if we don't have one */
+ if (!tree)
+ {
+ return;
+ }
+
+ switch(*conv_version) {
+ case SSL_VER_TLS:
+ proto_tree_add_item(tree, hf_ssl_handshake_finished,
+ tvb, offset, 12, FALSE);
+ break;
+
+ case SSL_VER_SSLv3:
+ proto_tree_add_item(tree, hf_ssl_handshake_md5_hash,
+ tvb, offset, 16, FALSE);
+ offset += 16;
+ proto_tree_add_item(tree, hf_ssl_handshake_sha_hash,
+ tvb, offset, 20, FALSE);
+ offset += 20;
+ break;
+ }
+}
+
+/*********************************************************************
+ *
+ * SSL version 2 Dissectors
+ *
+ *********************************************************************/
+
+
+/* record layer dissector */
+static int
+dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint32 offset, guint *conv_version,
+ gboolean *need_desegmentation)
+{
+ guint32 initial_offset = offset;
+ guint8 byte = 0;
+ guint8 record_length_length = 0;
+ guint32 record_length = 0;
+ gint is_escape = -1;
+ gint16 padding_length = -1;
+ guint8 msg_type = 0;
+ gchar *msg_type_str = NULL;
+ guint32 available_bytes = 0;
+
+ proto_tree *ti;
+ proto_tree *ssl_record_tree = NULL;
+
+ /* pull first byte; if high bit is set, then record
+ * length is three bytes due to padding; otherwise
+ * record length is two bytes
+ */
+ byte = tvb_get_guint8(tvb, offset);
+ record_length_length = (byte & 0x80) ? 2 : 3;
+
+ /*
+ * Can we do reassembly?
+ */
+ available_bytes = tvb_length_remaining(tvb, offset);
+
+ if (ssl_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the record header split across segment boundaries?
+ */
+ if (available_bytes < record_length_length) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = record_length_length - available_bytes;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+
+ /* parse out the record length */
+ switch(record_length_length) {
+ case 2: /* two-byte record length */
+ record_length = (byte & 0x7f) << 8;
+ byte = tvb_get_guint8(tvb, offset + 1);
+ record_length += byte;
+ break;
+ case 3: /* three-byte record length */
+ is_escape = (byte & 0x40) ? TRUE : FALSE;
+ record_length = (byte & 0x3f) << 8;
+ byte = tvb_get_guint8(tvb, offset + 1);
+ record_length += byte;
+ byte = tvb_get_guint8(tvb, offset + 2);
+ padding_length = byte;
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (ssl_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the record split across segment boundaries?
+ */
+ if (available_bytes < (record_length_length + record_length)) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this
+ * message starts in the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = (record_length_length + record_length)
+ - available_bytes;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+ offset += record_length_length;
+
+ /* add the record layer subtree header */
+ ti = proto_tree_add_item(tree, hf_ssl2_record, tvb, initial_offset,
+ record_length_length + record_length, 0);
+ ssl_record_tree = proto_item_add_subtree(ti, ett_ssl_record);
+
+ /* pull the msg_type so we can bail if it's unknown */
+ msg_type = tvb_get_guint8(tvb, initial_offset + record_length_length);
+
+ /* if we get a server_hello or later handshake in v2, then set
+ * this to sslv2
+ */
+ if (*conv_version == SSL_VER_UNKNOWN)
+ {
+ if (ssl_looks_like_valid_pct_handshake(tvb,
+ (initial_offset +
+ record_length_length),
+ record_length)) {
+ *conv_version = SSL_VER_PCT;
+ ssl_set_conv_version(pinfo, *conv_version);
+ }
+ else if (msg_type >= 2 && msg_type <= 8)
+ {
+ *conv_version = SSL_VER_SSLv2;
+ ssl_set_conv_version(pinfo, *conv_version);
+ }
+ }
+
+ /* if we get here, but don't have a version set for the
+ * conversation, then set a version for just this frame
+ * (e.g., on a client hello)
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ (*conv_version == SSL_VER_PCT) ? "PCT" : "SSLv2");
+ }
+
+ /* see if the msg_type is valid; if not the payload is
+ * probably encrypted, so note that fact and bail
+ */
+ msg_type_str = match_strval(msg_type,
+ (*conv_version == SSL_VER_PCT)
+ ? pct_msg_types : ssl_20_msg_types);
+ if (!msg_type_str
+ || ((*conv_version != SSL_VER_PCT) &&
+ !ssl_looks_like_valid_v2_handshake(tvb, initial_offset
+ + record_length_length,
+ record_length))
+ || ((*conv_version == SSL_VER_PCT) &&
+ !ssl_looks_like_valid_pct_handshake(tvb, initial_offset
+ + record_length_length,
+ record_length)))
+ {
+ if (ssl_record_tree)
+ {
+ proto_item_set_text(ssl_record_tree, "%s Record Layer: %s",
+ (*conv_version == SSL_VER_PCT)
+ ? "PCT" : "SSLv2",
+ "Encrypted Data");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Data");
+ return initial_offset + record_length_length + record_length;
+ }
+ else
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, msg_type_str);
+
+ if (ssl_record_tree)
+ {
+ proto_item_set_text(ssl_record_tree, "%s Record Layer: %s",
+ (*conv_version == SSL_VER_PCT)
+ ? "PCT" : "SSLv2",
+ msg_type_str);
+ }
+ }
+
+ /* We have a valid message type, so move foward, filling in the
+ * tree by adding the length, is_escape boolean and padding_length,
+ * if present in the original packet
+ */
+ if (ssl_record_tree)
+ {
+ /* add the record length */
+ ti = proto_tree_add_uint (ssl_record_tree,
+ hf_ssl_record_length, tvb,
+ initial_offset, record_length_length,
+ record_length);
+ }
+ if (ssl_record_tree && is_escape != -1)
+ {
+ proto_tree_add_boolean(ssl_record_tree,
+ hf_ssl2_record_is_escape, tvb,
+ initial_offset, 1, is_escape);
+ }
+ if (ssl_record_tree && padding_length != -1)
+ {
+ proto_tree_add_uint(ssl_record_tree,
+ hf_ssl2_record_padding_length, tvb,
+ initial_offset + 2, 1, padding_length);
+ }
+
+ /*
+ * dissect the record data
+ */
+
+ /* jump forward to the start of the record data */
+ offset = initial_offset + record_length_length;
+
+ /* add the message type */
+ if (ssl_record_tree)
+ {
+ proto_tree_add_item(ssl_record_tree,
+ (*conv_version == SSL_VER_PCT)
+ ? hf_pct_msg_type : hf_ssl2_msg_type,
+ tvb, offset, 1, 0);
+ }
+ offset++; /* move past msg_type byte */
+
+ if (*conv_version != SSL_VER_PCT)
+ {
+ /* dissect the message (only handle client hello right now) */
+ switch (msg_type) {
+ case SSL2_HND_CLIENT_HELLO:
+ dissect_ssl2_hnd_client_hello(tvb, ssl_record_tree, offset);
+ break;
+
+ case SSL2_HND_CLIENT_MASTER_KEY:
+ dissect_ssl2_hnd_client_master_key(tvb, ssl_record_tree, offset);
+ break;
+
+ case SSL2_HND_SERVER_HELLO:
+ dissect_ssl2_hnd_server_hello(tvb, ssl_record_tree, offset);
+ break;
+
+ case SSL2_HND_ERROR:
+ case SSL2_HND_CLIENT_FINISHED:
+ case SSL2_HND_SERVER_VERIFY:
+ case SSL2_HND_SERVER_FINISHED:
+ case SSL2_HND_REQUEST_CERTIFICATE:
+ case SSL2_HND_CLIENT_CERTIFICATE:
+ /* unimplemented */
+ break;
+
+ default: /* unknown */
+ break;
+ }
+ }
+ else
+ {
+ /* dissect the message */
+ switch (msg_type) {
+ case PCT_MSG_CLIENT_HELLO:
+ dissect_pct_msg_client_hello(tvb, ssl_record_tree, offset);
+ break;
+ case PCT_MSG_SERVER_HELLO:
+ dissect_pct_msg_server_hello(tvb, ssl_record_tree, offset);
+ break;
+ case PCT_MSG_CLIENT_MASTER_KEY:
+ dissect_pct_msg_client_master_key(tvb, ssl_record_tree, offset);
+ break;
+ case PCT_MSG_SERVER_VERIFY:
+ dissect_pct_msg_server_verify(tvb, ssl_record_tree, offset);
+ break;
+ case PCT_MSG_ERROR:
+ dissect_pct_msg_error(tvb, ssl_record_tree, offset);
+ break;
+
+ default: /* unknown */
+ break;
+ }
+ }
+ return (initial_offset + record_length_length + record_length);
+}
+
+static void
+dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+ /* struct {
+ * uint8 msg_type;
+ * Version version;
+ * uint16 cipher_spec_length;
+ * uint16 session_id_length;
+ * uint16 challenge_length;
+ * V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
+ * opaque session_id[V2ClientHello.session_id_length];
+ * Random challenge;
+ * } V2ClientHello;
+ *
+ * Note: when we get here, offset's already pointing at Version
+ *
+ */
+ guint16 version;
+ guint16 cipher_spec_length;
+ guint16 session_id_length;
+ guint16 challenge_length;
+
+ proto_tree *ti;
+ proto_tree *cs_tree;
+
+ version = tvb_get_ntohs(tvb, offset);
+ if (!ssl_is_valid_ssl_version(version))
+ {
+ /* invalid version; probably encrypted data */
+ return;
+ }
+
+ if (tree)
+ {
+ /* show the version */
+ proto_tree_add_item(tree, hf_ssl_record_version, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ cipher_spec_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_ssl2_handshake_cipher_spec_len,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ session_id_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_ssl2_handshake_session_id_len,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ challenge_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_ssl2_handshake_challenge_len,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* tell the user how many cipher specs they've won */
+ ti = proto_tree_add_none_format(tree, hf_ssl_handshake_cipher_suites,
+ tvb, offset, cipher_spec_length,
+ "Cipher Specs (%u specs)",
+ cipher_spec_length/3);
+
+ /* make this a subtree and expand the actual specs below */
+ cs_tree = proto_item_add_subtree(ti, ett_ssl_cipher_suites);
+ if (!cs_tree)
+ {
+ cs_tree = tree; /* failsafe */
+ }
+
+ /* iterate through the cipher specs, showing them */
+ while (cipher_spec_length > 0)
+ {
+ proto_tree_add_item(cs_tree, hf_ssl2_handshake_cipher_spec,
+ tvb, offset, 3, FALSE);
+ offset += 3; /* length of one cipher spec */
+ cipher_spec_length -= 3;
+ }
+
+ /* if there's a session id, show it */
+ if (session_id_length > 0)
+ {
+ proto_tree_add_bytes_format(tree,
+ hf_ssl_handshake_session_id,
+ tvb, offset, session_id_length,
+ tvb_get_ptr(tvb, offset, session_id_length),
+ "Session ID (%u byte%s)",
+ session_id_length,
+ plurality(session_id_length, "", "s"));
+
+ offset += session_id_length;
+ }
+
+ /* if there's a challenge, show it */
+ if (challenge_length > 0)
+ {
+ proto_tree_add_item(tree, hf_ssl2_handshake_challenge,
+ tvb, offset, challenge_length, 0);
+ offset += challenge_length;
+ }
+ }
+}
+
+static void
+dissect_pct_msg_client_hello(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+ guint16 CH_CLIENT_VERSION, CH_OFFSET, CH_CIPHER_SPECS_LENGTH, CH_HASH_SPECS_LENGTH, CH_CERT_SPECS_LENGTH, CH_EXCH_SPECS_LENGTH, CH_KEY_ARG_LENGTH;
+ proto_item *CH_CIPHER_SPECS_ti, *CH_HASH_SPECS_ti, *CH_CERT_SPECS_ti, *CH_EXCH_SPECS_ti;
+ proto_tree *CH_CIPHER_SPECS_tree, *CH_HASH_SPECS_tree, *CH_CERT_SPECS_tree, *CH_EXCH_SPECS_tree;
+ gint i;
+
+ CH_CLIENT_VERSION = tvb_get_ntohs(tvb, offset);
+ if(CH_CLIENT_VERSION != PCT_VERSION_1)
+ proto_tree_add_text(tree, tvb, offset, 2, "Client Version, should be %x in PCT version 1", PCT_VERSION_1);
+ else
+ proto_tree_add_text(tree, tvb, offset, 2, "Client Version (%x)", PCT_VERSION_1);
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "PAD");
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 32, "Client Session ID Data (32 bytes)");
+ offset += 32;
+
+ proto_tree_add_text(tree, tvb, offset, 32, "Challange Data(32 bytes)");
+ offset += 32;
+
+ CH_OFFSET = tvb_get_ntohs(tvb, offset);
+ if(CH_OFFSET != PCT_CH_OFFSET_V1)
+ proto_tree_add_text(tree, tvb, offset, 2, "CH_OFFSET: %d, should be %d in PCT version 1", CH_OFFSET, PCT_CH_OFFSET_V1);
+ else
+ proto_tree_add_text(tree, tvb, offset, 2, "CH_OFFSET: %d", CH_OFFSET);
+ offset += 2;
+
+ CH_CIPHER_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "CIPHER_SPECS Length: %d", CH_CIPHER_SPECS_LENGTH);
+ offset += 2;
+
+ CH_HASH_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "HASH_SPECS Length: %d", CH_HASH_SPECS_LENGTH);
+ offset += 2;
+
+ CH_CERT_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "CERT_SPECS Length: %d", CH_CERT_SPECS_LENGTH);
+ offset += 2;
+
+ CH_EXCH_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "EXCH_SPECS Length: %d", CH_EXCH_SPECS_LENGTH);
+ offset += 2;
+
+ CH_KEY_ARG_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "IV Length: %d", CH_KEY_ARG_LENGTH);
+ offset += 2;
+
+ if(CH_CIPHER_SPECS_LENGTH) {
+ CH_CIPHER_SPECS_ti = proto_tree_add_item(tree, hf_pct_handshake_cipher_spec, tvb, offset, CH_CIPHER_SPECS_LENGTH, FALSE);
+ CH_CIPHER_SPECS_tree = proto_item_add_subtree(CH_CIPHER_SPECS_ti, ett_pct_cipher_suites);
+
+ for(i=0; i<(CH_CIPHER_SPECS_LENGTH/4); i++) {
+ proto_tree_add_item(CH_CIPHER_SPECS_tree, hf_pct_handshake_cipher, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_text(CH_CIPHER_SPECS_tree, tvb, offset, 1, "Encryption key length: %d", tvb_get_guint8(tvb, offset));
+ offset += 1;
+ proto_tree_add_text(CH_CIPHER_SPECS_tree, tvb, offset, 1, "MAC key length in bits: %d", tvb_get_guint8(tvb, offset) + 64);
+ offset += 1;
+ }
+ }
+
+ if(CH_HASH_SPECS_LENGTH) {
+ CH_HASH_SPECS_ti = proto_tree_add_item(tree, hf_pct_handshake_hash_spec, tvb, offset, CH_HASH_SPECS_LENGTH, FALSE);
+ CH_HASH_SPECS_tree = proto_item_add_subtree(CH_HASH_SPECS_ti, ett_pct_hash_suites);
+
+ for(i=0; i<(CH_HASH_SPECS_LENGTH/2); i++) {
+ proto_tree_add_item(CH_HASH_SPECS_tree, hf_pct_handshake_hash, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ }
+
+ if(CH_CERT_SPECS_LENGTH) {
+ CH_CERT_SPECS_ti = proto_tree_add_item(tree, hf_pct_handshake_cert_spec, tvb, offset, CH_CERT_SPECS_LENGTH, FALSE);
+ CH_CERT_SPECS_tree = proto_item_add_subtree(CH_CERT_SPECS_ti, ett_pct_cert_suites);
+
+ for(i=0; i< (CH_CERT_SPECS_LENGTH/2); i++) {
+ proto_tree_add_item(CH_CERT_SPECS_tree, hf_pct_handshake_cert, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ }
+
+ if(CH_EXCH_SPECS_LENGTH) {
+ CH_EXCH_SPECS_ti = proto_tree_add_item(tree, hf_pct_handshake_exch_spec, tvb, offset, CH_EXCH_SPECS_LENGTH, FALSE);
+ CH_EXCH_SPECS_tree = proto_item_add_subtree(CH_EXCH_SPECS_ti, ett_pct_exch_suites);
+
+ for(i=0; i<(CH_EXCH_SPECS_LENGTH/2); i++) {
+ proto_tree_add_item(CH_EXCH_SPECS_tree, hf_pct_handshake_exch, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+ }
+
+ if(CH_KEY_ARG_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, CH_KEY_ARG_LENGTH, "IV data (%d bytes)", CH_KEY_ARG_LENGTH);
+ offset += CH_KEY_ARG_LENGTH;
+ }
+}
+
+static void
+dissect_pct_msg_server_hello(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+/* structure:
+char SH_MSG_SERVER_HELLO
+char SH_PAD
+char SH_SERVER_VERSION_MSB
+char SH_SERVER_VERSION_LSB
+char SH_RESTART_SESSION_OK
+char SH_CLIENT_AUTH_REQ
+char SH_CIPHER_SPECS_DATA[4]
+char SH_HASH_SPECS_DATA[2]
+char SH_CERT_SPECS_DATA[2]
+char SH_EXCH_SPECS_DATA[2]
+char SH_CONNECTION_ID_DATA[32]
+char SH_CERTIFICATE_LENGTH_MSB
+char SH_CERTIFICATE_LENGTH_LSB
+char SH_CLIENT_CERT_SPECS_LENGTH_MSB
+char SH_CLIENT_CERT_SPECS_LENGTH_LSB
+char SH_CLIENT_SIG_SPECS_LENGTH_MSB
+char SH_CLIENT_SIG_SPECS_LENGTH_LSB
+char SH_RESPONSE_LENGTH_MSB
+char SH_RESPONSE_LENGTH_LSB
+char SH_CERTIFICATE_DATA[MSB<<8|LSB]
+char SH_CLIENT_CERT_SPECS_DATA[MSB<<8|LSB]
+char SH_CLIENT_SIG_SPECS_DATA[MSB<<8|LSB]
+char SH_RESPONSE_DATA[MSB<<8|LSB]
+
+*/
+
+ guint16 SH_SERVER_VERSION, SH_CERT_LENGTH, SH_CERT_SPECS_LENGTH, SH_CLIENT_SIG_LENGTH, SH_RESPONSE_LENGTH;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "PAD");
+ offset += 1;
+
+ SH_SERVER_VERSION = tvb_get_ntohs(tvb, offset);
+ if(SH_SERVER_VERSION != PCT_VERSION_1)
+ proto_tree_add_text(tree, tvb, offset, 2, "Server Version, should be %x in PCT version 1", PCT_VERSION_1);
+ else
+ proto_tree_add_text(tree, tvb, offset, 2, "Server Version (%x)", PCT_VERSION_1);
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "SH_RESTART_SESSION_OK flag");
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "SH_CLIENT_AUTH_REQ flag");
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_pct_handshake_cipher, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_text(tree, tvb, offset, 1, "Encryption key length: %d", tvb_get_guint8(tvb, offset));
+ offset += 1;
+ proto_tree_add_text(tree, tvb, offset, 1, "MAC key length in bits: %d", tvb_get_guint8(tvb, offset) + 64);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_pct_handshake_hash, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_pct_handshake_cert, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_pct_handshake_exch, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 32, "Connection ID Data (32 bytes)");
+ offset += 32;
+
+ SH_CERT_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Server Certificate Length: %d", SH_CERT_LENGTH);
+ offset += 2;
+
+ SH_CERT_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Client CERT_SPECS Length: %d", SH_CERT_SPECS_LENGTH);
+ offset += 2;
+
+ SH_CLIENT_SIG_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Client SIG_SPECS Length: %d", SH_CLIENT_SIG_LENGTH);
+ offset += 2;
+
+ SH_RESPONSE_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Response Length: %d", SH_RESPONSE_LENGTH);
+ offset += 2;
+
+ if(SH_CERT_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, SH_CERT_LENGTH, "Server Certificate (%d bytes)", SH_CERT_LENGTH);
+ offset += SH_CERT_LENGTH;
+ }
+
+ if(SH_CERT_SPECS_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, SH_CERT_SPECS_LENGTH, "Client CERT_SPECS (%d bytes)", SH_CERT_SPECS_LENGTH);
+ offset += SH_CERT_SPECS_LENGTH;
+ }
+
+ if(SH_CLIENT_SIG_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, SH_CLIENT_SIG_LENGTH, "Client Signature (%d bytes)", SH_CLIENT_SIG_LENGTH);
+ offset += SH_CLIENT_SIG_LENGTH;
+ }
+
+ if(SH_RESPONSE_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, SH_RESPONSE_LENGTH, "Server Response (%d bytes)", SH_RESPONSE_LENGTH);
+ offset += SH_RESPONSE_LENGTH;
+ }
+
+}
+
+static void
+dissect_pct_msg_client_master_key(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
+{
+ guint16 CMK_CLEAR_KEY_LENGTH, CMK_ENCRYPTED_KEY_LENGTH, CMK_KEY_ARG_LENGTH, CMK_VERIFY_PRELUDE, CMK_CLIENT_CERT_LENGTH, CMK_RESPONSE_LENGTH;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "PAD");
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_pct_handshake_cert, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_pct_handshake_sig, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ CMK_CLEAR_KEY_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Clear Key Length: %d",CMK_CLEAR_KEY_LENGTH);
+ offset += 2;
+
+ CMK_ENCRYPTED_KEY_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Encrypted Key Length: %d",CMK_ENCRYPTED_KEY_LENGTH);
+ offset += 2;
+
+ CMK_KEY_ARG_LENGTH= tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "IV Length: %d",CMK_KEY_ARG_LENGTH);
+ offset += 2;
+
+ CMK_VERIFY_PRELUDE = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Verify Prelude Length: %d",CMK_VERIFY_PRELUDE);
+ offset += 2;
+
+ CMK_CLIENT_CERT_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Client Cert Length: %d",CMK_CLIENT_CERT_LENGTH);
+ offset += 2;
+
+ CMK_RESPONSE_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Response Length: %d",CMK_RESPONSE_LENGTH);
+ offset += 2;
+
+ if(CMK_CLEAR_KEY_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, CMK_CLEAR_KEY_LENGTH, "Clear Key data (%d bytes)", CMK_CLEAR_KEY_LENGTH);
+ offset += CMK_CLEAR_KEY_LENGTH;
+ }
+ if(CMK_ENCRYPTED_KEY_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, CMK_ENCRYPTED_KEY_LENGTH, "Encrypted Key data (%d bytes)", CMK_ENCRYPTED_KEY_LENGTH);
+ offset += CMK_ENCRYPTED_KEY_LENGTH;
+ }
+ if(CMK_KEY_ARG_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, CMK_KEY_ARG_LENGTH, "IV data (%d bytes)", CMK_KEY_ARG_LENGTH);
+ offset += CMK_KEY_ARG_LENGTH;
+ }
+ if(CMK_VERIFY_PRELUDE) {
+ proto_tree_add_text(tree, tvb, offset, CMK_VERIFY_PRELUDE, "Verify Prelude data (%d bytes)", CMK_VERIFY_PRELUDE);
+ offset += CMK_VERIFY_PRELUDE;
+ }
+ if(CMK_CLIENT_CERT_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, CMK_CLIENT_CERT_LENGTH, "Client Certificate data (%d bytes)", CMK_CLIENT_CERT_LENGTH);
+ offset += CMK_CLIENT_CERT_LENGTH;
+ }
+ if(CMK_RESPONSE_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, CMK_RESPONSE_LENGTH, "Response data (%d bytes)", CMK_RESPONSE_LENGTH);
+ offset += CMK_RESPONSE_LENGTH;
+ }
+}
+
+static void
+dissect_pct_msg_server_verify(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+ guint16 SV_RESPONSE_LENGTH;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "PAD");
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 32, "Server Session ID data (32 bytes)");
+ offset += 32;
+
+ SV_RESPONSE_LENGTH = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Server Response Length: %d", SV_RESPONSE_LENGTH);
+ offset += 2;
+
+ if(SV_RESPONSE_LENGTH) {
+ proto_tree_add_text(tree, tvb, offset, SV_RESPONSE_LENGTH, "Server Response (%d bytes)", SV_RESPONSE_LENGTH);
+ offset += SV_RESPONSE_LENGTH;
+ }
+}
+
+static void
+dissect_pct_msg_error(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+ guint16 ERROR_CODE, INFO_LEN;
+
+ ERROR_CODE = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_pct_msg_error_type, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ INFO_LEN = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Eror Information Length: %d", INFO_LEN);
+ offset += 2;
+ if (ERROR_CODE == PCT_ERR_SPECS_MISMATCH && INFO_LEN == 6)
+ {
+ proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_CIPHER");
+ offset += 1;
+ proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_HASH");
+ offset += 1;
+ proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_CERT");
+ offset += 1;
+ proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_EXCH");
+ offset += 1;
+ proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_CLIENT_CERT");
+ offset += 1;
+ proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_CLIENT_SIG");
+ offset += 1;
+ }
+ else if(INFO_LEN) {
+ proto_tree_add_text(tree, tvb, offset, INFO_LEN, "Error Information dta (%d bytes)", INFO_LEN);
+ offset += INFO_LEN;
+ }
+}
+
+static void
+dissect_ssl2_hnd_client_master_key(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+ /* struct {
+ * uint8 msg_type;
+ * V2Cipherspec cipher;
+ * uint16 clear_key_length;
+ * uint16 encrypted_key_length;
+ * uint16 key_arg_length;
+ * opaque clear_key_data[V2ClientMasterKey.clear_key_length];
+ * opaque encrypted_key_data[V2ClientMasterKey.encrypted_key_length];
+ * opaque key_arg_data[V2ClientMasterKey.key_arg_length];
+ * } V2ClientMasterKey;
+ *
+ * Note: when we get here, offset's already pointing at cipher
+ */
+ guint16 clear_key_length;
+ guint16 encrypted_key_length;
+ guint16 key_arg_length;
+
+ /* at this point, everything we do involves the tree,
+ * so quit now if we don't have one ;-)
+ */
+ if (!tree)
+ {
+ return;
+ }
+
+ /* show the selected cipher */
+ proto_tree_add_item(tree, hf_ssl2_handshake_cipher_spec,
+ tvb, offset, 3, FALSE);
+ offset += 3;
+
+ /* get the fixed fields */
+ clear_key_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_ssl2_handshake_clear_key_len,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ encrypted_key_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_ssl2_handshake_enc_key_len,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ key_arg_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(tree, hf_ssl2_handshake_key_arg_len,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* show the variable length fields */
+ if (clear_key_length > 0)
+ {
+ proto_tree_add_item(tree, hf_ssl2_handshake_clear_key,
+ tvb, offset, clear_key_length, FALSE);
+ offset += clear_key_length;
+ }
+
+ if (encrypted_key_length > 0)
+ {
+ proto_tree_add_item(tree, hf_ssl2_handshake_enc_key,
+ tvb, offset, encrypted_key_length, FALSE);
+ offset += encrypted_key_length;
+ }
+
+ if (key_arg_length > 0)
+ {
+ proto_tree_add_item(tree, hf_ssl2_handshake_key_arg,
+ tvb, offset, key_arg_length, FALSE);
+ offset += key_arg_length;
+ }
+
+}
+
+static void
+dissect_ssl2_hnd_server_hello(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset)
+{
+ /* struct {
+ * uint8 msg_type;
+ * uint8 session_id_hit;
+ * uint8 certificate_type;
+ * uint16 server_version;
+ * uint16 certificate_length;
+ * uint16 cipher_specs_length;
+ * uint16 connection_id_length;
+ * opaque certificate_data[V2ServerHello.certificate_length];
+ * opaque cipher_specs_data[V2ServerHello.cipher_specs_length];
+ * opaque connection_id_data[V2ServerHello.connection_id_length];
+ * } V2ServerHello;
+ *
+ * Note: when we get here, offset's already pointing at session_id_hit
+ */
+ guint16 certificate_length;
+ guint16 cipher_spec_length;
+ guint16 connection_id_length;
+ guint16 version;
+ proto_tree *ti;
+ proto_tree *subtree;
+
+ /* everything we do only makes sense with a tree, so
+ * quit now if we don't have one
+ */
+ if (!tree)
+ {
+ return;
+ }
+
+ version = tvb_get_ntohs(tvb, offset + 2);
+ if (!ssl_is_valid_ssl_version(version))
+ {
+ /* invalid version; probably encrypted data */
+ return;
+ }
+
+
+ /* is there a hit? */
+ proto_tree_add_item(tree, hf_ssl2_handshake_session_id_hit,
+ tvb, offset, 1, FALSE);
+ offset++;
+
+ /* what type of certificate is this? */
+ proto_tree_add_item(tree, hf_ssl2_handshake_cert_type,
+ tvb, offset, 1, FALSE);
+ offset++;
+
+ /* now the server version */
+ proto_tree_add_item(tree, hf_ssl_handshake_server_version,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* get the fixed fields */
+ certificate_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ssl_handshake_certificate_len,
+ tvb, offset, 2, certificate_length);
+ offset += 2;
+
+ cipher_spec_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ssl2_handshake_cipher_spec_len,
+ tvb, offset, 2, cipher_spec_length);
+ offset += 2;
+
+ connection_id_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_ssl2_handshake_connection_id_len,
+ tvb, offset, 2, connection_id_length);
+ offset += 2;
+
+ /* now the variable length fields */
+ if (certificate_length > 0)
+ {
+ proto_tree_add_bytes_format(tree, hf_ssl_handshake_certificate,
+ tvb, offset, certificate_length,
+ tvb_get_ptr(tvb, offset, certificate_length),
+ "Certificate (%u byte%s)",
+ certificate_length,
+ plurality(certificate_length, "", "s"));
+ offset += certificate_length;
+ }
+
+ if (cipher_spec_length > 0)
+ {
+ /* provide a collapsing node for the cipher specs */
+ ti = proto_tree_add_none_format(tree,
+ hf_ssl_handshake_cipher_suites,
+ tvb, offset, cipher_spec_length,
+ "Cipher Specs (%u spec%s)",
+ cipher_spec_length/3,
+ plurality(cipher_spec_length/3, "", "s"));
+ subtree = proto_item_add_subtree(ti, ett_ssl_cipher_suites);
+ if (!subtree)
+ {
+ subtree = tree;
+ }
+
+ /* iterate through the cipher specs */
+ while (cipher_spec_length > 0)
+ {
+ proto_tree_add_item(subtree, hf_ssl2_handshake_cipher_spec,
+ tvb, offset, 3, FALSE);
+ offset += 3;
+ cipher_spec_length -= 3;
+ }
+ }
+
+ if (connection_id_length > 0)
+ {
+ proto_tree_add_item(tree, hf_ssl2_handshake_connection_id,
+ tvb, offset, connection_id_length, FALSE);
+ offset += connection_id_length;
+ }
+
+}
+
+
+
+
+/*********************************************************************
+ *
+ * Support Functions
+ *
+ *********************************************************************/
+
+static void
+ssl_set_conv_version(packet_info *pinfo, guint version)
+{
+ conversation_t *conversation;
+
+ if (pinfo->fd->flags.visited)
+ {
+ /* We've already processed this frame; no need to do any more
+ * work on it.
+ */
+ return;
+ }
+
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+
+ if (conversation == NULL)
+ {
+ /* create a new conversation */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ }
+
+ if (conversation_get_proto_data(conversation, proto_ssl) != NULL)
+ {
+ /* get rid of the current data */
+ conversation_delete_proto_data(conversation, proto_ssl);
+ }
+ conversation_add_proto_data(conversation, proto_ssl, GINT_TO_POINTER(version));
+}
+
+static int
+ssl_is_valid_handshake_type(guint8 type)
+{
+
+ switch (type) {
+ case SSL_HND_HELLO_REQUEST:
+ case SSL_HND_CLIENT_HELLO:
+ case SSL_HND_SERVER_HELLO:
+ case SSL_HND_CERTIFICATE:
+ case SSL_HND_SERVER_KEY_EXCHG:
+ case SSL_HND_CERT_REQUEST:
+ case SSL_HND_SVR_HELLO_DONE:
+ case SSL_HND_CERT_VERIFY:
+ case SSL_HND_CLIENT_KEY_EXCHG:
+ case SSL_HND_FINISHED:
+ return 1;
+ }
+ return 0;
+}
+
+static int
+ssl_is_valid_content_type(guint8 type)
+{
+ if (type >= 0x14 && type <= 0x17)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+ssl_is_valid_ssl_version(guint16 version)
+{
+ gchar *version_str = match_strval(version, ssl_versions);
+ return version_str != NULL;
+}
+
+static int
+ssl_is_authoritative_version_message(guint8 content_type,
+ guint8 next_byte)
+{
+ if (content_type == SSL_ID_HANDSHAKE
+ && ssl_is_valid_handshake_type(next_byte))
+ {
+ return (next_byte != SSL_HND_CLIENT_HELLO);
+ }
+ else if (ssl_is_valid_content_type(content_type)
+ && content_type != SSL_ID_HANDSHAKE)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+static int
+ssl_is_v2_client_hello(tvbuff_t *tvb, guint32 offset)
+{
+ guint8 byte;
+
+ byte = tvb_get_guint8(tvb, offset);
+ if (byte != 0x80) /* v2 client hello should start this way */
+ {
+ return 0;
+ }
+
+ byte = tvb_get_guint8(tvb, offset+2);
+ if (byte != 0x01) /* v2 client hello msg type */
+ {
+ return 0;
+ }
+
+ /* 1 in 2^16 of being right; improve later if necessary */
+ return 1;
+}
+
+/* this applies a heuristic to determine whether
+ * or not the data beginning at offset looks like a
+ * valid sslv2 record. this isn't really possible,
+ * but we'll try to do a reasonable job anyway.
+ */
+static int
+ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset)
+{
+ /* here's the current approach:
+ *
+ * we only try to catch unencrypted handshake messages, so we can
+ * assume that there is not padding. This means that the
+ * first byte must be >= 0x80 and there must be a valid sslv2
+ * msg_type in the third byte
+ */
+
+ /* get the first byte; must have high bit set */
+ guint8 byte = tvb_get_guint8(tvb, offset);
+ if (byte < 0x80)
+ {
+ return 0;
+ }
+
+ /* get the supposed msg_type byte; since we only care about
+ * unencrypted handshake messages (we can't tell the type for
+ * encrypted messages), we just check against that list
+ */
+ byte = tvb_get_guint8(tvb, offset + 2);
+ switch(byte) {
+ case SSL2_HND_ERROR:
+ case SSL2_HND_CLIENT_HELLO:
+ case SSL2_HND_CLIENT_MASTER_KEY:
+ case SSL2_HND_SERVER_HELLO:
+ case PCT_MSG_CLIENT_MASTER_KEY:
+ case PCT_MSG_ERROR:
+ return 1;
+ }
+ return 0;
+}
+
+/* this applies a heuristic to determine whether
+ * or not the data beginning at offset looks like a
+ * valid sslv3 record. this is somewhat more reliable
+ * than sslv2 due to the structure of the v3 protocol
+ */
+static int
+ssl_looks_like_sslv3(tvbuff_t *tvb, guint32 offset)
+{
+ /* have to have a valid content type followed by a valid
+ * protocol version
+ */
+ guint8 byte;
+ guint16 version;
+
+ /* see if the first byte is a valid content type */
+ byte = tvb_get_guint8(tvb, offset);
+ if (!ssl_is_valid_content_type(byte))
+ {
+ return 0;
+ }
+
+ /* now check to see if the version byte appears valid */
+ version = tvb_get_ntohs(tvb, offset + 1);
+ if (version != 0x0300 && version != 0x0301)
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+/* applies a heuristic to determine whether
+ * or not the data beginning at offset looks
+ * like a valid, unencrypted v2 handshake message.
+ * since it isn't possible to completely tell random
+ * data apart from a valid message without state,
+ * we try to help the odds.
+ */
+static int
+ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb, guint32 offset,
+ guint32 record_length)
+{
+ /* first byte should be a msg_type.
+ *
+ * - we know we only see client_hello, client_master_key,
+ * and server_hello in the clear, so check to see if
+ * msg_type is one of those (this gives us a 3 in 2^8
+ * chance of saying yes with random payload)
+ *
+ * - for those three types that we know about, do some
+ * further validation to reduce the chance of an error
+ */
+ guint8 msg_type;
+ guint16 version;
+ guint32 sum;
+
+ /* fetch the msg_type */
+ msg_type = tvb_get_guint8(tvb, offset);
+
+ switch (msg_type) {
+ case SSL2_HND_CLIENT_HELLO:
+ /* version follows msg byte, so verify that this is valid */
+ version = tvb_get_ntohs(tvb, offset+1);
+ return ssl_is_valid_ssl_version(version);
+ break;
+
+ case SSL2_HND_SERVER_HELLO:
+ /* version is three bytes after msg_type */
+ version = tvb_get_ntohs(tvb, offset+3);
+ return ssl_is_valid_ssl_version(version);
+ break;
+
+ case SSL2_HND_CLIENT_MASTER_KEY:
+ /* sum of clear_key_length, encrypted_key_length, and key_arg_length
+ * must be less than record length
+ */
+ sum = tvb_get_ntohs(tvb, offset + 4); /* clear_key_length */
+ sum += tvb_get_ntohs(tvb, offset + 6); /* encrypted_key_length */
+ sum += tvb_get_ntohs(tvb, offset + 8); /* key_arg_length */
+ if (sum > record_length)
+ {
+ return 0;
+ }
+ return 1;
+ break;
+
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+/* applies a heuristic to determine whether
+ * or not the data beginning at offset looks
+ * like a valid, unencrypted v2 handshake message.
+ * since it isn't possible to completely tell random
+ * data apart from a valid message without state,
+ * we try to help the odds.
+ */
+static int
+ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb, guint32 offset,
+ guint32 record_length)
+{
+ /* first byte should be a msg_type.
+ *
+ * - we know we only see client_hello, client_master_key,
+ * and server_hello in the clear, so check to see if
+ * msg_type is one of those (this gives us a 3 in 2^8
+ * chance of saying yes with random payload)
+ *
+ * - for those three types that we know about, do some
+ * further validation to reduce the chance of an error
+ */
+ guint8 msg_type;
+ guint16 version;
+ guint32 sum;
+
+ /* fetch the msg_type */
+ msg_type = tvb_get_guint8(tvb, offset);
+
+ switch (msg_type) {
+ case PCT_MSG_CLIENT_HELLO:
+ /* version follows msg byte, so verify that this is valid */
+ version = tvb_get_ntohs(tvb, offset+1);
+ return version == PCT_VERSION_1;
+ break;
+
+ case PCT_MSG_SERVER_HELLO:
+ /* version is one byte after msg_type */
+ version = tvb_get_ntohs(tvb, offset+2);
+ return version == PCT_VERSION_1;
+ break;
+
+ case PCT_MSG_CLIENT_MASTER_KEY:
+ /* sum of various length fields must be less than record length */
+ sum = tvb_get_ntohs(tvb, offset + 6); /* clear_key_length */
+ sum += tvb_get_ntohs(tvb, offset + 8); /* encrypted_key_length */
+ sum += tvb_get_ntohs(tvb, offset + 10); /* key_arg_length */
+ sum += tvb_get_ntohs(tvb, offset + 12); /* verify_prelude_length */
+ sum += tvb_get_ntohs(tvb, offset + 14); /* client_cert_length */
+ sum += tvb_get_ntohs(tvb, offset + 16); /* response_length */
+ if (sum > record_length)
+ {
+ return 0;
+ }
+ return 1;
+ break;
+
+ case PCT_MSG_SERVER_VERIFY:
+ /* record is 36 bytes longer than response_length */
+ sum = tvb_get_ntohs(tvb, offset + 34); /* response_length */
+ if ((sum + 36) == record_length)
+ return 1;
+ else
+ return 0;
+ break;
+
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+
+/*********************************************************************
+ *
+ * Standard Ethereal Protocol Registration and housekeeping
+ *
+ *********************************************************************/
+void
+proto_register_ssl(void)
+{
+
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_ssl_record,
+ { "Record Layer", "ssl.record",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Record layer", HFILL }
+ },
+ { &hf_ssl_record_content_type,
+ { "Content Type", "ssl.record.content_type",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_content_type), 0x0,
+ "Content type", HFILL}
+ },
+ { &hf_ssl2_msg_type,
+ { "Handshake Message Type", "ssl.handshake.type",
+ FT_UINT8, BASE_DEC, VALS(ssl_20_msg_types), 0x0,
+ "SSLv2 handshake message type", HFILL}
+ },
+ { &hf_pct_msg_type,
+ { "Handshake Message Type", "ssl.pct_handshake.type",
+ FT_UINT8, BASE_DEC, VALS(pct_msg_types), 0x0,
+ "PCT handshake message type", HFILL}
+ },
+ { &hf_ssl_record_version,
+ { "Version", "ssl.record.version",
+ FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
+ "Record layer version.", HFILL }
+ },
+ { &hf_ssl_record_length,
+ { "Length", "ssl.record.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of SSL record data", HFILL }
+ },
+ { &hf_ssl_record_appdata,
+ { "Application Data", "ssl.app_data",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Payload is application data", HFILL }
+ },
+ { & hf_ssl2_record,
+ { "SSLv2/PCT Record Header", "ssl.record",
+ FT_NONE, BASE_DEC, NULL, 0x0,
+ "SSLv2/PCT record data", HFILL }
+ },
+ { &hf_ssl2_record_is_escape,
+ { "Is Escape", "ssl.record.is_escape",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Indicates a security escape", HFILL}
+ },
+ { &hf_ssl2_record_padding_length,
+ { "Padding Length", "ssl.record.padding_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of padding at end of record", HFILL }
+ },
+ { &hf_ssl_change_cipher_spec,
+ { "Change Cipher Spec Message", "ssl.change_cipher_spec",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Signals a change in cipher specifications", HFILL }
+ },
+ { & hf_ssl_alert_message,
+ { "Alert Message", "ssl.alert_message",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Alert message", HFILL }
+ },
+ { & hf_ssl_alert_message_level,
+ { "Level", "ssl.alert_message.level",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_alert_level), 0x0,
+ "Alert message level", HFILL }
+ },
+ { &hf_ssl_alert_message_description,
+ { "Description", "ssl.alert_message.desc",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_alert_description), 0x0,
+ "Alert message description", HFILL }
+ },
+ { &hf_ssl_handshake_protocol,
+ { "Handshake Protocol", "ssl.handshake",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Handshake protocol message", HFILL}
+ },
+ { &hf_ssl_handshake_type,
+ { "Handshake Type", "ssl.handshake.type",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_handshake_type), 0x0,
+ "Type of handshake message", HFILL}
+ },
+ { &hf_ssl_handshake_length,
+ { "Length", "ssl.handshake.length",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Length of handshake message", HFILL }
+ },
+ { &hf_ssl_handshake_client_version,
+ { "Version", "ssl.handshake.version",
+ FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
+ "Maximum version supported by client", HFILL }
+ },
+ { &hf_ssl_handshake_server_version,
+ { "Version", "ssl.handshake.version",
+ FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
+ "Version selected by server", HFILL }
+ },
+ { &hf_ssl_handshake_random_time,
+ { "Random.gmt_unix_time", "ssl.handshake.random_time",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Unix time field of random structure", HFILL }
+ },
+ { &hf_ssl_handshake_random_bytes,
+ { "Random.bytes", "ssl.handshake.random",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Random challenge used to authenticate server", HFILL }
+ },
+ { &hf_ssl_handshake_cipher_suites_len,
+ { "Cipher Suites Length", "ssl.handshake.cipher_suites_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of cipher suites field", HFILL }
+ },
+ { &hf_ssl_handshake_cipher_suites,
+ { "Cipher Suites", "ssl.handshake.ciphersuites",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of cipher suites supported by client", HFILL }
+ },
+ { &hf_ssl_handshake_cipher_suite,
+ { "Cipher Suite", "ssl.handshake.ciphersuite",
+ FT_UINT16, BASE_HEX, VALS(ssl_31_ciphersuite), 0x0,
+ "Cipher suite", HFILL }
+ },
+ { &hf_ssl2_handshake_cipher_spec,
+ { "Cipher Spec", "ssl.handshake.cipherspec",
+ FT_UINT24, BASE_HEX, VALS(ssl_20_cipher_suites), 0x0,
+ "Cipher specification", HFILL }
+ },
+ { &hf_ssl_handshake_session_id,
+ { "Session ID", "ssl.handshake.session_id",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Identifies the SSL session, allowing later resumption", HFILL }
+ },
+ { &hf_ssl_handshake_comp_methods_len,
+ { "Compression Methods Length", "ssl.handshake.comp_methods_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of compression methods field", HFILL }
+ },
+ { &hf_ssl_handshake_comp_methods,
+ { "Compression Methods", "ssl.handshake.comp_methods",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of compression methods supported by client", HFILL }
+ },
+ { &hf_ssl_handshake_comp_method,
+ { "Compression Method", "ssl.handshake.comp_method",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_compression_method), 0x0,
+ "Compression Method", HFILL }
+ },
+ { &hf_ssl_handshake_certificates_len,
+ { "Certificates Length", "ssl.handshake.certificates_length",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Length of certificates field", HFILL }
+ },
+ { &hf_ssl_handshake_certificates,
+ { "Certificates", "ssl.handshake.certificates",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of certificates", HFILL }
+ },
+ { &hf_ssl_handshake_certificate,
+ { "Certificate", "ssl.handshake.certificate",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Certificate", HFILL }
+ },
+ { &hf_ssl_handshake_certificate_len,
+ { "Certificate Length", "ssl.handshake.certificate_length",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Length of certificate", HFILL }
+ },
+ { &hf_ssl_handshake_cert_types_count,
+ { "Certificate types count", "ssl.handshake.cert_types_count",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Count of certificate types", HFILL }
+ },
+ { &hf_ssl_handshake_cert_types,
+ { "Certificate types", "ssl.handshake.cert_types",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of certificate types", HFILL }
+ },
+ { &hf_ssl_handshake_cert_type,
+ { "Certificate type", "ssl.handshake.cert_type",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_client_certificate_type), 0x0,
+ "Certificate type", HFILL }
+ },
+ { &hf_ssl_handshake_finished,
+ { "Verify Data", "ssl.handshake.verify_data",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Opaque verification data", HFILL }
+ },
+ { &hf_ssl_handshake_md5_hash,
+ { "MD5 Hash", "ssl.handshake.md5_hash",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Hash of messages, master_secret, etc.", HFILL }
+ },
+ { &hf_ssl_handshake_sha_hash,
+ { "SHA-1 Hash", "ssl.handshake.sha_hash",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Hash of messages, master_secret, etc.", HFILL }
+ },
+ { &hf_ssl_handshake_session_id_len,
+ { "Session ID Length", "ssl.handshake.session_id_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of session ID field", HFILL }
+ },
+ { &hf_ssl_handshake_dnames_len,
+ { "Distinguished Names Length", "ssl.handshake.dnames_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of list of CAs that server trusts", HFILL }
+ },
+ { &hf_ssl_handshake_dnames,
+ { "Distinguished Names", "ssl.handshake.dnames",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of CAs that server trusts", HFILL }
+ },
+ { &hf_ssl_handshake_dname_len,
+ { "Distinguished Name Length", "ssl.handshake.dname_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of distinguished name", HFILL }
+ },
+ { &hf_ssl_handshake_dname,
+ { "Distinguished Name", "ssl.handshake.dname",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Distinguished name of a CA that server trusts", HFILL }
+ },
+ { &hf_ssl2_handshake_challenge,
+ { "Challenge", "ssl.handshake.challenge",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Challenge data used to authenticate server", HFILL }
+ },
+ { &hf_ssl2_handshake_cipher_spec_len,
+ { "Cipher Spec Length", "ssl.handshake.cipher_spec_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of cipher specs field", HFILL }
+ },
+ { &hf_ssl2_handshake_session_id_len,
+ { "Session ID Length", "ssl.handshake.session_id_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of session ID field", HFILL }
+ },
+ { &hf_ssl2_handshake_challenge_len,
+ { "Challenge Length", "ssl.handshake.challenge_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of challenge field", HFILL }
+ },
+ { &hf_ssl2_handshake_clear_key_len,
+ { "Clear Key Data Length", "ssl.handshake.clear_key_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of clear key data", HFILL }
+ },
+ { &hf_ssl2_handshake_enc_key_len,
+ { "Encrypted Key Data Length", "ssl.handshake.encrypted_key_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of encrypted key data", HFILL }
+ },
+ { &hf_ssl2_handshake_key_arg_len,
+ { "Key Argument Length", "ssl.handshake.key_arg_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of key argument", HFILL }
+ },
+ { &hf_ssl2_handshake_clear_key,
+ { "Clear Key Data", "ssl.handshake.clear_key_data",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Clear portion of MASTER-KEY", HFILL }
+ },
+ { &hf_ssl2_handshake_enc_key,
+ { "Encrypted Key", "ssl.handshake.encrypted_key",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Secret portion of MASTER-KEY encrypted to server", HFILL }
+ },
+ { &hf_ssl2_handshake_key_arg,
+ { "Key Argument", "ssl.handshake.key_arg",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Key Argument (e.g., Initialization Vector)", HFILL }
+ },
+ { &hf_ssl2_handshake_session_id_hit,
+ { "Session ID Hit", "ssl.handshake.session_id_hit",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Did the server find the client's Session ID?", HFILL }
+ },
+ { &hf_ssl2_handshake_cert_type,
+ { "Certificate Type", "ssl.handshake.cert_type",
+ FT_UINT8, BASE_DEC, VALS(ssl_20_certificate_type), 0x0,
+ "Certificate Type", HFILL }
+ },
+ { &hf_ssl2_handshake_connection_id_len,
+ { "Connection ID Length", "ssl.handshake.connection_id_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of connection ID", HFILL }
+ },
+ { &hf_ssl2_handshake_connection_id,
+ { "Connection ID", "ssl.handshake.connection_id",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Server's challenge to client", HFILL }
+ },
+ { &hf_pct_handshake_cipher_spec,
+ { "Cipher Spec", "pct.handshake.cipherspec",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "PCT Cipher specification", HFILL }
+ },
+ { &hf_pct_handshake_cipher,
+ { "Cipher", "pct.handshake.cipher",
+ FT_UINT16, BASE_HEX, VALS(pct_cipher_type), 0x0,
+ "PCT Ciper", HFILL }
+ },
+ { &hf_pct_handshake_hash_spec,
+ { "Hash Spec", "pct.handshake.hashspec",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "PCT Hash specification", HFILL }
+ },
+ { &hf_pct_handshake_hash,
+ { "Hash", "pct.handshake.hash",
+ FT_UINT16, BASE_HEX, VALS(pct_hash_type), 0x0,
+ "PCT Hash", HFILL }
+ },
+ { &hf_pct_handshake_cert_spec,
+ { "Cert Spec", "pct.handshake.certspec",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "PCT Certificate specification", HFILL }
+ },
+ { &hf_pct_handshake_cert,
+ { "Cert Spec", "pct.handshake.cert",
+ FT_UINT16, BASE_HEX, VALS(pct_cert_type), 0x0,
+ "PCT Certificate", HFILL }
+ },
+ { &hf_pct_handshake_exch_spec,
+ { "Exchange Spec", "pct.handshake.exchspec",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "PCT Exchange specification", HFILL }
+ },
+ { &hf_pct_handshake_exch,
+ { "Exchange", "pct.handshake.exch",
+ FT_UINT16, BASE_HEX, VALS(pct_exch_type), 0x0,
+ "PCT Exchange", HFILL }
+ },
+ { &hf_pct_handshake_sig,
+ { "Sig Spec", "pct.handshake.sig",
+ FT_UINT16, BASE_HEX, VALS(pct_sig_type), 0x0,
+ "PCT Signature", HFILL }
+ },
+ { &hf_pct_msg_error_type,
+ { "PCT Error Code", "pct.msg_error_code",
+ FT_UINT16, BASE_HEX, VALS(pct_error_code), 0x0,
+ "PCT Error Code", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_ssl,
+ &ett_ssl_record,
+ &ett_ssl_alert,
+ &ett_ssl_handshake,
+ &ett_ssl_cipher_suites,
+ &ett_ssl_comp_methods,
+ &ett_ssl_certs,
+ &ett_ssl_cert_types,
+ &ett_ssl_dnames,
+ &ett_pct_cipher_suites,
+ &ett_pct_hash_suites,
+ &ett_pct_cert_suites,
+ &ett_pct_exch_suites,
+ };
+
+ /* Register the protocol name and description */
+ proto_ssl = proto_register_protocol("Secure Socket Layer",
+ "SSL", "ssl");
+
+ /* Required function calls to register the header fields and
+ * subtrees used */
+ proto_register_field_array(proto_ssl, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ {
+ module_t *ssl_module = prefs_register_protocol(proto_ssl, NULL);
+ prefs_register_bool_preference(ssl_module,
+ "desegment_ssl_records",
+ "Desegment SSL records",
+ "When enabled, SSL records that span multiple TCP segments are desegmented",
+ &ssl_desegment);
+ }
+
+ register_dissector("ssl", dissect_ssl, proto_ssl);
+
+}
+
+/* If this dissector uses sub-dissector registration add a registration
+ * routine. This format is required because a script is used to find
+ * these routines and create the code that calls these routines.
+ */
+void
+proto_reg_handoff_ssl(void)
+{
+ dissector_handle_t ssl_handle;
+
+ ssl_handle = find_dissector("ssl");
+ dissector_add("tcp.port", TCP_PORT_SSL, ssl_handle);
+ dissector_add("tcp.port", TCP_PORT_SSL_LDAP, ssl_handle);
+ dissector_add("tcp.port", TCP_PORT_SSL_IMAP, ssl_handle);
+ dissector_add("tcp.port", TCP_PORT_SSL_POP, ssl_handle);
+}
diff --git a/epan/dissectors/packet-stat-notify.c b/epan/dissectors/packet-stat-notify.c
new file mode 100644
index 0000000000..ad5ff36189
--- /dev/null
+++ b/epan/dissectors/packet-stat-notify.c
@@ -0,0 +1,108 @@
+/* packet-stat.c
+ * Routines for async NSM stat callback dissection
+ * 2001 Ronnie Sahlberg <See AUTHORS for email>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "packet-rpc.h"
+#include "packet-stat-notify.h"
+
+static int proto_statnotify = -1;
+static int hf_statnotify_procedure_v1 = -1;
+static int hf_statnotify_name = -1;
+static int hf_statnotify_state = -1;
+static int hf_statnotify_priv = -1;
+
+static gint ett_statnotify = -1;
+
+
+static int
+dissect_statnotify_mon(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+
+ offset = dissect_rpc_string(tvb,tree,hf_statnotify_name,offset,NULL);
+
+ offset = dissect_rpc_uint32(tvb,tree,hf_statnotify_state,offset);
+
+ proto_tree_add_item(tree,hf_statnotify_priv,tvb,offset,16,FALSE);
+ offset += 16;
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+
+static const vsff statnotify1_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { STATNOTIFYPROC_MON, "MON-CALLBACK",
+ dissect_statnotify_mon, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string statnotify1_proc_vals[] = {
+ { 0, "NULL" },
+ { STATNOTIFYPROC_MON, "MON-CALLBACK" },
+ { 0, NULL }
+};
+/* end of stat-notify version 1 */
+
+
+void
+proto_register_statnotify(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_statnotify_procedure_v1, {
+ "V1 Procedure", "statnotify.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(statnotify1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_statnotify_name, {
+ "Name", "statnotify.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name of client that changed", HFILL }},
+ { &hf_statnotify_state, {
+ "State", "statnotify.state", FT_UINT32, BASE_DEC,
+ NULL, 0, "New state of client that changed", HFILL }},
+ { &hf_statnotify_priv, {
+ "Priv", "statnotify.priv", FT_BYTES, BASE_HEX,
+ NULL, 0, "Client supplied opaque data", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_statnotify,
+ };
+
+ proto_statnotify = proto_register_protocol("Network Status Monitor CallBack Protocol", "STAT-CB", "statnotify");
+ proto_register_field_array(proto_statnotify, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_statnotify(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_statnotify, STATNOTIFY_PROGRAM, ett_statnotify);
+ /* Register the procedure tables */
+ rpc_init_proc_table(STATNOTIFY_PROGRAM, 1, statnotify1_proc, hf_statnotify_procedure_v1);
+}
diff --git a/epan/dissectors/packet-stat-notify.h b/epan/dissectors/packet-stat-notify.h
new file mode 100644
index 0000000000..f0f5e791ca
--- /dev/null
+++ b/epan/dissectors/packet-stat-notify.h
@@ -0,0 +1,34 @@
+/* packet-stat-notify.h
+ * Async callback to notify NSM servers of changes in client status
+ * 2001 Ronnie Sahlberg <See AUTHORS for email>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_STAT_NOTIFY_H
+#define PACKET_STAT_NOTIFY_H
+
+#define STATNOTIFY_PROGRAM 200048
+
+#define STATNOTIFYPROC_NULL 0
+#define STATNOTIFYPROC_MON 1
+
+#endif
diff --git a/epan/dissectors/packet-stat.c b/epan/dissectors/packet-stat.c
new file mode 100644
index 0000000000..a631ef4519
--- /dev/null
+++ b/epan/dissectors/packet-stat.c
@@ -0,0 +1,351 @@
+/* packet-stat.c
+ * Routines for stat dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-smb.c
+ *
+ * 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Added the dissectors for STAT protocol
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "packet-rpc.h"
+#include "packet-stat.h"
+
+static int proto_stat = -1;
+static int hf_stat_procedure_v1 = -1;
+static int hf_stat_mon_name = -1;
+static int hf_stat_stat_res = -1;
+static int hf_stat_stat_res_res = -1;
+static int hf_stat_stat_res_state = -1;
+static int hf_stat_state = -1;
+static int hf_stat_mon = -1;
+static int hf_stat_mon_id_name = -1;
+static int hf_stat_my_id = -1;
+static int hf_stat_my_id_hostname = -1;
+static int hf_stat_my_id_prog = -1;
+static int hf_stat_my_id_vers = -1;
+static int hf_stat_my_id_proc = -1;
+static int hf_stat_priv = -1;
+static int hf_stat_stat_chge = -1;
+
+static gint ett_stat = -1;
+static gint ett_stat_stat_res = -1;
+static gint ett_stat_mon = -1;
+static gint ett_stat_my_id = -1;
+static gint ett_stat_stat_chge = -1;
+
+#define STAT_SUCC 0
+#define STAT_FAIL 1
+
+static const value_string stat_res[] =
+{
+ { 0, "STAT_SUCC" },
+ { 1, "STAT_FAIL" },
+ { 0, NULL }
+};
+
+/* Calculate length (including padding) of my_id structure.
+ * First read the length of the string and round it upwards to nearest
+ * multiple of 4, then add 16 (4*uint32)
+ */
+static int
+my_id_len(tvbuff_t *tvb, int offset)
+{
+ int len;
+
+ len = tvb_get_ntohl(tvb, offset);
+ if(len&0x03)
+ len = (len&0xfc)+4;
+
+ len += 16;
+
+ return len;
+}
+
+/* Calculate length (including padding) of my_id structure.
+ * First read the length of the string and round it upwards to nearest
+ * multiple of 4, then add 4 (string len) and size of my_id struct.
+ */
+static int
+mon_id_len(tvbuff_t *tvb, int offset)
+{
+ int len;
+
+ len = tvb_get_ntohl(tvb, offset);
+ if(len&0x03){
+ len = (len&0xfc)+4;
+ }
+
+ len += 4;
+
+ return len+my_id_len(tvb,offset+len);
+}
+
+static int
+dissect_stat_stat(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if (tree)
+ {
+ offset = dissect_rpc_string(tvb,tree,hf_stat_mon_name,offset,NULL);
+ }
+
+ return offset;
+}
+
+static int
+dissect_stat_stat_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* sub_item = NULL;
+ proto_tree* sub_tree = NULL;
+ gint32 res;
+ gint32 state;
+
+ if (tree) {
+ sub_item = proto_tree_add_item(tree, hf_stat_stat_res, tvb,
+ offset, -1, FALSE);
+ if (sub_item)
+ sub_tree = proto_item_add_subtree(sub_item, ett_stat_stat_res);
+ }
+
+ res = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_stat_res_res,offset);
+
+ if (res==STAT_SUCC) {
+ state = tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_stat_res_state,offset);
+ } else {
+ offset += 4;
+ }
+
+ return offset;
+}
+
+static int
+dissect_stat_my_id(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item* sub_item = NULL;
+ proto_tree* sub_tree = NULL;
+
+ if (tree) {
+ sub_item = proto_tree_add_item(tree, hf_stat_my_id, tvb,
+ offset, my_id_len(tvb,offset), FALSE);
+ if (sub_item)
+ sub_tree = proto_item_add_subtree(sub_item, ett_stat_my_id);
+ }
+
+ offset = dissect_rpc_string(tvb,sub_tree,hf_stat_my_id_hostname,offset,NULL);
+ offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_my_id_prog,offset);
+ offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_my_id_vers,offset);
+ offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_my_id_proc,offset);
+
+ return offset;
+}
+
+static int
+dissect_stat_mon_id(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* sub_item = NULL;
+ proto_tree* sub_tree = NULL;
+
+ if (tree) {
+ sub_item = proto_tree_add_item(tree, hf_stat_mon, tvb,
+ offset, mon_id_len(tvb,offset), FALSE);
+ if (sub_item)
+ sub_tree = proto_item_add_subtree(sub_item, ett_stat_mon);
+ }
+
+
+ offset = dissect_rpc_string(tvb,sub_tree,hf_stat_mon_id_name,offset,NULL);
+
+ offset = dissect_stat_my_id(tvb,offset,sub_tree);
+
+ return offset;
+}
+
+static int
+dissect_stat_priv(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree_add_item(tree, hf_stat_priv, tvb, offset, 16, FALSE);
+ offset += 16;
+
+ return offset;
+}
+
+static int
+dissect_stat_mon(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+
+ offset = dissect_stat_mon_id(tvb,offset,pinfo,tree);
+
+ offset = dissect_stat_priv(tvb,offset,tree);
+ return offset;
+}
+
+static int
+dissect_stat_state(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb,tree,hf_stat_state,offset);
+
+ return offset;
+}
+
+static int
+dissect_stat_notify(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item* sub_item = NULL;
+ proto_tree* sub_tree = NULL;
+ int start_offset = offset;
+
+ if (tree) {
+ sub_item = proto_tree_add_item(tree, hf_stat_stat_chge, tvb,
+ offset, -1, FALSE);
+ if (sub_item)
+ sub_tree = proto_item_add_subtree(sub_item, ett_stat_stat_chge);
+ }
+
+ offset = dissect_rpc_string(tvb,sub_tree,hf_stat_mon_id_name,offset,NULL);
+
+ offset = dissect_rpc_uint32(tvb,tree,hf_stat_state,offset);
+
+ if(sub_item)
+ proto_item_set_len(sub_item, offset - start_offset);
+
+ return offset;
+}
+
+static int
+dissect_stat_umon_all(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_stat_my_id(tvb,offset,tree);
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+
+static const vsff stat1_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { STATPROC_STAT, "STAT",
+ dissect_stat_stat, dissect_stat_stat_res },
+ { STATPROC_MON, "MON",
+ dissect_stat_mon, dissect_stat_stat_res },
+ { STATPROC_UNMON, "UNMON",
+ dissect_stat_mon_id, dissect_stat_state },
+ { STATPROC_UNMON_ALL, "UNMON_ALL",
+ dissect_stat_umon_all, dissect_stat_state },
+ { STATPROC_SIMU_CRASH, "SIMU_CRASH",
+ NULL, NULL },
+ { STATPROC_NOTIFY, "NOTIFY",
+ dissect_stat_notify, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string stat1_proc_vals[] = {
+ { 0, "NULL" },
+ { STATPROC_STAT, "STAT" },
+ { STATPROC_MON, "MON" },
+ { STATPROC_UNMON, "UNMON" },
+ { STATPROC_UNMON_ALL, "UNMON_ALL" },
+ { STATPROC_SIMU_CRASH, "SIMU_CRASH" },
+ { STATPROC_NOTIFY, "NOTIFY" },
+ { 0, NULL }
+};
+/* end of stat version 1 */
+
+
+void
+proto_register_stat(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_stat_procedure_v1, {
+ "V1 Procedure", "stat.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(stat1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_stat_mon_name, {
+ "Name", "stat.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Name", HFILL }},
+ { &hf_stat_stat_res, {
+ "Status Result", "stat.stat_res", FT_NONE,0,
+ NULL, 0, "Status Result", HFILL }},
+ { &hf_stat_stat_res_res, {
+ "Result", "stat.stat_res.res", FT_UINT32, BASE_DEC,
+ VALS(stat_res), 0, "Result", HFILL }},
+ { &hf_stat_stat_res_state, {
+ "State", "stat.stat_res.state", FT_UINT32, BASE_DEC,
+ NULL, 0, "State", HFILL }},
+ { &hf_stat_mon, {
+ "Monitor", "stat.mon", FT_NONE, 0,
+ NULL, 0, "Monitor Host", HFILL }},
+ { &hf_stat_mon_id_name, {
+ "Monitor ID Name", "stat.mon_id.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Monitor ID Name", HFILL }},
+ { &hf_stat_my_id, {
+ "My ID", "stat.my_id", FT_NONE,0,
+ NULL, 0, "My_ID structure", HFILL }},
+ { &hf_stat_my_id_hostname, {
+ "Hostname", "stat.my_id.hostname", FT_STRING, BASE_DEC,
+ NULL, 0, "My_ID Host to callback", HFILL }},
+ { &hf_stat_my_id_prog, {
+ "Program", "stat.my_id.prog", FT_UINT32, BASE_DEC,
+ NULL, 0, "My_ID Program to callback", HFILL }},
+ { &hf_stat_my_id_vers, {
+ "Version", "stat.my_id.vers", FT_UINT32, BASE_DEC,
+ NULL, 0, "My_ID Version of callback", HFILL }},
+ { &hf_stat_my_id_proc, {
+ "Procedure", "stat.my_id.proc", FT_UINT32, BASE_DEC,
+ NULL, 0, "My_ID Procedure to callback", HFILL }},
+ { &hf_stat_priv, {
+ "Priv", "stat.priv", FT_BYTES, BASE_HEX,
+ NULL, 0, "Private client supplied opaque data", HFILL }},
+ { &hf_stat_state, {
+ "State", "stat.state", FT_UINT32, BASE_DEC,
+ NULL, 0, "State of local NSM", HFILL }},
+ { &hf_stat_stat_chge, {
+ "Status Change", "stat.stat_chge", FT_NONE, 0,
+ NULL, 0, "Status Change structure", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_stat,
+ &ett_stat_stat_res,
+ &ett_stat_mon,
+ &ett_stat_my_id,
+ &ett_stat_stat_chge,
+ };
+
+ proto_stat = proto_register_protocol("Network Status Monitor Protocol", "STAT", "stat");
+ proto_register_field_array(proto_stat, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_stat(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_stat, STAT_PROGRAM, ett_stat);
+ /* Register the procedure tables */
+ rpc_init_proc_table(STAT_PROGRAM, 1, stat1_proc, hf_stat_procedure_v1);
+}
diff --git a/epan/dissectors/packet-stat.h b/epan/dissectors/packet-stat.h
new file mode 100644
index 0000000000..8ad388feaa
--- /dev/null
+++ b/epan/dissectors/packet-stat.h
@@ -0,0 +1,38 @@
+/* packet-stat.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_STAT_H
+#define PACKET_STAT_H
+
+#define STAT_PROGRAM 100024
+
+#define STATPROC_NULL 0
+#define STATPROC_STAT 1
+#define STATPROC_MON 2
+#define STATPROC_UNMON 3
+#define STATPROC_UNMON_ALL 4
+#define STATPROC_SIMU_CRASH 5
+#define STATPROC_NOTIFY 6
+
+#endif
diff --git a/epan/dissectors/packet-stun.c b/epan/dissectors/packet-stun.c
new file mode 100644
index 0000000000..45249e1646
--- /dev/null
+++ b/epan/dissectors/packet-stun.c
@@ -0,0 +1,410 @@
+/* packet-stun.c
+ * Routines for Simple Traversal of UDP Through NAT dissection
+ * Copyright 2003, Shiang-Ming Huang <smhuang@pcs.csie.nctu.edu.tw>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Please refer to RFC 3489 for protocol detail.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+
+/* Initialize the protocol and registered fields */
+static int proto_stun = -1;
+
+static int hf_stun_type = -1; /* STUN message header */
+static int hf_stun_length = -1;
+static int hf_stun_id = -1;
+static int hf_stun_att = -1;
+
+static int stun_att_type = -1; /* STUN attribute fields */
+static int stun_att_length = -1;
+static int stun_att_value = -1;
+static int stun_att_family = -1;
+static int stun_att_ip = -1;
+static int stun_att_port = -1;
+static int stun_att_change_ip = -1;
+static int stun_att_change_port = -1;
+static int stun_att_unknown = -1;
+static int stun_att_error_class = -1;
+static int stun_att_error_number = -1;
+static int stun_att_error_reason = -1;
+
+
+
+/* Message Types */
+#define BINDING_REQUEST 0x0001
+#define BINDING_RESPONSE 0x0101
+#define BINDING_ERROR_RESPONSE 0x0111
+#define SHARED_SECRET_REQUEST 0x0002
+#define SHARED_SECRET_RESPONSE 0x0102
+#define SHARED_SECRET_ERROR_RESPONSE 0x1112
+
+/* Attribute Types */
+#define MAPPED_ADDRESS 0x0001
+#define RESPONSE_ADDRESS 0x0002
+#define CHANGE_REQUEST 0x0003
+#define SOURCE_ADDRESS 0x0004
+#define CHANGED_ADDRESS 0x0005
+#define USERNAME 0x0006
+#define PASSWORD 0x0007
+#define MESSAGE_INTEGRITY 0x0008
+#define ERROR_CODE 0x0009
+#define UNKNOWN_ATTRIBUTES 0x000a
+#define REFLECTED_FROM 0x000b
+
+
+
+/* Initialize the subtree pointers */
+static gint ett_stun = -1;
+static gint ett_stun_att = -1;
+
+
+#define UDP_PORT_STUN 3478
+#define TCP_PORT_STUN 3478
+
+
+#define STUN_HDR_LEN 20 /* STUN message header length */
+#define ATTR_HDR_LEN 4 /* STUN attribute header length */
+
+
+static const true_false_string set_flag = {
+ "SET",
+ "NOT SET"
+};
+
+static const value_string messages[] = {
+ {BINDING_REQUEST, "Binding Request"},
+ {BINDING_RESPONSE, "Binding Response"},
+ {BINDING_ERROR_RESPONSE, "Binding Error Response"},
+ {SHARED_SECRET_REQUEST, "Shared Secret Request"},
+ {SHARED_SECRET_RESPONSE, "Shared Secret Response"},
+ {SHARED_SECRET_ERROR_RESPONSE, "Shared Secret Error Response"},
+ {0x00, NULL}
+};
+
+static const value_string attributes[] = {
+ {MAPPED_ADDRESS, "MAPPED-ADDRESS"},
+ {RESPONSE_ADDRESS, "RESPONSE-ADDRESS"},
+ {CHANGE_REQUEST, "CHANGE-REQUEST"},
+ {SOURCE_ADDRESS, "SOURCE-ADDRESS"},
+ {CHANGED_ADDRESS, "CHANGED-ADDRESS"},
+ {USERNAME, "USERNAME"},
+ {PASSWORD, "PASSWORD"},
+ {MESSAGE_INTEGRITY, "MESSAGE-INTEGRITY"},
+ {ERROR_CODE, "ERROR-CODE"},
+ {REFLECTED_FROM, "REFLECTED-FROM"},
+ {0x00, NULL}
+};
+
+static const value_string attributes_family[] = {
+ {0x0001, "IPv4"},
+ {0x00, NULL}
+};
+
+static int
+dissect_stun(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ proto_item *ti;
+ proto_item *ta;
+ proto_tree *stun_tree;
+ proto_tree *att_tree;
+ guint16 att_type;
+ guint16 att_length;
+ guint16 offset;
+
+ /*
+ * First check if the frame is really meant for us.
+ */
+
+ /* First, make sure we have enough data to do the check. */
+ if (!tvb_bytes_exist(tvb, 0, STUN_HDR_LEN))
+ return 0;
+
+ att_type = tvb_get_ntohs(tvb, 0);
+
+ /* check if message type is correct */
+ if( (att_type != BINDING_REQUEST) &&
+ (att_type != BINDING_RESPONSE) &&
+ (att_type != BINDING_ERROR_RESPONSE) &&
+ (att_type != SHARED_SECRET_REQUEST) &&
+ (att_type != SHARED_SECRET_RESPONSE) &&
+ (att_type != SHARED_SECRET_ERROR_RESPONSE)
+ )
+ return 0;
+
+
+ att_length = tvb_get_ntohs(tvb, 2);
+
+ /* check if payload enough */
+ if (!tvb_bytes_exist(tvb, 0, STUN_HDR_LEN+att_length))
+ return 0;
+
+ if(tvb_bytes_exist(tvb, 0, STUN_HDR_LEN+att_length+1))
+ return 0;
+
+ /* The message seems to be a valid STUN message! */
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "STUN");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Message : %s",
+ (att_type==BINDING_REQUEST)?"Binding Request":
+ (att_type==BINDING_RESPONSE)?"Binding Response":
+ (att_type==BINDING_ERROR_RESPONSE)?"Binding Error Response":
+ (att_type==SHARED_SECRET_REQUEST)?"Shared Secret Request":
+ (att_type==SHARED_SECRET_RESPONSE)?"Shared Secret Response":
+ (att_type==SHARED_SECRET_ERROR_RESPONSE)?"Shared Secret Error Response":"UNKNOWN"
+ );
+
+ }
+
+
+ if (tree) {
+
+
+ ti = proto_tree_add_item(tree, proto_stun, tvb, 0, -1, FALSE);
+
+ stun_tree = proto_item_add_subtree(ti, ett_stun);
+
+
+
+
+ proto_tree_add_item(stun_tree, hf_stun_type, tvb, 0, 2, FALSE);
+ proto_tree_add_item(stun_tree, hf_stun_length, tvb, 2, 2, FALSE);
+ proto_tree_add_item(stun_tree, hf_stun_id, tvb, 4, 16, FALSE);
+
+ ta = proto_tree_add_item(stun_tree, hf_stun_att, tvb, STUN_HDR_LEN, -1, FALSE);
+ att_tree = proto_item_add_subtree(ta, ett_stun_att);
+
+ offset = STUN_HDR_LEN;
+
+ while(1){
+ if( !tvb_bytes_exist(tvb, offset, ATTR_HDR_LEN) ) /* no data anymore */
+ break;
+
+ att_type = tvb_get_ntohs(tvb, offset); /* Type field in attribute header */
+ att_length = tvb_get_ntohs(tvb, offset+2); /* Length field in attribute header */
+
+
+ switch( att_type ){
+ case MAPPED_ADDRESS:
+ case RESPONSE_ADDRESS:
+ case SOURCE_ADDRESS:
+ case CHANGED_ADDRESS:
+ case REFLECTED_FROM:
+ proto_tree_add_item(att_tree, stun_att_type, tvb, offset, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_length, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_family, tvb, offset+5, 1, FALSE);
+ proto_tree_add_item(att_tree, stun_att_port, tvb, offset+6, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_ip, tvb, offset+8, 4, FALSE);
+
+ offset = offset+(ATTR_HDR_LEN+att_length);
+
+ break;
+
+ case CHANGE_REQUEST:
+ proto_tree_add_item(att_tree, stun_att_type, tvb, offset, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_length, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_change_ip, tvb, offset+4, 4, FALSE);
+ proto_tree_add_item(att_tree, stun_att_change_port, tvb, offset+4, 4, FALSE);
+
+ offset = offset+(ATTR_HDR_LEN+att_length);
+
+ break;
+
+ case USERNAME:
+ case PASSWORD:
+ case MESSAGE_INTEGRITY:
+ proto_tree_add_item(att_tree, stun_att_type, tvb, offset, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_length, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_value, tvb, offset+4, att_length, FALSE);
+
+ offset = offset+(ATTR_HDR_LEN+att_length);
+
+ break;
+
+ case ERROR_CODE:
+ proto_tree_add_item(att_tree, stun_att_type, tvb, offset, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_length, tvb, offset+2, 2, FALSE);
+
+ proto_tree_add_item(att_tree, stun_att_error_class, tvb, offset+6, 1, FALSE);
+ proto_tree_add_item(att_tree, stun_att_error_number, tvb, offset+7, 1, FALSE);
+ proto_tree_add_item(att_tree, stun_att_error_reason, tvb, offset+8, (att_length-4), FALSE);
+
+ offset = offset+(ATTR_HDR_LEN+att_length);
+
+ break;
+
+
+ case UNKNOWN_ATTRIBUTES:
+ proto_tree_add_item(att_tree, stun_att_type, tvb, offset, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_length, tvb, offset+2, 2, FALSE);
+
+ offset = offset + ATTR_HDR_LEN;
+ while(tvb_bytes_exist(tvb, offset, 4)){ /* UNKNOWN-ATTRIBUTES is 4 bytes aligned */
+ proto_tree_add_item(att_tree, stun_att_unknown, tvb, offset, 2, FALSE);
+ proto_tree_add_item(att_tree, stun_att_unknown, tvb, offset+2, 2, FALSE);
+ offset = offset + 4;
+ }
+
+ break;
+
+ default:
+ return tvb_length(tvb);
+
+ }
+
+ }
+ }
+ return tvb_length(tvb);
+}
+
+
+static gboolean
+dissect_stun_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (dissect_stun(tvb, pinfo, tree) == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
+
+void
+proto_register_stun(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_stun_type,
+ { "Message Type", "stun.type", FT_UINT16,
+ BASE_HEX, VALS(messages), 0x0, "", HFILL }
+ },
+ { &hf_stun_length,
+ { "Message Length", "stun.length", FT_UINT16,
+ BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_stun_id,
+ { "Message Transaction ID", "stun.id", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &hf_stun_att,
+ { "Attributes", "stun.att", FT_NONE,
+ 0, NULL, 0x0, "", HFILL }
+ },
+ /* ////////////////////////////////////// */
+ { &stun_att_type,
+ { "Attribute Type", "stun.att.type", FT_UINT16,
+ BASE_HEX, VALS(attributes), 0x0, "", HFILL }
+ },
+ { &stun_att_length,
+ { "Attribute Length", "stun.att.length", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ { &stun_att_value,
+ { "Value", "stun.att.value", FT_BYTES,
+ BASE_HEX, NULL, 0x0, "", HFILL }
+ },
+ { &stun_att_family,
+ { "Protocol Family", "stun.att.family", FT_UINT16,
+ BASE_HEX, VALS(attributes_family), 0x0, "", HFILL }
+ },
+ { &stun_att_ip,
+ { "IP", "stun.att.ip", FT_IPv4,
+ BASE_NONE, NULL, 0x0, "", HFILL }
+ },
+ { &stun_att_port,
+ { "Port", "stun.att.port", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "", HFILL }
+ },
+ { &stun_att_change_ip,
+ { "Change IP","stun.att.change.ip", FT_BOOLEAN,
+ 16, TFS(&set_flag), 0x0004, "", HFILL}
+ },
+ { &stun_att_change_port,
+ { "Change Port","stun.att.change.port", FT_BOOLEAN,
+ 16, TFS(&set_flag), 0x0002, "", HFILL}
+ },
+ { &stun_att_unknown,
+ { "Unknown Attribute","stun.att.unknown", FT_UINT16,
+ BASE_HEX, NULL, 0x0, "", HFILL}
+ },
+ { &stun_att_error_class,
+ { "Error Class","stun.att.error.class", FT_UINT8,
+ BASE_DEC, NULL, 0x07, "", HFILL}
+ },
+ { &stun_att_error_number,
+ { "Error Code","stun.att.error", FT_UINT8,
+ BASE_DEC, NULL, 0x0, "", HFILL}
+ },
+ { &stun_att_error_reason,
+ { "Error Reason Phase","stun.att.error.reason", FT_STRING,
+ BASE_NONE, NULL, 0x0, "", HFILL}
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_stun,
+ &ett_stun_att,
+ };
+
+/* Register the protocol name and description */
+ proto_stun = proto_register_protocol("Simple Traversal of UDP Through NAT",
+ "STUN", "stun");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_stun, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+
+void
+proto_reg_handoff_stun(void)
+{
+ dissector_handle_t stun_handle;
+
+ stun_handle = new_create_dissector_handle(dissect_stun, proto_stun);
+ dissector_add("tcp.port", TCP_PORT_STUN, stun_handle);
+ dissector_add("udp.port", UDP_PORT_STUN, stun_handle);
+
+ heur_dissector_add("udp", dissect_stun_heur, proto_stun);
+ heur_dissector_add("tcp", dissect_stun_heur, proto_stun);
+}
diff --git a/epan/dissectors/packet-sua.c b/epan/dissectors/packet-sua.c
new file mode 100644
index 0000000000..cd90c4e390
--- /dev/null
+++ b/epan/dissectors/packet-sua.c
@@ -0,0 +1,1763 @@
+/* packet-sua.c
+ * Routines for SS7 SCCP-User Adaptation Layer (SUA) dissection
+ * It is hopefully (needs testing) compilant to
+ * http://www.ietf.org/internet-drafts/draft-ietf-sigtran-sua-15.txt
+ *
+ * Copyright 2002, 2003 Michael Tuexen <tuexen [AT] fh-muenster.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include "sctpppids.h"
+
+#define NETWORK_BYTE_ORDER FALSE
+#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
+#define SCTP_PORT_SUA 14001
+
+#define RESERVED_1_LENGTH 1
+#define RESERVED_2_LENGTH 2
+#define RESERVED_3_LENGTH 3
+
+#define VERSION_LENGTH 1
+#define RESERVED_LENGTH 1
+#define MESSAGE_CLASS_LENGTH 1
+#define MESSAGE_TYPE_LENGTH 1
+#define MESSAGE_LENGTH_LENGTH 4
+#define COMMON_HEADER_LENGTH (VERSION_LENGTH + RESERVED_LENGTH + MESSAGE_CLASS_LENGTH + \
+ MESSAGE_TYPE_LENGTH + MESSAGE_LENGTH_LENGTH)
+
+#define COMMON_HEADER_OFFSET 0
+#define VERSION_OFFSET COMMON_HEADER_OFFSET
+#define RESERVED_OFFSET (VERSION_OFFSET + VERSION_LENGTH)
+#define MESSAGE_CLASS_OFFSET (RESERVED_OFFSET + RESERVED_LENGTH)
+#define MESSAGE_TYPE_OFFSET (MESSAGE_CLASS_OFFSET + MESSAGE_CLASS_LENGTH)
+#define MESSAGE_LENGTH_OFFSET (MESSAGE_TYPE_OFFSET + MESSAGE_TYPE_LENGTH)
+
+#define PARAMETER_TAG_LENGTH 2
+#define PARAMETER_LENGTH_LENGTH 2
+#define PARAMETER_HEADER_LENGTH (PARAMETER_TAG_LENGTH + PARAMETER_LENGTH_LENGTH)
+
+#define PARAMETER_TAG_OFFSET 0
+#define PARAMETER_LENGTH_OFFSET (PARAMETER_TAG_OFFSET + PARAMETER_TAG_LENGTH)
+#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
+#define PARAMETER_HEADER_OFFSET PARAMETER_TAG_OFFSET
+
+#define INFO_STRING_PARAMETER_TAG 0x0004
+#define ROUTING_CONTEXT_PARAMETER_TAG 0x0006
+#define DIAGNOSTIC_INFO_PARAMETER_TAG 0x0007
+#define HEARTBEAT_DATA_PARAMETER_TAG 0x0009
+#define TRAFFIC_MODE_TYPE_PARAMETER_TAG 0x000b
+#define ERROR_CODE_PARAMETER_TAG 0x000c
+#define STATUS_PARAMETER_TAG 0x000d
+#define ASP_IDENTIFIER_PARAMETER_TAG 0x0011
+#define AFFECTED_POINT_CODE_PARAMETER_TAG 0x0012
+#define CORRELATION_ID_PARAMETER_TAG 0x0013
+#define REGISTRATION_RESULT_PARAMETER_TAG 0x0014
+#define DEREGISTRATION_RESULT_PARAMETER_TAG 0x0015
+#define REGISTRATION_STATUS_PARAMETER_TAG 0x0016
+#define DEREGISTRATION_STATUS_PARAMETER_TAG 0x0017
+#define LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG 0x0018
+
+#define SS7_HOP_COUNTER_PARAMETER_TAG 0x0101
+#define SOURCE_ADDRESS_PARAMETER_TAG 0x0102
+#define DESTINATION_ADDRESS_PARAMETER_TAG 0x0103
+#define SOURCE_REFERENCE_NUMBER_PARAMETER_TAG 0x0104
+#define DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG 0x0105
+#define SCCP_CAUSE_PARAMETER_TAG 0x0106
+#define SEQUENCE_NUMBER_PARAMETER_TAG 0x0107
+#define RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG 0x0108
+#define ASP_CAPABILITIES_PARAMETER_TAG 0x0109
+#define CREDIT_PARAMETER_TAG 0x010a
+#define DATA_PARAMETER_TAG 0x010b
+#define USER_CAUSE_PARAMETER_TAG 0x010c
+#define NETWORK_APPEARANCE_PARAMETER_TAG 0x010d
+#define ROUTING_KEY_PARAMETER_TAG 0x010e
+#define DRN_LABEL_PARAMETER_TAG 0x010f
+#define TID_LABEL_PARAMETER_TAG 0x0110
+#define ADDRESS_RANGE_PARAMETER_TAG 0x0111
+#define SMI_PARAMETER_TAG 0x0112
+#define IMPORTANCE_PARAMETER_TAG 0x0113
+#define MESSAGE_PRIORITY_PARAMETER_TAG 0x0114
+#define PROTOCOL_CLASS_PARAMETER_TAG 0x0115
+#define SEQUENCE_CONTROL_PARAMETER_TAG 0x0116
+#define SEGMENTATION_PARAMETER_TAG 0x0117
+#define CONGESTION_LEVEL_PARAMETER_TAG 0x0118
+
+#define GLOBAL_TITLE_PARAMETER_TAG 0x8001
+#define POINT_CODE_PARAMETER_TAG 0x8002
+#define SUBSYSTEM_NUMBER_PARAMETER_TAG 0x8003
+#define IPV4_ADDRESS_PARAMETER_TAG 0x8004
+#define HOSTNAME_PARAMETER_TAG 0x8005
+#define IPV6_ADDRESS_PARAMETER_TAG 0x8006
+
+static const value_string parameter_tag_values[] = {
+ { INFO_STRING_PARAMETER_TAG, "Info String" },
+ { ROUTING_CONTEXT_PARAMETER_TAG, "Routing context" },
+ { DIAGNOSTIC_INFO_PARAMETER_TAG, "Diagnostic info" },
+ { HEARTBEAT_DATA_PARAMETER_TAG, "Heartbeat data" },
+ { TRAFFIC_MODE_TYPE_PARAMETER_TAG, "Traffic mode type" },
+ { ERROR_CODE_PARAMETER_TAG, "Error code" },
+ { STATUS_PARAMETER_TAG, "Status" },
+ { ASP_IDENTIFIER_PARAMETER_TAG, "ASP identifier" },
+ { AFFECTED_POINT_CODE_PARAMETER_TAG, "Affected point code" },
+ { CORRELATION_ID_PARAMETER_TAG, "Correlation ID" },
+ { REGISTRATION_RESULT_PARAMETER_TAG, "Registration result" },
+ { DEREGISTRATION_RESULT_PARAMETER_TAG, "Deregistration result" },
+ { REGISTRATION_STATUS_PARAMETER_TAG, "Registration status" },
+ { DEREGISTRATION_STATUS_PARAMETER_TAG, "Deregistration status" },
+ { LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG, "Local routing key identifier" },
+ { SS7_HOP_COUNTER_PARAMETER_TAG, "SS7 hop counter" },
+ { SOURCE_ADDRESS_PARAMETER_TAG, "Source address" },
+ { DESTINATION_ADDRESS_PARAMETER_TAG, "Destination address" },
+ { SOURCE_REFERENCE_NUMBER_PARAMETER_TAG, "Source reference number" },
+ { DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG, "Destination reference number" },
+ { SCCP_CAUSE_PARAMETER_TAG, "SCCP cause" },
+ { SEQUENCE_NUMBER_PARAMETER_TAG, "Sequence number" },
+ { RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG, "Receive sequence number" },
+ { ASP_CAPABILITIES_PARAMETER_TAG, "ASP capabilities" },
+ { CREDIT_PARAMETER_TAG, "Credit" },
+ { DATA_PARAMETER_TAG, "Data" },
+ { USER_CAUSE_PARAMETER_TAG, "User/Cause" },
+ { NETWORK_APPEARANCE_PARAMETER_TAG, "Network appearance" },
+ { ROUTING_KEY_PARAMETER_TAG, "Routing key" },
+ { DRN_LABEL_PARAMETER_TAG, "DRN label" },
+ { TID_LABEL_PARAMETER_TAG, "TID label" },
+ { ADDRESS_RANGE_PARAMETER_TAG, "Address range" },
+ { SMI_PARAMETER_TAG, "SMI" },
+ { IMPORTANCE_PARAMETER_TAG, "Importance" },
+ { MESSAGE_PRIORITY_PARAMETER_TAG, "Message priority" },
+ { PROTOCOL_CLASS_PARAMETER_TAG, "Protocol class" },
+ { SEQUENCE_CONTROL_PARAMETER_TAG, "Sequence control" },
+ { SEGMENTATION_PARAMETER_TAG, "Segmentation" },
+ { CONGESTION_LEVEL_PARAMETER_TAG, "Congestion level" },
+ { GLOBAL_TITLE_PARAMETER_TAG, "Global title" },
+ { POINT_CODE_PARAMETER_TAG, "Point code" },
+ { SUBSYSTEM_NUMBER_PARAMETER_TAG, "Subsystem number" },
+ { IPV4_ADDRESS_PARAMETER_TAG, "IPv4 address" },
+ { HOSTNAME_PARAMETER_TAG, "Hostname" },
+ { IPV6_ADDRESS_PARAMETER_TAG, "IPv6 address" },
+ { 0, NULL } };
+
+#define PROTOCOL_VERSION_RELEASE_1 1
+
+static const value_string protocol_version_values[] = {
+ { PROTOCOL_VERSION_RELEASE_1, "Release 1" },
+ { 0, NULL } };
+
+#define MESSAGE_CLASS_MGMT_MESSAGE 0
+#define MESSAGE_CLASS_TFER_MESSAGE 1
+#define MESSAGE_CLASS_SSNM_MESSAGE 2
+#define MESSAGE_CLASS_ASPSM_MESSAGE 3
+#define MESSAGE_CLASS_ASPTM_MESSAGE 4
+#define MESSAGE_CLASS_CL_MESSAGE 7
+#define MESSAGE_CLASS_CO_MESSAGE 8
+#define MESSAGE_CLASS_RKM_MESSAGE 9
+
+static const value_string message_class_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE, "Management messages" },
+ { MESSAGE_CLASS_SSNM_MESSAGE, "SS7 signalling network management messages" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE, "ASP state maintenance messages" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE, "ASP traffic maintenance messages" },
+ { MESSAGE_CLASS_CL_MESSAGE, "Connectionless messages" },
+ { MESSAGE_CLASS_CO_MESSAGE, "Connection-Oriented messages" },
+ { MESSAGE_CLASS_RKM_MESSAGE, "Routing key management Messages" },
+ { 0, NULL } };
+
+#define MESSAGE_TYPE_ERR 0
+#define MESSAGE_TYPE_NTFY 1
+
+#define MESSAGE_TYPE_DUNA 1
+#define MESSAGE_TYPE_DAVA 2
+#define MESSAGE_TYPE_DAUD 3
+#define MESSAGE_TYPE_SCON 4
+#define MESSAGE_TYPE_DUPU 5
+#define MESSAGE_TYPE_DRST 6
+
+#define MESSAGE_TYPE_UP 1
+#define MESSAGE_TYPE_DOWN 2
+#define MESSAGE_TYPE_BEAT 3
+#define MESSAGE_TYPE_UP_ACK 4
+#define MESSAGE_TYPE_DOWN_ACK 5
+#define MESSAGE_TYPE_BEAT_ACK 6
+
+#define MESSAGE_TYPE_ACTIVE 1
+#define MESSAGE_TYPE_INACTIVE 2
+#define MESSAGE_TYPE_ACTIVE_ACK 3
+#define MESSAGE_TYPE_INACTIVE_ACK 4
+
+#define MESSAGE_TYPE_CLDT 1
+#define MESSAGE_TYPE_CLDR 2
+
+#define MESSAGE_TYPE_CORE 1
+#define MESSAGE_TYPE_COAK 2
+#define MESSAGE_TYPE_COREF 3
+#define MESSAGE_TYPE_RELRE 4
+#define MESSAGE_TYPE_RELCO 5
+#define MESSAGE_TYPE_RESCO 6
+#define MESSAGE_TYPE_RESRE 7
+#define MESSAGE_TYPE_CODT 8
+#define MESSAGE_TYPE_CODA 9
+#define MESSAGE_TYPE_COERR 10
+#define MESSAGE_TYPE_COIT 11
+
+#define MESSAGE_TYPE_REG_REQ 1
+#define MESSAGE_TYPE_REG_RSP 2
+#define MESSAGE_TYPE_DEREG_REQ 3
+#define MESSAGE_TYPE_DEREG_RSP 4
+
+
+static const value_string message_class_type_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "Error (ERR)" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "Notify (NTFY)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUNA, "Destination unavailable (DUNA)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAVA, "Destination available (DAVA)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAUD, "Destination state audit (DAUD)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_SCON, "SS7 Network congestion state (SCON)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUPU, "Destination userpart unavailable (DUPU)" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DRST, "Destination Restricted (DRST)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP up (UP)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP down (DOWN)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "Heartbeat (BEAT)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP up ack (UP ACK)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP down ack (DOWN ACK)" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "Heartbeat ack (BEAT ACK)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP active (ACTIVE)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP inactive (INACTIVE)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP active ack (ACTIVE ACK)" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP inactive ack (INACTIVE ACK)" },
+ { MESSAGE_CLASS_CL_MESSAGE * 256 + MESSAGE_TYPE_CLDR , "Connectionless Data Response (CLDR)" },
+ { MESSAGE_CLASS_CL_MESSAGE * 256 + MESSAGE_TYPE_CLDT , "Connectionless Data Transfer (CLDT)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_CORE , "Connection Request (CORE)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_COAK , "Connection Acknowledge (COAK)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_COREF , "Connection Refused (COREF)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_RELRE , "Release Request (RELRE)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_RELCO , "Release Complete (RELCO)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_RESCO , "Reset Confirm (RESCO)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_RESRE , "Reset Request (RESRE)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_CODT , "Connection Oriented Data Transfer (CODT)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_CODA , "Connection Oriented Data Acknowledge (CODA)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_COERR , "Connection Oriented Error (COERR)" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_COIT , "Inactivity Test (COIT)" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_REG_REQ , "Registration Request (REG_REQ)" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_REG_RSP , "Registartion Response (REG_RSP)" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_REQ , "Deregistration Request (DEREG_REQ)" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_RSP , "Deregistartion Response (DEREG_RSP)" },
+ { 0, NULL } };
+
+static const value_string message_class_type_acro_values[] = {
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_ERR, "ERR" },
+ { MESSAGE_CLASS_MGMT_MESSAGE * 256 + MESSAGE_TYPE_NTFY, "NTFY" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUNA, "DUNA" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAVA, "DAVA" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DAUD, "DAUD" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_SCON, "SCON" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DUPU, "DUPU" },
+ { MESSAGE_CLASS_SSNM_MESSAGE * 256 + MESSAGE_TYPE_DRST, "DRST" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP, "ASP_UP" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN, "ASP_DOWN" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT, "BEAT" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_UP_ACK, "ASP_UP_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_DOWN_ACK, "ASP_DOWN_ACK" },
+ { MESSAGE_CLASS_ASPSM_MESSAGE * 256 + MESSAGE_TYPE_BEAT_ACK, "BEAT_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE , "ASP_ACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE , "ASP_INACTIVE" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_ACTIVE_ACK , "ASP_ACTIVE_ACK" },
+ { MESSAGE_CLASS_ASPTM_MESSAGE * 256 + MESSAGE_TYPE_INACTIVE_ACK , "ASP_INACTIVE_ACK" },
+ { MESSAGE_CLASS_CL_MESSAGE * 256 + MESSAGE_TYPE_CLDR , "CLDR" },
+ { MESSAGE_CLASS_CL_MESSAGE * 256 + MESSAGE_TYPE_CLDT , "CLDT" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_CORE , "CORE" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_COAK , "COAK" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_COREF , "COREF" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_RELRE , "RELRE" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_RELCO , "RELCO" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_RESCO , "RESCO" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_RESRE , "RESRE" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_CODT , "CODT" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_CODA , "CODA" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_COERR , "COERR" },
+ { MESSAGE_CLASS_CO_MESSAGE * 256 + MESSAGE_TYPE_COIT , "COIT" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_REG_REQ , "REG_REQ" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_REG_RSP , "REG_RSP" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_REQ , "DEREG_REQ" },
+ { MESSAGE_CLASS_RKM_MESSAGE * 256 + MESSAGE_TYPE_DEREG_RSP , "DEREG_RSP" },
+ { 0, NULL } };
+
+/* Initialize the protocol and registered fields */
+static int proto_sua = -1;
+static int hf_version = -1;
+static int hf_reserved = -1;
+static int hf_message_class = -1;
+static int hf_message_type = -1;
+static int hf_message_length = -1;
+static int hf_parameter_tag = -1;
+static int hf_parameter_length = -1;
+static int hf_parameter_value = -1;
+static int hf_parameter_padding = -1;
+static int hf_info_string = -1;
+static int hf_routing_context = -1;
+static int hf_diagnostic_information_info = -1;
+static int hf_heartbeat_data = -1;
+static int hf_traffic_mode_type = -1;
+static int hf_error_code = -1;
+static int hf_status_type = -1;
+static int hf_status_info = -1;
+static int hf_congestion_level = -1;
+static int hf_asp_identifier = -1;
+static int hf_mask = -1;
+static int hf_dpc = -1;
+static int hf_registration_status = -1;
+static int hf_deregistration_status = -1;
+static int hf_local_routing_key_identifier = -1;
+static int hf_source_address_routing_indicator = -1;
+static int hf_source_address_reserved_bits = -1;
+static int hf_source_address_gt_bit = -1;
+static int hf_source_address_pc_bit = -1;
+static int hf_source_address_ssn_bit = -1;
+static int hf_destination_address_routing_indicator = -1;
+static int hf_destination_address_reserved_bits = -1;
+static int hf_destination_address_gt_bit = -1;
+static int hf_destination_address_pc_bit = -1;
+static int hf_destination_address_ssn_bit = -1;
+static int hf_ss7_hop_counter_counter = -1;
+static int hf_ss7_hop_counter_reserved = -1;
+static int hf_destination_reference_number = -1;
+static int hf_source_reference_number = -1;
+static int hf_cause_reserved = -1;
+static int hf_cause_type = -1;
+static int hf_cause_value = -1;
+static int hf_sequence_number_reserved = -1;
+static int hf_sequence_number_rec_number = -1;
+static int hf_sequence_number_spare_bit = -1;
+static int hf_sequence_number_sent_number = -1;
+static int hf_sequence_number_more_data_bit = -1;
+static int hf_receive_sequence_number_reserved = -1;
+static int hf_receive_sequence_number_number = -1;
+static int hf_receive_sequence_number_spare_bit = -1;
+static int hf_asp_capabilities_reserved = -1;
+static int hf_asp_capabilities_reserved_bits = -1;
+static int hf_asp_capabilities_a_bit =-1;
+static int hf_asp_capabilities_b_bit =-1;
+static int hf_asp_capabilities_c_bit =-1;
+static int hf_asp_capabilities_d_bit =-1;
+static int hf_asp_capabilities_interworking = -1;
+static int hf_credit = -1;
+static int hf_data = -1;
+static int hf_cause = -1;
+static int hf_user = -1;
+static int hf_network_appearance = -1;
+static int hf_routing_key_identifier = -1;
+static int hf_correlation_id = -1;
+static int hf_importance_reserved = -1;
+static int hf_importance = -1;
+static int hf_message_priority_reserved = -1;
+static int hf_message_priority = -1;
+static int hf_protocol_class_reserved = -1;
+static int hf_return_on_error_bit = -1;
+static int hf_protocol_class = -1;
+static int hf_sequence_control = -1;
+static int hf_first_bit = -1;
+static int hf_number_of_remaining_segments = -1;
+static int hf_segmentation_reference = -1;
+static int hf_smi = -1;
+static int hf_smi_reserved = -1;
+static int hf_tid_label_start = -1;
+static int hf_tid_label_end = -1;
+static int hf_tid_label_value = -1;
+static int hf_drn_label_start = -1;
+static int hf_drn_label_end = -1;
+static int hf_drn_label_value = -1;
+static int hf_gt_reserved = -1;
+static int hf_gti = -1;
+static int hf_number_of_digits = -1;
+static int hf_translation_type = -1;
+static int hf_numbering_plan = -1;
+static int hf_nature_of_address = -1;
+static int hf_global_title = -1;
+static int hf_point_code_dpc = -1;
+static int hf_ssn_reserved = -1;
+static int hf_ssn_number = -1;
+static int hf_ipv4 = -1;
+static int hf_hostname = -1;
+static int hf_ipv6 = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_sua = -1;
+static gint ett_sua_parameter = -1;
+static gint ett_sua_source_address_indicator = -1;
+static gint ett_sua_destination_address_indicator = -1;
+static gint ett_sua_affected_destination = -1;
+static gint ett_sua_first_remaining = -1;
+static gint ett_sua_sequence_number_rec_number = -1;
+static gint ett_sua_sequence_number_sent_number = -1;
+static gint ett_sua_receive_sequence_number_number = -1;
+static gint ett_sua_return_on_error_bit_and_protocol_class = -1;
+static gint ett_sua_protcol_classes = -1;
+
+static dissector_handle_t data_handle;
+static dissector_table_t sua_ssn_dissector_table;
+
+static void
+dissect_parameters(tvbuff_t *tlv_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn);
+
+static void
+dissect_common_header(tvbuff_t *common_header_tvb, packet_info *pinfo, proto_tree *sua_tree)
+{
+ guint8 message_class, message_type;
+
+ message_class = tvb_get_guint8(common_header_tvb, MESSAGE_CLASS_OFFSET);
+ message_type = tvb_get_guint8(common_header_tvb, MESSAGE_TYPE_OFFSET);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_class * 256 + message_type, message_class_type_acro_values, "reserved"));
+
+ if (sua_tree) {
+ /* add the components of the common header to the protocol tree */
+ proto_tree_add_item(sua_tree, hf_version, common_header_tvb, VERSION_OFFSET, VERSION_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(sua_tree, hf_reserved, common_header_tvb, RESERVED_OFFSET, RESERVED_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(sua_tree, hf_message_class, common_header_tvb, MESSAGE_CLASS_OFFSET, MESSAGE_CLASS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(sua_tree, hf_message_type, common_header_tvb, MESSAGE_TYPE_OFFSET, MESSAGE_TYPE_LENGTH, message_type, "Message Type: %s (%u)",
+ val_to_str(message_class * 256 + message_type, message_class_type_values, "reserved"), message_type);
+ proto_tree_add_item(sua_tree, hf_message_length, common_header_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ };
+}
+
+#define INFO_STRING_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_info_string_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 info_string_length;
+
+ info_string_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_info_string, parameter_tvb, INFO_STRING_OFFSET, info_string_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%.*s)", info_string_length,
+ (const char *)tvb_get_ptr(parameter_tvb, INFO_STRING_OFFSET, info_string_length));
+}
+
+#define ROUTING_CONTEXT_LENGTH 4
+
+static void
+dissect_routing_context_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 number_of_contexts, context_number;
+ gint context_offset;
+
+ number_of_contexts = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / 4;
+ context_offset = PARAMETER_VALUE_OFFSET;
+ for(context_number=1; context_number <= number_of_contexts; context_number++) {
+ proto_tree_add_item(parameter_tree, hf_routing_context, parameter_tvb, context_offset, ROUTING_CONTEXT_LENGTH, NETWORK_BYTE_ORDER);
+ context_offset += ROUTING_CONTEXT_LENGTH;
+ };
+ proto_item_append_text(parameter_item, " (%u context%s)", number_of_contexts, plurality(number_of_contexts, "", "s"));
+}
+
+#define DIAGNOSTIC_INFO_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_diagnostic_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 diag_info_length;
+
+ diag_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_diagnostic_information_info, parameter_tvb, DIAGNOSTIC_INFO_OFFSET, diag_info_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", diag_info_length, plurality(diag_info_length, "", "s"));
+}
+
+#define HEARTBEAT_DATA_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_heartbeat_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 heartbeat_data_length;
+
+ heartbeat_data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_heartbeat_data, parameter_tvb, HEARTBEAT_DATA_OFFSET, heartbeat_data_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u byte%s)", heartbeat_data_length, plurality(heartbeat_data_length, "", "s"));
+}
+
+#define TRAFFIC_MODE_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+#define TRAFFIC_MODE_TYPE_LENGTH 4
+
+static const value_string traffic_mode_type_values[] = {
+ { 1, "Over-ride" },
+ { 2, "Load-share" },
+ { 3, "Broadcast" },
+ { 0, NULL } };
+
+static void
+dissect_traffic_mode_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_traffic_mode_type, parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET, TRAFFIC_MODE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, TRAFFIC_MODE_TYPE_OFFSET), traffic_mode_type_values, "unknown"));
+}
+
+#define ERROR_CODE_OFFSET PARAMETER_VALUE_OFFSET
+#define ERROR_CODE_LENGTH 4
+
+static const value_string error_code_values[] = {
+ { 0x01, "Invalid version" },
+ { 0x03, "Unsupported message class" },
+ { 0x04, "Unsupported message type" },
+ { 0x05, "Unsupported traffic handling mode" },
+ { 0x06, "Unexpected message" },
+ { 0x07, "Protocol error" },
+ { 0x09, "Invalid stream identifier" },
+ { 0x0d, "Refused - management blocking" },
+ { 0x0e, "ASP identifier required" },
+ { 0x0f, "Invalid ASP identifier" },
+ { 0x11, "Invalid parameter value" },
+ { 0x12, "Parameter field error" },
+ { 0x13, "Unexpected parameter" },
+ { 0x14, "Destination status unknown" },
+ { 0x15, "Invalid network appearance" },
+ { 0x16, "Missing parameter" },
+ { 0x19, "Invalid routing context" },
+ { 0x1a, "No configured AS for ASP" },
+ { 0x1b, "Subsystem status unknown" },
+ { 0, NULL } };
+
+static void
+dissect_error_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_error_code, parameter_tvb, ERROR_CODE_OFFSET, ERROR_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, ERROR_CODE_OFFSET), error_code_values, "unknown"));
+}
+
+#define STATUS_TYPE_LENGTH 2
+#define STATUS_INFO_LENGTH 2
+#define STATUS_TYPE_OFFSET PARAMETER_VALUE_OFFSET
+#define STATUS_INFO_OFFSET (STATUS_TYPE_OFFSET + STATUS_TYPE_LENGTH)
+
+#define AS_STATE_CHANGE_TYPE 1
+#define OTHER_TYPE 2
+
+static const value_string status_type_values[] = {
+ { AS_STATE_CHANGE_TYPE, "Application server state change" },
+ { OTHER_TYPE, "Other" },
+ { 0, NULL } };
+
+#define RESERVED_INFO 1
+#define AS_INACTIVE_INFO 2
+#define AS_ACTIVE_INFO 3
+#define AS_PENDING_INFO 4
+
+#define INSUFFICIENT_ASP_RES_INFO 1
+#define ALTERNATE_ASP_ACTIVE_INFO 2
+#define ASP_FAILURE 3
+
+static const value_string status_type_info_values[] = {
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + RESERVED_INFO, "Reserved" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_INACTIVE_INFO, "Application server inactive" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_ACTIVE_INFO, "Application server active" },
+ { AS_STATE_CHANGE_TYPE * 256 * 256 + AS_PENDING_INFO, "Application server pending" },
+ { OTHER_TYPE * 256 * 256 + INSUFFICIENT_ASP_RES_INFO, "Insufficient ASP resources active in AS" },
+ { OTHER_TYPE * 256 * 256 + ALTERNATE_ASP_ACTIVE_INFO, "Alternate ASP active" },
+ { OTHER_TYPE * 256 * 256 + ASP_FAILURE, "ASP Failure" },
+ {0, NULL } };
+
+static void
+dissect_status_type_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 status_type, status_info;
+
+ status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
+ status_info = tvb_get_ntohs(parameter_tvb, STATUS_INFO_OFFSET);
+
+ proto_tree_add_item(parameter_tree, hf_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_uint_format(parameter_tree, hf_status_info, parameter_tvb, STATUS_INFO_OFFSET, STATUS_INFO_LENGTH,
+ status_info, "Status info: %s (%u)", val_to_str(status_type * 256 * 256 + status_info, status_type_info_values, "unknown"), status_info);
+
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(status_type * 256 * 256 + status_info, status_type_info_values, "unknown"));
+}
+
+#define ASP_IDENTIFIER_LENGTH 4
+#define ASP_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_asp_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_asp_identifier, parameter_tvb, ASP_IDENTIFIER_OFFSET, ASP_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, ASP_IDENTIFIER_OFFSET));
+}
+
+#define AFFECTED_MASK_LENGTH 1
+#define AFFECTED_DPC_LENGTH 3
+#define AFFECTED_DESTINATION_LENGTH (AFFECTED_MASK_LENGTH + AFFECTED_DPC_LENGTH)
+
+#define AFFECTED_MASK_OFFSET 0
+#define AFFECTED_DPC_OFFSET 1
+
+static void
+dissect_affected_destinations_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 number_of_destinations, destination_number;
+ gint destination_offset;
+
+ number_of_destinations= (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / 4;
+ destination_offset = PARAMETER_VALUE_OFFSET;
+ for(destination_number=1; destination_number <= number_of_destinations; destination_number++) {
+ proto_tree_add_item(parameter_tree, hf_mask, parameter_tvb, destination_offset + AFFECTED_MASK_OFFSET, AFFECTED_MASK_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_dpc, parameter_tvb, destination_offset + AFFECTED_DPC_OFFSET, AFFECTED_DPC_LENGTH, NETWORK_BYTE_ORDER);
+ destination_offset += AFFECTED_DESTINATION_LENGTH;
+ }
+ proto_item_append_text(parameter_item, " (%u destination%s)", number_of_destinations, plurality(number_of_destinations, "", "s"));
+}
+
+#define CORRELATION_ID_LENGTH 4
+#define CORRELATION_ID_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_correlation_id_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
+}
+
+static void
+dissect_registration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
+}
+
+static void
+dissect_deregistration_result_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
+}
+
+#define REGISTRATION_STATUS_LENGTH 4
+#define REGISTRATION_STATUS_OFFSET PARAMETER_VALUE_OFFSET
+
+static const value_string registration_status_values[] = {
+ { 0, "Successfully registered" },
+ { 1, "Error - unknown" },
+ { 2, "Error - invalid destination address" },
+ { 3, "Error - invalid network appearance" },
+ { 4, "Error - invalid routing key" },
+ { 5, "Error - permission denied" },
+ { 6, "Error - cannot support unique routing" },
+ { 7, "Error - routing key not currently provisioned" },
+ { 8, "Error - insufficient resources" },
+ { 9, "Error - unsupported RK parameter field" },
+ { 10, "Error - unsupported/invalid traffic mode type" },
+ { 11, "Error - routing key change refused" },
+ { 0, NULL } };
+
+static void
+dissect_registration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_registration_status, parameter_tvb, REGISTRATION_STATUS_OFFSET, REGISTRATION_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, REGISTRATION_STATUS_OFFSET), registration_status_values, "unknown"));
+}
+
+#define DEREGISTRATION_STATUS_LENGTH 4
+#define DEREGISTRATION_STATUS_OFFSET PARAMETER_VALUE_OFFSET
+
+static const value_string deregistration_status_values[] = {
+ { 0, "Successfully deregistered" },
+ { 1, "Error - unknown" },
+ { 2, "Error - invalid routing context" },
+ { 3, "Error - permission denied" },
+ { 4, "Error - not registered" },
+ { 5, "Error - ASP currently active for routing context" },
+ { 0, NULL } };
+
+static void
+dissect_deregistration_status_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_deregistration_status, parameter_tvb, DEREGISTRATION_STATUS_OFFSET, DEREGISTRATION_STATUS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_ntohl(parameter_tvb, DEREGISTRATION_STATUS_OFFSET), deregistration_status_values, "unknown"));
+}
+
+#define LOCAL_ROUTING_KEY_IDENTIFIER_LENGTH 4
+#define LOCAL_ROUTING_KEY_IDENTIFIER_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_local_routing_key_identifier_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_local_routing_key_identifier, parameter_tvb, LOCAL_ROUTING_KEY_IDENTIFIER_OFFSET, LOCAL_ROUTING_KEY_IDENTIFIER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%d)", tvb_get_ntohl(parameter_tvb, LOCAL_ROUTING_KEY_IDENTIFIER_OFFSET));
+}
+
+#define SS7_HOP_COUNTER_LENGTH 1
+#define SS7_HOP_COUNTER_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+
+static void
+dissect_ss7_hop_counter_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_ss7_hop_counter_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_ss7_hop_counter_counter, parameter_tvb, SS7_HOP_COUNTER_OFFSET, SS7_HOP_COUNTER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb, SS7_HOP_COUNTER_OFFSET));
+}
+
+#define ROUTING_INDICATOR_LENGTH 2
+#define ADDRESS_INDICATOR_LENGTH 2
+
+#define ROUTING_INDICATOR_OFFSET PARAMETER_VALUE_OFFSET
+#define ADDRESS_INDICATOR_OFFSET (ROUTING_INDICATOR_OFFSET + ROUTING_INDICATOR_LENGTH)
+#define ADDRESS_PARAMETERS_OFFSET (ADDRESS_INDICATOR_OFFSET + ADDRESS_INDICATOR_LENGTH)
+
+#define RESERVED_ROUTING_INDICATOR 0
+#define ROUTE_ON_GT_ROUTING_INDICATOR 1
+#define ROUTE_ON_SSN_PC_ROUTING_INDICATOR 2
+#define ROUTE_ON_HOSTNAMEROUTING_INDICATOR 3
+#define ROUTE_ON_SSN_IP_ROUTING_INDICATOR 4
+
+static const value_string routing_indicator_values[] = {
+ { RESERVED_ROUTING_INDICATOR, "Reserved" },
+ { ROUTE_ON_GT_ROUTING_INDICATOR, "Route on Global Title" },
+ { ROUTE_ON_SSN_PC_ROUTING_INDICATOR, "Route on SSN + PC" },
+ { ROUTE_ON_HOSTNAMEROUTING_INDICATOR, "Route on Hostname" },
+ { ROUTE_ON_SSN_IP_ROUTING_INDICATOR, "Route on SSN + IP Address" },
+ { 0, NULL } };
+
+#define ADDRESS_RESERVED_BITMASK 0xfff8
+#define ADDRESS_GT_BITMASK 0x0004
+#define ADDRESS_PC_BITMASK 0x0002
+#define ADDRESS_SSN_BITMASK 0x0001
+
+static void
+dissect_source_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, guint8 *ssn)
+{
+ proto_item *address_indicator_item;
+ proto_tree *address_indicator_tree;
+ tvbuff_t *parameters_tvb;
+
+ if(parameter_tree) {
+ proto_tree_add_item(parameter_tree, hf_source_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
+ address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_source_address_indicator);
+ proto_tree_add_item(address_indicator_tree, hf_source_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_source_address_gt_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_source_address_pc_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_source_address_ssn_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ }
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETERS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, ssn, NULL);
+}
+
+static void
+dissect_destination_address_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, guint8 *ssn)
+{
+ proto_item *address_indicator_item;
+ proto_tree *address_indicator_tree;
+ tvbuff_t *parameters_tvb;
+
+ if(parameter_tree) {
+ proto_tree_add_item(parameter_tree, hf_destination_address_routing_indicator, parameter_tvb, ROUTING_INDICATOR_OFFSET, ROUTING_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ address_indicator_item = proto_tree_add_text(parameter_tree, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, "Address Indicator");
+ address_indicator_tree = proto_item_add_subtree(address_indicator_item, ett_sua_destination_address_indicator);
+ proto_tree_add_item(address_indicator_tree, hf_destination_address_reserved_bits, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_destination_address_gt_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_destination_address_pc_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(address_indicator_tree, hf_destination_address_ssn_bit, parameter_tvb, ADDRESS_INDICATOR_OFFSET, ADDRESS_INDICATOR_LENGTH, NETWORK_BYTE_ORDER);
+ }
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, ADDRESS_PARAMETERS_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, ssn);
+}
+
+#define SOURCE_REFERENCE_NUMBER_LENGTH 4
+#define SOURCE_REFERENCE_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_source_reference_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_source_reference_number, parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET, SOURCE_REFERENCE_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, SOURCE_REFERENCE_NUMBER_OFFSET));
+}
+
+#define DESTINATION_REFERENCE_NUMBER_LENGTH 4
+#define DESTINATION_REFERENCE_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_destination_reference_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_destination_reference_number, parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET, DESTINATION_REFERENCE_NUMBER_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, DESTINATION_REFERENCE_NUMBER_OFFSET));
+}
+
+#define CAUSE_TYPE_LENGTH 1
+#define CAUSE_VALUE_LENGTH 1
+
+#define CAUSE_TYPE_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
+#define CAUSE_VALUE_OFFSET (CAUSE_TYPE_OFFSET + CAUSE_TYPE_LENGTH)
+
+static const value_string cause_type_values[] = {
+ { 0x1, "Return Cause" },
+ { 0x2, "Refusual Cause" },
+ { 0x3, "Release Cause" },
+ { 0x4, "Reset Cause" },
+ { 0x5, "Error cause" },
+ { 0, NULL } };
+
+static void
+dissect_sccp_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_cause_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_cause_type, parameter_tvb, CAUSE_TYPE_OFFSET, CAUSE_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_cause_value, parameter_tvb, CAUSE_VALUE_OFFSET, CAUSE_VALUE_LENGTH, NETWORK_BYTE_ORDER);
+
+ proto_item_append_text(parameter_item, " (%s)", val_to_str(tvb_get_guint8(parameter_tvb, CAUSE_TYPE_OFFSET), cause_type_values, "unknown"));
+}
+
+#define SEQUENCE_NUMBER_REC_SEQ_LENGTH 1
+#define SEQUENCE_NUMBER_SENT_SEQ_LENGTH 1
+#define SEQUENCE_NUMBER_REC_SEQ_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
+#define SEQUENCE_NUMBER_SENT_SEQ_OFFSET (SEQUENCE_NUMBER_REC_SEQ_OFFSET + SEQUENCE_NUMBER_REC_SEQ_LENGTH)
+
+#define SEQ_NUM_MASK 0xFE
+#define SPARE_BIT_MASK 0x01
+#define MORE_DATA_BIT_MASK 0x01
+
+static const true_false_string more_data_bit_value = {
+ "More Data",
+ "Not More Data"
+};
+
+static void
+dissect_sequence_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_item *sent_sequence_number_item;
+ proto_tree *sent_sequence_number_tree;
+ proto_item *receive_sequence_number_item;
+ proto_tree *receive_sequence_number_tree;
+
+ proto_tree_add_item(parameter_tree, hf_sequence_number_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH, NETWORK_BYTE_ORDER);
+
+ receive_sequence_number_item = proto_tree_add_text(parameter_tree, parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH, "Receive Sequence Number");
+ receive_sequence_number_tree = proto_item_add_subtree(receive_sequence_number_item, ett_sua_sequence_number_rec_number);
+ proto_tree_add_item(receive_sequence_number_tree, hf_sequence_number_rec_number, parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(receive_sequence_number_tree, hf_sequence_number_more_data_bit, parameter_tvb, SEQUENCE_NUMBER_REC_SEQ_OFFSET, SEQUENCE_NUMBER_REC_SEQ_LENGTH, NETWORK_BYTE_ORDER);
+
+ sent_sequence_number_item = proto_tree_add_text(parameter_tree, parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH, "Sent Sequence Number");
+ sent_sequence_number_tree = proto_item_add_subtree(sent_sequence_number_item, ett_sua_sequence_number_sent_number);
+ proto_tree_add_item(sent_sequence_number_tree, hf_sequence_number_sent_number, parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(sent_sequence_number_tree, hf_sequence_number_spare_bit, parameter_tvb, SEQUENCE_NUMBER_SENT_SEQ_OFFSET, SEQUENCE_NUMBER_SENT_SEQ_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH 1
+#define RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+
+static void
+dissect_receive_sequence_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_item *receive_sequence_number_item;
+ proto_tree *receive_sequence_number_tree;
+
+ proto_tree_add_item(parameter_tree, hf_receive_sequence_number_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+ receive_sequence_number_item = proto_tree_add_text(parameter_tree, parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, "Receive Sequence Number");
+ receive_sequence_number_tree = proto_item_add_subtree(receive_sequence_number_item, ett_sua_receive_sequence_number_number);
+ proto_tree_add_item(receive_sequence_number_tree, hf_receive_sequence_number_number, parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(receive_sequence_number_tree, hf_receive_sequence_number_spare_bit, parameter_tvb, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_OFFSET, RECEIVE_SEQUENCE_NUMBER_REC_SEQ_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define PROTOCOL_CLASSES_LENGTH 1
+#define INTERWORKING_LENGTH 1
+#define PROTOCOL_CLASSES_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_2_LENGTH)
+#define INTERWORKING_OFFSET (PROTOCOL_CLASSES_OFFSET + PROTOCOL_CLASSES_LENGTH)
+
+#define A_BIT_MASK 0x08
+#define B_BIT_MASK 0x04
+#define C_BIT_MASK 0x02
+#define D_BIT_MASK 0x01
+#define RESERVED_BITS_MASK 0xF0
+
+static const true_false_string sua_supported_bit_value = {
+ "Supported",
+ "Unsupported"
+};
+
+static const value_string interworking_values[] = {
+ { 0x0, "No Interworking with SS7 Networks" },
+ { 0x1, "IP-Signalling Endpoint interworking with with SS7 networks" },
+ { 0x2, "Signalling Gateway" },
+ { 0x3, "Relay Node Support" },
+ { 0, NULL } };
+
+static void
+dissect_asp_capabilities_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_item *protocol_classes_item;
+ proto_tree *protocol_classes_tree;
+
+ proto_tree_add_item(parameter_tree, hf_asp_capabilities_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_2_LENGTH, NETWORK_BYTE_ORDER);
+ protocol_classes_item = proto_tree_add_text(parameter_tree, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, "Protocol classes");
+ protocol_classes_tree = proto_item_add_subtree(protocol_classes_item, ett_sua_protcol_classes);
+ proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_reserved_bits, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_a_bit, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_b_bit, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_c_bit, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(protocol_classes_tree, hf_asp_capabilities_d_bit, parameter_tvb, PROTOCOL_CLASSES_OFFSET, PROTOCOL_CLASSES_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_asp_capabilities_interworking, parameter_tvb, INTERWORKING_OFFSET, INTERWORKING_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define CREDIT_LENGTH 4
+#define CREDIT_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_credit_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_credit, parameter_tvb, CREDIT_OFFSET, CREDIT_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CREDIT_OFFSET));
+}
+
+#define DATA_PARAMETER_DATA_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_data_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, tvbuff_t **data_tvb)
+{
+ guint16 data_length;
+
+ data_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+
+ if(parameter_tree) {
+ proto_tree_add_item(parameter_tree, hf_data, parameter_tvb, DATA_PARAMETER_DATA_OFFSET, data_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (SS7 message of %u byte%s)", data_length, plurality(data_length, "", "s"));
+ }
+
+ if(data_tvb)
+ {
+ *data_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, data_length, data_length);
+ }
+}
+
+
+#define CAUSE_LENGTH 2
+#define USER_LENGTH 2
+#define CAUSE_OFFSET PARAMETER_VALUE_OFFSET
+#define USER_OFFSET (CAUSE_OFFSET + CAUSE_LENGTH)
+
+static const value_string cause_values[] = {
+ { 0x0, "Remote SCCP unavailable, Reason unknown" },
+ { 0x2, "Remote SCCP unequipped" },
+ { 0x3, "Remote SCCP inaccessable" },
+ { 0, NULL } };
+
+static void
+dissect_user_cause_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_tree_add_item(parameter_tree, hf_cause, parameter_tvb, CAUSE_OFFSET, CAUSE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_user, parameter_tvb, USER_OFFSET, USER_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define NETWORK_APPEARANCE_LENGTH 4
+#define NETWORK_APPEARANCE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_network_appearance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_network_appearance, parameter_tvb, NETWORK_APPEARANCE_OFFSET, NETWORK_APPEARANCE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, NETWORK_APPEARANCE_OFFSET));
+}
+
+static void
+dissect_routing_key_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
+}
+#define DRN_START_LENGTH 1
+#define DRN_END_LENGTH 1
+#define DRN_VALUE_LENGTH 2
+
+#define DRN_START_OFFSET PARAMETER_VALUE_OFFSET
+#define DRN_END_OFFSET (DRN_START_OFFSET + DRN_START_LENGTH)
+#define DRN_VALUE_OFFSET (DRN_END_OFFSET + DRN_END_LENGTH)
+
+static void
+dissect_drn_label_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_tree_add_item(parameter_tree, hf_drn_label_start, parameter_tvb, DRN_START_OFFSET, DRN_START_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_drn_label_end, parameter_tvb, DRN_END_OFFSET, DRN_END_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_drn_label_value, parameter_tvb, DRN_VALUE_OFFSET, DRN_VALUE_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define TID_START_LENGTH 1
+#define TID_END_LENGTH 1
+#define TID_VALUE_LENGTH 2
+
+#define TID_START_OFFSET PARAMETER_VALUE_OFFSET
+#define TID_END_OFFSET (TID_START_OFFSET + TID_START_LENGTH)
+#define TID_VALUE_OFFSET (TID_END_OFFSET + TID_END_LENGTH)
+
+static void
+dissect_tid_label_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_tree_add_item(parameter_tree, hf_tid_label_start, parameter_tvb, TID_START_OFFSET, TID_START_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_tid_label_end, parameter_tvb, TID_END_OFFSET, TID_END_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_tid_label_value, parameter_tvb, TID_VALUE_OFFSET, TID_VALUE_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define ADDRESS_RANGE_ADDRESS_PARAMETERS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_address_range_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ tvbuff_t *parameters_tvb;
+
+ parameters_tvb = tvb_new_subset(parameter_tvb, PARAMETER_VALUE_OFFSET, -1, -1);
+ dissect_parameters(parameters_tvb, parameter_tree, NULL, NULL, NULL);
+}
+
+#define SMI_LENGTH 1
+#define SMI_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+
+static void
+dissect_smi_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_smi_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_smi, parameter_tvb, SMI_OFFSET, SMI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb, SMI_OFFSET));
+}
+
+#define IMPORTANCE_LENGTH 1
+#define IMPORTANCE_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+
+static void
+dissect_importance_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_importance_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_importance, parameter_tvb, IMPORTANCE_OFFSET, IMPORTANCE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb, IMPORTANCE_OFFSET));
+}
+
+#define MESSAGE_PRIORITY_LENGTH 1
+#define MESSAGE_PRIORITY_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+
+static void
+dissect_message_priority_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_message_priority_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_message_priority, parameter_tvb, MESSAGE_PRIORITY_OFFSET, MESSAGE_PRIORITY_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_guint8(parameter_tvb, MESSAGE_PRIORITY_OFFSET));
+}
+
+#define PROTOCOL_CLASS_LENGTH 1
+#define PROTOCOL_CLASS_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+
+#define RETURN_ON_ERROR_BIT_MASK 0x80
+#define PROTOCOL_CLASS_MASK 0x7f
+
+
+static const true_false_string return_on_error_bit_value = {
+ "Return Message On Error",
+ "No Special Options"
+};
+
+static void
+dissect_protocol_class_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_item *protocol_class_item;
+ proto_tree *protocol_class_tree;
+
+ proto_tree_add_item(parameter_tree, hf_protocol_class_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+
+ protocol_class_item = proto_tree_add_text(parameter_tree, parameter_tvb, PROTOCOL_CLASS_OFFSET, PROTOCOL_CLASS_LENGTH, "Protocol Class");
+ protocol_class_tree = proto_item_add_subtree(protocol_class_item, ett_sua_return_on_error_bit_and_protocol_class);
+
+ proto_tree_add_item(protocol_class_tree, hf_return_on_error_bit, parameter_tvb, PROTOCOL_CLASS_OFFSET, PROTOCOL_CLASS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(protocol_class_tree, hf_protocol_class, parameter_tvb, PROTOCOL_CLASS_OFFSET, PROTOCOL_CLASS_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define SEQUENCE_CONTROL_LENGTH 4
+#define SEQUENCE_CONTROL_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_sequence_control_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_sequence_control, parameter_tvb, SEQUENCE_CONTROL_OFFSET, SEQUENCE_CONTROL_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, SEQUENCE_CONTROL_OFFSET));
+}
+
+#define FIRST_REMAINING_LENGTH 1
+#define SEGMENTATION_REFERENCE_LENGTH 3
+#define FIRST_REMAINING_OFFSET PARAMETER_VALUE_OFFSET
+#define SEGMENTATION_REFERENCE_OFFSET (FIRST_REMAINING_OFFSET + FIRST_REMAINING_LENGTH)
+
+#define FIRST_BIT_MASK 0x80
+#define NUMBER_OF_SEGMENTS_MASK 0x7f
+
+static const true_false_string first_bit_value = {
+ "First segment",
+ "Subsequent segment"
+};
+
+static void
+dissect_segmentation_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ proto_item *first_remaining_item;
+ proto_tree *first_remaining_tree;
+
+ first_remaining_item = proto_tree_add_text(parameter_tree, parameter_tvb, FIRST_REMAINING_OFFSET, FIRST_REMAINING_LENGTH, "First / Remaining");
+ first_remaining_tree = proto_item_add_subtree(first_remaining_item, ett_sua_first_remaining);
+ proto_tree_add_item(first_remaining_tree, hf_first_bit, parameter_tvb, FIRST_REMAINING_OFFSET, FIRST_REMAINING_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(first_remaining_tree, hf_number_of_remaining_segments, parameter_tvb, FIRST_REMAINING_OFFSET, FIRST_REMAINING_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_segmentation_reference, parameter_tvb, SEGMENTATION_REFERENCE_OFFSET, SEGMENTATION_REFERENCE_LENGTH, NETWORK_BYTE_ORDER);
+}
+
+#define CONGESTION_LEVEL_LENGTH 4
+#define CONGESTION_LEVEL_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_congestion_level_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_congestion_level, parameter_tvb, CONGESTION_LEVEL_OFFSET, CONGESTION_LEVEL_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, CONGESTION_LEVEL_OFFSET));
+}
+
+#define GTI_LENGTH 1
+#define NO_OF_DIGITS_LENGTH 1
+#define TRANSLATION_TYPE_LENGTH 1
+#define NUMBERING_PLAN_LENGTH 1
+#define NATURE_OF_ADDRESS_LENGTH 1
+
+#define GTI_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+#define NO_OF_DIGITS_OFFSET (GTI_OFFSET + GTI_LENGTH)
+#define TRANSLATION_TYPE_OFFSET (NO_OF_DIGITS_OFFSET + NO_OF_DIGITS_LENGTH)
+#define NUMBERING_PLAN_OFFSET (TRANSLATION_TYPE_OFFSET + TRANSLATION_TYPE_LENGTH)
+#define NATURE_OF_ADDRESS_OFFSET (NUMBERING_PLAN_OFFSET + NUMBERING_PLAN_LENGTH)
+#define GLOBAL_TITLE_OFFSET (NATURE_OF_ADDRESS_OFFSET + NATURE_OF_ADDRESS_LENGTH)
+
+#define ISDN_TELEPHONY_NUMBERING_PLAN 1
+#define GENERIC_NUMBERING_PLAN 2
+#define DATA_NUMBERING_PLAN 3
+#define TELEX_NUMBERING_PLAN 4
+#define MARITIME_MOBILE_NUMBERING_PLAN 5
+#define LAND_MOBILE_NUMBERING_PLAN 6
+#define ISDN_MOBILE_NUMBERING_PLAN 7
+#define PRIVATE_NETWORK_NUMBERING_PLAN 14
+
+static const value_string numbering_plan_values[] = {
+ { ISDN_TELEPHONY_NUMBERING_PLAN, "ISDN/Telephony Numbering Plan (Rec. E.161 and E.164)" },
+ { GENERIC_NUMBERING_PLAN, "Generic Numbering Plan" },
+ { DATA_NUMBERING_PLAN, "Data Numbering Plan (Rec. X.121)" },
+ { TELEX_NUMBERING_PLAN, "Telex Numbering Plan (Rec. F.69)" },
+ { MARITIME_MOBILE_NUMBERING_PLAN, "Maritime Mobile Numbering Plan (Rec. E.210 and E.211)" },
+ { LAND_MOBILE_NUMBERING_PLAN, "Land Mobile Numbering Plan (Rec. E.212)" },
+ { ISDN_MOBILE_NUMBERING_PLAN, "ISDN/Mobile Numbering Plan (Rec. E.214)" },
+ { PRIVATE_NETWORK_NUMBERING_PLAN, "Private Network Or Network-Specific Numbering Plan" },
+ { 0, NULL } };
+
+#define UNKNOWN_NATURE_OF_ADDRESS 0
+#define SUBSCRIBER_NUMBER_NATURE_OF_ADDRESS 1
+#define RESERVED_FOR_NATIONAL_USE_NATURE_OF_ADDRESS 2
+#define NATIONAL_SIGNIFICANT_NUMBER_NATURE_OF_ADDRESS 3
+#define INTERNATION_NUMBER_NATURE_OF_ADDRESS 4
+
+static const value_string nature_of_address_values[] = {
+ { UNKNOWN_NATURE_OF_ADDRESS, "Unknown" },
+ { SUBSCRIBER_NUMBER_NATURE_OF_ADDRESS, "Subscriber Number" },
+ { RESERVED_FOR_NATIONAL_USE_NATURE_OF_ADDRESS, "Reserved For National Use" },
+ { NATIONAL_SIGNIFICANT_NUMBER_NATURE_OF_ADDRESS, "Natinal Significant Number" },
+ { INTERNATION_NUMBER_NATURE_OF_ADDRESS, "International Number" },
+ { 0, NULL } };
+
+static void
+dissect_global_title_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
+{
+ guint16 global_title_length;
+
+ global_title_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) -
+ (PARAMETER_HEADER_LENGTH + RESERVED_3_LENGTH + GTI_LENGTH + NO_OF_DIGITS_LENGTH + TRANSLATION_TYPE_LENGTH + NUMBERING_PLAN_LENGTH + NATURE_OF_ADDRESS_LENGTH);
+ proto_tree_add_item(parameter_tree, hf_gt_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_gti, parameter_tvb, GTI_OFFSET, GTI_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_number_of_digits, parameter_tvb, NO_OF_DIGITS_OFFSET, NO_OF_DIGITS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_translation_type, parameter_tvb, TRANSLATION_TYPE_OFFSET, TRANSLATION_TYPE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_numbering_plan, parameter_tvb, NUMBERING_PLAN_OFFSET, NUMBERING_PLAN_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_nature_of_address, parameter_tvb, NATURE_OF_ADDRESS_OFFSET, NATURE_OF_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_global_title, parameter_tvb, GLOBAL_TITLE_OFFSET, global_title_length, NETWORK_BYTE_ORDER);
+}
+
+#define POINT_CODE_LENGTH 4
+#define POINT_CODE_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_point_code_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_point_code_dpc, parameter_tvb, POINT_CODE_OFFSET, POINT_CODE_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", tvb_get_ntohl(parameter_tvb, POINT_CODE_OFFSET));
+}
+
+#define SSN_LENGTH 1
+#define SSN_OFFSET (PARAMETER_VALUE_OFFSET + RESERVED_3_LENGTH)
+#define INVALID_SSN 0xff
+
+static void
+dissect_ssn_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, guint8 *ssn)
+{
+ *ssn = tvb_get_guint8(parameter_tvb, SSN_OFFSET);
+
+ if(parameter_tree) {
+ proto_tree_add_item(parameter_tree, hf_ssn_reserved, parameter_tvb, PARAMETER_VALUE_OFFSET, RESERVED_3_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_ssn_number, parameter_tvb, SSN_OFFSET, SSN_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%u)", *ssn);
+ }
+}
+
+#define IPV4_ADDRESS_LENGTH 4
+#define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_ipv4_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_ipv4, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", ip_to_str((const guint8 *)tvb_get_ptr(parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH)));
+}
+
+#define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_hostname_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 hostname_length;
+
+ hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%.*s)", hostname_length,
+ (const char *)tvb_get_ptr(parameter_tvb, HOSTNAME_OFFSET, hostname_length));
+}
+
+#define IPV6_ADDRESS_LENGTH 16
+#define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
+
+static void
+dissect_ipv6_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ proto_tree_add_item(parameter_tree, hf_ipv6, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, " (%s)", ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH)));
+}
+
+static void
+dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
+{
+ guint16 parameter_value_length;
+
+ parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
+ proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, NETWORK_BYTE_ORDER);
+ proto_item_append_text(parameter_item, "(tag %u and %u byte%s value)", tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET), parameter_value_length, plurality(parameter_value_length, "", "s"));
+}
+
+static void
+dissect_parameter(tvbuff_t *parameter_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
+{
+ guint16 tag, length, padding_length;
+ proto_item *parameter_item;
+ proto_tree *parameter_tree;
+ guint8 ssn = INVALID_SSN;
+
+ /* extract tag and length from the parameter */
+ tag = tvb_get_ntohs(parameter_tvb, PARAMETER_TAG_OFFSET);
+ length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
+ padding_length = tvb_length(parameter_tvb) - length;
+
+ if (tree) {
+ /* create proto_tree stuff */
+ parameter_item = proto_tree_add_text(tree, parameter_tvb, PARAMETER_HEADER_OFFSET, tvb_length(parameter_tvb), val_to_str(tag, parameter_tag_values, "Unknown parameter"));
+ parameter_tree = proto_item_add_subtree(parameter_item, ett_sua_parameter);
+
+ /* add tag and length to the sua tree */
+ proto_tree_add_item(parameter_tree, hf_parameter_tag, parameter_tvb, PARAMETER_TAG_OFFSET, PARAMETER_TAG_LENGTH, NETWORK_BYTE_ORDER);
+ proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, NETWORK_BYTE_ORDER);
+ } else {
+ parameter_tree = NULL;
+ parameter_item = NULL;
+ }
+/*
+** If no tree, only the data and ssn parameters in the source and destination
+** address need to be dissected. This in order to make dissection of the data
+** possible when there is no tree.
+*/
+ switch(tag) {
+ case DATA_PARAMETER_TAG:
+ dissect_data_parameter(parameter_tvb, parameter_tree, parameter_item, data_tvb);
+ break;
+ case INFO_STRING_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_info_string_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case ROUTING_CONTEXT_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_routing_context_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case DIAGNOSTIC_INFO_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_diagnostic_information_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case HEARTBEAT_DATA_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_heartbeat_data_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case TRAFFIC_MODE_TYPE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_traffic_mode_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case ERROR_CODE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_error_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case STATUS_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_status_type_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case CONGESTION_LEVEL_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_congestion_level_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case ASP_IDENTIFIER_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_asp_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case AFFECTED_POINT_CODE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_affected_destinations_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case REGISTRATION_STATUS_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_registration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case DEREGISTRATION_STATUS_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_deregistration_status_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case LOCAL_ROUTING_KEY_IDENTIFIER_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_local_routing_key_identifier_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case SS7_HOP_COUNTER_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_ss7_hop_counter_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case SOURCE_ADDRESS_PARAMETER_TAG:
+ dissect_source_address_parameter(parameter_tvb, parameter_tree, source_ssn);
+ break;
+ case DESTINATION_ADDRESS_PARAMETER_TAG:
+ dissect_destination_address_parameter(parameter_tvb, parameter_tree, dest_ssn);
+ break;
+ case SOURCE_REFERENCE_NUMBER_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_source_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case DESTINATION_REFERENCE_NUMBER_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_destination_reference_number_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case SCCP_CAUSE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_sccp_cause_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case SEQUENCE_NUMBER_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_sequence_number_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case RECEIVE_SEQUENCE_NUMBER_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_receive_sequence_number_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case ASP_CAPABILITIES_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_asp_capabilities_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case CREDIT_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_credit_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case USER_CAUSE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_user_cause_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case NETWORK_APPEARANCE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_network_appearance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case ROUTING_KEY_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_routing_key_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case REGISTRATION_RESULT_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_registration_result_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case DEREGISTRATION_RESULT_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_deregistration_result_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case ADDRESS_RANGE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_address_range_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case CORRELATION_ID_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_correlation_id_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case IMPORTANCE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_importance_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case MESSAGE_PRIORITY_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_message_priority_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case PROTOCOL_CLASS_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_protocol_class_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case SEQUENCE_CONTROL_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_sequence_control_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case SEGMENTATION_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_segmentation_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case SMI_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_smi_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case TID_LABEL_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_tid_label_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case DRN_LABEL_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_drn_label_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case GLOBAL_TITLE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_global_title_parameter(parameter_tvb, parameter_tree);
+ }
+ break;
+ case POINT_CODE_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_point_code_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case SUBSYSTEM_NUMBER_PARAMETER_TAG:
+ dissect_ssn_parameter(parameter_tvb, parameter_tree, parameter_item, &ssn);
+ if(source_ssn)
+ {
+ *source_ssn = ssn;
+ }
+ if(dest_ssn)
+ {
+ *dest_ssn = ssn;
+ }
+ break;
+ case IPV4_ADDRESS_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_ipv4_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case HOSTNAME_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_hostname_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ case IPV6_ADDRESS_PARAMETER_TAG:
+ if (parameter_tree) {
+ dissect_ipv6_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ default:
+ if (parameter_tree) {
+ dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
+ }
+ break;
+ };
+ if (parameter_tree && (padding_length > 0))
+ proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, NETWORK_BYTE_ORDER);
+}
+
+static void
+dissect_parameters(tvbuff_t *parameters_tvb, proto_tree *tree, tvbuff_t **data_tvb, guint8 *source_ssn, guint8 *dest_ssn)
+{
+ gint offset, length, total_length, remaining_length;
+ tvbuff_t *parameter_tvb;
+
+ offset = 0;
+ while((remaining_length = tvb_length_remaining(parameters_tvb, offset))) {
+ length = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
+ total_length = ADD_PADDING(length);
+ if (remaining_length >= length)
+ total_length = MIN(total_length, remaining_length);
+ /* create a tvb for the parameter including the padding bytes */
+ parameter_tvb = tvb_new_subset(parameters_tvb, offset, total_length, total_length);
+ dissect_parameter(parameter_tvb, tree, data_tvb, source_ssn, dest_ssn);
+ /* get rid of the handled parameter */
+ offset += total_length;
+ }
+}
+
+static void
+dissect_sua_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *sua_tree, proto_tree *tree)
+{
+ tvbuff_t *common_header_tvb;
+ tvbuff_t *parameters_tvb;
+ tvbuff_t *data_tvb = NULL;
+ guint8 source_ssn = INVALID_SSN;
+ guint8 dest_ssn = INVALID_SSN;
+
+ common_header_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_OFFSET, COMMON_HEADER_LENGTH, COMMON_HEADER_LENGTH);
+ dissect_common_header(common_header_tvb, pinfo, sua_tree);
+
+ parameters_tvb = tvb_new_subset(message_tvb, COMMON_HEADER_LENGTH, -1, -1);
+ dissect_parameters(parameters_tvb, sua_tree, &data_tvb, &source_ssn, &dest_ssn);
+
+ /* If there was SUA data it could be dissected */
+ if(data_tvb)
+ {
+ /* Try subdissectors (if we found a valid SSN on the current message) */
+ if ((dest_ssn == INVALID_SSN ||
+ !dissector_try_port(sua_ssn_dissector_table, dest_ssn, data_tvb, pinfo, tree))
+ && (source_ssn == INVALID_SSN ||
+ !dissector_try_port(sua_ssn_dissector_table, source_ssn, data_tvb, pinfo, tree)))
+ {
+ /* No sub-dissection occured, treat it as raw data */
+ call_dissector(data_handle, data_tvb, pinfo, sua_tree);
+ }
+ }
+}
+
+static void
+dissect_sua(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *sua_item;
+ proto_tree *sua_tree;
+
+ /* make entry in the Protocol column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SUA");
+
+ /* Clear entries in Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+ /* create the sua protocol tree */
+ sua_item = proto_tree_add_item(tree, proto_sua, message_tvb, 0, -1, FALSE);
+ sua_tree = proto_item_add_subtree(sua_item, ett_sua);
+ } else {
+ sua_tree = NULL;
+ };
+
+ /* dissect the message */
+ dissect_sua_message(message_tvb, pinfo, sua_tree, tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_sua(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_version, { "Version", "sua.version", FT_UINT8, BASE_DEC, VALS(protocol_version_values), 0x0, "", HFILL } },
+ { &hf_reserved, { "Reserved", "sua.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_message_class, { "Message Class", "sua.message_class", FT_UINT8, BASE_DEC, VALS(message_class_values), 0x0, "", HFILL } },
+ { &hf_message_type, { "Message Type", "sua.message_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_message_length, { "Message Length", "sua.message_length", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_tag, { "Parameter Tag", "sua.parameter_tag", FT_UINT16, BASE_HEX, VALS(parameter_tag_values), 0x0, "", HFILL } },
+ { &hf_parameter_length, { "Parameter Length", "sua.parameter_length", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_value, { "Parameter Value", "sua.parameter_value", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_parameter_padding, { "Padding", "sua.parameter_padding", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_info_string, { "Info string", "sua.info_string", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_routing_context, { "Routing context", "sua.routing_context", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_diagnostic_information_info, { "Diagnostic Information", "sua.diagnostic_information", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_heartbeat_data, { "Heartbeat Data", "sua.heartbeat_data", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_traffic_mode_type, { "Traffic mode Type", "sua.traffic_mode_type", FT_UINT32, BASE_DEC, VALS(traffic_mode_type_values), 0x0, "", HFILL } },
+ { &hf_error_code, { "Error code", "sua.error_code", FT_UINT32, BASE_DEC, VALS(error_code_values), 0x0, "", HFILL } },
+ { &hf_status_type, { "Status type", "sua.status_type", FT_UINT16, BASE_DEC, VALS(status_type_values), 0x0, "", HFILL } },
+ { &hf_status_info, { "Status info", "sua.status_info", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_congestion_level, { "Congestion Level", "sua.congestion_level", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_asp_identifier, { "ASP Identifier", "sua.asp_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_mask, { "Mask", "sua.affected_point_code_mask", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_dpc, { "Affected DPC", "sua.affected_pointcode_dpc", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_registration_status, { "Registration status", "sua.registration_status", FT_UINT32, BASE_DEC, VALS(registration_status_values), 0x0, "", HFILL } },
+ { &hf_deregistration_status, { "Deregistration status", "sua.deregistration_status", FT_UINT32, BASE_DEC, VALS(deregistration_status_values), 0x0, "", HFILL } },
+ { &hf_local_routing_key_identifier, { "Local routing key identifier", "sua.local_routing_key_identifier", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_source_address_routing_indicator, { "Routing Indicator", "sua.source_address_routing_indicator", FT_UINT16, BASE_DEC, VALS(routing_indicator_values), 0x0, "", HFILL } },
+ { &hf_source_address_reserved_bits, { "Reserved Bits", "sua.source_address_reserved_bits", FT_UINT16, BASE_DEC, NULL, ADDRESS_RESERVED_BITMASK, "", HFILL } },
+ { &hf_source_address_gt_bit, { "Include GT", "sua.source_address_gt_bit", FT_BOOLEAN, 16, NULL, ADDRESS_GT_BITMASK, "", HFILL } },
+ { &hf_source_address_pc_bit, { "Include PC", "sua.source_address_pc_bit", FT_BOOLEAN, 16, NULL, ADDRESS_PC_BITMASK, "", HFILL } },
+ { &hf_source_address_ssn_bit, { "Include SSN", "sua.source_address_ssn_bit", FT_BOOLEAN, 16, NULL, ADDRESS_SSN_BITMASK, "", HFILL } },
+ { &hf_destination_address_routing_indicator, { "Routing Indicator", "sua.destination_address_routing_indicator", FT_UINT16, BASE_DEC, VALS(routing_indicator_values), 0x0, "", HFILL } },
+ { &hf_destination_address_reserved_bits, { "Reserved Bits", "sua.destination_address_reserved_bits", FT_UINT16, BASE_DEC, NULL, ADDRESS_RESERVED_BITMASK, "", HFILL } },
+ { &hf_destination_address_gt_bit, { "Include GT", "sua.destination_address_gt_bit", FT_BOOLEAN, 16, NULL, ADDRESS_GT_BITMASK, "", HFILL } },
+ { &hf_destination_address_pc_bit, { "Include PC", "sua.destination_address_pc_bit", FT_BOOLEAN, 16, NULL, ADDRESS_PC_BITMASK, "", HFILL } },
+ { &hf_destination_address_ssn_bit, { "Include SSN", "sua.destination_address_ssn_bit", FT_BOOLEAN, 16, NULL, ADDRESS_SSN_BITMASK, "", HFILL } },
+ { &hf_ss7_hop_counter_counter, { "SS7 Hop Counter", "sua.ss7_hop_counter_counter", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_ss7_hop_counter_reserved, { "Reserved", "sua.ss7_hop_counter_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_destination_reference_number, { "Destination Reference Number", "sua.destination_reference_number", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_source_reference_number, { "Source Reference Number", "sua.source_reference_number", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause_reserved, { "Reserved", "sua.sccp_cause_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_cause_type, { "Cause Type", "sua.sccp_cause_type", FT_UINT8, BASE_HEX, VALS(cause_type_values), 0x0, "", HFILL } },
+ { &hf_cause_value, { "Cause Value", "sua.sccp_cause_value", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_sequence_number_reserved, { "Reserved", "sua.sequence_number_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_sequence_number_rec_number, { "Receive Sequence Number P(R)", "sua.sequence_number_receive_sequence_number", FT_UINT8, BASE_DEC, NULL, SEQ_NUM_MASK, "", HFILL } },
+ { &hf_sequence_number_more_data_bit, { "More Data Bit", "sua.sequence_number_more_data_bit", FT_BOOLEAN, 8, TFS(&more_data_bit_value), MORE_DATA_BIT_MASK, "", HFILL } },
+ { &hf_sequence_number_sent_number, { "Sent Sequence Number P(S)", "sua.sequence_number_sent_sequence_number", FT_UINT8, BASE_DEC, NULL, SEQ_NUM_MASK, "", HFILL } },
+ { &hf_sequence_number_spare_bit, { "Spare Bit", "sua.sequence_number_spare_bit", FT_BOOLEAN, 8, NULL, SPARE_BIT_MASK, "", HFILL } },
+ { &hf_receive_sequence_number_reserved, { "Reserved", "sua.receive_sequence_number_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_receive_sequence_number_number, { "Receive Sequence Number P(R)", "sua.receive_sequence_number_number", FT_UINT8, BASE_DEC, NULL, SEQ_NUM_MASK, "", HFILL } },
+ { &hf_receive_sequence_number_spare_bit, { "Spare Bit", "sua.receive_sequence_number_spare_bit", FT_BOOLEAN, 8, NULL, SPARE_BIT_MASK, "", HFILL } },
+ { &hf_asp_capabilities_reserved, { "Reserved", "sua.asp_capabilities_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_asp_capabilities_reserved_bits, { "Reserved Bits", "sua.asp_capabilities_reserved_bits", FT_UINT8, BASE_HEX, NULL, RESERVED_BITS_MASK, "", HFILL } },
+ { &hf_asp_capabilities_a_bit, { "Protocol Class 3", "sua.asp_capabilities_a_bit", FT_BOOLEAN, 8, TFS(&sua_supported_bit_value), A_BIT_MASK, "", HFILL } },
+ { &hf_asp_capabilities_b_bit, { "Protocol Class 2", "sua.asp_capabilities_b_bit", FT_BOOLEAN, 8, TFS(&sua_supported_bit_value), B_BIT_MASK, "", HFILL } },
+ { &hf_asp_capabilities_c_bit, { "Protocol Class 1", "sua.asp_capabilities_c_bit", FT_BOOLEAN, 8, TFS(&sua_supported_bit_value), C_BIT_MASK, "", HFILL } },
+ { &hf_asp_capabilities_d_bit, { "Protocol Class 0", "sua.asp_capabilities_d_bit", FT_BOOLEAN, 8, TFS(&sua_supported_bit_value), D_BIT_MASK, "", HFILL } },
+ { &hf_asp_capabilities_interworking, { "Interworking", "sua.asp_capabilities_interworking", FT_UINT8, BASE_HEX, VALS(interworking_values), 0x0, "", HFILL } },
+ { &hf_credit, { "Credit", "sua.credit", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_cause, { "Cause", "sua.cause_user_cause", FT_UINT16, BASE_DEC, VALS(cause_values), 0x0, "", HFILL } },
+ { &hf_user, { "User", "sua.cause_user_user", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_data, { "Data", "sua.data", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_network_appearance, { "Network Appearance", "sua.network_appearance", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_routing_key_identifier, { "Local Routing Key Identifier", "sua.routing_key_identifier", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_correlation_id, { "Correlation ID", "sua.correlation_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_importance_reserved, { "Reserved", "sua.importance_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_importance, { "Importance", "sua.importance_inportance", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_message_priority_reserved, { "Reserved", "sua.message_priority_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_message_priority, { "Message Priority", "sua.message_priority_priority", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_protocol_class_reserved, { "Reserved", "sua.protcol_class_reserved", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_return_on_error_bit, { "Return On Error Bit", "sua.protocol_class_return_on_error_bit", FT_BOOLEAN, 8, TFS(&return_on_error_bit_value), RETURN_ON_ERROR_BIT_MASK, "", HFILL } },
+ { &hf_protocol_class, { "Protocol Class", "sua.protocol_class_class", FT_UINT8, BASE_DEC, NULL, PROTOCOL_CLASS_MASK, "", HFILL } },
+ { &hf_sequence_control, { "Sequence Control", "sua.sequence_control_sequence_control", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_first_bit, { "First Segment Bit", "sua.segmentation_first_bit", FT_BOOLEAN, 8, TFS(&first_bit_value), FIRST_BIT_MASK, "", HFILL } },
+ { &hf_number_of_remaining_segments, { "Number of Remaining Segments", "sua.segmentation_number_of_remaining_segments", FT_UINT8, BASE_DEC, NULL, NUMBER_OF_SEGMENTS_MASK, "", HFILL } },
+ { &hf_segmentation_reference, { "Segmentation Reference", "sua.segmentation_reference", FT_UINT24, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_smi_reserved, { "Reserved", "sua.smi_reserved", FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_smi, { "SMI", "sua.smi_smi", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_tid_label_start, { "Start", "sua.tid_label_start", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_tid_label_end, { "End", "sua.tid_label_end", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_tid_label_value, { "Label Value", "sua.tid_label_value", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_drn_label_start, { "Start", "sua.drn_label_start", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_drn_label_end, { "End", "sua.drn_label_end", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_drn_label_value, { "Label Value", "sua.drn_label_value", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_gt_reserved, { "Reserved", "sua.gt_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_gti, { "GTI", "sua.gti", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_number_of_digits, { "Number of Digits", "sua.global_title_number_of_digits", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_translation_type, { "Translation Type", "sua.global_title_translation_type", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL } },
+ { &hf_numbering_plan, { "Numbering Plan", "sua.global_title_numbering_plan", FT_UINT8, BASE_HEX, VALS(numbering_plan_values), 0x0, "", HFILL } },
+ { &hf_nature_of_address, { "Nature of Address", "sua.global_title_nature_of_address", FT_UINT8, BASE_HEX, VALS(nature_of_address_values), 0x0, "", HFILL } },
+ { &hf_global_title, { "Global Title", "sua.global_title_signals", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_point_code_dpc, { "Point Code", "sua.point_code", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_ssn_reserved, { "Reserved", "sua.ssn_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_ssn_number, { "Subsystem Number", "sua.ssn", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_ipv4, { "IP Version 4 address", "sua.ipv4_address", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_hostname, { "Hostname", "sua.hostname.name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL } },
+ { &hf_ipv6, { "IP Version 6 address", "sua.ipv6_address", FT_IPv6, BASE_NONE, NULL, 0x0, "", HFILL } },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_sua,
+ &ett_sua_parameter,
+ &ett_sua_source_address_indicator,
+ &ett_sua_destination_address_indicator,
+ &ett_sua_affected_destination,
+ &ett_sua_sequence_number_rec_number,
+ &ett_sua_sequence_number_sent_number,
+ &ett_sua_receive_sequence_number_number,
+ &ett_sua_protcol_classes,
+ &ett_sua_first_remaining,
+ &ett_sua_return_on_error_bit_and_protocol_class
+ };
+ module_t *sua_module;
+
+ /* Register the protocol name and description */
+ proto_sua = proto_register_protocol("SS7 SCCP-User Adaptation Layer", "SUA", "sua");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_sua, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ sua_module = prefs_register_protocol(proto_sua, NULL);
+ prefs_register_obsolete_preference(sua_module, "sua_version");
+
+ sua_ssn_dissector_table = register_dissector_table("sua.ssn", "SUA SSN", FT_UINT8, BASE_DEC);
+}
+
+void
+proto_reg_handoff_sua(void)
+{
+ dissector_handle_t sua_handle;
+
+ sua_handle = create_dissector_handle(dissect_sua, proto_sua);
+ dissector_add("sctp.ppi", SUA_PAYLOAD_PROTOCOL_ID, sua_handle);
+ dissector_add("sctp.port", SCTP_PORT_SUA, sua_handle);
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-symantec.c b/epan/dissectors/packet-symantec.c
new file mode 100644
index 0000000000..1969ab4f3f
--- /dev/null
+++ b/epan/dissectors/packet-symantec.c
@@ -0,0 +1,103 @@
+/* packet-symantec.c
+ * Routines for dissection of packets from the Axent Raptor firewall/
+ * Symantec Enterprise Firewall
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#include "etypes.h"
+
+static dissector_table_t ethertype_dissector_table;
+
+/* protocols and header fields */
+static int proto_symantec = -1;
+static int hf_symantec_etype = -1;
+
+static gint ett_symantec = -1;
+
+static void
+dissect_symantec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *symantec_tree = NULL;
+ guint16 etype;
+ tvbuff_t *next_tvb;
+
+ /*
+ * There appears to be 6 bytes of mysterious junk, followed by an
+ * Ethernet type (or, at least, there's 08 00), followed by 36 bytes
+ * of 0.
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_add_str(pinfo->cinfo, COL_PROTOCOL, "Symantec");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Symantec Enterprise Firewall");
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_symantec, tvb,
+ 0, 44, "Symantec firewall");
+ symantec_tree = proto_item_add_subtree(ti, ett_symantec);
+ }
+ etype = tvb_get_ntohs(tvb, 6);
+ if (tree) {
+ proto_tree_add_uint(symantec_tree, hf_symantec_etype, tvb,
+ 6, 2, etype);
+ }
+ next_tvb = tvb_new_subset(tvb, 44, -1, -1);
+ dissector_try_port(ethertype_dissector_table, etype, next_tvb, pinfo,
+ tree);
+}
+
+void
+proto_register_symantec(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_symantec_etype,
+ { "Type", "symantec.type", FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_symantec,
+ };
+
+ proto_symantec = proto_register_protocol("Symantec Enterprise Firewall",
+ "Symantec", "symantec");
+ proto_register_field_array(proto_symantec, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_symantec(void)
+{
+ dissector_handle_t symantec_handle;
+
+ ethertype_dissector_table = find_dissector_table("ethertype");
+
+ symantec_handle = create_dissector_handle(dissect_symantec,
+ proto_symantec);
+ dissector_add("wtap_encap", WTAP_ENCAP_SYMANTEC, symantec_handle);
+}
diff --git a/epan/dissectors/packet-syslog.c b/epan/dissectors/packet-syslog.c
new file mode 100644
index 0000000000..67859835e7
--- /dev/null
+++ b/epan/dissectors/packet-syslog.c
@@ -0,0 +1,253 @@
+/* packet-syslog.c
+ * Routines for syslog message dissection
+ *
+ * Copyright 2000, Gerald Combs <gerald@ethereal.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+#define UDP_PORT_SYSLOG 514
+
+#define PRIORITY_MASK 0x0007 /* 0000 0111 */
+#define FACILITY_MASK 0x03f8 /* 1111 1000 */
+
+/* The maximum number if priority digits to read in. */
+#define MAX_DIGITS 3
+
+#define COL_INFO_LEN 32
+#define ELLIPSIS "..." /* ISO 8859-1 doesn't appear to have a real ellipsis. */
+
+static const value_string short_lev[] = {
+ { 0, "EMERG" },
+ { 1, "ALERT" },
+ { 2, "CRIT" },
+ { 3, "ERR" },
+ { 4, "WARNING" },
+ { 5, "NOTICE" },
+ { 6, "INFO" },
+ { 7, "DEBUG" },
+ { 0, NULL },
+};
+
+static const value_string short_fac[] = {
+ { 0, "KERN" },
+ { 1, "USER" },
+ { 2, "MAIL" },
+ { 3, "DAEMON" },
+ { 4, "AUTH" },
+ { 5, "SYSLOG" },
+ { 6, "LPR" },
+ { 7, "NEWS" },
+ { 8, "UUCP" },
+ { 9, "CRON" }, /* The BSDs, Linux, and others */
+ { 10, "AUTHPRIV" },
+ { 11, "FTP" },
+ { 15, "CRON" }, /* Solaris */
+ { 16, "LOCAL0" },
+ { 17, "LOCAL1" },
+ { 18, "LOCAL2" },
+ { 19, "LOCAL3" },
+ { 20, "LOCAL4" },
+ { 21, "LOCAL5" },
+ { 22, "LOCAL6" },
+ { 23, "LOCAL7" },
+ { 0, NULL },
+};
+
+static const value_string long_lev[] = {
+ { 0, "EMERG - system is unusable" },
+ { 1, "ALERT - action must be taken immediately" },
+ { 2, "CRIT - critical conditions" },
+ { 3, "ERR - error conditions" },
+ { 4, "WARNING - warning conditions" },
+ { 5, "NOTICE - normal but significant condition" },
+ { 6, "INFO - informational" },
+ { 7, "DEBUG - debug-level messages" },
+ { 0, NULL },
+};
+
+static const value_string long_fac[] = {
+ { 0, "KERN - kernel messages" },
+ { 1, "USER - random user-level messages" },
+ { 2, "MAIL - mail system" },
+ { 3, "DAEMON - system daemons" },
+ { 4, "AUTH - security/authorization messages" },
+ { 5, "SYSLOG - messages generated internally by syslogd" },
+ { 6, "LPR - line printer subsystem" },
+ { 7, "NEWS - network news subsystem" },
+ { 8, "UUCP - UUCP subsystem" },
+ { 9, "CRON - clock daemon (BSD, Linux)" },
+ { 10, "AUTHPRIV - security/authorization messages (private)" },
+ { 11, "FTP - ftp daemon" },
+ { 15, "CRON - clock daemon (Solaris)" },
+ { 16, "LOCAL0 - reserved for local use" },
+ { 17, "LOCAL1 - reserved for local use" },
+ { 18, "LOCAL2 - reserved for local use" },
+ { 19, "LOCAL3 - reserved for local use" },
+ { 20, "LOCAL4 - reserved for local use" },
+ { 21, "LOCAL5 - reserved for local use" },
+ { 22, "LOCAL6 - reserved for local use" },
+ { 23, "LOCAL7 - reserved for local use" },
+ { 0, NULL },
+};
+
+static gint proto_syslog = -1;
+static gint hf_syslog_level = -1;
+static gint hf_syslog_facility = -1;
+static gint hf_syslog_msg = -1;
+
+static gint ett_syslog = -1;
+
+/* I couldn't find any documentation for the syslog message format.
+ According to the BSD sources, the message format is '<', P, '>', and
+ T. P is a decimal value, which should be treated as an 8 bit
+ unsigned integer. The lower three bits comprise the level, and the
+ upper five bits are the facility. T is the message text.
+ */
+
+static void dissect_syslog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gint pri = -1, lev = -1, fac = -1;
+ gint msg_off = 0, msg_len;
+ gint ellipsis_len = (COL_INFO_LEN - strlen(ELLIPSIS)) - 1;
+ proto_item *ti;
+ proto_tree *syslog_tree;
+ gchar msg_str[COL_INFO_LEN];
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Syslog");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tvb_get_guint8(tvb, msg_off) == '<') {
+ /* A facility and level follow. */
+ msg_off++;
+ pri = 0;
+ while (tvb_bytes_exist(tvb, msg_off, 1) &&
+ isdigit(tvb_get_guint8(tvb, msg_off)) && msg_off <= MAX_DIGITS) {
+ pri = pri * 10 + (tvb_get_guint8(tvb, msg_off) - '0');
+ msg_off++;
+ }
+ if (tvb_get_guint8(tvb, msg_off) == '>')
+ msg_off++;
+ fac = (pri & FACILITY_MASK) >> 3;
+ lev = pri & PRIORITY_MASK;
+ }
+
+ /* Copy the message into a string buffer, with a trailing ellipsis if needed. */
+ msg_len = tvb_ensure_length_remaining(tvb, msg_off);
+ if (msg_len >= COL_INFO_LEN) {
+ tvb_memcpy(tvb, msg_str, msg_off, ellipsis_len);
+ strcpy (msg_str + ellipsis_len, ELLIPSIS);
+ } else {
+ tvb_memcpy(tvb, msg_str, msg_off, msg_len);
+ msg_str[msg_len] = '\0';
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ if (pri >= 0) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s.%s: %s",
+ val_to_str(fac, short_fac, "UNKNOWN"),
+ val_to_str(lev, short_lev, "UNKNOWN"), msg_str);
+ } else {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", msg_str);
+ }
+ }
+
+ if (tree) {
+ if (pri >= 0) {
+ ti = proto_tree_add_protocol_format(tree, proto_syslog, tvb, 0, -1,
+ "Syslog message: %s.%s: %s",
+ val_to_str(fac, short_fac, "UNKNOWN"),
+ val_to_str(lev, short_lev, "UNKNOWN"), msg_str);
+ } else {
+ ti = proto_tree_add_protocol_format(tree, proto_syslog, tvb, 0, -1,
+ "Syslog message: (unknown): %s", msg_str);
+ }
+ syslog_tree = proto_item_add_subtree(ti, ett_syslog);
+ if (pri >= 0) {
+ ti = proto_tree_add_uint(syslog_tree, hf_syslog_facility, tvb, 0,
+ msg_off, pri);
+ ti = proto_tree_add_uint(syslog_tree, hf_syslog_level, tvb, 0,
+ msg_off, pri);
+ }
+ proto_tree_add_item(syslog_tree, hf_syslog_msg, tvb, msg_off,
+ msg_len, FALSE);
+ }
+ return;
+}
+
+/* Register the protocol with Ethereal */
+void proto_register_syslog(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_syslog_facility,
+ { "Facility", "syslog.facility",
+ FT_UINT8, BASE_DEC, VALS(long_fac), FACILITY_MASK,
+ "Message facility", HFILL }
+ },
+ { &hf_syslog_level,
+ { "Level", "syslog.level",
+ FT_UINT8, BASE_DEC, VALS(long_lev), PRIORITY_MASK,
+ "Message level", HFILL }
+ },
+ { &hf_syslog_msg,
+ { "Message", "syslog.msg",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Message Text", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_syslog,
+ };
+
+ /* Register the protocol name and description */
+ proto_syslog = proto_register_protocol("Syslog message", "Syslog", "syslog");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_syslog, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_syslog(void)
+{
+ dissector_handle_t syslog_handle;
+
+ syslog_handle = create_dissector_handle(dissect_syslog, proto_syslog);
+ dissector_add("udp.port", UDP_PORT_SYSLOG, syslog_handle);
+}
diff --git a/epan/dissectors/packet-t38.c b/epan/dissectors/packet-t38.c
new file mode 100644
index 0000000000..5fe112dbc1
--- /dev/null
+++ b/epan/dissectors/packet-t38.c
@@ -0,0 +1,929 @@
+/* packet-t38.c
+ * Routines for T.38 packet dissection
+ * 2003 Hans Viens
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+/* Depending on what ASN.1 specification is used you may have to change
+ * the preference setting regarding Pre-Corrigendum ASN.1 specification:
+ * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/1998/T38.html (Pre-Corrigendum=TRUE)
+ * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/2003/T38(1998).html (Pre-Corrigendum=TRUE)
+ *
+ * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/2003/T38(2002).html (Pre-Corrigendum=FALSE)
+ * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/2002/t38.html (Pre-Corrigendum=FALSE)
+ * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/2002-Amd1/T38.html (Pre-Corrigendum=FALSE)
+ */
+
+/* TO DO:
+ * - TCP desegmentation is currently not supported for T.38 IFP directly over TCP.
+ * - SDP and H.245 dissectors should be updated to start conversations for T.38 similar to RTP.
+ * - It would be nice if we could dissect the T.30 data.
+ * - Sometimes the last octet is not high-lighted when selecting something in the tree. Bug in PER dissector?
+ * - Add support for RTP payload audio/t38 (draft-jones-avt-audio-t38-03.txt), i.e. T38 in RTP packets.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "prefs.h"
+#include "ipproto.h"
+#include "packet-per.h"
+#include "prefs.h"
+#include "packet-tpkt.h"
+
+#define PORT_T38 6004
+static guint global_t38_tcp_port = PORT_T38;
+static guint global_t38_udp_port = PORT_T38;
+
+/*
+* Variables to allow for proper deletion of dissector registration when
+* the user changes port from the gui.
+*/
+static guint tcp_port = 0;
+static guint udp_port = 0;
+
+/* dissect using the Pre Corrigendum T.38 ASN.1 specification (1998) */
+static gboolean use_pre_corrigendum_asn1_specification = TRUE;
+
+/* dissect packets that looks like RTP version 2 packets as RTP */
+/* instead of as T.38. This may result in that some T.38 UPTL */
+/* packets with sequence number values higher than 32767 may be */
+/* shown as RTP packets. */
+static gboolean dissect_possible_rtpv2_packets_as_rtp = FALSE;
+
+
+/* Reassembly of T.38 PDUs over TPKT over TCP */
+static gboolean t38_tpkt_reassembly = TRUE;
+
+
+/* Preference setting whether TPKT header is used when sending T.38 over TCP.
+ * The default setting is Maybe where the dissector will look on the first
+ * bytes to try to determine whether TPKT header is used or not. This may not
+ * work so well in some cases. You may want to change the setting to Always or
+ * Newer.
+ */
+#define T38_TPKT_NEVER 0 /* Assume that there is never a TPKT header */
+#define T38_TPKT_ALWAYS 1 /* Assume that there is always a TPKT header */
+#define T38_TPKT_MAYBE 2 /* Assume TPKT if first octets are 03-00-xx-xx */
+static gint t38_tpkt_usage = T38_TPKT_MAYBE;
+
+static const enum_val_t t38_tpkt_options[] = {
+ {"never", "Never", T38_TPKT_NEVER},
+ {"always", "Always", T38_TPKT_ALWAYS},
+ {"maybe", "Maybe", T38_TPKT_MAYBE},
+ {NULL, NULL, -1}
+};
+
+
+static dissector_handle_t t38_udp_handle;
+static dissector_handle_t t38_tcp_handle;
+static dissector_handle_t t38_tcp_pdu_handle;
+static dissector_handle_t rtp_handle;
+
+static guint32 Type_of_msg_value;
+static guint32 Data_Field_field_type_value;
+static guint32 Data_value;
+static guint32 T30ind_value;
+
+static int proto_t38 = -1;
+static int hf_t38_IFPPacket = -1;
+static int hf_t38_Type_of_msg = -1;
+static int hf_t38_t30_indicator = -1;
+static int hf_t38_data = -1;
+static int hf_t38_Data_Field = -1;
+static int hf_t38_Data_Field_item = -1;
+static int hf_t38_Data_Field_field_type = -1;
+static int hf_t38_Data_Field_field_data = -1;
+static int hf_t38_UDPTLPacket = -1;
+static int hf_t38_seq_number = -1;
+static int hf_t38_primary_ifp_packet = -1;
+static int hf_t38_primary_ifp_packet_length = -1;
+static int hf_t38_error_recovery = -1;
+static int hf_t38_secondary_ifp_packets = -1;
+static int hf_t38_secondary_ifp_packets_item = -1;
+static int hf_t38_secondary_ifp_packets_item_length = -1;
+static int hf_t38_fec_info = -1;
+static int hf_t38_fec_npackets = -1;
+static int hf_t38_fec_data = -1;
+static int hf_t38_fec_data_item = -1;
+
+static gint ett_t38 = -1;
+static gint ett_t38_IFPPacket = -1;
+static gint ett_t38_Type_of_msg = -1;
+static gint ett_t38_t30_indicator = -1;
+static gint ett_t38_data = -1;
+static gint ett_t38_Data_Field = -1;
+static gint ett_t38_Data_Field_item = -1;
+static gint ett_t38_Data_Field_field_type = -1;
+static gint ett_t38_UDPTLPacket = -1;
+static gint ett_t38_error_recovery = -1;
+static gint ett_t38_secondary_ifp_packets = -1;
+static gint ett_t38_fec_info = -1;
+static gint ett_t38_fec_data = -1;
+
+static gboolean primary_part = TRUE;
+static guint32 seq_number = 0;
+
+
+/* RTP Version is the first 2 bits of the first octet in the UDP payload*/
+#define RTP_VERSION(octet) ((octet) >> 6)
+
+void proto_reg_handoff_t38(void);
+
+
+static int
+dissect_t38_NULL(tvbuff_t *tvb _U_, int offset, packet_info *pinfo _U_, proto_tree *tree _U_)
+{
+ return offset;
+}
+
+static per_choice_t t30_indicator_choice[] = {
+ { 0, "no-signal", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 1, "cng", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 2, "ced", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 3, "v21-preamble", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 4, "v27-2400-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 5, "v27-4800-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 6, "v29-7200-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 7, "v29-9600-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 8, "v17-7200-short-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 9, "v17-7200-long-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 10, "v17-9600-short-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 11, "v17-9600-long-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 12, "v17-12000-short-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 13, "v17-12000-long-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 14, "v17-14400-short-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 15, "v17-14400-long-training", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 16, "v8-ansam", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 17, "v8-signal", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 18, "v34-cntl-channel-1200", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 19, "v34-pri-channel", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 20, "v34-CC-retrain", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 21, "v33-12000-training", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 22, "v33-14400-training", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 0, NULL, 0, NULL }
+};
+
+static const value_string t30_indicator_vals[] = {
+ { 0, "no-signal" },
+ { 1, "cng" },
+ { 2, "ced" },
+ { 3, "v21-preamble" },
+ { 4, "v27-2400-training" },
+ { 5, "v27-4800-training" },
+ { 6, "v29-7200-training" },
+ { 7, "v29-9600-training" },
+ { 8, "v17-7200-short-training" },
+ { 9, "v17-7200-long-training" },
+ { 10, "v17-9600-short-training" },
+ { 11, "v17-9600-long-training" },
+ { 12, "v17-12000-short-training" },
+ { 13, "v17-12000-long-training" },
+ { 14, "v17-14400-short-training" },
+ { 15, "v17-14400-long-training" },
+ { 16, "v8-ansam" },
+ { 17, "v8-signal" },
+ { 18, "v34-cntl-channel-1200" },
+ { 19, "v34-pri-channel" },
+ { 20, "v34-CC-retrain" },
+ { 21, "v33-12000-training" },
+ { 22, "v33-14400-training" },
+ { 0, NULL },
+};
+
+static int
+dissect_t38_t30_indicator(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo,
+ tree, hf_t38_t30_indicator, ett_t38_t30_indicator,
+ t30_indicator_choice, "T30 Indicator", &T30ind_value);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && primary_part){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " t30ind: %s",
+ val_to_str(T30ind_value,t30_indicator_vals,"<unknown>"));
+ }
+ return offset;
+}
+
+static per_choice_t data_choice[] = {
+ { 0, "v21", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 1, "v27-2400", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 2, "v27-4800", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 3, "v29-7200", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 4, "v29-9600", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 5, "v17-7200", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 6, "v17-9600", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 7, "v17-12000", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 8, "v17-14400", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 9, "v8", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 10, "v34-pri-rate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 11, "v34-CC-1200", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 12, "v34-pri-ch", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 13, "v33-12000", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 14, "v33-14400", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 0, NULL, 0, NULL }
+};
+
+static const value_string data_vals[] = {
+ { 0, "v21" },
+ { 1, "v27-2400" },
+ { 2, "v27-4800" },
+ { 3, "v29-7200" },
+ { 4, "v29-9600" },
+ { 5, "v17-7200" },
+ { 6, "v17-9600" },
+ { 7, "v17-12000" },
+ { 8, "v17-14400" },
+ { 9, "v8" },
+ { 10, "v34-pri-rate" },
+ { 11, "v34-CC-1200" },
+ { 12, "v34-pri-ch" },
+ { 13, "v33-12000" },
+ { 14, "v33-14400" },
+ { 0, NULL },
+};
+
+static int
+dissect_t38_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo,
+ tree, hf_t38_data, ett_t38_data,
+ data_choice, "data", &Data_value);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && primary_part){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " data:%s:",
+ val_to_str(Data_value,data_vals,"<unknown>"));
+ }
+ return offset;
+}
+
+static per_choice_t Type_of_msg_choice[] = {
+ { 0, "t30-indicator", ASN1_NO_EXTENSIONS,
+ dissect_t38_t30_indicator},
+ { 1, "data", ASN1_NO_EXTENSIONS,
+ dissect_t38_data},
+ { 0, NULL, 0, NULL }
+};
+
+static const value_string Type_of_msg_vals[] = {
+ { 0, "t30-indicator" },
+ { 1, "data" },
+ { 0, NULL}
+};
+
+static int
+dissect_t38_Type_of_msg(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_choice(tvb, offset, pinfo,
+ tree, hf_t38_Type_of_msg, ett_t38_Type_of_msg,
+ Type_of_msg_choice, "Type of message", &Type_of_msg_value);
+ return offset;
+}
+
+static per_choice_t Data_Field_field_type_PreCorrigendum_choice[] = {
+ { 0, "hdlc-data", ASN1_NO_EXTENSIONS,
+ dissect_t38_NULL},
+ { 1, "hdlc-sig-end", ASN1_NO_EXTENSIONS,
+ dissect_t38_NULL},
+ { 2, "hdlc-fcs-OK", ASN1_NO_EXTENSIONS,
+ dissect_t38_NULL},
+ { 3, "hdlc-fcs-BAD", ASN1_NO_EXTENSIONS,
+ dissect_t38_NULL},
+ { 4, "hdlc-fcs-OK-sig-end", ASN1_NO_EXTENSIONS,
+ dissect_t38_NULL},
+ { 5, "hdlc-fcs-BAD-sig-end", ASN1_NO_EXTENSIONS,
+ dissect_t38_NULL},
+ { 6, "t4-non-ecm-data", ASN1_NO_EXTENSIONS,
+ dissect_t38_NULL},
+ { 7, "t4-non-ecm-sig-end", ASN1_NO_EXTENSIONS,
+ dissect_t38_NULL},
+ { 0, NULL, 0, NULL }
+};
+
+
+static per_choice_t Data_Field_field_type_choice[] = {
+ { 0, "hdlc-data", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 1, "hdlc-sig-end", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 2, "hdlc-fcs-OK", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 3, "hdlc-fcs-BAD", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 4, "hdlc-fcs-OK-sig-end", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 5, "hdlc-fcs-BAD-sig-end", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 6, "t4-non-ecm-data", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 7, "t4-non-ecm-sig-end", ASN1_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 8, "cm-message", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 9, "jm-message", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 10, "ci-message", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 11, "v34-rate", ASN1_NOT_EXTENSION_ROOT,
+ dissect_t38_NULL},
+ { 0, NULL, 0, NULL }
+};
+
+
+static const value_string Data_Field_field_type_vals[] = {
+ { 0, "hdlc-data" },
+ { 1, "hdlc-sig-end" },
+ { 2, "hdlc-fcs-OK" },
+ { 3, "hdlc-fcs-BAD" },
+ { 4, "hdlc-fcs-OK-sig-end" },
+ { 5, "hdlc-fcs-BAD-sig-end" },
+ { 6, "t4-non-ecm-data" },
+ { 7, "t4-non-ecm-sig-end" },
+ { 8, "cm-message" },
+ { 9, "jm-message" },
+ { 10, "ci-message" },
+ { 11, "v34-rate" },
+ { 0, NULL },
+};
+
+static int
+dissect_t38_Data_Field_field_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ if(use_pre_corrigendum_asn1_specification){
+ offset=dissect_per_choice(tvb, offset, pinfo,
+ tree, hf_t38_Data_Field_field_type, ett_t38_Data_Field_field_type,
+ Data_Field_field_type_PreCorrigendum_choice, "Field Type", &Data_Field_field_type_value);
+ }
+ else{
+ offset=dissect_per_choice(tvb, offset, pinfo,
+ tree, hf_t38_Data_Field_field_type, ett_t38_Data_Field_field_type,
+ Data_Field_field_type_choice, "Field Type", &Data_Field_field_type_value);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO) && primary_part){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
+ val_to_str(Data_Field_field_type_value,Data_Field_field_type_vals,"<unknown>"));
+ }
+
+ return offset;
+}
+
+static int
+dissect_t38_Data_Field_field_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 value_offset = 0;
+ guint32 value_len = 0;
+
+ offset=dissect_per_octet_string(tvb, offset, pinfo,
+ tree, hf_t38_Data_Field_field_data, 1, 65535,
+ &value_offset, &value_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO) && primary_part){
+ if(value_len < 8){
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s]",
+ tvb_bytes_to_str(tvb,value_offset,value_len));
+ }
+ else {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "[%s...]",
+ tvb_bytes_to_str(tvb,value_offset,7));
+ }
+ }
+ return offset;
+}
+
+static per_sequence_t Data_Field_item_sequence[] = {
+ { "field-type", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_t38_Data_Field_field_type },
+ { "field-data", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_t38_Data_Field_field_data },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_t38_Data_Field_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo,
+ tree, hf_t38_Data_Field_item, ett_t38_Data_Field_item,
+ Data_Field_item_sequence);
+ return offset;
+}
+
+static int
+dissect_t38_Data_Field(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo,
+ tree, hf_t38_Data_Field, ett_t38_Data_Field,
+ dissect_t38_Data_Field_item);
+ return offset;
+}
+
+static per_sequence_t IFPPacket_sequence[] = {
+ { "type-of-msg", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_t38_Type_of_msg },
+ { "data-field", ASN1_NO_EXTENSIONS, ASN1_OPTIONAL,
+ dissect_t38_Data_Field },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_t38_IFPPacket(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo,
+ tree, hf_t38_IFPPacket, ett_t38_IFPPacket,
+ IFPPacket_sequence);
+ return offset;
+}
+
+static int
+dissect_t38_seq_number(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_constrained_integer(tvb, offset, pinfo,
+ tree, hf_t38_seq_number, 0, 65535,
+ &seq_number, NULL, FALSE);
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Seq=%05u ",seq_number);
+ }
+ return offset;
+}
+
+static int
+dissect_t38_primary_ifp_packet(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 length;
+ primary_part = TRUE;
+
+ offset=dissect_per_length_determinant(tvb, offset, pinfo,
+ tree, hf_t38_primary_ifp_packet_length, &length);
+ offset=dissect_t38_IFPPacket(tvb, offset, pinfo, tree);
+ return offset;
+}
+
+static int
+dissect_t38_secondary_ifp_packets_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ guint32 length;
+
+ offset=dissect_per_length_determinant(tvb, offset, pinfo,
+ tree, hf_t38_secondary_ifp_packets_item_length, &length);
+ offset=dissect_t38_IFPPacket(tvb, offset, pinfo, tree);
+ return offset;
+}
+
+static int
+dissect_t38_secondary_ifp_packets(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* When the field-data is not present, we MUST offset 1 byte*/
+ if((Data_Field_field_type_value != 0) &&
+ (Data_Field_field_type_value != 6))
+ {
+ offset=offset+8;
+ }
+
+ offset=dissect_per_sequence_of(tvb, offset, pinfo,
+ tree, hf_t38_secondary_ifp_packets, ett_t38_secondary_ifp_packets,
+ dissect_t38_secondary_ifp_packets_item);
+ return offset;
+}
+
+static int
+dissect_t38_fec_npackets(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_integer(tvb, offset, pinfo,
+ tree, hf_t38_fec_npackets,
+ NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_t38_fec_data_item(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_octet_string(tvb, offset, pinfo,
+ tree, hf_t38_fec_data_item, -1, -1,
+ NULL, NULL);
+ return offset;
+}
+
+static int
+dissect_t38_fec_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence_of(tvb, offset, pinfo,
+ tree, hf_t38_fec_data, ett_t38_fec_data,
+ dissect_t38_fec_data_item);
+ return offset;
+}
+
+static per_sequence_t fec_info_sequence[] = {
+ { "fec-npackets", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_t38_fec_npackets },
+ { "fec-data", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_t38_fec_data },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_t38_fec_info(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ offset=dissect_per_sequence(tvb, offset, pinfo,
+ tree, hf_t38_fec_info, ett_t38_fec_info,
+ fec_info_sequence);
+ return offset;
+}
+
+static per_choice_t error_recovery_choice[] = {
+ { 0, "secondary-ifp-packets", ASN1_NO_EXTENSIONS,
+ dissect_t38_secondary_ifp_packets},
+ { 1, "fec-info", ASN1_NO_EXTENSIONS,
+ dissect_t38_fec_info},
+ { 0, NULL, 0, NULL }
+};
+
+static const value_string error_recovery_vals[] = {
+ { 0, "secondary-ifp-packets" },
+ { 1, "fec-info" },
+ { 0, NULL}
+};
+
+static int
+dissect_t38_error_recovery(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ primary_part = FALSE;
+
+ offset=dissect_per_choice(tvb, offset, pinfo,
+ tree, hf_t38_error_recovery, ett_t38_error_recovery,
+ error_recovery_choice, "Error recovery", NULL);
+
+ primary_part = TRUE;
+
+ return offset;
+}
+
+static per_sequence_t UDPTLPacket_sequence[] = {
+ { "seq-number", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_t38_seq_number },
+ { "primary-ifp-packet", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_t38_primary_ifp_packet },
+ { "error-recovery", ASN1_NO_EXTENSIONS, ASN1_NOT_OPTIONAL,
+ dissect_t38_error_recovery },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_t38_UDPTLPacket(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
+{
+ /* Initialize to something else than data type */
+ Data_Field_field_type_value = 1;
+
+ offset=dissect_per_sequence(tvb, offset, pinfo,
+ tree, hf_t38_UDPTLPacket, ett_t38_UDPTLPacket,
+ UDPTLPacket_sequence);
+ return offset;
+}
+
+/* Entry point for dissection */
+static void
+dissect_t38_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 octet1;
+ proto_item *it;
+ proto_tree *tr;
+ guint32 offset=0;
+
+ /*
+ * XXX - heuristic to check for misidentified packets.
+ */
+ if(dissect_possible_rtpv2_packets_as_rtp){
+ octet1 = tvb_get_guint8( tvb, offset );
+ if(RTP_VERSION(octet1) == 2){
+ call_dissector(rtp_handle,tvb,pinfo,tree);
+ return;
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)){
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "T.38");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ primary_part = TRUE;
+
+ it=proto_tree_add_protocol_format(tree, proto_t38, tvb, 0, -1,
+ "ITU-T Recommendation T.38");
+ tr=proto_item_add_subtree(it, ett_t38);
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, "UDP: UDPTLPacket ");
+ }
+
+ offset=dissect_t38_UDPTLPacket(tvb, offset, pinfo, tr);
+
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+ if(tvb_length_remaining(tvb,offset>>3)>0){
+ if(tr){
+ proto_tree_add_text(tr, tvb, offset, tvb_reported_length_remaining(tvb, offset),
+ "[MALFORMED PACKET or wrong preference settings]");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [Malformed?]");
+ }
+ }
+}
+
+static void
+dissect_t38_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *it;
+ proto_tree *tr;
+ guint32 offset=0;
+ guint16 ifp_packet_number=1;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)){
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "T.38");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ it=proto_tree_add_protocol_format(tree, proto_t38, tvb, 0, -1,
+ "ITU-T Recommendation T.38");
+ tr=proto_item_add_subtree(it, ett_t38);
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, "TCP: IFPPacket");
+ }
+
+ while(tvb_length_remaining(tvb,offset>>3)>0)
+ {
+ offset=dissect_t38_IFPPacket(tvb, offset, pinfo, tr);
+ ifp_packet_number++;
+
+ if(offset&0x07){
+ offset=(offset&0xfffffff8)+8;
+ }
+
+ if(tvb_length_remaining(tvb,offset>>3)>0){
+ if(t38_tpkt_usage == T38_TPKT_ALWAYS){
+ if(tr){
+ proto_tree_add_text(tr, tvb, offset, tvb_reported_length_remaining(tvb, offset),
+ "[MALFORMED PACKET or wrong preference settings]");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [Malformed?]");
+ }
+ break;
+ }
+ else {
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_append_fstr(pinfo->cinfo, COL_INFO, " IFPPacket#%u",ifp_packet_number);
+ }
+ }
+ }
+ }
+
+}
+
+static void
+dissect_t38_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ primary_part = TRUE;
+
+ if(t38_tpkt_usage == T38_TPKT_ALWAYS){
+ dissect_tpkt_encap(tvb,pinfo,tree,t38_tpkt_reassembly,t38_tcp_pdu_handle);
+ }
+ else if((t38_tpkt_usage == T38_TPKT_NEVER) || (is_tpkt(tvb,1) == -1)){
+ dissect_t38_tcp_pdu(tvb, pinfo, tree);
+ }
+ else {
+ dissect_tpkt_encap(tvb,pinfo,tree,t38_tpkt_reassembly,t38_tcp_pdu_handle);
+ }
+}
+
+static void
+dissect_t38(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if(pinfo->ipproto == IP_PROTO_TCP)
+ {
+ dissect_t38_tcp(tvb, pinfo, tree);
+ }
+ else if(pinfo->ipproto == IP_PROTO_UDP)
+ {
+ dissect_t38_udp(tvb, pinfo, tree);
+ }
+}
+
+/* Ethereal Protocol Registration */
+void
+proto_register_t38(void)
+{
+ static hf_register_info hf[] =
+ {
+ { &hf_t38_IFPPacket,
+ { "IFPPacket", "t38.IFPPacket", FT_NONE, BASE_NONE,
+ NULL, 0, "IFPPacket sequence", HFILL }},
+ { &hf_t38_Type_of_msg,
+ { "Type of msg", "t38.Type_of_msg_type", FT_UINT32, BASE_DEC,
+ VALS(Type_of_msg_vals), 0, "Type_of_msg choice", HFILL }},
+ { &hf_t38_t30_indicator,
+ { "T30 indicator", "t38.t30_indicator", FT_UINT32, BASE_DEC,
+ VALS(t30_indicator_vals), 0, "t30_indicator", HFILL }},
+ { &hf_t38_data,
+ { "data", "t38.t38_data", FT_UINT32, BASE_DEC,
+ VALS(data_vals), 0, "data", HFILL }},
+ { &hf_t38_Data_Field,
+ { "Data Field", "t38.Data_Field", FT_NONE, BASE_NONE,
+ NULL, 0, "Data_Field sequence of", HFILL }},
+ { &hf_t38_Data_Field_item,
+ { "Data_Field_item", "t38.Data_Field_item", FT_NONE, BASE_NONE,
+ NULL, 0, "Data_Field_item sequence", HFILL }},
+ { &hf_t38_Data_Field_field_type,
+ { "Data_Field_field_type", "t38.Data_Field_field_type", FT_UINT32, BASE_DEC,
+ VALS(Data_Field_field_type_vals), 0, "Data_Field_field_type choice", HFILL }},
+ { &hf_t38_Data_Field_field_data,
+ { "Data_Field_field_data", "t38.Data_Field_field_data", FT_BYTES, BASE_HEX,
+ NULL, 0, "Data_Field_field_data octet string", HFILL }},
+ { &hf_t38_UDPTLPacket,
+ { "UDPTLPacket", "t38.UDPTLPacket", FT_NONE, BASE_NONE,
+ NULL, 0, "UDPTLPacket sequence", HFILL }},
+ { &hf_t38_seq_number,
+ { "Sequence number", "t38.seq_number", FT_UINT32, BASE_DEC,
+ NULL, 0, "seq_number", HFILL }},
+ { &hf_t38_primary_ifp_packet,
+ { "Primary IFPPacket", "t38.primary_ifp_packet", FT_BYTES, BASE_HEX,
+ NULL, 0, "primary_ifp_packet octet string", HFILL }},
+ { &hf_t38_primary_ifp_packet_length,
+ { "primary_ifp_packet_length", "t38.primary_ifp_packet_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "primary_ifp_packet_length", HFILL }},
+ { &hf_t38_error_recovery,
+ { "Error recovery", "t38.error_recovery", FT_UINT32, BASE_DEC,
+ VALS(error_recovery_vals), 0, "error_recovery choice", HFILL }},
+ { &hf_t38_secondary_ifp_packets,
+ { "Secondary IFPPackets", "t38.secondary_ifp_packets", FT_NONE, BASE_NONE,
+ NULL, 0, "secondary_ifp_packets sequence of", HFILL }},
+ { &hf_t38_secondary_ifp_packets_item,
+ { "Secondary IFPPackets item", "t38.secondary_ifp_packets_item", FT_BYTES, BASE_HEX,
+ NULL, 0, "secondary_ifp_packets_item octet string", HFILL }},
+ { &hf_t38_secondary_ifp_packets_item_length,
+ { "secondary_ifp_packets_item_length", "t38.secondary_ifp_packets_item_length", FT_UINT32, BASE_DEC,
+ NULL, 0, "secondary_ifp_packets_item_length", HFILL }},
+ { &hf_t38_fec_info,
+ { "Fec info", "t38.fec_info", FT_NONE, BASE_NONE,
+ NULL, 0, "fec_info sequence", HFILL }},
+ { &hf_t38_fec_npackets,
+ { "Fec npackets", "h245.fec_npackets", FT_INT32, BASE_DEC,
+ NULL, 0, "fec_npackets value", HFILL }},
+ { &hf_t38_fec_data,
+ { "Fec data", "t38.fec_data", FT_NONE, BASE_NONE,
+ NULL, 0, "fec_data sequence of", HFILL }},
+ { &hf_t38_fec_data_item,
+ { "t38_fec_data_item", "t38.t38_fec_data_item", FT_BYTES, BASE_HEX,
+ NULL, 0, "t38_fec_data_item octet string", HFILL }},
+ };
+
+ static gint *ett[] =
+ {
+ &ett_t38,
+ &ett_t38_IFPPacket,
+ &ett_t38_Type_of_msg,
+ &ett_t38_t30_indicator,
+ &ett_t38_data,
+ &ett_t38_Data_Field,
+ &ett_t38_Data_Field_item,
+ &ett_t38_Data_Field_field_type,
+ &ett_t38_UDPTLPacket,
+ &ett_t38_error_recovery,
+ &ett_t38_secondary_ifp_packets,
+ &ett_t38_fec_info,
+ &ett_t38_fec_data,
+ };
+ module_t *t38_module;
+
+ proto_t38 = proto_register_protocol("T38", "T38", "t38");
+ proto_register_field_array(proto_t38, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("t38", dissect_t38, proto_t38);
+
+ t38_module = prefs_register_protocol(proto_t38, proto_reg_handoff_t38);
+ prefs_register_bool_preference(t38_module, "use_pre_corrigendum_asn1_specification",
+ "Use the Pre-Corrigendum ASN.1 specification",
+ "Whether the T.38 dissector should decode using the Pre-Corrigendum T.38 "
+ "ASN.1 specification (1998).",
+ &use_pre_corrigendum_asn1_specification);
+ prefs_register_bool_preference(t38_module, "dissect_possible_rtpv2_packets_as_rtp",
+ "Dissect possible RTP version 2 packets with RTP dissector",
+ "Whether a UDP packet that looks like RTP version 2 packet will "
+ "be dissected as RTP packet or T.38 packet. If enabled there is a risk that T.38 UDPTL "
+ "packets with sequence number higher than 32767 may be dissected as RTP.",
+ &dissect_possible_rtpv2_packets_as_rtp);
+ prefs_register_uint_preference(t38_module, "tcp.port",
+ "T.38 TCP Port",
+ "Set the TCP port for T.38 messages",
+ 10, &global_t38_tcp_port);
+ prefs_register_uint_preference(t38_module, "udp.port",
+ "T.38 UDP Port",
+ "Set the UDP port for T.38 messages",
+ 10, &global_t38_udp_port);
+ prefs_register_bool_preference(t38_module, "reassembly",
+ "Reassemble T.38 PDUs over TPKT over TCP",
+ "Whether the dissector should reassemble T.38 PDUs spanning multiple TCP segments "
+ "when TPKT is used over TCP",
+ &t38_tpkt_reassembly);
+ prefs_register_enum_preference(t38_module, "tpkt_usage",
+ "TPKT used over TCP",
+ "Whether T.38 is used with TPKT for TCP",
+ (gint *)&t38_tpkt_usage,t38_tpkt_options,FALSE);
+}
+
+void
+proto_reg_handoff_t38(void)
+{
+ static int t38_prefs_initialized = FALSE;
+
+ if (!t38_prefs_initialized) {
+ t38_udp_handle=create_dissector_handle(dissect_t38_udp, proto_t38);
+ t38_tcp_handle=create_dissector_handle(dissect_t38_tcp, proto_t38);
+ t38_tcp_pdu_handle=create_dissector_handle(dissect_t38_tcp_pdu, proto_t38);
+ t38_prefs_initialized = TRUE;
+ }
+ else {
+ dissector_delete("tcp.port", tcp_port, t38_tcp_handle);
+ dissector_delete("udp.port", udp_port, t38_udp_handle);
+ }
+ tcp_port = global_t38_tcp_port;
+ udp_port = global_t38_udp_port;
+
+ dissector_add("tcp.port", tcp_port, t38_tcp_handle);
+ dissector_add("udp.port", udp_port, t38_udp_handle);
+
+ rtp_handle = find_dissector("rtp");
+}
diff --git a/epan/dissectors/packet-tacacs.c b/epan/dissectors/packet-tacacs.c
new file mode 100644
index 0000000000..8968beb5a5
--- /dev/null
+++ b/epan/dissectors/packet-tacacs.c
@@ -0,0 +1,1137 @@
+/* packet-tacacs.c
+ * Routines for cisco tacacs/xtacacs/tacacs+ packet dissection
+ * Copyright 2001, Paul Ionescu <paul@acorp.ro>
+ *
+ * Full Tacacs+ parsing with decryption by
+ * Emanuele Caratti <wiz@iol.it>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from old packet-tacacs.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+/* rfc-1492 for tacacs and xtacacs
+ * draft-grant-tacacs-02.txt for tacacs+ (tacplus)
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+#include "prefs.h"
+#include "crypt-md5.h"
+#include "packet-tacacs.h"
+
+static void md5_xor( guint8 *data, char *key, int data_len, guint8 *session_id, guint8 version, guint8 seq_no );
+
+static int proto_tacacs = -1;
+static int hf_tacacs_version = -1;
+static int hf_tacacs_type = -1;
+static int hf_tacacs_nonce = -1;
+static int hf_tacacs_userlen = -1;
+static int hf_tacacs_passlen = -1;
+static int hf_tacacs_response = -1;
+static int hf_tacacs_reason = -1;
+static int hf_tacacs_result1 = -1;
+static int hf_tacacs_destaddr = -1;
+static int hf_tacacs_destport = -1;
+static int hf_tacacs_line = -1;
+static int hf_tacacs_result2 = -1;
+static int hf_tacacs_result3 = -1;
+
+static gint ett_tacacs = -1;
+
+static char *tacplus_opt_key;
+static GSList *tacplus_keys = NULL;
+
+#define VERSION_TACACS 0x00
+#define VERSION_XTACACS 0x80
+
+static const value_string tacacs_version_vals[] = {
+ { VERSION_TACACS, "TACACS" },
+ { VERSION_XTACACS, "XTACACS" },
+ { 0, NULL }
+};
+
+#define TACACS_LOGIN 1
+#define TACACS_RESPONSE 2
+#define TACACS_CHANGE 3
+#define TACACS_FOLLOW 4
+#define TACACS_CONNECT 5
+#define TACACS_SUPERUSER 6
+#define TACACS_LOGOUT 7
+#define TACACS_RELOAD 8
+#define TACACS_SLIP_ON 9
+#define TACACS_SLIP_OFF 10
+#define TACACS_SLIP_ADDR 11
+static const value_string tacacs_type_vals[] = {
+ { TACACS_LOGIN, "Login" },
+ { TACACS_RESPONSE, "Response" },
+ { TACACS_CHANGE, "Change" },
+ { TACACS_FOLLOW, "Follow" },
+ { TACACS_CONNECT, "Connect" },
+ { TACACS_SUPERUSER, "Superuser" },
+ { TACACS_LOGOUT, "Logout" },
+ { TACACS_RELOAD, "Reload" },
+ { TACACS_SLIP_ON, "SLIP on" },
+ { TACACS_SLIP_OFF, "SLIP off" },
+ { TACACS_SLIP_ADDR, "SLIP Addr" },
+ { 0, NULL }};
+
+static const value_string tacacs_reason_vals[] = {
+ { 0 , "none" },
+ { 1 , "expiring" },
+ { 2 , "password" },
+ { 3 , "denied" },
+ { 4 , "quit" },
+ { 5 , "idle" },
+ { 6 , "drop" },
+ { 7 , "bad" },
+ { 0 , NULL }
+};
+
+static const value_string tacacs_resp_vals[] = {
+ { 0 , "this is not a response" },
+ { 1 , "accepted" },
+ { 2 , "rejected" },
+ { 0 , NULL }
+};
+
+#define UDP_PORT_TACACS 49
+#define TCP_PORT_TACACS 49
+
+static void
+dissect_tacacs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *tacacs_tree;
+ proto_item *ti;
+ guint8 txt_buff[255+1],version,type,userlen,passlen;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TACACS");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ version = tvb_get_guint8(tvb,0);
+ if (version != 0) {
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "XTACACS");
+ }
+
+ type = tvb_get_guint8(tvb,1);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(type, tacacs_type_vals, "Unknown (0x%02x)"));
+
+ if (tree)
+ {
+ ti = proto_tree_add_protocol_format(tree, proto_tacacs,
+ tvb, 0, -1, version==0?"TACACS":"XTACACS");
+ tacacs_tree = proto_item_add_subtree(ti, ett_tacacs);
+
+ proto_tree_add_uint(tacacs_tree, hf_tacacs_version, tvb, 0, 1,
+ version);
+ proto_tree_add_uint(tacacs_tree, hf_tacacs_type, tvb, 1, 1,
+ type);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_nonce, tvb, 2, 2,
+ FALSE);
+
+ if (version==0)
+ {
+ if (type!=TACACS_RESPONSE)
+ {
+ userlen=tvb_get_guint8(tvb,4);
+ proto_tree_add_uint(tacacs_tree, hf_tacacs_userlen, tvb, 4, 1,
+ userlen);
+ passlen=tvb_get_guint8(tvb,5);
+ proto_tree_add_uint(tacacs_tree, hf_tacacs_passlen, tvb, 5, 1,
+ passlen);
+ tvb_get_nstringz0(tvb,6,userlen+1,txt_buff);
+ proto_tree_add_text(tacacs_tree, tvb, 6, userlen, "Username: %s",txt_buff);
+ tvb_get_nstringz0(tvb,6+userlen,passlen+1,txt_buff);
+ proto_tree_add_text(tacacs_tree, tvb, 6+userlen, passlen, "Password: %s",txt_buff);
+ }
+ else
+ {
+ proto_tree_add_item(tacacs_tree, hf_tacacs_response, tvb, 4, 1,
+ FALSE);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_reason, tvb, 5, 1,
+ FALSE);
+ }
+ }
+ else
+ {
+ userlen=tvb_get_guint8(tvb,4);
+ proto_tree_add_uint(tacacs_tree, hf_tacacs_userlen, tvb, 4, 1,
+ userlen);
+ passlen=tvb_get_guint8(tvb,5);
+ proto_tree_add_uint(tacacs_tree, hf_tacacs_passlen, tvb, 5, 1,
+ passlen);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_response, tvb, 6, 1,
+ FALSE);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_reason, tvb, 7, 1,
+ FALSE);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_result1, tvb, 8, 4,
+ FALSE);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_destaddr, tvb, 12, 4,
+ FALSE);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_destport, tvb, 16, 2,
+ FALSE);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_line, tvb, 18, 2,
+ FALSE);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_result2, tvb, 20, 4,
+ FALSE);
+ proto_tree_add_item(tacacs_tree, hf_tacacs_result3, tvb, 24, 2,
+ FALSE);
+ if (type!=TACACS_RESPONSE)
+ {
+ tvb_get_nstringz0(tvb,26,userlen+1,txt_buff);
+ proto_tree_add_text(tacacs_tree, tvb, 26, userlen, "Username: %s",txt_buff);
+ tvb_get_nstringz0(tvb,26+userlen,passlen+1,txt_buff);
+ proto_tree_add_text(tacacs_tree, tvb, 26+userlen, passlen, "Password; %s",txt_buff);
+ }
+ }
+ }
+}
+
+void
+proto_register_tacacs(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tacacs_version,
+ { "Version", "tacacs.version",
+ FT_UINT8, BASE_HEX, VALS(tacacs_version_vals), 0x0,
+ "Version", HFILL }},
+ { &hf_tacacs_type,
+ { "Type", "tacacs.type",
+ FT_UINT8, BASE_DEC, VALS(tacacs_type_vals), 0x0,
+ "Type", HFILL }},
+ { &hf_tacacs_nonce,
+ { "Nonce", "tacacs.nonce",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Nonce", HFILL }},
+ { &hf_tacacs_userlen,
+ { "Username length", "tacacs.userlen",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Username length", HFILL }},
+ { &hf_tacacs_passlen,
+ { "Password length", "tacacs.passlen",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Password length", HFILL }},
+ { &hf_tacacs_response,
+ { "Response", "tacacs.response",
+ FT_UINT8, BASE_DEC, VALS(tacacs_resp_vals), 0x0,
+ "Response", HFILL }},
+ { &hf_tacacs_reason,
+ { "Reason", "tacacs.reason",
+ FT_UINT8, BASE_DEC, VALS(tacacs_reason_vals), 0x0,
+ "Reason", HFILL }},
+ { &hf_tacacs_result1,
+ { "Result 1", "tacacs.result1",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Result 1", HFILL }},
+ { &hf_tacacs_destaddr,
+ { "Destination address", "tacacs.destaddr",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Destination address", HFILL }},
+ { &hf_tacacs_destport,
+ { "Destination port", "tacacs.destport",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Destination port", HFILL }},
+ { &hf_tacacs_line,
+ { "Line", "tacacs.line",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Line", HFILL }},
+ { &hf_tacacs_result2,
+ { "Result 2", "tacacs.result2",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Result 2", HFILL }},
+ { &hf_tacacs_result3,
+ { "Result 3", "tacacs.result3",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Result 3", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_tacacs,
+ };
+ proto_tacacs = proto_register_protocol("TACACS", "TACACS", "tacacs");
+ proto_register_field_array(proto_tacacs, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_tacacs(void)
+{
+ dissector_handle_t tacacs_handle;
+
+ tacacs_handle = create_dissector_handle(dissect_tacacs, proto_tacacs);
+ dissector_add("udp.port", UDP_PORT_TACACS, tacacs_handle);
+}
+
+static int proto_tacplus = -1;
+static int hf_tacplus_response = -1;
+static int hf_tacplus_request = -1;
+static int hf_tacplus_majvers = -1;
+static int hf_tacplus_minvers = -1;
+static int hf_tacplus_type = -1;
+static int hf_tacplus_seqno = -1;
+static int hf_tacplus_flags = -1;
+static int hf_tacplus_flags_payload_type = -1;
+static int hf_tacplus_flags_connection_type = -1;
+static int hf_tacplus_acct_flags = -1;
+static int hf_tacplus_session_id = -1;
+static int hf_tacplus_packet_len = -1;
+
+static gint ett_tacplus = -1;
+static gint ett_tacplus_body = -1;
+static gint ett_tacplus_body_chap = -1;
+static gint ett_tacplus_flags = -1;
+static gint ett_tacplus_acct_flags = -1;
+
+typedef struct _tacplus_key_entry {
+ address *s; /* Server address */
+ address *c; /* client address */
+ char *k; /* Key */
+} tacplus_key_entry;
+
+static gint
+tacplus_decrypted_tvb_setup( tvbuff_t *tvb, tvbuff_t **dst_tvb, packet_info *pinfo, guint32 len, guint8 version, char *key )
+{
+ guint8 *buff;
+ guint8 session_id[4];
+
+ /* TODO Check the possibility to use pinfo->decrypted_data */
+/* session_id is in NETWORK Byte Order, and is used as byte array in the md5_xor */
+
+ tvb_memcpy(tvb, (guint8*)session_id, 4,4);
+
+ buff = tvb_memdup(tvb, TAC_PLUS_HDR_SIZE, len);
+
+
+ md5_xor( buff, key, len, session_id,version, tvb_get_guint8(tvb,2) );
+
+ /* Allocate a new tvbuff, referring to the decrypted data. */
+ *dst_tvb = tvb_new_real_data( buff, len, len );
+
+ /* Arrange that the allocated packet data copy be freed when the
+ tvbuff is freed. */
+ tvb_set_free_cb( *dst_tvb, g_free );
+
+ /* Add the tvbuff to the list of tvbuffs to which the tvbuff we
+ were handed refers, so it'll get cleaned up when that tvbuff
+ is cleaned up. */
+ tvb_set_child_real_data_tvbuff( tvb, *dst_tvb );
+
+ /* Add the decrypted data to the data source list. */
+ add_new_data_source(pinfo, *dst_tvb, "TACACS+ Decrypted");
+
+ return 0;
+}
+static void
+dissect_tacplus_args_list( tvbuff_t *tvb, proto_tree *tree, int data_off, int len_off, int arg_cnt )
+{
+ int i;
+ guint8 buff[257];
+ for(i=0;i<arg_cnt;i++){
+ int len=tvb_get_guint8(tvb,len_off+i);
+ proto_tree_add_text( tree, tvb, len_off+i, 1, "Arg[%d] length: %d", i, len );
+ tvb_get_nstringz0(tvb, data_off, len+1, buff);
+ proto_tree_add_text( tree, tvb, data_off, len, "Arg[%d] value: %s", i, buff );
+ data_off+=len;
+ }
+}
+
+
+static int
+proto_tree_add_tacplus_common_fields( tvbuff_t *tvb, proto_tree *tree, int offset, int var_off )
+{
+ int val;
+ guint8 buff[257];
+ /* priv_lvl */
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "Privilege Level: %d", tvb_get_guint8(tvb,offset) );
+ offset++;
+
+ /* authen_type */
+ val=tvb_get_guint8(tvb,offset);
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "Authentication type: %s",
+ val_to_str( val, tacplus_authen_type_vals, "Unknown Packet" ) );
+ offset++;
+
+ /* service */
+ val=tvb_get_guint8(tvb,offset);
+ proto_tree_add_text( tree, tvb, offset, 1,
+ "Service: %s",
+ val_to_str( val, tacplus_authen_service_vals, "Unknown Packet" ) );
+ offset++;
+
+ /* user_len && user */
+ val=tvb_get_guint8(tvb,offset);
+ proto_tree_add_text( tree, tvb, offset, 1, "User len: %d", val );
+ if( val ){
+ tvb_get_nstringz0(tvb, var_off, val+1, buff);
+ proto_tree_add_text( tree, tvb, var_off, val, "User: %s", buff );
+ var_off+=val;
+ }
+ offset++;
+
+
+ /* port_len && port */
+ val=tvb_get_guint8(tvb,offset);
+ proto_tree_add_text( tree, tvb, offset, 1, "Port len: %d", val );
+ if( val ){
+ tvb_get_nstringz0(tvb, var_off, val+1, buff);
+ proto_tree_add_text( tree, tvb, var_off, val, "Port: %s", buff );
+ var_off+=val;
+ }
+ offset++;
+
+ /* rem_addr_len && rem_addr */
+ val=tvb_get_guint8(tvb,offset);
+ proto_tree_add_text( tree, tvb, offset, 1, "Remaddr len: %d", val );
+ if( val ){
+ tvb_get_nstringz0(tvb, var_off, val+1, buff);
+ proto_tree_add_text( tree, tvb, var_off, val, "Remote Address: %s", buff );
+ var_off+=val;
+ }
+ return var_off;
+}
+
+static void
+dissect_tacplus_body_authen_req_login( tvbuff_t* tvb, proto_tree *tree, int var_off )
+{
+ guint8 buff[257];
+ guint8 val;
+ val=tvb_get_guint8( tvb, AUTHEN_S_DATA_LEN_OFF );
+
+ switch ( tvb_get_guint8(tvb, AUTHEN_S_AUTHEN_TYPE_OFF ) ) { /* authen_type */
+
+ case TAC_PLUS_AUTHEN_TYPE_ASCII:
+ proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "Data: %d (not used)", val );
+ if( val )
+ proto_tree_add_text( tree, tvb, var_off, val, "Data" );
+ break;
+
+ case TAC_PLUS_AUTHEN_TYPE_PAP:
+ proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "Password Length %d", val );
+ if( val ) {
+ tvb_get_nstringz0( tvb, var_off, val+1, buff );
+ proto_tree_add_text( tree, tvb, var_off, val, "Password: %s", buff );
+ }
+ break;
+
+ case TAC_PLUS_AUTHEN_TYPE_CHAP:
+ proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "CHAP Data Length %d", val );
+ if( val ) {
+ proto_item *pi;
+ proto_tree *pt;
+ guint8 chal_len=val-(1+16); /* Response field alwayes 16 octets */
+ pi = proto_tree_add_text(tree, tvb, var_off, val, "CHAP Data" );
+ pt = proto_item_add_subtree( pi, ett_tacplus_body_chap );
+ val= tvb_get_guint8( tvb, var_off );
+ proto_tree_add_text( pt, tvb, var_off, 1, "ID: %d", val );
+ var_off++;
+ tvb_get_nstringz0( tvb, var_off, chal_len+1, buff );
+ proto_tree_add_text( pt, tvb, var_off, chal_len, "Challenge: %s", buff );
+ var_off+=chal_len;
+ tvb_get_nstringz0( tvb, var_off, 16+1, buff );
+ proto_tree_add_text( pt, tvb, var_off, 16 , "Response: %s", buff );
+ }
+ break;
+ case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
+ proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "MSCHAP Data Length %d", val );
+ if( val ) {
+ proto_item *pi;
+ proto_tree *pt;
+ guint8 chal_len=val-(1+49); /* Response field alwayes 49 octets */
+ pi = proto_tree_add_text(tree, tvb, var_off, val, "MSCHAP Data" );
+ pt = proto_item_add_subtree( pi, ett_tacplus_body_chap );
+ val= tvb_get_guint8( tvb, var_off );
+ proto_tree_add_text( pt, tvb, var_off, 1, "ID: %d", val );
+ var_off++;
+ tvb_get_nstringz0( tvb, var_off, chal_len+1, buff );
+ proto_tree_add_text( pt, tvb, var_off, chal_len, "Challenge: %s", buff );
+ var_off+=chal_len;
+ tvb_get_nstringz0( tvb, var_off, 49+1, buff );
+ proto_tree_add_text( pt, tvb, var_off, 49 , "Response: %s", buff );
+ }
+ break;
+ case TAC_PLUS_AUTHEN_TYPE_ARAP:
+ proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "ARAP Data Length %d", val );
+ if( val ) {
+ proto_item *pi;
+ proto_tree *pt;
+ pi = proto_tree_add_text(tree, tvb, var_off, val, "ARAP Data" );
+ pt = proto_item_add_subtree( pi, ett_tacplus_body_chap );
+
+ tvb_get_nstringz0( tvb, var_off, 8+1, buff );
+ proto_tree_add_text( pt, tvb, var_off, 8, "Nas Challenge: %s", buff );
+ var_off+=8;
+ tvb_get_nstringz0( tvb, var_off, 8+1, buff );
+ proto_tree_add_text( pt, tvb, var_off, 8, "Remote Challenge: %s", buff );
+ var_off+=8;
+ tvb_get_nstringz0( tvb, var_off, 8+1, buff );
+ proto_tree_add_text( pt, tvb, var_off, 8, "Remote Response: %s", buff );
+ var_off+=8;
+ }
+ break;
+
+ default: /* Should not be reached */
+ proto_tree_add_text( tree, tvb, AUTHEN_S_DATA_LEN_OFF, 1, "Data: %d", val );
+ if( val ){
+ proto_tree_add_text( tree, tvb, var_off, val, "Data" );
+ }
+ }
+}
+
+static void
+dissect_tacplus_body_authen_req( tvbuff_t* tvb, proto_tree *tree )
+{
+ guint8 val;
+ int var_off=AUTHEN_S_VARDATA_OFF;
+
+ /* Action */
+ val=tvb_get_guint8( tvb, AUTHEN_S_ACTION_OFF );
+ proto_tree_add_text( tree, tvb,
+ AUTHEN_S_ACTION_OFF, 1,
+ "Action: %s",
+ val_to_str( val, tacplus_authen_action_vals, "Unknown Packet" ) );
+
+ var_off=proto_tree_add_tacplus_common_fields( tvb, tree , AUTHEN_S_PRIV_LVL_OFF, AUTHEN_S_VARDATA_OFF );
+
+ switch( val ) {
+ case TAC_PLUS_AUTHEN_LOGIN:
+ dissect_tacplus_body_authen_req_login( tvb, tree, var_off );
+ break;
+ case TAC_PLUS_AUTHEN_SENDAUTH:
+ break;
+ }
+}
+
+static void
+dissect_tacplus_body_authen_req_cont( tvbuff_t *tvb, proto_tree *tree )
+{
+ int val;
+ int var_off=AUTHEN_C_VARDATA_OFF;
+ guint8 *buff=NULL;
+
+ val=tvb_get_guint8( tvb, AUTHEN_C_FLAGS_OFF );
+ proto_tree_add_text( tree, tvb,
+ AUTHEN_R_FLAGS_OFF, 1, "Flags: 0x%02x %s",
+ val,
+ (val&TAC_PLUS_CONTINUE_FLAG_ABORT?"(Abort)":"") );
+
+
+ val=tvb_get_ntohs( tvb, AUTHEN_C_USER_LEN_OFF );
+ proto_tree_add_text( tree, tvb, AUTHEN_C_USER_LEN_OFF, 2 , "User length: %d", val );
+ if( val ){
+ buff=tvb_get_string( tvb, var_off, val );
+ proto_tree_add_text( tree, tvb, var_off, val, "User: %s", buff );
+ var_off+=val;
+ g_free(buff);
+ }
+
+ val=tvb_get_ntohs( tvb, AUTHEN_C_DATA_LEN_OFF );
+ proto_tree_add_text( tree, tvb, AUTHEN_C_DATA_LEN_OFF, 2 ,
+ "Data length: %d", val );
+ if( val ){
+ proto_tree_add_text( tree, tvb, var_off, val, "Data" );
+ }
+
+}
+
+/* Server REPLY */
+static void
+dissect_tacplus_body_authen_rep( tvbuff_t *tvb, proto_tree *tree )
+{
+ int val;
+ int var_off=AUTHEN_R_VARDATA_OFF;
+ guint8 *buff=NULL;
+
+ val=tvb_get_guint8( tvb, AUTHEN_R_STATUS_OFF );
+ proto_tree_add_text(tree, tvb,
+ AUTHEN_R_STATUS_OFF, 1, "Status: 0x%01x (%s)", val,
+ val_to_str( val, tacplus_reply_status_vals, "Unknown Packet" ) );
+
+ val=tvb_get_guint8( tvb, AUTHEN_R_FLAGS_OFF );
+ proto_tree_add_text(tree, tvb,
+ AUTHEN_R_FLAGS_OFF, 1, "Flags: 0x%02x %s",
+ val, (val&TAC_PLUS_REPLY_FLAG_NOECHO?"(NoEcho)":"") );
+
+
+ val=tvb_get_ntohs(tvb, AUTHEN_R_SRV_MSG_LEN_OFF );
+ proto_tree_add_text( tree, tvb, AUTHEN_R_SRV_MSG_LEN_OFF, 2 ,
+ "Server message length: %d", val );
+ if( val ) {
+ buff=tvb_get_string(tvb, var_off, val );
+ proto_tree_add_text(tree, tvb, var_off, val, "Server message: %s", buff );
+ var_off+=val;
+ g_free(buff);
+ }
+
+ val=tvb_get_ntohs(tvb, AUTHEN_R_DATA_LEN_OFF );
+ proto_tree_add_text( tree, tvb, AUTHEN_R_DATA_LEN_OFF, 2 ,
+ "Data length: %d", val );
+ if( val ){
+ proto_tree_add_text(tree, tvb, var_off, val, "Data" );
+ }
+}
+
+static void
+dissect_tacplus_body_author_req( tvbuff_t* tvb, proto_tree *tree )
+{
+ int val;
+ int var_off;
+
+ val=tvb_get_guint8( tvb, AUTHOR_Q_AUTH_METH_OFF ) ;
+ proto_tree_add_text( tree, tvb, AUTHOR_Q_AUTH_METH_OFF, 1,
+ "Auth Method: %s", val_to_str( val, tacplus_authen_method, "Unknown Authen Method" ) );
+
+ val=tvb_get_guint8( tvb, AUTHOR_Q_ARGC_OFF );
+ var_off=proto_tree_add_tacplus_common_fields( tvb, tree ,
+ AUTHOR_Q_PRIV_LVL_OFF,
+ AUTHOR_Q_VARDATA_OFF + val );
+
+ proto_tree_add_text( tree, tvb, AUTHOR_Q_ARGC_OFF, 1, "Arg count: %d", val );
+
+/* var_off points after rem_addr */
+
+ dissect_tacplus_args_list( tvb, tree, var_off, AUTHOR_Q_VARDATA_OFF, val );
+}
+
+static void
+dissect_tacplus_body_author_rep( tvbuff_t* tvb, proto_tree *tree )
+{
+ int offset=AUTHOR_R_VARDATA_OFF;
+ int val=tvb_get_guint8( tvb, AUTHOR_R_STATUS_OFF ) ;
+
+
+ proto_tree_add_text( tree, tvb, AUTHOR_R_STATUS_OFF , 1,
+ "Auth Status: 0x%01x (%s)", val,
+ val_to_str( val, tacplus_author_status, "Unknown Authorization Status" ));
+
+ val=tvb_get_ntohs( tvb, AUTHOR_R_SRV_MSG_LEN_OFF );
+ offset+=val;
+ proto_tree_add_text( tree, tvb, AUTHOR_R_SRV_MSG_LEN_OFF, 2, "Server Msg length: %d", val );
+
+ val=tvb_get_ntohs( tvb, AUTHOR_R_DATA_LEN_OFF );
+ offset+=val;
+ proto_tree_add_text( tree, tvb, AUTHOR_R_DATA_LEN_OFF, 2, "Data length: %d", val );
+
+ val=tvb_get_guint8( tvb, AUTHOR_R_ARGC_OFF);
+ offset+=val;
+ proto_tree_add_text( tree, tvb, AUTHOR_R_ARGC_OFF, 1, "Arg count: %d", val );
+
+ dissect_tacplus_args_list( tvb, tree, offset, AUTHOR_R_VARDATA_OFF, val );
+}
+
+static void
+dissect_tacplus_body_acct_req( tvbuff_t* tvb, proto_tree *tree )
+{
+ int val, var_off;
+
+ proto_item *tf;
+ proto_tree *flags_tree;
+
+ val=tvb_get_guint8( tvb, ACCT_Q_FLAGS_OFF );
+ tf = proto_tree_add_uint( tree, hf_tacplus_acct_flags, tvb, ACCT_Q_FLAGS_OFF, 1, val );
+
+ flags_tree = proto_item_add_subtree( tf, ett_tacplus_acct_flags );
+ proto_tree_add_text( flags_tree, tvb, ACCT_Q_FLAGS_OFF, 1, "%s",
+ decode_boolean_bitfield( val, TAC_PLUS_ACCT_FLAG_MORE, 8,
+ "More: Set", "More: Not set" ) );
+ proto_tree_add_text( flags_tree, tvb, ACCT_Q_FLAGS_OFF, 1, "%s",
+ decode_boolean_bitfield( val, TAC_PLUS_ACCT_FLAG_START, 8,
+ "Start: Set", "Start: Not set" ) );
+ proto_tree_add_text( flags_tree, tvb, ACCT_Q_FLAGS_OFF, 1, "%s",
+ decode_boolean_bitfield( val, TAC_PLUS_ACCT_FLAG_STOP, 8,
+ "Stop: Set", "Stop: Not set" ) );
+ proto_tree_add_text( flags_tree, tvb, ACCT_Q_FLAGS_OFF, 1, "%s",
+ decode_boolean_bitfield( val, TAC_PLUS_ACCT_FLAG_WATCHDOG, 8,
+ "Watchdog: Set", "Watchdog: Not set" ) );
+
+ val=tvb_get_guint8( tvb, ACCT_Q_METHOD_OFF );
+ proto_tree_add_text( tree, tvb, ACCT_Q_METHOD_OFF, 1,
+ "Authen Method: 0x%01x (%s)",
+ val, val_to_str( val, tacplus_authen_method, "Unknown Authen Method" ) );
+
+ val=tvb_get_guint8( tvb, ACCT_Q_ARG_CNT_OFF );
+
+ /* authen_type */
+ var_off=proto_tree_add_tacplus_common_fields( tvb, tree ,
+ ACCT_Q_PRIV_LVL_OFF,
+ ACCT_Q_VARDATA_OFF+val
+ );
+
+ proto_tree_add_text( tree, tvb, ACCT_Q_ARG_CNT_OFF, 1,
+ "Arg Cnt: %d", val );
+
+ dissect_tacplus_args_list( tvb, tree, var_off, ACCT_Q_VARDATA_OFF, val );
+
+
+}
+
+static void
+dissect_tacplus_body_acct_rep( tvbuff_t* tvb, proto_tree *tree )
+{
+ int val, var_off=ACCT_Q_VARDATA_OFF;
+
+ guint8 *buff=NULL;
+
+ /* Status */
+ val=tvb_get_guint8( tvb, ACCT_R_STATUS_OFF );
+ proto_tree_add_text( tree, tvb, ACCT_R_STATUS_OFF, 1, "Status: 0x%02x (%s)", val,
+ val_to_str( val, tacplus_acct_status, "Bogus status..") );
+
+ /* Server Message */
+ val=tvb_get_ntohs( tvb, ACCT_R_SRV_MSG_LEN_OFF );
+ proto_tree_add_text( tree, tvb, ACCT_R_SRV_MSG_LEN_OFF, 2 ,
+ "Server message length: %d", val );
+ if( val ) {
+ buff=tvb_get_string( tvb, var_off, val );
+ proto_tree_add_text( tree, tvb, var_off,
+ val, "Server message: %s", buff );
+ var_off+=val;
+ g_free(buff);
+ }
+
+ /* Data */
+ val=tvb_get_ntohs( tvb, ACCT_R_DATA_LEN_OFF );
+ proto_tree_add_text( tree, tvb, ACCT_R_DATA_LEN_OFF, 2 ,
+ "Data length: %d", val );
+ if( val ) {
+ buff= tvb_get_string( tvb, var_off, val );
+ proto_tree_add_text( tree, tvb, var_off,
+ val, "Data: %s", buff );
+ g_free(buff);
+ }
+}
+
+
+
+static void
+dissect_tacplus_body(tvbuff_t * hdr_tvb, tvbuff_t * tvb, proto_tree * tree )
+{
+ int type = tvb_get_guint8( hdr_tvb, H_TYPE_OFF );
+ int seq_no = tvb_get_guint8( hdr_tvb, H_SEQ_NO_OFF );
+
+ switch (type) {
+ case TAC_PLUS_AUTHEN:
+ if ( seq_no & 0x01) {
+ if ( seq_no == 1 )
+ dissect_tacplus_body_authen_req( tvb, tree );
+ else
+ dissect_tacplus_body_authen_req_cont( tvb, tree );
+ } else {
+ dissect_tacplus_body_authen_rep( tvb, tree );
+ }
+ return;
+ break;
+ case TAC_PLUS_AUTHOR:
+ if ( seq_no & 0x01)
+ dissect_tacplus_body_author_req( tvb, tree );
+ else
+ dissect_tacplus_body_author_rep( tvb, tree );
+ return;
+ break;
+ case TAC_PLUS_ACCT:
+ if ( seq_no & 0x01)
+ dissect_tacplus_body_acct_req( tvb, tree );
+ else
+ dissect_tacplus_body_acct_rep( tvb, tree );
+ return;
+ break;
+ }
+ proto_tree_add_text( tree, tvb, 0, tvb_length( tvb ), "Bogus..");
+}
+
+#ifdef DEB_TACPLUS
+static void
+tacplus_print_key_entry( gpointer data, gpointer user_data )
+{
+ tacplus_key_entry *tacplus_data=(tacplus_key_entry *)data;
+ if( user_data ) {
+ printf("%s:%s=%s\n", address_to_str( tacplus_data->s ),
+ address_to_str( tacplus_data->c ), tacplus_data->k );
+ } else {
+ printf("%s:%s\n", address_to_str( tacplus_data->s ),
+ address_to_str( tacplus_data->c ) );
+ }
+}
+#endif
+static int
+cmp_conv_address( gconstpointer p1, gconstpointer p2 )
+{
+ tacplus_key_entry *a1=(tacplus_key_entry*)p1;
+ tacplus_key_entry *a2=(tacplus_key_entry*)p2;
+ gint32 ret;
+ /*
+ printf("p1=>");
+ tacplus_print_key_entry( p1, NULL );
+ printf("p2=>");
+ tacplus_print_key_entry( p2, NULL );
+ */
+ ret=CMP_ADDRESS( a1->s, a2->s );
+ if( !ret ) {
+ ret=CMP_ADDRESS( a1->c, a2->c );
+ /*
+ if(ret)
+ printf("No Client found!"); */
+ } else {
+ /* printf("No Server found!"); */
+ }
+ return ret;
+}
+
+static char*
+find_key( address *srv, address *cln )
+{
+ tacplus_key_entry data;
+ GSList *match;
+
+ data.s=srv;
+ data.c=cln;
+/* printf("Looking for: ");
+ tacplus_print_key_entry( (gconstpointer)&data, NULL ); */
+ match=g_slist_find_custom( tacplus_keys, (gpointer)&data, cmp_conv_address );
+/* printf("Finished (%p)\n", match); */
+ if( match )
+ return ((tacplus_key_entry*)match->data)->k;
+
+ return (tacplus_keys?NULL:tacplus_opt_key);
+}
+#define AF_INET 2
+int inet_pton(int , const char*, void*);
+
+static void
+mkipv4_address( address **addr, char *str_addr )
+{
+ *addr=g_malloc( sizeof(address) );
+ (*addr)->type=AT_IPv4;
+ (*addr)->len=4;
+ (*addr)->data=g_malloc( 4 );
+ inet_pton( AF_INET, (const char*)str_addr, (void*)(*addr)->data );
+}
+static void
+parse_tuple( char *key_from_option )
+{
+ char *client,*key;
+ tacplus_key_entry *tacplus_data=g_malloc( sizeof(tacplus_key_entry) );
+ /*
+ printf("keys: %s\n", key_from_option );
+ */
+ client=strchr(key_from_option,'/');
+ if(!client)
+ return;
+ *client++='\0';
+ key=strchr(client,'=');
+ if(!key)
+ return;
+ *key++='\0';
+ /*
+ printf("%s %s => %s\n", key_from_option, client, key );
+ */
+ mkipv4_address( &tacplus_data->s, key_from_option );
+ mkipv4_address( &tacplus_data->c, client );
+ tacplus_data->k=strdup( key );
+ tacplus_keys = g_slist_prepend( tacplus_keys, tacplus_data );
+}
+
+static
+void
+free_tacplus_keys( gpointer data, gpointer user_data _U_ )
+{
+ g_free( ((tacplus_key_entry *)data)->k );
+}
+
+static
+void
+parse_tacplus_keys( char *keys_from_option )
+{
+ char *s1,*s;
+
+ /* Drop old keys */
+ if( tacplus_keys ) {
+ g_slist_foreach( tacplus_keys, free_tacplus_keys, NULL );
+ g_slist_free( tacplus_keys );
+ tacplus_keys=NULL;
+ }
+
+ if( !strchr( keys_from_option, '/' ) ){
+ /* option not in client/server=key format */
+ return ;
+ }
+ s=strdup(keys_from_option);
+ s1=s;
+ keys_from_option = s;
+ while(keys_from_option){
+ if( (s=strchr( keys_from_option, ' ' )) != NULL )
+ *s++='\0';
+ parse_tuple( keys_from_option );
+ keys_from_option=s;
+ }
+ g_free( s1 );
+#ifdef DEB_TACPLUS
+ g_slist_foreach( tacplus_keys, tacplus_print_key_entry, GINT_TO_POINTER(1) );
+#endif
+}
+
+static void
+dissect_tacplus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tvbuff_t *new_tvb=NULL;
+ proto_tree *tacplus_tree;
+ proto_item *ti;
+ guint8 version,flags;
+ proto_tree *flags_tree;
+ proto_item *tf;
+ proto_item *tmp_pi;
+ guint32 len;
+ gboolean request=( pinfo->destport == TCP_PORT_TACACS );
+ char *key=NULL;
+
+ if( request ) {
+ key=find_key( &pinfo->dst, &pinfo->src );
+ } else {
+ key=find_key( &pinfo->src, &pinfo->dst );
+ }
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TACACS+");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ int type = tvb_get_guint8(tvb,1);
+ col_add_fstr( pinfo->cinfo, COL_INFO, "%s: %s",
+ request ? "Q" : "R",
+ val_to_str(type, tacplus_type_vals, "Unknown (0x%02x)"));
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_protocol_format(tree, proto_tacplus,
+ tvb, 0, -1, "TACACS+");
+
+ tacplus_tree = proto_item_add_subtree(ti, ett_tacplus);
+ if (pinfo->match_port == pinfo->destport)
+ {
+ proto_tree_add_boolean_hidden(tacplus_tree,
+ hf_tacplus_request, tvb, 0, 0, TRUE);
+ }
+ else
+ {
+ proto_tree_add_boolean_hidden(tacplus_tree,
+ hf_tacplus_response, tvb, 0, 0, TRUE);
+ }
+ version = tvb_get_guint8(tvb,0);
+ proto_tree_add_uint_format(tacplus_tree, hf_tacplus_majvers, tvb, 0, 1,
+ version,
+ "Major version: %s",
+ (version&0xf0)==0xc0?"TACACS+":"Unknown Version");
+ proto_tree_add_uint(tacplus_tree, hf_tacplus_minvers, tvb, 0, 1,
+ version&0xf);
+ proto_tree_add_item(tacplus_tree, hf_tacplus_type, tvb, 1, 1,
+ FALSE);
+ proto_tree_add_item(tacplus_tree, hf_tacplus_seqno, tvb, 2, 1,
+ FALSE);
+ flags = tvb_get_guint8(tvb,3);
+ tf = proto_tree_add_uint_format(tacplus_tree, hf_tacplus_flags,
+ tvb, 3, 1, flags,
+ "Flags: 0x%02x (%s payload, %s)",
+ flags,
+ (flags&FLAGS_UNENCRYPTED) ? "Unencrypted" :
+ "Encrypted",
+ (flags&FLAGS_SINGLE) ? "Single connection" :
+ "Multiple Connections" );
+ flags_tree = proto_item_add_subtree(tf, ett_tacplus_flags);
+ proto_tree_add_boolean(flags_tree, hf_tacplus_flags_payload_type,
+ tvb, 3, 1, flags);
+ proto_tree_add_boolean(flags_tree, hf_tacplus_flags_connection_type,
+ tvb, 3, 1, flags);
+ proto_tree_add_item(tacplus_tree, hf_tacplus_session_id, tvb, 4, 4,
+ FALSE);
+ len = tvb_get_ntohl(tvb,8);
+ proto_tree_add_uint(tacplus_tree, hf_tacplus_packet_len, tvb, 8, 4,
+ len);
+
+ tmp_pi = proto_tree_add_text(tacplus_tree, tvb, TAC_PLUS_HDR_SIZE, len, "%s%s",
+ ((flags&FLAGS_UNENCRYPTED)?"":"Encrypted "), request?"Request":"Reply" );
+
+ if( flags&FLAGS_UNENCRYPTED ) {
+ new_tvb = tvb_new_subset( tvb, TAC_PLUS_HDR_SIZE, len, len );
+ } else {
+ new_tvb=NULL;
+ if( key && *key ){
+ tacplus_decrypted_tvb_setup( tvb, &new_tvb, pinfo, len, version, key );
+ }
+ }
+ if( new_tvb ) {
+ /* Check to see if I've a decrypted tacacs packet */
+ if( !(flags&FLAGS_UNENCRYPTED) ){
+ tmp_pi = proto_tree_add_text(tacplus_tree, new_tvb, 0, len, "Decrypted %s",
+ request?"Request":"Reply" );
+ }
+ dissect_tacplus_body( tvb, new_tvb, proto_item_add_subtree( tmp_pi, ett_tacplus_body ));
+ }
+ }
+}
+
+void
+tacplus_pref_cb(void)
+{
+ parse_tacplus_keys( tacplus_opt_key );
+}
+
+void
+proto_register_tacplus(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tacplus_response,
+ { "Response", "tacplus.response",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if TACACS+ response", HFILL }},
+ { &hf_tacplus_request,
+ { "Request", "tacplus.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if TACACS+ request", HFILL }},
+ { &hf_tacplus_majvers,
+ { "Major version", "tacplus.majvers",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Major version number", HFILL }},
+ { &hf_tacplus_minvers,
+ { "Minor version", "tacplus.minvers",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Minor version number", HFILL }},
+ { &hf_tacplus_type,
+ { "Type", "tacplus.type",
+ FT_UINT8, BASE_DEC, VALS(tacplus_type_vals), 0x0,
+ "Type", HFILL }},
+ { &hf_tacplus_seqno,
+ { "Sequence number", "tacplus.seqno",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Sequence number", HFILL }},
+ { &hf_tacplus_flags,
+ { "Flags", "tacplus.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Flags", HFILL }},
+ { &hf_tacplus_flags_payload_type,
+ { "Unencrypted", "tacplus.flags.unencrypted",
+ FT_BOOLEAN, 8, TFS(&flags_set_truth), FLAGS_UNENCRYPTED,
+ "Is payload unencrypted?", HFILL }},
+ { &hf_tacplus_flags_connection_type,
+ { "Single Connection", "tacplus.flags.singleconn",
+ FT_BOOLEAN, 8, TFS(&flags_set_truth), FLAGS_SINGLE,
+ "Is this a single connection?", HFILL }},
+ { &hf_tacplus_acct_flags,
+ { "Flags", "tacplus.acct.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Flags", HFILL }},
+ { &hf_tacplus_session_id,
+ { "Session ID", "tacplus.session_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Session ID", HFILL }},
+ { &hf_tacplus_packet_len,
+ { "Packet length", "tacplus.packet_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Packet length", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_tacplus,
+ &ett_tacplus_flags,
+ &ett_tacplus_acct_flags,
+ &ett_tacplus_body,
+ &ett_tacplus_body_chap,
+ };
+ module_t *tacplus_module;
+
+ proto_tacplus = proto_register_protocol("TACACS+", "TACACS+", "tacplus");
+ proto_register_field_array(proto_tacplus, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ tacplus_module = prefs_register_protocol (proto_tacplus, tacplus_pref_cb );
+ prefs_register_string_preference ( tacplus_module, "key",
+ "TACACS+ Encryption Key", "TACACS+ Encryption Key", &tacplus_opt_key );
+}
+
+void
+proto_reg_handoff_tacplus(void)
+{
+ dissector_handle_t tacplus_handle;
+
+ tacplus_handle = create_dissector_handle(dissect_tacplus,
+ proto_tacplus);
+ dissector_add("tcp.port", TCP_PORT_TACACS, tacplus_handle);
+}
+
+
+#define MD5_LEN 16
+
+static void
+md5_xor( guint8 *data, char *key, int data_len, guint8 *session_id, guint8 version, guint8 seq_no )
+{
+ int i,j,md5_len;
+ md5_byte_t *md5_buff;
+ md5_byte_t hash[MD5_LEN]; /* the md5 hash */
+ md5_byte_t *mdp;
+ md5_state_t mdcontext;
+
+ md5_len = 4 /* sizeof(session_id) */ + strlen(key)
+ + sizeof(version) + sizeof(seq_no);
+
+ md5_buff = (md5_byte_t*)g_malloc(md5_len+MD5_LEN);
+
+
+ mdp = md5_buff;
+ *(guint32*)mdp = *(guint32*)session_id;
+ mdp += 4 ;
+ memcpy(mdp, key, strlen(key));
+ mdp += strlen(key);
+ *mdp++ = version;
+ *mdp++ = seq_no;
+
+
+ md5_init(&mdcontext);
+ md5_append(&mdcontext, md5_buff, md5_len);
+ md5_finish(&mdcontext,hash);
+ md5_len += MD5_LEN;
+ for (i = 0; i < data_len; i += 16) {
+
+ for (j = 0; j < 16; j++) {
+ if ((i + j) >= data_len) {
+ i = data_len+1; /* To exit from the external loop */
+ break;
+ }
+ data[i + j] ^= hash[j];
+ }
+ memcpy(mdp, hash, MD5_LEN);
+ md5_init(&mdcontext);
+ md5_append(&mdcontext, md5_buff, md5_len);
+ md5_finish(&mdcontext,hash);
+ }
+ g_free( md5_buff );
+}
diff --git a/epan/dissectors/packet-tacacs.h b/epan/dissectors/packet-tacacs.h
new file mode 100644
index 0000000000..0c8adc24c6
--- /dev/null
+++ b/epan/dissectors/packet-tacacs.h
@@ -0,0 +1,431 @@
+/* packet-tacacs.h
+ * Routines for cisco tacplus packet dissection
+ * Copyright 2000, Emanuele Caratti <wiz@iol.it>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_TACACS_H__
+#define __PACKET_TACACS_H__
+
+#define TAC_PLUS_HDR_SIZE 12
+
+#define MD5_LEN 16
+#define MSCHAP_DIGEST_LEN 49
+enum
+{
+ FLAGS_UNENCRYPTED = 0x01,
+ FLAGS_SINGLE = 0x04
+};
+
+/* Tacacs+ packet type */
+enum
+{
+ TAC_PLUS_AUTHEN = 0x01, /* Authentication */
+ TAC_PLUS_AUTHOR = 0x02, /* Authorization */
+ TAC_PLUS_ACCT = 0x03 /* Accounting */
+};
+
+/* Flags */
+#define TAC_PLUS_ENCRYPTED 0x0
+#define TAC_PLUS_CLEAR 0x1
+
+/* Authentication action to perform */
+enum
+{
+ TAC_PLUS_AUTHEN_LOGIN = 0x01,
+ TAC_PLUS_AUTHEN_CHPASS = 0x02,
+ TAC_PLUS_AUTHEN_SENDPASS = 0x03, /* deprecated */
+ TAC_PLUS_AUTHEN_SENDAUTH = 0x04
+};
+
+/* Authentication priv_levels */
+enum
+{
+ TAC_PLUS_PRIV_LVL_MAX = 0x0f,
+ TAC_PLUS_PRIV_LVL_ROOT = 0x0f,
+ TAC_PLUS_PRIV_LVL_USER = 0x01,
+ TAC_PLUS_PRIV_LVL_MIN = 0x00
+};
+
+/* authen types */
+enum
+{
+ TAC_PLUS_AUTHEN_TYPE_ASCII = 0x01, /* ascii */
+ TAC_PLUS_AUTHEN_TYPE_PAP = 0x02, /* pap */
+ TAC_PLUS_AUTHEN_TYPE_CHAP = 0x03, /* chap */
+ TAC_PLUS_AUTHEN_TYPE_ARAP = 0x04, /* arap */
+ TAC_PLUS_AUTHEN_TYPE_MSCHAP = 0x05 /* mschap */
+};
+
+/* authen services */
+enum
+{
+ TAC_PLUS_AUTHEN_SVC_NONE = 0x00,
+ TAC_PLUS_AUTHEN_SVC_LOGIN = 0x01,
+ TAC_PLUS_AUTHEN_SVC_ENABLE = 0x02,
+ TAC_PLUS_AUTHEN_SVC_PPP = 0x03,
+ TAC_PLUS_AUTHEN_SVC_ARAP = 0x04,
+ TAC_PLUS_AUTHEN_SVC_PT = 0x05,
+ TAC_PLUS_AUTHEN_SVC_RCMD = 0x06,
+ TAC_PLUS_AUTHEN_SVC_X25 = 0x07,
+ TAC_PLUS_AUTHEN_SVC_NASI = 0x08,
+ TAC_PLUS_AUTHEN_SVC_FWPROXY = 0x09
+};
+
+/* status of reply packet, that client get from server in authen */
+enum
+{
+ TAC_PLUS_AUTHEN_STATUS_PASS = 0x01,
+ TAC_PLUS_AUTHEN_STATUS_FAIL = 0x02,
+ TAC_PLUS_AUTHEN_STATUS_GETDATA = 0x03,
+ TAC_PLUS_AUTHEN_STATUS_GETUSER = 0x04,
+ TAC_PLUS_AUTHEN_STATUS_GETPASS = 0x05,
+ TAC_PLUS_AUTHEN_STATUS_RESTART = 0x06,
+ TAC_PLUS_AUTHEN_STATUS_ERROR = 0x07,
+ TAC_PLUS_AUTHEN_STATUS_FOLLOW = 0x21
+};
+
+/* Authen reply Flags */
+#define TAC_PLUS_REPLY_FLAG_NOECHO 0x01
+/* Authen continue Flags */
+#define TAC_PLUS_CONTINUE_FLAG_ABORT 0x01
+
+/* methods of authentication */
+enum {
+ TAC_PLUS_AUTHEN_METH_NOT_SET = 0x00,
+ TAC_PLUS_AUTHEN_METH_NONE = 0x01,
+ TAC_PLUS_AUTHEN_METH_KRB5 = 0x03,
+ TAC_PLUS_AUTHEN_METH_LINE = 0x03,
+ TAC_PLUS_AUTHEN_METH_ENABLE = 0x04,
+ TAC_PLUS_AUTHEN_METH_LOCAL = 0x05,
+ TAC_PLUS_AUTHEN_METH_TACACSPLUS = 0x06,
+ TAC_PLUS_AUTHEN_METH_GUEST = 0x08,
+ TAC_PLUS_AUTHEN_METH_RADIUS = 0x10,
+ TAC_PLUS_AUTHEN_METH_KRB4 = 0x11,
+ TAC_PLUS_AUTHEN_METH_RCMD = 0x20
+};
+
+/* authorization status */
+enum
+{
+ TAC_PLUS_AUTHOR_STATUS_PASS_ADD = 0x01,
+ TAC_PLUS_AUTHOR_STATUS_PASS_REPL = 0x02,
+ TAC_PLUS_AUTHOR_STATUS_FAIL = 0x10,
+ TAC_PLUS_AUTHOR_STATUS_ERROR = 0x11,
+ TAC_PLUS_AUTHOR_STATUS_FOLLOW = 0x21
+};
+
+/* accounting flag */
+
+enum
+{
+ TAC_PLUS_ACCT_FLAG_MORE = 0x1, /* deprecated */
+ TAC_PLUS_ACCT_FLAG_START = 0x2,
+ TAC_PLUS_ACCT_FLAG_STOP = 0x4,
+ TAC_PLUS_ACCT_FLAG_WATCHDOG = 0x8
+};
+/* accounting status */
+enum {
+ TAC_PLUS_ACCT_STATUS_SUCCESS = 0x01,
+ TAC_PLUS_ACCT_STATUS_ERROR = 0x02,
+ TAC_PLUS_ACCT_STATUS_FOLLOW = 0x21
+};
+
+/* Header offsets */
+#define H_VER_OFF (0)
+#define H_TYPE_OFF (H_VER_OFF+1)
+#define H_SEQ_NO_OFF (H_TYPE_OFF+1)
+#define H_FLAGS_OFF (H_SEQ_NO_OFF+1)
+#define H_SESSION_ID_OFF (H_FLAGS_OFF+1)
+#define H_LENGTH_OFF (H_SESSION_ID_OFF+4)
+
+#define TACPLUS_BODY_OFF 0
+/* authen START offsets */
+#define AUTHEN_S_ACTION_OFF (TACPLUS_BODY_OFF)
+#define AUTHEN_S_PRIV_LVL_OFF (AUTHEN_S_ACTION_OFF+1)
+#define AUTHEN_S_AUTHEN_TYPE_OFF (AUTHEN_S_PRIV_LVL_OFF+1)
+#define AUTHEN_S_SERVICE_OFF (AUTHEN_S_AUTHEN_TYPE_OFF+1)
+#define AUTHEN_S_USER_LEN_OFF (AUTHEN_S_SERVICE_OFF+1)
+#define AUTHEN_S_PORT_LEN_OFF (AUTHEN_S_USER_LEN_OFF+1)
+#define AUTHEN_S_REM_ADDR_LEN_OFF (AUTHEN_S_PORT_LEN_OFF+1)
+#define AUTHEN_S_DATA_LEN_OFF (AUTHEN_S_REM_ADDR_LEN_OFF+1)
+#define AUTHEN_S_VARDATA_OFF (AUTHEN_S_DATA_LEN_OFF+1) /* variable data offset (user, port, etc ) */
+
+/* authen REPLY fields offset */
+#define AUTHEN_R_STATUS_OFF (TACPLUS_BODY_OFF)
+#define AUTHEN_R_FLAGS_OFF (AUTHEN_R_STATUS_OFF+1)
+#define AUTHEN_R_SRV_MSG_LEN_OFF (AUTHEN_R_FLAGS_OFF+1)
+#define AUTHEN_R_DATA_LEN_OFF (AUTHEN_R_SRV_MSG_LEN_OFF+2)
+#define AUTHEN_R_VARDATA_OFF (AUTHEN_R_DATA_LEN_OFF+2)
+
+/* authen CONTINUE fields offset */
+#define AUTHEN_C_USER_LEN_OFF (TACPLUS_BODY_OFF)
+#define AUTHEN_C_DATA_LEN_OFF (AUTHEN_C_USER_LEN_OFF+2)
+#define AUTHEN_C_FLAGS_OFF (AUTHEN_C_DATA_LEN_OFF+2)
+#define AUTHEN_C_VARDATA_OFF (AUTHEN_C_FLAGS_OFF+1)
+
+/* acct REQUEST fields offsets */
+#define ACCT_Q_FLAGS_OFF (TACPLUS_BODY_OFF)
+#define ACCT_Q_METHOD_OFF (ACCT_Q_FLAGS_OFF+1)
+#define ACCT_Q_PRIV_LVL_OFF (ACCT_Q_METHOD_OFF+1)
+#define ACCT_Q_AUTHEN_TYPE_OFF (ACCT_Q_PRIV_LVL_OFF+1)
+#define ACCT_Q_SERVICE_OFF (ACCT_Q_AUTHEN_TYPE_OFF+1)
+#define ACCT_Q_USER_LEN_OFF (ACCT_Q_SERVICE_OFF+1)
+#define ACCT_Q_PORT_LEN_OFF (ACCT_Q_USER_LEN_OFF+1)
+#define ACCT_Q_REM_ADDR_LEN_OFF (ACCT_Q_PORT_LEN_OFF+1)
+#define ACCT_Q_ARG_CNT_OFF (ACCT_Q_REM_ADDR_LEN_OFF+1)
+#define ACCT_Q_VARDATA_OFF (ACCT_Q_ARG_CNT_OFF+1)
+
+/* acct REPLY fields offsets */
+#define ACCT_R_SRV_MSG_LEN_OFF (TACPLUS_BODY_OFF)
+#define ACCT_R_DATA_LEN_OFF (ACCT_R_SRV_MSG_LEN_OFF+2)
+#define ACCT_R_STATUS_OFF (ACCT_R_DATA_LEN_OFF+2)
+#define ACCT_R_VARDATA_OFF (ACCT_R_STATUS_OFF+1)
+
+/* AUTHORIZATION */
+/* Request */
+#define AUTHOR_Q_AUTH_METH_OFF (TACPLUS_BODY_OFF)
+#define AUTHOR_Q_PRIV_LVL_OFF (AUTHOR_Q_AUTH_METH_OFF+1)
+#define AUTHOR_Q_AUTHEN_TYPE_OFF (AUTHOR_Q_PRIV_LVL_OFF+1)
+#define AUTHOR_Q_SERVICE_OFF (AUTHOR_Q_AUTHEN_TYPE_OFF+1)
+#define AUTHOR_Q_USER_LEN_OFF (AUTHOR_Q_SERVICE_OFF+1)
+#define AUTHOR_Q_PORT_LEN_OFF (AUTHOR_Q_USER_LEN_OFF+1)
+#define AUTHOR_Q_REM_ADDR_LEN_OFF (AUTHOR_Q_PORT_LEN_OFF+1)
+#define AUTHOR_Q_ARGC_OFF (AUTHOR_Q_REM_ADDR_LEN_OFF+1)
+#define AUTHOR_Q_VARDATA_OFF (AUTHOR_Q_ARGC_OFF+1)
+
+/* Reply */
+#define AUTHOR_R_STATUS_OFF (TACPLUS_BODY_OFF)
+#define AUTHOR_R_ARGC_OFF (AUTHOR_R_STATUS_OFF+1)
+#define AUTHOR_R_SRV_MSG_LEN_OFF (AUTHOR_R_ARGC_OFF+1)
+#define AUTHOR_R_DATA_LEN_OFF (AUTHOR_R_SRV_MSG_LEN_OFF+2)
+#define AUTHOR_R_VARDATA_OFF (AUTHOR_R_DATA_LEN_OFF+2)
+
+
+#if 0
+/* Packet structures */
+typedef struct {
+ u_char version;
+ u_char type;
+ u_char seq_no;
+ u_char flags;
+ guint32 session_id;
+ guint32 length;
+} tacplus_pkt_hdr;
+
+/* Authentication START packet */
+typedef struct {
+ u_char action;
+ u_char priv_lvl;
+ u_char authen_type;
+ u_char service;
+ u_char user_len;
+ u_char port_len;
+ u_char rem_addr_len;
+ u_char data_len;
+ u_char vardata[1];
+} tacplus_authen_start ;
+
+/* Authentication CONTINUE packet */
+typedef struct {
+ guint16 user_len;
+ guint16 data_len;
+ u_char flags;
+ u_char vardata[1];
+} tacplus_authen_continue ;
+
+/* Authentication REPLY packet */
+typedef struct {
+ u_char status;
+ u_char flags;
+ guint16 srv_msg_len;
+ guint16 data_len;
+ u_char vardata[1];
+} tacplus_authen_reply;
+
+
+/* Authentication sub-PACKET */
+typedef union {
+ tacplus_authen_start s; /* start */
+ tacplus_authen_continue c; /* continue */
+ tacplus_authen_reply r; /* reply (from srv) */
+} tacplus_authen_pkt;
+
+/* AUTHORIZATION request */
+
+typedef struct {
+ u_char authen_method;
+ u_char priv_lvl;
+ u_char authen_type;
+ u_char authen_service;
+ u_char user_len;
+ u_char port_len;
+ u_char rem_addr_len;
+ u_char arg_cnt;
+ u_char vardata[1];
+} tacplus_author_request;
+
+typedef struct {
+ u_char status;
+ u_char arg_cnt;
+ guint16 srv_msg_len;
+ guint16 data_len;
+ u_char vardata[1];
+} tacplus_author_reply;
+
+typedef union {
+ tacplus_author_request q;
+ tacplus_author_reply r;
+} tacplus_author_pkt;
+
+/* ACCOUNTING request */
+typedef struct {
+ u_char flags;
+ u_char authen_method;
+ u_char priv_lvl;
+ u_char authen_type;
+ u_char authen_service;
+ u_char user_len;
+ u_char port_len;
+ u_char rem_addr_len;
+ u_char arg_cnt;
+ u_char vardata[1];
+} tacplus_account_request;
+
+typedef struct {
+ guint16 srv_msg_len;
+ guint16 data_len;
+ u_char status;
+ u_char vardata[1];
+} tacplus_account_reply;
+
+typedef union {
+ tacplus_account_request q; /* Request */
+ tacplus_account_reply r; /* Reply */
+} tacplus_account_pkt;
+
+/* TACACS+ Packet */
+typedef struct {
+ tacplus_pkt_hdr hdr;
+ union {
+ tacplus_authen_pkt authen;
+ tacplus_author_pkt author;
+ tacplus_account_pkt acct;
+ } body;
+} tacplus_pkt;
+
+#endif
+
+/* From my old tacacs dissector */
+static value_string tacplus_type_vals[] = {
+ {TAC_PLUS_AUTHEN, "Authentication"},
+ {TAC_PLUS_AUTHOR, "Authorization" },
+ {TAC_PLUS_ACCT, "Accounting" },
+ {0, NULL}};
+
+static value_string tacplus_authen_action_vals[] = {
+ {TAC_PLUS_AUTHEN_LOGIN, "Inbound Login"},
+ {TAC_PLUS_AUTHEN_CHPASS, "Change password request"},
+ {TAC_PLUS_AUTHEN_SENDPASS, "Send password request"},
+ {TAC_PLUS_AUTHEN_SENDAUTH, "Outbound Request (SENDAUTH)"},
+ {0, NULL}};
+
+#if 0
+static value_string tacplus_authen_priv_lvl_vals[] = {
+ {TAC_PLUS_PRIV_LVL_MAX, "LVL_MAX"},
+ {TAC_PLUS_PRIV_LVL_ROOT, "LVL_ROOT"},
+ {TAC_PLUS_PRIV_LVL_USER, "LVL_USER"},
+ {TAC_PLUS_PRIV_LVL_MIN, "LVL_MIN"},
+ {0, NULL}};
+#endif
+
+static value_string tacplus_authen_type_vals[] = {
+ {TAC_PLUS_AUTHEN_TYPE_ASCII, "ASCII"},
+ {TAC_PLUS_AUTHEN_TYPE_PAP, "PAP"},
+ {TAC_PLUS_AUTHEN_TYPE_CHAP, "CHAP"},
+ {TAC_PLUS_AUTHEN_TYPE_ARAP, "ARAP"},
+ {TAC_PLUS_AUTHEN_TYPE_MSCHAP, "MS-CHAP"},
+ {0, NULL}};
+
+static value_string tacplus_authen_service_vals[] = {
+ {TAC_PLUS_AUTHEN_SVC_NONE, "TAC_PLUS_AUTHEN_SVC_NONE"},
+ {TAC_PLUS_AUTHEN_SVC_LOGIN, "Login" },
+ {TAC_PLUS_AUTHEN_SVC_ENABLE, "ENABLE"},
+ {TAC_PLUS_AUTHEN_SVC_PPP, "PPP" },
+ {TAC_PLUS_AUTHEN_SVC_ARAP, "ARAP" },
+ {TAC_PLUS_AUTHEN_SVC_PT, "TAC_PLUS_AUTHEN_SVC_PT"},
+ {TAC_PLUS_AUTHEN_SVC_RCMD, "TAC_PLUS_AUTHEN_SVC_RCMD"},
+ {TAC_PLUS_AUTHEN_SVC_X25, "TAC_PLUS_AUTHEN_SVC_X25"},
+ {TAC_PLUS_AUTHEN_SVC_NASI, "TAC_PLUS_AUTHEN_SVC_NASI"},
+ {TAC_PLUS_AUTHEN_SVC_FWPROXY, "TAC_PLUS_AUTHEN_SVC_FWPROXY"},
+ {0, NULL}};
+
+static value_string tacplus_reply_status_vals[] = {
+ {TAC_PLUS_AUTHEN_STATUS_PASS, "Authentication Passed"},
+ {TAC_PLUS_AUTHEN_STATUS_FAIL, "Authentication Failed"},
+ {TAC_PLUS_AUTHEN_STATUS_GETDATA, "Send Data"},
+ {TAC_PLUS_AUTHEN_STATUS_GETUSER, "Send Username"},
+ {TAC_PLUS_AUTHEN_STATUS_GETPASS, "Send Password"},
+ {TAC_PLUS_AUTHEN_STATUS_RESTART, "Restart Authentication Sequence"},
+ {TAC_PLUS_AUTHEN_STATUS_ERROR, "Unrecoverable Error"},
+ {TAC_PLUS_AUTHEN_STATUS_FOLLOW, "Use Alternate Server"},
+ {0, NULL}};
+
+
+static value_string tacplus_authen_method[] = {
+ {TAC_PLUS_AUTHEN_METH_NOT_SET, "NOT_SET"},
+ {TAC_PLUS_AUTHEN_METH_NONE, "NONE"},
+ {TAC_PLUS_AUTHEN_METH_KRB5, "KRB5"},
+ {TAC_PLUS_AUTHEN_METH_LINE, "LINE"},
+ {TAC_PLUS_AUTHEN_METH_ENABLE, "ENABLE"},
+ {TAC_PLUS_AUTHEN_METH_LOCAL, "LOCAL"},
+ {TAC_PLUS_AUTHEN_METH_TACACSPLUS, "TACACSPLUS"},
+ {TAC_PLUS_AUTHEN_METH_GUEST, "GUEST"},
+ {TAC_PLUS_AUTHEN_METH_RADIUS, "RADIUS"},
+ {TAC_PLUS_AUTHEN_METH_KRB4, "KRB4"},
+ {TAC_PLUS_AUTHEN_METH_RCMD, "RCMD"},
+ {0, NULL}};
+
+static value_string tacplus_author_status[] = {
+ {TAC_PLUS_AUTHOR_STATUS_PASS_ADD, "PASS_ADD"},
+ {TAC_PLUS_AUTHOR_STATUS_PASS_REPL, "PASS_REPL"},
+ {TAC_PLUS_AUTHOR_STATUS_FAIL, "FAIL"},
+ {TAC_PLUS_AUTHOR_STATUS_ERROR, "ERROR"},
+ {TAC_PLUS_AUTHOR_STATUS_FOLLOW, "FOLLOW"},
+ {0, NULL}};
+
+static value_string tacplus_acct_status[] = {
+ {TAC_PLUS_ACCT_STATUS_SUCCESS, "Success"},
+ {TAC_PLUS_ACCT_STATUS_ERROR, "Error"},
+ {TAC_PLUS_ACCT_STATUS_FOLLOW, "Follow"},
+ {0, NULL}};
+
+#ifdef __TAC_ACCOUNTING__
+static value_string tacplus_acct_flags[] = {
+ {TAC_PLUS_ACCT_FLAG_MORE, "More (deprecated)"},
+ {TAC_PLUS_ACCT_FLAG_START, "Start"},
+ {TAC_PLUS_ACCT_FLAG_STOP, "Stop"},
+ {TAC_PLUS_ACCT_FLAG_WATCHDOG,"Update"},
+ {0, NULL}};
+#endif
+
+#endif /* __PACKET_TACACS_H__ */
diff --git a/epan/dissectors/packet-tcap.c b/epan/dissectors/packet-tcap.c
new file mode 100644
index 0000000000..4c87ebf756
--- /dev/null
+++ b/epan/dissectors/packet-tcap.c
@@ -0,0 +1,2900 @@
+/* packet-tcap.c
+ * Routines for TCAP dissection
+ *
+ * Copyright 2000, Samuel Qu <samuel.qu [AT] utstar.com>,
+ *
+ * Michael Lum <mlum [AT] telostech.com>,
+ * Modified for ANSI TCAP support and many changes for
+ * EOC matching. (2003)
+ *
+ * (append your name here for newer version)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
+ * is a dissector file; if you just copied this from README.developer,
+ * don't bother with the "Copied from" - you don't even need to put
+ * in a "Copied from" if you copied an existing dissector, especially
+ * if the bulk of the code in the new dissector is your code)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gmodule.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <glib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
+#include "prefs.h"
+#include "asn1.h"
+#include "packet-tcap.h"
+
+Tcap_Standard_Type tcap_standard = ITU_TCAP_STANDARD;
+
+/* saved pinfo */
+static packet_info *g_pinfo = NULL;
+static proto_tree *g_tcap_tree = NULL;
+static gboolean g_tcap_ends_def_len = FALSE;
+
+/* Initialize the protocol and registered fields */
+static int proto_tcap = -1;
+static int hf_tcap_message_type = -1;
+static int hf_ansi_tcap_message_type = -1;
+static int hf_tcap_tag = -1;
+static int hf_tcap_length = -1;
+static int hf_tcap_bytes = -1;
+static int hf_tcap_app_con_name = -1;
+static int hf_tcap_id = -1;
+static int hf_tcap_tid = -1;
+static int hf_tcap_ssn = -1; /* faked */
+static int hf_tcap_dlg_type = -1;
+static int hf_tcap_int = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_tcap = -1;
+/* Samuel */
+static gint ett_otid = -1;
+static gint ett_dtid = -1;
+static gint ett_dlg_portion = -1;
+static gint ett_dlg_req = -1;
+static gint ett_dlg_rsp = -1;
+static gint ett_dlg_abort = -1;
+static gint ett_comps_portion = -1;
+static gint ett_reason = -1;
+static gint ett_component = -1;
+static gint ett_problem = -1;
+static gint ett_error = -1;
+static gint ett_params = -1;
+static gint ett_param = -1;
+
+static dissector_handle_t data_handle;
+static dissector_table_t tcap_itu_ssn_dissector_table; /* map use ssn in sccp */
+static dissector_table_t tcap_ansi_ssn_dissector_table; /* map use ssn in sccp */
+static gboolean lock_info_col = TRUE;
+
+/* TCAP transaction message type definition - Samuel */
+#define ST_MSG_TYP_UNI 0x61 /*0b01100001*/
+#define ST_MSG_TYP_BGN 0x62 /*0b01100010*/
+#define ST_MSG_TYP_CNT 0x65 /*0b01100101*/
+#define ST_MSG_TYP_END 0x64 /*0b01100100*/
+#define ST_MSG_TYP_PABT 0x67 /*0b01100111*/
+static const value_string msg_type_strings[] = {
+ { ST_MSG_TYP_UNI, "TC-UNI" },
+ { ST_MSG_TYP_BGN, "TC-BEGIN" },
+ { ST_MSG_TYP_CNT, "TC-CONTINUE" },
+ { ST_MSG_TYP_END, "TC-END" },
+ { ST_MSG_TYP_PABT, "TC-PABORT" },
+ { 0, NULL },
+};
+
+/* ANSI TCAP transaction message type definition */
+#define ANSI_ST_MSG_TYP_UNI 0xe1
+#define ANSI_ST_MSG_TYP_QWP 0xe2
+#define ANSI_ST_MSG_TYP_QWOP 0xe3
+#define ANSI_ST_MSG_TYP_RSP 0xe4
+#define ANSI_ST_MSG_TYP_CWP 0xe5
+#define ANSI_ST_MSG_TYP_CWOP 0xe6
+#define ANSI_ST_MSG_TYP_ABT 0xf6
+static const value_string ansi_msg_type_strings[] = {
+ { ANSI_ST_MSG_TYP_UNI, "TC-UNI" },
+ { ANSI_ST_MSG_TYP_QWP, "TC-QUERY W PERM" },
+ { ANSI_ST_MSG_TYP_QWOP, "TC-QUERY WO PERM" },
+ { ANSI_ST_MSG_TYP_RSP, "TC-RESPONSE" },
+ { ANSI_ST_MSG_TYP_CWP, "TC-CONV W PERM" },
+ { ANSI_ST_MSG_TYP_CWOP, "TC-CONV WO PERM" },
+ { ANSI_ST_MSG_TYP_ABT, "TC-ABORT" },
+ { 0, NULL },
+};
+
+#define ST_ANSI_CMP_TAG 0xe8
+#define ST_ANSI_TID_TAG 0xc7
+
+/* TCAP TID tag value - Samuel */
+#define ST_TID_SOURCE 0
+#define ST_TID_DEST 1
+#define ST_ITU_ORG_TID_TAG 0x48 /*0b01001000*/
+#define ST_ITU_DST_TID_TAG 0x49 /*0b01001001*/
+#define ST_ITU_PABT_TAG 0x4a /*0b01001010*/
+#define ST_ITU_DLG_TAG 0x6b
+#define ST_ITU_CMP_TAG 0x6c
+
+static const value_string tid_strings[] = {
+ { ST_ITU_ORG_TID_TAG, "Source Transaction ID" },
+ { ST_ITU_DST_TID_TAG, "Destination Transaction ID" },
+ { 0, NULL },
+};
+
+/* TCAP dialog type */
+#define TC_DLG_REQ 0x60
+#define TC_DLG_RSP 0x61
+#define TC_DLG_ABRT 0x64
+
+static const value_string dlg_type_strings[] = {
+ { TC_DLG_REQ , "Dialogue Request" },
+ { TC_DLG_RSP , "Dialogue Response" },
+ { TC_DLG_ABRT, "Dialogue Abort" },
+ { 0, NULL },
+};
+
+const value_string tcap_component_type_str[] = {
+ { TCAP_COMP_INVOKE, "Invoke" },
+ { TCAP_COMP_RRL, "Return Result(L)" },
+ { TCAP_COMP_RE, "Return Error" },
+ { TCAP_COMP_REJECT, "Reject" },
+ { TCAP_COMP_RRN, "Return Result(NL)" },
+ { 0, NULL } };
+
+#define TC_DS_OK 1
+#define TC_DS_FAIL 0
+
+
+int
+tcap_find_eoc(ASN1_SCK *asn1)
+{
+ guint saved_offset;
+ guint tag;
+ guint len;
+ gboolean def_len;
+
+ saved_offset = asn1->offset;
+
+ while (!asn1_eoc(asn1, -1))
+ {
+ asn1_id_decode1(asn1, &tag);
+ asn1_length_decode(asn1, &def_len, &len);
+
+ if (def_len)
+ {
+ asn1->offset += len;
+ }
+ else
+ {
+ asn1->offset += tcap_find_eoc(asn1);
+ asn1_eoc_decode(asn1, -1);
+ }
+ }
+
+ len = asn1->offset - saved_offset;
+ asn1->offset = saved_offset;
+
+ return(len);
+}
+
+gboolean
+tcap_check_tag(ASN1_SCK *asn1, guint tag)
+{
+ guint saved_offset, real_tag;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
+ {
+ return (FALSE);
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &real_tag);
+ asn1->offset = saved_offset;
+ return (tag == real_tag);
+}
+
+
+static int
+dissect_tcap_len(ASN1_SCK *asn1, proto_tree *tree, gboolean *def_len, guint *len)
+{
+ guint saved_offset;
+ int ret;
+
+ saved_offset = asn1->offset;
+ *len = 0;
+ *def_len = FALSE;
+ ret = asn1_length_decode(asn1, def_len, len);
+
+ if (*def_len)
+ {
+ proto_tree_add_uint(tree, hf_tcap_length, asn1->tvb, saved_offset, asn1->offset - saved_offset, *len);
+ }
+ else
+ {
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "Length: Indefinite");
+ }
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_eoc(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset, ret;
+
+ saved_offset = asn1->offset;
+
+ if (tvb_length_remaining(asn1->tvb, saved_offset) <= 0)
+ {
+ return TC_DS_FAIL;
+ }
+
+ if (!asn1_eoc(asn1, -1))
+ {
+ return TC_DS_FAIL;
+ }
+
+ ret = asn1_eoc_decode(asn1, -1);
+
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "End of Contents");
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_tag(ASN1_SCK *asn1, proto_tree *tree, guint *tag, gchar * str)
+{
+ guint saved_offset, real_tag;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &real_tag);
+ if ((*tag != (guint) -1) && (real_tag != *tag))
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+ proto_tree_add_uint_format(tree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset,
+ real_tag, str);
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_octet(ASN1_SCK *asn1, proto_tree *tree, gchar * str)
+{
+ guint saved_offset;
+ guchar my_oct;
+
+ saved_offset = asn1->offset;
+ asn1_octet_decode(asn1, &my_oct);
+ proto_tree_add_uint_format(tree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset,
+ my_oct, "%s %d", str, my_oct);
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_integer(ASN1_SCK *asn1, proto_tree *tree, guint len, gchar * str)
+{
+ guint saved_offset;
+ gint32 invokeId;
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &invokeId);
+ proto_tree_add_int_format(tree, hf_tcap_int, asn1->tvb, saved_offset, asn1->offset - saved_offset,
+ invokeId, "%s %d", str, invokeId);
+ return TC_DS_OK;
+}
+
+/* dissect tid */
+static int
+dissect_tcap_tid(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti, int type)
+{
+ guint saved_offset, org_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *tid_item;
+ proto_tree *subtree;
+ guchar *poctets;
+ guint32 val;
+ gboolean def_len;
+
+ org_offset = asn1->offset;
+ if ( ST_TID_SOURCE == type)
+ {
+ tid_item = proto_tree_add_text(tcap_tree, asn1->tvb, asn1->offset, -1, "Source Transaction ID");
+ subtree = proto_item_add_subtree(tid_item, ett_otid);
+ }
+ else
+ {
+ tid_item = proto_tree_add_text(tcap_tree, asn1->tvb, asn1->offset, -1, "Destination Transaction ID");
+ subtree = proto_item_add_subtree(tid_item, ett_dtid);
+ }
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+ proto_tree_add_uint(subtree, hf_tcap_tid, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag);
+
+ /* error handling */
+ switch(type)
+ {
+ case ST_TID_SOURCE:
+ if (ST_ITU_ORG_TID_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+ break;
+ case ST_TID_DEST:
+ if (ST_ITU_DST_TID_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ /*
+ * XXX - this is, I think, an OCTET STRING (SIZE(1..4)); should it
+ * just be put into the protocol tree as an FT_BYTES value and
+ * displayed in the Info column with "bytes_to_str()"?
+ *
+ * If so, should we have separate hf_tcap_source_tid and
+ * hf_tcap_destination_tid?
+ *
+ * Does that apply to other transaction IDs?
+ */
+ if (len > 4)
+ {
+ return TC_DS_FAIL;
+ }
+
+ saved_offset = asn1->offset;
+ ret = asn1_string_value_decode(asn1, len, &poctets);
+ val = 0;
+ memcpy(&val, poctets, len);
+
+ ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
+ g_free(poctets);
+
+ proto_item_set_len(tid_item, asn1->offset - org_offset);
+
+ if (type == ST_TID_DEST)
+ {
+ if (check_col(g_pinfo->cinfo, COL_INFO))
+ col_append_fstr(g_pinfo->cinfo, COL_INFO, "dtid(%x) ", val);
+ }
+ else
+ {
+ if (check_col(g_pinfo->cinfo, COL_INFO))
+ col_append_fstr(g_pinfo->cinfo, COL_INFO, "stid(%x) ", val);
+ }
+
+ return TC_DS_OK;
+}
+
+/* Samuel */
+/* dissect operation portion */
+static int
+dissect_tcap_invokeId(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ guint tag;
+ gboolean def_len;
+
+#define INVOKE_ID_TAG 0x2
+ if (tcap_check_tag(asn1, INVOKE_ID_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Invoke ID Tag");
+ dissect_tcap_len(asn1, tree, &def_len, &len);
+ dissect_tcap_integer(asn1, tree, len, "Invoke ID:");
+ }
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_lnkId(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ guint tag;
+ gboolean def_len;
+
+ if (tcap_check_tag(asn1, TCAP_LINKED_ID_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Linked ID Tag");
+ dissect_tcap_len(asn1, tree, &def_len, &len);
+ dissect_tcap_integer(asn1, tree, len, "Linked ID:");
+ }
+
+ return TC_DS_OK;
+}
+
+static void
+dissect_tcap_opr_code(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ guint tag;
+ gboolean got_it = FALSE;
+ gboolean def_len;
+
+#define TCAP_LOC_OPR_CODE_TAG 0x02
+ if (tcap_check_tag(asn1, TCAP_LOC_OPR_CODE_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Local Operation Code Tag");
+ got_it = TRUE;
+ }
+#define TCAP_GLB_OPR_CODE_TAG 0x06
+ else if (tcap_check_tag(asn1, TCAP_GLB_OPR_CODE_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Global Operation Code Tag");
+ got_it = TRUE;
+ }
+
+ if (got_it)
+ {
+ dissect_tcap_len(asn1, tree, &def_len, &len);
+
+ proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Operation Code");
+
+ asn1->offset += len;
+ }
+}
+
+static int
+dissect_tcap_param(ASN1_SCK *asn1, proto_tree *tree, guint exp_len)
+{
+ guint orig_offset, saved_offset, len_offset;
+ guint tag, len;
+ gboolean def_len;
+ proto_item *item;
+ proto_tree *subtree;
+
+ orig_offset = asn1->offset;
+
+#define TC_INVALID_TAG 0
+ while ((tvb_length_remaining(asn1->tvb, asn1->offset) > 0) &&
+ (!tcap_check_tag(asn1, 0)))
+ {
+ if ((exp_len != 0) &&
+ ((asn1->offset - orig_offset) >= exp_len))
+ {
+ break;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+ len_offset = asn1->offset;
+ asn1_length_decode(asn1, &def_len, &len);
+
+ if (TCAP_CONSTRUCTOR(tag))
+ {
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Sequence");
+
+ subtree = proto_item_add_subtree(item, ett_params);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, len_offset - saved_offset, tag, "Sequence Tag");
+
+ if (def_len)
+ {
+ proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb,
+ len_offset, asn1->offset - len_offset, len);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ len_offset, asn1->offset - len_offset, "Length: Indefinite");
+
+ len = tcap_find_eoc(asn1);
+ }
+
+ proto_item_set_len(item,
+ (asn1->offset - saved_offset) + len +
+ (def_len ? 0 : TCAP_EOC_LEN));
+
+ dissect_tcap_param(asn1, subtree, len);
+
+ if (!def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+ }
+ continue;
+ }
+
+ if (!def_len)
+ {
+ proto_tree_add_uint_format(tree, hf_tcap_tag, asn1->tvb,
+ saved_offset, len_offset - saved_offset, tag, "Parameter Tag");
+
+ proto_tree_add_text(tree, asn1->tvb,
+ len_offset, asn1->offset - len_offset, "Length: Indefinite");
+
+ len = tcap_find_eoc(asn1);
+
+ dissect_tcap_param(asn1, tree, len);
+
+ dissect_tcap_eoc(asn1, tree);
+ continue;
+ }
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, (asn1->offset - saved_offset) + len, "Parameter");
+
+ subtree = proto_item_add_subtree(item, ett_param);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, len_offset - saved_offset, tag, "Parameter Tag");
+
+ proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb,
+ len_offset, asn1->offset - len_offset, len);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ asn1->offset, len, "Parameter Data");
+
+ asn1->offset += len;
+ }
+
+ return TC_DS_OK;
+}
+
+static proto_tree *
+dissect_tcap_component(ASN1_SCK *asn1, proto_tree *tree, guint *len_p)
+{
+ guint saved_offset;
+ guint tag;
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean def_len;
+
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component ID");
+
+ subtree = proto_item_add_subtree(item, ett_component);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag,
+ "Component ID Identifier");
+
+ dissect_tcap_len(asn1, subtree, &def_len, len_p);
+
+ proto_item_set_len(item, (asn1->offset - saved_offset) + *len_p);
+
+ return(subtree);
+}
+
+static void
+dissect_tcap_problem(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint orig_offset, saved_offset, len_offset;
+ guint len;
+ guint tag;
+ proto_tree *subtree;
+ proto_item *item = NULL;
+ gchar *str = NULL;
+ gchar *type_str = NULL;
+ gint32 spec;
+ gboolean def_len;
+
+
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ len_offset = asn1->offset;
+ asn1_length_decode(asn1, &def_len, &len);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Problem Code");
+
+ subtree = proto_item_add_subtree(item, ett_problem);
+
+ if (!def_len)
+ {
+ len = tcap_find_eoc(asn1);
+ }
+
+ proto_item_set_len(item, (asn1->offset - saved_offset) + len +
+ (def_len ? 0 : TCAP_EOC_LEN));
+
+ if (len != 1)
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ asn1->offset, len, "Unknown encoding of Problem Code");
+
+ asn1->offset += len;
+
+ if (!def_len)
+ {
+ asn1_eoc_decode(asn1, -1);
+ }
+
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &spec);
+
+ switch (tag)
+ {
+ case 0x80:
+ type_str = "General Problem";
+ switch (spec)
+ {
+ case 0: str = "Unrecognized Component"; break;
+ case 1: str = "Mistyped Component"; break;
+ case 2: str = "Badly Structured Component"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 0x81:
+ type_str = "Invoke";
+ switch (spec)
+ {
+ case 0: str = "Duplicate Invoke ID"; break;
+ case 1: str = "Unrecognized Operation"; break;
+ case 2: str = "Mistyped Parameter"; break;
+ case 3: str = "Resource Limitation"; break;
+ case 4: str = "Initiating Release"; break;
+ case 5: str = "Unrecognized Linked ID"; break;
+ case 6: str = "Linked Response Unexpected"; break;
+ case 7: str = "Unexpected Linked Operation"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 0x82:
+ type_str = "Return Result";
+ switch (spec)
+ {
+ case 0: str = "Unrecognized Invoke ID"; break;
+ case 1: str = "Return Result Unexpected"; break;
+ case 2: str = "Mistyped Parameter"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 0x83:
+ type_str = "Return Error";
+ switch (spec)
+ {
+ case 0: str = "Unrecognized Invoke ID"; break;
+ case 1: str = "Return Error Unexpected"; break;
+ case 2: str = "Unrecognized Error"; break;
+ case 3: str = "Unexpected Error"; break;
+ case 4: str = "Mistyped Parameter"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ default:
+ type_str = "Undefined";
+ break;
+ }
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ orig_offset, len_offset - orig_offset, tag, type_str);
+
+ if (def_len)
+ {
+ proto_tree_add_uint(subtree, hf_tcap_length, asn1->tvb,
+ len_offset, saved_offset - len_offset, len);
+ }
+ else
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ len_offset, saved_offset - len_offset, "Length: Indefinite");
+ }
+
+ proto_tree_add_text(subtree, asn1->tvb, saved_offset, 1,
+ "Problem Specifier %s", str);
+}
+
+
+static void
+dissect_ansi_opr_code(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ guint tag;
+ gboolean got_it = FALSE;
+ gboolean def_len;
+
+#define TCAP_NAT_OPR_CODE_TAG 0xd0
+ if (tcap_check_tag(asn1, TCAP_NAT_OPR_CODE_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "National TCAP Operation Code Identifier");
+ got_it = TRUE;
+ }
+#define TCAP_PRIV_OPR_CODE_TAG 0xd1
+ else if (tcap_check_tag(asn1, TCAP_PRIV_OPR_CODE_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Private TCAP Operation Code Identifier");
+ got_it = TRUE;
+ }
+
+ if (got_it)
+ {
+ dissect_tcap_len(asn1, tree, &def_len, &len);
+
+ proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Operation Code");
+
+ asn1->offset += len;
+ }
+}
+
+static void
+dissect_ansi_problem(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ proto_tree *subtree;
+ proto_item *item = NULL;
+ gchar *str = NULL;
+ gchar *type_str = NULL;
+ gint32 type, spec;
+ gboolean def_len;
+
+
+#define TCAP_PROB_CODE_TAG 0xd5
+ if (tcap_check_tag(asn1, TCAP_PROB_CODE_TAG))
+ {
+ str = "Problem Code Identifier";
+ }
+ else
+ {
+ /* XXX */
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Problem Code");
+
+ subtree = proto_item_add_subtree(item, ett_problem);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, str);
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ proto_item_set_len(item, (asn1->offset - saved_offset) + len);
+
+ if (len != 2)
+ {
+ proto_tree_add_text(subtree, asn1->tvb,
+ asn1->offset, len, "Unknown encoding of Problem Code");
+
+ asn1->offset += len;
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, 1, &type);
+ asn1_int32_value_decode(asn1, 1, &spec);
+
+ switch (type)
+ {
+ case 0: type_str = "Not used"; break;
+
+ case 1:
+ type_str = "General";
+ switch (spec)
+ {
+ case 1: str = "Unrecognized Component Type"; break;
+ case 2: str = "Incorrect Component Portion"; break;
+ case 3: str = "Badly Structured Component Portion"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 2:
+ type_str = "Invoke";
+ switch (spec)
+ {
+ case 1: str = "Duplicate Invoke ID"; break;
+ case 2: str = "Unrecognized Operation Code"; break;
+ case 3: str = "Incorrect Parameter"; break;
+ case 4: str = "Unrecognized Correlation ID"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 3:
+ type_str = "Return Result";
+ switch (spec)
+ {
+ case 1: str = "Unrecognized Correlation ID"; break;
+ case 2: str = "Unexpected Return Result"; break;
+ case 3: str = "Incorrect Parameter"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 4:
+ type_str = "Return Error";
+ switch (spec)
+ {
+ case 1: str = "Unrecognized Correlation ID"; break;
+ case 2: str = "Unexpected Return Error"; break;
+ case 3: str = "Unrecognized Error"; break;
+ case 4: str = "Unexpected Error"; break;
+ case 5: str = "Incorrect Parameter"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ case 5:
+ type_str = "Transaction Portion";
+ switch (spec)
+ {
+ case 1: str = "Unrecognized Package Type"; break;
+ case 2: str = "Incorrect Transaction Portion"; break;
+ case 3: str = "Badly Structured Transaction Portion"; break;
+ case 4: str = "Unrecognized Transaction ID"; break;
+ case 5: str = "Permission to Release"; break;
+ case 6: str = "Resource Unavailable"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+ break;
+
+ default:
+ type_str = "Undefined";
+ break;
+ }
+
+ if (spec == 255) { str = "Reserved"; }
+ else if (spec == 0) { str = "Not used"; }
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, 1, "Problem Type %s", type_str);
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset + 1, 1, "Problem Specifier %s", str);
+}
+
+
+static void
+dissect_ansi_error(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ proto_tree *subtree;
+ proto_item *item = NULL;
+ gchar *str = NULL;
+ gboolean def_len;
+
+
+#define TCAP_NAT_ERR_CODE_TAG 0xd3
+ if (tcap_check_tag(asn1, TCAP_NAT_ERR_CODE_TAG))
+ {
+ str = "National TCAP Error Code Identifier";
+ }
+#define TCAP_PRIV_ERR_CODE_TAG 0xd4
+ else if (tcap_check_tag(asn1, TCAP_PRIV_ERR_CODE_TAG))
+ {
+ str = "Private TCAP Error Code Identifier";
+ }
+ else
+ {
+ /* XXX */
+ return;
+ }
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb,
+ saved_offset, -1, "TCAP Error Code");
+
+ subtree = proto_item_add_subtree(item, ett_error);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, str);
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ proto_item_set_len(item, (asn1->offset - saved_offset) + len);
+
+ proto_tree_add_text(subtree, asn1->tvb, asn1->offset, len, "Error Code");
+
+ asn1->offset += len;
+}
+
+
+static void
+dissect_ansi_param(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ guint tag;
+ gboolean got_it = FALSE;
+ gboolean def_len;
+
+#define TCAP_PARAM_SET_TAG 0xf2
+ if (tcap_check_tag(asn1, TCAP_PARAM_SET_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Parameter Set Identifier");
+ got_it = TRUE;
+ }
+#define TCAP_PARAM_SEQ_TAG 0x30
+ else if (tcap_check_tag(asn1, TCAP_PARAM_SEQ_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Parameter Sequence Identifier");
+ got_it = TRUE;
+ }
+
+ if (got_it)
+ {
+ dissect_tcap_len(asn1, tree, &def_len, &len);
+
+ proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Parameter Data");
+
+ asn1->offset += len;
+ }
+}
+
+static void
+dissect_ansi_tcap_reject(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ proto_tree *subtree;
+
+#define COMPONENT_ID_TAG 0xcf
+ if (tcap_check_tag(asn1, COMPONENT_ID_TAG))
+ {
+ subtree = dissect_tcap_component(asn1, tree, &len);
+
+ switch (len)
+ {
+ case 1:
+ dissect_tcap_octet(asn1, subtree, "Correlation ID:");
+ break;
+ }
+ }
+
+ dissect_ansi_problem(asn1, tree);
+
+ dissect_ansi_param(asn1, tree);
+}
+
+static void
+dissect_ansi_tcap_re(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ proto_tree *subtree;
+
+#define COMPONENT_ID_TAG 0xcf
+ if (tcap_check_tag(asn1, COMPONENT_ID_TAG))
+ {
+ subtree = dissect_tcap_component(asn1, tree, &len);
+
+ switch (len)
+ {
+ case 1:
+ dissect_tcap_octet(asn1, tree, "Correlation ID:");
+ break;
+ }
+ }
+
+ dissect_ansi_error(asn1, tree);
+
+ dissect_ansi_param(asn1, tree);
+}
+
+static void
+dissect_ansi_tcap_rr(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ proto_tree *subtree;
+
+#define COMPONENT_ID_TAG 0xcf
+ if (tcap_check_tag(asn1, COMPONENT_ID_TAG))
+ {
+ subtree = dissect_tcap_component(asn1, tree, &len);
+
+ switch (len)
+ {
+ case 1:
+ dissect_tcap_octet(asn1, tree, "Correlation ID:");
+ break;
+ }
+ }
+
+ dissect_ansi_param(asn1, tree);
+}
+
+static void
+dissect_ansi_tcap_invoke(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint len;
+ proto_tree *subtree;
+
+#define COMPONENT_ID_TAG 0xcf
+ if (tcap_check_tag(asn1, COMPONENT_ID_TAG))
+ {
+ subtree = dissect_tcap_component(asn1, tree, &len);
+
+ switch (len)
+ {
+ case 1:
+ dissect_tcap_octet(asn1, tree, "Invoke ID:");
+ break;
+
+ case 2:
+ dissect_tcap_octet(asn1, tree, "Invoke ID:");
+ dissect_tcap_octet(asn1, tree, "Correlation ID:");
+ break;
+ }
+ }
+
+ dissect_ansi_opr_code(asn1, tree);
+
+ dissect_ansi_param(asn1, tree);
+}
+
+static void
+dissect_tcap_invoke(ASN1_SCK *asn1, proto_tree *tree)
+{
+ proto_tree *subtree;
+ guint orig_offset, saved_offset;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *item;
+ gboolean def_len;
+
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
+
+ subtree = proto_item_add_subtree(item, ett_component);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, "Invoke Type Tag");
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ saved_offset = asn1->offset;
+
+ dissect_tcap_invokeId(asn1, subtree);
+
+ dissect_tcap_lnkId(asn1, subtree);
+
+ dissect_tcap_opr_code(asn1, subtree);
+
+ if (def_len)
+ {
+ len -= asn1->offset - saved_offset;
+ }
+ else
+ {
+ len = tcap_find_eoc(asn1);
+ }
+
+ dissect_tcap_param(asn1, subtree, len);
+
+ if (!def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(item, asn1->offset - orig_offset);
+}
+
+static void
+dissect_tcap_rr(ASN1_SCK *asn1, proto_tree *tree, gchar *str)
+{
+ guint tag, len, comp_len;
+ guint orig_offset, saved_offset, len_offset;
+ proto_item *seq_item, *item;
+ proto_tree *seq_subtree, *subtree;
+ gboolean def_len;
+ gboolean comp_def_len;
+
+ tag = -1;
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
+
+ subtree = proto_item_add_subtree(item, ett_component);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, str);
+
+ dissect_tcap_len(asn1, subtree, &comp_def_len, &comp_len);
+
+ saved_offset = asn1->offset;
+
+ dissect_tcap_invokeId(asn1, subtree);
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
+ {
+ proto_item_set_len(item, asn1->offset - orig_offset);
+
+ return;
+ }
+
+ saved_offset = asn1->offset;
+
+ tag = -1;
+ asn1_id_decode1(asn1, &tag);
+
+ if (TCAP_CONSTRUCTOR(tag))
+ {
+ len_offset = asn1->offset;
+ asn1_length_decode(asn1, &def_len, &len);
+
+ seq_item =
+ proto_tree_add_text(subtree, asn1->tvb, saved_offset, -1, "Sequence");
+
+ seq_subtree = proto_item_add_subtree(seq_item, ett_params);
+
+ proto_tree_add_uint_format(seq_subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, len_offset - saved_offset, tag, "Sequence Tag");
+
+ if (def_len)
+ {
+ proto_tree_add_uint(seq_subtree, hf_tcap_length, asn1->tvb,
+ len_offset, asn1->offset - len_offset, len);
+ }
+ else
+ {
+ proto_tree_add_text(seq_subtree, asn1->tvb,
+ len_offset, asn1->offset - len_offset, "Length: Indefinite");
+
+ len = tcap_find_eoc(asn1);
+ }
+
+ proto_item_set_len(seq_item,
+ (asn1->offset - saved_offset) + len +
+ (def_len ? 0 : TCAP_EOC_LEN));
+
+ saved_offset = asn1->offset;
+
+ dissect_tcap_opr_code(asn1, seq_subtree);
+
+ len -= asn1->offset - saved_offset;
+
+ dissect_tcap_param(asn1, seq_subtree, len);
+
+ if (!def_len)
+ {
+ dissect_tcap_eoc(asn1, seq_subtree);
+ }
+ }
+
+ if (!comp_def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(item, asn1->offset - orig_offset);
+}
+
+static int
+dissect_tcap_re(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint tag, len, comp_len;
+ guint orig_offset, saved_offset;
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean comp_def_len, def_len;
+
+ tag = -1;
+ orig_offset = asn1->offset;
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item =
+ proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
+
+ subtree = proto_item_add_subtree(item, ett_component);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ tag, "Return Error Type Tag");
+
+ dissect_tcap_len(asn1, subtree, &comp_def_len, &comp_len);
+
+ if (!comp_def_len)
+ {
+ comp_len = tcap_find_eoc(asn1);
+ }
+
+ saved_offset = asn1->offset;
+
+ dissect_tcap_invokeId(asn1, subtree);
+
+#define TC_LOCAL_ERR_CODE_TAG 0x2
+#define TC_GBL_ERR_CODE_TAG 0x6
+ if (tcap_check_tag(asn1, TC_LOCAL_ERR_CODE_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, subtree, &tag, "Local Error Code Tag");
+ }
+ else if (tcap_check_tag(asn1, TC_GBL_ERR_CODE_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, subtree, &tag, "Global Error Code Tag");
+ }
+ else
+ {
+ proto_tree_add_text(subtree, asn1->tvb, asn1->offset, comp_len,
+ "Unknown Error Code");
+
+ asn1->offset += comp_len;
+
+ if (!comp_def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(item, asn1->offset - orig_offset);
+
+ return(TC_DS_OK);
+ }
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ dissect_tcap_integer(asn1, subtree, len, "Error Code:");
+
+ dissect_tcap_param(asn1, subtree, comp_len - (asn1->offset - saved_offset));
+
+ if (!comp_def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(item, asn1->offset - orig_offset);
+
+ return(TC_DS_OK);
+}
+
+static void
+dissect_tcap_reject(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint tag, comp_len;
+ guint saved_offset;
+ proto_item *item;
+ proto_tree *subtree;
+ gboolean def_len;
+
+ tag = -1;
+
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+
+ item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Component");
+
+ subtree = proto_item_add_subtree(item, ett_component);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset,
+ tag, "Reject Type Tag");
+
+ dissect_tcap_len(asn1, subtree, &def_len, &comp_len);
+
+ dissect_tcap_invokeId(asn1, subtree);
+
+ dissect_tcap_problem(asn1, subtree);
+
+ if (!def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(item, asn1->offset - saved_offset);
+}
+
+static void
+dissect_ansi_tcap_next_tvb(ASN1_SCK *asn1, guint len, proto_tree *tree)
+{
+ tvbuff_t *next_tvb;
+ guint saved_offset;
+ int ret;
+ gboolean flag = TRUE;
+ guint tag;
+ proto_item *item, *tag_item;
+ proto_tree *subtree, *tag_subtree;
+ gboolean def_len;
+
+
+ if (lock_info_col) col_set_fence(g_pinfo->cinfo, COL_INFO);
+
+ next_tvb = tvb_new_subset(asn1->tvb, asn1->offset, len, len);
+
+ /* process components data */
+ if (!dissector_try_port(tcap_ansi_ssn_dissector_table, g_pinfo->match_port, next_tvb, g_pinfo, g_tcap_tree))
+ {
+ /* dissect cmp */
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ /*
+ * verify tag type is known
+ */
+ switch (tag)
+ {
+ case ANSI_TC_INVOKE_L :
+ case ANSI_TC_RRL :
+ case ANSI_TC_RE :
+ case ANSI_TC_REJECT :
+ case ANSI_TC_INVOKE_N :
+ case ANSI_TC_RRN :
+ flag = TRUE;
+ break;
+
+ default:
+ flag = FALSE;
+ break;
+ }
+
+ if (flag != FALSE)
+ {
+ item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Components");
+ subtree = proto_item_add_subtree(item, ett_component);
+
+ switch (tag)
+ {
+ case ANSI_TC_INVOKE_L :
+ tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset, tag, "Invoke(Last)");
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ tag_subtree = proto_item_add_subtree(tag_item, ett_component);
+
+ dissect_ansi_tcap_invoke(asn1, tag_subtree);
+ break;
+ case ANSI_TC_RRL :
+ tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset, tag, "Return Result(Last)");
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ tag_subtree = proto_item_add_subtree(tag_item, ett_component);
+
+ dissect_ansi_tcap_rr(asn1, tag_subtree);
+ break;
+ case ANSI_TC_RE :
+ tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset, tag, "Return Error");
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ tag_subtree = proto_item_add_subtree(tag_item, ett_component);
+
+ dissect_ansi_tcap_re(asn1, tag_subtree);
+ break;
+ case ANSI_TC_REJECT :
+ tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset, tag, "Reject");
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ tag_subtree = proto_item_add_subtree(tag_item, ett_component);
+
+ dissect_ansi_tcap_reject(asn1, tag_subtree);
+ break;
+ case ANSI_TC_INVOKE_N :
+ tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset, tag, "Invoke(Not Last)");
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ tag_subtree = proto_item_add_subtree(tag_item, ett_component);
+
+ dissect_ansi_tcap_invoke(asn1, tag_subtree);
+ break;
+ case ANSI_TC_RRN :
+ tag_item = proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset, tag, "Return Result(Not Last)");
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ tag_subtree = proto_item_add_subtree(tag_item, ett_component);
+
+ dissect_ansi_tcap_rr(asn1, tag_subtree);
+ break;
+ }
+
+ proto_item_set_len(item, asn1->offset - saved_offset);
+ }
+ }
+
+ if (!flag)
+ {
+ /* No sub-dissection occured, treat it as raw data */
+ call_dissector(data_handle, next_tvb, g_pinfo, g_tcap_tree);
+ }
+}
+
+static int
+dissect_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree)
+{
+ proto_tree *subtree;
+ proto_item *comps_item;
+ guint saved_offset, comps_start;
+ guint len, comp_len;
+ gint keep_len;
+ gboolean comps_def_len, def_len;
+ guint tag;
+ int ret;
+ tvbuff_t *next_tvb;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
+ {
+ return TC_DS_FAIL;
+ }
+
+ comps_start = asn1->offset;
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ if (ST_ITU_CMP_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+
+ comps_item =
+ proto_tree_add_text(tcap_tree, asn1->tvb,
+ saved_offset, -1, "Components Portion");
+
+ subtree = proto_item_add_subtree(comps_item, ett_comps_portion);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset,
+ asn1->offset - saved_offset, tag, "Component Portion Tag");
+
+ dissect_tcap_len(asn1, subtree, &comps_def_len, &len);
+
+ if (comps_def_len)
+ {
+ proto_item_set_len(comps_item, (asn1->offset - comps_start) + len);
+ }
+
+ if (lock_info_col) col_set_fence(g_pinfo->cinfo, COL_INFO);
+
+ /* call next dissector for EACH component */
+
+ keep_len =
+ (comps_def_len ? 0 : TCAP_EOC_LEN) +
+ (g_tcap_ends_def_len ? 0 : TCAP_EOC_LEN);
+
+ while (tvb_length_remaining(asn1->tvb, asn1->offset) > keep_len)
+ {
+ /* peek at tag and length */
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ comp_len = 0;
+ def_len = FALSE;
+ ret = asn1_length_decode(asn1, &def_len, &comp_len);
+
+ if (def_len)
+ {
+ comp_len += (asn1->offset - saved_offset);
+ }
+ else
+ {
+ comp_len = (asn1->offset - saved_offset) + tcap_find_eoc(asn1) + TCAP_EOC_LEN;
+ }
+
+ next_tvb = tvb_new_subset(asn1->tvb, saved_offset, comp_len, comp_len);
+ asn1->offset = saved_offset;
+
+ /* process component data */
+ if (dissector_try_port(tcap_itu_ssn_dissector_table, g_pinfo->match_port, next_tvb, g_pinfo, g_tcap_tree))
+ {
+ proto_tree_add_text(subtree, asn1->tvb, asn1->offset, comp_len, "Component");
+
+ asn1->offset += comp_len;
+ }
+ else
+ {
+ switch (tag)
+ {
+ case TCAP_COMP_INVOKE :
+ dissect_tcap_invoke(asn1, subtree);
+ break;
+ case TCAP_COMP_RRL :
+ dissect_tcap_rr(asn1, subtree, "Return Result(Last) Type Tag");
+ break;
+ case TCAP_COMP_RE :
+ dissect_tcap_re(asn1, subtree);
+ break;
+ case TCAP_COMP_REJECT :
+ dissect_tcap_reject(asn1, subtree);
+ break;
+ case TCAP_COMP_RRN :
+ /* same definition as RRL */
+ dissect_tcap_rr(asn1, subtree, "Return Result(Not Last) Type Tag");
+ break;
+ default:
+ /* treat it as raw data */
+ call_dissector(data_handle, next_tvb, g_pinfo, g_tcap_tree);
+ break;
+ }
+ }
+ }
+
+ if (!comps_def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+
+ proto_item_set_len(comps_item, asn1->offset - comps_start);
+ }
+
+ return TC_DS_OK;
+}
+
+/* dissect dialog portion */
+static int
+dissect_tcap_dlg_protocol_version(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ gboolean def_len;
+
+#define TC_DLG_PROTO_VER_TAG 0x80
+ if (tcap_check_tag(asn1, TC_DLG_PROTO_VER_TAG))
+ {
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+ proto_tree_add_uint_format(tcap_tree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag,
+ "Protocol Version Tag: 0x%x", tag);
+
+ dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
+ saved_offset = asn1->offset;
+ ti =
+ proto_tree_add_bytes(tcap_tree, hf_tcap_bytes, asn1->tvb, saved_offset, len,
+ (guchar*)(tvb_get_ptr(asn1->tvb, saved_offset, len)));
+ asn1->offset += len;
+ }
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_dlg_application_context_name(ASN1_SCK *asn1, proto_tree *tcap_tree)
+{
+ guint saved_offset = 0;
+ guint name_len, len, len2;
+ guint tag;
+ subid_t *oid;
+ int ret;
+ gboolean def_len;
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+ proto_tree_add_uint_format(tcap_tree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
+ "Application Context Name Tag: 0x%x", tag);
+
+ dissect_tcap_len(asn1, tcap_tree, &def_len, &name_len);
+
+ saved_offset = asn1->offset;
+ ret = asn1_oid_decode (asn1, &oid, &len, &len2);
+ proto_tree_add_bytes(tcap_tree, hf_tcap_app_con_name, asn1->tvb, saved_offset, len2, tvb_get_ptr(asn1->tvb, saved_offset, len2));
+ if (ret == ASN1_ERR_NOERROR) g_free(oid);
+
+ if (!def_len)
+ {
+ /* for Application Context Name Tag */
+ dissect_tcap_eoc(asn1, tcap_tree);
+ }
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_dlg_result(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint tag, rtag_len, itag_len;
+ guint saved_offset = 0;
+ gint32 value;
+ gchar *str;
+ gboolean def_len;
+ gboolean rtag_def_len;
+
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Result Tag");
+
+ dissect_tcap_len(asn1, tree, &rtag_def_len, &rtag_len);
+
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Integer Tag");
+
+ dissect_tcap_len(asn1, tree, &def_len, &itag_len);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, itag_len, &value);
+
+ switch (value)
+ {
+ case 0x00: str = "Accepted"; break;
+ case 0x01: str = "Reject-permanent"; break;
+ default: str = "Unknown value"; break;
+ }
+
+ proto_tree_add_int_format(tree, hf_tcap_int, asn1->tvb, saved_offset, asn1->offset - saved_offset,
+ value, "%s %d", str, value);
+
+ if (!rtag_def_len)
+ {
+ /* for Result Tag */
+ dissect_tcap_eoc(asn1, tree);
+ }
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_dlg_result_src_diag(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint saved_offset = 0;
+ guint len, tag;
+ gint32 value;
+ gboolean user;
+ gchar *str;
+ gboolean def_len;
+ gboolean serv_def_len;
+ gboolean diag_def_len;
+
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Result Source Diagnostic Tag");
+
+ dissect_tcap_len(asn1, tree, &diag_def_len, &len);
+
+#define TC_DIAG_SERV_USER_TAG 0xa1
+#define TC_DIAG_SERV_PROV_TAG 0xa2
+ if (tcap_check_tag(asn1, TC_DIAG_SERV_USER_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Dialogue Service User Tag");
+ user = TRUE;
+ }
+ else if (tcap_check_tag(asn1, TC_DIAG_SERV_PROV_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Dialogue Service Provider Tag");
+ user = FALSE;
+ }
+ else
+ {
+ proto_tree_add_text(tree, asn1->tvb, asn1->offset, len,
+ "Unknown Result Source Diagnostic");
+
+ asn1->offset += len;
+ return(TC_DS_OK);
+ }
+
+ dissect_tcap_len(asn1, tree, &serv_def_len, &len);
+
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "Integer Tag");
+
+ dissect_tcap_len(asn1, tree, &def_len, &len);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ if (user)
+ {
+ switch (value)
+ {
+ case 0x00: str = "Null"; break;
+ case 0x01: str = "No reason given"; break;
+ case 0x02: str = "Application Context Name not supplied"; break;
+ default: str = "Unknown value"; break;
+ }
+ }
+ else
+ {
+ switch (value)
+ {
+ case 0x00: str = "Null"; break;
+ case 0x01: str = "No reason given"; break;
+ case 0x02: str = "No common dialogue portion"; break;
+ default: str = "Unknown value"; break;
+ }
+ }
+
+ proto_tree_add_int_format(tree, hf_tcap_int, asn1->tvb, saved_offset, asn1->offset - saved_offset,
+ value, "%s %d", str, value);
+
+ if (!serv_def_len)
+ {
+ /* for Dialogue Service User/Provider Tag */
+ dissect_tcap_eoc(asn1, tree);
+ }
+
+ if (!diag_def_len)
+ {
+ /* for Result Source Diagnostic Tag */
+ dissect_tcap_eoc(asn1, tree);
+ }
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_dlg_user_info(ASN1_SCK *asn1, proto_tree *tree)
+{
+ guint tag, len;
+ guint saved_offset = 0;
+ gboolean def_len;
+ gboolean user_info_def_len;
+
+#define TC_USR_INFO_TAG 0xbe
+ if (tcap_check_tag(asn1, TC_USR_INFO_TAG))
+ {
+ tag = -1;
+ dissect_tcap_tag(asn1, tree, &tag, "User Info Tag");
+ dissect_tcap_len(asn1, tree, &user_info_def_len, &len);
+
+#define TC_EXT_TAG 0x28
+ if (tcap_check_tag(asn1, TC_EXT_TAG))
+ {
+ saved_offset = asn1->offset;
+ asn1_id_decode1(asn1, &tag);
+ proto_tree_add_uint_format(tree, hf_tcap_length, asn1->tvb, saved_offset, asn1->offset - saved_offset,
+ tag, "External Tag: 0x%x", tag);
+
+ dissect_tcap_len(asn1, tree, &def_len, &len);
+ }
+
+ proto_tree_add_text(tree, asn1->tvb, asn1->offset, len, "Parameter Data");
+ asn1->offset += len;
+
+ if (!user_info_def_len)
+ {
+ /* for User Information Tag */
+ dissect_tcap_eoc(asn1, tree);
+ }
+ }
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_dlg_req(ASN1_SCK *asn1, proto_tree *tcap_tree)
+{
+ proto_tree *subtree;
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *req_item;
+ guint req_start = asn1->offset;
+ gboolean def_len;
+
+ /* dissect dialog portion */
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+ req_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Dialogue Request");
+ subtree = proto_item_add_subtree(req_item, ett_dlg_req);
+ proto_tree_add_uint(subtree, hf_tcap_dlg_type, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag);
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ dissect_tcap_dlg_protocol_version(asn1, subtree, NULL);
+
+ dissect_tcap_dlg_application_context_name(asn1, subtree);
+
+ dissect_tcap_dlg_user_info(asn1, subtree);
+
+ /* decode end of sequence */
+
+ if (!def_len)
+ {
+ /* for Dialogue Request Tag */
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(req_item, asn1->offset - req_start);
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_dlg_rsp(ASN1_SCK *asn1, proto_tree *tcap_tree)
+{
+ proto_tree *subtree;
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *req_item;
+ guint req_start = asn1->offset;
+ gboolean def_len;
+
+ /* dissect dialog portion */
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+ req_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Dialogue Response");
+ subtree = proto_item_add_subtree(req_item, ett_dlg_rsp);
+ proto_tree_add_uint(subtree, hf_tcap_dlg_type, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag);
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ dissect_tcap_dlg_protocol_version(asn1, subtree, NULL);
+
+ dissect_tcap_dlg_application_context_name(asn1, subtree);
+
+ /* result */
+ dissect_tcap_dlg_result(asn1, subtree);
+
+ /* result source diag */
+ dissect_tcap_dlg_result_src_diag(asn1, subtree);
+
+ dissect_tcap_dlg_user_info(asn1, subtree);
+
+ if (!def_len)
+ {
+ /* for Dialogue Response Tag */
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(req_item, asn1->offset - req_start);
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_dlg_abrt(ASN1_SCK *asn1, proto_tree *tree)
+{
+ proto_tree *subtree;
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *req_item;
+ gint32 value;
+ gchar *str;
+ gboolean def_len, abort_def_len;
+
+ /* dissect dialog pabort portion */
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+ req_item = proto_tree_add_text(tree, asn1->tvb, saved_offset, -1, "Dialogue Abort");
+ subtree = proto_item_add_subtree(req_item, ett_dlg_abort );
+ proto_tree_add_uint(subtree, hf_tcap_dlg_type, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag);
+
+ dissect_tcap_len(asn1, subtree, &abort_def_len, &len);
+
+ tag = -1;
+ dissect_tcap_tag(asn1, subtree, &tag, "Abort Source Tag");
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ switch (value)
+ {
+ case 0x00: str = "Dialogue Service User"; break;
+ case 0x01: str = "Dialogue Service Provider"; break;
+ default: str = "Unknown value"; break;
+ }
+
+ proto_tree_add_int_format(subtree, hf_tcap_int, asn1->tvb, saved_offset, asn1->offset - saved_offset,
+ value, "Abort Source: %s %d", str, value);
+
+ dissect_tcap_dlg_user_info(asn1, subtree);
+
+ if (!abort_def_len)
+ {
+ /* for Dialogue Abort Tag */
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_tcap_dialog_portion(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
+{
+ proto_tree *subtree;
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *dlg_item;
+ guint dlg_start = asn1->offset;
+ gboolean def_len, ext_tag_def_len, portion_def_len;
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
+ {
+ return TC_DS_FAIL;
+ }
+
+ /* dissect dialog portion */
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ /* error handling */
+ if (ST_ITU_DLG_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+
+ dlg_item =
+ proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Dialogue Portion");
+
+ subtree = proto_item_add_subtree(dlg_item, ett_dlg_portion);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag, "Dialogue Portion Tag");
+
+ dissect_tcap_len(asn1, subtree, &portion_def_len, &len);
+
+ if (portion_def_len)
+ {
+ proto_item_set_len(dlg_item, len);
+ }
+
+ ext_tag_def_len = FALSE;
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+#define TC_EXT_TAG 0x28
+ if (TC_EXT_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ }
+ else
+ {
+ proto_tree_add_uint_format(subtree, hf_tcap_length, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag,
+ "External Tag: 0x%x", tag);
+
+ dissect_tcap_len(asn1, subtree, &ext_tag_def_len, &len);
+ }
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+#define TC_OID_TAG 0x06
+ if (TC_OID_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ }
+ else
+ {
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag,
+ "Object Identifier Tag");
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ saved_offset = asn1->offset;
+ ti =
+ proto_tree_add_bytes(subtree, hf_tcap_bytes, asn1->tvb, saved_offset, len,
+ (guchar*)(tvb_get_ptr(asn1->tvb, saved_offset, len)));
+
+ asn1->offset += len;
+ }
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag,
+ "Single-ASN.1-type Tag");
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ proto_item_set_len(dlg_item, asn1->offset - dlg_start);
+
+ /* dialogue PDU */
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+ asn1->offset = saved_offset;
+
+ switch(tag)
+ {
+ case TC_DLG_REQ:
+ dissect_tcap_dlg_req(asn1, subtree);
+ break;
+ case TC_DLG_RSP:
+ dissect_tcap_dlg_rsp(asn1, subtree);
+ break;
+ case TC_DLG_ABRT:
+ dissect_tcap_dlg_abrt(asn1, subtree);
+ break;
+ default:
+ break;
+ }
+
+ /* decode end of sequence */
+
+ if (!def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ if (!ext_tag_def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ if (!portion_def_len)
+ {
+ dissect_tcap_eoc(asn1, subtree);
+ }
+
+ proto_item_set_len(dlg_item, asn1->offset - dlg_start);
+
+ return TC_DS_OK;
+}
+
+/* dissect reason */
+static int
+dissect_tcap_abort_reason(ASN1_SCK *asn1, proto_tree *tcap_tree)
+{
+ guint saved_offset = 0;
+ guint tag, len;
+ proto_tree *subtree;
+ proto_item *item;
+ gint32 value;
+ gchar *str = NULL;
+ gboolean def_len;
+
+#define TC_PABRT_REASON_TAG 0x4a
+ tag = TC_PABRT_REASON_TAG;
+ if (tcap_check_tag(asn1, tag))
+ {
+ saved_offset = asn1->offset;
+ item =
+ proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "PAbort Cause");
+
+ subtree = proto_item_add_subtree(item, ett_reason);
+
+ tag = -1;
+ dissect_tcap_tag(asn1, subtree, &tag, "PAbort Cause Tag");
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ proto_item_set_len(item, (asn1->offset - saved_offset) + len);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ switch (value)
+ {
+ case 0x00: str = "Unrecognized Message Type"; break;
+ case 0x01: str = "Unrecognized Transaction ID"; break;
+ case 0x02: str = "Badly Formatted Transaction Portion"; break;
+ case 0x03: str = "Incorrect Transaction Portion"; break;
+ case 0x04: str = "Resource Limitation"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "Cause Value %s (%d)",
+ str, value);
+ }
+
+ return TC_DS_OK;
+}
+
+/* dissect each type of message */
+
+static void
+dissect_tcap_unidirectional(ASN1_SCK *asn1, proto_tree *tcap_tree)
+{
+
+ dissect_tcap_dialog_portion(asn1, tcap_tree, NULL);
+
+ dissect_tcap_components(asn1, tcap_tree);
+}
+
+static void
+dissect_tcap_begin(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
+{
+
+ dissect_tcap_tid(asn1, tcap_tree, ti, ST_TID_SOURCE);
+
+ dissect_tcap_dialog_portion(asn1, tcap_tree, NULL);
+
+ dissect_tcap_components(asn1, tcap_tree);
+}
+
+static void
+dissect_tcap_continue(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
+{
+
+ dissect_tcap_tid(asn1, tcap_tree, ti, ST_TID_SOURCE);
+
+ dissect_tcap_tid(asn1, tcap_tree, ti, ST_TID_DEST);
+
+ dissect_tcap_dialog_portion(asn1, tcap_tree, NULL);
+
+ dissect_tcap_components(asn1, tcap_tree);
+
+}
+
+static void
+dissect_tcap_end(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
+{
+
+ dissect_tcap_tid(asn1, tcap_tree, ti, ST_TID_DEST);
+
+ dissect_tcap_dialog_portion(asn1, tcap_tree, NULL);
+
+ dissect_tcap_components(asn1, tcap_tree);
+}
+
+static void
+dissect_tcap_abort(ASN1_SCK *asn1, proto_tree *tree, proto_item *ti)
+{
+
+ dissect_tcap_tid(asn1, tree, ti, ST_TID_DEST);
+
+ dissect_tcap_abort_reason(asn1, tree);
+
+ dissect_tcap_dialog_portion(asn1, tree, NULL);
+}
+
+/* Samuel */
+static void
+dissect_tcap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tcap_tree)
+{
+ ASN1_SCK asn1;
+ guint msg_type_tag;
+ proto_item *ti;
+ guint offset = 0;
+ guint saved_offset = 0;
+ guint len;
+ gchar *str = NULL;
+
+ asn1_open(&asn1, tvb, offset);
+
+ asn1_id_decode1(&asn1, &msg_type_tag);
+
+ str = match_strval(msg_type_tag, msg_type_strings);
+
+ if (str == NULL)
+ {
+ proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1, "Unknown message type, ignoring");
+ return;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_set_str(pinfo->cinfo, COL_INFO, str);
+ col_append_str(pinfo->cinfo, COL_INFO, " ");
+ }
+
+ proto_tree_add_uint_hidden(tcap_tree, hf_tcap_ssn, asn1.tvb, offset,
+ 0, pinfo->match_port); /* len -1 is unacceptable */
+
+ ti = proto_tree_add_uint(tcap_tree, hf_tcap_message_type, asn1.tvb, offset, asn1.offset - saved_offset,
+ msg_type_tag);
+
+ dissect_tcap_len(&asn1, tcap_tree, &g_tcap_ends_def_len, &len);
+
+ switch(msg_type_tag)
+ {
+ case ST_MSG_TYP_UNI:
+ dissect_tcap_unidirectional(&asn1, tcap_tree);
+ break;
+ case ST_MSG_TYP_BGN:
+ dissect_tcap_begin(&asn1, tcap_tree, ti);
+ break;
+ case ST_MSG_TYP_CNT:
+ dissect_tcap_continue(&asn1, tcap_tree, ti);
+ break;
+ case ST_MSG_TYP_END:
+ dissect_tcap_end(&asn1, tcap_tree, ti);
+ break;
+ case ST_MSG_TYP_PABT:
+ dissect_tcap_abort(&asn1, tcap_tree, ti);
+ break;
+ default:
+ proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1,
+ "Message type not handled, ignoring");
+ break;
+ }
+
+ if (!g_tcap_ends_def_len)
+ {
+ dissect_tcap_eoc(&asn1, tcap_tree);
+ }
+
+ asn1_close(&asn1, &saved_offset);
+}
+
+static int
+dissect_ansi_tcap_components(ASN1_SCK *asn1, proto_tree *tcap_tree)
+{
+ proto_tree *subtree;
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *cmp_item;
+ guint cmp_start = asn1->offset;
+ gboolean def_len;
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ if (ST_ANSI_CMP_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+
+ cmp_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Components Portion");
+
+ subtree = proto_item_add_subtree(cmp_item, ett_comps_portion);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
+ "Component Sequence Identifier");
+
+ dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
+
+ /* call next dissector */
+
+ dissect_ansi_tcap_next_tvb(asn1, len, subtree);
+
+ proto_item_set_len(cmp_item, asn1->offset - cmp_start);
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_ansi_tcap_unidirectional(ASN1_SCK *asn1, proto_tree *tcap_tree)
+{
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *trans_item;
+ guint trans_start = asn1->offset;
+ gboolean def_len;
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ if (ST_ANSI_TID_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+
+ trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion");
+
+ dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
+
+ if (len != 0)
+ {
+ return TC_DS_FAIL;
+ }
+
+ proto_item_set_len(trans_item, asn1->offset - trans_start);
+
+ dissect_ansi_tcap_components(asn1, tcap_tree);
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_ansi_tcap_qwp_qwop(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
+{
+ proto_tree *subtree;
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *trans_item;
+ guint trans_start = asn1->offset;
+ guchar *poctets;
+ guint32 val;
+ gboolean def_len;
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ if (ST_ANSI_TID_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+
+ trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion");
+ subtree = proto_item_add_subtree(trans_item, ett_dlg_portion);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
+ "Originating Transaction ID Identifier");
+
+ dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
+
+ if (len != 4)
+ {
+ return TC_DS_FAIL;
+ }
+
+ saved_offset = asn1->offset;
+ ret = asn1_string_value_decode(asn1, len, &poctets);
+ val = 0;
+ memcpy(&val, poctets, len);
+ ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
+ g_free(poctets);
+
+ if (check_col(g_pinfo->cinfo, COL_INFO))
+ col_append_fstr(g_pinfo->cinfo, COL_INFO, "otid(%x) ", val);
+
+ proto_item_set_len(trans_item, asn1->offset - trans_start);
+
+ dissect_ansi_tcap_components(asn1, tcap_tree);
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_ansi_tcap_abort(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
+{
+ proto_tree *subtree;
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *trans_item;
+ guint trans_start = asn1->offset;
+ guchar *poctets;
+ guint32 val;
+ gint32 value;
+ gboolean def_len;
+ gchar *str;
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ if (ST_ANSI_TID_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+
+ trans_item =
+ proto_tree_add_text(tcap_tree, asn1->tvb,
+ saved_offset, -1, "Transaction Portion");
+
+ subtree = proto_item_add_subtree(trans_item, ett_dlg_portion);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, tag,
+ "Responding Transaction ID Identifier");
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ if (len != 4)
+ {
+ return TC_DS_FAIL;
+ }
+
+ saved_offset = asn1->offset;
+ ret = asn1_string_value_decode(asn1, len, &poctets);
+
+ val = 0;
+ memcpy(&val, poctets, len);
+ ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
+ g_free(poctets);
+
+ if (check_col(g_pinfo->cinfo, COL_INFO))
+ col_append_fstr(g_pinfo->cinfo, COL_INFO, "rtid(%x) ", val);
+
+ proto_item_set_len(trans_item, asn1->offset - trans_start);
+
+ if (tvb_length_remaining(asn1->tvb, asn1->offset) <= 0)
+ {
+ proto_tree_add_text(tcap_tree, asn1->tvb, asn1->offset, -1,
+ "!!! Missing Component Portion !!!");
+
+ return TC_DS_FAIL;
+ }
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+#define ANSI_TC_PABRT_CAUSE_TAG 0xd7
+ if (tag == ANSI_TC_PABRT_CAUSE_TAG)
+ {
+ trans_item =
+ proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "P-Abort Portion");
+
+ subtree = proto_item_add_subtree(trans_item, ett_dlg_abort);
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+
+ proto_item_set_len(trans_item, (asn1->offset - saved_offset) + len);
+
+ saved_offset = asn1->offset;
+ asn1_int32_value_decode(asn1, len, &value);
+
+ switch (value)
+ {
+ case 1: str = "Unrecognized Package Type"; break;
+ case 2: str = "Incorrect Transaction Portion"; break;
+ case 3: str = "Badly Structured Transaction Portion"; break;
+ case 4: str = "Unrecognized Transaction ID"; break;
+ case 5: str = "Permission to Release"; break;
+ case 6: str = "Resource Unavailable"; break;
+ default:
+ str = "Undefined";
+ break;
+ }
+
+ proto_tree_add_text(subtree, asn1->tvb,
+ saved_offset, asn1->offset - saved_offset, "P-Abort Cause Value %s (%d)",
+ str, value);
+ }
+#define ANSI_TC_UABRT_INFO_TAG 0xd8
+ else if (tag == ANSI_TC_UABRT_INFO_TAG)
+ {
+ trans_item =
+ proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "U-Abort Portion");
+
+ subtree = proto_item_add_subtree(trans_item, ett_dlg_abort);
+
+ dissect_tcap_len(asn1, subtree, &def_len, &len);
+ if (len > 0)
+ {
+ dissect_tcap_integer(asn1, subtree, len, "User Abort Information:");
+ }
+ }
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_ansi_tcap_rsp(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
+{
+ proto_tree *subtree;
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *trans_item;
+ guint trans_start = asn1->offset;
+ guchar *poctets;
+ guint32 val;
+ gboolean def_len;
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ if (ST_ANSI_TID_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+
+ trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion");
+ subtree = proto_item_add_subtree(trans_item, ett_dlg_portion);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
+ "Responding Transaction ID Identifier");
+
+ dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
+
+ if (len != 4)
+ {
+ return TC_DS_FAIL;
+ }
+
+ saved_offset = asn1->offset;
+ ret = asn1_string_value_decode(asn1, len, &poctets);
+ val = 0;
+ memcpy(&val, poctets, len);
+ ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
+ g_free(poctets);
+
+ if (check_col(g_pinfo->cinfo, COL_INFO))
+ col_append_fstr(g_pinfo->cinfo, COL_INFO, "rtid(%x) ", val);
+
+ proto_item_set_len(trans_item, asn1->offset - trans_start);
+
+ dissect_ansi_tcap_components(asn1, tcap_tree);
+
+ return TC_DS_OK;
+}
+
+static int
+dissect_ansi_tcap_cwp_cwop(ASN1_SCK *asn1, proto_tree *tcap_tree, proto_item *ti)
+{
+ proto_tree *subtree;
+ guint saved_offset = 0;
+ guint len;
+ guint tag;
+ int ret;
+ proto_item *trans_item;
+ guint trans_start = asn1->offset;
+ guchar *poctets;
+ guint32 val;
+ gboolean def_len;
+
+ saved_offset = asn1->offset;
+ ret = asn1_id_decode1(asn1, &tag);
+
+ if (ST_ANSI_TID_TAG != tag)
+ {
+ asn1->offset = saved_offset;
+ return TC_DS_FAIL;
+ }
+
+ trans_item = proto_tree_add_text(tcap_tree, asn1->tvb, saved_offset, -1, "Transaction Portion");
+ subtree = proto_item_add_subtree(trans_item, ett_dlg_portion);
+
+ proto_tree_add_uint_format(subtree, hf_tcap_tag, asn1->tvb, saved_offset, asn1->offset - saved_offset, tag,
+ "Transaction ID Identifier");
+
+ dissect_tcap_len(asn1, tcap_tree, &def_len, &len);
+
+ if (len != 8)
+ {
+ return TC_DS_FAIL;
+ }
+
+ saved_offset = asn1->offset;
+ ret = asn1_string_value_decode(asn1, 4, &poctets);
+ val = 0;
+ memcpy(&val, poctets, 4);
+ ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
+ g_free(poctets);
+
+ if (check_col(g_pinfo->cinfo, COL_INFO))
+ col_append_fstr(g_pinfo->cinfo, COL_INFO, "otid(%x) ", val);
+
+ saved_offset = asn1->offset;
+ ret = asn1_string_value_decode(asn1, 4, &poctets);
+ val = 0;
+ memcpy(&val, poctets, 4);
+ ti = proto_tree_add_uint(subtree, hf_tcap_id, asn1->tvb, saved_offset, asn1->offset - saved_offset, val);
+ g_free(poctets);
+
+ if (check_col(g_pinfo->cinfo, COL_INFO))
+ col_append_fstr(g_pinfo->cinfo, COL_INFO, "rtid(%x) ", val);
+
+ proto_item_set_len(trans_item, asn1->offset - trans_start);
+
+ dissect_ansi_tcap_components(asn1, tcap_tree);
+
+ return TC_DS_OK;
+}
+
+static void
+dissect_ansi_tcap_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tcap_tree)
+{
+ ASN1_SCK asn1;
+ guint msg_type_tag;
+ proto_item *ti;
+ guint offset = 0;
+ guint saved_offset = 0;
+ guint len;
+ gchar *str = NULL;
+ gboolean def_len;
+
+ asn1_open(&asn1, tvb, offset);
+
+ asn1_id_decode1(&asn1, &msg_type_tag);
+
+ str = match_strval(msg_type_tag, ansi_msg_type_strings);
+
+ if (str == NULL)
+ {
+ proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1, "Unknown message type, ignoring");
+ return;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_set_str(pinfo->cinfo, COL_INFO, str);
+ col_append_str(pinfo->cinfo, COL_INFO, " ");
+ }
+
+ proto_tree_add_uint_hidden(tcap_tree, hf_tcap_ssn, asn1.tvb, offset,
+ 0, pinfo->match_port); /* len -1 is unacceptable */
+
+ ti = proto_tree_add_uint(tcap_tree, hf_ansi_tcap_message_type, asn1.tvb, offset, asn1.offset - saved_offset,
+ msg_type_tag);
+
+ dissect_tcap_len(&asn1, tcap_tree, &def_len, &len);
+
+ switch(msg_type_tag)
+ {
+ case ANSI_ST_MSG_TYP_UNI:
+ dissect_ansi_tcap_unidirectional(&asn1, tcap_tree);
+ break;
+ case ANSI_ST_MSG_TYP_QWP:
+ dissect_ansi_tcap_qwp_qwop(&asn1, tcap_tree, ti);
+ break;
+ case ANSI_ST_MSG_TYP_QWOP:
+ dissect_ansi_tcap_qwp_qwop(&asn1, tcap_tree, ti);
+ break;
+ case ANSI_ST_MSG_TYP_RSP:
+ dissect_ansi_tcap_rsp(&asn1, tcap_tree, ti);
+ break;
+ case ANSI_ST_MSG_TYP_CWP:
+ dissect_ansi_tcap_cwp_cwop(&asn1, tcap_tree, ti);
+ break;
+ case ANSI_ST_MSG_TYP_CWOP:
+ dissect_ansi_tcap_cwp_cwop(&asn1, tcap_tree, ti);
+ break;
+ case ANSI_ST_MSG_TYP_ABT:
+ dissect_ansi_tcap_abort(&asn1, tcap_tree, ti);
+ break;
+ default:
+ proto_tree_add_text(tcap_tree, asn1.tvb, offset, -1,
+ "Message type not handled, ignoring");
+ break;
+ }
+
+ asn1_close(&asn1, &saved_offset);
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_tcap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *tcap_tree;
+
+ g_pinfo = pinfo;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCAP");
+
+ /* In the interest of speed, if "tree" is NULL, don't do any
+ * work not necessary to generate protocol tree items.
+ */
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_tcap, tvb, 0, -1, FALSE);
+ tcap_tree = proto_item_add_subtree(ti, ett_tcap);
+ g_tcap_tree = tree;
+
+ if (tcap_standard == ITU_TCAP_STANDARD)
+ {
+ dissect_tcap_message(tvb, pinfo, tcap_tree);
+ }
+ else
+ {
+ dissect_ansi_tcap_message(tvb, pinfo, tcap_tree);
+ }
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+
+/* this format is require because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+void
+proto_register_tcap(void)
+{
+
+/* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ /*{ &hf_tcap_FIELDABBREV,
+ { "FIELDNAME", "PROTOABBREV.FIELDABBREV",
+ FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
+ "FIELDDESCR" }
+ },*/
+ { &hf_tcap_tag,
+ { "Tag", "tcap.msgtype",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_tcap_length,
+ { "Length", "tcap.len",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_tcap_id,
+ { "Value", "tcap.id",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ "", HFILL }
+ },
+ { &hf_tcap_message_type,
+ { "Message Type", "tcap.msgtype",
+ FT_UINT8, BASE_HEX, VALS(msg_type_strings), 0,
+ "", HFILL }
+ },
+ { &hf_ansi_tcap_message_type,
+ { "Message Type", "tcap.msgtype",
+ FT_UINT8, BASE_HEX, VALS(ansi_msg_type_strings), 0,
+ "", HFILL }
+ },
+ { &hf_tcap_tid,
+ { "Transaction Id", "tcap.tid",
+ FT_UINT32, BASE_DEC, VALS(tid_strings), 0,
+ "", HFILL }
+ },
+ { &hf_tcap_ssn,
+ { "Called or Calling SubSystem Number", "tcap.ssn",
+ FT_UINT8, BASE_DEC, 0x0, 0x0,
+ "", HFILL }
+ },
+ { &hf_tcap_dlg_type,
+ { "Dialogue Type", "tcap.dlgtype",
+ FT_UINT8, BASE_HEX, VALS(dlg_type_strings), 0,
+ "", HFILL }
+ },
+ { &hf_tcap_app_con_name,
+ { "Application Context Name", "tcap.dlg.appconname",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ },
+ { &hf_tcap_bytes,
+ { "Binary Data", "tcap.data",
+ FT_BYTES, BASE_HEX, 0, 0,
+ "", HFILL }
+ },
+ { &hf_tcap_int,
+ { "Integer Data", "tcap.data",
+ FT_INT32, BASE_DEC, 0, 0,
+ "", HFILL }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_tcap,
+ &ett_otid,
+ &ett_dtid,
+ &ett_dlg_portion,
+ &ett_comps_portion,
+ &ett_reason,
+ &ett_dlg_req,
+ &ett_dlg_rsp,
+ &ett_dlg_abort,
+ &ett_component,
+ &ett_error,
+ &ett_problem,
+ &ett_params,
+ &ett_param,
+ };
+
+ static enum_val_t tcap_options[] = {
+ { "itu", "ITU", ITU_TCAP_STANDARD },
+ { "ansi", "ANSI", ANSI_TCAP_STANDARD },
+ { NULL, NULL, 0 }
+ };
+
+ module_t *tcap_module;
+
+/* Register the protocol name and description */
+ proto_tcap = proto_register_protocol("Transaction Capabilities Application Part",
+ "TCAP", "tcap");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_tcap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ tcap_module = prefs_register_protocol(proto_tcap, NULL);
+
+ prefs_register_enum_preference(tcap_module, "standard", "TCAP standard",
+ "The SS7 standard used in TCAP packets",
+ (gint *)&tcap_standard, tcap_options, FALSE);
+
+ prefs_register_bool_preference(tcap_module, "lock_info_col", "Lock Info column",
+ "Always show TCAP in Info column",
+ &lock_info_col);
+
+ /* we will fake a ssn subfield which has the same value obtained from sccp */
+ tcap_itu_ssn_dissector_table = register_dissector_table("tcap.itu_ssn", "ITU TCAP SSN", FT_UINT8, BASE_DEC);
+ tcap_ansi_ssn_dissector_table = register_dissector_table("tcap.ansi_ssn", "ANSI TCAP SSN", FT_UINT8, BASE_DEC);
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_tcap(void)
+{
+ dissector_handle_t tcap_handle;
+
+ tcap_handle = create_dissector_handle(dissect_tcap,
+ proto_tcap);
+
+ dissector_add("sccp.ssn", 5, tcap_handle); /* MAP*/
+ dissector_add("sccp.ssn", 6, tcap_handle); /* HLR*/
+ dissector_add("sccp.ssn", 7, tcap_handle); /* VLR */
+ dissector_add("sccp.ssn", 8, tcap_handle); /* MSC */
+ dissector_add("sccp.ssn", 9, tcap_handle); /* EIR */
+ dissector_add("sccp.ssn", 10, tcap_handle); /* EIR */
+ dissector_add("sccp.ssn", 11, tcap_handle); /* SMS/MC */
+ dissector_add("sccp.ssn", 12, tcap_handle); /* IS41 OTAF */
+
+ dissector_add("sua.ssn", 5, tcap_handle); /* MAP*/
+ dissector_add("sua.ssn", 6, tcap_handle); /* HLR*/
+ dissector_add("sua.ssn", 7, tcap_handle); /* VLR */
+ dissector_add("sua.ssn", 8, tcap_handle); /* MSC */
+ dissector_add("sua.ssn", 9, tcap_handle); /* EIR */
+ dissector_add("sua.ssn", 10, tcap_handle); /* EIR */
+ dissector_add("sua.ssn", 11, tcap_handle); /* SMS/MC */
+ dissector_add("sua.ssn", 12, tcap_handle); /* IS41 OTAF */
+
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-tcap.h b/epan/dissectors/packet-tcap.h
new file mode 100644
index 0000000000..7af75162f5
--- /dev/null
+++ b/epan/dissectors/packet-tcap.h
@@ -0,0 +1,64 @@
+/* packet-tcap.h
+ *
+ * $Id$
+ *
+ * Copyright 2003, Michael Lum <mlum [AT] telostech.com>,
+ * In association with Telos Technology Inc.
+ *
+ * Taken from packet-mtp3.h
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+typedef enum {
+ ITU_TCAP_STANDARD = 1,
+ ANSI_TCAP_STANDARD = 2
+} Tcap_Standard_Type;
+
+extern Tcap_Standard_Type tcap_standard;
+
+extern const value_string tcap_component_type_str[];
+
+/* TCAP component type */
+#define TCAP_COMP_INVOKE 0xa1
+#define TCAP_COMP_RRL 0xa2
+#define TCAP_COMP_RE 0xa3
+#define TCAP_COMP_REJECT 0xa4
+#define TCAP_COMP_RRN 0xa7
+
+/* ANSI TCAP component type */
+#define ANSI_TC_INVOKE_L 0xe9
+#define ANSI_TC_RRL 0xea
+#define ANSI_TC_RE 0xeb
+#define ANSI_TC_REJECT 0xec
+#define ANSI_TC_INVOKE_N 0xed
+#define ANSI_TC_RRN 0xee
+
+#define TCAP_SEQ_TAG 0x30
+#define TCAP_SET_TAG 0x31
+
+#define TCAP_INVOKE_ID_TAG 0x02
+#define TCAP_LINKED_ID_TAG 0x80
+
+#define TCAP_EOC_LEN 2 /* 0x00 0x00 */
+
+#define TCAP_CONSTRUCTOR(TCtag) (TCtag & 0x20)
+
+extern int tcap_find_eoc(ASN1_SCK *asn1);
+extern gboolean tcap_check_tag(ASN1_SCK *asn1, guint tag);
diff --git a/epan/dissectors/packet-tcp.c b/epan/dissectors/packet-tcp.c
new file mode 100644
index 0000000000..e48d7d0379
--- /dev/null
+++ b/epan/dissectors/packet-tcp.c
@@ -0,0 +1,3247 @@
+/* packet-tcp.c
+ * Routines for TCP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include "in_cksum.h"
+
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "ipproto.h"
+#include "ip_opts.h"
+#include "follow.h"
+#include "prefs.h"
+#include "packet-tcp.h"
+#include "packet-ip.h"
+#include "packet-frame.h"
+#include <epan/conversation.h>
+#include <epan/strutil.h>
+#include "reassemble.h"
+#include "tap.h"
+
+static int tcp_tap = -1;
+
+/* Place TCP summary in proto tree */
+static gboolean tcp_summary_in_tree = TRUE;
+
+/*
+ * Flag to control whether to check the TCP checksum.
+ *
+ * In at least some Solaris network traces, there are packets with bad
+ * TCP checksums, but the traffic appears to indicate that the packets
+ * *were* received; the packets were probably sent by the host on which
+ * the capture was being done, on a network interface to which
+ * checksumming was offloaded, so that DLPI supplied an un-checksummed
+ * packet to the capture program but a checksummed packet got put onto
+ * the wire.
+ */
+static gboolean tcp_check_checksum = TRUE;
+
+extern FILE* data_out_file;
+
+static int proto_tcp = -1;
+static int hf_tcp_srcport = -1;
+static int hf_tcp_dstport = -1;
+static int hf_tcp_port = -1;
+static int hf_tcp_seq = -1;
+static int hf_tcp_nxtseq = -1;
+static int hf_tcp_ack = -1;
+static int hf_tcp_hdr_len = -1;
+static int hf_tcp_flags = -1;
+static int hf_tcp_flags_cwr = -1;
+static int hf_tcp_flags_ecn = -1;
+static int hf_tcp_flags_urg = -1;
+static int hf_tcp_flags_ack = -1;
+static int hf_tcp_flags_push = -1;
+static int hf_tcp_flags_reset = -1;
+static int hf_tcp_flags_syn = -1;
+static int hf_tcp_flags_fin = -1;
+static int hf_tcp_window_size = -1;
+static int hf_tcp_checksum = -1;
+static int hf_tcp_checksum_bad = -1;
+static int hf_tcp_len = -1;
+static int hf_tcp_urgent_pointer = -1;
+static int hf_tcp_analysis_flags = -1;
+static int hf_tcp_analysis_acks_frame = -1;
+static int hf_tcp_analysis_ack_rtt = -1;
+static int hf_tcp_analysis_retransmission = -1;
+static int hf_tcp_analysis_fast_retransmission = -1;
+static int hf_tcp_analysis_out_of_order = -1;
+static int hf_tcp_analysis_lost_packet = -1;
+static int hf_tcp_analysis_ack_lost_packet = -1;
+static int hf_tcp_analysis_keep_alive = -1;
+static int hf_tcp_analysis_keep_alive_ack = -1;
+static int hf_tcp_analysis_duplicate_ack = -1;
+static int hf_tcp_analysis_duplicate_ack_num = -1;
+static int hf_tcp_analysis_duplicate_ack_frame = -1;
+static int hf_tcp_analysis_zero_window = -1;
+static int hf_tcp_analysis_zero_window_probe = -1;
+static int hf_tcp_analysis_zero_window_violation = -1;
+static int hf_tcp_continuation_to = -1;
+static int hf_tcp_reassembled_in = -1;
+static int hf_tcp_segments = -1;
+static int hf_tcp_segment = -1;
+static int hf_tcp_segment_overlap = -1;
+static int hf_tcp_segment_overlap_conflict = -1;
+static int hf_tcp_segment_multiple_tails = -1;
+static int hf_tcp_segment_too_long_fragment = -1;
+static int hf_tcp_segment_error = -1;
+static int hf_tcp_option_mss = -1;
+static int hf_tcp_option_mss_val = -1;
+static int hf_tcp_option_wscale = -1;
+static int hf_tcp_option_wscale_val = -1;
+static int hf_tcp_option_sack_perm = -1;
+static int hf_tcp_option_sack = -1;
+static int hf_tcp_option_sack_sle = -1;
+static int hf_tcp_option_sack_sre = -1;
+static int hf_tcp_option_echo = -1;
+static int hf_tcp_option_echo_reply = -1;
+static int hf_tcp_option_time_stamp = -1;
+static int hf_tcp_option_cc = -1;
+static int hf_tcp_option_ccnew = -1;
+static int hf_tcp_option_ccecho = -1;
+static int hf_tcp_option_md5 = -1;
+
+static gint ett_tcp = -1;
+static gint ett_tcp_flags = -1;
+static gint ett_tcp_options = -1;
+static gint ett_tcp_option_sack = -1;
+static gint ett_tcp_analysis = -1;
+static gint ett_tcp_analysis_faults = -1;
+static gint ett_tcp_segments = -1;
+static gint ett_tcp_segment = -1;
+
+
+/* not all of the hf_fields below make sense for TCP but we have to provide
+ them anyways to comply with the api (which was aimed for ip fragment
+ reassembly) */
+static const fragment_items tcp_segment_items = {
+ &ett_tcp_segment,
+ &ett_tcp_segments,
+ &hf_tcp_segments,
+ &hf_tcp_segment,
+ &hf_tcp_segment_overlap,
+ &hf_tcp_segment_overlap_conflict,
+ &hf_tcp_segment_multiple_tails,
+ &hf_tcp_segment_too_long_fragment,
+ &hf_tcp_segment_error,
+ &hf_tcp_reassembled_in,
+ "Segments"
+};
+
+static dissector_table_t subdissector_table;
+static heur_dissector_list_t heur_subdissector_list;
+static dissector_handle_t data_handle;
+
+/* TCP structs and definitions */
+
+static void
+process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
+ guint32 seq, guint32 nxtseq, gboolean is_tcp_segment);
+
+/* **************************************************************************
+ * stuff to analyze TCP sequencenumbers for retransmissions, missing segments,
+ * RTT and reltive sequence numbers.
+ * **************************************************************************/
+static gboolean tcp_analyze_seq = TRUE;
+static gboolean tcp_relative_seq = TRUE;
+
+static GMemChunk *tcp_unacked_chunk = NULL;
+static int tcp_unacked_count = 500; /* one for each packet until it is acked*/
+struct tcp_unacked {
+ struct tcp_unacked *next;
+ guint32 frame;
+ guint32 seq;
+ guint32 nextseq;
+ nstime_t ts;
+
+ /* this is to keep track of zero window and zero window probe */
+ guint32 window;
+
+ guint32 flags;
+};
+
+/* Idea for gt: either x > y, or y is much bigger (assume wrap) */
+#define GT_SEQ(x, y) ((gint32)((y) - (x)) < 0)
+#define LT_SEQ(x, y) ((gint32)((x) - (y)) < 0)
+#define GE_SEQ(x, y) ((gint32)((y) - (x)) <= 0)
+#define LE_SEQ(x, y) ((gint32)((x) - (y)) <= 0)
+#define EQ_SEQ(x, y) ((x) == (y))
+
+static GMemChunk *tcp_acked_chunk = NULL;
+static int tcp_acked_count = 5000; /* one for almost every other segment in the capture */
+#define TCP_A_RETRANSMISSION 0x0001
+#define TCP_A_LOST_PACKET 0x0002
+#define TCP_A_ACK_LOST_PACKET 0x0004
+#define TCP_A_KEEP_ALIVE 0x0008
+#define TCP_A_DUPLICATE_ACK 0x0010
+#define TCP_A_ZERO_WINDOW 0x0020
+#define TCP_A_ZERO_WINDOW_PROBE 0x0040
+#define TCP_A_ZERO_WINDOW_VIOLATION 0x0080
+#define TCP_A_KEEP_ALIVE_ACK 0x0100
+#define TCP_A_OUT_OF_ORDER 0x0200
+#define TCP_A_FAST_RETRANSMISSION 0x0400
+struct tcp_acked {
+ guint32 frame_acked;
+ nstime_t ts;
+ guint16 flags;
+ guint32 dupack_num; /* dup ack number */
+ guint32 dupack_frame; /* dup ack to frame # */
+};
+static GHashTable *tcp_analyze_acked_table = NULL;
+
+static GMemChunk *tcp_rel_seq_chunk = NULL;
+static int tcp_rel_seq_count = 10000; /* one for each segment in the capture */
+struct tcp_rel_seq {
+ guint32 seq_base;
+ guint32 ack_base;
+ gint16 win_scale;
+};
+static GHashTable *tcp_rel_seq_table = NULL;
+
+static GMemChunk *tcp_analysis_chunk = NULL;
+static int tcp_analysis_count = 20; /* one for each conversation */
+struct tcp_analysis {
+ /* These two structs are managed based on comparing the source
+ * and destination addresses and, if they're equal, comparing
+ * the source and destination ports.
+ *
+ * If the source is greater than the destination, then stuff
+ * sent from src is in ual1.
+ *
+ * If the source is less than the destination, then stuff
+ * sent from src is in ual2.
+ *
+ * XXX - if the addresses and ports are equal, we don't guarantee
+ * the behavior.
+ */
+ struct tcp_unacked *ual1; /* UnAcked List 1*/
+ guint32 base_seq1;
+ struct tcp_unacked *ual2; /* UnAcked List 2*/
+ guint32 base_seq2;
+ gint16 win_scale1;
+ gint16 win_scale2;
+ guint32 ack1, ack2;
+ guint32 ack1_frame, ack2_frame;
+ nstime_t ack1_time, ack2_time;
+ guint32 num1_acks, num2_acks;
+
+ /* these two lists are used to track when PDUs may start
+ inside a segment.
+ */
+ struct tcp_next_pdu *pdu_seq1;
+ struct tcp_next_pdu *pdu_seq2;
+};
+
+
+static GMemChunk *tcp_next_pdu_chunk = NULL;
+static int tcp_next_pdu_count = 20;
+struct tcp_next_pdu {
+ struct tcp_next_pdu *next;
+ guint32 seq;
+ guint32 nxtpdu;
+ guint32 first_frame;
+};
+static GHashTable *tcp_pdu_tracking_table = NULL;
+static GHashTable *tcp_pdu_skipping_table = NULL;
+
+
+static struct tcp_analysis *
+get_tcp_conversation_data(packet_info *pinfo)
+{
+ conversation_t *conv=NULL;
+ struct tcp_analysis *tcpd=NULL;
+
+ /* Have we seen this conversation before? */
+ if( (conv=find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0)) == NULL){
+ /* No this is a new conversation. */
+ conv=conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+
+ /* check if we have any data for this conversation */
+ tcpd=conversation_get_proto_data(conv, proto_tcp);
+ if(!tcpd){
+ /* No no such data yet. Allocate and init it */
+ tcpd=g_mem_chunk_alloc(tcp_analysis_chunk);
+ tcpd->ual1=NULL;
+ tcpd->base_seq1=0;
+ tcpd->win_scale1=-1;
+ tcpd->ack1=0;
+ tcpd->ack1_frame=0;
+ tcpd->ack1_time.secs=0;
+ tcpd->ack1_time.nsecs=0;
+ tcpd->num1_acks=0;
+ tcpd->ual2=NULL;
+ tcpd->base_seq2=0;
+ tcpd->win_scale2=-1;
+ tcpd->ack2=0;
+ tcpd->ack2_frame=0;
+ tcpd->ack2_time.secs=0;
+ tcpd->ack2_time.nsecs=0;
+ tcpd->num2_acks=0;
+
+ tcpd->pdu_seq1=NULL;
+ tcpd->pdu_seq2=NULL;
+
+ conversation_add_proto_data(conv, proto_tcp, tcpd);
+ }
+
+ return tcpd;
+}
+
+/* This function is called from the tcp analysis code to provide
+ clues on how the seq and ack numbers are changed.
+ To prevent the next_pdu lists from growing uncontrollable in size we
+ use this function to do the following :
+ IF we see an ACK then we assume that the left edge of the window has changed
+ at least to this point and assuming it is rare with reordering and
+ trailing duplicate/retransmitted segments, we just assume that after
+ we have seen the ACK we will not see any more segments prior to the
+ ACK value.
+ If we will not see any segments prior to the ACK value then we can just
+ delete all next_pdu entries that describe pdu's starting prior to the
+ ACK.
+ If this heuristics is prooved to be too simplistic we can just enhance it
+ later.
+*/
+/* XXX this function should be ehnanced to handle sequence number wrapping */
+/* XXX to handle retransmissions and reordered packets maybe we should only
+ discard entries that are more than (guesstimate) 50kb older than the
+ specified sequence number ?
+*/
+static void
+prune_next_pdu_list(struct tcp_next_pdu **tnp, guint32 seq)
+{
+ struct tcp_next_pdu *tmptnp;
+
+ if(*tnp == NULL){
+ return;
+ }
+
+ for(tmptnp=*tnp;tmptnp;tmptnp=tmptnp->next){
+ if(tmptnp->nxtpdu<=seq){
+ struct tcp_next_pdu *oldtnp;
+ oldtnp=tmptnp;
+
+ if(tmptnp==*tnp){
+ tmptnp=tmptnp->next;
+ *tnp=tmptnp;
+ g_mem_chunk_free(tcp_next_pdu_chunk, oldtnp);
+ if(!tmptnp){
+ return;
+ }
+ continue;
+ } else {
+ for(tmptnp=*tnp;tmptnp;tmptnp=tmptnp->next){
+ if(tmptnp->next==oldtnp){
+ tmptnp->next=oldtnp->next;
+ g_mem_chunk_free(tcp_next_pdu_chunk, oldtnp);
+ break;
+ }
+ }
+ if(!tmptnp){
+ return;
+ }
+ }
+ }
+ }
+}
+
+
+/* if we know that a PDU starts inside this segment, return the adjusted
+ offset to where that PDU starts or just return offset back
+ and let TCP try to find out what it can about this segment
+*/
+static int
+scan_for_next_pdu(tvbuff_t *tvb, proto_tree *tcp_tree, packet_info *pinfo, int offset, guint32 seq, guint32 nxtseq)
+{
+ struct tcp_analysis *tcpd=NULL;
+ struct tcp_next_pdu *tnp=NULL;
+ int direction;
+
+ if(!pinfo->fd->flags.visited){
+ /* find(or create if needed) the conversation for this tcp session */
+ tcpd=get_tcp_conversation_data(pinfo);
+ /* check direction and get pdu start lists */
+ direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
+ /* if the addresses are equal, match the ports instead */
+ if(direction==0) {
+ direction= (pinfo->srcport > pinfo->destport)*2-1;
+ }
+ if(direction>=0){
+ tnp=tcpd->pdu_seq1;
+ } else {
+ tnp=tcpd->pdu_seq2;
+ }
+
+ /* scan and see if we find any pdus starting inside this tvb */
+ for(;tnp;tnp=tnp->next){
+ /* XXX here we should also try to handle sequence number
+ wrapping
+ */
+ /* If this segment is completely within a previous PDU
+ * then we just skip this packet
+ */
+ if(seq>tnp->seq && nxtseq<=tnp->nxtpdu){
+ g_hash_table_insert(tcp_pdu_skipping_table,
+ (void *)pinfo->fd->num, (void *)tnp->first_frame);
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ",pinfo->fd->num);
+ }
+ proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
+ tvb, 0, 0, pinfo->fd->num);
+ return -1;
+ }
+ if(seq<tnp->nxtpdu && nxtseq>tnp->nxtpdu){
+ g_hash_table_insert(tcp_pdu_tracking_table,
+ (void *)pinfo->fd->num, (void *)tnp->nxtpdu);
+ offset+=tnp->nxtpdu-seq;
+ break;
+ }
+ }
+ } else {
+ guint32 pduseq;
+ guint32 first_frame;
+
+ /* check if this is a segment in the middle of a pdu */
+ first_frame=(guint32)g_hash_table_lookup(tcp_pdu_skipping_table, (void *)pinfo->fd->num);
+ if(first_frame){
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[Continuation to #%u] ", first_frame);
+ }
+ proto_tree_add_uint(tcp_tree, hf_tcp_continuation_to,
+ tvb, 0, 0, first_frame);
+ return -1;
+ }
+
+ pduseq=(guint32)g_hash_table_lookup(tcp_pdu_tracking_table, (void *)pinfo->fd->num);
+ if(pduseq){
+ offset+=pduseq-seq;
+ }
+ }
+
+ return offset;
+}
+
+/* if we saw a PDU that extended beyond the end of the segment,
+ use this function to remember where the next pdu starts
+*/
+static void
+pdu_store_sequencenumber_of_next_pdu(packet_info *pinfo, guint32 seq, guint32 nxtpdu)
+{
+ struct tcp_analysis *tcpd=NULL;
+ struct tcp_next_pdu *tnp=NULL;
+ int direction;
+
+ /* find(or create if needed) the conversation for this tcp session */
+ tcpd=get_tcp_conversation_data(pinfo);
+
+ tnp=g_mem_chunk_alloc(tcp_next_pdu_chunk);
+ tnp->nxtpdu=nxtpdu;
+ tnp->seq=seq;
+ tnp->first_frame=pinfo->fd->num;
+
+ /* check direction and get pdu start list */
+ direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
+ /* if the addresses are equal, match the ports instead */
+ if(direction==0) {
+ direction= (pinfo->srcport > pinfo->destport)*2-1;
+ }
+ if(direction>=0){
+ tnp->next=tcpd->pdu_seq1;
+ tcpd->pdu_seq1=tnp;
+ } else {
+ tnp->next=tcpd->pdu_seq2;
+ tcpd->pdu_seq2=tnp;
+ }
+ /*QQQ
+ Add check for ACKs and purge list of sequence numbers
+ already acked.
+ */
+}
+
+/* if we saw a window scaling option, store it for future reference
+*/
+static void pdu_store_window_scale_option(packet_info *pinfo, guint8 ws)
+{
+ struct tcp_analysis *tcpd=NULL;
+ int direction;
+
+ /* find(or create if needed) the conversation for this tcp session */
+ tcpd=get_tcp_conversation_data(pinfo);
+
+ /* check direction and get pdu start list */
+ direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
+ /* if the addresses are equal, match the ports instead */
+ if(direction==0) {
+ direction= (pinfo->srcport > pinfo->destport)*2-1;
+ }
+ if(direction>=0){
+ tcpd->win_scale1=ws;
+ } else {
+ tcpd->win_scale2=ws;
+ }
+}
+
+static void
+tcp_get_relative_seq_ack(guint32 frame, guint32 *seq, guint32 *ack, guint32 *win)
+{
+ struct tcp_rel_seq *trs;
+
+ trs=g_hash_table_lookup(tcp_rel_seq_table, (void *)frame);
+ if(!trs){
+ return;
+ }
+
+ (*seq) -= trs->seq_base;
+ (*ack) -= trs->ack_base;
+ if(trs->win_scale!=-1){
+ (*win)<<=trs->win_scale;
+ }
+}
+
+static struct tcp_acked *
+tcp_analyze_get_acked_struct(guint32 frame, gboolean createflag)
+{
+ struct tcp_acked *ta;
+
+ ta=g_hash_table_lookup(tcp_analyze_acked_table, (void *)frame);
+ if((!ta) && createflag){
+ ta=g_mem_chunk_alloc(tcp_acked_chunk);
+ ta->frame_acked=0;
+ ta->ts.secs=0;
+ ta->ts.nsecs=0;
+ ta->flags=0;
+ ta->dupack_num=0;
+ ta->dupack_frame=0;
+ g_hash_table_insert(tcp_analyze_acked_table, (void *)frame, ta);
+ }
+ return ta;
+}
+
+static void
+tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint8 flags, guint32 window)
+{
+ struct tcp_analysis *tcpd=NULL;
+ int direction;
+ struct tcp_unacked *ual1=NULL;
+ struct tcp_unacked *ual2=NULL;
+ struct tcp_unacked *ual=NULL;
+ guint32 base_seq;
+ guint32 base_ack;
+ guint32 ack1, ack2;
+ guint32 ack1_frame, ack2_frame;
+ nstime_t *ack1_time, *ack2_time;
+ guint32 num1_acks, num2_acks;
+ gint16 win_scale;
+ struct tcp_next_pdu **tnp=NULL;
+
+ /* find(or create if needed) the conversation for this tcp session */
+ tcpd=get_tcp_conversation_data(pinfo);
+
+ /* check direction and get ua lists */
+ direction=CMP_ADDRESS(&pinfo->src, &pinfo->dst);
+ /* if the addresses are equal, match the ports instead */
+ if(direction==0) {
+ direction= (pinfo->srcport > pinfo->destport)*2-1;
+ }
+ if(direction>=0){
+ ual1=tcpd->ual1;
+ ual2=tcpd->ual2;
+ ack1=tcpd->ack1;
+ ack2=tcpd->ack2;
+ ack1_frame=tcpd->ack1_frame;
+ ack2_frame=tcpd->ack2_frame;
+ ack1_time=&tcpd->ack1_time;
+ ack2_time=&tcpd->ack2_time;
+ num1_acks=tcpd->num1_acks;
+ num2_acks=tcpd->num2_acks;
+ tnp=&tcpd->pdu_seq2;
+ base_seq=(tcp_relative_seq && (ual1==NULL))?seq:tcpd->base_seq1;
+ base_ack=(tcp_relative_seq && (ual2==NULL))?ack:tcpd->base_seq2;
+ win_scale=tcpd->win_scale1;
+ } else {
+ ual1=tcpd->ual2;
+ ual2=tcpd->ual1;
+ ack1=tcpd->ack2;
+ ack2=tcpd->ack1;
+ ack1_frame=tcpd->ack2_frame;
+ ack2_frame=tcpd->ack1_frame;
+ ack1_time=&tcpd->ack2_time;
+ ack2_time=&tcpd->ack1_time;
+ num1_acks=tcpd->num2_acks;
+ num2_acks=tcpd->num1_acks;
+ tnp=&tcpd->pdu_seq1;
+ base_seq=(tcp_relative_seq && (ual1==NULL))?seq:tcpd->base_seq2;
+ base_ack=(tcp_relative_seq && (ual2==NULL))?ack:tcpd->base_seq1;
+ win_scale=tcpd->win_scale2;
+ }
+
+ if(!seglen){
+ if(!ack2_frame){
+ ack2_frame=pinfo->fd->num;
+ ack2=ack;
+ ack2_time->secs=pinfo->fd->abs_secs;
+ ack2_time->nsecs=pinfo->fd->abs_usecs*1000;
+ num2_acks=0;
+ } else if(GT_SEQ(ack, ack2)){
+ ack2_frame=pinfo->fd->num;
+ ack2=ack;
+ ack2_time->secs=pinfo->fd->abs_secs;
+ ack2_time->nsecs=pinfo->fd->abs_usecs*1000;
+ num2_acks=0;
+ }
+ }
+
+#ifdef REMOVED
+/* useful debug ouput
+ * it prints the two lists of the sliding window emulation
+ */
+{
+struct tcp_unacked *u=NULL;
+printf("\n");
+printf("analyze_sequence_number(frame:%d seq:%d nextseq:%d ack:%d baseseq:0x%08x baseack:0x%08x)\n",pinfo->fd->num,seq,seq+seglen,ack,base_seq,base_ack);
+printf("UAL1:\n");
+for(u=ual1;u;u=u->next){
+printf(" Frame:%d seq:%d nseq:%d time:%d.%09d ack:%d:%d\n",u->frame,u->seq,u->nextseq,u->ts.secs,u->ts.nsecs,ack1,ack2);
+}
+printf("UAL2:\n");
+for(u=ual2;u;u=u->next){
+printf(" Frame:%d seq:%d nseq:%d time:%d.%09d ack:%d:%d\n",u->frame,u->seq,u->nextseq,u->ts.secs,u->ts.nsecs,ack1,ack2);
+}
+}
+#endif
+
+ /* To handle FIN, just add 1 to the length.
+ else the ACK following the FIN-ACK will look like it was
+ outside the window. */
+ if( flags&TH_FIN ){
+ seglen+=1;
+ }
+
+ /* handle the sequence numbers */
+ /* if this was a SYN packet, then remove existing list and
+ * put SEQ+1 first the list */
+ if(flags&TH_SYN){
+ for(ual=ual1;ual1;ual1=ual){
+ ual=ual1->next;
+ g_mem_chunk_free(tcp_unacked_chunk, ual1);
+ }
+ ual1=g_mem_chunk_alloc(tcp_unacked_chunk);
+ ual1->next=NULL;
+ ual1->frame=pinfo->fd->num;
+ ack1_frame=0;
+ ack2_frame=0;
+ ack1=0;
+ ack2=0;
+ num1_acks=0;
+ num2_acks=0;
+ ual1->seq=seq;
+ ual1->nextseq=seq+1;
+ ual1->ts.secs=pinfo->fd->abs_secs;
+ ual1->ts.nsecs=pinfo->fd->abs_usecs*1000;
+ ual1->window=window;
+ ual1->flags=0;
+ if(tcp_relative_seq){
+ base_seq=seq;
+ /* if this was an SYN|ACK packet then set base_ack
+ * reflect the start of the sequence, i.e. one less
+ */
+ if(flags&TH_ACK){
+ base_ack=ack-1;
+ } else {
+ base_ack=ack;
+ }
+ }
+ goto seq_finished;
+ }
+
+ /* if this is the first segment we see then just add it */
+ if( !ual1 ){
+ ual1=g_mem_chunk_alloc(tcp_unacked_chunk);
+ ual1->next=NULL;
+ ual1->frame=pinfo->fd->num;
+ ual1->seq=seq;
+ ual1->nextseq=seq+seglen;
+ ual1->ts.secs=pinfo->fd->abs_secs;
+ ual1->ts.nsecs=pinfo->fd->abs_usecs*1000;
+ ual1->window=window;
+ ual1->flags=0;
+ if(tcp_relative_seq){
+ base_seq=seq;
+ base_ack=ack;
+ }
+ goto seq_finished;
+ }
+
+ /* if we get past here we know that ual1 points to a segment */
+
+
+ /* if seq is beyond ual1->nextseq we have lost a segment */
+ if (GT_SEQ(seq, ual1->nextseq)) {
+ struct tcp_acked *ta;
+
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_LOST_PACKET;
+
+ /* just add the segment to the beginning of the list */
+ ual=g_mem_chunk_alloc(tcp_unacked_chunk);
+ ual->next=ual1;
+ ual->frame=pinfo->fd->num;
+ ual->seq=seq;
+ ual->nextseq=seq+seglen;
+ ual->ts.secs=pinfo->fd->abs_secs;
+ ual->ts.nsecs=pinfo->fd->abs_usecs*1000;
+ ual->window=window;
+ ual->flags=0;
+ ual1=ual;
+ goto seq_finished;
+ }
+
+ /* keep-alives are empty segments with a sequence number -1 of what
+ * we would expect.
+ *
+ * Solaris is an exception, Solaris does not really use KeepAlives
+ * according to RFC793, instead they move the left window edge one
+ * byte to the left and makes up a fake byte to fill in this position
+ * of the enlarged window.
+ * This means that Solaris will do "weird" KeepAlives that actually
+ * contains a one-byte segment with "random" junk data which the
+ * Solaris host then will try to transmit, and posisbly retransmit
+ * to the other side. Of course the other side will ignore this junk
+ * byte since it is outside (left of) the window.
+ * This is actually a brilliant trick that gives them, for free,
+ * semi-reliable KeepAlives.
+ * (since normal retransmission will handle any lost keepalive segments
+ * , brilliant)
+ */
+ if( (seglen<=1) && EQ_SEQ(seq, (ual1->nextseq-1)) ){
+ if(!(flags&TH_FIN)){ /* FIN segments are not keepalives */
+ struct tcp_acked *ta;
+
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_KEEP_ALIVE;
+ ual1->flags|=TCP_A_KEEP_ALIVE;
+ goto seq_finished;
+ }
+ }
+
+
+ /* if this is an empty segment, just skip it all */
+ if( !seglen ){
+ goto seq_finished;
+ }
+
+ /* check if the sequence number is lower than expected, i.e. either a
+ * retransmission a fast retransmission or an out of order segment
+ */
+ if( LT_SEQ(seq, ual1->nextseq )){
+ gboolean outoforder;
+ struct tcp_unacked *tu,*ntu;
+
+ /* assume it is a fast retransmission if
+ * 1 we have seen >=3 dupacks in the other direction for this
+ * segment (i.e. >=4 acks)
+ * 2 if this segment is the next unacked segment
+ * 3 this segment came within 10ms of the last dupack
+ * (10ms is arbitrary but should be low enough not to be
+ * confused with a retransmission timeout
+ */
+ if( (num1_acks>=4) && (seq==ack1) ){
+ guint32 t;
+
+ t=(pinfo->fd->abs_secs-ack1_time->secs)*1000000000;
+ t=t+(pinfo->fd->abs_usecs*1000)-ack1_time->nsecs;
+ if(t<10000000){
+ /* has to be a retransmission then */
+ struct tcp_acked *ta;
+
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_FAST_RETRANSMISSION;
+ goto seq_finished;
+ }
+ }
+
+ /* check it is a suspected out of order segment.
+ * we assume it is an out of order segment if
+ * 1 it has not been ACKed yet.
+ * 2 we have not seen the segment before
+ * 3 it arrived within (arbitrary value) 4ms of the
+ * next semgent in the sequence.
+ * 4 there were no dupacks in the opposite direction.
+ */
+ outoforder=TRUE;
+#ifdef REMOVED
+ /* dont do this test. For full-duplex capture devices that
+ * capture in both directions using two NICs it is more common
+ * than one would expect for this to happen since they often
+ * lose the time integrity between the two NICs
+ */
+ /* 1 has it already been ACKed ? */
+ if(LT_SEQ(seq,ack1)){
+ outoforder=FALSE;
+ }
+#endif
+ /* 2 have we seen this segment before ? */
+ for(tu=ual1;tu;tu=tu->next){
+ if((tu->frame)&&(tu->seq==seq)){
+ outoforder=FALSE;
+ }
+ }
+ /* 3 was it received within 4ms of the next segment ?*/
+ ntu=NULL;
+ for(tu=ual1;tu;tu=tu->next){
+ if(LT_SEQ(seq,tu->seq)){
+ if(tu->frame){
+ ntu=tu;
+ }
+ }
+ }
+ if(ntu){
+ if(pinfo->fd->abs_secs>(guint32)(ntu->ts.secs+2)){
+ outoforder=FALSE;
+ } else if((pinfo->fd->abs_secs+2)<(guint32)ntu->ts.secs){
+ outoforder=FALSE;
+ } else {
+ guint32 t;
+
+ t=(ntu->ts.secs-pinfo->fd->abs_secs)*1000000000;
+ t=t+ntu->ts.nsecs-(pinfo->fd->abs_usecs*1000);
+ if(t>4000000){
+ outoforder=FALSE;
+ }
+ }
+ }
+
+
+ if(outoforder) {
+ struct tcp_acked *ta;
+
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_OUT_OF_ORDER;
+ } else {
+ /* has to be a retransmission then */
+ struct tcp_acked *ta;
+
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_RETRANSMISSION;
+
+ /* did this segment contain any more data we havent seen yet?
+ * if so we can just increase nextseq
+ */
+ if(GT_SEQ((seq+seglen), ual1->nextseq)){
+ ual1->nextseq=seq+seglen;
+ ual1->frame=pinfo->fd->num;
+ ual1->ts.secs=pinfo->fd->abs_secs;
+ ual1->ts.nsecs=pinfo->fd->abs_usecs*1000;
+ }
+ }
+ goto seq_finished;
+ }
+
+ /* just add the segment to the beginning of the list */
+ ual=g_mem_chunk_alloc(tcp_unacked_chunk);
+ ual->next=ual1;
+ ual->frame=pinfo->fd->num;
+ ual->seq=seq;
+ ual->nextseq=seq+seglen;
+ ual->ts.secs=pinfo->fd->abs_secs;
+ ual->ts.nsecs=pinfo->fd->abs_usecs*1000;
+ ual->window=window;
+ ual->flags=0;
+ ual1=ual;
+
+seq_finished:
+
+
+ /* handle the ack numbers */
+
+ /* if we dont have the ack flag its not much we can do */
+ if( !(flags&TH_ACK)){
+ goto ack_finished;
+ }
+
+ /* if we havent seen anything yet in the other direction we dont
+ * know what this one acks */
+ if( !ual2 ){
+ goto ack_finished;
+ }
+
+ /* if we dont have any real segments in the other direction not
+ * acked yet (as we see from the magic frame==0 entry)
+ * then there is no point in continuing
+ */
+ if( !ual2->frame ){
+ goto ack_finished;
+ }
+
+ /* if we get here we know ual2 is valid */
+
+ /* if we are acking beyong what we have seen in the other direction
+ * we must have lost packets. Not much point in keeping the segments
+ * in the other direction either.
+ */
+ if( GT_SEQ(ack, ual2->nextseq )){
+ struct tcp_acked *ta;
+
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_ACK_LOST_PACKET;
+ for(ual=ual2;ual2;ual2=ual){
+ ual=ual2->next;
+ g_mem_chunk_free(tcp_unacked_chunk, ual2);
+ }
+ prune_next_pdu_list(tnp, ack-base_ack);
+ goto ack_finished;
+ }
+
+
+ /* does this ACK ack all semgents we have seen in the other direction?*/
+ if( EQ_SEQ(ack, ual2->nextseq )){
+ struct tcp_acked *ta;
+
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->frame_acked=ual2->frame;
+ ta->ts.secs=pinfo->fd->abs_secs-ual2->ts.secs;
+ ta->ts.nsecs=pinfo->fd->abs_usecs*1000-ual2->ts.nsecs;
+ if(ta->ts.nsecs<0){
+ ta->ts.nsecs+=1000000000;
+ ta->ts.secs--;
+ }
+
+ /* its all been ACKed so we dont need to keep them anymore */
+ for(ual=ual2;ual2;ual2=ual){
+ ual=ual2->next;
+ g_mem_chunk_free(tcp_unacked_chunk, ual2);
+ }
+ prune_next_pdu_list(tnp, ack-base_ack);
+ goto ack_finished;
+ }
+
+ /* ok it only ACKs part of what we have seen. Find out how much
+ * update and remove the ACKed segments
+ */
+ for(ual=ual2;ual->next;ual=ual->next){
+ if( GE_SEQ(ack, ual->next->nextseq)){
+ break;
+ }
+ }
+ if(ual->next){
+ struct tcp_unacked *tmpual=NULL;
+ struct tcp_unacked *ackedual=NULL;
+ struct tcp_acked *ta;
+
+ /* XXX normal ACK*/
+ ackedual=ual->next;
+
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->frame_acked=ackedual->frame;
+ ta->ts.secs=pinfo->fd->abs_secs-ackedual->ts.secs;
+ ta->ts.nsecs=pinfo->fd->abs_usecs*1000-ackedual->ts.nsecs;
+ if(ta->ts.nsecs<0){
+ ta->ts.nsecs+=1000000000;
+ ta->ts.secs--;
+ }
+
+ /* just delete all ACKed segments */
+ tmpual=ual->next;
+ ual->next=NULL;
+ for(ual=tmpual;ual;ual=tmpual){
+ tmpual=ual->next;
+ g_mem_chunk_free(tcp_unacked_chunk, ual);
+ }
+ prune_next_pdu_list(tnp, ack-base_ack);
+ }
+
+ack_finished:
+ /* we might have deleted the entire ual2 list, if this is an ACK,
+ make sure ual2 at least has a dummy entry for the current ACK */
+ if( (!ual2) && (flags&TH_ACK) ){
+ ual2=g_mem_chunk_alloc(tcp_unacked_chunk);
+ ual2->next=NULL;
+ ual2->frame=0;
+ ual2->seq=ack;
+ ual2->nextseq=ack;
+ ual2->ts.secs=0;
+ ual2->ts.nsecs=0;
+ ual2->window=window;
+ ual2->flags=0;
+ }
+
+ /* update the ACK counter and check for
+ duplicate ACKs*/
+ /* go to the oldest segment in the list of segments
+ in the other direction */
+ /* XXX we should guarantee ual2 to always be non NULL here
+ so we can skip the ual/ual2 tests */
+ for(ual=ual2;ual&&ual->next;ual=ual->next)
+ ;
+ if(ual2){
+ /* we only consider this being a potential duplicate ack
+ if the segment length is 0 (ack only segment)
+ and if it acks something previous to oldest segment
+ in the other direction */
+ if((!seglen)&&LE_SEQ(ack,ual->seq)){
+ /* if this is the first ack to keep track of, it is not
+ a duplicate */
+ if(num2_acks==0){
+ ack2=ack;
+ ack2_frame=pinfo->fd->num;
+ num2_acks=1;
+ /* if this ack is different, store this one
+ instead and forget the previous one(s) */
+ } else if(ack2!=ack){
+ ack2=ack;
+ ack2_frame=pinfo->fd->num;
+ num2_acks=1;
+ /* this has to be a duplicate ack */
+ } else {
+ num2_acks++;
+ }
+
+ /* is this an ACK to a KeepAlive? */
+ if( (ual->flags&TCP_A_KEEP_ALIVE)
+ && (ack==ual->seq) ){
+ struct tcp_acked *ta;
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_KEEP_ALIVE_ACK;
+ ual->flags^=TCP_A_KEEP_ALIVE;
+ } else if(num2_acks>1) {
+ /* ok we have found a potential duplicate ack */
+ struct tcp_acked *ta;
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ /* keepalives are not dupacks and
+ * netiher are RST/FIN segments
+ */
+ if( (!(ta->flags&TCP_A_KEEP_ALIVE))
+ &&(!(flags&(TH_RST|TH_FIN))) ){
+ ta->flags|=TCP_A_DUPLICATE_ACK;
+ ta->dupack_num=num2_acks-1;
+ ta->dupack_frame=ack2_frame;
+ }
+ }
+ }
+
+ }
+
+
+ /* check for zero window probes
+ a zero window probe is when a TCP tries to write 1 byte segments
+ where the remote side has advertised a window of 0 bytes.
+ We only do this check if we actually have seen anything from the
+ other side of this connection.
+
+ We also assume ual still points to the last entry in the ual2
+ list from the section above.
+
+ At the same time, check for violations, i.e. attempts to write >1
+ byte to a zero-window.
+ */
+ /* XXX we should not need to do the ual->frame check here?
+ might be a bug somewhere. look for it later .
+ */
+ if(ual2&&(ual->frame)){
+ if((seglen==1)&&(ual->window==0)){
+ struct tcp_acked *ta;
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_ZERO_WINDOW_PROBE;
+ }
+ if((seglen>1)&&(ual->window==0)){
+ struct tcp_acked *ta;
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_ZERO_WINDOW_VIOLATION;
+ }
+ }
+
+ /* check for zero window
+ * dont check for RST/FIN segments since the window field is
+ * meaningless for those
+ */
+ if( (!window)
+ &&(!(flags&(TH_RST|TH_FIN))) ){
+ struct tcp_acked *ta;
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, TRUE);
+ ta->flags|=TCP_A_ZERO_WINDOW;
+ }
+
+
+ /* store the lists back in our struct */
+ if(direction>=0){
+ /*
+ * XXX - if direction == 0, that'll be true for packets
+ * from both sides of the connection, so this won't
+ * work.
+ *
+ * That'd be a connection from a given port on a machine
+ * to that same port on the same machine; does that ever
+ * happen?
+ */
+ tcpd->ual1=ual1;
+ tcpd->ual2=ual2;
+ tcpd->ack1=ack1;
+ tcpd->ack2=ack2;
+ tcpd->ack1_frame=ack1_frame;
+ tcpd->ack2_frame=ack2_frame;
+ tcpd->num1_acks=num1_acks;
+ tcpd->num2_acks=num2_acks;
+ tcpd->base_seq1=base_seq;
+ tcpd->base_seq2=base_ack;
+ } else {
+ tcpd->ual1=ual2;
+ tcpd->ual2=ual1;
+ tcpd->ack1=ack2;
+ tcpd->ack2=ack1;
+ tcpd->ack1_frame=ack2_frame;
+ tcpd->ack2_frame=ack1_frame;
+ tcpd->num1_acks=num2_acks;
+ tcpd->num2_acks=num1_acks;
+ tcpd->base_seq2=base_seq;
+ tcpd->base_seq1=base_ack;
+ }
+
+
+ if(tcp_relative_seq){
+ struct tcp_rel_seq *trs;
+ /* remember relative seq/ack number base for this packet */
+ trs=g_mem_chunk_alloc(tcp_rel_seq_chunk);
+ trs->seq_base=base_seq;
+ trs->ack_base=base_ack;
+ trs->win_scale=win_scale;
+ g_hash_table_insert(tcp_rel_seq_table, (void *)pinfo->fd->num, trs);
+ }
+}
+
+static void
+tcp_print_sequence_number_analysis(packet_info *pinfo, tvbuff_t *tvb, proto_tree *parent_tree)
+{
+ struct tcp_acked *ta;
+ proto_item *item;
+ proto_tree *tree;
+
+ ta=tcp_analyze_get_acked_struct(pinfo->fd->num, FALSE);
+ if(!ta){
+ return;
+ }
+
+ item=proto_tree_add_text(parent_tree, tvb, 0, 0, "SEQ/ACK analysis");
+ PROTO_ITEM_SET_GENERATED(item);
+ tree=proto_item_add_subtree(item, ett_tcp_analysis);
+
+ /* encapsulate all proto_tree_add_xxx in ifs so we only print what
+ data we actually have */
+ if(ta->frame_acked){
+ item = proto_tree_add_uint(tree, hf_tcp_analysis_acks_frame,
+ tvb, 0, 0, ta->frame_acked);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ if( ta->ts.secs || ta->ts.nsecs ){
+ item = proto_tree_add_time(tree, hf_tcp_analysis_ack_rtt,
+ tvb, 0, 0, &ta->ts);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+
+ if(ta->flags){
+ proto_item *flags_item=NULL;
+ proto_tree *flags_tree=NULL;
+
+ flags_item = proto_tree_add_item(tree, hf_tcp_analysis_flags, tvb, 0, -1, FALSE);
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ flags_tree=proto_item_add_subtree(flags_item, ett_tcp_analysis);
+ if( ta->flags&TCP_A_RETRANSMISSION ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_retransmission, tvb, 0, 0, "This frame is a (suspected) retransmission");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Retransmission] ");
+ }
+ }
+ if( ta->flags&TCP_A_FAST_RETRANSMISSION ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_fast_retransmission, tvb, 0, 0, "This frame is a (suspected) fast retransmission");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_retransmission, tvb, 0, 0, "This frame is a (suspected) retransmission");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Fast Retransmission] ");
+ }
+ }
+ if( ta->flags&TCP_A_OUT_OF_ORDER ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_out_of_order, tvb, 0, 0, "This frame is a (suspected) out-of-order segment");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Out-Of-Order] ");
+ }
+ }
+ if( ta->flags&TCP_A_LOST_PACKET ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_lost_packet, tvb, 0, 0, "A segment before this frame was lost");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Previous segment lost] ");
+ }
+ }
+ if( ta->flags&TCP_A_ACK_LOST_PACKET ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_ack_lost_packet, tvb, 0, 0, "This frame ACKs a segment we have not seen (lost?)");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ACKed lost segment] ");
+ }
+ }
+ if( ta->flags&TCP_A_KEEP_ALIVE ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_keep_alive, tvb, 0, 0, "This is a TCP keep-alive segment");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive] ");
+ }
+ }
+ if( ta->flags&TCP_A_KEEP_ALIVE_ACK ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_keep_alive_ack, tvb, 0, 0, "This is an ACK to a TCP keep-alive segment");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Keep-Alive ACK] ");
+ }
+ }
+ if( ta->dupack_num){
+ if( ta->flags&TCP_A_DUPLICATE_ACK ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_duplicate_ack, tvb, 0, 0, "This is a TCP duplicate ack");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP Dup ACK %d#%d] ", ta->dupack_frame, ta->dupack_num);
+ }
+ }
+ flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_num,
+ tvb, 0, 0, ta->dupack_num);
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ flags_item=proto_tree_add_uint(tree, hf_tcp_analysis_duplicate_ack_frame,
+ tvb, 0, 0, ta->dupack_frame);
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ }
+ if( ta->flags&TCP_A_ZERO_WINDOW_PROBE ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_zero_window_probe, tvb, 0, 0, "This is a TCP zero-window-probe");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowProbe] ");
+ }
+ }
+ if( ta->flags&TCP_A_ZERO_WINDOW ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_zero_window, tvb, 0, 0, "This is a ZeroWindow segment");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindow] ");
+ }
+ }
+ if( ta->flags&TCP_A_ZERO_WINDOW_VIOLATION ){
+ flags_item=proto_tree_add_none_format(flags_tree, hf_tcp_analysis_zero_window_violation, tvb, 0, 0, "This is a ZeroWindow violation, attempts to write >1 byte of data to a zero-window");
+ PROTO_ITEM_SET_GENERATED(flags_item);
+ if(check_col(pinfo->cinfo, COL_INFO)){
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "[TCP ZeroWindowViolation] ");
+ }
+ }
+ }
+
+}
+
+
+/* Do we still need to do this ...remove_all() even though we dont need
+ * to do anything special? The glib docs are not clear on this and
+ * its better safe than sorry
+ */
+static gboolean
+free_all_acked(gpointer key_arg _U_, gpointer value _U_, gpointer user_data _U_)
+{
+ return TRUE;
+}
+
+static guint
+tcp_acked_hash(gconstpointer k)
+{
+ guint32 frame = (guint32)k;
+
+ return frame;
+}
+static gint
+tcp_acked_equal(gconstpointer k1, gconstpointer k2)
+{
+ guint32 frame1 = (guint32)k1;
+ guint32 frame2 = (guint32)k2;
+
+ return frame1==frame2;
+}
+
+static void
+tcp_analyze_seq_init(void)
+{
+ /* first destroy the tables */
+ if( tcp_analyze_acked_table ){
+ g_hash_table_foreach_remove(tcp_analyze_acked_table,
+ free_all_acked, NULL);
+ g_hash_table_destroy(tcp_analyze_acked_table);
+ tcp_analyze_acked_table = NULL;
+ }
+ if( tcp_rel_seq_table ){
+ g_hash_table_foreach_remove(tcp_rel_seq_table,
+ free_all_acked, NULL);
+ g_hash_table_destroy(tcp_rel_seq_table);
+ tcp_rel_seq_table = NULL;
+ }
+ if( tcp_pdu_tracking_table ){
+ g_hash_table_foreach_remove(tcp_pdu_tracking_table,
+ free_all_acked, NULL);
+ g_hash_table_destroy(tcp_pdu_tracking_table);
+ tcp_pdu_tracking_table = NULL;
+ }
+ if( tcp_pdu_skipping_table ){
+ g_hash_table_foreach_remove(tcp_pdu_skipping_table,
+ free_all_acked, NULL);
+ g_hash_table_destroy(tcp_pdu_skipping_table);
+ tcp_pdu_skipping_table = NULL;
+ }
+
+ /*
+ * Now destroy the chunk from which the conversation table
+ * structures were allocated.
+ */
+ if (tcp_next_pdu_chunk) {
+ g_mem_chunk_destroy(tcp_next_pdu_chunk);
+ tcp_next_pdu_chunk = NULL;
+ }
+ if (tcp_analysis_chunk) {
+ g_mem_chunk_destroy(tcp_analysis_chunk);
+ tcp_analysis_chunk = NULL;
+ }
+ if (tcp_unacked_chunk) {
+ g_mem_chunk_destroy(tcp_unacked_chunk);
+ tcp_unacked_chunk = NULL;
+ }
+ if (tcp_acked_chunk) {
+ g_mem_chunk_destroy(tcp_acked_chunk);
+ tcp_acked_chunk = NULL;
+ }
+ if (tcp_rel_seq_chunk) {
+ g_mem_chunk_destroy(tcp_rel_seq_chunk);
+ tcp_rel_seq_chunk = NULL;
+ }
+
+ if(tcp_analyze_seq){
+ tcp_analyze_acked_table = g_hash_table_new(tcp_acked_hash,
+ tcp_acked_equal);
+ tcp_rel_seq_table = g_hash_table_new(tcp_acked_hash,
+ tcp_acked_equal);
+ tcp_pdu_tracking_table = g_hash_table_new(tcp_acked_hash,
+ tcp_acked_equal);
+ tcp_pdu_skipping_table = g_hash_table_new(tcp_acked_hash,
+ tcp_acked_equal);
+ tcp_next_pdu_chunk = g_mem_chunk_new("tcp_next_pdu_chunk",
+ sizeof(struct tcp_next_pdu),
+ tcp_next_pdu_count * sizeof(struct tcp_next_pdu),
+ G_ALLOC_ONLY);
+ tcp_analysis_chunk = g_mem_chunk_new("tcp_analysis_chunk",
+ sizeof(struct tcp_analysis),
+ tcp_analysis_count * sizeof(struct tcp_analysis),
+ G_ALLOC_ONLY);
+ tcp_unacked_chunk = g_mem_chunk_new("tcp_unacked_chunk",
+ sizeof(struct tcp_unacked),
+ tcp_unacked_count * sizeof(struct tcp_unacked),
+ G_ALLOC_ONLY);
+ tcp_acked_chunk = g_mem_chunk_new("tcp_acked_chunk",
+ sizeof(struct tcp_acked),
+ tcp_acked_count * sizeof(struct tcp_acked),
+ G_ALLOC_ONLY);
+ if(tcp_relative_seq){
+ tcp_rel_seq_chunk = g_mem_chunk_new("tcp_rel_seq_chunk",
+ sizeof(struct tcp_rel_seq),
+ tcp_rel_seq_count * sizeof(struct tcp_rel_seq),
+ G_ALLOC_ONLY);
+ }
+ }
+
+}
+
+/* **************************************************************************
+ * End of tcp sequence number analysis
+ * **************************************************************************/
+
+
+
+
+/* Minimum TCP header length. */
+#define TCPH_MIN_LEN 20
+
+/*
+ * TCP option
+ */
+
+#define TCPOPT_NOP 1 /* Padding */
+#define TCPOPT_EOL 0 /* End of options */
+#define TCPOPT_MSS 2 /* Segment size negotiating */
+#define TCPOPT_WINDOW 3 /* Window scaling */
+#define TCPOPT_SACK_PERM 4 /* SACK Permitted */
+#define TCPOPT_SACK 5 /* SACK Block */
+#define TCPOPT_ECHO 6
+#define TCPOPT_ECHOREPLY 7
+#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
+#define TCPOPT_CC 11
+#define TCPOPT_CCNEW 12
+#define TCPOPT_CCECHO 13
+#define TCPOPT_MD5 19 /* RFC2385 */
+
+/*
+ * TCP option lengths
+ */
+
+#define TCPOLEN_MSS 4
+#define TCPOLEN_WINDOW 3
+#define TCPOLEN_SACK_PERM 2
+#define TCPOLEN_SACK_MIN 2
+#define TCPOLEN_ECHO 6
+#define TCPOLEN_ECHOREPLY 6
+#define TCPOLEN_TIMESTAMP 10
+#define TCPOLEN_CC 6
+#define TCPOLEN_CCNEW 6
+#define TCPOLEN_CCECHO 6
+#define TCPOLEN_MD5 18
+
+
+
+/* Desegmentation of TCP streams */
+/* table to hold defragmented TCP streams */
+static GHashTable *tcp_fragment_table = NULL;
+static void
+tcp_fragment_init(void)
+{
+ fragment_table_init(&tcp_fragment_table);
+}
+
+/* functions to trace tcp segments */
+/* Enable desegmenting of TCP streams */
+static gboolean tcp_desegment = FALSE;
+
+static GHashTable *tcp_segment_table = NULL;
+static GMemChunk *tcp_segment_key_chunk = NULL;
+static int tcp_segment_init_count = 200;
+static GMemChunk *tcp_segment_address_chunk = NULL;
+static int tcp_segment_address_init_count = 500;
+
+typedef struct _tcp_segment_key {
+ /* for own bookkeeping inside packet-tcp.c */
+ address *src;
+ address *dst;
+ guint32 seq;
+ /* xxx */
+ guint16 sport;
+ guint16 dport;
+ guint32 start_seq;
+ guint32 tot_len;
+ guint32 first_frame;
+} tcp_segment_key;
+
+static gboolean
+free_all_segments(gpointer key_arg, gpointer value _U_, gpointer user_data _U_)
+{
+ tcp_segment_key *key = key_arg;
+
+ if((key->src)&&(key->src->data)){
+ g_free((gpointer)key->src->data);
+ key->src->data=NULL;
+ }
+
+ if((key->dst)&&(key->dst->data)){
+ g_free((gpointer)key->dst->data);
+ key->dst->data=NULL;
+ }
+
+ return TRUE;
+}
+
+static guint
+tcp_segment_hash(gconstpointer k)
+{
+ const tcp_segment_key *key = (const tcp_segment_key *)k;
+
+ return key->seq+key->sport;
+}
+
+static gint
+tcp_segment_equal(gconstpointer k1, gconstpointer k2)
+{
+ const tcp_segment_key *key1 = (const tcp_segment_key *)k1;
+ const tcp_segment_key *key2 = (const tcp_segment_key *)k2;
+
+ return ( ( (key1->seq==key2->seq)
+ &&(ADDRESSES_EQUAL(key1->src, key2->src))
+ &&(ADDRESSES_EQUAL(key1->dst, key2->dst))
+ &&(key1->sport==key2->sport)
+ &&(key1->dport==key2->dport)
+ ) ? TRUE:FALSE);
+}
+
+static void
+tcp_desegment_init(void)
+{
+ /*
+ * Free this before freeing any memory chunks; those
+ * chunks contain data we'll look at in "free_all_segments()".
+ */
+ if(tcp_segment_table){
+ g_hash_table_foreach_remove(tcp_segment_table,
+ free_all_segments, NULL);
+ g_hash_table_destroy(tcp_segment_table);
+ tcp_segment_table = NULL;
+ }
+
+ if(tcp_segment_key_chunk){
+ g_mem_chunk_destroy(tcp_segment_key_chunk);
+ tcp_segment_key_chunk = NULL;
+ }
+ if(tcp_segment_address_chunk){
+ g_mem_chunk_destroy(tcp_segment_address_chunk);
+ tcp_segment_address_chunk = NULL;
+ }
+
+ /* dont allocate any hash table or memory chunks unless the user
+ really uses this option
+ */
+ if(!tcp_desegment){
+ return;
+ }
+
+ tcp_segment_table = g_hash_table_new(tcp_segment_hash,
+ tcp_segment_equal);
+
+ tcp_segment_key_chunk = g_mem_chunk_new("tcp_segment_key_chunk",
+ sizeof(tcp_segment_key),
+ tcp_segment_init_count*sizeof(tcp_segment_key),
+ G_ALLOC_ONLY);
+
+ tcp_segment_address_chunk = g_mem_chunk_new("tcp_segment_address_chunk",
+ sizeof(address),
+ tcp_segment_address_init_count*sizeof(address),
+ G_ALLOC_ONLY);
+}
+
+static void
+desegment_tcp(tvbuff_t *tvb, packet_info *pinfo, int offset,
+ guint32 seq, guint32 nxtseq,
+ guint32 sport, guint32 dport,
+ proto_tree *tree, proto_tree *tcp_tree)
+{
+ struct tcpinfo *tcpinfo = pinfo->private_data;
+ fragment_data *ipfd_head=NULL;
+ tcp_segment_key old_tsk, *tsk;
+ gboolean must_desegment = FALSE;
+ gboolean called_dissector = FALSE;
+ int deseg_offset;
+ guint32 deseg_seq;
+ gint nbytes;
+ proto_item *item;
+
+ /*
+ * Initialize these to assume no desegmentation.
+ * If that's not the case, these will be set appropriately
+ * by the subdissector.
+ */
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
+
+ /*
+ * Initialize this to assume that this segment will just be
+ * added to the middle of a desegmented chunk of data, so
+ * that we should show it all as data.
+ * If that's not the case, it will be set appropriately.
+ */
+ deseg_offset = offset;
+
+ /* First we must check if this TCP segment should be desegmented.
+ This is only to check if we should desegment this packet,
+ so we dont spend time doing COPY_ADDRESS/g_free.
+ We just "borrow" some address structures from pinfo instead. Cheaper.
+ */
+ old_tsk.src = &pinfo->src;
+ old_tsk.dst = &pinfo->dst;
+ old_tsk.sport = sport;
+ old_tsk.dport = dport;
+ old_tsk.seq = seq;
+ tsk = g_hash_table_lookup(tcp_segment_table, &old_tsk);
+
+ if(tsk){
+ /* OK, this segment was found, which means it continues
+ a higher-level PDU. This means we must desegment it.
+ Add it to the defragmentation lists.
+ */
+ ipfd_head = fragment_add(tvb, offset, pinfo, tsk->first_frame,
+ tcp_fragment_table,
+ seq - tsk->start_seq,
+ nxtseq - seq,
+ (LT_SEQ (nxtseq,tsk->start_seq + tsk->tot_len)) );
+
+ if(!ipfd_head){
+ /* fragment_add() returned NULL, This means that
+ desegmentation is not completed yet.
+ (its like defragmentation but we know we will
+ always add the segments in order).
+ XXX - no, we don't; there is no guarantee that
+ TCP segments are in order on the wire.
+
+ we must add next segment to our table so we will
+ find it later.
+ */
+ tcp_segment_key *new_tsk;
+
+ new_tsk = g_mem_chunk_alloc(tcp_segment_key_chunk);
+ memcpy(new_tsk, tsk, sizeof(tcp_segment_key));
+ new_tsk->seq=nxtseq;
+ g_hash_table_insert(tcp_segment_table,new_tsk,new_tsk);
+ }
+ } else {
+ /* This segment was not found in our table, so it doesn't
+ contain a continuation of a higher-level PDU.
+ Call the normal subdissector.
+ */
+ process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree,
+ sport, dport, 0, 0, FALSE);
+ called_dissector = TRUE;
+
+ /* Did the subdissector ask us to desegment some more data
+ before it could handle the packet?
+ If so we have to create some structures in our table but
+ this is something we only do the first time we see this
+ packet.
+ */
+ if(pinfo->desegment_len) {
+ if (!pinfo->fd->flags.visited)
+ must_desegment = TRUE;
+
+ /*
+ * Set "deseg_offset" to the offset in "tvb"
+ * of the first byte of data that the
+ * subdissector didn't process.
+ */
+ deseg_offset = offset + pinfo->desegment_offset;
+ }
+
+ /* Either no desegmentation is necessary, or this is
+ segment contains the beginning but not the end of
+ a higher-level PDU and thus isn't completely
+ desegmented.
+ */
+ ipfd_head = NULL;
+ }
+
+ /* is it completely desegmented? */
+ if(ipfd_head){
+ fragment_data *ipfd;
+
+ /*
+ * Yes, we think it is.
+ * We only call subdissector for the last segment.
+ * Note that the last segment may include more than what
+ * we needed.
+ */
+ if(GE_SEQ(nxtseq, tsk->start_seq + tsk->tot_len)){
+ /*
+ * OK, this is the last segment.
+ * Let's call the subdissector with the desegmented
+ * data.
+ */
+ tvbuff_t *next_tvb;
+ int old_len;
+
+ /* create a new TVB structure for desegmented data */
+ next_tvb = tvb_new_real_data(ipfd_head->data,
+ ipfd_head->datalen, ipfd_head->datalen);
+
+ /* add this tvb as a child to the original one */
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+
+ /* add desegmented data to the data source list */
+ add_new_data_source(pinfo, next_tvb, "Desegmented TCP");
+
+ /*
+ * Supply the sequence number of the first of the
+ * reassembled bytes.
+ */
+ tcpinfo->seq = tsk->start_seq;
+
+ /* indicate that this is reassembled data */
+ tcpinfo->is_reassembled = TRUE;
+
+ /* call subdissector */
+ process_tcp_payload(next_tvb, 0, pinfo, tree,
+ tcp_tree, sport, dport, 0, 0, FALSE);
+ called_dissector = TRUE;
+
+ /*
+ * OK, did the subdissector think it was completely
+ * desegmented, or does it think we need even more
+ * data?
+ */
+ old_len=(int)(tvb_reported_length(next_tvb)-tvb_reported_length_remaining(tvb, offset));
+ if(pinfo->desegment_len &&
+ pinfo->desegment_offset<=old_len){
+ tcp_segment_key *new_tsk;
+
+ /*
+ * "desegment_len" isn't 0, so it needs more
+ * data for something - and "desegment_offset"
+ * is before "old_len", so it needs more data
+ * to dissect the stuff we thought was
+ * completely desegmented (as opposed to the
+ * stuff at the beginning being completely
+ * desegmented, but the stuff at the end
+ * being a new higher-level PDU that also
+ * needs desegmentation).
+ */
+ fragment_set_partial_reassembly(pinfo,tsk->first_frame,tcp_fragment_table);
+ tsk->tot_len = tvb_reported_length(next_tvb) + pinfo->desegment_len;
+
+ /*
+ * Update tsk structure.
+ * Can ask ->next->next because at least there's a hdr and one
+ * entry in fragment_add()
+ */
+ for(ipfd=ipfd_head->next; ipfd->next; ipfd=ipfd->next){
+ old_tsk.seq = tsk->start_seq + ipfd->offset;
+ new_tsk = g_hash_table_lookup(tcp_segment_table, &old_tsk);
+ new_tsk->tot_len = tsk->tot_len;
+ }
+
+ /* this is the next segment in the sequence we want */
+ new_tsk = g_mem_chunk_alloc(tcp_segment_key_chunk);
+ memcpy(new_tsk, tsk, sizeof(tcp_segment_key));
+ new_tsk->seq = nxtseq;
+ g_hash_table_insert(tcp_segment_table,new_tsk,new_tsk);
+ } else {
+ /*
+ * Show the stuff in this TCP segment as
+ * just raw TCP segment data.
+ */
+ nbytes =
+ tvb_reported_length_remaining(tvb, offset);
+ proto_tree_add_text(tcp_tree, tvb, offset, -1,
+ "TCP segment data (%u byte%s)", nbytes,
+ plurality(nbytes, "", "s"));
+
+ /*
+ * The subdissector thought it was completely
+ * desegmented (although the stuff at the
+ * end may, in turn, require desegmentation),
+ * so we show a tree with all segments.
+ */
+ show_fragment_tree(ipfd_head, &tcp_segment_items,
+ tcp_tree, pinfo, next_tvb);
+
+ /* Did the subdissector ask us to desegment
+ some more data? This means that the data
+ at the beginning of this segment completed
+ a higher-level PDU, but the data at the
+ end of this segment started a higher-level
+ PDU but didn't complete it.
+
+ If so, we have to create some structures
+ in our table, but this is something we
+ only do the first time we see this packet.
+ */
+ if(pinfo->desegment_len) {
+ if (!pinfo->fd->flags.visited)
+ must_desegment = TRUE;
+
+ /* The stuff we couldn't dissect
+ must have come from this segment,
+ so it's all in "tvb".
+
+ "pinfo->desegment_offset" is
+ relative to the beginning of
+ "next_tvb"; we want an offset
+ relative to the beginning of "tvb".
+
+ First, compute the offset relative
+ to the *end* of "next_tvb" - i.e.,
+ the number of bytes before the end
+ of "next_tvb" at which the
+ subdissector stopped. That's the
+ length of "next_tvb" minus the
+ offset, relative to the beginning
+ of "next_tvb, at which the
+ subdissector stopped.
+ */
+ deseg_offset =
+ ipfd_head->datalen - pinfo->desegment_offset;
+
+ /* "tvb" and "next_tvb" end at the
+ same byte of data, so the offset
+ relative to the end of "next_tvb"
+ of the byte at which we stopped
+ is also the offset relative to
+ the end of "tvb" of the byte at
+ which we stopped.
+
+ Convert that back into an offset
+ relative to the beginninng of
+ "tvb", by taking the length of
+ "tvb" and subtracting the offset
+ relative to the end.
+ */
+ deseg_offset=tvb_reported_length(tvb) - deseg_offset;
+ }
+ }
+ }
+ }
+
+ if (must_desegment) {
+ tcp_segment_key *tsk, *new_tsk;
+
+ /*
+ * The sequence number at which the stuff to be desegmented
+ * starts is the sequence number of the byte at an offset
+ * of "deseg_offset" into "tvb".
+ *
+ * The sequence number of the byte at an offset of "offset"
+ * is "seq", i.e. the starting sequence number of this
+ * segment, so the sequence number of the byte at
+ * "deseg_offset" is "seq + (deseg_offset - offset)".
+ */
+ deseg_seq = seq + (deseg_offset - offset);
+
+ /*
+ * XXX - how do we detect out-of-order transmissions?
+ * We can't just check for "nxtseq" being greater than
+ * "tsk->start_seq"; for now, we check for the difference
+ * being less than a megabyte, but this is a really
+ * gross hack - we really need to handle out-of-order
+ * transmissions correctly.
+ */
+ if ((nxtseq - deseg_seq) <= 1024*1024) {
+ /* OK, subdissector wants us to desegment
+ some data before it can process it. Add
+ what remains of this packet and set
+ up next packet/sequence number as well.
+
+ We must remember this segment
+ */
+ tsk = g_mem_chunk_alloc(tcp_segment_key_chunk);
+ tsk->src = g_mem_chunk_alloc(tcp_segment_address_chunk);
+ COPY_ADDRESS(tsk->src, &pinfo->src);
+ tsk->dst = g_mem_chunk_alloc(tcp_segment_address_chunk);
+ COPY_ADDRESS(tsk->dst, &pinfo->dst);
+ tsk->seq = deseg_seq;
+ tsk->start_seq = tsk->seq;
+ tsk->tot_len = nxtseq - tsk->start_seq + pinfo->desegment_len;
+ tsk->first_frame = pinfo->fd->num;
+ tsk->sport=sport;
+ tsk->dport=dport;
+ g_hash_table_insert(tcp_segment_table, tsk, tsk);
+
+ /* Add portion of segment unprocessed by the subdissector
+ to defragmentation lists */
+ fragment_add(tvb, deseg_offset, pinfo, tsk->first_frame,
+ tcp_fragment_table,
+ tsk->seq - tsk->start_seq,
+ nxtseq - tsk->start_seq,
+ LT_SEQ (nxtseq, tsk->start_seq + tsk->tot_len));
+
+ /* this is the next segment in the sequence we want */
+ new_tsk = g_mem_chunk_alloc(tcp_segment_key_chunk);
+ memcpy(new_tsk, tsk, sizeof(tcp_segment_key));
+ new_tsk->seq = nxtseq;
+ g_hash_table_insert(tcp_segment_table,new_tsk,new_tsk);
+ }
+ }
+
+ if (!called_dissector || pinfo->desegment_len != 0) {
+ if (ipfd_head != NULL && ipfd_head->reassembled_in != 0) {
+ /*
+ * We know what frame this PDU is reassembled in;
+ * let the user know.
+ */
+ item=proto_tree_add_uint(tcp_tree, hf_tcp_reassembled_in,
+ tvb, 0, 0, ipfd_head->reassembled_in);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+
+ /*
+ * Either we didn't call the subdissector at all (i.e.,
+ * this is a segment that contains the middle of a
+ * higher-level PDU, but contains neither the beginning
+ * nor the end), or the subdissector couldn't dissect it
+ * all, as some data was missing (i.e., it set
+ * "pinfo->desegment_len" to the amount of additional
+ * data it needs).
+ */
+ if (pinfo->desegment_offset == 0) {
+ /*
+ * It couldn't, in fact, dissect any of it (the
+ * first byte it couldn't dissect is at an offset
+ * of "pinfo->desegment_offset" from the beginning
+ * of the payload, and that's 0).
+ * Just mark this as TCP.
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)){
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_set_str(pinfo->cinfo, COL_INFO, "[Desegmented TCP]");
+ }
+ }
+
+ /*
+ * Show what's left in the packet as just raw TCP segment
+ * data.
+ * XXX - remember what protocol the last subdissector
+ * was, and report it as a continuation of that, instead?
+ */
+ nbytes = tvb_reported_length_remaining(tvb, deseg_offset);
+ proto_tree_add_text(tcp_tree, tvb, deseg_offset, -1,
+ "TCP segment data (%u byte%s)", nbytes,
+ plurality(nbytes, "", "s"));
+ }
+ pinfo->can_desegment=0;
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
+}
+
+/*
+ * Loop for dissecting PDUs within a TCP stream; assumes that a PDU
+ * consists of a fixed-length chunk of data that contains enough information
+ * to determine the length of the PDU, followed by rest of the PDU.
+ *
+ * The first three arguments are the arguments passed to the dissector
+ * that calls this routine.
+ *
+ * "proto_desegment" is the dissector's flag controlling whether it should
+ * desegment PDUs that cross TCP segment boundaries.
+ *
+ * "fixed_len" is the length of the fixed-length part of the PDU.
+ *
+ * "get_pdu_len()" is a routine called to get the length of the PDU from
+ * the fixed-length part of the PDU; it's passed "tvb" and "offset".
+ *
+ * "dissect_pdu()" is the routine to dissect a PDU.
+ */
+void
+tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean proto_desegment, guint fixed_len,
+ guint (*get_pdu_len)(tvbuff_t *, int),
+ void (*dissect_pdu)(tvbuff_t *, packet_info *, proto_tree *))
+{
+ volatile int offset = 0;
+ int offset_before;
+ guint length_remaining;
+ guint plen;
+ guint length;
+ tvbuff_t *next_tvb;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * We use "tvb_ensure_length_remaining()" to make sure there actually
+ * *is* data remaining. The protocol we're handling could conceivably
+ * consists of a sequence of fixed-length PDUs, and therefore the
+ * "get_pdu_len" routine might not actually fetch anything from
+ * the tvbuff, and thus might not cause an exception to be thrown if
+ * we've run past the end of the tvbuff.
+ *
+ * This means we're guaranteed that "length_remaining" is positive.
+ */
+ length_remaining = tvb_ensure_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (proto_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the fixed-length part of the PDU split across segment
+ * boundaries?
+ */
+ if (length_remaining < fixed_len) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this message
+ * starts in the data it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = fixed_len - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Get the length of the PDU.
+ */
+ plen = (*get_pdu_len)(tvb, offset);
+ if (plen < fixed_len) {
+ /*
+ * The PDU length from the fixed-length portion probably didn't
+ * include the fixed-length portion's length, and was probably so
+ * large that the total length overflowed.
+ *
+ * Report this as an error.
+ */
+ show_reported_bounds_error(tvb, pinfo, tree);
+ return;
+ }
+
+ /* give a hint to TCP where the next PDU starts
+ * so that it can attempt to find it in case it starts
+ * somewhere in the middle of a segment.
+ */
+ if(!pinfo->fd->flags.visited && tcp_analyze_seq){
+ guint remaining_bytes;
+ remaining_bytes=tvb_reported_length_remaining(tvb, offset);
+ if(plen>remaining_bytes){
+ pinfo->want_pdu_tracking=2;
+ pinfo->bytes_until_next_pdu=plen-remaining_bytes;
+ }
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (proto_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the PDU split across segment boundaries?
+ */
+ if (length_remaining < plen) {
+ /*
+ * Yes. Tell the TCP dissector where the data for this message
+ * starts in the data it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = plen - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload we have
+ * available. Make its reported length the amount of data in the PDU.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector will throw a
+ * BoundsError exception, rather than a ReportedBoundsError exception.
+ * We really want a tvbuff where the length is "length", the reported
+ * length is "plen", and the "if the snapshot length were infinite"
+ * length is the minimum of the reported length of the tvbuff handed
+ * to us and "plen", with a new type of exception thrown if the offset
+ * is within the reported length but beyond that third length, with
+ * that exception getting the "Unreassembled Packet" error.
+ */
+ length = length_remaining;
+ if (length > plen)
+ length = plen;
+ next_tvb = tvb_new_subset(tvb, offset, length, plen);
+
+ /*
+ * Dissect the PDU.
+ *
+ * Catch the ReportedBoundsError exception; if this particular message
+ * happens to get a ReportedBoundsError exception, that doesn't mean
+ * that we should stop dissecting PDUs within this frame or chunk of
+ * reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing more to
+ * see, so we just re-throw it.
+ */
+ TRY {
+ (*dissect_pdu)(next_tvb, pinfo, tree);
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ }
+ ENDTRY;
+
+ /*
+ * Step to the next PDU.
+ * Make sure we don't overflow.
+ */
+ offset_before = offset;
+ offset += plen;
+ if (offset <= offset_before)
+ break;
+ }
+}
+
+static void
+tcp_info_append_uint(packet_info *pinfo, const char *abbrev, guint32 val)
+{
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%u", abbrev, val);
+}
+
+static void
+dissect_tcpopt_maxseg(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
+{
+ guint16 mss;
+
+ mss = tvb_get_ntohs(tvb, offset + 2);
+ proto_tree_add_boolean_hidden(opt_tree, hf_tcp_option_mss, tvb, offset,
+ optlen, TRUE);
+ proto_tree_add_uint_format(opt_tree, hf_tcp_option_mss_val, tvb, offset,
+ optlen, mss, "%s: %u bytes", optp->name, mss);
+ tcp_info_append_uint(pinfo, "MSS", mss);
+}
+
+static void
+dissect_tcpopt_wscale(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
+{
+ guint8 ws;
+
+ ws = tvb_get_guint8(tvb, offset + 2);
+ proto_tree_add_boolean_hidden(opt_tree, hf_tcp_option_wscale, tvb,
+ offset, optlen, TRUE);
+ proto_tree_add_uint_format(opt_tree, hf_tcp_option_wscale_val, tvb,
+ offset, optlen, ws, "%s: %u (multiply by %u)",
+ optp->name, ws, 1 << ws);
+ tcp_info_append_uint(pinfo, "WS", ws);
+ if(!pinfo->fd->flags.visited && tcp_analyze_seq && tcp_relative_seq){
+ pdu_store_window_scale_option(pinfo, ws);
+ }
+}
+
+static void
+dissect_tcpopt_sack(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
+{
+ proto_tree *field_tree = NULL;
+ proto_item *tf;
+ guint leftedge, rightedge;
+
+ tf = proto_tree_add_text(opt_tree, tvb, offset, optlen, "%s:", optp->name);
+ offset += 2; /* skip past type and length */
+ optlen -= 2; /* subtract size of type and length */
+ while (optlen > 0) {
+ if (field_tree == NULL) {
+ /* Haven't yet made a subtree out of this option. Do so. */
+ field_tree = proto_item_add_subtree(tf, *optp->subtree_index);
+ proto_tree_add_boolean_hidden(field_tree, hf_tcp_option_sack, tvb,
+ offset, optlen, TRUE);
+ }
+ if (optlen < 4) {
+ proto_tree_add_text(field_tree, tvb, offset, optlen,
+ "(suboption would go past end of option)");
+ break;
+ }
+ leftedge = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sle, tvb,
+ offset, 4, leftedge,
+ "left edge = %u", leftedge);
+ optlen -= 4;
+ if (optlen < 4) {
+ proto_tree_add_text(field_tree, tvb, offset, optlen,
+ "(suboption would go past end of option)");
+ break;
+ }
+ /* XXX - check whether it goes past end of packet */
+ rightedge = tvb_get_ntohl(tvb, offset + 4);
+ optlen -= 4;
+ proto_tree_add_uint_format(field_tree, hf_tcp_option_sack_sre, tvb,
+ offset+4, 4, rightedge,
+ "right edge = %u", rightedge);
+ tcp_info_append_uint(pinfo, "SLE", leftedge);
+ tcp_info_append_uint(pinfo, "SRE", rightedge);
+ offset += 8;
+ }
+}
+
+static void
+dissect_tcpopt_echo(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
+{
+ guint32 echo;
+
+ echo = tvb_get_ntohl(tvb, offset + 2);
+ proto_tree_add_boolean_hidden(opt_tree, hf_tcp_option_echo, tvb, offset,
+ optlen, TRUE);
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: %u", optp->name, echo);
+ tcp_info_append_uint(pinfo, "ECHO", echo);
+}
+
+static void
+dissect_tcpopt_timestamp(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
+{
+ guint32 tsv, tser;
+
+ tsv = tvb_get_ntohl(tvb, offset + 2);
+ tser = tvb_get_ntohl(tvb, offset + 6);
+ proto_tree_add_boolean_hidden(opt_tree, hf_tcp_option_time_stamp, tvb,
+ offset, optlen, TRUE);
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: tsval %u, tsecr %u", optp->name, tsv, tser);
+ tcp_info_append_uint(pinfo, "TSV", tsv);
+ tcp_info_append_uint(pinfo, "TSER", tser);
+}
+
+static void
+dissect_tcpopt_cc(const ip_tcp_opt *optp, tvbuff_t *tvb,
+ int offset, guint optlen, packet_info *pinfo, proto_tree *opt_tree)
+{
+ guint32 cc;
+
+ cc = tvb_get_ntohl(tvb, offset + 2);
+ proto_tree_add_boolean_hidden(opt_tree, hf_tcp_option_cc, tvb, offset,
+ optlen, TRUE);
+ proto_tree_add_text(opt_tree, tvb, offset, optlen,
+ "%s: %u", optp->name, cc);
+ tcp_info_append_uint(pinfo, "CC", cc);
+}
+
+static const ip_tcp_opt tcpopts[] = {
+ {
+ TCPOPT_EOL,
+ "EOL",
+ NULL,
+ NO_LENGTH,
+ 0,
+ NULL,
+ },
+ {
+ TCPOPT_NOP,
+ "NOP",
+ NULL,
+ NO_LENGTH,
+ 0,
+ NULL,
+ },
+ {
+ TCPOPT_MSS,
+ "Maximum segment size",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_MSS,
+ dissect_tcpopt_maxseg
+ },
+ {
+ TCPOPT_WINDOW,
+ "Window scale",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_WINDOW,
+ dissect_tcpopt_wscale
+ },
+ {
+ TCPOPT_SACK_PERM,
+ "SACK permitted",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_SACK_PERM,
+ NULL,
+ },
+ {
+ TCPOPT_SACK,
+ "SACK",
+ &ett_tcp_option_sack,
+ VARIABLE_LENGTH,
+ TCPOLEN_SACK_MIN,
+ dissect_tcpopt_sack
+ },
+ {
+ TCPOPT_ECHO,
+ "Echo",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_ECHO,
+ dissect_tcpopt_echo
+ },
+ {
+ TCPOPT_ECHOREPLY,
+ "Echo reply",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_ECHOREPLY,
+ dissect_tcpopt_echo
+ },
+ {
+ TCPOPT_TIMESTAMP,
+ "Time stamp",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_TIMESTAMP,
+ dissect_tcpopt_timestamp
+ },
+ {
+ TCPOPT_CC,
+ "CC",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_CC,
+ dissect_tcpopt_cc
+ },
+ {
+ TCPOPT_CCNEW,
+ "CC.NEW",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_CCNEW,
+ dissect_tcpopt_cc
+ },
+ {
+ TCPOPT_CCECHO,
+ "CC.ECHO",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_CCECHO,
+ dissect_tcpopt_cc
+ },
+ {
+ TCPOPT_MD5,
+ "TCP MD5 signature",
+ NULL,
+ FIXED_LENGTH,
+ TCPOLEN_MD5,
+ NULL
+ }
+};
+
+#define N_TCP_OPTS (sizeof tcpopts / sizeof tcpopts[0])
+
+/* Determine if there is a sub-dissector and call it; return TRUE
+ if there was a sub-dissector, FALSE otherwise.
+
+ This has been separated into a stand alone routine to other protocol
+ dissectors can call to it, e.g., SOCKS. */
+
+static gboolean try_heuristic_first = FALSE;
+
+gboolean
+decode_tcp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, int src_port, int dst_port)
+{
+ tvbuff_t *next_tvb;
+ int low_port, high_port;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+/* determine if this packet is part of a conversation and call dissector */
+/* for the conversation if available */
+
+ if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_TCP,
+ src_port, dst_port, next_tvb, pinfo, tree)){
+ pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
+ return TRUE;
+ }
+
+ if (try_heuristic_first) {
+ /* do lookup with the heuristic subdissector table */
+ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
+ pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
+ return TRUE;
+ }
+ }
+
+ /* Do lookups with the subdissector table.
+ We try the port number with the lower value first, followed by the
+ port number with the higher value. This means that, for packets
+ where a dissector is registered for *both* port numbers:
+
+ 1) we pick the same dissector for traffic going in both directions;
+
+ 2) we prefer the port number that's more likely to be the right
+ one (as that prefers well-known ports to reserved ports);
+
+ although there is, of course, no guarantee that any such strategy
+ will always pick the right port number.
+
+ XXX - we ignore port numbers of 0, as some dissectors use a port
+ number of 0 to disable the port. */
+ if (src_port > dst_port) {
+ low_port = dst_port;
+ high_port = src_port;
+ } else {
+ low_port = src_port;
+ high_port = dst_port;
+ }
+ if (low_port != 0 &&
+ dissector_try_port(subdissector_table, low_port, next_tvb, pinfo, tree)){
+ pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
+ return TRUE;
+ }
+ if (high_port != 0 &&
+ dissector_try_port(subdissector_table, high_port, next_tvb, pinfo, tree)){
+ pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
+ return TRUE;
+ }
+
+ if (!try_heuristic_first) {
+ /* do lookup with the heuristic subdissector table */
+ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)){
+ pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
+ return TRUE;
+ }
+ }
+
+ /* Oh, well, we don't know this; dissect it as data. */
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+
+ pinfo->want_pdu_tracking -= !!(pinfo->want_pdu_tracking);
+ return FALSE;
+}
+
+static void
+process_tcp_payload(tvbuff_t *tvb, volatile int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tcp_tree, int src_port, int dst_port,
+ guint32 seq, guint32 nxtseq, gboolean is_tcp_segment)
+{
+ pinfo->want_pdu_tracking=0;
+
+ TRY {
+ if(is_tcp_segment){
+ /*qqq see if it is an unaligned PDU */
+ if(tcp_analyze_seq && (!tcp_desegment)){
+ if(seq || nxtseq){
+ offset=scan_for_next_pdu(tvb, tcp_tree, pinfo, offset,
+ seq, nxtseq);
+ }
+ }
+ }
+ /* if offset is -1 this means that this segment is known
+ * to be fully inside a previously detected pdu
+ * so we dont even need to try to dissect it either.
+ */
+ if( (offset!=-1) &&
+ decode_tcp_ports(tvb, offset, pinfo, tree, src_port,
+ dst_port) ){
+ /*
+ * We succeeded in handing off to a subdissector.
+ *
+ * Is this a TCP segment or a reassembled chunk of
+ * TCP payload?
+ */
+ if(is_tcp_segment){
+ /* if !visited, check want_pdu_tracking and
+ store it in table */
+ if((!pinfo->fd->flags.visited) &&
+ tcp_analyze_seq && pinfo->want_pdu_tracking){
+ if(seq || nxtseq){
+ pdu_store_sequencenumber_of_next_pdu(
+ pinfo,
+ seq,
+ nxtseq+pinfo->bytes_until_next_pdu);
+ }
+ }
+ }
+ }
+ }
+ CATCH_ALL {
+ /* We got an exception. At this point the dissection is
+ * completely aborted and execution will be transfered back
+ * to (probably) the frame dissector.
+ * Here we have to place whatever we want the dissector
+ * to do before aborting the tcp dissection.
+ */
+ /*
+ * Is this a TCP segment or a reassembled chunk of TCP
+ * payload?
+ */
+ if(is_tcp_segment){
+ /*
+ * It's from a TCP segment.
+ *
+ * Handle TCP seq# analysis, print any extra SEQ/ACK
+ * data for this segment.
+ */
+ if(tcp_analyze_seq){
+ tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree);
+ }
+ /*
+ * if !visited, check want_pdu_tracking and store it
+ * in table
+ */
+ if((!pinfo->fd->flags.visited) && tcp_analyze_seq && pinfo->want_pdu_tracking){
+ if(seq || nxtseq){
+ pdu_store_sequencenumber_of_next_pdu(pinfo,
+ seq,
+ nxtseq+pinfo->bytes_until_next_pdu);
+ }
+ }
+ }
+ RETHROW;
+ }
+ ENDTRY;
+}
+
+void
+dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 seq,
+ guint32 nxtseq, guint32 sport, guint32 dport,
+ proto_tree *tree, proto_tree *tcp_tree)
+{
+ gboolean save_fragmented;
+
+ /* Can we desegment this segment? */
+ if (pinfo->can_desegment) {
+ /* Yes. */
+ desegment_tcp(tvb, pinfo, offset, seq, nxtseq, sport, dport, tree,
+ tcp_tree);
+ } else {
+ /* No - just call the subdissector.
+ Mark this as fragmented, so if somebody throws an exception,
+ we don't report it as a malformed frame. */
+ save_fragmented = pinfo->fragmented;
+ pinfo->fragmented = TRUE;
+ process_tcp_payload(tvb, offset, pinfo, tree, tcp_tree, sport, dport,
+ seq, nxtseq, TRUE);
+ pinfo->fragmented = save_fragmented;
+ }
+}
+
+static void
+dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 th_off_x2; /* combines th_off and th_x2 */
+ guint16 th_sum;
+ guint16 th_urp;
+ proto_tree *tcp_tree = NULL, *field_tree = NULL;
+ proto_item *ti = NULL, *tf;
+ int offset = 0;
+ gchar flags[64] = "<None>";
+ gchar *fstr[] = {"FIN", "SYN", "RST", "PSH", "ACK", "URG", "ECN", "CWR" };
+ gint fpos = 0, i;
+ guint bpos;
+ guint optlen;
+ guint32 nxtseq = 0;
+ guint reported_len;
+ vec_t cksum_vec[4];
+ guint32 phdr[2];
+ guint16 computed_cksum;
+ guint length_remaining;
+ gboolean desegment_ok;
+ struct tcpinfo tcpinfo;
+ static struct tcpheader tcphstruct[4], *tcph;
+ static int tcph_count=0;
+
+ tcph_count++;
+ if(tcph_count>=4){
+ tcph_count=0;
+ }
+ tcph=&tcphstruct[tcph_count];
+ SET_ADDRESS(&tcph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
+ SET_ADDRESS(&tcph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCP");
+
+ /* Clear out the Info column. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tcph->th_sport = tvb_get_ntohs(tvb, offset);
+ tcph->th_dport = tvb_get_ntohs(tvb, offset + 2);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s > %s",
+ get_tcp_port(tcph->th_sport), get_tcp_port(tcph->th_dport));
+ }
+ if (tree) {
+ if (tcp_summary_in_tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_tcp, tvb, 0, -1,
+ "Transmission Control Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
+ get_tcp_port(tcph->th_sport), tcph->th_sport,
+ get_tcp_port(tcph->th_dport), tcph->th_dport);
+ }
+ else {
+ ti = proto_tree_add_item(tree, proto_tcp, tvb, 0, -1, FALSE);
+ }
+ tcp_tree = proto_item_add_subtree(ti, ett_tcp);
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_srcport, tvb, offset, 2, tcph->th_sport,
+ "Source port: %s (%u)", get_tcp_port(tcph->th_sport), tcph->th_sport);
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_dstport, tvb, offset + 2, 2, tcph->th_dport,
+ "Destination port: %s (%u)", get_tcp_port(tcph->th_dport), tcph->th_dport);
+ proto_tree_add_uint_hidden(tcp_tree, hf_tcp_port, tvb, offset, 2, tcph->th_sport);
+ proto_tree_add_uint_hidden(tcp_tree, hf_tcp_port, tvb, offset + 2, 2, tcph->th_dport);
+ }
+
+ /* Set the source and destination port numbers as soon as we get them,
+ so that they're available to the "Follow TCP Stream" code even if
+ we throw an exception dissecting the rest of the TCP header. */
+ pinfo->ptype = PT_TCP;
+ pinfo->srcport = tcph->th_sport;
+ pinfo->destport = tcph->th_dport;
+
+ tcph->th_seq = tvb_get_ntohl(tvb, offset + 4);
+ tcph->th_ack = tvb_get_ntohl(tvb, offset + 8);
+ th_off_x2 = tvb_get_guint8(tvb, offset + 12);
+ tcph->th_flags = tvb_get_guint8(tvb, offset + 13);
+ tcph->th_win = tvb_get_ntohs(tvb, offset + 14);
+ tcph->th_hlen = hi_nibble(th_off_x2) * 4; /* TCP header length, in bytes */
+
+ /*
+ * If we've been handed an IP fragment, we don't know how big the TCP
+ * segment is, so don't do anything that requires that we know that.
+ *
+ * The same applies if we're part of an error packet. (XXX - if the
+ * ICMP and ICMPv6 dissectors could set a "this is how big the IP
+ * header says it is" length in the tvbuff, we could use that; such
+ * a length might also be useful for handling packets where the IP
+ * length is bigger than the actual data available in the frame; the
+ * dissectors should trust that length, and then throw a
+ * ReportedBoundsError exception when they go past the end of the frame.)
+ *
+ * We also can't determine the segment length if the reported length
+ * of the TCP packet is less than the TCP header length.
+ */
+ reported_len = tvb_reported_length(tvb);
+
+ if (!pinfo->fragmented && !pinfo->in_error_pkt) {
+ if (reported_len < tcph->th_hlen) {
+ proto_tree_add_text(tcp_tree, tvb, offset, 0,
+ "Short segment. Segment/fragment does not contain a full TCP header"
+ " (might be NMAP or someone else deliberately sending unusual packets)");
+ tcph->th_have_seglen = FALSE;
+ } else {
+ /* Compute the length of data in this segment. */
+ tcph->th_seglen = reported_len - tcph->th_hlen;
+ tcph->th_have_seglen = TRUE;
+
+ if (tree) { /* Add the seglen as an invisible field */
+
+ proto_tree_add_uint_hidden(ti, hf_tcp_len, tvb, offset, 4, tcph->th_seglen);
+
+ }
+
+ /* handle TCP seq# analysis parse all new segments we see */
+ if(tcp_analyze_seq){
+ if(!(pinfo->fd->flags.visited)){
+ tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win);
+ }
+ if(tcp_relative_seq){
+ tcp_get_relative_seq_ack(pinfo->fd->num, &(tcph->th_seq), &(tcph->th_ack), &(tcph->th_win));
+ }
+ }
+
+ /* Compute the sequence number of next octet after this segment. */
+ nxtseq = tcph->th_seq + tcph->th_seglen;
+ }
+ } else
+ tcph->th_have_seglen = FALSE;
+
+ if (check_col(pinfo->cinfo, COL_INFO) || tree) {
+ for (i = 0; i < 8; i++) {
+ bpos = 1 << i;
+ if (tcph->th_flags & bpos) {
+ if (fpos) {
+ strcpy(&flags[fpos], ", ");
+ fpos += 2;
+ }
+ strcpy(&flags[fpos], fstr[i]);
+ fpos += 3;
+ }
+ }
+ flags[fpos] = '\0';
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] Seq=%u Ack=%u Win=%u",
+ flags, tcph->th_seq, tcph->th_ack, tcph->th_win);
+ }
+
+ if (tree) {
+ if (tcp_summary_in_tree) {
+ proto_item_append_text(ti, ", Seq: %u", tcph->th_seq);
+ }
+ if(tcp_relative_seq){
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq, "Sequence number: %u (relative sequence number)", tcph->th_seq);
+ } else {
+ proto_tree_add_uint(tcp_tree, hf_tcp_seq, tvb, offset + 4, 4, tcph->th_seq);
+ }
+ }
+
+ if (tcph->th_hlen < TCPH_MIN_LEN) {
+ /* Give up at this point; we put the source and destination port in
+ the tree, before fetching the header length, so that they'll
+ show up if this is in the failing packet in an ICMP error packet,
+ but it's now time to give up if the header length is bogus. */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", bogus TCP header length (%u, must be at least %u)",
+ tcph->th_hlen, TCPH_MIN_LEN);
+ if (tree) {
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
+ "Header length: %u bytes (bogus, must be at least %u)", tcph->th_hlen,
+ TCPH_MIN_LEN);
+ }
+ return;
+ }
+
+ if (tree) {
+ if (tcp_summary_in_tree) {
+ proto_item_append_text(ti, ", Ack: %u", tcph->th_ack);
+ if (tcph->th_have_seglen)
+ proto_item_append_text(ti, ", Len: %u", tcph->th_seglen);
+ }
+ proto_item_set_len(ti, tcph->th_hlen);
+ if (tcph->th_have_seglen) {
+ if (nxtseq != tcph->th_seq) {
+ if(tcp_relative_seq){
+ tf=proto_tree_add_uint_format(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq, "Next sequence number: %u (relative sequence number)", nxtseq);
+ } else {
+ tf=proto_tree_add_uint(tcp_tree, hf_tcp_nxtseq, tvb, offset, 0, nxtseq);
+ }
+ PROTO_ITEM_SET_GENERATED(tf);
+ }
+ }
+ if (tcph->th_flags & TH_ACK) {
+ if(tcp_relative_seq){
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack, "Acknowledgement number: %u (relative ack number)", tcph->th_ack);
+ } else {
+ proto_tree_add_uint(tcp_tree, hf_tcp_ack, tvb, offset + 8, 4, tcph->th_ack);
+ }
+ }
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
+ "Header length: %u bytes", tcph->th_hlen);
+ tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 13, 1,
+ tcph->th_flags, "Flags: 0x%04x (%s)", tcph->th_flags, flags);
+ field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_cwr, tvb, offset + 13, 1, tcph->th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_ecn, tvb, offset + 13, 1, tcph->th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_urg, tvb, offset + 13, 1, tcph->th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_ack, tvb, offset + 13, 1, tcph->th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_push, tvb, offset + 13, 1, tcph->th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_reset, tvb, offset + 13, 1, tcph->th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_syn, tvb, offset + 13, 1, tcph->th_flags);
+ proto_tree_add_boolean(field_tree, hf_tcp_flags_fin, tvb, offset + 13, 1, tcph->th_flags);
+ proto_tree_add_uint(tcp_tree, hf_tcp_window_size, tvb, offset + 14, 2, tcph->th_win);
+ }
+
+ /* Supply the sequence number of the first byte and of the first byte
+ after the segment. */
+ tcpinfo.seq = tcph->th_seq;
+ tcpinfo.nxtseq = nxtseq;
+
+ /* Assume we'll pass un-reassembled data to subdissectors. */
+ tcpinfo.is_reassembled = FALSE;
+
+ pinfo->private_data = &tcpinfo;
+
+ /*
+ * Assume, initially, that we can't desegment.
+ */
+ pinfo->can_desegment = 0;
+ th_sum = tvb_get_ntohs(tvb, offset + 16);
+ if (!pinfo->fragmented && tvb_bytes_exist(tvb, 0, reported_len)) {
+ /* The packet isn't part of an un-reassembled fragmented datagram
+ and isn't truncated. This means we have all the data, and thus
+ can checksum it and, unless it's being returned in an error
+ packet, are willing to allow subdissectors to request reassembly
+ on it. */
+
+ if (tcp_check_checksum) {
+ /* We haven't turned checksum checking off; checksum it. */
+
+ /* Set up the fields of the pseudo-header. */
+ cksum_vec[0].ptr = pinfo->src.data;
+ cksum_vec[0].len = pinfo->src.len;
+ cksum_vec[1].ptr = pinfo->dst.data;
+ cksum_vec[1].len = pinfo->dst.len;
+ cksum_vec[2].ptr = (const guint8 *)&phdr;
+ switch (pinfo->src.type) {
+
+ case AT_IPv4:
+ phdr[0] = g_htonl((IP_PROTO_TCP<<16) + reported_len);
+ cksum_vec[2].len = 4;
+ break;
+
+ case AT_IPv6:
+ phdr[0] = g_htonl(reported_len);
+ phdr[1] = g_htonl(IP_PROTO_TCP);
+ cksum_vec[2].len = 8;
+ break;
+
+ default:
+ /* TCP runs only atop IPv4 and IPv6.... */
+ g_assert_not_reached();
+ break;
+ }
+ cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, reported_len);
+ cksum_vec[3].len = reported_len;
+ computed_cksum = in_cksum(&cksum_vec[0], 4);
+ if (computed_cksum == 0) {
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
+ offset + 16, 2, th_sum, "Checksum: 0x%04x (correct)", th_sum);
+
+ /* Checksum is valid, so we're willing to desegment it. */
+ desegment_ok = TRUE;
+ } else {
+ proto_tree_add_boolean_hidden(tcp_tree, hf_tcp_checksum_bad, tvb,
+ offset + 16, 2, TRUE);
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
+ offset + 16, 2, th_sum,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)", th_sum,
+ in_cksum_shouldbe(th_sum, computed_cksum));
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [CHECKSUM INCORRECT]");
+
+ /* Checksum is invalid, so we're not willing to desegment it. */
+ desegment_ok = FALSE;
+ pinfo->noreassembly_reason = " (incorrect TCP checksum)";
+ }
+ } else {
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
+ offset + 16, 2, th_sum, "Checksum: 0x%04x", th_sum);
+
+ /* We didn't check the checksum, and don't care if it's valid,
+ so we're willing to desegment it. */
+ desegment_ok = TRUE;
+ }
+ } else {
+ /* We don't have all the packet data, so we can't checksum it... */
+ proto_tree_add_uint_format(tcp_tree, hf_tcp_checksum, tvb,
+ offset + 16, 2, th_sum, "Checksum: 0x%04x", th_sum);
+
+ /* ...and aren't willing to desegment it. */
+ desegment_ok = FALSE;
+ }
+
+ if (desegment_ok) {
+ /* We're willing to desegment this. Is desegmentation enabled? */
+ if (tcp_desegment) {
+ /* Yes - is this segment being returned in an error packet? */
+ if (!pinfo->in_error_pkt) {
+ /* No - indicate that we will desegment.
+ We do NOT want to desegment segments returned in error
+ packets, as they're not part of a TCP connection. */
+ pinfo->can_desegment = 2;
+ }
+ }
+ }
+
+ if (tcph->th_flags & TH_URG) {
+ th_urp = tvb_get_ntohs(tvb, offset + 18);
+ /* Export the urgent pointer, for the benefit of protocols such as
+ rlogin. */
+ tcpinfo.urgent = TRUE;
+ tcpinfo.urgent_pointer = th_urp;
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Urg=%u", th_urp);
+ if (tcp_tree != NULL)
+ proto_tree_add_uint(tcp_tree, hf_tcp_urgent_pointer, tvb, offset + 18, 2, th_urp);
+ } else
+ tcpinfo.urgent = FALSE;
+
+ if (tcph->th_have_seglen) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", tcph->th_seglen);
+ }
+
+ /* Decode TCP options, if any. */
+ if (tcph->th_hlen > TCPH_MIN_LEN) {
+ /* There's more than just the fixed-length header. Decode the
+ options. */
+ optlen = tcph->th_hlen - TCPH_MIN_LEN; /* length of options, in bytes */
+ if (tcp_tree != NULL) {
+ tf = proto_tree_add_text(tcp_tree, tvb, offset + 20, optlen,
+ "Options: (%u bytes)", optlen);
+ field_tree = proto_item_add_subtree(tf, ett_tcp_options);
+ } else
+ field_tree = NULL;
+ dissect_ip_tcp_options(tvb, offset + 20, optlen,
+ tcpopts, N_TCP_OPTS, TCPOPT_EOL, pinfo, field_tree);
+ }
+
+ /* Skip over header + options */
+ offset += tcph->th_hlen;
+
+ /* Check the packet length to see if there's more data
+ (it could be an ACK-only packet) */
+ length_remaining = tvb_length_remaining(tvb, offset);
+
+ if (tcph->th_have_seglen) {
+ if( data_out_file ) {
+ reassemble_tcp( tcph->th_seq, /* sequence number */
+ tcph->th_seglen, /* data length */
+ tvb_get_ptr(tvb, offset, length_remaining), /* data */
+ length_remaining, /* captured data length */
+ ( tcph->th_flags & TH_SYN ), /* is syn set? */
+ &pinfo->net_src,
+ &pinfo->net_dst,
+ pinfo->srcport,
+ pinfo->destport);
+ }
+ }
+
+ /*
+ * XXX - what, if any, of this should we do if this is included in an
+ * error packet? It might be nice to see the details of the packet
+ * that caused the ICMP error, but it might not be nice to have the
+ * dissector update state based on it.
+ * Also, we probably don't want to run TCP taps on those packets.
+ */
+ if (length_remaining != 0) {
+ if (tcph->th_flags & TH_RST) {
+ /*
+ * RFC1122 says:
+ *
+ * 4.2.2.12 RST Segment: RFC-793 Section 3.4
+ *
+ * A TCP SHOULD allow a received RST segment to include data.
+ *
+ * DISCUSSION
+ * It has been suggested that a RST segment could contain
+ * ASCII text that encoded and explained the cause of the
+ * RST. No standard has yet been established for such
+ * data.
+ *
+ * so for segments with RST we just display the data as text.
+ */
+ proto_tree_add_text(tcp_tree, tvb, offset, length_remaining,
+ "Reset cause: %s",
+ tvb_format_text(tvb, offset, length_remaining));
+ } else {
+ dissect_tcp_payload(tvb, pinfo, offset, tcph->th_seq, nxtseq,
+ tcph->th_sport, tcph->th_dport, tree, tcp_tree);
+ }
+ }
+
+ /* handle TCP seq# analysis, print any extra SEQ/ACK data for this segment*/
+ if(tcp_analyze_seq){
+ tcp_print_sequence_number_analysis(pinfo, tvb, tcp_tree);
+ }
+ tap_queue_packet(tcp_tap, pinfo, tcph);
+}
+
+void
+proto_register_tcp(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_tcp_srcport,
+ { "Source Port", "tcp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_dstport,
+ { "Destination Port", "tcp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_port,
+ { "Source or Destination Port", "tcp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_seq,
+ { "Sequence number", "tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_nxtseq,
+ { "Next sequence number", "tcp.nxtseq", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_ack,
+ { "Acknowledgement number", "tcp.ack", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_hdr_len,
+ { "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_flags,
+ { "Flags", "tcp.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_flags_cwr,
+ { "Congestion Window Reduced (CWR)", "tcp.flags.cwr", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_CWR,
+ "", HFILL }},
+
+ { &hf_tcp_flags_ecn,
+ { "ECN-Echo", "tcp.flags.ecn", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_ECN,
+ "", HFILL }},
+
+ { &hf_tcp_flags_urg,
+ { "Urgent", "tcp.flags.urg", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_URG,
+ "", HFILL }},
+
+ { &hf_tcp_flags_ack,
+ { "Acknowledgment", "tcp.flags.ack", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_ACK,
+ "", HFILL }},
+
+ { &hf_tcp_flags_push,
+ { "Push", "tcp.flags.push", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_PUSH,
+ "", HFILL }},
+
+ { &hf_tcp_flags_reset,
+ { "Reset", "tcp.flags.reset", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_RST,
+ "", HFILL }},
+
+ { &hf_tcp_flags_syn,
+ { "Syn", "tcp.flags.syn", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_SYN,
+ "", HFILL }},
+
+ { &hf_tcp_flags_fin,
+ { "Fin", "tcp.flags.fin", FT_BOOLEAN, 8, TFS(&flags_set_truth), TH_FIN,
+ "", HFILL }},
+
+ /* 32 bits so we can present some values adjusted to window scaling */
+ { &hf_tcp_window_size,
+ { "Window size", "tcp.window_size", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_checksum,
+ { "Checksum", "tcp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_checksum_bad,
+ { "Bad Checksum", "tcp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_analysis_flags,
+ { "TCP Analysis Flags", "tcp.analysis.flags", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This frame has some of the TCP analysis flags set", HFILL }},
+
+ { &hf_tcp_analysis_retransmission,
+ { "Retransmission", "tcp.analysis.retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This frame is a suspected TCP retransmission", HFILL }},
+
+ { &hf_tcp_analysis_fast_retransmission,
+ { "Fast Retransmission", "tcp.analysis.fast_retransmission", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This frame is a suspected TCP fast retransmission", HFILL }},
+
+ { &hf_tcp_analysis_out_of_order,
+ { "Out Of Order", "tcp.analysis.out_of_order", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This frame is a suspected Out-Of-Order segment", HFILL }},
+
+ { &hf_tcp_analysis_lost_packet,
+ { "Previous Segment Lost", "tcp.analysis.lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
+ "A segment before this one was lost from the capture", HFILL }},
+
+ { &hf_tcp_analysis_ack_lost_packet,
+ { "ACKed Lost Packet", "tcp.analysis.ack_lost_segment", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This frame ACKs a lost segment", HFILL }},
+
+ { &hf_tcp_analysis_keep_alive,
+ { "Keep Alive", "tcp.analysis.keep_alive", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This is a keep-alive segment", HFILL }},
+
+ { &hf_tcp_analysis_keep_alive_ack,
+ { "Keep Alive ACK", "tcp.analysis.keep_alive_ack", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This is an ACK to a keep-alive segment", HFILL }},
+
+ { &hf_tcp_analysis_duplicate_ack,
+ { "Duplicate ACK", "tcp.analysis.duplicate_ack", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This is a duplicate ACK", HFILL }},
+
+ { &hf_tcp_analysis_duplicate_ack_num,
+ { "Duplicate ACK #", "tcp.analysis.duplicate_ack_num", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "This is duplicate ACK number #", HFILL }},
+
+ { &hf_tcp_analysis_duplicate_ack_frame,
+ { "Duplicate to the ACK in frame", "tcp.analysis.duplicate_ack_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This is a duplicate to the ACK in frame #", HFILL }},
+
+ { &hf_tcp_continuation_to,
+ { "This is a continuation to the PDU in frame", "tcp.continuation_to", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This is a continuation to the PDU in frame #", HFILL }},
+
+ { &hf_tcp_analysis_zero_window_violation,
+ { "Zero Window Violation", "tcp.analysis.zero_window_violation", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This is a zero-window violation, an attempt to write >1 byte to a zero-window", HFILL }},
+
+ { &hf_tcp_analysis_zero_window_probe,
+ { "Zero Window Probe", "tcp.analysis.zero_window_probe", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This is a zero-window-probe", HFILL }},
+
+ { &hf_tcp_analysis_zero_window,
+ { "Zero Window", "tcp.analysis.zero_window", FT_NONE, BASE_NONE, NULL, 0x0,
+ "This is a zero-window", HFILL }},
+
+ { &hf_tcp_len,
+ { "TCP Segment Len", "tcp.len", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL}},
+
+ { &hf_tcp_analysis_acks_frame,
+ { "This is an ACK to the segment in frame", "tcp.analysis.acks_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Which previous segment is this an ACK for", HFILL}},
+
+ { &hf_tcp_analysis_ack_rtt,
+ { "The RTT to ACK the segment was", "tcp.analysis.ack_rtt", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
+ "How long time it took to ACK the segment (RTT)", HFILL}},
+
+ { &hf_tcp_urgent_pointer,
+ { "Urgent pointer", "tcp.urgent_pointer", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tcp_segment_overlap,
+ { "Segment overlap", "tcp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment overlaps with other segments", HFILL }},
+
+ { &hf_tcp_segment_overlap_conflict,
+ { "Conflicting data in segment overlap", "tcp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping segments contained conflicting data", HFILL }},
+
+ { &hf_tcp_segment_multiple_tails,
+ { "Multiple tail segments found", "tcp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when desegmenting the pdu", HFILL }},
+
+ { &hf_tcp_segment_too_long_fragment,
+ { "Segment too long", "tcp.segment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment contained data past end of the pdu", HFILL }},
+
+ { &hf_tcp_segment_error,
+ { "Desegmentation error", "tcp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Desegmentation error due to illegal segments", HFILL }},
+
+ { &hf_tcp_segment,
+ { "TCP Segment", "tcp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "TCP Segment", HFILL }},
+
+ { &hf_tcp_segments,
+ { "TCP Segments", "tcp.segments", FT_NONE, BASE_NONE, NULL, 0x0,
+ "TCP Segments", HFILL }},
+
+ { &hf_tcp_reassembled_in,
+ { "Reassembled PDU in frame", "tcp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "The PDU that starts but doesn't end in this segment is reassembled in this frame", HFILL }},
+
+ { &hf_tcp_option_mss,
+ { "TCP MSS Option", "tcp.options.mss", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "TCP MSS Option", HFILL }},
+
+ { &hf_tcp_option_mss_val,
+ { "TCP MSS Option Value", "tcp.options.mss_val", FT_UINT16,
+ BASE_DEC, NULL, 0x0, "TCP MSS Option Value", HFILL}},
+
+ { &hf_tcp_option_wscale,
+ { "TCP Window Scale Option", "tcp.options.wscale",
+ FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "TCP Window Option", HFILL}},
+
+ { &hf_tcp_option_wscale_val,
+ { "TCP Windows Scale Option Value", "tcp.options.wscale_val",
+ FT_UINT8, BASE_DEC, NULL, 0x0, "TCP Window Scale Value",
+ HFILL}},
+
+ { &hf_tcp_option_sack_perm,
+ { "TCP Sack Perm Option", "tcp.options.sack_perm",
+ FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "TCP Sack Perm Option", HFILL}},
+
+ { &hf_tcp_option_sack,
+ { "TCP Sack Option", "tcp.options.sack", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "TCP Sack Option", HFILL}},
+
+ { &hf_tcp_option_sack_sle,
+ {"TCP Sack Left Edge", "tcp.options.sack_le", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "TCP Sack Left Edge", HFILL}},
+
+ { &hf_tcp_option_sack_sre,
+ {"TCP Sack Right Edge", "tcp.options.sack_re", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "TCP Sack Right Edge", HFILL}},
+
+ { &hf_tcp_option_echo,
+ { "TCP Echo Option", "tcp.options.echo", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "TCP Sack Echo", HFILL}},
+
+ { &hf_tcp_option_echo_reply,
+ { "TCP Echo Reply Option", "tcp.options.echo_reply",
+ FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "TCP Echo Reply Option", HFILL}},
+
+ { &hf_tcp_option_time_stamp,
+ { "TCP Time Stamp Option", "tcp.options.time_stamp",
+ FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "TCP Time Stamp Option", HFILL}},
+
+ { &hf_tcp_option_cc,
+ { "TCP CC Option", "tcp.options.cc", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "TCP CC Option", HFILL}},
+
+ { &hf_tcp_option_ccnew,
+ { "TCP CC New Option", "tcp.options.ccnew", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "TCP CC New Option", HFILL}},
+
+ { &hf_tcp_option_ccecho,
+ { "TCP CC Echo Option", "tcp.options.ccecho", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "TCP CC Echo Option", HFILL}},
+
+ { &hf_tcp_option_md5,
+ { "TCP MD5 Option", "tcp.options.md5", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "TCP MD5 Option", HFILL}},
+ };
+ static gint *ett[] = {
+ &ett_tcp,
+ &ett_tcp_flags,
+ &ett_tcp_options,
+ &ett_tcp_option_sack,
+ &ett_tcp_analysis_faults,
+ &ett_tcp_analysis,
+ &ett_tcp_segments,
+ &ett_tcp_segment
+ };
+ module_t *tcp_module;
+
+ proto_tcp = proto_register_protocol("Transmission Control Protocol",
+ "TCP", "tcp");
+ proto_register_field_array(proto_tcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ subdissector_table = register_dissector_table("tcp.port",
+ "TCP port", FT_UINT16, BASE_DEC);
+ register_heur_dissector_list("tcp", &heur_subdissector_list);
+
+ /* Register configuration preferences */
+ tcp_module = prefs_register_protocol(proto_tcp, NULL);
+ prefs_register_bool_preference(tcp_module, "summary_in_tree",
+ "Show TCP summary in protocol tree",
+ "Whether the TCP summary line should be shown in the protocol tree",
+ &tcp_summary_in_tree);
+ prefs_register_bool_preference(tcp_module, "check_checksum",
+ "Check the validity of the TCP checksum when possible",
+ "Whether to check the validity of the TCP checksum",
+ &tcp_check_checksum);
+ prefs_register_bool_preference(tcp_module, "desegment_tcp_streams",
+ "Allow subdissector to desegment TCP streams",
+ "Whether subdissector can request TCP streams to be desegmented",
+ &tcp_desegment);
+ prefs_register_bool_preference(tcp_module, "analyze_sequence_numbers",
+ "Analyze TCP sequence numbers",
+ "Make the TCP dissector analyze TCP sequence numbers to find and flag segment retransmissions, missing segments and RTT",
+ &tcp_analyze_seq);
+ prefs_register_bool_preference(tcp_module, "relative_sequence_numbers",
+ "Relative sequence numbers and window scaling",
+ "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
+ "To use this option you must also enable \"Analyze TCP sequence numbers\". "
+ "This option will also try to track and adjust the window field according to any TCP window scaling options seen.",
+ &tcp_relative_seq);
+ prefs_register_bool_preference(tcp_module, "try_heuristic_first",
+ "Try heuristic sub-dissectors first",
+ "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
+ &try_heuristic_first);
+
+ register_init_routine(tcp_analyze_seq_init);
+ register_init_routine(tcp_desegment_init);
+ register_init_routine(tcp_fragment_init);
+}
+
+void
+proto_reg_handoff_tcp(void)
+{
+ dissector_handle_t tcp_handle;
+
+ tcp_handle = create_dissector_handle(dissect_tcp, proto_tcp);
+ dissector_add("ip.proto", IP_PROTO_TCP, tcp_handle);
+ data_handle = find_dissector("data");
+ tcp_tap = register_tap("tcp");
+}
diff --git a/epan/dissectors/packet-tcp.h b/epan/dissectors/packet-tcp.h
new file mode 100644
index 0000000000..a33472a978
--- /dev/null
+++ b/epan/dissectors/packet-tcp.h
@@ -0,0 +1,96 @@
+/* packet-tcp.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_TCP_H__
+#define __PACKET_TCP_H__
+
+/* TCP flags */
+#define TH_FIN 0x01
+#define TH_SYN 0x02
+#define TH_RST 0x04
+#define TH_PUSH 0x08
+#define TH_ACK 0x10
+#define TH_URG 0x20
+#define TH_ECN 0x40
+#define TH_CWR 0x80
+
+
+/* the tcp header structure, passed to tap listeners */
+struct tcpheader {
+ guint32 th_seq;
+ guint32 th_ack;
+ gboolean th_have_seglen; /* TRUE if th_seglen is valid */
+ guint32 th_seglen;
+ guint32 th_win; /* make it 32 bits so we can handle some scaling */
+ guint16 th_sport;
+ guint16 th_dport;
+ guint8 th_hlen;
+ guint8 th_flags;
+ address ip_src;
+ address ip_dst;
+};
+
+/*
+ * Private data passed from the TCP dissector to subdissectors.
+ */
+struct tcpinfo {
+ guint32 seq; /* Sequence number of first byte in the data */
+ guint32 nxtseq; /* Sequence number of first byte after data */
+ gboolean is_reassembled; /* This is reassembled data. */
+ gboolean urgent; /* TRUE if "urgent_pointer" is valid */
+ guint16 urgent_pointer; /* Urgent pointer value for the current packet. */
+};
+
+/*
+ * Loop for dissecting PDUs within a TCP stream; assumes that a PDU
+ * consists of a fixed-length chunk of data that contains enough information
+ * to determine the length of the PDU, followed by rest of the PDU.
+ *
+ * The first three arguments are the arguments passed to the dissector
+ * that calls this routine.
+ *
+ * "proto_desegment" is the dissector's flag controlling whether it should
+ * desegment PDUs that cross TCP segment boundaries.
+ *
+ * "fixed_len" is the length of the fixed-length part of the PDU.
+ *
+ * "get_pdu_len()" is a routine called to get the length of the PDU from
+ * the fixed-length part of the PDU; it's passed "tvb" and "offset".
+ *
+ * "dissect_pdu()" is the routine to dissect a PDU.
+ */
+extern void
+tcp_dissect_pdus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean proto_desegment, guint fixed_len,
+ guint (*get_pdu_len)(tvbuff_t *, int),
+ void (*dissect_pdu)(tvbuff_t *, packet_info *, proto_tree *));
+
+extern gboolean decode_tcp_ports(tvbuff_t *, int, packet_info *,
+ proto_tree *, int, int);
+
+extern void dissect_tcp_payload(tvbuff_t *tvb, packet_info *pinfo, int offset,
+ guint32 seq, guint32 nxtseq, guint32 sport,
+ guint32 dport, proto_tree *tree,
+ proto_tree *tcp_tree);
+
+#endif
diff --git a/epan/dissectors/packet-tds.c b/epan/dissectors/packet-tds.c
new file mode 100644
index 0000000000..f443ea53b1
--- /dev/null
+++ b/epan/dissectors/packet-tds.c
@@ -0,0 +1,1805 @@
+/* packet-tds.c
+ * Routines for TDS NetLib dissection
+ * Copyright 2000-2002, Brian Bruns <camber@ais.org>
+ * Copyright 2002, Steve Langasek <vorlon@netexpress.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * The NETLIB protocol is a small blocking protocol designed to allow TDS
+ * to be placed within different transports (TCP, DECNet, IPX/SPX). A
+ * NETLIB packet starts with an eight byte header containing:
+ *
+ * a one-byte packet type field;
+ *
+ * a one-byte status field;
+ *
+ * a two-byte big-endian size field giving the size of the packet,
+ * including the header;
+ *
+ * a two-byte big-endian channel number, used when multiple sessions
+ * are being multiplexed on a single connection;
+ *
+ * a one-byte packet number, giving "the frame number of a multiplexed
+ * message, modulo 256";
+ *
+ * a one-byte window, which is the number of frames to be sent
+ * before an acknowledgment message is received.
+ *
+ * followed by payload whose size is the value in the size field minus
+ * 8.
+ *
+ * Microsoft Network Monitor 2.x dissects the 4 byte field (and indicates
+ * that the one-byte last packet indicator also contains other bits).
+ *
+ * The TDS protocol consists of a number of protocol data units (PDUs) that
+ * appear to be assembled from NETLIB packets, in the form of zero or more
+ * NETLIB packets with the last packet indicator clear and a final NETLIB
+ * packet with the last packet indicator set. The type of the TDS PDU is
+ * specified by the packet type field of the NETLIB header (presumably that
+ * field has the same value for all NETLIB packets that make up a TDS PDU).
+ *
+ * The "server response" PDU consists of a sequence of multiple items, each
+ * one beginning with a one byte type field at the start of the PDU. Some
+ * items are fixed length, some are variable length with a two byte size
+ * field following the item type, and then there is TDS_ROW_TOKEN in which
+ * size is determined by analyzing the result set returned from the server.
+ * This in effect means that we are hopelessly lost if we haven't seen the
+ * result set. Also, TDS 4/5 is byte order negotiable, which is specified
+ * in the login packet. We can attempt to determine it later on, but not
+ * with 100% accuracy.
+ *
+ * Some preliminary documentation on the packet format can be found at
+ * http://www.freetds.org/tds.html
+ *
+ * Some more information can be found in
+ * http://download.nai.com/products/media/sniffer/support/sdos/sybase.pdf
+ *
+ * Much of this code was originally developed for the FreeTDS project.
+ * http://www.freetds.org
+ */
+
+/*
+ * Excerpts from Brian's posting to ethereal-dev:
+ *
+ * The TDS Protocol is actually a protocol within a protocol. On the outside
+ * there is netlib which is not so much a encapsulation as a blocking of the
+ * data, typically to 512 or 4096 bytes. Between this are the protocol data
+ * units for TDS. Netlib packets may be split over real packets, multiple
+ * netlib packets may appear in single real packets. TDS PDUs may be split
+ * over netlib packets (and real packets) and most certainly can appear
+ * multiple times within a netlib packet.
+ *
+ * Because of this, I abandoned my earlier attempt at making two dissectors,
+ * one for netlib and one for TDS. Counterintuitively, a single dissector
+ * turned out to be simpler than splitting it up.
+ *
+ * Here are some of the (hefty) limitations of the current code
+ *
+ * . We currently do not handle netlib headers that cross packet boundaries.
+ * This should be an easy fix.
+ * . I probably could have used the packet reassembly stuff, but I started
+ * this at version 0.8.20, so c'est la vie. It wouldn't have covered the
+ * netlib stuff anyway, so no big loss.
+ * . The older two layer version of the code dissected the PDU's, but the new
+ * version does not yet, it only labels the names. I need an elegant way to
+ * deal with dissecting data crossing (netlib and tcp) packet boundries. I
+ * think I have one, but ran out of time to do it.
+ * . It will only work on little endian platforms. Or rather I should say,
+ * the client that was captured must be little endian. TDS 7.0/8.0 is
+ * always LE; for TDS 4.2/5.0 look in the code for tvb_get_le*() functions,
+ * there are fields in the login packet which determine byte order.
+ * . result sets that span netlib packets are not working
+ * . TDS 7 and 4.2 result sets are not working yet
+ *
+ * All that said, the code does deal gracefully with different boudary
+ * conditions and what remains are the easier bits, IMHO.
+ *
+ * XXX - "real packets" means "TCP segments", for TCP.
+ *
+ * XXX - is it *REALLY* true that you can have more than one TDS PDU (as
+ * opposed to more than one server response item) per NETLIB packet? Or is
+ * all the data in a NETLIB packet put into a single TDS PDU? If so, then
+ * we can reassemble NETLIB packets using the standard TCP desegmentation
+ * code, and can reassemble TDS PDUs using "fragment_add_seq_check()",
+ * and more cleanly separate the NETLIB and TDS dissectors (although the
+ * "is this NETLIB" heuristic would have to look at TDS information past
+ * the NETLIB header, in order to make the heuristic strong enough not
+ * to get too many false positives; note that the heuristic should reject
+ * any putative NETLIB packet with a length field with a value < 8).
+ *
+ * That would substantially clean the dissector up, eliminating most of
+ * the per-packet data (we might still need information to handle
+ * TDS_ROW_TOKEN), getting rid of the stuff to handle data split across
+ * TCP segment boundaries in favor of simple reassembly code, and
+ * fixing some otherwise nasty-looking crashing bugs.
+ *
+ * NOTE: we assume that all the data in a NETLIB packet *can* be put into
+ * a single TDS PTU, so that we have separate reassembly of NETLIB
+ * packets and TDS PDUs; it seems to work, and it really did clean stuff
+ * up and fix crashes.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+
+#include "isprint.h"
+
+#include <epan/packet.h>
+#include <epan/conversation.h>
+#include <epan/strutil.h>
+
+#include "packet-smb-common.h"
+#include "packet-frame.h"
+#include "reassemble.h"
+#include "prefs.h"
+
+#define TDS_QUERY_PKT 1
+#define TDS_LOGIN_PKT 2
+#define TDS_RPC_PKT 3
+#define TDS_RESP_PKT 4
+#define TDS_RAW_PKT 5
+#define TDS_CANCEL_PKT 6
+#define TDS_BULK_DATA_PKT 7
+#define TDS_OPEN_CHN_PKT 8
+#define TDS_CLOSE_CHN_PKT 9
+#define TDS_RES_ERROR_PKT 10
+#define TDS_LOG_CHN_ACK_PKT 11
+#define TDS_ECHO_PKT 12
+#define TDS_LOGOUT_CHN_PKT 13
+#define TDS_QUERY5_PKT 15 /* or "Normal tokenized request or response */
+#define TDS_LOGIN7_PKT 16 /* or "Urgent tokenized request or response */
+#define TDS_XXX7_PKT 18 /* seen in one capture */
+
+#define is_valid_tds_type(x) ((x) >= TDS_QUERY_PKT && (x) <= TDS_XXX7_PKT)
+
+/* The following constants are imported more or less directly from FreeTDS */
+
+#define TDS5_DYN_TOKEN 231 /* 0xE7 TDS 5.0 only */
+#define TDS5_DYNRES_TOKEN 236 /* 0xEC TDS 5.0 only */
+#define TDS5_DYN3_TOKEN 215 /* 0xD7 TDS 5.0 only */
+#define TDS_LANG_TOKEN 33 /* 0x21 TDS 5.0 only */
+#define TDS_CLOSE_TOKEN 113 /* 0x71 TDS 5.0 only? ct_close() */
+#define TDS_RET_STAT_TOKEN 121 /* 0x79 */
+#define TDS_124_TOKEN 124 /* 0x7C TDS 4.2 only - TDS_PROCID */
+#define TDS7_RESULT_TOKEN 129 /* 0x81 TDS 7.0 only */
+#define TDS_COL_NAME_TOKEN 160 /* 0xA0 TDS 4.2 only */
+#define TDS_COL_INFO_TOKEN 161 /* 0xA1 TDS 4.2 only - TDS_COLFMT */
+/*#define TDS_TABNAME 164 */
+/*#define TDS_COL_INFO 165 */
+#define TDS_167_TOKEN 167 /* 0xA7 */
+#define TDS_168_TOKEN 168 /* 0xA8 */
+#define TDS_ORDER_BY_TOKEN 169 /* 0xA9 TDS_ORDER */
+#define TDS_ERR_TOKEN 170 /* 0xAA */
+#define TDS_MSG_TOKEN 171 /* 0xAB */
+#define TDS_PARAM_TOKEN 172 /* 0xAC RETURNVALUE? */
+#define TDS_LOGIN_ACK_TOKEN 173 /* 0xAD */
+#define TDS_174_TOKEN 174 /* 0xAE TDS_CONTROL */
+#define TDS_ROW_TOKEN 209 /* 0xD1 */
+#define TDS_CMP_ROW_TOKEN 211 /* 0xD3 */
+#define TDS_CAP_TOKEN 226 /* 0xE2 */
+#define TDS_ENV_CHG_TOKEN 227 /* 0xE3 */
+#define TDS_EED_TOKEN 229 /* 0xE5 */
+#define TDS_AUTH_TOKEN 237 /* 0xED */
+#define TDS_RESULT_TOKEN 238 /* 0xEE */
+#define TDS_DONE_TOKEN 253 /* 0xFD TDS_DONE */
+#define TDS_DONEPROC_TOKEN 254 /* 0xFE TDS_DONEPROC */
+#define TDS_DONEINPROC_TOKEN 255 /* 0xFF TDS_DONEINPROC */
+
+#define SYBCHAR 47 /* 0x2F */
+#define SYBVARCHAR 39 /* 0x27 */
+#define SYBINTN 38 /* 0x26 */
+#define SYBINT1 48 /* 0x30 */
+#define SYBINT2 52 /* 0x34 */
+#define SYBINT4 56 /* 0x38 */
+#define SYBINT8 127 /* 0x7F */
+#define SYBFLT8 62 /* 0x3E */
+#define SYBDATETIME 61 /* 0x3D */
+#define SYBBIT 50 /* 0x32 */
+#define SYBTEXT 35 /* 0x23 */
+#define SYBNTEXT 99 /* 0x63 */
+#define SYBIMAGE 34 /* 0x22 */
+#define SYBMONEY4 122 /* 0x7A */
+#define SYBMONEY 60 /* 0x3C */
+#define SYBDATETIME4 58 /* 0x3A */
+#define SYBREAL 59 /* 0x3B */
+#define SYBBINARY 45 /* 0x2D */
+#define SYBVOID 31 /* 0x1F */
+#define SYBVARBINARY 37 /* 0x25 */
+#define SYBNVARCHAR 103 /* 0x67 */
+#define SYBBITN 104 /* 0x68 */
+#define SYBNUMERIC 108 /* 0x6C */
+#define SYBDECIMAL 106 /* 0x6A */
+#define SYBFLTN 109 /* 0x6D */
+#define SYBMONEYN 110 /* 0x6E */
+#define SYBDATETIMN 111 /* 0x6F */
+#define XSYBCHAR 167 /* 0xA7 */
+#define XSYBVARCHAR 175 /* 0xAF */
+#define XSYBNVARCHAR 231 /* 0xE7 */
+#define XSYBNCHAR 239 /* 0xEF */
+#define SYBUNIQUE 0x24
+#define SYBVARIANT 0x62
+
+#define is_fixed_coltype(x) (x==SYBINT1 || \
+ x==SYBINT2 || \
+ x==SYBINT4 || \
+ x==SYBINT8 || \
+ x==SYBREAL || \
+ x==SYBFLT8 || \
+ x==SYBDATETIME || \
+ x==SYBDATETIME4 || \
+ x==SYBBIT || \
+ x==SYBMONEY || \
+ x==SYBMONEY4 || \
+ x==SYBUNIQUE)
+
+/* Initialize the protocol and registered fields */
+static int proto_tds = -1;
+static int hf_tds_type = -1;
+static int hf_tds_status = -1;
+static int hf_tds_size = -1;
+static int hf_tds_channel = -1;
+static int hf_tds_packet_number = -1;
+static int hf_tds_window = -1;
+static int hf_tds_reassembled_in = -1;
+static int hf_tds_fragments = -1;
+static int hf_tds_fragment = -1;
+static int hf_tds_fragment_overlap = -1;
+static int hf_tds_fragment_overlap_conflict = -1;
+static int hf_tds_fragment_multiple_tails = -1;
+static int hf_tds_fragment_too_long_fragment = -1;
+static int hf_tds_fragment_error = -1;
+
+static int hf_tds7_login_total_size = -1;
+static int hf_tds7_version = -1;
+static int hf_tds7_packet_size = -1;
+static int hf_tds7_client_version = -1;
+static int hf_tds7_client_pid = -1;
+static int hf_tds7_connection_id = -1;
+static int hf_tds7_option_flags1 = -1;
+static int hf_tds7_option_flags2 = -1;
+static int hf_tds7_sql_type_flags = -1;
+static int hf_tds7_reserved_flags = -1;
+static int hf_tds7_time_zone = -1;
+static int hf_tds7_collation = -1;
+static int hf_tds7_message = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_tds = -1;
+static gint ett_tds_fragments = -1;
+static gint ett_tds_fragment = -1;
+static gint ett_tds_token = -1;
+static gint ett_tds7_login = -1;
+static gint ett_tds7_query = 0;
+static gint ett_tds7_hdr = -1;
+
+/* Desegmentation of Netlib buffers crossing TCP segment boundaries. */
+static gboolean tds_desegment = TRUE;
+
+static const fragment_items tds_frag_items = {
+ &ett_tds_fragment,
+ &ett_tds_fragments,
+ &hf_tds_fragments,
+ &hf_tds_fragment,
+ &hf_tds_fragment_overlap,
+ &hf_tds_fragment_overlap_conflict,
+ &hf_tds_fragment_multiple_tails,
+ &hf_tds_fragment_too_long_fragment,
+ &hf_tds_fragment_error,
+ &hf_tds_reassembled_in,
+ "fragments"
+};
+
+/* Tables for reassembly of fragments. */
+static GHashTable *tds_fragment_table = NULL;
+static GHashTable *tds_reassembled_table = NULL;
+
+/* defragmentation of multi-buffer TDS PDUs */
+static gboolean tds_defragment = TRUE;
+
+static dissector_handle_t tds_tcp_handle;
+static dissector_handle_t ntlmssp_handle;
+static dissector_handle_t data_handle;
+
+/* These correspond to the netlib packet type field */
+static const value_string packet_type_names[] = {
+ {TDS_QUERY_PKT, "Query Packet"},
+ {TDS_LOGIN_PKT, "Login Packet"},
+ {TDS_RPC_PKT, "Remote Procedure Call Packet"},
+ {TDS_RESP_PKT, "Response Packet"},
+ {TDS_CANCEL_PKT, "Cancel Packet"},
+ {TDS_QUERY5_PKT, "TDS5 Query Packet"},
+ {TDS_LOGIN7_PKT, "TDS7/8 Login Packet"},
+ {0, NULL},
+};
+
+/* The status field */
+
+#define is_valid_tds_status(x) ((x) <= STATUS_EVENT_NOTIFICATION)
+
+#define STATUS_NOT_LAST_BUFFER 0x00
+#define STATUS_LAST_BUFFER 0x01
+#define STATUS_ATTN_REQUEST_ACK 0x02
+#define STATUS_ATTN_REQUEST 0x03
+#define STATUS_EVENT_NOTIFICATION 0x04
+
+static const value_string status_names[] = {
+ {STATUS_NOT_LAST_BUFFER, "Not last buffer"},
+ {STATUS_LAST_BUFFER, "Last buffer in request or response"},
+ {STATUS_ATTN_REQUEST_ACK, "Acknowledgment of last attention request"},
+ {STATUS_ATTN_REQUEST, "Attention request"},
+ {STATUS_EVENT_NOTIFICATION, "Event notification"},
+ {0, NULL},
+};
+
+/* The one byte token at the start of each TDS PDU */
+static const value_string token_names[] = {
+ {TDS5_DYN_TOKEN, "Dynamic SQL"},
+ {TDS5_DYNRES_TOKEN, "Dynamic Results"},
+ {TDS5_DYN3_TOKEN, "Dynamic (Unknown)"},
+ {TDS_LANG_TOKEN, "Language"},
+ {TDS_CLOSE_TOKEN, "Close Connection"},
+ {TDS_RET_STAT_TOKEN, "Return Status"},
+ {TDS_124_TOKEN, "Proc ID"},
+ {TDS7_RESULT_TOKEN, "TDS7+ Results"},
+ {TDS_COL_NAME_TOKEN, "Column Names"},
+ {TDS_COL_INFO_TOKEN, "Column Info"},
+ {TDS_167_TOKEN, "Unknown (167)"},
+ {TDS_168_TOKEN, "Unknown (168)"},
+ {TDS_ORDER_BY_TOKEN, "Order By"},
+ {TDS_ERR_TOKEN, "Error Message"},
+ {TDS_MSG_TOKEN, "Info Message"},
+ {TDS_PARAM_TOKEN, "Paramater"},
+ {TDS_LOGIN_ACK_TOKEN, "Login Acknowledgement"},
+ {TDS_174_TOKEN, "Unknown (174)"},
+ {TDS_ROW_TOKEN, "Row"},
+ {TDS_CMP_ROW_TOKEN, "Compute Row"},
+ {TDS_CAP_TOKEN, "Capabilities"},
+ {TDS_ENV_CHG_TOKEN, "Environment Change"},
+ {TDS_EED_TOKEN, "Extended Error"},
+ {TDS_AUTH_TOKEN, "Authentication"},
+ {TDS_RESULT_TOKEN, "Results"},
+ {TDS_DONE_TOKEN, "Done"},
+ {TDS_DONEPROC_TOKEN, "Done Proc"},
+ {TDS_DONEINPROC_TOKEN, "Done In Proc"},
+ {0, NULL},
+};
+
+static const value_string env_chg_names[] = {
+ {1, "Database"},
+ {2, "Language"},
+ {3, "Sort Order"},
+ {4, "Blocksize"},
+ {5, "Unicode Locale ID"},
+ {6, "Unicode Comparison Style"},
+ {7, "Collation Info"},
+ {0, NULL},
+};
+
+static const value_string login_field_names[] = {
+ {0, "Client Name"},
+ {1, "Username"},
+ {2, "Password"},
+ {3, "App Name"},
+ {4, "Server Name"},
+ {5, "Unknown1"},
+ {6, "Library Name"},
+ {7, "Locale"},
+ {8, "Unknown2"},
+ {0, NULL},
+};
+
+
+#define MAX_COLUMNS 256
+
+/*
+ * This is where we store the column information to be used in decoding the
+ * TDS_ROW_TOKEN tokens.
+ */
+struct _tds_col {
+ gchar name[256];
+ guint16 utype;
+ guint8 ctype;
+ guint csize;
+};
+
+struct _netlib_data {
+ guint num_cols;
+ struct _tds_col *columns[MAX_COLUMNS];
+};
+
+struct tds7_login_packet_hdr {
+ guint32 total_packet_size;
+ guint32 tds_version;
+ guint32 packet_size;
+ guint32 client_version;
+ guint32 client_pid;
+ guint32 connection_id;
+ guint8 option_flags1;
+ guint8 option_flags2;
+ guint8 sql_type_flags;
+ guint8 reserved_flags;
+ guint32 time_zone;
+ guint32 collation;
+};
+
+/* all the standard memory management stuff */
+#define tds_column_length (sizeof(struct _tds_col))
+#define tds_column_init_count 10
+
+static GMemChunk *tds_column = NULL;
+
+/* support routines */
+static void
+dissect_tds_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ guint offset, guint length)
+{
+ tvbuff_t *ntlmssp_tvb;
+
+ ntlmssp_tvb = tvb_new_subset(tvb, offset, length, length);
+ call_dissector(ntlmssp_handle, ntlmssp_tvb, pinfo, tree);
+}
+
+static void
+dissect_tds_query_packet(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint offset, len;
+ gboolean is_unicode = TRUE;
+ char *msg;
+
+ proto_item *query_hdr;
+ proto_tree *query_tree;
+
+ offset = 0;
+ query_hdr = proto_tree_add_text(tree, tvb, offset, -1, "TDS Query Packet");
+ query_tree = proto_item_add_subtree(query_hdr, ett_tds7_query);
+ len = tvb_reported_length_remaining(tvb, offset);
+ if((len < 2) || tvb_get_guint8(tvb, offset+1) !=0)
+ is_unicode = FALSE;
+
+ if (is_unicode) {
+ msg = tvb_fake_unicode(tvb, offset, len/2, TRUE);
+ proto_tree_add_text(query_tree, tvb, offset, len, "Query: %s", msg);
+ g_free(msg);
+ offset += len;
+ }
+}
+
+static void
+dissect_tds7_login(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint offset, i, offset2, len;
+ gboolean is_unicode = TRUE;
+ char *val;
+
+ proto_item *login_hdr;
+ proto_tree *login_tree;
+ proto_item *header_hdr;
+ proto_tree *header_tree;
+ proto_item *length_hdr;
+ proto_tree *length_tree;
+
+ struct tds7_login_packet_hdr td7hdr;
+ gint length_remaining;
+
+
+ /* create display subtree for the protocol */
+ offset = 0;
+ login_hdr = proto_tree_add_text(tree, tvb, offset, -1, "TDS7 Login Packet");
+ login_tree = proto_item_add_subtree(login_hdr, ett_tds7_login);
+ header_hdr = proto_tree_add_text(login_tree, tvb, offset, 36, "Login Packet Header");
+ header_tree = proto_item_add_subtree(header_hdr, ett_tds7_hdr);
+
+ td7hdr.total_packet_size = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_login_total_size, tvb, offset, sizeof(td7hdr.total_packet_size), td7hdr.total_packet_size);
+ offset += sizeof(td7hdr.total_packet_size);
+
+ td7hdr.tds_version = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_version, tvb, offset, sizeof(td7hdr.tds_version), td7hdr.tds_version);
+ offset += sizeof(td7hdr.tds_version);
+
+ td7hdr.packet_size = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_packet_size, tvb, offset, sizeof(td7hdr.packet_size), td7hdr.packet_size);
+ offset += sizeof(td7hdr.packet_size);
+
+ td7hdr.client_version = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_client_version, tvb, offset, sizeof(td7hdr.client_version), td7hdr.client_version);
+ offset += sizeof(td7hdr.client_version);
+
+ td7hdr.client_pid = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_client_pid, tvb, offset, sizeof(td7hdr.client_pid), td7hdr.client_pid);
+ offset += sizeof(td7hdr.client_pid);
+
+ td7hdr.connection_id= tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_connection_id, tvb, offset, sizeof(td7hdr.connection_id), td7hdr.connection_id);
+ offset += sizeof(td7hdr.connection_id);
+
+ td7hdr.option_flags1 = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_option_flags1, tvb, offset, sizeof(td7hdr.option_flags1), td7hdr.option_flags1);
+ offset += sizeof(td7hdr.option_flags1);
+
+ td7hdr.option_flags2 = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_option_flags2, tvb, offset, sizeof(td7hdr.option_flags2), td7hdr.option_flags2);
+ offset += sizeof(td7hdr.option_flags2);
+
+ td7hdr.sql_type_flags = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_sql_type_flags, tvb, offset, sizeof(td7hdr.sql_type_flags), td7hdr.sql_type_flags);
+ offset += sizeof(td7hdr.sql_type_flags);
+
+ td7hdr.reserved_flags = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_reserved_flags, tvb, offset, sizeof(td7hdr.reserved_flags), td7hdr.reserved_flags);
+ offset += sizeof(td7hdr.reserved_flags);
+
+ td7hdr.time_zone = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_time_zone, tvb, offset, sizeof(td7hdr.time_zone), td7hdr.time_zone);
+ offset += sizeof(td7hdr.time_zone);
+
+ td7hdr.collation = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(header_tree, hf_tds7_collation, tvb, offset, sizeof(td7hdr.collation), td7hdr.collation);
+ offset += sizeof(td7hdr.collation);
+
+ length_hdr = proto_tree_add_text(login_tree, tvb, offset, 50, "Lengths and offsets");
+ length_tree = proto_item_add_subtree(length_hdr, ett_tds7_hdr);
+
+ for (i = 0; i < 9; i++) {
+ offset2 = tvb_get_letohs(tvb, offset + i*4);
+ len = tvb_get_letohs(tvb, offset + i*4 + 2);
+ proto_tree_add_text(length_tree, tvb, offset + i*4, 2,
+ "%s offset: %u",
+ val_to_str(i, login_field_names, "Unknown"),
+ offset2);
+ proto_tree_add_text(length_tree, tvb, offset + i*4 + 2, 2,
+ "%s length: %u",
+ val_to_str(i, login_field_names, "Unknown"),
+ len);
+ if (len != 0) {
+ if( i != 2) {
+ if (is_unicode == TRUE) {
+ val = tvb_fake_unicode(tvb, offset2, len, TRUE);
+ len *= 2;
+ } else
+ val = tvb_get_string(tvb, offset2, len);
+ proto_tree_add_text(login_tree, tvb, offset2, len, "%s: %s", val_to_str(i, login_field_names, "Unknown"), val);
+ g_free(val);
+ }
+ else {
+ if (is_unicode)
+ len *= 2;
+ proto_tree_add_text(login_tree, tvb, offset2, len, "%s", val_to_str(i, login_field_names, "Unknown"));
+ }
+ }
+ }
+
+ length_remaining = tvb_reported_length_remaining(tvb, offset2 + len);
+ if (length_remaining > 0) {
+ dissect_tds_ntlmssp(tvb, pinfo, login_tree, offset2 + len,
+ length_remaining);
+ }
+}
+
+static int get_size_by_coltype(int servertype)
+{
+ switch(servertype)
+ {
+ case SYBINT1: return 1; break;
+ case SYBINT2: return 2; break;
+ case SYBINT4: return 4; break;
+ case SYBINT8: return 8; break;
+ case SYBREAL: return 4; break;
+ case SYBFLT8: return 8; break;
+ case SYBDATETIME: return 8; break;
+ case SYBDATETIME4: return 4; break;
+ case SYBBIT: return 1; break;
+ case SYBBITN: return 1; break;
+ case SYBMONEY: return 8; break;
+ case SYBMONEY4: return 4; break;
+ case SYBUNIQUE: return 16; break;
+ default: return -1; break;
+ }
+}
+static int tds_is_fixed_token(int token)
+{
+ switch (token) {
+ case TDS_DONE_TOKEN:
+ case TDS_DONEPROC_TOKEN:
+ case TDS_DONEINPROC_TOKEN:
+ case TDS_RET_STAT_TOKEN:
+ case TDS7_RESULT_TOKEN:
+ return 1;
+ default:
+ return 0;
+ }
+}
+static int tds_get_token_size(int token)
+{
+ switch(token) {
+ case TDS_DONE_TOKEN:
+ case TDS_DONEPROC_TOKEN:
+ case TDS_DONEINPROC_TOKEN:
+ return 8;
+ case TDS_RET_STAT_TOKEN:
+ return 4;
+ case TDS_124_TOKEN:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+# if 0
+/*
+ * data_to_string should take column data and turn it into something we can
+ * display on the tree.
+ */
+static char *data_to_string(void *data, guint col_type, guint col_size)
+{
+ static char result[256];
+ guint i;
+
+ switch(col_type) {
+ case SYBVARCHAR:
+ /* strncpy(result, (char *)data, col_size); */
+ for (i=0;i<col_size && i<(256-1);i++)
+ if (!isprint(((char *)data)[i])) result[i]='.';
+ else result[i]=((char *)data)[i];
+ result[i] = '\0';
+ break;
+ case SYBINT2:
+ sprintf(result, "%d", *(short *)data);
+ break;
+ case SYBINT4:
+ sprintf(result, "%d", *(int *)data);
+ break;
+ default:
+ sprintf(result, "Unexpected column_type %d", col_type);
+ break;
+ }
+ return result;
+}
+#endif
+
+/*
+ * Since rows are special PDUs in that they are not fixed and lack a size field,
+ * the length must be computed using the column information seen in the result
+ * PDU. This function does just that.
+ */
+static size_t
+tds_get_row_size(tvbuff_t *tvb, struct _netlib_data *nl_data, guint offset)
+{
+ guint cur, i, csize;
+
+ cur = offset;
+ for (i = 0; i < nl_data->num_cols; i++) {
+ if (!is_fixed_coltype(nl_data->columns[i]->ctype)) {
+ csize = tvb_get_guint8(tvb, cur);
+ cur++;
+ } else
+ csize = get_size_by_coltype(nl_data->columns[i]->ctype);
+ cur += csize;
+ }
+
+ return (cur - offset + 1);
+}
+
+/*
+ * Read the results token and store the relevant information in the
+ * _netlib_data structure for later use (see tds_get_row_size).
+ */
+static gboolean
+read_results_tds5(tvbuff_t *tvb, struct _netlib_data *nl_data, guint offset)
+{
+ guint len, name_len;
+ guint cur;
+ guint i;
+
+ len = tvb_get_letohs(tvb, offset+1);
+ cur = offset + 3;
+
+ /*
+ * This would be the logical place to check for little/big endianess
+ * if we didn't see the login packet.
+ */
+ nl_data->num_cols = tvb_get_letohs(tvb, cur);
+ if (nl_data->num_cols > MAX_COLUMNS) {
+ nl_data->num_cols = 0;
+ return FALSE;
+ }
+
+ cur += 2;
+
+ for (i = 0; i < nl_data->num_cols; i++) {
+ nl_data->columns[i] = g_mem_chunk_alloc(tds_column);
+ name_len = tvb_get_guint8(tvb,cur);
+ cur ++;
+ cur += name_len;
+
+ cur++; /* unknown */
+
+ nl_data->columns[i]->utype = tvb_get_letohs(tvb, cur);
+ cur += 2;
+
+ cur += 2; /* unknown */
+
+ nl_data->columns[i]->ctype = tvb_get_guint8(tvb,cur);
+ cur++;
+
+ if (!is_fixed_coltype(nl_data->columns[i]->ctype)) {
+ nl_data->columns[i]->csize = tvb_get_guint8(tvb,cur);
+ cur ++;
+ } else {
+ nl_data->columns[i]->csize =
+ get_size_by_coltype(nl_data->columns[i]->ctype);
+ }
+ cur++; /* unknown */
+ }
+ return TRUE;
+}
+
+/*
+ * If the packet type from the netlib header is a login packet, then dig into
+ * the packet to see if this is a supported TDS version and verify the otherwise
+ * weak heuristics of the netlib check.
+ */
+static gboolean
+netlib_check_login_pkt(tvbuff_t *tvb, guint offset, packet_info *pinfo, guint8 type)
+{
+ guint tds_major, bytes_avail;
+
+ bytes_avail = tvb_length(tvb) - offset;
+ /*
+ * we have two login packet styles, one for TDS 4.2 and 5.0
+ */
+ if (type==TDS_LOGIN_PKT) {
+ /* Use major version number to validate TDS 4/5 login
+ * packet */
+
+ /* Login packet is first in stream and should not be fragmented...
+ * if it is we are screwed */
+ if (bytes_avail < 467) return FALSE;
+ tds_major = tvb_get_guint8(tvb, 466);
+ if (tds_major != 4 && tds_major != 5) {
+ return FALSE;
+ }
+ /*
+ * and one added by Microsoft in SQL Server 7
+ */
+ } else if (type==TDS_LOGIN7_PKT) {
+ if (bytes_avail < 16) return FALSE;
+ tds_major = tvb_get_guint8(tvb, 15);
+ if (tds_major != 0x70 && tds_major != 0x80) {
+ return FALSE;
+ }
+ } else if (type==TDS_QUERY5_PKT) {
+ if (bytes_avail < 9) return FALSE;
+ /* if this is a TDS 5.0 query check the token */
+ if (tvb_get_guint8(tvb, 8) != TDS_LANG_TOKEN) {
+ return FALSE;
+ }
+ /* check if it is MS SQL default port */
+ } else if (pinfo->srcport != 1433 &&
+ pinfo->destport != 1433) {
+ /* otherwise, we can not ensure this is netlib */
+ /* beyond a reasonable doubt. */
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+dissect_tds_env_chg(tvbuff_t *tvb, guint offset, guint token_sz,
+ proto_tree *tree)
+{
+ guint8 env_type;
+ guint old_len, new_len, old_len_offset;
+ char *new_val = NULL, *old_val = NULL;
+ guint32 string_offset;
+ gboolean is_unicode = FALSE;
+ guint16 collate_codepage, collate_flags;
+ guint8 collate_charset_id;
+
+ env_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Type: %u (%s)", env_type,
+ val_to_str(env_type, env_chg_names, "Unknown"));
+
+ new_len = tvb_get_guint8(tvb, offset+1);
+ old_len_offset = offset + new_len + 2;
+ old_len = tvb_get_guint8(tvb, old_len_offset);
+
+ /*
+ * If our lengths plus the lengths of the type and the lengths
+ * don't add up to the token size, it must be UCS2.
+ */
+ if (old_len + new_len + 3 != token_sz) {
+ is_unicode = TRUE;
+ old_len_offset = offset + (new_len * 2) + 2;
+ old_len = tvb_get_guint8(tvb, old_len_offset);
+ }
+
+ proto_tree_add_text(tree, tvb, offset + 1, 1, "New Value Length: %u",
+ new_len);
+ if (new_len) {
+ if (env_type != 7) { /* if it's not 'Collation Info - which is not textual! */
+ string_offset = offset + 2;
+ if (is_unicode == TRUE) {
+ new_val = tvb_fake_unicode(tvb, string_offset,
+ new_len, TRUE);
+ new_len *= 2;
+ } else
+ new_val = tvb_get_string(tvb, string_offset, new_len);
+ proto_tree_add_text(tree, tvb, string_offset, new_len,
+ "New Value: %s", new_val);
+ g_free(new_val);
+ }
+ else { /* parse collation info structure. From http://www.freetds.org/tds.html#collate */
+ offset +=2;
+ collate_codepage = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Codepage: %u" , collate_codepage);
+ offset += 2;
+ collate_flags = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Flags: 0x%x", collate_flags);
+ offset += 2;
+ collate_charset_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Charset ID: %u", collate_charset_id);
+ offset +=1;
+ }
+ }
+
+ proto_tree_add_text(tree, tvb, old_len_offset, 1, "Old Value Length: %u",
+ old_len);
+ if (old_len) {
+ string_offset = old_len_offset + 1;
+ if (is_unicode == TRUE) {
+ old_val = tvb_fake_unicode(tvb, string_offset,
+ old_len, TRUE);
+ old_len *= 2;
+ } else
+ old_val = tvb_get_string(tvb, string_offset, old_len);
+ proto_tree_add_text(tree, tvb, string_offset, old_len,
+ "Old Value: %s", old_val);
+ g_free(old_val);
+ }
+}
+
+static void
+dissect_tds_msg_token(tvbuff_t *tvb, guint offset, guint token_sz, proto_tree *tree)
+{
+ guint16 msg_len;
+ guint8 srvr_len;
+ char *msg;
+ gboolean is_unicode = FALSE;
+
+ proto_tree_add_text(tree, tvb, offset, 4, "SQL Message Number: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_text(tree, tvb, offset, 1, "State: %u", tvb_get_guint8(tvb, offset));
+ offset +=1;
+ proto_tree_add_text(tree, tvb, offset, 1, "Level: %u", tvb_get_guint8(tvb, offset));
+ offset +=1;
+
+ msg_len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Message length: %u characters", msg_len);
+ offset +=2;
+
+ srvr_len = tvb_get_guint8(tvb, offset + msg_len);
+
+ if(msg_len + srvr_len + 9U + 3U != token_sz) /* 9 is the length of message number (4), state (1), level (1), msg_len (2), srvr_len (1) fields */
+ is_unicode = TRUE;
+
+ if(is_unicode) {
+ msg = tvb_fake_unicode(tvb, offset, msg_len, TRUE);
+ msg_len *= 2;
+ } else {
+ msg = tvb_get_string(tvb, offset, msg_len);
+ }
+ proto_tree_add_string(tree, hf_tds7_message, tvb, offset, msg_len, msg);
+ g_free(msg);
+ offset += msg_len;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "Server name length: %u characters", srvr_len);
+ offset +=1;
+
+ if (is_unicode) {
+ msg = tvb_fake_unicode(tvb, offset, srvr_len, TRUE);
+ srvr_len *=2;
+ } else {
+ msg = tvb_get_string(tvb, offset, srvr_len);
+ }
+ proto_tree_add_text(tree, tvb, offset, srvr_len, "Server name: %s", msg);
+ g_free(msg);
+}
+
+static void
+dissect_tds_err_token(tvbuff_t *tvb, guint offset, guint token_sz, proto_tree *tree)
+{
+ guint16 msg_len;
+ guint8 srvr_len;
+ char *msg;
+ gboolean is_unicode = FALSE;
+
+ proto_tree_add_text(tree, tvb, offset, 4, "SQL Error Number: %d", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_text(tree, tvb, offset, 1, "State: %u", tvb_get_guint8(tvb, offset));
+ offset +=1;
+ proto_tree_add_text(tree, tvb, offset, 1, "Level: %u", tvb_get_guint8(tvb, offset));
+ offset +=1;
+
+ msg_len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Error length: %u characters", msg_len);
+ offset +=2;
+
+ srvr_len = tvb_get_guint8(tvb, offset + msg_len);
+
+ if(msg_len + srvr_len + 9U + 3U != token_sz) /* 9 is the length of message number (4), state (1), level (1), msg_len (2), srvr_len (1) fields */
+ is_unicode = TRUE;
+
+ if(is_unicode) {
+ msg = tvb_fake_unicode(tvb, offset, msg_len, TRUE);
+ msg_len *= 2;
+ } else {
+ msg = tvb_get_string(tvb, offset, msg_len);
+ }
+ proto_tree_add_text(tree, tvb, offset, msg_len, "Error: %s", format_text(msg, strlen(msg)));
+ g_free(msg);
+ offset += msg_len;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "Server name length: %u characters", srvr_len);
+ offset +=1;
+
+ if (is_unicode) {
+ msg = tvb_fake_unicode(tvb, offset, srvr_len, TRUE);
+ srvr_len *=2;
+ } else {
+ msg = tvb_get_string(tvb, offset, srvr_len);
+ }
+ proto_tree_add_text(tree, tvb, offset, srvr_len, "Server name: %s", msg);
+ g_free(msg);
+}
+
+static void
+dissect_tds_login_ack_token(tvbuff_t *tvb, guint offset, guint token_sz, proto_tree *tree)
+{
+ guint8 msg_len;
+ char *msg;
+ gboolean is_unicode = FALSE;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "Ack: %u", tvb_get_guint8(tvb, offset));
+ offset +=1;
+ proto_tree_add_text(tree, tvb, offset, 1, "Major version (may be incorrect): %d", tvb_get_guint8(tvb, offset));
+ offset +=1;
+ proto_tree_add_text(tree, tvb, offset, 1, "Minor version (may be incorrect): %d", tvb_get_guint8(tvb, offset));
+ offset +=1;
+ proto_tree_add_text(tree, tvb, offset, 2, "zero usually");
+ offset +=2;
+
+ msg_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Text length: %u characters", msg_len);
+ offset +=1;
+
+ if(msg_len + 6U + 3U != token_sz - 1) /* 6 is the length of ack(1), version (4), text length (1) fields */
+ is_unicode = TRUE;
+ proto_tree_add_text(tree, tvb, offset, 0, "msg_len: %d, token_sz: %d, total: %d",msg_len, token_sz, msg_len + 6U + 3U);
+ if(is_unicode) {
+ msg = tvb_fake_unicode(tvb, offset, msg_len, TRUE);
+ msg_len *= 2;
+ } else {
+ msg = tvb_get_string(tvb, offset, msg_len);
+ }
+ proto_tree_add_text(tree, tvb, offset, msg_len, "Text: %s", format_text(msg, strlen(msg)));
+ g_free(msg);
+ offset += msg_len;
+
+ proto_tree_add_text(tree, tvb, offset, 4, "Server Version");
+ offset += 4;
+}
+
+int
+dissect_tds7_results_token(tvbuff_t *tvb, guint offset, proto_tree *tree)
+{
+ guint16 num_columns, table_len;
+ guint8 type, msg_len;
+ int i;
+ char *msg;
+ guint16 collate_codepage, collate_flags;
+ guint8 collate_charset_id;
+
+ num_columns = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Columns: %u", tvb_get_letohs(tvb, offset));
+ offset +=2;
+ for(i=0; i != num_columns; i++) {
+ proto_tree_add_text(tree, tvb, offset, 0, "Column %d", i + 1);
+ proto_tree_add_text(tree, tvb, offset, 2, "usertype: %d", tvb_get_letohs(tvb, offset));
+ offset +=2;
+ proto_tree_add_text(tree, tvb, offset, 2, "flags: %d", tvb_get_letohs(tvb, offset));
+ offset +=2;
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Type: %d", type);
+ offset +=1;
+ if(type == 38 || type == 104) { /* ugly, ugly hack. Wish I knew what it really means!*/
+ proto_tree_add_text(tree, tvb, offset, 1, "unknown 1 byte (%x)", tvb_get_guint8(tvb, offset));
+ offset +=1;
+ }
+ else if (type == 35) {
+ proto_tree_add_text(tree, tvb, offset, 4, "unknown 4 bytes (%x)", tvb_get_letohl(tvb, offset));
+ offset += 4;
+ collate_codepage = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Codepage: %u" , collate_codepage);
+ offset += 2;
+ collate_flags = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Flags: 0x%x", collate_flags);
+ offset += 2;
+ collate_charset_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Charset ID: %u", collate_charset_id);
+ offset +=1;
+ table_len = tvb_get_letohs(tvb, offset);
+ offset +=2;
+ if(table_len != 0) {
+ msg = tvb_fake_unicode(tvb, offset, table_len, TRUE);
+ proto_tree_add_text(tree, tvb, offset, table_len*2, "Table name: %s", msg);
+ g_free(msg);
+ offset += table_len*2;
+ }
+ }
+ else if (type == 106) {
+ proto_tree_add_text(tree, tvb, offset, 3, "unknown 3 bytes");
+ offset +=3;
+ }
+ if(type > 128) {
+ proto_tree_add_text(tree, tvb, offset, 2, "Large type size: 0x%x", tvb_get_letohs(tvb, offset));
+ offset += 2;
+ collate_codepage = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Codepage: %u" , collate_codepage);
+ offset += 2;
+ collate_flags = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "Flags: 0x%x", collate_flags);
+ offset += 2;
+ collate_charset_id = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Charset ID: %u", collate_charset_id);
+ offset +=1;
+ }
+ msg_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "message length: %d",msg_len);
+ offset += 1;
+ if(msg_len != 0) {
+ msg = tvb_fake_unicode(tvb, offset, msg_len, TRUE);
+ proto_tree_add_text(tree, tvb, offset, msg_len*2, "Text: %s", msg);
+ g_free(msg);
+ offset += msg_len*2;
+ }
+ }
+ return offset;
+}
+
+static void
+dissect_tds_done_token(tvbuff_t *tvb, guint offset, proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, 2, "bit flag");
+ offset += 2;
+ proto_tree_add_text(tree, tvb, offset, 2, "unknown");
+ offset += 2;
+ proto_tree_add_text(tree, tvb, offset, 4, "row count: %u", tvb_get_letohl(tvb, offset));
+ offset += 2;
+}
+
+static void
+dissect_tds_rpc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+ int offset = 0;
+ guint len;
+ const char *val;
+
+ /*
+ * RPC name.
+ * XXX - how can we determine whether this is ASCII or Unicode?
+ */
+ len = tvb_get_letohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "RPC Name Length: %u", len);
+ offset += 2;
+ if (len != 0) {
+ val = tvb_fake_unicode(tvb, offset, len, TRUE);
+ len *= 2;
+ proto_tree_add_text(tree, tvb, offset, len, "RPC Name: %s",
+ val);
+ offset += len;
+ }
+
+ proto_tree_add_text(tree, tvb, offset, -1, "Unknown data");
+}
+
+static void
+dissect_tds_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_item *token_item;
+ proto_tree *token_tree;
+ guint pos, token_sz = 0;
+ guint8 token;
+ struct _netlib_data nl_data;
+ gint length_remaining;
+
+ memset(&nl_data, '\0', sizeof nl_data);
+
+ /*
+ * Until we reach the end of the packet, read tokens.
+ */
+ pos = offset;
+ while (tvb_reported_length_remaining(tvb, pos) > 0) {
+ /* our token */
+ token = tvb_get_guint8(tvb, pos);
+
+ if (tds_is_fixed_token(token)) {
+ token_sz = tds_get_token_size(token) + 1;
+ } else if (token == TDS_ROW_TOKEN) {
+ /*
+ * Rows are special; they have no size field and
+ * aren't fixed length.
+ */
+ token_sz = tds_get_row_size(tvb, &nl_data, pos + 1);
+ } else
+ token_sz = tvb_get_letohs(tvb, pos + 1) + 3;
+
+ length_remaining = tvb_ensure_length_remaining(tvb, pos);
+ if (token_sz > (guint)length_remaining)
+ token_sz = (guint)length_remaining;
+
+ token_item = proto_tree_add_text(tree, tvb, pos, token_sz,
+ "Token 0x%02x %s", token,
+ val_to_str(token, token_names, "Unknown Token Type"));
+ token_tree = proto_item_add_subtree(token_item, ett_tds_token);
+
+ /*
+ * If it's a variable token, put the length field in here
+ * instead of replicating this for each token subdissector.
+ */
+ if (!tds_is_fixed_token(token) && token != TDS_ROW_TOKEN) {
+ proto_tree_add_text(token_tree, tvb, pos+1, 2,
+ "Length: %u", tvb_get_letohs(tvb, pos+1));
+ }
+
+ switch (token) {
+
+ case TDS_RESULT_TOKEN:
+ /*
+ * If it's a result token, we need to stash the
+ * column info.
+ */
+ read_results_tds5(tvb, &nl_data, pos);
+ break;
+
+ case TDS_ENV_CHG_TOKEN:
+ dissect_tds_env_chg(tvb, pos + 3, token_sz - 3,
+ token_tree);
+ break;
+
+ case TDS_AUTH_TOKEN:
+ dissect_tds_ntlmssp(tvb, pinfo, token_tree, pos + 3,
+ token_sz - 3);
+ break;
+ case TDS_MSG_TOKEN:
+ dissect_tds_msg_token(tvb, pos + 3, token_sz - 3, token_tree);
+ break;
+ case TDS_ERR_TOKEN:
+ dissect_tds_err_token(tvb, pos + 3, token_sz - 3, token_tree);
+ break;
+ case TDS_DONE_TOKEN:
+ dissect_tds_done_token(tvb, pos + 1, token_tree);
+ break;
+ case TDS_LOGIN_ACK_TOKEN:
+ dissect_tds_login_ack_token(tvb, pos + 3, token_sz - 3, token_tree);
+ break;
+ case TDS7_RESULT_TOKEN:
+ pos = (dissect_tds7_results_token(tvb, pos + 1, token_tree)-1);
+ break;
+ }
+
+ /* and step to the end of the token, rinse, lather, repeat */
+ pos += token_sz;
+ }
+}
+
+static void
+dissect_netlib_buffer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_item *tds_item = NULL;
+ proto_tree *tds_tree = NULL;
+ guint8 type;
+ guint8 status;
+ guint16 size;
+ guint16 channel;
+ guint8 packet_number;
+ gboolean save_fragmented;
+ int len;
+ fragment_data *fd_head;
+ tvbuff_t *next_tvb;
+
+ if (tree) {
+ /* create display subtree for the protocol */
+ tds_item = proto_tree_add_item(tree, proto_tds, tvb, offset, -1,
+ FALSE);
+
+ tds_tree = proto_item_add_subtree(tds_item, ett_tds);
+ }
+ type = tvb_get_guint8(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tds_tree, hf_tds_type, tvb, offset, 1,
+ type);
+ }
+ status = tvb_get_guint8(tvb, offset + 1);
+ if (tree) {
+ proto_tree_add_uint(tds_tree, hf_tds_status, tvb, offset + 1, 1,
+ status);
+ }
+ size = tvb_get_ntohs(tvb, offset + 2);
+ if (tree) {
+ proto_tree_add_uint(tds_tree, hf_tds_size, tvb, offset + 2, 2,
+ size);
+ }
+ channel = tvb_get_ntohs(tvb, offset + 4);
+ if (tree) {
+ proto_tree_add_uint(tds_tree, hf_tds_channel, tvb, offset + 4, 2,
+ channel);
+ }
+ packet_number = tvb_get_guint8(tvb, offset + 6);
+ if (tree) {
+ proto_tree_add_uint(tds_tree, hf_tds_packet_number, tvb, offset + 6, 1,
+ packet_number);
+ proto_tree_add_item(tds_tree, hf_tds_window, tvb, offset + 7, 1,
+ FALSE);
+ }
+ offset += 8; /* skip Netlib header */
+
+ /*
+ * Deal with fragmentation.
+ */
+ save_fragmented = pinfo->fragmented;
+ if (tds_defragment &&
+ (packet_number > 1 || status == STATUS_NOT_LAST_BUFFER)) {
+ if (status == STATUS_NOT_LAST_BUFFER) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO,
+ " (Not last buffer)");
+ }
+ len = tvb_reported_length_remaining(tvb, offset);
+ /*
+ * XXX - I've seen captures that start with a login
+ * packet with a sequence number of 2.
+ */
+ fd_head = fragment_add_seq_check(tvb, offset, pinfo, channel,
+ tds_fragment_table, tds_reassembled_table,
+ packet_number - 1, len, status == STATUS_NOT_LAST_BUFFER);
+ next_tvb = process_reassembled_data(tvb, offset, pinfo,
+ "Reassembled TDS", fd_head, &tds_frag_items, NULL,
+ tds_tree);
+ } else {
+ /*
+ * If this isn't the last buffer, just show it as a fragment.
+ * (XXX - it'd be nice to dissect it if it's the first
+ * buffer, but we'd need to do reassembly in order to
+ * discover that.)
+ *
+ * If this is the last buffer, dissect it.
+ * (XXX - it'd be nice to show it as a fragment if it's part
+ * of a fragmented message, but we'd need to do reassembly
+ * in order to discover that.)
+ */
+ if (status == STATUS_NOT_LAST_BUFFER)
+ next_tvb = NULL;
+ else {
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ }
+ }
+ if (next_tvb != NULL) {
+ switch (type) {
+
+ case TDS_RPC_PKT:
+ dissect_tds_rpc(next_tvb, pinfo, tds_tree);
+ break;
+
+ case TDS_RESP_PKT:
+ dissect_tds_resp(next_tvb, pinfo, tds_tree);
+ break;
+
+ case TDS_LOGIN7_PKT:
+ dissect_tds7_login(next_tvb, pinfo, tds_tree);
+ break;
+ case TDS_QUERY_PKT:
+ dissect_tds_query_packet(next_tvb, pinfo, tds_tree);
+ break;
+ default:
+ proto_tree_add_text(tds_tree, next_tvb, 0, -1,
+ "TDS Packet");
+ break;
+ }
+ } else {
+ next_tvb = tvb_new_subset (tvb, offset, -1, -1);
+ call_dissector(data_handle, next_tvb, pinfo, tds_tree);
+ }
+}
+
+static void
+dissect_tds_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ volatile gboolean first_time = TRUE;
+ volatile int offset = 0;
+ guint length_remaining;
+ guint8 type;
+ guint16 plen;
+ guint length;
+ tvbuff_t *next_tvb;
+ proto_item *tds_item = NULL;
+ proto_tree *tds_tree = NULL;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ length_remaining = tvb_ensure_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (tds_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the fixed-length part of the PDU
+ * split across segment boundaries?
+ */
+ if (length_remaining < 8) {
+ /*
+ * Yes. Tell the TCP dissector where the
+ * data for this message starts in the data
+ * it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 8 - length_remaining;
+ return;
+ }
+ }
+
+ type = tvb_get_guint8(tvb, offset);
+
+ /*
+ * Get the length of the PDU.
+ */
+ plen = tvb_get_ntohs(tvb, offset + 2);
+ if (plen < 8) {
+ /*
+ * The length is less than the header length.
+ * Put in the type, status, and length, and
+ * report the length as bogus.
+ */
+ if (tree) {
+ /* create display subtree for the protocol */
+ tds_item = proto_tree_add_item(tree, proto_tds,
+ tvb, offset, -1, FALSE);
+
+ tds_tree = proto_item_add_subtree(tds_item,
+ ett_tds);
+ proto_tree_add_uint(tds_tree, hf_tds_type, tvb,
+ offset, 1, type);
+ proto_tree_add_item(tds_tree, hf_tds_status,
+ tvb, offset + 1, 1, FALSE);
+ proto_tree_add_uint_format(tds_tree,
+ hf_tds_size, tvb, offset + 2, 2, plen,
+ "Size: %u (bogus, should be >= 8)", plen);
+ }
+
+ /*
+ * Give up - we can't dissect any more of this
+ * data.
+ */
+ break;
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (tds_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the PDU split across segment boundaries?
+ */
+ if (length_remaining < plen) {
+ /*
+ * Yes. Tell the TCP dissector where the
+ * data for this message starts in the data
+ * it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = plen - length_remaining;
+ return;
+ }
+ }
+
+ if (first_time) {
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TDS");
+
+ /*
+ * Set the packet description based on its TDS packet
+ * type.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(type, packet_type_names,
+ "Unknown Packet Type: %u"));
+ }
+ first_time = FALSE;
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload
+ * we have available. Make its reported length the amount
+ * of data in the PDU.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector will
+ * throw a BoundsError exception, rather than a
+ * ReportedBoundsError exception. We really want a tvbuff
+ * where the length is "length", the reported length is
+ * "plen", and the "if the snapshot length were infinite"
+ * length is the minimum of the reported length of the tvbuff
+ * handed to us and "plen", with a new type of exception
+ * thrown if the offset is within the reported length but
+ * beyond that third length, with that exception getting the
+ * "Unreassembled Packet" error.
+ */
+ length = length_remaining;
+ if (length > plen)
+ length = plen;
+ next_tvb = tvb_new_subset(tvb, offset, length, plen);
+
+ /*
+ * Dissect the Netlib buffer.
+ *
+ * Catch the ReportedBoundsError exception; if this
+ * particular Netlib buffer happens to get a
+ * ReportedBoundsError exception, that doesn't mean
+ * that we should stop dissecting PDUs within this frame
+ * or chunk of reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing
+ * more to see, so we just re-throw it.
+ */
+ TRY {
+ dissect_netlib_buffer(next_tvb, pinfo, tree);
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ }
+ ENDTRY;
+
+ /*
+ * Step to the next Netlib buffer.
+ */
+ offset += plen;
+ }
+}
+
+static gboolean
+dissect_tds_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint8 type;
+ guint8 status;
+ guint16 plen;
+ conversation_t *conv;
+
+ /*
+ * If we don't have even enough data for a Netlib header,
+ * just say it's not TDS.
+ */
+ if (!tvb_bytes_exist(tvb, offset, 8))
+ return FALSE;
+
+ /*
+ * Quickly scan all the data we have in order to see if
+ * everything in it looks like Netlib traffic.
+ */
+ while (tvb_bytes_exist(tvb, offset, 1)) {
+ /*
+ * Check the type field.
+ */
+ type = tvb_get_guint8(tvb, offset);
+ if (!is_valid_tds_type(type))
+ return FALSE;
+
+ /*
+ * Check the status field, if it's present.
+ */
+ if (!tvb_bytes_exist(tvb, offset + 1, 1))
+ break;
+ status = tvb_get_guint8(tvb, offset + 1);
+ if (!is_valid_tds_status(status))
+ return FALSE;
+
+ /*
+ * Get the length of the PDU.
+ */
+ if (!tvb_bytes_exist(tvb, offset + 2, 2))
+ break;
+ plen = tvb_get_ntohs(tvb, offset + 2);
+ if (plen < 8) {
+ /*
+ * The length is less than the header length.
+ * That's bogus.
+ */
+ return FALSE;
+ }
+
+ /*
+ * If we're at the beginning of the segment, check the
+ * payload if it's a login packet.
+ */
+ if (offset == 0) {
+ if (!netlib_check_login_pkt(tvb, offset, pinfo, type))
+ return FALSE;
+ }
+
+ /*
+ * Step to the next Netlib buffer.
+ */
+ offset += plen;
+ }
+
+ /*
+ * OK, it passes the test; assume the rest of this conversation
+ * is TDS.
+ */
+ conv = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (conv == NULL) {
+ /*
+ * No conversation exists yet - create one.
+ */
+ conv = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ conversation_set_dissector(conv, tds_tcp_handle);
+
+ /*
+ * Now dissect it as TDS.
+ */
+ dissect_tds_tcp(tvb, pinfo, tree);
+ return TRUE;
+}
+
+static void
+tds_init(void)
+{
+ /*
+ * Initialize the fragment and reassembly tables.
+ */
+ fragment_table_init(&tds_fragment_table);
+ reassembled_table_init(&tds_reassembled_table);
+
+ /*
+ * Reinitialize the chunks of data for remembering row
+ * information.
+ */
+ if (tds_column)
+ g_mem_chunk_destroy(tds_column);
+
+ tds_column = g_mem_chunk_new("tds_column", tds_column_length,
+ tds_column_init_count * tds_column_length,
+ G_ALLOC_AND_FREE);
+}
+
+/* Register the protocol with Ethereal */
+
+/* this format is required because a script is used to build the C function
+ that calls all the protocol registration.
+*/
+
+void
+proto_register_netlib(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tds_type,
+ { "Type", "tds.type",
+ FT_UINT8, BASE_HEX, VALS(packet_type_names), 0x0,
+ "Packet Type", HFILL }
+ },
+ { &hf_tds_status,
+ { "Status", "tds.status",
+ FT_UINT8, BASE_DEC, VALS(status_names), 0x0,
+ "Frame status", HFILL }
+ },
+ { &hf_tds_size,
+ { "Size", "tds.size",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Packet Size", HFILL }
+ },
+ { &hf_tds_channel,
+ { "Channel", "tds.channel",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Channel Number", HFILL }
+ },
+ { &hf_tds_packet_number,
+ { "Packet Number", "tds.packet_number",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Packet Number", HFILL }
+ },
+ { &hf_tds_window,
+ { "Window", "tds.window",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Window", HFILL }
+ },
+ { &hf_tds_fragment_overlap,
+ { "Segment overlap", "tds.fragment.overlap",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }
+ },
+ { &hf_tds_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "tds.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }
+ },
+ { &hf_tds_fragment_multiple_tails,
+ { "Multiple tail fragments found", "tds.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }
+ },
+ { &hf_tds_fragment_too_long_fragment,
+ { "Segment too long", "tds.fragment.toolongfragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment contained data past end of packet", HFILL }
+ },
+ { &hf_tds_fragment_error,
+ { "Defragmentation error", "tds.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }
+ },
+ { &hf_tds_fragment,
+ { "TDS Fragment", "tds.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "TDS Fragment", HFILL }
+ },
+ { &hf_tds_fragments,
+ { "TDS Fragments", "tds.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "TDS Fragments", HFILL }
+ },
+ { &hf_tds_reassembled_in,
+ { "Reassembled TDS in frame", "tds.reassembled_in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This TDS packet is reassembled in this frame", HFILL }
+ },
+ { &hf_tds7_login_total_size,
+ { "Total Packet Length", "tds7login.total_len",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "TDS7 Login Packet total packet length", HFILL }
+ },
+ { &hf_tds7_version,
+ { "TDS version", "tds7login.version",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "TDS version", HFILL }
+ },
+ { &hf_tds7_packet_size,
+ { "Packet Size", "tds7login.packet_size",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Packet size", HFILL }
+ },
+ { &hf_tds7_client_version,
+ { "Client version", "tds7login.client_version",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Client version", HFILL }
+ },
+ { &hf_tds7_client_pid,
+ { "Client PID", "tds7login.client_pid",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Client PID", HFILL }
+ },
+ { &hf_tds7_connection_id,
+ { "Connection ID", "tds7login.connection_id",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Connection ID", HFILL }
+ },
+ { &hf_tds7_option_flags1,
+ { "Option Flags 1", "tds7login.option_flags1",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Option Flags 1", HFILL }
+ },
+ { &hf_tds7_option_flags2,
+ { "Option Flags 2", "tds7login.option_flags2",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Option Flags 2", HFILL }
+ },
+ { &hf_tds7_sql_type_flags,
+ { "SQL Type Flags", "tds7login.sql_type_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "SQL Type Flags", HFILL }
+ },
+ { &hf_tds7_reserved_flags,
+ { "Reserved Flags", "tds7login.reserved_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ "reserved flags", HFILL }
+ },
+ { &hf_tds7_time_zone,
+ { "Time Zone", "tds7login.time_zone",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Time Zone", HFILL }
+ },
+ { &hf_tds7_collation,
+ { "Collation", "tds7login.collation",
+ FT_UINT32, BASE_HEX, NULL, 0x0,
+ "Collation", HFILL }
+ },
+ { &hf_tds7_message,
+ { "Message", "tds7.message",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }
+ },
+ };
+ static gint *ett[] = {
+ &ett_tds,
+ &ett_tds_fragments,
+ &ett_tds_fragment,
+ &ett_tds_token,
+ &ett_tds7_login,
+ &ett_tds7_hdr,
+ };
+ module_t *tds_module;
+
+/* Register the protocol name and description */
+ proto_tds = proto_register_protocol("Tabular Data Stream",
+ "TDS", "tds");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_tds, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ tds_tcp_handle = create_dissector_handle(dissect_tds_tcp, proto_tds);
+
+ tds_module = prefs_register_protocol(proto_tds, NULL);
+ prefs_register_bool_preference(tds_module, "desegment_buffers",
+ "Desegment all TDS buffers spanning multiple TCP segments",
+ "Whether the TDS dissector should desegment all TDS buffers spanning multiple TCP segments",
+ &tds_desegment);
+ prefs_register_bool_preference(tds_module, "defragment",
+ "Defragment all TDS messages with multiple buffers",
+ "Whether the TDS dissector should defragment all messages spanning multiple Netlib buffers",
+ &tds_defragment);
+
+ register_init_routine(tds_init);
+}
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ This format is required because a script is used to find these routines and
+ create the code that calls these routines.
+*/
+void
+proto_reg_handoff_tds(void)
+{
+ /* dissector_add("tcp.port", 1433, dissect_tds,
+ proto_tds); */
+ heur_dissector_add("tcp", dissect_tds_tcp_heur, proto_tds);
+
+ ntlmssp_handle = find_dissector("ntlmssp");
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-teimanagement.c b/epan/dissectors/packet-teimanagement.c
new file mode 100644
index 0000000000..8d6dab4d41
--- /dev/null
+++ b/epan/dissectors/packet-teimanagement.c
@@ -0,0 +1,146 @@
+/* packet-teimanagement.c
+ * Routines for LAPD TEI Management frame disassembly
+ * Rolf Fiedler <rolf.fiedler@innoventif.com>
+ * based on code by Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "lapd_sapi.h"
+
+/* ISDN/LAPD references:
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/cisintwk/ito_doc/isdn.htm
+ * http://www.ece.wpi.edu/courses/ee535/hwk11cd95/agrebe/agrebe.html
+ * http://www.acacia-net.com/Clarinet/Protocol/q9213o84.htm
+ */
+
+static int proto_tei=-1;
+
+static int lm_entity_id=-1;
+static int lm_reference=-1;
+static int lm_message=-1;
+static int lm_action=-1;
+static int lm_extend =-1;
+static gint lm_subtree=-1;
+
+#define TEI_ID_REQUEST 0x01
+#define TEI_ID_ASSIGNED 0x02
+#define TEI_ID_DENIED 0x03
+#define TEI_ID_CHECK_REQ 0x04
+#define TEI_ID_CHECK_RESP 0x05
+#define TEI_ID_REMOVE 0x06
+#define TEI_ID_VERIFY 0x07
+
+static const value_string tei_msg_vals[]={
+ { TEI_ID_REQUEST, "Identity Request"},
+ { TEI_ID_ASSIGNED, "Identity Assigned"},
+ { TEI_ID_DENIED, "Identity Denied"},
+ { TEI_ID_CHECK_REQ, "Identity Check Request"},
+ { TEI_ID_CHECK_RESP, "Identity Check Response"},
+ { TEI_ID_REMOVE, "Identity Remove"},
+ { TEI_ID_VERIFY, "Identity Verify"},
+ { 0, NULL}
+};
+
+static void
+dissect_teimanagement(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *tei_tree = NULL;
+ proto_item *tei_ti;
+ guint8 message;
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TEI");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ tei_ti = proto_tree_add_item(tree, proto_tei, tvb, 0, 5, FALSE);
+ tei_tree = proto_item_add_subtree(tei_ti, lm_subtree);
+
+ proto_tree_add_item(tei_tree, lm_entity_id, tvb, 0, 1, FALSE);
+ proto_tree_add_item(tei_tree, lm_reference, tvb, 1, 2, FALSE);
+ }
+
+ message = tvb_get_guint8(tvb, 3);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO,
+ val_to_str(message, tei_msg_vals, "Unknown message type (0x%04x)"));
+ if (tree) {
+ proto_tree_add_uint(tei_tree, lm_message, tvb, 3, 1, message);
+ proto_tree_add_item(tei_tree, lm_action, tvb, 4, 1, FALSE);
+ proto_tree_add_item(tei_tree, lm_extend, tvb, 4, 1, FALSE);
+ }
+}
+
+void
+proto_register_teimanagement(void)
+{
+ static gint *subtree[]={
+ &lm_subtree
+ };
+
+ static hf_register_info hf[] = {
+ { &lm_entity_id,
+ { "Entity", "tei.entity", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "Layer Management Entity Identifier", HFILL }},
+
+ { &lm_reference,
+ { "Reference", "tei.reference", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Reference Number", HFILL }},
+
+ { &lm_message,
+ { "Msg", "tei.msg", FT_UINT8, BASE_DEC, VALS(tei_msg_vals), 0x0,
+ "Message Type", HFILL }},
+
+ { &lm_action,
+ { "Action", "tei.action", FT_UINT8, BASE_DEC, NULL, 0xfe,
+ "Action Indicator", HFILL }},
+
+ { &lm_extend,
+ { "Extend", "tei.extend", FT_UINT8, BASE_DEC, NULL, 0x01,
+ "Extension Indicator", HFILL }}
+ };
+
+ proto_tei = proto_register_protocol("TEI Management Procedure, Channel D (LAPD)",
+ "TEI_MANAGEMENT", "tei_management");
+ proto_register_field_array (proto_tei, hf, array_length(hf));
+ proto_register_subtree_array(subtree, array_length(subtree));
+}
+
+void
+proto_reg_handoff_teimanagement(void)
+{
+ dissector_handle_t teimanagement_handle;
+
+ teimanagement_handle = create_dissector_handle(dissect_teimanagement,
+ proto_tei);
+ dissector_add("lapd.sapi", LAPD_SAPI_L2, teimanagement_handle);
+}
diff --git a/epan/dissectors/packet-telnet.c b/epan/dissectors/packet-telnet.c
new file mode 100644
index 0000000000..2f76364754
--- /dev/null
+++ b/epan/dissectors/packet-telnet.c
@@ -0,0 +1,1601 @@
+/* packet-telnet.c
+ * Routines for Telnet packet dissection; see RFC 854 and RFC 855
+ * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/* Telnet authentication options as per RFC2941
+ * Kerberos v5 telnet authentication as per RFC2942
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "packet-kerberos.h"
+
+static int proto_telnet = -1;
+static int hf_telnet_auth_cmd = -1;
+static int hf_telnet_auth_name = -1;
+static int hf_telnet_auth_type = -1;
+static int hf_telnet_auth_mod_who = -1;
+static int hf_telnet_auth_mod_how = -1;
+static int hf_telnet_auth_mod_cred_fwd = -1;
+static int hf_telnet_auth_mod_enc = -1;
+static int hf_telnet_auth_krb5_type = -1;
+
+static gint ett_telnet = -1;
+static gint ett_telnet_subopt = -1;
+static gint ett_status_subopt = -1;
+static gint ett_rcte_subopt = -1;
+static gint ett_olw_subopt = -1;
+static gint ett_ops_subopt = -1;
+static gint ett_crdisp_subopt = -1;
+static gint ett_htstops_subopt = -1;
+static gint ett_htdisp_subopt = -1;
+static gint ett_ffdisp_subopt = -1;
+static gint ett_vtstops_subopt = -1;
+static gint ett_vtdisp_subopt = -1;
+static gint ett_lfdisp_subopt = -1;
+static gint ett_extasc_subopt = -1;
+static gint ett_bytemacro_subopt = -1;
+static gint ett_det_subopt = -1;
+static gint ett_supdupout_subopt = -1;
+static gint ett_sendloc_subopt = -1;
+static gint ett_termtype_subopt = -1;
+static gint ett_tacacsui_subopt = -1;
+static gint ett_outmark_subopt = -1;
+static gint ett_tlocnum_subopt = -1;
+static gint ett_tn3270reg_subopt = -1;
+static gint ett_x3pad_subopt = -1;
+static gint ett_naws_subopt = -1;
+static gint ett_tspeed_subopt = -1;
+static gint ett_rfc_subopt = -1;
+static gint ett_linemode_subopt = -1;
+static gint ett_xdpyloc_subopt = -1;
+static gint ett_env_subopt = -1;
+static gint ett_auth_subopt = -1;
+static gint ett_enc_subopt = -1;
+static gint ett_newenv_subopt = -1;
+static gint ett_tn3270e_subopt = -1;
+static gint ett_xauth_subopt = -1;
+static gint ett_charset_subopt = -1;
+static gint ett_rsp_subopt = -1;
+static gint ett_comport_subopt = -1;
+
+
+/* Some defines for Telnet */
+
+#define TCP_PORT_TELNET 23
+
+#define TN_IAC 255
+#define TN_DONT 254
+#define TN_DO 253
+#define TN_WONT 252
+#define TN_WILL 251
+#define TN_SB 250
+#define TN_GA 249
+#define TN_EL 248
+#define TN_EC 247
+#define TN_AYT 246
+#define TN_AO 245
+#define TN_IP 244
+#define TN_BRK 243
+#define TN_DM 242
+#define TN_NOP 241
+#define TN_SE 240
+#define TN_EOR 239
+#define TN_ABORT 238
+#define TN_SUSP 237
+#define TN_EOF 236
+
+
+typedef enum {
+ NO_LENGTH, /* option has no data, hence no length */
+ FIXED_LENGTH, /* option always has the same length */
+ VARIABLE_LENGTH /* option is variable-length - optlen is minimum */
+} tn_opt_len_type;
+
+/* Member of table of IP or TCP options. */
+typedef struct tn_opt {
+ char *name; /* name of option */
+ gint *subtree_index; /* pointer to subtree index for option */
+ tn_opt_len_type len_type; /* type of option length field */
+ int optlen; /* value length should be (minimum if VARIABLE) */
+ void (*dissect)(packet_info *pinfo, const char *, tvbuff_t *, int, int, proto_tree *);
+ /* routine to dissect option */
+} tn_opt;
+
+static void
+dissect_string_subopt(packet_info *pinfo _U_, const char *optname, tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 cmd;
+
+ cmd = tvb_get_guint8(tvb, offset);
+ switch (cmd) {
+
+ case 0: /* IS */
+ proto_tree_add_text(tree, tvb, offset, 1, "Here's my %s", optname);
+ offset++;
+ len--;
+ if (len > 0) {
+ proto_tree_add_text(tree, tvb, offset, len, "Value: %s",
+ tvb_format_text(tvb, offset, len));
+ }
+ break;
+
+ case 1: /* SEND */
+ proto_tree_add_text(tree, tvb, offset, 1, "Send your %s", optname);
+ offset++;
+ len--;
+ if (len > 0)
+ proto_tree_add_text(tree, tvb, offset, len, "Extra data");
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Invalid %s subcommand %u",
+ optname, cmd);
+ offset++;
+ len--;
+ if (len > 0)
+ proto_tree_add_text(tree, tvb, offset, len, "Subcommand data");
+ break;
+ }
+}
+
+static void
+dissect_outmark_subopt(packet_info *pinfo _U_, const char *optname _U_, tvbuff_t *tvb, int offset,
+ int len, proto_tree *tree)
+{
+ guint8 cmd;
+ int gs_offset, datalen;
+
+ while (len > 0) {
+ cmd = tvb_get_guint8(tvb, offset);
+ switch (cmd) {
+
+ case 6: /* ACK */
+ proto_tree_add_text(tree, tvb, offset, 1, "ACK");
+ break;
+
+ case 21: /* NAK */
+ proto_tree_add_text(tree, tvb, offset, 1, "NAK");
+ break;
+
+ case 'D':
+ proto_tree_add_text(tree, tvb, offset, 1, "Default");
+ break;
+
+ case 'T':
+ proto_tree_add_text(tree, tvb, offset, 1, "Top");
+ break;
+
+ case 'B':
+ proto_tree_add_text(tree, tvb, offset, 1, "Bottom");
+ break;
+
+ case 'L':
+ proto_tree_add_text(tree, tvb, offset, 1, "Left");
+ break;
+
+ case 'R':
+ proto_tree_add_text(tree, tvb, offset, 1, "Right");
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Bogus value: %u", cmd);
+ break;
+ }
+ offset++;
+ len--;
+
+ /* Look for a GS */
+ gs_offset = tvb_find_guint8(tvb, offset, len, 29);
+ if (gs_offset == -1) {
+ /* None found - run to the end of the packet. */
+ gs_offset = offset + len;
+ }
+ datalen = gs_offset - offset;
+ if (datalen > 0) {
+ proto_tree_add_text(tree, tvb, offset, datalen, "Banner: %s",
+ tvb_format_text(tvb, offset, datalen));
+ offset += datalen;
+ len -= datalen;
+ }
+ }
+}
+
+static void
+dissect_htstops_subopt(packet_info *pinfo _U_, const char *optname, tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{
+ guint8 cmd;
+ guint8 tabval;
+
+ cmd = tvb_get_guint8(tvb, offset);
+ switch (cmd) {
+
+ case 0: /* IS */
+ proto_tree_add_text(tree, tvb, offset, 1, "Here's my %s", optname);
+ offset++;
+ len--;
+ break;
+
+ case 1: /* SEND */
+ proto_tree_add_text(tree, tvb, offset, 1, "Send your %s", optname);
+ offset++;
+ len--;
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Invalid %s subcommand %u",
+ optname, cmd);
+ offset++;
+ len--;
+ if (len > 0)
+ proto_tree_add_text(tree, tvb, offset, len, "Subcommand data");
+ return;
+ }
+
+ while (len > 0) {
+ tabval = tvb_get_guint8(tvb, offset);
+ switch (tabval) {
+
+ case 0:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Sender wants to handle tab stops");
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Sender wants receiver to handle tab stop at %u",
+ tabval);
+ break;
+
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Invalid value: %u", tabval);
+ break;
+
+ case 255:
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "Sender wants receiver to handle tab stops");
+ break;
+ }
+ offset++;
+ len--;
+ }
+}
+
+static void
+dissect_naws_subopt(packet_info *pinfo _U_, const char *optname _U_, tvbuff_t *tvb, int offset,
+ int len _U_, proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, 2, "Width: %u",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ proto_tree_add_text(tree, tvb, offset, 2, "Height: %u",
+ tvb_get_ntohs(tvb, offset));
+}
+
+/* BEGIN RFC-2217 (COM Port Control) Definitions */
+
+#define TNCOMPORT_SIGNATURE 0
+#define TNCOMPORT_SETBAUDRATE 1
+#define TNCOMPORT_SETDATASIZE 2
+#define TNCOMPORT_SETPARITY 3
+#define TNCOMPORT_SETSTOPSIZE 4
+#define TNCOMPORT_SETCONTROL 5
+#define TNCOMPORT_NOTIFYLINESTATE 6
+#define TNCOMPORT_NOTIFYMODEMSTATE 7
+#define TNCOMPORT_FLOWCONTROLSUSPEND 8
+#define TNCOMPORT_FLOWCONTROLRESUME 9
+#define TNCOMPORT_SETLINESTATEMASK 10
+#define TNCOMPORT_SETMODEMSTATEMASK 11
+#define TNCOMPORT_PURGEDATA 12
+
+/* END RFC-2217 (COM Port Control) Definitions */
+
+static void
+dissect_comport_subopt(packet_info *pinfo _U_, const char *optname, tvbuff_t *tvb, int offset, int len,
+ proto_tree *tree)
+{static const char *datasizes[] = {
+ "Request",
+ "<invalid>",
+ "<invalid>",
+ "<invalid>",
+ "<invalid>",
+ "5",
+ "6",
+ "7",
+ "8"
+ };
+ static const char *parities[] = {
+ "Request",
+ "None",
+ "Odd",
+ "Even",
+ "Mark",
+ "Space"
+ };
+ static const char *stops[] = {
+ "Request",
+ "1",
+ "2",
+ "1.5"
+ };
+ static const char *control[] = {
+ "Output Flow Control Request",
+ "Output Flow: None",
+ "Output Flow: XON/XOFF",
+ "Output Flow: CTS/RTS",
+ "Break Request",
+ "Break: ON",
+ "Break: OFF",
+ "DTR Request",
+ "DTR: ON",
+ "DTR: OFF",
+ "RTS Request",
+ "RTS: ON",
+ "RTS: OFF",
+ "Input Flow Control Request",
+ "Input Flow: None",
+ "Input Flow: XON/XOFF",
+ "Input Flow: CTS/RTS",
+ "Output Flow: DCD",
+ "Input Flow: DTR",
+ "Output Flow: DSR"
+ };
+ static const char *linestate_bits[] = {
+ "Data Ready",
+ "Overrun Error",
+ "Parity Error",
+ "Framing Error",
+ "Break Detected",
+ "Transfer Holding Register Empty",
+ "Transfer Shift Register Empty",
+ "Timeout Error"
+ };
+ static const char *modemstate_bits[] = {
+ "DCTS",
+ "DDSR",
+ "TERI",
+ "DDCD",
+ "CTS",
+ "DSR",
+ "RI",
+ "DCD"
+ };
+ static const char *purges[] = {
+ "Purge None",
+ "Purge RX",
+ "Purge TX",
+ "Purge RX/TX"
+ };
+
+ guint8 cmd;
+ guint8 isservercmd;
+ char *source;
+
+ cmd = tvb_get_guint8(tvb, offset);
+ isservercmd = cmd > 99;
+ cmd = (isservercmd) ? (cmd - 100) : cmd;
+ source = (isservercmd) ? "Server" : "Client";
+ switch (cmd) {
+
+ case TNCOMPORT_SIGNATURE:
+ len--;
+ if (len == 0) {
+ proto_tree_add_text(tree, tvb, offset, 1, "%s Requests Signature",source);
+ } else {
+ guint8 *sig = tvb_get_string(tvb, offset + 1, len);
+ proto_tree_add_text(tree, tvb, offset, 1 + len, "%s Signature: %s",source, sig);
+ g_free(sig);
+ }
+ break;
+
+ case TNCOMPORT_SETBAUDRATE:
+ len--;
+ if (len >= 4) {
+ guint32 baud = tvb_get_ntohl(tvb, offset+1);
+ if (baud == 0) {
+ proto_tree_add_text(tree, tvb, offset, 5, "%s Requests Baud Rate",source);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 5, "%s Baud Rate: %d",source,baud);
+ }
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1 + len, "%s <Invalid Baud Rate Packet>",source);
+ }
+ break;
+
+ case TNCOMPORT_SETDATASIZE:
+ len--;
+ if (len >= 1) {
+ guint8 datasize = tvb_get_guint8(tvb, offset+1);
+ const char *ds = (datasize > 8) ? "<invalid>" : datasizes[datasize];
+ proto_tree_add_text(tree, tvb, offset, 2, "%s Data Size: %s",source,ds);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1 + len, "%s <Invalid Data Size Packet>",source);
+ }
+ break;
+
+ case TNCOMPORT_SETPARITY:
+ len--;
+ if (len >= 1) {
+ guint8 parity = tvb_get_guint8(tvb, offset+1);
+ const char *pr = (parity > 5) ? "<invalid>" : parities[parity];
+ proto_tree_add_text(tree, tvb, offset, 2, "%s Parity: %s",source,pr);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1 + len, "%s <Invalid Parity Packet>",source);
+ }
+ break;
+
+ case TNCOMPORT_SETSTOPSIZE:
+ len--;
+ if (len >= 1) {
+ guint8 stop = tvb_get_guint8(tvb, offset+1);
+ const char *st = (stop > 3) ? "<invalid>" : stops[stop];
+ proto_tree_add_text(tree, tvb, offset, 2, "%s Stop: %s",source,st);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1 + len, "%s <Invalid Stop Packet>",source);
+ }
+ break;
+
+ case TNCOMPORT_SETCONTROL:
+ len--;
+ if (len >= 1) {
+ guint8 crt = tvb_get_guint8(tvb, offset+1);
+ const char *c = (crt > 19) ? "Control: <invalid>" : control[crt];
+ proto_tree_add_text(tree, tvb, offset, 2, "%s %s",source,c);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1 + len, "%s <Invalid Control Packet>",source);
+ }
+ break;
+
+ case TNCOMPORT_SETLINESTATEMASK:
+ case TNCOMPORT_NOTIFYLINESTATE:
+ len--;
+ if (len >= 1) {
+ const char *print_pattern = (cmd == TNCOMPORT_SETLINESTATEMASK) ?
+ "%s Set Linestate Mask: %s" : "%s Linestate: %s";
+ char ls_buffer[512];
+ guint8 ls = tvb_get_guint8(tvb, offset+1);
+ int print_count = 0;
+ int idx;
+ ls_buffer[0] = '\0';
+ for (idx = 0; idx < 8; idx++) {
+ int bit = ls & 1;
+ if (bit) {
+ if (print_count != 0) {
+ strcat(ls_buffer,", ");
+ }
+ strcat(ls_buffer,linestate_bits[idx]);
+ print_count++;
+ }
+ ls = ls >> 1;
+ }
+ proto_tree_add_text(tree, tvb, offset, 2, print_pattern, source, ls_buffer);
+ } else {
+ const char *print_pattern = (cmd == TNCOMPORT_SETLINESTATEMASK) ?
+ "%s <Invalid Linestate Mask>" : "%s <Invalid Linestate Packet>";
+ proto_tree_add_text(tree, tvb, offset, 1 + len, print_pattern, source);
+ }
+ break;
+
+ case TNCOMPORT_SETMODEMSTATEMASK:
+ case TNCOMPORT_NOTIFYMODEMSTATE:
+ len--;
+ if (len >= 1) {
+ const char *print_pattern = (cmd == TNCOMPORT_SETMODEMSTATEMASK) ?
+ "%s Set Modemstate Mask: %s" : "%s Modemstate: %s";
+ char ms_buffer[256];
+ guint8 ms = tvb_get_guint8(tvb, offset+1);
+ int print_count = 0;
+ int idx;
+ ms_buffer[0] = '\0';
+ for (idx = 0; idx < 8; idx++) {
+ int bit = ms & 1;
+ if (bit) {
+ if (print_count != 0) {
+ strcat(ms_buffer,", ");
+ }
+ strcat(ms_buffer,modemstate_bits[idx]);
+ print_count++;
+ }
+ ms = ms >> 1;
+ }
+ proto_tree_add_text(tree, tvb, offset, 2, print_pattern, source, ms_buffer);
+ } else {
+ const char *print_pattern = (cmd == TNCOMPORT_SETMODEMSTATEMASK) ?
+ "%s <Invalid Modemstate Mask>" : "%s <Invalid Modemstate Packet>";
+ proto_tree_add_text(tree, tvb, offset, 1 + len, print_pattern, source);
+ }
+ break;
+
+ case TNCOMPORT_FLOWCONTROLSUSPEND:
+ len--;
+ proto_tree_add_text(tree, tvb, offset, 1, "%s Flow Control Suspend",source);
+ break;
+
+ case TNCOMPORT_FLOWCONTROLRESUME:
+ len--;
+ proto_tree_add_text(tree, tvb, offset, 1, "%s Flow Control Resume",source);
+ break;
+
+ case TNCOMPORT_PURGEDATA:
+ len--;
+ if (len >= 1) {
+ guint8 purge = tvb_get_guint8(tvb, offset+1);
+ const char *p = (purge > 3) ? "<Purge invalid>" : purges[purge];
+ proto_tree_add_text(tree, tvb, offset, 2, "%s %s",source,p);
+ } else {
+ proto_tree_add_text(tree, tvb, offset, 1 + len, "%s <Invalid Purge Packet>",source);
+ }
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, 1, "Invalid %s subcommand %u",
+ optname, cmd);
+ offset++;
+ len--;
+ if (len > 0)
+ proto_tree_add_text(tree, tvb, offset, len, "Subcommand data");
+ return;
+ }
+
+}
+
+static const value_string rfc_opt_vals[] = {
+ { 0, "OFF" },
+ { 1, "ON" },
+ { 2, "RESTART-ANY" },
+ { 3, "RESTART-XON" },
+ { 0, NULL }
+};
+
+static void
+dissect_rfc_subopt(packet_info *pinfo _U_, const char *optname _U_, tvbuff_t *tvb, int offset,
+ int len _U_, proto_tree *tree)
+{
+ guint8 cmd;
+
+ cmd = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2, "%s",
+ val_to_str(cmd, rfc_opt_vals, "Unknown (%u)"));
+}
+
+
+#define TN_AC_IS 0
+#define TN_AC_SEND 1
+#define TN_AC_REPLY 2
+#define TN_AC_NAME 3
+static const value_string auth_cmd_vals[] = {
+ { TN_AC_IS, "IS" },
+ { TN_AC_SEND, "SEND" },
+ { TN_AC_REPLY, "REPLY" },
+ { TN_AC_NAME, "NAME" },
+ { 0, NULL }
+};
+
+#define TN_AT_NULL 0
+#define TN_AT_KRB4 1
+#define TN_AT_KRB5 2
+#define TN_AT_SPX 3
+#define TN_AT_MINK 4
+#define TN_AT_SRP 5
+#define TN_AT_RSA 6
+#define TN_AT_SSL 7
+#define TN_AT_LOKI 10
+#define TN_AT_SSA 11
+#define TN_AT_KEA_SJ 12
+#define TN_AT_KEA_SJ_INTEG 13
+#define TN_AT_DSS 14
+#define TN_AT_NTLM 15
+static const value_string auth_type_vals[] = {
+ { TN_AT_NULL, "NULL" },
+ { TN_AT_KRB4, "Kerberos v4" },
+ { TN_AT_KRB5, "Kerberos v5" },
+ { TN_AT_SPX, "SPX" },
+ { TN_AT_MINK, "MINK" },
+ { TN_AT_SRP, "SRP" },
+ { TN_AT_RSA, "RSA" },
+ { TN_AT_SSL, "SSL" },
+ { TN_AT_LOKI, "LOKI" },
+ { TN_AT_SSA, "SSA" },
+ { TN_AT_KEA_SJ, "KEA_SJ" },
+ { TN_AT_KEA_SJ_INTEG, "KEA_SJ_INTEG" },
+ { TN_AT_DSS, "DSS" },
+ { TN_AT_NTLM, "NTLM" },
+ { 0, NULL }
+};
+static const true_false_string auth_mod_cred_fwd = {
+ "Client WILL forward auth creds",
+ "Client will NOT forward auth creds"
+};
+static const true_false_string auth_mod_who = {
+ "Mask server to client",
+ "Mask client to server"
+};
+static const true_false_string auth_mod_how = {
+ "MUTUAL authentication",
+ "One Way authentication"
+};
+#define TN_AM_OFF 0x00
+#define TN_AM_USING_TELOPT 0x01
+#define TN_AM_AFTER_EXCHANGE 0x02
+#define TN_AM_RESERVED 0x04
+static const value_string auth_mod_enc[] = {
+ { TN_AM_OFF, "Off" },
+ { TN_AM_USING_TELOPT, "Telnet Options" },
+ { TN_AM_AFTER_EXCHANGE, "After Exchange" },
+ { TN_AM_RESERVED, "Reserved" },
+ { 0, NULL }
+};
+#define TN_KRB5_TYPE_AUTH 0
+#define TN_KRB5_TYPE_REJECT 1
+#define TN_KRB5_TYPE_ACCEPT 2
+#define TN_KRB5_TYPE_RESPONSE 3
+#define TN_KRB5_TYPE_FORWARD 4
+#define TN_KRB5_TYPE_FORWARD_ACCEPT 5
+#define TN_KRB5_TYPE_FORWARD_REJECT 6
+static const value_string auth_krb5_types[] = {
+ { TN_KRB5_TYPE_AUTH, "Auth" },
+ { TN_KRB5_TYPE_REJECT, "Reject" },
+ { TN_KRB5_TYPE_ACCEPT, "Accept" },
+ { TN_KRB5_TYPE_RESPONSE, "Response" },
+ { TN_KRB5_TYPE_FORWARD, "Forward" },
+ { TN_KRB5_TYPE_FORWARD_ACCEPT, "Forward Accept" },
+ { TN_KRB5_TYPE_FORWARD_REJECT, "Forward Reject" },
+ { 0, NULL }
+};
+static void
+dissect_authentication_type_pair(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint8 type, mod;
+
+ type=tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_telnet_auth_type, tvb, offset, 1, type);
+
+ mod=tvb_get_guint8(tvb, offset+1);
+ proto_tree_add_uint(tree, hf_telnet_auth_mod_enc, tvb, offset+1, 1, mod);
+ proto_tree_add_boolean(tree, hf_telnet_auth_mod_cred_fwd, tvb, offset+1, 1, mod);
+ proto_tree_add_boolean(tree, hf_telnet_auth_mod_how, tvb, offset+1, 1, mod);
+ proto_tree_add_boolean(tree, hf_telnet_auth_mod_who, tvb, offset+1, 1, mod);
+}
+
+/* no kerberos blobs are ever >10kb ? (arbitrary limit) */
+#define MAX_KRB5_BLOB_LEN 10240
+
+static tvbuff_t *
+unescape_and_tvbuffify_telnet_option(packet_info *pinfo, tvbuff_t *tvb, int offset, int len)
+{
+ tvbuff_t *krb5_tvb;
+ guint8 *buf;
+ const guint8 *spos;
+ guint8 *dpos;
+ int skip, l;
+
+ if(len>=MAX_KRB5_BLOB_LEN)
+ return NULL;
+
+ spos=tvb_get_ptr(tvb, offset, len);
+ /* XXX we never g_free() this one. This is done automagically
+ when the parent tvb is destroyed?
+ */
+ buf=g_malloc(len);
+ dpos=buf;
+ skip=0;
+ l=len;
+ while(l>0){
+ if((spos[0]==0xff) && (spos[1]==0xff)){
+ skip++;
+ l-=2;
+ *(dpos++)=0xff;
+ spos+=2;
+ continue;
+ }
+ *(dpos++)=*(spos++);
+ l--;
+ }
+ krb5_tvb = tvb_new_real_data(buf, len-skip, len-skip);
+ tvb_set_child_real_data_tvbuff(tvb, krb5_tvb);
+ add_new_data_source(pinfo, krb5_tvb, "Unpacked Telnet Uption");
+
+ return krb5_tvb;
+}
+
+
+/* as per RFC2942 */
+static void
+dissect_krb5_authentication_data(packet_info *pinfo, tvbuff_t *tvb, int offset, int len, proto_tree *tree, guint8 acmd)
+{
+ tvbuff_t *krb5_tvb;
+ guint8 krb5_cmd;
+
+ dissect_authentication_type_pair(pinfo, tvb, offset, tree);
+ offset+=2;
+ len-=2;
+
+
+ krb5_cmd=tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_telnet_auth_krb5_type, tvb, offset, 1, krb5_cmd);
+ offset++;
+ len--;
+
+
+ /* IAC SB AUTHENTICATION IS <authentication-type-pair> AUTH <Kerberos V5 KRB_AP_REQ message> IAC SE */
+ if((acmd==TN_AC_IS)&&(krb5_cmd==TN_KRB5_TYPE_AUTH)){
+ krb5_tvb=unescape_and_tvbuffify_telnet_option(pinfo, tvb, offset, len);
+ if(krb5_tvb)
+ dissect_kerberos_main(krb5_tvb, pinfo, tree, FALSE, NULL);
+ else
+ proto_tree_add_text(tree, tvb, offset, len, "Kerberos blob (too long to dissect - length %u > %u",
+ len, MAX_KRB5_BLOB_LEN);
+ }
+
+
+
+ /* IAC SB AUTHENTICATION REPLY <authentication-type-pair> ACCEPT IAC SE */
+ /* nothing more to dissect */
+
+
+
+ /* IAC SB AUTHENTICATION REPLY <authentication-type-pair> REJECT <optional reason for rejection> IAC SE*/
+/*qqq*/
+
+
+ /* IAC SB AUTHENTICATION REPLY <authentication-type-pair> RESPONSE <KRB_AP_REP message> IAC SE */
+ if((acmd==TN_AC_REPLY)&&(krb5_cmd==TN_KRB5_TYPE_RESPONSE)){
+ krb5_tvb=unescape_and_tvbuffify_telnet_option(pinfo, tvb, offset, len);
+ dissect_kerberos_main(krb5_tvb, pinfo, tree, FALSE, NULL);
+ }
+
+
+ /* IAC SB AUTHENTICATION <authentication-type-pair> FORWARD <KRB_CRED message> IAC SE */
+ /* XXX unclear what this one looks like */
+
+
+ /* IAC SB AUTHENTICATION <authentication-type-pair> FORWARD_ACCEPT IAC SE */
+ /* nothing more to dissect */
+
+
+
+ /* IAC SB AUTHENTICATION <authentication-type-pair> FORWARD_REJECT */
+ /* nothing more to dissect */
+}
+
+static void
+dissect_authentication_subopt(packet_info *pinfo, const char *optname _U_, tvbuff_t *tvb, int offset, int len, proto_tree *tree)
+{
+ guint8 acmd;
+ char name[256];
+
+/* XXX here we should really split it up in a conversation struct keeping
+ track of what method we actually use and not just assume it is always
+ kerberos v5
+*/
+ acmd=tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_telnet_auth_cmd, tvb, offset, 1, acmd);
+ offset++;
+ len--;
+
+ switch(acmd){
+ case TN_AC_REPLY:
+ case TN_AC_IS:
+ /* XXX here we shouldnt just assume it is krb5 */
+ dissect_krb5_authentication_data(pinfo, tvb, offset, len, tree, acmd);
+ break;
+ case TN_AC_SEND:
+ while(len>0){
+ dissect_authentication_type_pair(pinfo, tvb, offset, tree);
+ offset+=2;
+ len-=2;
+ }
+ break;
+ case TN_AC_NAME:
+ if(len<255){
+ tvb_memcpy(tvb, name, offset, len);
+ name[len]=0;
+ } else {
+ strcpy(name, "<...name too long...>");
+ }
+ proto_tree_add_string(tree, hf_telnet_auth_name, tvb, offset, len, name);
+ break;
+ }
+}
+
+static tn_opt options[] = {
+ {
+ "Binary Transmission", /* RFC 856 */
+ NULL, /* no suboption negotiation */
+ NO_LENGTH,
+ 0,
+ NULL
+ },
+ {
+ "Echo", /* RFC 857 */
+ NULL, /* no suboption negotiation */
+ NO_LENGTH,
+ 0,
+ NULL
+ },
+ {
+ "Reconnection", /* DOD Protocol Handbook */
+ NULL,
+ NO_LENGTH,
+ 0,
+ NULL
+ },
+ {
+ "Suppress Go Ahead", /* RFC 858 */
+ NULL, /* no suboption negotiation */
+ NO_LENGTH,
+ 0,
+ NULL
+ },
+ {
+ "Approx Message Size Negotiation", /* Ethernet spec(!) */
+ NULL,
+ NO_LENGTH,
+ 0,
+ NULL
+ },
+ {
+ "Status", /* RFC 859 */
+ &ett_status_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Timing Mark", /* RFC 860 */
+ NULL, /* no suboption negotiation */
+ NO_LENGTH,
+ 0,
+ NULL
+ },
+ {
+ "Remote Controlled Trans and Echo", /* RFC 726 */
+ &ett_rcte_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Output Line Width", /* DOD Protocol Handbook */
+ &ett_olw_subopt,
+ VARIABLE_LENGTH, /* XXX - fill me in */
+ 0, /* XXX - fill me in */
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Output Page Size", /* DOD Protocol Handbook */
+ &ett_ops_subopt,
+ VARIABLE_LENGTH, /* XXX - fill me in */
+ 0, /* XXX - fill me in */
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Output Carriage-Return Disposition", /* RFC 652 */
+ &ett_crdisp_subopt,
+ FIXED_LENGTH,
+ 2,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Output Horizontal Tab Stops", /* RFC 653 */
+ &ett_htstops_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ dissect_htstops_subopt
+ },
+ {
+ "Output Horizontal Tab Disposition", /* RFC 654 */
+ &ett_htdisp_subopt,
+ FIXED_LENGTH,
+ 2,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Output Formfeed Disposition", /* RFC 655 */
+ &ett_ffdisp_subopt,
+ FIXED_LENGTH,
+ 2,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Output Vertical Tabstops", /* RFC 656 */
+ &ett_vtstops_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Output Vertical Tab Disposition", /* RFC 657 */
+ &ett_vtdisp_subopt,
+ FIXED_LENGTH,
+ 2,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Output Linefeed Disposition", /* RFC 658 */
+ &ett_lfdisp_subopt,
+ FIXED_LENGTH,
+ 2,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Extended ASCII", /* RFC 698 */
+ &ett_extasc_subopt,
+ FIXED_LENGTH,
+ 2,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Logout", /* RFC 727 */
+ NULL, /* no suboption negotiation */
+ NO_LENGTH,
+ 0,
+ NULL
+ },
+ {
+ "Byte Macro", /* RFC 735 */
+ &ett_bytemacro_subopt,
+ VARIABLE_LENGTH,
+ 2,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Data Entry Terminal", /* RFC 732, RFC 1043 */
+ &ett_det_subopt,
+ VARIABLE_LENGTH,
+ 2,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "SUPDUP", /* RFC 734, RFC 736 */
+ NULL, /* no suboption negotiation */
+ NO_LENGTH,
+ 0,
+ NULL
+ },
+ {
+ "SUPDUP Output", /* RFC 749 */
+ &ett_supdupout_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Send Location", /* RFC 779 */
+ &ett_sendloc_subopt,
+ VARIABLE_LENGTH,
+ 0,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Terminal Type", /* RFC 1091 */
+ &ett_termtype_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ dissect_string_subopt
+ },
+ {
+ "End of Record", /* RFC 885 */
+ NULL, /* no suboption negotiation */
+ NO_LENGTH,
+ 0,
+ NULL
+ },
+ {
+ "TACACS User Identification", /* RFC 927 */
+ &ett_tacacsui_subopt,
+ FIXED_LENGTH,
+ 4,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Output Marking", /* RFC 933 */
+ &ett_outmark_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ dissect_outmark_subopt,
+ },
+ {
+ "Terminal Location Number", /* RFC 946 */
+ &ett_tlocnum_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Telnet 3270 Regime", /* RFC 1041 */
+ &ett_tn3270reg_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "X.3 PAD", /* RFC 1053 */
+ &ett_x3pad_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Negotiate About Window Size", /* RFC 1073, DW183 */
+ &ett_naws_subopt,
+ FIXED_LENGTH,
+ 4,
+ dissect_naws_subopt
+ },
+ {
+ "Terminal Speed", /* RFC 1079 */
+ &ett_tspeed_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Remote Flow Control", /* RFC 1372 */
+ &ett_rfc_subopt,
+ FIXED_LENGTH,
+ 1,
+ dissect_rfc_subopt
+ },
+ {
+ "Linemode", /* RFC 1184 */
+ &ett_linemode_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "X Display Location", /* RFC 1096 */
+ &ett_xdpyloc_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ dissect_string_subopt
+ },
+ {
+ "Environment Option", /* RFC 1408, RFC 1571 */
+ &ett_env_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Authentication Option", /* RFC 2941 */
+ &ett_auth_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ dissect_authentication_subopt
+ },
+ {
+ "Encryption Option", /* RFC 2946 */
+ &ett_enc_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "New Environment Option", /* RFC 1572 */
+ &ett_newenv_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "TN3270E", /* RFC 1647 */
+ &ett_tn3270e_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "XAUTH", /* XAUTH */
+ &ett_xauth_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "CHARSET", /* CHARSET */
+ &ett_charset_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "Remote Serial Port", /* Remote Serial Port */
+ &ett_rsp_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ NULL /* XXX - fill me in */
+ },
+ {
+ "COM Port Control", /* RFC 2217 */
+ &ett_comport_subopt,
+ VARIABLE_LENGTH,
+ 1,
+ dissect_comport_subopt
+ },
+
+};
+
+#define NOPTIONS (sizeof options / sizeof options[0])
+
+static int
+telnet_sub_option(packet_info *pinfo, proto_tree *telnet_tree, tvbuff_t *tvb, int start_offset)
+{
+ proto_tree *ti, *option_tree;
+ int offset = start_offset;
+ guint8 opt_byte;
+ int subneg_len;
+ const char *opt;
+ gint ett;
+ int iac_offset;
+ guint len;
+ void (*dissect)(packet_info *, const char *, tvbuff_t *, int, int, proto_tree *);
+ gint cur_offset;
+ gboolean iac_found;
+
+ offset += 2; /* skip IAC and SB */
+
+ /* Get the option code */
+ opt_byte = tvb_get_guint8(tvb, offset);
+ if (opt_byte > NOPTIONS) {
+ opt = "<unknown option>";
+ ett = ett_telnet_subopt;
+ dissect = NULL;
+ } else {
+ opt = options[opt_byte].name;
+ if (options[opt_byte].subtree_index != NULL)
+ ett = *(options[opt_byte].subtree_index);
+ else
+ ett = ett_telnet_subopt;
+ dissect = options[opt_byte].dissect;
+ }
+ offset++;
+
+ /* Search for an unescaped IAC. */
+ cur_offset = offset;
+ iac_found = FALSE;
+ len = tvb_length_remaining(tvb, offset);
+ do {
+ iac_offset = tvb_find_guint8(tvb, cur_offset, len, TN_IAC);
+ iac_found = TRUE;
+ if (iac_offset == -1) {
+ /* None found - run to the end of the packet. */
+ offset += len;
+ } else {
+ if (((guint)(iac_offset + 1) >= len) ||
+ (tvb_get_guint8(tvb, iac_offset + 1) != TN_IAC)) {
+ /* We really found a single IAC, so we're done */
+ offset = iac_offset;
+ } else {
+ /*
+ * We saw an escaped IAC, so we have to move ahead to the
+ * next section
+ */
+ iac_found = FALSE;
+ cur_offset = iac_offset + 2;
+ }
+ }
+
+ } while (!iac_found);
+
+ subneg_len = offset - start_offset;
+
+ ti = proto_tree_add_text(telnet_tree, tvb, start_offset, subneg_len,
+ "Suboption Begin: %s", opt);
+ option_tree = proto_item_add_subtree(ti, ett);
+ start_offset += 3; /* skip IAC, SB, and option code */
+ subneg_len -= 3;
+
+ if (subneg_len > 0) {
+ switch (options[opt_byte].len_type) {
+
+ case NO_LENGTH:
+ /* There isn't supposed to *be* sub-option negotiation for this. */
+ proto_tree_add_text(option_tree, tvb, start_offset, subneg_len,
+ "Bogus suboption data");
+ return offset;
+
+ case FIXED_LENGTH:
+ /* Make sure the length is what it's supposed to be. */
+ if (subneg_len != options[opt_byte].optlen) {
+ proto_tree_add_text(option_tree, tvb, start_offset, subneg_len,
+ "Suboption parameter length is %d, should be %d",
+ subneg_len, options[opt_byte].optlen);
+ return offset;
+ }
+ break;
+
+ case VARIABLE_LENGTH:
+ /* Make sure the length is greater than the minimum. */
+ if (subneg_len < options[opt_byte].optlen) {
+ proto_tree_add_text(option_tree, tvb, start_offset, subneg_len,
+ "Suboption parameter length is %d, should be at least %d",
+ subneg_len, options[opt_byte].optlen);
+ return offset;
+ }
+ break;
+ }
+
+ /* Now dissect the suboption parameters. */
+ if (dissect != NULL) {
+ /* We have a dissector for this suboption's parameters; call it. */
+ (*dissect)(pinfo, opt, tvb, start_offset, subneg_len, option_tree);
+ } else {
+ /* We don't have a dissector for them; just show them as data. */
+ proto_tree_add_text(option_tree, tvb, start_offset, subneg_len,
+ "Option data");
+ }
+ }
+ return offset;
+}
+
+static int
+telnet_will_wont_do_dont(proto_tree *telnet_tree, tvbuff_t *tvb,
+ int start_offset, char *type)
+{
+ int offset = start_offset;
+ guint8 opt_byte;
+ const char *opt;
+
+ offset += 2; /* skip IAC and WILL,WONT,DO,DONT} */
+ opt_byte = tvb_get_guint8(tvb, offset);
+ if (opt_byte > NOPTIONS)
+ opt = "<unknown option>";
+ else
+ opt = options[opt_byte].name;
+ offset++;
+
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 3,
+ "Command: %s %s", type, opt);
+ return offset;
+}
+
+static int
+telnet_command(packet_info *pinfo, proto_tree *telnet_tree, tvbuff_t *tvb, int start_offset)
+{
+ int offset = start_offset;
+ guchar optcode;
+
+ offset += 1; /* skip IAC */
+ optcode = tvb_get_guint8(tvb, offset);
+ offset++;
+ switch(optcode) {
+
+ case TN_EOF:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: End of File");
+ break;
+
+ case TN_SUSP:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Suspend Current Process");
+ break;
+
+ case TN_ABORT:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Abort Process");
+ break;
+
+ case TN_EOR:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: End of Record");
+ break;
+
+ case TN_SE:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Suboption End");
+ break;
+
+ case TN_NOP:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: No Operation");
+ break;
+
+ case TN_DM:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Data Mark");
+ break;
+
+ case TN_BRK:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Break");
+ break;
+
+ case TN_IP:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Interrupt Process");
+ break;
+
+ case TN_AO:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Abort Output");
+ break;
+
+ case TN_AYT:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Are You There?");
+ break;
+
+ case TN_EC:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Escape Character");
+ break;
+
+ case TN_EL:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Erase Line");
+ break;
+
+ case TN_GA:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Go Ahead");
+ break;
+
+ case TN_SB:
+ offset = telnet_sub_option(pinfo, telnet_tree, tvb, start_offset);
+ break;
+
+ case TN_WILL:
+ offset = telnet_will_wont_do_dont(telnet_tree, tvb, start_offset,
+ "Will");
+ break;
+
+ case TN_WONT:
+ offset = telnet_will_wont_do_dont(telnet_tree, tvb, start_offset,
+ "Won't");
+ break;
+
+ case TN_DO:
+ offset = telnet_will_wont_do_dont(telnet_tree, tvb, start_offset,
+ "Do");
+ break;
+
+ case TN_DONT:
+ offset = telnet_will_wont_do_dont(telnet_tree, tvb, start_offset,
+ "Don't");
+ break;
+
+ default:
+ proto_tree_add_text(telnet_tree, tvb, start_offset, 2,
+ "Command: Unknown (0x%02x)", optcode);
+ break;
+ }
+
+ return offset;
+}
+
+static void
+telnet_add_text(proto_tree *tree, tvbuff_t *tvb, int offset, int len)
+{
+ gint next_offset;
+ int linelen;
+ guint8 c;
+ gboolean last_char_was_cr;
+
+ while (len != 0 && tvb_offset_exists(tvb, offset)) {
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset, len, &next_offset, FALSE);
+ len -= next_offset - offset; /* subtract out the line's characters */
+
+ /*
+ * In Telnet, CR NUL is the way you send a CR by itself in the
+ * default ASCII mode; don't treat CR by itself as a line ending,
+ * treat only CR NUL, CR LF, or LF by itself as a line ending.
+ */
+ if (next_offset == offset + linelen + 1 && len >= 1) {
+ /*
+ * Well, we saw a one-character line ending, so either it's a CR
+ * or an LF; we have at least two characters left, including the
+ * CR.
+ *
+ * If the line ending is a CR, skip all subsequent CRs; at
+ * least one capture appeared to have multiple CRs at the end of
+ * a line.
+ */
+ if (tvb_get_guint8(tvb, offset + linelen) == '\r') {
+ last_char_was_cr = TRUE;
+ while (len != 0 && tvb_offset_exists(tvb, next_offset)) {
+ c = tvb_get_guint8(tvb, next_offset);
+ next_offset++; /* skip over that character */
+ len--;
+ if (c == '\n' || (c == '\0' && last_char_was_cr)) {
+ /*
+ * LF is a line ending, whether preceded by CR or not.
+ * NUL is a line ending if preceded by CR.
+ */
+ break;
+ }
+ last_char_was_cr = (c == '\r');
+ }
+ }
+ }
+
+ /*
+ * Now compute the length of the line *including* the end-of-line
+ * indication, if any; we display it all.
+ */
+ linelen = next_offset - offset;
+
+ proto_tree_add_text(tree, tvb, offset, linelen,
+ "Data: %s",
+ tvb_format_text(tvb, offset, linelen));
+ offset = next_offset;
+ }
+}
+
+static void
+dissect_telnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *telnet_tree, *ti;
+
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TELNET");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Telnet Data ...");
+
+ if (tree) {
+ gint offset = 0;
+ guint len;
+ int data_len;
+ gint iac_offset;
+
+ ti = proto_tree_add_item(tree, proto_telnet, tvb, offset, -1, FALSE);
+ telnet_tree = proto_item_add_subtree(ti, ett_telnet);
+
+ /*
+ * Scan through the buffer looking for an IAC byte.
+ */
+ while ((len = tvb_length_remaining(tvb, offset)) > 0) {
+ iac_offset = tvb_find_guint8(tvb, offset, len, TN_IAC);
+ if (iac_offset != -1) {
+ /*
+ * We found an IAC byte.
+ * If there's any data before it, add that data to the
+ * tree, a line at a time.
+ */
+ data_len = iac_offset - offset;
+ if (data_len > 0)
+ telnet_add_text(telnet_tree, tvb, offset, data_len);
+
+ /*
+ * Now interpret the command.
+ */
+ offset = telnet_command(pinfo, telnet_tree, tvb, iac_offset);
+ }
+ else {
+ /*
+ * We found no IAC byte, so what remains in the buffer
+ * is the last of the data in the packet.
+ * Add it to the tree, a line at a time, and then quit.
+ */
+ telnet_add_text(telnet_tree, tvb, offset, len);
+ break;
+ }
+ }
+ }
+}
+
+void
+proto_register_telnet(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_telnet_auth_name,
+ { "Name", "telnet.auth.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Name of user being authenticated", HFILL }},
+ { &hf_telnet_auth_cmd,
+ { "Auth Cmd", "telnet.auth.cmd", FT_UINT8, BASE_DEC,
+ VALS(auth_cmd_vals), 0, "Authentication Command", HFILL }},
+ { &hf_telnet_auth_type,
+ { "Auth Type", "telnet.auth.type", FT_UINT8, BASE_DEC,
+ VALS(auth_type_vals), 0, "Authentication Type", HFILL }},
+ { &hf_telnet_auth_mod_cred_fwd,
+ { "Cred Fwd", "telnet.auth.mod.cred_fwd", FT_BOOLEAN, 8,
+ TFS(&auth_mod_cred_fwd), 0x08, "Modifier: Whether client will forward creds or not", HFILL }},
+ { &hf_telnet_auth_mod_who,
+ { "Who", "telnet.auth.mod.who", FT_BOOLEAN, 8,
+ TFS(&auth_mod_who), 0x01, "Modifier: Who to mask", HFILL }},
+ { &hf_telnet_auth_mod_how,
+ { "How", "telnet.auth.mod.how", FT_BOOLEAN, 8,
+ TFS(&auth_mod_how), 0x02, "Modifier: How to mask", HFILL }},
+ { &hf_telnet_auth_mod_enc,
+ { "Encrypt", "telnet.auth.mod.enc", FT_UINT8, BASE_DEC,
+ VALS(auth_mod_enc), 0x14, "Modifier: How to enable Encryption", HFILL }},
+ { &hf_telnet_auth_krb5_type,
+ { "Command", "telnet.auth.krb5.cmd", FT_UINT8, BASE_DEC,
+ VALS(auth_krb5_types), 0, "Krb5 Authentication sub-command", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_telnet,
+ &ett_telnet_subopt,
+ &ett_status_subopt,
+ &ett_rcte_subopt,
+ &ett_olw_subopt,
+ &ett_ops_subopt,
+ &ett_crdisp_subopt,
+ &ett_htstops_subopt,
+ &ett_htdisp_subopt,
+ &ett_ffdisp_subopt,
+ &ett_vtstops_subopt,
+ &ett_vtdisp_subopt,
+ &ett_lfdisp_subopt,
+ &ett_extasc_subopt,
+ &ett_bytemacro_subopt,
+ &ett_det_subopt,
+ &ett_supdupout_subopt,
+ &ett_sendloc_subopt,
+ &ett_termtype_subopt,
+ &ett_tacacsui_subopt,
+ &ett_outmark_subopt,
+ &ett_tlocnum_subopt,
+ &ett_tn3270reg_subopt,
+ &ett_x3pad_subopt,
+ &ett_naws_subopt,
+ &ett_tspeed_subopt,
+ &ett_rfc_subopt,
+ &ett_linemode_subopt,
+ &ett_xdpyloc_subopt,
+ &ett_env_subopt,
+ &ett_auth_subopt,
+ &ett_enc_subopt,
+ &ett_newenv_subopt,
+ &ett_tn3270e_subopt,
+ &ett_xauth_subopt,
+ &ett_charset_subopt,
+ &ett_rsp_subopt,
+ &ett_comport_subopt,
+ };
+
+ proto_telnet = proto_register_protocol("Telnet", "TELNET", "telnet");
+ proto_register_field_array(proto_telnet, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_telnet(void)
+{
+ dissector_handle_t telnet_handle;
+
+ telnet_handle = create_dissector_handle(dissect_telnet, proto_telnet);
+ dissector_add("tcp.port", TCP_PORT_TELNET, telnet_handle);
+}
diff --git a/epan/dissectors/packet-teredo.c b/epan/dissectors/packet-teredo.c
new file mode 100644
index 0000000000..f591997a69
--- /dev/null
+++ b/epan/dissectors/packet-teredo.c
@@ -0,0 +1,267 @@
+/* packet-teredo.c v.1.0
+ * Routines for TEREDO packet disassembly
+ * draft-huitema-v6ops-teredo-00.txt
+ * Windows XP Teredo
+ *
+ * Copyright 2003, Ragi BEJJANI - 6WIND - <ragi.bejjani@6wind.com>
+ * Copyright 2003, Vincent JARDIN - 6WIND - <vincent.jardin@6wind.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "ipproto.h"
+#include "prefs.h"
+
+#include "packet-ip.h"
+#include "tap.h"
+
+#define UDP_PORT_TERREDO 3544
+
+static int teredo_tap = -1;
+
+static int proto_teredo = -1;
+static int hf_teredo_orgheader = -1;
+static int hf_teredo_authheader = -1;
+static int hf_teredo_orgport = -1;
+static int hf_teredo_orgaddr = -1;
+
+static gint ett_teredo = -1;
+
+typedef struct {
+ guint16 th_indtyp;
+ guint8 th_cidlen;
+ guint8 th_authdlen;
+ guint8 th_nonce[8];
+ guint8 th_conf;
+
+ guint8 th_ip_v_hl;
+ guint16 th_header;
+ guint16 th_orgport;
+ guint32 th_iporgaddr;
+} e_teredohdr;
+
+/* Place TEREDO summary in proto tree */
+static gboolean teredo_summary_in_tree = TRUE;
+
+static dissector_table_t teredo_dissector_table;
+/*static heur_dissector_list_t heur_subdissector_list;*/
+static dissector_handle_t data_handle;
+
+/* Determine if there is a sub-dissector and call it. This has been */
+/* separated into a stand alone routine to other protocol dissectors */
+/* can call to it, ie. socks */
+
+
+static void
+decode_teredo_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,proto_tree *tree, int th_header)
+{
+ tvbuff_t *next_tvb;
+
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+
+ if (dissector_try_port(teredo_dissector_table, th_header, next_tvb, pinfo, tree))
+ return;
+
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+}
+
+static void
+dissect_teredo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *teredo_tree;
+ proto_item *ti;
+ int offset = 0;
+ static e_teredohdr teredohstruct[4], *teredoh;
+ static int teredoh_count = 0;
+
+ proto_item *to;
+ proto_tree *teredo_origin_tree;
+
+ teredoh_count++;
+ if(teredoh_count>=4){
+ teredoh_count=0;
+ }
+ teredoh = &teredohstruct[teredoh_count];
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TEREDO");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ teredoh->th_header = tvb_get_ntohs(tvb, offset);
+ teredoh->th_ip_v_hl = tvb_get_guint8(tvb, offset);
+ teredoh->th_indtyp = 0;
+
+ if ( (teredoh->th_header)== 1 ) {
+ teredoh->th_indtyp = teredoh->th_header;
+ teredoh->th_cidlen = tvb_get_guint8(tvb,offset+2); /*Authentication header octet*/
+ teredoh->th_authdlen = tvb_get_guint8(tvb,offset+3);
+ tvb_memcpy(tvb,teredoh->th_nonce,offset+4,sizeof teredoh->th_nonce);
+ teredoh->th_conf = tvb_get_guint8(tvb,offset+12);
+
+ /*Skip over Authentication Header (fixed length-no authentication)*/
+ offset+=13;
+ teredoh->th_header = tvb_get_ntohs(tvb, offset);
+ teredoh->th_ip_v_hl = tvb_get_guint8(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO,
+ "Teredo : Tunneling IPv6 over UDP through NATs");
+
+ proto_tree_add_uint_hidden(tree, hf_teredo_authheader, tvb, offset-13, 2, teredoh->th_indtyp);
+
+ if (teredo_summary_in_tree) {
+
+ if (teredoh->th_header!=0) {
+ ti = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset-13, 13,
+ "TEREDO with Authentication encapsulation");
+ }
+
+ } else {
+ ti = proto_tree_add_item(tree, proto_teredo, tvb, offset, 13, FALSE);
+ }
+ }
+
+ if ( (teredoh->th_header)== 0 ) {
+ teredoh->th_orgport=tvb_get_ntohs(tvb, offset+2);
+ tvb_memcpy(tvb, (guint8 *)&teredoh->th_iporgaddr, offset + 4, 4);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO,
+ "Teredo : Tunneling IPv6 over UDP through NATs");
+
+ if (tree) {
+ if (teredo_summary_in_tree) {
+ if (teredoh->th_indtyp==1){
+ to = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset-13, 13+8,
+ "TEREDO with Authentication and Origin Indicator encapsulation");
+ teredo_tree = proto_item_add_subtree(to, ett_teredo);
+ proto_tree_add_protocol_format(teredo_tree,proto_teredo, tvb,offset-13, 13,
+ "Authentication encapsulation");
+ ti = proto_tree_add_protocol_format(teredo_tree, proto_teredo, tvb, offset, 8,
+ "Origin indicator encapsulation") ;
+ } else {
+ ti = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset, 8,
+ "TEREDO with Origin indicator encapsulation");
+ }
+ } else {
+ ti = proto_tree_add_item(tree, proto_teredo, tvb, offset, 8, FALSE);
+ }
+
+ teredo_origin_tree = proto_item_add_subtree(ti, ett_teredo);
+
+ proto_tree_add_uint_format(teredo_origin_tree, hf_teredo_orgheader, tvb, offset, 2,
+ teredoh->th_header,
+ "Teredo Origin encapsulation header: 0x%04x",
+ (teredoh->th_header));
+ proto_tree_add_uint_format(teredo_origin_tree, hf_teredo_orgport, tvb, offset + 2, 2,
+ teredoh->th_orgport,
+ "Origin port: %u",
+ ((teredoh->th_orgport)^(0xFFFF)));
+ proto_tree_add_ipv4_format(teredo_origin_tree, hf_teredo_orgaddr, tvb, offset + 4, 4,
+ teredoh->th_iporgaddr,
+ "Origin address: %s",
+ get_hostname((teredoh->th_iporgaddr)^(0xFFFFFFFF)));
+
+ proto_tree_add_uint_hidden(teredo_origin_tree, hf_teredo_orgheader, tvb, offset, 2,
+ teredoh->th_header);
+ proto_tree_add_uint_hidden(teredo_origin_tree, hf_teredo_orgport, tvb, offset+2, 2,
+ ((teredoh->th_orgport)^(0xFFFF)));
+ proto_tree_add_ipv4_hidden(teredo_origin_tree, hf_teredo_orgaddr, tvb, offset + 4, 4,
+ ((teredoh->th_iporgaddr)^(0xFFFFFFFF)));
+ };
+
+ offset+=8; /*Skip over Origin Header*/
+ };
+
+ if ( (hi_nibble(teredoh->th_ip_v_hl) == 6)
+ && ((teredoh->th_indtyp) != 1) ) { /* checking if the first 4 bits = 6 */
+
+ if (tree) {
+ if (teredo_summary_in_tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset, 0,"TEREDO simple encapsulation ");
+ }
+ }
+
+ offset+=0;
+ }
+
+ decode_teredo_ports(tvb, offset, pinfo, tree, teredoh->th_header /* , teredoh->th_orgport*/);
+ tap_queue_packet(teredo_tap, pinfo, teredoh);
+}
+
+void
+proto_register_teredo(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_teredo_authheader,
+ { "Teredo Authentication packet Header","teredo.authheader", FT_UINT16, BASE_DEC, NULL, 0x0,"", HFILL }},
+
+ { &hf_teredo_orgheader,
+ { "Teredo Origin encapsulation header","teredo.orgheader", FT_UINT16, BASE_DEC, NULL, 0x0,"", HFILL }},
+
+ { &hf_teredo_orgport,
+ { "Origin Port", "teredo.orgport", FT_UINT16, BASE_DEC, NULL, 0x0,"", HFILL }},
+
+ { &hf_teredo_orgaddr,
+ { "Origin IPv4 address","teredo.orgaddr", FT_IPv4, BASE_NONE, NULL, 0x0,"", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_teredo,
+ };
+
+ proto_teredo = proto_register_protocol("TEREDO Tunneling IPv6 over UDP through NATs",
+ "TEREDO", "teredo");
+ proto_register_field_array(proto_teredo, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+/* subdissector code */
+ teredo_dissector_table = register_dissector_table("teredo","TEREDO ", FT_UINT16, BASE_DEC);
+/* register_heur_dissector_list("teredo.heur", &heur_subdissector_list); */
+
+}
+
+void
+proto_reg_handoff_teredo(void)
+{
+ dissector_handle_t teredo_handle;
+
+ teredo_handle = create_dissector_handle(dissect_teredo, proto_teredo);
+ data_handle = find_dissector("ipv6");
+ teredo_tap = register_tap("teredo");
+
+ dissector_add("udp.port", UDP_PORT_TERREDO, teredo_handle);
+}
+
diff --git a/epan/dissectors/packet-text-media.c b/epan/dissectors/packet-text-media.c
new file mode 100644
index 0000000000..7e4d9516bf
--- /dev/null
+++ b/epan/dissectors/packet-text-media.c
@@ -0,0 +1,164 @@
+/* packet-text-media.c
+ * Routines for text-based media dissection.
+ *
+ * NOTE - The media type is either found in pinfo->match_string
+ * or in pinfo->private_data.
+ *
+ * (C) Olivier Biot, 2004.
+ *
+ * $Id$
+ *
+ * Refer to the AUTHORS file or the AUTHORS section in the man page
+ * for contacting the author(s) of this file.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Edit this file with 4-space tabs */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+
+
+/*
+ * Media dissector for line-based text media like text/plain, message/http.
+ *
+ * TODO - character set and chunked transfer-coding
+ */
+
+/* Filterable header fields */
+static gint proto_text_lines = -1;
+
+/* Subtrees */
+static gint ett_text_lines = -1;
+
+/* Dissector handles */
+static dissector_handle_t text_lines_handle;
+
+static void
+dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *subtree;
+ proto_item *ti;
+ gint offset = 0, next_offset;
+ gint len;
+ const char *data_name;
+
+ data_name = pinfo->match_string;
+ if (! (data_name && data_name[0])) {
+ /*
+ * No information from "match_string"
+ */
+ data_name = (char *)(pinfo->private_data);
+ if (! (data_name && data_name[0])) {
+ /*
+ * No information from "private_data"
+ */
+ data_name = NULL;
+ }
+ }
+
+ if (data_name && check_col(pinfo->cinfo, COL_INFO))
+ col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)",
+ data_name);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_text_lines,
+ tvb, 0, -1, FALSE);
+ if (data_name)
+ proto_item_append_text(ti, ": %s", data_name);
+ subtree = proto_item_add_subtree(ti, ett_text_lines);
+ /* Read the media line by line */
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * XXX - we need to be passed the parameters
+ * of the content type via "pinfo->private_data",
+ * so that we know the character set. We'd
+ * have to handle that character set, which
+ * might be a multibyte character set such
+ * as "iso-10646-ucs-2", or might require other
+ * special processing.
+ */
+ len = tvb_find_line_end(tvb, offset,
+ tvb_ensure_length_remaining(tvb, offset),
+ &next_offset, FALSE);
+ if (len == -1)
+ break;
+ proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
+ "%s", tvb_format_text(tvb, offset, len));
+ offset = next_offset;
+ }
+ }
+}
+
+void
+proto_register_text_lines(void)
+{
+ static gint *ett[] = {
+ &ett_text_lines,
+ };
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+ proto_text_lines = proto_register_protocol(
+ "Line-based text data", /* Long name */
+ "Line-based text data", /* Short name */
+ "data-text-lines"); /* Filter name */
+ register_dissector("data-text-lines", dissect_text_lines, proto_text_lines);
+}
+
+void
+proto_reg_handoff_text_lines(void)
+{
+ text_lines_handle = create_dissector_handle(
+ dissect_text_lines, proto_text_lines);
+
+ dissector_add_string("media_type", "text/plain", text_lines_handle);
+ /* W3C line-based textual media */
+ dissector_add_string("media_type", "text/html", text_lines_handle);
+ dissector_add_string("media_type", "text/xml", text_lines_handle);
+ dissector_add_string("media_type", "text/xml-external-parsed-entity", text_lines_handle);
+ dissector_add_string("media_type", "text/css", text_lines_handle);
+ dissector_add_string("media_type", "application/xml", text_lines_handle);
+ dissector_add_string("media_type", "application/xml-external-parsed-entity", text_lines_handle);
+ dissector_add_string("media_type", "application/xml-dtd", text_lines_handle);
+ dissector_add_string("media_type", "application/x-javascript", text_lines_handle);
+ dissector_add_string("media_type", "application/x-www-form-urlencoded", text_lines_handle);
+ dissector_add_string("media_type", "application/x-ns-proxy-autoconfig", text_lines_handle);
+ /* WAP and OMA line-based textual media */
+ dissector_add_string("media_type", "text/vnd.wap.wml", text_lines_handle);
+ dissector_add_string("media_type", "text/vnd.wap.si", text_lines_handle);
+ dissector_add_string("media_type", "text/vnd.wap.sl", text_lines_handle);
+ dissector_add_string("media_type", "text/vnd.wap.co", text_lines_handle);
+ dissector_add_string("media_type", "text/vnd.wap.emn", text_lines_handle);
+ dissector_add_string("media_type", "application/vnd.wv.csp+xml", text_lines_handle);
+ /* Other */
+ dissector_add_string("media_type", "text/vnd.sun.j2me.app-descriptor", text_lines_handle);
+ dissector_add_string("media_type", "application/smil", text_lines_handle);
+ dissector_add_string("media_type", "application/vnd.poc.refer-to", text_lines_handle);
+ dissector_add_string("media_type", "application/cpim-pidf+xml", text_lines_handle);
+}
diff --git a/epan/dissectors/packet-tftp.c b/epan/dissectors/packet-tftp.c
new file mode 100644
index 0000000000..879619b72f
--- /dev/null
+++ b/epan/dissectors/packet-tftp.c
@@ -0,0 +1,352 @@
+/* packet-tftp.c
+ * Routines for tftp packet dissection
+ *
+ * Richard Sharpe <rsharpe@ns.aus.com>
+ * Craig Newell <CraigN@cheque.uq.edu.au>
+ * RFC2347 TFTP Option Extension
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-bootp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+static int proto_tftp = -1;
+static int hf_tftp_opcode = -1;
+static int hf_tftp_source_file = -1;
+static int hf_tftp_destination_file = -1;
+static int hf_tftp_transfer_type = -1;
+static int hf_tftp_blocknum = -1;
+static int hf_tftp_error_code = -1;
+static int hf_tftp_error_string = -1;
+
+static gint ett_tftp = -1;
+
+static dissector_handle_t tftp_handle;
+
+#define UDP_PORT_TFTP 69
+
+#define TFTP_RRQ 1
+#define TFTP_WRQ 2
+#define TFTP_DATA 3
+#define TFTP_ACK 4
+#define TFTP_ERROR 5
+#define TFTP_OACK 6
+
+static const value_string tftp_opcode_vals[] = {
+ { TFTP_RRQ, "Read Request" },
+ { TFTP_WRQ, "Write Request" },
+ { TFTP_DATA, "Data Packet" },
+ { TFTP_ACK, "Acknowledgement" },
+ { TFTP_ERROR, "Error Code" },
+ { TFTP_OACK, "Option Acknowledgement" },
+ { 0, NULL }
+};
+
+static const value_string tftp_error_code_vals[] = {
+ { 0, "Not defined" },
+ { 1, "File not found" },
+ { 2, "Access violation" },
+ { 3, "Disk full or allocation exceeded" },
+ { 4, "Illegal TFTP Operation" },
+ { 5, "Unknown transfer ID" },
+ { 6, "File already exists" },
+ { 7, "No such user" },
+ { 8, "Option negotiation failed" },
+ { 0, NULL }
+};
+
+static void tftp_dissect_options(tvbuff_t *tvb, int offset, proto_tree *tree);
+
+static void
+dissect_tftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *tftp_tree = NULL;
+ proto_item *ti;
+ conversation_t *conversation;
+ gint offset = 0;
+ guint16 opcode;
+ guint16 bytes;
+ guint16 blocknum;
+ guint i1;
+ guint16 error;
+
+ /*
+ * The first TFTP packet goes to the TFTP port; the second one
+ * comes from some *other* port, but goes back to the same
+ * IP address and port as the ones from which the first packet
+ * came; all subsequent packets go between those two IP addresses
+ * and ports.
+ *
+ * If this packet went to the TFTP port, we check to see if
+ * there's already a conversation with one address/port pair
+ * matching the source IP address and port of this packet,
+ * the other address matching the destination IP address of this
+ * packet, and any destination port.
+ *
+ * If not, we create one, with its address 1/port 1 pair being
+ * the source address/port of this packet, its address 2 being
+ * the destination address of this packet, and its port 2 being
+ * wildcarded, and give it the TFTP dissector as a dissector.
+ */
+ if (pinfo->destport == UDP_PORT_TFTP) {
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, PT_UDP,
+ pinfo->srcport, 0, NO_PORT_B);
+ if (conversation == NULL) {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, PT_UDP,
+ pinfo->srcport, 0, NO_PORT2);
+ conversation_set_dissector(conversation, tftp_handle);
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFTP");
+
+ opcode = tvb_get_ntohs(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(opcode, tftp_opcode_vals, "Unknown (0x%04x)"));
+
+ }
+
+ if (tree) {
+
+ ti = proto_tree_add_item(tree, proto_tftp, tvb, offset, -1, FALSE);
+ tftp_tree = proto_item_add_subtree(ti, ett_tftp);
+
+ proto_tree_add_uint(tftp_tree, hf_tftp_opcode, tvb,
+ offset, 2, opcode);
+ }
+ offset += 2;
+
+ switch (opcode) {
+
+ case TFTP_RRQ:
+ i1 = tvb_strsize(tvb, offset);
+ if (tree) {
+ proto_tree_add_item(tftp_tree, hf_tftp_source_file,
+ tvb, offset, i1, FALSE);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
+ tvb_get_ptr(tvb, offset, i1));
+ }
+ offset += i1;
+
+ i1 = tvb_strsize(tvb, offset);
+ if (tree) {
+ ti = proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
+ tvb, offset, i1, FALSE);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
+ tvb_get_ptr(tvb, offset, i1));
+ }
+ offset += i1;
+
+ if (tree)
+ tftp_dissect_options(tvb, offset, tftp_tree);
+ break;
+
+ case TFTP_WRQ:
+ i1 = tvb_strsize(tvb, offset);
+ if (tree) {
+ proto_tree_add_item(tftp_tree, hf_tftp_destination_file,
+ tvb, offset, i1, FALSE);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
+ tvb_get_ptr(tvb, offset, i1));
+ }
+ offset += i1;
+
+ i1 = tvb_strsize(tvb, offset);
+ if (tree) {
+ ti = proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
+ tvb, offset, i1, FALSE);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
+ tvb_get_ptr(tvb, offset, i1));
+ }
+ offset += i1;
+
+ if (tree)
+ tftp_dissect_options(tvb, offset, tftp_tree);
+ break;
+
+ case TFTP_DATA:
+ blocknum = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
+ blocknum);
+ }
+ offset += 2;
+
+ bytes = tvb_reported_length_remaining(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i%s",
+ blocknum,
+ (bytes < 512)?" (last)":"" );
+ }
+
+ if (bytes != 0) {
+ if (tree) {
+ proto_tree_add_text(tftp_tree, tvb, offset, -1,
+ "Data (%d bytes)", bytes);
+ }
+ }
+ break;
+
+ case TFTP_ACK:
+ blocknum = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
+ blocknum);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i",
+ blocknum);
+ }
+ break;
+
+ case TFTP_ERROR:
+ error = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tftp_tree, hf_tftp_error_code, tvb, offset, 2,
+ error);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Code: %s",
+ val_to_str(error, tftp_error_code_vals, "Unknown (%u)"));
+ }
+ offset += 2;
+
+ i1 = tvb_strsize(tvb, offset);
+ if (tree) {
+ proto_tree_add_item(tftp_tree, hf_tftp_error_string, tvb, offset,
+ i1, FALSE);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Message: %s",
+ tvb_get_ptr(tvb, offset, i1));
+ }
+ break;
+
+ case TFTP_OACK:
+ if (tree)
+ tftp_dissect_options(tvb, offset, tftp_tree);
+ break;
+
+ default:
+ if (tree) {
+ proto_tree_add_text(tftp_tree, tvb, offset, -1,
+ "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
+ }
+ break;
+
+ }
+}
+
+static void
+tftp_dissect_options(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ int option_len, value_len;
+ int value_offset;
+
+ while (tvb_offset_exists(tvb, offset)) {
+ option_len = tvb_strsize(tvb, offset); /* length of option */
+ value_offset = offset + option_len;
+ value_len = tvb_strsize(tvb, value_offset); /* length of value */
+ proto_tree_add_text(tree, tvb, offset, option_len+value_len,
+ "Option: %s = %s",
+ tvb_get_ptr(tvb, offset, option_len),
+ tvb_get_ptr(tvb, value_offset, value_len));
+ offset += option_len + value_len;
+ }
+}
+
+void
+proto_register_tftp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tftp_opcode,
+ { "Opcode", "tftp.opcode",
+ FT_UINT16, BASE_DEC, VALS(tftp_opcode_vals), 0x0,
+ "TFTP message type", HFILL }},
+
+ { &hf_tftp_source_file,
+ { "Source File", "tftp.source_file",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "TFTP source file name", HFILL }},
+
+ { &hf_tftp_destination_file,
+ { "DESTINATION File", "tftp.destination_file",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "TFTP source file name", HFILL }},
+
+ { &hf_tftp_transfer_type,
+ { "Type", "tftp.type",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "TFTP transfer type", HFILL }},
+
+ { &hf_tftp_blocknum,
+ { "Block", "tftp.block",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Block number", HFILL }},
+
+ { &hf_tftp_error_code,
+ { "Error code", "tftp.error.code",
+ FT_UINT16, BASE_DEC, VALS(tftp_error_code_vals), 0x0,
+ "Error code in case of TFTP error message", HFILL }},
+
+ { &hf_tftp_error_string,
+ { "Error message", "tftp.error.message",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "Error string in case of TFTP error message", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_tftp,
+ };
+
+ proto_tftp = proto_register_protocol("Trivial File Transfer Protocol",
+ "TFTP", "tftp");
+ proto_register_field_array(proto_tftp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ tftp_handle = create_dissector_handle(dissect_tftp, proto_tftp);
+}
+
+void
+proto_reg_handoff_tftp(void)
+{
+ dissector_add("udp.port", UDP_PORT_TFTP, tftp_handle);
+}
diff --git a/epan/dissectors/packet-time.c b/epan/dissectors/packet-time.c
new file mode 100644
index 0000000000..73c115d13d
--- /dev/null
+++ b/epan/dissectors/packet-time.c
@@ -0,0 +1,99 @@
+/* packet-time.c
+ * Routines for Time Protocol (RFC 868) packet dissection
+ *
+ * Richard Sharpe <rsharpe@ns.aus.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+
+static int proto_time = -1;
+static int hf_time_time = -1;
+
+static gint ett_time = -1;
+
+#define UDP_PORT_TIME 37
+
+static void
+dissect_time(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *time_tree;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TIME");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "TIME %s",
+ pinfo->srcport == pinfo->match_port ? "Response":"Request");
+ }
+
+ if (tree) {
+
+ ti = proto_tree_add_item(tree, proto_time, tvb, 0, -1, FALSE);
+ time_tree = proto_item_add_subtree(ti, ett_time);
+
+ proto_tree_add_text(time_tree, tvb, 0, 0,
+ pinfo->srcport==UDP_PORT_TIME? "Type: Response":"Type: Request");
+ if (pinfo->srcport == UDP_PORT_TIME) {
+ /* seconds since 1900-01-01 00:00:00 GMT, *not* 1970 */
+ guint32 delta_seconds = tvb_get_ntohl(tvb, 0);
+ proto_tree_add_uint_format(time_tree, hf_time_time, tvb, 0, 4,
+ delta_seconds, "%s",
+ abs_time_secs_to_str(delta_seconds-(guint32)(70*365+18)*24*3600));
+ }
+ }
+}
+
+void
+proto_register_time(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_time_time,
+ { "Time", "time.time",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Seconds since 00:00 (midnight) 1 January 1900 GMT", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_time,
+ };
+
+ proto_time = proto_register_protocol("Time Protocol", "TIME", "time");
+ proto_register_field_array(proto_time, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_time(void)
+{
+ dissector_handle_t time_handle;
+
+ time_handle = create_dissector_handle(dissect_time, proto_time);
+ dissector_add("udp.port", UDP_PORT_TIME, time_handle);
+}
diff --git a/epan/dissectors/packet-tns.c b/epan/dissectors/packet-tns.c
new file mode 100644
index 0000000000..f3e0d50ed7
--- /dev/null
+++ b/epan/dissectors/packet-tns.c
@@ -0,0 +1,1341 @@
+/* packet-tns.c
+ * Routines for Oracle TNS packet dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-tcp.h"
+#include "packet-tns.h"
+
+#include "prefs.h"
+
+/* desegmentation of TNS over TCP */
+static gboolean tns_desegment = TRUE;
+
+static int proto_tns = -1;
+static int hf_tns_request = -1;
+static int hf_tns_response = -1;
+static int hf_tns_length = -1;
+static int hf_tns_packet_checksum = -1;
+static int hf_tns_header_checksum = -1;
+static int hf_tns_packet_type = -1;
+static int hf_tns_reserved_byte = -1;
+static int hf_tns_connect = -1;
+static int hf_tns_version = -1;
+static int hf_tns_compat_version = -1;
+
+static int hf_tns_service_options = -1;
+static int hf_tns_sopt_flag_bconn = -1;
+static int hf_tns_sopt_flag_pc = -1;
+static int hf_tns_sopt_flag_hc = -1;
+static int hf_tns_sopt_flag_fd = -1;
+static int hf_tns_sopt_flag_hd = -1;
+static int hf_tns_sopt_flag_dc1 = -1;
+static int hf_tns_sopt_flag_dc2 = -1;
+static int hf_tns_sopt_flag_dio = -1;
+static int hf_tns_sopt_flag_ap = -1;
+static int hf_tns_sopt_flag_ra = -1;
+static int hf_tns_sopt_flag_sa = -1;
+
+static int hf_tns_sdu_size = -1;
+static int hf_tns_max_tdu_size = -1;
+
+static int hf_tns_nt_proto_characteristics = -1;
+static int hf_tns_ntp_flag_hangon = -1;
+static int hf_tns_ntp_flag_crel = -1;
+static int hf_tns_ntp_flag_tduio = -1;
+static int hf_tns_ntp_flag_srun = -1;
+static int hf_tns_ntp_flag_dtest = -1;
+static int hf_tns_ntp_flag_cbio = -1;
+static int hf_tns_ntp_flag_asio = -1;
+static int hf_tns_ntp_flag_pio = -1;
+static int hf_tns_ntp_flag_grant = -1;
+static int hf_tns_ntp_flag_handoff = -1;
+static int hf_tns_ntp_flag_sigio = -1;
+static int hf_tns_ntp_flag_sigpipe = -1;
+static int hf_tns_ntp_flag_sigurg = -1;
+static int hf_tns_ntp_flag_urgentio = -1;
+static int hf_tns_ntp_flag_fdio = -1;
+static int hf_tns_ntp_flag_testop = -1;
+
+static int hf_tns_line_turnaround = -1;
+static int hf_tns_value_of_one = -1;
+static int hf_tns_connect_data_length = -1;
+static int hf_tns_connect_data_offset = -1;
+static int hf_tns_connect_data_max = -1;
+
+static int hf_tns_connect_flags0 = -1;
+static int hf_tns_connect_flags1 = -1;
+static int hf_tns_conn_flag_nareq = -1;
+static int hf_tns_conn_flag_nalink = -1;
+static int hf_tns_conn_flag_enablena = -1;
+static int hf_tns_conn_flag_ichg = -1;
+static int hf_tns_conn_flag_wantna = -1;
+
+static int hf_tns_connect_data = -1;
+static int hf_tns_trace_cf1 = -1;
+static int hf_tns_trace_cf2 = -1;
+static int hf_tns_trace_cid = -1;
+
+static int hf_tns_accept = -1;
+static int hf_tns_accept_data_length = -1;
+static int hf_tns_accept_data_offset = -1;
+static int hf_tns_accept_data = -1;
+
+static int hf_tns_refuse = -1;
+static int hf_tns_refuse_reason_user = -1;
+static int hf_tns_refuse_reason_system = -1;
+static int hf_tns_refuse_data_length = -1;
+static int hf_tns_refuse_data = -1;
+
+static int hf_tns_abort = -1;
+static int hf_tns_abort_reason_user = -1;
+static int hf_tns_abort_reason_system = -1;
+static int hf_tns_abort_data = -1;
+
+static int hf_tns_marker = -1;
+static int hf_tns_marker_type = -1;
+static int hf_tns_marker_data_byte = -1;
+static int hf_tns_marker_data = -1;
+
+static int hf_tns_redirect = -1;
+static int hf_tns_redirect_data_length = -1;
+static int hf_tns_redirect_data = -1;
+
+static int hf_tns_control = -1;
+static int hf_tns_control_cmd = -1;
+static int hf_tns_control_data = -1;
+
+static int hf_tns_data_flag = -1;
+static int hf_tns_data_flag_send = -1;
+static int hf_tns_data_flag_rc = -1;
+static int hf_tns_data_flag_c = -1;
+static int hf_tns_data_flag_reserved = -1;
+static int hf_tns_data_flag_more = -1;
+static int hf_tns_data_flag_eof = -1;
+static int hf_tns_data_flag_dic = -1;
+static int hf_tns_data_flag_rts = -1;
+static int hf_tns_data_flag_sntt = -1;
+static int hf_tns_data = -1;
+
+static gint ett_tns = -1;
+static gint ett_tns_connect = -1;
+static gint ett_tns_accept = -1;
+static gint ett_tns_refuse = -1;
+static gint ett_tns_abort = -1;
+static gint ett_tns_redirect = -1;
+static gint ett_tns_marker = -1;
+static gint ett_tns_attention = -1;
+static gint ett_tns_control = -1;
+static gint ett_tns_data = -1;
+static gint ett_tns_data_flag = -1;
+static gint ett_tns_sopt_flag = -1;
+static gint ett_tns_ntp_flag = -1;
+static gint ett_tns_conn_flag = -1;
+static gint ett_sql = -1;
+
+static dissector_handle_t data_handle;
+
+#define TCP_PORT_TNS 1521
+
+static const value_string tns_type_vals[] = {
+ {TNS_TYPE_CONNECT, "Connect" },
+ {TNS_TYPE_ACCEPT, "Accept" },
+ {TNS_TYPE_ACK, "Acknowledge" },
+ {TNS_TYPE_REFUSE, "Refuse" },
+ {TNS_TYPE_REDIRECT, "Redirect" },
+ {TNS_TYPE_DATA, "Data" },
+ {TNS_TYPE_NULL, "Null" },
+ {TNS_TYPE_ABORT, "Abort" },
+ {TNS_TYPE_RESEND, "Resend"},
+ {TNS_TYPE_MARKER, "Marker"},
+ {TNS_TYPE_ATTENTION, "Attention"},
+ {TNS_TYPE_CONTROL, "Control"},
+ {0, NULL}
+};
+
+static const value_string tns_marker_types[] = {
+ {0, "Data Marker - 0 Data Bytes"},
+ {1, "Data Marker - 1 Data Bytes"},
+ {2, "Attention Marker"},
+ {0, NULL}
+};
+
+static const value_string tns_control_cmds[] = {
+ {1, "Oracle Trace Command"},
+ {0, NULL}
+};
+
+void proto_reg_handoff_tns(void);
+static guint get_tns_pdu_len(tvbuff_t *tvb, int offset);
+static void dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static void dissect_tns_service_options(tvbuff_t *tvb, int offset,
+ proto_tree *sopt_tree)
+{
+
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_bconn, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_pc, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_hc, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_fd, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_hd, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_dc1, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_dc2, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_dio, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_ap, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_ra, tvb,
+ offset, 2, FALSE);
+ proto_tree_add_item(sopt_tree, hf_tns_sopt_flag_sa, tvb,
+ offset, 2, FALSE);
+
+}
+
+static void dissect_tns_connect_flag(tvbuff_t *tvb, int offset,
+ proto_tree *cflag_tree)
+{
+
+ proto_tree_add_item(cflag_tree, hf_tns_conn_flag_nareq, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cflag_tree, hf_tns_conn_flag_nalink, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cflag_tree, hf_tns_conn_flag_enablena, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cflag_tree, hf_tns_conn_flag_ichg, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cflag_tree, hf_tns_conn_flag_wantna, tvb, offset, 1, FALSE);
+}
+
+static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tns_tree)
+{
+ proto_tree *data_tree = NULL, *ti;
+ int is_sns = 0;
+
+ if ( tvb_bytes_exist(tvb, offset+2, 4) )
+ {
+ if ( tvb_get_guint8(tvb, offset+2) == 0xDE &&
+ tvb_get_guint8(tvb, offset+3) == 0xAD &&
+ tvb_get_guint8(tvb, offset+4) == 0xBE &&
+ tvb_get_guint8(tvb, offset+5) == 0xEF )
+ {
+ is_sns = 1;
+ }
+ }
+
+ if ( tree )
+ {
+ if ( is_sns )
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Secure Network Services");
+ }
+ else
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Data");
+ }
+ data_tree = proto_item_add_subtree(ti, ett_tns_data);
+
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_data, tvb, 0, 0,
+ TRUE);
+ }
+
+ if ( tree )
+ {
+ proto_tree *df_tree = NULL;
+
+ ti = proto_tree_add_item(data_tree, hf_tns_data_flag, tvb, offset, 2, FALSE);
+
+ df_tree = proto_item_add_subtree(ti, ett_tns_data_flag);
+ proto_tree_add_item(df_tree, hf_tns_data_flag_send, tvb, offset, 2, FALSE);
+ proto_tree_add_item(df_tree, hf_tns_data_flag_rc, tvb, offset, 2, FALSE);
+ proto_tree_add_item(df_tree, hf_tns_data_flag_c, tvb, offset, 2, FALSE);
+ proto_tree_add_item(df_tree, hf_tns_data_flag_reserved, tvb, offset, 2, FALSE);
+ proto_tree_add_item(df_tree, hf_tns_data_flag_more, tvb, offset, 2, FALSE);
+ proto_tree_add_item(df_tree, hf_tns_data_flag_eof, tvb, offset, 2, FALSE);
+ proto_tree_add_item(df_tree, hf_tns_data_flag_dic, tvb, offset, 2, FALSE);
+ proto_tree_add_item(df_tree, hf_tns_data_flag_rts, tvb, offset, 2, FALSE);
+ proto_tree_add_item(df_tree, hf_tns_data_flag_sntt, tvb, offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ if ( is_sns )
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", SNS");
+ }
+ else
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Data");
+ }
+ }
+
+ if ( data_tree )
+ {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo, data_tree);
+ }
+
+ return;
+}
+
+static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tns_tree)
+{
+ proto_tree *connect_tree = NULL, *ti;
+ int cd_offset;
+ int cd_len;
+ int tns_offset = offset-8;
+
+ if ( tree )
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Connect");
+ connect_tree = proto_item_add_subtree(ti, ett_tns_connect);
+
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_connect, tvb,
+ 0, 0, TRUE);
+ }
+
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Connect");
+ }
+
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_version, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_compat_version, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( connect_tree )
+ {
+ proto_tree *sopt_tree = NULL;
+
+ ti = proto_tree_add_item(connect_tree, hf_tns_service_options, tvb,
+ offset, 2, FALSE);
+
+ sopt_tree = proto_item_add_subtree(ti, ett_tns_sopt_flag);
+
+ dissect_tns_service_options(tvb, offset, sopt_tree);
+
+
+ }
+ offset += 2;
+
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_sdu_size, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_max_tdu_size, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( connect_tree )
+ {
+ proto_tree *ntp_tree = NULL;
+
+ ti = proto_tree_add_item(connect_tree, hf_tns_nt_proto_characteristics, tvb,
+ offset, 2, FALSE);
+
+ ntp_tree = proto_item_add_subtree(ti, ett_tns_ntp_flag);
+
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_hangon, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_crel, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_tduio, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_srun, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_dtest, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_cbio, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_asio, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_pio, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_grant, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_handoff, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigio, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigpipe, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigurg, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_urgentio, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_fdio, tvb, offset, 2, FALSE);
+ proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_testop, tvb, offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_line_turnaround, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_value_of_one, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ cd_len = tvb_get_ntohs(tvb, offset);
+ if ( connect_tree )
+ {
+ proto_tree_add_uint(connect_tree, hf_tns_connect_data_length, tvb,
+ offset, 2, cd_len);
+ }
+ offset += 2;
+
+ cd_offset = tvb_get_ntohs(tvb, offset);
+ if ( connect_tree )
+ {
+ proto_tree_add_uint(connect_tree, hf_tns_connect_data_offset, tvb,
+ offset, 2, cd_offset);
+ }
+ offset += 2;
+
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_connect_data_max, tvb,
+ offset, 4, FALSE);
+ }
+ offset += 4;
+
+ if ( connect_tree )
+ {
+ proto_tree *cflag_tree = NULL;
+
+ ti = proto_tree_add_item(connect_tree, hf_tns_connect_flags0, tvb,
+ offset, 1, FALSE);
+
+ cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag);
+
+ dissect_tns_connect_flag(tvb, offset, cflag_tree);
+ }
+ offset += 1;
+
+ if ( connect_tree )
+ {
+ proto_tree *cflag_tree = NULL;
+
+ ti = proto_tree_add_item(connect_tree, hf_tns_connect_flags1, tvb,
+ offset, 1, FALSE);
+
+ cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag);
+
+ dissect_tns_connect_flag(tvb, offset, cflag_tree);
+ }
+ offset += 1;
+
+ /*
+ * XXX - sometimes it appears that this stuff isn't present
+ * in the packet.
+ */
+ if (offset + 16 <= tns_offset+cd_offset)
+ {
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_trace_cf1, tvb,
+ offset, 4, FALSE);
+ }
+ offset += 4;
+
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_trace_cf2, tvb,
+ offset, 4, FALSE);
+ }
+ offset += 4;
+
+ if ( connect_tree )
+ {
+ proto_tree_add_item(connect_tree, hf_tns_trace_cid, tvb,
+ offset, 8, FALSE);
+ }
+ offset += 8;
+ }
+
+ if ( connect_tree && cd_len > 0)
+ {
+ proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb,
+ tns_offset+cd_offset, -1, FALSE);
+ }
+ return;
+}
+
+static void dissect_tns_accept(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tns_tree)
+{
+ proto_tree *accept_tree = NULL, *ti;
+ int accept_offset;
+ int accept_len;
+ int tns_offset = offset-8;
+
+ if ( tree )
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Accept");
+ accept_tree = proto_item_add_subtree(ti, ett_tns_accept);
+
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_accept, tvb,
+ 0, 0, TRUE);
+ }
+
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Accept");
+ }
+
+ if ( accept_tree )
+ {
+ proto_tree_add_item(accept_tree, hf_tns_version, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( accept_tree )
+ {
+ proto_tree *sopt_tree = NULL;
+
+ ti = proto_tree_add_item(accept_tree, hf_tns_service_options,
+ tvb, offset, 2, FALSE);
+
+ sopt_tree = proto_item_add_subtree(ti, ett_tns_sopt_flag);
+
+ dissect_tns_service_options(tvb, offset, sopt_tree);
+
+ }
+ offset += 2;
+
+ if ( accept_tree )
+ {
+ proto_tree_add_item(accept_tree, hf_tns_sdu_size, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( accept_tree )
+ {
+ proto_tree_add_item(accept_tree, hf_tns_max_tdu_size, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( accept_tree )
+ {
+ proto_tree_add_item(accept_tree, hf_tns_value_of_one, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ accept_len = tvb_get_ntohs(tvb, offset);
+ if ( accept_tree )
+ {
+ proto_tree_add_uint(accept_tree, hf_tns_accept_data_length, tvb,
+ offset, 2, accept_len);
+ }
+ offset += 2;
+
+ accept_offset = tvb_get_ntohs(tvb, offset);
+ if ( accept_tree )
+ {
+ proto_tree_add_uint(accept_tree, hf_tns_accept_data_offset, tvb,
+ offset, 2, accept_offset);
+ }
+ offset += 2;
+
+ if ( accept_tree )
+ {
+ proto_tree *cflag_tree = NULL;
+
+ ti = proto_tree_add_item(accept_tree, hf_tns_connect_flags0, tvb,
+ offset, 1, FALSE);
+
+ cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag);
+
+ dissect_tns_connect_flag(tvb, offset, cflag_tree);
+
+ }
+ offset += 1;
+
+ if ( accept_tree )
+ {
+ proto_tree *cflag_tree = NULL;
+
+ ti = proto_tree_add_item(accept_tree, hf_tns_connect_flags1, tvb,
+ offset, 1, FALSE);
+
+ cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag);
+
+ dissect_tns_connect_flag(tvb, offset, cflag_tree);
+
+ }
+ offset += 1;
+
+ if ( accept_tree && accept_len > 0)
+ {
+ proto_tree_add_item(accept_tree, hf_tns_accept_data, tvb,
+ tns_offset+accept_offset, -1, FALSE);
+ }
+ return;
+}
+
+
+static void dissect_tns_refuse(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tns_tree)
+{
+ proto_tree *refuse_tree = NULL, *ti;
+
+ if ( tree )
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Refuse");
+ refuse_tree = proto_item_add_subtree(ti, ett_tns_refuse);
+
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_refuse, tvb,
+ 0, 0, TRUE);
+ }
+
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Refuse");
+ }
+
+ if ( refuse_tree )
+ {
+ proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_user, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ if ( refuse_tree )
+ {
+ proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_system, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ if ( refuse_tree )
+ {
+ proto_tree_add_item(refuse_tree, hf_tns_refuse_data_length, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( refuse_tree )
+ {
+ proto_tree_add_item(refuse_tree, hf_tns_refuse_data, tvb,
+ offset, -1, FALSE);
+ }
+ return;
+}
+
+
+static void dissect_tns_abort(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tns_tree)
+{
+ proto_tree *abort_tree = NULL, *ti;
+
+ if ( tree )
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Abort");
+ abort_tree = proto_item_add_subtree(ti, ett_tns_abort);
+
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_abort, tvb,
+ 0, 0, TRUE);
+ }
+
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Abort");
+ }
+
+ if ( abort_tree )
+ {
+ proto_tree_add_item(abort_tree, hf_tns_abort_reason_user, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ if ( abort_tree )
+ {
+ proto_tree_add_item(abort_tree, hf_tns_abort_reason_system, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ if ( abort_tree )
+ {
+ proto_tree_add_item(abort_tree, hf_tns_abort_data, tvb,
+ offset, -1, FALSE);
+ }
+ return;
+}
+
+
+static void dissect_tns_marker(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tns_tree, int is_attention)
+{
+ proto_tree *marker_tree = NULL, *ti;
+
+ if ( tree )
+ {
+ if ( is_attention )
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Marker");
+ }
+ else
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Attention");
+ }
+
+ marker_tree = proto_item_add_subtree(ti, ett_tns_marker);
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_marker, tvb,
+ 0, 0, TRUE);
+ }
+
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ if ( is_attention )
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Marker");
+ }
+ else
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Attention");
+ }
+ }
+
+ if ( marker_tree )
+ {
+ proto_tree_add_item(marker_tree, hf_tns_marker_type, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ if ( marker_tree )
+ {
+ proto_tree_add_item(marker_tree, hf_tns_marker_data_byte, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ if ( marker_tree )
+ {
+ proto_tree_add_item(marker_tree, hf_tns_marker_data_byte, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ return;
+}
+
+static void dissect_tns_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tns_tree)
+{
+ proto_tree *redirect_tree = NULL, *ti;
+
+ if ( tree )
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Redirect");
+ redirect_tree = proto_item_add_subtree(ti, ett_tns_redirect);
+
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_redirect, tvb,
+ 0, 0, TRUE);
+ }
+
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Redirect");
+ }
+
+ if ( redirect_tree )
+ {
+ proto_tree_add_item(redirect_tree, hf_tns_redirect_data_length, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( redirect_tree )
+ {
+ proto_tree_add_item(redirect_tree, hf_tns_redirect_data, tvb,
+ offset, -1, FALSE);
+ }
+ return;
+}
+
+static void dissect_tns_control(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, proto_tree *tns_tree)
+{
+ proto_tree *control_tree = NULL, *ti;
+
+ if ( tree )
+ {
+ ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
+ "Control");
+ control_tree = proto_item_add_subtree(ti, ett_tns_control);
+
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_control, tvb,
+ 0, 0, TRUE);
+ }
+
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Control");
+ }
+
+ if ( control_tree )
+ {
+ proto_tree_add_item(control_tree, hf_tns_control_cmd, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ if ( control_tree )
+ {
+ proto_tree_add_item(control_tree, hf_tns_control_data, tvb,
+ offset, -1, FALSE);
+ }
+ return;
+}
+
+static guint
+get_tns_pdu_len(tvbuff_t *tvb, int offset)
+{
+ /*
+ * Get the length of the TNS message, including header
+ */
+ return tvb_get_ntohs(tvb, offset);
+}
+
+static int
+dissect_tns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 type;
+
+ /*
+ * First, do a sanity check to make sure what we have
+ * starts with a TNS PDU.
+ */
+ if (tvb_bytes_exist(tvb, 4, 1)) {
+ /*
+ * Well, we have the packet type; let's make sure
+ * it's a known type.
+ */
+ type = tvb_get_guint8(tvb, 4);
+ if (type < TNS_TYPE_CONNECT || type > TNS_TYPE_MAX)
+ return 0; /* it's not a known type */
+ }
+
+ tcp_dissect_pdus(tvb, pinfo, tree, tns_desegment, 2,
+ get_tns_pdu_len, dissect_tns_pdu);
+ return tvb_length(tvb);
+}
+
+static void
+dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *tns_tree = NULL, *ti;
+ int offset = 0;
+ guint16 length;
+ guint16 type;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TNS");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ (pinfo->match_port == pinfo->destport) ? "Request" : "Response");
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_tns, tvb, 0, -1, FALSE);
+ tns_tree = proto_item_add_subtree(ti, ett_tns);
+
+ if (pinfo->match_port == pinfo->destport)
+ {
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_request,
+ tvb, offset, 0, TRUE);
+ }
+ else
+ {
+ proto_tree_add_boolean_hidden(tns_tree, hf_tns_response,
+ tvb, offset, 0, TRUE);
+ }
+ }
+
+ length = tvb_get_ntohs(tvb, offset);
+ if (tree)
+ {
+ proto_tree_add_uint(tns_tree, hf_tns_length, tvb,
+ offset, 2, length);
+ }
+ offset += 2;
+
+ if ( tree )
+ {
+ proto_tree_add_item(tns_tree, hf_tns_packet_checksum, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ type = tvb_get_guint8(tvb, offset);
+ if ( tree )
+ {
+ proto_tree_add_uint(tns_tree, hf_tns_packet_type, tvb,
+ offset, 1, type);
+ }
+ offset += 1;
+
+ if ( check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s (%u)",
+ val_to_str(type, tns_type_vals, "Unknown"), type);
+ }
+
+ if ( tree )
+ {
+ proto_tree_add_item(tns_tree, hf_tns_reserved_byte, tvb,
+ offset, 1, FALSE);
+ }
+ offset += 1;
+
+ if ( tree )
+ {
+ proto_tree_add_item(tns_tree, hf_tns_header_checksum, tvb,
+ offset, 2, FALSE);
+ }
+ offset += 2;
+
+ switch (type)
+ {
+ case TNS_TYPE_CONNECT:
+ dissect_tns_connect(tvb,offset,pinfo,tree,tns_tree);
+ break;
+ case TNS_TYPE_ACCEPT:
+ dissect_tns_accept(tvb,offset,pinfo,tree,tns_tree);
+ break;
+ case TNS_TYPE_REFUSE:
+ dissect_tns_refuse(tvb,offset,pinfo,tree,tns_tree);
+ break;
+ case TNS_TYPE_REDIRECT:
+ dissect_tns_redirect(tvb,offset,pinfo,tree,tns_tree);
+ break;
+ case TNS_TYPE_ABORT:
+ dissect_tns_abort(tvb,offset,pinfo,tree,tns_tree);
+ break;
+ case TNS_TYPE_MARKER:
+ dissect_tns_marker(tvb,offset,pinfo,tree,tns_tree, 0);
+ break;
+ case TNS_TYPE_ATTENTION:
+ dissect_tns_marker(tvb,offset,pinfo,tree,tns_tree, 1);
+ break;
+ case TNS_TYPE_CONTROL:
+ dissect_tns_control(tvb,offset,pinfo,tree,tns_tree);
+ break;
+ case TNS_TYPE_DATA:
+ dissect_tns_data(tvb,offset,pinfo,tree,tns_tree);
+ break;
+ default:
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, offset, -1, -1), pinfo,
+ tns_tree);
+ break;
+ }
+}
+
+void proto_register_tns(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tns_response, {
+ "Response", "tns.response", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "TRUE if TNS response", HFILL }},
+ { &hf_tns_request, {
+ "Request", "tns.request", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "TRUE if TNS request", HFILL }},
+ { &hf_tns_length, {
+ "Packet Length", "tns.length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of TNS packet", HFILL }},
+ { &hf_tns_packet_checksum, {
+ "Packet Checksum", "tns.packet_checksum", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Checksum of Packet Data", HFILL }},
+ { &hf_tns_header_checksum, {
+ "Header Checksum", "tns.header_checksum", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Checksum of Header Data", HFILL }},
+
+ { &hf_tns_version, {
+ "Version", "tns.version", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Version", HFILL }},
+ { &hf_tns_compat_version, {
+ "Version (Compatible)", "tns.compat_version", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Version (Compatible)", HFILL }},
+
+ { &hf_tns_service_options, {
+ "Service Options", "tns.service_options", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Service Options", HFILL }},
+
+ { &hf_tns_sopt_flag_bconn, {
+ "Broken Connect Notify", "tns.so_flag.bconn", FT_BOOLEAN, 16,
+ NULL, 0x2000, "Broken Connect Notify", HFILL }},
+ { &hf_tns_sopt_flag_pc, {
+ "Packet Checksum", "tns.so_flag.pc", FT_BOOLEAN, 16,
+ NULL, 0x1000, "Packet Checksum", HFILL }},
+ { &hf_tns_sopt_flag_hc, {
+ "Header Checksum", "tns.so_flag.hc", FT_BOOLEAN, 16,
+ NULL, 0x0800, "Header Checksum", HFILL }},
+ { &hf_tns_sopt_flag_fd, {
+ "Full Duplex", "tns.so_flag.fd", FT_BOOLEAN, 16,
+ NULL, 0x0400, "Full Duplex", HFILL }},
+ { &hf_tns_sopt_flag_hd, {
+ "Half Duplex", "tns.so_flag.hd", FT_BOOLEAN, 16,
+ NULL, 0x0200, "Half Duplex", HFILL }},
+ { &hf_tns_sopt_flag_dc1, {
+ "Don't Care", "tns.so_flag.dc1", FT_BOOLEAN, 16,
+ NULL, 0x0100, "Don't Care", HFILL }},
+ { &hf_tns_sopt_flag_dc2, {
+ "Don't Care", "tns.so_flag.dc2", FT_BOOLEAN, 16,
+ NULL, 0x0080, "Don't Care", HFILL }},
+ { &hf_tns_sopt_flag_dio, {
+ "Direct IO to Transport", "tns.so_flag.dio", FT_BOOLEAN, 16,
+ NULL, 0x0010, "Direct IO to Transport", HFILL }},
+ { &hf_tns_sopt_flag_ap, {
+ "Attention Processing", "tns.so_flag.ap", FT_BOOLEAN, 16,
+ NULL, 0x0008, "Attention Processing", HFILL }},
+ { &hf_tns_sopt_flag_ra, {
+ "Can Receive Attention", "tns.so_flag.ra", FT_BOOLEAN, 16,
+ NULL, 0x0004, "Can Receive Attention", HFILL }},
+ { &hf_tns_sopt_flag_sa, {
+ "Can Send Attention", "tns.so_flag.sa", FT_BOOLEAN, 16,
+ NULL, 0x0002, "Can Send Attention", HFILL }},
+
+
+ { &hf_tns_sdu_size, {
+ "Session Data Unit Size", "tns.sdu_size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Session Data Unit Size", HFILL }},
+ { &hf_tns_max_tdu_size, {
+ "Maximum Transmission Data Unit Size", "tns.max_tdu_size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Maximum Transmission Data Unit Size", HFILL }},
+
+ { &hf_tns_nt_proto_characteristics, {
+ "NT Protocol Characteristics", "tns.nt_proto_characteristics", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "NT Protocol Characteristics", HFILL }},
+ { &hf_tns_ntp_flag_hangon, {
+ "Hangon to listener connect", "tns.ntp_flag.hangon", FT_BOOLEAN, 16,
+ NULL, 0x8000, "Hangon to listener connect", HFILL }},
+ { &hf_tns_ntp_flag_crel, {
+ "Confirmed release", "tns.ntp_flag.crel", FT_BOOLEAN, 16,
+ NULL, 0x4000, "Confirmed release", HFILL }},
+ { &hf_tns_ntp_flag_tduio, {
+ "TDU based IO", "tns.ntp_flag.tduio", FT_BOOLEAN, 16,
+ NULL, 0x2000, "TDU based IO", HFILL }},
+ { &hf_tns_ntp_flag_srun, {
+ "Spawner running", "tns.ntp_flag.srun", FT_BOOLEAN, 16,
+ NULL, 0x1000, "Spawner running", HFILL }},
+ { &hf_tns_ntp_flag_dtest, {
+ "Data test", "tns.ntp_flag.dtest", FT_BOOLEAN, 16,
+ NULL, 0x0800, "Data Test", HFILL }},
+ { &hf_tns_ntp_flag_cbio, {
+ "Callback IO supported", "tns.ntp_flag.cbio", FT_BOOLEAN, 16,
+ NULL, 0x0400, "Callback IO supported", HFILL }},
+ { &hf_tns_ntp_flag_asio, {
+ "ASync IO Supported", "tns.ntp_flag.asio", FT_BOOLEAN, 16,
+ NULL, 0x0200, "ASync IO Supported", HFILL }},
+ { &hf_tns_ntp_flag_pio, {
+ "Packet oriented IO", "tns.ntp_flag.pio", FT_BOOLEAN, 16,
+ NULL, 0x0100, "Packet oriented IO", HFILL }},
+ { &hf_tns_ntp_flag_grant, {
+ "Can grant connection to another", "tns.ntp_flag.grant", FT_BOOLEAN, 16,
+ NULL, 0x0080, "Can grant connection to another", HFILL }},
+ { &hf_tns_ntp_flag_handoff, {
+ "Can handoff connection to another", "tns.ntp_flag.handoff", FT_BOOLEAN, 16,
+ NULL, 0x0040, "Can handoff connection to another", HFILL }},
+ { &hf_tns_ntp_flag_sigio, {
+ "Generate SIGIO signal", "tns.ntp_flag.sigio", FT_BOOLEAN, 16,
+ NULL, 0x0020, "Generate SIGIO signal", HFILL }},
+ { &hf_tns_ntp_flag_sigpipe, {
+ "Generate SIGPIPE signal", "tns.ntp_flag.sigpipe", FT_BOOLEAN, 16,
+ NULL, 0x0010, "Generate SIGPIPE signal", HFILL }},
+ { &hf_tns_ntp_flag_sigurg, {
+ "Generate SIGURG signal", "tns.ntp_flag.sigurg", FT_BOOLEAN, 16,
+ NULL, 0x0008, "Generate SIGURG signal", HFILL }},
+ { &hf_tns_ntp_flag_urgentio, {
+ "Urgent IO supported", "tns.ntp_flag.urgentio", FT_BOOLEAN, 16,
+ NULL, 0x0004, "Urgent IO supported", HFILL }},
+ { &hf_tns_ntp_flag_fdio, {
+ "Full duplex IO supported", "tns.ntp_flag.dfio", FT_BOOLEAN, 16,
+ NULL, 0x0002, "Full duplex IO supported", HFILL }},
+ { &hf_tns_ntp_flag_testop, {
+ "Test operation", "tns.ntp_flag.testop", FT_BOOLEAN, 16,
+ NULL, 0x0001, "Test operation", HFILL }},
+
+
+
+
+ { &hf_tns_line_turnaround, {
+ "Line Turnaround Value", "tns.line_turnaround", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Line Turnaround Value", HFILL }},
+ { &hf_tns_value_of_one, {
+ "Value of 1 in Hardware", "tns.value_of_one", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "Value of 1 in Hardware", HFILL }},
+
+ { &hf_tns_connect, {
+ "Connect", "tns.connect", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Connect", HFILL }},
+ { &hf_tns_connect_data_length, {
+ "Length of Connect Data", "tns.connect_data_length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of Connect Data", HFILL }},
+ { &hf_tns_connect_data_offset, {
+ "Offset to Connect Data", "tns.connect_data_offset", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Offset to Connect Data", HFILL }},
+ { &hf_tns_connect_data_max, {
+ "Maximum Receivable Connect Data", "tns.connect_data_max", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "Maximum Receivable Connect Data", HFILL }},
+
+ { &hf_tns_connect_flags0, {
+ "Connect Flags 0", "tns.connect_flags0", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Connect Flags 0", HFILL }},
+ { &hf_tns_connect_flags1, {
+ "Connect Flags 1", "tns.connect_flags1", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Connect Flags 1", HFILL }},
+
+ { &hf_tns_conn_flag_nareq, {
+ "NA services required", "tns.connect_flags.nareq", FT_BOOLEAN, 8,
+ NULL, 0x10, "NA services required", HFILL }},
+ { &hf_tns_conn_flag_nalink, {
+ "NA services linked in", "tns.connect_flags.nalink", FT_BOOLEAN, 8,
+ NULL, 0x08, "NA services linked in", HFILL }},
+ { &hf_tns_conn_flag_enablena, {
+ "NA services enabled", "tns.connect_flags.enablena", FT_BOOLEAN, 8,
+ NULL, 0x04, "NA services enabled", HFILL }},
+ { &hf_tns_conn_flag_ichg, {
+ "Interchange is involved", "tns.connect_flags.ichg", FT_BOOLEAN, 8,
+ NULL, 0x02, "Interchange is involved", HFILL }},
+ { &hf_tns_conn_flag_wantna, {
+ "NA services wanted", "tns.connect_flags.wantna", FT_BOOLEAN, 8,
+ NULL, 0x01, "NA services wanted", HFILL }},
+
+
+ { &hf_tns_trace_cf1, {
+ "Trace Cross Facility Item 1", "tns.trace_cf1", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Trace Cross Facility Item 1", HFILL }},
+ { &hf_tns_trace_cf2, {
+ "Trace Cross Facility Item 2", "tns.trace_cf2", FT_UINT32, BASE_HEX,
+ NULL, 0x0, "Trace Cross Facility Item 2", HFILL }},
+ { &hf_tns_trace_cid, {
+ "Trace Unique Connection ID", "tns.trace_cid", FT_UINT64, BASE_HEX,
+ NULL, 0x0, "Trace Unique Connection ID", HFILL }},
+ { &hf_tns_connect_data, {
+ "Connect Data", "tns.connect_data", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Connect Data", HFILL }},
+
+ { &hf_tns_accept, {
+ "Accept", "tns.accept", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Accept", HFILL }},
+ { &hf_tns_accept_data_length, {
+ "Accept Data Length", "tns.accept_data_length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of Accept Data", HFILL }},
+ { &hf_tns_accept_data, {
+ "Accept Data", "tns.accept_data", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Accept Data", HFILL }},
+ { &hf_tns_accept_data_offset, {
+ "Offset to Accept Data", "tns.accept_data_offset", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Offset to Accept Data", HFILL }},
+
+
+ { &hf_tns_refuse, {
+ "Refuse", "tns.refuse", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Refuse", HFILL }},
+ { &hf_tns_refuse_reason_user, {
+ "Refuse Reason (User)", "tns.refuse_reason_user", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Refuse Reason from Application", HFILL }},
+ { &hf_tns_refuse_reason_system, {
+ "Refuse Reason (System)", "tns.refuse_reason_system", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Refuse Reason from System", HFILL }},
+ { &hf_tns_refuse_data_length, {
+ "Refuse Data Length", "tns.refuse_data_length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of Refuse Data", HFILL }},
+ { &hf_tns_refuse_data, {
+ "Refuse Data", "tns.refuse_data", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Refuse Data", HFILL }},
+
+ { &hf_tns_abort, {
+ "Abort", "tns.abort", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Abort", HFILL }},
+ { &hf_tns_abort_reason_user, {
+ "Abort Reason (User)", "tns.abort_reason_user", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Abort Reason from Application", HFILL }},
+ { &hf_tns_abort_reason_system, {
+ "Abort Reason (User)", "tns.abort_reason_system", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Abort Reason from System", HFILL }},
+ { &hf_tns_abort_data, {
+ "Abort Data", "tns.abort_data", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Abort Data", HFILL }},
+
+ { &hf_tns_marker, {
+ "Marker", "tns.marker", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Marker", HFILL }},
+ { &hf_tns_marker_type, {
+ "Marker Type", "tns.marker.type", FT_UINT8, BASE_HEX,
+ VALS(tns_marker_types), 0x0, "Marker Type", HFILL }},
+ { &hf_tns_marker_data_byte, {
+ "Marker Data Byte", "tns.marker.databyte", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Marker Data Byte", HFILL }},
+ { &hf_tns_marker_data, {
+ "Marker Data", "tns.marker.data", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Marker Data", HFILL }},
+
+ { &hf_tns_control, {
+ "Control", "tns.control", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Control", HFILL }},
+ { &hf_tns_control_cmd, {
+ "Control Command", "tns.control.cmd", FT_UINT16, BASE_HEX,
+ VALS(tns_control_cmds), 0x0, "Control Command", HFILL }},
+ { &hf_tns_control_data, {
+ "Control Data", "tns.control.data", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Control Data", HFILL }},
+
+ { &hf_tns_redirect, {
+ "Redirect", "tns.redirect", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Redirect", HFILL }},
+ { &hf_tns_redirect_data_length, {
+ "Redirect Data Length", "tns.redirect_data_length", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length of Redirect Data", HFILL }},
+ { &hf_tns_redirect_data, {
+ "Redirect Data", "tns.redirect_data", FT_STRING, BASE_NONE,
+ NULL, 0x0, "Redirect Data", HFILL }},
+
+ { &hf_tns_data, {
+ "Data", "tns.data", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Data", HFILL }},
+
+ { &hf_tns_data_flag, {
+ "Data Flag", "tns.data_flag", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Data Flag", HFILL }},
+ { &hf_tns_data_flag_send, {
+ "Send Token", "tns.data_flag.send", FT_BOOLEAN, 16,
+ NULL, 0x1, "Send Token", HFILL }},
+ { &hf_tns_data_flag_rc, {
+ "Request Confirmation", "tns.data_flag.rc", FT_BOOLEAN, 16,
+ NULL, 0x2, "Request Confirmation", HFILL }},
+ { &hf_tns_data_flag_c, {
+ "Confirmation", "tns.data_flag.c", FT_BOOLEAN, 16,
+ NULL, 0x4, "Confirmation", HFILL }},
+ { &hf_tns_data_flag_reserved, {
+ "Reserved", "tns.data_flag.reserved", FT_BOOLEAN, 16,
+ NULL, 0x8, "Reserved", HFILL }},
+ { &hf_tns_data_flag_more, {
+ "More Data to Come", "tns.data_flag.more", FT_BOOLEAN, 16,
+ NULL, 0x20, "More Data to Come", HFILL }},
+ { &hf_tns_data_flag_eof, {
+ "End of File", "tns.data_flag.eof", FT_BOOLEAN, 16,
+ NULL, 0x40, "End of File", HFILL }},
+ { &hf_tns_data_flag_dic, {
+ "Do Immediate Confirmation", "tns.data_flag.dic", FT_BOOLEAN, 16,
+ NULL, 0x80, "Do Immediate Confirmation", HFILL }},
+ { &hf_tns_data_flag_rts, {
+ "Request To Send", "tns.data_flag.rts", FT_BOOLEAN, 16,
+ NULL, 0x100, "Request To Send", HFILL }},
+ { &hf_tns_data_flag_sntt, {
+ "Send NT Trailer", "tns.data_flag.sntt", FT_BOOLEAN, 16,
+ NULL, 0x200, "Send NT Trailer", HFILL }},
+
+
+ { &hf_tns_reserved_byte, {
+ "Reserved Byte", "tns.reserved_byte", FT_BYTES, BASE_HEX,
+ NULL, 0x0, "Reserved Byte", HFILL }},
+ { &hf_tns_packet_type, {
+ "Packet Type", "tns.type", FT_UINT8, BASE_DEC,
+ VALS(tns_type_vals), 0x0, "Type of TNS packet", HFILL }}
+
+ };
+
+ static gint *ett[] = {
+ &ett_tns,
+ &ett_tns_connect,
+ &ett_tns_accept,
+ &ett_tns_refuse,
+ &ett_tns_abort,
+ &ett_tns_redirect,
+ &ett_tns_marker,
+ &ett_tns_attention,
+ &ett_tns_control,
+ &ett_tns_data,
+ &ett_tns_data_flag,
+ &ett_tns_sopt_flag,
+ &ett_tns_ntp_flag,
+ &ett_tns_conn_flag,
+ &ett_sql
+ };
+ module_t *tns_module;
+
+ proto_tns = proto_register_protocol(
+ "Transparent Network Substrate Protocol", "TNS", "tns");
+ proto_register_field_array(proto_tns, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ tns_module = prefs_register_protocol(proto_tns, NULL);
+ prefs_register_bool_preference(tns_module, "desegment_tns_messages",
+ "Desegment all TNS messages spanning multiple TCP segments",
+ "Whether the TNS dissector should desegment all messages spanning multiple TCP segments",
+ &tns_desegment);
+}
+
+void
+proto_reg_handoff_tns(void)
+{
+ dissector_handle_t tns_handle;
+
+ tns_handle = new_create_dissector_handle(dissect_tns, proto_tns);
+ dissector_add("tcp.port", TCP_PORT_TNS, tns_handle);
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-tns.h b/epan/dissectors/packet-tns.h
new file mode 100644
index 0000000000..26ea435704
--- /dev/null
+++ b/epan/dissectors/packet-tns.h
@@ -0,0 +1,43 @@
+/* packet-tns.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_TNS_H
+#define PACKET_TNS_H
+
+/* Packet Types */
+#define TNS_TYPE_CONNECT 1
+#define TNS_TYPE_ACCEPT 2
+#define TNS_TYPE_ACK 3
+#define TNS_TYPE_REFUSE 4
+#define TNS_TYPE_REDIRECT 5
+#define TNS_TYPE_DATA 6
+#define TNS_TYPE_NULL 7
+#define TNS_TYPE_ABORT 9
+#define TNS_TYPE_RESEND 11
+#define TNS_TYPE_MARKER 12
+#define TNS_TYPE_ATTENTION 13
+#define TNS_TYPE_CONTROL 14
+#define TNS_TYPE_MAX 19
+
+#endif
diff --git a/epan/dissectors/packet-tpkt.c b/epan/dissectors/packet-tpkt.c
new file mode 100644
index 0000000000..88938f56fe
--- /dev/null
+++ b/epan/dissectors/packet-tpkt.c
@@ -0,0 +1,395 @@
+/* packet-tpkt.c
+ *
+ * Routine to check for RFC 1006 TPKT header and to dissect TPKT header
+ * Copyright 2000, Philips Electronics N.V.
+ * Andreas Sikkema <h323@ramdyne.nl>
+ *
+ * Routine to dissect RFC 1006 TPKT packet containing OSI TP PDU
+ * Copyright 2001, Martin Thomas <Martin_A_Thomas@yahoo.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "packet-tpkt.h"
+#include "packet-frame.h"
+#include "prefs.h"
+
+/* TPKT header fields */
+static int proto_tpkt = -1;
+static protocol_t *proto_tpkt_ptr;
+static int hf_tpkt_version = -1;
+static int hf_tpkt_reserved = -1;
+static int hf_tpkt_length = -1;
+
+/* TPKT fields defining a sub tree */
+static gint ett_tpkt = -1;
+
+/* desegmentation of OSI over TPKT over TCP */
+static gboolean tpkt_desegment = TRUE;
+
+#define TCP_PORT_TPKT 102
+
+/* find the dissector for OSI TP (aka COTP) */
+static dissector_handle_t osi_tp_handle;
+
+/*
+ * Check whether this could be a TPKT-encapsulated PDU.
+ * Returns -1 if it's not, and the PDU length from the TPKT header
+ * if it is.
+ *
+ * "min_len" is the minimum length of the PDU; the length field in the
+ * TPKT header must be at least "4+min_len" in order for this to be a
+ * valid TPKT PDU for the protocol in question.
+ */
+int
+is_tpkt(tvbuff_t *tvb, int min_len)
+{
+ guint16 pkt_len;
+
+ /*
+ * If TPKT is disabled, don't dissect it, just return -1, meaning
+ * "this isn't TPKT".
+ */
+ if (!proto_is_protocol_enabled(proto_tpkt_ptr))
+ return -1;
+
+ /* There should at least be 4 bytes left in the frame */
+ if (!tvb_bytes_exist(tvb, 0, 4))
+ return -1; /* there aren't */
+
+ /*
+ * The first octet should be 3 and the second one should be 0
+ * The H.323 implementers guide suggests that this might not
+ * always be the case....
+ */
+ if (!(tvb_get_guint8(tvb, 0) == 3 && tvb_get_guint8(tvb, 1) == 0))
+ return -1; /* they're not */
+
+ /*
+ * Get the length from the TPKT header. Make sure it's large
+ * enough.
+ */
+ pkt_len = tvb_get_ntohs(tvb, 2);
+ if (pkt_len < 4 + min_len)
+ return -1; /* it's not */
+
+ /*
+ * Return the length from the header.
+ */
+ return pkt_len;
+}
+
+/*
+ * Dissect TPKT-encapsulated data in a TCP stream.
+ */
+void
+dissect_tpkt_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gboolean desegment, dissector_handle_t subdissector_handle)
+{
+ proto_item *ti = NULL;
+ proto_tree *tpkt_tree = NULL;
+ volatile int offset = 0;
+ int length_remaining;
+ int data_len;
+ volatile int length;
+ tvbuff_t *next_tvb;
+ const char *saved_proto;
+
+ /*
+ * If we're reassembling segmented TPKT PDUs, empty the COL_INFO
+ * column, so subdissectors can append information
+ * without having to worry about emptying the column.
+ *
+ * We use "col_add_str()" because the subdissector
+ * might be appending information to the column, in
+ * which case we'd have to zero the buffer out explicitly
+ * anyway.
+ */
+ if (tpkt_desegment && check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "");
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * Is the first byte of this putative TPKT header
+ * a valid TPKT version number, i.e. 3?
+ */
+ if (tvb_get_guint8(tvb, offset) != 3) {
+ /*
+ * No, so don't assume this is a TPKT header;
+ * we might be in the middle of TPKT data,
+ * so don't get the length and don't try to
+ * do reassembly.
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_tpkt, tvb,
+ offset, -1, FALSE);
+ tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
+
+ proto_tree_add_text(tpkt_tree, tvb, offset, -1,
+ "Continuation data");
+ }
+ return;
+ }
+
+ length_remaining = tvb_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the TPKT header split across segment
+ * boundaries?
+ */
+ if (length_remaining < 4) {
+ /*
+ * Yes. Tell the TCP dissector where
+ * the data for this message starts in
+ * the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4 - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Get the length from the TPKT header.
+ */
+ data_len = tvb_get_ntohs(tvb, offset + 2);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the payload split across segment
+ * boundaries?
+ */
+ if (length_remaining < data_len) {
+ /*
+ * Yes. Tell the TCP dissector where
+ * the data for this message starts in
+ * the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len =
+ data_len - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Dissect the TPKT header.
+ * Save and restore "pinfo->current_proto".
+ */
+ saved_proto = pinfo->current_proto;
+ pinfo->current_proto = "TPKT";
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
+ /*
+ * Don't add the TPKT header information if we're
+ * reassembling segmented TPKT PDUs or if this
+ * PDU isn't reassembled.
+ *
+ * XXX - the first is so that subdissectors can append
+ * information without getting TPKT stuff in the middle;
+ * why the second?
+ */
+ if (!tpkt_desegment && !pinfo->fragmented
+ && check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "TPKT Data length = %u", data_len);
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_tpkt, tvb,
+ offset, 4, FALSE);
+ tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
+
+ /* Version */
+ proto_tree_add_item(tpkt_tree, hf_tpkt_version, tvb,
+ offset, 1, FALSE);
+
+ /* Reserved octet*/
+ proto_tree_add_item(tpkt_tree, hf_tpkt_reserved, tvb,
+ offset + 1, 1, FALSE);
+
+ /* Length */
+ proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb,
+ offset + 2, 2, data_len);
+ }
+ pinfo->current_proto = saved_proto;
+
+ /* Skip the TPKT header. */
+ offset += 4;
+ data_len -= 4;
+
+ /*
+ * Construct a tvbuff containing the amount of the payload
+ * we have available. Make its reported length the
+ * amount of data in this TPKT packet.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector
+ * will throw a BoundsError exception, rather than a
+ * ReportedBoundsError exception. We really want
+ * a tvbuff where the length is "length", the reported
+ * length is "plen + 2", and the "if the snapshot length
+ * were infinite" length were the minimum of the
+ * reported length of the tvbuff handed to us and "plen+2",
+ * with a new type of exception thrown if the offset is
+ * within the reported length but beyond that third length,
+ * with that exception getting the "Unreassembled Packet"
+ * error.
+ */
+ length = length_remaining - 4;
+ if (length > data_len)
+ length = data_len;
+ next_tvb = tvb_new_subset(tvb, offset, length, data_len);
+
+ /*
+ * Call the subdissector.
+ *
+ * Catch the ReportedBoundsError exception; if this
+ * particular message happens to get a ReportedBoundsError
+ * exception, that doesn't mean that we should stop
+ * dissecting TPKT messages within this frame or chunk
+ * of reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing
+ * more to see, so we just re-throw it.
+ */
+ TRY {
+ call_dissector(subdissector_handle, next_tvb, pinfo,
+ tree);
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ }
+ ENDTRY;
+
+ /*
+ * Skip the payload.
+ */
+ offset += length;
+ }
+}
+
+/*
+ * Dissect RFC 1006 TPKT, which wraps a TPKT header around an OSI TP
+ * PDU.
+ */
+static void
+dissect_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_tpkt_encap(tvb, pinfo, tree, tpkt_desegment, osi_tp_handle);
+}
+
+void
+proto_register_tpkt(void)
+{
+ static hf_register_info hf[] =
+ {
+ {
+ &hf_tpkt_version,
+ {
+ "Version",
+ "tpkt.version",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_tpkt_reserved,
+ {
+ "Reserved",
+ "tpkt.reserved",
+ FT_UINT8,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ {
+ &hf_tpkt_length,
+ {
+ "Length",
+ "tpkt.length",
+ FT_UINT16,
+ BASE_DEC,
+ NULL,
+ 0x0,
+ "", HFILL
+ }
+ },
+ };
+
+ static gint *ett[] =
+ {
+ &ett_tpkt,
+ };
+ module_t *tpkt_module;
+
+ proto_tpkt = proto_register_protocol("TPKT", "TPKT", "tpkt");
+ proto_tpkt_ptr = find_protocol_by_id(proto_tpkt);
+ proto_register_field_array(proto_tpkt, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ tpkt_module = prefs_register_protocol(proto_tpkt, NULL);
+ prefs_register_bool_preference(tpkt_module, "desegment",
+ "Desegment all TPKT messages spanning multiple TCP segments",
+ "Whether the TPKT dissector should desegment all messages spanning multiple TCP segments",
+ &tpkt_desegment);
+}
+
+void
+proto_reg_handoff_tpkt(void)
+{
+ dissector_handle_t tpkt_handle;
+
+ osi_tp_handle = find_dissector("ositp");
+ tpkt_handle = create_dissector_handle(dissect_tpkt, proto_tpkt);
+ dissector_add("tcp.port", TCP_PORT_TPKT, tpkt_handle);
+}
diff --git a/epan/dissectors/packet-tpkt.h b/epan/dissectors/packet-tpkt.h
new file mode 100644
index 0000000000..f4404e8f0e
--- /dev/null
+++ b/epan/dissectors/packet-tpkt.h
@@ -0,0 +1,45 @@
+/* packet-tpkt.h
+ *
+ * Routines for TPKT dissection
+ *
+ * Copyright 2000, Philips Electronics N.V.
+ * Andreas Sikkema <andreas.sikkema@philips.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Check whether this could be a TPKT-encapsulated PDU.
+ * Returns -1 if it's not, and the PDU length from the TPKT header
+ * if it is.
+ *
+ * "min_len" is the minimum length of the PDU; the length field in the
+ * TPKT header must be at least "4+min_len" in order for this to be a
+ * valid TPKT PDU for the protocol in question.
+ */
+extern int is_tpkt(tvbuff_t *tvb, int min_len);
+
+/*
+ * Dissect TPKT-encapsulated data in a TCP stream.
+ */
+extern void dissect_tpkt_encap(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, gboolean desegment,
+ dissector_handle_t subdissector_handle);
diff --git a/epan/dissectors/packet-tr.c b/epan/dissectors/packet-tr.c
new file mode 100644
index 0000000000..79d1130a6a
--- /dev/null
+++ b/epan/dissectors/packet-tr.c
@@ -0,0 +1,749 @@
+/* packet-tr.c
+ * Routines for Token-Ring packet disassembly
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-tr.h"
+#include "packet-llc.h"
+#include "prefs.h"
+#include "tap.h"
+
+static int proto_tr = -1;
+static int hf_tr_dst = -1;
+static int hf_tr_src = -1;
+static int hf_tr_addr = -1;
+static int hf_tr_sr = -1;
+static int hf_tr_ac = -1;
+static int hf_tr_priority = -1;
+static int hf_tr_frame = -1;
+static int hf_tr_monitor_cnt = -1;
+static int hf_tr_priority_reservation = -1;
+static int hf_tr_fc = -1;
+static int hf_tr_fc_type = -1;
+static int hf_tr_fc_pcf = -1;
+static int hf_tr_rif_bytes = -1;
+static int hf_tr_broadcast = -1;
+static int hf_tr_max_frame_size = -1;
+static int hf_tr_direction = -1;
+static int hf_tr_rif = -1;
+static int hf_tr_rif_ring = -1;
+static int hf_tr_rif_bridge = -1;
+
+static gint ett_token_ring = -1;
+static gint ett_token_ring_ac = -1;
+static gint ett_token_ring_fc = -1;
+
+static int tr_tap = -1;
+
+/*
+ * Check for and attempt to fix Linux link-layer header mangling.
+ */
+static gboolean fix_linux_botches = FALSE;
+
+#define TR_MIN_HEADER_LEN 14
+#define TR_MAX_HEADER_LEN 32
+
+static const true_false_string ac_truth = { "Frame", "Token" };
+
+static const value_string pcf_vals[] = {
+ { 0, "Normal buffer" },
+ { 1, "Express buffer" },
+ { 2, "Purge" },
+ { 3, "Claim Token" },
+ { 4, "Beacon" },
+ { 5, "Active Monitor Present" },
+ { 6, "Standby Monitor Present" },
+ { 0, NULL },
+};
+
+static const value_string frame_vals[] = {
+ { 0, "MAC" },
+ { 1, "LLC" },
+ { 2, "Reserved" },
+ { 0, NULL },
+};
+
+static const value_string broadcast_vals[] = {
+ { 0 << 5, "Non-broadcast" },
+ { 1 << 5, "Non-broadcast" },
+ { 2 << 5, "Non-broadcast" },
+ { 3 << 5, "Non-broadcast" },
+ { 4 << 5, "All-routes broadcast" },
+ { 5 << 5, "All-routes broadcast" },
+ { 6 << 5, "Single-route broadcast" },
+ { 7 << 5, "Single-route broadcast" },
+ { 0, NULL }
+};
+
+static const value_string max_frame_size_vals[] = {
+ { 0 << 4, "516" },
+ { 1 << 4, "1500" },
+ { 2 << 4, "2052" },
+ { 3 << 4, "4472" },
+ { 4 << 4, "8144" },
+ { 5 << 4, "11407" },
+ { 6 << 4, "17800" },
+ { 7 << 4, "65535" },
+ { 0, NULL }
+};
+
+static const value_string direction_vals[] = {
+ { 0, "From originating station (-->)" },
+ { 128, "To originating station (<--)" },
+ { 0, NULL }
+};
+
+static dissector_handle_t trmac_handle;
+static dissector_handle_t llc_handle;
+static dissector_handle_t data_handle;
+
+/*
+ * DODGY LINUX HACK DODGY LINUX HACK
+ * Linux 2.0.x always passes frames to the Token Ring driver for transmission with
+ * 18 bytes padding for source routing information. Some drivers copy the first
+ * (18 - srlen) bytes up the frame (18 - srlen) bytes thus removing the padding.
+ * Other drivers just make a copy of the entire frame and then hack about with it
+ * so the frame the sniffer gets is fine (just has extra sr routing).
+ * In the first instance (driver hacking frame in situ) the sniffer gets a garbled
+ * frame.
+ * This function trys to detect this and returns the offset of where
+ * the frame really starts.
+ * This only detects frames that we have sent ourselves so if we are packet sniffing
+ * on the machine we are watching this is useful.
+ * Compare offset 0 with offset x+1 for a length of x bytes for all value of x = 1 to 18
+ * if match then Linux driver has done in situ source route compression of the crappy
+ * Linux 2.0.x frame so the beginning of the real frame is x bytes in.
+ * (And this real frame x bytes in looks like a proper TR frame that goes on the wire
+ * with none of the Linux idiosyncrasies).
+ *
+ * XXX - there should perhaps be a preference setting to turn this off,
+ * as sometimes it can, and does, get a false hit.
+ */
+static
+int check_for_old_linux_tvb(tvbuff_t *tvb)
+{
+ const guint8 *data;
+ int x, bytes;
+
+ /* Restrict our looping to the boundaries of the frame */
+ bytes = tvb_length(tvb);
+ if (bytes > 19) {
+ bytes = 19;
+ }
+
+ data = tvb_get_ptr(tvb, 0, bytes);
+
+ for(x = 1; x <= bytes-1 ;x++)
+ {
+ if (memcmp(&data[0], &data[x], x) == 0)
+ {
+ return x;
+ }
+ }
+ return 0;
+}
+
+static
+int check_for_old_linux(const guchar * pd)
+{
+ int x;
+ for(x=1;x<=18;x++)
+ {
+ if (memcmp(&pd[0],&pd[x],x) == 0)
+ {
+ return x;
+ }
+ }
+ return 0;
+}
+
+
+static void
+add_ring_bridge_pairs(int rcf_len, tvbuff_t*, proto_tree *tree);
+
+void
+capture_tr(const guchar *pd, int offset, int len, packet_counts *ld) {
+
+ int source_routed = 0;
+ int frame_type;
+ int x;
+ guint8 trn_rif_bytes;
+ guint8 actual_rif_bytes;
+ guint16 first2_sr;
+
+ /* The trn_hdr struct, as separate variables */
+ guint8 trn_fc; /* field control field */
+ const guint8 *trn_shost; /* source host */
+
+ if (!BYTES_ARE_IN_FRAME(offset, len, TR_MIN_HEADER_LEN)) {
+ ld->other++;
+ return;
+ }
+
+ if ((x = check_for_old_linux(pd)))
+ {
+ /* Actually packet starts x bytes into what we have got but with all
+ source routing compressed
+ */
+ /* pd = &pd[x]; */ offset+=x;
+ }
+
+ /* get the data */
+ trn_fc = pd[offset + 1];
+ trn_shost = &pd[offset + 8];
+
+ frame_type = (trn_fc & 192) >> 6;
+
+ /* if the high bit on the first byte of src hwaddr is 1, then
+ this packet is source-routed */
+ source_routed = trn_shost[0] & 128;
+
+ trn_rif_bytes = pd[offset + 14] & 31;
+
+ if (fix_linux_botches) {
+ /* the Linux 2.0 TR code strips source-route bits in
+ * order to test for SR. This can be removed from most
+ * packets with oltr, but not all. So, I try to figure out
+ * which packets should have been SR here. I'll check to
+ * see if there's a SNAP or IPX field right after
+ * my RIF fields.
+ *
+ * The Linux 2.4.18 code, at least appears to do the
+ * same thing, from a capture I got from somebody running
+ * 2.4.18 (RH 7.1, so perhaps this is a Red Hat
+ * "improvement").
+ */
+ if (!source_routed && trn_rif_bytes > 0) {
+ if (pd[offset + 0x0e] != pd[offset + 0x0f]) {
+ first2_sr = pntohs(&pd[offset + 0xe0 + trn_rif_bytes]);
+ if (
+ (first2_sr == 0xaaaa &&
+ pd[offset + 0x10 + trn_rif_bytes] == 0x03) ||
+
+ first2_sr == 0xe0e0 ||
+ first2_sr == 0xe0aa ) {
+
+ source_routed = 1;
+ }
+ }
+ }
+ }
+
+ if (source_routed) {
+ actual_rif_bytes = trn_rif_bytes;
+ }
+ else {
+ trn_rif_bytes = 0;
+ actual_rif_bytes = 0;
+ }
+
+ if (fix_linux_botches) {
+ /* this is a silly hack for Linux 2.0.x. Read the comment
+ * below, in front of the other #ifdef linux.
+ * If we're sniffing our own NIC, we get a full RIF,
+ * sometimes with garbage
+ */
+ if ((source_routed && trn_rif_bytes == 2 && frame_type == 1) ||
+ (!source_routed && frame_type == 1)) {
+ /* look for SNAP or IPX only */
+ if ( (pd[offset + 0x20] == 0xaa && pd[offset + 0x21] == 0xaa && pd[offset + 0x22] == 03) ||
+ (pd[offset + 0x20] == 0xe0 && pd[offset + 0x21] == 0xe0) ) {
+ actual_rif_bytes = 18;
+ } else if (
+ pd[offset + 0x23] == 0 &&
+ pd[offset + 0x24] == 0 &&
+ pd[offset + 0x25] == 0 &&
+ pd[offset + 0x26] == 0x00 &&
+ pd[offset + 0x27] == 0x11) {
+
+ actual_rif_bytes = 18;
+
+ /* Linux 2.0.x also requires drivers pass up
+ * a fake SNAP and LLC header before the
+ * real LLC hdr for all Token Ring frames
+ * that arrive with DSAP and SSAP != 0xAA
+ * (i.e. for non SNAP frames e.g. for Netware
+ * frames) the fake SNAP header has the
+ * ETH_P_TR_802_2 ether type (0x0011) and the protocol id
+ * bytes as zero frame looks like :-
+ * TR Header | Fake LLC | Fake SNAP | Wire LLC | Rest of data
+ */
+ offset += 8; /* Skip fake LLC and SNAP */
+ }
+ }
+ }
+
+ offset += actual_rif_bytes + TR_MIN_HEADER_LEN;
+
+ /* The package is either MAC or LLC */
+ switch (frame_type) {
+ /* MAC */
+ case 0:
+ ld->other++;
+ break;
+ case 1:
+ capture_llc(pd, offset, len, ld);
+ break;
+ default:
+ /* non-MAC, non-LLC, i.e., "Reserved" */
+ ld->other++;
+ break;
+ }
+}
+
+
+static void
+dissect_tr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *tr_tree, *bf_tree;
+ proto_item *ti;
+ int frame_type;
+ guint8 rcf1, rcf2;
+ tvbuff_t *next_tvb;
+
+ volatile int fixoffset = 0;
+ volatile int source_routed = 0;
+ volatile guint8 trn_rif_bytes;
+ volatile guint8 actual_rif_bytes;
+ volatile guint8 c1_nonsr;
+ volatile guint8 c2_nonsr;
+ volatile guint16 first2_sr;
+ tvbuff_t *volatile tr_tvb;
+
+ static tr_hdr trh_arr[4];
+ static int trh_current=0;
+ tr_hdr *trh;
+
+ /* non-source-routed version of source addr */
+ static guint8 trn_shost_nonsr[6];
+ int x;
+
+ /* Token-Ring Strings */
+ char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" };
+
+
+ trh_current++;
+ if(trh_current==4){
+ trh_current=0;
+ }
+ trh=&trh_arr[trh_current];
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TR");
+
+ if (fix_linux_botches)
+ x = check_for_old_linux_tvb((tvbuff_t*) tvb);
+ else
+ x = 0;
+ if (x != 0) {
+ /* Actually packet starts x bytes into what we have got but with all
+ source routing compressed. See comment above */
+ tr_tvb = tvb_new_subset((tvbuff_t*) tvb, x, -1, -1);
+ }
+ else {
+ tr_tvb = tvb;
+ }
+
+ /* Get the data */
+ trh->fc = tvb_get_guint8(tr_tvb, 1);
+ SET_ADDRESS(&trh->src, AT_ETHER, 6, tvb_get_ptr(tr_tvb, 8, 6));
+ SET_ADDRESS(&trh->dst, AT_ETHER, 6, tvb_get_ptr(tr_tvb, 2, 6));
+
+ memcpy(trn_shost_nonsr, trh->src.data, 6);
+ trn_shost_nonsr[0] &= 127;
+ frame_type = (trh->fc & 192) >> 6;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Token-Ring %s", fc[frame_type]);
+
+ /* if the high bit on the first byte of src hwaddr is 1, then
+ this packet is source-routed */
+ source_routed = trh->src.data[0] & 128;
+
+ trn_rif_bytes = tvb_get_guint8(tr_tvb, 14) & 31;
+
+ if (fix_linux_botches) {
+ /* the Linux 2.0 TR code strips source-route bits in
+ * order to test for SR. This can be removed from most
+ * packets with oltr, but not all. So, I try to figure out
+ * which packets should have been SR here. I'll check to
+ * see if there's a SNAP or IPX field right after
+ * my RIF fields.
+ *
+ * The Linux 2.4.18 code, at least appears to do the
+ * same thing, from a capture I got from somebody running
+ * 2.4.18 (RH 7.1, so perhaps this is a Red Hat
+ * "improvement").
+ */
+ if (frame_type == 1 && !source_routed && trn_rif_bytes > 0) {
+ TRY {
+
+ c1_nonsr = tvb_get_guint8(tr_tvb, 14);
+ c2_nonsr = tvb_get_guint8(tr_tvb, 15);
+
+ if (c1_nonsr != c2_nonsr) {
+
+ first2_sr = tvb_get_ntohs(tr_tvb, trn_rif_bytes + 0x0e);
+
+ if ( ( first2_sr == 0xaaaa &&
+ tvb_get_guint8(tr_tvb, trn_rif_bytes + 0x10) == 0x03) ||
+
+ first2_sr == 0xe0e0 ||
+ first2_sr == 0xe0aa ) {
+
+ source_routed = 1;
+ }
+ }
+ }
+ CATCH(BoundsError) {
+ /* We had no information beyond the TR header. Just assume
+ * this is a normal (non-Linux) TR header. */
+ ;
+ }
+ ENDTRY;
+ }
+ }
+
+ if (source_routed) {
+ actual_rif_bytes = trn_rif_bytes;
+ }
+ else {
+ trn_rif_bytes = 0;
+ actual_rif_bytes = 0;
+ }
+
+ if (fix_linux_botches) {
+ /* this is a silly hack for Linux 2.0.x. Read the comment
+ * below, in front of the other #ifdef linux. If we're
+ * sniffing our own NIC, we get a full RIF, sometimes with
+ * garbage
+ */
+ TRY {
+ if (frame_type == 1 && ( (source_routed && trn_rif_bytes == 2) ||
+ !source_routed) ) {
+ /* look for SNAP or IPX only */
+ if (
+ (tvb_get_ntohs(tr_tvb, 0x20) == 0xaaaa &&
+ tvb_get_guint8(tr_tvb, 0x22) == 0x03)
+ ||
+ tvb_get_ntohs(tr_tvb, 0x20) == 0xe0e0 ) {
+
+ actual_rif_bytes = 18;
+ }
+ else if (
+ tvb_get_ntohl(tr_tvb, 0x23) == 0 &&
+ tvb_get_guint8(tr_tvb, 0x27) == 0x11) {
+
+ actual_rif_bytes = 18;
+
+ /* Linux 2.0.x also requires drivers
+ * pass up a fake SNAP and LLC header
+ * before the real LLC hdr for all
+ * Token Ring frames that arrive with
+ * DSAP and SSAP != 0xAA
+ * (i.e. for non SNAP frames e.g. for
+ * Netware frames)
+ * the fake SNAP header has the
+ * ETH_P_TR_802_2 ether type (0x0011)
+ * and the protocol id bytes as zero frame looks like :-
+ * TR Header | Fake LLC | Fake SNAP | Wire LLC | Rest of data
+ */
+ fixoffset += 8; /* Skip fake LLC and SNAP */
+ }
+ }
+ }
+ CATCH(BoundsError) {
+ /* We had no information beyond the TR header. Just assume
+ * this is a normal (non-Linux) TR header. */
+ ;
+ }
+ ENDTRY;
+ }
+
+ /* XXX - copy it to some buffer associated with "*pinfo", rather than
+ just making "trn_shost_nonsr" static? */
+ SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, trn_shost_nonsr);
+ SET_ADDRESS(&pinfo->src, AT_ETHER, 6, trn_shost_nonsr);
+ SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, trh->dst.data);
+ SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, trh->dst.data);
+
+ /* protocol analysis tree */
+ if (tree) {
+ /* Create Token-Ring Tree */
+ ti = proto_tree_add_item(tree, proto_tr, tr_tvb, 0, TR_MIN_HEADER_LEN + actual_rif_bytes, FALSE);
+ tr_tree = proto_item_add_subtree(ti, ett_token_ring);
+
+ /* Create the Access Control bitfield tree */
+ trh->ac = tvb_get_guint8(tr_tvb, 0);
+ ti = proto_tree_add_uint(tr_tree, hf_tr_ac, tr_tvb, 0, 1, trh->ac);
+ bf_tree = proto_item_add_subtree(ti, ett_token_ring_ac);
+
+ proto_tree_add_uint(bf_tree, hf_tr_priority, tr_tvb, 0, 1, trh->ac);
+ proto_tree_add_boolean(bf_tree, hf_tr_frame, tr_tvb, 0, 1, trh->ac);
+ proto_tree_add_uint(bf_tree, hf_tr_monitor_cnt, tr_tvb, 0, 1, trh->ac);
+ proto_tree_add_uint(bf_tree, hf_tr_priority_reservation, tr_tvb, 0, 1, trh->ac);
+
+ /* Create the Frame Control bitfield tree */
+ ti = proto_tree_add_uint(tr_tree, hf_tr_fc, tr_tvb, 1, 1, trh->fc);
+ bf_tree = proto_item_add_subtree(ti, ett_token_ring_fc);
+
+ proto_tree_add_uint(bf_tree, hf_tr_fc_type, tr_tvb, 1, 1, trh->fc);
+ proto_tree_add_uint(bf_tree, hf_tr_fc_pcf, tr_tvb, 1, 1, trh->fc);
+ proto_tree_add_ether(tr_tree, hf_tr_dst, tr_tvb, 2, 6, trh->dst.data);
+ proto_tree_add_ether(tr_tree, hf_tr_src, tr_tvb, 8, 6, trh->src.data);
+ proto_tree_add_ether_hidden(tr_tree, hf_tr_addr, tr_tvb, 2, 6, trh->dst.data);
+ proto_tree_add_ether_hidden(tr_tree, hf_tr_addr, tr_tvb, 8, 6, trh->src.data);
+
+ proto_tree_add_boolean(tr_tree, hf_tr_sr, tr_tvb, 8, 1, source_routed);
+
+ /* non-source-routed version of src addr */
+ proto_tree_add_ether_hidden(tr_tree, hf_tr_src, tr_tvb, 8, 6, trn_shost_nonsr);
+
+ if (source_routed) {
+ /* RCF Byte 1 */
+ rcf1 = tvb_get_guint8(tr_tvb, 14);
+ proto_tree_add_uint(tr_tree, hf_tr_rif_bytes, tr_tvb, 14, 1, trn_rif_bytes);
+ proto_tree_add_uint(tr_tree, hf_tr_broadcast, tr_tvb, 14, 1, rcf1 & 224);
+
+ /* RCF Byte 2 */
+ rcf2 = tvb_get_guint8(tr_tvb, 15);
+ proto_tree_add_uint(tr_tree, hf_tr_max_frame_size, tr_tvb, 15, 1, rcf2 & 112);
+ proto_tree_add_uint(tr_tree, hf_tr_direction, tr_tvb, 15, 1, rcf2 & 128);
+
+ /* if we have more than 2 bytes of RIF, then we have
+ ring/bridge pairs */
+ if (trn_rif_bytes > 2) {
+ add_ring_bridge_pairs(trn_rif_bytes, tr_tvb, tr_tree);
+ }
+ }
+
+ /* Linux 2.0.x has a problem in that the 802.5 code creates
+ an emtpy full (18-byte) RIF area. It's up to the tr driver to
+ either fill it in or remove it before sending the bytes out
+ to the wire. If you run tcpdump on a Linux 2.0.x machine running
+ token-ring, tcpdump will capture these 18 filler bytes. They
+ are filled with garbage. The best way to detect this problem is
+ to know the src hwaddr of the machine from which you were running
+ tcpdump. W/o that, however, I'm guessing that DSAP == SSAP if the
+ frame type is LLC. It's very much a hack. */
+ if (actual_rif_bytes > trn_rif_bytes) {
+ proto_tree_add_text(tr_tree, tr_tvb, TR_MIN_HEADER_LEN + trn_rif_bytes, actual_rif_bytes - trn_rif_bytes,
+ "Empty RIF from Linux 2.0.x driver. The sniffing NIC "
+ "is also running a protocol stack.");
+ }
+ if (fixoffset) {
+ proto_tree_add_text(tr_tree, tr_tvb, TR_MIN_HEADER_LEN + 18,8,"Linux 2.0.x fake LLC and SNAP header");
+ }
+ }
+
+ next_tvb = tvb_new_subset(tr_tvb, TR_MIN_HEADER_LEN + actual_rif_bytes + fixoffset, -1, -1);
+
+ /* The package is either MAC or LLC */
+ switch (frame_type) {
+ /* MAC */
+ case 0:
+ call_dissector(trmac_handle, next_tvb, pinfo, tree);
+ break;
+ case 1:
+ call_dissector(llc_handle, next_tvb, pinfo, tree);
+ break;
+ default:
+ /* non-MAC, non-LLC, i.e., "Reserved" */
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+ break;
+ }
+
+ tap_queue_packet(tr_tap, pinfo, trh);
+}
+
+/* this routine is taken from the Linux net/802/tr.c code, which shows
+ring-bridge pairs in the /proc/net/tr_rif virtual file. */
+static void
+add_ring_bridge_pairs(int rcf_len, tvbuff_t *tvb, proto_tree *tree)
+{
+ int j, size;
+ int segment, brdgnmb, unprocessed_rif;
+ int buff_offset=0;
+
+#define RIF_OFFSET 16
+#define RIF_BYTES_TO_PROCESS 30
+
+ char buffer[3 + (RIF_BYTES_TO_PROCESS / 2) * 6 + 1];
+
+ /* Only process so many bytes of RIF, as per TR spec, and not overflow
+ * static buffer above */
+ unprocessed_rif = rcf_len - RIF_BYTES_TO_PROCESS;
+ rcf_len = MIN(rcf_len, RIF_BYTES_TO_PROCESS);
+
+ /* Ignore the 2 RCF bytes, since they don't make up the ring/bride pairs */
+ rcf_len -= 2;
+
+ for(j = 1; j < rcf_len - 1; j += 2) {
+ if (j==1) {
+ segment = tvb_get_ntohs(tvb, RIF_OFFSET) >> 4;
+ size = sprintf(buffer, "%03X",segment);
+ proto_tree_add_uint_hidden(tree, hf_tr_rif_ring, tvb, TR_MIN_HEADER_LEN + 2, 2, segment);
+ buff_offset += size;
+ }
+ segment = tvb_get_ntohs(tvb, RIF_OFFSET + 1 + j) >> 4;
+ brdgnmb = tvb_get_guint8(tvb, RIF_OFFSET + j) & 0x0f;
+ size = sprintf(buffer+buff_offset, "-%01X-%03X",brdgnmb,segment);
+ proto_tree_add_uint_hidden(tree, hf_tr_rif_ring, tvb, TR_MIN_HEADER_LEN + 3 + j, 2, segment);
+ proto_tree_add_uint_hidden(tree, hf_tr_rif_bridge, tvb, TR_MIN_HEADER_LEN + 2 + j, 1, brdgnmb);
+ buff_offset += size;
+ }
+ proto_tree_add_string(tree, hf_tr_rif, tvb, TR_MIN_HEADER_LEN + 2, rcf_len, buffer);
+
+ if (unprocessed_rif > 0) {
+ proto_tree_add_text(tree, tvb, TR_MIN_HEADER_LEN + RIF_BYTES_TO_PROCESS, unprocessed_rif,
+ "Extra RIF bytes beyond spec: %d", unprocessed_rif);
+ }
+}
+
+void
+proto_register_tr(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tr_ac,
+ { "Access Control", "tr.ac", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tr_priority,
+ { "Priority", "tr.priority", FT_UINT8, BASE_DEC, NULL, 0xe0,
+ "", HFILL }},
+
+ { &hf_tr_frame,
+ { "Frame", "tr.frame", FT_BOOLEAN, 8, TFS(&ac_truth), 0x10,
+ "", HFILL }},
+
+ { &hf_tr_monitor_cnt,
+ { "Monitor Count", "tr.monitor_cnt", FT_UINT8, BASE_DEC, NULL, 0x08,
+ "", HFILL }},
+
+ { &hf_tr_priority_reservation,
+ { "Priority Reservation","tr.priority_reservation", FT_UINT8, BASE_DEC, NULL, 0x07,
+ "", HFILL }},
+
+ { &hf_tr_fc,
+ { "Frame Control", "tr.fc", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tr_fc_type,
+ { "Frame Type", "tr.frame_type", FT_UINT8, BASE_DEC, VALS(frame_vals), 0xc0,
+ "", HFILL }},
+
+ { &hf_tr_fc_pcf,
+ { "Frame PCF", "tr.frame_pcf", FT_UINT8, BASE_DEC, VALS(pcf_vals), 0x0f,
+ "", HFILL }},
+
+ { &hf_tr_dst,
+ { "Destination", "tr.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Destination Hardware Address", HFILL }},
+
+ { &hf_tr_src,
+ { "Source", "tr.src", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Source Hardware Address", HFILL }},
+
+ { &hf_tr_addr,
+ { "Source or Destination Address", "tr.addr", FT_ETHER, BASE_NONE, NULL, 0x0,
+ "Source or Destination Hardware Address", HFILL }},
+
+ { &hf_tr_sr,
+ { "Source Routed", "tr.sr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Source Routed", HFILL }},
+
+ { &hf_tr_rif_bytes,
+ { "RIF Bytes", "tr.rif_bytes", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of bytes in Routing Information Fields, including "
+ "the two bytes of Routing Control Field", HFILL }},
+
+ { &hf_tr_broadcast,
+ { "Broadcast Type", "tr.broadcast", FT_UINT8, BASE_DEC, VALS(broadcast_vals), 0x0,
+ "Type of Token-Ring Broadcast", HFILL }},
+
+ { &hf_tr_max_frame_size,
+ { "Maximum Frame Size", "tr.max_frame_size", FT_UINT8, BASE_DEC, VALS(max_frame_size_vals),
+ 0x0,
+ "", HFILL }},
+
+ { &hf_tr_direction,
+ { "Direction", "tr.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
+ "Direction of RIF", HFILL }},
+
+ { &hf_tr_rif,
+ { "Ring-Bridge Pairs", "tr.rif", FT_STRING, BASE_NONE, NULL, 0x0,
+ "String representing Ring-Bridge Pairs", HFILL }},
+
+ { &hf_tr_rif_ring,
+ { "RIF Ring", "tr.rif.ring", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_tr_rif_bridge,
+ { "RIF Bridge", "tr.rif.bridge", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_token_ring,
+ &ett_token_ring_ac,
+ &ett_token_ring_fc,
+ };
+ module_t *tr_module;
+
+ proto_tr = proto_register_protocol("Token-Ring", "Token-Ring", "tr");
+ proto_register_field_array(proto_tr, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register configuration options */
+ tr_module = prefs_register_protocol(proto_tr, NULL);
+ prefs_register_bool_preference(tr_module, "fix_linux_botches",
+ "Attempt to compensate for Linux mangling of the link-layer header",
+ "Whether Linux mangling of the link-layer header should be checked for and worked around",
+ &fix_linux_botches);
+
+ register_dissector("tr", dissect_tr, proto_tr);
+ tr_tap=register_tap("tr");
+}
+
+void
+proto_reg_handoff_tr(void)
+{
+ dissector_handle_t tr_handle;
+
+ /*
+ * Get handles for the TR MAC and LLC dissectors.
+ */
+ trmac_handle = find_dissector("trmac");
+ llc_handle = find_dissector("llc");
+ data_handle = find_dissector("data");
+
+ tr_handle = find_dissector("tr");
+ dissector_add("wtap_encap", WTAP_ENCAP_TOKEN_RING, tr_handle);
+}
diff --git a/epan/dissectors/packet-tr.h b/epan/dissectors/packet-tr.h
new file mode 100644
index 0000000000..910bd4799c
--- /dev/null
+++ b/epan/dissectors/packet-tr.h
@@ -0,0 +1,36 @@
+/* packet-tr.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_TR_H__
+#define __PACKET_TR_H__
+
+typedef struct _tr_hdr {
+ guint8 ac;
+ guint8 fc;
+ address dst;
+ address src;
+} tr_hdr;
+
+void capture_tr(const guchar *, int, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-trmac.c b/epan/dissectors/packet-trmac.c
new file mode 100644
index 0000000000..42472b9866
--- /dev/null
+++ b/epan/dissectors/packet-trmac.c
@@ -0,0 +1,415 @@
+/* packet-trmac.c
+ * Routines for Token-Ring Media Access Control
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-frame.h"
+
+static int proto_trmac = -1;
+static int hf_trmac_mv = -1;
+static int hf_trmac_length = -1;
+static int hf_trmac_srcclass = -1;
+static int hf_trmac_dstclass = -1;
+static int hf_trmac_sv = -1;
+static int hf_trmac_errors_iso = -1;
+static int hf_trmac_errors_line = -1;
+static int hf_trmac_errors_internal = -1;
+static int hf_trmac_errors_burst = -1;
+static int hf_trmac_errors_ac = -1;
+static int hf_trmac_errors_abort = -1;
+static int hf_trmac_errors_noniso = -1;
+static int hf_trmac_errors_lost = -1;
+static int hf_trmac_errors_congestion = -1;
+static int hf_trmac_errors_fc = -1;
+static int hf_trmac_errors_freq = -1;
+static int hf_trmac_errors_token = -1;
+static int hf_trmac_naun = -1;
+
+static gint ett_tr_mac = -1;
+static gint ett_tr_ierr_cnt = -1;
+static gint ett_tr_nerr_cnt = -1;
+
+/* Major Vector */
+static value_string major_vector_vs[] = {
+ { 0x00, "Response" },
+ { 0x02, "Beacon" },
+ { 0x03, "Claim Token" },
+ { 0x04, "Ring Purge" },
+ { 0x05, "Active Monitor Present" },
+ { 0x06, "Standby Monitor Present" },
+ { 0x07, "Duplicate Address Test" },
+ { 0x09, "Transmit Forward" },
+ { 0x0B, "Remove Ring Station" },
+ { 0x0C, "Change Parameters" },
+ { 0x0D, "Initialize Ring Station" },
+ { 0x0E, "Request Ring Station Address" },
+ { 0x0F, "Request Ring Station Address" },
+ { 0x10, "Request Ring Station Attachments" },
+ { 0x20, "Request Initialization" },
+ { 0x22, "Report Ring Station Address" },
+ { 0x23, "Report Ring Station State" },
+ { 0x24, "Report Ring Station Attachments" },
+ { 0x25, "Report New Active Monitor" },
+ { 0x26, "Report NAUN Change" },
+ { 0x27, "Report Poll Error" },
+ { 0x28, "Report Monitor Errors" },
+ { 0x29, "Report Error" },
+ { 0x2A, "Report Transmit Forward" },
+ { 0x00, NULL }
+};
+
+/* Src. and Dest. Classes */
+static value_string classes_vs[] = {
+ { 0x00, "Ring Station" },
+ { 0x01, "LLC Manager" },
+ { 0x04, "Configuration Report Server" },
+ { 0x05, "Ring Parameter Server" },
+ { 0x06, "Ring Error Monitor" },
+ { 0x00, NULL }
+};
+
+
+/* Sub-vectors */
+static int
+sv_text(tvbuff_t *tvb, int svoff, proto_tree *tree)
+{
+ int sv_length = tvb_get_guint8(tvb, svoff+0);
+ guint16 beacon_type, ring;
+
+ char *beacon[] = {"Recovery mode set", "Signal loss error",
+ "Streaming signal not Claim Token MAC frame",
+ "Streaming signal, Claim Token MAC frame"};
+
+ proto_tree *sv_tree;
+ proto_item *ti;
+
+ guchar errors[6]; /* isolating or non-isolating */
+
+ /* Check the SV length.
+ XXX - Should we do this in each case statement below, e.g. to force
+ an SV length of 6 for the NAUN address? */
+ if (sv_length < 1) {
+ proto_tree_add_protocol_format(tree, proto_malformed, tvb, svoff+0, 1,
+ "Invalid subvector length: %d bytes", sv_length);
+ return sv_length;
+ }
+
+ /* this just adds to the clutter on the screen...
+ proto_tree_add_text(tree, tvb, svoff, 1,
+ "Subvector Length: %d bytes", sv_length);*/
+
+ proto_tree_add_uint_hidden(tree, hf_trmac_sv, tvb, svoff+1, 1, tvb_get_guint8(tvb, svoff+1));
+
+ switch(tvb_get_guint8(tvb, svoff+1)) {
+ case 0x01: /* Beacon Type */
+ beacon_type = tvb_get_ntohs(tvb, svoff+2);
+ if (beacon_type < array_length(beacon)) {
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Beacon Type: %s", beacon[beacon_type] );
+ } else {
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Beacon Type: Illegal value: %d", beacon_type );
+ }
+ break;
+
+ case 0x02: /* NAUN */
+ proto_tree_add_ether(tree, hf_trmac_naun, tvb, svoff+1, sv_length-1,
+ tvb_get_ptr(tvb, svoff+2, 6));
+ break;
+
+ case 0x03: /* Local Ring Number */
+ ring = tvb_get_ntohs(tvb, svoff+2);
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Local Ring Number: 0x%04X (%d)", ring, ring);
+ break;
+
+ case 0x04: /* Assign Physical Location */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Assign Physical Location: 0x%08X", tvb_get_ntohl(tvb, svoff+2) );
+ break;
+
+ case 0x05: /* Soft Error Report Value */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Soft Error Report Value: %d ms", 10 * tvb_get_ntohs(tvb, svoff+2) );
+ break;
+
+ case 0x06: /* Enabled Function Classes */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Enabled Function Classes: %04X", tvb_get_ntohs(tvb, svoff+2) );
+ break;
+
+ case 0x07: /* Allowed Access Priority */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Allowed Access Priority: %04X", tvb_get_ntohs(tvb, svoff+2) );
+ break;
+
+ case 0x09: /* Correlator */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Correlator: %04X", tvb_get_ntohs(tvb, svoff+2) );
+ break;
+
+ case 0x0A: /* Address of last neighbor notification */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Address of Last Neighbor Notification: %s",
+ ether_to_str(tvb_get_ptr(tvb, svoff+2, 6)));
+ break;
+
+ case 0x0B: /* Physical Location */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Physical Location: 0x%08X", tvb_get_ntohl(tvb, svoff+2) );
+ break;
+
+ case 0x20: /* Response Code */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Response Code: 0x%04X 0x%04X", tvb_get_ntohl(tvb, svoff+2),
+ tvb_get_ntohl(tvb, svoff+4) );
+ break;
+
+ case 0x21: /* Reserved */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Reserved: 0x%04X", tvb_get_ntohs(tvb, svoff+2) );
+ break;
+
+ case 0x22: /* Product Instance ID */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Product Instance ID: ...");
+ break;
+
+ case 0x23: /* Ring Station Microcode Level */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Ring Station Microcode Level: ...");
+ break;
+
+ case 0x26: /* Wrap data */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Wrap Data: ... (%d bytes)", sv_length - 2);
+ break;
+
+ case 0x27: /* Frame Forward */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Frame Forward: ... (%d bytes)", sv_length - 2);
+ break;
+
+ case 0x29: /* Ring Station Status Subvector */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Ring Station Status Subvector: ...");
+ break;
+
+ case 0x2A: /* Transmit Status Code */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Transmit Status Code: %04X", tvb_get_ntohs(tvb, svoff+2) );
+ break;
+
+ case 0x2B: /* Group Address */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Group Address: %08X", tvb_get_ntohl(tvb, svoff+2) );
+ break;
+
+ case 0x2C: /* Functional Address */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Functional Address: %08X", tvb_get_ntohl(tvb, svoff+2) );
+ break;
+
+ case 0x2D: /* Isolating Error Counts */
+ memcpy(errors, tvb_get_ptr(tvb, svoff+2, 6), 6);
+ ti = proto_tree_add_uint(tree, hf_trmac_errors_iso, tvb, svoff+1, sv_length-1,
+ errors[0] + errors[1] + errors[2] + errors[3] + errors[4]);
+ sv_tree = proto_item_add_subtree(ti, ett_tr_ierr_cnt);
+
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_line, tvb, svoff+2, 1, errors[0]);
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_internal, tvb, svoff+3, 1, errors[1]);
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_burst, tvb, svoff+4, 1, errors[2]);
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_ac, tvb, svoff+5, 1, errors[3]);
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_abort, tvb, svoff+6, 1, errors[4]);
+
+ break;
+
+ case 0x2E: /* Non-Isolating Error Counts */
+ memcpy(errors, tvb_get_ptr(tvb, svoff+2, 6), 6);
+ ti = proto_tree_add_uint(tree, hf_trmac_errors_noniso, tvb, svoff+1, sv_length-1,
+ errors[0] + errors[1] + errors[2] + errors[3] + errors[4]);
+ sv_tree = proto_item_add_subtree(ti, ett_tr_nerr_cnt);
+
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_lost, tvb, svoff+2, 1, errors[0]);
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_congestion, tvb, svoff+3, 1, errors[1]);
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_fc, tvb, svoff+4, 1, errors[2]);
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_freq, tvb, svoff+5, 1, errors[3]);
+ proto_tree_add_uint(sv_tree, hf_trmac_errors_token, tvb, svoff+6, 1, errors[4]);
+ break;
+
+ case 0x30: /* Error Code */
+ proto_tree_add_text(tree, tvb, svoff+1, sv_length-1,
+ "Error Code: %04X", tvb_get_ntohs(tvb, svoff+2) );
+ break;
+
+ default: /* Unknown */
+ proto_tree_add_text(tree, tvb, svoff+1, 1,
+ "Unknown Sub-Vector: 0x%02X", tvb_get_guint8(tvb, svoff+1));
+ }
+ return sv_length;
+}
+
+static void
+dissect_trmac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *mac_tree = NULL;
+ proto_item *ti;
+ int mv_length, sv_offset, sv_additional;
+ guint8 mv_val;
+ char *mv_text;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TR MAC");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ mv_val = tvb_get_guint8(tvb, 3);
+
+ /* Interpret the major vector */
+ mv_text = val_to_str(mv_val, major_vector_vs, "Unknown Major Vector: %u");
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, mv_text);
+
+ if (tree) {
+ mv_length = tvb_get_ntohs(tvb, 0);
+ ti = proto_tree_add_item(tree, proto_trmac, tvb, 0, mv_length, FALSE);
+ mac_tree = proto_item_add_subtree(ti, ett_tr_mac);
+
+ proto_tree_add_uint(mac_tree, hf_trmac_mv, tvb, 3, 1, mv_val);
+ proto_tree_add_uint_format(mac_tree, hf_trmac_length, tvb, 0, 2, mv_length,
+ "Total Length: %d bytes", mv_length);
+ proto_tree_add_uint(mac_tree, hf_trmac_srcclass, tvb, 2, 1, tvb_get_guint8(tvb, 2) & 0x0f);
+ proto_tree_add_uint(mac_tree, hf_trmac_dstclass, tvb, 2, 1, tvb_get_guint8(tvb, 2) >> 4 );
+
+ /* interpret the subvectors */
+ sv_offset = 4;
+ while (sv_offset < mv_length) {
+ sv_additional = sv_text(tvb, sv_offset, mac_tree);
+
+ /* if this is a bad packet, we could get a 0-length added here,
+ * looping forever */
+ if (sv_additional > 0)
+ sv_offset += sv_additional;
+ else
+ break;
+ }
+ }
+}
+
+void
+proto_register_trmac(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_trmac_mv,
+ { "Major Vector", "trmac.mvec", FT_UINT8, BASE_HEX, major_vector_vs, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_length,
+ { "Total Length", "trmac.length", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_srcclass,
+ { "Source Class", "trmac.srcclass", FT_UINT8, BASE_HEX, classes_vs, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_dstclass,
+ { "Destination Class", "trmac.dstclass", FT_UINT8, BASE_HEX, classes_vs, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_sv,
+ { "Sub-Vector", "trmac.svec", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_iso,
+ { "Isolating Errors", "trmac.errors.iso", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_line,
+ { "Line Errors", "trmac.errors.line", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_internal,
+ { "Internal Errors", "trmac.errors.internal", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_burst,
+ { "Burst Errors", "trmac.errors.burst", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_ac,
+ { "A/C Errors", "trmac.errors.ac", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_abort,
+ { "Abort Delimiter Transmitted Errors", "trmac.errors.abort", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_noniso,
+ { "Non-Isolating Errors", "trmac.errors.noniso", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_lost,
+ { "Lost Frame Errors", "trmac.errors.lost", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_congestion,
+ { "Receiver Congestion Errors", "trmac.errors.congestion", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_fc,
+ { "Frame-Copied Errors", "trmac.errors.fc", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_freq,
+ { "Frequency Errors", "trmac.errors.freq", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_errors_token,
+ { "Token Errors", "trmac.errors.token", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_trmac_naun,
+ { "NAUN", "trmac.naun", FT_ETHER, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_tr_mac,
+ &ett_tr_ierr_cnt,
+ &ett_tr_nerr_cnt,
+ };
+
+ proto_trmac = proto_register_protocol("Token-Ring Media Access Control",
+ "TR MAC", "trmac");
+ proto_register_field_array(proto_trmac, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("trmac", dissect_trmac, proto_trmac);
+}
diff --git a/epan/dissectors/packet-tsp.c b/epan/dissectors/packet-tsp.c
new file mode 100644
index 0000000000..1673712f0b
--- /dev/null
+++ b/epan/dissectors/packet-tsp.c
@@ -0,0 +1,227 @@
+/* packet-quake.c
+ * Routines for Time Synchronization Protocol (TSP) packet dissection
+ *
+ * Uwe Girlich <Uwe.Girlich@philosys.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-quake.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+
+/*
+ * For a full documentation of the Time Synchronization Protocol (TSP) see:
+ * http://docs.freebsd.org/44doc/smm/12.timed/paper.pdf
+ */
+
+static int proto_tsp = -1;
+static int hf_tsp_type = -1;
+static int hf_tsp_vers = -1;
+static int hf_tsp_seq = -1;
+static int hf_tsp_hopcnt = -1;
+static int hf_tsp_time_sec = -1;
+static int hf_tsp_time_usec = -1;
+static int hf_tsp_name = -1;
+
+static gint ett_tsp = -1;
+
+static dissector_handle_t tsp_handle;
+
+
+/* timed port from /etc/services */
+#define UDP_PORT_TIMED 525
+
+
+static const value_string names_tsp_type[] = {
+#define TSP_ANY 0 /* match any types */
+ { TSP_ANY, "any" },
+#define TSP_ADJTIME 1 /* send adjtime */
+ { TSP_ADJTIME, "adjtime" },
+#define TSP_ACK 2 /* generic acknowledgement */
+ { TSP_ACK, "ack" },
+#define TSP_MASTERREQ 3 /* ask for master's name */
+ { TSP_MASTERREQ, "masterreq" },
+#define TSP_MASTERACK 4 /* acknowledge master request */
+ { TSP_MASTERACK, "masterack" },
+#define TSP_SETTIME 5 /* send network time */
+ { TSP_SETTIME, "settime" },
+#define TSP_MASTERUP 6 /* inform slaves that master is up */
+ { TSP_MASTERUP, "masterup" },
+#define TSP_SLAVEUP 7 /* slave is up but not polled */
+ { TSP_SLAVEUP, "slaveup" },
+#define TSP_ELECTION 8 /* advance candidature for master */
+ { TSP_ELECTION, "election" },
+#define TSP_ACCEPT 9 /* support candidature of master */
+ { TSP_ACCEPT, "accept" },
+#define TSP_REFUSE 10 /* reject candidature of master */
+ { TSP_REFUSE, "refuse" },
+#define TSP_CONFLICT 11 /* two or more masters present */
+ { TSP_CONFLICT, "conflict" },
+#define TSP_RESOLVE 12 /* masters' conflict resolution */
+ { TSP_RESOLVE, "resolve" },
+#define TSP_QUIT 13 /* reject candidature if master is up */
+ { TSP_QUIT, "quit" },
+#define TSP_DATE 14 /* reset the time (date command) */
+ { TSP_DATE, "date" },
+#define TSP_DATEREQ 15 /* remote request to reset the time */
+ { TSP_DATEREQ, "datereq" },
+#define TSP_DATEACK 16 /* acknowledge time setting */
+ { TSP_DATEACK, "dateack" },
+#define TSP_TRACEON 17 /* turn tracing on */
+ { TSP_TRACEON, "traceon" },
+#define TSP_TRACEOFF 18 /* turn tracing off */
+ { TSP_TRACEOFF, "traceoff" },
+#define TSP_MSITE 19 /* find out master's site */
+ { TSP_MSITE, "msite" },
+#define TSP_MSITEREQ 20 /* remote master's site request */
+ { TSP_MSITEREQ, "msitereq" },
+#define TSP_TEST 21 /* for testing election algo */
+ { TSP_TEST, "test" },
+#define TSP_SETDATE 22 /* New from date command */
+ { TSP_SETDATE, "setdate" },
+#define TSP_SETDATEREQ 23 /* New remote for above */
+ { TSP_SETDATEREQ, "setdatereq" },
+#define TSP_LOOP 24 /* loop detection packet */
+ { TSP_LOOP, "loop" },
+ { 0, NULL }
+};
+
+
+static void
+dissect_tsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *tsp_tree = NULL;
+ proto_item *tsp_item = NULL;
+
+ guint8 tsp_type;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TSP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tsp_type = tvb_get_guint8(tvb, 0);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(tsp_type, names_tsp_type, "Unknown message type (%u)"));
+
+ if (tree) {
+ tsp_item = proto_tree_add_item(tree, proto_tsp,
+ tvb, 0, -1, FALSE);
+ if (tsp_item)
+ tsp_tree = proto_item_add_subtree(tsp_item, ett_tsp);
+ }
+
+ if (tsp_tree) {
+ proto_tree_add_uint(tsp_tree, hf_tsp_type,
+ tvb, 0, 1, tsp_type);
+ proto_tree_add_item(tsp_tree, hf_tsp_vers,
+ tvb, 1, 1, FALSE);
+ proto_tree_add_item(tsp_tree, hf_tsp_seq,
+ tvb, 2, 2, FALSE);
+ }
+
+ switch (tsp_type) {
+
+ case TSP_LOOP:
+ if (tsp_tree)
+ proto_tree_add_item(tsp_tree, hf_tsp_hopcnt,
+ tvb, 4, 1, FALSE);
+ break;
+
+ case TSP_SETTIME:
+ case TSP_ADJTIME:
+ case TSP_SETDATE:
+ case TSP_SETDATEREQ:
+ if (tsp_tree) {
+ proto_tree_add_item(tsp_tree, hf_tsp_time_sec,
+ tvb, 4, 4, FALSE);
+ proto_tree_add_item(tsp_tree, hf_tsp_time_usec,
+ tvb, 8, 4, FALSE);
+ }
+ break;
+ }
+
+ if (tsp_tree) {
+ proto_tree_add_item(tsp_tree, hf_tsp_name, tvb, 12,
+ -1, FALSE);
+ }
+}
+
+
+void
+proto_reg_handoff_tsp(void)
+{
+ dissector_add("udp.port", UDP_PORT_TIMED, tsp_handle);
+}
+
+
+void
+proto_register_tsp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tsp_type,
+ { "Type", "tsp.type",
+ FT_UINT8, BASE_DEC, VALS(names_tsp_type), 0x0,
+ "Packet Type", HFILL }},
+ { &hf_tsp_vers,
+ { "Version", "tsp.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Protocol Version Number", HFILL }},
+ { &hf_tsp_seq,
+ { "Sequence", "tsp.sequence",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Sequence Number", HFILL }},
+ { &hf_tsp_hopcnt,
+ { "Hop Count", "tsp.hopcnt",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Hop Count", HFILL }},
+ { &hf_tsp_time_sec,
+ { "Seconds", "tsp.sec",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Seconds", HFILL }},
+ { &hf_tsp_time_usec,
+ { "Microseconds", "tsp.usec",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Microseconds", HFILL }},
+ { &hf_tsp_name,
+ { "Machine Name", "tsp.name",
+ FT_STRINGZ, BASE_DEC, NULL, 0x0,
+ "Sender Machine Name", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_tsp
+ };
+
+ proto_tsp = proto_register_protocol("Time Synchronization Protocol",
+ "TSP", "tsp");
+ proto_register_field_array(proto_tsp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ tsp_handle = create_dissector_handle(dissect_tsp, proto_tsp);
+}
+
diff --git a/epan/dissectors/packet-tuxedo.c b/epan/dissectors/packet-tuxedo.c
new file mode 100644
index 0000000000..8144643694
--- /dev/null
+++ b/epan/dissectors/packet-tuxedo.c
@@ -0,0 +1,199 @@
+/* packet-tuxedo.c
+ * Routines for BEA Tuxedo ATMI protocol
+ *
+ * metatech <metatech@flashmail.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+static int proto_tuxedo = -1;
+static int hf_tuxedo_magic = -1;
+static int hf_tuxedo_opcode = -1;
+
+static gint ett_tuxedo = -1;
+
+static dissector_handle_t tuxedo_handle;
+
+#define TUXEDO_MAGIC 0x91039858
+#define TUXEDO_SMAGIC 0x73903842
+
+#define TUXEDO_ATMI_CALL 1
+#define TUXEDO_ATMI_REPLY 2
+#define TUXEDO_ATMI_FAILURE 3
+#define TUXEDO_ATMI_CONNECT 4
+#define TUXEDO_ATMI_DATA 5
+#define TUXEDO_ATMI_DISCON 6
+#define TUXEDO_ATMI_PREPARE 7
+#define TUXEDO_ATMI_READY 8
+#define TUXEDO_ATMI_COMMIT 9
+#define TUXEDO_ATMI_DONE 10
+#define TUXEDO_ATMI_COMPLETE 11
+#define TUXEDO_ATMI_ROLLBACK 12
+#define TUXEDO_ATMI_HEURISTIC 13
+#define TUXEDO_ATMI_PRE_NW_ACALL1 14
+#define TUXEDO_ATMI_PRE_NW_ACALL1_RPLY 15
+#define TUXEDO_ATMI_PRE_NW_ACALL2 16
+#define TUXEDO_ATMI_PRE_NW_ACALL2_RPLY 17
+#define TUXEDO_ATMI_PRE_NW_ACALL3 18
+#define TUXEDO_ATMI_PRE_NW_ACALL3_RPLY 19
+#define TUXEDO_ATMI_PRE_NW_LLE 20
+#define TUXEDO_ATMI_PRE_NW_LLE_RPLY 21
+#define TUXEDO_ATMI_SEC_EXCHG_RQST 22
+#define TUXEDO_ATMI_SEC_EXCHG_RPLY 23
+#define TUXEDO_ATMI_SEC_NW_ACALL3 24
+#define TUXEDO_ATMI_SEC_NW_ACALL3_RPLY 25
+
+
+static const value_string tuxedo_opcode_vals[] = {
+ { TUXEDO_ATMI_CALL, "CALL" },
+ { TUXEDO_ATMI_REPLY, "REPLY" },
+ { TUXEDO_ATMI_FAILURE, "FAILURE" },
+ { TUXEDO_ATMI_CONNECT, "CONNECT" },
+ { TUXEDO_ATMI_DATA, "DATA" },
+ { TUXEDO_ATMI_DISCON, "DISCON" },
+ { TUXEDO_ATMI_PREPARE, "PREPARE" },
+ { TUXEDO_ATMI_READY, "READY" },
+ { TUXEDO_ATMI_COMMIT, "COMMIT" },
+ { TUXEDO_ATMI_DONE, "DONE" },
+ { TUXEDO_ATMI_COMPLETE, "COMPLETE" },
+ { TUXEDO_ATMI_ROLLBACK, "ROLLBACK" },
+ { TUXEDO_ATMI_HEURISTIC, "HEURISTIC" },
+ { TUXEDO_ATMI_PRE_NW_ACALL1, "ACALL1" },
+ { TUXEDO_ATMI_PRE_NW_ACALL1_RPLY, "ACALL1_REPLY" },
+ { TUXEDO_ATMI_PRE_NW_ACALL2, "ACALL2" },
+ { TUXEDO_ATMI_PRE_NW_ACALL2_RPLY, "ACALL2_REPLY" },
+ { TUXEDO_ATMI_PRE_NW_ACALL3, "ACALL3" },
+ { TUXEDO_ATMI_PRE_NW_ACALL3_RPLY, "ACALL3_REPLY" },
+ { TUXEDO_ATMI_PRE_NW_LLE, "LLE" },
+ { TUXEDO_ATMI_PRE_NW_LLE_RPLY, "LLE_REPLY" },
+ { TUXEDO_ATMI_SEC_EXCHG_RQST, "SEC_EXCHANGE" },
+ { TUXEDO_ATMI_SEC_EXCHG_RPLY, "SEC_EXCHANGE_REPLY" },
+ { TUXEDO_ATMI_SEC_NW_ACALL3, "SEC_ACALL3" },
+ { TUXEDO_ATMI_SEC_NW_ACALL3_RPLY, "SEC_ACALL3_REPLY" },
+ { 0, NULL }
+};
+
+
+static void
+dissect_tuxedo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *tuxedoroot_tree = NULL;
+ proto_item *ti;
+ guint32 magic;
+ guint32 opcode;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "TUXEDO");
+
+ if (tvb_length(tvb) >= 8)
+ {
+ magic = tvb_get_ntohl(tvb, 0);
+ if (magic == TUXEDO_MAGIC || magic == TUXEDO_SMAGIC)
+ {
+ opcode = tvb_get_ntohl(tvb, 4);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(opcode, tuxedo_opcode_vals, "Unknown (0x%02x)"));
+ }
+
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_tuxedo, tvb, 0, -1, FALSE);
+ tuxedoroot_tree = proto_item_add_subtree(ti, ett_tuxedo);
+
+ proto_tree_add_item(tuxedoroot_tree, hf_tuxedo_magic, tvb, 0, 4, FALSE);
+ proto_tree_add_item(tuxedoroot_tree, hf_tuxedo_opcode, tvb, 4, 4, FALSE);
+ }
+ }
+ else
+ {
+ /* This packet is a continuation */
+ if (check_col(pinfo->cinfo, COL_INFO)) col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+ if (tree)
+ {
+ ti = proto_tree_add_item(tree, proto_tuxedo, tvb, 0, -1, FALSE);
+ }
+ }
+ }
+}
+
+static gboolean
+dissect_tuxedo_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (tvb_length(tvb) >= 8)
+ {
+ guint32 magic;
+ magic = tvb_get_ntohl(tvb, 0);
+ if (magic == TUXEDO_MAGIC || magic == TUXEDO_SMAGIC)
+ {
+ /* Register this dissector for this conversation */
+ conversation_t *conversation = NULL;
+ conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL)
+ {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+ conversation_set_dissector(conversation, tuxedo_handle);
+
+ dissect_tuxedo(tvb, pinfo, tree);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void
+proto_register_tuxedo(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_tuxedo_magic,
+ { "Magic", "tuxedo.magic", FT_UINT32, BASE_HEX, NULL, 0x0, "TUXEDO magic", HFILL }},
+
+ { &hf_tuxedo_opcode,
+ { "Opcode", "tuxedo.opcode", FT_UINT32, BASE_HEX, VALS(tuxedo_opcode_vals), 0x0, "TUXEDO opcode", HFILL }}
+
+ };
+ static gint *ett[] = {
+ &ett_tuxedo,
+ };
+
+ proto_tuxedo = proto_register_protocol("BEA Tuxedo", "TUXEDO", "tuxedo");
+ proto_register_field_array(proto_tuxedo, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ tuxedo_handle = create_dissector_handle(dissect_tuxedo, proto_tuxedo);
+
+}
+
+void
+proto_reg_handoff_tuxedo(void)
+{
+ heur_dissector_add("tcp", dissect_tuxedo_heur, proto_tuxedo);
+ dissector_add_handle("tcp.port", tuxedo_handle);
+}
diff --git a/epan/dissectors/packet-tzsp.c b/epan/dissectors/packet-tzsp.c
new file mode 100644
index 0000000000..b7db2431e8
--- /dev/null
+++ b/epan/dissectors/packet-tzsp.c
@@ -0,0 +1,521 @@
+/* packet-tzsp.c
+ *
+ * $Id$
+ *
+ * Copyright 2002, Tazmen Technologies Inc
+ *
+ * Tazmen Sniffer Protocol for encapsulating the packets across a network
+ * from a remote packet sniffer. TZSP can encapsulate any other protocol.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#define UDP_PORT_TZSP 0x9090
+
+static int proto_tzsp = -1;
+static int hf_tzsp_version = -1;
+static int hf_tzsp_type = -1;
+static int hf_tzsp_encap = -1;
+
+static const value_string tzsp_type[] = {
+ {0, "Received tag list"},
+ {1, "Packet for transmit"},
+ {2, "Reserved"},
+ {3, "Configuration"},
+ {4, "Keepalive"},
+ {5, "Port opener"},
+ {0, NULL}
+};
+
+static gint ett_tzsp = -1;
+
+static dissector_handle_t data_handle;
+static dissector_table_t encap_dissector_table;
+
+/* ************************************************************************* */
+/* WLAN radio header felds */
+/* ************************************************************************* */
+
+static int hf_status_field = -1;
+static int hf_status_msg_type = -1;
+static int hf_status_pcf = -1;
+static int hf_status_mac_port = -1;
+static int hf_status_undecrypted = -1;
+static int hf_status_fcs_error = -1;
+
+static int hf_time = -1;
+static int hf_silence = -1;
+static int hf_signal = -1;
+static int hf_rate = -1;
+static int hf_channel = -1;
+static int hf_unknown = -1;
+static int hf_original_length = -1;
+static int hf_sensormac = -1;
+
+/* ************************************************************************* */
+/* Encapsulation type values */
+/* Note that these are not all the same as DLT_ values */
+/* ************************************************************************* */
+
+#define TZSP_ENCAP_ETHERNET 1
+#define TZSP_ENCAP_IEEE_802_11 18
+#define TZSP_ENCAP_PRISM_HEADER 119
+#define TZSP_ENCAP_WLAN_AVS 127
+
+/* ************************************************************************* */
+/* Generic header options */
+/* ************************************************************************* */
+
+#define TZSP_HDR_PAD 0 /* Pad. */
+#define TZSP_HDR_END 1 /* End of the list. */
+#define TZSP_HDR_ORIGINAL_LENGTH 41 /* Length of the packet before slicing. 2 bytes. */
+#define TZSP_HDR_SENSOR 60 /* Sensor MAC address packet was received on, 6 byte ethernet address.*/
+
+/* ************************************************************************* */
+/* Options for 802.11 radios */
+/* ************************************************************************* */
+
+#define WLAN_RADIO_HDR_SIGNAL 10 /* Signal strength in dBm, signed byte. */
+#define WLAN_RADIO_HDR_NOISE 11 /* Noise level in dBm, signed byte. */
+#define WLAN_RADIO_HDR_RATE 12 /* Data rate, unsigned byte. */
+#define WLAN_RADIO_HDR_TIMESTAMP 13 /* Timestamp in us, unsigned 32-bits network byte order. */
+#define WLAN_RADIO_HDR_MSG_TYPE 14 /* Packet type, unsigned byte. */
+#define WLAN_RADIO_HDR_CF 15 /* Whether packet arrived during CF period, unsigned byte. */
+#define WLAN_RADIO_HDR_UN_DECR 16 /* Whether packet could not be decrypted by MAC, unsigned byte. */
+#define WLAN_RADIO_HDR_FCS_ERR 17 /* Whether packet contains an FCS error, unsigned byte. */
+#define WLAN_RADIO_HDR_CHANNEL 18 /* Channel number packet was received on, unsigned byte.*/
+
+/* ************************************************************************* */
+/* Add option information to the display */
+/* ************************************************************************* */
+
+static int
+add_option_info(tvbuff_t *tvb, int pos, proto_tree *tree, proto_item *ti)
+{
+ guint8 tag, length, fcs_err = 0, encr = 0, seen_fcs_err = 0;
+
+ /*
+ * Read all option tags in an endless loop. If the packet is malformed this
+ * loop might be a problem.
+ */
+ while (TRUE) {
+ tag = tvb_get_guint8(tvb, pos++);
+
+ switch (tag) {
+ case TZSP_HDR_PAD:
+ length = 0;
+ break;
+
+ case TZSP_HDR_END:
+ /* Fill in header with information from other tags. */
+ if (seen_fcs_err) {
+ if (tree)
+ proto_item_append_text(ti,"%s", fcs_err?"FCS Error":(encr?"Encrypted":"Good"));
+ }
+ return pos;
+
+ case TZSP_HDR_ORIGINAL_LENGTH:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_int (tree, hf_original_length, tvb, pos-2, 4,
+ tvb_get_ntohs(tvb, pos));
+ pos += length;
+ break;
+
+ case WLAN_RADIO_HDR_SIGNAL:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_int (tree, hf_signal, tvb, pos-2, 3,
+ tvb_get_ntohs(tvb, pos));
+ pos += length;
+ break;
+
+ case WLAN_RADIO_HDR_NOISE:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_int (tree, hf_silence, tvb, pos-2, 3,
+ tvb_get_ntohs(tvb, pos));
+ pos += length;
+ break;
+
+ case WLAN_RADIO_HDR_RATE:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_uint (tree, hf_rate, tvb, pos-2, 3,
+ tvb_get_guint8(tvb, pos));
+ pos += length;
+ break;
+
+ case WLAN_RADIO_HDR_TIMESTAMP:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_uint (tree, hf_time, tvb, pos-2, 6,
+ tvb_get_ntohl(tvb, pos));
+ pos += length;
+ break;
+
+ case WLAN_RADIO_HDR_MSG_TYPE:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_uint (tree, hf_status_msg_type, tvb, pos-2, 3,
+ tvb_get_guint8(tvb, pos));
+ pos += length;
+ break;
+
+ case WLAN_RADIO_HDR_CF:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_boolean (tree, hf_status_pcf, tvb, pos-2, 3,
+ tvb_get_guint8(tvb, pos));
+ pos += length;
+ break;
+
+ case WLAN_RADIO_HDR_UN_DECR:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_boolean (tree, hf_status_undecrypted, tvb, pos-2, 3,
+ tvb_get_guint8(tvb, pos));
+ encr = tvb_get_guint8(tvb, pos);
+ pos += length;
+ break;
+
+ case WLAN_RADIO_HDR_FCS_ERR:
+ seen_fcs_err = 1;
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_boolean (tree, hf_status_fcs_error, tvb, pos-2, 3,
+ tvb_get_guint8(tvb, pos));
+ fcs_err = tvb_get_guint8(tvb, pos);
+ pos += length;
+ break;
+
+ case WLAN_RADIO_HDR_CHANNEL:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_uint (tree, hf_channel, tvb, pos-2, 3,
+ tvb_get_guint8(tvb, pos));
+ pos += length;
+ break;
+
+ case TZSP_HDR_SENSOR:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_ether(tree, hf_sensormac, tvb, pos-2, 6,
+ tvb_get_ptr (tvb, pos, 6));
+ pos += length;
+ break;
+
+ default:
+ length = tvb_get_guint8(tvb, pos++);
+ if (tree)
+ proto_tree_add_bytes(tree, hf_unknown, tvb, pos-2, length+2,
+ tvb_get_ptr(tvb, pos, length));
+ pos += length;
+ break;
+ }
+ }
+}
+
+/* ************************************************************************* */
+/* Map TZSP encapsulation types to Wiretap encapsulation types */
+/* ************************************************************************* */
+struct encap_map {
+ guint16 tzsp_encap;
+ int wtap_encap;
+};
+
+static const struct encap_map map_table[] = {
+ { TZSP_ENCAP_ETHERNET, WTAP_ENCAP_ETHERNET },
+ { TZSP_ENCAP_PRISM_HEADER, WTAP_ENCAP_PRISM_HEADER },
+ { TZSP_ENCAP_WLAN_AVS, WTAP_ENCAP_IEEE_802_11_WLAN_AVS },
+ { TZSP_ENCAP_IEEE_802_11, WTAP_ENCAP_IEEE_802_11 },
+ { 0, -1 }
+};
+
+static int
+tzsp_encap_to_wtap_encap(guint16 encap)
+{
+ int i;
+
+ for (i = 0; map_table[i].wtap_encap != -1; i++) {
+ if (map_table[i].tzsp_encap == encap)
+ return map_table[i].wtap_encap;
+ }
+ return -1;
+}
+
+/* ************************************************************************* */
+/* Dissect a TZSP packet */
+/* ************************************************************************* */
+
+static void
+dissect_tzsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *tzsp_tree = NULL;
+ proto_item *ti = NULL;
+ int pos = 0;
+ tvbuff_t *next_tvb;
+ guint16 encapsulation = 0;
+ int wtap_encap;
+ dissector_handle_t encap_dissector;
+ char *encap_name, *info;
+ guint8 type;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TZSP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ type = tvb_get_guint8(tvb, 1);
+
+ /* Find the dissector. */
+ encapsulation = tvb_get_ntohs(tvb, 2);
+ if (encapsulation != 0) {
+ wtap_encap = tzsp_encap_to_wtap_encap(encapsulation);
+ if (wtap_encap != -1 &&
+ (encap_dissector = dissector_get_port_handle(encap_dissector_table, wtap_encap))) {
+ encap_name = dissector_handle_get_short_name(encap_dissector);
+ }
+ else {
+ encap_name = "Unknown";
+ }
+ info = encap_name;
+ }
+ else {
+ wtap_encap = -1;
+ encap_name = "Nothing";
+ info = tzsp_type[type].strptr;
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, info);
+
+ if (tree) {
+ /* Adding TZSP item and subtree */
+ ti = proto_tree_add_protocol_format(tree, proto_tzsp, tvb, 0,
+ -1, "TZSP: %s: ", info);
+ tzsp_tree = proto_item_add_subtree(ti, ett_tzsp);
+
+ proto_tree_add_item (tzsp_tree, hf_tzsp_version, tvb, 0, 1,
+ FALSE);
+ proto_tree_add_uint (tzsp_tree, hf_tzsp_type, tvb, 1, 1,
+ type);
+ proto_tree_add_uint_format (tzsp_tree, hf_tzsp_encap, tvb, 2, 2,
+ encapsulation, "Encapsulates: %s (%d)",
+ encap_name, encapsulation);
+ }
+
+ if (type != 4 && type != 5) {
+ pos = add_option_info(tvb, 4, tzsp_tree, ti);
+
+ if (tree)
+ proto_item_set_end(ti, tvb, pos);
+ next_tvb = tvb_new_subset(tvb, pos, -1, -1);
+ if (encapsulation != 0
+ && (wtap_encap == -1
+ || !dissector_try_port(encap_dissector_table, wtap_encap,
+ next_tvb, pinfo, tree))) {
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "TZSP_ENCAP = %u",
+ encapsulation);
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+ }
+}
+
+/* ************************************************************************* */
+/* Register the TZSP dissector */
+/* ************************************************************************* */
+
+void
+proto_register_tzsp(void)
+{
+ static const value_string msg_type[] = {
+ {0, "Normal"},
+ {1, "RFC1042 encoded"},
+ {2, "Bridge-tunnel encoded"},
+ {4, "802.11 management frame"},
+ {0, NULL}
+ };
+
+ static const true_false_string pcf_flag = {
+ "CF: Frame received during CF period",
+ "Not CF"
+ };
+
+ static const true_false_string undecr_flag = {
+ "Encrypted frame could not be decrypted",
+ "Unencrypted"
+ };
+
+ static const true_false_string fcs_err_flag = {
+ "FCS error, frame is corrupted",
+ "Frame is valid"
+ };
+
+ static const value_string channels[] = {
+ /* 802.11b/g */
+ {1, "1 (2.412 GHz)"},
+ {2, "2 (2.417 GHz)"},
+ {3, "3 (2.422 GHz)"},
+ {4, "4 (2.427 GHz)"},
+ {5, "5 (2.432 GHz)"},
+ {6, "6 (2.437 GHz)"},
+ {7, "7 (2.442 GHz)"},
+ {8, "8 (2.447 GHz)"},
+ {9, "9 (2.452 GHz)"},
+ {10, "10 (2.457 GHz)"},
+ {11, "11 (2.462 GHz)"},
+ {12, "12 (2.467 GHz)"},
+ {13, "13 (2.472 GHz)"},
+ {14, "14 (2.484 GHz)"},
+ /* 802.11a */
+ {36, "36 (5.180 GHz)"},
+ {40, "40 (5.200 GHz)"},
+ {44, "44 (5.220 GHz)"},
+ {48, "48 (5.240 GHz)"},
+ {52, "52 (5.260 GHz)"},
+ {56, "56 (5.280 GHz)"},
+ {60, "60 (5.300 GHz)"},
+ {64, "64 (5.320 GHz)"},
+ {149, "149 (5.745 GHz)"},
+ {153, "153 (5.765 GHz)"},
+ {157, "157 (5.785 GHz)"},
+ {161, "161 (5.805 GHz)"},
+ {0, NULL}
+ };
+
+ static const value_string rates[] = {
+ /* Old PRISM rates */
+ {0x0A, "1 Mbit/s"},
+ {0x14, "2 Mbit/s"},
+ {0x37, "5.5 Mbit/s"},
+ {0x6E, "11 Mbit/s"},
+ /* MicroAP rates */
+ {2, "1 Mbit/s"},
+ {4, "2 Mbit/s"},
+ {11, "5.5 Mbit/s"},
+ {12, "6 Mbit/s"},
+ {18, "9 Mbit/s"},
+ {22, "11 Mbit/s"},
+ {24, "12 Mbit/s"},
+ {36, "18 Mbit/s"},
+ {48, "24 Mbit/s"},
+ {72, "36 Mbit/s"},
+ {96, "48 Mbit/s"},
+ {108, "54 Mbit/s"},
+ {0, NULL}
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_tzsp_version, {
+ "Version", "tzsp.version", FT_UINT8, BASE_DEC,
+ NULL, 0, "Version", HFILL }},
+ { &hf_tzsp_type, {
+ "Type", "tzsp.type", FT_UINT8, BASE_DEC,
+ VALS(tzsp_type), 0, "Type", HFILL }},
+ { &hf_tzsp_encap, {
+ "Encapsulation", "tzsp.encap", FT_UINT16, BASE_DEC,
+ NULL, 0, "Encapsulation", HFILL }},
+ { &hf_status_field, {
+ "Status", "tzsp.wlan.status", FT_UINT16, BASE_HEX,
+ NULL, 0, "Status", HFILL }},
+ { &hf_status_msg_type, {
+ "Type", "tzsp.wlan.status.msg_type", FT_UINT8, BASE_HEX,
+ VALS(msg_type), 0, "Message type", HFILL }},
+ { &hf_status_mac_port, {
+ "Port", "tzsp.wlan.status.mac_port", FT_UINT8, BASE_DEC,
+ NULL, 0, "MAC port", HFILL }},
+ { &hf_status_pcf, {
+ "PCF", "tzsp.wlan.status.pcf", FT_BOOLEAN, BASE_HEX,
+ TFS (&pcf_flag), 0, "Point Coordination Function", HFILL }},
+ { &hf_status_undecrypted, {
+ "Undecrypted", "tzsp.wlan.status.undecrypted", FT_BOOLEAN, BASE_HEX,
+ TFS (&undecr_flag), 0, "Undecrypted", HFILL }},
+ { &hf_status_fcs_error, {
+ "FCS", "tzsp.wlan.status.fcs_err", FT_BOOLEAN, BASE_HEX,
+ TFS (&fcs_err_flag), 0, "Frame check sequence", HFILL }},
+ { &hf_time, {
+ "Time", "tzsp.wlan.time", FT_UINT32, BASE_HEX,
+ NULL, 0, "Time", HFILL }},
+ { &hf_silence, {
+ "Silence", "tzsp.wlan.silence", FT_INT8, BASE_HEX,
+ NULL, 0, "Silence", HFILL }},
+ { &hf_original_length, {
+ "Original Length", "tzsp.original_length", FT_INT16, BASE_DEC,
+ NULL, 0, "OrigLength", HFILL }},
+ { &hf_signal, {
+ "Signal", "tzsp.wlan.signal", FT_INT8, BASE_HEX,
+ NULL, 0, "Signal", HFILL }},
+ { &hf_rate, {
+ "Rate", "tzsp.wlan.rate", FT_UINT8, BASE_HEX,
+ VALS(rates), 0, "Rate", HFILL }},
+ { &hf_channel, {
+ "Channel", "tzsp.wlan.channel", FT_UINT8, BASE_DEC,
+ VALS(channels), 0, "Channel", HFILL }},
+ { &hf_unknown, {
+ "Unknown tag", "tzsp.unknown", FT_BYTES, BASE_HEX,
+ NULL, 0, "Unknown", HFILL }},
+ { &hf_sensormac, {
+ "Sensor Address", "tzsp.sensormac", FT_ETHER, BASE_HEX,
+ NULL, 0, "Sensor MAC", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_tzsp
+ };
+
+ proto_tzsp = proto_register_protocol("Tazmen Sniffer Protocol", "TZSP",
+ "tzsp");
+ proto_register_field_array(proto_tzsp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+void
+proto_reg_handoff_tzsp(void)
+{
+ dissector_handle_t tzsp_handle;
+
+ tzsp_handle = create_dissector_handle(dissect_tzsp, proto_tzsp);
+ dissector_add("udp.port", UDP_PORT_TZSP, tzsp_handle);
+
+ /* Get the data dissector for handling unknown encapsulation types. */
+ data_handle = find_dissector("data");
+
+ /* Register this protocol as an ecapsulation type. */
+ dissector_add("wtap_encap", WTAP_ENCAP_TZSP, tzsp_handle);
+
+ encap_dissector_table = find_dissector_table("wtap_encap");
+}
diff --git a/epan/dissectors/packet-ucp.c b/epan/dissectors/packet-ucp.c
new file mode 100644
index 0000000000..6ff5490dd1
--- /dev/null
+++ b/epan/dissectors/packet-ucp.c
@@ -0,0 +1,2595 @@
+/* packet-ucp.c
+ * Routines for Universal Computer Protocol dissection
+ * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * ----------
+ *
+ * Dissector of a UCP (Universal Computer Protocol) PDU, as defined for the
+ * ERMES paging system in ETS 300 133-3 (2nd final draft, September 1997,
+ * www.etsi.org).
+ * Includes the extension of EMI-UCP interface (V4.0, May 2001, www.cmgwds.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+/* #include "packet-ucp.h" */ /* We autoregister */
+
+/* Prototypes */
+static void dissect_ucp(tvbuff_t *, packet_info *, proto_tree *);
+
+/*
+ * Convert ASCII-hex character to binary equivalent. No checks, assume
+ * is valid hex character.
+ */
+#define AHex2Bin(n) (((n) & 0x40) ? ((n) & 0x0F) + 9 : ((n) & 0x0F))
+
+#define UCP_STX 0x02 /* Start of UCP PDU */
+#define UCP_ETX 0x03 /* End of UCP PDU */
+
+#define UCP_MALFORMED -1 /* Not a valid PDU */
+#define UCP_SHORTENED -2 /* May be valid but short */
+#define UCP_INV_CHK -3 /* Checksum doesn't add up */
+
+#define UCP_O_R_OFFSET 10 /* Location of O/R field*/
+#define UCP_OT_OFFSET 12 /* Location of OT field */
+
+#define UCP_TRN_LEN 2 /* Length of TRN-field */
+#define UCP_LEN_LEN 5 /* Length of LEN-field */
+#define UCP_O_R_LEN 1 /* Length of O/R-field */
+#define UCP_OT_LEN 2 /* Length of OT-field */
+
+/*
+ * Initialize the protocol and registered fields
+ *
+ * Header (fixed) section
+ */
+static int proto_ucp = -1;
+
+static int hf_ucp_hdr_TRN = -1;
+static int hf_ucp_hdr_LEN = -1;
+static int hf_ucp_hdr_O_R = -1;
+static int hf_ucp_hdr_OT = -1;
+
+/*
+ * Data (variable) section
+ */
+static int hf_ucp_oper_section = -1;
+static int hf_ucp_parm_AdC = -1;
+static int hf_ucp_parm_OAdC = -1;
+static int hf_ucp_parm_DAdC = -1;
+static int hf_ucp_parm_AC = -1;
+static int hf_ucp_parm_OAC = -1;
+static int hf_ucp_parm_BAS = -1;
+static int hf_ucp_parm_LAR = -1;
+static int hf_ucp_parm_LAC = -1;
+static int hf_ucp_parm_L1R = -1;
+static int hf_ucp_parm_L1P = -1;
+static int hf_ucp_parm_L3R = -1;
+static int hf_ucp_parm_L3P = -1;
+static int hf_ucp_parm_LCR = -1;
+static int hf_ucp_parm_LUR = -1;
+static int hf_ucp_parm_LRR = -1;
+static int hf_ucp_parm_RT = -1;
+static int hf_ucp_parm_NoN = -1;
+static int hf_ucp_parm_NoA = -1;
+static int hf_ucp_parm_NoB = -1;
+static int hf_ucp_parm_NAC = -1;
+static int hf_ucp_parm_PNC = -1;
+static int hf_ucp_parm_AMsg = -1;
+static int hf_ucp_parm_LNo = -1;
+static int hf_ucp_parm_LST = -1;
+static int hf_ucp_parm_TNo = -1;
+static int hf_ucp_parm_CS = -1;
+static int hf_ucp_parm_PID = -1;
+static int hf_ucp_parm_NPL = -1;
+static int hf_ucp_parm_GA = -1;
+static int hf_ucp_parm_RP = -1;
+static int hf_ucp_parm_LRP = -1;
+static int hf_ucp_parm_PR = -1;
+static int hf_ucp_parm_LPR = -1;
+static int hf_ucp_parm_UM = -1;
+static int hf_ucp_parm_LUM = -1;
+static int hf_ucp_parm_RC = -1;
+static int hf_ucp_parm_LRC = -1;
+static int hf_ucp_parm_NRq = -1;
+static int hf_ucp_parm_GAdC = -1;
+static int hf_ucp_parm_A_D = -1;
+static int hf_ucp_parm_CT = -1;
+static int hf_ucp_parm_AAC = -1;
+static int hf_ucp_parm_MNo = -1;
+static int hf_ucp_parm_R_T = -1;
+static int hf_ucp_parm_IVR5x = -1;
+static int hf_ucp_parm_REQ_OT = -1;
+static int hf_ucp_parm_SSTAT = -1;
+static int hf_ucp_parm_LMN = -1;
+static int hf_ucp_parm_NMESS = -1;
+static int hf_ucp_parm_NMESS_str= -1;
+static int hf_ucp_parm_NAdC = -1;
+static int hf_ucp_parm_NT = -1;
+static int hf_ucp_parm_NPID = -1;
+static int hf_ucp_parm_LRq = -1;
+static int hf_ucp_parm_LRAd = -1;
+static int hf_ucp_parm_LPID = -1;
+static int hf_ucp_parm_DD = -1;
+static int hf_ucp_parm_DDT = -1;
+static int hf_ucp_parm_STx = -1;
+static int hf_ucp_parm_ST = -1;
+static int hf_ucp_parm_SP = -1;
+static int hf_ucp_parm_VP = -1;
+static int hf_ucp_parm_RPID = -1;
+static int hf_ucp_parm_SCTS = -1;
+static int hf_ucp_parm_Dst = -1;
+static int hf_ucp_parm_Rsn = -1;
+static int hf_ucp_parm_DSCTS = -1;
+static int hf_ucp_parm_MT = -1;
+static int hf_ucp_parm_NB = -1;
+static int hf_ucp_data_section = -1;
+static int hf_ucp_parm_MMS = -1;
+static int hf_ucp_parm_DCs = -1;
+static int hf_ucp_parm_MCLs = -1;
+static int hf_ucp_parm_RPI = -1;
+static int hf_ucp_parm_CPg = -1;
+static int hf_ucp_parm_RPLy = -1;
+static int hf_ucp_parm_OTOA = -1;
+static int hf_ucp_parm_HPLMN = -1;
+static int hf_ucp_parm_RES4 = -1;
+static int hf_ucp_parm_RES5 = -1;
+static int hf_ucp_parm_OTON = -1;
+static int hf_ucp_parm_ONPI = -1;
+static int hf_ucp_parm_STYP0 = -1;
+static int hf_ucp_parm_STYP1 = -1;
+static int hf_ucp_parm_ACK = -1;
+static int hf_ucp_parm_PWD = -1;
+static int hf_ucp_parm_NPWD = -1;
+static int hf_ucp_parm_VERS = -1;
+static int hf_ucp_parm_LAdC = -1;
+static int hf_ucp_parm_LTON = -1;
+static int hf_ucp_parm_LNPI = -1;
+static int hf_ucp_parm_OPID = -1;
+static int hf_ucp_parm_RES1 = -1;
+static int hf_ucp_parm_RES2 = -1;
+static int hf_ucp_parm_MVP = -1;
+static int hf_ucp_parm_EC = -1;
+static int hf_ucp_parm_SM = -1;
+
+static int hf_ucp_parm_XSer = -1;
+static int hf_xser_service = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_ucp = -1;
+static gint ett_sub = -1;
+static gint ett_XSer = -1;
+
+/*
+ * Value-arrays for certain field-contents
+ */
+static const value_string vals_hdr_O_R[] = {
+ { 'O', "Operation" },
+ { 'R', "Result" },
+ { 0, NULL }
+};
+
+static const value_string vals_hdr_OT[] = { /* Operation type */
+ { 0, "Enquiry" },
+ { 1, "Call input" },
+ { 2, "Call input (multiple address)" },
+ { 3, "Call input (supplementary services included)" },
+ { 4, "Address list information" },
+ { 5, "Change address list" },
+ { 6, "Advice of accumulated charges" },
+ { 7, "Password management" },
+ { 8, "Legitimisation code management" },
+ { 9, "Standard text information" },
+ { 10, "Change standard text" },
+ { 11, "Request roaming information" },
+ { 12, "Change roaming information" },
+ { 13, "Roaming reset" },
+ { 14, "Message retrieval" },
+ { 15, "Request call barring" },
+ { 16, "Cancel call barring" },
+ { 17, "Request call diversion" },
+ { 18, "Cancel call diversion" },
+ { 19, "Request deferred delivery" },
+ { 20, "Cancel deferred delivery" },
+ { 21, "All features reset" },
+ { 22, "Call input (with specific character set)" },
+ { 23, "UCP version status request" },
+ { 24, "Mobile subscriber feature status request" },
+ { 30, "SMS message transfer" },
+ { 31, "SMT alert" },
+ { 32, "(proprietary)" },
+ { 34, "(proprietary)" },
+ { 36, "(proprietary)" },
+ { 38, "(proprietary)" },
+ { 40, "(proprietary)" },
+ { 41, "(proprietary)" },
+ { 42, "(proprietary)" },
+ { 43, "(proprietary)" },
+ { 44, "(proprietary)" },
+ { 45, "(proprietary)" },
+ { 51, "Submit short message" },
+ { 52, "Deliver short message" },
+ { 53, "Deliver notification" },
+ { 54, "Modify message" },
+ { 55, "Inquiry message" },
+ { 56, "Delete message" },
+ { 57, "Inquiry response message" },
+ { 58, "Delete response message" },
+ { 60, "Session management" },
+ { 61, "List management" },
+ { 95, "(proprietary)" },
+ { 96, "(proprietary)" },
+ { 97, "(proprietary)" },
+ { 98, "(proprietary)" },
+ { 99, "(proprietary)" },
+ { 0, NULL }
+};
+
+static const value_string vals_parm_EC[] = { /* Error code */
+ { 1, "Checksum error" },
+ { 2, "Syntax error" },
+ { 3, "Operation not supported by system" },
+ { 4, "Operation not allowed" },
+ { 5, "Call barring active" },
+ { 6, "AdC invalid" },
+ { 7, "Authentication failure" },
+ { 8, "Legitimisation code for all calls, failure" },
+ { 9, "GA not valid" },
+ { 10, "Repetition not allowed" },
+ { 11, "Legitimisation code for repetition, failure" },
+ { 12, "Priority call not allowed" },
+ { 13, "Legitimisation code for priority call, failure" },
+ { 14, "Urgent message not allowed" },
+ { 15, "Legitimisation code for urgent message, failure" },
+ { 16, "Reverse charging not alllowed" },
+ { 17, "Legitimisation code for rev. charging, failure" },
+ { 18, "Deferred delivery not allowed" },
+ { 19, "New AC not valid" },
+ { 20, "New legitimisation code not valid" },
+ { 21, "Standard text not valid" },
+ { 22, "Time period not valid" },
+ { 23, "Message type not supported by system" },
+ { 24, "Message too long" },
+ { 25, "Requested standard text not valid" },
+ { 26, "Message type not valid for the pager type" },
+ { 27, "Message not found in SMSC" },
+ { 28, "Invalid character set" },
+ { 30, "Subscriber hang-up" },
+ { 31, "Fax group not supported" },
+ { 32, "Fax message type not supported" },
+ { 33, "Address already in list (60-series)" },
+ { 34, "Address not in list (60-series)" },
+ { 35, "List full, cannot add address to list (60-series)" },
+ { 36, "RPID already in use" },
+ { 37, "Delivery in progress" },
+ { 38, "Message forwarded" },
+ { 50, "Low network status" },
+ { 51, "Legitimisation code for standard text, failure" },
+ { 53, "Operation partially successfull" },
+ { 54, "Operation not successfull" },
+ { 55, "System error" },
+ { 57, "AdC already a member of GAdC address list" },
+ { 58, "AdC not a member of GAdC address list" },
+ { 59, "Requested standard text list invalid" },
+ { 61, "Not controller of GAdC address list" },
+ { 62, "Standard text too large" },
+ { 63, "Not owner of standard text list" },
+ { 64, "Address list full" },
+ { 65, "GAdC invalid" },
+ { 66, "Operation restricted to mobile subscribers" },
+ { 68, "Invalid AdC type" },
+ { 69, "Cannot add AdC to GAdC address list" },
+ { 90, "(proprietary error code)" },
+ { 91, "(proprietary error code)" },
+ { 92, "(proprietary error code)" },
+ { 93, "(proprietary error code)" },
+ { 94, "(proprietary error code)" },
+ { 95, "(proprietary error code)" },
+ { 96, "(proprietary error code)" },
+ { 97, "(proprietary error code)" },
+ { 98, "(proprietary error code)" },
+ { 99, "(proprietary error code)" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_NRq[] = {
+ { '0', "NAdC not used" },
+ { '1', "NAdC used" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_NT[] = {
+ { '0', "Default value" },
+ { '1', "Delivery notification" },
+ { '2', "Non-delivery notification" },
+ { '3', "Delivery and Non-delivery notification" },
+ { '4', "Buffered message notification" },
+ { '5', "Buffered and Delivery notification" },
+ { '6', "Buffered and Non-delivery notification" },
+ { '7', "All notifications" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_PID[] = {
+ { 100, "Mobile station" },
+ { 122, "Fax Group 3" },
+ { 131, "X.400" },
+ { 138, "Menu over PSTN" },
+ { 139, "PC appl. over PSTN (E.164)" },
+ { 339, "PC appl. over X.25 (X.121)" },
+ { 439, "PC appl. over ISDN (E.164)" },
+ { 539, "PC appl. over TCP/IP" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_LRq[] = {
+ { '0', "LRAd not used" },
+ { '1', "LRAd used" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_DD[] = {
+ { '0', "DDT not used" },
+ { '1', "DDT used" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_Dst[] = {
+ { '0', "delivered" },
+ { '1', "buffered (see Rsn)" },
+ { '2', "not delivered (see Rsn)" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_Rsn[] = {
+ { 0, "Unknown subscriber" },
+ { 1, "Service temporary not available" },
+ { 2, "Service temporary not available" },
+ { 3, "Service temporary not available" },
+ { 4, "Service temporary not available" },
+ { 5, "Service temporary not available" },
+ { 6, "Service temporary not available" },
+ { 7, "Service temporary not available" },
+ { 8, "Service temporary not available" },
+ { 9, "Illegal error code" },
+ { 10, "Network time-out" },
+ { 100, "Facility not supported" },
+ { 101, "Unknown subscriber" },
+ { 102, "Facility not provided" },
+ { 103, "Call barred" },
+ { 104, "Operation barred" },
+ { 105, "SC congestion" },
+ { 106, "Facility not supported" },
+ { 107, "Absent subscriber" },
+ { 108, "Delivery fail" },
+ { 109, "Sc congestion" },
+ { 110, "Protocol error" },
+ { 111, "MS not equiped" },
+ { 112, "Unknown SC" },
+ { 113, "SC congestion" },
+ { 114, "Illegal MS" },
+ { 115, "MS nota subscriber" },
+ { 116, "Error in MS" },
+ { 117, "SMS lower layer not provisioned" },
+ { 118, "System fail" },
+ { 119, "PLMN system failure" },
+ { 120, "HLR system failure" },
+ { 121, "VLR system failure" },
+ { 122, "Previous VLR system failure" },
+ { 123, "Controlling MSC system failure" },
+ { 124, "VMSC system failure" },
+ { 125, "EIR system failure" },
+ { 126, "System failure" },
+ { 127, "Unexpected data value" },
+ { 200, "Error in address service centre" },
+ { 201, "Invalid absolute validity period" },
+ { 202, "Short message exceeds maximum" },
+ { 203, "Unable to unpack GSM message" },
+ { 204, "Unable to convert to IRA alphabet" },
+ { 205, "Invalid validity period format" },
+ { 206, "Invalid destination address" },
+ { 207, "Duplicate message submit" },
+ { 208, "Invalid message type indicator" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_MT[] = {
+ { '2', "Numeric message" },
+ { '3', "Alphanumeric message" },
+ { '4', "Transparent data" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_DCs[] = {
+ { '0', "default alphabet" },
+ { '1', "User defined data (8 bit)" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_MCLs[] = {
+ { '0', "message class 0" },
+ { '1', "message class 1" },
+ { '2', "message class 2" },
+ { '3', "message class 3" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_RPI[] = {
+ { '1', "Request" },
+ { '2', "Response" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_ACK[] = {
+ { 'A', "Ack" },
+ { 'N', "Nack" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_RP[] = {
+ { '1', "Repetition requested" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_UM[] = {
+ { '1', "Urgent message" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_RC[] = {
+ { '1', "Reverse charging request" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_OTON[] = {
+ { '1', "International number" },
+ { '2', "National number" },
+ { '6', "Abbreviated number (short number alias)" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_ONPI[] = {
+ { '1', "E.164 address" },
+ { '3', "X.121 address" },
+ { '5', "Private -TCP/IP or abbreviated number- address" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_STYP0[] = {
+ { '1', "open session" },
+ { '2', "reserved" },
+ { '3', "change password" },
+ { '4', "open provisioning session" },
+ { '5', "reserved" },
+ { '6', "change provisioning password" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_STYP1[] = {
+ { '1', "add item to mo-list" },
+ { '2', "remove item from mo-list" },
+ { '3', "verify item mo-list" },
+ { '4', "add item to mt-list" },
+ { '5', "remove item from mt-list" },
+ { '6', "verify item mt-list" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_OPID[] = {
+ { 0, "Mobile station" },
+ { 39, "PC application" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_BAS[] = {
+ { '1', "Barred" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_LAR[] = {
+ { '1', "Leg. code for all calls requested" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_L1R[] = {
+ { '1', "Leg. code for priority 1 requested" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_L3R[] = {
+ { '1', "Leg. code for priority 3 requested" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_LCR[] = {
+ { '1', "Leg. code for reverse charging requested" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_LUR[] = {
+ { '1', "Leg. code for urgent message requested" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_LRR[] = {
+ { '1', "Leg. code for repitition requested" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_RT[] = {
+ { '1', "Tone only" },
+ { '2', "Numeric" },
+ { '3', "Alphanumeric" },
+ { '4', "Transparent data" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_PNC[] = {
+ { 'H', "Home PNC" },
+ { 'I', "Input PNC" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_A_D[] = {
+ { 'A', "Add" },
+ { 'D', "Delete" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_R_T[] = {
+ { 'R', "Retrieval Ok" },
+ { 'T', "Retransmit on radio channel" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_REQ_OT[] = {
+ { 'S', "Send used operation types" },
+ { 'N', "Don't send used operation types" },
+ { 0, NULL },
+};
+
+static const value_string vals_parm_SSTAT[] = {
+ { '0', "All services" },
+ { '1', "All in the moment active servics" },
+ { '2', "Call diversion" },
+ { '3', "Roaming information status" },
+ { '4', "Call barring status" },
+ { '5', "Deferred delivery status" },
+ { '6', "Number of stored messages" },
+ { 0, NULL },
+};
+
+static const value_string vals_xser_service[] = {
+ { 1, "GSM UDH information" },
+ { 2, "GSM DCS information" },
+ { 3, "[Message Type] TDMA information exchange" },
+ { 4, "[Message Reference] TDMA information exchange" },
+ { 5, "[Privacy Indicator] TDMA information exchange" },
+ { 6, "[Urgency Indicator] TDMA information exchange" },
+ { 7, "[Acknowledgement Request] TDMA information exchange" },
+ { 8, "[Messsage Updating] TDMA information exchange" },
+ { 9, "[Call Back Number] TDMA information exchange" },
+ { 10, "[Response Code] TDMA information exchange" },
+ { 11, "[Teleservice ID] TDMA information exchange" },
+ { 12, "Billing identifier" },
+ { 13, "Single shot indicator" },
+ { 0, NULL },
+};
+
+/*!
+ * Checks whether the PDU looks a bit like UCP and checks the checksum
+ *
+ * \param tvb The buffer with PDU-data
+ * \param endpkt Returns pointer, indicating the end of the PDU
+ *
+ * \return The state of this PDU
+ * \retval 0 Definitely UCP
+ * \retval UCP_SHORTENED Packet may be there, but not complete
+ * \retval UCP_MALFORMED Hmmmm, not UCP after all...
+ * \retval UCP_INV_CHK Nice packet, but checksum doesn't add up...
+ */
+static int
+check_ucp(tvbuff_t *tvb, int *endpkt)
+{
+ guint offset = 1;
+ guint checksum = 0;
+ int pkt_check, tmp;
+ int length;
+
+ length = tvb_find_guint8(tvb, offset, -1, UCP_ETX);
+ if (length == -1) {
+ /* XXX - should we have an option to request reassembly? */
+ *endpkt = tvb_reported_length_remaining(tvb, offset);
+ return UCP_SHORTENED;
+ }
+ if (length > (int) tvb_reported_length(tvb)) {
+ /* XXX - "cannot happen" */
+ *endpkt = 0;
+ return UCP_MALFORMED;
+ }
+ for (; offset < (guint) (length - 2); offset++)
+ checksum += tvb_get_guint8(tvb, offset);
+ checksum &= 0xFF;
+ tmp = tvb_get_guint8(tvb, offset++);
+ pkt_check = AHex2Bin(tmp);
+ tmp = tvb_get_guint8(tvb, offset++);
+ pkt_check = 16 * pkt_check + AHex2Bin(tmp);
+ *endpkt = offset + 1;
+ if (checksum == (guint) pkt_check)
+ return 0;
+ else
+ return UCP_INV_CHK;
+}
+
+/*!
+ * UCP equivalent of mktime() (3). Convert date to standard 'time_t' format
+ *
+ * \param datestr The UCP-formatted date to convert
+ *
+ * \return The date in standard 'time_t' format.
+ */
+static time_t
+ucp_mktime(char *datestr)
+{
+ struct tm r_time;
+
+ r_time.tm_mday = 10 * (datestr[0] - '0') + (datestr[1] - '0');
+ r_time.tm_mon = (10 * (datestr[2] - '0') + (datestr[3] - '0')) - 1;
+ r_time.tm_year = 10 * (datestr[4] - '0') + (datestr[5] - '0');
+ if (r_time.tm_year < 90)
+ r_time.tm_year += 100;
+ r_time.tm_hour = 10 * (datestr[6] - '0') + (datestr[7] - '0');
+ r_time.tm_min = 10 * (datestr[8] - '0') + (datestr[9] - '0');
+ if (datestr[10])
+ r_time.tm_sec = 10 * (datestr[10] - '0') + (datestr[11] - '0');
+ else
+ r_time.tm_sec = 0;
+ r_time.tm_isdst = -1;
+ return mktime(&r_time);
+}
+
+/*!
+ * Scanning routines to add standard types (byte, int, string, data)
+ * to the protocol-tree. Each field is seperated with a slash ('/').
+ *
+ * \param tree The protocol tree to add to
+ * \param tvb Buffer containing the data
+ * \param field The actual field, whose value needs displaying
+ * \param offset Location of field within the buffer, returns location
+ * of next field.
+ *
+ * \return For 'int'-types, the value of the field.
+ */
+static void
+ucp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ gint idx, len;
+
+ idx = tvb_find_guint8(tvb, *offset, -1, '/');
+ if (idx == -1) {
+ /* Force the appropriate exception to be thrown. */
+ len = tvb_length_remaining(tvb, *offset);
+ tvb_ensure_bytes_exist(tvb, *offset, len + 1);
+ } else
+ len = idx - *offset;
+ if (len > 0)
+ proto_tree_add_item(tree, field, tvb, *offset, len, FALSE);
+ *offset += len;
+ if (idx != -1)
+ *offset += 1; /* skip terminating '/' */
+}
+
+static void
+ucp_handle_IRAstring(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ char strval[BUFSIZ + 1],
+ *p_dst = strval;
+ guint8 byte;
+ int idx = 0;
+ int tmpoff = *offset;
+
+ while (((byte = tvb_get_guint8(tvb, tmpoff++)) != '/') &&
+ (idx < BUFSIZ))
+ {
+ if (byte >= '0' && byte <= '9')
+ {
+ *p_dst = (byte - '0') * 16;
+ }
+ else
+ {
+ *p_dst = (byte - 'A' + 10) * 16;
+ }
+ if ((byte = tvb_get_guint8(tvb, tmpoff++)) == '/')
+ {
+ break;
+ }
+ if (byte >= '0' && byte <= '9')
+ {
+ *p_dst++ += byte - '0';
+ }
+ else
+ {
+ *p_dst++ += byte - 'A' + 10;
+ }
+ idx++;
+ }
+ strval[idx] = '\0';
+ if (idx == BUFSIZ)
+ {
+ /*
+ * Data clipped, eat rest of field
+ */
+ while ((tvb_get_guint8(tvb, tmpoff++)) != '/')
+ ;
+ }
+ if ((tmpoff - *offset) > 1)
+ proto_tree_add_string(tree, field, tvb, *offset,
+ tmpoff - *offset - 1, strval);
+ *offset = tmpoff;
+}
+
+static guint
+ucp_handle_byte(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ guint intval = 0;
+
+ if ((intval = tvb_get_guint8(tvb, (*offset)++)) != '/') {
+ proto_tree_add_uint(tree, field, tvb, *offset - 1, 1, intval);
+ (*offset)++;
+ }
+ return intval;
+}
+
+static guint
+ucp_handle_int(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ gint idx, len;
+ char *strval;
+ guint intval = 0;
+
+ idx = tvb_find_guint8(tvb, *offset, -1, '/');
+ if (idx == -1) {
+ /* Force the appropriate exception to be thrown. */
+ len = tvb_length_remaining(tvb, *offset);
+ tvb_ensure_bytes_exist(tvb, *offset, len + 1);
+ } else
+ len = idx - *offset;
+ strval = tvb_get_string(tvb, *offset, len);
+ if (len > 0) {
+ intval = atoi(strval);
+ proto_tree_add_uint(tree, field, tvb, *offset, idx, intval);
+ }
+ g_free(strval);
+ *offset += len;
+ if (idx != -1)
+ *offset += 1; /* skip terminating '/' */
+ return intval;
+}
+
+static void
+ucp_handle_time(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ gint idx, len;
+ char *strval;
+ time_t tval;
+ nstime_t tmptime;
+
+ idx = tvb_find_guint8(tvb, *offset, -1, '/');
+ if (idx == -1) {
+ /* Force the appropriate exception to be thrown. */
+ len = tvb_length_remaining(tvb, *offset);
+ tvb_ensure_bytes_exist(tvb, *offset, len + 1);
+ } else
+ len = idx - *offset;
+ strval = tvb_get_string(tvb, *offset, len);
+ if (len > 0) {
+ tval = ucp_mktime(strval);
+ tmptime.secs = tval;
+ tmptime.nsecs = 0;
+ proto_tree_add_time(tree, field, tvb, *offset, idx, &tmptime);
+ }
+ g_free(strval);
+ *offset += len;
+ if (idx != -1)
+ *offset += 1; /* skip terminating '/' */
+}
+
+static void
+ucp_handle_data(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+ int tmpoff = *offset;
+
+ while (tvb_get_guint8(tvb, tmpoff++) != '/')
+ ;
+ if ((tmpoff - *offset) > 1)
+ proto_tree_add_item(tree, field, tvb, *offset,
+ tmpoff - *offset - 1, FALSE);
+ *offset = tmpoff;
+}
+
+/*!
+ * Handle the data-field within the UCP-message, according the Message Type
+ * - 1 Tone only
+ * - 2 Numeric message
+ * - 3 Alphanumeric message
+ * - 4 Transparent (binary) data
+ * - 5 Standard text handling
+ * - 6 Alphanumeric message in specified character set
+ *
+ * \param tree The protocol tree to add to
+ * \param tvb Buffer containing the data
+ * \param field The actual field, whose value needs displaying
+ * \param offset Location of field within the buffer, returns location
+ * of next field.
+ */
+static void
+ucp_handle_mt(proto_tree *tree, tvbuff_t *tvb, int *offset)
+{
+ guint intval;
+
+ intval = ucp_handle_byte(tree, tvb, hf_ucp_parm_MT, offset);
+ switch (intval) {
+ case '1': /* Tone only, no data */
+ break;
+ case '4': /* TMsg, no of bits */
+ ucp_handle_string(tree, tvb, hf_ucp_parm_NB, offset);
+ /* fall through here for the data piece */
+ case '2':
+ ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
+ break;
+ case '3':
+ ucp_handle_IRAstring(tree, tvb, hf_ucp_parm_AMsg, offset);
+ break;
+ case '5':
+ ucp_handle_byte(tree, tvb, hf_ucp_parm_PNC, offset);
+ ucp_handle_string(tree, tvb, hf_ucp_parm_LNo, offset);
+ ucp_handle_string(tree, tvb, hf_ucp_parm_LST, offset);
+ ucp_handle_string(tree, tvb, hf_ucp_parm_TNo, offset);
+ break;
+ case '6':
+ ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
+ ucp_handle_int(tree, tvb, hf_ucp_parm_CS, offset);
+ break;
+ default:
+ break; /* No data so ? */
+ }
+}
+
+/*!
+ * Handle the data within the 'Extended services' field. Each field having the
+ * format TTLLDD..., TT being the type of service, LL giving the length of the
+ * field, DD... containing the actual data
+ *
+ * \param tree The protocol tree to add to
+ * \param tvb Buffer containing the extended services data
+ */
+static void
+ucp_handle_XSer(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+ guint intval;
+ int service;
+ int len;
+
+ while ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
+ service = AHex2Bin(intval);
+ intval = tvb_get_guint8(tvb, offset++);
+ service = service * 16 + AHex2Bin(intval);
+ intval = tvb_get_guint8(tvb, offset++);
+ len = AHex2Bin(intval);
+ intval = tvb_get_guint8(tvb, offset++);
+ len = len * 16 + AHex2Bin(intval);
+ proto_tree_add_uint(tree, hf_xser_service, tvb, offset,
+ 2 * len, service);
+ offset += (2 * len);
+ }
+}
+
+/* Next definitions are just a convenient shorthand to make the coding a
+ * bit more readable instead of summing up all these parameters.
+ */
+#define UcpHandleString(field) ucp_handle_string(tree, tvb, (field), &offset)
+
+#define UcpHandleIRAString(field) \
+ ucp_handle_IRAstring(tree, tvb, (field), &offset)
+
+#define UcpHandleByte(field) ucp_handle_byte(tree, tvb, (field), &offset)
+
+#define UcpHandleInt(field) ucp_handle_int(tree, tvb, (field), &offset)
+
+#define UcpHandleTime(field) ucp_handle_time(tree, tvb, (field), &offset)
+
+#define UcpHandleData(field) ucp_handle_data(tree, tvb, (field), &offset)
+
+/*!
+ * The next set of routines handle the different operation types,
+ * associated with UCP.
+ */
+static void
+add_00O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Enquiry */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleString(hf_ucp_parm_OAC);
+}
+
+static void
+add_00R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'A')
+ {
+ UcpHandleByte(hf_ucp_parm_BAS);
+ UcpHandleByte(hf_ucp_parm_LAR);
+ UcpHandleByte(hf_ucp_parm_L1R);
+ UcpHandleByte(hf_ucp_parm_L3R);
+ UcpHandleByte(hf_ucp_parm_LCR);
+ UcpHandleByte(hf_ucp_parm_LUR);
+ UcpHandleByte(hf_ucp_parm_LRR);
+ UcpHandleByte(hf_ucp_parm_RT);
+ UcpHandleInt(hf_ucp_parm_NoN);
+ UcpHandleInt(hf_ucp_parm_NoA);
+ UcpHandleInt(hf_ucp_parm_NoB);
+ } else {
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+ }
+}
+
+static void
+add_01O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Call input */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleString(hf_ucp_parm_OAC);
+ ucp_handle_mt(tree, tvb, &offset);
+}
+
+static void
+add_01R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'N')
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+}
+
+static void
+add_02O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Multiple address call input*/
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleString(hf_ucp_parm_AdC);
+
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleString(hf_ucp_parm_OAC);
+ ucp_handle_mt(tree, tvb, &offset);
+}
+
+#define add_02R(a, b) add_01R(a,b)
+
+static void
+add_03O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Call input with SS */
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleString(hf_ucp_parm_OAC);
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleString(hf_ucp_parm_GA);
+
+ UcpHandleByte(hf_ucp_parm_RP);
+ UcpHandleString(hf_ucp_parm_LRP);
+ UcpHandleByte(hf_ucp_parm_PR);
+ UcpHandleString(hf_ucp_parm_LPR);
+ UcpHandleByte(hf_ucp_parm_UM);
+ UcpHandleString(hf_ucp_parm_LUM);
+ UcpHandleByte(hf_ucp_parm_RC);
+ UcpHandleString(hf_ucp_parm_LRC);
+ UcpHandleByte(hf_ucp_parm_DD);
+ UcpHandleTime(hf_ucp_parm_DDT);
+ ucp_handle_mt(tree, tvb, &offset);
+}
+
+#define add_03R(a, b) add_01R(a,b)
+
+static void
+add_04O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Address list information */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_GAdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleString(hf_ucp_parm_OAC);
+}
+
+static void
+add_04R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'A') {
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_GAdC);
+ } else
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+}
+
+static void
+add_05O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Change address list */
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ UcpHandleString(hf_ucp_parm_GAdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleString(hf_ucp_parm_OAC);
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleByte(hf_ucp_parm_A_D);
+}
+
+#define add_05R(a, b) add_01R(a, b)
+
+static void
+add_06O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Advice of accum. charges */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+}
+
+static void
+add_06R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'A') {
+ UcpHandleTime(hf_ucp_parm_CT);
+ UcpHandleString(hf_ucp_parm_AAC);
+ } else
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+}
+
+static void
+add_07O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Password management */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleString(hf_ucp_parm_NAC);
+}
+
+#define add_07R(a, b) add_01R(a, b)
+
+static void
+add_08O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Leg. code management */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleString(hf_ucp_parm_LAC);
+ UcpHandleString(hf_ucp_parm_L1P);
+ UcpHandleString(hf_ucp_parm_L3P);
+ UcpHandleString(hf_ucp_parm_LRC);
+ UcpHandleString(hf_ucp_parm_LUM);
+ UcpHandleString(hf_ucp_parm_LRP);
+ UcpHandleString(hf_ucp_parm_LST);
+}
+
+#define add_08R(a, b) add_01R(a, b)
+
+static void
+add_09O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Standard text information */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_LNo);
+ UcpHandleString(hf_ucp_parm_LST);
+}
+
+static void
+add_09R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'A') {
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleString(hf_ucp_parm_LST);
+ } else
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+}
+
+static void
+add_10O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Change standard text */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleString(hf_ucp_parm_LNo);
+ UcpHandleString(hf_ucp_parm_TNo);
+ UcpHandleData(hf_ucp_parm_STx);
+ UcpHandleInt(hf_ucp_parm_CS);
+}
+
+#define add_10R(a, b) add_01R(a, b)
+
+#define add_11O(a, b) add_06O(a, b) /* Request roaming info */
+
+static void
+add_11R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'A') {
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleString(hf_ucp_parm_GA);
+ } else
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+}
+
+static void
+add_12O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Change roaming */
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleString(hf_ucp_parm_GA);
+}
+
+#define add_12R(a, b) add_01R(a, b)
+
+#define add_13O(a, b) add_06O(a, b) /* Roaming reset */
+
+#define add_13R(a, b) add_01R(a, b)
+
+static void
+add_14O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Message retrieval */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleString(hf_ucp_parm_MNo);
+ UcpHandleByte(hf_ucp_parm_R_T);
+}
+
+static void
+add_14R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'A') {
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ /*
+ * Spec is unclear here. Is 'SM' part of the Msg:s field or not?
+ * For now, assume it is part of it...
+ */
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleData(hf_ucp_data_section);
+ } else {
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+ }
+}
+
+static void
+add_15O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Request call barring */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleTime(hf_ucp_parm_ST);
+ UcpHandleTime(hf_ucp_parm_SP);
+}
+
+#define add_15R(a, b) add_01R(a, b)
+
+#define add_16O(a, b) add_06O(a, b) /* Cancel call barring */
+
+#define add_16R(a, b) add_01R(a, b)
+
+static void
+add_17O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Request call diversion */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleString(hf_ucp_parm_DAdC);
+ UcpHandleTime(hf_ucp_parm_ST);
+ UcpHandleTime(hf_ucp_parm_SP);
+}
+
+#define add_17R(a, b) add_01R(a, b)
+
+#define add_18O(a, b) add_06O(a, b) /* Cancel call diversion */
+
+#define add_18R(a, b) add_01R(a, b)
+
+static void
+add_19O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Request deferred delivery*/
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleTime(hf_ucp_parm_ST);
+ UcpHandleTime(hf_ucp_parm_SP);
+}
+
+#define add_19R(a, b) add_01R(a, b)
+
+#define add_20O(a, b) add_06O(a, b) /* Cancel deferred delivery */
+
+#define add_20R(a, b) add_01R(a, b)
+
+#define add_21O(a, b) add_06O(a, b) /* All features reset */
+
+#define add_21R(a, b) add_01R(a, b)
+
+static void
+add_22O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Call input w. add. CS */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleString(hf_ucp_parm_OAC);
+ UcpHandleData(hf_ucp_data_section);
+ UcpHandleInt(hf_ucp_parm_CS);
+}
+
+#define add_22R(a, b) add_01R(a, b)
+
+static void
+add_23O(proto_tree *tree, tvbuff_t *tvb)
+{ /* UCP version status */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_IVR5x);
+ UcpHandleByte(hf_ucp_parm_REQ_OT);
+}
+
+static void
+add_23R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'A') {
+ UcpHandleByte(hf_ucp_parm_IVR5x);
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleInt(hf_ucp_hdr_OT);
+ } else
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+}
+
+static void
+add_24O(proto_tree *tree, tvbuff_t *tvb)
+{ /* Mobile subs. feature stat*/
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleByte(hf_ucp_parm_SSTAT);
+}
+
+static void
+add_24R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+ guint idx;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'A') {
+ if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
+ proto_tree_add_text(tree, tvb, offset - 1, 1,
+ "GA roaming definitions");
+ if (intval == 'N') {
+ proto_tree_add_text(tree, tvb, offset -1, 1,
+ "Not subscribed/not allowed");
+ offset++;
+ } else {
+ --offset;
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleData(hf_ucp_data_section);
+ }
+ }
+ if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
+ proto_tree_add_text(tree, tvb, offset - 1, 1,
+ "Call barring definitions");
+ if (intval == 'N') {
+ proto_tree_add_text(tree, tvb, offset -1, 1,
+ "Not subscribed/not allowed");
+ offset++;
+ } else {
+ --offset;
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleData(hf_ucp_data_section);
+ }
+ }
+ if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
+ proto_tree_add_text(tree, tvb, offset - 1, 1,
+ "Deferred delivery definitions");
+ if (intval == 'N') {
+ proto_tree_add_text(tree, tvb, offset -1, 1,
+ "Not subscribed/not allowed");
+ offset++;
+ } else {
+ --offset;
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleData(hf_ucp_data_section);
+ }
+ }
+ if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
+ proto_tree_add_text(tree, tvb, offset - 1, 1,
+ "Diversion definitions");
+ if (intval == 'N') {
+ proto_tree_add_text(tree, tvb, offset -1, 1,
+ "Not subscribed/not allowed");
+ offset++;
+ } else {
+ --offset;
+ intval = UcpHandleInt(hf_ucp_parm_NPL);
+ for (idx = 0; idx < intval; idx++)
+ UcpHandleData(hf_ucp_data_section);
+ }
+ }
+ UcpHandleInt(hf_ucp_parm_LMN);
+ if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
+ if (intval == 'N') {
+ proto_tree_add_string(tree, hf_ucp_parm_NMESS_str, tvb,
+ offset -1, 1, "Not subscribed/not allowed");
+ offset++;
+ } else {
+ --offset;
+ intval = UcpHandleInt(hf_ucp_parm_NMESS);
+ }
+ }
+ } else
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+}
+
+static void
+add_30O(proto_tree *tree, tvbuff_t *tvb)
+{ /* SMS message transfer */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleByte(hf_ucp_parm_NRq);
+ UcpHandleString(hf_ucp_parm_NAdC);
+ UcpHandleInt(hf_ucp_parm_NPID);
+ UcpHandleByte(hf_ucp_parm_DD);
+ UcpHandleTime(hf_ucp_parm_DDT);
+ UcpHandleTime(hf_ucp_parm_VP);
+ UcpHandleData(hf_ucp_data_section);
+}
+
+static void
+add_30R(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 1;
+ guint intval;
+
+ intval = UcpHandleByte(hf_ucp_parm_ACK);
+ if (intval == 'A')
+ UcpHandleTime(hf_ucp_parm_MVP);
+ else
+ UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
+}
+
+static void
+add_31O(proto_tree *tree, tvbuff_t *tvb)
+{ /* SMT alert */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleInt(hf_ucp_parm_PID);
+}
+
+#define add_31R(a, b) add_01R(a, b)
+
+static void
+add_5xO(proto_tree *tree, tvbuff_t *tvb)
+{ /* 50-series operations */
+ guint intval;
+ int offset = 1;
+ int tmpoff;
+ proto_item *ti;
+ tvbuff_t *tmptvb;
+
+ UcpHandleString(hf_ucp_parm_AdC);
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleString(hf_ucp_parm_AC);
+ UcpHandleByte(hf_ucp_parm_NRq);
+ UcpHandleString(hf_ucp_parm_NAdC);
+ UcpHandleByte(hf_ucp_parm_NT);
+ UcpHandleInt(hf_ucp_parm_NPID);
+ UcpHandleByte(hf_ucp_parm_LRq);
+ UcpHandleString(hf_ucp_parm_LRAd);
+ UcpHandleInt(hf_ucp_parm_LPID);
+ UcpHandleByte(hf_ucp_parm_DD);
+ UcpHandleTime(hf_ucp_parm_DDT);
+ UcpHandleTime(hf_ucp_parm_VP);
+ UcpHandleString(hf_ucp_parm_RPID);
+ UcpHandleTime(hf_ucp_parm_SCTS);
+ UcpHandleByte(hf_ucp_parm_Dst);
+ UcpHandleInt(hf_ucp_parm_Rsn);
+ UcpHandleTime(hf_ucp_parm_DSCTS);
+ intval = UcpHandleByte(hf_ucp_parm_MT);
+ UcpHandleString(hf_ucp_parm_NB);
+ if (intval != '3')
+ UcpHandleData(hf_ucp_data_section);
+ else
+ UcpHandleIRAString(hf_ucp_parm_AMsg);
+ UcpHandleByte(hf_ucp_parm_MMS);
+ UcpHandleByte(hf_ucp_parm_PR);
+ UcpHandleByte(hf_ucp_parm_DCs);
+ UcpHandleByte(hf_ucp_parm_MCLs);
+ UcpHandleByte(hf_ucp_parm_RPI);
+ if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
+ proto_tree_add_string(tree, hf_ucp_parm_CPg, tvb, offset - 1,1,
+ "(reserved for Code Page)");
+ offset++;
+ }
+ if ((intval = tvb_get_guint8(tvb, offset++)) != '/') {
+ proto_tree_add_string(tree, hf_ucp_parm_RPLy, tvb, offset - 1,1,
+ "(reserved for Reply type)");
+ offset++;
+ }
+ UcpHandleString(hf_ucp_parm_OTOA);
+ UcpHandleString(hf_ucp_parm_HPLMN);
+ tmpoff = offset; /* Extra services */
+ while (tvb_get_guint8(tvb, tmpoff++) != '/')
+ ;
+ if ((tmpoff - offset) > 1) {
+ int len = tmpoff - offset - 1;
+
+ ti = proto_tree_add_item(tree, hf_ucp_parm_XSer,tvb,offset,len,FALSE);
+ tmptvb = tvb_new_subset(tvb, offset, len + 1, len + 1);
+ proto_item_add_subtree(ti, ett_XSer);
+ ucp_handle_XSer(ti, tmptvb);
+ }
+ offset = tmpoff;
+ UcpHandleData(hf_ucp_parm_RES4);
+ UcpHandleData(hf_ucp_parm_RES5);
+}
+
+#define add_5xR(a, b) add_30R(a, b)
+
+static void
+add_6xO(proto_tree *tree, tvbuff_t *tvb, guint8 OT)
+{ /* 60-series operations */
+ int offset = 1;
+
+ UcpHandleString(hf_ucp_parm_OAdC);
+ UcpHandleByte(hf_ucp_parm_OTON);
+ UcpHandleByte(hf_ucp_parm_ONPI);
+ if (OT == 60) {
+ UcpHandleByte(hf_ucp_parm_STYP0);
+ } else {
+ UcpHandleByte(hf_ucp_parm_STYP1);
+ }
+ UcpHandleIRAString(hf_ucp_parm_PWD);
+ UcpHandleIRAString(hf_ucp_parm_NPWD);
+ UcpHandleString(hf_ucp_parm_VERS);
+ UcpHandleString(hf_ucp_parm_LAdC);
+ UcpHandleByte(hf_ucp_parm_LTON);
+ UcpHandleByte(hf_ucp_parm_LNPI);
+ UcpHandleInt(hf_ucp_parm_OPID);
+ UcpHandleData(hf_ucp_parm_RES1);
+ UcpHandleData(hf_ucp_parm_RES2);
+}
+
+#define add_6xR(a, b) add_01R(a, b)
+
+/*
+ * End of convenient shorthands
+ */
+#undef UcpHandleString
+#undef UcpHandleIRAString
+#undef UcpHandleByte
+#undef UcpHandleInt
+#undef UcpHandleTime
+#undef UcpHandleData
+
+/* Code to actually dissect the packets */
+/*
+ * Overlapping data for these functions
+ */
+static int result, endpkt;
+
+/*
+ * The heuristic dissector
+ */
+static gboolean
+dissect_ucp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 O_R; /* Request or response */
+
+ /* This runs atop TCP, so we are guaranteed that there is at least one
+ byte in the tvbuff. */
+ if (tvb_get_guint8(tvb, 0) != UCP_STX)
+ return FALSE;
+
+ result = check_ucp(tvb, &endpkt);
+
+ if (result == UCP_MALFORMED)
+ return FALSE;
+ if (endpkt < UCP_OT_OFFSET + 1)
+ /*
+ * Might be shortened packet but don't handle anyway.
+ */
+ return FALSE;
+
+ /*
+ * Try getting the operation-type and whether it's a request/response
+ */
+ O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
+ if (match_strval(O_R, vals_hdr_O_R) == NULL)
+ return FALSE;
+ /*
+ * Ok, looks like a valid packet, go dissect.
+ */
+ dissect_ucp(tvb, pinfo, tree);
+ return TRUE;
+}
+
+/*
+ * The actual dissector
+ */
+static void
+dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0; /* Offset in packet within tvbuff */
+ int tmpoff; /* Local offset value (per field) */
+ guint8 O_R; /* Request or response */
+ guint8 OT; /* Operation type */
+ guint intval;
+ int i;
+
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_item *sub_ti;
+ proto_tree *ucp_tree;
+ proto_tree *sub_tree;
+ tvbuff_t *tmp_tvb;
+
+ O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
+ /*
+ * So do an atoi() on the operation type
+ */
+ OT = tvb_get_guint8(tvb, UCP_OT_OFFSET) - '0';
+ OT = 10 * OT + (tvb_get_guint8(tvb, UCP_OT_OFFSET + 1) - '0');
+
+ /* Make entries in Protocol column and Info column on summary display */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%s)",
+ val_to_str(OT, vals_hdr_OT, "unknown operation"),
+ match_strval(O_R, vals_hdr_O_R));
+ if (result == UCP_SHORTENED)
+ col_append_str(pinfo->cinfo, COL_INFO, " [short packet]");
+ else if (result == UCP_INV_CHK)
+ col_append_str(pinfo->cinfo, COL_INFO, " [checksum invalid]");
+ }
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_ucp, tvb, 0, -1, FALSE);
+
+ ucp_tree = proto_item_add_subtree(ti, ett_ucp);
+ /*
+ * Process the packet here.
+ * Transaction number
+ */
+ offset++; /* Skip <stx> */
+ tmpoff = offset;
+ intval = tvb_get_guint8(tvb, tmpoff++) - '0';
+ intval = 10 * intval + (tvb_get_guint8(tvb, tmpoff++) - '0');
+ proto_tree_add_uint(ucp_tree, hf_ucp_hdr_TRN, tvb, offset,
+ UCP_TRN_LEN, intval);
+ offset = tmpoff;
+
+ offset++; /* Skip '/' */
+ intval = 0;
+ tmpoff = offset;
+ for (i = 0; i < UCP_LEN_LEN; i++) { /* Length */
+ intval = 10 * intval +
+ (tvb_get_guint8(tvb, tmpoff++) - '0');
+ }
+ proto_tree_add_uint(ucp_tree, hf_ucp_hdr_LEN, tvb, offset,
+ UCP_LEN_LEN, intval);
+ offset = tmpoff;
+
+ offset++; /* Operation/Response */
+ proto_tree_add_uint(ucp_tree, hf_ucp_hdr_O_R, tvb, offset++,
+ UCP_O_R_LEN, O_R);
+
+ offset++; /* Operation type */
+ proto_tree_add_uint(ucp_tree, hf_ucp_hdr_OT, tvb, offset,
+ UCP_OT_LEN, OT);
+ offset += UCP_OT_LEN;
+ /*
+ * Variable part starts here. Don't dissect if not complete.
+ */
+ if (result == UCP_SHORTENED)
+ return;
+ tmp_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ sub_ti = proto_tree_add_item(ucp_tree, hf_ucp_oper_section, tvb,
+ offset, endpkt - offset, FALSE);
+ sub_tree = proto_item_add_subtree(sub_ti, ett_sub);
+
+ switch (OT) {
+ case 0:
+ O_R == 'O' ? add_00O(sub_tree,tmp_tvb) : add_00R(sub_tree,tmp_tvb);
+ break;
+ case 1:
+ O_R == 'O' ? add_01O(sub_tree,tmp_tvb) : add_01R(sub_tree,tmp_tvb);
+ break;
+ case 2:
+ O_R == 'O' ? add_02O(sub_tree,tmp_tvb) : add_02R(sub_tree,tmp_tvb);
+ break;
+ case 3:
+ O_R == 'O' ? add_03O(sub_tree,tmp_tvb) : add_03R(sub_tree,tmp_tvb);
+ break;
+ case 4:
+ O_R == 'O' ? add_04O(sub_tree,tmp_tvb) : add_04R(sub_tree,tmp_tvb);
+ break;
+ case 5:
+ O_R == 'O' ? add_05O(sub_tree,tmp_tvb) : add_05R(sub_tree,tmp_tvb);
+ break;
+ case 6:
+ O_R == 'O' ? add_06O(sub_tree,tmp_tvb) : add_06R(sub_tree,tmp_tvb);
+ break;
+ case 7:
+ O_R == 'O' ? add_07O(sub_tree,tmp_tvb) : add_07R(sub_tree,tmp_tvb);
+ break;
+ case 8:
+ O_R == 'O' ? add_08O(sub_tree,tmp_tvb) : add_08R(sub_tree,tmp_tvb);
+ break;
+ case 9:
+ O_R == 'O' ? add_09O(sub_tree,tmp_tvb) : add_09R(sub_tree,tmp_tvb);
+ break;
+ case 10:
+ O_R == 'O' ? add_10O(sub_tree,tmp_tvb) : add_10R(sub_tree,tmp_tvb);
+ break;
+ case 11:
+ O_R == 'O' ? add_11O(sub_tree,tmp_tvb) : add_11R(sub_tree,tmp_tvb);
+ break;
+ case 12:
+ O_R == 'O' ? add_12O(sub_tree,tmp_tvb) : add_12R(sub_tree,tmp_tvb);
+ break;
+ case 13:
+ O_R == 'O' ? add_13O(sub_tree,tmp_tvb) : add_13R(sub_tree,tmp_tvb);
+ break;
+ case 14:
+ O_R == 'O' ? add_14O(sub_tree,tmp_tvb) : add_14R(sub_tree,tmp_tvb);
+ break;
+ case 15:
+ O_R == 'O' ? add_15O(sub_tree,tmp_tvb) : add_15R(sub_tree,tmp_tvb);
+ break;
+ case 16:
+ O_R == 'O' ? add_16O(sub_tree,tmp_tvb) : add_16R(sub_tree,tmp_tvb);
+ break;
+ case 17:
+ O_R == 'O' ? add_17O(sub_tree,tmp_tvb) : add_17R(sub_tree,tmp_tvb);
+ break;
+ case 18:
+ O_R == 'O' ? add_18O(sub_tree,tmp_tvb) : add_18R(sub_tree,tmp_tvb);
+ break;
+ case 19:
+ O_R == 'O' ? add_19O(sub_tree,tmp_tvb) : add_19R(sub_tree,tmp_tvb);
+ break;
+ case 20:
+ O_R == 'O' ? add_20O(sub_tree,tmp_tvb) : add_20R(sub_tree,tmp_tvb);
+ break;
+ case 21:
+ O_R == 'O' ? add_21O(sub_tree,tmp_tvb) : add_21R(sub_tree,tmp_tvb);
+ break;
+ case 22:
+ O_R == 'O' ? add_22O(sub_tree,tmp_tvb) : add_22R(sub_tree,tmp_tvb);
+ break;
+ case 23:
+ O_R == 'O' ? add_23O(sub_tree,tmp_tvb) : add_23R(sub_tree,tmp_tvb);
+ break;
+ case 24:
+ O_R == 'O' ? add_24O(sub_tree,tmp_tvb) : add_24R(sub_tree,tmp_tvb);
+ break;
+ case 30:
+ O_R == 'O' ? add_30O(sub_tree,tmp_tvb) : add_30R(sub_tree,tmp_tvb);
+ break;
+ case 31:
+ O_R == 'O' ? add_31O(sub_tree,tmp_tvb) : add_31R(sub_tree,tmp_tvb);
+ break;
+ case 51: case 52: case 53: case 54: case 55: case 56: case 57:
+ case 58:
+ O_R == 'O' ? add_5xO(sub_tree,tmp_tvb) : add_5xR(sub_tree,tmp_tvb);
+ break;
+ case 60: case 61:
+ O_R == 'O' ? add_6xO(sub_tree,tmp_tvb,OT) : add_6xR(sub_tree,tmp_tvb);
+ break;
+ default:
+ break;
+ }
+ }
+ return;
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_ucp(void)
+{
+
+ /* Setup list of fields */
+ static hf_register_info hf[] = {
+ { &hf_ucp_hdr_TRN,
+ { "Transaction Reference Number", "ucp.hdr.TRN",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Transaction number for this command, used in windowing.",
+ HFILL
+ }
+ },
+ { &hf_ucp_hdr_LEN,
+ { "Length", "ucp.hdr.LEN",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Total number of characters between <stx>...<etx>.",
+ HFILL
+ }
+ },
+ { &hf_ucp_hdr_O_R,
+ { "Type", "ucp.hdr.O_R",
+ FT_UINT8, BASE_DEC, VALS(vals_hdr_O_R), 0x00,
+ "Your basic 'is a request or response'.",
+ HFILL
+ }
+ },
+ { &hf_ucp_hdr_OT,
+ { "Operation", "ucp.hdr.OT",
+ FT_UINT8, BASE_DEC, VALS(vals_hdr_OT), 0x00,
+ "The operation that is requested with this message.",
+ HFILL
+ }
+ },
+ { &hf_ucp_oper_section,
+ { "Data", "ucp.parm",
+ FT_NONE, BASE_DEC, NULL, 0x00,
+ "The actual content of the operation.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_AdC,
+ { "AdC", "ucp.parm.AdC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Address code recipient.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_OAdC,
+ { "OAdC", "ucp.parm.OAdC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Address code originator.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_DAdC,
+ { "DAdC", "ucp.parm.DAdC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Diverted address code.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_AC,
+ { "AC", "ucp.parm.AC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Authentication code.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_OAC,
+ { "OAC", "ucp.parm.OAC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Authentication code, originator.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NAC,
+ { "NAC", "ucp.parm.NAC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "New authentication code.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_BAS,
+ { "BAS", "ucp.parm.BAS",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_BAS), 0x00,
+ "Barring status flag.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LAR,
+ { "LAR", "ucp.parm.LAR",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_LAR), 0x00,
+ "Leg. code for all calls flag.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LAC,
+ { "LAC", "ucp.parm.LAC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "New leg. code for all calls.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_L1R,
+ { "L1R", "ucp.parm.L1R",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_L1R), 0x00,
+ "Leg. code for priority 1 flag.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_L1P,
+ { "L1P", "ucp.parm.L1P",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "New leg. code for level 1 priority.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_L3R,
+ { "L3R", "ucp.parm.L3R",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_L3R), 0x00,
+ "Leg. code for priority 3 flag.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_L3P,
+ { "L3P", "ucp.parm.L3P",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "New leg. code for level 3 priority.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LCR,
+ { "LCR", "ucp.parm.LCR",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_LCR), 0x00,
+ "Leg. code for reverse charging flag.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LUR,
+ { "LUR", "ucp.parm.LUR",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_LUR), 0x00,
+ "Leg. code for urgent message flag.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LRR,
+ { "LRR", "ucp.parm.LRR",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_LRR), 0x00,
+ "Leg. code for repitition flag.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RT,
+ { "RT", "ucp.parm.RT",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_RT), 0x00,
+ "Receiver type.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NoN,
+ { "NoN", "ucp.parm.NoN",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Maximum number of numerical characters accepted.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NoA,
+ { "NoA", "ucp.parm.NoA",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Maximum number of alphanumerical characters accepted.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NoB,
+ { "NoB", "ucp.parm.NoB",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Maximum number of data bits accepted.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_PNC,
+ { "PNC", "ucp.parm.PNC",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_PNC), 0x00,
+ "Paging network controller.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_AMsg,
+ { "AMsg", "ucp.parm.AMsg",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "The alphanumeric message that is being sent.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LNo,
+ { "LNo", "ucp.parm.LNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Standard text list number requested by calling party.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LST,
+ { "LST", "ucp.parm.LST",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Legitimisation code for standard text.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_TNo,
+ { "TNo", "ucp.parm.TNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Standard text number requested by calling party.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_CS,
+ { "CS", "ucp.parm.CS",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Additional character set number.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_PID,
+ { "PID", "ucp.parm.PID",
+ FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
+ "SMT PID value.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NPL,
+ { "NPL", "ucp.parm.NPL",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Number of parameters in the following list.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_GA,
+ { "GA", "ucp.parm.GA",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "GA?? haven't got a clue.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RP,
+ { "RP", "ucp.parm.RP",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_RP), 0x00,
+ "Repitition requested.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LRP,
+ { "LRP", "ucp.parm.LRP",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "Legitimisation code for repitition.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_PR,
+ { "PR", "ucp.parm.PR",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Priority requested.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LPR,
+ { "LPR", "ucp.parm.LPR",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "Legitimisation code for priority requested.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_UM,
+ { "UM", "ucp.parm.UM",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_UM), 0x00,
+ "Urgent message indicator.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LUM,
+ { "LUM", "ucp.parm.LUM",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "Legitimisation code for urgent message.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RC,
+ { "RC", "ucp.parm.RC",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_RC), 0x00,
+ "Reverse charging request.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LRC,
+ { "LRC", "ucp.parm.LRC",
+ FT_STRING, BASE_DEC, NULL, 0x00,
+ "Legitimisation code for reverse charging.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NRq,
+ { "NRq", "ucp.parm.NRq",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_NRq), 0x00,
+ "Notification request.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_GAdC,
+ { "GAdC", "ucp.parm.GAdC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Group address code.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_A_D,
+ { "A_D", "ucp.parm.A_D",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_A_D), 0x00,
+ "Add to/delete from fixed subscriber address list record.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_CT,
+ { "CT", "ucp.parm.CT",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Accumulated charges timestamp.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_AAC,
+ { "AAC", "ucp.parm.AAC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Accumulated charges.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_MNo,
+ { "MNo", "ucp.parm.MNo",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Message number.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_R_T,
+ { "R_T", "ucp.parm.R_T",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_R_T), 0x00,
+ "Message number.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NAdC,
+ { "NAdC", "ucp.parm.NAdC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Notification address.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NT,
+ { "NT", "ucp.parm.NT",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_NT), 0x00,
+ "Notification type.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_IVR5x,
+ { "IVR5x", "ucp.parm.IVR5x",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "UCP release number supported/accepted.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_REQ_OT,
+ { "REQ_OT", "ucp.parm.REQ_OT",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_REQ_OT), 0x00,
+ "UCP release number supported/accepted.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_SSTAT,
+ { "SSTAT", "ucp.parm.SSTAT",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_SSTAT), 0x00,
+ "Supplementary services for which status is requested.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LMN,
+ { "LMN", "ucp.parm.LMN",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Last message number.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NMESS,
+ { "NMESS", "ucp.parm.NMESS",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Number of stored messages.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NMESS_str,
+ { "NMESS_str", "ucp.parm.NMESS_str",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Number of stored messages.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NPID,
+ { "NPID", "ucp.parm.NPID",
+ FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
+ "Notification PID value.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LRq,
+ { "LRq", "ucp.parm.LRq",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_LRq), 0x00,
+ "Last resort address request.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LRAd,
+ { "LRAd", "ucp.parm.LRAd",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Last resort address.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LPID,
+ { "LPID", "ucp.parm.LPID",
+ FT_UINT16, BASE_DEC, VALS(vals_parm_PID), 0x00,
+ "Last resort PID value.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_DD,
+ { "DD", "ucp.parm.DD",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_DD), 0x00,
+ "Deferred delivery requested.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_DDT,
+ { "DDT", "ucp.parm.DDT",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Deferred delivery time.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_STx,
+ { "STx", "ucp.parm.STx",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Standard text.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_ST,
+ { "ST", "ucp.parm.ST",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Start time.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_SP,
+ { "SP", "ucp.parm.SP",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Stop time.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_VP,
+ { "VP", "ucp.parm.VP",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Validity period.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RPID,
+ { "RPID", "ucp.parm.RPID",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Replace PID",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_SCTS,
+ { "SCTS", "ucp.parm.SCTS",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Service Centre timestamp.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_Dst,
+ { "Dst", "ucp.parm.Dst",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_Dst), 0x00,
+ "Delivery status.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_Rsn,
+ { "Rsn", "ucp.parm.Rsn",
+ FT_UINT16, BASE_DEC, VALS(vals_parm_Rsn), 0x00,
+ "Reason code.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_DSCTS,
+ { "DSCTS", "ucp.parm.DSCTS",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Delivery timestamp.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_MT,
+ { "MT", "ucp.parm.MT",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_MT), 0x00,
+ "Message type.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NB,
+ { " NB", "ucp.parm.NB",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "No. of bits in Transparent Data (TD) message.",
+ HFILL
+ }
+ },
+ { &hf_ucp_data_section,
+ { " Data", "ucp.message",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "The actual message or data.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_MMS,
+ { "MMS", "ucp.parm.MMS",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "More messages to send.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_DCs,
+ { "DCs", "ucp.parm.DCs",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_DCs), 0x00,
+ "Data coding scheme (deprecated).",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_MCLs,
+ { "MCLs", "ucp.parm.MCLs",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_MCLs), 0x00,
+ "Message class.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RPI,
+ { "RPI", "ucp.parm.RPI",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_RPI), 0x00,
+ "Reply path.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_CPg,
+ { "CPg", "ucp.parm.CPg",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Reserved for Code Page.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RPLy,
+ { "RPLy", "ucp.parm.RPLy",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Reserved for Reply type.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_OTOA,
+ { "OTOA", "ucp.parm.OTOA",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Originator Type Of Address.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_HPLMN,
+ { "HPLMN", "ucp.parm.HPLMN",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Home PLMN address.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_XSer,
+ { "Extra services:", "ucp.parm.XSer",
+ FT_NONE, BASE_DEC, NULL, 0x00,
+ "Extra services.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RES4,
+ { "RES4", "ucp.parm.RES4",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Reserved for future use.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RES5,
+ { "RES5", "ucp.parm.RES5",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Reserved for future use.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_OTON,
+ { "OTON", "ucp.parm.OTON",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_OTON), 0x00,
+ "Originator type of number.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_ONPI,
+ { "ONPI", "ucp.parm.ONPI",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_ONPI), 0x00,
+ "Originator numbering plan id.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_STYP0,
+ { "STYP0", "ucp.parm.STYP0",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_STYP0), 0x00,
+ "Subtype of operation.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_STYP1,
+ { "STYP1", "ucp.parm.STYP1",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_STYP1), 0x00,
+ "Subtype of operation.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_PWD,
+ { "PWD", "ucp.parm.PWD",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Current password.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_NPWD,
+ { "NPWD", "ucp.parm.NPWD",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "New password.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_VERS,
+ { "VERS", "ucp.parm.VERS",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Version number.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LAdC,
+ { "LAdC", "ucp.parm.LAdC",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Address for VSMSC list operation.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LTON,
+ { "LTON", "ucp.parm.LTON",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Type of number list address.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_LNPI,
+ { "LNPI", "ucp.parm.LNPI",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Numbering plan id. list address.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_OPID,
+ { "OPID", "ucp.parm.OPID",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_OPID), 0x00,
+ "Originator protocol identifier.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RES1,
+ { "RES1", "ucp.parm.RES1",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Reserved for future use.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_RES2,
+ { "RES2", "ucp.parm.RES2",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Reserved for future use.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_ACK,
+ { "(N)Ack", "ucp.parm.ACK",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_ACK), 0x00,
+ "Positive or negative acknowledge of the operation.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_MVP,
+ { "MVP", "ucp.parm.MVP",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Mofified validity period.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_EC,
+ { "Error code", "ucp.parm.EC",
+ FT_UINT8, BASE_DEC, VALS(vals_parm_EC), 0x00,
+ "The result of the requested operation.",
+ HFILL
+ }
+ },
+ { &hf_ucp_parm_SM,
+ { "SM", "ucp.parm.SM",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "System message.",
+ HFILL
+ }
+ },
+ { &hf_xser_service,
+ { "Type of service", "ucp.xser.service",
+ FT_UINT8, BASE_HEX, VALS(vals_xser_service), 0x00,
+ "The type of service specified.",
+ HFILL
+ }
+ },
+ };
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_ucp,
+ &ett_sub,
+ &ett_XSer
+ };
+ /* Register the protocol name and description */
+ proto_ucp = proto_register_protocol("Universal Computer Protocol",
+ "UCP", "ucp");
+
+ /* Required function calls to register header fields and subtrees used */
+ proto_register_field_array(proto_ucp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+/*
+ * If dissector uses sub-dissector registration add a registration routine.
+ * This format is required because a script is used to find these routines and
+ * create the code that calls these routines.
+ */
+void
+proto_reg_handoff_ucp(void)
+{
+ dissector_handle_t ucp_handle;
+
+ /*
+ * UCP can be spoken on any port so, when not on a specific port, try this
+ * one whenever TCP is spoken.
+ */
+ heur_dissector_add("tcp", dissect_ucp_heur, proto_ucp);
+
+ /*
+ * Also register as one that can be selected by a TCP port number.
+ */
+ ucp_handle = create_dissector_handle(dissect_ucp, proto_ucp);
+ dissector_add_handle("tcp.port", ucp_handle);
+}
diff --git a/epan/dissectors/packet-udp.c b/epan/dissectors/packet-udp.c
new file mode 100644
index 0000000000..a905d46408
--- /dev/null
+++ b/epan/dissectors/packet-udp.c
@@ -0,0 +1,356 @@
+/* packet-udp.c
+ * Routines for UDP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Richard Sharpe, 13-Feb-1999, added dispatch table support and
+ * support for tftp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "ipproto.h"
+#include "in_cksum.h"
+#include "prefs.h"
+
+#include "packet-udp.h"
+
+#include "packet-ip.h"
+#include <epan/conversation.h>
+#include "tap.h"
+
+static int udp_tap = -1;
+
+static int proto_udp = -1;
+static int hf_udp_srcport = -1;
+static int hf_udp_dstport = -1;
+static int hf_udp_port = -1;
+static int hf_udp_length = -1;
+static int hf_udp_checksum = -1;
+static int hf_udp_checksum_bad = -1;
+
+static gint ett_udp = -1;
+
+/* Place UDP summary in proto tree */
+static gboolean udp_summary_in_tree = TRUE;
+
+static dissector_table_t udp_dissector_table;
+static heur_dissector_list_t heur_subdissector_list;
+static dissector_handle_t data_handle;
+
+/* Determine if there is a sub-dissector and call it. This has been */
+/* separated into a stand alone routine to other protocol dissectors */
+/* can call to it, ie. socks */
+
+static gboolean try_heuristic_first = FALSE;
+
+void
+decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, int uh_sport, int uh_dport, int uh_ulen)
+{
+ tvbuff_t *next_tvb;
+ int low_port, high_port;
+ gint len, reported_len;
+
+ len = tvb_length_remaining(tvb, offset);
+ reported_len = tvb_reported_length_remaining(tvb, offset);
+ if (uh_ulen != -1) {
+ /* This is the length from the UDP header; the payload should be cut
+ off at that length.
+ XXX - what if it's *greater* than the reported length? */
+ if (uh_ulen < len)
+ len = uh_ulen;
+ if (uh_ulen < reported_len)
+ reported_len = uh_ulen;
+ }
+ next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
+
+/* determine if this packet is part of a conversation and call dissector */
+/* for the conversation if available */
+
+ if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_UDP,
+ uh_sport, uh_dport, next_tvb, pinfo, tree))
+ return;
+
+ if (try_heuristic_first) {
+ /* do lookup with the heuristic subdissector table */
+ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
+ return;
+ }
+
+ /* Do lookups with the subdissector table.
+ We try the port number with the lower value first, followed by the
+ port number with the higher value. This means that, for packets
+ where a dissector is registered for *both* port numbers:
+
+ 1) we pick the same dissector for traffic going in both directions;
+
+ 2) we prefer the port number that's more likely to be the right
+ one (as that prefers well-known ports to reserved ports);
+
+ although there is, of course, no guarantee that any such strategy
+ will always pick the right port number.
+
+ XXX - we ignore port numbers of 0, as some dissectors use a port
+ number of 0 to disable the port, and as RFC 768 says that the source
+ port in UDP datagrams is optional and is 0 if not used. */
+ if (uh_sport > uh_dport) {
+ low_port = uh_dport;
+ high_port = uh_sport;
+ } else {
+ low_port = uh_sport;
+ high_port = uh_dport;
+ }
+ if (low_port != 0 &&
+ dissector_try_port(udp_dissector_table, low_port, next_tvb, pinfo, tree))
+ return;
+ if (high_port != 0 &&
+ dissector_try_port(udp_dissector_table, high_port, next_tvb, pinfo, tree))
+ return;
+
+ if (!try_heuristic_first) {
+ /* do lookup with the heuristic subdissector table */
+ if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree))
+ return;
+ }
+
+ call_dissector(data_handle,next_tvb, pinfo, tree);
+}
+
+
+static void
+dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *udp_tree;
+ proto_item *ti;
+ guint len;
+ guint reported_len;
+ vec_t cksum_vec[4];
+ guint32 phdr[2];
+ guint16 computed_cksum;
+ int offset = 0;
+ static e_udphdr udphstruct[4], *udph;
+ static int udph_count=0;
+
+ udph_count++;
+ if(udph_count>=4){
+ udph_count=0;
+ }
+ udph=&udphstruct[udph_count];
+ SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
+ SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ udph->uh_sport=tvb_get_ntohs(tvb, offset);
+ udph->uh_dport=tvb_get_ntohs(tvb, offset+2);
+ udph->uh_ulen=tvb_get_ntohs(tvb, offset+4);
+ udph->uh_sum=tvb_get_ntohs(tvb, offset+6);
+
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s Destination port: %s",
+ get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport));
+
+ if (tree) {
+ if (udp_summary_in_tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8,
+ "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
+ get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
+ } else {
+ ti = proto_tree_add_item(tree, proto_udp, tvb, offset, 8, FALSE);
+ }
+ udp_tree = proto_item_add_subtree(ti, ett_udp);
+
+ proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport,
+ "Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport);
+ proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport,
+ "Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport);
+
+ proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport);
+ proto_tree_add_uint_hidden(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport);
+
+ if (udph->uh_ulen < 8) {
+ /* Bogus length - it includes the header, so it must be >= 8. */
+ proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2,
+ udph->uh_ulen, "Length: %u (bogus, must be >= 8)", udph->uh_ulen);
+ return;
+ }
+ proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen);
+ reported_len = tvb_reported_length(tvb);
+ len = tvb_length(tvb);
+ if (udph->uh_sum == 0) {
+ /* No checksum supplied in the packet. */
+ proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
+ offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x (none)", udph->uh_sum);
+ } else if (!pinfo->fragmented && len >= reported_len &&
+ len >= udph->uh_ulen && reported_len >= udph->uh_ulen) {
+ /* The packet isn't part of a fragmented datagram and isn't
+ truncated, so we can checksum it.
+ XXX - make a bigger scatter-gather list once we do fragment
+ reassembly? */
+
+ /* Set up the fields of the pseudo-header. */
+ cksum_vec[0].ptr = pinfo->src.data;
+ cksum_vec[0].len = pinfo->src.len;
+ cksum_vec[1].ptr = pinfo->dst.data;
+ cksum_vec[1].len = pinfo->dst.len;
+ cksum_vec[2].ptr = (const guint8 *)&phdr;
+ switch (pinfo->src.type) {
+
+ case AT_IPv4:
+ phdr[0] = g_htonl((IP_PROTO_UDP<<16) + udph->uh_ulen);
+ cksum_vec[2].len = 4;
+ break;
+
+ case AT_IPv6:
+ phdr[0] = g_htonl(udph->uh_ulen);
+ phdr[1] = g_htonl(IP_PROTO_UDP);
+ cksum_vec[2].len = 8;
+ break;
+
+ default:
+ /* TCP runs only atop IPv4 and IPv6.... */
+ g_assert_not_reached();
+ break;
+ }
+ cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, udph->uh_ulen);
+ cksum_vec[3].len = udph->uh_ulen;
+ computed_cksum = in_cksum(&cksum_vec[0], 4);
+ if (computed_cksum == 0) {
+ proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
+ offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x (correct)", udph->uh_sum);
+ } else {
+ proto_tree_add_boolean_hidden(udp_tree, hf_udp_checksum_bad, tvb,
+ offset + 6, 2, TRUE);
+ proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
+ offset + 6, 2, udph->uh_sum,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)", udph->uh_sum,
+ in_cksum_shouldbe(udph->uh_sum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
+ offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x", udph->uh_sum);
+ }
+ }
+
+ /* Skip over header */
+ offset += 8;
+
+ pinfo->ptype = PT_UDP;
+ pinfo->srcport = udph->uh_sport;
+ pinfo->destport = udph->uh_dport;
+
+ tap_queue_packet(udp_tap, pinfo, udph);
+ /*
+ * Call sub-dissectors.
+ *
+ * XXX - should we do this if this is included in an error packet?
+ * It might be nice to see the details of the packet that caused the
+ * ICMP error, but it might not be nice to have the dissector update
+ * state based on it.
+ * Also, we probably don't want to run UDP taps on those packets.
+ *
+ * We definitely don't want to do it for an error packet if there's
+ * nothing left in the packet.
+ */
+ if (!pinfo->in_error_pkt || tvb_length_remaining(tvb, offset) > 0)
+ decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport,
+ udph->uh_ulen);
+}
+
+void
+proto_register_udp(void)
+{
+ module_t *udp_module;
+ static hf_register_info hf[] = {
+ { &hf_udp_srcport,
+ { "Source Port", "udp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_udp_dstport,
+ { "Destination Port", "udp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_udp_port,
+ { "Source or Destination Port", "udp.port", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_udp_length,
+ { "Length", "udp.length", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_udp_checksum_bad,
+ { "Bad Checksum", "udp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_udp_checksum,
+ { "Checksum", "udp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_udp,
+ };
+
+ proto_udp = proto_register_protocol("User Datagram Protocol",
+ "UDP", "udp");
+ proto_register_field_array(proto_udp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+/* subdissector code */
+ udp_dissector_table = register_dissector_table("udp.port",
+ "UDP port", FT_UINT16, BASE_DEC);
+ register_heur_dissector_list("udp", &heur_subdissector_list);
+
+ /* Register configuration preferences */
+ udp_module = prefs_register_protocol(proto_udp, NULL);
+ prefs_register_bool_preference(udp_module, "summary_in_tree",
+ "Show UDP summary in protocol tree",
+ "Whether the UDP summary line should be shown in the protocol tree",
+ &udp_summary_in_tree);
+ prefs_register_bool_preference(udp_module, "try_heuristic_first",
+ "Try heuristic sub-dissectors first",
+ "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port",
+ &try_heuristic_first);
+}
+
+void
+proto_reg_handoff_udp(void)
+{
+ dissector_handle_t udp_handle;
+
+ udp_handle = create_dissector_handle(dissect_udp, proto_udp);
+ dissector_add("ip.proto", IP_PROTO_UDP, udp_handle);
+ data_handle = find_dissector("data");
+ udp_tap = register_tap("udp");
+}
diff --git a/epan/dissectors/packet-udp.h b/epan/dissectors/packet-udp.h
new file mode 100644
index 0000000000..06fd66c708
--- /dev/null
+++ b/epan/dissectors/packet-udp.h
@@ -0,0 +1,42 @@
+/* packet-udp.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_UDP_H__
+#define __PACKET_UDP_H__
+
+/* UDP structs and definitions */
+typedef struct _e_udphdr {
+ guint16 uh_sport;
+ guint16 uh_dport;
+ guint16 uh_ulen;
+ guint16 uh_sum;
+ address ip_src;
+ address ip_dst;
+} e_udphdr;
+
+
+extern void decode_udp_ports(tvbuff_t *, int, packet_info *,
+ proto_tree *, int, int, int);
+
+#endif
diff --git a/epan/dissectors/packet-v120.c b/epan/dissectors/packet-v120.c
new file mode 100644
index 0000000000..b47668fc2a
--- /dev/null
+++ b/epan/dissectors/packet-v120.c
@@ -0,0 +1,305 @@
+/* packet-v120.c
+ * Routines for v120 frame disassembly
+ * Bert Driehuis <driehuis@playbeing.org>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "xdlc.h"
+
+static int proto_v120 = -1;
+static int hf_v120_address = -1;
+static int hf_v120_control = -1;
+static int hf_v120_n_r = -1;
+static int hf_v120_n_s = -1;
+static int hf_v120_p = -1;
+static int hf_v120_p_ext = -1;
+static int hf_v120_f = -1;
+static int hf_v120_f_ext = -1;
+static int hf_v120_s_ftype = -1;
+static int hf_v120_u_modifier_cmd = -1;
+static int hf_v120_u_modifier_resp = -1;
+static int hf_v120_ftype_i = -1;
+static int hf_v120_ftype_s_u = -1;
+static int hf_v120_ftype_s_u_ext = -1;
+static int hf_v120_header = -1;
+
+static gint ett_v120 = -1;
+static gint ett_v120_address = -1;
+static gint ett_v120_control = -1;
+static gint ett_v120_header = -1;
+
+static dissector_handle_t data_handle;
+
+static int dissect_v120_header(tvbuff_t *tvb, int offset, proto_tree *tree);
+
+/* Used only for U frames */
+static const xdlc_cf_items v120_cf_items = {
+ NULL,
+ NULL,
+ &hf_v120_p,
+ &hf_v120_f,
+ NULL,
+ &hf_v120_u_modifier_cmd,
+ &hf_v120_u_modifier_resp,
+ NULL,
+ &hf_v120_ftype_s_u
+};
+
+/* Used only for I and S frames */
+static const xdlc_cf_items v120_cf_items_ext = {
+ &hf_v120_n_r,
+ &hf_v120_n_s,
+ &hf_v120_p_ext,
+ &hf_v120_f_ext,
+ &hf_v120_s_ftype,
+ NULL,
+ NULL,
+ &hf_v120_ftype_i,
+ &hf_v120_ftype_s_u_ext
+};
+
+static void
+dissect_v120(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *v120_tree, *tc, *address_tree;
+ proto_item *ti;
+ int is_response;
+ int addr;
+ char info[80];
+ int v120len;
+ guint8 byte0, byte1;
+ guint16 control;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "V.120");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ byte0 = tvb_get_guint8(tvb, 0);
+
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_add_fstr(pinfo->cinfo, COL_RES_DL_SRC, "0x%02X", byte0);
+
+ byte1 = tvb_get_guint8(tvb, 1);
+
+ if ((byte0 & 0x01) != 0x00 && (byte1 && 0x01) != 0x01)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Invalid V.120 frame");
+ if (tree)
+ ti = proto_tree_add_protocol_format(tree, proto_v120, tvb, 0, -1,
+ "Invalid V.120 frame");
+ return;
+ }
+
+ if (pinfo->p2p_dir == P2P_DIR_SENT) {
+ is_response = (byte0 & 0x02) ? FALSE: TRUE;
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
+ } else {
+ /* XXX - what if the direction is unknown? */
+ is_response = (byte0 & 0x02) ? TRUE : FALSE;
+ if(check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
+ if(check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
+ }
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_v120, tvb, 0, -1, "V.120");
+ v120_tree = proto_item_add_subtree(ti, ett_v120);
+ addr = byte1 << 8 | byte0;
+ sprintf(info, "LLI: %d C/R: %s",
+ ((byte0 & 0xfc) << 5) | ((byte1 & 0xfe) >> 1),
+ byte0 & 0x02 ? "R" : "C");
+ tc = proto_tree_add_text(v120_tree, tvb,
+ 0, 2,
+ "Address field: %s", info);
+ address_tree = proto_item_add_subtree(tc, ett_v120_address);
+ proto_tree_add_text(address_tree, tvb, 0, 2,
+ decode_boolean_bitfield(addr, 0x0002, 2*8,
+ "Response", "Command"), NULL);
+ sprintf(info, "LLI: %d", ((byte0 & 0xfc) << 5) | ((byte1 & 0xfe) >> 1));
+ proto_tree_add_text(address_tree, tvb, 0, 2,
+ decode_numeric_bitfield(addr, 0xfefc, 2*8, info));
+ proto_tree_add_text(address_tree, tvb, 0, 2,
+ decode_boolean_bitfield(addr, 0x0001, 2*8,
+ "EA0 = 1 (Error)", "EA0 = 0"), NULL);
+ proto_tree_add_text(address_tree, tvb, 0, 2,
+ decode_boolean_bitfield(addr, 0x0100, 2*8,
+ "EA1 = 1", "EA1 = 0 (Error)"), NULL);
+ }
+ else {
+ v120_tree = NULL;
+ ti = NULL;
+ }
+ control = dissect_xdlc_control(tvb, 2, pinfo, v120_tree, hf_v120_control,
+ ett_v120_control, &v120_cf_items, &v120_cf_items_ext,
+ NULL, NULL, is_response, TRUE, FALSE);
+ if (tree) {
+ v120len = 2 + XDLC_CONTROL_LEN(control, TRUE);
+ if (tvb_bytes_exist(tvb, v120len, 1))
+ v120len += dissect_v120_header(tvb, v120len, v120_tree);
+ proto_item_set_len(ti, v120len);
+ next_tvb = tvb_new_subset(tvb, v120len, -1, -1);
+ call_dissector(data_handle,next_tvb, pinfo, v120_tree);
+ }
+}
+
+static int
+dissect_v120_header(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ char info[80];
+ int header_len, nbits;
+ int header;
+ proto_tree *h_tree, *tc;
+ guint8 byte0;
+
+ byte0 = tvb_get_guint8(tvb, offset);
+
+ if (byte0 & 0x80) {
+ header_len = 1;
+ header = byte0;
+ } else {
+ header_len = 2;
+ header = byte0 | tvb_get_guint8(tvb, offset + 1) << 8;
+ }
+ nbits = header_len * 8;
+ sprintf(info, "Header: B: %d F: %d", byte0 & 0x02 ? 1:0,
+ byte0 & 0x01 ? 1:0);
+ tc = proto_tree_add_text(tree, tvb,
+ offset, header_len,
+ "Header octet: %s (0x%02X)", info, byte0);
+ h_tree = proto_item_add_subtree(tc, ett_v120_header);
+ proto_tree_add_text(h_tree, tvb, offset, header_len,
+ decode_boolean_bitfield(header, 0x80, nbits,
+ "No extension octet", "Extension octet follows"), NULL);
+ proto_tree_add_text(h_tree, tvb, offset, header_len,
+ decode_boolean_bitfield(header, 0x40, nbits,
+ "Break condition", "No break condition"), NULL);
+ sprintf(info, "Error control C1/C2: %d", (header & 0x0c) >> 2);
+ proto_tree_add_text(h_tree, tvb, offset, header_len,
+ decode_numeric_bitfield(header, 0x0c, nbits, info));
+ proto_tree_add_text(h_tree, tvb, offset, header_len,
+ decode_boolean_bitfield(header, 0x02, nbits,
+ "Segmentation bit B", "No segmentation bit B"), NULL);
+ proto_tree_add_text(h_tree, tvb, offset, header_len,
+ decode_boolean_bitfield(header, 0x01, nbits,
+ "Segmentation bit F", "No segmentation bit F"), NULL);
+ if (header_len == 2) {
+ proto_tree_add_text(h_tree, tvb, offset, header_len,
+ decode_boolean_bitfield(header, 0x8000, nbits,
+ "E", "E bit not set (Error)"), NULL);
+ proto_tree_add_text(h_tree, tvb, offset, header_len,
+ decode_boolean_bitfield(header, 0x4000, nbits,
+ "DR", "No DR"), NULL);
+ proto_tree_add_text(h_tree, tvb, offset, header_len,
+ decode_boolean_bitfield(header, 0x2000, nbits,
+ "SR", "No SR"), NULL);
+ proto_tree_add_text(h_tree, tvb, offset, header_len,
+ decode_boolean_bitfield(header, 0x1000, nbits,
+ "RR", "No RR"), NULL);
+ }
+ return header_len;
+}
+
+void
+proto_register_v120(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_v120_address,
+ { "Link Address", "v120.address", FT_UINT16, BASE_HEX, NULL,
+ 0x0, "", HFILL }},
+ { &hf_v120_control,
+ { "Control Field", "v120.control", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+ { &hf_v120_n_r,
+ { "N(R)", "v120.control.n_r", FT_UINT16, BASE_DEC,
+ NULL, XDLC_N_R_EXT_MASK, "", HFILL }},
+ { &hf_v120_n_s,
+ { "N(S)", "v120.control.n_s", FT_UINT16, BASE_DEC,
+ NULL, XDLC_N_S_EXT_MASK, "", HFILL }},
+ { &hf_v120_p,
+ { "Poll", "v120.control.p", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+ { &hf_v120_p_ext,
+ { "Poll", "v120.control.p", FT_BOOLEAN, 16,
+ TFS(&flags_set_truth), XDLC_P_F_EXT, "", HFILL }},
+ { &hf_v120_f,
+ { "Final", "v120.control.f", FT_BOOLEAN, 8,
+ TFS(&flags_set_truth), XDLC_P_F, "", HFILL }},
+ { &hf_v120_f_ext,
+ { "Final", "v120.control.f", FT_BOOLEAN, 16,
+ TFS(&flags_set_truth), XDLC_P_F_EXT, "", HFILL }},
+ { &hf_v120_s_ftype,
+ { "Supervisory frame type", "v120.control.s_ftype", FT_UINT16, BASE_HEX,
+ VALS(stype_vals), XDLC_S_FTYPE_MASK, "", HFILL }},
+ { &hf_v120_u_modifier_cmd,
+ { "Command", "v120.control.u_modifier_cmd", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, "", HFILL }},
+ { &hf_v120_u_modifier_resp,
+ { "Response", "v120.control.u_modifier_resp", FT_UINT8, BASE_HEX,
+ VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, "", HFILL }},
+ { &hf_v120_ftype_i,
+ { "Frame type", "v120.control.ftype", FT_UINT16, BASE_HEX,
+ VALS(ftype_vals), XDLC_I_MASK, "", HFILL }},
+ { &hf_v120_ftype_s_u,
+ { "Frame type", "v120.control.ftype", FT_UINT8, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+ { &hf_v120_ftype_s_u_ext,
+ { "Frame type", "v120.control.ftype", FT_UINT16, BASE_HEX,
+ VALS(ftype_vals), XDLC_S_U_MASK, "", HFILL }},
+ { &hf_v120_header,
+ { "Header Field", "v120.header", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_v120,
+ &ett_v120_address,
+ &ett_v120_control,
+ &ett_v120_header,
+ };
+
+ proto_v120 = proto_register_protocol("Async data over ISDN (V.120)",
+ "V.120", "v120");
+ proto_register_field_array (proto_v120, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("v120", dissect_v120, proto_v120);
+}
+
+void
+proto_reg_handoff_v120(void)
+{
+ data_handle = find_dissector("data");
+}
diff --git a/epan/dissectors/packet-vines.c b/epan/dissectors/packet-vines.c
new file mode 100644
index 0000000000..4440012385
--- /dev/null
+++ b/epan/dissectors/packet-vines.c
@@ -0,0 +1,1661 @@
+/* packet-vines.c
+ * Routines for Banyan VINES protocol packet disassembly
+ *
+ * $Id$
+ *
+ * Don Lafontaine <lafont02@cn.ca>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ * Joerg Mayer <jmayer@loplof.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-vines.h"
+#include "etypes.h"
+#include "ppptypes.h"
+#include "ipproto.h"
+#include "arcnet_pids.h"
+#include "llcsaps.h"
+
+#define UDP_PORT_VINES 573
+
+static int proto_vines_frp = -1;
+
+static gint ett_vines_frp = -1;
+
+static int proto_vines_llc = -1;
+
+static gint ett_vines_llc = -1;
+
+static int proto_vines_ip = -1;
+static int hf_vines_ip_protocol = -1;
+
+static gint ett_vines_ip = -1;
+static gint ett_vines_ip_tctl = -1;
+
+static int proto_vines_echo = -1;
+
+static gint ett_vines_echo = -1;
+
+static int proto_vines_ipc = -1;
+
+static gint ett_vines_ipc = -1;
+static gint ett_vines_ipc_control = -1;
+
+static int proto_vines_spp = -1;
+
+static gint ett_vines_spp = -1;
+static gint ett_vines_spp_control = -1;
+
+static int proto_vines_arp = -1;
+
+static gint ett_vines_arp = -1;
+
+static int proto_vines_rtp = -1;
+
+static gint ett_vines_rtp = -1;
+static gint ett_vines_rtp_compatibility_flags = -1;
+static gint ett_vines_rtp_req_info = -1;
+static gint ett_vines_rtp_control_flags = -1;
+static gint ett_vines_rtp_mtype = -1;
+static gint ett_vines_rtp_flags = -1;
+
+static int proto_vines_icp = -1;
+
+static gint ett_vines_icp = -1;
+
+void
+capture_vines(packet_counts *ld)
+{
+ ld->vines++;
+}
+
+static dissector_handle_t vines_ip_handle;
+static dissector_handle_t data_handle;
+
+/* AFAIK Vines FRP (Fragmentation Protocol) is used on all media except
+ * Ethernet and TR (and probably FDDI) - Fragmentation on these media types
+ * is not possible
+ * FIXME: Do we need to use this header with PPP too?
+ */
+static void
+dissect_vines_frp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 vines_frp_ctrl;
+ proto_tree *vines_frp_tree;
+ proto_item *ti;
+ gchar frp_flags_str[32];
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines FRP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vines_frp, tvb, 0, 2,
+ FALSE);
+ vines_frp_tree = proto_item_add_subtree(ti, ett_vines_frp);
+
+ vines_frp_ctrl = tvb_get_guint8(tvb, 0);
+
+ /*
+ * 1: first fragment of vines packet
+ * 2: last fragment of vines packet
+ * 4 ... 80: unused
+ */
+ switch (vines_frp_ctrl) {
+
+ case 0:
+ strcpy(frp_flags_str, "middle");
+ break;
+
+ case 1:
+ strcpy(frp_flags_str, "first");
+ break;
+
+ case 2:
+ strcpy(frp_flags_str, "last");
+ break;
+
+ case 3:
+ strcpy(frp_flags_str, "only");
+ break;
+
+ default:
+ strcpy(frp_flags_str, "please report: unknown");
+ break;
+ }
+
+ proto_tree_add_text(vines_frp_tree, tvb, 0, 1,
+ "Control Flags: 0x%02x = %s fragment",
+ vines_frp_ctrl, frp_flags_str);
+
+ proto_tree_add_text(vines_frp_tree, tvb, 1, 1,
+ "Sequence Number: 0x%02x",
+ tvb_get_guint8(tvb, 1));
+ }
+
+ /* Decode the "real" Vines now */
+ next_tvb = tvb_new_subset(tvb, 2, -1, -1);
+ call_dissector(vines_ip_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_register_vines_frp(void)
+{
+ static gint *ett[] = {
+ &ett_vines_frp,
+ };
+
+ proto_vines_frp = proto_register_protocol(
+ "Banyan Vines Fragmentation Protocol", "Vines FRP", "vines_frp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_vines_frp(void)
+{
+ dissector_handle_t vines_frp_handle;
+
+ vines_frp_handle = create_dissector_handle(dissect_vines_frp,
+ proto_vines_frp);
+ dissector_add("ip.proto", IP_PROTO_VINES, vines_frp_handle);
+
+ /* XXX: AFAIK, src and dst port must be the same; should
+ the dissector check for that? */
+ dissector_add("udp.port", UDP_PORT_VINES, vines_frp_handle);
+}
+
+static dissector_table_t vines_llc_dissector_table;
+
+#define VINES_LLC_IP 0xba
+#define VINES_LLC_ECHO 0xbb
+
+static const value_string vines_llc_ptype_vals[] = {
+ { VINES_LLC_IP, "Vines IP" },
+ { VINES_LLC_ECHO, "Vines Echo" },
+ { 0, NULL }
+};
+
+static void
+dissect_vines_llc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 ptype;
+ proto_tree *vines_llc_tree;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines LLC");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ptype = tvb_get_guint8(tvb, 0);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(ptype, vines_llc_ptype_vals,
+ "Unknown protocol 0x%02x"));
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vines_llc, tvb, 0, 1,
+ FALSE);
+ vines_llc_tree = proto_item_add_subtree(ti, ett_vines_llc);
+
+ proto_tree_add_text(vines_llc_tree, tvb, 0, 1,
+ "Packet Type: %s (0x%02x)",
+ val_to_str(ptype, vines_llc_ptype_vals,
+ "Unknown"),
+ ptype);
+ }
+
+ next_tvb = tvb_new_subset(tvb, 1, -1, -1);
+ if (!dissector_try_port(vines_llc_dissector_table, ptype,
+ next_tvb, pinfo, tree))
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_register_vines_llc(void)
+{
+ static gint *ett[] = {
+ &ett_vines_llc,
+ };
+
+ proto_vines_llc = proto_register_protocol(
+ "Banyan Vines LLC", "Vines LLC", "vines_llc");
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ vines_llc_dissector_table = register_dissector_table("vines_llc.ptype",
+ "Vines LLC protocol", FT_UINT8, BASE_HEX);
+}
+
+void
+proto_reg_handoff_vines_llc(void)
+{
+ dissector_handle_t vines_llc_handle;
+
+ vines_llc_handle = create_dissector_handle(dissect_vines_llc,
+ proto_vines_llc);
+ dissector_add("llc.dsap", SAP_VINES2, vines_llc_handle);
+}
+
+static dissector_table_t vines_ip_dissector_table;
+
+static const value_string class_vals[] = {
+ { 0x00, "Reachable regardless of cost" },
+ { 0x10, "Reachable without cost" },
+ { 0x20, "Reachable with low cost (>= 4800 bps)" },
+ { 0x30, "Reachable via LAN" },
+ { 0, NULL }
+};
+
+static const value_string proto_vals[] = {
+ { VIP_PROTO_IPC, "IPC" },
+ { VIP_PROTO_SPP, "SPP" },
+ { VIP_PROTO_ARP, "ARP" },
+ { VIP_PROTO_RTP, "RTP" },
+ { VIP_PROTO_ICP, "ICP" },
+ { 0, NULL }
+};
+
+static const guint8 bcast_addr[VINES_ADDR_LEN] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static void
+dissect_vines_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ e_vip viph;
+ proto_tree *vip_tree, *tctl_tree;
+ proto_item *ti;
+ const guint8 *dst_addr, *src_addr;
+ gboolean is_broadcast = FALSE;
+ int hops = 0;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines IP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* To do: check for runts, errs, etc. */
+
+ /* Avoids alignment problems on many architectures. */
+ tvb_memcpy(tvb, (guint8 *)&viph, offset, sizeof(e_vip));
+
+ viph.vip_chksum = g_ntohs(viph.vip_chksum);
+ viph.vip_pktlen = g_ntohs(viph.vip_pktlen);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)",
+ val_to_str(viph.vip_proto, proto_vals,
+ "Unknown VIP protocol"),
+ viph.vip_proto);
+ }
+
+ src_addr = tvb_get_ptr(tvb, offset+12, VINES_ADDR_LEN);
+ SET_ADDRESS(&pinfo->net_src, AT_VINES, VINES_ADDR_LEN, src_addr);
+ SET_ADDRESS(&pinfo->src, AT_VINES, VINES_ADDR_LEN, src_addr);
+ dst_addr = tvb_get_ptr(tvb, offset+6, VINES_ADDR_LEN);
+ SET_ADDRESS(&pinfo->net_dst, AT_VINES, VINES_ADDR_LEN,dst_addr);
+ SET_ADDRESS(&pinfo->dst, AT_VINES, VINES_ADDR_LEN, dst_addr);
+
+ /* helpers to transport control */
+ if (memcmp(viph.vip_dst, bcast_addr, VINES_ADDR_LEN) == 0)
+ is_broadcast = TRUE;
+ hops = viph.vip_tctl & 0xf;
+
+ /*
+ * Adjust the length of this tvbuff to include only the Vines IP
+ * datagram.
+ */
+ set_actual_length(tvb, viph.vip_pktlen);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vines_ip, tvb,
+ offset, viph.vip_pktlen,
+ FALSE);
+ vip_tree = proto_item_add_subtree(ti, ett_vines_ip);
+ proto_tree_add_text(vip_tree, tvb, offset, 2,
+ "Packet checksum: 0x%04x",
+ viph.vip_chksum);
+ proto_tree_add_text(vip_tree, tvb, offset + 2, 2,
+ "Packet length: %u",
+ viph.vip_pktlen);
+ ti = proto_tree_add_text(vip_tree, tvb, offset + 4, 1,
+ "Transport control: 0x%02x",
+ viph.vip_tctl);
+ tctl_tree = proto_item_add_subtree(ti, ett_vines_ip_tctl);
+ /*
+ * XXX - bit 0x80 is "Normal" if 0; what is it if 1?
+ */
+ if (is_broadcast) {
+ proto_tree_add_text(tctl_tree, tvb, offset + 4, 1,
+ decode_boolean_bitfield(viph.vip_tctl, 0x40, 1*8,
+ "Router nodes",
+ "All nodes"));
+ proto_tree_add_text(tctl_tree, tvb, offset + 4, 1, "%s",
+ decode_enumerated_bitfield(viph.vip_tctl, 0x30, 1*8,
+ class_vals, "%s"));
+ } else {
+ proto_tree_add_text(tctl_tree, tvb, offset + 4, 1,
+ decode_boolean_bitfield(viph.vip_tctl, 0x40, 1*8,
+ "Forwarding router can handle redirect packets",
+ "Forwarding router cannot handle redirect packets"));
+ proto_tree_add_text(tctl_tree, tvb, offset + 4, 1,
+ decode_boolean_bitfield(viph.vip_tctl, 0x20, 1*8,
+ "Return metric notification packet",
+ "Do not return metric notification packet"));
+ proto_tree_add_text(tctl_tree, tvb, offset + 4, 1,
+ decode_boolean_bitfield(viph.vip_tctl, 0x10, 1*8,
+ "Return exception notification packet",
+ "Do not return exception notification packet"));
+ }
+ proto_tree_add_text(tctl_tree, tvb, offset + 4, 1,
+ decode_numeric_bitfield(viph.vip_tctl, 0x0F, 1*8,
+ "Hop count remaining = %u"));
+ proto_tree_add_uint(vip_tree, hf_vines_ip_protocol, tvb,
+ offset + 5, 1,
+ viph.vip_proto);
+ proto_tree_add_text(vip_tree, tvb, offset + 6,
+ VINES_ADDR_LEN,
+ "Destination: %s",
+ vines_addr_to_str(dst_addr));
+ proto_tree_add_text(vip_tree, tvb, offset + 12,
+ VINES_ADDR_LEN,
+ "Source: %s",
+ vines_addr_to_str(src_addr));
+ }
+
+ offset += 18;
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (!dissector_try_port(vines_ip_dissector_table, viph.vip_proto,
+ next_tvb, pinfo, tree))
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_register_vines_ip(void)
+{
+ static gint *ett[] = {
+ &ett_vines_ip,
+ &ett_vines_ip_tctl,
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_vines_ip_protocol,
+ { "Protocol", "vines_ip.protocol",
+ FT_UINT8, BASE_HEX, VALS(proto_vals), 0x0,
+ "Vines protocol", HFILL }}
+ };
+
+ proto_vines_ip = proto_register_protocol("Banyan Vines IP", "Vines IP",
+ "vines_ip");
+ proto_register_field_array(proto_vines_ip, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* subdissector code */
+ vines_ip_dissector_table = register_dissector_table("vines_ip.protocol",
+ "Vines protocol", FT_UINT8, BASE_HEX);
+
+ vines_ip_handle = create_dissector_handle(dissect_vines_ip,
+ proto_vines_ip);
+}
+
+void
+proto_reg_handoff_vines_ip(void)
+{
+ dissector_add("ethertype", ETHERTYPE_VINES_IP, vines_ip_handle);
+ dissector_add("ppp.protocol", PPP_VINES, vines_ip_handle);
+ dissector_add("arcnet.protocol_id", ARCNET_PROTO_BANYAN,
+ vines_ip_handle);
+ dissector_add("vines_llc.ptype", VINES_LLC_IP, vines_ip_handle);
+ data_handle = find_dissector("data");
+}
+
+static void
+dissect_vines_echo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *vines_echo_tree = NULL;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines Echo");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vines_echo, tvb, 0, -1,
+ FALSE);
+ vines_echo_tree = proto_item_add_subtree(ti, ett_vines_echo);
+ proto_tree_add_text(vines_echo_tree, tvb, 0, -1, "Data");
+ }
+}
+
+void
+proto_register_vines_echo(void)
+{
+ static gint *ett[] = {
+ &ett_vines_echo,
+ };
+
+ proto_vines_echo = proto_register_protocol(
+ "Banyan Vines Echo", "Vines Echo", "vines_echo");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_vines_echo(void)
+{
+ dissector_handle_t vines_echo_handle;
+
+ vines_echo_handle = create_dissector_handle(dissect_vines_echo,
+ proto_vines_echo);
+ dissector_add("vines_llc.ptype", VINES_LLC_ECHO, vines_echo_handle);
+ dissector_add("ethertype", ETHERTYPE_VINES_ECHO, vines_echo_handle);
+}
+
+static const value_string pkttype_vals[] = {
+ { PKTTYPE_DGRAM, "Datagram" },
+ { PKTTYPE_DATA, "Data" },
+ { PKTTYPE_ERR, "Error" },
+ { PKTTYPE_DISC, "Disconnect" },
+ { PKTTYPE_PROBE, "Probe" },
+ { PKTTYPE_ACK, "Ack" },
+ { 0, NULL }
+};
+
+static heur_dissector_list_t vines_ipc_heur_subdissector_list;
+
+static const value_string vipc_err_vals[] = {
+ { 151, "Bad socket descriptor" },
+ { 152, "Address already in use" },
+ { 153, "Invalid operation" },
+ { 154, "User address parameter fault" },
+ { 155, "Net/host unreachable" },
+ { 156, "Message overflow error" },
+ { 157, "Destination socket does not exist" },
+ { 158, "Address family does not exist" },
+ { 159, "Socket type does not exist" },
+ { 160, "Protocol does not exist" },
+ { 161, "No more sockets available" },
+ { 162, "No buffer space available" },
+ { 163, "Timeout event" },
+ { 164, "Operation not supported" },
+ { 165, "Resource not available" },
+ { 166, "Internal communication service failure" },
+ { 167, "Controller reset failure" },
+ { 0, NULL }
+};
+
+static void
+dissect_vines_ipc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ e_vipc viph;
+ proto_tree *vipc_tree = NULL, *control_tree;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "VIPC");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* To do: check for runts, errs, etc. */
+
+ /* Avoids alignment problems on many architectures. */
+ tvb_memcpy(tvb, (guint8 *)&viph, offset, sizeof(e_vipc));
+
+ viph.vipc_sport = g_ntohs(viph.vipc_sport);
+ viph.vipc_dport = g_ntohs(viph.vipc_dport);
+ viph.vipc_lclid = g_ntohs(viph.vipc_lclid);
+ viph.vipc_rmtid = g_ntohs(viph.vipc_rmtid);
+ viph.vipc_seqno = g_ntohs(viph.vipc_seqno);
+ viph.vipc_ack = g_ntohs(viph.vipc_ack);
+ viph.vipc_err_len = g_ntohs(viph.vipc_err_len);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines IPC");
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ switch (viph.vipc_pkttype) {
+
+ case PKTTYPE_DGRAM:
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s D=%04x S=%04x",
+ val_to_str(viph.vipc_pkttype, pkttype_vals,
+ "Unknown packet type (0x%02x)"),
+ viph.vipc_dport, viph.vipc_sport);
+ break;
+
+ case PKTTYPE_ERR:
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s NS=%u NR=%u Err=%s RID=%04x LID=%04x D=%04x S=%04x",
+ val_to_str(viph.vipc_pkttype, pkttype_vals,
+ "Unknown packet type (0x%02x)"),
+ viph.vipc_seqno, viph.vipc_ack,
+ val_to_str(viph.vipc_err_len,
+ vipc_err_vals, "Unknown (%u)"),
+ viph.vipc_rmtid, viph.vipc_lclid,
+ viph.vipc_dport, viph.vipc_sport);
+ break;
+
+ default:
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s NS=%u NR=%u Len=%u RID=%04x LID=%04x D=%04x S=%04x",
+ val_to_str(viph.vipc_pkttype, pkttype_vals,
+ "Unknown packet type (0x%02x)"),
+ viph.vipc_seqno, viph.vipc_ack,
+ viph.vipc_err_len, viph.vipc_rmtid,
+ viph.vipc_lclid, viph.vipc_dport,
+ viph.vipc_sport);
+ break;
+ }
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vines_ipc, tvb, offset,
+ sizeof(viph), FALSE);
+ vipc_tree = proto_item_add_subtree(ti, ett_vines_ipc);
+ proto_tree_add_text(vipc_tree, tvb, offset, 2,
+ "Source port: 0x%04x", viph.vipc_sport);
+ }
+ offset += 2;
+ if (tree) {
+ proto_tree_add_text(vipc_tree, tvb, offset, 2,
+ "Destination port: 0x%04x",
+ viph.vipc_dport);
+ }
+ offset += 2;
+ if (tree) {
+ proto_tree_add_text(vipc_tree, tvb, offset, 1,
+ "Packet type: 0x%02x (%s)",
+ viph.vipc_pkttype,
+ val_to_str(viph.vipc_pkttype, pkttype_vals,
+ "Unknown"));
+ }
+ offset += 1;
+ if (viph.vipc_pkttype != PKTTYPE_DGRAM) {
+ if (tree) {
+ ti = proto_tree_add_text(vipc_tree, tvb, offset, 1,
+ "Control: 0x%02x",
+ viph.vipc_control);
+ control_tree = proto_item_add_subtree(ti,
+ ett_vines_ipc_control);
+ /*
+ * XXX - do reassembly based on BOM/EOM bits.
+ */
+ proto_tree_add_text(control_tree, tvb, offset, 1,
+ decode_boolean_bitfield(viph.vipc_control, 0x80,
+ 1*8,
+ "Send immediate acknowledgment",
+ "Do not send immediate acknowledgement"));
+ proto_tree_add_text(control_tree, tvb, offset, 1,
+ decode_boolean_bitfield(viph.vipc_control, 0x40,
+ 1*8,
+ "End of message",
+ "Not end of message"));
+ proto_tree_add_text(control_tree, tvb, offset, 1,
+ decode_boolean_bitfield(viph.vipc_control, 0x20,
+ 1*8,
+ "Beginning of message",
+ "Not beginning of message"));
+ proto_tree_add_text(control_tree, tvb, offset, 1,
+ decode_boolean_bitfield(viph.vipc_control, 0x10,
+ 1*8,
+ "Abort current message",
+ "Do not abort current message"));
+ }
+ }
+ offset += 1;
+ if (viph.vipc_pkttype != PKTTYPE_DGRAM) {
+ if (tree) {
+ proto_tree_add_text(vipc_tree, tvb, offset, 2,
+ "Local Connection ID: 0x%04x",
+ viph.vipc_lclid);
+ }
+ offset += 2;
+ if (tree) {
+ proto_tree_add_text(vipc_tree, tvb, offset, 2,
+ "Remote Connection ID: 0x%04x",
+ viph.vipc_rmtid);
+ }
+ offset += 2;
+ if (tree) {
+ proto_tree_add_text(vipc_tree, tvb, offset, 2,
+ "Sequence number: %u",
+ viph.vipc_seqno);
+ }
+ offset += 2;
+ if (tree) {
+ proto_tree_add_text(vipc_tree, tvb, offset, 2,
+ "Ack number: %u", viph.vipc_ack);
+ }
+ offset += 2;
+ if (tree) {
+ if (viph.vipc_pkttype == PKTTYPE_ERR) {
+ proto_tree_add_text(vipc_tree, tvb, offset, 2,
+ "Error: %s (%u)",
+ val_to_str(viph.vipc_err_len,
+ vipc_err_vals,
+ "Unknown"),
+ viph.vipc_err_len);
+ } else {
+ proto_tree_add_text(vipc_tree, tvb, offset, 2,
+ "Length: %u",
+ viph.vipc_err_len);
+ }
+ }
+ offset += 2;
+ }
+
+ /*
+ * For data packets, try the heuristic dissectors for Vines SPP;
+ * if none of them accept the packet, or if it's not a data packet,
+ * dissect it as data.
+ */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (viph.vipc_pkttype != PKTTYPE_DATA ||
+ !dissector_try_heuristic(vines_ipc_heur_subdissector_list,
+ next_tvb, pinfo, tree))
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_register_vines_ipc(void)
+{
+ static gint *ett[] = {
+ &ett_vines_ipc,
+ &ett_vines_ipc_control,
+ };
+
+ proto_vines_ipc = proto_register_protocol("Banyan Vines IPC",
+ "Vines IPC", "vines_ipc");
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_heur_dissector_list("vines_ipc",
+ &vines_ipc_heur_subdissector_list);
+}
+
+void
+proto_reg_handoff_vines_ipc(void)
+{
+ dissector_handle_t vines_ipc_handle;
+
+ vines_ipc_handle = create_dissector_handle(dissect_vines_ipc,
+ proto_vines_ipc);
+ dissector_add("vines_ip.protocol", VIP_PROTO_IPC, vines_ipc_handle);
+}
+
+static heur_dissector_list_t vines_spp_heur_subdissector_list;
+
+static void
+dissect_vines_spp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ e_vspp viph;
+ proto_tree *vspp_tree, *control_tree;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "VSPP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* To do: check for runts, errs, etc. */
+
+ /* Avoids alignment problems on many architectures. */
+ tvb_memcpy(tvb, (guint8 *)&viph, offset, sizeof(e_vspp));
+
+ viph.vspp_sport = g_ntohs(viph.vspp_sport);
+ viph.vspp_dport = g_ntohs(viph.vspp_dport);
+ viph.vspp_lclid = g_ntohs(viph.vspp_lclid);
+ viph.vspp_rmtid = g_ntohs(viph.vspp_rmtid);
+ viph.vspp_seqno = g_ntohs(viph.vspp_seqno);
+ viph.vspp_ack = g_ntohs(viph.vspp_ack);
+ viph.vspp_win = g_ntohs(viph.vspp_win);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines SPP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s NS=%u NR=%u Window=%u RID=%04x LID=%04x D=%04x S=%04x",
+ val_to_str(viph.vspp_pkttype, pkttype_vals,
+ "Unknown packet type (0x%02x)"),
+ viph.vspp_seqno, viph.vspp_ack, viph.vspp_win,
+ viph.vspp_rmtid, viph.vspp_lclid, viph.vspp_dport,
+ viph.vspp_sport);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vines_spp, tvb, offset,
+ sizeof(viph), FALSE);
+ vspp_tree = proto_item_add_subtree(ti, ett_vines_spp);
+ proto_tree_add_text(vspp_tree, tvb, offset, 2,
+ "Source port: 0x%04x", viph.vspp_sport);
+ proto_tree_add_text(vspp_tree, tvb, offset + 2, 2,
+ "Destination port: 0x%04x",
+ viph.vspp_dport);
+ proto_tree_add_text(vspp_tree, tvb, offset + 4, 1,
+ "Packet type: 0x%02x (%s)",
+ viph.vspp_pkttype,
+ val_to_str(viph.vspp_pkttype, pkttype_vals,
+ "Unknown"));
+ ti = proto_tree_add_text(vspp_tree, tvb, offset + 5, 1,
+ "Control: 0x%02x", viph.vspp_control);
+ control_tree = proto_item_add_subtree(ti, ett_vines_spp_control);
+ /*
+ * XXX - do reassembly based on BOM/EOM bits.
+ */
+ proto_tree_add_text(control_tree, tvb, offset + 5, 1,
+ decode_boolean_bitfield(viph.vspp_control, 0x80, 1*8,
+ "Send immediate acknowledgment",
+ "Do not send immediate acknowledgement"));
+ proto_tree_add_text(control_tree, tvb, offset + 5, 1,
+ decode_boolean_bitfield(viph.vspp_control, 0x40, 1*8,
+ "End of message",
+ "Not end of message"));
+ proto_tree_add_text(control_tree, tvb, offset + 5, 1,
+ decode_boolean_bitfield(viph.vspp_control, 0x20, 1*8,
+ "Beginning of message",
+ "Not beginning of message"));
+ proto_tree_add_text(control_tree, tvb, offset + 5, 1,
+ decode_boolean_bitfield(viph.vspp_control, 0x10, 1*8,
+ "Abort current message",
+ "Do not abort current message"));
+ proto_tree_add_text(vspp_tree, tvb, offset + 6, 2,
+ "Local Connection ID: 0x%04x",
+ viph.vspp_lclid);
+ proto_tree_add_text(vspp_tree, tvb, offset + 8, 2,
+ "Remote Connection ID: 0x%04x",
+ viph.vspp_rmtid);
+ proto_tree_add_text(vspp_tree, tvb, offset + 10, 2,
+ "Sequence number: %u",
+ viph.vspp_seqno);
+ proto_tree_add_text(vspp_tree, tvb, offset + 12, 2,
+ "Ack number: %u", viph.vspp_ack);
+ proto_tree_add_text(vspp_tree, tvb, offset + 14, 2,
+ "Window: %u", viph.vspp_win);
+ }
+ offset += 16; /* sizeof SPP */
+
+ /*
+ * For data packets, try the heuristic dissectors for Vines SPP;
+ * if none of them accept the packet, or if it's not a data packet,
+ * dissect it as data.
+ */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ if (viph.vspp_pkttype != PKTTYPE_DATA ||
+ !dissector_try_heuristic(vines_spp_heur_subdissector_list,
+ next_tvb, pinfo, tree))
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_register_vines_spp(void)
+{
+ static gint *ett[] = {
+ &ett_vines_spp,
+ &ett_vines_spp_control,
+ };
+
+ proto_vines_spp = proto_register_protocol("Banyan Vines SPP",
+ "Vines SPP", "vines_spp");
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_heur_dissector_list("vines_spp",
+ &vines_spp_heur_subdissector_list);
+}
+
+void
+proto_reg_handoff_vines_spp(void)
+{
+ dissector_handle_t vines_spp_handle;
+
+ vines_spp_handle = create_dissector_handle(dissect_vines_spp,
+ proto_vines_spp);
+ dissector_add("vines_ip.protocol", VIP_PROTO_SPP, vines_spp_handle);
+}
+
+#define VINES_VERS_PRE_5_5 0x00
+#define VINES_VERS_5_5 0x01
+
+static const value_string vines_version_vals[] = {
+ { VINES_VERS_PRE_5_5, "Pre-5.50" },
+ { VINES_VERS_5_5, "5.50" },
+ { 0, NULL }
+};
+
+#define VARP_QUERY_REQ 0x00
+#define VARP_SERVICE_RESP 0x01
+#define VARP_ASSIGNMENT_REQ 0x02
+#define VARP_ASSIGNMENT_RESP 0x03
+
+static const value_string vines_arp_packet_type_vals[] = {
+ { VARP_QUERY_REQ, "Query request" },
+ { VARP_SERVICE_RESP, "Service response" },
+ { VARP_ASSIGNMENT_REQ, "Assignment request" },
+ { VARP_ASSIGNMENT_RESP, "Assignment response" },
+ { 0, NULL }
+};
+
+static void
+dissect_vines_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *vines_arp_tree = NULL;
+ proto_item *ti;
+ guint8 version;
+ guint16 packet_type;
+ guint16 metric;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines ARP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vines_arp, tvb, 0, -1,
+ FALSE);
+ vines_arp_tree = proto_item_add_subtree(ti, ett_vines_arp);
+ }
+
+ version = tvb_get_guint8(tvb, 0);
+ if (tree) {
+ proto_tree_add_text(vines_arp_tree, tvb, 0, 1,
+ "Version: %s (0x%02x)",
+ val_to_str(version, vines_version_vals,
+ "Unknown"),
+ version);
+ }
+ if (version == VINES_VERS_5_5) {
+ /*
+ * Sequenced ARP.
+ */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines SARP");
+ packet_type = tvb_get_guint8(tvb, 1);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(packet_type, vines_arp_packet_type_vals,
+ "Unknown (0x%02x)"));
+ }
+ if (tree) {
+ proto_tree_add_text(vines_arp_tree, tvb, 1, 1,
+ "Packet Type: %s (0x%02x)",
+ val_to_str(packet_type,
+ vines_arp_packet_type_vals,
+ "Unknown"),
+ packet_type);
+ }
+ if (packet_type == VARP_ASSIGNMENT_RESP) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", Address = %s",
+ vines_addr_to_str(tvb_get_ptr(tvb, 2, VINES_ADDR_LEN)));
+ }
+ if (tree) {
+ proto_tree_add_text(vines_arp_tree, tvb, 2,
+ VINES_ADDR_LEN,
+ "Address: %s",
+ vines_addr_to_str(tvb_get_ptr(tvb, 2, VINES_ADDR_LEN)));
+ }
+ }
+ if (tree) {
+ proto_tree_add_text(vines_arp_tree, tvb,
+ 2+VINES_ADDR_LEN, 4,
+ "Sequence Number: %u",
+ tvb_get_ntohl(tvb, 2+VINES_ADDR_LEN));
+ metric = tvb_get_ntohs(tvb, 2+VINES_ADDR_LEN+4);
+ proto_tree_add_text(vines_arp_tree, tvb,
+ 2+VINES_ADDR_LEN+4, 2,
+ "Interface Metric: %u ticks (%g seconds)",
+ metric, metric*.2);
+ }
+ } else {
+ /*
+ * Non-sequenced ARP.
+ */
+ packet_type = (guint8) tvb_get_ntohs(tvb, 0);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(packet_type, vines_arp_packet_type_vals,
+ "Unknown (0x%02x)"));
+ }
+ if (tree) {
+ proto_tree_add_text(vines_arp_tree, tvb, 0, 2,
+ "Packet Type: %s (0x%04x)",
+ val_to_str(packet_type,
+ vines_arp_packet_type_vals,
+ "Unknown"),
+ packet_type);
+ }
+ if (packet_type == VARP_ASSIGNMENT_RESP) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ", Address = %s",
+ vines_addr_to_str(tvb_get_ptr(tvb, 2, VINES_ADDR_LEN)));
+ }
+ if (tree) {
+ proto_tree_add_text(vines_arp_tree, tvb, 2,
+ VINES_ADDR_LEN,
+ "Address: %s",
+ vines_addr_to_str(tvb_get_ptr(tvb, 2, VINES_ADDR_LEN)));
+ }
+ }
+ }
+}
+
+void
+proto_register_vines_arp(void)
+{
+ static gint *ett[] = {
+ &ett_vines_arp,
+ };
+
+ proto_vines_arp = proto_register_protocol(
+ "Banyan Vines ARP", "Vines ARP", "vines_arp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_vines_arp(void)
+{
+ dissector_handle_t vines_arp_handle;
+
+ vines_arp_handle = create_dissector_handle(dissect_vines_arp,
+ proto_vines_arp);
+ dissector_add("vines_ip.protocol", VIP_PROTO_ARP, vines_arp_handle);
+}
+
+#define VRTP_OP_REQUEST 0x01
+#define VRTP_OP_UPDATE_RESPONSE 0x02
+#define VRTP_OP_REDIRECT 0x03
+#define VRTP_OP_REINITIALIZE 0x04
+#define VRTP_OP_REDIRECT2 0x06
+
+static const value_string vines_rtp_operation_type_vals[] = {
+ { VRTP_OP_REQUEST, "Request" },
+ { VRTP_OP_UPDATE_RESPONSE, "Update/response" },
+ { VRTP_OP_REDIRECT, "Redirect" },
+ { VRTP_OP_REINITIALIZE, "Reinitialize" },
+ { VRTP_OP_REDIRECT2, "Redirect" },
+ { 0, NULL }
+};
+
+static const value_string vines_rtp_node_type_vals[] = {
+ { 0x01, "Host" },
+ { 0x02, "Router" },
+ { 0, NULL }
+};
+
+static const value_string vines_rtp_controller_type_vals[] = {
+ { 0x00, "Default Card" },
+ { 0x01, "Multibuffer" },
+ { 0, NULL }
+};
+
+static const value_string vines_rtp_info_type_vals[] = {
+ { 0x00, "Update" },
+ { 0x01, "Update" },
+ { 0x02, "Response" },
+ { 0, NULL }
+};
+
+static void rtp_show_machine_type(proto_tree *tree, tvbuff_t *tvb, int offset,
+ char *tag);
+static void rtp_show_flags(proto_tree *tree, tvbuff_t *tvb, int offset,
+ char *tag);
+static int srtp_show_machine_info(proto_tree *tree, tvbuff_t *tvb, int offset,
+ char *tag);
+static int rtp_show_gateway_info(proto_tree *tree, tvbuff_t *tvb, int offset,
+ guint8 link_addr_length, guint8 source_route_length);
+
+static void
+dissect_vines_rtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *vines_rtp_tree = NULL;
+ proto_item *ti;
+ proto_tree *subtree;
+ guint16 version;
+ guint8 operation_type;
+ guint8 node_type;
+ guint8 controller_type;
+ guint8 compatibility_flags;
+ guint8 link_addr_length;
+ guint8 source_route_length;
+ guint8 requested_info;
+ guint8 info_type;
+ guint8 control_flags;
+ guint16 metric;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines RTP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vines_rtp, tvb, 0, -1,
+ FALSE);
+ vines_rtp_tree = proto_item_add_subtree(ti, ett_vines_rtp);
+ }
+
+ if (tvb_get_guint8(tvb, 0) != 0) {
+ /*
+ * Non-sequenced RTP.
+ */
+ operation_type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(operation_type, vines_rtp_operation_type_vals,
+ "Unknown (0x%02x)"));
+ }
+ if (tree) {
+ proto_tree_add_text(vines_rtp_tree, tvb, offset, 1,
+ "Operation Type: %s (0x%02x)",
+ val_to_str(operation_type,
+ vines_rtp_operation_type_vals,
+ "Unknown"),
+ operation_type);
+ offset += 1;
+ node_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb, offset, 1,
+ "Node Type: %s (0x%02x)",
+ val_to_str(node_type,
+ vines_rtp_node_type_vals,
+ "Unknown"),
+ node_type);
+ offset += 1;
+ controller_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb, offset, 1,
+ "Controller Type: %s (0x%02x)",
+ val_to_str(controller_type,
+ vines_rtp_controller_type_vals,
+ "Unknown"),
+ controller_type);
+ offset += 1;
+ rtp_show_machine_type(vines_rtp_tree, tvb, offset,
+ NULL);
+ offset += 1;
+ switch (operation_type) {
+
+ case VRTP_OP_REDIRECT:
+ case VRTP_OP_REDIRECT2:
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 2,
+ "Version: 0x%02x",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ link_addr_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 1,
+ "Link Address Length: %u",
+ link_addr_length);
+ offset += 1;
+ source_route_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 1,
+ "Source Route Length: %u",
+ source_route_length);
+ offset += 1;
+ offset = srtp_show_machine_info(vines_rtp_tree,
+ tvb, offset, "Destination");
+ offset += 1;
+ offset = srtp_show_machine_info(vines_rtp_tree,
+ tvb, offset, "Preferred Gateway");
+ offset += 1;
+ offset = rtp_show_gateway_info(vines_rtp_tree,
+ tvb,offset, link_addr_length,
+ source_route_length);
+ break;
+
+ default:
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 4,
+ "Network Number: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ metric = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 2,
+ "Neighbor Metric: %u ticks (%g seconds)",
+ metric,
+ metric*.2);
+ offset += 2;
+ }
+ break;
+ }
+ }
+ } else {
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines SRTP");
+ if (tree) {
+ version = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb, offset, 2,
+ "Version: %s (0x%04x)",
+ val_to_str(version, vines_version_vals,
+ "Unknown"),
+ version);
+ }
+ offset += 2;
+ operation_type = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(operation_type, vines_rtp_operation_type_vals,
+ "Unknown (0x%02x)"));
+ }
+ if (tree) {
+ proto_tree_add_text(vines_rtp_tree, tvb, offset, 1,
+ "Operation Type: %s (0x%02x)",
+ val_to_str(operation_type,
+ vines_rtp_operation_type_vals,
+ "Unknown"),
+ operation_type);
+ offset += 1;
+ node_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb, offset, 1,
+ "Node Type: %s (0x%02x)",
+ val_to_str(node_type,
+ vines_rtp_node_type_vals,
+ "Unknown"),
+ node_type);
+ offset += 1;
+ compatibility_flags = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(vines_rtp_tree, tvb, offset, 1,
+ "Compatibility Flags: 0x%02x",
+ compatibility_flags);
+ subtree = proto_item_add_subtree(ti,
+ ett_vines_rtp_compatibility_flags);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ decode_boolean_bitfield(compatibility_flags,
+ 0x04, 1*8,
+ "Auto-configured non-Vines-reachable neighbor router",
+ "Not an auto-configured non-Vines-reachable neighbor router"));
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ decode_boolean_bitfield(compatibility_flags,
+ 0x02, 1*8,
+ "Not all neighbor routers support Sequenced RTP",
+ "All neighbor routers support Sequenced RTP"));
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ decode_boolean_bitfield(compatibility_flags,
+ 0x01, 1*8,
+ "Sequenced RTP version mismatch",
+ "No Sequenced RTP version mismatch"));
+ offset += 1;
+ offset += 1; /* reserved */
+ switch (operation_type) {
+
+ case VRTP_OP_REQUEST:
+ requested_info = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 1,
+ "Requested Info: 0x%02x",
+ requested_info);
+ break;
+
+ case VRTP_OP_UPDATE_RESPONSE:
+ info_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 1,
+ "Information Type: %s (0x%02x)",
+ val_to_str(info_type,
+ vines_rtp_info_type_vals,
+ "Unknown"),
+ info_type);
+ offset += 1;
+ control_flags = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 1,
+ "Control Flags: 0x%02x",
+ control_flags);
+ subtree = proto_item_add_subtree(ti,
+ ett_vines_rtp_control_flags);
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ decode_boolean_bitfield(control_flags,
+ 0x10, 1*8,
+ "Part of routing table synchronization broadcast",
+ "Not part of routing table synchronization broadcast"));
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ decode_boolean_bitfield(control_flags,
+ 0x08, 1*8,
+ "Part of full topology update",
+ "Not part of full topology update"));
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ decode_boolean_bitfield(control_flags,
+ 0x04, 1*8,
+ "Contains info specifically requested or network changes",
+ "Not a response to a specific request"));
+ /* XXX - need reassembly? */
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ decode_boolean_bitfield(control_flags,
+ 0x02, 1*8,
+ "End of message",
+ "Not end of message"));
+ proto_tree_add_text(subtree, tvb,
+ offset, 1,
+ decode_boolean_bitfield(control_flags,
+ 0x01, 1*8,
+ "Beginning of message",
+ "Not beginning of message"));
+ offset += 1;
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 2,
+ "Packet ID: %u",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 2,
+ "Data Offset: %u",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 4,
+ "Router Sequence Number: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ metric = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 2,
+ "Metric: %u ticks (%g seconds)",
+ metric, metric*.2);
+ offset += 2;
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 4,
+ "Network Number: 0x%08x",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ metric = tvb_get_ntohs(tvb, offset);
+ if (metric == 0xffff) {
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 2,
+ "Neighbor Metric: Unreachable");
+ } else {
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 2,
+ "Neighbor Metric: %u ticks (%g seconds)",
+ metric, metric*.2);
+ }
+ offset += 2;
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 4,
+ "Sequence Number: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ rtp_show_flags(vines_rtp_tree, tvb,
+ offset, "Network");
+ offset += 1;
+ offset += 1; /* reserved */
+ }
+ break;
+
+ case VRTP_OP_REDIRECT:
+ link_addr_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 1,
+ "Link Address Length: %u",
+ link_addr_length);
+ offset += 1;
+ source_route_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 1,
+ "Source Route Length: %u",
+ source_route_length);
+ offset += 1;
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, VINES_ADDR_LEN,
+ "Destination: %s",
+ vines_addr_to_str(tvb_get_ptr(tvb, offset, VINES_ADDR_LEN)));
+ offset += VINES_ADDR_LEN;
+ metric = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 2,
+ "Metric to Destination: %u ticks (%g seconds)",
+ metric, metric*.2);
+ offset += 2;
+ node_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 1,
+ "Destination Node Type: %s (0x%02x)",
+ val_to_str(node_type,
+ vines_rtp_node_type_vals,
+ "Unknown"),
+ node_type);
+ offset += 1;
+ rtp_show_flags(vines_rtp_tree, tvb,
+ offset, "Destination");
+ offset += 1;
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 4,
+ "Destination Sequence Number: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, VINES_ADDR_LEN,
+ "Preferred Gateway: %s",
+ vines_addr_to_str(tvb_get_ptr(tvb, offset, VINES_ADDR_LEN)));
+ offset += VINES_ADDR_LEN;
+ metric = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 2,
+ "Metric to Preferred Gateway: %u ticks (%g seconds)",
+ metric, metric*.2);
+ offset += 2;
+ node_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 1,
+ "Preferred Gateway Node Type: %s (0x%02x)",
+ val_to_str(node_type,
+ vines_rtp_node_type_vals,
+ "Unknown"),
+ node_type);
+ offset += 1;
+ rtp_show_flags(vines_rtp_tree, tvb,
+ offset, "Preferred Gateway");
+ offset += 1;
+ proto_tree_add_text(vines_rtp_tree, tvb,
+ offset, 4,
+ "Preferred Gateway Sequence Number: %u",
+ tvb_get_ntohl(tvb, offset));
+ offset += 4;
+ offset = rtp_show_gateway_info(vines_rtp_tree,
+ tvb,offset, link_addr_length,
+ source_route_length);
+ break;
+
+ case VRTP_OP_REINITIALIZE:
+ break;
+ }
+
+ }
+ }
+}
+
+static void
+rtp_show_machine_type(proto_tree *tree, tvbuff_t *tvb, int offset, char *tag)
+{
+ guint8 machine_type;
+ proto_item *ti;
+ proto_tree *subtree;
+
+ machine_type = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(tree, tvb, offset, 1,
+ "%s%sMachine Type: 0x%02x",
+ tag == NULL ? "" : tag,
+ tag == NULL ? "" : " ",
+ machine_type);
+ subtree = proto_item_add_subtree(ti, ett_vines_rtp_mtype);
+ proto_tree_add_text(subtree, tvb, offset, 1,
+ decode_boolean_bitfield(machine_type, 0x04, 1*8,
+ "Sequenced RTP supported",
+ "Sequenced RTP not supported"));
+ proto_tree_add_text(subtree, tvb, offset, 1,
+ decode_boolean_bitfield(machine_type, 0x02, 1*8,
+ "TCP/IP supported",
+ "TCP/IP not supported"));
+ proto_tree_add_text(subtree, tvb, offset, 1,
+ decode_boolean_bitfield(machine_type, 0x01, 1*8,
+ "Fast bus",
+ "Slow bus"));
+}
+
+static void
+rtp_show_flags(proto_tree *tree, tvbuff_t *tvb, int offset, char *tag)
+{
+ guint8 flags;
+ proto_item *ti;
+ proto_tree *flags_tree;
+
+ flags = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(tree, tvb, offset, 1, "%s Flags: 0x%02x",
+ tag, flags);
+ flags_tree = proto_item_add_subtree(ti, ett_vines_rtp_flags);
+ proto_tree_add_text(flags_tree, tvb, offset, 1,
+ decode_boolean_bitfield(flags, 0x08, 1*8,
+ "Network doesn't support Sequenced RTP",
+ "Network supports Sequenced RTP"));
+ proto_tree_add_text(flags_tree, tvb, offset, 1,
+ decode_boolean_bitfield(flags, 0x04, 1*8,
+ "Network accessed point-to-point on non-Vines network",
+ "Network not accessed point-to-point on non-Vines network"));
+ proto_tree_add_text(flags_tree, tvb, offset, 1,
+ decode_boolean_bitfield(flags, 0x02, 1*8,
+ "Data link to network uses point-to-point connection",
+ "Data link to network doesn't use point-to-point connection"));
+ proto_tree_add_text(flags_tree, tvb, offset, 1,
+ decode_boolean_bitfield(flags, 0x01, 1*8,
+ "Network accessed across broadcast medium",
+ "Network not accessed across broadcast medium"));
+}
+
+static int
+srtp_show_machine_info(proto_tree *tree, tvbuff_t *tvb, int offset, char *tag)
+{
+ guint16 metric;
+ guint8 node_type;
+ guint8 controller_type;
+
+ proto_tree_add_text(tree, tvb, offset, VINES_ADDR_LEN,
+ "%s: %s", tag,
+ vines_addr_to_str(tvb_get_ptr(tvb, offset, VINES_ADDR_LEN)));
+ offset += VINES_ADDR_LEN;
+ metric = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Metric to %s: %u ticks (%g seconds)", tag, metric, metric*.2);
+ offset += 2;
+ node_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s Node Type: %s (0x%02x)", tag,
+ val_to_str(node_type, vines_rtp_node_type_vals, "Unknown"),
+ node_type);
+ offset += 1;
+ rtp_show_machine_type(tree, tvb, offset, tag);
+ offset += 1;
+ controller_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1,
+ "%s Controller Type: %s (0x%02x)", tag,
+ val_to_str(controller_type, vines_rtp_controller_type_vals, "Unknown"),
+ controller_type);
+ offset += 1;
+ return offset;
+}
+
+static int
+rtp_show_gateway_info(proto_tree *tree, tvbuff_t *tvb, int offset,
+ guint8 link_addr_length, guint8 source_route_length)
+{
+ if (link_addr_length != 0) {
+ proto_tree_add_text(tree, tvb, offset, link_addr_length,
+ "Preferred Gateway Data Link Address: %s",
+ link_addr_length == 6 ?
+ ether_to_str(tvb_get_ptr(tvb, offset, link_addr_length)) :
+ tvb_bytes_to_str(tvb, offset, link_addr_length));
+ offset += link_addr_length;
+ }
+ if (source_route_length != 0) {
+ proto_tree_add_text(tree, tvb, offset, source_route_length,
+ "Preferred Gateway Source Route: %s",
+ tvb_bytes_to_str(tvb, offset, source_route_length));
+ offset += source_route_length;
+ }
+ return offset;
+}
+
+void
+proto_register_vines_rtp(void)
+{
+ static gint *ett[] = {
+ &ett_vines_rtp,
+ &ett_vines_rtp_compatibility_flags,
+ &ett_vines_rtp_req_info,
+ &ett_vines_rtp_control_flags,
+ &ett_vines_rtp_mtype,
+ &ett_vines_rtp_flags,
+ };
+
+ proto_vines_rtp = proto_register_protocol(
+ "Banyan Vines RTP", "Vines RTP", "vines_rtp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_vines_rtp(void)
+{
+ dissector_handle_t vines_rtp_handle;
+
+ vines_rtp_handle = create_dissector_handle(dissect_vines_rtp,
+ proto_vines_rtp);
+ dissector_add("vines_ip.protocol", VIP_PROTO_RTP, vines_rtp_handle);
+}
+
+#define VICP_EXCEPTION_NOTIFICATION 0x0000
+#define VICP_METRIC_NOTIFICATION 0x0001
+
+static const value_string vines_icp_packet_type_vals[] = {
+ { VICP_EXCEPTION_NOTIFICATION, "Exception notification" },
+ { VICP_METRIC_NOTIFICATION, "Metric notification" },
+ { 0, NULL }
+};
+
+static void
+dissect_vines_icp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *vines_icp_tree = NULL;
+ proto_item *ti;
+ guint16 packet_type;
+ guint16 exception_code;
+ guint16 metric;
+ gboolean save_in_error_pkt;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Vines ICP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vines_icp, tvb, 0, -1,
+ FALSE);
+ vines_icp_tree = proto_item_add_subtree(ti, ett_vines_icp);
+ }
+
+ packet_type = tvb_get_ntohs(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
+ val_to_str(packet_type, vines_icp_packet_type_vals,
+ "Unknown (0x%02x)"));
+ }
+ if (tree) {
+ proto_tree_add_text(vines_icp_tree, tvb, offset, 2,
+ "Packet Type: %s (0x%04x)",
+ val_to_str(packet_type,
+ vines_icp_packet_type_vals,
+ "Unknown"),
+ packet_type);
+ }
+ offset += 2;
+
+ switch (packet_type) {
+
+ case VICP_EXCEPTION_NOTIFICATION:
+ exception_code = tvb_get_ntohs(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(exception_code, vipc_err_vals,
+ "Unknown exception code (%u)"));
+ }
+ if (tree) {
+ proto_tree_add_text(vines_icp_tree, tvb, offset, 2,
+ "Exception Code: %s (%u)",
+ val_to_str(exception_code,
+ vipc_err_vals,
+ "Unknown"),
+ exception_code);
+ }
+ break;
+
+ case VICP_METRIC_NOTIFICATION:
+ metric = tvb_get_ntohs(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", metric %u",
+ metric);
+ }
+ if (tree) {
+ proto_tree_add_text(vines_icp_tree, tvb, offset, 2,
+ "Metric: %u", metric);
+ }
+ break;
+ }
+ offset += 2;
+
+ /*
+ * Save the current value of the "we're inside an error packet"
+ * flag, and set that flag; subdissectors may treat packets
+ * that are the payload of error packets differently from
+ * "real" packets.
+ */
+ save_in_error_pkt = pinfo->in_error_pkt;
+ pinfo->in_error_pkt = TRUE;
+
+ /* Decode the first 40 bytes of the original VIP datagram. */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(vines_ip_handle, next_tvb, pinfo, vines_icp_tree);
+
+ /* Restore the "we're inside an error packet" flag. */
+ pinfo->in_error_pkt = save_in_error_pkt;
+}
+
+void
+proto_register_vines_icp(void)
+{
+ static gint *ett[] = {
+ &ett_vines_icp,
+ };
+
+ proto_vines_icp = proto_register_protocol(
+ "Banyan Vines ICP", "Vines ICP", "vines_icp");
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_vines_icp(void)
+{
+ dissector_handle_t vines_icp_handle;
+
+ vines_icp_handle = create_dissector_handle(dissect_vines_icp,
+ proto_vines_icp);
+ dissector_add("vines_ip.protocol", VIP_PROTO_ICP, vines_icp_handle);
+}
diff --git a/epan/dissectors/packet-vines.h b/epan/dissectors/packet-vines.h
new file mode 100644
index 0000000000..ff8a2c7a73
--- /dev/null
+++ b/epan/dissectors/packet-vines.h
@@ -0,0 +1,135 @@
+/* packet-vines.h
+ * Definitions for packet disassembly structures and routines
+ *
+ * $Id$
+ *
+ * Don Lafontaine <lafont02@cn.ca>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ * Joerg Mayer <jmayer@loplof.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Information about VINES can be found in
+ *
+ * VINES Protocol Definition
+ * Order Number: DA254-00
+ * Banyan Systems incorporated
+ * February 1990
+ * Part Number: 092093-000
+ *
+ * Some information can also be found in
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/cisintwk/ito_doc/vines.htm
+ *
+ * and at
+ *
+ * http://www.synapse.de/ban/HTML/P_VINES/Eng/P_vines.html
+ *
+ * The document at
+ *
+ * http://www.watersprings.org/pub/id/draft-ietf-rmonmib-rmonprot-v2-00.txt
+ *
+ * lists a bunch of values of protocol identifier fields for various
+ * protocols. It speaks of the Vines Fragmentation Protocol,
+ * the "Vines Token Ring Protocol" which appears to be the same as the
+ * "Vines LLC" protocol here, the Vines echo protocol, Vines IP, and
+ * protocols running atop Vines IP.
+ *
+ * The LLC values it describes are:
+ *
+ * 0xbc (SAP_VINES2) Vines Token Ring a/k/a Vines LLC
+ *
+ * It doesn't mention 0xba (SAP_VINES1).
+ *
+ * The Vines Token Ring/Vines LLC protocol identifier values it
+ * describes are:
+ *
+ * 0xba Vines IP
+ * 0xbb Vines Echo
+ *
+ * The Ethernet type values it describes are:
+ *
+ * 0x0bad (ETHERTYPE_VINES) Vines IP
+ * 0x0baf Vines Echo
+ */
+
+#ifndef __PACKETVINES_H__
+#define __PACKETVINES_H__
+
+#include <epan/to_str.h>
+
+#define VINES_ADDR_LEN 6
+
+/* VINES IP structs and definitions */
+
+enum {
+ VIP_PROTO_IPC = 1, /* Interprocess Communications Protocol (IPC) */
+ VIP_PROTO_SPP = 2, /* Sequenced Packet Protcol (SPP) */
+ VIP_PROTO_ARP = 4, /* Address Resolution Protocol (ARP) */
+ VIP_PROTO_RTP = 5, /* Routing Update Protocol (RTP) / SRTP (Sequenced RTP) */
+ VIP_PROTO_ICP = 6 /* Internet Control Protocol (ICP) */
+};
+
+typedef struct _e_vip {
+ guint16 vip_chksum;
+ guint16 vip_pktlen;
+ guint8 vip_tctl; /* Transport Control */
+ guint8 vip_proto;
+ guint8 vip_dst[VINES_ADDR_LEN];
+ guint8 vip_src[VINES_ADDR_LEN];
+} e_vip;
+
+/* VINES SPP and IPC structs and definitions */
+
+enum {
+ PKTTYPE_DGRAM = 0, /* Unreliable datagram */
+ PKTTYPE_DATA = 1, /* User Data */
+ PKTTYPE_ERR = 2, /* Error */
+ PKTTYPE_DISC = 3, /* Diconnect Request */
+ PKTTYPE_PROBE = 4, /* Probe (retransmit) */
+ PKTTYPE_ACK = 5 /* Acknowledgement */
+};
+
+typedef struct _e_vspp {
+ guint16 vspp_sport;
+ guint16 vspp_dport;
+ guint8 vspp_pkttype;
+ guint8 vspp_control;
+ guint16 vspp_lclid; /* Local Connection ID */
+ guint16 vspp_rmtid; /* Remote Connection ID */
+ guint16 vspp_seqno; /* Sequence Number */
+ guint16 vspp_ack; /* Acknowledgement Number */
+ guint16 vspp_win;
+} e_vspp;
+
+typedef struct _e_vipc {
+ guint16 vipc_sport;
+ guint16 vipc_dport;
+ guint8 vipc_pkttype;
+ guint8 vipc_control;
+ guint16 vipc_lclid; /* Local Connection ID */
+ guint16 vipc_rmtid; /* Remote Connection ID */
+ guint16 vipc_seqno; /* Sequence Number */
+ guint16 vipc_ack; /* Acknowledgement Number */
+ guint16 vipc_err_len;
+} e_vipc;
+
+void capture_vines(packet_counts *);
+
+#endif /* packet-vines.h */
diff --git a/epan/dissectors/packet-vj.c b/epan/dissectors/packet-vj.c
new file mode 100644
index 0000000000..30bbe0cbca
--- /dev/null
+++ b/epan/dissectors/packet-vj.c
@@ -0,0 +1,900 @@
+/* packet-vj.c
+ * Routines for Van Jacobson header decompression.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ *
+ * This file created by Irfan Khan <ikhan@qualcomm.com>
+ * Copyright (c) 2001 by QUALCOMM, Incorporated.
+ * All Rights reserved.
+ *
+ * Routines to compress and uncompress TCP packets (for transmission
+ * over low speed serial lines).
+ *
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
+ * - Initial distribution.
+ *
+ *
+ * modified for KA9Q Internet Software Package by
+ * Katie Stevens (dkstevens@ucdavis.edu)
+ * University of California, Davis
+ * Computing Services
+ * - 01-31-90 initial adaptation (from 1.19)
+ * PPP.05 02-15-90 [ks]
+ * PPP.08 05-02-90 [ks] use PPP protocol field to signal compression
+ * PPP.15 09-90 [ks] improve mbuf handling
+ * PPP.16 11-02 [karn] substantially rewritten to use NOS facilities
+ *
+ * - Feb 1991 Bill_Simpson@um.cc.umich.edu
+ * variable number of conversation slots
+ * allow zero or one slots
+ * separate routines
+ * status display
+ * - Jul 1994 Dmitry Gorodchanin
+ * Fixes for memory leaks.
+ * - Oct 1994 Dmitry Gorodchanin
+ * Modularization.
+ * - Jan 1995 Bjorn Ekwall
+ * Use ip_fast_csum from ip.h
+ * - July 1995 Christos A. Polyzols
+ * Spotted bug in tcp option checking
+ * - Sep 2001 Irfan Khan
+ * Rewrite to make the code work for ethereal.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "prefs.h"
+#include "packet-ppp.h"
+#include "ppptypes.h"
+#include "ipproto.h"
+#include "in_cksum.h"
+
+/* Define relevant IP/TCP parameters */
+#define IP_FIELD_TOT_LEN 2 /* Total length field in IP hdr */
+#define IP_FIELD_PROTOCOL 9 /* Protocol field byte in IP hdr */
+#define IP_ADDR_SIZE 4 /* Size in bytes of IPv4 address */
+#define IP_FIELD_SRC 12 /* Byte 12 in IP hdr - src address */
+#define IP_FIELD_DST 16 /* Byte 16 in IP hdr - dst address */
+#define IP_HDR_LEN 20 /* Minimum IP header length */
+#define IP_HDR_LEN_MASK 0x0f /* Mask for header length field */
+#define IP_MAX_OPT_LEN 44 /* Max length of IP options */
+#define TCP_FIELD_HDR_LEN 12 /* Data offset field in TCP hdr */
+#define TCP_HDR_LEN 20 /* Minimum TCP header length */
+#define TCP_MAX_OPT_LEN 44 /* Max length of TCP options */
+#define TCP_SIMUL_CONV_MAX 256 /* Max number of simul. TCP conversations */
+#define TCP_PUSH_BIT 0x08 /* TCP push bit */
+#define TCP_URG_BIT 0x20 /* TCP urgent bit */
+
+/* Bits in first octet of compressed packet */
+/* flag bits for what changed in a packet */
+#define NEW_C 0x40 /* Connection number changed */
+#define NEW_I 0x20 /* IP sequence number change by value != 1 */
+#define CHANGE_PUSH_BIT 0x10 /* TCP push bit set */
+#define NEW_S 0x08 /* Sequence number changed */
+#define NEW_A 0x04 /* Ack sequence number changed */
+#define NEW_W 0x02 /* Window changed */
+#define NEW_U 0x01 /* Urgent pointer present */
+
+/* reserved, special-case values of above */
+#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
+#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U)/* unidirectional data */
+#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
+
+/* Function return values */
+#define VJ_OK 0
+#define VJ_ERROR -1
+
+/* Define for 0 */
+#define ZERO 0
+
+/* VJ Mem Chunk defines */
+#define VJ_DATA_SIZE 128 /* Max IP hdr(64)+Max TCP hdr(64) */
+#define VJ_ATOM_COUNT 250 /* Number of Atoms per block */
+
+/* IP and TCP header types */
+typedef struct {
+ guint8 ihl_version;
+ guint8 tos;
+ guint16 tot_len;
+ guint16 id;
+ guint16 frag_off;
+ guint8 ttl;
+ guint8 proto;
+ guint16 cksum;
+ guint32 src;
+ guint32 dst;
+} iphdr_type;
+
+typedef struct {
+ guint16 srcport;
+ guint16 dstport;
+ guint32 seq;
+ guint32 ack_seq;
+ guint8 off_x2;
+ guint8 flags;
+ guint16 window;
+ guint16 cksum;
+ guint16 urg_ptr;
+} tcphdr_type;
+
+#define TCP_OFFSET(th) (((th)->off_x2 & 0xf0) >> 4)
+
+/* State per active tcp conversation */
+typedef struct cstate {
+ iphdr_type cs_ip;
+ tcphdr_type cs_tcp;
+ guint8 cs_ipopt[IP_MAX_OPT_LEN];
+ guint8 cs_tcpopt[TCP_MAX_OPT_LEN];
+ guint32 flags;
+#define SLF_TOSS 0x00000001 /* tossing rcvd frames until id received */
+} cstate;
+
+/* All the state data for one serial line */
+typedef struct {
+ cstate rstate[TCP_SIMUL_CONV_MAX]; /* receive connection states (array) */
+ guint8 recv_current; /* most recent rcvd id */
+} slcompress;
+
+/* Initialize the protocol and registered fields */
+static int proto_vj = -1;
+
+static int hf_vj_change_mask = -1;
+static int hf_vj_change_mask_c = -1;
+static int hf_vj_change_mask_i = -1;
+static int hf_vj_change_mask_p = -1;
+static int hf_vj_change_mask_s = -1;
+static int hf_vj_change_mask_a = -1;
+static int hf_vj_change_mask_w = -1;
+static int hf_vj_change_mask_u = -1;
+static int hf_vj_connection_number = -1;
+static int hf_vj_tcp_cksum = -1;
+static int hf_vj_urp = -1;
+static int hf_vj_win_delta = -1;
+static int hf_vj_ack_delta = -1;
+static int hf_vj_seq_delta = -1;
+static int hf_vj_ip_id_delta = -1;
+
+static gint ett_vj = -1;
+static gint ett_vj_changes = -1;
+
+/* Protocol handles */
+static dissector_handle_t ip_handle;
+static dissector_handle_t data_handle;
+
+/* State repository (Full Duplex) */
+#define RX_TX_STATE_COUNT 2
+static slcompress *rx_tx_state[RX_TX_STATE_COUNT] = {NULL, NULL};
+
+/* Mem Chunks for storing decompressed headers */
+static GMemChunk *vj_header_memchunk = NULL;
+typedef struct {
+ int offset; /* uppermost bit is "can't dissect" flag */
+ guint8 data[VJ_DATA_SIZE];
+} vj_header_t;
+
+/* Function prototypes */
+static int get_unsigned_delta(tvbuff_t *tvb, int *offsetp, int hf,
+ proto_tree *tree);
+static int get_signed_delta(tvbuff_t *tvb, int *offsetp, int hf,
+ proto_tree *tree);
+static guint16 ip_csum(const guint8 *ptr, guint32 len);
+static slcompress *slhc_init(void);
+static void vj_init(void);
+static gint vjc_process(tvbuff_t *src_tvb, packet_info *pinfo, proto_tree *tree,
+ slcompress *comp);
+static gint vjc_tvb_setup(tvbuff_t *src_tvb, tvbuff_t **dst_tvb,
+ packet_info *pinfo);
+
+/* Dissector for VJ Uncompressed packets */
+static void
+dissect_vjuc(tvbuff_t *tvb, packet_info *pinfo, proto_tree * tree)
+{
+ proto_item *ti;
+ proto_tree *vj_tree = NULL;
+ slcompress *comp;
+ int i;
+ gint conn_index;
+ cstate *cs = NULL;
+ guint8 ihl;
+ guint8 thl;
+ guint8 *buffer;
+ tvbuff_t *next_tvb;
+ gint isize = tvb_length(tvb);
+ gint ipsize;
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_INFO, "PPP VJ");
+
+ if(tree != NULL) {
+ ti = proto_tree_add_protocol_format(tree, proto_vj, tvb, 0, -1,
+ "PPP VJ Compression: Uncompressed data");
+ vj_tree = proto_item_add_subtree(ti, ett_vj);
+ }
+
+ if(pinfo->p2p_dir == P2P_DIR_UNKNOWN) {
+ /* Direction of the traffic unknown - can't update state */
+ comp = NULL;
+ } else {
+ /* Get state for that direction */
+ comp = rx_tx_state[pinfo->p2p_dir];
+ }
+
+ /*
+ * Check to make sure we can fetch the connection index.
+ */
+ if(!tvb_bytes_exist(tvb, IP_FIELD_PROTOCOL, 1)) {
+ /*
+ * We don't. We can't even mark a connection as non-decompressable,
+ * as we don't know which connection this is. Mark them all as
+ * non-decompressable.
+ */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ uncompressed TCP (not enough data available)");
+ if(tree != NULL)
+ call_dissector(data_handle, tvb, pinfo, tree);
+ if(comp != NULL) {
+ for(i = 0; i < TCP_SIMUL_CONV_MAX; i++)
+ comp->rstate[i].flags |= SLF_TOSS;
+ }
+ return;
+ }
+
+ /* Get connection index */
+ conn_index = tvb_get_guint8(tvb, IP_FIELD_PROTOCOL);
+ if(tree != NULL)
+ proto_tree_add_uint(vj_tree, hf_vj_connection_number, tvb,
+ IP_FIELD_PROTOCOL, 1, conn_index);
+
+ /*
+ * Update the current connection, and get a pointer to its state.
+ */
+ if(comp != NULL) {
+ comp->recv_current = conn_index;
+ cs = &comp->rstate[conn_index];
+ }
+
+ /* Get the IP header length */
+ ihl = tvb_get_guint8(tvb, 0) & IP_HDR_LEN_MASK;
+ ihl <<= 2;
+
+ /* Check IP header length */
+ if(ihl < IP_HDR_LEN) {
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "VJ uncompressed TCP (IP header length (%u) < %u)",
+ ihl, IP_HDR_LEN);
+ }
+ if(cs != NULL)
+ cs->flags |= SLF_TOSS;
+ return;
+ }
+
+ /* Make sure we have the full IP header */
+ if(isize < ihl) {
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ uncompressed TCP (not enough data available)");
+ if(tree != NULL)
+ call_dissector(data_handle, tvb, pinfo, tree);
+ if(cs != NULL)
+ cs->flags |= SLF_TOSS;
+ return;
+ }
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ uncompressed TCP");
+
+ /*
+ * Copy packet data to a buffer, and replace the connection index with
+ * the protocol type (which is always TCP), to give the actual IP header.
+ */
+ buffer = tvb_memdup(tvb, 0, isize);
+ buffer[IP_FIELD_PROTOCOL] = IP_PROTO_TCP;
+
+ /* Check IP checksum */
+ if(ip_csum(buffer, ihl) != ZERO) {
+ /*
+ * Checksum invalid - don't update state, and don't decompress
+ * any subsequent compressed packets in this direction.
+ */
+ if(cs != NULL)
+ cs->flags |= SLF_TOSS;
+ cs = NULL; /* disable state updates */
+ } else {
+ /* Do we have the TCP header length in the tvbuff? */
+ if(!tvb_bytes_exist(tvb, ihl + TCP_FIELD_HDR_LEN, 1)) {
+ /* We don't, so we can't provide enough data for decompression */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ uncompressed TCP (not enough data available)");
+ if(cs != NULL)
+ cs->flags |= SLF_TOSS;
+ cs = NULL; /* disable state updates */
+ } else {
+ /* Get the TCP header length */
+ thl = tvb_get_guint8(tvb, ihl + TCP_FIELD_HDR_LEN);
+ thl = ((thl & 0xf0) >> 4) * 4;
+
+ /* Check TCP header length */
+ if(thl < TCP_HDR_LEN) {
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "VJ uncompressed TCP (TCP header length (%u) < %u)",
+ thl, TCP_HDR_LEN);
+ }
+ if(cs != NULL)
+ cs->flags |= SLF_TOSS;
+ cs = NULL; /* disable state updates */
+ } else {
+ /* Make sure we have the full TCP header */
+ if(isize < thl) {
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ uncompressed TCP (not enough data available)");
+ if(cs != NULL)
+ cs->flags |= SLF_TOSS;
+ cs = NULL; /* disable state updates */
+ }
+ }
+ }
+ }
+
+ /*
+ * If packet seen for first time, update state if we have state and can
+ * update it.
+ */
+ if(!pinfo->fd->flags.visited) {
+ if(cs != NULL) {
+ cs->flags &= ~SLF_TOSS;
+ memcpy(&cs->cs_ip, &buffer[0], IP_HDR_LEN);
+ memcpy(&cs->cs_tcp, &buffer[ihl], TCP_HDR_LEN);
+ if(ihl > IP_HDR_LEN)
+ memcpy(cs->cs_ipopt, &buffer[sizeof(iphdr_type)], ihl - IP_HDR_LEN);
+ if(TCP_OFFSET(&(cs->cs_tcp)) > 5)
+ memcpy(cs->cs_tcpopt, &buffer[ihl + sizeof(tcphdr_type)],
+ (TCP_OFFSET(&(cs->cs_tcp)) - 5) * 4);
+ }
+ }
+
+ /*
+ * Set up tvbuff containing packet with protocol type.
+ * Neither header checksum is recalculated.
+ *
+ * Use the length field from the IP header as the reported length;
+ * use the minimum of that and the number of bytes we got from
+ * the tvbuff as the actual length, just in case the tvbuff we were
+ * handed includes part or all of the FCS (because the FCS preference
+ * for the PPP dissector doesn't match the FCS size in this session).
+ */
+ ipsize = pntohs(&buffer[IP_FIELD_TOT_LEN]);
+ if (ipsize < isize)
+ isize = ipsize;
+ next_tvb = tvb_new_real_data(buffer, isize, ipsize);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb, "VJ Uncompressed");
+
+ /*
+ * Call IP dissector.
+ */
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+}
+
+/* Dissector for VJ Compressed packets */
+static void
+dissect_vjc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *vj_tree = NULL;
+ tvbuff_t *next_tvb = NULL;
+ slcompress *comp = NULL;
+ gint err = VJ_ERROR;
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_INFO, "PPP VJ");
+
+ if(tree != NULL) {
+ ti = proto_tree_add_protocol_format(tree, proto_vj, tvb, 0, -1,
+ "PPP VJ Compression: Compressed data");
+ vj_tree = proto_item_add_subtree(ti, ett_vj);
+ }
+
+ if(!ppp_vj_decomp || pinfo->p2p_dir == P2P_DIR_UNKNOWN) {
+ /*
+ * VJ decompression turned off, so we shouldn't decompress, or
+ * direction of the traffic unknown, so we can't decompress.
+ */
+ comp = NULL;
+ } else {
+ /* Get state for that direction */
+ comp = rx_tx_state[pinfo->p2p_dir];
+ }
+
+ /* Process the compressed data header */
+ if(vjc_process(tvb, pinfo, vj_tree, comp) == VJ_ERROR)
+ return;
+
+ /* Decompression possible - set up tvb containing decompressed packet */
+ err = vjc_tvb_setup(tvb, &next_tvb, pinfo);
+ if(err == VJ_ERROR) {
+ if(tree != NULL)
+ call_dissector(data_handle, tvb, pinfo, vj_tree);
+ return;
+ }
+
+ /* No errors, so call IP dissector */
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+}
+
+/* Registration functions for dissectors */
+void
+proto_register_vj(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_vj_change_mask,
+ { "Change mask", "vj.change_mask", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_vj_change_mask_c,
+ { "Connection changed", "vj.change_mask_c", FT_BOOLEAN, 8,
+ NULL, NEW_C, "Connection number changed", HFILL }},
+ { &hf_vj_change_mask_i,
+ { "IP ID change != 1", "vj.change_mask_i", FT_BOOLEAN, 8,
+ NULL, NEW_I, "IP ID changed by a value other than 1", HFILL }},
+ { &hf_vj_change_mask_p,
+ { "Push bit set", "vj.change_mask_p", FT_BOOLEAN, 8,
+ NULL, CHANGE_PUSH_BIT, "TCP PSH flag set", HFILL }},
+ { &hf_vj_change_mask_s,
+ { "Sequence number changed", "vj.change_mask_s", FT_BOOLEAN, 8,
+ NULL, NEW_S, "Sequence number changed", HFILL }},
+ { &hf_vj_change_mask_a,
+ { "Ack number changed", "vj.change_mask_a", FT_BOOLEAN, 8,
+ NULL, NEW_A, "Acknowledgement sequence number changed", HFILL }},
+ { &hf_vj_change_mask_w,
+ { "Window changed", "vj.change_mask_w", FT_BOOLEAN, 8,
+ NULL, NEW_W, "TCP window changed", HFILL }},
+ { &hf_vj_change_mask_u,
+ { "Urgent pointer set", "vj.change_mask_u", FT_BOOLEAN, 8,
+ NULL, NEW_U, "Urgent pointer set", HFILL }},
+ { &hf_vj_connection_number,
+ { "Connection number", "vj.connection_number", FT_UINT8, BASE_DEC,
+ NULL, 0x0, "Connection number", HFILL }},
+ { &hf_vj_tcp_cksum,
+ { "TCP checksum", "vj.tcp_cksum", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "TCP checksum", HFILL }},
+ { &hf_vj_urp,
+ { "Urgent pointer", "vj.urp", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Urgent pointer", HFILL }},
+ { &hf_vj_win_delta,
+ { "Window delta", "vj.win_delta", FT_INT16, BASE_DEC,
+ NULL, 0x0, "Delta for window", HFILL }},
+ { &hf_vj_ack_delta,
+ { "Ack delta", "vj.ack_delta", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Delta for acknowledgment sequence number", HFILL }},
+ { &hf_vj_seq_delta,
+ { "Sequence delta", "vj.seq_delta", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Delta for sequence number", HFILL }},
+ { &hf_vj_ip_id_delta,
+ { "IP ID delta", "vj.ip_id_delta", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Delta for IP ID", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_vj,
+ &ett_vj_changes,
+ };
+
+ proto_vj = proto_register_protocol("PPP VJ Compression", "PPP VJ", "vj");
+ proto_register_field_array(proto_vj, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&vj_init);
+}
+
+void
+proto_reg_handoff_vj(void)
+{
+ dissector_handle_t vjc_handle;
+ dissector_handle_t vjuc_handle;
+
+ vjc_handle = create_dissector_handle(dissect_vjc, proto_vj);
+ dissector_add("ppp.protocol", PPP_VJC_COMP, vjc_handle);
+
+ vjuc_handle = create_dissector_handle(dissect_vjuc, proto_vj);
+ dissector_add("ppp.protocol", PPP_VJC_UNCOMP, vjuc_handle);
+
+ ip_handle = find_dissector("ip");
+ data_handle = find_dissector("data");
+}
+
+/* Initialization function */
+static void
+vj_init(void)
+{
+ gint i = ZERO;
+ slcompress *pslc = NULL;
+
+ if(vj_header_memchunk != NULL)
+ g_mem_chunk_destroy(vj_header_memchunk);
+ vj_header_memchunk = g_mem_chunk_new("vj header store", sizeof (vj_header_t),
+ sizeof (vj_header_t) * VJ_ATOM_COUNT,
+ G_ALLOC_ONLY);
+ for(i = 0; i < RX_TX_STATE_COUNT; i++) {
+ if((pslc = rx_tx_state[i]) != NULL)
+ g_free(pslc);
+ rx_tx_state[i] = slhc_init();
+ }
+ return;
+}
+
+/* Initialization routine for VJ decompression */
+static slcompress *
+slhc_init(void)
+{
+ slcompress *comp = g_malloc(sizeof(slcompress));
+ int i;
+
+ memset(comp, ZERO, sizeof(slcompress));
+
+ /*
+ * Initialize the state; there is no current connection, and
+ * we have no header data for any of the connections, as we
+ * haven't yet seen an uncompressed frame.
+ */
+ comp->recv_current = TCP_SIMUL_CONV_MAX - 1;
+ for (i = 0; i < TCP_SIMUL_CONV_MAX; i++)
+ comp->rstate[i].flags |= SLF_TOSS;
+ return comp;
+}
+
+/* Setup the decompressed packet tvb for VJ compressed packets */
+static gint
+vjc_tvb_setup(tvbuff_t *src_tvb,
+ tvbuff_t **dst_tvb,
+ packet_info *pinfo)
+{
+ vj_header_t *hdr_buf;
+ guint8 offset;
+ guint8 *data_ptr;
+ iphdr_type *ip;
+ tcphdr_type *thp;
+ gint hdr_len;
+ gint buf_len;
+ guint8 *pbuf;
+
+ g_assert(src_tvb);
+
+ /* Get decompressed header stored in fd protocol area */
+ hdr_buf = p_get_proto_data(pinfo->fd, proto_vj);
+ if(hdr_buf == NULL) {
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ compressed TCP (previous data bad or missing)");
+ return VJ_ERROR;
+ }
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ compressed TCP");
+
+ /* Get the data offset in the tvbuff */
+ offset = hdr_buf->offset;
+
+ /* Copy header and form tvb */
+ data_ptr = hdr_buf->data;
+ ip = (iphdr_type *)data_ptr;
+ hdr_len = lo_nibble(ip->ihl_version) * 4;
+ thp = (tcphdr_type *)(data_ptr + hdr_len);
+ hdr_len += TCP_OFFSET(thp) * 4;
+ buf_len = tvb_length(src_tvb) + hdr_len - offset;
+ pbuf = g_malloc(buf_len);
+ memcpy(pbuf, data_ptr, hdr_len);
+ tvb_memcpy(src_tvb, pbuf + hdr_len, offset, buf_len - hdr_len);
+ *dst_tvb = tvb_new_real_data(pbuf, buf_len, g_ntohs(ip->tot_len));
+ tvb_set_child_real_data_tvbuff(src_tvb, *dst_tvb);
+ add_new_data_source(pinfo, *dst_tvb, "VJ Decompressed");
+ return VJ_OK;
+}
+
+/*
+ * For VJ compressed packet:
+ *
+ * check if it is malformed;
+ * dissect the relevant fields;
+ * update the decompressor state on the first pass.
+ */
+static gint
+vjc_process(tvbuff_t *src_tvb, packet_info *pinfo, proto_tree *tree,
+ slcompress *comp)
+{
+ int offset = ZERO;
+ int i;
+ gint changes;
+ proto_item *ti;
+ proto_tree *changes_tree;
+ guint8 conn_index;
+ cstate *cs = NULL;
+ iphdr_type *ip = NULL;
+ tcphdr_type *thp = NULL;
+ guint16 tcp_cksum;
+ gint hdrlen = ZERO;
+ guint16 word;
+ int delta;
+ gint len;
+ vj_header_t *buf_hdr;
+ guint8 *data_ptr;
+
+ if(tvb_length(src_tvb) < 3){
+ /*
+ * We don't even have enough data for the change byte, so we can't
+ * determine which connection this is; mark all connections as
+ * non-decompressible.
+ */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ compressed TCP (not enough data available)");
+ if(tree != NULL)
+ call_dissector(data_handle, src_tvb, pinfo, tree);
+ if(comp != NULL) {
+ for(i = 0; i < TCP_SIMUL_CONV_MAX; i++)
+ comp->rstate[i].flags |= SLF_TOSS;
+ }
+ return VJ_ERROR;
+ }
+
+ /* Read the change byte */
+ changes = tvb_get_guint8(src_tvb, offset);
+ if(tree != NULL) {
+ switch (changes & SPECIALS_MASK) {
+
+ case SPECIAL_I:
+ ti = proto_tree_add_uint_format(tree, hf_vj_change_mask, src_tvb,
+ offset, 1, changes,
+ "Change mask: 0x%02x (echoed interactive traffic)",
+ changes);
+ break;
+
+ case SPECIAL_D:
+ ti = proto_tree_add_uint_format(tree, hf_vj_change_mask, src_tvb,
+ offset, 1, changes,
+ "Change mask: 0x%02x (unidirectional data)",
+ changes);
+ break;
+
+ default:
+ /*
+ * XXX - summarize bits?
+ */
+ ti = proto_tree_add_uint_format(tree, hf_vj_change_mask, src_tvb,
+ offset, 1, changes,
+ "Change mask: 0x%02x", changes);
+ break;
+ }
+ changes_tree = proto_item_add_subtree(ti, ett_vj_changes);
+ proto_tree_add_boolean(changes_tree, hf_vj_change_mask_c, src_tvb,
+ offset, 1, changes);
+ proto_tree_add_boolean(changes_tree, hf_vj_change_mask_i, src_tvb,
+ offset, 1, changes);
+ proto_tree_add_boolean(changes_tree, hf_vj_change_mask_p, src_tvb,
+ offset, 1, changes);
+ proto_tree_add_boolean(changes_tree, hf_vj_change_mask_s, src_tvb,
+ offset, 1, changes);
+ proto_tree_add_boolean(changes_tree, hf_vj_change_mask_a, src_tvb,
+ offset, 1, changes);
+ proto_tree_add_boolean(changes_tree, hf_vj_change_mask_w, src_tvb,
+ offset, 1, changes);
+ proto_tree_add_boolean(changes_tree, hf_vj_change_mask_u, src_tvb,
+ offset, 1, changes);
+ }
+ offset++;
+
+ if(changes & NEW_C){ /* Read conn index */
+ conn_index = tvb_get_guint8(src_tvb, offset);
+ if(tree != NULL)
+ proto_tree_add_uint(tree, hf_vj_connection_number, src_tvb, offset, 1,
+ conn_index);
+ offset++;
+ if(comp != NULL)
+ comp->recv_current = conn_index;
+ }
+
+ if(!pinfo->fd->flags.visited) {
+ /*
+ * This is the first time this frame has been seen, so we need
+ * state information to decompress it. If that information isn't
+ * available, don't use the state information, and don't update it,
+ * either.
+ */
+ if(comp != NULL && !(comp->rstate[comp->recv_current].flags & SLF_TOSS)) {
+ cs = &comp->rstate[comp->recv_current];
+ thp = &cs->cs_tcp;
+ ip = &cs->cs_ip;
+ }
+ }
+
+ /* Build TCP and IP headers */
+ tcp_cksum = tvb_get_ntohs(src_tvb, offset);
+ if(tree != NULL)
+ proto_tree_add_uint(tree, hf_vj_tcp_cksum, src_tvb, offset, 2, tcp_cksum);
+ if(cs != NULL) {
+ hdrlen = lo_nibble(ip->ihl_version) * 4 + TCP_OFFSET(thp) * 4;
+ thp->cksum = g_htons(tcp_cksum);
+ }
+ offset += 2;
+ if(cs != NULL) {
+ if(changes & CHANGE_PUSH_BIT)
+ thp->flags |= TCP_PUSH_BIT;
+ else
+ thp->flags &= ~TCP_PUSH_BIT;
+ }
+
+ /* Deal with special cases and normal deltas */
+ switch(changes & SPECIALS_MASK){
+ case SPECIAL_I: /* Echoed terminal traffic */
+ if(cs != NULL) {
+ word = g_ntohs(ip->tot_len) - hdrlen;
+ thp->ack_seq = g_htonl(g_ntohl(thp->ack_seq) + word);
+ thp->seq = g_htonl(g_ntohl(thp->seq) + word);
+ }
+ break;
+ case SPECIAL_D: /* Unidirectional data */
+ if(cs != NULL)
+ thp->seq = g_htonl(g_ntohl(thp->seq) + g_ntohs(ip->tot_len) - hdrlen);
+ break;
+ default:
+ if(changes & NEW_U){
+ delta = get_unsigned_delta(src_tvb, &offset, hf_vj_urp, tree);
+ if(cs != NULL) {
+ thp->urg_ptr = delta;
+ thp->flags |= TCP_URG_BIT;
+ }
+ } else {
+ if(cs != NULL)
+ thp->flags &= ~TCP_URG_BIT;
+ }
+ if(changes & NEW_W) {
+ delta = get_signed_delta(src_tvb, &offset, hf_vj_win_delta, tree);
+ if(cs != NULL)
+ thp->window = g_htons(g_ntohs(thp->window) + delta);
+ }
+ if(changes & NEW_A) {
+ delta = get_unsigned_delta(src_tvb, &offset, hf_vj_ack_delta, tree);
+ if(cs != NULL)
+ thp->ack_seq = g_htonl(g_ntohl(thp->ack_seq) + delta);
+ }
+ if(changes & NEW_S) {
+ delta = get_unsigned_delta(src_tvb, &offset, hf_vj_seq_delta, tree);
+ if(cs != NULL)
+ thp->seq = g_htonl(g_ntohl(thp->seq) + delta);
+ }
+ break;
+ }
+ if(changes & NEW_I)
+ delta = get_unsigned_delta(src_tvb, &offset, hf_vj_ip_id_delta, tree);
+ else
+ delta = 1;
+ if(cs != NULL)
+ ip->id = g_htons(g_ntohs(ip->id) + delta);
+
+ /* Compute IP packet length and the buffer length needed */
+ len = tvb_reported_length_remaining(src_tvb, offset);
+ if(len < ZERO) {
+ /*
+ * This shouldn't happen, as we *were* able to fetch stuff right before
+ * offset.
+ */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ compressed TCP (not enough data available)");
+ if(cs != NULL)
+ cs->flags |= SLF_TOSS;
+ return VJ_ERROR;
+ }
+
+ /* Show the TCP payload */
+ if(tree != NULL && tvb_offset_exists(src_tvb, offset))
+ proto_tree_add_text(tree, src_tvb, offset, -1, "TCP payload");
+
+ /* Nothing more to do if we don't have any compression state */
+ if(comp == NULL) {
+ /* Direction of the traffic unknown - can't decompress */
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "VJ compressed TCP (direction unknown)");
+ return VJ_ERROR;
+ }
+
+ if(cs != NULL) {
+ len += hdrlen;
+ ip->tot_len = g_htons(len);
+ /* Compute IP check sum */
+ ip->cksum = ZERO;
+ ip->cksum = ip_csum((guint8 *)ip, lo_nibble(ip->ihl_version) * 4);
+
+ /* Store the reconstructed header in frame data area */
+ buf_hdr = g_mem_chunk_alloc(vj_header_memchunk);
+ buf_hdr->offset = offset; /* Offset in tvbuff is also stored */
+ data_ptr = buf_hdr->data;
+ memcpy(data_ptr, ip, IP_HDR_LEN);
+ data_ptr += IP_HDR_LEN;
+ if(lo_nibble(ip->ihl_version) > 5) {
+ memcpy(data_ptr, cs->cs_ipopt, (lo_nibble(ip->ihl_version) - 5) * 4);
+ data_ptr += (lo_nibble(ip->ihl_version) - 5) * 4;
+ }
+ memcpy(data_ptr, thp, TCP_HDR_LEN);
+ data_ptr += TCP_HDR_LEN;
+ if(TCP_OFFSET(thp) > 5)
+ memcpy(data_ptr, cs->cs_tcpopt, (TCP_OFFSET(thp) - 5) * 4);
+ p_add_proto_data(pinfo->fd, proto_vj, buf_hdr);
+ }
+
+ return VJ_OK;
+}
+
+/*
+ * Get an unsigned delta for a field, and put it into the protocol tree if
+ * we're building a protocol tree.
+ */
+static int
+get_unsigned_delta(tvbuff_t *tvb, int *offsetp, int hf, proto_tree *tree)
+{
+ int offset = *offsetp;
+ int len;
+ guint16 del;
+
+ len = 1;
+ del = tvb_get_guint8(tvb, offset++);
+ if(del == ZERO){
+ del = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ len += 2;
+ }
+ if(tree != NULL)
+ proto_tree_add_uint(tree, hf, tvb, *offsetp, len, del);
+ *offsetp = offset;
+ return del;
+}
+
+/*
+ * Get a signed delta for a field, and put it into the protocol tree if
+ * we're building a protocol tree.
+ */
+static int
+get_signed_delta(tvbuff_t *tvb, int *offsetp, int hf, proto_tree *tree)
+{
+ int offset = *offsetp;
+ int len;
+ gint16 del;
+
+ len = 1;
+ del = tvb_get_guint8(tvb, offset++);
+ if(del == ZERO){
+ del = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ len += 2;
+ }
+ if(tree != NULL)
+ proto_tree_add_int(tree, hf, tvb, *offsetp, len, del);
+ *offsetp = offset;
+ return del;
+}
+
+/* Wrapper for in_cksum function */
+static guint16
+ip_csum(const guint8 * ptr, guint32 len)
+{
+ vec_t cksum_vec[1];
+
+ cksum_vec[0].ptr = ptr;
+ cksum_vec[0].len = len;
+ return in_cksum(&cksum_vec[0], 1);
+}
diff --git a/epan/dissectors/packet-vlan.c b/epan/dissectors/packet-vlan.c
new file mode 100644
index 0000000000..d9d423f411
--- /dev/null
+++ b/epan/dissectors/packet-vlan.c
@@ -0,0 +1,165 @@
+/* packet-vlan.c
+ * Routines for VLAN 802.1Q ethernet header disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-ieee8023.h"
+#include "packet-ipx.h"
+#include "packet-llc.h"
+#include "packet-vlan.h"
+#include "etypes.h"
+
+static int proto_vlan = -1;
+static int hf_vlan_priority = -1;
+static int hf_vlan_cfi = -1;
+static int hf_vlan_id = -1;
+static int hf_vlan_etype = -1;
+static int hf_vlan_len = -1;
+static int hf_vlan_trailer = -1;
+
+static gint ett_vlan = -1;
+
+void
+capture_vlan(const guchar *pd, int offset, int len, packet_counts *ld ) {
+ guint16 encap_proto;
+ if ( !BYTES_ARE_IN_FRAME(offset,len,5) ) {
+ ld->other++;
+ return;
+ }
+ encap_proto = pntohs( &pd[offset+2] );
+ if ( encap_proto <= IEEE_802_3_MAX_LEN) {
+ if ( pd[offset+4] == 0xff && pd[offset+5] == 0xff ) {
+ capture_ipx(ld);
+ } else {
+ capture_llc(pd,offset+4,len,ld);
+ }
+ } else {
+ capture_ethertype(encap_proto, pd, offset+4, len, ld);
+ }
+}
+
+static void
+dissect_vlan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ti;
+ guint16 tci,encap_proto;
+ volatile gboolean is_802_2;
+ proto_tree *volatile vlan_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "VLAN");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ tci = tvb_get_ntohs( tvb, 0 );
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "PRI: %d CFI: %d ID: %d",
+ (tci >> 13), ((tci >> 12) & 1), (tci & 0xFFF));
+ }
+
+ vlan_tree = NULL;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vlan, tvb, 0, 4, FALSE);
+ vlan_tree = proto_item_add_subtree(ti, ett_vlan);
+
+ proto_tree_add_uint(vlan_tree, hf_vlan_priority, tvb, 0, 2, tci);
+ proto_tree_add_uint(vlan_tree, hf_vlan_cfi, tvb, 0, 2, tci);
+ proto_tree_add_uint(vlan_tree, hf_vlan_id, tvb, 0, 2, tci);
+ }
+
+ encap_proto = tvb_get_ntohs(tvb, 2);
+ if (encap_proto <= IEEE_802_3_MAX_LEN) {
+ /* Is there an 802.2 layer? I can tell by looking at the first 2
+ bytes after the VLAN header. If they are 0xffff, then what
+ follows the VLAN header is an IPX payload, meaning no 802.2.
+ (IPX/SPX is they only thing that can be contained inside a
+ straight 802.3 packet, so presumably the same applies for
+ Ethernet VLAN packets). A non-0xffff value means that there's an
+ 802.2 layer inside the VLAN layer */
+ is_802_2 = TRUE;
+ TRY {
+ if (tvb_get_ntohs(tvb, 4) == 0xffff) {
+ is_802_2 = FALSE;
+ }
+ }
+ CATCH2(BoundsError, ReportedBoundsError) {
+ ; /* do nothing */
+
+ }
+ ENDTRY;
+
+ dissect_802_3(encap_proto, is_802_2, tvb, 4, pinfo, tree, vlan_tree,
+ hf_vlan_len, hf_vlan_trailer, 0);
+ } else {
+ ethertype(encap_proto, tvb, 4, pinfo, tree, vlan_tree,
+ hf_vlan_etype, hf_vlan_trailer, 0);
+ }
+}
+
+void
+proto_register_vlan(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_vlan_priority, {
+ "Priority", "vlan.priority", FT_UINT16, BASE_DEC,
+ 0, 0xE000, "Priority", HFILL }},
+ { &hf_vlan_cfi, {
+ "CFI", "vlan.cfi", FT_UINT16, BASE_DEC,
+ 0, 0x1000, "CFI", HFILL }}, /* XXX - Boolean? */
+ { &hf_vlan_id, {
+ "ID", "vlan.id", FT_UINT16, BASE_DEC,
+ 0, 0x0FFF, "ID", HFILL }},
+ { &hf_vlan_etype, {
+ "Type", "vlan.etype", FT_UINT16, BASE_HEX,
+ VALS(etype_vals), 0x0, "Type", HFILL }},
+ { &hf_vlan_len, {
+ "Length", "vlan.len", FT_UINT16, BASE_DEC,
+ NULL, 0x0, "Length", HFILL }},
+ { &hf_vlan_trailer, {
+ "Trailer", "vlan.trailer", FT_BYTES, BASE_NONE,
+ NULL, 0x0, "VLAN Trailer", HFILL }}
+ };
+ static gint *ett[] = {
+ &ett_vlan,
+ };
+
+ proto_vlan = proto_register_protocol("802.1q Virtual LAN", "VLAN", "vlan");
+ proto_register_field_array(proto_vlan, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_vlan(void)
+{
+ dissector_handle_t vlan_handle;
+
+ vlan_handle = create_dissector_handle(dissect_vlan, proto_vlan);
+ dissector_add("ethertype", ETHERTYPE_VLAN, vlan_handle);
+}
diff --git a/epan/dissectors/packet-vlan.h b/epan/dissectors/packet-vlan.h
new file mode 100644
index 0000000000..356b01a7c2
--- /dev/null
+++ b/epan/dissectors/packet-vlan.h
@@ -0,0 +1,29 @@
+/* packet-vlan.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_VLAN_H__
+#define __PACKET_VLAN_H__
+
+void capture_vlan(const guchar *, int, int, packet_counts *);
+
+#endif
diff --git a/epan/dissectors/packet-vrrp.c b/epan/dissectors/packet-vrrp.c
new file mode 100644
index 0000000000..e85c1c8cc4
--- /dev/null
+++ b/epan/dissectors/packet-vrrp.c
@@ -0,0 +1,302 @@
+/* packet-vrrp.c
+ * Routines for the Virtual Router Redundancy Protocol (VRRP)
+ * RFC2338
+ *
+ * Heikki Vatiainen <hessu@cs.tut.fi>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "ipproto.h"
+#include "in_cksum.h"
+
+static gint proto_vrrp = -1;
+static gint ett_vrrp = -1;
+static gint ett_vrrp_ver_type = -1;
+
+static gint hf_vrrp_ver_type = -1;
+static gint hf_vrrp_version = -1;
+static gint hf_vrrp_type = -1;
+static gint hf_vrrp_virt_rtr_id = -1;
+static gint hf_vrrp_prio = -1;
+static gint hf_vrrp_count_ip = -1;
+static gint hf_vrrp_auth_type = -1;
+static gint hf_vrrp_adver_int = -1;
+static gint hf_vrrp_ip = -1;
+static gint hf_vrrp_ip6 = -1;
+
+#define VRRP_VERSION_MASK 0xf0
+#define VRRP_TYPE_MASK 0x0f
+#define VRRP_AUTH_DATA_LEN 8
+
+#define VRRP_TYPE_ADVERTISEMENT 1
+static const value_string vrrp_type_vals[] = {
+ {VRRP_TYPE_ADVERTISEMENT, "Advertisement"},
+ {0, NULL}
+};
+
+#define VRRP_AUTH_TYPE_NONE 0
+#define VRRP_AUTH_TYPE_SIMPLE_TEXT 1
+#define VRRP_AUTH_TYPE_IP_AUTH_HDR 2
+static const value_string vrrp_auth_vals[] = {
+ {VRRP_AUTH_TYPE_NONE, "No Authentication"},
+ {VRRP_AUTH_TYPE_SIMPLE_TEXT, "Simple Text Authentication [RFC 2338] / Reserved [RFC 3768]"},
+ {VRRP_AUTH_TYPE_IP_AUTH_HDR, "IP Authentication Header [RFC 2338] / Reserved [RFC 3768]"},
+ {0, NULL}
+};
+
+#define VRRP_PRIORITY_MASTER_STOPPING 0
+/* Values between 1 and 254 inclusive are for backup VRRP routers */
+#define VRRP_PRIORITY_DEFAULT 100
+#define VRRP_PRIORITY_OWNER 255
+static const value_string vrrp_prio_vals[] = {
+ {VRRP_PRIORITY_MASTER_STOPPING, "Current Master has stopped participating in VRRP"},
+ {VRRP_PRIORITY_DEFAULT, "Default priority for a backup VRRP router"},
+ {VRRP_PRIORITY_OWNER, "This VRRP router owns the virtual router's IP address(es)"},
+ {0, NULL }
+};
+
+
+static void
+dissect_vrrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ gint vrrp_len;
+ guint8 ver_type;
+ vec_t cksum_vec[4];
+ guint32 phdr[2];
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "VRRP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ver_type = tvb_get_guint8(tvb, 0);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s (v%u)",
+ "Announcement", hi_nibble(ver_type));
+ }
+
+ if (tree) {
+ proto_item *ti, *tv;
+ proto_tree *vrrp_tree, *ver_type_tree;
+ guint8 priority, ip_count = 0, auth_type;
+ guint16 cksum, computed_cksum;
+ guint8 auth_buf[VRRP_AUTH_DATA_LEN + 1];
+
+ ti = proto_tree_add_item(tree, proto_vrrp, tvb, 0, -1, FALSE);
+ vrrp_tree = proto_item_add_subtree(ti, ett_vrrp);
+
+ tv = proto_tree_add_uint_format(vrrp_tree, hf_vrrp_ver_type,
+ tvb, offset, 1, ver_type,
+ "Version %u, Packet type %u (%s)",
+ hi_nibble(ver_type), lo_nibble(ver_type),
+ val_to_str(lo_nibble(ver_type), vrrp_type_vals, "Unknown"));
+ ver_type_tree = proto_item_add_subtree(tv, ett_vrrp_ver_type);
+ proto_tree_add_uint(ver_type_tree, hf_vrrp_version, tvb,
+ offset, 1, ver_type);
+ proto_tree_add_uint(ver_type_tree, hf_vrrp_type, tvb, offset, 1,
+ ver_type);
+ offset++;
+
+ proto_tree_add_item(vrrp_tree, hf_vrrp_virt_rtr_id, tvb, offset, 1, FALSE);
+ offset++;
+
+ priority = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint_format(vrrp_tree, hf_vrrp_prio, tvb, offset, 1, priority, "Priority: %u (%s)",
+ priority,
+ val_to_str(priority, vrrp_prio_vals, "Non-default backup priority"));
+ offset++;
+
+ switch(hi_nibble(ver_type)) {
+ case 3:
+ /* Skip reserve field */
+ offset++;
+ break;
+ case 2:
+ default:
+ ip_count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(vrrp_tree, hf_vrrp_count_ip, tvb,
+ offset, 1, ip_count);
+ offset++;
+ break;
+ }
+
+ auth_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(vrrp_tree, hf_vrrp_auth_type, tvb, offset, 1, FALSE);
+ offset++;
+
+ proto_tree_add_item(vrrp_tree, hf_vrrp_adver_int, tvb, offset, 1, FALSE);
+ offset++;
+
+ cksum = tvb_get_ntohs(tvb, offset);
+ vrrp_len = (gint)tvb_reported_length(tvb);
+ if (!pinfo->fragmented && (gint)tvb_length(tvb) >= vrrp_len) {
+ /* The packet isn't part of a fragmented datagram
+ and isn't truncated, so we can checksum it. */
+ switch(hi_nibble(ver_type)) {
+ case 3:
+ /* Set up the fields of the pseudo-header. */
+ cksum_vec[0].ptr = pinfo->src.data;
+ cksum_vec[0].len = pinfo->src.len;
+ cksum_vec[1].ptr = pinfo->dst.data;
+ cksum_vec[1].len = pinfo->dst.len;
+ cksum_vec[2].ptr = (const guint8 *)&phdr;
+ phdr[0] = g_htonl(vrrp_len);
+ phdr[1] = g_htonl(IP_PROTO_VRRP);
+ cksum_vec[2].len = 8;
+ cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, vrrp_len);
+ cksum_vec[3].len = vrrp_len;
+ computed_cksum = in_cksum(cksum_vec, 4);
+ break;
+ case 2:
+ default:
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, vrrp_len);
+ cksum_vec[0].len = vrrp_len;
+ computed_cksum = in_cksum(&cksum_vec[0], 1);
+ break;
+ }
+ if (computed_cksum == 0) {
+ proto_tree_add_text(vrrp_tree, tvb, offset, 2,
+ "Checksum: 0x%04x (correct)",
+ cksum);
+ } else {
+ proto_tree_add_text(vrrp_tree, tvb, offset, 2,
+ "Checksum: 0x%04x (incorrect, should be 0x%04x)",
+ cksum,
+ in_cksum_shouldbe(cksum, computed_cksum));
+ }
+ } else {
+ proto_tree_add_text(vrrp_tree, tvb, offset, 2,
+ "Checksum: 0x%04x", cksum);
+ }
+ offset+=2;
+
+ switch(hi_nibble(ver_type)) {
+ case 3:
+ proto_tree_add_item(vrrp_tree, hf_vrrp_ip6, tvb, offset, 16, FALSE);
+ offset+=16;
+ break;
+ case 2:
+ default:
+ while (ip_count > 0) {
+ proto_tree_add_item(vrrp_tree, hf_vrrp_ip, tvb,
+ offset, 4, FALSE);
+ offset+=4;
+ ip_count--;
+ }
+ break;
+ }
+ if (auth_type != VRRP_AUTH_TYPE_SIMPLE_TEXT)
+ return; /* Contents of the authentication data is undefined */
+
+ tvb_get_nstringz0(tvb, offset, sizeof auth_buf, auth_buf);
+ if (auth_buf[0] != '\0')
+ proto_tree_add_text(vrrp_tree, tvb, offset,
+ VRRP_AUTH_DATA_LEN,
+ "Authentication string: `%s'",
+ auth_buf);
+ offset+=8;
+ }
+}
+
+void proto_register_vrrp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_vrrp_ver_type,
+ {"VRRP message version and type", "vrrp.typever",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "VRRP version and type", HFILL }},
+
+ { &hf_vrrp_version,
+ {"VRRP protocol version", "vrrp.version",
+ FT_UINT8, BASE_DEC, NULL, VRRP_VERSION_MASK,
+ "VRRP version", HFILL }},
+
+ { &hf_vrrp_type,
+ {"VRRP packet type", "vrrp.type",
+ FT_UINT8, BASE_DEC, VALS(vrrp_type_vals), VRRP_TYPE_MASK,
+ "VRRP type", HFILL }},
+
+ { &hf_vrrp_virt_rtr_id,
+ {"Virtual Rtr ID", "vrrp.virt_rtr_id",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Virtual router this packet is reporting status for", HFILL }},
+
+ { &hf_vrrp_prio,
+ {"Priority", "vrrp.prio",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Sending VRRP router's priority for the virtual router", HFILL }},
+
+ { &hf_vrrp_count_ip,
+ {"Count IP Addrs", "vrrp.count_ip_addrs",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "The number of IP addresses contained in this VRRP advertisement", HFILL }},
+
+ { &hf_vrrp_auth_type,
+ {"Auth Type", "vrrp.auth_type",
+ FT_UINT8, BASE_DEC, VALS(vrrp_auth_vals), 0x0,
+ "The authentication method being utilized", HFILL }},
+
+ { &hf_vrrp_adver_int,
+ {"Adver Int", "vrrp.adver_int",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Time interval (in seconds) between ADVERTISEMENTS", HFILL }},
+
+ { &hf_vrrp_ip,
+ {"IP Address", "vrrp.ip_addr",
+ FT_IPv4, 0, NULL, 0x0,
+ "IP address associated with the virtual router", HFILL }},
+
+ { &hf_vrrp_ip6,
+ {"IPv6 Address", "vrrp.ipv6_addr",
+ FT_IPv6, 0, NULL, 0x0,
+ "IPv6 address associated with the virtual router", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_vrrp,
+ &ett_vrrp_ver_type
+ };
+
+ proto_vrrp = proto_register_protocol("Virtual Router Redundancy Protocol",
+ "VRRP", "vrrp");
+ proto_register_field_array(proto_vrrp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ return;
+}
+
+void
+proto_reg_handoff_vrrp(void)
+{
+ dissector_handle_t vrrp_handle;
+
+ vrrp_handle = create_dissector_handle(dissect_vrrp, proto_vrrp);
+ dissector_add("ip.proto", IP_PROTO_VRRP, vrrp_handle);
+}
diff --git a/epan/dissectors/packet-vtp.c b/epan/dissectors/packet-vtp.c
new file mode 100644
index 0000000000..0b82539b81
--- /dev/null
+++ b/epan/dissectors/packet-vtp.c
@@ -0,0 +1,698 @@
+/* packet-vtp.c
+ * Routines for the disassembly of Cisco's Virtual Trunking Protocol
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+
+/*
+ * See
+ *
+ * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
+ *
+ * for some information on VTP.
+ *
+ * It's incomplete, and it appears to be inaccurate in a number of places,
+ * but it's all I could find....
+ */
+
+static int proto_vtp = -1;
+static int hf_vtp_version = -1;
+static int hf_vtp_code = -1;
+static int hf_vtp_followers = -1;
+static int hf_vtp_md_len = -1;
+static int hf_vtp_md = -1;
+static int hf_vtp_conf_rev_num = -1;
+static int hf_vtp_upd_id = -1;
+static int hf_vtp_upd_ts = -1;
+static int hf_vtp_md5_digest = -1;
+static int hf_vtp_seq_num = -1;
+static int hf_vtp_start_value = -1;
+static int hf_vtp_vlan_info_len = -1;
+static int hf_vtp_vlan_status_vlan_susp = -1;
+static int hf_vtp_vlan_type = -1;
+static int hf_vtp_vlan_name_len = -1;
+static int hf_vtp_isl_vlan_id = -1;
+static int hf_vtp_mtu_size = -1;
+static int hf_vtp_802_10_index = -1;
+static int hf_vtp_vlan_name = -1;
+static int hf_vtp_vlan_tlvtype = -1;
+static int hf_vtp_vlan_tlvlength = -1;
+
+static gint ett_vtp = -1;
+static gint ett_vtp_vlan_info = -1;
+static gint ett_vtp_vlan_status = -1;
+static gint ett_vtp_tlv = -1;
+
+static int
+dissect_vlan_info(tvbuff_t *tvb, int offset, proto_tree *tree);
+static void
+dissect_vlan_info_tlv(tvbuff_t *tvb, int offset, int length,
+ proto_tree *tree, proto_item *ti, guint8 type);
+
+#define SUMMARY_ADVERT 0x01
+#define SUBSET_ADVERT 0x02
+#define ADVERT_REQUEST 0x03
+
+static const value_string type_vals[] = {
+ { SUMMARY_ADVERT, "Summary-Advert" },
+ { SUBSET_ADVERT, "Subset-Advert" },
+ { ADVERT_REQUEST, "Advert-Request" },
+ { 0, NULL },
+};
+
+static void
+dissect_vtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *vtp_tree = NULL;
+ int offset = 0;
+ guint8 code;
+ guint8 md_len;
+ const guint8 *upd_timestamp;
+ int vlan_info_len;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "VTP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Virtual Trunking Protocol");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_vtp, tvb, offset, -1,
+ FALSE);
+ vtp_tree = proto_item_add_subtree(ti, ett_vtp);
+
+ proto_tree_add_item(vtp_tree, hf_vtp_version, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ code = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(vtp_tree, hf_vtp_code, tvb, offset, 1,
+ code);
+ offset += 1;
+
+ switch (code) {
+
+ case SUMMARY_ADVERT:
+ proto_tree_add_item(vtp_tree, hf_vtp_followers, tvb, offset,
+ 1, FALSE);
+ offset += 1;
+
+ md_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(vtp_tree, hf_vtp_md_len, tvb, offset,
+ 1, md_len);
+ offset += 1;
+
+ proto_tree_add_item(vtp_tree, hf_vtp_md, tvb, offset,
+ 32, FALSE);
+ offset += 32;
+
+ proto_tree_add_item(vtp_tree, hf_vtp_conf_rev_num, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(vtp_tree, hf_vtp_upd_id, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ upd_timestamp = tvb_get_ptr(tvb, offset, 12);
+ proto_tree_add_string_format(vtp_tree, hf_vtp_upd_ts, tvb,
+ offset, 12, upd_timestamp,
+ "Update Timestamp: %.2s-%.2s-%.2s %.2s:%.2s:%.2s",
+ &upd_timestamp[0], &upd_timestamp[2], &upd_timestamp[4],
+ &upd_timestamp[6], &upd_timestamp[8], &upd_timestamp[10]);
+ offset += 12;
+
+ proto_tree_add_item(vtp_tree, hf_vtp_md5_digest, tvb,
+ offset, 16, FALSE);
+ break;
+
+ case SUBSET_ADVERT:
+ proto_tree_add_item(vtp_tree, hf_vtp_seq_num, tvb, offset,
+ 1, FALSE);
+ offset += 1;
+
+ md_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(vtp_tree, hf_vtp_md_len, tvb, offset,
+ 1, md_len);
+ offset += 1;
+
+ proto_tree_add_item(vtp_tree, hf_vtp_md, tvb, offset,
+ 32, FALSE);
+ offset += 32;
+
+ proto_tree_add_item(vtp_tree, hf_vtp_conf_rev_num, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ vlan_info_len =
+ dissect_vlan_info(tvb, offset, vtp_tree);
+ if (vlan_info_len < 0)
+ break;
+ offset += vlan_info_len;
+ }
+ break;
+
+ case ADVERT_REQUEST:
+ offset += 1; /* skip reserved field */
+
+ md_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(vtp_tree, hf_vtp_md_len, tvb, offset,
+ 1, md_len);
+ offset += 1;
+
+ proto_tree_add_item(vtp_tree, hf_vtp_start_value, tvb,
+ offset, 2, FALSE);
+ break;
+
+ case 0x04:
+ /*
+ * Mysterious type, seen a lot.
+ * Is this some mutant variant of Advert-Request?
+ */
+ offset += 1; /* skip unknown field */
+
+ md_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(vtp_tree, hf_vtp_md_len, tvb, offset,
+ 1, md_len);
+ offset += 1;
+
+ proto_tree_add_item(vtp_tree, hf_vtp_md, tvb, offset,
+ 32, FALSE);
+ offset += 32;
+
+ offset += 2; /* skip unknown field */
+
+ proto_tree_add_text(vtp_tree, tvb, offset, 2,
+ "VLAN ID of some sort: 0x%04x",
+ tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ break;
+ }
+ }
+}
+
+#define VLAN_SUSPENDED 0x01
+
+static const value_string vlan_type_vals[] = {
+ { 0x01, "Ethernet" },
+ { 0x02, "FDDI" },
+ { 0x03, "TrCRF" },
+ { 0x04, "FDDI-net" },
+ { 0x05, "TrBRF" },
+ { 0, NULL },
+};
+
+#define SR_RING_NUM 0x01
+#define SR_BRIDGE_NUM 0x02
+#define STP_TYPE 0x03
+#define PARENT_VLAN 0x04
+#define TR_BRIDGED_VLANS 0x05
+#define PRUNING 0x06
+#define BRIDGE_TYPE 0x07
+#define MAX_ARE_HOP_CNT 0x08
+#define MAX_STE_HOP_CNT 0x09
+#define BACKUP_CRF_MODE 0x0A
+
+static const value_string vlan_tlv_type_vals[] = {
+ { SR_RING_NUM, "Source-Routing Ring Number" },
+ { SR_BRIDGE_NUM, "Source-Routing Bridge Number" },
+ { STP_TYPE, "Spanning-Tree Protocol Type" },
+ { PARENT_VLAN, "Parent VLAN" },
+ { TR_BRIDGED_VLANS, "Translationally Bridged VLANs" },
+ { PRUNING, "Pruning" },
+ { BRIDGE_TYPE, "Bridge Type" },
+ { MAX_ARE_HOP_CNT, "Max ARE Hop Count" },
+ { MAX_STE_HOP_CNT, "Max STE Hop Count" },
+ { BACKUP_CRF_MODE, "Backup CRF Mode" },
+ { 0, NULL },
+};
+
+static int
+dissect_vlan_info(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *vlan_info_tree;
+ proto_tree *status_tree;
+ guint8 vlan_info_len;
+ int vlan_info_left;
+ guint8 status;
+ guint8 vlan_name_len;
+ guint8 type;
+ int length;
+ proto_tree *tlv_tree;
+
+ vlan_info_len = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(tree, tvb, offset, vlan_info_len,
+ "VLAN Information");
+ vlan_info_tree = proto_item_add_subtree(ti, ett_vtp_vlan_info);
+ vlan_info_left = vlan_info_len;
+
+ proto_tree_add_uint(vlan_info_tree, hf_vtp_vlan_info_len, tvb, offset, 1,
+ vlan_info_len);
+ offset += 1;
+ vlan_info_left -= 1;
+
+ if (vlan_info_left < 1)
+ return -1;
+ status = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_text(vlan_info_tree, tvb, offset, 1,
+ "Status: 0x%02x%s", status,
+ (status & VLAN_SUSPENDED) ? "(VLAN suspended)" : "");
+ status_tree = proto_item_add_subtree(ti, ett_vtp_vlan_status);
+ proto_tree_add_boolean(status_tree, hf_vtp_vlan_status_vlan_susp, tvb, offset, 1,
+ status);
+ offset += 1;
+ vlan_info_left -= 1;
+
+ if (vlan_info_left < 1)
+ return -1;
+ proto_tree_add_item(vlan_info_tree, hf_vtp_vlan_type, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+ vlan_info_left -= 1;
+
+ if (vlan_info_left < 1)
+ return -1;
+ vlan_name_len = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(vlan_info_tree, hf_vtp_vlan_name_len, tvb, offset, 1,
+ vlan_name_len);
+ offset += 1;
+ vlan_info_left -= 1;
+
+ if (vlan_info_left < 2)
+ return -1;
+ proto_tree_add_item(vlan_info_tree, hf_vtp_isl_vlan_id, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ vlan_info_left -= 2;
+
+ if (vlan_info_left < 2)
+ return -1;
+ proto_tree_add_item(vlan_info_tree, hf_vtp_mtu_size, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ vlan_info_left -= 2;
+
+ if (vlan_info_left < 4)
+ return -1;
+ proto_tree_add_item(vlan_info_tree, hf_vtp_802_10_index, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+ vlan_info_left -= 4;
+
+ /* VLAN name length appears to be rounded up to a multiple of 4. */
+ vlan_name_len = 4*((vlan_name_len + 3)/4);
+ if (vlan_info_left < vlan_name_len)
+ return -1;
+ proto_tree_add_item(vlan_info_tree, hf_vtp_vlan_name, tvb, offset,
+ vlan_name_len, FALSE);
+ offset += vlan_name_len;
+ vlan_info_left -= vlan_name_len;
+
+ while (vlan_info_left > 0) {
+ type = tvb_get_guint8(tvb, offset + 0);
+ length = tvb_get_guint8(tvb, offset + 1);
+
+ ti = proto_tree_add_text(vlan_info_tree, tvb, offset,
+ 2 + length*2, "%s",
+ val_to_str(type, vlan_tlv_type_vals,
+ "Unknown TLV type: 0x%02x"));
+ tlv_tree = proto_item_add_subtree(ti, ett_vtp_tlv);
+ proto_tree_add_uint(tlv_tree, hf_vtp_vlan_tlvtype, tvb, offset,
+ 1, type);
+ proto_tree_add_uint(tlv_tree, hf_vtp_vlan_tlvlength, tvb, offset+1,
+ 1, length);
+ offset += 2;
+ vlan_info_left -= 2;
+ if (length > 0) {
+ dissect_vlan_info_tlv(tvb, offset, length*2, tlv_tree,
+ ti, type);
+ }
+ offset += length*2;
+ vlan_info_left -= length*2;
+ }
+
+ return vlan_info_len;
+}
+
+static const value_string stp_type_vals[] = {
+ { 1, "SRT" },
+ { 2, "SRB" },
+ { 3, "Auto" },
+ { 0, NULL },
+};
+
+static const value_string pruning_vals[] = {
+ { 1, "Enabled" },
+ { 2, "Disabled" },
+ { 0, NULL },
+};
+
+static const value_string bridge_type_vals[] = {
+ { 1, "SRT" },
+ { 2, "SRB" },
+ { 0, NULL },
+};
+
+static const value_string backup_crf_mode_vals[] = {
+ { 1, "TrCRF is configured as a backup" },
+ { 2, "TrCRF is not configured as a backup" },
+ { 0, NULL },
+};
+
+static void
+dissect_vlan_info_tlv(tvbuff_t *tvb, int offset, int length,
+ proto_tree *tree, proto_item *ti, guint8 type)
+{
+ switch (type) {
+
+ case SR_RING_NUM:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Source-Routing Ring Number: 0x%04x",
+ tvb_get_ntohs(tvb, offset));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Source-Routing Ring Number: 0x%04x",
+ tvb_get_ntohs(tvb, offset));
+ } else {
+ proto_item_set_text(ti,
+ "Source-Routing Ring Number: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Source-Routing Ring Number: Bad length %u",
+ length);
+ }
+ break;
+
+ case SR_BRIDGE_NUM:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Source-Routing Bridge Number: 0x%04x",
+ tvb_get_ntohs(tvb, offset));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Source-Routing Bridge Number: 0x%04x",
+ tvb_get_ntohs(tvb, offset));
+ } else {
+ proto_item_set_text(ti,
+ "Source-Routing Bridge Number: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Source-Routing Bridge Number: Bad length %u",
+ length);
+ }
+ break;
+
+ case STP_TYPE:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Spanning-Tree Protocol Type: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), stp_type_vals,
+ "Unknown (0x%04x)"));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Spanning-Tree Protocol Type: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), stp_type_vals,
+ "Unknown (0x%04x)"));
+ } else {
+ proto_item_set_text(ti,
+ "Spanning-Tree Protocol Type: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Spanning-Tree Protocol Type: Bad length %u",
+ length);
+ }
+ break;
+
+ case PARENT_VLAN:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Parent VLAN: 0x%04x",
+ tvb_get_ntohs(tvb, offset));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Parent VLAN: 0x%04x",
+ tvb_get_ntohs(tvb, offset));
+ } else {
+ proto_item_set_text(ti,
+ "Parent VLAN: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Parent VLAN: Bad length %u",
+ length);
+ }
+ break;
+
+ case TR_BRIDGED_VLANS:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Translationally Bridged VLANs: 0x%04x",
+ tvb_get_ntohs(tvb, offset));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Translationally Bridged VLANs: 0x%04x",
+ tvb_get_ntohs(tvb, offset));
+ } else {
+ proto_item_set_text(ti,
+ "Translationally Bridged VLANs: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Translationally Bridged VLANs: Bad length %u",
+ length);
+ }
+ break;
+
+ case PRUNING:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Pruning: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), pruning_vals,
+ "Unknown (0x%04x)"));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Pruning: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), pruning_vals,
+ "Unknown (0x%04x)"));
+ } else {
+ proto_item_set_text(ti,
+ "Pruning: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Pruning: Bad length %u",
+ length);
+ }
+ break;
+
+ case BRIDGE_TYPE:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Bridge Type: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), bridge_type_vals,
+ "Unknown (0x%04x)"));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Bridge Type: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), bridge_type_vals,
+ "Unknown (0x%04x)"));
+ } else {
+ proto_item_set_text(ti,
+ "Bridge Type: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Bridge Type: Bad length %u",
+ length);
+ }
+ break;
+
+ case MAX_ARE_HOP_CNT:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Max ARE Hop Count: %u",
+ tvb_get_ntohs(tvb, offset));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Max ARE Hop Count: %u",
+ tvb_get_ntohs(tvb, offset));
+ } else {
+ proto_item_set_text(ti,
+ "Max ARE Hop Count: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Max ARE Hop Count: Bad length %u",
+ length);
+ }
+ break;
+
+ case MAX_STE_HOP_CNT:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Max STE Hop Count: %u",
+ tvb_get_ntohs(tvb, offset));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Max STE Hop Count: %u",
+ tvb_get_ntohs(tvb, offset));
+ } else {
+ proto_item_set_text(ti,
+ "Max STE Hop Count: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Max STE Hop Count: Bad length %u",
+ length);
+ }
+ break;
+
+ case BACKUP_CRF_MODE:
+ if (length == 2) {
+ proto_item_set_text(ti,
+ "Backup CRF Mode: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), backup_crf_mode_vals,
+ "Unknown (0x%04x)"));
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Backup CRF Mode: %s",
+ val_to_str(tvb_get_ntohs(tvb, offset), backup_crf_mode_vals,
+ "Unknown (0x%04x)"));
+ } else {
+ proto_item_set_text(ti,
+ "Backup CRF Mode: Bad length %u",
+ length);
+ proto_tree_add_text(tree, tvb, offset, length,
+ "Backup CRF Mode: Bad length %u",
+ length);
+ }
+ break;
+
+ default:
+ proto_tree_add_text(tree, tvb, offset, length, "Data");
+ break;
+ }
+}
+
+void
+proto_register_vtp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_vtp_version,
+ { "Version", "vtp.version", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_vtp_code,
+ { "Code", "vtp.code", FT_UINT8, BASE_HEX, VALS(type_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_vtp_followers,
+ { "Followers", "vtp.followers", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of following Subset-Advert messages", HFILL }},
+
+ { &hf_vtp_md_len,
+ { "Management Domain Length", "vtp.md_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of management domain string", HFILL }},
+
+ { &hf_vtp_md,
+ { "Management Domain", "vtp.md", FT_STRING, BASE_DEC, NULL, 0,
+ "Management domain", HFILL }},
+
+ { &hf_vtp_conf_rev_num,
+ { "Configuration Revision Number", "vtp.conf_rev_num", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Revision number of the configuration information", HFILL }},
+
+ { &hf_vtp_upd_id,
+ { "Updater Identity", "vtp.upd_id", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "IP address of the updater", HFILL }},
+
+ { &hf_vtp_upd_ts,
+ { "Update Timestamp", "vtp.upd_ts", FT_STRING, BASE_DEC, NULL, 0,
+ "Time stamp of the current configuration revision", HFILL }},
+
+ { &hf_vtp_md5_digest,
+ { "MD5 Digest", "vtp.md5_digest", FT_BYTES, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_vtp_seq_num,
+ { "Sequence Number", "vtp.seq_num", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Order of this frame in the sequence of Subset-Advert frames", HFILL }},
+
+ { &hf_vtp_start_value,
+ { "Start Value", "vtp.start_value", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "Virtual LAN ID of first VLAN for which information is requested", HFILL }},
+
+ { &hf_vtp_vlan_info_len,
+ { "VLAN Information Length", "vtp.vlan_info.len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of the VLAN information field", HFILL }},
+
+ { &hf_vtp_vlan_status_vlan_susp,
+ { "VLAN suspended", "vtp.vlan_info.status.vlan_susp", FT_BOOLEAN, 8, NULL, VLAN_SUSPENDED,
+ "VLAN suspended", HFILL }},
+
+ { &hf_vtp_vlan_type,
+ { "VLAN Type", "vtp.vlan_info.vlan_type", FT_UINT8, BASE_HEX, VALS(vlan_type_vals), 0x0,
+ "Type of VLAN", HFILL }},
+
+ { &hf_vtp_vlan_name_len,
+ { "VLAN Name Length", "vtp.vlan_info.vlan_name_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of VLAN name string", HFILL }},
+
+ { &hf_vtp_isl_vlan_id,
+ { "ISL VLAN ID", "vtp.vlan_info.isl_vlan_id", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "ID of this VLAN on ISL trunks", HFILL }},
+
+ { &hf_vtp_mtu_size,
+ { "MTU Size", "vtp.vlan_info.mtu_size", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "MTU for this VLAN", HFILL }},
+
+ { &hf_vtp_802_10_index,
+ { "802.10 Index", "vtp.vlan_info.802_10_index", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "IEEE 802.10 security association identifier for this VLAN", HFILL }},
+
+ { &hf_vtp_vlan_name,
+ { "VLAN Name", "vtp.vlan_info.vlan_name", FT_STRING, BASE_DEC, NULL, 0,
+ "VLAN name", HFILL }},
+
+ { &hf_vtp_vlan_tlvtype,
+ { "Type", "vtp.vlan_info.tlv_type", FT_UINT8, BASE_HEX, VALS(vlan_tlv_type_vals), 0x0,
+ "", HFILL }},
+
+ { &hf_vtp_vlan_tlvlength,
+ { "Length", "vtp.vlan_info.tlv_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_vtp,
+ &ett_vtp_vlan_info,
+ &ett_vtp_vlan_status,
+ &ett_vtp_tlv,
+ };
+
+ proto_vtp = proto_register_protocol("Virtual Trunking Protocol",
+ "VTP", "vtp");
+ proto_register_field_array(proto_vtp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_vtp(void)
+{
+ dissector_handle_t vtp_handle;
+
+ vtp_handle = create_dissector_handle(dissect_vtp, proto_vtp);
+ dissector_add("llc.cisco_pid", 0x2003, vtp_handle);
+}
diff --git a/epan/dissectors/packet-wap.c b/epan/dissectors/packet-wap.c
new file mode 100644
index 0000000000..f53db7b24c
--- /dev/null
+++ b/epan/dissectors/packet-wap.c
@@ -0,0 +1,327 @@
+/* packet-wap.c
+ *
+ * Utility routines for WAP dissectors
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * WAP dissector based on original work by Ben Fowler
+ * Updated by Neil Hunter <neil.hunter@energis-squared.com>
+ * WTLS support by Alexandre P. Ferreira (Splice IP)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-wap.h"
+
+/*
+ * Accessor to retrieve variable length int as used in WAP protocol.
+ * The value is encoded in the lower 7 bits. If the top bit is set, then the
+ * value continues into the next byte.
+ * The octetCount parameter holds the number of bytes read in order to return
+ * the final value. Can be pre-initialised to start at offset+count.
+*/
+guint
+tvb_get_guintvar (tvbuff_t *tvb, guint offset, guint *octetCount)
+{
+ guint value = 0;
+ guint octet;
+ guint counter = 0;
+ char cont = 1;
+
+#ifdef DEBUG
+ if (octetCount != NULL)
+ {
+ fprintf (stderr, "dissect_wap: Starting tvb_get_guintvar at offset %d, count=%d\n", offset, *octetCount);
+ /* counter = *octetCount; */
+ }
+ else
+ {
+ fprintf (stderr, "dissect_wap: Starting tvb_get_guintvar at offset %d, count=NULL\n", offset);
+ }
+#endif
+
+ while (cont != 0)
+ {
+ value<<=7; /* Value only exists in 7 of the 8 bits */
+ octet = tvb_get_guint8 (tvb, offset+counter);
+ counter++;
+ value += (octet & 0x7F);
+ cont = (octet & 0x80);
+#ifdef DEBUG
+ fprintf (stderr, "dissect_wap: computing: octet is %d (0x%02x), count=%d, value=%d, cont=%d\n", octet, octet, counter, value, cont);
+#endif
+ }
+
+ if (octetCount != NULL)
+ {
+ *octetCount = counter;
+#ifdef DEBUG
+ fprintf (stderr, "dissect_wap: Leaving tvb_get_guintvar count=%d, value=%u\n", *octetCount, value);
+#endif
+ }
+
+ return (value);
+}
+
+/* See http://www.iana.org/assignments/character-sets for the MIBenum mapping */
+const value_string vals_character_sets[] = {
+ { 0x0000, "*" },
+ { 0x0003, "us-ascii" },
+ { 0x0004, "iso-8859-1" },
+ { 0x0005, "iso-8859-2" },
+ { 0x0006, "iso-8859-3" },
+ { 0x0007, "iso-8859-4" },
+ { 0x0008, "iso-8859-5" },
+ { 0x0009, "iso-8859-6" },
+ { 0x000A, "iso-8859-7" },
+ { 0x000B, "iso-8859-8" },
+ { 0x000C, "iso-8859-9" },
+ { 0x000D, "iso-8859-10" },
+ { 0x000E, "iso_6937-2-add" },
+ { 0x000F, "jis_x0201" },
+ { 0x0010, "jis_encoding" },
+ { 0x0011, "shift_jis" },
+ { 0x0012, "euc-jp" },
+ { 0x0013, "extended_unix_code_fixed_width_for_japanese" },
+ { 0x0014, "bs_4730" },
+ { 0x0015, "sen_850200_c" },
+ { 0x0016, "it" },
+ { 0x0017, "es" },
+ { 0x0018, "din_66003" },
+ { 0x0019, "ns_4551-1" },
+ { 0x001A, "nf_z_62-010" },
+ { 0x001B, "iso-10646-utf-1" },
+ { 0x001C, "iso_646.basic:1983" },
+ { 0x001D, "invariant" },
+ { 0x001E, "iso_646.irv:1983" },
+ { 0x001F, "nats-sefi" },
+ { 0x0020, "nats-sefi-add" },
+ { 0x0021, "nats-dano" },
+ { 0x0022, "nats-dano-add" },
+ { 0x0023, "sen_850200_b" },
+ { 0x0024, "ks_c_5601-1987" },
+ { 0x0025, "iso-2022-kr" },
+ { 0x0026, "euc-kr" },
+ { 0x0027, "iso-2022-jp" },
+ { 0x0028, "iso-2022-jp-2" },
+ { 0x0029, "jis_c6220-1969-jp" },
+ { 0x002A, "jis_c6220-1969-ro" },
+ { 0x002B, "pt" },
+ { 0x002C, "greek7-old" },
+ { 0x002D, "latin-greek" },
+ { 0x002E, "nf_z_62-010_(1973)" },
+ { 0x002F, "latin-greek-1" },
+ { 0x0030, "iso_5427" },
+ { 0x0031, "jis_c6226-1978" },
+ { 0x0032, "bs_viewdata" },
+ { 0x0033, "inis" },
+ { 0x0034, "inis-8" },
+ { 0x0035, "inis-cyrillic" },
+ { 0x0036, "iso_5427:1981" },
+ { 0x0037, "iso_5428:1980" },
+ { 0x0038, "gb_1988-80" },
+ { 0x0039, "gb_2312-80" },
+ { 0x003A, "ns_4551-2" },
+ { 0x003B, "videotex-suppl" },
+ { 0x003C, "pt2" },
+ { 0x003D, "es2" },
+ { 0x003E, "msz_7795.3" },
+ { 0x003F, "jis_c6226-1983" },
+ { 0x0040, "greek7" },
+ { 0x0041, "asmo_449" },
+ { 0x0042, "iso-ir-90" },
+ { 0x0043, "jis_c6229-1984-a" },
+ { 0x0044, "jis_c6229-1984-b" },
+ { 0x0045, "jis_c6229-1984-b-add" },
+ { 0x0046, "jis_c6229-1984-hand" },
+ { 0x0047, "jis_c6229-1984-hand-add" },
+ { 0x0048, "jis_c6229-1984-kana" },
+ { 0x0049, "iso_2033-1983" },
+ { 0x004A, "ansi_x3.110-1983" },
+ { 0x004B, "t.61-7bit" },
+ { 0x004C, "t.61-8bit" },
+ { 0x004D, "ecma-cyrillic" },
+ { 0x004E, "csa_z243.4-1985-1" },
+ { 0x004F, "csa_z243.4-1985-2" },
+ { 0x0050, "csa_z243.4-1985-gr" },
+ { 0x0051, "iso_8859-6-e" },
+ { 0x0052, "iso_8859-6-i" },
+ { 0x0053, "t.101-g2" },
+ { 0x0054, "iso_8859-8-e" },
+ { 0x0055, "iso_8859-8-i" },
+ { 0x0056, "csn_369103" },
+ { 0x0057, "jus_i.b1.002" },
+ { 0x0058, "iec_p27-1" },
+ { 0x0059, "jus_i.b1.003-serb" },
+ { 0x005A, "jus_i.b1.003-mac" },
+ { 0x005B, "greek-ccitt" },
+ { 0x005C, "nc_nc00-10:81" },
+ { 0x005D, "iso_6937-2-25" },
+ { 0x005E, "gost_19768-74" },
+ { 0x005F, "iso_8859-supp" },
+ { 0x0060, "iso_10367-box" },
+ { 0x0061, "latin-lap" },
+ { 0x0062, "jis_x0212-1990" },
+ { 0x0063, "ds_2089" },
+ { 0x0064, "us-dk" },
+ { 0x0065, "dk-us" },
+ { 0x0066, "ksc5636" },
+ { 0x0067, "unicode-1-1-utf-7" },
+ { 0x0068, "iso-2022-cn" },
+ { 0x0069, "iso-2022-cn-ext" },
+ { 0x006A, "utf-8" },
+ { 0x006D, "iso-8859-13" },
+ { 0x006E, "iso-8859-14" },
+ { 0x006F, "iso-8859-15" },
+ { 0x03E8, "iso-10646-ucs-2" },
+ { 0x03E9, "iso-10646-ucs-4" },
+ { 0x03EA, "iso-10646-ucs-basic" },
+ { 0x03EB, "iso-10646-j-1" },
+ { 0x03EB, "iso-10646-unicode-latin1" },
+ { 0x03ED, "iso-unicode-ibm-1261" },
+ { 0x03EE, "iso-unicode-ibm-1268" },
+ { 0x03EF, "iso-unicode-ibm-1276" },
+ { 0x03F0, "iso-unicode-ibm-1264" },
+ { 0x03F1, "iso-unicode-ibm-1265" },
+ { 0x03F2, "unicode-1-1" },
+ { 0x03F3, "scsu" },
+ { 0x03F4, "utf-7" },
+ { 0x03F5, "utf-16be" },
+ { 0x03F6, "utf-16le" },
+ { 0x03F7, "utf-16" },
+ { 0x07D0, "iso-8859-1-windows-3.0-latin-1" },
+ { 0x07D1, "iso-8859-1-windows-3.1-latin-1" },
+ { 0x07D2, "iso-8859-2-windows-latin-2" },
+ { 0x07D3, "iso-8859-9-windows-latin-5" },
+ { 0x07D4, "hp-roman8" },
+ { 0x07D5, "adobe-standard-encoding" },
+ { 0x07D6, "ventura-us" },
+ { 0x07D7, "ventura-international" },
+ { 0x07D8, "dec-mcs" },
+ { 0x07D9, "ibm850" },
+ { 0x07DA, "ibm852" },
+ { 0x07DB, "ibm437" },
+ { 0x07DC, "pc8-danish-norwegian" },
+ { 0x07DD, "ibm862" },
+ { 0x07DE, "pc8-turkish" },
+ { 0x07DF, "ibm-symbols" },
+ { 0x07E0, "ibm-thai" },
+ { 0x07E1, "hp-legal" },
+ { 0x07E2, "hp-pi-font" },
+ { 0x07E3, "hp-math8" },
+ { 0x07E4, "adobe-symbol-encoding" },
+ { 0x07E5, "hp-desktop" },
+ { 0x07E6, "ventura-math" },
+ { 0x07E7, "microsoft-publishing" },
+ { 0x07E8, "windows-31j" },
+ { 0x07E9, "gb2312" },
+ { 0x07EA, "big5" },
+ { 0x07EB, "macintosh" },
+ { 0x07EC, "ibm037" },
+ { 0x07ED, "ibm038" },
+ { 0x07EE, "ibm273" },
+ { 0x07EF, "ibm274" },
+ { 0x07F0, "ibm275" },
+ { 0x07F1, "ibm277" },
+ { 0x07F2, "ibm278" },
+ { 0x07F3, "ibm280" },
+ { 0x07F4, "ibm281" },
+ { 0x07F5, "ibm284" },
+ { 0x07F6, "ibm285" },
+ { 0x07F7, "ibm290" },
+ { 0x07F8, "ibm297" },
+ { 0x07F9, "ibm420" },
+ { 0x07FA, "ibm423" },
+ { 0x07FB, "ibm424" },
+ { 0x07FC, "ibm500" },
+ { 0x07FD, "ibm851" },
+ { 0x07FE, "ibm855" },
+ { 0x07FF, "ibm857" },
+ { 0x0800, "ibm860" },
+ { 0x0801, "ibm861" },
+ { 0x0802, "ibm863" },
+ { 0x0803, "ibm864" },
+ { 0x0804, "ibm865" },
+ { 0x0805, "ibm868" },
+ { 0x0806, "ibm869" },
+ { 0x0807, "ibm870" },
+ { 0x0808, "ibm871" },
+ { 0x0809, "ibm880" },
+ { 0x080A, "ibm891" },
+ { 0x080B, "ibm903" },
+ { 0x080C, "ibm904" },
+ { 0x080D, "ibm905" },
+ { 0x080E, "ibm918" },
+ { 0x080F, "ibm1026" },
+ { 0x0810, "ebcdic-at-de" },
+ { 0x0811, "ebcdic-at-de-a" },
+ { 0x0812, "ebcdic-ca-fr" },
+ { 0x0813, "ebcdic-dk-no" },
+ { 0x0814, "ebcdic-dk-no-a" },
+ { 0x0815, "ebcdic-fi-se" },
+ { 0x0816, "ebcdic-fi-se-a" },
+ { 0x0817, "ebcdic-fr" },
+ { 0x0818, "ebcdic-it" },
+ { 0x0819, "ebcdic-pt" },
+ { 0x081A, "ebcdic-es" },
+ { 0x081B, "ebcdic-es-a" },
+ { 0x081C, "ebcdic-es-s" },
+ { 0x081D, "ebcdic-uk" },
+ { 0x081E, "ebcdic-us" },
+ { 0x081F, "unknown-8bit" },
+ { 0x0820, "mnemonic" },
+ { 0x0821, "mnem" },
+ { 0x0822, "viscii" },
+ { 0x0823, "viqr" },
+ { 0x0824, "koi8-r" },
+ { 0x0825, "hz-gb-2312" },
+ { 0x0826, "ibm866" },
+ { 0x0827, "ibm775" },
+ { 0x0828, "koi8-u" },
+ { 0x0829, "ibm00858" },
+ { 0x082A, "ibm00924" },
+ { 0x082B, "ibm01140" },
+ { 0x082C, "ibm01141" },
+ { 0x082D, "ibm01142" },
+ { 0x082E, "ibm01143" },
+ { 0x082F, "ibm01144" },
+ { 0x0830, "ibm01145" },
+ { 0x0831, "ibm01146" },
+ { 0x0832, "ibm01147" },
+ { 0x0833, "ibm01148" },
+ { 0x0834, "ibm01149" },
+ { 0x0835, "big5-hkscs" },
+ { 0x08CA, "windows-1250" },
+ { 0x08CB, "windows-1251" },
+ { 0x08CC, "windows-1252" },
+ { 0x08CD, "windows-1253" },
+ { 0x08CE, "windows-1254" },
+ { 0x08CF, "windows-1255" },
+ { 0x08D0, "windows-1256" },
+ { 0x08D1, "windows-1257" },
+ { 0x08D2, "windows-1258" },
+ { 0x08D3, "tis-620" },
+ { 0x0000, NULL }
+};
diff --git a/epan/dissectors/packet-wap.h b/epan/dissectors/packet-wap.h
new file mode 100644
index 0000000000..a28cdbf984
--- /dev/null
+++ b/epan/dissectors/packet-wap.h
@@ -0,0 +1,100 @@
+/* packet-wap.h
+ *
+ * Declarations for WAP packet disassembly
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * WAP dissector based on original work by Ben Fowler
+ * Updated by Neil Hunter <neil.hunter@energis-squared.com>
+ * WTLS support by Alexandre P. Ferreira (Splice IP)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_WAP_H__
+#define __PACKET_WAP_H__
+
+#include <glib.h>
+#include <epan/packet.h>
+
+/* Port Numbers as per IANA */
+/* < URL:http://www.iana.org/assignments/port-numbers/ > */
+#define UDP_PORT_WSP 9200 /* wap-wsp */
+#define UDP_PORT_WTP_WSP 9201 /* wap-wsp-wtp */
+#define UDP_PORT_WTLS_WSP 9202 /* wap-wsp-s */
+#define UDP_PORT_WTLS_WTP_WSP 9203 /* wap-wsp-wtp-s */
+#define UDP_PORT_WSP_PUSH 2948 /* wap-wsp */
+#define UDP_PORT_WTLS_WSP_PUSH 2949 /* wap-wsp-s */
+
+/*
+ * Note:
+ * There are four dissectors for the WAP protocol:
+ * WTLS
+ * WTP
+ * WSP
+ * WMLC
+ * Which of these are necessary is determined by the port number above.
+ * I.e. port 9200 (wap-wsp) indicates WSP data and possibly WMLC (depending on
+ * the WSP PDU).
+ * Port 9203 (wap-wsp-wtp-s), on the other hand, has WTLS, WTP, WSP and
+ * possibly WMLC data in that order in the packet.
+ *
+ * Therefore the dissectors are chained as follows:
+ *
+ * Port Dissectors
+ * 9200 WSP -> WMLC
+ * 9201 WTP -> WSP -> WMLC
+ * 9202 WTLS -> WSP -> WMLC
+ * 9203 WTLS -> WTP -> WSP -> WMLC
+ *
+ * 2948 WSP -> WMLC (Push)
+ * 2949 WTLS -> WSP -> WMLC (Push)
+ *
+ * At present, only the unencrypted parts of WTLS can be analysed. Therefore
+ * the WTP and WSP dissectors are not called.
+ */
+
+#define HF_EMPTY ( -1 )
+#define ETT_EMPTY ( -1 )
+
+enum
+{
+ bo_big_endian = 0,
+ bo_little_endian = 1
+};
+
+/* Utility function for reading Uintvar encoded values */
+guint tvb_get_guintvar (tvbuff_t *, guint , guint *);
+
+/* Character set encoding */
+extern const value_string vals_character_sets[];
+
+/*
+ * Misc TODO:
+ *
+ * WMLC Dissector
+ * Check Protocol display
+ * Check Protocol information display
+ * Check CONNECT/CONNECT REPLY headers
+ * Check add_headers code
+ * Check Content-Length code
+ *
+ */
+
+#endif /* packet-wap.h */
diff --git a/epan/dissectors/packet-wbxml.c b/epan/dissectors/packet-wbxml.c
new file mode 100644
index 0000000000..2ebba21fe4
--- /dev/null
+++ b/epan/dissectors/packet-wbxml.c
@@ -0,0 +1,6731 @@
+/* packet-wbxml.c
+ *
+ * Routines for WAP Binary XML dissection
+ * Copyright 2003, 2004, Olivier Biot.
+ *
+ * $Id$
+ *
+ * Refer to the AUTHORS file or the AUTHORS section in the man page
+ * for contacting the author(s) of this file.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * WAP Binary XML decoding functionality provided by Olivier Biot.
+ *
+ * The WAP specifications used to be found at the WAP Forum:
+ * <http://www.wapforum.org/what/Technical.htm>
+ * But now the correct link is at the Open Mobile Alliance:
+ * <http://www.openmobilealliance.org/tech/affiliates/wap/wapindex.html>
+ * Media types defined by OMA affiliates will have their standards at:
+ * <http://www.openmobilealliance.org/tech/affiliates/index.html>
+ * <http://www.openmobilealliance.org/release_program/index.html>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Edit this file with 4-space tabulation */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/packet.h>
+
+#include "prefs.h"
+
+/* We need the function tvb_get_guintvar() */
+#include "packet-wap.h"
+
+/* General-purpose debug logger.
+ * Requires double parentheses because of variable arguments of printf().
+ *
+ * Enable debug logging for WBXML by defining AM_FLAGS
+ * so that it contains "-DDEBUG_wbxml"
+ */
+#ifdef DEBUG_wbxml
+#define DebugLog(x) \
+ printf("%s:%u: ", __FILE__, __LINE__); \
+ printf x; \
+ fflush(stdout)
+#else
+#define DebugLog(x) ;
+#endif
+
+/* The code in this source file dissects the WAP Binary XML content,
+ * and if possible renders it. WBXML mappings are defined in the
+ * "wbxml_decoding" structure.
+ *
+ * NOTES:
+ *
+ * - Some WBXML content is *not* backwards compatible across minor versions.
+ * This painful remark is true for:
+ * o WMLC 1.0 with respect to later WMLC 1.x
+ * o All WV-CSP versions (never backwards compatible)
+ * The only way of correctly rendering the WBXML is to let the end-user
+ * choose from the possible renderings. This only applies to the case when
+ * the WBXML DocType is not included in the WBXML header (unknown/missing).
+ *
+ * - Some WBXML content uses EXT_T_* in a non-tableref manner. This is the
+ * case with WV-CSP 1.1 and up, where the index points to a value_string
+ * containing WV-CSP specific token values. This is allowed as it is not
+ * explicitly forbidden in the WBXML specifications. Hence the global token
+ * map for content must also contain a function pointer if no tableref
+ * string is used.
+ *
+ * - Code page switches apply until a new code page switch. In the WBXML/1.x
+ * ABNF notation, it can be proven that the switch_page can only precede
+ * the following tokens:
+ * o stag : TAG | LITERAL | LITERAL_A | LITERAL_C | LITERAL_AC
+ * o attr : ATTRSTART | ATTRVALUE
+ * o extension : EXT_I | EXT_T | EXT
+ * Code page switches are displayed in a separate column.
+ *
+ * - The WBXML spec states that code pages are static to both the tag and the
+ * attribute state parser. A SWITCH_PAGE within a state switches the code
+ * page of the active state only. Note that code page 255 is reserved for
+ * application-specific (read: testing) purposes.
+ *
+ * - In order to render the XML content, recursion is inevitable at some
+ * point (when a tag with content occurs in the content of a tag with
+ * content). The code will however not recurse if this is not strictly
+ * required (e.g., tag without content in the content of a tag with
+ * content).
+ *
+ * - I found it useful to display the XML nesting level as a first "column",
+ * followed by the abbreviated WBXML token interpretation. When a mapping
+ * is defined for the parsed WBXML content, then the XML rendering is
+ * displayed with appropriate indentation (maximum nesting level = 255,
+ * after which the nesting and level will safely roll-over to 0).
+ *
+ * - The WAP Forum defines the order of precedence for finding out the
+ * WBXML content type (same rules for charset) as follows:
+ * 1. Look in the Content-Type WSP header
+ * 2. Look in the WBXML header
+ * Currently there is no means of using content type parameters:
+ * o Type=<some_type>
+ * o Charset=<charset_of_the_content>
+ * So it is possible some WBXML content types are incorrectly parsed.
+ * This would only be the case when the content type declaration in the
+ * WSP Content-Type header would be different (or would have parameters
+ * which are relevant to the WBXML decoding) from the content type
+ * identifier specified in the WBXML header. This has to do with the
+ * decoding of terminated text strings in the different character codings.
+ * TODO: investigate this and provide correct decoding at all times.
+ */
+
+typedef struct _value_valuestring {
+ guint32 value;
+ const value_string *valstrptr;
+} value_valuestring;
+
+/* Tries to match val against each element in the value_value_string array vvs.
+ * Returns the associated value_string ptr on a match, or NULL on failure. */
+static const value_string *
+val_to_valstr(guint32 val, const value_valuestring *vvs)
+{
+ gint i = 0;
+
+ while (vvs[i].valstrptr) {
+ if (vvs[i].value == val)
+ return(vvs[i].valstrptr);
+ i++;
+ }
+
+ return(NULL);
+}
+
+/* Note on Token mapping
+ * ---------------------
+ *
+ * The WBXML dissector will try mapping the token decoding to their textual
+ * representation if the media type has a defined token representation. The
+ * following logic applies:
+ *
+ * a. Inspect the WBXML PublicID
+ * This means that I need a list { PublicID, decoding }
+ *
+ * b. Inspect the literal media type
+ * This requires a list { "media/type", discriminator, { decodings } }
+ *
+ * b.1. Use a discriminator to choose an appropriate token mapping;
+ * The disciminator needs a small number of bytes from the data tvbuff_t.
+ *
+ * else
+ * b.2. Provide a list to the end-user with all possible token mappings.
+ *
+ * c. If none match then only show the tokens without mapping.
+ *
+ */
+
+/* ext_t_func_ptr is a pointer to a function handling the EXT_T_i tokens:
+ *
+ * char * ext_t_function(tvbuff_t *tvb, guint32 value, guint32 strtbl);
+ */
+typedef char * (* ext_t_func_ptr)(tvbuff_t *, guint32, guint32);
+
+/* Note on parsing of OPAQUE data
+ * ------------------------------
+ *
+ * The WBXML encapsulation allows the insertion of opaque binary data in the
+ * WBXML body. Although this opaque data has no meaning in WBXML, the media
+ * type itself may define compact encoding of given input by encoding it in
+ * such a OPAQUE blob of bytes.
+ *
+ * The WBXML dissector now supports dissection of OPAQUE data by means of a
+ * mapping function that will operate based on the token (well-known or literal)
+ * and the active code page.
+ *
+ * For well-known tokens the simplest approach is to use a switch for the code
+ * pages and another switch for the relevant tokens within a code page.
+ *
+ * For literal tokens (tags and attribute names), the only approach is a string
+ * comparison with the literal representation of the given tag or attribute
+ * name.
+ *
+ * opaque_token_func_ptr is a pointer to a function handling OPAQUE values
+ * for binary tokens representing tags or attribute starts.
+ * opaque_literal_func_ptr is a pointer to a function handling OPAQUE values
+ * for literal tokens representing tags or attribute starts.
+ *
+ * The length field of the OPAQUE entry starts at offset (not offset + 1).
+ *
+ * The length of the processed OPAQUE value is returned by reference.
+ *
+ * char * opaque_token_function(tvbuff_t *tvb, guint32 offset,
+ * guint8 token, guint8 codepage, guint32 *length);
+ * char * opaque_literal_function(tvbuff_t *tvb, guint32 offset,
+ * const char *token, guint8 codepage, guint32 *length);
+ */
+typedef char * (* opaque_token_func_ptr)(tvbuff_t *, guint32, guint8, guint8, guint32 *);
+typedef char * (* opaque_literal_func_ptr)(tvbuff_t *, guint32, const char *, guint8, guint32 *);
+
+char *
+default_opaque_binary_tag(tvbuff_t *tvb, guint32 offset,
+ guint8 token _U_, guint8 codepage _U_, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = g_strdup_printf("(%d bytes of opaque data)", data_len);
+ *length += data_len;
+ return str;
+}
+
+char *
+default_opaque_literal_tag(tvbuff_t *tvb, guint32 offset,
+ const char *token _U_, guint8 codepage _U_, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = g_strdup_printf("(%d bytes of opaque data)", data_len);
+ *length += data_len;
+ return str;
+}
+
+char *
+default_opaque_binary_attr(tvbuff_t *tvb, guint32 offset,
+ guint8 token _U_, guint8 codepage _U_, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = g_strdup_printf("(%d bytes of opaque data)", data_len);
+ *length += data_len;
+ return str;
+}
+
+char *
+default_opaque_literal_attr(tvbuff_t *tvb, guint32 offset,
+ const char *token _U_, guint8 codepage _U_, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = g_strdup_printf("(%d bytes of opaque data)", data_len);
+ *length += data_len;
+ return str;
+}
+
+/* Render a hex %dateTime encoded timestamp as a string.
+ * 0x20011231123456 becomes "2001-12-31T12:34:56Z" */
+char *
+date_time_from_opaque(tvbuff_t *tvb, guint32 offset, guint32 data_len)
+{
+ char *str;
+
+ switch (data_len) {
+ case 4: /* YYYY-MM-DD[T00:00:00Z] */
+ str = g_strdup_printf("%%DateTime: "
+ "%02x%02x-%02x-%02xT00:00:00Z",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset + 1),
+ tvb_get_guint8(tvb, offset + 2),
+ tvb_get_guint8(tvb, offset + 3));
+ break;
+ case 5: /* YYYY-MM-DDThh[:00:00Z] */
+ str = g_strdup_printf("%%DateTime: "
+ "%02x%02x-%02x-%02xT%02x:00:00Z",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset + 1),
+ tvb_get_guint8(tvb, offset + 2),
+ tvb_get_guint8(tvb, offset + 3),
+ tvb_get_guint8(tvb, offset + 4));
+ break;
+ case 6: /* YYYY-MM-DDThh:mm[:00Z] */
+ str = g_strdup_printf("%%DateTime: "
+ "%02x%02x-%02x-%02xT%02x:%02x:00Z",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset + 1),
+ tvb_get_guint8(tvb, offset + 2),
+ tvb_get_guint8(tvb, offset + 3),
+ tvb_get_guint8(tvb, offset + 4),
+ tvb_get_guint8(tvb, offset + 5));
+ break;
+ case 7: /* YYYY-MM-DDThh:mm[:00Z] */
+ str = g_strdup_printf("%%DateTime: "
+ "%02x%02x-%02x-%02xT%02x:%02x:%02xZ",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset + 1),
+ tvb_get_guint8(tvb, offset + 2),
+ tvb_get_guint8(tvb, offset + 3),
+ tvb_get_guint8(tvb, offset + 4),
+ tvb_get_guint8(tvb, offset + 5),
+ tvb_get_guint8(tvb, offset + 6));
+ break;
+ default:
+ str = g_strdup_printf("<Error: invalid binary %%DateTime "
+ "(%d bytes of opaque data)>", data_len);
+ break;
+ }
+
+ return str;
+}
+
+/* Is ALWAYS 6 bytes long:
+ * 00YY YYYY YYYY YYMM MMDD DDDh hhhh mmmm mmss ssss ZZZZ ZZZZ */
+char *
+wv_datetime_from_opaque(tvbuff_t *tvb, guint32 offset, guint32 data_len)
+{
+ char *str;
+ guint16 year;
+ guint8 month, day, hour, minute, second, timezone;
+ guint8 peek;
+
+ if (data_len == 6) { /* Valid */
+
+ /* Octet 1: 00YY YYYY */
+ year = tvb_get_guint8(tvb, offset) & 0x3F; /* ..11 1111 */
+ year <<=6;
+ /* Octet 2: YYYY YYMM */
+ peek = tvb_get_guint8(tvb, offset + 1);
+ year += (peek >> 2); /* 1111 11.. */
+ month = (peek & 0x03) << 2; /* .... ..11 */
+ /* Octet 3: MMDD DDDh */
+ peek = tvb_get_guint8(tvb, offset + 2);
+ month += (peek >> 6); /* 11.. .... */
+ day = (peek & 0x3E) >> 1; /* ..11 111. */
+ hour = (peek & 0x01) << 4; /* .... ...1 */
+ /* Octet 4: hhhh mmmm */
+ peek = tvb_get_guint8(tvb, offset + 3);
+ hour += (peek >> 4);
+ minute = (peek & 0x0F) << 2; /* .... 1111 */
+ /* Octet 5: mmss ssss */
+ peek = tvb_get_guint8(tvb, offset + 4);
+ minute += (peek >> 6); /* 11.. .... */
+ second = peek & 0x3F; /* ..11 1111 */
+ /* octet 6: ZZZZZZZZ */
+ timezone = tvb_get_guint8(tvb, offset + 5);
+ /* Now construct the string */
+ str = g_strdup_printf("WV-CSP DateTime: "
+ "%04d-%02d-%02dT%02d:%02d:%02d%c",
+ year, month, day, hour, minute, second, timezone);
+ } else { /* Invalid length for a WV-CSP DateTime tag value */
+ str = g_strdup_printf("<Error: invalid binary WV-CSP DateTime value "
+ "(%d bytes of opaque data)>", data_len);
+ }
+ return str;
+}
+
+/* WV-CSP integer values for tag content is encoded in a fashion similar
+ * to a Long-Integer in WSP */
+char *
+wv_integer_from_opaque(tvbuff_t *tvb, guint32 offset, guint32 data_len)
+{
+ char *str;
+
+ switch (data_len) {
+ case 1:
+ str = g_strdup_printf("WV-CSP Integer: %d",
+ tvb_get_guint8(tvb, offset));
+ break;
+ case 2:
+ str = g_strdup_printf("WV-CSP Integer: %d",
+ tvb_get_ntohs(tvb, offset));
+ break;
+ case 3:
+ str = g_strdup_printf("WV-CSP Integer: %d",
+ tvb_get_ntoh24(tvb, offset));
+ break;
+ case 4:
+ str = g_strdup_printf("WV-CSP Integer: %d",
+ tvb_get_ntohl(tvb, offset));
+ break;
+ default:
+ str = g_strdup_printf("<Error: invalid binary WV-CSP Integer value "
+ "(%d bytes of opaque data)>", data_len);
+ break;
+ }
+
+ return str;
+}
+
+char *
+wv_csp10_opaque_literal_tag(tvbuff_t *tvb, guint32 offset,
+ const char *token, guint8 codepage _U_, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ if ( (strcmp(token, "Code") == 0)
+ || (strcmp(token, "ContentSize") == 0)
+ || (strcmp(token, "MessageCount") == 0)
+ || (strcmp(token, "Validity") == 0)
+ || (strcmp(token, "KeepAliveTime") == 0)
+ || (strcmp(token, "TimeToLive") == 0)
+ || (strcmp(token, "AcceptedContentLength") == 0)
+ || (strcmp(token, "MultiTrans") == 0)
+ || (strcmp(token, "ParserSize") == 0)
+ || (strcmp(token, "ServerPollMin") == 0)
+ || (strcmp(token, "TCPAddress") == 0)
+ || (strcmp(token, "TCPPort") == 0)
+ || (strcmp(token, "UDPPort") == 0) )
+ {
+ str = wv_integer_from_opaque(tvb, offset + *length, data_len);
+ }
+ else if (strcmp(token, "DateTime") == 0)
+ {
+ str = wv_datetime_from_opaque(tvb, offset + *length, data_len);
+ }
+
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+ return str;
+}
+
+char *
+wv_csp10_opaque_binary_tag(tvbuff_t *tvb, guint32 offset,
+ guint8 token, guint8 codepage, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ switch (codepage) {
+ case 0: /* Common code page */
+ switch (token) {
+ case 0x0B: /* <Code> */
+ case 0x0F: /* <ContentSize> */
+ case 0x1A: /* <MessageCount> */
+ case 0x3C: /* <Validity> */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ case 0x11: /* <DateTime> */
+ str = wv_datetime_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 1: /* Access code page */
+ switch (token) {
+ case 0x1C: /* <KeepAliveTime> */
+ case 0x32: /* <TimeToLive> */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ case 3: /* Client capability code page */
+ switch (token) {
+ case 0x06: /* <AcceptedContentLength> */
+ case 0x0C: /* <MultiTrans> */
+ case 0x0D: /* <ParserSize> */
+ case 0x0E: /* <ServerPollMin> */
+ case 0x11: /* <TCPAddress> */
+ case 0x12: /* <TCPPort> */
+ case 0x13: /* <UDPPort> */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+
+ return str;
+}
+
+char *
+wv_csp11_opaque_literal_tag(tvbuff_t *tvb, guint32 offset,
+ const char *token, guint8 codepage _U_, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ if ( (strcmp(token, "Code") == 0)
+ || (strcmp(token, "ContentSize") == 0)
+ || (strcmp(token, "MessageCount") == 0)
+ || (strcmp(token, "Validity") == 0)
+ || (strcmp(token, "KeepAliveTime") == 0)
+ || (strcmp(token, "TimeToLive") == 0)
+ || (strcmp(token, "AcceptedContentLength") == 0)
+ || (strcmp(token, "MultiTrans") == 0)
+ || (strcmp(token, "ParserSize") == 0)
+ || (strcmp(token, "ServerPollMin") == 0)
+ || (strcmp(token, "TCPPort") == 0)
+ || (strcmp(token, "UDPPort") == 0) )
+ {
+ str = wv_integer_from_opaque(tvb, offset + *length, data_len);
+ }
+ else
+ if ( (strcmp(token, "DateTime") == 0)
+ || (strcmp(token, "DeliveryTime") == 0) )
+ {
+ str = wv_datetime_from_opaque(tvb, offset + *length, data_len);
+ }
+
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+ return str;
+}
+
+char *
+wv_csp11_opaque_binary_tag(tvbuff_t *tvb, guint32 offset,
+ guint8 token, guint8 codepage, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ switch (codepage) {
+ case 0: /* Common code page */
+ switch (token) {
+ case 0x0B: /* <Code> */
+ case 0x0F: /* <ContentSize> */
+ case 0x1A: /* <MessageCount> */
+ case 0x3C: /* <Validity> */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ case 0x11: /* <DateTime> */
+ str = wv_datetime_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 1: /* Access code page */
+ switch (token) {
+ case 0x1C: /* <KeepAliveTime> */
+ case 0x32: /* <TimeToLive> */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ case 3: /* Client capability code page */
+ switch (token) {
+ case 0x06: /* <AcceptedContentLength> */
+ case 0x0C: /* <MultiTrans> */
+ case 0x0D: /* <ParserSize> */
+ case 0x0E: /* <ServerPollMin> */
+ case 0x12: /* <TCPPort> */
+ case 0x13: /* <UDPPort> */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 6: /* Messaging code page */
+ switch (token) {
+ case 0x1A: /* <DeliveryTime> - not in 1.0 */
+ str = wv_datetime_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+
+ return str;
+}
+
+char *
+wv_csp12_opaque_literal_tag(tvbuff_t *tvb, guint32 offset,
+ const char *token, guint8 codepage _U_, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ if ( (strcmp(token, "Code") == 0)
+ || (strcmp(token, "ContentSize") == 0)
+ || (strcmp(token, "MessageCount") == 0)
+ || (strcmp(token, "Validity") == 0)
+ || (strcmp(token, "KeepAliveTime") == 0)
+ || (strcmp(token, "TimeToLive") == 0)
+ || (strcmp(token, "AcceptedContentLength") == 0)
+ || (strcmp(token, "MultiTrans") == 0)
+ || (strcmp(token, "ParserSize") == 0)
+ || (strcmp(token, "ServerPollMin") == 0)
+ || (strcmp(token, "TCPPort") == 0)
+ || (strcmp(token, "UDPPort") == 0)
+ || (strcmp(token, "HistoryPeriod") == 0)
+ || (strcmp(token, "MaxWatcherList") == 0) )
+ {
+ str = wv_integer_from_opaque(tvb, offset + *length, data_len);
+ }
+ else
+ if ( (strcmp(token, "DateTime") == 0)
+ || (strcmp(token, "DeliveryTime") == 0) )
+ {
+ str = wv_datetime_from_opaque(tvb, offset + *length, data_len);
+ }
+
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+ return str;
+}
+
+char *
+wv_csp12_opaque_binary_tag(tvbuff_t *tvb, guint32 offset,
+ guint8 token, guint8 codepage, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ switch (codepage) {
+ case 0: /* Common code page */
+ switch (token) {
+ case 0x0B: /* <Code> */
+ case 0x0F: /* <ContentSize> */
+ case 0x1A: /* <MessageCount> */
+ case 0x3C: /* <Validity> */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ case 0x11: /* <DateTime> */
+ str = wv_datetime_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 1: /* Access code page */
+ switch (token) {
+ case 0x1C: /* <KeepAliveTime> */
+ case 0x32: /* <TimeToLive> */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ case 3: /* Client capability code page */
+ switch (token) {
+ case 0x06: /* <AcceptedContentLength> */
+ case 0x0C: /* <MultiTrans> */
+ case 0x0D: /* <ParserSize> */
+ case 0x0E: /* <ServerPollMin> */
+ case 0x12: /* <TCPPort> */
+ case 0x13: /* <UDPPort> */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 6: /* Messaging code page */
+ switch (token) {
+ case 0x1A: /* <DeliveryTime> - not in 1.0 */
+ str = wv_datetime_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 9: /* Common code page (continued) */
+ switch (token) {
+ case 0x08: /* <HistoryPeriod> - 1.2 only */
+ case 0x0A: /* <MaxWatcherList> - 1.2 only */
+ str = wv_integer_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+
+ return str;
+}
+
+char *
+sic10_opaque_literal_attr(tvbuff_t *tvb, guint32 offset,
+ const char *token, guint8 codepage _U_, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ if ( (strcmp(token, "created") == 0)
+ || (strcmp(token, "si-expires") == 0) )
+ {
+ str = date_time_from_opaque(tvb, offset + *length, data_len);
+ }
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+
+ return str;
+}
+
+char *
+sic10_opaque_binary_attr(tvbuff_t *tvb, guint32 offset,
+ guint8 token, guint8 codepage, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ switch (codepage) {
+ case 0: /* Only valid codepage for SI */
+ switch (token) {
+ case 0x0A: /* created= */
+ case 0x10: /* si-expires= */
+ str = date_time_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+
+ return str;
+}
+
+char *
+emnc10_opaque_literal_attr(tvbuff_t *tvb, guint32 offset,
+ const char *token, guint8 codepage _U_, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ if ( (strcmp(token, "timestamp") == 0) )
+ {
+ str = date_time_from_opaque(tvb, offset + *length, data_len);
+ }
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+
+ return str;
+}
+
+char *
+emnc10_opaque_binary_attr(tvbuff_t *tvb, guint32 offset,
+ guint8 token, guint8 codepage, guint32 *length)
+{
+ guint32 data_len = tvb_get_guintvar(tvb, offset, length);
+ char *str = NULL;
+
+ switch (codepage) {
+ case 0: /* Only valid codepage for EMN */
+ switch (token) {
+ case 0x05: /* timestamp= */
+ str = date_time_from_opaque(tvb,
+ offset + *length, data_len);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (str == NULL) { /* Error, or not parsed */
+ str = g_strdup_printf("(%d bytes of unparsed opaque data)", data_len);
+ }
+ *length += data_len;
+
+ return str;
+}
+
+typedef struct _wbxml_decoding {
+ const char *name;
+ const char *abbrev;
+ ext_t_func_ptr ext_t[3];
+ opaque_token_func_ptr opaque_binary_tag;
+ opaque_literal_func_ptr opaque_literal_tag;
+ opaque_token_func_ptr opaque_binary_attr;
+ opaque_literal_func_ptr opaque_literal_attr;
+ const value_valuestring *global;
+ const value_valuestring *tags;
+ const value_valuestring *attrStart;
+ const value_valuestring *attrValue;
+} wbxml_decoding;
+
+/* Define a pointer to a discriminator function taking a tvb and the start
+ * offset of the WBXML tokens in the body as arguments.
+ */
+typedef const wbxml_decoding * (* discriminator_func_ptr)(tvbuff_t *, guint32);
+
+/* For the decoding lists based on the known WBXML public ID */
+typedef struct _wbxml_integer_list {
+ guint32 public_id;
+ const wbxml_decoding *map;
+} wbxml_integer_list;
+
+/* For the decoding lists on the literal content type */
+typedef struct _wbxml_literal_list {
+ const char *content_type;
+ discriminator_func_ptr discriminator; /* TODO */
+ const wbxml_decoding *map;
+} wbxml_literal_list;
+
+/************************** Variable declarations **************************/
+
+
+/* Initialize the protocol and registered fields */
+static int proto_wbxml = -1;
+static int hf_wbxml_version = -1;
+static int hf_wbxml_public_id_known = -1;
+static int hf_wbxml_public_id_literal = -1;
+static int hf_wbxml_charset = -1;
+
+/* Initialize the subtree pointers */
+static gint ett_wbxml = -1;
+static gint ett_wbxml_str_tbl = -1;
+static gint ett_wbxml_content = -1;
+
+/* WBXML Preferences */
+static gboolean skip_wbxml_token_mapping = FALSE;
+static gboolean disable_wbxml_token_parsing = FALSE;
+
+
+/**************** WBXML related declarations and definitions ****************/
+
+
+/* WBXML public ID mappings. For an up-to-date list, see
+ * http://www.openmobilealliance.org/tech/omna/ */
+static const value_string vals_wbxml_public_ids[] = {
+ /* 0x00 = literal public identifier */
+ { 0x01, "Unknown / missing Public Identifier" },
+ { 0x02, "-//WAPFORUM//DTD WML 1.0//EN (WML 1.0)" },
+ { 0x03, "-//WAPFORUM//DTD WTA 1.0//EN (WTA Event 1.0) - Deprecated" },
+ { 0x04, "-//WAPFORUM//DTD WML 1.1//EN (WML 1.1)" },
+ { 0x05, "-//WAPFORUM//DTD SI 1.0//EN (Service Indication 1.0)" },
+ { 0x06, "-//WAPFORUM//DTD SL 1.0//EN (Service Loading 1.0)" },
+ { 0x07, "-//WAPFORUM//DTD CO 1.0//EN (Cache Operation 1.0)" },
+ { 0x08, "-//WAPFORUM//DTD CHANNEL 1.1//EN (Channel 1.1)" },
+ { 0x09, "-//WAPFORUM//DTD WML 1.2//EN (WML 1.2)" },
+ { 0x0a, "-//WAPFORUM//DTD WML 1.3//EN (WML 1.3)" },
+ { 0x0b, "-//WAPFORUM//DTD PROV 1.0//EN (Provisioning 1.0)" },
+ { 0x0c, "-//WAPFORUM//DTD WTA-WML 1.2//EN (WTA-WML 1.2)" },
+ { 0x0d, "-//WAPFORUM//DTD EMN 1.0//EN (Email Notification 1.0)" },
+ { 0x0e, "-//WAPFORUM//DTD DRMREL 1.0//EN (DRMREL 1.0)" },
+ { 0x0f, "-//WIRELESSVILLAGE//DTD CSP 1.0//EN"
+ " (Wireless Village Client-Server Protocol DTD v1.0)" },
+ { 0x10, "-//WIRELESSVILLAGE//DTD CSP 1.1//EN"
+ " (Wireless Village Client-Server Protocol DTD v1.1)" },
+
+ /* Registered values - www.syncml.org */
+ { 0x0fd1, "-//SYNCML//DTD SyncML 1.0//EN (SyncML 1.0)" },
+ { 0x0fd3, "-//SYNCML//DTD SyncML 1.1//EN (SyncML 1.1)" },
+
+ /* Registered values - www.wapforum.org/wina/ */
+ { 0x1100, "-//PHONE.COM//DTD ALERT 1.0//EN" },
+ { 0x1101, "-//PHONE.COM//DTD CACHE-OPERATION 1.0//EN" },
+ { 0x1102, "-//PHONE.COM//DTD SIGNAL 1.0//EN" },
+ { 0x1103, "-//PHONE.COM//DTD LIST 1.0//EN" },
+ { 0x1104, "-//PHONE.COM//DTD LISTCMD 1.0//EN" },
+ { 0x1105, "-//PHONE.COM//DTD CHANNEL 1.0//EN" },
+ { 0x1106, "-//PHONE.COM//DTD MMC 1.0//EN" },
+ { 0x1107, "-//PHONE.COM//DTD BEARER-CHOICE 1.0//EN" },
+ { 0x1108, "-//PHONE.COM//DTD WML 1.1//EN (WML+ 1.1)" },
+ { 0x1109, "-//PHONE.COM//DTD CHANNEL 1.1//EN" },
+ { 0x110a, "-//PHONE.COM//DTD LIST 1.1//EN" },
+ { 0x110b, "-//PHONE.COM//DTD LISTCMD 1.1//EN" },
+ { 0x110c, "-//PHONE.COM//DTD MMC 1.1//EN" },
+ { 0x110d, "-//PHONE.COM//DTD WML 1.3//EN (WML+ 1.3)" },
+ { 0x110e, "-//PHONE.COM//DTD MMC 2.0//EN" },
+ /* 0x110F -- 0x11FF: unassigned */
+ { 0x1200, "-//3GPP2.COM//DTD IOTA 1.0//EN" },
+
+ { 0x00, NULL }
+};
+
+static const value_string vals_wbxml_versions[] = {
+ { 0x00, "1.0" }, /* WAP-104-WBXML */
+ { 0x01, "1.1" }, /* WAP-135-WBXML */
+ { 0x02, "1.2" }, /* WAP-154-WBXML */
+ { 0x03, "1.3" }, /* WAP-192-WBXML */
+
+ { 0x00, NULL }
+};
+
+/* WBXML 1.0 global tokens: WAP-104-WBXML
+ * Same token mapping as in vals_wbxml1x_global_tokens, but:
+ * { 0xC3, "RESERVED_2" }
+ */
+
+/* WBXML 1.x (x>0) global tokens: WAP-135-WBXML, WAP-154-WBXML, WAP-192-WBXML
+ */
+static const value_string vals_wbxml1x_global_tokens[] = {
+ { 0x00, "SWITCH_PAGE" },
+ { 0x01, "END" },
+ { 0x02, "ENTITY" },
+ { 0x03, "STR_I" },
+ { 0x04, "LITERAL" },
+
+ { 0x40, "EXT_I_0" },
+ { 0x41, "EXT_I_1" },
+ { 0x42, "EXT_I_2" },
+ { 0x43, "PI" },
+ { 0x44, "LITERAL_C" },
+
+ { 0x80, "EXT_T_0" },
+ { 0x81, "EXT_T_1" },
+ { 0x82, "EXT_T_2" },
+ { 0x83, "STR_T" },
+ { 0x84, "LITERAL_A" },
+
+ { 0xC0, "EXT_0" },
+ { 0xC1, "EXT_1" },
+ { 0xC2, "EXT_2" },
+ { 0xC3, "OPAQUE" },
+ { 0xC4, "LITERAL_AC" },
+
+ { 0x00, NULL }
+};
+
+
+
+
+
+/********************** WBXML token mapping definition **********************/
+
+/*
+ * NOTE: Please make sure the Attribute Start values all contain an equal sign
+ * even in cases where they do not contain the start of an Attribute
+ * Value.
+ */
+
+
+/* WML 1.0
+ *
+ * Wireless Markup Language
+ ***************************************/
+static char *
+ext_t_0_wml_10(tvbuff_t *tvb, guint32 value, guint32 str_tbl)
+{
+ gint str_len = tvb_strsize (tvb, str_tbl + value);
+ char *str = g_strdup_printf("Variable substitution - escaped: '%s'",
+ tvb_get_ptr(tvb, str_tbl + value, str_len));
+ return str;
+}
+
+static char *
+ext_t_1_wml_10(tvbuff_t *tvb, guint32 value, guint32 str_tbl)
+{
+ gint str_len = tvb_strsize (tvb, str_tbl + value);
+ char *str = g_strdup_printf("Variable substitution - unescaped: '%s'",
+ tvb_get_ptr(tvb, str_tbl + value, str_len));
+ return str;
+}
+
+static char *
+ext_t_2_wml_10(tvbuff_t *tvb, guint32 value, guint32 str_tbl)
+{
+ gint str_len = tvb_strsize (tvb, str_tbl + value);
+ char *str = g_strdup_printf("Variable substitution - no transformation: '%s'",
+ tvb_get_ptr(tvb, str_tbl + value, str_len));
+ return str;
+}
+/***** Global extension tokens *****/
+static const value_string wbxml_wmlc10_global_cp0[] = {
+ { 0x40, "Variable substitution - escaped" },
+ { 0x41, "Variable substitution - unescaped" },
+ { 0x42, "Variable substitution - no transformation" },
+ { 0x80, "Variable substitution - escaped" },
+ { 0x81, "Variable substitution - unescaped" },
+ { 0x82, "Variable substitution - no transformation" },
+ { 0xC0, "Reserved" },
+ { 0xC1, "Reserved" },
+ { 0xC2, "Reserved" },
+
+ { 0x00, NULL }
+};
+
+/***** Tag tokens *****/
+static const value_string wbxml_wmlc10_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ /* 0x05 -- 0x21 */
+ { 0x22, "A" },
+ { 0x23, "ACCESS" },
+ { 0x24, "B" },
+ { 0x25, "BIG" },
+ { 0x26, "BR" },
+ { 0x27, "CARD" },
+ { 0x28, "DO" },
+ { 0x29, "EM" },
+ { 0x2A, "FIELDSET" },
+ { 0x2B, "GO" },
+ { 0x2C, "HEAD" },
+ { 0x2D, "I" },
+ { 0x2E, "IMG" },
+ { 0x2F, "INPUT" },
+ { 0x30, "META" },
+ { 0x31, "NOOP" },
+ { 0x32, "PREV" },
+ { 0x33, "ONEVENT" },
+ { 0x34, "OPTGROUP" },
+ { 0x35, "OPTION" },
+ { 0x36, "REFRESH" },
+ { 0x37, "SELECT" },
+ { 0x38, "SMALL" },
+ { 0x39, "STRONG" },
+ { 0x3A, "TAB" },
+ { 0x3B, "TEMPLATE" },
+ { 0x3C, "TIMER" },
+ { 0x3D, "U" },
+ { 0x3E, "VAR" },
+ { 0x3F, "WML" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_wmlc10_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "ACCEPT-CHARSET=" },
+ { 0x06, "ALIGN='BOTTOM'" },
+ { 0x07, "ALIGN='CENTER'" },
+ { 0x08, "ALIGN='LEFT'" },
+ { 0x09, "ALIGN='MIDDLE'" },
+ { 0x0A, "ALIGN='RIGHT'" },
+ { 0x0B, "ALIGN='TOP'" },
+ { 0x0C, "ALT=" },
+ { 0x0D, "CONTENT=" },
+ { 0x0E, "DEFAULT=" },
+ { 0x0F, "DOMAIN=" },
+ { 0x10, "EMPTYOK='FALSE'" },
+ { 0x11, "EMPTYOK='TRUE'" },
+ { 0x12, "FORMAT=" },
+ { 0x13, "HEIGHT=" },
+ { 0x14, "HSPACE=" },
+ { 0x15, "IDEFAULT=" },
+ { 0x16, "IKEY=" },
+ { 0x17, "KEY=" },
+ { 0x18, "LABEL=" },
+ { 0x19, "LOCALSRC=" },
+ { 0x1A, "MAXLENGTH=" },
+ { 0x1B, "METHOD='GET'" },
+ { 0x1C, "METHOD='POST'" },
+ { 0x1D, "MODE='NOWRAP'" },
+ { 0x1E, "MODE='WRAP'" },
+ { 0x1F, "MULTIPLE='FALSE'" },
+ { 0x20, "MULTIPLE='TRUE'" },
+ { 0x21, "NAME=" },
+ { 0x22, "NEWCONTEXT='FALSE'" },
+ { 0x23, "NEWCONTEXT='TRUE'" },
+ { 0x24, "ONCLICK=" },
+ { 0x25, "ONENTERBACKWARD=" },
+ { 0x26, "ONENTERFORWARD=" },
+ { 0x27, "ONTIMER=" },
+ { 0x28, "OPTIONAL='FALSE'" },
+ { 0x29, "OPTIONAL='TRUE'" },
+ { 0x2A, "PATH=" },
+ { 0x2B, "POSTDATA=" },
+ { 0x2C, "PUBLIC='FALSE'" },
+ { 0x2D, "PUBLIC='TRUE'" },
+ { 0x2E, "SCHEME=" },
+ { 0x2F, "SENDREFERER='FALSE'" },
+ { 0x30, "SENDREFERER='TRUE'" },
+ { 0x31, "SIZE=" },
+ { 0x32, "SRC=" },
+ { 0x33, "STYLE='LIST'" },
+ { 0x34, "STYLE='SET'" },
+ { 0x35, "TABINDEX=" },
+ { 0x36, "TITLE=" },
+ { 0x37, "TYPE=" },
+ { 0x38, "TYPE='ACCEPT'" },
+ { 0x39, "TYPE='DELETE'" },
+ { 0x3A, "TYPE='HELP'" },
+ { 0x3B, "TYPE='PASSWORD'" },
+ { 0x3C, "TYPE='ONCLICK'" },
+ { 0x3D, "TYPE='ONENTERBACKWARD'" },
+ { 0x3E, "TYPE='ONENTERFORWARD'" },
+ { 0x3F, "TYPE='ONTIMER'" },
+ /* 0x40 -- 0x44 GLOBAL */
+ { 0x45, "TYPE='OPTIONS'" },
+ { 0x46, "TYPE='PREV'" },
+ { 0x47, "TYPE='RESET'" },
+ { 0x48, "TYPE='TEXT'" },
+ { 0x49, "TYPE='vnd.'" },
+ { 0x4A, "URL=" },
+ { 0x4B, "URL='http://'" },
+ { 0x4C, "URL='https://'" },
+ { 0x4D, "USER-AGENT=" },
+ { 0x4E, "VALUE=" },
+ { 0x4F, "VSPACE=" },
+ { 0x50, "WIDTH=" },
+ { 0x51, "xml:lang=" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+static const value_string wbxml_wmlc10_attrValue_cp0[] = {
+ /* 0x80 -- 0x84 GLOBAL */
+ { 0x85, "'.com/'" },
+ { 0x86, "'.edu/'" },
+ { 0x87, "'.net/'" },
+ { 0x88, "'.org/'" },
+ { 0x89, "'ACCEPT'" },
+ { 0x8A, "'BOTTOM'" },
+ { 0x8B, "'CLEAR'" },
+ { 0x8C, "'DELETE'" },
+ { 0x8D, "'HELP'" },
+ { 0x8E, "'http://'" },
+ { 0x8F, "'http://www.'" },
+ { 0x90, "'https://'" },
+ { 0x91, "'https://www.'" },
+ { 0x92, "'LIST'" },
+ { 0x93, "'MIDDLE'" },
+ { 0x94, "'NOWRAP'" },
+ { 0x95, "'ONCLICK'" },
+ { 0x96, "'ONENTERBACKWARD'" },
+ { 0x97, "'ONENTERFORWARD'" },
+ { 0x98, "'ONTIMER'" },
+ { 0x99, "'OPTIONS'" },
+ { 0x9A, "'PASSWORD'" },
+ { 0x9B, "'RESET'" },
+ { 0x9C, "'SET'" },
+ { 0x9D, "'TEXT'" },
+ { 0x9E, "'TOP'" },
+ { 0x9F, "'UNKNOWN'" },
+ { 0xA0, "'WRAP'" },
+ { 0xA1, "'www.'" },
+
+ { 0x00, NULL }
+};
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_wmlc10_global[] = {
+ { 0, wbxml_wmlc10_global_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc10_tags[] = {
+ { 0, wbxml_wmlc10_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc10_attrStart[] = {
+ { 0, wbxml_wmlc10_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc10_attrValue[] = {
+ { 0, wbxml_wmlc10_attrValue_cp0 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_wmlc_10 = {
+ "Wireless Markup Language 1.0",
+ "WML 1.0",
+ { ext_t_0_wml_10, ext_t_1_wml_10, ext_t_2_wml_10 },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ wbxml_wmlc10_global,
+ wbxml_wmlc10_tags,
+ wbxml_wmlc10_attrStart,
+ wbxml_wmlc10_attrValue
+};
+
+
+
+
+/* WML 1.1
+ *
+ * Wireless Markup Language
+ ***************************************/
+
+/***** Global extension tokens *****/
+/* Same as in WML 1.0 */
+
+/***** Tag tokens *****/
+static const value_string wbxml_wmlc11_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ /* 0x05 -- 0x1B */
+ { 0x1C, "a" },
+ { 0x1D, "td" },
+ { 0x1E, "tr" },
+ { 0x1F, "table" },
+ { 0x20, "p" },
+ { 0x21, "postfield" },
+ { 0x22, "anchor" },
+ { 0x23, "access" },
+ { 0x24, "b" },
+ { 0x25, "big" },
+ { 0x26, "br" },
+ { 0x27, "card" },
+ { 0x28, "do" },
+ { 0x29, "em" },
+ { 0x2A, "fieldset" },
+ { 0x2B, "go" },
+ { 0x2C, "head" },
+ { 0x2D, "i" },
+ { 0x2E, "img" },
+ { 0x2F, "input" },
+ { 0x30, "meta" },
+ { 0x31, "noop" },
+ { 0x32, "prev" },
+ { 0x33, "onevent" },
+ { 0x34, "optgroup" },
+ { 0x35, "option" },
+ { 0x36, "refresh" },
+ { 0x37, "select" },
+ { 0x38, "small" },
+ { 0x39, "strong" },
+ /* 0x3A */
+ { 0x3B, "template" },
+ { 0x3C, "timer" },
+ { 0x3D, "u" },
+ { 0x3E, "setvar" },
+ { 0x3F, "wml" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_wmlc11_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "accept-charset=" },
+ { 0x06, "align='bottom'" },
+ { 0x07, "align='center'" },
+ { 0x08, "align='left'" },
+ { 0x09, "align='middle'" },
+ { 0x0A, "align='right'" },
+ { 0x0B, "align='top'" },
+ { 0x0C, "alt=" },
+ { 0x0D, "content=" },
+ /* 0x0E */
+ { 0x0F, "domain=" },
+ { 0x10, "emptyok='false'" },
+ { 0x11, "emptyok='true'" },
+ { 0x12, "format=" },
+ { 0x13, "height=" },
+ { 0x14, "hspace=" },
+ { 0x15, "ivalue=" },
+ { 0x16, "iname=" },
+ /* 0x17 */
+ { 0x18, "label=" },
+ { 0x19, "localsrc=" },
+ { 0x1A, "maxlength=" },
+ { 0x1B, "method='get'" },
+ { 0x1C, "method='post'" },
+ { 0x1D, "mode='nowrap'" },
+ { 0x1E, "mode='wrap'" },
+ { 0x1F, "multiple='false'" },
+ { 0x20, "multiple='true'" },
+ { 0x21, "name=" },
+ { 0x22, "newcontext='false'" },
+ { 0x23, "newcontext='true'" },
+ { 0x24, "onpick=" },
+ { 0x25, "onenterbackward=" },
+ { 0x26, "onenterforward=" },
+ { 0x27, "ontimer=" },
+ { 0x28, "optional='false'" },
+ { 0x29, "optional='true'" },
+ { 0x2A, "path=" },
+ /* 0x2B -- 0x2D */
+ { 0x2E, "scheme=" },
+ { 0x2F, "sendreferer='false'" },
+ { 0x30, "sendreferer='true'" },
+ { 0x31, "size=" },
+ { 0x32, "src=" },
+ { 0x33, "ordered='false'" },
+ { 0x34, "ordered='true'" },
+ { 0x35, "tabindex=" },
+ { 0x36, "title=" },
+ { 0x37, "type=" },
+ { 0x38, "type='accept'" },
+ { 0x39, "type='delete'" },
+ { 0x3A, "type='help'" },
+ { 0x3B, "type='password'" },
+ { 0x3C, "type='onpick'" },
+ { 0x3D, "type='onenterbackward'" },
+ { 0x3E, "type='onenterforward'" },
+ { 0x3F, "type='ontimer'" },
+ /* 0x40 -- 0x44 GLOBAL */
+ { 0x45, "type='options'" },
+ { 0x46, "type='prev'" },
+ { 0x47, "type='reset'" },
+ { 0x48, "type='text'" },
+ { 0x49, "type='vnd.'" },
+ { 0x4A, "href=" },
+ { 0x4B, "href='http://'" },
+ { 0x4C, "href='https://'" },
+ { 0x4D, "value=" },
+ { 0x4E, "vspace=" },
+ { 0x4F, "width=" },
+ { 0x50, "xml:lang=" },
+ /* 0x51 */
+ { 0x52, "align=" },
+ { 0x53, "columns=" },
+ { 0x54, "class=" },
+ { 0x55, "id=" },
+ { 0x56, "forua='false'" },
+ { 0x57, "forua='true'" },
+ { 0x58, "src='http://'" },
+ { 0x59, "src='https://'" },
+ { 0x5A, "http-equiv=" },
+ { 0x5B, "http-equiv='Content-Type'" },
+ { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
+ { 0x5D, "http-equiv='Expires'" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+static const value_string wbxml_wmlc11_attrValue_cp0[] = {
+ /* 0x80 -- 0x84 GLOBAL */
+ { 0x85, "'.com/'" },
+ { 0x86, "'.edu/'" },
+ { 0x87, "'.net/'" },
+ { 0x88, "'.org/'" },
+ { 0x89, "'accept'" },
+ { 0x8A, "'bottom'" },
+ { 0x8B, "'clear'" },
+ { 0x8C, "'delete'" },
+ { 0x8D, "'help'" },
+ { 0x8E, "'http://'" },
+ { 0x8F, "'http://www.'" },
+ { 0x90, "'https://'" },
+ { 0x91, "'https://www.'" },
+ /* 0x92 */
+ { 0x93, "'middle'" },
+ { 0x94, "'nowrap'" },
+ { 0x95, "'onpick'" },
+ { 0x96, "'onenterbackward'" },
+ { 0x97, "'onenterforward'" },
+ { 0x98, "'ontimer'" },
+ { 0x99, "'options'" },
+ { 0x9A, "'password'" },
+ { 0x9B, "'reset'" },
+ /* 0x9C */
+ { 0x9D, "'text'" },
+ { 0x9E, "'top'" },
+ { 0x9F, "'unknown'" },
+ { 0xA0, "'wrap'" },
+ { 0xA1, "'www.'" },
+
+ { 0x00, NULL }
+};
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_wmlc11_global[] = {
+ { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc11_tags[] = {
+ { 0, wbxml_wmlc11_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc11_attrStart[] = {
+ { 0, wbxml_wmlc11_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc11_attrValue[] = {
+ { 0, wbxml_wmlc11_attrValue_cp0 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_wmlc_11 = {
+ "Wireless Markup Language 1.1",
+ "WML 1.1",
+ { ext_t_0_wml_10, ext_t_1_wml_10, ext_t_2_wml_10 },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ wbxml_wmlc11_global,
+ wbxml_wmlc11_tags,
+ wbxml_wmlc11_attrStart,
+ wbxml_wmlc11_attrValue
+};
+
+
+
+
+
+/* WML 1.2
+ *
+ * Wireless Markup Language
+ ***************************************/
+
+/***** Global extension tokens *****/
+/* Same as in WML 1.0 */
+
+/***** Tag tokens *****/
+static const value_string wbxml_wmlc12_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ /* 0x05 -- 0x1A */
+ { 0x1B, "pre" },
+ { 0x1C, "a" },
+ { 0x1D, "td" },
+ { 0x1E, "tr" },
+ { 0x1F, "table" },
+ { 0x20, "p" },
+ { 0x21, "postfield" },
+ { 0x22, "anchor" },
+ { 0x23, "access" },
+ { 0x24, "b" },
+ { 0x25, "big" },
+ { 0x26, "br" },
+ { 0x27, "card" },
+ { 0x28, "do" },
+ { 0x29, "em" },
+ { 0x2A, "fieldset" },
+ { 0x2B, "go" },
+ { 0x2C, "head" },
+ { 0x2D, "i" },
+ { 0x2E, "img" },
+ { 0x2F, "input" },
+ { 0x30, "meta" },
+ { 0x31, "noop" },
+ { 0x32, "prev" },
+ { 0x33, "onevent" },
+ { 0x34, "optgroup" },
+ { 0x35, "option" },
+ { 0x36, "refresh" },
+ { 0x37, "select" },
+ { 0x38, "small" },
+ { 0x39, "strong" },
+ /* 0x3A */
+ { 0x3B, "template" },
+ { 0x3C, "timer" },
+ { 0x3D, "u" },
+ { 0x3E, "setvar" },
+ { 0x3F, "wml" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_wmlc12_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "accept-charset=" },
+ { 0x06, "align='bottom'" },
+ { 0x07, "align='center'" },
+ { 0x08, "align='left'" },
+ { 0x09, "align='middle'" },
+ { 0x0A, "align='right'" },
+ { 0x0B, "align='top'" },
+ { 0x0C, "alt=" },
+ { 0x0D, "content=" },
+ /* 0x0E */
+ { 0x0F, "domain=" },
+ { 0x10, "emptyok='false'" },
+ { 0x11, "emptyok='true'" },
+ { 0x12, "format=" },
+ { 0x13, "height=" },
+ { 0x14, "hspace=" },
+ { 0x15, "ivalue=" },
+ { 0x16, "iname=" },
+ /* 0x17 */
+ { 0x18, "label=" },
+ { 0x19, "localsrc=" },
+ { 0x1A, "maxlength=" },
+ { 0x1B, "method='get'" },
+ { 0x1C, "method='post'" },
+ { 0x1D, "mode='nowrap'" },
+ { 0x1E, "mode='wrap'" },
+ { 0x1F, "multiple='false'" },
+ { 0x20, "multiple='true'" },
+ { 0x21, "name=" },
+ { 0x22, "newcontext='false'" },
+ { 0x23, "newcontext='true'" },
+ { 0x24, "onpick=" },
+ { 0x25, "onenterbackward=" },
+ { 0x26, "onenterforward=" },
+ { 0x27, "ontimer=" },
+ { 0x28, "optional='false'" },
+ { 0x29, "optional='true'" },
+ { 0x2A, "path=" },
+ /* 0x2B -- 0x2D */
+ { 0x2E, "scheme=" },
+ { 0x2F, "sendreferer='false'" },
+ { 0x30, "sendreferer='true'" },
+ { 0x31, "size=" },
+ { 0x32, "src=" },
+ { 0x33, "ordered='false'" },
+ { 0x34, "ordered='true'" },
+ { 0x35, "tabindex=" },
+ { 0x36, "title=" },
+ { 0x37, "type=" },
+ { 0x38, "type='accept'" },
+ { 0x39, "type='delete'" },
+ { 0x3A, "type='help'" },
+ { 0x3B, "type='password'" },
+ { 0x3C, "type='onpick'" },
+ { 0x3D, "type='onenterbackward'" },
+ { 0x3E, "type='onenterforward'" },
+ { 0x3F, "type='ontimer'" },
+ /* 0x40 -- 0x44 GLOBAL */
+ { 0x45, "type='options'" },
+ { 0x46, "type='prev'" },
+ { 0x47, "type='reset'" },
+ { 0x48, "type='text'" },
+ { 0x49, "type='vnd.'" },
+ { 0x4A, "href=" },
+ { 0x4B, "href='http://'" },
+ { 0x4C, "href='https://'" },
+ { 0x4D, "value=" },
+ { 0x4E, "vspace=" },
+ { 0x4F, "width=" },
+ { 0x50, "xml:lang=" },
+ /* 0x51 */
+ { 0x52, "align=" },
+ { 0x53, "columns=" },
+ { 0x54, "class=" },
+ { 0x55, "id=" },
+ { 0x56, "forua='false'" },
+ { 0x57, "forua='true'" },
+ { 0x58, "src='http://'" },
+ { 0x59, "src='https://'" },
+ { 0x5A, "http-equiv=" },
+ { 0x5B, "http-equiv='Content-Type'" },
+ { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
+ { 0x5D, "http-equiv='Expires'" },
+ { 0x5E, "accesskey=" },
+ { 0x5F, "enctype=" },
+ { 0x60, "enctype='application/x-www-form-urlencoded'" },
+ { 0x61, "enctype='multipart/form-data'" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+/* Same as in WML 1.1 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_wmlc12_global[] = {
+ { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc12_tags[] = {
+ { 0, wbxml_wmlc12_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc12_attrStart[] = {
+ { 0, wbxml_wmlc12_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc12_attrValue[] = {
+ { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_wmlc_12 = {
+ "Wireless Markup Language 1.2",
+ "WML 1.2",
+ { ext_t_0_wml_10, ext_t_1_wml_10, ext_t_2_wml_10 },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ wbxml_wmlc12_global,
+ wbxml_wmlc12_tags,
+ wbxml_wmlc12_attrStart,
+ wbxml_wmlc12_attrValue
+};
+
+
+
+
+
+/* WML 1.3
+ *
+ * Wireless Markup Language
+ ***************************************/
+
+/***** Global extension tokens *****/
+/* Same as in WML 1.0 */
+
+/***** Tag tokens *****/
+/* Same as in WML 1.2 */
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_wmlc13_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "accept-charset=" },
+ { 0x06, "align='bottom'" },
+ { 0x07, "align='center'" },
+ { 0x08, "align='left'" },
+ { 0x09, "align='middle'" },
+ { 0x0A, "align='right'" },
+ { 0x0B, "align='top'" },
+ { 0x0C, "alt=" },
+ { 0x0D, "content=" },
+ /* 0x0E */
+ { 0x0F, "domain=" },
+ { 0x10, "emptyok='false'" },
+ { 0x11, "emptyok='true'" },
+ { 0x12, "format=" },
+ { 0x13, "height=" },
+ { 0x14, "hspace=" },
+ { 0x15, "ivalue=" },
+ { 0x16, "iname=" },
+ /* 0x17 */
+ { 0x18, "label=" },
+ { 0x19, "localsrc=" },
+ { 0x1A, "maxlength=" },
+ { 0x1B, "method='get'" },
+ { 0x1C, "method='post'" },
+ { 0x1D, "mode='nowrap'" },
+ { 0x1E, "mode='wrap'" },
+ { 0x1F, "multiple='false'" },
+ { 0x20, "multiple='true'" },
+ { 0x21, "name=" },
+ { 0x22, "newcontext='false'" },
+ { 0x23, "newcontext='true'" },
+ { 0x24, "onpick=" },
+ { 0x25, "onenterbackward=" },
+ { 0x26, "onenterforward=" },
+ { 0x27, "ontimer=" },
+ { 0x28, "optional='false'" },
+ { 0x29, "optional='true'" },
+ { 0x2A, "path=" },
+ /* 0x2B -- 0x2D */
+ { 0x2E, "scheme=" },
+ { 0x2F, "sendreferer='false'" },
+ { 0x30, "sendreferer='true'" },
+ { 0x31, "size=" },
+ { 0x32, "src=" },
+ { 0x33, "ordered='false'" },
+ { 0x34, "ordered='true'" },
+ { 0x35, "tabindex=" },
+ { 0x36, "title=" },
+ { 0x37, "type=" },
+ { 0x38, "type='accept'" },
+ { 0x39, "type='delete'" },
+ { 0x3A, "type='help'" },
+ { 0x3B, "type='password'" },
+ { 0x3C, "type='onpick'" },
+ { 0x3D, "type='onenterbackward'" },
+ { 0x3E, "type='onenterforward'" },
+ { 0x3F, "type='ontimer'" },
+ /* 0x40 -- 0x44 GLOBAL */
+ { 0x45, "type='options'" },
+ { 0x46, "type='prev'" },
+ { 0x47, "type='reset'" },
+ { 0x48, "type='text'" },
+ { 0x49, "type='vnd.'" },
+ { 0x4A, "href=" },
+ { 0x4B, "href='http://'" },
+ { 0x4C, "href='https://'" },
+ { 0x4D, "value=" },
+ { 0x4E, "vspace=" },
+ { 0x4F, "width=" },
+ { 0x50, "xml:lang=" },
+ /* 0x51 */
+ { 0x52, "align=" },
+ { 0x53, "columns=" },
+ { 0x54, "class=" },
+ { 0x55, "id=" },
+ { 0x56, "forua='false'" },
+ { 0x57, "forua='true'" },
+ { 0x58, "src='http://'" },
+ { 0x59, "src='https://'" },
+ { 0x5A, "http-equiv=" },
+ { 0x5B, "http-equiv='Content-Type'" },
+ { 0x5C, "content='application/vnd.wap.wmlc;charset='" },
+ { 0x5D, "http-equiv='Expires'" },
+ { 0x5E, "accesskey=" },
+ { 0x5F, "enctype=" },
+ { 0x60, "enctype='application/x-www-form-urlencoded'" },
+ { 0x61, "enctype='multipart/form-data'" },
+ { 0x62, "xml:space='preserve'" },
+ { 0x63, "xml:space='default'" },
+ { 0x64, "cache-control='no-cache'" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+/* Same as in WML 1.1 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_wmlc13_global[] = {
+ { 0, wbxml_wmlc10_global_cp0 }, /* Same as WML 1.0 */
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc13_tags[] = {
+ { 0, wbxml_wmlc12_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc13_attrStart[] = {
+ { 0, wbxml_wmlc13_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wmlc13_attrValue[] = {
+ { 0, wbxml_wmlc11_attrValue_cp0 }, /* Same as WML 1.1 */
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_wmlc_13 = {
+ "Wireless Markup Language 1.3",
+ "WML 1.3",
+ { ext_t_0_wml_10, ext_t_1_wml_10, ext_t_2_wml_10 },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ wbxml_wmlc13_global,
+ wbxml_wmlc13_tags,
+ wbxml_wmlc13_attrStart,
+ wbxml_wmlc13_attrValue
+};
+
+
+
+
+
+/* SI 1.0
+ *
+ * Service Indication
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+static const value_string wbxml_sic10_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "si" },
+ { 0x06, "indication" },
+ { 0x07, "info" },
+ { 0x08, "item" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_sic10_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "action='signal-none'" },
+ { 0x06, "action='signal-low'" },
+ { 0x07, "action='signal-medium'" },
+ { 0x08, "action='signal-high'" },
+ { 0x09, "action='delete'" },
+ { 0x0a, "created=" },
+ { 0x0b, "href=" },
+ { 0x0c, "href='http://'" },
+ { 0x0d, "href='http://www.'" },
+ { 0x0e, "href='https://'" },
+ { 0x0f, "href='https://www.'" },
+ { 0x10, "si-expires=" },
+ { 0x11, "si-id=" },
+ { 0x12, "class=" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+static const value_string wbxml_sic10_attrValue_cp0[] = {
+ /* 0x80 -- 0x84 GLOBAL */
+ { 0x85, "'.com/'" },
+ { 0x86, "'.edu/'" },
+ { 0x87, "'.net/'" },
+ { 0x88, "'.org/'" },
+
+ { 0x00, NULL }
+};
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_sic10_tags[] = {
+ { 0, wbxml_sic10_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_sic10_attrStart[] = {
+ { 0, wbxml_sic10_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_sic10_attrValue[] = {
+ { 0, wbxml_sic10_attrValue_cp0 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_sic_10 = {
+ "Service Indication 1.0",
+ "SI 1.0",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ sic10_opaque_binary_attr,
+ sic10_opaque_literal_attr,
+ NULL,
+ wbxml_sic10_tags,
+ wbxml_sic10_attrStart,
+ wbxml_sic10_attrValue
+};
+
+
+
+
+
+/* SL 1.0
+ *
+ * Service Loading
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+static const value_string wbxml_slc10_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "sl" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_slc10_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "action='execute-low'" },
+ { 0x06, "action='execute-high'" },
+ { 0x07, "action='cache'" },
+ { 0x08, "href=" },
+ { 0x09, "href='http://'" },
+ { 0x0a, "href='http://www.'" },
+ { 0x0b, "href='https://'" },
+ { 0x0c, "href='https://www.'" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+/* Same as in SI 1.0 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_slc10_tags[] = {
+ { 0, wbxml_slc10_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_slc10_attrStart[] = {
+ { 0, wbxml_slc10_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_slc10_attrValue[] = {
+ { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_slc_10 = {
+ "Service Loading 1.0",
+ "SL 1.0",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ NULL,
+ wbxml_slc10_tags,
+ wbxml_slc10_attrStart,
+ wbxml_slc10_attrValue
+};
+
+
+
+
+
+/* CO 1.0
+ *
+ * Cache Operation
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+static const value_string wbxml_coc10_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "co" },
+ { 0x06, "invalidate-object" },
+ { 0x07, "invalidate-service" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_coc10_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "uri=" },
+ { 0x06, "uri='http://'" },
+ { 0x07, "uri='http://www.'" },
+ { 0x08, "uri='https://'" },
+ { 0x09, "uri='https://www.'" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+/* Same as in SI 1.0 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_coc10_tags[] = {
+ { 0, wbxml_coc10_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_coc10_attrStart[] = {
+ { 0, wbxml_coc10_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_coc10_attrValue[] = {
+ { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_coc_10 = {
+ "Cache Operation 1.0",
+ "CO 1.0",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ NULL,
+ wbxml_coc10_tags,
+ wbxml_coc10_attrStart,
+ wbxml_coc10_attrValue
+};
+
+
+
+
+
+/* PROV 1.0
+ *
+ * Client Provisioning
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+static const value_string wbxml_provc10_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "wap-provisioningdoc" },
+ { 0x06, "characteristic" },
+ { 0x07, "parm" },
+
+ { 0x00, NULL }
+};
+static const value_string wbxml_provc10_tags_cp1[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ /* 0x05 */
+ { 0x06, "characteristic" },
+ { 0x07, "parm" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_provc10_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "name=" },
+ { 0x06, "value=" },
+ { 0x07, "name='NAME'" },
+ { 0x08, "name='NAP-ADDRESS'" },
+ { 0x09, "name='NAP-ADDRTYPE'" },
+ { 0x0A, "name='CALLTYPE'" },
+ { 0x0B, "name='VALIDUNTIL'" },
+ { 0x0C, "name='AUTHTYPE'" },
+ { 0x0D, "name='AUTHNAME'" },
+ { 0x0E, "name='AUTHSECRET'" },
+ { 0x0F, "name='LINGER'" },
+ { 0x10, "name='BEARER'" },
+ { 0x11, "name='NAPID'" },
+ { 0x12, "name='COUNTRY'" },
+ { 0x13, "name='NETWORK'" },
+ { 0x14, "name='INTERNET'" },
+ { 0x15, "name='PROXY-ID'" },
+ { 0x16, "name='PROXY-PROVIDER-ID'" },
+ { 0x17, "name='DOMAIN'" },
+ { 0x18, "name='PROVURL'" },
+ { 0x19, "name='PXAUTH-TYPE'" },
+ { 0x1A, "name='PXAUTH-ID'" },
+ { 0x1B, "name='PXAUTH-PW'" },
+ { 0x1C, "name='STARTPAGE'" },
+ { 0x1D, "name='BASAUTH-ID'" },
+ { 0x1E, "name='BASAUTH-PW'" },
+ { 0x1F, "name='PUSHENABLED'" },
+ { 0x20, "name='PXADDR'" },
+ { 0x21, "name='PXADDRTYPE'" },
+ { 0x22, "name='TO-NAPID'" },
+ { 0x23, "name='PORTNBR'" },
+ { 0x24, "name='SERVICE'" },
+ { 0x25, "name='LINKSPEED'" },
+ { 0x26, "name='DNLINKSPEED'" },
+ { 0x27, "name='LOCAL-ADDR'" },
+ { 0x28, "name='LOCAL-ADDRTYPE'" },
+ { 0x29, "name='CONTEXT-ALLOW'" },
+ { 0x2A, "name='TRUST'" },
+ { 0x2B, "name='MASTER'" },
+ { 0x2C, "name='SID'" },
+ { 0x2D, "name='SOC'" },
+ { 0x2E, "name='WSP-VERSION'" },
+ { 0x2F, "name='PHYSICAL-PROXY-ID'" },
+ { 0x30, "name='CLIENT-ID'" },
+ { 0x31, "name='DELIVERY-ERR-SDU'" },
+ { 0x32, "name='DELIVERY-ORDER'" },
+ { 0x33, "name='TRAFFIC-CLASS'" },
+ { 0x34, "name='MAX-SDU-SIZE'" },
+ { 0x35, "name='MAX-BITRATE-UPLINK'" },
+ { 0x36, "name='MAX-BITRATE-DNLINK'" },
+ { 0x37, "name='RESIDUAL-BER'" },
+ { 0x38, "name='SDU-ERROR-RATIO'" },
+ { 0x39, "name='TRAFFIC-HANDL-PRIO'" },
+ { 0x3A, "name='TRANSFER-DELAY'" },
+ { 0x3B, "name='GUARANTEED-BITRATE-UPLINK'" },
+ { 0x3C, "name='GUARANTEED-BITRATE-DNLINK'" },
+ { 0x3D, "name='PXADDR-FQDN'" },
+ { 0x3E, "name='PROXY-PW'" },
+ { 0x3F, "name='PPGAUTH-TYPE'" },
+ /* 0x40 -- 0x44 GLOBAL */
+ { 0x45, "version=" },
+ { 0x46, "version='1.0'" },
+ { 0x47, "name='PULLENABLED'" },
+ { 0x48, "name='DNS-ADDR'" },
+ { 0x49, "name='MAX-NUM-RETRY'" },
+ { 0x4A, "name='FIRST-RETRY-TIMEOUT'" },
+ { 0x4B, "name='REREG-THRESHOLD'" },
+ { 0x4C, "name='T-BIT'" },
+ /* 0x4D */
+ { 0x4E, "name='AUTH-ENTITY'" },
+ { 0x4F, "name='SPI'" },
+ { 0x50, "type=" },
+ { 0x51, "type='PXLOGICAL'" },
+ { 0x52, "type='PXPHYSICAL'" },
+ { 0x53, "type='PORT'" },
+ { 0x54, "type='VALIDITY'" },
+ { 0x55, "type='NAPDEF'" },
+ { 0x56, "type='BOOTSTRAP'" },
+ { 0x57, "type='VENDORCONFIG'" },
+ { 0x58, "type='CLIENTIDENTITY'" },
+ { 0x59, "type='PXAUTHINFO'" },
+ { 0x5A, "type='NAPAUTHINFO'" },
+ { 0x5B, "type='ACCESS'" },
+
+ { 0x00, NULL }
+};
+static const value_string wbxml_provc10_attrStart_cp1[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ /* 0x05 -- 0x06 */
+ { 0x07, "name='NAME'" },
+ /* 0x08 -- 0x13 */
+ { 0x14, "name='INTERNET'" },
+ /* 0x15 -- 0x1B */
+ { 0x1C, "name='STARTPAGE'" },
+ /* 0x1D -- 0x21 */
+ { 0x22, "name='TO-NAPID'" },
+ { 0x23, "name='PORTNBR'" },
+ { 0x24, "name='SERVICE'" },
+ /* 0x25 -- 0x2D */
+ { 0x2E, "name='AACCEPT'" },
+ { 0x2F, "name='AAUTHDATA'" },
+ { 0x30, "name='AAUTHLEVEL'" },
+ { 0x31, "name='AAUTHNAME'" },
+ { 0x32, "name='AAUTHSECRET'" },
+ { 0x33, "name='AAUTHTYPE'" },
+ { 0x34, "name='ADDR'" },
+ { 0x35, "name='ADDRTYPE'" },
+ { 0x36, "name='APPID'" },
+ { 0x37, "name='APROTOCOL'" },
+ { 0x38, "name='PROVIDER-ID'" },
+ { 0x39, "name='TO-PROXY'" },
+ { 0x3A, "name='URI'" },
+ { 0x3B, "name='RULE'" },
+ /* 0x3C -- 0x3F */
+ /* 0x40 -- 0x44 GLOBAL */
+ /* 0x45 -- 0x4F */
+ { 0x50, "type=" },
+ /* 0x51 -- 0x52 */
+ { 0x53, "type='PORT'" },
+ /* 0x54 */
+ { 0x55, "type='APPLICATION'" },
+ { 0x56, "type='APPADDR'" },
+ { 0x57, "type='APPAUTH'" },
+ { 0x58, "type='CLIENTIDENTITY'" },
+ { 0x59, "type='RESOURCE'" },
+ /* 0x5A -- 0x7F */
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_provc10_attrValue_cp0[] = {
+ /* 0x80 -- 0x84 GLOBAL */
+ { 0x85, "'IPV4'" },
+ { 0x86, "'IPV6'" },
+ { 0x87, "'E164'" },
+ { 0x88, "'ALPHA'" },
+ { 0x89, "'APN'" },
+ { 0x8A, "'SCODE'" },
+ { 0x8B, "'TETRA-ITSI'" },
+ { 0x8C, "'MAN'" },
+ /* 0x8D -- 0x8F */
+ { 0x90, "'ANALOG-MODEM'" },
+ { 0x91, "'V.120'" },
+ { 0x92, "'V.110'" },
+ { 0x93, "'X.31'" },
+ { 0x94, "'BIT-TRANSPARENT'" },
+ { 0x95, "'DIRECT-ASYNCHRONOUS-DATA-SERVICE'" },
+ /* 0x96 -- 0x99 */
+ { 0x9A, "'PAP'" },
+ { 0x9B, "'CHAP'" },
+ { 0x9C, "'HTTP-BASIC'" },
+ { 0x9D, "'HTTP-DIGEST'" },
+ { 0x9E, "'WTLS-SS'" },
+ { 0x9F, "'MD5'" },
+ /* 0xA0 -- 0xA1 */
+ { 0xA2, "'GSM-USSD'" },
+ { 0xA3, "'GSM-SMS'" },
+ { 0xA4, "'ANSI-136-GUTS'" },
+ { 0xA5, "'IS-95-CDMA-SMS'" },
+ { 0xA6, "'IS-95-CDMA-CSD'" },
+ { 0xA7, "'IS-95-CDMA-PACKET'" },
+ { 0xA8, "'ANSI-136-CSD'" },
+ { 0xA9, "'ANSI-136-GPRS'" },
+ { 0xAA, "'GSM-CSD'" },
+ { 0xAB, "'GSM-GPRS'" },
+ { 0xAC, "'AMPS-CDPD'" },
+ { 0xAD, "'PDC-CSD'" },
+ { 0xAE, "'PDC-PACKET'" },
+ { 0xAF, "'IDEN-SMS'" },
+ { 0xB0, "'IDEN-CSD'" },
+ { 0xB1, "'IDEN-PACKET'" },
+ { 0xB2, "'FLEX/REFLEX'" },
+ { 0xB3, "'PHS-SMS'" },
+ { 0xB4, "'PHS-CSD'" },
+ { 0xB5, "'TETRA-SDS'" },
+ { 0xB6, "'TETRA-PACKET'" },
+ { 0xB7, "'ANSI-136-GHOST'" },
+ { 0xB8, "'MOBITEX-MPAK'" },
+ { 0xB9, "'CDMA2000-IX-SIMPLE-IP'" },
+ { 0xBA, "'CDMA2000-IX-MOBILE-IP'" },
+ /* 0xBB -- 0xBF */
+ /* 0xC0 -- 0xC4 GLOBAL */
+ { 0xC5, "'AUTOBAUDING'" },
+ /* 0xC6 -- 0xC9 */
+ { 0xCA, "'CL-WSP'" },
+ { 0xCB, "'CO-WSP'" },
+ { 0xCC, "'CL-SEC-WSP'" },
+ { 0xCD, "'CO-SEC-WSP'" },
+ { 0xCE, "'CL-SEC-WTA'" },
+ { 0xCF, "'CO-SEC-WTA'" },
+ { 0xD0, "'OTA-HTTP-TO'" },
+ { 0xD1, "'OTA-HTTP-TLS-TO'" },
+ { 0xD2, "'OTA-HTTP-PO'" },
+ { 0xD3, "'OTA-HTTP-TLS-PO'" },
+ /* 0xD4 -- 0xFF */
+
+ { 0x00, NULL }
+};
+static const value_string wbxml_provc10_attrValue_cp1[] = {
+ /* 0x80 -- 0x84 GLOBAL */
+ /* 0x85 */
+ { 0x86, "'IPV6'" },
+ { 0x87, "'E164'" },
+ { 0x88, "'ALPHA'" },
+ { 0x8D, "'APPSRV'" },
+ { 0x8E, "'OBEX'" },
+ /* 0x8F */
+
+ /* XXX - Errors that require a fix in the OMA/WAP Client Provisioning specs:
+ { 0xXXX, "','" },
+ { 0xXXX, "'HTTP-'" },
+ { 0xXXX, "'BASIC'" },
+ { 0xXXX, "'DIGEST'" },
+ */
+
+ { 0xE0, "'AAA'" },
+ { 0xE1, "'HA'" },
+
+ { 0x00, NULL }
+};
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_provc10_tags[] = {
+ { 0, wbxml_provc10_tags_cp0 },
+ { 1, wbxml_provc10_tags_cp1 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_provc10_attrStart[] = {
+ { 0, wbxml_provc10_attrStart_cp0 },
+ { 1, wbxml_provc10_attrStart_cp1 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_provc10_attrValue[] = {
+ { 0, wbxml_provc10_attrValue_cp0 },
+ { 1, wbxml_provc10_attrValue_cp1 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_provc_10 = {
+ "WAP Client Provisioning Document 1.0",
+ "WAP ProvisioningDoc 1.0",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ NULL,
+ wbxml_provc10_tags,
+ wbxml_provc10_attrStart,
+ wbxml_provc10_attrValue
+};
+
+
+
+
+
+/* EMN 1.0
+ *
+ * Email Notification
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+static const value_string wbxml_emnc10_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "emn" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_emnc10_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "timestamp=" },
+ { 0x06, "mailbox=" },
+ { 0x07, "mailbox='mailat:'" },
+ { 0x08, "mailbox='pop://'" },
+ { 0x09, "mailbox='imap://'" },
+ { 0x0a, "mailbox='http://'" },
+ { 0x0b, "mailbox='http://www.'" },
+ { 0x0c, "mailbox='https://'" },
+ { 0x0D, "mailbox='https://www.'" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+/* Same as in SI 1.0 */
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_emnc10_tags[] = {
+ { 0, wbxml_emnc10_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_emnc10_attrStart[] = {
+ { 0, wbxml_emnc10_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_emnc10_attrValue[] = {
+ { 0, wbxml_sic10_attrValue_cp0 }, /* Same as SI 1.0 */
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_emnc_10 = {
+ "E-Mail Notification 1.0",
+ "EMN 1.0",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ emnc10_opaque_binary_attr,
+ emnc10_opaque_literal_attr,
+ NULL,
+ wbxml_emnc10_tags,
+ wbxml_emnc10_attrStart,
+ wbxml_emnc10_attrValue
+};
+
+
+
+
+
+/* SyncML 1.0
+ *
+ * SyncML Representation Protocol
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+static const value_string wbxml_syncmlc10_tags_cp0[] = { /* SyncML 1.0 */
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "Add" },
+ { 0x06, "Alert" },
+ { 0x07, "Archive" },
+ { 0x08, "Atomic" },
+ { 0x09, "Chal" },
+ { 0x0A, "Cmd" },
+ { 0x0B, "CmdID" },
+ { 0x0C, "CmdRef" },
+ { 0x0D, "Copy" },
+ { 0x0E, "Cred" },
+ { 0x0F, "Data" },
+ { 0x10, "Delete" },
+ { 0x11, "Exec" },
+ { 0x12, "Final" },
+ { 0x13, "Get" },
+ { 0x14, "Item" },
+ { 0x15, "Lang" },
+ { 0x16, "LocName" },
+ { 0x17, "LocURI" },
+ { 0x18, "Map" },
+ { 0x19, "MapItem" },
+ { 0x1A, "Meta" },
+ { 0x1B, "MsgID" },
+ { 0x1C, "MsgRef" },
+ { 0x1D, "NoResp" },
+ { 0x1E, "NoResults" },
+ { 0x1F, "Put" },
+ { 0x20, "Replace" },
+ { 0x21, "RespURI" },
+ { 0x22, "Results" },
+ { 0x23, "Search" },
+ { 0x24, "Sequence" },
+ { 0x25, "SessionID" },
+ { 0x26, "SftDel" },
+ { 0x27, "Source" },
+ { 0x28, "SourceRef" },
+ { 0x29, "Status" },
+ { 0x2A, "Sync" },
+ { 0x2B, "SyncBody" },
+ { 0x2C, "SyncHdr" },
+ { 0x2D, "SyncML" },
+ { 0x2E, "Target" },
+ { 0x2F, "TargetRef" },
+ /* 0x30 - Reserved */
+ { 0x31, "VerDTD" },
+ { 0x32, "VerProto" },
+
+ { 0x00, NULL }
+};
+
+static const value_string wbxml_syncmlc10_tags_cp1[] = { /* MetInf 1.0 */
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "Anchor" },
+ { 0x06, "EMI" },
+ { 0x07, "Format" },
+ { 0x08, "FreeID" },
+ { 0x09, "FreeMem" },
+ { 0x0A, "Last" },
+ { 0x0B, "Mark" },
+ { 0x0C, "MaxMsgSize" },
+ { 0x0D, "Mem" },
+ { 0x0E, "MetInf" },
+ { 0x0F, "Next" },
+ { 0x10, "NextNonce" },
+ { 0x11, "SharedMem" },
+ { 0x12, "Size" },
+ { 0x13, "Type" },
+ { 0x14, "Version" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+
+/***** Attribute Value tokens *****/
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_syncmlc10_tags[] = {
+ { 0, wbxml_syncmlc10_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.0//EN */
+ { 1, wbxml_syncmlc10_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.0//EN */
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_syncmlc_10 = {
+ "SyncML Representation Protocol 1.0",
+ "SyncML 1.0",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ NULL,
+ wbxml_syncmlc10_tags,
+ NULL,
+ NULL
+};
+
+
+
+
+
+/* SyncML 1.1
+ *
+ * SyncML Representation Protocol
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+static const value_string wbxml_syncmlc11_tags_cp0[] = { /* SyncML 1.1 */
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "Add" },
+ { 0x06, "Alert" },
+ { 0x07, "Archive" },
+ { 0x08, "Atomic" },
+ { 0x09, "Chal" },
+ { 0x0a, "Cmd" },
+ { 0x0b, "CmdID" },
+ { 0x0c, "CmdRef" },
+ { 0x0d, "Copy" },
+ { 0x0e, "Cred" },
+ { 0x0f, "Data" },
+ { 0x10, "Delete" },
+ { 0x11, "Exec" },
+ { 0x12, "Final" },
+ { 0x13, "Get" },
+ { 0x14, "Item" },
+ { 0x15, "Lang" },
+ { 0x16, "LocName" },
+ { 0x17, "LocURI" },
+ { 0x18, "Map" },
+ { 0x19, "MapItem" },
+ { 0x1a, "Meta" },
+ { 0x1b, "MsgID" },
+ { 0x1c, "MsgRef" },
+ { 0x1d, "NoResp" },
+ { 0x1e, "NoResults" },
+ { 0x1f, "Put" },
+ { 0x20, "Replace" },
+ { 0x21, "RespURI" },
+ { 0x22, "Results" },
+ { 0x23, "Search" },
+ { 0x24, "Sequence" },
+ { 0x25, "SessionID" },
+ { 0x26, "SftDel" },
+ { 0x27, "Source" },
+ { 0x28, "SourceRef" },
+ { 0x29, "Status" },
+ { 0x2a, "Sync" },
+ { 0x2b, "SyncBody" },
+ { 0x2c, "SyncHdr" },
+ { 0x2d, "SyncML" },
+ { 0x2e, "Target" },
+ { 0x2f, "TargetRef" },
+ /* 0x30 - Reserved */
+ { 0x31, "VerDTD" },
+ { 0x32, "VerProto" },
+ { 0x33, "NumberOfChanges" },
+ { 0x34, "MoreData" },
+
+ { 0x00, NULL }
+};
+
+static const value_string wbxml_syncmlc11_tags_cp1[] = { /* MetInf 1.1 */
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "Anchor" },
+ { 0x06, "EMI" },
+ { 0x07, "Format" },
+ { 0x08, "FreeID" },
+ { 0x09, "FreeMem" },
+ { 0x0A, "Last" },
+ { 0x0B, "Mark" },
+ { 0x0C, "MaxMsgSize" },
+ { 0x0D, "Mem" },
+ { 0x0E, "MetInf" },
+ { 0x0F, "Next" },
+ { 0x10, "NextNonce" },
+ { 0x11, "SharedMem" },
+ { 0x12, "Size" },
+ { 0x13, "Type" },
+ { 0x14, "Version" },
+ { 0x15, "MaxObjSize" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+
+/***** Attribute Value tokens *****/
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_syncmlc11_tags[] = {
+ { 0, wbxml_syncmlc11_tags_cp0 }, /* -//SYNCML//DTD SyncML 1.1//EN */
+ { 1, wbxml_syncmlc11_tags_cp1 }, /* -//SYNCML//DTD MetInf 1.1//EN */
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_syncmlc_11 = {
+ "SyncML Representation Protocol 1.1",
+ "SyncML 1.1",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ NULL,
+ wbxml_syncmlc11_tags,
+ NULL,
+ NULL
+};
+
+
+
+
+
+/* CHANNEL 1.0
+ *
+ * WTA Channel
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+static const value_string wbxml_channelc10_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "channel" },
+ { 0x06, "title" },
+ { 0x07, "abstract" },
+ { 0x08, "resource" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_channelc10_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "maxspace=" },
+ { 0x06, "base=" },
+ { 0x07, "href=" },
+ { 0x08, "href='http://'" },
+ { 0x09, "href='https://'" },
+ { 0x0A, "lastmod=" },
+ { 0x0B, "etag=" },
+ { 0x0C, "md5=" },
+ { 0x0D, "success=" },
+ { 0x0E, "success='http://'" },
+ { 0x0F, "success='https://'" },
+ { 0x10, "failure=" },
+ { 0x11, "failure='http://'" },
+ { 0x12, "failure='https://'" },
+ { 0x13, "EventId=" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_channelc10_tags[] = {
+ { 0, wbxml_channelc10_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_channelc10_attrStart[] = {
+ { 0, wbxml_channelc10_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_channelc_10 = {
+ "Wireless Telephony Application (WTA) Channel 1.0",
+ "CHANNEL 1.0",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ NULL,
+ wbxml_channelc10_tags,
+ wbxml_channelc10_attrStart,
+ NULL
+};
+
+
+
+
+
+/* application/x-wap-prov.browser-settings
+ * application/x-wap-prov.browser-bookmarks
+ *
+ * Nokia OTA Provisioning document format
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+static const value_string wbxml_nokiaprovc70_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "CHARACTERISTIC-LIST" },
+ { 0x06, "CHARACTERISTIC" },
+ { 0x07, "PARM" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+static const value_string wbxml_nokiaprovc70_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x06, "TYPE='ADDRESS'" },
+ { 0x07, "TYPE='URL'" },
+ { 0x08, "TYPE='NAME'" },
+ { 0x10, "NAME=" },
+ { 0x11, "VALUE=" },
+ { 0x12, "NAME='BEARER'" },
+ { 0x13, "NAME='PROXY'" },
+ { 0x14, "NAME='PORT'" },
+ { 0x15, "NAME='NAME'" },
+ { 0x16, "NAME='PROXY_TYPE'" },
+ { 0x17, "NAME='URL'" },
+ { 0x18, "NAME='PROXY_AUTHNAME'" },
+ { 0x19, "NAME='PROXY_AUTHSECRET'" },
+ { 0x1A, "NAME='SMS_SMSC_ADDRESS'" },
+ { 0x1B, "NAME='USSD_SERVICE_CODE'" },
+ { 0x1C, "NAME='GPRS_ACCESSPOINTNAME'" },
+ { 0x1D, "NAME='PPP_LOGINTYPE'" },
+ { 0x1E, "NAME='PROXY_LOGINTYPE'" },
+ { 0x21, "NAME='CSD_DIALSTRING'" },
+ { 0x22, "NAME='PPP_AUTHTYPE'" },
+ { 0x23, "NAME='PPP_AUTHNAME'" },
+ { 0x24, "NAME='PPP_AUTHSECRET'" },
+ { 0x28, "NAME='CSD_CALLTYPE'" },
+ { 0x29, "NAME='CSD_CALLSPEED'" },
+ { 0x45, "VALUE='GSM/CSD'" },
+ { 0x46, "VALUE='GSM/SMS'" },
+ { 0x47, "VALUE='GSM/USSD'" },
+ { 0x48, "VALUE='IS-136/CSD'" },
+ { 0x49, "VALUE='GPRS'" },
+ { 0x60, "VALUE='9200'" },
+ { 0x61, "VALUE='9201'" },
+ { 0x62, "VALUE='9202'" },
+ { 0x63, "VALUE='9203'" },
+ { 0x64, "VALUE='AUTOMATIC'" },
+ { 0x65, "VALUE='MANUAL'" },
+ { 0x6A, "VALUE='AUTO'" },
+ { 0x6B, "VALUE='9600'" },
+ { 0x6C, "VALUE='14400'" },
+ { 0x6D, "VALUE='19200'" },
+ { 0x6E, "VALUE='28800'" },
+ { 0x6F, "VALUE='38400'" },
+ { 0x70, "VALUE='PAP'" },
+ { 0x71, "VALUE='CHAP'" },
+ { 0x72, "VALUE='ANALOGUE'" },
+ { 0x73, "VALUE='ISDN'" },
+ { 0x74, "VALUE='43200'" },
+ { 0x75, "VALUE='57600'" },
+ { 0x76, "VALUE='MSISDN_NO'" },
+ { 0x77, "VALUE='IPV4'" },
+ { 0x78, "VALUE='MS_CHAP'" },
+ { 0x7C, "TYPE='MMSURL'" },
+ { 0x7D, "TYPE='ID'" },
+ { 0x7E, "NAME='ISP_NAME'" },
+ { 0x7F, "TYPE='BOOKMARK'" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_nokiaprovc70_tags[] = {
+ { 0, wbxml_nokiaprovc70_tags_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_nokiaprovc70_attrStart[] = {
+ { 0, wbxml_nokiaprovc70_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_nokiaprovc_70 = {
+ "Nokia Client Provisioning 7.0",
+ "Nokia Client Provisioning 7.0",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ NULL,
+ wbxml_nokiaprovc70_tags,
+ wbxml_nokiaprovc70_attrStart,
+ NULL
+};
+
+
+
+
+
+/* UAProf [WAP-248]
+ *
+ * User-Agent Profile (used in profile-diff WSP header)
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+/* CodePage 0 RDF */
+static const value_string wbxml_uaprof_tags_cp0[] = {
+ {0x05, "rdf:RDF"},
+ {0x06, "rdf:Description"},
+ {0x07, "rdf:Alt"},
+ {0x08, "rdf:Bag"},
+ {0x09, "rdf:Seq"},
+ {0x0A, "rdf:li"},
+ {0x0B, "rdf:type"},
+ {0x0C, "rdf:value"},
+ {0x0D, "rdf:subject"},
+ {0x0E, "rdf:predicate"},
+ {0x0F, "rdf:object"},
+
+ { 0x00, NULL }
+};
+
+/* CodePage 1 Core Vocabulary */
+static const value_string wbxml_uaprof_tags_cp1[] = {
+ {0x06, "rdf:Description"},
+ {0x07, "rdf:Alt"},
+ {0x08, "rdf:Bag"},
+ {0x09, "rdf:Seq"},
+ {0x0A, "rdf:li"},
+ {0x0B, "rdf:type"},
+ {0x0C, "prf:component"},
+ {0x0D, "prf:defaults"},
+ {0x0E, "prf:BitsPerPixel"},
+ {0x0F, "prf:ColorCapable"},
+ {0x10, "prf:CPU"},
+ {0x11, "prf:ImageCapable"},
+ {0x12, "prf:InputCharSet"},
+ {0x13, "prf:Keyboard"},
+ {0x15, "prf:Model"},
+ {0x16, "prf:OutputCharSet"},
+ {0x17, "prf:PointingResolution"},
+ {0x18, "prf:ScreenSize"},
+ {0x19, "prf:ScreenSizeChar"},
+ {0x1A, "prf:NumberOfSoftKeys"},
+ {0x1B, "prf:SoundOutputCapable"},
+ {0x1C, "prf:TextInputCapable"},
+ {0x1D, "prf:Vendor"},
+ {0x1E, "prf:VoiceInputCapable"},
+ {0x1F, "prf:AcceptDownloadableSoftware"},
+ {0x20, "prf:AudioInputEncoder"},
+ {0x21, "prf:DownloadableSoftwareSupport"},
+ {0x22, "prf:JavaEnabled"},
+ {0x23, "prf:JVMVersion"},
+ {0x24, "prf:MexeClassmark"},
+ {0x25, "prf:MexeSpec"},
+ {0x26, "prf:OSName"},
+ {0x27, "prf:OSVendor"},
+ {0x28, "prf:OSVersion"},
+ {0x29, "prf:RecipientAppAgent"},
+ {0x2A, "prf:SoftwareNumber"},
+ {0x2B, "prf:VideoInputEncoder"},
+ {0x2C, "prf:CurrentBearerService"},
+ {0x2D, "prf:SecuritySupport"},
+ {0x2E, "prf:SupportedBearers"},
+ {0x2F, "prf:WapDeviceClass"},
+ {0x30, "prf:WapPushMsgPriority"}, /* Deprecated */
+ {0x31, "prf:WapPushMsgSize"}, /* Deprecated */
+ {0x32, "prf:WapVersion"},
+ {0x33, "prf:WmlDeckSize"},
+ {0x34, "prf:WmlScriptLibraries"},
+ {0x35, "prf:WmlScriptVersion"},
+ {0x36, "prf:WmlVersion"},
+ {0x37, "prf:WtaiLibraries"},
+ {0x38, "prf:WtaVersion"},
+ {0x39, "prf:PixelAspectRatio"},
+ {0x3A, "prf:StandardFontProportional"},
+ {0x3B, "prf:WapSupportedApplications"}, /* Deprecated */
+ {0x3C, "prf:BluetoothProfile"},
+ {0x3D, "prf:MexeClassmarks"},
+ {0x3E, "prf:MexeSecureDomains"},
+
+ { 0x00, NULL }
+};
+
+/* CodePage 4 Core Vocabulary (continued) */
+static const value_string wbxml_uaprof_tags_cp4[] = {
+ {0x10, "prf:SupportedBluetoothVersion"},
+ {0x11, "prf:SupportedPictogramSet"},
+ {0x12, "prf:CcppAccept"},
+ {0x13, "prf:CcppAccept-Charset"},
+ {0x14, "prf:CcppAccept-Encoding"},
+ {0x15, "prf:CcppAccept-Language"},
+
+ { 0x00, NULL }
+};
+
+/* CodePage 2 BrowserUA */
+static const value_string wbxml_uaprof_tags_cp2[] = {
+ {0x05, "rdf:Description"},
+ {0x06, "rdf:Alt"},
+ {0x07, "rdf:Bag"},
+ {0x08, "rdf:Seq"},
+ {0x09, "rdf:li"},
+ {0x0A, "rdf:type"},
+ {0x0B, "prf:component"},
+ {0x0C, "prf:defaults"},
+ {0x0D, "prf:BrowserName"},
+ {0x0E, "prf:BrowserVersion"},
+ {0x0F, "prf:CcppAccept"}, /* Deprecated */
+ {0x10, "prf:CcppAccept-Charset"}, /* Deprecated */
+ {0x11, "prf:CcppAccept-Encoding"}, /* Deprecated */
+ {0x12, "prf:CcppAccept-Language"}, /* Deprecated */
+ {0x13, "prf:DownloadableBrowserApps"},
+ {0x14, "prf:FramesCapable"},
+ {0x15, "prf:HtmlVersion"},
+ {0x16, "prf:JavaAppletEnabled"},
+ {0x17, "prf:JavaScriptEnabled"},
+ {0x18, "prf:JavaScriptVersion"},
+ {0x19, "prf:PreferenceForFrames"},
+ {0x1A, "prf:TablesCapable"},
+ {0x1B, "Prf:XhtmlVersion"},
+ {0x1C, "prf:XhtmlModules"},
+
+ { 0x00, NULL }
+};
+
+/* CodePage 3 PushCharacteristics */
+static const value_string wbxml_uaprof_tags_cp3[] = {
+ {0x05, "rdf:Description"},
+ {0x06, "rdf:Alt"},
+ {0x07, "rdf:Bag"},
+ {0x08, "rdf:Seq"},
+ {0x09, "rdf:li"},
+ {0x0A, "rdf:type"},
+ {0x0B, "prf:component"},
+ {0x0C, "prf:defaults"},
+ {0x0D, "prf:Push-Accept"},
+ {0x0E, "prf:Push-Accept-Charset"},
+ {0x0F, "prf:Push-Accept-Encoding"},
+ {0x10, "prf:Push-Accept-Language"},
+ {0x11, "prf:Push-Accept-AppID"},
+ {0x12, "prf:Push-MsgSize"},
+ {0x13, "prf:Push-MaxPushReq"},
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+/* CodePage 0 RDF */
+static const value_string wbxml_uaprof_attrStart_cp0[] = {
+ {0x05, "ID"},
+ {0x06, "rdf:about"},
+ {0x07, "rdf:aboutEach"},
+ {0x08, "rdf:aboutEachPrefix"},
+ {0x09, "rdf:bagID"},
+ {0x0A, "rdf:type"},
+ {0x0B, "rdf:resource"},
+ {0x0C, "rdf:parseType='Literal'"},
+ {0x0D, "rdf:parseType='Resource'"},
+ {0x0E, "xml:lang"},
+ {0x0F, "xmlns:prf"},
+ {0x10, "xmlns:rdf"},
+
+ { 0x00, NULL }
+};
+
+/* CodePage 1 Core Vocabulary */
+static const value_string wbxml_uaprof_attrStart_cp1[] = {
+ {0x05, "rdf:resource"},
+ {0x06, "rdf:resource='http://www.wapforum.org/profiles/UAPROF/"
+ "ccppschema-20010430#HardwarePlatform'"},
+ {0x07, "rdf:resource='http://www.wapforum.org/profiles/UAPROF/"
+ "ccppschema-20010430#SoftwarePlatform'"},
+ {0x08, "rdf:resource='http://www.wapforum.org/profiles/UAPROF/"
+ "ccppschema-20010430#NetworkCharacteristics'"},
+ {0x09, "rdf:resource='http://www.wapforum.org/profiles/UAPROF/"
+ "ccppschema-20010430#WapCharacteristics'"},
+ {0x0A, "rdf:resource='http://www.wapforum.org/profiles/UAPROF/"
+ "ccppschema-20010430#BrowserUA'"},
+ {0x0B, "rdf:resource='http://www.wapforum.org/profiles/UAPROF/"
+ "ccppschema-20010430#PushCharacteristics'"},
+ {0x10, "prf:BitsPerPixel"},
+ {0x11, "prf:ColorCapable='Yes'"},
+ {0x12, "prf:ColorCapable='No'"},
+ {0x13, "prf:CPU"},
+ {0x14, "prf:ImageCapable='Yes'"},
+ {0x15, "prf:ImageCapable='No'"},
+ {0x16, "prf:InputCharSet"},
+ {0x17, "prf:Keyboard"},
+ {0x19, "prf:Model"},
+ {0x1A, "prf:OutputCharSet"},
+ {0x1B, "prf:PointingResolution"},
+ {0x1C, "prf:ScreenSize"},
+ {0x1D, "prf:ScreenSizeChar"},
+ {0x1E, "prf:NumberOfSoftKeys='Yes'"},
+ {0x20, "prf:SoundOutputCapable='Yes'"},
+ {0x21, "prf:SoundOutputCapable='No'"},
+ {0x22, "prf:TextInputCapable='Yes'"},
+ {0x23, "prf:TextInputCapable='No'"},
+ {0x24, "prf:Vendor"},
+ {0x25, "prf:VoiceInputCapable='Yes'"},
+ {0x26, "prf:VoiceInputCapable='No'"},
+ {0x27, "prf:PixelAspectRatio"},
+ {0x28, "prf:StandardFontProportional='Yes'"},
+ {0x29, "prf:StandardFontProportional='No'"},
+ {0x30, "prf:AcceptDownloadableSoftware='Yes'"},
+ {0x31, "prf:AcceptDownloadableSoftware='No'"},
+ {0x32, "prf:AudioInputEncoder"},
+ {0x33, "prf:DownloadableSoftwareSupport"},
+ {0x35, "prf:JavaEnabled='Yes'"},
+ {0x36, "prf:JavaEnabled='No'"},
+ {0x37, "prf:JVMVersion"},
+ {0x38, "prf:MexeClassmark"},
+ {0x39, "prf:MexeSpec"},
+ {0x3A, "prf:OSName"},
+ {0x3B, "prf:OSVendor"},
+ {0x3C, "prf:OSVersion"},
+ {0x3D, "prf:RecipientAppAgent"},
+ {0x3E, "prf:SoftwareNumber"},
+ {0x21, "prf:SoundOutputCapable='No'"},
+ {0x22, "prf:TextInputCapable='Yes'"},
+ {0x23, "prf:TextInputCapable='No'"},
+ {0x24, "prf:Vendor"},
+ {0x25, "prf:VoiceInputCapable='Yes'"},
+ {0x26, "prf:VoiceInputCapable='No'"},
+ {0x27, "prf:PixelAspectRatio"},
+ {0x28, "prf:StandardFontProportional='Yes'"},
+ {0x29, "prf:StandardFontProportional='No'"},
+ {0x30, "prf:AcceptDownloadableSoftware='Yes'"},
+ {0x31, "prf:AcceptDownloadableSoftware='No'"},
+ {0x32, "prf:AudioInputEncoder"},
+ {0x33, "prf:DownloadableSoftwareSupport"},
+ {0x35, "prf:JavaEnabled='Yes'"},
+ {0x36, "prf:JavaEnabled='No'"},
+ {0x37, "prf:JVMVersion"},
+ {0x38, "prf:MexeClassmark"},
+ {0x39, "prf:MexeSpec"},
+ {0x3A, "prf:OSName"},
+ {0x3B, "prf:OSVendor"},
+ {0x3C, "prf:OSVersion"},
+ {0x3D, "prf:RecipientAppAgent"},
+ {0x3E, "prf:SoftwareNumber"},
+ {0x3F, "prf:VideoInputEncoder"},
+ {0x50, "prf:CurrentBearerService"},
+ {0x51, "prf:SecuritySupport"},
+ {0x52, "prf:SupportedBearers"},
+ {0x60, "prf:WapDeviceClass"},
+ {0x61, "prf:WapPushMsgPriority"}, /* Deprecated */
+ {0x62, "prf:WapPushMsgSize"}, /* Deprecated */
+ {0x63, "prf:WapVersion"},
+ {0x64, "prf:WmlDeckSize"},
+ {0x65, "prf:WmlScriptLibraries"},
+ {0x66, "prf:WmlScriptVersion"},
+ {0x67, "prf:WmlVersion"},
+ {0x68, "prf:WtaiLibraries"},
+ {0x69, "prf:WtaVersion"},
+ {0x70, "prf:WapSupportedApplications"}, /* Deprecated */
+ {0x71, "prf:BluetoothProfile"},
+ {0x72, "prf:MexeClassmarks"},
+ {0x73, "prf:MexeSecureDomains='YES'"},
+ {0x74, "prf:MexeSecureDomains='NO'"},
+ {0x75, "prf:SupportedBluetoothVersion"},
+ {0x76, "prf:SupportedPictogramSet"},
+ {0x77, "prf:CcppAccept"},
+ {0x78, "prf:CcppAccept-Charset"},
+ {0x79, "prf:CcppAccept-Encoding"},
+ {0x7F, "prf:CcppAccept-Language"},
+
+ { 0x00, NULL }
+};
+
+/* CodePage 2 BrowserUA */
+static const value_string wbxml_uaprof_attrStart_cp2[] = {
+ {0x05, "prf:CcppAccept"}, /* Deprecated */
+ {0x06, "prf:CcppAccept-Charset"}, /* Deprecated */
+ {0x07, "prf:CcppAccept-Encoding"}, /* Deprecated */
+ {0x08, "prf:CcppAccept-Language"}, /* Deprecated */
+ {0x09, "prf:DownloadableBrowserApps"},
+ {0x0A, "prf:FramesCapable='Yes'"},
+ {0x0B, "prf:FramesCapable='No'"},
+ {0x0C, "prf:HtmlVersion='3.2'"},
+ {0x0D, "prf:HtmlVersion='4.0'"},
+ {0x0E, "prf:JavaAppletEnabled='Yes'"},
+ {0x0F, "prf:JavaAppletEnabled='No'"},
+ {0x10, "prf:JavaScriptEnabled='Yes'"},
+ {0x11, "prf:JavaScriptEnabled='No'"},
+ {0x12, "prf:JavaScriptVersion"},
+ {0x13, "prf:PreferenceForFrames='Yes'"},
+ {0x14, "prf:PreferenceForFrames='No'"},
+ {0x15, "prf:TablesCapable='Yes'"},
+ {0x16, "prf:TablesCapable='No'"},
+ {0x17, "prf:XhtmlVersion"},
+ {0x18, "prf:XhtmlModules"},
+ {0x19, "prf:BrowserName"},
+ {0x1A, "prf:BrowserVersion"},
+
+ { 0x00, NULL }
+};
+
+/* CodePage 3 PushCharacteristics */
+static const value_string wbxml_uaprof_attrStart_cp3[] = {
+ {0x05, "prf:Push-Accept"},
+ {0x06, "prf:Push-Accept-Charset"},
+ {0x07, "prf:Push-Accept-Encoding"},
+ {0x08, "prf:Push-Accept-Language"},
+ {0x09, "prf:Push-Accept-AppID"},
+ {0x0A, "prf:Push-MsgSize"},
+ {0x0B, "prf:Push-MaxPushReq"},
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+/* CodePage 0 RDF */
+static const value_string wbxml_uaprof_attrValue_cp0[] = {
+ {0x85, "rdf:Statement"},
+ {0x86, "http://"},
+ {0x87, "http://www."},
+ {0x88, "https://"},
+ {0x89, "https://www."},
+ {0x8A, "www."},
+ {0x8B, ".com/"},
+ {0x8C, ".edu/"},
+ {0x8D, ".net/"},
+ {0x8E, ".org/"},
+
+ { 0x00, NULL }
+};
+
+/* CodePage 1 CoreVocabularyAttrValue */
+static const value_string wbxml_uaprof_attrValue_cp1[] = {
+ {0x85, "No"},
+ {0x86, "Yes"},
+
+ { 0x00, NULL }
+};
+
+/* CodePage 2 BrowserUAAttrValue */
+static const value_string wbxml_uaprof_attrValue_cp2[] = {
+ {0x85, "No"},
+ {0x86, "Yes"},
+
+ { 0x00, NULL }
+};
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_uaprof_tags[] = {
+ { 0, wbxml_uaprof_tags_cp0 },
+ { 1, wbxml_uaprof_tags_cp1 },
+ { 2, wbxml_uaprof_tags_cp2 },
+ { 3, wbxml_uaprof_tags_cp3 },
+ { 4, wbxml_uaprof_tags_cp4 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_uaprof_attrStart[] = {
+ { 0, wbxml_uaprof_attrStart_cp0 },
+ { 1, wbxml_uaprof_attrStart_cp1 },
+ { 2, wbxml_uaprof_attrStart_cp2 },
+ { 3, wbxml_uaprof_attrStart_cp3 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_uaprof_attrValue[] = {
+ { 0, wbxml_uaprof_attrValue_cp0 },
+ { 1, wbxml_uaprof_attrValue_cp1 },
+ { 2, wbxml_uaprof_attrValue_cp2 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_uaprof_wap_248 = {
+ "User-Agent Profile (WAP-174, WAP-248)",
+ "UAProf (WAP-174, WAP-248)",
+ { NULL, NULL, NULL },
+ default_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ NULL,
+ wbxml_uaprof_tags,
+ wbxml_uaprof_attrStart,
+ wbxml_uaprof_attrValue
+};
+
+
+
+
+
+/* WV-CSP 1.0
+ *
+ * Wireless Village Client Server Protocol
+ ***************************************/
+
+/***** Global extension tokens *****/
+
+/***** Tag tokens *****/
+/* Common code page (0x00) */
+static const value_string wbxml_wv_csp_10_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "Acceptance" },
+ { 0x06, "AddList" },
+ { 0x07, "AddNickList" },
+ { 0x08, "Attribute" },
+ { 0x09, "AttributeList" },
+ { 0x0A, "ClientID" },
+ { 0x0B, "Code" },
+ { 0x0C, "ContactList" },
+ { 0x0D, "ContentData" },
+ { 0x0E, "ContentEncoding" },
+ { 0x0F, "ContentSize" },
+ { 0x10, "ContentType" },
+ { 0x11, "DateTime" },
+ { 0x12, "Description" },
+ { 0x13, "DetailedResult" },
+ { 0x14, "EntityList" },
+ { 0x15, "Group" },
+ { 0x16, "GroupID" },
+ { 0x17, "GroupList" },
+ { 0x18, "InUse" },
+ { 0x19, "Logo" },
+ { 0x1A, "MessageCount" },
+ { 0x1B, "MessageID" },
+ { 0x1C, "MessageURI" },
+ { 0x1D, "MSISDN" },
+ { 0x1E, "Name" },
+ { 0x1F, "NickList" },
+ { 0x20, "NickName" },
+ { 0x21, "Poll" },
+ { 0x22, "Presence" },
+ { 0x23, "PresenceSubList" },
+ { 0x24, "PresenceValue" },
+ { 0x25, "Property" },
+ { 0x26, "Qualifier" },
+ { 0x27, "Recipient" },
+ { 0x28, "RemoveList" },
+ { 0x29, "RemoveNickList" },
+ { 0x2A, "Result" },
+ { 0x2B, "ScreenName" },
+ { 0x2C, "Sender" },
+ { 0x2D, "Session" },
+ { 0x2E, "SessionDescriptor" },
+ { 0x2F, "SessionID" },
+ { 0x30, "SessionType" },
+ { 0x31, "Status" },
+ { 0x32, "Transaction" },
+ { 0x33, "TransactionContent" },
+ { 0x34, "TransactionDescriptor" },
+ { 0x35, "TransactionID" },
+ { 0x36, "TransactionMode" },
+ { 0x37, "URL" },
+ { 0x38, "URLList" },
+ { 0x39, "User" },
+ { 0x3A, "UserID" },
+ { 0x3B, "UserList" },
+ { 0x3C, "Validity" },
+ { 0x3D, "Value" },
+ { 0x3E, "WV-CSP-Message" },
+
+ { 0x00, NULL }
+};
+
+/* Access code page (0x01) */
+static const value_string wbxml_wv_csp_10_tags_cp1[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "AllFunctions" },
+ { 0x06, "AllFunctionsRequest" },
+ { 0x07, "CancelInvite-Request" },
+ { 0x08, "CancelInviteUser-Request" },
+ { 0x09, "Capability" },
+ { 0x0A, "CapabilityList" },
+ { 0x0B, "CapabilityRequest" },
+ { 0x0C, "ClientCapability-Request" },
+ { 0x0D, "ClientCapability-Response" },
+ { 0x0E, "DigestBytes" },
+ { 0x0F, "DigestSchema" },
+ { 0x10, "Disconnect" },
+ { 0x11, "Functions" },
+ { 0x12, "GetSPInfo-Request" },
+ { 0x13, "GetSPInfo-Response" },
+ { 0x14, "InviteID" },
+ { 0x15, "InviteNote" },
+ { 0x16, "Invite-Request" },
+ { 0x17, "Invite-Response" },
+ { 0x18, "InviteType" },
+ { 0x19, "InviteUser-Request" },
+ { 0x1A, "InviteUser-Response" },
+ { 0x1B, "KeepAlive-Request" },
+ { 0x1C, "KeepAliveTime" },
+ { 0x1D, "Login-Request" },
+ { 0x1E, "Login-Response" },
+ { 0x1F, "Logout-Request" },
+ { 0x20, "Nonce" },
+ { 0x21, "Password" },
+ { 0x22, "Polling-Request" },
+ { 0x23, "ResponseNote" },
+ { 0x24, "SearchElement" },
+ { 0x25, "SearchFindings" },
+ { 0x26, "SearchID" },
+ { 0x27, "SearchIndex" },
+ { 0x28, "SearchLimit" },
+ { 0x29, "SearchOnlineStatus" },
+ { 0x2A, "SearchPairList" },
+ { 0x2B, "Search-Request" },
+ { 0x2C, "Search-Response" },
+ { 0x2D, "SearchResult" },
+ { 0x2E, "Service-Request" },
+ { 0x2F, "Service-Response" },
+ { 0x30, "SessionCookie" },
+ { 0x31, "StopSearch-Request" },
+ { 0x32, "TimeToLive" },
+
+ { 0x00, NULL }
+};
+
+/* Service code page (0x02) */
+static const value_string wbxml_wv_csp_10_tags_cp2[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "ADDGM" },
+ { 0x06, "AttListFunc" },
+ { 0x07, "BLENT" },
+ { 0x08, "CAAUT" },
+ { 0x09, "CAINV" },
+ { 0x0A, "CALI" },
+ { 0x0B, "CCLI" },
+ { 0x0C, "ContListFunc" },
+ { 0x0D, "CREAG" },
+ { 0x0E, "DALI" },
+ { 0x0F, "DCLI" },
+ { 0x10, "DELGR" },
+ { 0x11, "FundamentalFeat" },
+ { 0x12, "FWMSG" },
+ { 0x13, "GALS" },
+ { 0x14, "GCLI" },
+ { 0x15, "GETGM" },
+ { 0x16, "GETGP" },
+ { 0x17, "GETLM" },
+ { 0x18, "GETM" },
+ { 0x19, "GETPR" },
+ { 0x1A, "GETSPI" },
+ { 0x1B, "GETWL" },
+ { 0x1C, "GLBLU" },
+ { 0x1D, "GRCHN" },
+ { 0x1E, "GroupAuthFunc" },
+ { 0x1F, "GroupFeat" },
+ { 0x20, "GroupMgmtFunc" },
+ { 0x21, "GroupUseFunc" },
+ { 0x22, "IMAuthFunc" },
+ { 0x23, "IMFeat" },
+ { 0x24, "IMReceiveFunc" },
+ { 0x25, "IMSendFunc" },
+ { 0x26, "INVIT" },
+ { 0x27, "InviteFunc" },
+ { 0x28, "MBRAC" },
+ { 0x29, "MCLS" },
+ { 0x2A, "MDELIV" },
+ { 0x2B, "NEWM" },
+ { 0x2C, "NOTIF" },
+ { 0x2D, "PresenceAuthFunc" },
+ { 0x2E, "PresenceDeliverFunc" },
+ { 0x2F, "PresenceFeat" },
+ { 0x30, "REACT" },
+ { 0x31, "REJCM" },
+ { 0x32, "REJEC" },
+ { 0x33, "RMVGM" },
+ { 0x34, "SearchFunc" },
+ { 0x35, "ServiceFunc" },
+ { 0x36, "SETD" },
+ { 0x37, "SETGP" },
+ { 0x38, "SRCH" },
+ { 0x39, "STSRC" },
+ { 0x3A, "SUBGCN" },
+ { 0x3B, "UPDPR" },
+ { 0x3C, "WVCSPFeat" },
+
+ { 0x00, NULL }
+};
+
+/* Client capability code page (0x03) */
+static const value_string wbxml_wv_csp_10_tags_cp3[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "AcceptedCharset" },
+ { 0x06, "AcceptedContentLength" },
+ { 0x07, "AcceptedContentType" },
+ { 0x08, "AcceptedTransferEncoding" },
+ { 0x09, "AnyContent" },
+ { 0x0A, "ClientType" },
+ { 0x0B, "InitialDeliveryMethod" },
+ { 0x0C, "MultiTrans" },
+ { 0x0D, "ParserSize" },
+ { 0x0E, "ServerPollMin" },
+ { 0x0F, "SupportedBearer" },
+ { 0x10, "SupportedCIRMethod" },
+ { 0x11, "TCPAddress" },
+ { 0x12, "TCPPort" },
+ { 0x13, "UDPPort" },
+
+ { 0x00, NULL }
+};
+
+/* Presence primitive code page (0x04) */
+static const value_string wbxml_wv_csp_10_tags_cp4[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "CancelAuth-Request" },
+ { 0x06, "ContactListProperties" },
+ { 0x07, "CreateAttributeList-Request" },
+ { 0x08, "CreateList-Request" },
+ { 0x09, "DefaultAttributeList" },
+ { 0x0A, "DefaultContactList" },
+ { 0x0B, "DefaultList" },
+ { 0x0C, "DeleteAttributeList-Request" },
+ { 0x0D, "DeleteList-Request" },
+ { 0x0E, "GetAttributeList-Request" },
+ { 0x0F, "GetAttributeList-Response" },
+ { 0x10, "GetList-Request" },
+ { 0x11, "GetList-Response" },
+ { 0x12, "GetPresence-Request" },
+ { 0x13, "GetPresence-Response" },
+ { 0x14, "GetWatcherList-Request" },
+ { 0x15, "GetWatcherList-Response" },
+ { 0x16, "ListManage-Request" },
+ { 0x17, "ListManage-Response" },
+ { 0x18, "Presence" },
+ { 0x19, "PresenceAuth-Request" },
+ { 0x1A, "PresenceAuth-Response" },
+ { 0x1B, "PresenceNotification-Request" },
+ { 0x1C, "PresenceValueList" },
+ { 0x1D, "SubscribePresence-Request" },
+ { 0x1E, "UnsubscribePresence-Request" },
+ { 0x1F, "UpdatePresence-Request" },
+
+ { 0x00, NULL }
+};
+
+/* Presence attribute code page (0x05) */
+static const value_string wbxml_wv_csp_10_tags_cp5[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "Accuracy" },
+ { 0x06, "Address" },
+ { 0x07, "AddrPref" },
+ { 0x08, "Alias" },
+ { 0x09, "Altitude" },
+ { 0x0A, "Building" },
+ { 0x0B, "CAddr" },
+ { 0x0C, "City" },
+ { 0x0D, "ClientInfo" },
+ { 0x0E, "ClientProducer" },
+ { 0x0F, "ClientType" },
+ { 0x10, "ClientVersion" },
+ { 0x11, "CommC" },
+ { 0x12, "CommCap" },
+ { 0x13, "ContactInfo" },
+ { 0x14, "ContainedvCard" },
+ { 0x15, "Country" },
+ { 0x16, "Crossing1" },
+ { 0x17, "Crossing2" },
+ { 0x18, "DevManufacturer" },
+ { 0x19, "DirectContent" },
+ { 0x1A, "FreeTextLocation" },
+ { 0x1B, "GeoLocation" },
+ { 0x1C, "Language" },
+ { 0x1D, "Latitude" },
+ { 0x1E, "Longitude" },
+ { 0x1F, "Model" },
+ { 0x20, "NamedArea" },
+ { 0x21, "OnlineStatus" },
+ { 0x22, "PLMN" },
+ { 0x23, "PrefC" },
+ { 0x24, "PreferredContacts" },
+ { 0x25, "PreferredLanguage" },
+ { 0x26, "ReferredContent" },
+ { 0x27, "ReferredvCard" },
+ { 0x28, "Registration" },
+ { 0x29, "StatusContent" },
+ { 0x2A, "StatusMood" },
+ { 0x2B, "StatusText" },
+ { 0x2C, "Street" },
+ { 0x2D, "TimeZone" },
+ { 0x2E, "UserAvailability" },
+
+ { 0x00, NULL }
+};
+
+/* Messaging code page (0x06) */
+static const value_string wbxml_wv_csp_10_tags_cp6[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "BlockList" },
+ { 0x06, "BlockUser-Request" },
+ { 0x07, "DeliveryMethod" },
+ { 0x08, "DeliveryReport" },
+ { 0x09, "DeliveryReport-Request" },
+ { 0x0A, "ForwardMessage-Request" },
+ { 0x0B, "GetBlockedList-Request" },
+ { 0x0C, "GetBlockedList-Response" },
+ { 0x0D, "GetMessageList-Request" },
+ { 0x0E, "GetMessageList-Response" },
+ { 0x0F, "GetMessage-Request" },
+ { 0x10, "GetMessage-Response" },
+ { 0x11, "GrantList" },
+ { 0x12, "MessageDelivered" },
+ { 0x13, "MessageInfo" },
+ { 0x14, "MessageNotification" },
+ { 0x15, "NewMessage" },
+ { 0x16, "RejectMessage-Request" },
+ { 0x17, "SendMessage-Request" },
+ { 0x18, "SendMessage-Response" },
+ { 0x19, "SetDeliveryMethod-Request" },
+
+ { 0x00, NULL }
+};
+
+/* Group code page (0x07) */
+static const value_string wbxml_wv_csp_10_tags_cp7[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "AddGroupMembers-Request" },
+ { 0x06, "Admin" },
+ { 0x07, "CreateGroup-Request" },
+ { 0x08, "DeleteGroup-Request" },
+ { 0x09, "GetGroupMembers-Request" },
+ { 0x0A, "GetGroupMembers-Response" },
+ { 0x0B, "GetGroupProps-Request" },
+ { 0x0C, "GetGroupProps-Response" },
+ { 0x0D, "GroupChangeNotice" },
+ { 0x0E, "GroupProperties" },
+ { 0x0F, "Joined" },
+ { 0x10, "JoinedRequest" },
+ { 0x11, "JoinGroup-Request" },
+ { 0x12, "JoinGroup-Response" },
+ { 0x13, "LeaveGroup-Request" },
+ { 0x14, "LeaveGroup-Response" },
+ { 0x15, "Left" },
+ { 0x16, "MemberAccess-Request" },
+ { 0x17, "Mod" },
+ { 0x18, "OwnProperties" },
+ { 0x19, "RejectList-Request" },
+ { 0x1A, "RejectList-Response" },
+ { 0x1B, "RemoveGroupMembers-Request" },
+ { 0x1C, "SetGroupProps-Request" },
+ { 0x1D, "SubscribeGroupNotice-Request" },
+ { 0x1E, "SubscribeGroupNotice-Response" },
+ { 0x1F, "Users" },
+ { 0x20, "WelcomeNote" },
+
+ { 0x00, NULL }
+};
+
+/*
+ * Attribute start tokens
+ */
+/* common code page (0x00) */
+static const value_string wbxml_wv_csp_10_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "xmlns='http://www.wireless-village.org/CSP'" },
+ { 0x06, "xmlns='http://www.wireless-village.org/PA'" },
+ { 0x07, "xmlns='http://www.wireless-village.org/TRC'" },
+
+ { 0x00, NULL }
+};
+
+/*
+ * Attribute value tokens
+ */
+/* Common value tokens (0x00) */
+static const value_string wbxml_wv_csp_10_attrValue_cp0[] = {
+ /* 0x80 -- 0x84 GLOBAL */
+ { 0x85, "AccessType" },
+ { 0x86, "ActiveUsers" },
+ { 0x87, "Admin" },
+ { 0x88, "application/" },
+ { 0x89, "application/vnd.wap.mms-message" },
+ { 0x8A, "application/x-sms" },
+ { 0x8B, "BASE64" },
+ { 0x8C, "Closed" },
+ { 0x8D, "Default" },
+ { 0x8E, "DisplayName" },
+ { 0x8F, "False (No)" },
+ { 0x90, "Get" },
+ { 0x91, "Group (GR)" },
+ { 0x92, "http://" },
+ { 0x93, "https://" },
+ { 0x94, "image/" },
+ { 0x95, "Inband" },
+ { 0x96, "Instant Messaging (IM)" },
+ { 0x97, "MaxActiveUsers" },
+ { 0x98, "Mod" },
+ { 0x99, "Name" },
+ { 0x9A, "None" },
+ { 0x9B, "Notify/Get" },
+ { 0x9C, "Open" },
+ { 0x9D, "Outband" },
+ { 0x9E, "Presence (PR)" },
+ { 0x9F, "Private" },
+ { 0xA0, "PrivateMessaging" },
+ { 0xA1, "PrivilegeLevel" },
+ { 0xA2, "Public" },
+ { 0xA3, "Push" },
+ { 0xA4, "Request" },
+ { 0xA5, "Response" },
+ { 0xA6, "ScreenName" },
+ { 0xA7, "Searchable" },
+ { 0xA8, "Set" },
+ { 0xA9, "Shared Content (SC)" },
+ { 0xAA, "text/" },
+ { 0xAB, "text/plain" },
+ { 0xAC, "text/x-vCalendar" },
+ { 0xAD, "text/x-vCard" },
+ { 0xAE, "Topic" },
+ { 0xAF, "True (Yes)" },
+ { 0xB0, "Type" },
+ { 0xB1, "Unset" },
+ { 0xB2, "User (US)" },
+ { 0xB3, "www.wireless-village.org" },
+
+ { 0x00, NULL }
+};
+
+/* Access value tokens (0x01) */
+static const value_string wbxml_wv_csp_10_attrValue_cp1[] = {
+ /* 0x80 -- 0x84 GLOBAL */
+ { 0x85, "GROUP_ID" },
+ { 0x86, "GROUP_NAME" },
+ { 0x87, "GROUP_TOPIC" },
+ { 0x88, "GROUP_USER_ID_JOINED" },
+ { 0x89, "HTTP" },
+ { 0x8A, "SMS" },
+ { 0x8B, "STCP" },
+ { 0x8C, "SUDP" },
+ { 0x8D, "USER_ALIAS" },
+ { 0x8E, "USER_EMAIL_ADDRESS" },
+ { 0x8F, "USER_FIRST_NAME" },
+ { 0x90, "USER_ID" },
+ { 0x91, "USER_LAST_NAME" },
+ { 0x92, "USER_MOBILE_NUMBER" },
+ { 0x93, "WAPSMS" },
+ { 0x94, "WAPUDP" },
+ { 0x95, "WSP" },
+
+ { 0x00, NULL }
+};
+
+/* Presence value tokens (0x05) */
+static const value_string wbxml_wv_csp_10_attrValue_cp5[] = {
+ /* 0x80 -- 0x84 GLOBAL */
+ { 0x85, "ANGRY" },
+ { 0x86, "ANXIOUS" },
+ { 0x87, "ASHAMED" },
+ { 0x88, "AUDIO_CALL" },
+ { 0x89, "AVAILABLE" },
+ { 0x8A, "BORED" },
+ { 0x8B, "CALL" },
+ { 0x8C, "CLI" },
+ { 0x8D, "COMPUTER" },
+ { 0x8E, "DISCREET" },
+ { 0x8F, "EMAIL" },
+ { 0x90, "EXCITED" },
+ { 0x91, "HAPPY" },
+ { 0x92, "IM" },
+ { 0x93, "IM_OFFLINE" },
+ { 0x94, "IM_ONLINE" },
+ { 0x95, "IN_LOVE" },
+ { 0x96, "INVINCIBLE" },
+ { 0x97, "JEALOUS" },
+ { 0x98, "MMS" },
+ { 0x99, "MOBILE_PHONE" },
+ { 0x9A, "NOT_AVAILABLE" },
+ { 0x9B, "OTHER" },
+ { 0x9C, "PDA" },
+ { 0x9D, "SAD" },
+ { 0x9E, "SLEEPY" },
+ { 0x9F, "SMS" },
+ { 0xA0, "VIDEO_CALL" },
+ { 0xA1, "VIDEO_STREAM" },
+
+ { 0x00, NULL }
+};
+
+
+/***** Token code page aggregation *****/
+static const value_valuestring wbxml_wv_csp_10_tags[] = {
+ { 0, wbxml_wv_csp_10_tags_cp0 },
+ { 1, wbxml_wv_csp_10_tags_cp1 },
+ { 2, wbxml_wv_csp_10_tags_cp2 },
+ { 3, wbxml_wv_csp_10_tags_cp3 },
+ { 4, wbxml_wv_csp_10_tags_cp4 },
+ { 5, wbxml_wv_csp_10_tags_cp5 },
+ { 6, wbxml_wv_csp_10_tags_cp6 },
+ { 7, wbxml_wv_csp_10_tags_cp7 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wv_csp_10_attrStart[] = {
+ { 0, wbxml_wv_csp_10_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wv_csp_10_attrValue[] = {
+ { 0, wbxml_wv_csp_10_attrValue_cp0 },
+ { 1, wbxml_wv_csp_10_attrValue_cp1 },
+ { 5, wbxml_wv_csp_10_attrValue_cp5 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_wv_cspc_10 = {
+ "Wireless-Village Client-Server Protocol 1.0",
+ "WV-CSP 1.0",
+ { NULL, NULL, NULL },
+ wv_csp10_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ NULL,
+ wbxml_wv_csp_10_tags,
+ wbxml_wv_csp_10_attrStart,
+ wbxml_wv_csp_10_attrValue
+};
+
+
+
+
+
+/* WV-CSP 1.1
+ *
+ * Wireless Village Client Server Protocol
+ ***************************************/
+
+/***** Global extension tokens *****/
+static const value_string wbxml_wv_csp_11_global_cp0[] = {
+ { 0x80, "Common Value" }, /* EXT_T_0 */
+
+ { 0x00, NULL }
+};
+
+/***** Tag tokens *****/
+/* Common code page */
+static const value_string wbxml_wv_csp_11_tags_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "Acceptance" },
+ { 0x06, "AddList" },
+ { 0x07, "AddNickList" },
+ { 0x08, "SName" }, /* Was: Attribute */
+ { 0x09, "WV-CSP-Message" }, /* Was: AttributeList */
+ { 0x0A, "ClientID" },
+ { 0x0B, "Code" },
+ { 0x0C, "ContactList" },
+ { 0x0D, "ContentData" },
+ { 0x0E, "ContentEncoding" },
+ { 0x0F, "ContentSize" },
+ { 0x10, "ContentType" },
+ { 0x11, "DateTime" },
+ { 0x12, "Description" },
+ { 0x13, "DetailedResult" },
+ { 0x14, "EntityList" },
+ { 0x15, "Group" },
+ { 0x16, "GroupID" },
+ { 0x17, "GroupList" },
+ { 0x18, "InUse" },
+ { 0x19, "Logo" },
+ { 0x1A, "MessageCount" },
+ { 0x1B, "MessageID" },
+ { 0x1C, "MessageURI" },
+ { 0x1D, "MSISDN" },
+ { 0x1E, "Name" },
+ { 0x1F, "NickList" },
+ { 0x20, "NickName" },
+ { 0x21, "Poll" },
+ { 0x22, "Presence" },
+ { 0x23, "PresenceSubList" },
+ { 0x24, "PresenceValue" },
+ { 0x25, "Property" },
+ { 0x26, "Qualifier" },
+ { 0x27, "Recipient" },
+ { 0x28, "RemoveList" },
+ { 0x29, "RemoveNickList" },
+ { 0x2A, "Result" },
+ { 0x2B, "ScreenName" },
+ { 0x2C, "Sender" },
+ { 0x2D, "Session" },
+ { 0x2E, "SessionDescriptor" },
+ { 0x2F, "SessionID" },
+ { 0x30, "SessionType" },
+ { 0x31, "Status" },
+ { 0x32, "Transaction" },
+ { 0x33, "TransactionContent" },
+ { 0x34, "TransactionDescriptor" },
+ { 0x35, "TransactionID" },
+ { 0x36, "TransactionMode" },
+ { 0x37, "URL" },
+ { 0x38, "URLList" },
+ { 0x39, "User" },
+ { 0x3A, "UserID" },
+ { 0x3B, "UserList" },
+ { 0x3C, "Validity" },
+ { 0x3D, "Value" },
+ /* 0x3E - Removed: WV-CSP-Message */
+
+ { 0x00, NULL }
+};
+
+/* Access code page */
+static const value_string wbxml_wv_csp_11_tags_cp1[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "AllFunctions" },
+ { 0x06, "AllFunctionsRequest" },
+ { 0x07, "CancelInvite-Request" },
+ { 0x08, "CancelInviteUser-Request" },
+ { 0x09, "Capability" },
+ { 0x0A, "CapabilityList" },
+ { 0x0B, "CapabilityRequest" },
+ { 0x0C, "ClientCapability-Request" },
+ { 0x0D, "ClientCapability-Response" },
+ { 0x0E, "DigestBytes" },
+ { 0x0F, "DigestSchema" },
+ { 0x10, "Disconnect" },
+ { 0x11, "Functions" },
+ { 0x12, "GetSPInfo-Request" },
+ { 0x13, "GetSPInfo-Response" },
+ { 0x14, "InviteID" },
+ { 0x15, "InviteNote" },
+ { 0x16, "Invite-Request" },
+ { 0x17, "Invite-Response" },
+ { 0x18, "InviteType" },
+ { 0x19, "InviteUser-Request" },
+ { 0x1A, "InviteUser-Response" },
+ { 0x1B, "KeepAlive-Request" },
+ { 0x1C, "KeepAliveTime" },
+ { 0x1D, "Login-Request" },
+ { 0x1E, "Login-Response" },
+ { 0x1F, "Logout-Request" },
+ { 0x20, "Nonce" },
+ { 0x21, "Password" },
+ { 0x22, "Polling-Request" },
+ { 0x23, "ResponseNote" },
+ { 0x24, "SearchElement" },
+ { 0x25, "SearchFindings" },
+ { 0x26, "SearchID" },
+ { 0x27, "SearchIndex" },
+ { 0x28, "SearchLimit" },
+ { 0x29, "KeepAlive-Response" }, /* Was: SearchOnlineStatus */
+ { 0x2A, "SearchPairList" },
+ { 0x2B, "Search-Request" },
+ { 0x2C, "Search-Response" },
+ { 0x2D, "SearchResult" },
+ { 0x2E, "Service-Request" },
+ { 0x2F, "Service-Response" },
+ { 0x30, "SessionCookie" },
+ { 0x31, "StopSearch-Request" },
+ { 0x32, "TimeToLive" },
+ /* New in WV-CSP 1.1 */
+ { 0x33, "SearchString" },
+ { 0x34, "CompletionFlag" },
+
+ { 0x00, NULL }
+};
+
+/* Service code page */
+/* Same as cp2 of WV-CSP 1.0 */
+#define wbxml_wv_csp_11_tags_cp2 wbxml_wv_csp_10_tags_cp2
+
+/* Client capability code page */
+static const value_string wbxml_wv_csp_11_tags_cp3[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "AcceptedCharset" },
+ { 0x06, "AcceptedContentLength" },
+ { 0x07, "AcceptedContentType" },
+ { 0x08, "AcceptedTransferEncoding" },
+ { 0x09, "AnyContent" },
+ { 0x0A, "DefaultLanguage" }, /* Was: ClientType */
+ { 0x0B, "InitialDeliveryMethod" },
+ { 0x0C, "MultiTrans" },
+ { 0x0D, "ParserSize" },
+ { 0x0E, "ServerPollMin" },
+ { 0x0F, "SupportedBearer" },
+ { 0x10, "SupportedCIRMethod" },
+ { 0x11, "TCPAddress" },
+ { 0x12, "TCPPort" },
+ { 0x13, "UDPPort" },
+
+ { 0x00, NULL }
+};
+
+/* Presence primitive code page */
+static const value_string wbxml_wv_csp_11_tags_cp4[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "CancelAuth-Request" },
+ { 0x06, "ContactListProperties" },
+ { 0x07, "CreateAttributeList-Request" },
+ { 0x08, "CreateList-Request" },
+ { 0x09, "DefaultAttributeList" },
+ { 0x0A, "DefaultContactList" },
+ { 0x0B, "DefaultList" },
+ { 0x0C, "DeleteAttributeList-Request" },
+ { 0x0D, "DeleteList-Request" },
+ { 0x0E, "GetAttributeList-Request" },
+ { 0x0F, "GetAttributeList-Response" },
+ { 0x10, "GetList-Request" },
+ { 0x11, "GetList-Response" },
+ { 0x12, "GetPresence-Request" },
+ { 0x13, "GetPresence-Response" },
+ { 0x14, "GetWatcherList-Request" },
+ { 0x15, "GetWatcherList-Response" },
+ { 0x16, "ListManage-Request" },
+ { 0x17, "ListManage-Response" },
+ { 0x18, "UnsubscribePresence-Request" }, /* Was: Presence */
+ { 0x19, "PresenceAuth-Request" },
+ { 0x1A, "PresenceAuth-User" }, /* Was: PresenceAuth-Response */
+ { 0x1B, "PresenceNotification-Request" },
+ { 0x1C, "UpdatePresence-Request" }, /* Was: PresenceValueList */
+ { 0x1D, "SubscribePresence-Request" },
+ /* 0x1E - Removed: UnsubscribePresence-Request */
+ /* 0x1F - Removed: UpdatePresence-Request */
+
+ { 0x00, NULL }
+};
+
+/* Presence attribute code page */
+static const value_string wbxml_wv_csp_11_tags_cp5[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "Accuracy" },
+ { 0x06, "Address" },
+ { 0x07, "AddrPref" },
+ { 0x08, "Alias" },
+ { 0x09, "Altitude" },
+ { 0x0A, "Building" },
+ { 0x0B, "Caddr" },
+ { 0x0C, "City" },
+ { 0x0D, "ClientInfo" },
+ { 0x0E, "ClientProducer" },
+ { 0x0F, "ClientType" },
+ { 0x10, "ClientVersion" },
+ { 0x11, "CommC" },
+ { 0x12, "CommCap" },
+ { 0x13, "ContactInfo" },
+ { 0x14, "ContainedvCard" },
+ { 0x15, "Country" },
+ { 0x16, "Crossing1" },
+ { 0x17, "Crossing2" },
+ { 0x18, "DevManufacturer" },
+ { 0x19, "DirectContent" },
+ { 0x1A, "FreeTextLocation" },
+ { 0x1B, "GeoLocation" },
+ { 0x1C, "Language" },
+ { 0x1D, "Latitude" },
+ { 0x1E, "Longitude" },
+ { 0x1F, "Model" },
+ { 0x20, "NamedArea" },
+ { 0x21, "OnlineStatus" },
+ { 0x22, "PLMN" },
+ { 0x23, "PrefC" },
+ { 0x24, "PreferredContacts" },
+ { 0x25, "PreferredLanguage" },
+ { 0x26, "ReferredContent" },
+ { 0x27, "ReferredvCard" },
+ { 0x28, "Registration" },
+ { 0x29, "StatusContent" },
+ { 0x2A, "StatusMood" },
+ { 0x2B, "StatusText" },
+ { 0x2C, "Street" },
+ { 0x2D, "TimeZone" },
+ { 0x2E, "UserAvailability" },
+ /* New in WV-CSP 1.1 */
+ { 0x2F, "Cap" },
+ { 0x30, "Cname" },
+ { 0x31, "Contact" },
+ { 0x32, "Cpriority" },
+ { 0x33, "Cstatus" },
+ { 0x34, "Note" },
+ { 0x35, "Zone" },
+
+ { 0x00, NULL }
+};
+
+/* Messaging code page */
+static const value_string wbxml_wv_csp_11_tags_cp6[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "BlockList" },
+ { 0x06, "BlockUser-Request" },
+ { 0x07, "DeliveryMethod" },
+ { 0x08, "DeliveryReport" },
+ { 0x09, "DeliveryReport-Request" },
+ { 0x0A, "ForwardMessage-Request" },
+ { 0x0B, "GetBlockedList-Request" },
+ { 0x0C, "GetBlockedList-Response" },
+ { 0x0D, "GetMessageList-Request" },
+ { 0x0E, "GetMessageList-Response" },
+ { 0x0F, "GetMessage-Request" },
+ { 0x10, "GetMessage-Response" },
+ { 0x11, "GrantList" },
+ { 0x12, "MessageDelivered" },
+ { 0x13, "MessageInfo" },
+ { 0x14, "MessageNotification" },
+ { 0x15, "NewMessage" },
+ { 0x16, "RejectMessage-Request" },
+ { 0x17, "SendMessage-Request" },
+ { 0x18, "SendMessage-Response" },
+ { 0x19, "SetDeliveryMethod-Request" },
+ /* New in WV-CSP 1.1 */
+ { 0x1A, "DeliveryTime" },
+
+ { 0x00, NULL }
+};
+
+/* Group code page */
+static const value_string wbxml_wv_csp_11_tags_cp7[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "AddGroupMembers-Request" },
+ { 0x06, "Admin" },
+ { 0x07, "CreateGroup-Request" },
+ { 0x08, "DeleteGroup-Request" },
+ { 0x09, "GetGroupMembers-Request" },
+ { 0x0A, "GetGroupMembers-Response" },
+ { 0x0B, "GetGroupProps-Request" },
+ { 0x0C, "GetGroupProps-Response" },
+ { 0x0D, "GroupChangeNotice" },
+ { 0x0E, "GroupProperties" },
+ { 0x0F, "Joined" },
+ { 0x10, "JoinedRequest" },
+ { 0x11, "JoinGroup-Request" },
+ { 0x12, "JoinGroup-Response" },
+ { 0x13, "LeaveGroup-Request" },
+ { 0x14, "LeaveGroup-Response" },
+ { 0x15, "Left" },
+ { 0x16, "MemberAccess-Request" },
+ { 0x17, "Mod" },
+ { 0x18, "OwnProperties" },
+ { 0x19, "RejectList-Request" },
+ { 0x1A, "RejectList-Response" },
+ { 0x1B, "RemoveGroupMembers-Request" },
+ { 0x1C, "SetGroupProps-Request" },
+ { 0x1D, "SubscribeGroupNotice-Request" },
+ { 0x1E, "SubscribeGroupNotice-Response" },
+ { 0x1F, "Users" },
+ { 0x20, "WelcomeNote" },
+ /* New in WV-CSP 1.1 */
+ { 0x21, "JoinGroup" },
+ { 0x22, "SubscribeNotification" },
+ { 0x23, "SubscribeType" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+/* Common code page */
+/* Same as cp0 of WV-CSP 1.0 */
+#define wbxml_wv_csp_11_attrStart_cp0 wbxml_wv_csp_10_attrStart_cp0
+
+/***** Attribute Value tokens *****/
+/*
+ * Element value tokens
+ *
+ * NOTE - WV-CSP uses the EXT_T_0 token in a peculiar way: the mb_u_int32
+ * does *not* reference an offset in the string table, but it refers to
+ * the index in the following value_string.
+ *
+ * Please note that:
+ * - Values 'T' and 'F' are Boolean values representing "True" and "False"
+ * (or "Yes" and "No" in some circumstances) respectively.
+ * - Values 'GR', 'IM', 'PR', 'SC', 'GM' and 'US' are enumerated values
+ * representing "Group", "Instant Messaging", "Presence", "Shared Content",
+ * "Group membership" and "User" respectively.
+ * - Values 'G', 'S' and 'U' are enumerated values representing "Get", "Set"
+ * and "Unset" respectively.
+ * - Values 'N' and 'P' are enumerated values representing "Notify/Get" and
+ * "Push" respectively.
+ *
+ * I repeat: this is NOT a attrValue[] array hence it is not called
+ * wbxml_wv_XXX but vals_wv_XXX.
+ *
+ * Result: the attribute value token definitions from WV-CSP 1.0 are dropped.
+ */
+static const value_string vals_wv_csp_11_element_value_tokens[] = {
+ /*
+ * Common value tokens
+ */
+ { 0x00, "AccessType" },
+ { 0x01, "ActiveUsers" },
+ { 0x02, "Admin" },
+ { 0x03, "application/" },
+ { 0x04, "application/vnd.wap.mms-message" },
+ { 0x05, "application/x-sms" },
+ { 0x06, "AutoJoin" },
+ { 0x07, "BASE64" },
+ { 0x08, "Closed" },
+ { 0x09, "Default" },
+ { 0x0A, "DisplayName" },
+ { 0x0B, "F" },
+ { 0x0C, "G" },
+ { 0x0D, "GR" },
+ { 0x0E, "http://" },
+ { 0x0F, "https://" },
+ { 0x10, "image/" },
+ { 0x11, "Inband" },
+ { 0x12, "IM" },
+ { 0x13, "MaxActiveUsers" },
+ { 0x14, "Mod" },
+ { 0x15, "Name" },
+ { 0x16, "None" },
+ { 0x17, "N" },
+ { 0x18, "Open" },
+ { 0x19, "Outband" },
+ { 0x1A, "PR" },
+ { 0x1B, "Private" },
+ { 0x1C, "PrivateMessaging" },
+ { 0x1D, "PrivilegeLevel" },
+ { 0x1E, "Public" },
+ { 0x1F, "P" },
+ { 0x20, "Request" },
+ { 0x21, "Response" },
+ { 0x22, "Restricted" },
+ { 0x23, "ScreenName" },
+ { 0x24, "Searchable" },
+ { 0x25, "S" },
+ { 0x26, "SC" },
+ { 0x27, "text/" },
+ { 0x28, "text/plain" },
+ { 0x29, "text/x-vCalendar" },
+ { 0x2A, "text/x-vCard" },
+ { 0x2B, "Topic" },
+ { 0x2C, "T" },
+ { 0x2D, "Type" },
+ { 0x2E, "U" },
+ { 0x2F, "US" },
+ { 0x30, "www.wireless-village.org" },
+ /*
+ * Access value tokens
+ */
+ { 0x3D, "GROUP_ID" },
+ { 0x3E, "GROUP_NAME" },
+ { 0x3F, "GROUP_TOPIC" },
+ { 0x40, "GROUP_USER_ID_JOINED" },
+ { 0x41, "GROUP_USER_ID_OWNER" },
+ { 0x42, "HTTP" },
+ { 0x43, "SMS" },
+ { 0x44, "STCP" },
+ { 0x45, "SUDP" },
+ { 0x46, "USER_ALIAS" },
+ { 0x47, "USER_EMAIL_ADDRESS" },
+ { 0x48, "USER_FIRST_NAME" },
+ { 0x49, "USER_ID" },
+ { 0x4A, "USER_LAST_NAME" },
+ { 0x4B, "USER_MOBILE_NUMBER" },
+ { 0x4C, "USER_ONLINE_STATUS" },
+ { 0x4D, "WAPSMS" },
+ { 0x4E, "WAPUDP" },
+ { 0x4F, "WSP" },
+ /*
+ * Presence value tokens
+ */
+ { 0x5B, "ANGRY" },
+ { 0x5C, "ANXIOUS" },
+ { 0x5D, "ASHAMED" },
+ { 0x5E, "AUDIO_CALL" },
+ { 0x5F, "AVAILABLE" },
+ { 0x60, "BORED" },
+ { 0x61, "CALL" },
+ { 0x62, "CLI" },
+ { 0x63, "COMPUTER" },
+ { 0x64, "DISCREET" },
+ { 0x65, "EMAIL" },
+ { 0x66, "EXCITED" },
+ { 0x67, "HAPPY" },
+ { 0x68, "IM" },
+ { 0x69, "IM_OFFLINE" },
+ { 0x6A, "IM_ONLINE" },
+ { 0x6B, "IN_LOVE" },
+ { 0x6C, "INVINCIBLE" },
+ { 0x6D, "JEALOUS" },
+ { 0x6E, "MMS" },
+ { 0x6F, "MOBILE_PHONE" },
+ { 0x70, "NOT_AVAILABLE" },
+ { 0x71, "OTHER" },
+ { 0x72, "PDA" },
+ { 0x73, "SAD" },
+ { 0x74, "SLEEPY" },
+ { 0x75, "SMS" },
+ { 0x76, "VIDEO_CALL" },
+ { 0x77, "VIDEO_STREAM" },
+
+ { 0x00, NULL }
+};
+
+
+/***** Token code page aggregation *****/
+
+static char *
+ext_t_0_wv_cspc_11(tvbuff_t *tvb _U_, guint32 value, guint32 str_tbl _U_)
+{
+ char *str = g_strdup_printf("Common Value: '%s'",
+ val_to_str(value, vals_wv_csp_11_element_value_tokens,
+ "<Unknown WV-CSP 1.1 Common Value token 0x%X>"));
+ return str;
+}
+
+static const value_valuestring wbxml_wv_csp_11_global[] = {
+ { 0, wbxml_wv_csp_11_global_cp0 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wv_csp_11_tags[] = {
+ { 0, wbxml_wv_csp_11_tags_cp0 },
+ { 1, wbxml_wv_csp_11_tags_cp1 },
+ { 2, wbxml_wv_csp_11_tags_cp2 },
+ { 3, wbxml_wv_csp_11_tags_cp3 },
+ { 4, wbxml_wv_csp_11_tags_cp4 },
+ { 5, wbxml_wv_csp_11_tags_cp5 },
+ { 6, wbxml_wv_csp_11_tags_cp6 },
+ { 7, wbxml_wv_csp_11_tags_cp7 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wv_csp_11_attrStart[] = {
+ { 0, wbxml_wv_csp_11_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_wv_cspc_11 = {
+ "Wireless-Village Client-Server Protocol 1.1",
+ "WV-CSP 1.1",
+ { ext_t_0_wv_cspc_11, NULL, NULL },
+ wv_csp11_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ wbxml_wv_csp_11_global,
+ wbxml_wv_csp_11_tags,
+ wbxml_wv_csp_11_attrStart,
+ NULL
+};
+
+
+
+
+
+/* WV-CSP 1.2
+ *
+ * Wireless Village Client Server Protocol
+ ***************************************/
+#ifdef Remove_this_comment_when_WV_CSP_will_be_an_approved_spec
+
+/***** Global extension tokens *****/
+/* Same as WV-CSP 1.1 */
+
+/***** Tag tokens *****/
+/* Common code page */
+/* Same as cp0 of WV-CSP 1.1 */
+#define wbxml_wv_csp_12_tags_cp0 wbxml_wv_csp_11_tags_cp0
+/* Note that the table continues in code page 0x09 */
+
+/* Access code page (0x01) */
+static const value_string wbxml_wv_csp_12_tags_cp1[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "AllFunctions" },
+ { 0x06, "AllFunctionsRequest" },
+ { 0x07, "CancelInvite-Request" },
+ { 0x08, "CancelInviteUser-Request" },
+ { 0x09, "Capability" },
+ { 0x0A, "CapabilityList" },
+ { 0x0B, "CapabilityRequest" },
+ { 0x0C, "ClientCapability-Request" },
+ { 0x0D, "ClientCapability-Response" },
+ { 0x0E, "DigestBytes" },
+ { 0x0F, "DigestSchema" },
+ { 0x10, "Disconnect" },
+ { 0x11, "Functions" },
+ { 0x12, "GetSPInfo-Request" },
+ { 0x13, "GetSPInfo-Response" },
+ { 0x14, "InviteID" },
+ { 0x15, "InviteNote" },
+ { 0x16, "Invite-Request" },
+ { 0x17, "Invite-Response" },
+ { 0x18, "InviteType" },
+ { 0x19, "InviteUser-Request" },
+ { 0x1A, "InviteUser-Response" },
+ { 0x1B, "KeepAlive-Request" },
+ { 0x1C, "KeepAliveTime" },
+ { 0x1D, "Login-Request" },
+ { 0x1E, "Login-Response" },
+ { 0x1F, "Logout-Request" },
+ { 0x20, "Nonce" },
+ { 0x21, "Password" },
+ { 0x22, "Polling-Request" },
+ { 0x23, "ResponseNote" },
+ { 0x24, "SearchElement" },
+ { 0x25, "SearchFindings" },
+ { 0x26, "SearchID" },
+ { 0x27, "SearchIndex" },
+ { 0x28, "SearchLimit" },
+ { 0x29, "KeepAlive-Response" },
+ { 0x2A, "SearchPairList" },
+ { 0x2B, "Search-Request" },
+ { 0x2C, "Search-Response" },
+ { 0x2D, "SearchResult" },
+ { 0x2E, "Service-Request" },
+ { 0x2F, "Service-Response" },
+ { 0x30, "SessionCookie" },
+ { 0x31, "StopSearch-Request" },
+ { 0x32, "TimeToLive" },
+ /* New in WV-CSP 1.1 */
+ { 0x33, "SearchString" },
+ { 0x34, "CompletionFlag" },
+ /* New in WV-CSP 1.2 */
+ { 0x36, "ReceiveList" },
+ { 0x37, "VerifyID-Request" },
+ { 0x38, "Extended-Request" },
+ { 0x39, "Extended-Response" },
+ { 0x3A, "AgreedCapabilityList" },
+ { 0x3B, "ExtendedData" },
+ { 0x3C, "OtherServer" },
+ { 0x3D, "PresenceAttributeNSName" },
+ { 0x3E, "SessionNSName" },
+ { 0x3F, "TransactionNSName" },
+
+ { 0x00, NULL }
+};
+/* Note that the table continues in code page 0x0A */
+
+/* Service code page (0x02) */
+static const value_string wbxml_wv_csp_12_tags_cp2[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "ADDGM" },
+ { 0x06, "AttListFunc" },
+ { 0x07, "BLENT" },
+ { 0x08, "CAAUT" },
+ { 0x09, "CAINV" },
+ { 0x0A, "CALI" },
+ { 0x0B, "CCLI" },
+ { 0x0C, "ContListFunc" },
+ { 0x0D, "CREAG" },
+ { 0x0E, "DALI" },
+ { 0x0F, "DCLI" },
+ { 0x10, "DELGR" },
+ { 0x11, "FundamentalFeat" },
+ { 0x12, "FWMSG" },
+ { 0x13, "GALS" },
+ { 0x14, "GCLI" },
+ { 0x15, "GETGM" },
+ { 0x16, "GETGP" },
+ { 0x17, "GETLM" },
+ { 0x18, "GETM" },
+ { 0x19, "GETPR" },
+ { 0x1A, "GETSPI" },
+ { 0x1B, "GETWL" },
+ { 0x1C, "GLBLU" },
+ { 0x1D, "GRCHN" },
+ { 0x1E, "GroupAuthFunc" },
+ { 0x1F, "GroupFeat" },
+ { 0x20, "GroupMgmtFunc" },
+ { 0x21, "GroupUseFunc" },
+ { 0x22, "IMAuthFunc" },
+ { 0x23, "IMFeat" },
+ { 0x24, "IMReceiveFunc" },
+ { 0x25, "IMSendFunc" },
+ { 0x26, "INVIT" },
+ { 0x27, "InviteFunc" },
+ { 0x28, "MBRAC" },
+ { 0x29, "MCLS" },
+ { 0x2A, "MDELIV" },
+ { 0x2B, "NEWM" },
+ { 0x2C, "NOTIF" },
+ { 0x2D, "PresenceAuthFunc" },
+ { 0x2E, "PresenceDeliverFunc" },
+ { 0x2F, "PresenceFeat" },
+ { 0x30, "REACT" },
+ { 0x31, "REJCM" },
+ { 0x32, "REJEC" },
+ { 0x33, "RMVGM" },
+ { 0x34, "SearchFunc" },
+ { 0x35, "ServiceFunc" },
+ { 0x36, "SETD" },
+ { 0x37, "SETGP" },
+ { 0x38, "SRCH" },
+ { 0x39, "STSRC" },
+ { 0x3A, "SUBGCN" },
+ { 0x3B, "UPDPR" },
+ { 0x3C, "WVCSPFeat" },
+ /* New in WV-CSP 1.2 */
+ { 0x3D, "MF" },
+ { 0x3E, "MG" },
+ { 0x3E, "VRID" }, /* Duplicate, and cp2 is full --> Will move to cp8? */
+ { 0x3F, "MM" },
+
+ { 0x00, NULL }
+};
+/* Note that the table continues in code page 0x08 */
+
+/* Client capability code page (0x03) */
+/* Same as cp3 of WV-CSP 1.1 */
+#define wbxml_wv_csp_12_tags_cp3 wbxml_wv_csp_11_tags_cp3
+
+/* Presence primitive code page (0x04) */
+static const value_string wbxml_wv_csp_12_tags_cp4[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "CancelAuth-Request" },
+ { 0x06, "ContactListProperties" },
+ { 0x07, "CreateAttributeList-Request" },
+ { 0x08, "CreateList-Request" },
+ { 0x09, "DefaultAttributeList" },
+ { 0x0A, "DefaultContactList" },
+ { 0x0B, "DefaultList" },
+ { 0x0C, "DeleteAttributeList-Request" },
+ { 0x0D, "DeleteList-Request" },
+ { 0x0E, "GetAttributeList-Request" },
+ { 0x0F, "GetAttributeList-Response" },
+ { 0x10, "GetList-Request" },
+ { 0x11, "GetList-Response" },
+ { 0x12, "GetPresence-Request" },
+ { 0x13, "GetPresence-Response" },
+ { 0x14, "GetWatcherList-Request" },
+ { 0x15, "GetWatcherList-Response" },
+ { 0x16, "ListManage-Request" },
+ { 0x17, "ListManage-Response" },
+ { 0x18, "UnsubscribePresence-Request" },
+ { 0x19, "PresenceAuth-Request" },
+ { 0x1A, "PresenceAuth-User" },
+ { 0x1B, "PresenceNotification-Request" },
+ { 0x1C, "UpdatePresence-Request" },
+ { 0x1D, "SubscribePresence-Request" },
+ /* New in WV-CSP 1.2 */
+ { 0x1E, "Auto-Subscribe" },
+ /* 0x1E was defined in WV-CSP 1.0: UnsubscribePresence-Request */
+ { 0x1F, "GetReactiveAuthStatus-Request" },
+ /* 0x1F was defined in WV-CSP 1.0: UpdatePresence-Request */
+ { 0x20, "GetReactiveAuthStatus-Response" },
+
+ { 0x00, NULL }
+};
+
+/* Presence attribute code page (0x05) */
+static const value_string wbxml_wv_csp_12_tags_cp5[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "Accuracy" },
+ { 0x06, "Address" },
+ { 0x07, "AddrPref" },
+ { 0x08, "Alias" },
+ { 0x09, "Altitude" },
+ { 0x0A, "Building" },
+ { 0x0B, "Caddr" },
+ { 0x0C, "City" },
+ { 0x0D, "ClientInfo" },
+ { 0x0E, "ClientProducer" },
+ { 0x0F, "ClientType" },
+ { 0x10, "ClientVersion" },
+ { 0x11, "CommC" },
+ { 0x12, "CommCap" },
+ { 0x13, "ContactInfo" },
+ { 0x14, "ContainedvCard" },
+ { 0x15, "Country" },
+ { 0x16, "Crossing1" },
+ { 0x17, "Crossing2" },
+ { 0x18, "DevManufacturer" },
+ { 0x19, "DirectContent" },
+ { 0x1A, "FreeTextLocation" },
+ { 0x1B, "GeoLocation" },
+ { 0x1C, "Language" },
+ { 0x1D, "Latitude" },
+ { 0x1E, "Longitude" },
+ { 0x1F, "Model" },
+ { 0x20, "NamedArea" },
+ { 0x21, "OnlineStatus" },
+ { 0x22, "PLMN" },
+ { 0x23, "PrefC" },
+ { 0x24, "PreferredContacts" },
+ { 0x25, "PreferredLanguage" },
+ { 0x26, "ReferredContent" },
+ { 0x27, "ReferredvCard" },
+ { 0x28, "Registration" },
+ { 0x29, "StatusContent" },
+ { 0x2A, "StatusMood" },
+ { 0x2B, "StatusText" },
+ { 0x2C, "Street" },
+ { 0x2D, "TimeZone" },
+ { 0x2E, "UserAvailability" },
+ /* New in WV-CSP 1.1 */
+ { 0x2F, "Cap" },
+ { 0x30, "Cname" },
+ { 0x31, "Contact" },
+ { 0x32, "Cpriority" },
+ { 0x33, "Cstatus" },
+ { 0x34, "Note" },
+ { 0x35, "Zone" },
+ /* New in WV-CSP 1.2 */
+ { 0x36, "ContentType" },
+ { 0x37, "Inf_link" },
+ { 0x38, "InfoLink" },
+ { 0x39, "Link" },
+ { 0x3A, "Text" },
+
+ { 0x00, NULL }
+};
+
+/* Messaging code page (0x06) */
+static const value_string wbxml_wv_csp_12_tags_cp6[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "BlockList" },
+ { 0x06, "BlockEntity-Request" }, /* Was: BlockUser-Request */
+ { 0x07, "DeliveryMethod" },
+ { 0x08, "DeliveryReport" },
+ { 0x09, "DeliveryReport-Request" },
+ { 0x0A, "ForwardMessage-Request" },
+ { 0x0B, "GetBlockedList-Request" },
+ { 0x0C, "GetBlockedList-Response" },
+ { 0x0D, "GetMessageList-Request" },
+ { 0x0E, "GetMessageList-Response" },
+ { 0x0F, "GetMessage-Request" },
+ { 0x10, "GetMessage-Response" },
+ { 0x11, "GrantList" },
+ { 0x12, "MessageDelivered" },
+ { 0x13, "MessageInfo" },
+ { 0x14, "MessageNotification" },
+ { 0x15, "NewMessage" },
+ { 0x16, "RejectMessage-Request" },
+ { 0x17, "SendMessage-Request" },
+ { 0x18, "SendMessage-Response" },
+ { 0x19, "SetDeliveryMethod-Request" },
+ { 0x1A, "DeliveryTime" },
+
+ { 0x00, NULL }
+};
+
+/* Group code page (0x07) */
+static const value_string wbxml_wv_csp_12_tags_cp7[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "AddGroupMembers-Request" },
+ { 0x06, "Admin" },
+ { 0x07, "CreateGroup-Request" },
+ { 0x08, "DeleteGroup-Request" },
+ { 0x09, "GetGroupMembers-Request" },
+ { 0x0A, "GetGroupMembers-Response" },
+ { 0x0B, "GetGroupProps-Request" },
+ { 0x0C, "GetGroupProps-Response" },
+ { 0x0D, "GroupChangeNotice" },
+ { 0x0E, "GroupProperties" },
+ { 0x0F, "Joined" },
+ { 0x10, "JoinedRequest" },
+ { 0x11, "JoinGroup-Request" },
+ { 0x12, "JoinGroup-Response" },
+ { 0x13, "LeaveGroup-Request" },
+ { 0x14, "LeaveGroup-Response" },
+ { 0x15, "Left" },
+ { 0x16, "MemberAccess-Request" },
+ { 0x17, "Mod" },
+ { 0x18, "OwnProperties" },
+ { 0x19, "RejectList-Request" },
+ { 0x1A, "RejectList-Response" },
+ { 0x1B, "RemoveGroupMembers-Request" },
+ { 0x1C, "SetGroupProps-Request" },
+ { 0x1D, "SubscribeGroupNotice-Request" },
+ { 0x1E, "SubscribeGroupNotice-Response" },
+ { 0x1F, "Users" },
+ { 0x20, "WelcomeNote" },
+ /* New in WV-CSP 1.1 */
+ { 0x21, "JoinGroup" },
+ { 0x22, "SubscribeNotification" },
+ { 0x23, "SubscribeType" },
+ /* New in WV-CSP 1.2 */
+ { 0x24, "GetJoinedUsers-Request" },
+ { 0x25, "GetJoinedUsers-Response" },
+ { 0x26, "AdminMapList" },
+ { 0x27, "AdminMapping" },
+ { 0x28, "Mapping" },
+ { 0x29, "ModMapping" },
+ { 0x2A, "UserMapList" },
+ { 0x2B, "UserMapping" },
+
+ { 0x00, NULL }
+};
+
+/* Service negotiation code page - continued (0x08) */
+/* Same as cp8 of WV-CSP 1.1, but a new token is likely to be added. - XXX */
+static const value_string wbxml_wv_csp_12_tags_cp8[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "MP" },
+ { 0x06, "GETAUT" },
+ { 0x07, "GETJU" },
+
+ { 0x00, NULL }
+};
+
+/* Common code page - continued (0x09) */
+static const value_string wbxml_wv_csp_12_tags_cp9[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "CIR" },
+ { 0x06, "Domain" },
+ { 0x07, "ExtBlock" },
+ { 0x08, "HistoryPeriod" },
+ { 0x09, "IDList" },
+ { 0x0A, "MaxWatcherList" },
+ { 0x0B, "ReactiveAuthState" },
+ { 0x0C, "ReactiveAuthStatus" },
+ { 0x0D, "ReactiveAuthStatusList" },
+ { 0x0E, "Watcher" },
+ { 0x0C, "WatcherStatus" }, /* Duplicate --> Will move to 0x0F? */
+
+ { 0x00, NULL }
+};
+
+/* Access code page - continued (0x0A) */
+static const value_string wbxml_wv_csp_12_tags_cp10[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "WV-CSP-NSDiscovery-Request" },
+ { 0x06, "WV-CSP-NSDiscovery-Response" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Start tokens *****/
+/* Common code page (0x00) */
+static const value_string wbxml_wv_csp_12_attrStart_cp0[] = {
+ /* 0x00 -- 0x04 GLOBAL */
+ { 0x05, "xmlns='http://www.wireless-village.org/CSP'" },
+ { 0x06, "xmlns='http://www.wireless-village.org/PA'" },
+ { 0x07, "xmlns='http://www.wireless-village.org/TRC'" },
+ /* New in WV-CSP 1.2 */
+ { 0x08, "xmlns='http://www.openmobilealliance.org/DTD/WV-CSP'" },
+ { 0x09, "xmlns='http://www.openmobilealliance.org/DTD/WV-PA'" },
+ { 0x0A, "xmlns http://www.openmobilealliance.org/DTD/WV-TRC'" },
+
+ { 0x00, NULL }
+};
+
+/***** Attribute Value tokens *****/
+/*
+ * Element value tokens
+ *
+ * NOTE - WV-CSP uses the EXT_T_0 token in a peculiar way: the mb_u_int32
+ * does *not* reference an offset in the string table, but it refers to
+ * the index in the following value_string.
+ *
+ * Please note that:
+ * - Values 'T' and 'F' are Boolean values representing "True" and "False"
+ * (or "Yes" and "No" in some circumstances) respectively.
+ * - Values 'GR', 'IM', 'PR', 'SC', 'GM' and 'US' are enumerated values
+ * representing "Group", "Instant Messaging", "Presence", "Shared Content",
+ * "Group membership" and "User" respectively.
+ * - Values 'G', 'S' and 'U' are enumerated values representing "Get", "Set"
+ * and "Unset" respectively.
+ * - Values 'N' and 'P' are enumerated values representing "Notify/Get" and
+ * "Push" respectively.
+ *
+ * I repeat: this is NOT a attrValue[] array hence it is not called
+ * wbxml_wv_XXX but vals_wv_XXX.
+ */
+static const value_string vals_wv_csp_12_element_value_tokens[] = {
+ /*
+ * Common value tokens
+ */
+ { 0x00, "AccessType" },
+ { 0x01, "ActiveUsers" },
+ { 0x02, "Admin" },
+ { 0x03, "application/" },
+ { 0x04, "application/vnd.wap.mms-message" },
+ { 0x05, "application/x-sms" },
+ { 0x06, "AutoJoin" },
+ { 0x07, "BASE64" },
+ { 0x08, "Closed" },
+ { 0x09, "Default" },
+ { 0x0A, "DisplayName" },
+ { 0x0B, "F" },
+ { 0x0C, "G" },
+ { 0x0D, "GR" },
+ { 0x0E, "http://" },
+ { 0x0F, "https://" },
+ { 0x10, "image/" },
+ { 0x11, "Inband" },
+ { 0x12, "IM" },
+ { 0x13, "MaxActiveUsers" },
+ { 0x14, "Mod" },
+ { 0x15, "Name" },
+ { 0x16, "None" },
+ { 0x17, "N" },
+ { 0x18, "Open" },
+ { 0x19, "Outband" },
+ { 0x1A, "PR" },
+ { 0x1B, "Private" },
+ { 0x1C, "PrivateMessaging" },
+ { 0x1D, "PrivilegeLevel" },
+ { 0x1E, "Public" },
+ { 0x1F, "P" },
+ { 0x20, "Request" },
+ { 0x21, "Response" },
+ { 0x22, "Restricted" },
+ { 0x23, "ScreenName" },
+ { 0x24, "Searchable" },
+ { 0x25, "S" },
+ { 0x26, "SC" },
+ { 0x27, "text/" },
+ { 0x28, "text/plain" },
+ { 0x29, "text/x-vCalendar" },
+ { 0x2A, "text/x-vCard" },
+ { 0x2B, "Topic" },
+ { 0x2C, "T" },
+ { 0x2D, "Type" },
+ { 0x2E, "U" },
+ { 0x2F, "US" },
+ { 0x30, "www.wireless-village.org" },
+ /* New in WV-CSP 1.2 */
+ { 0x31, "AutoDelete" },
+ { 0x32, "GM" },
+ { 0x33, "Validity" },
+ { 0x34, "DENIED" }, /* Duplicate */
+ { 0x34, "ShowID" }, /* Duplicate */
+ { 0x35, "GRANTED" },
+ { 0x36, "PENDING" },
+ /*
+ * Access value tokens
+ */
+ { 0x3D, "GROUP_ID" },
+ { 0x3E, "GROUP_NAME" },
+ { 0x3F, "GROUP_TOPIC" },
+ { 0x40, "GROUP_USER_ID_JOINED" },
+ { 0x41, "GROUP_USER_ID_OWNER" },
+ { 0x42, "HTTP" },
+ { 0x43, "SMS" },
+ { 0x44, "STCP" },
+ { 0x45, "SUDP" },
+ { 0x46, "USER_ALIAS" },
+ { 0x47, "USER_EMAIL_ADDRESS" },
+ { 0x48, "USER_FIRST_NAME" },
+ { 0x49, "USER_ID" },
+ { 0x4A, "USER_LAST_NAME" },
+ { 0x4B, "USER_MOBILE_NUMBER" },
+ { 0x4C, "USER_ONLINE_STATUS" },
+ { 0x4D, "WAPSMS" },
+ { 0x4E, "WAPUDP" },
+ { 0x4F, "WSP" },
+ /* New in WV-CSP 1.2 */
+ { 0x50, "GROUP_USER_ID_AUTOJOIN" },
+ /*
+ * Presence value tokens
+ */
+ { 0x5B, "ANGRY" },
+ { 0x5C, "ANXIOUS" },
+ { 0x5D, "ASHAMED" },
+ { 0x5E, "AUDIO_CALL" },
+ { 0x5F, "AVAILABLE" },
+ { 0x60, "BORED" },
+ { 0x61, "CALL" },
+ { 0x62, "CLI" },
+ { 0x63, "COMPUTER" },
+ { 0x64, "DISCREET" },
+ { 0x65, "EMAIL" },
+ { 0x66, "EXCITED" },
+ { 0x67, "HAPPY" },
+ { 0x68, "IM" },
+ { 0x69, "IM_OFFLINE" },
+ { 0x6A, "IM_ONLINE" },
+ { 0x6B, "IN_LOVE" },
+ { 0x6C, "INVINCIBLE" },
+ { 0x6D, "JEALOUS" },
+ { 0x6E, "MMS" },
+ { 0x6F, "MOBILE_PHONE" },
+ { 0x70, "NOT_AVAILABLE" },
+ { 0x71, "OTHER" },
+ { 0x72, "PDA" },
+ { 0x73, "SAD" },
+ { 0x74, "SLEEPY" },
+ { 0x75, "SMS" },
+ { 0x76, "VIDEO_CALL" },
+ { 0x77, "VIDEO_STREAM" },
+
+ { 0x00, NULL }
+};
+
+
+
+/***** Token code page aggregation *****/
+
+static char *
+ext_t_0_wv_cspc_12(tvbuff_t *tvb _U_, guint32 value, guint32 str_tbl _U_)
+{
+ char *str = g_strdup_printf("Common Value: '%s'",
+ val_to_str(value, vals_wv_csp_12_element_value_tokens,
+ "<Unknown WV-CSP 1.2 Common Value token 0x%X>"));
+ return str;
+}
+
+#define wbxml_wv_csp_12_global wbxml_wv_csp_11_global
+
+static const value_valuestring wbxml_wv_csp_12_tags[] = {
+ { 0, wbxml_wv_csp_12_tags_cp0 },
+ { 1, wbxml_wv_csp_12_tags_cp1 },
+ { 2, wbxml_wv_csp_12_tags_cp2 },
+ { 3, wbxml_wv_csp_12_tags_cp3 },
+ { 4, wbxml_wv_csp_12_tags_cp4 },
+ { 5, wbxml_wv_csp_12_tags_cp5 },
+ { 6, wbxml_wv_csp_12_tags_cp6 },
+ { 7, wbxml_wv_csp_12_tags_cp7 },
+ { 8, wbxml_wv_csp_12_tags_cp8 },
+ { 9, wbxml_wv_csp_12_tags_cp9 },
+ { 10, wbxml_wv_csp_12_tags_cp10 },
+ { 0, NULL }
+};
+
+static const value_valuestring wbxml_wv_csp_12_attrStart[] = {
+ { 0, wbxml_wv_csp_12_attrStart_cp0 },
+ { 0, NULL }
+};
+
+static const wbxml_decoding decode_wv_cspc_12 = {
+ "Wireless-Village Client-Server Protocol 1.2",
+ "WV-CSP 1.2",
+ { ext_t_0_wv_cspc_12, NULL, NULL },
+ wv_csp12_opaque_binary_tag,
+ default_opaque_literal_tag,
+ default_opaque_binary_attr,
+ default_opaque_literal_attr,
+ wbxml_wv_csp_12_global,
+ wbxml_wv_csp_12_tags,
+ wbxml_wv_csp_12_attrStart,
+ NULL
+};
+#endif /* Remove_this_comment_when_WV_CSP_will_be_an_approved_spec */
+
+
+
+
+
+/****************************** Discriminators ******************************/
+/* Discriminator for WV-CSP; allows version detection based on parsing parts
+ * of the start of the WBXML body.
+ */
+const wbxml_decoding *
+wv_csp_discriminator(tvbuff_t *tvb, guint32 offset)
+{
+ guint32 magic_1 = tvb_get_ntohl(tvb, offset + 0);
+ guint16 magic_2 = tvb_get_ntohs(tvb, offset + 4);
+
+ if (magic_1 == 0xFE050331 && magic_2 == 0x2e30) {
+ /* FE 05 03 31 23 30 --> WV-CSP 1.0 */
+ return &decode_wv_cspc_10;
+ } else if (magic_1 == 0xC9050331 && magic_2 == 0x2e31) {
+ /* C9 05 03 31 23 31 --> WV-CSP 1.1 */
+ return &decode_wv_cspc_11;
+#ifdef Remove_this_comment_when_WV_CSP_will_be_an_approved_spec
+ } else if (magic_1 == 0xC9050331 && magic_2 == 0x2e31) {
+ /* C9 05 03 31 23 32 --> WV-CSP 1.2 */
+ return &decode_wv_cspc_12;
+#endif /* Remove_this_comment_when_WV_CSP_will_be_an_approved_spec */
+ }
+
+ /* Default: WV-CSP 1.1 */
+ return &decode_wv_cspc_11;
+}
+
+/********************** WBXML token mapping aggregation **********************/
+
+static const wbxml_decoding *get_wbxml_decoding_from_public_id (guint32 publicid);
+static const wbxml_decoding *get_wbxml_decoding_from_content_type (
+ const char *content_type, tvbuff_t *tvb, guint32 offset);
+
+
+/**
+ ** Aggregation of content type and aggregated code pages
+ ** Content type map lookup will stop at the 1st entry with 3rd member = FALSE
+ **/
+
+/*
+ * The following map contains entries registered with a registered WBXML
+ * public ID. See WAP WINA or OMA OMNA for registered values:
+ * http://www.openmobilealliance.org/tech/omna/ */
+static const wbxml_integer_list well_known_public_id_list[] = {
+ /* 0x00 - Unknown or missing Public ID */
+ /* 0x01 - LITERAL PublicID - see String Table */
+ { 0x02, &decode_wmlc_10 }, /* WML 1.0 */
+ /* 0x03 - WTA 1.0 */
+ { 0x04, &decode_wmlc_11 }, /* WML 1.1 */
+ { 0x05, &decode_sic_10 }, /* SI 1.0 */
+ { 0x06, &decode_slc_10 }, /* SL 1.0 */
+ { 0x07, &decode_coc_10 }, /* CO 1.0 */
+ { 0x08, &decode_channelc_10 }, /* CHANNEL 1.0 */
+ { 0x09, &decode_wmlc_12 }, /* WML 1.2 */
+ { 0x0A, &decode_wmlc_13 }, /* WML 1.3 */
+ { 0x0B, &decode_provc_10 }, /* PROV 1.0 */
+ /* 0x0C - WTA-WML 1.2 */
+ { 0x0D, &decode_emnc_10 }, /* EMN 1.0 */
+ /* 0x0E - DRMREL 1.0 */
+ { 0x0F, &decode_wv_cspc_10 }, /* WV-CSP 1.0 */
+ { 0x10, &decode_wv_cspc_11 }, /* WV-CSP 1.1 */
+
+ { 0x020B, &decode_nokiaprovc_70 },/* Nokia OTA Provisioning 7.0 */
+ { 0x0FD1, &decode_syncmlc_10 }, /* SyncML 1.0 */
+ { 0x0FD3, &decode_syncmlc_11 }, /* SyncML 1.1 */
+ /* Note: I assumed WML+ 1.x would be not that different from WML 1.x,
+ * the real mapping should come from Phone.com (OpenWave)! */
+ { 0x1108, &decode_wmlc_11 }, /* Phone.com WMLC+ 1.1 - not 100% correct */
+ { 0x110D, &decode_wmlc_13 }, /* Phone.com WMLC+ 1.3 - not 100% correct */
+
+ { 0x00, NULL }
+};
+
+/* The following map contains entries only registered with a literal media
+ * type. */
+static const wbxml_literal_list content_type_list[] = {
+ { "application/x-wap-prov.browser-settings",
+ NULL,
+ &decode_nokiaprovc_70
+ },
+ { "application/x-wap-prov.browser-bookmarks",
+ NULL,
+ &decode_nokiaprovc_70
+ },
+ { "application/vnd.wv.csp.wbxml",
+ wv_csp_discriminator,
+ &decode_wv_cspc_11
+ },
+ { NULL, NULL, NULL }
+};
+
+
+/* Returns a pointer to the WBXML token map for the given WBXML public
+ * identifier value (see WINA for a table with defined identifiers). */
+static const wbxml_decoding *get_wbxml_decoding_from_public_id (guint32 public_id)
+{
+ const wbxml_decoding *map = NULL;
+
+ DebugLog(("get_wbxml_decoding_from_public_id: public_id = %u\n",
+ public_id));
+ if (public_id >= 2) {
+ const wbxml_integer_list *item = well_known_public_id_list;
+
+ while (item && item->public_id && item->map) {
+ if (item->public_id == public_id) {
+ map = item->map;
+ break;
+ }
+ item++;
+ }
+ }
+ return map;
+}
+
+static const wbxml_decoding *get_wbxml_decoding_from_content_type (
+ const char *content_type, tvbuff_t *tvb, guint32 offset)
+{
+ const wbxml_decoding *map = NULL;
+
+ DebugLog(("get_wbxml_decoding_from_content_type: content_type = [%s]\n",
+ content_type));
+ if (content_type && content_type[0]) {
+ const wbxml_literal_list *item = content_type_list;
+
+ while (item && item->content_type) {
+ if (strcasecmp(content_type, item->content_type) == 0) {
+ /* Try the discriminator */
+ if (item->discriminator != NULL) {
+ map = item->discriminator(tvb, offset);
+ }
+ if (map == NULL) {
+ map = item->map;
+ }
+ break;
+ }
+ item++;
+ }
+ }
+ return map;
+}
+
+
+/* WBXML content token mapping depends on the following parameters:
+ * - Content type (guint32)
+ * - Token type (global, tags, attrStart, attrValue)
+ * - Code page for tag and attribute
+ *
+ * This results in the following steps:
+ * 1. Retrieve content type mapping
+ * 2. If exists, retrieve token type mapping
+ * 3. If exists, retrieve required code page
+ * 4. If exists, retrieve token mapping
+ */
+
+#define wbxml_UNDEFINED_TOKEN \
+ "(Requested token not defined for this content type)"
+#define wbxml_UNDEFINED_TOKEN_CODE_PAGE \
+ "(Requested token code page not defined for this content type)"
+#define wbxml_UNDEFINED_TOKEN_MAP \
+ "(Requested token map not defined for this content type)"
+/* Return token mapping for a given content mapping entry. */
+static const char *
+map_token (const value_valuestring *token_map, guint8 codepage, guint8 token) {
+ const value_string *vs;
+ const char *s;
+
+ if (token_map) { /* Found map */
+ if ((vs = val_to_valstr (codepage, token_map))) {
+ /* Found codepage map */
+ s = match_strval (token, vs);
+ if (s) { /* Found valid token */
+ DebugLog(("map_token(codepage = %u, token = %u: [%s]\n", codepage, token, s));
+ return s;
+ }
+ /* No valid token mapping in specified code page of token map */
+ DebugLog(("map_token(codepage = %u, token = %u: "
+ wbxml_UNDEFINED_TOKEN "\n", codepage, token));
+ return wbxml_UNDEFINED_TOKEN;
+ }
+ /* There is no token map entry for the requested code page */
+ DebugLog(("map_token(codepage = %u, token = %u: "
+ wbxml_UNDEFINED_TOKEN_CODE_PAGE "\n", codepage, token));
+ return wbxml_UNDEFINED_TOKEN_CODE_PAGE;
+ }
+ /* The token map does not exist */
+ DebugLog(("map_token(codepage = %u, token = %u: "
+ wbxml_UNDEFINED_TOKEN_MAP "\n", codepage, token));
+ return wbxml_UNDEFINED_TOKEN_MAP;
+}
+
+
+
+
+
+/************************** Function prototypes **************************/
+
+
+static void
+dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static void
+dissect_uaprof(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static void
+dissect_wbxml_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const wbxml_decoding *override_content_map);
+
+void
+proto_register_wbxml(void);
+
+/* Parse and display the WBXML string table */
+static void
+show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
+ guint32 str_tbl_len);
+
+/* Parse data while in STAG state */
+static guint32
+parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
+ guint32 str_tbl, guint8 *level, guint8 *codepage_stag, guint8 *codepage_attr);
+
+/* Parse data while in STAG state;
+ * interpret tokens as defined by content type */
+static guint32
+parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
+ guint32 str_tbl, guint8 *level, guint8 *codepage_stag, guint8 *codepage_attr,
+ const wbxml_decoding *map);
+
+/* Parse data while in ATTR state */
+static guint32
+parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
+ guint32 offset, guint32 str_tbl, guint8 level, guint8 *codepage_attr);
+
+/* Parse data while in ATTR state;
+ * interpret tokens as defined by content type */
+static guint32
+parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
+ guint32 offset, guint32 str_tbl, guint8 level, guint8 *codepage_attr,
+ const wbxml_decoding *map);
+
+
+/****************** WBXML protocol dissection functions ******************/
+
+
+static void
+dissect_wbxml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_wbxml_common(tvb, pinfo, tree, NULL);
+}
+
+static void
+dissect_uaprof(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_wbxml_common(tvb, pinfo, tree, &decode_uaprof_wap_248);
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_wbxml_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const wbxml_decoding *override_content_map)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *wbxml_tree; /* Main WBXML tree */
+ proto_tree *wbxml_str_tbl_tree; /* String table subtree */
+ proto_tree *wbxml_content_tree; /* Content subtree */
+ guint8 version;
+ guint offset = 0;
+ guint32 len;
+ guint32 charset = 0;
+ guint32 charset_len = 0;
+ guint32 publicid;
+ guint32 publicid_index = 0;
+ guint32 publicid_len;
+ guint32 str_tbl;
+ guint32 str_tbl_len;
+ guint32 str_tbl_len_len = 0;
+ guint8 level = 0; /* WBXML recursion level */
+ const wbxml_decoding *content_map = NULL;
+ gchar *summary = NULL;
+ guint8 codepage_stag = 0;
+ guint8 codepage_attr = 0;
+
+ DebugLog(("dissect_wbxml: Dissecting packet %u\n", pinfo->fd->num));
+ /* WBXML format
+ *
+ * Version 1.0: version publicid strtbl BODY
+ * Version 1.x: version publicid charset strtbl BODY
+ *
+ * Last valid format: WBXML 1.3
+ */
+ switch ( version = tvb_get_guint8 (tvb, 0) ) {
+ case 0x00: /* WBXML/1.0 */
+ break;
+
+ case 0x01: /* WBXML/1.1 */
+ case 0x02: /* WBXML/1.2 */
+ case 0x03: /* WBXML/1.3 */
+ break;
+
+ default:
+ return;
+ }
+
+ /* In order to properly construct the packet summary,
+ * I need to read the entire WBXML header
+ * up to the string table length.
+ */
+
+ /* Public ID */
+ publicid = tvb_get_guintvar(tvb, 1, &publicid_len);
+ if (! publicid) {
+ /* Public identifier in string table */
+ publicid_index = tvb_get_guintvar (tvb, 1+publicid_len, &len);
+ publicid_len += len;
+ }
+ offset = 1 + publicid_len;
+
+ /* Version-specific handling of Charset */
+ switch ( version ) {
+ case 0x00: /* WBXML/1.0 */
+ /* No charset */
+ break;
+
+ case 0x01: /* WBXML/1.1 */
+ case 0x02: /* WBXML/1.2 */
+ case 0x03: /* WBXML/1.3 */
+ /* Get charset */
+ charset = tvb_get_guintvar (tvb, offset, &charset_len);
+ offset += charset_len;
+ break;
+
+ default: /* Impossible since we returned already earlier */
+ g_error("%s:%u: WBXML version octet 0x%02X only partly supported!\n"
+ "Please report this as a bug.\n", __FILE__, __LINE__, version);
+ g_assert_not_reached();
+ break;
+ }
+
+ /* String table: read string table length in bytes */
+ str_tbl_len = tvb_get_guintvar (tvb, offset, &str_tbl_len_len);
+ str_tbl = offset + str_tbl_len_len; /* Start of 1st string in string table */
+
+ /* Compose the summary line */
+ if ( publicid ) {
+ summary = g_strdup_printf("%s, Public ID: \"%s\"",
+ match_strval (version, vals_wbxml_versions),
+ match_strval (publicid, vals_wbxml_public_ids));
+ } else {
+ /* Read length of Public ID from string table */
+ len = tvb_strsize (tvb, str_tbl + publicid_index);
+ summary = g_strdup_printf("%s, Public ID: \"%s\"",
+ match_strval (version, vals_wbxml_versions),
+ tvb_format_text (tvb, str_tbl + publicid_index, len - 1));
+ }
+
+ /* Add summary to INFO column if it is enabled */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (WBXML %s)", summary);
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item (tree, proto_wbxml, tvb, 0, -1, FALSE);
+ proto_item_append_text(ti, ", Version: %s", summary);
+ g_free(summary);
+ /*
+ * Now show the protocol subtree, if tree is set.
+ */
+ if ( tree ) {
+ wbxml_tree = proto_item_add_subtree(ti, ett_wbxml);
+
+ /* WBXML Version */
+ proto_tree_add_uint (wbxml_tree, hf_wbxml_version,
+ tvb, 0, 1, version);
+
+ /* Public ID */
+ if (publicid) { /* Known Public ID */
+ proto_tree_add_uint(wbxml_tree, hf_wbxml_public_id_known,
+ tvb, 1, publicid_len, publicid);
+ } else { /* Public identifier in string table */
+ proto_tree_add_item (wbxml_tree, hf_wbxml_public_id_literal,
+ tvb, 1, publicid_len, FALSE);
+ }
+ offset = 1 + publicid_len;
+
+ if ( version ) { /* Charset */
+ proto_tree_add_uint (wbxml_tree, hf_wbxml_charset,
+ tvb, 1 + publicid_len, charset_len, charset);
+ offset += charset_len;
+ }
+
+ str_tbl_len = tvb_get_guintvar (tvb, offset, &len);
+ str_tbl = offset + len; /* Start of 1st string in string table */
+
+ /* String Table */
+ ti = proto_tree_add_text(wbxml_tree,
+ tvb, offset, len + str_tbl_len, "String table: %u bytes",
+ str_tbl_len);
+
+ if (wbxml_tree && str_tbl_len) { /* Display string table as subtree */
+ wbxml_str_tbl_tree = proto_item_add_subtree (ti,
+ ett_wbxml_str_tbl);
+ show_wbxml_string_table (wbxml_str_tbl_tree, tvb,
+ str_tbl, str_tbl_len);
+ }
+
+ /* Data starts HERE */
+ offset += len + str_tbl_len;
+
+ /* The WBXML BODY starts here */
+ if (disable_wbxml_token_parsing) {
+ ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
+ "Data representation not shown "
+ "(edit WBXML preferences to show)");
+ return;
+ } /* Else: render the WBXML tokens */
+ ti = proto_tree_add_text (wbxml_tree, tvb, offset, -1,
+ "Data representation");
+ wbxml_content_tree = proto_item_add_subtree (ti, ett_wbxml_content);
+
+ /* The parse_wbxml_X() functions will process the content correctly,
+ * irrespective of the WBXML version used. For the WBXML body, this
+ * means that there is a different processing for the global token
+ * RESERVED_2 (WBXML 1.0) or OPAQUE (WBXML 1.x with x > 0). */
+ if (wbxml_tree) { /* Show only if visible */
+ if (override_content_map != NULL) {
+ content_map = override_content_map;
+ proto_item_append_text(ti,
+ " is based on: %s",
+ content_map->name);
+ } else {
+ /* Retrieve the content token mapping if available */
+ content_map = get_wbxml_decoding_from_public_id (publicid);
+ if (! content_map) {
+ content_map = get_wbxml_decoding_from_content_type(
+ pinfo->match_string, tvb, offset);
+ if (! content_map) {
+ proto_tree_add_text (wbxml_content_tree,
+ tvb, offset, -1,
+ "[Rendering of this content type"
+ " not (yet) supported]");
+ } else {
+ proto_item_append_text(ti,
+ " is based on Content-Type: %s "
+ "(chosen decoding: %s)",
+ pinfo->match_string, content_map->name);
+ }
+ }
+ }
+ if (content_map && skip_wbxml_token_mapping) {
+ proto_tree_add_text (wbxml_content_tree,
+ tvb, offset, -1,
+ "[Rendering of this content type"
+ " has been disabled "
+ "(edit WBXML preferences to enable)]");
+ content_map = NULL;
+ }
+ proto_tree_add_text (wbxml_content_tree, tvb,
+ offset, -1,
+ "Level | State | Codepage "
+ "| WBXML Token Description "
+ "| Rendering");
+ if (content_map) {
+ len = parse_wbxml_tag_defined (wbxml_content_tree,
+ tvb, offset, str_tbl, &level, &codepage_stag,
+ &codepage_attr, content_map);
+ } else {
+ /* Default: WBXML only, no interpretation of the content */
+ len = parse_wbxml_tag (wbxml_content_tree, tvb, offset,
+ str_tbl, &level, &codepage_stag, &codepage_attr);
+ }
+ }
+ return;
+ }
+}
+
+
+/* Parse and display the WBXML string table (in a 3-column table format).
+ * This function displays:
+ * - the offset in the string table,
+ * - the length of the string
+ * - the string.
+ */
+static void
+show_wbxml_string_table (proto_tree *tree, tvbuff_t *tvb, guint32 str_tbl,
+ guint32 str_tbl_len)
+{
+ guint32 off = str_tbl;
+ guint32 len = 0;
+ guint32 end = str_tbl + str_tbl_len;
+
+ proto_tree_add_text (tree, tvb, off, end,
+ "Start | Length | String");
+ while (off < end) {
+ len = tvb_strsize (tvb, off);
+ proto_tree_add_text (tree, tvb, off, len,
+ "%6d | %6d | '%s'",
+ off - str_tbl, len,
+ tvb_format_text (tvb, off, len-1));
+ off += len;
+ }
+}
+
+
+/* Indentation code is based on a static const array of space characters.
+ * At least one single space is returned */
+static const char indent_buffer[514] = " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ " "
+ ; /* Generate XML indentation (length = 1 + 2 * 256 + 1 for '\0') */
+
+static const char * Indent (guint8 level) {
+ return indent_buffer + (512 - 2 * (level));
+}
+
+
+/********************
+ * WBXML tag tokens *
+ ********************
+ *
+ * Bit Mask : Example
+ * -------------------
+ * 00.. .... : <tag />
+ *
+ * 01.. .... : <tag>
+ * CONTENT
+ * </tag>
+ *
+ * 10.. .... : <tag
+ * atrtribute1="value1"
+ * atrtribute2="value2"
+ * />
+ *
+ * 11.. .... : <tag
+ * atrtribute1="value1"
+ * atrtribute2="value2"
+ * >
+ * CONTENT
+ * </tag>
+ *
+ * NOTES
+ * - An XML PI is parsed as an attribute list (same syntax).
+ * - A code page switch only applies to the single token that follows.
+ */
+
+
+/* This function parses the WBXML and maps known token interpretations
+ * to the WBXML tokens. As a result, the original XML document can be
+ * recreated. Indentation is generated in order to ease reading.
+ *
+ * Attribute parsing is done in parse_wbxml_attribute_list_defined().
+ *
+ * The wbxml_decoding entry *map contains the actual token mapping.
+ *
+ * NOTE: In order to parse the content, some recursion is required.
+ * However, for performance reasons, recursion has been avoided
+ * where possible (tags without content within tags with content).
+ * This is achieved by means of the parsing_tag_content and tag_save*
+ * variables.
+ *
+ * NOTE: See above for known token mappings.
+ *
+ * NOTE: As tags can be opened and closed, a tag representation lookup
+ * may happen once or twice for a given tag. For efficiency reasons,
+ * the literal tag value is stored and used throughout the code.
+ * With the introduction of code page support, this solution is robust
+ * as the lookup only occurs once, removing the need for storage of
+ * the used code page.
+ */
+static guint32
+parse_wbxml_tag_defined (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
+ guint32 str_tbl, guint8 *level, guint8 *codepage_stag, guint8 *codepage_attr,
+ const wbxml_decoding *map)
+{
+ guint32 tvb_len = tvb_reported_length (tvb);
+ guint32 off = offset;
+ guint32 len;
+ guint str_len;
+ guint32 ent;
+ guint32 index;
+ guint8 peek;
+ guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
+ guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
+ guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
+ const char *tag_save_literal; /* Will contain the LITERAL tag identity */
+ const char *tag_new_literal; /* Will contain the LITERAL tag identity */
+ guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
+ tag with content: <x>Content</x>
+
+ The initial state is FALSE.
+ This state will trigger recursion. */
+ tag_save_literal = NULL; /* Prevents compiler warning */
+
+ DebugLog(("parse_wbxml_tag_defined (level = %u, offset = %u)\n", *level, offset));
+ while (off < tvb_len) {
+ peek = tvb_get_guint8 (tvb, off);
+ DebugLog(("STAG: (top of while) level = %3u, peek = 0x%02X, off = %u, tvb_len = %u\n", *level, peek, off, tvb_len));
+ if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
+ but not the LITERAL tokens */
+ case 0x00: /* SWITCH_PAGE */
+ *codepage_stag = tvb_get_guint8 (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 2,
+ " | Tag | T -->%3d "
+ "| SWITCH_PAGE (Tag code page) "
+ "|",
+ *codepage_stag);
+ off += 2;
+ break;
+ case 0x01: /* END: only possible for Tag with Content */
+ if (tag_save_known) { /* Known TAG */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| END (Known Tag 0x%02X) "
+ "| %s</%s>",
+ *level, *codepage_stag,
+ tag_save_known, Indent (*level),
+ tag_save_literal); /* We already looked it up! */
+ } else { /* Literal TAG */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| END (Literal Tag) "
+ "| %s</%s>",
+ *level, *codepage_stag, Indent (*level),
+ tag_save_literal);
+ }
+ (*level)--;
+ off++;
+ /* Reset code page: not needed as return from recursion */
+ DebugLog(("STAG: level = %u, Return: len = %u\n", *level, off - offset));
+ return (off - offset);
+ break;
+ case 0x02: /* ENTITY */
+ ent = tvb_get_guintvar (tvb, off+1, &len);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| ENTITY "
+ "| %s'&#%u;'",
+ *level, *codepage_stag, Indent (*level), ent);
+ off += 1+len;
+ break;
+ case 0x03: /* STR_I */
+ len = tvb_strsize (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| STR_I (Inline string) "
+ "| %s\'%s\'",
+ *level, *codepage_stag, Indent(*level),
+ tvb_format_text (tvb, off+1, len-1));
+ off += 1+len;
+ break;
+ case 0x40: /* EXT_I_0 */
+ case 0x41: /* EXT_I_1 */
+ case 0x42: /* EXT_I_2 */
+ /* Extension tokens */
+ len = tvb_strsize (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| EXT_I_%1x (Extension Token) "
+ "| %s(%s: \'%s\')",
+ *level, *codepage_stag,
+ peek & 0x0f, Indent (*level),
+ map_token (map->global, 0, peek),
+ tvb_format_text (tvb, off+1, len-1));
+ off += 1+len;
+ break;
+ case 0x43: /* PI */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| PI (XML Processing Instruction) "
+ "| %s<?xml",
+ *level, *codepage_stag, Indent (*level));
+ len = parse_wbxml_attribute_list_defined (tree, tvb, off,
+ str_tbl, *level, codepage_attr, map);
+ /* Check that there is still room in packet */
+ off += len;
+ if (off >= tvb_len) {
+ DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
+ /*
+ * TODO - Do we need to free g_malloc()ed memory?
+ */
+ THROW(ReportedBoundsError);
+ }
+ proto_tree_add_text (tree, tvb, off-1, 1,
+ " %3d | Tag | T %3d "
+ "| END (PI) "
+ "| %s?>",
+ *level, *codepage_stag, Indent (*level));
+ break;
+ case 0x80: /* EXT_T_0 */
+ case 0x81: /* EXT_T_1 */
+ case 0x82: /* EXT_T_2 */
+ /* Extension tokens */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ { char *s;
+ if (map->ext_t[peek & 0x03])
+ s = (map->ext_t[peek & 0x03])(tvb, index, str_tbl);
+ else
+ s = g_strdup_printf("EXT_T_%1x (%s)", peek & 0x03,
+ map_token (map->global, 0, peek));
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| EXT_T_%1x (Extension Token) "
+ "| %s%s",
+ *level, *codepage_stag, peek & 0x0f, Indent (*level),
+ s);
+ g_free(s);
+ }
+ off += 1+len;
+ break;
+ case 0x83: /* STR_T */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ str_len = tvb_strsize (tvb, str_tbl+index);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| STR_T (Tableref string) "
+ "| %s\'%s\'",
+ *level, *codepage_stag, Indent (*level),
+ tvb_format_text (tvb, str_tbl+index, str_len-1));
+ off += 1+len;
+ break;
+ case 0xC0: /* EXT_0 */
+ case 0xC1: /* EXT_1 */
+ case 0xC2: /* EXT_2 */
+ /* Extension tokens */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| EXT_%1x (Extension Token) "
+ "| %s(%s)",
+ *level, *codepage_stag, peek & 0x0f, Indent (*level),
+ map_token (map->global, 0, peek));
+ off++;
+ break;
+ case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
+ if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
+ char *str;
+ if (tag_save_known) { /* Knwon tag */
+ if (map->opaque_binary_tag) {
+ str = map->opaque_binary_tag(tvb, off + 1,
+ tag_save_known, *codepage_stag, &len);
+ } else {
+ str = default_opaque_binary_tag(tvb, off + 1,
+ tag_save_known, *codepage_stag, &len);
+ }
+ } else { /* lITERAL tag */
+ if (map->opaque_literal_tag) {
+ str = map->opaque_literal_tag(tvb, off + 1,
+ tag_save_literal, *codepage_stag, &len);
+ } else {
+ str = default_opaque_literal_tag(tvb, off + 1,
+ tag_save_literal, *codepage_stag, &len);
+ }
+ }
+ proto_tree_add_text (tree, tvb, off, 1 + len,
+ " %3d | Tag | T %3d "
+ "| OPAQUE (Opaque data) "
+ "| %s%s",
+ *level, *codepage_stag, Indent (*level), str);
+ g_free(str);
+ off += 1 + len;
+ } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| RESERVED_2 (Invalid Token!) "
+ "| WBXML 1.0 parsing stops here.",
+ *level, *codepage_stag);
+ /* Stop processing as it is impossible to parse now */
+ off = tvb_len;
+ DebugLog(("STAG: level = %u, Return: len = %u\n", *level, off - offset));
+ return (off - offset);
+ }
+ break;
+
+ /* No default clause, as all cases have been treated */
+ } else { /* LITERAL or Known TAG */
+ /* We must store the initial tag, and also retrieve the new tag.
+ * For efficiency reasons, we store the literal tag representation
+ * for known tags too, so we can easily close the tag without the
+ * need of a new lookup and avoiding storage of token codepage.
+ *
+ * There are 4 possibilities:
+ *
+ * 1. Known tag followed by a known tag
+ * 2. Known tag followed by a LITERAL tag
+ * 3. LITERAL tag followed by Known tag
+ * 4. LITERAL tag followed by LITERAL tag
+ */
+
+ /* Store the new tag */
+ tag_len = 0;
+ if ((peek & 0x3F) == 4) { /* LITERAL */
+ DebugLog(("STAG: LITERAL tag (peek = 0x%02X, off = %u) - TableRef follows!\n", peek, off));
+ index = tvb_get_guintvar (tvb, off+1, &tag_len);
+ str_len = tvb_strsize (tvb, str_tbl+index);
+ tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
+ tag_new_known = 0; /* invalidate known tag_new */
+ } else { /* Known tag */
+ tag_new_known = peek & 0x3F;
+ tag_new_literal = map_token (map->tags, *codepage_stag,
+ tag_new_known);
+ /* Stored looked up tag name string */
+ }
+
+ /* Parsing of TAG starts HERE */
+ if (peek & 0x40) { /* Content present */
+ /* Content follows
+ * [!] An explicit END token is expected in these cases!
+ * ==> Recursion possible if we encounter a tag with content;
+ * recursion will return at the explicit END token.
+ */
+ if (parsing_tag_content) { /* Recurse */
+ DebugLog(("STAG: Tag in Tag - RECURSE! (off = %u)\n", off));
+ /* Do not process the attribute list:
+ * recursion will take care of it */
+ (*level)++;
+ len = parse_wbxml_tag_defined (tree, tvb, off, str_tbl,
+ level, codepage_stag, codepage_attr, map);
+ off += len;
+ } else { /* Now we will have content to parse */
+ /* Save the start tag so we can properly close it later. */
+ if ((peek & 0x3F) == 4) { /* Literal tag */
+ tag_save_literal = tag_new_literal;
+ tag_save_known = 0;
+ } else { /* Known tag */
+ tag_save_known = tag_new_known;
+ tag_save_literal = tag_new_literal;
+ /* The last statement avoids needless lookups */
+ }
+ /* Process the attribute list if present */
+ if (peek & 0x80) { /* Content and Attribute list present */
+ if (tag_new_known) { /* Known tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| Known Tag 0x%02X (AC) "
+ "| %s<%s",
+ *level, *codepage_stag, tag_new_known,
+ Indent (*level), tag_new_literal);
+ /* Tag string already looked up earlier! */
+ off++;
+ } else { /* LITERAL tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| LITERAL_AC (Literal tag) (AC) "
+ "| %s<%s",
+ *level, *codepage_stag, Indent (*level), tag_new_literal);
+ off += 1 + tag_len;
+ }
+ len = parse_wbxml_attribute_list_defined (tree, tvb,
+ off, str_tbl, *level, codepage_attr, map);
+ /* Check that there is still room in packet */
+ off += len;
+ if (off >= tvb_len) {
+ DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n",
+ *level, off - offset));
+ /*
+ * TODO - Do we need to free g_malloc()ed memory?
+ */
+ THROW(ReportedBoundsError);
+ }
+ proto_tree_add_text (tree, tvb, off-1, 1,
+ " %3d | Tag | T %3d "
+ "| END (attribute list) "
+ "| %s>",
+ *level, *codepage_stag, Indent (*level));
+ } else { /* Content, no Attribute list */
+ if (tag_new_known) { /* Known tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| Known Tag 0x%02X (.C) "
+ "| %s<%s>",
+ *level, *codepage_stag, tag_new_known,
+ Indent (*level), tag_new_literal);
+ /* Tag string already looked up earlier! */
+ off++;
+ } else { /* LITERAL tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| LITERAL_C (Literal Tag) (.C) "
+ "| %s<%s>",
+ *level, *codepage_stag, Indent (*level),
+ tag_new_literal);
+ off += 1 + tag_len;
+ }
+ }
+ /* The data that follows in the parsing process
+ * represents content for the opening tag
+ * we've just processed in the lines above.
+ * Next time we encounter a tag with content: recurse
+ */
+ parsing_tag_content = TRUE;
+ DebugLog(("Tag in Tag - No recursion this time! (off = %u)\n", off));
+ }
+ } else { /* No Content */
+ DebugLog(("<Tag/> in Tag - No recursion! (off = %u)\n", off));
+ (*level)++;
+ if (peek & 0x80) { /* No Content, Attribute list present */
+ if (tag_new_known) { /* Known tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| Known Tag 0x%02X (A.) "
+ "| %s<%s",
+ *level, *codepage_stag, tag_new_known,
+ Indent (*level), tag_new_literal);
+ /* Tag string already looked up earlier! */
+ off++;
+ len = parse_wbxml_attribute_list_defined (tree, tvb,
+ off, str_tbl, *level, codepage_attr, map);
+ /* Check that there is still room in packet */
+ off += len;
+ if (off >= tvb_len) {
+ DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
+ /*
+ * TODO - Do we need to free g_malloc()ed memory?
+ */
+ THROW(ReportedBoundsError);
+ }
+ proto_tree_add_text (tree, tvb, off-1, 1,
+ " %3d | Tag | T %3d "
+ "| END (Known Tag) "
+ "| %s/>",
+ *level, *codepage_stag, Indent (*level));
+ } else { /* LITERAL tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| LITERAL_A (Literal Tag) (A.) "
+ "| %s<%s",
+ *level, *codepage_stag, Indent (*level), tag_new_literal);
+ off += 1 + tag_len;
+ len = parse_wbxml_attribute_list_defined (tree, tvb,
+ off, str_tbl, *level, codepage_attr, map);
+ /* Check that there is still room in packet */
+ off += len;
+ if (off >= tvb_len) {
+ DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n", *level, off - offset));
+ /*
+ * TODO - Do we need to free g_malloc()ed memory?
+ */
+ THROW(ReportedBoundsError);
+ }
+ proto_tree_add_text (tree, tvb, off-1, 1,
+ " %3d | Tag | T %3d "
+ "| END (Literal Tag) "
+ "| %s/>",
+ *level, *codepage_stag, Indent (*level));
+ }
+ } else { /* No Content, No Attribute list */
+ if (tag_new_known) { /* Known tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| Known Tag 0x%02x (..) "
+ "| %s<%s />",
+ *level, *codepage_stag, tag_new_known,
+ Indent (*level), tag_new_literal);
+ /* Tag string already looked up earlier! */
+ off++;
+ } else { /* LITERAL tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| LITERAL (Literal Tag) (..) "
+ "| %s<%s />",
+ *level, *codepage_stag, Indent (*level),
+ tag_new_literal);
+ off += 1 + tag_len;
+ }
+ }
+ (*level)--;
+ /* TODO: Do I have to reset code page here? */
+ }
+ } /* if (tag & 0x3F) >= 5 */
+ } /* while */
+ DebugLog(("STAG: level = %u, Return: len = %u (end of function body)\n", *level, off - offset));
+ return (off - offset);
+}
+
+
+/* This function performs the WBXML decoding as in parse_wbxml_tag_defined()
+ * but this time no WBXML mapping is performed.
+ *
+ * Attribute parsing is done in parse_wbxml_attribute_list().
+ */
+static guint32
+parse_wbxml_tag (proto_tree *tree, tvbuff_t *tvb, guint32 offset,
+ guint32 str_tbl, guint8 *level,
+ guint8 *codepage_stag, guint8 *codepage_attr)
+{
+ guint32 tvb_len = tvb_reported_length (tvb);
+ guint32 off = offset;
+ guint32 len;
+ guint str_len;
+ guint32 ent;
+ guint32 index;
+ guint8 peek;
+ guint32 tag_len; /* Length of the index (uintvar) from a LITERAL tag */
+ guint8 tag_save_known = 0; /* Will contain peek & 0x3F (tag identity) */
+ guint8 tag_new_known = 0; /* Will contain peek & 0x3F (tag identity) */
+ const char *tag_save_literal; /* Will contain the LITERAL tag identity */
+ const char *tag_new_literal; /* Will contain the LITERAL tag identity */
+ char tag_save_buf[10]; /* Will contain "tag_0x%02X" */
+ char tag_new_buf[10]; /* Will contain "tag_0x%02X" */
+ guint8 parsing_tag_content = FALSE; /* Are we parsing content from a
+ tag with content: <x>Content</x>
+
+ The initial state is FALSE.
+ This state will trigger recursion. */
+ tag_save_literal = NULL; /* Prevents compiler warning */
+
+ DebugLog(("parse_wbxml_tag (level = %u, offset = %u)\n", *level, offset));
+ while (off < tvb_len) {
+ peek = tvb_get_guint8 (tvb, off);
+ DebugLog(("STAG: (top of while) level = %3u, peek = 0x%02X, off = %u, tvb_len = %u\n", *level, peek, off, tvb_len));
+ if ((peek & 0x3F) < 4) switch (peek) { /* Global tokens in state = STAG
+ but not the LITERAL tokens */
+ case 0x00: /* SWITCH_PAGE */
+ *codepage_stag = tvb_get_guint8 (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 2,
+ " | Tag | T -->%3d "
+ "| SWITCH_PAGE (Tag code page) "
+ "|",
+ *codepage_stag);
+ off += 2;
+ break;
+ case 0x01: /* END: only possible for Tag with Content */
+ if (tag_save_known) { /* Known TAG */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| END (Known Tag 0x%02X) "
+ "| %s</%s>",
+ *level, *codepage_stag, tag_save_known,
+ Indent (*level),
+ tag_save_literal); /* We already looked it up! */
+ } else { /* Literal TAG */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| END (Literal Tag) "
+ "| %s</%s>",
+ *level, *codepage_stag, Indent (*level),
+ tag_save_literal);
+ }
+ (*level)--;
+ off++;
+ /* Reset code page: not needed as return from recursion */
+ DebugLog(("STAG: level = %u, Return: len = %u\n",
+ *level, off - offset));
+ return (off - offset);
+ break;
+ case 0x02: /* ENTITY */
+ ent = tvb_get_guintvar (tvb, off+1, &len);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| ENTITY "
+ "| %s'&#%u;'",
+ *level, *codepage_stag, Indent (*level), ent);
+ off += 1+len;
+ break;
+ case 0x03: /* STR_I */
+ len = tvb_strsize (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| STR_I (Inline string) "
+ "| %s\'%s\'",
+ *level, *codepage_stag, Indent(*level),
+ tvb_format_text (tvb, off+1, len-1));
+ off += 1+len;
+ break;
+ case 0x40: /* EXT_I_0 */
+ case 0x41: /* EXT_I_1 */
+ case 0x42: /* EXT_I_2 */
+ /* Extension tokens */
+ len = tvb_strsize (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| EXT_I_%1x (Extension Token) "
+ "| %s(Inline string extension: \'%s\')",
+ *level, *codepage_stag, peek & 0x0f, Indent (*level),
+ tvb_format_text (tvb, off+1, len-1));
+ off += 1+len;
+ break;
+ case 0x43: /* PI */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| PI (XML Processing Instruction) "
+ "| %s<?xml",
+ *level, *codepage_stag, Indent (*level));
+ len = parse_wbxml_attribute_list (tree, tvb, off, str_tbl,
+ *level, codepage_attr);
+ /* Check that there is still room in packet */
+ off += len;
+ if (off >= tvb_len) {
+ DebugLog(("STAG: level = %u, ThrowException: len = %u (short frame)\n",
+ *level, off - offset));
+ /*
+ * TODO - Do we need to free g_malloc()ed memory?
+ */
+ THROW(ReportedBoundsError);
+ }
+ proto_tree_add_text (tree, tvb, off-1, 1,
+ " %3d | Tag | T %3d "
+ "| END (PI) "
+ "| %s?>",
+ *level, *codepage_stag, Indent (*level));
+ break;
+ case 0x80: /* EXT_T_0 */
+ case 0x81: /* EXT_T_1 */
+ case 0x82: /* EXT_T_2 */
+ /* Extension tokens */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| EXT_T_%1x (Extension Token) "
+ "| %s(Extension Token, integer value: %u)",
+ *level, *codepage_stag, peek & 0x0f, Indent (*level),
+ index);
+ off += 1+len;
+ break;
+ case 0x83: /* STR_T */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ str_len = tvb_strsize (tvb, str_tbl+index);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| STR_T (Tableref string) "
+ "| %s\'%s\'",
+ *level, *codepage_stag, Indent (*level),
+ tvb_format_text (tvb, str_tbl+index, str_len-1));
+ off += 1+len;
+ break;
+ case 0xC0: /* EXT_0 */
+ case 0xC1: /* EXT_1 */
+ case 0xC2: /* EXT_2 */
+ /* Extension tokens */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| EXT_%1x (Extension Token) "
+ "| %s(Single-byte extension)",
+ *level, *codepage_stag, peek & 0x0f, Indent (*level));
+ off++;
+ break;
+ case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
+ if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ proto_tree_add_text (tree, tvb, off, 1 + len + index,
+ " %3d | Tag | T %3d "
+ "| OPAQUE (Opaque data) "
+ "| %s(%d bytes of opaque data)",
+ *level, *codepage_stag, Indent (*level), index);
+ off += 1+len+index;
+ } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| RESERVED_2 (Invalid Token!) "
+ "| WBXML 1.0 parsing stops here.",
+ *level, *codepage_stag);
+ /* Stop processing as it is impossible to parse now */
+ off = tvb_len;
+ DebugLog(("STAG: level = %u, Return: len = %u\n",
+ *level, off - offset));
+ return (off - offset);
+ }
+ break;
+
+ /* No default clause, as all cases have been treated */
+ } else { /* LITERAL or Known TAG */
+ /* We must store the initial tag, and also retrieve the new tag.
+ * For efficiency reasons, we store the literal tag representation
+ * for known tags too, so we can easily close the tag without the
+ * need of a new lookup and avoiding storage of token codepage.
+ *
+ * There are 4 possibilities:
+ *
+ * 1. Known tag followed by a known tag
+ * 2. Known tag followed by a LITERAL tag
+ * 3. LITERAL tag followed by Known tag
+ * 4. LITERAL tag followed by LITERAL tag
+ */
+
+ /* Store the new tag */
+ tag_len = 0;
+ if ((peek & 0x3F) == 4) { /* LITERAL */
+ DebugLog(("STAG: LITERAL tag (peek = 0x%02X, off = %u)"
+ " - TableRef follows!\n", peek, off));
+ index = tvb_get_guintvar (tvb, off+1, &tag_len);
+ str_len = tvb_strsize (tvb, str_tbl+index);
+ tag_new_literal = tvb_get_ptr (tvb, str_tbl+index, str_len);
+ tag_new_known = 0; /* invalidate known tag_new */
+ } else { /* Known tag */
+ tag_new_known = peek & 0x3F;
+ sprintf (tag_new_buf, "Tag_0x%02X",
+ tag_new_known);
+ tag_new_literal = tag_new_buf;
+ /* Stored looked up tag name string */
+ }
+
+ /* Parsing of TAG starts HERE */
+ if (peek & 0x40) { /* Content present */
+ /* Content follows
+ * [!] An explicit END token is expected in these cases!
+ * ==> Recursion possible if we encounter a tag with content;
+ * recursion will return at the explicit END token.
+ */
+ if (parsing_tag_content) { /* Recurse */
+ DebugLog(("STAG: Tag in Tag - RECURSE! (off = %u)\n", off));
+ /* Do not process the attribute list:
+ * recursion will take care of it */
+ (*level)++;
+ len = parse_wbxml_tag (tree, tvb, off, str_tbl, level,
+ codepage_stag, codepage_attr);
+ off += len;
+ } else { /* Now we will have content to parse */
+ /* Save the start tag so we can properly close it later. */
+ if ((peek & 0x3F) == 4) { /* Literal tag */
+ tag_save_literal = tag_new_literal;
+ tag_save_known = 0;
+ } else { /* Known tag */
+ tag_save_known = tag_new_known;
+ sprintf (tag_save_buf, "Tag_0x%02X",
+ tag_new_known);
+ tag_save_literal = tag_save_buf;
+ /* The last statement avoids needless lookups */
+ }
+ /* Process the attribute list if present */
+ if (peek & 0x80) { /* Content and Attribute list present */
+ if (tag_new_known) { /* Known tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| Known Tag 0x%02X (AC) "
+ "| %s<%s",
+ *level, *codepage_stag, tag_new_known,
+ Indent (*level), tag_new_literal);
+ /* Tag string already looked up earlier! */
+ off++;
+ } else { /* LITERAL tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| LITERAL_AC (Literal tag) (AC) "
+ "| %s<%s",
+ *level, *codepage_stag, Indent (*level),
+ tag_new_literal);
+ off += 1 + tag_len;
+ }
+ len = parse_wbxml_attribute_list (tree, tvb,
+ off, str_tbl, *level, codepage_attr);
+ /* Check that there is still room in packet */
+ off += len;
+ if (off >= tvb_len) {
+ DebugLog(("STAG: level = %u, ThrowException: "
+ "len = %u (short frame)\n",
+ *level, off - offset));
+ /*
+ * TODO - Do we need to free g_malloc()ed memory?
+ */
+ THROW(ReportedBoundsError);
+ }
+ proto_tree_add_text (tree, tvb, off-1, 1,
+ " %3d | Tag | T %3d "
+ "| END (attribute list) "
+ "| %s>",
+ *level, *codepage_stag, Indent (*level));
+ } else { /* Content, no Attribute list */
+ if (tag_new_known) { /* Known tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| Known Tag 0x%02X (.C) "
+ "| %s<%s>",
+ *level, *codepage_stag, tag_new_known,
+ Indent (*level), tag_new_literal);
+ /* Tag string already looked up earlier! */
+ off++;
+ } else { /* LITERAL tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| LITERAL_C (Literal Tag) (.C) "
+ "| %s<%s>",
+ *level, *codepage_stag, Indent (*level),
+ tag_new_literal);
+ off += 1 + tag_len;
+ }
+ }
+ /* The data that follows in the parsing process
+ * represents content for the opening tag
+ * we've just processed in the lines above.
+ * Next time we encounter a tag with content: recurse
+ */
+ parsing_tag_content = TRUE;
+ DebugLog(("Tag in Tag - No recursion this time! "
+ "(off = %u)\n", off));
+ }
+ } else { /* No Content */
+ DebugLog(("<Tag/> in Tag - No recursion! (off = %u)\n", off));
+ (*level)++;
+ if (peek & 0x80) { /* No Content, Attribute list present */
+ if (tag_new_known) { /* Known tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| Known Tag 0x%02X (A.) "
+ "| %s<%s",
+ *level, *codepage_stag, tag_new_known,
+ Indent (*level), tag_new_literal);
+ /* Tag string already looked up earlier! */
+ off++;
+ len = parse_wbxml_attribute_list (tree, tvb,
+ off, str_tbl, *level, codepage_attr);
+ /* Check that there is still room in packet */
+ off += len;
+ if (off >= tvb_len) {
+ DebugLog(("STAG: level = %u, ThrowException: "
+ "len = %u (short frame)\n",
+ *level, off - offset));
+ /*
+ * TODO - Do we need to free g_malloc()ed memory?
+ */
+ THROW(ReportedBoundsError);
+ }
+ proto_tree_add_text (tree, tvb, off-1, 1,
+ " %3d | Tag | T %3d "
+ "| END (Known Tag) "
+ "| %s/>",
+ *level, *codepage_stag, Indent (*level));
+ } else { /* LITERAL tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| LITERAL_A (Literal Tag) (A.) "
+ "| %s<%s",
+ *level, *codepage_stag, Indent (*level),
+ tag_new_literal);
+ off += 1 + tag_len;
+ len = parse_wbxml_attribute_list (tree, tvb,
+ off, str_tbl, *level, codepage_attr);
+ /* Check that there is still room in packet */
+ off += len;
+ if (off >= tvb_len) {
+ DebugLog(("STAG: level = %u, ThrowException: "
+ "len = %u (short frame)\n",
+ *level, off - offset));
+ /*
+ * TODO - Do we need to free g_malloc()ed memory?
+ */
+ THROW(ReportedBoundsError);
+ }
+ proto_tree_add_text (tree, tvb, off-1, 1,
+ " %3d | Tag | T %3d "
+ "| END (Literal Tag) "
+ "| %s/>",
+ *level, *codepage_stag, Indent (*level));
+ }
+ } else { /* No Content, No Attribute list */
+ if (tag_new_known) { /* Known tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| Known Tag 0x%02x (..) "
+ "| %s<%s />",
+ *level, *codepage_stag, tag_new_known,
+ Indent (*level), tag_new_literal);
+ /* Tag string already looked up earlier! */
+ off++;
+ } else { /* LITERAL tag */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Tag | T %3d "
+ "| LITERAL (Literal Tag) (..) "
+ "| %s<%s />",
+ *level, *codepage_stag, Indent (*level),
+ tag_new_literal);
+ off += 1 + tag_len;
+ }
+ }
+ (*level)--;
+ /* TODO: Do I have to reset code page here? */
+ }
+ } /* if (tag & 0x3F) >= 5 */
+ } /* while */
+ DebugLog(("STAG: level = %u, Return: len = %u (end of function body)\n",
+ *level, off - offset));
+ return (off - offset);
+}
+
+
+/**************************
+ * WBXML Attribute tokens *
+ **************************
+ * Bit Mask : Example
+ * -------------------
+ * 0... .... : attr= (attribute name)
+ * href='http://' (attribute name with start of attribute value)
+ * 1... .... : 'www.' (attribute value, or part of it)
+ *
+ */
+
+
+/* This function parses the WBXML and maps known token interpretations
+ * to the WBXML tokens. As a result, the original XML document can be
+ * recreated. Indentation is generated in order to ease reading.
+ *
+ * This function performs attribute list parsing.
+ *
+ * The wbxml_decoding entry *map contains the actual token mapping.
+ *
+ * NOTE: See above for known token mappings.
+ */
+static guint32
+parse_wbxml_attribute_list_defined (proto_tree *tree, tvbuff_t *tvb,
+ guint32 offset, guint32 str_tbl, guint8 level, guint8 *codepage_attr,
+ const wbxml_decoding *map)
+{
+ guint32 tvb_len = tvb_reported_length (tvb);
+ guint32 off = offset;
+ guint32 len;
+ guint str_len;
+ guint32 ent;
+ guint32 index;
+ guint8 peek;
+ guint8 attr_save_known = 0; /* Will contain peek & 0x3F (attr identity) */
+ const char *attr_save_literal = NULL; /* Will contain the LITERAL attr identity */
+
+ DebugLog(("parse_wbxml_attr_defined (level = %u, offset = %u)\n",
+ level, offset));
+ /* Parse attributes */
+ while (off < tvb_len) {
+ peek = tvb_get_guint8 (tvb, off);
+ DebugLog(("ATTR: (top of while) level = %3u, peek = 0x%02X, "
+ "off = %u, tvb_len = %u\n", level, peek, off, tvb_len));
+ if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
+ in state = ATTR */
+ case 0x00: /* SWITCH_PAGE */
+ *codepage_attr = tvb_get_guint8 (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 2,
+ " | Attr | A -->%3d "
+ "| SWITCH_PAGE (Attr code page) |",
+ *codepage_attr);
+ off += 2;
+ break;
+ case 0x01: /* END */
+ /* BEWARE
+ * The Attribute END token means either ">" or "/>"
+ * and as a consequence both must be treated separately.
+ * This is done in the TAG state parser.
+ */
+ off++;
+ DebugLog(("ATTR: level = %u, Return: len = %u\n",
+ level, off - offset));
+ return (off - offset);
+ case 0x02: /* ENTITY */
+ ent = tvb_get_guintvar (tvb, off+1, &len);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| ENTITY "
+ "| %s'&#%u;'",
+ level, *codepage_attr, Indent (level), ent);
+ off += 1+len;
+ break;
+ case 0x03: /* STR_I */
+ len = tvb_strsize (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| STR_I (Inline string) "
+ "| %s\'%s\'",
+ level, *codepage_attr, Indent (level),
+ tvb_format_text (tvb, off+1, len-1));
+ off += 1+len;
+ break;
+ case 0x04: /* LITERAL */
+ /* ALWAYS means the start of a new attribute,
+ * and may only contain the NAME of the attribute.
+ */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ str_len = tvb_strsize (tvb, str_tbl+index);
+ attr_save_known = 0;
+ attr_save_literal = tvb_format_text (tvb,
+ str_tbl+index, str_len-1);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| LITERAL (Literal Attribute) "
+ "| %s<%s />",
+ level, *codepage_attr, Indent (level),
+ attr_save_literal);
+ off += 1+len;
+ break;
+ case 0x40: /* EXT_I_0 */
+ case 0x41: /* EXT_I_1 */
+ case 0x42: /* EXT_I_2 */
+ /* Extension tokens */
+ len = tvb_strsize (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| EXT_I_%1x (Extension Token) "
+ "| %s(%s: \'%s\')",
+ level, *codepage_attr, peek & 0x0f, Indent (level),
+ map_token (map->global, 0, peek),
+ tvb_format_text (tvb, off+1, len-1));
+ off += 1+len;
+ break;
+ /* 0x43 impossible in ATTR state */
+ /* 0x44 impossible in ATTR state */
+ case 0x80: /* EXT_T_0 */
+ case 0x81: /* EXT_T_1 */
+ case 0x82: /* EXT_T_2 */
+ /* Extension tokens */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ { char *s;
+
+ if (map->ext_t[peek & 0x03])
+ s = (map->ext_t[peek & 0x03])(tvb, index, str_tbl);
+ else
+ s = g_strdup_printf("EXT_T_%1x (%s)", peek & 0x03,
+ map_token (map->global, 0, peek));
+
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Tag | T %3d "
+ "| EXT_T_%1x (Extension Token) "
+ "| %s%s)",
+ level, *codepage_attr, peek & 0x0f, Indent (level),
+ s);
+ g_free(s);
+ }
+ off += 1+len;
+ break;
+ case 0x83: /* STR_T */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ str_len = tvb_strsize (tvb, str_tbl+index);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| STR_T (Tableref string) "
+ "| %s\'%s\'",
+ level, *codepage_attr, Indent (level),
+ tvb_format_text (tvb, str_tbl+index, str_len-1));
+ off += 1+len;
+ break;
+ /* 0x84 impossible in ATTR state */
+ case 0xC0: /* EXT_0 */
+ case 0xC1: /* EXT_1 */
+ case 0xC2: /* EXT_2 */
+ /* Extension tokens */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| EXT_%1x (Extension Token) "
+ "| %s(%s)",
+ level, *codepage_attr, peek & 0x0f, Indent (level),
+ map_token (map->global, 0, peek));
+ off++;
+ break;
+ case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
+ if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
+ char *str;
+ if (attr_save_known) { /* Knwon attribute */
+ if (map->opaque_binary_attr) {
+ str = map->opaque_binary_attr(tvb, off + 1,
+ attr_save_known, *codepage_attr, &len);
+ } else {
+ str = default_opaque_binary_attr(tvb, off + 1,
+ attr_save_known, *codepage_attr, &len);
+ }
+ } else { /* lITERAL attribute */
+ if (map->opaque_literal_tag) {
+ str = map->opaque_literal_attr(tvb, off + 1,
+ attr_save_literal, *codepage_attr, &len);
+ } else {
+ str = default_opaque_literal_attr(tvb, off + 1,
+ attr_save_literal, *codepage_attr, &len);
+ }
+ }
+ proto_tree_add_text (tree, tvb, off, 1 + len,
+ " %3d | Attr | A %3d "
+ "| OPAQUE (Opaque data) "
+ "| %s%s",
+ level, *codepage_attr, Indent (level), str);
+ g_free(str);
+ off += 1 + len;
+ } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| RESERVED_2 (Invalid Token!) "
+ "| WBXML 1.0 parsing stops here.",
+ level, *codepage_attr);
+ /* Stop processing as it is impossible to parse now */
+ off = tvb_len;
+ DebugLog(("ATTR: level = %u, Return: len = %u\n",
+ level, off - offset));
+ return (off - offset);
+ }
+ break;
+ /* 0xC4 impossible in ATTR state */
+ default:
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| %-10s (Invalid Token!) "
+ "| WBXML parsing stops here.",
+ level, *codepage_attr,
+ match_strval (peek, vals_wbxml1x_global_tokens));
+ /* Move to end of buffer */
+ off = tvb_len;
+ break;
+ } else { /* Known atribute token */
+ if (peek & 0x80) { /* attrValue */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| Known attrValue 0x%02X "
+ "| %s%s",
+ level, *codepage_attr, peek & 0x7f, Indent (level),
+ map_token (map->attrValue, *codepage_attr, peek));
+ off++;
+ } else { /* attrStart */
+ attr_save_known = peek & 0x7f;
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| Known attrStart 0x%02X "
+ "| %s%s",
+ level, *codepage_attr, attr_save_known, Indent (level),
+ map_token (map->attrStart, *codepage_attr, peek));
+ off++;
+ }
+ }
+ } /* End WHILE */
+ DebugLog(("ATTR: level = %u, Return: len = %u (end of function body)\n",
+ level, off - offset));
+ return (off - offset);
+}
+
+
+/* This function performs the WBXML attribute decoding as in
+ * parse_wbxml_attribute_list_defined() but this time no WBXML mapping
+ * is performed.
+ *
+ * This function performs attribute list parsing.
+ *
+ * NOTE: Code page switches not yet processed in the code!
+ */
+static guint32
+parse_wbxml_attribute_list (proto_tree *tree, tvbuff_t *tvb,
+ guint32 offset, guint32 str_tbl, guint8 level, guint8 *codepage_attr)
+{
+ guint32 tvb_len = tvb_reported_length (tvb);
+ guint32 off = offset;
+ guint32 len;
+ guint str_len;
+ guint32 ent;
+ guint32 index;
+ guint8 peek;
+
+ DebugLog(("parse_wbxml_attr (level = %u, offset = %u)\n", level, offset));
+ /* Parse attributes */
+ while (off < tvb_len) {
+ peek = tvb_get_guint8 (tvb, off);
+ DebugLog(("ATTR: (top of while) level = %3u, peek = 0x%02X, "
+ "off = %u, tvb_len = %u\n", level, peek, off, tvb_len));
+ if ((peek & 0x3F) < 5) switch (peek) { /* Global tokens
+ in state = ATTR */
+ case 0x00: /* SWITCH_PAGE */
+ *codepage_attr = tvb_get_guint8 (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 2,
+ " | Attr | A -->%3d "
+ "| SWITCH_PAGE (Attr code page) |",
+ *codepage_attr);
+ off += 2;
+ break;
+ case 0x01: /* END */
+ /* BEWARE
+ * The Attribute END token means either ">" or "/>"
+ * and as a consequence both must be treated separately.
+ * This is done in the TAG state parser.
+ */
+ off++;
+ DebugLog(("ATTR: level = %u, Return: len = %u\n",
+ level, off - offset));
+ return (off - offset);
+ case 0x02: /* ENTITY */
+ ent = tvb_get_guintvar (tvb, off+1, &len);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| ENTITY "
+ "| %s'&#%u;'",
+ level, *codepage_attr, Indent (level), ent);
+ off += 1+len;
+ break;
+ case 0x03: /* STR_I */
+ len = tvb_strsize (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| STR_I (Inline string) "
+ "| %s\'%s\'",
+ level, *codepage_attr, Indent (level),
+ tvb_format_text (tvb, off+1, len-1));
+ off += 1+len;
+ break;
+ case 0x04: /* LITERAL */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ str_len = tvb_strsize (tvb, str_tbl+index);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| LITERAL (Literal Attribute) "
+ "| %s<%s />",
+ level, *codepage_attr, Indent (level),
+ tvb_format_text (tvb, str_tbl+index, str_len-1));
+ off += 1+len;
+ break;
+ case 0x40: /* EXT_I_0 */
+ case 0x41: /* EXT_I_1 */
+ case 0x42: /* EXT_I_2 */
+ /* Extension tokens */
+ len = tvb_strsize (tvb, off+1);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| EXT_I_%1x (Extension Token) "
+ "| %s(Inline string extension: \'%s\')",
+ level, *codepage_attr, peek & 0x0f, Indent (level),
+ tvb_format_text (tvb, off+1, len-1));
+ off += 1+len;
+ break;
+ /* 0x43 impossible in ATTR state */
+ /* 0x44 impossible in ATTR state */
+ case 0x80: /* EXT_T_0 */
+ case 0x81: /* EXT_T_1 */
+ case 0x82: /* EXT_T_2 */
+ /* Extension tokens */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| EXT_T_%1x (Extension Token) "
+ "| %s(Extension Token, integer value: %u)",
+ level, *codepage_attr, peek & 0x0f, Indent (level),
+ index);
+ off += 1+len;
+ break;
+ case 0x83: /* STR_T */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ str_len = tvb_strsize (tvb, str_tbl+index);
+ proto_tree_add_text (tree, tvb, off, 1+len,
+ " %3d | Attr | A %3d "
+ "| STR_T (Tableref string) "
+ "| %s\'%s\'",
+ level, *codepage_attr, Indent (level),
+ tvb_format_text (tvb, str_tbl+index, str_len-1));
+ off += 1+len;
+ break;
+ /* 0x84 impossible in ATTR state */
+ case 0xC0: /* EXT_0 */
+ case 0xC1: /* EXT_1 */
+ case 0xC2: /* EXT_2 */
+ /* Extension tokens */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| EXT_%1x (Extension Token) "
+ "| %s(Single-byte extension)",
+ level, *codepage_attr, peek & 0x0f, Indent (level));
+ off++;
+ break;
+ case 0xC3: /* OPAQUE - WBXML 1.1 and newer */
+ if (tvb_get_guint8 (tvb, 0)) { /* WBXML 1.x (x > 0) */
+ index = tvb_get_guintvar (tvb, off+1, &len);
+ proto_tree_add_text (tree, tvb, off, 1 + len + index,
+ " %3d | Attr | A %3d "
+ "| OPAQUE (Opaque data) "
+ "| %s(%d bytes of opaque data)",
+ level, *codepage_attr, Indent (level), index);
+ off += 1+len+index;
+ } else { /* WBXML 1.0 - RESERVED_2 token (invalid) */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| RESERVED_2 (Invalid Token!) "
+ "| WBXML 1.0 parsing stops here.",
+ level, *codepage_attr);
+ /* Stop processing as it is impossible to parse now */
+ off = tvb_len;
+ DebugLog(("ATTR: level = %u, Return: len = %u\n",
+ level, off - offset));
+ return (off - offset);
+ }
+ break;
+ /* 0xC4 impossible in ATTR state */
+ default:
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| %-10s (Invalid Token!) "
+ "| WBXML parsing stops here.",
+ level, *codepage_attr,
+ match_strval (peek, vals_wbxml1x_global_tokens));
+ /* Move to end of buffer */
+ off = tvb_len;
+ break;
+ } else { /* Known atribute token */
+ if (peek & 0x80) { /* attrValue */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| Known attrValue 0x%02X "
+ "| %sattrValue_0x%02X",
+ level, *codepage_attr, peek & 0x7f, Indent (level),
+ peek);
+ off++;
+ } else { /* attrStart */
+ proto_tree_add_text (tree, tvb, off, 1,
+ " %3d | Attr | A %3d "
+ "| Known attrStart 0x%02X "
+ "| %sattrStart_0x%02X",
+ level, *codepage_attr, peek & 0x7f, Indent (level),
+ peek);
+ off++;
+ }
+ }
+ } /* End WHILE */
+ DebugLog(("ATTR: level = %u, Return: len = %u (end of function body)\n",
+ level, off - offset));
+ return (off - offset);
+}
+
+
+/****************** Register the protocol with Ethereal ******************/
+
+
+/* This format is required because a script is used to build the C function
+ * that calls the protocol registration. */
+
+void
+proto_register_wbxml(void)
+{
+ module_t *wbxml_module; /* WBXML Preferences */
+
+ /* Setup list of header fields. */
+ static hf_register_info hf[] = {
+ { &hf_wbxml_version,
+ { "Version",
+ "wbxml.version",
+ FT_UINT8, BASE_HEX,
+ VALS ( vals_wbxml_versions ), 0x00,
+ "WBXML Version", HFILL }
+ },
+ { &hf_wbxml_public_id_known,
+ { "Public Identifier (known)",
+ "wbxml.public_id.known",
+ FT_UINT32, BASE_HEX,
+ VALS ( vals_wbxml_public_ids ), 0x00,
+ "WBXML Known Public Identifier (integer)", HFILL }
+ },
+ { &hf_wbxml_public_id_literal,
+ { "Public Identifier (literal)",
+ "wbxml.public_id.literal",
+ FT_STRING, BASE_NONE,
+ NULL, 0x00,
+ "WBXML Literal Public Identifier (text string)", HFILL }
+ },
+ { &hf_wbxml_charset,
+ { "Character Set",
+ "wbxml.charset",
+ FT_UINT32, BASE_HEX,
+ VALS ( vals_character_sets ), 0x00,
+ "WBXML Character Set", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_wbxml,
+ &ett_wbxml_str_tbl,
+ &ett_wbxml_content,
+ };
+
+ /* Register the protocol name and description */
+ proto_wbxml = proto_register_protocol(
+ "WAP Binary XML",
+ "WBXML",
+ "wbxml"
+ );
+
+ /* Required function calls to register the header fields
+ * and subtrees used */
+ proto_register_field_array(proto_wbxml, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Preferences */
+ wbxml_module = prefs_register_protocol(proto_wbxml, NULL);
+ prefs_register_bool_preference(wbxml_module,
+ "skip_wbxml_token_mapping",
+ "Skip the mapping of WBXML tokens to media type tokens.",
+ "Enable this preference if you want to view the WBXML "
+ "tokens without the representation in a media type "
+ "(e.g., WML). Tokens will show up as Tag_0x12, "
+ "attrStart_0x08 or attrValue_0x0B for example.",
+ &skip_wbxml_token_mapping);
+ prefs_register_bool_preference(wbxml_module,
+ "disable_wbxml_token_parsing",
+ "Disable the parsing of the WBXML tokens.",
+ "Enable this preference if you want to skip the "
+ "parsing of the WBXML tokens that constitute the body "
+ "of the WBXML document. Only the WBXML header will be "
+ "dissected (and visualized) then.",
+ &disable_wbxml_token_parsing);
+
+ register_dissector("wbxml", dissect_wbxml, proto_wbxml);
+ register_dissector("wbxml-uaprof", dissect_uaprof, proto_wbxml);
+}
+
+
+void
+proto_reg_handoff_wbxml(void)
+{
+ dissector_handle_t wbxml_handle;
+
+ /* Heuristic dissectors would be declared by means of:
+ * heur_dissector_add("wsp", dissect_wbxml_heur, proto_wbxml);
+ */
+
+ wbxml_handle = create_dissector_handle(dissect_wbxml, proto_wbxml);
+
+ /* Register the WSP content types (defined as protocol port)
+ * for WBXML dissection.
+ *
+ * See http://www.wapforum.org/wina/wsp-content-type.htm
+ *
+ * As the media types for WSP and HTTP are the same, the WSP dissector
+ * uses the same string dissector table as the HTTP protocol.
+ */
+
+ /**** Well-known WBXML WSP Content-Type values ****/
+
+ dissector_add_string("media_type",
+ "application/vnd.wap.wmlc", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.wap.wta-eventc", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.wap.wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.wap.sic", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.wap.slc", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.wap.coc", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.wap.connectivity-wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.wap.locc+wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.syncml+wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.syncml.dm+wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.oma.drm.rights+wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.wv.csp.wbxml", wbxml_handle);
+
+ /**** Registered WBXML WSP Content-Type values ****/
+
+ dissector_add_string("media_type",
+ "application/vnd.uplanet.cacheop-wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.uplanet.alert-wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.uplanet.list-wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.uplanet.listcmd-wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.uplanet.channel-wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.uplanet.bearer-choice-wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.phonecom.mmc-wbxml", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/vnd.nokia.syncset+wbxml", wbxml_handle);
+
+ /***** Content types that only have a textual representation *****/
+ dissector_add_string("media_type",
+ "application/x-wap-prov.browser-bookmarks", wbxml_handle);
+ dissector_add_string("media_type",
+ "application/x-wap-prov.browser-settings", wbxml_handle);
+ /* Same as application/vnd.nokia.syncset+wbxml */
+ dissector_add_string("media_type",
+ "application/x-prov.syncset+wbxml", wbxml_handle);
+}
diff --git a/epan/dissectors/packet-wccp.c b/epan/dissectors/packet-wccp.c
new file mode 100644
index 0000000000..ef5d89fb62
--- /dev/null
+++ b/epan/dissectors/packet-wccp.c
@@ -0,0 +1,1323 @@
+/* packet-wccp.c
+ * Routines for Web Cache Coordination Protocol dissection
+ * Jerry Talkington <jtalkington@users.sourceforge.net>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "packet-wccp.h"
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+static int proto_wccp = -1;
+static int hf_wccp_message_type = -1; /* the message type */
+static int hf_wccp_version = -1; /* protocol version */
+static int hf_hash_revision = -1; /* the version of the hash */
+static int hf_change_num = -1; /* change number */
+static int hf_recvd_id = -1;
+static int hf_cache_ip = -1;
+
+static gint ett_wccp = -1;
+static gint ett_cache_count = -1;
+static gint ett_buckets = -1;
+static gint ett_flags = -1;
+static gint ett_cache_info = -1;
+static gint ett_security_info = -1;
+static gint ett_service_info = -1;
+static gint ett_service_flags = -1;
+static gint ett_router_identity_element = -1;
+static gint ett_router_identity_info = -1;
+static gint ett_wc_identity_element = -1;
+static gint ett_wc_identity_info = -1;
+static gint ett_router_view_info = -1;
+static gint ett_wc_view_info = -1;
+static gint ett_router_assignment_element = -1;
+static gint ett_router_assignment_info = -1;
+static gint ett_query_info = -1;
+static gint ett_capabilities_info = -1;
+static gint ett_capability_element = -1;
+static gint ett_capability_forwarding_method = -1;
+static gint ett_capability_assignment_method = -1;
+static gint ett_capability_return_method = -1;
+static gint ett_unknown_info = -1;
+
+/*
+ * At
+ *
+ * http://www.alternic.org/drafts/drafts-f-g/draft-forster-wrec-wccp-v1-00.html
+ *
+ * is a copy of the now-expired Internet-Draft for WCCP 1.0.
+ *
+ * At
+ *
+ * http://search.ietf.org/internet-drafts/draft-wilson-wrec-wccp-v2-01.txt
+ *
+ * is an Internet-Draft for WCCP 2.0.
+ */
+
+#define UDP_PORT_WCCP 2048
+
+#define WCCPv1 4
+#define WCCPv2 0x0200
+#define WCCP_HERE_I_AM 7
+#define WCCP_I_SEE_YOU 8
+#define WCCP_ASSIGN_BUCKET 9
+#define WCCP2_HERE_I_AM 10
+#define WCCP2_I_SEE_YOU 11
+#define WCCP2_REDIRECT_ASSIGN 12
+#define WCCP2_REMOVAL_QUERY 13
+
+static const value_string wccp_type_vals[] = {
+ { WCCP_HERE_I_AM, "1.0 Here I am" },
+ { WCCP_I_SEE_YOU, "1.0 I see you" },
+ { WCCP_ASSIGN_BUCKET, "1.0 Assign bucket" },
+ { WCCP2_HERE_I_AM, "2.0 Here I am" },
+ { WCCP2_I_SEE_YOU, "2.0 I see you" },
+ { WCCP2_REDIRECT_ASSIGN, "2.0 Redirect assign" },
+ { WCCP2_REMOVAL_QUERY, "2.0 Removal query" },
+ { 0, NULL }
+};
+
+static const value_string wccp_version_val[] = {
+ { WCCPv1, "1"},
+ { WCCPv2, "2"},
+ { 0, NULL}
+};
+
+#define HASH_INFO_SIZE (4*(1+8+1))
+
+#define WCCP_U_FLAG 0x80000000
+
+#define WCCP2_SECURITY_INFO 0
+#define WCCP2_SERVICE_INFO 1
+#define WCCP2_ROUTER_ID_INFO 2
+#define WCCP2_WC_ID_INFO 3
+#define WCCP2_RTR_VIEW_INFO 4
+#define WCCP2_WC_VIEW_INFO 5
+#define WCCP2_REDIRECT_ASSIGNMENT 6
+#define WCCP2_QUERY_INFO 7
+#define WCCP2_CAPABILITIES_INFO 8
+#define WCCP2_ALT_ASSIGNMENT 13
+#define WCCP2_ASSIGN_MAP 14
+#define WCCP2_COMMAND_EXTENSION 15
+
+static const value_string info_type_vals[] = {
+ { WCCP2_SECURITY_INFO, "Security Info" },
+ { WCCP2_SERVICE_INFO, "Service Info" },
+ { WCCP2_ROUTER_ID_INFO, "Router Identity Info" },
+ { WCCP2_WC_ID_INFO, "Web-Cache Identity Info" },
+ { WCCP2_RTR_VIEW_INFO, "Router View Info" },
+ { WCCP2_WC_VIEW_INFO, "Web-Cache View Info" },
+ { WCCP2_REDIRECT_ASSIGNMENT, "Assignment Info" },
+ { WCCP2_QUERY_INFO, "Query Info" },
+ { WCCP2_CAPABILITIES_INFO, "Capabilities Info" },
+ { WCCP2_COMMAND_EXTENSION, "Command Extension" },
+ { 0, NULL }
+};
+
+const value_string service_id_vals[] = {
+ { 0x00, "HTTP" },
+ { 0, NULL }
+};
+
+typedef struct capability_flag {
+ guint32 value;
+ const char *short_name;
+ const char *long_name;
+} capability_flag;
+
+static void dissect_hash_data(tvbuff_t *tvb, int offset,
+ proto_tree *wccp_tree);
+static void dissect_web_cache_list_entry(tvbuff_t *tvb, int offset,
+ int index, proto_tree *wccp_tree);
+static int wccp_bucket_info(guint8 bucket_info, proto_tree *bucket_tree,
+ guint32 start, tvbuff_t *tvb, int offset);
+static gchar *bucket_name(guint8 bucket);
+static guint16 dissect_wccp2_header(tvbuff_t *tvb, int offset,
+ proto_tree *wccp_tree);
+static void dissect_wccp2_info(tvbuff_t *tvb, int offset, guint16 length,
+ proto_tree *wccp_tree);
+static gboolean dissect_wccp2_security_info(tvbuff_t *tvb, int offset,
+ int length, proto_tree *info_tree);
+static gboolean dissect_wccp2_service_info(tvbuff_t *tvb, int offset,
+ int length, proto_tree *info_tree);
+static gboolean dissect_wccp2_router_identity_info(tvbuff_t *tvb,
+ int offset, int length, proto_tree *info_tree);
+static gboolean dissect_wccp2_wc_identity_info(tvbuff_t *tvb, int offset,
+ int length, proto_tree *info_tree);
+static gboolean dissect_wccp2_router_view_info(tvbuff_t *tvb, int offset,
+ int length, proto_tree *info_tree);
+static gboolean dissect_wccp2_wc_view_info(tvbuff_t *tvb, int offset,
+ int length, proto_tree *info_tree);
+static gboolean dissect_wccp2_assignment_info(tvbuff_t *tvb, int offset,
+ int length, proto_tree *info_tree);
+static gboolean dissect_wccp2_router_query_info(tvbuff_t *tvb, int offset,
+ int length, proto_tree *info_tree);
+static gboolean dissect_wccp2_capability_info(tvbuff_t *tvb, int offset,
+ int length, proto_tree *info_tree);
+static void dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
+ guint16 capability_val_len, gint ett, const capability_flag *flags,
+ proto_tree *element_tree);
+
+static void
+dissect_wccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *wccp_tree = NULL;
+ proto_item *wccp_tree_item;
+ guint32 wccp_message_type;
+ guint16 length;
+ guint32 cache_count;
+ guint32 ipaddr;
+ guint i;
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WCCP");
+ }
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+
+ wccp_message_type = tvb_get_ntohl(tvb, offset);
+
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(wccp_message_type,
+ wccp_type_vals, "Unknown WCCP message (%u)"));
+ }
+
+ if(tree != NULL) {
+ wccp_tree_item = proto_tree_add_item(tree, proto_wccp, tvb, offset,
+ -1, FALSE);
+ wccp_tree = proto_item_add_subtree(wccp_tree_item, ett_wccp);
+
+ proto_tree_add_uint(wccp_tree, hf_wccp_message_type, tvb, offset,
+ sizeof(wccp_message_type), wccp_message_type);
+ offset += sizeof(wccp_message_type);
+
+ switch (wccp_message_type) {
+
+ case WCCP_HERE_I_AM:
+ proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ dissect_hash_data(tvb, offset, wccp_tree);
+ offset += HASH_INFO_SIZE;
+ proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ break;
+
+ case WCCP_I_SEE_YOU:
+ proto_tree_add_item(wccp_tree, hf_wccp_version, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(wccp_tree, hf_change_num, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ cache_count = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(wccp_tree, tvb, offset, 4,
+ "Number of Web Caches: %u", cache_count);
+ offset += 4;
+ for (i = 0; i < cache_count; i++) {
+ dissect_web_cache_list_entry(tvb, offset, i,
+ wccp_tree);
+ offset += 4 + HASH_INFO_SIZE;
+ }
+ break;
+
+ case WCCP_ASSIGN_BUCKET:
+ /*
+ * This hasn't been tested, since I don't have any
+ * traces with this in it.
+ *
+ * The V1 spec claims that this does, indeed,
+ * have a Received ID field after the type,
+ * rather than a Version field.
+ */
+ proto_tree_add_item(wccp_tree, hf_recvd_id, tvb, offset,
+ 4, FALSE);
+ offset += 4;
+ cache_count = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(wccp_tree, tvb, offset, 4,
+ "Number of Web Caches: %u", cache_count);
+ offset += 4;
+ for (i = 0; i < cache_count; i++) {
+ tvb_memcpy(tvb, (guint8 *)&ipaddr, offset, 4);
+ proto_tree_add_ipv4_format(wccp_tree,
+ hf_cache_ip, tvb, offset, 4,
+ ipaddr,
+ "Web Cache %d IP Address: %s", i,
+ ip_to_str((guint8 *)&ipaddr));
+ offset += 4;
+ }
+ for (i = 0; i < 256; i += 4) {
+ proto_tree_add_text(wccp_tree, tvb, offset, 4,
+ "Buckets %d - %d: %10s %10s %10s %10s",
+ i, i + 3,
+ bucket_name(tvb_get_guint8(tvb, offset)),
+ bucket_name(tvb_get_guint8(tvb, offset+1)),
+ bucket_name(tvb_get_guint8(tvb, offset+2)),
+ bucket_name(tvb_get_guint8(tvb, offset+3)));
+ offset += 4;
+ }
+ break;
+
+ case WCCP2_HERE_I_AM:
+ case WCCP2_I_SEE_YOU:
+ case WCCP2_REMOVAL_QUERY:
+ case WCCP2_REDIRECT_ASSIGN:
+ default: /* assume unknown packets are v2 */
+ length = dissect_wccp2_header(tvb, offset, wccp_tree);
+ offset += 4;
+ dissect_wccp2_info(tvb, offset, length, wccp_tree);
+ break;
+ }
+ }
+}
+
+static void
+dissect_hash_data(tvbuff_t *tvb, int offset, proto_tree *wccp_tree)
+{
+ proto_item *bucket_item;
+ proto_tree *bucket_tree;
+ proto_item *tf;
+ proto_tree *field_tree;
+ int i;
+ guint8 bucket_info;
+ int n;
+ guint32 flags;
+
+ proto_tree_add_item(wccp_tree, hf_hash_revision, tvb, offset, 4,
+ FALSE);
+ offset += 4;
+
+ bucket_item = proto_tree_add_text(wccp_tree, tvb, offset, 32,
+ "Hash information");
+ bucket_tree = proto_item_add_subtree(bucket_item, ett_buckets);
+
+ for (i = 0, n = 0; i < 32; i++) {
+ bucket_info = tvb_get_guint8(tvb, offset);
+ n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
+ offset += 1;
+ }
+ flags = tvb_get_ntohl(tvb, offset);
+ tf = proto_tree_add_text(wccp_tree, tvb, offset, 4,
+ "Flags: 0x%08X (%s)", flags,
+ ((flags & WCCP_U_FLAG) ?
+ "Hash information is historical" :
+ "Hash information is current"));
+ field_tree = proto_item_add_subtree(tf, ett_flags);
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP_U_FLAG,
+ sizeof (flags)*8,
+ "Hash information is historical",
+ "Hash information is current"));
+}
+
+static void
+dissect_web_cache_list_entry(tvbuff_t *tvb, int offset, int index,
+ proto_tree *wccp_tree)
+{
+ proto_item *tl;
+ proto_tree *list_entry_tree;
+
+ tl = proto_tree_add_text(wccp_tree, tvb, offset, 4 + HASH_INFO_SIZE,
+ "Web-Cache List Entry(%d)", index);
+ list_entry_tree = proto_item_add_subtree(tl, ett_cache_info);
+ proto_tree_add_item(list_entry_tree, hf_cache_ip, tvb, offset, 4,
+ FALSE);
+ dissect_hash_data(tvb, offset + 4, list_entry_tree);
+}
+
+/*
+ * wccp_bucket_info()
+ * takes an integer representing a "Hash Information" bitmap, and spits out
+ * the corresponding proto_tree entries, returning the next bucket number.
+ */
+static int
+wccp_bucket_info(guint8 bucket_info, proto_tree *bucket_tree, guint32 start,
+ tvbuff_t *tvb, int offset)
+{
+ guint32 i;
+
+ for(i = 0; i < 8; i++) {
+ proto_tree_add_text(bucket_tree, tvb, offset, sizeof(bucket_info), "Bucket %3d: %s", start, (bucket_info & 1<<i ? "Assigned" : "Not Assigned") );
+ start++;
+ }
+ return(start);
+}
+
+static gchar *
+bucket_name(guint8 bucket)
+{
+ static gchar str[4][10+1];
+ static gchar *cur;
+
+ if (cur == &str[0][0])
+ cur = &str[1][0];
+ else if (cur == &str[1][0])
+ cur = &str[2][0];
+ else if (cur == &str[2][0])
+ cur = &str[3][0];
+ else
+ cur = &str[0][0];
+ if (bucket == 0xff)
+ strcpy(cur, "Unassigned");
+ else
+ sprintf(cur, "%u", bucket);
+ return cur;
+}
+
+static guint16
+dissect_wccp2_header(tvbuff_t *tvb, int offset, proto_tree *wccp_tree)
+{
+ guint16 length;
+
+ proto_tree_add_item(wccp_tree, hf_wccp_version, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(wccp_tree, tvb, offset, 2, "Length: %u",
+ length);
+ return length;
+}
+
+static void
+dissect_wccp2_info(tvbuff_t *tvb, int offset, guint16 length,
+ proto_tree *wccp_tree)
+{
+ guint16 type;
+ guint16 item_length;
+ proto_item *ti;
+ proto_tree *info_tree;
+ gint ett;
+ gboolean (*dissector)(tvbuff_t *, int, int, proto_tree *);
+
+ while (length != 0) {
+ type = tvb_get_ntohs(tvb, offset);
+ item_length = tvb_get_ntohs(tvb, offset+2);
+
+ switch (type) {
+
+ case WCCP2_SECURITY_INFO:
+ ett = ett_security_info;
+ dissector = dissect_wccp2_security_info;
+ break;
+
+ case WCCP2_SERVICE_INFO:
+ ett = ett_service_info;
+ dissector = dissect_wccp2_service_info;
+ break;
+
+ case WCCP2_ROUTER_ID_INFO:
+ ett = ett_router_identity_info;
+ dissector = dissect_wccp2_router_identity_info;
+ break;
+
+ case WCCP2_WC_ID_INFO:
+ ett = ett_wc_identity_info;
+ dissector = dissect_wccp2_wc_identity_info;
+ break;
+
+ case WCCP2_RTR_VIEW_INFO:
+ ett = ett_router_view_info;
+ dissector = dissect_wccp2_router_view_info;
+ break;
+
+ case WCCP2_WC_VIEW_INFO:
+ ett = ett_wc_view_info;
+ dissector = dissect_wccp2_wc_view_info;
+ break;
+
+ case WCCP2_REDIRECT_ASSIGNMENT:
+ ett = ett_router_assignment_info;
+ dissector = dissect_wccp2_assignment_info;
+ break;
+
+ case WCCP2_QUERY_INFO:
+ ett = ett_query_info;
+ dissector = dissect_wccp2_router_query_info;
+ break;
+
+ case WCCP2_CAPABILITIES_INFO:
+ ett = ett_capabilities_info;
+ dissector = dissect_wccp2_capability_info;
+ break;
+
+ default:
+ ett = ett_unknown_info;
+ dissector = NULL;
+ break;
+ }
+
+ ti = proto_tree_add_text(wccp_tree, tvb, offset, item_length + 4,
+ val_to_str(type, info_type_vals, "Unknown info type (%u)"));
+ info_tree = proto_item_add_subtree(ti, ett);
+ proto_tree_add_text(info_tree, tvb, offset, 2,
+ "Type: %s",
+ val_to_str(type, info_type_vals, "Unknown info type (%u)"));
+ proto_tree_add_text(info_tree, tvb, offset+2, 2,
+ "Length: %u", item_length);
+ offset += 4;
+ length -= 4;
+
+ /*
+ * XXX - pass in "length" and check for that as well.
+ */
+ if (dissector != NULL) {
+ if (!(*dissector)(tvb, offset, item_length, info_tree))
+ return; /* ran out of data */
+ } else {
+ proto_tree_add_text(info_tree, tvb, offset, item_length,
+ "Data: %u byte%s", item_length,
+ plurality(item_length, "", "s"));
+ }
+ offset += item_length;
+ length -= item_length;
+ }
+}
+
+#define SECURITY_INFO_LEN 4
+
+#define WCCP2_NO_SECURITY 0
+#define WCCP2_MD5_SECURITY 1
+
+static gboolean
+dissect_wccp2_security_info(tvbuff_t *tvb, int offset, int length,
+ proto_tree *info_tree)
+{
+ guint32 security_option;
+
+ if (length < SECURITY_INFO_LEN) {
+ proto_tree_add_text(info_tree, tvb, offset, 0,
+ "Item length is %u, should be %u", length,
+ SECURITY_INFO_LEN);
+ return TRUE;
+ }
+
+ security_option = tvb_get_ntohl(tvb, offset);
+ switch (security_option) {
+
+ case WCCP2_NO_SECURITY:
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Security Option: None");
+ break;
+
+ case WCCP2_MD5_SECURITY:
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Security Option: MD5");
+ offset += 4;
+ if (length > 4) {
+ proto_tree_add_text(info_tree, tvb, offset,
+ length - 4, "MD5 checksum: %s",
+ tvb_bytes_to_str(tvb, offset, length - 4));
+ }
+ break;
+
+ default:
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Security Option: Unknown (%u)", security_option);
+ break;
+ }
+ return TRUE;
+}
+
+#define SERVICE_INFO_LEN (4+4+8*2)
+
+#define WCCP2_SERVICE_STANDARD 0
+#define WCCP2_SERVICE_DYNAMIC 1
+
+/*
+ * Service flags.
+ */
+#define WCCP2_SI_SRC_IP_HASH 0x0001
+#define WCCP2_SI_DST_IP_HASH 0x0002
+#define WCCP2_SI_SRC_PORT_HASH 0x0004
+#define WCCP2_SI_DST_PORT_HASH 0x0008
+#define WCCP2_SI_PORTS_DEFINED 0x0010
+#define WCCP2_SI_PORTS_SOURCE 0x0020
+#define WCCP2_SI_SRC_IP_ALT_HASH 0x0100
+#define WCCP2_SI_DST_IP_ALT_HASH 0x0200
+#define WCCP2_SI_SRC_PORT_ALT_HASH 0x0400
+#define WCCP2_SI_DST_PORT_ALT_HASH 0x0800
+
+static gboolean
+dissect_wccp2_service_info(tvbuff_t *tvb, int offset, int length,
+ proto_tree *info_tree)
+{
+ guint8 service_type;
+ guint32 flags;
+ proto_item *tf;
+ proto_tree *field_tree;
+ int i;
+
+ if (length != SERVICE_INFO_LEN) {
+ proto_tree_add_text(info_tree, tvb, offset, 0,
+ "Item length is %u, should be %u", length,
+ SERVICE_INFO_LEN);
+ return TRUE;
+ }
+
+ service_type = tvb_get_guint8(tvb, offset);
+ switch (service_type) {
+
+ case WCCP2_SERVICE_STANDARD:
+ proto_tree_add_text(info_tree, tvb, offset, 1,
+ "Service Type: Well-known service");
+ proto_tree_add_text(info_tree, tvb, offset+1, 1,
+ "Service ID: %s",
+ val_to_str(tvb_get_guint8(tvb, offset+1), service_id_vals,
+ "Unknown (0x%02X)"));
+
+ break;
+
+ case WCCP2_SERVICE_DYNAMIC:
+ proto_tree_add_text(info_tree, tvb, offset, 1,
+ "Service Type: Dynamic service");
+ proto_tree_add_text(info_tree, tvb, offset+1, 1,
+ "Service ID: %s",
+ val_to_str(tvb_get_guint8(tvb, offset+1), service_id_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(info_tree, tvb, offset+2, 1,
+ "Priority: %u", tvb_get_guint8(tvb, offset+2));
+ /*
+ * XXX - does "IP protocol identifier" mean this is a
+ * protocol type of the sort you get in IP headers?
+ * If so, we should get a table of those from the
+ * IP dissector, and use that.
+ */
+ proto_tree_add_text(info_tree, tvb, offset+3, 1,
+ "Protocol: %u", tvb_get_guint8(tvb, offset+3)); /* IP protocol identifier */
+ break;
+
+ default:
+ proto_tree_add_text(info_tree, tvb, offset, 1,
+ "Service Type: Unknown (%u)", service_type);
+ break;
+ }
+ offset += 4;
+
+ flags = tvb_get_ntohl(tvb, offset);
+ tf = proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Flags: 0x%08X", flags);
+ field_tree = proto_item_add_subtree(tf, ett_service_flags);
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_SRC_IP_HASH,
+ sizeof (flags)*8,
+ "Use source IP address in primary hash",
+ "Don't use source IP address in primary hash"));
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_DST_IP_HASH,
+ sizeof (flags)*8,
+ "Use destination IP address in primary hash",
+ "Don't use destination IP address in primary hash"));
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_SRC_PORT_HASH,
+ sizeof (flags)*8,
+ "Use source port in primary hash",
+ "Don't use source port in primary hash"));
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_DST_PORT_HASH,
+ sizeof (flags)*8,
+ "Use destination port in primary hash",
+ "Don't use destination port in primary hash"));
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_PORTS_DEFINED,
+ sizeof (flags)*8,
+ "Ports defined",
+ "Ports not defined"));
+ if (flags & WCCP2_SI_PORTS_DEFINED) {
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_PORTS_SOURCE,
+ sizeof (flags)*8,
+ "Ports refer to source port",
+ "Ports refer to destination port"));
+ }
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_SRC_IP_ALT_HASH,
+ sizeof (flags)*8,
+ "Use source IP address in secondary hash",
+ "Don't use source IP address in secondary hash"));
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_DST_IP_ALT_HASH,
+ sizeof (flags)*8,
+ "Use destination IP address in secondary hash",
+ "Don't use destination IP address in secondary hash"));
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_SRC_PORT_ALT_HASH,
+ sizeof (flags)*8,
+ "Use source port in secondary hash",
+ "Don't use source port in secondary hash"));
+ proto_tree_add_text(field_tree, tvb, offset, 4, "%s",
+ decode_boolean_bitfield(flags, WCCP2_SI_DST_PORT_ALT_HASH,
+ sizeof (flags)*8,
+ "Use destination port in secondary hash",
+ "Don't use destination port in secondary hash"));
+ offset += 4;
+
+ if (flags & WCCP2_SI_PORTS_DEFINED) {
+ for (i = 0; i < 8; i++) {
+ proto_tree_add_text(info_tree, tvb, offset, 2,
+ "Port %d: %u", i, tvb_get_ntohs(tvb, offset));
+ offset += 2;
+ }
+ }
+
+ return TRUE;
+}
+
+#define ROUTER_ID_INFO_MIN_LEN (8+4+4)
+
+static void
+dissect_wccp2_router_identity_element(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "IP Address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ proto_tree_add_text(tree, tvb, offset + 4, 4,
+ "Receive ID: %u", tvb_get_ntohl(tvb, offset + 4));
+}
+
+static gboolean
+dissect_wccp2_router_identity_info(tvbuff_t *tvb, int offset, int length,
+ proto_tree *info_tree)
+{
+ guint32 n_received_from;
+ guint i;
+ proto_item *te;
+ proto_tree *element_tree;
+
+ if (length < ROUTER_ID_INFO_MIN_LEN) {
+ proto_tree_add_text(info_tree, tvb, offset, 0,
+ "Item length is %u, should be >= %u", length,
+ ROUTER_ID_INFO_MIN_LEN);
+ return TRUE;
+ }
+
+ te = proto_tree_add_text(info_tree, tvb, offset, 8,
+ "Router Identity Element: IP address %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ element_tree = proto_item_add_subtree(te,
+ ett_router_identity_element);
+ dissect_wccp2_router_identity_element(tvb, offset, element_tree);
+ offset += 8;
+
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Sent To IP Address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ n_received_from = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Number of Received From IP addresses: %u", n_received_from);
+ offset += 4;
+
+ for (i = 0; i < n_received_from; i++) {
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Received From IP Address %d: %s", i,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ }
+
+ return TRUE;
+}
+
+#define WC_ID_INFO_LEN (4+4+8*4+4)
+
+static gboolean
+dissect_wccp2_web_cache_identity_element(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+ proto_item *bucket_item;
+ proto_tree *bucket_tree;
+ proto_item *tf;
+ proto_tree *field_tree;
+ guint16 flags;
+ int i;
+ guint8 bucket_info;
+ int n;
+
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "Web-Cache IP Address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Hash Revision %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ flags = tvb_get_ntohs(tvb, offset);
+ tf = proto_tree_add_text(tree, tvb, offset, 2,
+ "Flags: 0x%04X (%s)", flags,
+ ((flags & 0x8000) ?
+ "Hash information is historical" :
+ "Hash information is current"));
+ field_tree = proto_item_add_subtree(tf, ett_flags);
+ proto_tree_add_text(field_tree, tvb, offset, 2, "%s",
+ decode_boolean_bitfield(flags, 0x8000,
+ sizeof (flags)*8,
+ "Hash information is historical",
+ "Hash information is current"));
+ offset += 2;
+
+ bucket_item = proto_tree_add_text(tree, tvb, offset, 8*4,
+ "Hash information");
+ bucket_tree = proto_item_add_subtree(bucket_item, ett_buckets);
+ for (i = 0, n = 0; i < 32; i++) {
+ bucket_info = tvb_get_guint8(tvb, offset);
+ n = wccp_bucket_info(bucket_info, bucket_tree, n, tvb, offset);
+ offset += 1;
+ }
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Assignment Weight: %u", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_text(tree, tvb, offset, 2,
+ "Status: 0x%04X", tvb_get_ntohs(tvb, offset));
+ offset += 2;
+
+ return TRUE;
+}
+
+static gboolean
+dissect_wccp2_wc_identity_info(tvbuff_t *tvb, int offset, int length,
+ proto_tree *info_tree)
+{
+ proto_item *te;
+ proto_tree *element_tree;
+
+ if (length != WC_ID_INFO_LEN) {
+ proto_tree_add_text(info_tree, tvb, offset, 0,
+ "Item length is %u, should be %u", length, WC_ID_INFO_LEN);
+ return TRUE;
+ }
+
+ te = proto_tree_add_text(info_tree, tvb, offset, 4+2+2+32+2+2,
+ "Web-Cache Identity Element: IP address %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ element_tree = proto_item_add_subtree(te, ett_wc_identity_element);
+ if (!dissect_wccp2_web_cache_identity_element(tvb, offset,
+ element_tree))
+ return FALSE; /* ran out of data */
+
+ return TRUE;
+}
+
+#define ROUTER_VIEW_INFO_MIN_LEN (4+8+4)
+
+static void
+dissect_wccp2_assignment_key(tvbuff_t *tvb, int offset,
+ proto_tree *info_tree)
+{
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Assignment Key IP Address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ proto_tree_add_text(info_tree, tvb, offset + 4, 4,
+ "Assignment Key Change Number: %u", tvb_get_ntohl(tvb, offset + 4));
+}
+
+static gboolean
+dissect_wccp2_router_view_info(tvbuff_t *tvb, int offset, int length,
+ proto_tree *info_tree)
+{
+ guint32 n_routers;
+ guint32 n_web_caches;
+ guint i;
+ proto_item *te;
+ proto_tree *element_tree;
+
+ if (length < ROUTER_VIEW_INFO_MIN_LEN) {
+ proto_tree_add_text(info_tree, tvb, offset, 0,
+ "Item length is %u, should be >= %u", length,
+ ROUTER_VIEW_INFO_MIN_LEN);
+ return TRUE;
+ }
+
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Member Change Number: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ dissect_wccp2_assignment_key(tvb, offset, info_tree);
+ offset += 8;
+
+ n_routers = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Number of Routers: %u", n_routers);
+ offset += 4;
+
+ for (i = 0; i < n_routers; i++) {
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Router %d IP Address: %s", i,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ }
+
+ n_web_caches = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Number of Web Caches: %u", n_web_caches);
+ offset += 4;
+
+ for (i = 0; i < n_web_caches; i++) {
+ te = proto_tree_add_text(info_tree, tvb, offset, WC_ID_INFO_LEN,
+ "Web-Cache Identity Element %d: IP address %s", i,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ element_tree = proto_item_add_subtree(te,
+ ett_wc_identity_element);
+ if (!dissect_wccp2_web_cache_identity_element(tvb,
+ offset, element_tree))
+ return FALSE; /* ran out of data */
+ offset += WC_ID_INFO_LEN;
+ }
+
+ return TRUE;
+}
+
+#define WC_VIEW_INFO_MIN_LEN (4+4)
+
+static gboolean
+dissect_wccp2_wc_view_info(tvbuff_t *tvb, int offset, int length,
+ proto_tree *info_tree)
+{
+ guint32 n_routers;
+ guint32 n_web_caches;
+ guint i;
+ proto_item *te;
+ proto_tree *element_tree;
+
+ if (length < WC_VIEW_INFO_MIN_LEN) {
+ proto_tree_add_text(info_tree, tvb, offset, 0,
+ "Item length is %u, should be >= %u", length,
+ WC_VIEW_INFO_MIN_LEN);
+ return TRUE;
+ }
+
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Change Number: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ n_routers = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Number of Routers: %u", n_routers);
+ offset += 4;
+
+ for (i = 0; i < n_routers; i++) {
+ te = proto_tree_add_text(info_tree, tvb, offset, 8,
+ "Router %d Identity Element: IP address %s", i,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ element_tree = proto_item_add_subtree(te,
+ ett_router_identity_element);
+ dissect_wccp2_router_identity_element(tvb, offset, element_tree);
+ offset += 8;
+ }
+
+ n_web_caches = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Number of Web Caches: %u", n_web_caches);
+ offset += 4;
+
+ for (i = 0; i < n_web_caches; i++) {
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Web-Cache %d: IP address %s", i,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ }
+
+ return TRUE;
+}
+
+#define ASSIGNMENT_INFO_MIN_LEN (8+4)
+
+static void
+dissect_wccp2_router_assignment_element(tvbuff_t *tvb, int offset,
+ proto_tree *tree)
+{
+ proto_tree_add_text(tree, tvb, offset, 4,
+ "IP Address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ proto_tree_add_text(tree, tvb, offset + 4, 4,
+ "Receive ID: %u", tvb_get_ntohl(tvb, offset + 4));
+ proto_tree_add_text(tree, tvb, offset + 8, 4,
+ "Change Number: %u", tvb_get_ntohl(tvb, offset + 8));
+}
+
+static gchar *
+assignment_bucket_name(guint8 bucket)
+{
+ static gchar str[4][10+1];
+ static gchar *cur;
+
+ if (cur == &str[0][0])
+ cur = &str[1][0];
+ else if (cur == &str[1][0])
+ cur = &str[2][0];
+ else if (cur == &str[2][0])
+ cur = &str[3][0];
+ else
+ cur = &str[0][0];
+ if (bucket == 0xff)
+ strcpy(cur, "Unassigned");
+ else {
+ sprintf(cur, "%u%s", bucket >> 1,
+ (bucket & 0x01) ? " (Alt)" : "");
+ }
+ return cur;
+}
+
+static gboolean
+dissect_wccp2_assignment_info(tvbuff_t *tvb, int offset, int length,
+ proto_tree *info_tree)
+{
+ guint32 n_routers;
+ guint32 n_web_caches;
+ guint i;
+ proto_item *te;
+ proto_tree *element_tree;
+
+ if (length < ASSIGNMENT_INFO_MIN_LEN) {
+ proto_tree_add_text(info_tree, tvb, offset, 0,
+ "Item length is %u, should be >= %u", length,
+ ASSIGNMENT_INFO_MIN_LEN);
+ return TRUE;
+ }
+
+ dissect_wccp2_assignment_key(tvb, offset, info_tree);
+ offset += 8;
+
+ n_routers = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Number of Routers: %u", n_routers);
+ offset += 4;
+
+ for (i = 0; i < n_routers; i++) {
+ te = proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Router %d Assignment Element: IP address %s", i,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ element_tree = proto_item_add_subtree(te,
+ ett_router_assignment_element);
+ dissect_wccp2_router_assignment_element(tvb, offset,
+ element_tree);
+ offset += 12;
+ }
+
+ n_web_caches = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Number of Web Caches: %u", n_web_caches);
+ offset += 4;
+
+ for (i = 0; i < n_web_caches; i++) {
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Web-Cache %d: IP address %s", i,
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+ }
+
+ for (i = 0; i < 256; i += 4) {
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Buckets %d - %d: %10s %10s %10s %10s",
+ i, i + 3,
+ assignment_bucket_name(tvb_get_guint8(tvb, offset)),
+ assignment_bucket_name(tvb_get_guint8(tvb, offset+1)),
+ assignment_bucket_name(tvb_get_guint8(tvb, offset+2)),
+ assignment_bucket_name(tvb_get_guint8(tvb, offset+3)));
+ offset += 4;
+ }
+
+ return TRUE;
+}
+
+#define QUERY_INFO_LEN (4+4+4+4)
+
+static gboolean
+dissect_wccp2_router_query_info(tvbuff_t *tvb, int offset, int length,
+ proto_tree *info_tree)
+{
+ if (length != QUERY_INFO_LEN) {
+ proto_tree_add_text(info_tree, tvb, offset, 0,
+ "Item length is %u, should be %u", length, QUERY_INFO_LEN);
+ return TRUE;
+ }
+
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Router IP Address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Receive ID: %u", tvb_get_ntohl(tvb, offset));
+ offset += 4;
+
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Sent To IP Address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ proto_tree_add_text(info_tree, tvb, offset, 4,
+ "Target IP Address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+ offset += 4;
+
+ return TRUE;
+}
+
+#define WCCP2_FORWARDING_METHOD 0x01
+#define WCCP2_ASSIGNMENT_METHOD 0x02
+#define WCCP2_PACKET_RETURN_METHOD 0x03
+
+static const value_string capability_type_vals[] = {
+ { WCCP2_FORWARDING_METHOD, "Forwarding Method" },
+ { WCCP2_ASSIGNMENT_METHOD, "Assignment Method" },
+ { WCCP2_PACKET_RETURN_METHOD, "Return Method" },
+ { 0, NULL }
+};
+
+#define WCCP2_FORWARDING_METHOD_GRE 0x00000001
+#define WCCP2_FORWARDING_METHOD_L2 0x00000002
+
+static const capability_flag forwarding_method_flags[] = {
+ { WCCP2_FORWARDING_METHOD_GRE,
+ "IP-GRE", "GRE-encapsulated" },
+ { WCCP2_FORWARDING_METHOD_L2,
+ "L2", "L2 rewrite" },
+ { 0,
+ NULL, NULL }
+};
+
+#define WCCP2_ASSIGNMENT_METHOD_HASH 0x00000001
+#define WCCP2_ASSIGNMENT_METHOD_MASK 0x00000002
+
+static const capability_flag assignment_method_flags[] = {
+ { WCCP2_ASSIGNMENT_METHOD_HASH, "Hash", "Hash" },
+ { WCCP2_ASSIGNMENT_METHOD_MASK, "Mask", "Mask" },
+ { 0, NULL, NULL }
+};
+
+#define WCCP2_PACKET_RETURN_METHOD_GRE 0x00000001
+#define WCCP2_PACKET_RETURN_METHOD_L2 0x00000002
+
+static const capability_flag packet_return_method_flags[] = {
+ { WCCP2_PACKET_RETURN_METHOD_GRE,
+ "IP-GRE", "GRE-encapsulated" },
+ { WCCP2_PACKET_RETURN_METHOD_L2,
+ "L2", "L2 rewrite" },
+ { 0,
+ NULL, NULL }
+};
+
+static gboolean
+dissect_wccp2_capability_info(tvbuff_t *tvb, int offset, int length,
+ proto_tree *info_tree)
+{
+ guint16 capability_type;
+ guint16 capability_val_len;
+ int curr_offset;
+ proto_item *te;
+ proto_tree *element_tree;
+
+ for (curr_offset = offset; curr_offset < (length + offset);
+ curr_offset += (capability_val_len + 4)) {
+ capability_type = tvb_get_ntohs(tvb, curr_offset);
+ capability_val_len = tvb_get_ntohs(tvb, curr_offset + 2);
+ te = proto_tree_add_text(info_tree, tvb, curr_offset,
+ capability_val_len + 4, "%s",
+ val_to_str(capability_type,
+ capability_type_vals, "Unknown Capability Element (0x%08X)"));
+ element_tree = proto_item_add_subtree(te,
+ ett_capability_element);
+
+ proto_tree_add_text(element_tree, tvb, curr_offset, 2,
+ "Type: %s",
+ val_to_str(capability_type,
+ capability_type_vals, "Unknown (0x%08X)"));
+
+ if (capability_val_len < 4) {
+ proto_tree_add_text(element_tree, tvb, curr_offset+2, 2,
+ "Value Length: %u (illegal, must be >= 4)",
+ capability_val_len);
+ break;
+ }
+ proto_tree_add_text(element_tree, tvb, curr_offset+2, 2,
+ "Value Length: %u", capability_val_len);
+
+ switch (capability_type) {
+
+ case WCCP2_FORWARDING_METHOD:
+ dissect_32_bit_capability_flags(tvb, curr_offset,
+ capability_val_len,
+ ett_capability_forwarding_method,
+ forwarding_method_flags, element_tree);
+ break;
+
+ case WCCP2_ASSIGNMENT_METHOD:
+ dissect_32_bit_capability_flags(tvb, curr_offset,
+ capability_val_len,
+ ett_capability_assignment_method,
+ assignment_method_flags, element_tree);
+ break;
+
+ case WCCP2_PACKET_RETURN_METHOD:
+ dissect_32_bit_capability_flags(tvb, curr_offset,
+ capability_val_len,
+ ett_capability_return_method,
+ packet_return_method_flags, element_tree);
+ break;
+
+ default:
+ proto_tree_add_text(element_tree, tvb,
+ curr_offset+4, capability_val_len,
+ "Value: %s",
+ tvb_bytes_to_str(tvb, curr_offset+4,
+ capability_val_len));
+ break;
+ }
+
+ }
+ return TRUE;
+}
+
+static void
+dissect_32_bit_capability_flags(tvbuff_t *tvb, int curr_offset,
+ guint16 capability_val_len, gint ett, const capability_flag *flags,
+ proto_tree *element_tree)
+{
+ guint32 capability_val;
+ proto_item *tm;
+ proto_tree *method_tree;
+ int i;
+ char flags_string[128+1];
+ char *p;
+ int space_left;
+ char buf[1025];
+
+ if (capability_val_len != 4) {
+ proto_tree_add_text(element_tree, tvb,
+ curr_offset+4, capability_val_len,
+ "Illegal length (must be 4)");
+ return;
+ }
+
+ capability_val = tvb_get_ntohl(tvb, curr_offset + 4);
+ flags_string[0] = '\0';
+ p = &flags_string[0];
+ space_left = sizeof flags_string;
+ for (i = 0; flags[i].short_name != NULL; i++) {
+ if (capability_val & flags[i].value) {
+ if (p != &flags_string[0]) {
+ snprintf(p, space_left, ",");
+ p = &flags_string[strlen(flags_string)];
+ }
+ snprintf(p, space_left, "%s", flags[i].short_name);
+ p = &flags_string[strlen(flags_string)];
+ }
+ }
+ tm = proto_tree_add_text(element_tree, tvb, curr_offset+4, 4,
+ "Value: 0x%08X (%s)", capability_val, flags_string);
+ method_tree = proto_item_add_subtree(tm, ett);
+ for (i = 0; flags[i].long_name != NULL; i++) {
+ p = decode_bitfield_value(buf, capability_val,
+ flags[i].value, 32);
+ strcpy(p, flags[i].long_name);
+ strcat(p, ": ");
+ if (capability_val & flags[i].value)
+ strcat(p, "Supported");
+ else
+ strcat(p, "Not supported");
+ proto_tree_add_text(method_tree, tvb, curr_offset+4, 4,
+ "%s", buf);
+ }
+}
+
+void
+proto_register_wccp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_wccp_message_type,
+ { "WCCP Message Type", "wccp.message", FT_UINT32, BASE_DEC, VALS(wccp_type_vals), 0x0,
+ "The WCCP message that was sent", HFILL }
+ },
+ { &hf_wccp_version,
+ { "WCCP Version", "wccp.version", FT_UINT32, BASE_HEX, VALS(wccp_version_val), 0x0,
+ "The WCCP version", HFILL }
+ },
+ { &hf_hash_revision,
+ { "Hash Revision", "wccp.hash_revision", FT_UINT32, BASE_DEC, 0x0, 0x0,
+ "The cache hash revision", HFILL }
+ },
+ { &hf_change_num,
+ { "Change Number", "wccp.change_num", FT_UINT32, BASE_DEC, 0x0, 0x0,
+ "The Web-Cache list entry change number", HFILL }
+ },
+ { &hf_recvd_id,
+ { "Received ID", "wccp.recvd_id", FT_UINT32, BASE_DEC, 0x0, 0x0,
+ "The number of I_SEE_YOU's that have been sent", HFILL }
+ },
+ { &hf_cache_ip,
+ { "Web Cache IP address", "wccp.cache_ip", FT_IPv4, BASE_NONE, NULL, 0x0,
+ "The IP address of a Web cache", HFILL }
+ },
+ };
+ static gint *ett[] = {
+ &ett_wccp,
+ &ett_cache_count,
+ &ett_buckets,
+ &ett_flags,
+ &ett_cache_info,
+ &ett_security_info,
+ &ett_service_info,
+ &ett_service_flags,
+ &ett_router_identity_element,
+ &ett_router_identity_info,
+ &ett_wc_identity_element,
+ &ett_wc_identity_info,
+ &ett_router_view_info,
+ &ett_wc_view_info,
+ &ett_query_info,
+ &ett_router_assignment_element,
+ &ett_router_assignment_info,
+ &ett_capabilities_info,
+ &ett_capability_element,
+ &ett_capability_forwarding_method,
+ &ett_capability_assignment_method,
+ &ett_capability_return_method,
+ &ett_unknown_info,
+ };
+
+ proto_wccp = proto_register_protocol("Web Cache Coordination Protocol",
+ "WCCP", "wccp");
+ proto_register_field_array(proto_wccp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_wccp(void)
+{
+ dissector_handle_t wccp_handle;
+
+ wccp_handle = create_dissector_handle(dissect_wccp, proto_wccp);
+ dissector_add("udp.port", UDP_PORT_WCCP, wccp_handle);
+}
diff --git a/epan/dissectors/packet-wccp.h b/epan/dissectors/packet-wccp.h
new file mode 100644
index 0000000000..7f3bf35c9a
--- /dev/null
+++ b/epan/dissectors/packet-wccp.h
@@ -0,0 +1,29 @@
+/* packet-wccp.h
+ * Declarations for Cisco Web Cache Coordination Protocol
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Maps service ID values to service names.
+ */
+extern const value_string service_id_vals[];
diff --git a/epan/dissectors/packet-wcp.c b/epan/dissectors/packet-wcp.c
new file mode 100644
index 0000000000..c46afafd31
--- /dev/null
+++ b/epan/dissectors/packet-wcp.c
@@ -0,0 +1,750 @@
+/* packet-wcp.c
+ * Routines for Wellfleet Compression frame disassembly
+ * Copyright 2001, Jeffrey C. Foster <jfoste@woodward.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ToDo:
+ * Add preference to allow/disallow decompression
+ * Calculate and verify check byte (last byte), if only we knew how!
+ * Handle Wellfleet compression over PPP links.
+ * - This will require changing the sub-dissector call
+ * routine to determine if layer 2 is frame relay or
+ * or PPP and different sub-dissector routines for each.
+ *
+ * Based upon information in the Nortel TCL based Pcaptap code.
+ *http://www.mynetworkforum.com/tools/PCAPTAP/pcaptap-Win32-3.00.exe
+ *
+ * And lzss algorithm
+ *http://www.rasip.fer.hr/research/compress/algorithms/fund/lz/lzss.html
+ */
+
+/*
+ * Wellfleet compression is a variation on LZSS encoding.
+ *
+ * Compression is done by keeping a sliding window of previous
+ * data transmited. The sender will use a pattern match to
+ * encode repeated data as a data pointer field. Then a stream
+ * of pointers and actual data bytes. The pointer values include
+ * an offset to previous data in the stream and the length of the
+ * matching data.
+ *
+ * The data pattern matching is done on the octects.
+ *
+ * The data is encoded as 8 field blocks with a compression flag
+ * byte at the beginning. If the bit is set in the compression
+ * flag, then that field has a compression field. If it isn't set
+ * then the byte is raw data.
+ *
+ * The compression field is either 2 or 3 bytes long. The length
+ * is determined by the length of the matching data, for short
+ * matches the match length is encoded in the high nibble of the
+ * first byte. Otherwise the third byte of the field contains
+ * the match length.
+ *
+ * First byte -
+ * lower 4 bits:
+ * High order nibble of the offset
+ *
+ * upper 4 bits:
+ * 1 = length is in 3rd byte
+ * 2-F = length of matching data - 1
+ *
+ * Second byte -
+ * Lower byte of the source offset.
+ *
+ * Third byte -
+ * Length of match - 1 if First byte upper nibble = 1, otherwise
+ * this byte isn't added to data stream.
+ *
+ * Example:
+ * Uncompressed data (hex): 11 22 22 22 22 33 44 55 66 77
+ *
+ *
+ * Compression data :
+ * Flag bits: 0x20 (third field is compressed)
+ * Data: 11 22 20 00 33 44 55
+ * / / / /
+ * raw data ------+--+ / /
+ * (Comp length - 1)<<4+ /
+ * Data offset ----------+
+ *
+ * Output data (hex): 20 11 22 20 00 33 44 55 66 77
+ *
+ * In this example the copy src is one byte behind the copy destination
+ * so if appears as if output is being loaded with the source byte.
+ *
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include "packet-frame.h"
+#include <epan/circuit.h>
+#include "etypes.h"
+#include "nlpid.h"
+
+#define MAX_WIN_BUF_LEN 0x7fff /* storage size for decompressed data */
+#define MAX_WCP_BUF_LEN 2048 /* storage size for decompressed data */
+#define FROM_DCE 0x80 /* for direction setting */
+
+typedef struct {
+
+ guint8 *buf_cur;
+ guint8 buffer[MAX_WIN_BUF_LEN];
+
+}wcp_window_t;
+
+typedef struct {
+ wcp_window_t recv;
+ wcp_window_t send;
+} wcp_circuit_data_t;
+
+/*XXX do I really want the length in here */
+typedef struct {
+
+ guint16 len;
+ guint8 buffer[MAX_WCP_BUF_LEN];
+
+}wcp_pdata_t;
+
+
+#define wcp_win_init_count 4
+#define wcp_packet_init_count 10
+
+#define wcp_circuit_length (sizeof(wcp_circuit_data_t))
+#define wcp_packet_length (sizeof(wcp_pdata_t))
+
+static GMemChunk *wcp_circuit = NULL;
+static GMemChunk *wcp_pdata = NULL;
+
+static int proto_wcp = -1;
+static int hf_wcp_cmd = -1;
+static int hf_wcp_ext_cmd = -1;
+static int hf_wcp_seq = -1;
+static int hf_wcp_chksum = -1;
+static int hf_wcp_tid = -1;
+static int hf_wcp_rev = -1;
+static int hf_wcp_init = -1;
+static int hf_wcp_seq_size = -1;
+static int hf_wcp_alg = -1;
+static int hf_wcp_alg_cnt = -1;
+static int hf_wcp_alg_a = -1;
+static int hf_wcp_alg_b = -1;
+static int hf_wcp_alg_c = -1;
+static int hf_wcp_alg_d = -1;
+static int hf_wcp_rexmit = -1;
+
+static int hf_wcp_hist_size = -1;
+static int hf_wcp_ppc = -1;
+static int hf_wcp_pib = -1;
+
+static int hf_wcp_comp_bits = -1;
+static int hf_wcp_comp_marker = -1;
+static int hf_wcp_short_len = -1;
+static int hf_wcp_long_len = -1;
+static int hf_wcp_short_run = -1;
+static int hf_wcp_long_run = -1;
+static int hf_wcp_offset = -1;
+
+static gint ett_wcp = -1;
+static gint ett_wcp_field = -1;
+
+static dissector_handle_t fr_uncompressed_handle;
+
+/*
+ * Bits in the address field.
+ */
+#define WCP_CMD 0xf0 /* WCP Command */
+#define WCP_EXT_CMD 0x0f /* WCP Extended Command */
+#define WCP_SEQ 0x0fff /* WCP Sequence number */
+#define WCP_OFFSET_MASK 0x0fff /* WCP Pattern source offset */
+
+#define PPC_COMPRESSED_IND 0x0
+#define PPC_UNCOMPRESSED_IND 0x1
+#define PPC_TPPC_COMPRESSED_IND 0x2
+#define PPC_TPPC_UNCOMPRESSED_IND 0x3
+#define CONNECT_REQ 0x4
+#define CONNECT_ACK 0x5
+#define CONNECT_NAK 0x6
+#define DISCONNECT_REQ 0x7
+#define DISCONNECT_ACK 0x8
+#define INIT_REQ 0x9
+#define INIT_ACK 0xa
+#define RESET_REQ 0xb
+#define RESET_ACK 0xc
+#define REXMIT_NAK 0xd
+
+
+static const value_string cmd_string[] = {
+ {0, "Compressed Data"},
+ {1, "Uncompressed Data"},
+ {15, "Extended"},
+ { 0, NULL }
+ };
+
+static const value_string ext_cmd_string[] = {
+ {0, "Per Packet Compression"},
+ {4, "Connect Req"},
+ {5, "Connect Ack"},
+ {9, "Init Req"},
+ {0x0a, "Init Ack"},
+
+ { 0, NULL }
+ };
+
+
+
+static tvbuff_t *wcp_uncompress( tvbuff_t *src_tvb, int offset, packet_info *pinfo, proto_tree *tree);
+static wcp_window_t *get_wcp_window_ptr( packet_info *pinfo);
+
+static void
+dissect_wcp_con_req(tvbuff_t *tvb, int offset, proto_tree *tree) {
+
+/* WCP connector request message */
+
+ guint alg_cnt = tvb_get_guint8(tvb, 5);
+
+ proto_tree_add_uint(tree, hf_wcp_tid, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+ proto_tree_add_uint(tree, hf_wcp_rev, tvb, offset + 2, 1, tvb_get_guint8(tvb, offset + 2));
+ proto_tree_add_uint(tree, hf_wcp_init, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
+ proto_tree_add_uint(tree, hf_wcp_seq_size, tvb, offset + 4, 1, tvb_get_guint8(tvb, offset + 4));
+ proto_tree_add_uint(tree, hf_wcp_alg_cnt, tvb, offset + 5, 1, alg_cnt);
+ proto_tree_add_uint(tree, hf_wcp_alg_a, tvb, offset + 6, 1, tvb_get_guint8(tvb, offset + 6));
+ if ( alg_cnt > 1)
+ proto_tree_add_uint(tree, hf_wcp_alg_b, tvb, offset + 7, 1, tvb_get_guint8(tvb, offset + 7));
+ if ( alg_cnt > 2)
+ proto_tree_add_uint(tree, hf_wcp_alg_c, tvb, offset + 8, 1, tvb_get_guint8(tvb, offset + 8));
+ if ( alg_cnt > 3)
+ proto_tree_add_uint(tree, hf_wcp_alg_d, tvb, offset + 9, 1, tvb_get_guint8(tvb, offset + 9));
+}
+
+static void
+dissect_wcp_con_ack( tvbuff_t *tvb, int offset, proto_tree *tree){
+
+/* WCP connector ack message */
+
+ proto_tree_add_uint(tree, hf_wcp_tid, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+ proto_tree_add_uint(tree, hf_wcp_rev, tvb, offset + 2, 1, tvb_get_guint8(tvb, offset + 2));
+ proto_tree_add_uint(tree, hf_wcp_seq_size, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
+ proto_tree_add_uint(tree, hf_wcp_alg, tvb, offset + 4, 1, tvb_get_guint8(tvb, offset + 4));
+}
+
+static void
+dissect_wcp_init( tvbuff_t *tvb, int offset, proto_tree *tree){
+
+/* WCP Initiate Request/Ack message */
+
+ proto_tree_add_uint(tree, hf_wcp_tid, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+ proto_tree_add_uint(tree, hf_wcp_rev, tvb, offset + 2, 1, tvb_get_guint8(tvb, offset + 2));
+ proto_tree_add_uint(tree, hf_wcp_hist_size, tvb, offset + 3, 1, tvb_get_guint8(tvb, offset + 3));
+ proto_tree_add_uint(tree, hf_wcp_ppc, tvb, offset + 4, 1, tvb_get_guint8(tvb, offset + 4));
+ proto_tree_add_uint(tree, hf_wcp_pib, tvb, offset + 5, 1, tvb_get_guint8(tvb, offset + 5));
+}
+
+
+static void
+dissect_wcp_reset( tvbuff_t *tvb, int offset, proto_tree *tree){
+
+/* Process WCP Reset Request/Ack message */
+
+ proto_tree_add_uint(tree, hf_wcp_tid, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+}
+
+
+static void wcp_save_data( tvbuff_t *tvb, packet_info *pinfo){
+
+ wcp_window_t *buf_ptr = 0;
+ int len;
+
+ /* discard first 2 bytes, header and last byte (check byte) */
+ len = tvb_reported_length( tvb)-3;
+ buf_ptr = get_wcp_window_ptr( pinfo);
+
+ if (( buf_ptr->buf_cur + len) <= (buf_ptr->buffer + MAX_WIN_BUF_LEN)){
+ tvb_memcpy( tvb, buf_ptr->buf_cur, 2, len);
+ buf_ptr->buf_cur = buf_ptr->buf_cur + len;
+
+ } else {
+ guint8 *buf_end = buf_ptr->buffer + MAX_WIN_BUF_LEN;
+ tvb_memcpy( tvb, buf_ptr->buf_cur, 2, buf_end - buf_ptr->buf_cur);
+ tvb_memcpy( tvb, buf_ptr->buffer, buf_end - buf_ptr->buf_cur-2,
+ len - (int)(buf_end - buf_ptr->buf_cur));
+ buf_ptr->buf_cur = buf_ptr->buf_cur + len - MAX_WIN_BUF_LEN;
+ }
+
+}
+
+
+static void dissect_wcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+
+ proto_tree *wcp_tree;
+ proto_item *ti;
+ int wcp_header_len;
+ guint16 temp, cmd, ext_cmd, seq;
+ tvbuff_t *next_tvb;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WCP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ temp =tvb_get_ntohs(tvb, 0);
+
+ cmd = (temp & 0xf000) >> 12;
+ ext_cmd = (temp & 0x0f00) >> 8;
+
+ if ( cmd == 0xf)
+ wcp_header_len= 1;
+ else
+ wcp_header_len= 2;
+
+ seq = temp & 0x0fff;
+
+/*XXX should test seq to be sure it the last + 1 !! */
+
+ if (check_col(pinfo->cinfo, COL_INFO)){
+ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, cmd_string, "Unknown"));
+ if ( cmd == 0xf)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
+ val_to_str(ext_cmd, ext_cmd_string, "Unknown"));
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_wcp, tvb, 0, wcp_header_len, FALSE);
+
+ wcp_tree = proto_item_add_subtree(ti, ett_wcp);
+
+ proto_tree_add_uint(wcp_tree, hf_wcp_cmd, tvb, 0, 1, tvb_get_guint8( tvb, 0));
+ if ( cmd == 0xf){
+ proto_tree_add_uint(wcp_tree, hf_wcp_ext_cmd, tvb, 1, 1,
+ tvb_get_guint8( tvb, 0));
+ switch (ext_cmd){
+ case CONNECT_REQ:
+ dissect_wcp_con_req( tvb, 1, wcp_tree);
+ break;
+
+ case CONNECT_ACK:
+ dissect_wcp_con_ack( tvb, 1, wcp_tree);
+ break;
+ case INIT_REQ:
+ case INIT_ACK:
+ dissect_wcp_init( tvb, 1, wcp_tree);
+ break;
+ case RESET_REQ:
+ case RESET_ACK:
+ dissect_wcp_reset( tvb, 1, wcp_tree);
+ break;
+ default:
+ break;
+ }
+ }else {
+ proto_tree_add_uint(wcp_tree, hf_wcp_seq, tvb, 0, 2, seq);
+ }
+ }
+ else {
+ wcp_tree = NULL;
+ }
+
+
+ /* exit if done */
+ if ( cmd != 1 && cmd != 0 && !(cmd == 0xf && ext_cmd == 0))
+ return;
+
+ if ( cmd == 1) { /* uncompressed data */
+ if ( !pinfo->fd->flags.visited){ /* if first pass */
+ wcp_save_data( tvb, pinfo);
+ }
+ next_tvb = tvb_new_subset(tvb, wcp_header_len, -1, -1);
+ }
+ else { /* cmd == 0 || (cmd == 0xf && ext_cmd == 0) */
+
+ next_tvb = wcp_uncompress( tvb, wcp_header_len, pinfo, wcp_tree);
+
+ if ( !next_tvb){
+ proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
+ "[Malformed Frame: Bad WCP compressed data]" );
+ return;
+ }
+ }
+
+ if ( tree) /* add the check byte */
+ proto_tree_add_uint(wcp_tree, hf_wcp_chksum, tvb,
+ tvb_reported_length( tvb)-1, 1,
+ tvb_get_guint8( tvb, tvb_reported_length(tvb)-1));
+
+ call_dissector(fr_uncompressed_handle, next_tvb, pinfo, tree);
+
+ return;
+}
+
+
+static guint8 *decompressed_entry( guint8 *src, guint8 *dst, int *len, guint8 * buf_start, guint8 *buf_end){
+
+/* do the decompression for one field */
+
+ guint16 data_offset, data_cnt;
+ guint8 tmp = *src;
+
+ data_offset = (*(src++) & 0xf) << 8; /* get high byte */
+ data_offset += *(src++); /* add next byte */
+
+ if (( tmp & 0xf0) == 0x10){ /* 2 byte count */
+ data_cnt = *src;
+ data_cnt++;
+
+ }else { /* one byte count */
+ data_cnt = tmp >> 4;
+ data_cnt++;
+ }
+
+
+ src = (dst - 1 - data_offset);
+ if ( src < buf_start)
+ src += MAX_WIN_BUF_LEN;
+
+
+/*XXX could do some fancy memory moves, later if speed is problem */
+
+ while( data_cnt--){
+ *dst = *src;
+ if ( ++(*len) >MAX_WCP_BUF_LEN){
+ printf("decomp failed, len = %d\n", *len);
+
+ return NULL; /* end of buffer error */
+ }
+ if ( dst++ == buf_end)
+ dst = buf_start;
+ if ( src++ == buf_end)
+ src = buf_start;
+
+ }
+ return dst;
+}
+
+
+static
+wcp_window_t *get_wcp_window_ptr( packet_info *pinfo){
+
+/* find the circuit for this DLCI, create one if needed */
+/* and return the wcp_window data structure pointer */
+/* for the direction of this packet */
+
+ circuit_t *circuit;
+ wcp_circuit_data_t *wcp_circuit_data;
+
+ circuit = find_circuit( pinfo->ctype, pinfo->circuit_id,
+ pinfo->fd->num);
+ if ( !circuit){
+ circuit = circuit_new( pinfo->ctype, pinfo->circuit_id,
+ pinfo->fd->num);
+ }
+ wcp_circuit_data = circuit_get_proto_data(circuit, proto_wcp);
+ if ( !wcp_circuit_data){
+ wcp_circuit_data = g_mem_chunk_alloc( wcp_circuit);
+ wcp_circuit_data->recv.buf_cur = wcp_circuit_data->recv.buffer;
+ wcp_circuit_data->send.buf_cur = wcp_circuit_data->send.buffer;
+ circuit_add_proto_data(circuit, proto_wcp, wcp_circuit_data);
+ }
+ if (pinfo->pseudo_header->x25.flags & FROM_DCE)
+ return &wcp_circuit_data->recv;
+ else
+ return &wcp_circuit_data->send;
+}
+
+
+static tvbuff_t *wcp_uncompress( tvbuff_t *src_tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+
+/* do the packet data uncompression and load it into the dst buffer */
+
+ proto_tree *sub_tree;
+ proto_item *ti;
+
+ int len=0, i = -1;
+ int cnt = tvb_reported_length( src_tvb)-1; /* don't include check byte */
+
+ guint8 *buf = 0, *dst, *src, *buf_start, *buf_end, *tmp, comp_flag_bits = 0;
+ guint8 src_buf[ MAX_WCP_BUF_LEN];
+ tvbuff_t *volatile tvb = 0;
+ wcp_window_t *buf_ptr = 0;
+ wcp_pdata_t *volatile pdata_ptr;
+
+ buf_ptr = get_wcp_window_ptr( pinfo);
+
+ buf_start = buf_ptr->buffer;
+ buf_end = buf_start + MAX_WIN_BUF_LEN;
+ tmp = buf_ptr->buf_cur;
+
+ if (cnt - offset > MAX_WCP_BUF_LEN) {
+ if (tree)
+ proto_tree_add_text( tree, src_tvb, offset, -1,
+ "Compressed data exceeds maximum buffer length (%d > %d)",
+ cnt - offset, MAX_WCP_BUF_LEN);
+ return NULL;
+ }
+
+ src = tvb_memcpy(src_tvb, src_buf, offset, cnt - offset);
+ dst = buf_ptr->buf_cur;
+
+ while( offset++ < cnt){
+
+ if ( --i >= 0){
+ if ( comp_flag_bits & 0x80){ /* if this is a compressed entry */
+
+ if ( !pinfo->fd->flags.visited){ /* if first pass */
+ dst = decompressed_entry( src, dst, &len, buf_start, buf_end);
+ }
+ if ((*src & 0xf0) == 0x10){
+ if ( tree) {
+ ti = proto_tree_add_item( tree, hf_wcp_long_run, src_tvb,
+ offset-1, 3, 0);
+ sub_tree = proto_item_add_subtree(ti, ett_wcp_field);
+ proto_tree_add_uint(sub_tree, hf_wcp_offset, src_tvb,
+ offset-1, 2, pntohs(src));
+
+ proto_tree_add_item( sub_tree, hf_wcp_long_len, src_tvb,
+ offset+1, 1, pntohs(src));
+ }
+ src += 3;
+ offset += 2;
+ }else{
+ if ( tree) {
+ ti = proto_tree_add_item( tree, hf_wcp_short_run, src_tvb,
+ offset - 1, 2, *src);
+ sub_tree = proto_item_add_subtree(ti, ett_wcp_field);
+ proto_tree_add_item( sub_tree, hf_wcp_short_len, src_tvb,
+ offset-1, 1, *src);
+ proto_tree_add_uint(sub_tree, hf_wcp_offset, src_tvb,
+ offset-1, 2, pntohs(src));
+ }
+ src += 2;
+ offset += 1;
+ }
+ }else {
+ if ( !pinfo->fd->flags.visited){ /* if first pass */
+ *dst = *src;
+ if ( dst++ == buf_end)
+ dst = buf_start;
+ }
+ ++src;
+ ++len;
+
+ }
+
+ if ( len >MAX_WCP_BUF_LEN){
+ return NULL;
+ }
+
+ comp_flag_bits <<= 1;
+
+ }else { /* compressed data flag */
+
+ comp_flag_bits = *src++;
+ if (tree)
+ proto_tree_add_uint( tree, hf_wcp_comp_bits, src_tvb, offset-1, 1,
+ comp_flag_bits);
+
+ i = 8;
+ }
+ }
+
+ if ( pinfo->fd->flags.visited){ /* if not first pass */
+ /* get uncompressed data */
+ pdata_ptr = p_get_proto_data( pinfo->fd, proto_wcp);
+
+ if ( !pdata_ptr) /* exit if no data */
+ return NULL;
+ len = pdata_ptr->len;
+ } else {
+
+ /* save the new data as per packet data */
+ pdata_ptr = g_mem_chunk_alloc( wcp_pdata);
+ memcpy( &pdata_ptr->buffer, buf_ptr->buf_cur, len);
+ pdata_ptr->len = len;
+
+ p_add_proto_data( pinfo->fd, proto_wcp, (void*)pdata_ptr);
+
+ buf_ptr->buf_cur = dst;
+ }
+
+
+ TRY {
+ tvb = tvb_new_real_data( pdata_ptr->buffer, pdata_ptr->len, pdata_ptr->len);
+
+ }
+ CATCH(BoundsError) {
+ g_assert_not_reached();
+ g_free(buf);
+ return NULL;
+ }
+ CATCH(ReportedBoundsError) {
+ g_free(buf);
+ return NULL;
+ }
+ ENDTRY;
+
+ /* link new tvbuff into tvbuff chain so cleanup is done later */
+ tvb_set_child_real_data_tvbuff( src_tvb, tvb);
+
+ /* Add new data to the data source list */
+ add_new_data_source( pinfo, tvb, "Uncompressed WCP");
+ return tvb;
+
+}
+
+
+static void wcp_reinit( void){
+
+/* Do the cleanup work when a new pass through the packet list is */
+/* performed. re-initialize the memory chunks. */
+
+ if (wcp_circuit)
+ g_mem_chunk_destroy(wcp_circuit);
+
+ wcp_circuit = g_mem_chunk_new("wcp_circuit", wcp_circuit_length,
+ wcp_win_init_count * wcp_circuit_length,
+ G_ALLOC_AND_FREE);
+
+ if (wcp_pdata)
+ g_mem_chunk_destroy(wcp_pdata);
+
+ wcp_pdata = g_mem_chunk_new("wcp_pdata", wcp_packet_length,
+ wcp_packet_init_count * wcp_packet_length,
+ G_ALLOC_AND_FREE);
+
+}
+
+
+void
+proto_register_wcp(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_wcp_cmd,
+ { "Command", "wcp.cmd", FT_UINT8, BASE_HEX, VALS(cmd_string), WCP_CMD,
+ "Compression Command", HFILL }},
+ { &hf_wcp_ext_cmd,
+ { "Extended Command", "wcp.ext_cmd", FT_UINT8, BASE_HEX, VALS(ext_cmd_string), WCP_EXT_CMD,
+ "Extended Compression Command", HFILL }},
+ { &hf_wcp_seq,
+ { "SEQ", "wcp.seq", FT_UINT16, BASE_HEX, NULL, WCP_SEQ,
+ "Sequence Number", HFILL }},
+ { &hf_wcp_chksum,
+ { "Checksum", "wcp.checksum", FT_UINT8, BASE_DEC, NULL, 0,
+ "Packet Checksum", HFILL }},
+ { &hf_wcp_tid,
+ { "TID", "wcp.tid", FT_UINT16, BASE_DEC, NULL, 0,
+ "TID", HFILL }},
+ { &hf_wcp_rev,
+ { "Revision", "wcp.rev", FT_UINT8, BASE_DEC, NULL, 0,
+ "Revision", HFILL }},
+ { &hf_wcp_init,
+ { "Initiator", "wcp.init", FT_UINT8, BASE_DEC, NULL, 0,
+ "Initiator", HFILL }},
+ { &hf_wcp_seq_size,
+ { "Seq Size", "wcp.seq_size", FT_UINT8, BASE_DEC, NULL, 0,
+ "Sequence Size", HFILL }},
+ { &hf_wcp_alg_cnt,
+ { "Alg Count", "wcp.alg_cnt", FT_UINT8, BASE_DEC, NULL, 0,
+ "Algorithm Count", HFILL }},
+ { &hf_wcp_alg_a,
+ { "Alg 1", "wcp.alg1", FT_UINT8, BASE_DEC, NULL, 0,
+ "Algorithm #1", HFILL }},
+ { &hf_wcp_alg_b,
+ { "Alg 2", "wcp.alg2", FT_UINT8, BASE_DEC, NULL, 0,
+ "Algorithm #2", HFILL }},
+ { &hf_wcp_alg_c,
+ { "Alg 3", "wcp.alg3", FT_UINT8, BASE_DEC, NULL, 0,
+ "Algorithm #3", HFILL }},
+ { &hf_wcp_alg_d,
+ { "Alg 4", "wcp.alg4", FT_UINT8, BASE_DEC, NULL, 0,
+ "Algorithm #4", HFILL }},
+ { &hf_wcp_alg,
+ { "Alg", "wcp.alg", FT_UINT8, BASE_DEC, NULL, 0,
+ "Algorithm", HFILL }},
+ { &hf_wcp_rexmit,
+ { "Rexmit", "wcp.rexmit", FT_UINT8, BASE_DEC, NULL, 0,
+ "Retransmit", HFILL }},
+ { &hf_wcp_hist_size,
+ { "History", "wcp.hist", FT_UINT8, BASE_DEC, NULL, 0,
+ "History Size", HFILL }},
+ { &hf_wcp_ppc,
+ { "PerPackComp", "wcp.ppc", FT_UINT8, BASE_DEC, NULL, 0,
+ "Per Packet Compression", HFILL }},
+ { &hf_wcp_pib,
+ { "PIB", "wcp.pib", FT_UINT8, BASE_DEC, NULL, 0,
+ "PIB", HFILL }},
+ { &hf_wcp_comp_bits,
+ { "Compress Flag", "wcp.flag", FT_UINT8, BASE_HEX, NULL, 0,
+ "Compressed byte flag", HFILL }},
+ { &hf_wcp_comp_marker,
+ { "Compress Marker", "wcp.mark", FT_UINT8, BASE_DEC, NULL, 0,
+ "Compressed marker", HFILL }},
+ { &hf_wcp_offset,
+ { "Source offset", "wcp.off", FT_UINT16, BASE_HEX, NULL, WCP_OFFSET_MASK,
+ "Data source offset", HFILL }},
+ { &hf_wcp_short_len,
+ { "Compress Length", "wcp.short_len", FT_UINT8, BASE_HEX, NULL, 0xf0,
+ "Compressed length", HFILL }},
+ { &hf_wcp_long_len,
+ { "Compress Length", "wcp.long_len", FT_UINT8, BASE_HEX, NULL, 0,
+ "Compressed length", HFILL }},
+ { &hf_wcp_long_run,
+ { "Long Compression", "wcp.long_comp", FT_UINT16, BASE_HEX, NULL, 0,
+ "Long Compression type", HFILL }},
+ { &hf_wcp_short_run,
+ { "Short Compression", "wcp.short_comp", FT_UINT8, BASE_HEX, NULL, 0,
+ "Short Compression type", HFILL }},
+
+ };
+
+
+ static gint *ett[] = {
+ &ett_wcp,
+ &ett_wcp_field,
+ };
+
+ proto_wcp = proto_register_protocol ("Wellfleet Compression", "WCP", "wcp");
+ proto_register_field_array (proto_wcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_init_routine(&wcp_reinit);
+}
+
+
+void
+proto_reg_handoff_wcp(void) {
+ dissector_handle_t wcp_handle;
+
+ /*
+ * Get handle for the Frame Relay (uncompressed) dissector.
+ */
+ fr_uncompressed_handle = find_dissector("fr_uncompressed");
+
+ wcp_handle = create_dissector_handle(dissect_wcp, proto_wcp);
+ dissector_add("fr.ietf", NLPID_COMPRESSED, wcp_handle);
+ dissector_add("ethertype", ETHERTYPE_WCP, wcp_handle);
+}
diff --git a/epan/dissectors/packet-wfleet-hdlc.c b/epan/dissectors/packet-wfleet-hdlc.c
new file mode 100644
index 0000000000..9c70f2d0fd
--- /dev/null
+++ b/epan/dissectors/packet-wfleet-hdlc.c
@@ -0,0 +1,127 @@
+/* packet-chdlc.c
+ * Routines for Wellfleet HDLC packet disassembly
+ * Copied from the Cisco HDLC packet disassembly routines
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "etypes.h"
+#include <epan/resolv.h>
+#include "packet-chdlc.h"
+#include "packet-ip.h"
+
+static int proto_wfleet_hdlc = -1;
+static int hf_wfleet_hdlc_addr = -1;
+static int hf_wfleet_hdlc_cmd = -1;
+
+static gint ett_wfleet_hdlc = -1;
+
+dissector_handle_t eth_handle;
+
+static const value_string wfleet_hdlc_cmd_vals[] = {
+ { 0x03, "Un-numbered I frame"},
+ { 0, NULL}
+};
+
+static void
+dissect_wfleet_hdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *fh_tree = NULL;
+ tvbuff_t *next_tvb;
+ guint8 addr;
+ guint8 cmd;
+
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WHDLC");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ addr = tvb_get_guint8(tvb, 0);
+ cmd = tvb_get_guint8(tvb, 1);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_wfleet_hdlc, tvb, 0, 2, FALSE);
+ fh_tree = proto_item_add_subtree(ti, ett_wfleet_hdlc);
+
+ proto_tree_add_uint(fh_tree, hf_wfleet_hdlc_addr, tvb, 0, 1, addr);
+ proto_tree_add_uint(fh_tree, hf_wfleet_hdlc_cmd, tvb, 1, 1, cmd);
+
+ }
+
+ /*
+ * Build a tvb of the piece past the first two bytes and call the
+ * ethernet dissector
+ */
+
+ next_tvb = tvb_new_subset(tvb, 2, -1, -1);
+
+ call_dissector(eth_handle, next_tvb, pinfo, tree);
+
+}
+
+void
+proto_register_wfleet_hdlc(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_wfleet_hdlc_addr,
+ { "Address", "wfleet_hdlc.address", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "", HFILL }},
+ { &hf_wfleet_hdlc_cmd,
+ { "Command", "wfleet_hdlc.command", FT_UINT8, BASE_HEX,
+ VALS(wfleet_hdlc_cmd_vals), 0x0, "", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_wfleet_hdlc,
+ };
+
+ proto_wfleet_hdlc = proto_register_protocol("Wellfleet HDLC", "WHDLC", "whdlc");
+ proto_register_field_array(proto_wfleet_hdlc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("wfleet_hdlc", dissect_wfleet_hdlc, proto_wfleet_hdlc);
+
+}
+
+void
+proto_reg_handoff_wfleet_hdlc(void)
+{
+ dissector_handle_t wfleet_hdlc_handle;
+
+ wfleet_hdlc_handle = find_dissector("wfleet_hdlc");
+ dissector_add("wtap_encap", WTAP_ENCAP_WFLEET_HDLC, wfleet_hdlc_handle);
+
+ /*
+ * Find the eth dissector and save a ref to it
+ */
+
+ eth_handle = find_dissector("eth");
+}
diff --git a/epan/dissectors/packet-who.c b/epan/dissectors/packet-who.c
new file mode 100644
index 0000000000..1050ecb7a3
--- /dev/null
+++ b/epan/dissectors/packet-who.c
@@ -0,0 +1,308 @@
+/* packet-who.c
+ * Routines for who protocol (see man rwhod)
+ * Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <time.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+
+/*
+ *
+RWHOD(8) UNIX System Manager's Manual RWHOD(8)
+
+
+ The messages sent and received, are of the form:
+
+ struct outmp {
+0 char out_line[8]; tty name
+8 char out_name[8]; user id
+16 long out_time; time on
+ };
+
+ struct whod {
+ 0 char wd_vers;
+ 1 char wd_type;
+ 2 char wd_fill[2];
+ 4 int wd_sendtime;
+ 8 int wd_recvtime;
+12 char wd_hostname[32];
+44 int wd_loadav[3];
+56 int wd_boottime;
+60 struct whoent {
+ struct outmp we_utmp;
+(20 each) int we_idle;
+ } wd_we[1024 / sizeof (struct whoent)];
+ };
+
+ Linux 2.0 May 13, 1997 2
+
+ *
+ */
+
+static int proto_who = -1;
+static int hf_who_vers = -1;
+static int hf_who_type = -1;
+static int hf_who_sendtime = -1;
+static int hf_who_recvtime = -1;
+static int hf_who_hostname = -1;
+static int hf_who_loadav_5 = -1;
+static int hf_who_loadav_10 = -1;
+static int hf_who_loadav_15 = -1;
+static int hf_who_boottime = -1;
+static int hf_who_whoent = -1;
+static int hf_who_tty = -1;
+static int hf_who_uid = -1;
+static int hf_who_timeon = -1;
+static int hf_who_idle = -1;
+
+static gint ett_who = -1;
+static gint ett_whoent = -1;
+
+#define UDP_PORT_WHO 513
+
+static void dissect_whoent(tvbuff_t *tvb, int offset, proto_tree *tree);
+
+static void
+dissect_who(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *who_tree = NULL;
+ proto_item *who_ti = NULL;
+ gchar server_name[33];
+ double loadav_5 = 0.0, loadav_10 = 0.0, loadav_15 = 0.0;
+ nstime_t ts;
+
+ /* Summary information */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WHO");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ts.nsecs = 0;
+
+ if (tree) {
+ who_ti = proto_tree_add_item(tree, proto_who, tvb, offset, -1,
+ FALSE);
+ who_tree = proto_item_add_subtree(who_ti, ett_who);
+ }
+
+ if (tree)
+ proto_tree_add_item(who_tree, hf_who_vers, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ if (tree)
+ proto_tree_add_item(who_tree, hf_who_type, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ /* 2 filler bytes */
+ offset += 2;
+
+ if (tree) {
+ ts.secs = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_time(who_tree, hf_who_sendtime, tvb, offset, 4,
+ &ts);
+ }
+ offset += 4;
+
+ if (tree) {
+ ts.secs = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_time(who_tree, hf_who_recvtime, tvb, offset, 4,
+ &ts);
+ }
+ offset += 4;
+
+ tvb_get_nstringz0(tvb, offset, sizeof(server_name), server_name);
+ if (tree)
+ proto_tree_add_string(who_tree, hf_who_hostname, tvb, offset,
+ 32, server_name);
+ offset += 32;
+
+ loadav_5 = (double) tvb_get_ntohl(tvb, offset) / 100.0;
+ if (tree)
+ proto_tree_add_double(who_tree, hf_who_loadav_5, tvb, offset,
+ 4, loadav_5);
+ offset += 4;
+
+ loadav_10 = (double) tvb_get_ntohl(tvb, offset) / 100.0;
+ if (tree)
+ proto_tree_add_double(who_tree, hf_who_loadav_10, tvb, offset,
+ 4, loadav_10);
+ offset += 4;
+
+ loadav_15 = (double) tvb_get_ntohl(tvb, offset) / 100.0;
+ if (tree)
+ proto_tree_add_double(who_tree, hf_who_loadav_15, tvb, offset,
+ 4, loadav_15);
+ offset += 4;
+
+ /* Summary information */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %.02f %.02f %.02f",
+ server_name, loadav_5, loadav_10, loadav_15);
+
+ if (tree) {
+ ts.secs = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_time(who_tree, hf_who_boottime, tvb, offset, 4,
+ &ts);
+ offset += 4;
+
+ dissect_whoent(tvb, offset, who_tree);
+ }
+}
+
+/* The man page says that (1024 / sizeof(struct whoent)) is the maximum number
+ * of whoent structures in the packet. */
+#define SIZE_OF_WHOENT 24
+#define MAX_NUM_WHOENTS (1024 / SIZE_OF_WHOENT)
+
+static void
+dissect_whoent(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ proto_tree *whoent_tree = NULL;
+ proto_item *whoent_ti = NULL;
+ int line_offset = offset;
+ gchar out_line[9];
+ gchar out_name[9];
+ nstime_t ts;
+ int whoent_num = 0;
+ guint32 idle_secs; /* say that out loud... */
+
+ ts.nsecs = 0;
+
+ while (tvb_reported_length_remaining(tvb, line_offset) > 0
+ && whoent_num < MAX_NUM_WHOENTS) {
+ whoent_ti = proto_tree_add_item(tree, hf_who_whoent, tvb,
+ line_offset, SIZE_OF_WHOENT, FALSE);
+ whoent_tree = proto_item_add_subtree(whoent_ti, ett_whoent);
+
+ tvb_get_nstringz0(tvb, line_offset, sizeof(out_line), out_line);
+ proto_tree_add_string(whoent_tree, hf_who_tty, tvb, line_offset,
+ 8, out_line);
+ line_offset += 8;
+
+ tvb_get_nstringz0(tvb, line_offset, sizeof(out_name), out_name);
+ proto_tree_add_string(whoent_tree, hf_who_uid, tvb, line_offset,
+ 8, out_name);
+ line_offset += 8;
+
+ ts.secs = tvb_get_ntohl(tvb, line_offset);
+ proto_tree_add_time(whoent_tree, hf_who_timeon, tvb,
+ line_offset, 4, &ts);
+ line_offset += 4;
+
+ idle_secs = tvb_get_ntohl(tvb, line_offset);
+ proto_tree_add_uint_format(whoent_tree, hf_who_idle, tvb,
+ line_offset, 4, idle_secs, "Idle: %s",
+ time_secs_to_str(idle_secs));
+ line_offset += 4;
+
+ whoent_num++;
+ }
+}
+
+void
+proto_register_who(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_who_vers,
+ { "Version", "who.vers", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_type,
+ { "Type", "who.type", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_sendtime,
+ { "Send Time", "who.sendtime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_recvtime,
+ { "Receive Time", "who.recvtime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_hostname,
+ { "Hostname", "who.hostname", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_loadav_5,
+ { "Load Average Over Past 5 Minutes", "who.loadav_5", FT_DOUBLE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_loadav_10,
+ { "Load Average Over Past 10 Minutes", "who.loadav_10", FT_DOUBLE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_loadav_15,
+ { "Load Average Over Past 15 Minutes", "who.loadav_15", FT_DOUBLE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_boottime,
+ { "Boot Time", "who.boottime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_whoent,
+ { "Who utmp Entry", "who.whoent", FT_NONE, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_tty,
+ { "TTY Name", "who.tty", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_uid,
+ { "User ID", "who.uid", FT_STRING, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_timeon,
+ { "Time On", "who.timeon", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "", HFILL }},
+
+ { &hf_who_idle,
+ { "Time Idle", "who.idle", FT_UINT32, BASE_DEC, NULL, 0x0,
+ "", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_who,
+ &ett_whoent,
+ };
+
+ proto_who = proto_register_protocol("Who", "WHO", "who");
+ proto_register_field_array(proto_who, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_who(void)
+{
+ dissector_handle_t who_handle;
+
+ who_handle = create_dissector_handle(dissect_who, proto_who);
+ dissector_add("udp.port", UDP_PORT_WHO, who_handle);
+}
diff --git a/epan/dissectors/packet-wlancap.c b/epan/dissectors/packet-wlancap.c
new file mode 100644
index 0000000000..ecb15a1419
--- /dev/null
+++ b/epan/dissectors/packet-wlancap.c
@@ -0,0 +1,302 @@
+/*
+ * packet-wlancap.c
+ * Decode packets with a AVS-WLAN header
+ *
+ * AVS linux-wlan-based products use a new sniff header to replace the
+ * old prism2-specific one dissected in packet-prism2.c. This one has
+ * additional fields, is designed to be non-hardware-specific, and more
+ * importantly, version and length fields so it can be extended later
+ * without breaking anything.
+ *
+ * See
+ *
+ * http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * By Solomon Peachy
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include <epan/packet.h>
+#include "packet-ieee80211.h"
+#include "packet-wlancap.h"
+
+#define SHORT_STR 256
+
+/* protocol */
+static int proto_wlancap = -1;
+
+/* header attached during wlan monitor mode */
+struct wlan_header_v1 {
+ guint32 version;
+ guint32 length;
+ guint64 mactime;
+ guint64 hosttime;
+ guint32 phytype;
+ guint32 channel;
+ guint32 datarate;
+ guint32 antenna;
+ guint32 priority;
+ guint32 ssi_type;
+ gint32 ssi_signal;
+ gint32 ssi_noise;
+ gint32 preamble;
+ gint32 encoding;
+};
+
+static int hf_wlan_version = -1;
+static int hf_wlan_length = -1;
+static int hf_wlan_mactime = -1;
+static int hf_wlan_hosttime = -1;
+static int hf_wlan_phytype = -1;
+static int hf_wlan_channel = -1;
+static int hf_wlan_datarate = -1;
+static int hf_wlan_antenna = -1;
+static int hf_wlan_priority = -1;
+static int hf_wlan_ssi_type = -1;
+static int hf_wlan_ssi_signal = -1;
+static int hf_wlan_ssi_noise = -1;
+static int hf_wlan_preamble = -1;
+static int hf_wlan_encoding = -1;
+
+static gint ett_wlan = -1;
+
+static dissector_handle_t ieee80211_handle;
+
+static void
+dissect_wlancap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+void
+capture_wlancap(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ /* XXX eventually add in a version test. */
+ if(!BYTES_ARE_IN_FRAME(offset, len, (int)sizeof(struct wlan_header_v1))) {
+ ld->other ++;
+ return;
+ }
+ offset += sizeof(struct wlan_header_v1);
+
+ /* 802.11 header follows */
+ capture_ieee80211(pd, offset, len, ld);
+}
+
+void
+proto_register_wlancap(void)
+{
+
+ static const value_string phy_type[] = {
+ { 0, "Unknown" },
+ { 1, "FHSS 802.11 '97" },
+ { 2, "DSSS 802.11 '97" },
+ { 3, "IR Baseband" },
+ { 4, "DSSS 802.11b" },
+ { 5, "PBCC 802.11b" },
+ { 6, "OFDM 802.11g" },
+ { 7, "PBCC 802.11g" },
+ { 8, "OFDM 802.11a" },
+ { 0, NULL },
+ };
+
+ static const value_string encoding_type[] = {
+ { 0, "Unknown" },
+ { 1, "CCK" },
+ { 2, "PBCC" },
+ { 3, "OFDM" },
+ { 0, NULL },
+ };
+
+ static const value_string ssi_type[] = {
+ { 0, "None" },
+ { 1, "Normalized RSSI" },
+ { 2, "dBm" },
+ { 3, "Raw RSSI" },
+ { 0, NULL },
+ };
+
+ static const value_string preamble_type[] = {
+ { 0, "Unknown" },
+ { 1, "Short" },
+ { 2, "Long" },
+ { 0, NULL },
+ };
+
+ static hf_register_info hf[] = {
+ { &hf_wlan_version, { "Header revision", "wlancap.version", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_wlan_length, { "Header length", "wlancap.length", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_wlan_mactime, { "MAC timestamp", "wlancap.mactime", FT_UINT64,
+ BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_wlan_hosttime, { "Host timestamp", "wlancap.hosttime", FT_UINT64,
+ BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_wlan_phytype, { "PHY type", "wlancap.phytype", FT_UINT32, BASE_DEC,
+ VALS(phy_type), 0x0, "", HFILL } },
+ { &hf_wlan_channel, { "Channel", "wlancap.channel", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL } },
+ { &hf_wlan_datarate, { "Data rate", "wlancap.datarate", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_wlan_antenna, { "Antenna", "wlancap.antenna", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL } },
+ { &hf_wlan_priority, { "Priority", "wlancap.priority", FT_UINT32, BASE_DEC,
+ NULL, 0x0, "", HFILL } },
+ { &hf_wlan_ssi_type, { "SSI Type", "wlancap.ssi_type", FT_UINT32, BASE_DEC,
+ VALS(ssi_type), 0x0, "", HFILL } },
+ { &hf_wlan_ssi_signal, { "SSI Signal", "wlancap.ssi_signal", FT_INT32,
+ BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_wlan_ssi_noise, { "SSI Noise", "wlancap.ssi_noise", FT_INT32,
+ BASE_DEC, NULL, 0x0, "", HFILL } },
+ { &hf_wlan_preamble, { "Preamble", "wlancap.preamble", FT_UINT32,
+ BASE_DEC, VALS(preamble_type), 0x0, "", HFILL } },
+ { &hf_wlan_encoding, { "Encoding Type", "wlancap.encoding", FT_UINT32,
+ BASE_DEC, VALS(encoding_type), 0x0, "", HFILL } },
+ };
+ static gint *ett[] = {
+ &ett_wlan
+ };
+
+ proto_wlancap = proto_register_protocol("AVS WLAN Capture header", "AVS WLANCAP", "wlancap");
+ proto_register_field_array(proto_wlancap, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("wlancap", dissect_wlancap, proto_wlancap);
+
+}
+
+static void
+dissect_wlancap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *wlan_tree;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+ int offset;
+ guint32 version;
+ guint32 length;
+ guint32 datarate;
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+ offset = 0;
+
+ version = tvb_get_ntohl(tvb, offset) - WLANCAP_MAGIC_COOKIE_BASE;
+ length = tvb_get_ntohl(tvb, offset+4);
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "AVS WLAN Capture v%x, Length %d",version, length);
+
+ if (check_col(pinfo->cinfo, COL_TX_RATE)) {
+ guint32 txrate = tvb_get_ntohl(tvb, offset + 32);
+ col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%d.%d",
+ txrate / 10, txrate % 10);
+ }
+ if (check_col(pinfo->cinfo, COL_RSSI)) {
+ /* XXX cook ssi_signal (Based on type; ie format) */
+ col_add_fstr(pinfo->cinfo, COL_RSSI, "%d",
+ tvb_get_ntohl(tvb, offset + 48));
+ }
+
+ /* Dissect the packet */
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_wlancap,
+ tvb, 0, length, "AVS WLAN Monitoring Header");
+ wlan_tree = proto_item_add_subtree(ti, ett_wlan);
+ proto_tree_add_uint(wlan_tree, hf_wlan_version, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset) - WLANCAP_MAGIC_COOKIE_BASE);
+ offset+=4;
+ proto_tree_add_uint(wlan_tree, hf_wlan_length, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ proto_tree_add_item(wlan_tree, hf_wlan_mactime, tvb, offset,
+ 8, FALSE);
+ offset+=8;
+ proto_tree_add_item(wlan_tree, hf_wlan_hosttime, tvb, offset,
+ 8, FALSE);
+ offset+=8;
+
+ proto_tree_add_uint(wlan_tree, hf_wlan_phytype, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ /* XXX cook channel (fh uses different numbers) */
+ proto_tree_add_uint(wlan_tree, hf_wlan_channel, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+
+ /* XXX - all other 802.11 pseudo-headers use 500Kb/s, not 100Kb/s,
+ as the units. */
+ datarate = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint_format(wlan_tree, hf_wlan_datarate, tvb, offset,
+ 4, datarate * 100,
+ "Data Rate: %u Kb/s", datarate * 100);
+ offset+=4;
+ proto_tree_add_uint(wlan_tree, hf_wlan_antenna, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ proto_tree_add_uint(wlan_tree, hf_wlan_priority, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ proto_tree_add_uint(wlan_tree, hf_wlan_ssi_type, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ /* XXX cook ssi_signal (Based on type; ie format) */
+ proto_tree_add_int(wlan_tree, hf_wlan_ssi_signal, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ /* XXX cook ssi_noise (Based on type; ie format) */
+ proto_tree_add_int(wlan_tree, hf_wlan_ssi_noise, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ proto_tree_add_uint(wlan_tree, hf_wlan_preamble, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ proto_tree_add_uint(wlan_tree, hf_wlan_encoding, tvb, offset,
+ 4, tvb_get_ntohl(tvb, offset));
+ offset+=4;
+ }
+
+ if (offset == 0)
+ offset = length;
+
+ /* dissect the 802.11 header next */
+ next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_reg_handoff_wlancap(void)
+{
+ dissector_handle_t wlancap_handle;
+
+ /* handle for 802.11 dissector */
+ ieee80211_handle = find_dissector("wlan");
+
+ wlancap_handle = create_dissector_handle(dissect_wlancap, proto_wlancap);
+
+ dissector_add("wtap_encap", WTAP_ENCAP_IEEE_802_11_WLAN_AVS, wlancap_handle);
+}
diff --git a/epan/dissectors/packet-wlancap.h b/epan/dissectors/packet-wlancap.h
new file mode 100644
index 0000000000..05c0990fcb
--- /dev/null
+++ b/epan/dissectors/packet-wlancap.h
@@ -0,0 +1,33 @@
+/*
+ * packet-wlancap.h
+ * Declarations for packet-wlancap.c
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+void capture_wlancap(const guchar *pd, int offset, int len, packet_counts *ld);
+void proto_register_wlancap(void);
+void proto_reg_handoff_wlancap(void);
+
+#define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
+#define WLANCAP_MAGIC_COOKIE_V1 0x80211001
diff --git a/epan/dissectors/packet-wsp.c b/epan/dissectors/packet-wsp.c
new file mode 100644
index 0000000000..e05bc1874c
--- /dev/null
+++ b/epan/dissectors/packet-wsp.c
@@ -0,0 +1,7410 @@
+/* packet-wsp.c
+ *
+ * Routines to dissect WSP component of WAP traffic.
+ *
+ * $Id$
+ *
+ * Refer to the AUTHORS file or the AUTHORS section in the man page
+ * for contacting the author(s) of this file.
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * WAP dissector based on original work by Ben Fowler
+ * Updated by Neil Hunter.
+ *
+ * WTLS support by Alexandre P. Ferreira (Splice IP).
+ *
+ * Openwave header support by Dermot Bradley (Openwave).
+ *
+ * Code optimizations, header value dissection simplification with parse error
+ * notification and macros, extra missing headers, WBXML registration,
+ * summary line of WSP PDUs,
+ * Session Initiation Request dissection
+ * by Olivier Biot.
+ *
+ * TODO - Move parts of dissection before and other parts after "if (tree)",
+ * for example skip almost all but content type in replies if tree is closed.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Edit with a 4-space tabulation */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/ipv6-utils.h>
+#include <epan/conversation.h>
+
+#include "packet-wap.h"
+#include "packet-wsp.h"
+
+#define PLURALIZE(x) ( (x) == 1 ? "" : "s" )
+
+/* General-purpose debug logger.
+ * Requires double parentheses because of variable arguments of printf().
+ *
+ * Enable debug logging for WSP by defining AM_CFLAGS
+ * so that it contains "-DDEBUG_wsp"
+ */
+#ifdef DEBUG_wsp
+#define DebugLog(x) \
+ printf("%s:%u: ", __FILE__, __LINE__); \
+ printf x; \
+ fflush(stdout)
+#else
+#define DebugLog(x) ;
+#endif
+
+/* Statistics (see doc/README.tapping) */
+#include "tap.h"
+static int wsp_tap = -1;
+
+
+/* File scoped variables for the protocol and registered fields */
+static int proto_wsp = HF_EMPTY;
+static int proto_sir = HF_EMPTY;
+
+/*
+ * Initialize the header field pointers
+ */
+
+/* WSP header fields and their subfields if available */
+static int hf_hdr_name = HF_EMPTY;
+static int hf_hdr_accept = HF_EMPTY;
+static int hf_hdr_accept_charset = HF_EMPTY;
+static int hf_hdr_accept_encoding = HF_EMPTY;
+static int hf_hdr_accept_language = HF_EMPTY;
+static int hf_hdr_accept_ranges = HF_EMPTY;
+static int hf_hdr_age = HF_EMPTY;
+static int hf_hdr_allow = HF_EMPTY;
+static int hf_hdr_authorization = HF_EMPTY;
+static int hf_hdr_authorization_scheme = HF_EMPTY; /* Subfield */
+static int hf_hdr_authorization_user_id = HF_EMPTY; /* Subfield */
+static int hf_hdr_authorization_password = HF_EMPTY; /* Subfield */
+static int hf_hdr_cache_control = HF_EMPTY;
+static int hf_hdr_connection = HF_EMPTY;
+static int hf_hdr_content_base = HF_EMPTY;
+static int hf_hdr_content_encoding = HF_EMPTY;
+static int hf_hdr_content_language = HF_EMPTY;
+static int hf_hdr_content_length = HF_EMPTY;
+static int hf_hdr_content_location = HF_EMPTY;
+static int hf_hdr_content_md5 = HF_EMPTY;
+static int hf_hdr_content_range = HF_EMPTY;
+static int hf_hdr_content_range_first_byte_pos = HF_EMPTY; /* Subfield */
+static int hf_hdr_content_range_entity_length = HF_EMPTY; /* Subfield */
+static int hf_hdr_content_type = HF_EMPTY;
+static int hf_hdr_date = HF_EMPTY;
+static int hf_hdr_etag = HF_EMPTY;
+static int hf_hdr_expires = HF_EMPTY;
+static int hf_hdr_from = HF_EMPTY;
+static int hf_hdr_host = HF_EMPTY;
+static int hf_hdr_if_modified_since = HF_EMPTY;
+static int hf_hdr_if_match = HF_EMPTY;
+static int hf_hdr_if_none_match = HF_EMPTY;
+static int hf_hdr_if_range = HF_EMPTY;
+static int hf_hdr_if_unmodified_since = HF_EMPTY;
+static int hf_hdr_last_modified = HF_EMPTY;
+static int hf_hdr_location = HF_EMPTY;
+static int hf_hdr_max_forwards = HF_EMPTY;
+static int hf_hdr_pragma = HF_EMPTY;
+static int hf_hdr_proxy_authenticate = HF_EMPTY;
+static int hf_hdr_proxy_authenticate_scheme = HF_EMPTY; /* Subfield */
+static int hf_hdr_proxy_authenticate_realm = HF_EMPTY; /* Subfield */
+static int hf_hdr_proxy_authorization = HF_EMPTY;
+static int hf_hdr_proxy_authorization_scheme = HF_EMPTY; /* Subfield */
+static int hf_hdr_proxy_authorization_user_id = HF_EMPTY; /* Subfield */
+static int hf_hdr_proxy_authorization_password = HF_EMPTY; /* Subfield */
+static int hf_hdr_public = HF_EMPTY;
+static int hf_hdr_range = HF_EMPTY;
+static int hf_hdr_range_first_byte_pos = HF_EMPTY; /* Subfield */
+static int hf_hdr_range_last_byte_pos = HF_EMPTY; /* Subfield */
+static int hf_hdr_range_suffix_length = HF_EMPTY; /* Subfield */
+static int hf_hdr_referer = HF_EMPTY;
+static int hf_hdr_retry_after = HF_EMPTY;
+static int hf_hdr_server = HF_EMPTY;
+static int hf_hdr_transfer_encoding = HF_EMPTY;
+static int hf_hdr_upgrade = HF_EMPTY;
+static int hf_hdr_user_agent = HF_EMPTY;
+static int hf_hdr_vary = HF_EMPTY;
+static int hf_hdr_via = HF_EMPTY;
+static int hf_hdr_warning = HF_EMPTY;
+static int hf_hdr_warning_code = HF_EMPTY; /* Subfield */
+static int hf_hdr_warning_agent = HF_EMPTY; /* Subfield */
+static int hf_hdr_warning_text = HF_EMPTY; /* Subfield */
+static int hf_hdr_www_authenticate = HF_EMPTY;
+static int hf_hdr_www_authenticate_scheme = HF_EMPTY; /* Subfield */
+static int hf_hdr_www_authenticate_realm = HF_EMPTY; /* Subfield */
+static int hf_hdr_content_disposition = HF_EMPTY;
+static int hf_hdr_application_id = HF_EMPTY;
+static int hf_hdr_content_uri = HF_EMPTY;
+static int hf_hdr_initiator_uri = HF_EMPTY;
+static int hf_hdr_bearer_indication = HF_EMPTY;
+static int hf_hdr_push_flag = HF_EMPTY;
+static int hf_hdr_push_flag_auth = HF_EMPTY; /* Subfield */
+static int hf_hdr_push_flag_trust = HF_EMPTY; /* Subfield */
+static int hf_hdr_push_flag_last = HF_EMPTY; /* Subfield */
+static int hf_hdr_profile = HF_EMPTY;
+static int hf_hdr_profile_diff = HF_EMPTY;
+static int hf_hdr_profile_warning = HF_EMPTY;
+static int hf_hdr_expect = HF_EMPTY;
+static int hf_hdr_te = HF_EMPTY;
+static int hf_hdr_trailer = HF_EMPTY;
+static int hf_hdr_x_wap_tod = HF_EMPTY;
+static int hf_hdr_content_id = HF_EMPTY;
+static int hf_hdr_set_cookie = HF_EMPTY;
+static int hf_hdr_cookie = HF_EMPTY;
+static int hf_hdr_encoding_version = HF_EMPTY;
+static int hf_hdr_x_wap_security = HF_EMPTY;
+static int hf_hdr_x_wap_application_id = HF_EMPTY;
+static int hf_hdr_accept_application = HF_EMPTY;
+
+
+/* Openwave headers */
+static int hf_hdr_openwave_x_up_proxy_operator_domain = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_home_page = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_uplink_version = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_ba_realm = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_request_uri = HF_EMPTY;
+#if 0
+static int hf_hdr_openwave_x_up_proxy_client_id = HF_EMPTY;
+#endif
+static int hf_hdr_openwave_x_up_proxy_bookmark = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_push_seq = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_notify = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_net_ask = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_tod = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_ba_enable = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_redirect_enable = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_redirect_status = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_linger = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_enable_trust = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_trust = HF_EMPTY;
+static int hf_hdr_openwave_x_up_devcap_has_color = HF_EMPTY;
+static int hf_hdr_openwave_x_up_devcap_num_softkeys = HF_EMPTY;
+static int hf_hdr_openwave_x_up_devcap_softkey_size = HF_EMPTY;
+static int hf_hdr_openwave_x_up_devcap_screen_chars = HF_EMPTY;
+static int hf_hdr_openwave_x_up_devcap_screen_pixels = HF_EMPTY;
+static int hf_hdr_openwave_x_up_devcap_em_size = HF_EMPTY;
+static int hf_hdr_openwave_x_up_devcap_screen_depth = HF_EMPTY;
+static int hf_hdr_openwave_x_up_devcap_immed_alert = HF_EMPTY;
+static int hf_hdr_openwave_x_up_devcap_gui = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_trans_charset = HF_EMPTY;
+static int hf_hdr_openwave_x_up_proxy_push_accept = HF_EMPTY;
+
+
+/* WSP parameter fields */
+static int hf_parameter_q = HF_EMPTY;
+static int hf_parameter_charset = HF_EMPTY;
+#if 0
+static int hf_parameter_textual = HF_EMPTY;
+static int hf_parameter_type = HF_EMPTY;
+static int hf_parameter_name = HF_EMPTY;
+static int hf_parameter_filename = HF_EMPTY;
+static int hf_parameter_start = HF_EMPTY;
+static int hf_parameter_start_info = HF_EMPTY;
+static int hf_parameter_comment = HF_EMPTY;
+static int hf_parameter_domain = HF_EMPTY;
+static int hf_parameter_path = HF_EMPTY;
+static int hf_parameter_sec = HF_EMPTY;
+static int hf_parameter_mac = HF_EMPTY;
+static int hf_parameter_upart_type = HF_EMPTY;
+static int hf_parameter_upart_type_value = HF_EMPTY;
+static int hf_parameter_level = HF_EMPTY;
+#endif
+
+/* Old header fields */
+
+static int hf_wsp_header_tid = HF_EMPTY;
+static int hf_wsp_header_pdu_type = HF_EMPTY;
+static int hf_wsp_version_major = HF_EMPTY;
+static int hf_wsp_version_minor = HF_EMPTY;
+/* Session capabilities (CO-WSP) */
+static int hf_capabilities_length = HF_EMPTY;
+static int hf_capabilities_section = HF_EMPTY;
+static int hf_capa_client_sdu_size = HF_EMPTY;
+static int hf_capa_server_sdu_size = HF_EMPTY;
+static int hf_capa_protocol_options = HF_EMPTY;
+static int hf_capa_protocol_option_confirmed_push = HF_EMPTY; /* Subfield */
+static int hf_capa_protocol_option_push = HF_EMPTY; /* Subfield */
+static int hf_capa_protocol_option_session_resume = HF_EMPTY; /* Subfield */
+static int hf_capa_protocol_option_ack_headers = HF_EMPTY; /* Subfield */
+static int hf_capa_protocol_option_large_data_transfer = HF_EMPTY; /* Subfield */
+static int hf_capa_method_mor = HF_EMPTY;
+static int hf_capa_push_mor = HF_EMPTY;
+static int hf_capa_extended_methods = HF_EMPTY;
+static int hf_capa_header_code_pages = HF_EMPTY;
+static int hf_capa_aliases = HF_EMPTY;
+static int hf_capa_client_message_size = HF_EMPTY;
+static int hf_capa_server_message_size = HF_EMPTY;
+
+static int hf_wsp_header_uri_len = HF_EMPTY;
+static int hf_wsp_header_uri = HF_EMPTY;
+static int hf_wsp_server_session_id = HF_EMPTY;
+static int hf_wsp_header_status = HF_EMPTY;
+static int hf_wsp_header_length = HF_EMPTY;
+static int hf_wsp_headers_section = HF_EMPTY;
+static int hf_wsp_parameter_type = HF_EMPTY;
+static int hf_wsp_parameter_name = HF_EMPTY;
+static int hf_wsp_parameter_filename = HF_EMPTY;
+static int hf_wsp_parameter_start = HF_EMPTY;
+static int hf_wsp_parameter_start_info = HF_EMPTY;
+static int hf_wsp_parameter_comment = HF_EMPTY;
+static int hf_wsp_parameter_domain = HF_EMPTY;
+static int hf_wsp_parameter_path = HF_EMPTY;
+static int hf_wsp_parameter_sec = HF_EMPTY;
+static int hf_wsp_parameter_mac = HF_EMPTY;
+static int hf_wsp_parameter_upart_type = HF_EMPTY;
+static int hf_wsp_parameter_level = HF_EMPTY;
+static int hf_wsp_parameter_size = HF_EMPTY;
+static int hf_wsp_reply_data = HF_EMPTY;
+static int hf_wsp_post_data = HF_EMPTY;
+static int hf_wsp_push_data = HF_EMPTY;
+static int hf_wsp_multipart_data = HF_EMPTY;
+static int hf_wsp_mpart = HF_EMPTY;
+
+/* Header code page shift sequence */
+static int hf_wsp_header_shift_code = HF_EMPTY;
+
+/* WSP Redirect fields */
+static int hf_wsp_redirect_flags = HF_EMPTY;
+static int hf_wsp_redirect_permanent = HF_EMPTY;
+static int hf_wsp_redirect_reuse_security_session = HF_EMPTY;
+static int hf_redirect_addresses = HF_EMPTY;
+
+/* Address fields */
+static int hf_address_entry = HF_EMPTY;
+static int hf_address_flags_length = HF_EMPTY;
+static int hf_address_flags_length_bearer_type_included = HF_EMPTY; /* Subfield */
+static int hf_address_flags_length_port_number_included = HF_EMPTY; /* Subfield */
+static int hf_address_flags_length_address_len = HF_EMPTY; /* Subfield */
+static int hf_address_bearer_type = HF_EMPTY;
+static int hf_address_port_num = HF_EMPTY;
+static int hf_address_ipv4_addr = HF_EMPTY;
+static int hf_address_ipv6_addr = HF_EMPTY;
+static int hf_address_addr = HF_EMPTY;
+
+/* Session Initiation Request fields */
+static int hf_sir_section = HF_EMPTY;
+static int hf_sir_version = HF_EMPTY;
+static int hf_sir_app_id_list_len = HF_EMPTY;
+static int hf_sir_app_id_list = HF_EMPTY;
+static int hf_sir_wsp_contact_points_len = HF_EMPTY;
+static int hf_sir_wsp_contact_points = HF_EMPTY;
+static int hf_sir_contact_points_len = HF_EMPTY;
+static int hf_sir_contact_points = HF_EMPTY;
+static int hf_sir_protocol_options_len = HF_EMPTY;
+static int hf_sir_protocol_options = HF_EMPTY;
+static int hf_sir_prov_url_len = HF_EMPTY;
+static int hf_sir_prov_url = HF_EMPTY;
+static int hf_sir_cpi_tag_len = HF_EMPTY;
+static int hf_sir_cpi_tag = HF_EMPTY;
+
+/*
+ * Initialize the subtree pointers
+ */
+
+/* WSP tree */
+static int ett_wsp = ETT_EMPTY;
+/* WSP headers tree */
+static int ett_header = ETT_EMPTY;
+/* WSP header subtree */
+static int ett_headers = ETT_EMPTY;
+/* CO-WSP session capabilities */
+static int ett_capabilities = ETT_EMPTY;
+static int ett_capability = ETT_EMPTY;
+static int ett_post = ETT_EMPTY;
+static int ett_redirect_flags = ETT_EMPTY;
+static int ett_address_flags = ETT_EMPTY;
+static int ett_multiparts = ETT_EMPTY;
+static int ett_mpartlist = ETT_EMPTY;
+/* Session Initiation Request tree */
+static int ett_sir = ETT_EMPTY;
+static int ett_addresses = ETT_EMPTY;
+static int ett_address = ETT_EMPTY;
+
+
+
+/* Handle for WSP-over-UDP dissector */
+static dissector_handle_t wsp_fromudp_handle;
+
+/* Handle for WTP-over-UDP dissector */
+static dissector_handle_t wtp_fromudp_handle;
+
+/* Handle for generic media dissector */
+static dissector_handle_t media_handle;
+
+/* Handle for WBXML-encoded UAPROF dissector */
+static dissector_handle_t wbxml_uaprof_handle;
+
+const value_string vals_pdu_type[] = {
+ { 0x00, "Reserved" },
+ { 0x01, "Connect" },
+ { 0x02, "ConnectReply" },
+ { 0x03, "Redirect" },
+ { 0x04, "Reply" },
+ { 0x05, "Disconnect" },
+ { 0x06, "Push" },
+ { 0x07, "ConfirmedPush" },
+ { 0x08, "Suspend" },
+ { 0x09, "Resume" },
+
+ /* 0x10 - 0x3F Unassigned */
+
+ { 0x40, "Get" },
+ { 0x41, "Options" },
+ { 0x42, "Head" },
+ { 0x43, "Delete" },
+ { 0x44, "Trace" },
+
+ /* 0x45 - 0x4F Unassigned (Get PDU) */
+ /* 0x50 - 0x5F Extended method (Get PDU) */
+ { 0x50, "Extended Get Method 0"},
+ { 0x51, "Extended Get Method 1"},
+ { 0x52, "Extended Get Method 2"},
+ { 0x53, "Extended Get Method 3"},
+ { 0x54, "Extended Get Method 4"},
+ { 0x55, "Extended Get Method 5"},
+ { 0x56, "Extended Get Method 6"},
+ { 0x57, "Extended Get Method 7"},
+ { 0x58, "Extended Get Method 8"},
+ { 0x59, "Extended Get Method 9"},
+ { 0x5A, "Extended Get Method 10"},
+ { 0x5B, "Extended Get Method 11"},
+ { 0x5C, "Extended Get Method 12"},
+ { 0x5D, "Extended Get Method 13"},
+ { 0x5E, "Extended Get Method 14"},
+ { 0x5F, "Extended Get Method 15"},
+
+ { 0x60, "Post" },
+ { 0x61, "Put" },
+
+ /* 0x62 - 0x6F Unassigned (Post PDU) */
+ /* 0x70 - 0x7F Extended method (Post PDU) */
+ { 0x70, "Extended Post Method 0"},
+ { 0x71, "Extended Post Method 1"},
+ { 0x72, "Extended Post Method 2"},
+ { 0x73, "Extended Post Method 3"},
+ { 0x74, "Extended Post Method 4"},
+ { 0x75, "Extended Post Method 5"},
+ { 0x76, "Extended Post Method 6"},
+ { 0x77, "Extended Post Method 7"},
+ { 0x78, "Extended Post Method 8"},
+ { 0x79, "Extended Post Method 9"},
+ { 0x7A, "Extended Post Method 10"},
+ { 0x7B, "Extended Post Method 11"},
+ { 0x7C, "Extended Post Method 12"},
+ { 0x7D, "Extended Post Method 13"},
+ { 0x7E, "Extended Post Method 14"},
+ { 0x7F, "Extended Post Method 15"},
+
+ /* 0x80 - 0xFF Reserved */
+
+ { 0x00, NULL }
+
+};
+
+/* The WSP status codes are inherited from the HTTP status codes */
+const value_string vals_status[] = {
+ /* 0x00 - 0x0F Reserved */
+
+ { 0x10, "100 Continue" },
+ { 0x11, "101 Switching Protocols" },
+
+ { 0x20, "200 OK" },
+ { 0x21, "201 Created" },
+ { 0x22, "202 Accepted" },
+ { 0x23, "203 Non-Authoritative Information" },
+ { 0x24, "204 No Content" },
+ { 0x25, "205 Reset Content" },
+ { 0x26, "206 Partial Content" },
+
+ { 0x30, "300 Multiple Choices" },
+ { 0x31, "301 Moved Permanently" },
+ { 0x32, "302 Moved Temporarily" },
+ { 0x33, "303 See Other" },
+ { 0x34, "304 Not Modified" },
+ { 0x35, "305 Use Proxy" },
+ { 0x37, "307 Temporary Redirect" },
+
+ { 0x40, "400 Bad Request" },
+ { 0x41, "401 Unauthorised" },
+ { 0x42, "402 Payment Required" },
+ { 0x43, "403 Forbidden" },
+ { 0x44, "404 Not Found" },
+ { 0x45, "405 Method Not Allowed" },
+ { 0x46, "406 Not Acceptable" },
+ { 0x47, "407 Proxy Authentication Required" },
+ { 0x48, "408 Request Timeout" },
+ { 0x49, "409 Conflict" },
+ { 0x4A, "410 Gone" },
+ { 0x4B, "411 Length Required" },
+ { 0x4C, "412 Precondition Failed" },
+ { 0x4D, "413 Request Entity Too Large" },
+ { 0x4E, "414 Request-URI Too Large" },
+ { 0x4F, "415 Unsupported Media Type" },
+ { 0x50, "416 Requested Range Not Satisfiable" },
+ { 0x51, "417 Expectation Failed" },
+
+ { 0x60, "500 Internal Server Error" },
+ { 0x61, "501 Not Implemented" },
+ { 0x62, "502 Bad Gateway" },
+ { 0x63, "503 Service Unavailable" },
+ { 0x64, "504 Gateway Timeout" },
+ { 0x65, "505 WSP/HTTP Version Not Supported" },
+
+ { 0x00, NULL }
+};
+
+const value_string vals_wsp_reason_codes[] = {
+ { 0xE0, "Protocol Error (Illegal PDU)" },
+ { 0xE1, "Session disconnected" },
+ { 0xE2, "Session suspended" },
+ { 0xE3, "Session resumed" },
+ { 0xE4, "Peer congested" },
+ { 0xE5, "Session connect failed" },
+ { 0xE6, "Maximum receive unit size exceeded" },
+ { 0xE7, "Maximum outstanding requests exceeded" },
+ { 0xE8, "Peer request" },
+ { 0xE9, "Network error" },
+ { 0xEA, "User request" },
+ { 0xEB, "No specific cause, no retries" },
+ { 0xEC, "Push message cannot be delivered" },
+ { 0xED, "Push message discarded" },
+ { 0xEE, "Content type cannot be processed" },
+
+ { 0x00, NULL }
+};
+
+/*
+ * Field names.
+ */
+#define FN_ACCEPT 0x00
+#define FN_ACCEPT_CHARSET_DEP 0x01 /* encoding version 1.1, deprecated */
+#define FN_ACCEPT_ENCODING_DEP 0x02 /* encoding version 1.1, deprecated */
+#define FN_ACCEPT_LANGUAGE 0x03
+#define FN_ACCEPT_RANGES 0x04
+#define FN_AGE 0x05
+#define FN_ALLOW 0x06
+#define FN_AUTHORIZATION 0x07
+#define FN_CACHE_CONTROL_DEP 0x08 /* encoding version 1.1, deprecated */
+#define FN_CONNECTION 0x09
+#define FN_CONTENT_BASE 0x0A
+#define FN_CONTENT_ENCODING 0x0B
+#define FN_CONTENT_LANGUAGE 0x0C
+#define FN_CONTENT_LENGTH 0x0D
+#define FN_CONTENT_LOCATION 0x0E
+#define FN_CONTENT_MD5 0x0F
+#define FN_CONTENT_RANGE_DEP 0x10 /* encoding version 1.1, deprecated */
+#define FN_CONTENT_TYPE 0x11
+#define FN_DATE 0x12
+#define FN_ETAG 0x13
+#define FN_EXPIRES 0x14
+#define FN_FROM 0x15
+#define FN_HOST 0x16
+#define FN_IF_MODIFIED_SINCE 0x17
+#define FN_IF_MATCH 0x18
+#define FN_IF_NONE_MATCH 0x19
+#define FN_IF_RANGE 0x1A
+#define FN_IF_UNMODIFIED_SINCE 0x1B
+#define FN_LOCATION 0x1C
+#define FN_LAST_MODIFIED 0x1D
+#define FN_MAX_FORWARDS 0x1E
+#define FN_PRAGMA 0x1F
+#define FN_PROXY_AUTHENTICATE 0x20
+#define FN_PROXY_AUTHORIZATION 0x21
+#define FN_PUBLIC 0x22
+#define FN_RANGE 0x23
+#define FN_REFERER 0x24
+#define FN_RETRY_AFTER 0x25
+#define FN_SERVER 0x26
+#define FN_TRANSFER_ENCODING 0x27
+#define FN_UPGRADE 0x28
+#define FN_USER_AGENT 0x29
+#define FN_VARY 0x2A
+#define FN_VIA 0x2B
+#define FN_WARNING 0x2C
+#define FN_WWW_AUTHENTICATE 0x2D
+#define FN_CONTENT_DISPOSITION 0x2E
+#define FN_X_WAP_APPLICATION_ID 0x2F
+#define FN_X_WAP_CONTENT_URI 0x30
+#define FN_X_WAP_INITIATOR_URI 0x31
+#define FN_ACCEPT_APPLICATION 0x32
+#define FN_BEARER_INDICATION 0x33
+#define FN_PUSH_FLAG 0x34
+#define FN_PROFILE 0x35
+#define FN_PROFILE_DIFF 0x36
+#define FN_PROFILE_WARNING 0x37
+#define FN_EXPECT 0x38
+#define FN_TE 0x39
+#define FN_TRAILER 0x3A
+#define FN_ACCEPT_CHARSET 0x3B /* encoding version 1.3 */
+#define FN_ACCEPT_ENCODING 0x3C /* encoding version 1.3 */
+#define FN_CACHE_CONTROL 0x3D /* encoding version 1.3 */
+#define FN_CONTENT_RANGE 0x3E /* encoding version 1.3 */
+#define FN_X_WAP_TOD 0x3F
+#define FN_CONTENT_ID 0x40
+#define FN_SET_COOKIE 0x41
+#define FN_COOKIE 0x42
+#define FN_ENCODING_VERSION 0x43
+#define FN_PROFILE_WARNING14 0x44 /* encoding version 1.4 */
+#define FN_CONTENT_DISPOSITION14 0x45 /* encoding version 1.4 */
+#define FN_X_WAP_SECURITY 0x46
+#define FN_CACHE_CONTROL14 0x47 /* encoding version 1.4 */
+#define FN_EXPECT15 0x48 /* encoding version 1.5 */
+#define FN_X_WAP_LOC_INVOCATION 0x49
+#define FN_X_WAP_LOC_DELIVERY 0x4A
+
+
+/*
+ * Openwave field names.
+ */
+#define FN_OPENWAVE_PROXY_PUSH_ADDR 0x00
+#define FN_OPENWAVE_PROXY_PUSH_ACCEPT 0x01
+#define FN_OPENWAVE_PROXY_PUSH_SEQ 0x02
+#define FN_OPENWAVE_PROXY_NOTIFY 0x03
+#define FN_OPENWAVE_PROXY_OPERATOR_DOMAIN 0x04
+#define FN_OPENWAVE_PROXY_HOME_PAGE 0x05
+#define FN_OPENWAVE_DEVCAP_HAS_COLOR 0x06
+#define FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS 0x07
+#define FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE 0x08
+#define FN_OPENWAVE_DEVCAP_SCREEN_CHARS 0x09
+#define FN_OPENWAVE_DEVCAP_SCREEN_PIXELS 0x0A
+#define FN_OPENWAVE_DEVCAP_EM_SIZE 0x0B
+#define FN_OPENWAVE_DEVCAP_SCREEN_DEPTH 0x0C
+#define FN_OPENWAVE_DEVCAP_IMMED_ALERT 0x0D
+#define FN_OPENWAVE_PROXY_NET_ASK 0x0E
+#define FN_OPENWAVE_PROXY_UPLINK_VERSION 0x0F
+#define FN_OPENWAVE_PROXY_TOD 0x10
+#define FN_OPENWAVE_PROXY_BA_ENABLE 0x11
+#define FN_OPENWAVE_PROXY_BA_REALM 0x12
+#define FN_OPENWAVE_PROXY_REDIRECT_ENABLE 0x13
+#define FN_OPENWAVE_PROXY_REQUEST_URI 0x14
+#define FN_OPENWAVE_PROXY_REDIRECT_STATUS 0x15
+#define FN_OPENWAVE_PROXY_TRANS_CHARSET 0x16
+#define FN_OPENWAVE_PROXY_LINGER 0x17
+#define FN_OPENWAVE_PROXY_CLIENT_ID 0x18
+#define FN_OPENWAVE_PROXY_ENABLE_TRUST 0x19
+#define FN_OPENWAVE_PROXY_TRUST_OLD 0x1A
+#define FN_OPENWAVE_PROXY_TRUST 0x20
+#define FN_OPENWAVE_PROXY_BOOKMARK 0x21
+#define FN_OPENWAVE_DEVCAP_GUI 0x22
+
+static const value_string vals_openwave_field_names[] = {
+ { FN_OPENWAVE_PROXY_PUSH_ADDR, "x-up-proxy-push-addr" },
+ { FN_OPENWAVE_PROXY_PUSH_ACCEPT, "x-up-proxy-push-accept" },
+ { FN_OPENWAVE_PROXY_PUSH_SEQ, "x-up-proxy-seq" },
+ { FN_OPENWAVE_PROXY_NOTIFY, "x-up-proxy-notify" },
+ { FN_OPENWAVE_PROXY_OPERATOR_DOMAIN, "x-up-proxy-operator-domain" },
+ { FN_OPENWAVE_PROXY_HOME_PAGE, "x-up-proxy-home-page" },
+ { FN_OPENWAVE_DEVCAP_HAS_COLOR, "x-up-devcap-has-color" },
+ { FN_OPENWAVE_DEVCAP_NUM_SOFTKEYS, "x-up-devcap-num-softkeys" },
+ { FN_OPENWAVE_DEVCAP_SOFTKEY_SIZE, "x-up-devcap-softkey-size" },
+ { FN_OPENWAVE_DEVCAP_SCREEN_CHARS, "x-up-devcap-screen-chars" },
+ { FN_OPENWAVE_DEVCAP_SCREEN_PIXELS, "x-up-devcap-screen-pixels" },
+ { FN_OPENWAVE_DEVCAP_EM_SIZE, "x-up-devcap-em-size" },
+ { FN_OPENWAVE_DEVCAP_SCREEN_DEPTH, "x-up-devcap-screen-depth" },
+ { FN_OPENWAVE_DEVCAP_IMMED_ALERT, "x-up-devcap-immed-alert" },
+ { FN_OPENWAVE_PROXY_NET_ASK, "x-up-proxy-net-ask" },
+ { FN_OPENWAVE_PROXY_UPLINK_VERSION, "x-up-proxy-uplink-version" },
+ { FN_OPENWAVE_PROXY_TOD, "x-up-proxy-tod" },
+ { FN_OPENWAVE_PROXY_BA_ENABLE, "x-up-proxy-ba-enable" },
+ { FN_OPENWAVE_PROXY_BA_REALM, "x-up-proxy-ba-realm" },
+ { FN_OPENWAVE_PROXY_REDIRECT_ENABLE, "x-up-proxy-redirect-enable" },
+ { FN_OPENWAVE_PROXY_REQUEST_URI, "x-up-proxy-request-uri" },
+ { FN_OPENWAVE_PROXY_REDIRECT_STATUS, "x-up-proxy-redirect-status" },
+ { FN_OPENWAVE_PROXY_TRANS_CHARSET, "x-up-proxy-trans-charset" },
+ { FN_OPENWAVE_PROXY_LINGER, "x-up-proxy-linger" },
+ { FN_OPENWAVE_PROXY_CLIENT_ID, "x-up-proxy-client-id" },
+ { FN_OPENWAVE_PROXY_ENABLE_TRUST, "x-up-proxy-enable-trust" },
+ { FN_OPENWAVE_PROXY_TRUST_OLD, "x-up-proxy-trust-old" },
+ { FN_OPENWAVE_PROXY_TRUST, "x-up-proxy-trust" },
+ { FN_OPENWAVE_PROXY_BOOKMARK, "x-up-proxy-bookmark" },
+ { FN_OPENWAVE_DEVCAP_GUI, "x-up-devcap-gui" },
+ { 0, NULL }
+};
+
+
+static const value_string vals_field_names[] = {
+ { FN_ACCEPT, "Accept" },
+ { FN_ACCEPT_CHARSET_DEP, "Accept-Charset (encoding 1.1)" },
+ { FN_ACCEPT_ENCODING_DEP, "Accept-Encoding (encoding 1.1)" },
+ { FN_ACCEPT_LANGUAGE, "Accept-Language" },
+ { FN_ACCEPT_RANGES, "Accept-Ranges" },
+ { FN_AGE, "Age" },
+ { FN_ALLOW, "Allow" },
+ { FN_AUTHORIZATION, "Authorization" },
+ { FN_CACHE_CONTROL_DEP, "Cache-Control (encoding 1.1)" },
+ { FN_CONNECTION, "Connection" },
+ { FN_CONTENT_BASE, "Content-Base" },
+ { FN_CONTENT_ENCODING, "Content-Encoding" },
+ { FN_CONTENT_LANGUAGE, "Content-Language" },
+ { FN_CONTENT_LENGTH, "Content-Length" },
+ { FN_CONTENT_LOCATION, "Content-Location" },
+ { FN_CONTENT_MD5, "Content-MD5" },
+ { FN_CONTENT_RANGE_DEP, "Content-Range (encoding 1.1)" },
+ { FN_CONTENT_TYPE, "Content-Type" },
+ { FN_DATE, "Date" },
+ { FN_ETAG, "ETag" },
+ { FN_EXPIRES, "Expires" },
+ { FN_FROM, "From" },
+ { FN_HOST, "Host" },
+ { FN_IF_MODIFIED_SINCE, "If-Modified-Since" },
+ { FN_IF_MATCH, "If-Match" },
+ { FN_IF_NONE_MATCH, "If-None-Match" },
+ { FN_IF_RANGE, "If-Range" },
+ { FN_IF_UNMODIFIED_SINCE, "If-Unmodified-Since" },
+ { FN_LOCATION, "Location" },
+ { FN_LAST_MODIFIED, "Last-Modified" },
+ { FN_MAX_FORWARDS, "Max-Forwards" },
+ { FN_PRAGMA, "Pragma" },
+ { FN_PROXY_AUTHENTICATE, "Proxy-Authenticate" },
+ { FN_PROXY_AUTHORIZATION, "Proxy-Authorization" },
+ { FN_PUBLIC, "Public" },
+ { FN_RANGE, "Range" },
+ { FN_REFERER, "Referer" },
+ { FN_RETRY_AFTER, "Retry-After" },
+ { FN_SERVER, "Server" },
+ { FN_TRANSFER_ENCODING, "Transfer-Encoding" },
+ { FN_UPGRADE, "Upgrade" },
+ { FN_USER_AGENT, "User-Agent" },
+ { FN_VARY, "Vary" },
+ { FN_VIA, "Via" },
+ { FN_WARNING, "Warning" },
+ { FN_WWW_AUTHENTICATE, "WWW-Authenticate" },
+ { FN_CONTENT_DISPOSITION, "Content-Disposition" },
+ { FN_X_WAP_APPLICATION_ID, "X-Wap-Application-ID" },
+ { FN_X_WAP_CONTENT_URI, "X-Wap-Content-URI" },
+ { FN_X_WAP_INITIATOR_URI, "X-Wap-Initiator-URI" },
+ { FN_ACCEPT_APPLICATION, "Accept-Application" },
+ { FN_BEARER_INDICATION, "Bearer-Indication" },
+ { FN_PUSH_FLAG, "Push-Flag" },
+ { FN_PROFILE, "Profile" },
+ { FN_PROFILE_DIFF, "Profile-Diff" },
+ { FN_PROFILE_WARNING, "Profile-Warning" },
+ { FN_EXPECT, "Expect" },
+ { FN_TE, "TE" },
+ { FN_TRAILER, "Trailer" },
+ { FN_ACCEPT_CHARSET, "Accept-Charset" },
+ { FN_ACCEPT_ENCODING, "Accept-Encoding" },
+ { FN_CACHE_CONTROL, "Cache-Control" },
+ { FN_CONTENT_RANGE, "Content-Range" },
+ { FN_X_WAP_TOD, "X-Wap-Tod" },
+ { FN_CONTENT_ID, "Content-ID" },
+ { FN_SET_COOKIE, "Set-Cookie" },
+ { FN_COOKIE, "Cookie" },
+ { FN_ENCODING_VERSION, "Encoding-Version" },
+ { FN_PROFILE_WARNING14, "Profile-Warning (encoding 1.4)" },
+ { FN_CONTENT_DISPOSITION14,"Content-Disposition (encoding 1.4)" },
+ { FN_X_WAP_SECURITY, "X-WAP-Security" },
+ { FN_CACHE_CONTROL14, "Cache-Control (encoding 1.4)" },
+ /* encoding-version 1.5 */
+ { FN_EXPECT15, "Expect (encoding 1.5)" },
+ { FN_X_WAP_LOC_INVOCATION, "X-Wap-Loc-Invocation" },
+ { FN_X_WAP_LOC_DELIVERY, "X-Wap-Loc-Delivery" },
+ { 0, NULL }
+};
+
+/*
+ * Bearer types (from the WDP specification).
+ */
+#define BT_IPv4 0x00
+#define BT_IPv6 0x01
+#define BT_GSM_USSD 0x02
+#define BT_GSM_SMS 0x03
+#define BT_ANSI_136_GUTS 0x04
+#define BT_IS_95_SMS 0x05
+#define BT_IS_95_CSD 0x06
+#define BT_IS_95_PACKET_DATA 0x07
+#define BT_ANSI_136_CSD 0x08
+#define BT_ANSI_136_PACKET_DATA 0x09
+#define BT_GSM_CSD 0x0A
+#define BT_GSM_GPRS 0x0B
+#define BT_GSM_USSD_IPv4 0x0C
+#define BT_AMPS_CDPD 0x0D
+#define BT_PDC_CSD 0x0E
+#define BT_PDC_PACKET_DATA 0x0F
+#define BT_IDEN_SMS 0x10
+#define BT_IDEN_CSD 0x11
+#define BT_IDEN_PACKET_DATA 0x12
+#define BT_PAGING_FLEX 0x13
+#define BT_PHS_SMS 0x14
+#define BT_PHS_CSD 0x15
+#define BT_GSM_USSD_GSM_SC 0x16
+#define BT_TETRA_SDS_ITSI 0x17
+#define BT_TETRA_SDS_MSISDN 0x18
+#define BT_TETRA_PACKET_DATA 0x19
+#define BT_PAGING_REFLEX 0x1A
+#define BT_GSM_USSD_MSISDN 0x1B
+#define BT_MOBITEX_MPAK 0x1C
+#define BT_ANSI_136_GHOST 0x1D
+
+static const value_string vals_bearer_types[] = {
+ { BT_IPv4, "IPv4" },
+ { BT_IPv6, "IPv6" },
+ { BT_GSM_USSD, "GSM USSD" },
+ { BT_GSM_SMS, "GSM SMS" },
+ { BT_ANSI_136_GUTS, "ANSI-136 GUTS/R-Data" },
+ { BT_IS_95_SMS, "IS-95 CDMA SMS" },
+ { BT_IS_95_CSD, "IS-95 CDMA CSD" },
+ { BT_IS_95_PACKET_DATA, "IS-95 CDMA Packet data" },
+ { BT_ANSI_136_CSD, "ANSI-136 CSD" },
+ { BT_ANSI_136_PACKET_DATA, "ANSI-136 Packet data" },
+ { BT_GSM_CSD, "GSM CSD" },
+ { BT_GSM_GPRS, "GSM GPRS" },
+ { BT_GSM_USSD_IPv4, "GSM USSD (IPv4 addresses)" },
+ { BT_AMPS_CDPD, "AMPS CDPD" },
+ { BT_PDC_CSD, "PDC CSD" },
+ { BT_PDC_PACKET_DATA, "PDC Packet data" },
+ { BT_IDEN_SMS, "IDEN SMS" },
+ { BT_IDEN_CSD, "IDEN CSD" },
+ { BT_IDEN_PACKET_DATA, "IDEN Packet data" },
+ { BT_PAGING_FLEX, "Paging network FLEX(TM)" },
+ { BT_PHS_SMS, "PHS SMS" },
+ { BT_PHS_CSD, "PHS CSD" },
+ { BT_GSM_USSD_GSM_SC, "GSM USSD (GSM Service Code addresses)" },
+ { BT_TETRA_SDS_ITSI, "TETRA SDS (ITSI addresses)" },
+ { BT_TETRA_SDS_MSISDN, "TETRA SDS (MSISDN addresses)" },
+ { BT_TETRA_PACKET_DATA, "TETRA Packet data" },
+ { BT_PAGING_REFLEX, "Paging network ReFLEX(TM)" },
+ { BT_GSM_USSD_MSISDN, "GSM USSD (MSISDN addresses)" },
+ { BT_MOBITEX_MPAK, "Mobitex MPAK" },
+ { BT_ANSI_136_GHOST, "ANSI-136 GHOST/R-Data" },
+ { 0, NULL }
+};
+
+static const value_string vals_content_types[] = {
+ /* Well-known media types */
+ { 0x00, "*/*" },
+ { 0x01, "text/*" },
+ { 0x02, "text/html" },
+ { 0x03, "text/plain" },
+ { 0x04, "text/x-hdml" },
+ { 0x05, "text/x-ttml" },
+ { 0x06, "text/x-vCalendar" },
+ { 0x07, "text/x-vCard" },
+ { 0x08, "text/vnd.wap.wml" },
+ { 0x09, "text/vnd.wap.wmlscript" },
+ { 0x0A, "text/vnd.wap.channel" },
+ { 0x0B, "multipart/*" },
+ { 0x0C, "multipart/mixed" },
+ { 0x0D, "multipart/form-data" },
+ { 0x0E, "multipart/byteranges" },
+ { 0x0F, "multipart/alternative" },
+ { 0x10, "application/*" },
+ { 0x11, "application/java-vm" },
+ { 0x12, "application/x-www-form-urlencoded" },
+ { 0x13, "application/x-hdmlc" },
+ { 0x14, "application/vnd.wap.wmlc" },
+ { 0x15, "application/vnd.wap.wmlscriptc" },
+ { 0x16, "application/vnd.wap.channelc" },
+ { 0x17, "application/vnd.wap.uaprof" },
+ { 0x18, "application/vnd.wap.wtls-ca-certificate" },
+ { 0x19, "application/vnd.wap.wtls-user-certificate" },
+ { 0x1A, "application/x-x509-ca-cert" },
+ { 0x1B, "application/x-x509-user-cert" },
+ { 0x1C, "image/*" },
+ { 0x1D, "image/gif" },
+ { 0x1E, "image/jpeg" },
+ { 0x1F, "image/tiff" },
+ { 0x20, "image/png" },
+ { 0x21, "image/vnd.wap.wbmp" },
+ { 0x22, "application/vnd.wap.multipart.*" },
+ { 0x23, "application/vnd.wap.multipart.mixed" },
+ { 0x24, "application/vnd.wap.multipart.form-data" },
+ { 0x25, "application/vnd.wap.multipart.byteranges" },
+ { 0x26, "application/vnd.wap.multipart.alternative" },
+ { 0x27, "application/xml" },
+ { 0x28, "text/xml" },
+ { 0x29, "application/vnd.wap.wbxml" },
+ { 0x2A, "application/x-x968-cross-cert" },
+ { 0x2B, "application/x-x968-ca-cert" },
+ { 0x2C, "application/x-x968-user-cert" },
+ { 0x2D, "text/vnd.wap.si" },
+ { 0x2E, "application/vnd.wap.sic" },
+ { 0x2F, "text/vnd.wap.sl" },
+ { 0x30, "application/vnd.wap.slc" },
+ { 0x31, "text/vnd.wap.co" },
+ { 0x32, "application/vnd.wap.coc" },
+ { 0x33, "application/vnd.wap.multipart.related" },
+ { 0x34, "application/vnd.wap.sia" },
+ { 0x35, "text/vnd.wap.connectivity-xml" },
+ { 0x36, "application/vnd.wap.connectivity-wbxml" },
+ { 0x37, "application/pkcs7-mime" },
+ { 0x38, "application/vnd.wap.hashed-certificate" },
+ { 0x39, "application/vnd.wap.signed-certificate" },
+ { 0x3A, "application/vnd.wap.cert-response" },
+ { 0x3B, "application/xhtml+xml" },
+ { 0x3C, "application/wml+xml" },
+ { 0x3D, "text/css" },
+ { 0x3E, "application/vnd.wap.mms-message" },
+ { 0x3F, "application/vnd.wap.rollover-certificate" },
+ { 0x40, "application/vnd.wap.locc+wbxml"},
+ { 0x41, "application/vnd.wap.loc+xml"},
+ { 0x42, "application/vnd.syncml.dm+wbxml"},
+ { 0x43, "application/vnd.syncml.dm+xml"},
+ { 0x44, "application/vnd.syncml.notification"},
+ { 0x45, "application/vnd.wap.xhtml+xml"},
+ { 0x46, "application/vnd.wv.csp.cir"},
+ { 0x47, "application/vnd.oma.dd+xml"},
+ { 0x48, "application/vnd.oma.drm.message"},
+ { 0x49, "application/vnd.oma.drm.content"},
+ { 0x4A, "application/vnd.oma.drm.rights+xml"},
+ { 0x4B, "application/vnd.oma.drm.rights+wbxml"},
+ { 0x4C, "application/vnd.wv.csp+xml"},
+ { 0x4D, "application/vnd.wv.csp+wbxml"},
+ /* The following media types are registered by 3rd parties */
+ { 0x0201, "application/vnd.uplanet.cachop-wbxml" },
+ { 0x0202, "application/vnd.uplanet.signal" },
+ { 0x0203, "application/vnd.uplanet.alert-wbxml" },
+ { 0x0204, "application/vnd.uplanet.list-wbxml" },
+ { 0x0205, "application/vnd.uplanet.listcmd-wbxml" },
+ { 0x0206, "application/vnd.uplanet.channel-wbxml" },
+ { 0x0207, "application/vnd.uplanet.provisioning-status-uri" },
+ { 0x0208, "x-wap.multipart/vnd.uplanet.header-set" },
+ { 0x0209, "application/vnd.uplanet.bearer-choice-wbxml" },
+ { 0x020A, "application/vnd.phonecom.mmc-wbxml" },
+ { 0x020B, "application/vnd.nokia.syncset+wbxml" },
+ { 0x020C, "image/x-up-wpng"},
+ { 0x0300, "application/iota.mmc-wbxml"},
+ { 0x0301, "application/iota.mmc-xml"},
+ { 0x00, NULL }
+};
+
+static const value_string vals_languages[] = {
+ { 0x01, "Afar (aa)" },
+ { 0x02, "Abkhazian (ab)" },
+ { 0x03, "Afrikaans (af)" },
+ { 0x04, "Amharic (am)" },
+ { 0x05, "Arabic (ar)" },
+ { 0x06, "Assamese (as)" },
+ { 0x07, "Aymara (ay)" },
+ { 0x08, "Azerbaijani (az)" },
+ { 0x09, "Bashkir (ba)" },
+ { 0x0A, "Byelorussian (be)" },
+ { 0x0B, "Bulgarian (bg)" },
+ { 0x0C, "Bihari (bh)" },
+ { 0x0D, "Bislama (bi)" },
+ { 0x0E, "Bengali; Bangla (bn)" },
+ { 0x0F, "Tibetan (bo)" },
+ { 0x10, "Breton (br)" },
+ { 0x11, "Catalan (ca)" },
+ { 0x12, "Corsican (co)" },
+ { 0x13, "Czech (cs)" },
+ { 0x14, "Welsh (cy)" },
+ { 0x15, "Danish (da)" },
+ { 0x16, "German (de)" },
+ { 0x17, "Bhutani (dz)" },
+ { 0x18, "Greek (el)" },
+ { 0x19, "English (en)" },
+ { 0x1A, "Esperanto (eo)" },
+ { 0x1B, "Spanish (es)" },
+ { 0x1C, "Estonian (et)" },
+ { 0x1D, "Basque (eu)" },
+ { 0x1E, "Persian (fa)" },
+ { 0x1F, "Finnish (fi)" },
+ { 0x20, "Fiji (fj)" },
+ { 0x21, "Urdu (ur)" },
+ { 0x22, "French (fr)" },
+ { 0x23, "Uzbek (uz)" },
+ { 0x24, "Irish (ga)" },
+ { 0x25, "Scots Gaelic (gd)" },
+ { 0x26, "Galician (gl)" },
+ { 0x27, "Guarani (gn)" },
+ { 0x28, "Gujarati (gu)" },
+ { 0x29, "Hausa (ha)" },
+ { 0x2A, "Hebrew (formerly iw) (he)" },
+ { 0x2B, "Hindi (hi)" },
+ { 0x2C, "Croatian (hr)" },
+ { 0x2D, "Hungarian (hu)" },
+ { 0x2E, "Armenian (hy)" },
+ { 0x2F, "Vietnamese (vi)" },
+ { 0x30, "Indonesian (formerly in) (id)" },
+ { 0x31, "Wolof (wo)" },
+ { 0x32, "Xhosa (xh)" },
+ { 0x33, "Icelandic (is)" },
+ { 0x34, "Italian (it)" },
+ { 0x35, "Yoruba (yo)" },
+ { 0x36, "Japanese (ja)" },
+ { 0x37, "Javanese (jw)" },
+ { 0x38, "Georgian (ka)" },
+ { 0x39, "Kazakh (kk)" },
+ { 0x3A, "Zhuang (za)" },
+ { 0x3B, "Cambodian (km)" },
+ { 0x3C, "Kannada (kn)" },
+ { 0x3D, "Korean (ko)" },
+ { 0x3E, "Kashmiri (ks)" },
+ { 0x3F, "Kurdish (ku)" },
+ { 0x40, "Kirghiz (ky)" },
+ { 0x41, "Chinese (zh)" },
+ { 0x42, "Lingala (ln)" },
+ { 0x43, "Laothian (lo)" },
+ { 0x44, "Lithuanian (lt)" },
+ { 0x45, "Latvian, Lettish (lv)" },
+ { 0x46, "Malagasy (mg)" },
+ { 0x47, "Maori (mi)" },
+ { 0x48, "Macedonian (mk)" },
+ { 0x49, "Malayalam (ml)" },
+ { 0x4A, "Mongolian (mn)" },
+ { 0x4B, "Moldavian (mo)" },
+ { 0x4C, "Marathi (mr)" },
+ { 0x4D, "Malay (ms)" },
+ { 0x4E, "Maltese (mt)" },
+ { 0x4F, "Burmese (my)" },
+ { 0x50, "Ukrainian (uk)" },
+ { 0x51, "Nepali (ne)" },
+ { 0x52, "Dutch (nl)" },
+ { 0x53, "Norwegian (no)" },
+ { 0x54, "Occitan (oc)" },
+ { 0x55, "(Afan) Oromo (om)" },
+ { 0x56, "Oriya (or)" },
+ { 0x57, "Punjabi (pa)" },
+ { 0x58, "Polish (po)" },
+ { 0x59, "Pashto, Pushto (ps)" },
+ { 0x5A, "Portuguese (pt)" },
+ { 0x5B, "Quechua (qu)" },
+ { 0x5C, "Zulu (zu)" },
+ { 0x5D, "Kirundi (rn)" },
+ { 0x5E, "Romanian (ro)" },
+ { 0x5F, "Russian (ru)" },
+ { 0x60, "Kinyarwanda (rw)" },
+ { 0x61, "Sanskrit (sa)" },
+ { 0x62, "Sindhi (sd)" },
+ { 0x63, "Sangho (sg)" },
+ { 0x64, "Serbo-Croatian (sh)" },
+ { 0x65, "Sinhalese (si)" },
+ { 0x66, "Slovak (sk)" },
+ { 0x67, "Slovenian (sl)" },
+ { 0x68, "Samoan (sm)" },
+ { 0x69, "Shona (sn)" },
+ { 0x6A, "Somali (so)" },
+ { 0x6B, "Albanian (sq)" },
+ { 0x6C, "Serbian (sr)" },
+ { 0x6D, "Siswati (ss)" },
+ { 0x6E, "Sesotho (st)" },
+ { 0x6F, "Sundanese (su)" },
+ { 0x70, "Swedish (sv)" },
+ { 0x71, "Swahili (sw)" },
+ { 0x72, "Tamil (ta)" },
+ { 0x73, "Telugu (te)" },
+ { 0x74, "Tajik (tg)" },
+ { 0x75, "Thai (th)" },
+ { 0x76, "Tigrinya (ti)" },
+ { 0x77, "Turkmen (tk)" },
+ { 0x78, "Tagalog (tl)" },
+ { 0x79, "Setswana (tn)" },
+ { 0x7A, "Tonga (to)" },
+ { 0x7B, "Turkish (tr)" },
+ { 0x7C, "Tsonga (ts)" },
+ { 0x7D, "Tatar (tt)" },
+ { 0x7E, "Twi (tw)" },
+ { 0x7F, "Uighur (ug)" },
+ { 0x81, "Nauru (na)" },
+ { 0x82, "Faeroese (fo)" },
+ { 0x83, "Frisian (fy)" },
+ { 0x84, "Interlingua (ia)" },
+ { 0x85, "Volapuk (vo)" },
+ { 0x86, "Interlingue (ie)" },
+ { 0x87, "Inupiak (ik)" },
+ { 0x88, "Yiddish (formerly ji) (yi)" },
+ { 0x89, "Inuktitut (iu)" },
+ { 0x8A, "Greenlandic (kl)" },
+ { 0x8B, "Latin (la)" },
+ { 0x8C, "Rhaeto-Romance (rm)" },
+ { 0x00, NULL }
+};
+
+
+#define CACHE_CONTROL_NO_CACHE 0x00
+#define CACHE_CONTROL_NO_STORE 0x01
+#define CACHE_CONTROL_MAX_AGE 0x02
+#define CACHE_CONTROL_MAX_STALE 0x03
+#define CACHE_CONTROL_MIN_FRESH 0x04
+#define CACHE_CONTROL_ONLY_IF_CACHED 0x05
+#define CACHE_CONTROL_PUBLIC 0x06
+#define CACHE_CONTROL_PRIVATE 0x07
+#define CACHE_CONTROL_NO_TRANSFORM 0x08
+#define CACHE_CONTROL_MUST_REVALIDATE 0x09
+#define CACHE_CONTROL_PROXY_REVALIDATE 0x0A
+#define CACHE_CONTROL_S_MAXAGE 0x0B
+
+static const value_string vals_cache_control[] = {
+ { CACHE_CONTROL_NO_CACHE, "no-cache" },
+ { CACHE_CONTROL_NO_STORE, "no-store" },
+ { CACHE_CONTROL_MAX_AGE, "max-age" },
+ { CACHE_CONTROL_MAX_STALE, "max-stale" },
+ { CACHE_CONTROL_MIN_FRESH, "min-fresh" },
+ { CACHE_CONTROL_ONLY_IF_CACHED, "only-if-cached" },
+ { CACHE_CONTROL_PUBLIC, "public" },
+ { CACHE_CONTROL_PRIVATE, "private" },
+ { CACHE_CONTROL_NO_TRANSFORM, "no-transform" },
+ { CACHE_CONTROL_MUST_REVALIDATE, "must-revalidate" },
+ { CACHE_CONTROL_PROXY_REVALIDATE, "proxy-revalidate" },
+ { CACHE_CONTROL_S_MAXAGE, "s-max-age" },
+
+ { 0x00, NULL }
+};
+
+static const value_string vals_wap_application_ids[] = {
+ /* Well-known WAP applications */
+ { 0x00, "x-wap-application:*"},
+ { 0x01, "x-wap-application:push.sia"},
+ { 0x02, "x-wap-application:wml.ua"},
+ { 0x03, "x-wap-application:wta.ua"},
+ { 0x04, "x-wap-application:mms.ua"},
+ { 0x05, "x-wap-application:push.syncml"},
+ { 0x06, "x-wap-application:loc.ua"},
+ { 0x07, "x-wap-application:syncml.dm"},
+ { 0x08, "x-wap-application:drm.ua"},
+ { 0x09, "x-wap-application:emn.ua"},
+ { 0x0A, "x-wap-application:wv.ua"},
+ /* Registered by 3rd parties */
+ { 0x8000, "x-wap-microsoft:localcontent.ua"},
+ { 0x8001, "x-wap-microsoft:IMclient.ua"},
+ { 0x8002, "x-wap-docomo:imode.mail.ua"},
+ { 0x8003, "x-wap-docomo:imode.mr.ua"},
+ { 0x8004, "x-wap-docomo:imode.mf.ua"},
+ { 0x8005, "x-motorola:location.ua"},
+ { 0x8006, "x-motorola:now.ua"},
+ { 0x8007, "x-motorola:otaprov.ua"},
+ { 0x8008, "x-motorola:browser.ua"},
+ { 0x8009, "x-motorola:splash.ua"},
+ /* 0x800A: unassigned */
+ { 0x800B, "x-wap-nai:mvsw.command"},
+ /* 0x800C -- 0x800F: unassigned */
+ { 0x8010, "x-wap-openwave:iota.ua"},
+ /* 0x8011 -- 0x8FFF: unassigned */
+ { 0x9000, "x-wap-docomo:imode.mail2.ua"},
+ { 0x9001, "x-oma-nec:otaprov.ua"},
+ { 0x9002, "x-oma-nokia:call.ua"},
+ { 0x9003, "x-oma-coremobility:sqa.ua"},
+
+ { 0x00, NULL }
+};
+
+
+/* Parameters and well-known encodings */
+static const value_string vals_wsp_parameter_sec[] = {
+ { 0x00, "NETWPIN" },
+ { 0x01, "USERPIN" },
+ { 0x02, "USERNETWPIN" },
+ { 0x03, "USERPINMAC" },
+
+ { 0x00, NULL }
+};
+
+/* Warning codes and mappings */
+static const value_string vals_wsp_warning_code[] = {
+ { 10, "110 Response is stale" },
+ { 11, "111 Revalidation failed" },
+ { 12, "112 Disconnected operation" },
+ { 13, "113 Heuristic expiration" },
+ { 14, "214 Transformation applied" },
+ { 99, "199/299 Miscellaneous warning" },
+
+ { 0, NULL }
+};
+
+static const value_string vals_wsp_warning_code_short[] = {
+ { 10, "110" },
+ { 11, "111" },
+ { 12, "112" },
+ { 13, "113" },
+ { 14, "214" },
+ { 99, "199/299" },
+
+ { 0, NULL }
+};
+
+/* Profile-Warning codes - see http://www.w3.org/TR/NOTE-CCPPexchange */
+static const value_string vals_wsp_profile_warning_code[] = {
+ { 0x10, "100 OK" },
+ { 0x11, "101 Used stale profile" },
+ { 0x12, "102 Not used profile" },
+ { 0x20, "200 Not applied" },
+ { 0x21, "101 Content selection applied" },
+ { 0x22, "202 Content generation applied" },
+ { 0x23, "203 Transformation applied" },
+
+ { 0x00, NULL }
+};
+
+/* Well-known TE values */
+static const value_string vals_well_known_te[] = {
+ { 0x82, "chunked" },
+ { 0x83, "identity" },
+ { 0x84, "gzip" },
+ { 0x85, "compress" },
+ { 0x86, "deflate" },
+
+ { 0x00, NULL }
+};
+
+
+/*
+ * Redirect flags.
+ */
+#define PERMANENT_REDIRECT 0x80
+#define REUSE_SECURITY_SESSION 0x40
+
+/*
+ * Redirect address flags and length.
+ */
+#define BEARER_TYPE_INCLUDED 0x80
+#define PORT_NUMBER_INCLUDED 0x40
+#define ADDRESS_LEN 0x3f
+
+static const true_false_string yes_no_truth = {
+ "Yes" ,
+ "No"
+};
+
+static const value_string vals_false_true[] = {
+ { 0, "False" },
+ { 1, "True" },
+ { 0, NULL },
+};
+
+enum {
+ WSP_PDU_RESERVED = 0x00,
+ WSP_PDU_CONNECT = 0x01,
+ WSP_PDU_CONNECTREPLY = 0x02,
+ WSP_PDU_REDIRECT = 0x03, /* No sample data */
+ WSP_PDU_REPLY = 0x04,
+ WSP_PDU_DISCONNECT = 0x05,
+ WSP_PDU_PUSH = 0x06, /* No sample data */
+ WSP_PDU_CONFIRMEDPUSH = 0x07, /* No sample data */
+ WSP_PDU_SUSPEND = 0x08, /* No sample data */
+ WSP_PDU_RESUME = 0x09, /* No sample data */
+
+ WSP_PDU_GET = 0x40,
+ WSP_PDU_OPTIONS = 0x41, /* No sample data */
+ WSP_PDU_HEAD = 0x42, /* No sample data */
+ WSP_PDU_DELETE = 0x43, /* No sample data */
+ WSP_PDU_TRACE = 0x44, /* No sample data */
+
+ WSP_PDU_POST = 0x60,
+ WSP_PDU_PUT = 0x61 /* No sample data */
+};
+
+
+/* Dissector tables for handoff */
+static dissector_table_t media_type_table;
+static heur_dissector_list_t heur_subdissector_list;
+
+static void add_uri (proto_tree *, packet_info *, tvbuff_t *, guint, guint, proto_item *);
+
+static void add_post_variable (proto_tree *, tvbuff_t *, guint, guint, guint, guint);
+static void add_multipart_data (proto_tree *, tvbuff_t *, packet_info *pinfo);
+
+static void add_capabilities (proto_tree *tree, tvbuff_t *tvb, guint8 pdu_type);
+
+
+/*
+ * Dissect the WSP header part.
+ * This function calls wkh_XXX functions that dissect well-known headers.
+ */
+static void add_headers (proto_tree *tree, tvbuff_t *tvb, int hf, packet_info *pinfo);
+
+/* The following macros define WSP basic data structures as found
+ * in the ABNF notation of WSP headers.
+ * Currently all text data types are mapped to text_string.
+ */
+#define is_short_integer(x) ( (x) & 0x80 )
+#define is_long_integer(x) ( (x) <= 30 )
+#define is_date_value(x) is_long_integer(x)
+#define is_integer_value(x) (is_short_integer(x) || is_long_integer(x))
+#define is_delta_seconds_value(x) is_integer_value(x)
+/* Text string == *TEXT 0x00, thus also an empty string matches the rule! */
+#define is_text_string(x) ( ((x) == 0) || ( ((x) >= 32) && ((x) <= 127)) )
+#define is_quoted_string(x) ( (x) == 0x22 ) /* " */
+#define is_token_text(x) is_text_string(x)
+#define is_text_value(x) is_text_string(x)
+#define is_uri_value(x) is_text_string(x)
+
+#define get_uintvar_integer(val,tvb,start,len,ok) \
+ val = tvb_get_guintvar(tvb,start,&len); \
+ if (len>5) ok = FALSE; else ok = TRUE;
+#define get_short_integer(val,tvb,start,len,ok) \
+ val = tvb_get_guint8(tvb,start); \
+ if (val & 0x80) ok = TRUE; else ok=FALSE; \
+ val &= 0x7F; len = 1;
+#define get_long_integer(val,tvb,start,len,ok) \
+ len = tvb_get_guint8(tvb,start); \
+ ok = TRUE; /* Valid lengths for us are 1-4 */ \
+ if (len==1) { val = tvb_get_guint8(tvb,start+1); } \
+ else if (len==2) { val = tvb_get_ntohs(tvb,start+1); } \
+ else if (len==3) { val = tvb_get_ntoh24(tvb,start+1); } \
+ else if (len==4) { val = tvb_get_ntohl(tvb,start+1); } \
+ else ok = FALSE; \
+ len++; /* Add the 1st octet to the length */
+#define get_integer_value(val,tvb,start,len,ok) \
+ len = tvb_get_guint8(tvb,start); \
+ ok = TRUE; \
+ if (len & 0x80) { val = len & 0x7F; len = 0; } \
+ else if (len==1) { val = tvb_get_guint8(tvb,start+1); } \
+ else if (len==2) { val = tvb_get_ntohs(tvb,start+1); } \
+ else if (len==3) { val = tvb_get_ntoh24(tvb,start+1); } \
+ else if (len==4) { val = tvb_get_ntohl(tvb,start+1); } \
+ else ok = FALSE; \
+ len++; /* Add the 1st octet to the length */
+#define get_date_value(val,tvb,start,len,ok) \
+ get_long_integer(val,tvb,start,len,ok)
+#define get_delta_seconds_value(val,tvb,start,len,ok) \
+ get_integer_value(val,tvb,start,len,ok)
+
+/* NOTE - Don't forget to g_free() the str value after its usage as the
+ * tvb_get_string[z]() functions return g_malloc()ed memory! */
+#define get_text_string(str,tvb,start,len,ok) \
+ if (is_text_string(tvb_get_guint8(tvb,start))) { \
+ str = (gchar *)tvb_get_stringz(tvb,start,(gint *)&len); \
+ g_assert (str); \
+ ok = TRUE; \
+ } else { len = 0; str = NULL; ok = FALSE; }
+#define get_token_text(str,tvb,start,len,ok) \
+ get_text_string(str,tvb,start,len,ok)
+#define get_extension_media(str,tvb,start,len,ok) \
+ get_text_string(str,tvb,start,len,ok)
+#define get_text_value(str,tvb,start,len,ok) \
+ get_text_string(str,tvb,start,len,ok)
+#define get_quoted_string(str,tvb,start,len,ok) \
+ get_text_string(str,tvb,start,len,ok)
+#define get_uri_value(str,tvb,start,len,ok) \
+ get_text_string(str,tvb,start,len,ok)
+
+#define get_version_value(val,str,tvb,start,len,ok) \
+ val = tvb_get_guint8(tvb,start); \
+ ok = TRUE; \
+ if (val & 0x80) { /* High nibble "." Low nibble */ \
+ len = 1; \
+ val &= 0x7F; \
+ str = g_strdup_printf("%u.%u", val >> 4, val & 0x0F); \
+ } else { get_text_string(str,tvb,start,len,ok); }
+
+/* Parameter parser */
+static int
+parameter (proto_tree *tree, proto_item *ti, tvbuff_t *tvb, int start, int len);
+static int
+parameter_value_q (proto_tree *tree, proto_item *ti, tvbuff_t *tvb, int start);
+
+#define InvalidValueForHeader(hdr) \
+ "<Error: Invalid value for the '" hdr "' header>"
+#define InvalidTextualHeader \
+ "<Error: Invalid zero-length textual header>"
+#define TrailingQuoteWarning \
+ " <Warning: Quoted-string value has been encoded with a trailing quote>"
+
+/* WSP well-known header parsing function prototypes;
+ * will be listed in the function lookup table WellKnownHeaders[] */
+static guint32 wkh_default (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_accept (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_content_type (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_accept_charset (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_accept_language (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_connection (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_push_flag (proto_tree *tree, tvbuff_t *tvb,
+ guint32 header_start, packet_info *pinfo _U_);
+static guint32 wkh_vary (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_accept_ranges (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_content_disposition (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_accept_encoding (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_content_encoding (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_transfer_encoding (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_pragma (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Single short-integer value */
+static guint32 wkh_x_wap_security (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Text */
+static guint32 wkh_content_base (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_content_location (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_etag (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_from (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_host (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_if_match (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_if_none_match (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_location (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_referer (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_server (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_user_agent (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_upgrade (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_via (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_content_uri (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_initiator_uri (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_profile (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_content_id (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Date-value or text */
+static guint32 wkh_if_range (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Date-value */
+static guint32 wkh_date (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_expires (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_if_modified_since (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_if_unmodified_since (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_last_modified (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Date-value with special meaning */
+static guint32 wkh_x_wap_tod (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Delta-seconds-value */
+static guint32 wkh_age (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Challenge */
+static guint32 wkh_proxy_authenticate (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_www_authenticate (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Credentials */
+static guint32 wkh_authorization (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_proxy_authorization (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Pragma */
+static guint32 wkh_pragma (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Integer-value */
+static guint32 wkh_content_length (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_max_forwards (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+
+/* Integer lookup value */
+static guint32 wkh_bearer_indication (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+
+/* WAP application ID value */
+static guint32 wkh_x_wap_application_id (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_accept_application (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_content_language (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+
+/* Allow and Public */
+static guint32 wkh_allow(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_public(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+
+/* Cache-control */
+static guint32 wkh_cache_control (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Warning */
+static guint32 wkh_warning (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Profile-warning */
+static guint32 wkh_profile_warning (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+
+/* Content-MD5 */
+static guint32 wkh_content_md5 (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+
+/* WSP encoding version */
+static guint32 wkh_encoding_version (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+
+/* Content-Range and Range */
+static guint32 wkh_content_range (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_range (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+
+/* TE */
+static guint32 wkh_te (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+
+/* Header value */
+static guint32 wkh_trailer (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+
+/* Profile-Diff with WBXML UAPROF document */
+static guint32 wkh_profile_diff_wbxml (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo);
+
+/* TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
+static guint32 wkh_retry_after (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_expect (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_set_cookie (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_cookie (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+*/
+
+
+/* WSP well-known Openwave header parsing function prototypes;
+ * will be listed in the function lookup table WellKnownOpenwaveHeaders[] */
+static guint32 wkh_openwave_default (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_);
+/* Textual headers */
+static guint32 wkh_openwave_x_up_proxy_operator_domain(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_home_page(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_uplink_version(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_ba_realm(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_request_uri(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_bookmark(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+/* Integer headers */
+static guint32 wkh_openwave_x_up_proxy_push_seq(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_notify(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_net_ask(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_tod (proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_ba_enable(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_redirect_enable(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_redirect_status(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_linger(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_enable_trust(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_trust(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_devcap_has_color(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_devcap_num_softkeys(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_devcap_softkey_size(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_devcap_screen_chars(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_devcap_screen_pixels(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_devcap_em_size(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_devcap_screen_depth(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_devcap_immed_alert(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_devcap_gui(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+
+static guint32 wkh_openwave_x_up_proxy_trans_charset(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+static guint32 wkh_openwave_x_up_proxy_push_accept(proto_tree *tree,
+ tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_);
+
+
+/* Define a pointer to function data type for the well-known header
+ * lookup table below */
+typedef guint32 (*hdr_parse_func_ptr) (proto_tree *, tvbuff_t *, guint32, packet_info *);
+
+/* Lookup table for well-known header parsing functions */
+static const hdr_parse_func_ptr WellKnownHeader[128] = {
+ /* 0x00 */ wkh_accept, /* 0x01 */ wkh_accept_charset,
+ /* 0x02 */ wkh_accept_encoding, /* 0x03 */ wkh_accept_language,
+ /* 0x04 */ wkh_accept_ranges, /* 0x05 */ wkh_age,
+ /* 0x06 */ wkh_allow, /* 0x07 */ wkh_authorization,
+ /* 0x08 */ wkh_cache_control, /* 0x09 */ wkh_connection,
+ /* 0x0A */ wkh_content_base, /* 0x0B */ wkh_content_encoding,
+ /* 0x0C */ wkh_content_language, /* 0x0D */ wkh_content_length,
+ /* 0x0E */ wkh_content_location, /* 0x0F */ wkh_content_md5,
+ /* 0x10 */ wkh_content_range, /* 0x11 */ wkh_content_type,
+ /* 0x12 */ wkh_date, /* 0x13 */ wkh_etag,
+ /* 0x14 */ wkh_expires, /* 0x15 */ wkh_from,
+ /* 0x16 */ wkh_host, /* 0x17 */ wkh_if_modified_since,
+ /* 0x18 */ wkh_if_match, /* 0x19 */ wkh_if_none_match,
+ /* 0x1A */ wkh_if_range, /* 0x1B */ wkh_if_unmodified_since,
+ /* 0x1C */ wkh_location, /* 0x1D */ wkh_last_modified,
+ /* 0x1E */ wkh_max_forwards, /* 0x1F */ wkh_pragma,
+ /* 0x20 */ wkh_proxy_authenticate, /* 0x21 */ wkh_proxy_authorization,
+ /* 0x22 */ wkh_public, /* 0x23 */ wkh_range,
+ /* 0x24 */ wkh_referer, /* 0x25 */ wkh_default,
+ /* 0x26 */ wkh_server, /* 0x27 */ wkh_transfer_encoding,
+ /* 0x28 */ wkh_upgrade, /* 0x29 */ wkh_user_agent,
+ /* 0x2A */ wkh_vary, /* 0x2B */ wkh_via,
+ /* 0x2C */ wkh_warning, /* 0x2D */ wkh_www_authenticate,
+ /* 0x2E */ wkh_content_disposition,/* 0x2F */ wkh_x_wap_application_id,
+ /* 0x30 */ wkh_content_uri, /* 0x31 */ wkh_initiator_uri,
+ /* 0x32 */ wkh_accept_application, /* 0x33 */ wkh_bearer_indication,
+ /* 0x34 */ wkh_push_flag, /* 0x35 */ wkh_profile,
+ /* 0x36 */ wkh_profile_diff_wbxml, /* 0x37 */ wkh_profile_warning,
+ /* 0x38 */ wkh_default, /* 0x39 */ wkh_te,
+ /* 0x3A */ wkh_trailer, /* 0x3B */ wkh_accept_charset,
+ /* 0x3C */ wkh_accept_encoding, /* 0x3D */ wkh_cache_control,
+ /* 0x3E */ wkh_content_range, /* 0x3F */ wkh_x_wap_tod,
+ /* 0x40 */ wkh_content_id, /* 0x41 */ wkh_default,
+ /* 0x42 */ wkh_default, /* 0x43 */ wkh_encoding_version,
+ /* 0x44 */ wkh_profile_warning, /* 0x45 */ wkh_content_disposition,
+ /* 0x46 */ wkh_x_wap_security, /* 0x47 */ wkh_cache_control,
+ /*******************************************************
+ *** The following headers are not (yet) registered. ***
+ *******************************************************/
+ /* 0x48 */ wkh_default, /* 0x49 */ wkh_default,
+ /* 0x4A */ wkh_default, /* 0x4B */ wkh_default,
+ /* 0x4C */ wkh_default, /* 0x4D */ wkh_default,
+ /* 0x4E */ wkh_default, /* 0x4F */ wkh_default,
+ /* 0x50 */ wkh_default, /* 0x51 */ wkh_default,
+ /* 0x52 */ wkh_default, /* 0x53 */ wkh_default,
+ /* 0x54 */ wkh_default, /* 0x55 */ wkh_default,
+ /* 0x56 */ wkh_default, /* 0x57 */ wkh_default,
+ /* 0x58 */ wkh_default, /* 0x59 */ wkh_default,
+ /* 0x5A */ wkh_default, /* 0x5B */ wkh_default,
+ /* 0x5C */ wkh_default, /* 0x5D */ wkh_default,
+ /* 0x5E */ wkh_default, /* 0x5F */ wkh_default,
+ /* 0x60 */ wkh_default, /* 0x61 */ wkh_default,
+ /* 0x62 */ wkh_default, /* 0x63 */ wkh_default,
+ /* 0x64 */ wkh_default, /* 0x65 */ wkh_default,
+ /* 0x66 */ wkh_default, /* 0x67 */ wkh_default,
+ /* 0x68 */ wkh_default, /* 0x69 */ wkh_default,
+ /* 0x6A */ wkh_default, /* 0x6B */ wkh_default,
+ /* 0x6C */ wkh_default, /* 0x6D */ wkh_default,
+ /* 0x6E */ wkh_default, /* 0x6F */ wkh_default,
+ /* 0x70 */ wkh_default, /* 0x71 */ wkh_default,
+ /* 0x72 */ wkh_default, /* 0x73 */ wkh_default,
+ /* 0x74 */ wkh_default, /* 0x75 */ wkh_default,
+ /* 0x76 */ wkh_default, /* 0x77 */ wkh_default,
+ /* 0x78 */ wkh_default, /* 0x79 */ wkh_default,
+ /* 0x7A */ wkh_default, /* 0x7B */ wkh_default,
+ /* 0x7C */ wkh_default, /* 0x7D */ wkh_default,
+ /* 0x7E */ wkh_default, /* 0x7F */ wkh_default,
+};
+
+/* Lookup table for well-known header parsing functions */
+static const hdr_parse_func_ptr WellKnownOpenwaveHeader[128] = {
+ /* 0x00 */ wkh_openwave_default,
+ /* 0x01 */ wkh_openwave_x_up_proxy_push_accept,
+ /* 0x02 */ wkh_openwave_x_up_proxy_push_seq,
+ /* 0x03 */ wkh_openwave_x_up_proxy_notify,
+ /* 0x04 */ wkh_openwave_x_up_proxy_operator_domain,
+ /* 0x05 */ wkh_openwave_x_up_proxy_home_page,
+ /* 0x06 */ wkh_openwave_x_up_devcap_has_color,
+ /* 0x07 */ wkh_openwave_x_up_devcap_num_softkeys,
+ /* 0x08 */ wkh_openwave_x_up_devcap_softkey_size,
+ /* 0x09 */ wkh_openwave_x_up_devcap_screen_chars,
+ /* 0x0A */ wkh_openwave_x_up_devcap_screen_pixels,
+ /* 0x0B */ wkh_openwave_x_up_devcap_em_size,
+ /* 0x0C */ wkh_openwave_x_up_devcap_screen_depth,
+ /* 0x0D */ wkh_openwave_x_up_devcap_immed_alert,
+ /* 0x0E */ wkh_openwave_x_up_proxy_net_ask,
+ /* 0x0F */ wkh_openwave_x_up_proxy_uplink_version,
+ /* 0x10 */ wkh_openwave_x_up_proxy_tod,
+ /* 0x11 */ wkh_openwave_x_up_proxy_ba_enable,
+ /* 0x12 */ wkh_openwave_x_up_proxy_ba_realm,
+ /* 0x13 */ wkh_openwave_x_up_proxy_redirect_enable,
+ /* 0x14 */ wkh_openwave_x_up_proxy_request_uri,
+ /* 0x15 */ wkh_openwave_x_up_proxy_redirect_status,
+ /* 0x16 */ wkh_openwave_x_up_proxy_trans_charset,
+ /* 0x17 */ wkh_openwave_x_up_proxy_linger,
+ /* 0x18 */ wkh_openwave_default,
+ /* 0x19 */ wkh_openwave_x_up_proxy_enable_trust,
+ /* 0x1A */ wkh_openwave_x_up_proxy_trust,
+ /* 0x1B */ wkh_openwave_default,
+ /* 0x1C */ wkh_openwave_default,
+ /* 0x1D */ wkh_openwave_default,
+ /* 0x1E */ wkh_openwave_default,
+ /* 0x1F */ wkh_openwave_default,
+ /* 0x20 */ wkh_openwave_x_up_proxy_trust,
+ /* 0x21 */ wkh_openwave_x_up_proxy_bookmark,
+ /* 0x22 */ wkh_openwave_x_up_devcap_gui,
+ /*******************************************************
+ *** The following headers are not (yet) registered. ***
+ *******************************************************/
+ /* 0x23 */ wkh_openwave_default,
+ /* 0x24 */ wkh_openwave_default, /* 0x25 */ wkh_openwave_default,
+ /* 0x26 */ wkh_openwave_default, /* 0x27 */ wkh_openwave_default,
+ /* 0x28 */ wkh_openwave_default, /* 0x29 */ wkh_openwave_default,
+ /* 0x2A */ wkh_openwave_default, /* 0x2B */ wkh_openwave_default,
+ /* 0x2C */ wkh_openwave_default, /* 0x2D */ wkh_openwave_default,
+ /* 0x2E */ wkh_openwave_default, /* 0x2F */ wkh_openwave_default,
+ /* 0x30 */ wkh_openwave_default, /* 0x31 */ wkh_openwave_default,
+ /* 0x32 */ wkh_openwave_default, /* 0x33 */ wkh_openwave_default,
+ /* 0x34 */ wkh_openwave_default, /* 0x35 */ wkh_openwave_default,
+ /* 0x36 */ wkh_openwave_default, /* 0x37 */ wkh_openwave_default,
+ /* 0x38 */ wkh_openwave_default, /* 0x39 */ wkh_openwave_default,
+ /* 0x3A */ wkh_openwave_default, /* 0x3B */ wkh_openwave_default,
+ /* 0x3C */ wkh_openwave_default, /* 0x3D */ wkh_openwave_default,
+ /* 0x3E */ wkh_openwave_default, /* 0x3F */ wkh_openwave_default,
+ /* 0x40 */ wkh_openwave_default, /* 0x41 */ wkh_openwave_default,
+ /* 0x42 */ wkh_openwave_default, /* 0x43 */ wkh_openwave_default,
+ /* 0x44 */ wkh_openwave_default, /* 0x45 */ wkh_openwave_default,
+ /* 0x46 */ wkh_openwave_default, /* 0x47 */ wkh_openwave_default,
+ /* 0x48 */ wkh_openwave_default, /* 0x49 */ wkh_openwave_default,
+ /* 0x4A */ wkh_openwave_default, /* 0x4B */ wkh_openwave_default,
+ /* 0x4C */ wkh_openwave_default, /* 0x4D */ wkh_openwave_default,
+ /* 0x4E */ wkh_openwave_default, /* 0x4F */ wkh_openwave_default,
+ /* 0x50 */ wkh_openwave_default, /* 0x51 */ wkh_openwave_default,
+ /* 0x52 */ wkh_openwave_default, /* 0x53 */ wkh_openwave_default,
+ /* 0x54 */ wkh_openwave_default, /* 0x55 */ wkh_openwave_default,
+ /* 0x56 */ wkh_openwave_default, /* 0x57 */ wkh_openwave_default,
+ /* 0x58 */ wkh_openwave_default, /* 0x59 */ wkh_openwave_default,
+ /* 0x5A */ wkh_openwave_default, /* 0x5B */ wkh_openwave_default,
+ /* 0x5C */ wkh_openwave_default, /* 0x5D */ wkh_openwave_default,
+ /* 0x5E */ wkh_openwave_default, /* 0x5F */ wkh_openwave_default,
+ /* 0x60 */ wkh_openwave_default, /* 0x61 */ wkh_openwave_default,
+ /* 0x62 */ wkh_openwave_default, /* 0x63 */ wkh_openwave_default,
+ /* 0x64 */ wkh_openwave_default, /* 0x65 */ wkh_openwave_default,
+ /* 0x66 */ wkh_openwave_default, /* 0x67 */ wkh_openwave_default,
+ /* 0x68 */ wkh_openwave_default, /* 0x69 */ wkh_openwave_default,
+ /* 0x6A */ wkh_openwave_default, /* 0x6B */ wkh_openwave_default,
+ /* 0x6C */ wkh_openwave_default, /* 0x6D */ wkh_openwave_default,
+ /* 0x6E */ wkh_openwave_default, /* 0x6F */ wkh_openwave_default,
+ /* 0x70 */ wkh_openwave_default, /* 0x71 */ wkh_openwave_default,
+ /* 0x72 */ wkh_openwave_default, /* 0x73 */ wkh_openwave_default,
+ /* 0x74 */ wkh_openwave_default, /* 0x75 */ wkh_openwave_default,
+ /* 0x76 */ wkh_openwave_default, /* 0x77 */ wkh_openwave_default,
+ /* 0x78 */ wkh_openwave_default, /* 0x79 */ wkh_openwave_default,
+ /* 0x7A */ wkh_openwave_default, /* 0x7B */ wkh_openwave_default,
+ /* 0x7C */ wkh_openwave_default, /* 0x7D */ wkh_openwave_default,
+ /* 0x7E */ wkh_openwave_default, /* 0x7F */ wkh_openwave_default,
+};
+
+
+
+
+
+
+/* WSP header format
+ * 1st byte: 0x00 : <Not allowed>
+ * 1st byte: 0x01 -- 0x1F: <Shorthand Header Code Page switch>
+ * 1st byte: 0x20 -- 0x7E: <Textual header (C string)>
+ * Followed with: <Textual header value (C string)>
+ * 1st byte: 0x7F : <Header Code Page switch>
+ * Followed with: 2nd byte: <Header Code Page>
+ * 1st byte: 0x80 -- 0xFF: <Binary header (7-bit encoded ID)>
+ * Followed with:
+ * 2nd byte: 0x00 -- 0x1E: <Value Length (bytes)>
+ * Followed with: <Len> bytes of data
+ * 2nd byte: 0x1F : <Value Length is a guintvar>
+ * Followed with: <guintvar Len>
+ * Followed with: <Len> bytes of data
+ * 2nd byte: 0x20 -- 0x7F: <Textual header value (C string)>
+ * 2nd byte: 0x80 -- 0xFF: <Binary value (7-bit encoded ID)>
+ */
+static void
+add_headers (proto_tree *tree, tvbuff_t *tvb, int hf, packet_info *pinfo)
+{
+ guint8 hdr_id, val_id, codepage = 1;
+ gint32 tvb_len = tvb_length(tvb);
+ gint32 offset = 0, hdr_len, hdr_start;
+ gint32 val_len, val_start;
+ gchar *hdr_str, *val_str;
+ proto_tree *wsp_headers;
+ proto_item *ti;
+ guint8 ok;
+ guint32 val = 0;
+ nstime_t tv;
+
+ if (! tree)
+ return;
+ if (offset >= tvb_len)
+ return; /* No headers! */
+
+ ti = proto_tree_add_item(tree, hf,
+ tvb, offset, tvb_len, bo_little_endian);
+ wsp_headers = proto_item_add_subtree(ti, ett_headers);
+
+ while (offset < tvb_len) {
+ hdr_start = offset;
+ hdr_id = tvb_get_guint8(tvb, offset);
+ if (hdr_id & 0x80) { /* Well-known header */
+ hdr_len = 1;
+ val_start = ++offset;
+ val_id = tvb_get_guint8(tvb, val_start);
+ /* Call header value dissector for given header */
+ if (codepage == 1) { /* Default header code page */
+ DebugLog(("add_headers(code page 0): %s\n",
+ match_strval (hdr_id & 0x7f, vals_field_names)));
+ offset = WellKnownHeader[hdr_id & 0x7F](wsp_headers, tvb,
+ hdr_start, pinfo);
+ } else { /* Openwave header code page */
+ /* Here I'm delibarately assuming that Openwave is the only
+ * company that defines a WSP header code page. */
+ DebugLog(("add_headers(code page 0x%02x - assumed to be x-up-1): %s\n",
+ codepage, match_strval (hdr_id & 0x7f, vals_openwave_field_names)));
+ offset = WellKnownOpenwaveHeader[hdr_id & 0x7F](wsp_headers,
+ tvb, hdr_start, pinfo);
+ }
+ } else if (hdr_id == 0x7F) { /* HCP shift sequence */
+ codepage = tvb_get_guint8(tvb, offset+1);
+ proto_tree_add_uint(wsp_headers, hf_wsp_header_shift_code,
+ tvb, offset, 2, codepage);
+ offset += 2;
+ } else if (hdr_id >= 0x20) { /* Textual header */
+ /* Header name MUST be NUL-ended string ==> tvb_get_stringz() */
+ hdr_str = (gchar *)tvb_get_stringz(tvb, hdr_start, (gint *)&hdr_len);
+ val_start = hdr_start + hdr_len;
+ val_id = tvb_get_guint8(tvb, val_start);
+ /* Call header value dissector for given header */
+ if (val_id >= 0x20 && val_id <=0x7E) { /* OK! */
+ val_str = (gchar *)tvb_get_stringz(tvb, val_start, (gint *)&val_len);
+ g_assert(val_str);
+ offset = val_start + val_len;
+ proto_tree_add_text(wsp_headers,tvb,hdr_start,offset-hdr_start,
+ "%s: %s", hdr_str, val_str);
+ g_free (val_str);
+ } else {
+ /* Old-style X-WAP-TOD uses a non-textual value
+ * after a textual header. */
+ if (strcasecmp(hdr_str, "x-wap.tod") == 0) {
+ get_delta_seconds_value(val, tvb, val_start, val_len, ok);
+ if (ok) {
+ if (val == 0) {
+ ti = proto_tree_add_string (wsp_headers,
+ hf_hdr_x_wap_tod,
+ tvb, hdr_start, hdr_len + val_len,
+ "Requesting Time Of Day");
+ } else {
+ tv.secs = val;
+ tv.nsecs = 0;
+ val_str = abs_time_to_str(&tv);
+ g_assert (val_str);
+ ti = proto_tree_add_string (wsp_headers,
+ hf_hdr_x_wap_tod,
+ tvb, hdr_start, hdr_len + val_len, val_str);
+ }
+ proto_item_append_text(ti, " <Warning: "
+ "should be encoded as a textual value>");
+ } else {
+ /* I prefer using X-Wap-Tod to the real hdr_str */
+ proto_tree_add_string (wsp_headers, hf_hdr_x_wap_tod,
+ tvb, hdr_start, hdr_len + val_len,
+ InvalidValueForHeader("X-Wap-Tod"));
+ }
+ } else {
+ proto_tree_add_text (wsp_headers, tvb, hdr_start, hdr_len,
+ "<Error: Invalid value for the textual '%s' header"
+ " (should be a textual value)>",
+ hdr_str);
+ }
+ offset = tvb_len;
+ }
+ proto_tree_add_string_hidden(wsp_headers, hf_hdr_name,
+ tvb, hdr_start, offset - hdr_start, hdr_str);
+ } else if (hdr_id > 0) { /* Shorthand HCP switch */
+ codepage = hdr_id;
+ proto_tree_add_uint (wsp_headers, hf_wsp_header_shift_code,
+ tvb, offset, 1, codepage);
+ offset++;
+ } else {
+ proto_tree_add_text (wsp_headers, tvb, hdr_start, 1,
+ InvalidTextualHeader);
+ offset = tvb_len;
+ }
+ }
+}
+
+
+/* The following macros hide common processing for all well-known headers
+ * and shortens the code to be written in a wkh_XXX() function.
+ * Even declarations are hidden by a macro.
+ *
+ * Define a wkh_XXX() function as follows:
+ *
+ * static guint32
+ * wkh_XXX (proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+ * {
+ * wkh_0_Declarations;
+ * << add other required declarations here >>
+ *
+ * wkh_1_WellKnownValue;
+ * << add well-known value proto item here; don't forget to set the
+ * ok variable to TRUE if parsing was correct >>
+ * wkh_2_TextualValue;
+ * << add textual value proto item here; don't forget to set the
+ * ok variable to TRUE if parsing was correct >>
+ * wkh_3_ValueWithLength;
+ * << add custom code for value processing and value proto item here >>
+ *
+ * wkh_4_End(hf);
+ * << This macro takes care of parse errors within the header value;
+ * it requires the header field index if the header has not yet been
+ * written to the protocol tree (ti == NULL). >>
+ * }
+ *
+ * NOTE: You only need to write parsing code for the successful case,
+ * Errors are automatically reported through the wkh_4_End() macro
+ * when ok <> TRUE.
+ */
+
+/* The following code is the generic template with which the value of a
+ * well-known header can be processed. Not all sections yield a semantically
+ * correct result, so appropriate error information must be provided.
+ */
+
+
+#define wkh_0_Declarations /* Declarations for Parsing */ \
+ gboolean ok = FALSE; /* Triggers error notification code at end */ \
+ proto_item *ti = NULL; /* Needed for error notification at end */ \
+ guint32 val_start = hdr_start + 1; \
+ guint8 hdr_id = tvb_get_guint8 (tvb, hdr_start) & 0x7F; \
+ guint8 val_id = tvb_get_guint8 (tvb, val_start); \
+ guint32 offset = val_start; /* Offset to one past this header */ \
+ guint32 val_len; /* length for value with length field */ \
+ guint32 val_len_len; /* length of length field */ \
+ gchar *val_str = NULL
+
+#define wkh_1_WellKnownValue /* Parse Well Known Value */ \
+ proto_tree_add_string_hidden(tree, hf_hdr_name, \
+ tvb, hdr_start, offset - hdr_start, \
+ val_to_str (hdr_id, vals_field_names, \
+ "<Unknown WSP header field 0x%02X>")); \
+ if (val_id & 0x80) { /* Well-known value */ \
+ offset++; \
+ /* Well-known value processing starts HERE \
+ * \
+ * BEGIN */
+
+#define wkh_2_TextualValue /* Parse Textual Value */ \
+ /* END */ \
+ } else if ((val_id == 0) || (val_id >= 0x20)) { /* Textual value */ \
+ val_str = (gchar *)tvb_get_stringz (tvb, val_start, (gint *)&val_len); \
+ g_assert(val_str); \
+ offset = val_start + val_len; \
+ /* Textual value processing starts HERE \
+ * \
+ * BEGIN */
+
+#define wkh_3_ValueWithLength /* Parse Value With Length */ \
+ /* END */ \
+ g_free(val_str); \
+ } else { /* val_start points to 1st byte of length field */ \
+ if (val_id == 0x1F) { /* Value Length = guintvar */ \
+ val_len = tvb_get_guintvar(tvb, val_start + 1, &val_len_len); \
+ val_len_len++; /* 0x1F length indicator byte */ \
+ } else { /* Short length followed by Len data octets */ \
+ val_len = tvb_get_guint8(tvb, offset); \
+ val_len_len = 1; \
+ } \
+ offset += val_len_len + val_len; \
+ /* Value with length processing starts HERE \
+ * The value lies between val_start and offset: \
+ * - Value Length: Start = val_start \
+ * Length = val_len_len \
+ * - Value Data : Start = val_start + val_len_len \
+ * Length = val_len \
+ * End = offset - 1 \
+ * BEGIN */
+
+#define wkh_4_End(hf) /* End of value parsing */ \
+ /* END */ \
+ } \
+ /* Check for errors */ \
+ if (! ok) { \
+ if (ti) { /* Append to protocol tree item label */ \
+ proto_item_append_text(ti, \
+ " <Error: Invalid header value>"); \
+ } else if (hf > 0) { /* Create protocol tree item */ \
+ proto_tree_add_string(tree, hf, \
+ tvb, hdr_start, offset - hdr_start, \
+ " <Error: Invalid header value>"); \
+ } else { /* Create anonymous header field entry */ \
+ proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start, \
+ "%s: <Error: Invalid header value>", \
+ val_to_str (hdr_id, vals_field_names, \
+ "<Unknown WSP header field 0x%02X>")); \
+ } \
+ } \
+ return offset;
+
+
+/*
+ * This yields the following default header value parser function body
+ */
+static guint32
+wkh_default(proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ ok = TRUE; /* Bypass error checking as we don't parse the values! */
+
+ wkh_1_WellKnownValue;
+ ti = proto_tree_add_text (tree, tvb, hdr_start, offset - hdr_start,
+ "%s: (Undecoded well-known value 0x%02x)",
+ val_to_str (hdr_id, vals_field_names,
+ "<Unknown WSP header field 0x%02X>"), val_id & 0x7F);
+ wkh_2_TextualValue;
+ ti = proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start,
+ "%s: %s",
+ val_to_str (hdr_id, vals_field_names,
+ "<Unknown WSP header field 0x%02X>"), val_str);
+ wkh_3_ValueWithLength;
+ ti = proto_tree_add_text (tree, tvb, hdr_start, offset - hdr_start,
+ "%s: (Undecoded value in general form with length indicator)",
+ val_to_str (hdr_id, vals_field_names,
+ "<Unknown WSP header field 0x%02X>"));
+
+ wkh_4_End(HF_EMPTY); /* The default parser has no associated hf_index;
+ additionally the error code is always bypassed */
+}
+
+
+/* Content-type processing uses the following common core: */
+#define wkh_content_type_header(underscored,Text) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint32 off, val = 0, len; \
+ guint8 peek; \
+ proto_tree *parameter_tree = NULL; \
+ \
+ wkh_1_WellKnownValue; \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ val_to_str(val_id & 0x7F, vals_content_types, \
+ "(Unknown content type identifier 0x%X)")); \
+ ok = TRUE; \
+ wkh_2_TextualValue; \
+ /* Sometimes with a No-Content response, a NULL content type \
+ * is reported. Process this correctly! */ \
+ if (*val_str) { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ val_str); \
+ } else { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ "<no content type has been specified>"); \
+ } \
+ ok = TRUE; \
+ wkh_3_ValueWithLength; \
+ off = val_start + val_len_len; \
+ peek = tvb_get_guint8(tvb, off); \
+ if (is_text_string(peek)) { \
+ get_extension_media(val_str, tvb, off, len, ok); \
+ /* As we're using val_str, it is automatically g_free()d */ \
+ off += len; /* off now points to 1st byte after string */ \
+ ti = proto_tree_add_string (tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, val_str); \
+ } else if (is_integer_value(peek)) { \
+ get_integer_value(val, tvb, off, len, ok); \
+ if (ok) { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ val_to_str(val, vals_content_types, \
+ "(Unknown content type identifier 0x%X)")); \
+ } \
+ off += len; \
+ } \
+ /* Remember: offset == val_start + val_len + val_len_len */ \
+ if (ok && (off < offset)) { /* Add parameters if any */ \
+ parameter_tree = proto_item_add_subtree (ti, ett_header); \
+ while (off < offset) { \
+ off = parameter (parameter_tree, ti, tvb, off, offset - off); \
+ } \
+ } \
+ \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+
+/*
+ * Accept-value =
+ * Short-integer
+ * | Extension-media
+ * | ( Value-length ( Extension-media | Integer-value ) *( Parameter ) )
+ */
+wkh_content_type_header(accept, "Accept")
+
+
+/*
+ * Content-type-value =
+ * Short-integer
+ * | Extension-media
+ * | ( Value-length ( Extension-media | Integer-value ) *( Parameter ) )
+ *
+ * Beware: this header should not appear as such; it is dissected elsewhere
+ * and at the same time the content type is used for subdissectors.
+ * It is here for the sake of completeness.
+ */
+wkh_content_type_header(content_type, "Content-Type")
+
+
+/*
+ * Content-type-value =
+ * Short-integer
+ * | Extension-media
+ * | ( Value-length ( Extension-media | Integer-value ) *( Parameter ) )
+ *
+ * This function adds the content type value to the protocol tree,
+ * and computes either the numeric or textual media type in return,
+ * which will be used for further subdissection (e.g., MMS, WBXML).
+ */
+guint32
+add_content_type(proto_tree *tree, tvbuff_t *tvb, guint32 val_start,
+ guint32 *well_known_content, const char **textual_content)
+{
+ /* Replace wkh_0_Declarations with slightly modified declarations
+ * so we can still make use of the wkh_[1-4]_XXX macros! */
+ guint32 hdr_start = val_start; /* No header name, only value! */
+ guint8 hdr_id = FN_CONTENT_TYPE; /* Same remark */
+ guint8 val_id = tvb_get_guint8 (tvb, val_start);
+ guint32 offset = val_start; /* Offset to one past this header */
+ guint32 val_len; /* length for value with length field */
+ guint32 val_len_len; /* length of length field */
+ gchar *val_str = NULL;
+ guint32 off, val = 0, len;
+ guint8 peek;
+ gboolean ok = FALSE;
+ proto_item *ti = NULL;
+ proto_tree *parameter_tree = NULL;
+
+ *textual_content = NULL;
+ *well_known_content = 0;
+
+ DebugLog(("add_content_type() - START\n"));
+
+ wkh_1_WellKnownValue;
+ DebugLog(("add_content_type() - Well-known - Start\n"));
+ *textual_content = val_to_str(val_id & 0x7F, vals_content_types,
+ "<Unknown media type identifier 0x%X>");
+ ti = proto_tree_add_string(tree, hf_hdr_content_type,
+ tvb, hdr_start, offset - hdr_start,
+ *textual_content);
+ *well_known_content = val_id & 0x7F;
+ ok = TRUE;
+ DebugLog(("add_content_type() - Well-known - End\n"));
+ wkh_2_TextualValue;
+ DebugLog(("add_content_type() - Textual - Start\n"));
+ /* Sometimes with a No-Content response, a NULL content type
+ * is reported. Process this correctly! */
+ if (*val_str) {
+ ti = proto_tree_add_string(tree, hf_hdr_content_type,
+ tvb, hdr_start, offset - hdr_start,
+ val_str);
+ /* As we're using val_str, it is automatically g_free()d */
+ *textual_content = g_strdup(val_str);
+ *well_known_content = 0;
+ } else {
+ ti = proto_tree_add_string(tree, hf_hdr_content_type,
+ tvb, hdr_start, offset - hdr_start,
+ "<no media type has been specified>");
+ *textual_content = NULL;
+ *well_known_content = 0;
+ }
+ ok = TRUE;
+ DebugLog(("add_content_type() - Textual - End\n"));
+ wkh_3_ValueWithLength;
+ DebugLog(("add_content_type() - General form - Start\n"));
+ off = val_start + val_len_len;
+ peek = tvb_get_guint8(tvb, off);
+ if (is_text_string(peek)) {
+ DebugLog(("add_content_type() - General form - extension-media\n"));
+ get_extension_media(val_str, tvb, off, len, ok);
+ /* As we're using val_str, it is automatically g_free()d */
+ /* ??? Not sure anymore, we're in wkh_3, not in wkh_2 ! */
+ off += len; /* off now points to 1st byte after string */
+ ti = proto_tree_add_string (tree, hf_hdr_content_type,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ /* Following statement: required? */
+ *textual_content = g_strdup(val_str);
+ *well_known_content = 0;
+ } else if (is_integer_value(peek)) {
+ DebugLog(("add_content_type() - General form - integer_value\n"));
+ get_integer_value(val, tvb, off, len, ok);
+ if (ok) {
+ *textual_content = val_to_str(val, vals_content_types,
+ "<Unknown media type identifier 0x%X>");
+ ti = proto_tree_add_string(tree, hf_hdr_content_type,
+ tvb, hdr_start, offset - hdr_start,
+ *textual_content);
+ *well_known_content = val;
+ }
+ off += len;
+ } /* else ok = FALSE */
+ /* Remember: offset == val_start + val_len_len + val_len */
+ if (ok && (off < offset)) { /* Add parameters if any */
+ DebugLog(("add_content_type() - General form - parameters\n"));
+ parameter_tree = proto_item_add_subtree (ti, ett_header);
+ while (off < offset) {
+ DebugLog(("add_content_type() - General form - parameter start "
+ "(off = %u)\n", off));
+ off = parameter (parameter_tree, ti, tvb, off, offset - off);
+ DebugLog(("add_content_type() - General form - parameter end "
+ "(off = %u)\n", off));
+ }
+ }
+ DebugLog(("add_content_type() - General form - End\n"));
+
+ wkh_4_End(hf_hdr_content_type);
+}
+
+
+/*
+ * Template for accept_X headers with optional Q parameter value
+ */
+#define wkh_accept_x_q_header(underscored,Text,valueString,valueName) \
+static guint32 \
+wkh_ ## underscored (proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint32 off, val = 0, len; \
+ guint8 peek; \
+ proto_tree *parameter_tree = NULL; \
+ \
+ wkh_1_WellKnownValue; \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ val_to_str(val_id & 0x7F, valueString, \
+ "<Unknown " valueName " identifier 0x%X>")); \
+ ok = TRUE; \
+ wkh_2_TextualValue; \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, val_str); \
+ ok = TRUE; \
+ wkh_3_ValueWithLength; \
+ off = val_start + val_len_len; \
+ peek = tvb_get_guint8(tvb, off); \
+ if (is_text_string(peek)) { \
+ get_token_text(val_str, tvb, off, len, ok); \
+ /* As we're using val_str, it is automatically g_free()d */ \
+ off += len; /* off now points to 1st byte after string */ \
+ ti = proto_tree_add_string (tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, val_str); \
+ } else if (is_integer_value(peek)) { \
+ get_integer_value(val, tvb, off, len, ok); \
+ if (ok) { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ val_to_str(val, valueString, \
+ "<Unknown " valueName " identifier 0x%X>")); \
+ } \
+ off += len; \
+ } /* else ok = FALSE */ \
+ /* Remember: offset == val_start + val_len */ \
+ if (ok && (off < offset)) { /* Add Q-value if available */ \
+ parameter_tree = proto_item_add_subtree (ti, ett_header); \
+ off = parameter_value_q (parameter_tree, ti, tvb, off); \
+ } \
+ \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+/*
+ * Accept-charset-value =
+ * Short-integer
+ * | Extension-media
+ * | ( Value-length ( Token-text | Integer-value ) [ Q-value ] )
+ */
+wkh_accept_x_q_header(accept_charset, "Accept-Charset",
+ vals_character_sets, "character set")
+/*
+ * Accept-language-value =
+ * Short-integer
+ * | Extension-media
+ * | ( Value-length ( Text-string | Integer-value ) [ Q-value ] )
+ */
+wkh_accept_x_q_header(accept_language, "Accept-Language",
+ vals_languages, "language")
+
+
+/*
+ * Push-flag-value = Short-integer
+ */
+static guint32
+wkh_push_flag(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ proto_tree *subtree = NULL;
+
+ wkh_1_WellKnownValue;
+ ti = proto_tree_add_string(tree, hf_hdr_push_flag,
+ tvb, hdr_start, offset - hdr_start, "");
+ subtree = proto_item_add_subtree(ti, ett_header);
+ proto_tree_add_uint(subtree, hf_hdr_push_flag_auth,
+ tvb, val_start, 1, val_id);
+ proto_tree_add_uint(subtree, hf_hdr_push_flag_trust,
+ tvb, val_start, 1, val_id);
+ proto_tree_add_uint(subtree, hf_hdr_push_flag_last,
+ tvb, val_start, 1, val_id);
+ if (val_id & 0x01)
+ proto_item_append_string(ti, " (Initiator URI authenticated)");
+ if (val_id & 0x02)
+ proto_item_append_string(ti, " (Content trusted)");
+ if (val_id & 0x04)
+ proto_item_append_string(ti, " (Last push message)");
+ if (val_id & 0x78)
+ proto_item_append_text(ti, " <Warning: Reserved flags set>");
+ else
+ ok = TRUE;
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ /* Invalid */
+ wkh_4_End(hf_hdr_push_flag);
+}
+
+
+/*
+ * Profile-Diff (with WBXML): Profile-diff-value =
+ * Value-length <WBXML-Content>
+ */
+static guint32 wkh_profile_diff_wbxml (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo)
+{
+ wkh_0_Declarations;
+ tvbuff_t *tmp_tvb;
+ proto_tree *subtree;
+
+ ok = TRUE; /* Bypass error checking as we don't parse the values! */
+
+ wkh_1_WellKnownValue;
+ /* Invalid */
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ ti = proto_tree_add_string(tree, hf_hdr_profile_diff, tvb, hdr_start, offset - hdr_start,
+ "(Profile-Diff value as WBXML)");
+ subtree = proto_item_add_subtree(ti, ett_header);
+ tmp_tvb = tvb_new_subset(tvb, val_start + val_len_len, val_len, val_len); /* TODO: fix 2nd length */
+ call_dissector(wbxml_uaprof_handle, tmp_tvb, pinfo, subtree);
+ ok = TRUE;
+ wkh_4_End(hf_hdr_profile_diff);
+}
+
+
+/*
+ * Allow-value =
+ * Short-integer
+ */
+static guint32
+wkh_allow(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ wkh_1_WellKnownValue;
+ val_id &= 0x7F;
+ if (val_id >= 0x40) { /* Valid WSP method */
+ ti = proto_tree_add_string(tree, hf_hdr_allow,
+ tvb, hdr_start, offset - hdr_start,
+ val_to_str(val_id & 0x7F, vals_pdu_type,
+ "<Unknown WSP method 0x%02X>"));
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ /* Invalid */
+ wkh_4_End(hf_hdr_allow);
+}
+
+
+/*
+ * Public-value =
+ * Token-text | Short-integer
+ */
+static guint32
+wkh_public(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ wkh_1_WellKnownValue;
+ val_id &= 0x7F;
+ if (val_id >= 0x40) { /* Valid WSP method */
+ ti = proto_tree_add_string(tree, hf_hdr_public,
+ tvb, hdr_start, offset - hdr_start,
+ val_to_str(val_id & 0x7F, vals_pdu_type,
+ "<Unknown WSP method 0x%02X>"));
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ ti = proto_tree_add_string(tree, hf_hdr_public,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ wkh_3_ValueWithLength;
+ /* Invalid */
+ wkh_4_End(hf_hdr_public);
+}
+
+
+/*
+ * Vary-value =
+ * Token-text | Short-integer
+ */
+static guint32
+wkh_vary(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ wkh_1_WellKnownValue;
+ ti = proto_tree_add_string(tree, hf_hdr_vary,
+ tvb, hdr_start, offset - hdr_start,
+ val_to_str(val_id & 0x7F, vals_field_names,
+ "<Unknown WSP header field 0x%02X>"));
+ ok = TRUE;
+ wkh_2_TextualValue;
+ ti = proto_tree_add_string(tree, hf_hdr_vary,
+ tvb, hdr_start, offset - hdr_start,
+ val_str);
+ ok = TRUE;
+ wkh_3_ValueWithLength;
+ /* Invalid */
+ wkh_4_End(hf_hdr_vary);
+}
+
+
+/*
+ * X-wap-security-value = 0x80
+ */
+static guint32
+wkh_x_wap_security(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ wkh_1_WellKnownValue;
+ if (val_id == 0x80) {
+ ti = proto_tree_add_string(tree, hf_hdr_x_wap_security,
+ tvb, hdr_start, offset - hdr_start, "close-subordinate");
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ /* Invalid */
+ wkh_4_End(hf_hdr_x_wap_security);
+}
+
+
+/*
+ * Connection-value = 0x80 | Token-text
+ */
+static guint32
+wkh_connection(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ wkh_1_WellKnownValue;
+ if (val_id == 0x80) {
+ ti = proto_tree_add_string(tree, hf_hdr_connection,
+ tvb, hdr_start, offset - hdr_start, "close");
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ ti = proto_tree_add_string(tree, hf_hdr_connection,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ wkh_3_ValueWithLength;
+ /* Invalid */
+ wkh_4_End(hf_hdr_connection);
+}
+
+
+/*
+ * Transfer-encoding-value = 0x80 | Token-text
+ */
+static guint32
+wkh_transfer_encoding(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ wkh_1_WellKnownValue;
+ if (val_id == 0x80) {
+ ti = proto_tree_add_string(tree, hf_hdr_transfer_encoding,
+ tvb, hdr_start, offset - hdr_start, "chunked");
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ ti = proto_tree_add_string(tree, hf_hdr_transfer_encoding,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ wkh_3_ValueWithLength;
+ /* Invalid */
+ wkh_4_End(hf_hdr_transfer_encoding);
+}
+
+
+/*
+ * Accept-range-value = 0x80 | 0x81 | Token-text
+ */
+static guint32
+wkh_accept_ranges(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ wkh_1_WellKnownValue;
+ switch (val_id) {
+ case 0x80: /* none */
+ ti = proto_tree_add_string(tree, hf_hdr_accept_ranges,
+ tvb, hdr_start, offset - hdr_start, "none");
+ ok = TRUE;
+ break;
+ case 0x81: /* bytes */
+ ti = proto_tree_add_string(tree, hf_hdr_accept_ranges,
+ tvb, hdr_start, offset - hdr_start, "bytes");
+ ok = TRUE;
+ break;
+ }
+ wkh_2_TextualValue;
+ ti = proto_tree_add_string(tree, hf_hdr_accept_ranges,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ wkh_3_ValueWithLength;
+ /* Invalid */
+ wkh_4_End(hf_hdr_accept_ranges);
+}
+
+
+/*
+ * Content-encoding-value = 0x80 | 0x81 | 0x82 | Token-text
+ */
+static guint32
+wkh_content_encoding(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ wkh_1_WellKnownValue;
+ switch (val_id) {
+ case 0x80: /* gzip */
+ ti = proto_tree_add_string(tree, hf_hdr_content_encoding,
+ tvb, hdr_start, offset - hdr_start, "gzip");
+ ok = TRUE;
+ break;
+ case 0x81: /* compress */
+ ti = proto_tree_add_string(tree, hf_hdr_content_encoding,
+ tvb, hdr_start, offset - hdr_start, "compress");
+ ok = TRUE;
+ break;
+ case 0x82: /* deflate */
+ ti = proto_tree_add_string(tree, hf_hdr_content_encoding,
+ tvb, hdr_start, offset - hdr_start, "deflate");
+ ok = TRUE;
+ break;
+ }
+ wkh_2_TextualValue;
+ ti = proto_tree_add_string(tree, hf_hdr_content_encoding,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ wkh_3_ValueWithLength;
+ /* Invalid */
+ wkh_4_End(hf_hdr_content_encoding);
+}
+
+
+/*
+ * Accept-encoding-value =
+ * Short-integer
+ * | Token-text
+ * | ( Value-length ( Short-integer | Text-string ) [ Q-value ] )
+ */
+static guint32
+wkh_accept_encoding(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 len, off;
+ guint8 peek;
+ gchar *str;
+ proto_tree *parameter_tree = NULL;
+
+ wkh_1_WellKnownValue;
+ switch (val_id) {
+ case 0x80: /* gzip */
+ ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
+ tvb, hdr_start, offset - hdr_start, "gzip");
+ ok = TRUE;
+ break;
+ case 0x81: /* compress */
+ ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
+ tvb, hdr_start, offset - hdr_start, "compress");
+ ok = TRUE;
+ break;
+ case 0x82: /* deflate */
+ ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
+ tvb, hdr_start, offset - hdr_start, "deflate");
+ ok = TRUE;
+ break;
+ }
+ wkh_2_TextualValue;
+ proto_tree_add_string(tree, hf_hdr_accept_encoding,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ wkh_3_ValueWithLength;
+ off = val_start + val_len_len;
+ peek = tvb_get_guint8(tvb, off);
+ if (is_short_integer(peek)) {
+ switch (val_id) {
+ case 0x80: /* gzip */
+ ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
+ tvb, hdr_start, offset - hdr_start, "gzip");
+ ok = TRUE;
+ break;
+ case 0x81: /* compress */
+ ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
+ tvb, hdr_start, offset - hdr_start, "compress");
+ ok = TRUE;
+ break;
+ case 0x82: /* deflate */
+ ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
+ tvb, hdr_start, offset - hdr_start, "deflate");
+ ok = TRUE;
+ break;
+ case 0x83: /* any */
+ ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
+ tvb, hdr_start, offset - hdr_start, "*");
+ ok = TRUE;
+ break;
+ }
+ off++;
+ } else {
+ get_token_text(str, tvb, off, len, ok);
+ if (ok) {
+ ti = proto_tree_add_string(tree, hf_hdr_accept_encoding,
+ tvb, hdr_start, offset - hdr_start, str);
+ g_free(str);
+ }
+ off += len;
+ }
+ if (ok) {
+ /* Remember: offset == val_start + val_len_len + val_len */
+ if (off < offset) { /* Add Q-value if available */
+ parameter_tree = proto_item_add_subtree(ti, ett_header);
+ off = parameter_value_q(parameter_tree, ti, tvb, off);
+ }
+ }
+ wkh_4_End(hf_hdr_accept_encoding);
+}
+
+
+/*
+ * Content-disposition-value = Value-length ( Disposition ) *( Parameter )
+ * Disposition = Form-data | Attachment | Inline | Token-text
+ * Form-data = 0x80
+ * Attachment = 0x81
+ * Inline = 0x82
+ * We handle this as:
+ * Value-length ( Short-integer | Text-string ) *( Parameter )
+ */
+static guint32
+wkh_content_disposition(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 len, off;
+ guint8 peek;
+ gchar *str;
+ proto_tree *parameter_tree = NULL;
+
+ wkh_1_WellKnownValue;
+ /* Invalid */
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ off = val_start + val_len_len;
+ peek = tvb_get_guint8(tvb, off);
+ if (is_short_integer(peek)) {
+ switch (peek) {
+ case 0x80: /* form-data */
+ ti = proto_tree_add_string(tree, hf_hdr_content_disposition,
+ tvb, hdr_start, offset - hdr_start, "form-data");
+ ok = TRUE;
+ break;
+ case 0x81: /* attachment */
+ ti = proto_tree_add_string(tree, hf_hdr_content_disposition,
+ tvb, hdr_start, offset - hdr_start, "attachment");
+ ok = TRUE;
+ break;
+ case 0x82: /* inline */
+ ti = proto_tree_add_string(tree, hf_hdr_content_disposition,
+ tvb, hdr_start, offset - hdr_start, "inline");
+ ok = TRUE;
+ break;
+ }
+ off++;
+ } else {
+ get_token_text(str, tvb, off, len, ok);
+ if (ok) {
+ ti = proto_tree_add_string(tree, hf_hdr_content_disposition,
+ tvb, hdr_start, offset - hdr_start, str);
+ g_free(str);
+ }
+ off += len;
+ }
+ if ((ok) && (off < offset)) {
+ /* Remember: offset == val_start + val_len_len + val_len */
+ parameter_tree = proto_item_add_subtree(ti, ett_header);
+ while (off < offset) { /* Add parameters if available */
+ off = parameter(parameter_tree, ti, tvb, off, offset - off);
+ }
+ }
+ wkh_4_End(hf_hdr_content_disposition);
+}
+
+
+/*
+ * Common code for headers with only a textual value
+ * is written in the macro below:
+ */
+#define wkh_text_header(underscored,Text) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ \
+ wkh_1_WellKnownValue; \
+ /* Invalid */ \
+ wkh_2_TextualValue; \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, val_str); \
+ ok = TRUE; \
+ wkh_3_ValueWithLength; \
+ /* Invalid */ \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+/* Text-only headers: */
+wkh_text_header(content_base, "Content-Base")
+wkh_text_header(content_location, "Content-Location")
+wkh_text_header(etag, "ETag")
+wkh_text_header(from, "From")
+wkh_text_header(host, "Host")
+wkh_text_header(if_match, "If-Match")
+wkh_text_header(if_none_match, "If-None-Match")
+wkh_text_header(location, "Location")
+wkh_text_header(referer, "Referer")
+wkh_text_header(server, "Server")
+wkh_text_header(user_agent, "User-Agent")
+wkh_text_header(upgrade, "Upgrade")
+wkh_text_header(via, "Via")
+wkh_text_header(content_uri, "Content-Uri")
+wkh_text_header(initiator_uri, "Initiator-Uri")
+wkh_text_header(profile, "Profile")
+
+/*
+ * Same for quoted-string value
+ */
+#define wkh_quoted_string_header(underscored,Text) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ gchar *str; \
+ \
+ wkh_1_WellKnownValue; \
+ /* Invalid */ \
+ wkh_2_TextualValue; \
+ if (is_quoted_string(val_str[0])) { \
+ if (is_quoted_string(val_str[val_len-2])) { \
+ /* Trailing quote - issue a warning */ \
+ str = g_strdup_printf("%s" TrailingQuoteWarning, val_str); \
+ } else { /* OK (no trailing quote) */ \
+ str = g_strdup_printf("%s\"", val_str); \
+ } \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, str); \
+ g_free(str); \
+ } else { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, val_str); \
+ proto_item_append_text(ti, \
+ " <Warning: should be encoded as a Quoted-string>"); \
+ } \
+ ok = TRUE; \
+ wkh_3_ValueWithLength; \
+ /* Invalid */ \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+wkh_quoted_string_header(content_id, "Content-ID")
+
+
+/*
+ * Common code for headers with only a textual or a date value
+ * is written in the macro below:
+ */
+#define wkh_text_or_date_value_header(underscored,Text) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint32 val = 0, off = val_start, len; \
+ nstime_t tv; \
+ gchar *str; /* may not be freed! */ \
+ \
+ wkh_1_WellKnownValue; \
+ /* Invalid */ \
+ wkh_2_TextualValue; \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, val_str); \
+ ok = TRUE; \
+ wkh_3_ValueWithLength; \
+ if (val_id <= 4) { /* Length field already parsed by macro! */ \
+ get_date_value(val, tvb, off, len, ok); \
+ if (ok) { \
+ tv.secs = val; \
+ tv.nsecs = 0; \
+ str = abs_time_to_str(&tv); \
+ g_assert(str); \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, str); \
+ /* BEHOLD: do NOT try to free str, as this generates a core
+ * dump! It looks like abs_time_to_str() is buggy or works
+ * with static data. */ \
+ } \
+ } \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+/* If-Range */
+wkh_text_or_date_value_header(if_range,"If-Range")
+
+
+/*
+ * Common code for headers with only a date value
+ * is written in the macro below:
+ */
+#define wkh_date_value_header(underscored,Text) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint32 val = 0, off = val_start, len; \
+ nstime_t tv; \
+ gchar *str; /* may not be freed! */ \
+ \
+ wkh_1_WellKnownValue; \
+ /* Invalid */ \
+ wkh_2_TextualValue; \
+ /* Invalid */ \
+ wkh_3_ValueWithLength; \
+ if (val_id <= 4) { /* Length field already parsed by macro! */ \
+ get_date_value(val, tvb, off, len, ok); \
+ if (ok) { \
+ tv.secs = val; \
+ tv.nsecs = 0; \
+ str = abs_time_to_str(&tv); \
+ g_assert(str); \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, str); \
+ /* BEHOLD: do NOT try to free str, as this generates a core
+ * dump! It looks like abs_time_to_str() is buggy or works
+ * with static data. */ \
+ } \
+ } \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+/* Date-value only headers: */
+wkh_date_value_header(date, "Date")
+wkh_date_value_header(expires, "Expires")
+wkh_date_value_header(if_modified_since, "If-Modified-Since")
+wkh_date_value_header(if_unmodified_since, "If-Unmodified-Since")
+wkh_date_value_header(last_modified, "Last-Modified")
+
+
+/* Date-value with special interpretation of zero value */
+#define wkh_tod_value_header(underscored,Text) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint32 val = 0, off = val_start, len; \
+ nstime_t tv; \
+ gchar *str; /* may not be freed! */ \
+ \
+ wkh_1_WellKnownValue; \
+ if (val_id == 0x80) { /* Openwave TOD header uses this format */ \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ "Requesting Time Of Day"); \
+ proto_item_append_text(ti, \
+ " <Warning: should be encoded as long-integer>"); \
+ ok = TRUE; \
+ } \
+ /* It seems VERY unlikely that we'll see date values within the first \
+ * 127 seconds of the UNIX 1-1-1970 00:00:00 start of the date clocks \
+ * so I assume such a value is a genuine error */ \
+ wkh_2_TextualValue; \
+ /* Invalid */ \
+ wkh_3_ValueWithLength; \
+ if (val_id <= 4) { /* Length field already parsed by macro! */ \
+ get_date_value(val, tvb, off, len, ok); \
+ if (ok) { \
+ if (val == 0) { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ "Requesting Time Of Day"); \
+ } else { \
+ tv.secs = val; \
+ tv.nsecs = 0; \
+ str = abs_time_to_str(&tv); \
+ g_assert(str); \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, str); \
+ } \
+ } \
+ } \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+wkh_tod_value_header(x_wap_tod, "X-Wap-Tod")
+
+
+/*
+ * Age-value: Delta-seconds-value
+ */
+static guint32
+wkh_age(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 val = 0, off = val_start, len;
+
+ wkh_1_WellKnownValue;
+ val = val_id & 0x7F;
+ val_str = g_strdup_printf("%u second%s", val, PLURALIZE(val));
+ ti = proto_tree_add_string(tree, hf_hdr_age,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ g_free(val_str); /* proto_XXX creates a copy */
+ ok = TRUE;
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ if (val_id <= 4) { /* Length field already parsed by macro! */
+ get_long_integer(val, tvb, off, len, ok);
+ if (ok) {
+ val_str = g_strdup_printf("%u second%s", val, PLURALIZE(val));
+ ti = proto_tree_add_string(tree, hf_hdr_age,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ g_free(val_str); /* proto_XXX creates a copy */
+ }
+ }
+ wkh_4_End(hf_hdr_age);
+}
+
+
+/*
+ * Template for Integer lookup or text value headers:
+ */
+#define wkh_integer_lookup_or_text_value(underscored,Text,valueString,valueName) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint32 val = 0, off = val_start, len; \
+ \
+ wkh_1_WellKnownValue; \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ val_to_str(val_id & 0x7F, valueString, \
+ "(Unknown " valueName " identifier 0x%X)")); \
+ ok = TRUE; \
+ wkh_2_TextualValue; \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, val_str); \
+ ok = TRUE; \
+ wkh_3_ValueWithLength; \
+ if (val_id <= 4) { /* Length field already parsed by macro! */ \
+ get_long_integer(val, tvb, off, len, ok); \
+ if (ok) { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ val_to_str(val_id & 0x7F, valueString, \
+ "(Unknown " valueName " identifier 0x%X)")); \
+ } \
+ } \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+/*
+ * Wap-application-value: Uri-value | Integer-value
+ */
+wkh_integer_lookup_or_text_value(x_wap_application_id, "X-Wap-Application-Id",
+ vals_wap_application_ids, "WAP application")
+wkh_integer_lookup_or_text_value(accept_application, "Accept-Application",
+ vals_wap_application_ids, "WAP application")
+wkh_integer_lookup_or_text_value(content_language, "Content-Language",
+ vals_languages, "language")
+/* NOTE - Although the WSP spec says this is an integer-value, the WSP headers
+ * are encoded as a 7-bit entity! */
+wkh_integer_lookup_or_text_value(trailer, "Trailer",
+ vals_field_names, "well-known-header")
+
+
+/*
+ * Challenge
+ */
+
+/*
+ * Common code for headers with only a challenge value
+ * is written in the macro below:
+ */
+#define wkh_challenge_value_header(underscored,Text) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, \
+ guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint8 peek; \
+ guint32 off, len; \
+ proto_tree *subtree; \
+ gchar *str; \
+ \
+ wkh_1_WellKnownValue; \
+ /* Invalid */ \
+ wkh_2_TextualValue; \
+ /* Invalid */ \
+ wkh_3_ValueWithLength; \
+ off = val_start + val_len_len; \
+ peek = tvb_get_guint8(tvb, off); \
+ if (peek == 0x80) { /* Basic */ \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, "basic"); \
+ subtree = proto_item_add_subtree(ti, ett_header); \
+ proto_tree_add_string(subtree, hf_hdr_ ## underscored ## _scheme, \
+ tvb, off, 1, "basic"); \
+ off++; \
+ /* Realm: text-string */ \
+ get_text_string(str,tvb,off,len,ok); \
+ if (ok) { \
+ proto_tree_add_string(subtree, \
+ hf_hdr_ ## underscored ## _realm, \
+ tvb, off, len, str); \
+ val_str = g_strdup_printf("; realm=%s", str); \
+ proto_item_append_string(ti, val_str); \
+ g_free(val_str); \
+ g_free(str); \
+ off += len; \
+ } \
+ } else { /* Authentication-scheme: token-text */ \
+ get_token_text(str, tvb, off, len, ok); \
+ if (ok) { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, off - hdr_start, str); \
+ subtree = proto_item_add_subtree(ti, ett_header); \
+ proto_tree_add_string(subtree, \
+ hf_hdr_ ## underscored ## _scheme, \
+ tvb, hdr_start, off - hdr_start, str); \
+ g_free(str); \
+ off += len; \
+ /* Realm: text-string */ \
+ get_text_string(str,tvb,off,len,ok); \
+ if (ok) { \
+ proto_tree_add_string(subtree, \
+ hf_hdr_ ## underscored ## _realm, \
+ tvb, off, len, str); \
+ val_str = g_strdup_printf("; realm=%s", str); \
+ proto_item_append_string(ti, val_str); \
+ g_free(val_str); \
+ g_free(str); \
+ off += len; \
+ /* Auth-params: parameter - TODO */ \
+ while (off < offset) /* Parse parameters */ \
+ off = parameter(subtree, ti, tvb, off, offset - off); \
+ } \
+ } \
+ } \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+/* Challenge-value only headers: */
+wkh_challenge_value_header(www_authenticate, "WWW-Authenticate")
+wkh_challenge_value_header(proxy_authenticate, "Proxy-Authenticate")
+
+
+/*
+ * Credentials
+ */
+
+/*
+ * Common code for headers with only a credentials value
+ * is written in the macro below:
+ */
+#define wkh_credentials_value_header(underscored,Text) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, \
+ guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint8 peek; \
+ guint32 off, len; \
+ proto_tree *subtree; \
+ gchar *str; \
+ \
+ wkh_1_WellKnownValue; \
+ /* Invalid */ \
+ wkh_2_TextualValue; \
+ /* Invalid */ \
+ wkh_3_ValueWithLength; \
+ off = val_start + val_len_len; \
+ peek = tvb_get_guint8(tvb, off); \
+ if (peek == 0x80) { /* Basic */ \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, "basic"); \
+ subtree = proto_item_add_subtree(ti, ett_header); \
+ proto_tree_add_string(subtree, hf_hdr_ ## underscored ## _scheme, \
+ tvb, off, 1, "basic"); \
+ off++; \
+ /* User-id: text-string */ \
+ get_text_string(str,tvb,off,len,ok); \
+ if (ok) { \
+ proto_tree_add_string(subtree, \
+ hf_hdr_ ## underscored ## _user_id, \
+ tvb, off, len, str); \
+ val_str = g_strdup_printf("; user-id=%s", str); \
+ proto_item_append_string(ti, val_str); \
+ g_free(val_str); \
+ g_free(str); \
+ off += len; \
+ /* Password: text-string */ \
+ get_text_string(str,tvb,off,len,ok); \
+ if (ok) { \
+ proto_tree_add_string(subtree, \
+ hf_hdr_ ## underscored ## _password, \
+ tvb, off, len, str); \
+ val_str = g_strdup_printf("; password=%s", str); \
+ proto_item_append_string(ti, val_str); \
+ g_free(val_str); \
+ g_free(str); \
+ off += len; \
+ } \
+ } \
+ } else { /* Authentication-scheme: token-text */ \
+ get_token_text(str, tvb, off, len, ok); \
+ if (ok) { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, off - hdr_start, str); \
+ subtree = proto_item_add_subtree(ti, ett_header); \
+ proto_tree_add_string(subtree, \
+ hf_hdr_ ## underscored ## _scheme, \
+ tvb, hdr_start, off - hdr_start, str); \
+ g_free(str); \
+ off += len; \
+ /* Auth-params: parameter - TODO */ \
+ while (off < offset) /* Parse parameters */ \
+ off = parameter(subtree, ti, tvb, off, offset - off); \
+ } \
+ } \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+/* Credentials-value only headers: */
+wkh_credentials_value_header(authorization, "Authorization")
+wkh_credentials_value_header(proxy_authorization, "Proxy-Authorization")
+
+
+/*
+ * Content-md5-value = 16*16 OCTET
+ */
+static guint32
+wkh_content_md5 (proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 off;
+
+ wkh_1_WellKnownValue;
+ /* Invalid */
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ off = val_start + val_len_len;
+ if (val_len == 16) {
+ val_str = g_strdup_printf(
+ "%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x%02x%02x%02x",
+ tvb_get_guint8(tvb, off),
+ tvb_get_guint8(tvb, off + 1),
+ tvb_get_guint8(tvb, off + 2),
+ tvb_get_guint8(tvb, off + 3),
+ tvb_get_guint8(tvb, off + 4),
+ tvb_get_guint8(tvb, off + 5),
+ tvb_get_guint8(tvb, off + 6),
+ tvb_get_guint8(tvb, off + 7),
+ tvb_get_guint8(tvb, off + 8),
+ tvb_get_guint8(tvb, off + 9),
+ tvb_get_guint8(tvb, off + 10),
+ tvb_get_guint8(tvb, off + 11),
+ tvb_get_guint8(tvb, off + 12),
+ tvb_get_guint8(tvb, off + 13),
+ tvb_get_guint8(tvb, off + 14),
+ tvb_get_guint8(tvb, off + 15)
+ );
+ ti = proto_tree_add_string(tree, hf_hdr_content_md5,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ g_free(val_str);
+ ok = TRUE;
+ }
+ wkh_4_End(hf_hdr_content_md5);
+}
+
+
+/*
+ * Pragma-value = 0x80 | Length Parameter
+ */
+static guint32
+wkh_pragma(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 off;
+
+ wkh_1_WellKnownValue;
+ if (val_id == 0x80) {
+ ti = proto_tree_add_string(tree, hf_hdr_pragma,
+ tvb, hdr_start, offset - hdr_start, "no-cache");
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ off = val_start + val_len_len;
+ ti = proto_tree_add_string(tree, hf_hdr_pragma,
+ tvb, hdr_start, off - hdr_start, "");
+ /* NULL subtree for parameter() results in no subtree
+ * TODO - provide a single parameter dissector that appends data
+ * to the header field data. */
+ off = parameter(NULL, ti, tvb, off, offset - off);
+ ok = TRUE;
+ wkh_4_End(hf_hdr_pragma);
+}
+
+
+/*
+ * Integer-value
+ */
+#define wkh_integer_value_header(underscored,Text) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint32 val = 0, off = val_start, len; \
+ gchar *str; /* may not be freed! */ \
+ \
+ wkh_1_WellKnownValue; \
+ str = g_strdup_printf("%u", val_id & 0x7F); \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, str); \
+ g_free(str); \
+ ok = TRUE; \
+ wkh_2_TextualValue; \
+ /* Invalid */ \
+ wkh_3_ValueWithLength; \
+ if (val_id <= 4) { /* Length field already parsed by macro! */ \
+ get_long_integer(val, tvb, off, len, ok); \
+ if (ok) { \
+ str = g_strdup_printf("%u", val); \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, str); \
+ g_free(str); \
+ } \
+ } \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+wkh_integer_value_header(content_length, "Content-Length")
+wkh_integer_value_header(max_forwards, "Max-Forwards")
+
+
+#define wkh_integer_lookup_value_header(underscored,Text,valueString,valueName) \
+static guint32 \
+wkh_ ## underscored(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_) \
+{ \
+ wkh_0_Declarations; \
+ guint32 val = 0, off = val_start, len; \
+ \
+ wkh_1_WellKnownValue; \
+ val_str = match_strval(val_id & 0x7F, valueString); \
+ if (val_str) { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, val_str); \
+ ok = TRUE; \
+ } else { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ "<Unknown " valueName ">"); \
+ } \
+ wkh_2_TextualValue; \
+ /* Invalid */ \
+ wkh_3_ValueWithLength; \
+ if (val_id <= 4) { /* Length field already parsed by macro! */ \
+ get_long_integer(val, tvb, off, len, ok); \
+ if (ok) { \
+ val_str = match_strval(val_id & 0x7F, valueString); \
+ if (val_str) { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, val_str); \
+ ok = TRUE; \
+ } else { \
+ ti = proto_tree_add_string(tree, hf_hdr_ ## underscored, \
+ tvb, hdr_start, offset - hdr_start, \
+ "<Unknown " valueName ">"); \
+ } \
+ } \
+ } \
+ wkh_4_End(hf_hdr_ ## underscored); \
+}
+
+wkh_integer_lookup_value_header(bearer_indication, "Bearer-Indication",
+ vals_bearer_types, "bearer type")
+
+
+/*
+ * Cache-control-value
+ */
+static guint32
+wkh_cache_control(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 off, len, val = 0;
+ guint8 peek, cache_control_directive;
+ gchar *str;
+
+ wkh_1_WellKnownValue;
+ val = val_id & 0x7F;
+ val_str = match_strval(val, vals_cache_control);
+ if (val_str) {
+ ti = proto_tree_add_string(tree, hf_hdr_cache_control,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ ti = proto_tree_add_string(tree, hf_hdr_cache_control,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ wkh_3_ValueWithLength;
+ /* General form:
+ * ( no-cache | private ) 1*( Field-name )
+ * | ( max-age | max-stale | min-fresh | s-maxage) Delta-seconds-value
+ * | Token-text ( Integer-value | Text-value )
+ * Where:
+ * Field-name = Short-integer | Token-text
+ */
+ off = val_start + val_len_len;
+ cache_control_directive = tvb_get_guint8(tvb, off++);
+ if (cache_control_directive & 0x80) { /* Well known cache directive */
+ switch (cache_control_directive & 0x7F) {
+ case CACHE_CONTROL_NO_CACHE:
+ case CACHE_CONTROL_PRIVATE:
+ ti = proto_tree_add_string(tree, hf_hdr_cache_control,
+ tvb, hdr_start, offset - hdr_start,
+ val_to_str (cache_control_directive & 0x7F, vals_cache_control,
+ "<Unknown cache control directive 0x%02X>"));
+ /* TODO: split multiple entries */
+ while (ok && (off < offset)) { /* 1*( Field-name ) */
+ ok = TRUE;
+ peek = tvb_get_guint8(tvb, off);
+ if (peek & 0x80) { /* Well-known-field-name */
+ proto_item_append_string(ti,
+ val_to_str (peek, vals_field_names,
+ "<Unknown WSP header field 0x%02X>"));
+ off++;
+ } else { /* Token-text */
+ get_token_text(val_str, tvb, off, len, ok);
+ if (ok) {
+ proto_item_append_string(ti, val_str);
+ g_free(val_str);
+ off += len;
+ }
+ }
+ }
+ break;
+
+ case CACHE_CONTROL_MAX_AGE:
+ case CACHE_CONTROL_MAX_STALE:
+ case CACHE_CONTROL_MIN_FRESH:
+ case CACHE_CONTROL_S_MAXAGE:
+ ti = proto_tree_add_string(tree, hf_hdr_cache_control,
+ tvb, hdr_start, offset - hdr_start,
+ val_to_str (cache_control_directive & 0x7F, vals_cache_control,
+ "<Unknown cache control directive 0x%02X>"));
+ get_delta_seconds_value(val, tvb, off, len, ok);
+ if (ok) {
+ val_str = g_strdup_printf("=%u second%s",
+ val, PLURALIZE(val));
+ proto_item_append_string(ti, val_str);
+ g_free(val_str); /* proto_XXX creates a copy */
+ }
+ break;
+
+ default:
+ /* ok = FALSE */
+ break;
+ }
+ } else if (is_token_text(cache_control_directive)) {
+ get_token_text(val_str, tvb, off, len, ok);
+ if (ok) {
+ ti = proto_tree_add_string(tree, hf_hdr_cache_control,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ g_free(val_str);
+ get_integer_value(val, tvb, off, len, ok);
+ if (ok) { /* Integer-value */
+ val_str = g_strdup_printf("=%u", val);
+ proto_item_append_string(ti, val_str);
+ g_free(val_str); /* proto_XXX creates a copy */
+ } else { /* Text-value */
+ get_text_string(val_str, tvb, off, len, ok);
+ if (ok) {
+ if (is_quoted_string(val_str[0])) {
+ if (is_quoted_string(val_str[len-2])) {
+ /* Trailing quote - issue a warning */
+ str = g_strdup_printf("%s" TrailingQuoteWarning,
+ val_str);
+ } else { /* OK (no trailing quote) */
+ str = g_strdup_printf("%s\"", val_str);
+ }
+ proto_item_append_string(ti, str);
+ g_free(str);
+ } else { /* Token-text | 0x00 */
+ /* TODO - check that we have Token-text or 0x00 */
+ proto_item_append_string(ti, val_str);
+ }
+ g_free(val_str);
+ }
+ }
+ }
+ }
+ wkh_4_End(hf_hdr_cache_control);
+}
+
+
+/*
+ * Warning-value =
+ * Short-integer
+ * | ( Value-length Short-integer Text-string Text-string )
+ */
+static guint32
+wkh_warning(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 off, len, val;
+ guint8 warn_code;
+ gchar *str;
+ proto_tree *subtree;
+
+ /* TODO - subtree with values */
+
+ wkh_1_WellKnownValue;
+ val = val_id & 0x7F;
+ val_str = match_strval(val, vals_wsp_warning_code);
+ if (val_str) {
+ ti = proto_tree_add_string(tree, hf_hdr_warning,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ subtree = proto_item_add_subtree(ti, ett_header);
+ proto_tree_add_uint(subtree, hf_hdr_warning_code,
+ tvb, val_start, 1, val);
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ /* TODO - subtree with individual values */
+ off = val_start + val_len_len;
+ warn_code = tvb_get_guint8(tvb, off);
+ if (warn_code & 0x80) { /* Well known warn code */
+ val = warn_code & 0x7f;
+ val_str = match_strval(val, vals_wsp_warning_code_short);
+ if (val_str) { /* OK */
+ str = g_strdup_printf("code=%s", val_str);
+ ti = proto_tree_add_string(tree, hf_hdr_warning,
+ tvb, hdr_start, offset - hdr_start, str);
+ g_free(str);
+ subtree = proto_item_add_subtree(ti, ett_header);
+ proto_tree_add_uint(subtree, hf_hdr_warning_code,
+ tvb, off, 1, val);
+ off++; /* Now skip to the warn-agent subfield */
+ get_text_string(str, tvb, off, len, ok);
+ if (ok) { /* Valid warn-agent string */
+ proto_tree_add_string(subtree, hf_hdr_warning_agent,
+ tvb, off, len, str);
+ val_str = g_strdup_printf("; agent=%s", str);
+ proto_item_append_string(ti, val_str);
+ g_free(val_str); /* proto_XXX creates a copy */
+ g_free(str);
+ off += len;
+ get_text_string(str, tvb, off, len, ok);
+ if (ok) { /* Valid warn-text string */
+ proto_tree_add_string(subtree,
+ hf_hdr_warning_text,
+ tvb, off, len, str);
+ val_str = g_strdup_printf("; text=%s", str);
+ proto_item_append_string(ti, val_str);
+ g_free(val_str); /* proto_XXX creates a copy */
+ g_free(str);
+ off += len;
+ }
+ }
+ }
+ }
+ wkh_4_End(hf_hdr_warning);
+}
+
+
+/*
+ * Profile-warning-value =
+ * Short-integer
+ * | ( Value-length Short-integer Text-string *( Date-value ) )
+ */
+static guint32
+wkh_profile_warning(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 off, len, val = 0;
+ nstime_t tv;
+ guint8 warn_code;
+ gchar *str;
+
+ wkh_1_WellKnownValue;
+ val = val_id & 0x7F;
+ val_str = match_strval(val, vals_wsp_profile_warning_code);
+ if (val_str) {
+ ti = proto_tree_add_string(tree, hf_hdr_profile_warning,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ off = val_start + val_len_len;
+ warn_code = tvb_get_guint8(tvb, off++);
+ if (warn_code & 0x80) { /* Well known warn code */
+ val_str = match_strval(val, vals_wsp_profile_warning_code);
+ if (val_str) { /* OK */
+ ti = proto_tree_add_string(tree, hf_hdr_profile_warning,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ get_uri_value(str, tvb, off, len, ok);
+ if (ok) { /* Valid warn-target string */
+ off += len;
+ str = g_strdup_printf("; target=%s", val_str);
+ proto_item_append_string(ti, str);
+ g_free(str); /* proto_XXX creates a copy */
+ /* Add zero or more dates */
+ while (ok && (off < offset)) {
+ get_date_value(val, tvb, off, len, ok);
+ if (ok) { /* Valid warn-text string */
+ off += len;
+ tv.secs = val;
+ tv.nsecs = 0;
+ val_str = abs_time_to_str(&tv);
+ g_assert(val_str);
+ str = g_strdup_printf("; date=%s", val_str);
+ proto_item_append_string(ti, str);
+ g_free(str); /* proto_XXX creates a copy */
+ /* BEHOLD: do NOT try to free val_str, as this
+ * generates a core dump!
+ * It looks like abs_time_to_str() is
+ * buggy or works with static data. */
+ }
+ }
+ }
+ }
+ }
+ wkh_4_End(hf_hdr_profile_warning);
+}
+
+
+/* Encoding-version-value =
+ * Short-integer
+ * | Text-string
+ * | Length Short-integer [ Short-integer | text-string ]
+ */
+static guint32 wkh_encoding_version (proto_tree *tree, tvbuff_t *tvb,
+ guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 off, val, len;
+ gchar *str;
+
+ wkh_1_WellKnownValue;
+ val = val_id & 0x7F;
+ val_str = g_strdup_printf("%u.%u", val >> 4, val & 0x0F);
+ proto_tree_add_string(tree, hf_hdr_encoding_version,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ g_free(val_str);
+ ok = TRUE;
+ wkh_2_TextualValue;
+ proto_tree_add_string(tree, hf_hdr_encoding_version,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ ok = TRUE;
+ wkh_3_ValueWithLength;
+ off = val_start + val_len_len;
+ val = tvb_get_guint8(tvb, off);
+ if (val & 0x80) { /* Header Code Page */
+ val_str = g_strdup_printf("code-page=%u", val & 0x7F);
+ ti = proto_tree_add_string(tree, hf_hdr_encoding_version,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ g_free(val_str);
+ off++;
+ ok = TRUE;
+ if (off < offset) { /* Extra version-value */
+ get_version_value(val,val_str,tvb,off,len,ok);
+ if (ok) { /* Always creates a string if OK */
+ str = g_strdup_printf(": %s", val_str);
+ proto_item_append_string(ti, str);
+ g_free(str);
+ g_free(val_str);
+ }
+ }
+ }
+
+ wkh_4_End(hf_hdr_encoding_version);
+}
+
+
+/* Content-range-value =
+ * Length Uintvar-integer ( 0x80 | Uintvar-integer )
+ */
+static guint32
+wkh_content_range(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 off, val, len;
+ proto_tree *subtree = NULL;
+
+ wkh_1_WellKnownValue;
+ /* Invalid */
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ off = val_start + val_len_len;
+ get_uintvar_integer (val, tvb, off, len, ok); /* Uintvar start */
+ if (ok) {
+ val_str = g_strdup_printf("first-byte-pos=%u", val);
+ ti = proto_tree_add_string(tree, hf_hdr_content_range,
+ tvb, hdr_start, offset - hdr_start, val_str);
+ subtree = proto_item_add_subtree(ti, ett_header);
+ proto_tree_add_uint(subtree, hf_hdr_content_range_first_byte_pos,
+ tvb, off, len, val);
+ g_free(val_str);
+ off += len;
+ /* Now check next value */
+ val = tvb_get_guint8(tvb, off);
+ if (val == 0x80) { /* Unknown length */
+ proto_item_append_string(ti, "; entity-length=unknown");
+ } else { /* Uintvar entity length */
+ get_uintvar_integer (val, tvb, off, len, ok);
+ if (ok) {
+ val_str = g_strdup_printf("; entity-length=%u", val);
+ proto_item_append_string(ti, val_str);
+ proto_tree_add_uint(subtree,
+ hf_hdr_content_range_entity_length,
+ tvb, off, len, val);
+ g_free(val_str);
+ }
+ }
+ }
+
+ wkh_4_End(hf_hdr_content_range);
+}
+
+
+/* Range-value =
+ * Length
+ * 0x80 Uintvar-integer [ Uintvar-integer ]
+ * | 0x81 Uintvar-integer
+ */
+static guint32
+wkh_range(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 off, val, len;
+ proto_tree *subtree = NULL;
+
+ wkh_1_WellKnownValue;
+ /* Invalid */
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ off = val_start + val_len_len;
+ val = tvb_get_guint8(tvb, off);
+ if (val == 0x80) { /* Byte-range */
+ ti = proto_tree_add_string(tree, hf_hdr_range,
+ tvb, hdr_start, offset - hdr_start, "byte-range");
+ subtree = proto_item_add_subtree(ti, ett_header);
+ /* Get the First-byte-pos (Uintvar-integer) */
+ get_uintvar_integer (val, tvb, off, len, ok);
+ if (ok) {
+ val_str = g_strdup_printf("; first-byte-pos=%u", val);
+ proto_item_append_string(ti, val_str);
+ proto_tree_add_uint(subtree, hf_hdr_range_first_byte_pos,
+ tvb, off, len, val);
+ g_free(val_str);
+ off += len;
+ /* Get the optional Last-byte-pos (Uintvar-integer) */
+ if (off < offset) {
+ get_uintvar_integer (val, tvb, off, len, ok);
+ if (ok) {
+ val_str = g_strdup_printf("; last-byte-pos=%u", val);
+ proto_item_append_string(ti, val_str);
+ proto_tree_add_uint(subtree,
+ hf_hdr_range_last_byte_pos,
+ tvb, off, len, val);
+ g_free(val_str);
+ }
+ }
+ }
+ } else if (val == 0x81) { /* Suffix-byte-range */
+ ti = proto_tree_add_string(tree, hf_hdr_range,
+ tvb, hdr_start, offset - hdr_start, "suffix-byte-range");
+ subtree = proto_item_add_subtree(ti, ett_header);
+ /* Get the Suffix-length (Uintvar-integer) */
+ get_uintvar_integer (val, tvb, off, len, ok);
+ if (ok) {
+ val_str = g_strdup_printf("; suffix-length=%u", val);
+ proto_item_append_string(ti, val_str);
+ proto_tree_add_uint(subtree, hf_hdr_range_suffix_length,
+ tvb, off, len, val);
+ g_free(val_str);
+ }
+ }
+
+ wkh_4_End(hf_hdr_range);
+}
+
+
+/* TE-value =
+ * 0x81
+ * | Value-length (0x82--0x86 | Token-text) [ Q-token Q-value ]
+ */
+static guint32 wkh_te (proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+ guint32 off, val, len;
+
+ wkh_1_WellKnownValue;
+ if (val_id == 0x81) {
+ proto_tree_add_string(tree, hf_hdr_encoding_version,
+ tvb, hdr_start, offset - hdr_start, "trailers");
+ ok = TRUE;
+ }
+ wkh_2_TextualValue;
+ /* Invalid */
+ wkh_3_ValueWithLength;
+ off = val_start + val_len_len;
+ val = tvb_get_guint8(tvb, off);
+ if (val & 0x80) { /* Well-known-TE */
+ val_str = match_strval((val & 0x7F), vals_well_known_te);
+ if (val_str) {
+ ti = proto_tree_add_string(tree, hf_hdr_te,
+ tvb, hdr_start, off - hdr_start, val_str);
+ off++;
+ ok = TRUE;
+ }
+ } else { /* TE in Token-text format */
+ get_token_text(val_str, tvb, off, len, ok);
+ ti = proto_tree_add_string(tree, hf_hdr_te,
+ tvb, hdr_start, off - hdr_start, val_str);
+ g_free(val_str);
+ off += len;
+ ok = TRUE;
+ }
+ if ((ok) && (off < offset)) { /* Q-token Q-value */
+ /* TODO */
+ }
+
+ wkh_4_End(hf_hdr_te);
+}
+
+
+/****************************************************************************
+ * O p e n w a v e h e a d e r s
+ ****************************************************************************/
+
+
+
+
+/*
+ * Redefine the WellKnownValue parsing so Openwave header field names are used
+ * are used instead of the default WSP header field names
+ */
+#undef wkh_1_WellKnownValue
+#define wkh_1_WellKnownValue /* Parse Well Known Value */ \
+ proto_tree_add_string_hidden(tree, hf_hdr_name, \
+ tvb, hdr_start, offset - hdr_start, \
+ val_to_str (hdr_id, vals_openwave_field_names, \
+ "<Unknown WSP header field 0x%02X>")); \
+ if (val_id & 0x80) { /* Well-known value */ \
+ offset++; \
+ /* Well-known value processing starts HERE \
+ * \
+ * BEGIN */
+
+/*
+ * Redefine the End parsing so Openwave header field names are used
+ * instead of the default WSP field names
+ */
+#undef wkh_4_End
+#define wkh_4_End(hf) /* End of value parsing */ \
+ /* END */ \
+ } \
+ /* Check for errors */ \
+ if (! ok) { \
+ if (ti) { /* Append to protocol tree item label */ \
+ proto_item_append_text(ti, \
+ "<Error: Invalid header value>"); \
+ } else if (hf > 0) { /* Create protocol tree item */ \
+ proto_tree_add_string(tree, hf, \
+ tvb, hdr_start, offset - hdr_start, \
+ " <Error: Invalid header value>"); \
+ } else { /* Create anonymous header field entry */ \
+ proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start, \
+ "%s: <Error: Invalid header value>", \
+ val_to_str (hdr_id, vals_openwave_field_names, \
+ "<Unknown WSP header field 0x%02X>")); \
+ } \
+ } \
+ return offset;
+
+
+/* Dissect the Openwave header value (generic) */
+static guint32
+wkh_openwave_default(proto_tree *tree, tvbuff_t *tvb, guint32 hdr_start, packet_info *pinfo _U_)
+{
+ wkh_0_Declarations;
+
+ ok = TRUE; /* Bypass error checking as we don't parse the values! */
+
+ wkh_1_WellKnownValue;
+ ti = proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start,
+ "%s: (Undecoded well-known value 0x%02x)",
+ val_to_str (hdr_id, vals_openwave_field_names,
+ "<Unknown WSP header field 0x%02X>"), val_id & 0x7F);
+ wkh_2_TextualValue;
+ ti = proto_tree_add_text(tree,tvb,hdr_start, offset - hdr_start,
+ "%s: %s",
+ val_to_str (hdr_id, vals_openwave_field_names,
+ "<Unknown WSP header field 0x%02X>"), val_str);
+ wkh_3_ValueWithLength;
+ ti = proto_tree_add_text(tree, tvb, hdr_start, offset - hdr_start,
+ "%s: (Undecoded value in general form with length indicator)",
+ val_to_str (hdr_id, vals_openwave_field_names,
+ "<Unknown WSP header field 0x%02X>"));
+
+ wkh_4_End(HF_EMPTY); /* See wkh_default for explanation */
+}
+
+
+/* Textual Openwave headers */
+wkh_text_header(openwave_x_up_proxy_operator_domain,
+ "x-up-proxy-operator-domain")
+wkh_text_header(openwave_x_up_proxy_home_page,
+ "x-up-proxy-home-page")
+wkh_text_header(openwave_x_up_proxy_uplink_version,
+ "x-up-proxy-uplink-version")
+wkh_text_header(openwave_x_up_proxy_ba_realm,
+ "x-up-proxy-ba-realm")
+wkh_text_header(openwave_x_up_proxy_request_uri,
+ "x-up-proxy-request-uri")
+wkh_text_header(openwave_x_up_proxy_bookmark,
+ "x-up-proxy-bookmark")
+
+/* Integer Openwave headers */
+wkh_integer_value_header(openwave_x_up_proxy_push_seq,
+ "x-up-proxy-push-seq")
+wkh_integer_value_header(openwave_x_up_proxy_notify,
+ "x-up-proxy-notify")
+wkh_integer_value_header(openwave_x_up_proxy_net_ask,
+ "x-up-proxy-net-ask")
+wkh_integer_value_header(openwave_x_up_proxy_ba_enable,
+ "x-up-proxy-ba-enable")
+wkh_integer_value_header(openwave_x_up_proxy_redirect_enable,
+ "x-up-proxy-redirect-enable")
+wkh_integer_value_header(openwave_x_up_proxy_redirect_status,
+ "x-up-proxy-redirect-status")
+wkh_integer_value_header(openwave_x_up_proxy_linger,
+ "x-up-proxy-linger")
+wkh_integer_value_header(openwave_x_up_proxy_enable_trust,
+ "x-up-proxy-enable-trust")
+wkh_integer_value_header(openwave_x_up_proxy_trust,
+ "x-up-proxy-trust")
+
+wkh_integer_value_header(openwave_x_up_devcap_has_color,
+ "x-up-devcap-has-color")
+wkh_integer_value_header(openwave_x_up_devcap_num_softkeys,
+ "x-up-devcap-num-softkeys")
+wkh_integer_value_header(openwave_x_up_devcap_softkey_size,
+ "x-up-devcap-softkey-size")
+wkh_integer_value_header(openwave_x_up_devcap_screen_chars,
+ "x-up-devcap-screen-chars")
+wkh_integer_value_header(openwave_x_up_devcap_screen_pixels,
+ "x-up-devcap-screen-pixels")
+wkh_integer_value_header(openwave_x_up_devcap_em_size,
+ "x-up-devcap-em-size")
+wkh_integer_value_header(openwave_x_up_devcap_screen_depth,
+ "x-up-devcap-screen-depth")
+wkh_integer_value_header(openwave_x_up_devcap_immed_alert,
+ "x-up-devcap-immed_alert")
+wkh_integer_value_header(openwave_x_up_devcap_gui,
+ "x-up-devcap-gui")
+
+/* Openwave Time-Of-Day value header */
+wkh_tod_value_header(openwave_x_up_proxy_tod,
+ "x-up-proxy-tod")
+
+/* Openwave accept_x_q header */
+wkh_accept_x_q_header(openwave_x_up_proxy_trans_charset,
+ "x-up-proxy-trans-charset",
+ vals_character_sets, "character set")
+
+/* Openwave content type header */
+wkh_content_type_header(openwave_x_up_proxy_push_accept,
+ "x-up-proxy-push-accept")
+
+/*
+ * Header value parameter parsing
+ */
+#define InvalidParameterValue(parameter,value) \
+ "<Error: Invalid " parameter " parameter value: invalid " value ">"
+
+
+
+
+
+#define parameter_text(hf,lowercase,Uppercase,value) \
+ DebugLog(("parameter with text_string value: " Uppercase "\n")); \
+ get_text_string(val_str, tvb, offset, val_len, ok); \
+ if (ok) { \
+ DebugLog(("OK, valid text_string value found!\n")); \
+ DebugLog(("Adding val_str to the header field in proto tree\n")); \
+ proto_tree_add_string(tree, hf, \
+ tvb, start, type_len + val_len, val_str); \
+ DebugLog(("Creating str to append to ti\n")); \
+ str = g_strdup_printf("; " lowercase "=%s", val_str); \
+ DebugLog(("Appending str to ti\n")); \
+ proto_item_append_string(ti, str); \
+ DebugLog(("\tFreeing str [%s]\n", str)); \
+ g_free(str); \
+ DebugLog(("\tFreeing val_str [%s]\n", val_str)); \
+ g_free(val_str); \
+ offset += val_len; \
+ } else { \
+ DebugLog(("\tError: invalid parameter value!\n")); \
+ proto_tree_add_string(tree, hf, tvb, start, len - start, \
+ InvalidParameterValue(Uppercase, value)); \
+ offset = start + len; /* Skip to end of buffer */ \
+ } \
+ DebugLog(("parameter with text_string value - END\n"));
+
+
+#define parameter_text_value(hf,lowercase,Uppercase,value) \
+ get_text_string(val_str, tvb, offset, val_len, ok); \
+ if (ok) { \
+ if (is_quoted_string(val_str[0])) { \
+ if (is_quoted_string(val_str[val_len-2])) { \
+ /* Trailing quote - issue a warning */ \
+ str = g_strdup_printf("%s" TrailingQuoteWarning, val_str); \
+ proto_tree_add_string(tree, hf, \
+ tvb, start, type_len + val_len, str); \
+ g_free(str); \
+ str = g_strdup_printf("; " lowercase "=%s", val_str); \
+ } else { /* OK (no trailing quote) */ \
+ str = g_strdup_printf("%s\"", val_str); \
+ proto_tree_add_string(tree, hf, \
+ tvb, start, type_len + val_len, str); \
+ g_free(str); \
+ str = g_strdup_printf("; " lowercase "=%s\"", val_str); \
+ } \
+ } else { /* Token-text | 0x00 */ \
+ /* TODO - verify that we have either Token-text or 0x00 */ \
+ proto_tree_add_string(tree, hf, \
+ tvb, start, type_len + val_len, val_str); \
+ str = g_strdup_printf("; " lowercase "=%s", val_str); \
+ } \
+ proto_item_append_string(ti, str); \
+ g_free(str); \
+ g_free(val_str); \
+ offset += val_len; \
+ } else { \
+ proto_tree_add_string(tree, hf, tvb, start, len - start, \
+ InvalidParameterValue(Uppercase, value)); \
+ offset = start + len; /* Skip to end of buffer */ \
+ }
+
+
+/* Parameter = Untyped-parameter | Typed-parameter
+ * Untyped-parameter = Token-text ( Integer-value | Text-value )
+ * Typed-parameter =
+ * Integer-value (
+ * ( Integer-value | Date-value | Delta-seconds-value
+ * | Q-value | Version-value | Uri-value )
+ * | Text-value )
+ *
+ *
+ * Returns: next offset
+ *
+ * TODO - Verify byte highlighting in case of invalid parameter values
+ */
+static int
+parameter (proto_tree *tree, proto_item *ti, tvbuff_t *tvb, int start, int len)
+{
+ int offset = start;
+ guint8 peek = tvb_get_guint8 (tvb,start);
+ guint32 val = 0, type = 0, type_len, val_len;
+ gchar *str = NULL;
+ gchar *val_str = NULL;
+ gchar *s;
+ gboolean ok;
+
+ DebugLog(("parameter(start = %u, len = %u)\n", start, len));
+ if (is_token_text (peek)) {
+ /*
+ * Untyped parameter
+ */
+ DebugLog(("parameter() - Untyped - Start\n"));
+ get_token_text (str,tvb,start,val_len,ok); /* Should always succeed */
+ if (ok) { /* Found a textual parameter name: str */
+ offset += val_len;
+ get_text_value(val_str, tvb, offset, val_len, ok);
+ if (ok) { /* Also found a textual parameter value: val_str */
+ DebugLog(("Trying textual parameter value.\n"));
+ offset += val_len;
+ if (is_quoted_string(val_str[0])) { /* Add trailing quote! */
+ if (is_quoted_string(val_str[val_len-2])) {
+ /* Trailing quote - issue a warning */
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "%s: %s" TrailingQuoteWarning, str, val_str);
+ s = g_strdup_printf("; %s=%s", str, val_str);
+ } else { /* OK (no trailing quote) */
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "%s: %s\"", str, val_str);
+ s = g_strdup_printf("; %s=%s\"", str, val_str);
+ }
+ } else { /* Token-text | 0x00 */
+ /* TODO - verify that it is either Token-text or 0x00
+ * and flag with warning if invalid */
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "%s: %s", str, val_str);
+ s = g_strdup_printf("; %s=%s", str, val_str);
+ }
+ /* TODO - check if we can insert a searchable field in the
+ * protocol tree for the untyped parameter case */
+ DebugLog(("parameter() - Untyped: %s\n", s));
+ proto_item_append_string(ti, s);
+ DebugLog(("Freeing s\n"));
+ g_free(s);
+ DebugLog(("Freeing val_str\n"));
+ g_free(val_str);
+ DebugLog(("Done!\n"));
+ } else { /* Try integer value */
+ DebugLog(("Trying integer parameter value.\n"));
+ get_integer_value (val,tvb,offset,val_len,ok);
+ if (ok) { /* Also found a valid integer parameter value: val */
+ offset += val_len;
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "%s: %u", str, val);
+ s = g_strdup_printf("; %s=%u", str, val);
+ proto_item_append_string(ti, s);
+ DebugLog(("parameter() - Untyped: %s\n", s));
+ g_free(s);
+ /* TODO - check if we can insert a searchable field in the
+ * protocol tree for the untyped parameter case */
+ } else { /* Error: neither token-text not Integer-value */
+ DebugLog(("Invalid untyped parameter value!\n"));
+ proto_tree_add_text (tree, tvb, start, offset - start,
+ "<Error: Invalid untyped parameter definition>");
+ offset = start + len; /* Skip to end of buffer */
+ }
+ }
+ g_free(str);
+ }
+ DebugLog(("parameter() - Untyped - End\n"));
+ return offset;
+ }
+ /*
+ * Else: Typed parameter
+ */
+ DebugLog(("parameter() - Typed - Start\n"));
+ get_integer_value (type,tvb,start,type_len,ok);
+ if (!ok) {
+ proto_tree_add_text (tree, tvb, start, offset - start,
+ "<Error: Invalid typed parameter definition>");
+ return (start + len); /* Skip to end of buffer */
+ }
+ offset += type_len;
+ /* Now offset points to the parameter value */
+ DebugLog(("Typed parameter = 0x%02x\n", type));
+ switch (type) {
+ case 0x01: /* WSP 1.1 encoding - Charset: Well-known-charset */
+ get_integer_value(val, tvb, offset, val_len, ok);
+ if (ok) {
+ val_str = val_to_str(val, vals_character_sets,
+ "<Unknown character set Identifier 0x%X>");
+ proto_tree_add_string(tree, hf_parameter_charset,
+ tvb, start, type_len + val_len, val_str);
+ str = g_strdup_printf("; charset=%s", val_str);
+ proto_item_append_string(ti, str);
+ g_free(str);
+ offset += val_len;
+ } else {
+ proto_tree_add_text (tree, tvb, start, offset,
+ InvalidParameterValue("Charset", "Integer-value"));
+ offset = start + len; /* Skip to end of buffer */
+ }
+ break;
+
+ case 0x03: /* WSP 1.1 encoding - Type: Integer-value */
+ get_integer_value (val,tvb,offset,val_len,ok);
+ if (ok) {
+ proto_tree_add_uint (tree, hf_wsp_parameter_type,
+ tvb, start, type_len + val_len, val);
+ s = g_strdup_printf("; Type=%u", val);
+ proto_item_append_string (ti, s);
+ g_free(s);
+ offset += val_len;
+ } else {
+ proto_tree_add_text (tree, tvb, start, offset,
+ InvalidParameterValue("Type", "Integer-value"));
+ offset = start + len; /* Skip to end of buffer */
+ }
+ break;
+
+ case 0x05: /* WSP 1.1 encoding - Name: Text-string */
+ parameter_text(hf_wsp_parameter_name, "name",
+ "Name (WSP 1.1 encoding)", "Text-string");
+ break;
+ case 0x17: /* WSP 1.4 encoding - Name: Text-value */
+ parameter_text_value(hf_wsp_parameter_name, "name",
+ "Name (WSP 1.4 encoding)", "Text-value");
+ break;
+
+ case 0x06: /* WSP 1.1 encoding - Filename: Text-string */
+ parameter_text(hf_wsp_parameter_filename, "filename",
+ "Filename (WSP 1.1 encoding)", "Text-string");
+ break;
+ case 0x18: /* WSP 1.4 encoding - Filename: Text-value */
+ parameter_text_value(hf_wsp_parameter_filename, "filename",
+ "Filename (WSP 1.4 encoding)", "Text-value");
+ break;
+
+ case 0x09: /* WSP 1.2 encoding - Type (special): Constrained-encoding */
+ /* This is similar to the Content-Type header decoding,
+ * but it is much simpler:
+ * Constrained-encoding = Short-integer | Extension-media
+ * Extension-media = *TEXT <Octet 0>
+ */
+ get_extension_media(val_str,tvb,offset,val_len,ok);
+ if (ok) { /* Extension-media */
+ offset += val_len;
+ } else {
+ get_short_integer(val,tvb,offset,val_len,ok);
+ if (ok) {
+ offset += val_len;
+ val_str = val_to_str(val, vals_content_types,
+ "(Unknown content type identifier 0x%X)");
+ } /* Else: invalid parameter value */
+ }
+ if (ok) {
+ proto_tree_add_string (tree, hf_wsp_parameter_upart_type,
+ tvb, start, offset - start, val_str);
+ str = g_strdup_printf("; type=%s", val_str);
+ proto_item_append_string(ti, str);
+ g_free(str);
+ } else { /* Invalid parameter value */
+ proto_tree_add_text (tree, tvb, start, len - start,
+ InvalidParameterValue("Type",
+ "Constrained-encoding"));
+ offset = start + len; /* Skip the parameters */
+ }
+ break;
+
+ case 0x0A: /* WSP 1.2 encoding - Start: Text-string */
+ parameter_text(hf_wsp_parameter_start, "start",
+ "Start (WSP 1.2 encoding)", "Text-string");
+ break;
+ case 0x19: /* WSP 1.4 encoding - Start (with multipart/related): Text-value */
+ parameter_text_value(hf_wsp_parameter_start, "start",
+ "Start (WSP 1.4 encoding)", "Text-value");
+ break;
+
+ case 0x0B: /* WSP 1.2 encoding - Start-info: Text-string */
+ parameter_text(hf_wsp_parameter_start_info, "start-info",
+ "Start-info (WSP 1.2 encoding)", "Text-string");
+ break;
+ case 0x1A: /* WSP 1.4 encoding - Start-info (with multipart/related): Text-value */
+ parameter_text_value(hf_wsp_parameter_start_info, "start-info",
+ "Start-info (WSP 1.4 encoding)", "Text-value");
+ break;
+
+ case 0x0C: /* WSP 1.3 encoding - Comment: Text-string */
+ parameter_text(hf_wsp_parameter_comment, "comment",
+ "Comment (WSP 1.3 encoding)", "Text-string");
+ break;
+ case 0x1B: /* WSP 1.4 encoding - Comment: Text-value */
+ parameter_text_value(hf_wsp_parameter_comment, "comment",
+ "Comment (WSP 1.4 encoding)", "Text-value");
+ break;
+
+ case 0x0D: /* WSP 1.3 encoding - Domain: Text-string */
+ parameter_text(hf_wsp_parameter_domain, "domain",
+ "Domain (WSP 1.3 encoding)", "Text-string");
+ break;
+ case 0x1C: /* WSP 1.4 encoding - Domain: Text-value */
+ parameter_text_value(hf_wsp_parameter_domain, "domain",
+ "Domain (WSP 1.4 encoding)", "Text-value");
+ break;
+
+ case 0x0F: /* WSP 1.3 encoding - Path: Text-string */
+ parameter_text(hf_wsp_parameter_path, "path",
+ "Path (WSP 1.3 encoding)", "Text-string");
+ break;
+ case 0x1D: /* WSP 1.4 encoding - Path: Text-value */
+ parameter_text_value(hf_wsp_parameter_path, "path",
+ "Path (WSP 1.4 encoding)", "Text-value");
+ break;
+
+ case 0x11: /* WSP 1.4 encoding - SEC: Short-integer (OCTET) */
+ peek = tvb_get_guint8 (tvb, start+1);
+ if (peek & 0x80) { /* Valid Short-integer */
+ peek &= 0x7F;
+ proto_tree_add_uint (tree, hf_wsp_parameter_sec,
+ tvb, start, 2, peek);
+ str = match_strval(peek, vals_wsp_parameter_sec);
+ s = g_strdup_printf("; SEC=%s", str);
+ proto_item_append_string (ti, s);
+ g_free(s);
+ offset++;
+ } else { /* Error */
+ proto_tree_add_text (tree, tvb, start, len - start,
+ InvalidParameterValue("SEC", "Short-integer"));
+ offset = start + len; /* Skip to end of buffer */
+ }
+ break;
+
+ case 0x12: /* WSP 1.4 encoding - MAC: Text-value */
+ parameter_text_value(hf_wsp_parameter_mac, "MAC",
+ "MAC", "Text-value");
+ break;
+
+ case 0x02: /* WSP 1.1 encoding - Level: Version-value */
+ get_version_value(val,str,tvb,offset,val_len,ok);
+ if (ok) {
+ proto_tree_add_string (tree, hf_wsp_parameter_level,
+ tvb, start, type_len + val_len, str);
+ s = g_strdup_printf("; level=%s", str);
+ proto_item_append_string (ti, s);
+ g_free(s);
+ offset += val_len;
+ } else {
+ proto_tree_add_text (tree, tvb, start, len - start,
+ InvalidParameterValue("Level", "Version-value"));
+ offset = start + len; /* Skip to end of buffer */
+ }
+ break;
+
+ case 0x00: /* WSP 1.1 encoding - Q: Q-value */
+ offset = parameter_value_q(tree, ti, tvb, offset);
+ break;
+
+ case 0x16: /* WSP 1.4 encoding - Size: Integer-value */
+ get_integer_value (val,tvb,offset,val_len,ok);
+ if (ok) {
+ proto_tree_add_uint (tree, hf_wsp_parameter_size,
+ tvb, start, type_len + val_len, val);
+ s = g_strdup_printf("; Size=%u", val);
+ proto_item_append_string (ti, s);
+ g_free(s);
+ offset += val_len;
+ } else {
+ proto_tree_add_text (tree, tvb, start, offset,
+ InvalidParameterValue("Size", "Integer-value"));
+ offset = start + len; /* Skip to end of buffer */
+ }
+ break;
+
+ /*
+ * TODO
+ */
+
+ case 0x07: /* WSP 1.1 encoding - Differences: Field-name */
+ DebugLog(("Skipping remaining parameters from here\n"));
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "Undecoded parameter Differences - decoding stopped");
+ break;
+
+ case 0x08: /* WSP 1.1 encoding - Padding: Short-integer */
+ DebugLog(("Skipping remaining parameters from here\n"));
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "Undecoded parameter Padding - decoding stopped");
+ break;
+
+ case 0x0E: /* WSP 1.3 encoding - Max-Age: Delta-seconds-value */
+ DebugLog(("Skipping remaining parameters from here\n"));
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "Undecoded parameter Max-Age - decoding stopped");
+ break;
+
+ case 0x10: /* WSP 1.3 encoding - Secure: No-value */
+ DebugLog(("Skipping remaining parameters from here\n"));
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "Undecoded parameter Secure - decoding stopped");
+ break;
+
+ case 0x13: /* WSP 1.4 encoding - Creation-date: Date-value */
+ DebugLog(("Skipping remaining parameters from here\n"));
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "Undecoded parameter Creation-Date - decoding stopped");
+ break;
+
+ case 0x14: /* WSP 1.4 encoding - Modification-date: Date-value */
+ DebugLog(("Skipping remaining parameters from here\n"));
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "Undecoded parameter Modification-Date - decoding stopped");
+ break;
+
+ case 0x15: /* WSP 1.4 encoding - Read-date: Date-value */
+ DebugLog(("Skipping remaining parameters from here\n"));
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "Undecoded parameter Read-Date - decoding stopped");
+ break;
+
+ default:
+ DebugLog(("Skipping remaining parameters from here\n"));
+ proto_tree_add_text(tree, tvb, start, offset - start,
+ "Undecoded parameter type 0x%02x - decoding stopped",
+ type);
+ offset = start + len; /* Skip the parameters */
+ break;
+ }
+ DebugLog(("parameter() - Typed - End\n"));
+ return offset;
+}
+
+
+/*
+ * Dissects the Q-value parameter value.
+ *
+ * Returns: next offset
+ */
+static int
+parameter_value_q (proto_tree *tree, proto_item *ti, tvbuff_t *tvb, int start)
+{
+ int offset = start;
+ guint32 val = 0, val_len;
+ gchar *str = NULL, *s = NULL;
+ guint8 ok;
+
+ get_uintvar_integer (val, tvb, offset, val_len, ok);
+ if (ok && (val < 1100)) {
+ if (val <= 100) { /* Q-value in 0.01 steps */
+ str = g_strdup_printf("0.%02u", val - 1);
+ } else { /* Q-value in 0.001 steps */
+ str = g_strdup_printf("0.%03u", val - 100);
+ }
+ s = g_strdup_printf("; q=%s", str);
+ proto_item_append_string (ti, s);
+ g_free(s);
+ proto_tree_add_string (tree, hf_parameter_q,
+ tvb, start, val_len, str);
+ g_free(str);
+ offset += val_len;
+ } else {
+ proto_tree_add_text (tree, tvb, start, offset,
+ InvalidParameterValue("Q", "Q-value"));
+ offset += val_len;
+ }
+ return offset;
+}
+
+
+/* Code to actually dissect the packets */
+
+/*
+ * WSP redirect
+ */
+
+/* Dissect a WSP redirect PDU.
+ * Looks up or builds conversations, so parts of the code must always run,
+ * even if tree is NULL.
+ */
+static void
+dissect_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *tree, dissector_handle_t dissector_handle)
+{
+ guint8 flags;
+ proto_item *ti;
+ proto_tree *addresses_tree = NULL;
+ proto_tree *addr_tree = NULL;
+ proto_tree *flags_tree;
+ guint8 bearer_type;
+ guint8 address_flags_len;
+ int address_len;
+ proto_tree *address_flags_tree;
+ guint16 port_num;
+ guint32 address_ipv4;
+ struct e_in6_addr address_ipv6;
+ address redir_address;
+ conversation_t *conv;
+ guint32 index = 0; /* Address index */
+
+ /*
+ * Redirect flags.
+ */
+ flags = tvb_get_guint8 (tvb, offset);
+ if (tree) {
+ ti = proto_tree_add_uint (tree, hf_wsp_redirect_flags,
+ tvb, offset, 1, flags);
+ flags_tree = proto_item_add_subtree (ti, ett_redirect_flags);
+ proto_tree_add_boolean (flags_tree, hf_wsp_redirect_permanent,
+ tvb, offset, 1, flags);
+ proto_tree_add_boolean (flags_tree, hf_wsp_redirect_reuse_security_session,
+ tvb, offset, 1, flags);
+ }
+ offset++;
+
+ /*
+ * Redirect addresses.
+ */
+ if (tree) {
+ ti = proto_tree_add_item(tree, hf_redirect_addresses,
+ tvb, 0, -1, bo_little_endian);
+ addresses_tree = proto_item_add_subtree(ti, ett_addresses);
+ }
+
+ while (tvb_reported_length_remaining (tvb, offset) > 0) {
+ index++;
+ /*
+ * Read a single address at a time.
+ */
+ address_flags_len = tvb_get_guint8 (tvb, offset);
+ address_len = address_flags_len & ADDRESS_LEN;
+ if (tree) {
+
+ ti = proto_tree_add_uint(addresses_tree, hf_address_entry,
+ tvb, offset, 1 + address_len, index);
+ addr_tree = proto_item_add_subtree(ti, ett_address);
+
+ ti = proto_tree_add_uint (addr_tree, hf_address_flags_length,
+ tvb, offset, 1, address_flags_len);
+ address_flags_tree = proto_item_add_subtree (ti, ett_address_flags);
+ proto_tree_add_boolean (address_flags_tree, hf_address_flags_length_bearer_type_included,
+ tvb, offset, 1, address_flags_len);
+ proto_tree_add_boolean (address_flags_tree, hf_address_flags_length_port_number_included,
+ tvb, offset, 1, address_flags_len);
+ proto_tree_add_uint (address_flags_tree, hf_address_flags_length_address_len,
+ tvb, offset, 1, address_flags_len);
+ }
+ offset++;
+ if (address_flags_len & BEARER_TYPE_INCLUDED) {
+ bearer_type = tvb_get_guint8 (tvb, offset);
+ if (tree) {
+ proto_tree_add_uint (addr_tree, hf_address_bearer_type,
+ tvb, offset, 1, bearer_type);
+ }
+ offset++;
+ } else {
+ bearer_type = 0x00; /* XXX */
+ }
+ if (address_flags_len & PORT_NUMBER_INCLUDED) {
+ port_num = tvb_get_ntohs (tvb, offset);
+ if (tree) {
+ proto_tree_add_uint (addr_tree, hf_address_port_num,
+ tvb, offset, 2, port_num);
+ }
+ offset += 2;
+ } else {
+ /*
+ * Redirecting to the same server port number as was
+ * being used, i.e. the source port number of this
+ * redirect.
+ */
+ port_num = pinfo->srcport;
+ }
+ if (!(address_flags_len & BEARER_TYPE_INCLUDED)) {
+ /*
+ * We don't have the bearer type in the message,
+ * so we don't know the address type.
+ * (It's the same bearer type as the original
+ * connection.)
+ */
+ goto unknown_address_type;
+ }
+
+ /*
+ * We know the bearer type, so we know the address type.
+ */
+ switch (bearer_type) {
+
+ case BT_IPv4:
+ case BT_IS_95_CSD:
+ case BT_IS_95_PACKET_DATA:
+ case BT_ANSI_136_CSD:
+ case BT_ANSI_136_PACKET_DATA:
+ case BT_GSM_CSD:
+ case BT_GSM_GPRS:
+ case BT_GSM_USSD_IPv4:
+ case BT_AMPS_CDPD:
+ case BT_PDC_CSD:
+ case BT_PDC_PACKET_DATA:
+ case BT_IDEN_CSD:
+ case BT_IDEN_PACKET_DATA:
+ case BT_PHS_CSD:
+ case BT_TETRA_PACKET_DATA:
+ /*
+ * IPv4.
+ */
+ if (address_len != 4) {
+ /*
+ * Say what?
+ */
+ goto unknown_address_type;
+ }
+ tvb_memcpy(tvb, (guint8 *)&address_ipv4, offset, 4);
+ if (tree) {
+ proto_tree_add_ipv4 (addr_tree,
+ hf_address_ipv4_addr,
+ tvb, offset, 4, address_ipv4);
+ }
+
+ /*
+ * Create a conversation so that the
+ * redirected session will be dissected
+ * as WAP.
+ */
+ redir_address.type = AT_IPv4;
+ redir_address.len = 4;
+ redir_address.data = (const guint8 *)&address_ipv4;
+ /* Find a conversation based on redir_address and pinfo->dst */
+ conv = find_conversation(&redir_address, &pinfo->dst,
+ PT_UDP, port_num, 0, NO_PORT_B);
+ if (conv == NULL) { /* This conversation does not exist yet */
+ conv = conversation_new(&redir_address,
+ &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
+ }
+ /* Apply WSP dissection to the conversation */
+ conversation_set_dissector(conv, dissector_handle);
+ break;
+
+ case BT_IPv6:
+ /*
+ * IPv6.
+ */
+ if (address_len != 16) {
+ /*
+ * Say what?
+ */
+ goto unknown_address_type;
+ }
+ tvb_memcpy(tvb, (guint8 *)&address_ipv6, offset, 16);
+ if (tree) {
+ proto_tree_add_ipv6 (addr_tree,
+ hf_address_ipv6_addr,
+ tvb, offset, 16, (guint8 *)&address_ipv6);
+ }
+
+ /*
+ * Create a conversation so that the
+ * redirected session will be dissected
+ * as WAP.
+ */
+ redir_address.type = AT_IPv6;
+ redir_address.len = 16;
+ redir_address.data = (const guint8 *)&address_ipv4;
+ /* Find a conversation based on redir_address and pinfo->dst */
+ conv = find_conversation(&redir_address, &pinfo->dst,
+ PT_UDP, port_num, 0, NO_PORT_B);
+ if (conv == NULL) { /* This conversation does not exist yet */
+ conv = conversation_new(&redir_address,
+ &pinfo->dst, PT_UDP, port_num, 0, NO_PORT2);
+ }
+ /* Apply WSP dissection to the conversation */
+ conversation_set_dissector(conv, dissector_handle);
+ break;
+
+ unknown_address_type:
+ default:
+ if (address_len != 0) {
+ if (tree) {
+ proto_tree_add_item (addr_tree, hf_address_addr,
+ tvb, offset, address_len, bo_little_endian);
+ }
+ }
+ break;
+ }
+ offset += address_len;
+ } /* while */
+}
+
+/* Add addresses to the protocol tree.
+ * This is a display-only function, so return if tree is NULL
+ */
+static void
+add_addresses(proto_tree *tree, tvbuff_t *tvb, int hf)
+{
+ proto_item *ti;
+ proto_tree *addresses_tree;
+ proto_tree *addr_tree;
+ guint8 bearer_type;
+ guint8 address_flags_len;
+ int address_len;
+ proto_tree *address_flags_tree;
+ guint16 port_num;
+ guint32 address_ipv4;
+ struct e_in6_addr address_ipv6;
+ guint32 tvb_len = tvb_length(tvb);
+ guint32 offset = 0;
+ guint32 index = 0; /* Address index */
+
+ /* Skip needless processing */
+ if (! tree)
+ return;
+ if (offset >= tvb_len)
+ return;
+
+ /*
+ * Addresses.
+ */
+ ti = proto_tree_add_item(tree, hf, tvb, 0, -1, bo_little_endian);
+ addresses_tree = proto_item_add_subtree(ti, ett_addresses);
+
+ while (offset < tvb_len) {
+ index++;
+ /*
+ * Read a single address at a time.
+ */
+ address_flags_len = tvb_get_guint8 (tvb, offset);
+ address_len = address_flags_len & ADDRESS_LEN;
+
+ ti = proto_tree_add_uint(addresses_tree, hf_address_entry,
+ tvb, offset, 1 + address_len, index);
+ addr_tree = proto_item_add_subtree(ti, ett_address);
+
+ ti = proto_tree_add_uint (addr_tree, hf_address_flags_length,
+ tvb, offset, 1, address_flags_len);
+ address_flags_tree = proto_item_add_subtree (ti, ett_address_flags);
+ proto_tree_add_boolean (address_flags_tree, hf_address_flags_length_bearer_type_included,
+ tvb, offset, 1, address_flags_len);
+ proto_tree_add_boolean (address_flags_tree, hf_address_flags_length_port_number_included,
+ tvb, offset, 1, address_flags_len);
+ proto_tree_add_uint (address_flags_tree, hf_address_flags_length_address_len,
+ tvb, offset, 1, address_flags_len);
+ offset++;
+ if (address_flags_len & BEARER_TYPE_INCLUDED) {
+ bearer_type = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_uint (addr_tree, hf_address_bearer_type,
+ tvb, offset, 1, bearer_type);
+ offset++;
+ } else {
+ bearer_type = 0x00; /* XXX */
+ }
+ if (address_flags_len & PORT_NUMBER_INCLUDED) {
+ port_num = tvb_get_ntohs (tvb, offset);
+ proto_tree_add_uint (addr_tree, hf_address_port_num,
+ tvb, offset, 2, port_num);
+ offset += 2;
+ } else {
+ /*
+ * Redirecting to the same server port number as was
+ * being used, i.e. the source port number of this
+ * redirect.
+ */
+ port_num = 0;
+ }
+ if (!(address_flags_len & BEARER_TYPE_INCLUDED)) {
+ /*
+ * We don't have the bearer type in the message,
+ * so we don't know the address type.
+ * (It's the same bearer type as the original
+ * connection.)
+ */
+ goto unknown_address_type;
+ }
+
+ /*
+ * We know the bearer type, so we know the address type.
+ */
+ switch (bearer_type) {
+
+ case BT_IPv4:
+ case BT_IS_95_CSD:
+ case BT_IS_95_PACKET_DATA:
+ case BT_ANSI_136_CSD:
+ case BT_ANSI_136_PACKET_DATA:
+ case BT_GSM_CSD:
+ case BT_GSM_GPRS:
+ case BT_GSM_USSD_IPv4:
+ case BT_AMPS_CDPD:
+ case BT_PDC_CSD:
+ case BT_PDC_PACKET_DATA:
+ case BT_IDEN_CSD:
+ case BT_IDEN_PACKET_DATA:
+ case BT_PHS_CSD:
+ case BT_TETRA_PACKET_DATA:
+ /*
+ * IPv4.
+ */
+ if (address_len != 4) {
+ /*
+ * Say what?
+ */
+ goto unknown_address_type;
+ }
+ tvb_memcpy(tvb, (guint8 *)&address_ipv4, offset, 4);
+ proto_tree_add_ipv4 (addr_tree, hf_address_ipv4_addr,
+ tvb, offset, 4, address_ipv4);
+ break;
+
+ case BT_IPv6:
+ /*
+ * IPv6.
+ */
+ if (address_len != 16) {
+ /*
+ * Say what?
+ */
+ goto unknown_address_type;
+ }
+ tvb_memcpy(tvb, (guint8 *)&address_ipv6, offset, 16);
+ proto_tree_add_ipv6 (addr_tree, hf_address_ipv6_addr,
+ tvb, offset, 16, (guint8 *)&address_ipv6);
+ break;
+
+ unknown_address_type:
+ default:
+ if (address_len != 0) {
+ proto_tree_add_item (addr_tree, hf_address_addr,
+ tvb, offset, address_len, bo_little_endian);
+ }
+ break;
+ }
+ offset += address_len;
+ } /* while */
+}
+
+static const value_string vals_sir_protocol_options[] = {
+ { 0, "OTA-HTTP, no CPITag present" },
+ { 1, "OTA-HTTP, CPITag present" },
+ /* 2--255 are reserved */
+ /* 256--16383 are available for private WINA registration */
+
+ { 0x00, NULL }
+};
+
+/* Dissect a Session Initiation Request.
+ *
+ * Arguably this should be a separate dissector, but SIR does not make sense
+ * outside of WSP anyway.
+ */
+static void
+dissect_sir(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint8 version;
+ guint32 val_len;
+ guint32 len;
+ guint32 offset = 0;
+ guint32 i;
+ tvbuff_t *tmp_tvb;
+ proto_tree *subtree;
+ proto_item *ti;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ { /* Append status code to INFO column */
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ": WAP Session Initiation Request");
+ }
+
+ /* The remainder of the code adds items to the protocol tree */
+ if (! tree)
+ return;
+
+ ti = proto_tree_add_item(tree, hf_sir_section,
+ tvb, 0, -1, bo_little_endian);
+ subtree = proto_item_add_subtree(ti, ett_sir);
+
+ /* Version */
+ version = tvb_get_guint8(tvb, 0);
+ proto_tree_add_uint(subtree, hf_sir_version,
+ tvb, 0, 1, version);
+
+ /* Length of Application-Id headers list */
+ val_len = tvb_get_guintvar(tvb, 1, &len);
+ proto_tree_add_uint(subtree, hf_sir_app_id_list_len,
+ tvb, 1, len, val_len);
+ offset = 1 + len;
+ /* Application-Id headers */
+ tmp_tvb = tvb_new_subset(tvb, offset, val_len, val_len);
+ add_headers (subtree, tmp_tvb, hf_sir_app_id_list, pinfo);
+ offset += val_len;
+
+ /* Length of WSP contact points list */
+ val_len = tvb_get_guintvar(tvb, offset, &len);
+ proto_tree_add_uint(subtree, hf_sir_wsp_contact_points_len,
+ tvb, offset, len, val_len);
+ offset += len;
+ /* WSP contact point list */
+ tmp_tvb = tvb_new_subset (tvb, offset, val_len, val_len);
+ add_addresses(subtree, tmp_tvb, hf_sir_wsp_contact_points);
+ g_free(tmp_tvb);
+
+ /* End of version 0 SIR content */
+ if (version == 0)
+ return;
+
+ /* Length of non-WSP contact points list */
+ val_len = tvb_get_guintvar(tvb, offset, &len);
+ proto_tree_add_uint(subtree, hf_sir_contact_points_len,
+ tvb, offset, len, val_len);
+ offset += len;
+ /* Non-WSP contact point list */
+ tmp_tvb = tvb_new_subset (tvb, offset, val_len, val_len);
+ add_addresses(subtree, tmp_tvb, hf_sir_contact_points);
+ g_free(tmp_tvb);
+
+ /* Number of entries in the Protocol Options list */
+ val_len = tvb_get_guintvar(tvb, offset, &len);
+ proto_tree_add_uint(subtree, hf_sir_protocol_options_len,
+ tvb, offset, len, val_len);
+ offset += len;
+ /* Protocol Options list.
+ * Each protocol option is encoded as a guintvar */
+ for (i = 0; i < val_len; i++) {
+ val_len = tvb_get_guintvar(tvb, offset, &len);
+ proto_tree_add_uint(subtree, hf_sir_protocol_options,
+ tvb, offset, len, val_len);
+ offset += len;
+ }
+
+ /* Length of ProvURL */
+ val_len = tvb_get_guintvar(tvb, offset, &len);
+ proto_tree_add_uint(subtree, hf_sir_prov_url_len,
+ tvb, offset, len, val_len);
+ offset += len;
+ /* ProvURL */
+ tvb_ensure_bytes_exist(tvb, offset, val_len);
+ ti = proto_tree_add_item (tree, hf_sir_prov_url,
+ tvb, offset, val_len, bo_little_endian);
+ offset += val_len;
+
+ /* Number of entries in the CPITag list */
+ val_len = tvb_get_guintvar(tvb, offset, &len);
+ proto_tree_add_uint(subtree, hf_sir_cpi_tag_len,
+ tvb, offset, len, val_len);
+ offset += len;
+ /* CPITag list.
+ * Each CPITag is encoded as 4 octets of opaque data.
+ * In OTA-HTTP, it is conveyed in the X-Wap-CPITag header
+ * but with a Base64 encoding of the 4 bytes. */
+ for (i = 0; i < val_len; i++) {
+ val_len = tvb_get_guintvar(tvb, offset, &len);
+ proto_tree_add_item(subtree, hf_sir_cpi_tag,
+ tvb, offset, 4, val_len);
+ offset += 4;
+ }
+}
+
+static void
+dissect_wsp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ dissector_handle_t dissector_handle, gboolean is_connectionless)
+{
+ int offset = 0;
+
+ guint8 pdut;
+ guint count = 0;
+ guint value = 0;
+ guint uriLength = 0;
+ guint uriStart = 0;
+ guint capabilityLength = 0;
+ guint capabilityStart = 0;
+ guint headersLength = 0;
+ guint headerLength = 0;
+ guint headerStart = 0;
+ guint nextOffset = 0;
+ guint contentTypeStart = 0;
+ guint contentType = 0;
+ const char *contentTypeStr;
+ tvbuff_t *tmp_tvb;
+ gboolean found_match;
+
+/* Set up structures we will need to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_item *proto_ti = NULL; /* for the proto entry */
+ proto_tree *wsp_tree = NULL;
+
+ wsp_info_value_t *stat_info;
+ stat_info = g_malloc( sizeof(wsp_info_value_t) );
+ stat_info->status_code = 0;
+
+/* This field shows up as the "Info" column in the display; you should make
+ it, if possible, summarize what's in the packet, so that a user looking
+ at the list of packets can tell what type of packet it is. */
+
+ /* Connection-less mode has a TID first */
+ if (is_connectionless)
+ {
+ offset++; /* Skip the 1-byte Transaction ID */
+ };
+
+ /* Find the PDU type */
+ pdut = tvb_get_guint8 (tvb, offset);
+
+ /* Develop the string to put in the Info column */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "WSP %s (0x%02x)",
+ val_to_str (pdut, vals_pdu_type, "Unknown PDU type (0x%02x)"),
+ pdut);
+ };
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ * necessary to generate protocol tree items. */
+ if (tree) {
+ proto_ti = proto_tree_add_item(tree, proto_wsp,
+ tvb, 0, -1, bo_little_endian);
+ wsp_tree = proto_item_add_subtree(proto_ti, ett_wsp);
+ proto_item_append_text(proto_ti, ", Method: %s (0x%02x)",
+ val_to_str (pdut, vals_pdu_type, "Unknown (0x%02x)"),
+ pdut);
+
+ /* Add common items: only TID and PDU Type */
+
+ /* If this is connectionless, then the TID Field is always first */
+ if (is_connectionless)
+ {
+ ti = proto_tree_add_item (wsp_tree, hf_wsp_header_tid,
+ tvb, 0, 1, bo_little_endian);
+ }
+ ti = proto_tree_add_item( wsp_tree, hf_wsp_header_pdu_type,
+ tvb, offset, 1, bo_little_endian);
+ }
+ offset++;
+
+ /* Map extended methods to the main method now the Column info has been
+ * written; this way we can dissect the extended method PDUs. */
+ if ((pdut >= 0x50) && (pdut <= 0x5F)) /* Extended GET --> GET */
+ pdut = WSP_PDU_GET;
+ else if ((pdut >= 0x70) && (pdut <= 0x7F)) /* Extended POST --> POST */
+ pdut = WSP_PDU_POST;
+
+ switch (pdut)
+ {
+ case WSP_PDU_CONNECT:
+ case WSP_PDU_CONNECTREPLY:
+ case WSP_PDU_RESUME:
+ if (tree) {
+ if (pdut == WSP_PDU_CONNECT)
+ {
+ ti = proto_tree_add_item (wsp_tree, hf_wsp_version_major,
+ tvb, offset, 1, bo_little_endian);
+ ti = proto_tree_add_item (wsp_tree, hf_wsp_version_minor,
+ tvb, offset, 1, bo_little_endian);
+ {
+ guint8 ver = tvb_get_guint8(tvb, offset);
+ proto_item_append_text(proto_ti, ", Version: %u.%u",
+ ver >> 4, ver & 0x0F);
+ }
+ offset++;
+ } else {
+ count = 0; /* Initialise count */
+ value = tvb_get_guintvar (tvb, offset, &count);
+ ti = proto_tree_add_uint (wsp_tree,
+ hf_wsp_server_session_id,
+ tvb, offset, count, value);
+ proto_item_append_text(proto_ti, ", Session ID: %u", value);
+ offset += count;
+ }
+ capabilityStart = offset;
+ count = 0; /* Initialise count */
+ capabilityLength = tvb_get_guintvar (tvb, offset, &count);
+ offset += count;
+ ti = proto_tree_add_uint (wsp_tree, hf_capabilities_length,
+ tvb, capabilityStart, count, capabilityLength);
+
+ if (pdut != WSP_PDU_RESUME)
+ {
+ count = 0; /* Initialise count */
+ headerLength = tvb_get_guintvar (tvb, offset, &count);
+ ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,
+ tvb, offset, count, headerLength);
+ offset += count;
+ capabilityStart = offset;
+ headerStart = capabilityStart + capabilityLength;
+ } else {
+ /* Resume computes the headerlength
+ * by remaining bytes */
+ capabilityStart = offset;
+ headerStart = capabilityStart + capabilityLength;
+ headerLength = tvb_reported_length_remaining (tvb,
+ headerStart);
+ }
+ if (capabilityLength > 0)
+ {
+ tmp_tvb = tvb_new_subset (tvb, offset,
+ capabilityLength, capabilityLength);
+ add_capabilities (wsp_tree, tmp_tvb, pdut);
+ offset += capabilityLength;
+ }
+
+ if (headerLength > 0)
+ {
+ tmp_tvb = tvb_new_subset (tvb, offset,
+ headerLength, headerLength);
+ add_headers (wsp_tree, tmp_tvb, hf_wsp_headers_section, pinfo);
+ }
+ } /* if (tree) */
+
+ break;
+
+ case WSP_PDU_REDIRECT:
+ dissect_redirect(tvb, offset, pinfo, wsp_tree, dissector_handle);
+ break;
+
+ case WSP_PDU_DISCONNECT:
+ case WSP_PDU_SUSPEND:
+ if (tree) {
+ count = 0; /* Initialise count */
+ value = tvb_get_guintvar (tvb, offset, &count);
+ ti = proto_tree_add_uint (wsp_tree,
+ hf_wsp_server_session_id,
+ tvb, offset, count, value);
+ proto_item_append_text(proto_ti, ", Session ID: %u", value);
+ }
+ break;
+
+ case WSP_PDU_GET:
+ case WSP_PDU_OPTIONS:
+ case WSP_PDU_HEAD:
+ case WSP_PDU_DELETE:
+ case WSP_PDU_TRACE:
+ count = 0; /* Initialise count */
+ /* Length of URI and size of URILen field */
+ value = tvb_get_guintvar (tvb, offset, &count);
+ nextOffset = offset + count;
+ add_uri (wsp_tree, pinfo, tvb, offset, nextOffset, proto_ti);
+ if (tree) {
+ offset += value + count; /* VERIFY */
+ tmp_tvb = tvb_new_subset (tvb, offset, -1, -1);
+ add_headers (wsp_tree, tmp_tvb, hf_wsp_headers_section, pinfo);
+ }
+ break;
+
+ case WSP_PDU_POST:
+ case WSP_PDU_PUT:
+ uriStart = offset;
+ count = 0; /* Initialise count */
+ uriLength = tvb_get_guintvar (tvb, offset, &count);
+ headerStart = uriStart+count;
+ count = 0; /* Initialise count */
+ headersLength = tvb_get_guintvar (tvb, headerStart, &count);
+ offset = headerStart + count;
+
+ add_uri (wsp_tree, pinfo, tvb, uriStart, offset, proto_ti);
+ offset += uriLength;
+
+ if (tree)
+ ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,
+ tvb, headerStart, count, headersLength);
+
+ /* Stop processing POST PDU if length of headers is zero;
+ * this should not happen as we expect at least Content-Type. */
+ if (headersLength == 0)
+ break;
+
+ contentTypeStart = offset;
+ nextOffset = add_content_type (wsp_tree,
+ tvb, offset, &contentType, &contentTypeStr);
+
+ if (tree) {
+ /* Add content type to protocol summary line */
+ if (contentTypeStr) {
+ proto_item_append_text(proto_ti, ", Content-Type: %s",
+ contentTypeStr);
+ } else {
+ proto_item_append_text(proto_ti, ", Content-Type: 0x%X",
+ contentType);
+ }
+
+ /* Add headers subtree that will hold the headers fields */
+ /* Runs from nextOffset for
+ * headersLength - (length of content-type field) */
+ headerLength = headersLength - (nextOffset - contentTypeStart);
+ if (headerLength > 0)
+ {
+ tmp_tvb = tvb_new_subset (tvb, nextOffset,
+ headerLength, headerLength);
+ add_headers (wsp_tree, tmp_tvb, hf_wsp_headers_section, pinfo);
+ }
+ /* XXX - offset is no longer used after this point */
+ offset = nextOffset+headerLength;
+ }
+ /* WSP_PDU_POST data - First check whether a subdissector exists
+ * for the content type */
+ if (tvb_reported_length_remaining(tvb,
+ headerStart + count + uriLength + headersLength) > 0)
+ {
+ tmp_tvb = tvb_new_subset (tvb,
+ headerStart + count + uriLength + headersLength,
+ -1, -1);
+ /*
+ * Try finding a dissector for the content
+ * first, then fallback.
+ */
+ found_match = FALSE;
+ if (contentTypeStr) {
+ /*
+ * Content type is a string.
+ */
+ found_match = dissector_try_string(media_type_table,
+ contentTypeStr, tmp_tvb, pinfo, tree);
+ }
+ if (! found_match) {
+ if (! dissector_try_heuristic(heur_subdissector_list,
+ tmp_tvb, pinfo, tree)) {
+ guint8* save_private_data = pinfo->private_data;
+
+ pinfo->match_string = contentTypeStr;
+ pinfo->private_data = NULL; /* TODO: parameters */
+ call_dissector(media_handle, tmp_tvb, pinfo, tree);
+ pinfo->private_data = save_private_data;
+#if 0
+ if (tree) /* Only display if needed */
+ add_post_data (wsp_tree, tmp_tvb,
+ contentType, contentTypeStr, pinfo);
+#endif
+ }
+ }
+ }
+ break;
+
+ case WSP_PDU_REPLY:
+ count = 0; /* Initialise count */
+ headersLength = tvb_get_guintvar (tvb, offset+1, &count);
+ headerStart = offset + count + 1;
+ {
+ guint8 reply_status = tvb_get_guint8(tvb, offset);
+ char *reply_status_str = match_strval (reply_status, vals_status);
+
+ if (reply_status_str == NULL)
+ reply_status_str = "(Unknown response status)";
+
+ if (tree) {
+ ti = proto_tree_add_item (wsp_tree, hf_wsp_header_status,
+ tvb, offset, 1, bo_little_endian);
+ proto_item_append_text(proto_ti, ", Status: %s (0x%02x)",
+ reply_status_str, reply_status);
+ }
+ stat_info->status_code = (gint) reply_status;
+ if (check_col(pinfo->cinfo, COL_INFO))
+ { /* Append status code to INFO column */
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ ": %s (0x%02x)",
+ reply_status_str, reply_status);
+ }
+ }
+ nextOffset = offset + 1 + count;
+ if (tree)
+ ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,
+ tvb, offset + 1, count, headersLength);
+
+ if (headersLength == 0)
+ break;
+
+ contentTypeStart = nextOffset;
+ nextOffset = add_content_type (wsp_tree, tvb,
+ nextOffset, &contentType, &contentTypeStr);
+
+ if (tree) {
+ /* Add content type to protocol summary line */
+ if (contentTypeStr) {
+ proto_item_append_text(proto_ti, ", Content-Type: %s",
+ contentTypeStr);
+ } else {
+ proto_item_append_text(proto_ti, ", Content-Type: 0x%X",
+ contentType);
+ }
+
+ /* Add headers subtree that will hold the headers fields */
+ /* Runs from nextOffset for
+ * headersLength - (length of Content-Type field) */
+ headerLength = headersLength - (nextOffset - contentTypeStart);
+ if (headerLength > 0)
+ {
+ tmp_tvb = tvb_new_subset (tvb, nextOffset,
+ headerLength, headerLength);
+ add_headers (wsp_tree, tmp_tvb, hf_wsp_headers_section, pinfo);
+ }
+ /* XXX - offset is no longer used after this point */
+ offset += count+headersLength+1;
+ }
+ /* WSP_PDU_REPLY data - First check whether a subdissector exists
+ * for the content type */
+ if (tvb_reported_length_remaining(tvb, headerStart + headersLength)
+ > 0)
+ {
+ tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength,
+ -1, -1);
+ /*
+ * Try finding a dissector for the content
+ * first, then fallback.
+ */
+ found_match = FALSE;
+ if (contentTypeStr) {
+ /*
+ * Content type is a string.
+ */
+ found_match = dissector_try_string(media_type_table,
+ contentTypeStr, tmp_tvb, pinfo, tree);
+ }
+ if (! found_match) {
+ if (! dissector_try_heuristic(heur_subdissector_list,
+ tmp_tvb, pinfo, tree)) {
+ guint8* save_private_data = pinfo->private_data;
+
+ pinfo->match_string = contentTypeStr;
+ pinfo->private_data = NULL; /* TODO: parameters */
+ call_dissector(media_handle, tmp_tvb, pinfo, tree);
+ pinfo->private_data = save_private_data;
+#if 0
+ if (tree) / * Only display if needed * /
+ ti = proto_tree_add_item (wsp_tree,
+ hf_wsp_reply_data,
+ tmp_tvb, 0, -1, bo_little_endian);
+#endif
+ }
+ }
+ }
+ break;
+
+ case WSP_PDU_PUSH:
+ case WSP_PDU_CONFIRMEDPUSH:
+ count = 0; /* Initialise count */
+ headersLength = tvb_get_guintvar (tvb, offset, &count);
+ headerStart = offset + count;
+
+ if (tree)
+ ti = proto_tree_add_uint (wsp_tree, hf_wsp_header_length,
+ tvb, offset, count, headersLength);
+
+ if (headersLength == 0)
+ break;
+
+ offset += count;
+ contentTypeStart = offset;
+ nextOffset = add_content_type (wsp_tree,
+ tvb, offset, &contentType, &contentTypeStr);
+
+ if (tree) {
+ /* Add content type to protocol summary line */
+ if (contentTypeStr) {
+ proto_item_append_text(proto_ti, ", Content-Type: %s",
+ contentTypeStr);
+ } else {
+ proto_item_append_text(proto_ti, ", Content-Type: 0x%X",
+ contentType);
+ }
+
+ /* Add headers subtree that will hold the headers fields */
+ /* Runs from nextOffset for
+ * headersLength-(length of Content-Type field) */
+ headerLength = headersLength-(nextOffset-contentTypeStart);
+ if (headerLength > 0)
+ {
+ tmp_tvb = tvb_new_subset (tvb, nextOffset,
+ headerLength, headerLength);
+ add_headers (wsp_tree, tmp_tvb, hf_wsp_headers_section, pinfo);
+ }
+ /* XXX - offset is no longer used after this point */
+ offset += headersLength;
+ }
+ /* WSP_PDU_PUSH data - First check whether a subdissector exists
+ * for the content type */
+ if (tvb_reported_length_remaining(tvb, headerStart + headersLength)
+ > 0)
+ {
+ tmp_tvb = tvb_new_subset (tvb, headerStart + headersLength,
+ -1, -1);
+ /*
+ * Try finding a dissector for the content
+ * first, then fallback.
+ */
+ found_match = FALSE;
+ if (contentTypeStr) {
+ /*
+ * Content type is a string.
+ */
+ /*
+ if (strcasecmp(contentTypeStr, "application/vnd.wap.sia") == 0) {
+ dissect_sir(tree, tmp_tvb);
+ } else
+ */
+ found_match = dissector_try_string(media_type_table,
+ contentTypeStr, tmp_tvb, pinfo, tree);
+ }
+ if (! found_match) {
+ if (! dissector_try_heuristic(heur_subdissector_list,
+ tmp_tvb, pinfo, tree)) {
+ guint8* save_private_data = pinfo->private_data;
+
+ pinfo->match_string = contentTypeStr;
+ pinfo->private_data = NULL; /* TODO: parameters */
+ call_dissector(media_handle, tmp_tvb, pinfo, tree);
+ pinfo->private_data = save_private_data;
+#if 0
+ if (tree) /* Only display if needed */
+ ti = proto_tree_add_item (wsp_tree,
+ hf_wsp_push_data,
+ tmp_tvb, 0, -1, bo_little_endian);
+#endif
+ }
+ }
+ }
+ break;
+
+ }
+ stat_info->pdut = pdut;
+ tap_queue_packet (wsp_tap, pinfo, stat_info);
+}
+
+
+/*
+ * Called directly from UDP.
+ * Put "WSP" into the "Protocol" column.
+ */
+static void
+dissect_wsp_fromudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WSP" );
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ dissect_wsp_common(tvb, pinfo, tree, wsp_fromudp_handle, TRUE);
+}
+
+
+/*
+ * Called from a higher-level WAP dissector, in connection-oriented mode.
+ * Leave the "Protocol" column alone - the dissector calling us should
+ * have set it.
+ */
+static void
+dissect_wsp_fromwap_co(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /*
+ * XXX - what about WTLS->WTP->WSP?
+ */
+ dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, FALSE);
+}
+
+
+/*
+ * Called from a higher-level WAP dissector, in connectionless mode.
+ * Leave the "Protocol" column alone - the dissector calling us should
+ * have set it.
+ */
+static void
+dissect_wsp_fromwap_cl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /*
+ * XXX - what about WTLS->WSP?
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
+ dissect_wsp_common(tvb, pinfo, tree, wtp_fromudp_handle, TRUE);
+}
+
+
+static void
+add_uri (proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
+ guint URILenOffset, guint URIOffset, proto_item *proto_ti)
+{
+ proto_item *ti;
+
+ guint count = 0;
+ guint uriLen = tvb_get_guintvar (tvb, URILenOffset, &count);
+ gchar *str = NULL;
+
+ if (tree)
+ ti = proto_tree_add_uint (tree, hf_wsp_header_uri_len,
+ tvb, URILenOffset, count, uriLen);
+
+ tvb_ensure_bytes_exist(tvb, URIOffset, uriLen);
+ if (tree)
+ ti = proto_tree_add_item (tree, hf_wsp_header_uri,
+ tvb, URIOffset, uriLen, bo_little_endian);
+
+ str = tvb_format_text (tvb, URIOffset, uriLen);
+ /* XXX - tvb_format_text() returns a pointer to a static text string
+ * so please DO NOT attempt at g_free()ing it!
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", str);
+ }
+ if (proto_ti)
+ proto_item_append_text(proto_ti, ", URI: %s", str);
+}
+
+
+/*
+ * CO-WSP capability negotiation
+ */
+
+enum {
+ WSP_CAPA_CLIENT_SDU_SIZE = 0x00,
+ WSP_CAPA_SERVER_SDU_SIZE,
+ WSP_CAPA_PROTOCOL_OPTIONS,
+ WSP_CAPA_METHOD_MOR,
+ WSP_CAPA_PUSH_MOR,
+ WSP_CAPA_EXTENDED_METHODS,
+ WSP_CAPA_HEADER_CODE_PAGES,
+ WSP_CAPA_ALIASES,
+ WSP_CAPA_CLIENT_MESSAGE_SIZE,
+ WSP_CAPA_SERVER_MESSAGE_SIZE
+};
+
+static void
+add_capabilities (proto_tree *tree, tvbuff_t *tvb, guint8 pdu_type)
+{
+ proto_tree *wsp_capabilities;
+ proto_tree *capa_subtree;
+ proto_item *ti;
+ char *capaName, *str, *valStr;
+ guint32 offset = 0;
+ guint32 len = 0;
+ guint32 capaStart = 0; /* Start offset of the capability */
+ guint32 capaLen = 0; /* Length of the entire capability */
+ guint32 capaValueLen = 0; /* Length of the capability value & type */
+ guint32 tvb_len = tvb_reported_length(tvb);
+ gboolean ok = FALSE;
+ guint8 peek;
+ guint32 value;
+
+ if (tvb_len == 0) {
+ DebugLog(("add_capabilities(): Capabilities = 0\n"));
+ return;
+ }
+
+ DebugLog(("add_capabilities(): capabilities to process\n"));
+
+ ti = proto_tree_add_item(tree, hf_capabilities_section,
+ tvb, 0, tvb_len, bo_little_endian);
+ wsp_capabilities = proto_item_add_subtree(ti, ett_capabilities);
+
+ while (offset < tvb_len) {
+ /*
+ * WSP capabilities consist of:
+ * - a guint32 length field,
+ * - a capability identifier as Token-text or Short-integer,
+ * - a capability-specific sequence of <length> octets.
+ */
+ capaStart = offset;
+ /*
+ * Now Offset points to the 1st byte of a capability field.
+ * Get the length of the capability field
+ */
+ capaValueLen = tvb_get_guintvar(tvb, offset, &len);
+ capaLen = capaValueLen + len;
+ offset += len;
+ /*
+ * Now offset points to the 1st byte of the capability type.
+ * Get the capability identifier.
+ */
+ peek = tvb_get_guint8(tvb, offset);
+ if (is_token_text(peek)) { /* Literal capability name */
+ /* 1. Get the string from the tvb */
+ get_token_text(capaName, tvb, offset, len, ok);
+ if (! ok) {
+ DebugLog(("add_capabilities(): expecting capability name as token_text "
+ "at offset %u (1st char = 0x%02x)\n", offset, peek));
+ return;
+ }
+ /* 2. Look up the string capability name */
+ if (strcasecmp(capaName, "client-sdu-size") == 0) {
+ peek = WSP_CAPA_CLIENT_SDU_SIZE;
+ } else if (strcasecmp(capaName, "server-sdu-size") == 0) {
+ peek = WSP_CAPA_SERVER_SDU_SIZE;
+ } else if (strcasecmp(capaName, "protocol options") == 0) {
+ peek = WSP_CAPA_PROTOCOL_OPTIONS;
+ } else if (strcasecmp(capaName, "method-mor") == 0) {
+ peek = WSP_CAPA_METHOD_MOR;
+ } else if (strcasecmp(capaName, "push-mor") == 0) {
+ peek = WSP_CAPA_PUSH_MOR;
+ } else if (strcasecmp(capaName, "extended methods") == 0) {
+ peek = WSP_CAPA_EXTENDED_METHODS;
+ } else if (strcasecmp(capaName, "header code pages") == 0) {
+ peek = WSP_CAPA_HEADER_CODE_PAGES;
+ } else if (strcasecmp(capaName, "aliases") == 0) {
+ peek = WSP_CAPA_ALIASES;
+ } else if (strcasecmp(capaName, "client-message-size") == 0) {
+ peek = WSP_CAPA_CLIENT_MESSAGE_SIZE;
+ } else if (strcasecmp(capaName, "server-message-size") == 0) {
+ peek = WSP_CAPA_SERVER_MESSAGE_SIZE;
+ } else {
+ DebugLog(("add_capabilities(): unknown capability '%s' at offset %u\n",
+ capaName, offset));
+ proto_tree_add_text(wsp_capabilities, tvb, capaStart, capaLen,
+ "Unknown or invalid textual capability: %s", capaName);
+ g_free(capaName);
+ /* Skip this capability */
+ offset = capaStart + capaLen;
+ continue;
+ }
+ g_free(capaName);
+ offset += len;
+ /* Now offset points to the 1st value byte of the capability. */
+ } else if (peek < 0x80) {
+ DebugLog(("add_capabilities(): invalid capability type identifier 0x%02X at offset %u.",
+ peek, offset - 1));
+ proto_tree_add_text(wsp_capabilities, tvb, capaStart, capaLen,
+ "Invalid well-known capability: 0x%02X", peek);
+ /* Skip further capability parsing */
+ return;
+ }
+ if (peek & 0x80) { /* Well-known capability */
+ peek &= 0x7F;
+ len = 1;
+ offset++;
+ /* Now offset points to the 1st value byte of the capability. */
+ }
+ /* Now the capability type is known */
+ switch (peek) {
+ case WSP_CAPA_CLIENT_SDU_SIZE:
+ value = tvb_get_guintvar(tvb, offset, &len);
+ DebugLog(("add_capabilities(client-sdu-size): "
+ "guintvar = %u (0x%X) at offset %u (1st byte = 0x%02X) (len = %u)\n",
+ value, value, offset, tvb_get_guint8(tvb, offset), len));
+ proto_tree_add_uint(wsp_capabilities, hf_capa_client_sdu_size,
+ tvb, capaStart, capaLen, value);
+ break;
+ case WSP_CAPA_SERVER_SDU_SIZE:
+ value = tvb_get_guintvar(tvb, offset, &len);
+ DebugLog(("add_capabilities(server-sdu-size): "
+ "guintvar = %u (0x%X) at offset %u (1st byte = 0x%02X) (len = %u)\n",
+ value, value, offset, tvb_get_guint8(tvb, offset), len));
+ proto_tree_add_uint(wsp_capabilities, hf_capa_server_sdu_size,
+ tvb, capaStart, capaLen, value);
+ break;
+ case WSP_CAPA_PROTOCOL_OPTIONS:
+ ti = proto_tree_add_string(wsp_capabilities, hf_capa_protocol_options,
+ tvb, capaStart, capaLen, "");
+ capa_subtree = proto_item_add_subtree(ti, ett_capability);
+ /*
+ * The bits are stored in one or more octets, not an
+ * uintvar-integer! Note that capability name and value
+ * have length capaValueLength, and that the capability
+ * name has length = len. Hence the remaining length is
+ * given by capaValueLen - len.
+ */
+ switch (capaValueLen - len) {
+ case 1:
+ value = tvb_get_guint8(tvb, offset);
+ len = 1;
+ break;
+ default:
+ /*
+ * The WSP spec foresees that this bit field can be
+ * extended in the future. This does not make sense yet.
+ */
+ DebugLog(("add_capabilities(protocol options): "
+ "bit field too large (%u bytes)\n",
+ capaValueLen));
+ proto_item_append_text(ti,
+ " <warning: bit field too large>");
+ offset = capaStart + capaLen;
+ continue;
+ }
+ DebugLog(("add_capabilities(protocol options): "
+ "guintvar = %u (0x%X) at offset %u (1st byte = 0x%02X) (len = %u)\n",
+ value, value, offset, tvb_get_guint8(tvb, offset), len));
+ if (value & 0x80)
+ proto_item_append_string(ti, " (confirmed push facility)");
+ if (value & 0x40)
+ proto_item_append_string(ti, " (push facility)");
+ if (value & 0x20)
+ proto_item_append_string(ti, " (session resume facility)");
+ if (value & 0x10)
+ proto_item_append_string(ti, " (acknowledgement headers)");
+ if (value & 0x08)
+ proto_item_append_string(ti, " (large data transfer)");
+ if (value & 0xFFFFFF07)
+ proto_item_append_text(ti, " <warning: reserved bits have been set>");
+ proto_tree_add_boolean(capa_subtree,
+ hf_capa_protocol_option_confirmed_push,
+ tvb, offset, len, value);
+ proto_tree_add_boolean(capa_subtree,
+ hf_capa_protocol_option_push,
+ tvb, offset, len, value);
+ proto_tree_add_boolean(capa_subtree,
+ hf_capa_protocol_option_session_resume,
+ tvb, offset, len, value);
+ proto_tree_add_boolean(capa_subtree,
+ hf_capa_protocol_option_ack_headers,
+ tvb, offset, len, value);
+ proto_tree_add_boolean(capa_subtree,
+ hf_capa_protocol_option_large_data_transfer,
+ tvb, offset, len, value);
+ break;
+ case WSP_CAPA_METHOD_MOR:
+ value = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint (wsp_capabilities,
+ hf_capa_method_mor,
+ tvb, capaStart, capaLen, value);
+ break;
+ case WSP_CAPA_PUSH_MOR:
+ value = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint (wsp_capabilities,
+ hf_capa_push_mor,
+ tvb, capaStart, capaLen, value);
+ break;
+ case WSP_CAPA_EXTENDED_METHODS:
+ /* Extended Methods capability format:
+ * Connect PDU: collection of { Method (octet), Method-name (Token-text) }
+ * ConnectReply PDU: collection of accepted { Method (octet) }
+ */
+ ti = proto_tree_add_string(wsp_capabilities,
+ hf_capa_extended_methods,
+ tvb, capaStart, capaLen, "");
+ if (pdu_type == WSP_PDU_CONNECT) {
+ while (offset < capaStart + capaLen) {
+ peek = tvb_get_guint8(tvb, offset++);
+ get_text_string(str, tvb, offset, len, ok);
+ if (! ok) {
+ proto_item_append_text(ti, " <error: invalid capability encoding>");
+ DebugLog(("add_capability(extended methods): "
+ "invalid method name at offset %u "
+ "(octet = 0x%02X)\n",
+ offset, tvb_get_guint8(tvb, offset)));
+ return;
+ }
+ valStr = g_strdup_printf(" (0x%02x = %s)", peek, str);
+ DebugLog(("add_capabilities(extended methods):%s\n",
+ valStr));
+ proto_item_append_string(ti, valStr);
+ g_free(valStr);
+ g_free(str);
+ offset += len;
+ }
+ } else {
+ while (offset < capaStart + capaLen) {
+ peek = tvb_get_guint8(tvb, offset++);
+ valStr = g_strdup_printf(" (0x%02x)", peek);
+ DebugLog(("add_capabilities(extended methods):%s\n",
+ valStr));
+ proto_item_append_string(ti, valStr);
+ g_free(valStr);
+ }
+ }
+ break;
+ case WSP_CAPA_HEADER_CODE_PAGES:
+ /* Header Code Pages capability format:
+ * Connect PDU: collection of { Page-id (octet), Page-name (Token-text) }
+ * ConnectReply PDU: collection of accepted { Page-id (octet) }
+ */
+ ti = proto_tree_add_string(wsp_capabilities,
+ hf_capa_header_code_pages,
+ tvb, capaStart, capaLen, "");
+ if (pdu_type == WSP_PDU_CONNECT) {
+ while (offset < capaStart + capaLen) {
+ peek = tvb_get_guint8(tvb, offset++);
+ get_text_string(str, tvb, offset, len, ok);
+ if (! ok) {
+ proto_item_append_text(ti,
+ " <error: invalid capability encoding>");
+ DebugLog(("add_capability(header code pages): "
+ "invalid header code page name at offset %u "
+ "(octet = 0x%02X)\n",
+ offset, tvb_get_guint8(tvb, offset)));
+ return;
+ }
+ valStr = g_strdup_printf(" (0x%02x = %s)", peek, str);
+ DebugLog(("add_capabilities(header code pages):%s\n",
+ valStr));
+ proto_item_append_string(ti, valStr);
+ g_free(valStr);
+ g_free(str);
+ offset += len;
+ }
+ } else {
+ while (offset < capaStart + capaLen) {
+ peek = tvb_get_guint8(tvb, offset++);
+ valStr = g_strdup_printf(" (0x%02x)", peek);
+ DebugLog(("add_capabilities(header code pages):%s\n",
+ valStr));
+ proto_item_append_string(ti, valStr);
+ g_free(valStr);
+ }
+ }
+ break;
+ case WSP_CAPA_ALIASES:
+ /* TODO - same format as redirect addresses */
+ proto_tree_add_item(wsp_capabilities, hf_capa_aliases,
+ tvb, capaStart, capaLen, bo_little_endian);
+ break;
+ case WSP_CAPA_CLIENT_MESSAGE_SIZE:
+ value = tvb_get_guintvar(tvb, offset, &len);
+ DebugLog(("add_capabilities(client-message-size): "
+ "guintvar = %u (0x%X) at offset %u (1st byte = 0x%02X) (len = %u)\n",
+ value, value, offset, tvb_get_guint8(tvb, offset), len));
+ proto_tree_add_uint(wsp_capabilities, hf_capa_client_message_size,
+ tvb, capaStart, capaLen, value);
+ break;
+ case WSP_CAPA_SERVER_MESSAGE_SIZE:
+ value = tvb_get_guintvar(tvb, offset, &len);
+ DebugLog(("add_capabilities(server-message-size): "
+ "guintvar = %u (0x%X) at offset %u (1st byte = 0x%02X) (len = %u)\n",
+ value, value, offset, tvb_get_guint8(tvb, offset), len));
+ proto_tree_add_uint(wsp_capabilities, hf_capa_server_message_size,
+ tvb, capaStart, capaLen, value);
+ break;
+ default:
+ proto_tree_add_text(wsp_capabilities, tvb, capaStart, capaLen,
+ "Unknown well-known capability: 0x%02X", peek);
+ break;
+ }
+ offset = capaStart + capaLen;
+ }
+}
+
+void
+add_post_data (proto_tree *tree, tvbuff_t *tvb, guint contentType,
+ const char *contentTypeStr, packet_info *pinfo)
+{
+ guint offset = 0;
+ guint variableStart = 0;
+ guint variableEnd = 0;
+ guint valueStart = 0;
+ guint valueEnd = 0;
+ guint8 peek = 0;
+ proto_item *ti;
+ proto_tree *sub_tree = NULL;
+
+ DebugLog(("add_post_data() - START\n"));
+
+ /* VERIFY ti = proto_tree_add_item (tree, hf_wsp_post_data,tvb,offset,-1,bo_little_endian); */
+ if (tree) {
+ ti = proto_tree_add_item (tree, hf_wsp_post_data,
+ tvb, offset, -1, bo_little_endian);
+ sub_tree = proto_item_add_subtree(ti, ett_post);
+ }
+
+ if ( (contentTypeStr == NULL && contentType == 0x12)
+ || (contentTypeStr && (strcasecmp(contentTypeStr,
+ "application/x-www-form-urlencoded") == 0)) )
+ {
+ if (tree) {
+ /*
+ * URL Encoded data.
+ * Iterate through post data.
+ */
+ for (offset = 0; offset < tvb_reported_length (tvb); offset++)
+ {
+ peek = tvb_get_guint8 (tvb, offset);
+ if (peek == '=')
+ {
+ variableEnd = offset;
+ valueStart = offset+1;
+ }
+ else if (peek == '&')
+ {
+ if (variableEnd > 0)
+ {
+ add_post_variable (sub_tree, tvb, variableStart, variableEnd, valueStart, offset);
+ }
+ variableStart = offset+1;
+ variableEnd = 0;
+ valueStart = 0;
+ valueEnd = 0;
+ }
+ }
+
+ /* See if there's outstanding data */
+ if (variableEnd > 0)
+ {
+ add_post_variable (sub_tree, tvb, variableStart, variableEnd, valueStart, offset);
+ }
+ } /* if (tree) */
+ }
+ else if ((contentType == 0x22) || (contentType == 0x23) || (contentType == 0x24) ||
+ (contentType == 0x25) || (contentType == 0x26) || (contentType == 0x33))
+ {
+ /* add_multipart_data takes also care of subdissection */
+ add_multipart_data(sub_tree, tvb, pinfo);
+ }
+ DebugLog(("add_post_data() - END\n"));
+}
+
+static void
+add_post_variable (proto_tree *tree, tvbuff_t *tvb, guint variableStart, guint variableEnd, guint valueStart, guint valueEnd)
+{
+ int variableLength = variableEnd-variableStart;
+ int valueLength = 0;
+ char *variableBuffer;
+ char *valueBuffer;
+
+ variableBuffer = tvb_get_string(tvb, variableStart, variableLength);
+
+ if (valueEnd < valueStart)
+ {
+ valueBuffer = g_malloc (1);
+ valueBuffer[0] = 0;
+ valueEnd = valueStart;
+ }
+ else
+ {
+ valueLength = valueEnd-valueStart;
+ /* XXX - if this throws an exception, "variableBuffer"
+ is leaked */
+ valueBuffer = tvb_get_string(tvb, valueStart, valueLength);
+ }
+
+ /* Check for variables with no value */
+ if (valueStart >= tvb_reported_length (tvb))
+ {
+ valueStart = tvb_reported_length (tvb);
+ valueEnd = valueStart;
+ }
+ valueLength = valueEnd-valueStart;
+
+ proto_tree_add_text (tree, tvb, variableStart, valueEnd-variableStart, "%s: %s", variableBuffer, valueBuffer);
+
+ g_free (variableBuffer);
+ g_free (valueBuffer);
+}
+
+static void
+add_multipart_data (proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo)
+{
+ int offset = 0;
+ guint nextOffset;
+ guint nEntries = 0;
+ guint count;
+ guint HeadersLen;
+ guint DataLen;
+ guint contentType = 0;
+ const char *contentTypeStr;
+ tvbuff_t *tmp_tvb;
+ int partnr = 1;
+ int part_start;
+ gboolean found_match = FALSE;
+
+ proto_item *sub_tree = NULL;
+ proto_item *ti = NULL;
+ proto_tree *mpart_tree = NULL;
+
+ DebugLog(("add_multipart_data(): offset = %u, byte = 0x%02x: ",
+ offset, tvb_get_guint8(tvb,offset)));
+ nEntries = tvb_get_guintvar (tvb, offset, &count);
+ DebugLog(("parts = %u\n", nEntries));
+ offset += count;
+ if (nEntries)
+ {
+ sub_tree = proto_tree_add_text(tree, tvb, offset - count, 0,
+ "Multipart body");
+ proto_item_add_subtree(sub_tree, ett_mpartlist);
+ }
+ while (nEntries--)
+ {
+ DebugLog(("add_multipart_data(): Parts to do after this: %u"
+ " (offset = %u, 0x%02x): ",
+ nEntries, offset, tvb_get_guint8(tvb,offset)));
+ part_start = offset;
+ HeadersLen = tvb_get_guintvar (tvb, offset, &count);
+ offset += count;
+ DataLen = tvb_get_guintvar (tvb, offset, &count);
+ offset += count;
+ if (tree) {
+ ti = proto_tree_add_uint(sub_tree, hf_wsp_mpart, tvb, part_start,
+ HeadersLen + DataLen + (offset - part_start), partnr);
+ mpart_tree = proto_item_add_subtree(ti, ett_multiparts);
+ }
+ nextOffset = add_content_type (mpart_tree, tvb, offset,
+ &contentType, &contentTypeStr);
+
+ if (tree) {
+ /* Add content type to protocol summary line */
+ if (contentTypeStr) {
+ proto_item_append_text(ti, ", content-type: %s",
+ contentTypeStr);
+ } else {
+ proto_item_append_text(ti, ", content-type: 0x%X",
+ contentType);
+ }
+ }
+
+ HeadersLen -= (nextOffset - offset);
+ if (HeadersLen > 0)
+ {
+ tmp_tvb = tvb_new_subset (tvb, nextOffset, HeadersLen, HeadersLen);
+ add_headers (mpart_tree, tmp_tvb, hf_wsp_headers_section, pinfo);
+ }
+ offset = nextOffset + HeadersLen;
+ /*
+ * Try the dissectors of the multipart content.
+ *
+ * TODO - handle nested multipart documents.
+ */
+ tmp_tvb = tvb_new_subset(tvb, offset, DataLen, DataLen);
+ /*
+ * Try finding a dissector for the content
+ * first, then fallback.
+ */
+ found_match = FALSE;
+ if (contentTypeStr) {
+ /*
+ * Content type is a string.
+ */
+ found_match = dissector_try_string(media_type_table,
+ contentTypeStr, tmp_tvb, pinfo, mpart_tree);
+ }
+ if (! found_match) {
+ if (! dissector_try_heuristic(heur_subdissector_list,
+ tmp_tvb, pinfo, mpart_tree)) {
+ guint8* save_private_data = pinfo->private_data;
+
+ pinfo->match_string = contentTypeStr;
+ pinfo->private_data = NULL; /* TODO: parameters */
+ call_dissector(media_handle, tmp_tvb, pinfo, tree);
+ pinfo->private_data = save_private_data;
+#if 0
+ if (tree) /* Only display if needed */
+ proto_tree_add_item (mpart_tree, hf_wsp_multipart_data,
+ tvb, offset, DataLen, bo_little_endian);
+#endif
+ }
+ }
+
+ offset += DataLen;
+ partnr++;
+ }
+}
+
+
+/* Register the protocol with Ethereal */
+void
+proto_register_wsp(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_wsp_header_tid,
+ { "Transaction ID",
+ "wsp.TID",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "WSP Transaction ID (for connectionless WSP)", HFILL
+ }
+ },
+ { &hf_wsp_header_pdu_type,
+ { "PDU Type",
+ "wsp.pdu_type",
+ FT_UINT8, BASE_HEX, VALS( vals_pdu_type ), 0x00,
+ "PDU Type", HFILL
+ }
+ },
+ { &hf_wsp_version_major,
+ { "Version (Major)",
+ "wsp.version.major",
+ FT_UINT8, BASE_DEC, NULL, 0xF0,
+ "Version (Major)", HFILL
+ }
+ },
+ { &hf_wsp_version_minor,
+ { "Version (Minor)",
+ "wsp.version.minor",
+ FT_UINT8, BASE_DEC, NULL, 0x0F,
+ "Version (Minor)", HFILL
+ }
+ },
+ { &hf_capabilities_length,
+ { "Capabilities Length",
+ "wsp.capabilities.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Length of Capabilities field (bytes)", HFILL
+ }
+ },
+ { &hf_wsp_header_length,
+ { "Headers Length",
+ "wsp.headers_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Length of Headers field (bytes)", HFILL
+ }
+ },
+ { &hf_capabilities_section,
+ { "Capabilities",
+ "wsp.capabilities",
+ FT_NONE, BASE_DEC, NULL, 0x00,
+ "Capabilities", HFILL
+ }
+ },
+ { &hf_wsp_headers_section,
+ { "Headers",
+ "wsp.headers",
+ FT_NONE, BASE_DEC, NULL, 0x00,
+ "Headers", HFILL
+ }
+ },
+ { &hf_wsp_header_uri_len,
+ { "URI Length",
+ "wsp.uri_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Length of URI field", HFILL
+ }
+ },
+ { &hf_wsp_header_uri,
+ { "URI",
+ "wsp.uri",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "URI", HFILL
+ }
+ },
+ { &hf_wsp_server_session_id,
+ { "Server Session ID",
+ "wsp.server.session_id",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Server Session ID", HFILL
+ }
+ },
+ { &hf_wsp_header_status,
+ { "Status",
+ "wsp.reply.status",
+ FT_UINT8, BASE_HEX, VALS( vals_status ), 0x00,
+ "Reply Status", HFILL
+ }
+ },
+ { &hf_wsp_parameter_type,
+ { "Type",
+ "wsp.parameter.type",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Type parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_name,
+ { "Name",
+ "wsp.parameter.name",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Name parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_filename,
+ { "Filename",
+ "wsp.parameter.filename",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Filename parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_start,
+ { "Start",
+ "wsp.parameter.start",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Start parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_start_info,
+ { "Start-info",
+ "wsp.parameter.start_info",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Start-info parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_comment,
+ { "Comment",
+ "wsp.parameter.comment",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Comment parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_domain,
+ { "Domain",
+ "wsp.parameter.domain",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Domain parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_path,
+ { "Path",
+ "wsp.parameter.path",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Path parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_sec,
+ { "SEC",
+ "wsp.parameter.sec",
+ FT_UINT8, BASE_HEX, VALS (vals_wsp_parameter_sec), 0x00,
+ "SEC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", HFILL
+ }
+ },
+ { &hf_wsp_parameter_mac,
+ { "MAC",
+ "wsp.parameter.mac",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "MAC parameter (Content-Type: application/vnd.wap.connectivity-wbxml)", HFILL
+ }
+ },
+ { &hf_wsp_parameter_upart_type,
+ { "Type",
+ "wsp.parameter.upart.type",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Multipart type parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_level,
+ { "Level",
+ "wsp.parameter.level",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Level parameter", HFILL
+ }
+ },
+ { &hf_wsp_parameter_size,
+ { "Size",
+ "wsp.parameter.size",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Size parameter", HFILL
+ }
+ },
+ { &hf_wsp_reply_data,
+ { "Data",
+ "wsp.reply.data",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Data", HFILL
+ }
+ },
+ { &hf_wsp_header_shift_code,
+ { "Switching to WSP header code-page",
+ "wsp.code_page",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Header code-page shift code", HFILL
+ }
+ },
+ /*
+ * CO-WSP capability negotiation
+ */
+ { &hf_capa_client_sdu_size,
+ { "Client SDU Size",
+ "wsp.capability.client_sdu_size",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Client Service Data Unit size (bytes)", HFILL
+ }
+ },
+ { &hf_capa_server_sdu_size,
+ { "Server SDU Size",
+ "wsp.capability.server_sdu_size",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Server Service Data Unit size (bytes)", HFILL
+ }
+ },
+ { &hf_capa_protocol_options,
+ { "Protocol Options",
+ "wsp.capability.protocol_opt",
+ FT_STRING, BASE_HEX, NULL, 0x00,
+ "Protocol Options", HFILL
+ }
+ },
+ { &hf_capa_protocol_option_confirmed_push,
+ { "Confirmed Push facility",
+ "wsp.capability.protocol_option.confirmed_push",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ "If set, this CO-WSP session supports the Confirmed Push facility", HFILL
+ }
+ },
+ { &hf_capa_protocol_option_push,
+ { "Push facility",
+ "wsp.capability.protocol_option.push",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ "If set, this CO-WSP session supports the Push facility", HFILL
+ }
+ },
+ { &hf_capa_protocol_option_session_resume,
+ { "Session Resume facility",
+ "wsp.capability.protocol_option.session_resume",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ "If set, this CO-WSP session supports the Session Resume facility", HFILL
+ }
+ },
+ { &hf_capa_protocol_option_ack_headers,
+ { "Acknowledgement headers",
+ "wsp.capability.protocol_option.ack_headers",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ "If set, this CO-WSP session supports Acknowledgement headers", HFILL
+ }
+ },
+ { &hf_capa_protocol_option_large_data_transfer,
+ { "Large data transfer",
+ "wsp.capability.protocol_option.large_data_transfer",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ "If set, this CO-WSP session supports Large data transfer", HFILL
+ }
+ },
+ { &hf_capa_method_mor,
+ { "Method MOR",
+ "wsp.capability.method_mor",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Method MOR", HFILL
+ }
+ },
+ { &hf_capa_push_mor,
+ { "Push MOR",
+ "wsp.capability.push_mor",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Push MOR", HFILL
+ }
+ },
+ { &hf_capa_extended_methods,
+ { "Extended Methods",
+ "wsp.capability.extended_methods",
+ FT_STRING, BASE_HEX, NULL, 0x00,
+ "Extended Methods", HFILL
+ }
+ },
+ { &hf_capa_header_code_pages,
+ { "Header Code Pages",
+ "wsp.capability.code_pages",
+ FT_STRING, BASE_HEX, NULL, 0x00,
+ "Header Code Pages", HFILL
+ }
+ },
+ { &hf_capa_aliases,
+ { "Aliases",
+ "wsp.capability.aliases",
+ FT_BYTES, BASE_NONE, NULL, 0x00,
+ "Aliases", HFILL
+ }
+ },
+ { &hf_capa_client_message_size,
+ { "Client Message Size",
+ "wsp.capability.client_message_size",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Client Message size (bytes)", HFILL
+ }
+ },
+ { &hf_capa_server_message_size,
+ { "Server Message Size",
+ "wsp.capability.server_message_size",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Server Message size (bytes)", HFILL
+ }
+ },
+ { &hf_wsp_post_data,
+ { "Data (Post)",
+ "wsp.post.data",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Post Data", HFILL
+ }
+ },
+ { &hf_wsp_push_data,
+ { "Push Data",
+ "wsp.push.data",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Push Data", HFILL
+ }
+ },
+ { &hf_wsp_multipart_data,
+ { "Data in this part",
+ "wsp.multipart.data",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "The data of 1 MIME-multipart part.", HFILL
+ }
+ },
+ { &hf_wsp_mpart,
+ { "Part",
+ "wsp.multipart",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "MIME part of multipart data.", HFILL
+ }
+ },
+ { &hf_wsp_redirect_flags,
+ { "Flags",
+ "wsp.redirect.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Redirect Flags", HFILL
+ }
+ },
+ { &hf_wsp_redirect_permanent,
+ { "Permanent Redirect",
+ "wsp.redirect.flags.permanent",
+ FT_BOOLEAN, 8, TFS(&yes_no_truth), PERMANENT_REDIRECT,
+ "Permanent Redirect", HFILL
+ }
+ },
+ { &hf_wsp_redirect_reuse_security_session,
+ { "Reuse Security Session",
+ "wsp.redirect.flags.reuse_security_session",
+ FT_BOOLEAN, 8, TFS(&yes_no_truth), REUSE_SECURITY_SESSION,
+ "If set, the existing Security Session may be reused", HFILL
+ }
+ },
+ { &hf_redirect_addresses,
+ { "Redirect Addresses",
+ "wsp.redirect.addresses",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "List of Redirect Addresses", HFILL
+ }
+ },
+
+ /*
+ * Addresses
+ */
+ { &hf_address_entry,
+ { "Address Record",
+ "wsp.address",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Address Record", HFILL
+ }
+ },
+ { &hf_address_flags_length,
+ { "Flags/Length",
+ "wsp.address.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Address Flags/Length", HFILL
+ }
+ },
+ { &hf_address_flags_length_bearer_type_included,
+ { "Bearer Type Included",
+ "wsp.address.flags.bearer_type_included",
+ FT_BOOLEAN, 8, TFS(&yes_no_truth), BEARER_TYPE_INCLUDED,
+ "Address bearer type included", HFILL
+ }
+ },
+ { &hf_address_flags_length_port_number_included,
+ { "Port Number Included",
+ "wsp.address.flags.port_number_included",
+ FT_BOOLEAN, 8, TFS(&yes_no_truth), PORT_NUMBER_INCLUDED,
+ "Address port number included", HFILL
+ }
+ },
+ { &hf_address_flags_length_address_len,
+ { "Address Length",
+ "wsp.address.flags.length",
+ FT_UINT8, BASE_DEC, NULL, ADDRESS_LEN,
+ "Address Length", HFILL
+ }
+ },
+ { &hf_address_bearer_type,
+ { "Bearer Type",
+ "wsp.address.bearer_type",
+ FT_UINT8, BASE_HEX, VALS(vals_bearer_types), 0x0,
+ "Bearer Type", HFILL
+ }
+ },
+ { &hf_address_port_num,
+ { "Port Number",
+ "wsp.address.port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Port Number", HFILL
+ }
+ },
+ { &hf_address_ipv4_addr,
+ { "IPv4 Address",
+ "wsp.address.ipv4",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Address (IPv4)", HFILL
+ }
+ },
+ { &hf_address_ipv6_addr,
+ { "IPv6 Address",
+ "wsp.address.ipv6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Address (IPv6)", HFILL
+ }
+ },
+ { &hf_address_addr,
+ { "Address",
+ "wsp.address.unknown",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Address (unknown)", HFILL
+ }
+ },
+
+
+ /*
+ * New WSP header fields
+ */
+
+
+ /* WSP header name */
+ { &hf_hdr_name,
+ { "Header name",
+ "wsp.header.name",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Name of the WSP header", HFILL
+ }
+ },
+ /* WSP headers start here */
+ { &hf_hdr_accept,
+ { "Accept",
+ "wsp.header.accept",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Accept", HFILL
+ }
+ },
+ { &hf_hdr_accept_charset,
+ { "Accept-Charset",
+ "wsp.header.accept_charset",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Accept-Charset", HFILL
+ }
+ },
+ { &hf_hdr_accept_encoding,
+ { "Accept-Encoding",
+ "wsp.header.accept_encoding",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Accept-Encoding", HFILL
+ }
+ },
+ { &hf_hdr_accept_language,
+ { "Accept-Language",
+ "wsp.header.accept_language",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Accept-Language", HFILL
+ }
+ },
+ { &hf_hdr_accept_ranges,
+ { "Accept-Ranges",
+ "wsp.header.accept_ranges",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Accept-Ranges", HFILL
+ }
+ },
+ { &hf_hdr_age,
+ { "Age",
+ "wsp.header.age",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Age", HFILL
+ }
+ },
+ { &hf_hdr_allow,
+ { "Allow",
+ "wsp.header.allow",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Allow", HFILL
+ }
+ },
+ { &hf_hdr_authorization,
+ { "Authorization",
+ "wsp.header.authorization",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Authorization", HFILL
+ }
+ },
+ { &hf_hdr_authorization_scheme,
+ { "Authorization Scheme",
+ "wsp.header.authorization.scheme",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Authorization: used scheme", HFILL
+ }
+ },
+ { &hf_hdr_authorization_user_id,
+ { "User-id",
+ "wsp.header.authorization.user_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Authorization: user ID for basic authorization", HFILL
+ }
+ },
+ { &hf_hdr_authorization_password,
+ { "Password",
+ "wsp.header.authorization.password",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Authorization: password for basic authorization", HFILL
+ }
+ },
+ { &hf_hdr_cache_control,
+ { "Cache-Control",
+ "wsp.header.cache_control",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Cache-Control", HFILL
+ }
+ },
+ { &hf_hdr_connection,
+ { "Connection",
+ "wsp.header.connection",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Connection", HFILL
+ }
+ },
+ { &hf_hdr_content_base,
+ { "Content-Base",
+ "wsp.header.content_base",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Base", HFILL
+ }
+ },
+ { &hf_hdr_content_encoding,
+ { "Content-Encoding",
+ "wsp.header.content_encoding",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Encoding", HFILL
+ }
+ },
+ { &hf_hdr_content_language,
+ { "Content-Language",
+ "wsp.header.content_language",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Language", HFILL
+ }
+ },
+ { &hf_hdr_content_length,
+ { "Content-Length",
+ "wsp.header.content_length",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Length", HFILL
+ }
+ },
+ { &hf_hdr_content_location,
+ { "Content-Location",
+ "wsp.header.content_location",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Location", HFILL
+ }
+ },
+ { &hf_hdr_content_md5,
+ { "Content-Md5",
+ "wsp.header.content_md5",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Md5", HFILL
+ }
+ },
+ { &hf_hdr_content_range,
+ { "Content-Range",
+ "wsp.header.content_range",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Range", HFILL
+ }
+ },
+ { &hf_hdr_content_range_first_byte_pos,
+ { "First-byte-position",
+ "wsp.header.content_range.first_byte_pos",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "WSP header Content-Range: position of first byte", HFILL
+ }
+ },
+ { &hf_hdr_content_range_entity_length,
+ { "Entity-length",
+ "wsp.header.content_range.entity_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "WSP header Content-Range: length of the entity", HFILL
+ }
+ },
+ { &hf_hdr_content_type,
+ { "Content-Type",
+ "wsp.header.content_type",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Type", HFILL
+ }
+ },
+ { &hf_hdr_date,
+ { "Date",
+ "wsp.header.date",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Date", HFILL
+ }
+ },
+ { &hf_hdr_etag,
+ { "ETag",
+ "wsp.header.etag",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header ETag", HFILL
+ }
+ },
+ { &hf_hdr_expires,
+ { "Expires",
+ "wsp.header.expires",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Expires", HFILL
+ }
+ },
+ { &hf_hdr_from,
+ { "From",
+ "wsp.header.from",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header From", HFILL
+ }
+ },
+ { &hf_hdr_host,
+ { "Host",
+ "wsp.header.host",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Host", HFILL
+ }
+ },
+ { &hf_hdr_if_modified_since,
+ { "If-Modified-Since",
+ "wsp.header.if_modified_since",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header If-Modified-Since", HFILL
+ }
+ },
+ { &hf_hdr_if_match,
+ { "If-Match",
+ "wsp.header.if_match",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header If-Match", HFILL
+ }
+ },
+ { &hf_hdr_if_none_match,
+ { "If-None-Match",
+ "wsp.header.if_none_match",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header If-None-Match", HFILL
+ }
+ },
+ { &hf_hdr_if_range,
+ { "If-Range",
+ "wsp.header.if_range",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header If-Range", HFILL
+ }
+ },
+ { &hf_hdr_if_unmodified_since,
+ { "If-Unmodified-Since",
+ "wsp.header.if_unmodified_since",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header If-Unmodified-Since", HFILL
+ }
+ },
+ { &hf_hdr_last_modified,
+ { "Last-Modified",
+ "wsp.header.last_modified",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Last-Modified", HFILL
+ }
+ },
+ { &hf_hdr_location,
+ { "Location",
+ "wsp.header.location",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Location", HFILL
+ }
+ },
+ { &hf_hdr_max_forwards,
+ { "Max-Forwards",
+ "wsp.header.max_forwards",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Max-Forwards", HFILL
+ }
+ },
+ { &hf_hdr_pragma,
+ { "Pragma",
+ "wsp.header.pragma",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Pragma", HFILL
+ }
+ },
+ { &hf_hdr_proxy_authenticate,
+ { "Proxy-Authenticate",
+ "wsp.header.proxy_authenticate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Proxy-Authenticate", HFILL
+ }
+ },
+ { &hf_hdr_proxy_authenticate_scheme,
+ { "Authentication Scheme",
+ "wsp.header.proxy_authenticate.scheme",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Proxy-Authenticate: used scheme", HFILL
+ }
+ },
+ { &hf_hdr_proxy_authenticate_realm,
+ { "Authentication Realm",
+ "wsp.header.proxy_authenticate.realm",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Proxy-Authenticate: used realm", HFILL
+ }
+ },
+ { &hf_hdr_proxy_authorization,
+ { "Proxy-Authorization",
+ "wsp.header.proxy_authorization",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Proxy-Authorization", HFILL
+ }
+ },
+ { &hf_hdr_proxy_authorization_scheme,
+ { "Authorization Scheme",
+ "wsp.header.proxy_authorization.scheme",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Proxy-Authorization: used scheme", HFILL
+ }
+ },
+ { &hf_hdr_proxy_authorization_user_id,
+ { "User-id",
+ "wsp.header.proxy_authorization.user_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Proxy-Authorization: user ID for basic authorization", HFILL
+ }
+ },
+ { &hf_hdr_proxy_authorization_password,
+ { "Password",
+ "wsp.header.proxy_authorization.password",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Proxy-Authorization: password for basic authorization", HFILL
+ }
+ },
+ { &hf_hdr_public,
+ { "Public",
+ "wsp.header.public",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Public", HFILL
+ }
+ },
+ { &hf_hdr_range,
+ { "Range",
+ "wsp.header.range",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Range", HFILL
+ }
+ },
+ { &hf_hdr_range_first_byte_pos,
+ { "First-byte-position",
+ "wsp.header.range.first_byte_pos",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "WSP header Range: position of first byte", HFILL
+ }
+ },
+ { &hf_hdr_range_last_byte_pos,
+ { "Last-byte-position",
+ "wsp.header.range.last_byte_pos",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "WSP header Range: position of last byte", HFILL
+ }
+ },
+ { &hf_hdr_range_suffix_length,
+ { "Suffix-length",
+ "wsp.header.range.suffix_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "WSP header Range: length of the suffix", HFILL
+ }
+ },
+ { &hf_hdr_referer,
+ { "Referer",
+ "wsp.header.referer",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Referer", HFILL
+ }
+ },
+ { &hf_hdr_retry_after,
+ { "Retry-After",
+ "wsp.header.retry_after",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Retry-After", HFILL
+ }
+ },
+ { &hf_hdr_server,
+ { "Server",
+ "wsp.header.server",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Server", HFILL
+ }
+ },
+ { &hf_hdr_transfer_encoding,
+ { "Transfer-Encoding",
+ "wsp.header.transfer_encoding",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Transfer-Encoding", HFILL
+ }
+ },
+ { &hf_hdr_upgrade,
+ { "Upgrade",
+ "wsp.header.upgrade",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Upgrade", HFILL
+ }
+ },
+ { &hf_hdr_user_agent,
+ { "User-Agent",
+ "wsp.header.user_agent",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header User-Agent", HFILL
+ }
+ },
+ { &hf_hdr_vary,
+ { "Vary",
+ "wsp.header.vary",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Vary", HFILL
+ }
+ },
+ { &hf_hdr_via,
+ { "Via",
+ "wsp.header.via",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Via", HFILL
+ }
+ },
+ { &hf_hdr_warning,
+ { "Warning",
+ "wsp.header.warning",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Warning", HFILL
+ }
+ },
+ { &hf_hdr_warning_code,
+ { "Warning code",
+ "wsp.header.warning.code",
+ FT_UINT8, BASE_HEX, VALS(vals_wsp_warning_code), 0x00,
+ "WSP header Warning code", HFILL
+ }
+ },
+ { &hf_hdr_warning_agent,
+ { "Warning agent",
+ "wsp.header.warning.agent",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Warning agent", HFILL
+ }
+ },
+ { &hf_hdr_warning_text,
+ { "Warning text",
+ "wsp.header.warning.text",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Warning text", HFILL
+ }
+ },
+ { &hf_hdr_www_authenticate,
+ { "Www-Authenticate",
+ "wsp.header.www_authenticate",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Www-Authenticate", HFILL
+ }
+ },
+ { &hf_hdr_www_authenticate_scheme,
+ { "Authentication Scheme",
+ "wsp.header.www_authenticate.scheme",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header WWW-Authenticate: used scheme", HFILL
+ }
+ },
+ { &hf_hdr_www_authenticate_realm,
+ { "Authentication Realm",
+ "wsp.header.www_authenticate.realm",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header WWW-Authenticate: used realm", HFILL
+ }
+ },
+ { &hf_hdr_content_disposition,
+ { "Content-Disposition",
+ "wsp.header.content_disposition",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Disposition", HFILL
+ }
+ },
+ { &hf_hdr_application_id,
+ { "Application-Id",
+ "wsp.header.application_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Application-Id", HFILL
+ }
+ },
+ { &hf_hdr_content_uri,
+ { "Content-Uri",
+ "wsp.header.content_uri",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Uri", HFILL
+ }
+ },
+ { &hf_hdr_initiator_uri,
+ { "Initiator-Uri",
+ "wsp.header.initiator_uri",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Initiator-Uri", HFILL
+ }
+ },
+ { &hf_hdr_bearer_indication,
+ { "Bearer-Indication",
+ "wsp.header.bearer_indication",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Bearer-Indication", HFILL
+ }
+ },
+ { &hf_hdr_push_flag,
+ { "Push-Flag",
+ "wsp.header.push_flag",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Push-Flag", HFILL
+ }
+ },
+ { &hf_hdr_push_flag_auth,
+ { "Initiator URI is authenticated",
+ "wsp.header.push_flag.authenticated",
+ FT_UINT8, BASE_DEC, VALS(vals_false_true), 0x01,
+ "The X-Wap-Initiator-URI has been authenticated.", HFILL
+ }
+ },
+ { &hf_hdr_push_flag_trust,
+ { "Content is trusted",
+ "wsp.header.push_flag.trusted",
+ FT_UINT8, BASE_DEC, VALS(vals_false_true), 0x02,
+ "The push content is trusted.", HFILL
+ }
+ },
+ { &hf_hdr_push_flag_last,
+ { "Last push message",
+ "wsp.header.push_flag.last",
+ FT_UINT8, BASE_DEC, VALS(vals_false_true), 0x04,
+ "Indicates whether this is the last push message.", HFILL
+ }
+ },
+ { &hf_hdr_profile,
+ { "Profile",
+ "wsp.header.profile",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Profile", HFILL
+ }
+ },
+ { &hf_hdr_profile_diff,
+ { "Profile-Diff",
+ "wsp.header.profile_diff",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Profile-Diff", HFILL
+ }
+ },
+ { &hf_hdr_profile_warning,
+ { "Profile-Warning",
+ "wsp.header.profile_warning",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Profile-Warning", HFILL
+ }
+ },
+ { &hf_hdr_expect,
+ { "Expect",
+ "wsp.header.expect",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Expect", HFILL
+ }
+ },
+ { &hf_hdr_te,
+ { "Te",
+ "wsp.header.te",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Te", HFILL
+ }
+ },
+ { &hf_hdr_trailer,
+ { "Trailer",
+ "wsp.header.trailer",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Trailer", HFILL
+ }
+ },
+ { &hf_hdr_x_wap_tod,
+ { "X-Wap-Tod",
+ "wsp.header.x_wap_tod",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header X-Wap-Tod", HFILL
+ }
+ },
+ { &hf_hdr_content_id,
+ { "Content-Id",
+ "wsp.header.content_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Content-Id", HFILL
+ }
+ },
+ { &hf_hdr_set_cookie,
+ { "Set-Cookie",
+ "wsp.header.set_cookie",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Set-Cookie", HFILL
+ }
+ },
+ { &hf_hdr_cookie,
+ { "Cookie",
+ "wsp.header.cookie",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Cookie", HFILL
+ }
+ },
+ { &hf_hdr_encoding_version,
+ { "Encoding-Version",
+ "wsp.header.encoding_version",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Encoding-Version", HFILL
+ }
+ },
+ { &hf_hdr_x_wap_security,
+ { "X-Wap-Security",
+ "wsp.header.x_wap_security",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header X-Wap-Security", HFILL
+ }
+ },
+ { &hf_hdr_x_wap_application_id,
+ { "X-Wap-Application-Id",
+ "wsp.header.x_wap_application_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header X-Wap-Application-Id", HFILL
+ }
+ },
+ { &hf_hdr_accept_application,
+ { "Accept-Application",
+ "wsp.header.accept_application",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP header Accept-Application", HFILL
+ }
+ },
+
+
+ /*
+ * Openwave headers
+ * Header Code Page: x-up-1
+ */
+
+ /* Textual headers */
+ { &hf_hdr_openwave_x_up_proxy_operator_domain,
+ { "x-up-proxy-operator-domain",
+ "wsp.header.x_up_1.x_up_proxy_operator_domain",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-operator-domain", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_home_page,
+ { "x-up-proxy-home-page",
+ "wsp.header.x_up_1.x_up_proxy_home_page",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-home-page", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_uplink_version,
+ { "x-up-proxy-uplink-version",
+ "wsp.header.x_up_1.x_up_proxy_uplink_version",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-uplink-version", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_ba_realm,
+ { "x-up-proxy-ba-realm",
+ "wsp.header.x_up_1.x_up_proxy_ba_realm",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-ba-realm", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_request_uri,
+ { "x-up-proxy-request-uri",
+ "wsp.header.x_up_1.x_up_proxy_request_uri",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-request-uri", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_bookmark,
+ { "x-up-proxy-bookmark",
+ "wsp.header.x_up_1.x_up_proxy_bookmark",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-bookmark", HFILL
+ }
+ },
+ /* Integer-value headers */
+ { &hf_hdr_openwave_x_up_proxy_push_seq,
+ { "x-up-proxy-push-seq",
+ "wsp.header.x_up_1.x_up_proxy_push_seq",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-push-seq", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_notify,
+ { "x-up-proxy-notify",
+ "wsp.header.x_up_1.x_up_proxy_notify",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-notify", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_net_ask,
+ { "x-up-proxy-net-ask",
+ "wsp.header.x_up_1.x_up_proxy_net_ask",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-net-ask", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_tod,
+ { "x-up-proxy-tod",
+ "wsp.header.x_up_1.x_up_proxy_tod",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-tod", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_ba_enable,
+ { "x-up-proxy-ba-enable",
+ "wsp.header.x_up_1.x_up_proxy_ba_enable",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-ba-enable", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_redirect_enable,
+ { "x-up-proxy-redirect-enable",
+ "wsp.header.x_up_1.x_up_proxy_redirect_enable",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-redirect-enable", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_redirect_status,
+ { "x-up-proxy-redirect-status",
+ "wsp.header.x_up_1.x_up_proxy_redirect_status",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-redirect-status", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_linger,
+ { "x-up-proxy-linger",
+ "wsp.header.x_up_1.x_up_proxy_linger",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-linger", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_enable_trust,
+ { "x-up-proxy-enable-trust",
+ "wsp.header.x_up_1.x_up_proxy_enable_trust",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-enable-trust", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_trust,
+ { "x-up-proxy-trust",
+ "wsp.header.x_up_1.x_up_proxy_trust",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-trust", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_devcap_has_color,
+ { "x-up-devcap-has-color",
+ "wsp.header.x_up_1.x_up_devcap_has_color",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-devcap-has-color", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_devcap_num_softkeys,
+ { "x-up-devcap-num-softkeys",
+ "wsp.header.x_up_1.x_up_devcap_num_softkeys",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-devcap-num-softkeys", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_devcap_softkey_size,
+ { "x-up-devcap-softkey-size",
+ "wsp.header.x_up_1.x_up_devcap_softkey_size",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-devcap-softkey-size", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_devcap_screen_chars,
+ { "x-up-devcap-screen-chars",
+ "wsp.header.x_up_1.x_up_devcap_screen_chars",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-devcap-screen-chars", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_devcap_screen_pixels,
+ { "x-up-devcap-screen-pixels",
+ "wsp.header.x_up_1.x_up_devcap_screen_pixels",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-devcap-screen-pixels", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_devcap_em_size,
+ { "x-up-devcap-em-size",
+ "wsp.header.x_up_1.x_up_devcap_em_size",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-devcap-em-size", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_devcap_screen_depth,
+ { "x-up-devcap-screen-depth",
+ "wsp.header.x_up_1.x_up_devcap_screen_depth",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-devcap-screen-depth", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_devcap_immed_alert,
+ { "x-up-devcap-immed-alert",
+ "wsp.header.x_up_1.x_up_devcap_immed_alert",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-devcap-immed-alert", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_devcap_gui,
+ { "x-up-devcap-gui",
+ "wsp.header.x_up_1.x_up_devcap_gui",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-devcap-gui", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_trans_charset,
+ { "x-up-proxy-trans-charset",
+ "wsp.header.x_up_1.x_up_proxy_trans_charset",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-trans-charset", HFILL
+ }
+ },
+ { &hf_hdr_openwave_x_up_proxy_push_accept,
+ { "x-up-proxy-push-accept",
+ "wsp.header.x_up_1.x_up_proxy_push_accept",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-push-accept", HFILL
+ }
+ },
+
+ /* Not used for now
+ { &hf_hdr_openwave_x_up_proxy_client_id,
+ { "x-up-proxy-client-id",
+ "wsp.header.x_up_1.x_up_proxy_client_id",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "WSP Openwave header x-up-proxy-client-id", HFILL
+ }
+ },
+ */
+
+ /*
+ * Header value parameters
+ */
+
+ { &hf_parameter_q,
+ { "Q",
+ "wsp.parameter.q",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Q parameter", HFILL
+ }
+ },
+ { &hf_parameter_charset,
+ { "Charset",
+ "wsp.parameter.charset",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Charset parameter", HFILL
+ }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_wsp,
+ &ett_header, /* Header field subtree */
+ &ett_headers, /* Subtree for WSP headers */
+ &ett_capabilities, /* CO-WSP Session Capabilities */
+ &ett_capability, /* CO-WSP Session single Capability */
+ &ett_post,
+ &ett_redirect_flags,
+ &ett_address_flags,
+ &ett_multiparts,
+ &ett_mpartlist,
+ &ett_addresses, /* Addresses */
+ &ett_address, /* Single address */
+ };
+
+/* Register the protocol name and description */
+ proto_wsp = proto_register_protocol(
+ "Wireless Session Protocol", /* protocol name for use by ethereal */
+ "WSP", /* short version of name */
+ "wsp" /* Abbreviated protocol name,
+ should Match IANA:
+ < URL:http://www.iana.org/assignments/port-numbers/ >
+ */
+ );
+ wsp_tap = register_tap("wsp");
+ /* Init the hash table */
+/* wsp_sessions = g_hash_table_new(
+ (GHashFunc) wsp_session_hash,
+ (GEqualFunc)wsp_session_equal);*/
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_wsp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("wsp-co", dissect_wsp_fromwap_co, proto_wsp);
+ register_dissector("wsp-cl", dissect_wsp_fromwap_cl, proto_wsp);
+ /* As the media types for WSP and HTTP are the same, the WSP dissector
+ * uses the same string dissector table as the HTTP protocol. */
+ media_type_table = find_dissector_table("media_type");
+ register_heur_dissector_list("wsp", &heur_subdissector_list);
+
+ wsp_fromudp_handle = create_dissector_handle(dissect_wsp_fromudp,
+ proto_wsp);
+}
+
+void
+proto_reg_handoff_wsp(void)
+{
+ /*
+ * Get a handle for the WTP-over-UDP and the generic media dissectors.
+ */
+ wtp_fromudp_handle = find_dissector("wtp-udp");
+ media_handle = find_dissector("media");
+ wbxml_uaprof_handle = find_dissector("wbxml-uaprof");
+
+ /* Only connection-less WSP has no previous handler */
+ dissector_add("udp.port", UDP_PORT_WSP, wsp_fromudp_handle);
+ dissector_add("udp.port", UDP_PORT_WSP_PUSH, wsp_fromudp_handle);
+
+ /* GSM SMS UD dissector can also carry WSP */
+ dissector_add("gsm-sms-ud.udh.port", UDP_PORT_WSP, wsp_fromudp_handle);
+ dissector_add("gsm-sms-ud.udh.port", UDP_PORT_WSP_PUSH, wsp_fromudp_handle);
+
+ /* This dissector is also called from the WTP and WTLS dissectors */
+}
+
+/*
+ * Session Initiation Request
+ */
+
+/* Register the protocol with Ethereal */
+void
+proto_register_sir(void)
+{
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_sir_section,
+ { "Session Initiation Request",
+ "wap.sir",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Session Initiation Request content", HFILL
+ }
+ },
+ { &hf_sir_version,
+ { "Version",
+ "wap.sir.version",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Version of the Session Initiation Request document", HFILL
+ }
+ },
+ { &hf_sir_app_id_list_len,
+ { "Application-ID List Length",
+ "wap.sir.app_id_list.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Length of the Application-ID list (bytes)", HFILL
+ }
+ },
+ { &hf_sir_app_id_list,
+ { "Application-ID List",
+ "wap.sir.app_id_list",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Application-ID list", HFILL
+ }
+ },
+ { &hf_sir_wsp_contact_points_len,
+ { "WSP Contact Points Length",
+ "wap.sir.wsp_contact_points.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Length of the WSP Contact Points list (bytes)", HFILL
+ }
+ },
+ { &hf_sir_wsp_contact_points,
+ { "WSP Contact Points",
+ "wap.sir.wsp_contact_points",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "WSP Contact Points list", HFILL
+ }
+ },
+ { &hf_sir_contact_points_len,
+ { "Non-WSP Contact Points Length",
+ "wap.sir.contact_points.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Length of the Non-WSP Contact Points list (bytes)", HFILL
+ }
+ },
+ { &hf_sir_contact_points,
+ { "Non-WSP Contact Points",
+ "wap.sir.contact_points",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Non-WSP Contact Points list", HFILL
+ }
+ },
+ { &hf_sir_protocol_options_len,
+ { "Protocol Options List Entries",
+ "wap.sir.protocol_options.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Number of entries in the Protocol Options list", HFILL
+ }
+ },
+ { &hf_sir_protocol_options,
+ { "Protocol Options",
+ "wap.sir.protocol_options",
+ FT_UINT16, BASE_DEC, VALS(vals_sir_protocol_options), 0x00,
+ "Protocol Options list", HFILL
+ }
+ },
+ { &hf_sir_prov_url_len,
+ { "X-Wap-ProvURL Length",
+ "wap.sir.prov_url.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Length of the X-Wap-ProvURL (Identifies the WAP Client Provisioning Context)", HFILL
+ }
+ },
+ { &hf_sir_prov_url,
+ { "X-Wap-ProvURL",
+ "wap.sir.prov_url",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "X-Wap-ProvURL (Identifies the WAP Client Provisioning Context)", HFILL
+ }
+ },
+ { &hf_sir_cpi_tag_len,
+ { "CPITag List Entries",
+ "wap.sir.cpi_tag.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Number of entries in the CPITag list", HFILL
+ }
+ },
+ { &hf_sir_cpi_tag,
+ { "CPITag",
+ "wap.sir.cpi_tag",
+ FT_BYTES, BASE_HEX, NULL, 0x00,
+ "CPITag (OTA-HTTP)", HFILL
+ }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_sir, /* Session Initiation Request */
+ };
+
+ /* Register the dissector */
+ proto_sir = proto_register_protocol(
+ "WAP Session Initiation Request", /* protocol name for use by ethereal */
+ "WAP SIR", /* short version of name */
+ "wap-sir" /* Abbreviated protocol name,
+ should Match IANA:
+ < URL:http://www.iana.org/assignments/port-numbers/ >
+ */
+ );
+
+ /* Register header fields and protocol subtrees */
+ proto_register_field_array(proto_sir, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_sir(void)
+{
+ dissector_handle_t sir_handle;
+
+ sir_handle = create_dissector_handle(dissect_sir, proto_sir);
+
+ /* Add dissector bindings for SIR dissection */
+ dissector_add_string("media_type", "application/vnd.wap.sia", sir_handle);
+}
diff --git a/epan/dissectors/packet-wsp.h b/epan/dissectors/packet-wsp.h
new file mode 100644
index 0000000000..cd3773e32e
--- /dev/null
+++ b/epan/dissectors/packet-wsp.h
@@ -0,0 +1,60 @@
+/* packet-wsp.h
+ *
+ * Declarations for disassembly of WSP component of WAP traffic.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * WAP dissector based on original work by Ben Fowler
+ * Updated by Neil Hunter <neil.hunter@energis-squared.com>
+ * WTLS support by Alexandre P. Ferreira (Splice IP)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_WSP_H__
+#define __PACKET_WSP_H__
+
+
+/* These reason codes are used in the WTP dissector as the WTP user is
+ * assumed to be WSP */
+extern const value_string vals_wsp_reason_codes[];
+
+/*
+ * the following allows TAP code access to the messages
+ * without having to duplicate it. With MSVC and a
+ * libethereal.dll, we need a special declaration.
+ */
+ETH_VAR_IMPORT const value_string vals_pdu_type[];
+ETH_VAR_IMPORT const value_string vals_status[];
+/*
+ * exported functionality
+ */
+void add_post_data (proto_tree *, tvbuff_t *, guint, const char *,
+ packet_info *);
+guint32 add_content_type (proto_tree *tree, tvbuff_t *tvb,
+ guint32 val_start,
+ guint32 *well_known_content, const char **textual_content);
+
+/* statistics */
+typedef struct _wsp_info_value_t /* see README.tapping and tap-wspstat.c */
+{
+ gint status_code;
+ guint8 pdut;
+} wsp_info_value_t;
+#endif /* packet-wsp.h */
diff --git a/epan/dissectors/packet-wtls.c b/epan/dissectors/packet-wtls.c
new file mode 100644
index 0000000000..50e0dbfa5a
--- /dev/null
+++ b/epan/dissectors/packet-wtls.c
@@ -0,0 +1,1627 @@
+/* packet-wtls.c
+ *
+ * Routines to dissect WTLS component of WAP traffic.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * WAP dissector based on original work by Ben Fowler
+ * Updated by Neil Hunter <neil.hunter@energis-squared.com>
+ * WTLS support by Alexandre P. Ferreira (Splice IP)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-wap.h"
+#include "packet-wtls.h"
+
+/* File scoped variables for the protocol and registered fields */
+static int proto_wtls = HF_EMPTY;
+
+/* These fields used by fixed part of header */
+static int hf_wtls_record = HF_EMPTY;
+static int hf_wtls_record_type = HF_EMPTY;
+static int hf_wtls_record_length = HF_EMPTY;
+static int hf_wtls_record_sequence = HF_EMPTY;
+static int hf_wtls_record_ciphered = HF_EMPTY;
+static int hf_wtls_hands = HF_EMPTY;
+static int hf_wtls_hands_type = HF_EMPTY;
+static int hf_wtls_hands_length = HF_EMPTY;
+static int hf_wtls_hands_cli_hello = HF_EMPTY;
+static int hf_wtls_hands_cli_hello_version = HF_EMPTY;
+static int hf_wtls_hands_cli_hello_gmt = HF_EMPTY;
+static int hf_wtls_hands_cli_hello_random = HF_EMPTY;
+static int hf_wtls_hands_cli_hello_session = HF_EMPTY;
+static int hf_wtls_hands_cli_hello_session_str = HF_EMPTY;
+static int hf_wtls_hands_cli_hello_cli_key_id = HF_EMPTY;
+static int hf_wtls_hands_cli_hello_cli_key_len = HF_EMPTY;
+static int hf_wtls_hands_cli_hello_trust_key_id = HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_exchange =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_exchange_suite =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_parameter_index =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_parameter_set =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_identifier_type =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_identifier_charset =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_identifier_size =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_identifier =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_identifier_str =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_cipher_suite =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_cipher_suite_item =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_compression_methods =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_compression =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_sequence_mode =HF_EMPTY;
+static int hf_wtls_hands_cli_hello_key_refresh =HF_EMPTY;
+static int hf_wtls_hands_serv_hello = HF_EMPTY;
+static int hf_wtls_hands_serv_hello_version = HF_EMPTY;
+static int hf_wtls_hands_serv_hello_gmt = HF_EMPTY;
+static int hf_wtls_hands_serv_hello_random = HF_EMPTY;
+static int hf_wtls_hands_serv_hello_session = HF_EMPTY;
+static int hf_wtls_hands_serv_hello_session_str = HF_EMPTY;
+static int hf_wtls_hands_serv_hello_cli_key_id =HF_EMPTY;
+static int hf_wtls_hands_serv_hello_cipher_suite_item =HF_EMPTY;
+static int hf_wtls_hands_serv_hello_cipher_bulk =HF_EMPTY;
+static int hf_wtls_hands_serv_hello_cipher_mac =HF_EMPTY;
+static int hf_wtls_hands_serv_hello_compression =HF_EMPTY;
+static int hf_wtls_hands_serv_hello_sequence_mode =HF_EMPTY;
+static int hf_wtls_hands_serv_hello_key_refresh =HF_EMPTY;
+static int hf_wtls_hands_certificates =HF_EMPTY;
+static int hf_wtls_hands_certificate =HF_EMPTY;
+static int hf_wtls_hands_certificate_type =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_version =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_signature_type =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_issuer_type =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_issuer_charset =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_issuer_size =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_issuer_name =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_valid_not_before =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_valid_not_after =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_subject_type =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_subject_charset =HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_subject_size = HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_subject_name = HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_public_key_type = HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_key_parameter_index = HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_key_parameter_set = HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_rsa_exponent = HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_rsa_modules = HF_EMPTY;
+static int hf_wtls_hands_certificate_wtls_signature = HF_EMPTY;
+static int hf_wtls_alert = HF_EMPTY;
+static int hf_wtls_alert_level = HF_EMPTY;
+static int hf_wtls_alert_description = HF_EMPTY;
+
+/* Initialize the subtree pointers */
+static gint ett_wtls = ETT_EMPTY;
+static gint ett_wtls_rec = ETT_EMPTY;
+static gint ett_wtls_msg_type = ETT_EMPTY;
+static gint ett_wtls_msg_type_item = ETT_EMPTY;
+static gint ett_wtls_msg_type_item_sub = ETT_EMPTY;
+static gint ett_wtls_msg_type_item_sub_sub = ETT_EMPTY;
+
+static const value_string wtls_vals_record_type[] = {
+ { 1, "change_cipher_data" },
+ { 2, "alert" },
+ { 3, "handshake" },
+ { 4, "application_data" },
+ { 0, NULL }
+};
+
+static const value_string wtls_vals_cipher_bulk[] = {
+ { 0, "Null" },
+ { 1, "RC5 CBC 40" },
+ { 2, "RC5 CBC 56" },
+ { 3, "RC5 CBC" },
+ { 4, "DES CBC 40" },
+ { 5, "DES CBC" },
+ { 6, "3DES CBC cwEDE40" },
+ { 7, "IDEA CBC 40" },
+ { 8, "IDEA CBC 56" },
+ { 9, "IDEA CBC" },
+ { 0, NULL }
+};
+
+static const value_string wtls_vals_cipher_mac[] = {
+ { 0, "SHA 0" },
+ { 1, "SHA 40 " },
+ { 2, "SHA 80" },
+ { 3, "SHA" },
+ { 4, "SHA XOR 40" },
+ { 5, "MD5 40" },
+ { 6, "MD5 80" },
+ { 7, "MD5" },
+ { 0, NULL }
+};
+
+static const value_string wtls_vals_handshake_type[] = {
+ { 0, "Hello Request" },
+ { 1, "Client Hello" },
+ { 2, "Server Hello" },
+ { 11, "Certificate" },
+ { 12, "Server Key Exchange" },
+ { 13, "Certificate Request" },
+ { 14, "Server Hello Done" },
+ { 15, "Certificate Verify" },
+ { 16, "Client Key Exchange" },
+ { 20, "Finished" },
+ { 0x00, NULL }
+};
+
+static const value_string wtls_vals_key_exchange_suite[] = {
+ { 0, "NULL" },
+ { 1, "Shared Secret" },
+ { 2, "Diffie Hellman Anonymous" },
+ { 3, "Diffie Hellman Anonymous 512" },
+ { 4, "Diffie Hellman Anonymous 768" },
+ { 5, "RSA Anonymous" },
+ { 6, "RSA Anonymous 512" },
+ { 7, "RSA Anonymous 768" },
+ { 8, "RSA" },
+ { 9, "RSA 512" },
+ { 10, "RSA 768" },
+ { 11, "EC Diffie Hellman Anonymous" },
+ { 12, "EC Diffie Hellman Anonymous 113" },
+ { 13, "EC Diffie Hellman Anonymous 131" },
+ { 14, "EC Diffie Hellman ECDSA" },
+ { 15, "EC Diffie Hellman Anonymous Uncomp" },
+ { 16, "EC Diffie Hellman Anonymous Uncomp 113" },
+ { 17, "EC Diffie Hellman Anonymous Uncomp 131" },
+ { 18, "EC Diffie Hellman ECDSA Uncomp" },
+ { 0x00, NULL }
+};
+
+static const value_string wtls_vals_identifier_type[] = {
+ { 0, "No identifier" },
+ { 1, "Textual Name" },
+ { 2, "Binary Name" },
+ { 254, "SHA-1 Hash of Public Key" },
+ { 255, "x509 Distinguished Name" },
+ { 0x00, NULL }
+};
+
+static const value_string wtls_vals_certificate_type[] = {
+ { 1, "WTLS" },
+ { 2, "X.509" },
+ { 3, "X.968" },
+ { 4, "URL" },
+ { 0x00, NULL }
+};
+
+static const value_string wtls_vals_compression[] = {
+ { 0, "Null" },
+ { 0x00, NULL }
+};
+
+static const value_string wtls_vals_sequence_mode[] = {
+ { 0, "Off" },
+ { 1, "Implicit" },
+ { 2, "Explicit" },
+ { 0x00, NULL }
+};
+
+static const value_string wtls_vals_certificate_signature[] = {
+ { 0, "Anonymous" },
+ { 1, "ECDSA_SHA" },
+ { 2, "RSA_SHA" },
+ { 0x00, NULL }
+};
+
+static const value_string wtls_vals_public_key_type[] = {
+ { 2, "RSA" },
+ { 3, "ECDH" },
+ { 4, "ECSA" },
+ { 0x00, NULL }
+};
+
+static const value_string wtls_vals_alert_level[] = {
+ { 1, "Warning" },
+ { 2, "Critical" },
+ { 3, "Fatal" },
+ { 0x00, NULL }
+};
+
+static const value_string wtls_vals_alert_description[] = {
+ { 0,"connection_close_notify"},
+ { 1,"session_close_notify"},
+ { 5,"no_connection"},
+ { 10,"unexpected_message"},
+ { 11,"time_required"},
+ { 20,"bad_record_mac"},
+ { 21,"decryption_failed"},
+ { 22,"record_overflow"},
+ { 30,"decompression_failure"},
+ { 40,"handshake_failure"},
+ { 42,"bad_certificate"},
+ { 43,"unsupported_certificate"},
+ { 44,"certificate_revoked"},
+ { 45,"certificate_expired"},
+ { 46,"certificate_unknown"},
+ { 47,"illegal_parameter"},
+ { 48,"unknown_ca"},
+ { 49,"access_denied"},
+ { 50,"decode_error"},
+ { 51,"decrypt_error"},
+ { 52,"unknown_key_id"},
+ { 53,"disabled_key_id"},
+ { 54,"key_exchange_disabled"},
+ { 55,"session_not_ready"},
+ { 56,"unknown_parameter_index"},
+ { 57,"duplicate_finished_received"},
+ { 60,"export_restriction"},
+ { 70,"protocol_version"},
+ { 71,"insufficient_security"},
+ { 80,"internal_error"},
+ { 90,"user_canceled"},
+ { 100,"no_renegotiation"},
+ { 0x00, NULL }
+};
+
+#define WTLS_RECORD_TYPE_LENGTH 0x80
+#define WTLS_RECORD_TYPE_SEQUENCE 0x40
+#define WTLS_RECORD_TYPE_CIPHER_CUR 0x20
+#define WTLS_RECORD_CONTENT_TYPE 0x0f
+
+#define WTLS_ALERT 0x02
+#define WTLS_PLAIN_HANDSHAKE 0x03
+
+#define WTLS_HANDSHAKE_CLIENT_HELLO 1
+#define WTLS_HANDSHAKE_SERVER_HELLO 2
+#define WTLS_HANDSHAKE_CERTIFICATE 11
+
+#define CERTIFICATE_WTLS 1
+#define CERTIFICATE_X509 2
+#define CERTIFICATE_X968 3
+#define CERTIFICATE_URL 4
+
+#define IDENTIFIER_NULL 0
+#define IDENTIFIER_TEXT 1
+#define IDENTIFIER_BIN 2
+#define IDENTIFIER_SHA_1 254
+#define IDENTIFIER_X509 255
+
+#define PUBLIC_KEY_RSA 2
+#define PUBLIC_KEY_ECDH 3
+#define PUBLIC_KEY_ECDSA 4
+
+static void dissect_wtls_handshake (proto_tree *, tvbuff_t *, guint, guint);
+
+/* Code to actually dissect the packets */
+static void
+dissect_wtls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+
+ char pdut;
+ char pdu_msg_type;
+ guint count = 0;
+ guint offset_wtls = 0;
+
+/* Set up structures we will need to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *wtls_tree;
+ proto_tree *wtls_rec_tree;
+ proto_tree *wtls_msg_type_tree;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ switch ( pinfo->match_port )
+ {
+ case UDP_PORT_WTLS_WSP:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WTLS+WSP" );
+ break;
+ case UDP_PORT_WTLS_WTP_WSP:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WTLS+WTP+WSP" );
+ break;
+ }
+ }
+
+ /* Develop the string to put in the Info column */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, "WTLS" );
+ };
+
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_wtls, tvb, offset_wtls,
+ -1, bo_little_endian);
+ wtls_tree = proto_item_add_subtree(ti, ett_wtls);
+
+ for (offset_wtls=0; offset_wtls < (tvb_reported_length(tvb)-1);) {
+ pdut = tvb_get_guint8 (tvb, offset_wtls);
+
+ offset = offset_wtls+1;
+
+ if (pdut & WTLS_RECORD_TYPE_SEQUENCE) {
+ offset+=2;
+ }
+ if (pdut & WTLS_RECORD_TYPE_LENGTH) {
+ count = tvb_get_ntohs(tvb, offset);
+ offset+=2;
+ count += offset-offset_wtls;
+ }
+ else {
+ count = tvb_length_remaining (tvb, offset_wtls);
+ }
+ ti = proto_tree_add_uint(wtls_tree, hf_wtls_record, tvb, offset_wtls,
+ count, pdut);
+ wtls_rec_tree = proto_item_add_subtree(ti, ett_wtls_rec);
+
+ offset = offset_wtls;
+
+ ti = proto_tree_add_item (wtls_rec_tree, hf_wtls_record_type,
+ tvb,offset,1,bo_big_endian);
+
+ offset++;
+
+ offset_wtls += count;
+
+ if (pdut & WTLS_RECORD_TYPE_SEQUENCE) {
+ ti = proto_tree_add_item (wtls_rec_tree, hf_wtls_record_sequence,
+ tvb,offset,2,bo_big_endian);
+ offset+=2;
+ }
+ if (pdut & WTLS_RECORD_TYPE_LENGTH) {
+ count = tvb_get_ntohs(tvb, offset);
+ ti = proto_tree_add_item (wtls_rec_tree, hf_wtls_record_length,
+ tvb,offset,2,bo_big_endian);
+ offset+=2;
+ }
+ else {
+ count = tvb_length_remaining (tvb, offset);
+ }
+
+ if (pdut & WTLS_RECORD_TYPE_CIPHER_CUR) {
+ ti = proto_tree_add_item (wtls_rec_tree, hf_wtls_record_ciphered,
+ tvb,offset,count,bo_big_endian);
+ continue;
+ }
+
+ switch (pdut & WTLS_RECORD_CONTENT_TYPE) {
+ case WTLS_PLAIN_HANDSHAKE :
+ dissect_wtls_handshake(wtls_rec_tree,tvb,offset,count);
+ break;
+ case WTLS_ALERT :
+ ti = proto_tree_add_item(wtls_rec_tree, hf_wtls_alert, tvb, offset,
+ count, bo_little_endian);
+ wtls_msg_type_tree = proto_item_add_subtree(ti, ett_wtls_msg_type);
+ pdu_msg_type = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item (wtls_msg_type_tree, hf_wtls_alert_level,
+ tvb,offset,1,bo_big_endian);
+ offset+=1;
+ count = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_item (wtls_msg_type_tree, hf_wtls_alert_description,
+ tvb,offset,1,bo_big_endian);
+ offset+=1;
+ default:
+ offset+=count;
+ break;
+ }
+ }
+ }
+}
+
+static int
+add_text_identifier(tvbuff_t *tvb, int offset, int hf_charset,
+ int hf_size, int hf_str, proto_tree *tree)
+{
+ guint8 size;
+ int client_size = 0;
+
+ proto_tree_add_item(tree, hf_charset, tvb, offset, 2, bo_big_endian);
+ offset+=2;
+ size = tvb_get_guint8 (tvb, offset);
+ proto_tree_add_item(tree, hf_size, tvb, offset, 1, bo_big_endian);
+ offset++;
+ proto_tree_add_item(tree, hf_str, tvb, offset, size, bo_big_endian);
+ offset+=size;
+ client_size+=size+3;
+#ifdef DEBUG
+ fprintf(stderr, "text id size = %d, client_size = %d\n",
+ size, client_size);
+#endif /* DEBUG */
+ return client_size;
+}
+
+static void
+dissect_wtls_handshake(proto_tree *tree, tvbuff_t *tvb, guint offset, guint count)
+{
+ char pdu_msg_type;
+ nstime_t timeValue;
+ int client_size = 0;
+ guint value = 0;
+ int size = 0;
+ guint public_key = 0;
+ guint signature = 0;
+ char valStr[1024];
+ char *valBulk = NULL;
+ char *valMac = NULL;
+
+ proto_item *ti;
+ proto_item *cli_key_item;
+ proto_tree *wtls_msg_type_tree;
+ proto_tree *wtls_msg_type_item_tree;
+ proto_tree *wtls_msg_type_item_sub_tree;
+ proto_tree *wtls_msg_type_item_sub_sub_tree;
+
+ pdu_msg_type = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_uint(tree, hf_wtls_hands, tvb, offset,count, pdu_msg_type);
+ wtls_msg_type_tree = proto_item_add_subtree(ti, ett_wtls_msg_type);
+
+ ti = proto_tree_add_item (wtls_msg_type_tree, hf_wtls_hands_type,
+ tvb,offset,1,bo_big_endian);
+ offset+=1;
+ count = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_item (wtls_msg_type_tree, hf_wtls_hands_length,
+ tvb,offset,2,bo_big_endian);
+ offset+=2;
+ switch(pdu_msg_type) {
+ case WTLS_HANDSHAKE_CLIENT_HELLO :
+ ti = proto_tree_add_item(wtls_msg_type_tree, hf_wtls_hands_cli_hello, tvb, offset,
+ count, bo_little_endian);
+ wtls_msg_type_item_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item);
+ ti = proto_tree_add_item (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_version,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ timeValue.secs = tvb_get_ntohl (tvb, offset);
+ timeValue.nsecs = 0;
+ ti = proto_tree_add_time (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_gmt, tvb,
+ offset, 4, &timeValue);
+ offset+=4;
+ ti = proto_tree_add_item (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_random,
+ tvb,offset,12,bo_big_endian);
+ offset+=12;
+ count = tvb_get_guint8(tvb, offset);
+ switch(count) {
+ case 0:
+ ti = proto_tree_add_string (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_session_str,
+ tvb,offset,count+1,"NULL");
+ break;
+ case 1 :
+ ti = proto_tree_add_uint (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_session,
+ tvb,offset,count+1,tvb_get_guint8(tvb,offset+1));
+ break;
+ case 2 :
+ ti = proto_tree_add_uint (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_session,
+ tvb,offset,count+1,tvb_get_ntohs(tvb,offset+1));
+ break;
+ case 3 :
+ ti = proto_tree_add_uint (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_session,
+ tvb,offset,count+1,tvb_get_ntoh24(tvb,offset+1));
+ break;
+ case 4 :
+ ti = proto_tree_add_uint (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_session,
+ tvb,offset,count+1,tvb_get_ntohl(tvb,offset+1));
+ break;
+ default:
+ ti = proto_tree_add_string (wtls_msg_type_item_tree, hf_wtls_hands_cli_hello_session_str,
+ tvb,offset,count+1,"Too big");
+ break;
+ }
+ offset+=1+count;
+
+ /* process client_key_ids structure */
+ count = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_cli_hello_cli_key_id, tvb, offset,
+ count+2, bo_little_endian);
+ wtls_msg_type_item_sub_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item_sub);
+
+ /* display length of client_key_ids structure */
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_cli_hello_cli_key_len,
+ tvb,offset,2,bo_big_endian);
+ offset+=2;
+
+ /* cycle through client_key_ids entries */
+ for (;count > 0;count-=client_size) {
+ /* get encryption suite id (one byte) */
+ value = tvb_get_guint8 (tvb, offset);
+ cli_key_item = proto_tree_add_uint(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_cli_hello_key_exchange, tvb, offset,1,
+ value);
+ client_size=1;
+ wtls_msg_type_item_sub_sub_tree = proto_item_add_subtree(cli_key_item,
+ ett_wtls_msg_type_item_sub_sub);
+ ti = proto_tree_add_uint(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_exchange_suite,
+ tvb,offset,1,value);
+ offset++;
+#ifdef DEBUG
+ fprintf(stderr, "encryption suite = %d, client_size = %d\n", value, client_size);
+#endif /* DEBUG */
+
+ /* get parameter index (one byte) */
+ value = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_parameter_index,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ client_size++;
+#ifdef DEBUG
+ fprintf(stderr, "parameter index = %d, client_size = %d\n", value, client_size);
+#endif /* DEBUG */
+
+ /* explicit parameters present in next field */
+ if (value == 0xff) {
+ size = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_parameter_set,
+ tvb,offset,size+2,bo_big_endian);
+ offset+=size+2;
+ client_size+=size+2;
+ }
+
+ /* get identifier type */
+ value = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier_type,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ client_size++;
+#ifdef DEBUG
+ fprintf(stderr, "identifier type = %d, client_size = %d\n", value, client_size);
+#endif /* DEBUG */
+
+ /* identifier present in next field */
+ /* note: value 0x0 means no identifier */
+ switch(value) {
+ case IDENTIFIER_TEXT :
+ /* text identifier */
+ /* not tested */
+ size = add_text_identifier(
+ tvb, offset,
+ hf_wtls_hands_cli_hello_key_identifier_charset,
+ hf_wtls_hands_cli_hello_key_identifier_size,
+ hf_wtls_hands_cli_hello_key_identifier_str,
+ wtls_msg_type_item_sub_sub_tree);
+ offset += size;
+ client_size += size;
+ break;
+ case IDENTIFIER_BIN :
+ /* binary identifier */
+ size = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier_size,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier,
+ tvb,offset,size,bo_big_endian);
+ offset+=size;
+ client_size+=size+1;
+#ifdef DEBUG
+ fprintf(stderr, "binary id size = %d, client_size = %d\n",
+ size, client_size);
+#endif /* DEBUG */
+ break;
+ case IDENTIFIER_SHA_1 :
+ /* SHA-1 hash of the public key */
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier,
+ tvb,offset,20,bo_big_endian);
+ offset+=20;
+ client_size+=20;
+#ifdef DEBUG
+ fprintf(stderr, "SHA-1 hash size = 20, client_size = %d\n",
+ client_size);
+#endif /* DEBUG */
+ break;
+ case IDENTIFIER_X509 :
+ /* X.509 distinguished name */
+ /* not tested */
+ size = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier_size,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier,
+ tvb,offset,size,bo_big_endian);
+ offset+=size;
+ client_size+=size+1;
+#ifdef DEBUG
+ fprintf(stderr, "X.509 name size = %d, client_size = %d\n",
+ size, client_size);
+#endif /* DEBUG */
+ break;
+ }
+
+ proto_item_set_len(cli_key_item, client_size);
+ }
+
+ /* process trusted_keys structure */
+ count = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_cli_hello_trust_key_id, tvb, offset,
+ count+2, bo_little_endian);
+ wtls_msg_type_item_sub_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item_sub);
+
+ /* display length of trusted_keys structure */
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_cli_hello_cli_key_len,
+ tvb,offset,2,bo_big_endian);
+
+ offset+=2;
+ for (;count > 0;count-=client_size) {
+ /* get encryption suite id (one byte) */
+ value = tvb_get_guint8 (tvb, offset);
+ cli_key_item = proto_tree_add_uint(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_cli_hello_key_exchange, tvb, offset,1,
+ value);
+ client_size=1;
+ wtls_msg_type_item_sub_sub_tree = proto_item_add_subtree(cli_key_item,
+ ett_wtls_msg_type_item_sub_sub);
+ ti = proto_tree_add_uint(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_exchange_suite,
+ tvb,offset,1,value);
+ offset++;
+#ifdef DEBUG
+ fprintf(stderr, "encryption suite = %d, client_size = %d\n", value, client_size);
+#endif /* DEBUG */
+
+ /* get parameter index (one byte) */
+ value = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_parameter_index,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ client_size++;
+#ifdef DEBUG
+ fprintf(stderr, "parameter index = %d, client_size = %d\n", value, client_size);
+#endif /* DEBUG */
+
+ /* explicit parameters present in next field */
+ if (value == 0xff) {
+ size = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_parameter_set,
+ tvb,offset,size+2,bo_big_endian);
+ offset+=size+2;
+ client_size+=size+2;
+ }
+
+ /* get identifier type */
+ value = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier_type,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ client_size++;
+#ifdef DEBUG
+ fprintf(stderr, "identifier type = %d, client_size = %d\n", value, client_size);
+#endif /* DEBUG */
+
+ /* identifier present in next field */
+ /* note: value 0x0 means no identifier */
+ switch (value) {
+ case IDENTIFIER_TEXT :
+ /* text identifier */
+ /* not tested */
+ size = add_text_identifier(
+ tvb, offset,
+ hf_wtls_hands_cli_hello_key_identifier_charset,
+ hf_wtls_hands_cli_hello_key_identifier_size,
+ hf_wtls_hands_cli_hello_key_identifier_str,
+ wtls_msg_type_item_sub_sub_tree);
+ offset += size;
+ client_size += size;
+ break;
+ case IDENTIFIER_BIN :
+ /* binary identifier */
+ size = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier_size,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier,
+ tvb,offset,size,bo_big_endian);
+ offset+=size;
+ client_size+=size+1;
+#ifdef DEBUG
+ fprintf(stderr, "binary id size = %d, client_size = %d\n",
+ size, client_size);
+#endif /* DEBUG */
+ break;
+ case IDENTIFIER_SHA_1 :
+ /* SHA-1 hash of the public key */
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier,
+ tvb,offset,20,bo_big_endian);
+ offset+=20;
+ client_size+=20;
+#ifdef DEBUG
+ fprintf(stderr, "SHA-1 hash size = 20, client_size = %d\n",
+ client_size);
+#endif /* DEBUG */
+ break;
+ case IDENTIFIER_X509 :
+ /* X.509 distinguished name */
+ /* not tested */
+ size = tvb_get_guint8 (tvb, offset);
+ /* need to fetch identifier and display it */
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier_size,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_sub_tree,
+ hf_wtls_hands_cli_hello_key_identifier,
+ tvb,offset,size,bo_big_endian);
+ offset+=size;
+ client_size+=size+1;
+#ifdef DEBUG
+ fprintf(stderr, "X.509 name size = %d, client_size = %d\n",
+ size, client_size);
+#endif /* DEBUG */
+ break;
+ }
+ proto_item_set_len(cli_key_item, client_size);
+ }
+
+ /* process cipher_suites structure */
+ count = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_cli_hello_cipher_suite, tvb, offset,
+ count+1, bo_little_endian);
+ wtls_msg_type_item_sub_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item_sub);
+ offset+=1;
+ for (;count > 0;count-=client_size) {
+ value = tvb_get_guint8 (tvb, offset);
+ valBulk = match_strval(value, wtls_vals_cipher_bulk);
+ offset++;
+ client_size=1;
+ valMac = match_strval(tvb_get_guint8 (tvb, offset), wtls_vals_cipher_mac);
+ if (valBulk != NULL)
+ {
+ if (valMac != NULL)
+ {
+ snprintf(valStr,1024,"%s, %s",valBulk,valMac);
+ }
+ else
+ {
+ snprintf(valStr,1024,"%s, Unknown MAC (0x%02x)",valBulk,tvb_get_guint8 (tvb, offset));
+ }
+ }
+ else
+ {
+ if (valMac != NULL)
+ {
+ snprintf(valStr,1024,"Unknown Bulk (0x%02x), %s",value,valMac);
+ }
+ else
+ {
+ snprintf(valStr,1024,"Unknown Bulk (0x%02x), Unknown MAC (0x%02x)",value,
+ tvb_get_guint8 (tvb, offset));
+ }
+ }
+ offset++;
+ client_size++;
+ cli_key_item = proto_tree_add_string(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_cli_hello_cipher_suite_item, tvb, offset-2,2,
+ valStr);
+ }
+ count = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_cli_hello_compression_methods, tvb, offset,
+ count+1, bo_little_endian);
+ wtls_msg_type_item_sub_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item_sub);
+ offset+=1;
+ for (;count > 0;count-=client_size) {
+ client_size=0;
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_cli_hello_compression, tvb, offset,1,
+ bo_little_endian);
+ offset++;
+ client_size++;
+ }
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_cli_hello_sequence_mode, tvb, offset,
+ 1, bo_little_endian);
+ offset++;
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_cli_hello_key_refresh, tvb, offset,
+ 1, bo_little_endian);
+ break;
+ case WTLS_HANDSHAKE_SERVER_HELLO :
+ ti = proto_tree_add_item(wtls_msg_type_tree, hf_wtls_hands_serv_hello, tvb, offset,
+ count, bo_little_endian);
+ wtls_msg_type_item_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item);
+ ti = proto_tree_add_item (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_version,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ timeValue.secs = tvb_get_ntohl (tvb, offset);
+ timeValue.nsecs = 0;
+ ti = proto_tree_add_time (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_gmt, tvb,
+ offset, 4, &timeValue);
+ offset+=4;
+ ti = proto_tree_add_item (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_random,
+ tvb,offset,12,bo_big_endian);
+ offset+=12;
+ count = tvb_get_guint8(tvb, offset);
+ switch(count) {
+ case 0:
+ ti = proto_tree_add_string (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_session_str,
+ tvb,offset,count+1,"NULL");
+ break;
+ case 1 :
+ ti = proto_tree_add_uint (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_session,
+ tvb,offset,count+1,tvb_get_guint8(tvb,offset+1));
+ break;
+ case 2 :
+ ti = proto_tree_add_uint (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_session,
+ tvb,offset,count+1,tvb_get_ntohs(tvb,offset+1));
+ break;
+ case 3 :
+ ti = proto_tree_add_uint (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_session,
+ tvb,offset,count+1,tvb_get_ntoh24(tvb,offset+1));
+ break;
+ case 4 :
+ ti = proto_tree_add_uint (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_session,
+ tvb,offset,count+1,tvb_get_ntohl(tvb,offset+1));
+ break;
+ default:
+ ti = proto_tree_add_string (wtls_msg_type_item_tree, hf_wtls_hands_serv_hello_session_str,
+ tvb,offset,count+1,"Too big");
+ break;
+ }
+ offset+=1+count;
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_serv_hello_cli_key_id,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ cli_key_item = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_serv_hello_cipher_suite_item, tvb, offset,2,
+ bo_little_endian);
+ wtls_msg_type_item_sub_tree = proto_item_add_subtree(cli_key_item,
+ ett_wtls_msg_type_item_sub);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_serv_hello_cipher_bulk,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ value = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_serv_hello_cipher_mac,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_serv_hello_compression, tvb, offset,1,
+ bo_little_endian);
+ offset++;
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_serv_hello_sequence_mode, tvb, offset,
+ 1, bo_little_endian);
+ offset++;
+ ti = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_serv_hello_key_refresh, tvb, offset,
+ 1, bo_little_endian);
+ offset++;
+ break;
+ case WTLS_HANDSHAKE_CERTIFICATE :
+ ti = proto_tree_add_item(wtls_msg_type_tree, hf_wtls_hands_certificates,
+ tvb, offset,count, bo_little_endian);
+ wtls_msg_type_item_tree = proto_item_add_subtree(ti, ett_wtls_msg_type_item);
+ count = tvb_get_ntohs (tvb, offset);
+ offset+=2;
+ for (;count > 0;count-=client_size) {
+ cli_key_item = proto_tree_add_item(wtls_msg_type_item_tree,
+ hf_wtls_hands_certificate, tvb, offset,1,
+ bo_little_endian);
+ client_size=0;
+ wtls_msg_type_item_sub_tree = proto_item_add_subtree(cli_key_item,
+ ett_wtls_msg_type_item_sub);
+ proto_item_set_len(cli_key_item, client_size);
+ value = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_type, tvb, offset,1,
+ bo_little_endian);
+ offset++;
+ client_size++;
+ switch(value) {
+ case CERTIFICATE_WTLS:
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_version,
+ tvb, offset,1,
+ bo_little_endian);
+ offset++;
+ client_size++;
+ signature = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_signature_type,
+ tvb, offset,1,
+ bo_little_endian);
+ offset++;
+ client_size++;
+ value = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_issuer_type,
+ tvb, offset,1,
+ bo_little_endian);
+ offset++;
+ client_size++;
+ switch (value) {
+ case IDENTIFIER_NULL :
+ break;
+ case IDENTIFIER_TEXT :
+ value = add_text_identifier(tvb, offset,
+ hf_wtls_hands_certificate_wtls_issuer_charset,
+ hf_wtls_hands_certificate_wtls_issuer_size,
+ hf_wtls_hands_certificate_wtls_issuer_name,
+ wtls_msg_type_item_sub_tree);
+ offset += value;
+ client_size += value;
+ break;
+ case IDENTIFIER_BIN :
+ break;
+ case IDENTIFIER_SHA_1 :
+ break;
+ case IDENTIFIER_X509 :
+ break;
+ }
+ timeValue.secs = tvb_get_ntohl (tvb, offset);
+ timeValue.nsecs = 0;
+ ti = proto_tree_add_time (wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_valid_not_before,
+ tvb, offset, 4, &timeValue);
+ offset+=4;
+ client_size+=4;
+ timeValue.secs = tvb_get_ntohl (tvb, offset);
+ timeValue.nsecs = 0;
+ ti = proto_tree_add_time (wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_valid_not_after,
+ tvb, offset, 4, &timeValue);
+ offset+=4;
+ client_size+=4;
+ value = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_subject_type,
+ tvb, offset,1,
+ bo_little_endian);
+ offset++;
+ client_size++;
+ switch (value) {
+ case IDENTIFIER_NULL :
+ break;
+ case IDENTIFIER_TEXT :
+ value = add_text_identifier(tvb, offset,
+ hf_wtls_hands_certificate_wtls_subject_charset,
+ hf_wtls_hands_certificate_wtls_subject_size,
+ hf_wtls_hands_certificate_wtls_subject_name,
+ wtls_msg_type_item_sub_tree);
+ offset += value;
+ client_size += value;
+ break;
+ case IDENTIFIER_BIN :
+ break;
+ case IDENTIFIER_SHA_1 :
+ break;
+ case IDENTIFIER_X509 :
+ break;
+ }
+ public_key = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_public_key_type,
+ tvb, offset,1,
+ bo_little_endian);
+ offset++;
+ client_size++;
+ value = tvb_get_guint8 (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_key_parameter_index,
+ tvb,offset,1,bo_big_endian);
+ offset++;
+ client_size++;
+ if (value == 0xff) {
+ size = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_item(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_key_parameter_set,
+ tvb,offset,size+2,bo_big_endian);
+ offset+=size+2;
+ client_size+=size+2;
+ }
+ switch (public_key) {
+ case PUBLIC_KEY_RSA :
+ value = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_uint(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_rsa_exponent,
+ tvb,offset,value+2,value*8);
+ offset+=2+value;
+ client_size+=2+value;
+ value = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_uint(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_rsa_modules,
+ tvb,offset,value+2,value*8);
+ offset+=2+value;
+ client_size+=2+value;
+ break;
+ case PUBLIC_KEY_ECDH :
+ break;
+ case PUBLIC_KEY_ECDSA :
+ break;
+ }
+ value = tvb_get_ntohs (tvb, offset);
+ ti = proto_tree_add_uint(wtls_msg_type_item_sub_tree,
+ hf_wtls_hands_certificate_wtls_signature,
+ tvb,offset,2+value,value*8);
+ offset+=2+value;
+ client_size+=2+value;
+ break;
+ case CERTIFICATE_X509:
+ case CERTIFICATE_X968:
+ value = tvb_get_ntohs (tvb, offset);
+ offset+=2;
+ client_size+=2;
+ client_size += value;
+ offset += value;
+ break;
+ case CERTIFICATE_URL:
+ value = tvb_get_guint8 (tvb, offset);
+ offset++;
+ client_size++;
+ client_size += value;
+ offset += value;
+ break;
+ }
+ proto_item_set_len(cli_key_item, client_size);
+ }
+ break;
+ default:
+ offset+=count;
+ break;
+ }
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_wtls(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_wtls_record,
+ { "Record",
+ "wtls.record",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_record_type ), 0x0f,
+ "Record", HFILL
+ }
+ },
+ { &hf_wtls_record_type,
+ { "Record Type",
+ "wtls.rec_type",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_record_type ), 0x0f,
+ "Record Type", HFILL
+ }
+ },
+ { &hf_wtls_record_length,
+ { "Record Length",
+ "wtls.rec_length",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Record Length", HFILL
+ }
+ },
+ { &hf_wtls_record_sequence,
+ { "Record Sequence",
+ "wtls.rec_seq",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Record Sequence", HFILL
+ }
+ },
+ { &hf_wtls_record_ciphered,
+ { "Record Ciphered",
+ "wtls.rec_cipher",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Record Ciphered", HFILL
+ }
+ },
+ { &hf_wtls_hands,
+ { "Handshake",
+ "wtls.handshake",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_handshake_type ), 0x00,
+ "Handshake", HFILL
+ }
+ },
+ { &hf_wtls_hands_type,
+ { "Type",
+ "wtls.handshake.type",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_handshake_type ), 0x00,
+ "Type", HFILL
+ }
+ },
+ { &hf_wtls_hands_length,
+ { "Length",
+ "wtls.handshake.length",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Length", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello,
+ { "Client Hello",
+ "wtls.handshake.client_hello",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Client Hello", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_version,
+ { "Version",
+ "wtls.handshake.client_hello.version",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Version", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_gmt,
+ { "Time GMT",
+ "wtls.handshake.client_hello.gmt",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Time GMT", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_random,
+ { "Random",
+ "wtls.handshake.client_hello.random",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Random", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_session,
+ { "Session ID",
+ "wtls.handshake.client_hello.sessionid",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Session ID", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_session_str,
+ { "Session ID",
+ "wtls.handshake.client_hello.session.str",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Session ID", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_cli_key_id,
+ { "Client Keys",
+ "wtls.handshake.client_hello.client_keys_id",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Client Keys" , HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_cli_key_len,
+ { "Length",
+ "wtls.handshake.client_hello.client_keys_len",
+ FT_UINT16, BASE_DEC, NULL, 0x00,
+ "Length" , HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_trust_key_id,
+ { "Trusted Keys",
+ "wtls.handshake.client_hello.trusted_keys_id",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Trusted Keys" , HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_exchange,
+ { "Key Exchange",
+ "wtls.handshake.client_hello.key.key_exchange",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_key_exchange_suite ), 0x00,
+ "Key Exchange", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_exchange_suite,
+ { "Suite",
+ "wtls.handshake.client_hello.key.key_exchange.suite",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_key_exchange_suite ), 0x00,
+ "Suite", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_parameter_index,
+ { "Parameter Index",
+ "wtls.handshake.client_hello.parameter_index",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Parameter Index", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_parameter_set,
+ { "Parameter Set",
+ "wtls.handshake.client_hello.parameter",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Parameter Set", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_identifier_type,
+ { "Identifier Type",
+ "wtls.handshake.client_hello.ident_type",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_identifier_type ), 0x00,
+ "Identifier Type", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_identifier_charset,
+ { "Identifier CharSet",
+ "wtls.handshake.client_hello.ident_charset",
+ FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
+ "Identifier CharSet", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_identifier_size,
+ { "Identifier Size",
+ "wtls.handshake.client_hello.ident_size",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Identifier Size", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_identifier,
+ { "Identifier",
+ "wtls.handshake.client_hello.identifier",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Identifier", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_identifier_str,
+ { "Identifier Name",
+ "wtls.handshake.client_hello.ident_name",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Identifier Name", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_cipher_suite,
+ { "Cipher Suites",
+ "wtls.handshake.client_hello.ciphers",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Cipher Suite", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_cipher_suite_item,
+ { "Cipher",
+ "wtls.handshake.client_hello.cipher",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Cipher", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_compression_methods,
+ { "Compression Methods",
+ "wtls.handshake.client_hello.comp_methods",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Compression Methods", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_compression,
+ { "Compression",
+ "wtls.handshake.client_hello.compression",
+ FT_UINT8, BASE_HEX, VALS ( wtls_vals_compression ), 0x00,
+ "Compression", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_sequence_mode,
+ { "Sequence Mode",
+ "wtls.handshake.client_hello.sequence_mode",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_sequence_mode ), 0x00,
+ "Sequence Mode", HFILL
+ }
+ },
+ { &hf_wtls_hands_cli_hello_key_refresh,
+ { "Refresh",
+ "wtls.handshake.client_hello.refresh",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Refresh", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello,
+ { "Server Hello",
+ "wtls.handshake.server_hello",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Server Hello", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_version,
+ { "Version",
+ "wtls.handshake.server_hello.version",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Version", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_gmt,
+ { "Time GMT",
+ "wtls.handshake.server_hello.gmt",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Time GMT", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_random,
+ { "Random",
+ "wtls.handshake.server_hello.random",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Random", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_session,
+ { "Session ID",
+ "wtls.handshake.server_hello.sessionid",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Session ID", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_session_str,
+ { "Session ID",
+ "wtls.handshake.server_hello.session.str",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Session ID", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_cli_key_id,
+ { "Client Key ID",
+ "wtls.handshake.server_hello.key",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Client Key ID", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_cipher_suite_item,
+ { "Cipher",
+ "wtls.handshake.server_hello.cipher",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Cipher", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_cipher_bulk,
+ { "Cipher Bulk",
+ "wtls.handshake.server_hello.cipher.bulk",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_cipher_bulk ), 0x00,
+ "Cipher Bulk", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_cipher_mac,
+ { "Cipher MAC",
+ "wtls.handshake.server_hello.cipher.mac",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_cipher_mac ), 0x00,
+ "Cipher MAC", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_compression,
+ { "Compression",
+ "wtls.handshake.server_hello.compression",
+ FT_UINT8, BASE_HEX, VALS ( wtls_vals_compression ), 0x00,
+ "Compression", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_sequence_mode,
+ { "Sequence Mode",
+ "wtls.handshake.server_hello.sequence_mode",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_sequence_mode ), 0x00,
+ "Sequence Mode", HFILL
+ }
+ },
+ { &hf_wtls_hands_serv_hello_key_refresh,
+ { "Refresh",
+ "wtls.handshake.server_hello.refresh",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Refresh", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificates,
+ { "Certificates",
+ "wtls.handshake.certificates",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Certificates", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate,
+ { "Certificate",
+ "wtls.handshake.certificate",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Certificate", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_type,
+ { "Type",
+ "wtls.handshake.certificate.type",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_certificate_type ), 0x00,
+ "Type", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_version,
+ { "Version",
+ "wtls.handshake.certificate.version",
+ FT_UINT8, BASE_HEX, NULL, 0x00,
+ "Version", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_signature_type,
+ { "Signature Type",
+ "wtls.handshake.certificate.signature.type",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_certificate_signature ), 0x00,
+ "Signature Type", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_signature,
+ { "Signature Size",
+ "wtls.handshake.certificate.signature.signature",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "Signature Size", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_issuer_type,
+ { "Issuer",
+ "wtls.handshake.certificate.issuer.type",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_identifier_type ), 0x00,
+ "Issuer", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_issuer_charset,
+ { "Charset",
+ "wtls.handshake.certificate.issuer.charset",
+ FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
+ "Charset", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_issuer_size,
+ { "Size",
+ "wtls.handshake.certificate.issuer.size",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Size", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_issuer_name,
+ { "Name",
+ "wtls.handshake.certificate.issuer.name",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Name", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_valid_not_before,
+ { "Valid not before",
+ "wtls.handshake.certificate.before",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Valid not before", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_valid_not_after,
+ { "Valid not after",
+ "wtls.handshake.certificate.after",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ "Valid not after", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_subject_type,
+ { "Subject",
+ "wtls.handshake.certificate.subject.type",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_identifier_type ), 0x00,
+ "Subject", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_subject_charset,
+ { "Charset",
+ "wtls.handshake.certificate.subject.charset",
+ FT_UINT16, BASE_HEX, VALS ( vals_character_sets ), 0x00,
+ "Charset", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_subject_size,
+ { "Size",
+ "wtls.handshake.certificate.subject.size",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Size", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_subject_name,
+ { "Name",
+ "wtls.handshake.certificate.subject.name",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Name", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_public_key_type,
+ { "Public Key Type",
+ "wtls.handshake.certificate.public.type",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_public_key_type ), 0x00,
+ "Public Key Type", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_key_parameter_index,
+ { "Parameter Index",
+ "wtls.handshake.certificate.parameter_index",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Parameter Index", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_key_parameter_set,
+ { "Parameter Set",
+ "wtls.handshake.certificate.parameter",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Parameter Set", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_rsa_exponent,
+ { "RSA Exponent Size",
+ "wtls.handshake.certificate.rsa.exponent",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "RSA Exponent Size", HFILL
+ }
+ },
+ { &hf_wtls_hands_certificate_wtls_rsa_modules,
+ { "RSA Modulus Size",
+ "wtls.handshake.certificate.rsa.modules",
+ FT_UINT32, BASE_DEC, NULL, 0x00,
+ "RSA Modulus Size", HFILL
+ }
+ },
+ { &hf_wtls_alert,
+ { "Alert",
+ "wtls.alert",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "Alert", HFILL
+ }
+ },
+ { &hf_wtls_alert_level,
+ { "Level",
+ "wtls.alert.level",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_alert_level ), 0x00,
+ "Level", HFILL
+ }
+ },
+ { &hf_wtls_alert_description,
+ { "Description",
+ "wtls.alert.description",
+ FT_UINT8, BASE_DEC, VALS ( wtls_vals_alert_description ), 0x00,
+ "Description", HFILL
+ }
+ },
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_wtls,
+ &ett_wtls_rec,
+ &ett_wtls_msg_type,
+ &ett_wtls_msg_type_item,
+ &ett_wtls_msg_type_item_sub,
+ &ett_wtls_msg_type_item_sub_sub,
+ };
+
+/* Register the protocol name and description */
+ proto_wtls = proto_register_protocol(
+ "Wireless Transport Layer Security", /* protocol name for use by ethereal */
+ "WTLS", /* short version of name */
+ "wtls" /* Abbreviated protocol name, should Match IANA
+ < URL:http://www.iana.org/assignments/port-numbers/ >
+ */
+ );
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_wtls, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_wtls(void)
+{
+ dissector_handle_t wtls_handle;
+
+ wtls_handle = create_dissector_handle(dissect_wtls, proto_wtls);
+ dissector_add("udp.port", UDP_PORT_WTLS_WSP, wtls_handle);
+ dissector_add("udp.port", UDP_PORT_WTLS_WTP_WSP, wtls_handle);
+ dissector_add("udp.port", UDP_PORT_WTLS_WSP_PUSH,wtls_handle);
+}
diff --git a/epan/dissectors/packet-wtls.h b/epan/dissectors/packet-wtls.h
new file mode 100644
index 0000000000..d8acf91630
--- /dev/null
+++ b/epan/dissectors/packet-wtls.h
@@ -0,0 +1,40 @@
+/* packet-wtls.h
+ *
+ * Declarations for disassembly of WTLS component of WAP traffic.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * WAP dissector based on original work by Ben Fowler
+ * Updated by Neil Hunter <neil.hunter@energis-squared.com>
+ * WTLS support by Alexandre P. Ferreira (Splice IP)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_WTLS_H__
+#define __PACKET_WTLS_H__
+
+/* Implementation Status:
+ *
+ *
+ *
+ * TODO:
+ */
+
+#endif /* packet-wtls.h */
diff --git a/epan/dissectors/packet-wtp.c b/epan/dissectors/packet-wtp.c
new file mode 100644
index 0000000000..d05693ebc2
--- /dev/null
+++ b/epan/dissectors/packet-wtp.c
@@ -0,0 +1,1095 @@
+/* packet-wtp.c
+ *
+ * Routines to dissect WTP component of WAP traffic.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * WAP dissector based on original work by Ben Fowler
+ * Updated by Neil Hunter <neil.hunter@energis-squared.com>
+ * WTLS support by Alexandre P. Ferreira (Splice IP)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "reassemble.h"
+#include "packet-wap.h"
+#include "packet-wtp.h"
+#include "packet-wsp.h"
+
+static const true_false_string continue_truth = {
+ "TPI Present" ,
+ "No TPI"
+};
+
+static const true_false_string RID_truth = {
+ "Re-Transmission",
+ "First transmission"
+};
+
+static const true_false_string TIDNew_truth = {
+ "TID is new" ,
+ "TID is valid"
+};
+
+static const true_false_string tid_response_truth = {
+ "Response" ,
+ "Original"
+};
+
+static const true_false_string UP_truth = {
+ "User Acknowledgement required" ,
+ "User Acknowledgement optional"
+};
+
+static const true_false_string TVETOK_truth = {
+ "True",
+ "False"
+};
+
+static const value_string vals_wtp_pdu_type[] = {
+ { 0, "Not Allowed" },
+ { 1, "Invoke" },
+ { 2, "Result" },
+ { 3, "Ack" },
+ { 4, "Abort" },
+ { 5, "Segmented Invoke" },
+ { 6, "Segmented Result" },
+ { 7, "Negative Ack" },
+ { 0, NULL }
+};
+
+static const value_string vals_transaction_trailer[] = {
+ { 0, "Not last packet" },
+ { 1, "Last packet of message" },
+ { 2, "Last packet of group" },
+ { 3, "Re-assembly not supported" },
+ { 0, NULL }
+};
+
+static const value_string vals_version[] = {
+ { 0, "Current" },
+ { 1, "Undefined" },
+ { 2, "Undefined" },
+ { 3, "Undefined" },
+ { 0, NULL }
+};
+
+static const value_string vals_abort_type[] = {
+ { 0, "Provider" },
+ { 1, "User (WSP)" },
+ { 0, NULL }
+};
+
+static const value_string vals_abort_reason_provider[] = {
+ { 0x00, "Unknown" },
+ { 0x01, "Protocol Error" },
+ { 0x02, "Invalid TID" },
+ { 0x03, "Not Implemented Class 2" },
+ { 0x04, "Not Implemented SAR" },
+ { 0x05, "Not Implemented User Acknowledgement" },
+ { 0x06, "WTP Version Zero" },
+ { 0x07, "Capacity Temporarily Exceeded" },
+ { 0x08, "No Response" },
+ { 0x09, "Message Too Large" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_transaction_classes[] = {
+ { 0x00, "Unreliable Invoke without Result" },
+ { 0x01, "Reliable Invoke without Result" },
+ { 0x02, "Reliable Invoke with Reliable Result" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_tpi_type[] = {
+ { 0x00, "Error" },
+ { 0x01, "Info" },
+ { 0x02, "Option" },
+ { 0x03, "Packet sequence number" },
+ { 0x04, "SDU boundary" },
+ { 0x05, "Frame boundary" },
+ { 0x00, NULL }
+};
+
+static const value_string vals_tpi_opt[] = {
+ { 0x01, "Maximum receive unit" },
+ { 0x02, "Total message size" },
+ { 0x03, "Delay transmission timer" },
+ { 0x04, "Maximum group" },
+ { 0x05, "Current TID" },
+ { 0x06, "No cached TID" },
+ { 0x00, NULL }
+};
+
+/* File scoped variables for the protocol and registered fields */
+static int proto_wtp = HF_EMPTY;
+
+/* These fields used by fixed part of header */
+static int hf_wtp_header_sub_pdu_size = HF_EMPTY;
+static int hf_wtp_header_flag_continue = HF_EMPTY;
+static int hf_wtp_header_pdu_type = HF_EMPTY;
+static int hf_wtp_header_flag_Trailer = HF_EMPTY;
+static int hf_wtp_header_flag_RID = HF_EMPTY;
+static int hf_wtp_header_flag_TID = HF_EMPTY;
+static int hf_wtp_header_flag_TID_response = HF_EMPTY;
+
+/* These fields used by Invoke packets */
+static int hf_wtp_header_Inv_version = HF_EMPTY;
+static int hf_wtp_header_Inv_flag_TIDNew = HF_EMPTY;
+static int hf_wtp_header_Inv_flag_UP = HF_EMPTY;
+static int hf_wtp_header_Inv_Reserved = HF_EMPTY;
+static int hf_wtp_header_Inv_TransactionClass = HF_EMPTY;
+
+
+static int hf_wtp_header_variable_part = HF_EMPTY;
+static int hf_wtp_data = HF_EMPTY;
+
+static int hf_wtp_tpi_type = HF_EMPTY;
+static int hf_wtp_tpi_psn = HF_EMPTY;
+static int hf_wtp_tpi_opt = HF_EMPTY;
+static int hf_wtp_tpi_optval = HF_EMPTY;
+static int hf_wtp_tpi_info = HF_EMPTY;
+
+static int hf_wtp_header_Ack_flag_TVETOK = HF_EMPTY;
+static int hf_wtp_header_Abort_type = HF_EMPTY;
+static int hf_wtp_header_Abort_reason_provider = HF_EMPTY;
+static int hf_wtp_header_Abort_reason_user = HF_EMPTY;
+static int hf_wtp_header_sequence_number = HF_EMPTY;
+static int hf_wtp_header_missing_packets = HF_EMPTY;
+
+/* These fields used when reassembling WTP fragments */
+static int hf_wtp_fragments = HF_EMPTY;
+static int hf_wtp_fragment = HF_EMPTY;
+static int hf_wtp_fragment_overlap = HF_EMPTY;
+static int hf_wtp_fragment_overlap_conflict = HF_EMPTY;
+static int hf_wtp_fragment_multiple_tails = HF_EMPTY;
+static int hf_wtp_fragment_too_long_fragment = HF_EMPTY;
+static int hf_wtp_fragment_error = HF_EMPTY;
+static int hf_wtp_reassembled_in = HF_EMPTY;
+
+/* Initialize the subtree pointers */
+static gint ett_wtp = ETT_EMPTY;
+static gint ett_wtp_sub_pdu_tree = ETT_EMPTY;
+static gint ett_header = ETT_EMPTY;
+static gint ett_tpilist = ETT_EMPTY;
+static gint ett_wsp_fragments = ETT_EMPTY;
+static gint ett_wtp_fragment = ETT_EMPTY;
+
+static const fragment_items wtp_frag_items = {
+ &ett_wtp_fragment,
+ &ett_wsp_fragments,
+ &hf_wtp_fragments,
+ &hf_wtp_fragment,
+ &hf_wtp_fragment_overlap,
+ &hf_wtp_fragment_overlap_conflict,
+ &hf_wtp_fragment_multiple_tails,
+ &hf_wtp_fragment_too_long_fragment,
+ &hf_wtp_fragment_error,
+ &hf_wtp_reassembled_in,
+ "fragments"
+};
+
+/* Handle for WSP dissector */
+static dissector_handle_t wsp_handle;
+
+/*
+ * reassembly of WSP
+ */
+static GHashTable *wtp_fragment_table = NULL;
+
+static void
+wtp_defragment_init(void)
+{
+ fragment_table_init(&wtp_fragment_table);
+}
+
+/*
+ * Extract some bitfields
+ */
+#define pdu_type(octet) (((octet) >> 3) & 0x0F) /* Note pdu type must not be 0x00 */
+#define transaction_class(octet) ((octet) & 0x03) /* ......XX */
+#define transmission_trailer(octet) (((octet) >> 1) & 0x01) /* ......X. */
+
+static char retransmission_indicator(unsigned char octet)
+{
+ switch (pdu_type(octet)) {
+ case INVOKE:
+ case RESULT:
+ case ACK:
+ case SEGMENTED_INVOKE:
+ case SEGMENTED_RESULT:
+ case NEGATIVE_ACK:
+ return octet & 0x01; /* .......X */
+ default:
+ return 0;
+ }
+}
+
+/*
+ * dissect a TPI
+ */
+static void
+wtp_handle_tpi(proto_tree *tree, tvbuff_t *tvb)
+{
+ int offset = 0;
+ unsigned char tByte;
+ unsigned char tType;
+ unsigned char tLen;
+ proto_item *subTree = NULL;
+
+ tByte = tvb_get_guint8(tvb, offset++);
+ tType = (tByte & 0x78) >> 3;
+ if (tByte & 0x04) /* Long TPI */
+ tLen = tvb_get_guint8(tvb, offset++);
+ else
+ tLen = tByte & 0x03;
+ subTree = proto_tree_add_uint(tree, hf_wtp_tpi_type,
+ tvb, 0, tvb_length(tvb), tType);
+ proto_item_add_subtree(subTree, ett_tpilist);
+ switch (tType) {
+ case 0x00: /* Error*/
+ /* \todo */
+ break;
+ case 0x01: /* Info */
+ /* Beware, untested case here */
+ proto_tree_add_item(subTree, hf_wtp_tpi_info,
+ tvb, offset, tLen, bo_little_endian);
+ break;
+ case 0x02: /* Option */
+ proto_tree_add_item(subTree, hf_wtp_tpi_opt,
+ tvb, offset++, 1, bo_little_endian);
+ proto_tree_add_item(subTree, hf_wtp_tpi_optval,
+ tvb, offset, tLen - 1, bo_little_endian);
+ break;
+ case 0x03: /* PSN */
+ proto_tree_add_item(subTree, hf_wtp_tpi_psn,
+ tvb, offset, 1, bo_little_endian);
+ break;
+ case 0x04: /* SDU boundary */
+ /* \todo */
+ break;
+ case 0x05: /* Frame boundary */
+ /* \todo */
+ break;
+ default:
+ break;
+ }
+}
+
+/* Code to actually dissect the packets */
+static void
+dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ static GString *szInfo = NULL;
+ int offCur = 0; /* current offset from start of WTP data */
+
+ unsigned char b0;
+
+ /* continuation flag */
+ unsigned char fCon; /* Continue flag */
+ unsigned char fRID; /* Re-transmission indicator*/
+ unsigned char fTTR = '\0'; /* Transmission trailer */
+ guint cbHeader = 0; /* Fixed header length */
+ guint vHeader = 0; /* Variable header length*/
+ int abortType = 0;
+
+ /* Set up structures we'll need to add the protocol subtree and manage it */
+ proto_item *ti = NULL;
+ proto_tree *wtp_tree = NULL;
+
+ char pdut;
+ char clsTransaction = ' ';
+ int numMissing = 0; /* Number of missing packets in a negative ack */
+ int i;
+ tvbuff_t *wsp_tvb = NULL;
+ guint8 psn = 0; /* Packet sequence number*/
+ guint16 TID = 0; /* Transaction-Id */
+ int dataOffset;
+ gint dataLen;
+
+ if (szInfo == NULL)
+ szInfo = g_string_sized_new(32);
+
+ b0 = tvb_get_guint8 (tvb, offCur + 0);
+ /* Discover Concatenated PDUs */
+ if (b0 == 0) {
+ guint c_fieldlen = 0; /* Length of length-field */
+ guint c_pdulen = 0; /* Length of conc. PDU */
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_wtp,
+ tvb, offCur, 1, bo_little_endian);
+ wtp_tree = proto_item_add_subtree(ti, ett_wtp_sub_pdu_tree);
+ proto_item_append_text(ti, ", PDU concatenation");
+ }
+ offCur = 1;
+ i = 1;
+ while (offCur < (int) tvb_reported_length(tvb)) {
+ tvbuff_t *wtp_tvb;
+ /* The length of an embedded WTP PDU is coded as either:
+ * - a 7-bit value contained in one octet with highest bit == 0.
+ * - a 15-bit value contained in two octets (little endian)
+ * if the 1st octet has its highest bit == 1.
+ * This means that this is NOT encoded as an uintvar-integer!!!
+ */
+ b0 = tvb_get_guint8(tvb, offCur + 0);
+ if (b0 & 0x80) {
+ c_fieldlen = 2;
+ c_pdulen = ((b0 & 0x7f) << 8) | tvb_get_guint8(tvb, offCur + 1);
+ } else {
+ c_fieldlen = 1;
+ c_pdulen = b0;
+ }
+ if (tree) {
+ proto_tree_add_uint(wtp_tree, hf_wtp_header_sub_pdu_size,
+ tvb, offCur, c_fieldlen, c_pdulen);
+ }
+ if (i > 1 && check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ }
+ /* Skip the length field for the WTP sub-tvb */
+ wtp_tvb = tvb_new_subset(tvb, offCur + c_fieldlen, c_pdulen, c_pdulen);
+ dissect_wtp_common(wtp_tvb, pinfo, wtp_tree);
+ offCur += c_fieldlen + c_pdulen;
+ i++;
+ }
+ if (tree) {
+ proto_item_append_text(ti, ", PDU count: %u", i);
+ }
+ return;
+ }
+ /* No concatenation */
+ fCon = b0 & 0x80;
+ fRID = retransmission_indicator(b0);
+ pdut = pdu_type(b0);
+
+#ifdef DEBUG
+ printf("WTP packet %u: tree = %p, pdu = %s (%u) length: %u\n",
+ pinfo->fd->num, tree,
+ match_strval(pdut, vals_wtp_pdu_type), pdut, tvb_length(tvb));
+#endif
+
+ /* Develop the string to put in the Info column */
+ g_string_sprintf(szInfo, "WTP %s",
+ val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"));
+
+ switch (pdut) {
+ case INVOKE:
+ fTTR = transmission_trailer(b0);
+ TID = tvb_get_ntohs(tvb, offCur + 1);
+ psn = 0;
+ clsTransaction = transaction_class(tvb_get_guint8(tvb, offCur + 3));
+ g_string_sprintfa(szInfo, " Class %d", clsTransaction);
+ cbHeader = 4;
+ break;
+
+ case SEGMENTED_INVOKE:
+ case SEGMENTED_RESULT:
+ fTTR = transmission_trailer(b0);
+ TID = tvb_get_ntohs(tvb, offCur + 1);
+ psn = tvb_get_guint8(tvb, offCur + 3);
+ if (psn != 0)
+ g_string_sprintfa(szInfo, " (%u)", psn);
+ cbHeader = 4;
+ break;
+
+ case ABORT:
+ cbHeader = 4;
+ break;
+
+ case RESULT:
+ fTTR = transmission_trailer(b0);
+ TID = tvb_get_ntohs(tvb, offCur + 1);
+ psn = 0;
+ cbHeader = 3;
+ break;
+
+ case ACK:
+ cbHeader = 3;
+ break;
+
+ case NEGATIVE_ACK:
+ /* Variable number of missing packets */
+ numMissing = tvb_get_guint8(tvb, offCur + 3);
+ cbHeader = numMissing + 4;
+ break;
+
+ default:
+ break;
+ };
+ if (fRID) {
+ g_string_append( szInfo, " R" );
+ };
+ /* In the interest of speed, if "tree" is NULL, don't do any work not
+ necessary to generate protocol tree items. */
+ if (tree) {
+#ifdef DEBUG
+ fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
+#endif
+ /* NOTE - Length will be set when we process the TPI */
+ ti = proto_tree_add_item(tree, proto_wtp, tvb, offCur, 0, bo_little_endian);
+#ifdef DEBUG
+ fprintf(stderr, "dissect_wtp: (7) Returned from proto_tree_add_item\n");
+#endif
+ wtp_tree = proto_item_add_subtree(ti, ett_wtp);
+
+/* Code to process the packet goes here */
+#ifdef DEBUG
+ fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
+ fprintf(stderr, "dissect_wtp: offCur = %d\n", offCur);
+#endif
+ /* Add common items: only CON and PDU Type */
+ proto_tree_add_item(
+ wtp_tree, /* tree */
+ hf_wtp_header_flag_continue, /* id */
+ tvb,
+ offCur, /* start of highlight */
+ 1, /* length of highlight*/
+ b0 /* value */
+ );
+ proto_tree_add_item(wtp_tree, hf_wtp_header_pdu_type, tvb, offCur, 1, bo_little_endian);
+
+ switch(pdut) {
+ case INVOKE:
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, bo_big_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, bo_big_endian);
+
+ proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_version , tvb, offCur + 3, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_TIDNew, tvb, offCur + 3, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_UP, tvb, offCur + 3, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_Reserved, tvb, offCur + 3, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_TransactionClass, tvb, offCur + 3, 1, bo_little_endian);
+ proto_item_append_text(ti,
+ ", PDU: Invoke (%u)"
+ ", Transaction Class: %s (%u)",
+ INVOKE,
+ match_strval(clsTransaction, vals_transaction_classes),
+ clsTransaction);
+ break;
+
+ case RESULT:
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, bo_big_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, bo_big_endian);
+ proto_item_append_text(ti, ", PDU: Result (%u)", RESULT);
+ break;
+
+ case ACK:
+ proto_tree_add_item(wtp_tree, hf_wtp_header_Ack_flag_TVETOK, tvb, offCur, 1, bo_big_endian);
+
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, bo_big_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, bo_big_endian);
+ proto_item_append_text(ti, ", PDU: ACK (%u)", ACK);
+ break;
+
+ case ABORT:
+ abortType = tvb_get_guint8 (tvb, offCur) & 0x07;
+ proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_type , tvb, offCur , 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, bo_big_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, bo_big_endian);
+
+ if (abortType == PROVIDER)
+ {
+ guint8 reason = tvb_get_guint8(tvb, offCur + 3);
+ proto_tree_add_item( wtp_tree, hf_wtp_header_Abort_reason_provider , tvb, offCur + 3 , 1, bo_little_endian);
+ proto_item_append_text(ti,
+ ", PDU: Abort (%u)"
+ ", Type: Provider (%u)"
+ ", Reason: %s (%u)",
+ ABORT,
+ PROVIDER,
+ match_strval(reason, vals_abort_reason_provider),
+ reason);
+ }
+ else if (abortType == USER)
+ {
+ guint8 reason = tvb_get_guint8(tvb, offCur + 3);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_reason_user , tvb, offCur + 3 , 1, bo_little_endian);
+ proto_item_append_text(ti,
+ ", PDU: Abort (%u)"
+ ", Type: User (%u)"
+ ", Reason: %s (%u)",
+ ABORT,
+ PROVIDER,
+ match_strval(reason, vals_wsp_reason_codes),
+ reason);
+ }
+ break;
+
+ case SEGMENTED_INVOKE:
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, bo_big_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, bo_big_endian);
+
+ proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, bo_little_endian);
+ proto_item_append_text(ti,
+ ", PDU: Segmented Invoke (%u)"
+ ", Packet Sequence Number: %u",
+ SEGMENTED_INVOKE, psn);
+ break;
+
+ case SEGMENTED_RESULT:
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, bo_big_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, bo_big_endian);
+
+ proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, bo_little_endian);
+ proto_item_append_text(ti,
+ ", PDU: Segmented Result (%u)"
+ ", Packet Sequence Number: %u",
+ SEGMENTED_RESULT, psn);
+ break;
+
+ case NEGATIVE_ACK:
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, bo_little_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, bo_big_endian);
+ proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, bo_big_endian);
+
+ proto_tree_add_item(wtp_tree, hf_wtp_header_missing_packets , tvb, offCur + 3, 1, bo_little_endian);
+ /* Iterate through missing packets */
+ for (i = 0; i < numMissing; i++)
+ {
+ proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number, tvb, offCur + 4 + i, 1, bo_little_endian);
+ }
+ proto_item_append_text(ti,
+ ", PDU: Negative Ack (%u)"
+ ", Missing Packets: %u",
+ NEGATIVE_ACK, numMissing);
+ break;
+
+ default:
+ break;
+ };
+ if (fRID) {
+ proto_item_append_text(ti, ", Retransmission");
+ }
+ } else { /* tree is NULL */
+#ifdef DEBUG
+ fprintf(stderr, "dissect_wtp: (4) tree was %p\n", tree);
+#endif
+ }
+ /* Process the variable part */
+ if (fCon) { /* Now, analyze variable part */
+ unsigned char tCon;
+ unsigned char tByte;
+ unsigned char tpiLen;
+ tvbuff_t *tmp_tvb;
+
+ vHeader = 0; /* Start scan all over */
+
+ do {
+ tByte = tvb_get_guint8(tvb, offCur + cbHeader + vHeader);
+ tCon = tByte & 0x80;
+ if (tByte & 0x04) /* Long TPI */
+ tpiLen = 2 + tvb_get_guint8(tvb,
+ offCur + cbHeader + vHeader + 1);
+ else
+ tpiLen = 1 + (tByte & 0x03);
+ if (tree)
+ {
+ tmp_tvb = tvb_new_subset(tvb, offCur + cbHeader + vHeader,
+ tpiLen, tpiLen);
+ wtp_handle_tpi(wtp_tree, tmp_tvb);
+ }
+ vHeader += tpiLen;
+ } while (tCon);
+ } else {
+ /* There is no variable part */
+ } /* End of variable part of header */
+
+ /* Set the length of the WTP protocol part now we know the length of the
+ * fixed and variable WTP headers */
+ if (tree)
+ proto_item_set_len(ti, cbHeader + vHeader);
+
+#ifdef DEBUG
+ fprintf( stderr, "dissect_wtp: cbHeader = %d\n", cbHeader );
+#endif
+
+ /*
+ * Any remaining data ought to be WSP data (if not WTP ACK, NACK
+ * or ABORT pdu), so, if we have any remaining data, and it's
+ * not an ACK, NACK, or ABORT PDU, hand it off (defragmented) to the
+ * WSP dissector.
+ * Note that the last packet of a fragmented WTP message needn't
+ * contain any data, so we allow payloadless packets to be
+ * reassembled. (XXX - does the reassembly code handle this
+ * for packets other than the last packet?)
+ *
+ * Try calling a subdissector only if:
+ * - The WTP payload is ressembled in this very packet,
+ * - The WTP payload is not fragmented across packets.
+ */
+ dataOffset = offCur + cbHeader + vHeader;
+ dataLen = tvb_reported_length_remaining(tvb, dataOffset);
+ if ((dataLen >= 0) &&
+ ! ((pdut==ACK) || (pdut==NEGATIVE_ACK) || (pdut==ABORT)))
+ {
+ /* Try to reassemble if needed, and hand over to WSP
+ * A fragmented WTP packet is either:
+ * - An INVOKE with fTTR (transmission trailer) not set,
+ * - a SEGMENTED_INVOKE,
+ * - A RESULT with fTTR (transmission trailer) not set,
+ * - a SEGMENTED_RESULT.
+ */
+ if ( ( (pdut == SEGMENTED_INVOKE) || (pdut == SEGMENTED_RESULT)
+ || ( ((pdut == INVOKE) || (pdut == RESULT)) && (!fTTR) )
+ ) && tvb_bytes_exist(tvb, dataOffset, dataLen) )
+ {
+ /* Try reassembling fragments */
+ fragment_data *fd_wtp = NULL;
+ guint32 reassembled_in = 0;
+ gboolean save_fragmented = pinfo->fragmented;
+
+ pinfo->fragmented = TRUE;
+ fd_wtp = fragment_add_seq(tvb, dataOffset, pinfo, TID,
+ wtp_fragment_table, psn, dataLen, !fTTR);
+ /* XXX - fragment_add_seq() yields NULL unless Ethereal knows
+ * that the packet is part of a reassembled whole. This means
+ * that fd_wtp will be NULL as long as Ethereal did not encounter
+ * (and process) the packet containing the last fragment.
+ * This implies that Ethereal needs two passes over the data for
+ * correct reassembly. At the first pass, a capture containing
+ * three fragments plus a retransmssion of the last fragment
+ * will progressively show:
+ *
+ * Packet 1: (Unreassembled fragment 1)
+ * Packet 2: (Unreassembled fragment 2)
+ * Packet 3: (Reassembled WTP)
+ * Packet 4: (WTP payload reassembled in packet 3)
+ *
+ * However at subsequent evaluation (e.g., by applying a display
+ * filter) the packet summary will show:
+ *
+ * Packet 1: (WTP payload reassembled in packet 3)
+ * Packet 2: (WTP payload reassembled in packet 3)
+ * Packet 3: (Reassembled WTP)
+ * Packet 4: (WTP payload reassembled in packet 3)
+ *
+ * This is important to know, and also affects read filters!
+ */
+ wsp_tvb = process_reassembled_data(tvb, dataOffset, pinfo,
+ "Reassembled WTP", fd_wtp, &wtp_frag_items,
+ NULL, wtp_tree);
+#ifdef DEBUG
+ printf("WTP: Packet %u %s -> %d: wsp_tvb = %p, fd_wtp = %p, frame = %u\n",
+ pinfo->fd->num,
+ fd_wtp ? "Reassembled" : "Not reassembled",
+ fd_wtp ? fd_wtp->reassembled_in : -1,
+ wsp_tvb,
+ fd_wtp
+ );
+#endif
+ if (fd_wtp) {
+ /* Reassembled */
+ reassembled_in = fd_wtp->reassembled_in;
+ if (pinfo->fd->num == reassembled_in) {
+ /* Reassembled in this very packet:
+ * We can safely hand the tvb to the WSP dissector */
+ call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
+ } else {
+ /* Not reassembled in this packet */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "%s (WTP payload reassembled in packet %u)",
+ szInfo->str, fd_wtp->reassembled_in);
+ }
+ if (tree) {
+ proto_tree_add_text(wtp_tree, tvb, dataOffset, -1,
+ "Payload");
+ }
+ }
+ } else {
+ /* Not reassembled yet, or not reassembled at all */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "%s (Unreassembled fragment %u)",
+ szInfo->str, psn);
+ }
+ if (tree) {
+ proto_tree_add_text(wtp_tree, tvb, dataOffset, -1,
+ "Payload");
+ }
+ }
+ /* Now reset fragmentation information in pinfo */
+ pinfo->fragmented = save_fragmented;
+ }
+ else if ( ((pdut == INVOKE) || (pdut == RESULT)) && (fTTR) )
+ {
+ /* Non-fragmented payload */
+ wsp_tvb = tvb_new_subset(tvb, dataOffset, -1, -1);
+ /* We can safely hand the tvb to the WSP dissector */
+ call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
+ }
+ else
+ {
+ /* Nothing to hand to subdissector */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, szInfo->str);
+ }
+ }
+ else
+ {
+ /* Nothing to hand to subdissector */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, szInfo->str);
+ }
+}
+
+/*
+ * Called directly from UDP.
+ * Put "WTP+WSP" into the "Protocol" column.
+ */
+static void
+dissect_wtp_fromudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WTP+WSP" );
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ dissect_wtp_common(tvb, pinfo, tree);
+}
+
+/*
+ * Called from a higher-level WAP dissector, presumably WTLS.
+ * Put "WTLS+WSP+WTP" to the "Protocol" column.
+ *
+ * XXX - is this supposed to be called from WTLS? If so, we're not
+ * calling it....
+ *
+ * XXX - can this be called from any other dissector?
+ */
+static void
+dissect_wtp_fromwtls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "WTLS+WTP+WSP" );
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ dissect_wtp_common(tvb, pinfo, tree);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_wtp(void)
+{
+
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_wtp_header_sub_pdu_size,
+ { "Sub PDU size",
+ "wtp.sub_pdu_size",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Size of Sub-PDU (bytes)", HFILL
+ }
+ },
+ { &hf_wtp_header_flag_continue,
+ { "Continue Flag",
+ "wtp.continue_flag",
+ FT_BOOLEAN, 8, TFS( &continue_truth ), 0x80,
+ "Continue Flag", HFILL
+ }
+ },
+ { &hf_wtp_header_pdu_type,
+ { "PDU Type",
+ "wtp.pdu_type",
+ FT_UINT8, BASE_HEX, VALS( vals_wtp_pdu_type ), 0x78,
+ "PDU Type", HFILL
+ }
+ },
+ { &hf_wtp_header_flag_Trailer,
+ { "Trailer Flags",
+ "wtp.trailer_flags",
+ FT_UINT8, BASE_HEX, VALS( vals_transaction_trailer ), 0x06,
+ "Trailer Flags", HFILL
+ }
+ },
+ { &hf_wtp_header_flag_RID,
+ { "Re-transmission Indicator",
+ "wtp.RID",
+ FT_BOOLEAN, 8, TFS( &RID_truth ), 0x01,
+ "Re-transmission Indicator", HFILL
+ }
+ },
+ { &hf_wtp_header_flag_TID_response,
+ { "TID Response",
+ "wtp.TID.response",
+ FT_BOOLEAN, 16, TFS( &tid_response_truth ), 0x8000,
+ "TID Response", HFILL
+ }
+ },
+ { &hf_wtp_header_flag_TID,
+ { "Transaction ID",
+ "wtp.TID",
+ FT_UINT16, BASE_HEX, NULL, 0x7FFF,
+ "Transaction ID", HFILL
+ }
+ },
+ { &hf_wtp_header_Inv_version,
+ { "Version",
+ "wtp.header.version",
+ FT_UINT8, BASE_HEX, VALS( vals_version ), 0xC0,
+ "Version", HFILL
+ }
+ },
+ { &hf_wtp_header_Inv_flag_TIDNew,
+ { "TIDNew",
+ "wtp.header.TIDNew",
+ FT_BOOLEAN, 8, TFS( &TIDNew_truth ), 0x20,
+ "TIDNew", HFILL
+ }
+ },
+ { &hf_wtp_header_Inv_flag_UP,
+ { "U/P flag",
+ "wtp.header.UP",
+ FT_BOOLEAN, 8, TFS( &UP_truth ), 0x10,
+ "U/P Flag", HFILL
+ }
+ },
+ { &hf_wtp_header_Inv_Reserved,
+ { "Reserved",
+ "wtp.inv.reserved",
+ FT_UINT8, BASE_HEX, NULL, 0x0C,
+ "Reserved", HFILL
+ }
+ },
+ { &hf_wtp_header_Inv_TransactionClass,
+ { "Transaction Class",
+ "wtp.inv.transaction_class",
+ FT_UINT8, BASE_HEX, VALS( vals_transaction_classes ), 0x03,
+ "Transaction Class", HFILL
+ }
+ },
+ { &hf_wtp_header_Ack_flag_TVETOK,
+ { "Tve/Tok flag",
+ "wtp.ack.tvetok",
+ FT_BOOLEAN, 8, TFS( &TVETOK_truth ), 0x04,
+ "Tve/Tok flag", HFILL
+ }
+ },
+ { &hf_wtp_header_Abort_type,
+ { "Abort Type",
+ "wtp.abort.type",
+ FT_UINT8, BASE_HEX, VALS ( vals_abort_type ), 0x07,
+ "Abort Type", HFILL
+ }
+ },
+ { &hf_wtp_header_Abort_reason_provider,
+ { "Abort Reason",
+ "wtp.abort.reason.provider",
+ FT_UINT8, BASE_HEX, VALS ( vals_abort_reason_provider ), 0x00,
+ "Abort Reason", HFILL
+ }
+ },
+ /* Assume WSP is the user and use its reason codes */
+ { &hf_wtp_header_Abort_reason_user,
+ { "Abort Reason",
+ "wtp.abort.reason.user",
+ FT_UINT8, BASE_HEX, VALS ( vals_wsp_reason_codes ), 0x00,
+ "Abort Reason", HFILL
+ }
+ },
+ { &hf_wtp_header_sequence_number,
+ { "Packet Sequence Number",
+ "wtp.header.sequence",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Packet Sequence Number", HFILL
+ }
+ },
+ { &hf_wtp_header_missing_packets,
+ { "Missing Packets",
+ "wtp.header.missing_packets",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Missing Packets", HFILL
+ }
+ },
+ { &hf_wtp_header_variable_part,
+ { "Header: Variable part",
+ "wtp.header_variable_part",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Variable part of the header", HFILL
+ }
+ },
+ { &hf_wtp_data,
+ { "Data",
+ "wtp.header_data",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Data", HFILL
+ }
+ },
+ { &hf_wtp_tpi_type,
+ { "TPI",
+ "wtp.tpi",
+ FT_UINT8, BASE_HEX, VALS(vals_tpi_type), 0x00,
+ "Identification of the Transport Information Item", HFILL
+ }
+ },
+ { &hf_wtp_tpi_psn,
+ { "Packet sequence number",
+ "wtp.tpi.psn",
+ FT_UINT8, BASE_DEC, NULL, 0x00,
+ "Sequence number of this packet", HFILL
+ }
+ },
+ { &hf_wtp_tpi_opt,
+ { "Option",
+ "wtp.tpi.opt",
+ FT_UINT8, BASE_HEX, VALS(vals_tpi_opt), 0x00,
+ "The given option for this TPI", HFILL
+ }
+ },
+ { &hf_wtp_tpi_optval,
+ { "Option Value",
+ "wtp.tpi.opt.val",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "The value that is supplied with this option", HFILL
+ }
+ },
+ { &hf_wtp_tpi_info,
+ { "Information",
+ "wtp.tpi.info",
+ FT_NONE, BASE_NONE, NULL, 0x00,
+ "The information being send by this TPI", HFILL
+ }
+ },
+
+ /* Fragment fields */
+ { &hf_wtp_fragment_overlap,
+ { "Fragment overlap",
+ "wtp.fragment.overlap",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL
+ }
+ },
+ { &hf_wtp_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap",
+ "wtp.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL
+ }
+ },
+ { &hf_wtp_fragment_multiple_tails,
+ { "Multiple tail fragments found",
+ "wtp.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL
+ }
+ },
+ { &hf_wtp_fragment_too_long_fragment,
+ { "Fragment too long",
+ "wtp.fragment.toolongfragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL
+ }
+ },
+ { &hf_wtp_fragment_error,
+ { "Defragmentation error",
+ "wtp.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL
+ }
+ },
+ { &hf_wtp_reassembled_in,
+ { "Reassembled in",
+ "wtp.reassembled.in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "WTP fragments are reassembled in the given packet", HFILL
+ }
+ },
+ { &hf_wtp_fragment,
+ { "WTP Fragment",
+ "wtp.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "WTP Fragment", HFILL
+ }
+ },
+ { &hf_wtp_fragments,
+ { "WTP Fragments",
+ "wtp.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "WTP Fragments", HFILL
+ }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_wtp,
+ &ett_wtp_sub_pdu_tree,
+ &ett_header,
+ &ett_tpilist,
+ &ett_wsp_fragments,
+ &ett_wtp_fragment,
+ };
+
+ /* Register the protocol name and description */
+ proto_wtp = proto_register_protocol(
+ "Wireless Transaction Protocol", /* protocol name for use by ethereal */
+ "WTP", /* short version of name */
+ "wtp" /* Abbreviated protocol name, should Match IANA
+ < URL:http://www.iana.org/assignments/port-numbers/ >
+ */
+ );
+
+ /* Required calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_wtp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("wtp-wtls", dissect_wtp_fromwtls, proto_wtp);
+ register_dissector("wtp-udp", dissect_wtp_fromudp, proto_wtp);
+ register_init_routine(wtp_defragment_init);
+}
+
+void
+proto_reg_handoff_wtp(void)
+{
+ dissector_handle_t wtp_fromudp_handle;
+
+ /*
+ * Get a handle for the connection-oriented WSP dissector - if WTP
+ * PDUs have data, it is WSP.
+ */
+ wsp_handle = find_dissector("wsp-co");
+
+ wtp_fromudp_handle = find_dissector("wtp-udp");
+ dissector_add("udp.port", UDP_PORT_WTP_WSP, wtp_fromudp_handle);
+ dissector_add("gsm-sms-ud.udh.port", UDP_PORT_WTP_WSP, wtp_fromudp_handle);
+}
diff --git a/epan/dissectors/packet-wtp.h b/epan/dissectors/packet-wtp.h
new file mode 100644
index 0000000000..552cff095c
--- /dev/null
+++ b/epan/dissectors/packet-wtp.h
@@ -0,0 +1,63 @@
+/* packet-wtp.h
+ *
+ * Declarations for disassembly of WTP component of WAP traffic.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * WAP dissector based on original work by Ben Fowler
+ * Updated by Neil Hunter <neil.hunter@energis-squared.com>
+ * WTLS support by Alexandre P. Ferreira (Splice IP)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_WTP_H__
+#define __PACKET_WTP_H__
+
+/* Implementation Status:
+ *
+ * All fixed headers decoded for non-concatenated PDUs.
+ *
+ * TODO:
+ * Support for concatenated PDUs
+ * Support for decoding TPIs in variable header
+ */
+
+/* WTP PDU Types
+ See section 9.1 (p. 40) of spec-wtp-19990611.pdf
+*/
+
+enum {
+ ERRONEOUS = -0x01,
+ NOT_ALLOWED = 0x00,
+ INVOKE = 0x01,
+ RESULT = 0x02,
+ ACK = 0x03,
+ ABORT = 0x04,
+ SEGMENTED_INVOKE = 0x05,
+ SEGMENTED_RESULT = 0x06,
+ NEGATIVE_ACK = 0x07
+};
+
+enum {
+ PROVIDER = 0x00,
+ USER = 0x01
+};
+
+#endif /* packet-wtp.h */
diff --git a/epan/dissectors/packet-x11-keysym.h b/epan/dissectors/packet-x11-keysym.h
new file mode 100644
index 0000000000..9afbfd5e93
--- /dev/null
+++ b/epan/dissectors/packet-x11-keysym.h
@@ -0,0 +1,349 @@
+/* packet-x11-keysym.h
+ *
+ * $Id$
+ *
+ * Put there so as to make packet-x11.c lighter. See packet-x11.c
+ */
+
+#ifndef __PACKET_X11_KEYSYM_H__
+#define __PACKET_X11_KEYSYM_H__
+
+static const value_string keysym_vals_source[] = {
+ { 0, "NoSymbol" }, { 0x020, "space" }, { 0x021, "!" }, { 0x022, "\"" },
+ { 0x023, "#" }, { 0x024, "$" }, { 0x025, "%" }, { 0x026, "&" },
+ { 0x027, "'" }, { 0x028, "(" }, { 0x029, ")" }, { 0x02a, "*" },
+ { 0x02b, "+" }, { 0x02c, "," }, { 0x02d, "-" }, { 0x02e, "." },
+ { 0x02f, "/" }, { 0x030, "0" }, { 0x031, "1" }, { 0x032, "2" },
+ { 0x033, "3" }, { 0x034, "4" }, { 0x035, "5" }, { 0x036, "6" },
+ { 0x037, "7" }, { 0x038, "8" }, { 0x039, "9" }, { 0x03a, ":" },
+ { 0x03b, ";" }, { 0x03c, "<" }, { 0x03d, "=" }, { 0x03e, ">" },
+ { 0x03f, "?" }, { 0x040, "@" }, { 0x041, "A" }, { 0x042, "B" },
+ { 0x043, "C" }, { 0x044, "D" }, { 0x045, "E" }, { 0x046, "F" },
+ { 0x047, "G" }, { 0x048, "H" }, { 0x049, "I" }, { 0x04a, "J" },
+ { 0x04b, "K" }, { 0x04c, "L" }, { 0x04d, "M" }, { 0x04e, "N" },
+ { 0x04f, "O" }, { 0x050, "P" }, { 0x051, "Q" }, { 0x052, "R" },
+ { 0x053, "S" }, { 0x054, "T" }, { 0x055, "U" }, { 0x056, "V" },
+ { 0x057, "W" }, { 0x058, "X" }, { 0x059, "Y" }, { 0x05a, "Z" },
+ { 0x05b, "[" }, { 0x05c, "\\" }, { 0x05d, "]" }, { 0x05e, "^" },
+ { 0x05f, "_" }, { 0x060, "`" }, { 0x061, "a" }, { 0x062, "b" },
+ { 0x063, "c" }, { 0x064, "d" }, { 0x065, "e" }, { 0x066, "f" },
+ { 0x067, "g" }, { 0x068, "h" }, { 0x069, "i" }, { 0x06a, "j" },
+ { 0x06b, "k" }, { 0x06c, "l" }, { 0x06d, "m" }, { 0x06e, "n" },
+ { 0x06f, "o" }, { 0x070, "p" }, { 0x071, "q" }, { 0x072, "r" },
+ { 0x073, "s" }, { 0x074, "t" }, { 0x075, "u" }, { 0x076, "v" },
+ { 0x077, "w" }, { 0x078, "x" }, { 0x079, "y" }, { 0x07a, "z" },
+ { 0x07b, "{" }, { 0x07c, "|" }, { 0x07d, ", HFILL }" }, { 0x07e, "~" },
+ { 0x0a0, "nobreakspace" }, { 0x0a1, "\x0a1" }, { 0x0a2, "\x0a2" }, { 0x0a3, "\x0a3" },
+ { 0x0a4, "\x0a4" }, { 0x0a5, "\x0a5" }, { 0x0a6, "\x0a6" }, { 0x0a7, "\x0a7" },
+ { 0x0a8, "\x0a8" }, { 0x0a9, "\x0a9" }, { 0x0aa, "\x0aa" }, { 0x0ab, "\x0ab" },
+ { 0x0ac, "\x0ac" }, { 0x0ad, "\x0ad" }, { 0x0ae, "\x0ae" }, { 0x0af, "\x0af" },
+ { 0x0b0, "\x0b0" }, { 0x0b1, "\x0b1" }, { 0x0b2, "\x0b2" }, { 0x0b3, "\x0b3" },
+ { 0x0b4, "\x0b4" }, { 0x0b5, "\x0b5" }, { 0x0b6, "\x0b6" }, { 0x0b7, "\x0b7" },
+ { 0x0b8, "\x0b8" }, { 0x0b9, "\x0b9" }, { 0x0ba, "\x0ba" }, { 0x0bb, "\x0bb" },
+ { 0x0bc, "\x0bc" }, { 0x0bd, "\x0bd" }, { 0x0be, "\x0be" }, { 0x0bf, "\x0bf" },
+ { 0x0c0, "\x0c0" }, { 0x0c1, "\x0c1" }, { 0x0c2, "\x0c2" }, { 0x0c3, "\x0c3" },
+ { 0x0c4, "\x0c4" }, { 0x0c5, "\x0c5" }, { 0x0c6, "\x0c6" }, { 0x0c7, "\x0c7" },
+ { 0x0c8, "\x0c8" }, { 0x0c9, "\x0c9" }, { 0x0ca, "\x0ca" }, { 0x0cb, "\x0cb" },
+ { 0x0cc, "\x0cc" }, { 0x0cd, "\x0cd" }, { 0x0ce, "\x0ce" }, { 0x0cf, "\x0cf" },
+
+ { 0x0d0, "\x0d0" }, { 0x0d1, "\x0d1" }, { 0x0d2, "\x0d2" }, { 0x0d3, "\x0d3" },
+ { 0x0d4, "\x0d4" }, { 0x0d5, "\x0d5" }, { 0x0d6, "\x0d6" }, { 0x0d7, "\x0d7" },
+ { 0x0d8, "\x0d8" }, { 0x0d9, "\x0d9" }, { 0x0da, "\x0da" }, { 0x0db, "\x0db" },
+ { 0x0dc, "\x0dc" }, { 0x0dd, "\x0dd" }, { 0x0de, "\x0de" }, { 0x0df, "\x0df" },
+ { 0x0e0, "\x0e0" }, { 0x0e1, "\x0e1" }, { 0x0e2, "\x0e2" }, { 0x0e3, "\x0e3" },
+ { 0x0e4, "\x0e4" }, { 0x0e5, "\x0e5" }, { 0x0e6, "\x0e6" }, { 0x0e7, "\x0e7" },
+ { 0x0e8, "\x0e8" }, { 0x0e9, "\x0e9" }, { 0x0ea, "\x0ea" }, { 0x0eb, "\x0eb" },
+ { 0x0ec, "\x0ec" }, { 0x0ed, "\x0ed" }, { 0x0ee, "\x0ee" }, { 0x0ef, "\x0ef" },
+ { 0x0f0, "\x0f0" }, { 0x0f1, "\x0f1" }, { 0x0f2, "\x0f2" }, { 0x0f3, "\x0f3" },
+ { 0x0f4, "\x0f4" }, { 0x0f5, "\x0f5" }, { 0x0f6, "\x0f6" }, { 0x0f7, "\x0f7" },
+ { 0x0f8, "\x0f8" }, { 0x0f9, "\x0f9" }, { 0x0fa, "\x0fa" }, { 0x0fb, "\x0fb" },
+ { 0x0fc, "\x0fc" }, { 0x0fd, "\x0fd" }, { 0x0fe, "\x0fe" }, { 0x0ff, "\x0ff" },
+ { 0x13bc, "OE" }, { 0x13bd, "oe" }, { 0x13be, "Ydiaeresis" },
+ { 0x1a1, "Aogonek" }, { 0x1a2, "breve" }, { 0x1a3, "Lstroke" }, { 0x1a5, "Lcaron" },
+ { 0x1a6, "Sacute" }, { 0x1a9, "Scaron" }, { 0x1aa, "Scedilla" }, { 0x1ab, "Tcaron" },
+ { 0x1ac, "Zacute" }, { 0x1ae, "Zcaron" }, { 0x1af, "Zabovedot" }, { 0x1b1, "aogonek" },
+ { 0x1b2, "ogonek" }, { 0x1b3, "lstroke" }, { 0x1b5, "lcaron" }, { 0x1b6, "sacute" },
+ { 0x1b7, "caron" }, { 0x1b9, "scaron" }, { 0x1ba, "scedilla" }, { 0x1bb, "tcaron" },
+ { 0x1bc, "zacute" }, { 0x1bd, "doubleacute" }, { 0x1be, "zcaron" }, { 0x1bf, "zabovedot" },
+ { 0x1c0, "Racute" }, { 0x1c3, "Abreve" }, { 0x1c5, "Lacute" }, { 0x1c6, "Cacute" },
+ { 0x1c8, "Ccaron" }, { 0x1ca, "Eogonek" }, { 0x1cc, "Ecaron" }, { 0x1cf, "Dcaron" },
+ { 0x1d0, "Dstroke" }, { 0x1d1, "Nacute" }, { 0x1d2, "Ncaron" }, { 0x1d5, "Odoubleacute" },
+ { 0x1d8, "Rcaron" }, { 0x1d9, "Uring" }, { 0x1db, "Udoubleacute" }, { 0x1de, "Tcedilla" },
+ { 0x1e0, "racute" }, { 0x1e3, "abreve" }, { 0x1e5, "lacute" }, { 0x1e6, "cacute" },
+ { 0x1e8, "ccaron" }, { 0x1ea, "eogonek" }, { 0x1ec, "ecaron" }, { 0x1ef, "dcaron" },
+ { 0x1f0, "dstroke" }, { 0x1f1, "nacute" }, { 0x1f2, "ncaron" }, { 0x1f5, "odoubleacute" },
+ { 0x1f8, "rcaron" }, { 0x1f9, "uring" }, { 0x1fb, "udoubleacute" }, { 0x1fe, "tcedilla" },
+ { 0x1ff, "abovedot" }, { 0x20a0, "EcuSign" }, { 0x20a1, "ColonSign" }, { 0x20a2, "CruzeiroSign" },
+ { 0x20a3, "FFrancSign" }, { 0x20a4, "LiraSign" }, { 0x20a5, "MillSign" }, { 0x20a6, "NairaSign" },
+ { 0x20a7, "PesetaSign" }, { 0x20a8, "RupeeSign" }, { 0x20a9, "WonSign" }, { 0x20aa, "NewSheqelSign" },
+ { 0x20ab, "DongSign" }, { 0x20ac, "EuroSign" }, { 0x2a1, "Hstroke" }, { 0x2a6, "Hcircumflex" },
+ { 0x2a9, "Iabovedot" }, { 0x2ab, "Gbreve" }, { 0x2ac, "Jcircumflex" }, { 0x2b1, "hstroke" },
+ { 0x2b6, "hcircumflex" }, { 0x2b9, "idotless" }, { 0x2bb, "gbreve" }, { 0x2bc, "jcircumflex" },
+ { 0x2c5, "Cabovedot" }, { 0x2c6, "Ccircumflex" }, { 0x2d5, "Gabovedot" }, { 0x2d8, "Gcircumflex" },
+ { 0x2dd, "Ubreve" }, { 0x2de, "Scircumflex" }, { 0x2e5, "cabovedot" }, { 0x2e6, "ccircumflex" },
+ { 0x2f5, "gabovedot" }, { 0x2f8, "gcircumflex" }, { 0x2fd, "ubreve" }, { 0x2fe, "scircumflex" },
+ { 0x3a2, "kappa" }, { 0x3a2, "kra" }, { 0x3a3, "Rcedilla" }, { 0x3a5, "Itilde" },
+ { 0x3a6, "Lcedilla" }, { 0x3aa, "Emacron" }, { 0x3ab, "Gcedilla" }, { 0x3ac, "Tslash" },
+ { 0x3b3, "rcedilla" }, { 0x3b5, "itilde" }, { 0x3b6, "lcedilla" }, { 0x3ba, "emacron" },
+ { 0x3bb, "gcedilla" }, { 0x3bc, "tslash" }, { 0x3bd, "ENG" }, { 0x3bf, "eng" },
+ { 0x3c0, "Amacron" }, { 0x3c7, "Iogonek" }, { 0x3cc, "Eabovedot" }, { 0x3cf, "Imacron" },
+ { 0x3d1, "Ncedilla" }, { 0x3d2, "Omacron" }, { 0x3d3, "Kcedilla" }, { 0x3d9, "Uogonek" },
+ { 0x3dd, "Utilde" }, { 0x3de, "Umacron" }, { 0x3e0, "amacron" }, { 0x3e7, "iogonek" },
+ { 0x3ec, "eabovedot" }, { 0x3ef, "imacron" }, { 0x3f1, "ncedilla" }, { 0x3f2, "omacron" },
+ { 0x3f3, "kcedilla" }, { 0x3f9, "uogonek" }, { 0x3fd, "utilde" }, { 0x3fe, "umacron" },
+ { 0x47e, "overline" }, { 0x4a1, "kana_fullstop" }, { 0x4a2, "kana_openingbracket" }, { 0x4a3, "kana_closingbracket" },
+ { 0x4a4, "kana_comma" }, { 0x4a5, "kana_conjunctive" }, { 0x4a5, "kana_middledot" }, { 0x4a6, "kana_WO" },
+ { 0x4a7, "kana_a" }, { 0x4a8, "kana_i" }, { 0x4a9, "kana_u" }, { 0x4aa, "kana_e" },
+ { 0x4ab, "kana_o" }, { 0x4ac, "kana_ya" }, { 0x4ad, "kana_yu" }, { 0x4ae, "kana_yo" },
+ { 0x4af, "kana_tsu" }, { 0x4af, "kana_tu" }, { 0x4b0, "prolongedsound" }, { 0x4b1, "kana_A" },
+ { 0x4b2, "kana_I" }, { 0x4b3, "kana_U" }, { 0x4b4, "kana_E" }, { 0x4b5, "kana_O" },
+ { 0x4b6, "kana_KA" }, { 0x4b7, "kana_KI" }, { 0x4b8, "kana_KU" }, { 0x4b9, "kana_KE" },
+ { 0x4ba, "kana_KO" }, { 0x4bb, "kana_SA" }, { 0x4bc, "kana_SHI" }, { 0x4bd, "kana_SU" },
+ { 0x4be, "kana_SE" }, { 0x4bf, "kana_SO" }, { 0x4c0, "kana_TA" }, { 0x4c1, "kana_CHI" },
+ { 0x4c1, "kana_TI" }, { 0x4c2, "kana_TSU" }, { 0x4c2, "kana_TU" }, { 0x4c3, "kana_TE" },
+ { 0x4c4, "kana_TO" }, { 0x4c5, "kana_NA" }, { 0x4c6, "kana_NI" }, { 0x4c7, "kana_NU" },
+ { 0x4c8, "kana_NE" }, { 0x4c9, "kana_NO" }, { 0x4ca, "kana_HA" }, { 0x4cb, "kana_HI" },
+ { 0x4cc, "kana_FU" }, { 0x4cc, "kana_HU" }, { 0x4cd, "kana_HE" }, { 0x4ce, "kana_HO" },
+ { 0x4cf, "kana_MA" }, { 0x4d0, "kana_MI" }, { 0x4d1, "kana_MU" }, { 0x4d2, "kana_ME" },
+ { 0x4d3, "kana_MO" }, { 0x4d4, "kana_YA" }, { 0x4d5, "kana_YU" }, { 0x4d6, "kana_YO" },
+ { 0x4d7, "kana_RA" }, { 0x4d8, "kana_RI" }, { 0x4d9, "kana_RU" }, { 0x4da, "kana_RE" },
+ { 0x4db, "kana_RO" }, { 0x4dc, "kana_WA" }, { 0x4dd, "kana_N" }, { 0x4de, "voicedsound" },
+ { 0x4df, "semivoicedsound" }, { 0x5ac, "Arabic_comma" }, { 0x5bb, "Arabic_semicolon" }, { 0x5bf, "Arabic_question_mark" },
+ { 0x5c1, "Arabic_hamza" }, { 0x5c2, "Arabic_maddaonalef" }, { 0x5c3, "Arabic_hamzaonalef" }, { 0x5c4, "Arabic_hamzaonwaw" },
+ { 0x5c5, "Arabic_hamzaunderalef" }, { 0x5c6, "Arabic_hamzaonyeh" }, { 0x5c7, "Arabic_alef" }, { 0x5c8, "Arabic_beh" },
+ { 0x5c9, "Arabic_tehmarbuta" }, { 0x5ca, "Arabic_teh" }, { 0x5cb, "Arabic_theh" }, { 0x5cc, "Arabic_jeem" },
+ { 0x5cd, "Arabic_hah" }, { 0x5ce, "Arabic_khah" }, { 0x5cf, "Arabic_dal" }, { 0x5d0, "Arabic_thal" },
+ { 0x5d1, "Arabic_ra" }, { 0x5d2, "Arabic_zain" }, { 0x5d3, "Arabic_seen" }, { 0x5d4, "Arabic_sheen" },
+ { 0x5d5, "Arabic_sad" }, { 0x5d6, "Arabic_dad" }, { 0x5d7, "Arabic_tah" }, { 0x5d8, "Arabic_zah" },
+ { 0x5d9, "Arabic_ain" }, { 0x5da, "Arabic_ghain" }, { 0x5e0, "Arabic_tatweel" }, { 0x5e1, "Arabic_feh" },
+ { 0x5e2, "Arabic_qaf" }, { 0x5e3, "Arabic_kaf" }, { 0x5e4, "Arabic_lam" }, { 0x5e5, "Arabic_meem" },
+ { 0x5e6, "Arabic_noon" }, { 0x5e7, "Arabic_ha" }, { 0x5e7, "Arabic_heh" }, { 0x5e8, "Arabic_waw" },
+ { 0x5e9, "Arabic_alefmaksura" }, { 0x5ea, "Arabic_yeh" }, { 0x5eb, "Arabic_fathatan" }, { 0x5ec, "Arabic_dammatan" },
+ { 0x5ed, "Arabic_kasratan" }, { 0x5ee, "Arabic_fatha" }, { 0x5ef, "Arabic_damma" }, { 0x5f0, "Arabic_kasra" },
+ { 0x5f1, "Arabic_shadda" }, { 0x5f2, "Arabic_sukun" }, { 0x6a1, "Serbian_dje" }, { 0x6a2, "Macedonia_gje" },
+ { 0x6a3, "Cyrillic_io" }, { 0x6a4, "Ukrainian_ie" }, { 0x6a4, "Ukranian_je" }, { 0x6a5, "Macedonia_dse" },
+ { 0x6a6, "Ukrainian_i" }, { 0x6a6, "Ukranian_i" }, { 0x6a7, "Ukrainian_yi" }, { 0x6a7, "Ukranian_yi" },
+ { 0x6a8, "Cyrillic_je" }, { 0x6a8, "Serbian_je" }, { 0x6a9, "Cyrillic_lje" }, { 0x6a9, "Serbian_lje" },
+ { 0x6aa, "Cyrillic_nje" }, { 0x6aa, "Serbian_nje" }, { 0x6ab, "Serbian_tshe" }, { 0x6ac, "Macedonia_kje" },
+ { 0x6ae, "Byelorussian_shortu" }, { 0x6af, "Cyrillic_dzhe" }, { 0x6af, "Serbian_dze" }, { 0x6b0, "numerosign" },
+ { 0x6b1, "Serbian_DJE" }, { 0x6b2, "Macedonia_GJE" }, { 0x6b3, "Cyrillic_IO" }, { 0x6b4, "Ukrainian_IE" },
+ { 0x6b4, "Ukranian_JE" }, { 0x6b5, "Macedonia_DSE" }, { 0x6b6, "Ukrainian_I" }, { 0x6b6, "Ukranian_I" },
+ { 0x6b7, "Ukrainian_YI" }, { 0x6b7, "Ukranian_YI" }, { 0x6b8, "Cyrillic_JE" }, { 0x6b8, "Serbian_JE" },
+ { 0x6b9, "Cyrillic_LJE" }, { 0x6b9, "Serbian_LJE" }, { 0x6ba, "Cyrillic_NJE" }, { 0x6ba, "Serbian_NJE" },
+ { 0x6bb, "Serbian_TSHE" }, { 0x6bc, "Macedonia_KJE" }, { 0x6be, "Byelorussian_SHORTU" }, { 0x6bf, "Cyrillic_DZHE" },
+ { 0x6bf, "Serbian_DZE" }, { 0x6c0, "Cyrillic_yu" }, { 0x6c1, "Cyrillic_a" }, { 0x6c2, "Cyrillic_be" },
+ { 0x6c3, "Cyrillic_tse" }, { 0x6c4, "Cyrillic_de" }, { 0x6c5, "Cyrillic_ie" }, { 0x6c6, "Cyrillic_ef" },
+ { 0x6c7, "Cyrillic_ghe" }, { 0x6c8, "Cyrillic_ha" }, { 0x6c9, "Cyrillic_i" }, { 0x6ca, "Cyrillic_shorti" },
+ { 0x6cb, "Cyrillic_ka" }, { 0x6cc, "Cyrillic_el" }, { 0x6cd, "Cyrillic_em" }, { 0x6ce, "Cyrillic_en" },
+ { 0x6cf, "Cyrillic_o" }, { 0x6d0, "Cyrillic_pe" }, { 0x6d1, "Cyrillic_ya" }, { 0x6d2, "Cyrillic_er" },
+ { 0x6d3, "Cyrillic_es" }, { 0x6d4, "Cyrillic_te" }, { 0x6d5, "Cyrillic_u" }, { 0x6d6, "Cyrillic_zhe" },
+ { 0x6d7, "Cyrillic_ve" }, { 0x6d8, "Cyrillic_softsign" }, { 0x6d9, "Cyrillic_yeru" }, { 0x6da, "Cyrillic_ze" },
+ { 0x6db, "Cyrillic_sha" }, { 0x6dc, "Cyrillic_e" }, { 0x6dd, "Cyrillic_shcha" }, { 0x6de, "Cyrillic_che" },
+ { 0x6df, "Cyrillic_hardsign" }, { 0x6e0, "Cyrillic_YU" }, { 0x6e1, "Cyrillic_A" }, { 0x6e2, "Cyrillic_BE" },
+ { 0x6e3, "Cyrillic_TSE" }, { 0x6e4, "Cyrillic_DE" }, { 0x6e5, "Cyrillic_IE" }, { 0x6e6, "Cyrillic_EF" },
+ { 0x6e7, "Cyrillic_GHE" }, { 0x6e8, "Cyrillic_HA" }, { 0x6e9, "Cyrillic_I" }, { 0x6ea, "Cyrillic_SHORTI" },
+ { 0x6eb, "Cyrillic_KA" }, { 0x6ec, "Cyrillic_EL" }, { 0x6ed, "Cyrillic_EM" }, { 0x6ee, "Cyrillic_EN" },
+ { 0x6ef, "Cyrillic_O" }, { 0x6f0, "Cyrillic_PE" }, { 0x6f1, "Cyrillic_YA" }, { 0x6f2, "Cyrillic_ER" },
+ { 0x6f3, "Cyrillic_ES" }, { 0x6f4, "Cyrillic_TE" }, { 0x6f5, "Cyrillic_U" }, { 0x6f6, "Cyrillic_ZHE" },
+ { 0x6f7, "Cyrillic_VE" }, { 0x6f8, "Cyrillic_SOFTSIGN" }, { 0x6f9, "Cyrillic_YERU" }, { 0x6fa, "Cyrillic_ZE" },
+ { 0x6fb, "Cyrillic_SHA" }, { 0x6fc, "Cyrillic_E" }, { 0x6fd, "Cyrillic_SHCHA" }, { 0x6fe, "Cyrillic_CHE" },
+ { 0x6ff, "Cyrillic_HARDSIGN" }, { 0x7a1, "Greek_ALPHAaccent" }, { 0x7a2, "Greek_EPSILONaccent" }, { 0x7a3, "Greek_ETAaccent" },
+ { 0x7a4, "Greek_IOTAaccent" }, { 0x7a5, "Greek_IOTAdiaeresis" }, { 0x7a7, "Greek_OMICRONaccent" }, { 0x7a8, "Greek_UPSILONaccent" },
+ { 0x7a9, "Greek_UPSILONdieresis" }, { 0x7ab, "Greek_OMEGAaccent" }, { 0x7ae, "Greek_accentdieresis" }, { 0x7af, "Greek_horizbar" },
+ { 0x7b1, "Greek_alphaaccent" }, { 0x7b2, "Greek_epsilonaccent" }, { 0x7b3, "Greek_etaaccent" }, { 0x7b4, "Greek_iotaaccent" },
+ { 0x7b5, "Greek_iotadieresis" }, { 0x7b6, "Greek_iotaaccentdieresis" }, { 0x7b7, "Greek_omicronaccent" }, { 0x7b8, "Greek_upsilonaccent" },
+ { 0x7b9, "Greek_upsilondieresis" }, { 0x7ba, "Greek_upsilonaccentdieresis" }, { 0x7bb, "Greek_omegaaccent" }, { 0x7c1, "Greek_ALPHA" },
+ { 0x7c2, "Greek_BETA" }, { 0x7c3, "Greek_GAMMA" }, { 0x7c4, "Greek_DELTA" }, { 0x7c5, "Greek_EPSILON" },
+ { 0x7c6, "Greek_ZETA" }, { 0x7c7, "Greek_ETA" }, { 0x7c8, "Greek_THETA" }, { 0x7c9, "Greek_IOTA" },
+ { 0x7ca, "Greek_KAPPA" }, { 0x7cb, "Greek_LAMBDA" }, { 0x7cb, "Greek_LAMDA" }, { 0x7cc, "Greek_MU" },
+ { 0x7cd, "Greek_NU" }, { 0x7ce, "Greek_XI" }, { 0x7cf, "Greek_OMICRON" }, { 0x7d0, "Greek_PI" },
+ { 0x7d1, "Greek_RHO" }, { 0x7d2, "Greek_SIGMA" }, { 0x7d4, "Greek_TAU" }, { 0x7d5, "Greek_UPSILON" },
+ { 0x7d6, "Greek_PHI" }, { 0x7d7, "Greek_CHI" }, { 0x7d8, "Greek_PSI" }, { 0x7d9, "Greek_OMEGA" },
+ { 0x7e1, "Greek_alpha" }, { 0x7e2, "Greek_beta" }, { 0x7e3, "Greek_gamma" }, { 0x7e4, "Greek_delta" },
+ { 0x7e5, "Greek_epsilon" }, { 0x7e6, "Greek_zeta" }, { 0x7e7, "Greek_eta" }, { 0x7e8, "Greek_theta" },
+ { 0x7e9, "Greek_iota" }, { 0x7ea, "Greek_kappa" }, { 0x7eb, "Greek_lambda" }, { 0x7eb, "Greek_lamda" },
+ { 0x7ec, "Greek_mu" }, { 0x7ed, "Greek_nu" }, { 0x7ee, "Greek_xi" }, { 0x7ef, "Greek_omicron" },
+ { 0x7f0, "Greek_pi" }, { 0x7f1, "Greek_rho" }, { 0x7f2, "Greek_sigma" }, { 0x7f3, "Greek_finalsmallsigma" },
+ { 0x7f4, "Greek_tau" }, { 0x7f5, "Greek_upsilon" }, { 0x7f6, "Greek_phi" }, { 0x7f7, "Greek_chi" },
+ { 0x7f8, "Greek_psi" }, { 0x7f9, "Greek_omega" }, { 0x8a1, "leftradical" }, { 0x8a2, "topleftradical" },
+ { 0x8a3, "horizconnector" }, { 0x8a4, "topintegral" }, { 0x8a5, "botintegral" }, { 0x8a6, "vertconnector" },
+ { 0x8a7, "topleftsqbracket" }, { 0x8a8, "botleftsqbracket" }, { 0x8a9, "toprightsqbracket" }, { 0x8aa, "botrightsqbracket" },
+ { 0x8ab, "topleftparens" }, { 0x8ac, "botleftparens" }, { 0x8ad, "toprightparens" }, { 0x8ae, "botrightparens" },
+ { 0x8af, "leftmiddlecurlybrace" }, { 0x8b0, "rightmiddlecurlybrace" }, { 0x8b1, "topleftsummation" }, { 0x8b2, "botleftsummation" },
+ { 0x8b3, "topvertsummationconnector" }, { 0x8b4, "botvertsummationconnector" }, { 0x8b5, "toprightsummation" }, { 0x8b6, "botrightsummation" },
+ { 0x8b7, "rightmiddlesummation" }, { 0x8bc, "lessthanequal" }, { 0x8bd, "notequal" }, { 0x8be, "greaterthanequal" },
+ { 0x8bf, "integral" }, { 0x8c0, "therefore" }, { 0x8c1, "variation" }, { 0x8c2, "infinity" },
+ { 0x8c5, "nabla" }, { 0x8c8, "approximate" }, { 0x8c9, "similarequal" }, { 0x8cd, "ifonlyif" },
+ { 0x8ce, "implies" }, { 0x8cf, "identical" }, { 0x8d6, "radical" }, { 0x8da, "includedin" },
+ { 0x8db, "includes" }, { 0x8dc, "intersection" }, { 0x8dd, "union" }, { 0x8de, "logicaland" },
+ { 0x8df, "logicalor" }, { 0x8ef, "partialderivative" }, { 0x8f6, "function" }, { 0x8fb, "leftarrow" },
+ { 0x8fc, "uparrow" }, { 0x8fd, "rightarrow" }, { 0x8fe, "downarrow" }, { 0x9df, "blank" },
+ { 0x9e0, "soliddiamond" }, { 0x9e1, "checkerboard" }, { 0x9e2, "ht" }, { 0x9e3, "ff" },
+ { 0x9e4, "cr" }, { 0x9e5, "lf" }, { 0x9e8, "nl" }, { 0x9e9, "vt" },
+ { 0x9ea, "lowrightcorner" }, { 0x9eb, "uprightcorner" }, { 0x9ec, "upleftcorner" }, { 0x9ed, "lowleftcorner" },
+ { 0x9ee, "crossinglines" }, { 0x9ef, "horizlinescan1" }, { 0x9f0, "horizlinescan3" }, { 0x9f1, "horizlinescan5" },
+ { 0x9f2, "horizlinescan7" }, { 0x9f3, "horizlinescan9" }, { 0x9f4, "leftt" }, { 0x9f5, "rightt" },
+ { 0x9f6, "bott" }, { 0x9f7, "topt" }, { 0x9f8, "vertbar" }, { 0xaa1, "emspace" },
+ { 0xaa2, "enspace" }, { 0xaa3, "em3space" }, { 0xaa4, "em4space" }, { 0xaa5, "digitspace" },
+ { 0xaa6, "punctspace" }, { 0xaa7, "thinspace" }, { 0xaa8, "hairspace" }, { 0xaa9, "emdash" },
+ { 0xaaa, "endash" }, { 0xaac, "signifblank" }, { 0xaae, "ellipsis" }, { 0xaaf, "doubbaselinedot" },
+ { 0xab0, "onethird" }, { 0xab1, "twothirds" }, { 0xab2, "onefifth" }, { 0xab3, "twofifths" },
+ { 0xab4, "threefifths" }, { 0xab5, "fourfifths" }, { 0xab6, "onesixth" }, { 0xab7, "fivesixths" },
+ { 0xab8, "careof" }, { 0xabb, "figdash" }, { 0xabc, "leftanglebracket" }, { 0xabd, "decimalpoint" },
+ { 0xabe, "rightanglebracket" }, { 0xabf, "marker" }, { 0xac3, "oneeighth" }, { 0xac4, "threeeighths" },
+ { 0xac5, "fiveeighths" }, { 0xac6, "seveneighths" }, { 0xac9, "trademark" }, { 0xaca, "signaturemark" },
+ { 0xacb, "trademarkincircle" }, { 0xacc, "leftopentriangle" }, { 0xacd, "rightopentriangle" }, { 0xace, "emopencircle" },
+ { 0xacf, "emopenrectangle" }, { 0xad0, "leftsinglequotemark" }, { 0xad1, "rightsinglequotemark" }, { 0xad2, "leftdoublequotemark" },
+ { 0xad3, "rightdoublequotemark" }, { 0xad4, "prescription" }, { 0xad6, "minutes" }, { 0xad7, "seconds" },
+ { 0xad9, "latincross" }, { 0xada, "hexagram" }, { 0xadb, "filledrectbullet" }, { 0xadc, "filledlefttribullet" },
+ { 0xadd, "filledrighttribullet" }, { 0xade, "emfilledcircle" }, { 0xadf, "emfilledrect" }, { 0xae0, "enopencircbullet" },
+ { 0xae1, "enopensquarebullet" }, { 0xae2, "openrectbullet" }, { 0xae3, "opentribulletup" }, { 0xae4, "opentribulletdown" },
+ { 0xae5, "openstar" }, { 0xae6, "enfilledcircbullet" }, { 0xae7, "enfilledsqbullet" }, { 0xae8, "filledtribulletup" },
+ { 0xae9, "filledtribulletdown" }, { 0xaea, "leftpointer" }, { 0xaeb, "rightpointer" }, { 0xaec, "club" },
+ { 0xaed, "diamond" }, { 0xaee, "heart" }, { 0xaf0, "maltesecross" }, { 0xaf1, "dagger" },
+ { 0xaf2, "doubledagger" }, { 0xaf3, "checkmark" }, { 0xaf4, "ballotcross" }, { 0xaf5, "musicalsharp" },
+ { 0xaf6, "musicalflat" }, { 0xaf7, "malesymbol" }, { 0xaf8, "femalesymbol" }, { 0xaf9, "telephone" },
+ { 0xafa, "telephonerecorder" }, { 0xafb, "phonographcopyright" }, { 0xafc, "caret" }, { 0xafd, "singlelowquotemark" },
+ { 0xafe, "doublelowquotemark" }, { 0xaff, "cursor" }, { 0xba3, "leftcaret" }, { 0xba6, "rightcaret" },
+ { 0xba8, "downcaret" }, { 0xba9, "upcaret" }, { 0xbc0, "overbar" }, { 0xbc2, "downtack" },
+ { 0xbc3, "upshoe" }, { 0xbc4, "downstile" }, { 0xbc6, "underbar" }, { 0xbca, "jot" },
+ { 0xbcc, "quad" }, { 0xbce, "uptack" }, { 0xbcf, "circle" }, { 0xbd3, "upstile" },
+ { 0xbd6, "downshoe" }, { 0xbd8, "rightshoe" }, { 0xbda, "leftshoe" }, { 0xbdc, "lefttack" },
+ { 0xbfc, "righttack" }, { 0xcdf, "hebrew_doublelowline" }, { 0xce0, "hebrew_aleph" }, { 0xce1, "hebrew_bet" },
+ { 0xce1, "hebrew_beth" }, { 0xce2, "hebrew_gimel" }, { 0xce2, "hebrew_gimmel" }, { 0xce3, "hebrew_dalet" },
+ { 0xce3, "hebrew_daleth" }, { 0xce4, "hebrew_he" }, { 0xce5, "hebrew_waw" }, { 0xce6, "hebrew_zain" },
+ { 0xce6, "hebrew_zayin" }, { 0xce7, "hebrew_chet" }, { 0xce7, "hebrew_het" }, { 0xce8, "hebrew_tet" },
+ { 0xce8, "hebrew_teth" }, { 0xce9, "hebrew_yod" }, { 0xcea, "hebrew_finalkaph" }, { 0xceb, "hebrew_kaph" },
+ { 0xcec, "hebrew_lamed" }, { 0xced, "hebrew_finalmem" }, { 0xcee, "hebrew_mem" }, { 0xcef, "hebrew_finalnun" },
+ { 0xcf0, "hebrew_nun" }, { 0xcf1, "hebrew_samech" }, { 0xcf1, "hebrew_samekh" }, { 0xcf2, "hebrew_ayin" },
+ { 0xcf3, "hebrew_finalpe" }, { 0xcf4, "hebrew_pe" }, { 0xcf5, "hebrew_finalzade" }, { 0xcf5, "hebrew_finalzadi" },
+ { 0xcf6, "hebrew_zade" }, { 0xcf6, "hebrew_zadi" }, { 0xcf7, "hebrew_kuf" }, { 0xcf7, "hebrew_qoph" },
+ { 0xcf8, "hebrew_resh" }, { 0xcf9, "hebrew_shin" }, { 0xcfa, "hebrew_taf" }, { 0xcfa, "hebrew_taw" },
+ { 0xda1, "Thai_kokai" }, { 0xda2, "Thai_khokhai" }, { 0xda3, "Thai_khokhuat" }, { 0xda4, "Thai_khokhwai" },
+ { 0xda5, "Thai_khokhon" }, { 0xda6, "Thai_khorakhang" }, { 0xda7, "Thai_ngongu" }, { 0xda8, "Thai_chochan" },
+ { 0xda9, "Thai_choching" }, { 0xdaa, "Thai_chochang" }, { 0xdab, "Thai_soso" }, { 0xdac, "Thai_chochoe" },
+ { 0xdad, "Thai_yoying" }, { 0xdae, "Thai_dochada" }, { 0xdaf, "Thai_topatak" }, { 0xdb0, "Thai_thothan" },
+ { 0xdb1, "Thai_thonangmontho" }, { 0xdb2, "Thai_thophuthao" }, { 0xdb3, "Thai_nonen" }, { 0xdb4, "Thai_dodek" },
+ { 0xdb5, "Thai_totao" }, { 0xdb6, "Thai_thothung" }, { 0xdb7, "Thai_thothahan" }, { 0xdb8, "Thai_thothong" },
+ { 0xdb9, "Thai_nonu" }, { 0xdba, "Thai_bobaimai" }, { 0xdbb, "Thai_popla" }, { 0xdbc, "Thai_phophung" },
+ { 0xdbd, "Thai_fofa" }, { 0xdbe, "Thai_phophan" }, { 0xdbf, "Thai_fofan" }, { 0xdc0, "Thai_phosamphao" },
+ { 0xdc1, "Thai_moma" }, { 0xdc2, "Thai_yoyak" }, { 0xdc3, "Thai_rorua" }, { 0xdc4, "Thai_ru" },
+ { 0xdc5, "Thai_loling" }, { 0xdc6, "Thai_lu" }, { 0xdc7, "Thai_wowaen" }, { 0xdc8, "Thai_sosala" },
+ { 0xdc9, "Thai_sorusi" }, { 0xdca, "Thai_sosua" }, { 0xdcb, "Thai_hohip" }, { 0xdcc, "Thai_lochula" },
+ { 0xdcd, "Thai_oang" }, { 0xdce, "Thai_honokhuk" }, { 0xdcf, "Thai_paiyannoi" }, { 0xdd0, "Thai_saraa" },
+ { 0xdd1, "Thai_maihanakat" }, { 0xdd2, "Thai_saraaa" }, { 0xdd3, "Thai_saraam" }, { 0xdd4, "Thai_sarai" },
+ { 0xdd5, "Thai_saraii" }, { 0xdd6, "Thai_saraue" }, { 0xdd7, "Thai_sarauee" }, { 0xdd8, "Thai_sarau" },
+ { 0xdd9, "Thai_sarauu" }, { 0xdda, "Thai_phinthu" }, { 0xdde, "Thai_maihanakat_maitho" }, { 0xddf, "Thai_baht" },
+ { 0xde0, "Thai_sarae" }, { 0xde1, "Thai_saraae" }, { 0xde2, "Thai_sarao" }, { 0xde3, "Thai_saraaimaimuan" },
+ { 0xde4, "Thai_saraaimaimalai" }, { 0xde5, "Thai_lakkhangyao" }, { 0xde6, "Thai_maiyamok" }, { 0xde7, "Thai_maitaikhu" },
+ { 0xde8, "Thai_maiek" }, { 0xde9, "Thai_maitho" }, { 0xdea, "Thai_maitri" }, { 0xdeb, "Thai_maichattawa" },
+ { 0xdec, "Thai_thanthakhat" }, { 0xded, "Thai_nikhahit" }, { 0xdf0, "Thai_leksun" }, { 0xdf1, "Thai_leknung" },
+ { 0xdf2, "Thai_leksong" }, { 0xdf3, "Thai_leksam" }, { 0xdf4, "Thai_leksi" }, { 0xdf5, "Thai_lekha" },
+ { 0xdf6, "Thai_lekhok" }, { 0xdf7, "Thai_lekchet" }, { 0xdf8, "Thai_lekpaet" }, { 0xdf9, "Thai_lekkao" },
+ { 0xea1, "Hangul_Kiyeog" }, { 0xea2, "Hangul_SsangKiyeog" }, { 0xea3, "Hangul_KiyeogSios" }, { 0xea4, "Hangul_Nieun" },
+ { 0xea5, "Hangul_NieunJieuj" }, { 0xea6, "Hangul_NieunHieuh" }, { 0xea7, "Hangul_Dikeud" }, { 0xea8, "Hangul_SsangDikeud" },
+ { 0xea9, "Hangul_Rieul" }, { 0xeaa, "Hangul_RieulKiyeog" }, { 0xeab, "Hangul_RieulMieum" }, { 0xeac, "Hangul_RieulPieub" },
+ { 0xead, "Hangul_RieulSios" }, { 0xeae, "Hangul_RieulTieut" }, { 0xeaf, "Hangul_RieulPhieuf" }, { 0xeb0, "Hangul_RieulHieuh" },
+ { 0xeb1, "Hangul_Mieum" }, { 0xeb2, "Hangul_Pieub" }, { 0xeb3, "Hangul_SsangPieub" }, { 0xeb4, "Hangul_PieubSios" },
+ { 0xeb5, "Hangul_Sios" }, { 0xeb6, "Hangul_SsangSios" }, { 0xeb7, "Hangul_Ieung" }, { 0xeb8, "Hangul_Jieuj" },
+ { 0xeb9, "Hangul_SsangJieuj" }, { 0xeba, "Hangul_Cieuc" }, { 0xebb, "Hangul_Khieuq" }, { 0xebc, "Hangul_Tieut" },
+ { 0xebd, "Hangul_Phieuf" }, { 0xebe, "Hangul_Hieuh" }, { 0xebf, "Hangul_A" }, { 0xec0, "Hangul_AE" },
+ { 0xec1, "Hangul_YA" }, { 0xec2, "Hangul_YAE" }, { 0xec3, "Hangul_EO" }, { 0xec4, "Hangul_E" },
+ { 0xec5, "Hangul_YEO" }, { 0xec6, "Hangul_YE" }, { 0xec7, "Hangul_O" }, { 0xec8, "Hangul_WA" },
+ { 0xec9, "Hangul_WAE" }, { 0xeca, "Hangul_OE" }, { 0xecb, "Hangul_YO" }, { 0xecc, "Hangul_U" },
+ { 0xecd, "Hangul_WEO" }, { 0xece, "Hangul_WE" }, { 0xecf, "Hangul_WI" }, { 0xed0, "Hangul_YU" },
+ { 0xed1, "Hangul_EU" }, { 0xed2, "Hangul_YI" }, { 0xed3, "Hangul_I" }, { 0xed4, "Hangul_J_Kiyeog" },
+ { 0xed5, "Hangul_J_SsangKiyeog" }, { 0xed6, "Hangul_J_KiyeogSios" }, { 0xed7, "Hangul_J_Nieun" }, { 0xed8, "Hangul_J_NieunJieuj" },
+ { 0xed9, "Hangul_J_NieunHieuh" }, { 0xeda, "Hangul_J_Dikeud" }, { 0xedb, "Hangul_J_Rieul" }, { 0xedc, "Hangul_J_RieulKiyeog" },
+ { 0xedd, "Hangul_J_RieulMieum" }, { 0xede, "Hangul_J_RieulPieub" }, { 0xedf, "Hangul_J_RieulSios" }, { 0xee0, "Hangul_J_RieulTieut" },
+ { 0xee1, "Hangul_J_RieulPhieuf" }, { 0xee2, "Hangul_J_RieulHieuh" }, { 0xee3, "Hangul_J_Mieum" }, { 0xee4, "Hangul_J_Pieub" },
+ { 0xee5, "Hangul_J_PieubSios" }, { 0xee6, "Hangul_J_Sios" }, { 0xee7, "Hangul_J_SsangSios" }, { 0xee8, "Hangul_J_Ieung" },
+ { 0xee9, "Hangul_J_Jieuj" }, { 0xeea, "Hangul_J_Cieuc" }, { 0xeeb, "Hangul_J_Khieuq" }, { 0xeec, "Hangul_J_Tieut" },
+ { 0xeed, "Hangul_J_Phieuf" }, { 0xeee, "Hangul_J_Hieuh" }, { 0xeef, "Hangul_RieulYeorinHieuh" }, { 0xef0, "Hangul_SunkyeongeumMieum" },
+ { 0xef1, "Hangul_SunkyeongeumPieub" }, { 0xef2, "Hangul_PanSios" }, { 0xef3, "Hangul_KkogjiDalrinIeung" }, { 0xef4, "Hangul_SunkyeongeumPhieuf" },
+ { 0xef5, "Hangul_YeorinHieuh" }, { 0xef6, "Hangul_AraeA" }, { 0xef7, "Hangul_AraeAE" }, { 0xef8, "Hangul_J_PanSios" },
+ { 0xef9, "Hangul_J_KkogjiDalrinIeung" }, { 0xefa, "Hangul_J_YeorinHieuh" }, { 0xeff, "Korean_Won" }, { 0xFD01, "3270_Duplicate" },
+ { 0xFD02, "3270_FieldMark" }, { 0xFD03, "3270_Right2" }, { 0xFD04, "3270_Left2" }, { 0xFD05, "3270_BackTab" },
+ { 0xFD06, "3270_EraseEOF" }, { 0xFD07, "3270_EraseInput" }, { 0xFD08, "3270_Reset" }, { 0xFD09, "3270_Quit" },
+ { 0xFD0A, "3270_PA1" }, { 0xFD0B, "3270_PA2" }, { 0xFD0C, "3270_PA3" }, { 0xFD0D, "3270_Test" },
+ { 0xFD0E, "3270_Attn" }, { 0xFD0F, "3270_CursorBlink" }, { 0xFD10, "3270_AltCursor" }, { 0xFD11, "3270_KeyClick" },
+ { 0xFD12, "3270_Jump" }, { 0xFD13, "3270_Ident" }, { 0xFD14, "3270_Rule" }, { 0xFD15, "3270_Copy" },
+ { 0xFD16, "3270_Play" }, { 0xFD17, "3270_Setup" }, { 0xFD18, "3270_Record" }, { 0xFD19, "3270_ChangeScreen" },
+ { 0xFD1A, "3270_DeleteWord" }, { 0xFD1B, "3270_ExSelect" }, { 0xFD1C, "3270_CursorSelect" }, { 0xFD1D, "3270_PrintScreen" },
+ { 0xFD1E, "3270_Enter" }, { 0xFE01, "ISO_Lock" }, { 0xFE02, "ISO_Level2_Latch" }, { 0xFE03, "ISO_Level3_Shift" },
+ { 0xFE04, "ISO_Level3_Latch" }, { 0xFE05, "ISO_Level3_Lock" }, { 0xFE06, "ISO_Group_Latch" }, { 0xFE07, "ISO_Group_Lock" },
+ { 0xFE08, "ISO_Next_Group" }, { 0xFE09, "ISO_Next_Group_Lock" }, { 0xFE0A, "ISO_Prev_Group" }, { 0xFE0B, "ISO_Prev_Group_Lock" },
+ { 0xFE0C, "ISO_First_Group" }, { 0xFE0D, "ISO_First_Group_Lock" }, { 0xFE0E, "ISO_Last_Group" }, { 0xFE0F, "ISO_Last_Group_Lock" },
+ { 0xFE20, "ISO_Left_Tab" }, { 0xFE21, "ISO_Move_Line_Up" }, { 0xFE22, "ISO_Move_Line_Down" }, { 0xFE23, "ISO_Partial_Line_Up" },
+ { 0xFE24, "ISO_Partial_Line_Down" }, { 0xFE25, "ISO_Partial_Space_Left" }, { 0xFE26, "ISO_Partial_Space_Right" }, { 0xFE27, "ISO_Set_Margin_Left" },
+ { 0xFE28, "ISO_Set_Margin_Right" }, { 0xFE29, "ISO_Release_Margin_Left" }, { 0xFE2A, "ISO_Release_Margin_Right" }, { 0xFE2B, "ISO_Release_Both_Margins" },
+ { 0xFE2C, "ISO_Fast_Cursor_Left" }, { 0xFE2D, "ISO_Fast_Cursor_Right" }, { 0xFE2E, "ISO_Fast_Cursor_Up" }, { 0xFE2F, "ISO_Fast_Cursor_Down" },
+ { 0xFE30, "ISO_Continuous_Underline" }, { 0xFE31, "ISO_Discontinuous_Underline" }, { 0xFE32, "ISO_Emphasize" }, { 0xFE33, "ISO_Center_Object" },
+ { 0xFE34, "ISO_Enter" }, { 0xFE50, "dead_grave" }, { 0xFE51, "dead_acute" }, { 0xFE52, "dead_circumflex" },
+ { 0xFE53, "dead_tilde" }, { 0xFE54, "dead_macron" }, { 0xFE55, "dead_breve" }, { 0xFE56, "dead_abovedot" },
+ { 0xFE57, "dead_diaeresis" }, { 0xFE58, "dead_abovering" }, { 0xFE59, "dead_doubleacute" }, { 0xFE5A, "dead_caron" },
+ { 0xFE5B, "dead_cedilla" }, { 0xFE5C, "dead_ogonek" }, { 0xFE5D, "dead_iota" }, { 0xFE5E, "dead_voiced_sound" },
+ { 0xFE5F, "dead_semivoiced_sound" }, { 0xFE60, "dead_belowdot" }, { 0xFE70, "AccessX_Enable" }, { 0xFE71, "AccessX_Feedback_Enable" },
+ { 0xFE72, "RepeatKeys_Enable" }, { 0xFE73, "SlowKeys_Enable" }, { 0xFE74, "BounceKeys_Enable" }, { 0xFE75, "StickyKeys_Enable" },
+ { 0xFE76, "MouseKeys_Enable" }, { 0xFE77, "MouseKeys_Accel_Enable" }, { 0xFE78, "Overlay1_Enable" }, { 0xFE79, "Overlay2_Enable" },
+ { 0xFE7A, "AudibleBell_Enable" }, { 0xFED0, "First_Virtual_Screen" }, { 0xFED1, "Prev_Virtual_Screen" }, { 0xFED2, "Next_Virtual_Screen" },
+ { 0xFED4, "Last_Virtual_Screen" }, { 0xFED5, "Terminate_Server" }, { 0xFEE0, "Pointer_Left" }, { 0xFEE1, "Pointer_Right" },
+ { 0xFEE2, "Pointer_Up" }, { 0xFEE3, "Pointer_Down" }, { 0xFEE4, "Pointer_UpLeft" }, { 0xFEE5, "Pointer_UpRight" },
+ { 0xFEE6, "Pointer_DownLeft" }, { 0xFEE7, "Pointer_DownRight" }, { 0xFEE8, "Pointer_Button_Dflt" }, { 0xFEE9, "Pointer_Button1" },
+ { 0xFEEA, "Pointer_Button2" }, { 0xFEEB, "Pointer_Button3" }, { 0xFEEC, "Pointer_Button4" }, { 0xFEED, "Pointer_Button5" },
+ { 0xFEEE, "Pointer_DblClick_Dflt" }, { 0xFEEF, "Pointer_DblClick1" }, { 0xFEF0, "Pointer_DblClick2" }, { 0xFEF1, "Pointer_DblClick3" },
+ { 0xFEF2, "Pointer_DblClick4" }, { 0xFEF3, "Pointer_DblClick5" }, { 0xFEF4, "Pointer_Drag_Dflt" }, { 0xFEF5, "Pointer_Drag1" },
+ { 0xFEF6, "Pointer_Drag2" }, { 0xFEF7, "Pointer_Drag3" }, { 0xFEF8, "Pointer_Drag4" }, { 0xFEF9, "Pointer_EnableKeys" },
+ { 0xFEFA, "Pointer_Accelerate" }, { 0xFEFB, "Pointer_DfltBtnNext" }, { 0xFEFC, "Pointer_DfltBtnPrev" }, { 0xFEFD, "Pointer_Drag5" },
+ { 0xFF08, "BackSpace" }, { 0xFF09, "Tab" }, { 0xFF0A, "Linefeed" }, { 0xFF0B, "Clear" },
+ { 0xFF0D, "Return" }, { 0xFF13, "Pause" }, { 0xFF14, "Scroll_Lock" }, { 0xFF15, "Sys_Req" },
+ { 0xFF1B, "Escape" }, { 0xFF20, "Multi_key" }, { 0xFF21, "Kanji" }, { 0xFF22, "Muhenkan" },
+ { 0xFF23, "Henkan" }, { 0xFF23, "Henkan_Mode" }, { 0xFF24, "Romaji" }, { 0xFF25, "Hiragana" },
+ { 0xFF26, "Katakana" }, { 0xFF27, "Hiragana_Katakana" }, { 0xFF28, "Zenkaku" }, { 0xFF29, "Hankaku" },
+ { 0xFF2A, "Zenkaku_Hankaku" }, { 0xFF2B, "Touroku" }, { 0xFF2C, "Massyo" }, { 0xFF2D, "Kana_Lock" },
+ { 0xFF2E, "Kana_Shift" }, { 0xFF2F, "Eisu_Shift" }, { 0xFF30, "Eisu_toggle" }, { 0xff31, "Hangul" },
+ { 0xff32, "Hangul_Start" }, { 0xff33, "Hangul_End" }, { 0xff34, "Hangul_Hanja" }, { 0xff35, "Hangul_Jamo" },
+ { 0xff36, "Hangul_Romaja" }, { 0xFF37, "Codeinput" }, { 0xff37, "Hangul_Codeinput" }, { 0xFF37, "Kanji_Bangou" },
+ { 0xff38, "Hangul_Jeonja" }, { 0xff39, "Hangul_Banja" }, { 0xff3a, "Hangul_PreHanja" }, { 0xff3b, "Hangul_PostHanja" },
+ { 0xff3c, "Hangul_SingleCandidate" }, { 0xFF3C, "SingleCandidate" }, { 0xff3d, "Hangul_MultipleCandidate" }, { 0xFF3D, "MultipleCandidate" },
+ { 0xFF3D, "Zen_Koho" }, { 0xff3e, "Hangul_PreviousCandidate" }, { 0xFF3E, "Mae_Koho" }, { 0xFF3E, "PreviousCandidate" },
+ { 0xff3f, "Hangul_Special" }, { 0xFF50, "Home" }, { 0xFF51, "Left" }, { 0xFF52, "Up" },
+ { 0xFF53, "Right" }, { 0xFF54, "Down" }, { 0xFF55, "Page_Up" }, { 0xFF55, "Prior" },
+ { 0xFF56, "Next" }, { 0xFF56, "Page_Down" }, { 0xFF57, "End" }, { 0xFF58, "Begin" },
+ { 0xFF60, "Select" }, { 0xFF61, "Print" }, { 0xFF62, "Execute" }, { 0xFF63, "Insert" },
+ { 0xFF65, "Undo" }, { 0xFF66, "Redo" }, { 0xFF67, "Menu" }, { 0xFF68, "Find" },
+ { 0xFF69, "Cancel" }, { 0xFF6A, "Help" }, { 0xFF6B, "Break" }, { 0xFF7E, "Arabic_switch" },
+ { 0xFF7E, "Greek_switch" }, { 0xFF7E, "Hangul_switch" }, { 0xFF7E, "Hebrew_switch" }, { 0xFF7E, "ISO_Group_Shift" },
+ { 0xFF7E, "kana_switch" }, { 0xFF7E, "Mode_switch" }, { 0xFF7E, "script_switch" }, { 0xFF7F, "Num_Lock" },
+ { 0xFF80, "KP_Space" }, { 0xFF89, "KP_Tab" }, { 0xFF8D, "KP_Enter" }, { 0xFF91, "KP_F1" },
+ { 0xFF92, "KP_F2" }, { 0xFF93, "KP_F3" }, { 0xFF94, "KP_F4" }, { 0xFF95, "KP_Home" },
+ { 0xFF96, "KP_Left" }, { 0xFF97, "KP_Up" }, { 0xFF98, "KP_Right" }, { 0xFF99, "KP_Down" },
+ { 0xFF9A, "KP_Page_Up" }, { 0xFF9A, "KP_Prior" }, { 0xFF9B, "KP_Next" }, { 0xFF9B, "KP_Page_Down" },
+ { 0xFF9C, "KP_End" }, { 0xFF9D, "KP_Begin" }, { 0xFF9E, "KP_Insert" }, { 0xFF9F, "KP_Delete" },
+ { 0xFFAA, "KP_Multiply" }, { 0xFFAB, "KP_Add" }, { 0xFFAC, "KP_Separator" }, { 0xFFAD, "KP_Subtract" },
+ { 0xFFAE, "KP_Decimal" }, { 0xFFAF, "KP_Divide" }, { 0xFFB0, "KP_0" }, { 0xFFB1, "KP_1" },
+ { 0xFFB2, "KP_2" }, { 0xFFB3, "KP_3" }, { 0xFFB4, "KP_4" }, { 0xFFB5, "KP_5" },
+ { 0xFFB6, "KP_6" }, { 0xFFB7, "KP_7" }, { 0xFFB8, "KP_8" }, { 0xFFB9, "KP_9" },
+ { 0xFFBD, "KP_Equal" }, { 0xFFBE, "F1" }, { 0xFFBF, "F2" }, { 0xFFC0, "F3" },
+ { 0xFFC1, "F4" }, { 0xFFC2, "F5" }, { 0xFFC3, "F6" }, { 0xFFC4, "F7" },
+ { 0xFFC5, "F8" }, { 0xFFC6, "F9" }, { 0xFFC7, "F10" }, { 0xFFC8, "F11" },
+ { 0xFFC8, "L1" }, { 0xFFC9, "F12" }, { 0xFFC9, "L2" }, { 0xFFCA, "F13" },
+ { 0xFFCA, "L3" }, { 0xFFCB, "F14" }, { 0xFFCB, "L4" }, { 0xFFCC, "F15" },
+ { 0xFFCC, "L5" }, { 0xFFCD, "F16" }, { 0xFFCD, "L6" }, { 0xFFCE, "F17" },
+ { 0xFFCE, "L7" }, { 0xFFCF, "F18" }, { 0xFFCF, "L8" }, { 0xFFD0, "F19" },
+ { 0xFFD0, "L9" }, { 0xFFD1, "F20" }, { 0xFFD1, "L10" }, { 0xFFD2, "F21" },
+ { 0xFFD2, "R1" }, { 0xFFD3, "F22" }, { 0xFFD3, "R2" }, { 0xFFD4, "F23" },
+ { 0xFFD4, "R3" }, { 0xFFD5, "F24" }, { 0xFFD5, "R4" }, { 0xFFD6, "F25" },
+ { 0xFFD6, "R5" }, { 0xFFD7, "F26" }, { 0xFFD7, "R6" }, { 0xFFD8, "F27" },
+ { 0xFFD8, "R7" }, { 0xFFD9, "F28" }, { 0xFFD9, "R8" }, { 0xFFDA, "F29" },
+ { 0xFFDA, "R9" }, { 0xFFDB, "F30" }, { 0xFFDB, "R10" }, { 0xFFDC, "F31" },
+ { 0xFFDC, "R11" }, { 0xFFDD, "F32" }, { 0xFFDD, "R12" }, { 0xFFDE, "F33" },
+ { 0xFFDE, "R13" }, { 0xFFDF, "F34" }, { 0xFFDF, "R14" }, { 0xFFE0, "F35" },
+ { 0xFFE0, "R15" }, { 0xFFE1, "Shift_L" }, { 0xFFE2, "Shift_R" }, { 0xFFE3, "Control_L" },
+ { 0xFFE4, "Control_R" }, { 0xFFE5, "Caps_Lock" }, { 0xFFE6, "Shift_Lock" }, { 0xFFE7, "Meta_L" },
+ { 0xFFE8, "Meta_R" }, { 0xFFE9, "Alt_L" }, { 0xFFEA, "Alt_R" }, { 0xFFEB, "Super_L" },
+ { 0xFFEC, "Super_R" }, { 0xFFED, "Hyper_L" }, { 0xFFEE, "Hyper_R" }, { 0xFFFF, "Delete" },
+ { 0xFFFFFF, "VoidSymbol" }, { 0, NULL }
+};
+
+#endif
diff --git a/epan/dissectors/packet-x11-keysymdef.h b/epan/dissectors/packet-x11-keysymdef.h
new file mode 100644
index 0000000000..c1e263e273
--- /dev/null
+++ b/epan/dissectors/packet-x11-keysymdef.h
@@ -0,0 +1,2063 @@
+/* packet-x11-keysymdef.h
+ * Key symbol definitions for X11 (XFree86 distribution: keysymdef.h)
+ * Copyright holders: Digital, The Open Group
+ * (see below for their copyright statement)
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* $TOG: keysymdef.h /main/28 1998/05/22 16:18:01 kaleb $ */
+
+/***********************************************************
+Copyright 1987, 1994, 1998 The Open Group
+
+All Rights Reserved.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+/* $XFree86: xc/include/keysymdef.h,v 1.10 2000/10/27 18:30:46 dawes Exp $ */
+
+#define XK_VoidSymbol 0xFFFFFF /* void symbol */
+
+#define XK_MISCELLANY
+#ifdef XK_MISCELLANY
+/*
+ * TTY Functions, cleverly chosen to map to ascii, for convenience of
+ * programming, but could have been arbitrary (at the cost of lookup
+ * tables in client code.
+ */
+
+#define XK_BackSpace 0xFF08 /* back space, back char */
+#define XK_Tab 0xFF09
+#define XK_Linefeed 0xFF0A /* Linefeed, LF */
+#define XK_Clear 0xFF0B
+#define XK_Return 0xFF0D /* Return, enter */
+#define XK_Pause 0xFF13 /* Pause, hold */
+#define XK_Scroll_Lock 0xFF14
+#define XK_Sys_Req 0xFF15
+#define XK_Escape 0xFF1B
+#define XK_Delete 0xFFFF /* Delete, rubout */
+
+
+
+/* International & multi-key character composition */
+
+#define XK_Multi_key 0xFF20 /* Multi-key character compose */
+#define XK_Codeinput 0xFF37
+#define XK_SingleCandidate 0xFF3C
+#define XK_MultipleCandidate 0xFF3D
+#define XK_PreviousCandidate 0xFF3E
+
+/* Japanese keyboard support */
+
+#define XK_Kanji 0xFF21 /* Kanji, Kanji convert */
+#define XK_Muhenkan 0xFF22 /* Cancel Conversion */
+#define XK_Henkan_Mode 0xFF23 /* Start/Stop Conversion */
+#define XK_Henkan 0xFF23 /* Alias for Henkan_Mode */
+#define XK_Romaji 0xFF24 /* to Romaji */
+#define XK_Hiragana 0xFF25 /* to Hiragana */
+#define XK_Katakana 0xFF26 /* to Katakana */
+#define XK_Hiragana_Katakana 0xFF27 /* Hiragana/Katakana toggle */
+#define XK_Zenkaku 0xFF28 /* to Zenkaku */
+#define XK_Hankaku 0xFF29 /* to Hankaku */
+#define XK_Zenkaku_Hankaku 0xFF2A /* Zenkaku/Hankaku toggle */
+#define XK_Touroku 0xFF2B /* Add to Dictionary */
+#define XK_Massyo 0xFF2C /* Delete from Dictionary */
+#define XK_Kana_Lock 0xFF2D /* Kana Lock */
+#define XK_Kana_Shift 0xFF2E /* Kana Shift */
+#define XK_Eisu_Shift 0xFF2F /* Alphanumeric Shift */
+#define XK_Eisu_toggle 0xFF30 /* Alphanumeric toggle */
+#define XK_Kanji_Bangou 0xFF37 /* Codeinput */
+#define XK_Zen_Koho 0xFF3D /* Multiple/All Candidate(s) */
+#define XK_Mae_Koho 0xFF3E /* Previous Candidate */
+
+/* 0xFF31 thru 0xFF3F are under XK_KOREAN */
+
+/* Cursor control & motion */
+
+#define XK_Home 0xFF50
+#define XK_Left 0xFF51 /* Move left, left arrow */
+#define XK_Up 0xFF52 /* Move up, up arrow */
+#define XK_Right 0xFF53 /* Move right, right arrow */
+#define XK_Down 0xFF54 /* Move down, down arrow */
+#define XK_Prior 0xFF55 /* Prior, previous */
+#define XK_Page_Up 0xFF55
+#define XK_Next 0xFF56 /* Next */
+#define XK_Page_Down 0xFF56
+#define XK_End 0xFF57 /* EOL */
+#define XK_Begin 0xFF58 /* BOL */
+
+
+/* Misc Functions */
+
+#define XK_Select 0xFF60 /* Select, mark */
+#define XK_Print 0xFF61
+#define XK_Execute 0xFF62 /* Execute, run, do */
+#define XK_Insert 0xFF63 /* Insert, insert here */
+#define XK_Undo 0xFF65 /* Undo, oops */
+#define XK_Redo 0xFF66 /* redo, again */
+#define XK_Menu 0xFF67
+#define XK_Find 0xFF68 /* Find, search */
+#define XK_Cancel 0xFF69 /* Cancel, stop, abort, exit */
+#define XK_Help 0xFF6A /* Help */
+#define XK_Break 0xFF6B
+#define XK_Mode_switch 0xFF7E /* Character set switch */
+#define XK_script_switch 0xFF7E /* Alias for mode_switch */
+#define XK_Num_Lock 0xFF7F
+
+/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
+
+#define XK_KP_Space 0xFF80 /* space */
+#define XK_KP_Tab 0xFF89
+#define XK_KP_Enter 0xFF8D /* enter */
+#define XK_KP_F1 0xFF91 /* PF1, KP_A, ... */
+#define XK_KP_F2 0xFF92
+#define XK_KP_F3 0xFF93
+#define XK_KP_F4 0xFF94
+#define XK_KP_Home 0xFF95
+#define XK_KP_Left 0xFF96
+#define XK_KP_Up 0xFF97
+#define XK_KP_Right 0xFF98
+#define XK_KP_Down 0xFF99
+#define XK_KP_Prior 0xFF9A
+#define XK_KP_Page_Up 0xFF9A
+#define XK_KP_Next 0xFF9B
+#define XK_KP_Page_Down 0xFF9B
+#define XK_KP_End 0xFF9C
+#define XK_KP_Begin 0xFF9D
+#define XK_KP_Insert 0xFF9E
+#define XK_KP_Delete 0xFF9F
+#define XK_KP_Equal 0xFFBD /* equals */
+#define XK_KP_Multiply 0xFFAA
+#define XK_KP_Add 0xFFAB
+#define XK_KP_Separator 0xFFAC /* separator, often comma */
+#define XK_KP_Subtract 0xFFAD
+#define XK_KP_Decimal 0xFFAE
+#define XK_KP_Divide 0xFFAF
+
+#define XK_KP_0 0xFFB0
+#define XK_KP_1 0xFFB1
+#define XK_KP_2 0xFFB2
+#define XK_KP_3 0xFFB3
+#define XK_KP_4 0xFFB4
+#define XK_KP_5 0xFFB5
+#define XK_KP_6 0xFFB6
+#define XK_KP_7 0xFFB7
+#define XK_KP_8 0xFFB8
+#define XK_KP_9 0xFFB9
+
+
+
+/*
+ * Auxilliary Functions; note the duplicate definitions for left and right
+ * function keys; Sun keyboards and a few other manufactures have such
+ * function key groups on the left and/or right sides of the keyboard.
+ * We've not found a keyboard with more than 35 function keys total.
+ */
+
+#define XK_F1 0xFFBE
+#define XK_F2 0xFFBF
+#define XK_F3 0xFFC0
+#define XK_F4 0xFFC1
+#define XK_F5 0xFFC2
+#define XK_F6 0xFFC3
+#define XK_F7 0xFFC4
+#define XK_F8 0xFFC5
+#define XK_F9 0xFFC6
+#define XK_F10 0xFFC7
+#define XK_F11 0xFFC8
+#define XK_L1 0xFFC8
+#define XK_F12 0xFFC9
+#define XK_L2 0xFFC9
+#define XK_F13 0xFFCA
+#define XK_L3 0xFFCA
+#define XK_F14 0xFFCB
+#define XK_L4 0xFFCB
+#define XK_F15 0xFFCC
+#define XK_L5 0xFFCC
+#define XK_F16 0xFFCD
+#define XK_L6 0xFFCD
+#define XK_F17 0xFFCE
+#define XK_L7 0xFFCE
+#define XK_F18 0xFFCF
+#define XK_L8 0xFFCF
+#define XK_F19 0xFFD0
+#define XK_L9 0xFFD0
+#define XK_F20 0xFFD1
+#define XK_L10 0xFFD1
+#define XK_F21 0xFFD2
+#define XK_R1 0xFFD2
+#define XK_F22 0xFFD3
+#define XK_R2 0xFFD3
+#define XK_F23 0xFFD4
+#define XK_R3 0xFFD4
+#define XK_F24 0xFFD5
+#define XK_R4 0xFFD5
+#define XK_F25 0xFFD6
+#define XK_R5 0xFFD6
+#define XK_F26 0xFFD7
+#define XK_R6 0xFFD7
+#define XK_F27 0xFFD8
+#define XK_R7 0xFFD8
+#define XK_F28 0xFFD9
+#define XK_R8 0xFFD9
+#define XK_F29 0xFFDA
+#define XK_R9 0xFFDA
+#define XK_F30 0xFFDB
+#define XK_R10 0xFFDB
+#define XK_F31 0xFFDC
+#define XK_R11 0xFFDC
+#define XK_F32 0xFFDD
+#define XK_R12 0xFFDD
+#define XK_F33 0xFFDE
+#define XK_R13 0xFFDE
+#define XK_F34 0xFFDF
+#define XK_R14 0xFFDF
+#define XK_F35 0xFFE0
+#define XK_R15 0xFFE0
+
+/* Modifiers */
+
+#define XK_Shift_L 0xFFE1 /* Left shift */
+#define XK_Shift_R 0xFFE2 /* Right shift */
+#define XK_Control_L 0xFFE3 /* Left control */
+#define XK_Control_R 0xFFE4 /* Right control */
+#define XK_Caps_Lock 0xFFE5 /* Caps lock */
+#define XK_Shift_Lock 0xFFE6 /* Shift lock */
+
+#define XK_Meta_L 0xFFE7 /* Left meta */
+#define XK_Meta_R 0xFFE8 /* Right meta */
+#define XK_Alt_L 0xFFE9 /* Left alt */
+#define XK_Alt_R 0xFFEA /* Right alt */
+#define XK_Super_L 0xFFEB /* Left super */
+#define XK_Super_R 0xFFEC /* Right super */
+#define XK_Hyper_L 0xFFED /* Left hyper */
+#define XK_Hyper_R 0xFFEE /* Right hyper */
+#endif /* XK_MISCELLANY */
+
+/*
+ * ISO 9995 Function and Modifier Keys
+ * Byte 3 = 0xFE
+ */
+
+#define XK_XKB_KEYS
+#ifdef XK_XKB_KEYS
+#define XK_ISO_Lock 0xFE01
+#define XK_ISO_Level2_Latch 0xFE02
+#define XK_ISO_Level3_Shift 0xFE03
+#define XK_ISO_Level3_Latch 0xFE04
+#define XK_ISO_Level3_Lock 0xFE05
+#define XK_ISO_Group_Shift 0xFF7E /* Alias for mode_switch */
+#define XK_ISO_Group_Latch 0xFE06
+#define XK_ISO_Group_Lock 0xFE07
+#define XK_ISO_Next_Group 0xFE08
+#define XK_ISO_Next_Group_Lock 0xFE09
+#define XK_ISO_Prev_Group 0xFE0A
+#define XK_ISO_Prev_Group_Lock 0xFE0B
+#define XK_ISO_First_Group 0xFE0C
+#define XK_ISO_First_Group_Lock 0xFE0D
+#define XK_ISO_Last_Group 0xFE0E
+#define XK_ISO_Last_Group_Lock 0xFE0F
+
+#define XK_ISO_Left_Tab 0xFE20
+#define XK_ISO_Move_Line_Up 0xFE21
+#define XK_ISO_Move_Line_Down 0xFE22
+#define XK_ISO_Partial_Line_Up 0xFE23
+#define XK_ISO_Partial_Line_Down 0xFE24
+#define XK_ISO_Partial_Space_Left 0xFE25
+#define XK_ISO_Partial_Space_Right 0xFE26
+#define XK_ISO_Set_Margin_Left 0xFE27
+#define XK_ISO_Set_Margin_Right 0xFE28
+#define XK_ISO_Release_Margin_Left 0xFE29
+#define XK_ISO_Release_Margin_Right 0xFE2A
+#define XK_ISO_Release_Both_Margins 0xFE2B
+#define XK_ISO_Fast_Cursor_Left 0xFE2C
+#define XK_ISO_Fast_Cursor_Right 0xFE2D
+#define XK_ISO_Fast_Cursor_Up 0xFE2E
+#define XK_ISO_Fast_Cursor_Down 0xFE2F
+#define XK_ISO_Continuous_Underline 0xFE30
+#define XK_ISO_Discontinuous_Underline 0xFE31
+#define XK_ISO_Emphasize 0xFE32
+#define XK_ISO_Center_Object 0xFE33
+#define XK_ISO_Enter 0xFE34
+
+#define XK_dead_grave 0xFE50
+#define XK_dead_acute 0xFE51
+#define XK_dead_circumflex 0xFE52
+#define XK_dead_tilde 0xFE53
+#define XK_dead_macron 0xFE54
+#define XK_dead_breve 0xFE55
+#define XK_dead_abovedot 0xFE56
+#define XK_dead_diaeresis 0xFE57
+#define XK_dead_abovering 0xFE58
+#define XK_dead_doubleacute 0xFE59
+#define XK_dead_caron 0xFE5A
+#define XK_dead_cedilla 0xFE5B
+#define XK_dead_ogonek 0xFE5C
+#define XK_dead_iota 0xFE5D
+#define XK_dead_voiced_sound 0xFE5E
+#define XK_dead_semivoiced_sound 0xFE5F
+#define XK_dead_belowdot 0xFE60
+#define XK_dead_hook 0xFE61
+#define XK_dead_horn 0xFE62
+
+#define XK_First_Virtual_Screen 0xFED0
+#define XK_Prev_Virtual_Screen 0xFED1
+#define XK_Next_Virtual_Screen 0xFED2
+#define XK_Last_Virtual_Screen 0xFED4
+#define XK_Terminate_Server 0xFED5
+
+#define XK_AccessX_Enable 0xFE70
+#define XK_AccessX_Feedback_Enable 0xFE71
+#define XK_RepeatKeys_Enable 0xFE72
+#define XK_SlowKeys_Enable 0xFE73
+#define XK_BounceKeys_Enable 0xFE74
+#define XK_StickyKeys_Enable 0xFE75
+#define XK_MouseKeys_Enable 0xFE76
+#define XK_MouseKeys_Accel_Enable 0xFE77
+#define XK_Overlay1_Enable 0xFE78
+#define XK_Overlay2_Enable 0xFE79
+#define XK_AudibleBell_Enable 0xFE7A
+
+#define XK_Pointer_Left 0xFEE0
+#define XK_Pointer_Right 0xFEE1
+#define XK_Pointer_Up 0xFEE2
+#define XK_Pointer_Down 0xFEE3
+#define XK_Pointer_UpLeft 0xFEE4
+#define XK_Pointer_UpRight 0xFEE5
+#define XK_Pointer_DownLeft 0xFEE6
+#define XK_Pointer_DownRight 0xFEE7
+#define XK_Pointer_Button_Dflt 0xFEE8
+#define XK_Pointer_Button1 0xFEE9
+#define XK_Pointer_Button2 0xFEEA
+#define XK_Pointer_Button3 0xFEEB
+#define XK_Pointer_Button4 0xFEEC
+#define XK_Pointer_Button5 0xFEED
+#define XK_Pointer_DblClick_Dflt 0xFEEE
+#define XK_Pointer_DblClick1 0xFEEF
+#define XK_Pointer_DblClick2 0xFEF0
+#define XK_Pointer_DblClick3 0xFEF1
+#define XK_Pointer_DblClick4 0xFEF2
+#define XK_Pointer_DblClick5 0xFEF3
+#define XK_Pointer_Drag_Dflt 0xFEF4
+#define XK_Pointer_Drag1 0xFEF5
+#define XK_Pointer_Drag2 0xFEF6
+#define XK_Pointer_Drag3 0xFEF7
+#define XK_Pointer_Drag4 0xFEF8
+#define XK_Pointer_Drag5 0xFEFD
+
+#define XK_Pointer_EnableKeys 0xFEF9
+#define XK_Pointer_Accelerate 0xFEFA
+#define XK_Pointer_DfltBtnNext 0xFEFB
+#define XK_Pointer_DfltBtnPrev 0xFEFC
+
+#endif
+
+/*
+ * 3270 Terminal Keys
+ * Byte 3 = 0xFD
+ */
+
+#define XK_3270
+#ifdef XK_3270
+#define XK_3270_Duplicate 0xFD01
+#define XK_3270_FieldMark 0xFD02
+#define XK_3270_Right2 0xFD03
+#define XK_3270_Left2 0xFD04
+#define XK_3270_BackTab 0xFD05
+#define XK_3270_EraseEOF 0xFD06
+#define XK_3270_EraseInput 0xFD07
+#define XK_3270_Reset 0xFD08
+#define XK_3270_Quit 0xFD09
+#define XK_3270_PA1 0xFD0A
+#define XK_3270_PA2 0xFD0B
+#define XK_3270_PA3 0xFD0C
+#define XK_3270_Test 0xFD0D
+#define XK_3270_Attn 0xFD0E
+#define XK_3270_CursorBlink 0xFD0F
+#define XK_3270_AltCursor 0xFD10
+#define XK_3270_KeyClick 0xFD11
+#define XK_3270_Jump 0xFD12
+#define XK_3270_Ident 0xFD13
+#define XK_3270_Rule 0xFD14
+#define XK_3270_Copy 0xFD15
+#define XK_3270_Play 0xFD16
+#define XK_3270_Setup 0xFD17
+#define XK_3270_Record 0xFD18
+#define XK_3270_ChangeScreen 0xFD19
+#define XK_3270_DeleteWord 0xFD1A
+#define XK_3270_ExSelect 0xFD1B
+#define XK_3270_CursorSelect 0xFD1C
+#define XK_3270_PrintScreen 0xFD1D
+#define XK_3270_Enter 0xFD1E
+#endif
+
+/*
+ * Latin 1
+ * Byte 3 = 0
+ */
+#define XK_LATIN1
+#ifdef XK_LATIN1
+#define XK_space 0x020
+#define XK_exclam 0x021
+#define XK_quotedbl 0x022
+#define XK_numbersign 0x023
+#define XK_dollar 0x024
+#define XK_percent 0x025
+#define XK_ampersand 0x026
+#define XK_apostrophe 0x027
+#define XK_quoteright 0x027 /* deprecated */
+#define XK_parenleft 0x028
+#define XK_parenright 0x029
+#define XK_asterisk 0x02a
+#define XK_plus 0x02b
+#define XK_comma 0x02c
+#define XK_minus 0x02d
+#define XK_period 0x02e
+#define XK_slash 0x02f
+#define XK_0 0x030
+#define XK_1 0x031
+#define XK_2 0x032
+#define XK_3 0x033
+#define XK_4 0x034
+#define XK_5 0x035
+#define XK_6 0x036
+#define XK_7 0x037
+#define XK_8 0x038
+#define XK_9 0x039
+#define XK_colon 0x03a
+#define XK_semicolon 0x03b
+#define XK_less 0x03c
+#define XK_equal 0x03d
+#define XK_greater 0x03e
+#define XK_question 0x03f
+#define XK_at 0x040
+#define XK_A 0x041
+#define XK_B 0x042
+#define XK_C 0x043
+#define XK_D 0x044
+#define XK_E 0x045
+#define XK_F 0x046
+#define XK_G 0x047
+#define XK_H 0x048
+#define XK_I 0x049
+#define XK_J 0x04a
+#define XK_K 0x04b
+#define XK_L 0x04c
+#define XK_M 0x04d
+#define XK_N 0x04e
+#define XK_O 0x04f
+#define XK_P 0x050
+#define XK_Q 0x051
+#define XK_R 0x052
+#define XK_S 0x053
+#define XK_T 0x054
+#define XK_U 0x055
+#define XK_V 0x056
+#define XK_W 0x057
+#define XK_X 0x058
+#define XK_Y 0x059
+#define XK_Z 0x05a
+#define XK_bracketleft 0x05b
+#define XK_backslash 0x05c
+#define XK_bracketright 0x05d
+#define XK_asciicircum 0x05e
+#define XK_underscore 0x05f
+#define XK_grave 0x060
+#define XK_quoteleft 0x060 /* deprecated */
+#define XK_a 0x061
+#define XK_b 0x062
+#define XK_c 0x063
+#define XK_d 0x064
+#define XK_e 0x065
+#define XK_f 0x066
+#define XK_g 0x067
+#define XK_h 0x068
+#define XK_i 0x069
+#define XK_j 0x06a
+#define XK_k 0x06b
+#define XK_l 0x06c
+#define XK_m 0x06d
+#define XK_n 0x06e
+#define XK_o 0x06f
+#define XK_p 0x070
+#define XK_q 0x071
+#define XK_r 0x072
+#define XK_s 0x073
+#define XK_t 0x074
+#define XK_u 0x075
+#define XK_v 0x076
+#define XK_w 0x077
+#define XK_x 0x078
+#define XK_y 0x079
+#define XK_z 0x07a
+#define XK_braceleft 0x07b
+#define XK_bar 0x07c
+#define XK_braceright 0x07d
+#define XK_asciitilde 0x07e
+
+#define XK_nobreakspace 0x0a0
+#define XK_exclamdown 0x0a1
+#define XK_cent 0x0a2
+#define XK_sterling 0x0a3
+#define XK_currency 0x0a4
+#define XK_yen 0x0a5
+#define XK_brokenbar 0x0a6
+#define XK_section 0x0a7
+#define XK_diaeresis 0x0a8
+#define XK_copyright 0x0a9
+#define XK_ordfeminine 0x0aa
+#define XK_guillemotleft 0x0ab /* left angle quotation mark */
+#define XK_notsign 0x0ac
+#define XK_hyphen 0x0ad
+#define XK_registered 0x0ae
+#define XK_macron 0x0af
+#define XK_degree 0x0b0
+#define XK_plusminus 0x0b1
+#define XK_twosuperior 0x0b2
+#define XK_threesuperior 0x0b3
+#define XK_acute 0x0b4
+#define XK_mu 0x0b5
+#define XK_paragraph 0x0b6
+#define XK_periodcentered 0x0b7
+#define XK_cedilla 0x0b8
+#define XK_onesuperior 0x0b9
+#define XK_masculine 0x0ba
+#define XK_guillemotright 0x0bb /* right angle quotation mark */
+#define XK_onequarter 0x0bc
+#define XK_onehalf 0x0bd
+#define XK_threequarters 0x0be
+#define XK_questiondown 0x0bf
+#define XK_Agrave 0x0c0
+#define XK_Aacute 0x0c1
+#define XK_Acircumflex 0x0c2
+#define XK_Atilde 0x0c3
+#define XK_Adiaeresis 0x0c4
+#define XK_Aring 0x0c5
+#define XK_AE 0x0c6
+#define XK_Ccedilla 0x0c7
+#define XK_Egrave 0x0c8
+#define XK_Eacute 0x0c9
+#define XK_Ecircumflex 0x0ca
+#define XK_Ediaeresis 0x0cb
+#define XK_Igrave 0x0cc
+#define XK_Iacute 0x0cd
+#define XK_Icircumflex 0x0ce
+#define XK_Idiaeresis 0x0cf
+#define XK_ETH 0x0d0
+#define XK_Eth 0x0d0 /* deprecated */
+#define XK_Ntilde 0x0d1
+#define XK_Ograve 0x0d2
+#define XK_Oacute 0x0d3
+#define XK_Ocircumflex 0x0d4
+#define XK_Otilde 0x0d5
+#define XK_Odiaeresis 0x0d6
+#define XK_multiply 0x0d7
+#define XK_Ooblique 0x0d8
+#define XK_Oslash XK_Ooblique
+#define XK_Ugrave 0x0d9
+#define XK_Uacute 0x0da
+#define XK_Ucircumflex 0x0db
+#define XK_Udiaeresis 0x0dc
+#define XK_Yacute 0x0dd
+#define XK_THORN 0x0de
+#define XK_Thorn 0x0de /* deprecated */
+#define XK_ssharp 0x0df
+#define XK_agrave 0x0e0
+#define XK_aacute 0x0e1
+#define XK_acircumflex 0x0e2
+#define XK_atilde 0x0e3
+#define XK_adiaeresis 0x0e4
+#define XK_aring 0x0e5
+#define XK_ae 0x0e6
+#define XK_ccedilla 0x0e7
+#define XK_egrave 0x0e8
+#define XK_eacute 0x0e9
+#define XK_ecircumflex 0x0ea
+#define XK_ediaeresis 0x0eb
+#define XK_igrave 0x0ec
+#define XK_iacute 0x0ed
+#define XK_icircumflex 0x0ee
+#define XK_idiaeresis 0x0ef
+#define XK_eth 0x0f0
+#define XK_ntilde 0x0f1
+#define XK_ograve 0x0f2
+#define XK_oacute 0x0f3
+#define XK_ocircumflex 0x0f4
+#define XK_otilde 0x0f5
+#define XK_odiaeresis 0x0f6
+#define XK_division 0x0f7
+#define XK_oslash 0x0f8
+#define XK_ooblique XK_oslash
+#define XK_ugrave 0x0f9
+#define XK_uacute 0x0fa
+#define XK_ucircumflex 0x0fb
+#define XK_udiaeresis 0x0fc
+#define XK_yacute 0x0fd
+#define XK_thorn 0x0fe
+#define XK_ydiaeresis 0x0ff
+#endif /* XK_LATIN1 */
+
+/*
+ * Latin 2
+ * Byte 3 = 1
+ */
+
+#define XK_LATIN2
+#ifdef XK_LATIN2
+#define XK_Aogonek 0x1a1
+#define XK_breve 0x1a2
+#define XK_Lstroke 0x1a3
+#define XK_Lcaron 0x1a5
+#define XK_Sacute 0x1a6
+#define XK_Scaron 0x1a9
+#define XK_Scedilla 0x1aa
+#define XK_Tcaron 0x1ab
+#define XK_Zacute 0x1ac
+#define XK_Zcaron 0x1ae
+#define XK_Zabovedot 0x1af
+#define XK_aogonek 0x1b1
+#define XK_ogonek 0x1b2
+#define XK_lstroke 0x1b3
+#define XK_lcaron 0x1b5
+#define XK_sacute 0x1b6
+#define XK_caron 0x1b7
+#define XK_scaron 0x1b9
+#define XK_scedilla 0x1ba
+#define XK_tcaron 0x1bb
+#define XK_zacute 0x1bc
+#define XK_doubleacute 0x1bd
+#define XK_zcaron 0x1be
+#define XK_zabovedot 0x1bf
+#define XK_Racute 0x1c0
+#define XK_Abreve 0x1c3
+#define XK_Lacute 0x1c5
+#define XK_Cacute 0x1c6
+#define XK_Ccaron 0x1c8
+#define XK_Eogonek 0x1ca
+#define XK_Ecaron 0x1cc
+#define XK_Dcaron 0x1cf
+#define XK_Dstroke 0x1d0
+#define XK_Nacute 0x1d1
+#define XK_Ncaron 0x1d2
+#define XK_Odoubleacute 0x1d5
+#define XK_Rcaron 0x1d8
+#define XK_Uring 0x1d9
+#define XK_Udoubleacute 0x1db
+#define XK_Tcedilla 0x1de
+#define XK_racute 0x1e0
+#define XK_abreve 0x1e3
+#define XK_lacute 0x1e5
+#define XK_cacute 0x1e6
+#define XK_ccaron 0x1e8
+#define XK_eogonek 0x1ea
+#define XK_ecaron 0x1ec
+#define XK_dcaron 0x1ef
+#define XK_dstroke 0x1f0
+#define XK_nacute 0x1f1
+#define XK_ncaron 0x1f2
+#define XK_odoubleacute 0x1f5
+#define XK_udoubleacute 0x1fb
+#define XK_rcaron 0x1f8
+#define XK_uring 0x1f9
+#define XK_tcedilla 0x1fe
+#define XK_abovedot 0x1ff
+#endif /* XK_LATIN2 */
+
+/*
+ * Latin 3
+ * Byte 3 = 2
+ */
+
+#define XK_LATIN3
+#ifdef XK_LATIN3
+#define XK_Hstroke 0x2a1
+#define XK_Hcircumflex 0x2a6
+#define XK_Iabovedot 0x2a9
+#define XK_Gbreve 0x2ab
+#define XK_Jcircumflex 0x2ac
+#define XK_hstroke 0x2b1
+#define XK_hcircumflex 0x2b6
+#define XK_idotless 0x2b9
+#define XK_gbreve 0x2bb
+#define XK_jcircumflex 0x2bc
+#define XK_Cabovedot 0x2c5
+#define XK_Ccircumflex 0x2c6
+#define XK_Gabovedot 0x2d5
+#define XK_Gcircumflex 0x2d8
+#define XK_Ubreve 0x2dd
+#define XK_Scircumflex 0x2de
+#define XK_cabovedot 0x2e5
+#define XK_ccircumflex 0x2e6
+#define XK_gabovedot 0x2f5
+#define XK_gcircumflex 0x2f8
+#define XK_ubreve 0x2fd
+#define XK_scircumflex 0x2fe
+#endif /* XK_LATIN3 */
+
+
+/*
+ * Latin 4
+ * Byte 3 = 3
+ */
+
+#define XK_LATIN4
+#ifdef XK_LATIN4
+#define XK_kra 0x3a2
+#define XK_kappa 0x3a2 /* deprecated */
+#define XK_Rcedilla 0x3a3
+#define XK_Itilde 0x3a5
+#define XK_Lcedilla 0x3a6
+#define XK_Emacron 0x3aa
+#define XK_Gcedilla 0x3ab
+#define XK_Tslash 0x3ac
+#define XK_rcedilla 0x3b3
+#define XK_itilde 0x3b5
+#define XK_lcedilla 0x3b6
+#define XK_emacron 0x3ba
+#define XK_gcedilla 0x3bb
+#define XK_tslash 0x3bc
+#define XK_ENG 0x3bd
+#define XK_eng 0x3bf
+#define XK_Amacron 0x3c0
+#define XK_Iogonek 0x3c7
+#define XK_Eabovedot 0x3cc
+#define XK_Imacron 0x3cf
+#define XK_Ncedilla 0x3d1
+#define XK_Omacron 0x3d2
+#define XK_Kcedilla 0x3d3
+#define XK_Uogonek 0x3d9
+#define XK_Utilde 0x3dd
+#define XK_Umacron 0x3de
+#define XK_amacron 0x3e0
+#define XK_iogonek 0x3e7
+#define XK_eabovedot 0x3ec
+#define XK_imacron 0x3ef
+#define XK_ncedilla 0x3f1
+#define XK_omacron 0x3f2
+#define XK_kcedilla 0x3f3
+#define XK_uogonek 0x3f9
+#define XK_utilde 0x3fd
+#define XK_umacron 0x3fe
+#endif /* XK_LATIN4 */
+
+/*
+ * Latin-8
+ * Byte 3 = 18
+ */
+#define XK_LATIN8
+#ifdef XK_LATIN8
+#define XK_Babovedot 0x12a1
+#define XK_babovedot 0x12a2
+#define XK_Dabovedot 0x12a6
+#define XK_Wgrave 0x12a8
+#define XK_Wacute 0x12aa
+#define XK_dabovedot 0x12ab
+#define XK_Ygrave 0x12ac
+#define XK_Fabovedot 0x12b0
+#define XK_fabovedot 0x12b1
+#define XK_Mabovedot 0x12b4
+#define XK_mabovedot 0x12b5
+#define XK_Pabovedot 0x12b7
+#define XK_wgrave 0x12b8
+#define XK_pabovedot 0x12b9
+#define XK_wacute 0x12ba
+#define XK_Sabovedot 0x12bb
+#define XK_ygrave 0x12bc
+#define XK_Wdiaeresis 0x12bd
+#define XK_wdiaeresis 0x12be
+#define XK_sabovedot 0x12bf
+#define XK_Wcircumflex 0x12d0
+#define XK_Tabovedot 0x12d7
+#define XK_Ycircumflex 0x12de
+#define XK_wcircumflex 0x12f0
+#define XK_tabovedot 0x12f7
+#define XK_ycircumflex 0x12fe
+#endif /* XK_LATIN8 */
+
+/*
+ * Latin-9 (a.k.a. Latin-0)
+ * Byte 3 = 19
+ */
+
+#define XK_LATIN9
+#ifdef XK_LATIN9
+#define XK_OE 0x13bc
+#define XK_oe 0x13bd
+#define XK_Ydiaeresis 0x13be
+#endif /* XK_LATIN9 */
+
+/*
+ * Katakana
+ * Byte 3 = 4
+ */
+
+#define XK_KATAKANA
+#ifdef XK_KATAKANA
+#define XK_overline 0x47e
+#define XK_kana_fullstop 0x4a1
+#define XK_kana_openingbracket 0x4a2
+#define XK_kana_closingbracket 0x4a3
+#define XK_kana_comma 0x4a4
+#define XK_kana_conjunctive 0x4a5
+#define XK_kana_middledot 0x4a5 /* deprecated */
+#define XK_kana_WO 0x4a6
+#define XK_kana_a 0x4a7
+#define XK_kana_i 0x4a8
+#define XK_kana_u 0x4a9
+#define XK_kana_e 0x4aa
+#define XK_kana_o 0x4ab
+#define XK_kana_ya 0x4ac
+#define XK_kana_yu 0x4ad
+#define XK_kana_yo 0x4ae
+#define XK_kana_tsu 0x4af
+#define XK_kana_tu 0x4af /* deprecated */
+#define XK_prolongedsound 0x4b0
+#define XK_kana_A 0x4b1
+#define XK_kana_I 0x4b2
+#define XK_kana_U 0x4b3
+#define XK_kana_E 0x4b4
+#define XK_kana_O 0x4b5
+#define XK_kana_KA 0x4b6
+#define XK_kana_KI 0x4b7
+#define XK_kana_KU 0x4b8
+#define XK_kana_KE 0x4b9
+#define XK_kana_KO 0x4ba
+#define XK_kana_SA 0x4bb
+#define XK_kana_SHI 0x4bc
+#define XK_kana_SU 0x4bd
+#define XK_kana_SE 0x4be
+#define XK_kana_SO 0x4bf
+#define XK_kana_TA 0x4c0
+#define XK_kana_CHI 0x4c1
+#define XK_kana_TI 0x4c1 /* deprecated */
+#define XK_kana_TSU 0x4c2
+#define XK_kana_TU 0x4c2 /* deprecated */
+#define XK_kana_TE 0x4c3
+#define XK_kana_TO 0x4c4
+#define XK_kana_NA 0x4c5
+#define XK_kana_NI 0x4c6
+#define XK_kana_NU 0x4c7
+#define XK_kana_NE 0x4c8
+#define XK_kana_NO 0x4c9
+#define XK_kana_HA 0x4ca
+#define XK_kana_HI 0x4cb
+#define XK_kana_FU 0x4cc
+#define XK_kana_HU 0x4cc /* deprecated */
+#define XK_kana_HE 0x4cd
+#define XK_kana_HO 0x4ce
+#define XK_kana_MA 0x4cf
+#define XK_kana_MI 0x4d0
+#define XK_kana_MU 0x4d1
+#define XK_kana_ME 0x4d2
+#define XK_kana_MO 0x4d3
+#define XK_kana_YA 0x4d4
+#define XK_kana_YU 0x4d5
+#define XK_kana_YO 0x4d6
+#define XK_kana_RA 0x4d7
+#define XK_kana_RI 0x4d8
+#define XK_kana_RU 0x4d9
+#define XK_kana_RE 0x4da
+#define XK_kana_RO 0x4db
+#define XK_kana_WA 0x4dc
+#define XK_kana_N 0x4dd
+#define XK_voicedsound 0x4de
+#define XK_semivoicedsound 0x4df
+#define XK_kana_switch 0xFF7E /* Alias for mode_switch */
+#endif /* XK_KATAKANA */
+
+/*
+ * Arabic
+ * Byte 3 = 5
+ */
+
+#define XK_ARABIC
+#ifdef XK_ARABIC
+#define XK_Farsi_0 0x590
+#define XK_Farsi_1 0x591
+#define XK_Farsi_2 0x592
+#define XK_Farsi_3 0x593
+#define XK_Farsi_4 0x594
+#define XK_Farsi_5 0x595
+#define XK_Farsi_6 0x596
+#define XK_Farsi_7 0x597
+#define XK_Farsi_8 0x598
+#define XK_Farsi_9 0x599
+#define XK_Arabic_percent 0x5a5
+#define XK_Arabic_superscript_alef 0x5a6
+#define XK_Arabic_tteh 0x5a7
+#define XK_Arabic_peh 0x5a8
+#define XK_Arabic_tcheh 0x5a9
+#define XK_Arabic_ddal 0x5aa
+#define XK_Arabic_rreh 0x5ab
+#define XK_Arabic_comma 0x5ac
+#define XK_Arabic_fullstop 0x5ae
+#define XK_Arabic_0 0x5b0
+#define XK_Arabic_1 0x5b1
+#define XK_Arabic_2 0x5b2
+#define XK_Arabic_3 0x5b3
+#define XK_Arabic_4 0x5b4
+#define XK_Arabic_5 0x5b5
+#define XK_Arabic_6 0x5b6
+#define XK_Arabic_7 0x5b7
+#define XK_Arabic_8 0x5b8
+#define XK_Arabic_9 0x5b9
+#define XK_Arabic_semicolon 0x5bb
+#define XK_Arabic_question_mark 0x5bf
+#define XK_Arabic_hamza 0x5c1
+#define XK_Arabic_maddaonalef 0x5c2
+#define XK_Arabic_hamzaonalef 0x5c3
+#define XK_Arabic_hamzaonwaw 0x5c4
+#define XK_Arabic_hamzaunderalef 0x5c5
+#define XK_Arabic_hamzaonyeh 0x5c6
+#define XK_Arabic_alef 0x5c7
+#define XK_Arabic_beh 0x5c8
+#define XK_Arabic_tehmarbuta 0x5c9
+#define XK_Arabic_teh 0x5ca
+#define XK_Arabic_theh 0x5cb
+#define XK_Arabic_jeem 0x5cc
+#define XK_Arabic_hah 0x5cd
+#define XK_Arabic_khah 0x5ce
+#define XK_Arabic_dal 0x5cf
+#define XK_Arabic_thal 0x5d0
+#define XK_Arabic_ra 0x5d1
+#define XK_Arabic_zain 0x5d2
+#define XK_Arabic_seen 0x5d3
+#define XK_Arabic_sheen 0x5d4
+#define XK_Arabic_sad 0x5d5
+#define XK_Arabic_dad 0x5d6
+#define XK_Arabic_tah 0x5d7
+#define XK_Arabic_zah 0x5d8
+#define XK_Arabic_ain 0x5d9
+#define XK_Arabic_ghain 0x5da
+#define XK_Arabic_tatweel 0x5e0
+#define XK_Arabic_feh 0x5e1
+#define XK_Arabic_qaf 0x5e2
+#define XK_Arabic_kaf 0x5e3
+#define XK_Arabic_lam 0x5e4
+#define XK_Arabic_meem 0x5e5
+#define XK_Arabic_noon 0x5e6
+#define XK_Arabic_ha 0x5e7
+#define XK_Arabic_heh 0x5e7 /* deprecated */
+#define XK_Arabic_waw 0x5e8
+#define XK_Arabic_alefmaksura 0x5e9
+#define XK_Arabic_yeh 0x5ea
+#define XK_Arabic_fathatan 0x5eb
+#define XK_Arabic_dammatan 0x5ec
+#define XK_Arabic_kasratan 0x5ed
+#define XK_Arabic_fatha 0x5ee
+#define XK_Arabic_damma 0x5ef
+#define XK_Arabic_kasra 0x5f0
+#define XK_Arabic_shadda 0x5f1
+#define XK_Arabic_sukun 0x5f2
+#define XK_Arabic_madda_above 0x5f3
+#define XK_Arabic_hamza_above 0x5f4
+#define XK_Arabic_hamza_below 0x5f5
+#define XK_Arabic_jeh 0x5f6
+#define XK_Arabic_veh 0x5f7
+#define XK_Arabic_keheh 0x5f8
+#define XK_Arabic_gaf 0x5f9
+#define XK_Arabic_noon_ghunna 0x5fa
+#define XK_Arabic_heh_doachashmee 0x5fb
+#define XK_Farsi_yeh 0x5fc
+#define XK_Arabic_farsi_yeh XK_Farsi_yeh
+#define XK_Arabic_yeh_baree 0x5fd
+#define XK_Arabic_heh_goal 0x5fe
+#define XK_Arabic_switch 0xFF7E /* Alias for mode_switch */
+#endif /* XK_ARABIC */
+
+/*
+ * Cyrillic
+ * Byte 3 = 6
+ */
+#define XK_CYRILLIC
+#ifdef XK_CYRILLIC
+#define XK_Cyrillic_GHE_bar 0x680
+#define XK_Cyrillic_ghe_bar 0x690
+#define XK_Cyrillic_ZHE_descender 0x681
+#define XK_Cyrillic_zhe_descender 0x691
+#define XK_Cyrillic_KA_descender 0x682
+#define XK_Cyrillic_ka_descender 0x692
+#define XK_Cyrillic_KA_vertstroke 0x683
+#define XK_Cyrillic_ka_vertstroke 0x693
+#define XK_Cyrillic_EN_descender 0x684
+#define XK_Cyrillic_en_descender 0x694
+#define XK_Cyrillic_U_straight 0x685
+#define XK_Cyrillic_u_straight 0x695
+#define XK_Cyrillic_U_straight_bar 0x686
+#define XK_Cyrillic_u_straight_bar 0x696
+#define XK_Cyrillic_HA_descender 0x687
+#define XK_Cyrillic_ha_descender 0x697
+#define XK_Cyrillic_CHE_descender 0x688
+#define XK_Cyrillic_che_descender 0x698
+#define XK_Cyrillic_CHE_vertstroke 0x689
+#define XK_Cyrillic_che_vertstroke 0x699
+#define XK_Cyrillic_SHHA 0x68a
+#define XK_Cyrillic_shha 0x69a
+
+#define XK_Cyrillic_SCHWA 0x68c
+#define XK_Cyrillic_schwa 0x69c
+#define XK_Cyrillic_I_macron 0x68d
+#define XK_Cyrillic_i_macron 0x69d
+#define XK_Cyrillic_O_bar 0x68e
+#define XK_Cyrillic_o_bar 0x69e
+#define XK_Cyrillic_U_macron 0x68f
+#define XK_Cyrillic_u_macron 0x69f
+
+#define XK_Serbian_dje 0x6a1
+#define XK_Macedonia_gje 0x6a2
+#define XK_Cyrillic_io 0x6a3
+#define XK_Ukrainian_ie 0x6a4
+#define XK_Ukranian_je 0x6a4 /* deprecated */
+#define XK_Macedonia_dse 0x6a5
+#define XK_Ukrainian_i 0x6a6
+#define XK_Ukranian_i 0x6a6 /* deprecated */
+#define XK_Ukrainian_yi 0x6a7
+#define XK_Ukranian_yi 0x6a7 /* deprecated */
+#define XK_Cyrillic_je 0x6a8
+#define XK_Serbian_je 0x6a8 /* deprecated */
+#define XK_Cyrillic_lje 0x6a9
+#define XK_Serbian_lje 0x6a9 /* deprecated */
+#define XK_Cyrillic_nje 0x6aa
+#define XK_Serbian_nje 0x6aa /* deprecated */
+#define XK_Serbian_tshe 0x6ab
+#define XK_Macedonia_kje 0x6ac
+#define XK_Ukrainian_ghe_with_upturn 0x6ad
+#define XK_Byelorussian_shortu 0x6ae
+#define XK_Cyrillic_dzhe 0x6af
+#define XK_Serbian_dze 0x6af /* deprecated */
+#define XK_numerosign 0x6b0
+#define XK_Serbian_DJE 0x6b1
+#define XK_Macedonia_GJE 0x6b2
+#define XK_Cyrillic_IO 0x6b3
+#define XK_Ukrainian_IE 0x6b4
+#define XK_Ukranian_JE 0x6b4 /* deprecated */
+#define XK_Macedonia_DSE 0x6b5
+#define XK_Ukrainian_I 0x6b6
+#define XK_Ukranian_I 0x6b6 /* deprecated */
+#define XK_Ukrainian_YI 0x6b7
+#define XK_Ukranian_YI 0x6b7 /* deprecated */
+#define XK_Cyrillic_JE 0x6b8
+#define XK_Serbian_JE 0x6b8 /* deprecated */
+#define XK_Cyrillic_LJE 0x6b9
+#define XK_Serbian_LJE 0x6b9 /* deprecated */
+#define XK_Cyrillic_NJE 0x6ba
+#define XK_Serbian_NJE 0x6ba /* deprecated */
+#define XK_Serbian_TSHE 0x6bb
+#define XK_Macedonia_KJE 0x6bc
+#define XK_Ukrainian_GHE_WITH_UPTURN 0x6bd
+#define XK_Byelorussian_SHORTU 0x6be
+#define XK_Cyrillic_DZHE 0x6bf
+#define XK_Serbian_DZE 0x6bf /* deprecated */
+#define XK_Cyrillic_yu 0x6c0
+#define XK_Cyrillic_a 0x6c1
+#define XK_Cyrillic_be 0x6c2
+#define XK_Cyrillic_tse 0x6c3
+#define XK_Cyrillic_de 0x6c4
+#define XK_Cyrillic_ie 0x6c5
+#define XK_Cyrillic_ef 0x6c6
+#define XK_Cyrillic_ghe 0x6c7
+#define XK_Cyrillic_ha 0x6c8
+#define XK_Cyrillic_i 0x6c9
+#define XK_Cyrillic_shorti 0x6ca
+#define XK_Cyrillic_ka 0x6cb
+#define XK_Cyrillic_el 0x6cc
+#define XK_Cyrillic_em 0x6cd
+#define XK_Cyrillic_en 0x6ce
+#define XK_Cyrillic_o 0x6cf
+#define XK_Cyrillic_pe 0x6d0
+#define XK_Cyrillic_ya 0x6d1
+#define XK_Cyrillic_er 0x6d2
+#define XK_Cyrillic_es 0x6d3
+#define XK_Cyrillic_te 0x6d4
+#define XK_Cyrillic_u 0x6d5
+#define XK_Cyrillic_zhe 0x6d6
+#define XK_Cyrillic_ve 0x6d7
+#define XK_Cyrillic_softsign 0x6d8
+#define XK_Cyrillic_yeru 0x6d9
+#define XK_Cyrillic_ze 0x6da
+#define XK_Cyrillic_sha 0x6db
+#define XK_Cyrillic_e 0x6dc
+#define XK_Cyrillic_shcha 0x6dd
+#define XK_Cyrillic_che 0x6de
+#define XK_Cyrillic_hardsign 0x6df
+#define XK_Cyrillic_YU 0x6e0
+#define XK_Cyrillic_A 0x6e1
+#define XK_Cyrillic_BE 0x6e2
+#define XK_Cyrillic_TSE 0x6e3
+#define XK_Cyrillic_DE 0x6e4
+#define XK_Cyrillic_IE 0x6e5
+#define XK_Cyrillic_EF 0x6e6
+#define XK_Cyrillic_GHE 0x6e7
+#define XK_Cyrillic_HA 0x6e8
+#define XK_Cyrillic_I 0x6e9
+#define XK_Cyrillic_SHORTI 0x6ea
+#define XK_Cyrillic_KA 0x6eb
+#define XK_Cyrillic_EL 0x6ec
+#define XK_Cyrillic_EM 0x6ed
+#define XK_Cyrillic_EN 0x6ee
+#define XK_Cyrillic_O 0x6ef
+#define XK_Cyrillic_PE 0x6f0
+#define XK_Cyrillic_YA 0x6f1
+#define XK_Cyrillic_ER 0x6f2
+#define XK_Cyrillic_ES 0x6f3
+#define XK_Cyrillic_TE 0x6f4
+#define XK_Cyrillic_U 0x6f5
+#define XK_Cyrillic_ZHE 0x6f6
+#define XK_Cyrillic_VE 0x6f7
+#define XK_Cyrillic_SOFTSIGN 0x6f8
+#define XK_Cyrillic_YERU 0x6f9
+#define XK_Cyrillic_ZE 0x6fa
+#define XK_Cyrillic_SHA 0x6fb
+#define XK_Cyrillic_E 0x6fc
+#define XK_Cyrillic_SHCHA 0x6fd
+#define XK_Cyrillic_CHE 0x6fe
+#define XK_Cyrillic_HARDSIGN 0x6ff
+#endif /* XK_CYRILLIC */
+
+/*
+ * Greek
+ * Byte 3 = 7
+ */
+
+#define XK_GREEK
+#ifdef XK_GREEK
+#define XK_Greek_ALPHAaccent 0x7a1
+#define XK_Greek_EPSILONaccent 0x7a2
+#define XK_Greek_ETAaccent 0x7a3
+#define XK_Greek_IOTAaccent 0x7a4
+#define XK_Greek_IOTAdieresis 0x7a5
+#define XK_Greek_IOTAdiaeresis XK_Greek_IOTAdieresis /* old typo */
+#define XK_Greek_OMICRONaccent 0x7a7
+#define XK_Greek_UPSILONaccent 0x7a8
+#define XK_Greek_UPSILONdieresis 0x7a9
+#define XK_Greek_OMEGAaccent 0x7ab
+#define XK_Greek_accentdieresis 0x7ae
+#define XK_Greek_horizbar 0x7af
+#define XK_Greek_alphaaccent 0x7b1
+#define XK_Greek_epsilonaccent 0x7b2
+#define XK_Greek_etaaccent 0x7b3
+#define XK_Greek_iotaaccent 0x7b4
+#define XK_Greek_iotadieresis 0x7b5
+#define XK_Greek_iotaaccentdieresis 0x7b6
+#define XK_Greek_omicronaccent 0x7b7
+#define XK_Greek_upsilonaccent 0x7b8
+#define XK_Greek_upsilondieresis 0x7b9
+#define XK_Greek_upsilonaccentdieresis 0x7ba
+#define XK_Greek_omegaaccent 0x7bb
+#define XK_Greek_ALPHA 0x7c1
+#define XK_Greek_BETA 0x7c2
+#define XK_Greek_GAMMA 0x7c3
+#define XK_Greek_DELTA 0x7c4
+#define XK_Greek_EPSILON 0x7c5
+#define XK_Greek_ZETA 0x7c6
+#define XK_Greek_ETA 0x7c7
+#define XK_Greek_THETA 0x7c8
+#define XK_Greek_IOTA 0x7c9
+#define XK_Greek_KAPPA 0x7ca
+#define XK_Greek_LAMDA 0x7cb
+#define XK_Greek_LAMBDA 0x7cb
+#define XK_Greek_MU 0x7cc
+#define XK_Greek_NU 0x7cd
+#define XK_Greek_XI 0x7ce
+#define XK_Greek_OMICRON 0x7cf
+#define XK_Greek_PI 0x7d0
+#define XK_Greek_RHO 0x7d1
+#define XK_Greek_SIGMA 0x7d2
+#define XK_Greek_TAU 0x7d4
+#define XK_Greek_UPSILON 0x7d5
+#define XK_Greek_PHI 0x7d6
+#define XK_Greek_CHI 0x7d7
+#define XK_Greek_PSI 0x7d8
+#define XK_Greek_OMEGA 0x7d9
+#define XK_Greek_alpha 0x7e1
+#define XK_Greek_beta 0x7e2
+#define XK_Greek_gamma 0x7e3
+#define XK_Greek_delta 0x7e4
+#define XK_Greek_epsilon 0x7e5
+#define XK_Greek_zeta 0x7e6
+#define XK_Greek_eta 0x7e7
+#define XK_Greek_theta 0x7e8
+#define XK_Greek_iota 0x7e9
+#define XK_Greek_kappa 0x7ea
+#define XK_Greek_lamda 0x7eb
+#define XK_Greek_lambda 0x7eb
+#define XK_Greek_mu 0x7ec
+#define XK_Greek_nu 0x7ed
+#define XK_Greek_xi 0x7ee
+#define XK_Greek_omicron 0x7ef
+#define XK_Greek_pi 0x7f0
+#define XK_Greek_rho 0x7f1
+#define XK_Greek_sigma 0x7f2
+#define XK_Greek_finalsmallsigma 0x7f3
+#define XK_Greek_tau 0x7f4
+#define XK_Greek_upsilon 0x7f5
+#define XK_Greek_phi 0x7f6
+#define XK_Greek_chi 0x7f7
+#define XK_Greek_psi 0x7f8
+#define XK_Greek_omega 0x7f9
+#define XK_Greek_switch 0xFF7E /* Alias for mode_switch */
+#endif /* XK_GREEK */
+
+/*
+ * Technical
+ * Byte 3 = 8
+ */
+
+#define XK_TECHNICAL
+#ifdef XK_TECHNICAL
+#define XK_leftradical 0x8a1
+#define XK_topleftradical 0x8a2
+#define XK_horizconnector 0x8a3
+#define XK_topintegral 0x8a4
+#define XK_botintegral 0x8a5
+#define XK_vertconnector 0x8a6
+#define XK_topleftsqbracket 0x8a7
+#define XK_botleftsqbracket 0x8a8
+#define XK_toprightsqbracket 0x8a9
+#define XK_botrightsqbracket 0x8aa
+#define XK_topleftparens 0x8ab
+#define XK_botleftparens 0x8ac
+#define XK_toprightparens 0x8ad
+#define XK_botrightparens 0x8ae
+#define XK_leftmiddlecurlybrace 0x8af
+#define XK_rightmiddlecurlybrace 0x8b0
+#define XK_topleftsummation 0x8b1
+#define XK_botleftsummation 0x8b2
+#define XK_topvertsummationconnector 0x8b3
+#define XK_botvertsummationconnector 0x8b4
+#define XK_toprightsummation 0x8b5
+#define XK_botrightsummation 0x8b6
+#define XK_rightmiddlesummation 0x8b7
+#define XK_lessthanequal 0x8bc
+#define XK_notequal 0x8bd
+#define XK_greaterthanequal 0x8be
+#define XK_integral 0x8bf
+#define XK_therefore 0x8c0
+#define XK_variation 0x8c1
+#define XK_infinity 0x8c2
+#define XK_nabla 0x8c5
+#define XK_approximate 0x8c8
+#define XK_similarequal 0x8c9
+#define XK_ifonlyif 0x8cd
+#define XK_implies 0x8ce
+#define XK_identical 0x8cf
+#define XK_radical 0x8d6
+#define XK_includedin 0x8da
+#define XK_includes 0x8db
+#define XK_intersection 0x8dc
+#define XK_union 0x8dd
+#define XK_logicaland 0x8de
+#define XK_logicalor 0x8df
+#define XK_partialderivative 0x8ef
+#define XK_function 0x8f6
+#define XK_leftarrow 0x8fb
+#define XK_uparrow 0x8fc
+#define XK_rightarrow 0x8fd
+#define XK_downarrow 0x8fe
+#endif /* XK_TECHNICAL */
+
+/*
+ * Special
+ * Byte 3 = 9
+ */
+
+#define XK_SPECIAL
+#ifdef XK_SPECIAL
+#define XK_blank 0x9df
+#define XK_soliddiamond 0x9e0
+#define XK_checkerboard 0x9e1
+#define XK_ht 0x9e2
+#define XK_ff 0x9e3
+#define XK_cr 0x9e4
+#define XK_lf 0x9e5
+#define XK_nl 0x9e8
+#define XK_vt 0x9e9
+#define XK_lowrightcorner 0x9ea
+#define XK_uprightcorner 0x9eb
+#define XK_upleftcorner 0x9ec
+#define XK_lowleftcorner 0x9ed
+#define XK_crossinglines 0x9ee
+#define XK_horizlinescan1 0x9ef
+#define XK_horizlinescan3 0x9f0
+#define XK_horizlinescan5 0x9f1
+#define XK_horizlinescan7 0x9f2
+#define XK_horizlinescan9 0x9f3
+#define XK_leftt 0x9f4
+#define XK_rightt 0x9f5
+#define XK_bott 0x9f6
+#define XK_topt 0x9f7
+#define XK_vertbar 0x9f8
+#endif /* XK_SPECIAL */
+
+/*
+ * Publishing
+ * Byte 3 = a
+ */
+
+#define XK_PUBLISHING
+#ifdef XK_PUBLISHING
+#define XK_emspace 0xaa1
+#define XK_enspace 0xaa2
+#define XK_em3space 0xaa3
+#define XK_em4space 0xaa4
+#define XK_digitspace 0xaa5
+#define XK_punctspace 0xaa6
+#define XK_thinspace 0xaa7
+#define XK_hairspace 0xaa8
+#define XK_emdash 0xaa9
+#define XK_endash 0xaaa
+#define XK_signifblank 0xaac
+#define XK_ellipsis 0xaae
+#define XK_doubbaselinedot 0xaaf
+#define XK_onethird 0xab0
+#define XK_twothirds 0xab1
+#define XK_onefifth 0xab2
+#define XK_twofifths 0xab3
+#define XK_threefifths 0xab4
+#define XK_fourfifths 0xab5
+#define XK_onesixth 0xab6
+#define XK_fivesixths 0xab7
+#define XK_careof 0xab8
+#define XK_figdash 0xabb
+#define XK_leftanglebracket 0xabc
+#define XK_decimalpoint 0xabd
+#define XK_rightanglebracket 0xabe
+#define XK_marker 0xabf
+#define XK_oneeighth 0xac3
+#define XK_threeeighths 0xac4
+#define XK_fiveeighths 0xac5
+#define XK_seveneighths 0xac6
+#define XK_trademark 0xac9
+#define XK_signaturemark 0xaca
+#define XK_trademarkincircle 0xacb
+#define XK_leftopentriangle 0xacc
+#define XK_rightopentriangle 0xacd
+#define XK_emopencircle 0xace
+#define XK_emopenrectangle 0xacf
+#define XK_leftsinglequotemark 0xad0
+#define XK_rightsinglequotemark 0xad1
+#define XK_leftdoublequotemark 0xad2
+#define XK_rightdoublequotemark 0xad3
+#define XK_prescription 0xad4
+#define XK_minutes 0xad6
+#define XK_seconds 0xad7
+#define XK_latincross 0xad9
+#define XK_hexagram 0xada
+#define XK_filledrectbullet 0xadb
+#define XK_filledlefttribullet 0xadc
+#define XK_filledrighttribullet 0xadd
+#define XK_emfilledcircle 0xade
+#define XK_emfilledrect 0xadf
+#define XK_enopencircbullet 0xae0
+#define XK_enopensquarebullet 0xae1
+#define XK_openrectbullet 0xae2
+#define XK_opentribulletup 0xae3
+#define XK_opentribulletdown 0xae4
+#define XK_openstar 0xae5
+#define XK_enfilledcircbullet 0xae6
+#define XK_enfilledsqbullet 0xae7
+#define XK_filledtribulletup 0xae8
+#define XK_filledtribulletdown 0xae9
+#define XK_leftpointer 0xaea
+#define XK_rightpointer 0xaeb
+#define XK_club 0xaec
+#define XK_diamond 0xaed
+#define XK_heart 0xaee
+#define XK_maltesecross 0xaf0
+#define XK_dagger 0xaf1
+#define XK_doubledagger 0xaf2
+#define XK_checkmark 0xaf3
+#define XK_ballotcross 0xaf4
+#define XK_musicalsharp 0xaf5
+#define XK_musicalflat 0xaf6
+#define XK_malesymbol 0xaf7
+#define XK_femalesymbol 0xaf8
+#define XK_telephone 0xaf9
+#define XK_telephonerecorder 0xafa
+#define XK_phonographcopyright 0xafb
+#define XK_caret 0xafc
+#define XK_singlelowquotemark 0xafd
+#define XK_doublelowquotemark 0xafe
+#define XK_cursor 0xaff
+#endif /* XK_PUBLISHING */
+
+/*
+ * APL
+ * Byte 3 = b
+ */
+
+#define XK_APL
+#ifdef XK_APL
+#define XK_leftcaret 0xba3
+#define XK_rightcaret 0xba6
+#define XK_downcaret 0xba8
+#define XK_upcaret 0xba9
+#define XK_overbar 0xbc0
+#define XK_downtack 0xbc2
+#define XK_upshoe 0xbc3
+#define XK_downstile 0xbc4
+#define XK_underbar 0xbc6
+#define XK_jot 0xbca
+#define XK_quad 0xbcc
+#define XK_uptack 0xbce
+#define XK_circle 0xbcf
+#define XK_upstile 0xbd3
+#define XK_downshoe 0xbd6
+#define XK_rightshoe 0xbd8
+#define XK_leftshoe 0xbda
+#define XK_lefttack 0xbdc
+#define XK_righttack 0xbfc
+#endif /* XK_APL */
+
+/*
+ * Hebrew
+ * Byte 3 = c
+ */
+
+#define XK_HEBREW
+#ifdef XK_HEBREW
+#define XK_hebrew_doublelowline 0xcdf
+#define XK_hebrew_aleph 0xce0
+#define XK_hebrew_bet 0xce1
+#define XK_hebrew_beth 0xce1 /* deprecated */
+#define XK_hebrew_gimel 0xce2
+#define XK_hebrew_gimmel 0xce2 /* deprecated */
+#define XK_hebrew_dalet 0xce3
+#define XK_hebrew_daleth 0xce3 /* deprecated */
+#define XK_hebrew_he 0xce4
+#define XK_hebrew_waw 0xce5
+#define XK_hebrew_zain 0xce6
+#define XK_hebrew_zayin 0xce6 /* deprecated */
+#define XK_hebrew_chet 0xce7
+#define XK_hebrew_het 0xce7 /* deprecated */
+#define XK_hebrew_tet 0xce8
+#define XK_hebrew_teth 0xce8 /* deprecated */
+#define XK_hebrew_yod 0xce9
+#define XK_hebrew_finalkaph 0xcea
+#define XK_hebrew_kaph 0xceb
+#define XK_hebrew_lamed 0xcec
+#define XK_hebrew_finalmem 0xced
+#define XK_hebrew_mem 0xcee
+#define XK_hebrew_finalnun 0xcef
+#define XK_hebrew_nun 0xcf0
+#define XK_hebrew_samech 0xcf1
+#define XK_hebrew_samekh 0xcf1 /* deprecated */
+#define XK_hebrew_ayin 0xcf2
+#define XK_hebrew_finalpe 0xcf3
+#define XK_hebrew_pe 0xcf4
+#define XK_hebrew_finalzade 0xcf5
+#define XK_hebrew_finalzadi 0xcf5 /* deprecated */
+#define XK_hebrew_zade 0xcf6
+#define XK_hebrew_zadi 0xcf6 /* deprecated */
+#define XK_hebrew_qoph 0xcf7
+#define XK_hebrew_kuf 0xcf7 /* deprecated */
+#define XK_hebrew_resh 0xcf8
+#define XK_hebrew_shin 0xcf9
+#define XK_hebrew_taw 0xcfa
+#define XK_hebrew_taf 0xcfa /* deprecated */
+#define XK_Hebrew_switch 0xFF7E /* Alias for mode_switch */
+#endif /* XK_HEBREW */
+
+/*
+ * Thai
+ * Byte 3 = d
+ */
+
+#define XK_THAI
+#ifdef XK_THAI
+#define XK_Thai_kokai 0xda1
+#define XK_Thai_khokhai 0xda2
+#define XK_Thai_khokhuat 0xda3
+#define XK_Thai_khokhwai 0xda4
+#define XK_Thai_khokhon 0xda5
+#define XK_Thai_khorakhang 0xda6
+#define XK_Thai_ngongu 0xda7
+#define XK_Thai_chochan 0xda8
+#define XK_Thai_choching 0xda9
+#define XK_Thai_chochang 0xdaa
+#define XK_Thai_soso 0xdab
+#define XK_Thai_chochoe 0xdac
+#define XK_Thai_yoying 0xdad
+#define XK_Thai_dochada 0xdae
+#define XK_Thai_topatak 0xdaf
+#define XK_Thai_thothan 0xdb0
+#define XK_Thai_thonangmontho 0xdb1
+#define XK_Thai_thophuthao 0xdb2
+#define XK_Thai_nonen 0xdb3
+#define XK_Thai_dodek 0xdb4
+#define XK_Thai_totao 0xdb5
+#define XK_Thai_thothung 0xdb6
+#define XK_Thai_thothahan 0xdb7
+#define XK_Thai_thothong 0xdb8
+#define XK_Thai_nonu 0xdb9
+#define XK_Thai_bobaimai 0xdba
+#define XK_Thai_popla 0xdbb
+#define XK_Thai_phophung 0xdbc
+#define XK_Thai_fofa 0xdbd
+#define XK_Thai_phophan 0xdbe
+#define XK_Thai_fofan 0xdbf
+#define XK_Thai_phosamphao 0xdc0
+#define XK_Thai_moma 0xdc1
+#define XK_Thai_yoyak 0xdc2
+#define XK_Thai_rorua 0xdc3
+#define XK_Thai_ru 0xdc4
+#define XK_Thai_loling 0xdc5
+#define XK_Thai_lu 0xdc6
+#define XK_Thai_wowaen 0xdc7
+#define XK_Thai_sosala 0xdc8
+#define XK_Thai_sorusi 0xdc9
+#define XK_Thai_sosua 0xdca
+#define XK_Thai_hohip 0xdcb
+#define XK_Thai_lochula 0xdcc
+#define XK_Thai_oang 0xdcd
+#define XK_Thai_honokhuk 0xdce
+#define XK_Thai_paiyannoi 0xdcf
+#define XK_Thai_saraa 0xdd0
+#define XK_Thai_maihanakat 0xdd1
+#define XK_Thai_saraaa 0xdd2
+#define XK_Thai_saraam 0xdd3
+#define XK_Thai_sarai 0xdd4
+#define XK_Thai_saraii 0xdd5
+#define XK_Thai_saraue 0xdd6
+#define XK_Thai_sarauee 0xdd7
+#define XK_Thai_sarau 0xdd8
+#define XK_Thai_sarauu 0xdd9
+#define XK_Thai_phinthu 0xdda
+#define XK_Thai_maihanakat_maitho 0xdde
+#define XK_Thai_baht 0xddf
+#define XK_Thai_sarae 0xde0
+#define XK_Thai_saraae 0xde1
+#define XK_Thai_sarao 0xde2
+#define XK_Thai_saraaimaimuan 0xde3
+#define XK_Thai_saraaimaimalai 0xde4
+#define XK_Thai_lakkhangyao 0xde5
+#define XK_Thai_maiyamok 0xde6
+#define XK_Thai_maitaikhu 0xde7
+#define XK_Thai_maiek 0xde8
+#define XK_Thai_maitho 0xde9
+#define XK_Thai_maitri 0xdea
+#define XK_Thai_maichattawa 0xdeb
+#define XK_Thai_thanthakhat 0xdec
+#define XK_Thai_nikhahit 0xded
+#define XK_Thai_leksun 0xdf0
+#define XK_Thai_leknung 0xdf1
+#define XK_Thai_leksong 0xdf2
+#define XK_Thai_leksam 0xdf3
+#define XK_Thai_leksi 0xdf4
+#define XK_Thai_lekha 0xdf5
+#define XK_Thai_lekhok 0xdf6
+#define XK_Thai_lekchet 0xdf7
+#define XK_Thai_lekpaet 0xdf8
+#define XK_Thai_lekkao 0xdf9
+#endif /* XK_THAI */
+
+/*
+ * Korean
+ * Byte 3 = e
+ */
+
+#define XK_KOREAN
+#ifdef XK_KOREAN
+
+#define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */
+#define XK_Hangul_Start 0xff32 /* Hangul start */
+#define XK_Hangul_End 0xff33 /* Hangul end, English start */
+#define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */
+#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */
+#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */
+#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */
+#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */
+#define XK_Hangul_Banja 0xff39 /* Banja mode */
+#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */
+#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */
+#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */
+#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */
+#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */
+#define XK_Hangul_Special 0xff3f /* Special symbols */
+#define XK_Hangul_switch 0xFF7E /* Alias for mode_switch */
+
+/* Hangul Consonant Characters */
+#define XK_Hangul_Kiyeog 0xea1
+#define XK_Hangul_SsangKiyeog 0xea2
+#define XK_Hangul_KiyeogSios 0xea3
+#define XK_Hangul_Nieun 0xea4
+#define XK_Hangul_NieunJieuj 0xea5
+#define XK_Hangul_NieunHieuh 0xea6
+#define XK_Hangul_Dikeud 0xea7
+#define XK_Hangul_SsangDikeud 0xea8
+#define XK_Hangul_Rieul 0xea9
+#define XK_Hangul_RieulKiyeog 0xeaa
+#define XK_Hangul_RieulMieum 0xeab
+#define XK_Hangul_RieulPieub 0xeac
+#define XK_Hangul_RieulSios 0xead
+#define XK_Hangul_RieulTieut 0xeae
+#define XK_Hangul_RieulPhieuf 0xeaf
+#define XK_Hangul_RieulHieuh 0xeb0
+#define XK_Hangul_Mieum 0xeb1
+#define XK_Hangul_Pieub 0xeb2
+#define XK_Hangul_SsangPieub 0xeb3
+#define XK_Hangul_PieubSios 0xeb4
+#define XK_Hangul_Sios 0xeb5
+#define XK_Hangul_SsangSios 0xeb6
+#define XK_Hangul_Ieung 0xeb7
+#define XK_Hangul_Jieuj 0xeb8
+#define XK_Hangul_SsangJieuj 0xeb9
+#define XK_Hangul_Cieuc 0xeba
+#define XK_Hangul_Khieuq 0xebb
+#define XK_Hangul_Tieut 0xebc
+#define XK_Hangul_Phieuf 0xebd
+#define XK_Hangul_Hieuh 0xebe
+
+/* Hangul Vowel Characters */
+#define XK_Hangul_A 0xebf
+#define XK_Hangul_AE 0xec0
+#define XK_Hangul_YA 0xec1
+#define XK_Hangul_YAE 0xec2
+#define XK_Hangul_EO 0xec3
+#define XK_Hangul_E 0xec4
+#define XK_Hangul_YEO 0xec5
+#define XK_Hangul_YE 0xec6
+#define XK_Hangul_O 0xec7
+#define XK_Hangul_WA 0xec8
+#define XK_Hangul_WAE 0xec9
+#define XK_Hangul_OE 0xeca
+#define XK_Hangul_YO 0xecb
+#define XK_Hangul_U 0xecc
+#define XK_Hangul_WEO 0xecd
+#define XK_Hangul_WE 0xece
+#define XK_Hangul_WI 0xecf
+#define XK_Hangul_YU 0xed0
+#define XK_Hangul_EU 0xed1
+#define XK_Hangul_YI 0xed2
+#define XK_Hangul_I 0xed3
+
+/* Hangul syllable-final (JongSeong) Characters */
+#define XK_Hangul_J_Kiyeog 0xed4
+#define XK_Hangul_J_SsangKiyeog 0xed5
+#define XK_Hangul_J_KiyeogSios 0xed6
+#define XK_Hangul_J_Nieun 0xed7
+#define XK_Hangul_J_NieunJieuj 0xed8
+#define XK_Hangul_J_NieunHieuh 0xed9
+#define XK_Hangul_J_Dikeud 0xeda
+#define XK_Hangul_J_Rieul 0xedb
+#define XK_Hangul_J_RieulKiyeog 0xedc
+#define XK_Hangul_J_RieulMieum 0xedd
+#define XK_Hangul_J_RieulPieub 0xede
+#define XK_Hangul_J_RieulSios 0xedf
+#define XK_Hangul_J_RieulTieut 0xee0
+#define XK_Hangul_J_RieulPhieuf 0xee1
+#define XK_Hangul_J_RieulHieuh 0xee2
+#define XK_Hangul_J_Mieum 0xee3
+#define XK_Hangul_J_Pieub 0xee4
+#define XK_Hangul_J_PieubSios 0xee5
+#define XK_Hangul_J_Sios 0xee6
+#define XK_Hangul_J_SsangSios 0xee7
+#define XK_Hangul_J_Ieung 0xee8
+#define XK_Hangul_J_Jieuj 0xee9
+#define XK_Hangul_J_Cieuc 0xeea
+#define XK_Hangul_J_Khieuq 0xeeb
+#define XK_Hangul_J_Tieut 0xeec
+#define XK_Hangul_J_Phieuf 0xeed
+#define XK_Hangul_J_Hieuh 0xeee
+
+/* Ancient Hangul Consonant Characters */
+#define XK_Hangul_RieulYeorinHieuh 0xeef
+#define XK_Hangul_SunkyeongeumMieum 0xef0
+#define XK_Hangul_SunkyeongeumPieub 0xef1
+#define XK_Hangul_PanSios 0xef2
+#define XK_Hangul_KkogjiDalrinIeung 0xef3
+#define XK_Hangul_SunkyeongeumPhieuf 0xef4
+#define XK_Hangul_YeorinHieuh 0xef5
+
+/* Ancient Hangul Vowel Characters */
+#define XK_Hangul_AraeA 0xef6
+#define XK_Hangul_AraeAE 0xef7
+
+/* Ancient Hangul syllable-final (JongSeong) Characters */
+#define XK_Hangul_J_PanSios 0xef8
+#define XK_Hangul_J_KkogjiDalrinIeung 0xef9
+#define XK_Hangul_J_YeorinHieuh 0xefa
+
+/* Korean currency symbol */
+#define XK_Korean_Won 0xeff
+
+#endif /* XK_KOREAN */
+
+/*
+ * Armenian
+ * Byte 3 = 0x14
+ */
+
+#define XK_ARMENIAN
+#ifdef XK_ARMENIAN
+#define XK_Armenian_eternity 0x14a1
+#define XK_Armenian_ligature_ew 0x14a2
+#define XK_Armenian_full_stop 0x14a3
+#define XK_Armenian_verjaket 0x14a3
+#define XK_Armenian_parenright 0x14a4
+#define XK_Armenian_parenleft 0x14a5
+#define XK_Armenian_guillemotright 0x14a6
+#define XK_Armenian_guillemotleft 0x14a7
+#define XK_Armenian_em_dash 0x14a8
+#define XK_Armenian_dot 0x14a9
+#define XK_Armenian_mijaket 0x14a9
+#define XK_Armenian_separation_mark 0x14aa
+#define XK_Armenian_but 0x14aa
+#define XK_Armenian_comma 0x14ab
+#define XK_Armenian_en_dash 0x14ac
+#define XK_Armenian_hyphen 0x14ad
+#define XK_Armenian_yentamna 0x14ad
+#define XK_Armenian_ellipsis 0x14ae
+#define XK_Armenian_exclam 0x14af
+#define XK_Armenian_amanak 0x14af
+#define XK_Armenian_accent 0x14b0
+#define XK_Armenian_shesht 0x14b0
+#define XK_Armenian_question 0x14b1
+#define XK_Armenian_paruyk 0x14b1
+#define XK_Armenian_AYB 0x14b2
+#define XK_Armenian_ayb 0x14b3
+#define XK_Armenian_BEN 0x14b4
+#define XK_Armenian_ben 0x14b5
+#define XK_Armenian_GIM 0x14b6
+#define XK_Armenian_gim 0x14b7
+#define XK_Armenian_DA 0x14b8
+#define XK_Armenian_da 0x14b9
+#define XK_Armenian_YECH 0x14ba
+#define XK_Armenian_yech 0x14bb
+#define XK_Armenian_ZA 0x14bc
+#define XK_Armenian_za 0x14bd
+#define XK_Armenian_E 0x14be
+#define XK_Armenian_e 0x14bf
+#define XK_Armenian_AT 0x14c0
+#define XK_Armenian_at 0x14c1
+#define XK_Armenian_TO 0x14c2
+#define XK_Armenian_to 0x14c3
+#define XK_Armenian_ZHE 0x14c4
+#define XK_Armenian_zhe 0x14c5
+#define XK_Armenian_INI 0x14c6
+#define XK_Armenian_ini 0x14c7
+#define XK_Armenian_LYUN 0x14c8
+#define XK_Armenian_lyun 0x14c9
+#define XK_Armenian_KHE 0x14ca
+#define XK_Armenian_khe 0x14cb
+#define XK_Armenian_TSA 0x14cc
+#define XK_Armenian_tsa 0x14cd
+#define XK_Armenian_KEN 0x14ce
+#define XK_Armenian_ken 0x14cf
+#define XK_Armenian_HO 0x14d0
+#define XK_Armenian_ho 0x14d1
+#define XK_Armenian_DZA 0x14d2
+#define XK_Armenian_dza 0x14d3
+#define XK_Armenian_GHAT 0x14d4
+#define XK_Armenian_ghat 0x14d5
+#define XK_Armenian_TCHE 0x14d6
+#define XK_Armenian_tche 0x14d7
+#define XK_Armenian_MEN 0x14d8
+#define XK_Armenian_men 0x14d9
+#define XK_Armenian_HI 0x14da
+#define XK_Armenian_hi 0x14db
+#define XK_Armenian_NU 0x14dc
+#define XK_Armenian_nu 0x14dd
+#define XK_Armenian_SHA 0x14de
+#define XK_Armenian_sha 0x14df
+#define XK_Armenian_VO 0x14e0
+#define XK_Armenian_vo 0x14e1
+#define XK_Armenian_CHA 0x14e2
+#define XK_Armenian_cha 0x14e3
+#define XK_Armenian_PE 0x14e4
+#define XK_Armenian_pe 0x14e5
+#define XK_Armenian_JE 0x14e6
+#define XK_Armenian_je 0x14e7
+#define XK_Armenian_RA 0x14e8
+#define XK_Armenian_ra 0x14e9
+#define XK_Armenian_SE 0x14ea
+#define XK_Armenian_se 0x14eb
+#define XK_Armenian_VEV 0x14ec
+#define XK_Armenian_vev 0x14ed
+#define XK_Armenian_TYUN 0x14ee
+#define XK_Armenian_tyun 0x14ef
+#define XK_Armenian_RE 0x14f0
+#define XK_Armenian_re 0x14f1
+#define XK_Armenian_TSO 0x14f2
+#define XK_Armenian_tso 0x14f3
+#define XK_Armenian_VYUN 0x14f4
+#define XK_Armenian_vyun 0x14f5
+#define XK_Armenian_PYUR 0x14f6
+#define XK_Armenian_pyur 0x14f7
+#define XK_Armenian_KE 0x14f8
+#define XK_Armenian_ke 0x14f9
+#define XK_Armenian_O 0x14fa
+#define XK_Armenian_o 0x14fb
+#define XK_Armenian_FE 0x14fc
+#define XK_Armenian_fe 0x14fd
+#define XK_Armenian_apostrophe 0x14fe
+#define XK_Armenian_section_sign 0x14ff
+#endif /* XK_ARMENIAN */
+
+/*
+ * Georgian
+ * Byte 3 = 0x15
+ */
+
+#define XK_GEORGIAN
+#ifdef XK_GEORGIAN
+#define XK_Georgian_an 0x15d0
+#define XK_Georgian_ban 0x15d1
+#define XK_Georgian_gan 0x15d2
+#define XK_Georgian_don 0x15d3
+#define XK_Georgian_en 0x15d4
+#define XK_Georgian_vin 0x15d5
+#define XK_Georgian_zen 0x15d6
+#define XK_Georgian_tan 0x15d7
+#define XK_Georgian_in 0x15d8
+#define XK_Georgian_kan 0x15d9
+#define XK_Georgian_las 0x15da
+#define XK_Georgian_man 0x15db
+#define XK_Georgian_nar 0x15dc
+#define XK_Georgian_on 0x15dd
+#define XK_Georgian_par 0x15de
+#define XK_Georgian_zhar 0x15df
+#define XK_Georgian_rae 0x15e0
+#define XK_Georgian_san 0x15e1
+#define XK_Georgian_tar 0x15e2
+#define XK_Georgian_un 0x15e3
+#define XK_Georgian_phar 0x15e4
+#define XK_Georgian_khar 0x15e5
+#define XK_Georgian_ghan 0x15e6
+#define XK_Georgian_qar 0x15e7
+#define XK_Georgian_shin 0x15e8
+#define XK_Georgian_chin 0x15e9
+#define XK_Georgian_can 0x15ea
+#define XK_Georgian_jil 0x15eb
+#define XK_Georgian_cil 0x15ec
+#define XK_Georgian_char 0x15ed
+#define XK_Georgian_xan 0x15ee
+#define XK_Georgian_jhan 0x15ef
+#define XK_Georgian_hae 0x15f0
+#define XK_Georgian_he 0x15f1
+#define XK_Georgian_hie 0x15f2
+#define XK_Georgian_we 0x15f3
+#define XK_Georgian_har 0x15f4
+#define XK_Georgian_hoe 0x15f5
+#define XK_Georgian_fi 0x15f6
+#endif /* XK_GEORGIAN */
+
+/*
+ * Azeri (and other Turkic or Caucasian languages of ex-USSR)
+ * Byte 3 = 0x16
+ */
+
+#define XK_CAUCASUS
+#ifdef XK_CAUCASUS
+/* latin */
+#define XK_Ccedillaabovedot 0x16a2
+#define XK_Xabovedot 0x16a3
+#define XK_Qabovedot 0x16a5
+#define XK_Ibreve 0x16a6
+#define XK_IE 0x16a7
+#define XK_UO 0x16a8
+#define XK_Zstroke 0x16a9
+#define XK_Gcaron 0x16aa
+#define XK_Obarred 0x16af
+#define XK_ccedillaabovedot 0x16b2
+#define XK_xabovedot 0x16b3
+#define XK_Ocaron 0x16b4
+#define XK_qabovedot 0x16b5
+#define XK_ibreve 0x16b6
+#define XK_ie 0x16b7
+#define XK_uo 0x16b8
+#define XK_zstroke 0x16b9
+#define XK_gcaron 0x16ba
+#define XK_ocaron 0x16bd
+#define XK_obarred 0x16bf
+#define XK_SCHWA 0x16c6
+#define XK_schwa 0x16f6
+/* those are not really Caucasus, but I put them here for now */
+/* For Inupiak */
+#define XK_Lbelowdot 0x16d1
+#define XK_Lstrokebelowdot 0x16d2
+#define XK_lbelowdot 0x16e1
+#define XK_lstrokebelowdot 0x16e2
+/* For Guarani */
+#define XK_Gtilde 0x16d3
+#define XK_gtilde 0x16e3
+#endif /* XK_CAUCASUS */
+
+/*
+ * Vietnamese
+ * Byte 3 = 0x1e
+ */
+
+#define XK_VIETNAMESE
+#ifdef XK_VIETNAMESE
+#define XK_Abelowdot 0x1ea0
+#define XK_abelowdot 0x1ea1
+#define XK_Ahook 0x1ea2
+#define XK_ahook 0x1ea3
+#define XK_Acircumflexacute 0x1ea4
+#define XK_acircumflexacute 0x1ea5
+#define XK_Acircumflexgrave 0x1ea6
+#define XK_acircumflexgrave 0x1ea7
+#define XK_Acircumflexhook 0x1ea8
+#define XK_acircumflexhook 0x1ea9
+#define XK_Acircumflextilde 0x1eaa
+#define XK_acircumflextilde 0x1eab
+#define XK_Acircumflexbelowdot 0x1eac
+#define XK_acircumflexbelowdot 0x1ead
+#define XK_Abreveacute 0x1eae
+#define XK_abreveacute 0x1eaf
+#define XK_Abrevegrave 0x1eb0
+#define XK_abrevegrave 0x1eb1
+#define XK_Abrevehook 0x1eb2
+#define XK_abrevehook 0x1eb3
+#define XK_Abrevetilde 0x1eb4
+#define XK_abrevetilde 0x1eb5
+#define XK_Abrevebelowdot 0x1eb6
+#define XK_abrevebelowdot 0x1eb7
+#define XK_Ebelowdot 0x1eb8
+#define XK_ebelowdot 0x1eb9
+#define XK_Ehook 0x1eba
+#define XK_ehook 0x1ebb
+#define XK_Etilde 0x1ebc
+#define XK_etilde 0x1ebd
+#define XK_Ecircumflexacute 0x1ebe
+#define XK_ecircumflexacute 0x1ebf
+#define XK_Ecircumflexgrave 0x1ec0
+#define XK_ecircumflexgrave 0x1ec1
+#define XK_Ecircumflexhook 0x1ec2
+#define XK_ecircumflexhook 0x1ec3
+#define XK_Ecircumflextilde 0x1ec4
+#define XK_ecircumflextilde 0x1ec5
+#define XK_Ecircumflexbelowdot 0x1ec6
+#define XK_ecircumflexbelowdot 0x1ec7
+#define XK_Ihook 0x1ec8
+#define XK_ihook 0x1ec9
+#define XK_Ibelowdot 0x1eca
+#define XK_ibelowdot 0x1ecb
+#define XK_Obelowdot 0x1ecc
+#define XK_obelowdot 0x1ecd
+#define XK_Ohook 0x1ece
+#define XK_ohook 0x1ecf
+#define XK_Ocircumflexacute 0x1ed0
+#define XK_ocircumflexacute 0x1ed1
+#define XK_Ocircumflexgrave 0x1ed2
+#define XK_ocircumflexgrave 0x1ed3
+#define XK_Ocircumflexhook 0x1ed4
+#define XK_ocircumflexhook 0x1ed5
+#define XK_Ocircumflextilde 0x1ed6
+#define XK_ocircumflextilde 0x1ed7
+#define XK_Ocircumflexbelowdot 0x1ed8
+#define XK_ocircumflexbelowdot 0x1ed9
+#define XK_Ohornacute 0x1eda
+#define XK_ohornacute 0x1edb
+#define XK_Ohorngrave 0x1edc
+#define XK_ohorngrave 0x1edd
+#define XK_Ohornhook 0x1ede
+#define XK_ohornhook 0x1edf
+#define XK_Ohorntilde 0x1ee0
+#define XK_ohorntilde 0x1ee1
+#define XK_Ohornbelowdot 0x1ee2
+#define XK_ohornbelowdot 0x1ee3
+#define XK_Ubelowdot 0x1ee4
+#define XK_ubelowdot 0x1ee5
+#define XK_Uhook 0x1ee6
+#define XK_uhook 0x1ee7
+#define XK_Uhornacute 0x1ee8
+#define XK_uhornacute 0x1ee9
+#define XK_Uhorngrave 0x1eea
+#define XK_uhorngrave 0x1eeb
+#define XK_Uhornhook 0x1eec
+#define XK_uhornhook 0x1eed
+#define XK_Uhorntilde 0x1eee
+#define XK_uhorntilde 0x1eef
+#define XK_Uhornbelowdot 0x1ef0
+#define XK_uhornbelowdot 0x1ef1
+#define XK_Ybelowdot 0x1ef4
+#define XK_ybelowdot 0x1ef5
+#define XK_Yhook 0x1ef6
+#define XK_yhook 0x1ef7
+#define XK_Ytilde 0x1ef8
+#define XK_ytilde 0x1ef9
+#define XK_Ohorn 0x1efa /* U+01a0 */
+#define XK_ohorn 0x1efb /* U+01a1 */
+#define XK_Uhorn 0x1efc /* U+01af */
+#define XK_uhorn 0x1efd /* U+01b0 */
+
+#define XK_combining_tilde 0x1e9f /* U+0303 */
+#define XK_combining_grave 0x1ef2 /* U+0300 */
+#define XK_combining_acute 0x1ef3 /* U+0301 */
+#define XK_combining_hook 0x1efe /* U+0309 */
+#define XK_combining_belowdot 0x1eff /* U+0323 */
+#endif /* XK_VIETNAMESE */
+
+#define XK_CURRENCY
+#ifdef XK_CURRENCY
+#define XK_EcuSign 0x20a0
+#define XK_ColonSign 0x20a1
+#define XK_CruzeiroSign 0x20a2
+#define XK_FFrancSign 0x20a3
+#define XK_LiraSign 0x20a4
+#define XK_MillSign 0x20a5
+#define XK_NairaSign 0x20a6
+#define XK_PesetaSign 0x20a7
+#define XK_RupeeSign 0x20a8
+#define XK_WonSign 0x20a9
+#define XK_NewSheqelSign 0x20aa
+#define XK_DongSign 0x20ab
+#define XK_EuroSign 0x20ac
+#endif
diff --git a/epan/dissectors/packet-x11.c b/epan/dissectors/packet-x11.c
new file mode 100644
index 0000000000..dc7a16751c
--- /dev/null
+++ b/epan/dissectors/packet-x11.c
@@ -0,0 +1,5382 @@
+/* packet-x11.c
+ * Routines for X11 dissection
+ * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
+ * Copyright 2003, Michael Shuldman
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* TODO (in no particular order):
+ *
+ * - keep track of Atom creation by server to be able to display
+ * non-predefined atoms
+ * - Idem for keysym <-> keycode ???
+ * - Idem for fonts
+ * - Subtree the request ids (that is x11.create-window.window and
+ * x11.change-window.window should be distinct), and add hidden fields
+ * (so we still have x11.window).
+ * - add hidden fields so we can have x11.circulate-window in addition to
+ * x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
+ * now)
+ * - add hidden fields so we have x11.listOfStuff.length
+ * - use a faster scheme that linear list searching for the opcode.
+ * - correct display of Unicode chars.
+ * - Not everything is homogeneous, in particular the handling of items in
+ * list is a total mess.
+ */
+
+/* By the way, I wrote a program to generate every request and test
+ * that stuff. If you're interested, you can get it at
+ * http://tronche.com/gui/x/
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include "prefs.h"
+#include "packet-frame.h"
+#include "packet-x11-keysymdef.h"
+
+#define cVALS(x) (const value_string*)(x)
+
+/*
+ * Data structure associated with a conversation; keeps track of the
+ * request for which we're expecting a reply, the frame number of
+ * the initial connection request, and the byte order of the connection.
+ *
+ * An opcode of -3 means we haven't yet seen any requests yet.
+ * An opcode of -2 means we're not expecting a reply (unused).
+ * An opcode of -1 means we're waiting for a reply to the initial
+ * connection request.
+ * An opcode of 0 means the request was not seen (or unknown).
+ * Other values are the opcode of the request for which we're expecting
+ * a reply.
+ *
+ */
+#define NOTHING_SEEN -3
+#define NOTHING_EXPECTED -2
+#define INITIAL_CONN -1
+#define UNKNOWN_OPCODE 0
+
+#define MAX_OPCODES (255 + 1) /* 255 + INITIAL_CONN */
+
+#define BYTE_ORDER_BE 0
+#define BYTE_ORDER_LE 1
+#define BYTE_ORDER_UNKNOWN -1
+
+static const char *modifiers[] = {
+ "Shift",
+ "Lock",
+ "Control",
+ "Mod1",
+ "Mod2",
+ "Mod3",
+ "Mod4",
+ "Mod5"
+};
+
+/* Keymasks. From <X11/X.h>. */
+#define ShiftMask (1<<0)
+#define LockMask (1<<1)
+#define ControlMask (1<<2)
+#define Mod1Mask (1<<3)
+#define Mod2Mask (1<<4)
+#define Mod3Mask (1<<5)
+#define Mod4Mask (1<<6)
+#define Mod5Mask (1<<7)
+
+static const int modifiermask[] = { ShiftMask, LockMask, ControlMask,
+Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
+
+/* from <X11/X.h> */
+#define NoSymbol 0L /* special KeySym */
+
+typedef struct {
+ GHashTable *seqtable; /* hashtable of sequencenumber <-> opcode. */
+ GHashTable *valtable;/* hashtable of sequencenumber <-> &opcode_vals */
+ /* major opcodes including extensions (NULL terminated) */
+ value_string opcode_vals[MAX_OPCODES+1];
+ int sequencenumber; /* sequencenumber of current packet. */
+ guint32 iconn_frame; /* frame # of initial connection request */
+ guint32 iconn_reply; /* frame # of initial connection reply */
+ int byte_order; /* byte order of connection */
+ gboolean resync; /* resynchronization of sequence number performed */
+
+ int *keycodemap[256]; /* keycode to keysymvalue map. */
+ int keysyms_per_keycode;
+ int first_keycode;
+ int *modifiermap[array_length(modifiers)];/* modifier to keycode.*/
+ int keycodes_per_modifier;
+
+ union {
+ struct {
+ int first_keycode;
+ } GetKeyboardMapping;
+ } request;
+} x11_conv_data_t;
+
+static GMemChunk *x11_state_chunk = NULL;
+
+
+/* Initialize the protocol and registered fields */
+static int proto_x11 = -1;
+
+#include "x11-declarations.h"
+
+/* Initialize the subtree pointers */
+static gint ett_x11 = -1;
+static gint ett_x11_color_flags = -1;
+static gint ett_x11_list_of_arc = -1;
+static gint ett_x11_arc = -1;
+static gint ett_x11_list_of_atom = -1;
+static gint ett_x11_list_of_card32 = -1;
+static gint ett_x11_list_of_color_item = -1;
+static gint ett_x11_color_item = -1;
+static gint ett_x11_list_of_keycode = -1;
+static gint ett_x11_list_of_keysyms = -1;
+static gint ett_x11_keysym = -1;
+static gint ett_x11_list_of_point = -1;
+static gint ett_x11_point = -1;
+static gint ett_x11_list_of_rectangle = -1;
+static gint ett_x11_rectangle = -1;
+static gint ett_x11_list_of_segment = -1;
+static gint ett_x11_segment = -1;
+static gint ett_x11_list_of_string8 = -1;
+static gint ett_x11_list_of_text_item = -1;
+static gint ett_x11_text_item = -1;
+static gint ett_x11_gc_value_mask = -1; /* XXX - unused */
+static gint ett_x11_event_mask = -1; /* XXX - unused */
+static gint ett_x11_do_not_propagate_mask = -1; /* XXX - unused */
+static gint ett_x11_set_of_key_mask = -1;
+static gint ett_x11_pointer_event_mask = -1; /* XXX - unused */
+static gint ett_x11_window_value_mask = -1; /* XXX - unused */
+static gint ett_x11_configure_window_mask = -1; /* XXX - unused */
+static gint ett_x11_keyboard_value_mask = -1; /* XXX - unused */
+static gint ett_x11_same_screen_focus = -1;
+
+/* desegmentation of X11 messages */
+static gboolean x11_desegment = TRUE;
+
+static dissector_handle_t data_handle;
+
+#define TCP_PORT_X11 6000
+#define TCP_PORT_X11_2 6001
+#define TCP_PORT_X11_3 6002
+
+/*
+ * Round a length to a multiple of 4 bytes.
+ */
+#define ROUND_LENGTH(n) ((((n) + 3)/4) * 4)
+
+/************************************************************************
+ *** ***
+ *** E N U M T A B L E S D E F I N I T I O N S ***
+ *** ***
+ ************************************************************************/
+
+static const value_string byte_order_vals[] = {
+ { 'B', "Big-endian" },
+ { 'l', "Little-endian" },
+ { 0, NULL }
+};
+
+static const value_string image_byte_order_vals[] = {
+ { 0, "LSBFirst" },
+ { 1, "MSBFirst" },
+ { 0, NULL }
+};
+
+static const value_string access_mode_vals[] = {
+ { 0, "Disable" },
+ { 1, "Enable" },
+ { 0, NULL }
+};
+
+static const value_string all_temporary_vals[] = {
+ { 0, "AllTemporary" },
+ { 0, NULL }
+};
+
+static const value_string alloc_vals[] = {
+ { 0, "None" },
+ { 1, "All" },
+ { 0, NULL }
+};
+
+static const value_string allow_events_mode_vals[] = {
+ { 0, "AsyncPointer" },
+ { 1, "SyncPointer" },
+ { 2, "ReplayPointer" },
+ { 3, "AsyncKeyboard" },
+ { 4, "SyncKeyboard" },
+ { 5, "ReplayKeyboard" },
+ { 6, "AsyncBoth" },
+ { 7, "SyncBoth" },
+ { 0, NULL }
+};
+
+static const value_string arc_mode_vals[] = {
+ { 0, "Chord" },
+ { 1, "PieSlice" },
+ { 0, NULL }
+};
+
+static const char *atom_predefined_interpretation[] = {
+ "<error>",
+ "PRIMARY",
+ "SECONDARY",
+ "ARC",
+ "ATOM",
+ "BITMAP",
+ "CARDINAL",
+ "COLORMAP",
+ "CURSOR",
+ "CUT_BUFFER0",
+ "CUT_BUFFER1",
+ "CUT_BUFFER2",
+ "CUT_BUFFER3",
+ "CUT_BUFFER4",
+ "CUT_BUFFER5",
+ "CUT_BUFFER6",
+ "CUT_BUFFER7",
+ "DRAWABLE",
+ "FONT",
+ "INTEGER",
+ "PIXMAP",
+ "POINT",
+ "RECTANGLE",
+ "RESOURCE_MANAGER",
+ "RGB_COLOR_MAP",
+ "RGB_BEST_MAP",
+ "RGB_BLUE_MAP",
+ "RGB_DEFAULT_MAP",
+ "RGB_GRAY_MAP",
+ "RGB_GREEN_MAP",
+ "RGB_RED_MAP",
+ "STRING",
+ "VISUALID",
+ "WINDOW",
+ "WM_COMMAND",
+ "WM_HINTS",
+ "WM_CLIENT_MACHINE",
+ "WM_ICON_NAME",
+ "WM_ICON_SIZE",
+ "WM_NAME",
+ "WM_NORMAL_HINTS",
+ "WM_SIZE_HINTS",
+ "WM_ZOOM_HINTS",
+ "MIN_SPACE",
+ "NORM_SPACE",
+ "MAX_SPACE",
+ "END_SPACE",
+ "SUPERSCRIPT_X",
+ "SUPERSCRIPT_Y",
+ "SUBSCRIPT_X",
+ "SUBSCRIPT_Y",
+ "UNDERLINE_POSITION",
+ "UNDERLINE_THICKNESS",
+ "STRIKEOUT_ASCENT",
+ "STRIKEOUT_DESCENT",
+ "ITALIC_ANGLE",
+ "X_HEIGHT",
+ "QUAD_WIDTH",
+ "WEIGHT",
+ "POINT_SIZE",
+ "RESOLUTION",
+ "COPYRIGHT",
+ "NOTICE",
+ "FONT_NAME",
+ "FAMILY_NAME",
+ "FULL_NAME",
+ "CAP_HEIGHT",
+ "WM_CLASS",
+ "WM_TRANSIENT_FOR",
+};
+
+static const value_string auto_repeat_mode_vals[] = {
+ { 0, "Off" },
+ { 1, "On" },
+ { 2, "Default" },
+ { 0, NULL }
+};
+
+static const value_string background_pixmap_vals[] = {
+ { 0, "None" },
+ { 1, "ParentRelative" },
+ { 0, NULL }
+};
+
+static const value_string backing_store_vals[] = {
+ { 0, "NotUseful" },
+ { 1, "WhenMapped" },
+ { 2, "Always" },
+ { 0, NULL }
+};
+
+static const value_string border_pixmap_vals[] = {
+ { 0, "CopyFromParent" },
+ { 0, NULL }
+};
+
+static const value_string button_vals[] = {
+ { 0x8000, "AnyButton" },
+ { 0, NULL }
+};
+
+static const value_string cap_style_vals[] = {
+ { 0, "NotLast" },
+ { 1, "Butt" },
+ { 2, "Round" },
+ { 3, "Projecting" },
+ { 0, NULL }
+};
+
+static const value_string class_vals[] = {
+ { 0, "Cursor" },
+ { 1, "Tile" },
+ { 2, "Stipple" },
+ { 0, NULL }
+};
+
+static const value_string close_down_mode_vals[] = {
+ { 0, "Destroy" },
+ { 1, "RetainPermanent" },
+ { 2, "RetainTemporary" },
+ { 0, NULL }
+};
+
+static const value_string colormap_state_vals[] = {
+ { 0, "Uninstalled" },
+ { 1, "Installed" },
+ { 0, NULL }
+};
+
+static const value_string coordinate_mode_vals[] = {
+ { 0, "Origin" },
+ { 1, "Previous" },
+ { 0, NULL }
+};
+
+static const value_string destination_vals[] = {
+ { 0, "PointerWindow" },
+ { 1, "InputFocus" },
+ { 0, NULL }
+};
+
+static const value_string direction_vals[] = {
+ { 0, "RaiseLowest" },
+ { 1, "LowerHighest" },
+ { 0, NULL }
+};
+
+static const value_string event_detail_vals[] = {
+ { 0, "Ancestor" },
+ { 1, "Virtual" },
+ { 2, "Inferior" },
+ { 3, "Nonlinear" },
+ { 4, "NonlinearVirtual" },
+ { 0, NULL }
+};
+
+#define FAMILY_INTERNET 0
+#define FAMILY_DECNET 1
+#define FAMILY_CHAOS 2
+
+static const value_string family_vals[] = {
+ { FAMILY_INTERNET, "Internet" },
+ { FAMILY_DECNET, "DECnet" },
+ { FAMILY_CHAOS, "Chaos" },
+ { 0, NULL }
+};
+
+static const value_string fill_rule_vals[] = {
+ { 0, "EvenOdd" },
+ { 1, "Winding" },
+ { 0, NULL }
+};
+
+static const value_string fill_style_vals[] = {
+ { 0, "Solid" },
+ { 1, "Tiled" },
+ { 2, "Stippled" },
+ { 3, "OpaqueStippled" },
+ { 0, NULL }
+};
+
+static const value_string focus_detail_vals[] = {
+ { 0, "Ancestor" },
+ { 1, "Virtual" },
+ { 2, "Inferior" },
+ { 3, "Nonlinear" },
+ { 4, "NonlinearVirtual" },
+ { 5, "Pointer" },
+ { 6, "PointerRoot" },
+ { 7, "None" },
+ { 0, NULL }
+};
+
+static const value_string focus_mode_vals[] = {
+ { 0, "Normal" },
+ { 1, "Grab" },
+ { 2, "Ungrab" },
+ { 3, "WhileGrabbed" },
+ { 0, NULL }
+};
+
+static const value_string focus_vals[] = {
+ { 0, "None" },
+ { 1, "PointerRoot" },
+ { 0, NULL }
+};
+
+static const value_string function_vals[] = {
+ { 0, "Clear" },
+ { 1, "And" },
+ { 2, "AndReverse" },
+ { 3, "Copy" },
+ { 4, "AndInverted" },
+ { 5, "NoOp" },
+ { 6, "Xor" },
+ { 7, "Or" },
+ { 8, "Nor" },
+ { 9, "Equiv" },
+ { 10, "Invert" },
+ { 11, "OrReverse" },
+ { 12, "CopyInverted" },
+ { 13, "OrInverted" },
+ { 14, "Nand" },
+ { 15, "Set" },
+ { 0, NULL }
+};
+
+static const value_string grab_mode_vals[] = {
+ { 0, "Normal" },
+ { 1, "Grab" },
+ { 2, "Ungrab" },
+ { 0, NULL }
+};
+
+static const value_string grab_status_vals[] = {
+ { 0, "Success" },
+ { 1, "AlreadyGrabbed" },
+ { 2, "InvalidTime" },
+ { 3, "NotViewable" },
+ { 4, "Frozen" },
+ { 0, NULL }
+};
+
+static const value_string gravity_vals[] = {
+ { 1, "NorthWest" },
+ { 2, "North" },
+ { 3, "NorthEast" },
+ { 4, "West" },
+ { 5, "Center" },
+ { 6, "East" },
+ { 7, "SouthWest" },
+ { 8, "South" },
+ { 9, "SouthEast" },
+ { 10, "Static" },
+ { 0, NULL }
+};
+
+static const value_string image_format_vals[] = {
+ { 0, "Bitmap" },
+ { 1, "XYPixmap" },
+ { 2, "ZPixmap" },
+ { 0, NULL }
+};
+
+static const value_string image_pixmap_format_vals[] = {
+ { 1, "XYPixmap" },
+ { 2, "ZPixmap" },
+ { 0, NULL }
+};
+
+static const value_string join_style_vals[] = {
+ { 0, "Miter" },
+ { 1, "Round" },
+ { 2, "Bevel" },
+ { 0, NULL }
+};
+
+static const value_string key_vals[] = {
+ { 0, "AnyKey" },
+ { 0, NULL }
+};
+
+#include "packet-x11-keysym.h"
+
+static const value_string line_style_vals[] = {
+ { 0, "Solid" },
+ { 1, "OnOffDash" },
+ { 2, "DoubleDash" },
+ { 0, NULL }
+};
+
+static const value_string mode_vals[] = {
+ { 0, "Replace" },
+ { 1, "Prepend" },
+ { 2, "Append" },
+ { 0, NULL }
+};
+
+static const value_string on_off_vals[] = {
+ { 0, "Off" },
+ { 1, "On" },
+ { 0, NULL }
+};
+
+static const value_string place_vals[] = {
+ { 0, "Top" },
+ { 1, "Bottom" },
+ { 0, NULL }
+};
+
+static const value_string property_state_vals[] = {
+ { 0, "NewValue" },
+ { 1, "Deleted" },
+ { 0, NULL }
+};
+
+static const value_string visibility_state_vals[] = {
+ { 0, "Unobscured" },
+ { 1, "PartiallyObscured" },
+ { 2, "FullyObscured" },
+ { 0, NULL }
+};
+
+/* Requestcodes. From <X11/Xproto.h>. */
+#define X_CreateWindow 1
+#define X_ChangeWindowAttributes 2
+#define X_GetWindowAttributes 3
+#define X_DestroyWindow 4
+#define X_DestroySubwindows 5
+#define X_ChangeSaveSet 6
+#define X_ReparentWindow 7
+#define X_MapWindow 8
+#define X_MapSubwindows 9
+#define X_UnmapWindow 10
+#define X_UnmapSubwindows 11
+#define X_ConfigureWindow 12
+#define X_CirculateWindow 13
+#define X_GetGeometry 14
+#define X_QueryTree 15
+#define X_InternAtom 16
+#define X_GetAtomName 17
+#define X_ChangeProperty 18
+#define X_DeleteProperty 19
+#define X_GetProperty 20
+#define X_ListProperties 21
+#define X_SetSelectionOwner 22
+#define X_GetSelectionOwner 23
+#define X_ConvertSelection 24
+#define X_SendEvent 25
+#define X_GrabPointer 26
+#define X_UngrabPointer 27
+#define X_GrabButton 28
+#define X_UngrabButton 29
+#define X_ChangeActivePointerGrab 30
+#define X_GrabKeyboard 31
+#define X_UngrabKeyboard 32
+#define X_GrabKey 33
+#define X_UngrabKey 34
+#define X_AllowEvents 35
+#define X_GrabServer 36
+#define X_UngrabServer 37
+#define X_QueryPointer 38
+#define X_GetMotionEvents 39
+#define X_TranslateCoords 40
+#define X_WarpPointer 41
+#define X_SetInputFocus 42
+#define X_GetInputFocus 43
+#define X_QueryKeymap 44
+#define X_OpenFont 45
+#define X_CloseFont 46
+#define X_QueryFont 47
+#define X_QueryTextExtents 48
+#define X_ListFonts 49
+#define X_ListFontsWithInfo 50
+#define X_SetFontPath 51
+#define X_GetFontPath 52
+#define X_CreatePixmap 53
+#define X_FreePixmap 54
+#define X_CreateGC 55
+#define X_ChangeGC 56
+#define X_CopyGC 57
+#define X_SetDashes 58
+#define X_SetClipRectangles 59
+#define X_FreeGC 60
+#define X_ClearArea 61
+#define X_CopyArea 62
+#define X_CopyPlane 63
+#define X_PolyPoint 64
+#define X_PolyLine 65
+#define X_PolySegment 66
+#define X_PolyRectangle 67
+#define X_PolyArc 68
+#define X_FillPoly 69
+#define X_PolyFillRectangle 70
+#define X_PolyFillArc 71
+#define X_PutImage 72
+#define X_GetImage 73
+#define X_PolyText8 74
+#define X_PolyText16 75
+#define X_ImageText8 76
+#define X_ImageText16 77
+#define X_CreateColormap 78
+#define X_FreeColormap 79
+#define X_CopyColormapAndFree 80
+#define X_InstallColormap 81
+#define X_UninstallColormap 82
+#define X_ListInstalledColormaps 83
+#define X_AllocColor 84
+#define X_AllocNamedColor 85
+#define X_AllocColorCells 86
+#define X_AllocColorPlanes 87
+#define X_FreeColors 88
+#define X_StoreColors 89
+#define X_StoreNamedColor 90
+#define X_QueryColors 91
+#define X_LookupColor 92
+#define X_CreateCursor 93
+#define X_CreateGlyphCursor 94
+#define X_FreeCursor 95
+#define X_RecolorCursor 96
+#define X_QueryBestSize 97
+#define X_QueryExtension 98
+#define X_ListExtensions 99
+#define X_ChangeKeyboardMapping 100
+#define X_GetKeyboardMapping 101
+#define X_ChangeKeyboardControl 102
+#define X_GetKeyboardControl 103
+#define X_Bell 104
+#define X_ChangePointerControl 105
+#define X_GetPointerControl 106
+#define X_SetScreenSaver 107
+#define X_GetScreenSaver 108
+#define X_ChangeHosts 109
+#define X_ListHosts 110
+#define X_SetAccessControl 111
+#define X_SetCloseDownMode 112
+#define X_KillClient 113
+#define X_RotateProperties 114
+#define X_ForceScreenSaver 115
+#define X_SetPointerMapping 116
+#define X_GetPointerMapping 117
+#define X_SetModifierMapping 118
+#define X_GetModifierMapping 119
+#define X_NoOperation 127
+#define X_FirstExtension 128
+#define X_LastExtension 255
+
+static const value_string opcode_vals[] = {
+ { INITIAL_CONN, "Initial connection request" },
+ { X_CreateWindow, "CreateWindow" },
+ { X_ChangeWindowAttributes, "ChangeWindowAttributes" },
+ { X_GetWindowAttributes, "GetWindowAttributes" },
+ { X_DestroyWindow, "DestroyWindow" },
+ { X_DestroySubwindows, "DestroySubwindows" },
+ { X_ChangeSaveSet, "ChangeSaveSet" },
+ { X_ReparentWindow, "ReparentWindow" },
+ { X_MapWindow, "MapWindow" },
+ { X_MapSubwindows, "MapSubwindows" },
+ { X_UnmapWindow, "UnmapWindow" },
+ { X_UnmapSubwindows, "UnmapSubwindows" },
+ { X_ConfigureWindow, "ConfigureWindow" },
+ { X_CirculateWindow, "CirculateWindow" },
+ { X_GetGeometry, "GetGeometry" },
+ { X_QueryTree, "QueryTree" },
+ { X_InternAtom, "InternAtom" },
+ { X_GetAtomName, "GetAtomName" },
+ { X_ChangeProperty, "ChangeProperty" },
+ { X_DeleteProperty, "DeleteProperty" },
+ { X_GetProperty, "GetProperty" },
+ { X_ListProperties, "ListProperties" },
+ { X_SetSelectionOwner, "SetSelectionOwner" },
+ { X_GetSelectionOwner, "GetSelectionOwner" },
+ { X_ConvertSelection, "ConvertSelection" },
+ { X_SendEvent, "SendEvent" },
+ { X_GrabPointer, "GrabPointer" },
+ { X_UngrabPointer, "UngrabPointer" },
+ { X_GrabButton, "GrabButton" },
+ { X_UngrabButton, "UngrabButton" },
+ { X_ChangeActivePointerGrab, "ChangeActivePointerGrab" },
+ { X_GrabKeyboard, "GrabKeyboard" },
+ { X_UngrabKeyboard, "UngrabKeyboard" },
+ { X_GrabKey, "GrabKey" },
+ { X_UngrabKey, "UngrabKey" },
+ { X_AllowEvents, "AllowEvents" },
+ { X_GrabServer, "GrabServer" },
+ { X_UngrabServer, "UngrabServer" },
+ { X_QueryPointer, "QueryPointer" },
+ { X_GetMotionEvents, "GetMotionEvents" },
+ { X_TranslateCoords, "TranslateCoordinates" },
+ { X_WarpPointer, "WarpPointer" },
+ { X_SetInputFocus, "SetInputFocus" },
+ { X_GetInputFocus, "GetInputFocus" },
+ { X_QueryKeymap, "QueryKeymap" },
+ { X_OpenFont, "OpenFont" },
+ { X_CloseFont, "CloseFont" },
+ { X_QueryFont, "QueryFont" },
+ { X_QueryTextExtents, "QueryTextExtents" },
+ { X_ListFonts, "ListFonts" },
+ { X_ListFontsWithInfo, "ListFontsWithInfo" },
+ { X_SetFontPath, "SetFontPath" },
+ { X_GetFontPath, "GetFontPath" },
+ { X_CreatePixmap, "CreatePixmap" },
+ { X_FreePixmap, "FreePixmap" },
+ { X_CreateGC, "CreateGC" },
+ { X_ChangeGC, "ChangeGC" },
+ { X_CopyGC, "CopyGC" },
+ { X_SetDashes, "SetDashes" },
+ { X_SetClipRectangles, "SetClipRectangles" },
+ { X_FreeGC, "FreeGC" },
+ { X_ClearArea, "ClearArea" },
+ { X_CopyArea, "CopyArea" },
+ { X_CopyPlane, "CopyPlane" },
+ { X_PolyPoint, "PolyPoint" },
+ { X_PolyLine, "PolyLine" },
+ { X_PolySegment, "PolySegment" },
+ { X_PolyRectangle, "PolyRectangle" },
+ { X_PolyArc, "PolyArc" },
+ { X_FillPoly, "FillPoly" },
+ { X_PolyFillRectangle, "PolyFillRectangle" },
+ { X_PolyFillArc, "PolyFillArc" },
+ { X_PutImage, "PutImage" },
+ { X_GetImage, "GetImage" },
+ { X_PolyText8, "PolyText8" },
+ { X_PolyText16, "PolyText16" },
+ { X_ImageText8, "ImageText8" },
+ { X_ImageText16, "ImageText16" },
+ { X_CreateColormap, "CreateColormap" },
+ { X_FreeColormap, "FreeColormap" },
+ { X_CopyColormapAndFree, "CopyColormapAndFree" },
+ { X_InstallColormap, "InstallColormap" },
+ { X_UninstallColormap, "UninstallColormap" },
+ { X_ListInstalledColormaps, "ListInstalledColormaps" },
+ { X_AllocColor, "AllocColor" },
+ { X_AllocNamedColor, "AllocNamedColor" },
+ { X_AllocColorCells, "AllocColorCells" },
+ { X_AllocColorPlanes, "AllocColorPlanes" },
+ { X_FreeColors, "FreeColors" },
+ { X_StoreColors, "StoreColors" },
+ { X_StoreNamedColor, "StoreNamedColor" },
+ { X_QueryColors, "QueryColors" },
+ { X_LookupColor, "LookupColor" },
+ { X_CreateCursor, "CreateCursor" },
+ { X_CreateGlyphCursor, "CreateGlyphCursor" },
+ { X_FreeCursor, "FreeCursor" },
+ { X_RecolorCursor, "RecolorCursor" },
+ { X_QueryBestSize, "QueryBestSize" },
+ { X_QueryExtension, "QueryExtension" },
+ { X_ListExtensions, "ListExtensions" },
+ { X_ChangeKeyboardMapping, "ChangeKeyboardMapping" },
+ { X_GetKeyboardMapping, "GetKeyboardMapping" },
+ { X_ChangeKeyboardControl, "ChangeKeyboardControl" },
+ { X_GetKeyboardControl, "GetKeyboardControl" },
+ { X_Bell, "Bell" },
+ { X_ChangePointerControl, "ChangePointerControl" },
+ { X_GetPointerControl, "GetPointerControl" },
+ { X_SetScreenSaver, "SetScreenSaver" },
+ { X_GetScreenSaver, "GetScreenSaver" },
+ { X_ChangeHosts, "ChangeHosts" },
+ { X_ListHosts, "ListHosts" },
+ { X_SetAccessControl, "SetAccessControl" },
+ { X_SetCloseDownMode, "SetCloseDownMode" },
+ { X_KillClient, "KillClient" },
+ { X_RotateProperties, "RotateProperties" },
+ { X_ForceScreenSaver, "ForceScreenSaver" },
+ { X_SetPointerMapping, "SetPointerMapping" },
+ { X_GetPointerMapping, "GetPointerMapping" },
+ { X_SetModifierMapping, "SetModifierMapping" },
+ { X_GetModifierMapping, "GetModifierMapping" },
+ { X_NoOperation, "NoOperation" },
+ { 0, NULL }
+};
+
+/* Eventscodes. From <X11/X.h>. */
+#define KeyPress 2
+#define KeyRelease 3
+#define ButtonPress 4
+#define ButtonRelease 5
+#define MotionNotify 6
+#define EnterNotify 7
+#define LeaveNotify 8
+#define FocusIn 9
+#define FocusOut 10
+#define KeymapNotify 11
+#define Expose 12
+#define GraphicsExpose 13
+#define NoExpose 14
+#define VisibilityNotify 15
+#define CreateNotify 16
+#define DestroyNotify 17
+#define UnmapNotify 18
+#define MapNotify 19
+#define MapRequest 20
+#define ReparentNotify 21
+#define ConfigureNotify 22
+#define ConfigureRequest 23
+#define GravityNotify 24
+#define ResizeRequest 25
+#define CirculateNotify 26
+#define CirculateRequest 27
+#define PropertyNotify 28
+#define SelectionClear 29
+#define SelectionRequest 30
+#define SelectionNotify 31
+#define ColormapNotify 32
+#define ClientMessage 33
+#define MappingNotify 34
+#define FirstExtensionEvent 64
+#define LastExtensionEvent 127
+
+static const value_string eventcode_vals[] = {
+ { KeyPress, "KeyPress" },
+ { KeyRelease, "KeyRelease" },
+ { ButtonPress, "ButtonPress" },
+ { ButtonRelease, "ButtonRelease" },
+ { MotionNotify, "MotionNotify" },
+ { EnterNotify, "EnterNotify" },
+ { LeaveNotify, "LeaveNotify" },
+ { FocusIn, "FocusIn" },
+ { FocusOut, "FocusOut" },
+ { KeymapNotify, "KeymapNotify" },
+ { Expose, "Expose" },
+ { GraphicsExpose, "GraphicsExpose" },
+ { NoExpose, "NoExpose" },
+ { VisibilityNotify, "VisibilityNotify" },
+ { CreateNotify, "CreateNotify" },
+ { DestroyNotify, "DestroyNotify" },
+ { UnmapNotify, "UnmapNotify" },
+ { MapNotify, "MapNotify" },
+ { MapRequest, "MapRequest" },
+ { ReparentNotify, "ReparentNotify" },
+ { ConfigureNotify, "ConfigureNotify" },
+ { ConfigureRequest, "ConfigureRequest" },
+ { GravityNotify, "GravityNotify" },
+ { ResizeRequest, "ResizeRequest" },
+ { CirculateNotify, "CirculateNotify" },
+ { CirculateRequest, "CirculateRequest" },
+ { PropertyNotify, "PropertyNotify" },
+ { SelectionClear, "SelectionClear" },
+ { SelectionRequest, "SelectionRequest" },
+ { SelectionNotify, "SelectionNotify" },
+ { ColormapNotify, "ColormapNotify" },
+ { ClientMessage, "ClientMessage" },
+ { MappingNotify, "MappingNotify" },
+ { 0, NULL }
+};
+
+/* Errorcodes. From <X11/X.h> */
+#define Success 0 /* everything's okay */
+#define BadRequest 1 /* bad request code */
+#define BadValue 2 /* int parameter out of range */
+#define BadWindow 3 /* parameter not a Window */
+#define BadPixmap 4 /* parameter not a Pixmap */
+#define BadAtom 5 /* parameter not an Atom */
+#define BadCursor 6 /* parameter not a Cursor */
+#define BadFont 7 /* parameter not a Font */
+#define BadMatch 8 /* parameter mismatch */
+#define BadDrawable 9 /* parameter not a Pixmap or Window */
+#define BadAccess 10 /* depending on context:
+ - key/button already grabbed
+ - attempt to free an illegal
+ cmap entry
+ - attempt to store into a read-only
+ color map entry.
+ - attempt to modify the access control
+ list from other than the local host.
+ */
+#define BadAlloc 11 /* insufficient resources */
+#define BadColor 12 /* no such colormap */
+#define BadGC 13 /* parameter not a GC */
+#define BadIDChoice 14 /* choice not in range or already used */
+#define BadName 15 /* font or color name doesn't exist */
+#define BadLength 16 /* Request length incorrect */
+#define BadImplementation 17 /* server is defective */
+
+#define FirstExtensionError 128
+#define LastExtensionError 255
+
+static const value_string errorcode_vals[] = {
+ { Success, "Success" },
+ { BadRequest, "BadRequest" },
+ { BadValue, "BadValue" },
+ { BadWindow, "BadWindow" },
+ { BadPixmap, "BadPixmap" },
+ { BadAtom, "BadAtom" },
+ { BadCursor, "BadCursor" },
+ { BadFont, "BadFont" },
+ { BadMatch, "BadMatch" },
+ { BadDrawable, "BadDrawable" },
+ { BadAccess, "BadAccess" },
+ { BadAlloc, "BadAlloc" },
+ { BadColor, "BadColor" },
+ { BadGC, "BadGC" },
+ { BadIDChoice, "BadIDChoice" },
+ { BadName, "BadName" },
+ { BadLength, "BadLength" },
+ { BadImplementation, "BadImplementation" },
+ { FirstExtensionError, "FirstExtensionError" },
+ { LastExtensionError, "LastExtensionError" },
+ { 0, NULL }
+};
+
+static const value_string ordering_vals[] = {
+ { 0, "UnSorted" },
+ { 1, "YSorted" },
+ { 2, "YXSorted" },
+ { 3, "YXBanded" },
+ { 0, NULL }
+};
+
+static const value_string plane_mask_vals[] = {
+ { 0xFFFFFFFF, "AllPlanes" },
+ { 0, NULL }
+};
+
+static const value_string pointer_keyboard_mode_vals[] = {
+ { 0, "Synchronous" },
+ { 1, "Asynchronous" },
+ { 0, NULL }
+};
+
+static const value_string revert_to_vals[] = {
+ { 0, "None" },
+ { 1, "PointerRoot" },
+ { 2, "Parent" },
+ { 0, NULL }
+};
+
+static const value_string insert_delete_vals[] = {
+ { 0, "Insert" },
+ { 1, "Delete" },
+ { 0, NULL }
+};
+
+static const value_string screen_saver_mode_vals[] = {
+ { 0, "Reset" },
+ { 1, "Activate" },
+ { 0, NULL }
+};
+
+static const value_string shape_vals[] = {
+ { 0, "Complex" },
+ { 1, "Nonconvex" },
+ { 2, "Convex" },
+ { 0, NULL }
+};
+
+static const value_string stack_mode_vals[] = {
+ { 0, "Above" },
+ { 1, "Below" },
+ { 2, "TopIf" },
+ { 3, "BottomIf" },
+ { 4, "Opposite" },
+ { 0, NULL }
+};
+
+static const value_string subwindow_mode_vals[] = {
+ { 0, "ClipByChildren" },
+ { 1, "IncludeInferiors" },
+ { 0, NULL }
+};
+
+static const value_string window_class_vals[] = {
+ { 0, "CopyFromParent" },
+ { 1, "InputOutput" },
+ { 2, "InputOnly" },
+ { 0, NULL }
+};
+
+static const value_string yes_no_default_vals[] = {
+ { 0, "No" },
+ { 1, "Yes" },
+ { 2, "Default" },
+ { 0, NULL }
+};
+
+static const value_string zero_is_any_property_type_vals[] = {
+ { 0, "AnyPropertyType" },
+ { 0, NULL }
+};
+
+static const value_string zero_is_none_vals[] = {
+ { 0, "None" },
+ { 0, NULL }
+};
+
+/* we have not seen packet before. */
+#define PACKET_IS_NEW(pinfo) \
+ (!((pinfo)->fd->flags.visited))
+
+/************************************************************************
+ *** ***
+ *** F I E L D D E C O D I N G M A C R O S ***
+ *** ***
+ ************************************************************************/
+
+#define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
+#define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
+#define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
+
+#define FIELD8(name) (field8(tvb, offsetp, t, hf_x11_##name, little_endian))
+#define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name, little_endian))
+#define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name, little_endian))
+
+#define BITFIELD(TYPE, position, name) {\
+ int unused;\
+ int save = *offsetp;\
+ proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
+ bitmask_size, little_endian); \
+ if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
+ TYPE(name);\
+ unused = save + 4 - *offsetp;\
+ if (unused)\
+ proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, little_endian);\
+ *offsetp = save + 4;\
+ }\
+}
+
+#define FLAG(position, name) {\
+ proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
+
+#define FLAG_IF_NONZERO(position, name) do {\
+ if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
+ proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); } while (0)
+
+#define ATOM(name) { atom(tvb, offsetp, t, hf_x11_##name, little_endian); }
+#define BITGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Forget"); }
+#define BITMASK(name, size) {\
+ proto_item *ti; \
+ guint32 bitmask_value; \
+ int bitmask_offset; \
+ int bitmask_size; \
+ proto_tree *bitmask_tree; \
+ bitmask_value = ((size == 1) ? (guint32)VALUE8(tvb, *offsetp) : \
+ ((size == 2) ? (guint32)VALUE16(tvb, *offsetp) : \
+ (guint32)VALUE32(tvb, *offsetp))); \
+ bitmask_offset = *offsetp; \
+ bitmask_size = size; \
+ ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
+ bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
+ *offsetp += size;
+#define ENDBITMASK }
+#define BITMASK8(name) BITMASK(name, 1);
+#define BITMASK16(name) BITMASK(name, 2);
+#define BITMASK32(name) BITMASK(name, 4);
+#define BOOL(name) (add_boolean(tvb, offsetp, t, hf_x11_##name))
+#define BUTTON(name) FIELD8(name)
+#define CARD8(name) FIELD8(name)
+#define CARD16(name) (FIELD16(name))
+#define CARD32(name) (FIELD32(name))
+#define COLOR_FLAGS(name) colorFlags(tvb, offsetp, t)
+#define COLORMAP(name) FIELD32(name)
+#define CURSOR(name) FIELD32(name)
+#define DRAWABLE(name) FIELD32(name)
+#define ENUM8(name) (FIELD8(name))
+#define ENUM16(name) (FIELD16(name))
+#define FONT(name) FIELD32(name)
+#define FONTABLE(name) FIELD32(name)
+#define GCONTEXT(name) FIELD32(name)
+#define INT8(name) FIELD8(name)
+#define INT16(name) FIELD16(name)
+#define INT32(name) FIELD32(name)
+#define KEYCODE(name) FIELD8(name)
+#define KEYCODE_DECODED(name, keycode, mask) do { \
+ proto_tree_add_uint_format(t, hf_x11_##name, tvb, offset, 1, \
+ keycode, "keycode: %d (%s)", \
+ keycode, keycode2keysymString(state->keycodemap, \
+ state->first_keycode, state->keysyms_per_keycode, \
+ state->modifiermap, state->keycodes_per_modifier, \
+ keycode, mask)); \
+ ++offset; \
+} while (0)
+
+#define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12, little_endian); }
+#define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
+#define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
+#define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
+#define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4, little_endian); }
+#define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12, little_endian); }
+#define LISTofKEYCODE(map, name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, map, (length), little_endian); }
+#define LISTofKEYSYM(name, map, keycode_first, keycode_count, \
+keysyms_per_keycode) {\
+ listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, map, (keycode_first), (keycode_count), (keysyms_per_keycode), little_endian); }
+#define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
+#define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
+#define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
+#define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length), little_endian); }
+#define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset, little_endian); }
+#define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset, little_endian); }
+#define OPCODE() { opcode = FIELD8(opcode); }
+#define PIXMAP(name) { FIELD32(name); }
+#define REQUEST_LENGTH() (requestLength(tvb, offsetp, t, little_endian))
+#define SETofEVENT(name) { setOfEvent(tvb, offsetp, t, little_endian); }
+#define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t, little_endian);}
+#define SETofKEYMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 0); }
+#define SETofKEYBUTMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 1); }
+#define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t, little_endian); }
+#define STRING8(name, length) { string8(tvb, offsetp, t, hf_x11_##name, length); }
+#define STRING16(name, length) { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length, little_endian); }
+#define TIMESTAMP(name){ timestamp(tvb, offsetp, t, hf_x11_##name, little_endian); }
+#define UNDECODED(x) { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, x, little_endian); *offsetp += x; }
+#define UNUSED(x) { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, x, little_endian); *offsetp += x; }
+#define PAD() { if (next_offset - *offsetp > 0) proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, next_offset - *offsetp, little_endian); *offsetp = next_offset; }
+#define WINDOW(name) { FIELD32(name); }
+#define WINGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Unmap"); }
+
+#define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
+ proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
+ v ? "" : " (CopyFromParent)"); *offsetp += 4; }
+#define REPLY(name) FIELD8(name);
+#define REPLYLENGTH(name) FIELD32(name);
+
+#define EVENTCONTENTS_COMMON() do { \
+ TIMESTAMP(time); \
+ WINDOW(rootwindow); \
+ WINDOW(eventwindow); \
+ WINDOW(childwindow); \
+ INT16(root_x); \
+ INT16(root_y); \
+ INT16(event_x); \
+ INT16(event_y); \
+ setOfKeyButMask(tvb, offsetp, t, little_endian, 1); \
+} while (0)
+
+#define SEQUENCENUMBER_REPLY(name) do { \
+ guint16 seqno; \
+ \
+ seqno = VALUE16(tvb, *offsetp); \
+ proto_tree_add_uint_format(t, hf_x11_reply_##name, tvb, \
+ *offsetp, sizeof(seqno), seqno, \
+ "sequencenumber: %d (%s)", \
+ (int)seqno, \
+ val_to_str(opcode, state->opcode_vals, "<Unknown opcode %d>")); \
+ *offsetp += sizeof(seqno); \
+} while (0)
+
+#define REPLYCONTENTS_COMMON() do { \
+ REPLY(reply); \
+ proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
+ 1, little_endian); \
+ ++offset; \
+ SEQUENCENUMBER_REPLY(sequencenumber); \
+ REPLYLENGTH(replylength); \
+ proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, \
+ tvb_reported_length_remaining(tvb, offset), little_endian); \
+ offset += tvb_reported_length_remaining(tvb, offset); \
+} while (0)
+
+
+#define HANDLE_REPLY(plen, length_remaining, str, func) do { \
+ if (length_remaining < plen) { \
+ if (x11_desegment && pinfo->can_desegment) { \
+ pinfo->desegment_offset = offset; \
+ pinfo->desegment_len = plen - length_remaining;\
+ return; \
+ } else { \
+ ; /* XXX yes, what then? Need to skip/join. */ \
+ } \
+ } \
+ if (length_remaining > plen) \
+ length_remaining = plen; \
+ next_tvb = tvb_new_subset(tvb, offset, length_remaining, plen); \
+ \
+ if (sep == NULL) { \
+ if (check_col(pinfo->cinfo, COL_INFO)) \
+ col_add_str(pinfo->cinfo, COL_INFO, str); \
+ sep = ":"; \
+ } \
+ \
+ TRY { \
+ func(next_tvb, pinfo, tree, sep, state, little_endian); \
+ } \
+ \
+ CATCH(BoundsError) { \
+ RETHROW; \
+ } \
+ CATCH(ReportedBoundsError) { \
+ show_reported_bounds_error(next_tvb, pinfo, tree); \
+ } \
+ ENDTRY; \
+ \
+ sep = ","; \
+} while (0)
+
+static void
+dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const char *sep, x11_conv_data_t *volatile state,
+ gboolean little_endian);
+
+static void
+dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const char *volatile sep, x11_conv_data_t *volatile state,
+ gboolean little_endian);
+
+static void
+dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const char *volatile sep, x11_conv_data_t *volatile state,
+ gboolean little_endian);
+
+static void
+dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const char *volatile sep, x11_conv_data_t *volatile state,
+ gboolean little_endian);
+
+static void
+x11_stateinit(x11_conv_data_t **state, conversation_t *conversation);
+
+static const char *
+keysymString(guint32 v);
+
+
+/************************************************************************
+ *** ***
+ *** D E C O D I N G F I E L D S ***
+ *** ***
+ ************************************************************************/
+
+static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ gboolean little_endian)
+{
+ const char *interpretation = NULL;
+
+ guint32 v = VALUE32(tvb, *offsetp);
+ if (v >= 1 && v < array_length(atom_predefined_interpretation))
+ interpretation = atom_predefined_interpretation[v];
+ else if (v)
+ interpretation = "Not a predefined atom";
+ else {
+ header_field_info *hfi = proto_registrar_get_nth(hf);
+ if (hfi -> strings)
+ interpretation = match_strval(v, cVALS(hfi -> strings));
+ }
+ if (!interpretation) interpretation = "error in Xlib client program ?";
+ proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)",
+ proto_registrar_get_nth(hf) -> name, v, interpretation);
+ *offsetp += 4;
+}
+
+static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
+{
+ guint32 v = VALUE8(tvb, *offsetp);
+ proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
+ *offsetp += 1;
+ return v;
+}
+
+static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
+{
+ unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
+ proto_item *ti;
+ proto_tree *tt;
+
+ if (do_red_green_blue) {
+ int sep = FALSE;
+ char buffer[512];
+ char *bp = buffer + sprintf(buffer, "flags: ");
+
+ if (do_red_green_blue & 0x1) {
+ bp += sprintf(bp, "DoRed");
+ sep = TRUE;
+ }
+
+ if (do_red_green_blue & 0x2) {
+ if (sep) bp += sprintf(bp, " | ");
+ bp += sprintf(bp, "DoGreen");
+ sep = TRUE;
+ }
+
+ if (do_red_green_blue & 0x4) {
+ if (sep) bp += sprintf(bp, " | ");
+ bp += sprintf(bp, "DoBlue");
+ sep = TRUE;
+ }
+
+ if (do_red_green_blue & 0xf8) {
+ if (sep) bp += sprintf(bp, " + ");
+ sprintf(bp, "trash");
+ }
+
+ ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
+ "%s", buffer);
+ tt = proto_item_add_subtree(ti, ett_x11_color_flags);
+ if (do_red_green_blue & 0x1)
+ proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
+ do_red_green_blue & 0x1);
+ if (do_red_green_blue & 0x2)
+ proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
+ do_red_green_blue & 0x2);
+ if (do_red_green_blue & 0x4)
+ proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
+ do_red_green_blue & 0x4);
+ if (do_red_green_blue & 0xf8)
+ proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
+ do_red_green_blue & 0xf8);
+ } else
+ proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
+ "flags: none");
+ *offsetp += 1;
+}
+
+static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ int hf, const char *nullInterpretation)
+{
+ guint8 v = VALUE8(tvb, *offsetp);
+
+ if (!v)
+ proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
+ proto_registrar_get_nth(hf) -> name,
+ nullInterpretation);
+ else
+ proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
+ *offsetp += 1;
+}
+
+static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int length, gboolean little_endian)
+{
+ proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
+ proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
+ while(length--) {
+ gint16 x = VALUE16(tvb, *offsetp);
+ gint16 y = VALUE16(tvb, *offsetp + 2);
+ guint16 width = VALUE16(tvb, *offsetp + 4);
+ guint16 height = VALUE16(tvb, *offsetp + 6);
+ gint16 angle1 = VALUE16(tvb, *offsetp + 8);
+ gint16 angle2 = VALUE16(tvb, *offsetp + 10);
+
+ proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
+ "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
+ width, height, x, y, angle1, angle2,
+ angle1 / 64.0, angle2 / 64.0);
+ proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
+ proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
+ *offsetp += 2;
+ proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
+ *offsetp += 2;
+ proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
+ *offsetp += 2;
+ proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
+ *offsetp += 2;
+ proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
+ *offsetp += 2;
+ proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
+ *offsetp += 2;
+ }
+}
+
+static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int length, gboolean little_endian)
+{
+ proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
+ proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
+ while(length--)
+ atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
+}
+
+static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int length, gboolean little_endian)
+{
+ if (length <= 0) length = 1;
+ proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
+ *offsetp += length;
+}
+
+static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int hf_item, int length, gboolean little_endian)
+{
+ proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
+ proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
+ while(length--) {
+ proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
+ *offsetp += 4;
+ }
+}
+
+static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int length, gboolean little_endian)
+{
+ proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
+ proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
+ while(length--) {
+ proto_item *tti;
+ proto_tree *ttt;
+ unsigned do_red_green_blue;
+ guint16 red, green, blue;
+ char buffer[1024];
+ char *bp;
+ const char *sep;
+
+ red = VALUE16(tvb, *offsetp + 4);
+ green = VALUE16(tvb, *offsetp + 6);
+ blue = VALUE16(tvb, *offsetp + 8);
+ do_red_green_blue = VALUE8(tvb, *offsetp + 10);
+
+ bp = buffer + sprintf(buffer, "colorItem: ");
+ sep = "";
+ if (do_red_green_blue & 0x1) {
+ bp += sprintf(bp, "red = %d", red);
+ sep = ", ";
+ }
+ if (do_red_green_blue & 0x2) {
+ bp += sprintf(bp, "%sgreen = %d", sep, green);
+ sep = ", ";
+ }
+ if (do_red_green_blue & 0x4)
+ bp += sprintf(bp, "%sblue = %d", sep, blue);
+
+ tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
+ ttt = proto_item_add_subtree(tti, ett_x11_color_item);
+ proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
+ *offsetp += 4;
+ proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
+ *offsetp += 2;
+ proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
+ *offsetp += 2;
+ proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
+ *offsetp += 2;
+ colorFlags(tvb, offsetp, ttt);
+ proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
+ *offsetp += 1;
+ }
+}
+
+static GTree *keysymTable = NULL;
+
+static gint compareGuint32(gconstpointer a, gconstpointer b)
+{
+ return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
+}
+
+static void
+XConvertCase(register int sym, int *lower, int *upper)
+{
+ *lower = sym;
+ *upper = sym;
+ switch(sym >> 8) {
+ case 0: /* Latin 1 */
+ if ((sym >= XK_A) && (sym <= XK_Z))
+ *lower += (XK_a - XK_A);
+ else if ((sym >= XK_a) && (sym <= XK_z))
+ *upper -= (XK_a - XK_A);
+ else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
+ *lower += (XK_agrave - XK_Agrave);
+ else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
+ *upper -= (XK_agrave - XK_Agrave);
+ else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
+ *lower += (XK_oslash - XK_Ooblique);
+ else if ((sym >= XK_oslash) && (sym <= XK_thorn))
+ *upper -= (XK_oslash - XK_Ooblique);
+ break;
+ case 1: /* Latin 2 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym == XK_Aogonek)
+ *lower = XK_aogonek;
+ else if (sym >= XK_Lstroke && sym <= XK_Sacute)
+ *lower += (XK_lstroke - XK_Lstroke);
+ else if (sym >= XK_Scaron && sym <= XK_Zacute)
+ *lower += (XK_scaron - XK_Scaron);
+ else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
+ *lower += (XK_zcaron - XK_Zcaron);
+ else if (sym == XK_aogonek)
+ *upper = XK_Aogonek;
+ else if (sym >= XK_lstroke && sym <= XK_sacute)
+ *upper -= (XK_lstroke - XK_Lstroke);
+ else if (sym >= XK_scaron && sym <= XK_zacute)
+ *upper -= (XK_scaron - XK_Scaron);
+ else if (sym >= XK_zcaron && sym <= XK_zabovedot)
+ *upper -= (XK_zcaron - XK_Zcaron);
+ else if (sym >= XK_Racute && sym <= XK_Tcedilla)
+ *lower += (XK_racute - XK_Racute);
+ else if (sym >= XK_racute && sym <= XK_tcedilla)
+ *upper -= (XK_racute - XK_Racute);
+ break;
+ case 2: /* Latin 3 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
+ *lower += (XK_hstroke - XK_Hstroke);
+ else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
+ *lower += (XK_gbreve - XK_Gbreve);
+ else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
+ *upper -= (XK_hstroke - XK_Hstroke);
+ else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
+ *upper -= (XK_gbreve - XK_Gbreve);
+ else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
+ *lower += (XK_cabovedot - XK_Cabovedot);
+ else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
+ *upper -= (XK_cabovedot - XK_Cabovedot);
+ break;
+ case 3: /* Latin 4 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Rcedilla && sym <= XK_Tslash)
+ *lower += (XK_rcedilla - XK_Rcedilla);
+ else if (sym >= XK_rcedilla && sym <= XK_tslash)
+ *upper -= (XK_rcedilla - XK_Rcedilla);
+ else if (sym == XK_ENG)
+ *lower = XK_eng;
+ else if (sym == XK_eng)
+ *upper = XK_ENG;
+ else if (sym >= XK_Amacron && sym <= XK_Umacron)
+ *lower += (XK_amacron - XK_Amacron);
+ else if (sym >= XK_amacron && sym <= XK_umacron)
+ *upper -= (XK_amacron - XK_Amacron);
+ break;
+ case 6: /* Cyrillic */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
+ *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
+ else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
+ *upper += (XK_Serbian_DJE - XK_Serbian_dje);
+ else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
+ *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
+ else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
+ *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
+ break;
+ case 7: /* Greek */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
+ *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+ else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
+ sym != XK_Greek_iotaaccentdieresis &&
+ sym != XK_Greek_upsilonaccentdieresis)
+ *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+ else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
+ *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
+ else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
+ sym != XK_Greek_finalsmallsigma)
+ *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
+ break;
+ }
+}
+
+static const char *
+keycode2keysymString(int *keycodemap[256], int first_keycode,
+ int keysyms_per_keycode,
+ int *modifiermap[array_length(modifiers)],
+ int keycodes_per_modifier,
+ guint32 keycode, guint32 bitmask)
+{
+ static char buf[32];
+ int *syms;
+ int groupmodkc, numlockkc, numlockmod, groupmod;
+ int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
+ int lockmod_is_nosymbol = 1;
+ int modifier, kc, keysym;
+
+ if ((syms = keycodemap[keycode]) == NULL)
+ return "<Unknown>";
+
+ for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
+ for (keysym = 0; keysym < keysyms_per_keycode; ++keysym) {
+ if (keycodemap[kc] == NULL)
+ return "<Unknown>";
+ switch (keycodemap[kc][keysym]) {
+ case 0xff7e:
+ groupmodkc = kc;
+ break;
+
+ case 0xff7f:
+ numlockkc = kc;
+ break;
+
+ case 0xffe5:
+ lockmod_is_capslock = kc;
+ break;
+
+ case 0xffe6:
+ lockmod_is_shiftlock = kc;
+ break;
+ }
+ }
+
+
+ /*
+ * If we have not seen the modifiermap we don't know what the
+ * keycode translates to, but we do know it's one of the keys
+ * in syms (give or take a case-conversion), so we could in
+ * theory list them all.
+ */
+ if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
+ return "<Unknown>";
+
+ /* find out what the numlockmodifer and groupmodifier is. */
+ for (modifier = 0, numlockmod = groupmod = -1;
+ modifier < (int)array_length(modifiers) && numlockmod == -1;
+ ++modifier)
+ for (kc = 0; kc < keycodes_per_modifier; ++kc)
+ if (modifiermap[modifier][kc] == numlockkc)
+ numlockmod = modifier;
+ else if (modifiermap[modifier][kc] == groupmodkc)
+ groupmod = modifier;
+
+ /*
+ * ... and what the lockmodifier is interpreted as.
+ * (X11v4r6 ref, keyboard and pointers section.)
+ */
+ for (kc = 0; kc < keycodes_per_modifier; ++kc)
+ if (modifiermap[1][kc] == lockmod_is_capslock) {
+ lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
+ break;
+ }
+ else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
+ lockmod_is_capslock = lockmod_is_nosymbol = 0;
+ break;
+ }
+
+#if 0
+ /*
+ * This is (how I understand) the X11v4R6 protocol description given
+ * in A. Nye's book. It is quite different from the
+ * code in _XTranslateKey() in the file
+ * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
+ * as shipped with XFree, and doesn't work correctly, nor do I see
+ * how it could (e.g. the case of lower/uppercase-letters).
+ * -- Michael Shuldman
+ */
+
+ if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
+ && ((syms[1] >= 0xff80
+ && syms[1] <= 0xffbd)
+ || (syms[1] >= 0x11000000
+ && syms[1] <= 0x1100ffff))) {
+ if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
+ return keysymString(syms[groupmod + 0]);
+ else
+ if (syms[groupmod + 1] == NoSymbol)
+ return keysymString(syms[groupmod + 0]);
+ else
+ return keysymString(syms[groupmod + 1]);
+ }
+ else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
+ return keysymString(syms[groupmod + 0]);
+ else if (!(bitmask & ShiftMask)
+ && ((bitmask & LockMask) && lockmod_is_capslock))
+ if (islower(syms[groupmod + 0]))
+/* return toupper(keysymString(syms[groupmod + 0])); */
+ return "Uppercase"; /* XXX */
+ else
+ return keysymString(syms[groupmod + 0]);
+
+ else if ((bitmask & ShiftMask)
+ && ((bitmask & LockMask) && lockmod_is_capslock))
+ if (islower(syms[groupmod + 1]))
+/* return toupper(keysymString(syms[groupmod + 1])); */
+ return "Uppercase"; /* XXX */
+ else
+ return keysymString(syms[groupmod + 1]);
+
+ else if ((bitmask & ShiftMask)
+ || ((bitmask & LockMask) && lockmod_is_shiftlock))
+ return keysymString(syms[groupmod + 1]);
+#else /* _XTranslateKey() based code. */
+
+ while (keysyms_per_keycode > 2
+ && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
+ --keysyms_per_keycode;
+ if (keysyms_per_keycode > 2
+ && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
+ syms += 2;
+ keysyms_per_keycode -= 2;
+ }
+
+ if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
+ && keysyms_per_keycode > 1
+ && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
+ || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
+ if ((bitmask & ShiftMask)
+ || (bitmask & LockMask && lockmod_is_shiftlock))
+ keysym = syms[0];
+ else
+ keysym = syms[1];
+ }
+ else if (!(bitmask & ShiftMask)
+ && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
+ if (keysyms_per_keycode == 1
+ || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
+ int usym;
+
+ XConvertCase(syms[0], &keysym, &usym);
+ }
+ else
+ keysym = syms[0];
+ }
+ else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
+ int lsym, usym;
+
+ if (keysyms_per_keycode == 1
+ || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
+ XConvertCase(syms[0], &lsym, &usym);
+ keysym = usym;
+ }
+ else {
+ int lsym, usym;
+
+ if (keysyms_per_keycode == 1
+ || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
+ keysym = syms[0];
+
+ XConvertCase(keysym, &lsym, &usym);
+
+ if (!(bitmask & ShiftMask) && keysym != syms[0]
+ && ((keysym != usym) || (lsym == usym)))
+ XConvertCase(syms[0], &lsym, &usym);
+ keysym = usym;
+ }
+
+ if (keysym == XK_VoidSymbol)
+ keysym = NoSymbol;
+
+ sprintf(buf, "%d, \"%s\"", keysym, keysymString(keysym));
+ return buf;
+#endif
+}
+
+static const char *keysymString(guint32 v)
+{
+ gpointer res;
+ if (!keysymTable) {
+
+ /* This table is so big that we built it only if necessary */
+
+ const value_string *p = keysym_vals_source;
+ keysymTable = g_tree_new(compareGuint32);
+ for(; p -> strptr; p++)
+ g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
+ }
+ res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
+ return res ? res : "<Unknown>";
+}
+
+static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int *modifiermap[], int keycodes_per_modifier,
+ gboolean little_endian)
+{
+ char buffer[1024];
+ proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
+ array_length(modifiers) * keycodes_per_modifier, little_endian);
+
+ proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
+ size_t m;
+
+ for (m = 0; m < array_length(modifiers);
+ ++m, *offsetp += keycodes_per_modifier) {
+ const guint8 *p;
+ char *bp = buffer;
+ int i;
+
+ p = tvb_get_ptr(tvb, *offsetp, keycodes_per_modifier);
+ modifiermap[m] =
+ g_malloc(sizeof(*modifiermap[m]) * keycodes_per_modifier);
+
+ for(i = 0; i < keycodes_per_modifier; ++i) {
+ guchar c = p[i];
+
+ if (c)
+ bp += sprintf(bp, " %s=%d", modifiers[m], c);
+
+ modifiermap[m][i] = c;
+ }
+
+ proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
+ *offsetp, keycodes_per_modifier, p,
+ "item: %s", buffer);
+ }
+}
+
+static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int hf_item, int *keycodemap[256],
+ int keycode_first, int keycode_count,
+ int keysyms_per_keycode, gboolean little_endian)
+{
+ proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
+ proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
+ proto_item *tti;
+ proto_tree *ttt;
+ int i, keycode;
+
+ g_assert(keycode_first >= 0);
+ g_assert(keycode_count >= 0);
+ g_assert((size_t)(keycode_first + keycode_count) <= 256);
+
+
+ for (keycode = keycode_first; keycode_count > 0;
+ ++keycode, --keycode_count) {
+ tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
+ keysyms_per_keycode * 4, "keysyms (keycode %d):", keycode);
+
+ ttt = proto_item_add_subtree(tti, ett_x11_keysym);
+
+ tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
+ keycodemap[keycode]
+ = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
+
+ for(i = 0; i < keysyms_per_keycode; ++i) {
+ /* keysymvalue = byte3 * 256 + byte4. */
+ guint32 v = VALUE32(tvb, *offsetp);
+
+ proto_item_append_text(tti, " %s", keysymString(v));
+ proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
+ tvb, *offsetp, 4, v,
+ "keysym (keycode %d): 0x%08x (%s)",
+ keycode, v, keysymString(v));
+
+ keycodemap[keycode][i] = v;
+ *offsetp += 4;
+ }
+
+ for (i = 1; i < keysyms_per_keycode; ++i)
+ if (keycodemap[keycode][i] != NoSymbol)
+ break;
+
+ if (i == keysyms_per_keycode) {
+ /* all but (possibly) first were NoSymbol. */
+ if (keysyms_per_keycode == 4) {
+ keycodemap[keycode][1] = NoSymbol;
+ keycodemap[keycode][2] = keycodemap[keycode][0];
+ keycodemap[keycode][3] = NoSymbol;
+ }
+
+ continue;
+ }
+
+ for (i = 2; i < keysyms_per_keycode; ++i)
+ if (keycodemap[keycode][i] != NoSymbol)
+ break;
+ if (i == keysyms_per_keycode) {
+ /* all but (possibly) first two were NoSymbol. */
+ if (keysyms_per_keycode == 4) {
+ keycodemap[keycode][2] = keycodemap[keycode][0];
+ keycodemap[keycode][3] = keycodemap[keycode][1];
+ }
+
+ continue;
+ }
+ }
+}
+
+static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int length, gboolean little_endian)
+{
+ proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
+ proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
+ while(length--) {
+ gint16 x, y;
+ proto_item *tti;
+ proto_tree *ttt;
+
+ x = VALUE16(tvb, *offsetp);
+ y = VALUE16(tvb, *offsetp + 2);
+
+ tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
+ ttt = proto_item_add_subtree(tti, ett_x11_point);
+ proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
+ *offsetp += 2;
+ proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
+ *offsetp += 2;
+ }
+}
+
+static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int length, gboolean little_endian)
+{
+ proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
+ proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
+ while(length--) {
+ gint16 x, y;
+ unsigned width, height;
+ proto_item *tti;
+ proto_tree *ttt;
+
+ x = VALUE16(tvb, *offsetp);
+ y = VALUE16(tvb, *offsetp + 2);
+ width = VALUE16(tvb, *offsetp + 4);
+ height = VALUE16(tvb, *offsetp + 6);
+
+ tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
+ "rectangle: %dx%d+%d+%d", width, height, x, y);
+ ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
+ proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
+ *offsetp += 2;
+ proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
+ *offsetp += 2;
+ proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
+ *offsetp += 2;
+ proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
+ *offsetp += 2;
+ }
+}
+
+static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int length, gboolean little_endian)
+{
+ proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
+ proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
+ while(length--) {
+ gint16 x1, y1, x2, y2;
+ proto_item *tti;
+ proto_tree *ttt;
+
+ x1 = VALUE16(tvb, *offsetp);
+ y1 = VALUE16(tvb, *offsetp + 2);
+ x2 = VALUE16(tvb, *offsetp + 4);
+ y2 = VALUE16(tvb, *offsetp + 6);
+
+ tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
+ "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
+ ttt = proto_item_add_subtree(tti, ett_x11_segment);
+ proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
+ *offsetp += 2;
+ proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
+ *offsetp += 2;
+ proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
+ *offsetp += 2;
+ proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
+ *offsetp += 2;
+ }
+}
+
+/* XXX - the protocol tree code should handle non-printable characters.
+ Note that "non-printable characters" may depend on your locale.... */
+static void stringCopy(char *dest, const char *source, int length)
+{
+ guchar c;
+ while(length--) {
+ c = *source++;
+ if (!isgraph(c) && c != ' ') c = '.';
+ *dest++ = c;
+ }
+ *dest++ = '\0';
+}
+
+static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int hf_item, int length, gboolean little_endian)
+{
+ char *s = NULL;
+ guint allocated = 0;
+ proto_item *ti;
+ proto_tree *tt;
+ int i;
+
+ /* Compute total length */
+
+ int scanning_offset = *offsetp; /* Scanning pointer */
+ int l;
+ for(i = length; i; i--) {
+ l = tvb_get_guint8(tvb, scanning_offset);
+ scanning_offset += 1 + l;
+ }
+
+ ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
+ tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
+
+ /*
+ * In case we throw an exception, clean up whatever stuff we've
+ * allocated (if any).
+ */
+ CLEANUP_PUSH(g_free, s);
+
+ while(length--) {
+ unsigned l = VALUE8(tvb, *offsetp);
+ if (allocated < (l + 1)) {
+ /* g_realloc doesn't work ??? */
+ g_free(s);
+ s = g_malloc(l + 1);
+ allocated = l + 1;
+ }
+ stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
+ proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
+ *offsetp += l + 1;
+ }
+
+ /*
+ * Call the cleanup handler to free the string and pop the handler.
+ */
+ CLEANUP_CALL_AND_POP;
+}
+
+#define STRING16_MAX_DISPLAYED_LENGTH 150
+
+static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
+{
+ if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
+ for(; length > 0; offset += 2, length--) {
+ if (tvb_get_guint8(tvb, offset))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* length is the length of the _byte_zone_ (that is, twice the length of the string) */
+
+static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
+ int hf, int hf_bytes,
+ int offset, unsigned length,
+ char **s, int *sLength,
+ gboolean little_endian)
+{
+ int truncated = FALSE;
+ unsigned l = length / 2;
+
+ if (stringIsActuallyAn8BitString(tvb, offset, l)) {
+ char *dp;
+ int soffset = offset;
+
+ if (l > STRING16_MAX_DISPLAYED_LENGTH) {
+ truncated = TRUE;
+ l = STRING16_MAX_DISPLAYED_LENGTH;
+ }
+ if (*sLength < (int) l + 3) {
+ g_free(*s);
+ *s = g_malloc(l + 3);
+ *sLength = l + 3;
+ }
+ dp = *s;
+ *dp++ = '"';
+ if (truncated) l -= 3;
+
+ while(l--) {
+ soffset++;
+ *dp++ = tvb_get_guint8(tvb, soffset);
+ soffset++;
+ }
+ *dp++ = '"';
+
+ /* If truncated, add an ellipsis */
+ if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
+
+ *dp++ = '\0';
+ proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
+ proto_registrar_get_nth(hf) -> name, *s);
+ } else
+ proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
+
+}
+
+static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int sizeIs16, int next_offset, gboolean little_endian)
+{
+ int allocated = 0;
+ char *s = NULL;
+ proto_item *ti;
+ proto_tree *tt;
+ guint32 fid;
+
+ /* Compute total length */
+
+ int scanning_offset = *offsetp; /* Scanning pointer */
+ int l; /* Length of an individual item */
+ int n = 0; /* Number of items */
+
+ while(scanning_offset < next_offset) {
+ l = tvb_get_guint8(tvb, scanning_offset);
+ scanning_offset++;
+ if (!l) break;
+ n++;
+ scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
+ }
+
+ ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
+ tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
+
+ /*
+ * In case we throw an exception, clean up whatever stuff we've
+ * allocated (if any).
+ */
+ CLEANUP_PUSH(g_free, s);
+
+ while(n--) {
+ unsigned l = VALUE8(tvb, *offsetp);
+ if (l == 255) { /* Item is a font */
+ fid = tvb_get_ntohl(tvb, *offsetp + 1);
+ proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
+ *offsetp += 5;
+ } else { /* Item is a string */
+ proto_item *tti;
+ proto_tree *ttt;
+ gint8 delta = VALUE8(tvb, *offsetp + 1);
+ if (sizeIs16) l += l;
+ if ((unsigned) allocated < l + 1) {
+ /* g_realloc doesn't work ??? */
+ g_free(s);
+ s = g_malloc(l + 1);
+ allocated = l + 1;
+ }
+ stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
+ tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
+ "textitem (string): delta = %d, \"%s\"",
+ delta, s);
+ ttt = proto_item_add_subtree(tti, ett_x11_text_item);
+ proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
+ if (sizeIs16)
+ string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
+ hf_x11_textitem_string_string16_bytes,
+ *offsetp + 2, l,
+ &s, &allocated,
+ little_endian);
+ else
+ proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
+ *offsetp + 2, l, s, "\"%s\"", s);
+ *offsetp += l + 2;
+ }
+ }
+
+ /*
+ * Call the cleanup handler to free the string and pop the handler.
+ */
+ CLEANUP_CALL_AND_POP;
+}
+
+static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ gboolean little_endian)
+{
+ guint32 v = VALUE8(tvb, *offsetp);
+ header_field_info *hfi = proto_registrar_get_nth(hf);
+ gchar *enumValue = NULL;
+
+ if (hfi -> strings)
+ enumValue = match_strval(v, cVALS(hfi -> strings));
+ if (enumValue)
+ proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
+ hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
+ hfi -> name, v, enumValue);
+ else
+ proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
+ *offsetp += 1;
+ return v;
+}
+
+static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ gboolean little_endian)
+{
+ guint32 v = VALUE16(tvb, *offsetp);
+ header_field_info *hfi = proto_registrar_get_nth(hf);
+ gchar *enumValue = NULL;
+
+ if (hfi -> strings)
+ enumValue = match_strval(v, cVALS(hfi -> strings));
+ if (enumValue)
+ proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
+ hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
+ hfi -> name, v, enumValue);
+ else
+ proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
+ *offsetp += 2;
+ return v;
+}
+
+static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ gboolean little_endian)
+{
+ guint32 v = VALUE32(tvb, *offsetp);
+ header_field_info *hfi = proto_registrar_get_nth(hf);
+ gchar *enumValue = NULL;
+ gchar *nameAsChar = hfi -> name;
+
+ if (hfi -> strings)
+ enumValue = match_strval(v, cVALS(hfi -> strings));
+ if (enumValue)
+ proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
+ hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
+ nameAsChar, v, enumValue);
+ else
+ proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
+ hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
+ nameAsChar, v);
+ *offsetp += 4;
+ return v;
+}
+
+static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ gboolean little_endian)
+{
+ BITMASK32(gc_value);
+ BITFIELD(ENUM8, gc_value_mask, function);
+ BITFIELD(CARD32, gc_value_mask, plane_mask);
+ BITFIELD(CARD32, gc_value_mask, foreground);
+ BITFIELD(CARD32, gc_value_mask, background);
+ BITFIELD(CARD16, gc_value_mask, line_width);
+ BITFIELD(ENUM8, gc_value_mask, line_style);
+ BITFIELD(ENUM8, gc_value_mask, cap_style);
+ BITFIELD(ENUM8, gc_value_mask, join_style);
+ BITFIELD(ENUM8, gc_value_mask, fill_style);
+ BITFIELD(ENUM8, gc_value_mask, fill_rule);
+ BITFIELD(PIXMAP, gc_value_mask, tile);
+ BITFIELD(PIXMAP, gc_value_mask, stipple);
+ BITFIELD(INT16, gc_value_mask, tile_stipple_x_origin);
+ BITFIELD(INT16, gc_value_mask, tile_stipple_y_origin);
+ BITFIELD(FONT, gc_value_mask, font);
+ BITFIELD(ENUM8, gc_value_mask, subwindow_mode);
+ BITFIELD(BOOL, gc_value_mask, graphics_exposures);
+ BITFIELD(INT16, gc_value_mask, clip_x_origin);
+ BITFIELD(INT16, gc_value_mask, clip_y_origin);
+ BITFIELD(PIXMAP, gc_value_mask, clip_mask);
+ BITFIELD(CARD16, gc_value_mask, dash_offset);
+ BITFIELD(CARD8, gc_value_mask, gc_dashes);
+ BITFIELD(ENUM8, gc_value_mask, arc_mode);
+ ENDBITMASK;
+}
+
+static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ gboolean little_endian)
+{
+ BITMASK32(gc_value);
+ FLAG(gc_value, function);
+ FLAG(gc_value, plane_mask);
+ FLAG(gc_value, foreground);
+ FLAG(gc_value, background);
+ FLAG(gc_value, line_width);
+ FLAG(gc_value, line_style);
+ FLAG(gc_value, cap_style);
+ FLAG(gc_value, join_style);
+ FLAG(gc_value, fill_style);
+ FLAG(gc_value, fill_rule);
+ FLAG(gc_value, tile);
+ FLAG(gc_value, stipple);
+ FLAG(gc_value, tile_stipple_x_origin);
+ FLAG(gc_value, tile_stipple_y_origin);
+ FLAG(gc_value, font);
+ FLAG(gc_value, subwindow_mode);
+ FLAG(gc_value, graphics_exposures);
+ FLAG(gc_value, clip_x_origin);
+ FLAG(gc_value, clip_y_origin);
+ FLAG(gc_value, clip_mask);
+ FLAG(gc_value, dash_offset);
+ FLAG(gc_value, gc_dashes);
+ FLAG(gc_value, arc_mode);
+ ENDBITMASK;
+}
+
+static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ gboolean little_endian)
+{
+ guint32 res = VALUE16(tvb, *offsetp);
+ proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
+ *offsetp += 2;
+ return res * 4;
+}
+
+static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ gboolean little_endian)
+{
+ BITMASK32(event);
+ FLAG(event, KeyPress);
+ FLAG(event, KeyRelease);
+ FLAG(event, ButtonPress);
+ FLAG(event, ButtonRelease);
+ FLAG(event, EnterWindow);
+ FLAG(event, LeaveWindow);
+ FLAG(event, PointerMotion);
+ FLAG(event, PointerMotionHint);
+ FLAG(event, Button1Motion);
+ FLAG(event, Button2Motion);
+ FLAG(event, Button3Motion);
+ FLAG(event, Button4Motion);
+ FLAG(event, Button5Motion);
+ FLAG(event, ButtonMotion);
+ FLAG(event, KeymapState);
+ FLAG(event, Exposure);
+ FLAG(event, VisibilityChange);
+ FLAG(event, StructureNotify);
+ FLAG(event, ResizeRedirect);
+ FLAG(event, SubstructureNotify);
+ FLAG(event, SubstructureRedirect);
+ FLAG(event, FocusChange);
+ FLAG(event, PropertyChange);
+ FLAG(event, ColormapChange);
+ FLAG(event, OwnerGrabButton);
+ FLAG_IF_NONZERO(event, erroneous_bits);
+ ENDBITMASK;
+}
+
+static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ gboolean little_endian)
+{
+ BITMASK32(do_not_propagate);
+ FLAG(do_not_propagate, KeyPress);
+ FLAG(do_not_propagate, KeyRelease);
+ FLAG(do_not_propagate, ButtonPress);
+ FLAG(do_not_propagate, ButtonRelease);
+ FLAG(do_not_propagate, PointerMotion);
+ FLAG(do_not_propagate, Button1Motion);
+ FLAG(do_not_propagate, Button2Motion);
+ FLAG(do_not_propagate, Button3Motion);
+ FLAG(do_not_propagate, Button4Motion);
+ FLAG(do_not_propagate, Button5Motion);
+ FLAG(do_not_propagate, ButtonMotion);
+ FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
+ ENDBITMASK;
+}
+
+
+static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ gboolean little_endian, gboolean butmask)
+{
+ proto_item *ti;
+ guint32 bitmask_value;
+ int bitmask_offset;
+ int bitmask_size;
+ proto_tree *bitmask_tree;
+
+ bitmask_value = VALUE16(tvb, *offsetp);
+ bitmask_offset = *offsetp;
+ bitmask_size = 2;
+
+ if (!butmask && bitmask_value == 0x8000)
+ proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
+ "modifiers-masks: 0x8000 (AnyModifier)");
+ else {
+ ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
+ bitmask_value);
+ bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
+ FLAG(modifiers, Shift);
+ FLAG(modifiers, Lock);
+ FLAG(modifiers, Control);
+ FLAG(modifiers, Mod1);
+ FLAG(modifiers, Mod2);
+ FLAG(modifiers, Mod3);
+ FLAG(modifiers, Mod4);
+ FLAG(modifiers, Mod5);
+
+ if (butmask) {
+ FLAG(modifiers, Button1);
+ FLAG(modifiers, Button2);
+ FLAG(modifiers, Button3);
+ FLAG(modifiers, Button4);
+ FLAG(modifiers, Button5);
+ }
+
+ if (butmask)
+ FLAG_IF_NONZERO(keybut, erroneous_bits);
+ else
+ FLAG_IF_NONZERO(modifiers, erroneous_bits);
+ }
+ *offsetp += 2;
+}
+
+static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ gboolean little_endian)
+{
+ BITMASK16(pointer_event);
+ FLAG(pointer_event, ButtonPress);
+ FLAG(pointer_event, ButtonRelease);
+ FLAG(pointer_event, EnterWindow);
+ FLAG(pointer_event, LeaveWindow);
+ FLAG(pointer_event, PointerMotion);
+ FLAG(pointer_event, PointerMotionHint);
+ FLAG(pointer_event, Button1Motion);
+ FLAG(pointer_event, Button2Motion);
+ FLAG(pointer_event, Button3Motion);
+ FLAG(pointer_event, Button4Motion);
+ FLAG(pointer_event, Button5Motion);
+ FLAG(pointer_event, ButtonMotion);
+ FLAG(pointer_event, KeymapState);
+ FLAG_IF_NONZERO(pointer_event, erroneous_bits);
+ ENDBITMASK;
+}
+
+static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ int hf, unsigned length)
+{
+ const guint8 *p;
+ char *s;
+
+ p = tvb_get_ptr(tvb, *offsetp, length);
+ s = g_malloc(length + 1);
+ stringCopy(s, p, length);
+ proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
+ g_free(s);
+ *offsetp += length;
+}
+
+/* The length is the length of the _byte_zone_ (twice the length of the string) */
+
+static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ int hf_bytes, unsigned length, gboolean little_endian)
+{
+ char *s = NULL;
+ unsigned l = 0;
+
+ /*
+ * In case we throw an exception, clean up whatever stuff we've
+ * allocated (if any).
+ */
+ CLEANUP_PUSH(g_free, s);
+
+ length += length;
+ string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
+ &s, &l, little_endian);
+
+ /*
+ * Call the cleanup handler to free the string and pop the handler.
+ */
+ CLEANUP_CALL_AND_POP;
+
+ *offsetp += length;
+}
+
+static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+ gboolean little_endian)
+{
+ guint32 v = VALUE32(tvb, *offsetp);
+
+ if (!v)
+ proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
+ proto_registrar_get_nth(hf) -> name);
+ else
+ proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
+ *offsetp += 4;
+}
+
+static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+ gboolean little_endian)
+{
+ BITMASK32(window_value);
+ BITFIELD(PIXMAP, window_value_mask, background_pixmap);
+ BITFIELD(CARD32, window_value_mask, background_pixel);
+ BITFIELD(PIXMAP, window_value_mask, border_pixmap);
+ BITFIELD(CARD32, window_value_mask, border_pixel);
+ BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
+ BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
+ BITFIELD(ENUM8, window_value_mask, backing_store);
+ BITFIELD(CARD32, window_value_mask, backing_planes);
+ BITFIELD(CARD32, window_value_mask, backing_pixel);
+ BITFIELD(BOOL, window_value_mask, override_redirect);
+ BITFIELD(BOOL, window_value_mask, save_under);
+ BITFIELD(SETofEVENT, window_value_mask, event_mask);
+ BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
+ BITFIELD(COLORMAP, window_value_mask, colormap);
+ BITFIELD(CURSOR, window_value_mask, cursor);
+ ENDBITMASK;
+}
+
+static void x11_init_protocol(void)
+{
+ if (x11_state_chunk != NULL)
+ g_mem_chunk_destroy(x11_state_chunk);
+
+ x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
+ sizeof (x11_conv_data_t),
+ 128 * sizeof (x11_conv_data_t),
+ G_ALLOC_ONLY);
+}
+
+/************************************************************************
+ *** ***
+ *** G U E S S I N G T H E B Y T E O R D E R I N G ***
+ *** ***
+ ************************************************************************/
+
+/* If we can't guess, we return TRUE (that is little_endian), cause
+ I'm developing on a Linux box :-). The (non-)guess isn't cached
+ however, so we may have more luck next time. I'm quite conservative
+ in my assertions, cause once it's cached, it's stay in cache, and
+ we may be fooled up by a packet starting with the end of a request
+ started in a previous packet...
+*/
+
+static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+
+static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
+{
+ int res = 0;
+ while(maskLength--) {
+ int c = tvb_get_guint8(tvb, offset);
+ offset++;
+ res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
+ }
+ return res;
+}
+
+static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
+{
+ if (listLength > length) return FALSE;
+ while(listLength--) {
+ int l;
+ if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
+ l = tvb_get_guint8(tvb, offset);
+ if (!l) break;
+ l++;
+ if (l > length) return FALSE;
+ if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
+ offset += l;
+ length -= l;
+ }
+ if (length > 3) return FALSE;
+ return TRUE;
+}
+
+static int rounded4(int n)
+{
+ int remainder = n % 4;
+ int res = n / 4;
+ if (remainder) res++;
+ return res;
+}
+
+/* We assume the order to be consistent, until proven wrong. */
+
+static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
+{
+ switch(tvb_get_guint8(tvb, offset)) {
+ case X_CreateWindow:
+ return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
+
+ case X_ChangeWindowAttributes:
+ case X_ChangeGC:
+ return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
+
+ case X_GetWindowAttributes:
+ case X_DestroyWindow:
+ case X_DestroySubwindows:
+ case X_ChangeSaveSet:
+ case X_MapWindow:
+ case X_MapSubwindows:
+ case X_UnmapWindow:
+ case X_UnmapSubwindows:
+ case X_CirculateWindow:
+ case X_GetGeometry:
+ case X_QueryTree:
+ case X_GetAtomName:
+ case X_ListProperties:
+ case X_GetSelectionOwner:
+ case X_UngrabPointer:
+ case X_UngrabKeyboard:
+ case X_AllowEvents:
+ case X_QueryPointer:
+ case X_CloseFont:
+ case X_QueryFont:
+ case X_FreePixmap:
+ case X_FreeGC:
+ case X_FreeColormap:
+ case X_InstallColormap:
+ case X_UninstallColormap:
+ case X_ListInstalledColormaps:
+ case X_FreeCursor:
+ case X_GetKeyboardMapping:
+ case X_KillClient:
+ return length == 2;
+
+ case X_ReparentWindow:
+ case X_SetSelectionOwner:
+ case X_ChangeActivePointerGrab:
+ case X_GrabKeyboard:
+ case X_GrabKey:
+ case X_GetMotionEvents:
+ case X_TranslateCoords:
+ case X_CreatePixmap:
+ case X_CopyGC:
+ case X_ClearArea:
+ case X_CreateColormap:
+ case X_AllocColor:
+ case X_AllocColorPlanes:
+ return length == 4;
+
+ case X_ConfigureWindow:
+ return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
+
+ case X_InternAtom:
+ case X_QueryExtension:
+ return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
+
+ case X_ChangeProperty:
+ {
+ int multiplier, type;
+ if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
+ type = tvb_get_guint8(tvb, 16);
+ if (type != 8 && type != 16 && type != 32) return FALSE;
+ multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
+ if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
+ return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
+ }
+
+ case X_DeleteProperty:
+ case X_UngrabButton:
+ case X_UngrabKey:
+ case X_SetInputFocus:
+ case X_CopyColormapAndFree:
+ case X_AllocColorCells:
+ case X_QueryBestSize:
+ case X_ChangePointerControl:
+ case X_SetScreenSaver:
+ return length == 3;
+
+ case X_GetProperty:
+ case X_ConvertSelection:
+ case X_GrabPointer:
+ case X_GrabButton:
+ case X_WarpPointer:
+ return length == 6;
+
+ case X_SendEvent:
+ return length == 11;
+
+ case X_GrabServer:
+ case X_UngrabServer:
+ case X_GetInputFocus:
+ case X_QueryKeymap:
+ case X_GetFontPath:
+ case X_ListExtensions:
+ case X_GetKeyboardControl:
+ case X_Bell:
+ case X_GetPointerControl:
+ case X_GetScreenSaver:
+ case X_ListHosts:
+ case X_SetAccessControl:
+ case X_SetCloseDownMode:
+ case X_ForceScreenSaver:
+ case X_GetPointerMapping:
+ case X_GetModifierMapping:
+ return length == 1;
+
+ case X_OpenFont:
+ case X_AllocNamedColor:
+ case X_LookupColor:
+ return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
+
+ case X_QueryTextExtents:
+ return length >= 2;
+
+ case X_ListFonts:
+ case X_ListFontsWithInfo:
+ case X_ChangeHosts:
+ return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
+
+ case X_SetFontPath:
+ if (length < 2) return FALSE;
+ if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
+ return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
+
+ case X_CreateGC:
+ return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
+
+ case X_SetDashes:
+ return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
+
+ case X_SetClipRectangles:
+ case X_PolySegment:
+ case X_PolyRectangle:
+ case X_PolyFillRectangle:
+ return length >= 3 && (length - 3) % 2 == 0;
+
+ case X_CopyArea:
+ return length == 7;
+
+ case X_CopyPlane:
+ case X_CreateCursor:
+ case X_CreateGlyphCursor:
+ return length == 8;
+
+ case X_PolyPoint:
+ case X_PolyLine:
+ case X_FreeColors:
+ return length >= 3;
+
+ case X_PolyArc:
+ case X_PolyFillArc:
+ return length >= 3 && (length - 3) % 3 == 0;
+
+ case X_FillPoly:
+ case X_ImageText8:
+ return length >= 4;
+
+ case X_PutImage:
+ return length >= 6;
+
+ case X_GetImage:
+ case X_RecolorCursor:
+ return length == 5;
+
+ case X_PolyText8:
+ if (length < 4) return FALSE;
+ return TRUE; /* We don't perform many controls on this one */
+
+ case X_PolyText16:
+ if (length < 4) return FALSE;
+ return TRUE; /* We don't perform many controls on this one */
+
+ case X_ImageText16:
+ return length >= 4;
+
+ case X_StoreColors:
+ return length > 2 && (length - 2) % 3 == 0;
+
+ case X_StoreNamedColor:
+ return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
+
+ case X_QueryColors:
+ return length >= 2;
+
+ case X_ChangeKeyboardMapping:
+ return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
+
+ case X_ChangeKeyboardControl:
+ return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
+
+ case X_RotateProperties:
+ return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
+
+ case X_SetPointerMapping:
+ return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
+
+ case X_SetModifierMapping:
+ return length == 1 + tvb_get_guint8(tvb, 1) * 2;
+
+ case X_NoOperation:
+ return length >= 1;
+
+ default:
+ return TRUE;
+ }
+}
+
+/* -1 means doesn't match, +1 means match, 0 means don't know */
+
+static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
+{
+ int offset, nextoffset;
+ int atLeastOne = 0;
+
+ for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
+ int length;
+ length = v16(tvb, offset + 2);
+ if (!length) return -1;
+ nextoffset = offset + length * 4;
+ if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
+ atLeastOne = 1;
+ }
+ return atLeastOne;
+}
+
+static gboolean
+guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
+ x11_conv_data_t *state)
+{
+ /* With X the client gives the byte ordering for the protocol,
+ and the port on the server tells us we're speaking X. */
+
+ int le, be, decision, decisionToCache;
+
+ if (state->byte_order == BYTE_ORDER_BE)
+ return FALSE; /* known to be big-endian */
+ else if (state->byte_order == BYTE_ORDER_LE)
+ return TRUE; /* known to be little-endian */
+
+ if (pinfo->srcport == pinfo->match_port) {
+ /*
+ * This is a reply or event; we don't try to guess the
+ * byte order on it for now.
+ */
+ return TRUE;
+ }
+
+ le = x_endian_match(tvb, tvb_get_letohs);
+ be = x_endian_match(tvb, tvb_get_ntohs);
+
+ /* remember that "decision" really means "little_endian". */
+ if (le == be) {
+ /* We have no reason to believe it's little- rather than
+ big-endian, so we guess the shortest length is the
+ right one.
+ */
+ if (!tvb_bytes_exist(tvb, 0, 4))
+ /* Not even a way to get the length. We're biased
+ toward little endianness here (essentially the
+ x86 world right now). Decoding won't go very far
+ anyway.
+ */
+ decision = TRUE;
+ else
+ decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
+ } else
+ decision = le >= be;
+
+ decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
+ if (decisionToCache) {
+ /*
+ * Remember the decision.
+ */
+ state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
+ }
+
+ /*
+ fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
+ pinfo->fd -> num, le, be, decision, decisionToCache);
+ */
+ return decision;
+}
+
+/************************************************************************
+ *** ***
+ *** D E C O D I N G O N E P A C K E T ***
+ *** ***
+ ************************************************************************/
+
+/*
+ * Decode an initial connection request.
+ */
+static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
+{
+ int offset = 0;
+ int *offsetp = &offset;
+ proto_item *ti;
+ proto_tree *t;
+ guint16 auth_proto_name_length, auth_proto_data_length;
+ gint left;
+
+ ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+ proto_item_append_text(ti, ", Request, Initial connection request");
+ t = proto_item_add_subtree(ti, ett_x11);
+
+ CARD8(byte_order);
+ UNUSED(1);
+ CARD16(protocol_major_version);
+ CARD16(protocol_minor_version);
+ auth_proto_name_length = CARD16(authorization_protocol_name_length);
+ auth_proto_data_length = CARD16(authorization_protocol_data_length);
+ UNUSED(2);
+
+ if (auth_proto_name_length != 0) {
+ STRING8(authorization_protocol_name, auth_proto_name_length);
+ offset = ROUND_LENGTH(offset);
+ }
+
+ if (auth_proto_data_length != 0) {
+ STRING8(authorization_protocol_data, auth_proto_data_length);
+ offset = ROUND_LENGTH(offset);
+ }
+
+ if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
+ proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
+ little_endian);
+
+ /*
+ * This is the initial connection request...
+ */
+ state->iconn_frame = pinfo->fd->num;
+
+ /*
+ * ...and we're expecting a reply to it.
+ */
+ state->sequencenumber = 0;
+ g_hash_table_insert(state->seqtable, (int *)state->sequencenumber,
+ (int *)INITIAL_CONN);
+}
+
+static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
+ gboolean little_endian)
+{
+ int offset = 0, *offsetp = &offset, left;
+ unsigned char success;
+ int length_of_vendor;
+ int length_of_reason;
+ proto_item *ti;
+ proto_tree *t;
+
+ ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+ proto_item_append_text(ti, ", Reply, Initial connection reply");
+ t = proto_item_add_subtree(ti, ett_x11);
+
+ state->iconn_reply = pinfo->fd->num;
+ success = INT8(success);
+ if (success) {
+ UNUSED(1);
+ length_of_reason = 0;
+ }
+ else {
+ length_of_reason = INT8(length_of_reason);
+ }
+
+ INT16(protocol_major_version);
+ INT16(protocol_minor_version);
+ INT16(replylength);
+ if (success) {
+ INT32(release_number);
+ INT32(resource_id_base);
+ INT32(resource_id_mask);
+ INT32(motion_buffer_size);
+ length_of_vendor = INT16(length_of_vendor);
+ INT16(maximum_request_length);
+ INT8(number_of_screens_in_roots);
+ INT8(number_of_formats_in_pixmap_formats);
+ INT8(image_byte_order);
+ INT8(bitmap_format_bit_order);
+ INT8(bitmap_format_scanline_unit);
+ INT8(bitmap_format_scanline_pad);
+ INT8(min_keycode);
+ INT8(max_keycode);
+ UNUSED(4);
+ STRING8(vendor, length_of_vendor);
+ } else {
+ STRING8(reason, length_of_reason);
+ }
+
+ if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
+ UNDECODED(left);
+
+}
+
+static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, const char *sep, x11_conv_data_t *state,
+ gboolean little_endian)
+{
+ int offset = 0;
+ int *offsetp = &offset;
+ int next_offset;
+ proto_item *ti;
+ proto_tree *t;
+ int length, opcode, i;
+ guint8 v8, v8_2, v8_3;
+ guint16 v16;
+ guint32 v32;
+ gint left;
+ gchar *name;
+
+ length = VALUE16(tvb, 2) * 4;
+
+ if (length < 4) {
+ /* Bogus message length? */
+ return;
+ }
+
+ next_offset = offset + length;
+
+ ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+ t = proto_item_add_subtree(ti, ett_x11);
+
+ if (PACKET_IS_NEW(pinfo))
+ ++state->sequencenumber;
+
+ OPCODE();
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
+ val_to_str(opcode, state->opcode_vals,
+ "<Unknown opcode %d>"));
+
+ proto_item_append_text(ti, ", Request, opcode: %d (%s)",
+ opcode, val_to_str(opcode, state->opcode_vals,
+ "<Unknown opcode %d>"));
+
+ /*
+ * Does this request expect a reply?
+ */
+ switch(opcode) {
+
+ case X_QueryExtension:
+
+ /* necessary processing even if tree == NULL */
+
+ v16 = VALUE16(tvb, 4);
+ name = g_malloc(v16 + 1);
+ stringCopy(name, tvb_get_ptr(tvb, 8, v16), v16);
+
+ /* store string of extension, opcode will be set at reply */
+ i = 0;
+ while(i < MAX_OPCODES) {
+ if (state->opcode_vals[i].strptr == NULL) {
+ state->opcode_vals[i].strptr = name;
+ g_hash_table_insert(state->valtable,
+ (int *)state->sequencenumber,
+ (int *)&state->opcode_vals[i]);
+ break;
+ } else if (strcmp(state->opcode_vals[i].strptr,
+ name) == 0) {
+ g_hash_table_insert(state->valtable,
+ (int *)state->sequencenumber,
+ (int *)&state->opcode_vals[i]);
+ break;
+ }
+ i++;
+ }
+
+ /* QueryExtension expects a reply, fall through */
+
+ case X_AllocColor:
+ case X_AllocColorCells:
+ case X_AllocColorPlanes:
+ case X_AllocNamedColor:
+ case X_GetAtomName:
+ case X_GetFontPath:
+ case X_GetGeometry:
+ case X_GetImage:
+ case X_GetInputFocus:
+ case X_GetKeyboardControl:
+ case X_GetKeyboardMapping:
+ case X_GetModifierMapping:
+ case X_GetMotionEvents:
+ case X_GetPointerControl:
+ case X_GetPointerMapping:
+ case X_GetProperty:
+ case X_GetScreenSaver:
+ case X_GetSelectionOwner:
+ case X_GetWindowAttributes:
+ case X_GrabKeyboard:
+ case X_GrabPointer:
+ case X_InternAtom:
+ case X_ListExtensions:
+ case X_ListFonts:
+ case X_ListFontsWithInfo:
+ case X_ListHosts:
+ case X_ListInstalledColormaps:
+ case X_ListProperties:
+ case X_LookupColor:
+ case X_QueryBestSize:
+ case X_QueryColors:
+ case X_QueryFont:
+ case X_QueryKeymap:
+ case X_QueryPointer:
+ case X_QueryTextExtents:
+ case X_QueryTree:
+ case X_SetModifierMapping:
+ case X_SetPointerMapping:
+ case X_TranslateCoords:
+ /*
+ * Those requests expect a reply.
+ */
+ g_hash_table_insert(state->seqtable,
+ (int *)state->sequencenumber,
+ (int *)opcode);
+
+ break;
+
+ default:
+ /*
+ * With Extension, we don't know, so assume there could be one
+ */
+ if (opcode >= X_FirstExtension && opcode <= X_LastExtension) {
+ g_hash_table_insert(state->seqtable,
+ (int *)state->sequencenumber,
+ (int *)opcode);
+ }
+
+ /*
+ * No reply is expected from any other request.
+ */
+ break;
+ }
+
+ if (tree == NULL)
+ return;
+
+ switch(opcode) {
+
+ case X_CreateWindow:
+ CARD8(depth);
+ REQUEST_LENGTH();
+ WINDOW(wid);
+ WINDOW(parent);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ CARD16(border_width);
+ ENUM16(window_class);
+ VISUALID(visual);
+ windowAttributes(tvb, offsetp, t, little_endian);
+ break;
+
+ case X_ChangeWindowAttributes:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ windowAttributes(tvb, offsetp, t, little_endian);
+ break;
+
+ case X_GetWindowAttributes:
+ case X_DestroyWindow:
+ case X_DestroySubwindows:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case X_ChangeSaveSet:
+ ENUM8(save_set_mode);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case X_ReparentWindow:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ WINDOW(parent);
+ INT16(x);
+ INT16(y);
+ break;
+
+ case X_MapWindow:
+ case X_MapSubwindows:
+ case X_UnmapWindow:
+ case X_UnmapSubwindows:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case X_ConfigureWindow:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ BITMASK16(configure_window);
+ UNUSED(2);
+ BITFIELD(INT16, configure_window_mask, x);
+ BITFIELD(INT16, configure_window_mask, y);
+ BITFIELD(CARD16, configure_window_mask, width);
+ BITFIELD(CARD16, configure_window_mask, height);
+ BITFIELD(CARD16, configure_window_mask, border_width);
+ BITFIELD(WINDOW, configure_window_mask, sibling);
+ BITFIELD(ENUM8, configure_window_mask, stack_mode);
+ ENDBITMASK;
+ PAD();
+ break;
+
+ case X_CirculateWindow:
+ ENUM8(direction);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case X_GetGeometry:
+ case X_QueryTree:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ break;
+
+ case X_InternAtom:
+ BOOL(only_if_exists);
+ REQUEST_LENGTH();
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case X_GetAtomName:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ ATOM(atom);
+ break;
+
+ case X_ChangeProperty:
+ ENUM8(mode);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ ATOM(property);
+ ATOM(type);
+ CARD8(format);
+ UNUSED(3);
+ v32 = CARD32(data_length);
+ LISTofBYTE(data, v32);
+ PAD();
+ break;
+
+ case X_DeleteProperty:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ ATOM(property);
+ break;
+
+ case X_GetProperty:
+ BOOL(delete);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ ATOM(property);
+ ATOM(get_property_type);
+ CARD32(long_offset);
+ CARD32(long_length);
+ break;
+
+ case X_ListProperties:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case X_SetSelectionOwner:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(owner);
+ ATOM(selection);
+ TIMESTAMP(time);
+ break;
+
+ case X_GetSelectionOwner:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ ATOM(selection);
+ break;
+
+ case X_ConvertSelection:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(requestor);
+ ATOM(selection);
+ ATOM(target);
+ ATOM(property);
+ TIMESTAMP(time);
+ break;
+
+ case X_SendEvent:
+ BOOL(propagate);
+ REQUEST_LENGTH();
+ WINDOW(destination);
+ SETofEVENT(event_mask);
+ UNDECODED(32);
+ break;
+
+ case X_GrabPointer:
+ BOOL(owner_events);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofPOINTEREVENT(pointer_event_mask);
+ ENUM8(pointer_mode);
+ ENUM8(keyboard_mode);
+ WINDOW(confine_to);
+ CURSOR(cursor);
+ TIMESTAMP(time);
+ break;
+
+ case X_UngrabPointer:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ TIMESTAMP(time);
+ break;
+
+ case X_GrabButton:
+ BOOL(owner_events);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofPOINTEREVENT(event_mask);
+ ENUM8(pointer_mode);
+ ENUM8(keyboard_mode);
+ WINDOW(confine_to);
+ CURSOR(cursor);
+ BUTTON(button);
+ UNUSED(1);
+ SETofKEYMASK(modifiers);
+ break;
+
+ case X_UngrabButton:
+ BUTTON(button);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofKEYMASK(modifiers);
+ UNUSED(2);
+ break;
+
+ case X_ChangeActivePointerGrab:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cursor);
+ TIMESTAMP(time);
+ SETofPOINTEREVENT(event_mask);
+ UNUSED(2);
+ break;
+
+ case X_GrabKeyboard:
+ BOOL(owner_events);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ TIMESTAMP(time);
+ ENUM8(pointer_mode);
+ ENUM8(keyboard_mode);
+ UNUSED(2);
+ break;
+
+ case X_UngrabKeyboard:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ TIMESTAMP(time);
+ break;
+
+ case X_GrabKey:
+ BOOL(owner_events);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofKEYMASK(modifiers);
+ KEYCODE(key);
+ ENUM8(pointer_mode);
+ ENUM8(keyboard_mode);
+ UNUSED(3);
+ break;
+
+ case X_UngrabKey:
+ KEYCODE(key);
+ REQUEST_LENGTH();
+ WINDOW(grab_window);
+ SETofKEYMASK(modifiers);
+ UNUSED(2);
+ break;
+
+ case X_AllowEvents:
+ ENUM8(allow_events_mode);
+ REQUEST_LENGTH();
+ TIMESTAMP(time);
+ break;
+
+ case X_GrabServer:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_UngrabServer:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_QueryPointer:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case X_GetMotionEvents:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ TIMESTAMP(start);
+ TIMESTAMP(stop);
+ break;
+
+ case X_TranslateCoords:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(src_window);
+ WINDOW(dst_window);
+ INT16(src_x);
+ INT16(src_y);
+ break;
+
+ case X_WarpPointer:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(warp_pointer_src_window);
+ WINDOW(warp_pointer_dst_window);
+ INT16(src_x);
+ INT16(src_y);
+ CARD16(src_width);
+ CARD16(src_height);
+ INT16(dst_x);
+ INT16(dst_y);
+ break;
+
+ case X_SetInputFocus:
+ ENUM8(revert_to);
+ REQUEST_LENGTH();
+ WINDOW(focus);
+ TIMESTAMP(time);
+ break;
+
+ case X_GetInputFocus:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_QueryKeymap:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_OpenFont:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ FONT(fid);
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case X_CloseFont:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ FONT(font);
+ break;
+
+ case X_QueryFont:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ FONTABLE(font);
+ break;
+
+ case X_QueryTextExtents:
+ v8 = BOOL(odd_length);
+ REQUEST_LENGTH();
+ FONTABLE(font);
+ STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
+ PAD();
+ break;
+
+ case X_ListFonts:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CARD16(max_names);
+ v16 = FIELD16(pattern_length);
+ STRING8(pattern, v16);
+ PAD();
+ break;
+
+ case X_ListFontsWithInfo:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CARD16(max_names);
+ v16 = FIELD16(pattern_length);
+ STRING8(pattern, v16);
+ PAD();
+ break;
+
+ case X_SetFontPath:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ v16 = CARD16(str_number_in_path);
+ UNUSED(2);
+ LISTofSTRING8(path, v16);
+ PAD();
+ break;
+
+ case X_GetFontPath:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_CreatePixmap:
+ CARD8(depth);
+ REQUEST_LENGTH();
+ PIXMAP(pid);
+ DRAWABLE(drawable);
+ CARD16(width);
+ CARD16(height);
+ break;
+
+ case X_FreePixmap:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ PIXMAP(pixmap);
+ break;
+
+ case X_CreateGC:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(cid);
+ DRAWABLE(drawable);
+ gcAttributes(tvb, offsetp, t, little_endian);
+ break;
+
+ case X_ChangeGC:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(gc);
+ gcAttributes(tvb, offsetp, t, little_endian);
+ break;
+
+ case X_CopyGC:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(src_gc);
+ GCONTEXT(dst_gc);
+ gcMask(tvb, offsetp, t, little_endian);
+ break;
+
+ case X_SetDashes:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(gc);
+ CARD16(dash_offset);
+ v16 = FIELD16(dashes_length);
+ LISTofCARD8(dashes, v16);
+ PAD();
+ break;
+
+ case X_SetClipRectangles:
+ ENUM8(ordering);
+ REQUEST_LENGTH();
+ GCONTEXT(gc);
+ INT16(clip_x_origin);
+ INT16(clip_y_origin);
+ LISTofRECTANGLE(rectangles);
+ break;
+
+ case X_FreeGC:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ GCONTEXT(gc);
+ break;
+
+ case X_ClearArea:
+ BOOL(exposures);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ break;
+
+ case X_CopyArea:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(src_drawable);
+ DRAWABLE(dst_drawable);
+ GCONTEXT(gc);
+ INT16(src_x);
+ INT16(src_y);
+ INT16(dst_x);
+ INT16(dst_y);
+ CARD16(width);
+ CARD16(height);
+ break;
+
+ case X_CopyPlane:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(src_drawable);
+ DRAWABLE(dst_drawable);
+ GCONTEXT(gc);
+ INT16(src_x);
+ INT16(src_y);
+ INT16(dst_x);
+ INT16(dst_y);
+ CARD16(width);
+ CARD16(height);
+ CARD32(bit_plane);
+ break;
+
+ case X_PolyPoint:
+ ENUM8(coordinate_mode);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofPOINT(points, v16 - 12);
+ break;
+
+ case X_PolyLine:
+ ENUM8(coordinate_mode);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofPOINT(points, v16 - 12);
+ break;
+
+ case X_PolySegment:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofSEGMENT(segments);
+ break;
+
+ case X_PolyRectangle:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofRECTANGLE(rectangles);
+ break;
+
+ case X_PolyArc:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofARC(arcs);
+ break;
+
+ case X_FillPoly:
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ ENUM8(shape);
+ ENUM8(coordinate_mode);
+ UNUSED(2);
+ LISTofPOINT(points, v16 - 16);
+ break;
+
+ case X_PolyFillRectangle:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofRECTANGLE(rectangles);
+ break;
+
+ case X_PolyFillArc:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ LISTofARC(arcs);
+ break;
+
+ case X_PutImage:
+ ENUM8(image_format);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ CARD16(width);
+ CARD16(height);
+ INT16(dst_x);
+ INT16(dst_y);
+ CARD8(left_pad);
+ CARD8(depth);
+ UNUSED(2);
+ LISTofBYTE(data, v16 - 24);
+ PAD();
+ break;
+
+ case X_GetImage:
+ ENUM8(image_pixmap_format);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ CARD32(plane_mask);
+ break;
+
+ case X_PolyText8:
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ INT16(x);
+ INT16(y);
+ LISTofTEXTITEM8(items);
+ PAD();
+ break;
+
+ case X_PolyText16:
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ INT16(x);
+ INT16(y);
+ LISTofTEXTITEM16(items);
+ PAD();
+ break;
+
+ case X_ImageText8:
+ v8 = FIELD8(string_length);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ INT16(x);
+ INT16(y);
+ STRING8(string, v8);
+ PAD();
+ break;
+
+ case X_ImageText16:
+ v8 = FIELD8(string_length);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ GCONTEXT(gc);
+ INT16(x);
+ INT16(y);
+ STRING16(string16, v8);
+ PAD();
+ break;
+
+ case X_CreateColormap:
+ ENUM8(alloc);
+ REQUEST_LENGTH();
+ COLORMAP(mid);
+ WINDOW(window);
+ VISUALID(visual);
+ break;
+
+ case X_FreeColormap:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ break;
+
+ case X_CopyColormapAndFree:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(mid);
+ COLORMAP(src_cmap);
+ break;
+
+ case X_InstallColormap:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ break;
+
+ case X_UninstallColormap:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ break;
+
+ case X_ListInstalledColormaps:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ WINDOW(window);
+ break;
+
+ case X_AllocColor:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD16(red);
+ CARD16(green);
+ CARD16(blue);
+ UNUSED(2);
+ break;
+
+ case X_AllocNamedColor:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case X_AllocColorCells:
+ BOOL(contiguous);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD16(colors);
+ CARD16(planes);
+ break;
+
+ case X_AllocColorPlanes:
+ BOOL(contiguous);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD16(colors);
+ CARD16(reds);
+ CARD16(greens);
+ CARD16(blues);
+ break;
+
+ case X_FreeColors:
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD32(plane_mask);
+ LISTofCARD32(pixels, v16 - 12);
+ break;
+
+ case X_StoreColors:
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ COLORMAP(cmap);
+ LISTofCOLORITEM(color_items, v16 - 8);
+ break;
+
+ case X_StoreNamedColor:
+ COLOR_FLAGS(color);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ CARD32(pixel);
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case X_QueryColors:
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ COLORMAP(cmap);
+ LISTofCARD32(pixels, v16 - 8);
+ break;
+
+ case X_LookupColor:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ COLORMAP(cmap);
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case X_CreateCursor:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cid);
+ PIXMAP(source_pixmap);
+ PIXMAP(mask);
+ CARD16(fore_red);
+ CARD16(fore_green);
+ CARD16(fore_blue);
+ CARD16(back_red);
+ CARD16(back_green);
+ CARD16(back_blue);
+ CARD16(x);
+ CARD16(y);
+ break;
+
+ case X_CreateGlyphCursor:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cid);
+ FONT(source_font);
+ FONT(mask_font);
+ CARD16(source_char);
+ CARD16(mask_char);
+ CARD16(fore_red);
+ CARD16(fore_green);
+ CARD16(fore_blue);
+ CARD16(back_red);
+ CARD16(back_green);
+ CARD16(back_blue);
+ break;
+
+ case X_FreeCursor:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cursor);
+ break;
+
+ case X_RecolorCursor:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CURSOR(cursor);
+ CARD16(fore_red);
+ CARD16(fore_green);
+ CARD16(fore_blue);
+ CARD16(back_red);
+ CARD16(back_green);
+ CARD16(back_blue);
+ break;
+
+ case X_QueryBestSize:
+ ENUM8(class);
+ REQUEST_LENGTH();
+ DRAWABLE(drawable);
+ CARD16(width);
+ CARD16(height);
+ break;
+
+ case X_QueryExtension:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ v16 = FIELD16(name_length);
+ UNUSED(2);
+ STRING8(name, v16);
+ PAD();
+ break;
+
+ case X_ListExtensions:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_ChangeKeyboardMapping:
+ v8 = FIELD8(keycode_count);
+ REQUEST_LENGTH();
+ v8_2 = KEYCODE(first_keycode);
+ v8_3 = FIELD8(keysyms_per_keycode);
+ UNUSED(2);
+ LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
+ break;
+
+ case X_GetKeyboardMapping:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ state->request.GetKeyboardMapping.first_keycode
+ = KEYCODE(first_keycode);
+ FIELD8(count);
+ UNUSED(2);
+ break;
+
+ case X_ChangeKeyboardControl:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ BITMASK32(keyboard_value);
+ BITFIELD(INT8, keyboard_value_mask, key_click_percent);
+ BITFIELD(INT8, keyboard_value_mask, bell_percent);
+ BITFIELD(INT16, keyboard_value_mask, bell_pitch);
+ BITFIELD(INT16, keyboard_value_mask, bell_duration);
+ BITFIELD(INT16, keyboard_value_mask, led);
+ BITFIELD(ENUM8, keyboard_value_mask, led_mode);
+ BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
+ BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
+ ENDBITMASK;
+ break;
+
+ case X_GetKeyboardControl:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_Bell:
+ INT8(percent);
+ REQUEST_LENGTH();
+ break;
+
+ case X_ChangePointerControl:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ INT16(acceleration_numerator);
+ INT16(acceleration_denominator);
+ INT16(threshold);
+ BOOL(do_acceleration);
+ BOOL(do_threshold);
+ break;
+
+ case X_GetPointerControl:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_SetScreenSaver:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ INT16(timeout);
+ INT16(interval);
+ ENUM8(prefer_blanking);
+ ENUM8(allow_exposures);
+ UNUSED(2);
+ break;
+
+ case X_GetScreenSaver:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_ChangeHosts:
+ ENUM8(change_host_mode);
+ REQUEST_LENGTH();
+ v8 = ENUM8(family);
+ UNUSED(1);
+ v16 = CARD16(address_length);
+ if (v8 == FAMILY_INTERNET && v16 == 4) {
+ /*
+ * IPv4 addresses.
+ * XXX - what about IPv6? Is that a family of
+ * FAMILY_INTERNET (0) with a length of 16?
+ */
+ LISTofCARD8(ip_address, v16);
+ } else
+ LISTofCARD8(address, v16);
+ break;
+
+ case X_ListHosts:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_SetAccessControl:
+ ENUM8(access_mode);
+ REQUEST_LENGTH();
+ break;
+
+ case X_SetCloseDownMode:
+ ENUM8(close_down_mode);
+ REQUEST_LENGTH();
+ break;
+
+ case X_KillClient:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ CARD32(resource);
+ break;
+
+ case X_RotateProperties:
+ UNUSED(1);
+ v16 = REQUEST_LENGTH();
+ WINDOW(window);
+ CARD16(property_number);
+ INT16(delta);
+ LISTofATOM(properties, (v16 - 12));
+ break;
+
+ case X_ForceScreenSaver:
+ ENUM8(screen_saver_mode);
+ REQUEST_LENGTH();
+ break;
+
+ case X_SetPointerMapping:
+ v8 = FIELD8(map_length);
+ REQUEST_LENGTH();
+ LISTofCARD8(map, v8);
+ PAD();
+ break;
+
+ case X_GetPointerMapping:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_SetModifierMapping:
+ v8 = FIELD8(keycodes_per_modifier);
+ REQUEST_LENGTH();
+ LISTofKEYCODE(state->modifiermap, keycodes, v8);
+ break;
+
+ case X_GetModifierMapping:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+
+ case X_NoOperation:
+ UNUSED(1);
+ REQUEST_LENGTH();
+ break;
+ }
+
+ if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
+ UNDECODED(left);
+}
+
+static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree)
+{
+ volatile int offset = 0;
+ int length_remaining;
+ volatile gboolean little_endian;
+ guint8 opcode;
+ volatile int plen;
+ proto_item *ti;
+ proto_tree *t;
+ volatile gboolean is_initial_creq;
+ guint16 auth_proto_len, auth_data_len;
+ const char *volatile sep = NULL;
+ conversation_t *conversation;
+ x11_conv_data_t *state;
+ int length;
+ tvbuff_t *next_tvb;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * We use "tvb_ensure_length_remaining()" to make sure there
+ * actually *is* data remaining.
+ *
+ * This means we're guaranteed that "length_remaining" is
+ * positive.
+ */
+ length_remaining = tvb_ensure_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (x11_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the X11 request header split across
+ * segment boundaries?
+ */
+ if (length_remaining < 4) {
+ /*
+ * Yes. Tell the TCP dissector where the data
+ * for this message starts in the data it handed
+ * us, and how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4 - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Get the state for this conversation; create the conversation
+ * if we don't have one, and create the state if we don't have
+ * any.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL) {
+ /*
+ * No - create one.
+ */
+ conversation = conversation_new(&pinfo->src,
+ &pinfo->dst, pinfo->ptype, pinfo->srcport,
+ pinfo->destport, 0);
+ }
+
+ /*
+ * Is there state attached to this conversation?
+ */
+ if ((state = conversation_get_proto_data(conversation, proto_x11))
+ == NULL)
+ x11_stateinit(&state, conversation);
+
+ /*
+ * Guess the byte order if we don't already know it.
+ */
+ little_endian = guess_byte_ordering(tvb, pinfo, state);
+
+ /*
+ * Get the opcode and length of the putative X11 request.
+ */
+ opcode = VALUE8(tvb, 0);
+ plen = VALUE16(tvb, offset + 2);
+
+ if (plen == 0) {
+ /*
+ * This can't be 0, as it includes the header length.
+ * A different choice of byte order wouldn't have
+ * helped.
+ * Give up.
+ */
+ ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
+ FALSE);
+ t = proto_item_add_subtree(ti, ett_x11);
+ proto_tree_add_text(t, tvb, offset, -1,
+ "Bogus request length (0)");
+ return;
+ }
+
+ if (state->iconn_frame == pinfo->fd->num ||
+ (g_hash_table_lookup(state->seqtable,
+ (int *)state->sequencenumber) == (int *)NOTHING_SEEN &&
+ (opcode == 'B' || opcode == 'l') &&
+ (plen == 11 || plen == 2816))) {
+ /*
+ * Either
+ *
+ * we saw this on the first pass and this is
+ * it again
+ *
+ * or
+ * we haven't already seen any requests, the first
+ * byte of the message is 'B' or 'l', and the 16-bit
+ * integer 2 bytes into the data stream is either 11
+ * or a byte-swapped 11.
+ *
+ * This means it's probably an initial connection
+ * request, not a message.
+ *
+ * 'B' is decimal 66, which is the opcode for a
+ * PolySegment request; unfortunately, 11 is a valid
+ * length for a PolySegment request request, so we
+ * might mis-identify that request. (Are there any
+ * other checks we can do?)
+ *
+ * 'l' is decimal 108, which is the opcode for a
+ * GetScreenSaver request; the only valid length
+ * for that request is 1.
+ */
+ is_initial_creq = TRUE;
+
+ /*
+ * We now know the byte order. Override the guess.
+ */
+ if (state->byte_order == BYTE_ORDER_UNKNOWN) {
+ if (opcode == 'B') {
+ /*
+ * Big-endian.
+ */
+ state->byte_order = BYTE_ORDER_BE;
+ little_endian = FALSE;
+ } else {
+ /*
+ * Little-endian.
+ */
+ state->byte_order = BYTE_ORDER_LE;
+ little_endian = TRUE;
+ }
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (x11_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the fixed-length portion of the
+ * initial connection header split across
+ * segment boundaries?
+ */
+ if (length_remaining < 10) {
+ /*
+ * Yes. Tell the TCP dissector where the
+ * data for this message starts in the data
+ * it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 10 - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Get the lengths of the authorization protocol and
+ * the authorization data.
+ */
+ auth_proto_len = VALUE16(tvb, offset + 6);
+ auth_data_len = VALUE16(tvb, offset + 8);
+ plen = 12 + ROUND_LENGTH(auth_proto_len) +
+ ROUND_LENGTH(auth_data_len);
+ } else {
+ /*
+ * This is probably an ordinary request.
+ */
+ is_initial_creq = FALSE;
+
+ /*
+ * The length of a request is in 4-byte words.
+ */
+ plen *= 4;
+ }
+
+ /*
+ * Can we do reassembly?
+ */
+ if (x11_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the X11 request split across segment
+ * boundaries?
+ */
+ if (length_remaining < plen) {
+ /*
+ * Yes. Tell the TCP dissector where the data
+ * for this message starts in the data it handed
+ * us, and how many more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = plen - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload
+ * we have available. Make its reported length the
+ * amount of data in the X11 request.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector
+ * will throw a BoundsError exception, rather than a
+ * ReportedBoundsError exception. We really want a tvbuff
+ * where the length is "length", the reported length is "plen",
+ * and the "if the snapshot length were infinite" length is the
+ * minimum of the reported length of the tvbuff handed to us
+ * and "plen", with a new type of exception thrown if the offset
+ * is within the reported length but beyond that third length,
+ * with that exception getting the "Unreassembled Packet" error.
+ */
+ length = length_remaining;
+ if (length > plen)
+ length = plen;
+ next_tvb = tvb_new_subset(tvb, offset, length, plen);
+
+ /*
+ * Set the column appropriately.
+ */
+ if (is_initial_creq) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO,
+ "Initial connection request");
+ } else {
+ if (sep == NULL) {
+ /*
+ * We haven't set the column yet; set it.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "Requests");
+
+ /*
+ * Initialize the separator.
+ */
+ sep = ":";
+ }
+ }
+
+ /*
+ * Dissect the X11 request.
+ *
+ * Catch the ReportedBoundsError exception; if this
+ * particular message happens to get a ReportedBoundsError
+ * exception, that doesn't mean that we should stop
+ * dissecting X11 requests within this frame or chunk of
+ * reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing
+ * more to see, so we just re-throw it.
+ */
+ TRY {
+ if (is_initial_creq) {
+ dissect_x11_initial_conn(next_tvb, pinfo, tree,
+ state, little_endian);
+ } else {
+ dissect_x11_request(next_tvb, pinfo, tree, sep,
+ state, little_endian);
+ }
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ }
+ ENDTRY;
+
+ /*
+ * Skip the X11 message.
+ */
+ offset += plen;
+
+ sep = ",";
+ }
+}
+
+static void
+x11_stateinit(x11_conv_data_t **state, conversation_t *conversation)
+{
+ static x11_conv_data_t stateinit;
+ int i = 0;
+
+ *state = g_mem_chunk_alloc(x11_state_chunk);
+ **state = stateinit;
+
+ /* initialise opcodes */
+ while (1) {
+ if (opcode_vals[i].strptr == NULL) break;
+ (*state)->opcode_vals[i].value = opcode_vals[i].value;
+ (*state)->opcode_vals[i].strptr = opcode_vals[i].strptr;
+ i++;
+ }
+ while (i <= MAX_OPCODES) {
+ (*state)->opcode_vals[i].value = 0;
+ (*state)->opcode_vals[i].strptr = NULL;
+ i++;
+ }
+
+ (*state)->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
+ (*state)->valtable = g_hash_table_new(g_direct_hash, g_direct_equal);
+ g_hash_table_insert((*state)->seqtable, (int *)0, (int *)NOTHING_SEEN);
+ (*state)->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
+ conversation_add_proto_data(conversation, proto_x11, *state);
+}
+
+
+static void
+dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+/* Set up structures we will need to add the protocol subtree and manage it */
+ volatile int offset, plen;
+ tvbuff_t * volatile next_tvb;
+ conversation_t *conversation;
+ x11_conv_data_t *state;
+ gboolean little_endian;
+ int length_remaining;
+ const char *volatile sep = NULL;
+
+
+ /*
+ * Get the state for this conversation; create the conversation
+ * if we don't have one, and create the state if we don't have
+ * any.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ if (conversation == NULL) {
+ /*
+ * No - create one.
+ */
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+ }
+
+ /*
+ * Is there state attached to this conversation?
+ */
+ if ((state = conversation_get_proto_data(conversation, proto_x11))
+ == NULL) {
+ /*
+ * No - create a state structure and attach it.
+ */
+ x11_stateinit(&state, conversation);
+ }
+
+ /*
+ * Guess the byte order if we don't already know it.
+ */
+ little_endian = guess_byte_ordering(tvb, pinfo, state);
+
+ offset = 0;
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ /*
+ * We use "tvb_ensure_length_remaining()" to make sure there
+ * actually *is* data remaining.
+ *
+ * This means we're guaranteed that "length_remaining" is
+ * positive.
+ */
+ length_remaining = tvb_ensure_length_remaining(tvb, offset);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (x11_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the X11 reply header split across
+ * segment boundaries?
+ */
+ if (length_remaining < 8) {
+ /*
+ * Yes. Tell the TCP dissector where the data
+ * for this message starts in the data it handed
+ * us, and how many more bytes we need, and
+ * return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4 - length_remaining;
+ return;
+ }
+ }
+
+ /*
+ * Find out what kind of a reply it is.
+ * There are four possible:
+ * - reply to initial connection
+ * - errorreply (a request generated an error)
+ * - requestreply (reply to a request)
+ * - event (some event occured)
+ */
+ if (g_hash_table_lookup(state->seqtable,
+ (int *)state->sequencenumber) == (int *)INITIAL_CONN
+ || (state->iconn_reply == pinfo->fd->num)) {
+ /*
+ * Either the connection is in the "initial
+ * connection" state, or this frame is known
+ * to have the initial connection reply.
+ * That means this is the initial connection
+ * reply.
+ */
+ plen = 8 + VALUE16(tvb, offset + 6) * 4;
+
+ HANDLE_REPLY(plen, length_remaining,
+ "Initial connection reply",
+ dissect_x11_initial_reply);
+ } else {
+ /*
+ * This isn't an initial connection reply
+ * (XXX - unless we missed the initial
+ * connection request). Look at the first
+ * byte to determine what it is; errors
+ * start with a byte of 0, replies start
+ * with a byte of 1, events start with
+ * a byte with of 2 or greater.
+ */
+ switch (tvb_get_guint8(tvb, offset)) {
+
+ case 0:
+ plen = 32;
+ HANDLE_REPLY(plen, length_remaining,
+ "Error", dissect_x11_error);
+ break;
+
+ case 1:
+ /* replylength is in units of four. */
+ plen = 32 + VALUE32(tvb, offset + 4) * 4;
+
+ HANDLE_REPLY(plen, length_remaining,
+ "Reply", dissect_x11_reply);
+ break;
+
+ default:
+ /* Event */
+ plen = 32;
+ HANDLE_REPLY(plen, length_remaining,
+ "Event", dissect_x11_event);
+ break;
+ }
+ }
+
+ offset += plen;
+ }
+
+ return;
+}
+
+static void
+dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const char *volatile sep, x11_conv_data_t *volatile state,
+ gboolean little_endian)
+{
+ int offset = 0, *offsetp = &offset, length, left, opcode;
+ int major_opcode, sequence_number;
+ value_string *vals_p;
+ proto_item *ti;
+ proto_tree *t;
+
+ ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
+ tvb_reported_length_remaining(tvb, offset),
+ FALSE);
+ t = proto_item_add_subtree(ti, ett_x11);
+
+
+ /*
+ * XXX - this doesn't work correctly if either
+ *
+ * 1) the request sequence number wraps in the lower 16
+ * bits;
+ *
+ * 2) we don't see the initial connection request and the
+ * resynchronization of sequence number fails and thus
+ * don't have the right sequence numbers
+ *
+ * 3) we don't have all the packets in the capture and
+ * get out of sequence.
+ *
+ * We might, instead, want to assume that a reply is a reply to
+ * the most recent not-already-replied-to request in the same
+ * connection. That also might mismatch replies to requests if
+ * packets are lost, but there's nothing you can do to fix that.
+ */
+
+ sequence_number = VALUE16(tvb, offset + 2);
+ opcode = (int)g_hash_table_lookup(state->seqtable,
+ (int *)sequence_number);
+
+ if (state->iconn_frame == 0 && state->resync == FALSE) {
+
+ /*
+ * We don't see the initial connection request and no
+ * resynchronization has been performed yet (first reply),
+ * set the current sequence number to the one of the
+ * current reply (this is only performed once).
+ */
+ state->sequencenumber = sequence_number;
+ state->resync = TRUE;
+ }
+
+ if (opcode == UNKNOWN_OPCODE) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "%s to unknown request", sep);
+ proto_item_append_text(ti, ", Reply to unknown request");
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ sep,
+ val_to_str(opcode, state->opcode_vals,
+ "<Unknown opcode %d>"));
+
+ proto_item_append_text(ti, ", Reply, opcode: %d (%s)",
+ opcode, val_to_str(opcode,
+ state->opcode_vals,
+ "<Unknown opcode %d>"));
+ }
+
+ switch (opcode) {
+
+ /*
+ * Replies that need special processing outside tree
+ */
+
+ case X_QueryExtension:
+
+ /*
+ * if extension is present and request is known:
+ * store opcode of extension in value_string of
+ * opcodes
+ */
+ if (!VALUE8(tvb, offset + 8)) {
+ /* not present */
+ break;
+ }
+
+ vals_p = g_hash_table_lookup(state->valtable,
+ (int *)sequence_number);
+ if (vals_p != NULL) {
+ major_opcode = VALUE8(tvb, offset + 9);
+ vals_p->value = major_opcode;
+ g_hash_table_remove(state->valtable,
+ (int *)sequence_number);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (tree == NULL)
+ return;
+
+ switch (opcode) {
+ /*
+ * Requests that expect a reply.
+ */
+
+ case X_GetWindowAttributes:
+ REPLYCONTENTS_COMMON();
+ break;
+
+ case X_GetGeometry:
+ REPLY(reply);
+ CARD8(depth);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ WINDOW(rootwindow);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ CARD16(border_width);
+ UNUSED(10);
+ break;
+
+ case X_QueryTree:
+ REPLYCONTENTS_COMMON();
+ break;
+
+ case X_InternAtom:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ ATOM(atom);
+ UNUSED(20);
+ break;
+
+ case X_GetAtomName:
+ REPLYCONTENTS_COMMON();
+ break;
+
+ case X_GetProperty:
+ REPLY(reply);
+ CARD8(format);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ length = REPLYLENGTH(replylength);
+ ATOM(get_property_type);
+ CARD32(bytes_after);
+ CARD32(valuelength);
+ UNUSED(12);
+ break;
+
+ case X_ListProperties:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ length = CARD16(property_number);
+ UNUSED(22);
+ LISTofATOM(properties, length*4);
+ break;
+
+ case X_GetSelectionOwner:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ WINDOW(owner);
+ UNUSED(20);
+ break;
+
+ case X_GrabPointer:
+ case X_GrabKeyboard:
+ REPLY(reply);
+ ENUM8(grab_status);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ UNUSED(24);
+ break;
+
+ case X_QueryPointer:
+ REPLY(reply);
+ BOOL(same_screen);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ WINDOW(rootwindow);
+ WINDOW(childwindow);
+ INT16(root_x);
+ INT16(root_y);
+ INT16(win_x);
+ INT16(win_y);
+ SETofKEYBUTMASK(mask);
+ UNUSED(6);
+ break;
+
+ case X_GetMotionEvents:
+ REPLYCONTENTS_COMMON();
+ break;
+
+ case X_TranslateCoords:
+ REPLY(reply);
+ BOOL(same_screen);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ WINDOW(childwindow);
+ INT16(dst_x);
+ INT16(dst_y);
+ UNUSED(16);
+ break;
+
+ case X_GetInputFocus:
+ REPLY(reply);
+ ENUM8(revert_to);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ WINDOW(focus);
+ UNUSED(20);
+ break;
+
+ case X_QueryKeymap:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ LISTofCARD8(keys, 32);
+ break;
+
+ case X_QueryFont:
+ case X_QueryTextExtents:
+ case X_ListFonts:
+ case X_GetImage:
+ case X_ListInstalledColormaps:
+ REPLYCONTENTS_COMMON();
+ break;
+
+ case X_AllocColor:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ CARD16(red);
+ CARD16(green);
+ CARD16(blue);
+ UNUSED(2);
+ CARD32(pixel);
+ UNUSED(12);
+ break;
+
+ case X_QueryColors:
+ REPLYCONTENTS_COMMON();
+ break;
+
+ case X_LookupColor:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ CARD16(exact_red);
+ CARD16(exact_green);
+ CARD16(exact_blue);
+ CARD16(visual_red);
+ CARD16(visual_green);
+ CARD16(visual_blue);
+ UNUSED(12);
+ break;
+
+ case X_QueryBestSize:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ CARD16(width);
+ CARD16(height);
+ UNUSED(20);
+ break;
+
+ case X_QueryExtension:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ BOOL(present);
+ CARD8(major_opcode);
+ CARD8(first_event);
+ CARD8(first_error);
+ UNUSED(20);
+ break;
+
+ case X_ListExtensions:
+ REPLYCONTENTS_COMMON();
+ break;
+
+ case X_GetKeyboardMapping:
+ state->first_keycode =
+ state->request.GetKeyboardMapping.first_keycode;
+ REPLY(reply);
+ state->keysyms_per_keycode =
+ FIELD8(keysyms_per_keycode);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ length = REPLYLENGTH(replylength);
+ UNUSED(24);
+ LISTofKEYSYM(keysyms, state->keycodemap,
+ state->request.GetKeyboardMapping.first_keycode,
+ length / state->keysyms_per_keycode,
+ state->keysyms_per_keycode);
+ break;
+
+ case X_GetKeyboardControl:
+ REPLYCONTENTS_COMMON();
+ break;
+
+ case X_GetPointerControl:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ CARD16(acceleration_numerator);
+ CARD16(acceleration_denominator);
+ CARD16(threshold);
+ UNUSED(18);
+ break;
+
+ case X_GetScreenSaver:
+ REPLY(reply);
+ UNUSED(1);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ CARD16(timeout);
+ CARD16(interval);
+ ENUM8(prefer_blanking);
+ ENUM8(allow_exposures);
+ UNUSED(18);
+ break;
+
+ case X_ListHosts:
+ case X_SetPointerMapping:
+ case X_GetPointerMapping:
+ case X_SetModifierMapping:
+ REPLYCONTENTS_COMMON();
+ break;
+
+ case X_GetModifierMapping:
+ REPLY(reply);
+ state->keycodes_per_modifier =
+ FIELD8(keycodes_per_modifier);
+ SEQUENCENUMBER_REPLY(sequencenumber);
+ REPLYLENGTH(replylength);
+ UNUSED(24);
+ LISTofKEYCODE(state->modifiermap, keycodes,
+ state->keycodes_per_modifier);
+ break;
+
+ default:
+ REPLYCONTENTS_COMMON();
+ }
+
+ if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
+ UNDECODED(left);
+}
+
+static void
+same_screen_focus(tvbuff_t *tvb, int *offsetp, proto_tree *t)
+{
+ proto_item *ti;
+ guint32 bitmask_value;
+ int bitmask_offset;
+ int bitmask_size;
+ proto_tree *bitmask_tree;
+
+ bitmask_value = VALUE8(tvb, *offsetp);
+ bitmask_offset = *offsetp;
+ bitmask_size = 1;
+
+ ti = proto_tree_add_uint(t, hf_x11_same_screen_focus_mask, tvb, *offsetp, 1,
+ bitmask_value);
+ bitmask_tree = proto_item_add_subtree(ti, ett_x11_same_screen_focus);
+ FLAG(same_screen_focus, focus);
+ FLAG(same_screen_focus, same_screen);
+
+ *offsetp += 1;
+}
+
+static void
+dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const char *volatile sep, x11_conv_data_t *volatile state,
+ gboolean little_endian)
+{
+ int offset = 0, *offsetp = &offset, left;
+ unsigned char eventcode;
+ proto_item *ti;
+ proto_tree *t;
+
+ ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+ t = proto_item_add_subtree(ti, ett_x11);
+
+ eventcode = tvb_get_guint8(tvb, offset);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ sep, val_to_str(eventcode, eventcode_vals,
+ "<Unknown eventcode %u>"));
+
+ proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
+ eventcode,
+ "eventcode: %d (%s)",
+ eventcode,
+ val_to_str(eventcode, eventcode_vals,
+ "<Unknown eventcode %u>"));
+ ++offset;
+
+ proto_item_append_text(ti, ", Event, eventcode: %d (%s)",
+ eventcode, val_to_str(eventcode, eventcode_vals,
+ "<Unknown eventcode %u>"));
+
+ if (tree == NULL)
+ return;
+
+ switch (eventcode) {
+ case KeyPress:
+ case KeyRelease: {
+ int code, mask;
+
+ /* need to do some prefetching here ... */
+ code = VALUE8(tvb, offset);
+ mask = VALUE16(tvb, 28);
+
+ KEYCODE_DECODED(keycode, code, mask);
+ CARD16(event_sequencenumber);
+ EVENTCONTENTS_COMMON();
+ BOOL(same_screen);
+ UNUSED(1);
+ break;
+ }
+
+ case ButtonPress:
+ case ButtonRelease:
+ BUTTON(eventbutton);
+ CARD16(event_sequencenumber);
+ EVENTCONTENTS_COMMON();
+ BOOL(same_screen);
+ UNUSED(1);
+ break;
+
+ case MotionNotify:
+ CARD8(detail);
+ CARD16(event_sequencenumber);
+ EVENTCONTENTS_COMMON();
+ BOOL(same_screen);
+ UNUSED(1);
+ break;
+
+ case EnterNotify:
+ case LeaveNotify:
+ ENUM8(event_detail);
+ CARD16(event_sequencenumber);
+ EVENTCONTENTS_COMMON();
+ ENUM8(grab_mode);
+ same_screen_focus(tvb, offsetp, t);
+ break;
+
+ case FocusIn:
+ case FocusOut:
+ ENUM8(focus_detail);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ ENUM8(focus_mode);
+ UNUSED(23);
+ break;
+
+ case KeymapNotify:
+ break;
+
+ case Expose:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ CARD16(count);
+ UNUSED(14);
+ break;
+
+ case GraphicsExpose:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ DRAWABLE(drawable);
+ CARD16(x);
+ CARD16(y);
+ CARD16(width);
+ CARD16(height);
+ CARD16(minor_opcode);
+ CARD16(count);
+ CARD8(major_opcode);
+ UNUSED(11);
+ break;
+
+ case NoExpose:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ DRAWABLE(drawable);
+ CARD16(minor_opcode);
+ CARD8(major_opcode);
+ UNUSED(21);
+ break;
+
+ case VisibilityNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ ENUM8(visibility_state);
+ UNUSED(23);
+ break;
+
+ case CreateNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(parent);
+ WINDOW(eventwindow);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ CARD16(border_width);
+ BOOL(override_redirect);
+ UNUSED(9);
+ break;
+
+ case DestroyNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ WINDOW(window);
+ UNUSED(20);
+ break;
+
+ case UnmapNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ WINDOW(window);
+ BOOL(from_configure);
+ UNUSED(19);
+ break;
+
+ case MapNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ WINDOW(window);
+ BOOL(override_redirect);
+ UNUSED(19);
+ break;
+
+ case MapRequest:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(parent);
+ WINDOW(eventwindow);
+ UNUSED(20);
+ break;
+
+ case ReparentNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ WINDOW(window);
+ WINDOW(parent);
+ INT16(x);
+ INT16(y);
+ BOOL(override_redirect);
+ UNUSED(11);
+ break;
+
+ case ConfigureNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ WINDOW(window);
+ WINDOW(above_sibling);
+ INT16(x);
+ INT16(y);
+ CARD16(width);
+ CARD16(height);
+ CARD16(border_width);
+ BOOL(override_redirect);
+ UNUSED(5);
+ break;
+
+ case ConfigureRequest:
+ break;
+
+ case GravityNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ WINDOW(window);
+ INT16(x);
+ INT16(y);
+ UNUSED(16);
+ break;
+
+ case ResizeRequest:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ CARD16(width);
+ CARD16(height);
+ UNUSED(20);
+ break;
+
+ case CirculateNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ WINDOW(window);
+ UNUSED(4);
+ ENUM8(place);
+ UNUSED(15);
+ break;
+
+ case CirculateRequest:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(parent);
+ WINDOW(eventwindow);
+ UNUSED(4);
+ ENUM8(place);
+ UNUSED(15);
+ break;
+
+ case PropertyNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ ATOM(atom);
+ TIMESTAMP(time);
+ ENUM8(property_state);
+ UNUSED(15);
+ break;
+
+ case SelectionClear:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ TIMESTAMP(time);
+ WINDOW(owner);
+ ATOM(selection);
+ UNUSED(16);
+ break;
+
+ case SelectionRequest:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ TIMESTAMP(time);
+ WINDOW(owner);
+ WINDOW(requestor);
+ ATOM(selection);
+ ATOM(target);
+ ATOM(property);
+ UNUSED(4);
+ break;
+
+ case SelectionNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ TIMESTAMP(time);
+ WINDOW(requestor);
+ ATOM(selection);
+ ATOM(target);
+ ATOM(property);
+ UNUSED(8);
+ break;
+
+ case ColormapNotify:
+ UNUSED(1);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ COLORMAP(cmap);
+ BOOL(new);
+ ENUM8(colormap_state);
+ UNUSED(18);
+ break;
+
+ case ClientMessage:
+ CARD8(format);
+ CARD16(event_sequencenumber);
+ WINDOW(eventwindow);
+ ATOM(type);
+ LISTofBYTE(data, 20);
+ break;
+
+ case MappingNotify:
+ default:
+ break;
+ }
+
+ if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
+ UNDECODED(left);
+
+ return;
+}
+
+static void
+dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ const char *volatile sep, x11_conv_data_t *volatile state _U_,
+ gboolean little_endian)
+{
+ int offset = 0, *offsetp = &offset, left;
+ unsigned char errorcode, error;
+ proto_item *ti;
+ proto_tree *t;
+
+ ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+ t = proto_item_add_subtree(ti, ett_x11);
+
+ error = tvb_get_guint8(tvb, offset);
+ CARD8(error);
+
+ errorcode = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
+ sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
+
+ proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
+ errorcode,
+ "errorcode: %d (%s)",
+ errorcode,
+ val_to_str(errorcode, errorcode_vals,
+ "<Unknown errocode %u>"));
+ ++offset;
+
+ proto_item_append_text(ti, ", Error, errorcode: %d (%s)",
+ errorcode, val_to_str(errorcode, errorcode_vals,
+ "<Unknown errorcode %u>"));
+
+ if (tree == NULL)
+ return;
+
+ CARD16(error_sequencenumber);
+
+ switch (errorcode) {
+ case BadValue:
+ CARD32(error_badvalue);
+ break;
+
+ default:
+ UNDECODED(4);
+ }
+
+ CARD16(minor_opcode);
+ CARD8(major_opcode);
+
+ if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
+ UNDECODED(left);
+}
+
+
+
+/************************************************************************
+ *** ***
+ *** I N I T I A L I Z A T I O N A N D M A I N ***
+ *** ***
+ ************************************************************************/
+
+static void
+dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
+
+ if (pinfo->match_port == pinfo->srcport)
+ dissect_x11_replies(tvb, pinfo, tree);
+ else
+ dissect_x11_requests(tvb, pinfo, tree);
+}
+
+/* Register the protocol with Ethereal */
+void proto_register_x11(void)
+{
+
+/* Setup list of header fields */
+ static hf_register_info hf[] = {
+#include "x11-register-info.h"
+ };
+
+/* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_x11,
+ &ett_x11_color_flags,
+ &ett_x11_list_of_arc,
+ &ett_x11_arc,
+ &ett_x11_list_of_atom,
+ &ett_x11_list_of_card32,
+ &ett_x11_list_of_color_item,
+ &ett_x11_color_item,
+ &ett_x11_list_of_keycode,
+ &ett_x11_list_of_keysyms,
+ &ett_x11_keysym,
+ &ett_x11_list_of_point,
+ &ett_x11_point,
+ &ett_x11_list_of_rectangle,
+ &ett_x11_rectangle,
+ &ett_x11_list_of_segment,
+ &ett_x11_segment,
+ &ett_x11_list_of_string8,
+ &ett_x11_list_of_text_item,
+ &ett_x11_text_item,
+ &ett_x11_gc_value_mask,
+ &ett_x11_event_mask,
+ &ett_x11_do_not_propagate_mask,
+ &ett_x11_set_of_key_mask,
+ &ett_x11_pointer_event_mask,
+ &ett_x11_window_value_mask,
+ &ett_x11_configure_window_mask,
+ &ett_x11_keyboard_value_mask,
+ &ett_x11_same_screen_focus,
+ };
+ module_t *x11_module;
+
+/* Register the protocol name and description */
+ proto_x11 = proto_register_protocol("X11", "X11", "x11");
+
+/* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_x11, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_init_routine(x11_init_protocol);
+
+ x11_module = prefs_register_protocol(proto_x11, NULL);
+ prefs_register_bool_preference(x11_module, "desegment",
+ "Desegment all X11 messages spanning multiple TCP segments",
+ "Whether the X11 dissector should desegment all messages spanning multiple TCP segments",
+ &x11_desegment);
+}
+
+void
+proto_reg_handoff_x11(void)
+{
+ dissector_handle_t x11_handle;
+
+ x11_handle = create_dissector_handle(dissect_x11, proto_x11);
+ dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
+ dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
+ dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
+ data_handle = find_dissector("data");
+}
+
diff --git a/epan/dissectors/packet-x25.c b/epan/dissectors/packet-x25.c
new file mode 100644
index 0000000000..653b5049c1
--- /dev/null
+++ b/epan/dissectors/packet-x25.c
@@ -0,0 +1,2518 @@
+/* packet-x25.c
+ * Routines for X.25 packet disassembly
+ * Olivier Abad <oabad@noos.fr>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include "llcsaps.h"
+#include <epan/packet.h>
+#include <epan/circuit.h>
+#include "reassemble.h"
+#include "prefs.h"
+#include "nlpid.h"
+#include "x264_prt_id.h"
+
+/*
+ * Direction of packet.
+ */
+typedef enum {
+ X25_FROM_DCE, /* DCE->DTE */
+ X25_FROM_DTE, /* DTE->DCE */
+ X25_UNKNOWN /* direction unknown */
+} x25_dir_t;
+
+/*
+ * 0 for data packets, 1 for non-data packets.
+ */
+#define X25_NONDATA_BIT 0x01
+
+#define X25_CALL_REQUEST 0x0B
+#define X25_CALL_ACCEPTED 0x0F
+#define X25_CLEAR_REQUEST 0x13
+#define X25_CLEAR_CONFIRMATION 0x17
+#define X25_INTERRUPT 0x23
+#define X25_INTERRUPT_CONFIRMATION 0x27
+#define X25_RESET_REQUEST 0x1B
+#define X25_RESET_CONFIRMATION 0x1F
+#define X25_RESTART_REQUEST 0xFB
+#define X25_RESTART_CONFIRMATION 0xFF
+#define X25_REGISTRATION_REQUEST 0xF3
+#define X25_REGISTRATION_CONFIRMATION 0xF7
+#define X25_DIAGNOSTIC 0xF1
+#define X25_RR 0x01
+#define X25_RNR 0x05
+#define X25_REJ 0x09
+#define X25_DATA 0x00
+
+#define PACKET_IS_DATA(type) (!(type & X25_NONDATA_BIT))
+#define PACKET_TYPE_FC(type) (type & 0x1F)
+
+#define X25_MBIT_MOD8 0x10
+#define X25_MBIT_MOD128 0x01
+
+#define X25_ABIT 0x8000
+
+#define X25_QBIT 0x8000
+#define X25_DBIT 0x4000
+
+#define X25_FAC_CLASS_MASK 0xC0
+
+#define X25_FAC_CLASS_A 0x00
+#define X25_FAC_CLASS_B 0x40
+#define X25_FAC_CLASS_C 0x80
+#define X25_FAC_CLASS_D 0xC0
+
+#define X25_FAC_COMP_MARK 0x00
+#define X25_FAC_REVERSE 0x01
+#define X25_FAC_THROUGHPUT 0x02
+#define X25_FAC_CUG 0x03
+#define X25_FAC_CALLED_MODIF 0x08
+#define X25_FAC_CUG_OUTGOING_ACC 0x09
+#define X25_FAC_THROUGHPUT_MIN 0x0A
+#define X25_FAC_EXPRESS_DATA 0x0B
+#define X25_FAC_BILATERAL_CUG 0x41
+#define X25_FAC_PACKET_SIZE 0x42
+#define X25_FAC_WINDOW_SIZE 0x43
+#define X25_FAC_RPOA_SELECTION 0x44
+#define X25_FAC_TRANSIT_DELAY 0x49
+#define X25_FAC_CALL_TRANSFER 0xC3
+#define X25_FAC_CALLED_ADDR_EXT 0xC9
+#define X25_FAC_ETE_TRANSIT_DELAY 0xCA
+#define X25_FAC_CALLING_ADDR_EXT 0xCB
+#define X25_FAC_CALL_DEFLECT 0xD1
+#define X25_FAC_PRIORITY 0xD2
+
+static int proto_x25 = -1;
+static int hf_x25_gfi = -1;
+static int hf_x25_abit = -1;
+static int hf_x25_qbit = -1;
+static int hf_x25_dbit = -1;
+static int hf_x25_mod = -1;
+static int hf_x25_lcn = -1;
+static int hf_x25_type = -1;
+static int hf_x25_type_fc_mod8 = -1;
+static int hf_x25_type_data = -1;
+static int hf_x25_p_r_mod8 = -1;
+static int hf_x25_p_r_mod128 = -1;
+static int hf_x25_mbit_mod8 = -1;
+static int hf_x25_mbit_mod128 = -1;
+static int hf_x25_p_s_mod8 = -1;
+static int hf_x25_p_s_mod128 = -1;
+
+static gint ett_x25 = -1;
+static gint ett_x25_gfi = -1;
+static gint ett_x25_fac = -1;
+static gint ett_x25_fac_unknown = -1;
+static gint ett_x25_fac_mark = -1;
+static gint ett_x25_fac_reverse = -1;
+static gint ett_x25_fac_throughput = -1;
+static gint ett_x25_fac_cug = -1;
+static gint ett_x25_fac_called_modif = -1;
+static gint ett_x25_fac_cug_outgoing_acc = -1;
+static gint ett_x25_fac_throughput_min = -1;
+static gint ett_x25_fac_express_data = -1;
+static gint ett_x25_fac_bilateral_cug = -1;
+static gint ett_x25_fac_packet_size = -1;
+static gint ett_x25_fac_window_size = -1;
+static gint ett_x25_fac_rpoa_selection = -1;
+static gint ett_x25_fac_transit_delay = -1;
+static gint ett_x25_fac_call_transfer = -1;
+static gint ett_x25_fac_called_addr_ext = -1;
+static gint ett_x25_fac_ete_transit_delay = -1;
+static gint ett_x25_fac_calling_addr_ext = -1;
+static gint ett_x25_fac_call_deflect = -1;
+static gint ett_x25_fac_priority = -1;
+static gint ett_x25_user_data = -1;
+
+static gint ett_x25_segment = -1;
+static gint ett_x25_segments = -1;
+static gint hf_x25_segments = -1;
+static gint hf_x25_segment = -1;
+static gint hf_x25_segment_overlap = -1;
+static gint hf_x25_segment_overlap_conflict = -1;
+static gint hf_x25_segment_multiple_tails = -1;
+static gint hf_x25_segment_too_long_segment = -1;
+static gint hf_x25_segment_error = -1;
+
+static const value_string vals_modulo[] = {
+ { 1, "8" },
+ { 2, "128" },
+ { 0, NULL}
+};
+
+static const value_string vals_x25_type[] = {
+ { X25_CALL_REQUEST, "Call" },
+ { X25_CALL_ACCEPTED, "Call Accepted" },
+ { X25_CLEAR_REQUEST, "Clear" },
+ { X25_CLEAR_CONFIRMATION, "Clear Confirmation" },
+ { X25_INTERRUPT, "Interrupt" },
+ { X25_INTERRUPT_CONFIRMATION, "Interrupt Confirmation" },
+ { X25_RESET_REQUEST, "Reset" },
+ { X25_RESET_CONFIRMATION, "Reset Confirmation" },
+ { X25_RESTART_REQUEST, "Restart" },
+ { X25_RESTART_CONFIRMATION, "Restart Confirmation" },
+ { X25_REGISTRATION_REQUEST, "Registration" },
+ { X25_REGISTRATION_CONFIRMATION, "Registration Confirmation" },
+ { X25_DIAGNOSTIC, "Diagnostic" },
+ { X25_RR, "RR" },
+ { X25_RNR, "RNR" },
+ { X25_REJ, "REJ" },
+ { X25_DATA, "Data" },
+ { 0, NULL}
+};
+
+static struct true_false_string m_bit_tfs = {
+ "More data follows",
+ "End of data"
+};
+
+static const fragment_items x25_frag_items = {
+ &ett_x25_segment,
+ &ett_x25_segments,
+ &hf_x25_segments,
+ &hf_x25_segment,
+ &hf_x25_segment_overlap,
+ &hf_x25_segment_overlap_conflict,
+ &hf_x25_segment_multiple_tails,
+ &hf_x25_segment_too_long_segment,
+ &hf_x25_segment_error,
+ NULL,
+ "segments"
+};
+
+static dissector_handle_t ip_handle;
+static dissector_handle_t clnp_handle;
+static dissector_handle_t ositp_handle;
+static dissector_handle_t qllc_handle;
+static dissector_handle_t data_handle;
+
+/* Preferences */
+static gboolean payload_is_qllc_sna = FALSE;
+static gboolean reassemble_x25 = FALSE;
+
+/* Reassembly of X.25 */
+
+static GHashTable *x25_segment_table = NULL;
+static GHashTable *x25_reassembled_table = NULL;
+
+static dissector_table_t x25_subdissector_table;
+static heur_dissector_list_t x25_heur_subdissector_list;
+
+static void
+x25_hash_add_proto_start(guint16 vc, guint32 frame, dissector_handle_t dissect)
+{
+ circuit_t *circuit;
+
+ /*
+ * Is there already a circuit with this VC number?
+ */
+ circuit = find_circuit(CT_X25, vc, frame);
+ if (circuit != NULL) {
+ /*
+ * Yes - close it, as we're creating a new one.
+ */
+ close_circuit(circuit, frame - 1);
+ }
+
+ /*
+ * Set up a new circuit.
+ */
+ circuit = circuit_new(CT_X25, vc, frame);
+
+ /*
+ * Set its dissector.
+ */
+ circuit_set_dissector(circuit, dissect);
+}
+
+static void
+x25_hash_add_proto_end(guint16 vc, guint32 frame)
+{
+ circuit_t *circuit;
+
+ /*
+ * Try to find the circuit.
+ */
+ circuit = find_circuit(CT_X25, vc, frame);
+
+ /*
+ * If we succeeded, close it.
+ */
+ if (circuit != NULL)
+ close_circuit(circuit, frame);
+}
+
+static char *clear_code(unsigned char code)
+{
+ static char buffer[25];
+
+ if (code == 0x00 || (code & 0x80) == 0x80)
+ return "DTE Originated";
+ if (code == 0x01)
+ return "Number Busy";
+ if (code == 0x03)
+ return "Invalid Facility Requested";
+ if (code == 0x05)
+ return "Network Congestion";
+ if (code == 0x09)
+ return "Out Of Order";
+ if (code == 0x0B)
+ return "Access Barred";
+ if (code == 0x0D)
+ return "Not Obtainable";
+ if (code == 0x11)
+ return "Remote Procedure Error";
+ if (code == 0x13)
+ return "Local Procedure Error";
+ if (code == 0x15)
+ return "RPOA Out Of Order";
+ if (code == 0x19)
+ return "Reverse Charging Acceptance Not Subscribed";
+ if (code == 0x21)
+ return "Incompatible Destination";
+ if (code == 0x29)
+ return "Fast Select Acceptance Not Subscribed";
+ if (code == 0x39)
+ return "Destination Absent";
+
+ sprintf(buffer, "Unknown %02X", code);
+
+ return buffer;
+}
+
+static char *clear_diag(unsigned char code)
+{
+ static char buffer[25];
+
+ if (code == 0)
+ return "No additional information";
+ if (code == 1)
+ return "Invalid P(S)";
+ if (code == 2)
+ return "Invalid P(R)";
+ if (code == 16)
+ return "Packet type invalid";
+ if (code == 17)
+ return "Packet type invalid for state r1";
+ if (code == 18)
+ return "Packet type invalid for state r2";
+ if (code == 19)
+ return "Packet type invalid for state r3";
+ if (code == 20)
+ return "Packet type invalid for state p1";
+ if (code == 21)
+ return "Packet type invalid for state p2";
+ if (code == 22)
+ return "Packet type invalid for state p3";
+ if (code == 23)
+ return "Packet type invalid for state p4";
+ if (code == 24)
+ return "Packet type invalid for state p5";
+ if (code == 25)
+ return "Packet type invalid for state p6";
+ if (code == 26)
+ return "Packet type invalid for state p7";
+ if (code == 27)
+ return "Packet type invalid for state d1";
+ if (code == 28)
+ return "Packet type invalid for state d2";
+ if (code == 29)
+ return "Packet type invalid for state d3";
+ if (code == 32)
+ return "Packet not allowed";
+ if (code == 33)
+ return "Unidentifiable packet";
+ if (code == 34)
+ return "Call on one-way logical channel";
+ if (code == 35)
+ return "Invalid packet type on a PVC";
+ if (code == 36)
+ return "Packet on unassigned LC";
+ if (code == 37)
+ return "Reject not subscribed to";
+ if (code == 38)
+ return "Packet too short";
+ if (code == 39)
+ return "Packet too long";
+ if (code == 40)
+ return "Invalid general format identifier";
+ if (code == 41)
+ return "Restart/registration packet with nonzero bits";
+ if (code == 42)
+ return "Packet type not compatible with facility";
+ if (code == 43)
+ return "Unauthorised interrupt confirmation";
+ if (code == 44)
+ return "Unauthorised interrupt";
+ if (code == 45)
+ return "Unauthorised reject";
+ if (code == 48)
+ return "Time expired";
+ if (code == 49)
+ return "Time expired for incoming call";
+ if (code == 50)
+ return "Time expired for clear indication";
+ if (code == 51)
+ return "Time expired for reset indication";
+ if (code == 52)
+ return "Time expired for restart indication";
+ if (code == 53)
+ return "Time expired for call deflection";
+ if (code == 64)
+ return "Call set-up/clearing or registration pb.";
+ if (code == 65)
+ return "Facility/registration code not allowed";
+ if (code == 66)
+ return "Facility parameter not allowed";
+ if (code == 67)
+ return "Invalid called DTE address";
+ if (code == 68)
+ return "Invalid calling DTE address";
+ if (code == 69)
+ return "Invalid facility/registration length";
+ if (code == 70)
+ return "Incoming call barred";
+ if (code == 71)
+ return "No logical channel available";
+ if (code == 72)
+ return "Call collision";
+ if (code == 73)
+ return "Duplicate facility requested";
+ if (code == 74)
+ return "Non zero address length";
+ if (code == 75)
+ return "Non zero facility length";
+ if (code == 76)
+ return "Facility not provided when expected";
+ if (code == 77)
+ return "Invalid CCITT-specified DTE facility";
+ if (code == 78)
+ return "Max. nb of call redir/defl. exceeded";
+ if (code == 80)
+ return "Miscellaneous";
+ if (code == 81)
+ return "Improper cause code from DTE";
+ if (code == 82)
+ return "Not aligned octet";
+ if (code == 83)
+ return "Inconsistent Q bit setting";
+ if (code == 84)
+ return "NUI problem";
+ if (code == 112)
+ return "International problem";
+ if (code == 113)
+ return "Remote network problem";
+ if (code == 114)
+ return "International protocol problem";
+ if (code == 115)
+ return "International link out of order";
+ if (code == 116)
+ return "International link busy";
+ if (code == 117)
+ return "Transit network facility problem";
+ if (code == 118)
+ return "Remote network facility problem";
+ if (code == 119)
+ return "International routing problem";
+ if (code == 120)
+ return "Temporary routing problem";
+ if (code == 121)
+ return "Unknown called DNIC";
+ if (code == 122)
+ return "Maintenance action";
+ if (code == 144)
+ return "Timer expired or retransmission count surpassed";
+ if (code == 145)
+ return "Timer expired or retransmission count surpassed for INTERRUPT";
+ if (code == 146)
+ return "Timer expired or retransmission count surpassed for DATA "
+ "packet transmission";
+ if (code == 147)
+ return "Timer expired or retransmission count surpassed for REJECT";
+ if (code == 160)
+ return "DTE-specific signals";
+ if (code == 161)
+ return "DTE operational";
+ if (code == 162)
+ return "DTE not operational";
+ if (code == 163)
+ return "DTE resource constraint";
+ if (code == 164)
+ return "Fast select not subscribed";
+ if (code == 165)
+ return "Invalid partially full DATA packet";
+ if (code == 166)
+ return "D-bit procedure not supported";
+ if (code == 167)
+ return "Registration/Cancellation confirmed";
+ if (code == 224)
+ return "OSI network service problem";
+ if (code == 225)
+ return "Disconnection (transient condition)";
+ if (code == 226)
+ return "Disconnection (permanent condition)";
+ if (code == 227)
+ return "Connection rejection - reason unspecified (transient "
+ "condition)";
+ if (code == 228)
+ return "Connection rejection - reason unspecified (permanent "
+ "condition)";
+ if (code == 229)
+ return "Connection rejection - quality of service not available "
+ "transient condition)";
+ if (code == 230)
+ return "Connection rejection - quality of service not available "
+ "permanent condition)";
+ if (code == 231)
+ return "Connection rejection - NSAP unreachable (transient condition)";
+ if (code == 232)
+ return "Connection rejection - NSAP unreachable (permanent condition)";
+ if (code == 233)
+ return "reset - reason unspecified";
+ if (code == 234)
+ return "reset - congestion";
+ if (code == 235)
+ return "Connection rejection - NSAP address unknown (permanent "
+ "condition)";
+ if (code == 240)
+ return "Higher layer initiated";
+ if (code == 241)
+ return "Disconnection - normal";
+ if (code == 242)
+ return "Disconnection - abnormal";
+ if (code == 243)
+ return "Disconnection - incompatible information in user data";
+ if (code == 244)
+ return "Connection rejection - reason unspecified (transient "
+ "condition)";
+ if (code == 245)
+ return "Connection rejection - reason unspecified (permanent "
+ "condition)";
+ if (code == 246)
+ return "Connection rejection - quality of service not available "
+ "(transient condition)";
+ if (code == 247)
+ return "Connection rejection - quality of service not available "
+ "(permanent condition)";
+ if (code == 248)
+ return "Connection rejection - incompatible information in user data";
+ if (code == 249)
+ return "Connection rejection - unrecognizable protocol indentifier "
+ "in user data";
+ if (code == 250)
+ return "Reset - user resynchronization";
+
+ sprintf(buffer, "Unknown %d", code);
+
+ return buffer;
+}
+
+static char *reset_code(unsigned char code)
+{
+ static char buffer[25];
+
+ if (code == 0x00 || (code & 0x80) == 0x80)
+ return "DTE Originated";
+ if (code == 0x01)
+ return "Out of order";
+ if (code == 0x03)
+ return "Remote Procedure Error";
+ if (code == 0x05)
+ return "Local Procedure Error";
+ if (code == 0x07)
+ return "Network Congestion";
+ if (code == 0x09)
+ return "Remote DTE operational";
+ if (code == 0x0F)
+ return "Network operational";
+ if (code == 0x11)
+ return "Incompatible Destination";
+ if (code == 0x1D)
+ return "Network out of order";
+
+ sprintf(buffer, "Unknown %02X", code);
+
+ return buffer;
+}
+
+static char *restart_code(unsigned char code)
+{
+ static char buffer[25];
+
+ if (code == 0x00 || (code & 0x80) == 0x80)
+ return "DTE Originated";
+ if (code == 0x01)
+ return "Local Procedure Error";
+ if (code == 0x03)
+ return "Network Congestion";
+ if (code == 0x07)
+ return "Network Operational";
+ if (code == 0x7F)
+ return "Registration/cancellation confirmed";
+
+ sprintf(buffer, "Unknown %02X", code);
+
+ return buffer;
+}
+
+static char *registration_code(unsigned char code)
+{
+ static char buffer[25];
+
+ if (code == 0x03)
+ return "Invalid facility request";
+ if (code == 0x05)
+ return "Network congestion";
+ if (code == 0x13)
+ return "Local procedure error";
+ if (code == 0x7F)
+ return "Registration/cancellation confirmed";
+
+ sprintf(buffer, "Unknown %02X", code);
+
+ return buffer;
+}
+
+static void
+dump_facilities(proto_tree *tree, int *offset, tvbuff_t *tvb)
+{
+ guint8 fac, byte1, byte2, byte3;
+ guint32 len; /* facilities length */
+ proto_item *ti=0;
+ proto_tree *fac_tree = 0;
+ proto_tree *fac_subtree;
+
+ len = tvb_get_guint8(tvb, *offset);
+ if (len && tree) {
+ ti = proto_tree_add_text(tree, tvb, *offset, len + 1,
+ "Facilities");
+ fac_tree = proto_item_add_subtree(ti, ett_x25_fac);
+ proto_tree_add_text(fac_tree, tvb, *offset, 1,
+ "Facilities length: %d", len);
+ }
+ (*offset)++;
+
+ while (len > 0) {
+ fac = tvb_get_guint8(tvb, *offset);
+ switch(fac & X25_FAC_CLASS_MASK) {
+ case X25_FAC_CLASS_A:
+ switch (fac) {
+ case X25_FAC_COMP_MARK:
+ if (fac_tree)
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
+ "Code : 00 (Marker)");
+ switch (tvb_get_guint8(tvb, *offset + 1)) {
+ case 0x00:
+ if (fac_tree) {
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Parameter : 00 (Network complementary "
+ "services - calling DTE)");
+ }
+ break;
+ case 0xFF:
+ if (fac_tree) {
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Parameter : FF (Network complementary "
+ "services - called DTE)");
+ }
+ break;
+ case 0x0F:
+ if (fac_tree) {
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Parameter : 0F (DTE complementary "
+ "services)");
+ }
+ break;
+ default:
+ if (fac_tree) {
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_mark);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Parameter : %02X (Unknown marker)",
+ tvb_get_guint8(tvb, *offset+1));
+ }
+ break;
+ }
+ break;
+ case X25_FAC_REVERSE:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Reverse charging / Fast select)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_reverse);
+ byte1 = tvb_get_guint8(tvb, *offset + 1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Parameter : %02X", byte1);
+ if (byte1 & 0xC0)
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "11.. .... = Fast select with restriction");
+ else if (byte1 & 0x80)
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "10.. .... = Fast select - no restriction");
+ else
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "00.. .... = Fast select not requested");
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ decode_boolean_bitfield(byte1, 0x01, 1*8,
+ "Reverse charging requested",
+ "Reverse charging not requested"));
+ }
+ break;
+ case X25_FAC_THROUGHPUT:
+ if (fac_tree) {
+ char tmpbuf[80];
+
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Throughput class negociation)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_throughput);
+ byte1 = tvb_get_guint8(tvb, *offset + 1);
+ switch (byte1 >> 4)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ sprintf(tmpbuf, "From the called DTE : %%u (%d bps)",
+ 75*(1<<((byte1 >> 4)-3)));
+ break;
+ case 12:
+ sprintf(tmpbuf, "From the called DTE : %%u (48000 bps)");
+ break;
+ case 13:
+ sprintf(tmpbuf, "From the called DTE : %%u (64000 bps)");
+ break;
+ default:
+ sprintf(tmpbuf, "From the called DTE : %%u (Reserved)");
+ }
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ decode_numeric_bitfield(byte1, 0xF0, 1*8, tmpbuf));
+ switch (byte1 & 0x0F)
+ {
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ sprintf(tmpbuf, "From the calling DTE : %%u (%d bps)",
+ 75*(1<<((byte1 & 0x0F)-3)));
+ break;
+ case 12:
+ sprintf(tmpbuf, "From the calling DTE : %%u (48000 bps)");
+ break;
+ case 13:
+ sprintf(tmpbuf, "From the calling DTE : %%u (64000 bps)");
+ break;
+ default:
+ sprintf(tmpbuf, "From the calling DTE : %%u (Reserved)");
+ }
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
+ }
+ break;
+ case X25_FAC_CUG:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Closed user group selection)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_cug);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
+ }
+ break;
+ case X25_FAC_CALLED_MODIF:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Called address modified)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_called_modif);
+ proto_tree_add_text(fac_tree, tvb, *offset+1, 1,
+ "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
+ }
+ break;
+ case X25_FAC_CUG_OUTGOING_ACC:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Closed user group with outgoing access selection)",
+ fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_cug_outgoing_acc);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Closed user group: %02X", tvb_get_guint8(tvb, *offset+1));
+ }
+ break;
+ case X25_FAC_THROUGHPUT_MIN:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Minimum throughput class)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_throughput_min);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
+ }
+ break;
+ case X25_FAC_EXPRESS_DATA:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Negociation of express data)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_express_data);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
+ }
+ break;
+ default:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
+ "Code : %02X (Unknown class A)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Parameter %02X", tvb_get_guint8(tvb, *offset+1));
+ }
+ break;
+ }
+ (*offset) += 2;
+ len -= 2;
+ break;
+ case X25_FAC_CLASS_B:
+ switch (fac) {
+ case X25_FAC_BILATERAL_CUG:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Bilateral closed user group selection)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_bilateral_cug);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
+ "Bilateral CUG: %04X",
+ tvb_get_ntohs(tvb, *offset+1));
+ }
+ break;
+ case X25_FAC_PACKET_SIZE:
+ if (fac_tree)
+ {
+ char tmpbuf[80];
+
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Packet size)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_packet_size);
+ byte1 = tvb_get_guint8(tvb, *offset + 1);
+ switch (byte1)
+ {
+ case 0x04:
+ sprintf(tmpbuf, "From the called DTE : %%u (16)");
+ break;
+ case 0x05:
+ sprintf(tmpbuf, "From the called DTE : %%u (32)");
+ break;
+ case 0x06:
+ sprintf(tmpbuf, "From the called DTE : %%u (64)");
+ break;
+ case 0x07:
+ sprintf(tmpbuf, "From the called DTE : %%u (128)");
+ break;
+ case 0x08:
+ sprintf(tmpbuf, "From the called DTE : %%u (256)");
+ break;
+ case 0x0D:
+ sprintf(tmpbuf, "From the called DTE : %%u (512)");
+ break;
+ case 0x0C:
+ sprintf(tmpbuf, "From the called DTE : %%u (1024)");
+ break;
+ case 0x0E:
+ sprintf(tmpbuf, "From the called DTE : %%u (2048)");
+ break;
+ case 0x0F:
+ sprintf(tmpbuf, "From the called DTE : %%u (4096)");
+ break;
+ default:
+ sprintf(tmpbuf, "From the called DTE : %%u (Unknown)");
+ break;
+ }
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ decode_numeric_bitfield(byte1, 0x0F, 1*8, tmpbuf));
+
+ byte2 = tvb_get_guint8(tvb, *offset + 1);
+ switch (byte2)
+ {
+ case 0x04:
+ sprintf(tmpbuf, "From the calling DTE : %%u (16)");
+ break;
+ case 0x05:
+ sprintf(tmpbuf, "From the calling DTE : %%u (32)");
+ break;
+ case 0x06:
+ sprintf(tmpbuf, "From the calling DTE : %%u (64)");
+ break;
+ case 0x07:
+ sprintf(tmpbuf, "From the calling DTE : %%u (128)");
+ break;
+ case 0x08:
+ sprintf(tmpbuf, "From the calling DTE : %%u (256)");
+ break;
+ case 0x0D:
+ sprintf(tmpbuf, "From the calling DTE : %%u (512)");
+ break;
+ case 0x0C:
+ sprintf(tmpbuf, "From the calling DTE : %%u (1024)");
+ break;
+ case 0x0E:
+ sprintf(tmpbuf, "From the calling DTE : %%u (2048)");
+ break;
+ case 0x0F:
+ sprintf(tmpbuf, "From the calling DTE : %%u (4096)");
+ break;
+ default:
+ sprintf(tmpbuf, "From the calling DTE : %%u (Unknown)");
+ break;
+ }
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ decode_numeric_bitfield(byte2, 0x0F, 1*8, tmpbuf));
+ }
+ break;
+ case X25_FAC_WINDOW_SIZE:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Window size)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_window_size);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+1),
+ 0x7F, 1*8, "From the called DTE: %u"));
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ decode_numeric_bitfield(tvb_get_guint8(tvb, *offset+2),
+ 0x7F, 1*8, "From the calling DTE: %u"));
+ }
+ break;
+ case X25_FAC_RPOA_SELECTION:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(RPOA selection)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_rpoa_selection);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
+ "Data network identification code : %04X",
+ tvb_get_ntohs(tvb, *offset+1));
+ }
+ break;
+ case X25_FAC_TRANSIT_DELAY:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Transit delay selection and indication)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_transit_delay);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
+ "Transit delay: %d ms",
+ tvb_get_ntohs(tvb, *offset+1));
+ }
+ break;
+ default:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
+ "Code : %02X (Unknown class B)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 2,
+ "Parameter %04X", tvb_get_ntohs(tvb, *offset+1));
+ }
+ break;
+ }
+ (*offset) += 3;
+ len -= 3;
+ break;
+ case X25_FAC_CLASS_C:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
+ "Code : %02X (Unknown class C)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 3,
+ "Parameter %06X",
+ tvb_get_ntoh24(tvb, *offset+1));
+ }
+ (*offset) += 4;
+ len -= 4;
+ break;
+ case X25_FAC_CLASS_D:
+ switch (fac) {
+ case X25_FAC_CALL_TRANSFER:
+ if (fac_tree) {
+ int i;
+ char tmpbuf[256];
+
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Call redirection or deflection notification)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_call_transfer);
+ byte1 = tvb_get_guint8(tvb, *offset+1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Length : %u", byte1);
+ byte2 = tvb_get_guint8(tvb, *offset+2);
+ if ((byte2 & 0xC0) == 0xC0) {
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Reason : call deflection by the originally "
+ "called DTE address");
+ }
+ else {
+ switch (byte2) {
+ case 0x01:
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Reason : originally called DTE busy");
+ break;
+ case 0x07:
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Reason : call dist. within a hunt group");
+ break;
+ case 0x09:
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Reason : originally called DTE out of order");
+ break;
+ case 0x0F:
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Reason : systematic call redirection");
+ break;
+ default:
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Reason : unknown");
+ break;
+ }
+ }
+ byte3 = tvb_get_guint8(tvb, *offset+3);
+ proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
+ "Number of semi-octets in DTE address : %u",
+ byte3);
+ for (i = 0; i < byte3; i++) {
+ if (i % 2 == 0) {
+ tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
+ & 0x0F) + '0';
+ /* if > 9, convert to the right hexadecimal letter */
+ if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
+ } else {
+ tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
+ & 0x0F) + '0';
+ /* if > 9, convert to the right hexadecimal letter */
+ if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
+ }
+ }
+ tmpbuf[i] = 0;
+ proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
+ "DTE address : %s", tmpbuf);
+ }
+ break;
+ case X25_FAC_CALLING_ADDR_EXT:
+ if (fac_tree) {
+ int i;
+ char tmpbuf[256];
+
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Calling address extension)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_calling_addr_ext);
+ byte1 = tvb_get_guint8(tvb, *offset+1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Length : %u", byte1);
+ byte2 = tvb_get_guint8(tvb, *offset+2) & 0x3F;
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Number of semi-octets in DTE address : %u", byte2);
+ for (i = 0; i < byte2; i++) {
+ if (i % 2 == 0) {
+ tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
+ & 0x0F) + '0';
+ /* if > 9, convert to the right hexadecimal letter */
+ if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
+ } else {
+ tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
+ & 0x0F) + '0';
+ /* if > 9, convert to the right hexadecimal letter */
+ if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
+ }
+ }
+ tmpbuf[i] = 0;
+ proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
+ "DTE address : %s", tmpbuf);
+ }
+ break;
+ case X25_FAC_CALLED_ADDR_EXT:
+ if (fac_tree) {
+ int i;
+ char tmpbuf[256];
+
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Called address extension)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_called_addr_ext);
+ byte1 = tvb_get_guint8(tvb, *offset+1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Length : %u", byte1);
+ byte2 = tvb_get_guint8(tvb, *offset+2) & 0x3F;
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Number of semi-octets in DTE address : %u", byte2);
+ for (i = 0; i < byte2; i++) {
+ if (i % 2 == 0) {
+ tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+3+i/2) >> 4)
+ & 0x0F) + '0';
+ /* if > 9, convert to the right hexadecimal letter */
+ if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
+ } else {
+ tmpbuf[i] = (tvb_get_guint8(tvb, *offset+3+i/2)
+ & 0x0F) + '0';
+ /* if > 9, convert to the right hexadecimal letter */
+ if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
+ }
+ }
+ tmpbuf[i] = 0;
+ proto_tree_add_text(fac_subtree, tvb, *offset+3, byte1 - 1,
+ "DTE address : %s", tmpbuf);
+ }
+ break;
+ case X25_FAC_ETE_TRANSIT_DELAY:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(End to end transit delay)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_ete_transit_delay);
+ byte1 = tvb_get_guint8(tvb, *offset+1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Length : %u", byte1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
+ }
+ break;
+ case X25_FAC_CALL_DEFLECT:
+ if (fac_tree) {
+ int i;
+ char tmpbuf[256];
+
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1, "Code : %02X "
+ "(Call deflection selection)", fac);
+ fac_subtree = proto_item_add_subtree(ti,
+ ett_x25_fac_call_deflect);
+ byte1 = tvb_get_guint8(tvb, *offset+1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Length : %u", byte1);
+ byte2 = tvb_get_guint8(tvb, *offset+2);
+ if ((byte2 & 0xC0) == 0xC0)
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Reason : call DTE originated");
+ else
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, 1,
+ "Reason : unknown");
+ byte3 = tvb_get_guint8(tvb, *offset+3);
+ proto_tree_add_text(fac_subtree, tvb, *offset+3, 1,
+ "Number of semi-octets in the alternative DTE address : %u",
+ byte3);
+ for (i = 0; i < byte3; i++) {
+ if (i % 2 == 0) {
+ tmpbuf[i] = ((tvb_get_guint8(tvb, *offset+4+i/2) >> 4)
+ & 0x0F) + '0';
+ /* if > 9, convert to the right hexadecimal letter */
+ if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
+ } else {
+ tmpbuf[i] = (tvb_get_guint8(tvb, *offset+4+i/2)
+ & 0x0F) + '0';
+ /* if > 9, convert to the right hexadecimal letter */
+ if (tmpbuf[i] > '9') tmpbuf[i] += ('A' - '0' - 10);
+ }
+ }
+ tmpbuf[i] = 0;
+ proto_tree_add_text(fac_subtree, tvb, *offset+4, byte1 - 2,
+ "Alternative DTE address : %s", tmpbuf);
+ }
+ break;
+ case X25_FAC_PRIORITY:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
+ "Code : %02X (Priority)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_priority);
+ byte1 = tvb_get_guint8(tvb, *offset+1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Length : %u", byte1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
+ }
+ break;
+ default:
+ if (fac_tree) {
+ ti = proto_tree_add_text(fac_tree, tvb, *offset, 1,
+ "Code : %02X (Unknown class D)", fac);
+ fac_subtree = proto_item_add_subtree(ti, ett_x25_fac_unknown);
+ byte1 = tvb_get_guint8(tvb, *offset+1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+1, 1,
+ "Length : %u", byte1);
+ proto_tree_add_text(fac_subtree, tvb, *offset+2, byte1, "Value");
+ }
+ }
+ byte1 = tvb_get_guint8(tvb, *offset+1);
+ (*offset) += byte1+2;
+ len -= byte1+2;
+ break;
+ }
+ }
+}
+
+static void
+x25_ntoa(proto_tree *tree, int *offset, tvbuff_t *tvb,
+ packet_info *pinfo, gboolean is_registration)
+{
+ int len1, len2;
+ int i;
+ char addr1[16], addr2[16];
+ char *first, *second;
+ guint8 byte;
+ int localoffset;
+
+ byte = tvb_get_guint8(tvb, *offset);
+ len1 = (byte >> 0) & 0x0F;
+ len2 = (byte >> 4) & 0x0F;
+
+ if (tree) {
+ proto_tree_add_text(tree, tvb, *offset, 1,
+ decode_numeric_bitfield(byte, 0xF0, 1*8,
+ is_registration ?
+ "DTE address length : %u" :
+ "Calling address length : %u"));
+ proto_tree_add_text(tree, tvb, *offset, 1,
+ decode_numeric_bitfield(byte, 0x0F, 1*8,
+ is_registration ?
+ "DCE address length : %u" :
+ "Called address length : %u"));
+ }
+ (*offset)++;
+
+ localoffset = *offset;
+ byte = tvb_get_guint8(tvb, localoffset);
+
+ first=addr1;
+ second=addr2;
+ for (i = 0; i < (len1 + len2); i++) {
+ if (i < len1) {
+ if (i % 2 != 0) {
+ *first++ = ((byte >> 0) & 0x0F) + '0';
+ localoffset++;
+ byte = tvb_get_guint8(tvb, localoffset);
+ } else {
+ *first++ = ((byte >> 4) & 0x0F) + '0';
+ }
+ } else {
+ if (i % 2 != 0) {
+ *second++ = ((byte >> 0) & 0x0F) + '0';
+ localoffset++;
+ byte = tvb_get_guint8(tvb, localoffset);
+ } else {
+ *second++ = ((byte >> 4) & 0x0F) + '0';
+ }
+ }
+ }
+
+ *first = '\0';
+ *second = '\0';
+
+ if (len1) {
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_add_str(pinfo->cinfo, COL_RES_DL_DST, addr1);
+ if (tree)
+ proto_tree_add_text(tree, tvb, *offset,
+ (len1 + 1) / 2,
+ is_registration ?
+ "DCE address : %s" :
+ "Called address : %s",
+ addr1);
+ }
+ if (len2) {
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_add_str(pinfo->cinfo, COL_RES_DL_SRC, addr2);
+ if (tree)
+ proto_tree_add_text(tree, tvb, *offset + len1/2,
+ (len2+1)/2+(len1%2+(len2+1)%2)/2,
+ is_registration ?
+ "DTE address : %s" :
+ "Calling address : %s",
+ addr2);
+ }
+ (*offset) += ((len1 + len2 + 1) / 2);
+}
+
+static void
+x25_toa(proto_tree *tree, int *offset, tvbuff_t *tvb,
+ packet_info *pinfo)
+{
+ int len1, len2;
+ int i;
+ char addr1[256], addr2[256];
+ char *first, *second;
+ guint8 byte;
+ int localoffset;
+
+ len1 = tvb_get_guint8(tvb, *offset);
+ if (tree) {
+ proto_tree_add_text(tree, tvb, *offset, 1,
+ "Called address length : %u",
+ len1);
+ }
+ (*offset)++;
+
+ len2 = tvb_get_guint8(tvb, *offset);
+ if (tree) {
+ proto_tree_add_text(tree, tvb, *offset, 1,
+ "Calling address length : %u",
+ len2);
+ }
+ (*offset)++;
+
+ localoffset = *offset;
+ byte = tvb_get_guint8(tvb, localoffset);
+
+ /*
+ * XXX - the first two half-octets of the address are the TOA and
+ * NPI; process them as such and, if the TOA says an address is
+ * an alternative address, process it correctly (i.e., not as a
+ * sequence of half-octets containing digit values).
+ */
+ first=addr1;
+ second=addr2;
+ for (i = 0; i < (len1 + len2); i++) {
+ if (i < len1) {
+ if (i % 2 != 0) {
+ *first++ = ((byte >> 0) & 0x0F) + '0';
+ localoffset++;
+ byte = tvb_get_guint8(tvb, localoffset);
+ } else {
+ *first++ = ((byte >> 4) & 0x0F) + '0';
+ }
+ } else {
+ if (i % 2 != 0) {
+ *second++ = ((byte >> 0) & 0x0F) + '0';
+ localoffset++;
+ byte = tvb_get_guint8(tvb, localoffset);
+ } else {
+ *second++ = ((byte >> 4) & 0x0F) + '0';
+ }
+ }
+ }
+
+ *first = '\0';
+ *second = '\0';
+
+ if (len1) {
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_add_str(pinfo->cinfo, COL_RES_DL_DST, addr1);
+ if (tree)
+ proto_tree_add_text(tree, tvb, *offset,
+ (len1 + 1) / 2,
+ "Called address : %s",
+ addr1);
+ }
+ if (len2) {
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_add_str(pinfo->cinfo, COL_RES_DL_SRC, addr2);
+ if (tree)
+ proto_tree_add_text(tree, tvb, *offset + len1/2,
+ (len2+1)/2+(len1%2+(len2+1)%2)/2,
+ "Calling address : %s",
+ addr2);
+ }
+ (*offset) += ((len1 + len2 + 1) / 2);
+}
+
+static int
+get_x25_pkt_len(tvbuff_t *tvb)
+{
+ guint length, called_len, calling_len, dte_len, dce_len;
+ guint8 byte2, bytex;
+
+ byte2 = tvb_get_guint8(tvb, 2);
+ switch (byte2)
+ {
+ case X25_CALL_REQUEST:
+ bytex = tvb_get_guint8(tvb, 3);
+ called_len = (bytex >> 0) & 0x0F;
+ calling_len = (bytex >> 4) & 0x0F;
+ length = 4 + (called_len + calling_len + 1) / 2; /* addr */
+ if (length < tvb_reported_length(tvb))
+ length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
+
+ return MIN(tvb_reported_length(tvb),length);
+
+ case X25_CALL_ACCEPTED:
+ /* The calling/called address length byte (following the packet type)
+ * is not mandatory, so we must check the packet length before trying
+ * to read it */
+ if (tvb_reported_length(tvb) == 3)
+ return(3);
+ bytex = tvb_get_guint8(tvb, 3);
+ called_len = (bytex >> 0) & 0x0F;
+ calling_len = (bytex >> 4) & 0x0F;
+ length = 4 + (called_len + calling_len + 1) / 2; /* addr */
+ if (length < tvb_reported_length(tvb))
+ length += (1 + tvb_get_guint8(tvb, length)); /* facilities */
+
+ return MIN(tvb_reported_length(tvb),length);
+
+ case X25_CLEAR_REQUEST:
+ case X25_RESET_REQUEST:
+ case X25_RESTART_REQUEST:
+ return MIN(tvb_reported_length(tvb),5);
+
+ case X25_DIAGNOSTIC:
+ return MIN(tvb_reported_length(tvb),4);
+
+ case X25_CLEAR_CONFIRMATION:
+ case X25_INTERRUPT:
+ case X25_INTERRUPT_CONFIRMATION:
+ case X25_RESET_CONFIRMATION:
+ case X25_RESTART_CONFIRMATION:
+ return MIN(tvb_reported_length(tvb),3);
+
+ case X25_REGISTRATION_REQUEST:
+ bytex = tvb_get_guint8(tvb, 3);
+ dce_len = (bytex >> 0) & 0x0F;
+ dte_len = (bytex >> 4) & 0x0F;
+ length = 4 + (dte_len + dce_len + 1) / 2; /* addr */
+ if (length < tvb_reported_length(tvb))
+ length += (1 + tvb_get_guint8(tvb, length)); /* registration */
+
+ return MIN(tvb_reported_length(tvb),length);
+
+ case X25_REGISTRATION_CONFIRMATION:
+ bytex = tvb_get_guint8(tvb, 5);
+ dce_len = (bytex >> 0) & 0x0F;
+ dte_len = (bytex >> 4) & 0x0F;
+ length = 6 + (dte_len + dce_len + 1) / 2; /* addr */
+ if (length < tvb_reported_length(tvb))
+ length += (1 + tvb_get_guint8(tvb, length)); /* registration */
+
+ return MIN(tvb_reported_length(tvb),length);
+ }
+
+ if (PACKET_IS_DATA(byte2))
+ return MIN(tvb_reported_length(tvb),3);
+
+ switch (PACKET_TYPE_FC(byte2))
+ {
+ case X25_RR:
+ return MIN(tvb_reported_length(tvb),3);
+
+ case X25_RNR:
+ return MIN(tvb_reported_length(tvb),3);
+
+ case X25_REJ:
+ return MIN(tvb_reported_length(tvb),3);
+ }
+
+ return 0;
+}
+
+static const value_string prt_id_vals[] = {
+ {PRT_ID_ISO_8073, "ISO 8073 COTP"},
+ {PRT_ID_ISO_8602, "ISO 8602 CLTP"},
+ {PRT_ID_ISO_10736_ISO_8073, "ISO 10736 in conjunction with ISO 8073 COTP"},
+ {PRT_ID_ISO_10736_ISO_8602, "ISO 10736 in conjunction with ISO 8602 CLTP"},
+ {0x00, NULL}
+};
+
+static const value_string sharing_strategy_vals[] = {
+ {0x00, "No sharing"},
+ {0x00, NULL}
+};
+
+static void
+dissect_x25_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ x25_dir_t dir, gboolean side)
+{
+ proto_tree *x25_tree=0, *gfi_tree=0, *userdata_tree=0;
+ proto_item *ti;
+ guint localoffset=0;
+ guint x25_pkt_len;
+ int modulo;
+ guint16 vc;
+ dissector_handle_t dissect = NULL;
+ gboolean toa; /* TOA/NPI address format */
+ guint16 bytes0_1;
+ guint8 pkt_type;
+ char *short_name = NULL, *long_name = NULL;
+ tvbuff_t *next_tvb = NULL;
+ gboolean q_bit_set = FALSE;
+ gboolean m_bit_set;
+ gint payload_len;
+ guint32 frag_key;
+ void *saved_private_data;
+ fragment_data *fd_head;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "X.25");
+
+ bytes0_1 = tvb_get_ntohs(tvb, 0);
+
+ modulo = ((bytes0_1 & 0x2000) ? 128 : 8);
+ vc = (int)(bytes0_1 & 0x0FFF);
+
+ pinfo->ctype = CT_X25;
+ pinfo->circuit_id = vc;
+
+ if (bytes0_1 & X25_ABIT) toa = TRUE;
+ else toa = FALSE;
+
+ x25_pkt_len = get_x25_pkt_len(tvb);
+ if (x25_pkt_len < 3) /* packet too short */
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Invalid/short X.25 packet");
+ if (tree)
+ proto_tree_add_protocol_format(tree, proto_x25, tvb, 0, -1,
+ "Invalid/short X.25 packet");
+ return;
+ }
+
+ pkt_type = tvb_get_guint8(tvb, 2);
+ if (PACKET_IS_DATA(pkt_type)) {
+ if (bytes0_1 & X25_QBIT)
+ q_bit_set = TRUE;
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_x25, tvb, 0, x25_pkt_len, FALSE);
+ x25_tree = proto_item_add_subtree(ti, ett_x25);
+ ti = proto_tree_add_item(x25_tree, hf_x25_gfi, tvb, 0, 2, FALSE);
+ gfi_tree = proto_item_add_subtree(ti, ett_x25_gfi);
+
+ if (PACKET_IS_DATA(pkt_type)) {
+ proto_tree_add_boolean(gfi_tree, hf_x25_qbit, tvb, 0, 2,
+ bytes0_1);
+ }
+ else if (pkt_type == X25_CALL_REQUEST ||
+ pkt_type == X25_CALL_ACCEPTED ||
+ pkt_type == X25_CLEAR_REQUEST ||
+ pkt_type == X25_CLEAR_CONFIRMATION) {
+ proto_tree_add_boolean(gfi_tree, hf_x25_abit, tvb, 0, 2,
+ bytes0_1);
+ }
+
+ if (pkt_type == X25_CALL_REQUEST || pkt_type == X25_CALL_ACCEPTED ||
+ PACKET_IS_DATA(pkt_type)) {
+ proto_tree_add_boolean(gfi_tree, hf_x25_dbit, tvb, 0, 2,
+ bytes0_1);
+ }
+ proto_tree_add_uint(gfi_tree, hf_x25_mod, tvb, 0, 2, bytes0_1);
+ }
+
+ switch (pkt_type) {
+ case X25_CALL_REQUEST:
+ switch (dir) {
+
+ case X25_FROM_DCE:
+ short_name = "Inc. call";
+ long_name = "Incoming call";
+ break;
+
+ case X25_FROM_DTE:
+ short_name = "Call req.";
+ long_name = "Call request";
+ break;
+
+ case X25_UNKNOWN:
+ short_name = "Inc. call/Call req.";
+ long_name = "Incoming call/Call request";
+ break;
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d", short_name, vc);
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb,
+ 0, 2, bytes0_1);
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_CALL_REQUEST, "Packet Type: %s", long_name);
+ }
+ localoffset = 3;
+ if (localoffset < x25_pkt_len) { /* calling/called addresses */
+ if (toa)
+ x25_toa(x25_tree, &localoffset, tvb, pinfo);
+ else
+ x25_ntoa(x25_tree, &localoffset, tvb, pinfo, FALSE);
+ }
+
+ if (localoffset < x25_pkt_len) /* facilities */
+ dump_facilities(x25_tree, &localoffset, tvb);
+
+ if (localoffset < tvb_reported_length(tvb)) /* user data */
+ {
+ guint8 spi;
+ int is_x_264;
+ guint8 prt_id;
+
+ if (x25_tree) {
+ ti = proto_tree_add_text(x25_tree, tvb, localoffset, -1,
+ "User data");
+ userdata_tree = proto_item_add_subtree(ti, ett_x25_user_data);
+ }
+
+ /* X.263/ISO 9577 says that:
+
+ When CLNP or ESIS are run over X.25, the SPI
+ is 0x81 or 0x82, respectively; those are the
+ NLPIDs for those protocol.
+
+ When X.224/ISO 8073 COTP is run over X.25, and
+ when ISO 11570 explicit identification is being
+ used, the first octet of the user data field is
+ a TPDU length field, and the rest is "as defined
+ in ITU-T Rec. X.225 | ISO/IEC 8073, Annex B,
+ or ITU-T Rec. X.264 and ISO/IEC 11570".
+
+ When X.264/ISO 11570 default identification is
+ being used, there is no user data field in the
+ CALL REQUEST packet. This is for X.225/ISO 8073
+ COTP.
+
+ It also says that SPI values from 0x03 through 0x3f are
+ reserved and are in use by X.224/ISO 8073 Annex B and
+ X.264/ISO 11570. The note says that those values are
+ not NLPIDs, they're "used by the respective higher layer
+ protocol" and "not used for higher layer protocol
+ identification". I infer from this and from what
+ X.264/ISO 11570 says that this means that values in those
+ range are valid values for the first octet of an
+ X.224/ISO 8073 packet or for X.264/ISO 11570.
+
+ Annex B of X.225/ISO 8073 mentions some additional TPDU
+ types that can be put in what I presume is the user
+ data of connect requests. It says that:
+
+ The sending transport entity shall:
+
+ a) either not transmit any TPDU in the NS-user data
+ parameter of the N-CONNECT request primitive; or
+
+ b) transmit the UN-TPDU (see ITU-T Rec. X.264 and
+ ISO/IEC 11570) followed by the NCM-TPDU in the
+ NS-user data parameter of the N-CONNECT request
+ primitive.
+
+ I don't know if this means that the user data field
+ will contain a UN TPDU followed by an NCM TPDU or not.
+
+ X.264/ISO 11570 says that:
+
+ When default identification is being used,
+ X.225/ISO 8073 COTP is identified. No user data
+ is sent in the network-layer connection request.
+
+ When explicit identification is being used,
+ the user data is a UN TPDU ("Use of network
+ connection TPDU"), which specifies the transport
+ protocol to use over this network connection.
+ It also says that the length of a UN TPDU shall
+ not exceed 32 octets, i.e. shall not exceed 0x20;
+ it says this is "due to the desire not to conflict
+ with the protocol identifier field carried by X.25
+ CALL REQUEST/INCOMING CALL packets", and says that
+ field has values specified in X.244. X.244 has been
+ superseded by X.263/ISO 9577, so that presumably
+ means the goal is to allow a UN TPDU's length
+ field to be distinguished from an NLPID, allowing
+ you to tell whether X.264/ISO 11570 explicit
+ identification is being used or an NLPID is
+ being used as the SPI.
+
+ I read this as meaning that, if the ISO mechanisms are
+ used to identify the protocol being carried over X.25:
+
+ if there's no user data in the CALL REQUEST/
+ INCOMING CALL packet, it's COTP;
+
+ if there is user data, then:
+
+ if the first octet is less than or equal to
+ 32, it might be a UN TPDU, and that identifies
+ the transport protocol being used, and
+ it may be followed by more data, such
+ as a COTP NCM TPDU if it's COTP;
+
+ if the first octet is greater than 32, it's
+ an NLPID, *not* a TPDU length, and the
+ stuff following it is *not* a TPDU.
+
+ Figure A.2 of X.263/ISO 9577 seems to say that the
+ first octet of the user data is a TPDU length field,
+ in the range 0x03 through 0x82, and says they are
+ for X.225/ISO 8073 Annex B or X.264/ISO 11570.
+
+ However, X.264/ISO 11570 seems to imply that the length
+ field would be that of a UN TPDU, which must be less
+ than or equal to 0x20, and X.225/ISO 8073 Annex B seems
+ to indicate that the user data must begin with
+ an X.264/ISO 11570 UN TPDU, so I'd say that A.2 should
+ have said "in the range 0x03 through 0x20", instead
+ (the length value doesn't include the length field,
+ and the minimum UN TPDU has length, type, PRT-ID,
+ and SHARE, so that's 3 bytes without the length). */
+ spi = tvb_get_guint8(tvb, localoffset);
+ if (spi > 32 || spi < 3) {
+ /* First octet is > 32, or < 3, so the user data isn't an
+ X.264/ISO 11570 UN TPDU */
+ is_x_264 = FALSE;
+ } else {
+ /* First octet is >= 3 and <= 32, so the user data *might*
+ be an X.264/ISO 11570 UN TPDU. Check whether we have
+ enough data to see if it is. */
+ if (tvb_bytes_exist(tvb, localoffset+1, 1)) {
+ /* We do; check whether the second octet is 1. */
+ if (tvb_get_guint8(tvb, localoffset+1) == 0x01) {
+ /* Yes, the second byte is 1, so it looks like
+ a UN TPDU. */
+ is_x_264 = TRUE;
+ } else {
+ /* No, the second byte is not 1, so it's not a
+ UN TPDU. */
+ is_x_264 = FALSE;
+ }
+ } else {
+ /* We can't see the second byte of the putative UN
+ TPDU, so we don't know if that's what it is. */
+ is_x_264 = -1;
+ }
+ }
+ if (is_x_264 == -1) {
+ /*
+ * We don't know what it is; just skip it.
+ */
+ localoffset = tvb_length(tvb);
+ } else if (is_x_264) {
+ /* It looks like an X.264 UN TPDU, so show it as such. */
+ if (userdata_tree) {
+ proto_tree_add_text(userdata_tree, tvb, localoffset, 1,
+ "X.264 length indicator: %u",
+ spi);
+ proto_tree_add_text(userdata_tree, tvb, localoffset+1, 1,
+ "X.264 UN TPDU identifier: 0x%02X",
+ tvb_get_guint8(tvb, localoffset+1));
+ }
+ prt_id = tvb_get_guint8(tvb, localoffset+2);
+ if (userdata_tree) {
+ proto_tree_add_text(userdata_tree, tvb, localoffset+2, 1,
+ "X.264 protocol identifier: %s",
+ val_to_str(prt_id, prt_id_vals,
+ "Unknown (0x%02X)"));
+ proto_tree_add_text(userdata_tree, tvb, localoffset+3, 1,
+ "X.264 sharing strategy: %s",
+ val_to_str(tvb_get_guint8(tvb, localoffset+3),
+ sharing_strategy_vals, "Unknown (0x%02X)"));
+ }
+
+ /* XXX - dissect the variable part? */
+
+ /* The length doesn't include the length octet itself. */
+ localoffset += spi + 1;
+
+ switch (prt_id) {
+
+ case PRT_ID_ISO_8073:
+ /* ISO 8073 COTP */
+ if (!pinfo->fd->flags.visited)
+ x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
+ /* XXX - dissect the rest of the user data as COTP?
+ That needs support for NCM TPDUs, etc. */
+ break;
+
+ case PRT_ID_ISO_8602:
+ /* ISO 8602 CLTP */
+ if (!pinfo->fd->flags.visited)
+ x25_hash_add_proto_start(vc, pinfo->fd->num, ositp_handle);
+ break;
+ }
+ } else if (is_x_264 == 0) {
+ /* It doesn't look like a UN TPDU, so compare the first
+ octet of the CALL REQUEST packet with various X.263/
+ ISO 9577 NLPIDs, as per Annex A of X.263/ISO 9577. */
+
+ if (userdata_tree) {
+ proto_tree_add_text(userdata_tree, tvb, localoffset, 1,
+ "X.263 secondary protocol ID: %s",
+ val_to_str(spi, nlpid_vals, "Unknown (0x%02x)"));
+ }
+
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * Is there a dissector handle for this SPI?
+ * If so, assign it to this virtual circuit.
+ */
+ dissect = dissector_get_port_handle(x25_subdissector_table, spi);
+ if (dissect != NULL)
+ x25_hash_add_proto_start(vc, pinfo->fd->num, dissect);
+ }
+
+ /*
+ * If there's only one octet of user data, it's just
+ * an NLPID; don't try to dissect it.
+ */
+ if (localoffset + 1 == tvb_reported_length(tvb))
+ return;
+
+ /*
+ * There's more than one octet of user data, so we'll
+ * dissect it; for some protocols, the NLPID is considered
+ * to be part of the PDU, so, for those cases, we don't
+ * skip past it. For other protocols, we skip the NLPID.
+ */
+ switch (spi) {
+
+ case NLPID_ISO8473_CLNP:
+ case NLPID_ISO9542_ESIS:
+ case NLPID_ISO10589_ISIS:
+ case NLPID_ISO10747_IDRP:
+ case NLPID_SNDCF:
+ /*
+ * The NLPID is part of the PDU. Don't skip it.
+ * But if it's all there is to the PDU, don't
+ * bother dissecting it.
+ */
+ break;
+
+ case NLPID_SPI_X_29:
+ /*
+ * The first 4 bytes of the call user data are
+ * the SPI plus 3 reserved bytes; they are not
+ * part of the data to be dissected as X.29 data.
+ */
+ localoffset += 4;
+ break;
+
+ default:
+ /*
+ * The NLPID isn't part of the PDU - skip it.
+ * If that means there's nothing to dissect
+ */
+ localoffset++;
+ }
+ }
+ }
+ break;
+ case X25_CALL_ACCEPTED:
+ switch (dir) {
+
+ case X25_FROM_DCE:
+ short_name = "Call conn.";
+ long_name = "Call connected";
+ break;
+
+ case X25_FROM_DTE:
+ short_name = "Call acc.";
+ long_name = "Call accepted";
+ break;
+
+ case X25_UNKNOWN:
+ short_name = "Call conn./Call acc.";
+ long_name = "Call connected/Call accepted";
+ break;
+ }
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d", short_name, vc);
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_CALL_ACCEPTED, "Packet Type: %s", long_name);
+ }
+ localoffset = 3;
+ if (localoffset < x25_pkt_len) { /* calling/called addresses */
+ if (toa)
+ x25_toa(x25_tree, &localoffset, tvb, pinfo);
+ else
+ x25_ntoa(x25_tree, &localoffset, tvb, pinfo, FALSE);
+ }
+
+ if (localoffset < x25_pkt_len) /* facilities */
+ dump_facilities(x25_tree, &localoffset, tvb);
+ break;
+ case X25_CLEAR_REQUEST:
+ switch (dir) {
+
+ case X25_FROM_DCE:
+ short_name = "Clear ind.";
+ long_name = "Clear indication";
+ break;
+
+ case X25_FROM_DTE:
+ short_name = "Clear req.";
+ long_name = "Clear request";
+ break;
+
+ case X25_UNKNOWN:
+ short_name = "Clear ind./Clear req.";
+ long_name = "Clear indication/Clear request";
+ break;
+ }
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d %s - %s", short_name,
+ vc, clear_code(tvb_get_guint8(tvb, 3)),
+ clear_diag(tvb_get_guint8(tvb, 4)));
+ }
+ x25_hash_add_proto_end(vc, pinfo->fd->num);
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb,
+ localoffset+2, 1, X25_CLEAR_REQUEST, "Packet Type: %s",
+ long_name);
+ proto_tree_add_text(x25_tree, tvb, 3, 1,
+ "Cause : %s", clear_code(tvb_get_guint8(tvb, 3)));
+ proto_tree_add_text(x25_tree, tvb, 4, 1,
+ "Diagnostic : %s", clear_diag(tvb_get_guint8(tvb, 4)));
+ }
+ localoffset = x25_pkt_len;
+ break;
+ case X25_CLEAR_CONFIRMATION:
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Clear Conf. VC:%d", vc);
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_CLEAR_CONFIRMATION);
+ }
+ localoffset = x25_pkt_len;
+
+ if (localoffset < tvb_reported_length(tvb)) { /* extended clear conf format */
+ if (toa)
+ x25_toa(x25_tree, &localoffset, tvb, pinfo);
+ else
+ x25_ntoa(x25_tree, &localoffset, tvb, pinfo, FALSE);
+ }
+
+ if (localoffset < tvb_reported_length(tvb)) /* facilities */
+ dump_facilities(x25_tree, &localoffset, tvb);
+ break;
+ case X25_DIAGNOSTIC:
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Diag. %d",
+ (int)tvb_get_guint8(tvb, 3));
+ }
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_DIAGNOSTIC);
+ proto_tree_add_text(x25_tree, tvb, 3, 1,
+ "Diagnostic : %d", (int)tvb_get_guint8(tvb, 3));
+ }
+ localoffset = x25_pkt_len;
+ break;
+ case X25_INTERRUPT:
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Interrupt VC:%d", vc);
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_INTERRUPT);
+ }
+ localoffset = x25_pkt_len;
+ break;
+ case X25_INTERRUPT_CONFIRMATION:
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Interrupt Conf. VC:%d", vc);
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_INTERRUPT_CONFIRMATION);
+ }
+ localoffset = x25_pkt_len;
+ break;
+ case X25_RESET_REQUEST:
+ switch (dir) {
+
+ case X25_FROM_DCE:
+ short_name = "Reset ind.";
+ long_name = "Reset indication";
+ break;
+
+ case X25_FROM_DTE:
+ short_name = "Reset req.";
+ long_name = "Reset request";
+ break;
+
+ case X25_UNKNOWN:
+ short_name = "Reset ind./Reset req.";
+ long_name = "Reset indication/Reset request";
+ break;
+ }
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s VC:%d %s - Diag.:%d",
+ short_name, vc, reset_code(tvb_get_guint8(tvb, 3)),
+ (int)tvb_get_guint8(tvb, 4));
+ }
+ x25_hash_add_proto_end(vc, pinfo->fd->num);
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_RESET_REQUEST, "Packet Type: %s", long_name);
+ proto_tree_add_text(x25_tree, tvb, 3, 1,
+ "Cause : %s", reset_code(tvb_get_guint8(tvb, 3)));
+ proto_tree_add_text(x25_tree, tvb, 4, 1,
+ "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
+ }
+ localoffset = x25_pkt_len;
+ break;
+ case X25_RESET_CONFIRMATION:
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Reset conf. VC:%d", vc);
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, 0, 2, bytes0_1);
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_RESET_CONFIRMATION);
+ }
+ localoffset = x25_pkt_len;
+ break;
+ case X25_RESTART_REQUEST:
+ switch (dir) {
+
+ case X25_FROM_DCE:
+ short_name = "Restart ind.";
+ long_name = "Restart indication";
+ break;
+
+ case X25_FROM_DTE:
+ short_name = "Restart req.";
+ long_name = "Restart request";
+ break;
+
+ case X25_UNKNOWN:
+ short_name = "Restart ind./Restart req.";
+ long_name = "Restart indication/Restart request";
+ break;
+ }
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s - Diag.:%d",
+ short_name,
+ restart_code(tvb_get_guint8(tvb, 3)),
+ (int)tvb_get_guint8(tvb, 3));
+ }
+ if (x25_tree) {
+ proto_tree_add_uint_format(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_RESTART_REQUEST, "Packet Type: %s", long_name);
+ proto_tree_add_text(x25_tree, tvb, 3, 1,
+ "Cause : %s", restart_code(tvb_get_guint8(tvb, 3)));
+ proto_tree_add_text(x25_tree, tvb, 4, 1,
+ "Diagnostic : %d", (int)tvb_get_guint8(tvb, 4));
+ }
+ localoffset = x25_pkt_len;
+ break;
+ case X25_RESTART_CONFIRMATION:
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Restart conf.");
+ if (x25_tree)
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_RESTART_CONFIRMATION);
+ localoffset = x25_pkt_len;
+ break;
+ case X25_REGISTRATION_REQUEST:
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Registration req.");
+ if (x25_tree)
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_REGISTRATION_REQUEST);
+ localoffset = 3;
+ if (localoffset < x25_pkt_len)
+ x25_ntoa(x25_tree, &localoffset, tvb, pinfo, TRUE);
+
+ if (x25_tree) {
+ if (localoffset < x25_pkt_len)
+ proto_tree_add_text(x25_tree, tvb, localoffset, 1,
+ "Registration length: %d",
+ tvb_get_guint8(tvb, localoffset) & 0x7F);
+ if (localoffset+1 < x25_pkt_len)
+ proto_tree_add_text(x25_tree, tvb, localoffset+1,
+ tvb_get_guint8(tvb, localoffset) & 0x7F,
+ "Registration");
+ }
+ localoffset = tvb_reported_length(tvb);
+ break;
+ case X25_REGISTRATION_CONFIRMATION:
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Registration conf.");
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb, 2, 1,
+ X25_REGISTRATION_CONFIRMATION);
+ proto_tree_add_text(x25_tree, tvb, 3, 1,
+ "Cause: %s", registration_code(tvb_get_guint8(tvb, 3)));
+ proto_tree_add_text(x25_tree, tvb, 4, 1,
+ "Diagnostic: %s", registration_code(tvb_get_guint8(tvb, 4)));
+ }
+ localoffset = 5;
+ if (localoffset < x25_pkt_len)
+ x25_ntoa(x25_tree, &localoffset, tvb, pinfo, TRUE);
+
+ if (x25_tree) {
+ if (localoffset < x25_pkt_len)
+ proto_tree_add_text(x25_tree, tvb, localoffset, 1,
+ "Registration length: %d",
+ tvb_get_guint8(tvb, localoffset) & 0x7F);
+ if (localoffset+1 < x25_pkt_len)
+ proto_tree_add_text(x25_tree, tvb, localoffset+1,
+ tvb_get_guint8(tvb, localoffset) & 0x7F,
+ "Registration");
+ }
+ localoffset = tvb_reported_length(tvb);
+ break;
+ default :
+ localoffset = 2;
+ if (PACKET_IS_DATA(pkt_type))
+ {
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ if (modulo == 8)
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Data VC:%d P(S):%d P(R):%d %s", vc,
+ (pkt_type >> 1) & 0x07,
+ (pkt_type >> 5) & 0x07,
+ (pkt_type & X25_MBIT_MOD8) ? " M" : "");
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Data VC:%d P(S):%d P(R):%d %s", vc,
+ tvb_get_guint8(tvb, localoffset+1) >> 1,
+ pkt_type >> 1,
+ (tvb_get_guint8(tvb, localoffset+1) & X25_MBIT_MOD128) ? " M" : "");
+ }
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+ 2, bytes0_1);
+ if (modulo == 8) {
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
+ localoffset, 1, pkt_type);
+ proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod8, tvb,
+ localoffset, 1, pkt_type);
+ proto_tree_add_uint(x25_tree, hf_x25_p_s_mod8, tvb,
+ localoffset, 1, pkt_type);
+ proto_tree_add_uint(x25_tree, hf_x25_type_data, tvb,
+ localoffset, 1, pkt_type);
+ }
+ else {
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod128, tvb,
+ localoffset, 1, pkt_type);
+ proto_tree_add_uint(x25_tree, hf_x25_type_data, tvb,
+ localoffset, 1, pkt_type);
+ proto_tree_add_uint(x25_tree, hf_x25_p_s_mod128, tvb,
+ localoffset+1, 1,
+ tvb_get_guint8(tvb, localoffset+1));
+ proto_tree_add_boolean(x25_tree, hf_x25_mbit_mod128, tvb,
+ localoffset+1, 1,
+ tvb_get_guint8(tvb, localoffset+1));
+ }
+ }
+ if (modulo == 8) {
+ m_bit_set = pkt_type & X25_MBIT_MOD8;
+ localoffset += 1;
+ } else {
+ m_bit_set = tvb_get_guint8(tvb, localoffset+1) & X25_MBIT_MOD128;
+ localoffset += 2;
+ }
+ payload_len = tvb_reported_length_remaining(tvb, localoffset);
+ if (reassemble_x25) {
+ /*
+ * Reassemble received and sent traffic separately.
+ * We don't reassemble traffic with an unknown direction
+ * at all.
+ */
+ frag_key = vc;
+ if (side) {
+ /*
+ * OR in an extra bit to distinguish from traffic
+ * in the other direction.
+ */
+ frag_key |= 0x10000;
+ }
+ fd_head = fragment_add_seq_next(tvb, localoffset,
+ pinfo, frag_key,
+ x25_segment_table,
+ x25_reassembled_table,
+ payload_len, m_bit_set);
+ pinfo->fragmented = m_bit_set;
+
+ if (fd_head) {
+ if (fd_head->next) {
+ /* This is the last packet */
+ next_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->len,
+ fd_head->len);
+ tvb_set_child_real_data_tvbuff(tvb, next_tvb);
+ add_new_data_source(pinfo, next_tvb, "Reassembled X.25");
+ show_fragment_seq_tree(fd_head,
+ &x25_frag_items,
+ x25_tree,
+ pinfo, next_tvb);
+ }
+ }
+
+ if (m_bit_set && next_tvb == NULL) {
+ /*
+ * This isn't the last packet, so just
+ * show it as X.25 user data.
+ */
+ proto_tree_add_text(x25_tree, tvb, localoffset, -1,
+ "User data (%u byte%s)", payload_len,
+ plurality(payload_len, "", "s"));
+ return;
+ }
+ }
+ break;
+ }
+
+ /*
+ * Non-data packets (RR, RNR, REJ).
+ */
+ switch (PACKET_TYPE_FC(pkt_type))
+ {
+ case X25_RR:
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ if (modulo == 8)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "RR VC:%d P(R):%d",
+ vc, (pkt_type >> 5) & 0x07);
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "RR VC:%d P(R):%d",
+ vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
+ }
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+ 2, bytes0_1);
+ if (modulo == 8) {
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
+ localoffset, 1, pkt_type);
+ proto_tree_add_uint(x25_tree, hf_x25_type_fc_mod8, tvb,
+ localoffset, 1, X25_RR);
+ }
+ else {
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
+ localoffset, 1, X25_RR);
+ proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
+ localoffset+1, 1, FALSE);
+ }
+ }
+ break;
+
+ case X25_RNR:
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ if (modulo == 8)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "RNR VC:%d P(R):%d",
+ vc, (pkt_type >> 5) & 0x07);
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "RNR VC:%d P(R):%d",
+ vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
+ }
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+ 2, bytes0_1);
+ if (modulo == 8) {
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
+ localoffset, 1, pkt_type);
+ proto_tree_add_uint(x25_tree, hf_x25_type_fc_mod8, tvb,
+ localoffset, 1, X25_RNR);
+ }
+ else {
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
+ localoffset, 1, X25_RNR);
+ proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
+ localoffset+1, 1, FALSE);
+ }
+ }
+ break;
+
+ case X25_REJ:
+ if(check_col(pinfo->cinfo, COL_INFO)) {
+ if (modulo == 8)
+ col_add_fstr(pinfo->cinfo, COL_INFO, "REJ VC:%d P(R):%d",
+ vc, (pkt_type >> 5) & 0x07);
+ else
+ col_add_fstr(pinfo->cinfo, COL_INFO, "REJ VC:%d P(R):%d",
+ vc, tvb_get_guint8(tvb, localoffset+1) >> 1);
+ }
+ if (x25_tree) {
+ proto_tree_add_uint(x25_tree, hf_x25_lcn, tvb, localoffset-2,
+ 2, bytes0_1);
+ if (modulo == 8) {
+ proto_tree_add_uint(x25_tree, hf_x25_p_r_mod8, tvb,
+ localoffset, 1, pkt_type);
+ proto_tree_add_uint(x25_tree, hf_x25_type_fc_mod8, tvb,
+ localoffset, 1, X25_REJ);
+ }
+ else {
+ proto_tree_add_uint(x25_tree, hf_x25_type, tvb,
+ localoffset, 1, X25_REJ);
+ proto_tree_add_item(x25_tree, hf_x25_p_r_mod128, tvb,
+ localoffset+1, 1, FALSE);
+ }
+ }
+ }
+ localoffset += (modulo == 8) ? 1 : 2;
+ }
+
+ if (localoffset >= tvb_reported_length(tvb))
+ return;
+ if (pinfo->fragmented)
+ return;
+
+ if (!next_tvb)
+ next_tvb = tvb_new_subset(tvb, localoffset, -1, -1);
+
+ saved_private_data = pinfo->private_data;
+ pinfo->private_data = &q_bit_set;
+
+ /* See if there's already a dissector for this circuit. */
+ if (try_circuit_dissector(CT_X25, vc, pinfo->fd->num, next_tvb, pinfo,
+ tree)) {
+ pinfo->private_data = saved_private_data;
+ return; /* found it and dissected it */
+ }
+
+ /* Did the user suggest QLLC/SNA? */
+ if (payload_is_qllc_sna) {
+ /* Yes - dissect it as QLLC/SNA. */
+ if (!pinfo->fd->flags.visited)
+ x25_hash_add_proto_start(vc, pinfo->fd->num, qllc_handle);
+ call_dissector(qllc_handle, next_tvb, pinfo, tree);
+ pinfo->private_data = saved_private_data;
+ return;
+ }
+
+ /* If the Call Req. has not been captured, let's look at the first
+ byte of the payload to see if this looks like IP or CLNP. */
+ switch (tvb_get_guint8(tvb, localoffset)) {
+
+ case 0x45:
+ /* Looks like an IP header */
+ if (!pinfo->fd->flags.visited)
+ x25_hash_add_proto_start(vc, pinfo->fd->num, ip_handle);
+ call_dissector(ip_handle, next_tvb, pinfo, tree);
+ pinfo->private_data = saved_private_data;
+ return;
+
+ case NLPID_ISO8473_CLNP:
+ if (!pinfo->fd->flags.visited)
+ x25_hash_add_proto_start(vc, pinfo->fd->num, clnp_handle);
+ call_dissector(clnp_handle, next_tvb, pinfo, tree);
+ pinfo->private_data = saved_private_data;
+ return;
+ }
+
+ /* Try the heuristic dissectors. */
+ if (dissector_try_heuristic(x25_heur_subdissector_list, next_tvb, pinfo,
+ tree)) {
+ pinfo->private_data = saved_private_data;
+ return;
+ }
+
+ /* All else failed; dissect it as raw data */
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ pinfo->private_data = saved_private_data;
+}
+
+/*
+ * X.25 dissector for use when "pinfo->pseudo_header" points to a
+ * "struct x25_phdr".
+ */
+static void
+dissect_x25_dir(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ dissect_x25_common(tvb, pinfo, tree,
+ (pinfo->pseudo_header->x25.flags & FROM_DCE) ? X25_FROM_DCE :
+ X25_FROM_DTE,
+ pinfo->pseudo_header->x25.flags & FROM_DCE);
+}
+
+/*
+ * X.25 dissector for use when "pinfo->pseudo_header" doesn't point to a
+ * "struct x25_phdr".
+ */
+static void
+dissect_x25(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int direction;
+
+ /*
+ * We don't know if this packet is DTE->DCE or DCE->DCE.
+ * However, we can, at least, distinguish between the two
+ * sides of the conversation, based on the addresses and
+ * ports.
+ */
+ direction = CMP_ADDRESS(&pinfo->src, &pinfo->dst);
+ if (direction == 0)
+ direction = (pinfo->srcport > pinfo->destport)*2 - 1;
+ dissect_x25_common(tvb, pinfo, tree, X25_UNKNOWN, direction > 0);
+}
+
+static void
+x25_reassemble_init(void)
+{
+ fragment_table_init(&x25_segment_table);
+ reassembled_table_init(&x25_reassembled_table);
+}
+
+void
+proto_register_x25(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_x25_gfi,
+ { "GFI", "x.25.gfi", FT_UINT16, BASE_DEC, NULL, 0xF000,
+ "General format identifier", HFILL }},
+ { &hf_x25_abit,
+ { "A Bit", "x.25.a", FT_BOOLEAN, 16, NULL, X25_ABIT,
+ "Address Bit", HFILL }},
+ { &hf_x25_qbit,
+ { "Q Bit", "x.25.q", FT_BOOLEAN, 16, NULL, X25_QBIT,
+ "Qualifier Bit", HFILL }},
+ { &hf_x25_dbit,
+ { "D Bit", "x.25.d", FT_BOOLEAN, 16, NULL, X25_DBIT,
+ "Delivery Confirmation Bit", HFILL }},
+ { &hf_x25_mod,
+ { "Modulo", "x.25.mod", FT_UINT16, BASE_DEC, VALS(vals_modulo), 0x3000,
+ "Specifies whether the frame is modulo 8 or 128", HFILL }},
+ { &hf_x25_lcn,
+ { "Logical Channel", "x.25.lcn", FT_UINT16, BASE_DEC, NULL, 0x0FFF,
+ "Logical Channel Number", HFILL }},
+ { &hf_x25_type,
+ { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x0,
+ "Packet Type", HFILL }},
+ { &hf_x25_type_fc_mod8,
+ { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x1F,
+ "Packet Type", HFILL }},
+ { &hf_x25_type_data,
+ { "Packet Type", "x.25.type", FT_UINT8, BASE_HEX, VALS(vals_x25_type), 0x01,
+ "Packet Type", HFILL }},
+ { &hf_x25_p_r_mod8,
+ { "P(R)", "x.25.p_r", FT_UINT8, BASE_DEC, NULL, 0xE0,
+ "Packet Receive Sequence Number", HFILL }},
+ { &hf_x25_p_r_mod128,
+ { "P(R)", "x.25.p_r", FT_UINT8, BASE_DEC, NULL, 0xFE,
+ "Packet Receive Sequence Number", HFILL }},
+ { &hf_x25_mbit_mod8,
+ { "M Bit", "x.25.m", FT_BOOLEAN, 8, TFS(&m_bit_tfs), X25_MBIT_MOD8,
+ "More Bit", HFILL }},
+ { &hf_x25_mbit_mod128,
+ { "M Bit", "x.25.m", FT_BOOLEAN, 8, TFS(&m_bit_tfs), X25_MBIT_MOD128,
+ "More Bit", HFILL }},
+ { &hf_x25_p_s_mod8,
+ { "P(S)", "x.25.p_s", FT_UINT8, BASE_DEC, NULL, 0x0E,
+ "Packet Send Sequence Number", HFILL }},
+ { &hf_x25_p_s_mod128,
+ { "P(S)", "x.25.p_s", FT_UINT8, BASE_DEC, NULL, 0xFE,
+ "Packet Send Sequence Number", HFILL }},
+ { &hf_x25_segment_overlap,
+ { "Fragment overlap", "x25.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment overlaps with other fragments", HFILL }},
+
+ { &hf_x25_segment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "x25.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping fragments contained conflicting data", HFILL }},
+
+ { &hf_x25_segment_multiple_tails,
+ { "Multiple tail fragments found", "x25.fragment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when defragmenting the packet", HFILL }},
+
+ { &hf_x25_segment_too_long_segment,
+ { "Fragment too long", "x25.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Fragment contained data past end of packet", HFILL }},
+
+ { &hf_x25_segment_error,
+ { "Defragmentation error", "x25.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Defragmentation error due to illegal fragments", HFILL }},
+
+ { &hf_x25_segment,
+ { "X.25 Fragment", "x25.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "X25 Fragment", HFILL }},
+
+ { &hf_x25_segments,
+ { "X.25 Fragments", "x25.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
+ "X.25 Fragments", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_x25,
+ &ett_x25_gfi,
+ &ett_x25_fac,
+ &ett_x25_fac_unknown,
+ &ett_x25_fac_mark,
+ &ett_x25_fac_reverse,
+ &ett_x25_fac_throughput,
+ &ett_x25_fac_cug,
+ &ett_x25_fac_called_modif,
+ &ett_x25_fac_cug_outgoing_acc,
+ &ett_x25_fac_throughput_min,
+ &ett_x25_fac_express_data,
+ &ett_x25_fac_bilateral_cug,
+ &ett_x25_fac_packet_size,
+ &ett_x25_fac_window_size,
+ &ett_x25_fac_rpoa_selection,
+ &ett_x25_fac_transit_delay,
+ &ett_x25_fac_call_transfer,
+ &ett_x25_fac_called_addr_ext,
+ &ett_x25_fac_ete_transit_delay,
+ &ett_x25_fac_calling_addr_ext,
+ &ett_x25_fac_call_deflect,
+ &ett_x25_fac_priority,
+ &ett_x25_user_data,
+ &ett_x25_segment,
+ &ett_x25_segments
+ };
+ module_t *x25_module;
+
+ proto_x25 = proto_register_protocol ("X.25", "X.25", "x.25");
+ proto_register_field_array (proto_x25, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ x25_subdissector_table = register_dissector_table("x.25.spi",
+ "X.25 secondary protocol identifier", FT_UINT8, BASE_HEX);
+ register_heur_dissector_list("x.25", &x25_heur_subdissector_list);
+
+ register_dissector("x.25_dir", dissect_x25_dir, proto_x25);
+ register_dissector("x.25", dissect_x25, proto_x25);
+
+ /* Preferences */
+ x25_module = prefs_register_protocol(proto_x25, NULL);
+ prefs_register_obsolete_preference(x25_module, "non_q_bit_is_sna");
+ prefs_register_bool_preference(x25_module, "payload_is_qllc_sna",
+ "Default to QLLC/SNA",
+ "If CALL REQUEST not seen or didn't specify protocol, dissect as QLLC/SNA",
+ &payload_is_qllc_sna);
+ prefs_register_bool_preference(x25_module, "reassemble",
+ "Reassemble fragmented X.25 packets",
+ "Reassemble fragmented X.25 packets",
+ &reassemble_x25);
+ register_init_routine(&x25_reassemble_init);
+}
+
+void
+proto_reg_handoff_x25(void)
+{
+ dissector_handle_t x25_handle;
+
+ /*
+ * Get handles for various dissectors.
+ */
+ ip_handle = find_dissector("ip");
+ clnp_handle = find_dissector("clnp");
+ ositp_handle = find_dissector("ositp");
+ qllc_handle = find_dissector("qllc");
+ data_handle = find_dissector("data");
+
+ x25_handle = find_dissector("x.25");
+ dissector_add("llc.dsap", SAP_X25, x25_handle);
+}
diff --git a/epan/dissectors/packet-x29.c b/epan/dissectors/packet-x29.c
new file mode 100644
index 0000000000..5d7b937b47
--- /dev/null
+++ b/epan/dissectors/packet-x29.c
@@ -0,0 +1,281 @@
+/* packet-x29.c
+ * Routines for X.29 packet dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/strutil.h>
+#include "nlpid.h"
+
+static int proto_x29 = -1;
+static int hf_msg_code = -1;
+static int hf_error_type = -1;
+static int hf_inv_msg_code = -1;
+
+static gint ett_x29 = -1;
+
+/*
+ * PAD messages.
+ */
+#define SET_MSG 0x02
+#define READ_MSG 0x04
+#define SET_AND_READ_MSG 0x06
+#define PARAMETER_IND_MSG 0x00
+#define INV_TO_CLEAR_MSG 0x01
+#define BREAK_IND_MSG 0x03
+#define RESELECTION_MSG 0x07
+#define ERROR_MSG 0x05
+#define RESEL_WITH_TOA_NPI_MSG 0x08
+
+static const value_string message_code_vals[] = {
+ { SET_MSG, "Set" },
+ { READ_MSG, "Read" },
+ { SET_AND_READ_MSG, "Set and read" },
+ { PARAMETER_IND_MSG, "Parameter indication" },
+ { INV_TO_CLEAR_MSG, "Invitation to clear" },
+ { BREAK_IND_MSG, "Indication of break" },
+ { RESELECTION_MSG, "Reselection" },
+ { ERROR_MSG, "Error" },
+ { RESEL_WITH_TOA_NPI_MSG, "Reselection with TOA/NPI" },
+ { 0, NULL }
+};
+
+static const value_string error_type_vals[] = {
+ { 0x00, "Received PAD message contained less than eight bits" },
+ { 0x02, "Unrecognized message code in received PAD message" },
+ { 0x04, "Parameter field format was incorrect or incompatible with message code" },
+ { 0x06, "Received PAD message did not contain an integral number of octets" },
+ { 0x08, "Received Parameter Indication PAD message was unsolicited" },
+ { 0x0A, "Received PAD message was too long" },
+ { 0x0C, "Unauthorized reselection PAD message" },
+ { 0, NULL },
+};
+
+static void
+dissect_x29(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ proto_tree *x29_tree = NULL;
+ proto_item *ti;
+ gboolean *q_bit_set = pinfo->private_data;
+ guint8 msg_code;
+ guint8 error_type;
+ guint8 type_ref;
+ gint next_offset;
+ int linelen;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "X.29");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_x29, tvb, offset, -1,
+ FALSE);
+ x29_tree = proto_item_add_subtree(ti, ett_x29);
+ }
+
+ if (*q_bit_set) {
+ /*
+ * Q bit set - this is a PAD message.
+ */
+ msg_code = tvb_get_guint8(tvb, offset);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s PAD message",
+ val_to_str(msg_code, message_code_vals,
+ "Unknown (0x%02x)"));
+ }
+ proto_tree_add_uint(x29_tree, hf_msg_code, tvb,
+ offset, 1, msg_code);
+ offset++;
+
+ switch (msg_code) {
+
+ case SET_MSG:
+ case READ_MSG:
+ case SET_AND_READ_MSG:
+ case PARAMETER_IND_MSG:
+ /*
+ * XXX - dissect the references as per X.3.
+ */
+ while (tvb_reported_length_remaining(tvb, offset) > 0) {
+ proto_tree_add_text(x29_tree, tvb, offset, 2,
+ "Parameter %u, value %u",
+ tvb_get_guint8(tvb, offset),
+ tvb_get_guint8(tvb, offset + 1));
+ offset += 2;
+ }
+ break;
+
+ case INV_TO_CLEAR_MSG:
+ /*
+ * No data for this message.
+ */
+ break;
+
+ case ERROR_MSG:
+ error_type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(x29_tree, hf_error_type, tvb,
+ offset, 1, error_type);
+ offset++;
+ if (error_type != 0) {
+ proto_tree_add_item(x29_tree, hf_inv_msg_code,
+ tvb, offset, 1, FALSE);
+ }
+ break;
+
+ case BREAK_IND_MSG:
+ if (tvb_reported_length_remaining(tvb, offset) > 0) {
+ type_ref = tvb_get_guint8(tvb, offset);
+ switch (type_ref) {
+
+ case 0x01: /* change in PAD Aspect */
+ /*
+ * XXX - dissect as per X.28.
+ */
+ proto_tree_add_text(x29_tree, tvb,
+ offset, 1, "Type reference: Change in PAD Aspect");
+ offset++;
+ proto_tree_add_text(x29_tree, tvb,
+ offset, 1, "Type of aspect: 0x%02x",
+ type_ref);
+ offset++;
+ break;
+
+ case 0x08: /* break */
+ proto_tree_add_text(x29_tree, tvb,
+ offset, 1, "Type reference: Break");
+ offset++;
+ proto_tree_add_text(x29_tree, tvb,
+ offset, 1, "Break value: 0x%02x",
+ type_ref);
+ offset++;
+ break;
+
+ default:
+ proto_tree_add_text(x29_tree, tvb,
+ offset, 1, "Unknown type reference (0x%02x)",
+ type_ref);
+ offset++;
+ proto_tree_add_text(x29_tree, tvb,
+ offset, 1, "Type value: 0x%02x",
+ type_ref);
+ offset++;
+ break;
+ }
+ }
+ break;
+
+ case RESELECTION_MSG:
+ /*
+ * XXX - dissect me.
+ */
+ proto_tree_add_text(x29_tree, tvb, offset, -1,
+ "Reselection message data");
+ break;
+
+ case RESEL_WITH_TOA_NPI_MSG:
+ /*
+ * XXX - dissect me.
+ */
+ proto_tree_add_text(x29_tree, tvb, offset, -1,
+ "Reselection message data");
+ break;
+
+ default:
+ proto_tree_add_text(x29_tree, tvb, offset, -1,
+ "PAD message data");
+ break;
+ }
+ } else {
+ /*
+ * Q bit not set - this is data.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Data ...");
+
+ if (tree) {
+ while (tvb_offset_exists(tvb, offset)) {
+ /*
+ * Find the end of the line.
+ */
+ linelen = tvb_find_line_end(tvb, offset, -1,
+ &next_offset, FALSE);
+
+ /*
+ * Now compute the length of the line
+ * *including* the end-of-line indication,
+ * if any; we display it all.
+ */
+ linelen = next_offset - offset;
+
+ proto_tree_add_text(x29_tree, tvb, offset,
+ linelen, "Data: %s",
+ tvb_format_text(tvb, offset, linelen));
+ offset = next_offset;
+ }
+ }
+ }
+}
+
+void
+proto_register_x29(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_msg_code,
+ { "Message code", "x29.msg_code", FT_UINT8, BASE_HEX,
+ VALS(message_code_vals), 0x0, "X.29 PAD message code",
+ HFILL }},
+ { &hf_error_type,
+ { "Error type", "x29.error_type", FT_UINT8, BASE_HEX,
+ VALS(error_type_vals), 0x0, "X.29 error PAD message error type",
+ HFILL }},
+ { &hf_inv_msg_code,
+ { "Invalid message code", "x29.inv_msg_code", FT_UINT8, BASE_HEX,
+ VALS(message_code_vals), 0x0, "X.29 Error PAD message invalid message code",
+ HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_x29,
+ };
+
+ proto_x29 = proto_register_protocol("X.29", "X.29", "x.29");
+ proto_register_field_array(proto_x29, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_x29(void)
+{
+ dissector_handle_t x29_handle;
+
+ x29_handle = create_dissector_handle(dissect_x29, proto_x29);
+ dissector_add("x.25.spi", NLPID_SPI_X_29, x29_handle);
+}
diff --git a/epan/dissectors/packet-xdmcp.c b/epan/dissectors/packet-xdmcp.c
new file mode 100644
index 0000000000..6bf94692c7
--- /dev/null
+++ b/epan/dissectors/packet-xdmcp.c
@@ -0,0 +1,520 @@
+/* packet-xdmcp.c
+ * Routines for XDMCP message dissection
+ * Copyright 2002, Pasi Eronen <pasi.eronen@nixu.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+#define UDP_PORT_XDMCP 177
+
+#define XDMCP_PROTOCOL_VERSION 1
+
+#define XDMCP_BROADCAST_QUERY 1
+#define XDMCP_QUERY 2
+#define XDMCP_INDIRECT_QUERY 3
+#define XDMCP_FORWARD_QUERY 4
+#define XDMCP_WILLING 5
+#define XDMCP_UNWILLING 6
+#define XDMCP_REQUEST 7
+#define XDMCP_ACCEPT 8
+#define XDMCP_DECLINE 9
+#define XDMCP_MANAGE 10
+#define XDMCP_REFUSE 11
+#define XDMCP_FAILED 12
+#define XDMCP_KEEPALIVE 13
+#define XDMCP_ALIVE 14
+
+static const value_string opcode_vals[] = {
+ { XDMCP_BROADCAST_QUERY, "Broadcast_query" },
+ { XDMCP_QUERY, "Query" },
+ { XDMCP_INDIRECT_QUERY, "Indirect_query" },
+ { XDMCP_FORWARD_QUERY, "Forward_query" },
+ { XDMCP_WILLING, "Willing" },
+ { XDMCP_UNWILLING, "Unwilling" },
+ { XDMCP_REQUEST, "Request" },
+ { XDMCP_ACCEPT, "Accept "},
+ { XDMCP_DECLINE, "Decline" },
+ { XDMCP_MANAGE, "Manage" },
+ { XDMCP_REFUSE, "Refuse" },
+ { XDMCP_FAILED, "Failed" },
+ { XDMCP_KEEPALIVE, "Keepalive" },
+ { XDMCP_ALIVE, "Alive" },
+ { 0, NULL }
+};
+
+/* Copied from packet-x11.c */
+static const value_string family_vals[] = {
+ { 0, "Internet" },
+ { 1, "DECnet" },
+ { 2, "Chaos" },
+ { 0, NULL }
+};
+
+static gint proto_xdmcp = -1;
+static gint hf_xdmcp_version = -1;
+static gint hf_xdmcp_opcode = -1;
+static gint hf_xdmcp_length = -1;
+static gint hf_xdmcp_authentication_name = -1;
+static gint hf_xdmcp_authorization_name = -1;
+static gint hf_xdmcp_hostname = -1;
+static gint hf_xdmcp_status = -1;
+static gint hf_xdmcp_session_id = -1;
+static gint hf_xdmcp_display_number = -1;
+
+static gint ett_xdmcp = -1;
+static gint ett_xdmcp_authorization_names = -1;
+static gint ett_xdmcp_connections = -1;
+static gint ett_xdmcp_connection = -1;
+
+/* Copied from packet-x11.c */
+static void stringCopy(char *dest, const char *source, int length)
+{
+ guchar c;
+ while(length--) {
+ c = *source++;
+ if (!isgraph(c) && c != ' ') c = '.';
+ *dest++ = c;
+ }
+ *dest++ = '\0';
+}
+
+static gint xdmcp_add_string(proto_tree *tree, gint hf,
+ tvbuff_t *tvb, gint offset)
+{
+ const guint8 *p;
+ char *str;
+ guint len;
+
+ len = tvb_get_ntohs(tvb, offset);
+ p = tvb_get_ptr(tvb, offset+2, len);
+ str = g_malloc(len+1);
+ stringCopy(str, p, len);
+ proto_tree_add_string(tree, hf, tvb, offset, len+2, str);
+ g_free(str);
+
+ return len+2;
+}
+
+static gint xdmcp_add_text(proto_tree *tree, const char *text,
+ tvbuff_t *tvb, gint offset)
+{
+ const guint8 *p;
+ char *str;
+ guint len;
+
+ len = tvb_get_ntohs(tvb, offset);
+ p = tvb_get_ptr(tvb, offset+2, len);
+ str = g_malloc(len+1);
+ stringCopy(str, p, len);
+ proto_tree_add_text(tree, tvb, offset, len+2, "%s: %s", text, str);
+ g_free(str);
+
+ return len+2;
+}
+
+static gint xdmcp_add_bytes(proto_tree *tree, const char *text,
+ tvbuff_t *tvb, gint offset)
+{
+ guint len;
+ len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, len+2,
+ "%s (%u byte%s)", text, len, plurality(len, "", "s"));
+ return len+2;
+}
+
+static gint xdmcp_add_authorization_names(proto_tree *tree,
+ tvbuff_t *tvb, gint offset)
+{
+ proto_tree *anames_tree;
+ proto_item *anames_ti;
+ gint anames_len, anames_start_offset;
+
+ anames_start_offset = offset;
+ anames_len = tvb_get_guint8(tvb, offset);
+ anames_ti = proto_tree_add_text(tree, tvb,
+ anames_start_offset, -1,
+ "Authorization names (%d)",
+ anames_len);
+ anames_tree = proto_item_add_subtree(anames_ti,
+ ett_xdmcp_authorization_names);
+
+ anames_len = tvb_get_guint8(tvb, offset);
+ offset++;
+ while (anames_len > 0) {
+ offset += xdmcp_add_string(anames_tree, hf_xdmcp_authorization_name,
+ tvb, offset);
+ anames_len--;
+ }
+ proto_item_set_len(anames_ti, offset - anames_start_offset);
+ return offset - anames_start_offset;
+}
+
+/*
+ * I didn't find any documentation for the XDMCP protocol, so
+ * this is reverse-engineered from XFree86 source files
+ * xc/programs/xdm/xdmcp.c and xc/programs/Xserver/os/xdmcp.c.
+ */
+
+static void dissect_xdmcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gint version = -1, opcode = -1;
+ gint offset = 0;
+ proto_item *ti;
+ proto_tree *xdmcp_tree = 0;
+
+ version = tvb_get_ntohs(tvb, offset);
+ if (version != XDMCP_PROTOCOL_VERSION) {
+ /* Only version 1 exists, so this probably is not XDMCP at all... */
+ return;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "XDMCP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_xdmcp, tvb, offset, -1, FALSE);
+ xdmcp_tree = proto_item_add_subtree(ti, ett_xdmcp);
+
+ proto_tree_add_uint(xdmcp_tree, hf_xdmcp_version, tvb,
+ offset, 2, version);
+ }
+ offset += 2;
+
+ opcode = tvb_get_ntohs(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(xdmcp_tree, hf_xdmcp_opcode, tvb,
+ offset, 2, opcode);
+ }
+ offset += 2;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ val_to_str(opcode, opcode_vals, "Unknown (0x%04x)"));
+
+ }
+
+ if (tree) {
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_length, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ switch (opcode) {
+ case XDMCP_FORWARD_QUERY:
+ {
+ gint alen, plen;
+ alen = tvb_get_ntohs(tvb, offset);
+ /* I have never seen anything except IPv4 addresses here,
+ * but in theory the protocol should support other address
+ * families. */
+ if (alen == 4) {
+ proto_tree_add_text(xdmcp_tree, tvb, offset, alen+2,
+ "Client address: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset+2, 4)));
+ offset += 6;
+ } else {
+ offset += xdmcp_add_bytes(xdmcp_tree, "Client address", tvb, offset);
+ }
+
+ plen = tvb_get_ntohs(tvb, offset);
+ if (plen == 2) {
+ proto_tree_add_text(xdmcp_tree, tvb, offset, plen+2,
+ "Client port: %u",
+ tvb_get_ntohs(tvb, offset+2));
+ offset += 4;
+ } else {
+ offset += xdmcp_add_bytes(xdmcp_tree, "Client port", tvb, offset);
+ }
+ }
+ /* fall-through */
+
+ case XDMCP_BROADCAST_QUERY:
+ case XDMCP_QUERY:
+ case XDMCP_INDIRECT_QUERY:
+ offset += xdmcp_add_authorization_names(xdmcp_tree, tvb, offset);
+ break;
+
+ case XDMCP_WILLING:
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name,
+ tvb, offset);
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_hostname,
+ tvb, offset);
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status,
+ tvb, offset);
+ break;
+
+ case XDMCP_UNWILLING:
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_hostname,
+ tvb, offset);
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status,
+ tvb, offset);
+ break;
+
+ case XDMCP_REQUEST:
+ {
+ proto_tree *clist_tree;
+ proto_item *clist_ti;
+ gint ctypes_len, caddrs_len, n;
+ gint ctypes_start_offset, caddrs_offset;
+
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ ctypes_len = tvb_get_guint8(tvb, offset);
+ ctypes_start_offset = offset;
+ caddrs_offset = offset + 1 + 2*ctypes_len;
+ caddrs_len = tvb_get_guint8(tvb, caddrs_offset);
+ if (ctypes_len != caddrs_len) {
+ proto_tree_add_text(xdmcp_tree, NULL, 0, 0,
+ "Error: Connection type/address arrays don't match");
+ return;
+ }
+
+ clist_ti = proto_tree_add_text(xdmcp_tree,
+ tvb, ctypes_start_offset, -1,
+ "Connections (%d)",
+ ctypes_len);
+ clist_tree = proto_item_add_subtree(clist_ti, ett_xdmcp_connections);
+
+ offset++;
+ caddrs_offset++;
+
+ n = 1;
+ while (ctypes_len > 0) {
+ proto_item *connection_ti;
+ proto_tree *connection_tree;
+ const char *ip_string;
+
+ gint alen;
+ gint ctype = tvb_get_ntohs(tvb, offset);
+ offset += 2;
+ alen = tvb_get_ntohs(tvb, caddrs_offset);
+ caddrs_offset += 2;
+
+ if ((ctype == 0) && (alen == 4)) {
+ ip_string = ip_to_str(tvb_get_ptr(tvb, caddrs_offset, 4));
+ } else {
+ ip_string = NULL;
+ }
+
+ connection_ti = proto_tree_add_text(clist_tree, NULL, 0, 0,
+ "Connection %d%s%s", n,
+ (ip_string ? ": " : ""),
+ (ip_string ? ip_string : ""));
+ connection_tree = proto_item_add_subtree(connection_ti,
+ ett_xdmcp_connection);
+
+ proto_tree_add_text(connection_tree, tvb, offset-2, 2,
+ "Type: %s",
+ val_to_str(ctype, family_vals,
+ "Unknown (0x%04x)"));
+ if ((ctype == 0) && (alen == 4)) {
+ proto_tree_add_text(connection_tree, tvb, caddrs_offset-2, alen+2,
+ "Address: %s", ip_string);
+ } else {
+ proto_tree_add_text(connection_tree, tvb, caddrs_offset-2, alen+2,
+ "Address: (%u byte%s)", alen,
+ plurality(alen, "", "s"));
+ }
+ caddrs_offset += alen;
+ ctypes_len--;
+ n++;
+ }
+ offset = caddrs_offset;
+ proto_item_set_len(clist_ti, offset - ctypes_start_offset);
+
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name,
+ tvb, offset);
+ offset += xdmcp_add_bytes(xdmcp_tree, "Authentication data",
+ tvb, offset);
+
+ offset += xdmcp_add_authorization_names(xdmcp_tree, tvb, offset);
+
+ offset += xdmcp_add_text(xdmcp_tree, "Manufacturer display ID",
+ tvb, offset);
+ break;
+ }
+
+ case XDMCP_ACCEPT:
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name,
+ tvb, offset);
+ offset += xdmcp_add_bytes(xdmcp_tree, "Authentication data",
+ tvb, offset);
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authorization_name,
+ tvb, offset);
+ offset += xdmcp_add_bytes(xdmcp_tree, "Authorization data",
+ tvb, offset);
+ break;
+
+ case XDMCP_DECLINE:
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status,
+ tvb, offset);
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_authentication_name,
+ tvb, offset);
+ offset += xdmcp_add_bytes(xdmcp_tree, "Authentication data",
+ tvb, offset);
+ break;
+
+ case XDMCP_MANAGE:
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ offset += xdmcp_add_text(xdmcp_tree, "Display class",
+ tvb, offset);
+ break;
+
+ case XDMCP_REFUSE:
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ break;
+
+ case XDMCP_FAILED:
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ offset += xdmcp_add_string(xdmcp_tree, hf_xdmcp_status,
+ tvb, offset);
+ break;
+
+ case XDMCP_KEEPALIVE:
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_display_number, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ break;
+
+ case XDMCP_ALIVE:
+ proto_tree_add_text(xdmcp_tree, tvb, offset, 1,
+ "Session running: %s",
+ (tvb_get_guint8(tvb, offset) ? "Yes" : "No"));
+ offset++;
+
+ proto_tree_add_item(xdmcp_tree, hf_xdmcp_session_id, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ break;
+ }
+ }
+}
+
+/* Register the protocol with Ethereal */
+void proto_register_xdmcp(void)
+{
+ /* Setup list of header fields */
+ static hf_register_info hf[] = {
+ { &hf_xdmcp_version,
+ { "Version", "xdmcp.version",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Protocol version", HFILL }
+ },
+ { &hf_xdmcp_opcode,
+ { "Opcode", "xdmcp.opcode",
+ FT_UINT16, BASE_HEX, VALS(opcode_vals), 0,
+ "Opcode", HFILL }
+ },
+ { &hf_xdmcp_length,
+ { "Message length", "xdmcp.length",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Length of the remaining message", HFILL }
+ },
+ { &hf_xdmcp_authentication_name,
+ { "Authentication name", "xdmcp.authentication_name",
+ FT_STRING, BASE_DEC, NULL, 0,
+ "Authentication name", HFILL }
+ },
+ { &hf_xdmcp_authorization_name,
+ { "Authorization name", "xdmcp.authorization_name",
+ FT_STRING, BASE_DEC, NULL, 0,
+ "Authorization name", HFILL }
+ },
+ { &hf_xdmcp_hostname,
+ { "Hostname", "xdmcp.hostname",
+ FT_STRING, BASE_DEC, NULL, 0,
+ "Hostname", HFILL }
+ },
+ { &hf_xdmcp_status,
+ { "Status", "xdmcp.status",
+ FT_STRING, BASE_DEC, NULL, 0,
+ "Status", HFILL }
+ },
+ { &hf_xdmcp_session_id,
+ { "Session ID", "xdmcp.session_id",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ "Session identifier", HFILL }
+ },
+ { &hf_xdmcp_display_number,
+ { "Display number", "xdmcp.display_number",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ "Display number", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_xdmcp,
+ &ett_xdmcp_authorization_names,
+ &ett_xdmcp_connections,
+ &ett_xdmcp_connection
+ };
+
+ /* Register the protocol name and description */
+ proto_xdmcp = proto_register_protocol("X Display Manager Control Protocol",
+ "XDMCP", "xdmcp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_xdmcp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_xdmcp(void)
+{
+ dissector_handle_t xdmcp_handle;
+
+ xdmcp_handle = create_dissector_handle(dissect_xdmcp, proto_xdmcp);
+ dissector_add("udp.port", UDP_PORT_XDMCP, xdmcp_handle);
+}
diff --git a/epan/dissectors/packet-xot.c b/epan/dissectors/packet-xot.c
new file mode 100644
index 0000000000..6c3f56fe15
--- /dev/null
+++ b/epan/dissectors/packet-xot.c
@@ -0,0 +1,174 @@
+/* packet-xot.c
+ * Routines for X.25 over TCP dissection (RFC 1613)
+ *
+ * Copyright 2000, Paul Ionescu <paul@acorp.ro>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include "packet-tcp.h"
+#include "prefs.h"
+
+#define TCP_PORT_XOT 1998
+
+static gint proto_xot = -1;
+static gint hf_xot_version = -1;
+static gint hf_xot_length = -1;
+
+static gint ett_xot = -1;
+
+/* desegmentation of X.25 over TCP */
+static gboolean xot_desegment = TRUE;
+
+static dissector_handle_t x25_handle;
+
+static guint get_xot_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint16 plen;
+
+ /*
+ * Get the length of the X.25-over-TCP packet.
+ */
+ plen = tvb_get_ntohs(tvb, offset + 2);
+
+ /*
+ * That length doesn't include the header; add that in.
+ */
+ return plen + 4;
+}
+
+static void dissect_xot_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint16 version;
+ guint16 plen;
+ int length;
+ proto_item *ti;
+ proto_tree *xot_tree;
+ tvbuff_t *next_tvb;
+
+ /*
+ * Dissect the X.25-over-TCP packet.
+ */
+ version = tvb_get_ntohs(tvb, offset + 0);
+ plen = tvb_get_ntohs(tvb, offset + 2);
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "XOT");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "XOT Version = %u, size = %u",
+ version, plen);
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_xot, tvb, offset, 4,
+ "X.25 over TCP");
+ xot_tree = proto_item_add_subtree(ti, ett_xot);
+
+ proto_tree_add_uint(xot_tree, hf_xot_version, tvb, offset, 2, version);
+ proto_tree_add_uint(xot_tree, hf_xot_length, tvb, offset + 2, 2, plen);
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload we have
+ * available. Make its reported length the amount of data in the
+ * X.25-over-TCP packet.
+ */
+ length = tvb_length_remaining(tvb, offset + 4);
+ if (length > plen)
+ length = plen;
+ next_tvb = tvb_new_subset(tvb, offset + 4, length, plen);
+ call_dissector(x25_handle, next_tvb, pinfo, tree);
+}
+
+static int dissect_xot(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ /*
+ * Do we have the full version number and, if so, is it zero?
+ * If we have it but it's not zero, reject this segment.
+ */
+ if (tvb_bytes_exist(tvb, 0, 2)) {
+ if (tvb_get_ntohs(tvb, 0) != 0)
+ return 0;
+ }
+
+ /*
+ * The version number's OK, so dissect this segment.
+ */
+ tcp_dissect_pdus(tvb, pinfo, tree, xot_desegment, 4, get_xot_pdu_len,
+ dissect_xot_pdu);
+
+ return tvb_length(tvb);
+}
+
+/* Register the protocol with Ethereal */
+void
+proto_register_xot(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_xot_version,
+ { "Version", "xot.version", FT_UINT16, BASE_DEC,
+ NULL, 0, "Version of X.25 over TCP protocol", HFILL }},
+
+ { &hf_xot_length,
+ { "Length", "xot.length", FT_UINT16, BASE_DEC,
+ NULL, 0, "Length of X.25 over TCP packet", HFILL }}
+
+ };
+
+ static gint *ett[] = {
+ &ett_xot,
+ };
+ module_t *xot_module;
+
+ proto_xot = proto_register_protocol("X.25 over TCP", "XOT", "xot");
+ proto_register_field_array(proto_xot, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ xot_module = prefs_register_protocol(proto_xot, NULL);
+ prefs_register_bool_preference(xot_module, "desegment",
+ "Desegment all X.25-over-TCP messages spanning multiple TCP segments",
+ "Whether the X.25-over-TCP dissector should desegment all messages spanning multiple TCP segments",
+ &xot_desegment);
+}
+
+void
+proto_reg_handoff_xot(void)
+{
+ dissector_handle_t xot_handle;
+
+ /*
+ * Get a handle for the X.25 dissector.
+ */
+ x25_handle = find_dissector("x.25");
+
+ xot_handle = new_create_dissector_handle(dissect_xot, proto_xot);
+ dissector_add("tcp.port", TCP_PORT_XOT, xot_handle);
+}
diff --git a/epan/dissectors/packet-xyplex.c b/epan/dissectors/packet-xyplex.c
new file mode 100644
index 0000000000..9ad7a58b59
--- /dev/null
+++ b/epan/dissectors/packet-xyplex.c
@@ -0,0 +1,215 @@
+/* packet-xyplex.c
+ * Routines for xyplex packet dissection
+ *
+ * Copyright 2002 Randy McEoin <rmceoin@pe.com>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+static int proto_xyplex = -1;
+static int hf_xyplex_type = -1;
+static int hf_xyplex_pad = -1;
+static int hf_xyplex_server_port = -1;
+static int hf_xyplex_return_port = -1;
+static int hf_xyplex_reserved = -1;
+static int hf_xyplex_reply = -1;
+
+static gint ett_xyplex = -1;
+
+static dissector_handle_t xyplex_handle;
+
+#define UDP_PORT_XYPLEX 173
+
+#define XYPLEX_REG_OK 0x00
+#define XYPLEX_REG_QUEFULL 0x05
+
+static const value_string xyplex_reg_vals[] = {
+ { XYPLEX_REG_OK, "OK" },
+ { XYPLEX_REG_QUEFULL, "Queue Full" },
+ { 0, NULL }
+};
+
+static void
+dissect_xyplex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *xyplex_tree = NULL;
+ proto_item *ti;
+ conversation_t *conversation;
+ gint offset = 0;
+
+ guint8 prototype;
+ guint8 padding;
+ guint16 server_port;
+ guint16 return_port;
+ guint16 reserved;
+ guint16 reply;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "XYPLEX");
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_xyplex, tvb, offset, -1, FALSE);
+ xyplex_tree = proto_item_add_subtree(ti, ett_xyplex);
+ }
+
+ if (pinfo->destport == UDP_PORT_XYPLEX) {
+ /* This is a registration request from a Unix server
+ * to the Xyplex server. The server_port indicates
+ * which Xyplex serial port is desired. The
+ * return_port tells the Xyplex server what TCP port
+ * to open to the Unix server.
+ */
+ prototype = tvb_get_guint8(tvb, offset);
+ padding = tvb_get_guint8(tvb, offset+1);
+ server_port = tvb_get_ntohs(tvb, offset+2);
+ return_port = tvb_get_ntohs(tvb, offset+4);
+ reserved = tvb_get_ntohs(tvb, offset+6);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "Registration Request: %d Return: %d",
+ server_port, return_port);
+ }
+ if (tree) {
+ proto_tree_add_uint(xyplex_tree, hf_xyplex_type, tvb,
+ offset, 1, prototype);
+ proto_tree_add_uint(xyplex_tree, hf_xyplex_pad, tvb,
+ offset+1, 1, padding);
+ proto_tree_add_uint(xyplex_tree, hf_xyplex_server_port, tvb,
+ offset+2, 2, server_port);
+ proto_tree_add_uint(xyplex_tree, hf_xyplex_return_port, tvb,
+ offset+4, 2, return_port);
+ proto_tree_add_uint(xyplex_tree, hf_xyplex_reserved, tvb,
+ offset+6, 2, reserved);
+ }
+ offset += 8;
+
+ /* Look for all future TCP conversations between the
+ * requestiong server and the Xyplex host using the
+ * return_port.
+ */
+ conversation = find_conversation(&pinfo->src, &pinfo->dst,
+ PT_TCP, return_port, 0, NO_PORT_B);
+ if (conversation == NULL) {
+ conversation = conversation_new(&pinfo->src, &pinfo->dst,
+ PT_TCP, return_port, 0, NO_PORT2);
+ conversation_set_dissector(conversation, xyplex_handle);
+ }
+ return;
+ }
+
+ if (pinfo->srcport == UDP_PORT_XYPLEX) {
+ prototype = tvb_get_guint8(tvb, offset);
+ padding = tvb_get_guint8(tvb, offset+1);
+ reply = tvb_get_ntohs(tvb, offset+2);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Registration Reply: %s",
+ val_to_str(reply, xyplex_reg_vals, "Unknown (0x%02x)"));
+ }
+ if (tree) {
+ proto_tree_add_uint(xyplex_tree, hf_xyplex_type, tvb,
+ offset, 1, prototype);
+ proto_tree_add_uint(xyplex_tree, hf_xyplex_pad, tvb,
+ offset+1, 1, padding);
+ proto_tree_add_uint(xyplex_tree, hf_xyplex_reply, tvb,
+ offset+2, 2, reply);
+ }
+ offset += 4;
+ return;
+ }
+
+ /*
+ * This must be the TCP data stream. This will just be
+ * the raw data being transfered from the remote server
+ * and the Xyplex serial port.
+ */
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d Data",
+ pinfo->srcport, pinfo->destport);
+ }
+ if (tree) {
+ proto_tree_add_text(xyplex_tree, tvb, offset, -1,
+ "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
+ }
+}
+
+
+void
+proto_register_xyplex(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_xyplex_type,
+ { "Type", "xyplex.type",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Protocol type", HFILL }},
+
+ { &hf_xyplex_pad,
+ { "Pad", "xyplex.pad",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Padding", HFILL }},
+
+ { &hf_xyplex_server_port,
+ { "Server Port", "xyplex.server_port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Server port", HFILL }},
+
+ { &hf_xyplex_return_port,
+ { "Return Port", "xyplex.return_port",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Return port", HFILL }},
+
+ { &hf_xyplex_reserved,
+ { "Reserved field", "xyplex.reserved",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Reserved field", HFILL }},
+
+ { &hf_xyplex_reply,
+ { "Registration Reply", "xyplex.reply",
+ FT_UINT16, BASE_DEC, VALS(xyplex_reg_vals), 0x0,
+ "Registration reply", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_xyplex,
+ };
+
+ proto_xyplex = proto_register_protocol("Xyplex", "XYPLEX", "xyplex");
+ proto_register_field_array(proto_xyplex, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ xyplex_handle = create_dissector_handle(dissect_xyplex, proto_xyplex);
+}
+
+void
+proto_reg_handoff_xyplex(void)
+{
+ dissector_add("udp.port", UDP_PORT_XYPLEX, xyplex_handle);
+}
+
diff --git a/epan/dissectors/packet-yhoo.c b/epan/dissectors/packet-yhoo.c
new file mode 100644
index 0000000000..f812816421
--- /dev/null
+++ b/epan/dissectors/packet-yhoo.c
@@ -0,0 +1,298 @@
+/* packet-yhoo.c
+ * Routines for yahoo messenger packet dissection
+ * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+static int proto_yhoo = -1;
+static int hf_yhoo_version = -1;
+static int hf_yhoo_len = -1;
+static int hf_yhoo_service = -1;
+static int hf_yhoo_connection_id = -1;
+static int hf_yhoo_magic_id = -1;
+static int hf_yhoo_unknown1 = -1;
+static int hf_yhoo_msgtype = -1;
+static int hf_yhoo_nick1 = -1;
+static int hf_yhoo_nick2 = -1;
+static int hf_yhoo_content = -1;
+
+static gint ett_yhoo = -1;
+
+#define TCP_PORT_YHOO 5050
+
+/* This is from yahoolib.h from gtkyahoo */
+
+/* Service constants */
+#define YAHOO_SERVICE_LOGON 1
+#define YAHOO_SERVICE_LOGOFF 2
+#define YAHOO_SERVICE_ISAWAY 3
+#define YAHOO_SERVICE_ISBACK 4
+#define YAHOO_SERVICE_IDLE 5
+#define YAHOO_SERVICE_MESSAGE 6
+#define YAHOO_SERVICE_IDACT 7
+#define YAHOO_SERVICE_IDDEACT 8
+#define YAHOO_SERVICE_MAILSTAT 9
+#define YAHOO_SERVICE_USERSTAT 10
+#define YAHOO_SERVICE_NEWMAIL 11
+#define YAHOO_SERVICE_CHATINVITE 12
+#define YAHOO_SERVICE_CALENDAR 13
+#define YAHOO_SERVICE_NEWPERSONALMAIL 14
+#define YAHOO_SERVICE_NEWCONTACT 15
+#define YAHOO_SERVICE_ADDIDENT 16
+#define YAHOO_SERVICE_ADDIGNORE 17
+#define YAHOO_SERVICE_PING 18
+#define YAHOO_SERVICE_GROUPRENAME 19
+#define YAHOO_SERVICE_SYSMESSAGE 20
+#define YAHOO_SERVICE_PASSTHROUGH2 22
+#define YAHOO_SERVICE_CONFINVITE 24
+#define YAHOO_SERVICE_CONFLOGON 25
+#define YAHOO_SERVICE_CONFDECLINE 26
+#define YAHOO_SERVICE_CONFLOGOFF 27
+#define YAHOO_SERVICE_CONFADDINVITE 28
+#define YAHOO_SERVICE_CONFMSG 29
+#define YAHOO_SERVICE_CHATLOGON 30
+#define YAHOO_SERVICE_CHATLOGOFF 31
+#define YAHOO_SERVICE_CHATMSG 32
+#define YAHOO_SERVICE_FILETRANSFER 70
+
+/* Message flags */
+#define YAHOO_MSGTYPE_NONE 0
+#define YAHOO_MSGTYPE_NORMAL 1
+#define YAHOO_MSGTYPE_BOUNCE 2
+#define YAHOO_MSGTYPE_STATUS 4
+#define YAHOO_MSGTYPE_OFFLINE 1515563606 /* yuck! */
+
+struct yahoo_rawpacket
+{
+ char version[8]; /* 7 chars and trailing null */
+ unsigned char len[4]; /* length - little endian */
+ unsigned char service[4]; /* service - little endian */
+ unsigned char connection_id[4]; /* connection number - little endian */
+ unsigned char magic_id[4]; /* magic number used for http session */
+ unsigned char unknown1[4];
+ unsigned char msgtype[4];
+ char nick1[36];
+ char nick2[36];
+ char content[1]; /* was zero, had problems with aix xlc */
+};
+
+static const value_string yhoo_service_vals[] = {
+ {YAHOO_SERVICE_LOGON, "Pager Logon"},
+ {YAHOO_SERVICE_LOGOFF, "Pager Logoff"},
+ {YAHOO_SERVICE_ISAWAY, "Is Away"},
+ {YAHOO_SERVICE_ISBACK, "Is Back"},
+ {YAHOO_SERVICE_IDLE, "Idle"},
+ {YAHOO_SERVICE_MESSAGE, "Message"},
+ {YAHOO_SERVICE_IDACT, "Activate Identity"},
+ {YAHOO_SERVICE_IDDEACT, "Deactivate Identity"},
+ {YAHOO_SERVICE_MAILSTAT, "Mail Status"},
+ {YAHOO_SERVICE_USERSTAT, "User Status"},
+ {YAHOO_SERVICE_NEWMAIL, "New Mail"},
+ {YAHOO_SERVICE_CHATINVITE, "Chat Invitation"},
+ {YAHOO_SERVICE_CALENDAR, "Calendar Reminder"},
+ {YAHOO_SERVICE_NEWPERSONALMAIL, "New Personals Mail"},
+ {YAHOO_SERVICE_NEWCONTACT, "New Friend"},
+ {YAHOO_SERVICE_GROUPRENAME, "Group Renamed"},
+ {YAHOO_SERVICE_ADDIDENT, "Add Identity"},
+ {YAHOO_SERVICE_ADDIGNORE, "Add Ignore"},
+ {YAHOO_SERVICE_PING, "Ping"},
+ {YAHOO_SERVICE_SYSMESSAGE, "System Message"},
+ {YAHOO_SERVICE_CONFINVITE, "Conference Invitation"},
+ {YAHOO_SERVICE_CONFLOGON, "Conference Logon"},
+ {YAHOO_SERVICE_CONFDECLINE, "Conference Decline"},
+ {YAHOO_SERVICE_CONFLOGOFF, "Conference Logoff"},
+ {YAHOO_SERVICE_CONFMSG, "Conference Message"},
+ {YAHOO_SERVICE_CONFADDINVITE, "Conference Additional Invitation"},
+ {YAHOO_SERVICE_CHATLOGON, "Chat Logon"},
+ {YAHOO_SERVICE_CHATLOGOFF, "Chat Logoff"},
+ {YAHOO_SERVICE_CHATMSG, "Chat Message"},
+ {YAHOO_SERVICE_FILETRANSFER, "File Transfer"},
+ {YAHOO_SERVICE_PASSTHROUGH2, "Passthrough 2"},
+ {0, NULL}
+};
+
+static const value_string yhoo_msgtype_vals[] = {
+ {YAHOO_MSGTYPE_NONE, "None"},
+ {YAHOO_MSGTYPE_NORMAL, "Normal"},
+ {YAHOO_MSGTYPE_BOUNCE, "Bounce"},
+ {YAHOO_MSGTYPE_STATUS, "Status Update"},
+ {YAHOO_MSGTYPE_OFFLINE, "Request Offline"},
+ {0, NULL}
+};
+
+static gboolean
+dissect_yhoo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *yhoo_tree, *ti;
+ int offset = 0;
+
+ if (pinfo->srcport != TCP_PORT_YHOO && pinfo->destport != TCP_PORT_YHOO) {
+ /* Not the Yahoo port - not a Yahoo Messenger packet. */
+ return FALSE;
+ }
+
+ /* get at least a full packet structure */
+ if ( !tvb_bytes_exist(tvb, 0, sizeof(struct yahoo_rawpacket)) ) {
+ /* Not enough data captured; maybe it is a Yahoo
+ Messenger packet, but it contains too little data to
+ tell. */
+ return FALSE;
+ }
+
+ if (memcmp(tvb_get_ptr(tvb, offset, 4), "YPNS", 4) != 0 &&
+ memcmp(tvb_get_ptr(tvb, offset, 4), "YHOO", 4) != 0) {
+ /* Not a Yahoo Messenger packet. */
+ return FALSE;
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "YHOO");
+
+ offset = 0;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s: %s",
+ ( strncmp(tvb_get_ptr(tvb, offset + 0, 4), "YPNS", 4) == 0 ) ? "Request" : "Response",
+ val_to_str(tvb_get_letohl(tvb, offset + 12),
+ yhoo_service_vals, "Unknown Service: %u")
+ );
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_yhoo, tvb, offset, -1,
+ FALSE);
+ yhoo_tree = proto_item_add_subtree(ti, ett_yhoo);
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_version, tvb,
+ offset, 8, TRUE);
+ offset += 8;
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_len, tvb,
+ offset, 4, TRUE);
+ offset += 4;
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_service, tvb,
+ offset, 4, TRUE);
+ offset += 4;
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_connection_id, tvb,
+ offset, 4, TRUE);
+ offset += 4;
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_magic_id, tvb,
+ offset, 4, TRUE);
+ offset += 4;
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_unknown1, tvb,
+ offset, 4, TRUE);
+ offset += 4;
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_msgtype, tvb,
+ offset, 4, TRUE);
+ offset += 4;
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_nick1, tvb,
+ offset, 36, TRUE);
+ offset += 36;
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_nick2, tvb,
+ offset, 36, TRUE);
+ offset += 36;
+
+ proto_tree_add_item(yhoo_tree, hf_yhoo_content, tvb, -1,
+ offset, TRUE);
+ }
+
+ return TRUE;
+}
+
+void
+proto_register_yhoo(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_yhoo_service, {
+ "Service Type", "yhoo.service", FT_UINT32, BASE_DEC,
+ VALS(yhoo_service_vals), 0, "Service Type", HFILL }},
+ { &hf_yhoo_msgtype, {
+ "Message Type", "yhoo.msgtype", FT_UINT32, BASE_DEC,
+ VALS(yhoo_msgtype_vals), 0, "Message Type Flags", HFILL }},
+ { &hf_yhoo_connection_id, {
+ "Connection ID", "yhoo.connection_id", FT_UINT32, BASE_HEX,
+ NULL, 0, "Connection ID", HFILL }},
+ { &hf_yhoo_magic_id, {
+ "Magic ID", "yhoo.magic_id", FT_UINT32, BASE_HEX,
+ NULL, 0, "Magic ID", HFILL }},
+ { &hf_yhoo_unknown1, {
+ "Unknown 1", "yhoo.unknown1", FT_UINT32, BASE_HEX,
+ NULL, 0, "Unknown 1", HFILL }},
+ { &hf_yhoo_len, {
+ "Packet Length", "yhoo.len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Packet Length", HFILL }},
+ { &hf_yhoo_nick1, {
+ "Real Nick (nick1)", "yhoo.nick1", FT_STRING, 0,
+ NULL, 0, "Real Nick (nick1)", HFILL }},
+ { &hf_yhoo_nick2, {
+ "Active Nick (nick2)", "yhoo.nick2", FT_STRING, 0,
+ NULL, 0, "Active Nick (nick2)", HFILL }},
+ { &hf_yhoo_content, {
+ "Content", "yhoo.content", FT_STRING, 0,
+ NULL, 0, "Data portion of the packet", HFILL }},
+ { &hf_yhoo_version, {
+ "Version", "yhoo.version", FT_STRING, 0,
+ NULL, 0, "Packet version identifier", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_yhoo,
+ };
+
+ proto_yhoo = proto_register_protocol("Yahoo Messenger Protocol",
+ "YHOO", "yhoo");
+
+ proto_register_field_array(proto_yhoo, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_yhoo(void)
+{
+ /*
+ * DO NOT register for port 5050, as that's used by the
+ * old and new Yahoo messenger protocols.
+ *
+ * Just register as a heuristic TCP dissector, and reject stuff
+ * not to or from that port.
+ */
+ heur_dissector_add("tcp", dissect_yhoo, proto_yhoo);
+}
diff --git a/epan/dissectors/packet-ymsg.c b/epan/dissectors/packet-ymsg.c
new file mode 100644
index 0000000000..a9ed099730
--- /dev/null
+++ b/epan/dissectors/packet-ymsg.c
@@ -0,0 +1,433 @@
+/* packet-ymsg.c
+ * Routines for Yahoo Messenger YMSG protocol packet version 9 dissection
+ * Copyright 2003, Wayne Parrott <wayne_p@pacific.net.au>
+ * Copied from packet-yhoo.c and updated
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+
+#include "packet-tcp.h"
+#include "prefs.h"
+
+static int proto_ymsg = -1;
+static int hf_ymsg_version = -1;
+static int hf_ymsg_len = -1;
+static int hf_ymsg_service = -1;
+static int hf_ymsg_status = -1;
+static int hf_ymsg_session_id = -1;
+static int hf_ymsg_content = -1;
+
+static gint ett_ymsg = -1;
+static gint ett_ymsg_content = -1;
+
+#define TCP_PORT_YMSG 23 /* XXX - this is Telnet! */
+#define TCP_PORT_YMSG_2 25 /* And this is SMTP! */
+#define TCP_PORT_YMSG_3 5050 /* This, however, is regular Yahoo Messenger */
+
+/* desegmentation of YMSG over TCP */
+static gboolean ymsg_desegment = TRUE;
+
+/*
+ * This is from yahoolib2.c from libyahoo2.
+ *
+ * See also
+ *
+ * http://libyahoo2.sourceforge.net/ymsg-9.txt
+ *
+ * and
+ *
+ * http://www.venkydude.com/articles/yahoo.htm
+ *
+ * and
+ *
+ * http://www.cse.iitb.ac.in/~varunk/YahooProtocol.htm
+ *
+ * and
+ *
+ * http://www.geocrawler.com/archives/3/4893/2002/1/0/7459037/
+ *
+ * and
+ *
+ * http://www.geocities.com/ziggycubbe/ym.html
+ */
+
+/* Service constants */
+enum yahoo_service { /* these are easier to see in hex */
+ YAHOO_SERVICE_LOGON = 1,
+ YAHOO_SERVICE_LOGOFF,
+ YAHOO_SERVICE_ISAWAY,
+ YAHOO_SERVICE_ISBACK,
+ YAHOO_SERVICE_IDLE, /* 5 (placemarker) */
+ YAHOO_SERVICE_MESSAGE,
+ YAHOO_SERVICE_IDACT,
+ YAHOO_SERVICE_IDDEACT,
+ YAHOO_SERVICE_MAILSTAT,
+ YAHOO_SERVICE_USERSTAT, /* 0xa */
+ YAHOO_SERVICE_NEWMAIL,
+ YAHOO_SERVICE_CHATINVITE,
+ YAHOO_SERVICE_CALENDAR,
+ YAHOO_SERVICE_NEWPERSONALMAIL,
+ YAHOO_SERVICE_NEWCONTACT,
+ YAHOO_SERVICE_ADDIDENT, /* 0x10 */
+ YAHOO_SERVICE_ADDIGNORE,
+ YAHOO_SERVICE_PING,
+ YAHOO_SERVICE_GOTGROUPRENAME, /* < 1, 36(old), 37(new) */
+ YAHOO_SERVICE_SYSMESSAGE = 0x14,
+ YAHOO_SERVICE_PASSTHROUGH2 = 0x16,
+ YAHOO_SERVICE_CONFINVITE = 0x18,
+ YAHOO_SERVICE_CONFLOGON,
+ YAHOO_SERVICE_CONFDECLINE,
+ YAHOO_SERVICE_CONFLOGOFF,
+ YAHOO_SERVICE_CONFADDINVITE,
+ YAHOO_SERVICE_CONFMSG,
+ YAHOO_SERVICE_CHATLOGON,
+ YAHOO_SERVICE_CHATLOGOFF,
+ YAHOO_SERVICE_CHATMSG = 0x20,
+ YAHOO_SERVICE_GAMELOGON = 0x28,
+ YAHOO_SERVICE_GAMELOGOFF,
+ YAHOO_SERVICE_GAMEMSG = 0x2a,
+ YAHOO_SERVICE_FILETRANSFER = 0x46,
+ YAHOO_SERVICE_VOICECHAT = 0x4A,
+ YAHOO_SERVICE_NOTIFY,
+ YAHOO_SERVICE_VERIFY,
+ YAHOO_SERVICE_P2PFILEXFER,
+ YAHOO_SERVICE_PEERTOPEER = 0x4F, /* Checks if P2P possible */
+ YAHOO_SERVICE_AUTHRESP = 0x54,
+ YAHOO_SERVICE_LIST,
+ YAHOO_SERVICE_AUTH = 0x57,
+ YAHOO_SERVICE_ADDBUDDY = 0x83,
+ YAHOO_SERVICE_REMBUDDY,
+ YAHOO_SERVICE_IGNORECONTACT, /* > 1, 7, 13 < 1, 66, 13, 0*/
+ YAHOO_SERVICE_REJECTCONTACT,
+ YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */
+ YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
+ YAHOO_SERVICE_CHATGOTO,
+ YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */
+ YAHOO_SERVICE_CHATLEAVE,
+ YAHOO_SERVICE_CHATEXIT = 0x9b,
+ YAHOO_SERVICE_CHATLOGOUT = 0xa0,
+ YAHOO_SERVICE_CHATPING,
+ YAHOO_SERVICE_COMMENT = 0xa8
+};
+
+/* Message flags */
+enum yahoo_status {
+ YAHOO_STATUS_AVAILABLE = 0,
+ YAHOO_STATUS_BRB,
+ YAHOO_STATUS_BUSY,
+ YAHOO_STATUS_NOTATHOME,
+ YAHOO_STATUS_NOTATDESK,
+ YAHOO_STATUS_NOTINOFFICE,
+ YAHOO_STATUS_ONPHONE,
+ YAHOO_STATUS_ONVACATION,
+ YAHOO_STATUS_OUTTOLUNCH,
+ YAHOO_STATUS_STEPPEDOUT,
+ YAHOO_STATUS_INVISIBLE = 12,
+ YAHOO_STATUS_CUSTOM = 99,
+ YAHOO_STATUS_IDLE = 999,
+ YAHOO_STATUS_OFFLINE = 0x5a55aa56, /* don't ask */
+ YAHOO_STATUS_TYPING = 0x16
+};
+
+struct yahoo_rawpacket
+{
+ char ymsg[4]; /* Packet identification string (YMSG) */
+ unsigned char version[4]; /* 4 bytes, little endian? */
+ unsigned char len[2]; /* length - little endian */
+ unsigned char service[2]; /* service - little endian */
+ unsigned char status[4]; /* Status - online, away etc.*/
+ unsigned char session_id[4]; /* Session ID */
+ char content[6]; /* 6 is the minimum size of the content */
+};
+
+static const value_string ymsg_service_vals[] = {
+ {YAHOO_SERVICE_LOGON, "Pager Logon"},
+ {YAHOO_SERVICE_LOGOFF, "Pager Logoff"},
+ {YAHOO_SERVICE_ISAWAY, "Is Away"},
+ {YAHOO_SERVICE_ISBACK, "Is Back"},
+ {YAHOO_SERVICE_IDLE, "Idle"},
+ {YAHOO_SERVICE_MESSAGE, "Message"},
+ {YAHOO_SERVICE_IDACT, "Activate Identity"},
+ {YAHOO_SERVICE_IDDEACT, "Deactivate Identity"},
+ {YAHOO_SERVICE_MAILSTAT, "Mail Status"},
+ {YAHOO_SERVICE_USERSTAT, "User Status"},
+ {YAHOO_SERVICE_NEWMAIL, "New Mail"},
+ {YAHOO_SERVICE_CHATINVITE, "Chat Invitation"},
+ {YAHOO_SERVICE_CALENDAR, "Calendar Reminder"},
+ {YAHOO_SERVICE_NEWPERSONALMAIL, "New Personals Mail"},
+ {YAHOO_SERVICE_NEWCONTACT, "New Friend"},
+ {YAHOO_SERVICE_ADDIDENT, "Add Identity"},
+ {YAHOO_SERVICE_ADDIGNORE, "Add Ignore"},
+ {YAHOO_SERVICE_PING, "Ping"},
+ {YAHOO_SERVICE_GOTGROUPRENAME, "YAHOO_SERVICE_GOTGROUPRENAME"},
+ {YAHOO_SERVICE_SYSMESSAGE, "System Message"},
+ {YAHOO_SERVICE_PASSTHROUGH2, "Passthrough 2"},
+ {YAHOO_SERVICE_CONFINVITE, "Conference Invitation"},
+ {YAHOO_SERVICE_CONFLOGON, "Conference Logon"},
+ {YAHOO_SERVICE_CONFDECLINE, "Conference Decline"},
+ {YAHOO_SERVICE_CONFLOGOFF, "Conference Logoff"},
+ {YAHOO_SERVICE_CONFADDINVITE, "Conference Additional Invitation"},
+ {YAHOO_SERVICE_CONFMSG, "Conference Message"},
+ {YAHOO_SERVICE_CHATLOGON, "Chat Logon"},
+ {YAHOO_SERVICE_CHATLOGOFF, "Chat Logoff"},
+ {YAHOO_SERVICE_CHATMSG, "Chat Message"},
+ {YAHOO_SERVICE_GAMELOGON, "Game Logon"},
+ {YAHOO_SERVICE_GAMELOGOFF, "Game Logoff"},
+ {YAHOO_SERVICE_GAMEMSG, "Game Message"},
+ {YAHOO_SERVICE_FILETRANSFER, "File Transfer"},
+ {YAHOO_SERVICE_VOICECHAT, "Voice Chat"},
+ {YAHOO_SERVICE_NOTIFY, "YAHOO_SERVICE_NOTIFY"},
+ {YAHOO_SERVICE_VERIFY, "YAHOO_SERVICE_VERIFY"},
+ {YAHOO_SERVICE_P2PFILEXFER, "YAHOO_SERVICE_P2PFILEXFER"},
+ {YAHOO_SERVICE_PEERTOPEER, "YAHOO_SERVICE_PEERTOPEER"},
+ {YAHOO_SERVICE_AUTHRESP, "YAHOO_SERVICE_AUTHRESP"},
+ {YAHOO_SERVICE_LIST, "YAHOO_SERVICE_LIST"},
+ {YAHOO_SERVICE_AUTH, "YAHOO_SERVICE_AUTH"},
+ {YAHOO_SERVICE_ADDBUDDY, "YAHOO_SERVICE_ADDBUDDY"},
+ {YAHOO_SERVICE_REMBUDDY, "YAHOO_SERVICE_REMBUDDY"},
+ {YAHOO_SERVICE_IGNORECONTACT, "YAHOO_SERVICE_IGNORECONTACT"},
+ {YAHOO_SERVICE_REJECTCONTACT, "YAHOO_SERVICE_REJECTCONTACT"},
+ {YAHOO_SERVICE_GROUPRENAME, "Group Renamed"},
+ {YAHOO_SERVICE_CHATONLINE, "YAHOO_SERVICE_CHATONLINE"},
+ {YAHOO_SERVICE_CHATGOTO, "YAHOO_SERVICE_CHATGOTO"},
+ {YAHOO_SERVICE_CHATJOIN, "YAHOO_SERVICE_CHATJOIN"},
+ {YAHOO_SERVICE_CHATLEAVE, "YAHOO_SERVICE_CHATLEAVE"},
+ {YAHOO_SERVICE_CHATEXIT, "YAHOO_SERVICE_CHATEXIT"},
+ {YAHOO_SERVICE_CHATLOGOUT, "YAHOO_SERVICE_CHATLOGOUT"},
+ {YAHOO_SERVICE_CHATPING, "YAHOO_SERVICE_CHATPING"},
+ {YAHOO_SERVICE_COMMENT, "YAHOO_SERVICE_COMMENT"},
+ {0, NULL}
+};
+
+static const value_string ymsg_status_vals[] = {
+ {YAHOO_STATUS_AVAILABLE, "YAHOO_STATUS_AVAILABLE"},
+ {YAHOO_STATUS_BRB, "YAHOO_STATUS_BRB"},
+ {YAHOO_STATUS_BUSY, "YAHOO_STATUS_BUSY"},
+ {YAHOO_STATUS_NOTATHOME, "YAHOO_STATUS_NOTATHOME"},
+ {YAHOO_STATUS_NOTATDESK, "YAHOO_STATUS_NOTATDESK"},
+ {YAHOO_STATUS_NOTINOFFICE, "YAHOO_STATUS_NOTINOFFICE"},
+ {YAHOO_STATUS_ONPHONE, "YAHOO_STATUS_ONPHONE"},
+ {YAHOO_STATUS_ONVACATION, "YAHOO_STATUS_ONVACATION"},
+ {YAHOO_STATUS_OUTTOLUNCH, "YAHOO_STATUS_OUTTOLUNCH"},
+ {YAHOO_STATUS_STEPPEDOUT, "YAHOO_STATUS_STEPPEDOUT"},
+ {YAHOO_STATUS_INVISIBLE, "YAHOO_STATUS_INVISIBLE"},
+ {YAHOO_STATUS_CUSTOM, "YAHOO_STATUS_CUSTOM"},
+ {YAHOO_STATUS_IDLE, "YAHOO_STATUS_IDLE"},
+ {YAHOO_STATUS_OFFLINE, "YAHOO_STATUS_OFFLINE"},
+ {YAHOO_STATUS_TYPING, "YAHOO_STATUS_TYPING"},
+ {0, NULL}
+};
+
+static guint get_ymsg_pdu_len(tvbuff_t *tvb, int offset);
+static void dissect_ymsg_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+int
+get_content_item_length(tvbuff_t *tvb, int offset) {
+ int origoffset = offset;
+ guint16 curdata;
+ for (;;) {
+ curdata = tvb_get_ntohs(tvb, offset);
+ if (curdata == 0xc080) {
+ break;
+ }
+ offset++;
+ }
+ return offset - origoffset;
+}
+
+
+static gboolean
+dissect_ymsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+
+ if (tvb_memeql(tvb, 0, "YMSG", 4) == -1) {
+ /* Not a Yahoo Messenger packet. */
+ return FALSE;
+ }
+
+ tcp_dissect_pdus(tvb, pinfo, tree, ymsg_desegment, 8, get_ymsg_pdu_len,
+ dissect_ymsg_pdu);
+ return TRUE;
+}
+
+static guint
+get_ymsg_pdu_len(tvbuff_t *tvb, int offset)
+{
+ guint16 plen;
+
+ /*
+ * Get the length of the YMSG packet.
+ */
+ plen = tvb_get_ntohs(tvb, offset + 8);
+
+ /*
+ * That length doesn't include the length of the header itself; add that in.
+ */
+ return plen + 20;
+}
+
+static void
+dissect_ymsg_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_tree *ymsg_tree, *ti;
+ proto_item *content_item;
+ proto_tree *content_tree;
+ char *keybuf;
+ char *valbuf;
+ int headersize = sizeof(struct yahoo_rawpacket)-6;
+ int keylen = 0;
+ int vallen = 0;
+ int offset = 0;
+ int content_len = 0;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "YMSG");
+
+ offset = 0;
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s, %s",
+ val_to_str(tvb_get_ntohs(tvb, offset + 10),
+ ymsg_service_vals, "Unknown Service: %u"),
+ val_to_str(tvb_get_ntohl(tvb, offset + 12),
+ ymsg_status_vals, "Unknown Status: %u")
+ );
+ }
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ymsg, tvb, offset, -1,
+ FALSE);
+ ymsg_tree = proto_item_add_subtree(ti, ett_ymsg);
+
+ offset += 4; /* skip the YMSG string */
+
+ proto_tree_add_item(ymsg_tree, hf_ymsg_version, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ offset += 2; /* XXX - padding? */
+
+ content_len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(ymsg_tree, hf_ymsg_len, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(ymsg_tree, hf_ymsg_service, tvb,
+ offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(ymsg_tree, hf_ymsg_status, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(ymsg_tree, hf_ymsg_session_id, tvb,
+ offset, 4, TRUE);
+ offset += 4;
+
+ content_item = proto_tree_add_item(ymsg_tree, hf_ymsg_content, tvb,
+ offset, -1, TRUE);
+ content_tree = proto_item_add_subtree(content_item, ett_ymsg_content);
+
+ for (;;) {
+ if (offset >= headersize+content_len) {
+ break;
+ }
+ keylen = get_content_item_length (tvb, offset);
+ keybuf = tvb_format_text(tvb, offset, keylen);
+ vallen = get_content_item_length (tvb, offset+keylen+2);
+ content_item = proto_tree_add_text(content_tree, tvb, offset, keylen+vallen+4, "%s: ", keybuf);
+ valbuf = tvb_format_text(tvb, offset+keylen+2, vallen);
+ proto_item_append_text(content_item, "%s", valbuf);
+ offset += keylen+vallen+4;
+ }
+ }
+
+ return;
+}
+
+void
+proto_register_ymsg(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ymsg_version, {
+ "Version", "ymsg.version", FT_UINT16, BASE_DEC,
+ NULL, 0, "Packet version identifier", HFILL }},
+ { &hf_ymsg_len, {
+ "Packet Length", "ymsg.len", FT_UINT16, BASE_DEC,
+ NULL, 0, "Packet Length", HFILL }},
+ { &hf_ymsg_service, {
+ "Service", "ymsg.service", FT_UINT16, BASE_DEC,
+ VALS(ymsg_service_vals), 0, "Service Type", HFILL }},
+ { &hf_ymsg_status, {
+ "Status", "ymsg.status", FT_UINT32, BASE_DEC,
+ VALS(ymsg_status_vals), 0, "Message Type Flags", HFILL }},
+ { &hf_ymsg_session_id, {
+ "Session ID", "ymsg.session_id", FT_UINT32, BASE_HEX,
+ NULL, 0, "Connection ID", HFILL }},
+ { &hf_ymsg_content, {
+ "Content", "ymsg.content", FT_STRING, 0,
+ NULL, 0, "Data portion of the packet", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ymsg,
+ &ett_ymsg_content,
+ };
+ module_t *ymsg_module;
+
+ proto_ymsg = proto_register_protocol("Yahoo YMSG Messenger Protocol",
+ "YMSG", "ymsg");
+
+ proto_register_field_array(proto_ymsg, hf, array_length(hf));
+
+ proto_register_subtree_array(ett, array_length(ett));
+
+ ymsg_module = prefs_register_protocol(proto_ymsg, NULL);
+ prefs_register_bool_preference(ymsg_module, "desegment",
+ "Desegment all YMSG messages spanning multiple TCP segments",
+ "Whether the YMSG dissector should desegment all messages spanning multiple TCP segments",
+ &ymsg_desegment);
+}
+
+void
+proto_reg_handoff_ymsg(void)
+{
+ /*
+ * DO NOT register for port 23, as that's Telnet, or for port
+ * 25, as that's SMTP.
+ *
+ * Also, DO NOT register for port 5050, as that's used by the
+ * old and new Yahoo messenger protocols.
+ *
+ * Just register as a heuristic TCP dissector, and reject stuff
+ * that doesn't begin with a YMSG signature.
+ */
+ heur_dissector_add("tcp", dissect_ymsg, proto_ymsg);
+}
diff --git a/epan/dissectors/packet-ypbind.c b/epan/dissectors/packet-ypbind.c
new file mode 100644
index 0000000000..c66a503550
--- /dev/null
+++ b/epan/dissectors/packet-ypbind.c
@@ -0,0 +1,222 @@
+/* packet-ypbind.c
+ * Routines for ypbind dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-smb.c
+ *
+ * 2001 Ronnie Sahlberg, added dissectors for the commands
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-ypbind.h"
+
+static int proto_ypbind = -1;
+static int hf_ypbind_procedure_v1 = -1;
+static int hf_ypbind_procedure_v2 = -1;
+static int hf_ypbind_domain = -1;
+static int hf_ypbind_resp_type = -1;
+static int hf_ypbind_error = -1;
+static int hf_ypbind_addr = -1;
+static int hf_ypbind_port = -1;
+static int hf_ypbind_setdom_version = -1;
+
+static gint ett_ypbind = -1;
+
+
+static int
+dissect_ypbind_domain_v2_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ /* domain */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ypbind_domain, offset, NULL);
+
+ return offset;
+}
+
+#define YPBIND_RESP_TYPE_SUCC_VAL 1
+#define YPBIND_RESP_TYPE_FAIL_VAL 2
+static const value_string resp_type_vals[] = {
+ {YPBIND_RESP_TYPE_SUCC_VAL, "SUCC_VAL"},
+ {YPBIND_RESP_TYPE_FAIL_VAL, "FAIL_VAL"},
+ {0, NULL}
+};
+
+#define YPBIND_ERROR_ERR 1
+#define YPBIND_ERROR_NOSERV 2
+#define YPBIND_ERROR_RESC 3
+static const value_string error_vals[] = {
+ {YPBIND_ERROR_ERR, "Internal error"},
+ {YPBIND_ERROR_NOSERV, "No bound server for passed domain"},
+ {YPBIND_ERROR_RESC, "System resource allocation failure"},
+ {0, NULL}
+};
+
+static int
+dissect_ypbind_domain_v2_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 type;
+
+ /* response type */
+ type=tvb_get_ntohl(tvb, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypbind_resp_type, offset);
+
+ switch(type){
+ case YPBIND_RESP_TYPE_SUCC_VAL:
+ /* ip address */
+ proto_tree_add_item(tree, hf_ypbind_addr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* port */
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_ypbind_port, offset);
+
+ break;
+ case YPBIND_RESP_TYPE_FAIL_VAL:
+ /* error */
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_ypbind_resp_type, offset);
+ break;
+ }
+
+ return offset;
+}
+
+static int
+dissect_ypbind_setdomain_v2_request(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ /* domain */
+ offset = dissect_rpc_string(tvb, tree,
+ hf_ypbind_domain, offset, NULL);
+
+ /* ip address */
+ proto_tree_add_item(tree, hf_ypbind_addr,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+
+ /* port */
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_ypbind_port, offset);
+
+ /* version */
+ offset = dissect_rpc_uint32(tvb, tree,
+ hf_ypbind_setdom_version, offset);
+
+ return offset;
+}
+
+
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff ypbind1_proc[] = {
+ { YPBINDPROC_NULL, "NULL", NULL, NULL },
+ { YPBINDPROC_DOMAIN, "DOMAIN", NULL, NULL },
+ { YPBINDPROC_SETDOM, "SETDOMAIN", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string ypbind1_proc_vals[] = {
+ { YPBINDPROC_NULL, "NULL" },
+ { YPBINDPROC_DOMAIN, "DOMAIN" },
+ { YPBINDPROC_SETDOM, "SETDOMAIN" },
+ { 0, NULL }
+};
+/* end of YPBind version 1 */
+
+static const vsff ypbind2_proc[] = {
+ { YPBINDPROC_NULL, "NULL", NULL, NULL },
+ { YPBINDPROC_DOMAIN, "DOMAIN",
+ dissect_ypbind_domain_v2_request, dissect_ypbind_domain_v2_reply},
+ { YPBINDPROC_SETDOM, "SETDOMAIN",
+ dissect_ypbind_setdomain_v2_request, NULL},
+ { 0, NULL, NULL, NULL }
+};
+static const value_string ypbind2_proc_vals[] = {
+ { YPBINDPROC_NULL, "NULL" },
+ { YPBINDPROC_DOMAIN, "DOMAIN" },
+ { YPBINDPROC_SETDOM, "SETDOMAIN" },
+ { 0, NULL }
+};
+/* end of YPBind version 2 */
+
+
+void
+proto_register_ypbind(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ypbind_procedure_v1, {
+ "V1 Procedure", "ypbind.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(ypbind1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_ypbind_procedure_v2, {
+ "V2 Procedure", "ypbind.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(ypbind2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_ypbind_domain, {
+ "Domain", "ypbind.domain", FT_STRING, BASE_DEC,
+ NULL, 0, "Name of the NIS/YP Domain", HFILL }},
+
+ { &hf_ypbind_resp_type, {
+ "Response Type", "ypbind.resp_type", FT_UINT32, BASE_DEC,
+ VALS(resp_type_vals), 0, "Response type", HFILL }},
+
+ { &hf_ypbind_error, {
+ "Error", "ypbind.error", FT_UINT32, BASE_DEC,
+ VALS(error_vals), 0, "YPBIND Error code", HFILL }},
+
+ { &hf_ypbind_addr, {
+ "IP Addr", "ypbind.addr", FT_IPv4, BASE_DEC,
+ NULL, 0, "IP Address of server", HFILL }},
+
+ { &hf_ypbind_port, {
+ "Port", "ypbind.port", FT_UINT32, BASE_DEC,
+ NULL, 0, "Port to use", HFILL }},
+
+ { &hf_ypbind_setdom_version, {
+ "Version", "ypbind.setdom.version", FT_UINT32, BASE_DEC,
+ NULL, 0, "Version of setdom", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_ypbind,
+ };
+
+ proto_ypbind = proto_register_protocol("Yellow Pages Bind",
+ "YPBIND", "ypbind");
+ proto_register_field_array(proto_ypbind, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ypbind(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_ypbind, YPBIND_PROGRAM, ett_ypbind);
+ /* Register the procedure tables */
+ rpc_init_proc_table(YPBIND_PROGRAM, 1, ypbind1_proc, hf_ypbind_procedure_v1);
+ rpc_init_proc_table(YPBIND_PROGRAM, 2, ypbind2_proc, hf_ypbind_procedure_v2);
+}
diff --git a/epan/dissectors/packet-ypbind.h b/epan/dissectors/packet-ypbind.h
new file mode 100644
index 0000000000..19ef71f84f
--- /dev/null
+++ b/epan/dissectors/packet-ypbind.h
@@ -0,0 +1,34 @@
+/* packet-ypbind.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_YPBIND_H
+#define PACKET_YPBIND_H
+
+#define YPBINDPROC_NULL 0
+#define YPBINDPROC_DOMAIN 1
+#define YPBINDPROC_SETDOM 2
+
+#define YPBIND_PROGRAM 100007
+
+#endif
diff --git a/epan/dissectors/packet-yppasswd.c b/epan/dissectors/packet-yppasswd.c
new file mode 100644
index 0000000000..2db6fe9644
--- /dev/null
+++ b/epan/dissectors/packet-yppasswd.c
@@ -0,0 +1,173 @@
+/* packet-yppasswd.c
+ * Routines for yppasswd dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-yppasswd.h"
+
+static int proto_yppasswd = -1;
+static int hf_yppasswd_procedure_v1 = -1;
+static int hf_yppasswd_status = -1;
+static int hf_yppasswd_oldpass = -1;
+static int hf_yppasswd_newpw = -1;
+static int hf_yppasswd_newpw_name = -1;
+static int hf_yppasswd_newpw_passwd = -1;
+static int hf_yppasswd_newpw_uid = -1;
+static int hf_yppasswd_newpw_gid = -1;
+static int hf_yppasswd_newpw_gecos = -1;
+static int hf_yppasswd_newpw_dir = -1;
+static int hf_yppasswd_newpw_shell = -1;
+
+static gint ett_yppasswd = -1;
+static gint ett_yppasswd_newpw = -1;
+
+static int
+dissect_yppasswd_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item *lock_item = NULL;
+ proto_tree *lock_tree = NULL;
+
+ offset = dissect_rpc_string(tvb, tree, hf_yppasswd_oldpass,
+ offset, NULL);
+
+ lock_item = proto_tree_add_item(tree, hf_yppasswd_newpw, tvb,
+ offset, -1, FALSE);
+
+ lock_tree = proto_item_add_subtree(lock_item, ett_yppasswd_newpw);
+
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_yppasswd_newpw_name, offset, NULL);
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_yppasswd_newpw_passwd, offset, NULL);
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_yppasswd_newpw_uid, offset);
+ offset = dissect_rpc_uint32(tvb, lock_tree,
+ hf_yppasswd_newpw_gid, offset);
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_yppasswd_newpw_gecos, offset, NULL);
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_yppasswd_newpw_dir, offset, NULL);
+ offset = dissect_rpc_string(tvb, lock_tree,
+ hf_yppasswd_newpw_shell, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_yppasswd_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree, hf_yppasswd_status, offset);
+
+ return offset;
+}
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff yppasswd1_proc[] = {
+ { YPPASSWDPROC_NULL, "NULL",
+ NULL, NULL },
+ { YPPASSWDPROC_UPDATE, "UPDATE",
+ dissect_yppasswd_call, dissect_yppasswd_reply },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string yppasswd1_proc_vals[] = {
+ { YPPASSWDPROC_NULL, "NULL" },
+ { YPPASSWDPROC_UPDATE, "UPDATE" },
+ { 0, NULL }
+};
+
+void
+proto_register_yppasswd(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_yppasswd_procedure_v1, {
+ "V1 Procedure", "yppasswd.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(yppasswd1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_yppasswd_status, {
+ "status", "yppasswd.status", FT_UINT32, BASE_DEC,
+ NULL, 0, "YPPasswd update status", HFILL }},
+
+ { &hf_yppasswd_oldpass, {
+ "oldpass", "yppasswd.oldpass", FT_STRING, BASE_DEC,
+ NULL, 0, "Old encrypted password", HFILL }},
+
+ { &hf_yppasswd_newpw, {
+ "newpw", "yppasswd.newpw", FT_NONE, 0,
+ NULL, 0, "New passwd entry", HFILL }},
+
+ { &hf_yppasswd_newpw_name, {
+ "name", "yppasswd.newpw.name", FT_STRING, BASE_DEC,
+ NULL, 0, "Username", HFILL }},
+
+ { &hf_yppasswd_newpw_passwd, {
+ "passwd", "yppasswd.newpw.passwd", FT_STRING, BASE_DEC,
+ NULL, 0, "Encrypted passwd", HFILL }},
+
+ { &hf_yppasswd_newpw_uid, {
+ "uid", "yppasswd.newpw.uid", FT_UINT32, BASE_DEC,
+ NULL, 0, "UserID", HFILL }},
+
+ { &hf_yppasswd_newpw_gid, {
+ "gid", "yppasswd.newpw.gid", FT_UINT32, BASE_DEC,
+ NULL, 0, "GroupID", HFILL }},
+
+ { &hf_yppasswd_newpw_gecos, {
+ "gecos", "yppasswd.newpw.gecos", FT_STRING, BASE_DEC,
+ NULL, 0, "In real life name", HFILL }},
+
+ { &hf_yppasswd_newpw_dir, {
+ "dir", "yppasswd.newpw.dir", FT_STRING, BASE_DEC,
+ NULL, 0, "Home Directory", HFILL }},
+
+ { &hf_yppasswd_newpw_shell, {
+ "shell", "yppasswd.newpw.shell", FT_STRING, BASE_DEC,
+ NULL, 0, "Default shell", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_yppasswd,
+ &ett_yppasswd_newpw,
+ };
+
+ proto_yppasswd = proto_register_protocol("Yellow Pages Passwd",
+ "YPPASSWD", "yppasswd");
+ proto_register_field_array(proto_yppasswd, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_yppasswd(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_yppasswd, YPPASSWD_PROGRAM, ett_yppasswd);
+ /* Register the procedure tables */
+ rpc_init_proc_table(YPPASSWD_PROGRAM, 1, yppasswd1_proc, hf_yppasswd_procedure_v1);
+}
+
diff --git a/epan/dissectors/packet-yppasswd.h b/epan/dissectors/packet-yppasswd.h
new file mode 100644
index 0000000000..9e6f666c4c
--- /dev/null
+++ b/epan/dissectors/packet-yppasswd.h
@@ -0,0 +1,32 @@
+/* packet-yppasswd.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_YPPASSWD_H
+#define PACKET_YPPASSWD_H
+
+#define YPPASSWDPROC_NULL 0
+#define YPPASSWDPROC_UPDATE 1
+
+#define YPPASSWD_PROGRAM 100009
+
+#endif
diff --git a/epan/dissectors/packet-ypserv.c b/epan/dissectors/packet-ypserv.c
new file mode 100644
index 0000000000..18aa640384
--- /dev/null
+++ b/epan/dissectors/packet-ypserv.c
@@ -0,0 +1,494 @@
+/* packet-ypserv.c
+ * Routines for ypserv dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-smb.c
+ *
+ * 2001 Ronnie Sahlberg <See AUTHORS for email>
+ * Added all remaining dissectors for this protocol
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-ypserv.h"
+
+static int proto_ypserv = -1;
+static int hf_ypserv_procedure_v1 = -1;
+static int hf_ypserv_procedure_v2 = -1;
+static int hf_ypserv_domain = -1;
+static int hf_ypserv_servesdomain = -1;
+static int hf_ypserv_map = -1;
+static int hf_ypserv_key = -1;
+static int hf_ypserv_peer = -1;
+static int hf_ypserv_more = -1;
+static int hf_ypserv_ordernum = -1;
+static int hf_ypserv_transid = -1;
+static int hf_ypserv_prog = -1;
+static int hf_ypserv_port = -1;
+static int hf_ypserv_value = -1;
+static int hf_ypserv_status = -1;
+static int hf_ypserv_map_parms = -1;
+static int hf_ypserv_xfrstat = -1;
+
+static gint ett_ypserv = -1;
+static gint ett_ypserv_map_parms = -1;
+
+static const value_string ypstat[] =
+{
+ { 1, "YP_TRUE" },
+ { 2, "YP_NOMORE" },
+ { 0, "YP_FALSE" },
+ { -1, "YP_NOMAP" },
+ { -2, "YP_NODOM" },
+ { -3, "YP_NOKEY" },
+ { -4, "YP_BADOP" },
+ { -5, "YP_BADDB" },
+ { -6, "YP_YPERR" },
+ { -7, "YP_BADARGS" },
+ { -8, "YP_VERS" },
+ { 0, NULL },
+};
+
+static const value_string xfrstat[] =
+{
+ { 1, "YPXFR_SUCC" },
+ { 2, "YPXFR_AGE" },
+ { -1, "YPXFR_NOMAP" },
+ { -2, "YPXFR_NODOM" },
+ { -3, "YPXFR_RSRC" },
+ { -4, "YPXFR_RPC" },
+ { -5, "YPXFR_MADDR" },
+ { -6, "YPXFR_YPERR" },
+ { -7, "YPXFR_BADARGS" },
+ { -8, "YPXFR_DBM" },
+ { -9, "YPXFR_FILE" },
+ { -10, "YPXFR_SKEW" },
+ { -11, "YPXFR_CLEAR" },
+ { -12, "YPXFR_FORCE" },
+ { -13, "YPXFR_XFRERR" },
+ { -14, "YPXFR_REFUSED" },
+ { 0, NULL },
+};
+
+static int
+dissect_domain_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ offset = dissect_rpc_string(tvb,tree,hf_ypserv_domain,offset,NULL);
+ }
+
+ return offset;
+}
+
+static int
+dissect_domain_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ proto_tree_add_boolean(tree, hf_ypserv_servesdomain, tvb,
+ offset, 4, tvb_get_ntohl(tvb,offset));
+ }
+
+ offset += 4;
+ return offset;
+}
+
+static int
+dissect_match_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_domain, offset, NULL);
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_map, offset, NULL);
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_key, offset, NULL);
+ }
+
+ return offset;
+}
+
+static int
+dissect_match_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_status, offset);
+
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_value,offset, NULL);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_first_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ /*
+ * XXX - does Sun's "yp.x" lie, and claim that the argument to a
+ * FIRST call is a "ypreq_key" rather than a "ypreq_nokey"?
+ * You presumably need the key for NEXT, as "next" is "next
+ * after some entry", and the key tells you which entry, but
+ * you don't need a key for FIRST, as there's only one entry that
+ * is the first entry.
+ *
+ * The NIS server originally used DBM, which has a "firstkey()"
+ * call, with no argument, and a "nextkey()" argument, with
+ * a key argument. (Heck, it might *still* use DBM.)
+ *
+ * Given that, and given that at least one FIRST call from a Sun
+ * running Solaris 8 (the Sun on which I'm typing this, in fact)
+ * had a "ypreq_nokey" as the argument, I'm assuming that "yp.x"
+ * is buggy.
+ */
+
+ if ( tree )
+ {
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_domain, offset, NULL);
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_map, offset, NULL);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_firstnext_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_status, offset);
+
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_value, offset, NULL);
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_key, offset, NULL);
+ }
+
+ return offset;
+}
+
+
+static int
+dissect_next_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ if ( tree )
+ {
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_domain, offset, NULL);
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_map, offset, NULL);
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_key, offset, NULL);
+ }
+
+ return offset;
+}
+
+static int
+dissect_xfr_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_item *sub_item=NULL;
+ proto_tree *sub_tree=NULL;
+ int start_offset = offset;
+
+ if(tree){
+ sub_item = proto_tree_add_item(tree, hf_ypserv_map_parms, tvb,
+ offset, -1, FALSE);
+ if(sub_item)
+ sub_tree = proto_item_add_subtree(sub_item, ett_ypserv_map_parms);
+ }
+
+ offset = dissect_rpc_string(tvb, sub_tree, hf_ypserv_domain, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, sub_tree, hf_ypserv_map, offset, NULL);
+
+ offset = dissect_rpc_uint32(tvb, sub_tree, hf_ypserv_ordernum, offset);
+
+ offset = dissect_rpc_string(tvb, sub_tree, hf_ypserv_peer, offset, NULL);
+
+ proto_tree_add_item(tree, hf_ypserv_transid, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_prog, offset);
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_port, offset);
+
+ if(sub_item)
+ proto_item_set_len(sub_item, offset - start_offset);
+
+ return offset;
+}
+
+static int
+dissect_xfr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ proto_tree_add_item(tree, hf_ypserv_transid, tvb, offset, 4, FALSE);
+ offset += 4;
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_xfrstat, offset);
+
+ return offset;
+}
+
+static int
+dissect_ypreq_nokey(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_domain, offset, NULL);
+
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_map, offset, NULL);
+
+ return offset;
+}
+
+static int
+dissect_ypresp_all(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ guint32 more;
+
+ for (;;) {
+ more = tvb_get_ntohl(tvb, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_more, offset);
+ if (!more)
+ break;
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_status, offset);
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_value, offset, NULL);
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_key, offset, NULL);
+ }
+
+ return offset;
+}
+
+static int
+dissect_ypresp_master(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_status, offset);
+
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_peer, offset, NULL);
+
+ return offset;
+}
+
+
+static int
+dissect_ypresp_order(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_status, offset);
+
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_ordernum, offset);
+
+ return offset;
+}
+
+
+static int
+dissect_ypresp_maplist(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
+{
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_status, offset);
+ while(tvb_get_ntohl(tvb,offset)){
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_more, offset);
+ offset = dissect_rpc_string(tvb, tree, hf_ypserv_map, offset, NULL);
+
+ }
+ offset = dissect_rpc_uint32(tvb, tree, hf_ypserv_more, offset);
+ return offset;
+}
+
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+
+/* someone please get me a version 1 trace */
+
+static const vsff ypserv1_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { YPPROC_DOMAIN, "DOMAIN",
+ NULL, NULL },
+ { YPPROC_DOMAIN_NONACK, "DOMAIN_NONACK",
+ NULL, NULL },
+ { YPPROC_MATCH, "MATCH",
+ NULL, NULL },
+ { YPPROC_FIRST, "FIRST",
+ NULL, NULL },
+ { YPPROC_NEXT, "NEXT",
+ NULL, NULL },
+ { YPPROC_XFR, "XFR",
+ NULL, NULL },
+ { YPPROC_CLEAR, "CLEAR",
+ NULL, NULL },
+ { YPPROC_ALL, "ALL",
+ NULL, NULL },
+ { YPPROC_MASTER, "MASTER",
+ NULL, NULL },
+ { YPPROC_ORDER, "ORDER",
+ NULL, NULL },
+ { YPPROC_MAPLIST, "MAPLIST",
+ NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+
+static const value_string ypserv1_proc_vals[] = {
+ { YPPROC_DOMAIN, "DOMAIN" },
+ { YPPROC_DOMAIN_NONACK, "DOMAIN_NONACK" },
+ { YPPROC_MATCH, "MATCH" },
+ { YPPROC_FIRST, "FIRST" },
+ { YPPROC_NEXT, "NEXT" },
+ { YPPROC_XFR, "XFR" },
+ { YPPROC_CLEAR, "CLEAR" },
+ { YPPROC_ALL, "ALL" },
+ { YPPROC_MASTER, "MASTER" },
+ { YPPROC_ORDER, "ORDER" },
+ { YPPROC_MAPLIST, "MAPLIST" },
+ { 0, NULL }
+};
+
+/* end of YPServ version 1 */
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+
+static const vsff ypserv2_proc[] = {
+ { 0, "NULL", NULL, NULL },
+ { YPPROC_DOMAIN, "DOMAIN",
+ dissect_domain_call, dissect_domain_reply },
+ { YPPROC_DOMAIN_NONACK, "DOMAIN_NONACK",
+ dissect_domain_call, dissect_domain_reply },
+ { YPPROC_MATCH, "MATCH",
+ dissect_match_call, dissect_match_reply },
+ { YPPROC_FIRST, "FIRST",
+ dissect_first_call, dissect_firstnext_reply },
+ { YPPROC_NEXT, "NEXT",
+ dissect_next_call, dissect_firstnext_reply },
+ { YPPROC_XFR, "XFR",
+ dissect_xfr_call, dissect_xfr_reply },
+ { YPPROC_CLEAR, "CLEAR",
+ NULL, NULL },
+ { YPPROC_ALL, "ALL",
+ dissect_ypreq_nokey, dissect_ypresp_all },
+ { YPPROC_MASTER, "MASTER",
+ dissect_ypreq_nokey, dissect_ypresp_master },
+ { YPPROC_ORDER, "ORDER",
+ dissect_ypreq_nokey, dissect_ypresp_order },
+ { YPPROC_MAPLIST, "MAPLIST",
+ dissect_domain_call, dissect_ypresp_maplist },
+ { 0, NULL, NULL, NULL }
+};
+
+static const value_string ypserv2_proc_vals[] = {
+ { YPPROC_DOMAIN, "DOMAIN" },
+ { YPPROC_DOMAIN_NONACK, "DOMAIN_NONACK" },
+ { YPPROC_MATCH, "MATCH" },
+ { YPPROC_FIRST, "FIRST" },
+ { YPPROC_NEXT, "NEXT" },
+ { YPPROC_XFR, "XFR" },
+ { YPPROC_CLEAR, "CLEAR" },
+ { YPPROC_ALL, "ALL" },
+ { YPPROC_MASTER, "MASTER" },
+ { YPPROC_ORDER, "ORDER" },
+ { YPPROC_MAPLIST, "MAPLIST" },
+ { 0, NULL }
+};
+
+/* end of YPServ version 2 */
+
+
+void
+proto_register_ypserv(void)
+{
+ /*static struct true_false_string okfailed = { "Ok", "Failed" };*/
+ static struct true_false_string yesno = { "Yes", "No" };
+
+ static hf_register_info hf[] = {
+ { &hf_ypserv_procedure_v1, {
+ "V1 Procedure", "ypserv.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(ypserv1_proc_vals), 0, "V1 Procedure", HFILL }},
+ { &hf_ypserv_procedure_v2, {
+ "V2 Procedure", "ypserv.procedure_v2", FT_UINT32, BASE_DEC,
+ VALS(ypserv2_proc_vals), 0, "V2 Procedure", HFILL }},
+ { &hf_ypserv_domain, {
+ "Domain", "ypserv.domain", FT_STRING, BASE_DEC,
+ NULL, 0, "Domain", HFILL }},
+ { &hf_ypserv_servesdomain, {
+ "Serves Domain", "ypserv.servesdomain", FT_BOOLEAN, BASE_DEC,
+ &yesno, 0, "Serves Domain", HFILL }},
+ { &hf_ypserv_map, {
+ "Map Name", "ypserv.map", FT_STRING, BASE_DEC,
+ NULL, 0, "Map Name", HFILL }},
+ { &hf_ypserv_peer, {
+ "Peer Name", "ypserv.peer", FT_STRING, BASE_DEC,
+ NULL, 0, "Peer Name", HFILL }},
+ { &hf_ypserv_more, {
+ "More", "ypserv.more", FT_BOOLEAN, BASE_NONE,
+ &yesno, 0, "More", HFILL }},
+ { &hf_ypserv_ordernum, {
+ "Order Number", "ypserv.ordernum", FT_UINT32, BASE_DEC,
+ NULL, 0, "Order Number for XFR", HFILL }},
+ { &hf_ypserv_transid, {
+ "Host Transport ID", "ypserv.transid", FT_IPv4, BASE_DEC,
+ NULL, 0, "Host Transport ID to use for XFR Callback", HFILL }},
+ { &hf_ypserv_prog, {
+ "Program Number", "ypserv.prog", FT_UINT32, BASE_DEC,
+ NULL, 0, "Program Number to use for XFR Callback", HFILL }},
+ { &hf_ypserv_port, {
+ "Port", "ypserv.port", FT_UINT32, BASE_DEC,
+ NULL, 0, "Port to use for XFR Callback", HFILL }},
+ { &hf_ypserv_key, {
+ "Key", "ypserv.key", FT_STRING, BASE_DEC,
+ NULL, 0, "Key", HFILL }},
+ { &hf_ypserv_value, {
+ "Value", "ypserv.value", FT_STRING, BASE_DEC,
+ NULL, 0, "Value", HFILL }},
+ { &hf_ypserv_status, {
+ "Status", "ypserv.status", FT_INT32, BASE_DEC,
+ VALS(ypstat) , 0, "Status", HFILL }},
+ { &hf_ypserv_map_parms, {
+ "YP Map Parameters", "ypserv.map_parms", FT_NONE, BASE_DEC,
+ NULL, 0, "YP Map Parameters", HFILL }},
+ { &hf_ypserv_xfrstat, {
+ "Xfrstat", "ypserv.xfrstat", FT_INT32, BASE_DEC,
+ VALS(xfrstat), 0, "Xfrstat", HFILL }},
+ };
+ static gint *ett[] = {
+ &ett_ypserv,
+ &ett_ypserv_map_parms,
+ };
+
+ proto_ypserv = proto_register_protocol("Yellow Pages Service",
+ "YPSERV", "ypserv");
+ proto_register_field_array(proto_ypserv, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ypserv(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_ypserv, YPSERV_PROGRAM, ett_ypserv);
+ /* Register the procedure tables */
+ rpc_init_proc_table(YPSERV_PROGRAM, 1, ypserv1_proc,
+ hf_ypserv_procedure_v1);
+ rpc_init_proc_table(YPSERV_PROGRAM, 2, ypserv2_proc,
+ hf_ypserv_procedure_v2);
+}
diff --git a/epan/dissectors/packet-ypserv.h b/epan/dissectors/packet-ypserv.h
new file mode 100644
index 0000000000..b528bf6493
--- /dev/null
+++ b/epan/dissectors/packet-ypserv.h
@@ -0,0 +1,43 @@
+/* packet-ypserv.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_YPSERV_H
+#define PACKET_YPSERV_H
+
+#define YPSERV_PROGRAM 100004
+
+#define YPPROC_NULL 0
+#define YPPROC_DOMAIN 1
+#define YPPROC_DOMAIN_NONACK 2
+#define YPPROC_MATCH 3
+#define YPPROC_FIRST 4
+#define YPPROC_NEXT 5
+#define YPPROC_XFR 6
+#define YPPROC_CLEAR 7
+#define YPPROC_ALL 8
+#define YPPROC_MASTER 9
+#define YPPROC_ORDER 10
+#define YPPROC_MAPLIST 11
+
+#endif
diff --git a/epan/dissectors/packet-ypxfr.c b/epan/dissectors/packet-ypxfr.c
new file mode 100644
index 0000000000..706e68e636
--- /dev/null
+++ b/epan/dissectors/packet-ypxfr.c
@@ -0,0 +1,81 @@
+/* packet-ypxfr.c
+ * Routines for ypxfr dissection
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-smb.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+
+#include "packet-rpc.h"
+#include "packet-ypxfr.h"
+
+static int proto_ypxfr = -1;
+static int hf_ypxfr_procedure_v1 = -1;
+
+static gint ett_ypxfr = -1;
+
+/* proc number, "proc name", dissect_request, dissect_reply */
+/* NULL as function pointer means: type of arguments is "void". */
+static const vsff ypxfr1_proc[] = {
+ { YPXFRPROC_NULL, "NULL", NULL, NULL },
+ { YPXFRPROC_GETMAP, "GETMAP", NULL, NULL },
+ { 0, NULL, NULL, NULL }
+};
+static const value_string ypxfr1_proc_vals[] = {
+ { YPXFRPROC_NULL, "NULL" },
+ { YPXFRPROC_GETMAP, "GETMAP" },
+ { 0, NULL }
+};
+/* end of YPXFR version 1 */
+
+void
+proto_register_ypxfr(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_ypxfr_procedure_v1, {
+ "V1 Procedure", "ypxfr.procedure_v1", FT_UINT32, BASE_DEC,
+ VALS(ypxfr1_proc_vals), 0, "V1 Procedure", HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_ypxfr
+ };
+
+ proto_ypxfr = proto_register_protocol("Yellow Pages Transfer",
+ "YPXFR", "ypxfr");
+ proto_register_field_array(proto_ypxfr, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_ypxfr(void)
+{
+ /* Register the protocol as RPC */
+ rpc_init_prog(proto_ypxfr, YPXFR_PROGRAM, ett_ypxfr);
+ /* Register the procedure tables */
+ rpc_init_proc_table(YPXFR_PROGRAM, 1, ypxfr1_proc, hf_ypxfr_procedure_v1);
+}
diff --git a/epan/dissectors/packet-ypxfr.h b/epan/dissectors/packet-ypxfr.h
new file mode 100644
index 0000000000..9a346806fa
--- /dev/null
+++ b/epan/dissectors/packet-ypxfr.h
@@ -0,0 +1,33 @@
+/* packet-ypxfr.h
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * Copyright 1998 Gerald Combs
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_YPXFR_H
+#define PACKET_YPXFR_H
+
+#define YPXFRPROC_NULL 0
+#define YPXFRPROC_GETMAP 1
+
+#define YPXFR_PROGRAM 100069
+
+#endif
diff --git a/epan/dissectors/packet-zebra.c b/epan/dissectors/packet-zebra.c
new file mode 100644
index 0000000000..5e5bfaef2b
--- /dev/null
+++ b/epan/dissectors/packet-zebra.c
@@ -0,0 +1,617 @@
+/* packet-zebra.c
+ * Routines for zebra packet disassembly
+ *
+ * Jochen Friedrich <jochen@scram.de>
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+
+static int proto_zebra = -1;
+static int hf_zebra_len = -1;
+static int hf_zebra_command = -1;
+static int hf_zebra_request = -1;
+static int hf_zebra_interface = -1;
+static int hf_zebra_index = -1;
+static int hf_zebra_indexnum = -1;
+static int hf_zebra_type = -1;
+static int hf_zebra_intflags = -1;
+static int hf_zebra_rtflags = -1;
+static int hf_zebra_distance = -1;
+static int hf_zebra_metric = -1;
+static int hf_zebra_mtu = -1;
+static int hf_zebra_bandwidth = -1;
+static int hf_zebra_family = -1;
+static int hf_zebra_message = -1;
+static int hf_zebra_msg_nexthop = -1;
+static int hf_zebra_msg_index = -1;
+static int hf_zebra_msg_distance = -1;
+static int hf_zebra_msg_metric = -1;
+static int hf_zebra_nexthopnum = -1;
+static int hf_zebra_nexthop4 = -1;
+static int hf_zebra_nexthop6 = -1;
+static int hf_zebra_dest4 = -1;
+static int hf_zebra_dest6 = -1;
+static int hf_zebra_prefixlen = -1;
+static int hf_zebra_prefix4 = -1;
+static int hf_zebra_prefix6 = -1;
+
+static gint ett_zebra = -1;
+static gint ett_zebra_request = -1;
+static gint ett_message = -1;
+
+#define TCP_PORT_ZEBRA 2600
+
+/* Zebra message types. */
+#define ZEBRA_INTERFACE_ADD 1
+#define ZEBRA_INTERFACE_DELETE 2
+#define ZEBRA_INTERFACE_ADDRESS_ADD 3
+#define ZEBRA_INTERFACE_ADDRESS_DELETE 4
+#define ZEBRA_INTERFACE_UP 5
+#define ZEBRA_INTERFACE_DOWN 6
+#define ZEBRA_IPV4_ROUTE_ADD 7
+#define ZEBRA_IPV4_ROUTE_DELETE 8
+#define ZEBRA_IPV6_ROUTE_ADD 9
+#define ZEBRA_IPV6_ROUTE_DELETE 10
+#define ZEBRA_REDISTRIBUTE_ADD 11
+#define ZEBRA_REDISTRIBUTE_DELETE 12
+#define ZEBRA_REDISTRIBUTE_DEFAULT_ADD 13
+#define ZEBRA_REDISTRIBUTE_DEFAULT_DELETE 14
+#define ZEBRA_IPV4_NEXTHOP_LOOKUP 15
+#define ZEBRA_IPV6_NEXTHOP_LOOKUP 16
+
+static const value_string messages[] = {
+ { ZEBRA_INTERFACE_ADD, "Add Interface" },
+ { ZEBRA_INTERFACE_DELETE, "Delete Interface" },
+ { ZEBRA_INTERFACE_ADDRESS_ADD, "Add Interface Address" },
+ { ZEBRA_INTERFACE_ADDRESS_DELETE, "Delete Interface Address" },
+ { ZEBRA_INTERFACE_UP, "Interface Up" },
+ { ZEBRA_INTERFACE_DOWN, "Interface Down" },
+ { ZEBRA_IPV4_ROUTE_ADD, "Add IPv4 Route" },
+ { ZEBRA_IPV4_ROUTE_DELETE, "Delete IPv4 Route" },
+ { ZEBRA_IPV6_ROUTE_ADD, "Add IPv6 Route" },
+ { ZEBRA_IPV6_ROUTE_DELETE, "Delete IPv6 Route" },
+ { ZEBRA_REDISTRIBUTE_ADD, "Add Redistribute" },
+ { ZEBRA_REDISTRIBUTE_DELETE, "Delete Redistribute" },
+ { ZEBRA_REDISTRIBUTE_DEFAULT_ADD, "Add Default Redistribute" },
+ { ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, "Delete Default Redistribute" },
+ { ZEBRA_IPV4_NEXTHOP_LOOKUP, "IPv4 Nexthop Lookup" },
+ { ZEBRA_IPV6_NEXTHOP_LOOKUP, "IPv6 Nexthop Lookup" },
+ { 0, NULL },
+};
+
+/* Zebra route's types. */
+#define ZEBRA_ROUTE_SYSTEM 0
+#define ZEBRA_ROUTE_KERNEL 1
+#define ZEBRA_ROUTE_CONNECT 2
+#define ZEBRA_ROUTE_STATIC 3
+#define ZEBRA_ROUTE_RIP 4
+#define ZEBRA_ROUTE_RIPNG 5
+#define ZEBRA_ROUTE_OSPF 6
+#define ZEBRA_ROUTE_OSPF6 7
+#define ZEBRA_ROUTE_BGP 8
+
+static const value_string routes[] = {
+ { ZEBRA_ROUTE_SYSTEM, "System Route" },
+ { ZEBRA_ROUTE_KERNEL, "Kernel Route" },
+ { ZEBRA_ROUTE_CONNECT, "Connected Route" },
+ { ZEBRA_ROUTE_STATIC, "Static Route" },
+ { ZEBRA_ROUTE_RIP, "RIP Route" },
+ { ZEBRA_ROUTE_RIPNG, "RIPnG Route" },
+ { ZEBRA_ROUTE_OSPF, "OSPF Route" },
+ { ZEBRA_ROUTE_OSPF6, "OSPF6 Route" },
+ { ZEBRA_ROUTE_BGP, "BGP Route" },
+ { 0, NULL },
+};
+
+/* Zebra's family types. */
+#define ZEBRA_FAMILY_IPV4 1
+#define ZEBRA_FAMILY_IPV6 2
+
+static const value_string families[] = {
+ { ZEBRA_FAMILY_IPV4, "IPv4" },
+ { ZEBRA_FAMILY_IPV6, "IPv6" },
+ { 0, NULL },
+};
+
+/* Zebra message flags */
+#define ZEBRA_FLAG_INTERNAL 0x01
+#define ZEBRA_FLAG_SELFROUTE 0x02
+#define ZEBRA_FLAG_BLACKHOLE 0x04
+
+/* Zebra API message flag. */
+#define ZEBRA_ZAPI_MESSAGE_NEXTHOP 0x01
+#define ZEBRA_ZAPI_MESSAGE_IFINDEX 0x02
+#define ZEBRA_ZAPI_MESSAGE_DISTANCE 0x04
+#define ZEBRA_ZAPI_MESSAGE_METRIC 0x08
+
+#define INTERFACE_NAMSIZ 20
+
+#define PSIZE(a) (((a) + 7) / (8))
+
+static void
+dissect_zebra_request(proto_tree *tree, gboolean request, tvbuff_t *tvb,
+ int offset, guint16 len, guint8 command)
+{
+ guint32 prefix4;
+ guint16 i;
+ guint8 buffer6[16], prefixlen, message;
+ proto_item *ti;
+ proto_tree *msg_tree;
+
+ proto_tree_add_uint(tree, hf_zebra_len, tvb, offset, 2, len);
+ offset += 2;
+ proto_tree_add_uint(tree, hf_zebra_command, tvb, offset, 1,
+ command);
+ offset += 1;
+ switch(command) {
+ case ZEBRA_INTERFACE_ADD:
+ case ZEBRA_INTERFACE_UP:
+ case ZEBRA_INTERFACE_DOWN:
+ if (request) break;
+ /* Request just subscribes to messages */
+
+ proto_tree_add_item(tree, hf_zebra_interface,
+ tvb, offset, INTERFACE_NAMSIZ, FALSE);
+ offset += INTERFACE_NAMSIZ;
+
+ proto_tree_add_item(tree, hf_zebra_index, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_zebra_intflags, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_zebra_metric, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_zebra_mtu, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_zebra_bandwidth, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ break;
+ case ZEBRA_INTERFACE_DELETE:
+ proto_tree_add_item(tree, hf_zebra_interface,
+ tvb, offset, INTERFACE_NAMSIZ, FALSE);
+ offset += INTERFACE_NAMSIZ;
+
+ proto_tree_add_item(tree, hf_zebra_index, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ break;
+ case ZEBRA_INTERFACE_ADDRESS_ADD:
+ case ZEBRA_INTERFACE_ADDRESS_DELETE:
+ proto_tree_add_item(tree, hf_zebra_index, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_zebra_family, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ /* XXX - switch on the address family here, instead? */
+ if (len == 17) { /* IPv4 */
+ proto_tree_add_item(tree, hf_zebra_prefix4,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ else if (len == 41) { /* IPv6 */
+ proto_tree_add_item(tree, hf_zebra_prefix6,
+ tvb, offset, 16, FALSE);
+ offset += 16;
+ }
+ else break;
+
+ proto_tree_add_item(tree, hf_zebra_prefixlen, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ if (len == 17) { /* IPv4 */
+ proto_tree_add_item(tree, hf_zebra_dest4,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ else if (len == 41) { /* IPv6 */
+ proto_tree_add_item(tree, hf_zebra_dest6,
+ tvb, offset, 16, FALSE);
+ offset += 16;
+ }
+ break;
+
+ case ZEBRA_IPV4_ROUTE_ADD:
+ case ZEBRA_IPV4_ROUTE_DELETE:
+ proto_tree_add_item(tree, hf_zebra_type, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_zebra_rtflags, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ message = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_uint(tree, hf_zebra_message, tvb,
+ offset, 1, message);
+ msg_tree = proto_item_add_subtree(ti, ett_message);
+ proto_tree_add_boolean(msg_tree, hf_zebra_msg_nexthop,
+ tvb, offset, 1, message);
+ proto_tree_add_boolean(msg_tree, hf_zebra_msg_index,
+ tvb, offset, 1, message);
+ proto_tree_add_boolean(msg_tree, hf_zebra_msg_distance,
+ tvb, offset, 1, message);
+ proto_tree_add_boolean(msg_tree, hf_zebra_msg_metric,
+ tvb, offset, 1, message);
+ offset += 1;
+
+ prefixlen = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_zebra_prefixlen, tvb,
+ offset, 1, prefixlen);
+ offset += 1;
+
+ prefix4 = 0;
+ tvb_memcpy(tvb, (guint8 *)&prefix4, offset,
+ MIN((unsigned) PSIZE(prefixlen), sizeof prefix4));
+ proto_tree_add_ipv4(tree, hf_zebra_prefix4,
+ tvb, offset, PSIZE(prefixlen), prefix4);
+ offset += PSIZE(prefixlen);
+
+ if (message & ZEBRA_ZAPI_MESSAGE_NEXTHOP) {
+ i = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_zebra_nexthopnum,
+ tvb, offset, 1, i);
+ offset += 1;
+
+ if (i>len) break; /* Sanity */
+
+ while (i--) {
+ proto_tree_add_item(tree,
+ hf_zebra_nexthop4, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ }
+ }
+ if (message & ZEBRA_ZAPI_MESSAGE_IFINDEX) {
+ i = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_zebra_indexnum,
+ tvb, offset, 1, i);
+ offset += 1;
+
+ if (i>len) break; /* Sanity */
+
+ while (i--) {
+ proto_tree_add_item(tree,
+ hf_zebra_index, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ }
+ }
+ if (message & ZEBRA_ZAPI_MESSAGE_DISTANCE) {
+ proto_tree_add_item(tree, hf_zebra_distance,
+ tvb, offset, 1, FALSE);
+ offset += 1;
+ }
+ if (message & ZEBRA_ZAPI_MESSAGE_METRIC) {
+ proto_tree_add_item(tree, hf_zebra_metric,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ break;
+ case ZEBRA_IPV6_ROUTE_ADD:
+ case ZEBRA_IPV6_ROUTE_DELETE:
+ proto_tree_add_item(tree, hf_zebra_type, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tree, hf_zebra_rtflags, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+
+ message = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_uint(tree, hf_zebra_message, tvb,
+ offset, 1, message);
+ msg_tree = proto_item_add_subtree(ti, ett_message);
+ proto_tree_add_boolean(msg_tree, hf_zebra_msg_nexthop,
+ tvb, offset, 1, message);
+ proto_tree_add_boolean(msg_tree, hf_zebra_msg_index,
+ tvb, offset, 1, message);
+ proto_tree_add_boolean(msg_tree, hf_zebra_msg_distance,
+ tvb, offset, 1, message);
+ proto_tree_add_boolean(msg_tree, hf_zebra_msg_metric,
+ tvb, offset, 1, message);
+ offset += 1;
+
+ prefixlen = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_zebra_prefixlen, tvb,
+ offset, 1, prefixlen);
+ offset += 1;
+
+ memset(buffer6, '\0', sizeof buffer6);
+ tvb_memcpy(tvb, buffer6, offset,
+ MIN((unsigned) PSIZE(prefixlen), sizeof buffer6));
+ proto_tree_add_ipv6(tree, hf_zebra_prefix6,
+ tvb, offset, PSIZE(prefixlen), buffer6);
+ offset += PSIZE(prefixlen);
+
+ if (message & ZEBRA_ZAPI_MESSAGE_NEXTHOP) {
+ i = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_zebra_nexthopnum,
+ tvb, offset, 1, i);
+ offset += 1;
+
+ if (i>len) break; /* Sanity */
+
+ while (i--) {
+ proto_tree_add_item(tree,
+ hf_zebra_nexthop6, tvb,
+ offset, 16, FALSE);
+ offset += 16;
+ }
+ }
+ if (message & ZEBRA_ZAPI_MESSAGE_IFINDEX) {
+ i = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_zebra_indexnum,
+ tvb, offset, 1, i);
+ offset += 1;
+
+ if (i>len) break; /* Sanity */
+
+ while (i--) {
+ proto_tree_add_item(tree,
+ hf_zebra_index, tvb,
+ offset, 4, FALSE);
+ offset += 4;
+ }
+ }
+ if (message & ZEBRA_ZAPI_MESSAGE_DISTANCE) {
+ proto_tree_add_item(tree, hf_zebra_distance,
+ tvb, offset, 1, FALSE);
+ offset += 1;
+ }
+ if (message & ZEBRA_ZAPI_MESSAGE_METRIC) {
+ proto_tree_add_item(tree, hf_zebra_metric,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ }
+ break;
+ case ZEBRA_REDISTRIBUTE_ADD:
+ case ZEBRA_REDISTRIBUTE_DELETE:
+ proto_tree_add_item(tree, hf_zebra_type, tvb,
+ offset, 1, FALSE);
+ offset += 1;
+ break;
+ case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
+ case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
+ break;
+ case ZEBRA_IPV4_NEXTHOP_LOOKUP:
+ proto_tree_add_item(tree, hf_zebra_nexthop4,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_zebra_metric,
+ tvb, offset, 4, FALSE);
+ offset += 4;
+ break;
+ case ZEBRA_IPV6_NEXTHOP_LOOKUP:
+ /* Not yet implemeted in ZEBRA */
+ break;
+ }
+}
+
+static void
+dissect_zebra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *zebra_tree;
+ gboolean request;
+ int left, offset;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZEBRA");
+
+ request = (pinfo->destport == pinfo->match_port);
+ left = tvb_reported_length(tvb);
+ offset = 0;
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ request? "ZEBRA Request" : "ZEBRA Reply");
+ }
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_zebra, tvb, offset, -1,
+ FALSE);
+ zebra_tree = proto_item_add_subtree(ti, ett_zebra);
+ proto_tree_add_boolean_hidden(zebra_tree, hf_zebra_request,
+ tvb, offset, 0, request);
+
+ for (;;) {
+ guint8 command;
+ guint16 len;
+ proto_tree *zebra_request_tree;
+
+ if (left < 3) break;
+
+ len = tvb_get_ntohs(tvb, offset);
+ if (len < 3) break;
+
+ command = tvb_get_guint8(tvb, offset+2);
+
+ ti = proto_tree_add_uint(zebra_tree,
+ hf_zebra_command, tvb, offset, len,
+ command);
+ zebra_request_tree = proto_item_add_subtree(ti,
+ ett_zebra_request);
+ dissect_zebra_request(zebra_request_tree, request, tvb,
+ offset, len, command);
+
+ offset += len;
+ left -= len;
+ }
+ }
+}
+
+void
+proto_register_zebra(void)
+{
+
+ static hf_register_info hf[] = {
+ { &hf_zebra_len,
+ { "Length", "zebra.len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of ZEBRA request", HFILL }},
+ { &hf_zebra_request,
+ { "Request", "zebra.request",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "TRUE if ZEBRA request", HFILL }},
+ { &hf_zebra_command,
+ { "Command", "zebra.command",
+ FT_UINT8, BASE_DEC, VALS(messages), 0x0,
+ "ZEBRA command", HFILL }},
+ { &hf_zebra_interface,
+ { "Interface", "zebra.interface",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "Interface name of ZEBRA request", HFILL }},
+ { &hf_zebra_index,
+ { "Index", "zebra.index",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Index of interface", HFILL }},
+ { &hf_zebra_indexnum,
+ { "Index Number", "zebra.indexnum",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of indices for route", HFILL }},
+ { &hf_zebra_intflags,
+ { "Flags", "zebra.intflags",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Flags of interface", HFILL }},
+ { &hf_zebra_rtflags,
+ { "Flags", "zebra.rtflags",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Flags of route", HFILL }},
+ { &hf_zebra_message,
+ { "Message", "zebra.message",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Message type of route", HFILL }},
+ { &hf_zebra_msg_nexthop,
+ { "Message Nexthop", "zebra.message.nexthop",
+ FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_NEXTHOP,
+ "Message contains nexthop", HFILL }},
+ { &hf_zebra_msg_index,
+ { "Message Index", "zebra.message.index",
+ FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_IFINDEX,
+ "Message contains index", HFILL }},
+ { &hf_zebra_msg_distance,
+ { "Message Distance", "zebra.message.distance",
+ FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_DISTANCE,
+ "Message contains distance", HFILL }},
+ { &hf_zebra_msg_metric,
+ { "Message Metric", "zebra.message.metric",
+ FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_METRIC,
+ "Message contains metric", HFILL }},
+ { &hf_zebra_type,
+ { "Type", "zebra.type",
+ FT_UINT8, BASE_DEC, VALS(routes), 0x0,
+ "Type of route", HFILL }},
+ { &hf_zebra_distance,
+ { "Distance", "zebra.distance",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Distance of route", HFILL }},
+ { &hf_zebra_metric,
+ { "Metric", "zebra.metric",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Metric of interface or route", HFILL }},
+ { &hf_zebra_mtu,
+ { "MTU", "zebra.mtu",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "MTU of interface", HFILL }},
+ { &hf_zebra_bandwidth,
+ { "Bandwidth", "zebra.bandwidth",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Bandwidth of interface", HFILL }},
+ { &hf_zebra_family,
+ { "Family", "zebra.family",
+ FT_UINT32, BASE_DEC, VALS(families), 0x0,
+ "Family of IP address", HFILL }},
+ { &hf_zebra_dest4,
+ { "Destination", "zebra.dest4",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Destination IPv4 field", HFILL }},
+ { &hf_zebra_dest6,
+ { "Destination", "zebra.dest6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Destination IPv6 field", HFILL }},
+ { &hf_zebra_nexthopnum,
+ { "Nexthop Number", "zebra.nexthopnum",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Number of nexthops in route", HFILL }},
+ { &hf_zebra_nexthop4,
+ { "Nexthop", "zebra.nexthop4",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Nethop IPv4 field of route", HFILL }},
+ { &hf_zebra_nexthop6,
+ { "Nexthop", "zebra.nexthop6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Nethop IPv6 field of route", HFILL }},
+ { &hf_zebra_prefixlen,
+ { "Prefix length", "zebra.prefixlen",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "Prefix length", HFILL }},
+ { &hf_zebra_prefix4,
+ { "Prefix", "zebra.prefix4",
+ FT_IPv4, BASE_NONE, NULL, 0x0,
+ "Prefix IPv4", HFILL }},
+ { &hf_zebra_prefix6,
+ { "Prefix", "zebra.prefix6",
+ FT_IPv6, BASE_NONE, NULL, 0x0,
+ "Prefix IPv6", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_zebra,
+ &ett_zebra_request,
+ &ett_message,
+ };
+
+ proto_zebra = proto_register_protocol("Zebra Protocol", "ZEBRA", "zebra");
+ proto_register_field_array(proto_zebra, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_zebra(void)
+{
+ dissector_handle_t zebra_handle;
+
+ zebra_handle = create_dissector_handle(dissect_zebra, proto_zebra);
+ dissector_add("tcp.port", TCP_PORT_ZEBRA, zebra_handle);
+}
diff --git a/epan/dissectors/process-x11-fields.pl b/epan/dissectors/process-x11-fields.pl
new file mode 100644
index 0000000000..057f9b44b7
--- /dev/null
+++ b/epan/dissectors/process-x11-fields.pl
@@ -0,0 +1,131 @@
+#!/usr/bin/perl
+#
+# Script to convert "x11-fields" file, listing fields for
+# X11 dissector, into header files declaring field-index
+# values and field definitions for those fields.
+#
+# Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
+#
+# $Id$
+#
+# Ethereal - Network traffic analyzer
+# By Gerald Combs <gerald@ethereal.com>
+# Copyright 1998 Gerald Combs
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+open(DECL, ">x11-declarations.h") || die;
+open(REG, ">x11-register-info.h") || die;
+
+$comment = "/* This file is generated by $0, do not edit. */\n\n";
+print DECL $comment;
+print REG $comment;
+
+$prefix = '';
+$subfieldStringLength = 0;
+
+while(<>) {
+ s/#.*$//go;
+ next if /^\s*$/o;
+ s/^(\s*)//o;
+ $subfield = $1;
+
+ if (length $subfield != $subfieldStringLength) {
+ if (!length $subfield) {
+ $prefix = '';
+ } elsif (length $subfield > $subfieldStringLength) {
+ $prefix .= "$lastAbbrev.";
+ } else {
+ $prefix =~ s/^(.*)\.[^\.]+\.$/$1./o;
+ }
+ $subfieldStringLength = length $subfield;
+ }
+
+ @fields = split /\s+/o ;
+ if ($fields[0] eq '#') {
+ #
+ # If the line begins with "#", treat it as a comment, by
+ # ignoring it.
+ #
+ # (We don't support comments at the end of a line; that would
+ # require some more pain in our simple parser.)
+ #
+ next;
+ }
+ $abbrev = shift @fields;
+ $type = shift @fields;
+ $lastAbbrev = $abbrev;
+
+ $field = $prefix.$abbrev;
+
+ if ($fields[0] =~ /^\d+$/o) {
+ #
+ # This is presumably a Boolean bitfield, and this is the number
+ # of bits in the parent field.
+ #
+ $fieldDisplay = shift @fields;
+ } else {
+ #
+ # The next token is the base for the field.
+ #
+ $fieldDisplay = "BASE_".shift @fields;
+ }
+
+ if ($fields[0] eq 'VALS') {
+ #
+ # It's an enumerated field, with the value_string table having a
+ # name based on the field's name.
+ #
+ shift @fields;
+ $fieldStrings = "VALS(${abbrev}_vals)";
+ $fieldStrings =~ s/-/_/go;
+ } elsif ($fields[0] =~ /^VALS\(/o) {
+ #
+ # It's an enumerated field, with a specified name for the
+ # value_string table.
+ #
+ $fieldStrings = shift @fields;
+ $fieldStrings =~ s/\)/_vals\)/o;
+ } else {
+ #
+ # It's not an enumerated field.
+ #
+ $fieldStrings = 'NULL';
+ }
+
+ if ($fields[0] =~ /^0x/) {
+ #
+ # The next token looks like a bitmask for a bitfield.
+ #
+ $mask = shift @fields;
+ } else {
+ $mask = 0;
+ }
+
+ $rest = join(' ', @fields);
+ $longName = uc $name;
+ $longName = $rest if ($rest);
+
+ $variable = $field;
+ $variable =~ s/-/_/go;
+ $variable =~ s/\./_/go;
+
+ print DECL "static int hf_x11_$variable = -1;\n";
+
+ print REG <<END;
+{ &hf_x11_$variable, { "$abbrev", "x11.$field", FT_$type, $fieldDisplay, $fieldStrings, $mask, "$longName", HFILL }},
+END
+}
diff --git a/epan/dissectors/x11-fields b/epan/dissectors/x11-fields
new file mode 100644
index 0000000000..51625d953e
--- /dev/null
+++ b/epan/dissectors/x11-fields
@@ -0,0 +1,520 @@
+#
+# Fields for X11 dissector.
+#
+# Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
+#
+# $Id$
+#
+# Ethereal - Network traffic analyzer
+# By Gerald Combs <gerald@ethereal.com>
+# Copyright 1998 Gerald Combs
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+above-sibling UINT32 HEX
+acceleration-denominator INT16 DEC
+acceleration-numerator INT16 DEC
+access-mode UINT8 DEC VALS
+address BYTES NONE
+ip-address IPv4 NONE
+address-length UINT16 DEC
+alloc UINT8 DEC VALS
+allow-events-mode UINT8 DEC VALS
+allow-exposures UINT8 DEC VALS(yes_no_default)
+arcs NONE NONE
+
+arc NONE NONE
+ x INT16 DEC
+ y INT16 DEC
+ width UINT16 DEC
+ height UINT16 DEC
+ angle1 INT16 DEC
+ angle2 INT16 DEC
+
+arc-mode UINT8 DEC VALS Tell us if we're drawing an arc or a pie
+atom UINT32 HEX
+authorization-protocol-name-length UINT16 DEC
+authorization-protocol-name STRING HEX
+authorization-protocol-data-length UINT16 DEC
+authorization-protocol-data STRING HEX
+auto-repeat-mode UINT8 DEC VALS
+
+bitmap-format-bit-order UINT8 HEX VALS(image_byte_order)
+bitmap-format-scanline-pad UINT8 DEC bitmap format scanline-pad
+bitmap-format-scanline-unit UINT8 DEC bitmap format scanline unit
+bytes-after UINT32 DEC bytes after
+back-blue UINT16 DEC Background blue value for a cursor
+back-green UINT16 DEC Background green value for a cursor
+back-red UINT16 DEC Background red value for a cursor
+background UINT32 HEX Background color
+background-pixel UINT32 HEX Background color for a window
+background-pixmap UINT32 HEX VALS Background pixmap for a window
+backing-pixel UINT32 HEX
+backing-planes UINT32 HEX
+backing-store UINT8 DEC VALS
+bell-duration INT16 DEC
+bell-percent INT8 DEC
+bell-pitch INT16 DEC
+bit-gravity UINT8 DEC VALS(gravity)
+bit-plane UINT32 HEX
+blue UINT16 DEC
+blues UINT16 DEC
+border-pixel UINT32 HEX
+border-pixmap UINT32 HEX VALS
+border-width UINT16 DEC
+button UINT8 DEC VALS
+byte-order UINT8 HEX VALS
+
+childwindow UINT32 HEX childwindow
+cap-style UINT8 DEC VALS
+change-host-mode UINT8 DEC VALS(insert_delete)
+cid UINT32 HEX
+class UINT8 DEC VALS
+clip-mask UINT32 HEX VALS(zero_is_none)
+clip-x-origin INT16 DEC
+clip-y-origin INT16 DEC
+close-down-mode UINT8 DEC VALS
+cmap UINT32 HEX
+colormap UINT32 HEX
+colormap-state UINT8 DEC VALS
+color-items NONE NONE
+
+coloritem NONE NONE
+ pixel UINT32 HEX
+ red UINT16 DEC
+ green UINT16 DEC
+ blue UINT16 DEC
+ flags UINT8 HEX
+ do-red BOOLEAN 8 0x01
+ do-green BOOLEAN 8 0x02
+ do-blue BOOLEAN 8 0x04
+ unused BOOLEAN 8 0xf8
+ unused NONE NONE
+
+colors UINT16 DEC The number of color cells to allocate
+
+configure-window-mask UINT16 HEX
+ x BOOLEAN 16 0x0001
+ y BOOLEAN 16 0x0002
+ width BOOLEAN 16 0x0004
+ height BOOLEAN 16 0x0008
+ border-width BOOLEAN 16 0x0010
+ sibling BOOLEAN 16 0x0020
+ stack-mode BOOLEAN 16 0x0040
+
+confine-to UINT32 HEX VALS(zero_is_none)
+contiguous BOOLEAN NONE
+coordinate-mode UINT8 DEC VALS
+count UINT8 DEC
+cursor UINT32 HEX VALS(zero_is_none)
+dash-offset UINT16 DEC
+dashes BYTES NONE
+dashes-length UINT16 DEC
+do-acceleration BOOLEAN NONE
+do-threshold BOOLEAN NONE
+
+detail UINT8 DEC detail
+do-not-propagate-mask UINT32 HEX
+ KeyPress BOOLEAN 32 0x00000001
+ KeyRelease BOOLEAN 32 0x00000002
+ ButtonPress BOOLEAN 32 0x00000004
+ ButtonRelease BOOLEAN 32 0x00000008
+ PointerMotion BOOLEAN 32 0x00000040
+ Button1Motion BOOLEAN 32 0x00000100
+ Button2Motion BOOLEAN 32 0x00000200
+ Button3Motion BOOLEAN 32 0x00000400
+ Button4Motion BOOLEAN 32 0x00000800
+ Button5Motion BOOLEAN 32 0x00001000
+ ButtonMotion BOOLEAN 32 0x00002000
+ erroneous-bits BOOLEAN 32 0xffffc0b0
+
+event-sequencenumber UINT16 DEC event sequencenumber
+error UINT8 DEC error
+error-badvalue UINT32 DEC error badvalue
+error_sequencenumber UINT16 DEC error sequencenumber
+errorcode UINT8 DEC VALS errrorcode
+event-x UINT16 DEC event x
+event-y UINT16 DEC event y
+eventbutton UINT8 DEC eventbutton
+eventcode UINT8 DEC VALS eventcode
+eventwindow UINT32 HEX eventwindow
+
+first-event UINT8 DEC
+first-error UINT8 DEC
+
+gc-dashes UINT8 DEC
+
+gc-value-mask UINT32 HEX
+ function BOOLEAN 32 0x00000001
+ plane-mask BOOLEAN 32 0x00000002
+ foreground BOOLEAN 32 0x00000004
+ background BOOLEAN 32 0x00000008
+ line-width BOOLEAN 32 0x00000010
+ line-style BOOLEAN 32 0x00000020
+ cap-style BOOLEAN 32 0x00000040
+ join-style BOOLEAN 32 0x00000080
+ fill-style BOOLEAN 32 0x00000100
+ fill-rule BOOLEAN 32 0x00000200
+ tile BOOLEAN 32 0x00000400
+ stipple BOOLEAN 32 0x00000800
+ tile-stipple-x-origin BOOLEAN 32 0x00001000
+ tile-stipple-y-origin BOOLEAN 32 0x00002000
+ font BOOLEAN 32 0x00004000
+ subwindow-mode BOOLEAN 32 0x00008000
+ graphics-exposures BOOLEAN 32 0x00010000
+ clip-x-origin BOOLEAN 32 0x00020000
+ clip-y-origin BOOLEAN 32 0x00040000
+ clip-mask BOOLEAN 32 0x00080000
+ dash-offset BOOLEAN 32 0x00100000
+ gc-dashes BOOLEAN 32 0x00200000
+ arc-mode BOOLEAN 32 0x00400000
+
+green UINT16 DEC
+greens UINT16 DEC
+data BYTES NONE
+data-length UINT32 DEC
+delete BOOLEAN NONE Delete this property after reading
+delta INT16 DEC
+depth UINT8 DEC
+destination UINT8 DEC VALS
+direction UINT8 DEC VALS
+drawable UINT32 HEX
+dst-drawable UINT32 HEX
+dst-gc UINT32 HEX
+dst-window UINT32 HEX
+dst-x INT16 DEC
+dst-y INT16 DEC
+event-detail UINT8 DEC VALS
+
+event-mask UINT32 HEX
+ KeyPress BOOLEAN 32 0x00000001
+ KeyRelease BOOLEAN 32 0x00000002
+ ButtonPress BOOLEAN 32 0x00000004
+ ButtonRelease BOOLEAN 32 0x00000008
+ EnterWindow BOOLEAN 32 0x00000010
+ LeaveWindow BOOLEAN 32 0x00000020
+ PointerMotion BOOLEAN 32 0x00000040
+ PointerMotionHint BOOLEAN 32 0x00000080
+ Button1Motion BOOLEAN 32 0x00000100
+ Button2Motion BOOLEAN 32 0x00000200
+ Button3Motion BOOLEAN 32 0x00000400
+ Button4Motion BOOLEAN 32 0x00000800
+ Button5Motion BOOLEAN 32 0x00001000
+ ButtonMotion BOOLEAN 32 0x00002000
+ KeymapState BOOLEAN 32 0x00004000
+ Exposure BOOLEAN 32 0x00008000
+ VisibilityChange BOOLEAN 32 0x00010000
+ StructureNotify BOOLEAN 32 0x00020000
+ ResizeRedirect BOOLEAN 32 0x00040000
+ SubstructureNotify BOOLEAN 32 0x00080000
+ SubstructureRedirect BOOLEAN 32 0x00100000
+ FocusChange BOOLEAN 32 0x00200000
+ PropertyChange BOOLEAN 32 0x00400000
+ ColormapChange BOOLEAN 32 0x00800000
+ OwnerGrabButton BOOLEAN 32 0x01000000
+ erroneous-bits BOOLEAN 32 0xfe000000
+
+exact-blue UINT16 DEC
+exact-green UINT16 DEC
+exact-red UINT16 DEC
+exposures BOOLEAN NONE
+family UINT8 DEC VALS
+fid UINT32 HEX Font id
+fill-rule UINT8 DEC VALS
+fill-style UINT8 DEC VALS
+first-keycode UINT8 DEC
+focus UINT8 DEC VALS
+focus-detail UINT8 DEC VALS
+focus-mode UINT8 DEC VALS
+font UINT32 HEX
+fore-blue UINT16 DEC
+fore-green UINT16 DEC
+fore-red UINT16 DEC
+foreground UINT32 HEX
+format UINT8 DEC
+from-configure BOOLEAN NONE
+function UINT8 DEC VALS
+gc UINT32 HEX
+get-property-type UINT32 HEX VALS(zero_is_any_property_type)
+grab-mode UINT8 DEC VALS
+grab-status UINT8 DEC VALS
+grab-window UINT32 HEX
+graphics-exposures BOOLEAN NONE
+height UINT16 DEC
+image-byte-order UINT8 HEX VALS
+initial-connection NONE NONE undecoded
+image-format UINT8 DEC VALS
+image-pixmap-format UINT8 DEC VALS
+interval INT16 DEC
+items NONE NONE
+join-style UINT8 DEC VALS
+key UINT8 DEC VALS
+key-click-percent INT8 DEC
+keyboard-key UINT8 DEC
+keyboard-mode UINT8 DEC VALS(pointer_keyboard_mode)
+keybut-mask-erroneous-bits BOOLEAN 16 0xe000 keybut mask erroneous bits
+keycode UINT8 HEX keycode
+
+keyboard-value-mask UINT32 HEX
+ key-click-percent BOOLEAN 32 0x0001
+ bell-percent BOOLEAN 32 0x0002
+ bell-pitch BOOLEAN 32 0x0004
+ bell-duration BOOLEAN 32 0x0008
+ led BOOLEAN 32 0x0010
+ led-mode BOOLEAN 32 0x0020
+ keyboard-key BOOLEAN 32 0x0040
+ auto-repeat-mode BOOLEAN 32 0x0080
+
+keycode-count UINT8 DEC
+
+keycodes NONE NONE
+ item BYTES NONE
+
+keycodes-per-modifier UINT8 DEC
+
+keys BYTES NONE
+
+keysyms NONE NONE
+ item NONE NONE
+ keysym UINT32 HEX
+
+keysyms-per-keycode UINT8 DEC
+length-of-reason UINT8 DEC length of reason
+length-of-vendor UINT16 DEC length of vendor
+led UINT8 DEC
+led-mode UINT8 DEC VALS(on_off)
+left-pad UINT8 DEC
+line-style UINT8 DEC VALS
+line-width UINT16 DEC
+long-length UINT32 DEC The maximum length of the property in bytes
+long-offset UINT32 DEC The starting position in the property bytes array
+map BYTES NONE
+map-length UINT8 DEC
+mask UINT32 HEX VALS(zero_is_none)
+mask-char UINT16 DEC
+mask-font UINT32 HEX VALS(zero_is_none)
+max-names UINT16 DEC
+mid UINT32 HEX
+mode UINT8 DEC VALS
+major-opcode UINT16 DEC major opcode
+max-keycode UINT8 DEC max keycode
+maximum-request-length UINT16 DEC maximum request length
+min-keycode UINT8 DEC min keycode
+minor-opcode UINT16 DEC minor opcode
+
+modifiers-mask UINT16 HEX
+ Shift BOOLEAN 16 0x0001
+ Lock BOOLEAN 16 0x0002
+ Control BOOLEAN 16 0x0004
+ Mod1 BOOLEAN 16 0x0008
+ Mod2 BOOLEAN 16 0x0010
+ Mod3 BOOLEAN 16 0x0020
+ Mod4 BOOLEAN 16 0x0040
+ Mod5 BOOLEAN 16 0x0080
+ Button1 BOOLEAN 16 0x0100
+ Button2 BOOLEAN 16 0x0200
+ Button3 BOOLEAN 16 0x0400
+ Button4 BOOLEAN 16 0x0800
+ Button5 BOOLEAN 16 0x1000
+ AnyModifier UINT16 HEX 0x8000
+ erroneous-bits BOOLEAN 16 0xff00
+
+motion-buffer-size UINT16 DEC motion buffer size
+
+new BOOLEAN NONE
+number-of-formats-in-pixmap-formats UINT8 DEC number of formats in pixmap formats
+number-of-screens-in-roots UINT8 DEC number of screens in roots
+
+name STRING HEX
+name-length UINT16 DEC
+odd-length BOOLEAN NONE
+only-if-exists BOOLEAN NONE
+opcode UINT8 DEC VALS
+ordering UINT8 DEC VALS
+override-redirect BOOLEAN NONE Window manager doesn't manage this window when true
+owner UINT32 HEX VALS(zero_is_none)
+owner-events BOOLEAN NONE
+parent UINT32 HEX
+
+path NONE NONE
+ string STRING NONE
+
+pattern STRING HEX
+pattern-length UINT16 DEC
+percent UINT8 DEC
+pid UINT32 HEX
+pixel UINT32 HEX
+pixels NONE NONE
+pixels_item UINT32 HEX
+pixmap UINT32 HEX
+place UINT8 DEC VALS
+plane-mask UINT32 HEX VALS
+planes UINT16 DEC
+point NONE NONE
+points NONE NONE
+point-x INT16 DEC
+point-y INT16 DEC
+
+pointer-event-mask UINT16 HEX
+ ButtonPress BOOLEAN 16 0x0004
+ ButtonRelease BOOLEAN 16 0x0008
+ EnterWindow BOOLEAN 16 0x0010
+ LeaveWindow BOOLEAN 16 0x0020
+ PointerMotion BOOLEAN 16 0x0040
+ PointerMotionHint BOOLEAN 16 0x0080
+ Button1Motion BOOLEAN 16 0x0100
+ Button2Motion BOOLEAN 16 0x0200
+ Button3Motion BOOLEAN 16 0x0400
+ Button4Motion BOOLEAN 16 0x0800
+ Button5Motion BOOLEAN 16 0x1000
+ ButtonMotion BOOLEAN 16 0x2000
+ KeymapState BOOLEAN 16 0x4000
+ erroneous-bits BOOLEAN 16 0x8003
+
+pointer-mode UINT8 DEC VALS(pointer_keyboard_mode)
+prefer-blanking UINT8 DEC VALS(yes_no_default)
+present BOOLEAN NONE
+propagate BOOLEAN NONE
+
+properties NONE NONE
+ item UINT32 HEX
+
+property UINT32 HEX
+property-number UINT16 DEC
+property-state UINT8 DEC VALS
+protocol-major-version UINT16 DEC
+protocol-minor-version UINT16 DEC
+reason STRING HEX reason
+rectangle-height UINT16 DEC
+rectangles NONE NONE
+rectangle NONE NONE
+rectangle-width UINT16 DEC
+rectangle-x INT16 DEC
+rectangle-y INT16 DEC
+red UINT16 DEC
+reds UINT16 DEC
+request UINT8 DEC VALS(opcode)
+requestor UINT32 HEX
+request-length UINT16 DEC Request length
+resource UINT32 HEX VALS(all_temporary)
+revert-to UINT8 DEC VALS
+release-number UINT32 DEC release number
+reply UINT8 DEC reply
+reply-sequencenumber UINT16 DEC VALS(opcode)
+replylength UINT32 DEC replylength
+replyopcode UINT8 DEC VALS(opcode)
+resource-id-base UINT32 HEX resource id base
+resource-id-mask UINT32 HEX resource id mask
+root-x UINT16 DEC root x
+root-y UINT16 DEC root y
+rootwindow UINT32 HEX rootwindow
+
+same-screen BOOLEAN NONE same screen
+same-screen-focus-mask UINT8 HEX
+ focus BOOLEAN 8 0x01
+ same-screen BOOLEAN 8 0x02
+success UINT8 DEC success
+save-set-mode UINT8 DEC VALS(insert_delete)
+save-under BOOLEAN NONE
+screen-saver-mode UINT8 DEC VALS
+segment NONE NONE
+segments NONE NONE
+segment_x1 INT16 DEC
+segment_x2 INT16 DEC
+segment_y1 INT16 DEC
+segment_y2 INT16 DEC
+selection UINT32 HEX
+shape UINT8 DEC VALS
+sibling UINT32 HEX
+source-pixmap UINT32 HEX
+source-font UINT32 HEX
+source-char UINT16 DEC
+src-cmap UINT32 HEX
+src-drawable UINT32 HEX
+src-gc UINT32 HEX
+src-height UINT16 DEC
+src-width UINT16 DEC
+src-window UINT32 HEX
+src-x INT16 DEC
+src-y INT16 DEC
+start UINT32 DEC
+stack-mode UINT8 DEC VALS
+stipple UINT32 HEX
+stop UINT32 DEC
+str-number-in-path UINT16 DEC
+string STRING HEX
+
+string16 STRING HEX
+ bytes BYTES NONE
+
+string-length UINT32 DEC
+subwindow-mode UINT8 DEC VALS
+target UINT32 HEX
+
+textitem NONE NONE
+ font UINT32 HEX
+ string NONE NONE
+ delta INT8 DEC
+ string8 STRING NONE
+ string16 STRING NONE
+ bytes BYTES NONE
+
+threshold INT16 DEC
+tile UINT32 HEX
+tile-stipple-x-origin INT16 DEC
+tile-stipple-y-origin INT16 DEC
+time UINT32 DEC
+timeout INT16 DEC
+type UINT32 HEX
+undecoded NONE NONE Yet undecoded by dissector
+unused NONE NONE
+valuelength UINT32 DEC valuelength
+vendor STRING HEX vendor
+visibility-state UINT8 DEC VALS
+visual UINT32 HEX
+visual-blue UINT16 DEC
+visual-green UINT16 DEC
+visual-red UINT16 DEC
+visualid UINT32 HEX
+warp-pointer-dst-window UINT32 HEX VALS(zero_is_none)
+warp-pointer-src-window UINT32 HEX VALS(zero_is_none)
+wid UINT32 HEX Window id
+width UINT16 DEC
+win-gravity UINT8 DEC VALS(gravity)
+win-x INT16 DEC
+win-y INT16 DEC
+window UINT32 HEX
+window-class UINT16 DEC VALS Window class
+
+window-value-mask UINT32 HEX
+ background-pixmap BOOLEAN 32 0x00000001
+ background-pixel BOOLEAN 32 0x00000002
+ border-pixmap BOOLEAN 32 0x00000004
+ border-pixel BOOLEAN 32 0x00000008
+ bit-gravity BOOLEAN 32 0x00000010
+ win-gravity BOOLEAN 32 0x00000020
+ backing-store BOOLEAN 32 0x00000040
+ backing-planes BOOLEAN 32 0x00000080
+ backing-pixel BOOLEAN 32 0x00000100
+ override-redirect BOOLEAN 32 0x00000200
+ save-under BOOLEAN 32 0x00000400
+ event-mask BOOLEAN 32 0x00000800
+ do-not-propagate-mask BOOLEAN 32 0x00001000
+ colormap BOOLEAN 32 0x00002000
+ cursor BOOLEAN 32 0x00004000
+
+x INT16 DEC
+y INT16 DEC